diff -druNp --no-dereference linux-libre-4.6-gnu/arch/alpha/include/asm/pgalloc.h linux-libre-4.7-gnu/arch/alpha/include/asm/pgalloc.h
--- linux-libre-4.6-gnu/arch/alpha/include/asm/pgalloc.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/alpha/include/asm/pgalloc.h	2016-07-24 15:23:50.000000000 -0400
@@ -40,7 +40,7 @@ pgd_free(struct mm_struct *mm, pgd_t *pg
 static inline pmd_t *
 pmd_alloc_one(struct mm_struct *mm, unsigned long address)
 {
-	pmd_t *ret = (pmd_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
+	pmd_t *ret = (pmd_t *)__get_free_page(GFP_KERNEL|__GFP_ZERO);
 	return ret;
 }
 
@@ -53,7 +53,7 @@ pmd_free(struct mm_struct *mm, pmd_t *pm
 static inline pte_t *
 pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
 {
-	pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
+	pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_ZERO);
 	return pte;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/alpha/include/asm/rwsem.h linux-libre-4.7-gnu/arch/alpha/include/asm/rwsem.h
--- linux-libre-4.6-gnu/arch/alpha/include/asm/rwsem.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/alpha/include/asm/rwsem.h	2016-07-24 15:23:50.000000000 -0400
@@ -63,7 +63,7 @@ static inline int __down_read_trylock(st
 	return res >= 0 ? 1 : 0;
 }
 
-static inline void __down_write(struct rw_semaphore *sem)
+static inline long ___down_write(struct rw_semaphore *sem)
 {
 	long oldcount;
 #ifndef	CONFIG_SMP
@@ -83,10 +83,24 @@ static inline void __down_write(struct r
 	:"=&r" (oldcount), "=m" (sem->count), "=&r" (temp)
 	:"Ir" (RWSEM_ACTIVE_WRITE_BIAS), "m" (sem->count) : "memory");
 #endif
-	if (unlikely(oldcount))
+	return oldcount;
+}
+
+static inline void __down_write(struct rw_semaphore *sem)
+{
+	if (unlikely(___down_write(sem)))
 		rwsem_down_write_failed(sem);
 }
 
+static inline int __down_write_killable(struct rw_semaphore *sem)
+{
+	if (unlikely(___down_write(sem)))
+		if (IS_ERR(rwsem_down_write_failed_killable(sem)))
+			return -EINTR;
+
+	return 0;
+}
+
 /*
  * trylock for writing -- returns 1 if successful, 0 if contention
  */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/alpha/Kconfig linux-libre-4.7-gnu/arch/alpha/Kconfig
--- linux-libre-4.6-gnu/arch/alpha/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/alpha/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -13,7 +13,6 @@ config ALPHA
 	select GENERIC_IRQ_PROBE
 	select AUTO_IRQ_AFFINITY if SMP
 	select GENERIC_IRQ_SHOW
-	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select ARCH_WANT_IPC_PARSE_VERSION
 	select ARCH_HAVE_NMI_SAFE_CMPXCHG
 	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
@@ -27,6 +26,7 @@ config ALPHA
 	select MODULES_USE_ELF_RELA
 	select ODD_RT_SIGACTION
 	select OLD_SIGSUSPEND
+	select CPU_NO_EFFICIENT_FFS if !ALPHA_EV67
 	help
 	  The Alpha is a 64-bit general-purpose processor designed and
 	  marketed by the Digital Equipment Corporation of blessed memory,
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/alpha/kernel/osf_sys.c linux-libre-4.7-gnu/arch/alpha/kernel/osf_sys.c
--- linux-libre-4.6-gnu/arch/alpha/kernel/osf_sys.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/alpha/kernel/osf_sys.c	2016-07-24 15:23:50.000000000 -0400
@@ -147,7 +147,7 @@ SYSCALL_DEFINE4(osf_getdirentries, unsig
 		long __user *, basep)
 {
 	int error;
-	struct fd arg = fdget(fd);
+	struct fd arg = fdget_pos(fd);
 	struct osf_dirent_callback buf = {
 		.ctx.actor = osf_filldir,
 		.dirent = dirent,
@@ -164,7 +164,7 @@ SYSCALL_DEFINE4(osf_getdirentries, unsig
 	if (count != buf.count)
 		error = count - buf.count;
 
-	fdput(arg);
+	fdput_pos(arg);
 	return error;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/alpha/kernel/pci-sysfs.c linux-libre-4.7-gnu/arch/alpha/kernel/pci-sysfs.c
--- linux-libre-4.6-gnu/arch/alpha/kernel/pci-sysfs.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/alpha/kernel/pci-sysfs.c	2016-07-24 15:23:50.000000000 -0400
@@ -77,10 +77,10 @@ static int pci_mmap_resource(struct kobj
 	if (i >= PCI_ROM_RESOURCE)
 		return -ENODEV;
 
-	if (!__pci_mmap_fits(pdev, i, vma, sparse))
+	if (res->flags & IORESOURCE_MEM && iomem_is_exclusive(res->start))
 		return -EINVAL;
 
-	if (iomem_is_exclusive(res->start))
+	if (!__pci_mmap_fits(pdev, i, vma, sparse))
 		return -EINVAL;
 
 	pcibios_resource_to_bus(pdev->bus, &bar, res);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/alpha/kernel/process.c linux-libre-4.7-gnu/arch/alpha/kernel/process.c
--- linux-libre-4.6-gnu/arch/alpha/kernel/process.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/alpha/kernel/process.c	2016-07-24 15:23:50.000000000 -0400
@@ -210,14 +210,6 @@ start_thread(struct pt_regs * regs, unsi
 }
 EXPORT_SYMBOL(start_thread);
 
-/*
- * Free current thread data structures etc..
- */
-void
-exit_thread(void)
-{
-}
-
 void
 flush_thread(void)
 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/boot/dts/abilis_tb100.dtsi linux-libre-4.7-gnu/arch/arc/boot/dts/abilis_tb100.dtsi
--- linux-libre-4.6-gnu/arch/arc/boot/dts/abilis_tb100.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/boot/dts/abilis_tb100.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -23,8 +23,6 @@
 
 
 / {
-	clock-frequency		= <500000000>;	/* 500 MHZ */
-
 	soc100 {
 		bus-frequency	= <166666666>;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/boot/dts/abilis_tb101.dtsi linux-libre-4.7-gnu/arch/arc/boot/dts/abilis_tb101.dtsi
--- linux-libre-4.6-gnu/arch/arc/boot/dts/abilis_tb101.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/boot/dts/abilis_tb101.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -23,8 +23,6 @@
 
 
 / {
-	clock-frequency		= <500000000>;	/* 500 MHZ */
-
 	soc100 {
 		bus-frequency	= <166666666>;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/boot/dts/abilis_tb10x.dtsi linux-libre-4.7-gnu/arch/arc/boot/dts/abilis_tb10x.dtsi
--- linux-libre-4.6-gnu/arch/arc/boot/dts/abilis_tb10x.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/boot/dts/abilis_tb10x.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -35,6 +35,20 @@
 		};
 	};
 
+	/* TIMER0 with interrupt for clockevent */
+	timer0 {
+		compatible = "snps,arc-timer";
+		interrupts = <3>;
+		interrupt-parent = <&intc>;
+		clocks = <&cpu_clk>;
+	};
+
+	/* TIMER1 for free running clocksource */
+	timer1 {
+		compatible = "snps,arc-timer";
+		clocks = <&cpu_clk>;
+	};
+
 	soc100 {
 		#address-cells	= <1>;
 		#size-cells	= <1>;
@@ -112,7 +126,7 @@
 			chan_allocation_order = <0>;
 			chan_priority = <1>;
 			block_size = <0x7ff>;
-			data_width = <2>;
+			data-width = <4>;
 			clocks = <&ahb_clk>;
 			clock-names = "hclk";
 		};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/boot/dts/axc001.dtsi linux-libre-4.7-gnu/arch/arc/boot/dts/axc001.dtsi
--- linux-libre-4.6-gnu/arch/arc/boot/dts/axc001.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/boot/dts/axc001.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -11,9 +11,10 @@
  * Note that this file only supports the 770D CPU
  */
 
+/include/ "skeleton.dtsi"
+
 / {
 	compatible = "snps,arc";
-	clock-frequency = <750000000>;	/* 750 MHZ */
 	#address-cells = <1>;
 	#size-cells = <1>;
 
@@ -24,7 +25,13 @@
 
 		ranges = <0x00000000 0xf0000000 0x10000000>;
 
-		cpu_intc: arc700-intc@cpu {
+		core_clk: core_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <750000000>;
+		};
+
+		core_intc: arc700-intc@cpu {
 			compatible = "snps,arc700-intc";
 			interrupt-controller;
 			#interrupt-cells = <1>;
@@ -48,7 +55,7 @@
 				reg = <0>;
 				interrupt-controller;
 				#interrupt-cells = <2>;
-				interrupt-parent = <&cpu_intc>;
+				interrupt-parent = <&core_intc>;
 				interrupts = <15>;
 			};
 		};
@@ -86,15 +93,33 @@
 		compatible = "snps,dw-apb-ictl";
 		reg = < 0xe0012000 0x200 >;
 		interrupt-controller;
-		interrupt-parent = <&cpu_intc>;
+		interrupt-parent = <&core_intc>;
 		interrupts = < 7 >;
 	};
 
 	memory {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		ranges = <0x00000000 0x80000000 0x40000000>;
+		ranges = <0x00000000 0x80000000 0x20000000>;
 		device_type = "memory";
-		reg = <0x80000000 0x20000000>;	/* 512MiB */
+		reg = <0x80000000 0x1b000000>;	/* (512 - 32) MiB */
+	};
+
+	reserved-memory {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		/*
+		 * We just move frame buffer area to the very end of
+		 * available DDR. And even though in case of ARC770 there's
+		 * no strict requirement for a frame-buffer to be in any
+		 * particular location it allows us to use the same
+		 * base board's DT node for ARC PGU as for ARc HS38.
+		 */
+		frame_buffer: frame_buffer@9e000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x9e000000 0x2000000>;
+			no-map;
+		};
 	};
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/boot/dts/axc003.dtsi linux-libre-4.7-gnu/arch/arc/boot/dts/axc003.dtsi
--- linux-libre-4.6-gnu/arch/arc/boot/dts/axc003.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/boot/dts/axc003.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -10,9 +10,10 @@
  * Device tree for AXC003 CPU card: HS38x UP configuration
  */
 
+/include/ "skeleton_hs.dtsi"
+
 / {
 	compatible = "snps,arc";
-	clock-frequency = <90000000>;
 	#address-cells = <1>;
 	#size-cells = <1>;
 
@@ -23,7 +24,13 @@
 
 		ranges = <0x00000000 0xf0000000 0x10000000>;
 
-		cpu_intc: archs-intc@cpu {
+		core_clk: core_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <90000000>;
+		};
+
+		core_intc: archs-intc@cpu {
 			compatible = "snps,archs-intc";
 			interrupt-controller;
 			#interrupt-cells = <1>;
@@ -47,7 +54,7 @@
 				reg = <0>;
 				interrupt-controller;
 				#interrupt-cells = <2>;
-				interrupt-parent = <&cpu_intc>;
+				interrupt-parent = <&core_intc>;
 				interrupts = <25>;
 			};
 		};
@@ -66,7 +73,7 @@
 		arcpct0: pct {
 			compatible = "snps,archs-pct";
 			#interrupt-cells = <1>;
-			interrupt-parent = <&cpu_intc>;
+			interrupt-parent = <&core_intc>;
 			interrupts = <20>;
 		};
 	};
@@ -89,7 +96,7 @@
 		compatible = "snps,dw-apb-ictl";
 		reg = < 0xe0012000 0x200 >;
 		interrupt-controller;
-		interrupt-parent = <&cpu_intc>;
+		interrupt-parent = <&core_intc>;
 		interrupts = < 24 >;
 	};
 
@@ -100,4 +107,18 @@
 		device_type = "memory";
 		reg = <0x80000000 0x20000000>;	/* 512MiB */
 	};
+
+	reserved-memory {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		/*
+		 * Move frame buffer out of IOC aperture (0x8z-0xAz).
+		 */
+		frame_buffer: frame_buffer@be000000 {
+			compatible = "shared-dma-pool";
+			reg = <0xbe000000 0x2000000>;
+			no-map;
+		};
+	};
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/boot/dts/axc003_idu.dtsi linux-libre-4.7-gnu/arch/arc/boot/dts/axc003_idu.dtsi
--- linux-libre-4.6-gnu/arch/arc/boot/dts/axc003_idu.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/boot/dts/axc003_idu.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -10,9 +10,10 @@
  * Device tree for AXC003 CPU card: HS38x2 (Dual Core) with IDU intc
  */
 
+/include/ "skeleton_hs_idu.dtsi"
+
 / {
 	compatible = "snps,arc";
-	clock-frequency = <90000000>;
 	#address-cells = <1>;
 	#size-cells = <1>;
 
@@ -23,7 +24,13 @@
 
 		ranges = <0x00000000 0xf0000000 0x10000000>;
 
-		cpu_intc: archs-intc@cpu {
+		core_clk: core_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <100000000>;
+		};
+
+		core_intc: archs-intc@cpu {
 			compatible = "snps,archs-intc";
 			interrupt-controller;
 			#interrupt-cells = <1>;
@@ -32,7 +39,7 @@
 		idu_intc: idu-interrupt-controller {
 			compatible = "snps,archs-idu-intc";
 			interrupt-controller;
-			interrupt-parent = <&cpu_intc>;
+			interrupt-parent = <&core_intc>;
 
 			/*
 			 * <hwirq  distribution>
@@ -89,7 +96,7 @@
 		arcpct0: pct {
 			compatible = "snps,archs-pct";
 			#interrupt-cells = <1>;
-			interrupt-parent = <&cpu_intc>;
+			interrupt-parent = <&core_intc>;
 			interrupts = <20>;
 		};
 	};
@@ -123,4 +130,18 @@
 		device_type = "memory";
 		reg = <0x80000000 0x20000000>;	/* 512MiB */
 	};
+
+	reserved-memory {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		/*
+		 * Move frame buffer out of IOC aperture (0x8z-0xAz).
+		 */
+		frame_buffer: frame_buffer@be000000 {
+			compatible = "shared-dma-pool";
+			reg = <0xbe000000 0x2000000>;
+			no-map;
+		};
+	};
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/boot/dts/axs10x_mb.dtsi linux-libre-4.7-gnu/arch/arc/boot/dts/axs10x_mb.dtsi
--- linux-libre-4.6-gnu/arch/arc/boot/dts/axs10x_mb.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/boot/dts/axs10x_mb.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -16,7 +16,20 @@
 		ranges = <0x00000000 0xe0000000 0x10000000>;
 		interrupt-parent = <&mb_intc>;
 
+		i2sclk: i2sclk@100a0 {
+			compatible = "snps,axs10x-i2s-pll-clock";
+			reg = <0x100a0 0x10>;
+			clocks = <&i2spll_clk>;
+			#clock-cells = <0>;
+		};
+
 		clocks {
+			i2spll_clk: i2spll_clk {
+				compatible = "fixed-clock";
+				clock-frequency = <27000000>;
+				#clock-cells = <0>;
+			};
+
 			i2cclk: i2cclk {
 				compatible = "fixed-clock";
 				clock-frequency = <50000000>;
@@ -34,6 +47,12 @@
 				clock-frequency = <50000000>;
 				#clock-cells = <0>;
 			};
+
+			pguclk: pguclk {
+				#clock-cells = <0>;
+				compatible = "fixed-clock";
+				clock-frequency = <74440000>;
+			};
 		};
 
 		ethernet@0x18000 {
@@ -147,6 +166,37 @@
 			clocks = <&i2cclk>;
 			interrupts = <16>;
 
+			adv7511:adv7511@39{
+				compatible="adi,adv7511";
+				reg = <0x39>;
+				interrupts = <23>;
+				adi,input-depth = <8>;
+				adi,input-colorspace = "rgb";
+				adi,input-clock = "1x";
+				adi,clock-delay = <0x03>;
+
+				ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					/* RGB/YUV input */
+					port@0 {
+						reg = <0>;
+						adv7511_input:endpoint {
+						remote-endpoint = <&pgu_output>;
+						};
+					};
+
+					/* HDMI output */
+					port@1 {
+						reg = <1>;
+						adv7511_output: endpoint {
+							remote-endpoint = <&hdmi_connector_in>;
+						};
+					};
+				};
+			};
+
 			eeprom@0x54{
 				compatible = "24c01";
 				reg = <0x54>;
@@ -160,6 +210,16 @@
 			};
 		};
 
+		hdmi0: connector {
+			compatible = "hdmi-connector";
+			type = "a";
+			port {
+				hdmi_connector_in: endpoint {
+					remote-endpoint = <&adv7511_output>;
+				};
+			};
+		};
+
 		gpio0:gpio@13000 {
 			compatible = "snps,dw-apb-gpio";
 			reg = <0x13000 0x1000>;
@@ -221,5 +281,19 @@
 				reg = <2>;
 			};
 		};
+
+		pgu@17000 {
+			compatible = "snps,arcpgu";
+			reg = <0x17000 0x400>;
+			encoder-slave = <&adv7511>;
+			clocks = <&pguclk>;
+			clock-names = "pxlclk";
+			memory-region = <&frame_buffer>;
+			port {
+				pgu_output: endpoint {
+					remote-endpoint = <&adv7511_input>;
+				};
+			};
+		};
 	};
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/boot/dts/eznps.dts linux-libre-4.7-gnu/arch/arc/boot/dts/eznps.dts
--- linux-libre-4.6-gnu/arch/arc/boot/dts/eznps.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arc/boot/dts/eznps.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,95 @@
+/*
+ * Copyright(c) 2015 EZchip Technologies.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ */
+
+/dts-v1/;
+
+/ {
+	compatible = "ezchip,arc-nps";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	interrupt-parent = <&intc>;
+	present-cpus = "0-1,16-17";
+	possible-cpus = "0-4095";
+
+	aliases {
+		ethernet0 = &gmac0;
+	};
+
+	chosen {
+		bootargs = "earlycon=uart8250,mmio32be,0xf7209000,115200n8 console=ttyS0,115200n8";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x20000000>;	/* 512M */
+	};
+
+	clocks {
+		sysclk: sysclk {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <83333333>;
+		};
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		/* child and parent address space 1:1 mapped */
+		ranges;
+
+		intc: interrupt-controller {
+			compatible = "ezchip,nps400-ic";
+			interrupt-controller;
+			#interrupt-cells = <1>;
+		};
+
+		timer0: timer_clkevt {
+			compatible = "snps,arc-timer";
+			interrupts = <3>;
+			clocks = <&sysclk>;
+		};
+
+		timer1: timer_clksrc {
+			compatible = "ezchip,nps400-timer";
+			clocks = <&sysclk>;
+			clock-names="sysclk";
+		};
+
+		uart@f7209000 {
+			compatible = "snps,dw-apb-uart";
+			device_type = "serial";
+			reg = <0xf7209000 0x100>;
+			interrupts = <6>;
+			clocks = <&sysclk>;
+			clock-names="baudclk";
+			baud = <115200>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			native-endian;
+		};
+
+		gmac0: ethernet@f7470000 {
+			compatible = "ezchip,nps-mgt-enet";
+			reg = <0xf7470000 0x1940>;
+			interrupts = <7>;
+			/* Filled in by U-Boot */
+			mac-address = [ 00 C0 00 F0 04 03 ];
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/boot/dts/nsim_700.dts linux-libre-4.7-gnu/arch/arc/boot/dts/nsim_700.dts
--- linux-libre-4.6-gnu/arch/arc/boot/dts/nsim_700.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/boot/dts/nsim_700.dts	2016-07-24 15:23:50.000000000 -0400
@@ -11,10 +11,9 @@
 
 / {
 	compatible = "snps,nsim";
-	clock-frequency = <80000000>;	/* 80 MHZ */
 	#address-cells = <1>;
 	#size-cells = <1>;
-	interrupt-parent = <&intc>;
+	interrupt-parent = <&core_intc>;
 
 	chosen {
 		bootargs = "earlycon=arc_uart,mmio32,0xc0fc1000,115200n8 console=ttyARC0,115200n8";
@@ -32,7 +31,13 @@
 		/* child and parent address space 1:1 mapped */
 		ranges;
 
-		intc: interrupt-controller {
+		core_clk: core_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <80000000>;
+		};
+
+		core_intc: interrupt-controller {
 			compatible = "snps,arc700-intc";
 			interrupt-controller;
 			#interrupt-cells = <1>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/boot/dts/nsim_hs.dts linux-libre-4.7-gnu/arch/arc/boot/dts/nsim_hs.dts
--- linux-libre-4.6-gnu/arch/arc/boot/dts/nsim_hs.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/boot/dts/nsim_hs.dts	2016-07-24 15:23:50.000000000 -0400
@@ -7,7 +7,7 @@
  */
 /dts-v1/;
 
-/include/ "skeleton.dtsi"
+/include/ "skeleton_hs.dtsi"
 
 / {
 	compatible = "snps,nsim_hs";
@@ -39,6 +39,12 @@
 			 bus addr,   parent bus addr, size */
 		ranges = <0x80000000 0x0 0x80000000 0x80000000>;
 
+		core_clk: core_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <80000000>;
+		};
+
 		core_intc: core-interrupt-controller {
 			compatible = "snps,archs-intc";
 			interrupt-controller;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/boot/dts/nsim_hs_idu.dts linux-libre-4.7-gnu/arch/arc/boot/dts/nsim_hs_idu.dts
--- linux-libre-4.6-gnu/arch/arc/boot/dts/nsim_hs_idu.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/boot/dts/nsim_hs_idu.dts	2016-07-24 15:23:50.000000000 -0400
@@ -7,7 +7,7 @@
  */
 /dts-v1/;
 
-/include/ "skeleton.dtsi"
+/include/ "skeleton_hs_idu.dtsi"
 
 / {
 	compatible = "snps,nsim_hs";
@@ -29,6 +29,12 @@
 		/* child and parent address space 1:1 mapped */
 		ranges;
 
+		core_clk: core_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <80000000>;
+		};
+
 		core_intc: core-interrupt-controller {
 			compatible = "snps,archs-intc";
 			interrupt-controller;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/boot/dts/nsimosci.dts linux-libre-4.7-gnu/arch/arc/boot/dts/nsimosci.dts
--- linux-libre-4.6-gnu/arch/arc/boot/dts/nsimosci.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/boot/dts/nsimosci.dts	2016-07-24 15:23:50.000000000 -0400
@@ -11,10 +11,9 @@
 
 / {
 	compatible = "snps,nsimosci";
-	clock-frequency = <20000000>;	/* 20 MHZ */
 	#address-cells = <1>;
 	#size-cells = <1>;
-	interrupt-parent = <&intc>;
+	interrupt-parent = <&core_intc>;
 
 	chosen {
 		/* this is for console on PGU */
@@ -35,7 +34,13 @@
 		/* child and parent address space 1:1 mapped */
 		ranges;
 
-		intc: interrupt-controller {
+		core_clk: core_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <20000000>;
+		};
+
+		core_intc: interrupt-controller {
 			compatible = "snps,arc700-intc";
 			interrupt-controller;
 			#interrupt-cells = <1>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/boot/dts/nsimosci_hs.dts linux-libre-4.7-gnu/arch/arc/boot/dts/nsimosci_hs.dts
--- linux-libre-4.6-gnu/arch/arc/boot/dts/nsimosci_hs.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/boot/dts/nsimosci_hs.dts	2016-07-24 15:23:50.000000000 -0400
@@ -7,11 +7,10 @@
  */
 /dts-v1/;
 
-/include/ "skeleton.dtsi"
+/include/ "skeleton_hs.dtsi"
 
 / {
 	compatible = "snps,nsimosci_hs";
-	clock-frequency = <20000000>;	/* 20 MHZ */
 	#address-cells = <1>;
 	#size-cells = <1>;
 	interrupt-parent = <&core_intc>;
@@ -35,6 +34,12 @@
 		/* child and parent address space 1:1 mapped */
 		ranges;
 
+		core_clk: core_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <20000000>;
+		};
+
 		core_intc: core-interrupt-controller {
 			compatible = "snps,archs-intc";
 			interrupt-controller;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/boot/dts/nsimosci_hs_idu.dts linux-libre-4.7-gnu/arch/arc/boot/dts/nsimosci_hs_idu.dts
--- linux-libre-4.6-gnu/arch/arc/boot/dts/nsimosci_hs_idu.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/boot/dts/nsimosci_hs_idu.dts	2016-07-24 15:23:50.000000000 -0400
@@ -7,11 +7,10 @@
  */
 /dts-v1/;
 
-/include/ "skeleton.dtsi"
+/include/ "skeleton_hs_idu.dtsi"
 
 / {
 	compatible = "snps,nsimosci_hs";
-	clock-frequency = <5000000>;	/* 5 MHZ */
 	#address-cells = <1>;
 	#size-cells = <1>;
 	interrupt-parent = <&core_intc>;
@@ -33,6 +32,12 @@
 		/* child and parent address space 1:1 mapped */
 		ranges;
 
+		core_clk: core_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <5000000>;
+		};
+
 		core_intc: core-interrupt-controller {
 			compatible = "snps,archs-intc";
 			interrupt-controller;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/boot/dts/skeleton.dtsi linux-libre-4.7-gnu/arch/arc/boot/dts/skeleton.dtsi
--- linux-libre-4.6-gnu/arch/arc/boot/dts/skeleton.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/boot/dts/skeleton.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -13,7 +13,6 @@
 
 / {
 	compatible = "snps,arc";
-	clock-frequency = <80000000>;	/* 80 MHZ */
 	#address-cells = <1>;
 	#size-cells = <1>;
 	chosen { };
@@ -30,6 +29,20 @@
 		};
 	};
 
+	/* TIMER0 with interrupt for clockevent */
+	timer0 {
+		compatible = "snps,arc-timer";
+		interrupts = <3>;
+		interrupt-parent = <&core_intc>;
+		clocks = <&core_clk>;
+	};
+
+	/* TIMER1 for free running clocksource */
+	timer1 {
+		compatible = "snps,arc-timer";
+		clocks = <&core_clk>;
+	};
+
 	memory {
 		device_type = "memory";
 		reg = <0x80000000 0x10000000>;	/* 256M */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/boot/dts/skeleton_hs.dtsi linux-libre-4.7-gnu/arch/arc/boot/dts/skeleton_hs.dtsi
--- linux-libre-4.6-gnu/arch/arc/boot/dts/skeleton_hs.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arc/boot/dts/skeleton_hs.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/ {
+	compatible = "snps,arc";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	chosen { };
+	aliases { };
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "snps,archs38";
+			reg = <0>;
+		};
+	};
+
+	/* TIMER0 with interrupt for clockevent */
+	timer0 {
+		compatible = "snps,arc-timer";
+		interrupts = <16>;
+		interrupt-parent = <&core_intc>;
+		clocks = <&core_clk>;
+	};
+
+	/* 64-bit Local RTC: preferred clocksource for UP */
+	rtc {
+		compatible = "snps,archs-timer-rtc";
+		clocks = <&core_clk>;
+	};
+
+	/* TIMER1 for free running clocksource: Fallback if rtc not found */
+	timer1 {
+		compatible = "snps,arc-timer";
+		clocks = <&core_clk>;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x10000000>;	/* 256M */
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/boot/dts/skeleton_hs_idu.dtsi linux-libre-4.7-gnu/arch/arc/boot/dts/skeleton_hs_idu.dtsi
--- linux-libre-4.6-gnu/arch/arc/boot/dts/skeleton_hs_idu.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arc/boot/dts/skeleton_hs_idu.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/ {
+	compatible = "snps,arc";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	chosen { };
+	aliases { };
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "snps,archs38xN";
+			reg = <0>;
+		};
+	};
+
+	/* TIMER0 with interrupt for clockevent */
+	timer0 {
+		compatible = "snps,arc-timer";
+		interrupts = <16>;
+		interrupt-parent = <&core_intc>;
+		clocks = <&core_clk>;
+	};
+
+	/* 64-bit Global Free Running Counter */
+	gfrc {
+		compatible = "snps,archs-timer-gfrc";
+		clocks = <&core_clk>;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x10000000>;	/* 256M */
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/boot/dts/vdk_axc003.dtsi linux-libre-4.7-gnu/arch/arc/boot/dts/vdk_axc003.dtsi
--- linux-libre-4.6-gnu/arch/arc/boot/dts/vdk_axc003.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/boot/dts/vdk_axc003.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -10,9 +10,10 @@
  * Device tree for AXC003 CPU card: HS38x UP configuration (VDK version)
  */
 
+/include/ "skeleton_hs.dtsi"
+
 / {
 	compatible = "snps,arc";
-	clock-frequency = <50000000>;
 	#address-cells = <1>;
 	#size-cells = <1>;
 
@@ -23,7 +24,13 @@
 
 		ranges = <0x00000000 0xf0000000 0x10000000>;
 
-		cpu_intc: archs-intc@cpu {
+		core_clk: core_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <50000000>;
+		};
+
+		core_intc: archs-intc@cpu {
 			compatible = "snps,archs-intc";
 			interrupt-controller;
 			#interrupt-cells = <1>;
@@ -33,7 +40,7 @@
 			compatible = "snps,dw-apb-uart";
 			reg = <0x5000 0x100>;
 			clock-frequency = <2403200>;
-			interrupt-parent = <&cpu_intc>;
+			interrupt-parent = <&core_intc>;
 			interrupts = <19>;
 			baud = <115200>;
 			reg-shift = <2>;
@@ -47,7 +54,7 @@
 		compatible = "snps,dw-apb-ictl";
 		reg = < 0xe0012000 0x200 >;
 		interrupt-controller;
-		interrupt-parent = <&cpu_intc>;
+		interrupt-parent = <&core_intc>;
 		interrupts = < 18 >;
 	};
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/boot/dts/vdk_axc003_idu.dtsi linux-libre-4.7-gnu/arch/arc/boot/dts/vdk_axc003_idu.dtsi
--- linux-libre-4.6-gnu/arch/arc/boot/dts/vdk_axc003_idu.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/boot/dts/vdk_axc003_idu.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -11,9 +11,10 @@
  * HS38x2 (Dual Core) with IDU intc (VDK version)
  */
 
+/include/ "skeleton_hs_idu.dtsi"
+
 / {
 	compatible = "snps,arc";
-	clock-frequency = <50000000>;
 	#address-cells = <1>;
 	#size-cells = <1>;
 
@@ -24,7 +25,13 @@
 
 		ranges = <0x00000000 0xf0000000 0x10000000>;
 
-		cpu_intc: archs-intc@cpu {
+		core_clk: core_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <50000000>;
+		};
+
+		core_intc: archs-intc@cpu {
 			compatible = "snps,archs-intc";
 			interrupt-controller;
 			#interrupt-cells = <1>;
@@ -33,7 +40,7 @@
 		idu_intc: idu-interrupt-controller {
 			compatible = "snps,archs-idu-intc";
 			interrupt-controller;
-			interrupt-parent = <&cpu_intc>;
+			interrupt-parent = <&core_intc>;
 
 			/*
 			 * <hwirq  distribution>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/configs/nps_defconfig linux-libre-4.7-gnu/arch/arc/configs/nps_defconfig
--- linux-libre-4.6-gnu/arch/arc/configs/nps_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arc/configs/nps_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,84 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ_IDLE=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_EPOLL is not set
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
+# CONFIG_AIO is not set
+CONFIG_EMBEDDED=y
+CONFIG_PERF_EVENTS=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_KPROBES=y
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARC_PLAT_EZNPS=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=4096
+CONFIG_ARC_CACHE_LINE_SHIFT=5
+# CONFIG_ARC_CACHE_PAGES is not set
+# CONFIG_ARC_HAS_LLSC is not set
+CONFIG_ARC_KVADDR_SIZE=402
+CONFIG_ARC_EMUL_UNALIGNED=y
+CONFIG_ARC_UBOOT_SUPPORT=y
+CONFIG_PREEMPT=y
+CONFIG_NET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=1
+CONFIG_BLK_DEV_RAM_SIZE=2048
+CONFIG_NETDEVICES=y
+CONFIG_NETCONSOLE=y
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_WLAN is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=1
+CONFIG_SERIAL_8250_RUNTIME_UARTS=1
+CONFIG_SERIAL_8250_DW=y
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_DNOTIFY is not set
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_ENABLE_DEFAULT_TRACERS=y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/include/asm/atomic.h linux-libre-4.7-gnu/arch/arc/include/asm/atomic.h
--- linux-libre-4.6-gnu/arch/arc/include/asm/atomic.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/include/asm/atomic.h	2016-07-24 15:23:50.000000000 -0400
@@ -17,56 +17,25 @@
 #include <asm/barrier.h>
 #include <asm/smp.h>
 
+#ifndef CONFIG_ARC_PLAT_EZNPS
+
 #define atomic_read(v)  READ_ONCE((v)->counter)
 
 #ifdef CONFIG_ARC_HAS_LLSC
 
 #define atomic_set(v, i) WRITE_ONCE(((v)->counter), (i))
 
-#ifdef CONFIG_ARC_STAR_9000923308
-
-#define SCOND_FAIL_RETRY_VAR_DEF						\
-	unsigned int delay = 1, tmp;						\
-
-#define SCOND_FAIL_RETRY_ASM							\
-	"	bz	4f			\n"				\
-	"   ; --- scond fail delay ---		\n"				\
-	"	mov	%[tmp], %[delay]	\n"	/* tmp = delay */	\
-	"2: 	brne.d	%[tmp], 0, 2b		\n"	/* while (tmp != 0) */	\
-	"	sub	%[tmp], %[tmp], 1	\n"	/* tmp-- */		\
-	"	rol	%[delay], %[delay]	\n"	/* delay *= 2 */	\
-	"	b	1b			\n"	/* start over */	\
-	"4: ; --- success ---			\n"				\
-
-#define SCOND_FAIL_RETRY_VARS							\
-	  ,[delay] "+&r" (delay),[tmp] "=&r"	(tmp)				\
-
-#else	/* !CONFIG_ARC_STAR_9000923308 */
-
-#define SCOND_FAIL_RETRY_VAR_DEF
-
-#define SCOND_FAIL_RETRY_ASM							\
-	"	bnz     1b			\n"				\
-
-#define SCOND_FAIL_RETRY_VARS
-
-#endif
-
 #define ATOMIC_OP(op, c_op, asm_op)					\
 static inline void atomic_##op(int i, atomic_t *v)			\
 {									\
-	unsigned int val;				                \
-	SCOND_FAIL_RETRY_VAR_DEF                                        \
+	unsigned int val;						\
 									\
 	__asm__ __volatile__(						\
 	"1:	llock   %[val], [%[ctr]]		\n"		\
 	"	" #asm_op " %[val], %[val], %[i]	\n"		\
 	"	scond   %[val], [%[ctr]]		\n"		\
-	"						\n"		\
-	SCOND_FAIL_RETRY_ASM						\
-									\
+	"	bnz     1b				\n"		\
 	: [val]	"=&r"	(val) /* Early clobber to prevent reg reuse */	\
-	  SCOND_FAIL_RETRY_VARS						\
 	: [ctr]	"r"	(&v->counter), /* Not "m": llock only supports reg direct addr mode */	\
 	  [i]	"ir"	(i)						\
 	: "cc");							\
@@ -75,8 +44,7 @@ static inline void atomic_##op(int i, at
 #define ATOMIC_OP_RETURN(op, c_op, asm_op)				\
 static inline int atomic_##op##_return(int i, atomic_t *v)		\
 {									\
-	unsigned int val;				                \
-	SCOND_FAIL_RETRY_VAR_DEF                                        \
+	unsigned int val;						\
 									\
 	/*								\
 	 * Explicit full memory barrier needed before/after as		\
@@ -88,11 +56,8 @@ static inline int atomic_##op##_return(i
 	"1:	llock   %[val], [%[ctr]]		\n"		\
 	"	" #asm_op " %[val], %[val], %[i]	\n"		\
 	"	scond   %[val], [%[ctr]]		\n"		\
-	"						\n"		\
-	SCOND_FAIL_RETRY_ASM						\
-									\
+	"	bnz     1b				\n"		\
 	: [val]	"=&r"	(val)						\
-	  SCOND_FAIL_RETRY_VARS						\
 	: [ctr]	"r"	(&v->counter),					\
 	  [i]	"ir"	(i)						\
 	: "cc");							\
@@ -180,13 +145,88 @@ ATOMIC_OP(andnot, &= ~, bic)
 ATOMIC_OP(or, |=, or)
 ATOMIC_OP(xor, ^=, xor)
 
-#undef ATOMIC_OPS
-#undef ATOMIC_OP_RETURN
-#undef ATOMIC_OP
 #undef SCOND_FAIL_RETRY_VAR_DEF
 #undef SCOND_FAIL_RETRY_ASM
 #undef SCOND_FAIL_RETRY_VARS
 
+#else /* CONFIG_ARC_PLAT_EZNPS */
+
+static inline int atomic_read(const atomic_t *v)
+{
+	int temp;
+
+	__asm__ __volatile__(
+	"	ld.di %0, [%1]"
+	: "=r"(temp)
+	: "r"(&v->counter)
+	: "memory");
+	return temp;
+}
+
+static inline void atomic_set(atomic_t *v, int i)
+{
+	__asm__ __volatile__(
+	"	st.di %0,[%1]"
+	:
+	: "r"(i), "r"(&v->counter)
+	: "memory");
+}
+
+#define ATOMIC_OP(op, c_op, asm_op)					\
+static inline void atomic_##op(int i, atomic_t *v)			\
+{									\
+	__asm__ __volatile__(						\
+	"	mov r2, %0\n"						\
+	"	mov r3, %1\n"						\
+	"       .word %2\n"						\
+	:								\
+	: "r"(i), "r"(&v->counter), "i"(asm_op)				\
+	: "r2", "r3", "memory");					\
+}									\
+
+#define ATOMIC_OP_RETURN(op, c_op, asm_op)				\
+static inline int atomic_##op##_return(int i, atomic_t *v)		\
+{									\
+	unsigned int temp = i;						\
+									\
+	/* Explicit full memory barrier needed before/after */		\
+	smp_mb();							\
+									\
+	__asm__ __volatile__(						\
+	"	mov r2, %0\n"						\
+	"	mov r3, %1\n"						\
+	"       .word %2\n"						\
+	"	mov %0, r2"						\
+	: "+r"(temp)							\
+	: "r"(&v->counter), "i"(asm_op)					\
+	: "r2", "r3", "memory");					\
+									\
+	smp_mb();							\
+									\
+	temp c_op i;							\
+									\
+	return temp;							\
+}
+
+#define ATOMIC_OPS(op, c_op, asm_op)					\
+	ATOMIC_OP(op, c_op, asm_op)					\
+	ATOMIC_OP_RETURN(op, c_op, asm_op)
+
+ATOMIC_OPS(add, +=, CTOP_INST_AADD_DI_R2_R2_R3)
+#define atomic_sub(i, v) atomic_add(-(i), (v))
+#define atomic_sub_return(i, v) atomic_add_return(-(i), (v))
+
+ATOMIC_OP(and, &=, CTOP_INST_AAND_DI_R2_R2_R3)
+#define atomic_andnot(mask, v) atomic_and(~(mask), (v))
+ATOMIC_OP(or, |=, CTOP_INST_AOR_DI_R2_R2_R3)
+ATOMIC_OP(xor, ^=, CTOP_INST_AXOR_DI_R2_R2_R3)
+
+#endif /* CONFIG_ARC_PLAT_EZNPS */
+
+#undef ATOMIC_OPS
+#undef ATOMIC_OP_RETURN
+#undef ATOMIC_OP
+
 /**
  * __atomic_add_unless - add unless the number is a given value
  * @v: pointer of type atomic_t
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/include/asm/barrier.h linux-libre-4.7-gnu/arch/arc/include/asm/barrier.h
--- linux-libre-4.6-gnu/arch/arc/include/asm/barrier.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/include/asm/barrier.h	2016-07-24 15:23:50.000000000 -0400
@@ -30,9 +30,7 @@
 #define rmb()	asm volatile("dmb 1\n" : : : "memory")
 #define wmb()	asm volatile("dmb 2\n" : : : "memory")
 
-#endif
-
-#ifdef CONFIG_ISA_ARCOMPACT
+#elif !defined(CONFIG_ARC_PLAT_EZNPS)  /* CONFIG_ISA_ARCOMPACT */
 
 /*
  * ARCompact based cores (ARC700) only have SYNC instruction which is super
@@ -41,6 +39,14 @@
  */
 
 #define mb()	asm volatile("sync\n" : : : "memory")
+
+#else	/* CONFIG_ARC_PLAT_EZNPS */
+
+#include <plat/ctop.h>
+
+#define mb()	asm volatile (".word %0" : : "i"(CTOP_INST_SCHD_RW) : "memory")
+#define rmb()	asm volatile (".word %0" : : "i"(CTOP_INST_SCHD_RD) : "memory")
+
 #endif
 
 #include <asm-generic/barrier.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/include/asm/bitops.h linux-libre-4.7-gnu/arch/arc/include/asm/bitops.h
--- linux-libre-4.6-gnu/arch/arc/include/asm/bitops.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/include/asm/bitops.h	2016-07-24 15:23:50.000000000 -0400
@@ -22,7 +22,7 @@
 #include <asm/smp.h>
 #endif
 
-#if defined(CONFIG_ARC_HAS_LLSC)
+#ifdef CONFIG_ARC_HAS_LLSC
 
 /*
  * Hardware assisted Atomic-R-M-W
@@ -88,7 +88,7 @@ static inline int test_and_##op##_bit(un
 	return (old & (1 << nr)) != 0;					\
 }
 
-#else	/* !CONFIG_ARC_HAS_LLSC */
+#elif !defined(CONFIG_ARC_PLAT_EZNPS)
 
 /*
  * Non hardware assisted Atomic-R-M-W
@@ -139,7 +139,55 @@ static inline int test_and_##op##_bit(un
 	return (old & (1UL << (nr & 0x1f))) != 0;			\
 }
 
-#endif /* CONFIG_ARC_HAS_LLSC */
+#else /* CONFIG_ARC_PLAT_EZNPS */
+
+#define BIT_OP(op, c_op, asm_op)					\
+static inline void op##_bit(unsigned long nr, volatile unsigned long *m)\
+{									\
+	m += nr >> 5;							\
+									\
+	nr = (1UL << (nr & 0x1f));					\
+	if (asm_op == CTOP_INST_AAND_DI_R2_R2_R3)			\
+		nr = ~nr;						\
+									\
+	__asm__ __volatile__(						\
+	"	mov r2, %0\n"						\
+	"	mov r3, %1\n"						\
+	"	.word %2\n"						\
+	:								\
+	: "r"(nr), "r"(m), "i"(asm_op)					\
+	: "r2", "r3", "memory");					\
+}
+
+#define TEST_N_BIT_OP(op, c_op, asm_op)					\
+static inline int test_and_##op##_bit(unsigned long nr, volatile unsigned long *m)\
+{									\
+	unsigned long old;						\
+									\
+	m += nr >> 5;							\
+									\
+	nr = old = (1UL << (nr & 0x1f));				\
+	if (asm_op == CTOP_INST_AAND_DI_R2_R2_R3)			\
+		old = ~old;						\
+									\
+	/* Explicit full memory barrier needed before/after */		\
+	smp_mb();							\
+									\
+	__asm__ __volatile__(						\
+	"	mov r2, %0\n"						\
+	"	mov r3, %1\n"						\
+	"       .word %2\n"						\
+	"	mov %0, r2"						\
+	: "+r"(old)							\
+	: "r"(m), "i"(asm_op)						\
+	: "r2", "r3", "memory");					\
+									\
+	smp_mb();							\
+									\
+	return (old & nr) != 0;					\
+}
+
+#endif /* CONFIG_ARC_PLAT_EZNPS */
 
 /***************************************
  * Non atomic variants
@@ -181,9 +229,15 @@ static inline int __test_and_##op##_bit(
 	/* __test_and_set_bit(), __test_and_clear_bit(), __test_and_change_bit() */\
 	__TEST_N_BIT_OP(op, c_op, asm_op)
 
+#ifndef CONFIG_ARC_PLAT_EZNPS
 BIT_OPS(set, |, bset)
 BIT_OPS(clear, & ~, bclr)
 BIT_OPS(change, ^, bxor)
+#else
+BIT_OPS(set, |, CTOP_INST_AOR_DI_R2_R2_R3)
+BIT_OPS(clear, & ~, CTOP_INST_AAND_DI_R2_R2_R3)
+BIT_OPS(change, ^, CTOP_INST_AXOR_DI_R2_R2_R3)
+#endif
 
 /*
  * This routine doesn't need to be atomic.
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/include/asm/clk.h linux-libre-4.7-gnu/arch/arc/include/asm/clk.h
--- linux-libre-4.6-gnu/arch/arc/include/asm/clk.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/include/asm/clk.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2012 Synopsys, Inc. (www.synopsys.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef _ASM_ARC_CLK_H
-#define _ASM_ARC_CLK_H
-
-/* Although we can't really hide core_freq, the accessor is still better way */
-extern unsigned long core_freq;
-
-static inline unsigned long arc_get_core_freq(void)
-{
-	return core_freq;
-}
-
-extern int arc_set_core_freq(unsigned long);
-
-#endif
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/include/asm/cmpxchg.h linux-libre-4.7-gnu/arch/arc/include/asm/cmpxchg.h
--- linux-libre-4.6-gnu/arch/arc/include/asm/cmpxchg.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/include/asm/cmpxchg.h	2016-07-24 15:23:50.000000000 -0400
@@ -44,7 +44,7 @@ __cmpxchg(volatile void *ptr, unsigned l
 	return prev;
 }
 
-#else
+#elif !defined(CONFIG_ARC_PLAT_EZNPS)
 
 static inline unsigned long
 __cmpxchg(volatile void *ptr, unsigned long expected, unsigned long new)
@@ -64,23 +64,48 @@ __cmpxchg(volatile void *ptr, unsigned l
 	return prev;
 }
 
+#else /* CONFIG_ARC_PLAT_EZNPS */
+
+static inline unsigned long
+__cmpxchg(volatile void *ptr, unsigned long expected, unsigned long new)
+{
+	/*
+	 * Explicit full memory barrier needed before/after
+	 */
+	smp_mb();
+
+	write_aux_reg(CTOP_AUX_GPA1, expected);
+
+	__asm__ __volatile__(
+	"	mov r2, %0\n"
+	"	mov r3, %1\n"
+	"	.word %2\n"
+	"	mov %0, r2"
+	: "+r"(new)
+	: "r"(ptr), "i"(CTOP_INST_EXC_DI_R2_R2_R3)
+	: "r2", "r3", "memory");
+
+	smp_mb();
+
+	return new;
+}
+
 #endif /* CONFIG_ARC_HAS_LLSC */
 
 #define cmpxchg(ptr, o, n) ((typeof(*(ptr)))__cmpxchg((ptr), \
 				(unsigned long)(o), (unsigned long)(n)))
 
 /*
- * Since not supported natively, ARC cmpxchg() uses atomic_ops_lock (UP/SMP)
- * just to gaurantee semantics.
- * atomic_cmpxchg() needs to use the same locks as it's other atomic siblings
- * which also happens to be atomic_ops_lock.
- *
- * Thus despite semantically being different, implementation of atomic_cmpxchg()
- * is same as cmpxchg().
+ * atomic_cmpxchg is same as cmpxchg
+ *   LLSC: only different in data-type, semantics are exactly same
+ *  !LLSC: cmpxchg() has to use an external lock atomic_ops_lock to guarantee
+ *         semantics, and this lock also happens to be used by atomic_*()
  */
 #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
 
 
+#ifndef CONFIG_ARC_PLAT_EZNPS
+
 /*
  * xchg (reg with memory) based on "Native atomic" EX insn
  */
@@ -143,6 +168,41 @@ static inline unsigned long __xchg(unsig
 
 #endif
 
+#else /* CONFIG_ARC_PLAT_EZNPS */
+
+static inline unsigned long __xchg(unsigned long val, volatile void *ptr,
+				   int size)
+{
+	extern unsigned long __xchg_bad_pointer(void);
+
+	switch (size) {
+	case 4:
+		/*
+		 * Explicit full memory barrier needed before/after
+		 */
+		smp_mb();
+
+		__asm__ __volatile__(
+		"	mov r2, %0\n"
+		"	mov r3, %1\n"
+		"	.word %2\n"
+		"	mov %0, r2\n"
+		: "+r"(val)
+		: "r"(ptr), "i"(CTOP_INST_XEX_DI_R2_R2_R3)
+		: "r2", "r3", "memory");
+
+		smp_mb();
+
+		return val;
+	}
+	return __xchg_bad_pointer();
+}
+
+#define xchg(ptr, with) ((typeof(*(ptr)))__xchg((unsigned long)(with), (ptr), \
+						 sizeof(*(ptr))))
+
+#endif /* CONFIG_ARC_PLAT_EZNPS */
+
 /*
  * "atomic" variant of xchg()
  * REQ: It needs to follow the same serialization rules as other atomic_xxx()
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/include/asm/entry-compact.h linux-libre-4.7-gnu/arch/arc/include/asm/entry-compact.h
--- linux-libre-4.6-gnu/arch/arc/include/asm/entry-compact.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/include/asm/entry-compact.h	2016-07-24 15:23:50.000000000 -0400
@@ -36,6 +36,10 @@
 #include <asm/irqflags-compact.h>
 #include <asm/thread_info.h>	/* For THREAD_SIZE */
 
+#ifdef CONFIG_ARC_PLAT_EZNPS
+#include <plat/ctop.h>
+#endif
+
 /*--------------------------------------------------------------
  * Switch to Kernel Mode stack if SP points to User Mode stack
  *
@@ -72,8 +76,8 @@
 	 * We need to be a bit more cautious here. What if a kernel bug in
 	 * L1 ISR, caused SP to go whaco (some small value which looks like
 	 * USER stk) and then we take L2 ISR.
-	 * Above brlo alone would treat it as a valid L1-L2 sceanrio
-	 * instead of shouting alound
+	 * Above brlo alone would treat it as a valid L1-L2 scenario
+	 * instead of shouting around
 	 * The only feasible way is to make sure this L2 happened in
 	 * L1 prelogue ONLY i.e. ilink2 is less than a pre-set marker in
 	 * L1 ISR before it switches stack
@@ -296,11 +300,13 @@
 	bic \reg, sp, (THREAD_SIZE - 1)
 .endm
 
+#ifndef CONFIG_ARC_PLAT_EZNPS
 /* Get CPU-ID of this core */
 .macro  GET_CPU_ID  reg
 	lr  \reg, [identity]
 	lsr \reg, \reg, 8
 	bmsk \reg, \reg, 7
 .endm
+#endif
 
 #endif  /* __ASM_ARC_ENTRY_COMPACT_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/include/asm/hugepage.h linux-libre-4.7-gnu/arch/arc/include/asm/hugepage.h
--- linux-libre-4.6-gnu/arch/arc/include/asm/hugepage.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/include/asm/hugepage.h	2016-07-24 15:23:50.000000000 -0400
@@ -61,8 +61,6 @@ static inline void set_pmd_at(struct mm_
 extern void update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr,
 				 pmd_t *pmd);
 
-#define has_transparent_hugepage() 1
-
 /* Generic variants assume pgtable_t is struct page *, hence need for these */
 #define __HAVE_ARCH_PGTABLE_DEPOSIT
 extern void pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp,
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/include/asm/irq.h linux-libre-4.7-gnu/arch/arc/include/asm/irq.h
--- linux-libre-4.6-gnu/arch/arc/include/asm/irq.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/include/asm/irq.h	2016-07-24 15:23:50.000000000 -0400
@@ -13,21 +13,14 @@
 #define NR_IRQS		128 /* allow some CPU external IRQ handling */
 
 /* Platform Independent IRQs */
-#ifdef CONFIG_ISA_ARCOMPACT
-#define TIMER0_IRQ      3
-#define TIMER1_IRQ      4
-#else
-#define TIMER0_IRQ      16
-#define TIMER1_IRQ      17
+#ifdef CONFIG_ISA_ARCV2
+#define IPI_IRQ		19
+#define SOFTIRQ_IRQ	21
 #endif
 
 #include <linux/interrupt.h>
 #include <asm-generic/irq.h>
 
 extern void arc_init_IRQ(void);
-void arc_local_timer_setup(void);
-void arc_request_percpu_irq(int irq, int cpu,
-                            irqreturn_t (*isr)(int irq, void *dev),
-                            const char *irq_nm, void *percpu_dev);
 
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/include/asm/mmu_context.h linux-libre-4.7-gnu/arch/arc/include/asm/mmu_context.h
--- linux-libre-4.6-gnu/arch/arc/include/asm/mmu_context.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/include/asm/mmu_context.h	2016-07-24 15:23:50.000000000 -0400
@@ -83,7 +83,7 @@ static inline void get_new_mmu_context(s
 		local_flush_tlb_all();
 
 		/*
-		 * Above checke for rollover of 8 bit ASID in 32 bit container.
+		 * Above check for rollover of 8 bit ASID in 32 bit container.
 		 * If the container itself wrapped around, set it to a non zero
 		 * "generation" to distinguish from no context
 		 */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/include/asm/page.h linux-libre-4.7-gnu/arch/arc/include/asm/page.h
--- linux-libre-4.6-gnu/arch/arc/include/asm/page.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/include/asm/page.h	2016-07-24 15:23:50.000000000 -0400
@@ -31,7 +31,11 @@ void clear_user_page(void *to, unsigned
  * These are used to make use of C type-checking..
  */
 typedef struct {
+#ifdef CONFIG_ARC_HAS_PAE40
+	unsigned long long pte;
+#else
 	unsigned long pte;
+#endif
 } pte_t;
 typedef struct {
 	unsigned long pgd;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/include/asm/pgalloc.h linux-libre-4.7-gnu/arch/arc/include/asm/pgalloc.h
--- linux-libre-4.6-gnu/arch/arc/include/asm/pgalloc.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/include/asm/pgalloc.h	2016-07-24 15:23:50.000000000 -0400
@@ -95,7 +95,7 @@ static inline pte_t *pte_alloc_one_kerne
 {
 	pte_t *pte;
 
-	pte = (pte_t *) __get_free_pages(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO,
+	pte = (pte_t *) __get_free_pages(GFP_KERNEL | __GFP_ZERO,
 					 __get_order_pte());
 
 	return pte;
@@ -107,7 +107,7 @@ pte_alloc_one(struct mm_struct *mm, unsi
 	pgtable_t pte_pg;
 	struct page *page;
 
-	pte_pg = (pgtable_t)__get_free_pages(GFP_KERNEL | __GFP_REPEAT, __get_order_pte());
+	pte_pg = (pgtable_t)__get_free_pages(GFP_KERNEL, __get_order_pte());
 	if (!pte_pg)
 		return 0;
 	memzero((void *)pte_pg, PTRS_PER_PTE * sizeof(pte_t));
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/include/asm/pgtable.h linux-libre-4.7-gnu/arch/arc/include/asm/pgtable.h
--- linux-libre-4.6-gnu/arch/arc/include/asm/pgtable.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/include/asm/pgtable.h	2016-07-24 15:23:50.000000000 -0400
@@ -47,7 +47,7 @@
  * Page Tables are purely for Linux VM's consumption and the bits below are
  * suited to that (uniqueness). Hence some are not implemented in the TLB and
  * some have different value in TLB.
- * e.g. MMU v2: K_READ bit is 8 and so is GLOBAL (possible becoz they live in
+ * e.g. MMU v2: K_READ bit is 8 and so is GLOBAL (possible because they live in
  *      seperate PD0 and PD1, which combined forms a translation entry)
  *      while for PTE perspective, they are 8 and 9 respectively
  * with MMU v3: Most bits (except SHARED) represent the exact hardware pos
@@ -217,7 +217,7 @@
 #define BITS_FOR_PTE	(PGDIR_SHIFT - PAGE_SHIFT)
 #define BITS_FOR_PGD	(32 - PGDIR_SHIFT)
 
-#define PGDIR_SIZE	(1UL << PGDIR_SHIFT)	/* vaddr span, not PDG sz */
+#define PGDIR_SIZE	_BITUL(PGDIR_SHIFT)	/* vaddr span, not PDG sz */
 #define PGDIR_MASK	(~(PGDIR_SIZE-1))
 
 #define	PTRS_PER_PTE	_BITUL(BITS_FOR_PTE)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/include/asm/processor.h linux-libre-4.7-gnu/arch/arc/include/asm/processor.h
--- linux-libre-4.6-gnu/arch/arc/include/asm/processor.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/include/asm/processor.h	2016-07-24 15:23:50.000000000 -0400
@@ -57,9 +57,19 @@ struct task_struct;
  * A lot of busy-wait loops in SMP are based off of non-volatile data otherwise
  * get optimised away by gcc
  */
-#define cpu_relax()	__asm__ __volatile__ ("" : : : "memory")
+#ifndef CONFIG_EZNPS_MTM_EXT
 
-#define cpu_relax_lowlatency() cpu_relax()
+#define cpu_relax()		barrier()
+#define cpu_relax_lowlatency()	cpu_relax()
+
+#else
+
+#define cpu_relax()     \
+	__asm__ __volatile__ (".word %0" : : "i"(CTOP_INST_SCHD_RW) : "memory")
+
+#define cpu_relax_lowlatency()	barrier()
+
+#endif
 
 #define copy_segments(tsk, mm)      do { } while (0)
 #define release_segments(mm)        do { } while (0)
@@ -68,7 +78,7 @@ struct task_struct;
 #define KSTK_ESP(tsk)   (task_pt_regs(tsk)->sp)
 
 /*
- * Where abouts of Task's sp, fp, blink when it was last seen in kernel mode.
+ * Where about of Task's sp, fp, blink when it was last seen in kernel mode.
  * Look in process.c for details of kernel stack layout
  */
 #define TSK_K_ESP(tsk)		(tsk->thread.ksp)
@@ -97,7 +107,7 @@ extern unsigned int get_wchan(struct tas
 #endif /* !__ASSEMBLY__ */
 
 /*
- * System Memory Map on ARC
+ * Default System Memory Map on ARC
  *
  * ---------------------------- (lower 2G, Translated) -------------------------
  * 0x0000_0000		0x5FFF_FFFF	(user vaddr: TASK_SIZE)
@@ -109,20 +119,37 @@ extern unsigned int get_wchan(struct tas
  * 0xC000_0000		0xFFFF_FFFF	(peripheral uncached space)
  * -----------------------------------------------------------------------------
  */
-#define VMALLOC_START	0x70000000
 
-/*
- * 1 PGDIR_SIZE each for fixmap/pkmap, 2 PGDIR_SIZE gutter
- * See asm/highmem.h for details
- */
-#define VMALLOC_SIZE	(PAGE_OFFSET - VMALLOC_START - PGDIR_SIZE * 4)
-#define VMALLOC_END	(VMALLOC_START + VMALLOC_SIZE)
+#define TASK_SIZE	0x60000000
 
-#define USER_KERNEL_GUTTER    0x10000000
+#define VMALLOC_START	(PAGE_OFFSET - (CONFIG_ARC_KVADDR_SIZE << 20))
 
-#define TASK_SIZE	(VMALLOC_START - USER_KERNEL_GUTTER)
+/* 1 PGDIR_SIZE each for fixmap/pkmap, 2 PGDIR_SIZE gutter (see asm/highmem.h) */
+#define VMALLOC_SIZE	((CONFIG_ARC_KVADDR_SIZE << 20) - PGDIR_SIZE * 4)
 
+#define VMALLOC_END	(VMALLOC_START + VMALLOC_SIZE)
+
+#define USER_KERNEL_GUTTER    (VMALLOC_START - TASK_SIZE)
+
+#ifdef CONFIG_ARC_PLAT_EZNPS
+/* NPS architecture defines special window of 129M in user address space for
+ * special memory areas, when accessing this window the MMU do not use TLB.
+ * Instead MMU direct the access to:
+ * 0x57f00000:0x57ffffff -- 1M of closely coupled memory (aka CMEM)
+ * 0x58000000:0x5fffffff -- 16 huge pages, 8M each, with fixed map (aka FMTs)
+ *
+ * CMEM - is the fastest memory we got and its size is 16K.
+ * FMT  - is used to map either to internal/external memory.
+ * Internal memory is the second fast memory and its size is 16M
+ * External memory is the biggest memory (16G) and also the slowest.
+ *
+ * STACK_TOP need to be PMD align (21bit) that is why we supply 0x57e00000.
+ */
+#define STACK_TOP       0x57e00000
+#else
 #define STACK_TOP       TASK_SIZE
+#endif
+
 #define STACK_TOP_MAX   STACK_TOP
 
 /* This decides where the kernel will search for a free chunk of vm
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/include/asm/setup.h linux-libre-4.7-gnu/arch/arc/include/asm/setup.h
--- linux-libre-4.6-gnu/arch/arc/include/asm/setup.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/include/asm/setup.h	2016-07-24 15:23:50.000000000 -0400
@@ -12,7 +12,11 @@
 #include <linux/types.h>
 #include <uapi/asm/setup.h>
 
+#ifdef CONFIG_ARC_PLAT_EZNPS
+#define COMMAND_LINE_SIZE 2048
+#else
 #define COMMAND_LINE_SIZE 256
+#endif
 
 /*
  * Data structure to map a ID to string
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/include/asm/smp.h linux-libre-4.7-gnu/arch/arc/include/asm/smp.h
--- linux-libre-4.6-gnu/arch/arc/include/asm/smp.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/include/asm/smp.h	2016-07-24 15:23:50.000000000 -0400
@@ -86,7 +86,7 @@ static inline const char *arc_platform_s
  * (1) These insn were introduced only in 4.10 release. So for older released
  *	support needed.
  *
- * (2) In a SMP setup, the LLOCK/SCOND atomiticity across CPUs needs to be
+ * (2) In a SMP setup, the LLOCK/SCOND atomicity across CPUs needs to be
  *	gaurantted by the platform (not something which core handles).
  *	Assuming a platform won't, SMP Linux needs to use spinlocks + local IRQ
  *	disabling for atomicity.
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/include/asm/spinlock.h linux-libre-4.7-gnu/arch/arc/include/asm/spinlock.h
--- linux-libre-4.6-gnu/arch/arc/include/asm/spinlock.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/include/asm/spinlock.h	2016-07-24 15:23:50.000000000 -0400
@@ -20,11 +20,6 @@
 
 #ifdef CONFIG_ARC_HAS_LLSC
 
-/*
- * A normal LLOCK/SCOND based system, w/o need for livelock workaround
- */
-#ifndef CONFIG_ARC_STAR_9000923308
-
 static inline void arch_spin_lock(arch_spinlock_t *lock)
 {
 	unsigned int val;
@@ -238,293 +233,6 @@ static inline void arch_write_unlock(arc
 	smp_mb();
 }
 
-#else	/* CONFIG_ARC_STAR_9000923308 */
-
-/*
- * HS38x4 could get into a LLOCK/SCOND livelock in case of multiple overlapping
- * coherency transactions in the SCU. The exclusive line state keeps rotating
- * among contenting cores leading to a never ending cycle. So break the cycle
- * by deferring the retry of failed exclusive access (SCOND). The actual delay
- * needed is function of number of contending cores as well as the unrelated
- * coherency traffic from other cores. To keep the code simple, start off with
- * small delay of 1 which would suffice most cases and in case of contention
- * double the delay. Eventually the delay is sufficient such that the coherency
- * pipeline is drained, thus a subsequent exclusive access would succeed.
- */
-
-#define SCOND_FAIL_RETRY_VAR_DEF						\
-	unsigned int delay, tmp;						\
-
-#define SCOND_FAIL_RETRY_ASM							\
-	"   ; --- scond fail delay ---		\n"				\
-	"	mov	%[tmp], %[delay]	\n"	/* tmp = delay */	\
-	"2: 	brne.d	%[tmp], 0, 2b		\n"	/* while (tmp != 0) */	\
-	"	sub	%[tmp], %[tmp], 1	\n"	/* tmp-- */		\
-	"	rol	%[delay], %[delay]	\n"	/* delay *= 2 */	\
-	"	b	1b			\n"	/* start over */	\
-	"					\n"				\
-	"4: ; --- done ---			\n"				\
-
-#define SCOND_FAIL_RETRY_VARS							\
-	  ,[delay] "=&r" (delay), [tmp] "=&r"	(tmp)				\
-
-static inline void arch_spin_lock(arch_spinlock_t *lock)
-{
-	unsigned int val;
-	SCOND_FAIL_RETRY_VAR_DEF;
-
-	smp_mb();
-
-	__asm__ __volatile__(
-	"0:	mov	%[delay], 1		\n"
-	"1:	llock	%[val], [%[slock]]	\n"
-	"	breq	%[val], %[LOCKED], 0b	\n"	/* spin while LOCKED */
-	"	scond	%[LOCKED], [%[slock]]	\n"	/* acquire */
-	"	bz	4f			\n"	/* done */
-	"					\n"
-	SCOND_FAIL_RETRY_ASM
-
-	: [val]		"=&r"	(val)
-	  SCOND_FAIL_RETRY_VARS
-	: [slock]	"r"	(&(lock->slock)),
-	  [LOCKED]	"r"	(__ARCH_SPIN_LOCK_LOCKED__)
-	: "memory", "cc");
-
-	smp_mb();
-}
-
-/* 1 - lock taken successfully */
-static inline int arch_spin_trylock(arch_spinlock_t *lock)
-{
-	unsigned int val, got_it = 0;
-	SCOND_FAIL_RETRY_VAR_DEF;
-
-	smp_mb();
-
-	__asm__ __volatile__(
-	"0:	mov	%[delay], 1		\n"
-	"1:	llock	%[val], [%[slock]]	\n"
-	"	breq	%[val], %[LOCKED], 4f	\n"	/* already LOCKED, just bail */
-	"	scond	%[LOCKED], [%[slock]]	\n"	/* acquire */
-	"	bz.d	4f			\n"
-	"	mov.z	%[got_it], 1		\n"	/* got it */
-	"					\n"
-	SCOND_FAIL_RETRY_ASM
-
-	: [val]		"=&r"	(val),
-	  [got_it]	"+&r"	(got_it)
-	  SCOND_FAIL_RETRY_VARS
-	: [slock]	"r"	(&(lock->slock)),
-	  [LOCKED]	"r"	(__ARCH_SPIN_LOCK_LOCKED__)
-	: "memory", "cc");
-
-	smp_mb();
-
-	return got_it;
-}
-
-static inline void arch_spin_unlock(arch_spinlock_t *lock)
-{
-	smp_mb();
-
-	lock->slock = __ARCH_SPIN_LOCK_UNLOCKED__;
-
-	smp_mb();
-}
-
-/*
- * Read-write spinlocks, allowing multiple readers but only one writer.
- * Unfair locking as Writers could be starved indefinitely by Reader(s)
- */
-
-static inline void arch_read_lock(arch_rwlock_t *rw)
-{
-	unsigned int val;
-	SCOND_FAIL_RETRY_VAR_DEF;
-
-	smp_mb();
-
-	/*
-	 * zero means writer holds the lock exclusively, deny Reader.
-	 * Otherwise grant lock to first/subseq reader
-	 *
-	 * 	if (rw->counter > 0) {
-	 *		rw->counter--;
-	 *		ret = 1;
-	 *	}
-	 */
-
-	__asm__ __volatile__(
-	"0:	mov	%[delay], 1		\n"
-	"1:	llock	%[val], [%[rwlock]]	\n"
-	"	brls	%[val], %[WR_LOCKED], 0b\n"	/* <= 0: spin while write locked */
-	"	sub	%[val], %[val], 1	\n"	/* reader lock */
-	"	scond	%[val], [%[rwlock]]	\n"
-	"	bz	4f			\n"	/* done */
-	"					\n"
-	SCOND_FAIL_RETRY_ASM
-
-	: [val]		"=&r"	(val)
-	  SCOND_FAIL_RETRY_VARS
-	: [rwlock]	"r"	(&(rw->counter)),
-	  [WR_LOCKED]	"ir"	(0)
-	: "memory", "cc");
-
-	smp_mb();
-}
-
-/* 1 - lock taken successfully */
-static inline int arch_read_trylock(arch_rwlock_t *rw)
-{
-	unsigned int val, got_it = 0;
-	SCOND_FAIL_RETRY_VAR_DEF;
-
-	smp_mb();
-
-	__asm__ __volatile__(
-	"0:	mov	%[delay], 1		\n"
-	"1:	llock	%[val], [%[rwlock]]	\n"
-	"	brls	%[val], %[WR_LOCKED], 4f\n"	/* <= 0: already write locked, bail */
-	"	sub	%[val], %[val], 1	\n"	/* counter-- */
-	"	scond	%[val], [%[rwlock]]	\n"
-	"	bz.d	4f			\n"
-	"	mov.z	%[got_it], 1		\n"	/* got it */
-	"					\n"
-	SCOND_FAIL_RETRY_ASM
-
-	: [val]		"=&r"	(val),
-	  [got_it]	"+&r"	(got_it)
-	  SCOND_FAIL_RETRY_VARS
-	: [rwlock]	"r"	(&(rw->counter)),
-	  [WR_LOCKED]	"ir"	(0)
-	: "memory", "cc");
-
-	smp_mb();
-
-	return got_it;
-}
-
-static inline void arch_write_lock(arch_rwlock_t *rw)
-{
-	unsigned int val;
-	SCOND_FAIL_RETRY_VAR_DEF;
-
-	smp_mb();
-
-	/*
-	 * If reader(s) hold lock (lock < __ARCH_RW_LOCK_UNLOCKED__),
-	 * deny writer. Otherwise if unlocked grant to writer
-	 * Hence the claim that Linux rwlocks are unfair to writers.
-	 * (can be starved for an indefinite time by readers).
-	 *
-	 *	if (rw->counter == __ARCH_RW_LOCK_UNLOCKED__) {
-	 *		rw->counter = 0;
-	 *		ret = 1;
-	 *	}
-	 */
-
-	__asm__ __volatile__(
-	"0:	mov	%[delay], 1		\n"
-	"1:	llock	%[val], [%[rwlock]]	\n"
-	"	brne	%[val], %[UNLOCKED], 0b	\n"	/* while !UNLOCKED spin */
-	"	mov	%[val], %[WR_LOCKED]	\n"
-	"	scond	%[val], [%[rwlock]]	\n"
-	"	bz	4f			\n"
-	"					\n"
-	SCOND_FAIL_RETRY_ASM
-
-	: [val]		"=&r"	(val)
-	  SCOND_FAIL_RETRY_VARS
-	: [rwlock]	"r"	(&(rw->counter)),
-	  [UNLOCKED]	"ir"	(__ARCH_RW_LOCK_UNLOCKED__),
-	  [WR_LOCKED]	"ir"	(0)
-	: "memory", "cc");
-
-	smp_mb();
-}
-
-/* 1 - lock taken successfully */
-static inline int arch_write_trylock(arch_rwlock_t *rw)
-{
-	unsigned int val, got_it = 0;
-	SCOND_FAIL_RETRY_VAR_DEF;
-
-	smp_mb();
-
-	__asm__ __volatile__(
-	"0:	mov	%[delay], 1		\n"
-	"1:	llock	%[val], [%[rwlock]]	\n"
-	"	brne	%[val], %[UNLOCKED], 4f	\n"	/* !UNLOCKED, bail */
-	"	mov	%[val], %[WR_LOCKED]	\n"
-	"	scond	%[val], [%[rwlock]]	\n"
-	"	bz.d	4f			\n"
-	"	mov.z	%[got_it], 1		\n"	/* got it */
-	"					\n"
-	SCOND_FAIL_RETRY_ASM
-
-	: [val]		"=&r"	(val),
-	  [got_it]	"+&r"	(got_it)
-	  SCOND_FAIL_RETRY_VARS
-	: [rwlock]	"r"	(&(rw->counter)),
-	  [UNLOCKED]	"ir"	(__ARCH_RW_LOCK_UNLOCKED__),
-	  [WR_LOCKED]	"ir"	(0)
-	: "memory", "cc");
-
-	smp_mb();
-
-	return got_it;
-}
-
-static inline void arch_read_unlock(arch_rwlock_t *rw)
-{
-	unsigned int val;
-
-	smp_mb();
-
-	/*
-	 * rw->counter++;
-	 */
-	__asm__ __volatile__(
-	"1:	llock	%[val], [%[rwlock]]	\n"
-	"	add	%[val], %[val], 1	\n"
-	"	scond	%[val], [%[rwlock]]	\n"
-	"	bnz	1b			\n"
-	"					\n"
-	: [val]		"=&r"	(val)
-	: [rwlock]	"r"	(&(rw->counter))
-	: "memory", "cc");
-
-	smp_mb();
-}
-
-static inline void arch_write_unlock(arch_rwlock_t *rw)
-{
-	unsigned int val;
-
-	smp_mb();
-
-	/*
-	 * rw->counter = __ARCH_RW_LOCK_UNLOCKED__;
-	 */
-	__asm__ __volatile__(
-	"1:	llock	%[val], [%[rwlock]]	\n"
-	"	scond	%[UNLOCKED], [%[rwlock]]\n"
-	"	bnz	1b			\n"
-	"					\n"
-	: [val]		"=&r"	(val)
-	: [rwlock]	"r"	(&(rw->counter)),
-	  [UNLOCKED]	"r"	(__ARCH_RW_LOCK_UNLOCKED__)
-	: "memory", "cc");
-
-	smp_mb();
-}
-
-#undef SCOND_FAIL_RETRY_VAR_DEF
-#undef SCOND_FAIL_RETRY_ASM
-#undef SCOND_FAIL_RETRY_VARS
-
-#endif	/* CONFIG_ARC_STAR_9000923308 */
-
 #else	/* !CONFIG_ARC_HAS_LLSC */
 
 static inline void arch_spin_lock(arch_spinlock_t *lock)
@@ -610,7 +318,9 @@ static inline void arch_spin_unlock(arch
 static inline int arch_read_trylock(arch_rwlock_t *rw)
 {
 	int ret = 0;
+	unsigned long flags;
 
+	local_irq_save(flags);
 	arch_spin_lock(&(rw->lock_mutex));
 
 	/*
@@ -623,6 +333,7 @@ static inline int arch_read_trylock(arch
 	}
 
 	arch_spin_unlock(&(rw->lock_mutex));
+	local_irq_restore(flags);
 
 	smp_mb();
 	return ret;
@@ -632,7 +343,9 @@ static inline int arch_read_trylock(arch
 static inline int arch_write_trylock(arch_rwlock_t *rw)
 {
 	int ret = 0;
+	unsigned long flags;
 
+	local_irq_save(flags);
 	arch_spin_lock(&(rw->lock_mutex));
 
 	/*
@@ -646,6 +359,7 @@ static inline int arch_write_trylock(arc
 		ret = 1;
 	}
 	arch_spin_unlock(&(rw->lock_mutex));
+	local_irq_restore(flags);
 
 	return ret;
 }
@@ -664,16 +378,24 @@ static inline void arch_write_lock(arch_
 
 static inline void arch_read_unlock(arch_rwlock_t *rw)
 {
+	unsigned long flags;
+
+	local_irq_save(flags);
 	arch_spin_lock(&(rw->lock_mutex));
 	rw->counter++;
 	arch_spin_unlock(&(rw->lock_mutex));
+	local_irq_restore(flags);
 }
 
 static inline void arch_write_unlock(arch_rwlock_t *rw)
 {
+	unsigned long flags;
+
+	local_irq_save(flags);
 	arch_spin_lock(&(rw->lock_mutex));
 	rw->counter = __ARCH_RW_LOCK_UNLOCKED__;
 	arch_spin_unlock(&(rw->lock_mutex));
+	local_irq_restore(flags);
 }
 
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/include/asm/thread_info.h linux-libre-4.7-gnu/arch/arc/include/asm/thread_info.h
--- linux-libre-4.6-gnu/arch/arc/include/asm/thread_info.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/include/asm/thread_info.h	2016-07-24 15:23:50.000000000 -0400
@@ -103,7 +103,7 @@ static inline __attribute_const__ struct
 
 /*
  * _TIF_ALLWORK_MASK includes SYSCALL_TRACE, but we don't need it.
- * SYSCALL_TRACE is anways seperately/unconditionally tested right after a
+ * SYSCALL_TRACE is anyway seperately/unconditionally tested right after a
  * syscall, so all that reamins to be tested is _TIF_WORK_MASK
  */
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/include/asm/uaccess.h linux-libre-4.7-gnu/arch/arc/include/asm/uaccess.h
--- linux-libre-4.6-gnu/arch/arc/include/asm/uaccess.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/include/asm/uaccess.h	2016-07-24 15:23:50.000000000 -0400
@@ -32,7 +32,7 @@
 #define __kernel_ok		(segment_eq(get_fs(), KERNEL_DS))
 
 /*
- * Algorthmically, for __user_ok() we want do:
+ * Algorithmically, for __user_ok() we want do:
  * 	(start < TASK_SIZE) && (start+len < TASK_SIZE)
  * where TASK_SIZE could either be retrieved from thread_info->addr_limit or
  * emitted directly in code.
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/include/uapi/asm/byteorder.h linux-libre-4.7-gnu/arch/arc/include/uapi/asm/byteorder.h
--- linux-libre-4.6-gnu/arch/arc/include/uapi/asm/byteorder.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/include/uapi/asm/byteorder.h	2016-07-24 15:23:50.000000000 -0400
@@ -9,7 +9,7 @@
 #ifndef __ASM_ARC_BYTEORDER_H
 #define __ASM_ARC_BYTEORDER_H
 
-#ifdef CONFIG_CPU_BIG_ENDIAN
+#ifdef __BIG_ENDIAN__
 #include <linux/byteorder/big_endian.h>
 #else
 #include <linux/byteorder/little_endian.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/include/uapi/asm/swab.h linux-libre-4.7-gnu/arch/arc/include/uapi/asm/swab.h
--- linux-libre-4.6-gnu/arch/arc/include/uapi/asm/swab.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/include/uapi/asm/swab.h	2016-07-24 15:23:50.000000000 -0400
@@ -74,7 +74,7 @@
 	__tmp ^ __in;						\
 })
 
-#elif (ARC_BSWAP_TYPE == 2)	/* Custom single cycle bwap instruction */
+#elif (ARC_BSWAP_TYPE == 2)	/* Custom single cycle bswap instruction */
 
 #define __arch_swab32(x)						\
 ({									\
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/include/uapi/asm/unistd.h linux-libre-4.7-gnu/arch/arc/include/uapi/asm/unistd.h
--- linux-libre-4.6-gnu/arch/arc/include/uapi/asm/unistd.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/include/uapi/asm/unistd.h	2016-07-24 15:23:50.000000000 -0400
@@ -15,6 +15,7 @@
 #if !defined(_UAPI_ASM_ARC_UNISTD_H) || defined(__SYSCALL)
 #define _UAPI_ASM_ARC_UNISTD_H
 
+#define __ARCH_WANT_RENAMEAT
 #define __ARCH_WANT_SYS_EXECVE
 #define __ARCH_WANT_SYS_CLONE
 #define __ARCH_WANT_SYS_VFORK
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/Kconfig linux-libre-4.7-gnu/arch/arc/Kconfig
--- linux-libre-4.6-gnu/arch/arc/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -10,8 +10,9 @@ config ARC
 	def_bool y
 	select ARCH_SUPPORTS_ATOMIC_RMW if ARC_HAS_LLSC
 	select BUILDTIME_EXTABLE_SORT
-	select COMMON_CLK
+	select CLKSRC_OF
 	select CLONE_BACKWARDS
+	select COMMON_CLK
 	select GENERIC_ATOMIC64
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_FIND_FIRST_BIT
@@ -30,6 +31,7 @@ config ARC
 	select HAVE_MOD_ARCH_SPECIFIC if ARC_DW2_UNWIND
 	select HAVE_OPROFILE
 	select HAVE_PERF_EVENTS
+	select HANDLE_DOMAIN_IRQ
 	select IRQ_DOMAIN
 	select MODULES_USE_ELF_RELA
 	select NO_BOOTMEM
@@ -59,7 +61,7 @@ config RWSEM_GENERIC_SPINLOCK
 	def_bool y
 
 config ARCH_DISCONTIGMEM_ENABLE
-	def_bool y
+	def_bool n
 
 config ARCH_FLATMEM_ENABLE
 	def_bool y
@@ -95,6 +97,7 @@ source "arch/arc/plat-sim/Kconfig"
 source "arch/arc/plat-tb10x/Kconfig"
 source "arch/arc/plat-axs10x/Kconfig"
 #New platform adds here
+source "arch/arc/plat-eznps/Kconfig"
 
 endmenu
 
@@ -104,6 +107,7 @@ choice
 
 config ISA_ARCOMPACT
 	bool "ARCompact ISA"
+	select CPU_NO_EFFICIENT_FFS
 	help
 	  The original ARC ISA of ARC600/700 cores
 
@@ -182,9 +186,6 @@ if SMP
 config ARC_HAS_COH_CACHES
 	def_bool n
 
-config ARC_HAS_REENTRANT_IRQ_LV2
-	def_bool n
-
 config ARC_MCIP
 	bool "ARConnect Multicore IP (MCIP) Support "
 	depends on ISA_ARCV2
@@ -362,25 +363,10 @@ config NODES_SHIFT
 if ISA_ARCOMPACT
 
 config ARC_COMPACT_IRQ_LEVELS
-	bool "ARCompact IRQ Priorities: High(2)/Low(1)"
+	bool "Setup Timer IRQ as high Priority"
 	default n
-	# Timer HAS to be high priority, for any other high priority config
-	select ARC_IRQ3_LV2
 	# if SMP, LV2 enabled ONLY if ARC implementation has LV2 re-entrancy
-	depends on !SMP || ARC_HAS_REENTRANT_IRQ_LV2
-
-if ARC_COMPACT_IRQ_LEVELS
-
-config ARC_IRQ3_LV2
-	bool
-
-config ARC_IRQ5_LV2
-	bool
-
-config ARC_IRQ6_LV2
-	bool
-
-endif	#ARC_COMPACT_IRQ_LEVELS
+	depends on !SMP
 
 config ARC_FPU_SAVE_RESTORE
 	bool "Enable FPU state persistence across context switch"
@@ -403,11 +389,6 @@ config ARC_HAS_LLSC
 	default y
 	depends on !ARC_CANT_LLSC
 
-config ARC_STAR_9000923308
-	bool "Workaround for llock/scond livelock"
-	default n
-	depends on ISA_ARCV2 && SMP && ARC_HAS_LLSC
-
 config ARC_HAS_SWAPE
 	bool "Insn: SWAPE (endian-swap)"
 	default y
@@ -467,7 +448,7 @@ config LINUX_LINK_BASE
 
 config HIGHMEM
 	bool "High Memory Support"
-	select DISCONTIGMEM
+	select ARCH_DISCONTIGMEM_ENABLE
 	help
 	  With ARC 2G:2G address split, only upper 2G is directly addressable by
 	  kernel. Enable this to potentially allow access to rest of 2G and PAE
@@ -490,6 +471,17 @@ config ARCH_DMA_ADDR_T_64BIT
 config ARC_PLAT_NEEDS_PHYS_TO_DMA
 	bool
 
+config ARC_KVADDR_SIZE
+	int "Kernel Virtaul Address Space size (MB)"
+	range 0 512
+	default "256"
+	help
+	  The kernel address space is carved out of 256MB of translated address
+	  space for catering to vmalloc, modules, pkmap, fixmap. This however may
+	  not suffice vmalloc requirements of a 4K CPU EZChip system. So allow
+	  this to be stretched to 512 MB (by extending into the reserved
+	  kernel-user gutter)
+
 config ARC_CURR_IN_REG
 	bool "Dedicate Register r25 for current_task pointer"
 	default y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/kernel/clk.c linux-libre-4.7-gnu/arch/arc/kernel/clk.c
--- linux-libre-4.6-gnu/arch/arc/kernel/clk.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/kernel/clk.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2012 Synopsys, Inc. (www.synopsys.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <asm/clk.h>
-
-unsigned long core_freq = 80000000;
-
-/*
- * As of now we default to device-tree provided clock
- * In future we can determine this in early boot
- */
-int arc_set_core_freq(unsigned long freq)
-{
-	core_freq = freq;
-	return 0;
-}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/kernel/ctx_sw.c linux-libre-4.7-gnu/arch/arc/kernel/ctx_sw.c
--- linux-libre-4.6-gnu/arch/arc/kernel/ctx_sw.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/kernel/ctx_sw.c	2016-07-24 15:23:50.000000000 -0400
@@ -16,6 +16,9 @@
 
 #include <asm/asm-offsets.h>
 #include <linux/sched.h>
+#ifdef CONFIG_ARC_PLAT_EZNPS
+#include <plat/ctop.h>
+#endif
 
 #define KSP_WORD_OFF 	((TASK_THREAD + THREAD_KSP) / 4)
 
@@ -67,9 +70,16 @@ __switch_to(struct task_struct *prev_tas
 #ifndef CONFIG_SMP
 		"st  %2, [@_current_task]	\n\t"
 #else
+#ifdef CONFIG_ARC_PLAT_EZNPS
+		"lr   r24, [%4]		\n\t"
+#ifndef CONFIG_EZNPS_MTM_EXT
+		"lsr  r24, r24, 4		\n\t"
+#endif
+#else
 		"lr   r24, [identity]		\n\t"
 		"lsr  r24, r24, 8		\n\t"
 		"bmsk r24, r24, 7		\n\t"
+#endif
 		"add2 r24, @_current_task, r24	\n\t"
 		"st   %2,  [r24]		\n\t"
 #endif
@@ -107,6 +117,9 @@ __switch_to(struct task_struct *prev_tas
 
 		: "=r"(tmp)
 		: "n"(KSP_WORD_OFF), "r"(next), "r"(prev)
+#ifdef CONFIG_ARC_PLAT_EZNPS
+		, "i"(CTOP_AUX_LOGIC_GLOBAL_ID)
+#endif
 		: "blink"
 	);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/kernel/devtree.c linux-libre-4.7-gnu/arch/arc/kernel/devtree.c
--- linux-libre-4.6-gnu/arch/arc/kernel/devtree.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/kernel/devtree.c	2016-07-24 15:23:50.000000000 -0400
@@ -14,7 +14,6 @@
 #include <linux/memblock.h>
 #include <linux/of.h>
 #include <linux/of_fdt.h>
-#include <asm/clk.h>
 #include <asm/mach_desc.h>
 
 #ifdef CONFIG_SERIAL_EARLYCON
@@ -28,14 +27,12 @@ unsigned int __init arc_early_base_baud(
 
 static void __init arc_set_early_base_baud(unsigned long dt_root)
 {
-	unsigned int core_clk = arc_get_core_freq();
-
 	if (of_flat_dt_is_compatible(dt_root, "abilis,arc-tb10x"))
-		arc_base_baud = core_clk/3;
+		arc_base_baud = 166666666;	/* Fixed 166.6MHz clk (TB10x) */
 	else if (of_flat_dt_is_compatible(dt_root, "snps,arc-sdp"))
 		arc_base_baud = 33333333;	/* Fixed 33MHz clk (AXS10x) */
 	else
-		arc_base_baud = core_clk;
+		arc_base_baud = 50000000;	/* Fixed default 50MHz */
 }
 #else
 #define arc_set_early_base_baud(dt_root)
@@ -65,8 +62,6 @@ const struct machine_desc * __init setup
 {
 	const struct machine_desc *mdesc;
 	unsigned long dt_root;
-	const void *clk;
-	int len;
 
 	if (!early_init_dt_scan(dt))
 		return NULL;
@@ -76,10 +71,6 @@ const struct machine_desc * __init setup
 		machine_halt();
 
 	dt_root = of_get_flat_dt_root();
-	clk = of_get_flat_dt_prop(dt_root, "clock-frequency", &len);
-	if (clk)
-		arc_set_core_freq(of_read_ulong(clk, len/4));
-
 	arc_set_early_base_baud(dt_root);
 
 	return mdesc;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/kernel/entry-compact.S linux-libre-4.7-gnu/arch/arc/kernel/entry-compact.S
--- linux-libre-4.6-gnu/arch/arc/kernel/entry-compact.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/kernel/entry-compact.S	2016-07-24 15:23:50.000000000 -0400
@@ -91,27 +91,13 @@ VECTOR   mem_service             ; 0x8,
 VECTOR   instr_service           ; 0x10, Instrn Error   (0x2)
 
 ; ******************** Device ISRs **********************
-#ifdef CONFIG_ARC_IRQ3_LV2
-VECTOR   handle_interrupt_level2
-#else
-VECTOR   handle_interrupt_level1
-#endif
-
-VECTOR   handle_interrupt_level1
-
-#ifdef CONFIG_ARC_IRQ5_LV2
-VECTOR   handle_interrupt_level2
-#else
-VECTOR   handle_interrupt_level1
-#endif
-
-#ifdef CONFIG_ARC_IRQ6_LV2
+#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
 VECTOR   handle_interrupt_level2
 #else
 VECTOR   handle_interrupt_level1
 #endif
 
-.rept   25
+.rept   28
 VECTOR   handle_interrupt_level1 ; Other devices
 .endr
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/kernel/intc-arcv2.c linux-libre-4.7-gnu/arch/arc/kernel/intc-arcv2.c
--- linux-libre-4.6-gnu/arch/arc/kernel/intc-arcv2.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/kernel/intc-arcv2.c	2016-07-24 15:23:50.000000000 -0400
@@ -137,23 +137,30 @@ static const struct irq_domain_ops arcv2
 	.map = arcv2_irq_map,
 };
 
-static struct irq_domain *root_domain;
 
 static int __init
 init_onchip_IRQ(struct device_node *intc, struct device_node *parent)
 {
+	struct irq_domain *root_domain;
+
 	if (parent)
 		panic("DeviceTree incore intc not a root irq controller\n");
 
-	root_domain = irq_domain_add_legacy(intc, NR_CPU_IRQS, 0, 0,
-					    &arcv2_irq_ops, NULL);
-
+	root_domain = irq_domain_add_linear(intc, NR_CPU_IRQS, &arcv2_irq_ops, NULL);
 	if (!root_domain)
 		panic("root irq domain not avail\n");
 
-	/* with this we don't need to export root_domain */
+	/*
+	 * Needed for primary domain lookup to succeed
+	 * This is a primary irqchip, and can never have a parent
+	 */
 	irq_set_default_host(root_domain);
 
+#ifdef CONFIG_SMP
+	irq_create_mapping(root_domain, IPI_IRQ);
+#endif
+	irq_create_mapping(root_domain, SOFTIRQ_IRQ);
+
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/kernel/intc-compact.c linux-libre-4.7-gnu/arch/arc/kernel/intc-compact.c
--- linux-libre-4.6-gnu/arch/arc/kernel/intc-compact.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/kernel/intc-compact.c	2016-07-24 15:23:50.000000000 -0400
@@ -14,6 +14,8 @@
 #include <linux/irqchip.h>
 #include <asm/irq.h>
 
+#define TIMER0_IRQ	3	/* Fixed by ISA */
+
 /*
  * Early Hardware specific Interrupt setup
  * -Platform independent, needed for each CPU (not foldable into init_IRQ)
@@ -26,10 +28,8 @@ void arc_init_IRQ(void)
 {
 	int level_mask = 0;
 
-       /* setup any high priority Interrupts (Level2 in ARCompact jargon) */
-	level_mask |= IS_ENABLED(CONFIG_ARC_IRQ3_LV2) << 3;
-	level_mask |= IS_ENABLED(CONFIG_ARC_IRQ5_LV2) << 5;
-	level_mask |= IS_ENABLED(CONFIG_ARC_IRQ6_LV2) << 6;
+       /* Is timer high priority Interrupt (Level2 in ARCompact jargon) */
+	level_mask |= IS_ENABLED(CONFIG_ARC_COMPACT_IRQ_LEVELS) << TIMER0_IRQ;
 
 	/*
 	 * Write to register, even if no LV2 IRQs configured to reset it
@@ -79,8 +79,9 @@ static struct irq_chip onchip_intc = {
 static int arc_intc_domain_map(struct irq_domain *d, unsigned int irq,
 			       irq_hw_number_t hw)
 {
-	switch (irq) {
+	switch (hw) {
 	case TIMER0_IRQ:
+		irq_set_percpu_devid(irq);
 		irq_set_chip_and_handler(irq, &onchip_intc, handle_percpu_irq);
 		break;
 	default:
@@ -94,21 +95,23 @@ static const struct irq_domain_ops arc_i
 	.map = arc_intc_domain_map,
 };
 
-static struct irq_domain *root_domain;
-
 static int __init
 init_onchip_IRQ(struct device_node *intc, struct device_node *parent)
 {
+	struct irq_domain *root_domain;
+
 	if (parent)
 		panic("DeviceTree incore intc not a root irq controller\n");
 
-	root_domain = irq_domain_add_legacy(intc, NR_CPU_IRQS, 0, 0,
+	root_domain = irq_domain_add_linear(intc, NR_CPU_IRQS,
 					    &arc_intc_domain_ops, NULL);
-
 	if (!root_domain)
 		panic("root irq domain not avail\n");
 
-	/* with this we don't need to export root_domain */
+	/*
+	 * Needed for primary domain lookup to succeed
+	 * This is a primary irqchip, and can never have a parent
+	 */
 	irq_set_default_host(root_domain);
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/kernel/irq.c linux-libre-4.7-gnu/arch/arc/kernel/irq.c
--- linux-libre-4.6-gnu/arch/arc/kernel/irq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/kernel/irq.c	2016-07-24 15:23:50.000000000 -0400
@@ -41,53 +41,7 @@ void __init init_IRQ(void)
  * "C" Entry point for any ARC ISR, called from low level vector handler
  * @irq is the vector number read from ICAUSE reg of on-chip intc
  */
-void arch_do_IRQ(unsigned int irq, struct pt_regs *regs)
-{
-	struct pt_regs *old_regs = set_irq_regs(regs);
-
-	irq_enter();
-	generic_handle_irq(irq);
-	irq_exit();
-	set_irq_regs(old_regs);
-}
-
-/*
- * API called for requesting percpu interrupts - called by each CPU
- *  - For boot CPU, actually request the IRQ with genirq core + enables
- *  - For subsequent callers only enable called locally
- *
- * Relies on being called by boot cpu first (i.e. request called ahead) of
- * any enable as expected by genirq. Hence Suitable only for TIMER, IPI
- * which are guaranteed to be setup on boot core first.
- * Late probed peripherals such as perf can't use this as there no guarantee
- * of being called on boot CPU first.
- */
-
-void arc_request_percpu_irq(int irq, int cpu,
-                            irqreturn_t (*isr)(int irq, void *dev),
-                            const char *irq_nm,
-                            void *percpu_dev)
+void arch_do_IRQ(unsigned int hwirq, struct pt_regs *regs)
 {
-	/* Boot cpu calls request, all call enable */
-	if (!cpu) {
-		int rc;
-
-#ifdef CONFIG_ISA_ARCOMPACT
-		/*
-		 * A subsequent request_percpu_irq() fails if percpu_devid is
-		 * not set. That in turns sets NOAUTOEN, meaning each core needs
-		 * to call enable_percpu_irq()
-		 *
-		 * For ARCv2, this is done in irq map function since we know
-		 * which irqs are strictly per cpu
-		 */
-		irq_set_percpu_devid(irq);
-#endif
-
-		rc = request_percpu_irq(irq, isr, irq_nm, percpu_dev);
-		if (rc)
-			panic("Percpu IRQ request failed for %d\n", irq);
-	}
-
-	enable_percpu_irq(irq, 0);
+	handle_domain_irq(NULL, hwirq, regs);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/kernel/Makefile linux-libre-4.7-gnu/arch/arc/kernel/Makefile
--- linux-libre-4.6-gnu/arch/arc/kernel/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/kernel/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -9,7 +9,7 @@
 CFLAGS_ptrace.o		+= -DUTS_MACHINE='"$(UTS_MACHINE)"'
 
 obj-y	:= arcksyms.o setup.o irq.o time.o reset.o ptrace.o process.o devtree.o
-obj-y	+= signal.o traps.o sys.o troubleshoot.o stacktrace.o disasm.o clk.o
+obj-y	+= signal.o traps.o sys.o troubleshoot.o stacktrace.o disasm.o
 obj-$(CONFIG_ISA_ARCOMPACT)		+= entry-compact.o intc-compact.o
 obj-$(CONFIG_ISA_ARCV2)			+= entry-arcv2.o intc-arcv2.o
 obj-$(CONFIG_PCI)  			+= pcibios.o
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/kernel/mcip.c linux-libre-4.7-gnu/arch/arc/kernel/mcip.c
--- linux-libre-4.6-gnu/arch/arc/kernel/mcip.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/kernel/mcip.c	2016-07-24 15:23:50.000000000 -0400
@@ -15,9 +15,6 @@
 #include <asm/mcip.h>
 #include <asm/setup.h>
 
-#define IPI_IRQ		19
-#define SOFTIRQ_IRQ	21
-
 static char smp_cpuinfo_buf[128];
 static int idu_detected;
 
@@ -116,15 +113,13 @@ static void mcip_probe_n_setup(void)
 		IS_AVAIL1(mp.dbg, "DEBUG "),
 		IS_AVAIL1(mp.gfrc, "GFRC"));
 
+	cpuinfo_arc700[0].extn.gfrc = mp.gfrc;
 	idu_detected = mp.idu;
 
 	if (mp.dbg) {
 		__mcip_cmd_data(CMD_DEBUG_SET_SELECT, 0, 0xf);
 		__mcip_cmd_data(CMD_DEBUG_SET_MASK, 0xf, 0xf);
 	}
-
-	if (IS_ENABLED(CONFIG_ARC_HAS_GFRC) && !mp.gfrc)
-		panic("kernel trying to use non-existent GFRC\n");
 }
 
 struct plat_smp_ops plat_smp_ops = {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/kernel/perf_event.c linux-libre-4.7-gnu/arch/arc/kernel/perf_event.c
--- linux-libre-4.6-gnu/arch/arc/kernel/perf_event.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/kernel/perf_event.c	2016-07-24 15:23:50.000000000 -0400
@@ -48,7 +48,7 @@ struct arc_callchain_trace {
 static int callchain_trace(unsigned int addr, void *data)
 {
 	struct arc_callchain_trace *ctrl = data;
-	struct perf_callchain_entry *entry = ctrl->perf_stuff;
+	struct perf_callchain_entry_ctx *entry = ctrl->perf_stuff;
 	perf_callchain_store(entry, addr);
 
 	if (ctrl->depth++ < 3)
@@ -58,7 +58,7 @@ static int callchain_trace(unsigned int
 }
 
 void
-perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs)
+perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs)
 {
 	struct arc_callchain_trace ctrl = {
 		.depth = 0,
@@ -69,7 +69,7 @@ perf_callchain_kernel(struct perf_callch
 }
 
 void
-perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
+perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs)
 {
 	/*
 	 * User stack can't be unwound trivially with kernel dwarf unwinder
@@ -108,7 +108,7 @@ static void arc_perf_event_update(struct
 	int64_t delta = new_raw_count - prev_raw_count;
 
 	/*
-	 * We don't afaraid of hwc->prev_count changing beneath our feet
+	 * We aren't afraid of hwc->prev_count changing beneath our feet
 	 * because there's no way for us to re-enter this function anytime.
 	 */
 	local64_set(&hwc->prev_count, new_raw_count);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/kernel/process.c linux-libre-4.7-gnu/arch/arc/kernel/process.c
--- linux-libre-4.6-gnu/arch/arc/kernel/process.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/kernel/process.c	2016-07-24 15:23:50.000000000 -0400
@@ -183,13 +183,6 @@ void flush_thread(void)
 {
 }
 
-/*
- * Free any architecture-specific thread data structures, etc.
- */
-void exit_thread(void)
-{
-}
-
 int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
 {
 	return 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/kernel/setup.c linux-libre-4.7-gnu/arch/arc/kernel/setup.c
--- linux-libre-4.6-gnu/arch/arc/kernel/setup.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/kernel/setup.c	2016-07-24 15:23:50.000000000 -0400
@@ -13,7 +13,6 @@
 #include <linux/console.h>
 #include <linux/module.h>
 #include <linux/cpu.h>
-#include <linux/clk-provider.h>
 #include <linux/of_fdt.h>
 #include <linux/of_platform.h>
 #include <linux/cache.h>
@@ -24,7 +23,6 @@
 #include <asm/page.h>
 #include <asm/irq.h>
 #include <asm/unwind.h>
-#include <asm/clk.h>
 #include <asm/mach_desc.h>
 #include <asm/smp.h>
 
@@ -220,10 +218,6 @@ static char *arc_cpu_mumbojumbo(int cpu_
 	if (tbl->info.id == 0)
 		n += scnprintf(buf + n, len - n, "UNKNOWN ARC Processor\n");
 
-	n += scnprintf(buf + n, len - n, "CPU speed\t: %u.%02u Mhz\n",
-		       (unsigned int)(arc_get_core_freq() / 1000000),
-		       (unsigned int)(arc_get_core_freq() / 10000) % 100);
-
 	n += scnprintf(buf + n, len - n, "Timers\t\t: %s%s%s%s\nISA Extn\t: ",
 		       IS_AVAIL1(cpu->extn.timer0, "Timer0 "),
 		       IS_AVAIL1(cpu->extn.timer1, "Timer1 "),
@@ -314,9 +308,6 @@ static void arc_chk_core_config(void)
 	if (!cpu->extn.timer1)
 		panic("Timer1 is not present!\n");
 
-	if (IS_ENABLED(CONFIG_ARC_HAS_RTC) && !cpu->extn.rtc)
-		panic("RTC is not present\n");
-
 #ifdef CONFIG_ARC_HAS_DCCM
 	/*
 	 * DCCM can be arbit placed in hardware.
@@ -401,7 +392,7 @@ void __init setup_arch(char **cmdline_p)
 		/*
 		 * If we are here, it is established that @uboot_arg didn't
 		 * point to DT blob. Instead if u-boot says it is cmdline,
-		 * Appent to embedded DT cmdline.
+		 * append to embedded DT cmdline.
 		 * setup_machine_fdt() would have populated @boot_command_line
 		 */
 		if (uboot_tag == 1) {
@@ -444,7 +435,6 @@ void __init setup_arch(char **cmdline_p)
 
 static int __init customize_machine(void)
 {
-	of_clk_init(NULL);
 	/*
 	 * Traverses flattened DeviceTree - registering platform devices
 	 * (if any) complete with their resources
@@ -477,6 +467,8 @@ static int show_cpuinfo(struct seq_file
 {
 	char *str;
 	int cpu_id = ptr_to_cpu(v);
+	struct device_node *core_clk = of_find_node_by_name(NULL, "core_clk");
+	u32 freq = 0;
 
 	if (!cpu_online(cpu_id)) {
 		seq_printf(m, "processor [%d]\t: Offline\n", cpu_id);
@@ -489,6 +481,11 @@ static int show_cpuinfo(struct seq_file
 
 	seq_printf(m, arc_cpu_mumbojumbo(cpu_id, str, PAGE_SIZE));
 
+	of_property_read_u32(core_clk, "clock-frequency", &freq);
+	if (freq)
+		seq_printf(m, "CPU speed\t: %u.%02u Mhz\n",
+			   freq / 1000000, (freq / 10000) % 100);
+
 	seq_printf(m, "Bogo MIPS\t: %lu.%02lu\n",
 		   loops_per_jiffy / (500000 / HZ),
 		   (loops_per_jiffy / (5000 / HZ)) % 100);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/kernel/signal.c linux-libre-4.7-gnu/arch/arc/kernel/signal.c
--- linux-libre-4.6-gnu/arch/arc/kernel/signal.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/kernel/signal.c	2016-07-24 15:23:50.000000000 -0400
@@ -34,7 +34,7 @@
  *  -ViXS were still seeing crashes when using insmod to load drivers.
  *   It turned out that the code to change Execute permssions for TLB entries
  *   of user was not guarded for interrupts (mod_tlb_permission)
- *   This was cauing TLB entries to be overwritten on unrelated indexes
+ *   This was causing TLB entries to be overwritten on unrelated indexes
  *
  * Vineetg: July 15th 2008: Bug #94183
  *  -Exception happens in Delay slot of a JMP, and before user space resumes,
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/kernel/smp.c linux-libre-4.7-gnu/arch/arc/kernel/smp.c
--- linux-libre-4.6-gnu/arch/arc/kernel/smp.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/kernel/smp.c	2016-07-24 15:23:50.000000000 -0400
@@ -126,11 +126,6 @@ void start_kernel_secondary(void)
 	current->active_mm = mm;
 	cpumask_set_cpu(cpu, mm_cpumask(mm));
 
-	notify_cpu_starting(cpu);
-	set_cpu_online(cpu, true);
-
-	pr_info("## CPU%u LIVE ##: Executing Code...\n", cpu);
-
 	/* Some SMP H/w setup - for each cpu */
 	if (plat_smp_ops.init_per_cpu)
 		plat_smp_ops.init_per_cpu(cpu);
@@ -138,7 +133,10 @@ void start_kernel_secondary(void)
 	if (machine_desc->init_per_cpu)
 		machine_desc->init_per_cpu(cpu);
 
-	arc_local_timer_setup();
+	notify_cpu_starting(cpu);
+	set_cpu_online(cpu, true);
+
+	pr_info("## CPU%u LIVE ##: Executing Code...\n", cpu);
 
 	local_irq_enable();
 	preempt_disable();
@@ -346,6 +344,10 @@ irqreturn_t do_IPI(int irq, void *dev_id
 
 /*
  * API called by platform code to hookup arch-common ISR to their IPI IRQ
+ *
+ * Note: If IPI is provided by platform (vs. say ARC MCIP), their intc setup/map
+ * function needs to call call irq_set_percpu_devid() for IPI IRQ, otherwise
+ * request_percpu_irq() below will fail
  */
 static DEFINE_PER_CPU(int, ipi_dev);
 
@@ -353,7 +355,16 @@ int smp_ipi_irq_setup(int cpu, int irq)
 {
 	int *dev = per_cpu_ptr(&ipi_dev, cpu);
 
-	arc_request_percpu_irq(irq, cpu, do_IPI, "IPI Interrupt", dev);
+	/* Boot cpu calls request, all call enable */
+	if (!cpu) {
+		int rc;
+
+		rc = request_percpu_irq(irq, do_IPI, "IPI Interrupt", dev);
+		if (rc)
+			panic("Percpu IRQ request failed for %d\n", irq);
+	}
+
+	enable_percpu_irq(irq, 0);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/kernel/stacktrace.c linux-libre-4.7-gnu/arch/arc/kernel/stacktrace.c
--- linux-libre-4.6-gnu/arch/arc/kernel/stacktrace.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/kernel/stacktrace.c	2016-07-24 15:23:50.000000000 -0400
@@ -142,7 +142,7 @@ arc_unwind_core(struct task_struct *tsk,
 	 * prelogue is setup (callee regs saved and then fp set and not other
 	 * way around
 	 */
-	pr_warn("CONFIG_ARC_DW2_UNWIND needs to be enabled\n");
+	pr_warn_once("CONFIG_ARC_DW2_UNWIND needs to be enabled\n");
 	return 0;
 
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/kernel/time.c linux-libre-4.7-gnu/arch/arc/kernel/time.c
--- linux-libre-4.6-gnu/arch/arc/kernel/time.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/kernel/time.c	2016-07-24 15:23:50.000000000 -0400
@@ -29,21 +29,16 @@
  * which however is currently broken
  */
 
-#include <linux/spinlock.h>
 #include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/time.h>
-#include <linux/init.h>
-#include <linux/timex.h>
-#include <linux/profile.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
+#include <linux/cpu.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
 #include <asm/irq.h>
 #include <asm/arcregs.h>
-#include <asm/clk.h>
-#include <asm/mach_desc.h>
 
 #include <asm/mcip.h>
 
@@ -60,16 +55,35 @@
 
 #define ARC_TIMER_MAX	0xFFFFFFFF
 
-/********** Clock Source Device *********/
-
-#ifdef CONFIG_ARC_HAS_GFRC
+static unsigned long arc_timer_freq;
 
-static int arc_counter_setup(void)
+static int noinline arc_get_timer_clk(struct device_node *node)
 {
-	return 1;
+	struct clk *clk;
+	int ret;
+
+	clk = of_clk_get(node, 0);
+	if (IS_ERR(clk)) {
+		pr_err("timer missing clk");
+		return PTR_ERR(clk);
+	}
+
+	ret = clk_prepare_enable(clk);
+	if (ret) {
+		pr_err("Couldn't enable parent clk\n");
+		return ret;
+	}
+
+	arc_timer_freq = clk_get_rate(clk);
+
+	return 0;
 }
 
-static cycle_t arc_counter_read(struct clocksource *cs)
+/********** Clock Source Device *********/
+
+#ifdef CONFIG_ARC_HAS_GFRC
+
+static cycle_t arc_read_gfrc(struct clocksource *cs)
 {
 	unsigned long flags;
 	union {
@@ -94,15 +108,31 @@ static cycle_t arc_counter_read(struct c
 	return stamp.full;
 }
 
-static struct clocksource arc_counter = {
+static struct clocksource arc_counter_gfrc = {
 	.name   = "ARConnect GFRC",
 	.rating = 400,
-	.read   = arc_counter_read,
+	.read   = arc_read_gfrc,
 	.mask   = CLOCKSOURCE_MASK(64),
 	.flags  = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
-#else
+static void __init arc_cs_setup_gfrc(struct device_node *node)
+{
+	int exists = cpuinfo_arc700[0].extn.gfrc;
+	int ret;
+
+	if (WARN(!exists, "Global-64-bit-Ctr clocksource not detected"))
+		return;
+
+	ret = arc_get_timer_clk(node);
+	if (ret)
+		return;
+
+	clocksource_register_hz(&arc_counter_gfrc, arc_timer_freq);
+}
+CLOCKSOURCE_OF_DECLARE(arc_gfrc, "snps,archs-timer-gfrc", arc_cs_setup_gfrc);
+
+#endif
 
 #ifdef CONFIG_ARC_HAS_RTC
 
@@ -110,15 +140,7 @@ static struct clocksource arc_counter =
 #define AUX_RTC_LOW	0x104
 #define AUX_RTC_HIGH	0x105
 
-int arc_counter_setup(void)
-{
-	write_aux_reg(AUX_RTC_CTRL, 1);
-
-	/* Not usable in SMP */
-	return !IS_ENABLED(CONFIG_SMP);
-}
-
-static cycle_t arc_counter_read(struct clocksource *cs)
+static cycle_t arc_read_rtc(struct clocksource *cs)
 {
 	unsigned long status;
 	union {
@@ -142,47 +164,78 @@ static cycle_t arc_counter_read(struct c
 	return stamp.full;
 }
 
-static struct clocksource arc_counter = {
+static struct clocksource arc_counter_rtc = {
 	.name   = "ARCv2 RTC",
 	.rating = 350,
-	.read   = arc_counter_read,
+	.read   = arc_read_rtc,
 	.mask   = CLOCKSOURCE_MASK(64),
 	.flags  = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
-#else /* !CONFIG_ARC_HAS_RTC */
-
-/*
- * set 32bit TIMER1 to keep counting monotonically and wraparound
- */
-int arc_counter_setup(void)
+static void __init arc_cs_setup_rtc(struct device_node *node)
 {
-	write_aux_reg(ARC_REG_TIMER1_LIMIT, ARC_TIMER_MAX);
-	write_aux_reg(ARC_REG_TIMER1_CNT, 0);
-	write_aux_reg(ARC_REG_TIMER1_CTRL, TIMER_CTRL_NH);
+	int exists = cpuinfo_arc700[smp_processor_id()].extn.rtc;
+	int ret;
 
-	/* Not usable in SMP */
-	return !IS_ENABLED(CONFIG_SMP);
+	if (WARN(!exists, "Local-64-bit-Ctr clocksource not detected"))
+		return;
+
+	/* Local to CPU hence not usable in SMP */
+	if (WARN(IS_ENABLED(CONFIG_SMP), "Local-64-bit-Ctr not usable in SMP"))
+		return;
+
+	ret = arc_get_timer_clk(node);
+	if (ret)
+		return;
+
+	write_aux_reg(AUX_RTC_CTRL, 1);
+
+	clocksource_register_hz(&arc_counter_rtc, arc_timer_freq);
 }
+CLOCKSOURCE_OF_DECLARE(arc_rtc, "snps,archs-timer-rtc", arc_cs_setup_rtc);
 
-static cycle_t arc_counter_read(struct clocksource *cs)
+#endif
+
+/*
+ * 32bit TIMER1 to keep counting monotonically and wraparound
+ */
+
+static cycle_t arc_read_timer1(struct clocksource *cs)
 {
 	return (cycle_t) read_aux_reg(ARC_REG_TIMER1_CNT);
 }
 
-static struct clocksource arc_counter = {
+static struct clocksource arc_counter_timer1 = {
 	.name   = "ARC Timer1",
 	.rating = 300,
-	.read   = arc_counter_read,
+	.read   = arc_read_timer1,
 	.mask   = CLOCKSOURCE_MASK(32),
 	.flags  = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
-#endif
-#endif
+static void __init arc_cs_setup_timer1(struct device_node *node)
+{
+	int ret;
+
+	/* Local to CPU hence not usable in SMP */
+	if (IS_ENABLED(CONFIG_SMP))
+		return;
+
+	ret = arc_get_timer_clk(node);
+	if (ret)
+		return;
+
+	write_aux_reg(ARC_REG_TIMER1_LIMIT, ARC_TIMER_MAX);
+	write_aux_reg(ARC_REG_TIMER1_CNT, 0);
+	write_aux_reg(ARC_REG_TIMER1_CTRL, TIMER_CTRL_NH);
+
+	clocksource_register_hz(&arc_counter_timer1, arc_timer_freq);
+}
 
 /********** Clock Event Device *********/
 
+static int arc_timer_irq;
+
 /*
  * Arm the timer to interrupt after @cycles
  * The distinction for oneshot/periodic is done in arc_event_timer_ack() below
@@ -209,7 +262,7 @@ static int arc_clkevent_set_periodic(str
 	 * At X Hz, 1 sec = 1000ms -> X cycles;
 	 *		      10ms -> X / 100 cycles
 	 */
-	arc_timer_event_setup(arc_get_core_freq() / HZ);
+	arc_timer_event_setup(arc_timer_freq / HZ);
 	return 0;
 }
 
@@ -218,7 +271,6 @@ static DEFINE_PER_CPU(struct clock_event
 	.features		= CLOCK_EVT_FEAT_ONESHOT |
 				  CLOCK_EVT_FEAT_PERIODIC,
 	.rating			= 300,
-	.irq			= TIMER0_IRQ,	/* hardwired, no need for resources */
 	.set_next_event		= arc_clkevent_set_next_event,
 	.set_state_periodic	= arc_clkevent_set_periodic,
 };
@@ -244,45 +296,81 @@ static irqreturn_t timer_irq_handler(int
 	return IRQ_HANDLED;
 }
 
+static int arc_timer_cpu_notify(struct notifier_block *self,
+				unsigned long action, void *hcpu)
+{
+	struct clock_event_device *evt = this_cpu_ptr(&arc_clockevent_device);
+
+	evt->cpumask = cpumask_of(smp_processor_id());
+
+	switch (action & ~CPU_TASKS_FROZEN) {
+	case CPU_STARTING:
+		clockevents_config_and_register(evt, arc_timer_freq,
+						0, ULONG_MAX);
+		enable_percpu_irq(arc_timer_irq, 0);
+		break;
+	case CPU_DYING:
+		disable_percpu_irq(arc_timer_irq);
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block arc_timer_cpu_nb = {
+	.notifier_call = arc_timer_cpu_notify,
+};
+
 /*
- * Setup the local event timer for @cpu
+ * clockevent setup for boot CPU
  */
-void arc_local_timer_setup()
+static void __init arc_clockevent_setup(struct device_node *node)
 {
 	struct clock_event_device *evt = this_cpu_ptr(&arc_clockevent_device);
-	int cpu = smp_processor_id();
+	int ret;
 
-	evt->cpumask = cpumask_of(cpu);
-	clockevents_config_and_register(evt, arc_get_core_freq(),
+	register_cpu_notifier(&arc_timer_cpu_nb);
+
+	arc_timer_irq = irq_of_parse_and_map(node, 0);
+	if (arc_timer_irq <= 0)
+		panic("clockevent: missing irq");
+
+	ret = arc_get_timer_clk(node);
+	if (ret)
+		panic("clockevent: missing clk");
+
+	evt->irq = arc_timer_irq;
+	evt->cpumask = cpumask_of(smp_processor_id());
+	clockevents_config_and_register(evt, arc_timer_freq,
 					0, ARC_TIMER_MAX);
 
-	/* setup the per-cpu timer IRQ handler - for all cpus */
-	arc_request_percpu_irq(TIMER0_IRQ, cpu, timer_irq_handler,
-			       "Timer0 (per-cpu-tick)", evt);
+	/* Needs apriori irq_set_percpu_devid() done in intc map function */
+	ret = request_percpu_irq(arc_timer_irq, timer_irq_handler,
+				 "Timer0 (per-cpu-tick)", evt);
+	if (ret)
+		panic("clockevent: unable to request irq\n");
+
+	enable_percpu_irq(arc_timer_irq, 0);
 }
 
+static void __init arc_of_timer_init(struct device_node *np)
+{
+	static int init_count = 0;
+
+	if (!init_count) {
+		init_count = 1;
+		arc_clockevent_setup(np);
+	} else {
+		arc_cs_setup_timer1(np);
+	}
+}
+CLOCKSOURCE_OF_DECLARE(arc_clkevt, "snps,arc-timer", arc_of_timer_init);
+
 /*
  * Called from start_kernel() - boot CPU only
- *
- * -Sets up h/w timers as applicable on boot cpu
- * -Also sets up any global state needed for timer subsystem:
- *    - for "counting" timer, registers a clocksource, usable across CPUs
- *      (provided that underlying counter h/w is synchronized across cores)
- *    - for "event" timer, sets up TIMER0 IRQ (as that is platform agnostic)
  */
 void __init time_init(void)
 {
-	/*
-	 * sets up the timekeeping free-flowing counter which also returns
-	 * whether the counter is usable as clocksource
-	 */
-	if (arc_counter_setup())
-		/*
-		 * CLK upto 4.29 GHz can be safely represented in 32 bits
-		 * because Max 32 bit number is 4,294,967,295
-		 */
-		clocksource_register_hz(&arc_counter, arc_get_core_freq());
-
-	/* sets up the periodic event timer */
-	arc_local_timer_setup();
+	of_clk_init(NULL);
+	clocksource_probe();
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/kernel/troubleshoot.c linux-libre-4.7-gnu/arch/arc/kernel/troubleshoot.c
--- linux-libre-4.6-gnu/arch/arc/kernel/troubleshoot.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/kernel/troubleshoot.c	2016-07-24 15:23:50.000000000 -0400
@@ -276,7 +276,7 @@ static int tlb_stats_open(struct inode *
 	return 0;
 }
 
-/* called on user read(): display the couters */
+/* called on user read(): display the counters */
 static ssize_t tlb_stats_output(struct file *file,	/* file descriptor */
 				char __user *user_buf,	/* user buffer */
 				size_t len,		/* length of buffer */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/Makefile linux-libre-4.7-gnu/arch/arc/Makefile
--- linux-libre-4.6-gnu/arch/arc/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -66,8 +66,6 @@ endif
 
 endif
 
-cflags-$(CONFIG_ARC_DW2_UNWIND)		+= -fasynchronous-unwind-tables
-
 # By default gcc 4.8 generates dwarf4 which kernel unwinder can't grok
 ifeq ($(atleast_gcc48),y)
 cflags-$(CONFIG_ARC_DW2_UNWIND)		+= -gdwarf-2
@@ -115,6 +113,11 @@ core-y		+= arch/arc/boot/dts/
 core-$(CONFIG_ARC_PLAT_SIM)	+= arch/arc/plat-sim/
 core-$(CONFIG_ARC_PLAT_TB10X)	+= arch/arc/plat-tb10x/
 core-$(CONFIG_ARC_PLAT_AXS10X)	+= arch/arc/plat-axs10x/
+core-$(CONFIG_ARC_PLAT_EZNPS)	+= arch/arc/plat-eznps/
+
+ifdef CONFIG_ARC_PLAT_EZNPS
+KBUILD_CPPFLAGS += -I$(srctree)/arch/arc/plat-eznps/include
+endif
 
 drivers-$(CONFIG_OPROFILE)	+= arch/arc/oprofile/
 
@@ -122,7 +125,7 @@ libs-y		+= arch/arc/lib/ $(LIBGCC)
 
 boot		:= arch/arc/boot
 
-#default target for make without any arguements.
+#default target for make without any arguments.
 KBUILD_IMAGE	:= bootpImage
 
 all:	$(KBUILD_IMAGE)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/mm/cache.c linux-libre-4.7-gnu/arch/arc/mm/cache.c
--- linux-libre-4.6-gnu/arch/arc/mm/cache.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/mm/cache.c	2016-07-24 15:23:50.000000000 -0400
@@ -215,7 +215,7 @@ slc_chk:
  * ------------------
  * This ver of MMU supports variable page sizes (1k-16k): although Linux will
  * only support 8k (default), 16k and 4k.
- * However from hardware perspective, smaller page sizes aggrevate aliasing
+ * However from hardware perspective, smaller page sizes aggravate aliasing
  * meaning more vaddr bits needed to disambiguate the cache-line-op ;
  * the existing scheme of piggybacking won't work for certain configurations.
  * Two new registers IC_PTAG and DC_PTAG inttoduced.
@@ -302,7 +302,7 @@ void __cache_line_loop_v3(phys_addr_t pa
 
 	/*
 	 * This is technically for MMU v4, using the MMU v3 programming model
-	 * Special work for HS38 aliasing I-cache configuratino with PAE40
+	 * Special work for HS38 aliasing I-cache configuration with PAE40
 	 *   - upper 8 bits of paddr need to be written into PTAG_HI
 	 *   - (and needs to be written before the lower 32 bits)
 	 * Note that PTAG_HI is hoisted outside the line loop
@@ -936,7 +936,7 @@ void arc_cache_init(void)
 			      ic->ver, CONFIG_ARC_MMU_VER);
 
 		/*
-		 * In MMU v4 (HS38x) the alising icache config uses IVIL/PTAG
+		 * In MMU v4 (HS38x) the aliasing icache config uses IVIL/PTAG
 		 * pair to provide vaddr/paddr respectively, just as in MMU v3
 		 */
 		if (is_isa_arcv2() && ic->alias)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/mm/dma.c linux-libre-4.7-gnu/arch/arc/mm/dma.c
--- linux-libre-4.6-gnu/arch/arc/mm/dma.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/mm/dma.c	2016-07-24 15:23:50.000000000 -0400
@@ -10,7 +10,7 @@
  * DMA Coherent API Notes
  *
  * I/O is inherently non-coherent on ARC. So a coherent DMA buffer is
- * implemented by accessintg it using a kernel virtual address, with
+ * implemented by accessing it using a kernel virtual address, with
  * Cache bit off in the TLB entry.
  *
  * The default DMA address == Phy address which is 0x8000_0000 based.
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/mm/tlb.c linux-libre-4.7-gnu/arch/arc/mm/tlb.c
--- linux-libre-4.6-gnu/arch/arc/mm/tlb.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/mm/tlb.c	2016-07-24 15:23:50.000000000 -0400
@@ -814,6 +814,17 @@ void arc_mmu_init(void)
 
 	printk(arc_mmu_mumbojumbo(0, str, sizeof(str)));
 
+	/*
+	 * Can't be done in processor.h due to header include depenedencies
+	 */
+	BUILD_BUG_ON(!IS_ALIGNED((CONFIG_ARC_KVADDR_SIZE << 20), PMD_SIZE));
+
+	/*
+	 * stack top size sanity check,
+	 * Can't be done in processor.h due to header include depenedencies
+	 */
+	BUILD_BUG_ON(!IS_ALIGNED(STACK_TOP, PMD_SIZE));
+
 	/* For efficiency sake, kernel is compile time built for a MMU ver
 	 * This must match the hardware it is running on.
 	 * Linux built for MMU V2, if run on MMU V1 will break down because V1
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/plat-axs10x/axs10x.c linux-libre-4.7-gnu/arch/arc/plat-axs10x/axs10x.c
--- linux-libre-4.6-gnu/arch/arc/plat-axs10x/axs10x.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/plat-axs10x/axs10x.c	2016-07-24 15:23:50.000000000 -0400
@@ -14,10 +14,11 @@
  *
  */
 
+#include <linux/of_fdt.h>
 #include <linux/of_platform.h>
+#include <linux/libfdt.h>
 
 #include <asm/asm-offsets.h>
-#include <asm/clk.h>
 #include <asm/io.h>
 #include <asm/mach_desc.h>
 #include <asm/mcip.h>
@@ -389,6 +390,13 @@ axs103_set_freq(unsigned int id, unsigne
 
 static void __init axs103_early_init(void)
 {
+	int offset = fdt_path_offset(initial_boot_params, "/cpu_card/core_clk");
+	const struct fdt_property *prop = fdt_get_property(initial_boot_params,
+							   offset,
+							   "clock-frequency",
+							   NULL);
+	u32 freq = be32_to_cpu(*(u32*)(prop->data)) / 1000000, orig = freq;
+
 	/*
 	 * AXS103 configurations for SMP/QUAD configurations share device tree
 	 * which defaults to 90 MHz. However recent failures of Quad config
@@ -401,12 +409,10 @@ static void __init axs103_early_init(voi
 #ifdef CONFIG_ARC_MCIP
 	unsigned int num_cores = (read_aux_reg(ARC_REG_MCIP_BCR) >> 16) & 0x3F;
 	if (num_cores > 2)
-		arc_set_core_freq(50 * 1000000);
-	else if (num_cores == 2)
-		arc_set_core_freq(75 * 1000000);
+		freq = 50;
 #endif
 
-	switch (arc_get_core_freq()/1000000) {
+	switch (freq) {
 	case 33:
 		axs103_set_freq(1, 1, 1);
 		break;
@@ -431,11 +437,18 @@ static void __init axs103_early_init(voi
 		 * DT "clock-frequency" might not match with board value.
 		 * Hence update it to match the board value.
 		 */
-		arc_set_core_freq(axs103_get_freq() * 1000000);
+		freq = axs103_get_freq();
 		break;
 	}
 
-	pr_info("Freq is %dMHz\n", axs103_get_freq());
+	pr_info("Freq is %dMHz\n", freq);
+
+	/* Patching .dtb in-place with new core clock value */
+	if (freq != orig ) {
+		freq = cpu_to_be32(freq * 1000000);
+		fdt_setprop_inplace(initial_boot_params, offset,
+				    "clock-frequency", &freq, sizeof(freq));
+	}
 
 	/* Memory maps already config in pre-bootloader */
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/plat-axs10x/Kconfig linux-libre-4.7-gnu/arch/arc/plat-axs10x/Kconfig
--- linux-libre-4.6-gnu/arch/arc/plat-axs10x/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/plat-axs10x/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -13,7 +13,7 @@ menuconfig ARC_PLAT_AXS10X
 	select OF_GPIO
 	select MIGHT_HAVE_PCI
 	select GENERIC_IRQ_CHIP
-	select ARCH_REQUIRE_GPIOLIB
+	select GPIOLIB
 	help
 	  Support for the ARC AXS10x Software Development Platforms.
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/plat-eznps/entry.S linux-libre-4.7-gnu/arch/arc/plat-eznps/entry.S
--- linux-libre-4.6-gnu/arch/arc/plat-eznps/entry.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arc/plat-eznps/entry.S	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,70 @@
+/*******************************************************************************
+
+  EZNPS CPU startup Code
+  Copyright(c) 2012 EZchip Technologies.
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms and conditions of the GNU General Public License,
+  version 2, as published by the Free Software Foundation.
+
+  This program is distributed in the hope 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.
+
+  The full GNU General Public License is included in this distribution in
+  the file called "COPYING".
+
+*******************************************************************************/
+#include <linux/linkage.h>
+#include <asm/entry.h>
+#include <asm/cache.h>
+#include <plat/ctop.h>
+
+	.cpu A7
+
+	.section .init.text, "ax",@progbits
+	.align 1024	; HW requierment for restart first PC
+
+ENTRY(res_service)
+#ifdef CONFIG_EZNPS_MTM_EXT
+	; There is no work for HW thread id != 0
+	lr	r3, [CTOP_AUX_THREAD_ID]
+	cmp	r3, 0
+	jne	stext
+#endif
+
+#ifdef CONFIG_ARC_HAS_DCACHE
+	; With no cache coherency mechanism D$ need to be used very carefully.
+	; Address space:
+	; 0G-2G: We disable CONFIG_ARC_CACHE_PAGES.
+	; 2G-3G: We disable D$ by setting this bit.
+	; 3G-4G: D$ is disabled by architecture.
+	; FMT are huge pages for user application reside at 0-2G.
+	; Only FMT left as one who can use D$ where each such page got
+	; disable/enable bit for cachability.
+	; Programmer will use FMT pages for private data so cache coherency
+	; would not be a problem.
+	; First thing we invalidate D$
+	sr	1, [ARC_REG_DC_IVDC]
+	sr	HW_COMPLY_KRN_NOT_D_CACHED, [CTOP_AUX_HW_COMPLY]
+#endif
+
+#ifdef CONFIG_SMP
+	; We set logical cpuid to be used by GET_CPUID
+	; We do not use physical cpuid since we want ids to be continious when
+	; it comes to cpus on the same quad cluster.
+	; This is useful for applications that used shared resources of a quad
+	; cluster such SRAMS.
+	lr 	r3, [CTOP_AUX_CORE_ID]
+	sr	r3, [CTOP_AUX_LOGIC_CORE_ID]
+	lr	r3, [CTOP_AUX_CLUSTER_ID]
+	; Set logical is acheived by swap of 2 middle bits of cluster id (4 bit)
+	; r3 is used since we use short instruction and we need q-class reg
+	.short	CTOP_INST_MOV2B_FLIP_R3_B1_B2_INST
+	.word 	CTOP_INST_MOV2B_FLIP_R3_B1_B2_LIMM
+	 sr	r3, [CTOP_AUX_LOGIC_CLUSTER_ID]
+#endif
+
+	j	stext
+END(res_service)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/plat-eznps/include/plat/ctop.h linux-libre-4.7-gnu/arch/arc/plat-eznps/include/plat/ctop.h
--- linux-libre-4.6-gnu/arch/arc/plat-eznps/include/plat/ctop.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arc/plat-eznps/include/plat/ctop.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,209 @@
+/*
+ * Copyright(c) 2015 EZchip Technologies.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ */
+
+#ifndef _PLAT_EZNPS_CTOP_H
+#define _PLAT_EZNPS_CTOP_H
+
+#ifndef CONFIG_ARC_PLAT_EZNPS
+#error "Incorrect ctop.h include"
+#endif
+
+#include <soc/nps/common.h>
+
+/* core auxiliary registers */
+#ifdef __ASSEMBLY__
+#define CTOP_AUX_BASE				(-0x800)
+#else
+#define CTOP_AUX_BASE				0xFFFFF800
+#endif
+
+#define CTOP_AUX_GLOBAL_ID			(CTOP_AUX_BASE + 0x000)
+#define CTOP_AUX_CLUSTER_ID			(CTOP_AUX_BASE + 0x004)
+#define CTOP_AUX_CORE_ID			(CTOP_AUX_BASE + 0x008)
+#define CTOP_AUX_THREAD_ID			(CTOP_AUX_BASE + 0x00C)
+#define CTOP_AUX_LOGIC_GLOBAL_ID		(CTOP_AUX_BASE + 0x010)
+#define CTOP_AUX_LOGIC_CLUSTER_ID		(CTOP_AUX_BASE + 0x014)
+#define CTOP_AUX_LOGIC_CORE_ID			(CTOP_AUX_BASE + 0x018)
+#define CTOP_AUX_MT_CTRL			(CTOP_AUX_BASE + 0x020)
+#define CTOP_AUX_HW_COMPLY			(CTOP_AUX_BASE + 0x024)
+#define CTOP_AUX_LPC				(CTOP_AUX_BASE + 0x030)
+#define CTOP_AUX_EFLAGS				(CTOP_AUX_BASE + 0x080)
+#define CTOP_AUX_IACK				(CTOP_AUX_BASE + 0x088)
+#define CTOP_AUX_GPA1				(CTOP_AUX_BASE + 0x08C)
+#define CTOP_AUX_UDMC				(CTOP_AUX_BASE + 0x300)
+
+/* EZchip core instructions */
+#define CTOP_INST_HWSCHD_OFF_R3			0x3B6F00BF
+#define CTOP_INST_HWSCHD_OFF_R4			0x3C6F00BF
+#define CTOP_INST_HWSCHD_RESTORE_R3		0x3E6F70C3
+#define CTOP_INST_HWSCHD_RESTORE_R4		0x3E6F7103
+#define CTOP_INST_SCHD_RW			0x3E6F7004
+#define CTOP_INST_SCHD_RD			0x3E6F7084
+#define CTOP_INST_ASRI_0_R3			0x3B56003E
+#define CTOP_INST_XEX_DI_R2_R2_R3		0x4A664C00
+#define CTOP_INST_EXC_DI_R2_R2_R3		0x4A664C01
+#define CTOP_INST_AADD_DI_R2_R2_R3		0x4A664C02
+#define CTOP_INST_AAND_DI_R2_R2_R3		0x4A664C04
+#define CTOP_INST_AOR_DI_R2_R2_R3		0x4A664C05
+#define CTOP_INST_AXOR_DI_R2_R2_R3		0x4A664C06
+
+/* Do not use D$ for address in 2G-3G */
+#define HW_COMPLY_KRN_NOT_D_CACHED		_BITUL(28)
+
+#define NPS_MSU_EN_CFG				0x80
+#define NPS_CRG_BLKID				0x480
+#define NPS_CRG_SYNC_BIT			_BITUL(0)
+#define NPS_GIM_BLKID				0x5C0
+
+/* GIM registers and fields*/
+#define NPS_GIM_UART_LINE			_BITUL(7)
+#define NPS_GIM_DBG_LAN_EAST_TX_DONE_LINE	_BITUL(10)
+#define NPS_GIM_DBG_LAN_EAST_RX_RDY_LINE	_BITUL(11)
+#define NPS_GIM_DBG_LAN_WEST_TX_DONE_LINE	_BITUL(25)
+#define NPS_GIM_DBG_LAN_WEST_RX_RDY_LINE	_BITUL(26)
+
+#ifndef __ASSEMBLY__
+/* Functional registers definition */
+struct nps_host_reg_mtm_cfg {
+	union {
+		struct {
+			u32 gen:1, gdis:1, clk_gate_dis:1, asb:1,
+			__reserved:9, nat:3, ten:16;
+		};
+		u32 value;
+	};
+};
+
+struct nps_host_reg_mtm_cpu_cfg {
+	union {
+		struct {
+			u32 csa:22, dmsid:6, __reserved:3, cs:1;
+		};
+		u32 value;
+	};
+};
+
+struct nps_host_reg_thr_init {
+	union {
+		struct {
+			u32 str:1, __reserved:27, thr_id:4;
+		};
+		u32 value;
+	};
+};
+
+struct nps_host_reg_thr_init_sts {
+	union {
+		struct {
+			u32 bsy:1, err:1, __reserved:26, thr_id:4;
+		};
+		u32 value;
+	};
+};
+
+struct nps_host_reg_msu_en_cfg {
+	union {
+		struct {
+			u32     __reserved1:11,
+			rtc_en:1, ipc_en:1, gim_1_en:1,
+			gim_0_en:1, ipi_en:1, buff_e_rls_bmuw:1,
+			buff_e_alc_bmuw:1, buff_i_rls_bmuw:1, buff_i_alc_bmuw:1,
+			buff_e_rls_bmue:1, buff_e_alc_bmue:1, buff_i_rls_bmue:1,
+			buff_i_alc_bmue:1, __reserved2:1, buff_e_pre_en:1,
+			buff_i_pre_en:1, pmuw_ja_en:1, pmue_ja_en:1,
+			pmuw_nj_en:1, pmue_nj_en:1, msu_en:1;
+		};
+		u32 value;
+	};
+};
+
+struct nps_host_reg_gim_p_int_dst {
+	union {
+		struct {
+			u32 int_out_en:1, __reserved1:4,
+			is:1, intm:2, __reserved2:4,
+			nid:4, __reserved3:4, cid:4,
+			 __reserved4:4, tid:4;
+		};
+		u32 value;
+	};
+};
+
+/* AUX registers definition */
+struct nps_host_reg_aux_udmc {
+	union {
+		struct {
+			u32 dcp:1, cme:1, __reserved:19, nat:3,
+			__reserved2:5, dcas:3;
+		};
+		u32 value;
+	};
+};
+
+struct nps_host_reg_aux_mt_ctrl {
+	union {
+		struct {
+			u32 mten:1, hsen:1, scd:1, sten:1,
+			st_cnt:8, __reserved:8,
+			hs_cnt:8, __reserved1:4;
+		};
+		u32 value;
+	};
+};
+
+struct nps_host_reg_aux_hw_comply {
+	union {
+		struct {
+			u32 me:1, le:1, te:1, knc:1, __reserved:28;
+		};
+		u32 value;
+	};
+};
+
+struct nps_host_reg_aux_lpc {
+	union {
+		struct {
+			u32 mep:1, __reserved:31;
+		};
+		u32 value;
+	};
+};
+
+/* CRG registers */
+#define REG_GEN_PURP_0          nps_host_reg_non_cl(NPS_CRG_BLKID, 0x1BF)
+
+/* GIM registers */
+#define REG_GIM_P_INT_EN_0      nps_host_reg_non_cl(NPS_GIM_BLKID, 0x100)
+#define REG_GIM_P_INT_POL_0     nps_host_reg_non_cl(NPS_GIM_BLKID, 0x110)
+#define REG_GIM_P_INT_SENS_0    nps_host_reg_non_cl(NPS_GIM_BLKID, 0x114)
+#define REG_GIM_P_INT_BLK_0     nps_host_reg_non_cl(NPS_GIM_BLKID, 0x118)
+#define REG_GIM_P_INT_DST_10    nps_host_reg_non_cl(NPS_GIM_BLKID, 0x13A)
+#define REG_GIM_P_INT_DST_11    nps_host_reg_non_cl(NPS_GIM_BLKID, 0x13B)
+#define REG_GIM_P_INT_DST_25    nps_host_reg_non_cl(NPS_GIM_BLKID, 0x149)
+#define REG_GIM_P_INT_DST_26    nps_host_reg_non_cl(NPS_GIM_BLKID, 0x14A)
+
+#else
+
+.macro  GET_CPU_ID  reg
+	lr  \reg, [CTOP_AUX_LOGIC_GLOBAL_ID]
+#ifndef CONFIG_EZNPS_MTM_EXT
+	lsr \reg, \reg, 4
+#endif
+.endm
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _PLAT_EZNPS_CTOP_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/plat-eznps/include/plat/mtm.h linux-libre-4.7-gnu/arch/arc/plat-eznps/include/plat/mtm.h
--- linux-libre-4.6-gnu/arch/arc/plat-eznps/include/plat/mtm.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arc/plat-eznps/include/plat/mtm.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,60 @@
+/*
+ * Copyright(c) 2015 EZchip Technologies.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ */
+
+#ifndef _PLAT_EZNPS_MTM_H
+#define _PLAT_EZNPS_MTM_H
+
+#include <plat/ctop.h>
+
+static inline void *nps_mtm_reg_addr(u32 cpu, u32 reg)
+{
+	struct global_id gid;
+	u32 core, blkid;
+
+	gid.value = cpu;
+	core = gid.core;
+	blkid = (((core & 0x0C) << 2) | (core & 0x03));
+
+	return nps_host_reg(cpu, blkid, reg);
+}
+
+#ifdef CONFIG_EZNPS_MTM_EXT
+#define NPS_CPU_TO_THREAD_NUM(cpu) \
+	({ struct global_id gid; gid.value = cpu; gid.thread; })
+
+/* MTM registers */
+#define MTM_CFG(cpu)			nps_mtm_reg_addr(cpu, 0x81)
+#define MTM_THR_INIT(cpu)		nps_mtm_reg_addr(cpu, 0x92)
+#define MTM_THR_INIT_STS(cpu)		nps_mtm_reg_addr(cpu, 0x93)
+
+#define get_thread(map) map.thread
+#define eznps_max_cpus 4096
+#define eznps_cpus_per_cluster	256
+
+void mtm_enable_core(unsigned int cpu);
+int mtm_enable_thread(int cpu);
+#else /* !CONFIG_EZNPS_MTM_EXT */
+
+#define get_thread(map) 0
+#define eznps_max_cpus 256
+#define eznps_cpus_per_cluster	16
+#define mtm_enable_core(cpu)
+#define mtm_enable_thread(cpu) 1
+#define NPS_CPU_TO_THREAD_NUM(cpu) 0
+
+#endif /* CONFIG_EZNPS_MTM_EXT */
+
+#endif /* _PLAT_EZNPS_MTM_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/plat-eznps/include/plat/smp.h linux-libre-4.7-gnu/arch/arc/plat-eznps/include/plat/smp.h
--- linux-libre-4.6-gnu/arch/arc/plat-eznps/include/plat/smp.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arc/plat-eznps/include/plat/smp.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,26 @@
+/*
+ * Copyright(c) 2015 EZchip Technologies.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ */
+
+#ifndef __PLAT_EZNPS_SMP_H
+#define __PLAT_EZNPS_SMP_H
+
+#ifdef CONFIG_SMP
+
+extern void res_service(void);
+
+#endif /* CONFIG_SMP */
+
+#endif
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/plat-eznps/Kconfig linux-libre-4.7-gnu/arch/arc/plat-eznps/Kconfig
--- linux-libre-4.6-gnu/arch/arc/plat-eznps/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arc/plat-eznps/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,35 @@
+#
+# For a description of the syntax of this configuration file,
+# see Documentation/kbuild/kconfig-language.txt.
+#
+
+menuconfig ARC_PLAT_EZNPS
+	bool "\"EZchip\" ARC dev platform"
+	select ARC_HAS_COH_CACHES if SMP
+	select CPU_BIG_ENDIAN
+	select CLKSRC_NPS
+	select EZNPS_GIC
+	select EZCHIP_NPS_MANAGEMENT_ENET if ETHERNET
+	help
+	  Support for EZchip development platforms,
+	  based on ARC700 cores.
+	  We handle few flavours:
+	    - Hardware Emulator AKA HE which is FPGA based chasis
+	    - Simulator based on MetaWare nSIM
+	    - NPS400 chip based on ASIC
+
+config EZNPS_MTM_EXT
+	bool "ARC-EZchip MTM Extensions"
+	select CPUMASK_OFFSTACK
+	depends on ARC_PLAT_EZNPS && SMP
+	default y
+	help
+	  Here we add new hierarchy for CPUs topology.
+	  We got:
+		Core
+		Thread
+	  At the new thread level each CPU represent one HW thread.
+	  At highest hierarchy each core contain 16 threads,
+	  any of them seem like CPU from Linux point of view.
+	  All threads within same core share the execution unit of the
+	  core and HW scheduler round robin between them.
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/plat-eznps/Makefile linux-libre-4.7-gnu/arch/arc/plat-eznps/Makefile
--- linux-libre-4.6-gnu/arch/arc/plat-eznps/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arc/plat-eznps/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,7 @@
+#
+# Makefile for the linux kernel.
+#
+
+obj-y := entry.o platform.o
+obj-$(CONFIG_SMP) += smp.o
+obj-$(CONFIG_EZNPS_MTM_EXT) += mtm.o
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/plat-eznps/mtm.c linux-libre-4.7-gnu/arch/arc/plat-eznps/mtm.c
--- linux-libre-4.6-gnu/arch/arc/plat-eznps/mtm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arc/plat-eznps/mtm.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,133 @@
+/*
+ * Copyright(c) 2015 EZchip Technologies.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ */
+
+#include <linux/smp.h>
+#include <linux/io.h>
+#include <linux/log2.h>
+#include <asm/arcregs.h>
+#include <plat/mtm.h>
+#include <plat/smp.h>
+
+#define MT_CTRL_HS_CNT		0xFF
+#define MT_CTRL_ST_CNT		0xF
+#define NPS_NUM_HW_THREADS	0x10
+
+static void mtm_init_nat(int cpu)
+{
+	struct nps_host_reg_mtm_cfg mtm_cfg;
+	struct nps_host_reg_aux_udmc udmc;
+	int log_nat, nat = 0, i, t;
+
+	/* Iterate core threads and update nat */
+	for (i = 0, t = cpu; i < NPS_NUM_HW_THREADS; i++, t++)
+		nat += test_bit(t, cpumask_bits(cpu_possible_mask));
+
+	log_nat = ilog2(nat);
+
+	udmc.value = read_aux_reg(CTOP_AUX_UDMC);
+	udmc.nat = log_nat;
+	write_aux_reg(CTOP_AUX_UDMC, udmc.value);
+
+	mtm_cfg.value = ioread32be(MTM_CFG(cpu));
+	mtm_cfg.nat = log_nat;
+	iowrite32be(mtm_cfg.value, MTM_CFG(cpu));
+}
+
+static void mtm_init_thread(int cpu)
+{
+	int i, tries = 5;
+	struct nps_host_reg_thr_init thr_init;
+	struct nps_host_reg_thr_init_sts thr_init_sts;
+
+	/* Set thread init register */
+	thr_init.value = 0;
+	iowrite32be(thr_init.value, MTM_THR_INIT(cpu));
+	thr_init.thr_id = NPS_CPU_TO_THREAD_NUM(cpu);
+	thr_init.str = 1;
+	iowrite32be(thr_init.value, MTM_THR_INIT(cpu));
+
+	/* Poll till thread init is done */
+	for (i = 0; i < tries; i++) {
+		thr_init_sts.value = ioread32be(MTM_THR_INIT_STS(cpu));
+		if (thr_init_sts.thr_id == thr_init.thr_id) {
+			if (thr_init_sts.bsy)
+				continue;
+			else if (thr_init_sts.err)
+				pr_warn("Failed to thread init cpu %u\n", cpu);
+			break;
+		}
+
+		pr_warn("Wrong thread id in thread init for cpu %u\n", cpu);
+		break;
+	}
+
+	if (i == tries)
+		pr_warn("Got thread init timeout for cpu %u\n", cpu);
+}
+
+int mtm_enable_thread(int cpu)
+{
+	struct nps_host_reg_mtm_cfg mtm_cfg;
+
+	if (NPS_CPU_TO_THREAD_NUM(cpu) == 0)
+		return 1;
+
+	/* Enable thread in mtm */
+	mtm_cfg.value = ioread32be(MTM_CFG(cpu));
+	mtm_cfg.ten |= (1 << (NPS_CPU_TO_THREAD_NUM(cpu)));
+	iowrite32be(mtm_cfg.value, MTM_CFG(cpu));
+
+	return 0;
+}
+
+void mtm_enable_core(unsigned int cpu)
+{
+	int i;
+	struct nps_host_reg_aux_mt_ctrl mt_ctrl;
+	struct nps_host_reg_mtm_cfg mtm_cfg;
+
+	if (NPS_CPU_TO_THREAD_NUM(cpu) != 0)
+		return;
+
+	/* Initialize Number of Active Threads */
+	mtm_init_nat(cpu);
+
+	/* Initialize mtm_cfg */
+	mtm_cfg.value = ioread32be(MTM_CFG(cpu));
+	mtm_cfg.ten = 1;
+	iowrite32be(mtm_cfg.value, MTM_CFG(cpu));
+
+	/* Initialize all other threads in core */
+	for (i = 1; i < NPS_NUM_HW_THREADS; i++)
+		mtm_init_thread(cpu + i);
+
+
+	/* Enable HW schedule, stall counter, mtm */
+	mt_ctrl.value = 0;
+	mt_ctrl.hsen = 1;
+	mt_ctrl.hs_cnt = MT_CTRL_HS_CNT;
+	mt_ctrl.sten = 1;
+	mt_ctrl.st_cnt = MT_CTRL_ST_CNT;
+	mt_ctrl.mten = 1;
+	write_aux_reg(CTOP_AUX_MT_CTRL, mt_ctrl.value);
+
+	/*
+	 * HW scheduling mechanism will start working
+	 * Only after call to instruction "schd.rw".
+	 * cpu_relax() calls "schd.rw" instruction.
+	 */
+	cpu_relax();
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/plat-eznps/platform.c linux-libre-4.7-gnu/arch/arc/plat-eznps/platform.c
--- linux-libre-4.6-gnu/arch/arc/plat-eznps/platform.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arc/plat-eznps/platform.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,102 @@
+/*
+ * Copyright(c) 2015 EZchip Technologies.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <asm/mach_desc.h>
+#include <plat/mtm.h>
+
+static void __init eznps_configure_msu(void)
+{
+	int cpu;
+	struct nps_host_reg_msu_en_cfg msu_en_cfg = {.value = 0};
+
+	msu_en_cfg.msu_en = 1;
+	msu_en_cfg.ipi_en = 1;
+	msu_en_cfg.gim_0_en = 1;
+	msu_en_cfg.gim_1_en = 1;
+
+	/* enable IPI and GIM messages on all clusters */
+	for (cpu = 0 ; cpu < eznps_max_cpus; cpu += eznps_cpus_per_cluster)
+		iowrite32be(msu_en_cfg.value,
+			    nps_host_reg(cpu, NPS_MSU_BLKID, NPS_MSU_EN_CFG));
+}
+
+static void __init eznps_configure_gim(void)
+{
+	u32 reg_value;
+	u32 gim_int_lines;
+	struct nps_host_reg_gim_p_int_dst gim_p_int_dst = {.value = 0};
+
+	gim_int_lines = NPS_GIM_UART_LINE;
+	gim_int_lines |= NPS_GIM_DBG_LAN_EAST_TX_DONE_LINE;
+	gim_int_lines |= NPS_GIM_DBG_LAN_EAST_RX_RDY_LINE;
+	gim_int_lines |= NPS_GIM_DBG_LAN_WEST_TX_DONE_LINE;
+	gim_int_lines |= NPS_GIM_DBG_LAN_WEST_RX_RDY_LINE;
+
+	/*
+	 * IRQ polarity
+	 * low or high level
+	 * negative or positive edge
+	 */
+	reg_value = ioread32be(REG_GIM_P_INT_POL_0);
+	reg_value &= ~gim_int_lines;
+	iowrite32be(reg_value, REG_GIM_P_INT_POL_0);
+
+	/* IRQ type level or edge */
+	reg_value = ioread32be(REG_GIM_P_INT_SENS_0);
+	reg_value |= NPS_GIM_DBG_LAN_EAST_TX_DONE_LINE;
+	reg_value |= NPS_GIM_DBG_LAN_WEST_TX_DONE_LINE;
+	iowrite32be(reg_value, REG_GIM_P_INT_SENS_0);
+
+	/*
+	 * GIM interrupt select type for
+	 * dbg_lan TX and RX interrupts
+	 * should be type 1
+	 * type 0 = IRQ line 6
+	 * type 1 = IRQ line 7
+	 */
+	gim_p_int_dst.is = 1;
+	iowrite32be(gim_p_int_dst.value, REG_GIM_P_INT_DST_10);
+	iowrite32be(gim_p_int_dst.value, REG_GIM_P_INT_DST_11);
+	iowrite32be(gim_p_int_dst.value, REG_GIM_P_INT_DST_25);
+	iowrite32be(gim_p_int_dst.value, REG_GIM_P_INT_DST_26);
+
+	/*
+	 * CTOP IRQ lines should be defined
+	 * as blocking in GIM
+	*/
+	iowrite32be(gim_int_lines, REG_GIM_P_INT_BLK_0);
+
+	/* enable CTOP IRQ lines in GIM */
+	iowrite32be(gim_int_lines, REG_GIM_P_INT_EN_0);
+}
+
+static void __init eznps_early_init(void)
+{
+	eznps_configure_msu();
+	eznps_configure_gim();
+}
+
+static const char *eznps_compat[] __initconst = {
+	"ezchip,arc-nps",
+	NULL,
+};
+
+MACHINE_START(NPS, "nps")
+	.dt_compat	= eznps_compat,
+	.init_early	= eznps_early_init,
+MACHINE_END
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/plat-eznps/smp.c linux-libre-4.7-gnu/arch/arc/plat-eznps/smp.c
--- linux-libre-4.6-gnu/arch/arc/plat-eznps/smp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arc/plat-eznps/smp.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,155 @@
+/*
+ * Copyright(c) 2015 EZchip Technologies.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ */
+
+#include <linux/smp.h>
+#include <linux/of_fdt.h>
+#include <linux/io.h>
+#include <linux/irqdomain.h>
+#include <asm/irq.h>
+#include <plat/ctop.h>
+#include <plat/smp.h>
+#include <plat/mtm.h>
+
+#define NPS_DEFAULT_MSID	0x34
+#define NPS_MTM_CPU_CFG		0x90
+
+static char smp_cpuinfo_buf[128] = {"Extn [EZNPS-SMP]\t: On\n"};
+
+/* Get cpu map from device tree */
+static int __init eznps_get_map(const char *name, struct cpumask *cpumask)
+{
+	unsigned long dt_root = of_get_flat_dt_root();
+	const char *buf;
+
+	buf = of_get_flat_dt_prop(dt_root, name, NULL);
+	if (!buf)
+		return 1;
+
+	cpulist_parse(buf, cpumask);
+
+	return 0;
+}
+
+/* Update board cpu maps */
+static void __init eznps_init_cpumasks(void)
+{
+	struct cpumask cpumask;
+
+	if (eznps_get_map("present-cpus", &cpumask)) {
+		pr_err("Failed to get present-cpus from dtb");
+		return;
+	}
+	init_cpu_present(&cpumask);
+
+	if (eznps_get_map("possible-cpus", &cpumask)) {
+		pr_err("Failed to get possible-cpus from dtb");
+		return;
+	}
+	init_cpu_possible(&cpumask);
+}
+
+static void eznps_init_core(unsigned int cpu)
+{
+	u32 sync_value;
+	struct nps_host_reg_aux_hw_comply hw_comply;
+	struct nps_host_reg_aux_lpc lpc;
+
+	if (NPS_CPU_TO_THREAD_NUM(cpu) != 0)
+		return;
+
+	hw_comply.value = read_aux_reg(CTOP_AUX_HW_COMPLY);
+	hw_comply.me  = 1;
+	hw_comply.le  = 1;
+	hw_comply.te  = 1;
+	write_aux_reg(CTOP_AUX_HW_COMPLY, hw_comply.value);
+
+	/* Enable MMU clock */
+	lpc.mep = 1;
+	write_aux_reg(CTOP_AUX_LPC, lpc.value);
+
+	/* Boot CPU only */
+	if (!cpu) {
+		/* Write to general purpose register in CRG */
+		sync_value = ioread32be(REG_GEN_PURP_0);
+		sync_value |= NPS_CRG_SYNC_BIT;
+		iowrite32be(sync_value, REG_GEN_PURP_0);
+	}
+}
+
+/*
+ * Master kick starting another CPU
+ */
+static void __init eznps_smp_wakeup_cpu(int cpu, unsigned long pc)
+{
+	struct nps_host_reg_mtm_cpu_cfg cpu_cfg;
+
+	if (mtm_enable_thread(cpu) == 0)
+		return;
+
+	/* set PC, dmsid, and start CPU */
+	cpu_cfg.value = (u32)res_service;
+	cpu_cfg.dmsid = NPS_DEFAULT_MSID;
+	cpu_cfg.cs = 1;
+	iowrite32be(cpu_cfg.value, nps_mtm_reg_addr(cpu, NPS_MTM_CPU_CFG));
+}
+
+static void eznps_ipi_send(int cpu)
+{
+	struct global_id gid;
+	struct {
+		union {
+			struct {
+				u32 num:8, cluster:8, core:8, thread:8;
+			};
+			u32 value;
+		};
+	} ipi;
+
+	gid.value = cpu;
+	ipi.thread = get_thread(gid);
+	ipi.core = gid.core;
+	ipi.cluster = nps_cluster_logic_to_phys(gid.cluster);
+	ipi.num = NPS_IPI_IRQ;
+
+	__asm__ __volatile__(
+	"	mov r3, %0\n"
+	"	.word %1\n"
+	:
+	: "r"(ipi.value), "i"(CTOP_INST_ASRI_0_R3)
+	: "r3");
+}
+
+static void eznps_init_per_cpu(int cpu)
+{
+	smp_ipi_irq_setup(cpu, NPS_IPI_IRQ);
+
+	eznps_init_core(cpu);
+	mtm_enable_core(cpu);
+}
+
+static void eznps_ipi_clear(int irq)
+{
+	write_aux_reg(CTOP_AUX_IACK, 1 << irq);
+}
+
+struct plat_smp_ops plat_smp_ops = {
+	.info		= smp_cpuinfo_buf,
+	.init_early_smp	= eznps_init_cpumasks,
+	.cpu_kick	= eznps_smp_wakeup_cpu,
+	.ipi_send	= eznps_ipi_send,
+	.init_per_cpu	= eznps_init_per_cpu,
+	.ipi_clear	= eznps_ipi_clear,
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arc/plat-tb10x/Kconfig linux-libre-4.7-gnu/arch/arc/plat-tb10x/Kconfig
--- linux-libre-4.6-gnu/arch/arc/plat-tb10x/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arc/plat-tb10x/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -21,7 +21,7 @@ menuconfig ARC_PLAT_TB10X
 	select PINCTRL
 	select PINCTRL_TB10X
 	select PINMUX
-	select ARCH_REQUIRE_GPIOLIB
+	select GPIOLIB
 	select GPIO_TB10X
 	select TB10X_IRQC
 	help
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/bootp/Makefile linux-libre-4.7-gnu/arch/arm/boot/bootp/Makefile
--- linux-libre-4.6-gnu/arch/arm/boot/bootp/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/bootp/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -17,7 +17,6 @@ targets	:= bootp init.o kernel.o initrd.
 # Note that bootp.lds picks up kernel.o and initrd.o
 $(obj)/bootp:	$(src)/bootp.lds $(addprefix $(obj)/,init.o kernel.o initrd.o) FORCE
 	$(call if_changed,ld)
-	@:
 
 # kernel.o and initrd.o includes a binary image using
 # .incbin, a dependency which is not tracked automatically
@@ -26,4 +25,4 @@ $(obj)/kernel.o: arch/arm/boot/zImage FO
 
 $(obj)/initrd.o: $(INITRD) FORCE
 
-PHONY += $(INITRD) FORCE
+PHONY += $(INITRD)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/am335x-baltos.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/am335x-baltos.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/am335x-baltos.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/am335x-baltos.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,408 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * VScom OnRISC
+ * http://www.vscom.de
+ */
+
+#include "am33xx.dtsi"
+#include <dt-bindings/pwm/pwm.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	compatible = "vscom,onrisc", "ti,am33xx";
+
+	cpus {
+		cpu@0 {
+			cpu0-supply = <&vdd1_reg>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x10000000>; /* 256 MB */
+	};
+
+	vbat: fixedregulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "vbat";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-boot-on;
+	};
+
+	wl12xx_vmmc: fixedregulator@2 {
+		pinctrl-names = "default";
+		pinctrl-0 = <&wl12xx_gpio>;
+		compatible = "regulator-fixed";
+		regulator-name = "vwl1271";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		gpio = <&gpio3 8 0>;
+		startup-delay-us = <70000>;
+		enable-active-high;
+	};
+};
+
+&am33xx_pinmux {
+	mmc2_pins: pinmux_mmc2_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x820, PIN_INPUT_PULLUP | MUX_MODE2)      /* gpmc_ad8.mmc1_dat0_mux0 */
+			AM33XX_IOPAD(0x824, PIN_INPUT_PULLUP | MUX_MODE2)      /* gpmc_ad9.mmc1_dat1_mux0 */
+			AM33XX_IOPAD(0x828, PIN_INPUT_PULLUP | MUX_MODE2)      /* gpmc_ad10.mmc1_dat2_mux0 */
+			AM33XX_IOPAD(0x82c, PIN_INPUT_PULLUP | MUX_MODE2)      /* gpmc_ad11.mmc1_dat3_mux0 */
+			AM33XX_IOPAD(0x880, PIN_INPUT_PULLUP | MUX_MODE2)      /* gpmc_csn1.mmc1_clk_mux0 */
+			AM33XX_IOPAD(0x884, PIN_INPUT_PULLUP | MUX_MODE2)      /* gpmc_csn2.mmc1_cmd_mux0 */
+			AM33XX_IOPAD(0x9e4, PIN_INPUT_PULLUP | MUX_MODE7)      /* emu0.gpio3[7] */
+		>;
+	};
+
+	wl12xx_gpio: pinmux_wl12xx_gpio {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x9e8, PIN_OUTPUT_PULLUP | MUX_MODE7)      /* emu1.gpio3[8] */
+		>;
+	};
+
+	tps65910_pins: pinmux_tps65910_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x878, PIN_INPUT_PULLUP | MUX_MODE7)      /* gpmc_ben1.gpio1[28] */
+		>;
+	};
+
+	i2c1_pins: pinmux_i2c1_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x958, PIN_INPUT | MUX_MODE2)      /* spi0_d1.i2c1_sda_mux3 */
+			AM33XX_IOPAD(0x95c, PIN_INPUT | MUX_MODE2)      /* spi0_cs0.i2c1_scl_mux3 */
+		>;
+	};
+
+	uart0_pins: pinmux_uart0_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0)	/* uart0_rxd.uart0_rxd */
+			AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0)		/* uart0_txd.uart0_txd */
+		>;
+	};
+
+	cpsw_default: cpsw_default {
+		pinctrl-single,pins = <
+			/* Slave 1 */
+			AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE1)       /* mii1_crs.rmii1_crs_dv */
+			AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE1)      /* mii1_tx_en.rmii1_txen */
+			AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE1)      /* mii1_txd1.rmii1_txd1 */
+			AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE1)      /* mii1_txd0.rmii1_txd0 */
+			AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE1)      /* mii1_rxd1.rmii1_rxd1 */
+			AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE1)      /* mii1_rxd0.rmii1_rxd0 */
+			AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE0)      /* rmii1_ref_clk.rmii1_refclk */
+
+
+			/* Slave 2 */
+			AM33XX_IOPAD(0x840, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a0.rgmii2_tctl */
+			AM33XX_IOPAD(0x844, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a1.rgmii2_rctl */
+			AM33XX_IOPAD(0x848, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a2.rgmii2_td3 */
+			AM33XX_IOPAD(0x84c, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a3.rgmii2_td2 */
+			AM33XX_IOPAD(0x850, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a4.rgmii2_td1 */
+			AM33XX_IOPAD(0x854, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a5.rgmii2_td0 */
+			AM33XX_IOPAD(0x858, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a6.rgmii2_tclk */
+			AM33XX_IOPAD(0x85c, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a7.rgmii2_rclk */
+			AM33XX_IOPAD(0x860, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a8.rgmii2_rd3 */
+			AM33XX_IOPAD(0x864, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a9.rgmii2_rd2 */
+			AM33XX_IOPAD(0x868, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a10.rgmii2_rd1 */
+			AM33XX_IOPAD(0x86c, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a11.rgmii2_rd0 */
+		>;
+	};
+
+	cpsw_sleep: cpsw_sleep {
+		pinctrl-single,pins = <
+			/* Slave 1 reset value */
+			AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE7)
+
+			/* Slave 2 reset value*/
+			AM33XX_IOPAD(0x840, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x844, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x848, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x84c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x850, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x854, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x858, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x85c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x860, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x864, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x868, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x86c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	davinci_mdio_default: davinci_mdio_default {
+		pinctrl-single,pins = <
+			/* MDIO */
+			AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)	/* mdio_data.mdio_data */
+			AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0)			/* mdio_clk.mdio_clk */
+		>;
+	};
+
+	davinci_mdio_sleep: davinci_mdio_sleep {
+		pinctrl-single,pins = <
+			/* MDIO reset value */
+			AM33XX_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	nandflash_pins_s0: nandflash_pins_s0 {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad0.gpmc_ad0 */
+			AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad1.gpmc_ad1 */
+			AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad2.gpmc_ad2 */
+			AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad3.gpmc_ad3 */
+			AM33XX_IOPAD(0x810, PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad4.gpmc_ad4 */
+			AM33XX_IOPAD(0x814, PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad5.gpmc_ad5 */
+			AM33XX_IOPAD(0x818, PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad6.gpmc_ad6 */
+			AM33XX_IOPAD(0x81c, PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad7.gpmc_ad7 */
+			AM33XX_IOPAD(0x870, PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_wait0.gpmc_wait0 */
+			AM33XX_IOPAD(0x874, PIN_INPUT_PULLUP | MUX_MODE7)	/* gpmc_wpn.gpio0_30 */
+			AM33XX_IOPAD(0x87c, PIN_OUTPUT | MUX_MODE0)		/* gpmc_csn0.gpmc_csn0  */
+			AM33XX_IOPAD(0x890, PIN_OUTPUT | MUX_MODE0)		/* gpmc_advn_ale.gpmc_advn_ale */
+			AM33XX_IOPAD(0x894, PIN_OUTPUT | MUX_MODE0)		/* gpmc_oen_ren.gpmc_oen_ren */
+			AM33XX_IOPAD(0x898, PIN_OUTPUT | MUX_MODE0)		/* gpmc_wen.gpmc_wen */
+			AM33XX_IOPAD(0x89c, PIN_OUTPUT | MUX_MODE0)		/* gpmc_be0n_cle.gpmc_be0n_cle */
+		>;
+	};
+};
+
+&elm {
+	status = "okay";
+};
+
+&gpmc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&nandflash_pins_s0>;
+	ranges = <0 0 0x08000000 0x10000000>;	/* CS0: NAND */
+	status = "okay";
+
+	nand@0,0 {
+		compatible = "ti,omap2-nand";
+		reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
+		interrupt-parent = <&gpmc>;
+		interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
+			     <1 IRQ_TYPE_NONE>;	/* termcount */
+		rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */
+		nand-bus-width = <8>;
+		ti,nand-ecc-opt = "bch8";
+		ti,nand-xfer-type = "polled";
+
+		gpmc,device-nand = "true";
+		gpmc,device-width = <1>;
+		gpmc,sync-clk-ps = <0>;
+		gpmc,cs-on-ns = <0>;
+		gpmc,cs-rd-off-ns = <44>;
+		gpmc,cs-wr-off-ns = <44>;
+		gpmc,adv-on-ns = <6>;
+		gpmc,adv-rd-off-ns = <34>;
+		gpmc,adv-wr-off-ns = <44>;
+		gpmc,we-on-ns = <0>;
+		gpmc,we-off-ns = <40>;
+		gpmc,oe-on-ns = <0>;
+		gpmc,oe-off-ns = <54>;
+		gpmc,access-ns = <64>;
+		gpmc,rd-cycle-ns = <82>;
+		gpmc,wr-cycle-ns = <82>;
+		gpmc,bus-turnaround-ns = <0>;
+		gpmc,cycle2cycle-delay-ns = <0>;
+		gpmc,clk-activation-ns = <0>;
+		gpmc,wr-access-ns = <40>;
+		gpmc,wr-data-mux-bus-ns = <0>;
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+		elm_id = <&elm>;
+	};
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins>;
+
+	status = "okay";
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
+
+	status = "okay";
+	clock-frequency = <400000>;
+
+	tps: tps@2d {
+		reg = <0x2d>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <28 GPIO_ACTIVE_LOW>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&tps65910_pins>;
+	};
+
+	at24@50 {
+		compatible = "at24,24c02";
+		pagesize = <8>;
+		reg = <0x50>;
+	};
+};
+
+&usb {
+	status = "okay";
+};
+
+&usb_ctrl_mod {
+	status = "okay";
+};
+
+&cppi41dma  {
+	status = "okay";
+};
+
+#include "tps65910.dtsi"
+
+&tps {
+	vcc1-supply = <&vbat>;
+	vcc2-supply = <&vbat>;
+	vcc3-supply = <&vbat>;
+	vcc4-supply = <&vbat>;
+	vcc5-supply = <&vbat>;
+	vcc6-supply = <&vbat>;
+	vcc7-supply = <&vbat>;
+	vccio-supply = <&vbat>;
+
+	ti,en-ck32k-xtal = <1>;
+
+	regulators {
+		vrtc_reg: regulator@0 {
+			regulator-always-on;
+		};
+
+		vio_reg: regulator@1 {
+			regulator-always-on;
+		};
+
+		vdd1_reg: regulator@2 {
+			/* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
+			regulator-name = "vdd_mpu";
+			regulator-min-microvolt = <912500>;
+			regulator-max-microvolt = <1312500>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		vdd2_reg: regulator@3 {
+			/* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
+			regulator-name = "vdd_core";
+			regulator-min-microvolt = <912500>;
+			regulator-max-microvolt = <1150000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		vdd3_reg: regulator@4 {
+			regulator-always-on;
+		};
+
+		vdig1_reg: regulator@5 {
+			regulator-always-on;
+		};
+
+		vdig2_reg: regulator@6 {
+			regulator-always-on;
+		};
+
+		vpll_reg: regulator@7 {
+			regulator-always-on;
+		};
+
+		vdac_reg: regulator@8 {
+			regulator-always-on;
+		};
+
+		vaux1_reg: regulator@9 {
+			regulator-always-on;
+		};
+
+		vaux2_reg: regulator@10 {
+			regulator-always-on;
+		};
+
+		vaux33_reg: regulator@11 {
+			regulator-always-on;
+		};
+
+		vmmc_reg: regulator@12 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+	};
+};
+
+&mac {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&cpsw_default>;
+	pinctrl-1 = <&cpsw_sleep>;
+	dual_emac = <1>;
+
+	status = "okay";
+};
+
+&davinci_mdio {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&davinci_mdio_default>;
+	pinctrl-1 = <&davinci_mdio_sleep>;
+
+	status = "okay";
+};
+
+&mmc1 {
+	vmmc-supply = <&vmmc_reg>;
+	status = "okay";
+};
+
+&mmc2 {
+	status = "okay";
+	vmmc-supply = <&wl12xx_vmmc>;
+	ti,non-removable;
+	bus-width = <4>;
+	cap-power-off-card;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc2_pins>;
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+	wlcore: wlcore@2 {
+		compatible = "ti,wl1835";
+		reg = <2>;
+		interrupt-parent = <&gpio3>;
+		interrupts = <7 IRQ_TYPE_LEVEL_HIGH>;
+	};
+};
+
+&sham {
+	status = "okay";
+};
+
+&aes {
+	status = "okay";
+};
+
+&gpio0 {
+	ti,no-reset-on-init;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/am335x-baltos-ir2110.dts linux-libre-4.7-gnu/arch/arm/boot/dts/am335x-baltos-ir2110.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/am335x-baltos-ir2110.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/am335x-baltos-ir2110.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * VScom OnRISC
+ * http://www.vscom.de
+ */
+
+/dts-v1/;
+
+#include "am335x-baltos.dtsi"
+
+/ {
+	model = "OnRISC Baltos iR 2110";
+};
+
+&am33xx_pinmux {
+	uart1_pins: pinmux_uart1_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x980, PIN_INPUT | MUX_MODE0)      /* uart1_rxd */
+			AM33XX_IOPAD(0x984, PIN_INPUT | MUX_MODE0)      /* uart1_txd */
+			AM33XX_IOPAD(0x978, PIN_INPUT_PULLDOWN | MUX_MODE0)      /* uart1_ctsn */
+			AM33XX_IOPAD(0x97c, PIN_OUTPUT_PULLDOWN | MUX_MODE0)      /* uart1_rtsn */
+			AM33XX_IOPAD(0x8e0, PIN_OUTPUT_PULLDOWN | MUX_MODE7)      /* lcd_vsync.gpio2[22] DTR */
+			AM33XX_IOPAD(0x8e4, PIN_INPUT_PULLDOWN | MUX_MODE7)      /* lcd_hsync.gpio2[23] DSR */
+			AM33XX_IOPAD(0x8e8, PIN_INPUT_PULLDOWN | MUX_MODE7)      /* lcd_pclk.gpio2[24] DCD */
+			AM33XX_IOPAD(0x8ec, PIN_INPUT_PULLDOWN | MUX_MODE7)      /* lcd_ac_bias_en.gpio2[25] RI */
+		>;
+	};
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_pins>;
+	dtr-gpios = <&gpio2 22 GPIO_ACTIVE_LOW>;
+	dsr-gpios = <&gpio2 23 GPIO_ACTIVE_LOW>;
+	dcd-gpios = <&gpio2 24 GPIO_ACTIVE_LOW>;
+	rng-gpios = <&gpio2 25 GPIO_ACTIVE_LOW>;
+
+	status = "okay";
+};
+
+&usb0_phy {
+	status = "okay";
+};
+
+&usb0 {
+	status = "okay";
+	dr_mode = "host";
+};
+
+&cpsw_emac0 {
+	phy_id = <&davinci_mdio>, <1>;
+	phy-mode = "rmii";
+	dual_emac_res_vlan = <1>;
+};
+
+&cpsw_emac1 {
+	phy_id = <&davinci_mdio>, <7>;
+	phy-mode = "rgmii-txid";
+	dual_emac_res_vlan = <2>;
+};
+
+&phy_sel {
+	rmii-clock-ext = <1>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/am335x-baltos-ir3220.dts linux-libre-4.7-gnu/arch/arm/boot/dts/am335x-baltos-ir3220.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/am335x-baltos-ir3220.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/am335x-baltos-ir3220.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * VScom OnRISC
+ * http://www.vscom.de
+ */
+
+/dts-v1/;
+
+#include "am335x-baltos.dtsi"
+
+/ {
+	model = "OnRISC Baltos iR 3220";
+};
+
+&am33xx_pinmux {
+	tca6416_pins: pinmux_tca6416_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x9b4, PIN_INPUT_PULLUP | MUX_MODE7)      /* xdma_event_intr1.gpio0[20] tca6416 stuff */
+		>;
+	};
+
+	uart1_pins: pinmux_uart1_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x980, PIN_INPUT | MUX_MODE0)      /* uart1_rxd */
+			AM33XX_IOPAD(0x984, PIN_INPUT | MUX_MODE0)      /* uart1_txd */
+			AM33XX_IOPAD(0x978, PIN_INPUT_PULLDOWN | MUX_MODE0)      /* uart1_ctsn */
+			AM33XX_IOPAD(0x97c, PIN_OUTPUT_PULLDOWN | MUX_MODE0)      /* uart1_rtsn */
+			AM33XX_IOPAD(0x8e0, PIN_OUTPUT_PULLDOWN | MUX_MODE7)      /* lcd_vsync.gpio2[22] DTR */
+			AM33XX_IOPAD(0x8e4, PIN_INPUT_PULLDOWN | MUX_MODE7)      /* lcd_hsync.gpio2[23] DSR */
+			AM33XX_IOPAD(0x8e8, PIN_INPUT_PULLDOWN | MUX_MODE7)      /* lcd_pclk.gpio2[24] DCD */
+			AM33XX_IOPAD(0x8ec, PIN_INPUT_PULLDOWN | MUX_MODE7)      /* lcd_ac_bias_en.gpio2[25] RI */
+		>;
+	};
+
+	uart2_pins: pinmux_uart2_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x950, PIN_INPUT | MUX_MODE1)      /* spi0_sclk.uart2_rxd_mux3 */
+			AM33XX_IOPAD(0x954, PIN_OUTPUT | MUX_MODE1)      /* spi0_d0.uart2_txd_mux3 */
+			AM33XX_IOPAD(0x988, PIN_INPUT_PULLDOWN | MUX_MODE2)      /* i2c0_sda.uart2_ctsn_mux0 */
+			AM33XX_IOPAD(0x98c, PIN_OUTPUT_PULLDOWN | MUX_MODE2)      /* i2c0_scl.uart2_rtsn_mux0 */
+			AM33XX_IOPAD(0x830, PIN_OUTPUT_PULLDOWN | MUX_MODE7)      /* gpmc_ad12.gpio1[12] DTR */
+			AM33XX_IOPAD(0x834, PIN_INPUT_PULLDOWN | MUX_MODE7)      /* gpmc_ad13.gpio1[13] DSR */
+			AM33XX_IOPAD(0x838, PIN_INPUT_PULLDOWN | MUX_MODE7)      /* gpmc_ad14.gpio1[14] DCD */
+			AM33XX_IOPAD(0x83c, PIN_INPUT_PULLDOWN | MUX_MODE7)     /* gpmc_ad15.gpio1[15] RI */
+
+			AM33XX_IOPAD(0x9a0, PIN_INPUT_PULLUP | MUX_MODE7)      /* mcasp0_aclkr.gpio3[18], INPUT_PULLDOWN | MODE7 */
+		>;
+	};
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_pins>;
+	dtr-gpios = <&gpio2 22 GPIO_ACTIVE_LOW>;
+	dsr-gpios = <&gpio2 23 GPIO_ACTIVE_LOW>;
+	dcd-gpios = <&gpio2 24 GPIO_ACTIVE_LOW>;
+	rng-gpios = <&gpio2 25 GPIO_ACTIVE_LOW>;
+
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart2_pins>;
+	dtr-gpios = <&gpio1 12 GPIO_ACTIVE_LOW>;
+	dsr-gpios = <&gpio1 13 GPIO_ACTIVE_LOW>;
+	dcd-gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
+	rng-gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
+
+	status = "okay";
+};
+
+&i2c1 {
+	tca6416: gpio@20 {
+		compatible = "ti,tca6416";
+		reg = <0x20>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&gpio0>;
+		interrupts = <20 GPIO_ACTIVE_LOW>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&tca6416_pins>;
+	};
+};
+
+&usb0_phy {
+	status = "okay";
+};
+
+&usb0 {
+	status = "okay";
+	dr_mode = "host";
+};
+
+&cpsw_emac0 {
+	phy-mode = "rmii";
+	dual_emac_res_vlan = <1>;
+	fixed-link {
+		speed = <100>;
+		full-duplex;
+	};
+};
+
+&cpsw_emac1 {
+	phy_id = <&davinci_mdio>, <7>;
+	phy-mode = "rgmii-txid";
+	dual_emac_res_vlan = <2>;
+};
+
+&phy_sel {
+	rmii-clock-ext = <1>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/am335x-baltos-ir5221.dts linux-libre-4.7-gnu/arch/arm/boot/dts/am335x-baltos-ir5221.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/am335x-baltos-ir5221.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/am335x-baltos-ir5221.dts	2016-07-24 15:23:50.000000000 -0400
@@ -13,83 +13,19 @@
 
 /dts-v1/;
 
-#include "am33xx.dtsi"
-#include <dt-bindings/pwm/pwm.h>
-#include <dt-bindings/interrupt-controller/irq.h>
+#include "am335x-baltos.dtsi"
 
 / {
 	model = "OnRISC Baltos iR 5221";
-	compatible = "vscom,onrisc", "ti,am33xx";
-
-	cpus {
-		cpu@0 {
-			cpu0-supply = <&vdd1_reg>;
-		};
-	};
-
-	memory {
-		device_type = "memory";
-		reg = <0x80000000 0x10000000>; /* 256 MB */
-	};
-
-	vbat: fixedregulator@0 {
-		compatible = "regulator-fixed";
-		regulator-name = "vbat";
-		regulator-min-microvolt = <5000000>;
-		regulator-max-microvolt = <5000000>;
-		regulator-boot-on;
-	};
-
-	wl12xx_vmmc: fixedregulator@2 {
-		pinctrl-names = "default";
-		pinctrl-0 = <&wl12xx_gpio>;
-		compatible = "regulator-fixed";
-		regulator-name = "vwl1271";
-		regulator-min-microvolt = <3300000>;
-		regulator-max-microvolt = <3300000>;
-		gpio = <&gpio3 8 0>;
-		startup-delay-us = <70000>;
-		enable-active-high;
-	};
 };
 
 &am33xx_pinmux {
-	mmc2_pins: pinmux_mmc2_pins {
-		pinctrl-single,pins = <
-			AM33XX_IOPAD(0x820, PIN_INPUT_PULLUP | MUX_MODE2)      /* gpmc_ad8.mmc1_dat0_mux0 */
-			AM33XX_IOPAD(0x824, PIN_INPUT_PULLUP | MUX_MODE2)      /* gpmc_ad9.mmc1_dat1_mux0 */
-			AM33XX_IOPAD(0x828, PIN_INPUT_PULLUP | MUX_MODE2)      /* gpmc_ad10.mmc1_dat2_mux0 */
-			AM33XX_IOPAD(0x82c, PIN_INPUT_PULLUP | MUX_MODE2)      /* gpmc_ad11.mmc1_dat3_mux0 */
-			AM33XX_IOPAD(0x880, PIN_INPUT_PULLUP | MUX_MODE2)      /* gpmc_csn1.mmc1_clk_mux0 */
-			AM33XX_IOPAD(0x884, PIN_INPUT_PULLUP | MUX_MODE2)      /* gpmc_csn2.mmc1_cmd_mux0 */
-			AM33XX_IOPAD(0x9e4, PIN_INPUT_PULLUP | MUX_MODE7)      /* emu0.gpio3[7] */
-		>;
-	};
-
-	wl12xx_gpio: pinmux_wl12xx_gpio {
-		pinctrl-single,pins = <
-			AM33XX_IOPAD(0x9e8, PIN_OUTPUT_PULLUP | MUX_MODE7)      /* emu1.gpio3[8] */
-		>;
-	};
-
-	tps65910_pins: pinmux_tps65910_pins {
-		pinctrl-single,pins = <
-			AM33XX_IOPAD(0x878, PIN_INPUT_PULLUP | MUX_MODE7)      /* gpmc_ben1.gpio1[28] */
-		>;
-	};
-
 	tca6416_pins: pinmux_tca6416_pins {
 		pinctrl-single,pins = <
 			AM33XX_IOPAD(0x9b4, PIN_INPUT_PULLUP | MUX_MODE7)      /* xdma_event_intr1.gpio0[20] tca6416 stuff */
 		>;
 	};
 
-	i2c1_pins: pinmux_i2c1_pins {
-		pinctrl-single,pins = <
-			AM33XX_IOPAD(0x958, PIN_INPUT | MUX_MODE2)      /* spi0_d1.i2c1_sda_mux3 */
-			AM33XX_IOPAD(0x95c, PIN_INPUT | MUX_MODE2)      /* spi0_cs0.i2c1_scl_mux3 */
-		>;
-	};
 
 	dcan1_pins: pinmux_dcan1_pins {
 		pinctrl-single,pins = <
@@ -98,19 +34,12 @@
 		>;
 	};
 
-	uart0_pins: pinmux_uart0_pins {
-		pinctrl-single,pins = <
-			AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0)	/* uart0_rxd.uart0_rxd */
-			AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0)		/* uart0_txd.uart0_txd */
-		>;
-	};
-
 	uart1_pins: pinmux_uart1_pins {
 		pinctrl-single,pins = <
 			AM33XX_IOPAD(0x980, PIN_INPUT | MUX_MODE0)      /* uart1_rxd */
 			AM33XX_IOPAD(0x984, PIN_INPUT | MUX_MODE0)      /* uart1_txd */
-			AM33XX_IOPAD(0x978, PIN_INPUT_PULLDOWN | MUX_MODE7)      /* uart1_ctsn, INPUT | MODE0 */
-			AM33XX_IOPAD(0x97c, PIN_OUTPUT_PULLDOWN | MUX_MODE7)      /* uart1_rtsn, OUTPUT | MODE0 */
+			AM33XX_IOPAD(0x978, PIN_INPUT_PULLDOWN | MUX_MODE0)      /* uart1_ctsn */
+			AM33XX_IOPAD(0x97c, PIN_OUTPUT_PULLDOWN | MUX_MODE0)      /* uart1_rtsn */
 			AM33XX_IOPAD(0x8e0, PIN_OUTPUT_PULLDOWN | MUX_MODE7)      /* lcd_vsync.gpio2[22] DTR */
 			AM33XX_IOPAD(0x8e4, PIN_INPUT_PULLDOWN | MUX_MODE7)      /* lcd_hsync.gpio2[23] DSR */
 			AM33XX_IOPAD(0x8e8, PIN_INPUT_PULLDOWN | MUX_MODE7)      /* lcd_pclk.gpio2[24] DCD */
@@ -122,8 +51,8 @@
 		pinctrl-single,pins = <
 			AM33XX_IOPAD(0x950, PIN_INPUT | MUX_MODE1)      /* spi0_sclk.uart2_rxd_mux3 */
 			AM33XX_IOPAD(0x954, PIN_OUTPUT | MUX_MODE1)      /* spi0_d0.uart2_txd_mux3 */
-			AM33XX_IOPAD(0x988, PIN_INPUT_PULLDOWN | MUX_MODE7)      /* i2c0_sda.uart2_ctsn_mux0 */
-			AM33XX_IOPAD(0x98c, PIN_OUTPUT_PULLDOWN | MUX_MODE7)      /* i2c0_scl.uart2_rtsn_mux0 */
+			AM33XX_IOPAD(0x988, PIN_INPUT_PULLDOWN | MUX_MODE2)      /* i2c0_sda.uart2_ctsn_mux0 */
+			AM33XX_IOPAD(0x98c, PIN_OUTPUT_PULLDOWN | MUX_MODE2)      /* i2c0_scl.uart2_rtsn_mux0 */
 			AM33XX_IOPAD(0x830, PIN_OUTPUT_PULLDOWN | MUX_MODE7)      /* gpmc_ad12.gpio1[12] DTR */
 			AM33XX_IOPAD(0x834, PIN_INPUT_PULLDOWN | MUX_MODE7)      /* gpmc_ad13.gpio1[13] DSR */
 			AM33XX_IOPAD(0x838, PIN_INPUT_PULLDOWN | MUX_MODE7)      /* gpmc_ad14.gpio1[14] DCD */
@@ -133,151 +62,6 @@
 		>;
 	};
 
-	cpsw_default: cpsw_default {
-		pinctrl-single,pins = <
-			/* Slave 1 */
-			AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE1)       /* mii1_crs.rmii1_crs_dv */
-			AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE1)      /* mii1_tx_en.rmii1_txen */
-			AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE1)      /* mii1_txd1.rmii1_txd1 */
-			AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE1)      /* mii1_txd0.rmii1_txd0 */
-			AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE1)      /* mii1_rxd1.rmii1_rxd1 */
-			AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE1)      /* mii1_rxd0.rmii1_rxd0 */
-			AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE0)      /* rmii1_ref_clk.rmii1_refclk */
-
-
-			/* Slave 2 */
-			AM33XX_IOPAD(0x840, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a0.rgmii2_tctl */
-			AM33XX_IOPAD(0x844, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a1.rgmii2_rctl */
-			AM33XX_IOPAD(0x848, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a2.rgmii2_td3 */
-			AM33XX_IOPAD(0x84c, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a3.rgmii2_td2 */
-			AM33XX_IOPAD(0x850, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a4.rgmii2_td1 */
-			AM33XX_IOPAD(0x854, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a5.rgmii2_td0 */
-			AM33XX_IOPAD(0x858, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a6.rgmii2_tclk */
-			AM33XX_IOPAD(0x85c, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a7.rgmii2_rclk */
-			AM33XX_IOPAD(0x860, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a8.rgmii2_rd3 */
-			AM33XX_IOPAD(0x864, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a9.rgmii2_rd2 */
-			AM33XX_IOPAD(0x868, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a10.rgmii2_rd1 */
-			AM33XX_IOPAD(0x86c, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* gpmc_a11.rgmii2_rd0 */
-		>;
-	};
-
-	cpsw_sleep: cpsw_sleep {
-		pinctrl-single,pins = <
-			/* Slave 1 reset value */
-			AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-			AM33XX_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7)
-			AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7)
-			AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7)
-			AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-			AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7)
-			AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE7)
-
-			/* Slave 2 reset value*/
-			AM33XX_IOPAD(0x840, PIN_INPUT_PULLDOWN | MUX_MODE7)
-			AM33XX_IOPAD(0x844, PIN_INPUT_PULLDOWN | MUX_MODE7)
-			AM33XX_IOPAD(0x848, PIN_INPUT_PULLDOWN | MUX_MODE7)
-			AM33XX_IOPAD(0x84c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-			AM33XX_IOPAD(0x850, PIN_INPUT_PULLDOWN | MUX_MODE7)
-			AM33XX_IOPAD(0x854, PIN_INPUT_PULLDOWN | MUX_MODE7)
-			AM33XX_IOPAD(0x858, PIN_INPUT_PULLDOWN | MUX_MODE7)
-			AM33XX_IOPAD(0x85c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-			AM33XX_IOPAD(0x860, PIN_INPUT_PULLDOWN | MUX_MODE7)
-			AM33XX_IOPAD(0x864, PIN_INPUT_PULLDOWN | MUX_MODE7)
-			AM33XX_IOPAD(0x868, PIN_INPUT_PULLDOWN | MUX_MODE7)
-			AM33XX_IOPAD(0x86c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-		>;
-	};
-
-	davinci_mdio_default: davinci_mdio_default {
-		pinctrl-single,pins = <
-			/* MDIO */
-			AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)	/* mdio_data.mdio_data */
-			AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0)			/* mdio_clk.mdio_clk */
-		>;
-	};
-
-	davinci_mdio_sleep: davinci_mdio_sleep {
-		pinctrl-single,pins = <
-			/* MDIO reset value */
-			AM33XX_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7)
-			AM33XX_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-		>;
-	};
-
-	nandflash_pins_s0: nandflash_pins_s0 {
-		pinctrl-single,pins = <
-			AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad0.gpmc_ad0 */
-			AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad1.gpmc_ad1 */
-			AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad2.gpmc_ad2 */
-			AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad3.gpmc_ad3 */
-			AM33XX_IOPAD(0x810, PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad4.gpmc_ad4 */
-			AM33XX_IOPAD(0x814, PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad5.gpmc_ad5 */
-			AM33XX_IOPAD(0x818, PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad6.gpmc_ad6 */
-			AM33XX_IOPAD(0x81c, PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_ad7.gpmc_ad7 */
-			AM33XX_IOPAD(0x870, PIN_INPUT_PULLUP | MUX_MODE0)	/* gpmc_wait0.gpmc_wait0 */
-			AM33XX_IOPAD(0x874, PIN_INPUT_PULLUP | MUX_MODE7)	/* gpmc_wpn.gpio0_30 */
-			AM33XX_IOPAD(0x87c, PIN_OUTPUT | MUX_MODE0)		/* gpmc_csn0.gpmc_csn0  */
-			AM33XX_IOPAD(0x890, PIN_OUTPUT | MUX_MODE0)		/* gpmc_advn_ale.gpmc_advn_ale */
-			AM33XX_IOPAD(0x894, PIN_OUTPUT | MUX_MODE0)		/* gpmc_oen_ren.gpmc_oen_ren */
-			AM33XX_IOPAD(0x898, PIN_OUTPUT | MUX_MODE0)		/* gpmc_wen.gpmc_wen */
-			AM33XX_IOPAD(0x89c, PIN_OUTPUT | MUX_MODE0)		/* gpmc_be0n_cle.gpmc_be0n_cle */
-		>;
-	};
-};
-
-&elm {
-	status = "okay";
-};
-
-&gpmc {
-	pinctrl-names = "default";
-	pinctrl-0 = <&nandflash_pins_s0>;
-	ranges = <0 0 0x08000000 0x10000000>;	/* CS0: NAND */
-	status = "okay";
-
-	nand@0,0 {
-		compatible = "ti,omap2-nand";
-		reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
-		interrupt-parent = <&gpmc>;
-		interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
-			     <1 IRQ_TYPE_NONE>;	/* termcount */
-		nand-bus-width = <8>;
-		ti,nand-ecc-opt = "bch8";
-		ti,nand-xfer-type = "polled";
-
-		gpmc,device-nand = "true";
-		gpmc,device-width = <1>;
-		gpmc,sync-clk-ps = <0>;
-		gpmc,cs-on-ns = <0>;
-		gpmc,cs-rd-off-ns = <44>;
-		gpmc,cs-wr-off-ns = <44>;
-		gpmc,adv-on-ns = <6>;
-		gpmc,adv-rd-off-ns = <34>;
-		gpmc,adv-wr-off-ns = <44>;
-		gpmc,we-on-ns = <0>;
-		gpmc,we-off-ns = <40>;
-		gpmc,oe-on-ns = <0>;
-		gpmc,oe-off-ns = <54>;
-		gpmc,access-ns = <64>;
-		gpmc,rd-cycle-ns = <82>;
-		gpmc,wr-cycle-ns = <82>;
-		gpmc,bus-turnaround-ns = <0>;
-		gpmc,cycle2cycle-delay-ns = <0>;
-		gpmc,clk-activation-ns = <0>;
-		gpmc,wr-access-ns = <40>;
-		gpmc,wr-data-mux-bus-ns = <0>;
-
-		#address-cells = <1>;
-		#size-cells = <1>;
-		elm_id = <&elm>;
-	};
-};
-
-&uart0 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&uart0_pins>;
-
-	status = "okay";
 };
 
 &uart1 {
@@ -287,8 +71,6 @@
 	dsr-gpios = <&gpio2 23 GPIO_ACTIVE_LOW>;
 	dcd-gpios = <&gpio2 24 GPIO_ACTIVE_LOW>;
 	rng-gpios = <&gpio2 25 GPIO_ACTIVE_LOW>;
-	cts-gpios = <&gpio0 12 GPIO_ACTIVE_LOW>;
-	rts-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
 
 	status = "okay";
 };
@@ -300,35 +82,11 @@
 	dsr-gpios = <&gpio1 13 GPIO_ACTIVE_LOW>;
 	dcd-gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
 	rng-gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
-	cts-gpios = <&gpio3 5 GPIO_ACTIVE_LOW>;
-	rts-gpios = <&gpio3 6 GPIO_ACTIVE_LOW>;
 
 	status = "okay";
 };
 
 &i2c1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&i2c1_pins>;
-
-	status = "okay";
-	clock-frequency = <400000>;
-
-	tps: tps@2d {
-		reg = <0x2d>;
-		gpio-controller;
-		#gpio-cells = <2>;
-		interrupt-parent = <&gpio1>;
-		interrupts = <28 GPIO_ACTIVE_LOW>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&tps65910_pins>;
-	};
-
-	at24@50 {
-		compatible = "at24,24c02";
-		pagesize = <8>;
-		reg = <0x50>;
-	};
-
 	tca6416: gpio@20 {
 		compatible = "ti,tca6416";
 		reg = <0x20>;
@@ -341,14 +99,6 @@
 	};
 };
 
-&usb {
-	status = "okay";
-};
-
-&usb_ctrl_mod {
-	status = "okay";
-};
-
 &usb0_phy {
 	status = "okay";
 };
@@ -367,108 +117,6 @@
 	dr_mode = "otg";
 };
 
-&cppi41dma  {
-	status = "okay";
-};
-
-#include "tps65910.dtsi"
-
-&tps {
-	vcc1-supply = <&vbat>;
-	vcc2-supply = <&vbat>;
-	vcc3-supply = <&vbat>;
-	vcc4-supply = <&vbat>;
-	vcc5-supply = <&vbat>;
-	vcc6-supply = <&vbat>;
-	vcc7-supply = <&vbat>;
-	vccio-supply = <&vbat>;
-
-	ti,en-ck32k-xtal = <1>;
-
-	regulators {
-		vrtc_reg: regulator@0 {
-			regulator-always-on;
-		};
-
-		vio_reg: regulator@1 {
-			regulator-always-on;
-		};
-
-		vdd1_reg: regulator@2 {
-			/* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
-			regulator-name = "vdd_mpu";
-			regulator-min-microvolt = <912500>;
-			regulator-max-microvolt = <1312500>;
-			regulator-boot-on;
-			regulator-always-on;
-		};
-
-		vdd2_reg: regulator@3 {
-			/* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
-			regulator-name = "vdd_core";
-			regulator-min-microvolt = <912500>;
-			regulator-max-microvolt = <1150000>;
-			regulator-boot-on;
-			regulator-always-on;
-		};
-
-		vdd3_reg: regulator@4 {
-			regulator-always-on;
-		};
-
-		vdig1_reg: regulator@5 {
-			regulator-always-on;
-		};
-
-		vdig2_reg: regulator@6 {
-			regulator-always-on;
-		};
-
-		vpll_reg: regulator@7 {
-			regulator-always-on;
-		};
-
-		vdac_reg: regulator@8 {
-			regulator-always-on;
-		};
-
-		vaux1_reg: regulator@9 {
-			regulator-always-on;
-		};
-
-		vaux2_reg: regulator@10 {
-			regulator-always-on;
-		};
-
-		vaux33_reg: regulator@11 {
-			regulator-always-on;
-		};
-
-		vmmc_reg: regulator@12 {
-			regulator-min-microvolt = <1800000>;
-			regulator-max-microvolt = <3300000>;
-			regulator-always-on;
-		};
-	};
-};
-
-&mac {
-	pinctrl-names = "default", "sleep";
-	pinctrl-0 = <&cpsw_default>;
-	pinctrl-1 = <&cpsw_sleep>;
-	dual_emac = <1>;
-
-	status = "okay";
-};
-
-&davinci_mdio {
-	pinctrl-names = "default", "sleep";
-	pinctrl-0 = <&davinci_mdio_default>;
-	pinctrl-1 = <&davinci_mdio_sleep>;
-
-	status = "okay";
-};
-
 &cpsw_emac0 {
 	phy-mode = "rmii";
 	dual_emac_res_vlan = <1>;
@@ -488,42 +136,6 @@
 	rmii-clock-ext = <1>;
 };
 
-&mmc1 {
-	vmmc-supply = <&vmmc_reg>;
-	status = "okay";
-};
-
-&mmc2 {
-	status = "okay";
-	vmmc-supply = <&wl12xx_vmmc>;
-	ti,non-removable;
-	bus-width = <4>;
-	cap-power-off-card;
-	pinctrl-names = "default";
-	pinctrl-0 = <&mmc2_pins>;
-
-	#address-cells = <1>;
-	#size-cells = <0>;
-	wlcore: wlcore@2 {
-		compatible = "ti,wl1835";
-		reg = <2>;
-		interrupt-parent = <&gpio3>;
-		interrupts = <7 IRQ_TYPE_LEVEL_HIGH>;
-	};
-};
-
-&sham {
-	status = "okay";
-};
-
-&aes {
-	status = "okay";
-};
-
-&gpio0 {
-	ti,no-reset-on-init;
-};
-
 &dcan1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&dcan1_pins>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/am335x-chiliboard.dts linux-libre-4.7-gnu/arch/arm/boot/dts/am335x-chiliboard.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/am335x-chiliboard.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/am335x-chiliboard.dts	2016-07-24 15:23:50.000000000 -0400
@@ -35,6 +35,59 @@
 };
 
 &am33xx_pinmux {
+	uart0_pins: pinmux_uart0_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0)	/* uart0_rxd.uart0_rxd */
+			AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* uart0_txd.uart0_txd */
+		>;
+	};
+
+	cpsw_default: cpsw_default {
+		pinctrl-single,pins = <
+			/* Slave 1 */
+			AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE1)  /* mii1_crs.rmii1_crs */
+			AM33XX_IOPAD(0x910, PIN_INPUT_PULLUP | MUX_MODE1)	/* mii1_rxerr.rmii1_rxerr */
+			AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE1)	/* mii1_txen.rmii1_txen */
+			AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE1)	/* mii1_txd1.rmii1_txd1 */
+			AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE1)	/* mii1_txd0.rmii1_txd0 */
+			AM33XX_IOPAD(0x93c, PIN_INPUT_PULLUP | MUX_MODE1)	/* mii1_rxd1.rmii1_rxd1 */
+			AM33XX_IOPAD(0x940, PIN_INPUT_PULLUP | MUX_MODE1)	/* mii1_rxd0.rmii1_rxd0 */
+			AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE0)	/* rmii1_ref_clk.rmii_ref_clk */
+		>;
+	};
+
+	cpsw_sleep: cpsw_sleep {
+		pinctrl-single,pins = <
+			/* Slave 1 reset value */
+			AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
+	davinci_mdio_default: davinci_mdio_default {
+		pinctrl-single,pins = <
+			/* mdio_data.mdio_data */
+			AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)
+			/* mdio_clk.mdio_clk */
+			AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0)
+		>;
+	};
+
+	davinci_mdio_sleep: davinci_mdio_sleep {
+		pinctrl-single,pins = <
+			/* MDIO reset value */
+			AM33XX_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM33XX_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
 	usb1_drvvbus: usb1_drvvbus {
 		pinctrl-single,pins = <
 			AM33XX_IOPAD(0xa34, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* usb1_drvvbus.usb1_drvvbus */
@@ -61,12 +114,34 @@
 	};
 };
 
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins>;
+
+	status = "okay";
+};
+
 &ldo4_reg {
 	regulator-min-microvolt = <3300000>;
 	regulator-max-microvolt = <3300000>;
 };
 
 /* Ethernet */
+&mac {
+	slaves = <1>;
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&cpsw_default>;
+	pinctrl-1 = <&cpsw_sleep>;
+	status = "okay";
+};
+
+&davinci_mdio {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&davinci_mdio_default>;
+	pinctrl-1 = <&davinci_mdio_sleep>;
+	status = "okay";
+};
+
 &cpsw_emac0 {
 	phy_id = <&davinci_mdio>, <0>;
 	phy-mode = "rmii";
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/am335x-chilisom.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/am335x-chilisom.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/am335x-chilisom.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/am335x-chilisom.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -35,59 +35,6 @@
 		>;
 	};
 
-	uart0_pins: pinmux_uart0_pins {
-		pinctrl-single,pins = <
-			AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0)	/* uart0_rxd.uart0_rxd */
-			AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* uart0_txd.uart0_txd */
-		>;
-	};
-
-	cpsw_default: cpsw_default {
-		pinctrl-single,pins = <
-			/* Slave 1 */
-			AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE1)  /* mii1_crs.rmii1_crs */
-			AM33XX_IOPAD(0x910, PIN_INPUT_PULLUP | MUX_MODE1)	/* mii1_rxerr.rmii1_rxerr */
-			AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE1)	/* mii1_txen.rmii1_txen */
-			AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE1)	/* mii1_txd1.rmii1_txd1 */
-			AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE1)	/* mii1_txd0.rmii1_txd0 */
-			AM33XX_IOPAD(0x93c, PIN_INPUT_PULLUP | MUX_MODE1)	/* mii1_rxd1.rmii1_rxd1 */
-			AM33XX_IOPAD(0x940, PIN_INPUT_PULLUP | MUX_MODE1)	/* mii1_rxd0.rmii1_rxd0 */
-			AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE0)	/* rmii1_ref_clk.rmii_ref_clk */
-		>;
-	};
-
-	cpsw_sleep: cpsw_sleep {
-		pinctrl-single,pins = <
-			/* Slave 1 reset value */
-			AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-			AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE7)
-			AM33XX_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7)
-			AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE7)
-			AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7)
-			AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7)
-			AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-			AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7)
-			AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE7)
-		>;
-	};
-
-	davinci_mdio_default: davinci_mdio_default {
-		pinctrl-single,pins = <
-			/* mdio_data.mdio_data */
-			AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)
-			/* mdio_clk.mdio_clk */
-			AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0)
-		>;
-	};
-
-	davinci_mdio_sleep: davinci_mdio_sleep {
-		pinctrl-single,pins = <
-			/* MDIO reset value */
-			AM33XX_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7)
-			AM33XX_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7)
-		>;
-	};
-
 	nandflash_pins: nandflash_pins {
 		pinctrl-single,pins = <
 			AM33XX_IOPAD(0x800, PIN_INPUT_PULLDOWN | MUX_MODE0)	/* gpmc_ad0.gpmc_ad0 */
@@ -109,13 +56,6 @@
 	};
 };
 
-&uart0 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&uart0_pins>;
-
-	status = "okay";
-};
-
 &i2c0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&i2c0_pins>;
@@ -182,20 +122,8 @@
 	};
 };
 
-/* Ethernet MAC */
-&mac {
-	slaves = <1>;
-	pinctrl-names = "default", "sleep";
-	pinctrl-0 = <&cpsw_default>;
-	pinctrl-1 = <&cpsw_sleep>;
-	status = "okay";
-};
-
-&davinci_mdio {
-	pinctrl-names = "default", "sleep";
-	pinctrl-0 = <&davinci_mdio_default>;
-	pinctrl-1 = <&davinci_mdio_sleep>;
-	status = "okay";
+&rtc {
+	system-power-controller;
 };
 
 /* NAND Flash */
@@ -214,6 +142,7 @@
 		interrupt-parent = <&gpmc>;
 		interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
 			     <1 IRQ_TYPE_NONE>;	/* termcount */
+		rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */
 		ti,nand-ecc-opt = "bch8";
 		ti,elm-id = <&elm>;
 		nand-bus-width = <8>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/am335x-cm-t335.dts linux-libre-4.7-gnu/arch/arm/boot/dts/am335x-cm-t335.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/am335x-cm-t335.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/am335x-cm-t335.dts	2016-07-24 15:23:50.000000000 -0400
@@ -411,6 +411,7 @@ status = "okay";
 		interrupt-parent = <&gpmc>;
 		interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
 			     <1 IRQ_TYPE_NONE>;	/* termcount */
+		rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */
 		ti,nand-ecc-opt = "bch8";
 		ti,elm-id = <&elm>;
 		nand-bus-width = <8>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/am335x-evm.dts linux-libre-4.7-gnu/arch/arm/boot/dts/am335x-evm.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/am335x-evm.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/am335x-evm.dts	2016-07-24 15:23:50.000000000 -0400
@@ -524,6 +524,7 @@
 		interrupt-parent = <&gpmc>;
 		interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
 			     <1 IRQ_TYPE_NONE>;	/* termcount */
+		rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */
 		ti,nand-ecc-opt = "bch8";
 		ti,elm-id = <&elm>;
 		nand-bus-width = <8>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/am335x-icev2.dts linux-libre-4.7-gnu/arch/arm/boot/dts/am335x-icev2.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/am335x-icev2.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/am335x-icev2.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * AM335x ICE V2 board
+ * http://www.ti.com/tool/tmdsice3359
+ */
+
+/dts-v1/;
+
+#include "am33xx.dtsi"
+
+/ {
+	model = "TI AM3359 ICE-V2";
+	compatible = "ti,am3359-icev2", "ti,am33xx";
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x10000000>; /* 256 MB */
+	};
+
+	vbat: fixedregulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "vbat";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-boot-on;
+	};
+
+	vtt_fixed: fixedregulator@1 {
+		compatible = "regulator-fixed";
+		regulator-name = "vtt";
+		regulator-min-microvolt = <1500000>;
+		regulator-max-microvolt = <1500000>;
+		gpio = <&gpio0 18 GPIO_ACTIVE_HIGH>;
+		regulator-always-on;
+		regulator-boot-on;
+		enable-active-high;
+	};
+
+	leds@0 {
+		compatible = "gpio-leds";
+
+		led@0 {
+			label = "out0";
+			gpios = <&tpic2810 0 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led@1 {
+			label = "out1";
+			gpios = <&tpic2810 1 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led@2 {
+			label = "out2";
+			gpios = <&tpic2810 2 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led@3 {
+			label = "out3";
+			gpios = <&tpic2810 3 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led@4 {
+			label = "out4";
+			gpios = <&tpic2810 4 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led@5 {
+			label = "out5";
+			gpios = <&tpic2810 5 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led@6 {
+			label = "out6";
+			gpios = <&tpic2810 6 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led@7 {
+			label = "out7";
+			gpios = <&tpic2810 7 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+	};
+
+	/* Tricolor status LEDs */
+	leds@1 {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&user_leds>;
+
+		led@0 {
+			label = "status0:red:cpu0";
+			gpios = <&gpio0 17 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+			linux,default-trigger = "cpu0";
+		};
+
+		led@1 {
+			label = "status0:green:usr";
+			gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led@2 {
+			label = "status0:yellow:usr";
+			gpios = <&gpio3 9 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led@3 {
+			label = "status1:red:mmc0";
+			gpios = <&gpio1 30 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+			linux,default-trigger = "mmc0";
+		};
+
+		led@4 {
+			label = "status1:green:usr";
+			gpios = <&gpio0 20 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led@5 {
+			label = "status1:yellow:usr";
+			gpios = <&gpio0 19 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+	};
+};
+
+&am33xx_pinmux {
+	user_leds: user_leds {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x91c, PIN_OUTPUT | MUX_MODE7) /* (J18) gmii1_txd3.gpio0[16] */
+			AM33XX_IOPAD(0x920, PIN_OUTPUT | MUX_MODE7) /* (K15) gmii1_txd2.gpio0[17] */
+			AM33XX_IOPAD(0x9b0, PIN_OUTPUT | MUX_MODE7) /* (A15) xdma_event_intr0.gpio0[19] */
+			AM33XX_IOPAD(0x9b4, PIN_OUTPUT | MUX_MODE7) /* (D14) xdma_event_intr1.gpio0[20] */
+			AM33XX_IOPAD(0x880, PIN_OUTPUT | MUX_MODE7) /* (U9) gpmc_csn1.gpio1[30] */
+			AM33XX_IOPAD(0x92c, PIN_OUTPUT | MUX_MODE7) /* (K18) gmii1_txclk.gpio3[9] */
+		>;
+	};
+
+	mmc0_pins_default: mmc0_pins_default {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x8f0, PIN_INPUT_PULLUP | MUX_MODE0) /* (F17) mmc0_dat3.mmc0_dat3 */
+			AM33XX_IOPAD(0x8f4, PIN_INPUT_PULLUP | MUX_MODE0) /* (F18) mmc0_dat2.mmc0_dat2 */
+			AM33XX_IOPAD(0x8f8, PIN_INPUT_PULLUP | MUX_MODE0) /* (G15) mmc0_dat1.mmc0_dat1 */
+			AM33XX_IOPAD(0x8fc, PIN_INPUT_PULLUP | MUX_MODE0) /* (G16) mmc0_dat0.mmc0_dat0 */
+			AM33XX_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE0) /* (G17) mmc0_clk.mmc0_clk */
+			AM33XX_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE0) /* (G18) mmc0_cmd.mmc0_cmd */
+			AM33XX_IOPAD(0x960, PIN_INPUT_PULLUP | MUX_MODE5) /* (C15) spi0_cs1.mmc0_sdcd */
+		>;
+	};
+
+	i2c0_pins_default: i2c0_pins_default {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x988, PIN_INPUT | MUX_MODE0) /* (C17) I2C0_SDA.I2C0_SDA */
+			AM33XX_IOPAD(0x98c, PIN_INPUT | MUX_MODE0) /* (C16) I2C0_SCL.I2C0_SCL */
+		>;
+	};
+
+	spi0_pins_default: spi0_pins_default {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x950, PIN_INPUT_PULLUP | MUX_MODE0) /* (A17) spi0_sclk.spi0_sclk */
+			AM33XX_IOPAD(0x954, PIN_INPUT_PULLUP | MUX_MODE0) /* (B17) spi0_d0.spi0_d0 */
+			AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | MUX_MODE0) /* (B16) spi0_d1.spi0_d1 */
+			AM33XX_IOPAD(0x95c, PIN_INPUT_PULLUP | MUX_MODE0) /* (A16) spi0_cs0.spi0_cs0 */
+		>;
+	};
+
+	uart3_pins_default: uart3_pins_default {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x934, PIN_INPUT_PULLUP | MUX_MODE1) /* (L17) gmii1_rxd3.uart3_rxd */
+			AM33XX_IOPAD(0x938, PIN_OUTPUT_PULLUP | MUX_MODE1) /* (L16) gmii1_rxd2.uart3_txd */
+		>;
+	};
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins_default>;
+
+	status = "okay";
+	clock-frequency = <400000>;
+
+	tps: power-controller@2d {
+		reg = <0x2d>;
+	};
+
+	tpic2810: gpio@60 {
+		compatible = "ti,tpic2810";
+		reg = <0x60>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+};
+
+#include "tps65910.dtsi"
+
+&tps {
+	vcc1-supply = <&vbat>;
+	vcc2-supply = <&vbat>;
+	vcc3-supply = <&vbat>;
+	vcc4-supply = <&vbat>;
+	vcc5-supply = <&vbat>;
+	vcc6-supply = <&vbat>;
+	vcc7-supply = <&vbat>;
+	vccio-supply = <&vbat>;
+
+	regulators {
+		vrtc_reg: regulator@0 {
+			regulator-always-on;
+		};
+
+		vio_reg: regulator@1 {
+			regulator-always-on;
+		};
+
+		vdd1_reg: regulator@2 {
+			regulator-name = "vdd_mpu";
+			regulator-min-microvolt = <912500>;
+			regulator-max-microvolt = <1326000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		vdd2_reg: regulator@3 {
+			regulator-name = "vdd_core";
+			regulator-min-microvolt = <912500>;
+			regulator-max-microvolt = <1144000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		vdd3_reg: regulator@4 {
+			regulator-always-on;
+		};
+
+		vdig1_reg: regulator@5 {
+			regulator-always-on;
+		};
+
+		vdig2_reg: regulator@6 {
+			regulator-always-on;
+		};
+
+		vpll_reg: regulator@7 {
+			regulator-always-on;
+		};
+
+		vdac_reg: regulator@8 {
+			regulator-always-on;
+		};
+
+		vaux1_reg: regulator@9 {
+			regulator-always-on;
+		};
+
+		vaux2_reg: regulator@10 {
+			regulator-always-on;
+		};
+
+		vaux33_reg: regulator@11 {
+			regulator-always-on;
+		};
+
+		vmmc_reg: regulator@12 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+	};
+};
+
+&mmc1 {
+	status = "okay";
+	vmmc-supply = <&vmmc_reg>;
+	bus-width = <4>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc0_pins_default>;
+};
+
+&gpio0 {
+	/* Do not idle the GPIO used for holding the VTT regulator */
+	ti,no-reset-on-init;
+	ti,no-idle-on-init;
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart3_pins_default>;
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/am335x-igep0033.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/am335x-igep0033.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/am335x-igep0033.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/am335x-igep0033.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -135,6 +135,7 @@
 		interrupt-parent = <&gpmc>;
 		interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
 			     <1 IRQ_TYPE_NONE>;	/* termcount */
+		rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */
 		nand-bus-width = <8>;
 		ti,nand-ecc-opt = "bch8";
 		gpmc,device-width = <1>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/am335x-phycore-som.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/am335x-phycore-som.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/am335x-phycore-som.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/am335x-phycore-som.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -171,6 +171,7 @@
 		interrupt-parent = <&gpmc>;
 		interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
 			     <1 IRQ_TYPE_NONE>;	/* termcount */
+		rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */
 		nand-bus-width = <8>;
 		ti,nand-ecc-opt = "bch8";
 		gpmc,device-nand = "true";
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/am335x-shc.dts linux-libre-4.7-gnu/arch/arm/boot/dts/am335x-shc.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/am335x-shc.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/am335x-shc.dts	2016-07-24 15:23:50.000000000 -0400
@@ -138,7 +138,7 @@
 &epwmss1 {
 	status = "okay";
 
-	ehrpwm1: ehrpwm@48302200 {
+	ehrpwm1: pwm@48302200 {
 		pinctrl-names = "default";
 		pinctrl-0 = <&ehrpwm1_pins>;
 		status = "okay";
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/am33xx-clocks.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/am33xx-clocks.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/am33xx-clocks.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/am33xx-clocks.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -8,7 +8,7 @@
  * published by the Free Software Foundation.
  */
 &scm_clocks {
-	sys_clkin_ck: sys_clkin_ck {
+	sys_clkin_ck: sys_clkin_ck@40 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&virt_19200000_ck>, <&virt_24000000_ck>, <&virt_25000000_ck>, <&virt_26000000_ck>;
@@ -163,7 +163,7 @@
 		clock-frequency = <12000000>;
 	};
 
-	dpll_core_ck: dpll_core_ck {
+	dpll_core_ck: dpll_core_ck@490 {
 		#clock-cells = <0>;
 		compatible = "ti,am3-dpll-core-clock";
 		clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
@@ -176,7 +176,7 @@
 		clocks = <&dpll_core_ck>;
 	};
 
-	dpll_core_m4_ck: dpll_core_m4_ck {
+	dpll_core_m4_ck: dpll_core_m4_ck@480 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_core_x2_ck>;
@@ -185,7 +185,7 @@
 		ti,index-starts-at-one;
 	};
 
-	dpll_core_m5_ck: dpll_core_m5_ck {
+	dpll_core_m5_ck: dpll_core_m5_ck@484 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_core_x2_ck>;
@@ -194,7 +194,7 @@
 		ti,index-starts-at-one;
 	};
 
-	dpll_core_m6_ck: dpll_core_m6_ck {
+	dpll_core_m6_ck: dpll_core_m6_ck@4d8 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_core_x2_ck>;
@@ -203,14 +203,14 @@
 		ti,index-starts-at-one;
 	};
 
-	dpll_mpu_ck: dpll_mpu_ck {
+	dpll_mpu_ck: dpll_mpu_ck@488 {
 		#clock-cells = <0>;
 		compatible = "ti,am3-dpll-clock";
 		clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
 		reg = <0x0488>, <0x0420>, <0x042c>;
 	};
 
-	dpll_mpu_m2_ck: dpll_mpu_m2_ck {
+	dpll_mpu_m2_ck: dpll_mpu_m2_ck@4a8 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_mpu_ck>;
@@ -219,14 +219,14 @@
 		ti,index-starts-at-one;
 	};
 
-	dpll_ddr_ck: dpll_ddr_ck {
+	dpll_ddr_ck: dpll_ddr_ck@494 {
 		#clock-cells = <0>;
 		compatible = "ti,am3-dpll-no-gate-clock";
 		clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
 		reg = <0x0494>, <0x0434>, <0x0440>;
 	};
 
-	dpll_ddr_m2_ck: dpll_ddr_m2_ck {
+	dpll_ddr_m2_ck: dpll_ddr_m2_ck@4a0 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_ddr_ck>;
@@ -243,14 +243,14 @@
 		clock-div = <2>;
 	};
 
-	dpll_disp_ck: dpll_disp_ck {
+	dpll_disp_ck: dpll_disp_ck@498 {
 		#clock-cells = <0>;
 		compatible = "ti,am3-dpll-no-gate-clock";
 		clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
 		reg = <0x0498>, <0x0448>, <0x0454>;
 	};
 
-	dpll_disp_m2_ck: dpll_disp_m2_ck {
+	dpll_disp_m2_ck: dpll_disp_m2_ck@4a4 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_disp_ck>;
@@ -260,14 +260,14 @@
 		ti,set-rate-parent;
 	};
 
-	dpll_per_ck: dpll_per_ck {
+	dpll_per_ck: dpll_per_ck@48c {
 		#clock-cells = <0>;
 		compatible = "ti,am3-dpll-no-gate-j-type-clock";
 		clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
 		reg = <0x048c>, <0x0470>, <0x049c>;
 	};
 
-	dpll_per_m2_ck: dpll_per_m2_ck {
+	dpll_per_m2_ck: dpll_per_m2_ck@4ac {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_per_ck>;
@@ -292,7 +292,7 @@
 		clock-div = <4>;
 	};
 
-	cefuse_fck: cefuse_fck {
+	cefuse_fck: cefuse_fck@a20 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_clkin_ck>;
@@ -316,7 +316,7 @@
 		clock-div = <732>;
 	};
 
-	clkdiv32k_ick: clkdiv32k_ick {
+	clkdiv32k_ick: clkdiv32k_ick@14c {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&clkdiv32k_ck>;
@@ -332,14 +332,14 @@
 		clock-div = <1>;
 	};
 
-	pruss_ocp_gclk: pruss_ocp_gclk {
+	pruss_ocp_gclk: pruss_ocp_gclk@530 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&l3_gclk>, <&dpll_disp_m2_ck>;
 		reg = <0x0530>;
 	};
 
-	mmu_fck: mmu_fck {
+	mmu_fck: mmu_fck@914 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&dpll_core_m4_ck>;
@@ -347,56 +347,56 @@
 		reg = <0x0914>;
 	};
 
-	timer1_fck: timer1_fck {
+	timer1_fck: timer1_fck@528 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin_ck>, <&clkdiv32k_ick>, <&tclkin_ck>, <&clk_rc32k_ck>, <&clk_32768_ck>;
 		reg = <0x0528>;
 	};
 
-	timer2_fck: timer2_fck {
+	timer2_fck: timer2_fck@508 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>;
 		reg = <0x0508>;
 	};
 
-	timer3_fck: timer3_fck {
+	timer3_fck: timer3_fck@50c {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>;
 		reg = <0x050c>;
 	};
 
-	timer4_fck: timer4_fck {
+	timer4_fck: timer4_fck@510 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>;
 		reg = <0x0510>;
 	};
 
-	timer5_fck: timer5_fck {
+	timer5_fck: timer5_fck@518 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>;
 		reg = <0x0518>;
 	};
 
-	timer6_fck: timer6_fck {
+	timer6_fck: timer6_fck@51c {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>;
 		reg = <0x051c>;
 	};
 
-	timer7_fck: timer7_fck {
+	timer7_fck: timer7_fck@504 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>;
 		reg = <0x0504>;
 	};
 
-	usbotg_fck: usbotg_fck {
+	usbotg_fck: usbotg_fck@47c {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&dpll_per_ck>;
@@ -412,7 +412,7 @@
 		clock-div = <2>;
 	};
 
-	ieee5000_fck: ieee5000_fck {
+	ieee5000_fck: ieee5000_fck@e4 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&dpll_core_m4_div2_ck>;
@@ -420,7 +420,7 @@
 		reg = <0x00e4>;
 	};
 
-	wdt1_fck: wdt1_fck {
+	wdt1_fck: wdt1_fck@538 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&clk_rc32k_ck>, <&clkdiv32k_ick>;
@@ -483,21 +483,21 @@
 		clock-div = <2>;
 	};
 
-	cpsw_cpts_rft_clk: cpsw_cpts_rft_clk {
+	cpsw_cpts_rft_clk: cpsw_cpts_rft_clk@520 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&dpll_core_m5_ck>, <&dpll_core_m4_ck>;
 		reg = <0x0520>;
 	};
 
-	gpio0_dbclk_mux_ck: gpio0_dbclk_mux_ck {
+	gpio0_dbclk_mux_ck: gpio0_dbclk_mux_ck@53c {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&clk_rc32k_ck>, <&clk_32768_ck>, <&clkdiv32k_ick>;
 		reg = <0x053c>;
 	};
 
-	gpio0_dbclk: gpio0_dbclk {
+	gpio0_dbclk: gpio0_dbclk@408 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&gpio0_dbclk_mux_ck>;
@@ -505,7 +505,7 @@
 		reg = <0x0408>;
 	};
 
-	gpio1_dbclk: gpio1_dbclk {
+	gpio1_dbclk: gpio1_dbclk@ac {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&clkdiv32k_ick>;
@@ -513,7 +513,7 @@
 		reg = <0x00ac>;
 	};
 
-	gpio2_dbclk: gpio2_dbclk {
+	gpio2_dbclk: gpio2_dbclk@b0 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&clkdiv32k_ick>;
@@ -521,7 +521,7 @@
 		reg = <0x00b0>;
 	};
 
-	gpio3_dbclk: gpio3_dbclk {
+	gpio3_dbclk: gpio3_dbclk@b4 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&clkdiv32k_ick>;
@@ -529,7 +529,7 @@
 		reg = <0x00b4>;
 	};
 
-	lcd_gclk: lcd_gclk {
+	lcd_gclk: lcd_gclk@534 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&dpll_disp_m2_ck>, <&dpll_core_m5_ck>, <&dpll_per_m2_ck>;
@@ -545,7 +545,7 @@
 		clock-div = <2>;
 	};
 
-	gfx_fclk_clksel_ck: gfx_fclk_clksel_ck {
+	gfx_fclk_clksel_ck: gfx_fclk_clksel_ck@52c {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&dpll_core_m4_ck>, <&dpll_per_m2_ck>;
@@ -553,7 +553,7 @@
 		reg = <0x052c>;
 	};
 
-	gfx_fck_div_ck: gfx_fck_div_ck {
+	gfx_fck_div_ck: gfx_fck_div_ck@52c {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&gfx_fclk_clksel_ck>;
@@ -561,14 +561,14 @@
 		ti,max-div = <2>;
 	};
 
-	sysclkout_pre_ck: sysclkout_pre_ck {
+	sysclkout_pre_ck: sysclkout_pre_ck@700 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&clk_32768_ck>, <&l3_gclk>, <&dpll_ddr_m2_ck>, <&dpll_per_m2_ck>, <&lcd_gclk>;
 		reg = <0x0700>;
 	};
 
-	clkout2_div_ck: clkout2_div_ck {
+	clkout2_div_ck: clkout2_div_ck@700 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&sysclkout_pre_ck>;
@@ -577,7 +577,7 @@
 		reg = <0x0700>;
 	};
 
-	dbg_sysclk_ck: dbg_sysclk_ck {
+	dbg_sysclk_ck: dbg_sysclk_ck@414 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_clkin_ck>;
@@ -585,7 +585,7 @@
 		reg = <0x0414>;
 	};
 
-	dbg_clka_ck: dbg_clka_ck {
+	dbg_clka_ck: dbg_clka_ck@414 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&dpll_core_m4_ck>;
@@ -593,7 +593,7 @@
 		reg = <0x0414>;
 	};
 
-	stm_pmd_clock_mux_ck: stm_pmd_clock_mux_ck {
+	stm_pmd_clock_mux_ck: stm_pmd_clock_mux_ck@414 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&dbg_sysclk_ck>, <&dbg_clka_ck>;
@@ -601,7 +601,7 @@
 		reg = <0x0414>;
 	};
 
-	trace_pmd_clk_mux_ck: trace_pmd_clk_mux_ck {
+	trace_pmd_clk_mux_ck: trace_pmd_clk_mux_ck@414 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&dbg_sysclk_ck>, <&dbg_clka_ck>;
@@ -609,7 +609,7 @@
 		reg = <0x0414>;
 	};
 
-	stm_clk_div_ck: stm_clk_div_ck {
+	stm_clk_div_ck: stm_clk_div_ck@414 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&stm_pmd_clock_mux_ck>;
@@ -619,7 +619,7 @@
 		ti,index-power-of-two;
 	};
 
-	trace_clk_div_ck: trace_clk_div_ck {
+	trace_clk_div_ck: trace_clk_div_ck@414 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&trace_pmd_clk_mux_ck>;
@@ -629,7 +629,7 @@
 		ti,index-power-of-two;
 	};
 
-	clkout2_ck: clkout2_ck {
+	clkout2_ck: clkout2_ck@700 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&clkout2_div_ck>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/am33xx.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/am33xx.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/am33xx.dtsi	2016-05-15 19:44:35.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/am33xx.dtsi	2016-07-24 18:37:58.000000000 -0400
@@ -688,7 +688,7 @@
 				status = "disabled";
 			};
 
-			ehrpwm0: ehrpwm@48300200 {
+			ehrpwm0: pwm@48300200 {
 				compatible = "ti,am33xx-ehrpwm";
 				#pwm-cells = <3>;
 				reg = <0x48300200 0x80>;
@@ -718,7 +718,7 @@
 				status = "disabled";
 			};
 
-			ehrpwm1: ehrpwm@48302200 {
+			ehrpwm1: pwm@48302200 {
 				compatible = "ti,am33xx-ehrpwm";
 				#pwm-cells = <3>;
 				reg = <0x48302200 0x80>;
@@ -748,7 +748,7 @@
 				status = "disabled";
 			};
 
-			ehrpwm2: ehrpwm@48304200 {
+			ehrpwm2: pwm@48304200 {
 				compatible = "ti,am33xx-ehrpwm";
 				#pwm-cells = <3>;
 				reg = <0x48304200 0x80>;
@@ -868,6 +868,8 @@
 			#size-cells = <1>;
 			interrupt-controller;
 			#interrupt-cells = <2>;
+			gpio-controller;
+			#gpio-cells = <2>;
 			status = "disabled";
 		};
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/am35xx-clocks.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/am35xx-clocks.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/am35xx-clocks.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/am35xx-clocks.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -8,7 +8,7 @@
  * published by the Free Software Foundation.
  */
 &scm_clocks {
-	emac_ick: emac_ick {
+	emac_ick: emac_ick@32c {
 		#clock-cells = <0>;
 		compatible = "ti,am35xx-gate-clock";
 		clocks = <&ipss_ick>;
@@ -16,7 +16,7 @@
 		ti,bit-shift = <1>;
 	};
 
-	emac_fck: emac_fck {
+	emac_fck: emac_fck@32c {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&rmii_ck>;
@@ -24,7 +24,7 @@
 		ti,bit-shift = <9>;
 	};
 
-	vpfe_ick: vpfe_ick {
+	vpfe_ick: vpfe_ick@32c {
 		#clock-cells = <0>;
 		compatible = "ti,am35xx-gate-clock";
 		clocks = <&ipss_ick>;
@@ -32,7 +32,7 @@
 		ti,bit-shift = <2>;
 	};
 
-	vpfe_fck: vpfe_fck {
+	vpfe_fck: vpfe_fck@32c {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&pclk_ck>;
@@ -40,7 +40,7 @@
 		ti,bit-shift = <10>;
 	};
 
-	hsotgusb_ick_am35xx: hsotgusb_ick_am35xx {
+	hsotgusb_ick_am35xx: hsotgusb_ick_am35xx@32c {
 		#clock-cells = <0>;
 		compatible = "ti,am35xx-gate-clock";
 		clocks = <&ipss_ick>;
@@ -48,7 +48,7 @@
 		ti,bit-shift = <0>;
 	};
 
-	hsotgusb_fck_am35xx: hsotgusb_fck_am35xx {
+	hsotgusb_fck_am35xx: hsotgusb_fck_am35xx@32c {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_ck>;
@@ -56,7 +56,7 @@
 		ti,bit-shift = <8>;
 	};
 
-	hecc_ck: hecc_ck {
+	hecc_ck: hecc_ck@32c {
 		#clock-cells = <0>;
 		compatible = "ti,am35xx-gate-clock";
 		clocks = <&sys_ck>;
@@ -65,7 +65,7 @@
 	};
 };
 &cm_clocks {
-	ipss_ick: ipss_ick {
+	ipss_ick: ipss_ick@a10 {
 		#clock-cells = <0>;
 		compatible = "ti,am35xx-interface-clock";
 		clocks = <&core_l3_ick>;
@@ -85,7 +85,7 @@
 		clock-frequency = <27000000>;
 	};
 
-	uart4_ick_am35xx: uart4_ick_am35xx {
+	uart4_ick_am35xx: uart4_ick_am35xx@a10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&core_l4_ick>;
@@ -93,7 +93,7 @@
 		ti,bit-shift = <23>;
 	};
 
-	uart4_fck_am35xx: uart4_fck_am35xx {
+	uart4_fck_am35xx: uart4_fck_am35xx@a00 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&core_48m_fck>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/am4372.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/am4372.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/am4372.dtsi	2016-05-15 19:44:38.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/am4372.dtsi	2016-07-24 18:38:01.000000000 -0400
@@ -679,7 +679,7 @@
 				status = "disabled";
 			};
 
-			ehrpwm0: ehrpwm@48300200 {
+			ehrpwm0: pwm@48300200 {
 				compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm";
 				#pwm-cells = <3>;
 				reg = <0x48300200 0x80>;
@@ -705,7 +705,7 @@
 				status = "disabled";
 			};
 
-			ehrpwm1: ehrpwm@48302200 {
+			ehrpwm1: pwm@48302200 {
 				compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm";
 				#pwm-cells = <3>;
 				reg = <0x48302200 0x80>;
@@ -731,7 +731,7 @@
 				status = "disabled";
 			};
 
-			ehrpwm2: ehrpwm@48304200 {
+			ehrpwm2: pwm@48304200 {
 				compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm";
 				#pwm-cells = <3>;
 				reg = <0x48304200 0x80>;
@@ -749,7 +749,7 @@
 			ti,hwmods = "epwmss3";
 			status = "disabled";
 
-			ehrpwm3: ehrpwm@48306200 {
+			ehrpwm3: pwm@48306200 {
 				compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm";
 				#pwm-cells = <3>;
 				reg = <0x48306200 0x80>;
@@ -767,7 +767,7 @@
 			ti,hwmods = "epwmss4";
 			status = "disabled";
 
-			ehrpwm4: ehrpwm@48308200 {
+			ehrpwm4: pwm@48308200 {
 				compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm";
 				#pwm-cells = <3>;
 				reg = <0x48308200 0x80>;
@@ -785,7 +785,7 @@
 			ti,hwmods = "epwmss5";
 			status = "disabled";
 
-			ehrpwm5: ehrpwm@4830a200 {
+			ehrpwm5: pwm@4830a200 {
 				compatible = "ti,am4372-ehrpwm","ti,am33xx-ehrpwm";
 				#pwm-cells = <3>;
 				reg = <0x4830a200 0x80>;
@@ -896,6 +896,8 @@
 			#size-cells = <1>;
 			interrupt-controller;
 			#interrupt-cells = <2>;
+			gpio-controller;
+			#gpio-cells = <2>;
 			status = "disabled";
 		};
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/am437x-gp-evm.dts linux-libre-4.7-gnu/arch/arm/boot/dts/am437x-gp-evm.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/am437x-gp-evm.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/am437x-gp-evm.dts	2016-07-24 15:23:50.000000000 -0400
@@ -119,7 +119,7 @@
 		clock-frequency = <32768>;
 	};
 
-	sound0: sound@0 {
+	sound0: sound0 {
 		compatible = "simple-audio-card";
 		simple-audio-card,name = "AM437x-GP-EVM";
 		simple-audio-card,widgets =
@@ -817,6 +817,7 @@
 		interrupt-parent = <&gpmc>;
 		interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
 			     <1 IRQ_TYPE_NONE>;	/* termcount */
+		rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>;	/* gpmc_wait0 */
 		ti,nand-ecc-opt = "bch16";
 		ti,elm-id = <&elm>;
 		nand-bus-width = <8>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/am437x-sk-evm.dts linux-libre-4.7-gnu/arch/arm/boot/dts/am437x-sk-evm.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/am437x-sk-evm.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/am437x-sk-evm.dts	2016-07-24 15:23:50.000000000 -0400
@@ -418,7 +418,7 @@
 	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&i2c0_pins>;
-	clock-frequency = <400000>;
+	clock-frequency = <100000>;
 
 	tps@24 {
 		compatible = "ti,tps65218";
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/am43x-epos-evm.dts linux-libre-4.7-gnu/arch/arm/boot/dts/am43x-epos-evm.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/am43x-epos-evm.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/am43x-epos-evm.dts	2016-07-24 15:23:50.000000000 -0400
@@ -107,7 +107,7 @@
 		default-brightness-level = <8>;
 	};
 
-	sound0: sound@0 {
+	sound0: sound0 {
 		compatible = "simple-audio-card";
 		simple-audio-card,name = "AM43-EPOS-EVM";
 		simple-audio-card,widgets =
@@ -568,6 +568,7 @@
 		interrupt-parent = <&gpmc>;
 		interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
 			     <1 IRQ_TYPE_NONE>;	/* termcount */
+		rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>;	/* gpmc_wait0 */
 		ti,nand-ecc-opt = "bch16";
 		ti,elm-id = <&elm>;
 		nand-bus-width = <8>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/am43xx-clocks.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/am43xx-clocks.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/am43xx-clocks.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/am43xx-clocks.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -8,7 +8,7 @@
  * published by the Free Software Foundation.
  */
 &scm_clocks {
-	sys_clkin_ck: sys_clkin_ck {
+	sys_clkin_ck: sys_clkin_ck@40 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sysboot_freq_sel_ck>, <&crystal_freq_sel_ck>;
@@ -16,7 +16,7 @@
 		reg = <0x0040>;
 	};
 
-	crystal_freq_sel_ck: crystal_freq_sel_ck {
+	crystal_freq_sel_ck: crystal_freq_sel_ck@40 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&virt_19200000_ck>, <&virt_24000000_ck>, <&virt_25000000_ck>, <&virt_26000000_ck>;
@@ -104,7 +104,7 @@
 		clock-div = <1>;
 	};
 
-	ehrpwm0_tbclk: ehrpwm0_tbclk {
+	ehrpwm0_tbclk: ehrpwm0_tbclk@664 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&l4ls_gclk>;
@@ -112,7 +112,7 @@
 		reg = <0x0664>;
 	};
 
-	ehrpwm1_tbclk: ehrpwm1_tbclk {
+	ehrpwm1_tbclk: ehrpwm1_tbclk@664 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&l4ls_gclk>;
@@ -120,7 +120,7 @@
 		reg = <0x0664>;
 	};
 
-	ehrpwm2_tbclk: ehrpwm2_tbclk {
+	ehrpwm2_tbclk: ehrpwm2_tbclk@664 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&l4ls_gclk>;
@@ -128,7 +128,7 @@
 		reg = <0x0664>;
 	};
 
-	ehrpwm3_tbclk: ehrpwm3_tbclk {
+	ehrpwm3_tbclk: ehrpwm3_tbclk@664 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&l4ls_gclk>;
@@ -136,7 +136,7 @@
 		reg = <0x0664>;
 	};
 
-	ehrpwm4_tbclk: ehrpwm4_tbclk {
+	ehrpwm4_tbclk: ehrpwm4_tbclk@664 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&l4ls_gclk>;
@@ -144,7 +144,7 @@
 		reg = <0x0664>;
 	};
 
-	ehrpwm5_tbclk: ehrpwm5_tbclk {
+	ehrpwm5_tbclk: ehrpwm5_tbclk@664 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&l4ls_gclk>;
@@ -195,7 +195,7 @@
 		clock-frequency = <26000000>;
 	};
 
-	dpll_core_ck: dpll_core_ck {
+	dpll_core_ck: dpll_core_ck@2d20 {
 		#clock-cells = <0>;
 		compatible = "ti,am3-dpll-core-clock";
 		clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
@@ -208,7 +208,7 @@
 		clocks = <&dpll_core_ck>;
 	};
 
-	dpll_core_m4_ck: dpll_core_m4_ck {
+	dpll_core_m4_ck: dpll_core_m4_ck@2d38 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_core_x2_ck>;
@@ -219,7 +219,7 @@
 		ti,invert-autoidle-bit;
 	};
 
-	dpll_core_m5_ck: dpll_core_m5_ck {
+	dpll_core_m5_ck: dpll_core_m5_ck@2d3c {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_core_x2_ck>;
@@ -230,7 +230,7 @@
 		ti,invert-autoidle-bit;
 	};
 
-	dpll_core_m6_ck: dpll_core_m6_ck {
+	dpll_core_m6_ck: dpll_core_m6_ck@2d40 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_core_x2_ck>;
@@ -241,14 +241,14 @@
 		ti,invert-autoidle-bit;
 	};
 
-	dpll_mpu_ck: dpll_mpu_ck {
+	dpll_mpu_ck: dpll_mpu_ck@2d60 {
 		#clock-cells = <0>;
 		compatible = "ti,am3-dpll-clock";
 		clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
 		reg = <0x2d60>, <0x2d64>, <0x2d6c>;
 	};
 
-	dpll_mpu_m2_ck: dpll_mpu_m2_ck {
+	dpll_mpu_m2_ck: dpll_mpu_m2_ck@2d70 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_mpu_ck>;
@@ -267,14 +267,14 @@
 		clock-div = <2>;
 	};
 
-	dpll_ddr_ck: dpll_ddr_ck {
+	dpll_ddr_ck: dpll_ddr_ck@2da0 {
 		#clock-cells = <0>;
 		compatible = "ti,am3-dpll-clock";
 		clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
 		reg = <0x2da0>, <0x2da4>, <0x2dac>;
 	};
 
-	dpll_ddr_m2_ck: dpll_ddr_m2_ck {
+	dpll_ddr_m2_ck: dpll_ddr_m2_ck@2db0 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_ddr_ck>;
@@ -285,14 +285,14 @@
 		ti,invert-autoidle-bit;
 	};
 
-	dpll_disp_ck: dpll_disp_ck {
+	dpll_disp_ck: dpll_disp_ck@2e20 {
 		#clock-cells = <0>;
 		compatible = "ti,am3-dpll-clock";
 		clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
 		reg = <0x2e20>, <0x2e24>, <0x2e2c>;
 	};
 
-	dpll_disp_m2_ck: dpll_disp_m2_ck {
+	dpll_disp_m2_ck: dpll_disp_m2_ck@2e30 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_disp_ck>;
@@ -304,14 +304,14 @@
 		ti,set-rate-parent;
 	};
 
-	dpll_per_ck: dpll_per_ck {
+	dpll_per_ck: dpll_per_ck@2de0 {
 		#clock-cells = <0>;
 		compatible = "ti,am3-dpll-j-type-clock";
 		clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
 		reg = <0x2de0>, <0x2de4>, <0x2dec>;
 	};
 
-	dpll_per_m2_ck: dpll_per_m2_ck {
+	dpll_per_m2_ck: dpll_per_m2_ck@2df0 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_per_ck>;
@@ -354,7 +354,7 @@
 		clock-div = <732>;
 	};
 
-	clkdiv32k_ick: clkdiv32k_ick {
+	clkdiv32k_ick: clkdiv32k_ick@2a38 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&clkdiv32k_ck>;
@@ -370,7 +370,7 @@
 		clock-div = <1>;
 	};
 
-	pruss_ocp_gclk: pruss_ocp_gclk {
+	pruss_ocp_gclk: pruss_ocp_gclk@4248 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sysclk_div>, <&dpll_disp_m2_ck>;
@@ -383,56 +383,56 @@
 		clock-frequency = <32768>;
 	};
 
-	timer1_fck: timer1_fck {
+	timer1_fck: timer1_fck@4200 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin_ck>, <&clkdiv32k_ick>, <&tclkin_ck>, <&clk_rc32k_ck>, <&clk_32768_ck>, <&clk_32k_tpm_ck>;
 		reg = <0x4200>;
 	};
 
-	timer2_fck: timer2_fck {
+	timer2_fck: timer2_fck@4204 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>;
 		reg = <0x4204>;
 	};
 
-	timer3_fck: timer3_fck {
+	timer3_fck: timer3_fck@4208 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>;
 		reg = <0x4208>;
 	};
 
-	timer4_fck: timer4_fck {
+	timer4_fck: timer4_fck@420c {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>;
 		reg = <0x420c>;
 	};
 
-	timer5_fck: timer5_fck {
+	timer5_fck: timer5_fck@4210 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>;
 		reg = <0x4210>;
 	};
 
-	timer6_fck: timer6_fck {
+	timer6_fck: timer6_fck@4214 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>;
 		reg = <0x4214>;
 	};
 
-	timer7_fck: timer7_fck {
+	timer7_fck: timer7_fck@4218 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>;
 		reg = <0x4218>;
 	};
 
-	wdt1_fck: wdt1_fck {
+	wdt1_fck: wdt1_fck@422c {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&clk_rc32k_ck>, <&clkdiv32k_ick>;
@@ -487,14 +487,14 @@
 		clock-div = <2>;
 	};
 
-	cpsw_cpts_rft_clk: cpsw_cpts_rft_clk {
+	cpsw_cpts_rft_clk: cpsw_cpts_rft_clk@4238 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sysclk_div>, <&dpll_core_m5_ck>, <&dpll_disp_m2_ck>;
 		reg = <0x4238>;
 	};
 
-	dpll_clksel_mac_clk: dpll_clksel_mac_clk {
+	dpll_clksel_mac_clk: dpll_clksel_mac_clk@4234 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_core_m5_ck>;
@@ -509,14 +509,14 @@
 		clock-frequency = <32768>;
 	};
 
-	gpio0_dbclk_mux_ck: gpio0_dbclk_mux_ck {
+	gpio0_dbclk_mux_ck: gpio0_dbclk_mux_ck@4240 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&clk_rc32k_ck>, <&clk_32768_ck>, <&clkdiv32k_ick>, <&clk_32k_mosc_ck>, <&clk_32k_tpm_ck>;
 		reg = <0x4240>;
 	};
 
-	gpio0_dbclk: gpio0_dbclk {
+	gpio0_dbclk: gpio0_dbclk@2b68 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&gpio0_dbclk_mux_ck>;
@@ -524,7 +524,7 @@
 		reg = <0x2b68>;
 	};
 
-	gpio1_dbclk: gpio1_dbclk {
+	gpio1_dbclk: gpio1_dbclk@8c78 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&clkdiv32k_ick>;
@@ -532,7 +532,7 @@
 		reg = <0x8c78>;
 	};
 
-	gpio2_dbclk: gpio2_dbclk {
+	gpio2_dbclk: gpio2_dbclk@8c80 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&clkdiv32k_ick>;
@@ -540,7 +540,7 @@
 		reg = <0x8c80>;
 	};
 
-	gpio3_dbclk: gpio3_dbclk {
+	gpio3_dbclk: gpio3_dbclk@8c88 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&clkdiv32k_ick>;
@@ -548,7 +548,7 @@
 		reg = <0x8c88>;
 	};
 
-	gpio4_dbclk: gpio4_dbclk {
+	gpio4_dbclk: gpio4_dbclk@8c90 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&clkdiv32k_ick>;
@@ -556,7 +556,7 @@
 		reg = <0x8c90>;
 	};
 
-	gpio5_dbclk: gpio5_dbclk {
+	gpio5_dbclk: gpio5_dbclk@8c98 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&clkdiv32k_ick>;
@@ -572,7 +572,7 @@
 		clock-div = <2>;
 	};
 
-	gfx_fclk_clksel_ck: gfx_fclk_clksel_ck {
+	gfx_fclk_clksel_ck: gfx_fclk_clksel_ck@423c {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sysclk_div>, <&dpll_per_m2_ck>;
@@ -580,7 +580,7 @@
 		reg = <0x423c>;
 	};
 
-	gfx_fck_div_ck: gfx_fck_div_ck {
+	gfx_fck_div_ck: gfx_fck_div_ck@423c {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&gfx_fclk_clksel_ck>;
@@ -588,7 +588,7 @@
 		ti,max-div = <2>;
 	};
 
-	disp_clk: disp_clk {
+	disp_clk: disp_clk@4244 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&dpll_disp_m2_ck>, <&dpll_core_m5_ck>, <&dpll_per_m2_ck>;
@@ -596,14 +596,14 @@
 		ti,set-rate-parent;
 	};
 
-	dpll_extdev_ck: dpll_extdev_ck {
+	dpll_extdev_ck: dpll_extdev_ck@2e60 {
 		#clock-cells = <0>;
 		compatible = "ti,am3-dpll-clock";
 		clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
 		reg = <0x2e60>, <0x2e64>, <0x2e6c>;
 	};
 
-	dpll_extdev_m2_ck: dpll_extdev_m2_ck {
+	dpll_extdev_m2_ck: dpll_extdev_m2_ck@2e70 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_extdev_ck>;
@@ -614,14 +614,14 @@
 		ti,invert-autoidle-bit;
 	};
 
-	mux_synctimer32k_ck: mux_synctimer32k_ck {
+	mux_synctimer32k_ck: mux_synctimer32k_ck@4230 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&clk_32768_ck>, <&clk_32k_tpm_ck>, <&clkdiv32k_ick>;
 		reg = <0x4230>;
 	};
 
-	synctimer_32kclk: synctimer_32kclk {
+	synctimer_32kclk: synctimer_32kclk@2a30 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&mux_synctimer32k_ck>;
@@ -629,28 +629,28 @@
 		reg = <0x2a30>;
 	};
 
-	timer8_fck: timer8_fck {
+	timer8_fck: timer8_fck@421c {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>, <&clk_32k_tpm_ck>;
 		reg = <0x421c>;
 	};
 
-	timer9_fck: timer9_fck {
+	timer9_fck: timer9_fck@4220 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>, <&clk_32k_tpm_ck>;
 		reg = <0x4220>;
 	};
 
-	timer10_fck: timer10_fck {
+	timer10_fck: timer10_fck@4224 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>, <&clk_32k_tpm_ck>;
 		reg = <0x4224>;
 	};
 
-	timer11_fck: timer11_fck {
+	timer11_fck: timer11_fck@4228 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&tclkin_ck>, <&sys_clkin_ck>, <&clkdiv32k_ick>, <&clk_32k_tpm_ck>;
@@ -679,7 +679,7 @@
 		clocks = <&dpll_ddr_ck>;
 	};
 
-	dpll_ddr_m4_ck: dpll_ddr_m4_ck {
+	dpll_ddr_m4_ck: dpll_ddr_m4_ck@2db8 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_ddr_x2_ck>;
@@ -690,7 +690,7 @@
 		ti,invert-autoidle-bit;
 	};
 
-	dpll_per_clkdcoldo: dpll_per_clkdcoldo {
+	dpll_per_clkdcoldo: dpll_per_clkdcoldo@2e14 {
 		#clock-cells = <0>;
 		compatible = "ti,fixed-factor-clock";
 		clocks = <&dpll_per_ck>;
@@ -701,7 +701,7 @@
 		ti,invert-autoidle-bit;
 	};
 
-	dll_aging_clk_div: dll_aging_clk_div {
+	dll_aging_clk_div: dll_aging_clk_div@4250 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&sys_clkin_ck>;
@@ -733,14 +733,14 @@
 		clock-div = <2>;
 	};
 
-	usbphy_32khz_clkmux: usbphy_32khz_clkmux {
+	usbphy_32khz_clkmux: usbphy_32khz_clkmux@4260 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&clk_32768_ck>, <&clk_32k_tpm_ck>;
 		reg = <0x4260>;
 	};
 
-	usb_phy0_always_on_clk32k: usb_phy0_always_on_clk32k {
+	usb_phy0_always_on_clk32k: usb_phy0_always_on_clk32k@2a40 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&usbphy_32khz_clkmux>;
@@ -748,7 +748,7 @@
 		reg = <0x2a40>;
 	};
 
-	usb_phy1_always_on_clk32k: usb_phy1_always_on_clk32k {
+	usb_phy1_always_on_clk32k: usb_phy1_always_on_clk32k@2a48 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&usbphy_32khz_clkmux>;
@@ -756,7 +756,7 @@
 		reg = <0x2a48>;
 	};
 
-	usb_otg_ss0_refclk960m: usb_otg_ss0_refclk960m {
+	usb_otg_ss0_refclk960m: usb_otg_ss0_refclk960m@8a60 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&dpll_per_clkdcoldo>;
@@ -764,11 +764,65 @@
 		reg = <0x8a60>;
 	};
 
-	usb_otg_ss1_refclk960m: usb_otg_ss1_refclk960m {
+	usb_otg_ss1_refclk960m: usb_otg_ss1_refclk960m@8a68 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&dpll_per_clkdcoldo>;
 		ti,bit-shift = <8>;
 		reg = <0x8a68>;
 	};
+
+	clkout1_osc_div_ck: clkout1_osc_div_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&sys_clkin_ck>;
+		ti,bit-shift = <20>;
+		ti,max-div = <4>;
+		reg = <0x4100>;
+	};
+
+	clkout1_src2_mux_ck: clkout1_src2_mux_ck {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&clk_rc32k_ck>, <&sysclk_div>, <&dpll_ddr_m2_ck>,
+			 <&dpll_per_m2_ck>, <&dpll_disp_m2_ck>,
+			 <&dpll_mpu_m2_ck>;
+		reg = <0x4100>;
+	};
+
+	clkout1_src2_pre_div_ck: clkout1_src2_pre_div_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&clkout1_src2_mux_ck>;
+		ti,bit-shift = <4>;
+		ti,max-div = <8>;
+		reg = <0x4100>;
+	};
+
+	clkout1_src2_post_div_ck: clkout1_src2_post_div_ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&clkout1_src2_pre_div_ck>;
+		ti,bit-shift = <8>;
+		ti,max-div = <32>;
+		ti,index-power-of-two;
+		reg = <0x4100>;
+	};
+
+	clkout1_mux_ck: clkout1_mux_ck {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&clkout1_osc_div_ck>, <&clk_rc32k_ck>,
+			 <&clkout1_src2_post_div_ck>, <&dpll_extdev_m2_ck>;
+		ti,bit-shift = <16>;
+		reg = <0x4100>;
+	};
+
+	clkout1_ck: clkout1_ck {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&clkout1_mux_ck>;
+		ti,bit-shift = <23>;
+		reg = <0x4100>;
+	};
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/am572x-idk.dts linux-libre-4.7-gnu/arch/arm/boot/dts/am572x-idk.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/am572x-idk.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/am572x-idk.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/dts-v1/;
+
+#include "dra74x.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include "am57xx-idk-common.dtsi"
+
+/ {
+	model = "TI AM5728 IDK";
+	compatible = "ti,am5728-idk", "ti,am5728", "ti,dra742", "ti,dra74",
+		     "ti,dra7";
+
+	memory {
+		device_type = "memory";
+		reg = <0x0 0x80000000 0x0 0x80000000>;
+	};
+
+	extcon_usb2: extcon_usb2 {
+		compatible = "linux,extcon-usb-gpio";
+		id-gpio = <&gpio3 16 GPIO_ACTIVE_HIGH>;
+	};
+
+	status-leds {
+		compatible = "gpio-leds";
+		cpu0-led {
+			label = "status0:red:cpu0";
+			gpios = <&gpio4 0 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+			linux,default-trigger = "cpu0";
+		};
+
+		usr0-led {
+			label = "status0:green:usr";
+			gpios = <&gpio3 11 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		heartbeat-led {
+			label = "status0:blue:heartbeat";
+			gpios = <&gpio3 12 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+			linux,default-trigger = "heartbeat";
+		};
+
+		cpu1-led {
+			label = "status1:red:cpu1";
+			gpios = <&gpio3 10 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+			linux,default-trigger = "cpu1";
+		};
+
+		usr1-led {
+			label = "status1:green:usr";
+			gpios = <&gpio7 23 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		mmc0-led {
+			label = "status1:blue:mmc0";
+			gpios = <&gpio7 22 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+			linux,default-trigger = "mmc0";
+		};
+	};
+};
+
+&omap_dwc3_2 {
+	extcon = <&extcon_usb2>;
+};
+
+&mmc1 {
+	status = "okay";
+	vmmc-supply = <&v3_3d>;
+	vmmc_aux-supply = <&ldo1_reg>;
+	bus-width = <4>;
+	cd-gpios = <&gpio6 27 0>; /* gpio 219 */
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/am57xx-beagle-x15.dts linux-libre-4.7-gnu/arch/arm/boot/dts/am57xx-beagle-x15.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/am57xx-beagle-x15.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/am57xx-beagle-x15.dts	2016-07-24 15:23:50.000000000 -0400
@@ -8,6 +8,7 @@
 /dts-v1/;
 
 #include "dra74x.dtsi"
+#include "am57xx-commercial-grade.dtsi"
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 
@@ -144,7 +145,7 @@
 		};
 	};
 
-	sound0: sound@0 {
+	sound0: sound0 {
 		compatible = "simple-audio-card";
 		simple-audio-card,name = "BeagleBoard-X15";
 		simple-audio-card,widgets =
@@ -166,8 +167,6 @@
 
 		sound0_master: simple-audio-card,codec {
 			sound-dai = <&tlv320aic3104>;
-			assigned-clocks = <&clkoutmux2_clk_mux>;
-			assigned-clock-parents = <&sys_clk2_dclk_div>;
 			clocks = <&clkout2_clk>;
 		};
 	};
@@ -427,7 +426,7 @@
 					/* VDD_DSPEVE, VDD_IVA, VDD_GPU */
 					regulator-name = "smps45";
 					regulator-min-microvolt = < 850000>;
-					regulator-max-microvolt = <1150000>;
+					regulator-max-microvolt = <1250000>;
 					regulator-always-on;
 					regulator-boot-on;
 				};
@@ -436,7 +435,7 @@
 					/* VDD_CORE */
 					regulator-name = "smps6";
 					regulator-min-microvolt = <850000>;
-					regulator-max-microvolt = <1030000>;
+					regulator-max-microvolt = <1150000>;
 					regulator-always-on;
 					regulator-boot-on;
 				};
@@ -571,6 +570,9 @@
 		pinctrl-names = "default", "sleep";
 		pinctrl-0 = <&clkout2_pins_default>;
 		pinctrl-1 = <&clkout2_pins_sleep>;
+		assigned-clocks = <&clkoutmux2_clk_mux>;
+		assigned-clock-parents = <&sys_clk2_dclk_div>;
+
 		status = "okay";
 		adc-settle-ms = <40>;
 
@@ -795,6 +797,8 @@
 	serial-dir = <	/* 0: INACTIVE, 1: TX, 2: RX */
 		1 2 0 0
 	>;
+	tx-num-evt = <32>;
+	rx-num-evt = <32>;
 };
 
 &mailbox5 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/am57xx-cl-som-am57x.dts linux-libre-4.7-gnu/arch/arm/boot/dts/am57xx-cl-som-am57x.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/am57xx-cl-som-am57x.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/am57xx-cl-som-am57x.dts	2016-07-24 15:23:50.000000000 -0400
@@ -51,7 +51,7 @@
 		regulator-max-microvolt = <3300000>;
 	};
 
-	sound0: sound@0 {
+	sound0: sound0 {
 		compatible = "simple-audio-card";
 		simple-audio-card,name = "CL-SOM-AM57x-Sound-Card";
 		simple-audio-card,format = "i2s";
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/am57xx-commercial-grade.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/am57xx-commercial-grade.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/am57xx-commercial-grade.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/am57xx-commercial-grade.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,23 @@
+&cpu_alert0 {
+	temperature = <80000>; /* milliCelsius */
+};
+
+&cpu_crit {
+	temperature = <90000>; /* milliCelsius */
+};
+
+&gpu_crit {
+	temperature = <90000>; /* milliCelsius */
+};
+
+&core_crit {
+	temperature = <90000>; /* milliCelsius */
+};
+
+&dspeve_crit {
+	temperature = <90000>; /* milliCelsius */
+};
+
+&iva_crit {
+	temperature = <90000>; /* milliCelsius */
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/am57xx-idk-common.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/am57xx-idk-common.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/am57xx-idk-common.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/am57xx-idk-common.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "am57xx-industrial-grade.dtsi"
+
+/ {
+	aliases {
+		rtc0 = &tps659038_rtc;
+		rtc1 = &rtc;
+	};
+
+	vmain: fixedregulator-vmain {
+		compatible = "regulator-fixed";
+		regulator-name = "VMAIN";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	v3_3d: fixedregulator-v3_3d {
+		compatible = "regulator-fixed";
+		regulator-name = "V3_3D";
+		vin-supply = <&smps9_reg>;
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	vtt_fixed: fixedregulator-vtt {
+		/* TPS51200 */
+		compatible = "regulator-fixed";
+		regulator-name = "vtt_fixed";
+		vin-supply = <&v3_3d>;
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+};
+
+&i2c1 {
+	status = "okay";
+	clock-frequency = <400000>;
+
+	tps659038: tps659038@58 {
+		compatible = "ti,tps659038";
+		reg = <0x58>;
+		interrupts-extended = <&gpio6 16 IRQ_TYPE_LEVEL_HIGH
+			       &dra7_pmx_core 0x418>;
+		#interrupt-cells = <2>;
+		interrupt-controller;
+		ti,system-power-controller;
+
+		tps659038_pmic {
+			compatible = "ti,tps659038-pmic";
+
+			smps12-in-supply = <&vmain>;
+			smps3-in-supply = <&vmain>;
+			smps45-in-supply = <&vmain>;
+			smps6-in-supply = <&vmain>;
+			smps7-in-supply = <&vmain>;
+			smps8-in-supply = <&vmain>;
+			smps9-in-supply = <&vmain>;
+			ldo1-in-supply = <&vmain>;
+			ldo2-in-supply = <&vmain>;
+			ldo3-in-supply = <&vmain>;
+			ldo4-in-supply = <&vmain>;
+			ldo9-in-supply = <&vmain>;
+			ldoln-in-supply = <&vmain>;
+			ldousb-in-supply = <&vmain>;
+			ldortc-in-supply = <&vmain>;
+
+			regulators {
+				smps12_reg: smps12 {
+					/* VDD_MPU */
+					regulator-name = "smps12";
+					regulator-min-microvolt = <850000>;
+					regulator-max-microvolt = <1250000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				smps3_reg: smps3 {
+					/* VDD_DDR EMIF1 EMIF2 */
+					regulator-name = "smps3";
+					regulator-min-microvolt = <1350000>;
+					regulator-max-microvolt = <1350000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				smps45_reg: smps45 {
+					/* VDD_DSPEVE on AM572 */
+					/* VDD_IVA + VDD_DSP on AM571 */
+					regulator-name = "smps45";
+					regulator-min-microvolt = <850000>;
+					regulator-max-microvolt = <1250000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				smps6_reg: smps6 {
+					/* VDD_GPU */
+					regulator-name = "smps6";
+					regulator-min-microvolt = <850000>;
+					regulator-max-microvolt = <1250000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				smps7_reg: smps7 {
+					/* VDD_CORE */
+					regulator-name = "smps7";
+					regulator-min-microvolt = <850000>;
+					regulator-max-microvolt = <1150000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				smps8_reg: smps8 {
+					/* 5728 - VDD_IVAHD */
+					/* 5718 - N.C. test point */
+					regulator-name = "smps8";
+				};
+
+				smps9_reg: smps9 {
+					/* VDD_3_3D */
+					regulator-name = "smps9";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				ldo1_reg: ldo1 {
+					/* VDDSHV8 - VSDMMC  */
+					/* NOTE: on rev 1.3a, data supply */
+					regulator-name = "ldo1";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-boot-on;
+					regulator-always-on;
+				};
+
+				ldo2_reg: ldo2 {
+					/* VDDSH18V */
+					regulator-name = "ldo2";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				ldo3_reg: ldo3 {
+					/* R1.3a 572x V1_8PHY_LDO3: USB, SATA */
+					regulator-name = "ldo3";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				ldo4_reg: ldo4 {
+					/* R1.3a 572x V1_8PHY_LDO4: PCIE, HDMI*/
+					regulator-name = "ldo4";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				/* LDO5-8 unused */
+
+				ldo9_reg: ldo9 {
+					/* VDD_RTC  */
+					regulator-name = "ldo9";
+					regulator-min-microvolt = <840000>;
+					regulator-max-microvolt = <1160000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				ldoln_reg: ldoln {
+					/* VDDA_1V8_PLL */
+					regulator-name = "ldoln";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				ldousb_reg: ldousb {
+					/* VDDA_3V_USB: VDDA_USBHS33 */
+					regulator-name = "ldousb";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				ldortc_reg: ldortc {
+					/* VDDA_RTC  */
+					regulator-name = "ldortc";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				regen1: regen1 {
+					/* VDD_3V3_ON */
+					regulator-name = "regen1";
+					regulator-boot-on;
+					regulator-always-on;
+				};
+
+				regen2: regen2 {
+					/* Needed for PMIC internal resource */
+					regulator-name = "regen2";
+					regulator-boot-on;
+					regulator-always-on;
+				};
+			};
+		};
+
+		tps659038_rtc: tps659038_rtc {
+			compatible = "ti,palmas-rtc";
+			interrupt-parent = <&tps659038>;
+			interrupts = <8 IRQ_TYPE_EDGE_FALLING>;
+			wakeup-source;
+		};
+
+		tps659038_pwr_button: tps659038_pwr_button {
+			compatible = "ti,palmas-pwrbutton";
+			interrupt-parent = <&tps659038>;
+			interrupts = <1 IRQ_TYPE_EDGE_FALLING>;
+			wakeup-source;
+			ti,palmas-long-press-seconds = <12>;
+		};
+
+		tps659038_gpio: tps659038_gpio {
+			compatible = "ti,palmas-gpio";
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+	};
+};
+
+&uart3 {
+	status = "okay";
+	interrupts-extended = <&crossbar_mpu GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH
+			       &dra7_pmx_core 0x248>;
+};
+
+&rtc {
+	status = "okay";
+	ext-clk-src;
+};
+
+&mac {
+	status = "okay";
+	dual_emac;
+};
+
+&cpsw_emac0 {
+	phy_id = <&davinci_mdio>, <0>;
+	phy-mode = "rgmii";
+	dual_emac_res_vlan = <1>;
+};
+
+&cpsw_emac1 {
+	phy_id = <&davinci_mdio>, <1>;
+	phy-mode = "rgmii";
+	dual_emac_res_vlan = <2>;
+};
+
+&usb2_phy1 {
+	phy-supply = <&ldousb_reg>;
+};
+
+&usb2_phy2 {
+	phy-supply = <&ldousb_reg>;
+};
+
+&usb1 {
+	dr_mode = "host";
+};
+
+&usb2 {
+	dr_mode = "otg";
+};
+
+&mmc2 {
+	status = "okay";
+	vmmc-supply = <&v3_3d>;
+	bus-width = <8>;
+	ti,non-removable;
+	max-frequency = <96000000>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/am57xx-industrial-grade.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/am57xx-industrial-grade.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/am57xx-industrial-grade.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/am57xx-industrial-grade.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,23 @@
+&cpu_alert0 {
+	temperature = <90000>; /* milliCelsius */
+};
+
+&cpu_crit {
+	temperature = <105000>; /* milliCelsius */
+};
+
+&gpu_crit {
+	temperature = <105000>; /* milliCelsius */
+};
+
+&core_crit {
+	temperature = <105000>; /* milliCelsius */
+};
+
+&dspeve_crit {
+	temperature = <105000>; /* milliCelsius */
+};
+
+&iva_crit {
+	temperature = <105000>; /* milliCelsius */
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/armada-385-linksys.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/armada-385-linksys.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/armada-385-linksys.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/armada-385-linksys.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -58,8 +58,8 @@
 	soc {
 		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000
 			  MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000
-			  MBUS_ID(0x09, 0x09) 0 0xf1100000 0x10000
-			  MBUS_ID(0x09, 0x05) 0 0xf1110000 0x10000>;
+			  MBUS_ID(0x09, 0x19) 0 0xf1100000 0x10000
+			  MBUS_ID(0x09, 0x15) 0 0xf1110000 0x10000>;
 
 		internal-regs {
 
@@ -245,7 +245,7 @@
 		button@2 {
 			label = "Factory Reset Button";
 			linux,code = <KEY_RESTART>;
-			gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
+			gpios = <&gpio0 29 GPIO_ACTIVE_LOW>;
 		};
 	};
 
@@ -260,7 +260,7 @@
 		};
 
 		sata {
-			gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>;
+			gpios = <&gpio1 22 GPIO_ACTIVE_LOW>;
 			default-state = "off";
 		};
 	};
@@ -313,7 +313,7 @@
 
 &pinctrl {
 	keys_pin: keys-pin {
-		marvell,pins = "mpp24", "mpp47";
+		marvell,pins = "mpp24", "mpp29";
 		marvell,function = "gpio";
 	};
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/armada-xp-linksys-mamba.dts linux-libre-4.7-gnu/arch/arm/boot/dts/armada-xp-linksys-mamba.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/armada-xp-linksys-mamba.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/armada-xp-linksys-mamba.dts	2016-07-24 15:23:50.000000000 -0400
@@ -304,13 +304,13 @@
 		button@1 {
 			label = "WPS";
 			linux,code = <KEY_WPS_BUTTON>;
-			gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>;
+			gpios = <&gpio1 0 GPIO_ACTIVE_LOW>;
 		};
 
 		button@2 {
 			label = "Factory Reset Button";
 			linux,code = <KEY_RESTART>;
-			gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>;
+			gpios = <&gpio1 1 GPIO_ACTIVE_LOW>;
 		};
 	};
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/arm-realview-eb-11mp.dts linux-libre-4.7-gnu/arch/arm/boot/dts/arm-realview-eb-11mp.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/arm-realview-eb-11mp.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/arm-realview-eb-11mp.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2016 Linaro Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "arm-realview-eb-mp.dtsi"
+
+/ {
+	model = "ARM RealView Emulation Baseboard with ARM11MPCore Rev C";
+	arm,hbi = <0x146>;
+
+	/*
+	 * This is the ARM11 MPCore tile (HBI-0146) used with the RealView EB.
+	 * Reference: ARM DUI 0318F
+	 *
+	 * To run this machine with QEMU, specify the following:
+	 * qemu-system-arm -M realview-eb-mpcore -smp cpus=4
+	 */
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		enable-method = "arm,realview-smp";
+
+		MP11_0: cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,arm11mpcore";
+			reg = <0>;
+			next-level-cache = <&L2>;
+		};
+
+		MP11_1: cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,arm11mpcore";
+			reg = <1>;
+			next-level-cache = <&L2>;
+		};
+
+		MP11_2: cpu@2 {
+			device_type = "cpu";
+			compatible = "arm,arm11mpcore";
+			reg = <2>;
+			next-level-cache = <&L2>;
+		};
+
+		MP11_3: cpu@3 {
+			device_type = "cpu";
+			compatible = "arm,arm11mpcore";
+			reg = <3>;
+			next-level-cache = <&L2>;
+		};
+	};
+};
+
+&pmu {
+	interrupt-affinity = <&MP11_0>, <&MP11_1>, <&MP11_2>, <&MP11_3>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/arm-realview-eb-11mp-revb.dts linux-libre-4.7-gnu/arch/arm/boot/dts/arm-realview-eb-11mp-revb.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/arm-realview-eb-11mp-revb.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/arm-realview-eb-11mp-revb.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2016 Linaro Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "arm-realview-eb-11mp.dts"
+
+/ {
+	model = "ARM RealView Emulation Baseboard with ARM11MPCore Rev B";
+};
+
+/*
+ * The revision B has a distinctly different layout of the syscon, so
+ * append a specific compatible-string.
+ */
+&syscon {
+	compatible = "arm,realview-eb11mp-revb-syscon", "arm,realview-eb-syscon", "syscon", "simple-mfd";
+};
+
+&intc {
+	reg = <0x10101000 0x1000>,
+	      <0x10100100 0x100>;
+};
+
+&L2 {
+	reg = <0x10102000 0x1000>;
+};
+
+&scu {
+	reg = <0x10100000 0x100>;
+};
+
+&twd_timer {
+	reg = <0x10100600 0x20>;
+};
+
+&twd_wdog {
+	reg = <0x10100620 0x20>;
+};
+
+/*
+ * On revision B, we cannot reach the secondary interrupt
+ * controller, as a result, some peripherals that are dependent
+ * on their IRQ cannot be reached, so disable them.
+ */
+&intc_second {
+	status = "disabled";
+};
+
+&gpio0 {
+	status = "disabled";
+};
+
+&gpio1 {
+	status = "disabled";
+};
+
+&gpio2 {
+	status = "disabled";
+};
+
+&serial2 {
+	status = "disabled";
+};
+
+&serial3 {
+	status = "disabled";
+};
+
+&ssp {
+	status = "disabled";
+};
+
+&wdog {
+	status = "disabled";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/arm-realview-eb-a9mp.dts linux-libre-4.7-gnu/arch/arm/boot/dts/arm-realview-eb-a9mp.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/arm-realview-eb-a9mp.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/arm-realview-eb-a9mp.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2016 Linaro Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "arm-realview-eb-mp.dtsi"
+
+/ {
+	model = "ARM RealView EB Cortex A9 MPCore";
+
+	/*
+	 * This is the Cortex A9 MPCore tile used with the
+	 * RealView EB.
+	 */
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		enable-method = "arm,realview-smp";
+
+		A9_0: cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <0>;
+			next-level-cache = <&L2>;
+		};
+
+		A9_1: cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <1>;
+			next-level-cache = <&L2>;
+		};
+
+		A9_2: cpu@2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <2>;
+			next-level-cache = <&L2>;
+		};
+
+		A9_3: cpu@3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <3>;
+			next-level-cache = <&L2>;
+		};
+	};
+};
+
+&pmu {
+	interrupt-affinity = <&A9_0>, <&A9_1>, <&A9_2>, <&A9_3>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/arm-realview-eb.dts linux-libre-4.7-gnu/arch/arm/boot/dts/arm-realview-eb.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/arm-realview-eb.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/arm-realview-eb.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2016 Linaro Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/gpio/gpio.h>
+#include "arm-realview-eb.dtsi"
+
+/ {
+	model = "ARM RealView Emulation Baseboard";
+	compatible = "arm,realview-eb";
+	arm,hbi = <0x140>;
+
+	/*
+	 * This is the core tile with the CPU and GIC etc for the
+	 * ARM926EJ-S, ARM1136, ARM1176 that does not have L2 cache
+	 * or PMU.
+	 *
+	 * To run this machine with QEMU, specify the following:
+	 * qemu-system-arm -M realview-eb
+	 * Unless specified, QEMU will emulate an ARM926EJ-S core tile.
+	 * Switches -cpu arm1136 or -cpu arm1176 emulates the other
+	 * core tiles.
+	 */
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "arm,realview-eb-soc", "simple-bus";
+		regmap = <&syscon>;
+		ranges;
+
+		intc: interrupt-controller@10040000 {
+			compatible = "arm,pl390";
+			#interrupt-cells = <3>;
+			#address-cells = <1>;
+			interrupt-controller;
+			reg = <0x10041000 0x1000>,
+			      <0x10040000 0x100>;
+		};
+	};
+};
+
+/*
+ * This adapts all the peripherals to the interrupt routing
+ * to the GIC on the core tile.
+ */
+
+&ethernet {
+	interrupt-parent = <&intc>;
+	interrupts = <0 28 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&usb {
+	interrupt-parent = <&intc>;
+	interrupts = <0 29 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&aaci {
+	interrupt-parent = <&intc>;
+	interrupts = <0 19 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&mmc {
+	interrupt-parent = <&intc>;
+	interrupts = <0 17 IRQ_TYPE_LEVEL_HIGH>,
+			<0 18 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&kmi0 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 20 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&kmi1 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 21 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&charlcd {
+	interrupt-parent = <&intc>;
+	interrupts = <0 22 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&serial0 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 12 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&serial1 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 13 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&serial2 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 14 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&serial3 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 15 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&ssp {
+	interrupt-parent = <&intc>;
+	interrupts = <0 11 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&wdog {
+	interrupt-parent = <&intc>;
+	interrupts = <0 0 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&timer01 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 4 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&timer23 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 5 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&gpio0 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 6 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&gpio1 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 7 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&gpio2 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 8 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&rtc {
+	interrupt-parent = <&intc>;
+	interrupts = <0 10 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&clcd {
+	interrupt-parent = <&intc>;
+	interrupts = <0 23 IRQ_TYPE_LEVEL_HIGH>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/arm-realview-eb.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/arm-realview-eb.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/arm-realview-eb.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/arm-realview-eb.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,453 @@
+/*
+ * Copyright 2016 Linaro Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/gpio/gpio.h>
+#include "skeleton.dtsi"
+
+/ {
+	compatible = "arm,realview-eb";
+
+	chosen { };
+
+	aliases {
+		serial0 = &serial0;
+		serial1 = &serial1;
+		serial2 = &serial2;
+		serial3 = &serial3;
+		i2c0 = &i2c;
+	};
+
+	memory {
+		/* 128 MiB memory @ 0x0 */
+		reg = <0x00000000 0x08000000>;
+	};
+
+	/* The voltage to the MMC card is hardwired at 3.3V */
+	vmmc: fixedregulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "vmmc";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+        };
+
+	veth: fixedregulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "veth";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+	};
+
+	xtal24mhz: xtal24mhz@24M {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+	};
+
+	timclk: timclk@1M {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clock-div = <24>;
+		clock-mult = <1>;
+		clocks = <&xtal24mhz>;
+	};
+
+	mclk: mclk@24M {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clock-div = <1>;
+		clock-mult = <1>;
+		clocks = <&xtal24mhz>;
+	};
+
+	kmiclk: kmiclk@24M {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clock-div = <1>;
+		clock-mult = <1>;
+		clocks = <&xtal24mhz>;
+	};
+
+	sspclk: sspclk@24M {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clock-div = <1>;
+		clock-mult = <1>;
+		clocks = <&xtal24mhz>;
+	};
+
+	uartclk: uartclk@24M {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clock-div = <1>;
+		clock-mult = <1>;
+		clocks = <&xtal24mhz>;
+	};
+
+	wdogclk: wdogclk@24M {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clock-div = <1>;
+		clock-mult = <1>;
+		clocks = <&xtal24mhz>;
+	};
+
+	/* FIXME: this actually hangs off the PLL clocks */
+	pclk: pclk@0 {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <0>;
+	};
+
+	flash0@40000000 {
+		/* 2 * 32MiB NOR Flash memory */
+		compatible = "arm,versatile-flash", "cfi-flash";
+		reg = <0x40000000 0x04000000>;
+		bank-width = <4>;
+	};
+
+	flash1@44000000 {
+		/* 2 * 32MiB NOR Flash memory */
+		compatible = "arm,versatile-flash", "cfi-flash";
+		reg = <0x44000000 0x04000000>;
+		bank-width = <4>;
+	};
+
+	/* SMSC 9118 ethernet with PHY and EEPROM */
+	ethernet: ethernet@4e000000 {
+		compatible = "smsc,lan9118", "smsc,lan9115";
+		reg = <0x4e000000 0x10000>;
+		phy-mode = "mii";
+		reg-io-width = <4>;
+		smsc,irq-active-high;
+		smsc,irq-push-pull;
+		vdd33a-supply = <&veth>;
+		vddvario-supply = <&veth>;
+	};
+
+	usb: usb@4f000000 {
+		compatible = "nxp,usb-isp1761";
+		reg = <0x4f000000 0x20000>;
+		port1-otg;
+	};
+
+	/* These peripherals are inside the FPGA */
+	fpga {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		ranges;
+
+		syscon: syscon@10000000 {
+			compatible = "arm,realview-eb-syscon", "syscon", "simple-mfd";
+			reg = <0x10000000 0x1000>;
+
+			led@08.0 {
+				compatible = "register-bit-led";
+				offset = <0x08>;
+				mask = <0x01>;
+				label = "versatile:0";
+				linux,default-trigger = "heartbeat";
+				default-state = "on";
+			};
+			led@08.1 {
+				compatible = "register-bit-led";
+				offset = <0x08>;
+				mask = <0x02>;
+				label = "versatile:1";
+				linux,default-trigger = "mmc0";
+				default-state = "off";
+			};
+			led@08.2 {
+				compatible = "register-bit-led";
+				offset = <0x08>;
+				mask = <0x04>;
+				label = "versatile:2";
+				linux,default-trigger = "cpu0";
+				default-state = "off";
+			};
+			led@08.3 {
+				compatible = "register-bit-led";
+				offset = <0x08>;
+				mask = <0x08>;
+				label = "versatile:3";
+				default-state = "off";
+			};
+			led@08.4 {
+				compatible = "register-bit-led";
+				offset = <0x08>;
+				mask = <0x10>;
+				label = "versatile:4";
+				default-state = "off";
+			};
+			led@08.5 {
+				compatible = "register-bit-led";
+				offset = <0x08>;
+				mask = <0x20>;
+				label = "versatile:5";
+				default-state = "off";
+			};
+			led@08.6 {
+				compatible = "register-bit-led";
+				offset = <0x08>;
+				mask = <0x40>;
+				label = "versatile:6";
+				default-state = "off";
+			};
+			led@08.7 {
+				compatible = "register-bit-led";
+				offset = <0x08>;
+				mask = <0x80>;
+				label = "versatile:7";
+				default-state = "off";
+			};
+			oscclk0: osc0@0c {
+				compatible = "arm,syscon-icst307";
+				#clock-cells = <0>;
+				lock-offset = <0x20>;
+				vco-offset = <0x0C>;
+				clocks = <&xtal24mhz>;
+			};
+			oscclk1: osc1@10 {
+				compatible = "arm,syscon-icst307";
+				#clock-cells = <0>;
+				lock-offset = <0x20>;
+				vco-offset = <0x10>;
+				clocks = <&xtal24mhz>;
+			};
+			oscclk2: osc2@14 {
+				compatible = "arm,syscon-icst307";
+				#clock-cells = <0>;
+				lock-offset = <0x20>;
+				vco-offset = <0x14>;
+				clocks = <&xtal24mhz>;
+			};
+			oscclk3: osc3@18 {
+				compatible = "arm,syscon-icst307";
+				#clock-cells = <0>;
+				lock-offset = <0x20>;
+				vco-offset = <0x18>;
+				clocks = <&xtal24mhz>;
+			};
+			oscclk4: osc4@1c {
+				compatible = "arm,syscon-icst307";
+				#clock-cells = <0>;
+				lock-offset = <0x20>;
+				vco-offset = <0x1c>;
+				clocks = <&xtal24mhz>;
+			};
+		};
+
+		i2c: i2c@10002000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "arm,versatile-i2c";
+			reg = <0x10002000 0x1000>;
+
+			rtc@68 {
+				compatible = "dallas,ds1338";
+				reg = <0x68>;
+			};
+		};
+
+		aaci: aaci@10004000 {
+			compatible = "arm,pl041", "arm,primecell";
+			reg = <0x10004000 0x1000>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
+		};
+
+		mmc: mmcsd@10005000 {
+			compatible = "arm,pl18x", "arm,primecell";
+			reg = <0x10005000 0x1000>;
+
+			/* Due to frequent FIFO overruns, use just 500 kHz */
+			max-frequency = <500000>;
+			bus-width = <4>;
+			cap-sd-highspeed;
+			cap-mmc-highspeed;
+			clocks = <&mclk>, <&pclk>;
+			clock-names = "mclk", "apb_pclk";
+			vmmc-supply = <&vmmc>;
+			cd-gpios = <&gpio1 0 GPIO_ACTIVE_LOW>;
+			wp-gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>;
+		};
+
+		kmi0: kmi@10006000 {
+			compatible = "arm,pl050", "arm,primecell";
+			reg = <0x10006000 0x1000>;
+			clocks = <&kmiclk>, <&pclk>;
+			clock-names = "KMIREFCLK", "apb_pclk";
+		};
+
+		kmi1: kmi@10007000 {
+			compatible = "arm,pl050", "arm,primecell";
+			reg = <0x10007000 0x1000>;
+			clocks = <&kmiclk>, <&pclk>;
+			clock-names = "KMIREFCLK", "apb_pclk";
+		};
+
+		charlcd: fpga_charlcd: charlcd@10008000 {
+			compatible = "arm,versatile-lcd";
+			reg = <0x10008000 0x1000>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
+		};
+
+		serial0: serial@10009000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0x10009000 0x1000>;
+			clocks = <&uartclk>, <&pclk>;
+			clock-names = "uartclk", "apb_pclk";
+		};
+
+		serial1: serial@1000a000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0x1000a000 0x1000>;
+			clocks = <&uartclk>, <&pclk>;
+			clock-names = "uartclk", "apb_pclk";
+		};
+
+		serial2: serial@1000b000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0x1000b000 0x1000>;
+			clocks = <&uartclk>, <&pclk>;
+			clock-names = "uartclk", "apb_pclk";
+		};
+
+		serial3: serial@1000c000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0x1000c000 0x1000>;
+			clocks = <&uartclk>, <&pclk>;
+			clock-names = "uartclk", "apb_pclk";
+		};
+
+		ssp: ssp@1000d000 {
+			compatible = "arm,pl022", "arm,primecell";
+			reg = <0x1000d000 0x1000>;
+			clocks = <&sspclk>, <&pclk>;
+			clock-names = "SSPCLK", "apb_pclk";
+		};
+
+		wdog: watchdog@10010000 {
+			compatible = "arm,sp805", "arm,primecell";
+			reg = <0x10010000 0x1000>;
+			clocks = <&wdogclk>, <&pclk>;
+			clock-names = "wdogclk", "apb_pclk";
+			status = "disabled";
+		};
+
+		timer01: timer@10011000 {
+			compatible = "arm,sp804", "arm,primecell";
+			reg = <0x10011000 0x1000>;
+			clocks = <&timclk>, <&timclk>, <&pclk>;
+			clock-names = "timer1", "timer2", "apb_pclk";
+		};
+
+		timer23: timer@10012000 {
+			compatible = "arm,sp804", "arm,primecell";
+			reg = <0x10012000 0x1000>;
+			clocks = <&timclk>, <&timclk>, <&pclk>;
+			clock-names = "timer1", "timer2", "apb_pclk";
+		};
+
+		gpio0: gpio@10013000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0x10013000 0x1000>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio1: gpio@10014000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0x10014000 0x1000>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio2: gpio@10015000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0x10015000 0x1000>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
+		};
+
+		rtc: rtc@10017000 {
+			compatible = "arm,pl031", "arm,primecell";
+			reg = <0x10017000 0x1000>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
+		};
+
+		clcd: clcd@10020000 {
+			compatible = "arm,pl111", "arm,primecell";
+			reg = <0x10020000 0x1000>;
+			interrupt-names = "combined";
+			clocks = <&oscclk0>, <&pclk>;
+			clock-names = "clcdclk", "apb_pclk";
+
+			port {
+				clcd_pads: endpoint {
+					remote-endpoint = <&clcd_panel>;
+					arm,pl11x,tft-r0g0b0-pads = <0 8 16>;
+				};
+			};
+
+			panel {
+				compatible = "panel-dpi";
+
+				port {
+					clcd_panel: endpoint {
+						remote-endpoint = <&clcd_pads>;
+					};
+				};
+
+				/* Standard 640x480 VGA timings */
+				panel-timing {
+					clock-frequency = <25175000>;
+					hactive = <640>;
+					hback-porch = <48>;
+					hfront-porch = <16>;
+					hsync-len = <96>;
+					vactive = <480>;
+					vback-porch = <33>;
+					vfront-porch = <10>;
+					vsync-len = <2>;
+				};
+			};
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/arm-realview-eb-mp.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/arm-realview-eb-mp.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/arm-realview-eb-mp.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/arm-realview-eb-mp.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,225 @@
+/*
+ * Copyright 2016 Linaro Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/gpio/gpio.h>
+#include "arm-realview-eb.dtsi"
+
+/*
+ * This is the common include file for all MPCore variants of the
+ * Evaluation Baseboard, i.e. ARM11MPCore, ARM11MPCore Revision B
+ * and Cortex-A9 MPCore.
+ */
+/ {
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "arm,realview-eb-soc", "simple-bus";
+		regmap = <&syscon>;
+		ranges;
+
+		/* Primary interrupt controller in the test chip */
+		intc: interrupt-controller@1f000100 {
+			compatible = "arm,eb11mp-gic";
+			#interrupt-cells = <3>;
+			#address-cells = <1>;
+			interrupt-controller;
+			reg = <0x1f001000 0x1000>,
+			      <0x1f000100 0x100>;
+		};
+
+		/* Secondary interrupt controller on the FPGA */
+		intc_second: interrupt-controller@10040000 {
+			compatible = "arm,pl390";
+			#interrupt-cells = <3>;
+			#address-cells = <1>;
+			interrupt-controller;
+			reg = <0x10041000 0x1000>,
+			      <0x10040000 0x100>;
+			interrupt-parent = <&intc>;
+			interrupts = <0 10 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		L2: l2-cache {
+			compatible = "arm,l220-cache";
+			reg = <0x1f002000 0x1000>;
+			interrupt-parent = <&intc>;
+			interrupts = <0 29 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 30 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 31 IRQ_TYPE_LEVEL_HIGH>;
+			cache-unified;
+			cache-level = <2>;
+			/*
+			 * Override default cache size, sets and
+			 * associativity as these may be erroneously set
+			 * up by boot loader(s), probably for safety
+			 * since th outer sync operation can cause the
+			 * cache to hang unless disabled.
+			 */
+			cache-size = <1048576>; // 1MB
+			cache-sets = <4096>;
+			cache-line-size = <32>;
+			arm,shared-override;
+			arm,parity-enable;
+			arm,outer-sync-disable;
+		};
+
+		scu: scu@1f000000 {
+			compatible = "arm,arm11mp-scu";
+			reg = <0x1f000000 0x100>;
+		};
+
+		twd_timer: timer@1f000600 {
+			compatible = "arm,arm11mp-twd-timer";
+			reg = <0x1f000600 0x20>;
+			interrupt-parent = <&intc>;
+			interrupts = <1 13 0xf04>;
+		};
+
+		twd_wdog: watchdog@1f000620 {
+			compatible = "arm,arm11mp-twd-wdt";
+			reg = <0x1f000620 0x20>;
+			interrupt-parent = <&intc>;
+			interrupts = <1 14 0xf04>;
+		};
+
+		/* PMU with one IRQ line per core */
+		pmu: pmu@0 {
+			compatible = "arm,arm11mpcore-pmu";
+			interrupt-parent = <&intc>;
+			interrupts = <0 17 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 18 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 19 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 20 IRQ_TYPE_LEVEL_HIGH>;
+		};
+	};
+};
+
+/*
+ * This adapts all the peripherals to the interrupt routing
+ * to the GIC on the core tile.
+ */
+
+&ethernet {
+	interrupt-parent = <&intc>;
+	interrupts = <0 9 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&usb {
+	interrupt-parent = <&intc>;
+	interrupts = <0 3 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&aaci {
+	interrupt-parent = <&intc>;
+	interrupts = <0 0 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&mmc {
+	interrupt-parent = <&intc>;
+	interrupts = <0 14 IRQ_TYPE_LEVEL_HIGH>,
+			<0 15 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&kmi0 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 7 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&kmi1 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 8 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&charlcd {
+	interrupt-parent = <&intc>;
+	interrupts = <0  IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&serial0 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 4 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&serial1 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 5 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&timer01 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 1 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&timer23 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 2 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&rtc {
+	interrupt-parent = <&intc>;
+	interrupts = <0 6 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+/*
+ * On revision A, these peripherals does not have their IRQ lines
+ * routed to the core tile, but they can be reached on the secondary
+ * GIC.
+ */
+&gpio0 {
+	interrupt-parent = <&intc_second>;
+	interrupts = <0 6 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&gpio1 {
+	interrupt-parent = <&intc_second>;
+	interrupts = <0 7 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&gpio2 {
+	interrupt-parent = <&intc_second>;
+	interrupts = <0 8 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&serial2 {
+	interrupt-parent = <&intc_second>;
+	interrupts = <0 14 IRQ_TYPE_LEVEL_HIGH>;
+	status = "okay";
+};
+
+&serial3 {
+	interrupt-parent = <&intc_second>;
+	interrupts = <0 15 IRQ_TYPE_LEVEL_HIGH>;
+	status = "okay";
+};
+
+&ssp {
+	interrupt-parent = <&intc_second>;
+	interrupts = <0 11 IRQ_TYPE_LEVEL_HIGH>;
+	status = "okay";
+};
+
+&wdog {
+	interrupt-parent = <&intc_second>;
+	interrupts = <0 0 IRQ_TYPE_LEVEL_HIGH>;
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/arm-realview-pb1176.dts linux-libre-4.7-gnu/arch/arm/boot/dts/arm-realview-pb1176.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/arm-realview-pb1176.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/arm-realview-pb1176.dts	2016-07-24 15:23:50.000000000 -0400
@@ -394,6 +394,46 @@
 			reg = <0x10200000 0x4000>;
 			bank-width = <1>;
 		};
+
+		clcd@10112000 {
+			compatible = "arm,pl111", "arm,primecell";
+			reg = <0x10112000 0x1000>;
+			interrupt-parent = <&intc_dc1176>;
+			interrupt-names = "combined";
+			interrupts = <0 47 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&oscclk0>, <&pclk>;
+			clock-names = "clcdclk", "apb_pclk";
+
+			port {
+				clcd_pads: endpoint {
+					remote-endpoint = <&clcd_panel>;
+					arm,pl11x,tft-r0g0b0-pads = <0 8 16>;
+				};
+			};
+
+			panel {
+				compatible = "panel-dpi";
+
+				port {
+					clcd_panel: endpoint {
+						remote-endpoint = <&clcd_pads>;
+					};
+				};
+
+				/* Standard 640x480 VGA timings */
+				panel-timing {
+					clock-frequency = <25175000>;
+					hactive = <640>;
+					hback-porch = <48>;
+					hfront-porch = <16>;
+					hsync-len = <96>;
+					vactive = <480>;
+					vback-porch = <33>;
+					vfront-porch = <10>;
+					vsync-len = <2>;
+				};
+			};
+		};
 	};
 
 	/* These peripherals are inside the FPGA rather than the DevChip */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/arm-realview-pb11mp.dts linux-libre-4.7-gnu/arch/arm/boot/dts/arm-realview-pb11mp.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/arm-realview-pb11mp.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/arm-realview-pb11mp.dts	2016-07-24 15:23:50.000000000 -0400
@@ -627,16 +627,17 @@
 					};
 				};
 
+				/* Standard 640x480 VGA timings */
 				panel-timing {
-					clock-frequency = <63500127>;
-					hactive = <1024>;
-					hback-porch = <152>;
-					hfront-porch = <48>;
-					hsync-len = <104>;
-					vactive = <768>;
-					vback-porch = <23>;
-					vfront-porch = <3>;
-					vsync-len = <4>;
+					clock-frequency = <25175000>;
+					hactive = <640>;
+					hback-porch = <48>;
+					hfront-porch = <16>;
+					hsync-len = <96>;
+					vactive = <480>;
+					vback-porch = <33>;
+					vfront-porch = <10>;
+					vsync-len = <2>;
 				};
 			};
 		};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/arm-realview-pba8.dts linux-libre-4.7-gnu/arch/arm/boot/dts/arm-realview-pba8.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/arm-realview-pba8.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/arm-realview-pba8.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2016 Linaro Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "arm-realview-pbx.dtsi"
+
+/ {
+	model = "ARM RealView Platform Baseboard for Cortex-A8";
+	compatible = "arm,realview-pba8";
+	arm,hbi = <0x178>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		enable-method = "arm,realview-smp";
+
+		cpu0: cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a8";
+			reg = <0>;
+		};
+	};
+
+	pmu: pmu@0 {
+		compatible = "arm,cortex-a8-pmu";
+		interrupt-parent = <&intc>;
+		interrupts = <0 47 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-affinity = <&cpu0>;
+	};
+
+	/* Primary GIC PL390 interrupt controller in the test chip */
+	intc: interrupt-controller@1e000000 {
+		compatible = "arm,pl390";
+		#interrupt-cells = <3>;
+		#address-cells = <1>;
+		interrupt-controller;
+		reg = <0x1e001000 0x1000>,
+		      <0x1e000000 0x100>;
+	};
+};
+
+&ethernet {
+	interrupt-parent = <&intc>;
+	interrupts = <0 28 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&usb {
+	interrupt-parent = <&intc>;
+	interrupts = <0 29 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&soc {
+	compatible = "arm,realview-pba8-soc", "simple-bus";
+};
+
+&syscon {
+	compatible = "arm,realview-pba8-syscon", "syscon", "simple-mfd";
+};
+
+&serial0 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 12 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&serial1 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 13 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&serial2 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 14 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&serial3 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 15 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&ssp {
+	interrupt-parent = <&intc>;
+	interrupts = <0 11 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&wdog0 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 0 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&wdog1 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 40 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&timer01 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 4 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&timer23 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 5 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&gpio0 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 6 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&gpio1 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 7 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&gpio2 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 8 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&rtc {
+	interrupt-parent = <&intc>;
+	interrupts = <0 10 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&timer45 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&timer67 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 42 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&aaci {
+	interrupt-parent = <&intc>;
+	interrupts = <0 19 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&mmc {
+	interrupt-parent = <&intc>;
+	interrupts = <0 17 IRQ_TYPE_LEVEL_HIGH>,
+		     <0 18 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&kmi0 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 20 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&kmi1 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 21 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&clcd {
+	interrupt-parent = <&intc>;
+	interrupts = <0 23 IRQ_TYPE_LEVEL_HIGH>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/arm-realview-pbx-a9.dts linux-libre-4.7-gnu/arch/arm/boot/dts/arm-realview-pbx-a9.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/arm-realview-pbx-a9.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/arm-realview-pbx-a9.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,229 @@
+/*
+ * Copyright 2016 Linaro Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "arm-realview-pbx.dtsi"
+
+/ {
+	/*
+	 * This is the RealView Platform Baseboard Explore for Cortex-A9
+	 * (HBI0182 + HBI0183) as described in ARM DUI 0440B
+	 */
+	model = "ARM RealView Platform Baseboard Explore for Cortex-A9";
+	arm,hbi = <0x182>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		enable-method = "arm,realview-smp";
+
+		cpu-map {
+			cluster0 {
+				core0 {
+					cpu = <&CPU0>;
+				};
+				core1 {
+					cpu = <&CPU1>;
+				};
+			};
+		};
+		CPU0: cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <0x0>;
+			next-level-cache = <&L2>;
+		};
+		CPU1: cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <0x1>;
+			next-level-cache = <&L2>;
+		};
+	};
+
+	L2: l2-cache {
+		compatible = "arm,pl310-cache";
+		reg = <0x1f002000 0x1000>;
+		cache-unified;
+		cache-level = <2>;
+		/*
+		 * Override default cache size, sets and
+		 * associativity as these may be erroneously set
+		 * up by boot loader(s).
+		 */
+		cache-size = <1048576>; // 1MB
+		cache-sets = <4096>;
+		cache-line-size = <32>;
+		arm,parity-disable;
+		arm,tag-latency = <1>;
+		arm,data-latency = <1 1>;
+		arm,dirty-latency = <1>;
+	};
+
+	scu: scu@1f000000 {
+		compatible = "arm,cortex-a9-scu";
+		reg = <0x1f000000 0x100>;
+	};
+
+	twd_timer: timer@1f000600 {
+		compatible = "arm,cortex-a9-twd-timer";
+		reg = <0x1f000600 0x20>;
+		interrupt-parent = <&intc>;
+		interrupts = <1 13 0xf04>;
+	};
+
+	twd_wdog: watchdog@1f000620 {
+		compatible = "arm,cortex-a9-twd-wdt";
+		reg = <0x1f000620 0x20>;
+		interrupt-parent = <&intc>;
+		interrupts = <1 14 0xf04>;
+	};
+
+	pmu: pmu@0 {
+		compatible = "arm,cortex-a9-pmu";
+		interrupt-parent = <&intc>;
+		interrupts = <0 44 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 45 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-affinity = <&CPU0>, <&CPU1>;
+	};
+
+	/* Primary GIC PL390 interrupt controller in the test chip */
+	intc: interrupt-controller@1f000000 {
+		compatible = "arm,cortex-a9-gic";
+		#interrupt-cells = <3>;
+		#address-cells = <1>;
+		interrupt-controller;
+		reg = <0x1f001000 0x1000>,
+		      <0x1f000100 0x100>;
+	};
+};
+
+&ethernet {
+	interrupt-parent = <&intc>;
+	interrupts = <0 28 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&usb {
+	interrupt-parent = <&intc>;
+	interrupts = <0 29 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&serial0 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 12 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&serial1 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 13 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&serial2 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 14 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&serial3 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 15 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&ssp {
+	interrupt-parent = <&intc>;
+	interrupts = <0 11 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&wdog0 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 0 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&wdog1 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 40 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&timer01 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 4 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&timer23 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 5 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&gpio0 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 6 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&gpio1 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 7 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&gpio2 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 8 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&rtc {
+	interrupt-parent = <&intc>;
+	interrupts = <0 10 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&timer45 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&timer67 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 42 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&aaci {
+	interrupt-parent = <&intc>;
+	interrupts = <0 19 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&mmc {
+	interrupt-parent = <&intc>;
+	interrupts = <0 17 IRQ_TYPE_LEVEL_HIGH>,
+		     <0 18 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&kmi0 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 20 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&kmi1 {
+	interrupt-parent = <&intc>;
+	interrupts = <0 21 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&clcd {
+	interrupt-parent = <&intc>;
+	interrupts = <0 23 IRQ_TYPE_LEVEL_HIGH>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/arm-realview-pbx.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/arm-realview-pbx.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/arm-realview-pbx.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/arm-realview-pbx.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,542 @@
+/*
+ * Copyright 2016 Linaro Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/gpio/gpio.h>
+#include "skeleton.dtsi"
+
+/ {
+	compatible = "arm,realview-pbx";
+
+	chosen { };
+
+	aliases {
+		serial0 = &serial0;
+		serial1 = &serial1;
+		serial2 = &serial2;
+		serial3 = &serial3;
+		i2c0 = &i2c;
+	};
+
+	memory {
+		/* 128 MiB memory @ 0x0 */
+		reg = <0x00000000 0x08000000>;
+	};
+
+	/* The voltage to the MMC card is hardwired at 3.3V */
+	vmmc: fixedregulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "vmmc";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+        };
+
+	veth: fixedregulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "veth";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+	};
+
+	xtal24mhz: xtal24mhz@24M {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+	};
+
+	refclk32khz: refclk32khz {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <32768>;
+	};
+
+	timclk: timclk@1M {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clock-div = <24>;
+		clock-mult = <1>;
+		clocks = <&xtal24mhz>;
+	};
+
+	mclk: mclk@24M {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clock-div = <1>;
+		clock-mult = <1>;
+		clocks = <&xtal24mhz>;
+	};
+
+	kmiclk: kmiclk@24M {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clock-div = <1>;
+		clock-mult = <1>;
+		clocks = <&xtal24mhz>;
+	};
+
+	sspclk: sspclk@24M {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clock-div = <1>;
+		clock-mult = <1>;
+		clocks = <&xtal24mhz>;
+	};
+
+	uartclk: uartclk@24M {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clock-div = <1>;
+		clock-mult = <1>;
+		clocks = <&xtal24mhz>;
+	};
+
+	wdogclk: wdogclk@24M {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clock-div = <1>;
+		clock-mult = <1>;
+		clocks = <&xtal24mhz>;
+	};
+
+	/* FIXME: this actually hangs off the PLL clocks */
+	pclk: pclk@0 {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <0>;
+	};
+
+	flash0@40000000 {
+		/* 2 * 32MiB NOR Flash memory */
+		compatible = "arm,versatile-flash", "cfi-flash";
+		reg = <0x40000000 0x04000000>;
+		bank-width = <4>;
+	};
+
+	flash1@44000000 {
+		/* 2 * 32MiB NOR Flash memory */
+		compatible = "arm,versatile-flash", "cfi-flash";
+		reg = <0x44000000 0x04000000>;
+		bank-width = <4>;
+	};
+
+	/* SMSC 9118 ethernet with PHY and EEPROM */
+	ethernet: ethernet@4e000000 {
+		compatible = "smsc,lan9118", "smsc,lan9115";
+		reg = <0x4e000000 0x10000>;
+		phy-mode = "mii";
+		reg-io-width = <4>;
+		smsc,irq-active-high;
+		smsc,irq-push-pull;
+		vdd33a-supply = <&veth>;
+		vddvario-supply = <&veth>;
+	};
+
+	usb: usb@4f000000 {
+		compatible = "nxp,usb-isp1761";
+		reg = <0x4f000000 0x20000>;
+		port1-otg;
+	};
+
+	soc: soc@0 {
+		compatible = "arm,realview-pbx-soc", "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		regmap = <&syscon>;
+		ranges;
+
+		syscon: syscon@10000000 {
+			compatible = "arm,realview-pbx-syscon", "syscon", "simple-mfd";
+			reg = <0x10000000 0x1000>;
+
+			led@08.0 {
+				compatible = "register-bit-led";
+				offset = <0x08>;
+				mask = <0x01>;
+				label = "versatile:0";
+				linux,default-trigger = "heartbeat";
+				default-state = "on";
+			};
+			led@08.1 {
+				compatible = "register-bit-led";
+				offset = <0x08>;
+				mask = <0x02>;
+				label = "versatile:1";
+				linux,default-trigger = "mmc0";
+				default-state = "off";
+			};
+			led@08.2 {
+				compatible = "register-bit-led";
+				offset = <0x08>;
+				mask = <0x04>;
+				label = "versatile:2";
+				linux,default-trigger = "cpu0";
+				default-state = "off";
+			};
+			led@08.3 {
+				compatible = "register-bit-led";
+				offset = <0x08>;
+				mask = <0x08>;
+				label = "versatile:3";
+				default-state = "off";
+			};
+			led@08.4 {
+				compatible = "register-bit-led";
+				offset = <0x08>;
+				mask = <0x10>;
+				label = "versatile:4";
+				default-state = "off";
+			};
+			led@08.5 {
+				compatible = "register-bit-led";
+				offset = <0x08>;
+				mask = <0x20>;
+				label = "versatile:5";
+				default-state = "off";
+			};
+			led@08.6 {
+				compatible = "register-bit-led";
+				offset = <0x08>;
+				mask = <0x40>;
+				label = "versatile:6";
+				default-state = "off";
+			};
+			led@08.7 {
+				compatible = "register-bit-led";
+				offset = <0x08>;
+				mask = <0x80>;
+				label = "versatile:7";
+				default-state = "off";
+			};
+			oscclk0: osc0@0c {
+				compatible = "arm,syscon-icst307";
+				#clock-cells = <0>;
+				lock-offset = <0x20>;
+				vco-offset = <0x0C>;
+				clocks = <&xtal24mhz>;
+			};
+			oscclk1: osc1@10 {
+				compatible = "arm,syscon-icst307";
+				#clock-cells = <0>;
+				lock-offset = <0x20>;
+				vco-offset = <0x10>;
+				clocks = <&xtal24mhz>;
+			};
+			oscclk2: osc2@14 {
+				compatible = "arm,syscon-icst307";
+				#clock-cells = <0>;
+				lock-offset = <0x20>;
+				vco-offset = <0x14>;
+				clocks = <&xtal24mhz>;
+			};
+			oscclk3: osc3@18 {
+				compatible = "arm,syscon-icst307";
+				#clock-cells = <0>;
+				lock-offset = <0x20>;
+				vco-offset = <0x18>;
+				clocks = <&xtal24mhz>;
+			};
+			oscclk4: osc4@1c {
+				compatible = "arm,syscon-icst307";
+				#clock-cells = <0>;
+				lock-offset = <0x20>;
+				vco-offset = <0x1c>;
+				clocks = <&xtal24mhz>;
+			};
+		};
+
+		sp810_syscon0: sysctl@10001000 {
+			compatible = "arm,sp810", "arm,primecell";
+			reg = <0x10001000 0x1000>;
+			clocks = <&refclk32khz>, <&timclk>, <&xtal24mhz>;
+			clock-names = "refclk", "timclk", "apb_pclk";
+			#clock-cells = <1>;
+			clock-output-names = "timerclk0",
+					     "timerclk1",
+					     "timerclk2",
+					     "timerclk3";
+			assigned-clocks = <&sp810_syscon0 0>,
+					  <&sp810_syscon0 1>,
+					  <&sp810_syscon0 2>,
+					  <&sp810_syscon0 3>;
+			assigned-clock-parents = <&timclk>,
+					       <&timclk>,
+					       <&timclk>,
+					       <&timclk>;
+		};
+
+		i2c: i2c@10002000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "arm,versatile-i2c";
+			reg = <0x10002000 0x1000>;
+
+			rtc@68 {
+				compatible = "dallas,ds1338";
+				reg = <0x68>;
+			};
+		};
+
+		serial0: serial@10009000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0x10009000 0x1000>;
+			clocks = <&uartclk>, <&pclk>;
+			clock-names = "uartclk", "apb_pclk";
+		};
+
+		serial1: serial@1000a000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0x1000a000 0x1000>;
+			clocks = <&uartclk>, <&pclk>;
+			clock-names = "uartclk", "apb_pclk";
+		};
+
+		serial2: serial@1000b000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0x1000b000 0x1000>;
+			clocks = <&uartclk>, <&pclk>;
+			clock-names = "uartclk", "apb_pclk";
+		};
+
+		ssp: ssp@1000d000 {
+			compatible = "arm,pl022", "arm,primecell";
+			reg = <0x1000d000 0x1000>;
+			clocks = <&sspclk>, <&pclk>;
+			clock-names = "SSPCLK", "apb_pclk";
+		};
+
+		wdog0: watchdog@1000f000 {
+			compatible = "arm,sp805", "arm,primecell";
+			reg = <0x1000f000 0x1000>;
+			clocks = <&wdogclk>, <&pclk>;
+			clock-names = "wdogclk", "apb_pclk";
+			status = "disabled";
+		};
+
+		wdog1: watchdog@10010000 {
+			compatible = "arm,sp805", "arm,primecell";
+			reg = <0x10010000 0x1000>;
+			clocks = <&wdogclk>, <&pclk>;
+			clock-names = "wdogclk", "apb_pclk";
+			status = "disabled";
+		};
+
+		timer01: timer@10011000 {
+			compatible = "arm,sp804", "arm,primecell";
+			reg = <0x10011000 0x1000>;
+			clocks = <&sp810_syscon0 0>,
+			         <&sp810_syscon0 1>,
+				 <&pclk>;
+			clock-names = "timerclk0",
+				    "timerclk1",
+				    "apb_pclk";
+		};
+
+		timer23: timer@10012000 {
+			compatible = "arm,sp804", "arm,primecell";
+			reg = <0x10012000 0x1000>;
+			clocks = <&sp810_syscon0 2>,
+			         <&sp810_syscon0 3>,
+				 <&pclk>;
+			clock-names = "timerclk2",
+				    "timerclk3",
+				    "apb_pclk";
+		};
+
+		gpio0: gpio@10013000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0x10013000 0x1000>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio1: gpio@10014000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0x10014000 0x1000>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio2: gpio@10015000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0x10015000 0x1000>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
+		};
+
+		/* DVI serial bus control is at 10016000 */
+
+		rtc: rtc@10017000 {
+			compatible = "arm,pl031", "arm,primecell";
+			reg = <0x10017000 0x1000>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
+		};
+
+		timer45: timer@10018000 {
+			compatible = "arm,sp804", "arm,primecell";
+			reg = <0x10018000 0x1000>;
+			clocks = <&timclk>, <&timclk>, <&pclk>;
+			clock-names = "timerclk4", "timerclk5", "apb_pclk";
+		};
+
+		timer67: timer@10019000 {
+			compatible = "arm,sp804", "arm,primecell";
+			reg = <0x10019000 0x1000>;
+			clocks = <&timclk>, <&timclk>, <&pclk>;
+			clock-names = "timerclk6", "timerclk7", "apb_pclk";
+		};
+
+		sp810_syscon1: sysctl@1001a000 {
+			compatible = "arm,sp810", "arm,primecell";
+			reg = <0x1001a000 0x1000>;
+			clocks = <&refclk32khz>, <&timclk>, <&xtal24mhz>;
+			clock-names = "refclk", "timclk", "apb_pclk";
+			#clock-cells = <1>;
+			clock-output-names = "timerclk4",
+					     "timerclk5",
+					     "timerclk6",
+					     "timerclk7";
+			assigned-clocks = <&sp810_syscon1 0>,
+					  <&sp810_syscon1 1>,
+					  <&sp810_syscon1 2>,
+					  <&sp810_syscon1 3>;
+			assigned-clock-parents = <&timclk>,
+					       <&timclk>,
+					       <&timclk>,
+					       <&timclk>;
+		};
+	};
+
+
+	/* These peripherals are inside the FPGA */
+	fpga {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		ranges;
+
+		aaci: aaci@10004000 {
+			compatible = "arm,pl041", "arm,primecell";
+			reg = <0x10004000 0x1000>;
+			clocks = <&pclk>;
+			clock-names = "apb_pclk";
+		};
+
+		mmc: mmcsd@10005000 {
+			compatible = "arm,pl18x", "arm,primecell";
+			reg = <0x10005000 0x1000>;
+
+			/* Due to frequent FIFO overruns, use just 500 kHz */
+			max-frequency = <500000>;
+			bus-width = <4>;
+			cap-sd-highspeed;
+			cap-mmc-highspeed;
+			clocks = <&mclk>, <&pclk>;
+			clock-names = "mclk", "apb_pclk";
+			vmmc-supply = <&vmmc>;
+			cd-gpios = <&gpio2 0 GPIO_ACTIVE_LOW>;
+			wp-gpios = <&gpio2 1 GPIO_ACTIVE_HIGH>;
+		};
+
+		kmi0: kmi@10006000 {
+			compatible = "arm,pl050", "arm,primecell";
+			reg = <0x10006000 0x1000>;
+			clocks = <&kmiclk>, <&pclk>;
+			clock-names = "KMIREFCLK", "apb_pclk";
+		};
+
+		kmi1: kmi@10007000 {
+			compatible = "arm,pl050", "arm,primecell";
+			reg = <0x10007000 0x1000>;
+			clocks = <&kmiclk>, <&pclk>;
+			clock-names = "KMIREFCLK", "apb_pclk";
+		};
+
+		serial3: serial@1000c000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0x1000c000 0x1000>;
+			clocks = <&uartclk>, <&pclk>;
+			clock-names = "uartclk", "apb_pclk";
+		};
+	};
+
+	/* These peripherals are inside the NEC ISSP */
+	issp {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		ranges;
+
+		clcd: clcd@10020000 {
+			compatible = "arm,pl111", "arm,primecell";
+			reg = <0x10020000 0x1000>;
+			interrupt-names = "combined";
+			clocks = <&oscclk4>, <&pclk>;
+			clock-names = "clcdclk", "apb_pclk";
+
+			port {
+				clcd_pads: endpoint {
+					remote-endpoint = <&clcd_panel>;
+					arm,pl11x,tft-r0g0b0-pads = <0 8 16>;
+				};
+			};
+
+			panel {
+				compatible = "panel-dpi";
+
+				port {
+					clcd_panel: endpoint {
+						remote-endpoint = <&clcd_pads>;
+					};
+				};
+
+				/* Standard 640x480 VGA timings */
+				panel-timing {
+					clock-frequency = <25175000>;
+					hactive = <640>;
+					hback-porch = <48>;
+					hfront-porch = <16>;
+					hsync-len = <96>;
+					vactive = <480>;
+					vback-porch = <33>;
+					vfront-porch = <10>;
+					vsync-len = <2>;
+				};
+			};
+		};
+	};
+};
+
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/armv7-m.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/armv7-m.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/armv7-m.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/armv7-m.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -1,7 +1,7 @@
 #include "skeleton.dtsi"
 
 / {
-	nvic: nv-interrupt-controller  {
+	nvic: interrupt-controller@e000e100  {
 		compatible = "arm,armv7m-nvic";
 		interrupt-controller;
 		#interrupt-cells = <1>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/artpec6.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/artpec6.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/artpec6.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/artpec6.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -91,96 +91,32 @@
 		clock-frequency = <50000000>;
 	};
 
-	/* PLL1 is used by CPU and some peripherals */
-	pll1_clk: pll1_clk@f8000000 {
-		#clock-cells = <0>;
-		compatible = "axis,artpec6-pll1-clock";
-		reg = <0xf8000000 4>;
-		clocks = <&ext_clk>;
-	};
-
-	cpu_clk: cpu_clk {
-		#clock-cells = <0>;
-		compatible = "fixed-factor-clock";
-		clock-div = <1>;
-		clock-mult = <1>;
-		clocks = <&pll1_clk>;
-		clock-output-names = "cpu_clk";
-	};
-
-	cpu_clkdiv2: cpu_clkdiv2 {
-		#clock-cells = <0>;
-		compatible = "fixed-factor-clock";
-		clock-div = <2>;
-		clock-mult = <1>;
-		clocks = <&cpu_clk>;
-	};
-
-	cpu_clkdiv4: cpu_clkdiv4 {
-		#clock-cells = <0>;
-		compatible = "fixed-factor-clock";
-		clock-div = <4>;
-		clock-mult = <1>;
-		clocks = <&cpu_clk>;
-	};
-
-	apb_pclk: apb_pclk {
+	eth_phy_ref_clk: eth_phy_ref_clk {
 		#clock-cells = <0>;
-		compatible = "fixed-factor-clock";
-		clock-div = <8>;
-		clock-mult = <1>;
-		clocks = <&cpu_clk>;
-		clock-output-names = "apb_pclk";
+		compatible = "fixed-clock";
+		clock-frequency = <125000000>;
 	};
 
-	/* PLL2 is used by a number of peripherals, including UDL */
-	pll2: pll2 {
-		#clock-cells = <0>;
-		compatible = "fixed-factor-clock";
-		clock-div = <1>;
-		clock-mult = <24>;
+	clkctrl: clkctrl@0xf8000000 {
+		#clock-cells = <1>;
+		compatible = "axis,artpec6-clkctrl";
+		reg = <0xf8000000 0x48>;
 		clocks = <&ext_clk>;
+		clock-names = "sys_refclk";
 	};
 
-	/* PLL2DIV2 is used by the Fractional Clock Divider, for i2s */
-	pll2div2: pll2div2 {
-		#clock-cells = <0>;
-		compatible = "fixed-factor-clock";
-		clock-div = <2>;
-		clock-mult = <1>;
-		clocks = <&pll2>;
-	};
-
-	pll2div12: pll2div12 {
-		#clock-cells = <0>;
-		compatible = "fixed-factor-clock";
-		clock-div = <12>;
-		clock-mult = <1>;
-		clocks = <&pll2>;
-	};
-
-	pll2div24: pll2div24 {
-		#clock-cells = <0>;
-		compatible = "fixed-factor-clock";
-		clock-div = <24>;
-		clock-mult = <1>;
-		clocks = <&pll2>;
-		clock-output-names = "uart_clk";
-	};
-
-
 	gtimer@faf00200 {
 		compatible = "arm,cortex-a9-global-timer";
 		reg = <0xfaf00200 0x20>;
 		interrupts = <GIC_PPI 11 0xf01>;
-		clocks = <&cpu_clkdiv2>;
+		clocks = <&clkctrl 1>;
 	};
 
 	timer@faf00600 {
 		compatible = "arm,cortex-a9-twd-timer";
 		reg = <0xfaf00600 0x20>;
 		interrupts = <GIC_PPI 13 0xf04>;
-		clocks = <&cpu_clkdiv2>;
+		clocks = <&clkctrl 1>;
 		status = "disabled";
 	};
 
@@ -220,7 +156,8 @@
 
 		ethernet: ethernet@f8010000 {
 			clock-names = "phy_ref_clk", "apb_pclk";
-			clocks = <&ext_clk>, <&apb_pclk>;
+			clocks = <&eth_phy_ref_clk>,
+				<&clkctrl 4>;
 			compatible = "snps,dwc-qos-ethernet-4.10";
 			interrupt-parent = <&intc>;
 			interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
@@ -238,7 +175,8 @@
 			compatible = "arm,pl011", "arm,primecell";
 			reg = <0xf8036000 0x1000>;
 			interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&pll2div24>, <&apb_pclk>;
+			clocks = <&clkctrl 13>,
+				<&clkctrl 12>;
 			clock-names = "uart_clk", "apb_pclk";
 			status = "disabled";
 		};
@@ -246,7 +184,8 @@
 			compatible = "arm,pl011", "arm,primecell";
 			reg = <0xf8037000 0x1000>;
 			interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&pll2div24>, <&apb_pclk>;
+			clocks = <&clkctrl 13>,
+				<&clkctrl 12>;
 			clock-names = "uart_clk", "apb_pclk";
 			status = "disabled";
 		};
@@ -254,7 +193,8 @@
 			compatible = "arm,pl011", "arm,primecell";
 			reg = <0xf8038000 0x1000>;
 			interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&pll2div24>, <&apb_pclk>;
+			clocks = <&clkctrl 13>,
+				<&clkctrl 12>;
 			clock-names = "uart_clk", "apb_pclk";
 			status = "disabled";
 		};
@@ -262,7 +202,8 @@
 			compatible = "arm,pl011", "arm,primecell";
 			reg = <0xf8039000 0x1000>;
 			interrupts = <GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&pll2div24>, <&apb_pclk>;
+			clocks = <&clkctrl 13>,
+				<&clkctrl 12>;
 			clock-names = "uart_clk", "apb_pclk";
 			status = "disabled";
 		};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/aspeed-ast2500-evb.dts linux-libre-4.7-gnu/arch/arm/boot/dts/aspeed-ast2500-evb.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/aspeed-ast2500-evb.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/aspeed-ast2500-evb.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,25 @@
+/dts-v1/;
+
+#include "aspeed-g5.dtsi"
+
+/ {
+	model = "AST2500 EVB";
+	compatible = "aspeed,ast2500";
+
+	aliases {
+		serial4 = &uart5;
+	};
+
+	chosen {
+		stdout-path = &uart5;
+		bootargs = "console=ttyS4,115200 earlyprintk";
+	};
+
+	memory {
+		reg = <0x80000000 0x20000000>;
+	};
+};
+
+&uart5 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts linux-libre-4.7-gnu/arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,25 @@
+/dts-v1/;
+
+#include "aspeed-g4.dtsi"
+
+/ {
+	model = "Palmetto BMC";
+	compatible = "tyan,palmetto-bmc", "aspeed,ast2400";
+
+	aliases {
+		serial4 = &uart5;
+	};
+
+	chosen {
+		stdout-path = &uart5;
+		bootargs = "console=ttyS4,38400 earlyprintk";
+	};
+
+	memory {
+		reg = <0x40000000 0x10000000>;
+	};
+};
+
+&uart5 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/aspeed-g4.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/aspeed-g4.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/aspeed-g4.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/aspeed-g4.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,161 @@
+#include "skeleton.dtsi"
+
+/ {
+	model = "Aspeed BMC";
+	compatible = "aspeed,ast2400";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	interrupt-parent = <&vic>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			compatible = "arm,arm926ej-s";
+			device_type = "cpu";
+			reg = <0>;
+		};
+	};
+
+	clocks {
+		clk_clkin: clk_clkin {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <48000000>;
+		};
+
+	};
+
+	ahb {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		vic: interrupt-controller@1e6c0080 {
+			compatible = "aspeed,ast2400-vic";
+			interrupt-controller;
+			#interrupt-cells = <1>;
+			valid-sources = <0xffffffff 0x0007ffff>;
+			reg = <0x1e6c0080 0x80>;
+		};
+
+		apb {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+
+			clk_hpll: clk_hpll@1e6e2070 {
+				#clock-cells = <0>;
+				compatible = "aspeed,g4-hpll-clock";
+				reg = <0x1e6e2070 0x4>;
+				clocks = <&clk_clkin>;
+			};
+
+			clk_apb: clk_apb@1e6e2008 {
+				#clock-cells = <0>;
+				compatible = "aspeed,g4-apb-clock";
+				reg = <0x1e6e2008 0x4>;
+				clocks = <&clk_hpll>;
+			};
+
+			clk_uart: clk_uart@1e6e2008 {
+				#clock-cells = <0>;
+				compatible = "aspeed,uart-clock";
+				reg = <0x1e6e202c 0x4>;
+			};
+
+			sram@1e720000 {
+				compatible = "mmio-sram";
+				reg = <0x1e720000 0x8000>;	// 32K
+			};
+
+			timer: timer@1e782000 {
+				compatible = "aspeed,ast2400-timer";
+				reg = <0x1e782000 0x90>;
+				// The moxart_timer driver registers only one
+				// interrupt and assumes it's for timer 1
+				//interrupts = <16 17 18 35 36 37 38 39>;
+				interrupts = <16>;
+				clocks = <&clk_apb>;
+			};
+
+			wdt1: wdt@1e785000 {
+				compatible = "aspeed,wdt";
+				reg = <0x1e785000 0x1c>;
+				interrupts = <27>;
+			};
+
+			wdt2: wdt@1e785020 {
+				compatible = "aspeed,wdt";
+				reg = <0x1e785020 0x1c>;
+				interrupts = <27>;
+				clocks = <&clk_apb>;
+				status = "disabled";
+			};
+
+			uart1: serial@1e783000 {
+				compatible = "ns16550a";
+				reg = <0x1e783000 0x1000>;
+				reg-shift = <2>;
+				interrupts = <9>;
+				clocks = <&clk_uart>;
+				no-loopback-test;
+				status = "disabled";
+			};
+
+			uart2: serial@1e78d000 {
+				compatible = "ns16550a";
+				reg = <0x1e78d000 0x1000>;
+				reg-shift = <2>;
+				interrupts = <32>;
+				clocks = <&clk_uart>;
+				no-loopback-test;
+				status = "disabled";
+			};
+
+			uart3: serial@1e78e000 {
+				compatible = "ns16550a";
+				reg = <0x1e78e000 0x1000>;
+				reg-shift = <2>;
+				interrupts = <33>;
+				clocks = <&clk_uart>;
+				no-loopback-test;
+				status = "disabled";
+			};
+
+			uart4: serial@1e78f000 {
+				compatible = "ns16550a";
+				reg = <0x1e78f000 0x1000>;
+				reg-shift = <2>;
+				interrupts = <34>;
+				clocks = <&clk_uart>;
+				no-loopback-test;
+				status = "disabled";
+			};
+
+			uart5: serial@1e784000 {
+				compatible = "ns16550a";
+				reg = <0x1e784000 0x1000>;
+				reg-shift = <2>;
+				interrupts = <10>;
+				clocks = <&clk_uart>;
+				current-speed = <38400>;
+				no-loopback-test;
+				status = "disabled";
+			};
+
+			uart6: serial@1e787000 {
+				compatible = "ns16550a";
+				reg = <0x1e787000 0x1000>;
+				reg-shift = <2>;
+				interrupts = <10>;
+				clocks = <&clk_uart>;
+				no-loopback-test;
+				status = "disabled";
+			};
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/aspeed-g5.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/aspeed-g5.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/aspeed-g5.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/aspeed-g5.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,170 @@
+#include "skeleton.dtsi"
+
+/ {
+	model = "Aspeed BMC";
+	compatible = "aspeed,ast2500";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	interrupt-parent = <&vic>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			compatible = "arm,arm1176jzf-s";
+			device_type = "cpu";
+			reg = <0>;
+		};
+	};
+
+	ahb {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		vic: interrupt-controller@1e6c0080 {
+			compatible = "aspeed,ast2400-vic";
+			interrupt-controller;
+			#interrupt-cells = <1>;
+			valid-sources = <0xfefff7ff 0x0807ffff>;
+			reg = <0x1e6c0080 0x80>;
+		};
+
+		apb {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+
+			clk_clkin: clk_clkin@1e6e2070 {
+				#clock-cells = <0>;
+				compatible = "aspeed,g5-clkin-clock";
+				reg = <0x1e6e2070 0x04>;
+			};
+
+			clk_hpll: clk_hpll@1e6e2024 {
+				#clock-cells = <0>;
+				compatible = "aspeed,g5-hpll-clock";
+				reg = <0x1e6e2024 0x4>;
+				clocks = <&clk_clkin>;
+			};
+
+			clk_ahb: clk_ahb@1e6e2070 {
+				#clock-cells = <0>;
+				compatible = "aspeed,g5-ahb-clock";
+				reg = <0x1e6e2070 0x4>;
+				clocks = <&clk_hpll>;
+			};
+
+			clk_apb: clk_apb@1e6e2008 {
+				#clock-cells = <0>;
+				compatible = "aspeed,g5-apb-clock";
+				reg = <0x1e6e2008 0x4>;
+				clocks = <&clk_hpll>;
+			};
+
+			clk_uart: clk_uart@1e6e2008 {
+				#clock-cells = <0>;
+				compatible = "aspeed,uart-clock";
+				reg = <0x1e6e202c 0x4>;
+			};
+
+			sram@1e720000 {
+				compatible = "mmio-sram";
+				reg = <0x1e720000 0x9000>;	// 36K
+			};
+
+			timer: timer@1e782000 {
+				compatible = "aspeed,ast2400-timer";
+				reg = <0x1e782000 0x90>;
+				// The moxart_timer driver registers only one
+				// interrupt and assumes it's for timer 1
+				//interrupts = <16 17 18 35 36 37 38 39>;
+				interrupts = <16>;
+				clocks = <&clk_apb>;
+			};
+
+			wdt1: wdt@1e785000 {
+				compatible = "aspeed,wdt";
+				reg = <0x1e785000 0x1c>;
+				interrupts = <27>;
+			};
+
+			wdt2: wdt@1e785020 {
+				compatible = "aspeed,wdt";
+				reg = <0x1e785020 0x1c>;
+				interrupts = <27>;
+				status = "disabled";
+			};
+
+			wdt3: wdt@1e785040 {
+				compatible = "aspeed,wdt";
+				reg = <0x1e785074 0x1c>;
+				status = "disabled";
+			};
+
+			uart1: serial@1e783000 {
+				compatible = "ns16550a";
+				reg = <0x1e783000 0x1000>;
+				reg-shift = <2>;
+				interrupts = <9>;
+				clocks = <&clk_uart>;
+				no-loopback-test;
+				status = "disabled";
+			};
+
+			uart2: serial@1e78d000 {
+				compatible = "ns16550a";
+				reg = <0x1e78d000 0x1000>;
+				reg-shift = <2>;
+				interrupts = <32>;
+				clocks = <&clk_uart>;
+				no-loopback-test;
+				status = "disabled";
+			};
+
+			uart3: serial@1e78e000 {
+				compatible = "ns16550a";
+				reg = <0x1e78e000 0x1000>;
+				reg-shift = <2>;
+				interrupts = <33>;
+				clocks = <&clk_uart>;
+				no-loopback-test;
+				status = "disabled";
+			};
+
+			uart4: serial@1e78f000 {
+				compatible = "ns16550a";
+				reg = <0x1e78f000 0x1000>;
+				reg-shift = <2>;
+				interrupts = <34>;
+				clocks = <&clk_uart>;
+				no-loopback-test;
+				status = "disabled";
+			};
+
+			uart5: serial@1e784000 {
+				compatible = "ns16550a";
+				reg = <0x1e784000 0x1000>;
+				reg-shift = <2>;
+				interrupts = <10>;
+				clocks = <&clk_uart>;
+				current-speed = <38400>;
+				no-loopback-test;
+				status = "disabled";
+			};
+
+			uart6: serial@1e787000 {
+				compatible = "ns16550a";
+				reg = <0x1e787000 0x1000>;
+				reg-shift = <2>;
+				interrupts = <10>;
+				clocks = <&clk_uart>;
+				no-loopback-test;
+				status = "disabled";
+			};
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/at91sam9g45.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/at91sam9g45.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/at91sam9g45.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/at91sam9g45.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -978,7 +978,7 @@
 
 			trng@fffcc000 {
 				compatible = "atmel,at91sam9g45-trng";
-				reg = <0xfffcc000 0x4000>;
+				reg = <0xfffcc000 0x100>;
 				interrupts = <6 IRQ_TYPE_LEVEL_HIGH 0>;
 				clocks = <&trng_clk>;
 			};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/at91-sama5d2_xplained.dts linux-libre-4.7-gnu/arch/arm/boot/dts/at91-sama5d2_xplained.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/at91-sama5d2_xplained.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/at91-sama5d2_xplained.dts	2016-07-24 15:23:50.000000000 -0400
@@ -234,6 +234,15 @@
 				};
 			};
 
+			shdwc@f8048010 {
+				atmel,shdwc-debouncer = <976>;
+
+				input@0 {
+					reg = <0>;
+					atmel,wakeup-type = "low";
+				};
+			};
+
 			watchdog@f8048040 {
 				status = "okay";
 			};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/at91-vinco.dts linux-libre-4.7-gnu/arch/arm/boot/dts/at91-vinco.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/at91-vinco.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/at91-vinco.dts	2016-07-24 15:23:50.000000000 -0400
@@ -118,7 +118,7 @@
 
 				ethernet-phy@1 {
 					reg = <0x1>;
-					reset-gpios = <&pioE 8 GPIO_ACTIVE_HIGH>;
+					reset-gpios = <&pioE 8 GPIO_ACTIVE_LOW>;
 					interrupt-parent = <&pioB>;
 					interrupts = <15 IRQ_TYPE_EDGE_FALLING>;
 				};
@@ -162,7 +162,7 @@
 					reg = <0x1>;
 					interrupt-parent = <&pioB>;
 					interrupts = <31 IRQ_TYPE_EDGE_FALLING>;
-					reset-gpios = <&pioE 6 GPIO_ACTIVE_HIGH>;
+					reset-gpios = <&pioE 6 GPIO_ACTIVE_LOW>;
 				};
 			};
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/bcm2835.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/bcm2835.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/bcm2835.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/bcm2835.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -3,6 +3,17 @@
 / {
 	compatible = "brcm,bcm2835";
 
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,arm1176jzf-s";
+			reg = <0x0>;
+		};
+	};
+
 	soc {
 		ranges = <0x7e000000 0x20000000 0x02000000>;
 		dma-ranges = <0x40000000 0x00000000 0x20000000>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/bcm2835-rpi-a.dts linux-libre-4.7-gnu/arch/arm/boot/dts/bcm2835-rpi-a.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/bcm2835-rpi-a.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/bcm2835-rpi-a.dts	2016-07-24 15:23:50.000000000 -0400
@@ -22,3 +22,7 @@
 		brcm,function = <BCM2835_FSEL_ALT2>;
 	};
 };
+
+&hdmi {
+	hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts linux-libre-4.7-gnu/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts	2016-07-24 15:23:50.000000000 -0400
@@ -29,3 +29,7 @@
 		brcm,function = <BCM2835_FSEL_ALT0>;
 	};
 };
+
+&hdmi {
+	hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/bcm2835-rpi-b.dts linux-libre-4.7-gnu/arch/arm/boot/dts/bcm2835-rpi-b.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/bcm2835-rpi-b.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/bcm2835-rpi-b.dts	2016-07-24 15:23:50.000000000 -0400
@@ -16,3 +16,7 @@
 &gpio {
 	pinctrl-0 = <&gpioout &alt0 &alt3>;
 };
+
+&hdmi {
+	hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts linux-libre-4.7-gnu/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts	2016-07-24 15:23:50.000000000 -0400
@@ -29,3 +29,7 @@
 		brcm,function = <BCM2835_FSEL_ALT0>;
 	};
 };
+
+&hdmi {
+	hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts linux-libre-4.7-gnu/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts	2016-07-24 15:23:50.000000000 -0400
@@ -22,3 +22,7 @@
 		brcm,function = <BCM2835_FSEL_ALT2>;
 	};
 };
+
+&hdmi {
+	hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/bcm2835-rpi.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/bcm2835-rpi.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/bcm2835-rpi.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/bcm2835-rpi.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -74,3 +74,12 @@
 &usb {
 	power-domains = <&power RPI_POWER_DOMAIN_USB>;
 };
+
+&v3d {
+	power-domains = <&power RPI_POWER_DOMAIN_V3D>;
+};
+
+&hdmi {
+	power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/bcm2836-rpi-2-b.dts linux-libre-4.7-gnu/arch/arm/boot/dts/bcm2836-rpi-2-b.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/bcm2836-rpi-2-b.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/bcm2836-rpi-2-b.dts	2016-07-24 15:23:50.000000000 -0400
@@ -33,3 +33,7 @@
 		brcm,function = <BCM2835_FSEL_ALT0>;
 	};
 };
+
+&hdmi {
+	hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/bcm283x.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/bcm283x.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/bcm283x.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/bcm283x.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -1,6 +1,7 @@
 #include <dt-bindings/pinctrl/bcm2835.h>
 #include <dt-bindings/clock/bcm2835.h>
 #include <dt-bindings/clock/bcm2835-aux.h>
+#include <dt-bindings/gpio/gpio.h>
 #include "skeleton.dtsi"
 
 /* This include file covers the common peripherals and configuration between
@@ -47,9 +48,29 @@
 				     <1 24>,
 				     <1 25>,
 				     <1 26>,
+				     /* dma channel 11-14 share one irq */
+				     <1 27>,
+				     <1 27>,
+				     <1 27>,
 				     <1 27>,
+				     /* unused shared irq for all channels */
 				     <1 28>;
-
+			interrupt-names = "dma0",
+					  "dma1",
+					  "dma2",
+					  "dma3",
+					  "dma4",
+					  "dma5",
+					  "dma6",
+					  "dma7",
+					  "dma8",
+					  "dma9",
+					  "dma10",
+					  "dma11",
+					  "dma12",
+					  "dma13",
+					  "dma14",
+					  "dma-shared-all";
 			#dma-cells = <1>;
 			brcm,dma-channel-mask = <0x7f35>;
 		};
@@ -153,6 +174,18 @@
 			status = "disabled";
 		};
 
+		pixelvalve@7e206000 {
+			compatible = "brcm,bcm2835-pixelvalve0";
+			reg = <0x7e206000 0x100>;
+			interrupts = <2 13>; /* pwa0 */
+		};
+
+		pixelvalve@7e207000 {
+			compatible = "brcm,bcm2835-pixelvalve1";
+			reg = <0x7e207000 0x100>;
+			interrupts = <2 14>; /* pwa1 */
+		};
+
 		aux: aux@0x7e215000 {
 			compatible = "brcm,bcm2835-aux";
 			#clock-cells = <1>;
@@ -206,6 +239,12 @@
 			status = "disabled";
 		};
 
+		hvs@7e400000 {
+			compatible = "brcm,bcm2835-hvs";
+			reg = <0x7e400000 0x6000>;
+			interrupts = <2 1>;
+		};
+
 		i2c1: i2c@7e804000 {
 			compatible = "brcm,bcm2835-i2c";
 			reg = <0x7e804000 0x1000>;
@@ -226,11 +265,39 @@
 			status = "disabled";
 		};
 
+		pixelvalve@7e807000 {
+			compatible = "brcm,bcm2835-pixelvalve2";
+			reg = <0x7e807000 0x100>;
+			interrupts = <2 10>; /* pixelvalve */
+		};
+
+		hdmi: hdmi@7e902000 {
+			compatible = "brcm,bcm2835-hdmi";
+			reg = <0x7e902000 0x600>,
+			      <0x7e808000 0x100>;
+			interrupts = <2 8>, <2 9>;
+			ddc = <&i2c2>;
+			clocks = <&clocks BCM2835_PLLH_PIX>,
+				 <&clocks BCM2835_CLOCK_HSM>;
+			clock-names = "pixel", "hdmi";
+			status = "disabled";
+		};
+
 		usb: usb@7e980000 {
 			compatible = "brcm,bcm2835-usb";
 			reg = <0x7e980000 0x10000>;
 			interrupts = <1 9>;
 		};
+
+		v3d: v3d@7ec00000 {
+			compatible = "brcm,bcm2835-v3d";
+			reg = <0x7ec00000 0x1000>;
+			interrupts = <1 10>;
+		};
+
+		vc4: gpu {
+			compatible = "brcm,bcm2835-vc4";
+		};
 	};
 
 	clocks {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts linux-libre-4.7-gnu/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts	2016-07-24 15:23:50.000000000 -0400
@@ -17,7 +17,7 @@
 	model = "Buffalo WZR-600DHP2 (BCM47081)";
 
 	chosen {
-		bootargs = "console=ttyS0,115200";
+		bootargs = "console=ttyS0,115200 earlycon";
 	};
 
 	memory {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts linux-libre-4.7-gnu/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts	2016-07-24 15:23:50.000000000 -0400
@@ -17,7 +17,7 @@
 	model = "Buffalo WZR-1750DHP (BCM4708)";
 
 	chosen {
-		bootargs = "console=ttyS0,115200";
+		bootargs = "console=ttyS0,115200 earlycon";
 	};
 
 	memory {
@@ -139,3 +139,11 @@
 &uart0 {
 	status = "okay";
 };
+
+&usb2 {
+	vcc-gpio = <&chipcommon 9 GPIO_ACTIVE_HIGH>;
+};
+
+&usb3 {
+	vcc-gpio = <&chipcommon 10 GPIO_ACTIVE_LOW>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts linux-libre-4.7-gnu/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts	2016-07-24 15:23:50.000000000 -0400
@@ -17,7 +17,7 @@
 	model = "Luxul XWC-1000 (BCM4708)";
 
 	chosen {
-		bootargs = "console=ttyS0,115200";
+		bootargs = "console=ttyS0,115200 earlycon";
 	};
 
 	memory {
@@ -59,3 +59,7 @@
 &uart0 {
 	status = "okay";
 };
+
+&spi_nor {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/bcm4708-netgear-r6250.dts linux-libre-4.7-gnu/arch/arm/boot/dts/bcm4708-netgear-r6250.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/bcm4708-netgear-r6250.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/bcm4708-netgear-r6250.dts	2016-07-24 15:23:50.000000000 -0400
@@ -17,24 +17,13 @@
 	model = "Netgear R6250 V1 (BCM4708)";
 
 	chosen {
-		bootargs = "console=ttyS0,115200";
+		bootargs = "console=ttyS0,115200 earlycon";
 	};
 
 	memory {
 		reg = <0x00000000 0x08000000>;
 	};
 
-	axi@18000000 {
-		usb3@23000 {
-			reg = <0x00023000 0x1000>;
-
-			#address-cells = <1>;
-			#size-cells = <1>;
-
-			vcc-gpio = <&chipcommon 0 GPIO_ACTIVE_HIGH>;
-		};
-	};
-
 	leds {
 		compatible = "gpio-leds";
 
@@ -97,3 +86,7 @@
 &uart0 {
 	status = "okay";
 };
+
+&usb3 {
+	vcc-gpio = <&chipcommon 0 GPIO_ACTIVE_HIGH>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts linux-libre-4.7-gnu/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts	2016-07-24 15:23:50.000000000 -0400
@@ -17,7 +17,7 @@
 	model = "SmartRG SR400ac";
 
 	chosen {
-		bootargs = "console=ttyS0,115200";
+		bootargs = "console=ttyS0,115200 earlycon";
 	};
 
 	memory {
@@ -122,3 +122,7 @@
 &uart0 {
 	status = "okay";
 };
+
+&spi_nor {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts linux-libre-4.7-gnu/arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts	2016-07-24 15:23:50.000000000 -0400
@@ -17,7 +17,7 @@
 	model = "D-Link DIR-885L";
 
 	chosen {
-		bootargs = "console=ttyS0,115200";
+		bootargs = "console=ttyS0,115200 earlycon";
 	};
 
 	memory {
@@ -109,3 +109,7 @@
 	status = "okay";
 	clock-frequency = <125000000>;
 };
+
+&usb3 {
+	vcc-gpio = <&chipcommon 18 GPIO_ACTIVE_HIGH>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts linux-libre-4.7-gnu/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts	2016-07-24 15:23:50.000000000 -0400
@@ -126,3 +126,8 @@
 		};
 	};
 };
+
+
+&usb2 {
+	vcc-gpio = <&chipcommon 13 GPIO_ACTIVE_HIGH>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/bcm4709-netgear-r8000.dts linux-libre-4.7-gnu/arch/arm/boot/dts/bcm4709-netgear-r8000.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/bcm4709-netgear-r8000.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/bcm4709-netgear-r8000.dts	2016-07-24 15:23:50.000000000 -0400
@@ -106,3 +106,11 @@
 		};
 	};
 };
+
+&usb2 {
+	vcc-gpio = <&chipcommon 0 GPIO_ACTIVE_HIGH>;
+};
+
+&usb3 {
+	vcc-gpio = <&chipcommon 0 GPIO_ACTIVE_HIGH>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/bcm5301x.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/bcm5301x.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/bcm5301x.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/bcm5301x.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -18,6 +18,10 @@
 / {
 	interrupt-parent = <&gic>;
 
+	chosen {
+		stdout-path = &uart0;
+	};
+
 	chipcommonA {
 		compatible = "simple-bus";
 		ranges = <0x00000000 0x18000000 0x00001000>;
@@ -207,6 +211,34 @@
 			gpio-controller;
 			#gpio-cells = <2>;
 		};
+
+		usb2: usb2@21000 {
+			reg = <0x00021000 0x1000>;
+
+			#address-cells = <1>;
+			#size-cells = <1>;
+		};
+
+		usb3: usb3@23000 {
+			reg = <0x00023000 0x1000>;
+
+			#address-cells = <1>;
+			#size-cells = <1>;
+		};
+
+		spi@29000 {
+			reg = <0x00029000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			spi_nor: spi-nor@0 {
+				compatible = "jedec,spi-nor";
+				reg = <0>;
+				spi-max-frequency = <20000000>;
+				linux,part-probe = "ofpart", "bcm47xxpart";
+				status = "disabled";
+			};
+		};
 	};
 
 	lcpll0: lcpll0@1800c100 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/bcm-cygnus.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/bcm-cygnus.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/bcm-cygnus.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/bcm-cygnus.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -351,9 +351,16 @@
 					<&pinctrl 142 10 1>;
 		};
 
-		touchscreen: tsc@180a6000 {
+		ts_adc_syscon: ts_adc_syscon@180a6000 {
+			compatible = "brcm,iproc-ts-adc-syscon", "syscon";
+			reg = <0x180a6000 0xc30>;
+		};
+
+		touchscreen: touchscreen@180a6000 {
 			compatible = "brcm,iproc-touchscreen";
-			reg = <0x180a6000 0x40>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ts_syscon = <&ts_adc_syscon>;
 			clocks = <&asiu_clks BCM_CYGNUS_ASIU_ADC_CLK>;
 			clock-names = "tsc_clk";
 			interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/cros-adc-thermistors.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/cros-adc-thermistors.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/cros-adc-thermistors.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/cros-adc-thermistors.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -13,28 +13,28 @@
 */
 
 &adc {
-	ncp15wb473@3 {
+	thermistor3 {
 		compatible = "murata,ncp15wb473";
 		pullup-uv = <1800000>;
 		pullup-ohm = <47000>;
 		pulldown-ohm = <0>;
 		io-channels = <&adc 3>;
 	};
-	ncp15wb473@4 {
+	thermistor4 {
 		compatible = "murata,ncp15wb473";
 		pullup-uv = <1800000>;
 		pullup-ohm = <47000>;
 		pulldown-ohm = <0>;
 		io-channels = <&adc 4>;
 	};
-	ncp15wb473@5 {
+	thermistor5 {
 		compatible = "murata,ncp15wb473";
 		pullup-uv = <1800000>;
 		pullup-ohm = <47000>;
 		pulldown-ohm = <0>;
 		io-channels = <&adc 5>;
 	};
-	ncp15wb473@6 {
+	thermistor6 {
 		compatible = "murata,ncp15wb473";
 		pullup-uv = <1800000>;
 		pullup-ohm = <47000>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/da850.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/da850.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/da850.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/da850.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -15,15 +15,15 @@
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges;
-		intc: interrupt-controller {
+		intc: interrupt-controller@fffee000 {
 			compatible = "ti,cp-intc";
 			interrupt-controller;
 			#interrupt-cells = <1>;
-			ti,intc-size = <100>;
+			ti,intc-size = <101>;
 			reg = <0xfffee000 0x2000>;
 		};
 	};
-	soc {
+	soc@1c00000 {
 		compatible = "simple-bus";
 		model = "da850";
 		#address-cells = <1>;
@@ -31,7 +31,7 @@
 		ranges = <0x0 0x01c00000 0x400000>;
 		interrupt-parent = <&intc>;
 
-		pmx_core: pinmux@1c14120 {
+		pmx_core: pinmux@14120 {
 			compatible = "pinctrl-single";
 			reg = <0x14120 0x50>;
 			#address-cells = <1>;
@@ -63,6 +63,12 @@
 					0x10 0x00002200 0x0000ff00
 				>;
 			};
+			i2c1_pins: pinmux_i2c1_pins {
+				pinctrl-single,bits = <
+					/* I2C1_SDA, I2C1_SCL */
+					0x10 0x00440000 0x00ff0000
+				>;
+			};
 			mmc0_pins: pinmux_mmc_pins {
 				pinctrl-single,bits = <
 					/* MMCSD0_DAT[3] MMCSD0_DAT[2]
@@ -114,7 +120,19 @@
 					0x4 0x00000004 0x0000000f
 				>;
 			};
-			spi1_pins: pinmux_spi_pins {
+			spi0_pins: pinmux_spi0_pins {
+				pinctrl-single,bits = <
+					/* SIMO, SOMI, CLK */
+					0xc 0x00001101 0x0000ff0f
+				>;
+			};
+			spi0_cs0_pin: pinmux_spi0_cs0 {
+				pinctrl-single,bits = <
+					/* CS0 */
+					0x10 0x00000010 0x000000f0
+				>;
+			};
+			spi1_pins: pinmux_spi1_pins {
 				pinctrl-single,bits = <
 					/* SIMO, SOMI, CLK */
 					0x14 0x00110100 0x00ff0f00
@@ -150,7 +168,7 @@
 			};
 
 		};
-		edma0: edma@01c00000 {
+		edma0: edma@0 {
 			compatible = "ti,edma3-tpcc";
 			/* eDMA3 CC0: 0x01c0 0000 - 0x01c0 7fff */
 			reg =	<0x0 0x8000>;
@@ -161,19 +179,19 @@
 
 			ti,tptcs = <&edma0_tptc0 7>, <&edma0_tptc1 0>;
 		};
-		edma0_tptc0: tptc@01c08000 {
+		edma0_tptc0: tptc@8000 {
 			compatible = "ti,edma3-tptc";
 			reg =	<0x8000 0x400>;
 			interrupts = <13>;
 			interrupt-names = "edm3_tcerrint";
 		};
-		edma0_tptc1: tptc@01c08400 {
+		edma0_tptc1: tptc@8400 {
 			compatible = "ti,edma3-tptc";
 			reg =	<0x8400 0x400>;
 			interrupts = <32>;
 			interrupt-names = "edm3_tcerrint";
 		};
-		edma1: edma@01e30000 {
+		edma1: edma@230000 {
 			compatible = "ti,edma3-tpcc";
 			/* eDMA3 CC1: 0x01e3 0000 - 0x01e3 7fff */
 			reg =	<0x230000 0x8000>;
@@ -184,41 +202,41 @@
 
 			ti,tptcs = <&edma1_tptc0 7>;
 		};
-		edma1_tptc0: tptc@01e38000 {
+		edma1_tptc0: tptc@238000 {
 			compatible = "ti,edma3-tptc";
 			reg =	<0x238000 0x400>;
 			interrupts = <95>;
 			interrupt-names = "edm3_tcerrint";
 		};
-		serial0: serial@1c42000 {
+		serial0: serial@42000 {
 			compatible = "ns16550a";
 			reg = <0x42000 0x100>;
 			reg-shift = <2>;
 			interrupts = <25>;
 			status = "disabled";
 		};
-		serial1: serial@1d0c000 {
+		serial1: serial@10c000 {
 			compatible = "ns16550a";
 			reg = <0x10c000 0x100>;
 			reg-shift = <2>;
 			interrupts = <53>;
 			status = "disabled";
 		};
-		serial2: serial@1d0d000 {
+		serial2: serial@10d000 {
 			compatible = "ns16550a";
 			reg = <0x10d000 0x100>;
 			reg-shift = <2>;
 			interrupts = <61>;
 			status = "disabled";
 		};
-		rtc0: rtc@1c23000 {
+		rtc0: rtc@23000 {
 			compatible = "ti,da830-rtc";
 			reg = <0x23000 0x1000>;
 			interrupts = <19
 				      19>;
 			status = "disabled";
 		};
-		i2c0: i2c@1c22000 {
+		i2c0: i2c@22000 {
 			compatible = "ti,davinci-i2c";
 			reg = <0x22000 0x1000>;
 			interrupts = <15>;
@@ -226,12 +244,20 @@
 			#size-cells = <0>;
 			status = "disabled";
 		};
-		wdt: wdt@1c21000 {
+		i2c1: i2c@228000 {
+			compatible = "ti,davinci-i2c";
+			reg = <0x228000 0x1000>;
+			interrupts = <51>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+		wdt: wdt@21000 {
 			compatible = "ti,davinci-wdt";
 			reg = <0x21000 0x1000>;
 			status = "disabled";
 		};
-		mmc0: mmc@1c40000 {
+		mmc0: mmc@40000 {
 			compatible = "ti,da830-mmc";
 			reg = <0x40000 0x1000>;
 			interrupts = <16>;
@@ -239,7 +265,7 @@
 			dma-names = "rx", "tx";
 			status = "disabled";
 		};
-		mmc1: mmc@1e1b000 {
+		mmc1: mmc@21b000 {
 			compatible = "ti,da830-mmc";
 			reg = <0x21b000 0x1000>;
 			interrupts = <72>;
@@ -247,37 +273,47 @@
 			dma-names = "rx", "tx";
 			status = "disabled";
 		};
-		ehrpwm0: ehrpwm@01f00000 {
+		ehrpwm0: pwm@300000 {
 			compatible = "ti,da850-ehrpwm", "ti,am33xx-ehrpwm";
 			#pwm-cells = <3>;
 			reg = <0x300000 0x2000>;
 			status = "disabled";
 		};
-		ehrpwm1: ehrpwm@01f02000 {
+		ehrpwm1: pwm@302000 {
 			compatible = "ti,da850-ehrpwm", "ti,am33xx-ehrpwm";
 			#pwm-cells = <3>;
 			reg = <0x302000 0x2000>;
 			status = "disabled";
 		};
-		ecap0: ecap@01f06000 {
+		ecap0: ecap@306000 {
 			compatible = "ti,da850-ecap", "ti,am33xx-ecap";
 			#pwm-cells = <3>;
 			reg = <0x306000 0x80>;
 			status = "disabled";
 		};
-		ecap1: ecap@01f07000 {
+		ecap1: ecap@307000 {
 			compatible = "ti,da850-ecap", "ti,am33xx-ecap";
 			#pwm-cells = <3>;
 			reg = <0x307000 0x80>;
 			status = "disabled";
 		};
-		ecap2: ecap@01f08000 {
+		ecap2: ecap@308000 {
 			compatible = "ti,da850-ecap", "ti,am33xx-ecap";
 			#pwm-cells = <3>;
 			reg = <0x308000 0x80>;
 			status = "disabled";
 		};
-		spi1: spi@1f0e000 {
+		spi0: spi@41000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "ti,da830-spi";
+			reg = <0x41000 0x1000>;
+			num-cs = <6>;
+			ti,davinci-spi-intr-line = <1>;
+			interrupts = <20>;
+			status = "disabled";
+		};
+		spi1: spi@30e000 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			compatible = "ti,da830-spi";
@@ -289,13 +325,14 @@
 			dma-names = "rx", "tx";
 			status = "disabled";
 		};
-		mdio: mdio@1e24000 {
+		mdio: mdio@224000 {
 			compatible = "ti,davinci_mdio";
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <0x224000 0x1000>;
+			status = "disabled";
 		};
-		eth0: ethernet@1e20000 {
+		eth0: ethernet@220000 {
 			compatible = "ti,davinci-dm6467-emac";
 			reg = <0x220000 0x4000>;
 			ti,davinci-ctrl-reg-offset = <0x3000>;
@@ -308,10 +345,12 @@
 					35
 					36
 					>;
+			status = "disabled";
 		};
-		gpio: gpio@1e26000 {
+		gpio: gpio@226000 {
 			compatible = "ti,dm6441-gpio";
 			gpio-controller;
+			#gpio-cells = <2>;
 			reg = <0x226000 0x1000>;
 			interrupts = <42 IRQ_TYPE_EDGE_BOTH
 				43 IRQ_TYPE_EDGE_BOTH 44 IRQ_TYPE_EDGE_BOTH
@@ -323,7 +362,7 @@
 			status = "disabled";
 		};
 
-		mcasp0: mcasp@01d00000 {
+		mcasp0: mcasp@100000 {
 			compatible = "ti,da830-mcasp-audio";
 			reg = <0x100000 0x2000>,
 			      <0x102000 0x400000>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/da850-enbw-cmc.dts linux-libre-4.7-gnu/arch/arm/boot/dts/da850-enbw-cmc.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/da850-enbw-cmc.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/da850-enbw-cmc.dts	2016-07-24 15:23:50.000000000 -0400
@@ -16,14 +16,20 @@
 	compatible = "enbw,cmc", "ti,da850";
 	model = "EnBW CMC";
 
-	soc {
-		serial0: serial@1c42000 {
+	soc@1c00000 {
+		serial0: serial@42000 {
 			status = "okay";
 		};
-		serial1: serial@1d0c000 {
+		serial1: serial@10c000 {
 			status = "okay";
 		};
-		serial2: serial@1d0d000 {
+		serial2: serial@10d000 {
+			status = "okay";
+		};
+		mdio: mdio@224000 {
+			status = "okay";
+		};
+		eth0: ethernet@220000 {
 			status = "okay";
 		};
 	};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/da850-evm.dts linux-libre-4.7-gnu/arch/arm/boot/dts/da850-evm.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/da850-evm.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/da850-evm.dts	2016-07-24 15:23:50.000000000 -0400
@@ -14,8 +14,8 @@
 	compatible = "ti,da850-evm", "ti,da850";
 	model = "DA850/AM1808/OMAP-L138 EVM";
 
-	soc {
-		pmx_core: pinmux@1c14120 {
+	soc@1c00000 {
+		pmx_core: pinmux@14120 {
 			status = "okay";
 
 			mcasp0_pins: pinmux_mcasp0_pins {
@@ -30,19 +30,19 @@
 				>;
 			};
 		};
-		serial0: serial@1c42000 {
+		serial0: serial@42000 {
 			status = "okay";
 		};
-		serial1: serial@1d0c000 {
+		serial1: serial@10c000 {
 			status = "okay";
 		};
-		serial2: serial@1d0d000 {
+		serial2: serial@10d000 {
 			status = "okay";
 		};
-		rtc0: rtc@1c23000 {
+		rtc0: rtc@23000 {
 			status = "okay";
 		};
-		i2c0: i2c@1c22000 {
+		i2c0: i2c@22000 {
 			status = "okay";
 			clock-frequency = <100000>;
 			pinctrl-names = "default";
@@ -66,17 +66,17 @@
 			};
 
 		};
-		wdt: wdt@1c21000 {
+		wdt: wdt@21000 {
 			status = "okay";
 		};
-		mmc0: mmc@1c40000 {
+		mmc0: mmc@40000 {
 			max-frequency = <50000000>;
 			bus-width = <4>;
 			status = "okay";
 			pinctrl-names = "default";
 			pinctrl-0 = <&mmc0_pins>;
 		};
-		spi1: spi@1f0e000 {
+		spi1: spi@30e000 {
 			status = "okay";
 			pinctrl-names = "default";
 			pinctrl-0 = <&spi1_pins &spi1_cs0_pin>;
@@ -116,18 +116,18 @@
 				};
 			};
 		};
-		mdio: mdio@1e24000 {
+		mdio: mdio@224000 {
 			status = "okay";
 			pinctrl-names = "default";
 			pinctrl-0 = <&mdio_pins>;
 			bus_freq = <2200000>;
 		};
-		eth0: ethernet@1e20000 {
+		eth0: ethernet@220000 {
 			status = "okay";
 			pinctrl-names = "default";
 			pinctrl-0 = <&mii_pins>;
 		};
-		gpio: gpio@1e26000 {
+		gpio: gpio@226000 {
 			status = "okay";
 		};
 	};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/dm8148-evm.dts linux-libre-4.7-gnu/arch/arm/boot/dts/dm8148-evm.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/dm8148-evm.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/dm8148-evm.dts	2016-07-24 15:23:50.000000000 -0400
@@ -93,6 +93,10 @@
 	};
 };
 
+&mmc1 {
+        status = "disabled";
+};
+
 &mmc2 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&sd1_pins>;
@@ -101,6 +105,10 @@
 	cd-gpios = <&gpio2 6 GPIO_ACTIVE_LOW>;
 };
 
+&mmc3 {
+        status = "disabled";
+};
+
 &pincntl {
 	sd1_pins: pinmux_sd1_pins {
 		pinctrl-single,pins = <
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/dm8148-t410.dts linux-libre-4.7-gnu/arch/arm/boot/dts/dm8148-t410.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/dm8148-t410.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/dm8148-t410.dts	2016-07-24 15:23:50.000000000 -0400
@@ -45,6 +45,14 @@
 	phy-mode = "rgmii";
 };
 
+&mmc1 {
+	status = "disabled";
+};
+
+&mmc2 {
+	status = "disabled";
+};
+
 &mmc3 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&sd2_pins>;
@@ -53,6 +61,7 @@
 	dmas = <&edma_xbar 8 0 1	/* use SDTXEVT1 instead of MCASP0TX */
 		&edma_xbar 9 0 2>;	/* use SDRXEVT1 instead of MCASP0RX */
 	dma-names = "tx", "rx";
+	non-removable;
 };
 
 &pincntl {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/dm814x-clocks.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/dm814x-clocks.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/dm814x-clocks.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/dm814x-clocks.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -156,7 +156,7 @@
 };
 
 &pllss_clocks {
-	timer1_fck: timer1_fck {
+	timer1_fck: timer1_fck@2e0 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sysclk18_ck &aud_clkin0_ck &aud_clkin1_ck
@@ -165,7 +165,7 @@
 		reg = <0x2e0>;
 	};
 
-	timer2_fck: timer2_fck {
+	timer2_fck: timer2_fck@2e0 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sysclk18_ck &aud_clkin0_ck &aud_clkin1_ck
@@ -192,7 +192,7 @@
 		clock-frequency = <125000000>;
 	};
 
-	sysclk18_ck: sysclk18_ck {
+	sysclk18_ck: sysclk18_ck@2f0 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&rtcosc_ck>, <&rtcdivider_ck>;
@@ -202,7 +202,7 @@
 };
 
 &scm_clocks {
-	devosc_ck: devosc_ck {
+	devosc_ck: devosc_ck@40 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&virt_20000000_ck>, <&virt_19200000_ck>;
@@ -259,7 +259,7 @@
 		clock-div = <1>;
 	};
 
-	mpu_clksrc_ck: mpu_clksrc_ck {
+	mpu_clksrc_ck: mpu_clksrc_ck@40 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&devosc_ck>, <&rtcdivider_ck>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/dm814x.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/dm814x.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/dm814x.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/dm814x.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -568,6 +568,8 @@
 			#size-cells = <1>;
 			interrupt-controller;
 			#interrupt-cells = <2>;
+			gpio-controller;
+			#gpio-cells = <2>;
 		};
 	};
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/dm816x-clocks.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/dm816x-clocks.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/dm816x-clocks.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/dm816x-clocks.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -86,7 +86,7 @@
 
 /* 0x48180000 */
 &prcm_clocks {
-	clkout_pre_ck: clkout_pre_ck {
+	clkout_pre_ck: clkout_pre_ck@100 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&main_fapll 5 &ddr_fapll 1 &video_fapll 1
@@ -94,7 +94,7 @@
 		reg = <0x100>;
 	};
 
-	clkout_div_ck: clkout_div_ck {
+	clkout_div_ck: clkout_div_ck@100 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&clkout_pre_ck>;
@@ -103,7 +103,7 @@
 		reg = <0x100>;
 	};
 
-	clkout_ck: clkout_ck {
+	clkout_ck: clkout_ck@100 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&clkout_div_ck>;
@@ -112,7 +112,7 @@
 	};
 
 	/* CM_DPLL clocks p1795 */
-	sysclk1_ck: sysclk1_ck {
+	sysclk1_ck: sysclk1_ck@300 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&main_fapll 1>;
@@ -120,7 +120,7 @@
 		reg = <0x0300>;
 	};
 
-	sysclk2_ck: sysclk2_ck {
+	sysclk2_ck: sysclk2_ck@304 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&main_fapll 2>;
@@ -128,7 +128,7 @@
 		reg = <0x0304>;
 	};
 
-	sysclk3_ck: sysclk3_ck {
+	sysclk3_ck: sysclk3_ck@308 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&main_fapll 3>;
@@ -136,7 +136,7 @@
 		reg = <0x0308>;
 	};
 
-	sysclk4_ck: sysclk4_ck {
+	sysclk4_ck: sysclk4_ck@30c {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&main_fapll 4>;
@@ -144,7 +144,7 @@
 		reg = <0x030c>;
 	};
 
-	sysclk5_ck: sysclk5_ck {
+	sysclk5_ck: sysclk5_ck@310 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&sysclk4_ck>;
@@ -152,7 +152,7 @@
 		reg = <0x0310>;
 	};
 
-	sysclk6_ck: sysclk6_ck {
+	sysclk6_ck: sysclk6_ck@314 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&main_fapll 4>;
@@ -160,7 +160,7 @@
 		reg = <0x0314>;
 	};
 
-	sysclk10_ck: sysclk10_ck {
+	sysclk10_ck: sysclk10_ck@324 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&ddr_fapll 2>;
@@ -168,7 +168,7 @@
 		reg = <0x0324>;
 	};
 
-	sysclk24_ck: sysclk24_ck {
+	sysclk24_ck: sysclk24_ck@3b4 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&main_fapll 5>;
@@ -176,7 +176,7 @@
 		reg = <0x03b4>;
 	};
 
-	mpu_ck: mpu_ck {
+	mpu_ck: mpu_ck@15dc {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sysclk2_ck>;
@@ -184,7 +184,7 @@
                 reg = <0x15dc>;
 	};
 
-	audio_pll_a_ck: audio_pll_a_ck {
+	audio_pll_a_ck: audio_pll_a_ck@35c {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&audio_fapll 1>;
@@ -192,56 +192,56 @@
 		reg = <0x035c>;
 	};
 
-	sysclk18_ck: sysclk18_ck {
+	sysclk18_ck: sysclk18_ck@378 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_32k_ck>, <&audio_pll_a_ck>;
 		reg = <0x0378>;
 	};
 
-	timer1_fck: timer1_fck {
+	timer1_fck: timer1_fck@390 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&tclkin_ck>, <&sysclk18_ck>, <&sys_clkin_ck>;
 		reg = <0x0390>;
 	};
 
-	timer2_fck: timer2_fck {
+	timer2_fck: timer2_fck@394 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&tclkin_ck>, <&sysclk18_ck>, <&sys_clkin_ck>;
 		reg = <0x0394>;
 	};
 
-	timer3_fck: timer3_fck {
+	timer3_fck: timer3_fck@398 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&tclkin_ck>, <&sysclk18_ck>, <&sys_clkin_ck>;
 		reg = <0x0398>;
 	};
 
-	timer4_fck: timer4_fck {
+	timer4_fck: timer4_fck@39c {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&tclkin_ck>, <&sysclk18_ck>, <&sys_clkin_ck>;
 		reg = <0x039c>;
 	};
 
-	timer5_fck: timer5_fck {
+	timer5_fck: timer5_fck@3a0 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&tclkin_ck>, <&sysclk18_ck>, <&sys_clkin_ck>;
 		reg = <0x03a0>;
 	};
 
-	timer6_fck: timer6_fck {
+	timer6_fck: timer6_fck@3a4 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&tclkin_ck>, <&sysclk18_ck>, <&sys_clkin_ck>;
 		reg = <0x03a4>;
 	};
 
-	timer7_fck: timer7_fck {
+	timer7_fck: timer7_fck@3a8 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&tclkin_ck>, <&sysclk18_ck>, <&sys_clkin_ck>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/dm816x.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/dm816x.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/dm816x.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/dm816x.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -185,6 +185,8 @@
 			gpmc,num-waitpins = <2>;
 			interrupt-controller;
 			#interrupt-cells = <2>;
+			gpio-controller;
+			#gpio-cells = <2>;
 		};
 
 		i2c1: i2c@48028000 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/dra72-evm-common.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/dra72-evm-common.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/dra72-evm-common.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/dra72-evm-common.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,817 @@
+/*
+ * Copyright (C) 2014-2016 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "dra72x.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/clk/ti-dra7-atl.h>
+
+/ {
+	compatible = "ti,dra72-evm", "ti,dra722", "ti,dra72", "ti,dra7";
+
+	aliases {
+		display0 = &hdmi0;
+	};
+
+	evm_3v3: fixedregulator-evm_3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "evm_3v3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	aic_dvdd: fixedregulator-aic_dvdd {
+		/* TPS77018DBVT */
+		compatible = "regulator-fixed";
+		regulator-name = "aic_dvdd";
+		vin-supply = <&evm_3v3>;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+	};
+
+	evm_3v3_sd: fixedregulator-sd {
+		compatible = "regulator-fixed";
+		regulator-name = "evm_3v3_sd";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		enable-active-high;
+		gpio = <&pcf_gpio_21 5 GPIO_ACTIVE_HIGH>;
+	};
+
+	extcon_usb1: extcon_usb1 {
+		compatible = "linux,extcon-usb-gpio";
+		id-gpio = <&pcf_gpio_21 1 GPIO_ACTIVE_HIGH>;
+	};
+
+	extcon_usb2: extcon_usb2 {
+		compatible = "linux,extcon-usb-gpio";
+		id-gpio = <&pcf_gpio_21 2 GPIO_ACTIVE_HIGH>;
+	};
+
+	hdmi0: connector {
+		compatible = "hdmi-connector";
+		label = "hdmi";
+
+		type = "a";
+
+		port {
+			hdmi_connector_in: endpoint {
+				remote-endpoint = <&tpd12s015_out>;
+			};
+		};
+	};
+
+	tpd12s015: encoder {
+		compatible = "ti,tpd12s015";
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&tpd12s015_pins>;
+
+		gpios = <&pcf_hdmi 4 GPIO_ACTIVE_HIGH>,	/* P4, CT CP HPD */
+			<&pcf_hdmi 5 GPIO_ACTIVE_HIGH>,	/* P5, LS OE */
+			<&gpio7 12 GPIO_ACTIVE_HIGH>;	/* gpio7_12/sp1_cs2, HPD */
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+
+				tpd12s015_in: endpoint {
+					remote-endpoint = <&hdmi_out>;
+				};
+			};
+
+			port@1 {
+				reg = <1>;
+
+				tpd12s015_out: endpoint {
+					remote-endpoint = <&hdmi_connector_in>;
+				};
+			};
+		};
+	};
+
+	sound0: sound0 {
+		compatible = "simple-audio-card";
+		simple-audio-card,name = "DRA7xx-EVM";
+		simple-audio-card,widgets =
+			"Headphone", "Headphone Jack",
+			"Line", "Line Out",
+			"Microphone", "Mic Jack",
+			"Line", "Line In";
+		simple-audio-card,routing =
+			"Headphone Jack",       "HPLOUT",
+			"Headphone Jack",       "HPROUT",
+			"Line Out",		"LLOUT",
+			"Line Out",		"RLOUT",
+			"MIC3L",		"Mic Jack",
+			"MIC3R",		"Mic Jack",
+			"Mic Jack",		"Mic Bias",
+			"LINE1L",               "Line In",
+			"LINE1R",               "Line In";
+		simple-audio-card,format = "dsp_b";
+		simple-audio-card,bitclock-master = <&sound0_master>;
+		simple-audio-card,frame-master = <&sound0_master>;
+		simple-audio-card,bitclock-inversion;
+
+		sound0_master: simple-audio-card,cpu {
+			sound-dai = <&mcasp3>;
+			system-clock-frequency = <5644800>;
+		};
+
+		simple-audio-card,codec {
+			sound-dai = <&tlv320aic3106>;
+			clocks = <&atl_clkin2_ck>;
+		};
+	};
+};
+
+&dra7_pmx_core {
+	i2c1_pins: pinmux_i2c1_pins {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x3800, PIN_INPUT | MUX_MODE0) /* i2c1_sda.i2c1_sda */
+			DRA7XX_CORE_IOPAD(0x3804, PIN_INPUT | MUX_MODE0) /* i2c1_scl.i2c1_scl */
+		>;
+	};
+
+	i2c5_pins: pinmux_i2c5_pins {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x36b4, PIN_INPUT | MUX_MODE10) /* mcasp1_axr0.i2c5_sda */
+			DRA7XX_CORE_IOPAD(0x36b8, PIN_INPUT | MUX_MODE10) /* mcasp1_axr1.i2c5_scl */
+		>;
+	};
+
+	i2c5_pins: pinmux_i2c5_pins {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x36b4, PIN_INPUT | MUX_MODE10) /* mcasp1_axr0.i2c5_sda */
+			DRA7XX_CORE_IOPAD(0x36b8, PIN_INPUT | MUX_MODE10) /* mcasp1_axr1.i2c5_scl */
+		>;
+	};
+
+	nand_default: nand_default {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x3400, PIN_INPUT  | MUX_MODE0) /* gpmc_ad0 */
+			DRA7XX_CORE_IOPAD(0x3404, PIN_INPUT  | MUX_MODE0) /* gpmc_ad1 */
+			DRA7XX_CORE_IOPAD(0x3408, PIN_INPUT  | MUX_MODE0) /* gpmc_ad2 */
+			DRA7XX_CORE_IOPAD(0x340c, PIN_INPUT  | MUX_MODE0) /* gpmc_ad3 */
+			DRA7XX_CORE_IOPAD(0x3410, PIN_INPUT  | MUX_MODE0) /* gpmc_ad4 */
+			DRA7XX_CORE_IOPAD(0x3414, PIN_INPUT  | MUX_MODE0) /* gpmc_ad5 */
+			DRA7XX_CORE_IOPAD(0x3418, PIN_INPUT  | MUX_MODE0) /* gpmc_ad6 */
+			DRA7XX_CORE_IOPAD(0x341c, PIN_INPUT  | MUX_MODE0) /* gpmc_ad7 */
+			DRA7XX_CORE_IOPAD(0x3420, PIN_INPUT  | MUX_MODE0) /* gpmc_ad8 */
+			DRA7XX_CORE_IOPAD(0x3424, PIN_INPUT  | MUX_MODE0) /* gpmc_ad9 */
+			DRA7XX_CORE_IOPAD(0x3428, PIN_INPUT  | MUX_MODE0) /* gpmc_ad10 */
+			DRA7XX_CORE_IOPAD(0x342c, PIN_INPUT  | MUX_MODE0) /* gpmc_ad11 */
+			DRA7XX_CORE_IOPAD(0x3430, PIN_INPUT  | MUX_MODE0) /* gpmc_ad12 */
+			DRA7XX_CORE_IOPAD(0x3434, PIN_INPUT  | MUX_MODE0) /* gpmc_ad13 */
+			DRA7XX_CORE_IOPAD(0x3438, PIN_INPUT  | MUX_MODE0) /* gpmc_ad14 */
+			DRA7XX_CORE_IOPAD(0x343c, PIN_INPUT  | MUX_MODE0) /* gpmc_ad15 */
+			DRA7XX_CORE_IOPAD(0x34b4, PIN_OUTPUT | MUX_MODE0) /* gpmc_cs0 */
+			DRA7XX_CORE_IOPAD(0x34c4, PIN_OUTPUT | MUX_MODE0) /* gpmc_advn_ale */
+			DRA7XX_CORE_IOPAD(0x34cc, PIN_OUTPUT | MUX_MODE0) /* gpmc_wen */
+			DRA7XX_CORE_IOPAD(0x34c8, PIN_OUTPUT | MUX_MODE0) /* gpmc_oen_ren */
+			DRA7XX_CORE_IOPAD(0x34d0, PIN_OUTPUT | MUX_MODE0) /* gpmc_ben0 */
+			DRA7XX_CORE_IOPAD(0x34d8, PIN_INPUT  | MUX_MODE0) /* gpmc_wait0 */
+		>;
+	};
+
+	usb1_pins: pinmux_usb1_pins {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x3680, PIN_INPUT_SLEW | MUX_MODE0) /* usb1_drvvbus */
+		>;
+	};
+
+	usb2_pins: pinmux_usb2_pins {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x3684, PIN_INPUT_SLEW | MUX_MODE0) /* usb2_drvvbus */
+		>;
+	};
+
+	tps65917_pins_default: tps65917_pins_default {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x3824, PIN_INPUT_PULLUP | MUX_MODE1) /* wakeup3.sys_nirq1 */
+		>;
+	};
+
+	mmc1_pins_default: mmc1_pins_default {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x376c, PIN_INPUT | MUX_MODE14)	/* mmc1sdcd.gpio219 */
+			DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_clk.clk */
+			DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_cmd.cmd */
+			DRA7XX_CORE_IOPAD(0x375c, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat0.dat0 */
+			DRA7XX_CORE_IOPAD(0x3760, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat1.dat1 */
+			DRA7XX_CORE_IOPAD(0x3764, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat2.dat2 */
+			DRA7XX_CORE_IOPAD(0x3768, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat3.dat3 */
+		>;
+	};
+
+	mmc2_pins_default: mmc2_pins_default {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x349c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a23.mmc2_clk */
+			DRA7XX_CORE_IOPAD(0x34b0, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_cs1.mmc2_cmd */
+			DRA7XX_CORE_IOPAD(0x34a0, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a24.mmc2_dat0 */
+			DRA7XX_CORE_IOPAD(0x34a4, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a25.mmc2_dat1 */
+			DRA7XX_CORE_IOPAD(0x34a8, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a26.mmc2_dat2 */
+			DRA7XX_CORE_IOPAD(0x34ac, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a27.mmc2_dat3 */
+			DRA7XX_CORE_IOPAD(0x348c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a19.mmc2_dat4 */
+			DRA7XX_CORE_IOPAD(0x3490, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a20.mmc2_dat5 */
+			DRA7XX_CORE_IOPAD(0x3494, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a21.mmc2_dat6 */
+			DRA7XX_CORE_IOPAD(0x3498, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a22.mmc2_dat7 */
+		>;
+	};
+
+	dcan1_pins_default: dcan1_pins_default {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x37d0, PIN_OUTPUT_PULLUP | MUX_MODE0) /* dcan1_tx */
+			DRA7XX_CORE_IOPAD(0x3818, PULL_UP | MUX_MODE1)	/* wakeup0.dcan1_rx */
+		>;
+	};
+
+	dcan1_pins_sleep: dcan1_pins_sleep {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x37d0, MUX_MODE15 | PULL_UP)	/* dcan1_tx.off */
+			DRA7XX_CORE_IOPAD(0x3818, MUX_MODE15 | PULL_UP)	/* wakeup0.off */
+		>;
+	};
+
+	hdmi_pins: pinmux_hdmi_pins {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x3808, PIN_INPUT | MUX_MODE1) /* i2c2_sda.hdmi1_ddc_scl */
+			DRA7XX_CORE_IOPAD(0x380c, PIN_INPUT | MUX_MODE1) /* i2c2_scl.hdmi1_ddc_sda */
+		>;
+	};
+
+	tpd12s015_pins: pinmux_tpd12s015_pins {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x37b8, PIN_INPUT_PULLDOWN | MUX_MODE14) /* gpio7_12 HPD */
+		>;
+	};
+
+	atl_pins: pinmux_atl_pins {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x3698, PIN_OUTPUT | MUX_MODE5)	/* xref_clk1.atl_clk1 */
+			DRA7XX_CORE_IOPAD(0x369c, PIN_OUTPUT | MUX_MODE5)	/* xref_clk2.atl_clk2 */
+		>;
+	};
+
+	mcasp3_pins: pinmux_mcasp3_pins {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x3724, PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* mcasp3_aclkx */
+			DRA7XX_CORE_IOPAD(0x3728, PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* mcasp3_fsx */
+			DRA7XX_CORE_IOPAD(0x372c, PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* mcasp3_axr0 */
+			DRA7XX_CORE_IOPAD(0x3730, PIN_INPUT_PULLDOWN | MUX_MODE0)	/* mcasp3_axr1 */
+		>;
+	};
+
+	mcasp3_sleep_pins: pinmux_mcasp3_sleep_pins {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x3724, PIN_INPUT_PULLDOWN | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x3728, PIN_INPUT_PULLDOWN | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x372c, PIN_INPUT_PULLDOWN | MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x3730, PIN_INPUT_PULLDOWN | MUX_MODE15)
+		>;
+	};
+};
+
+&i2c1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
+	clock-frequency = <400000>;
+
+	tps65917: tps65917@58 {
+		compatible = "ti,tps65917";
+		reg = <0x58>;
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&tps65917_pins_default>;
+
+		interrupts = <GIC_SPI 2 IRQ_TYPE_NONE>;  /* IRQ_SYS_1N */
+		interrupt-controller;
+		#interrupt-cells = <2>;
+
+		ti,system-power-controller;
+
+		tps65917_pmic {
+			compatible = "ti,tps65917-pmic";
+
+			tps65917_regulators: regulators {
+				smps1_reg: smps1 {
+					/* VDD_MPU */
+					regulator-name = "smps1";
+					regulator-min-microvolt = <850000>;
+					regulator-max-microvolt = <1250000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				smps2_reg: smps2 {
+					/* VDD_CORE */
+					regulator-name = "smps2";
+					regulator-min-microvolt = <850000>;
+					regulator-max-microvolt = <1150000>;
+					regulator-boot-on;
+					regulator-always-on;
+				};
+
+				smps3_reg: smps3 {
+					/* VDD_GPU IVA DSPEVE */
+					regulator-name = "smps3";
+					regulator-min-microvolt = <850000>;
+					regulator-max-microvolt = <1250000>;
+					regulator-boot-on;
+					regulator-always-on;
+				};
+
+				smps4_reg: smps4 {
+					/* VDDS1V8 */
+					regulator-name = "smps4";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				smps5_reg: smps5 {
+					/* VDD_DDR */
+					regulator-name = "smps5";
+					regulator-min-microvolt = <1350000>;
+					regulator-max-microvolt = <1350000>;
+					regulator-boot-on;
+					regulator-always-on;
+				};
+
+				ldo1_reg: ldo1 {
+					/* LDO1_OUT --> SDIO  */
+					regulator-name = "ldo1";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-always-on;
+					regulator-boot-on;
+					regulator-allow-bypass;
+				};
+
+				ldo3_reg: ldo3 {
+					/* VDDA_1V8_PHY */
+					regulator-name = "ldo3";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-boot-on;
+					regulator-always-on;
+				};
+
+				ldo5_reg: ldo5 {
+					/* VDDA_1V8_PLL */
+					regulator-name = "ldo5";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+
+				ldo4_reg: ldo4 {
+					/* VDDA_3V_USB: VDDA_USBHS33 */
+					regulator-name = "ldo4";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-boot-on;
+				};
+			};
+		};
+
+		tps65917_power_button {
+			compatible = "ti,palmas-pwrbutton";
+			interrupt-parent = <&tps65917>;
+			interrupts = <1 IRQ_TYPE_NONE>;
+			wakeup-source;
+			ti,palmas-long-press-seconds = <6>;
+		};
+	};
+
+	pcf_gpio_21: gpio@21 {
+		compatible = "ti,pcf8575", "nxp,pcf8575";
+		reg = <0x21>;
+		lines-initial-states = <0x1408>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	tlv320aic3106: tlv320aic3106@19 {
+		#sound-dai-cells = <0>;
+		compatible = "ti,tlv320aic3106";
+		reg = <0x19>;
+		adc-settle-ms = <40>;
+		ai3x-micbias-vg = <1>;		/* 2.0V */
+		status = "okay";
+
+		/* Regulators */
+		AVDD-supply = <&evm_3v3>;
+		IOVDD-supply = <&evm_3v3>;
+		DRVDD-supply = <&evm_3v3>;
+		DVDD-supply = <&aic_dvdd>;
+	};
+};
+
+&i2c5 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c5_pins>;
+	clock-frequency = <400000>;
+
+	pcf_hdmi: pcf8575@26 {
+		compatible = "ti,pcf8575", "nxp,pcf8575";
+		reg = <0x26>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		/*
+		 * initial state is used here to keep the mdio interface
+		 * selected on RU89 through SEL_VIN4_MUX_S0, VIN2_S1 and
+		 * VIN2_S0 driven high otherwise Ethernet stops working
+		 * VIN6_SEL_S0 is low, thus selecting McASP3 over VIN6
+		 */
+		lines-initial-states = <0x0f2b>;
+
+		p1 {
+			/* vin6_sel_s0: high: VIN6, low: audio */
+			gpio-hog;
+			gpios = <1 GPIO_ACTIVE_HIGH>;
+			output-low;
+			line-name = "vin6_sel_s0";
+		};
+	};
+};
+
+&uart1 {
+	status = "okay";
+	interrupts-extended = <&crossbar_mpu GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>,
+			      <&dra7_pmx_core 0x3e0>;
+};
+
+&elm {
+	status = "okay";
+};
+
+&gpmc {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&nand_default>;
+	ranges = <0 0 0x08000000 0x01000000>;	/* minimum GPMC partition = 16MB */
+	nand@0,0 {
+		/* To use NAND, DIP switch SW5 must be set like so:
+		 * SW5.1 (NAND_SELn) = ON (LOW)
+		 * SW5.9 (GPMC_WPN) = OFF (HIGH)
+		 */
+		compatible = "ti,omap2-nand";
+		reg = <0 0 4>;		/* device IO registers */
+		interrupt-parent = <&gpmc>;
+		interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
+			     <1 IRQ_TYPE_NONE>;	/* termcount */
+		rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 pin */
+		ti,nand-ecc-opt = "bch8";
+		ti,elm-id = <&elm>;
+		nand-bus-width = <16>;
+		gpmc,device-width = <2>;
+		gpmc,sync-clk-ps = <0>;
+		gpmc,cs-on-ns = <0>;
+		gpmc,cs-rd-off-ns = <80>;
+		gpmc,cs-wr-off-ns = <80>;
+		gpmc,adv-on-ns = <0>;
+		gpmc,adv-rd-off-ns = <60>;
+		gpmc,adv-wr-off-ns = <60>;
+		gpmc,we-on-ns = <10>;
+		gpmc,we-off-ns = <50>;
+		gpmc,oe-on-ns = <4>;
+		gpmc,oe-off-ns = <40>;
+		gpmc,access-ns = <40>;
+		gpmc,wr-access-ns = <80>;
+		gpmc,rd-cycle-ns = <80>;
+		gpmc,wr-cycle-ns = <80>;
+		gpmc,bus-turnaround-ns = <0>;
+		gpmc,cycle2cycle-delay-ns = <0>;
+		gpmc,clk-activation-ns = <0>;
+		gpmc,wr-data-mux-bus-ns = <0>;
+		/* MTD partition table */
+		/* All SPL-* partitions are sized to minimal length
+		 * which can be independently programmable. For
+		 * NAND flash this is equal to size of erase-block */
+		#address-cells = <1>;
+		#size-cells = <1>;
+		partition@0 {
+			label = "NAND.SPL";
+			reg = <0x00000000 0x000020000>;
+		};
+		partition@1 {
+			label = "NAND.SPL.backup1";
+			reg = <0x00020000 0x00020000>;
+		};
+		partition@2 {
+			label = "NAND.SPL.backup2";
+			reg = <0x00040000 0x00020000>;
+		};
+		partition@3 {
+			label = "NAND.SPL.backup3";
+			reg = <0x00060000 0x00020000>;
+		};
+		partition@4 {
+			label = "NAND.u-boot-spl-os";
+			reg = <0x00080000 0x00040000>;
+		};
+		partition@5 {
+			label = "NAND.u-boot";
+			reg = <0x000c0000 0x00100000>;
+		};
+		partition@6 {
+			label = "NAND.u-boot-env";
+			reg = <0x001c0000 0x00020000>;
+		};
+		partition@7 {
+			label = "NAND.u-boot-env.backup1";
+			reg = <0x001e0000 0x00020000>;
+		};
+		partition@8 {
+			label = "NAND.kernel";
+			reg = <0x00200000 0x00800000>;
+		};
+		partition@9 {
+			label = "NAND.file-system";
+			reg = <0x00a00000 0x0f600000>;
+		};
+	};
+};
+
+&usb2_phy1 {
+	phy-supply = <&ldo4_reg>;
+};
+
+&usb2_phy2 {
+	phy-supply = <&ldo4_reg>;
+};
+
+&omap_dwc3_1 {
+	extcon = <&extcon_usb1>;
+};
+
+&omap_dwc3_2 {
+	extcon = <&extcon_usb2>;
+};
+
+&usb1 {
+	dr_mode = "peripheral";
+	pinctrl-names = "default";
+	pinctrl-0 = <&usb1_pins>;
+};
+
+&usb2 {
+	dr_mode = "host";
+	pinctrl-names = "default";
+	pinctrl-0 = <&usb2_pins>;
+};
+
+&mmc1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins_default>;
+	vmmc-supply = <&evm_3v3_sd>;
+	vmmc_aux-supply = <&ldo1_reg>;
+	bus-width = <4>;
+	/*
+	 * SDCD signal is not being used here - using the fact that GPIO mode
+	 * is a viable alternative
+	 */
+	cd-gpios = <&gpio6 27 GPIO_ACTIVE_LOW>;
+	max-frequency = <192000000>;
+};
+
+&mmc2 {
+	/* SW5-3 in ON position */
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc2_pins_default>;
+
+	vmmc-supply = <&evm_3v3>;
+	bus-width = <8>;
+	ti,non-removable;
+	max-frequency = <192000000>;
+};
+
+&dra7_pmx_core {
+	cpsw_default: cpsw_default {
+		pinctrl-single,pins = <
+			/* Slave 2 */
+			DRA7XX_CORE_IOPAD(0x3598, PIN_OUTPUT | MUX_MODE3)	/* vin2a_d12.rgmii1_txc */
+			DRA7XX_CORE_IOPAD(0x359c, PIN_OUTPUT | MUX_MODE3)	/* vin2a_d13.rgmii1_tctl */
+			DRA7XX_CORE_IOPAD(0x35a0, PIN_OUTPUT | MUX_MODE3)	/* vin2a_d14.rgmii1_td3 */
+			DRA7XX_CORE_IOPAD(0x35a4, PIN_OUTPUT | MUX_MODE3)	/* vin2a_d15.rgmii1_td2 */
+			DRA7XX_CORE_IOPAD(0x35a8, PIN_OUTPUT | MUX_MODE3)	/* vin2a_d16.rgmii1_td1 */
+			DRA7XX_CORE_IOPAD(0x35ac, PIN_OUTPUT | MUX_MODE3)	/* vin2a_d17.rgmii1_td0 */
+			DRA7XX_CORE_IOPAD(0x35b0, PIN_INPUT | MUX_MODE3)	/* vin2a_d18.rgmii1_rclk */
+			DRA7XX_CORE_IOPAD(0x35b4, PIN_INPUT | MUX_MODE3)	/* vin2a_d19.rgmii1_rctl */
+			DRA7XX_CORE_IOPAD(0x35b8, PIN_INPUT | MUX_MODE3)	/* vin2a_d20.rgmii1_rd3 */
+			DRA7XX_CORE_IOPAD(0x35bc, PIN_INPUT | MUX_MODE3)	/* vin2a_d21.rgmii1_rd2 */
+			DRA7XX_CORE_IOPAD(0x35c0, PIN_INPUT | MUX_MODE3)	/* vin2a_d22.rgmii1_rd1 */
+			DRA7XX_CORE_IOPAD(0x35c4, PIN_INPUT | MUX_MODE3)	/* vin2a_d23.rgmii1_rd0 */
+		>;
+
+	};
+
+	cpsw_sleep: cpsw_sleep {
+		pinctrl-single,pins = <
+			/* Slave 2 */
+			DRA7XX_CORE_IOPAD(0x3598, MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x359c, MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x35a0, MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x35a4, MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x35a8, MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x35ac, MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x35b0, MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x35b4, MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x35b8, MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x35bc, MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x35c0, MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x35c4, MUX_MODE15)
+		>;
+	};
+
+	davinci_mdio_default: davinci_mdio_default {
+		pinctrl-single,pins = <
+			/* MDIO */
+			DRA7XX_CORE_IOPAD(0x363c, PIN_OUTPUT_PULLUP | MUX_MODE0)	/* mdio_d.mdio_d */
+			DRA7XX_CORE_IOPAD(0x3640, PIN_INPUT_PULLUP | MUX_MODE0)	/* mdio_clk.mdio_clk */
+		>;
+	};
+
+	davinci_mdio_sleep: davinci_mdio_sleep {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x363c, MUX_MODE15)
+			DRA7XX_CORE_IOPAD(0x3640, MUX_MODE15)
+		>;
+	};
+};
+
+&mac {
+	status = "okay";
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&cpsw_default>;
+	pinctrl-1 = <&cpsw_sleep>;
+};
+
+&davinci_mdio {
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&davinci_mdio_default>;
+	pinctrl-1 = <&davinci_mdio_sleep>;
+};
+
+&dcan1 {
+	status = "ok";
+	pinctrl-names = "default", "sleep", "active";
+	pinctrl-0 = <&dcan1_pins_sleep>;
+	pinctrl-1 = <&dcan1_pins_sleep>;
+	pinctrl-2 = <&dcan1_pins_default>;
+};
+
+&qspi {
+	status = "okay";
+
+	spi-max-frequency = <64000000>;
+	m25p80@0 {
+		compatible = "s25fl256s1";
+		spi-max-frequency = <64000000>;
+		reg = <0>;
+		spi-tx-bus-width = <1>;
+		spi-rx-bus-width = <4>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		/* MTD partition table.
+		 * The ROM checks the first four physical blocks
+		 * for a valid file to boot and the flash here is
+		 * 64KiB block size.
+		 */
+		partition@0 {
+			label = "QSPI.SPL";
+			reg = <0x00000000 0x000010000>;
+		};
+		partition@1 {
+			label = "QSPI.SPL.backup1";
+			reg = <0x00010000 0x00010000>;
+		};
+		partition@2 {
+			label = "QSPI.SPL.backup2";
+			reg = <0x00020000 0x00010000>;
+		};
+		partition@3 {
+			label = "QSPI.SPL.backup3";
+			reg = <0x00030000 0x00010000>;
+		};
+		partition@4 {
+			label = "QSPI.u-boot";
+			reg = <0x00040000 0x00100000>;
+		};
+		partition@5 {
+			label = "QSPI.u-boot-spl-os";
+			reg = <0x00140000 0x00080000>;
+		};
+		partition@6 {
+			label = "QSPI.u-boot-env";
+			reg = <0x001c0000 0x00010000>;
+		};
+		partition@7 {
+			label = "QSPI.u-boot-env.backup1";
+			reg = <0x001d0000 0x0010000>;
+		};
+		partition@8 {
+			label = "QSPI.kernel";
+			reg = <0x001e0000 0x0800000>;
+		};
+		partition@9 {
+			label = "QSPI.file-system";
+			reg = <0x009e0000 0x01620000>;
+		};
+	};
+};
+
+&dss {
+	status = "ok";
+
+	vdda_video-supply = <&ldo5_reg>;
+};
+
+&hdmi {
+	status = "ok";
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&hdmi_pins>;
+
+	port {
+		hdmi_out: endpoint {
+			remote-endpoint = <&tpd12s015_in>;
+		};
+	};
+};
+
+&atl {
+	pinctrl-names = "default";
+	pinctrl-0 = <&atl_pins>;
+
+	assigned-clocks = <&abe_dpll_sys_clk_mux>,
+			  <&atl_gfclk_mux>,
+			  <&dpll_abe_ck>,
+			  <&dpll_abe_m2x2_ck>,
+			  <&atl_clkin2_ck>;
+	assigned-clock-parents = <&sys_clkin2>, <&dpll_abe_m2_ck>;
+	assigned-clock-rates = <0>, <0>, <180633600>, <361267200>, <5644800>;
+
+	status = "okay";
+
+	atl2 {
+		bws = <DRA7_ATL_WS_MCASP2_FSX>;
+		aws = <DRA7_ATL_WS_MCASP3_FSX>;
+	};
+};
+
+&mcasp3 {
+	#sound-dai-cells = <0>;
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&mcasp3_pins>;
+	pinctrl-1 = <&mcasp3_sleep_pins>;
+
+	assigned-clocks = <&mcasp3_ahclkx_mux>;
+	assigned-clock-parents = <&atl_clkin2_ck>;
+
+	status = "okay";
+
+	op-mode = <0>;          /* MCASP_IIS_MODE */
+	tdm-slots = <2>;
+	/* 4 serializer */
+	serial-dir = <  /* 0: INACTIVE, 1: TX, 2: RX */
+		1 2 0 0
+	>;
+	tx-num-evt = <32>;
+	rx-num-evt = <32>;
+};
+
+&mailbox5 {
+	status = "okay";
+	mbox_ipu1_ipc3x: mbox_ipu1_ipc3x {
+		status = "okay";
+	};
+	mbox_dsp1_ipc3x: mbox_dsp1_ipc3x {
+		status = "okay";
+	};
+};
+
+&mailbox6 {
+	status = "okay";
+	mbox_ipu2_ipc3x: mbox_ipu2_ipc3x {
+		status = "okay";
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/dra72-evm.dts linux-libre-4.7-gnu/arch/arm/boot/dts/dra72-evm.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/dra72-evm.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/dra72-evm.dts	2016-07-24 15:23:50.000000000 -0400
@@ -1,694 +1,40 @@
 /*
- * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C) 2014-2016 Texas Instruments Incorporated - http://www.ti.com/
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-/dts-v1/;
-
-#include "dra72x.dtsi"
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/clk/ti-dra7-atl.h>
-
+#include "dra72-evm-common.dtsi"
 / {
 	model = "TI DRA722";
-	compatible = "ti,dra72-evm", "ti,dra722", "ti,dra72", "ti,dra7";
 
 	memory {
 		device_type = "memory";
 		reg = <0x0 0x80000000 0x0 0x40000000>; /* 1024 MB */
 	};
+};
 
-	aliases {
-		display0 = &hdmi0;
-	};
-
-	evm_3v3: fixedregulator-evm_3v3 {
-		compatible = "regulator-fixed";
-		regulator-name = "evm_3v3";
-		regulator-min-microvolt = <3300000>;
-		regulator-max-microvolt = <3300000>;
-	};
-
-	aic_dvdd: fixedregulator-aic_dvdd {
-		/* TPS77018DBVT */
-		compatible = "regulator-fixed";
-		regulator-name = "aic_dvdd";
-		vin-supply = <&evm_3v3>;
+&tps65917_regulators {
+	ldo2_reg: ldo2 {
+		/* LDO2_OUT --> TP1017 (UNUSED)  */
+		regulator-name = "ldo2";
 		regulator-min-microvolt = <1800000>;
-		regulator-max-microvolt = <1800000>;
-	};
-
-	evm_3v3_sd: fixedregulator-sd {
-		compatible = "regulator-fixed";
-		regulator-name = "evm_3v3_sd";
-		regulator-min-microvolt = <3300000>;
 		regulator-max-microvolt = <3300000>;
-		enable-active-high;
-		gpio = <&pcf_gpio_21 5 GPIO_ACTIVE_HIGH>;
-	};
-
-	extcon_usb1: extcon_usb1 {
-		compatible = "linux,extcon-usb-gpio";
-		id-gpio = <&pcf_gpio_21 1 GPIO_ACTIVE_HIGH>;
-	};
-
-	extcon_usb2: extcon_usb2 {
-		compatible = "linux,extcon-usb-gpio";
-		id-gpio = <&pcf_gpio_21 2 GPIO_ACTIVE_HIGH>;
-	};
-
-	hdmi0: connector {
-		compatible = "hdmi-connector";
-		label = "hdmi";
-
-		type = "a";
-
-		port {
-			hdmi_connector_in: endpoint {
-				remote-endpoint = <&tpd12s015_out>;
-			};
-		};
-	};
-
-	tpd12s015: encoder {
-		compatible = "ti,tpd12s015";
-
-		pinctrl-names = "default";
-		pinctrl-0 = <&tpd12s015_pins>;
-
-		gpios = <&pcf_hdmi 4 GPIO_ACTIVE_HIGH>,	/* P4, CT CP HPD */
-			<&pcf_hdmi 5 GPIO_ACTIVE_HIGH>,	/* P5, LS OE */
-			<&gpio7 12 GPIO_ACTIVE_HIGH>;	/* gpio7_12/sp1_cs2, HPD */
-
-		ports {
-			#address-cells = <1>;
-			#size-cells = <0>;
-
-			port@0 {
-				reg = <0>;
-
-				tpd12s015_in: endpoint {
-					remote-endpoint = <&hdmi_out>;
-				};
-			};
-
-			port@1 {
-				reg = <1>;
-
-				tpd12s015_out: endpoint {
-					remote-endpoint = <&hdmi_connector_in>;
-				};
-			};
-		};
-	};
-
-	sound0: sound@0 {
-		compatible = "simple-audio-card";
-		simple-audio-card,name = "DRA7xx-EVM";
-		simple-audio-card,widgets =
-			"Headphone", "Headphone Jack",
-			"Line", "Line Out",
-			"Microphone", "Mic Jack",
-			"Line", "Line In";
-		simple-audio-card,routing =
-			"Headphone Jack",       "HPLOUT",
-			"Headphone Jack",       "HPROUT",
-			"Line Out",		"LLOUT",
-			"Line Out",		"RLOUT",
-			"MIC3L",		"Mic Jack",
-			"MIC3R",		"Mic Jack",
-			"Mic Jack",		"Mic Bias",
-			"LINE1L",               "Line In",
-			"LINE1R",               "Line In";
-		simple-audio-card,format = "dsp_b";
-		simple-audio-card,bitclock-master = <&sound0_master>;
-		simple-audio-card,frame-master = <&sound0_master>;
-		simple-audio-card,bitclock-inversion;
-
-		sound0_master: simple-audio-card,cpu {
-			sound-dai = <&mcasp3>;
-			system-clock-frequency = <5644800>;
-		};
-
-		simple-audio-card,codec {
-			sound-dai = <&tlv320aic3106>;
-			clocks = <&atl_clkin2_ck>;
-		};
-	};
-};
-
-&dra7_pmx_core {
-	i2c1_pins: pinmux_i2c1_pins {
-		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x3800, PIN_INPUT | MUX_MODE0) /* i2c1_sda.i2c1_sda */
-			DRA7XX_CORE_IOPAD(0x3804, PIN_INPUT | MUX_MODE0) /* i2c1_scl.i2c1_scl */
-		>;
-	};
-
-	i2c5_pins: pinmux_i2c5_pins {
-		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x36b4, PIN_INPUT | MUX_MODE10) /* mcasp1_axr0.i2c5_sda */
-			DRA7XX_CORE_IOPAD(0x36b8, PIN_INPUT | MUX_MODE10) /* mcasp1_axr1.i2c5_scl */
-		>;
-	};
-
-	i2c5_pins: pinmux_i2c5_pins {
-		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x36b4, PIN_INPUT | MUX_MODE10) /* mcasp1_axr0.i2c5_sda */
-			DRA7XX_CORE_IOPAD(0x36b8, PIN_INPUT | MUX_MODE10) /* mcasp1_axr1.i2c5_scl */
-		>;
-	};
-
-	nand_default: nand_default {
-		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x3400, PIN_INPUT  | MUX_MODE0) /* gpmc_ad0 */
-			DRA7XX_CORE_IOPAD(0x3404, PIN_INPUT  | MUX_MODE0) /* gpmc_ad1 */
-			DRA7XX_CORE_IOPAD(0x3408, PIN_INPUT  | MUX_MODE0) /* gpmc_ad2 */
-			DRA7XX_CORE_IOPAD(0x340c, PIN_INPUT  | MUX_MODE0) /* gpmc_ad3 */
-			DRA7XX_CORE_IOPAD(0x3410, PIN_INPUT  | MUX_MODE0) /* gpmc_ad4 */
-			DRA7XX_CORE_IOPAD(0x3414, PIN_INPUT  | MUX_MODE0) /* gpmc_ad5 */
-			DRA7XX_CORE_IOPAD(0x3418, PIN_INPUT  | MUX_MODE0) /* gpmc_ad6 */
-			DRA7XX_CORE_IOPAD(0x341c, PIN_INPUT  | MUX_MODE0) /* gpmc_ad7 */
-			DRA7XX_CORE_IOPAD(0x3420, PIN_INPUT  | MUX_MODE0) /* gpmc_ad8 */
-			DRA7XX_CORE_IOPAD(0x3424, PIN_INPUT  | MUX_MODE0) /* gpmc_ad9 */
-			DRA7XX_CORE_IOPAD(0x3428, PIN_INPUT  | MUX_MODE0) /* gpmc_ad10 */
-			DRA7XX_CORE_IOPAD(0x342c, PIN_INPUT  | MUX_MODE0) /* gpmc_ad11 */
-			DRA7XX_CORE_IOPAD(0x3430, PIN_INPUT  | MUX_MODE0) /* gpmc_ad12 */
-			DRA7XX_CORE_IOPAD(0x3434, PIN_INPUT  | MUX_MODE0) /* gpmc_ad13 */
-			DRA7XX_CORE_IOPAD(0x3438, PIN_INPUT  | MUX_MODE0) /* gpmc_ad14 */
-			DRA7XX_CORE_IOPAD(0x343c, PIN_INPUT  | MUX_MODE0) /* gpmc_ad15 */
-			DRA7XX_CORE_IOPAD(0x34b4, PIN_OUTPUT | MUX_MODE0) /* gpmc_cs0 */
-			DRA7XX_CORE_IOPAD(0x34c4, PIN_OUTPUT | MUX_MODE0) /* gpmc_advn_ale */
-			DRA7XX_CORE_IOPAD(0x34cc, PIN_OUTPUT | MUX_MODE0) /* gpmc_wen */
-			DRA7XX_CORE_IOPAD(0x34c8, PIN_OUTPUT | MUX_MODE0) /* gpmc_oen_ren */
-			DRA7XX_CORE_IOPAD(0x34d0, PIN_OUTPUT | MUX_MODE0) /* gpmc_ben0 */
-			DRA7XX_CORE_IOPAD(0x34d8, PIN_INPUT  | MUX_MODE0) /* gpmc_wait0 */
-		>;
-	};
-
-	usb1_pins: pinmux_usb1_pins {
-		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x3680, PIN_INPUT_SLEW | MUX_MODE0) /* usb1_drvvbus */
-		>;
-	};
-
-	usb2_pins: pinmux_usb2_pins {
-		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x3684, PIN_INPUT_SLEW | MUX_MODE0) /* usb2_drvvbus */
-		>;
-	};
-
-	tps65917_pins_default: tps65917_pins_default {
-		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x3824, PIN_INPUT_PULLUP | MUX_MODE1) /* wakeup3.sys_nirq1 */
-		>;
-	};
-
-	mmc1_pins_default: mmc1_pins_default {
-		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x376c, PIN_INPUT | MUX_MODE14)	/* mmc1sdcd.gpio219 */
-			DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_clk.clk */
-			DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_cmd.cmd */
-			DRA7XX_CORE_IOPAD(0x375c, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat0.dat0 */
-			DRA7XX_CORE_IOPAD(0x3760, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat1.dat1 */
-			DRA7XX_CORE_IOPAD(0x3764, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat2.dat2 */
-			DRA7XX_CORE_IOPAD(0x3768, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat3.dat3 */
-		>;
-	};
-
-	mmc2_pins_default: mmc2_pins_default {
-		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x349c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a23.mmc2_clk */
-			DRA7XX_CORE_IOPAD(0x34b0, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_cs1.mmc2_cmd */
-			DRA7XX_CORE_IOPAD(0x34a0, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a24.mmc2_dat0 */
-			DRA7XX_CORE_IOPAD(0x34a4, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a25.mmc2_dat1 */
-			DRA7XX_CORE_IOPAD(0x34a8, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a26.mmc2_dat2 */
-			DRA7XX_CORE_IOPAD(0x34ac, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a27.mmc2_dat3 */
-			DRA7XX_CORE_IOPAD(0x348c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a19.mmc2_dat4 */
-			DRA7XX_CORE_IOPAD(0x3490, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a20.mmc2_dat5 */
-			DRA7XX_CORE_IOPAD(0x3494, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a21.mmc2_dat6 */
-			DRA7XX_CORE_IOPAD(0x3498, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a22.mmc2_dat7 */
-		>;
-	};
-
-	dcan1_pins_default: dcan1_pins_default {
-		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x37d0, PIN_OUTPUT_PULLUP | MUX_MODE0) /* dcan1_tx */
-			DRA7XX_CORE_IOPAD(0x3818, PULL_UP | MUX_MODE1)	/* wakeup0.dcan1_rx */
-		>;
-	};
-
-	dcan1_pins_sleep: dcan1_pins_sleep {
-		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x37d0, MUX_MODE15 | PULL_UP)	/* dcan1_tx.off */
-			DRA7XX_CORE_IOPAD(0x3818, MUX_MODE15 | PULL_UP)	/* wakeup0.off */
-		>;
-	};
-
-	qspi1_pins: pinmux_qspi1_pins {
-		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x3474, PIN_OUTPUT | MUX_MODE1)	/* gpmc_a13.qspi1_rtclk */
-			DRA7XX_CORE_IOPAD(0x3478, PIN_INPUT | MUX_MODE1)	/* gpmc_a14.qspi1_d3 */
-			DRA7XX_CORE_IOPAD(0x347c, PIN_INPUT | MUX_MODE1)	/* gpmc_a15.qspi1_d2 */
-			DRA7XX_CORE_IOPAD(0x3480, PIN_INPUT | MUX_MODE1)	/* gpmc_a16.qspi1_d1 */
-			DRA7XX_CORE_IOPAD(0x3484, PIN_INPUT | MUX_MODE1)	/* gpmc_a17.qspi1_d0 */
-			DRA7XX_CORE_IOPAD(0x3488, PIN_OUTPUT | MUX_MODE1)	/* qpmc_a18.qspi1_sclk */
-			DRA7XX_CORE_IOPAD(0x34b8, PIN_OUTPUT | MUX_MODE1)	/* gpmc_cs2.qspi1_cs0 */
-		>;
-	};
-
-	hdmi_pins: pinmux_hdmi_pins {
-		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x3808, PIN_INPUT | MUX_MODE1) /* i2c2_sda.hdmi1_ddc_scl */
-			DRA7XX_CORE_IOPAD(0x380c, PIN_INPUT | MUX_MODE1) /* i2c2_scl.hdmi1_ddc_sda */
-		>;
-	};
-
-	tpd12s015_pins: pinmux_tpd12s015_pins {
-		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x37b8, PIN_INPUT_PULLDOWN | MUX_MODE14) /* gpio7_12 HPD */
-		>;
-	};
-
-	atl_pins: pinmux_atl_pins {
-		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x3698, PIN_OUTPUT | MUX_MODE5)	/* xref_clk1.atl_clk1 */
-			DRA7XX_CORE_IOPAD(0x369c, PIN_OUTPUT | MUX_MODE5)	/* xref_clk2.atl_clk2 */
-		>;
-	};
-
-	mcasp3_pins: pinmux_mcasp3_pins {
-		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x3724, PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* mcasp3_aclkx */
-			DRA7XX_CORE_IOPAD(0x3728, PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* mcasp3_fsx */
-			DRA7XX_CORE_IOPAD(0x372c, PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* mcasp3_axr0 */
-			DRA7XX_CORE_IOPAD(0x3730, PIN_INPUT_PULLDOWN | MUX_MODE0)	/* mcasp3_axr1 */
-		>;
-	};
-
-	mcasp3_sleep_pins: pinmux_mcasp3_sleep_pins {
-		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x3724, PIN_INPUT_PULLDOWN | MUX_MODE15)
-			DRA7XX_CORE_IOPAD(0x3728, PIN_INPUT_PULLDOWN | MUX_MODE15)
-			DRA7XX_CORE_IOPAD(0x372c, PIN_INPUT_PULLDOWN | MUX_MODE15)
-			DRA7XX_CORE_IOPAD(0x3730, PIN_INPUT_PULLDOWN | MUX_MODE15)
-		>;
-	};
-};
-
-&i2c1 {
-	status = "okay";
-	pinctrl-names = "default";
-	pinctrl-0 = <&i2c1_pins>;
-	clock-frequency = <400000>;
-
-	tps65917: tps65917@58 {
-		compatible = "ti,tps65917";
-		reg = <0x58>;
-
-		pinctrl-names = "default";
-		pinctrl-0 = <&tps65917_pins_default>;
-
-		interrupts = <GIC_SPI 2 IRQ_TYPE_NONE>;  /* IRQ_SYS_1N */
-		interrupt-controller;
-		#interrupt-cells = <2>;
-
-		ti,system-power-controller;
-
-		tps65917_pmic {
-			compatible = "ti,tps65917-pmic";
-
-			regulators {
-				smps1_reg: smps1 {
-					/* VDD_MPU */
-					regulator-name = "smps1";
-					regulator-min-microvolt = <850000>;
-					regulator-max-microvolt = <1250000>;
-					regulator-always-on;
-					regulator-boot-on;
-				};
-
-				smps2_reg: smps2 {
-					/* VDD_CORE */
-					regulator-name = "smps2";
-					regulator-min-microvolt = <850000>;
-					regulator-max-microvolt = <1060000>;
-					regulator-boot-on;
-					regulator-always-on;
-				};
-
-				smps3_reg: smps3 {
-					/* VDD_GPU IVA DSPEVE */
-					regulator-name = "smps3";
-					regulator-min-microvolt = <850000>;
-					regulator-max-microvolt = <1250000>;
-					regulator-boot-on;
-					regulator-always-on;
-				};
-
-				smps4_reg: smps4 {
-					/* VDDS1V8 */
-					regulator-name = "smps4";
-					regulator-min-microvolt = <1800000>;
-					regulator-max-microvolt = <1800000>;
-					regulator-always-on;
-					regulator-boot-on;
-				};
-
-				smps5_reg: smps5 {
-					/* VDD_DDR */
-					regulator-name = "smps5";
-					regulator-min-microvolt = <1350000>;
-					regulator-max-microvolt = <1350000>;
-					regulator-boot-on;
-					regulator-always-on;
-				};
-
-				ldo1_reg: ldo1 {
-					/* LDO1_OUT --> SDIO  */
-					regulator-name = "ldo1";
-					regulator-min-microvolt = <1800000>;
-					regulator-max-microvolt = <3300000>;
-					regulator-always-on;
-					regulator-boot-on;
-					regulator-allow-bypass;
-				};
-
-				ldo2_reg: ldo2 {
-					/* LDO2_OUT --> TP1017 (UNUSED)  */
-					regulator-name = "ldo2";
-					regulator-min-microvolt = <1800000>;
-					regulator-max-microvolt = <3300000>;
-					regulator-allow-bypass;
-				};
-
-				ldo3_reg: ldo3 {
-					/* VDDA_1V8_PHY */
-					regulator-name = "ldo3";
-					regulator-min-microvolt = <1800000>;
-					regulator-max-microvolt = <1800000>;
-					regulator-boot-on;
-					regulator-always-on;
-				};
-
-				ldo5_reg: ldo5 {
-					/* VDDA_1V8_PLL */
-					regulator-name = "ldo5";
-					regulator-min-microvolt = <1800000>;
-					regulator-max-microvolt = <1800000>;
-					regulator-always-on;
-					regulator-boot-on;
-				};
-
-				ldo4_reg: ldo4 {
-					/* VDDA_3V_USB: VDDA_USBHS33 */
-					regulator-name = "ldo4";
-					regulator-min-microvolt = <3300000>;
-					regulator-max-microvolt = <3300000>;
-					regulator-boot-on;
-				};
-			};
-		};
-
-		tps65917_power_button {
-			compatible = "ti,palmas-pwrbutton";
-			interrupt-parent = <&tps65917>;
-			interrupts = <1 IRQ_TYPE_NONE>;
-			wakeup-source;
-			ti,palmas-long-press-seconds = <6>;
-		};
-	};
-
-	pcf_gpio_21: gpio@21 {
-		compatible = "ti,pcf8575";
-		reg = <0x21>;
-		lines-initial-states = <0x1408>;
-		gpio-controller;
-		#gpio-cells = <2>;
-		interrupt-parent = <&gpio6>;
-		interrupts = <11 IRQ_TYPE_EDGE_FALLING>;
-		interrupt-controller;
-		#interrupt-cells = <2>;
-	};
-
-	tlv320aic3106: tlv320aic3106@19 {
-		#sound-dai-cells = <0>;
-		compatible = "ti,tlv320aic3106";
-		reg = <0x19>;
-		adc-settle-ms = <40>;
-		ai3x-micbias-vg = <1>;		/* 2.0V */
-		status = "okay";
-
-		/* Regulators */
-		AVDD-supply = <&evm_3v3>;
-		IOVDD-supply = <&evm_3v3>;
-		DRVDD-supply = <&evm_3v3>;
-		DVDD-supply = <&aic_dvdd>;
-	};
-};
-
-&i2c5 {
-	status = "okay";
-	pinctrl-names = "default";
-	pinctrl-0 = <&i2c5_pins>;
-	clock-frequency = <400000>;
-
-	pcf_hdmi: pcf8575@26 {
-		compatible = "nxp,pcf8575";
-		reg = <0x26>;
-		gpio-controller;
-		#gpio-cells = <2>;
-		/*
-		 * initial state is used here to keep the mdio interface
-		 * selected on RU89 through SEL_VIN4_MUX_S0, VIN2_S1 and
-		 * VIN2_S0 driven high otherwise Ethernet stops working
-		 * VIN6_SEL_S0 is low, thus selecting McASP3 over VIN6
-		 */
-		lines-initial-states = <0x0f2b>;
-
-		p1 {
-			/* vin6_sel_s0: high: VIN6, low: audio */
-			gpio-hog;
-			gpios = <1 GPIO_ACTIVE_HIGH>;
-			output-low;
-			line-name = "vin6_sel_s0";
-		};
-	};
-};
-
-&uart1 {
-	status = "okay";
-	interrupts-extended = <&crossbar_mpu GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>,
-			      <&dra7_pmx_core 0x3e0>;
-};
-
-&elm {
-	status = "okay";
-};
-
-&gpmc {
-	status = "okay";
-	pinctrl-names = "default";
-	pinctrl-0 = <&nand_default>;
-	ranges = <0 0 0x08000000 0x01000000>;	/* minimum GPMC partition = 16MB */
-	nand@0,0 {
-		/* To use NAND, DIP switch SW5 must be set like so:
-		 * SW5.1 (NAND_SELn) = ON (LOW)
-		 * SW5.9 (GPMC_WPN) = OFF (HIGH)
-		 */
-		compatible = "ti,omap2-nand";
-		reg = <0 0 4>;		/* device IO registers */
-		interrupt-parent = <&gpmc>;
-		interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
-			     <1 IRQ_TYPE_NONE>;	/* termcount */
-		ti,nand-ecc-opt = "bch8";
-		ti,elm-id = <&elm>;
-		nand-bus-width = <16>;
-		gpmc,device-width = <2>;
-		gpmc,sync-clk-ps = <0>;
-		gpmc,cs-on-ns = <0>;
-		gpmc,cs-rd-off-ns = <80>;
-		gpmc,cs-wr-off-ns = <80>;
-		gpmc,adv-on-ns = <0>;
-		gpmc,adv-rd-off-ns = <60>;
-		gpmc,adv-wr-off-ns = <60>;
-		gpmc,we-on-ns = <10>;
-		gpmc,we-off-ns = <50>;
-		gpmc,oe-on-ns = <4>;
-		gpmc,oe-off-ns = <40>;
-		gpmc,access-ns = <40>;
-		gpmc,wr-access-ns = <80>;
-		gpmc,rd-cycle-ns = <80>;
-		gpmc,wr-cycle-ns = <80>;
-		gpmc,bus-turnaround-ns = <0>;
-		gpmc,cycle2cycle-delay-ns = <0>;
-		gpmc,clk-activation-ns = <0>;
-		gpmc,wr-data-mux-bus-ns = <0>;
-		/* MTD partition table */
-		/* All SPL-* partitions are sized to minimal length
-		 * which can be independently programmable. For
-		 * NAND flash this is equal to size of erase-block */
-		#address-cells = <1>;
-		#size-cells = <1>;
-		partition@0 {
-			label = "NAND.SPL";
-			reg = <0x00000000 0x000020000>;
-		};
-		partition@1 {
-			label = "NAND.SPL.backup1";
-			reg = <0x00020000 0x00020000>;
-		};
-		partition@2 {
-			label = "NAND.SPL.backup2";
-			reg = <0x00040000 0x00020000>;
-		};
-		partition@3 {
-			label = "NAND.SPL.backup3";
-			reg = <0x00060000 0x00020000>;
-		};
-		partition@4 {
-			label = "NAND.u-boot-spl-os";
-			reg = <0x00080000 0x00040000>;
-		};
-		partition@5 {
-			label = "NAND.u-boot";
-			reg = <0x000c0000 0x00100000>;
-		};
-		partition@6 {
-			label = "NAND.u-boot-env";
-			reg = <0x001c0000 0x00020000>;
-		};
-		partition@7 {
-			label = "NAND.u-boot-env.backup1";
-			reg = <0x001e0000 0x00020000>;
-		};
-		partition@8 {
-			label = "NAND.kernel";
-			reg = <0x00200000 0x00800000>;
-		};
-		partition@9 {
-			label = "NAND.file-system";
-			reg = <0x00a00000 0x0f600000>;
-		};
+		regulator-allow-bypass;
 	};
 };
 
-&usb2_phy1 {
-	phy-supply = <&ldo4_reg>;
-};
-
-&usb2_phy2 {
-	phy-supply = <&ldo4_reg>;
-};
-
-&omap_dwc3_1 {
-	extcon = <&extcon_usb1>;
-};
-
-&omap_dwc3_2 {
-	extcon = <&extcon_usb2>;
-};
-
-&usb1 {
-	dr_mode = "peripheral";
-	pinctrl-names = "default";
-	pinctrl-0 = <&usb1_pins>;
-};
-
-&usb2 {
-	dr_mode = "host";
-	pinctrl-names = "default";
-	pinctrl-0 = <&usb2_pins>;
-};
-
-&mmc1 {
-	status = "okay";
-	pinctrl-names = "default";
-	pinctrl-0 = <&mmc1_pins_default>;
-	vmmc-supply = <&evm_3v3_sd>;
-	vmmc_aux-supply = <&ldo1_reg>;
-	bus-width = <4>;
-	/*
-	 * SDCD signal is not being used here - using the fact that GPIO mode
-	 * is a viable alternative
-	 */
-	cd-gpios = <&gpio6 27 GPIO_ACTIVE_LOW>;
-	max-frequency = <192000000>;
-};
-
-&mmc2 {
-	/* SW5-3 in ON position */
-	status = "okay";
-	pinctrl-names = "default";
-	pinctrl-0 = <&mmc2_pins_default>;
-
-	vmmc-supply = <&evm_3v3>;
-	bus-width = <8>;
-	ti,non-removable;
-	max-frequency = <192000000>;
+&hdmi {
+	vdda-supply = <&ldo3_reg>;
 };
 
-&dra7_pmx_core {
-	cpsw_default: cpsw_default {
-		pinctrl-single,pins = <
-			/* Slave 2 */
-			DRA7XX_CORE_IOPAD(0x3598, PIN_OUTPUT | MUX_MODE3)	/* vin2a_d12.rgmii1_txc */
-			DRA7XX_CORE_IOPAD(0x359c, PIN_OUTPUT | MUX_MODE3)	/* vin2a_d13.rgmii1_tctl */
-			DRA7XX_CORE_IOPAD(0x35a0, PIN_OUTPUT | MUX_MODE3)	/* vin2a_d14.rgmii1_td3 */
-			DRA7XX_CORE_IOPAD(0x35a4, PIN_OUTPUT | MUX_MODE3)	/* vin2a_d15.rgmii1_td2 */
-			DRA7XX_CORE_IOPAD(0x35a8, PIN_OUTPUT | MUX_MODE3)	/* vin2a_d16.rgmii1_td1 */
-			DRA7XX_CORE_IOPAD(0x35ac, PIN_OUTPUT | MUX_MODE3)	/* vin2a_d17.rgmii1_td0 */
-			DRA7XX_CORE_IOPAD(0x35b0, PIN_INPUT | MUX_MODE3)	/* vin2a_d18.rgmii1_rclk */
-			DRA7XX_CORE_IOPAD(0x35b4, PIN_INPUT | MUX_MODE3)	/* vin2a_d19.rgmii1_rctl */
-			DRA7XX_CORE_IOPAD(0x35b8, PIN_INPUT | MUX_MODE3)	/* vin2a_d20.rgmii1_rd3 */
-			DRA7XX_CORE_IOPAD(0x35bc, PIN_INPUT | MUX_MODE3)	/* vin2a_d21.rgmii1_rd2 */
-			DRA7XX_CORE_IOPAD(0x35c0, PIN_INPUT | MUX_MODE3)	/* vin2a_d22.rgmii1_rd1 */
-			DRA7XX_CORE_IOPAD(0x35c4, PIN_INPUT | MUX_MODE3)	/* vin2a_d23.rgmii1_rd0 */
-		>;
-
-	};
-
-	cpsw_sleep: cpsw_sleep {
-		pinctrl-single,pins = <
-			/* Slave 2 */
-			DRA7XX_CORE_IOPAD(0x3598, MUX_MODE15)
-			DRA7XX_CORE_IOPAD(0x359c, MUX_MODE15)
-			DRA7XX_CORE_IOPAD(0x35a0, MUX_MODE15)
-			DRA7XX_CORE_IOPAD(0x35a4, MUX_MODE15)
-			DRA7XX_CORE_IOPAD(0x35a8, MUX_MODE15)
-			DRA7XX_CORE_IOPAD(0x35ac, MUX_MODE15)
-			DRA7XX_CORE_IOPAD(0x35b0, MUX_MODE15)
-			DRA7XX_CORE_IOPAD(0x35b4, MUX_MODE15)
-			DRA7XX_CORE_IOPAD(0x35b8, MUX_MODE15)
-			DRA7XX_CORE_IOPAD(0x35bc, MUX_MODE15)
-			DRA7XX_CORE_IOPAD(0x35c0, MUX_MODE15)
-			DRA7XX_CORE_IOPAD(0x35c4, MUX_MODE15)
-		>;
-	};
-
-	davinci_mdio_default: davinci_mdio_default {
-		pinctrl-single,pins = <
-			/* MDIO */
-			DRA7XX_CORE_IOPAD(0x363c, PIN_OUTPUT_PULLUP | MUX_MODE0)	/* mdio_d.mdio_d */
-			DRA7XX_CORE_IOPAD(0x3640, PIN_INPUT_PULLUP | MUX_MODE0)	/* mdio_clk.mdio_clk */
-		>;
-	};
-
-	davinci_mdio_sleep: davinci_mdio_sleep {
-		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x363c, MUX_MODE15)
-			DRA7XX_CORE_IOPAD(0x3640, MUX_MODE15)
-		>;
-	};
+&pcf_gpio_21 {
+	interrupt-parent = <&gpio6>;
+	interrupts = <11 IRQ_TYPE_EDGE_FALLING>;
 };
 
 &mac {
-	status = "okay";
-	pinctrl-names = "default", "sleep";
-	pinctrl-0 = <&cpsw_default>;
-	pinctrl-1 = <&cpsw_sleep>;
 	slaves = <1>;
 	mode-gpios = <&pcf_gpio_21 4 GPIO_ACTIVE_HIGH>;
 };
@@ -697,158 +43,3 @@
 	phy_id = <&davinci_mdio>, <3>;
 	phy-mode = "rgmii";
 };
-
-&davinci_mdio {
-	pinctrl-names = "default", "sleep";
-	pinctrl-0 = <&davinci_mdio_default>;
-	pinctrl-1 = <&davinci_mdio_sleep>;
-};
-
-&dcan1 {
-	status = "ok";
-	pinctrl-names = "default", "sleep", "active";
-	pinctrl-0 = <&dcan1_pins_sleep>;
-	pinctrl-1 = <&dcan1_pins_sleep>;
-	pinctrl-2 = <&dcan1_pins_default>;
-};
-
-&qspi {
-	status = "okay";
-	pinctrl-names = "default";
-	pinctrl-0 = <&qspi1_pins>;
-
-	spi-max-frequency = <48000000>;
-	m25p80@0 {
-		compatible = "s25fl256s1";
-		spi-max-frequency = <48000000>;
-		reg = <0>;
-		spi-tx-bus-width = <1>;
-		spi-rx-bus-width = <4>;
-		spi-cpol;
-		spi-cpha;
-		#address-cells = <1>;
-		#size-cells = <1>;
-
-		/* MTD partition table.
-		 * The ROM checks the first four physical blocks
-		 * for a valid file to boot and the flash here is
-		 * 64KiB block size.
-		 */
-		partition@0 {
-			label = "QSPI.SPL";
-			reg = <0x00000000 0x000010000>;
-		};
-		partition@1 {
-			label = "QSPI.SPL.backup1";
-			reg = <0x00010000 0x00010000>;
-		};
-		partition@2 {
-			label = "QSPI.SPL.backup2";
-			reg = <0x00020000 0x00010000>;
-		};
-		partition@3 {
-			label = "QSPI.SPL.backup3";
-			reg = <0x00030000 0x00010000>;
-		};
-		partition@4 {
-			label = "QSPI.u-boot";
-			reg = <0x00040000 0x00100000>;
-		};
-		partition@5 {
-			label = "QSPI.u-boot-spl-os";
-			reg = <0x00140000 0x00080000>;
-		};
-		partition@6 {
-			label = "QSPI.u-boot-env";
-			reg = <0x001c0000 0x00010000>;
-		};
-		partition@7 {
-			label = "QSPI.u-boot-env.backup1";
-			reg = <0x001d0000 0x0010000>;
-		};
-		partition@8 {
-			label = "QSPI.kernel";
-			reg = <0x001e0000 0x0800000>;
-		};
-		partition@9 {
-			label = "QSPI.file-system";
-			reg = <0x009e0000 0x01620000>;
-		};
-	};
-};
-
-&dss {
-	status = "ok";
-
-	vdda_video-supply = <&ldo5_reg>;
-};
-
-&hdmi {
-	status = "ok";
-	vdda-supply = <&ldo3_reg>;
-
-	pinctrl-names = "default";
-	pinctrl-0 = <&hdmi_pins>;
-
-	port {
-		hdmi_out: endpoint {
-			remote-endpoint = <&tpd12s015_in>;
-		};
-	};
-};
-
-&atl {
-	pinctrl-names = "default";
-	pinctrl-0 = <&atl_pins>;
-
-	assigned-clocks = <&abe_dpll_sys_clk_mux>,
-			  <&atl_gfclk_mux>,
-			  <&dpll_abe_ck>,
-			  <&dpll_abe_m2x2_ck>,
-			  <&atl_clkin2_ck>;
-	assigned-clock-parents = <&sys_clkin2>, <&dpll_abe_m2_ck>;
-	assigned-clock-rates = <0>, <0>, <180633600>, <361267200>, <5644800>;
-
-	status = "okay";
-
-	atl2 {
-		bws = <DRA7_ATL_WS_MCASP2_FSX>;
-		aws = <DRA7_ATL_WS_MCASP3_FSX>;
-	};
-};
-
-&mcasp3 {
-	#sound-dai-cells = <0>;
-	pinctrl-names = "default", "sleep";
-	pinctrl-0 = <&mcasp3_pins>;
-	pinctrl-1 = <&mcasp3_sleep_pins>;
-
-	assigned-clocks = <&mcasp3_ahclkx_mux>;
-	assigned-clock-parents = <&atl_clkin2_ck>;
-
-	status = "okay";
-
-	op-mode = <0>;          /* MCASP_IIS_MODE */
-	tdm-slots = <2>;
-	/* 4 serializer */
-	serial-dir = <  /* 0: INACTIVE, 1: TX, 2: RX */
-		1 2 0 0
-	>;
-};
-
-&mailbox5 {
-	status = "okay";
-	mbox_ipu1_ipc3x: mbox_ipu1_ipc3x {
-		status = "okay";
-	};
-	mbox_dsp1_ipc3x: mbox_dsp1_ipc3x {
-		status = "okay";
-	};
-};
-
-&mailbox6 {
-	status = "okay";
-	mbox_ipu2_ipc3x: mbox_ipu2_ipc3x {
-		status = "okay";
-	};
-};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/dra72-evm-revc.dts linux-libre-4.7-gnu/arch/arm/boot/dts/dra72-evm-revc.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/dra72-evm-revc.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/dra72-evm-revc.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include "dra72-evm-common.dtsi"
+#include <dt-bindings/net/ti-dp83867.h>
+
+/ {
+	model = "TI DRA722 Rev C EVM";
+
+	memory {
+		device_type = "memory";
+		reg = <0x0 0x80000000 0x0 0x80000000>; /* 2GB */
+	};
+};
+
+&tps65917_regulators {
+	ldo2_reg: ldo2 {
+		/* LDO2_OUT --> VDDA_1V8_PHY2 */
+		regulator-name = "ldo2";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+};
+
+&hdmi {
+	vdda-supply = <&ldo2_reg>;
+};
+
+&pcf_gpio_21 {
+	interrupt-parent = <&gpio3>;
+	interrupts = <30 IRQ_TYPE_EDGE_FALLING>;
+};
+
+&mac {
+	mode-gpios = <&pcf_gpio_21 4 GPIO_ACTIVE_LOW>,
+		     <&pcf_hdmi 9 GPIO_ACTIVE_LOW>,	/* P11 */
+		     <&pcf_hdmi 10 GPIO_ACTIVE_LOW>;	/* P12 */
+	dual_emac;
+};
+
+&cpsw_emac0 {
+	phy_id = <&davinci_mdio>, <2>;
+	phy-mode = "rgmii-id";
+	dual_emac_res_vlan = <1>;
+};
+
+&cpsw_emac1 {
+	phy_id = <&davinci_mdio>, <3>;
+	phy-mode = "rgmii-id";
+	dual_emac_res_vlan = <2>;
+};
+
+&davinci_mdio {
+	dp83867_0: ethernet-phy@2 {
+		reg = <2>;
+		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+		ti,tx-internal-delay = <DP83867_RGMIIDCTL_1_NS>;
+		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_8_B_NIB>;
+	};
+
+	dp83867_1: ethernet-phy@3 {
+		reg = <3>;
+		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+		ti,tx-internal-delay = <DP83867_RGMIIDCTL_1_NS>;
+		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_8_B_NIB>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/dra74x.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/dra74x.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/dra74x.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/dra74x.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -107,8 +107,8 @@
 	reg = <0x58000000 0x80>,
 	      <0x58004054 0x4>,
 	      <0x58004300 0x20>,
-	      <0x58005054 0x4>,
-	      <0x58005300 0x20>;
+	      <0x58009054 0x4>,
+	      <0x58009300 0x20>;
 	reg-names = "dss", "pll1_clkctrl", "pll1",
 		    "pll2_clkctrl", "pll2";
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/dra7.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/dra7.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/dra7.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/dra7.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -123,7 +123,7 @@
 					#size-cells = <1>;
 					ranges = <0 0x0 0x1400>;
 
-					pbias_regulator: pbias_regulator {
+					pbias_regulator: pbias_regulator@e00 {
 						compatible = "ti,pbias-dra7", "ti,pbias-omap";
 						reg = <0xe00 0x4>;
 						syscon = <&scm_conf>;
@@ -161,6 +161,24 @@
 					compatible = "syscon";
 					reg = <0x1c24 0x0024>;
 				};
+
+				sdma_xbar: dma-router@b78 {
+					compatible = "ti,dra7-dma-crossbar";
+					reg = <0xb78 0xfc>;
+					#dma-cells = <1>;
+					dma-requests = <205>;
+					ti,dma-safe-map = <0>;
+					dma-masters = <&sdma>;
+				};
+
+				edma_xbar: dma-router@c78 {
+					compatible = "ti,dra7-dma-crossbar";
+					reg = <0xc78 0x7c>;
+					#dma-cells = <2>;
+					dma-requests = <204>;
+					ti,dma-safe-map = <0>;
+					dma-masters = <&edma>;
+				};
 			};
 
 			cm_core_aon: cm_core_aon@5000 {
@@ -315,13 +333,43 @@
 			dma-requests = <127>;
 		};
 
-		sdma_xbar: dma-router@4a002b78 {
-			compatible = "ti,dra7-dma-crossbar";
-			reg = <0x4a002b78 0xfc>;
-			#dma-cells = <1>;
-			dma-requests = <205>;
-			ti,dma-safe-map = <0>;
-			dma-masters = <&sdma>;
+		edma: edma@43300000 {
+			compatible = "ti,edma3-tpcc";
+			ti,hwmods = "tpcc";
+			reg = <0x43300000 0x100000>;
+			reg-names = "edma3_cc";
+			interrupts = <GIC_SPI 361 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 360 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 359 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "edma3_ccint", "emda3_mperr",
+					  "edma3_ccerrint";
+			dma-requests = <64>;
+			#dma-cells = <2>;
+
+			ti,tptcs = <&edma_tptc0 7>, <&edma_tptc1 0>;
+
+			/*
+			 * memcpy is disabled, can be enabled with:
+			 * ti,edma-memcpy-channels = <20 21>;
+			 * for example. Note that these channels need to be
+			 * masked in the xbar as well.
+			 */
+		};
+
+		edma_tptc0: tptc@43400000 {
+			compatible = "ti,edma3-tptc";
+			ti,hwmods = "tptc0";
+			reg =	<0x43400000 0x100000>;
+			interrupts = <GIC_SPI 370 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "edma3_tcerrint";
+		};
+
+		edma_tptc1: tptc@43500000 {
+			compatible = "ti,edma3-tptc";
+			ti,hwmods = "tptc1";
+			reg =	<0x43500000 0x100000>;
+			interrupts = <GIC_SPI 371 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "edma3_tcerrint";
 		};
 
 		gpio1: gpio@4ae10000 {
@@ -773,12 +821,20 @@
 			ti,hwmods = "timer11";
 		};
 
+		timer12: timer@4ae20000 {
+			compatible = "ti,omap5430-timer";
+			reg = <0x4ae20000 0x80>;
+			interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
+			ti,hwmods = "timer12";
+			ti,timer-alwon;
+			ti,timer-secure;
+		};
+
 		timer13: timer@48828000 {
 			compatible = "ti,omap5430-timer";
 			reg = <0x48828000 0x80>;
 			interrupts = <GIC_SPI 339 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "timer13";
-			status = "disabled";
 		};
 
 		timer14: timer@4882a000 {
@@ -786,7 +842,6 @@
 			reg = <0x4882a000 0x80>;
 			interrupts = <GIC_SPI 340 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "timer14";
-			status = "disabled";
 		};
 
 		timer15: timer@4882c000 {
@@ -794,7 +849,6 @@
 			reg = <0x4882c000 0x80>;
 			interrupts = <GIC_SPI 341 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "timer15";
-			status = "disabled";
 		};
 
 		timer16: timer@4882e000 {
@@ -802,7 +856,6 @@
 			reg = <0x4882e000 0x80>;
 			interrupts = <GIC_SPI 342 IRQ_TYPE_LEVEL_HIGH>;
 			ti,hwmods = "timer16";
-			status = "disabled";
 		};
 
 		wdt2: wdt@4ae14000 {
@@ -1398,12 +1451,16 @@
 			ti,hwmods = "gpmc";
 			reg = <0x50000000 0x37c>;      /* device IO registers */
 			interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+			dmas = <&edma_xbar 4 0>;
+			dma-names = "rxtx";
 			gpmc,num-cs = <8>;
 			gpmc,num-waitpins = <2>;
 			#address-cells = <2>;
 			#size-cells = <1>;
 			interrupt-controller;
 			#interrupt-cells = <2>;
+			gpio-controller;
+			#gpio-cells = <2>;
 			status = "disabled";
 		};
 
@@ -1418,20 +1475,135 @@
 			status = "disabled";
 		};
 
+		mcasp1: mcasp@48460000 {
+			compatible = "ti,dra7-mcasp-audio";
+			ti,hwmods = "mcasp1";
+			reg = <0x48460000 0x2000>,
+			      <0x45800000 0x1000>;
+			reg-names = "mpu","dat";
+			interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "tx", "rx";
+			dmas = <&edma_xbar 129 1>, <&edma_xbar 128 1>;
+			dma-names = "tx", "rx";
+			clocks = <&mcasp1_aux_gfclk_mux>, <&mcasp1_ahclkx_mux>,
+				 <&mcasp1_ahclkr_mux>;
+			clock-names = "fck", "ahclkx", "ahclkr";
+			status = "disabled";
+		};
+
+		mcasp2: mcasp@48464000 {
+			compatible = "ti,dra7-mcasp-audio";
+			ti,hwmods = "mcasp2";
+			reg = <0x48464000 0x2000>,
+			      <0x45c00000 0x1000>;
+			reg-names = "mpu","dat";
+			interrupts = <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "tx", "rx";
+			dmas = <&edma_xbar 131 1>, <&edma_xbar 130 1>;
+			dma-names = "tx", "rx";
+			clocks = <&mcasp2_aux_gfclk_mux>, <&mcasp2_ahclkx_mux>,
+				 <&mcasp2_ahclkr_mux>;
+			clock-names = "fck", "ahclkx", "ahclkr";
+			status = "disabled";
+		};
+
 		mcasp3: mcasp@48468000 {
 			compatible = "ti,dra7-mcasp-audio";
 			ti,hwmods = "mcasp3";
-			reg = <0x48468000 0x2000>;
-			reg-names = "mpu";
+			reg = <0x48468000 0x2000>,
+			      <0x46000000 0x1000>;
+			reg-names = "mpu","dat";
 			interrupts = <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>,
 				     <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>;
 			interrupt-names = "tx", "rx";
-			dmas = <&sdma_xbar 133>, <&sdma_xbar 132>;
+			dmas = <&edma_xbar 133 1>, <&edma_xbar 132 1>;
 			dma-names = "tx", "rx";
 			clocks = <&mcasp3_aux_gfclk_mux>, <&mcasp3_ahclkx_mux>;
 			clock-names = "fck", "ahclkx";
 			status = "disabled";
 		};
+
+		mcasp4: mcasp@4846c000 {
+			compatible = "ti,dra7-mcasp-audio";
+			ti,hwmods = "mcasp4";
+			reg = <0x4846c000 0x2000>,
+			      <0x48436000 0x1000>;
+			reg-names = "mpu","dat";
+			interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "tx", "rx";
+			dmas = <&edma_xbar 135 1>, <&edma_xbar 134 1>;
+			dma-names = "tx", "rx";
+			clocks = <&mcasp4_aux_gfclk_mux>, <&mcasp4_ahclkx_mux>;
+			clock-names = "fck", "ahclkx";
+			status = "disabled";
+		};
+
+		mcasp5: mcasp@48470000 {
+			compatible = "ti,dra7-mcasp-audio";
+			ti,hwmods = "mcasp5";
+			reg = <0x48470000 0x2000>,
+			      <0x4843a000 0x1000>;
+			reg-names = "mpu","dat";
+			interrupts = <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "tx", "rx";
+			dmas = <&edma_xbar 137 1>, <&edma_xbar 136 1>;
+			dma-names = "tx", "rx";
+			clocks = <&mcasp5_aux_gfclk_mux>, <&mcasp5_ahclkx_mux>;
+			clock-names = "fck", "ahclkx";
+			status = "disabled";
+		};
+
+		mcasp6: mcasp@48474000 {
+			compatible = "ti,dra7-mcasp-audio";
+			ti,hwmods = "mcasp6";
+			reg = <0x48474000 0x2000>,
+			      <0x4844c000 0x1000>;
+			reg-names = "mpu","dat";
+			interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "tx", "rx";
+			dmas = <&edma_xbar 139 1>, <&edma_xbar 138 1>;
+			dma-names = "tx", "rx";
+			clocks = <&mcasp6_aux_gfclk_mux>, <&mcasp6_ahclkx_mux>;
+			clock-names = "fck", "ahclkx";
+			status = "disabled";
+		};
+
+		mcasp7: mcasp@48478000 {
+			compatible = "ti,dra7-mcasp-audio";
+			ti,hwmods = "mcasp7";
+			reg = <0x48478000 0x2000>,
+			      <0x48450000 0x1000>;
+			reg-names = "mpu","dat";
+			interrupts = <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "tx", "rx";
+			dmas = <&edma_xbar 141 1>, <&edma_xbar 140 1>;
+			dma-names = "tx", "rx";
+			clocks = <&mcasp7_aux_gfclk_mux>, <&mcasp7_ahclkx_mux>;
+			clock-names = "fck", "ahclkx";
+			status = "disabled";
+		};
+
+		mcasp8: mcasp@4847c000 {
+			compatible = "ti,dra7-mcasp-audio";
+			ti,hwmods = "mcasp8";
+			reg = <0x4847c000 0x2000>,
+			      <0x48454000 0x1000>;
+			reg-names = "mpu","dat";
+			interrupts = <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "tx", "rx";
+			dmas = <&edma_xbar 143 1>, <&edma_xbar 142 1>;
+			dma-names = "tx", "rx";
+			clocks = <&mcasp8_aux_gfclk_mux>, <&mcasp8_ahclkx_mux>;
+			clock-names = "fck", "ahclkx";
+			status = "disabled";
+		};
 
 		crossbar_mpu: crossbar@4a002a48 {
 			compatible = "ti,irq-crossbar";
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/dra7-evm.dts linux-libre-4.7-gnu/arch/arm/boot/dts/dra7-evm.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/dra7-evm.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/dra7-evm.dts	2016-07-24 15:23:50.000000000 -0400
@@ -33,6 +33,7 @@
 	evm_3v3_sw: fixedregulator-evm_3v3_sw {
 		compatible = "regulator-fixed";
 		regulator-name = "evm_3v3_sw";
+		vin-supply = <&sysen1>;
 		regulator-min-microvolt = <3300000>;
 		regulator-max-microvolt = <3300000>;
 	};
@@ -64,10 +65,11 @@
 		regulator-always-on;
 		regulator-boot-on;
 		enable-active-high;
+		vin-supply = <&sysen2>;
 		gpio = <&gpio7 11 GPIO_ACTIVE_HIGH>;
 	};
 
-	sound0: sound@0 {
+	sound0: sound0 {
 		compatible = "simple-audio-card";
 		simple-audio-card,name = "DRA7xx-EVM";
 		simple-audio-card,widgets =
@@ -224,21 +226,6 @@
 		>;
 	};
 
-	qspi1_pins: pinmux_qspi1_pins {
-		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x344c, PIN_INPUT | MUX_MODE1)  /* gpmc_a3.qspi1_cs2 */
-			DRA7XX_CORE_IOPAD(0x3450, PIN_INPUT | MUX_MODE1)  /* gpmc_a4.qspi1_cs3 */
-			DRA7XX_CORE_IOPAD(0x3474, PIN_INPUT | MUX_MODE1)  /* gpmc_a13.qspi1_rtclk */
-			DRA7XX_CORE_IOPAD(0x3478, PIN_INPUT | MUX_MODE1)  /* gpmc_a14.qspi1_d3 */
-			DRA7XX_CORE_IOPAD(0x347c, PIN_INPUT | MUX_MODE1)  /* gpmc_a15.qspi1_d2 */
-			DRA7XX_CORE_IOPAD(0x3480, PIN_INPUT | MUX_MODE1) /* gpmc_a16.qspi1_d1 */
-			DRA7XX_CORE_IOPAD(0x3484, PIN_INPUT | MUX_MODE1)  /* gpmc_a17.qspi1_d0 */
-			DRA7XX_CORE_IOPAD(0x3488, PIN_INPUT | MUX_MODE1)  /* qpmc_a18.qspi1_sclk */
-			DRA7XX_CORE_IOPAD(0x34b8, PIN_INPUT_PULLUP | MUX_MODE1)  /* gpmc_cs2.qspi1_cs0 */
-			DRA7XX_CORE_IOPAD(0x34bc, PIN_INPUT_PULLUP | MUX_MODE1)  /* gpmc_cs3.qspi1_cs1 */
-		>;
-	};
-
 	usb1_pins: pinmux_usb1_pins {
                 pinctrl-single,pins = <
 			DRA7XX_CORE_IOPAD(0x3680, PIN_INPUT_SLEW | MUX_MODE0) /* usb1_drvvbus */
@@ -254,8 +241,9 @@
 	nand_flash_x16: nand_flash_x16 {
 		/* On DRA7 EVM, GPMC_WPN and NAND_BOOTn comes from DIP switch
 		 * So NAND flash requires following switch settings:
-		 * SW5.9 (GPMC_WPN) = LOW
-		 * SW5.1 (NAND_BOOTn) = HIGH */
+		 * SW5.1 (NAND_BOOTn) = ON (LOW)
+		 * SW5.9 (GPMC_WPN) = OFF (HIGH)
+		 */
 		pinctrl-single,pins = <
 			DRA7XX_CORE_IOPAD(0x3400, PIN_INPUT  | MUX_MODE0)	/* gpmc_ad0	*/
 			DRA7XX_CORE_IOPAD(0x3404, PIN_INPUT  | MUX_MODE0)	/* gpmc_ad1	*/
@@ -428,7 +416,7 @@
 					/* VDD_DSPEVE */
 					regulator-name = "smps45";
 					regulator-min-microvolt = < 850000>;
-					regulator-max-microvolt = <1150000>;
+					regulator-max-microvolt = <1250000>;
 					regulator-always-on;
 					regulator-boot-on;
 				};
@@ -446,7 +434,7 @@
 					/* CORE_VDD */
 					regulator-name = "smps7";
 					regulator-min-microvolt = <850000>;
-					regulator-max-microvolt = <1060000>;
+					regulator-max-microvolt = <1150000>;
 					regulator-always-on;
 					regulator-boot-on;
 				};
@@ -523,12 +511,37 @@
 					regulator-max-microvolt = <3300000>;
 					regulator-boot-on;
 				};
+
+				/* REGEN1 is unused */
+
+				regen2: regen2 {
+					/* Needed for PMIC internal resources */
+					regulator-name = "regen2";
+					regulator-boot-on;
+					regulator-always-on;
+				};
+
+				/* REGEN3 is unused */
+
+				sysen1: sysen1 {
+					/* PMIC_REGEN_3V3 */
+					regulator-name = "sysen1";
+					regulator-boot-on;
+					regulator-always-on;
+				};
+
+				sysen2: sysen2 {
+					/* PMIC_REGEN_DDR */
+					regulator-name = "sysen2";
+					regulator-boot-on;
+					regulator-always-on;
+				};
 			};
 		};
 	};
 
 	pcf_lcd: gpio@20 {
-		compatible = "nxp,pcf8575";
+		compatible = "ti,pcf8575", "nxp,pcf8575";
 		reg = <0x20>;
 		gpio-controller;
 		#gpio-cells = <2>;
@@ -539,7 +552,7 @@
 	};
 
 	pcf_gpio_21: gpio@21 {
-		compatible = "ti,pcf8575";
+		compatible = "ti,pcf8575", "nxp,pcf8575";
 		reg = <0x21>;
 		lines-initial-states = <0x1408>;
 		gpio-controller;
@@ -573,7 +586,7 @@
 	clock-frequency = <400000>;
 
 	pcf_hdmi: gpio@26 {
-		compatible = "nxp,pcf8575";
+		compatible = "ti,pcf8575", "nxp,pcf8575";
 		reg = <0x26>;
 		gpio-controller;
 		#gpio-cells = <2>;
@@ -650,18 +663,14 @@
 
 &qspi {
 	status = "okay";
-	pinctrl-names = "default";
-	pinctrl-0 = <&qspi1_pins>;
 
-	spi-max-frequency = <48000000>;
+	spi-max-frequency = <64000000>;
 	m25p80@0 {
 		compatible = "s25fl256s1";
-		spi-max-frequency = <48000000>;
+		spi-max-frequency = <64000000>;
 		reg = <0>;
 		spi-tx-bus-width = <1>;
 		spi-rx-bus-width = <4>;
-		spi-cpol;
-		spi-cpha;
 		#address-cells = <1>;
 		#size-cells = <1>;
 
@@ -748,6 +757,7 @@
 		interrupt-parent = <&gpmc>;
 		interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
 			     <1 IRQ_TYPE_NONE>; /* termcount */
+		rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 pin */
 		ti,nand-ecc-opt = "bch8";
 		ti,elm-id = <&elm>;
 		nand-bus-width = <16>;
@@ -904,6 +914,8 @@
 	serial-dir = <  /* 0: INACTIVE, 1: TX, 2: RX */
 		1 2 0 0
 	>;
+	tx-num-evt = <32>;
+	rx-num-evt = <32>;
 };
 
 &mailbox5 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/dra7xx-clocks.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/dra7xx-clocks.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/dra7xx-clocks.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/dra7xx-clocks.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -196,7 +196,7 @@
 		clock-frequency = <0>;
 	};
 
-	dpll_abe_ck: dpll_abe_ck {
+	dpll_abe_ck: dpll_abe_ck@1e0 {
 		#clock-cells = <0>;
 		compatible = "ti,omap4-dpll-m4xen-clock";
 		clocks = <&abe_dpll_clk_mux>, <&abe_dpll_bypass_clk_mux>;
@@ -209,7 +209,7 @@
 		clocks = <&dpll_abe_ck>;
 	};
 
-	dpll_abe_m2x2_ck: dpll_abe_m2x2_ck {
+	dpll_abe_m2x2_ck: dpll_abe_m2x2_ck@1f0 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_abe_x2_ck>;
@@ -220,7 +220,7 @@
 		ti,invert-autoidle-bit;
 	};
 
-	abe_clk: abe_clk {
+	abe_clk: abe_clk@108 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_abe_m2x2_ck>;
@@ -229,7 +229,7 @@
 		ti,index-power-of-two;
 	};
 
-	dpll_abe_m2_ck: dpll_abe_m2_ck {
+	dpll_abe_m2_ck: dpll_abe_m2_ck@1f0 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_abe_ck>;
@@ -240,7 +240,7 @@
 		ti,invert-autoidle-bit;
 	};
 
-	dpll_abe_m3x2_ck: dpll_abe_m3x2_ck {
+	dpll_abe_m3x2_ck: dpll_abe_m3x2_ck@1f4 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_abe_x2_ck>;
@@ -251,7 +251,7 @@
 		ti,invert-autoidle-bit;
 	};
 
-	dpll_core_byp_mux: dpll_core_byp_mux {
+	dpll_core_byp_mux: dpll_core_byp_mux@12c {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>;
@@ -259,7 +259,7 @@
 		reg = <0x012c>;
 	};
 
-	dpll_core_ck: dpll_core_ck {
+	dpll_core_ck: dpll_core_ck@120 {
 		#clock-cells = <0>;
 		compatible = "ti,omap4-dpll-core-clock";
 		clocks = <&sys_clkin1>, <&dpll_core_byp_mux>;
@@ -272,7 +272,7 @@
 		clocks = <&dpll_core_ck>;
 	};
 
-	dpll_core_h12x2_ck: dpll_core_h12x2_ck {
+	dpll_core_h12x2_ck: dpll_core_h12x2_ck@13c {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_core_x2_ck>;
@@ -291,14 +291,14 @@
 		clock-div = <1>;
 	};
 
-	dpll_mpu_ck: dpll_mpu_ck {
+	dpll_mpu_ck: dpll_mpu_ck@160 {
 		#clock-cells = <0>;
 		compatible = "ti,omap5-mpu-dpll-clock";
 		clocks = <&sys_clkin1>, <&mpu_dpll_hs_clk_div>;
 		reg = <0x0160>, <0x0164>, <0x016c>, <0x0168>;
 	};
 
-	dpll_mpu_m2_ck: dpll_mpu_m2_ck {
+	dpll_mpu_m2_ck: dpll_mpu_m2_ck@170 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_mpu_ck>;
@@ -325,7 +325,7 @@
 		clock-div = <1>;
 	};
 
-	dpll_dsp_byp_mux: dpll_dsp_byp_mux {
+	dpll_dsp_byp_mux: dpll_dsp_byp_mux@240 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin1>, <&dsp_dpll_hs_clk_div>;
@@ -333,14 +333,14 @@
 		reg = <0x0240>;
 	};
 
-	dpll_dsp_ck: dpll_dsp_ck {
+	dpll_dsp_ck: dpll_dsp_ck@234 {
 		#clock-cells = <0>;
 		compatible = "ti,omap4-dpll-clock";
 		clocks = <&sys_clkin1>, <&dpll_dsp_byp_mux>;
 		reg = <0x0234>, <0x0238>, <0x0240>, <0x023c>;
 	};
 
-	dpll_dsp_m2_ck: dpll_dsp_m2_ck {
+	dpll_dsp_m2_ck: dpll_dsp_m2_ck@244 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_dsp_ck>;
@@ -359,7 +359,7 @@
 		clock-div = <1>;
 	};
 
-	dpll_iva_byp_mux: dpll_iva_byp_mux {
+	dpll_iva_byp_mux: dpll_iva_byp_mux@1ac {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin1>, <&iva_dpll_hs_clk_div>;
@@ -367,14 +367,14 @@
 		reg = <0x01ac>;
 	};
 
-	dpll_iva_ck: dpll_iva_ck {
+	dpll_iva_ck: dpll_iva_ck@1a0 {
 		#clock-cells = <0>;
 		compatible = "ti,omap4-dpll-clock";
 		clocks = <&sys_clkin1>, <&dpll_iva_byp_mux>;
 		reg = <0x01a0>, <0x01a4>, <0x01ac>, <0x01a8>;
 	};
 
-	dpll_iva_m2_ck: dpll_iva_m2_ck {
+	dpll_iva_m2_ck: dpll_iva_m2_ck@1b0 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_iva_ck>;
@@ -393,7 +393,7 @@
 		clock-div = <1>;
 	};
 
-	dpll_gpu_byp_mux: dpll_gpu_byp_mux {
+	dpll_gpu_byp_mux: dpll_gpu_byp_mux@2e4 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>;
@@ -401,14 +401,14 @@
 		reg = <0x02e4>;
 	};
 
-	dpll_gpu_ck: dpll_gpu_ck {
+	dpll_gpu_ck: dpll_gpu_ck@2d8 {
 		#clock-cells = <0>;
 		compatible = "ti,omap4-dpll-clock";
 		clocks = <&sys_clkin1>, <&dpll_gpu_byp_mux>;
 		reg = <0x02d8>, <0x02dc>, <0x02e4>, <0x02e0>;
 	};
 
-	dpll_gpu_m2_ck: dpll_gpu_m2_ck {
+	dpll_gpu_m2_ck: dpll_gpu_m2_ck@2e8 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_gpu_ck>;
@@ -419,7 +419,7 @@
 		ti,invert-autoidle-bit;
 	};
 
-	dpll_core_m2_ck: dpll_core_m2_ck {
+	dpll_core_m2_ck: dpll_core_m2_ck@130 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_core_ck>;
@@ -438,7 +438,7 @@
 		clock-div = <1>;
 	};
 
-	dpll_ddr_byp_mux: dpll_ddr_byp_mux {
+	dpll_ddr_byp_mux: dpll_ddr_byp_mux@21c {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>;
@@ -446,14 +446,14 @@
 		reg = <0x021c>;
 	};
 
-	dpll_ddr_ck: dpll_ddr_ck {
+	dpll_ddr_ck: dpll_ddr_ck@210 {
 		#clock-cells = <0>;
 		compatible = "ti,omap4-dpll-clock";
 		clocks = <&sys_clkin1>, <&dpll_ddr_byp_mux>;
 		reg = <0x0210>, <0x0214>, <0x021c>, <0x0218>;
 	};
 
-	dpll_ddr_m2_ck: dpll_ddr_m2_ck {
+	dpll_ddr_m2_ck: dpll_ddr_m2_ck@220 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_ddr_ck>;
@@ -464,7 +464,7 @@
 		ti,invert-autoidle-bit;
 	};
 
-	dpll_gmac_byp_mux: dpll_gmac_byp_mux {
+	dpll_gmac_byp_mux: dpll_gmac_byp_mux@2b4 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin1>, <&dpll_abe_m3x2_ck>;
@@ -472,14 +472,14 @@
 		reg = <0x02b4>;
 	};
 
-	dpll_gmac_ck: dpll_gmac_ck {
+	dpll_gmac_ck: dpll_gmac_ck@2a8 {
 		#clock-cells = <0>;
 		compatible = "ti,omap4-dpll-clock";
 		clocks = <&sys_clkin1>, <&dpll_gmac_byp_mux>;
 		reg = <0x02a8>, <0x02ac>, <0x02b4>, <0x02b0>;
 	};
 
-	dpll_gmac_m2_ck: dpll_gmac_m2_ck {
+	dpll_gmac_m2_ck: dpll_gmac_m2_ck@2b8 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_gmac_ck>;
@@ -538,7 +538,7 @@
 		clock-div = <1>;
 	};
 
-	dpll_eve_byp_mux: dpll_eve_byp_mux {
+	dpll_eve_byp_mux: dpll_eve_byp_mux@290 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin1>, <&eve_dpll_hs_clk_div>;
@@ -546,14 +546,14 @@
 		reg = <0x0290>;
 	};
 
-	dpll_eve_ck: dpll_eve_ck {
+	dpll_eve_ck: dpll_eve_ck@284 {
 		#clock-cells = <0>;
 		compatible = "ti,omap4-dpll-clock";
 		clocks = <&sys_clkin1>, <&dpll_eve_byp_mux>;
 		reg = <0x0284>, <0x0288>, <0x0290>, <0x028c>;
 	};
 
-	dpll_eve_m2_ck: dpll_eve_m2_ck {
+	dpll_eve_m2_ck: dpll_eve_m2_ck@294 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_eve_ck>;
@@ -572,7 +572,7 @@
 		clock-div = <1>;
 	};
 
-	dpll_core_h13x2_ck: dpll_core_h13x2_ck {
+	dpll_core_h13x2_ck: dpll_core_h13x2_ck@140 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_core_x2_ck>;
@@ -583,7 +583,7 @@
 		ti,invert-autoidle-bit;
 	};
 
-	dpll_core_h14x2_ck: dpll_core_h14x2_ck {
+	dpll_core_h14x2_ck: dpll_core_h14x2_ck@144 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_core_x2_ck>;
@@ -594,7 +594,7 @@
 		ti,invert-autoidle-bit;
 	};
 
-	dpll_core_h22x2_ck: dpll_core_h22x2_ck {
+	dpll_core_h22x2_ck: dpll_core_h22x2_ck@154 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_core_x2_ck>;
@@ -605,7 +605,7 @@
 		ti,invert-autoidle-bit;
 	};
 
-	dpll_core_h23x2_ck: dpll_core_h23x2_ck {
+	dpll_core_h23x2_ck: dpll_core_h23x2_ck@158 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_core_x2_ck>;
@@ -616,7 +616,7 @@
 		ti,invert-autoidle-bit;
 	};
 
-	dpll_core_h24x2_ck: dpll_core_h24x2_ck {
+	dpll_core_h24x2_ck: dpll_core_h24x2_ck@15c {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_core_x2_ck>;
@@ -633,7 +633,7 @@
 		clocks = <&dpll_ddr_ck>;
 	};
 
-	dpll_ddr_h11x2_ck: dpll_ddr_h11x2_ck {
+	dpll_ddr_h11x2_ck: dpll_ddr_h11x2_ck@228 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_ddr_x2_ck>;
@@ -650,7 +650,7 @@
 		clocks = <&dpll_dsp_ck>;
 	};
 
-	dpll_dsp_m3x2_ck: dpll_dsp_m3x2_ck {
+	dpll_dsp_m3x2_ck: dpll_dsp_m3x2_ck@248 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_dsp_x2_ck>;
@@ -667,7 +667,7 @@
 		clocks = <&dpll_gmac_ck>;
 	};
 
-	dpll_gmac_h11x2_ck: dpll_gmac_h11x2_ck {
+	dpll_gmac_h11x2_ck: dpll_gmac_h11x2_ck@2c0 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_gmac_x2_ck>;
@@ -678,7 +678,7 @@
 		ti,invert-autoidle-bit;
 	};
 
-	dpll_gmac_h12x2_ck: dpll_gmac_h12x2_ck {
+	dpll_gmac_h12x2_ck: dpll_gmac_h12x2_ck@2c4 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_gmac_x2_ck>;
@@ -689,7 +689,7 @@
 		ti,invert-autoidle-bit;
 	};
 
-	dpll_gmac_h13x2_ck: dpll_gmac_h13x2_ck {
+	dpll_gmac_h13x2_ck: dpll_gmac_h13x2_ck@2c8 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_gmac_x2_ck>;
@@ -700,7 +700,7 @@
 		ti,invert-autoidle-bit;
 	};
 
-	dpll_gmac_m3x2_ck: dpll_gmac_m3x2_ck {
+	dpll_gmac_m3x2_ck: dpll_gmac_m3x2_ck@2bc {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_gmac_x2_ck>;
@@ -735,7 +735,7 @@
 		clock-div = <1>;
 	};
 
-	l3_iclk_div: l3_iclk_div {
+	l3_iclk_div: l3_iclk_div@100 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		ti,max-div = <2>;
@@ -785,7 +785,7 @@
 		clock-div = <1>;
 	};
 
-	ipu1_gfclk_mux: ipu1_gfclk_mux {
+	ipu1_gfclk_mux: ipu1_gfclk_mux@520 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&dpll_abe_m2x2_ck>, <&dpll_core_h22x2_ck>;
@@ -793,7 +793,7 @@
 		reg = <0x0520>;
 	};
 
-	mcasp1_ahclkr_mux: mcasp1_ahclkr_mux {
+	mcasp1_ahclkr_mux: mcasp1_ahclkr_mux@550 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
@@ -801,7 +801,7 @@
 		reg = <0x0550>;
 	};
 
-	mcasp1_ahclkx_mux: mcasp1_ahclkx_mux {
+	mcasp1_ahclkx_mux: mcasp1_ahclkx_mux@550 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
@@ -809,7 +809,7 @@
 		reg = <0x0550>;
 	};
 
-	mcasp1_aux_gfclk_mux: mcasp1_aux_gfclk_mux {
+	mcasp1_aux_gfclk_mux: mcasp1_aux_gfclk_mux@550 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>;
@@ -817,7 +817,7 @@
 		reg = <0x0550>;
 	};
 
-	timer5_gfclk_mux: timer5_gfclk_mux {
+	timer5_gfclk_mux: timer5_gfclk_mux@558 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>, <&clkoutmux0_clk_mux>;
@@ -825,7 +825,7 @@
 		reg = <0x0558>;
 	};
 
-	timer6_gfclk_mux: timer6_gfclk_mux {
+	timer6_gfclk_mux: timer6_gfclk_mux@560 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>, <&clkoutmux0_clk_mux>;
@@ -833,7 +833,7 @@
 		reg = <0x0560>;
 	};
 
-	timer7_gfclk_mux: timer7_gfclk_mux {
+	timer7_gfclk_mux: timer7_gfclk_mux@568 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>, <&clkoutmux0_clk_mux>;
@@ -841,7 +841,7 @@
 		reg = <0x0568>;
 	};
 
-	timer8_gfclk_mux: timer8_gfclk_mux {
+	timer8_gfclk_mux: timer8_gfclk_mux@570 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>, <&clkoutmux0_clk_mux>;
@@ -849,7 +849,7 @@
 		reg = <0x0570>;
 	};
 
-	uart6_gfclk_mux: uart6_gfclk_mux {
+	uart6_gfclk_mux: uart6_gfclk_mux@580 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>;
@@ -864,7 +864,7 @@
 	};
 };
 &prm_clocks {
-	sys_clkin1: sys_clkin1 {
+	sys_clkin1: sys_clkin1@110 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&virt_12000000_ck>, <&virt_20000000_ck>, <&virt_16800000_ck>, <&virt_19200000_ck>, <&virt_26000000_ck>, <&virt_27000000_ck>, <&virt_38400000_ck>;
@@ -872,28 +872,28 @@
 		ti,index-starts-at-one;
 	};
 
-	abe_dpll_sys_clk_mux: abe_dpll_sys_clk_mux {
+	abe_dpll_sys_clk_mux: abe_dpll_sys_clk_mux@118 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin1>, <&sys_clkin2>;
 		reg = <0x0118>;
 	};
 
-	abe_dpll_bypass_clk_mux: abe_dpll_bypass_clk_mux {
+	abe_dpll_bypass_clk_mux: abe_dpll_bypass_clk_mux@114 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&abe_dpll_sys_clk_mux>, <&sys_32k_ck>;
 		reg = <0x0114>;
 	};
 
-	abe_dpll_clk_mux: abe_dpll_clk_mux {
+	abe_dpll_clk_mux: abe_dpll_clk_mux@10c {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&abe_dpll_sys_clk_mux>, <&sys_32k_ck>;
 		reg = <0x010c>;
 	};
 
-	abe_24m_fclk: abe_24m_fclk {
+	abe_24m_fclk: abe_24m_fclk@11c {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_abe_m2x2_ck>;
@@ -901,7 +901,7 @@
 		ti,dividers = <8>, <16>;
 	};
 
-	aess_fclk: aess_fclk {
+	aess_fclk: aess_fclk@178 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&abe_clk>;
@@ -909,7 +909,7 @@
 		ti,max-div = <2>;
 	};
 
-	abe_giclk_div: abe_giclk_div {
+	abe_giclk_div: abe_giclk_div@174 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&aess_fclk>;
@@ -917,7 +917,7 @@
 		ti,max-div = <2>;
 	};
 
-	abe_lp_clk_div: abe_lp_clk_div {
+	abe_lp_clk_div: abe_lp_clk_div@1d8 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_abe_m2x2_ck>;
@@ -925,7 +925,7 @@
 		ti,dividers = <16>, <32>;
 	};
 
-	abe_sys_clk_div: abe_sys_clk_div {
+	abe_sys_clk_div: abe_sys_clk_div@120 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&sys_clkin1>;
@@ -933,14 +933,14 @@
 		ti,max-div = <2>;
 	};
 
-	adc_gfclk_mux: adc_gfclk_mux {
+	adc_gfclk_mux: adc_gfclk_mux@1dc {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin1>, <&sys_clkin2>, <&sys_32k_ck>;
 		reg = <0x01dc>;
 	};
 
-	sys_clk1_dclk_div: sys_clk1_dclk_div {
+	sys_clk1_dclk_div: sys_clk1_dclk_div@1c8 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&sys_clkin1>;
@@ -949,7 +949,7 @@
 		ti,index-power-of-two;
 	};
 
-	sys_clk2_dclk_div: sys_clk2_dclk_div {
+	sys_clk2_dclk_div: sys_clk2_dclk_div@1cc {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&sys_clkin2>;
@@ -958,7 +958,7 @@
 		ti,index-power-of-two;
 	};
 
-	per_abe_x1_dclk_div: per_abe_x1_dclk_div {
+	per_abe_x1_dclk_div: per_abe_x1_dclk_div@1bc {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_abe_m2_ck>;
@@ -967,7 +967,7 @@
 		ti,index-power-of-two;
 	};
 
-	dsp_gclk_div: dsp_gclk_div {
+	dsp_gclk_div: dsp_gclk_div@18c {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_dsp_m2_ck>;
@@ -976,7 +976,7 @@
 		ti,index-power-of-two;
 	};
 
-	gpu_dclk: gpu_dclk {
+	gpu_dclk: gpu_dclk@1a0 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_gpu_m2_ck>;
@@ -985,7 +985,7 @@
 		ti,index-power-of-two;
 	};
 
-	emif_phy_dclk_div: emif_phy_dclk_div {
+	emif_phy_dclk_div: emif_phy_dclk_div@190 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_ddr_m2_ck>;
@@ -994,7 +994,7 @@
 		ti,index-power-of-two;
 	};
 
-	gmac_250m_dclk_div: gmac_250m_dclk_div {
+	gmac_250m_dclk_div: gmac_250m_dclk_div@19c {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_gmac_m2_ck>;
@@ -1003,7 +1003,7 @@
 		ti,index-power-of-two;
 	};
 
-	l3init_480m_dclk_div: l3init_480m_dclk_div {
+	l3init_480m_dclk_div: l3init_480m_dclk_div@1ac {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_usb_m2_ck>;
@@ -1012,7 +1012,7 @@
 		ti,index-power-of-two;
 	};
 
-	usb_otg_dclk_div: usb_otg_dclk_div {
+	usb_otg_dclk_div: usb_otg_dclk_div@184 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&usb_otg_clkin_ck>;
@@ -1021,7 +1021,7 @@
 		ti,index-power-of-two;
 	};
 
-	sata_dclk_div: sata_dclk_div {
+	sata_dclk_div: sata_dclk_div@1c0 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&sys_clkin1>;
@@ -1030,7 +1030,7 @@
 		ti,index-power-of-two;
 	};
 
-	pcie2_dclk_div: pcie2_dclk_div {
+	pcie2_dclk_div: pcie2_dclk_div@1b8 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_pcie_ref_m2_ck>;
@@ -1039,7 +1039,7 @@
 		ti,index-power-of-two;
 	};
 
-	pcie_dclk_div: pcie_dclk_div {
+	pcie_dclk_div: pcie_dclk_div@1b4 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&apll_pcie_m2_ck>;
@@ -1048,7 +1048,7 @@
 		ti,index-power-of-two;
 	};
 
-	emu_dclk_div: emu_dclk_div {
+	emu_dclk_div: emu_dclk_div@194 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&sys_clkin1>;
@@ -1057,7 +1057,7 @@
 		ti,index-power-of-two;
 	};
 
-	secure_32k_dclk_div: secure_32k_dclk_div {
+	secure_32k_dclk_div: secure_32k_dclk_div@1c4 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&secure_32k_clk_src_ck>;
@@ -1066,21 +1066,21 @@
 		ti,index-power-of-two;
 	};
 
-	clkoutmux0_clk_mux: clkoutmux0_clk_mux {
+	clkoutmux0_clk_mux: clkoutmux0_clk_mux@158 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clk1_dclk_div>, <&sys_clk2_dclk_div>, <&per_abe_x1_dclk_div>, <&mpu_dclk_div>, <&dsp_gclk_div>, <&iva_dclk>, <&gpu_dclk>, <&core_dpll_out_dclk_div>, <&emif_phy_dclk_div>, <&gmac_250m_dclk_div>, <&video2_dclk_div>, <&video1_dclk_div>, <&hdmi_dclk_div>, <&func_96m_aon_dclk_div>, <&l3init_480m_dclk_div>, <&usb_otg_dclk_div>, <&sata_dclk_div>, <&pcie2_dclk_div>, <&pcie_dclk_div>, <&emu_dclk_div>, <&secure_32k_dclk_div>, <&eve_dclk_div>;
 		reg = <0x0158>;
 	};
 
-	clkoutmux1_clk_mux: clkoutmux1_clk_mux {
+	clkoutmux1_clk_mux: clkoutmux1_clk_mux@15c {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clk1_dclk_div>, <&sys_clk2_dclk_div>, <&per_abe_x1_dclk_div>, <&mpu_dclk_div>, <&dsp_gclk_div>, <&iva_dclk>, <&gpu_dclk>, <&core_dpll_out_dclk_div>, <&emif_phy_dclk_div>, <&gmac_250m_dclk_div>, <&video2_dclk_div>, <&video1_dclk_div>, <&hdmi_dclk_div>, <&func_96m_aon_dclk_div>, <&l3init_480m_dclk_div>, <&usb_otg_dclk_div>, <&sata_dclk_div>, <&pcie2_dclk_div>, <&pcie_dclk_div>, <&emu_dclk_div>, <&secure_32k_dclk_div>, <&eve_dclk_div>;
 		reg = <0x015c>;
 	};
 
-	clkoutmux2_clk_mux: clkoutmux2_clk_mux {
+	clkoutmux2_clk_mux: clkoutmux2_clk_mux@160 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clk1_dclk_div>, <&sys_clk2_dclk_div>, <&per_abe_x1_dclk_div>, <&mpu_dclk_div>, <&dsp_gclk_div>, <&iva_dclk>, <&gpu_dclk>, <&core_dpll_out_dclk_div>, <&emif_phy_dclk_div>, <&gmac_250m_dclk_div>, <&video2_dclk_div>, <&video1_dclk_div>, <&hdmi_dclk_div>, <&func_96m_aon_dclk_div>, <&l3init_480m_dclk_div>, <&usb_otg_dclk_div>, <&sata_dclk_div>, <&pcie2_dclk_div>, <&pcie_dclk_div>, <&emu_dclk_div>, <&secure_32k_dclk_div>, <&eve_dclk_div>;
@@ -1095,21 +1095,21 @@
 		clock-div = <2>;
 	};
 
-	eve_clk: eve_clk {
+	eve_clk: eve_clk@180 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&dpll_eve_m2_ck>, <&dpll_dsp_m3x2_ck>;
 		reg = <0x0180>;
 	};
 
-	hdmi_dpll_clk_mux: hdmi_dpll_clk_mux {
+	hdmi_dpll_clk_mux: hdmi_dpll_clk_mux@164 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin1>, <&sys_clkin2>;
 		reg = <0x0164>;
 	};
 
-	mlb_clk: mlb_clk {
+	mlb_clk: mlb_clk@134 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&mlb_clkin_ck>;
@@ -1118,7 +1118,7 @@
 		ti,index-power-of-two;
 	};
 
-	mlbp_clk: mlbp_clk {
+	mlbp_clk: mlbp_clk@130 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&mlbp_clkin_ck>;
@@ -1127,7 +1127,7 @@
 		ti,index-power-of-two;
 	};
 
-	per_abe_x1_gfclk2_div: per_abe_x1_gfclk2_div {
+	per_abe_x1_gfclk2_div: per_abe_x1_gfclk2_div@138 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_abe_m2_ck>;
@@ -1136,7 +1136,7 @@
 		ti,index-power-of-two;
 	};
 
-	timer_sys_clk_div: timer_sys_clk_div {
+	timer_sys_clk_div: timer_sys_clk_div@144 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&sys_clkin1>;
@@ -1144,28 +1144,28 @@
 		ti,max-div = <2>;
 	};
 
-	video1_dpll_clk_mux: video1_dpll_clk_mux {
+	video1_dpll_clk_mux: video1_dpll_clk_mux@168 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin1>, <&sys_clkin2>;
 		reg = <0x0168>;
 	};
 
-	video2_dpll_clk_mux: video2_dpll_clk_mux {
+	video2_dpll_clk_mux: video2_dpll_clk_mux@16c {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin1>, <&sys_clkin2>;
 		reg = <0x016c>;
 	};
 
-	wkupaon_iclk_mux: wkupaon_iclk_mux {
+	wkupaon_iclk_mux: wkupaon_iclk_mux@108 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin1>, <&abe_lp_clk_div>;
 		reg = <0x0108>;
 	};
 
-	gpio1_dbclk: gpio1_dbclk {
+	gpio1_dbclk: gpio1_dbclk@1838 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_32k_ck>;
@@ -1173,7 +1173,7 @@
 		reg = <0x1838>;
 	};
 
-	dcan1_sys_clk_mux: dcan1_sys_clk_mux {
+	dcan1_sys_clk_mux: dcan1_sys_clk_mux@1888 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin1>, <&sys_clkin2>;
@@ -1181,7 +1181,7 @@
 		reg = <0x1888>;
 	};
 
-	timer1_gfclk_mux: timer1_gfclk_mux {
+	timer1_gfclk_mux: timer1_gfclk_mux@1840 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>;
@@ -1189,7 +1189,7 @@
 		reg = <0x1840>;
 	};
 
-	uart10_gfclk_mux: uart10_gfclk_mux {
+	uart10_gfclk_mux: uart10_gfclk_mux@1880 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>;
@@ -1198,14 +1198,14 @@
 	};
 };
 &cm_core_clocks {
-	dpll_pcie_ref_ck: dpll_pcie_ref_ck {
+	dpll_pcie_ref_ck: dpll_pcie_ref_ck@200 {
 		#clock-cells = <0>;
 		compatible = "ti,omap4-dpll-clock";
 		clocks = <&sys_clkin1>, <&sys_clkin1>;
 		reg = <0x0200>, <0x0204>, <0x020c>, <0x0208>;
 	};
 
-	dpll_pcie_ref_m2ldo_ck: dpll_pcie_ref_m2ldo_ck {
+	dpll_pcie_ref_m2ldo_ck: dpll_pcie_ref_m2ldo_ck@210 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_pcie_ref_ck>;
@@ -1224,7 +1224,7 @@
 		ti,bit-shift = <7>;
 	};
 
-	apll_pcie_ck: apll_pcie_ck {
+	apll_pcie_ck: apll_pcie_ck@21c {
 		#clock-cells = <0>;
 		compatible = "ti,dra7-apll-clock";
 		clocks = <&apll_pcie_in_clk_mux>, <&dpll_pcie_ref_ck>;
@@ -1313,7 +1313,7 @@
 		clock-div = <1>;
 	};
 
-	dpll_per_byp_mux: dpll_per_byp_mux {
+	dpll_per_byp_mux: dpll_per_byp_mux@14c {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin1>, <&per_dpll_hs_clk_div>;
@@ -1321,14 +1321,14 @@
 		reg = <0x014c>;
 	};
 
-	dpll_per_ck: dpll_per_ck {
+	dpll_per_ck: dpll_per_ck@140 {
 		#clock-cells = <0>;
 		compatible = "ti,omap4-dpll-clock";
 		clocks = <&sys_clkin1>, <&dpll_per_byp_mux>;
 		reg = <0x0140>, <0x0144>, <0x014c>, <0x0148>;
 	};
 
-	dpll_per_m2_ck: dpll_per_m2_ck {
+	dpll_per_m2_ck: dpll_per_m2_ck@150 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_per_ck>;
@@ -1347,7 +1347,7 @@
 		clock-div = <1>;
 	};
 
-	dpll_usb_byp_mux: dpll_usb_byp_mux {
+	dpll_usb_byp_mux: dpll_usb_byp_mux@18c {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin1>, <&usb_dpll_hs_clk_div>;
@@ -1355,14 +1355,14 @@
 		reg = <0x018c>;
 	};
 
-	dpll_usb_ck: dpll_usb_ck {
+	dpll_usb_ck: dpll_usb_ck@180 {
 		#clock-cells = <0>;
 		compatible = "ti,omap4-dpll-j-type-clock";
 		clocks = <&sys_clkin1>, <&dpll_usb_byp_mux>;
 		reg = <0x0180>, <0x0184>, <0x018c>, <0x0188>;
 	};
 
-	dpll_usb_m2_ck: dpll_usb_m2_ck {
+	dpll_usb_m2_ck: dpll_usb_m2_ck@190 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_usb_ck>;
@@ -1373,7 +1373,7 @@
 		ti,invert-autoidle-bit;
 	};
 
-	dpll_pcie_ref_m2_ck: dpll_pcie_ref_m2_ck {
+	dpll_pcie_ref_m2_ck: dpll_pcie_ref_m2_ck@210 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_pcie_ref_ck>;
@@ -1390,7 +1390,7 @@
 		clocks = <&dpll_per_ck>;
 	};
 
-	dpll_per_h11x2_ck: dpll_per_h11x2_ck {
+	dpll_per_h11x2_ck: dpll_per_h11x2_ck@158 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_per_x2_ck>;
@@ -1401,7 +1401,7 @@
 		ti,invert-autoidle-bit;
 	};
 
-	dpll_per_h12x2_ck: dpll_per_h12x2_ck {
+	dpll_per_h12x2_ck: dpll_per_h12x2_ck@15c {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_per_x2_ck>;
@@ -1412,7 +1412,7 @@
 		ti,invert-autoidle-bit;
 	};
 
-	dpll_per_h13x2_ck: dpll_per_h13x2_ck {
+	dpll_per_h13x2_ck: dpll_per_h13x2_ck@160 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_per_x2_ck>;
@@ -1423,7 +1423,7 @@
 		ti,invert-autoidle-bit;
 	};
 
-	dpll_per_h14x2_ck: dpll_per_h14x2_ck {
+	dpll_per_h14x2_ck: dpll_per_h14x2_ck@164 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_per_x2_ck>;
@@ -1434,7 +1434,7 @@
 		ti,invert-autoidle-bit;
 	};
 
-	dpll_per_m2x2_ck: dpll_per_m2x2_ck {
+	dpll_per_m2x2_ck: dpll_per_m2x2_ck@150 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_per_x2_ck>;
@@ -1493,7 +1493,7 @@
 		clock-div = <2>;
 	};
 
-	l3init_60m_fclk: l3init_60m_fclk {
+	l3init_60m_fclk: l3init_60m_fclk@104 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_usb_m2_ck>;
@@ -1501,7 +1501,7 @@
 		ti,dividers = <1>, <8>;
 	};
 
-	clkout2_clk: clkout2_clk {
+	clkout2_clk: clkout2_clk@6b0 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&clkoutmux2_clk_mux>;
@@ -1509,7 +1509,7 @@
 		reg = <0x06b0>;
 	};
 
-	l3init_960m_gfclk: l3init_960m_gfclk {
+	l3init_960m_gfclk: l3init_960m_gfclk@6c0 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&dpll_usb_clkdcoldo>;
@@ -1517,7 +1517,7 @@
 		reg = <0x06c0>;
 	};
 
-	dss_32khz_clk: dss_32khz_clk {
+	dss_32khz_clk: dss_32khz_clk@1120 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_32k_ck>;
@@ -1525,7 +1525,7 @@
 		reg = <0x1120>;
 	};
 
-	dss_48mhz_clk: dss_48mhz_clk {
+	dss_48mhz_clk: dss_48mhz_clk@1120 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&func_48m_fclk>;
@@ -1533,7 +1533,7 @@
 		reg = <0x1120>;
 	};
 
-	dss_dss_clk: dss_dss_clk {
+	dss_dss_clk: dss_dss_clk@1120 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&dpll_per_h12x2_ck>;
@@ -1542,7 +1542,7 @@
 		ti,set-rate-parent;
 	};
 
-	dss_hdmi_clk: dss_hdmi_clk {
+	dss_hdmi_clk: dss_hdmi_clk@1120 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&hdmi_dpll_clk_mux>;
@@ -1550,7 +1550,7 @@
 		reg = <0x1120>;
 	};
 
-	dss_video1_clk: dss_video1_clk {
+	dss_video1_clk: dss_video1_clk@1120 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&video1_dpll_clk_mux>;
@@ -1558,7 +1558,7 @@
 		reg = <0x1120>;
 	};
 
-	dss_video2_clk: dss_video2_clk {
+	dss_video2_clk: dss_video2_clk@1120 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&video2_dpll_clk_mux>;
@@ -1566,7 +1566,7 @@
 		reg = <0x1120>;
 	};
 
-	gpio2_dbclk: gpio2_dbclk {
+	gpio2_dbclk: gpio2_dbclk@1760 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_32k_ck>;
@@ -1574,7 +1574,7 @@
 		reg = <0x1760>;
 	};
 
-	gpio3_dbclk: gpio3_dbclk {
+	gpio3_dbclk: gpio3_dbclk@1768 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_32k_ck>;
@@ -1582,7 +1582,7 @@
 		reg = <0x1768>;
 	};
 
-	gpio4_dbclk: gpio4_dbclk {
+	gpio4_dbclk: gpio4_dbclk@1770 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_32k_ck>;
@@ -1590,7 +1590,7 @@
 		reg = <0x1770>;
 	};
 
-	gpio5_dbclk: gpio5_dbclk {
+	gpio5_dbclk: gpio5_dbclk@1778 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_32k_ck>;
@@ -1598,7 +1598,7 @@
 		reg = <0x1778>;
 	};
 
-	gpio6_dbclk: gpio6_dbclk {
+	gpio6_dbclk: gpio6_dbclk@1780 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_32k_ck>;
@@ -1606,7 +1606,7 @@
 		reg = <0x1780>;
 	};
 
-	gpio7_dbclk: gpio7_dbclk {
+	gpio7_dbclk: gpio7_dbclk@1810 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_32k_ck>;
@@ -1614,7 +1614,7 @@
 		reg = <0x1810>;
 	};
 
-	gpio8_dbclk: gpio8_dbclk {
+	gpio8_dbclk: gpio8_dbclk@1818 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_32k_ck>;
@@ -1622,7 +1622,7 @@
 		reg = <0x1818>;
 	};
 
-	mmc1_clk32k: mmc1_clk32k {
+	mmc1_clk32k: mmc1_clk32k@1328 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_32k_ck>;
@@ -1630,7 +1630,7 @@
 		reg = <0x1328>;
 	};
 
-	mmc2_clk32k: mmc2_clk32k {
+	mmc2_clk32k: mmc2_clk32k@1330 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_32k_ck>;
@@ -1638,7 +1638,7 @@
 		reg = <0x1330>;
 	};
 
-	mmc3_clk32k: mmc3_clk32k {
+	mmc3_clk32k: mmc3_clk32k@1820 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_32k_ck>;
@@ -1646,7 +1646,7 @@
 		reg = <0x1820>;
 	};
 
-	mmc4_clk32k: mmc4_clk32k {
+	mmc4_clk32k: mmc4_clk32k@1828 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_32k_ck>;
@@ -1654,7 +1654,7 @@
 		reg = <0x1828>;
 	};
 
-	sata_ref_clk: sata_ref_clk {
+	sata_ref_clk: sata_ref_clk@1388 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_clkin1>;
@@ -1662,7 +1662,7 @@
 		reg = <0x1388>;
 	};
 
-	usb_otg_ss1_refclk960m: usb_otg_ss1_refclk960m {
+	usb_otg_ss1_refclk960m: usb_otg_ss1_refclk960m@13f0 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&l3init_960m_gfclk>;
@@ -1670,7 +1670,7 @@
 		reg = <0x13f0>;
 	};
 
-	usb_otg_ss2_refclk960m: usb_otg_ss2_refclk960m {
+	usb_otg_ss2_refclk960m: usb_otg_ss2_refclk960m@1340 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&l3init_960m_gfclk>;
@@ -1678,7 +1678,7 @@
 		reg = <0x1340>;
 	};
 
-	usb_phy1_always_on_clk32k: usb_phy1_always_on_clk32k {
+	usb_phy1_always_on_clk32k: usb_phy1_always_on_clk32k@640 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_32k_ck>;
@@ -1686,7 +1686,7 @@
 		reg = <0x0640>;
 	};
 
-	usb_phy2_always_on_clk32k: usb_phy2_always_on_clk32k {
+	usb_phy2_always_on_clk32k: usb_phy2_always_on_clk32k@688 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_32k_ck>;
@@ -1694,7 +1694,7 @@
 		reg = <0x0688>;
 	};
 
-	usb_phy3_always_on_clk32k: usb_phy3_always_on_clk32k {
+	usb_phy3_always_on_clk32k: usb_phy3_always_on_clk32k@698 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_32k_ck>;
@@ -1702,7 +1702,7 @@
 		reg = <0x0698>;
 	};
 
-	atl_dpll_clk_mux: atl_dpll_clk_mux {
+	atl_dpll_clk_mux: atl_dpll_clk_mux@c00 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_32k_ck>, <&video1_clkin_ck>, <&video2_clkin_ck>, <&hdmi_clkin_ck>;
@@ -1710,7 +1710,7 @@
 		reg = <0x0c00>;
 	};
 
-	atl_gfclk_mux: atl_gfclk_mux {
+	atl_gfclk_mux: atl_gfclk_mux@c00 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&l3_iclk_div>, <&dpll_abe_m2_ck>, <&atl_dpll_clk_mux>;
@@ -1718,7 +1718,7 @@
 		reg = <0x0c00>;
 	};
 
-	gmac_gmii_ref_clk_div: gmac_gmii_ref_clk_div {
+	gmac_gmii_ref_clk_div: gmac_gmii_ref_clk_div@13d0 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_gmac_m2_ck>;
@@ -1727,7 +1727,7 @@
 		ti,dividers = <2>;
 	};
 
-	gmac_rft_clk_mux: gmac_rft_clk_mux {
+	gmac_rft_clk_mux: gmac_rft_clk_mux@13d0 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&video1_clkin_ck>, <&video2_clkin_ck>, <&dpll_abe_m2_ck>, <&hdmi_clkin_ck>, <&l3_iclk_div>;
@@ -1735,7 +1735,7 @@
 		reg = <0x13d0>;
 	};
 
-	gpu_core_gclk_mux: gpu_core_gclk_mux {
+	gpu_core_gclk_mux: gpu_core_gclk_mux@1220 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&dpll_core_h14x2_ck>, <&dpll_per_h14x2_ck>, <&dpll_gpu_m2_ck>;
@@ -1743,7 +1743,7 @@
 		reg = <0x1220>;
 	};
 
-	gpu_hyd_gclk_mux: gpu_hyd_gclk_mux {
+	gpu_hyd_gclk_mux: gpu_hyd_gclk_mux@1220 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&dpll_core_h14x2_ck>, <&dpll_per_h14x2_ck>, <&dpll_gpu_m2_ck>;
@@ -1751,7 +1751,7 @@
 		reg = <0x1220>;
 	};
 
-	l3instr_ts_gclk_div: l3instr_ts_gclk_div {
+	l3instr_ts_gclk_div: l3instr_ts_gclk_div@e50 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&wkupaon_iclk_mux>;
@@ -1760,7 +1760,7 @@
 		ti,dividers = <8>, <16>, <32>;
 	};
 
-	mcasp2_ahclkr_mux: mcasp2_ahclkr_mux {
+	mcasp2_ahclkr_mux: mcasp2_ahclkr_mux@1860 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
@@ -1768,7 +1768,7 @@
 		reg = <0x1860>;
 	};
 
-	mcasp2_ahclkx_mux: mcasp2_ahclkx_mux {
+	mcasp2_ahclkx_mux: mcasp2_ahclkx_mux@1860 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
@@ -1776,7 +1776,7 @@
 		reg = <0x1860>;
 	};
 
-	mcasp2_aux_gfclk_mux: mcasp2_aux_gfclk_mux {
+	mcasp2_aux_gfclk_mux: mcasp2_aux_gfclk_mux@1860 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>;
@@ -1784,7 +1784,7 @@
 		reg = <0x1860>;
 	};
 
-	mcasp3_ahclkx_mux: mcasp3_ahclkx_mux {
+	mcasp3_ahclkx_mux: mcasp3_ahclkx_mux@1868 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
@@ -1792,7 +1792,7 @@
 		reg = <0x1868>;
 	};
 
-	mcasp3_aux_gfclk_mux: mcasp3_aux_gfclk_mux {
+	mcasp3_aux_gfclk_mux: mcasp3_aux_gfclk_mux@1868 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>;
@@ -1800,7 +1800,7 @@
 		reg = <0x1868>;
 	};
 
-	mcasp4_ahclkx_mux: mcasp4_ahclkx_mux {
+	mcasp4_ahclkx_mux: mcasp4_ahclkx_mux@1898 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
@@ -1808,7 +1808,7 @@
 		reg = <0x1898>;
 	};
 
-	mcasp4_aux_gfclk_mux: mcasp4_aux_gfclk_mux {
+	mcasp4_aux_gfclk_mux: mcasp4_aux_gfclk_mux@1898 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>;
@@ -1816,7 +1816,7 @@
 		reg = <0x1898>;
 	};
 
-	mcasp5_ahclkx_mux: mcasp5_ahclkx_mux {
+	mcasp5_ahclkx_mux: mcasp5_ahclkx_mux@1878 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
@@ -1824,7 +1824,7 @@
 		reg = <0x1878>;
 	};
 
-	mcasp5_aux_gfclk_mux: mcasp5_aux_gfclk_mux {
+	mcasp5_aux_gfclk_mux: mcasp5_aux_gfclk_mux@1878 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>;
@@ -1832,7 +1832,7 @@
 		reg = <0x1878>;
 	};
 
-	mcasp6_ahclkx_mux: mcasp6_ahclkx_mux {
+	mcasp6_ahclkx_mux: mcasp6_ahclkx_mux@1904 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
@@ -1840,7 +1840,7 @@
 		reg = <0x1904>;
 	};
 
-	mcasp6_aux_gfclk_mux: mcasp6_aux_gfclk_mux {
+	mcasp6_aux_gfclk_mux: mcasp6_aux_gfclk_mux@1904 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>;
@@ -1848,7 +1848,7 @@
 		reg = <0x1904>;
 	};
 
-	mcasp7_ahclkx_mux: mcasp7_ahclkx_mux {
+	mcasp7_ahclkx_mux: mcasp7_ahclkx_mux@1908 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
@@ -1856,7 +1856,7 @@
 		reg = <0x1908>;
 	};
 
-	mcasp7_aux_gfclk_mux: mcasp7_aux_gfclk_mux {
+	mcasp7_aux_gfclk_mux: mcasp7_aux_gfclk_mux@1908 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>;
@@ -1864,7 +1864,7 @@
 		reg = <0x1908>;
 	};
 
-	mcasp8_ahclk_mux: mcasp8_ahclk_mux {
+	mcasp8_ahclkx_mux: mcasp8_ahclkx_mux@1890 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
@@ -1872,7 +1872,7 @@
 		reg = <0x1890>;
 	};
 
-	mcasp8_aux_gfclk_mux: mcasp8_aux_gfclk_mux {
+	mcasp8_aux_gfclk_mux: mcasp8_aux_gfclk_mux@1890 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&per_abe_x1_gfclk2_div>, <&video1_clk2_div>, <&video2_clk2_div>, <&hdmi_clk2_div>;
@@ -1880,7 +1880,7 @@
 		reg = <0x1890>;
 	};
 
-	mmc1_fclk_mux: mmc1_fclk_mux {
+	mmc1_fclk_mux: mmc1_fclk_mux@1328 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&func_128m_clk>, <&dpll_per_m2x2_ck>;
@@ -1888,7 +1888,7 @@
 		reg = <0x1328>;
 	};
 
-	mmc1_fclk_div: mmc1_fclk_div {
+	mmc1_fclk_div: mmc1_fclk_div@1328 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&mmc1_fclk_mux>;
@@ -1898,7 +1898,7 @@
 		ti,index-power-of-two;
 	};
 
-	mmc2_fclk_mux: mmc2_fclk_mux {
+	mmc2_fclk_mux: mmc2_fclk_mux@1330 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&func_128m_clk>, <&dpll_per_m2x2_ck>;
@@ -1906,7 +1906,7 @@
 		reg = <0x1330>;
 	};
 
-	mmc2_fclk_div: mmc2_fclk_div {
+	mmc2_fclk_div: mmc2_fclk_div@1330 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&mmc2_fclk_mux>;
@@ -1916,7 +1916,7 @@
 		ti,index-power-of-two;
 	};
 
-	mmc3_gfclk_mux: mmc3_gfclk_mux {
+	mmc3_gfclk_mux: mmc3_gfclk_mux@1820 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>;
@@ -1924,7 +1924,7 @@
 		reg = <0x1820>;
 	};
 
-	mmc3_gfclk_div: mmc3_gfclk_div {
+	mmc3_gfclk_div: mmc3_gfclk_div@1820 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&mmc3_gfclk_mux>;
@@ -1934,7 +1934,7 @@
 		ti,index-power-of-two;
 	};
 
-	mmc4_gfclk_mux: mmc4_gfclk_mux {
+	mmc4_gfclk_mux: mmc4_gfclk_mux@1828 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>;
@@ -1942,7 +1942,7 @@
 		reg = <0x1828>;
 	};
 
-	mmc4_gfclk_div: mmc4_gfclk_div {
+	mmc4_gfclk_div: mmc4_gfclk_div@1828 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&mmc4_gfclk_mux>;
@@ -1952,7 +1952,7 @@
 		ti,index-power-of-two;
 	};
 
-	qspi_gfclk_mux: qspi_gfclk_mux {
+	qspi_gfclk_mux: qspi_gfclk_mux@1838 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&func_128m_clk>, <&dpll_per_h13x2_ck>;
@@ -1960,7 +1960,7 @@
 		reg = <0x1838>;
 	};
 
-	qspi_gfclk_div: qspi_gfclk_div {
+	qspi_gfclk_div: qspi_gfclk_div@1838 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&qspi_gfclk_mux>;
@@ -1970,7 +1970,7 @@
 		ti,index-power-of-two;
 	};
 
-	timer10_gfclk_mux: timer10_gfclk_mux {
+	timer10_gfclk_mux: timer10_gfclk_mux@1728 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>;
@@ -1978,7 +1978,7 @@
 		reg = <0x1728>;
 	};
 
-	timer11_gfclk_mux: timer11_gfclk_mux {
+	timer11_gfclk_mux: timer11_gfclk_mux@1730 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>;
@@ -1986,7 +1986,7 @@
 		reg = <0x1730>;
 	};
 
-	timer13_gfclk_mux: timer13_gfclk_mux {
+	timer13_gfclk_mux: timer13_gfclk_mux@17c8 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>;
@@ -1994,7 +1994,7 @@
 		reg = <0x17c8>;
 	};
 
-	timer14_gfclk_mux: timer14_gfclk_mux {
+	timer14_gfclk_mux: timer14_gfclk_mux@17d0 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>;
@@ -2002,7 +2002,7 @@
 		reg = <0x17d0>;
 	};
 
-	timer15_gfclk_mux: timer15_gfclk_mux {
+	timer15_gfclk_mux: timer15_gfclk_mux@17d8 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>;
@@ -2010,7 +2010,7 @@
 		reg = <0x17d8>;
 	};
 
-	timer16_gfclk_mux: timer16_gfclk_mux {
+	timer16_gfclk_mux: timer16_gfclk_mux@1830 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>;
@@ -2018,7 +2018,7 @@
 		reg = <0x1830>;
 	};
 
-	timer2_gfclk_mux: timer2_gfclk_mux {
+	timer2_gfclk_mux: timer2_gfclk_mux@1738 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>;
@@ -2026,7 +2026,7 @@
 		reg = <0x1738>;
 	};
 
-	timer3_gfclk_mux: timer3_gfclk_mux {
+	timer3_gfclk_mux: timer3_gfclk_mux@1740 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>;
@@ -2034,7 +2034,7 @@
 		reg = <0x1740>;
 	};
 
-	timer4_gfclk_mux: timer4_gfclk_mux {
+	timer4_gfclk_mux: timer4_gfclk_mux@1748 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>;
@@ -2042,7 +2042,7 @@
 		reg = <0x1748>;
 	};
 
-	timer9_gfclk_mux: timer9_gfclk_mux {
+	timer9_gfclk_mux: timer9_gfclk_mux@1750 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&timer_sys_clk_div>, <&sys_32k_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&abe_giclk_div>, <&video1_div_clk>, <&video2_div_clk>, <&hdmi_div_clk>;
@@ -2050,7 +2050,7 @@
 		reg = <0x1750>;
 	};
 
-	uart1_gfclk_mux: uart1_gfclk_mux {
+	uart1_gfclk_mux: uart1_gfclk_mux@1840 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>;
@@ -2058,7 +2058,7 @@
 		reg = <0x1840>;
 	};
 
-	uart2_gfclk_mux: uart2_gfclk_mux {
+	uart2_gfclk_mux: uart2_gfclk_mux@1848 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>;
@@ -2066,7 +2066,7 @@
 		reg = <0x1848>;
 	};
 
-	uart3_gfclk_mux: uart3_gfclk_mux {
+	uart3_gfclk_mux: uart3_gfclk_mux@1850 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>;
@@ -2074,7 +2074,7 @@
 		reg = <0x1850>;
 	};
 
-	uart4_gfclk_mux: uart4_gfclk_mux {
+	uart4_gfclk_mux: uart4_gfclk_mux@1858 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>;
@@ -2082,7 +2082,7 @@
 		reg = <0x1858>;
 	};
 
-	uart5_gfclk_mux: uart5_gfclk_mux {
+	uart5_gfclk_mux: uart5_gfclk_mux@1870 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>;
@@ -2090,7 +2090,7 @@
 		reg = <0x1870>;
 	};
 
-	uart7_gfclk_mux: uart7_gfclk_mux {
+	uart7_gfclk_mux: uart7_gfclk_mux@18d0 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>;
@@ -2098,7 +2098,7 @@
 		reg = <0x18d0>;
 	};
 
-	uart8_gfclk_mux: uart8_gfclk_mux {
+	uart8_gfclk_mux: uart8_gfclk_mux@18e0 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>;
@@ -2106,7 +2106,7 @@
 		reg = <0x18e0>;
 	};
 
-	uart9_gfclk_mux: uart9_gfclk_mux {
+	uart9_gfclk_mux: uart9_gfclk_mux@18e8 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&func_48m_fclk>, <&dpll_per_m2x2_ck>;
@@ -2114,7 +2114,7 @@
 		reg = <0x18e8>;
 	};
 
-	vip1_gclk_mux: vip1_gclk_mux {
+	vip1_gclk_mux: vip1_gclk_mux@1020 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&l3_iclk_div>, <&dpll_core_h23x2_ck>;
@@ -2122,7 +2122,7 @@
 		reg = <0x1020>;
 	};
 
-	vip2_gclk_mux: vip2_gclk_mux {
+	vip2_gclk_mux: vip2_gclk_mux@1028 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&l3_iclk_div>, <&dpll_core_h23x2_ck>;
@@ -2130,7 +2130,7 @@
 		reg = <0x1028>;
 	};
 
-	vip3_gclk_mux: vip3_gclk_mux {
+	vip3_gclk_mux: vip3_gclk_mux@1030 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&l3_iclk_div>, <&dpll_core_h23x2_ck>;
@@ -2147,7 +2147,7 @@
 };
 
 &scm_conf_clocks {
-	dss_deshdcp_clk: dss_deshdcp_clk {
+	dss_deshdcp_clk: dss_deshdcp_clk@558 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&l3_iclk_div>;
@@ -2155,7 +2155,7 @@
 		reg = <0x558>;
 	};
 
-       ehrpwm0_tbclk: ehrpwm0_tbclk {
+       ehrpwm0_tbclk: ehrpwm0_tbclk@558 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&l4_root_clk_div>;
@@ -2163,7 +2163,7 @@
 		reg = <0x0558>;
 	};
 
-	ehrpwm1_tbclk: ehrpwm1_tbclk {
+	ehrpwm1_tbclk: ehrpwm1_tbclk@558 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&l4_root_clk_div>;
@@ -2171,7 +2171,7 @@
 		reg = <0x0558>;
 	};
 
-	ehrpwm2_tbclk: ehrpwm2_tbclk {
+	ehrpwm2_tbclk: ehrpwm2_tbclk@558 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&l4_root_clk_div>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/ea3250.dts linux-libre-4.7-gnu/arch/arm/boot/dts/ea3250.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/ea3250.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/ea3250.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,274 +0,0 @@
-/*
- * Embedded Artists LPC3250 board
- *
- * Copyright 2012 Roland Stigge <stigge@antcom.de>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-/dts-v1/;
-#include "lpc32xx.dtsi"
-
-/ {
-	model = "Embedded Artists LPC3250 board based on NXP LPC3250";
-	compatible = "ea,ea3250", "nxp,lpc3250";
-	#address-cells = <1>;
-	#size-cells = <1>;
-
-	memory {
-		device_type = "memory";
-		reg = <0x80000000 0x4000000>;
-	};
-
-	ahb {
-		mac: ethernet@31060000 {
-			phy-mode = "rmii";
-			use-iram;
-		};
-
-		/* 128MB Flash via SLC NAND controller */
-		slc: flash@20020000 {
-			status = "okay";
-			#address-cells = <1>;
-			#size-cells = <1>;
-
-			nxp,wdr-clks = <14>;
-			nxp,wwidth = <260000000>;
-			nxp,whold = <104000000>;
-			nxp,wsetup = <200000000>;
-			nxp,rdr-clks = <14>;
-			nxp,rwidth = <34666666>;
-			nxp,rhold = <104000000>;
-			nxp,rsetup = <200000000>;
-			nand-on-flash-bbt;
-			gpios = <&gpio 5 19 1>; /* GPO_P3 19, active low */
-
-			mtd0@00000000 {
-				label = "ea3250-boot";
-				reg = <0x00000000 0x00080000>;
-				read-only;
-			};
-
-			mtd1@00080000 {
-				label = "ea3250-uboot";
-				reg = <0x00080000 0x000c0000>;
-				read-only;
-			};
-
-			mtd2@00140000 {
-				label = "ea3250-kernel";
-				reg = <0x00140000 0x00400000>;
-			};
-
-			mtd3@00540000 {
-				label = "ea3250-rootfs";
-				reg = <0x00540000 0x07ac0000>;
-			};
-		};
-
-		apb {
-			uart5: serial@40090000 {
-				status = "okay";
-			};
-
-			uart3: serial@40080000 {
-				status = "okay";
-			};
-
-			uart6: serial@40098000 {
-				status = "okay";
-			};
-
-			i2c1: i2c@400A0000 {
-				clock-frequency = <100000>;
-
-				eeprom@50 {
-					compatible = "at,24c256";
-					reg = <0x50>;
-				};
-
-				eeprom@57 {
-					compatible = "at,24c64";
-					reg = <0x57>;
-				};
-
-				uda1380: uda1380@18 {
-					compatible = "nxp,uda1380";
-					reg = <0x18>;
-					power-gpio = <&gpio 0x59 0>;
-					reset-gpio = <&gpio 0x51 0>;
-					dac-clk = "wspll";
-				};
-
-				pca9532: pca9532@60 {
-					compatible = "nxp,pca9532";
-					gpio-controller;
-					#gpio-cells = <2>;
-					reg = <0x60>;
-				};
-			};
-
-			i2c2: i2c@400A8000 {
-				clock-frequency = <100000>;
-			};
-
-			sd@20098000 {
-				wp-gpios = <&pca9532 5 0>;
-				cd-gpios = <&pca9532 4 0>;
-				cd-inverted;
-				bus-width = <4>;
-				status = "okay";
-			};
-		};
-
-		fab {
-			uart1: serial@40014000 {
-				status = "okay";
-			};
-
-			/* 3-axis accelerometer X,Y,Z (or AD-IN instead of Z) */
-			adc@40048000 {
-				status = "okay";
-			};
-		};
-	};
-
-	gpio_keys {
-		compatible = "gpio-keys";
-		#address-cells = <1>;
-		#size-cells = <0>;
-		autorepeat;
-		button@21 {
-			label = "Interrupt Key";
-			linux,code = <103>;
-			gpios = <&gpio 4 1 0>; /* GPI_P3 1 */
-		};
-		key1 {
-			label = "KEY1";
-			linux,code = <1>;
-			gpios = <&pca9532 0 0>;
-		};
-		key2 {
-			label = "KEY2";
-			linux,code = <2>;
-			gpios = <&pca9532 1 0>;
-		};
-		key3 {
-			label = "KEY3";
-			linux,code = <3>;
-			gpios = <&pca9532 2 0>;
-		};
-		key4 {
-			label = "KEY4";
-			linux,code = <4>;
-			gpios = <&pca9532 3 0>;
-		};
-		joy0 {
-			label = "Joystick Key 0";
-			linux,code = <10>;
-			gpios = <&gpio 2 0 0>; /* P2.0 */
-		};
-		joy1 {
-			label = "Joystick Key 1";
-			linux,code = <11>;
-			gpios = <&gpio 2 1 0>; /* P2.1 */
-		};
-		joy2 {
-			label = "Joystick Key 2";
-			linux,code = <12>;
-			gpios = <&gpio 2 2 0>; /* P2.2 */
-		};
-		joy3 {
-			label = "Joystick Key 3";
-			linux,code = <13>;
-			gpios = <&gpio 2 3 0>; /* P2.3 */
-		};
-		joy4 {
-			label = "Joystick Key 4";
-			linux,code = <14>;
-			gpios = <&gpio 2 4 0>; /* P2.4 */
-		};
-	};
-
-	leds {
-		compatible = "gpio-leds";
-
-		/* LEDs on OEM Board */
-
-		led1 {
-			gpios = <&gpio 5 14 1>; /* GPO_P3 14, GPIO 93, active low */
-			linux,default-trigger = "timer";
-			default-state = "off";
-		};
-
-		led2 {
-			gpios = <&gpio 2 10 1>; /* P2.10, active low */
-			default-state = "off";
-		};
-
-		led3 {
-			gpios = <&gpio 2 11 1>; /* P2.11, active low */
-			default-state = "off";
-		};
-
-		led4 {
-			gpios = <&gpio 2 12 1>; /* P2.12, active low */
-			default-state = "off";
-		};
-
-		/* LEDs on Base Board */
-
-		lede1 {
-			gpios = <&pca9532 8 0>;
-			default-state = "off";
-		};
-		lede2 {
-			gpios = <&pca9532 9 0>;
-			default-state = "off";
-		};
-		lede3 {
-			gpios = <&pca9532 10 0>;
-			default-state = "off";
-		};
-		lede4 {
-			gpios = <&pca9532 11 0>;
-			default-state = "off";
-		};
-		lede5 {
-			gpios = <&pca9532 12 0>;
-			default-state = "off";
-		};
-		lede6 {
-			gpios = <&pca9532 13 0>;
-			default-state = "off";
-		};
-		lede7 {
-			gpios = <&pca9532 14 0>;
-			default-state = "off";
-		};
-		lede8 {
-			gpios = <&pca9532 15 0>;
-			default-state = "off";
-		};
-	};
-};
-
-/* Here, choose exactly one from: ohci, usbd */
-&ohci /* &usbd */ {
-	transceiver = <&isp1301>;
-	status = "okay";
-};
-
-&i2cusb {
-	clock-frequency = <100000>;
-
-	isp1301: usb-transceiver@2d {
-		compatible = "nxp,isp1301";
-		reg = <0x2d>;
-	};
-};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/emev2-kzm9d.dts linux-libre-4.7-gnu/arch/arm/boot/dts/emev2-kzm9d.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/emev2-kzm9d.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/emev2-kzm9d.dts	2016-07-24 15:23:50.000000000 -0400
@@ -105,8 +105,8 @@
 
 &pfc {
 	uart1_pins: serial@e1030000 {
-		renesas,groups = "uart1_ctrl", "uart1_data";
-		renesas,function = "uart1";
+		groups = "uart1_ctrl", "uart1_data";
+		function = "uart1";
 	};
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/exynos3250-artik5.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/exynos3250-artik5.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/exynos3250-artik5.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/exynos3250-artik5.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,334 @@
+/*
+ * Samsung's Exynos3250 based ARTIK5 module device tree source
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Device tree source file for Samsung's ARTIK5 module which is based on
+ * Samsung Exynos3250 SoC.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "exynos3250.dtsi"
+#include <dt-bindings/clock/samsung,s2mps11.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	compatible = "samsung,artik5", "samsung,exynos3250", "samsung,exynos3";
+
+	chosen {
+		stdout-path = &serial_2;
+	};
+
+	memory {
+		reg = <0x40000000 0x1ff00000>;
+	};
+
+	firmware@0205f000 {
+		compatible = "samsung,secure-firmware";
+		reg = <0x0205f000 0x1000>;
+	};
+
+	thermal-zones {
+		cpu_thermal: cpu-thermal {
+			cooling-maps {
+				map0 {
+					/* Corresponds to 500MHz */
+					cooling-device = <&cpu0 5 5>;
+				};
+				map1 {
+					/* Corresponds to 200MHz */
+					cooling-device = <&cpu0 8 8>;
+				};
+			};
+		};
+	};
+};
+
+&adc {
+	vdd-supply = <&ldo7_reg>;
+	assigned-clocks = <&cmu CLK_SCLK_TSADC>;
+	assigned-clock-rates = <6000000>;
+};
+
+&cpu0 {
+	cpu0-supply = <&buck2_reg>;
+};
+
+&i2c_0 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	samsung,i2c-sda-delay = <100>;
+	samsung,i2c-slave-addr = <0x10>;
+	samsung,i2c-max-bus-freq = <100000>;
+	status = "okay";
+
+	s2mps14_pmic@66 {
+		compatible = "samsung,s2mps14-pmic";
+		interrupt-parent = <&gpx3>;
+		interrupts = <5 IRQ_TYPE_NONE>;
+		reg = <0x66>;
+
+		s2mps14_osc: clocks {
+			compatible = "samsung,s2mps14-clk";
+			#clock-cells = <1>;
+			clock-output-names = "s2mps14_ap", "unused",
+				"s2mps14_bt";
+		};
+
+		regulators {
+			ldo1_reg: LDO1 {
+				/* VDD_ALIVE15x */
+				regulator-name = "VLDO1_1.0V";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-always-on;
+			};
+
+			ldo2_reg: LDO2 {
+				/* VDDQM176 ~ VDDQM185 */
+				regulator-name = "VLDO2_1.2V";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1200000>;
+				regulator-always-on;
+			};
+
+			ldo3_reg: LDO3 {
+				/*
+				 * VDD1_E106 ~ VDD1_E111
+				 * DVDD_RTC_AP, DVDD_MMC2_AP
+				 */
+				regulator-name = "VLDO3_1.8V";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+			};
+
+			ldo4_reg: LDO4 {
+				/*  AVDD_PLL1120 ~ AVDD_PLL11201 */
+				regulator-name = "VLDO4_1.8V";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+			};
+
+			ldo5_reg: LDO5 {
+				/* VDDI_PLL_ISO141 ~ VDDI_PLL_ISO142 */
+				regulator-name = "VLDO5_1.0V";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-always-on;
+			};
+
+			ldo6_reg: LDO6 {
+				/* VDD_USB, VDD10_HSIC */
+				regulator-name = "VLDO6_1.0V";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-always-on;
+			};
+
+			ldo7_reg: LDO7 {
+				/*
+				 * VDD18P, AVDD18_TS, AVDD18_HSIC, AVDD_PLL2,
+				 * AVDD_ADC, AVDD_ABB_0, M4S_VDD18
+				 */
+				regulator-name = "VLDO7_1.8V";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+			};
+
+			ldo8_reg: LDO8 {
+				/* AVDD33_UOTG */
+				regulator-name = "VLDO8_3.0V";
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-always-on;
+			};
+
+			ldo9_reg: LDO9 {
+				/* VDDQ_E86 ~ VDDQ_E105*/
+				regulator-name = "VLDO9_1.2V";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1200000>;
+				regulator-always-on;
+			};
+
+			ldo10_reg: LDO10 {
+				regulator-name = "VLDO10_1.0V";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+			};
+
+			ldo11_reg: LDO11 {
+				/* VDD74 ~ VDD75 */
+				regulator-name = "VLDO11_1.8V";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				samsung,ext-control-gpios = <&gpk0 2 GPIO_ACTIVE_HIGH>;
+			};
+
+			ldo12_reg: LDO12 {
+				/* VDD72 ~ VDD73 */
+				regulator-name = "VLDO12_2.8V";
+				regulator-min-microvolt = <2800000>;
+				regulator-max-microvolt = <2800000>;
+				samsung,ext-control-gpios = <&gpk0 2 GPIO_ACTIVE_HIGH>;
+			};
+
+			ldo13_reg: LDO13 {
+				regulator-name = "VLDO13_2.8V";
+				regulator-min-microvolt = <2800000>;
+				regulator-max-microvolt = <2800000>;
+			};
+
+			ldo14_reg: LDO14 {
+				regulator-name = "VLDO14_2.7V";
+				regulator-min-microvolt = <2700000>;
+				regulator-max-microvolt = <2700000>;
+			};
+
+			ldo15_reg: LDO15 {
+				regulator-name = "VLDO_3.3V";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			ldo16_reg: LDO16 {
+				regulator-name = "VLDO16_3.3V";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			ldo17_reg: LDO17 {
+				regulator-name = "VLDO17_3.0V";
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+			};
+
+			ldo18_reg: LDO18 {
+				/* DVDD_MMC2_AP */
+				regulator-name = "VLDO18_2.8V";
+				regulator-min-microvolt = <2800000>;
+				regulator-max-microvolt = <2800000>;
+			};
+
+			ldo19_reg: LDO19 {
+				regulator-name = "VLDO19_1.8V";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+			};
+
+			ldo20_reg: LDO20 {
+				regulator-name = "VLDO20_1.8V";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+			};
+
+			ldo21_reg: LDO21 {
+				regulator-name = "VLDO21_1.25V";
+				regulator-min-microvolt = <1250000>;
+				regulator-max-microvolt = <1250000>;
+			};
+
+			ldo22_reg: LDO22 {
+				regulator-name = "VLDO22_1.2V";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1200000>;
+			};
+
+			ldo23_reg: LDO23 {
+				/* Xi2c3_SDA/SCL, Xi2c7_SDA/SCL, WLAN_SDIO */
+				regulator-name = "VLDO23_1.8V";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+			};
+
+			ldo24_reg: LDO24 {
+				regulator-name = "VLDO24_3.0V";
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+			};
+
+			ldo25_reg: LDO25 {
+				regulator-name = "VLDO25_3.0V";
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+			};
+
+			buck1_reg: BUCK1 {
+				/* VDD_MIF */
+				regulator-name = "VBUCK1_1.0V";
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-always-on;
+			};
+
+			buck2_reg: BUCK2 {
+				/* VDD_CPU */
+				regulator-name = "VBUCK2_1.2V";
+				regulator-min-microvolt = <850000>;
+				regulator-max-microvolt = <1200000>;
+				regulator-always-on;
+			};
+
+			buck3_reg: BUCK3 {
+				/* VDD_G3D */
+				regulator-name = "VBUCK3_1.0V";
+				regulator-min-microvolt = <850000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-always-on;
+			};
+
+			buck4_reg: BUCK4 {
+				regulator-name = "VBUCK4_1.95V";
+				regulator-min-microvolt = <1950000>;
+				regulator-max-microvolt = <1950000>;
+				regulator-always-on;
+			};
+
+			buck5_reg: BUCK5 {
+				regulator-name = "VBUCK5_1.35V";
+				regulator-min-microvolt = <1350000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-always-on;
+			};
+		};
+	};
+};
+
+&mshc_0 {
+	num-slots = <1>;
+	non-removable;
+	cap-mmc-highspeed;
+	card-detect-delay = <200>;
+	vmmc-supply = <&ldo12_reg>;
+	clock-frequency = <100000000>;
+	clock-freq-min-max = <400000 100000000>;
+	samsung,dw-mshc-ciu-div = <1>;
+	samsung,dw-mshc-sdr-timing = <0 1>;
+	samsung,dw-mshc-ddr-timing = <1 2>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&sd0_cmd &sd0_bus1 &sd0_bus4 &sd0_bus8>;
+	bus-width = <8>;
+	status = "okay";
+};
+
+&rtc {
+	clocks = <&cmu CLK_RTC>, <&s2mps14_osc S2MPS11_CLK_AP>;
+	clock-names = "rtc", "rtc_src";
+	status = "okay";
+};
+
+&tmu {
+	status = "okay";
+};
+
+&xusbxti {
+	clock-frequency = <24000000>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/exynos3250-artik5-eval.dts linux-libre-4.7-gnu/arch/arm/boot/dts/exynos3250-artik5-eval.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/exynos3250-artik5-eval.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/exynos3250-artik5-eval.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,43 @@
+/*
+ * Samsung's Exynos3250 based ARTIK5 evaluation board device tree source
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Device tree source file for Samsung's ARTIK5 evaluation board
+ * which is based on Samsung Exynos3250 SoC.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/dts-v1/;
+#include "exynos3250-artik5.dtsi"
+
+/ {
+	model = "Samsung ARTIK5 evaluation board";
+	compatible = "samsung,artik5-eval", "samsung,artik5",
+			"samsung,exynos3250", "samsung,exynos3";
+};
+
+&mshc_2 {
+	num-slots = <1>;
+	cap-sd-highspeed;
+	disable-wp;
+	vqmmc-supply = <&ldo3_reg>;
+	card-detect-delay = <200>;
+	clock-frequency = <100000000>;
+	clock-freq-min-max = <400000 100000000>;
+	samsung,dw-mshc-ciu-div = <1>;
+	samsung,dw-mshc-sdr-timing = <0 1>;
+	samsung,dw-mshc-ddr-timing = <1 2>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&sd2_cmd &sd2_clk &sd2_cd &sd2_bus1 &sd2_bus4>;
+	bus-width = <4>;
+	status = "okay";
+};
+
+&serial_2 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/exynos3250.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/exynos3250.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/exynos3250.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/exynos3250.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -31,6 +31,7 @@
 		pinctrl1 = &pinctrl_1;
 		mshc0 = &mshc_0;
 		mshc1 = &mshc_1;
+		mshc2 = &mshc_2;
 		spi0 = &spi_0;
 		spi1 = &spi_1;
 		i2c0 = &i2c_0;
@@ -43,6 +44,7 @@
 		i2c7 = &i2c_7;
 		serial0 = &serial_0;
 		serial1 = &serial_1;
+		serial2 = &serial_2;
 	};
 
 	cpus {
@@ -153,7 +155,7 @@
 			interrupt-parent = <&gic>;
 		};
 
-		mipi_phy: video-phy@10020710 {
+		mipi_phy: video-phy {
 			compatible = "samsung,s5pv210-mipi-video-phy";
 			#phy-cells = <1>;
 			syscon = <&pmu_system_controller>;
@@ -357,6 +359,18 @@
 			status = "disabled";
 		};
 
+		mshc_2: mshc@12530000 {
+			compatible = "samsung,exynos5250-dw-mshc";
+			reg = <0x12530000 0x1000>;
+			interrupts = <0 144 0>;
+			clocks = <&cmu CLK_SDMMC2>, <&cmu CLK_SCLK_MMC2>;
+			clock-names = "biu", "ciu";
+			fifo-depth = <0x80>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
 		exynos_usbphy: exynos-usbphy@125B0000 {
 			compatible = "samsung,exynos3250-usb2-phy";
 			reg = <0x125B0000 0x100>;
@@ -452,6 +466,17 @@
 			status = "disabled";
 		};
 
+		serial_2: serial@13820000 {
+			compatible = "samsung,exynos4210-uart";
+			reg = <0x13820000 0x100>;
+			interrupts = <0 111 0>;
+			clocks = <&cmu CLK_UART2>, <&cmu CLK_SCLK_UART2>;
+			clock-names = "uart", "clk_uart_baud0";
+			pinctrl-names = "default";
+			pinctrl-0 = <&uart2_data>;
+			status = "disabled";
+		};
+
 		i2c_0: i2c@13860000 {
 			#address-cells = <1>;
 			#size-cells = <0>;
@@ -688,6 +713,187 @@
 			clock-names = "ppmu";
 			status = "disabled";
 		};
+
+		bus_dmc: bus_dmc {
+			compatible = "samsung,exynos-bus";
+			clocks = <&cmu_dmc CLK_DIV_DMC>;
+			clock-names = "bus";
+			operating-points-v2 = <&bus_dmc_opp_table>;
+			status = "disabled";
+		};
+
+		bus_dmc_opp_table: opp_table1 {
+			compatible = "operating-points-v2";
+			opp-shared;
+
+			opp@50000000 {
+				opp-hz = /bits/ 64 <50000000>;
+				opp-microvolt = <800000>;
+			};
+			opp@100000000 {
+				opp-hz = /bits/ 64 <100000000>;
+				opp-microvolt = <800000>;
+			};
+			opp@134000000 {
+				opp-hz = /bits/ 64 <134000000>;
+				opp-microvolt = <800000>;
+			};
+			opp@200000000 {
+				opp-hz = /bits/ 64 <200000000>;
+				opp-microvolt = <825000>;
+			};
+			opp@400000000 {
+				opp-hz = /bits/ 64 <400000000>;
+				opp-microvolt = <875000>;
+			};
+		};
+
+		bus_leftbus: bus_leftbus {
+			compatible = "samsung,exynos-bus";
+			clocks = <&cmu CLK_DIV_GDL>;
+			clock-names = "bus";
+			operating-points-v2 = <&bus_leftbus_opp_table>;
+			status = "disabled";
+		};
+
+		bus_rightbus: bus_rightbus {
+			compatible = "samsung,exynos-bus";
+			clocks = <&cmu CLK_DIV_GDR>;
+			clock-names = "bus";
+			operating-points-v2 = <&bus_leftbus_opp_table>;
+			status = "disabled";
+		};
+
+		bus_lcd0: bus_lcd0 {
+			compatible = "samsung,exynos-bus";
+			clocks = <&cmu CLK_DIV_ACLK_160>;
+			clock-names = "bus";
+			operating-points-v2 = <&bus_leftbus_opp_table>;
+			status = "disabled";
+		};
+
+		bus_fsys: bus_fsys {
+			compatible = "samsung,exynos-bus";
+			clocks = <&cmu CLK_DIV_ACLK_200>;
+			clock-names = "bus";
+			operating-points-v2 = <&bus_leftbus_opp_table>;
+			status = "disabled";
+		};
+
+		bus_mcuisp: bus_mcuisp {
+			compatible = "samsung,exynos-bus";
+			clocks = <&cmu CLK_DIV_ACLK_400_MCUISP>;
+			clock-names = "bus";
+			operating-points-v2 = <&bus_mcuisp_opp_table>;
+			status = "disabled";
+		};
+
+		bus_isp: bus_isp {
+			compatible = "samsung,exynos-bus";
+			clocks = <&cmu CLK_DIV_ACLK_266>;
+			clock-names = "bus";
+			operating-points-v2 = <&bus_isp_opp_table>;
+			status = "disabled";
+		};
+
+		bus_peril: bus_peril {
+			compatible = "samsung,exynos-bus";
+			clocks = <&cmu CLK_DIV_ACLK_100>;
+			clock-names = "bus";
+			operating-points-v2 = <&bus_peril_opp_table>;
+			status = "disabled";
+		};
+
+		bus_mfc: bus_mfc {
+			compatible = "samsung,exynos-bus";
+			clocks = <&cmu CLK_SCLK_MFC>;
+			clock-names = "bus";
+			operating-points-v2 = <&bus_leftbus_opp_table>;
+			status = "disabled";
+		};
+
+		bus_leftbus_opp_table: opp_table2 {
+			compatible = "operating-points-v2";
+			opp-shared;
+
+			opp@50000000 {
+				opp-hz = /bits/ 64 <50000000>;
+				opp-microvolt = <900000>;
+			};
+			opp@80000000 {
+				opp-hz = /bits/ 64 <80000000>;
+				opp-microvolt = <900000>;
+			};
+			opp@100000000 {
+				opp-hz = /bits/ 64 <100000000>;
+				opp-microvolt = <1000000>;
+			};
+			opp@134000000 {
+				opp-hz = /bits/ 64 <134000000>;
+				opp-microvolt = <1000000>;
+			};
+			opp@200000000 {
+				opp-hz = /bits/ 64 <200000000>;
+				opp-microvolt = <1000000>;
+			};
+		};
+
+		bus_mcuisp_opp_table: opp_table3 {
+			compatible = "operating-points-v2";
+			opp-shared;
+
+			opp@50000000 {
+				opp-hz = /bits/ 64 <50000000>;
+			};
+			opp@80000000 {
+				opp-hz = /bits/ 64 <80000000>;
+			};
+			opp@100000000 {
+				opp-hz = /bits/ 64 <100000000>;
+			};
+			opp@200000000 {
+				opp-hz = /bits/ 64 <200000000>;
+			};
+			opp@400000000 {
+				opp-hz = /bits/ 64 <400000000>;
+			};
+		};
+
+		bus_isp_opp_table: opp_table4 {
+			compatible = "operating-points-v2";
+			opp-shared;
+
+			opp@50000000 {
+				opp-hz = /bits/ 64 <50000000>;
+			};
+			opp@80000000 {
+				opp-hz = /bits/ 64 <80000000>;
+			};
+			opp@100000000 {
+				opp-hz = /bits/ 64 <100000000>;
+			};
+			opp@200000000 {
+				opp-hz = /bits/ 64 <200000000>;
+			};
+			opp@300000000 {
+				opp-hz = /bits/ 64 <300000000>;
+			};
+		};
+
+		bus_peril_opp_table: opp_table5 {
+			compatible = "operating-points-v2";
+			opp-shared;
+
+			opp@50000000 {
+				opp-hz = /bits/ 64 <50000000>;
+			};
+			opp@80000000 {
+				opp-hz = /bits/ 64 <80000000>;
+			};
+			opp@100000000 {
+				opp-hz = /bits/ 64 <100000000>;
+			};
+		};
 	};
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/exynos3250-monk.dts linux-libre-4.7-gnu/arch/arm/boot/dts/exynos3250-monk.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/exynos3250-monk.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/exynos3250-monk.dts	2016-07-24 15:23:50.000000000 -0400
@@ -14,6 +14,7 @@
 
 /dts-v1/;
 #include "exynos3250.dtsi"
+#include "exynos4412-ppmu-common.dtsi"
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/clock/samsung,s2mps11.h>
@@ -156,6 +157,12 @@
 	};
 };
 
+&bus_dmc {
+	devfreq-events = <&ppmu_dmc0_3>, <&ppmu_dmc1_3>;
+	vdd-supply = <&buck1_reg>;
+	status = "okay";
+};
+
 &cpu0 {
 	cpu0-supply = <&buck2_reg>;
 };
@@ -458,46 +465,6 @@
 	status = "okay";
 };
 
-&ppmu_dmc0 {
-	status = "okay";
-
-	events {
-		ppmu_dmc0_3: ppmu-event3-dmc0 {
-			event-name = "ppmu-event3-dmc0";
-		};
-	};
-};
-
-&ppmu_dmc1 {
-	status = "okay";
-
-	events {
-		ppmu_dmc1_3: ppmu-event3-dmc1 {
-			event-name = "ppmu-event3-dmc1";
-		};
-	};
-};
-
-&ppmu_leftbus {
-	status = "okay";
-
-	events {
-		ppmu_leftbus_3: ppmu-event3-leftbus {
-			event-name = "ppmu-event3-leftbus";
-		};
-	};
-};
-
-&ppmu_rightbus {
-	status = "okay";
-
-	events {
-		ppmu_rightbus_3: ppmu-event3-rightbus {
-			event-name = "ppmu-event3-rightbus";
-		};
-	};
-};
-
 &xusbxti {
 	clock-frequency = <24000000>;
 };
@@ -558,7 +525,17 @@
 
 &pinctrl_1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&sleep1>;
+	pinctrl-0 = <&initial1 &sleep1>;
+
+	initial1: initial-state {
+		PIN_IN(gpk2-0, DOWN, LV1);
+		PIN_IN(gpk2-1, DOWN, LV1);
+		PIN_IN(gpk2-2, DOWN, LV1);
+		PIN_IN(gpk2-3, DOWN, LV1);
+		PIN_IN(gpk2-4, DOWN, LV1);
+		PIN_IN(gpk2-5, DOWN, LV1);
+		PIN_IN(gpk2-6, DOWN, LV1);
+	};
 
 	sleep1: sleep-state {
 		PIN_SLP(gpe0-0, PREV, NONE);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/exynos3250-pinctrl.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/exynos3250-pinctrl.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/exynos3250-pinctrl.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/exynos3250-pinctrl.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -16,11 +16,49 @@
 #define PIN_PULL_DOWN		1
 #define PIN_PULL_UP		3
 
+#define PIN_DRV_LV1		0
+#define PIN_DRV_LV2		2
+#define PIN_DRV_LV3		1
+#define PIN_DRV_LV4		3
+
 #define PIN_PDN_OUT0		0
 #define PIN_PDN_OUT1		1
 #define PIN_PDN_INPUT		2
 #define PIN_PDN_PREV		3
 
+#define PIN_IN(_pin, _pull, _drv)			\
+	_pin {						\
+		samsung,pins = #_pin;			\
+		samsung,pin-function = <0>;		\
+		samsung,pin-pud = <PIN_PULL_ ##_pull>;	\
+		samsung,pin-drv = <PIN_DRV_ ##_drv>;	\
+	}
+
+#define PIN_OUT(_pin, _drv)				\
+	_pin {						\
+		samsung,pins = #_pin;			\
+		samsung,pin-function = <1>;		\
+		samsung,pin-pud = <0>;			\
+		samsung,pin-drv = <PIN_DRV_ ##_drv>;	\
+	}
+
+#define PIN_OUT_SET(_pin, _val, _drv)			\
+	_pin {						\
+		samsung,pins = #_pin;			\
+		samsung,pin-function = <1>;		\
+		samsung,pin-pud = <0>;			\
+		samsung,pin-drv = <PIN_DRV_ ##_drv>;	\
+		samsung,pin-val = <_val>;		\
+	}
+
+#define PIN_CFG(_pin, _sel, _pull, _drv)		\
+	_pin {						\
+		samsung,pins = #_pin;			\
+		samsung,pin-function = <_sel>;		\
+		samsung,pin-pud = <PIN_PULL_ ##_pull>;	\
+		samsung,pin-drv = <PIN_DRV_ ##_drv>;	\
+	}
+
 #define PIN_SLP(_pin, _mode, _pull)				\
 	_pin {							\
 		samsung,pins = #_pin;				\
@@ -120,6 +158,13 @@
 		samsung,pin-drv = <0>;
 	};
 
+	uart2_data: uart2-data {
+		samsung,pins = "gpa1-0", "gpa1-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
 	i2c3_bus: i2c3-bus {
 		samsung,pins = "gpa1-2", "gpa1-3";
 		samsung,pin-function = <3>;
@@ -443,6 +488,41 @@
 		samsung,pin-function = <2>;
 		samsung,pin-pud = <3>;
 		samsung,pin-drv = <3>;
+	};
+
+	sd2_clk: sd2-clk {
+		samsung,pins = "gpk2-0";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_cmd: sd2-cmd {
+		samsung,pins = "gpk2-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_cd: sd2-cd {
+		samsung,pins = "gpk2-2";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_bus1: sd2-bus-width1 {
+		samsung,pins = "gpk2-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_bus4: sd2-bus-width4 {
+		samsung,pins = "gpk2-4", "gpk2-5", "gpk2-6";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
 	};
 
 	cam_port_b_io: cam-port-b-io {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/exynos3250-rinato.dts linux-libre-4.7-gnu/arch/arm/boot/dts/exynos3250-rinato.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/exynos3250-rinato.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/exynos3250-rinato.dts	2016-07-24 15:23:50.000000000 -0400
@@ -14,6 +14,7 @@
 
 /dts-v1/;
 #include "exynos3250.dtsi"
+#include "exynos4412-ppmu-common.dtsi"
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/clock/samsung,s2mps11.h>
@@ -147,6 +148,53 @@
 	};
 };
 
+&bus_dmc {
+	devfreq-events = <&ppmu_dmc0_3>, <&ppmu_dmc1_3>;
+	vdd-supply = <&buck1_reg>;
+	status = "okay";
+};
+
+&bus_leftbus {
+	devfreq-events = <&ppmu_leftbus_3>, <&ppmu_rightbus_3>;
+	vdd-supply = <&buck3_reg>;
+	status = "okay";
+};
+
+&bus_rightbus {
+	devfreq = <&bus_leftbus>;
+	status = "okay";
+};
+
+&bus_lcd0 {
+	devfreq = <&bus_leftbus>;
+	status = "okay";
+};
+
+&bus_fsys {
+	devfreq = <&bus_leftbus>;
+	status = "okay";
+};
+
+&bus_mcuisp {
+	devfreq = <&bus_leftbus>;
+	status = "okay";
+};
+
+&bus_isp {
+	devfreq = <&bus_leftbus>;
+	status = "okay";
+};
+
+&bus_peril {
+	devfreq = <&bus_leftbus>;
+	status = "okay";
+};
+
+&bus_mfc {
+	devfreq = <&bus_leftbus>;
+	status = "okay";
+};
+
 &cpu0 {
 	cpu0-supply = <&buck2_reg>;
 };
@@ -635,53 +683,27 @@
 	status = "okay";
 };
 
-&ppmu_dmc0 {
-	status = "okay";
-
-	events {
-		ppmu_dmc0_3: ppmu-event3-dmc0 {
-			event-name = "ppmu-event3-dmc0";
-		};
-	};
-};
-
-&ppmu_dmc1 {
-	status = "okay";
-
-	events {
-		ppmu_dmc1_3: ppmu-event3-dmc1 {
-			event-name = "ppmu-event3-dmc1";
-		};
-	};
-};
-
-&ppmu_leftbus {
-	status = "okay";
-
-	events {
-		ppmu_leftbus_3: ppmu-event3-leftbus {
-			event-name = "ppmu-event3-leftbus";
-		};
-	};
-};
-
-&ppmu_rightbus {
-	status = "okay";
-
-	events {
-		ppmu_rightbus_3: ppmu-event3-rightbus {
-			event-name = "ppmu-event3-rightbus";
-		};
-	};
-};
-
 &xusbxti {
 	clock-frequency = <24000000>;
 };
 
 &pinctrl_0 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&sleep0>;
+	pinctrl-0 = <&initial0 &sleep0>;
+
+	initial0: initial-state {
+		PIN_IN(gpa1-4, DOWN, LV1);
+		PIN_IN(gpa1-5, DOWN, LV1);
+
+		PIN_IN(gpc0-0, DOWN, LV1);
+		PIN_IN(gpc0-1, DOWN, LV1);
+		PIN_IN(gpc0-2, DOWN, LV1);
+		PIN_IN(gpc0-3, DOWN, LV1);
+		PIN_IN(gpc0-4, DOWN, LV1);
+
+		PIN_IN(gpd0-0, DOWN, LV1);
+		PIN_IN(gpd0-1, DOWN, LV1);
+	};
 
 	sleep0: sleep-state {
 		PIN_SLP(gpa0-0, INPUT, DOWN);
@@ -735,7 +757,60 @@
 
 &pinctrl_1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&sleep1>;
+	pinctrl-0 = <&initial1 &sleep1>;
+
+	initial1: initial-state {
+		PIN_IN(gpe0-6, DOWN, LV1);
+		PIN_IN(gpe0-7, DOWN, LV1);
+
+		PIN_IN(gpe1-0, DOWN, LV1);
+		PIN_IN(gpe1-3, DOWN, LV1);
+		PIN_IN(gpe1-4, DOWN, LV1);
+		PIN_IN(gpe1-5, DOWN, LV1);
+		PIN_IN(gpe1-6, DOWN, LV1);
+
+		PIN_IN(gpk2-0, DOWN, LV1);
+		PIN_IN(gpk2-1, DOWN, LV1);
+		PIN_IN(gpk2-2, DOWN, LV1);
+		PIN_IN(gpk2-3, DOWN, LV1);
+		PIN_IN(gpk2-4, DOWN, LV1);
+		PIN_IN(gpk2-5, DOWN, LV1);
+		PIN_IN(gpk2-6, DOWN, LV1);
+
+		PIN_IN(gpm0-0, DOWN, LV1);
+		PIN_IN(gpm0-1, DOWN, LV1);
+		PIN_IN(gpm0-2, DOWN, LV1);
+		PIN_IN(gpm0-3, DOWN, LV1);
+		PIN_IN(gpm0-4, DOWN, LV1);
+		PIN_IN(gpm0-5, DOWN, LV1);
+		PIN_IN(gpm0-6, DOWN, LV1);
+		PIN_IN(gpm0-7, DOWN, LV1);
+
+		PIN_IN(gpm1-0, DOWN, LV1);
+		PIN_IN(gpm1-1, DOWN, LV1);
+		PIN_IN(gpm1-2, DOWN, LV1);
+		PIN_IN(gpm1-3, DOWN, LV1);
+		PIN_IN(gpm1-4, DOWN, LV1);
+		PIN_IN(gpm1-5, DOWN, LV1);
+		PIN_IN(gpm1-6, DOWN, LV1);
+
+		PIN_IN(gpm2-0, DOWN, LV1);
+		PIN_IN(gpm2-1, DOWN, LV1);
+
+		PIN_IN(gpm3-0, DOWN, LV1);
+		PIN_IN(gpm3-1, DOWN, LV1);
+		PIN_IN(gpm3-2, DOWN, LV1);
+		PIN_IN(gpm3-3, DOWN, LV1);
+		PIN_IN(gpm3-4, DOWN, LV1);
+
+		PIN_IN(gpm4-1, DOWN, LV1);
+		PIN_IN(gpm4-2, DOWN, LV1);
+		PIN_IN(gpm4-3, DOWN, LV1);
+		PIN_IN(gpm4-4, DOWN, LV1);
+		PIN_IN(gpm4-5, DOWN, LV1);
+		PIN_IN(gpm4-6, DOWN, LV1);
+		PIN_IN(gpm4-7, DOWN, LV1);
+	};
 
 	sleep1: sleep-state {
 		PIN_SLP(gpe0-0, PREV, NONE);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/exynos4210.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/exynos4210.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/exynos4210.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/exynos4210.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -257,6 +257,165 @@
 		power-domains = <&pd_lcd1>;
 		#iommu-cells = <0>;
 	};
+
+	bus_dmc: bus_dmc {
+		compatible = "samsung,exynos-bus";
+		clocks = <&clock CLK_DIV_DMC>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_dmc_opp_table>;
+		status = "disabled";
+	};
+
+	bus_acp: bus_acp {
+		compatible = "samsung,exynos-bus";
+		clocks = <&clock CLK_DIV_ACP>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_acp_opp_table>;
+		status = "disabled";
+	};
+
+	bus_peri: bus_peri {
+		compatible = "samsung,exynos-bus";
+		clocks = <&clock CLK_ACLK100>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_peri_opp_table>;
+		status = "disabled";
+	};
+
+	bus_fsys: bus_fsys {
+		compatible = "samsung,exynos-bus";
+		clocks = <&clock CLK_ACLK133>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_fsys_opp_table>;
+		status = "disabled";
+	};
+
+	bus_display: bus_display {
+		compatible = "samsung,exynos-bus";
+		clocks = <&clock CLK_ACLK160>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_display_opp_table>;
+		status = "disabled";
+	};
+
+	bus_lcd0: bus_lcd0 {
+		compatible = "samsung,exynos-bus";
+		clocks = <&clock CLK_ACLK200>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_leftbus_opp_table>;
+		status = "disabled";
+	};
+
+	bus_leftbus: bus_leftbus {
+		compatible = "samsung,exynos-bus";
+		clocks = <&clock CLK_DIV_GDL>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_leftbus_opp_table>;
+		status = "disabled";
+	};
+
+	bus_rightbus: bus_rightbus {
+		compatible = "samsung,exynos-bus";
+		clocks = <&clock CLK_DIV_GDR>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_leftbus_opp_table>;
+		status = "disabled";
+	};
+
+	bus_mfc: bus_mfc {
+		compatible = "samsung,exynos-bus";
+		clocks = <&clock CLK_SCLK_MFC>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_leftbus_opp_table>;
+		status = "disabled";
+	};
+
+	bus_dmc_opp_table: opp_table1 {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp@134000000 {
+			opp-hz = /bits/ 64 <134000000>;
+			opp-microvolt = <1025000>;
+		};
+		opp@267000000 {
+			opp-hz = /bits/ 64 <267000000>;
+			opp-microvolt = <1050000>;
+		};
+		opp@400000000 {
+			opp-hz = /bits/ 64 <400000000>;
+			opp-microvolt = <1150000>;
+		};
+	};
+
+	bus_acp_opp_table: opp_table2 {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp@134000000 {
+			opp-hz = /bits/ 64 <134000000>;
+		};
+		opp@160000000 {
+			opp-hz = /bits/ 64 <160000000>;
+		};
+		opp@200000000 {
+			opp-hz = /bits/ 64 <200000000>;
+		};
+	};
+
+	bus_peri_opp_table: opp_table3 {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp@5000000 {
+			opp-hz = /bits/ 64 <5000000>;
+		};
+		opp@100000000 {
+			opp-hz = /bits/ 64 <100000000>;
+		};
+	};
+
+	bus_fsys_opp_table: opp_table4 {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp@10000000 {
+			opp-hz = /bits/ 64 <10000000>;
+		};
+		opp@134000000 {
+			opp-hz = /bits/ 64 <134000000>;
+		};
+	};
+
+	bus_display_opp_table: opp_table5 {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp@100000000 {
+			opp-hz = /bits/ 64 <100000000>;
+		};
+		opp@134000000 {
+			opp-hz = /bits/ 64 <134000000>;
+		};
+		opp@160000000 {
+			opp-hz = /bits/ 64 <160000000>;
+		};
+	};
+
+	bus_leftbus_opp_table: opp_table6 {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp@100000000 {
+			opp-hz = /bits/ 64 <100000000>;
+		};
+		opp@160000000 {
+			opp-hz = /bits/ 64 <160000000>;
+		};
+		opp@200000000 {
+			opp-hz = /bits/ 64 <200000000>;
+		};
+	};
 };
 
 &gic {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/exynos4210-pinctrl.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/exynos4210-pinctrl.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/exynos4210-pinctrl.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/exynos4210-pinctrl.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -820,6 +820,13 @@
 			samsung,pin-pud = <1>;
 			samsung,pin-drv = <0>;
 		};
+
+		hdmi_cec: hdmi-cec {
+			samsung,pins = "gpx3-6";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
 	};
 
 	pinctrl@03860000 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/exynos4210-trats.dts linux-libre-4.7-gnu/arch/arm/boot/dts/exynos4210-trats.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/exynos4210-trats.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/exynos4210-trats.dts	2016-07-24 15:23:50.000000000 -0400
@@ -298,6 +298,8 @@
 		compatible = "maxim,max8997-pmic";
 
 		reg = <0x66>;
+		interrupt-parent = <&gpx0>;
+		interrupts = <7 0>;
 
 		max8997,pmic-buck1-uses-gpio-dvs;
 		max8997,pmic-buck2-uses-gpio-dvs;
@@ -359,7 +361,7 @@
 			};
 
 			vusbdac_reg: LDO8 {
-			     regulator-name = "VUSB/VDAC_3.3V_C210";
+			     regulator-name = "VUSB+VDAC_3.3V_C210";
 			     regulator-min-microvolt = <3300000>;
 			     regulator-max-microvolt = <3300000>;
 			};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/exynos4412-odroid-common.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/exynos4412-odroid-common.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/exynos4412-odroid-common.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -11,6 +11,7 @@
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/clock/maxim,max77686.h>
 #include "exynos4412.dtsi"
+#include "exynos4412-ppmu-common.dtsi"
 #include <dt-bindings/gpio/gpio.h>
 
 / {
@@ -108,6 +109,53 @@
 	};
 };
 
+&bus_dmc {
+	devfreq-events = <&ppmu_dmc0_3>, <&ppmu_dmc1_3>;
+	vdd-supply = <&buck1_reg>;
+	status = "okay";
+};
+
+&bus_acp {
+	devfreq = <&bus_dmc>;
+	status = "okay";
+};
+
+&bus_c2c {
+	devfreq = <&bus_dmc>;
+	status = "okay";
+};
+
+&bus_leftbus {
+	devfreq-events = <&ppmu_leftbus_3>, <&ppmu_rightbus_3>;
+	vdd-supply = <&buck3_reg>;
+	status = "okay";
+};
+
+&bus_rightbus {
+	devfreq = <&bus_leftbus>;
+	status = "okay";
+};
+
+&bus_display {
+	devfreq = <&bus_leftbus>;
+	status = "okay";
+};
+
+&bus_fsys {
+	devfreq = <&bus_leftbus>;
+	status = "okay";
+};
+
+&bus_peri {
+	devfreq = <&bus_leftbus>;
+	status = "okay";
+};
+
+&bus_mfc {
+	devfreq = <&bus_leftbus>;
+	status = "okay";
+};
+
 &cpu0 {
 	cpu0-supply = <&buck2_reg>;
 };
@@ -188,6 +236,10 @@
 	status = "okay";
 };
 
+&hdmicec {
+	status = "okay";
+};
+
 &hsotg {
 	dr_mode = "peripheral";
 	status = "okay";
@@ -355,8 +407,8 @@
 
 			buck1_reg: BUCK1 {
 				regulator-name = "vdd_mif";
-				regulator-min-microvolt = <1000000>;
-				regulator-max-microvolt = <1000000>;
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <1100000>;
 				regulator-always-on;
 				regulator-boot-on;
 			};
@@ -371,8 +423,8 @@
 
 			buck3_reg: BUCK3 {
 				regulator-name = "vdd_int";
-				regulator-min-microvolt = <1000000>;
-				regulator-max-microvolt = <1000000>;
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <1050000>;
 				regulator-always-on;
 				regulator-boot-on;
 			};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/exynos4412-ppmu-common.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/exynos4412-ppmu-common.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/exynos4412-ppmu-common.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/exynos4412-ppmu-common.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,50 @@
+/*
+ * Device tree sources for Exynos4412 PPMU common device tree
+ *
+ * Copyright (C) 2015 Samsung Electronics
+ * Author: Chanwoo Choi <cw00.choi@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+&ppmu_dmc0 {
+       status = "okay";
+
+       events {
+	       ppmu_dmc0_3: ppmu-event3-dmc0 {
+		       event-name = "ppmu-event3-dmc0";
+	       };
+       };
+};
+
+&ppmu_dmc1 {
+       status = "okay";
+
+       events {
+	       ppmu_dmc1_3: ppmu-event3-dmc1 {
+		       event-name = "ppmu-event3-dmc1";
+	       };
+       };
+};
+
+&ppmu_leftbus {
+       status = "okay";
+
+       events {
+	       ppmu_leftbus_3: ppmu-event3-leftbus {
+		       event-name = "ppmu-event3-leftbus";
+	       };
+       };
+};
+
+&ppmu_rightbus {
+       status = "okay";
+
+       events {
+	       ppmu_rightbus_3: ppmu-event3-rightbus {
+		       event-name = "ppmu-event3-rightbus";
+	       };
+       };
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/exynos4412-trats2.dts linux-libre-4.7-gnu/arch/arm/boot/dts/exynos4412-trats2.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/exynos4412-trats2.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/exynos4412-trats2.dts	2016-07-24 15:23:50.000000000 -0400
@@ -14,6 +14,7 @@
 
 /dts-v1/;
 #include "exynos4412.dtsi"
+#include "exynos4412-ppmu-common.dtsi"
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/clock/maxim,max77686.h>
@@ -146,13 +147,13 @@
 			reg = <0x66>;
 
 			regulators {
-				esafeout1_reg: ESAFEOUT1@1 {
+				esafeout1_reg: ESAFEOUT1 {
 					regulator-name = "ESAFEOUT1";
 				};
-				esafeout2_reg: ESAFEOUT2@2 {
+				esafeout2_reg: ESAFEOUT2 {
 					regulator-name = "ESAFEOUT2";
 				};
-				charger_reg: CHARGER@0 {
+				charger_reg: CHARGER {
 					regulator-name = "CHARGER";
 					regulator-min-microamp = <60000>;
 					regulator-max-microamp = <2580000>;
@@ -251,7 +252,7 @@
 			"SPK", "SPKOUTRP";
 	};
 
-	thermistor-ap@0 {
+	thermistor-ap {
 		compatible = "ntc,ncp15wb473";
 		pullup-uv = <1800000>;	 /* VCC_1.8V_AP */
 		pullup-ohm = <100000>;	 /* 100K */
@@ -259,7 +260,7 @@
 		io-channels = <&adc 1>;  /* AP temperature */
 	};
 
-	thermistor-battery@1 {
+	thermistor-battery {
 		compatible = "ntc,ncp15wb473";
 		pullup-uv = <1800000>;	 /* VCC_1.8V_AP */
 		pullup-ohm = <100000>;	 /* 100K */
@@ -288,6 +289,53 @@
 	status = "okay";
 };
 
+&bus_dmc {
+	devfreq-events = <&ppmu_dmc0_3>, <&ppmu_dmc1_3>;
+	vdd-supply = <&buck1_reg>;
+	status = "okay";
+};
+
+&bus_acp {
+	devfreq = <&bus_dmc>;
+	status = "okay";
+};
+
+&bus_c2c {
+	devfreq = <&bus_dmc>;
+	status = "okay";
+};
+
+&bus_leftbus {
+	devfreq-events = <&ppmu_leftbus_3>, <&ppmu_rightbus_3>;
+	vdd-supply = <&buck3_reg>;
+	status = "okay";
+};
+
+&bus_rightbus {
+	devfreq = <&bus_leftbus>;
+	status = "okay";
+};
+
+&bus_display {
+	devfreq = <&bus_leftbus>;
+	status = "okay";
+};
+
+&bus_fsys {
+	devfreq = <&bus_leftbus>;
+	status = "okay";
+};
+
+&bus_peri {
+	devfreq = <&bus_leftbus>;
+	status = "okay";
+};
+
+&bus_mfc {
+	devfreq = <&bus_leftbus>;
+	status = "okay";
+};
+
 &cpu0 {
 	cpu0-supply = <&buck2_reg>;
 };
@@ -871,46 +919,6 @@
 	assigned-clock-parents =  <&clock CLK_XUSBXTI>;
 };
 
-&ppmu_dmc0 {
-	status = "okay";
-
-	events {
-		ppmu_dmc0_3: ppmu-event3-dmc0 {
-			event-name = "ppmu-event3-dmc0";
-		};
-	};
-};
-
-&ppmu_dmc1 {
-	status = "okay";
-
-	events {
-		ppmu_dmc1_3: ppmu-event3-dmc1 {
-			event-name = "ppmu-event3-dmc1";
-		};
-	};
-};
-
-&ppmu_leftbus {
-	status = "okay";
-
-	events {
-		ppmu_leftbus_3: ppmu-event3-leftbus {
-			event-name = "ppmu-event3-leftbus";
-		};
-	};
-};
-
-&ppmu_rightbus {
-	status = "okay";
-
-	events {
-		ppmu_rightbus_3: ppmu-event3-rightbus {
-			event-name = "ppmu-event3-rightbus";
-		};
-	};
-};
-
 &pinctrl_0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&sleep0>;
@@ -1234,10 +1242,6 @@
 	status = "okay";
 };
 
-&prng {
-	status = "okay";
-};
-
 &rtc {
 	status = "okay";
 	clocks = <&clock CLK_RTC>, <&max77686 MAX77686_CLK_AP>;
@@ -1276,7 +1280,7 @@
 	cs-gpios = <&gpb 5 GPIO_ACTIVE_HIGH>;
 	status = "okay";
 
-	s5c73m3_spi: s5c73m3 {
+	s5c73m3_spi: s5c73m3@0 {
 		compatible = "samsung,s5c73m3";
 		spi-max-frequency = <50000000>;
 		reg = <0>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/exynos4.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/exynos4.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/exynos4.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/exynos4.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -77,12 +77,12 @@
 		reg = <0x10000000 0x100>;
 	};
 
-	sromc@12570000 {
-		compatible = "samsung,exynos-srom";
+	memory-controller@12570000 {
+		compatible = "samsung,exynos4210-srom";
 		reg = <0x12570000 0x14>;
 	};
 
-	mipi_phy: video-phy@10020710 {
+	mipi_phy: video-phy {
 		compatible = "samsung,s5pv210-mipi-video-phy";
 		#phy-cells = <1>;
 		syscon = <&pmu_system_controller>;
@@ -743,6 +743,18 @@
 		status = "disabled";
 	};
 
+	hdmicec: cec@100B0000 {
+		compatible = "samsung,s5p-cec";
+		reg = <0x100B0000 0x200>;
+		interrupts = <0 114 0>;
+		clocks = <&clock CLK_HDMI_CEC>;
+		clock-names = "hdmicec";
+		samsung,syscon-phandle = <&pmu_system_controller>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&hdmi_cec>;
+		status = "disabled";
+	};
+
 	mixer: mixer@12C10000 {
 		compatible = "samsung,exynos4210-mixer";
 		interrupts = <0 91 0>;
@@ -969,11 +981,18 @@
 		#iommu-cells = <0>;
 	};
 
+	sss: sss@10830000 {
+		compatible = "samsung,exynos4210-secss";
+		reg = <0x10830000 0x300>;
+		interrupts = <0 112 0>;
+		clocks = <&clock CLK_SSS>;
+		clock-names = "secss";
+	};
+
 	prng: rng@10830400 {
 		compatible = "samsung,exynos4-rng";
 		reg = <0x10830400 0x200>;
 		clocks = <&clock CLK_SSS>;
 		clock-names = "secss";
-		status = "disabled";
 	};
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/exynos4x12.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/exynos4x12.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/exynos4x12.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/exynos4x12.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -179,7 +179,7 @@
 			ranges;
 			status = "disabled";
 
-			pmu {
+			pmu@10020000 {
 				reg = <0x10020000 0x3000>;
 			};
 
@@ -281,6 +281,180 @@
 		clocks = <&clock CLK_SMMU_LITE1>, <&clock CLK_FIMC_LITE1>;
 		#iommu-cells = <0>;
 	};
+
+	bus_dmc: bus_dmc {
+		compatible = "samsung,exynos-bus";
+		clocks = <&clock CLK_DIV_DMC>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_dmc_opp_table>;
+		status = "disabled";
+	};
+
+	bus_acp: bus_acp {
+		compatible = "samsung,exynos-bus";
+		clocks = <&clock CLK_DIV_ACP>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_acp_opp_table>;
+		status = "disabled";
+	};
+
+	bus_c2c: bus_c2c {
+		compatible = "samsung,exynos-bus";
+		clocks = <&clock CLK_DIV_C2C>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_dmc_opp_table>;
+		status = "disabled";
+	};
+
+	bus_dmc_opp_table: opp_table1 {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp@100000000 {
+			opp-hz = /bits/ 64 <100000000>;
+			opp-microvolt = <900000>;
+		};
+		opp@134000000 {
+			opp-hz = /bits/ 64 <134000000>;
+			opp-microvolt = <900000>;
+		};
+		opp@160000000 {
+			opp-hz = /bits/ 64 <160000000>;
+			opp-microvolt = <900000>;
+		};
+		opp@267000000 {
+			opp-hz = /bits/ 64 <267000000>;
+			opp-microvolt = <950000>;
+		};
+		opp@400000000 {
+			opp-hz = /bits/ 64 <400000000>;
+			opp-microvolt = <1050000>;
+		};
+	};
+
+	bus_acp_opp_table: opp_table2 {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp@100000000 {
+			opp-hz = /bits/ 64 <100000000>;
+		};
+		opp@134000000 {
+			opp-hz = /bits/ 64 <134000000>;
+		};
+		opp@160000000 {
+			opp-hz = /bits/ 64 <160000000>;
+		};
+		opp@267000000 {
+			opp-hz = /bits/ 64 <267000000>;
+		};
+	};
+
+	bus_leftbus: bus_leftbus {
+		compatible = "samsung,exynos-bus";
+		clocks = <&clock CLK_DIV_GDL>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_leftbus_opp_table>;
+		status = "disabled";
+	};
+
+	bus_rightbus: bus_rightbus {
+		compatible = "samsung,exynos-bus";
+		clocks = <&clock CLK_DIV_GDR>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_leftbus_opp_table>;
+		status = "disabled";
+	};
+
+	bus_display: bus_display {
+		compatible = "samsung,exynos-bus";
+		clocks = <&clock CLK_ACLK160>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_display_opp_table>;
+		status = "disabled";
+	};
+
+	bus_fsys: bus_fsys {
+		compatible = "samsung,exynos-bus";
+		clocks = <&clock CLK_ACLK133>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_fsys_opp_table>;
+		status = "disabled";
+	};
+
+	bus_peri: bus_peri {
+		compatible = "samsung,exynos-bus";
+		clocks = <&clock CLK_ACLK100>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_peri_opp_table>;
+		status = "disabled";
+	};
+
+	bus_mfc: bus_mfc {
+		compatible = "samsung,exynos-bus";
+		clocks = <&clock CLK_SCLK_MFC>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_leftbus_opp_table>;
+		status = "disabled";
+	};
+
+	bus_leftbus_opp_table: opp_table3 {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp@100000000 {
+			opp-hz = /bits/ 64 <100000000>;
+			opp-microvolt = <900000>;
+		};
+		opp@134000000 {
+			opp-hz = /bits/ 64 <134000000>;
+			opp-microvolt = <925000>;
+		};
+		opp@160000000 {
+			opp-hz = /bits/ 64 <160000000>;
+			opp-microvolt = <950000>;
+		};
+		opp@200000000 {
+			opp-hz = /bits/ 64 <200000000>;
+			opp-microvolt = <1000000>;
+		};
+	};
+
+	bus_display_opp_table: opp_table4 {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp@160000000 {
+			opp-hz = /bits/ 64 <160000000>;
+		};
+		opp@200000000 {
+			opp-hz = /bits/ 64 <200000000>;
+		};
+	};
+
+	bus_fsys_opp_table: opp_table5 {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp@100000000 {
+			opp-hz = /bits/ 64 <100000000>;
+		};
+		opp@134000000 {
+			opp-hz = /bits/ 64 <134000000>;
+		};
+	};
+
+	bus_peri_opp_table: opp_table6 {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp@50000000 {
+			opp-hz = /bits/ 64 <50000000>;
+		};
+		opp@100000000 {
+			opp-hz = /bits/ 64 <100000000>;
+		};
+	};
 };
 
 &combiner {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/exynos4x12-pinctrl.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/exynos4x12-pinctrl.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/exynos4x12-pinctrl.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/exynos4x12-pinctrl.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -885,6 +885,13 @@
 			samsung,pin-pud = <0>;
 			samsung,pin-drv = <0>;
 		};
+
+		hdmi_cec: hdmi-cec {
+			samsung,pins = "gpx3-6";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
 	};
 
 	pinctrl_2: pinctrl@03860000 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/exynos5250-arndale.dts linux-libre-4.7-gnu/arch/arm/boot/dts/exynos5250-arndale.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/exynos5250-arndale.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/exynos5250-arndale.dts	2016-07-24 15:23:50.000000000 -0400
@@ -124,8 +124,6 @@
 &dp {
 	status = "okay";
 	samsung,color-space = <0>;
-	samsung,dynamic-range = <0>;
-	samsung,ycbcr-coeff = <0>;
 	samsung,color-depth = <1>;
 	samsung,link-rate = <0x0a>;
 	samsung,lane-count = <4>;
@@ -133,7 +131,7 @@
 	display-timings {
 		native-mode = <&timing0>;
 
-		timing0: timing@0 {
+		timing0: timing {
 			/* 2560x1600 DP panel */
 			clock-frequency = <50000>;
 			hactive = <2560>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/exynos5250.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/exynos5250.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/exynos5250.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/exynos5250.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -596,7 +596,7 @@
 		pinctrl-0 = <&i2s2_bus>;
 	};
 
-	usb@12000000 {
+	usb_dwc3 {
 		compatible = "samsung,exynos5250-dwusb3";
 		clocks = <&clock CLK_USB3>;
 		clock-names = "usbdrd30";
@@ -604,7 +604,7 @@
 		#size-cells = <1>;
 		ranges;
 
-		usbdrd_dwc3: dwc3 {
+		usbdrd_dwc3: dwc3@12000000 {
 			compatible = "synopsys,dwc3";
 			reg = <0x12000000 0x10000>;
 			interrupts = <0 72 0>;
@@ -763,7 +763,7 @@
 		iommu = <&sysmmu_gsc3>;
 	};
 
-	hdmi: hdmi {
+	hdmi: hdmi@14530000 {
 		compatible = "samsung,exynos4212-hdmi";
 		reg = <0x14530000 0x70000>;
 		power-domains = <&pd_disp1>;
@@ -776,7 +776,7 @@
 		samsung,syscon-phandle = <&pmu_system_controller>;
 	};
 
-	mixer {
+	mixer@14450000 {
 		compatible = "samsung,exynos5250-mixer";
 		reg = <0x14450000 0x10000>;
 		power-domains = <&pd_disp1>;
@@ -787,7 +787,7 @@
 		iommus = <&sysmmu_tv>;
 	};
 
-	dp_phy: video-phy@10040720 {
+	dp_phy: video-phy {
 		compatible = "samsung,exynos5250-dp-video-phy";
 		samsung,pmu-syscon = <&pmu_system_controller>;
 		#phy-cells = <0>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/exynos5250-smdk5250.dts linux-libre-4.7-gnu/arch/arm/boot/dts/exynos5250-smdk5250.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/exynos5250-smdk5250.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/exynos5250-smdk5250.dts	2016-07-24 15:23:50.000000000 -0400
@@ -29,7 +29,7 @@
 		bootargs = "root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC2,115200 init=/linuxrc";
 	};
 
-	vdd: fixed-regulator@0 {
+	vdd: fixed-regulator-vdd {
 		compatible = "regulator-fixed";
 		regulator-name = "vdd-supply";
 		regulator-min-microvolt = <1800000>;
@@ -37,7 +37,7 @@
 		regulator-always-on;
 	};
 
-	dbvdd: fixed-regulator@1 {
+	dbvdd: fixed-regulator-dbvdd {
 		compatible = "regulator-fixed";
 		regulator-name = "dbvdd-supply";
 		regulator-min-microvolt = <3300000>;
@@ -45,7 +45,7 @@
 		regulator-always-on;
 	};
 
-	spkvdd: fixed-regulator@2 {
+	spkvdd: fixed-regulator-spkvdd {
 		compatible = "regulator-fixed";
 		regulator-name = "spkvdd-supply";
 		regulator-min-microvolt = <5000000>;
@@ -80,8 +80,6 @@
 
 &dp {
 	samsung,color-space = <0>;
-	samsung,dynamic-range = <0>;
-	samsung,ycbcr-coeff = <0>;
 	samsung,color-depth = <1>;
 	samsung,link-rate = <0x0a>;
 	samsung,lane-count = <4>;
@@ -93,7 +91,7 @@
 	display-timings {
 		native-mode = <&timing0>;
 
-		timing0: timing@0 {
+		timing0: timing {
 			/* 1280x800 */
 			clock-frequency = <50000>;
 			hactive = <1280>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/exynos5250-snow-common.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/exynos5250-snow-common.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/exynos5250-snow-common.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/exynos5250-snow-common.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -84,7 +84,7 @@
 				sbs,poll-retry-count = <1>;
 			};
 
-			cros_ec: embedded-controller {
+			cros_ec: embedded-controller@1e {
 				compatible = "google,cros-ec-i2c";
 				reg = <0x1e>;
 				interrupts = <6 IRQ_TYPE_NONE>;
@@ -94,7 +94,7 @@
 				wakeup-source;
 			};
 
-			power-regulator {
+			power-regulator@48 {
 				compatible = "ti,tps65090";
 				reg = <0x48>;
 
@@ -236,15 +236,13 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&dp_hpd>;
 	samsung,color-space = <0>;
-	samsung,dynamic-range = <0>;
-	samsung,ycbcr-coeff = <0>;
 	samsung,color-depth = <1>;
 	samsung,link-rate = <0x0a>;
 	samsung,lane-count = <2>;
-	samsung,hpd-gpio = <&gpx0 7 GPIO_ACTIVE_HIGH>;
+	hpd-gpios = <&gpx0 7 GPIO_ACTIVE_HIGH>;
 
 	ports {
-		port@0 {
+		port {
 			dp_out: endpoint {
 				remote-endpoint = <&bridge_in>;
 			};
@@ -428,7 +426,7 @@
 	samsung,i2c-sda-delay = <100>;
 	samsung,i2c-max-bus-freq = <378000>;
 
-	trackpad {
+	trackpad@67 {
 		reg = <0x67>;
 		compatible = "cypress,cyapa";
 		interrupts = <2 IRQ_TYPE_NONE>;
@@ -487,13 +485,20 @@
 		edid-emulation = <5>;
 
 		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
 			port@0 {
+				reg = <0>;
+
 				bridge_out: endpoint {
 					remote-endpoint = <&panel_in>;
 				};
 			};
 
 			port@1 {
+				reg = <1>;
+
 				bridge_in: endpoint {
 					remote-endpoint = <&dp_out>;
 				};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/exynos5250-spring.dts linux-libre-4.7-gnu/arch/arm/boot/dts/exynos5250-spring.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/exynos5250-spring.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/exynos5250-spring.dts	2016-07-24 15:23:50.000000000 -0400
@@ -74,12 +74,10 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&dp_hpd_gpio>;
 	samsung,color-space = <0>;
-	samsung,dynamic-range = <0>;
-	samsung,ycbcr-coeff = <0>;
 	samsung,color-depth = <1>;
 	samsung,link-rate = <0x0a>;
 	samsung,lane-count = <1>;
-	samsung,hpd-gpio = <&gpc3 0 GPIO_ACTIVE_HIGH>;
+	hpd-gpios = <&gpc3 0 GPIO_ACTIVE_HIGH>;
 };
 
 &ehci {
@@ -383,7 +381,7 @@
 	samsung,i2c-sda-delay = <100>;
 	samsung,i2c-max-bus-freq = <66000>;
 
-	cros_ec: embedded-controller {
+	cros_ec: embedded-controller@1e {
 		compatible = "google,cros-ec-i2c";
 		reg = <0x1e>;
 		interrupts = <6 IRQ_TYPE_NONE>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/exynos5410.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/exynos5410.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/exynos5410.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/exynos5410.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -102,8 +102,8 @@
 			reg = <0x10000000 0x100>;
 		};
 
-		sromc: sromc@12250000 {
-			compatible = "samsung,exynos-srom";
+		sromc: memory-controller@12250000 {
+			compatible = "samsung,exynos4210-srom";
 			reg = <0x12250000 0x14>;
 			#address-cells = <2>;
 			#size-cells = <1>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/exynos5410-smdk5410.dts linux-libre-4.7-gnu/arch/arm/boot/dts/exynos5410-smdk5410.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/exynos5410-smdk5410.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/exynos5410-smdk5410.dts	2016-07-24 15:23:50.000000000 -0400
@@ -97,7 +97,7 @@
 		smsc,irq-push-pull;
 		smsc,force-internal-phy;
 
-		samsung,srom-page-mode = <1>;
+		samsung,srom-page-mode;
 		samsung,srom-timing = <9 12 1 9 1 1>;
 	};
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/exynos5420-arndale-octa.dts linux-libre-4.7-gnu/arch/arm/boot/dts/exynos5420-arndale-octa.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/exynos5420-arndale-octa.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/exynos5420-arndale-octa.dts	2016-07-24 15:23:50.000000000 -0400
@@ -75,13 +75,6 @@
 	s2mps11_pmic@66 {
 		compatible = "samsung,s2mps11-pmic";
 		reg = <0x66>;
-		s2mps11,buck2-ramp-delay = <12>;
-		s2mps11,buck34-ramp-delay = <12>;
-		s2mps11,buck16-ramp-delay = <12>;
-		s2mps11,buck6-ramp-enable = <1>;
-		s2mps11,buck2-ramp-enable = <1>;
-		s2mps11,buck3-ramp-enable = <1>;
-		s2mps11,buck4-ramp-enable = <1>;
 
 		interrupt-parent = <&gpx3>;
 		interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/exynos5420.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/exynos5420.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/exynos5420.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/exynos5420.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -294,6 +294,42 @@
 		};
 	};
 
+	nocp_mem0_0: nocp@10CA1000 {
+		compatible = "samsung,exynos5420-nocp";
+		reg = <0x10CA1000 0x200>;
+		status = "disabled";
+	};
+
+	nocp_mem0_1: nocp@10CA1400 {
+		compatible = "samsung,exynos5420-nocp";
+		reg = <0x10CA1400 0x200>;
+		status = "disabled";
+	};
+
+	nocp_mem1_0: nocp@10CA1800 {
+		compatible = "samsung,exynos5420-nocp";
+		reg = <0x10CA1800 0x200>;
+		status = "disabled";
+	};
+
+	nocp_mem1_1: nocp@10CA1C00 {
+		compatible = "samsung,exynos5420-nocp";
+		reg = <0x10CA1C00 0x200>;
+		status = "disabled";
+	};
+
+	nocp_g3d_0: nocp@11A51000 {
+		compatible = "samsung,exynos5420-nocp";
+		reg = <0x11A51000 0x200>;
+		status = "disabled";
+	};
+
+	nocp_g3d_1: nocp@11A51400 {
+		compatible = "samsung,exynos5420-nocp";
+		reg = <0x11A51400 0x200>;
+		status = "disabled";
+	};
+
 	gsc_pd: power-domain@10044000 {
 		compatible = "samsung,exynos4210-pd";
 		reg = <0x10044000 0x20>;
@@ -551,13 +587,13 @@
 		clock-names = "timers";
 	};
 
-	dp_phy: video-phy@10040728 {
+	dp_phy: dp-video-phy {
 		compatible = "samsung,exynos5420-dp-video-phy";
 		samsung,pmu-syscon = <&pmu_system_controller>;
 		#phy-cells = <0>;
 	};
 
-	mipi_phy: video-phy@10040714 {
+	mipi_phy: mipi-video-phy {
 		compatible = "samsung,s5pv210-mipi-video-phy";
 		syscon = <&pmu_system_controller>;
 		#phy-cells = <1>;
@@ -913,7 +949,7 @@
 		clock-names = "secss";
 	};
 
-	usbdrd3_0: usb@12000000 {
+	usbdrd3_0: usb3-0 {
 		compatible = "samsung,exynos5250-dwusb3";
 		clocks = <&clock CLK_USBD300>;
 		clock-names = "usbdrd30";
@@ -921,7 +957,7 @@
 		#size-cells = <1>;
 		ranges;
 
-		usbdrd_dwc3_0: dwc3 {
+		usbdrd_dwc3_0: dwc3@12000000 {
 			compatible = "snps,dwc3";
 			reg = <0x12000000 0x10000>;
 			interrupts = <0 72 0>;
@@ -939,7 +975,7 @@
 		#phy-cells = <1>;
 	};
 
-	usbdrd3_1: usb@12400000 {
+	usbdrd3_1: usb3-1 {
 		compatible = "samsung,exynos5250-dwusb3";
 		clocks = <&clock CLK_USBD301>;
 		clock-names = "usbdrd30";
@@ -947,7 +983,7 @@
 		#size-cells = <1>;
 		ranges;
 
-		usbdrd_dwc3_1: dwc3 {
+		usbdrd_dwc3_1: dwc3@12400000 {
 			compatible = "snps,dwc3";
 			reg = <0x12400000 0x10000>;
 			interrupts = <0 73 0>;
@@ -1188,6 +1224,377 @@
 		power-domains = <&disp_pd>;
 		#iommu-cells = <0>;
 	};
+
+	bus_wcore: bus_wcore {
+		compatible = "samsung,exynos-bus";
+		clocks = <&clock CLK_DOUT_ACLK400_WCORE>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_wcore_opp_table>;
+		status = "disabled";
+	};
+
+	bus_noc: bus_noc {
+		compatible = "samsung,exynos-bus";
+		clocks = <&clock CLK_DOUT_ACLK100_NOC>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_noc_opp_table>;
+		status = "disabled";
+	};
+
+	bus_fsys_apb: bus_fsys_apb {
+		compatible = "samsung,exynos-bus";
+		clocks = <&clock CLK_DOUT_PCLK200_FSYS>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_fsys_apb_opp_table>;
+		status = "disabled";
+	};
+
+	bus_fsys: bus_fsys {
+		compatible = "samsung,exynos-bus";
+		clocks = <&clock CLK_DOUT_ACLK200_FSYS>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_fsys_apb_opp_table>;
+		status = "disabled";
+	};
+
+	bus_fsys2: bus_fsys2 {
+		compatible = "samsung,exynos-bus";
+		clocks = <&clock CLK_DOUT_ACLK200_FSYS2>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_fsys2_opp_table>;
+		status = "disabled";
+	};
+
+	bus_mfc: bus_mfc {
+		compatible = "samsung,exynos-bus";
+		clocks = <&clock CLK_DOUT_ACLK333>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_mfc_opp_table>;
+		status = "disabled";
+	};
+
+	bus_gen: bus_gen {
+		compatible = "samsung,exynos-bus";
+		clocks = <&clock CLK_DOUT_ACLK266>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_gen_opp_table>;
+		status = "disabled";
+	};
+
+	bus_peri: bus_peri {
+		compatible = "samsung,exynos-bus";
+		clocks = <&clock CLK_DOUT_ACLK66>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_peri_opp_table>;
+		status = "disabled";
+	};
+
+	bus_g2d: bus_g2d {
+		compatible = "samsung,exynos-bus";
+		clocks = <&clock CLK_DOUT_ACLK333_G2D>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_g2d_opp_table>;
+		status = "disabled";
+	};
+
+	bus_g2d_acp: bus_g2d_acp {
+		compatible = "samsung,exynos-bus";
+		clocks = <&clock CLK_DOUT_ACLK266_G2D>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_g2d_acp_opp_table>;
+		status = "disabled";
+	};
+
+	bus_jpeg: bus_jpeg {
+		compatible = "samsung,exynos-bus";
+		clocks = <&clock CLK_DOUT_ACLK300_JPEG>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_jpeg_opp_table>;
+		status = "disabled";
+	};
+
+	bus_jpeg_apb: bus_jpeg_apb {
+		compatible = "samsung,exynos-bus";
+		clocks = <&clock CLK_DOUT_ACLK166>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_jpeg_apb_opp_table>;
+		status = "disabled";
+	};
+
+	bus_disp1_fimd: bus_disp1_fimd {
+		compatible = "samsung,exynos-bus";
+		clocks = <&clock CLK_DOUT_ACLK300_DISP1>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_disp1_fimd_opp_table>;
+		status = "disabled";
+	};
+
+	bus_disp1: bus_disp1 {
+		compatible = "samsung,exynos-bus";
+		clocks = <&clock CLK_DOUT_ACLK400_DISP1>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_disp1_opp_table>;
+		status = "disabled";
+	};
+
+	bus_gscl_scaler: bus_gscl_scaler {
+		compatible = "samsung,exynos-bus";
+		clocks = <&clock CLK_DOUT_ACLK300_GSCL>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_gscl_opp_table>;
+		status = "disabled";
+	};
+
+	bus_mscl: bus_mscl {
+		compatible = "samsung,exynos-bus";
+		clocks = <&clock CLK_DOUT_ACLK400_MSCL>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_mscl_opp_table>;
+		status = "disabled";
+	};
+
+	bus_wcore_opp_table: opp_table2 {
+		compatible = "operating-points-v2";
+
+		opp00 {
+			opp-hz = /bits/ 64 <84000000>;
+			opp-microvolt = <925000>;
+		};
+		opp01 {
+			opp-hz = /bits/ 64 <111000000>;
+			opp-microvolt = <950000>;
+		};
+		opp02 {
+			opp-hz = /bits/ 64 <222000000>;
+			opp-microvolt = <950000>;
+		};
+		opp03 {
+			opp-hz = /bits/ 64 <333000000>;
+			opp-microvolt = <950000>;
+		};
+		opp04 {
+			opp-hz = /bits/ 64 <400000000>;
+			opp-microvolt = <987500>;
+		};
+	};
+
+	bus_noc_opp_table: opp_table3 {
+		compatible = "operating-points-v2";
+
+		opp00 {
+			opp-hz = /bits/ 64 <67000000>;
+		};
+		opp01 {
+			opp-hz = /bits/ 64 <75000000>;
+		};
+		opp02 {
+			opp-hz = /bits/ 64 <86000000>;
+		};
+		opp03 {
+			opp-hz = /bits/ 64 <100000000>;
+		};
+	};
+
+	bus_fsys_apb_opp_table: opp_table4 {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp00 {
+			opp-hz = /bits/ 64 <100000000>;
+		};
+		opp01 {
+			opp-hz = /bits/ 64 <200000000>;
+		};
+	};
+
+	bus_fsys2_opp_table: opp_table5 {
+		compatible = "operating-points-v2";
+
+		opp00 {
+			opp-hz = /bits/ 64 <75000000>;
+		};
+		opp01 {
+			opp-hz = /bits/ 64 <100000000>;
+		};
+		opp02 {
+			opp-hz = /bits/ 64 <150000000>;
+		};
+	};
+
+	bus_mfc_opp_table: opp_table6 {
+		compatible = "operating-points-v2";
+
+		opp00 {
+			opp-hz = /bits/ 64 <96000000>;
+		};
+		opp01 {
+			opp-hz = /bits/ 64 <111000000>;
+		};
+		opp02 {
+			opp-hz = /bits/ 64 <167000000>;
+		};
+		opp03 {
+			opp-hz = /bits/ 64 <222000000>;
+		};
+		opp04 {
+			opp-hz = /bits/ 64 <333000000>;
+		};
+	};
+
+	bus_gen_opp_table: opp_table7 {
+		compatible = "operating-points-v2";
+
+		opp00 {
+			opp-hz = /bits/ 64 <89000000>;
+		};
+		opp01 {
+			opp-hz = /bits/ 64 <133000000>;
+		};
+		opp02 {
+			opp-hz = /bits/ 64 <178000000>;
+		};
+		opp03 {
+			opp-hz = /bits/ 64 <267000000>;
+		};
+	};
+
+	bus_peri_opp_table: opp_table8 {
+		compatible = "operating-points-v2";
+
+		opp00 {
+			opp-hz = /bits/ 64 <67000000>;
+		};
+	};
+
+	bus_g2d_opp_table: opp_table9 {
+		compatible = "operating-points-v2";
+
+		opp00 {
+			opp-hz = /bits/ 64 <84000000>;
+		};
+		opp01 {
+			opp-hz = /bits/ 64 <167000000>;
+		};
+		opp02 {
+			opp-hz = /bits/ 64 <222000000>;
+		};
+		opp03 {
+			opp-hz = /bits/ 64 <300000000>;
+		};
+		opp04 {
+			opp-hz = /bits/ 64 <333000000>;
+		};
+	};
+
+	bus_g2d_acp_opp_table: opp_table10 {
+		compatible = "operating-points-v2";
+
+		opp00 {
+			opp-hz = /bits/ 64 <67000000>;
+		};
+		opp01 {
+			opp-hz = /bits/ 64 <133000000>;
+		};
+		opp02 {
+			opp-hz = /bits/ 64 <178000000>;
+		};
+		opp03 {
+			opp-hz = /bits/ 64 <267000000>;
+		};
+	};
+
+	bus_jpeg_opp_table: opp_table11 {
+		compatible = "operating-points-v2";
+
+		opp00 {
+			opp-hz = /bits/ 64 <75000000>;
+		};
+		opp01 {
+			opp-hz = /bits/ 64 <150000000>;
+		};
+		opp02 {
+			opp-hz = /bits/ 64 <200000000>;
+		};
+		opp03 {
+			opp-hz = /bits/ 64 <300000000>;
+		};
+	};
+
+	bus_jpeg_apb_opp_table: opp_table12 {
+		compatible = "operating-points-v2";
+
+		opp00 {
+			opp-hz = /bits/ 64 <84000000>;
+		};
+		opp01 {
+			opp-hz = /bits/ 64 <111000000>;
+		};
+		opp02 {
+			opp-hz = /bits/ 64 <134000000>;
+		};
+		opp03 {
+			opp-hz = /bits/ 64 <167000000>;
+		};
+	};
+
+	bus_disp1_fimd_opp_table: opp_table13 {
+		compatible = "operating-points-v2";
+
+		opp00 {
+			opp-hz = /bits/ 64 <120000000>;
+		};
+		opp01 {
+			opp-hz = /bits/ 64 <200000000>;
+		};
+	};
+
+	bus_disp1_opp_table: opp_table14 {
+		compatible = "operating-points-v2";
+
+		opp00 {
+			opp-hz = /bits/ 64 <120000000>;
+		};
+		opp01 {
+			opp-hz = /bits/ 64 <200000000>;
+		};
+		opp02 {
+			opp-hz = /bits/ 64 <300000000>;
+		};
+	};
+
+	bus_gscl_opp_table: opp_table15 {
+		compatible = "operating-points-v2";
+
+		opp00 {
+			opp-hz = /bits/ 64 <150000000>;
+		};
+		opp01 {
+			opp-hz = /bits/ 64 <200000000>;
+		};
+		opp02 {
+			opp-hz = /bits/ 64 <300000000>;
+		};
+	};
+
+	bus_mscl_opp_table: opp_table16 {
+		compatible = "operating-points-v2";
+
+		opp00 {
+			opp-hz = /bits/ 64 <84000000>;
+		};
+		opp01 {
+			opp-hz = /bits/ 64 <167000000>;
+		};
+		opp02 {
+			opp-hz = /bits/ 64 <222000000>;
+		};
+		opp03 {
+			opp-hz = /bits/ 64 <333000000>;
+		};
+		opp04 {
+			opp-hz = /bits/ 64 <400000000>;
+		};
+	};
 };
 
 &dp {
@@ -1199,6 +1606,7 @@
 };
 
 &fimd {
+	compatible = "samsung,exynos5420-fimd";
 	clocks = <&clock CLK_SCLK_FIMD1>, <&clock CLK_FIMD1>;
 	clock-names = "sclk_fimd", "fimd";
 	power-domains = <&disp_pd>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/exynos5420-peach-pit.dts linux-libre-4.7-gnu/arch/arm/boot/dts/exynos5420-peach-pit.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/exynos5420-peach-pit.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/exynos5420-peach-pit.dts	2016-07-24 15:23:50.000000000 -0400
@@ -157,15 +157,13 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&dp_hpd_gpio>;
 	samsung,color-space = <0>;
-	samsung,dynamic-range = <0>;
-	samsung,ycbcr-coeff = <0>;
 	samsung,color-depth = <1>;
 	samsung,link-rate = <0x06>;
 	samsung,lane-count = <2>;
-	samsung,hpd-gpio = <&gpx2 6 GPIO_ACTIVE_HIGH>;
+	hpd-gpios = <&gpx2 6 GPIO_ACTIVE_HIGH>;
 
 	ports {
-		port@0 {
+		port {
 			dp_out: endpoint {
 				remote-endpoint = <&bridge_in>;
 			};
@@ -633,13 +631,20 @@
 		use-external-pwm;
 
 		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
 			port@0 {
+				reg = <0>;
+
 				bridge_out: endpoint {
 					remote-endpoint = <&panel_in>;
 				};
 			};
 
 			port@1 {
+				reg = <1>;
+
 				bridge_in: endpoint {
 					remote-endpoint = <&dp_out>;
 				};
@@ -696,6 +701,11 @@
 	status = "okay";
 };
 
+&mfc {
+	samsung,mfc-r = <0x43000000 0x800000>;
+	samsung,mfc-l = <0x51000000 0x800000>;
+};
+
 &mmc_0 {
 	status = "okay";
 	num-slots = <1>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/exynos5420-smdk5420.dts linux-libre-4.7-gnu/arch/arm/boot/dts/exynos5420-smdk5420.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/exynos5420-smdk5420.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/exynos5420-smdk5420.dts	2016-07-24 15:23:50.000000000 -0400
@@ -102,8 +102,6 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&dp_hpd>;
 	samsung,color-space = <0>;
-	samsung,dynamic-range = <0>;
-	samsung,ycbcr-coeff = <0>;
 	samsung,color-depth = <1>;
 	samsung,link-rate = <0x0a>;
 	samsung,lane-count = <4>;
@@ -111,7 +109,7 @@
 
 	display-timings {
 		native-mode = <&timing0>;
-		timing0: timing@0 {
+		timing0: timing {
 			clock-frequency = <50000>;
 			hactive = <2560>;
 			vactive = <1600>;
@@ -142,13 +140,6 @@
 	s2mps11_pmic@66 {
 		compatible = "samsung,s2mps11-pmic";
 		reg = <0x66>;
-		s2mps11,buck2-ramp-delay = <12>;
-		s2mps11,buck34-ramp-delay = <12>;
-		s2mps11,buck16-ramp-delay = <12>;
-		s2mps11,buck6-ramp-enable = <1>;
-		s2mps11,buck2-ramp-enable = <1>;
-		s2mps11,buck3-ramp-enable = <1>;
-		s2mps11,buck4-ramp-enable = <1>;
 
 		s2mps11_osc: clocks {
 			#clock-cells = <1>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -56,6 +56,89 @@
 	};
 };
 
+&bus_wcore {
+	devfreq-events = <&nocp_mem0_0>, <&nocp_mem0_1>,
+			<&nocp_mem1_0>, <&nocp_mem1_1>;
+	vdd-supply = <&buck3_reg>;
+	exynos,saturation-ratio = <100>;
+	status = "okay";
+};
+
+&bus_noc {
+	devfreq = <&bus_wcore>;
+	status = "okay";
+};
+
+&bus_fsys_apb {
+	devfreq = <&bus_wcore>;
+	status = "okay";
+};
+
+&bus_fsys {
+	devfreq = <&bus_wcore>;
+	status = "okay";
+};
+
+&bus_fsys2 {
+	devfreq = <&bus_wcore>;
+	status = "okay";
+};
+
+&bus_mfc {
+	devfreq = <&bus_wcore>;
+	status = "okay";
+};
+
+&bus_gen {
+	devfreq = <&bus_wcore>;
+	status = "okay";
+};
+
+&bus_peri {
+	devfreq = <&bus_wcore>;
+	status = "okay";
+};
+
+&bus_g2d {
+	devfreq = <&bus_wcore>;
+	status = "okay";
+};
+
+&bus_g2d_acp {
+	devfreq = <&bus_wcore>;
+	status = "okay";
+};
+
+&bus_jpeg {
+	devfreq = <&bus_wcore>;
+	status = "okay";
+};
+
+&bus_jpeg_apb {
+	devfreq = <&bus_wcore>;
+	status = "okay";
+};
+
+&bus_disp1_fimd {
+	devfreq = <&bus_wcore>;
+	status = "okay";
+};
+
+&bus_disp1 {
+	devfreq = <&bus_wcore>;
+	status = "okay";
+};
+
+&bus_gscl_scaler {
+	devfreq = <&bus_wcore>;
+	status = "okay";
+};
+
+&bus_mscl {
+	devfreq = <&bus_wcore>;
+	status = "okay";
+};
+
 &clock_audss {
 	assigned-clocks = <&clock_audss EXYNOS_MOUT_AUDSS>,
 			<&clock_audss EXYNOS_MOUT_I2S>,
@@ -92,13 +175,6 @@
 	s2mps11_pmic@66 {
 		compatible = "samsung,s2mps11-pmic";
 		reg = <0x66>;
-		s2mps11,buck2-ramp-delay = <12>;
-		s2mps11,buck34-ramp-delay = <12>;
-		s2mps11,buck16-ramp-delay = <12>;
-		s2mps11,buck6-ramp-enable = <1>;
-		s2mps11,buck2-ramp-enable = <1>;
-		s2mps11,buck3-ramp-enable = <1>;
-		s2mps11,buck4-ramp-enable = <1>;
 		samsung,s2mps11-acokb-ground;
 
 		interrupt-parent = <&gpx0>;
@@ -121,10 +197,9 @@
 			};
 
 			ldo3_reg: LDO3 {
-				regulator-name = "vdd_ldo3";
+				regulator-name = "vddq_mmc0";
 				regulator-min-microvolt = <1800000>;
 				regulator-max-microvolt = <1800000>;
-				regulator-always-on;
 			};
 
 			ldo5_reg: LDO5 {
@@ -184,10 +259,9 @@
 			};
 
 			ldo13_reg: LDO13 {
-				regulator-name = "vdd_ldo13";
+				regulator-name = "vddq_mmc2";
 				regulator-min-microvolt = <2800000>;
 				regulator-max-microvolt = <2800000>;
-				regulator-always-on;
 			};
 
 			ldo15_reg: LDO15 {
@@ -211,11 +285,16 @@
 				regulator-always-on;
 			};
 
+			ldo18_reg: LDO18 {
+				regulator-name = "vdd_emmc_1V8";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+			};
+
 			ldo19_reg: LDO19 {
 				regulator-name = "vdd_sd";
 				regulator-min-microvolt = <2800000>;
 				regulator-max-microvolt = <2800000>;
-				regulator-always-on;
 			};
 
 			ldo24_reg: LDO24 {
@@ -347,6 +426,8 @@
 	cap-mmc-highspeed;
 	mmc-hs200-1_8v;
 	mmc-hs400-1_8v;
+	vmmc-supply = <&ldo18_reg>;
+	vqmmc-supply = <&ldo3_reg>;
 };
 
 &mmc_2 {
@@ -359,6 +440,24 @@
 	pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus1 &sd2_bus4>;
 	bus-width = <4>;
 	cap-sd-highspeed;
+	vmmc-supply = <&ldo19_reg>;
+	vqmmc-supply = <&ldo13_reg>;
+};
+
+&nocp_mem0_0 {
+	status = "okay";
+};
+
+&nocp_mem0_1 {
+	status = "okay";
+};
+
+&nocp_mem1_0 {
+	status = "okay";
+};
+
+&nocp_mem1_1 {
+	status = "okay";
 };
 
 &pinctrl_0 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/exynos5440.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/exynos5440.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/exynos5440.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/exynos5440.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -132,7 +132,7 @@
 		clock-names = "spi", "spi_busclk0";
 	};
 
-	pin_ctrl: pinctrl {
+	pin_ctrl: pinctrl@E0000 {
 		compatible = "samsung,exynos5440-pinctrl";
 		reg = <0xE0000 0x1000>;
 		interrupts = <0 37 0>, <0 38 0>, <0 39 0>, <0 40 0>,
@@ -205,7 +205,7 @@
 		ranges;
 	};
 
-	rtc {
+	rtc@130000 {
 		compatible = "samsung,s3c6410-rtc";
 		reg = <0x130000 0x1000>;
 		interrupts = <0 17 0>, <0 16 0>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/exynos5800-peach-pi.dts linux-libre-4.7-gnu/arch/arm/boot/dts/exynos5800-peach-pi.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/exynos5800-peach-pi.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/exynos5800-peach-pi.dts	2016-07-24 15:23:50.000000000 -0400
@@ -157,8 +157,6 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&dp_hpd_gpio>;
 	samsung,color-space = <0>;
-	samsung,dynamic-range = <0>;
-	samsung,ycbcr-coeff = <0>;
 	samsung,color-depth = <1>;
 	samsung,link-rate = <0x0a>;
 	samsung,lane-count = <2>;
@@ -671,6 +669,11 @@
 	status = "okay";
 };
 
+&mfc {
+	samsung,mfc-r = <0x43000000 0x800000>;
+	samsung,mfc-l = <0x51000000 0x800000>;
+};
+
 &mmc_0 {
 	status = "okay";
 	num-slots = <1>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/exynos5.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/exynos5.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/exynos5.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/exynos5.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -31,8 +31,8 @@
 		reg = <0x10000000 0x100>;
 	};
 
-	sromc@12250000 {
-		compatible = "samsung,exynos-srom";
+	memory-controller@12250000 {
+		compatible = "samsung,exynos4210-srom";
 		reg = <0x12250000 0x14>;
 	};
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx25.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/imx25.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx25.dtsi	2016-05-15 19:22:42.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx25.dtsi	2016-07-24 18:19:24.000000000 -0400
@@ -420,6 +420,15 @@
 				interrupts = <41>;
 			};
 
+			scc: crypto@53fac000 {
+				compatible = "fsl,imx25-scc";
+				reg = <0x53fac000 0x4000>;
+				clocks = <&clks 111>;
+				clock-names = "ipg";
+				interrupts = <49>, <50>;
+				interrupt-names = "scm", "smn";
+			};
+
 			esdhc1: esdhc@53fb4000 {
 				compatible = "fsl,imx25-esdhc";
 				reg = <0x53fb4000 0x4000>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx25-pinfunc.h linux-libre-4.7-gnu/arch/arm/boot/dts/imx25-pinfunc.h
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx25-pinfunc.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx25-pinfunc.h	2016-07-24 15:23:50.000000000 -0400
@@ -110,20 +110,20 @@
 #define MX25_PAD_CS4__UART5_CTS			0x054 0x264 0x000 0x13 0x000
 #define MX25_PAD_CS4__GPIO_3_20			0x054 0x264 0x000 0x15 0x000
 
-#define MX25_PAD_CS5__CS5			0x058 0x268 0x000 0x10 0x000
+#define MX25_PAD_CS5__CS5			0x058 0x268 0x000 0x00 0x000
 #define MX25_PAD_CS5__NF_CE2			0x058 0x268 0x000 0x01 0x000
-#define MX25_PAD_CS5__UART5_RTS			0x058 0x268 0x574 0x13 0x000
-#define MX25_PAD_CS5__GPIO_3_21			0x058 0x268 0x000 0x15 0x000
+#define MX25_PAD_CS5__UART5_RTS			0x058 0x268 0x574 0x03 0x000
+#define MX25_PAD_CS5__GPIO_3_21			0x058 0x268 0x000 0x05 0x000
 
 #define MX25_PAD_NF_CE0__NF_CE0			0x05c 0x26c 0x000 0x10 0x000
 #define MX25_PAD_NF_CE0__GPIO_3_22		0x05c 0x26c 0x000 0x15 0x000
 
 #define MX25_PAD_ECB__ECB			0x060 0x270 0x000 0x10 0x000
-#define MX25_PAD_ECB__UART5_TXD_MUX		0x060 0x270 0x000 0x13 0x000
+#define MX25_PAD_ECB__UART5_TXD			0x060 0x270 0x000 0x13 0x000
 #define MX25_PAD_ECB__GPIO_3_23			0x060 0x270 0x000 0x15 0x000
 
 #define MX25_PAD_LBA__LBA			0x064 0x274 0x000 0x10 0x000
-#define MX25_PAD_LBA__UART5_RXD_MUX		0x064 0x274 0x578 0x13 0x000
+#define MX25_PAD_LBA__UART5_RXD			0x064 0x274 0x578 0x13 0x000
 #define MX25_PAD_LBA__GPIO_3_24			0x064 0x274 0x000 0x15 0x000
 
 #define MX25_PAD_BCLK__BCLK			0x068 0x000 0x000 0x00 0x000
@@ -237,17 +237,21 @@
 #define MX25_PAD_LD7__GPIO_1_21			0x0e4 0x2dc 0x000 0x15 0x000
 
 #define MX25_PAD_LD8__LD8			0x0e8 0x2e0 0x000 0x10 0x000
+#define MX25_PAD_LD8__UART4_RXD			0x0e8 0x2e0 0x570 0x12 0x000
 #define MX25_PAD_LD8__FEC_TX_ERR		0x0e8 0x2e0 0x000 0x15 0x000
 #define MX25_PAD_LD8__SDHC2_CMD			0x0e8 0x2e0 0x4e0 0x06 0x000
 
 #define MX25_PAD_LD9__LD9			0x0ec 0x2e4 0x000 0x10 0x000
+#define MX25_PAD_LD9__UART4_TXD			0x0ec 0x2e4 0x000 0x12 0x000
 #define MX25_PAD_LD9__FEC_COL			0x0ec 0x2e4 0x504 0x15 0x001
 #define MX25_PAD_LD9__SDHC2_CLK			0x0ec 0x2e4 0x4dc 0x06 0x000
 
-#define MX25_PAD_LD10__LD10			0x0f0 0x2e8 0x000 0x10 0x000
-#define MX25_PAD_LD10__FEC_RX_ERR		0x0f0 0x2e8 0x518 0x15 0x001
+#define MX25_PAD_LD10__LD10			0x0f0 0x2e8 0x000 0x00 0x000
+#define MX25_PAD_LD10__UART4_RTS		0x0f0 0x2e8 0x56c 0x02 0x000
+#define MX25_PAD_LD10__FEC_RX_ERR		0x0f0 0x2e8 0x518 0x05 0x001
 
 #define MX25_PAD_LD11__LD11			0x0f4 0x2ec 0x000 0x10 0x000
+#define MX25_PAD_LD11__UART4_CTS		0x0f4 0x2ec 0x000 0x12 0x000
 #define MX25_PAD_LD11__FEC_RDATA2		0x0f4 0x2ec 0x50c 0x15 0x001
 #define MX25_PAD_LD11__SDHC2_DAT1		0x0f4 0x2ec 0x4e8 0x06 0x000
 
@@ -291,22 +295,22 @@
 #define MX25_PAD_PWM__USBH2_OC			0x11c 0x314 0x580 0x16 0x001
 
 #define MX25_PAD_CSI_D2__CSI_D2			0x120 0x318 0x000 0x10 0x000
-#define MX25_PAD_CSI_D2__UART5_RXD_MUX		0x120 0x318 0x578 0x11 0x001
+#define MX25_PAD_CSI_D2__UART5_RXD		0x120 0x318 0x578 0x11 0x001
 #define MX25_PAD_CSI_D2__SIM1_CLK0		0x120 0x318 0x000 0x04 0x000
 #define MX25_PAD_CSI_D2__GPIO_1_27		0x120 0x318 0x000 0x15 0x000
 #define MX25_PAD_CSI_D2__CSPI3_MOSI		0x120 0x318 0x000 0x17 0x000
 
 #define MX25_PAD_CSI_D3__CSI_D3			0x124 0x31c 0x000 0x10 0x000
-#define MX25_PAD_CSI_D3__UART5_TXD_MUX		0x124 0x31c 0x000 0x11 0x000
+#define MX25_PAD_CSI_D3__UART5_TXD		0x124 0x31c 0x000 0x11 0x000
 #define MX25_PAD_CSI_D3__SIM1_RST0		0x124 0x31c 0x000 0x04 0x000
 #define MX25_PAD_CSI_D3__GPIO_1_28		0x124 0x31c 0x000 0x15 0x000
 #define MX25_PAD_CSI_D3__CSPI3_MISO		0x124 0x31c 0x4b4 0x17 0x001
 
-#define MX25_PAD_CSI_D4__CSI_D4			0x128 0x320 0x000 0x10 0x000
-#define MX25_PAD_CSI_D4__UART5_RTS		0x128 0x320 0x574 0x11 0x001
+#define MX25_PAD_CSI_D4__CSI_D4			0x128 0x320 0x000 0x00 0x000
+#define MX25_PAD_CSI_D4__UART5_RTS		0x128 0x320 0x574 0x01 0x001
 #define MX25_PAD_CSI_D4__SIM1_VEN0		0x128 0x320 0x000 0x04 0x000
-#define MX25_PAD_CSI_D4__GPIO_1_29		0x128 0x320 0x000 0x15 0x000
-#define MX25_PAD_CSI_D4__CSPI3_SCLK		0x128 0x320 0x000 0x17 0x000
+#define MX25_PAD_CSI_D4__GPIO_1_29		0x128 0x320 0x000 0x05 0x000
+#define MX25_PAD_CSI_D4__CSPI3_SCLK		0x128 0x320 0x000 0x07 0x000
 
 #define MX25_PAD_CSI_D5__CSI_D5			0x12c 0x324 0x000 0x10 0x000
 #define MX25_PAD_CSI_D5__UART5_CTS		0x12c 0x324 0x000 0x11 0x000
@@ -360,7 +364,7 @@
 #define MX25_PAD_I2C1_DAT__GPIO_1_13		0x154 0x34c 0x000 0x15 0x000
 
 #define MX25_PAD_CSPI1_MOSI__CSPI1_MOSI		0x158 0x350 0x000 0x10 0x000
-#define MX25_PAD_CSPI1_MOSI__UART3_RXD		0x158 0x350 0x000 0x12 0x000
+#define MX25_PAD_CSPI1_MOSI__UART3_RXD		0x158 0x350 0x568 0x12 0x000
 #define MX25_PAD_CSPI1_MOSI__GPIO_1_14		0x158 0x350 0x000 0x15 0x000
 
 #define MX25_PAD_CSPI1_MISO__CSPI1_MISO		0x15c 0x354 0x000 0x10 0x000
@@ -371,10 +375,10 @@
 #define MX25_PAD_CSPI1_SS0__PWM2_PWMO		0x160 0x358 0x000 0x12 0x000
 #define MX25_PAD_CSPI1_SS0__GPIO_1_16		0x160 0x358 0x000 0x15 0x000
 
-#define MX25_PAD_CSPI1_SS1__CSPI1_SS1		0x164 0x35c 0x000 0x10 0x000
-#define MX25_PAD_CSPI1_SS1__I2C3_DAT		0x164 0x35C 0x528 0x11 0x001
-#define MX25_PAD_CSPI1_SS1__UART3_RTS		0x164 0x35c 0x000 0x12 0x000
-#define MX25_PAD_CSPI1_SS1__GPIO_1_17		0x164 0x35c 0x000 0x15 0x000
+#define MX25_PAD_CSPI1_SS1__CSPI1_SS1		0x164 0x35c 0x000 0x00 0x000
+#define MX25_PAD_CSPI1_SS1__I2C3_DAT		0x164 0x35C 0x528 0x01 0x001
+#define MX25_PAD_CSPI1_SS1__UART3_RTS		0x164 0x35c 0x000 0x02 0x000
+#define MX25_PAD_CSPI1_SS1__GPIO_1_17		0x164 0x35c 0x000 0x05 0x000
 
 #define MX25_PAD_CSPI1_SCLK__CSPI1_SCLK		0x168 0x360 0x000 0x10 0x000
 #define MX25_PAD_CSPI1_SCLK__UART3_CTS		0x168 0x360 0x000 0x12 0x000
@@ -383,20 +387,24 @@
 #define MX25_PAD_CSPI1_RDY__CSPI1_RDY		0x16c 0x364 0x000 0x10 0x000
 #define MX25_PAD_CSPI1_RDY__GPIO_2_22		0x16c 0x364 0x000 0x15 0x000
 
-#define MX25_PAD_UART1_RXD__UART1_RXD		0x170 0x368 0x000 0x10 0x000
-#define MX25_PAD_UART1_RXD__GPIO_4_22		0x170 0x368 0x000 0x15 0x000
+#define MX25_PAD_UART1_RXD__UART1_RXD		0x170 0x368 0x000 0x00 0x000
+#define MX25_PAD_UART1_RXD__UART2_DTR		0x170 0x368 0x000 0x03 0x000
+#define MX25_PAD_UART1_RXD__GPIO_4_22		0x170 0x368 0x000 0x05 0x000
 
-#define MX25_PAD_UART1_TXD__UART1_TXD		0x174 0x36c 0x000 0x10 0x000
-#define MX25_PAD_UART1_TXD__GPIO_4_23		0x174 0x36c 0x000 0x15 0x000
+#define MX25_PAD_UART1_TXD__UART1_TXD		0x174 0x36c 0x000 0x00 0x000
+#define MX25_PAD_UART1_TXD__UART2_DSR		0x174 0x36c 0x000 0x03 0x000
+#define MX25_PAD_UART1_TXD__GPIO_4_23		0x174 0x36c 0x000 0x05 0x000
 
-#define MX25_PAD_UART1_RTS__UART1_RTS		0x178 0x370 0x000 0x10 0x000
-#define MX25_PAD_UART1_RTS__CSI_D0		0x178 0x370 0x488 0x11 0x001
-#define MX25_PAD_UART1_RTS__CC3			0x178 0x370 0x000 0x12 0x000
-#define MX25_PAD_UART1_RTS__GPIO_4_24		0x178 0x370 0x000 0x15 0x000
+#define MX25_PAD_UART1_RTS__UART1_RTS		0x178 0x370 0x000 0x00 0x000
+#define MX25_PAD_UART1_RTS__CSI_D0		0x178 0x370 0x488 0x01 0x001
+#define MX25_PAD_UART1_RTS__CC3			0x178 0x370 0x000 0x02 0x000
+#define MX25_PAD_UART1_RTS__UART2_DCD		0x178 0x370 0x000 0x03 0x000
+#define MX25_PAD_UART1_RTS__GPIO_4_24		0x178 0x370 0x000 0x05 0x000
 
-#define MX25_PAD_UART1_CTS__UART1_CTS		0x17c 0x374 0x000 0x10 0x000
-#define MX25_PAD_UART1_CTS__CSI_D1		0x17c 0x374 0x48c 0x11 0x001
-#define MX25_PAD_UART1_CTS__GPIO_4_25		0x17c 0x374 0x000 0x15 0x000
+#define MX25_PAD_UART1_CTS__UART1_CTS		0x17c 0x374 0x000 0x00 0x000
+#define MX25_PAD_UART1_CTS__CSI_D1		0x17c 0x374 0x48c 0x01 0x001
+#define MX25_PAD_UART1_CTS__UART2_RI		0x17c 0x374 0x000 0x03 0x001
+#define MX25_PAD_UART1_CTS__GPIO_4_25		0x17c 0x374 0x000 0x05 0x000
 
 #define MX25_PAD_UART2_RXD__UART2_RXD		0x180 0x378 0x000 0x10 0x000
 #define MX25_PAD_UART2_RXD__GPIO_4_26		0x180 0x378 0x000 0x15 0x000
@@ -404,10 +412,10 @@
 #define MX25_PAD_UART2_TXD__UART2_TXD		0x184 0x37c 0x000 0x10 0x000
 #define MX25_PAD_UART2_TXD__GPIO_4_27		0x184 0x37c 0x000 0x15 0x000
 
-#define MX25_PAD_UART2_RTS__UART2_RTS		0x188 0x380 0x000 0x10 0x000
-#define MX25_PAD_UART2_RTS__FEC_COL		0x188 0x380 0x504 0x12 0x002
-#define MX25_PAD_UART2_RTS__CC1			0x188 0x380 0x000 0x13 0x000
-#define MX25_PAD_UART2_RTS__GPIO_4_28		0x188 0x380 0x000 0x15 0x000
+#define MX25_PAD_UART2_RTS__UART2_RTS		0x188 0x380 0x000 0x00 0x000
+#define MX25_PAD_UART2_RTS__FEC_COL		0x188 0x380 0x504 0x02 0x002
+#define MX25_PAD_UART2_RTS__CC1			0x188 0x380 0x000 0x03 0x000
+#define MX25_PAD_UART2_RTS__GPIO_4_28		0x188 0x380 0x000 0x05 0x000
 
 #define MX25_PAD_UART2_CTS__UART2_CTS		0x18c 0x384 0x000 0x10 0x000
 #define MX25_PAD_UART2_CTS__FEC_RX_ERR		0x18c 0x384 0x518 0x12 0x002
@@ -439,36 +447,42 @@
 #define MX25_PAD_SD1_DATA3__FEC_CRS		0x1a4 0x39c 0x508 0x12 0x002
 #define MX25_PAD_SD1_DATA3__GPIO_2_28		0x1a4 0x39c 0x000 0x15 0x000
 
-#define MX25_PAD_KPP_ROW0__KPP_ROW0		0x1a8 0x3a0 0x000 0x10 0x000
-#define MX25_PAD_KPP_ROW0__UART1_DTR		0x1a8 0x3a0 0x000 0x14 0x000
-#define MX25_PAD_KPP_ROW0__GPIO_2_29		0x1a8 0x3a0 0x000 0x15 0x000
+#define MX25_PAD_KPP_ROW0__KPP_ROW0		0x1a8 0x3a0 0x000 0x00 0x000
+#define MX25_PAD_KPP_ROW0__UART3_RXD		0x1a8 0x3a0 0x568 0x01 0x001
+#define MX25_PAD_KPP_ROW0__UART1_DTR		0x1a8 0x3a0 0x000 0x04 0x000
+#define MX25_PAD_KPP_ROW0__GPIO_2_29		0x1a8 0x3a0 0x000 0x05 0x000
 
-#define MX25_PAD_KPP_ROW1__KPP_ROW1		0x1ac 0x3a4 0x000 0x10 0x000
-#define MX25_PAD_KPP_ROW1__GPIO_2_30		0x1ac 0x3a4 0x000 0x15 0x000
+#define MX25_PAD_KPP_ROW1__KPP_ROW1		0x1ac 0x3a4 0x000 0x00 0x000
+#define MX25_PAD_KPP_ROW1__UART3_TXD		0x1ac 0x3a4 0x000 0x01 0x000
+#define MX25_PAD_KPP_ROW1__UART1_DSR		0x1ac 0x3a4 0x000 0x04 0x000
+#define MX25_PAD_KPP_ROW1__GPIO_2_30		0x1ac 0x3a4 0x000 0x05 0x000
 
-#define MX25_PAD_KPP_ROW2__KPP_ROW2		0x1b0 0x3a8 0x000 0x10 0x000
-#define MX25_PAD_KPP_ROW2__CSI_D0		0x1b0 0x3a8 0x488 0x13 0x002
-#define MX25_PAD_KPP_ROW2__UART1_DCD		0x1b0 0x3a8 0x000 0x14 0x000
-#define MX25_PAD_KPP_ROW2__GPIO_2_31		0x1b0 0x3a8 0x000 0x15 0x000
+#define MX25_PAD_KPP_ROW2__KPP_ROW2		0x1b0 0x3a8 0x000 0x00 0x000
+#define MX25_PAD_KPP_ROW2__UART3_RTS		0x1b0 0x3a8 0x000 0x01 0x000
+#define MX25_PAD_KPP_ROW2__CSI_D0		0x1b0 0x3a8 0x488 0x03 0x002
+#define MX25_PAD_KPP_ROW2__UART1_DCD		0x1b0 0x3a8 0x000 0x04 0x000
+#define MX25_PAD_KPP_ROW2__GPIO_2_31		0x1b0 0x3a8 0x000 0x05 0x000
 
-#define MX25_PAD_KPP_ROW3__KPP_ROW3		0x1b4 0x3ac 0x000 0x10 0x000
-#define MX25_PAD_KPP_ROW3__CSI_D1		0x1b4 0x3ac 0x48c 0x13 0x002
-#define MX25_PAD_KPP_ROW3__GPIO_3_0		0x1b4 0x3ac 0x000 0x15 0x000
+#define MX25_PAD_KPP_ROW3__KPP_ROW3		0x1b4 0x3ac 0x000 0x00 0x000
+#define MX25_PAD_KPP_ROW3__UART3_CTS		0x1b4 0x3ac 0x000 0x01 0x000
+#define MX25_PAD_KPP_ROW3__CSI_D1		0x1b4 0x3ac 0x48c 0x03 0x002
+#define MX25_PAD_KPP_ROW3__UART1_RI		0x1b4 0x3ac 0x000 0x04 0x000
+#define MX25_PAD_KPP_ROW3__GPIO_3_0		0x1b4 0x3ac 0x000 0x05 0x000
 
 #define MX25_PAD_KPP_COL0__KPP_COL0		0x1b8 0x3b0 0x000 0x10 0x000
-#define MX25_PAD_KPP_COL0__UART4_RXD_MUX	0x1b8 0x3b0 0x570 0x11 0x001
+#define MX25_PAD_KPP_COL0__UART4_RXD		0x1b8 0x3b0 0x570 0x11 0x001
 #define MX25_PAD_KPP_COL0__AUD5_TXD		0x1b8 0x3b0 0x000 0x12 0x000
 #define MX25_PAD_KPP_COL0__GPIO_3_1		0x1b8 0x3b0 0x000 0x15 0x000
 
 #define MX25_PAD_KPP_COL1__KPP_COL1		0x1bc 0x3b4 0x000 0x10 0x000
-#define MX25_PAD_KPP_COL1__UART4_TXD_MUX	0x1bc 0x3b4 0x000 0x11 0x000
+#define MX25_PAD_KPP_COL1__UART4_TXD		0x1bc 0x3b4 0x000 0x11 0x000
 #define MX25_PAD_KPP_COL1__AUD5_RXD		0x1bc 0x3b4 0x000 0x12 0x000
 #define MX25_PAD_KPP_COL1__GPIO_3_2		0x1bc 0x3b4 0x000 0x15 0x000
 
-#define MX25_PAD_KPP_COL2__KPP_COL2		0x1c0 0x3b8 0x000 0x10 0x000
-#define MX25_PAD_KPP_COL2__UART4_RTS		0x1c0 0x3b8 0x000 0x11 0x000
-#define MX25_PAD_KPP_COL2__AUD5_TXC		0x1c0 0x3b8 0x000 0x12 0x000
-#define MX25_PAD_KPP_COL2__GPIO_3_3		0x1c0 0x3b8 0x000 0x15 0x000
+#define MX25_PAD_KPP_COL2__KPP_COL2		0x1c0 0x3b8 0x000 0x00 0x000
+#define MX25_PAD_KPP_COL2__UART4_RTS		0x1c0 0x3b8 0x56c 0x01 0x001
+#define MX25_PAD_KPP_COL2__AUD5_TXC		0x1c0 0x3b8 0x000 0x02 0x000
+#define MX25_PAD_KPP_COL2__GPIO_3_3		0x1c0 0x3b8 0x000 0x05 0x000
 
 #define MX25_PAD_KPP_COL3__KPP_COL3		0x1c4 0x3bc 0x000 0x10 0x000
 #define MX25_PAD_KPP_COL3__UART4_CTS		0x1c4 0x3bc 0x000 0x11 0x000
@@ -557,9 +571,10 @@
 #define MX25_PAD_UPLL_BYPCLK__UPLL_BYPCLK	0x210 0x000 0x000 0x10 0x000
 #define MX25_PAD_UPLL_BYPCLK__GPIO_3_16		0x210 0x000 0x000 0x15 0x000
 
-#define MX25_PAD_VSTBY_REQ__VSTBY_REQ		0x214 0x408 0x000 0x10 0x000
-#define MX25_PAD_VSTBY_REQ__AUD7_TXFS		0x214 0x408 0x000 0x14 0x000
-#define MX25_PAD_VSTBY_REQ__GPIO_3_17		0x214 0x408 0x000 0x15 0x000
+#define MX25_PAD_VSTBY_REQ__VSTBY_REQ		0x214 0x408 0x000 0x00 0x000
+#define MX25_PAD_VSTBY_REQ__AUD7_TXFS		0x214 0x408 0x000 0x04 0x000
+#define MX25_PAD_VSTBY_REQ__GPIO_3_17		0x214 0x408 0x000 0x05 0x000
+#define MX25_PAD_VSTBY_REQ__UART4_RTS		0x214 0x408 0x56c 0x06 0x002
 
 #define MX25_PAD_VSTBY_ACK__VSTBY_ACK		0x218 0x40c 0x000 0x10 0x000
 #define MX25_PAD_VSTBY_ACK__GPIO_3_18		0x218 0x40c 0x000 0x15 0x000
@@ -567,6 +582,7 @@
 #define MX25_PAD_POWER_FAIL__POWER_FAIL		0x21c 0x410 0x000 0x10 0x000
 #define MX25_PAD_POWER_FAIL__AUD7_RXD		0x21c 0x410 0x478 0x14 0x001
 #define MX25_PAD_POWER_FAIL__GPIO_3_19		0x21c 0x410 0x000 0x15 0x000
+#define MX25_PAD_POWER_FAIL__UART4_CTS		0x21c 0x410 0x000 0x16 0x000
 
 #define MX25_PAD_CLKO__CLKO			0x220 0x414 0x000 0x10 0x000
 #define MX25_PAD_CLKO__GPIO_2_21		0x220 0x414 0x000 0x15 0x000
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx28.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/imx28.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx28.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx28.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -434,6 +434,32 @@
 					fsl,pull-up = <MXS_PULL_ENABLE>;
 				};
 
+				mac0_pins_b: mac0@1 {
+					reg = <1>;
+					fsl,pinmux-ids = <
+						MX28_PAD_ENET0_MDC__ENET0_MDC
+						MX28_PAD_ENET0_MDIO__ENET0_MDIO
+						MX28_PAD_ENET0_RX_EN__ENET0_RX_EN
+						MX28_PAD_ENET0_RXD0__ENET0_RXD0
+						MX28_PAD_ENET0_RXD1__ENET0_RXD1
+						MX28_PAD_ENET0_RXD2__ENET0_RXD2
+						MX28_PAD_ENET0_RXD3__ENET0_RXD3
+						MX28_PAD_ENET0_TX_EN__ENET0_TX_EN
+						MX28_PAD_ENET0_TXD0__ENET0_TXD0
+						MX28_PAD_ENET0_TXD1__ENET0_TXD1
+						MX28_PAD_ENET0_TXD2__ENET0_TXD2
+						MX28_PAD_ENET0_TXD3__ENET0_TXD3
+						MX28_PAD_ENET_CLK__CLKCTRL_ENET
+						MX28_PAD_ENET0_COL__ENET0_COL
+						MX28_PAD_ENET0_CRS__ENET0_CRS
+						MX28_PAD_ENET0_TX_CLK__ENET0_TX_CLK
+						MX28_PAD_ENET0_RX_CLK__ENET0_RX_CLK
+						>;
+					fsl,drive-strength = <MXS_DRIVE_8mA>;
+					fsl,voltage = <MXS_VOLTAGE_HIGH>;
+					fsl,pull-up = <MXS_PULL_ENABLE>;
+				};
+
 				mac1_pins_a: mac1@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx28-m28.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/imx28-m28.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx28-m28.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx28-m28.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -27,32 +27,6 @@
 				pinctrl-names = "default";
 				pinctrl-0 = <&gpmi_pins_a &gpmi_status_cfg>;
 				status = "okay";
-
-				partition@0 {
-					label = "bootloader";
-					reg = <0x00000000 0x00300000>;
-					read-only;
-				};
-
-				partition@1 {
-					label = "environment";
-					reg = <0x00300000 0x00080000>;
-				};
-
-				partition@2 {
-					label = "redundant-environment";
-					reg = <0x00380000 0x00080000>;
-				};
-
-				partition@3 {
-					label = "kernel";
-					reg = <0x00400000 0x00400000>;
-				};
-
-				partition@4 {
-					label = "filesystem";
-					reg = <0x00800000 0x0f800000>;
-				};
 			};
 		};
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx31.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/imx31.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx31.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx31.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -69,6 +69,14 @@
 				status = "disabled";
 			};
 
+			kpp: kpp@43fa8000 {
+				compatible = "fsl,imx31-kpp", "fsl,imx21-kpp";
+				reg = <0x43fa8000 0x4000>;
+				interrupts = <24>;
+				clocks = <&clks 46>;
+				status = "disabled";
+			};
+
 			uart4: serial@43fb0000 {
 				compatible = "fsl,imx31-uart", "fsl,imx21-uart";
 				reg = <0x43fb0000 0x4000>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx35.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/imx35.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx35.dtsi	2016-05-15 19:22:45.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx35.dtsi	2016-07-24 18:19:26.000000000 -0400
@@ -137,6 +137,14 @@
 				status = "disabled";
 			};
 
+			kpp: kpp@43fa8000 {
+				compatible = "fsl,imx35-kpp", "fsl,imx21-kpp";
+				reg = <0x43fa8000 0x4000>;
+				interrupts = <24>;
+				clocks = <&clks 56>;
+				status = "disabled";
+			};
+
 			iomuxc: iomuxc@43fac000 {
 				compatible = "fsl,imx35-iomuxc";
 				reg = <0x43fac000 0x4000>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx53-m53evk.dts linux-libre-4.7-gnu/arch/arm/boot/dts/imx53-m53evk.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx53-m53evk.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx53-m53evk.dts	2016-07-24 15:23:50.000000000 -0400
@@ -84,6 +84,15 @@
 			regulator-max-microvolt = <5000000>;
 			gpio = <&gpio1 2 0>;
 		};
+
+		reg_usb_otg_vbus: regulator@4 {
+			compatible = "regulator-fixed";
+			reg = <4>;
+			regulator-name = "usb_otg_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio1 4 0>;
+		};
 	};
 
 	sound {
@@ -168,6 +177,12 @@
 			>;
 		};
 
+		pinctrl_usbotg: usbotggrp {
+			fsl,pins = <
+				MX53_PAD_GPIO_4__GPIO1_4		0x000b0
+			>;
+		};
+
 		led_pin_gpio: led_gpio@0 {
 			fsl,pins = <
 				MX53_PAD_PATA_DATA8__GPIO2_8		0x80000000
@@ -351,6 +366,10 @@
 };
 
 &usbotg {
-	dr_mode = "peripheral";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	dr_mode = "otg";
+	vbus-supply = <&reg_usb_otg_vbus>;
+	disable-over-current;
 	status = "okay";
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6dl.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/imx6dl.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6dl.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6dl.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -30,7 +30,7 @@
 				/* kHz    uV */
 				996000  1250000
 				792000  1175000
-				396000  1075000
+				396000  1150000
 			>;
 			fsl,soc-operating-points = <
 				/* ARM kHz  SOC-PU uV */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6dl-riotboard.dts linux-libre-4.7-gnu/arch/arm/boot/dts/imx6dl-riotboard.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6dl-riotboard.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6dl-riotboard.dts	2016-07-24 15:23:50.000000000 -0400
@@ -114,7 +114,7 @@
 	codec: sgtl5000@0a {
 		compatible = "fsl,sgtl5000";
 		reg = <0x0a>;
-		clocks = <&clks 201>;
+		clocks = <&clks IMX6QDL_CLK_CKO>;
 		VDDA-supply = <&reg_2p5v>;
 		VDDIO-supply = <&reg_3p3v>;
 	};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6dl-tx6dl-comtft.dts linux-libre-4.7-gnu/arch/arm/boot/dts/imx6dl-tx6dl-comtft.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6dl-tx6dl-comtft.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6dl-tx6dl-comtft.dts	2016-07-24 15:23:50.000000000 -0400
@@ -1,12 +1,42 @@
 /*
- * Copyright 2014 Lothar Waßmann <LW@KARO-electronics.de>
+ * Copyright 2014-2016 Lothar Waßmann <LW@KARO-electronics.de>
  *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 at the following locations:
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
  *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
 /dts-v1/;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6dl-tx6s-8034.dts linux-libre-4.7-gnu/arch/arm/boot/dts/imx6dl-tx6s-8034.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6dl-tx6s-8034.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6dl-tx6s-8034.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,237 @@
+/*
+ * Copyright 2015-2016 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-tx6.dtsi"
+
+/ {
+	model = "Ka-Ro electronics TX6S-8034 Module";
+	compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl";
+
+	aliases {
+		display = &display;
+		ipu1 = &ipu1;
+	};
+
+	cpus {
+		/delete-node/ cpu@1;
+	};
+
+	backlight: backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm2 0 500000 PWM_POLARITY_INVERTED>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_lcd0_pwr>;
+		enable-gpios = <&gpio3 29 GPIO_ACTIVE_HIGH>;
+		power-supply = <&reg_lcd1_pwr>;
+		/*
+		 * a poor man's way to create a 1:1 relationship between
+		 * the PWM value and the actual duty cycle
+		 */
+		brightness-levels = < 0  1  2  3  4  5  6  7  8  9
+				     10 11 12 13 14 15 16 17 18 19
+				     20 21 22 23 24 25 26 27 28 29
+				     30 31 32 33 34 35 36 37 38 39
+				     40 41 42 43 44 45 46 47 48 49
+				     50 51 52 53 54 55 56 57 58 59
+				     60 61 62 63 64 65 66 67 68 69
+				     70 71 72 73 74 75 76 77 78 79
+				     80 81 82 83 84 85 86 87 88 89
+				     90 91 92 93 94 95 96 97 98 99
+				    100>;
+		default-brightness-level = <50>;
+	};
+
+	display: display@di0 {
+		compatible = "fsl,imx-parallel-display";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_disp0_2>;
+		interface-pix-fmt = "rgb24";
+		status = "okay";
+
+		port {
+			display0_in: endpoint {
+				remote-endpoint = <&ipu1_di0_disp0>;
+			};
+		};
+
+		display-timings {
+			native-mode = <&vga>;
+
+			vga: VGA {
+				clock-frequency = <25200000>;
+				hactive = <640>;
+				vactive = <480>;
+				hback-porch = <48>;
+				hsync-len = <96>;
+				hfront-porch = <16>;
+				vback-porch = <31>;
+				vsync-len = <2>;
+				vfront-porch = <12>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			ETV570 {
+				clock-frequency = <25200000>;
+				hactive = <640>;
+				vactive = <480>;
+				hback-porch = <114>;
+				hsync-len = <30>;
+				hfront-porch = <16>;
+				vback-porch = <32>;
+				vsync-len = <3>;
+				vfront-porch = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			ET0350 {
+				clock-frequency = <6413760>;
+				hactive = <320>;
+				vactive = <240>;
+				hback-porch = <34>;
+				hsync-len = <34>;
+				hfront-porch = <20>;
+				vback-porch = <15>;
+				vsync-len = <3>;
+				vfront-porch = <4>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			ET0430 {
+				clock-frequency = <9009000>;
+				hactive = <480>;
+				vactive = <272>;
+				hback-porch = <2>;
+				hsync-len = <41>;
+				hfront-porch = <2>;
+				vback-porch = <2>;
+				vsync-len = <10>;
+				vfront-porch = <2>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <1>;
+			};
+
+			ET0500 {
+				clock-frequency = <33264000>;
+				hactive = <800>;
+				vactive = <480>;
+				hback-porch = <88>;
+				hsync-len = <128>;
+				hfront-porch = <40>;
+				vback-porch = <33>;
+				vsync-len = <2>;
+				vfront-porch = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			ET0700 { /* same as ET0500 */
+				clock-frequency = <33264000>;
+				hactive = <800>;
+				vactive = <480>;
+				hback-porch = <88>;
+				hsync-len = <128>;
+				hfront-porch = <40>;
+				vback-porch = <33>;
+				vsync-len = <2>;
+				vfront-porch = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			ETQ570 {
+				clock-frequency = <6596040>;
+				hactive = <320>;
+				vactive = <240>;
+				hback-porch = <38>;
+				hsync-len = <30>;
+				hfront-porch = <30>;
+				vback-porch = <16>;
+				vsync-len = <3>;
+				vfront-porch = <4>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+		};
+	};
+};
+
+&ds1339 {
+	status = "disabled";
+};
+
+&pinctrl_usdhc1 {
+	fsl,pins = <
+		MX6QDL_PAD_SD1_CMD__SD1_CMD		0x070b1
+		MX6QDL_PAD_SD1_CLK__SD1_CLK		0x070b1
+		MX6QDL_PAD_SD1_DAT0__SD1_DATA0		0x070b1
+		MX6QDL_PAD_SD1_DAT1__SD1_DATA1		0x070b1
+		MX6QDL_PAD_SD1_DAT2__SD1_DATA2		0x070b1
+		MX6QDL_PAD_SD1_DAT3__SD1_DATA3		0x070b1
+		MX6QDL_PAD_SD3_CMD__GPIO7_IO02		0x170b0 /* SD1 CD */
+	>;
+};
+
+&ipu1_di0_disp0 {
+	remote-endpoint = <&display0_in>;
+};
+
+&reg_lcd0_pwr {
+	status = "disabled";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6dl-tx6s-8035.dts linux-libre-4.7-gnu/arch/arm/boot/dts/imx6dl-tx6s-8035.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6dl-tx6s-8035.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6dl-tx6s-8035.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,253 @@
+/*
+ * Copyright 2015-2016 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-tx6.dtsi"
+
+/ {
+	model = "Ka-Ro electronics TX6S-8035 Module";
+	compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl";
+
+	aliases {
+		display = &display;
+		ipu1 = &ipu1;
+	};
+
+	cpus {
+		/delete-node/ cpu@1;
+	};
+
+	backlight: backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm2 0 500000 PWM_POLARITY_INVERTED>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_lcd0_pwr>;
+		enable-gpios = <&gpio3 29 GPIO_ACTIVE_HIGH>;
+		power-supply = <&reg_lcd1_pwr>;
+		/*
+		 * a poor man's way to create a 1:1 relationship between
+		 * the PWM value and the actual duty cycle
+		 */
+		brightness-levels = < 0  1  2  3  4  5  6  7  8  9
+				     10 11 12 13 14 15 16 17 18 19
+				     20 21 22 23 24 25 26 27 28 29
+				     30 31 32 33 34 35 36 37 38 39
+				     40 41 42 43 44 45 46 47 48 49
+				     50 51 52 53 54 55 56 57 58 59
+				     60 61 62 63 64 65 66 67 68 69
+				     70 71 72 73 74 75 76 77 78 79
+				     80 81 82 83 84 85 86 87 88 89
+				     90 91 92 93 94 95 96 97 98 99
+				    100>;
+		default-brightness-level = <50>;
+	};
+
+	display: display@di0 {
+		compatible = "fsl,imx-parallel-display";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_disp0_2>;
+		interface-pix-fmt = "rgb24";
+		status = "okay";
+
+		port {
+			display0_in: endpoint {
+				remote-endpoint = <&ipu1_di0_disp0>;
+			};
+		};
+
+		display-timings {
+			native-mode = <&vga>;
+
+			vga: VGA {
+				clock-frequency = <25200000>;
+				hactive = <640>;
+				vactive = <480>;
+				hback-porch = <48>;
+				hsync-len = <96>;
+				hfront-porch = <16>;
+				vback-porch = <31>;
+				vsync-len = <2>;
+				vfront-porch = <12>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			ETV570 {
+				clock-frequency = <25200000>;
+				hactive = <640>;
+				vactive = <480>;
+				hback-porch = <114>;
+				hsync-len = <30>;
+				hfront-porch = <16>;
+				vback-porch = <32>;
+				vsync-len = <3>;
+				vfront-porch = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			ET0350 {
+				clock-frequency = <6413760>;
+				hactive = <320>;
+				vactive = <240>;
+				hback-porch = <34>;
+				hsync-len = <34>;
+				hfront-porch = <20>;
+				vback-porch = <15>;
+				vsync-len = <3>;
+				vfront-porch = <4>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			ET0430 {
+				clock-frequency = <9009000>;
+				hactive = <480>;
+				vactive = <272>;
+				hback-porch = <2>;
+				hsync-len = <41>;
+				hfront-porch = <2>;
+				vback-porch = <2>;
+				vsync-len = <10>;
+				vfront-porch = <2>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <1>;
+			};
+
+			ET0500 {
+				clock-frequency = <33264000>;
+				hactive = <800>;
+				vactive = <480>;
+				hback-porch = <88>;
+				hsync-len = <128>;
+				hfront-porch = <40>;
+				vback-porch = <33>;
+				vsync-len = <2>;
+				vfront-porch = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			ET0700 { /* same as ET0500 */
+				clock-frequency = <33264000>;
+				hactive = <800>;
+				vactive = <480>;
+				hback-porch = <88>;
+				hsync-len = <128>;
+				hfront-porch = <40>;
+				vback-porch = <33>;
+				vsync-len = <2>;
+				vfront-porch = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			ETQ570 {
+				clock-frequency = <6596040>;
+				hactive = <320>;
+				vactive = <240>;
+				hback-porch = <38>;
+				hsync-len = <30>;
+				hfront-porch = <30>;
+				vback-porch = <16>;
+				vsync-len = <3>;
+				vfront-porch = <4>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+		};
+	};
+};
+
+&ds1339 {
+	status = "disabled";
+};
+
+&gpmi {
+	status = "disabled";
+};
+
+&ipu1_di0_disp0 {
+	remote-endpoint = <&display0_in>;
+};
+
+&reg_lcd0_pwr {
+	status = "disabled";
+};
+
+&usdhc4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc4>;
+	bus-width = <4>;
+	non-removable;
+	no-1-8-v;
+	fsl,wp-controller;
+	status = "okay";
+};
+
+&iomuxc {
+	pinctrl_usdhc4: usdhc4grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD4_CMD__SD4_CMD		0x070b1
+			MX6QDL_PAD_SD4_CLK__SD4_CLK		0x070b1
+			MX6QDL_PAD_SD4_DAT0__SD4_DATA0		0x070b1
+			MX6QDL_PAD_SD4_DAT1__SD4_DATA1		0x070b1
+			MX6QDL_PAD_SD4_DAT2__SD4_DATA2		0x070b1
+			MX6QDL_PAD_SD4_DAT3__SD4_DATA3		0x070b1
+			MX6QDL_PAD_NANDF_ALE__SD4_RESET		0x0b0b1
+		>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6dl-tx6u-801x.dts linux-libre-4.7-gnu/arch/arm/boot/dts/imx6dl-tx6u-801x.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6dl-tx6u-801x.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6dl-tx6u-801x.dts	2016-07-24 15:23:50.000000000 -0400
@@ -1,12 +1,42 @@
 /*
- * Copyright 2014 Lothar Waßmann <LW@KARO-electronics.de>
+ * Copyright 2014-2016 Lothar Waßmann <LW@KARO-electronics.de>
  *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 at the following locations:
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
  *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
 /dts-v1/;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6dl-tx6u-8033.dts linux-libre-4.7-gnu/arch/arm/boot/dts/imx6dl-tx6u-8033.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6dl-tx6u-8033.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6dl-tx6u-8033.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,248 @@
+/*
+ * Copyright 2014-2016 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-tx6.dtsi"
+
+/ {
+	model = "Ka-Ro electronics TX6U-8033 Module";
+	compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl";
+
+	aliases {
+		display = &display;
+	};
+
+	backlight: backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm2 0 500000 PWM_POLARITY_INVERTED>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_lcd0_pwr>;
+		enable-gpios = <&gpio3 29 GPIO_ACTIVE_HIGH>;
+		power-supply = <&reg_lcd1_pwr>;
+		/*
+		 * a poor man's way to create a 1:1 relationship between
+		 * the PWM value and the actual duty cycle
+		 */
+		brightness-levels = < 0  1  2  3  4  5  6  7  8  9
+				     10 11 12 13 14 15 16 17 18 19
+				     20 21 22 23 24 25 26 27 28 29
+				     30 31 32 33 34 35 36 37 38 39
+				     40 41 42 43 44 45 46 47 48 49
+				     50 51 52 53 54 55 56 57 58 59
+				     60 61 62 63 64 65 66 67 68 69
+				     70 71 72 73 74 75 76 77 78 79
+				     80 81 82 83 84 85 86 87 88 89
+				     90 91 92 93 94 95 96 97 98 99
+				    100>;
+		default-brightness-level = <50>;
+	};
+
+	display: display@di0 {
+		compatible = "fsl,imx-parallel-display";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_disp0_2>;
+		interface-pix-fmt = "rgb24";
+		status = "okay";
+
+		port {
+			display0_in: endpoint {
+				remote-endpoint = <&ipu1_di0_disp0>;
+			};
+		};
+
+		display-timings {
+			native-mode = <&vga>;
+
+			vga: VGA {
+				clock-frequency = <25200000>;
+				hactive = <640>;
+				vactive = <480>;
+				hback-porch = <48>;
+				hsync-len = <96>;
+				hfront-porch = <16>;
+				vback-porch = <31>;
+				vsync-len = <2>;
+				vfront-porch = <12>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			ETV570 {
+				clock-frequency = <25200000>;
+				hactive = <640>;
+				vactive = <480>;
+				hback-porch = <114>;
+				hsync-len = <30>;
+				hfront-porch = <16>;
+				vback-porch = <32>;
+				vsync-len = <3>;
+				vfront-porch = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			ET0350 {
+				clock-frequency = <6413760>;
+				hactive = <320>;
+				vactive = <240>;
+				hback-porch = <34>;
+				hsync-len = <34>;
+				hfront-porch = <20>;
+				vback-porch = <15>;
+				vsync-len = <3>;
+				vfront-porch = <4>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			ET0430 {
+				clock-frequency = <9009000>;
+				hactive = <480>;
+				vactive = <272>;
+				hback-porch = <2>;
+				hsync-len = <41>;
+				hfront-porch = <2>;
+				vback-porch = <2>;
+				vsync-len = <10>;
+				vfront-porch = <2>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <1>;
+			};
+
+			ET0500 {
+				clock-frequency = <33264000>;
+				hactive = <800>;
+				vactive = <480>;
+				hback-porch = <88>;
+				hsync-len = <128>;
+				hfront-porch = <40>;
+				vback-porch = <33>;
+				vsync-len = <2>;
+				vfront-porch = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			ET0700 { /* same as ET0500 */
+				clock-frequency = <33264000>;
+				hactive = <800>;
+				vactive = <480>;
+				hback-porch = <88>;
+				hsync-len = <128>;
+				hfront-porch = <40>;
+				vback-porch = <33>;
+				vsync-len = <2>;
+				vfront-porch = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			ETQ570 {
+				clock-frequency = <6596040>;
+				hactive = <320>;
+				vactive = <240>;
+				hback-porch = <38>;
+				hsync-len = <30>;
+				hfront-porch = <30>;
+				vback-porch = <16>;
+				vsync-len = <3>;
+				vfront-porch = <4>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+		};
+	};
+};
+
+&ds1339 {
+	status = "disabled";
+};
+
+&gpmi {
+	status = "disabled";
+};
+
+&ipu1_di0_disp0 {
+	remote-endpoint = <&display0_in>;
+};
+
+&reg_lcd0_pwr {
+	status = "disabled";
+};
+
+&usdhc4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc4>;
+	bus-width = <4>;
+	non-removable;
+	no-1-8-v;
+	fsl,wp-controller;
+	status = "okay";
+};
+
+&iomuxc {
+	pinctrl_usdhc4: usdhc4grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD4_CMD__SD4_CMD		0x070b1
+			MX6QDL_PAD_SD4_CLK__SD4_CLK		0x070b1
+			MX6QDL_PAD_SD4_DAT0__SD4_DATA0		0x070b1
+			MX6QDL_PAD_SD4_DAT1__SD4_DATA1		0x070b1
+			MX6QDL_PAD_SD4_DAT2__SD4_DATA2		0x070b1
+			MX6QDL_PAD_SD4_DAT3__SD4_DATA3		0x070b1
+			MX6QDL_PAD_NANDF_ALE__SD4_RESET		0x0b0b1
+		>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6dl-tx6u-811x.dts linux-libre-4.7-gnu/arch/arm/boot/dts/imx6dl-tx6u-811x.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6dl-tx6u-811x.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6dl-tx6u-811x.dts	2016-07-24 15:23:50.000000000 -0400
@@ -1,12 +1,42 @@
 /*
- * Copyright 2014 Lothar Waßmann <LW@KARO-electronics.de>
+ * Copyright 2014-2016 Lothar Waßmann <LW@KARO-electronics.de>
  *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 at the following locations:
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
  *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
 /dts-v1/;
@@ -81,16 +111,6 @@
 	};
 };
 
-&iomuxc {
-	imx6dl-tx6u-811x {
-		pinctrl_eeti: eetigrp {
-			fsl,pins = <
-				MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x1b0b1 /* Interrupt */
-			>;
-		};
-	};
-};
-
 &kpp {
 	status = "disabled"; /* pad conflict with backlight1 PWM */
 };
@@ -148,3 +168,11 @@
 &pwm1 {
 	status = "okay";
 };
+
+&iomuxc {
+	pinctrl_eeti: eetigrp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x1b0b1 /* Interrupt */
+		>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6dl-tx6u-81xx-mb7.dts linux-libre-4.7-gnu/arch/arm/boot/dts/imx6dl-tx6u-81xx-mb7.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6dl-tx6u-81xx-mb7.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6dl-tx6u-81xx-mb7.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,255 @@
+/*
+ * Copyright 2016 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-tx6.dtsi"
+
+/ {
+	model = "Ka-Ro electronics TX6U-81xx Module on MB7 baseboard";
+	compatible = "karo,imx6dl-tx6dl", "fsl,imx6dl";
+
+	aliases {
+		display = &lvds0;
+		lvds0 = &lvds0;
+		lvds1 = &lvds1;
+	};
+
+	backlight0: backlight0 {
+		compatible = "pwm-backlight";
+		pwms = <&pwm2 0 500000 PWM_POLARITY_INVERTED>;
+		power-supply = <&reg_lcd0_pwr>;
+		/*
+		 * a poor man's way to create a 1:1 relationship between
+		 * the PWM value and the actual duty cycle
+		 */
+		brightness-levels = < 0  1  2  3  4  5  6  7  8  9
+				     10 11 12 13 14 15 16 17 18 19
+				     20 21 22 23 24 25 26 27 28 29
+				     30 31 32 33 34 35 36 37 38 39
+				     40 41 42 43 44 45 46 47 48 49
+				     50 51 52 53 54 55 56 57 58 59
+				     60 61 62 63 64 65 66 67 68 69
+				     70 71 72 73 74 75 76 77 78 79
+				     80 81 82 83 84 85 86 87 88 89
+				     90 91 92 93 94 95 96 97 98 99
+				    100>;
+		default-brightness-level = <50>;
+	};
+
+	backlight1: backlight1 {
+		compatible = "pwm-backlight";
+		pwms = <&pwm1 0 500000 PWM_POLARITY_INVERTED>;
+		power-supply = <&reg_lcd1_pwr>;
+		/*
+		 * a poor man's way to create a 1:1 relationship between
+		 * the PWM value and the actual duty cycle
+		 */
+		brightness-levels = < 0  1  2  3  4  5  6  7  8  9
+				     10 11 12 13 14 15 16 17 18 19
+				     20 21 22 23 24 25 26 27 28 29
+				     30 31 32 33 34 35 36 37 38 39
+				     40 41 42 43 44 45 46 47 48 49
+				     50 51 52 53 54 55 56 57 58 59
+				     60 61 62 63 64 65 66 67 68 69
+				     70 71 72 73 74 75 76 77 78 79
+				     80 81 82 83 84 85 86 87 88 89
+				     90 91 92 93 94 95 96 97 98 99
+				    100>;
+		default-brightness-level = <50>;
+	};
+};
+
+&can1 {
+	status = "disabled";
+};
+
+&can2 {
+	xceiver-supply = <&reg_3v3>;
+};
+
+&i2c3 {
+	polytouch1: eeti@04 {
+		compatible = "eeti,egalax_ts";
+		reg = <0x04>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_eeti>;
+		interrupts-extended = <&gpio3 22 IRQ_TYPE_EDGE_FALLING>;
+		wakeup-gpios = <&gpio3 22 GPIO_ACTIVE_HIGH>;
+		wakeup-source;
+	};
+};
+
+&kpp {
+	status = "disabled"; /* pads partially clash with backlight1 PWM */
+};
+
+&ldb {
+	status = "okay";
+
+	lvds0: lvds-channel@0 {
+		fsl,data-mapping = "spwg";
+		fsl,data-width = <18>;
+		status = "okay";
+
+		display-timings {
+			native-mode = <&lvds0_timing1>;
+
+			lvds0_timing0: hsd100pxn1 {
+				clock-frequency = <65000000>;
+				hactive = <1024>;
+				vactive = <768>;
+				hback-porch = <220>;
+				hfront-porch = <40>;
+				vback-porch = <21>;
+				vfront-porch = <7>;
+				hsync-len = <60>;
+				vsync-len = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <1>;
+			};
+
+			lvds0_timing1: VGA {
+				clock-frequency = <25200000>;
+				hactive = <640>;
+				vactive = <480>;
+				hback-porch = <48>;
+				hfront-porch = <16>;
+				vback-porch = <31>;
+				vfront-porch = <12>;
+				hsync-len = <96>;
+				vsync-len = <2>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			lvds0_timing2: nl12880bc20 {
+				clock-frequency = <71000000>;
+				hactive = <1280>;
+				vactive = <800>;
+				hback-porch = <50>;
+				hfront-porch = <50>;
+				vback-porch = <5>;
+				vfront-porch = <5>;
+				hsync-len = <60>;
+				vsync-len = <13>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <1>;
+			};
+		};
+	};
+
+	lvds1: lvds-channel@1 {
+		fsl,data-mapping = "spwg";
+		fsl,data-width = <18>;
+		status = "okay";
+
+		display-timings {
+			native-mode = <&lvds1_timing2>;
+
+			lvds1_timing0: hsd100pxn1 {
+				clock-frequency = <65000000>;
+				hactive = <1024>;
+				vactive = <768>;
+				hback-porch = <220>;
+				hfront-porch = <40>;
+				vback-porch = <21>;
+				vfront-porch = <7>;
+				hsync-len = <60>;
+				vsync-len = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <1>;
+			};
+
+			lvds1_timing1: VGA {
+				clock-frequency = <25200000>;
+				hactive = <640>;
+				vactive = <480>;
+				hback-porch = <48>;
+				hfront-porch = <16>;
+				vback-porch = <31>;
+				vfront-porch = <12>;
+				hsync-len = <96>;
+				vsync-len = <2>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			lvds1_timing2: nl12880bc20 {
+				clock-frequency = <71000000>;
+				hactive = <1280>;
+				vactive = <800>;
+				hback-porch = <50>;
+				hfront-porch = <50>;
+				vback-porch = <5>;
+				vfront-porch = <5>;
+				hsync-len = <60>;
+				vsync-len = <13>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <1>;
+			};
+		};
+	};
+};
+
+&pwm1 {
+	status = "okay";
+};
+
+&iomuxc {
+	pinctrl_eeti: eetigrp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x1b0b1 /* Interrupt */
+		>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6q-apalis-ixora.dts linux-libre-4.7-gnu/arch/arm/boot/dts/imx6q-apalis-ixora.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6q-apalis-ixora.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6q-apalis-ixora.dts	2016-07-24 15:23:50.000000000 -0400
@@ -80,6 +80,47 @@
 		};
 	};
 
+	lcd_display: display@di0 {
+		compatible = "fsl,imx-parallel-display";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		interface-pix-fmt = "rgb24";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_ipu1_lcdif>;
+		status = "okay";
+
+		port@0 {
+			reg = <0>;
+
+			lcd_display_in: endpoint {
+				remote-endpoint = <&ipu1_di0_disp1>;
+			};
+		};
+
+		port@1 {
+			reg = <1>;
+
+			lcd_display_out: endpoint {
+				remote-endpoint = <&lcd_panel_in>;
+			};
+		};
+	};
+
+	panel: panel {
+		/*
+		 * edt,et057090dhu: EDT 5.7" LCD TFT
+		 * edt,et070080dh6: EDT 7.0" LCD TFT
+		 */
+		compatible = "edt,et057090dhu";
+		backlight = <&backlight>;
+
+		port {
+			lcd_panel_in: endpoint {
+				remote-endpoint = <&lcd_display_out>;
+			};
+		};
+	};
+
 	leds {
 		compatible = "gpio-leds";
 
@@ -169,13 +210,18 @@
 	};
 };
 
+&ipu1_di0_disp1 {
+	remote-endpoint = <&lcd_display_in>;
+};
+
 &ldb {
 	status = "okay";
 };
 
 &pcie {
-	/* active-low meaning opposite of regular PERST# active-low polarity */
-	reset-gpio = <&gpio1 28 GPIO_ACTIVE_LOW>;
+	/* active-high meaning opposite of regular PERST# active-low polarity */
+	reset-gpio = <&gpio1 28 GPIO_ACTIVE_HIGH>;
+	reset-gpio-active-high;
 	status = "okay";
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6q-b450v3.dts linux-libre-4.7-gnu/arch/arm/boot/dts/imx6q-b450v3.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6q-b450v3.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6q-b450v3.dts	2016-07-24 15:23:50.000000000 -0400
@@ -65,11 +65,14 @@
 	};
 };
 
-&ldb {
+&clks {
 	assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>,
 			  <&clks IMX6QDL_CLK_LDB_DI1_SEL>;
 	assigned-clock-parents = <&clks IMX6QDL_CLK_PLL3_USB_OTG>,
 				 <&clks IMX6QDL_CLK_PLL3_USB_OTG>;
+};
+
+&ldb {
 	status = "okay";
 
 	lvds0: lvds-channel@0 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6q-b650v3.dts linux-libre-4.7-gnu/arch/arm/boot/dts/imx6q-b650v3.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6q-b650v3.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6q-b650v3.dts	2016-07-24 15:23:50.000000000 -0400
@@ -65,11 +65,14 @@
 	};
 };
 
-&ldb {
+&clks {
 	assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>,
 			  <&clks IMX6QDL_CLK_LDB_DI1_SEL>;
 	assigned-clock-parents = <&clks IMX6QDL_CLK_PLL3_USB_OTG>,
 				 <&clks IMX6QDL_CLK_PLL3_USB_OTG>;
+};
+
+&ldb {
 	status = "okay";
 
 	lvds0: lvds-channel@0 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6q-b850v3.dts linux-libre-4.7-gnu/arch/arm/boot/dts/imx6q-b850v3.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6q-b850v3.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6q-b850v3.dts	2016-07-24 15:23:50.000000000 -0400
@@ -51,25 +51,20 @@
 	chosen {
 		stdout-path = &uart3;
 	};
+};
 
-	panel-lvds0 {
-		compatible = "auo,b133htn01";
-		backlight = <&backlight_lvds>;
-		ddc-i2c-bus = <&mux2_i2c2>;
-
-		port {
-			panel_in_lvds0: endpoint {
-				remote-endpoint = <&lvds0_out>;
-			};
-		};
-	};
+&clks {
+	assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>,
+			  <&clks IMX6QDL_CLK_LDB_DI1_SEL>,
+			  <&clks IMX6QDL_CLK_IPU1_DI0_PRE_SEL>,
+			  <&clks IMX6QDL_CLK_IPU1_DI1_PRE_SEL>;
+	assigned-clock-parents = <&clks IMX6QDL_CLK_PLL5_VIDEO_DIV>,
+				 <&clks IMX6QDL_CLK_PLL5_VIDEO_DIV>,
+				 <&clks IMX6QDL_CLK_PLL2_PFD2_396M>,
+				 <&clks IMX6QDL_CLK_PLL2_PFD2_396M>;
 };
 
 &ldb {
-	assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>,
-			  <&clks IMX6QDL_CLK_LDB_DI1_SEL>;
-	assigned-clock-parents = <&clks IMX6QDL_CLK_PLL3_USB_OTG>,
-				 <&clks IMX6QDL_CLK_PLL3_USB_OTG>;
 	fsl,dual-channel;
 	status = "okay";
 
@@ -77,14 +72,6 @@
 		fsl,data-mapping = "spwg";
 		fsl,data-width = <24>;
 		status = "okay";
-
-		port@4 {
-			reg = <4>;
-
-			lvds0_out: endpoint {
-				remote-endpoint = <&panel_in_lvds0>;
-			};
-		};
 	};
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6q-ba16.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/imx6q-ba16.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6q-ba16.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6q-ba16.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -323,6 +323,8 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_pcie>;
 	reset-gpio = <&gpio7 12 GPIO_ACTIVE_HIGH>;
+	fsl,tx-swing-full = <103>;
+	fsl,tx-swing-low = <103>;
 	status = "okay";
 };
 
@@ -335,7 +337,7 @@
 &pwm2 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_pwm2>;
-	status = "okay";
+	status = "disabled";
 };
 
 &sata {
@@ -390,7 +392,6 @@
 	pinctrl-0 = <&pinctrl_usdhc3 &pinctrl_usdhc3_reset>;
 	bus-width = <8>;
 	vmmc-supply = <&vdd_bperi>;
-	vqmmc-supply = <&vdd_bio>;
 	non-removable;
 	keep-power-in-suspend;
 	status = "okay";
@@ -399,6 +400,7 @@
 &wdog1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_wdog>;
+	fsl,ext-reset-output;
 };
 
 &iomuxc {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6qdl-apalis.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/imx6qdl-apalis.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6qdl-apalis.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6qdl-apalis.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -324,7 +324,7 @@
 	codec: sgtl5000@0a {
 		compatible = "fsl,sgtl5000";
 		reg = <0x0a>;
-		clocks = <&clks 201>;
+		clocks = <&clks IMX6QDL_CLK_CKO>;
 		VDDA-supply = <&reg_2p5v>;
 		VDDIO-supply = <&reg_3p3v>;
 	};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6qdl-apf6dev.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/imx6qdl-apf6dev.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6qdl-apf6dev.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6qdl-apf6dev.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -213,7 +213,7 @@
 	codec: sgtl5000@0a {
 		compatible = "fsl,sgtl5000";
 		reg = <0x0a>;
-		clocks = <&clks 201>;
+		clocks = <&clks IMX6QDL_CLK_CKO>;
 		VDDA-supply = <&reg_3p3v>;
 		VDDIO-supply = <&reg_3p3v>;
 	};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6qdl.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/imx6qdl.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6qdl.dtsi	2016-05-15 19:22:59.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6qdl.dtsi	2016-07-24 18:19:43.000000000 -0400
@@ -621,7 +621,7 @@
 					     <0 54 IRQ_TYPE_LEVEL_HIGH>,
 					     <0 127 IRQ_TYPE_LEVEL_HIGH>;
 
-				regulator-1p1@110 {
+				regulator-1p1 {
 					compatible = "fsl,anatop-regulator";
 					regulator-name = "vdd1p1";
 					regulator-min-microvolt = <800000>;
@@ -635,7 +635,7 @@
 					anatop-max-voltage = <1375000>;
 				};
 
-				regulator-3p0@120 {
+				regulator-3p0 {
 					compatible = "fsl,anatop-regulator";
 					regulator-name = "vdd3p0";
 					regulator-min-microvolt = <2800000>;
@@ -649,7 +649,7 @@
 					anatop-max-voltage = <3400000>;
 				};
 
-				regulator-2p5@130 {
+				regulator-2p5 {
 					compatible = "fsl,anatop-regulator";
 					regulator-name = "vdd2p5";
 					regulator-min-microvolt = <2000000>;
@@ -663,7 +663,7 @@
 					anatop-max-voltage = <2750000>;
 				};
 
-				reg_arm: regulator-vddcore@140 {
+				reg_arm: regulator-vddcore {
 					compatible = "fsl,anatop-regulator";
 					regulator-name = "vddarm";
 					regulator-min-microvolt = <725000>;
@@ -680,7 +680,7 @@
 					anatop-max-voltage = <1450000>;
 				};
 
-				reg_pu: regulator-vddpu@140 {
+				reg_pu: regulator-vddpu {
 					compatible = "fsl,anatop-regulator";
 					regulator-name = "vddpu";
 					regulator-min-microvolt = <725000>;
@@ -697,7 +697,7 @@
 					anatop-max-voltage = <1450000>;
 				};
 
-				reg_soc: regulator-vddsoc@140 {
+				reg_soc: regulator-vddsoc {
 					compatible = "fsl,anatop-regulator";
 					regulator-name = "vddsoc";
 					regulator-min-microvolt = <725000>;
@@ -1230,22 +1230,22 @@
 				#size-cells = <0>;
 				reg = <2>;
 
-				ipu1_di0_disp0: endpoint@0 {
+				ipu1_di0_disp0: disp0-endpoint {
 				};
 
-				ipu1_di0_hdmi: endpoint@1 {
+				ipu1_di0_hdmi: hdmi-endpoint {
 					remote-endpoint = <&hdmi_mux_0>;
 				};
 
-				ipu1_di0_mipi: endpoint@2 {
+				ipu1_di0_mipi: mipi-endpoint {
 					remote-endpoint = <&mipi_mux_0>;
 				};
 
-				ipu1_di0_lvds0: endpoint@3 {
+				ipu1_di0_lvds0: lvds0-endpoint {
 					remote-endpoint = <&lvds0_mux_0>;
 				};
 
-				ipu1_di0_lvds1: endpoint@4 {
+				ipu1_di0_lvds1: lvds1-endpoint {
 					remote-endpoint = <&lvds1_mux_0>;
 				};
 			};
@@ -1255,22 +1255,22 @@
 				#size-cells = <0>;
 				reg = <3>;
 
-				ipu1_di0_disp1: endpoint@0 {
+				ipu1_di0_disp1: disp1-endpoint {
 				};
 
-				ipu1_di1_hdmi: endpoint@1 {
+				ipu1_di1_hdmi: hdmi-endpoint {
 					remote-endpoint = <&hdmi_mux_1>;
 				};
 
-				ipu1_di1_mipi: endpoint@2 {
+				ipu1_di1_mipi: mipi-endpoint {
 					remote-endpoint = <&mipi_mux_1>;
 				};
 
-				ipu1_di1_lvds0: endpoint@3 {
+				ipu1_di1_lvds0: lvds0-endpoint {
 					remote-endpoint = <&lvds0_mux_1>;
 				};
 
-				ipu1_di1_lvds1: endpoint@4 {
+				ipu1_di1_lvds1: lvds1-endpoint {
 					remote-endpoint = <&lvds1_mux_1>;
 				};
 			};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -244,7 +244,7 @@
 	codec: sgtl5000@0a {
 		compatible = "fsl,sgtl5000";
 		reg = <0x0a>;
-		clocks = <&clks 201>;
+		clocks = <&clks IMX6QDL_CLK_CKO>;
 		VDDA-supply = <&reg_1p8v>;
 		VDDIO-supply = <&reg_3p3v>;
 	};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -237,7 +237,7 @@
 	codec: sgtl5000@0a {
 		compatible = "fsl,sgtl5000";
 		reg = <0x0a>;
-		clocks = <&clks 201>;
+		clocks = <&clks IMX6QDL_CLK_CKO>;
 		VDDA-supply = <&reg_1p8v>;
 		VDDIO-supply = <&reg_3p3v>;
 	};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -328,7 +328,7 @@
 	codec: sgtl5000@0a {
 		compatible = "fsl,sgtl5000";
 		reg = <0x0a>;
-		clocks = <&clks 201>;
+		clocks = <&clks IMX6QDL_CLK_CKO>;
 		VDDA-supply = <&sw4_reg>;
 		VDDIO-supply = <&reg_3p3v>;
 	};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -269,7 +269,7 @@
 		pinctrl-names = "default";
 		pinctrl-0 = <&pinctrl_sgtl5000>;
 		reg = <0x0a>;
-		clocks = <&clks 201>;
+		clocks = <&clks IMX6QDL_CLK_CKO>;
 		VDDA-supply = <&reg_2p5v>;
 		VDDIO-supply = <&reg_3p3v>;
 	};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -402,7 +402,7 @@
 	codec: sgtl5000@0a {
 		compatible = "fsl,sgtl5000";
 		reg = <0x0a>;
-		clocks = <&clks 201>;
+		clocks = <&clks IMX6QDL_CLK_CKO>;
 		VDDA-supply = <&reg_2p5v>;
 		VDDIO-supply = <&reg_3p3v>;
 	};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -304,7 +304,7 @@
 	codec: sgtl5000@0a {
 		compatible = "fsl,sgtl5000";
 		reg = <0x0a>;
-		clocks = <&clks 201>;
+		clocks = <&clks IMX6QDL_CLK_CKO>;
 		VDDA-supply = <&reg_2p5v>;
 		VDDIO-supply = <&reg_3p3v>;
 	};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6qdl-rex.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/imx6qdl-rex.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6qdl-rex.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6qdl-rex.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -126,7 +126,7 @@
 	codec: sgtl5000@0a {
 		compatible = "fsl,sgtl5000";
 		reg = <0x0a>;
-		clocks = <&clks 201>;
+		clocks = <&clks IMX6QDL_CLK_CKO>;
 		VDDA-supply = <&reg_3p3v>;
 		VDDIO-supply = <&reg_3p3v>;
 	};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -290,7 +290,7 @@
 	codec: sgtl5000@0a {
 		compatible = "fsl,sgtl5000";
 		reg = <0x0a>;
-		clocks = <&clks 201>;
+		clocks = <&clks IMX6QDL_CLK_CKO>;
 		VDDA-supply = <&reg_2p5v>;
 		VDDIO-supply = <&reg_3p3v>;
 	};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6qdl-sabresd.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6qdl-sabresd.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6qdl-sabresd.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -115,7 +115,7 @@
 		mux-ext-port = <3>;
 	};
 
-	backlight {
+	backlight_lvds: backlight-lvds {
 		compatible = "pwm-backlight";
 		pwms = <&pwm1 0 5000000>;
 		brightness-levels = <0 4 8 16 32 64 128 255>;
@@ -133,6 +133,17 @@
 		        default-state = "on";
 		};
 	};
+
+	panel {
+		compatible = "hannstar,hsd100pxn1";
+		backlight = <&backlight_lvds>;
+
+		port {
+			panel_in: endpoint {
+				remote-endpoint = <&lvds0_out>;
+			};
+		};
+	};
 };
 
 &audmux {
@@ -509,18 +520,11 @@
 		fsl,data-width = <18>;
 		status = "okay";
 
-		display-timings {
-			native-mode = <&timing0>;
-			timing0: hsd100pxn1 {
-				clock-frequency = <65000000>;
-				hactive = <1024>;
-				vactive = <768>;
-				hback-porch = <220>;
-				hfront-porch = <40>;
-				vback-porch = <21>;
-				vfront-porch = <7>;
-				hsync-len = <60>;
-				vsync-len = <10>;
+		port@4 {
+			reg = <4>;
+
+			lvds0_out: endpoint {
+				remote-endpoint = <&panel_in>;
 			};
 		};
 	};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6qdl-tx6.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/imx6qdl-tx6.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6qdl-tx6.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6qdl-tx6.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -1,12 +1,42 @@
 /*
- * Copyright 2014 Lothar Waßmann <LW@KARO-electronics.de>
+ * Copyright 2014-2016 Lothar Waßmann <LW@KARO-electronics.de>
  *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 at the following locations:
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
  *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
 #include <dt-bindings/gpio/gpio.h>
@@ -37,6 +67,7 @@
 	clocks {
 		#address-cells = <1>;
 		#size-cells = <0>;
+
 		mclk: clock@0 {
 			compatible = "fixed-clock";
 			reg = <0>;
@@ -61,109 +92,95 @@
 
 		user_led: user {
 			label = "Heartbeat";
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_user_led>;
 			gpios = <&gpio2 20 GPIO_ACTIVE_HIGH>;
 			linux,default-trigger = "heartbeat";
 		};
 	};
 
-	regulators {
-		compatible = "simple-bus";
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		reg_3v3_etn: regulator@0 {
-			compatible = "regulator-fixed";
-			reg = <0>;
-			regulator-name = "3V3_ETN";
-			regulator-min-microvolt = <3300000>;
-			regulator-max-microvolt = <3300000>;
-			pinctrl-names = "default";
-			pinctrl-0 = <&pinctrl_etnphy_power>;
-			gpio = <&gpio3 20 GPIO_ACTIVE_HIGH>;
-			enable-active-high;
-		};
+	reg_3v3_etn: regulator-3v3-etn {
+		compatible = "regulator-fixed";
+		regulator-name = "3V3_ETN";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_etnphy_power>;
+		gpio = <&gpio3 20 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
 
-		reg_2v5: regulator@1 {
-			compatible = "regulator-fixed";
-			reg = <1>;
-			regulator-name = "2V5";
-			regulator-min-microvolt = <2500000>;
-			regulator-max-microvolt = <2500000>;
-			regulator-always-on;
-		};
+	reg_2v5: regulator-2v5 {
+		compatible = "regulator-fixed";
+		regulator-name = "2V5";
+		regulator-min-microvolt = <2500000>;
+		regulator-max-microvolt = <2500000>;
+		regulator-always-on;
+	};
 
-		reg_3v3: regulator@2 {
-			compatible = "regulator-fixed";
-			reg = <2>;
-			regulator-name = "3V3";
-			regulator-min-microvolt = <3300000>;
-			regulator-max-microvolt = <3300000>;
-			regulator-always-on;
-		};
+	reg_3v3: regulator-3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+	};
 
-		reg_can_xcvr: regulator@3 {
-			compatible = "regulator-fixed";
-			reg = <3>;
-			regulator-name = "CAN XCVR";
-			regulator-min-microvolt = <3300000>;
-			regulator-max-microvolt = <3300000>;
-			pinctrl-names = "default";
-			pinctrl-0 = <&pinctrl_flexcan_xcvr>;
-			gpio = <&gpio4 21 GPIO_ACTIVE_HIGH>;
-			enable-active-low;
-		};
+	reg_can_xcvr: regulator-can-xcvr {
+		compatible = "regulator-fixed";
+		regulator-name = "CAN XCVR";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_flexcan_xcvr>;
+		gpio = <&gpio4 21 GPIO_ACTIVE_HIGH>;
+		enable-active-low;
+	};
 
-		reg_lcd0_pwr: regulator@4 {
-			compatible = "regulator-fixed";
-			reg = <4>;
-			regulator-name = "LCD0 POWER";
-			regulator-min-microvolt = <3300000>;
-			regulator-max-microvolt = <3300000>;
-			pinctrl-names = "default";
-			pinctrl-0 = <&pinctrl_lcd0_pwr>;
-			gpio = <&gpio3 29 GPIO_ACTIVE_HIGH>;
-			enable-active-high;
-			regulator-boot-on;
-			regulator-always-on;
-		};
+	reg_lcd0_pwr: regulator-lcd0-pwr {
+		compatible = "regulator-fixed";
+		regulator-name = "LCD0 POWER";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_lcd0_pwr>;
+		gpio = <&gpio3 29 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+		regulator-boot-on;
+	};
 
-		reg_lcd1_pwr: regulator@5 {
-			compatible = "regulator-fixed";
-			reg = <5>;
-			regulator-name = "LCD1 POWER";
-			regulator-min-microvolt = <3300000>;
-			regulator-max-microvolt = <3300000>;
-			pinctrl-names = "default";
-			pinctrl-0 = <&pinctrl_lcd1_pwr>;
-			gpio = <&gpio2 31 GPIO_ACTIVE_HIGH>;
-			enable-active-high;
-			regulator-boot-on;
-			regulator-always-on;
-		};
+	reg_lcd1_pwr: regulator-lcd1-pwr {
+		compatible = "regulator-fixed";
+		regulator-name = "LCD1 POWER";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_lcd1_pwr>;
+		gpio = <&gpio2 31 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+		regulator-boot-on;
+	};
 
-		reg_usbh1_vbus: regulator@6 {
-			compatible = "regulator-fixed";
-			reg = <6>;
-			regulator-name = "usbh1_vbus";
-			regulator-min-microvolt = <5000000>;
-			regulator-max-microvolt = <5000000>;
-			pinctrl-names = "default";
-			pinctrl-0 = <&pinctrl_usbh1_vbus>;
-			gpio = <&gpio3 31 GPIO_ACTIVE_HIGH>;
-			enable-active-high;
-		};
+	reg_usbh1_vbus: regulator-usbh1-vbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usbh1_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_usbh1_vbus>;
+		gpio = <&gpio3 31 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
 
-		reg_usbotg_vbus: regulator@7 {
-			compatible = "regulator-fixed";
-			reg = <7>;
-			regulator-name = "usbotg_vbus";
-			regulator-min-microvolt = <5000000>;
-			regulator-max-microvolt = <5000000>;
-			pinctrl-names = "default";
-			pinctrl-0 = <&pinctrl_usbotg_vbus>;
-			gpio = <&gpio1 7 GPIO_ACTIVE_HIGH>;
-			enable-active-high;
-		};
+	reg_usbotg_vbus: regulator-usbotg-vbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usbotg_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_usbotg_vbus>;
+		gpio = <&gpio1 7 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
 	};
 
 	sound {
@@ -209,7 +226,7 @@
 		&gpio2 30 GPIO_ACTIVE_HIGH
 		&gpio3 19 GPIO_ACTIVE_HIGH
 	>;
-	status = "okay";
+	status = "disabled";
 
 	spidev0: spi@0 {
 		compatible = "spidev";
@@ -234,8 +251,22 @@
 	clock-names = "ipg", "ahb", "ptp", "enet_out";
 	phy-mode = "rmii";
 	phy-reset-gpios = <&gpio7 6 GPIO_ACTIVE_HIGH>;
+	phy-handle = <&etnphy>;
 	phy-supply = <&reg_3v3_etn>;
 	status = "okay";
+
+	mdio {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		etnphy: ethernet-phy@0 {
+			compatible = "ethernet-phy-ieee802.3-c22";
+			reg = <0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_enet_mdio>;
+			interrupts-extended = <&gpio7 1 IRQ_TYPE_EDGE_FALLING>;
+		};
+	};
 };
 
 &gpmi {
@@ -301,310 +332,318 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_hog>;
 
-	imx6qdl-tx6 {
-		pinctrl_hog: hoggrp {
-			fsl,pins = <
-				MX6QDL_PAD_EIM_A18__GPIO2_IO20		0x1b0b1 /* LED */
-				MX6QDL_PAD_SD3_DAT2__GPIO7_IO06		0x1b0b1 /* ETN PHY RESET */
-				MX6QDL_PAD_SD3_DAT4__GPIO7_IO01		0x1b0b1 /* ETN PHY INT */
-				MX6QDL_PAD_EIM_A25__GPIO5_IO02		0x1b0b1 /* PWR BTN */
-			>;
-		};
+	pinctrl_hog: hoggrp {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_DAT2__GPIO7_IO06		0x1b0b1 /* ETN PHY RESET */
+			MX6QDL_PAD_SD3_DAT4__GPIO7_IO01		0x1b0b1 /* ETN PHY INT */
+			MX6QDL_PAD_EIM_A25__GPIO5_IO02		0x1b0b1 /* PWR BTN */
+		>;
+	};
 
-		pinctrl_audmux: audmuxgrp {
-			fsl,pins = <
-				MX6QDL_PAD_KEY_ROW1__AUD5_RXD		0x130b0 /* SSI1_RXD */
-				MX6QDL_PAD_KEY_ROW0__AUD5_TXD		0x110b0 /* SSI1_TXD */
-				MX6QDL_PAD_KEY_COL0__AUD5_TXC		0x130b0 /* SSI1_CLK */
-				MX6QDL_PAD_KEY_COL1__AUD5_TXFS		0x130b0 /* SSI1_FS */
-			>;
-		};
+	pinctrl_audmux: audmuxgrp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_ROW1__AUD5_RXD		0x130b0 /* SSI1_RXD */
+			MX6QDL_PAD_KEY_ROW0__AUD5_TXD		0x110b0 /* SSI1_TXD */
+			MX6QDL_PAD_KEY_COL0__AUD5_TXC		0x130b0 /* SSI1_CLK */
+			MX6QDL_PAD_KEY_COL1__AUD5_TXFS		0x130b0 /* SSI1_FS */
+		>;
+	};
 
-		pinctrl_disp0_1: disp0grp-1 {
-			fsl,pins = <
-				MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x10
-				MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15       0x10
-				MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02        0x10
-				MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03        0x10
-				/* PAD DISP0_DAT0 is used for the Flexcan transceiver control */
-				MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01   0x10
-				MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02   0x10
-				MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03   0x10
-				MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04   0x10
-				MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05   0x10
-				MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06   0x10
-				MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07   0x10
-				MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08   0x10
-				MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09   0x10
-				MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10  0x10
-				MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11  0x10
-				MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12  0x10
-				MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13  0x10
-				MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14  0x10
-				MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15  0x10
-				MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16  0x10
-				MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17  0x10
-				MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18  0x10
-				MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19  0x10
-				MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20  0x10
-				MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21  0x10
-				MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22  0x10
-				MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23  0x10
-			>;
-		};
+	pinctrl_disp0_1: disp0grp-1 {
+		fsl,pins = <
+			MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x10
+			MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15       0x10
+			MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02        0x10
+			MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03        0x10
+			/* PAD DISP0_DAT0 is used for the Flexcan transceiver control */
+			MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01   0x10
+			MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02   0x10
+			MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03   0x10
+			MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04   0x10
+			MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05   0x10
+			MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06   0x10
+			MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07   0x10
+			MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08   0x10
+			MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09   0x10
+			MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10  0x10
+			MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11  0x10
+			MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12  0x10
+			MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13  0x10
+			MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14  0x10
+			MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15  0x10
+			MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16  0x10
+			MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17  0x10
+			MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18  0x10
+			MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19  0x10
+			MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20  0x10
+			MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21  0x10
+			MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22  0x10
+			MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23  0x10
+		>;
+	};
 
-		pinctrl_disp0_2: disp0grp-2 {
-			fsl,pins = <
-				MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x10
-				MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15       0x10
-				MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02        0x10
-				MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03        0x10
-				MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00   0x10
-				MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01   0x10
-				MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02   0x10
-				MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03   0x10
-				MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04   0x10
-				MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05   0x10
-				MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06   0x10
-				MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07   0x10
-				MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08   0x10
-				MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09   0x10
-				MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10  0x10
-				MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11  0x10
-				MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12  0x10
-				MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13  0x10
-				MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14  0x10
-				MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15  0x10
-				MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16  0x10
-				MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17  0x10
-				MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18  0x10
-				MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19  0x10
-				MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20  0x10
-				MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21  0x10
-				MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22  0x10
-				MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23  0x10
-			>;
-		};
+	pinctrl_disp0_2: disp0grp-2 {
+		fsl,pins = <
+			MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x10
+			MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15       0x10
+			MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02        0x10
+			MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03        0x10
+			MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00   0x10
+			MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01   0x10
+			MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02   0x10
+			MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03   0x10
+			MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04   0x10
+			MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05   0x10
+			MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06   0x10
+			MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07   0x10
+			MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08   0x10
+			MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09   0x10
+			MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10  0x10
+			MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11  0x10
+			MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12  0x10
+			MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13  0x10
+			MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14  0x10
+			MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15  0x10
+			MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16  0x10
+			MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17  0x10
+			MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18  0x10
+			MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19  0x10
+			MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20  0x10
+			MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21  0x10
+			MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22  0x10
+			MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23  0x10
+		>;
+	};
 
-		pinctrl_ecspi1: ecspi1grp {
-			fsl,pins = <
-				MX6QDL_PAD_EIM_D18__ECSPI1_MOSI		0x0b0b0
-				MX6QDL_PAD_EIM_D17__ECSPI1_MISO		0x0b0b0
-				MX6QDL_PAD_EIM_D16__ECSPI1_SCLK		0x0b0b0
-				MX6QDL_PAD_GPIO_19__ECSPI1_RDY		0x0b0b0
-				MX6QDL_PAD_EIM_EB2__GPIO2_IO30		0x0b0b0 /* SPI CS0 */
-				MX6QDL_PAD_EIM_D19__GPIO3_IO19		0x0b0b0 /* SPI CS1 */
-			>;
-		};
+	pinctrl_ecspi1: ecspi1grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D18__ECSPI1_MOSI		0x0b0b0
+			MX6QDL_PAD_EIM_D17__ECSPI1_MISO		0x0b0b0
+			MX6QDL_PAD_EIM_D16__ECSPI1_SCLK		0x0b0b0
+			MX6QDL_PAD_GPIO_19__ECSPI1_RDY		0x0b0b0
+			MX6QDL_PAD_EIM_EB2__GPIO2_IO30		0x0b0b0 /* SPI CS0 */
+			MX6QDL_PAD_EIM_D19__GPIO3_IO19		0x0b0b0 /* SPI CS1 */
+		>;
+	};
 
-		pinctrl_edt_ft5x06: edt-ft5x06grp {
-			fsl,pins = <
-				MX6QDL_PAD_NANDF_CS2__GPIO6_IO15	0x1b0b0 /* Interrupt */
-				MX6QDL_PAD_EIM_A16__GPIO2_IO22  	0x1b0b0 /* Reset */
-				MX6QDL_PAD_EIM_A17__GPIO2_IO21  	0x1b0b0 /* Wake */
-			>;
-		};
+	pinctrl_edt_ft5x06: edt-ft5x06grp {
+		fsl,pins = <
+			MX6QDL_PAD_NANDF_CS2__GPIO6_IO15	0x1b0b0 /* Interrupt */
+			MX6QDL_PAD_EIM_A16__GPIO2_IO22  	0x1b0b0 /* Reset */
+			MX6QDL_PAD_EIM_A17__GPIO2_IO21  	0x1b0b0 /* Wake */
+		>;
+	};
 
-		pinctrl_enet: enetgrp {
-			fsl,pins = <
-				MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
-				MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
-				MX6QDL_PAD_ENET_RXD0__ENET_RX_DATA0	0x1b0b0
-				MX6QDL_PAD_ENET_RXD1__ENET_RX_DATA1	0x1b0b0
-				MX6QDL_PAD_ENET_RX_ER__ENET_RX_ER	0x1b0b0
-				MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN	0x1b0b0
-				MX6QDL_PAD_ENET_TXD0__ENET_TX_DATA0	0x1b0b0
-				MX6QDL_PAD_ENET_TXD1__ENET_TX_DATA1	0x1b0b0
-				MX6QDL_PAD_ENET_CRS_DV__ENET_RX_EN	0x1b0b0
-			>;
-		};
+	pinctrl_enet: enetgrp {
+		fsl,pins = <
+			MX6QDL_PAD_ENET_RXD0__ENET_RX_DATA0	0x1b0b0
+			MX6QDL_PAD_ENET_RXD1__ENET_RX_DATA1	0x1b0b0
+			MX6QDL_PAD_ENET_RX_ER__ENET_RX_ER	0x1b0b0
+			MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN	0x1b0b0
+			MX6QDL_PAD_ENET_TXD0__ENET_TX_DATA0	0x1b0b0
+			MX6QDL_PAD_ENET_TXD1__ENET_TX_DATA1	0x1b0b0
+			MX6QDL_PAD_ENET_CRS_DV__ENET_RX_EN	0x1b0b0
+		>;
+	};
 
-		pinctrl_etnphy_power: etnphy-pwrgrp {
-			fsl,pins = <
-				MX6QDL_PAD_EIM_D20__GPIO3_IO20		0x1b0b1 /* ETN PHY POWER */
-			>;
-		};
+	pinctrl_enet_mdio: enet-mdiogrp {
+		fsl,pins = <
+			MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
+			MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
+		>;
+	};
 
-		pinctrl_flexcan1: flexcan1grp {
-			fsl,pins = <
-				MX6QDL_PAD_GPIO_7__FLEXCAN1_TX		0x1b0b0
-				MX6QDL_PAD_GPIO_8__FLEXCAN1_RX		0x1b0b0
-			>;
-		};
+	pinctrl_etnphy_power: etnphy-pwrgrp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D20__GPIO3_IO20		0x1b0b1 /* ETN PHY POWER */
+		>;
+	};
 
-		pinctrl_flexcan2: flexcan2grp {
-			fsl,pins = <
-				MX6QDL_PAD_KEY_COL4__FLEXCAN2_TX	0x1b0b0
-				MX6QDL_PAD_KEY_ROW4__FLEXCAN2_RX	0x1b0b0
-			>;
-		};
+	pinctrl_flexcan1: flexcan1grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_7__FLEXCAN1_TX		0x1b0b0
+			MX6QDL_PAD_GPIO_8__FLEXCAN1_RX		0x1b0b0
+		>;
+	};
 
-		pinctrl_flexcan_xcvr: flexcan-xcvrgrp {
-			fsl,pins = <
-				MX6QDL_PAD_DISP0_DAT0__GPIO4_IO21	0x1b0b0 /* Flexcan XCVR enable */
-			>;
-		};
+	pinctrl_flexcan2: flexcan2grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL4__FLEXCAN2_TX	0x1b0b0
+			MX6QDL_PAD_KEY_ROW4__FLEXCAN2_RX	0x1b0b0
+		>;
+	};
 
-		pinctrl_gpmi_nand: gpminandgrp {
-			fsl,pins = <
-				MX6QDL_PAD_NANDF_CLE__NAND_CLE    	0x0b0b1
-				MX6QDL_PAD_NANDF_ALE__NAND_ALE    	0x0b0b1
-				MX6QDL_PAD_NANDF_WP_B__NAND_WP_B  	0x0b0b1
-				MX6QDL_PAD_NANDF_RB0__NAND_READY_B	0x0b000
-				MX6QDL_PAD_NANDF_CS0__NAND_CE0_B  	0x0b0b1
-				MX6QDL_PAD_SD4_CMD__NAND_RE_B     	0x0b0b1
-				MX6QDL_PAD_SD4_CLK__NAND_WE_B     	0x0b0b1
-				MX6QDL_PAD_NANDF_D0__NAND_DATA00  	0x0b0b1
-				MX6QDL_PAD_NANDF_D1__NAND_DATA01  	0x0b0b1
-				MX6QDL_PAD_NANDF_D2__NAND_DATA02  	0x0b0b1
-				MX6QDL_PAD_NANDF_D3__NAND_DATA03  	0x0b0b1
-				MX6QDL_PAD_NANDF_D4__NAND_DATA04  	0x0b0b1
-				MX6QDL_PAD_NANDF_D5__NAND_DATA05  	0x0b0b1
-				MX6QDL_PAD_NANDF_D6__NAND_DATA06  	0x0b0b1
-				MX6QDL_PAD_NANDF_D7__NAND_DATA07  	0x0b0b1
-			>;
-		};
+	pinctrl_flexcan_xcvr: flexcan-xcvrgrp {
+		fsl,pins = <
+			MX6QDL_PAD_DISP0_DAT0__GPIO4_IO21	0x1b0b0 /* Flexcan XCVR enable */
+		>;
+	};
 
-		pinctrl_i2c1: i2c1grp {
-			fsl,pins = <
-				MX6QDL_PAD_EIM_D21__I2C1_SCL		0x4001b8b1
-				MX6QDL_PAD_EIM_D28__I2C1_SDA		0x4001b8b1
-			>;
-		};
+	pinctrl_gpmi_nand: gpminandgrp {
+		fsl,pins = <
+			MX6QDL_PAD_NANDF_CLE__NAND_CLE    	0x0b0b1
+			MX6QDL_PAD_NANDF_ALE__NAND_ALE    	0x0b0b1
+			MX6QDL_PAD_NANDF_WP_B__NAND_WP_B  	0x0b0b1
+			MX6QDL_PAD_NANDF_RB0__NAND_READY_B	0x0b000
+			MX6QDL_PAD_NANDF_CS0__NAND_CE0_B  	0x0b0b1
+			MX6QDL_PAD_SD4_CMD__NAND_RE_B     	0x0b0b1
+			MX6QDL_PAD_SD4_CLK__NAND_WE_B     	0x0b0b1
+			MX6QDL_PAD_NANDF_D0__NAND_DATA00  	0x0b0b1
+			MX6QDL_PAD_NANDF_D1__NAND_DATA01  	0x0b0b1
+			MX6QDL_PAD_NANDF_D2__NAND_DATA02  	0x0b0b1
+			MX6QDL_PAD_NANDF_D3__NAND_DATA03  	0x0b0b1
+			MX6QDL_PAD_NANDF_D4__NAND_DATA04  	0x0b0b1
+			MX6QDL_PAD_NANDF_D5__NAND_DATA05  	0x0b0b1
+			MX6QDL_PAD_NANDF_D6__NAND_DATA06  	0x0b0b1
+			MX6QDL_PAD_NANDF_D7__NAND_DATA07  	0x0b0b1
+		>;
+	};
 
-		pinctrl_i2c3: i2c3grp {
-			fsl,pins = <
-				MX6QDL_PAD_GPIO_3__I2C3_SCL		0x4001b8b1
-				MX6QDL_PAD_GPIO_6__I2C3_SDA		0x4001b8b1
-			>;
-		};
+	pinctrl_i2c1: i2c1grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D21__I2C1_SCL		0x4001b8b1
+			MX6QDL_PAD_EIM_D28__I2C1_SDA		0x4001b8b1
+		>;
+	};
 
-		pinctrl_kpp: kppgrp {
-			fsl,pins = <
-				MX6QDL_PAD_GPIO_9__KEY_COL6		0x1b0b1
-				MX6QDL_PAD_GPIO_4__KEY_COL7		0x1b0b1
-				MX6QDL_PAD_KEY_COL2__KEY_COL2		0x1b0b1
-				MX6QDL_PAD_KEY_COL3__KEY_COL3		0x1b0b1
-				MX6QDL_PAD_GPIO_2__KEY_ROW6		0x1b0b1
-				MX6QDL_PAD_GPIO_5__KEY_ROW7		0x1b0b1
-				MX6QDL_PAD_KEY_ROW2__KEY_ROW2		0x1b0b1
-				MX6QDL_PAD_KEY_ROW3__KEY_ROW3		0x1b0b1
-			>;
-		};
+	pinctrl_i2c3: i2c3grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_3__I2C3_SCL		0x4001b8b1
+			MX6QDL_PAD_GPIO_6__I2C3_SDA		0x4001b8b1
+		>;
+	};
 
-		pinctrl_lcd0_pwr: lcd0-pwrgrp {
-			fsl,pins = <
-				MX6QDL_PAD_EIM_D29__GPIO3_IO29		0x1b0b1 /* LCD Reset */
-			>;
-		};
+	pinctrl_kpp: kppgrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_9__KEY_COL6		0x1b0b1
+			MX6QDL_PAD_GPIO_4__KEY_COL7		0x1b0b1
+			MX6QDL_PAD_KEY_COL2__KEY_COL2		0x1b0b1
+			MX6QDL_PAD_KEY_COL3__KEY_COL3		0x1b0b1
+			MX6QDL_PAD_GPIO_2__KEY_ROW6		0x1b0b1
+			MX6QDL_PAD_GPIO_5__KEY_ROW7		0x1b0b1
+			MX6QDL_PAD_KEY_ROW2__KEY_ROW2		0x1b0b1
+			MX6QDL_PAD_KEY_ROW3__KEY_ROW3		0x1b0b1
+		>;
+	};
 
-		pinctrl_lcd1_pwr: lcd1-pwrgrp {
-			fsl,pins = <
-				MX6QDL_PAD_EIM_EB3__GPIO2_IO31		0x1b0b1 /* LCD Power Enable */
-			>;
-		};
+	pinctrl_lcd0_pwr: lcd0-pwrgrp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D29__GPIO3_IO29		0x1b0b1 /* LCD Reset */
+		>;
+	};
 
-		pinctrl_pwm1: pwm1grp {
-			fsl,pins = <
-				MX6QDL_PAD_GPIO_9__PWM1_OUT		0x1b0b1
-			>;
-		};
+	pinctrl_lcd1_pwr: lcd-pwrgrp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_EB3__GPIO2_IO31		0x1b0b1 /* LCD Power Enable */
+		>;
+	};
 
-		pinctrl_pwm2: pwm2grp {
-			fsl,pins = <
-				MX6QDL_PAD_GPIO_1__PWM2_OUT		0x1b0b1
-			>;
-		};
+	pinctrl_pwm1: pwm1grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_9__PWM1_OUT		0x1b0b1
+		>;
+	};
 
-		pinctrl_tsc2007: tsc2007grp {
-			fsl,pins = <
-				MX6QDL_PAD_EIM_D26__GPIO3_IO26		0x1b0b0 /* Interrupt */
-			>;
-		};
+	pinctrl_pwm2: pwm2grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_1__PWM2_OUT		0x1b0b1
+		>;
+	};
 
-		pinctrl_uart1: uart1grp {
-			fsl,pins = <
-				MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA	0x1b0b1
-				MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA	0x1b0b1
-			>;
-		};
+	pinctrl_tsc2007: tsc2007grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D26__GPIO3_IO26		0x1b0b0 /* Interrupt */
+		>;
+	};
 
-		pinctrl_uart1_rtscts: uart1_rtsctsgrp {
-			fsl,pins = <
-				MX6QDL_PAD_SD3_DAT1__UART1_RTS_B	0x1b0b1
-				MX6QDL_PAD_SD3_DAT0__UART1_CTS_B	0x1b0b1
-			>;
-		};
+	pinctrl_uart1: uart1grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA	0x1b0b1
+			MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA	0x1b0b1
+		>;
+	};
 
-		pinctrl_uart2: uart2grp {
-			fsl,pins = <
-				MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA	0x1b0b1
-				MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA	0x1b0b1
-			>;
-		};
+	pinctrl_uart1_rtscts: uart1_rtsctsgrp {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_DAT1__UART1_RTS_B	0x1b0b1
+			MX6QDL_PAD_SD3_DAT0__UART1_CTS_B	0x1b0b1
+		>;
+	};
 
-		pinctrl_uart2_rtscts: uart2_rtsctsgrp {
-			fsl,pins = <
-				MX6QDL_PAD_SD4_DAT5__UART2_RTS_B	0x1b0b1
-				MX6QDL_PAD_SD4_DAT6__UART2_CTS_B	0x1b0b1
-			>;
-		};
+	pinctrl_uart2: uart2grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA	0x1b0b1
+			MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA	0x1b0b1
+		>;
+	};
 
-		pinctrl_uart3: uart3grp {
-			fsl,pins = <
-				MX6QDL_PAD_EIM_D24__UART3_TX_DATA	0x1b0b1
-				MX6QDL_PAD_EIM_D25__UART3_RX_DATA	0x1b0b1
-			>;
-		};
+	pinctrl_uart2_rtscts: uart2_rtsctsgrp {
+		fsl,pins = <
+			MX6QDL_PAD_SD4_DAT5__UART2_RTS_B	0x1b0b1
+			MX6QDL_PAD_SD4_DAT6__UART2_CTS_B	0x1b0b1
+		>;
+	};
 
-		pinctrl_uart3_rtscts: uart3_rtsctsgrp {
-			fsl,pins = <
-				MX6QDL_PAD_SD3_DAT3__UART3_CTS_B	0x1b0b1
-				MX6QDL_PAD_SD3_RST__UART3_RTS_B		0x1b0b1
-			>;
-		};
+	pinctrl_uart3: uart3grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D24__UART3_TX_DATA	0x1b0b1
+			MX6QDL_PAD_EIM_D25__UART3_RX_DATA	0x1b0b1
+		>;
+	};
 
-		pinctrl_usbh1_vbus: usbh1-vbusgrp {
-			fsl,pins = <
-				MX6QDL_PAD_EIM_D31__GPIO3_IO31		0x1b0b0 /* USBH1_VBUSEN */
-			>;
-		};
+	pinctrl_uart3_rtscts: uart3_rtsctsgrp {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_DAT3__UART3_CTS_B	0x1b0b1
+			MX6QDL_PAD_SD3_RST__UART3_RTS_B		0x1b0b1
+		>;
+	};
 
-		pinctrl_usbotg: usbotggrp {
-			fsl,pins = <
-				MX6QDL_PAD_EIM_D23__GPIO3_IO23		0x17059
-			>;
-		};
+	pinctrl_usbh1_vbus: usbh1-vbusgrp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D31__GPIO3_IO31		0x1b0b0 /* USBH1_VBUSEN */
+		>;
+	};
 
-		pinctrl_usbotg_vbus: usbotg-vbusgrp {
-			fsl,pins = <
-				MX6QDL_PAD_GPIO_7__GPIO1_IO07		0x1b0b0 /* USBOTG_VBUSEN */
-			>;
-		};
+	pinctrl_usbotg: usbotggrp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D23__GPIO3_IO23		0x17059
+		>;
+	};
 
-		pinctrl_usdhc1: usdhc1grp {
-			fsl,pins = <
-				MX6QDL_PAD_SD1_CMD__SD1_CMD		0x070b1
-				MX6QDL_PAD_SD1_CLK__SD1_CLK		0x070b1
-				MX6QDL_PAD_SD1_DAT0__SD1_DATA0		0x070b1
-				MX6QDL_PAD_SD1_DAT1__SD1_DATA1		0x070b1
-				MX6QDL_PAD_SD1_DAT2__SD1_DATA2		0x070b1
-				MX6QDL_PAD_SD1_DAT3__SD1_DATA3		0x070b1
-				MX6QDL_PAD_SD3_CMD__GPIO7_IO02		0x170b0 /* SD1 CD */
-			>;
-		};
+	pinctrl_usbotg_vbus: usbotg-vbusgrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_7__GPIO1_IO07		0x1b0b0 /* USBOTG_VBUSEN */
+		>;
+	};
 
-		pinctrl_usdhc2: usdhc2grp {
-			fsl,pins = <
-				MX6QDL_PAD_SD2_CMD__SD2_CMD		0x070b1
-				MX6QDL_PAD_SD2_CLK__SD2_CLK		0x070b1
-				MX6QDL_PAD_SD2_DAT0__SD2_DATA0		0x070b1
-				MX6QDL_PAD_SD2_DAT1__SD2_DATA1		0x070b1
-				MX6QDL_PAD_SD2_DAT2__SD2_DATA2		0x070b1
-				MX6QDL_PAD_SD2_DAT3__SD2_DATA3		0x070b1
-				MX6QDL_PAD_SD3_CLK__GPIO7_IO03		0x170b0 /* SD2 CD */
-			>;
-		};
+	pinctrl_usdhc1: usdhc1grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_CMD__SD1_CMD		0x070b1
+			MX6QDL_PAD_SD1_CLK__SD1_CLK		0x070b1
+			MX6QDL_PAD_SD1_DAT0__SD1_DATA0		0x070b1
+			MX6QDL_PAD_SD1_DAT1__SD1_DATA1		0x070b1
+			MX6QDL_PAD_SD1_DAT2__SD1_DATA2		0x070b1
+			MX6QDL_PAD_SD1_DAT3__SD1_DATA3		0x070b1
+			MX6QDL_PAD_SD3_CMD__GPIO7_IO02		0x170b0 /* SD1 CD */
+		>;
+	};
+
+	pinctrl_usdhc2: usdhc2grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD2_CMD__SD2_CMD		0x070b1
+			MX6QDL_PAD_SD2_CLK__SD2_CLK		0x070b1
+			MX6QDL_PAD_SD2_DAT0__SD2_DATA0		0x070b1
+			MX6QDL_PAD_SD2_DAT1__SD2_DATA1		0x070b1
+			MX6QDL_PAD_SD2_DAT2__SD2_DATA2		0x070b1
+			MX6QDL_PAD_SD2_DAT3__SD2_DATA3		0x070b1
+			MX6QDL_PAD_SD3_CLK__GPIO7_IO03		0x170b0 /* SD2 CD */
+		>;
+	};
+
+	pinctrl_user_led: user-ledgrp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_A18__GPIO2_IO20		0x1b0b1 /* LED */
+		>;
 	};
 };
 
@@ -649,19 +688,22 @@
 
 &uart1 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart1>;
+	pinctrl-0 = <&pinctrl_uart1 &pinctrl_uart1_rtscts>;
+	fsl,uart-has-rtscts;
 	status = "okay";
 };
 
 &uart2 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_uart2 &pinctrl_uart2_rtscts>;
+	fsl,uart-has-rtscts;
 	status = "okay";
 };
 
 &uart3 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_uart3 &pinctrl_uart3_rtscts>;
+	fsl,uart-has-rtscts;
 	status = "okay";
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6qdl-udoo.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/imx6qdl-udoo.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6qdl-udoo.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6qdl-udoo.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -10,14 +10,49 @@
  */
 
 / {
+	aliases {
+		backlight = &backlight;
+		panelchan = &panelchan;
+		panel7 = &panel7;
+		touchscreenp7 = &touchscreenp7;
+	};
+
 	chosen {
 		stdout-path = &uart2;
 	};
 
+	backlight: backlight {
+		compatible = "gpio-backlight";
+		gpios = <&gpio1 4 0>;
+		default-on;
+		status = "disabled";
+	};
+
 	memory {
 		reg = <0x10000000 0x40000000>;
 	};
 
+	panel7: panel7 {
+		/*
+		 * in reality it is a -20t (parallel) model,
+		 * but with LVDS bridge chip attached,
+		 * so it is equivalent to -19t model in drive
+		 * characteristics
+		 */
+		compatible = "urt,umsh-8596md-19t";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_panel>;
+		power-supply = <&reg_panel>;
+		backlight = <&backlight>;
+		status = "disabled";
+
+		port {
+			panel_in: endpoint {
+				remote-endpoint = <&lvds0_out>;
+			};
+		};
+	};
+
 	regulators {
 		compatible = "simple-bus";
 		#address-cells = <1>;
@@ -33,6 +68,14 @@
 			startup-delay-us = <2>; /* USB2415 requires a POR of 1 us minimum */
 			gpio = <&gpio7 12 0>;
 		};
+
+		reg_panel: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "lcd_panel";
+			enable-active-high;
+			gpio = <&gpio1 2 0>;
+		};
 	};
 
 	sound {
@@ -67,6 +110,24 @@
 	status = "okay";
 };
 
+&i2c3 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+
+	touchscreenp7: touchscreenp7@55 {
+		compatible = "sitronix,st1232";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_touchscreenp7>;
+		reg = <0x55>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <13 8>;
+		gpios = <&gpio1 15 0>;
+		status = "disabled";
+	};
+};
+
 &iomuxc {
 	imx6q-udoo {
 		pinctrl_enet: enetgrp {
@@ -97,6 +158,27 @@
 			>;
 		};
 
+		pinctrl_i2c3: i2c3grp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_5__I2C3_SCL		0x4001f8b1
+				MX6QDL_PAD_GPIO_6__I2C3_SDA		0x4001f8b1
+			>;
+		};
+
+		pinctrl_panel: panelgrp {
+			fsl,pins = <
+				MX6QDL_PAD_GPIO_2__GPIO1_IO02		0x70
+				MX6QDL_PAD_GPIO_4__GPIO1_IO04		0x70
+			>;
+		};
+
+		pinctrl_touchscreenp7: touchscreenp7grp {
+			fsl,pins = <
+				MX6QDL_PAD_SD2_DAT0__GPIO1_IO15		0x70
+				MX6QDL_PAD_SD2_DAT2__GPIO1_IO13		0x1b0b0
+			>;
+		};
+
 		pinctrl_uart2: uart2grp {
 			fsl,pins = <
 				MX6QDL_PAD_EIM_D26__UART2_TX_DATA	0x1b0b1
@@ -154,6 +236,20 @@
 	};
 };
 
+&ldb {
+	status = "okay";
+
+	panelchan: lvds-channel@0 {
+		port@4 {
+			reg = <4>;
+
+			lvds0_out: endpoint {
+				remote-endpoint = <&panel_in>;
+			};
+		};
+	};
+};
+
 &uart2 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_uart2>;
@@ -164,7 +260,7 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_usbh>;
 	vbus-supply = <&reg_usb_h1_vbus>;
-	clocks = <&clks 201>;
+	clocks = <&clks IMX6QDL_CLK_CKO>;
 	status = "okay";
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6qdl-wandboard.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6qdl-wandboard.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6qdl-wandboard.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -85,7 +85,7 @@
 	codec: sgtl5000@0a {
 		compatible = "fsl,sgtl5000";
 		reg = <0x0a>;
-		clocks = <&clks 201>;
+		clocks = <&clks IMX6QDL_CLK_CKO>;
 		VDDA-supply = <&reg_2p5v>;
 		VDDIO-supply = <&reg_3p3v>;
 	};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6q.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/imx6q.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6q.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6q.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -154,22 +154,22 @@
 				#size-cells = <0>;
 				reg = <2>;
 
-				ipu2_di0_disp0: endpoint@0 {
+				ipu2_di0_disp0: disp0-endpoint {
 				};
 
-				ipu2_di0_hdmi: endpoint@1 {
+				ipu2_di0_hdmi: hdmi-endpoint {
 					remote-endpoint = <&hdmi_mux_2>;
 				};
 
-				ipu2_di0_mipi: endpoint@2 {
+				ipu2_di0_mipi: mipi-endpoint {
 					remote-endpoint = <&mipi_mux_2>;
 				};
 
-				ipu2_di0_lvds0: endpoint@3 {
+				ipu2_di0_lvds0: lvds0-endpoint {
 					remote-endpoint = <&lvds0_mux_2>;
 				};
 
-				ipu2_di0_lvds1: endpoint@4 {
+				ipu2_di0_lvds1: lvds1-endpoint {
 					remote-endpoint = <&lvds1_mux_2>;
 				};
 			};
@@ -179,19 +179,19 @@
 				#size-cells = <0>;
 				reg = <3>;
 
-				ipu2_di1_hdmi: endpoint@1 {
+				ipu2_di1_hdmi: hdmi-endpoint {
 					remote-endpoint = <&hdmi_mux_3>;
 				};
 
-				ipu2_di1_mipi: endpoint@2 {
+				ipu2_di1_mipi: mipi-endpoint {
 					remote-endpoint = <&mipi_mux_3>;
 				};
 
-				ipu2_di1_lvds0: endpoint@3 {
+				ipu2_di1_lvds0: lvds0-endpoint {
 					remote-endpoint = <&lvds0_mux_3>;
 				};
 
-				ipu2_di1_lvds1: endpoint@4 {
+				ipu2_di1_lvds1: lvds1-endpoint {
 					remote-endpoint = <&lvds1_mux_3>;
 				};
 			};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6q-gw5400-a.dts linux-libre-4.7-gnu/arch/arm/boot/dts/imx6q-gw5400-a.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6q-gw5400-a.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6q-gw5400-a.dts	2016-07-24 15:23:50.000000000 -0400
@@ -327,7 +327,7 @@
 	codec: sgtl5000@0a {
 		compatible = "fsl,sgtl5000";
 		reg = <0x0a>;
-		clocks = <&clks 201>;
+		clocks = <&clks IMX6QDL_CLK_CKO>;
 		VDDA-supply = <&sw4_reg>;
 		VDDIO-supply = <&reg_3p3v>;
 	};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6q-marsboard.dts linux-libre-4.7-gnu/arch/arm/boot/dts/imx6q-marsboard.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6q-marsboard.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6q-marsboard.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,403 @@
+/*
+ * Copyright (C) 2016 Sergio Prado (sergio.prado@e-labworks.com)
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	model = "Embest MarS Board i.MX6Dual";
+	compatible = "embest,imx6q-marsboard", "fsl,imx6q";
+
+	memory {
+		reg = <0x10000000 0x40000000>;
+	};
+
+	reg_3p3v: regulator-3p3v {
+		compatible = "regulator-fixed";
+		regulator-name = "3P3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	reg_usb_otg_vbus: regulator-usb-otg-vbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usb_otg_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&gpio3 22 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_led>;
+
+		user1 {
+			label = "imx6:green:user1";
+			gpios = <&gpio5 2 GPIO_ACTIVE_LOW>;
+			default-state = "off";
+			linux,default-trigger = "heartbeat";
+		};
+
+		user2 {
+			label = "imx6:green:user2";
+			gpios = <&gpio3 28 GPIO_ACTIVE_LOW>;
+			default-state = "off";
+		};
+	};
+};
+
+&audmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_audmux>;
+	status = "okay";
+};
+
+&ecspi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi1>;
+	cs-gpios = <&gpio2 30 GPIO_ACTIVE_LOW>;
+	fsl,spi-num-chipselects = <1>;
+	status = "okay";
+
+	m25p80@0 {
+		compatible = "microchip,sst25vf016b";
+		spi-max-frequency = <20000000>;
+		reg = <0>;
+	};
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet>;
+	phy-mode = "rgmii";
+	phy-reset-gpios = <&gpio3 31 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
+&hdmi {
+	ddc-i2c-bus = <&i2c2>;
+	status = "okay";
+};
+
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+};
+
+&i2c3 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+};
+
+&pwm1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm1>;
+	status = "okay";
+};
+
+&pwm2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm2>;
+	status = "okay";
+};
+
+&pwm3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm3>;
+	status = "okay";
+};
+
+&pwm4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm4>;
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart3>;
+	status = "okay";
+};
+
+&uart4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart4>;
+	status = "okay";
+};
+
+&uart5 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart5>;
+	status = "okay";
+};
+
+&usbh1 {
+	dr_mode = "host";
+	disable-over-current;
+	status = "okay";
+};
+
+&usbotg {
+	vbus-supply = <&reg_usb_otg_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	dr_mode = "otg";
+	disable-over-current;
+	status = "okay";
+};
+
+&usdhc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc2>;
+	vmmc-supply = <&reg_3p3v>;
+	cd-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
+	wp-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
+	status = "okay";
+};
+
+&usdhc3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc3>;
+	vmmc-supply = <&reg_3p3v>;
+	non-removable;
+	status = "okay";
+};
+
+&iomuxc {
+
+	pinctrl_audmux: audmuxgrp {
+		fsl,pins = <
+			MX6QDL_PAD_CSI0_DAT7__AUD3_RXD		0x130b0
+			MX6QDL_PAD_CSI0_DAT4__AUD3_TXC		0x130b0
+			MX6QDL_PAD_CSI0_DAT5__AUD3_TXD		0x110b0
+			MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS		0x130b0
+			MX6QDL_PAD_GPIO_0__CCM_CLKO1		0x130b0	/* CAM_MCLK */
+		>;
+	};
+
+	pinctrl_ecspi1: ecspi1grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D16__ECSPI1_SCLK		0x100b1
+			MX6QDL_PAD_EIM_D17__ECSPI1_MISO		0x100b1
+			MX6QDL_PAD_EIM_D18__ECSPI1_MOSI		0x100b1
+			MX6QDL_PAD_EIM_EB2__GPIO2_IO30		0x000b1	/* CS0 */
+		>;
+	};
+
+	pinctrl_enet: enetgrp {
+		fsl,pins = <
+			MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
+			MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
+			MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x1b0b0
+			MX6QDL_PAD_RGMII_TD0__RGMII_TD0		0x1b0b0
+			MX6QDL_PAD_RGMII_TD1__RGMII_TD1		0x1b0b0
+			MX6QDL_PAD_RGMII_TD2__RGMII_TD2		0x1b0b0
+			MX6QDL_PAD_RGMII_TD3__RGMII_TD3		0x1b0b0
+			MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL	0x1b0b0
+			/* AR8035 CLK_25M --> ENET_REF_CLK (V22) */
+			MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK	0x0a0b1
+			/* AR8035 pin strapping: IO voltage: pull up */
+			MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b0b0
+			/* AR8035 pin strapping: PHYADDR#0: pull down */
+			MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x130b0
+			/* AR8035 pin strapping: PHYADDR#1: pull down */
+			MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x130b0
+			/* AR8035 pin strapping: MODE#1: pull up */
+			MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b0b0
+			/* AR8035 pin strapping: MODE#3: pull up */
+			MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b0b0
+			/* AR8035 pin strapping: MODE#0: pull down */
+			MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x130b0
+			/* GPIO16 -> AR8035 25MHz */
+			MX6QDL_PAD_GPIO_16__ENET_REF_CLK	0x4001b0a8
+			/* RGMII_nRST */
+			MX6QDL_PAD_EIM_D31__GPIO3_IO31		0x130b0
+			/* AR8035 interrupt */
+			MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28	0x180b0
+		>;
+	};
+
+	pinctrl_i2c1: i2c1grp {
+		fsl,pins = <
+			MX6QDL_PAD_CSI0_DAT8__I2C1_SDA		0x4001b8b1
+			MX6QDL_PAD_CSI0_DAT9__I2C1_SCL		0x4001b8b1
+		>;
+	};
+
+	pinctrl_i2c2: i2c2grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL3__I2C2_SCL		0x4001b8b1
+			MX6QDL_PAD_KEY_ROW3__I2C2_SDA		0x4001b8b1
+		>;
+	};
+
+	pinctrl_i2c3: i2c3grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_5__I2C3_SCL		0x4001b8b1
+			MX6QDL_PAD_GPIO_6__I2C3_SDA		0x4001b8b1
+		>;
+	};
+
+	pinctrl_led: ledgrp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_A25__GPIO5_IO02		0x1b0b1	/* LED1 */
+			MX6QDL_PAD_EIM_D28__GPIO3_IO28		0x1b0b1	/* LED2 */
+		>;
+	};
+
+	pinctrl_pwm1: pwm1grp {
+		fsl,pins = <
+			MX6QDL_PAD_DISP0_DAT8__PWM1_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm2: pwm2grp {
+		fsl,pins = <
+			MX6QDL_PAD_DISP0_DAT9__PWM2_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm3: pwm3grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_DAT1__PWM3_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm4: pwm4grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_CMD__PWM4_OUT		0x1b0b1
+		>;
+	};
+
+	pinctrl_uart1: uart1grp {
+		fsl,pins = <
+			MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA	0x1b0b1
+			MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart2: uart2grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D26__UART2_TX_DATA	0x1b0b1
+			MX6QDL_PAD_EIM_D27__UART2_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart3: uart3grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D24__UART3_TX_DATA	0x1b0b1
+			MX6QDL_PAD_EIM_D25__UART3_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart4: uart4grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL0__UART4_TX_DATA	0x1b0b1
+			MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart5: uart5grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL1__UART5_TX_DATA	0x1b0b1
+			MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_usbotg: usbotggrp {
+		fsl,pins = <
+			MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID	0x17059
+			MX6QDL_PAD_EIM_D21__USB_OTG_OC		0x1b0b0
+			MX6QDL_PAD_EIM_D22__GPIO3_IO22		0x000b0	/* USB OTG POWER ENABLE */
+		>;
+	};
+
+	pinctrl_usdhc2: usdhc2grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD2_CMD__SD2_CMD		0x17059
+			MX6QDL_PAD_SD2_CLK__SD2_CLK		0x10059
+			MX6QDL_PAD_SD2_DAT0__SD2_DATA0		0x17059
+			MX6QDL_PAD_SD2_DAT1__SD2_DATA1		0x17059
+			MX6QDL_PAD_SD2_DAT2__SD2_DATA2		0x17059
+			MX6QDL_PAD_SD2_DAT3__SD2_DATA3		0x17059
+			MX6QDL_PAD_GPIO_4__GPIO1_IO04		0x1b0b0	/* CD */
+			MX6QDL_PAD_GPIO_2__GPIO1_IO02		0x1f0b0	/* WP */
+		>;
+	};
+
+	pinctrl_usdhc3: usdhc3grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_CMD__SD3_CMD		0x17009
+			MX6QDL_PAD_SD3_CLK__SD3_CLK		0x10009
+			MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x17009
+			MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x17009
+			MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x17009
+			MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x17009
+			MX6QDL_PAD_SD3_RST__SD3_RESET		0x17009
+		>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6qp.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/imx6qp.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6qp.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6qp.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -82,5 +82,8 @@
 				      "ldb_di0", "ldb_di1", "prg";
 		};
 
+		pcie: pcie@0x01000000 {
+			compatible = "fsl,imx6qp-pcie", "snps,dw-pcie";
+		};
 	};
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6qp-nitrogen6_max.dts linux-libre-4.7-gnu/arch/arm/boot/dts/imx6qp-nitrogen6_max.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6qp-nitrogen6_max.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6qp-nitrogen6_max.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2016 Boundary Devices, Inc.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include "imx6qp.dtsi"
+#include "imx6qdl-nitrogen6_max.dtsi"
+
+/ {
+	model = "Boundary Devices i.MX6 Quad Plus Nitrogen6_MAX Board";
+	compatible = "boundary,imx6qp-nitrogen6_max", "fsl,imx6qp";
+};
+
+&pcie {
+	status = "disabled";
+};
+
+&sata {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6q-tbs2910.dts linux-libre-4.7-gnu/arch/arm/boot/dts/imx6q-tbs2910.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6q-tbs2910.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6q-tbs2910.dts	2016-07-24 15:23:50.000000000 -0400
@@ -141,7 +141,7 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_enet>;
 	phy-mode = "rgmii";
-	phy-reset-gpios = <&gpio1 25 GPIO_ACTIVE_HIGH>;
+	phy-reset-gpios = <&gpio1 25 GPIO_ACTIVE_LOW>;
 	status = "okay";
 };
 
@@ -159,7 +159,7 @@
 	status = "okay";
 
 	sgtl5000: sgtl5000@0a {
-		clocks = <&clks 201>;
+		clocks = <&clks IMX6QDL_CLK_CKO>;
 		compatible = "fsl,sgtl5000";
 		pinctrl-names = "default";
 		pinctrl-0 = <&pinctrl_sgtl5000>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6q-tx6q-1010-comtft.dts linux-libre-4.7-gnu/arch/arm/boot/dts/imx6q-tx6q-1010-comtft.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6q-tx6q-1010-comtft.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6q-tx6q-1010-comtft.dts	2016-07-24 15:23:50.000000000 -0400
@@ -1,12 +1,42 @@
 /*
- * Copyright 2014 Lothar Waßmann <LW@KARO-electronics.de>
+ * Copyright 2014-2016 Lothar Waßmann <LW@KARO-electronics.de>
  *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 at the following locations:
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
  *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
 /dts-v1/;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6q-tx6q-1010.dts linux-libre-4.7-gnu/arch/arm/boot/dts/imx6q-tx6q-1010.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6q-tx6q-1010.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6q-tx6q-1010.dts	2016-07-24 15:23:50.000000000 -0400
@@ -1,12 +1,42 @@
 /*
- * Copyright 2014 Lothar Waßmann <LW@KARO-electronics.de>
+ * Copyright 2014-2016 Lothar Waßmann <LW@KARO-electronics.de>
  *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 at the following locations:
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
  *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
 /dts-v1/;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6q-tx6q-1020-comtft.dts linux-libre-4.7-gnu/arch/arm/boot/dts/imx6q-tx6q-1020-comtft.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6q-tx6q-1020-comtft.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6q-tx6q-1020-comtft.dts	2016-07-24 15:23:50.000000000 -0400
@@ -1,12 +1,42 @@
 /*
- * Copyright 2014 Lothar Waßmann <LW@KARO-electronics.de>
+ * Copyright 2014-2016 Lothar Waßmann <LW@KARO-electronics.de>
  *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 at the following locations:
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
  *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
 /dts-v1/;
@@ -94,22 +124,6 @@
 	status = "disabled";
 };
 
-&iomuxc {
-	imx6qdl-tx6 {
-		pinctrl_usdhc4: usdhc4grp {
-			fsl,pins = <
-				MX6QDL_PAD_SD4_CMD__SD4_CMD		0x070b1
-				MX6QDL_PAD_SD4_CLK__SD4_CLK		0x070b1
-				MX6QDL_PAD_SD4_DAT0__SD4_DATA0		0x070b1
-				MX6QDL_PAD_SD4_DAT1__SD4_DATA1		0x070b1
-				MX6QDL_PAD_SD4_DAT2__SD4_DATA2		0x070b1
-				MX6QDL_PAD_SD4_DAT3__SD4_DATA3		0x070b1
-				MX6QDL_PAD_NANDF_ALE__SD4_RESET		0x0b0b1
-			>;
-		};
-	};
-};
-
 &ipu1_di0_disp0 {
 	remote-endpoint = <&display0_in>;
 };
@@ -134,3 +148,17 @@
 	fsl,wp-controller;
 	status = "okay";
 };
+
+&iomuxc {
+	pinctrl_usdhc4: usdhc4grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD4_CMD__SD4_CMD		0x070b1
+			MX6QDL_PAD_SD4_CLK__SD4_CLK		0x070b1
+			MX6QDL_PAD_SD4_DAT0__SD4_DATA0		0x070b1
+			MX6QDL_PAD_SD4_DAT1__SD4_DATA1		0x070b1
+			MX6QDL_PAD_SD4_DAT2__SD4_DATA2		0x070b1
+			MX6QDL_PAD_SD4_DAT3__SD4_DATA3		0x070b1
+			MX6QDL_PAD_NANDF_ALE__SD4_RESET		0x0b0b1
+		>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6q-tx6q-1020.dts linux-libre-4.7-gnu/arch/arm/boot/dts/imx6q-tx6q-1020.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6q-tx6q-1020.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6q-tx6q-1020.dts	2016-07-24 15:23:50.000000000 -0400
@@ -1,12 +1,42 @@
 /*
- * Copyright 2014 Lothar Waßmann <LW@KARO-electronics.de>
+ * Copyright 2014-2016 Lothar Waßmann <LW@KARO-electronics.de>
  *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 at the following locations:
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
  *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
 /dts-v1/;
@@ -180,22 +210,6 @@
 	status = "disabled";
 };
 
-&iomuxc {
-	imx6qdl-tx6 {
-		pinctrl_usdhc4: usdhc4grp {
-			fsl,pins = <
-				MX6QDL_PAD_SD4_CMD__SD4_CMD		0x070b1
-				MX6QDL_PAD_SD4_CLK__SD4_CLK		0x070b1
-				MX6QDL_PAD_SD4_DAT0__SD4_DATA0		0x070b1
-				MX6QDL_PAD_SD4_DAT1__SD4_DATA1		0x070b1
-				MX6QDL_PAD_SD4_DAT2__SD4_DATA2		0x070b1
-				MX6QDL_PAD_SD4_DAT3__SD4_DATA3		0x070b1
-				MX6QDL_PAD_NANDF_ALE__SD4_RESET		0x0b0b1
-			>;
-		};
-	};
-};
-
 &ipu1_di0_disp0 {
 	remote-endpoint = <&display0_in>;
 };
@@ -208,3 +222,17 @@
 	fsl,wp-controller;
 	status = "okay";
 };
+
+&iomuxc {
+	pinctrl_usdhc4: usdhc4grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD4_CMD__SD4_CMD		0x070b1
+			MX6QDL_PAD_SD4_CLK__SD4_CLK		0x070b1
+			MX6QDL_PAD_SD4_DAT0__SD4_DATA0		0x070b1
+			MX6QDL_PAD_SD4_DAT1__SD4_DATA1		0x070b1
+			MX6QDL_PAD_SD4_DAT2__SD4_DATA2		0x070b1
+			MX6QDL_PAD_SD4_DAT3__SD4_DATA3		0x070b1
+			MX6QDL_PAD_NANDF_ALE__SD4_RESET		0x0b0b1
+		>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6q-tx6q-1036.dts linux-libre-4.7-gnu/arch/arm/boot/dts/imx6q-tx6q-1036.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6q-tx6q-1036.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6q-tx6q-1036.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2014-2016 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-tx6.dtsi"
+
+/ {
+	model = "Ka-Ro electronics TX6Q-1036 Module";
+	compatible = "karo,imx6q-tx6q", "fsl,imx6q";
+
+	aliases {
+		display = &display;
+	};
+
+	backlight: backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm2 0 500000 PWM_POLARITY_INVERTED>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_lcd0_pwr>;
+		enable-gpios = <&gpio3 29 GPIO_ACTIVE_HIGH>;
+		power-supply = <&reg_lcd1_pwr>;
+		/*
+		 * a poor man's way to create a 1:1 relationship between
+		 * the PWM value and the actual duty cycle
+		 */
+		brightness-levels = < 0  1  2  3  4  5  6  7  8  9
+				     10 11 12 13 14 15 16 17 18 19
+				     20 21 22 23 24 25 26 27 28 29
+				     30 31 32 33 34 35 36 37 38 39
+				     40 41 42 43 44 45 46 47 48 49
+				     50 51 52 53 54 55 56 57 58 59
+				     60 61 62 63 64 65 66 67 68 69
+				     70 71 72 73 74 75 76 77 78 79
+				     80 81 82 83 84 85 86 87 88 89
+				     90 91 92 93 94 95 96 97 98 99
+				    100>;
+		default-brightness-level = <50>;
+	};
+
+	display: display@di0 {
+		compatible = "fsl,imx-parallel-display";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_disp0_2>;
+		interface-pix-fmt = "rgb24";
+		status = "okay";
+
+		port {
+			display0_in: endpoint {
+				remote-endpoint = <&ipu1_di0_disp0>;
+			};
+		};
+
+		display-timings {
+			native-mode = <&vga>;
+
+			vga: VGA {
+				clock-frequency = <25200000>;
+				hactive = <640>;
+				vactive = <480>;
+				hback-porch = <48>;
+				hsync-len = <96>;
+				hfront-porch = <16>;
+				vback-porch = <31>;
+				vsync-len = <2>;
+				vfront-porch = <12>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			ETV570 {
+				clock-frequency = <25200000>;
+				hactive = <640>;
+				vactive = <480>;
+				hback-porch = <114>;
+				hsync-len = <30>;
+				hfront-porch = <16>;
+				vback-porch = <32>;
+				vsync-len = <3>;
+				vfront-porch = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			ET0350 {
+				clock-frequency = <6413760>;
+				hactive = <320>;
+				vactive = <240>;
+				hback-porch = <34>;
+				hsync-len = <34>;
+				hfront-porch = <20>;
+				vback-porch = <15>;
+				vsync-len = <3>;
+				vfront-porch = <4>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			ET0430 {
+				clock-frequency = <9009000>;
+				hactive = <480>;
+				vactive = <272>;
+				hback-porch = <2>;
+				hsync-len = <41>;
+				hfront-porch = <2>;
+				vback-porch = <2>;
+				vsync-len = <10>;
+				vfront-porch = <2>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <1>;
+			};
+
+			ET0500 {
+				clock-frequency = <33264000>;
+				hactive = <800>;
+				vactive = <480>;
+				hback-porch = <88>;
+				hsync-len = <128>;
+				hfront-porch = <40>;
+				vback-porch = <33>;
+				vsync-len = <2>;
+				vfront-porch = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			ET0700 { /* same as ET0500 */
+				clock-frequency = <33264000>;
+				hactive = <800>;
+				vactive = <480>;
+				hback-porch = <88>;
+				hsync-len = <128>;
+				hfront-porch = <40>;
+				vback-porch = <33>;
+				vsync-len = <2>;
+				vfront-porch = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			ETQ570 {
+				clock-frequency = <6596040>;
+				hactive = <320>;
+				vactive = <240>;
+				hback-porch = <38>;
+				hsync-len = <30>;
+				hfront-porch = <30>;
+				vback-porch = <16>;
+				vsync-len = <3>;
+				vfront-porch = <4>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+		};
+	};
+};
+
+&ds1339 {
+	status = "disabled";
+};
+
+&gpmi {
+	status = "disabled";
+};
+
+&ipu1_di0_disp0 {
+	remote-endpoint = <&display0_in>;
+};
+
+&ipu2 {
+	status = "disabled";
+};
+
+&reg_lcd0_pwr {
+	status = "disabled";
+};
+
+&usdhc4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc4>;
+	bus-width = <4>;
+	non-removable;
+	no-1-8-v;
+	fsl,wp-controller;
+	status = "okay";
+};
+
+&iomuxc {
+	pinctrl_usdhc4: usdhc4grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD4_CMD__SD4_CMD		0x070b1
+			MX6QDL_PAD_SD4_CLK__SD4_CLK		0x070b1
+			MX6QDL_PAD_SD4_DAT0__SD4_DATA0		0x070b1
+			MX6QDL_PAD_SD4_DAT1__SD4_DATA1		0x070b1
+			MX6QDL_PAD_SD4_DAT2__SD4_DATA2		0x070b1
+			MX6QDL_PAD_SD4_DAT3__SD4_DATA3		0x070b1
+			MX6QDL_PAD_NANDF_ALE__SD4_RESET		0x0b0b1
+		>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6q-tx6q-1110.dts linux-libre-4.7-gnu/arch/arm/boot/dts/imx6q-tx6q-1110.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6q-tx6q-1110.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6q-tx6q-1110.dts	2016-07-24 15:23:50.000000000 -0400
@@ -1,12 +1,42 @@
 /*
- * Copyright 2014 Lothar Waßmann <LW@KARO-electronics.de>
+ * Copyright 2014-2016 Lothar Waßmann <LW@KARO-electronics.de>
  *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 at the following locations:
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
  *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
 /dts-v1/;
@@ -81,16 +111,6 @@
 	};
 };
 
-&iomuxc {
-	imx6q-tx6q-1110 {
-		pinctrl_eeti: eetigrp {
-			fsl,pins = <
-				MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x1b0b1 /* Interrupt */
-			>;
-		};
-	};
-};
-
 &kpp {
 	status = "disabled"; /* pad conflict with backlight1 PWM */
 };
@@ -152,3 +172,11 @@
 &sata {
 	status = "okay";
 };
+
+&iomuxc {
+	pinctrl_eeti: eetigrp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x1b0b1 /* Interrupt */
+		>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6q-tx6q-11x0-mb7.dts linux-libre-4.7-gnu/arch/arm/boot/dts/imx6q-tx6q-11x0-mb7.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6q-tx6q-11x0-mb7.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6q-tx6q-11x0-mb7.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,264 @@
+/*
+ * Copyright 2016 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-tx6.dtsi"
+
+/ {
+	model = "Ka-Ro electronics TX6Q-1110/-1130 Module on MB7 baseboard";
+	compatible = "karo,imx6q-tx6q", "fsl,imx6q";
+
+	aliases {
+		display = &lvds0;
+		ipu1 = &ipu2;
+		lvds0 = &lvds0;
+		lvds1 = &lvds1;
+	};
+
+	backlight0: backlight0 {
+		compatible = "pwm-backlight";
+		pwms = <&pwm2 0 500000 PWM_POLARITY_INVERTED>;
+		power-supply = <&reg_lcd0_pwr>;
+		/*
+		 * a poor man's way to create a 1:1 relationship between
+		 * the PWM value and the actual duty cycle
+		 */
+		brightness-levels = < 0  1  2  3  4  5  6  7  8  9
+				     10 11 12 13 14 15 16 17 18 19
+				     20 21 22 23 24 25 26 27 28 29
+				     30 31 32 33 34 35 36 37 38 39
+				     40 41 42 43 44 45 46 47 48 49
+				     50 51 52 53 54 55 56 57 58 59
+				     60 61 62 63 64 65 66 67 68 69
+				     70 71 72 73 74 75 76 77 78 79
+				     80 81 82 83 84 85 86 87 88 89
+				     90 91 92 93 94 95 96 97 98 99
+				    100>;
+		default-brightness-level = <50>;
+	};
+
+	backlight1: backlight1 {
+		compatible = "pwm-backlight";
+		pwms = <&pwm1 0 500000 PWM_POLARITY_INVERTED>;
+		power-supply = <&reg_lcd1_pwr>;
+		/*
+		 * a poor man's way to create a 1:1 relationship between
+		 * the PWM value and the actual duty cycle
+		 */
+		brightness-levels = < 0  1  2  3  4  5  6  7  8  9
+				     10 11 12 13 14 15 16 17 18 19
+				     20 21 22 23 24 25 26 27 28 29
+				     30 31 32 33 34 35 36 37 38 39
+				     40 41 42 43 44 45 46 47 48 49
+				     50 51 52 53 54 55 56 57 58 59
+				     60 61 62 63 64 65 66 67 68 69
+				     70 71 72 73 74 75 76 77 78 79
+				     80 81 82 83 84 85 86 87 88 89
+				     90 91 92 93 94 95 96 97 98 99
+				    100>;
+		default-brightness-level = <50>;
+	};
+};
+
+&can1 {
+	status = "disabled";
+};
+
+&can2 {
+	xceiver-supply = <&reg_3v3>;
+};
+
+&i2c3 {
+	polytouch1: eeti@04 {
+		compatible = "eeti,egalax_ts";
+		reg = <0x04>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_eeti>;
+		interrupts-extended = <&gpio3 22 IRQ_TYPE_EDGE_FALLING>;
+		wakeup-gpios = <&gpio3 22 GPIO_ACTIVE_HIGH>;
+		wakeup-source;
+	};
+};
+
+&ipu2 {
+	status = "disabled";
+};
+
+&kpp {
+	status = "disabled"; /* pads partially clash with backlight1 PWM */
+};
+
+&ldb {
+	status = "okay";
+
+	lvds0: lvds-channel@0 {
+		fsl,data-mapping = "spwg";
+		fsl,data-width = <18>;
+		status = "okay";
+
+		display-timings {
+			native-mode = <&lvds0_timing1>;
+
+			lvds0_timing0: hsd100pxn1 {
+				clock-frequency = <65000000>;
+				hactive = <1024>;
+				vactive = <768>;
+				hback-porch = <220>;
+				hfront-porch = <40>;
+				vback-porch = <21>;
+				vfront-porch = <7>;
+				hsync-len = <60>;
+				vsync-len = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <1>;
+			};
+
+			lvds0_timing1: VGA {
+				clock-frequency = <25200000>;
+				hactive = <640>;
+				vactive = <480>;
+				hback-porch = <48>;
+				hfront-porch = <16>;
+				vback-porch = <31>;
+				vfront-porch = <12>;
+				hsync-len = <96>;
+				vsync-len = <2>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			lvds0_timing2: nl12880bc20 {
+				clock-frequency = <71000000>;
+				hactive = <1280>;
+				vactive = <800>;
+				hback-porch = <50>;
+				hfront-porch = <50>;
+				vback-porch = <5>;
+				vfront-porch = <5>;
+				hsync-len = <60>;
+				vsync-len = <13>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <1>;
+			};
+		};
+	};
+
+	lvds1: lvds-channel@1 {
+		fsl,data-mapping = "spwg";
+		fsl,data-width = <18>;
+		status = "okay";
+
+		display-timings {
+			native-mode = <&lvds1_timing2>;
+
+			lvds1_timing0: hsd100pxn1 {
+				clock-frequency = <65000000>;
+				hactive = <1024>;
+				vactive = <768>;
+				hback-porch = <220>;
+				hfront-porch = <40>;
+				vback-porch = <21>;
+				vfront-porch = <7>;
+				hsync-len = <60>;
+				vsync-len = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <1>;
+			};
+
+			lvds1_timing1: VGA {
+				clock-frequency = <25200000>;
+				hactive = <640>;
+				vactive = <480>;
+				hback-porch = <48>;
+				hfront-porch = <16>;
+				vback-porch = <31>;
+				vfront-porch = <12>;
+				hsync-len = <96>;
+				vsync-len = <2>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			lvds1_timing2: nl12880bc20 {
+				clock-frequency = <71000000>;
+				hactive = <1280>;
+				vactive = <800>;
+				hback-porch = <50>;
+				hfront-porch = <50>;
+				vback-porch = <5>;
+				vfront-porch = <5>;
+				hsync-len = <60>;
+				vsync-len = <13>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <1>;
+			};
+		};
+	};
+};
+
+&pwm1 {
+	status = "okay";
+};
+
+&sata {
+	status = "okay";
+};
+
+&iomuxc {
+	pinctrl_eeti: eetigrp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x1b0b1 /* Interrupt */
+		>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6sx.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/imx6sx.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6sx.dtsi	2016-05-15 19:23:05.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6sx.dtsi	2016-07-24 18:19:49.000000000 -0400
@@ -63,12 +63,14 @@
 				996000  1250000
 				792000  1175000
 				396000  1075000
+				198000	975000
 			>;
 			fsl,soc-operating-points = <
 				/* ARM kHz  SOC uV */
 				996000      1175000
 				792000      1175000
 				396000      1175000
+				198000	    1175000
 			>;
 			clock-latency = <61036>; /* two CLK32 periods */
 			clocks = <&clks IMX6SX_CLK_ARM>,
@@ -970,8 +972,7 @@
 					 <&clks 0>, <&clks 0>;
 				clock-names = "bus", "mclk1", "mclk2", "mclk3";
 				dma-names = "rx", "tx";
-				dmas = <&sdma 31 23 0>, <&sdma 32 23 0>;
-				dma-source = <&gpr 0 15 0 16>;
+				dmas = <&sdma 31 24 0>, <&sdma 32 24 0>;
 				status = "disabled";
 			};
 
@@ -990,8 +991,7 @@
 					 <&clks 0>, <&clks 0>;
 				clock-names = "bus", "mclk1", "mclk2", "mclk3";
 				dma-names = "rx", "tx";
-				dmas = <&sdma 33 23 0>, <&sdma 34 23 0>;
-				dma-source = <&gpr 0 17 0 18>;
+				dmas = <&sdma 33 24 0>, <&sdma 34 24 0>;
 				status = "disabled";
 			};
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6sx-nitrogen6sx.dts linux-libre-4.7-gnu/arch/arm/boot/dts/imx6sx-nitrogen6sx.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6sx-nitrogen6sx.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6sx-nitrogen6sx.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,709 @@
+/*
+ * Copyright (C) 2016 Boundary Devices, Inc.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include "imx6sx.dtsi"
+
+/ {
+	model = "Boundary Devices i.MX6 SoloX Nitrogen6sx Board";
+	compatible = "boundary,imx6sx-nitrogen6sx", "fsl,imx6sx";
+
+	aliases {
+		fb_lcd = &lcdif1;
+		t_lcd = &t_lcd;
+	};
+
+	memory {
+		reg = <0x80000000 0x40000000>;
+	};
+
+	backlight-lvds {
+		compatible = "pwm-backlight";
+		pwms = <&pwm4 0 5000000>;
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <6>;
+		power-supply = <&reg_3p3v>;
+	};
+
+	reg_1p8v: regulator-1p8v {
+		compatible = "regulator-fixed";
+		regulator-name = "1P8V";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-always-on;
+	};
+
+	reg_3p3v: regulator-3p3v {
+		compatible = "regulator-fixed";
+		regulator-name = "3P3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+	};
+
+	reg_can1_3v3: regulator-can1-3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "can1-3v3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		gpio = <&gpio4 27 GPIO_ACTIVE_LOW>;
+	};
+
+	reg_can2_3v3: regulator-can2-3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "can2-3v3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		gpio = <&gpio4 24 GPIO_ACTIVE_LOW>;
+	};
+
+	reg_usb_otg1_vbus: regulator-usb-otg1-vbus {
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_usbotg1_vbus>;
+		compatible = "regulator-fixed";
+		regulator-name = "usb_otg1_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	reg_wlan: regulator-wlan {
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_reg_wlan>;
+		compatible = "regulator-fixed";
+		clocks = <&clks IMX6SX_CLK_CKO>;
+		clock-names = "slow";
+		regulator-name = "wlan-en";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		startup-delay-us = <70000>;
+		gpio = <&gpio7 6 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	sound {
+		compatible = "fsl,imx-audio-sgtl5000";
+		model = "imx6sx-nitrogen6sx-sgtl5000";
+		cpu-dai = <&ssi1>;
+		audio-codec = <&codec>;
+		audio-routing =
+			"MIC_IN", "Mic Jack",
+			"Mic Jack", "Mic Bias",
+			"Headphone Jack", "HP_OUT";
+		mux-int-port = <1>;
+		mux-ext-port = <5>;
+	};
+};
+
+&audmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_audmux>;
+	status = "okay";
+};
+
+&ecspi1 {
+	fsl,spi-num-chipselects = <1>;
+	cs-gpios = <&gpio2 16 GPIO_ACTIVE_LOW>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi1>;
+	status = "okay";
+
+	flash: m25p80@0 {
+		compatible = "microchip,sst25vf016b";
+		spi-max-frequency = <20000000>;
+		reg = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		partition@0 {
+			label = "U-Boot";
+			reg = <0x0 0xc0000>;
+			read-only;
+		};
+
+		partition@c0000 {
+			label = "env";
+			reg = <0xc0000 0x2000>;
+			read-only;
+		};
+
+		partition@c2000 {
+			label = "Kernel";
+			reg = <0xc2000 0x11e000>;
+		};
+
+		partition@1e0000 {
+			label = "M4";
+			reg = <0x1e0000 0x20000>;
+		};
+	};
+};
+
+&fec1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet1>;
+	phy-mode = "rgmii";
+	phy-handle = <&ethphy1>;
+	phy-supply = <&reg_3p3v>;
+	fsl,magic-packet;
+	status = "okay";
+
+	mdio {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ethphy1: ethernet-phy@4 {
+			reg = <4>;
+		};
+
+		ethphy2: ethernet-phy@5 {
+			reg = <5>;
+		};
+	};
+};
+
+&fec2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet2>;
+	phy-mode = "rgmii";
+	phy-handle = <&ethphy2>;
+	phy-supply = <&reg_3p3v>;
+	fsl,magic-packet;
+	status = "okay";
+};
+
+&flexcan1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_flexcan1>;
+	xceiver-supply = <&reg_can1_3v3>;
+	status = "okay";
+};
+
+&flexcan2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_flexcan2>;
+	xceiver-supply = <&reg_can2_3v3>;
+	status = "okay";
+};
+
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	codec: sgtl5000@0a {
+		compatible = "fsl,sgtl5000";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_sgtl5000>;
+		reg = <0x0a>;
+		clocks = <&clks IMX6SX_CLK_CKO2>;
+		VDDA-supply = <&reg_1p8v>;
+		VDDIO-supply = <&reg_1p8v>;
+		VDDD-supply = <&reg_1p8v>;
+		assigned-clocks = <&clks IMX6SX_CLK_CKO2_SEL>,
+				  <&clks IMX6SX_CLK_CKO2>;
+		assigned-clock-parents = <&clks IMX6SX_CLK_OSC>;
+		assigned-clock-rates = <0>, <24000000>;
+	};
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+};
+
+&i2c3 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+};
+
+&lcdif1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_lcdif1>;
+	lcd-supply = <&reg_3p3v>;
+	display = <&display0>;
+	status = "okay";
+
+	display0: display0 {
+		bits-per-pixel = <16>;
+		bus-width = <24>;
+
+		display-timings {
+			native-mode = <&t_lcd>;
+			t_lcd: t_lcd_default {
+				clock-frequency = <74160000>;
+				hactive = <1280>;
+				vactive = <720>;
+				hback-porch = <220>;
+				hfront-porch = <110>;
+				vback-porch = <20>;
+				vfront-porch = <5>;
+				hsync-len = <40>;
+				vsync-len = <5>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+		};
+	};
+};
+
+&pcie {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pcie>;
+	reset-gpio = <&gpio4 10 GPIO_ACTIVE_HIGH>;
+	status = "okay";
+};
+
+&pwm4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm4>;
+	status = "okay";
+};
+
+&ssi1 {
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart3>;
+	fsl,uart-has-rtscts;
+	status = "okay";
+};
+
+&uart5 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart5>;
+	status = "okay";
+};
+
+&usbotg1 {
+	vbus-supply = <&reg_usb_otg1_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg1>;
+	status = "okay";
+};
+
+&usbotg2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg2>;
+	dr_mode = "host";
+	disable-over-current;
+	reset-gpios = <&gpio4 26 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
+&usdhc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc2>;
+	bus-width = <4>;
+	cd-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>;
+	keep-power-in-suspend;
+	wakeup-source;
+	status = "okay";
+};
+
+&usdhc3 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc3>;
+	bus-width = <4>;
+	non-removable;
+	keep-power-in-suspend;
+	vmmc-supply = <&reg_wlan>;
+	cap-power-off-card;
+	cap-sdio-irq;
+	status = "okay";
+
+	brcmf: bcrmf@1 {
+		reg = <1>;
+		compatible = "brcm,bcm4329-fmac";
+		interrupt-parent = <&gpio7>;
+		interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
+	};
+
+	wlcore: wlcore@2 {
+		compatible = "ti,wl1271";
+		reg = <2>;
+		interrupt-parent = <&gpio7>;
+		interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
+		ref-clock-frequency = <38400000>;
+	};
+};
+
+&usdhc4 {
+	pinctrl-names = "default", "state_100mhz", "state_200mhz";
+	pinctrl-0 = <&pinctrl_usdhc4_50mhz>;
+	pinctrl-1 = <&pinctrl_usdhc4_100mhz>;
+	pinctrl-2 = <&pinctrl_usdhc4_200mhz>;
+	bus-width = <8>;
+	non-removable;
+	vmmc-supply = <&reg_1p8v>;
+	keep-power-in-suspend;
+	status = "okay";
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	pinctrl_audmux: audmuxgrp {
+		fsl,pins = <
+			MX6SX_PAD_SD1_DATA0__AUDMUX_AUD5_RXD	0x1b0b0
+			MX6SX_PAD_SD1_DATA1__AUDMUX_AUD5_TXC	0x1b0b0
+			MX6SX_PAD_SD1_DATA2__AUDMUX_AUD5_TXFS	0x1b0b0
+			MX6SX_PAD_SD1_DATA3__AUDMUX_AUD5_TXD	0x1b0b0
+		>;
+	};
+
+	pinctrl_ecspi1: ecspi1grp {
+		fsl,pins = <
+			MX6SX_PAD_KEY_COL1__ECSPI1_MISO		0x100b1
+			MX6SX_PAD_KEY_ROW0__ECSPI1_MOSI		0x100b1
+			MX6SX_PAD_KEY_COL0__ECSPI1_SCLK		0x100b1
+			MX6SX_PAD_KEY_ROW1__GPIO2_IO_16		0x0b0b1
+		>;
+	};
+
+	pinctrl_enet1: enet1grp {
+		fsl,pins = <
+			MX6SX_PAD_ENET1_MDIO__ENET1_MDIO	0x1b0b0
+			MX6SX_PAD_ENET1_MDC__ENET1_MDC		0x1b0b0
+			MX6SX_PAD_RGMII1_TD0__ENET1_TX_DATA_0	0x30b1
+			MX6SX_PAD_RGMII1_TD1__ENET1_TX_DATA_1	0x30b1
+			MX6SX_PAD_RGMII1_TD2__ENET1_TX_DATA_2	0x30b1
+			MX6SX_PAD_RGMII1_TD3__ENET1_TX_DATA_3	0x30b1
+			MX6SX_PAD_RGMII1_TXC__ENET1_RGMII_TXC	0x30b1
+			MX6SX_PAD_RGMII1_TX_CTL__ENET1_TX_EN	0x30b1
+			MX6SX_PAD_RGMII1_RD0__ENET1_RX_DATA_0	0x3081
+			MX6SX_PAD_RGMII1_RD1__ENET1_RX_DATA_1	0x3081
+			MX6SX_PAD_RGMII1_RX_CTL__ENET1_RX_EN	0x3081
+			MX6SX_PAD_RGMII1_RD2__ENET1_RX_DATA_2	0x3081
+			MX6SX_PAD_RGMII1_RD3__ENET1_RX_DATA_3	0x3081
+			MX6SX_PAD_RGMII1_RXC__ENET1_RX_CLK	0x3081
+			MX6SX_PAD_ENET2_CRS__GPIO2_IO_7		0xb0b0
+			MX6SX_PAD_ENET1_RX_CLK__GPIO2_IO_4	0xb0b0
+			MX6SX_PAD_ENET1_TX_CLK__GPIO2_IO_5	0xb0b0
+		>;
+	};
+
+	pinctrl_enet2: enet2grp {
+		fsl,pins = <
+			MX6SX_PAD_RGMII2_TD0__ENET2_TX_DATA_0	0x30b1
+			MX6SX_PAD_RGMII2_TD1__ENET2_TX_DATA_1	0x30b1
+			MX6SX_PAD_RGMII2_TD2__ENET2_TX_DATA_2	0x30b1
+			MX6SX_PAD_RGMII2_TD3__ENET2_TX_DATA_3	0x30b1
+			MX6SX_PAD_RGMII2_TXC__ENET2_RGMII_TXC	0x30b1
+			MX6SX_PAD_RGMII2_TX_CTL__ENET2_TX_EN	0x30b1
+			MX6SX_PAD_RGMII2_RD0__ENET2_RX_DATA_0	0x3081
+			MX6SX_PAD_RGMII2_RD1__ENET2_RX_DATA_1	0x3081
+			MX6SX_PAD_RGMII2_RX_CTL__ENET2_RX_EN	0x3081
+			MX6SX_PAD_RGMII2_RD2__ENET2_RX_DATA_2	0x3081
+			MX6SX_PAD_RGMII2_RD3__ENET2_RX_DATA_3	0x3081
+			MX6SX_PAD_RGMII2_RXC__ENET2_RX_CLK	0x3081
+			MX6SX_PAD_ENET2_COL__GPIO2_IO_6		0xb0b0
+			MX6SX_PAD_ENET2_RX_CLK__GPIO2_IO_8	0xb0b0
+			MX6SX_PAD_ENET2_TX_CLK__GPIO2_IO_9	0xb0b0
+		>;
+	};
+
+	pinctrl_flexcan1: flexcan1grp {
+		fsl,pins = <
+			MX6SX_PAD_QSPI1B_DQS__CAN1_TX		0x1b0b0
+			MX6SX_PAD_QSPI1A_SS1_B__CAN1_RX		0x1b0b0
+			MX6SX_PAD_QSPI1B_DATA3__GPIO4_IO_27	0x1b0b0
+			MX6SX_PAD_QSPI1B_DATA3__GPIO4_IO_27	0x0b0b0
+		>;
+	};
+
+	pinctrl_flexcan2: flexcan2grp {
+		fsl,pins = <
+			MX6SX_PAD_QSPI1A_DQS__CAN2_TX		0x1b0b0
+			MX6SX_PAD_QSPI1B_SS1_B__CAN2_RX		0x1b0b0
+			MX6SX_PAD_QSPI1B_DATA0__GPIO4_IO_24	0x0b0b0
+		>;
+	};
+
+	pinctrl_hog: hoggrp {
+		fsl,pins = <
+			MX6SX_PAD_NAND_CE0_B__GPIO4_IO_1	0x1b0b0
+			MX6SX_PAD_NAND_CLE__GPIO4_IO_3		0x1b0b0
+			MX6SX_PAD_NAND_RE_B__GPIO4_IO_12	0x1b0b0
+			MX6SX_PAD_NAND_WE_B__GPIO4_IO_14	0x1b0b0
+			MX6SX_PAD_NAND_WP_B__GPIO4_IO_15	0x1b0b0
+			MX6SX_PAD_NAND_READY_B__GPIO4_IO_13	0x1b0b0
+			MX6SX_PAD_QSPI1A_DATA0__GPIO4_IO_16	0x1b0b0
+			MX6SX_PAD_QSPI1A_DATA1__GPIO4_IO_17	0x1b0b0
+			MX6SX_PAD_QSPI1A_DATA2__GPIO4_IO_18	0x1b0b0
+			MX6SX_PAD_QSPI1A_DATA3__GPIO4_IO_19	0x1b0b0
+			MX6SX_PAD_SD1_CMD__CCM_CLKO1		0x000b0
+			MX6SX_PAD_SD3_DATA5__GPIO7_IO_7		0x1b0b0
+			/* Test points */
+			MX6SX_PAD_NAND_DATA04__GPIO4_IO_8	0x1b0b0
+			MX6SX_PAD_QSPI1B_DATA1__GPIO4_IO_25	0x1b0b0
+		>;
+	};
+
+	pinctrl_i2c1: i2c1grp {
+		fsl,pins = <
+			MX6SX_PAD_GPIO1_IO00__I2C1_SCL		0x4001b8b1
+			MX6SX_PAD_GPIO1_IO01__I2C1_SDA		0x4001b8b1
+		>;
+	};
+
+	pinctrl_i2c2: i2c2grp {
+		fsl,pins = <
+			MX6SX_PAD_GPIO1_IO02__I2C2_SCL		0x4001b8b1
+			MX6SX_PAD_GPIO1_IO03__I2C2_SDA		0x4001b8b1
+		>;
+	};
+
+	pinctrl_i2c3: i2c3grp {
+		fsl,pins = <
+			MX6SX_PAD_KEY_COL4__I2C3_SCL		0x4001b8b1
+			MX6SX_PAD_KEY_ROW4__I2C3_SDA		0x4001b8b1
+		>;
+	};
+
+	pinctrl_lcdif1: lcdif1grp {
+		fsl,pins = <
+			MX6SX_PAD_LCD1_CLK__LCDIF1_CLK		0x4001b0b0
+			MX6SX_PAD_LCD1_ENABLE__LCDIF1_ENABLE	0x4001b0b0
+			MX6SX_PAD_LCD1_HSYNC__LCDIF1_HSYNC	0x4001b0b0
+			MX6SX_PAD_LCD1_VSYNC__LCDIF1_VSYNC	0x4001b0b0
+			MX6SX_PAD_LCD1_RESET__GPIO3_IO_27	0x4001b0b0
+			MX6SX_PAD_LCD1_DATA00__LCDIF1_DATA_0	0x4001b0b0
+			MX6SX_PAD_LCD1_DATA01__LCDIF1_DATA_1	0x4001b0b0
+			MX6SX_PAD_LCD1_DATA02__LCDIF1_DATA_2	0x4001b0b0
+			MX6SX_PAD_LCD1_DATA03__LCDIF1_DATA_3	0x4001b0b0
+			MX6SX_PAD_LCD1_DATA04__LCDIF1_DATA_4	0x4001b0b0
+			MX6SX_PAD_LCD1_DATA05__LCDIF1_DATA_5	0x4001b0b0
+			MX6SX_PAD_LCD1_DATA06__LCDIF1_DATA_6	0x4001b0b0
+			MX6SX_PAD_LCD1_DATA07__LCDIF1_DATA_7	0x4001b0b0
+			MX6SX_PAD_LCD1_DATA08__LCDIF1_DATA_8	0x4001b0b0
+			MX6SX_PAD_LCD1_DATA09__LCDIF1_DATA_9	0x4001b0b0
+			MX6SX_PAD_LCD1_DATA10__LCDIF1_DATA_10	0x4001b0b0
+			MX6SX_PAD_LCD1_DATA11__LCDIF1_DATA_11	0x4001b0b0
+			MX6SX_PAD_LCD1_DATA12__LCDIF1_DATA_12	0x4001b0b0
+			MX6SX_PAD_LCD1_DATA13__LCDIF1_DATA_13	0x4001b0b0
+			MX6SX_PAD_LCD1_DATA14__LCDIF1_DATA_14	0x4001b0b0
+			MX6SX_PAD_LCD1_DATA15__LCDIF1_DATA_15	0x4001b0b0
+			MX6SX_PAD_LCD1_DATA16__LCDIF1_DATA_16	0x4001b0b0
+			MX6SX_PAD_LCD1_DATA17__LCDIF1_DATA_17	0x4001b0b0
+			MX6SX_PAD_LCD1_DATA18__LCDIF1_DATA_18	0x4001b0b0
+			MX6SX_PAD_LCD1_DATA19__LCDIF1_DATA_19	0x4001b0b0
+			MX6SX_PAD_LCD1_DATA20__LCDIF1_DATA_20	0x4001b0b0
+			MX6SX_PAD_LCD1_DATA21__LCDIF1_DATA_21	0x4001b0b0
+			MX6SX_PAD_LCD1_DATA22__LCDIF1_DATA_22	0x4001b0b0
+			MX6SX_PAD_LCD1_DATA23__LCDIF1_DATA_23	0x4001b0b0
+		>;
+	};
+
+	pinctrl_pcie: pciegrp {
+		fsl,pins = <
+			MX6SX_PAD_NAND_DATA05__GPIO4_IO_9	0xb0b0
+			MX6SX_PAD_NAND_DATA06__GPIO4_IO_10	0xb0b0
+			MX6SX_PAD_NAND_DATA07__GPIO4_IO_11	0xb0b0
+		>;
+	};
+
+	pinctrl_pwm4: pwm4grp {
+		fsl,pins = <
+			MX6SX_PAD_GPIO1_IO13__PWM4_OUT		0x110b0
+		>;
+	};
+
+	pinctrl_reg_wlan: reg-wlangrp {
+		fsl,pins = <
+			MX6SX_PAD_SD3_DATA4__GPIO7_IO_6		0x1b0b0
+			MX6SX_PAD_GPIO1_IO11__CCM_CLKO1		0x000b0
+		>;
+	};
+
+	pinctrl_sgtl5000: sgtl5000grp {
+		fsl,pins = <
+			MX6SX_PAD_GPIO1_IO12__CCM_CLKO2		0x000b0
+			MX6SX_PAD_ENET1_COL__GPIO2_IO_0		0x1b0b0
+			MX6SX_PAD_ENET1_CRS__GPIO2_IO_1		0x1b0b0
+			MX6SX_PAD_QSPI1A_SS0_B__GPIO4_IO_22	0xb0b0
+		>;
+	};
+
+	pinctrl_uart1: uart1grp {
+		fsl,pins = <
+			MX6SX_PAD_GPIO1_IO04__UART1_TX		0x1b0b1
+			MX6SX_PAD_GPIO1_IO05__UART1_RX		0x1b0b1
+		>;
+	};
+
+	pinctrl_uart2: uart2grp {
+		fsl,pins = <
+			MX6SX_PAD_GPIO1_IO06__UART2_TX		0x1b0b1
+			MX6SX_PAD_GPIO1_IO07__UART2_RX		0x1b0b1
+		>;
+	};
+
+	pinctrl_uart3: uart3grp {
+		fsl,pins = <
+			MX6SX_PAD_QSPI1B_SS0_B__UART3_TX	0x1b0b1
+			MX6SX_PAD_QSPI1B_SCLK__UART3_RX		0x1b0b1
+		>;
+	};
+
+	pinctrl_uart5: uart5grp {
+		fsl,pins = <
+			MX6SX_PAD_KEY_COL3__UART5_TX		0x1b0b1
+			MX6SX_PAD_KEY_ROW3__UART5_RX		0x1b0b1
+			MX6SX_PAD_SD3_DATA6__UART3_RTS_B	0x1b0b1
+			MX6SX_PAD_SD3_DATA7__UART3_CTS_B	0x1b0b1
+		>;
+	};
+
+	pinctrl_usbotg1: usbotg1grp {
+		fsl,pins = <
+			MX6SX_PAD_GPIO1_IO08__USB_OTG1_OC	0x1b0b0
+			MX6SX_PAD_GPIO1_IO10__ANATOP_OTG1_ID	0x170b1
+		>;
+	};
+
+	pinctrl_usbotg1_vbus: usbotg1-vbusgrp {
+		fsl,pins = <
+			MX6SX_PAD_GPIO1_IO09__GPIO1_IO_9	0x1b0b0
+		>;
+	};
+
+	pinctrl_usbotg2: usbotg2grp {
+		fsl,pins = <
+			MX6SX_PAD_QSPI1B_DATA2__GPIO4_IO_26	0xb0b0
+		>;
+	};
+
+	pinctrl_usdhc2: usdhc2grp {
+		fsl,pins = <
+			MX6SX_PAD_SD2_CMD__USDHC2_CMD		0x17059
+			MX6SX_PAD_SD2_CLK__USDHC2_CLK		0x10059
+			MX6SX_PAD_SD2_DATA0__USDHC2_DATA0	0x17059
+			MX6SX_PAD_SD2_DATA1__USDHC2_DATA1	0x17059
+			MX6SX_PAD_SD2_DATA2__USDHC2_DATA2	0x17059
+			MX6SX_PAD_SD2_DATA3__USDHC2_DATA3	0x17059
+			MX6SX_PAD_KEY_COL2__GPIO2_IO_12		0x1b0b0
+		>;
+	};
+
+	pinctrl_usdhc3: usdhc3grp {
+		fsl,pins = <
+			MX6SX_PAD_SD3_CLK__USDHC3_CLK		0x10071
+			MX6SX_PAD_SD3_CMD__USDHC3_CMD		0x17071
+			MX6SX_PAD_SD3_DATA0__USDHC3_DATA0	0x17071
+			MX6SX_PAD_SD3_DATA1__USDHC3_DATA1	0x17071
+			MX6SX_PAD_SD3_DATA2__USDHC3_DATA2	0x17071
+			MX6SX_PAD_SD3_DATA3__USDHC3_DATA3	0x17071
+		>;
+	};
+
+	pinctrl_usdhc4_50mhz: usdhc4-50mhzgrp {
+		fsl,pins = <
+			MX6SX_PAD_SD4_CLK__USDHC4_CLK		0x10071
+			MX6SX_PAD_SD4_CMD__USDHC4_CMD		0x17071
+			MX6SX_PAD_SD4_RESET_B__USDHC4_RESET_B	0x17071
+			MX6SX_PAD_SD4_DATA0__USDHC4_DATA0	0x17071
+			MX6SX_PAD_SD4_DATA1__USDHC4_DATA1	0x17071
+			MX6SX_PAD_SD4_DATA2__USDHC4_DATA2	0x17071
+			MX6SX_PAD_SD4_DATA3__USDHC4_DATA3	0x17071
+			MX6SX_PAD_SD4_DATA4__USDHC4_DATA4	0x17071
+			MX6SX_PAD_SD4_DATA5__USDHC4_DATA5	0x17071
+			MX6SX_PAD_SD4_DATA6__USDHC4_DATA6	0x17071
+			MX6SX_PAD_SD4_DATA7__USDHC4_DATA7	0x17071
+		>;
+	};
+
+	pinctrl_usdhc4_100mhz: usdhc4-100mhzgrp {
+		fsl,pins = <
+			MX6SX_PAD_SD4_CLK__USDHC4_CLK		0x100b9
+			MX6SX_PAD_SD4_CMD__USDHC4_CMD		0x170b9
+			MX6SX_PAD_SD4_DATA0__USDHC4_DATA0	0x170b9
+			MX6SX_PAD_SD4_DATA1__USDHC4_DATA1	0x170b9
+			MX6SX_PAD_SD4_DATA2__USDHC4_DATA2	0x170b9
+			MX6SX_PAD_SD4_DATA3__USDHC4_DATA3	0x170b9
+			MX6SX_PAD_SD4_DATA4__USDHC4_DATA4	0x170b9
+			MX6SX_PAD_SD4_DATA5__USDHC4_DATA5	0x170b9
+			MX6SX_PAD_SD4_DATA6__USDHC4_DATA6	0x170b9
+			MX6SX_PAD_SD4_DATA7__USDHC4_DATA7	0x170b9
+		>;
+	};
+
+	pinctrl_usdhc4_200mhz: usdhc4-200mhzgrp {
+		fsl,pins = <
+			MX6SX_PAD_SD4_CLK__USDHC4_CLK		0x100f9
+			MX6SX_PAD_SD4_CMD__USDHC4_CMD		0x170f9
+			MX6SX_PAD_SD4_DATA0__USDHC4_DATA0	0x170f9
+			MX6SX_PAD_SD4_DATA1__USDHC4_DATA1	0x170f9
+			MX6SX_PAD_SD4_DATA2__USDHC4_DATA2	0x170f9
+			MX6SX_PAD_SD4_DATA3__USDHC4_DATA3	0x170f9
+			MX6SX_PAD_SD4_DATA4__USDHC4_DATA4	0x170f9
+			MX6SX_PAD_SD4_DATA5__USDHC4_DATA5	0x170f9
+			MX6SX_PAD_SD4_DATA6__USDHC4_DATA6	0x170f9
+			MX6SX_PAD_SD4_DATA7__USDHC4_DATA7	0x170f9
+		>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6sx-sdb.dts linux-libre-4.7-gnu/arch/arm/boot/dts/imx6sx-sdb.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6sx-sdb.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6sx-sdb.dts	2016-07-24 15:23:50.000000000 -0400
@@ -18,12 +18,14 @@
 		996000  1250000
 		792000  1175000
 		396000  1175000
+		198000  1175000
 		>;
 	fsl,soc-operating-points = <
 		/* ARM kHz      SOC uV */
 		996000	1250000
 		792000	1175000
 		396000	1175000
+		198000  1175000
 	>;
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6sx-sdb.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/imx6sx-sdb.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6sx-sdb.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6sx-sdb.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -254,6 +254,12 @@
 	status = "okay";
 };
 
+&sai1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_sai1>;
+	status = "disabled";
+};
+
 &ssi2 {
 	status = "okay";
 };
@@ -468,6 +474,16 @@
 			>;
 		};
 
+		pinctrl_sai1: sai1grp {
+			fsl,pins = <
+				MX6SX_PAD_CSI_DATA00__SAI1_TX_BCLK	0x130b0
+				MX6SX_PAD_CSI_DATA01__SAI1_TX_SYNC	0x130b0
+				MX6SX_PAD_CSI_HSYNC__SAI1_TX_DATA_0	0x120b0
+				MX6SX_PAD_CSI_VSYNC__SAI1_RX_DATA_0	0x130b0
+				MX6SX_PAD_CSI_PIXCLK__AUDMUX_MCLK	0x130b0
+			>;
+		};
+
 		pinctrl_uart1: uart1grp {
 			fsl,pins = <
 				MX6SX_PAD_GPIO1_IO04__UART1_TX		0x1b0b1
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6sx-sdb-sai.dts linux-libre-4.7-gnu/arch/arm/boot/dts/imx6sx-sdb-sai.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6sx-sdb-sai.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6sx-sdb-sai.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2016 NXP Semiconductors
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "imx6sx-sdb.dts"
+
+/ {
+	sound {
+		audio-cpu = <&sai1>;
+	};
+};
+
+&audmux {
+	/* pin conflict with sai */
+	status = "disabled";
+};
+
+&sai1 {
+	status = "okay";
+};
+
+&sdma {
+	gpr = <&gpr>;
+	/* SDMA event remap for SAI1 */
+	fsl,sdma-event-remap = <0 15 1>, <0 16 1>;
+};
+
+&ssi2 {
+	status = "disabled";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6ul-14x14-evk.dts linux-libre-4.7-gnu/arch/arm/boot/dts/imx6ul-14x14-evk.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6ul-14x14-evk.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6ul-14x14-evk.dts	2016-07-24 15:23:50.000000000 -0400
@@ -36,6 +36,45 @@
 			enable-active-high;
 		};
 	};
+
+	sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,name = "mx6ul-wm8960";
+		simple-audio-card,format = "i2s";
+		simple-audio-card,bitclock-master = <&dailink_master>;
+		simple-audio-card,frame-master = <&dailink_master>;
+		simple-audio-card,widgets =
+			"Microphone", "Mic Jack",
+			"Line", "Line In",
+			"Line", "Line Out",
+			"Speaker", "Speaker",
+			"Headphone", "Headphone Jack";
+		simple-audio-card,routing =
+			"Headphone Jack", "HP_L",
+			"Headphone Jack", "HP_R",
+			"Speaker", "SPK_LP",
+			"Speaker", "SPK_LN",
+			"Speaker", "SPK_RP",
+			"Speaker", "SPK_RN",
+			"LINPUT1", "Mic Jack",
+			"LINPUT3", "Mic Jack",
+			"RINPUT1", "Mic Jack",
+			"RINPUT2", "Mic Jack";
+
+		simple-audio-card,cpu {
+			sound-dai = <&sai2>;
+		};
+
+		dailink_master: simple-audio-card,codec {
+			sound-dai = <&codec>;
+			clocks = <&clks IMX6UL_CLK_SAI2>;
+		};
+	};
+};
+
+&clks {
+	assigned-clocks = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
+	assigned-clock-rates = <786432000>;
 };
 
 &cpu0 {
@@ -43,6 +82,20 @@
 	soc-supply = <&reg_soc>;
 };
 
+&i2c2 {
+	clock_frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+
+	codec: wm8960@1a {
+		#sound-dai-cells = <0>;
+		compatible = "wlf,wm8960";
+		reg = <0x1a>;
+		wlf,shared-lrclk;
+	};
+};
+
 &fec1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_enet1>;
@@ -86,6 +139,16 @@
 	};
 };
 
+&sai2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_sai2>;
+	assigned-clocks = <&clks IMX6UL_CLK_SAI2_SEL>,
+			  <&clks IMX6UL_CLK_SAI2>;
+	assigned-clock-parents = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
+	assigned-clock-rates = <0>, <12288000>;
+	status = "okay";
+};
+
 &snvs_poweroff {
 	status = "okay";
 };
@@ -272,6 +335,17 @@
 		>;
 	};
 
+	pinctrl_sai2: sai2grp {
+		fsl,pins = <
+			MX6UL_PAD_JTAG_TDI__SAI2_TX_BCLK	0x17088
+			MX6UL_PAD_JTAG_TDO__SAI2_TX_SYNC	0x17088
+			MX6UL_PAD_JTAG_TRST_B__SAI2_TX_DATA	0x11088
+			MX6UL_PAD_JTAG_TCK__SAI2_RX_DATA	0x11088
+			MX6UL_PAD_JTAG_TMS__SAI2_MCLK		0x17088
+			MX6UL_PAD_SNVS_TAMPER4__GPIO5_IO04	0x17059
+		>;
+	};
+
 	pinctrl_pwm1: pwm1grp {
 		fsl,pins = <
 			MX6UL_PAD_GPIO1_IO08__PWM1_OUT   0x110b0
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6ul.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/imx6ul.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6ul.dtsi	2016-05-15 19:23:08.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6ul.dtsi	2016-07-24 18:19:52.000000000 -0400
@@ -55,15 +55,15 @@
 			clock-latency = <61036>; /* two CLK32 periods */
 			operating-points = <
 				/* kHz	uV */
-				528000	1250000
-				396000	1150000
-				198000	1150000
+				528000	1175000
+				396000	1025000
+				198000	950000
 			>;
 			fsl,soc-operating-points = <
 				/* KHz	uV */
-				528000	1250000
-				396000	1150000
-				198000	1150000
+				528000	1175000
+				396000	1175000
+				198000	1175000
 			>;
 			clocks = <&clks IMX6UL_CLK_ARM>,
 				 <&clks IMX6UL_CLK_PLL2_BUS>,
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6ul-pico-hobbit.dts linux-libre-4.7-gnu/arch/arm/boot/dts/imx6ul-pico-hobbit.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6ul-pico-hobbit.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6ul-pico-hobbit.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,516 @@
+/*
+ * Copyright 2015 Technexion Ltd.
+ *
+ * Author: Wig Cheng  <wig.cheng@technexion.com>
+ *	   Richard Hu <richard.hu@technexion.com>
+ *	   Tapani Utriainen <tapani@technexion.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include "imx6ul.dtsi"
+
+/ {
+	model = "Technexion Pico i.MX6UL Board";
+	compatible = "technexion,imx6ul-pico-hobbit", "fsl,imx6ul";
+
+	memory {
+		reg = <0x80000000 0x10000000>;
+	};
+
+	chosen {
+		stdout-path = &uart6;
+	};
+
+	backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm3 0 5000000>;
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <6>;
+		status = "okay";
+	};
+
+	reg_2p5v: regulator-2p5v {
+		compatible = "regulator-fixed";
+		regulator-name = "2P5V";
+		regulator-min-microvolt = <2500000>;
+		regulator-max-microvolt = <2500000>;
+	};
+
+	reg_3p3v: regulator-3p3v {
+		compatible = "regulator-fixed";
+		regulator-name = "3P3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	reg_sd1_vmmc: regulator-sd1-vmmc {
+		compatible = "regulator-fixed";
+		regulator-name = "VSD_3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	reg_usb_otg_vbus: regulator-usb-otg-vbus {
+		compatible = "regulator-fixed";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_usb_otg1>;
+		regulator-name = "usb_otg_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&gpio1 6 0>;
+	};
+
+	sound {
+		compatible = "fsl,imx-audio-sgtl5000";
+		model = "imx6ul-sgtl5000";
+		audio-cpu = <&sai1>;
+		audio-codec = <&codec>;
+		audio-routing =
+			"LINE_IN", "Line In Jack",
+			"MIC_IN", "Mic Jack",
+			"Mic Jack", "Mic Bias",
+			"Headphone Jack", "HP_OUT";
+	};
+
+	sys_mclk: clock-sys-mclk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <24576000>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		hobbitled {
+			label = "hobbitled";
+			gpios = <&gpio1 29 GPIO_ACTIVE_LOW>;
+		};
+	};
+};
+
+&can1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_flexcan1>;
+	status = "okay";
+};
+
+&can2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_flexcan2>;
+	status = "okay";
+};
+
+&clks {
+	assigned-clocks = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
+	assigned-clock-rates = <786432000>;
+};
+
+&fec2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet2>;
+	phy-mode = "rmii";
+	phy-handle = <&ethphy1>;
+	status = "okay";
+	phy-reset-gpios = <&gpio2 15 GPIO_ACTIVE_LOW>;
+	phy-reset-duration = <11>;
+
+	mdio {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ethphy1: ethernet-phy@1 {
+			compatible = "ethernet-phy-ieee802.3-c22";
+			reg = <1>;
+			max-speed = <100>;
+			interrupt-parent = <&gpio5>;
+			interrupts = <6 IRQ_TYPE_LEVEL_LOW 0>;
+		};
+	};
+};
+
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	pmic: pfuze3000@08 {
+		compatible = "fsl,pfuze3000";
+		reg = <0x08>;
+
+		regulators {
+			/* VDD_ARM_SOC_IN*/
+			sw1b_reg: sw1b {
+				regulator-min-microvolt = <700000>;
+				regulator-max-microvolt = <1475000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-ramp-delay = <6250>;
+			};
+
+			/* DRAM */
+			sw3a_reg: sw3 {
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <1650000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* DRAM */
+			vref_reg: vrefddr {
+				regulator-boot-on;
+				regulator-always-on;
+			};
+		};
+	};
+};
+
+&i2c2 {
+	clock_frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+
+	codec: sgtl5000@0a {
+		reg = <0x0a>;
+		compatible = "fsl,sgtl5000";
+		clocks = <&sys_mclk>;
+		VDDA-supply = <&reg_2p5v>;
+		VDDIO-supply = <&reg_3p3v>;
+	};
+};
+
+&i2c3 {
+	clock_frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+};
+
+&lcdif {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_lcdif_dat &pinctrl_lcdif_ctrl>;
+	display = <&display0>;
+	status = "okay";
+
+	display0: display0 {
+		bits-per-pixel = <32>;
+		bus-width = <24>;
+
+		display-timings {
+			native-mode = <&timing0>;
+
+			timing0: timing0 {
+				clock-frequency = <33200000>;
+				hactive = <800>;
+				vactive = <480>;
+				hfront-porch = <210>;
+				hback-porch = <46>;
+				hsync-len = <1>;
+				vback-porch = <22>;
+				vfront-porch = <23>;
+				vsync-len = <1>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+		};
+	};
+};
+
+&pwm3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm3>;
+	status = "okay";
+};
+
+&pwm7 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm7>;
+	status = "okay";
+};
+
+&pwm8 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm8>;
+	status = "okay";
+};
+
+&sai1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_sai1>;
+	status = "okay";
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart3>;
+	fsl,uart-has-rtscts;
+	status = "okay";
+};
+
+&uart6 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart6>;
+	status = "okay";
+};
+
+&usbotg1 {
+	vbus-supply = <&reg_usb_otg_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usb_otg1_id>;
+	dr_mode = "otg";
+	disable-over-current;
+	status = "okay";
+};
+
+&usbotg2 {
+	dr_mode = "host";
+	disable-over-current;
+	status = "okay";
+};
+
+&usdhc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc1>;
+	bus-width = <8>;
+	no-1-8-v;
+	non-removable;
+	keep-power-in-suspend;
+	status = "okay";
+};
+
+&usdhc2 {  /* Wifi SDIO */
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc2>;
+	no-1-8-v;
+	keep-power-in-suspend;
+	wakeup-source;
+	status = "okay";
+};
+
+&iomuxc {
+	pinctrl_enet2: enet2grp {
+		fsl,pins = <
+			MX6UL_PAD_ENET1_TX_DATA1__ENET2_MDIO	0x1b0b0
+			MX6UL_PAD_ENET1_TX_EN__ENET2_MDC	0x1b0b0
+			MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN	0x1b0b0
+			MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER	0x1b0b0
+			MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00	0x1b0b0
+			MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01	0x1b0b0
+			MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN	0x1b0b0
+			MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00	0x1b0b0
+			MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01	0x1b0b0
+			MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2	0x4001b031
+			MX6UL_PAD_SNVS_TAMPER6__GPIO5_IO06	0x800
+			MX6UL_PAD_UART4_TX_DATA__GPIO1_IO28	0x79
+		>;
+	};
+
+	pinctrl_flexcan1: flexcan1grp {
+		fsl,pins = <
+			MX6UL_PAD_ENET1_RX_DATA0__FLEXCAN1_TX	0x1b020
+			MX6UL_PAD_ENET1_RX_DATA1__FLEXCAN1_RX	0x1b020
+		>;
+	};
+
+	pinctrl_flexcan2: flexcan2grp {
+		fsl,pins = <
+			MX6UL_PAD_ENET1_TX_DATA0__FLEXCAN2_RX	0x1b020
+			MX6UL_PAD_ENET1_RX_EN__FLEXCAN2_TX	0x1b020
+		>;
+	};
+
+	pinctrl_i2c1: i2c1grp {
+		fsl,pins = <
+			MX6UL_PAD_GPIO1_IO02__I2C1_SCL		0x4001b8b0
+			MX6UL_PAD_GPIO1_IO03__I2C1_SDA		0x4001b8b0
+		>;
+	};
+
+	pinctrl_i2c2: i2c2grp {
+		fsl,pins = <
+			MX6UL_PAD_UART5_TX_DATA__I2C2_SCL	0x4001b8b0
+			MX6UL_PAD_UART5_RX_DATA__I2C2_SDA	0x4001b8b0
+		>;
+	};
+
+	pinctrl_i2c3: i2c3grp {
+		fsl,pins = <
+			MX6UL_PAD_UART1_TX_DATA__I2C3_SCL	0x4001b8b0
+			MX6UL_PAD_UART1_RX_DATA__I2C3_SDA	0x4001b8b0
+			>;
+	};
+
+	pinctrl_lcdif_dat: lcdifdatgrp {
+		fsl,pins = <
+			MX6UL_PAD_LCD_DATA00__LCDIF_DATA00	0x79
+			MX6UL_PAD_LCD_DATA01__LCDIF_DATA01	0x79
+			MX6UL_PAD_LCD_DATA02__LCDIF_DATA02	0x79
+			MX6UL_PAD_LCD_DATA03__LCDIF_DATA03	0x79
+			MX6UL_PAD_LCD_DATA04__LCDIF_DATA04	0x79
+			MX6UL_PAD_LCD_DATA05__LCDIF_DATA05	0x79
+			MX6UL_PAD_LCD_DATA06__LCDIF_DATA06	0x79
+			MX6UL_PAD_LCD_DATA07__LCDIF_DATA07	0x79
+			MX6UL_PAD_LCD_DATA08__LCDIF_DATA08	0x79
+			MX6UL_PAD_LCD_DATA09__LCDIF_DATA09	0x79
+			MX6UL_PAD_LCD_DATA10__LCDIF_DATA10	0x79
+			MX6UL_PAD_LCD_DATA11__LCDIF_DATA11	0x79
+			MX6UL_PAD_LCD_DATA12__LCDIF_DATA12	0x79
+			MX6UL_PAD_LCD_DATA13__LCDIF_DATA13	0x79
+			MX6UL_PAD_LCD_DATA14__LCDIF_DATA14	0x79
+			MX6UL_PAD_LCD_DATA15__LCDIF_DATA15	0x79
+			MX6UL_PAD_LCD_DATA16__LCDIF_DATA16	0x79
+			MX6UL_PAD_LCD_DATA17__LCDIF_DATA17	0x79
+			MX6UL_PAD_LCD_DATA18__LCDIF_DATA18	0x79
+			MX6UL_PAD_LCD_DATA19__LCDIF_DATA19	0x79
+			MX6UL_PAD_LCD_DATA20__LCDIF_DATA20	0x79
+			MX6UL_PAD_LCD_DATA21__LCDIF_DATA21	0x79
+			MX6UL_PAD_LCD_DATA22__LCDIF_DATA22	0x79
+			MX6UL_PAD_LCD_DATA23__LCDIF_DATA23	0x79
+		>;
+	};
+
+	pinctrl_lcdif_ctrl: lcdifctrlgrp {
+		fsl,pins = <
+			MX6UL_PAD_LCD_CLK__LCDIF_CLK		0x79
+			MX6UL_PAD_LCD_ENABLE__LCDIF_ENABLE	0x79
+			MX6UL_PAD_LCD_HSYNC__LCDIF_HSYNC	0x79
+			MX6UL_PAD_LCD_VSYNC__LCDIF_VSYNC	0x79
+			/* LCD reset */
+			MX6UL_PAD_SNVS_TAMPER9__GPIO5_IO09	0x79
+		>;
+	};
+
+	pinctrl_pwm3: pwm3grp {
+		fsl,pins = <
+			MX6UL_PAD_NAND_ALE__PWM3_OUT		0x110b0
+		>;
+	};
+
+	pinctrl_pwm7: pwm7grp {
+		fsl,pins = <
+			MX6UL_PAD_ENET1_TX_CLK__PWM7_OUT	0x110b0
+		>;
+	};
+
+	pinctrl_pwm8: pwm8grp {
+		fsl,pins = <
+			MX6UL_PAD_ENET1_RX_ER__PWM8_OUT		0x110b0
+		>;
+	};
+
+	pinctrl_sai1: sai1grp {
+		fsl,pins = <
+			MX6UL_PAD_CSI_DATA04__SAI1_TX_SYNC	0x1b0b0
+			MX6UL_PAD_CSI_DATA05__SAI1_TX_BCLK	0x1b0b0
+			MX6UL_PAD_CSI_DATA06__SAI1_RX_DATA	0x110b0
+			MX6UL_PAD_CSI_DATA07__SAI1_TX_DATA	0x1f0b8
+		>;
+	};
+
+	pinctrl_uart3: uart3grp {
+		fsl,pins = <
+			MX6UL_PAD_UART3_TX_DATA__UART3_DCE_TX	0x1b0b0
+			MX6UL_PAD_UART3_RX_DATA__UART3_DCE_RX	0x1b0b0
+			MX6UL_PAD_UART3_RTS_B__UART3_DCE_RTS	0x1b0b0
+			MX6UL_PAD_UART3_CTS_B__UART3_DCE_CTS	0x1b0b0
+		>;
+	};
+
+	pinctrl_uart5: uart5grp {
+		fsl,pins = <
+			MX6UL_PAD_GPIO1_IO04__UART5_DCE_TX	0x1b0b1
+			MX6UL_PAD_GPIO1_IO05__UART5_DCE_RX	0x1b0b1
+			MX6UL_PAD_GPIO1_IO08__UART5_DCE_RTS	0x1b0b1
+			MX6UL_PAD_GPIO1_IO09__UART5_DCE_CTS	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart6: uart6grp {
+		fsl,pins = <
+			MX6UL_PAD_CSI_MCLK__UART6_DCE_TX	0x1b0b1
+			MX6UL_PAD_CSI_PIXCLK__UART6_DCE_RX	0x1b0b1
+		>;
+	};
+
+	pinctrl_usb_otg1: usbotg1grp {
+		fsl,pins = <
+			MX6UL_PAD_GPIO1_IO06__GPIO1_IO06	0x10b0
+			>;
+	};
+
+	pinctrl_usb_otg1_id: usbotg1idgrp {
+		fsl,pins = <
+			MX6UL_PAD_GPIO1_IO00__ANATOP_OTG1_ID	0x17059
+		>;
+	};
+
+	pinctrl_usdhc1: usdhc1grp {
+		fsl,pins = <
+			MX6UL_PAD_SD1_CMD__USDHC1_CMD		0x17059
+			MX6UL_PAD_SD1_CLK__USDHC1_CLK		0x10071
+			MX6UL_PAD_SD1_DATA0__USDHC1_DATA0	0x17059
+			MX6UL_PAD_SD1_DATA1__USDHC1_DATA1	0x17059
+			MX6UL_PAD_SD1_DATA2__USDHC1_DATA2	0x17059
+			MX6UL_PAD_SD1_DATA3__USDHC1_DATA3	0x17059
+			MX6UL_PAD_UART1_RTS_B__USDHC1_CD_B	0x03029
+			MX6UL_PAD_NAND_READY_B__USDHC1_DATA4	0x17059
+			MX6UL_PAD_NAND_CE0_B__USDHC1_DATA5	0x17059
+			MX6UL_PAD_NAND_CE1_B__USDHC1_DATA6	0x17059
+			MX6UL_PAD_NAND_CLE__USDHC1_DATA7	0x17059
+		>;
+	};
+
+	pinctrl_usdhc2: usdhc2grp {
+		fsl,pins = <
+			MX6UL_PAD_NAND_WE_B__USDHC2_CMD		0x17059
+			MX6UL_PAD_NAND_RE_B__USDHC2_CLK		0x10059
+			MX6UL_PAD_NAND_DATA00__USDHC2_DATA0	0x17059
+			MX6UL_PAD_NAND_DATA01__USDHC2_DATA1	0x17059
+			MX6UL_PAD_NAND_DATA02__USDHC2_DATA2	0x17059
+			MX6UL_PAD_NAND_DATA03__USDHC2_DATA3	0x17059
+		>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6ul-tx6ul-0010.dts linux-libre-4.7-gnu/arch/arm/boot/dts/imx6ul-tx6ul-0010.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6ul-tx6ul-0010.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6ul-tx6ul-0010.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2015 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "imx6ul.dtsi"
+#include "imx6ul-tx6ul.dtsi"
+
+/ {
+	model = "Ka-Ro electronics TXUL-0010 Module";
+	compatible = "karo,imx6ul-tx6ul", "fsl,imx6ul";
+
+	aliases {
+		/delete-property/ mmc1;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6ul-tx6ul-0011.dts linux-libre-4.7-gnu/arch/arm/boot/dts/imx6ul-tx6ul-0011.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6ul-tx6ul-0011.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6ul-tx6ul-0011.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2015 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "imx6ul.dtsi"
+#include "imx6ul-tx6ul.dtsi"
+
+/ {
+	model = "Ka-Ro electronics TXUL-0011 Module";
+	compatible = "karo,imx6ul-tx6ul", "fsl,imx6ul";
+
+	aliases {
+		mmc0 = &usdhc2;
+		mmc1 = &usdhc1;
+	};
+};
+
+&gpmi {
+	status = "disabled";
+};
+
+&usdhc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc2>;
+	bus-width = <4>;
+	no-1-8-v;
+	non-removable;
+	fsl,wp-controller;
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6ul-tx6ul.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/imx6ul-tx6ul.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6ul-tx6ul.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6ul-tx6ul.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,973 @@
+/*
+ * Copyright 2015 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/pwm/pwm.h>
+
+/ {
+	aliases {
+		can0 = &can2;
+		can1 = &can1;
+		display = &display;
+		i2c0 = &i2c2;
+		i2c1 = &i2c_gpio;
+		i2c2 = &i2c1;
+		i2c3 = &i2c3;
+		i2c4 = &i2c4;
+		lcdif_23bit_pins_a = &pinctrl_disp0_1;
+		lcdif_24bit_pins_a = &pinctrl_disp0_2;
+		pwm0 = &pwm5;
+		reg_can_xcvr = &reg_can_xcvr;
+		serial2 = &uart5;
+		serial4 = &uart3;
+		spi0 = &ecspi2;
+		spi1 = &spi_gpio;
+		stk5led = &user_led;
+		usbh1 = &usbotg2;
+		usbotg = &usbotg1;
+	};
+
+	chosen {
+		stdout-path = &uart1;
+	};
+
+	memory {
+		reg = <0 0>; /* will be filled by U-Boot */
+	};
+
+	clocks {
+		mclk: mclk {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <26000000>;
+		};
+	};
+
+	backlight: backlight {
+		compatible = "pwm-backlight";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_lcd_rst>;
+		enable-gpios = <&gpio3 4 GPIO_ACTIVE_HIGH>;
+		pwms = <&pwm5 0 500000 PWM_POLARITY_INVERTED>;
+		power-supply = <&reg_lcd_pwr>;
+		/*
+		 * a poor man's way to create a 1:1 relationship between
+		 * the PWM value and the actual duty cycle
+		 */
+		brightness-levels = < 0  1  2  3  4  5  6  7  8  9
+				     10 11 12 13 14 15 16 17 18 19
+				     20 21 22 23 24 25 26 27 28 29
+				     30 31 32 33 34 35 36 37 38 39
+				     40 41 42 43 44 45 46 47 48 49
+				     50 51 52 53 54 55 56 57 58 59
+				     60 61 62 63 64 65 66 67 68 69
+				     70 71 72 73 74 75 76 77 78 79
+				     80 81 82 83 84 85 86 87 88 89
+				     90 91 92 93 94 95 96 97 98 99
+				    100>;
+		default-brightness-level = <50>;
+	};
+
+	i2c_gpio: i2c-gpio {
+		compatible = "i2c-gpio";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_i2c_gpio>;
+		gpios = <
+			&gpio5 1 GPIO_ACTIVE_HIGH /* SDA */
+			&gpio5 0 GPIO_ACTIVE_HIGH /* SCL */
+		>;
+		clock-frequency = <400000>;
+		status = "okay";
+
+		ds1339: rtc@68 {
+			compatible = "dallas,ds1339";
+			reg = <0x68>;
+			status = "disabled";
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		user_led: user {
+			label = "Heartbeat";
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_led>;
+			gpios = <&gpio5 9 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+
+	reg_3v3_etn: regulator-3v3etn {
+		compatible = "regulator-fixed";
+		regulator-name = "3V3_ETN";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_etnphy_power>;
+		gpio = <&gpio5 7 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	reg_2v5: regulator-2v5 {
+		compatible = "regulator-fixed";
+		regulator-name = "2V5";
+		regulator-min-microvolt = <2500000>;
+		regulator-max-microvolt = <2500000>;
+		regulator-always-on;
+	};
+
+	reg_3v3: regulator-3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+	};
+
+	reg_can_xcvr: regulator-canxcvr {
+		compatible = "regulator-fixed";
+		regulator-name = "CAN XCVR";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_flexcan_xcvr>;
+		gpio = <&gpio3 5 GPIO_ACTIVE_HIGH>;
+		enable-active-low;
+	};
+
+	reg_lcd_pwr: regulator-lcdpwr {
+		compatible = "regulator-fixed";
+		regulator-name = "LCD POWER";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_lcd_pwr>;
+		gpio = <&gpio5 4 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	reg_usbh1_vbus: regulator-usbh1vbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usbh1_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_usbh1_vbus &pinctrl_usbh1_oc>;
+		gpio = <&gpio1 2 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	reg_usbotg_vbus: regulator-usbotgvbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usbotg_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_usbotg_vbus &pinctrl_usbotg_oc>;
+		gpio = <&gpio1 26 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	spi_gpio: spi-gpio {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "spi-gpio";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_spi_gpio>;
+		gpio-mosi = <&gpio1 30 GPIO_ACTIVE_HIGH>;
+		gpio-miso = <&gpio1 31 GPIO_ACTIVE_HIGH>;
+		gpio-sck = <&gpio1 28 GPIO_ACTIVE_HIGH>;
+		num-chipselects = <2>;
+		cs-gpios = <
+			&gpio1 29 GPIO_ACTIVE_HIGH
+			&gpio1 10 GPIO_ACTIVE_HIGH
+		>;
+		status = "disabled";
+
+		spi@0 {
+			compatible = "spidev";
+			reg = <0>;
+			spi-max-frequency = <660000>;
+		};
+
+		spi@1 {
+			compatible = "spidev";
+			reg = <1>;
+			spi-max-frequency = <660000>;
+		};
+	};
+
+	sound {
+		compatible = "karo,imx6ul-tx6ul-sgtl5000",
+			     "simple-audio-card";
+		simple-audio-card,name = "imx6ul-tx6ul-sgtl5000-audio";
+		simple-audio-card,format = "i2s";
+		simple-audio-card,bitclock-master = <&codec_dai>;
+		simple-audio-card,frame-master = <&codec_dai>;
+		simple-audio-card,widgets =
+			"Microphone", "Mic Jack",
+			"Line", "Line In",
+			"Line", "Line Out",
+			"Headphone", "Headphone Jack";
+		simple-audio-card,routing =
+			"MIC_IN", "Mic Jack",
+			"Mic Jack", "Mic Bias",
+			"Headphone Jack", "HP_OUT";
+
+		cpu_dai: simple-audio-card,cpu {
+			sound-dai = <&sai2>;
+		};
+
+		codec_dai: simple-audio-card,codec {
+			sound-dai = <&sgtl5000>;
+		};
+	};
+};
+
+&can1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_flexcan1>;
+	xceiver-supply = <&reg_can_xcvr>;
+	status = "okay";
+};
+
+&can2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_flexcan2>;
+	xceiver-supply = <&reg_can_xcvr>;
+	status = "okay";
+};
+
+&ecspi2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi2>;
+	fsl,spi-num-chipselects = <2>;
+	cs-gpios = <
+		&gpio1 29 GPIO_ACTIVE_HIGH
+		&gpio1 10 GPIO_ACTIVE_HIGH
+	>;
+	status = "disabled";
+
+	spidev0: spi@0 {
+		compatible = "spidev";
+		reg = <0>;
+		spi-max-frequency = <60000000>;
+	};
+
+	spidev1: spi@1 {
+		compatible = "spidev";
+		reg = <1>;
+		spi-max-frequency = <60000000>;
+	};
+};
+
+&fec1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet1 &pinctrl_enet1_mdio &pinctrl_etnphy0_rst>;
+	phy-mode = "rmii";
+	phy-reset-gpios = <&gpio5 6 GPIO_ACTIVE_HIGH>;
+	phy-supply = <&reg_3v3_etn>;
+	phy-handle = <&etnphy0>;
+	status = "okay";
+
+	mdio {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		etnphy0: ethernet-phy@0 {
+			compatible = "ethernet-phy-ieee802.3-c22";
+			reg = <0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_etnphy0_int>;
+			interrupt-parent = <&gpio5>;
+			interrupts = <5 IRQ_TYPE_EDGE_FALLING>;
+			status = "okay";
+		};
+
+		etnphy1: ethernet-phy@2 {
+			compatible = "ethernet-phy-ieee802.3-c22";
+			reg = <2>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_etnphy1_int>;
+			interrupt-parent = <&gpio4>;
+			interrupts = <27 IRQ_TYPE_EDGE_FALLING>;
+			status = "okay";
+		};
+	};
+};
+
+&fec2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet2 &pinctrl_etnphy1_rst>;
+	phy-mode = "rmii";
+	phy-reset-gpios = <&gpio4 28 GPIO_ACTIVE_HIGH>;
+	phy-supply = <&reg_3v3_etn>;
+	phy-handle = <&etnphy1>;
+	status = "disabled";
+};
+
+&gpmi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gpmi_nand>;
+	nand-on-flash-bbt;
+	fsl,no-blockmark-swap;
+	status = "okay";
+};
+
+&i2c2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	clock-frequency = <400000>;
+	status = "okay";
+
+	sgtl5000: codec@0a {
+		compatible = "fsl,sgtl5000";
+		reg = <0x0a>;
+		#sound-dai-cells = <0>;
+		VDDA-supply = <&reg_2v5>;
+		VDDIO-supply = <&reg_3v3>;
+		clocks = <&mclk>;
+	};
+
+	polytouch: polytouch@38 {
+		compatible = "edt,edt-ft5x06";
+		reg = <0x38>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_edt_ft5x06>;
+		interrupt-parent = <&gpio5>;
+		interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
+		reset-gpios = <&gpio5 3 GPIO_ACTIVE_LOW>;
+		wake-gpios = <&gpio5 8 GPIO_ACTIVE_HIGH>;
+		wakeup-source;
+	};
+
+	touchscreen: touchscreen@48 {
+		compatible = "ti,tsc2007";
+		reg = <0x48>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_tsc2007>;
+		interrupt-parent = <&gpio3>;
+		interrupts = <26 IRQ_TYPE_NONE>;
+		gpios = <&gpio3 26 GPIO_ACTIVE_LOW>;
+		ti,x-plate-ohms = <660>;
+		wakeup-source;
+	};
+};
+
+&kpp {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_kpp>;
+	/* sample keymap */
+	/* row/col 0..3 are mapped to KPP row/col 4..7 */
+	linux,keymap = <
+		MATRIX_KEY(4, 4, KEY_POWER)
+		MATRIX_KEY(4, 5, KEY_KP0)
+		MATRIX_KEY(4, 6, KEY_KP1)
+		MATRIX_KEY(4, 7, KEY_KP2)
+		MATRIX_KEY(5, 4, KEY_KP3)
+		MATRIX_KEY(5, 5, KEY_KP4)
+		MATRIX_KEY(5, 6, KEY_KP5)
+		MATRIX_KEY(5, 7, KEY_KP6)
+		MATRIX_KEY(6, 4, KEY_KP7)
+		MATRIX_KEY(6, 5, KEY_KP8)
+		MATRIX_KEY(6, 6, KEY_KP9)
+	>;
+	status = "okay";
+};
+
+&lcdif {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_disp0_1>;
+	lcd-supply = <&reg_lcd_pwr>;
+	display = <&display>;
+	status = "okay";
+
+	display: display@di0 {
+		bits-per-pixel = <32>;
+		bus-width = <24>;
+		status = "okay";
+
+		display-timings {
+			VGA {
+				clock-frequency = <25200000>;
+				hactive = <640>;
+				vactive = <480>;
+				hback-porch = <48>;
+				hsync-len = <96>;
+				hfront-porch = <16>;
+				vback-porch = <31>;
+				vsync-len = <2>;
+				vfront-porch = <12>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <1>;
+			};
+
+			ETV570 {
+				clock-frequency = <25200000>;
+				hactive = <640>;
+				vactive = <480>;
+				hback-porch = <114>;
+				hsync-len = <30>;
+				hfront-porch = <16>;
+				vback-porch = <32>;
+				vsync-len = <3>;
+				vfront-porch = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <1>;
+			};
+
+			ET0350 {
+				clock-frequency = <6413760>;
+				hactive = <320>;
+				vactive = <240>;
+				hback-porch = <34>;
+				hsync-len = <34>;
+				hfront-porch = <20>;
+				vback-porch = <15>;
+				vsync-len = <3>;
+				vfront-porch = <4>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <1>;
+			};
+
+			ET0430 {
+				clock-frequency = <9009000>;
+				hactive = <480>;
+				vactive = <272>;
+				hback-porch = <2>;
+				hsync-len = <41>;
+				hfront-porch = <2>;
+				vback-porch = <2>;
+				vsync-len = <10>;
+				vfront-porch = <2>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+
+			ET0500 {
+				clock-frequency = <33264000>;
+				hactive = <800>;
+				vactive = <480>;
+				hback-porch = <88>;
+				hsync-len = <128>;
+				hfront-porch = <40>;
+				vback-porch = <33>;
+				vsync-len = <2>;
+				vfront-porch = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <1>;
+			};
+
+			ET0700 { /* same as ET0500 */
+				clock-frequency = <33264000>;
+				hactive = <800>;
+				vactive = <480>;
+				hback-porch = <88>;
+				hsync-len = <128>;
+				hfront-porch = <40>;
+				vback-porch = <33>;
+				vsync-len = <2>;
+				vfront-porch = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <1>;
+			};
+
+			ETQ570 {
+				clock-frequency = <6596040>;
+				hactive = <320>;
+				vactive = <240>;
+				hback-porch = <38>;
+				hsync-len = <30>;
+				hfront-porch = <30>;
+				vback-porch = <16>;
+				vsync-len = <3>;
+				vfront-porch = <4>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <1>;
+			};
+		};
+	};
+};
+
+&pwm5 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm5>;
+	#pwm-cells = <3>;
+	status = "okay";
+};
+
+&sai2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_sai2>;
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1 &pinctrl_uart1_rtscts>;
+	fsl,uart-has-rtscts;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2 &pinctrl_uart2_rtscts>;
+	fsl,uart-has-rtscts;
+	status = "okay";
+};
+
+&uart5 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart5 &pinctrl_uart5_rtscts>;
+	fsl,uart-has-rtscts;
+	status = "okay";
+};
+
+&usbotg1 {
+	vbus-supply = <&reg_usbotg_vbus>;
+	dr_mode = "peripheral";
+	disable-over-current;
+	status = "okay";
+};
+
+&usbotg2 {
+	vbus-supply = <&reg_usbh1_vbus>;
+	dr_mode = "host";
+	disable-over-current;
+	status = "okay";
+};
+
+&usdhc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc1 &pinctrl_usdhc1_cd>;
+	bus-width = <4>;
+	no-1-8-v;
+	cd-gpios = <&gpio4 14 GPIO_ACTIVE_LOW>;
+	fsl,wp-controller;
+	status = "okay";
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	pinctrl_hog: hoggrp {
+	};
+
+	pinctrl_led: ledgrp {
+		fsl,pins = <
+			MX6UL_PAD_SNVS_TAMPER9__GPIO5_IO09	0x0b0b0 /* LED */
+		>;
+	};
+
+	pinctrl_disp0_1: disp0grp-1 {
+		fsl,pins = <
+			MX6UL_PAD_LCD_CLK__LCDIF_CLK		0x10 /* LSCLK */
+			MX6UL_PAD_LCD_ENABLE__LCDIF_ENABLE	0x10 /* OE_ACD */
+			MX6UL_PAD_LCD_HSYNC__LCDIF_HSYNC	0x10 /* HSYNC */
+			MX6UL_PAD_LCD_VSYNC__LCDIF_VSYNC	0x10 /* VSYNC */
+			/* PAD DISP0_DAT0 is used for the Flexcan transceiver control on STK5-v5 */
+			MX6UL_PAD_LCD_DATA01__LCDIF_DATA01	0x10
+			MX6UL_PAD_LCD_DATA02__LCDIF_DATA02	0x10
+			MX6UL_PAD_LCD_DATA03__LCDIF_DATA03	0x10
+			MX6UL_PAD_LCD_DATA04__LCDIF_DATA04	0x10
+			MX6UL_PAD_LCD_DATA05__LCDIF_DATA05	0x10
+			MX6UL_PAD_LCD_DATA06__LCDIF_DATA06	0x10
+			MX6UL_PAD_LCD_DATA07__LCDIF_DATA07	0x10
+			MX6UL_PAD_LCD_DATA08__LCDIF_DATA08	0x10
+			MX6UL_PAD_LCD_DATA09__LCDIF_DATA09	0x10
+			MX6UL_PAD_LCD_DATA10__LCDIF_DATA10	0x10
+			MX6UL_PAD_LCD_DATA11__LCDIF_DATA11	0x10
+			MX6UL_PAD_LCD_DATA12__LCDIF_DATA12	0x10
+			MX6UL_PAD_LCD_DATA13__LCDIF_DATA13	0x10
+			MX6UL_PAD_LCD_DATA14__LCDIF_DATA14	0x10
+			MX6UL_PAD_LCD_DATA15__LCDIF_DATA15	0x10
+			MX6UL_PAD_LCD_DATA16__LCDIF_DATA16	0x10
+			MX6UL_PAD_LCD_DATA17__LCDIF_DATA17	0x10
+			MX6UL_PAD_LCD_DATA18__LCDIF_DATA18	0x10
+			MX6UL_PAD_LCD_DATA19__LCDIF_DATA19	0x10
+			MX6UL_PAD_LCD_DATA20__LCDIF_DATA20	0x10
+			MX6UL_PAD_LCD_DATA21__LCDIF_DATA21	0x10
+			MX6UL_PAD_LCD_DATA22__LCDIF_DATA22	0x10
+			MX6UL_PAD_LCD_DATA23__LCDIF_DATA23	0x10
+		>;
+	};
+
+	pinctrl_disp0_2: disp0grp-2 {
+		fsl,pins = <
+			MX6UL_PAD_LCD_CLK__LCDIF_CLK		0x10 /* LSCLK */
+			MX6UL_PAD_LCD_ENABLE__LCDIF_ENABLE	0x10 /* OE_ACD */
+			MX6UL_PAD_LCD_HSYNC__LCDIF_HSYNC	0x10 /* HSYNC */
+			MX6UL_PAD_LCD_VSYNC__LCDIF_VSYNC	0x10 /* VSYNC */
+			MX6UL_PAD_LCD_DATA00__LCDIF_DATA00	0x10
+			MX6UL_PAD_LCD_DATA01__LCDIF_DATA01	0x10
+			MX6UL_PAD_LCD_DATA02__LCDIF_DATA02	0x10
+			MX6UL_PAD_LCD_DATA03__LCDIF_DATA03	0x10
+			MX6UL_PAD_LCD_DATA04__LCDIF_DATA04	0x10
+			MX6UL_PAD_LCD_DATA05__LCDIF_DATA05	0x10
+			MX6UL_PAD_LCD_DATA06__LCDIF_DATA06	0x10
+			MX6UL_PAD_LCD_DATA07__LCDIF_DATA07	0x10
+			MX6UL_PAD_LCD_DATA08__LCDIF_DATA08	0x10
+			MX6UL_PAD_LCD_DATA09__LCDIF_DATA09	0x10
+			MX6UL_PAD_LCD_DATA10__LCDIF_DATA10	0x10
+			MX6UL_PAD_LCD_DATA11__LCDIF_DATA11	0x10
+			MX6UL_PAD_LCD_DATA12__LCDIF_DATA12	0x10
+			MX6UL_PAD_LCD_DATA13__LCDIF_DATA13	0x10
+			MX6UL_PAD_LCD_DATA14__LCDIF_DATA14	0x10
+			MX6UL_PAD_LCD_DATA15__LCDIF_DATA15	0x10
+			MX6UL_PAD_LCD_DATA16__LCDIF_DATA16	0x10
+			MX6UL_PAD_LCD_DATA17__LCDIF_DATA17	0x10
+			MX6UL_PAD_LCD_DATA18__LCDIF_DATA18	0x10
+			MX6UL_PAD_LCD_DATA19__LCDIF_DATA19	0x10
+			MX6UL_PAD_LCD_DATA20__LCDIF_DATA20	0x10
+			MX6UL_PAD_LCD_DATA21__LCDIF_DATA21	0x10
+			MX6UL_PAD_LCD_DATA22__LCDIF_DATA22	0x10
+			MX6UL_PAD_LCD_DATA23__LCDIF_DATA23	0x10
+		>;
+	};
+
+	pinctrl_ecspi2: ecspi2grp {
+		fsl,pins = <
+			MX6UL_PAD_UART4_RX_DATA__GPIO1_IO29	0x0b0b0 /* CSPI_SS */
+			MX6UL_PAD_JTAG_MOD__GPIO1_IO10		0x0b0b0 /* CSPI_SS */
+			MX6UL_PAD_UART5_TX_DATA__ECSPI2_MOSI	0x0b0b0 /* CSPI_MOSI */
+			MX6UL_PAD_UART5_RX_DATA__ECSPI2_MISO	0x0b0b0 /* CSPI_MISO */
+			MX6UL_PAD_UART4_TX_DATA__ECSPI2_SCLK	0x0b0b0 /* CSPI_SCLK */
+		>;
+	};
+
+	pinctrl_edt_ft5x06: edt-ft5x06grp {
+		fsl,pins = <
+			MX6UL_PAD_SNVS_TAMPER2__GPIO5_IO02	0x1b0b0 /* Interrupt */
+			MX6UL_PAD_SNVS_TAMPER3__GPIO5_IO03	0x1b0b0 /* Reset */
+			MX6UL_PAD_SNVS_TAMPER8__GPIO5_IO08	0x1b0b0 /* Wake */
+		>;
+	};
+
+	pinctrl_enet1: enet1grp {
+		fsl,pins = <
+			MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00	0x000b0
+			MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01	0x000b0
+			MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN	0x000b0
+			MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER	0x000b0
+			MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN	0x000b0
+			MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00	0x000b0
+			MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01	0x000b0
+			MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1	0x400000b1
+		>;
+	};
+
+	pinctrl_enet2: enet2grp {
+		fsl,pins = <
+			MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00	0x000b0
+			MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01	0x000b0
+			MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN	0x000b0
+			MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER	0x000b0
+			MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN	0x000b0
+			MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00	0x000b0
+			MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01	0x000b0
+			MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2	0x400000b1
+		>;
+	};
+
+	pinctrl_enet1_mdio: enet1-mdiogrp {
+		fsl,pins = <
+			MX6UL_PAD_GPIO1_IO07__ENET1_MDC		0x0b0b0
+			MX6UL_PAD_GPIO1_IO06__ENET1_MDIO	0x1b0b0
+		>;
+	};
+
+	pinctrl_etnphy_power: etnphy-pwrgrp {
+		fsl,pins = <
+			MX6UL_PAD_SNVS_TAMPER7__GPIO5_IO07	0x0b0b0 /* ETN PHY POWER */
+		>;
+	};
+
+	pinctrl_etnphy0_int: etnphy-intgrp-0 {
+		fsl,pins = <
+			MX6UL_PAD_SNVS_TAMPER5__GPIO5_IO05	0x0b0b0 /* ETN PHY INT */
+		>;
+	};
+
+	pinctrl_etnphy0_rst: etnphy-rstgrp-0 {
+		fsl,pins = <
+			MX6UL_PAD_SNVS_TAMPER6__GPIO5_IO06	0x0b0b0 /* ETN PHY RESET */
+		>;
+	};
+
+	pinctrl_etnphy1_int: etnphy-intgrp-1 {
+		fsl,pins = <
+			MX6UL_PAD_CSI_DATA06__GPIO4_IO27	0x0b0b0 /* ETN PHY INT */
+		>;
+	};
+
+	pinctrl_etnphy1_rst: etnphy-rstgrp-1 {
+		fsl,pins = <
+			MX6UL_PAD_CSI_DATA07__GPIO4_IO28	0x0b0b0 /* ETN PHY RESET */
+		>;
+	};
+
+	pinctrl_flexcan1: flexcan1grp {
+		fsl,pins = <
+			MX6UL_PAD_UART3_CTS_B__FLEXCAN1_TX	0x0b0b0
+			MX6UL_PAD_UART3_RTS_B__FLEXCAN1_RX	0x0b0b0
+		>;
+	};
+
+	pinctrl_flexcan2: flexcan2grp {
+		fsl,pins = <
+			MX6UL_PAD_UART2_CTS_B__FLEXCAN2_TX	0x0b0b0
+			MX6UL_PAD_UART2_RTS_B__FLEXCAN2_RX	0x0b0b0
+		>;
+	};
+
+	pinctrl_flexcan_xcvr: flexcan-xcvrgrp {
+		fsl,pins = <
+			MX6UL_PAD_LCD_DATA00__GPIO3_IO05	0x0b0b0 /* Flexcan XCVR enable */
+		>;
+	};
+
+	pinctrl_gpmi_nand: gpminandgrp {
+		fsl,pins = <
+			MX6UL_PAD_NAND_CLE__RAWNAND_CLE		0x0b0b1
+			MX6UL_PAD_NAND_ALE__RAWNAND_ALE		0x0b0b1
+			MX6UL_PAD_NAND_WP_B__RAWNAND_WP_B	0x0b0b1
+			MX6UL_PAD_NAND_READY_B__RAWNAND_READY_B	0x0b000
+			MX6UL_PAD_NAND_CE0_B__RAWNAND_CE0_B	0x0b0b1
+			MX6UL_PAD_NAND_RE_B__RAWNAND_RE_B	0x0b0b1
+			MX6UL_PAD_NAND_WE_B__RAWNAND_WE_B	0x0b0b1
+			MX6UL_PAD_NAND_DATA00__RAWNAND_DATA00	0x0b0b1
+			MX6UL_PAD_NAND_DATA01__RAWNAND_DATA01	0x0b0b1
+			MX6UL_PAD_NAND_DATA02__RAWNAND_DATA02	0x0b0b1
+			MX6UL_PAD_NAND_DATA03__RAWNAND_DATA03	0x0b0b1
+			MX6UL_PAD_NAND_DATA04__RAWNAND_DATA04	0x0b0b1
+			MX6UL_PAD_NAND_DATA05__RAWNAND_DATA05	0x0b0b1
+			MX6UL_PAD_NAND_DATA06__RAWNAND_DATA06	0x0b0b1
+			MX6UL_PAD_NAND_DATA07__RAWNAND_DATA07	0x0b0b1
+		>;
+	};
+
+	pinctrl_i2c_gpio: i2c-gpiogrp {
+		fsl,pins = <
+			MX6UL_PAD_SNVS_TAMPER0__GPIO5_IO00	0x4001b8b1 /* I2C SCL */
+			MX6UL_PAD_SNVS_TAMPER1__GPIO5_IO01	0x4001b8b1 /* I2C SDA */
+		>;
+	};
+
+	pinctrl_i2c2: i2c2grp {
+		fsl,pins = <
+			MX6UL_PAD_GPIO1_IO00__I2C2_SCL		0x4001b8b1
+			MX6UL_PAD_GPIO1_IO01__I2C2_SDA		0x4001b8b1
+		>;
+	};
+
+	pinctrl_kpp: kppgrp {
+		fsl,pins = <
+			MX6UL_PAD_ENET2_RX_DATA1__KPP_COL04	0x1b0b0
+			MX6UL_PAD_ENET2_TX_DATA0__KPP_COL05	0x1b0b0
+			MX6UL_PAD_ENET2_TX_EN__KPP_COL06	0x1b0b0
+			MX6UL_PAD_ENET2_RX_ER__KPP_COL07	0x1b0b0
+			MX6UL_PAD_ENET2_RX_DATA0__KPP_ROW04	0x1b0b0
+			MX6UL_PAD_ENET2_RX_EN__KPP_ROW05	0x1b0b0
+			MX6UL_PAD_ENET2_TX_DATA1__KPP_ROW06	0x1b0b0
+			MX6UL_PAD_ENET2_TX_CLK__KPP_ROW07	0x1b0b0
+		>;
+	};
+
+	pinctrl_lcd_pwr: lcd-pwrgrp {
+		fsl,pins = <
+			MX6UL_PAD_SNVS_TAMPER4__GPIO5_IO04	0x0b0b0 /* LCD Power Enable */
+		>;
+	};
+
+	pinctrl_lcd_rst: lcd-rstgrp {
+		fsl,pins = <
+			MX6UL_PAD_LCD_RESET__GPIO3_IO04	0x0b0b0 /* LCD Reset */
+		>;
+	};
+
+	pinctrl_pwm5: pwm5grp {
+		fsl,pins = <
+			MX6UL_PAD_NAND_DQS__PWM5_OUT		0x0b0b0
+		>;
+	};
+
+	pinctrl_sai2: sai2grp {
+		fsl,pins = <
+			MX6UL_PAD_JTAG_TCK__SAI2_RX_DATA	0x0b0b0 /* SSI1_RXD */
+			MX6UL_PAD_JTAG_TRST_B__SAI2_TX_DATA	0x0b0b0 /* SSI1_TXD */
+			MX6UL_PAD_JTAG_TDI__SAI2_TX_BCLK	0x0b0b0 /* SSI1_CLK */
+			MX6UL_PAD_JTAG_TDO__SAI2_TX_SYNC	0x0b0b0 /* SSI1_FS */
+		>;
+	};
+
+	pinctrl_spi_gpio: spi-gpiogrp {
+		fsl,pins = <
+			MX6UL_PAD_UART4_RX_DATA__GPIO1_IO29	0x0b0b0 /* CSPI_SS */
+			MX6UL_PAD_JTAG_MOD__GPIO1_IO10		0x0b0b0 /* CSPI_SS */
+			MX6UL_PAD_UART5_TX_DATA__GPIO1_IO30	0x0b0b0 /* CSPI_MOSI */
+			MX6UL_PAD_UART5_RX_DATA__GPIO1_IO31	0x0b0b0 /* CSPI_MISO */
+			MX6UL_PAD_UART4_TX_DATA__GPIO1_IO28	0x0b0b0 /* CSPI_SCLK */
+		>;
+	};
+
+	pinctrl_tsc2007: tsc2007grp {
+		fsl,pins = <
+			MX6UL_PAD_JTAG_TMS__GPIO1_IO11		0x1b0b0 /* Interrupt */
+		>;
+	};
+
+	pinctrl_uart1: uart1grp {
+		fsl,pins = <
+			MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX	0x0b0b0
+			MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX	0x0b0b0
+		>;
+	};
+
+	pinctrl_uart1_rtscts: uart1-rtsctsgrp {
+		fsl,pins = <
+			MX6UL_PAD_UART1_RTS_B__UART1_DCE_RTS	0x0b0b0
+			MX6UL_PAD_UART1_CTS_B__UART1_DCE_CTS	0x0b0b0
+		>;
+	};
+
+	pinctrl_uart2: uart2grp {
+		fsl,pins = <
+			MX6UL_PAD_UART2_TX_DATA__UART2_DCE_TX	0x0b0b0
+			MX6UL_PAD_UART2_RX_DATA__UART2_DCE_RX	0x0b0b0
+		>;
+	};
+
+	pinctrl_uart2_rtscts: uart2-rtsctsgrp {
+		fsl,pins = <
+			MX6UL_PAD_UART3_RX_DATA__UART2_DCE_RTS	0x0b0b0
+			MX6UL_PAD_UART3_TX_DATA__UART2_DCE_CTS	0x0b0b0
+		>;
+	};
+
+	pinctrl_uart5: uart5grp {
+		fsl,pins = <
+			MX6UL_PAD_GPIO1_IO04__UART5_DCE_TX	0x0b0b0
+			MX6UL_PAD_GPIO1_IO05__UART5_DCE_RX	0x0b0b0
+		>;
+	};
+
+	pinctrl_uart5_rtscts: uart5-rtsctsgrp {
+		fsl,pins = <
+			MX6UL_PAD_GPIO1_IO08__UART5_DCE_RTS	0x0b0b0
+			MX6UL_PAD_GPIO1_IO09__UART5_DCE_CTS	0x0b0b0
+		>;
+	};
+
+	pinctrl_usbh1_oc: usbh1-ocgrp {
+		fsl,pins = <
+			MX6UL_PAD_GPIO1_IO03__GPIO1_IO03	0x17059 /* USBH1_OC */
+		>;
+	};
+
+	pinctrl_usbh1_vbus: usbh1-vbusgrp {
+		fsl,pins = <
+			MX6UL_PAD_GPIO1_IO02__GPIO1_IO02	0x0b0b0 /* USBH1_VBUSEN */
+		>;
+	};
+
+	pinctrl_usbotg_oc: usbotg-ocgrp {
+		fsl,pins = <
+			MX6UL_PAD_UART3_RTS_B__GPIO1_IO27	0x17059 /* USBOTG_OC */
+		>;
+	};
+
+	pinctrl_usbotg_vbus: usbotg-vbusgrp {
+		fsl,pins = <
+			MX6UL_PAD_UART3_CTS_B__GPIO1_IO26	0x1b0b0 /* USBOTG_VBUSEN */
+		>;
+	};
+
+	pinctrl_usdhc1: usdhc1grp {
+		fsl,pins = <
+			MX6UL_PAD_SD1_CMD__USDHC1_CMD		0x070b1
+			MX6UL_PAD_SD1_CLK__USDHC1_CLK		0x07099
+			MX6UL_PAD_SD1_DATA0__USDHC1_DATA0	0x070b1
+			MX6UL_PAD_SD1_DATA1__USDHC1_DATA1	0x070b1
+			MX6UL_PAD_SD1_DATA2__USDHC1_DATA2	0x070b1
+			MX6UL_PAD_SD1_DATA3__USDHC1_DATA3	0x070b1
+		>;
+	};
+
+	pinctrl_usdhc1_cd: usdhc1cdgrp {
+		fsl,pins = <
+			MX6UL_PAD_NAND_CE1_B__GPIO4_IO14	0x170b0 /* SD1 CD */
+		>;
+	};
+
+	pinctrl_usdhc2: usdhc2grp {
+		fsl,pins = <
+			MX6UL_PAD_NAND_WE_B__USDHC2_CMD		0x070b1
+			MX6UL_PAD_NAND_RE_B__USDHC2_CLK		0x070b1
+			MX6UL_PAD_NAND_DATA00__USDHC2_DATA0	0x070b1
+			MX6UL_PAD_NAND_DATA01__USDHC2_DATA1	0x070b1
+			MX6UL_PAD_NAND_DATA02__USDHC2_DATA2	0x070b1
+			MX6UL_PAD_NAND_DATA03__USDHC2_DATA3	0x070b1
+			/* eMMC RESET */
+			MX6UL_PAD_NAND_ALE__USDHC2_RESET_B	0x170b0
+		>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx6ul-tx6ul-mainboard.dts linux-libre-4.7-gnu/arch/arm/boot/dts/imx6ul-tx6ul-mainboard.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx6ul-tx6ul-mainboard.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx6ul-tx6ul-mainboard.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,271 @@
+/*
+ * Copyright 2015 Lothar Waßmann <LW@KARO-electronics.de>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "imx6ul.dtsi"
+#include "imx6ul-tx6ul.dtsi"
+
+/ {
+	model = "Ka-Ro electronics TXUL-0010 Module on TXUL Mainboard";
+	compatible = "karo,imx6ul-tx6ul", "fsl,imx6ul";
+
+	aliases {
+		lcdif_24bit_pins_a = &pinctrl_disp0_3;
+		mmc0 = &usdhc1;
+		/delete-property/ mmc1;
+		serial2 = &uart3;
+		serial4 = &uart5;
+	};
+	/delete-node/ sound;
+};
+
+&can1 {
+	xceiver-supply = <&reg_3v3>;
+};
+
+&can2 {
+	xceiver-supply = <&reg_3v3>;
+};
+
+&ds1339 {
+	status = "disabled";
+};
+
+&fec1 {
+	pinctrl-0 = <&pinctrl_enet1 &pinctrl_etnphy0_rst>;
+	/delete-node/ mdio;
+};
+
+&fec2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet2 &pinctrl_enet2_mdio &pinctrl_etnphy1_rst>;
+	phy-mode = "rmii";
+	phy-reset-gpios = <&gpio4 28 GPIO_ACTIVE_HIGH>;
+	phy-supply = <&reg_3v3_etn>;
+	phy-handle = <&etnphy1>;
+	status = "okay";
+
+	mdio {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		etnphy0: ethernet-phy@0 {
+			compatible = "ethernet-phy-ieee802.3-c22";
+			reg = <0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_etnphy0_int>;
+			interrupt-parent = <&gpio5>;
+			interrupts = <5 IRQ_TYPE_EDGE_FALLING>;
+			interrupts-extended = <&gpio5 5 IRQ_TYPE_EDGE_FALLING>;
+			status = "okay";
+		};
+
+		etnphy1: ethernet-phy@2 {
+			compatible = "ethernet-phy-ieee802.3-c22";
+			reg = <2>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_etnphy1_int>;
+			interrupt-parent = <&gpio4>;
+			interrupts = <27 IRQ_TYPE_EDGE_FALLING>;
+			interrupts-extended = <&gpio4 27 IRQ_TYPE_EDGE_FALLING>;
+			status = "okay";
+		};
+	};
+};
+
+&i2c_gpio {
+	status = "disabled";
+};
+
+&i2c2 {
+	/delete-node/ codec@0a;
+	/delete-node/ touchscreen@48;
+
+	rtc: mcp7940x@6f {
+		compatible = "microchip,mcp7940x";
+		reg = <0x6f>;
+	};
+};
+
+&kpp {
+	status = "disabled";
+};
+
+&lcdif {
+	pinctrl-0 = <&pinctrl_disp0_3>;
+};
+
+&reg_usbotg_vbus{
+	status = "disabled";
+};
+
+&usdhc1 {
+	pinctrl-0 = <&pinctrl_usdhc1>;
+	non-removable;
+	/delete-property/ cd-gpios;
+	cap-sdio-irq;
+};
+
+&uart1 {
+	pinctrl-0 = <&pinctrl_uart1>;
+	/delete-property/ fsl,uart-has-rtscts;
+};
+
+&uart2 {
+	pinctrl-0 = <&pinctrl_uart2>;
+	/delete-property/ fsl,uart-has-rtscts;
+	status = "okay";
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart3>;
+	status = "okay";
+};
+
+&uart4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart4>;
+	status = "okay";
+};
+
+&uart5 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart5>;
+	status = "okay";
+};
+
+&uart6 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart6>;
+	status = "okay";
+};
+
+&uart7 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart7>;
+	status = "okay";
+};
+
+&uart8 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart8>;
+	status = "disabled"; /* conflicts with LCDIF */
+};
+
+&iomuxc {
+	hoggrp {
+		fsl,pins = <
+			MX6UL_PAD_CSI_DATA01__GPIO4_IO22	0x0b0b0 /* WLAN_RESET */
+		>;
+	};
+
+	pinctrl_disp0_3: disp0grp-3 {
+		fsl,pins = <
+			MX6UL_PAD_LCD_CLK__LCDIF_CLK		0x10 /* LSCLK */
+			MX6UL_PAD_LCD_ENABLE__LCDIF_ENABLE	0x10 /* OE_ACD */
+			MX6UL_PAD_LCD_HSYNC__LCDIF_HSYNC	0x10 /* HSYNC */
+			MX6UL_PAD_LCD_VSYNC__LCDIF_VSYNC	0x10 /* VSYNC */
+			MX6UL_PAD_LCD_DATA02__LCDIF_DATA02	0x10
+			MX6UL_PAD_LCD_DATA03__LCDIF_DATA03	0x10
+			MX6UL_PAD_LCD_DATA04__LCDIF_DATA04	0x10
+			MX6UL_PAD_LCD_DATA05__LCDIF_DATA05	0x10
+			MX6UL_PAD_LCD_DATA06__LCDIF_DATA06	0x10
+			MX6UL_PAD_LCD_DATA07__LCDIF_DATA07	0x10
+			/* LCD_DATA08..09 not wired */
+			MX6UL_PAD_LCD_DATA10__LCDIF_DATA10	0x10
+			MX6UL_PAD_LCD_DATA11__LCDIF_DATA11	0x10
+			MX6UL_PAD_LCD_DATA12__LCDIF_DATA12	0x10
+			MX6UL_PAD_LCD_DATA13__LCDIF_DATA13	0x10
+			MX6UL_PAD_LCD_DATA14__LCDIF_DATA14	0x10
+			MX6UL_PAD_LCD_DATA15__LCDIF_DATA15	0x10
+			/* LCD_DATA16..17 not wired */
+			MX6UL_PAD_LCD_DATA18__LCDIF_DATA18	0x10
+			MX6UL_PAD_LCD_DATA19__LCDIF_DATA19	0x10
+			MX6UL_PAD_LCD_DATA20__LCDIF_DATA20	0x10
+			MX6UL_PAD_LCD_DATA21__LCDIF_DATA21	0x10
+			MX6UL_PAD_LCD_DATA22__LCDIF_DATA22	0x10
+			MX6UL_PAD_LCD_DATA23__LCDIF_DATA23	0x10
+		>;
+	};
+
+	pinctrl_enet2_mdio: enet2-mdiogrp {
+		fsl,pins = <
+			MX6UL_PAD_GPIO1_IO07__ENET2_MDC		0x0b0b0
+			MX6UL_PAD_GPIO1_IO06__ENET2_MDIO	0x1b0b0
+		>;
+	};
+
+	pinctrl_uart3: uart3grp {
+		fsl,pins = <
+			MX6UL_PAD_UART3_TX_DATA__UART3_DCE_TX	0x0b0b0
+			MX6UL_PAD_UART3_RX_DATA__UART3_DCE_RX	0x0b0b0
+		>;
+	};
+
+	pinctrl_uart4: uart4grp {
+		fsl,pins = <
+			MX6UL_PAD_UART4_TX_DATA__UART4_DCE_TX	0x0b0b0
+			MX6UL_PAD_UART4_RX_DATA__UART4_DCE_RX	0x0b0b0
+		>;
+	};
+
+	pinctrl_uart6: uart6grp {
+		fsl,pins = <
+			MX6UL_PAD_CSI_MCLK__UART6_DCE_TX	0x0b0b0
+			MX6UL_PAD_CSI_PIXCLK__UART6_DCE_RX	0x0b0b0
+		>;
+	};
+
+	pinctrl_uart7: uart7grp {
+		fsl,pins = <
+			MX6UL_PAD_LCD_DATA16__UART7_DCE_TX	0x0b0b0
+			MX6UL_PAD_LCD_DATA17__UART7_DCE_RX	0x0b0b0
+		>;
+	};
+
+	pinctrl_uart8: uart8grp {
+		fsl,pins = <
+			MX6UL_PAD_LCD_DATA20__UART8_DCE_TX	0x0b0b0
+			MX6UL_PAD_LCD_DATA21__UART8_DCE_RX	0x0b0b0
+		>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx7d.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/imx7d.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx7d.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx7d.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -651,6 +651,17 @@
 				#pwm-cells = <2>;
 				status = "disabled";
 			};
+
+			lcdif: lcdif@30730000 {
+				compatible = "fsl,imx7d-lcdif", "fsl,imx28-lcdif";
+				reg = <0x30730000 0x10000>;
+				interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX7D_LCDIF_PIXEL_ROOT_CLK>,
+					<&clks IMX7D_CLK_DUMMY>,
+					<&clks IMX7D_CLK_DUMMY>;
+				clock-names = "pix", "axi", "disp_axi";
+				status = "disabled";
+			};
 		};
 
 		aips3: aips-bus@30800000 {
@@ -692,6 +703,26 @@
 				clock-names = "ipg", "per";
 				status = "disabled";
 			};
+
+			flexcan1: can@30a00000 {
+				compatible = "fsl,imx7d-flexcan", "fsl,imx6q-flexcan";
+				reg = <0x30a00000 0x10000>;
+				interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX7D_CLK_DUMMY>,
+					<&clks IMX7D_CAN1_ROOT_CLK>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
+
+			flexcan2: can@30a10000 {
+				compatible = "fsl,imx7d-flexcan", "fsl,imx6q-flexcan";
+				reg = <0x30a10000 0x10000>;
+				interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX7D_CLK_DUMMY>,
+					<&clks IMX7D_CAN2_ROOT_CLK>;
+				clock-names = "ipg", "per";
+				status = "disabled";
+			};
 
 			i2c1: i2c@30a20000 {
 				#address-cells = <1>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/imx7d-nitrogen7.dts linux-libre-4.7-gnu/arch/arm/boot/dts/imx7d-nitrogen7.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/imx7d-nitrogen7.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/imx7d-nitrogen7.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,745 @@
+/*
+ * Copyright 2016 Boundary Devices, Inc.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include "imx7d.dtsi"
+
+/ {
+	model = "Boundary Devices i.MX7 Nitrogen7 Board";
+	compatible = "boundary,imx7d-nitrogen7", "fsl,imx7d";
+
+	aliases {
+		fb_lcd = &lcdif;
+		t_lcd = &t_lcd;
+	};
+
+	memory {
+		reg = <0x80000000 0x40000000>;
+	};
+
+	backlight-j9 {
+		compatible = "gpio-backlight";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_backlight_j9>;
+		gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>;
+		default-on;
+	};
+
+	backlight-j20 {
+		compatible = "pwm-backlight";
+		pwms = <&pwm1 0 5000000>;
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <6>;
+		status = "okay";
+	};
+
+	reg_usb_otg1_vbus: regulator-usb-otg1-vbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usb_otg1_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&gpio1 5 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	reg_usb_otg2_vbus: regulator-usb-otg2-vbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usb_otg2_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&gpio4 7 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	reg_can2_3v3: regulator-can2-3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "can2-3v3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		gpio = <&gpio2 14 GPIO_ACTIVE_LOW>;
+	};
+
+	reg_vref_1v8: regulator-vref-1v8 {
+		compatible = "regulator-fixed";
+		regulator-name = "vref-1v8";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+	};
+
+	reg_vref_3v3: regulator-vref-3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "vref-3v3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	reg_wlan: regulator-wlan {
+		compatible = "regulator-fixed";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		clocks = <&clks IMX7D_CLKO2_ROOT_DIV>;
+		clock-names = "slow";
+		regulator-name = "reg_wlan";
+		startup-delay-us = <70000>;
+		gpio = <&gpio4 21 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+};
+
+&adc1 {
+	vref-supply = <&reg_vref_1v8>;
+	status = "okay";
+};
+
+&adc2 {
+	vref-supply = <&reg_vref_1v8>;
+	status = "okay";
+};
+
+&clks {
+	assigned-clocks = <&clks IMX7D_CLKO2_ROOT_SRC>,
+			  <&clks IMX7D_CLKO2_ROOT_DIV>;
+	assigned-clock-parents = <&clks IMX7D_CKIL>;
+	assigned-clock-rates = <0>, <32768>;
+};
+
+&cpu0 {
+	arm-supply = <&sw1a_reg>;
+};
+
+&fec1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet1>;
+	assigned-clocks = <&clks IMX7D_ENET1_TIME_ROOT_SRC>,
+			  <&clks IMX7D_ENET1_TIME_ROOT_CLK>;
+	assigned-clock-parents = <&clks IMX7D_PLL_ENET_MAIN_100M_CLK>;
+	assigned-clock-rates = <0>, <100000000>;
+	phy-mode = "rgmii";
+	phy-handle = <&ethphy0>;
+	fsl,magic-packet;
+	status = "okay";
+
+	mdio {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ethphy0: ethernet-phy@4 {
+			reg = <4>;
+		};
+	};
+};
+
+&flexcan2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_flexcan2>;
+	xceiver-supply = <&reg_can2_3v3>;
+	status = "okay";
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	pmic: pfuze3000@08 {
+		compatible = "fsl,pfuze3000";
+		reg = <0x08>;
+
+		regulators {
+			sw1a_reg: sw1a {
+				regulator-min-microvolt = <700000>;
+				regulator-max-microvolt = <1475000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-ramp-delay = <6250>;
+			};
+
+			/* use sw1c_reg to align with pfuze100/pfuze200 */
+			sw1c_reg: sw1b {
+				regulator-min-microvolt = <700000>;
+				regulator-max-microvolt = <1475000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-ramp-delay = <6250>;
+			};
+
+			sw2_reg: sw2 {
+				regulator-min-microvolt = <1500000>;
+				regulator-max-microvolt = <1850000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw3a_reg: sw3 {
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <1650000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			swbst_reg: swbst {
+				regulator-min-microvolt = <5000000>;
+				regulator-max-microvolt = <5150000>;
+			};
+
+			snvs_reg: vsnvs {
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vref_reg: vrefddr {
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vgen1_reg: vldo1 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vgen2_reg: vldo2 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1550000>;
+				regulator-always-on;
+			};
+
+			vgen3_reg: vccsd {
+				regulator-min-microvolt = <2850000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vgen4_reg: v33 {
+				regulator-min-microvolt = <2850000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vgen5_reg: vldo3 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vgen6_reg: vldo4 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+		};
+	};
+};
+
+&i2c2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+
+	rtc@68 {
+		compatible = "rv4162";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_i2c2_rv4162>;
+		reg = <0x68>;
+		interrupts-extended = <&gpio2 15 IRQ_TYPE_LEVEL_LOW>;
+	};
+};
+
+&i2c3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+
+	touch@48 {
+		compatible = "ti,tsc2004";
+		reg = <0x48>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_i2c3_tsc2004>;
+		interrupts-extended = <&gpio3 4 IRQ_TYPE_EDGE_FALLING>;
+		wakeup-gpios = <&gpio3 4 GPIO_ACTIVE_LOW>;
+	};
+};
+
+&i2c4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c4>;
+	status = "okay";
+
+	codec: wm8960@1a {
+		compatible = "wlf,wm8960";
+		reg = <0x1a>;
+		clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_CLK>;
+		clock-names = "mclk";
+		wlf,shared-lrclk;
+	};
+};
+
+&lcdif {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_lcdif_dat
+		     &pinctrl_lcdif_ctrl>;
+	lcd-supply = <&reg_vref_3v3>;
+	display = <&display0>;
+	status = "okay";
+
+	display0: lcd-display {
+		bits-per-pixel = <16>;
+		bus-width = <18>;
+
+		display-timings {
+			native-mode = <&t_lcd>;
+			t_lcd: t_lcd_default {
+				/* default to Okaya display */
+				clock-frequency = <30000000>;
+				hactive = <800>;
+				vactive = <480>;
+				hfront-porch = <40>;
+				hback-porch = <40>;
+				hsync-len = <48>;
+				vback-porch = <29>;
+				vfront-porch = <13>;
+				vsync-len = <3>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+		};
+	};
+};
+
+&pwm1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm1>;
+	status = "okay";
+};
+
+&pwm2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm2>;
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	assigned-clocks = <&clks IMX7D_UART1_ROOT_SRC>;
+	assigned-clock-parents = <&clks IMX7D_OSC_24M_CLK>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	assigned-clocks = <&clks IMX7D_UART2_ROOT_SRC>;
+	assigned-clock-parents = <&clks IMX7D_OSC_24M_CLK>;
+	status = "okay";
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart3>;
+	assigned-clocks = <&clks IMX7D_UART3_ROOT_SRC>;
+	assigned-clock-parents = <&clks IMX7D_OSC_24M_CLK>;
+	status = "okay";
+};
+
+&uart6 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart6>;
+	assigned-clocks = <&clks IMX7D_UART6_ROOT_SRC>;
+	assigned-clock-parents = <&clks IMX7D_PLL_SYS_MAIN_240M_CLK>;
+	fsl,uart-has-rtscts;
+	status = "okay";
+};
+
+&usbotg1 {
+	vbus-supply = <&reg_usb_otg1_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg1>;
+	status = "okay";
+};
+
+&usbotg2 {
+	vbus-supply = <&reg_usb_otg2_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg2>;
+	dr_mode = "host";
+	status = "okay";
+};
+
+&usdhc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc1>;
+	cd-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
+	vmmc-supply = <&vgen3_reg>;
+	bus-width = <4>;
+	fsl,tuning-step = <2>;
+	wakeup-source;
+	keep-power-in-suspend;
+	status = "okay";
+};
+
+&usdhc2 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc2>;
+	bus-width = <4>;
+	non-removable;
+	vmmc-supply = <&reg_wlan>;
+	cap-power-off-card;
+	keep-power-in-suspend;
+	status = "okay";
+
+	wlcore: wlcore@2 {
+		compatible = "ti,wl1271";
+		reg = <2>;
+		interrupt-parent = <&gpio4>;
+		interrupts = <20 IRQ_TYPE_LEVEL_HIGH>;
+		ref-clock-frequency = <38400000>;
+	};
+};
+
+&usdhc3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc3>;
+	assigned-clocks = <&clks IMX7D_USDHC3_ROOT_CLK>;
+	assigned-clock-rates = <400000000>;
+	bus-width = <8>;
+	fsl,tuning-step = <2>;
+	non-removable;
+	status = "okay";
+};
+
+&wdog1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_wdog1>;
+	status = "okay";
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog_1 &pinctrl_j2>;
+
+	pinctrl_hog_1: hoggrp-1 {
+		fsl,pins = <
+			MX7D_PAD_SD3_RESET_B__GPIO6_IO11	0x5d
+			MX7D_PAD_GPIO1_IO13__GPIO1_IO13		0x7d
+			MX7D_PAD_ECSPI2_MISO__GPIO4_IO22	0x7d
+		>;
+	};
+
+	pinctrl_enet1: enet1grp {
+		fsl,pins = <
+			MX7D_PAD_GPIO1_IO10__ENET1_MDIO			0x3
+			MX7D_PAD_GPIO1_IO11__ENET1_MDC			0x3
+			MX7D_PAD_GPIO1_IO12__CCM_ENET_REF_CLK1		0x3
+			MX7D_PAD_ENET1_RGMII_TXC__ENET1_RGMII_TXC	0x71
+			MX7D_PAD_ENET1_RGMII_TD0__ENET1_RGMII_TD0	0x71
+			MX7D_PAD_ENET1_RGMII_TD1__ENET1_RGMII_TD1	0x71
+			MX7D_PAD_ENET1_RGMII_TD2__ENET1_RGMII_TD2	0x71
+			MX7D_PAD_ENET1_RGMII_TD3__ENET1_RGMII_TD3	0x71
+			MX7D_PAD_ENET1_RGMII_TX_CTL__ENET1_RGMII_TX_CTL	0x71
+			MX7D_PAD_ENET1_RGMII_RXC__ENET1_RGMII_RXC	0x71
+			MX7D_PAD_ENET1_RGMII_RD0__ENET1_RGMII_RD0	0x11
+			MX7D_PAD_ENET1_RGMII_RD1__ENET1_RGMII_RD1	0x11
+			MX7D_PAD_ENET1_RGMII_RD2__ENET1_RGMII_RD2	0x11
+			MX7D_PAD_ENET1_RGMII_RD3__ENET1_RGMII_RD3	0x71
+			MX7D_PAD_ENET1_RGMII_RX_CTL__ENET1_RGMII_RX_CTL	0x11
+			MX7D_PAD_SD3_STROBE__GPIO6_IO10			0x75
+		>;
+	};
+
+	pinctrl_flexcan2: flexcan2grp {
+		fsl,pins = <
+			MX7D_PAD_GPIO1_IO14__FLEXCAN2_RX	0x7d
+			MX7D_PAD_GPIO1_IO15__FLEXCAN2_TX	0x7d
+			MX7D_PAD_EPDC_DATA14__GPIO2_IO14	0x7d
+		>;
+	};
+
+	pinctrl_i2c1: i2c1grp {
+		fsl,pins = <
+			MX7D_PAD_I2C1_SDA__I2C1_SDA		0x4000007f
+			MX7D_PAD_I2C1_SCL__I2C1_SCL		0x4000007f
+		>;
+	};
+
+	pinctrl_i2c2: i2c2grp {
+		fsl,pins = <
+			MX7D_PAD_I2C2_SDA__I2C2_SDA		0x4000007f
+			MX7D_PAD_I2C2_SCL__I2C2_SCL		0x4000007f
+		>;
+	};
+
+	pinctrl_i2c2_rv4162: i2c2-rv4162grp {
+		fsl,pins = <
+			MX7D_PAD_EPDC_DATA15__GPIO2_IO15	0x7d
+		>;
+	};
+
+	pinctrl_i2c3: i2c3grp {
+		fsl,pins = <
+			MX7D_PAD_I2C3_SDA__I2C3_SDA		0x4000007f
+			MX7D_PAD_I2C3_SCL__I2C3_SCL		0x4000007f
+		>;
+	};
+
+	pinctrl_i2c3_tsc2004: i2c3tsc2004grp {
+		fsl,pins = <
+			MX7D_PAD_LCD_RESET__GPIO3_IO4		0x79
+			MX7D_PAD_SD2_WP__GPIO5_IO10		0x7d
+		>;
+	};
+
+	pinctrl_i2c4: i2c4grp {
+		fsl,pins = <
+			MX7D_PAD_I2C4_SDA__I2C4_SDA		0x4000007f
+			MX7D_PAD_I2C4_SCL__I2C4_SCL		0x4000007f
+		>;
+	};
+
+	pinctrl_j2: j2grp {
+		fsl,pins = <
+			MX7D_PAD_SAI1_TX_DATA__GPIO6_IO15	0x7d
+			MX7D_PAD_EPDC_BDR0__GPIO2_IO28		0x7d
+			MX7D_PAD_SAI1_RX_DATA__GPIO6_IO12	0x7d
+			MX7D_PAD_EPDC_BDR1__GPIO2_IO29		0x7d
+			MX7D_PAD_SD1_WP__GPIO5_IO1		0x7d
+			MX7D_PAD_EPDC_SDSHR__GPIO2_IO19		0x7d
+			MX7D_PAD_SD1_RESET_B__GPIO5_IO2		0x7d
+			MX7D_PAD_SD2_RESET_B__GPIO5_IO11	0x7d
+			MX7D_PAD_EPDC_DATA07__GPIO2_IO7		0x7d
+			MX7D_PAD_EPDC_DATA08__GPIO2_IO8		0x7d
+			MX7D_PAD_EPDC_DATA09__GPIO2_IO9		0x7d
+			MX7D_PAD_EPDC_DATA10__GPIO2_IO10	0x7d
+			MX7D_PAD_EPDC_DATA11__GPIO2_IO11	0x7d
+			MX7D_PAD_EPDC_DATA12__GPIO2_IO12	0x7d
+			MX7D_PAD_SAI1_TX_SYNC__GPIO6_IO14	0x7d
+			MX7D_PAD_EPDC_DATA13__GPIO2_IO13	0x7d
+			MX7D_PAD_SAI1_TX_BCLK__GPIO6_IO13	0x7d
+			MX7D_PAD_SD2_CD_B__GPIO5_IO9		0x7d
+			MX7D_PAD_EPDC_GDCLK__GPIO2_IO24		0x7d
+			MX7D_PAD_SAI2_RX_DATA__GPIO6_IO21	0x7d
+			MX7D_PAD_EPDC_GDOE__GPIO2_IO25		0x7d
+			MX7D_PAD_EPDC_GDRL__GPIO2_IO26		0x7d
+			MX7D_PAD_SAI2_TX_DATA__GPIO6_IO22	0x7d
+			MX7D_PAD_EPDC_SDCE0__GPIO2_IO20		0x7d
+			MX7D_PAD_SAI2_TX_BCLK__GPIO6_IO20	0x7d
+			MX7D_PAD_EPDC_SDCE1__GPIO2_IO21		0x7d
+			MX7D_PAD_SAI2_TX_SYNC__GPIO6_IO19	0x7d
+			MX7D_PAD_EPDC_SDCE2__GPIO2_IO22		0x7d
+			MX7D_PAD_EPDC_SDCE3__GPIO2_IO23		0x7d
+			MX7D_PAD_EPDC_GDSP__GPIO2_IO27		0x7d
+			MX7D_PAD_EPDC_SDCLK__GPIO2_IO16		0x7d
+			MX7D_PAD_EPDC_SDLE__GPIO2_IO17		0x7d
+			MX7D_PAD_EPDC_SDOE__GPIO2_IO18		0x7d
+			MX7D_PAD_EPDC_PWR_COM__GPIO2_IO30	0x7d
+			MX7D_PAD_EPDC_PWR_STAT__GPIO2_IO31	0x7d
+		>;
+	};
+
+	pinctrl_lcdif_dat: lcdifdatgrp {
+		fsl,pins = <
+			MX7D_PAD_LCD_DATA00__LCD_DATA0		0x79
+			MX7D_PAD_LCD_DATA01__LCD_DATA1		0x79
+			MX7D_PAD_LCD_DATA02__LCD_DATA2		0x79
+			MX7D_PAD_LCD_DATA03__LCD_DATA3		0x79
+			MX7D_PAD_LCD_DATA04__LCD_DATA4		0x79
+			MX7D_PAD_LCD_DATA05__LCD_DATA5		0x79
+			MX7D_PAD_LCD_DATA06__LCD_DATA6		0x79
+			MX7D_PAD_LCD_DATA07__LCD_DATA7		0x79
+			MX7D_PAD_LCD_DATA08__LCD_DATA8		0x79
+			MX7D_PAD_LCD_DATA09__LCD_DATA9		0x79
+			MX7D_PAD_LCD_DATA10__LCD_DATA10		0x79
+			MX7D_PAD_LCD_DATA11__LCD_DATA11		0x79
+			MX7D_PAD_LCD_DATA12__LCD_DATA12		0x79
+			MX7D_PAD_LCD_DATA13__LCD_DATA13		0x79
+			MX7D_PAD_LCD_DATA14__LCD_DATA14		0x79
+			MX7D_PAD_LCD_DATA15__LCD_DATA15		0x79
+			MX7D_PAD_LCD_DATA16__LCD_DATA16		0x79
+			MX7D_PAD_LCD_DATA17__LCD_DATA17		0x79
+			MX7D_PAD_LCD_DATA18__LCD_DATA18		0x79
+			MX7D_PAD_LCD_DATA19__LCD_DATA19		0x79
+			MX7D_PAD_LCD_DATA20__LCD_DATA20		0x79
+			MX7D_PAD_LCD_DATA21__LCD_DATA21		0x79
+			MX7D_PAD_LCD_DATA22__LCD_DATA22		0x79
+			MX7D_PAD_LCD_DATA23__LCD_DATA23		0x79
+		>;
+	};
+
+	pinctrl_lcdif_ctrl: lcdifctrlgrp {
+		fsl,pins = <
+			MX7D_PAD_LCD_CLK__LCD_CLK		0x79
+			MX7D_PAD_LCD_ENABLE__LCD_ENABLE		0x79
+			MX7D_PAD_LCD_VSYNC__LCD_VSYNC		0x79
+			MX7D_PAD_LCD_HSYNC__LCD_HSYNC		0x79
+		>;
+	};
+
+	pinctrl_pwm2: pwm2grp {
+		fsl,pins = <
+			MX7D_PAD_GPIO1_IO09__PWM2_OUT		0x7d
+		>;
+	};
+
+	pinctrl_uart1: uart1grp {
+		fsl,pins = <
+			MX7D_PAD_UART1_TX_DATA__UART1_DCE_TX	0x79
+			MX7D_PAD_UART1_RX_DATA__UART1_DCE_RX	0x79
+		>;
+	};
+
+	pinctrl_uart2: uart2grp {
+		fsl,pins = <
+			MX7D_PAD_UART2_TX_DATA__UART2_DCE_TX	0x79
+			MX7D_PAD_UART2_RX_DATA__UART2_DCE_RX	0x79
+		>;
+	};
+
+	pinctrl_uart3: uart3grp {
+		fsl,pins = <
+			MX7D_PAD_UART3_TX_DATA__UART3_DCE_TX	0x79
+			MX7D_PAD_UART3_RX_DATA__UART3_DCE_RX	0x79
+			MX7D_PAD_EPDC_DATA04__GPIO2_IO4		0x7d
+		>;
+	};
+
+	pinctrl_uart6: uart6grp {
+		fsl,pins = <
+			MX7D_PAD_ECSPI1_MOSI__UART6_DCE_TX	0x79
+			MX7D_PAD_ECSPI1_SCLK__UART6_DCE_RX	0x79
+			MX7D_PAD_ECSPI1_SS0__UART6_DCE_CTS	0x79
+			MX7D_PAD_ECSPI1_MISO__UART6_DCE_RTS	0x79
+		>;
+	};
+
+	pinctrl_usbotg2: usbotg2grp {
+		fsl,pins = <
+			MX7D_PAD_UART3_RTS_B__USB_OTG2_OC	0x7d
+			MX7D_PAD_UART3_CTS_B__GPIO4_IO7		0x14
+		>;
+	};
+
+	pinctrl_usdhc1: usdhc1grp {
+		fsl,pins = <
+			MX7D_PAD_SD1_CMD__SD1_CMD		0x59
+			MX7D_PAD_SD1_CLK__SD1_CLK		0x19
+			MX7D_PAD_SD1_DATA0__SD1_DATA0		0x59
+			MX7D_PAD_SD1_DATA1__SD1_DATA1		0x59
+			MX7D_PAD_SD1_DATA2__SD1_DATA2		0x59
+			MX7D_PAD_SD1_DATA3__SD1_DATA3		0x59
+			MX7D_PAD_GPIO1_IO08__SD1_VSELECT	0x75
+			MX7D_PAD_SD1_CD_B__GPIO5_IO0		0x75
+		>;
+	};
+
+	pinctrl_usdhc2: usdhc2grp {
+		fsl,pins = <
+			MX7D_PAD_SD2_CMD__SD2_CMD		0x59
+			MX7D_PAD_SD2_CLK__SD2_CLK		0x19
+			MX7D_PAD_SD2_DATA0__SD2_DATA0		0x59
+			MX7D_PAD_SD2_DATA1__SD2_DATA1		0x59
+			MX7D_PAD_SD2_DATA2__SD2_DATA2		0x59
+			MX7D_PAD_SD2_DATA3__SD2_DATA3		0x59
+			MX7D_PAD_ECSPI2_SCLK__GPIO4_IO20	0x59
+			MX7D_PAD_ECSPI2_MOSI__GPIO4_IO21	0x59
+		>;
+	};
+
+	pinctrl_usdhc3: usdhc3grp {
+		fsl,pins = <
+			MX7D_PAD_SD3_CMD__SD3_CMD		0x59
+			MX7D_PAD_SD3_CLK__SD3_CLK		0x19
+			MX7D_PAD_SD3_DATA0__SD3_DATA0		0x59
+			MX7D_PAD_SD3_DATA1__SD3_DATA1		0x59
+			MX7D_PAD_SD3_DATA2__SD3_DATA2		0x59
+			MX7D_PAD_SD3_DATA3__SD3_DATA3		0x59
+			MX7D_PAD_SD3_DATA4__SD3_DATA4		0x59
+			MX7D_PAD_SD3_DATA5__SD3_DATA5		0x59
+			MX7D_PAD_SD3_DATA6__SD3_DATA6		0x59
+			MX7D_PAD_SD3_DATA7__SD3_DATA7		0x59
+		>;
+	};
+};
+
+&iomuxc_lpsr {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog_2>;
+
+	pinctrl_hog_2: hoggrp-2 {
+		fsl,pins = <
+			MX7D_PAD_GPIO1_IO02__GPIO1_IO2		0x7d
+			MX7D_PAD_GPIO1_IO03__CCM_CLKO2		0x7d
+		>;
+	};
+
+	pinctrl_backlight_j9: backlightj9grp {
+		fsl,pins = <
+			MX7D_PAD_GPIO1_IO07__GPIO1_IO7		0x7d
+		>;
+	};
+
+	pinctrl_pwm1: pwm1grp {
+		fsl,pins = <
+			MX7D_PAD_GPIO1_IO01__PWM1_OUT		0x7d
+		>;
+	};
+
+	pinctrl_usbotg1: usbotg1grp {
+		fsl,pins = <
+			MX7D_PAD_GPIO1_IO04__USB_OTG1_OC	0x7d
+			MX7D_PAD_GPIO1_IO05__GPIO1_IO5		0x14
+		>;
+	};
+
+	pinctrl_wdog1: wdog1grp {
+		fsl,pins = <
+			MX7D_PAD_GPIO1_IO00__WDOD1_WDOG_B	0x75
+		>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/integrator.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/integrator.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/integrator.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/integrator.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -52,8 +52,9 @@
 	};
 
 	flash@24000000 {
-		compatible = "cfi-flash";
+		compatible = "arm,versatile-flash", "cfi-flash";
 		reg = <0x24000000 0x02000000>;
+		bank-width = <4>;
 	};
 
 	fpga {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/k2e-clocks.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/k2e-clocks.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/k2e-clocks.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/k2e-clocks.dtsi	1969-12-31 19:00:00.000000000 -0500
@@ -1,77 +0,0 @@
-/*
- * Copyright 2014 Texas Instruments, Inc.
- *
- * Keystone 2 Edison SoC specific device tree
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-clocks {
-	mainpllclk: mainpllclk@2310110 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,main-pll-clock";
-		clocks = <&refclksys>;
-		reg = <0x02620350 4>, <0x02310110 4>, <0x02310108 4>;
-		reg-names = "control", "multiplier", "post-divider";
-	};
-
-	papllclk: papllclk@2620358 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,pll-clock";
-		clocks = <&refclkpass>;
-		clock-output-names = "papllclk";
-		reg = <0x02620358 4>;
-		reg-names = "control";
-	};
-
-	ddr3apllclk: ddr3apllclk@2620360 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,pll-clock";
-		clocks = <&refclkddr3a>;
-		clock-output-names = "ddr-3a-pll-clk";
-		reg = <0x02620360 4>;
-		reg-names = "control";
-	};
-
-	clkusb1: clkusb1 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk16>;
-		clock-output-names = "usb1";
-		reg = <0x02350004 0xb00>, <0x02350000 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <0>;
-	};
-
-	clkhyperlink0: clkhyperlink0 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk12>;
-		clock-output-names = "hyperlink-0";
-		reg = <0x02350030 0xb00>, <0x02350014 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <5>;
-	};
-
-	clkpcie1: clkpcie1 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk12>;
-		clock-output-names = "pcie1";
-		reg = <0x0235006c 0xb00>, <0x02350048 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <18>;
-	};
-
-	clkxge: clkxge {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "xge";
-		reg = <0x023500c8 0xb00>, <0x02350074 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <29>;
-	};
-};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/k2e.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/k2e.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/k2e.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/k2e.dtsi	1969-12-31 19:00:00.000000000 -0500
@@ -1,150 +0,0 @@
-/*
- * Copyright 2013-2014 Texas Instruments, Inc.
- *
- * Keystone 2 Edison soc device tree
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-/ {
-	compatible = "ti,k2e", "ti,keystone";
-	model = "Texas Instruments Keystone 2 Edison SoC";
-
-	cpus {
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		interrupt-parent = <&gic>;
-
-		cpu@0 {
-			compatible = "arm,cortex-a15";
-			device_type = "cpu";
-			reg = <0>;
-		};
-
-		cpu@1 {
-			compatible = "arm,cortex-a15";
-			device_type = "cpu";
-			reg = <1>;
-		};
-
-		cpu@2 {
-			compatible = "arm,cortex-a15";
-			device_type = "cpu";
-			reg = <2>;
-		};
-
-		cpu@3 {
-			compatible = "arm,cortex-a15";
-			device_type = "cpu";
-			reg = <3>;
-		};
-	};
-
-	soc {
-		/include/ "k2e-clocks.dtsi"
-
-		usb: usb@2680000 {
-			interrupts = <GIC_SPI 152 IRQ_TYPE_EDGE_RISING>;
-			dwc3@2690000 {
-				interrupts = <GIC_SPI 152 IRQ_TYPE_EDGE_RISING>;
-			};
-		};
-
-		usb1_phy: usb_phy@2620750 {
-			compatible = "ti,keystone-usbphy";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			reg = <0x2620750 24>;
-			status = "disabled";
-		};
-
-		usb1: usb@25000000 {
-			compatible = "ti,keystone-dwc3";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			reg = <0x25000000 0x10000>;
-			clocks = <&clkusb1>;
-			clock-names = "usb";
-			interrupts = <GIC_SPI 414 IRQ_TYPE_EDGE_RISING>;
-			ranges;
-			dma-coherent;
-			dma-ranges;
-			status = "disabled";
-
-			dwc3@25010000 {
-				compatible = "synopsys,dwc3";
-				reg = <0x25010000 0x70000>;
-				interrupts = <GIC_SPI 414 IRQ_TYPE_EDGE_RISING>;
-				usb-phy = <&usb1_phy>, <&usb1_phy>;
-			};
-		};
-
-		dspgpio0: keystone_dsp_gpio@02620240 {
-			compatible = "ti,keystone-dsp-gpio";
-			gpio-controller;
-			#gpio-cells = <2>;
-			gpio,syscon-dev = <&devctrl 0x240>;
-		};
-
-		pcie1: pcie@21020000 {
-			compatible = "ti,keystone-pcie","snps,dw-pcie";
-			clocks = <&clkpcie1>;
-			clock-names = "pcie";
-			#address-cells = <3>;
-			#size-cells = <2>;
-			reg =  <0x21021000 0x2000>, <0x21020000 0x1000>, <0x02620128 4>;
-			ranges = <0x81000000 0 0 0x23260000 0x4000 0x4000
-				0x82000000 0 0x60000000 0x60000000 0 0x10000000>;
-
-			status = "disabled";
-			device_type = "pci";
-			num-lanes = <2>;
-
-			#interrupt-cells = <1>;
-			interrupt-map-mask = <0 0 0 7>;
-			interrupt-map = <0 0 0 1 &pcie_intc1 0>, /* INT A */
-					<0 0 0 2 &pcie_intc1 1>, /* INT B */
-					<0 0 0 3 &pcie_intc1 2>, /* INT C */
-					<0 0 0 4 &pcie_intc1 3>; /* INT D */
-
-			pcie_msi_intc1: msi-interrupt-controller {
-				interrupt-controller;
-				#interrupt-cells = <1>;
-				interrupt-parent = <&gic>;
-				interrupts = <GIC_SPI 377 IRQ_TYPE_EDGE_RISING>,
-					<GIC_SPI 378 IRQ_TYPE_EDGE_RISING>,
-					<GIC_SPI 379 IRQ_TYPE_EDGE_RISING>,
-					<GIC_SPI 380 IRQ_TYPE_EDGE_RISING>,
-					<GIC_SPI 381 IRQ_TYPE_EDGE_RISING>,
-					<GIC_SPI 382 IRQ_TYPE_EDGE_RISING>,
-					<GIC_SPI 383 IRQ_TYPE_EDGE_RISING>,
-					<GIC_SPI 384 IRQ_TYPE_EDGE_RISING>;
-			};
-
-			pcie_intc1: legacy-interrupt-controller {
-				interrupt-controller;
-				#interrupt-cells = <1>;
-				interrupt-parent = <&gic>;
-				interrupts = <GIC_SPI 373 IRQ_TYPE_EDGE_RISING>,
-					<GIC_SPI 374 IRQ_TYPE_EDGE_RISING>,
-					<GIC_SPI 375 IRQ_TYPE_EDGE_RISING>,
-					<GIC_SPI 376 IRQ_TYPE_EDGE_RISING>;
-			};
-		};
-
-		mdio: mdio@24200f00 {
-			compatible	= "ti,keystone_mdio", "ti,davinci_mdio";
-			#address-cells = <1>;
-			#size-cells = <0>;
-			reg = <0x24200f00 0x100>;
-			status = "disabled";
-			clocks = <&clkcpgmac>;
-			clock-names = "fck";
-			bus_freq	= <2500000>;
-		};
-		/include/ "k2e-netcp.dtsi"
-	};
-};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/k2e-evm.dts linux-libre-4.7-gnu/arch/arm/boot/dts/k2e-evm.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/k2e-evm.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/k2e-evm.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,154 +0,0 @@
-/*
- * Copyright 2013-2014 Texas Instruments, Inc.
- *
- * Keystone 2 Edison EVM device tree
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-/dts-v1/;
-
-#include "keystone.dtsi"
-#include "k2e.dtsi"
-
-/ {
-	compatible = "ti,k2e-evm", "ti,k2e", "ti,keystone";
-	model = "Texas Instruments Keystone 2 Edison EVM";
-
-	soc {
-
-		clocks {
-			refclksys: refclksys {
-				#clock-cells = <0>;
-				compatible = "fixed-clock";
-				clock-frequency = <100000000>;
-				clock-output-names = "refclk-sys";
-			};
-
-			refclkpass: refclkpass {
-				#clock-cells = <0>;
-				compatible = "fixed-clock";
-				clock-frequency = <100000000>;
-				clock-output-names = "refclk-pass";
-			};
-
-			refclkddr3a: refclkddr3a {
-				#clock-cells = <0>;
-				compatible = "fixed-clock";
-				clock-frequency = <100000000>;
-				clock-output-names = "refclk-ddr3a";
-			};
-		};
-	};
-};
-
-&usb_phy {
-	status = "okay";
-};
-
-&usb {
-	status = "okay";
-};
-
-&usb1_phy {
-	status = "okay";
-};
-
-&usb1 {
-	status = "okay";
-};
-
-&i2c0 {
-	dtt@50 {
-		compatible = "at,24c1024";
-		reg = <0x50>;
-	};
-};
-
-&aemif {
-	cs0 {
-		#address-cells = <2>;
-		#size-cells = <1>;
-		clock-ranges;
-		ranges;
-
-		ti,cs-chipselect = <0>;
-		/* all timings in nanoseconds */
-		ti,cs-min-turnaround-ns = <12>;
-		ti,cs-read-hold-ns = <6>;
-		ti,cs-read-strobe-ns = <23>;
-		ti,cs-read-setup-ns = <9>;
-		ti,cs-write-hold-ns = <8>;
-		ti,cs-write-strobe-ns = <23>;
-		ti,cs-write-setup-ns = <8>;
-
-		nand@0,0 {
-			compatible = "ti,keystone-nand","ti,davinci-nand";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			reg = <0 0 0x4000000
-			       1 0 0x0000100>;
-
-			ti,davinci-chipselect = <0>;
-			ti,davinci-mask-ale = <0x2000>;
-			ti,davinci-mask-cle = <0x4000>;
-			ti,davinci-mask-chipsel = <0>;
-			nand-ecc-mode = "hw";
-			ti,davinci-ecc-bits = <4>;
-			nand-on-flash-bbt;
-
-			partition@0 {
-				label = "u-boot";
-				reg = <0x0 0x100000>;
-				read-only;
-			};
-
-			partition@100000 {
-				label = "params";
-				reg = <0x100000 0x80000>;
-				read-only;
-			};
-
-			partition@180000 {
-				label = "ubifs";
-				reg = <0x180000 0x1FE80000>;
-			};
-		};
-	};
-};
-
-&spi0 {
-	nor_flash: n25q128a11@0 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "Micron,n25q128a11";
-		spi-max-frequency = <54000000>;
-		m25p,fast-read;
-		reg = <0>;
-
-		partition@0 {
-			label = "u-boot-spl";
-			reg = <0x0 0x80000>;
-			read-only;
-		};
-
-		partition@1 {
-			label = "misc";
-			reg = <0x80000 0xf80000>;
-		};
-	};
-};
-
-&mdio {
-	status = "ok";
-	ethphy0: ethernet-phy@0 {
-		compatible = "marvell,88E1514", "marvell,88E1510", "ethernet-phy-ieee802.3-c22";
-		reg = <0>;
-	};
-
-	ethphy1: ethernet-phy@1 {
-		compatible = "marvell,88E1514", "marvell,88E1510", "ethernet-phy-ieee802.3-c22";
-		reg = <1>;
-	};
-};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/k2e-netcp.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/k2e-netcp.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/k2e-netcp.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/k2e-netcp.dtsi	1969-12-31 19:00:00.000000000 -0500
@@ -1,229 +0,0 @@
-/*
- * Device Tree Source for Keystone 2 Edison Netcp driver
- *
- * Copyright 2015 Texas Instruments, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-qmss: qmss@2a40000 {
-	compatible = "ti,keystone-navigator-qmss";
-	dma-coherent;
-	#address-cells = <1>;
-	#size-cells = <1>;
-	clocks = <&chipclk13>;
-	ranges;
-	queue-range	= <0 0x2000>;
-	linkram0	= <0x100000 0x4000>;
-	linkram1	= <0 0x10000>;
-
-	qmgrs {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		ranges;
-		qmgr0 {
-			managed-queues = <0 0x2000>;
-			reg = <0x2a40000 0x20000>,
-			      <0x2a06000 0x400>,
-			      <0x2a02000 0x1000>,
-			      <0x2a03000 0x1000>,
-			      <0x23a80000 0x20000>,
-			      <0x2a80000 0x20000>;
-			reg-names = "peek", "status", "config",
-				    "region", "push", "pop";
-		};
-	};
-	queue-pools {
-		qpend {
-			qpend-0 {
-				qrange = <658 8>;
-				interrupts =<0 40 0xf04 0 41 0xf04 0 42 0xf04
-					     0 43 0xf04 0 44 0xf04 0 45 0xf04
-					     0 46 0xf04 0 47 0xf04>;
-			};
-			qpend-1 {
-				qrange = <528 16>;
-				interrupts = <0 48 0xf04 0 49 0xf04 0 50 0xf04
-					      0 51 0xf04 0 52 0xf04 0 53 0xf04
-					      0 54 0xf04 0 55 0xf04 0 56 0xf04
-					      0 57 0xf04 0 58 0xf04 0 59 0xf04
-					      0 60 0xf04 0 61 0xf04 0 62 0xf04
-					      0 63 0xf04>;
-				qalloc-by-id;
-			};
-			qpend-2 {
-				qrange = <544 16>;
-				interrupts = <0 64 0xf04 0 65 0xf04 0 66 0xf04
-					      0 59 0xf04 0 68 0xf04 0 69 0xf04
-					      0 70 0xf04 0 71 0xf04 0 72 0xf04
-					      0 73 0xf04 0 74 0xf04 0 75 0xf04
-					      0 76 0xf04 0 77 0xf04 0 78 0xf04
-					      0 79 0xf04>;
-			};
-		};
-		general-purpose {
-			gp-0 {
-				qrange = <4000 64>;
-			};
-			netcp-tx {
-				qrange = <896 128>;
-				qalloc-by-id;
-			};
-		};
-		accumulator {
-			acc-low-0 {
-				qrange = <480 32>;
-				accumulator = <0 47 16 2 50>;
-				interrupts = <0 226 0xf01>;
-				multi-queue;
-				qalloc-by-id;
-			};
-		};
-	};
-
-	descriptor-regions {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		ranges;
-		region-12 {
-			id = <12>;
-			region-spec = <8192 128>;	/* num_desc desc_size */
-			link-index = <0x4000>;
-		};
-	};
-
-	pdsps {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		ranges;
-		pdsp0@0x2a10000 {
-			reg = <0x2a10000 0x1000    /*iram */
-			       0x2a0f000 0x100     /*reg*/
-			       0x2a0c000 0x3c8	   /*intd */
-			       0x2a20000 0x4000>;  /*cmd*/
-			id = <0>;
-		};
-	};
-}; /* qmss */
-
-knav_dmas: knav_dmas@0 {
-	compatible = "ti,keystone-navigator-dma";
-	clocks = <&papllclk>;
-	#address-cells = <1>;
-	#size-cells = <1>;
-	ranges;
-	ti,navigator-cloud-address = <0x23a80000 0x23a90000
-				 0x23a80000 0x23a90000>;
-
-	dma_gbe: dma_gbe@0 {
-		reg = <0x24186000 0x100>,
-			  <0x24187000 0x2a0>,
-			  <0x24188000 0xb60>,
-			  <0x24186100 0x80>,
-			  <0x24189000 0x1000>;
-		reg-names = "global", "txchan", "rxchan",
-				"txsched", "rxflow";
-	};
-};
-
-netcp: netcp@24000000 {
-	reg = <0x2620110 0x8>;
-	reg-names = "efuse";
-	compatible = "ti,netcp-1.0";
-	#address-cells = <1>;
-	#size-cells = <1>;
-
-	/* NetCP address range */
-	ranges = <0 0x24000000 0x1000000>;
-
-	clocks = <&papllclk>, <&clkcpgmac>, <&chipclk12>;
-	dma-coherent;
-
-	ti,navigator-dmas = <&dma_gbe 0>,
-			<&dma_gbe 8>,
-			<&dma_gbe 0>;
-	ti,navigator-dma-names = "netrx0", "netrx1", "nettx";
-
-	netcp-devices {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		ranges;
-		gbe@200000 { /* ETHSS */
-			label = "netcp-gbe";
-			compatible = "ti,netcp-gbe-9";
-			reg = <0x200000 0x900>, <0x220000 0x20000>;
-			/* enable-ale; */
-			tx-queue = <896>;
-			tx-channel = "nettx";
-
-			interfaces {
-				gbe0: interface-0 {
-					slave-port = <0>;
-					link-interface	= <1>;
-					phy-handle	= <&ethphy0>;
-				};
-				gbe1: interface-1 {
-					slave-port = <1>;
-					link-interface	= <1>;
-					phy-handle	= <&ethphy1>;
-				};
-			};
-
-			secondary-slave-ports {
-				port-2 {
-					slave-port = <2>;
-					link-interface	= <2>;
-				};
-				port-3 {
-					slave-port = <3>;
-					link-interface	= <2>;
-				};
-				port-4 {
-					slave-port = <4>;
-					link-interface	= <2>;
-				};
-				port-5 {
-					slave-port = <5>;
-					link-interface	= <2>;
-				};
-				port-6 {
-					slave-port = <6>;
-					link-interface	= <2>;
-				};
-				port-7 {
-					slave-port = <7>;
-					link-interface	= <2>;
-				};
-			};
-		};
-	};
-
-	netcp-interfaces {
-		interface-0 {
-			rx-channel = "netrx0";
-			rx-pool = <1024 12>;
-			tx-pool = <1024 12>;
-			rx-queue-depth = <128 128 0 0>;
-			rx-buffer-size = <1518 4096 0 0>;
-			rx-queue = <528>;
-			tx-completion-queue = <530>;
-			efuse-mac = <1>;
-			netcp-gbe = <&gbe0>;
-
-		};
-		interface-1 {
-			rx-channel = "netrx1";
-			rx-pool = <1024 12>;
-			tx-pool = <1024 12>;
-			rx-queue-depth = <128 128 0 0>;
-			rx-buffer-size = <1518 4096 0 0>;
-			rx-queue = <529>;
-			tx-completion-queue = <531>;
-			efuse-mac = <0>;
-			local-mac-address = [02 18 31 7e 3e 00];
-			netcp-gbe = <&gbe1>;
-		};
-	};
-};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/k2hk-clocks.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/k2hk-clocks.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/k2hk-clocks.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/k2hk-clocks.dtsi	1969-12-31 19:00:00.000000000 -0500
@@ -1,425 +0,0 @@
-/*
- * Copyright 2013-2014 Texas Instruments, Inc.
- *
- * Keystone 2 Kepler/Hawking SoC clock nodes
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-clocks {
-	armpllclk: armpllclk@2620370 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,pll-clock";
-		clocks = <&refclkarm>;
-		clock-output-names = "arm-pll-clk";
-		reg = <0x02620370 4>;
-		reg-names = "control";
-	};
-
-	mainpllclk: mainpllclk@2310110 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,main-pll-clock";
-		clocks = <&refclksys>;
-		reg = <0x02620350 4>, <0x02310110 4>, <0x02310108 4>;
-		reg-names = "control", "multiplier", "post-divider";
-	};
-
-	papllclk: papllclk@2620358 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,pll-clock";
-		clocks = <&refclkpass>;
-		clock-output-names = "papllclk";
-		reg = <0x02620358 4>;
-		reg-names = "control";
-	};
-
-	ddr3apllclk: ddr3apllclk@2620360 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,pll-clock";
-		clocks = <&refclkddr3a>;
-		clock-output-names = "ddr-3a-pll-clk";
-		reg = <0x02620360 4>;
-		reg-names = "control";
-	};
-
-	ddr3bpllclk: ddr3bpllclk@2620368 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,pll-clock";
-		clocks = <&refclkddr3b>;
-		clock-output-names = "ddr-3b-pll-clk";
-		reg = <0x02620368 4>;
-		reg-names = "control";
-	};
-
-	clktsip: clktsip {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk16>;
-		clock-output-names = "tsip";
-		reg = <0x02350000 0xb00>, <0x02350000 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <0>;
-	};
-
-	clksrio: clksrio {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk1rstiso13>;
-		clock-output-names = "srio";
-		reg = <0x0235002c 0xb00>, <0x02350010 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <4>;
-	};
-
-	clkhyperlink0: clkhyperlink0 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk12>;
-		clock-output-names = "hyperlink-0";
-		reg = <0x02350030 0xb00>, <0x02350014 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <5>;
-	};
-
-	clkgem1: clkgem1 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk1>;
-		clock-output-names = "gem1";
-		reg = <0x02350040 0xb00>, <0x02350024 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <9>;
-	};
-
-	clkgem2: clkgem2 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk1>;
-		clock-output-names = "gem2";
-		reg = <0x02350044 0xb00>, <0x02350028 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <10>;
-	};
-
-	clkgem3: clkgem3 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk1>;
-		clock-output-names = "gem3";
-		reg = <0x02350048 0xb00>, <0x0235002c 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <11>;
-	};
-
-	clkgem4: clkgem4 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk1>;
-		clock-output-names = "gem4";
-		reg = <0x0235004c 0xb00>, <0x02350030 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <12>;
-	};
-
-	clkgem5: clkgem5 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk1>;
-		clock-output-names = "gem5";
-		reg = <0x02350050 0xb00>, <0x02350034 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <13>;
-	};
-
-	clkgem6: clkgem6 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk1>;
-		clock-output-names = "gem6";
-		reg = <0x02350054 0xb00>, <0x02350038 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <14>;
-	};
-
-	clkgem7: clkgem7 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk1>;
-		clock-output-names = "gem7";
-		reg = <0x02350058 0xb00>, <0x0235003c 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <15>;
-	};
-
-	clkddr31: clkddr31 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "ddr3-1";
-		reg = <0x02350060 0xb00>, <0x02350040 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <16>;
-	};
-
-	clktac: clktac {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "tac";
-		reg = <0x02350064 0xb00>, <0x02350044 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <17>;
-	};
-
-	clkrac01: clkrac01 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "rac-01";
-		reg = <0x02350068 0xb00>, <0x02350044 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <17>;
-	};
-
-	clkrac23: clkrac23 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "rac-23";
-		reg = <0x0235006c 0xb00>, <0x02350048 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <18>;
-	};
-
-	clkfftc0: clkfftc0 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "fftc-0";
-		reg = <0x02350070 0xb00>, <0x0235004c 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <19>;
-	};
-
-	clkfftc1: clkfftc1 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "fftc-1";
-		reg = <0x02350074 0xb00>, <0x0235004c 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <19>;
-	};
-
-	clkfftc2: clkfftc2 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "fftc-2";
-		reg = <0x02350078 0xb00>, <0x02350050 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <20>;
-	};
-
-	clkfftc3: clkfftc3 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "fftc-3";
-		reg = <0x0235007c 0xb00>, <0x02350050 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <20>;
-	};
-
-	clkfftc4: clkfftc4 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "fftc-4";
-		reg = <0x02350080 0xb00>, <0x02350050 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <20>;
-	};
-
-	clkfftc5: clkfftc5 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "fftc-5";
-		reg = <0x02350084 0xb00>, <0x02350050 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <20>;
-	};
-
-	clkaif: clkaif {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "aif";
-		reg = <0x02350088 0xb00>, <0x02350054 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <21>;
-	};
-
-	clktcp3d0: clktcp3d0 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "tcp3d-0";
-		reg = <0x0235008c 0xb00>, <0x02350058 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <22>;
-	};
-
-	clktcp3d1: clktcp3d1 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "tcp3d-1";
-		reg = <0x02350090 0xb00>, <0x02350058 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <22>;
-	};
-
-	clktcp3d2: clktcp3d2 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "tcp3d-2";
-		reg = <0x02350094 0xb00>, <0x0235005c 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <23>;
-	};
-
-	clktcp3d3: clktcp3d3 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "tcp3d-3";
-		reg = <0x02350098 0xb00>, <0x0235005c 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <23>;
-	};
-
-	clkvcp0: clkvcp0 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "vcp-0";
-		reg = <0x0235009c 0xb00>, <0x02350060 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <24>;
-	};
-
-	clkvcp1: clkvcp1 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "vcp-1";
-		reg = <0x023500a0 0xb00>, <0x02350060 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <24>;
-	};
-
-	clkvcp2: clkvcp2 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "vcp-2";
-		reg = <0x023500a4 0xb00>, <0x02350060 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <24>;
-	};
-
-	clkvcp3: clkvcp3 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "vcp-3";
-		reg = <0x023500a8 0xb00>, <0x02350060 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <24>;
-	};
-
-	clkvcp4: clkvcp4 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "vcp-4";
-		reg = <0x023500ac 0xb00>, <0x02350064 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <25>;
-	};
-
-	clkvcp5: clkvcp5 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "vcp-5";
-		reg = <0x023500b0 0xb00>, <0x02350064 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <25>;
-	};
-
-	clkvcp6: clkvcp6 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "vcp-6";
-		reg = <0x023500b4 0xb00>, <0x02350064 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <25>;
-	};
-
-	clkvcp7: clkvcp7 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "vcp-7";
-		reg = <0x023500b8 0xb00>, <0x02350064 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <25>;
-	};
-
-	clkbcp: clkbcp {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "bcp";
-		reg = <0x023500bc 0xb00>, <0x02350068 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <26>;
-	};
-
-	clkdxb: clkdxb {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "dxb";
-		reg = <0x023500c0 0xb00>, <0x0235006c 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <27>;
-	};
-
-	clkhyperlink1: clkhyperlink1 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk12>;
-		clock-output-names = "hyperlink-1";
-		reg = <0x023500c4 0xb00>, <0x02350070 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <28>;
-	};
-
-	clkxge: clkxge {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "xge";
-		reg = <0x023500c8 0xb00>, <0x02350074 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <29>;
-	};
-};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/k2hk.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/k2hk.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/k2hk.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/k2hk.dtsi	1969-12-31 19:00:00.000000000 -0500
@@ -1,117 +0,0 @@
-/*
- * Copyright 2013-2014 Texas Instruments, Inc.
- *
- * Keystone 2 Kepler/Hawking soc specific device tree
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-/ {
-	compatible = "ti,k2hk", "ti,keystone";
-	model = "Texas Instruments Keystone 2 Kepler/Hawking SoC";
-
-	cpus {
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		interrupt-parent = <&gic>;
-
-		cpu@0 {
-			compatible = "arm,cortex-a15";
-			device_type = "cpu";
-			reg = <0>;
-		};
-
-		cpu@1 {
-			compatible = "arm,cortex-a15";
-			device_type = "cpu";
-			reg = <1>;
-		};
-
-		cpu@2 {
-			compatible = "arm,cortex-a15";
-			device_type = "cpu";
-			reg = <2>;
-		};
-
-		cpu@3 {
-			compatible = "arm,cortex-a15";
-			device_type = "cpu";
-			reg = <3>;
-		};
-	};
-
-	soc {
-		/include/ "k2hk-clocks.dtsi"
-
-		dspgpio0: keystone_dsp_gpio@02620240 {
-			compatible = "ti,keystone-dsp-gpio";
-			gpio-controller;
-			#gpio-cells = <2>;
-			gpio,syscon-dev = <&devctrl 0x240>;
-		};
-
-		dspgpio1: keystone_dsp_gpio@2620244 {
-			compatible = "ti,keystone-dsp-gpio";
-			gpio-controller;
-			#gpio-cells = <2>;
-			gpio,syscon-dev = <&devctrl 0x244>;
-		};
-
-		dspgpio2: keystone_dsp_gpio@2620248 {
-			compatible = "ti,keystone-dsp-gpio";
-			gpio-controller;
-			#gpio-cells = <2>;
-			gpio,syscon-dev = <&devctrl 0x248>;
-		};
-
-		dspgpio3: keystone_dsp_gpio@262024c {
-			compatible = "ti,keystone-dsp-gpio";
-			gpio-controller;
-			#gpio-cells = <2>;
-			gpio,syscon-dev = <&devctrl 0x24c>;
-		};
-
-		dspgpio4: keystone_dsp_gpio@2620250 {
-			compatible = "ti,keystone-dsp-gpio";
-			gpio-controller;
-			#gpio-cells = <2>;
-			gpio,syscon-dev = <&devctrl 0x250>;
-		};
-
-		dspgpio5: keystone_dsp_gpio@2620254 {
-			compatible = "ti,keystone-dsp-gpio";
-			gpio-controller;
-			#gpio-cells = <2>;
-			gpio,syscon-dev = <&devctrl 0x254>;
-		};
-
-		dspgpio6: keystone_dsp_gpio@2620258 {
-			compatible = "ti,keystone-dsp-gpio";
-			gpio-controller;
-			#gpio-cells = <2>;
-			gpio,syscon-dev = <&devctrl 0x258>;
-		};
-
-		dspgpio7: keystone_dsp_gpio@262025c {
-			compatible = "ti,keystone-dsp-gpio";
-			gpio-controller;
-			#gpio-cells = <2>;
-			gpio,syscon-dev = <&devctrl 0x25c>;
-		};
-
-		mdio: mdio@02090300 {
-			compatible	= "ti,keystone_mdio", "ti,davinci_mdio";
-			#address-cells = <1>;
-			#size-cells = <0>;
-			reg = <0x02090300 0x100>;
-			status = "disabled";
-			clocks = <&clkcpgmac>;
-			clock-names = "fck";
-			bus_freq	= <2500000>;
-		};
-		/include/ "k2hk-netcp.dtsi"
-	};
-};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/k2hk-evm.dts linux-libre-4.7-gnu/arch/arm/boot/dts/k2hk-evm.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/k2hk-evm.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/k2hk-evm.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,182 +0,0 @@
-/*
- * Copyright 2013-2014 Texas Instruments, Inc.
- *
- * Keystone 2 Kepler/Hawking EVM device tree
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-/dts-v1/;
-
-#include "keystone.dtsi"
-#include "k2hk.dtsi"
-
-/ {
-	compatible =  "ti,k2hk-evm", "ti,k2hk", "ti,keystone";
-	model = "Texas Instruments Keystone 2 Kepler/Hawking EVM";
-
-	soc {
-		clocks {
-			refclksys: refclksys {
-				#clock-cells = <0>;
-				compatible = "fixed-clock";
-				clock-frequency = <122880000>;
-				clock-output-names = "refclk-sys";
-			};
-
-			refclkpass: refclkpass {
-				#clock-cells = <0>;
-				compatible = "fixed-clock";
-				clock-frequency = <122880000>;
-				clock-output-names = "refclk-pass";
-			};
-
-			refclkarm: refclkarm {
-				#clock-cells = <0>;
-				compatible = "fixed-clock";
-				clock-frequency = <125000000>;
-				clock-output-names = "refclk-arm";
-			};
-
-			refclkddr3a: refclkddr3a {
-				#clock-cells = <0>;
-				compatible = "fixed-clock";
-				clock-frequency = <100000000>;
-				clock-output-names = "refclk-ddr3a";
-			};
-
-			refclkddr3b: refclkddr3b {
-				#clock-cells = <0>;
-				compatible = "fixed-clock";
-				clock-frequency = <100000000>;
-				clock-output-names = "refclk-ddr3b";
-			};
-		};
-	};
-
-	leds {
-		compatible = "gpio-leds";
-		debug1_1 {
-			label = "keystone:green:debug1";
-			gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>; /* 12 */
-		};
-
-		debug1_2 {
-			label = "keystone:red:debug1";
-			gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>; /* 13 */
-		};
-
-		debug2 {
-			label = "keystone:blue:debug2";
-			gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>; /* 14 */
-		};
-
-		debug3 {
-			label = "keystone:blue:debug3";
-			gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>; /* 15 */
-		};
-	};
-};
-
-&usb_phy {
-	status = "okay";
-};
-
-&usb {
-	status = "okay";
-};
-
-&aemif {
-	cs0 {
-		#address-cells = <2>;
-		#size-cells = <1>;
-		clock-ranges;
-		ranges;
-
-		ti,cs-chipselect = <0>;
-		/* all timings in nanoseconds */
-		ti,cs-min-turnaround-ns = <12>;
-		ti,cs-read-hold-ns = <6>;
-		ti,cs-read-strobe-ns = <23>;
-		ti,cs-read-setup-ns = <9>;
-		ti,cs-write-hold-ns = <8>;
-		ti,cs-write-strobe-ns = <23>;
-		ti,cs-write-setup-ns = <8>;
-
-		nand@0,0 {
-			compatible = "ti,keystone-nand","ti,davinci-nand";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			reg = <0 0 0x4000000
-			       1 0 0x0000100>;
-
-			ti,davinci-chipselect = <0>;
-			ti,davinci-mask-ale = <0x2000>;
-			ti,davinci-mask-cle = <0x4000>;
-			ti,davinci-mask-chipsel = <0>;
-			nand-ecc-mode = "hw";
-			ti,davinci-ecc-bits = <4>;
-			nand-on-flash-bbt;
-
-			partition@0 {
-				label = "u-boot";
-				reg = <0x0 0x100000>;
-				read-only;
-			};
-
-			partition@100000 {
-				label = "params";
-				reg = <0x100000 0x80000>;
-				read-only;
-			};
-
-			partition@180000 {
-				label = "ubifs";
-				reg = <0x180000 0x1fe80000>;
-			};
-		};
-	};
-};
-
-&i2c0 {
-	dtt@50 {
-		compatible = "at,24c1024";
-		reg = <0x50>;
-	};
-};
-
-&spi0 {
-	nor_flash: n25q128a11@0 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "Micron,n25q128a11";
-		spi-max-frequency = <54000000>;
-		m25p,fast-read;
-		reg = <0>;
-
-		partition@0 {
-			label = "u-boot-spl";
-			reg = <0x0 0x80000>;
-			read-only;
-		};
-
-		partition@1 {
-			label = "misc";
-			reg = <0x80000 0xf80000>;
-		};
-	};
-};
-
-&mdio {
-	status = "ok";
-	ethphy0: ethernet-phy@0 {
-		compatible = "marvell,88E1111", "ethernet-phy-ieee802.3-c22";
-		reg = <0>;
-	};
-
-	ethphy1: ethernet-phy@1 {
-		compatible = "marvell,88E1111", "ethernet-phy-ieee802.3-c22";
-		reg = <1>;
-	};
-};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/k2hk-netcp.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/k2hk-netcp.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/k2hk-netcp.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/k2hk-netcp.dtsi	1969-12-31 19:00:00.000000000 -0500
@@ -1,232 +0,0 @@
-/*
- * Device Tree Source for Keystone 2 Hawking Netcp driver
- *
- * Copyright 2015 Texas Instruments, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-qmss: qmss@2a40000 {
-	compatible = "ti,keystone-navigator-qmss";
-	dma-coherent;
-	#address-cells = <1>;
-	#size-cells = <1>;
-	clocks = <&chipclk13>;
-	ranges;
-	queue-range	= <0 0x4000>;
-	linkram0	= <0x100000 0x8000>;
-	linkram1	= <0x0 0x10000>;
-
-	qmgrs {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		ranges;
-		qmgr0 {
-			managed-queues = <0 0x2000>;
-			reg = <0x2a40000 0x20000>,
-			      <0x2a06000 0x400>,
-			      <0x2a02000 0x1000>,
-			      <0x2a03000 0x1000>,
-			      <0x23a80000 0x20000>,
-			      <0x2a80000 0x20000>;
-			reg-names = "peek", "status", "config",
-				    "region", "push", "pop";
-		};
-
-		qmgr1 {
-			managed-queues = <0x2000 0x2000>;
-			reg = <0x2a60000 0x20000>,
-			      <0x2a06400 0x400>,
-			      <0x2a04000 0x1000>,
-			      <0x2a05000 0x1000>,
-			      <0x23aa0000 0x20000>,
-			      <0x2aa0000 0x20000>;
-			reg-names = "peek", "status", "config",
-				    "region", "push", "pop";
-		};
-	};
-
-	queue-pools {
-		qpend {
-			qpend-0 {
-				qrange = <658 8>;
-				interrupts =<0 40 0xf04 0 41 0xf04 0 42 0xf04
-					     0 43 0xf04 0 44 0xf04 0 45 0xf04
-					     0 46 0xf04 0 47 0xf04>;
-			};
-			qpend-1 {
-				qrange = <8704 16>;
-				interrupts = <0 48 0xf04 0 49 0xf04 0 50 0xf04
-					      0 51 0xf04 0 52 0xf04 0 53 0xf04
-					      0 54 0xf04 0 55 0xf04 0 56 0xf04
-					      0 57 0xf04 0 58 0xf04 0 59 0xf04
-					      0 60 0xf04 0 61 0xf04 0 62 0xf04
-					      0 63 0xf04>;
-				qalloc-by-id;
-			};
-			qpend-2 {
-				qrange = <8720 16>;
-				interrupts = <0 64 0xf04 0 65 0xf04 0 66 0xf04
-					      0 59 0xf04 0 68 0xf04 0 69 0xf04
-					      0 70 0xf04 0 71 0xf04 0 72 0xf04
-					      0 73 0xf04 0 74 0xf04 0 75 0xf04
-					      0 76 0xf04 0 77 0xf04 0 78 0xf04
-					      0 79 0xf04>;
-			};
-		};
-		general-purpose {
-			gp-0 {
-				qrange = <4000 64>;
-			};
-			netcp-tx {
-				qrange = <640 9>;
-				qalloc-by-id;
-			};
-			netcpx-tx {
-				qrange = <8752 8>;
-				qalloc-by-id;
-			};
-		};
-		accumulator {
-			acc-low-0 {
-				qrange = <480 32>;
-				accumulator = <0 47 16 2 50>;
-				interrupts = <0 226 0xf01>;
-				multi-queue;
-				qalloc-by-id;
-			};
-		};
-	};
-
-	descriptor-regions {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		ranges;
-		region-12 {
-			id = <12>;
-			region-spec = <8192 128>;	/* num_desc desc_size */
-			link-index = <0x4000>;
-		};
-	};
-
-	pdsps {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		ranges;
-		pdsp0@0x2a10000 {
-			reg = <0x2a10000 0x1000    /*iram */
-			       0x2a0f000 0x100     /*reg*/
-			       0x2a0c000 0x3c8	   /*intd */
-			       0x2a20000 0x4000>;  /*cmd*/
-			id = <0>;
-		};
-	};
-}; /* qmss */
-
-knav_dmas: knav_dmas@0 {
-	compatible = "ti,keystone-navigator-dma";
-	clocks = <&papllclk>;
-	#address-cells = <1>;
-	#size-cells = <1>;
-	ranges;
-	ti,navigator-cloud-address = <0x23a80000 0x23a90000
-				   0x23aa0000 0x23ab0000>;
-
-	dma_gbe: dma_gbe@0 {
-		reg = <0x2004000 0x100>,
-			  <0x2004400 0x120>,
-			  <0x2004800 0x300>,
-			  <0x2004c00 0x120>,
-			  <0x2005000 0x400>;
-		reg-names = "global", "txchan", "rxchan",
-				"txsched", "rxflow";
-	};
-};
-
-netcp: netcp@2000000 {
-	reg = <0x2620110 0x8>;
-	reg-names = "efuse";
-	compatible = "ti,netcp-1.0";
-	#address-cells = <1>;
-	#size-cells = <1>;
-
-	/* NetCP address range */
-	ranges  = <0 0x2000000 0x100000>;
-
-	clocks = <&papllclk>, <&clkcpgmac>, <&chipclk12>;
-	dma-coherent;
-
-	ti,navigator-dmas = <&dma_gbe 22>,
-			<&dma_gbe 23>,
-			<&dma_gbe 8>;
-	ti,navigator-dma-names = "netrx0", "netrx1", "nettx";
-
-	netcp-devices {
-		ranges;
-		#address-cells = <1>;
-		#size-cells = <1>;
-		gbe@90000 { /* ETHSS */
-			#address-cells = <1>;
-			#size-cells = <1>;
-			label = "netcp-gbe";
-			compatible = "ti,netcp-gbe";
-			reg = <0x90000 0x300>, <0x90400 0x400>, <0x90800 0x700>;
-			/* enable-ale; */
-			tx-queue = <648>;
-			tx-channel = "nettx";
-
-			interfaces {
-				gbe0: interface-0 {
-					slave-port = <0>;
-					link-interface = <1>;
-					phy-handle = <&ethphy0>;
-				};
-				gbe1: interface-1 {
-					slave-port = <1>;
-					link-interface = <1>;
-					phy-handle = <&ethphy1>;
-				};
-			};
-
-			secondary-slave-ports {
-				port-2 {
-					slave-port = <2>;
-					link-interface	= <2>;
-				};
-				port-3 {
-					slave-port = <3>;
-					link-interface	= <2>;
-				};
-			};
-		};
-	};
-
-	netcp-interfaces {
-		interface-0 {
-			rx-channel = "netrx0";
-			rx-pool = <1024 12>;
-			tx-pool = <1024 12>;
-			rx-queue-depth = <128 128 0 0>;
-			rx-buffer-size = <1518 4096 0 0>;
-			rx-queue = <8704>;
-			tx-completion-queue = <8706>;
-			efuse-mac = <1>;
-			netcp-gbe = <&gbe0>;
-
-		};
-		interface-1 {
-			rx-channel = "netrx1";
-			rx-pool = <1024 12>;
-			tx-pool = <1024 12>;
-			rx-queue-depth = <128 128 0 0>;
-			rx-buffer-size = <1518 4096 0 0>;
-			rx-queue = <8705>;
-			tx-completion-queue = <8707>;
-			efuse-mac = <0>;
-			local-mac-address = [02 18 31 7e 3e 6f];
-			netcp-gbe = <&gbe1>;
-		};
-	};
-};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/k2l-clocks.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/k2l-clocks.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/k2l-clocks.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/k2l-clocks.dtsi	1969-12-31 19:00:00.000000000 -0500
@@ -1,266 +0,0 @@
-/*
- * Copyright 2013-2014 Texas Instruments, Inc.
- *
- * Keystone 2 lamarr SoC clock nodes
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-clocks {
-	armpllclk: armpllclk@2620370 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,pll-clock";
-		clocks = <&refclksys>;
-		clock-output-names = "arm-pll-clk";
-		reg = <0x02620370 4>;
-		reg-names = "control";
-	};
-
-	mainpllclk: mainpllclk@2310110 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,main-pll-clock";
-		clocks = <&refclksys>;
-		reg = <0x02620350 4>, <0x02310110 4>, <0x02310108 4>;
-		reg-names = "control", "multiplier", "post-divider";
-	};
-
-	papllclk: papllclk@2620358 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,pll-clock";
-		clocks = <&refclksys>;
-		clock-output-names = "papllclk";
-		reg = <0x02620358 4>;
-		reg-names = "control";
-	};
-
-	ddr3apllclk: ddr3apllclk@2620360 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,pll-clock";
-		clocks = <&refclksys>;
-		clock-output-names = "ddr-3a-pll-clk";
-		reg = <0x02620360 4>;
-		reg-names = "control";
-	};
-
-	clkdfeiqnsys: clkdfeiqnsys {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk12>;
-		clock-output-names = "dfe";
-		reg-names = "control", "domain";
-		reg = <0x02350004 0xb00>, <0x02350000 0x400>;
-		domain-id = <0>;
-	};
-
-	clkpcie1: clkpcie1 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk12>;
-		clock-output-names = "pcie";
-		reg = <0x0235002c 0xb00>, <0x02350000 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <4>;
-	};
-
-	clkgem1: clkgem1 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk1>;
-		clock-output-names = "gem1";
-		reg = <0x02350040 0xb00>, <0x02350024 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <9>;
-	};
-
-	clkgem2: clkgem2 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk1>;
-		clock-output-names = "gem2";
-		reg = <0x02350044 0xb00>, <0x02350028 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <10>;
-	};
-
-	clkgem3: clkgem3 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk1>;
-		clock-output-names = "gem3";
-		reg = <0x02350048 0xb00>, <0x0235002c 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <11>;
-	};
-
-	clktac: clktac {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "tac";
-		reg = <0x02350064 0xb00>, <0x02350044 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <17>;
-	};
-
-	clkrac: clkrac {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "rac";
-		reg = <0x02350068 0xb00>, <0x02350044 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <17>;
-	};
-
-	clkdfepd0: clkdfepd0 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "dfe-pd0";
-		reg = <0x0235006c 0xb00>, <0x02350044 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <18>;
-	};
-
-	clkfftc0: clkfftc0 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "fftc-0";
-		reg = <0x02350070 0xb00>, <0x0235004c 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <19>;
-	};
-
-	clkosr: clkosr {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "osr";
-		reg = <0x02350088 0xb00>, <0x0235004c 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <21>;
-	};
-
-	clktcp3d0: clktcp3d0 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "tcp3d-0";
-		reg = <0x0235008c 0xb00>, <0x02350058 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <22>;
-	};
-
-	clktcp3d1: clktcp3d1 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "tcp3d-1";
-		reg = <0x02350094 0xb00>, <0x02350058 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <23>;
-	};
-
-	clkvcp0: clkvcp0 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "vcp-0";
-		reg = <0x0235009c 0xb00>, <0x02350060 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <24>;
-	};
-
-	clkvcp1: clkvcp1 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "vcp-1";
-		reg = <0x023500a0 0xb00>, <0x02350060 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <24>;
-	};
-
-	clkvcp2: clkvcp2 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "vcp-2";
-		reg = <0x023500a4 0xb00>, <0x02350060 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <24>;
-	};
-
-	clkvcp3: clkvcp3 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "vcp-3";
-		reg = <0x023500a8 0xb00>, <0x02350060 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <24>;
-	};
-
-	clkbcp: clkbcp {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "bcp";
-		reg = <0x023500bc 0xb00>, <0x02350068 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <26>;
-	};
-
-	clkdfepd1: clkdfepd1 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "dfe-pd1";
-		reg = <0x023500c0 0xb00>, <0x02350044 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <27>;
-	};
-
-	clkfftc1: clkfftc1 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "fftc-1";
-		reg = <0x023500c4 0xb00>, <0x023504c0 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <28>;
-	};
-
-	clkiqnail: clkiqnail {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&chipclk13>;
-		clock-output-names = "iqn-ail";
-		reg = <0x023500c8 0xb00>, <0x0235004c 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <29>;
-	};
-
-	clkuart2: clkuart2 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&clkmodrst0>;
-		clock-output-names = "uart2";
-		reg = <0x02350000 0xb00>, <0x02350000 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <0>;
-	};
-
-	clkuart3: clkuart3 {
-		#clock-cells = <0>;
-		compatible = "ti,keystone,psc-clock";
-		clocks = <&clkmodrst0>;
-		clock-output-names = "uart3";
-		reg = <0x02350000 0xb00>, <0x02350000 0x400>;
-		reg-names = "control", "domain";
-		domain-id = <0>;
-	};
-};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/k2l.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/k2l.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/k2l.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/k2l.dtsi	1969-12-31 19:00:00.000000000 -0500
@@ -1,111 +0,0 @@
-/*
- * Copyright 2014 Texas Instruments, Inc.
- *
- * Keystone 2 Lamarr SoC specific device tree
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-/ {
-	compatible = "ti,k2l", "ti,keystone";
-	model = "Texas Instruments Keystone 2 Lamarr SoC";
-
-	cpus {
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		interrupt-parent = <&gic>;
-
-		cpu@0 {
-			compatible = "arm,cortex-a15";
-			device_type = "cpu";
-			reg = <0>;
-		};
-
-		cpu@1 {
-			compatible = "arm,cortex-a15";
-			device_type = "cpu";
-			reg = <1>;
-		};
-	};
-
-	soc {
-		/include/ "k2l-clocks.dtsi"
-
-		uart2: serial@02348400 {
-			compatible = "ns16550a";
-			current-speed = <115200>;
-			reg-shift = <2>;
-			reg-io-width = <4>;
-			reg = <0x02348400 0x100>;
-			clocks	= <&clkuart2>;
-			interrupts = <GIC_SPI 432 IRQ_TYPE_EDGE_RISING>;
-		};
-
-		uart3:	serial@02348800 {
-			compatible = "ns16550a";
-			current-speed = <115200>;
-			reg-shift = <2>;
-			reg-io-width = <4>;
-			reg = <0x02348800 0x100>;
-			clocks	= <&clkuart3>;
-			interrupts = <GIC_SPI 435 IRQ_TYPE_EDGE_RISING>;
-		};
-
-		dspgpio0: keystone_dsp_gpio@02620240 {
-			compatible = "ti,keystone-dsp-gpio";
-			gpio-controller;
-			#gpio-cells = <2>;
-			gpio,syscon-dev = <&devctrl 0x240>;
-		};
-
-		dspgpio1: keystone_dsp_gpio@2620244 {
-			compatible = "ti,keystone-dsp-gpio";
-			gpio-controller;
-			#gpio-cells = <2>;
-			gpio,syscon-dev = <&devctrl 0x244>;
-		};
-
-		dspgpio2: keystone_dsp_gpio@2620248 {
-			compatible = "ti,keystone-dsp-gpio";
-			gpio-controller;
-			#gpio-cells = <2>;
-			gpio,syscon-dev = <&devctrl 0x248>;
-		};
-
-		dspgpio3: keystone_dsp_gpio@262024c {
-			compatible = "ti,keystone-dsp-gpio";
-			gpio-controller;
-			#gpio-cells = <2>;
-			gpio,syscon-dev = <&devctrl 0x24c>;
-		};
-
-		mdio: mdio@26200f00 {
-			compatible	= "ti,keystone_mdio", "ti,davinci_mdio";
-			#address-cells = <1>;
-			#size-cells = <0>;
-			reg = <0x26200f00 0x100>;
-			status = "disabled";
-			clocks = <&clkcpgmac>;
-			clock-names = "fck";
-			bus_freq	= <2500000>;
-		};
-		/include/ "k2l-netcp.dtsi"
-	};
-};
-
-&spi0 {
-       ti,davinci-spi-num-cs = <5>;
-};
-
-&spi1 {
-       ti,davinci-spi-num-cs = <3>;
-};
-
-&spi2 {
-       ti,davinci-spi-num-cs = <5>;
-       /* Pin muxed. Enabled and configured by Bootloader */
-       status = "disabled";
-};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/k2l-evm.dts linux-libre-4.7-gnu/arch/arm/boot/dts/k2l-evm.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/k2l-evm.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/k2l-evm.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,131 +0,0 @@
-/*
- * Copyright 2014 Texas Instruments, Inc.
- *
- * Keystone 2 Lamarr EVM device tree
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-/dts-v1/;
-
-#include "keystone.dtsi"
-#include "k2l.dtsi"
-
-/ {
-	compatible = "ti,k2l-evm", "ti,k2l", "ti,keystone";
-	model = "Texas Instruments Keystone 2 Lamarr EVM";
-
-	soc {
-		clocks {
-			refclksys: refclksys {
-				#clock-cells = <0>;
-				compatible = "fixed-clock";
-				clock-frequency = <122880000>;
-				clock-output-names = "refclk-sys";
-			};
-		};
-	};
-};
-
-&usb_phy {
-	status = "okay";
-};
-
-&usb {
-	status = "okay";
-};
-
-&i2c0 {
-	dtt@50 {
-		compatible = "at,24c1024";
-		reg = <0x50>;
-	};
-};
-
-&aemif {
-	cs0 {
-		#address-cells = <2>;
-		#size-cells = <1>;
-		clock-ranges;
-		ranges;
-
-		ti,cs-chipselect = <0>;
-		/* all timings in nanoseconds */
-		ti,cs-min-turnaround-ns = <12>;
-		ti,cs-read-hold-ns = <6>;
-		ti,cs-read-strobe-ns = <23>;
-		ti,cs-read-setup-ns = <9>;
-		ti,cs-write-hold-ns = <8>;
-		ti,cs-write-strobe-ns = <23>;
-		ti,cs-write-setup-ns = <8>;
-
-		nand@0,0 {
-			compatible = "ti,keystone-nand","ti,davinci-nand";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			reg = <0 0 0x4000000
-			       1 0 0x0000100>;
-
-			ti,davinci-chipselect = <0>;
-			ti,davinci-mask-ale = <0x2000>;
-			ti,davinci-mask-cle = <0x4000>;
-			ti,davinci-mask-chipsel = <0>;
-			nand-ecc-mode = "hw";
-			ti,davinci-ecc-bits = <4>;
-			nand-on-flash-bbt;
-
-			partition@0 {
-				label = "u-boot";
-				reg = <0x0 0x100000>;
-				read-only;
-			};
-
-			partition@100000 {
-				label = "params";
-				reg = <0x100000 0x80000>;
-				read-only;
-			};
-
-			partition@180000 {
-				label = "ubifs";
-				reg = <0x180000 0x7FE80000>;
-			};
-		};
-	};
-};
-
-&spi0 {
-	nor_flash: n25q128a11@0 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "Micron,n25q128a11";
-		spi-max-frequency = <54000000>;
-		m25p,fast-read;
-		reg = <0>;
-
-		partition@0 {
-			label = "u-boot-spl";
-			reg = <0x0 0x80000>;
-			read-only;
-		};
-
-		partition@1 {
-			label = "misc";
-			reg = <0x80000 0xf80000>;
-		};
-	};
-};
-
-&mdio {
-	status = "ok";
-	ethphy0: ethernet-phy@0 {
-		compatible = "marvell,88E1514", "marvell,88E1510", "ethernet-phy-ieee802.3-c22";
-		reg = <0>;
-	};
-
-	ethphy1: ethernet-phy@1 {
-		compatible = "marvell,88E1514", "marvell,88E1510", "ethernet-phy-ieee802.3-c22";
-		reg = <1>;
-	};
-};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/k2l-netcp.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/k2l-netcp.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/k2l-netcp.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/k2l-netcp.dtsi	1969-12-31 19:00:00.000000000 -0500
@@ -1,212 +0,0 @@
-/*
- * Device Tree Source for Keystone 2 Lamarr Netcp driver
- *
- * Copyright 2015 Texas Instruments, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-qmss: qmss@2a40000 {
-	compatible = "ti,keystone-navigator-qmss";
-	dma-coherent;
-	#address-cells = <1>;
-	#size-cells = <1>;
-	clocks = <&chipclk13>;
-	ranges;
-	queue-range	= <0 0x2000>;
-	linkram0	= <0x100000 0x4000>;
-	linkram1	= <0x70000000 0x10000>; /* 1MB OSR mem */
-
-	qmgrs {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		ranges;
-		qmgr0 {
-			managed-queues = <0 0x2000>;
-			reg = <0x2a40000 0x20000>,
-			      <0x2a06000 0x400>,
-			      <0x2a02000 0x1000>,
-			      <0x2a03000 0x1000>,
-			      <0x23a80000 0x20000>,
-			      <0x2a80000 0x20000>;
-			reg-names = "peek", "status", "config",
-				    "region", "push", "pop";
-		};
-	};
-	queue-pools {
-		qpend {
-			qpend-0 {
-				qrange = <658 8>;
-				interrupts =<0 40 0xf04 0 41 0xf04 0 42 0xf04
-					     0 43 0xf04 0 44 0xf04 0 45 0xf04
-					     0 46 0xf04 0 47 0xf04>;
-			};
-			qpend-1 {
-				qrange = <528 16>;
-				interrupts = <0 48 0xf04 0 49 0xf04 0 50 0xf04
-					      0 51 0xf04 0 52 0xf04 0 53 0xf04
-					      0 54 0xf04 0 55 0xf04 0 56 0xf04
-					      0 57 0xf04 0 58 0xf04 0 59 0xf04
-					      0 60 0xf04 0 61 0xf04 0 62 0xf04
-					      0 63 0xf04>;
-				qalloc-by-id;
-			};
-			qpend-2 {
-				qrange = <544 16>;
-				interrupts = <0 64 0xf04 0 65 0xf04 0 66 0xf04
-					      0 59 0xf04 0 68 0xf04 0 69 0xf04
-					      0 70 0xf04 0 71 0xf04 0 72 0xf04
-					      0 73 0xf04 0 74 0xf04 0 75 0xf04
-					      0 76 0xf04 0 77 0xf04 0 78 0xf04
-					      0 79 0xf04>;
-			};
-		};
-		general-purpose {
-			gp-0 {
-				qrange = <4000 64>;
-			};
-			netcp-tx {
-				qrange = <896 128>;
-				qalloc-by-id;
-			};
-		};
-		accumulator {
-			acc-low-0 {
-				qrange = <480 32>;
-				accumulator = <0 47 16 2 50>;
-				interrupts = <0 226 0xf01>;
-				multi-queue;
-			};
-		};
-	};
-
-	descriptor-regions {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		ranges;
-		region-12 {
-			id = <12>;
-			region-spec = <8192 128>;	/* num_desc desc_size */
-			link-index = <0x4000>;
-		};
-	};
-
-	pdsps {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		ranges;
-		pdsp0@0x2a10000 {
-			reg = <0x2a10000 0x1000    /*iram */
-			       0x2a0f000 0x100     /*reg*/
-			       0x2a0c000 0x3c8	   /*intd */
-			       0x2a20000 0x4000>;  /*cmd*/
-			id = <0>;
-		};
-	};
-
-}; /* qmss */
-
-knav_dmas: knav_dmas@0 {
-	compatible = "ti,keystone-navigator-dma";
-	clocks = <&papllclk>;
-	#address-cells = <1>;
-	#size-cells = <1>;
-	ranges;
-	ti,navigator-cloud-address = <0x23a80000 0x23a90000>;
-
-	dma_gbe: dma_gbe@0 {
-		reg = <0x26186000 0x100>,
-			  <0x26187000 0x2a0>,
-			  <0x26188000 0xb60>,
-			  <0x26186100 0x80>,
-			  <0x26189000 0x1000>;
-		reg-names = "global", "txchan", "rxchan",
-				"txsched", "rxflow";
-	};
-};
-
-netcp: netcp@26000000 {
-	reg = <0x2620110 0x8>;
-	reg-names = "efuse";
-	compatible = "ti,netcp-1.0";
-	#address-cells = <1>;
-	#size-cells = <1>;
-
-	/* NetCP address range */
-	ranges = <0 0x26000000 0x1000000>;
-
-	clocks = <&clkosr>, <&papllclk>, <&clkcpgmac>, <&chipclk12>;
-	dma-coherent;
-
-	ti,navigator-dmas = <&dma_gbe 0>,
-			<&dma_gbe 8>,
-			<&dma_gbe 0>;
-	ti,navigator-dma-names = "netrx0", "netrx1", "nettx";
-
-	netcp-devices {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		ranges;
-		gbe@200000 { /* ETHSS */
-			label = "netcp-gbe";
-			compatible = "ti,netcp-gbe-5";
-			reg = <0x200000 0x900>, <0x220000 0x20000>;
-			/* enable-ale; */
-			tx-queue = <896>;
-			tx-channel = "nettx";
-
-			interfaces {
-				gbe0: interface-0 {
-					slave-port = <0>;
-					link-interface	= <1>;
-					phy-handle	= <&ethphy0>;
-				};
-				gbe1: interface-1 {
-					slave-port = <1>;
-					link-interface	= <1>;
-					phy-handle	= <&ethphy1>;
-				};
-			};
-
-			secondary-slave-ports {
-				port-2 {
-					slave-port = <2>;
-					link-interface	= <2>;
-				};
-				port-3 {
-					slave-port = <3>;
-					link-interface	= <2>;
-				};
-			};
-		};
-	};
-
-	netcp-interfaces {
-		interface-0 {
-			rx-channel = "netrx0";
-			rx-pool = <1024 12>;
-			tx-pool = <1024 12>;
-			rx-queue-depth = <128 128 0 0>;
-			rx-buffer-size = <1518 4096 0 0>;
-			rx-queue = <528>;
-			tx-completion-queue = <530>;
-			efuse-mac = <1>;
-			netcp-gbe = <&gbe0>;
-
-		};
-		interface-1 {
-			rx-channel = "netrx1";
-			rx-pool = <1024 12>;
-			tx-pool = <1024 12>;
-			rx-queue-depth = <128 128 0 0>;
-			rx-buffer-size = <1518 4096 0 0>;
-			rx-queue = <529>;
-			tx-completion-queue = <531>;
-			efuse-mac = <0>;
-			local-mac-address = [02 18 31 7e 3e 7f];
-			netcp-gbe = <&gbe1>;
-		};
-	};
-};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/keystone.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/keystone.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/keystone.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/keystone.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -20,6 +20,9 @@
 
 	aliases {
 		serial0	= &uart0;
+		spi0 = &spi0;
+		spi1 = &spi1;
+		spi2 = &spi2;
 	};
 
 	memory {
@@ -59,6 +62,14 @@
 			     <GIC_SPI 23 IRQ_TYPE_EDGE_RISING>;
 	};
 
+	psci {
+		compatible	= "arm,psci";
+		method		= "smc";
+		cpu_suspend	= <0x84000001>;
+		cpu_off		= <0x84000002>;
+		cpu_on		= <0x84000003>;
+	};
+
 	soc {
 		#address-cells = <1>;
 		#size-cells = <1>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/keystone-k2e-clocks.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/keystone-k2e-clocks.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/keystone-k2e-clocks.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/keystone-k2e-clocks.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2014 Texas Instruments, Inc.
+ *
+ * Keystone 2 Edison SoC specific device tree
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+clocks {
+	mainpllclk: mainpllclk@2310110 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,main-pll-clock";
+		clocks = <&refclksys>;
+		reg = <0x02620350 4>, <0x02310110 4>, <0x02310108 4>;
+		reg-names = "control", "multiplier", "post-divider";
+	};
+
+	papllclk: papllclk@2620358 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,pll-clock";
+		clocks = <&refclkpass>;
+		clock-output-names = "papllclk";
+		reg = <0x02620358 4>;
+		reg-names = "control";
+	};
+
+	ddr3apllclk: ddr3apllclk@2620360 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,pll-clock";
+		clocks = <&refclkddr3a>;
+		clock-output-names = "ddr-3a-pll-clk";
+		reg = <0x02620360 4>;
+		reg-names = "control";
+	};
+
+	clkusb1: clkusb1 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk16>;
+		clock-output-names = "usb1";
+		reg = <0x02350004 0xb00>, <0x02350000 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <0>;
+	};
+
+	clkhyperlink0: clkhyperlink0 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk12>;
+		clock-output-names = "hyperlink-0";
+		reg = <0x02350030 0xb00>, <0x02350014 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <5>;
+	};
+
+	clkpcie1: clkpcie1 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk12>;
+		clock-output-names = "pcie1";
+		reg = <0x0235006c 0xb00>, <0x02350048 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <18>;
+	};
+
+	clkxge: clkxge {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "xge";
+		reg = <0x023500c8 0xb00>, <0x02350074 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <29>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/keystone-k2e.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/keystone-k2e.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/keystone-k2e.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/keystone-k2e.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2013-2014 Texas Instruments, Inc.
+ *
+ * Keystone 2 Edison soc device tree
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/ {
+	compatible = "ti,k2e", "ti,keystone";
+	model = "Texas Instruments Keystone 2 Edison SoC";
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		interrupt-parent = <&gic>;
+
+		cpu@0 {
+			compatible = "arm,cortex-a15";
+			device_type = "cpu";
+			reg = <0>;
+		};
+
+		cpu@1 {
+			compatible = "arm,cortex-a15";
+			device_type = "cpu";
+			reg = <1>;
+		};
+
+		cpu@2 {
+			compatible = "arm,cortex-a15";
+			device_type = "cpu";
+			reg = <2>;
+		};
+
+		cpu@3 {
+			compatible = "arm,cortex-a15";
+			device_type = "cpu";
+			reg = <3>;
+		};
+	};
+
+	soc {
+		/include/ "keystone-k2e-clocks.dtsi"
+
+		usb: usb@2680000 {
+			interrupts = <GIC_SPI 152 IRQ_TYPE_EDGE_RISING>;
+			dwc3@2690000 {
+				interrupts = <GIC_SPI 152 IRQ_TYPE_EDGE_RISING>;
+			};
+		};
+
+		usb1_phy: usb_phy@2620750 {
+			compatible = "ti,keystone-usbphy";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x2620750 24>;
+			status = "disabled";
+		};
+
+		usb1: usb@25000000 {
+			compatible = "ti,keystone-dwc3";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x25000000 0x10000>;
+			clocks = <&clkusb1>;
+			clock-names = "usb";
+			interrupts = <GIC_SPI 414 IRQ_TYPE_EDGE_RISING>;
+			ranges;
+			dma-coherent;
+			dma-ranges;
+			status = "disabled";
+
+			dwc3@25010000 {
+				compatible = "synopsys,dwc3";
+				reg = <0x25010000 0x70000>;
+				interrupts = <GIC_SPI 414 IRQ_TYPE_EDGE_RISING>;
+				usb-phy = <&usb1_phy>, <&usb1_phy>;
+			};
+		};
+
+		dspgpio0: keystone_dsp_gpio@02620240 {
+			compatible = "ti,keystone-dsp-gpio";
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio,syscon-dev = <&devctrl 0x240>;
+		};
+
+		pcie1: pcie@21020000 {
+			compatible = "ti,keystone-pcie","snps,dw-pcie";
+			clocks = <&clkpcie1>;
+			clock-names = "pcie";
+			#address-cells = <3>;
+			#size-cells = <2>;
+			reg =  <0x21021000 0x2000>, <0x21020000 0x1000>, <0x02620128 4>;
+			ranges = <0x81000000 0 0 0x23260000 0x4000 0x4000
+				0x82000000 0 0x60000000 0x60000000 0 0x10000000>;
+
+			status = "disabled";
+			device_type = "pci";
+			num-lanes = <2>;
+
+			#interrupt-cells = <1>;
+			interrupt-map-mask = <0 0 0 7>;
+			interrupt-map = <0 0 0 1 &pcie_intc1 0>, /* INT A */
+					<0 0 0 2 &pcie_intc1 1>, /* INT B */
+					<0 0 0 3 &pcie_intc1 2>, /* INT C */
+					<0 0 0 4 &pcie_intc1 3>; /* INT D */
+
+			pcie_msi_intc1: msi-interrupt-controller {
+				interrupt-controller;
+				#interrupt-cells = <1>;
+				interrupt-parent = <&gic>;
+				interrupts = <GIC_SPI 377 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 378 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 379 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 380 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 381 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 382 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 383 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 384 IRQ_TYPE_EDGE_RISING>;
+			};
+
+			pcie_intc1: legacy-interrupt-controller {
+				interrupt-controller;
+				#interrupt-cells = <1>;
+				interrupt-parent = <&gic>;
+				interrupts = <GIC_SPI 373 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 374 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 375 IRQ_TYPE_EDGE_RISING>,
+					<GIC_SPI 376 IRQ_TYPE_EDGE_RISING>;
+			};
+		};
+
+		mdio: mdio@24200f00 {
+			compatible	= "ti,keystone_mdio", "ti,davinci_mdio";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x24200f00 0x100>;
+			status = "disabled";
+			clocks = <&clkcpgmac>;
+			clock-names = "fck";
+			bus_freq	= <2500000>;
+		};
+		/include/ "keystone-k2e-netcp.dtsi"
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/keystone-k2e-evm.dts linux-libre-4.7-gnu/arch/arm/boot/dts/keystone-k2e-evm.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/keystone-k2e-evm.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/keystone-k2e-evm.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2013-2014 Texas Instruments, Inc.
+ *
+ * Keystone 2 Edison EVM device tree
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "keystone.dtsi"
+#include "keystone-k2e.dtsi"
+
+/ {
+	compatible = "ti,k2e-evm", "ti,k2e", "ti,keystone";
+	model = "Texas Instruments Keystone 2 Edison EVM";
+
+	soc {
+
+		clocks {
+			refclksys: refclksys {
+				#clock-cells = <0>;
+				compatible = "fixed-clock";
+				clock-frequency = <100000000>;
+				clock-output-names = "refclk-sys";
+			};
+
+			refclkpass: refclkpass {
+				#clock-cells = <0>;
+				compatible = "fixed-clock";
+				clock-frequency = <100000000>;
+				clock-output-names = "refclk-pass";
+			};
+
+			refclkddr3a: refclkddr3a {
+				#clock-cells = <0>;
+				compatible = "fixed-clock";
+				clock-frequency = <100000000>;
+				clock-output-names = "refclk-ddr3a";
+			};
+		};
+	};
+};
+
+&usb_phy {
+	status = "okay";
+};
+
+&usb {
+	status = "okay";
+};
+
+&usb1_phy {
+	status = "okay";
+};
+
+&usb1 {
+	status = "okay";
+};
+
+&i2c0 {
+	dtt@50 {
+		compatible = "at,24c1024";
+		reg = <0x50>;
+	};
+};
+
+&aemif {
+	cs0 {
+		#address-cells = <2>;
+		#size-cells = <1>;
+		clock-ranges;
+		ranges;
+
+		ti,cs-chipselect = <0>;
+		/* all timings in nanoseconds */
+		ti,cs-min-turnaround-ns = <12>;
+		ti,cs-read-hold-ns = <6>;
+		ti,cs-read-strobe-ns = <23>;
+		ti,cs-read-setup-ns = <9>;
+		ti,cs-write-hold-ns = <8>;
+		ti,cs-write-strobe-ns = <23>;
+		ti,cs-write-setup-ns = <8>;
+
+		nand@0,0 {
+			compatible = "ti,keystone-nand","ti,davinci-nand";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0 0 0x4000000
+			       1 0 0x0000100>;
+
+			ti,davinci-chipselect = <0>;
+			ti,davinci-mask-ale = <0x2000>;
+			ti,davinci-mask-cle = <0x4000>;
+			ti,davinci-mask-chipsel = <0>;
+			nand-ecc-mode = "hw";
+			ti,davinci-ecc-bits = <4>;
+			nand-on-flash-bbt;
+
+			partition@0 {
+				label = "u-boot";
+				reg = <0x0 0x100000>;
+				read-only;
+			};
+
+			partition@100000 {
+				label = "params";
+				reg = <0x100000 0x80000>;
+				read-only;
+			};
+
+			partition@180000 {
+				label = "ubifs";
+				reg = <0x180000 0x1FE80000>;
+			};
+		};
+	};
+};
+
+&spi0 {
+	nor_flash: n25q128a11@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "Micron,n25q128a11";
+		spi-max-frequency = <54000000>;
+		m25p,fast-read;
+		reg = <0>;
+
+		partition@0 {
+			label = "u-boot-spl";
+			reg = <0x0 0x80000>;
+			read-only;
+		};
+
+		partition@1 {
+			label = "misc";
+			reg = <0x80000 0xf80000>;
+		};
+	};
+};
+
+&mdio {
+	status = "ok";
+	ethphy0: ethernet-phy@0 {
+		compatible = "marvell,88E1514", "marvell,88E1510", "ethernet-phy-ieee802.3-c22";
+		reg = <0>;
+	};
+
+	ethphy1: ethernet-phy@1 {
+		compatible = "marvell,88E1514", "marvell,88E1510", "ethernet-phy-ieee802.3-c22";
+		reg = <1>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/keystone-k2e-netcp.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/keystone-k2e-netcp.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/keystone-k2e-netcp.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/keystone-k2e-netcp.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,229 @@
+/*
+ * Device Tree Source for Keystone 2 Edison Netcp driver
+ *
+ * Copyright 2015 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+qmss: qmss@2a40000 {
+	compatible = "ti,keystone-navigator-qmss";
+	dma-coherent;
+	#address-cells = <1>;
+	#size-cells = <1>;
+	clocks = <&chipclk13>;
+	ranges;
+	queue-range	= <0 0x2000>;
+	linkram0	= <0x100000 0x4000>;
+	linkram1	= <0 0x10000>;
+
+	qmgrs {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		qmgr0 {
+			managed-queues = <0 0x2000>;
+			reg = <0x2a40000 0x20000>,
+			      <0x2a06000 0x400>,
+			      <0x2a02000 0x1000>,
+			      <0x2a03000 0x1000>,
+			      <0x23a80000 0x20000>,
+			      <0x2a80000 0x20000>;
+			reg-names = "peek", "status", "config",
+				    "region", "push", "pop";
+		};
+	};
+	queue-pools {
+		qpend {
+			qpend-0 {
+				qrange = <658 8>;
+				interrupts =<0 40 0xf04 0 41 0xf04 0 42 0xf04
+					     0 43 0xf04 0 44 0xf04 0 45 0xf04
+					     0 46 0xf04 0 47 0xf04>;
+			};
+			qpend-1 {
+				qrange = <528 16>;
+				interrupts = <0 48 0xf04 0 49 0xf04 0 50 0xf04
+					      0 51 0xf04 0 52 0xf04 0 53 0xf04
+					      0 54 0xf04 0 55 0xf04 0 56 0xf04
+					      0 57 0xf04 0 58 0xf04 0 59 0xf04
+					      0 60 0xf04 0 61 0xf04 0 62 0xf04
+					      0 63 0xf04>;
+				qalloc-by-id;
+			};
+			qpend-2 {
+				qrange = <544 16>;
+				interrupts = <0 64 0xf04 0 65 0xf04 0 66 0xf04
+					      0 59 0xf04 0 68 0xf04 0 69 0xf04
+					      0 70 0xf04 0 71 0xf04 0 72 0xf04
+					      0 73 0xf04 0 74 0xf04 0 75 0xf04
+					      0 76 0xf04 0 77 0xf04 0 78 0xf04
+					      0 79 0xf04>;
+			};
+		};
+		general-purpose {
+			gp-0 {
+				qrange = <4000 64>;
+			};
+			netcp-tx {
+				qrange = <896 128>;
+				qalloc-by-id;
+			};
+		};
+		accumulator {
+			acc-low-0 {
+				qrange = <480 32>;
+				accumulator = <0 47 16 2 50>;
+				interrupts = <0 226 0xf01>;
+				multi-queue;
+				qalloc-by-id;
+			};
+		};
+	};
+
+	descriptor-regions {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		region-12 {
+			id = <12>;
+			region-spec = <8192 128>;	/* num_desc desc_size */
+			link-index = <0x4000>;
+		};
+	};
+
+	pdsps {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		pdsp0@0x2a10000 {
+			reg = <0x2a10000 0x1000    /*iram */
+			       0x2a0f000 0x100     /*reg*/
+			       0x2a0c000 0x3c8	   /*intd */
+			       0x2a20000 0x4000>;  /*cmd*/
+			id = <0>;
+		};
+	};
+}; /* qmss */
+
+knav_dmas: knav_dmas@0 {
+	compatible = "ti,keystone-navigator-dma";
+	clocks = <&papllclk>;
+	#address-cells = <1>;
+	#size-cells = <1>;
+	ranges;
+	ti,navigator-cloud-address = <0x23a80000 0x23a90000
+				 0x23a80000 0x23a90000>;
+
+	dma_gbe: dma_gbe@0 {
+		reg = <0x24186000 0x100>,
+			  <0x24187000 0x2a0>,
+			  <0x24188000 0xb60>,
+			  <0x24186100 0x80>,
+			  <0x24189000 0x1000>;
+		reg-names = "global", "txchan", "rxchan",
+				"txsched", "rxflow";
+	};
+};
+
+netcp: netcp@24000000 {
+	reg = <0x2620110 0x8>;
+	reg-names = "efuse";
+	compatible = "ti,netcp-1.0";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	/* NetCP address range */
+	ranges = <0 0x24000000 0x1000000>;
+
+	clocks = <&papllclk>, <&clkcpgmac>, <&chipclk12>;
+	dma-coherent;
+
+	ti,navigator-dmas = <&dma_gbe 0>,
+			<&dma_gbe 8>,
+			<&dma_gbe 0>;
+	ti,navigator-dma-names = "netrx0", "netrx1", "nettx";
+
+	netcp-devices {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		gbe@200000 { /* ETHSS */
+			label = "netcp-gbe";
+			compatible = "ti,netcp-gbe-9";
+			reg = <0x200000 0x900>, <0x220000 0x20000>;
+			/* enable-ale; */
+			tx-queue = <896>;
+			tx-channel = "nettx";
+
+			interfaces {
+				gbe0: interface-0 {
+					slave-port = <0>;
+					link-interface	= <1>;
+					phy-handle	= <&ethphy0>;
+				};
+				gbe1: interface-1 {
+					slave-port = <1>;
+					link-interface	= <1>;
+					phy-handle	= <&ethphy1>;
+				};
+			};
+
+			secondary-slave-ports {
+				port-2 {
+					slave-port = <2>;
+					link-interface	= <2>;
+				};
+				port-3 {
+					slave-port = <3>;
+					link-interface	= <2>;
+				};
+				port-4 {
+					slave-port = <4>;
+					link-interface	= <2>;
+				};
+				port-5 {
+					slave-port = <5>;
+					link-interface	= <2>;
+				};
+				port-6 {
+					slave-port = <6>;
+					link-interface	= <2>;
+				};
+				port-7 {
+					slave-port = <7>;
+					link-interface	= <2>;
+				};
+			};
+		};
+	};
+
+	netcp-interfaces {
+		interface-0 {
+			rx-channel = "netrx0";
+			rx-pool = <1024 12>;
+			tx-pool = <1024 12>;
+			rx-queue-depth = <128 128 0 0>;
+			rx-buffer-size = <1518 4096 0 0>;
+			rx-queue = <528>;
+			tx-completion-queue = <530>;
+			efuse-mac = <1>;
+			netcp-gbe = <&gbe0>;
+
+		};
+		interface-1 {
+			rx-channel = "netrx1";
+			rx-pool = <1024 12>;
+			tx-pool = <1024 12>;
+			rx-queue-depth = <128 128 0 0>;
+			rx-buffer-size = <1518 4096 0 0>;
+			rx-queue = <529>;
+			tx-completion-queue = <531>;
+			efuse-mac = <0>;
+			local-mac-address = [02 18 31 7e 3e 00];
+			netcp-gbe = <&gbe1>;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/keystone-k2hk-clocks.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/keystone-k2hk-clocks.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/keystone-k2hk-clocks.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/keystone-k2hk-clocks.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,425 @@
+/*
+ * Copyright 2013-2014 Texas Instruments, Inc.
+ *
+ * Keystone 2 Kepler/Hawking SoC clock nodes
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+clocks {
+	armpllclk: armpllclk@2620370 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,pll-clock";
+		clocks = <&refclkarm>;
+		clock-output-names = "arm-pll-clk";
+		reg = <0x02620370 4>;
+		reg-names = "control";
+	};
+
+	mainpllclk: mainpllclk@2310110 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,main-pll-clock";
+		clocks = <&refclksys>;
+		reg = <0x02620350 4>, <0x02310110 4>, <0x02310108 4>;
+		reg-names = "control", "multiplier", "post-divider";
+	};
+
+	papllclk: papllclk@2620358 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,pll-clock";
+		clocks = <&refclkpass>;
+		clock-output-names = "papllclk";
+		reg = <0x02620358 4>;
+		reg-names = "control";
+	};
+
+	ddr3apllclk: ddr3apllclk@2620360 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,pll-clock";
+		clocks = <&refclkddr3a>;
+		clock-output-names = "ddr-3a-pll-clk";
+		reg = <0x02620360 4>;
+		reg-names = "control";
+	};
+
+	ddr3bpllclk: ddr3bpllclk@2620368 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,pll-clock";
+		clocks = <&refclkddr3b>;
+		clock-output-names = "ddr-3b-pll-clk";
+		reg = <0x02620368 4>;
+		reg-names = "control";
+	};
+
+	clktsip: clktsip {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk16>;
+		clock-output-names = "tsip";
+		reg = <0x02350000 0xb00>, <0x02350000 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <0>;
+	};
+
+	clksrio: clksrio {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk1rstiso13>;
+		clock-output-names = "srio";
+		reg = <0x0235002c 0xb00>, <0x02350010 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <4>;
+	};
+
+	clkhyperlink0: clkhyperlink0 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk12>;
+		clock-output-names = "hyperlink-0";
+		reg = <0x02350030 0xb00>, <0x02350014 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <5>;
+	};
+
+	clkgem1: clkgem1 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk1>;
+		clock-output-names = "gem1";
+		reg = <0x02350040 0xb00>, <0x02350024 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <9>;
+	};
+
+	clkgem2: clkgem2 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk1>;
+		clock-output-names = "gem2";
+		reg = <0x02350044 0xb00>, <0x02350028 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <10>;
+	};
+
+	clkgem3: clkgem3 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk1>;
+		clock-output-names = "gem3";
+		reg = <0x02350048 0xb00>, <0x0235002c 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <11>;
+	};
+
+	clkgem4: clkgem4 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk1>;
+		clock-output-names = "gem4";
+		reg = <0x0235004c 0xb00>, <0x02350030 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <12>;
+	};
+
+	clkgem5: clkgem5 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk1>;
+		clock-output-names = "gem5";
+		reg = <0x02350050 0xb00>, <0x02350034 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <13>;
+	};
+
+	clkgem6: clkgem6 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk1>;
+		clock-output-names = "gem6";
+		reg = <0x02350054 0xb00>, <0x02350038 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <14>;
+	};
+
+	clkgem7: clkgem7 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk1>;
+		clock-output-names = "gem7";
+		reg = <0x02350058 0xb00>, <0x0235003c 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <15>;
+	};
+
+	clkddr31: clkddr31 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "ddr3-1";
+		reg = <0x02350060 0xb00>, <0x02350040 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <16>;
+	};
+
+	clktac: clktac {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "tac";
+		reg = <0x02350064 0xb00>, <0x02350044 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <17>;
+	};
+
+	clkrac01: clkrac01 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "rac-01";
+		reg = <0x02350068 0xb00>, <0x02350044 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <17>;
+	};
+
+	clkrac23: clkrac23 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "rac-23";
+		reg = <0x0235006c 0xb00>, <0x02350048 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <18>;
+	};
+
+	clkfftc0: clkfftc0 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "fftc-0";
+		reg = <0x02350070 0xb00>, <0x0235004c 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <19>;
+	};
+
+	clkfftc1: clkfftc1 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "fftc-1";
+		reg = <0x02350074 0xb00>, <0x0235004c 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <19>;
+	};
+
+	clkfftc2: clkfftc2 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "fftc-2";
+		reg = <0x02350078 0xb00>, <0x02350050 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <20>;
+	};
+
+	clkfftc3: clkfftc3 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "fftc-3";
+		reg = <0x0235007c 0xb00>, <0x02350050 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <20>;
+	};
+
+	clkfftc4: clkfftc4 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "fftc-4";
+		reg = <0x02350080 0xb00>, <0x02350050 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <20>;
+	};
+
+	clkfftc5: clkfftc5 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "fftc-5";
+		reg = <0x02350084 0xb00>, <0x02350050 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <20>;
+	};
+
+	clkaif: clkaif {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "aif";
+		reg = <0x02350088 0xb00>, <0x02350054 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <21>;
+	};
+
+	clktcp3d0: clktcp3d0 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "tcp3d-0";
+		reg = <0x0235008c 0xb00>, <0x02350058 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <22>;
+	};
+
+	clktcp3d1: clktcp3d1 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "tcp3d-1";
+		reg = <0x02350090 0xb00>, <0x02350058 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <22>;
+	};
+
+	clktcp3d2: clktcp3d2 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "tcp3d-2";
+		reg = <0x02350094 0xb00>, <0x0235005c 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <23>;
+	};
+
+	clktcp3d3: clktcp3d3 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "tcp3d-3";
+		reg = <0x02350098 0xb00>, <0x0235005c 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <23>;
+	};
+
+	clkvcp0: clkvcp0 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "vcp-0";
+		reg = <0x0235009c 0xb00>, <0x02350060 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <24>;
+	};
+
+	clkvcp1: clkvcp1 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "vcp-1";
+		reg = <0x023500a0 0xb00>, <0x02350060 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <24>;
+	};
+
+	clkvcp2: clkvcp2 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "vcp-2";
+		reg = <0x023500a4 0xb00>, <0x02350060 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <24>;
+	};
+
+	clkvcp3: clkvcp3 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "vcp-3";
+		reg = <0x023500a8 0xb00>, <0x02350060 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <24>;
+	};
+
+	clkvcp4: clkvcp4 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "vcp-4";
+		reg = <0x023500ac 0xb00>, <0x02350064 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <25>;
+	};
+
+	clkvcp5: clkvcp5 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "vcp-5";
+		reg = <0x023500b0 0xb00>, <0x02350064 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <25>;
+	};
+
+	clkvcp6: clkvcp6 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "vcp-6";
+		reg = <0x023500b4 0xb00>, <0x02350064 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <25>;
+	};
+
+	clkvcp7: clkvcp7 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "vcp-7";
+		reg = <0x023500b8 0xb00>, <0x02350064 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <25>;
+	};
+
+	clkbcp: clkbcp {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "bcp";
+		reg = <0x023500bc 0xb00>, <0x02350068 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <26>;
+	};
+
+	clkdxb: clkdxb {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "dxb";
+		reg = <0x023500c0 0xb00>, <0x0235006c 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <27>;
+	};
+
+	clkhyperlink1: clkhyperlink1 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk12>;
+		clock-output-names = "hyperlink-1";
+		reg = <0x023500c4 0xb00>, <0x02350070 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <28>;
+	};
+
+	clkxge: clkxge {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "xge";
+		reg = <0x023500c8 0xb00>, <0x02350074 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <29>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/keystone-k2hk.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/keystone-k2hk.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/keystone-k2hk.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/keystone-k2hk.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2013-2014 Texas Instruments, Inc.
+ *
+ * Keystone 2 Kepler/Hawking soc specific device tree
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/ {
+	compatible = "ti,k2hk", "ti,keystone";
+	model = "Texas Instruments Keystone 2 Kepler/Hawking SoC";
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		interrupt-parent = <&gic>;
+
+		cpu@0 {
+			compatible = "arm,cortex-a15";
+			device_type = "cpu";
+			reg = <0>;
+		};
+
+		cpu@1 {
+			compatible = "arm,cortex-a15";
+			device_type = "cpu";
+			reg = <1>;
+		};
+
+		cpu@2 {
+			compatible = "arm,cortex-a15";
+			device_type = "cpu";
+			reg = <2>;
+		};
+
+		cpu@3 {
+			compatible = "arm,cortex-a15";
+			device_type = "cpu";
+			reg = <3>;
+		};
+	};
+
+	soc {
+		/include/ "keystone-k2hk-clocks.dtsi"
+
+		dspgpio0: keystone_dsp_gpio@02620240 {
+			compatible = "ti,keystone-dsp-gpio";
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio,syscon-dev = <&devctrl 0x240>;
+		};
+
+		dspgpio1: keystone_dsp_gpio@2620244 {
+			compatible = "ti,keystone-dsp-gpio";
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio,syscon-dev = <&devctrl 0x244>;
+		};
+
+		dspgpio2: keystone_dsp_gpio@2620248 {
+			compatible = "ti,keystone-dsp-gpio";
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio,syscon-dev = <&devctrl 0x248>;
+		};
+
+		dspgpio3: keystone_dsp_gpio@262024c {
+			compatible = "ti,keystone-dsp-gpio";
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio,syscon-dev = <&devctrl 0x24c>;
+		};
+
+		dspgpio4: keystone_dsp_gpio@2620250 {
+			compatible = "ti,keystone-dsp-gpio";
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio,syscon-dev = <&devctrl 0x250>;
+		};
+
+		dspgpio5: keystone_dsp_gpio@2620254 {
+			compatible = "ti,keystone-dsp-gpio";
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio,syscon-dev = <&devctrl 0x254>;
+		};
+
+		dspgpio6: keystone_dsp_gpio@2620258 {
+			compatible = "ti,keystone-dsp-gpio";
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio,syscon-dev = <&devctrl 0x258>;
+		};
+
+		dspgpio7: keystone_dsp_gpio@262025c {
+			compatible = "ti,keystone-dsp-gpio";
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio,syscon-dev = <&devctrl 0x25c>;
+		};
+
+		mdio: mdio@02090300 {
+			compatible	= "ti,keystone_mdio", "ti,davinci_mdio";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x02090300 0x100>;
+			status = "disabled";
+			clocks = <&clkcpgmac>;
+			clock-names = "fck";
+			bus_freq	= <2500000>;
+		};
+		/include/ "keystone-k2hk-netcp.dtsi"
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/keystone-k2hk-evm.dts linux-libre-4.7-gnu/arch/arm/boot/dts/keystone-k2hk-evm.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/keystone-k2hk-evm.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/keystone-k2hk-evm.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,182 @@
+/*
+ * Copyright 2013-2014 Texas Instruments, Inc.
+ *
+ * Keystone 2 Kepler/Hawking EVM device tree
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "keystone.dtsi"
+#include "keystone-k2hk.dtsi"
+
+/ {
+	compatible =  "ti,k2hk-evm", "ti,k2hk", "ti,keystone";
+	model = "Texas Instruments Keystone 2 Kepler/Hawking EVM";
+
+	soc {
+		clocks {
+			refclksys: refclksys {
+				#clock-cells = <0>;
+				compatible = "fixed-clock";
+				clock-frequency = <122880000>;
+				clock-output-names = "refclk-sys";
+			};
+
+			refclkpass: refclkpass {
+				#clock-cells = <0>;
+				compatible = "fixed-clock";
+				clock-frequency = <122880000>;
+				clock-output-names = "refclk-pass";
+			};
+
+			refclkarm: refclkarm {
+				#clock-cells = <0>;
+				compatible = "fixed-clock";
+				clock-frequency = <125000000>;
+				clock-output-names = "refclk-arm";
+			};
+
+			refclkddr3a: refclkddr3a {
+				#clock-cells = <0>;
+				compatible = "fixed-clock";
+				clock-frequency = <100000000>;
+				clock-output-names = "refclk-ddr3a";
+			};
+
+			refclkddr3b: refclkddr3b {
+				#clock-cells = <0>;
+				compatible = "fixed-clock";
+				clock-frequency = <100000000>;
+				clock-output-names = "refclk-ddr3b";
+			};
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		debug1_1 {
+			label = "keystone:green:debug1";
+			gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>; /* 12 */
+		};
+
+		debug1_2 {
+			label = "keystone:red:debug1";
+			gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>; /* 13 */
+		};
+
+		debug2 {
+			label = "keystone:blue:debug2";
+			gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>; /* 14 */
+		};
+
+		debug3 {
+			label = "keystone:blue:debug3";
+			gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>; /* 15 */
+		};
+	};
+};
+
+&usb_phy {
+	status = "okay";
+};
+
+&usb {
+	status = "okay";
+};
+
+&aemif {
+	cs0 {
+		#address-cells = <2>;
+		#size-cells = <1>;
+		clock-ranges;
+		ranges;
+
+		ti,cs-chipselect = <0>;
+		/* all timings in nanoseconds */
+		ti,cs-min-turnaround-ns = <12>;
+		ti,cs-read-hold-ns = <6>;
+		ti,cs-read-strobe-ns = <23>;
+		ti,cs-read-setup-ns = <9>;
+		ti,cs-write-hold-ns = <8>;
+		ti,cs-write-strobe-ns = <23>;
+		ti,cs-write-setup-ns = <8>;
+
+		nand@0,0 {
+			compatible = "ti,keystone-nand","ti,davinci-nand";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0 0 0x4000000
+			       1 0 0x0000100>;
+
+			ti,davinci-chipselect = <0>;
+			ti,davinci-mask-ale = <0x2000>;
+			ti,davinci-mask-cle = <0x4000>;
+			ti,davinci-mask-chipsel = <0>;
+			nand-ecc-mode = "hw";
+			ti,davinci-ecc-bits = <4>;
+			nand-on-flash-bbt;
+
+			partition@0 {
+				label = "u-boot";
+				reg = <0x0 0x100000>;
+				read-only;
+			};
+
+			partition@100000 {
+				label = "params";
+				reg = <0x100000 0x80000>;
+				read-only;
+			};
+
+			partition@180000 {
+				label = "ubifs";
+				reg = <0x180000 0x1fe80000>;
+			};
+		};
+	};
+};
+
+&i2c0 {
+	dtt@50 {
+		compatible = "at,24c1024";
+		reg = <0x50>;
+	};
+};
+
+&spi0 {
+	nor_flash: n25q128a11@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "Micron,n25q128a11";
+		spi-max-frequency = <54000000>;
+		m25p,fast-read;
+		reg = <0>;
+
+		partition@0 {
+			label = "u-boot-spl";
+			reg = <0x0 0x80000>;
+			read-only;
+		};
+
+		partition@1 {
+			label = "misc";
+			reg = <0x80000 0xf80000>;
+		};
+	};
+};
+
+&mdio {
+	status = "ok";
+	ethphy0: ethernet-phy@0 {
+		compatible = "marvell,88E1111", "ethernet-phy-ieee802.3-c22";
+		reg = <0>;
+	};
+
+	ethphy1: ethernet-phy@1 {
+		compatible = "marvell,88E1111", "ethernet-phy-ieee802.3-c22";
+		reg = <1>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/keystone-k2hk-netcp.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/keystone-k2hk-netcp.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/keystone-k2hk-netcp.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/keystone-k2hk-netcp.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,232 @@
+/*
+ * Device Tree Source for Keystone 2 Hawking Netcp driver
+ *
+ * Copyright 2015 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+qmss: qmss@2a40000 {
+	compatible = "ti,keystone-navigator-qmss";
+	dma-coherent;
+	#address-cells = <1>;
+	#size-cells = <1>;
+	clocks = <&chipclk13>;
+	ranges;
+	queue-range	= <0 0x4000>;
+	linkram0	= <0x100000 0x8000>;
+	linkram1	= <0x0 0x10000>;
+
+	qmgrs {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		qmgr0 {
+			managed-queues = <0 0x2000>;
+			reg = <0x2a40000 0x20000>,
+			      <0x2a06000 0x400>,
+			      <0x2a02000 0x1000>,
+			      <0x2a03000 0x1000>,
+			      <0x23a80000 0x20000>,
+			      <0x2a80000 0x20000>;
+			reg-names = "peek", "status", "config",
+				    "region", "push", "pop";
+		};
+
+		qmgr1 {
+			managed-queues = <0x2000 0x2000>;
+			reg = <0x2a60000 0x20000>,
+			      <0x2a06400 0x400>,
+			      <0x2a04000 0x1000>,
+			      <0x2a05000 0x1000>,
+			      <0x23aa0000 0x20000>,
+			      <0x2aa0000 0x20000>;
+			reg-names = "peek", "status", "config",
+				    "region", "push", "pop";
+		};
+	};
+
+	queue-pools {
+		qpend {
+			qpend-0 {
+				qrange = <658 8>;
+				interrupts =<0 40 0xf04 0 41 0xf04 0 42 0xf04
+					     0 43 0xf04 0 44 0xf04 0 45 0xf04
+					     0 46 0xf04 0 47 0xf04>;
+			};
+			qpend-1 {
+				qrange = <8704 16>;
+				interrupts = <0 48 0xf04 0 49 0xf04 0 50 0xf04
+					      0 51 0xf04 0 52 0xf04 0 53 0xf04
+					      0 54 0xf04 0 55 0xf04 0 56 0xf04
+					      0 57 0xf04 0 58 0xf04 0 59 0xf04
+					      0 60 0xf04 0 61 0xf04 0 62 0xf04
+					      0 63 0xf04>;
+				qalloc-by-id;
+			};
+			qpend-2 {
+				qrange = <8720 16>;
+				interrupts = <0 64 0xf04 0 65 0xf04 0 66 0xf04
+					      0 59 0xf04 0 68 0xf04 0 69 0xf04
+					      0 70 0xf04 0 71 0xf04 0 72 0xf04
+					      0 73 0xf04 0 74 0xf04 0 75 0xf04
+					      0 76 0xf04 0 77 0xf04 0 78 0xf04
+					      0 79 0xf04>;
+			};
+		};
+		general-purpose {
+			gp-0 {
+				qrange = <4000 64>;
+			};
+			netcp-tx {
+				qrange = <640 9>;
+				qalloc-by-id;
+			};
+			netcpx-tx {
+				qrange = <8752 8>;
+				qalloc-by-id;
+			};
+		};
+		accumulator {
+			acc-low-0 {
+				qrange = <480 32>;
+				accumulator = <0 47 16 2 50>;
+				interrupts = <0 226 0xf01>;
+				multi-queue;
+				qalloc-by-id;
+			};
+		};
+	};
+
+	descriptor-regions {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		region-12 {
+			id = <12>;
+			region-spec = <8192 128>;	/* num_desc desc_size */
+			link-index = <0x4000>;
+		};
+	};
+
+	pdsps {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		pdsp0@0x2a10000 {
+			reg = <0x2a10000 0x1000    /*iram */
+			       0x2a0f000 0x100     /*reg*/
+			       0x2a0c000 0x3c8	   /*intd */
+			       0x2a20000 0x4000>;  /*cmd*/
+			id = <0>;
+		};
+	};
+}; /* qmss */
+
+knav_dmas: knav_dmas@0 {
+	compatible = "ti,keystone-navigator-dma";
+	clocks = <&papllclk>;
+	#address-cells = <1>;
+	#size-cells = <1>;
+	ranges;
+	ti,navigator-cloud-address = <0x23a80000 0x23a90000
+				   0x23aa0000 0x23ab0000>;
+
+	dma_gbe: dma_gbe@0 {
+		reg = <0x2004000 0x100>,
+			  <0x2004400 0x120>,
+			  <0x2004800 0x300>,
+			  <0x2004c00 0x120>,
+			  <0x2005000 0x400>;
+		reg-names = "global", "txchan", "rxchan",
+				"txsched", "rxflow";
+	};
+};
+
+netcp: netcp@2000000 {
+	reg = <0x2620110 0x8>;
+	reg-names = "efuse";
+	compatible = "ti,netcp-1.0";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	/* NetCP address range */
+	ranges  = <0 0x2000000 0x100000>;
+
+	clocks = <&papllclk>, <&clkcpgmac>, <&chipclk12>;
+	dma-coherent;
+
+	ti,navigator-dmas = <&dma_gbe 22>,
+			<&dma_gbe 23>,
+			<&dma_gbe 8>;
+	ti,navigator-dma-names = "netrx0", "netrx1", "nettx";
+
+	netcp-devices {
+		ranges;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		gbe@90000 { /* ETHSS */
+			#address-cells = <1>;
+			#size-cells = <1>;
+			label = "netcp-gbe";
+			compatible = "ti,netcp-gbe";
+			reg = <0x90000 0x300>, <0x90400 0x400>, <0x90800 0x700>;
+			/* enable-ale; */
+			tx-queue = <648>;
+			tx-channel = "nettx";
+
+			interfaces {
+				gbe0: interface-0 {
+					slave-port = <0>;
+					link-interface = <1>;
+					phy-handle = <&ethphy0>;
+				};
+				gbe1: interface-1 {
+					slave-port = <1>;
+					link-interface = <1>;
+					phy-handle = <&ethphy1>;
+				};
+			};
+
+			secondary-slave-ports {
+				port-2 {
+					slave-port = <2>;
+					link-interface	= <2>;
+				};
+				port-3 {
+					slave-port = <3>;
+					link-interface	= <2>;
+				};
+			};
+		};
+	};
+
+	netcp-interfaces {
+		interface-0 {
+			rx-channel = "netrx0";
+			rx-pool = <1024 12>;
+			tx-pool = <1024 12>;
+			rx-queue-depth = <128 128 0 0>;
+			rx-buffer-size = <1518 4096 0 0>;
+			rx-queue = <8704>;
+			tx-completion-queue = <8706>;
+			efuse-mac = <1>;
+			netcp-gbe = <&gbe0>;
+
+		};
+		interface-1 {
+			rx-channel = "netrx1";
+			rx-pool = <1024 12>;
+			tx-pool = <1024 12>;
+			rx-queue-depth = <128 128 0 0>;
+			rx-buffer-size = <1518 4096 0 0>;
+			rx-queue = <8705>;
+			tx-completion-queue = <8707>;
+			efuse-mac = <0>;
+			local-mac-address = [02 18 31 7e 3e 6f];
+			netcp-gbe = <&gbe1>;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/keystone-k2l-clocks.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/keystone-k2l-clocks.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/keystone-k2l-clocks.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/keystone-k2l-clocks.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2013-2014 Texas Instruments, Inc.
+ *
+ * Keystone 2 lamarr SoC clock nodes
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+clocks {
+	armpllclk: armpllclk@2620370 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,pll-clock";
+		clocks = <&refclksys>;
+		clock-output-names = "arm-pll-clk";
+		reg = <0x02620370 4>;
+		reg-names = "control";
+	};
+
+	mainpllclk: mainpllclk@2310110 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,main-pll-clock";
+		clocks = <&refclksys>;
+		reg = <0x02620350 4>, <0x02310110 4>, <0x02310108 4>;
+		reg-names = "control", "multiplier", "post-divider";
+	};
+
+	papllclk: papllclk@2620358 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,pll-clock";
+		clocks = <&refclksys>;
+		clock-output-names = "papllclk";
+		reg = <0x02620358 4>;
+		reg-names = "control";
+	};
+
+	ddr3apllclk: ddr3apllclk@2620360 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,pll-clock";
+		clocks = <&refclksys>;
+		clock-output-names = "ddr-3a-pll-clk";
+		reg = <0x02620360 4>;
+		reg-names = "control";
+	};
+
+	clkdfeiqnsys: clkdfeiqnsys {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk12>;
+		clock-output-names = "dfe";
+		reg-names = "control", "domain";
+		reg = <0x02350004 0xb00>, <0x02350000 0x400>;
+		domain-id = <0>;
+	};
+
+	clkpcie1: clkpcie1 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk12>;
+		clock-output-names = "pcie";
+		reg = <0x0235002c 0xb00>, <0x02350000 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <4>;
+	};
+
+	clkgem1: clkgem1 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk1>;
+		clock-output-names = "gem1";
+		reg = <0x02350040 0xb00>, <0x02350024 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <9>;
+	};
+
+	clkgem2: clkgem2 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk1>;
+		clock-output-names = "gem2";
+		reg = <0x02350044 0xb00>, <0x02350028 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <10>;
+	};
+
+	clkgem3: clkgem3 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk1>;
+		clock-output-names = "gem3";
+		reg = <0x02350048 0xb00>, <0x0235002c 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <11>;
+	};
+
+	clktac: clktac {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "tac";
+		reg = <0x02350064 0xb00>, <0x02350044 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <17>;
+	};
+
+	clkrac: clkrac {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "rac";
+		reg = <0x02350068 0xb00>, <0x02350044 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <17>;
+	};
+
+	clkdfepd0: clkdfepd0 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "dfe-pd0";
+		reg = <0x0235006c 0xb00>, <0x02350044 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <18>;
+	};
+
+	clkfftc0: clkfftc0 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "fftc-0";
+		reg = <0x02350070 0xb00>, <0x0235004c 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <19>;
+	};
+
+	clkosr: clkosr {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "osr";
+		reg = <0x02350088 0xb00>, <0x0235004c 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <21>;
+	};
+
+	clktcp3d0: clktcp3d0 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "tcp3d-0";
+		reg = <0x0235008c 0xb00>, <0x02350058 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <22>;
+	};
+
+	clktcp3d1: clktcp3d1 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "tcp3d-1";
+		reg = <0x02350094 0xb00>, <0x02350058 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <23>;
+	};
+
+	clkvcp0: clkvcp0 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "vcp-0";
+		reg = <0x0235009c 0xb00>, <0x02350060 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <24>;
+	};
+
+	clkvcp1: clkvcp1 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "vcp-1";
+		reg = <0x023500a0 0xb00>, <0x02350060 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <24>;
+	};
+
+	clkvcp2: clkvcp2 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "vcp-2";
+		reg = <0x023500a4 0xb00>, <0x02350060 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <24>;
+	};
+
+	clkvcp3: clkvcp3 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "vcp-3";
+		reg = <0x023500a8 0xb00>, <0x02350060 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <24>;
+	};
+
+	clkbcp: clkbcp {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "bcp";
+		reg = <0x023500bc 0xb00>, <0x02350068 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <26>;
+	};
+
+	clkdfepd1: clkdfepd1 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "dfe-pd1";
+		reg = <0x023500c0 0xb00>, <0x02350044 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <27>;
+	};
+
+	clkfftc1: clkfftc1 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "fftc-1";
+		reg = <0x023500c4 0xb00>, <0x023504c0 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <28>;
+	};
+
+	clkiqnail: clkiqnail {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&chipclk13>;
+		clock-output-names = "iqn-ail";
+		reg = <0x023500c8 0xb00>, <0x0235004c 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <29>;
+	};
+
+	clkuart2: clkuart2 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&clkmodrst0>;
+		clock-output-names = "uart2";
+		reg = <0x02350000 0xb00>, <0x02350000 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <0>;
+	};
+
+	clkuart3: clkuart3 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&clkmodrst0>;
+		clock-output-names = "uart3";
+		reg = <0x02350000 0xb00>, <0x02350000 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <0>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/keystone-k2l.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/keystone-k2l.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/keystone-k2l.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/keystone-k2l.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2014 Texas Instruments, Inc.
+ *
+ * Keystone 2 Lamarr SoC specific device tree
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/ {
+	compatible = "ti,k2l", "ti,keystone";
+	model = "Texas Instruments Keystone 2 Lamarr SoC";
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		interrupt-parent = <&gic>;
+
+		cpu@0 {
+			compatible = "arm,cortex-a15";
+			device_type = "cpu";
+			reg = <0>;
+		};
+
+		cpu@1 {
+			compatible = "arm,cortex-a15";
+			device_type = "cpu";
+			reg = <1>;
+		};
+	};
+
+	soc {
+		/include/ "keystone-k2l-clocks.dtsi"
+
+		uart2: serial@02348400 {
+			compatible = "ns16550a";
+			current-speed = <115200>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			reg = <0x02348400 0x100>;
+			clocks	= <&clkuart2>;
+			interrupts = <GIC_SPI 432 IRQ_TYPE_EDGE_RISING>;
+		};
+
+		uart3:	serial@02348800 {
+			compatible = "ns16550a";
+			current-speed = <115200>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			reg = <0x02348800 0x100>;
+			clocks	= <&clkuart3>;
+			interrupts = <GIC_SPI 435 IRQ_TYPE_EDGE_RISING>;
+		};
+
+		dspgpio0: keystone_dsp_gpio@02620240 {
+			compatible = "ti,keystone-dsp-gpio";
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio,syscon-dev = <&devctrl 0x240>;
+		};
+
+		dspgpio1: keystone_dsp_gpio@2620244 {
+			compatible = "ti,keystone-dsp-gpio";
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio,syscon-dev = <&devctrl 0x244>;
+		};
+
+		dspgpio2: keystone_dsp_gpio@2620248 {
+			compatible = "ti,keystone-dsp-gpio";
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio,syscon-dev = <&devctrl 0x248>;
+		};
+
+		dspgpio3: keystone_dsp_gpio@262024c {
+			compatible = "ti,keystone-dsp-gpio";
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio,syscon-dev = <&devctrl 0x24c>;
+		};
+
+		mdio: mdio@26200f00 {
+			compatible	= "ti,keystone_mdio", "ti,davinci_mdio";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x26200f00 0x100>;
+			status = "disabled";
+			clocks = <&clkcpgmac>;
+			clock-names = "fck";
+			bus_freq	= <2500000>;
+		};
+		/include/ "keystone-k2l-netcp.dtsi"
+	};
+};
+
+&spi0 {
+       ti,davinci-spi-num-cs = <5>;
+};
+
+&spi1 {
+       ti,davinci-spi-num-cs = <3>;
+};
+
+&spi2 {
+       ti,davinci-spi-num-cs = <5>;
+       /* Pin muxed. Enabled and configured by Bootloader */
+       status = "disabled";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/keystone-k2l-evm.dts linux-libre-4.7-gnu/arch/arm/boot/dts/keystone-k2l-evm.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/keystone-k2l-evm.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/keystone-k2l-evm.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2014 Texas Instruments, Inc.
+ *
+ * Keystone 2 Lamarr EVM device tree
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "keystone.dtsi"
+#include "keystone-k2l.dtsi"
+
+/ {
+	compatible = "ti,k2l-evm", "ti,k2l", "ti,keystone";
+	model = "Texas Instruments Keystone 2 Lamarr EVM";
+
+	soc {
+		clocks {
+			refclksys: refclksys {
+				#clock-cells = <0>;
+				compatible = "fixed-clock";
+				clock-frequency = <122880000>;
+				clock-output-names = "refclk-sys";
+			};
+		};
+	};
+};
+
+&usb_phy {
+	status = "okay";
+};
+
+&usb {
+	status = "okay";
+};
+
+&i2c0 {
+	dtt@50 {
+		compatible = "at,24c1024";
+		reg = <0x50>;
+	};
+};
+
+&aemif {
+	cs0 {
+		#address-cells = <2>;
+		#size-cells = <1>;
+		clock-ranges;
+		ranges;
+
+		ti,cs-chipselect = <0>;
+		/* all timings in nanoseconds */
+		ti,cs-min-turnaround-ns = <12>;
+		ti,cs-read-hold-ns = <6>;
+		ti,cs-read-strobe-ns = <23>;
+		ti,cs-read-setup-ns = <9>;
+		ti,cs-write-hold-ns = <8>;
+		ti,cs-write-strobe-ns = <23>;
+		ti,cs-write-setup-ns = <8>;
+
+		nand@0,0 {
+			compatible = "ti,keystone-nand","ti,davinci-nand";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0 0 0x4000000
+			       1 0 0x0000100>;
+
+			ti,davinci-chipselect = <0>;
+			ti,davinci-mask-ale = <0x2000>;
+			ti,davinci-mask-cle = <0x4000>;
+			ti,davinci-mask-chipsel = <0>;
+			nand-ecc-mode = "hw";
+			ti,davinci-ecc-bits = <4>;
+			nand-on-flash-bbt;
+
+			partition@0 {
+				label = "u-boot";
+				reg = <0x0 0x100000>;
+				read-only;
+			};
+
+			partition@100000 {
+				label = "params";
+				reg = <0x100000 0x80000>;
+				read-only;
+			};
+
+			partition@180000 {
+				label = "ubifs";
+				reg = <0x180000 0x7FE80000>;
+			};
+		};
+	};
+};
+
+&spi0 {
+	nor_flash: n25q128a11@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "Micron,n25q128a11";
+		spi-max-frequency = <54000000>;
+		m25p,fast-read;
+		reg = <0>;
+
+		partition@0 {
+			label = "u-boot-spl";
+			reg = <0x0 0x80000>;
+			read-only;
+		};
+
+		partition@1 {
+			label = "misc";
+			reg = <0x80000 0xf80000>;
+		};
+	};
+};
+
+&mdio {
+	status = "ok";
+	ethphy0: ethernet-phy@0 {
+		compatible = "marvell,88E1514", "marvell,88E1510", "ethernet-phy-ieee802.3-c22";
+		reg = <0>;
+	};
+
+	ethphy1: ethernet-phy@1 {
+		compatible = "marvell,88E1514", "marvell,88E1510", "ethernet-phy-ieee802.3-c22";
+		reg = <1>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/keystone-k2l-netcp.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/keystone-k2l-netcp.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/keystone-k2l-netcp.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/keystone-k2l-netcp.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,212 @@
+/*
+ * Device Tree Source for Keystone 2 Lamarr Netcp driver
+ *
+ * Copyright 2015 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+qmss: qmss@2a40000 {
+	compatible = "ti,keystone-navigator-qmss";
+	dma-coherent;
+	#address-cells = <1>;
+	#size-cells = <1>;
+	clocks = <&chipclk13>;
+	ranges;
+	queue-range	= <0 0x2000>;
+	linkram0	= <0x100000 0x4000>;
+	linkram1	= <0x70000000 0x10000>; /* 1MB OSR mem */
+
+	qmgrs {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		qmgr0 {
+			managed-queues = <0 0x2000>;
+			reg = <0x2a40000 0x20000>,
+			      <0x2a06000 0x400>,
+			      <0x2a02000 0x1000>,
+			      <0x2a03000 0x1000>,
+			      <0x23a80000 0x20000>,
+			      <0x2a80000 0x20000>;
+			reg-names = "peek", "status", "config",
+				    "region", "push", "pop";
+		};
+	};
+	queue-pools {
+		qpend {
+			qpend-0 {
+				qrange = <658 8>;
+				interrupts =<0 40 0xf04 0 41 0xf04 0 42 0xf04
+					     0 43 0xf04 0 44 0xf04 0 45 0xf04
+					     0 46 0xf04 0 47 0xf04>;
+			};
+			qpend-1 {
+				qrange = <528 16>;
+				interrupts = <0 48 0xf04 0 49 0xf04 0 50 0xf04
+					      0 51 0xf04 0 52 0xf04 0 53 0xf04
+					      0 54 0xf04 0 55 0xf04 0 56 0xf04
+					      0 57 0xf04 0 58 0xf04 0 59 0xf04
+					      0 60 0xf04 0 61 0xf04 0 62 0xf04
+					      0 63 0xf04>;
+				qalloc-by-id;
+			};
+			qpend-2 {
+				qrange = <544 16>;
+				interrupts = <0 64 0xf04 0 65 0xf04 0 66 0xf04
+					      0 59 0xf04 0 68 0xf04 0 69 0xf04
+					      0 70 0xf04 0 71 0xf04 0 72 0xf04
+					      0 73 0xf04 0 74 0xf04 0 75 0xf04
+					      0 76 0xf04 0 77 0xf04 0 78 0xf04
+					      0 79 0xf04>;
+			};
+		};
+		general-purpose {
+			gp-0 {
+				qrange = <4000 64>;
+			};
+			netcp-tx {
+				qrange = <896 128>;
+				qalloc-by-id;
+			};
+		};
+		accumulator {
+			acc-low-0 {
+				qrange = <480 32>;
+				accumulator = <0 47 16 2 50>;
+				interrupts = <0 226 0xf01>;
+				multi-queue;
+			};
+		};
+	};
+
+	descriptor-regions {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		region-12 {
+			id = <12>;
+			region-spec = <8192 128>;	/* num_desc desc_size */
+			link-index = <0x4000>;
+		};
+	};
+
+	pdsps {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		pdsp0@0x2a10000 {
+			reg = <0x2a10000 0x1000    /*iram */
+			       0x2a0f000 0x100     /*reg*/
+			       0x2a0c000 0x3c8	   /*intd */
+			       0x2a20000 0x4000>;  /*cmd*/
+			id = <0>;
+		};
+	};
+
+}; /* qmss */
+
+knav_dmas: knav_dmas@0 {
+	compatible = "ti,keystone-navigator-dma";
+	clocks = <&papllclk>;
+	#address-cells = <1>;
+	#size-cells = <1>;
+	ranges;
+	ti,navigator-cloud-address = <0x23a80000 0x23a90000>;
+
+	dma_gbe: dma_gbe@0 {
+		reg = <0x26186000 0x100>,
+			  <0x26187000 0x2a0>,
+			  <0x26188000 0xb60>,
+			  <0x26186100 0x80>,
+			  <0x26189000 0x1000>;
+		reg-names = "global", "txchan", "rxchan",
+				"txsched", "rxflow";
+	};
+};
+
+netcp: netcp@26000000 {
+	reg = <0x2620110 0x8>;
+	reg-names = "efuse";
+	compatible = "ti,netcp-1.0";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	/* NetCP address range */
+	ranges = <0 0x26000000 0x1000000>;
+
+	clocks = <&clkosr>, <&papllclk>, <&clkcpgmac>, <&chipclk12>;
+	dma-coherent;
+
+	ti,navigator-dmas = <&dma_gbe 0>,
+			<&dma_gbe 8>,
+			<&dma_gbe 0>;
+	ti,navigator-dma-names = "netrx0", "netrx1", "nettx";
+
+	netcp-devices {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		gbe@200000 { /* ETHSS */
+			label = "netcp-gbe";
+			compatible = "ti,netcp-gbe-5";
+			reg = <0x200000 0x900>, <0x220000 0x20000>;
+			/* enable-ale; */
+			tx-queue = <896>;
+			tx-channel = "nettx";
+
+			interfaces {
+				gbe0: interface-0 {
+					slave-port = <0>;
+					link-interface	= <1>;
+					phy-handle	= <&ethphy0>;
+				};
+				gbe1: interface-1 {
+					slave-port = <1>;
+					link-interface	= <1>;
+					phy-handle	= <&ethphy1>;
+				};
+			};
+
+			secondary-slave-ports {
+				port-2 {
+					slave-port = <2>;
+					link-interface	= <2>;
+				};
+				port-3 {
+					slave-port = <3>;
+					link-interface	= <2>;
+				};
+			};
+		};
+	};
+
+	netcp-interfaces {
+		interface-0 {
+			rx-channel = "netrx0";
+			rx-pool = <1024 12>;
+			tx-pool = <1024 12>;
+			rx-queue-depth = <128 128 0 0>;
+			rx-buffer-size = <1518 4096 0 0>;
+			rx-queue = <528>;
+			tx-completion-queue = <530>;
+			efuse-mac = <1>;
+			netcp-gbe = <&gbe0>;
+
+		};
+		interface-1 {
+			rx-channel = "netrx1";
+			rx-pool = <1024 12>;
+			tx-pool = <1024 12>;
+			rx-queue-depth = <128 128 0 0>;
+			rx-buffer-size = <1518 4096 0 0>;
+			rx-queue = <529>;
+			tx-completion-queue = <531>;
+			efuse-mac = <0>;
+			local-mac-address = [02 18 31 7e 3e 7f];
+			netcp-gbe = <&gbe1>;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-6192.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-6192.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-6192.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-6192.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -1,6 +1,6 @@
 / {
-	mbus {
-		pciec: pcie-controller {
+	mbus@f1000000 {
+		pciec: pcie-controller@82000000 {
 			compatible = "marvell,kirkwood-pcie";
 			status = "disabled";
 			device_type = "pci";
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-6281.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-6281.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-6281.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-6281.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -1,6 +1,6 @@
 / {
-	mbus {
-		pciec: pcie-controller {
+	mbus@f1000000 {
+		pciec: pcie-controller@82000000 {
 			compatible = "marvell,kirkwood-pcie";
 			status = "disabled";
 			device_type = "pci";
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-6282.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-6282.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-6282.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-6282.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -1,6 +1,6 @@
 / {
-	mbus {
-		pciec: pcie-controller {
+	mbus@f1000000 {
+		pciec: pcie-controller@82000000 {
 			compatible = "marvell,kirkwood-pcie";
 			status = "disabled";
 			device_type = "pci";
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-98dx4122.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-98dx4122.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-98dx4122.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-98dx4122.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -1,6 +1,6 @@
 / {
-	mbus {
-		pciec: pcie-controller {
+	mbus@f1000000 {
+		pciec: pcie-controller@82000000 {
 			compatible = "marvell,kirkwood-pcie";
 			status = "disabled";
 			device_type = "pci";
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-b3.dts linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-b3.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-b3.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-b3.dts	2016-07-24 15:23:50.000000000 -0400
@@ -33,17 +33,6 @@
 		stdout-path = &uart0;
 	};
 
-	mbus {
-		pcie-controller {
-			status = "okay";
-
-			/* Wifi model has Atheros chipset on pcie port */
-			pcie@1,0 {
-				status = "okay";
-			};
-		};
-	};
-
 	ocp@f1000000 {
 		pinctrl: pin-controller@10000 {
 			pmx_button_power: pmx-button-power {
@@ -199,3 +188,11 @@
 	};
 };
 
+/* Wifi model has Atheros chipset on pcie port */
+&pciec {
+        status = "okay";
+};
+
+&pcie0 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-blackarmor-nas220.dts linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-blackarmor-nas220.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-blackarmor-nas220.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-blackarmor-nas220.dts	2016-07-24 15:23:50.000000000 -0400
@@ -36,13 +36,13 @@
 	gpio_keys {
 		compatible = "gpio-keys";
 
-		button@1{
+		reset {
 			label = "Reset";
 			linux,code = <KEY_POWER>;
 			gpios = <&gpio0 29 GPIO_ACTIVE_HIGH>;
 		};
 
-		button@2{
+		button {
 			label = "Power";
 			linux,code = <KEY_SLEEP>;
 			gpios = <&gpio0 26 GPIO_ACTIVE_LOW>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-cloudbox.dts linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-cloudbox.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-cloudbox.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-cloudbox.dts	2016-07-24 15:23:50.000000000 -0400
@@ -60,7 +60,7 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		button@1 {
+		power {
 			label = "Power push button";
 			linux,code = <KEY_POWER>;
 			gpios = <&gpio0 16 GPIO_ACTIVE_LOW>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-db-88f6281.dts linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-db-88f6281.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-db-88f6281.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-db-88f6281.dts	2016-07-24 15:23:50.000000000 -0400
@@ -17,14 +17,12 @@
 / {
 	model = "Marvell DB-88F6281-BP Development Board";
 	compatible = "marvell,db-88f6281-bp", "marvell,kirkwood-88f6281", "marvell,kirkwood";
+};
 
-	mbus {
-		pcie-controller {
-			status = "okay";
+&pciec {
+        status = "okay";
+};
 
-			pcie@1,0 {
-				status = "okay";
-			};
-		};
-	};
+&pcie0 {
+	status = "okay";
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-db-88f6282.dts linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-db-88f6282.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-db-88f6282.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-db-88f6282.dts	2016-07-24 15:23:50.000000000 -0400
@@ -17,18 +17,16 @@
 / {
 	model = "Marvell DB-88F6282-BP Development Board";
 	compatible = "marvell,db-88f6282-bp", "marvell,kirkwood-88f6282", "marvell,kirkwood";
+};
 
-	mbus {
-		pcie-controller {
-			status = "okay";
+&pciec {
+        status = "okay";
+};
 
-			pcie@1,0 {
-				status = "okay";
-			};
+&pcie0 {
+	status = "okay";
+};
 
-			pcie@2,0 {
-				status = "okay";
-			};
-		};
-	};
+&pcie1 {
+	status = "okay";
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-dir665.dts linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-dir665.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-dir665.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-dir665.dts	2016-07-24 15:23:50.000000000 -0400
@@ -25,16 +25,6 @@
 		stdout-path = &uart0;
 	};
 
-	mbus {
-		pcie-controller {
-			status = "okay";
-
-			pcie@1,0 {
-				status = "okay";
-			};
-		};
-	};
-
 	ocp@f1000000 {
 		pinctrl: pin-controller@10000 {
 			pinctrl-0 =< &pmx_led_usb
@@ -203,7 +193,7 @@
 		};
 	};
 
-	dsa@0 {
+	dsa {
 		compatible = "marvell,dsa";
 		#address-cells = <2>;
 		#size-cells = <0>;
@@ -276,3 +266,11 @@
 &rtc {
 	status = "disabled";
 };
+
+&pciec {
+        status = "okay";
+};
+
+&pcie0 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-dnskw.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-dnskw.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-dnskw.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-dnskw.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -13,17 +13,17 @@
 			     &pmx_button_reset>;
 		pinctrl-names = "default";
 
-		button@1 {
+		power {
 			label = "Power button";
 			linux,code = <KEY_POWER>;
 			gpios = <&gpio1 2 GPIO_ACTIVE_LOW>;
 		};
-		button@2 {
+		eject {
 			label = "USB unmount button";
 			linux,code = <KEY_EJECTCD>;
 			gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
 		};
-		button@3 {
+		reset {
 			label = "Reset button";
 			linux,code = <KEY_RESTART>;
 			gpios = <&gpio1 16 GPIO_ACTIVE_LOW>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-ds111.dts linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-ds111.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-ds111.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-ds111.dts	2016-07-24 15:23:50.000000000 -0400
@@ -40,6 +40,6 @@
 	status = "okay";
 };
 
-&pcie2 {
+&pcie1 {
 	status = "okay";
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-ds112.dts linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-ds112.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-ds112.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-ds112.dts	2016-07-24 15:23:50.000000000 -0400
@@ -44,6 +44,10 @@
 	status = "okay";
 };
 
-&pcie2 {
+&pciec {
+        status = "okay";
+};
+
+&pcie1 {
 	status = "okay";
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-ds212.dts linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-ds212.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-ds212.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-ds212.dts	2016-07-24 15:23:50.000000000 -0400
@@ -43,6 +43,6 @@
 	status = "okay";
 };
 
-&pcie2 {
+&pcie1 {
 	status = "okay";
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-ds411.dts linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-ds411.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-ds411.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-ds411.dts	2016-07-24 15:23:50.000000000 -0400
@@ -48,6 +48,10 @@
 	status = "okay";
 };
 
-&pcie2 {
+&pciec {
+        status = "okay";
+};
+
+&pcie1 {
 	status = "okay";
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-ds411slim.dts linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-ds411slim.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-ds411slim.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-ds411slim.dts	2016-07-24 15:23:50.000000000 -0400
@@ -44,6 +44,6 @@
 	status = "okay";
 };
 
-&pcie2 {
+&pcie1 {
 	status = "okay";
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -27,7 +27,7 @@
 	       i2c0 = &i2c0;
 	};
 
-	mbus {
+	mbus@f1000000 {
 		compatible = "marvell,kirkwood-mbus", "simple-bus";
 		#address-cells = <2>;
 		#size-cells = <1>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-ib62x0.dts linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-ib62x0.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-ib62x0.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-ib62x0.dts	2016-07-24 15:23:50.000000000 -0400
@@ -62,12 +62,12 @@
 		pinctrl-0 = <&pmx_button_reset &pmx_button_usb_copy>;
 		pinctrl-names = "default";
 
-		button@1 {
+		copy {
 			label = "USB Copy";
 			linux,code = <KEY_COPY>;
 			gpios = <&gpio0 29 GPIO_ACTIVE_LOW>;
 		};
-		button@2 {
+		reset {
 			label = "Reset";
 			linux,code = <KEY_RESTART>;
 			gpios = <&gpio0 28 GPIO_ACTIVE_LOW>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-iconnect.dts linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-iconnect.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-iconnect.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-iconnect.dts	2016-07-24 15:23:50.000000000 -0400
@@ -19,16 +19,6 @@
 		linux,initrd-end   = <0x4800000>;
 	};
 
-	mbus {
-		pcie-controller {
-			status = "okay";
-
-			pcie@1,0 {
-				status = "okay";
-			};
-		};
-	};
-
 	ocp@f1000000 {
 		pinctrl: pin-controller@10000 {
 			pmx_button_reset: pmx-button-reset {
@@ -136,13 +126,13 @@
 		pinctrl-0 = < &pmx_button_reset &pmx_button_otb >;
 		pinctrl-names = "default";
 
-		button@1 {
+		otb {
 			label = "OTB Button";
 			linux,code = <KEY_COPY>;
 			gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;
 			debounce-interval = <100>;
 		};
-		button@2 {
+		reset {
 			label = "Reset";
 			linux,code = <KEY_RESTART>;
 			gpios = <&gpio0 12 GPIO_ACTIVE_LOW>;
@@ -194,3 +184,11 @@
 		phy-handle = <&ethphy0>;
 	};
 };
+
+&pciec {
+        status = "okay";
+};
+
+&pcie0 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-km_common.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-km_common.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-km_common.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-km_common.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -4,16 +4,6 @@
 		stdout-path = &uart0;
 	};
 
-	mbus {
-		pcie-controller {
-			status = "okay";
-
-			pcie@1,0 {
-				status = "okay";
-			};
-		};
-	};
-
 	ocp@f1000000 {
 		pinctrl: pin-controller@10000 {
 			pinctrl-0 = < &pmx_i2c_gpio_sda &pmx_i2c_gpio_scl >;
@@ -34,7 +24,7 @@
 		};
 	};
 
-	i2c@0 {
+	i2c {
 		compatible = "i2c-gpio";
 		gpios = < &gpio0 8 GPIO_ACTIVE_HIGH		/* sda */
 			  &gpio0 9 GPIO_ACTIVE_HIGH>;		/* scl */
@@ -46,3 +36,11 @@
 	status = "okay";
 	chip-delay = <25>;
 };
+
+&pciec {
+        status = "okay";
+};
+
+&pcie0 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-laplug.dts linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-laplug.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-laplug.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-laplug.dts	2016-07-24 15:23:50.000000000 -0400
@@ -27,15 +27,6 @@
 		stdout-path = &uart0;
 	};
 
-	mbus {
-		pcie-controller {
-			status = "okay";
-			pcie@1,0 {
-				status = "okay";
-			};
-		};
-	};
-
 	ocp@f1000000 {
 		serial@12000 {
 			status = "okay";
@@ -62,7 +53,7 @@
 	gpio_keys {
 		compatible = "gpio-keys";
 
-		button@1{
+		power {
 			label = "Power push button";
 			linux,code = <KEY_POWER>;
 			gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>;
@@ -169,3 +160,11 @@
 		phy-handle = <&ethphy0>;
 	};
 };
+
+&pciec {
+        status = "okay";
+};
+
+&pcie0 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-linkstation.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-linkstation.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-linkstation.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-linkstation.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -49,15 +49,6 @@
 		stdout-path = &uart0;
 	};
 
-	mbus {
-		pcie-controller {
-			status = "okay";
-			pcie@1,0 {
-				status = "okay";
-			};
-		};
-	};
-
 	ocp@f1000000 {
 		pinctrl: pin-controller@10000 {
 			pmx_power_hdd0: pmx-power-hdd0 {
@@ -200,3 +191,11 @@
 		};
 	};
 };
+
+&pciec {
+        status = "okay";
+};
+
+&pcie0 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-linksys-viper.dts linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-linksys-viper.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-linksys-viper.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-linksys-viper.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,240 @@
+/*
+ * kirkwood-viper.dts - Device Tree file for Linksys viper (E4200v2 / EA4500)
+ *
+ * (c) 2013 Jonas Gorski <jogo@openwrt.org>
+ * (c) 2013 Deutsche Telekom Innovation Laboratories
+ * (c) 2014 Luka Perkov <luka@openwrt.org>
+ * (c) 2014 Randy C. Will <randall.will@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+/dts-v1/;
+
+#include "kirkwood.dtsi"
+#include "kirkwood-6282.dtsi"
+
+/ {
+	model = "Linksys Viper (E4200v2 / EA4500)";
+	compatible = "linksys,viper", "marvell,kirkwood-88f6282", "marvell,kirkwood";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x8000000>;
+	};
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		pinctrl-0 = < &pmx_btn_wps &pmx_btn_reset >;
+		pinctrl-names = "default";
+
+		wps {
+			label = "WPS Button";
+			linux,code = <KEY_WPS_BUTTON>;
+			gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
+		};
+
+		reset {
+			label = "Reset Button";
+			linux,code = <KEY_RESTART>;
+			gpios = <&gpio1 16 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+		pinctrl-0 = < &pmx_led_white_health &pmx_led_white_pulse >;
+		pinctrl-names = "default";
+
+		white-health {
+			label = "viper:white:health";
+			gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>;
+		};
+
+		white-pulse {
+			label = "viper:white:pulse";
+			gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>;
+		};
+	};
+
+	dsa {
+		compatible = "marvell,dsa";
+		#address-cells = <2>;
+		#size-cells = <0>;
+
+		dsa,ethernet = <&eth0port>;
+		dsa,mii-bus = <&mdio>;
+
+		switch@16,0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <16 0>;	/* MDIO address 16, switch 0 in tree */
+
+			port@0 {
+				reg = <0>;
+				label = "ethernet1";
+			};
+
+			port@1 {
+				reg = <1>;
+				label = "ethernet2";
+			};
+
+			port@2 {
+				reg = <2>;
+				label = "ethernet3";
+			};
+
+			port@3 {
+				reg = <3>;
+				label = "ethernet4";
+			};
+
+			port@4 {
+				reg = <4>;
+				label = "internet";
+			};
+
+			port@5 {
+				reg = <5>;
+				label = "cpu";
+			};
+		};
+	};
+};
+
+&pinctrl {
+	pmx_led_white_health: pmx-led-white-health {
+		marvell,pins = "mpp7";
+		marvell,function = "gpo";
+	};
+	pmx_led_white_pulse: pmx-led-white-pulse {
+		marvell,pins = "mpp14";
+		marvell,function = "gpio";
+	};
+	pmx_btn_wps: pmx-btn-wps {
+		marvell,pins = "mpp47";
+		marvell,function = "gpio";
+	};
+	pmx_btn_reset: pmx-btn-reset {
+		marvell,pins = "mpp48";
+		marvell,function = "gpio";
+	};
+};
+
+&nand {
+	status = "okay";
+	pinctrl-0 = <&pmx_nand>;
+	pinctrl-names = "default";
+
+	partitions {
+		compatible = "fixed-partitions";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		partition@0 {
+			label = "u-boot";
+			reg = <0x0 0x80000>;
+			read-only;
+		};
+
+		partition@80000 {
+			label = "u_env";
+			reg = <0x80000 0x20000>;
+		};
+
+		partition@A0000 {
+			label = "s_env";
+			reg = <0xA0000 0x20000>;
+		};
+
+		partition@200000 {
+			label = "kernel";
+			reg = <0x200000 0x2A0000>;
+		};
+
+		partition@4A0000 {
+			label = "rootfs";
+			reg = <0x4A0000 0x1760000>;
+		};
+
+		partition@1C00000 {
+			label = "alt_kernel";
+			reg = <0x1C00000 0x2A0000>;
+		};
+
+		partition@1EA0000 {
+			label = "alt_rootfs";
+			reg = <0x1EA0000 0x1760000>;
+		};
+
+		partition@3600000 {
+			label = "syscfg";
+			reg = <0x3600000 0x4A00000>;
+		};
+
+		partition@C0000 {
+			label = "unused";
+			reg = <0xC0000 0x140000>;
+		};
+
+	};
+};
+
+&pciec {
+	status = "okay";
+};
+
+&pcie0 {
+	status = "okay";
+};
+
+&pcie1 {
+	status = "okay";
+};
+
+&mdio {
+	status = "okay";
+};
+
+&uart0 {
+	status = "okay";
+};
+
+/* eth0 is connected to a Marvell 88E6171 switch, without a PHY. So set
+ * fixed speed and duplex.
+ */
+&eth0 {
+	status = "okay";
+	ethernet0-port@0 {
+		speed = <1000>;
+		duplex = <1>;
+	};
+};
+
+/* eth1 is connected to the switch at port 6. However DSA only supports a
+ * single CPU port. So leave this port disabled to avoid confusion.
+ */
+&eth1 {
+	status = "disabled";
+};
+
+/* There is no battery on the board, so the RTC does not keep
+ * time when there is no power, making it useless.
+ */
+&rtc {
+	status = "disabled";
+};
+
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-lsxl.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-lsxl.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-lsxl.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-lsxl.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -107,18 +107,18 @@
 			     &pmx_power_auto_switch>;
 		pinctrl-names = "default";
 
-		button@1 {
+		option {
 			label = "Function Button";
 			linux,code = <KEY_OPTION>;
 			gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
 		};
-		button@2 {
+		reserved {
 			label = "Power-on Switch";
 			linux,code = <KEY_RESERVED>;
 			linux,input-type = <5>;
 			gpios = <&gpio1 10 GPIO_ACTIVE_LOW>;
 		};
-		button@3 {
+		power {
 			label = "Power-auto Switch";
 			linux,code = <KEY_ESC>;
 			linux,input-type = <5>;
@@ -133,28 +133,28 @@
 			     &pmx_led_function_blue>;
 		pinctrl-names = "default";
 
-		led@1 {
+		func_blue {
 			label = "lsxl:blue:func";
 			gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
 		};
 
-		led@2 {
+		alarm {
 			label = "lsxl:red:alarm";
 			gpios = <&gpio1 5 GPIO_ACTIVE_LOW>;
 		};
 
-		led@3 {
+		info {
 			label = "lsxl:amber:info";
 			gpios = <&gpio1 6 GPIO_ACTIVE_LOW>;
 		};
 
-		led@4 {
+		power {
 			label = "lsxl:blue:power";
 			gpios = <&gpio1 7 GPIO_ACTIVE_LOW>;
 			default-state = "keep";
 		};
 
-		led@5 {
+		func_red {
 			label = "lsxl:red:func";
 			gpios = <&gpio1 16 GPIO_ACTIVE_LOW>;
 		};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-mplcec4.dts linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-mplcec4.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-mplcec4.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-mplcec4.dts	2016-07-24 15:23:50.000000000 -0400
@@ -17,16 +17,6 @@
 		stdout-path = &uart0;
 	};
 
-	mbus {
-		pcie-controller {
-			status = "okay";
-
-			pcie@1,0 {
-				status = "okay";
-			};
-		};
-	};
-
 	ocp@f1000000 {
 		pinctrl: pin-controller@10000 {
 			pmx_led_health: pmx-led-health {
@@ -215,3 +205,11 @@
 		phy-handle = <&ethphy1>;
 	};
 };
+
+&pciec {
+        status = "okay";
+};
+
+&pcie0 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts	2016-07-24 15:23:50.000000000 -0400
@@ -31,16 +31,6 @@
 		stdout-path = &uart0;
 	};
 
-	mbus {
-		pcie-controller {
-			status = "okay";
-
-			pcie@1,0 {
-				status = "okay";
-			};
-		};
-        };
-
 	ocp@f1000000 {
 		pin-controller@10000 {
 			pmx_usb_led: pmx-usb-led {
@@ -109,19 +99,19 @@
 		pinctrl-0 = <&pmx_keys>;
 		pinctrl-names = "default";
 
-		button@1 {
+		restart {
 			label = "SWR Button";
 			linux,code = <KEY_RESTART>;
 			gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
 		};
-		button@2 {
+		wps {
 			label = "WPS Button";
 			linux,code = <KEY_WPS_BUTTON>;
 			gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
 		};
 	};
 
-	dsa@0 {
+	dsa {
 		compatible = "marvell,dsa";
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -179,3 +169,11 @@
 		duplex = <1>;
 	};
 };
+
+&pciec {
+        status = "okay";
+};
+
+&pcie0 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-nas2big.dts linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-nas2big.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-nas2big.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-nas2big.dts	2016-07-24 15:23:50.000000000 -0400
@@ -28,16 +28,6 @@
 		stdout-path = &uart0;
 	};
 
-	mbus {
-		pcie-controller {
-			status = "okay";
-
-			pcie@1,0 {
-				status = "okay";
-			};
-		};
-	};
-
 	ocp@f1000000 {
 		rtc@10300 {
 			/* The on-chip RTC is not powered (no supercap). */
@@ -141,3 +131,11 @@
 		reg = <0x9100000 0x6f00000>;
 	};
 };
+
+&pciec {
+        status = "okay";
+};
+
+&pcie0 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-netgear_readynas_duo_v2.dts linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-netgear_readynas_duo_v2.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-netgear_readynas_duo_v2.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-netgear_readynas_duo_v2.dts	2016-07-24 15:23:50.000000000 -0400
@@ -28,16 +28,6 @@
 		stdout-path = &uart0;
 	};
 
-	mbus {
-		pcie-controller {
-			status = "okay";
-
-			pcie@1,0 {
-				status = "okay";
-			};
-		};
-	};
-
 	ocp@f1000000 {
 		pinctrl: pin-controller@10000 {
 			pmx_button_power: pmx-button-power {
@@ -193,7 +183,7 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		usb3_regulator: usb3-regulator {
+		usb3_regulator: usb3-regulator@1 {
 			compatible = "regulator-fixed";
 			reg = <1>;
 			regulator-name = "USB 3.0 Power";
@@ -251,3 +241,11 @@
 		phy-handle = <&ethphy0>;
 	};
 };
+
+&pciec {
+        status = "okay";
+};
+
+&pcie0 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-netgear_readynas_nv+_v2.dts linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-netgear_readynas_nv+_v2.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-netgear_readynas_nv+_v2.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-netgear_readynas_nv+_v2.dts	2016-07-24 15:23:50.000000000 -0400
@@ -28,18 +28,6 @@
 		stdout-path = &uart0;
 	};
 
-	mbus {
-		pcie-controller {
-			status = "okay";
-
-			/* Connected to NEC uPD720200 USB 3.0 controller */
-			pcie@1,0 {
-				/* Port 0, Lane 0 */
-				status = "okay";
-			};
-		};
-	};
-
 	ocp@f1000000 {
 		pinctrl: pin-controller@10000 {
 			pmx_button_power: pmx-button-power {
@@ -205,7 +193,7 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		usb3_regulator: usb3-regulator {
+		usb3_regulator: usb3-regulator@1 {
 			compatible = "regulator-fixed";
 			reg = <1>;
 			regulator-name = "USB 3.0 Power";
@@ -265,3 +253,12 @@
 		phy-handle = <&ethphy0>;
 	};
 };
+
+/* Connected to NEC uPD720200 USB 3.0 controller */
+&pciec {
+        status = "okay";
+};
+
+&pcie0 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-netxbig.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-netxbig.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-netxbig.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-netxbig.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -59,22 +59,22 @@
 		#size-cells = <0>;
 
 		/*
-		 * button@1 and button@2 represent a three position rocker
+		 * esc and power represent a three position rocker
 		 * switch. Thus the conventional KEY_POWER does not fit
 		 */
-		button@1 {
+		exc {
 			label = "Back power switch (on|auto)";
 			linux,code = <KEY_ESC>;
 			linux,input-type = <5>;
 			gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
 		};
-		button@2 {
+		power {
 			label = "Back power switch (auto|off)";
 			linux,code = <KEY_1>;
 			linux,input-type = <5>;
 			gpios = <&gpio0 15 GPIO_ACTIVE_LOW>;
 		};
-		button@3 {
+		option {
 			label = "Function button";
 			linux,code = <KEY_OPTION>;
 			gpios = <&gpio1 2 GPIO_ACTIVE_LOW>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-ns2-common.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-ns2-common.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-ns2-common.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-ns2-common.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -57,7 +57,7 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		button@1 {
+		power {
 			label = "Power push button";
 			linux,code = <KEY_POWER>;
 			gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>;
@@ -83,7 +83,7 @@
 &mdio {
 	status = "okay";
 
-	ethphy0: ethernet-phy {
+	ethphy0: ethernet-phy@X {
                 /* overwrite reg property in board file */
 	};
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-nsa310.dts linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-nsa310.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-nsa310.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-nsa310.dts	2016-07-24 15:23:50.000000000 -0400
@@ -15,16 +15,6 @@
 		stdout-path = &uart0;
 	};
 
-	mbus {
-		pcie-controller {
-			status = "okay";
-
-			pcie@1,0 {
-				status = "okay";
-			};
-		};
-	};
-
 	ocp@f1000000 {
 		pinctrl: pin-controller@10000 {
 			pinctrl-0 = <&pmx_unknown>;
@@ -138,3 +128,11 @@
 		};
 	};
 };
+
+&pciec {
+        status = "okay";
+};
+
+&pcie0 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-nsa320.dts linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-nsa320.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-nsa320.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-nsa320.dts	2016-07-24 15:23:50.000000000 -0400
@@ -27,16 +27,6 @@
 		stdout-path = &uart0;
 	};
 
-	mbus {
-		pcie-controller {
-			status = "okay";
-
-			pcie@1,0 {
-				status = "okay";
-			};
-		};
-	};
-
 	ocp@f1000000 {
 		pinctrl: pin-controller@10000 {
 			pinctrl-names = "default";
@@ -193,10 +183,19 @@
 		};
 	};
 
+	hwmon {
+		compatible = "zyxel,nsa320-mcu";
+		pinctrl-0 = <&pmx_mcu_data &pmx_mcu_clk &pmx_mcu_act>;
+		pinctrl-names = "default";
+
+		data-gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>;
+		clk-gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>;
+		act-gpios = <&gpio0 17 GPIO_ACTIVE_LOW>;
+	};
+
 	/* The following pins are currently not assigned to a driver,
 	   some of them should be configured as inputs.
-	pinctrl-0 = <&pmx_mcu_data &pmx_mcu_clk &pmx_mcu_act
-		     &pmx_htp &pmx_vid_b1
+	pinctrl-0 = <&pmx_htp &pmx_vid_b1
 		     &pmx_power_resume_data &pmx_power_resume_clk>; */
 };
 
@@ -213,3 +212,11 @@
 		phy-handle = <&ethphy0>;
 	};
 };
+
+&pciec {
+        status = "okay";
+};
+
+&pcie0 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-nsa325.dts linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-nsa325.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-nsa325.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-nsa325.dts	2016-07-24 15:23:50.000000000 -0400
@@ -28,16 +28,6 @@
 		stdout-path = &uart0;
 	};
 
-	mbus {
-		pcie-controller {
-			status = "okay";
-
-			pcie@1,0 {
-				status = "okay";
-			};
-		};
-	};
-
 	ocp@f1000000 {
 		pinctrl: pin-controller@10000 {
 			pinctrl-names = "default";
@@ -236,3 +226,10 @@
 	};
 };
 
+&pciec {
+        status = "okay";
+};
+
+&pcie0 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-nsa3x0-common.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-nsa3x0-common.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-nsa3x0-common.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-nsa3x0-common.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -4,16 +4,6 @@
 / {
 	model = "ZyXEL NSA310";
 
-	mbus {
-		pcie-controller {
-			status = "okay";
-
-			pcie@1,0 {
-				status = "okay";
-			};
-		};
-	};
-
 	ocp@f1000000 {
 		pinctrl: pin-controller@10000 {
 
@@ -77,17 +67,17 @@
 		pinctrl-0 = <&pmx_btn_reset &pmx_btn_copy &pmx_btn_power>;
 		pinctrl-names = "default";
 
-		button@1 {
+		power {
 			label = "Power Button";
 			linux,code = <KEY_POWER>;
 			gpios = <&gpio1 14 GPIO_ACTIVE_HIGH>;
 		};
-		button@2 {
+		copy {
 			label = "Copy Button";
 			linux,code = <KEY_COPY>;
 			gpios = <&gpio1 5 GPIO_ACTIVE_LOW>;
 		};
-		button@3 {
+		reset {
 			label = "Reset Button";
 			linux,code = <KEY_RESTART>;
 			gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
@@ -157,3 +147,11 @@
 		reg = <0x5040000 0x2fc0000>;
 	};
 };
+
+&pciec {
+        status = "okay";
+};
+
+&pcie0 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-openblocks_a6.dts linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-openblocks_a6.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-openblocks_a6.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-openblocks_a6.dts	2016-07-24 15:23:50.000000000 -0400
@@ -117,7 +117,7 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		button@1 {
+		power {
 			label = "Init Button";
 			linux,code = <KEY_POWER>;
 			gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-openblocks_a7.dts linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-openblocks_a7.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-openblocks_a7.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-openblocks_a7.dts	2016-07-24 15:23:50.000000000 -0400
@@ -135,7 +135,7 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		button@1 {
+		button {
 			label = "Init Button";
 			linux,code = <KEY_POWER>;
 			gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-openrd.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-openrd.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-openrd.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-openrd.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -25,16 +25,6 @@
 		stdout-path = &uart0;
 	};
 
-	mbus {
-		pcie-controller {
-			status = "okay";
-
-			pcie@1,0 {
-				status = "okay";
-			};
-		};
-	};
-
 	ocp@f1000000 {
 		pinctrl: pin-controller@10000 {
 			pinctrl-0 = <&pmx_select28 &pmx_sdio_cd &pmx_select34>;
@@ -125,3 +115,7 @@
 		reg = <0x0600000 0x1FA00000>;
 	};
 };
+
+&pcie0 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-pogoplug-series-4.dts linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-pogoplug-series-4.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-pogoplug-series-4.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-pogoplug-series-4.dts	2016-07-24 15:23:50.000000000 -0400
@@ -33,7 +33,7 @@
 		pinctrl-0 = <&pmx_button_eject>;
 		pinctrl-names = "default";
 
-		button@1 {
+		eject {
 			debounce_interval = <50>;
 			wakeup-source;
 			linux,code = <KEY_EJECTCD>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-rd88f6192.dts linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-rd88f6192.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-rd88f6192.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-rd88f6192.dts	2016-07-24 15:23:50.000000000 -0400
@@ -29,16 +29,6 @@
 		stdout-path = &uart0;
 	};
 
-	mbus {
-		pcie-controller {
-			status = "okay";
-
-			pcie@1,0 {
-				status = "okay";
-			};
-		};
-	};
-
 	ocp@f1000000 {
 		pinctrl: pin-controller@10000 {
 			pinctrl-0 = <&pmx_usb_power>;
@@ -108,4 +98,12 @@
         ethernet0-port@0 {
                 phy-handle = <&ethphy0>;
         };
-};
\ No newline at end of file
+};
+
+&pciec {
+        status = "okay";
+};
+
+&pcie0 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-rd88f6281-a.dts linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-rd88f6281-a.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-rd88f6281-a.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-rd88f6281-a.dts	2016-07-24 15:23:50.000000000 -0400
@@ -19,7 +19,7 @@
 	model = "Marvell RD88f6281 Reference design, with A0 or higher SoC";
 	compatible = "marvell,rd88f6281-a", "marvell,rd88f6281","marvell,kirkwood-88f6281", "marvell,kirkwood";
 
-	dsa@0 {
+	dsa {
 		switch@0 {
 			reg = <10 0>;	 /* MDIO address 10, switch 0 in tree */
 		};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-rd88f6281.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-rd88f6281.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-rd88f6281.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-rd88f6281.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -25,16 +25,6 @@
 		stdout-path = &uart0;
 	};
 
-	mbus {
-		pcie-controller {
-			status = "okay";
-
-			pcie@1,0 {
-				status = "okay";
-			};
-		};
-	};
-
 	ocp@f1000000 {
 		pinctrl: pin-controller@10000 {
 			pinctrl-names = "default";
@@ -63,7 +53,7 @@
 		};
 	};
 
-	dsa@0 {
+	dsa {
 		compatible = "marvell,dsa";
 		#address-cells = <2>;
 		#size-cells = <0>;
@@ -134,3 +124,11 @@
 		duplex = <1>;
 	};
 };
+
+&pciec {
+        status = "okay";
+};
+
+&pcie0 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-rd88f6281-z0.dts linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-rd88f6281-z0.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-rd88f6281-z0.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-rd88f6281-z0.dts	2016-07-24 15:23:50.000000000 -0400
@@ -19,7 +19,7 @@
 	model = "Marvell RD88f6281 Reference design, with Z0 SoC";
 	compatible = "marvell,rd88f6281-z0", "marvell,rd88f6281","marvell,kirkwood-88f6281", "marvell,kirkwood";
 
-	dsa@0 {
+	dsa {
 		switch@0 {
 			reg = <0 0>;    /* MDIO address 0, switch 0 in tree */
 			port@4 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-rs212.dts linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-rs212.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-rs212.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-rs212.dts	2016-07-24 15:23:50.000000000 -0400
@@ -44,6 +44,10 @@
 	status = "okay";
 };
 
-&pcie2 {
+&pciec {
+        status = "okay";
+};
+
+&pcie1 {
 	status = "okay";
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-synology.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-synology.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-synology.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-synology.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -10,20 +10,6 @@
  */
 
 / {
-	mbus {
-		pcie-controller {
-			status = "okay";
-
-			pcie@1,0 {
-				status = "okay";
-			};
-
-			pcie2: pcie@2,0 {
-				status = "disabled";
-			};
-		};
-	};
-
 	ocp@f1000000 {
 		pinctrl: pin-controller@10000 {
 			pmx_alarmled_12: pmx-alarmled-12 {
@@ -861,3 +847,11 @@
 		phy-handle = <&ethphy1>;
 	};
 };
+
+&pciec {
+        status = "okay";
+};
+
+&pcie0 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-t5325.dts linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-t5325.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-t5325.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-t5325.dts	2016-07-24 15:23:50.000000000 -0400
@@ -30,16 +30,6 @@
 		stdout-path = &uart0;
 	};
 
-	mbus {
-		pcie-controller {
-			status = "okay";
-
-			pcie@1,0 {
-				status = "okay";
-			};
-		};
-	};
-
 	ocp@f1000000 {
 		pinctrl: pin-controller@10000 {
 			pinctrl-0 = <&pmx_i2s &pmx_sysrst>;
@@ -173,7 +163,7 @@
 		pinctrl-0 = <&pmx_button_power>;
 		pinctrl-names = "default";
 
-		button@1 {
+		power {
 			label = "Power Button";
 			linux,code = <KEY_POWER>;
 			gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>;
@@ -217,7 +207,7 @@
 &mdio {
 	status = "okay";
 
-	ethphy0: ethernet-phy {
+	ethphy0: ethernet-phy@8 {
 		device_type = "ethernet-phy";
 		reg = <8>;
 	};
@@ -229,3 +219,11 @@
 		phy-handle = <&ethphy0>;
 	};
 };
+
+&pciec {
+        status = "okay";
+};
+
+&pcie0 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-ts219-6281.dts linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-ts219-6281.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-ts219-6281.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-ts219-6281.dts	2016-07-24 15:23:50.000000000 -0400
@@ -39,12 +39,12 @@
 		pinctrl-0 = <&pmx_reset_button &pmx_USB_copy_button>;
 		pinctrl-names = "default";
 
-		button@1 {
+		copy {
 			label = "USB Copy";
 			linux,code = <KEY_COPY>;
 			gpios = <&gpio0 15 GPIO_ACTIVE_LOW>;
 		};
-		button@2 {
+		reset {
 			label = "Reset";
 			linux,code = <KEY_RESTART>;
 			gpios = <&gpio0 16 GPIO_ACTIVE_LOW>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-ts219-6282.dts linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-ts219-6282.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-ts219-6282.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-ts219-6282.dts	2016-07-24 15:23:50.000000000 -0400
@@ -5,16 +5,6 @@
 #include "kirkwood-ts219.dtsi"
 
 / {
-	mbus {
-		pcie-controller {
-			status = "okay";
-
-			pcie@2,0 {
-				status = "okay";
-			};
-		};
-	};
-
 	ocp@f1000000 {
 		pinctrl: pin-controller@10000 {
 
@@ -49,12 +39,12 @@
 		pinctrl-0 = <&pmx_reset_button &pmx_USB_copy_button>;
 		pinctrl-names = "default";
 
-		button@1 {
+		copy {
 			label = "USB Copy";
 			linux,code = <KEY_COPY>;
 			gpios = <&gpio1 11 GPIO_ACTIVE_LOW>;
 		};
-		button@2 {
+		reset {
 			label = "Reset";
 			linux,code = <KEY_RESTART>;
 			gpios = <&gpio1 5 GPIO_ACTIVE_LOW>;
@@ -63,3 +53,5 @@
 };
 
 &ethphy0 { reg = <0>; };
+
+&pcie1 { status = "okay"; };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-ts219.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-ts219.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-ts219.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-ts219.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -12,16 +12,6 @@
 		stdout-path = &uart0;
 	};
 
-	mbus {
-		pcie-controller {
-			status = "okay";
-
-			pcie@1,0 {
-				status = "okay";
-			};
-		};
-	};
-
 	ocp@f1000000 {
 		i2c@11000 {
 			status = "okay";
@@ -94,7 +84,7 @@
 &mdio {
 	status = "okay";
 
-	ethphy0: ethernet-phy {
+	ethphy0: ethernet-phy@X {
                 /* overwrite reg property in board file */
 	};
 };
@@ -105,3 +95,11 @@
 		phy-handle = <&ethphy0>;
 	};
 };
+
+&pciec {
+        status = "okay";
+};
+
+&pcie0 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-ts419-6282.dts linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-ts419-6282.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-ts419-6282.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-ts419-6282.dts	2016-07-24 15:23:50.000000000 -0400
@@ -16,17 +16,8 @@
 #include "kirkwood-ts219.dtsi"
 #include "kirkwood-ts419.dtsi"
 
-/ {
-	mbus {
-		pcie-controller {
-			status = "okay";
-
-			pcie@2,0 {
-				status = "okay";
-			};
-		};
-	};
-};
-
 &ethphy0 { reg = <0>; };
 &ethphy1 { reg = <1>; };
+
+&pciec { status = "okay"; };
+&pcie1 { status = "okay"; };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-ts419.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-ts419.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/kirkwood-ts419.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/kirkwood-ts419.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -45,12 +45,12 @@
 		pinctrl-0 = <&pmx_reset_button &pmx_USB_copy_button>;
 		pinctrl-names = "default";
 
-		button@1 {
+		copy {
 			label = "USB Copy";
 			linux,code = <KEY_COPY>;
 			gpios = <&gpio1 11 GPIO_ACTIVE_LOW>;
 		};
-		button@2 {
+		reset {
 			label = "Reset";
 			linux,code = <KEY_RESTART>;
 			gpios = <&gpio1 5 GPIO_ACTIVE_LOW>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/lpc18xx.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/lpc18xx.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/lpc18xx.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/lpc18xx.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -195,13 +195,19 @@
 			clocks = <&ccu1 CLK_CPU_CREG>;
 			resets = <&rgu 5>;
 
-			usb0_otg_phy: phy@004 {
+			creg_clk: clock-controller {
+				compatible = "nxp,lpc1850-creg-clk";
+				clocks = <&xtal32>;
+				#clock-cells = <1>;
+			};
+
+			usb0_otg_phy: phy {
 				compatible = "nxp,lpc1850-usb-otg-phy";
 				clocks = <&ccu1 CLK_USB0>;
 				#phy-cells = <0>;
 			};
 
-			dmamux: dma-mux@11c {
+			dmamux: dma-mux {
 				compatible = "nxp,lpc1850-dmamux";
 				#dma-cells = <3>;
 				dma-requests = <64>;
@@ -209,11 +215,19 @@
 			};
 		};
 
+		rtc: rtc@40046000 {
+			compatible = "nxp,lpc1850-rtc", "nxp,lpc1788-rtc";
+			reg = <0x40046000 0x1000>;
+			interrupts = <47>;
+			clocks = <&creg_clk 0>, <&ccu1 CLK_CPU_BUS>;
+			clock-names = "rtc", "reg";
+		};
+
 		cgu: clock-controller@40050000 {
 			compatible = "nxp,lpc1850-cgu";
 			reg = <0x40050000 0x1000>;
 			#clock-cells = <1>;
-			clocks = <&xtal>, <&xtal32>, <&enet_rx_clk>, <&enet_tx_clk>, <&gp_clkin>;
+			clocks = <&xtal>, <&creg_clk 1>, <&enet_rx_clk>, <&enet_tx_clk>, <&gp_clkin>;
 		};
 
 		ccu1: clock-controller@40051000 {
@@ -430,6 +444,15 @@
 			status = "disabled";
 		};
 
+		dac: dac@400e1000 {
+			compatible = "nxp,lpc1850-dac";
+			reg = <0x400e1000 0x1000>;
+			interrupts = <0>;
+			clocks = <&ccu1 CLK_APB3_DAC>;
+			resets = <&rgu 42>;
+			status = "disabled";
+		};
+
 		can0: can@400e2000 {
 			compatible = "bosch,c_can";
 			reg = <0x400e2000 0x1000>;
@@ -439,6 +462,24 @@
 			status = "disabled";
 		};
 
+		adc0: adc@400e3000 {
+			compatible = "nxp,lpc1850-adc";
+			reg = <0x400e3000 0x1000>;
+			interrupts = <17>;
+			clocks = <&ccu1 CLK_APB3_ADC0>;
+			resets = <&rgu 40>;
+			status = "disabled";
+		};
+
+		adc1: adc@400e4000 {
+			compatible = "nxp,lpc1850-adc";
+			reg = <0x400e4000 0x1000>;
+			interrupts = <21>;
+			clocks = <&ccu1 CLK_APB3_ADC1>;
+			resets = <&rgu 41>;
+			status = "disabled";
+		};
+
 		gpio: gpio@400f4000 {
 			compatible = "nxp,lpc1850-gpio";
 			reg = <0x400f4000 0x4000>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/lpc3250-ea3250.dts linux-libre-4.7-gnu/arch/arm/boot/dts/lpc3250-ea3250.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/lpc3250-ea3250.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/lpc3250-ea3250.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,272 @@
+/*
+ * Embedded Artists LPC3250 board
+ *
+ * Copyright 2012 Roland Stigge <stigge@antcom.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "lpc32xx.dtsi"
+
+/ {
+	model = "Embedded Artists LPC3250 board based on NXP LPC3250";
+	compatible = "ea,ea3250", "nxp,lpc3250";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x4000000>;
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		autorepeat;
+		button@21 {
+			label = "Interrupt Key";
+			linux,code = <103>;
+			gpios = <&gpio 4 1 0>; /* GPI_P3 1 */
+		};
+		key1 {
+			label = "KEY1";
+			linux,code = <1>;
+			gpios = <&pca9532 0 0>;
+		};
+		key2 {
+			label = "KEY2";
+			linux,code = <2>;
+			gpios = <&pca9532 1 0>;
+		};
+		key3 {
+			label = "KEY3";
+			linux,code = <3>;
+			gpios = <&pca9532 2 0>;
+		};
+		key4 {
+			label = "KEY4";
+			linux,code = <4>;
+			gpios = <&pca9532 3 0>;
+		};
+		joy0 {
+			label = "Joystick Key 0";
+			linux,code = <10>;
+			gpios = <&gpio 2 0 0>; /* P2.0 */
+		};
+		joy1 {
+			label = "Joystick Key 1";
+			linux,code = <11>;
+			gpios = <&gpio 2 1 0>; /* P2.1 */
+		};
+		joy2 {
+			label = "Joystick Key 2";
+			linux,code = <12>;
+			gpios = <&gpio 2 2 0>; /* P2.2 */
+		};
+		joy3 {
+			label = "Joystick Key 3";
+			linux,code = <13>;
+			gpios = <&gpio 2 3 0>; /* P2.3 */
+		};
+		joy4 {
+			label = "Joystick Key 4";
+			linux,code = <14>;
+			gpios = <&gpio 2 4 0>; /* P2.4 */
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		/* LEDs on OEM Board */
+
+		led1 {
+			gpios = <&gpio 5 14 1>; /* GPO_P3 14, GPIO 93, active low */
+			linux,default-trigger = "timer";
+			default-state = "off";
+		};
+
+		led2 {
+			gpios = <&gpio 2 10 1>; /* P2.10, active low */
+			default-state = "off";
+		};
+
+		led3 {
+			gpios = <&gpio 2 11 1>; /* P2.11, active low */
+			default-state = "off";
+		};
+
+		led4 {
+			gpios = <&gpio 2 12 1>; /* P2.12, active low */
+			default-state = "off";
+		};
+
+		/* LEDs on Base Board */
+
+		lede1 {
+			gpios = <&pca9532 8 0>;
+			default-state = "off";
+		};
+		lede2 {
+			gpios = <&pca9532 9 0>;
+			default-state = "off";
+		};
+		lede3 {
+			gpios = <&pca9532 10 0>;
+			default-state = "off";
+		};
+		lede4 {
+			gpios = <&pca9532 11 0>;
+			default-state = "off";
+		};
+		lede5 {
+			gpios = <&pca9532 12 0>;
+			default-state = "off";
+		};
+		lede6 {
+			gpios = <&pca9532 13 0>;
+			default-state = "off";
+		};
+		lede7 {
+			gpios = <&pca9532 14 0>;
+			default-state = "off";
+		};
+		lede8 {
+			gpios = <&pca9532 15 0>;
+			default-state = "off";
+		};
+	};
+};
+
+/* 3-axis accelerometer X,Y,Z (or AD-IN instead of Z) */
+&adc {
+	status = "okay";
+};
+
+&i2c1 {
+	clock-frequency = <100000>;
+
+	uda1380: uda1380@18 {
+		compatible = "nxp,uda1380";
+		reg = <0x18>;
+		power-gpio = <&gpio 0x59 0>;
+		reset-gpio = <&gpio 0x51 0>;
+		dac-clk = "wspll";
+	};
+
+	eeprom@50 {
+		compatible = "atmel,24c256";
+		reg = <0x50>;
+	};
+
+	eeprom@57 {
+		compatible = "atmel,24c64";
+		reg = <0x57>;
+	};
+
+	pca9532: pca9532@60 {
+		compatible = "nxp,pca9532";
+		gpio-controller;
+		#gpio-cells = <2>;
+		reg = <0x60>;
+	};
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+};
+
+&i2cusb {
+	clock-frequency = <100000>;
+
+	isp1301: usb-transceiver@2d {
+		compatible = "nxp,isp1301";
+		reg = <0x2d>;
+	};
+};
+
+&mac {
+	phy-mode = "rmii";
+	use-iram;
+};
+
+/* Here, choose exactly one from: ohci, usbd */
+&ohci /* &usbd */ {
+	transceiver = <&isp1301>;
+	status = "okay";
+};
+
+&sd {
+	wp-gpios = <&pca9532 5 0>;
+	cd-gpios = <&pca9532 4 0>;
+	cd-inverted;
+	bus-width = <4>;
+	status = "okay";
+};
+
+/* 128MB Flash via SLC NAND controller */
+&slc {
+	status = "okay";
+
+	nxp,wdr-clks = <14>;
+	nxp,wwidth = <260000000>;
+	nxp,whold = <104000000>;
+	nxp,wsetup = <200000000>;
+	nxp,rdr-clks = <14>;
+	nxp,rwidth = <34666666>;
+	nxp,rhold = <104000000>;
+	nxp,rsetup = <200000000>;
+	nand-on-flash-bbt;
+	gpios = <&gpio 5 19 1>; /* GPO_P3 19, active low */
+
+	partitions {
+		compatible = "fixed-partitions";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		mtd0@00000000 {
+			label = "ea3250-boot";
+			reg = <0x00000000 0x00080000>;
+			read-only;
+		};
+
+		mtd1@00080000 {
+			label = "ea3250-uboot";
+			reg = <0x00080000 0x000c0000>;
+			read-only;
+		};
+
+		mtd2@00140000 {
+			label = "ea3250-kernel";
+			reg = <0x00140000 0x00400000>;
+		};
+
+		mtd3@00540000 {
+			label = "ea3250-rootfs";
+			reg = <0x00540000 0x07ac0000>;
+		};
+	};
+};
+
+&uart1 {
+	status = "okay";
+};
+
+&uart3 {
+	status = "okay";
+};
+
+&uart5 {
+	status = "okay";
+};
+
+&uart6 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/lpc3250-phy3250.dts linux-libre-4.7-gnu/arch/arm/boot/dts/lpc3250-phy3250.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/lpc3250-phy3250.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/lpc3250-phy3250.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,226 @@
+/*
+ * PHYTEC phyCORE-LPC3250 board
+ *
+ * Copyright 2012 Roland Stigge <stigge@antcom.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "lpc32xx.dtsi"
+
+/ {
+	model = "PHYTEC phyCORE-LPC3250 board based on NXP LPC3250";
+	compatible = "phytec,phy3250", "nxp,lpc3250";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x4000000>;
+	};
+
+	regulators {
+		backlight_reg: regulator@0 {
+			compatible = "regulator-fixed";
+			regulator-name = "backlight_reg";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			gpio = <&gpio 5 4 0>;
+			enable-active-high;
+			regulator-boot-on;
+		};
+
+		lcd_reg: regulator@1 {
+			compatible = "regulator-fixed";
+			regulator-name = "lcd_reg";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			gpio = <&gpio 5 0 0>;
+			enable-active-high;
+			regulator-boot-on;
+		};
+
+		sd_reg: regulator@2 {
+			compatible = "regulator-fixed";
+			regulator-name = "sd_reg";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			gpio = <&gpio 5 5 0>;
+			enable-active-high;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		led0 { /* red */
+			gpios = <&gpio 5 1 0>; /* GPO_P3 1, GPIO 80, active high */
+			default-state = "off";
+		};
+
+		led1 { /* green */
+			gpios = <&gpio 5 14 0>; /* GPO_P3 14, GPIO 93, active high */
+			linux,default-trigger = "heartbeat";
+		};
+	};
+};
+
+&clcd {
+	status = "okay";
+};
+
+&i2c1 {
+	clock-frequency = <100000>;
+
+	uda1380: uda1380@18 {
+		compatible = "nxp,uda1380";
+		reg = <0x18>;
+		power-gpio = <&gpio 0x59 0>;
+		reset-gpio = <&gpio 0x51 0>;
+		dac-clk = "wspll";
+	};
+
+	pcf8563: rtc@51 {
+		compatible = "nxp,pcf8563";
+		reg = <0x51>;
+	};
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+};
+
+&i2cusb {
+	clock-frequency = <100000>;
+
+	isp1301: usb-transceiver@2c {
+		compatible = "nxp,isp1301";
+		reg = <0x2c>;
+	};
+};
+
+&key {
+	keypad,num-rows = <1>;
+	keypad,num-columns = <1>;
+	nxp,debounce-delay-ms = <3>;
+	nxp,scan-delay-ms = <34>;
+	linux,keymap = <0x00000002>;
+	status = "okay";
+};
+
+&mac {
+	phy-mode = "rmii";
+	use-iram;
+};
+
+/* Here, choose exactly one from: ohci, usbd */
+&ohci /* &usbd */ {
+	transceiver = <&isp1301>;
+	status = "okay";
+};
+
+&sd {
+	wp-gpios = <&gpio 3 0 0>;
+	cd-gpios = <&gpio 3 1 0>;
+	cd-inverted;
+	bus-width = <4>;
+	vmmc-supply = <&sd_reg>;
+	status = "okay";
+};
+
+/* 64MB Flash via SLC NAND controller */
+&slc {
+	status = "okay";
+
+	nxp,wdr-clks = <14>;
+	nxp,wwidth = <40000000>;
+	nxp,whold = <100000000>;
+	nxp,wsetup = <100000000>;
+	nxp,rdr-clks = <14>;
+	nxp,rwidth = <40000000>;
+	nxp,rhold = <66666666>;
+	nxp,rsetup = <100000000>;
+	nand-on-flash-bbt;
+	gpios = <&gpio 5 19 1>; /* GPO_P3 19, active low */
+
+	partitions {
+		compatible = "fixed-partitions";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		mtd0@00000000 {
+			label = "phy3250-boot";
+			reg = <0x00000000 0x00064000>;
+			read-only;
+		};
+
+		mtd1@00064000 {
+			label = "phy3250-uboot";
+			reg = <0x00064000 0x00190000>;
+			read-only;
+		};
+
+		mtd2@001f4000 {
+			label = "phy3250-ubt-prms";
+			reg = <0x001f4000 0x00010000>;
+		};
+
+		mtd3@00204000 {
+			label = "phy3250-kernel";
+			reg = <0x00204000 0x00400000>;
+		};
+
+		mtd4@00604000 {
+			label = "phy3250-rootfs";
+			reg = <0x00604000 0x039fc000>;
+		};
+	};
+};
+
+&ssp0 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	num-cs = <1>;
+	cs-gpios = <&gpio 3 5 0>;
+	status = "okay";
+
+	eeprom: at25@0 {
+		compatible = "atmel,at25";
+		reg = <0>;
+		spi-max-frequency = <5000000>;
+
+		pl022,interface = <0>;
+		pl022,com-mode = <0>;
+		pl022,rx-level-trig = <1>;
+		pl022,tx-level-trig = <1>;
+		pl022,ctrl-len = <11>;
+		pl022,wait-state = <0>;
+		pl022,duplex = <0>;
+
+		at25,byte-len = <0x8000>;
+		at25,addr-mode = <2>;
+		at25,page-size = <64>;
+	};
+};
+
+&tsc {
+	status = "okay";
+};
+
+&uart2 {
+	status = "okay";
+};
+
+&uart3 {
+	status = "okay";
+};
+
+&uart5 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/lpc32xx.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/lpc32xx.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/lpc32xx.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/lpc32xx.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -92,7 +92,8 @@
 			ohci: ohci@0 {
 				compatible = "nxp,ohci-nxp", "usb-ohci";
 				reg = <0x0 0x300>;
-				interrupts = <59 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-parent = <&sic1>;
+				interrupts = <27 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&usbclk LPC32XX_USB_CLK_HOST>;
 				status = "disabled";
 			};
@@ -100,10 +101,11 @@
 			usbd: usbd@0 {
 				compatible = "nxp,lpc3220-udc";
 				reg = <0x0 0x300>;
-				interrupts = <61 IRQ_TYPE_LEVEL_HIGH>,
-					     <62 IRQ_TYPE_LEVEL_HIGH>,
-					     <60 IRQ_TYPE_LEVEL_HIGH>,
-					     <58 IRQ_TYPE_LEVEL_LOW>;
+				interrupt-parent = <&sic1>;
+				interrupts = <29 IRQ_TYPE_LEVEL_HIGH>,
+					     <30 IRQ_TYPE_LEVEL_HIGH>,
+					     <28 IRQ_TYPE_LEVEL_HIGH>,
+					     <26 IRQ_TYPE_LEVEL_LOW>;
 				clocks = <&usbclk LPC32XX_USB_CLK_DEVICE>;
 				status = "disabled";
 			};
@@ -111,7 +113,8 @@
 			i2cusb: i2c@300 {
 				compatible = "nxp,pnx-i2c";
 				reg = <0x300 0x100>;
-				interrupts = <63 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-parent = <&sic1>;
+				interrupts = <31 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&usbclk LPC32XX_USB_CLK_I2C>;
 				#address-cells = <1>;
 				#size-cells = <0>;
@@ -162,30 +165,44 @@
 			compatible = "simple-bus";
 			ranges = <0x20000000 0x20000000 0x30000000>;
 
+			/*
+			 * ssp0 and spi1 are shared pins;
+			 * enable one in your board dts, as needed.
+			 */
 			ssp0: ssp@20084000 {
 				compatible = "arm,pl022", "arm,primecell";
 				reg = <0x20084000 0x1000>;
 				interrupts = <20 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clk LPC32XX_CLK_SSP0>;
 				clock-names = "apb_pclk";
+				status = "disabled";
 			};
 
 			spi1: spi@20088000 {
 				compatible = "nxp,lpc3220-spi";
 				reg = <0x20088000 0x1000>;
+				clocks = <&clk LPC32XX_CLK_SPI1>;
+				status = "disabled";
 			};
 
+			/*
+			 * ssp1 and spi2 are shared pins;
+			 * enable one in your board dts, as needed.
+			 */
 			ssp1: ssp@2008c000 {
 				compatible = "arm,pl022", "arm,primecell";
 				reg = <0x2008c000 0x1000>;
 				interrupts = <21 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clk LPC32XX_CLK_SSP1>;
 				clock-names = "apb_pclk";
+				status = "disabled";
 			};
 
 			spi2: spi@20090000 {
 				compatible = "nxp,lpc3220-spi";
 				reg = <0x20090000 0x1000>;
+				clocks = <&clk LPC32XX_CLK_SPI2>;
+				status = "disabled";
 			};
 
 			i2s0: i2s@20094000 {
@@ -249,7 +266,8 @@
 			i2c1: i2c@400A0000 {
 				compatible = "nxp,pnx-i2c";
 				reg = <0x400A0000 0x100>;
-				interrupts = <51 IRQ_TYPE_LEVEL_LOW>;
+				interrupt-parent = <&sic1>;
+				interrupts = <19 IRQ_TYPE_LEVEL_LOW>;
 				#address-cells = <1>;
 				#size-cells = <0>;
 				pnx,timeout = <0x64>;
@@ -259,7 +277,8 @@
 			i2c2: i2c@400A8000 {
 				compatible = "nxp,pnx-i2c";
 				reg = <0x400A8000 0x100>;
-				interrupts = <50 IRQ_TYPE_LEVEL_LOW>;
+				interrupt-parent = <&sic1>;
+				interrupts = <18 IRQ_TYPE_LEVEL_LOW>;
 				#address-cells = <1>;
 				#size-cells = <0>;
 				pnx,timeout = <0x64>;
@@ -294,20 +313,39 @@
 
 					clocks = <&xtal_32k>, <&xtal>;
 					clock-names = "xtal_32k", "xtal";
+
+					assigned-clocks = <&clk LPC32XX_CLK_HCLK_PLL>;
+					assigned-clock-rates = <208000000>;
 				};
 			};
 
-			/*
-			 * MIC Interrupt controller includes:
-			 *   MIC @40008000
-			 *   SIC1 @4000C000
-			 *   SIC2 @40010000
-			 */
 			mic: interrupt-controller@40008000 {
 				compatible = "nxp,lpc3220-mic";
+				reg = <0x40008000 0x4000>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+			};
+
+			sic1: interrupt-controller@4000c000 {
+				compatible = "nxp,lpc3220-sic";
+				reg = <0x4000c000 0x4000>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+
+				interrupt-parent = <&mic>;
+				interrupts = <0 IRQ_TYPE_LEVEL_LOW>,
+					     <30 IRQ_TYPE_LEVEL_LOW>;
+				};
+
+			sic2: interrupt-controller@40010000 {
+				compatible = "nxp,lpc3220-sic";
+				reg = <0x40010000 0x4000>;
 				interrupt-controller;
-				reg = <0x40008000 0xC000>;
 				#interrupt-cells = <2>;
+
+				interrupt-parent = <&mic>;
+				interrupts = <1 IRQ_TYPE_LEVEL_LOW>,
+					     <31 IRQ_TYPE_LEVEL_LOW>;
 			};
 
 			uart1: serial@40014000 {
@@ -334,7 +372,8 @@
 			rtc: rtc@40024000 {
 				compatible = "nxp,lpc3220-rtc";
 				reg = <0x40024000 0x1000>;
-				interrupts = <52 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-parent = <&sic1>;
+				interrupts = <20 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clk LPC32XX_CLK_RTC>;
 			};
 
@@ -387,7 +426,8 @@
 			adc: adc@40048000 {
 				compatible = "nxp,lpc3220-adc";
 				reg = <0x40048000 0x1000>;
-				interrupts = <39 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-parent = <&sic1>;
+				interrupts = <7 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clk LPC32XX_CLK_ADC>;
 				status = "disabled";
 			};
@@ -395,7 +435,8 @@
 			tsc: tsc@40048000 {
 				compatible = "nxp,lpc3220-tsc";
 				reg = <0x40048000 0x1000>;
-				interrupts = <39 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-parent = <&sic1>;
+				interrupts = <7 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clk LPC32XX_CLK_ADC>;
 				status = "disabled";
 			};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/lpc4350-hitex-eval.dts linux-libre-4.7-gnu/arch/arm/boot/dts/lpc4350-hitex-eval.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/lpc4350-hitex-eval.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/lpc4350-hitex-eval.dts	2016-07-24 15:23:50.000000000 -0400
@@ -45,50 +45,50 @@
 		poll-interval = <100>;
 		autorepeat;
 
-		button@0 {
+		button0 {
 			label = "joy:right";
 			linux,code = <KEY_RIGHT>;
 			gpios = <&pca_gpio 8 GPIO_ACTIVE_LOW>;
 		};
 
-		button@1 {
+		button1 {
 			label = "joy:up";
 			linux,code = <KEY_UP>;
 			gpios = <&pca_gpio 9 GPIO_ACTIVE_LOW>;
 		};
 
 
-		button@2 {
+		button2 {
 			label = "joy:enter";
 			linux,code = <KEY_ENTER>;
 			gpios = <&pca_gpio 10 GPIO_ACTIVE_LOW>;
 		};
 
-		button@3 {
+		button3 {
 			label = "joy:left";
 			linux,code = <KEY_LEFT>;
 			gpios = <&pca_gpio 11 GPIO_ACTIVE_LOW>;
 		};
 
-		button@4 {
+		button4 {
 			label = "joy:down";
 			linux,code = <KEY_DOWN>;
 			gpios = <&pca_gpio 12 GPIO_ACTIVE_LOW>;
 		};
 
-		button@5 {
+		button5 {
 			label = "user:sw3";
 			linux,code = <KEY_F1>;
 			gpios = <&pca_gpio 13 GPIO_ACTIVE_LOW>;
 		};
 
-		button@6 {
+		button6 {
 			label = "user:sw4";
 			linux,code = <KEY_F2>;
 			gpios = <&pca_gpio 14 GPIO_ACTIVE_LOW>;
 		};
 
-		button@7 {
+		button7 {
 			label = "user:sw5";
 			linux,code = <KEY_F3>;
 			gpios = <&pca_gpio 15 GPIO_ACTIVE_LOW>;
@@ -119,9 +119,25 @@
 			gpios = <&pca_gpio 3 GPIO_ACTIVE_LOW>;
 		};
 	};
+
+	vcc: vcc_fixed {
+		compatible = "regulator-fixed";
+		regulator-name = "3v3io";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
 };
 
 &pinctrl {
+	adc1_pins: adc1-pins {
+		adc1_pins_cfg {
+			pins = "pf_9";
+			function = "adc";
+			input-disable;
+			bias-disable;
+		};
+	};
+
 	emc_pins: emc-pins {
 		emc_addr0_23_cfg {
 			pins =	"p2_9",  "p2_10", "p2_11", "p2_12",
@@ -325,6 +341,13 @@
 	};
 };
 
+&adc1 {
+	status = "okay";
+	vref-supply = <&vcc>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&adc1_pins>;
+};
+
 &emc {
 	status = "okay";
 	pinctrl-names = "default";
@@ -430,7 +453,7 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&spifi_pins>;
 
-	flash@0 {
+	flash {
 		compatible = "jedec,spi-nor";
 		spi-rx-bus-width = <4>;
 		#address-cells = <1>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/lpc4357-ea4357-devkit.dts linux-libre-4.7-gnu/arch/arm/boot/dts/lpc4357-ea4357-devkit.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/lpc4357-ea4357-devkit.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/lpc4357-ea4357-devkit.dts	2016-07-24 15:23:50.000000000 -0400
@@ -38,6 +38,13 @@
 		reg = <0x28000000 0x2000000>; /* 32 MB */
 	};
 
+	vcc: vcc_fixed {
+		compatible = "regulator-fixed";
+		regulator-name = "3v3-supply";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
 	/* vmmc is controlled by sdmmc host internally */
 	vmmc: vmmc_fixed {
 		compatible = "regulator-fixed";
@@ -55,31 +62,31 @@
 		poll-interval = <100>;
 		autorepeat;
 
-		button@0 {
+		button0 {
 			label = "joy_enter";
 			linux,code = <KEY_ENTER>;
 			gpios = <&gpio LPC_GPIO(4,8) GPIO_ACTIVE_LOW>;
 		};
 
-		button@1 {
+		button1 {
 			label = "joy_left";
 			linux,code = <KEY_LEFT>;
 			gpios = <&gpio LPC_GPIO(4,9) GPIO_ACTIVE_LOW>;
 		};
 
-		button@2 {
+		button2 {
 			label = "joy_up";
 			linux,code = <KEY_UP>;
 			gpios = <&gpio LPC_GPIO(4,10) GPIO_ACTIVE_LOW>;
 		};
 
-		button@3 {
+		button3 {
 			label = "joy_right";
 			linux,code = <KEY_RIGHT>;
 			gpios = <&gpio LPC_GPIO(4,12) GPIO_ACTIVE_LOW>;
 		};
 
-		button@4 {
+		button4 {
 			label = "joy_down";
 			linux,code = <KEY_DOWN>;
 			gpios = <&gpio LPC_GPIO(4,13) GPIO_ACTIVE_LOW>;
@@ -461,6 +468,11 @@
 	};
 };
 
+&adc0 {
+	status = "okay";
+	vref-supply = <&vcc>;
+};
+
 &i2c0 {
 	status = "okay";
 	pinctrl-names = "default";
@@ -483,6 +495,11 @@
 	};
 };
 
+&dac {
+	status = "okay";
+	vref-supply = <&vcc>;
+};
+
 &emc {
 	status = "okay";
 	pinctrl-names = "default";
@@ -567,7 +584,7 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&spifi_pins>;
 
-	flash@0 {
+	flash {
 		compatible = "jedec,spi-nor";
 		spi-cpol;
 		spi-cpha;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/ls1021a.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/ls1021a.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/ls1021a.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/ls1021a.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -119,6 +119,20 @@
 
 		};
 
+		msi1: msi-controller@1570e00 {
+			compatible = "fsl,1s1021a-msi";
+			reg = <0x0 0x1570e00 0x0 0x8>;
+			msi-controller;
+			interrupts =  <GIC_SPI 179 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		msi2: msi-controller@1570e08 {
+			compatible = "fsl,1s1021a-msi";
+			reg = <0x0 0x1570e08 0x0 0x8>;
+			msi-controller;
+			interrupts = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
 		ifc: ifc@1530000 {
 			compatible = "fsl,ifc", "simple-bus";
 			reg = <0x0 0x1530000 0x0 0x10000>;
@@ -245,7 +259,7 @@
 			interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
 			clock-names = "dspi";
 			clocks = <&platform_clk 1>;
-			spi-num-chipselects = <5>;
+			spi-num-chipselects = <6>;
 			big-endian;
 			status = "disabled";
 		};
@@ -258,7 +272,7 @@
 			interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
 			clock-names = "dspi";
 			clocks = <&platform_clk 1>;
-			spi-num-chipselects = <5>;
+			spi-num-chipselects = <6>;
 			big-endian;
 			status = "disabled";
 		};
@@ -332,6 +346,46 @@
 			status = "disabled";
 		};
 
+		gpio0: gpio@2300000 {
+			compatible = "fsl,ls1021a-gpio", "fsl,qoriq-gpio";
+			reg = <0x0 0x2300000 0x0 0x10000>;
+			interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpio1: gpio@2310000 {
+			compatible = "fsl,ls1021a-gpio", "fsl,qoriq-gpio";
+			reg = <0x0 0x2310000 0x0 0x10000>;
+			interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpio2: gpio@2320000 {
+			compatible = "fsl,ls1021a-gpio", "fsl,qoriq-gpio";
+			reg = <0x0 0x2320000 0x0 0x10000>;
+			interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpio3: gpio@2330000 {
+			compatible = "fsl,ls1021a-gpio", "fsl,qoriq-gpio";
+			reg = <0x0 0x2330000 0x0 0x10000>;
+			interrupts = <GIC_SPI 166 IRQ_TYPE_LEVEL_HIGH>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
 		lpuart0: serial@2950000 {
 			compatible = "fsl,ls1021a-lpuart";
 			reg = <0x0 0x2950000 0x0 0x1000>;
@@ -443,8 +497,9 @@
 			compatible = "fsl,ls1021a-dcu";
 			reg = <0x0 0x2ce0000 0x0 0x10000>;
 			interrupts = <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&platform_clk 0>;
-			clock-names = "dcu";
+			clocks = <&platform_clk 0>,
+				<&platform_clk 0>;
+			clock-names = "dcu", "pix";
 			big-endian;
 			status = "disabled";
 		};
@@ -587,6 +642,7 @@
 			bus-range = <0x0 0xff>;
 			ranges = <0x81000000 0x0 0x00000000 0x40 0x00010000 0x0 0x00010000   /* downstream I/O */
 				  0x82000000 0x0 0x40000000 0x40 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
+			msi-parent = <&msi1>;
 			#interrupt-cells = <1>;
 			interrupt-map-mask = <0 0 0 7>;
 			interrupt-map = <0000 0 0 1 &gic GIC_SPI 91  IRQ_TYPE_LEVEL_HIGH>,
@@ -609,6 +665,7 @@
 			bus-range = <0x0 0xff>;
 			ranges = <0x81000000 0x0 0x00000000 0x48 0x00010000 0x0 0x00010000   /* downstream I/O */
 				  0x82000000 0x0 0x40000000 0x48 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
+			msi-parent = <&msi2>;
 			#interrupt-cells = <1>;
 			interrupt-map-mask = <0 0 0 7>;
 			interrupt-map = <0000 0 0 1 &gic GIC_SPI 92  IRQ_TYPE_LEVEL_HIGH>,
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/Makefile linux-libre-4.7-gnu/arch/arm/boot/dts/Makefile
--- linux-libre-4.6-gnu/arch/arm/boot/dts/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -112,6 +112,7 @@ dtb-$(CONFIG_ARCH_DIGICOLOR) += \
 dtb-$(CONFIG_ARCH_EFM32) += \
 	efm32gg-dk3750.dtb
 dtb-$(CONFIG_ARCH_EXYNOS3) += \
+	exynos3250-artik5-eval.dtb \
 	exynos3250-monk.dtb \
 	exynos3250-rinato.dtb
 dtb-$(CONFIG_ARCH_EXYNOS4) += \
@@ -158,9 +159,9 @@ dtb-$(CONFIG_ARCH_INTEGRATOR) += \
 	integratorap.dtb \
 	integratorcp.dtb
 dtb-$(CONFIG_ARCH_KEYSTONE) += \
-	k2hk-evm.dtb \
-	k2l-evm.dtb \
-	k2e-evm.dtb \
+	keystone-k2hk-evm.dtb \
+	keystone-k2l-evm.dtb \
+	keystone-k2e-evm.dtb \
 	keystone-k2g-evm.dtb
 dtb-$(CONFIG_MACH_KIRKWOOD) += \
 	kirkwood-b3.dtb \
@@ -177,6 +178,7 @@ dtb-$(CONFIG_MACH_KIRKWOOD) += \
 	kirkwood-ds109.dtb \
 	kirkwood-ds110jv10.dtb \
 	kirkwood-ds111.dtb \
+	kirkwood-ds112.dtb \
 	kirkwood-ds209.dtb \
 	kirkwood-ds210.dtb \
 	kirkwood-ds212.dtb \
@@ -199,6 +201,7 @@ dtb-$(CONFIG_MACH_KIRKWOOD) += \
 	kirkwood-linkstation-lswsxl.dtb \
 	kirkwood-linkstation-lswvl.dtb \
 	kirkwood-linkstation-lswxl.dtb \
+	kirkwood-linksys-viper.dtb \
 	kirkwood-lschlv2.dtb \
 	kirkwood-lsxhl.dtb \
 	kirkwood-mplcec4.dtb \
@@ -214,6 +217,7 @@ dtb-$(CONFIG_MACH_KIRKWOOD) += \
 	kirkwood-ns2mini.dtb \
 	kirkwood-nsa310.dtb \
 	kirkwood-nsa310a.dtb \
+	kirkwood-nsa320.dtb \
 	kirkwood-nsa325.dtb \
 	kirkwood-openblocks_a6.dtb \
 	kirkwood-openblocks_a7.dtb \
@@ -241,7 +245,8 @@ dtb-$(CONFIG_ARCH_LPC18XX) += \
 	lpc4350-hitex-eval.dtb \
 	lpc4357-ea4357-devkit.dtb
 dtb-$(CONFIG_ARCH_LPC32XX) += \
-	ea3250.dtb phy3250.dtb
+	lpc3250-ea3250.dtb \
+	lpc3250-phy3250.dtb
 dtb-$(CONFIG_MACH_MESON6) += \
 	meson6-atv1200.dtb
 dtb-$(CONFIG_MACH_MESON8) += \
@@ -253,6 +258,9 @@ dtb-$(CONFIG_ARCH_MMP) += \
 dtb-$(CONFIG_MACH_MESON8B) += \
 	meson8b-mxq.dtb \
 	meson8b-odroidc1.dtb
+dtb-$(CONFIG_ARCH_MPS2) += \
+	mps2-an385.dtb \
+	mps2-an399.dtb
 dtb-$(CONFIG_ARCH_MOXART) += \
 	moxart-uc7112lx.dtb
 dtb-$(CONFIG_SOC_IMX1) += \
@@ -320,8 +328,12 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
 	imx6dl-sabrelite.dtb \
 	imx6dl-sabresd.dtb \
 	imx6dl-tx6dl-comtft.dtb \
+	imx6dl-tx6s-8034.dtb \
+	imx6dl-tx6s-8035.dtb \
 	imx6dl-tx6u-801x.dtb \
+	imx6dl-tx6u-8033.dtb \
 	imx6dl-tx6u-811x.dtb \
+	imx6dl-tx6u-81xx-mb7.dtb \
 	imx6dl-udoo.dtb \
 	imx6dl-wandboard.dtb \
 	imx6dl-wandboard-revb1.dtb \
@@ -346,6 +358,7 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
 	imx6q-gw552x.dtb \
 	imx6q-hummingboard.dtb \
 	imx6q-icore-rqs.dtb \
+	imx6q-marsboard.dtb \
 	imx6q-nitrogen6x.dtb \
 	imx6q-nitrogen6_max.dtb \
 	imx6q-novena.dtb \
@@ -360,23 +373,33 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
 	imx6q-tx6q-1010-comtft.dtb \
 	imx6q-tx6q-1020.dtb \
 	imx6q-tx6q-1020-comtft.dtb \
+	imx6q-tx6q-1036.dtb \
 	imx6q-tx6q-1110.dtb \
+	imx6q-tx6q-11x0-mb7.dtb \
 	imx6q-udoo.dtb \
 	imx6q-wandboard.dtb \
 	imx6q-wandboard-revb1.dtb \
+	imx6qp-nitrogen6_max.dtb \
 	imx6qp-sabreauto.dtb \
 	imx6qp-sabresd.dtb
 dtb-$(CONFIG_SOC_IMX6SL) += \
 	imx6sl-evk.dtb \
 	imx6sl-warp.dtb
 dtb-$(CONFIG_SOC_IMX6SX) += \
+	imx6sx-nitrogen6sx.dtb \
 	imx6sx-sabreauto.dtb \
 	imx6sx-sdb-reva.dtb \
+	imx6sx-sdb-sai.dtb \
 	imx6sx-sdb.dtb
 dtb-$(CONFIG_SOC_IMX6UL) += \
-	imx6ul-14x14-evk.dtb
+	imx6ul-14x14-evk.dtb \
+	imx6ul-pico-hobbit.dtb \
+	imx6ul-tx6ul-0010.dtb \
+	imx6ul-tx6ul-0011.dtb \
+	imx6ul-tx6ul-mainboard.dtb
 dtb-$(CONFIG_SOC_IMX7D) += \
 	imx7d-cl-som-imx7.dtb \
+	imx7d-nitrogen7.dtb \
 	imx7d-sbc-imx7.dtb \
 	imx7d-sdb.dtb
 dtb-$(CONFIG_SOC_LS1021A) += \
@@ -388,7 +411,8 @@ dtb-$(CONFIG_SOC_VF610) += \
 	vf610m4-colibri.dtb \
 	vf610-cosmic.dtb \
 	vf610m4-cosmic.dtb \
-	vf610-twr.dtb
+	vf610-twr.dtb \
+	vf610-zii-dev-rev-b.dtb
 dtb-$(CONFIG_ARCH_MXS) += \
 	imx23-evk.dtb \
 	imx23-olinuxino.dtb \
@@ -485,6 +509,8 @@ dtb-$(CONFIG_SOC_TI81XX) += \
 	dm8168-evm.dtb \
 	dra62x-j5eco-evm.dtb
 dtb-$(CONFIG_SOC_AM33XX) += \
+	am335x-baltos-ir2110.dtb \
+	am335x-baltos-ir3220.dtb \
 	am335x-baltos-ir5221.dtb \
 	am335x-base0033.dtb \
 	am335x-bone.dtb \
@@ -494,6 +520,7 @@ dtb-$(CONFIG_SOC_AM33XX) += \
 	am335x-cm-t335.dtb \
 	am335x-evm.dtb \
 	am335x-evmsk.dtb \
+	am335x-icev2.dtb \
 	am335x-lxm.dtb \
 	am335x-nano.dtb \
 	am335x-pepper.dtb \
@@ -503,6 +530,7 @@ dtb-$(CONFIG_SOC_AM33XX) += \
 	am335x-wega-rdk.dtb
 dtb-$(CONFIG_ARCH_OMAP4) += \
 	omap4-duovero-parlor.dtb \
+	omap4-kc1.dtb \
 	omap4-panda.dtb \
 	omap4-panda-a4.dtb \
 	omap4-panda-es.dtb \
@@ -526,9 +554,12 @@ dtb-$(CONFIG_SOC_DRA7XX) += \
 	am57xx-beagle-x15.dtb \
 	am57xx-cl-som-am57x.dtb \
 	am57xx-sbc-am57x.dtb \
+	am572x-idk.dtb \
 	dra7-evm.dtb \
-	dra72-evm.dtb
+	dra72-evm.dtb \
+	dra72-evm-revc.dtb
 dtb-$(CONFIG_ARCH_ORION5X) += \
+	orion5x-kuroboxpro.dtb \
 	orion5x-lacie-d2-network.dtb \
 	orion5x-lacie-ethernet-disk-mini-v2.dtb \
 	orion5x-linkstation-lsgl.dtb \
@@ -538,7 +569,10 @@ dtb-$(CONFIG_ARCH_ORION5X) += \
 	orion5x-rd88f5182-nas.dtb
 dtb-$(CONFIG_ARCH_PRIMA2) += \
 	prima2-evb.dtb
+dtb-$(CONFIG_ARCH_OXNAS) += \
+	wd-mbwe.dtb
 dtb-$(CONFIG_ARCH_QCOM) += \
+	qcom-apq8064-arrow-db600c.dtb \
 	qcom-apq8064-cm-qs600.dtb \
 	qcom-apq8064-ifc6410.dtb \
 	qcom-apq8064-sony-xperia-yuga.dtb \
@@ -546,13 +580,20 @@ dtb-$(CONFIG_ARCH_QCOM) += \
 	qcom-apq8074-dragonboard.dtb \
 	qcom-apq8084-ifc6540.dtb \
 	qcom-apq8084-mtp.dtb \
+	qcom-ipq4019-ap.dk01.1-c1.dtb \
 	qcom-ipq8064-ap148.dtb \
 	qcom-msm8660-surf.dtb \
 	qcom-msm8960-cdp.dtb \
 	qcom-msm8974-sony-xperia-honami.dtb
 dtb-$(CONFIG_ARCH_REALVIEW) += \
 	arm-realview-pb1176.dtb \
-	arm-realview-pb11mp.dtb
+	arm-realview-pb11mp.dtb \
+	arm-realview-eb.dtb \
+	arm-realview-eb-11mp.dtb \
+	arm-realview-eb-11mp-revb.dtb \
+	arm-realview-eb-a9mp.dtb \
+	arm-realview-pba8.dtb \
+	arm-realview-pbx-a9.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += \
 	rk3036-evb.dtb \
 	rk3036-kylin.dtb \
@@ -565,6 +606,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \
 	rk3288-evb-rk808.dtb \
 	rk3288-firefly-beta.dtb \
 	rk3288-firefly.dtb \
+	rk3288-miqi.dtb \
 	rk3288-popmetal.dtb \
 	rk3288-r89.dtb \
 	rk3288-rock2-square.dtb \
@@ -608,6 +650,7 @@ dtb-$(CONFIG_ARCH_SOCFPGA) += \
 	socfpga_cyclone5_de0_sockit.dtb \
 	socfpga_cyclone5_sockit.dtb \
 	socfpga_cyclone5_socrates.dtb \
+	socfpga_cyclone5_vining_fpga.dtb \
 	socfpga_vt.dtb
 dtb-$(CONFIG_ARCH_SPEAR13XX) += \
 	spear1310-evb.dtb \
@@ -637,6 +680,7 @@ dtb-$(CONFIG_MACH_SUN4I) += \
 	sun4i-a10-ba10-tvbox.dtb \
 	sun4i-a10-chuwi-v7-cw0825.dtb \
 	sun4i-a10-cubieboard.dtb \
+	sun4i-a10-dserve-dsrv9703c.dtb \
 	sun4i-a10-gemei-g9.dtb \
 	sun4i-a10-hackberry.dtb \
 	sun4i-a10-hyundai-a7hd.dtb \
@@ -660,6 +704,7 @@ dtb-$(CONFIG_MACH_SUN5I) += \
 	sun5i-a10s-olinuxino-micro.dtb \
 	sun5i-a10s-r7-tv-dongle.dtb \
 	sun5i-a10s-wobo-i5.dtb \
+	sun5i-a13-difrnce-dit4350.dtb \
 	sun5i-a13-empire-electronix-d709.dtb \
 	sun5i-a13-hsg-h702.dtb \
 	sun5i-a13-inet-98v-rev2.dtb \
@@ -675,6 +720,7 @@ dtb-$(CONFIG_MACH_SUN6I) += \
 	sun6i-a31-i7.dtb \
 	sun6i-a31-m9.dtb \
 	sun6i-a31-mele-a1000g-quad.dtb \
+	sun6i-a31s-colorfly-e708-q1.dtb \
 	sun6i-a31s-cs908.dtb \
 	sun6i-a31s-primo81.dtb \
 	sun6i-a31s-sina31s.dtb \
@@ -695,6 +741,7 @@ dtb-$(CONFIG_MACH_SUN7I) += \
 	sun7i-a20-olimex-som-evb.dtb \
 	sun7i-a20-olinuxino-lime.dtb \
 	sun7i-a20-olinuxino-lime2.dtb \
+	sun7i-a20-olinuxino-lime2-emmc.dtb \
 	sun7i-a20-olinuxino-micro.dtb \
 	sun7i-a20-orangepi.dtb \
 	sun7i-a20-orangepi-mini.dtb \
@@ -707,6 +754,7 @@ dtb-$(CONFIG_MACH_SUN8I) += \
 	sun8i-a23-gt90h-v4.dtb \
 	sun8i-a23-ippo-q8h-v5.dtb \
 	sun8i-a23-ippo-q8h-v1.2.dtb \
+	sun8i-a23-polaroid-mid2809pxe04.dtb \
 	sun8i-a23-q8-tablet.dtb \
 	sun8i-a33-et-q8-v1.6.dtb \
 	sun8i-a33-ga10h-v1.1.dtb \
@@ -715,6 +763,9 @@ dtb-$(CONFIG_MACH_SUN8I) += \
 	sun8i-a33-sinlinx-sina33.dtb \
 	sun8i-a83t-allwinner-h8homlet-v2.dtb \
 	sun8i-a83t-cubietruck-plus.dtb \
+	sun8i-h3-orangepi-2.dtb \
+	sun8i-h3-orangepi-one.dtb \
+	sun8i-h3-orangepi-pc.dtb \
 	sun8i-h3-orangepi-plus.dtb
 dtb-$(CONFIG_MACH_SUN9I) += \
 	sun9i-a80-optimus.dtb \
@@ -839,6 +890,8 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \
 	mt8127-moose.dtb \
 	mt8135-evbp1.dtb
 dtb-$(CONFIG_ARCH_ZX) += zx296702-ad1.dtb
+dtb-$(CONFIG_ARCH_ASPEED) += aspeed-bmc-opp-palmetto.dtb \
+	aspeed-ast2500-evb.dtb
 endif
 
 dtstree		:= $(srctree)/$(src)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/mps2-an385.dts linux-libre-4.7-gnu/arch/arm/boot/dts/mps2-an385.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/mps2-an385.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/mps2-an385.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2015 ARM Limited
+ *
+ * Author: Vladimir Murzin <vladimir.murzin@arm.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include "mps2.dtsi"
+
+/ {
+	model = "ARM MPS2 Application Note 385/386";
+	compatible = "arm,mps2";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	chosen {
+		bootargs = "earlycon";
+		stdout-path = "serial0:9600n8";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x21000000 0x1000000>;
+	};
+
+	smb {
+		ethernet@0,0 {
+			compatible = "smsc,lan9220", "smsc,lan9115";
+			reg = <0 0x0 0x10000>;
+			interrupts = <13>;
+			interrupt-parent = <&nvic>;
+			smsc,irq-active-high;
+		};
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&timer0 {
+	status = "okay";
+};
+
+&timer1 {
+	status = "okay";
+};
+
+&wdt {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/mps2-an399.dts linux-libre-4.7-gnu/arch/arm/boot/dts/mps2-an399.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/mps2-an399.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/mps2-an399.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2015 ARM Limited
+ *
+ * Author: Vladimir Murzin <vladimir.murzin@arm.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include "mps2.dtsi"
+
+/ {
+	model = "ARM MPS2 Application Note 399/400";
+	compatible = "arm,mps2";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	chosen {
+		bootargs = "earlycon";
+		stdout-path = "serial0:9600n8";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x60000000 0x1000000>;
+	};
+
+	smb {
+		ethernet@1,0 {
+			compatible = "smsc,lan9220", "smsc,lan9115";
+			reg = <1 0x0 0x10000>;
+			interrupts = <13>;
+			interrupt-parent = <&nvic>;
+			smsc,irq-active-high;
+		};
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&timer0 {
+	status = "okay";
+};
+
+&timer1 {
+	status = "okay";
+};
+
+&wdt {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/mps2.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/mps2.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/mps2.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/mps2.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2015 ARM Limited
+ *
+ * Author: Vladimir Murzin <vladimir.murzin@arm.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "armv7-m.dtsi"
+
+/ {
+	oscclk0: clk-osc0 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <50000000>;
+	};
+
+	oscclk1: clk-osc1 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <24576000>;
+	};
+
+	oscclk2: clk-osc2 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <25000000>;
+	};
+
+	cfgclk: clk-cfg {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <5000000>;
+	};
+
+	spicfgclk: clk-spicfg {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <75000000>;
+	};
+
+	sysclk: clk-sys {
+		compatible = "fixed-factor-clock";
+		clocks = <&oscclk0>;
+		#clock-cells = <0>;
+		clock-div = <2>;
+		clock-mult = <1>;
+	};
+
+	audmclk: clk-audm {
+		compatible = "fixed-factor-clock";
+		clocks = <&oscclk1>;
+		#clock-cells = <0>;
+		clock-div = <2>;
+		clock-mult = <1>;
+	};
+
+	audsclk: clk-auds {
+		compatible = "fixed-factor-clock";
+		clocks = <&oscclk1>;
+		#clock-cells = <0>;
+		clock-div = <8>;
+		clock-mult = <1>;
+	};
+
+	spiclcd: clk-cpiclcd {
+		compatible = "fixed-factor-clock";
+		clocks = <&oscclk0>;
+		#clock-cells = <0>;
+		clock-div = <2>;
+		clock-mult = <1>;
+	};
+
+	spicon: clk-spicon {
+		compatible = "fixed-factor-clock";
+		clocks = <&oscclk0>;
+		#clock-cells = <0>;
+		clock-div = <2>;
+		clock-mult = <1>;
+	};
+
+	i2cclcd: clk-i2cclcd {
+		compatible = "fixed-factor-clock";
+		clocks = <&oscclk0>;
+		#clock-cells = <0>;
+		clock-div = <2>;
+		clock-mult = <1>;
+	};
+
+	i2caud: clk-i2caud {
+		compatible = "fixed-factor-clock";
+		clocks = <&oscclk0>;
+		#clock-cells = <0>;
+		clock-div = <2>;
+		clock-mult = <1>;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		ranges;
+
+		apb@40000000 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 0x40000000 0x10000>;
+
+			timer0: mps2-timer0@0 {
+				compatible = "arm,mps2-timer";
+				reg = <0x0 0x1000>;
+				interrupts = <8>;
+				clocks = <&sysclk>;
+				status = "disabled";
+			};
+
+			timer1: mps2-timer1@1000 {
+				compatible = "arm,mps2-timer";
+				reg = <0x1000 0x1000>;
+				interrupts = <9>;
+				clocks = <&sysclk>;
+				status = "disabled";
+			};
+
+			timer2: dual-timer@2000 {
+				compatible = "arm,sp804";
+				reg = <0x2000 0x1000>;
+				clocks = <&sysclk>;
+				interrupts = <10>;
+				status = "disabled";
+			};
+
+			uart0: serial@4000 {
+				compatible = "arm,mps2-uart";
+				reg = <0x4000 0x1000>;
+				interrupts = <0 1 12>;
+				clocks = <&sysclk>;
+				status = "disabled";
+			};
+
+			uart1: serial@5000 {
+				compatible = "arm,mps2-uart";
+				reg = <0x5000 0x1000>;
+				interrupts = <2 3 12>;
+				clocks = <&sysclk>;
+				status = "disabled";
+			};
+
+			uart2: serial@6000 {
+				compatible = "arm,mps2-uart";
+				reg = <0x6000 0x1000>;
+				interrupts = <4 5 12>;
+				clocks = <&sysclk>;
+				status = "disabled";
+			};
+
+			wdt: watchdog@8000 {
+				compatible = "arm,sp805", "arm,primecell";
+				arm,primecell-periphid = <0x00141805>;
+				reg = <0x8000 0x1000>;
+				interrupts = <0>;
+				clocks = <&sysclk>;
+				clock-names = "apb_pclk";
+				status = "disabled";
+			};
+		};
+	};
+
+	fpga@40020000 {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0x40020000 0x10000>;
+
+		fpgaio@8000 {
+			compatible = "syscon", "simple-mfd";
+			reg = <0x8000 0x10>;
+
+			led0 {
+				compatible = "register-bit-led";
+				offset = <0x0>;
+				mask = <0x01>;
+				label = "userled:0";
+				linux,default-trigger = "heartbeat";
+				default-state = "on";
+			};
+
+			led1 {
+				compatible = "register-bit-led";
+				offset = <0x0>;
+				mask = <0x02>;
+				label = "userled:1";
+				linux,default-trigger = "usr";
+				default-state = "off";
+			};
+		};
+	};
+
+	smb {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <1>;
+		ranges = <0 0 0x40200000 0x10000>,
+			 <1 0 0xa0000000 0x10000>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/mt2701.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/mt2701.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/mt2701.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/mt2701.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -15,6 +15,7 @@
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include "skeleton64.dtsi"
+#include "mt2701-pinfunc.h"
 
 / {
 	compatible = "mediatek,mt2701";
@@ -85,6 +86,24 @@
 			     <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
 	};
 
+	pio: pinctrl@10005000 {
+		compatible = "mediatek,mt2701-pinctrl";
+		reg = <0 0x1000b000 0 0x1000>;
+		mediatek,pctl-regmap = <&syscfg_pctl_a>;
+		pins-are-numbered;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	syscfg_pctl_a: syscfg@10005000 {
+		compatible = "mediatek,mt2701-pctl-a-syscfg", "syscon";
+		reg = <0 0x10005000 0 0x1000>;
+	};
+
 	watchdog: watchdog@10007000 {
 		compatible = "mediatek,mt2701-wdt",
 			     "mediatek,mt6589-wdt";
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/omap2420-clocks.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/omap2420-clocks.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/omap2420-clocks.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/omap2420-clocks.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -9,7 +9,7 @@
  */
 
 &prcm_clocks {
-	sys_clkout2_src_gate: sys_clkout2_src_gate {
+	sys_clkout2_src_gate: sys_clkout2_src_gate@70 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-no-wait-gate-clock";
 		clocks = <&core_ck>;
@@ -17,7 +17,7 @@
 		reg = <0x0070>;
 	};
 
-	sys_clkout2_src_mux: sys_clkout2_src_mux {
+	sys_clkout2_src_mux: sys_clkout2_src_mux@70 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&core_ck>, <&sys_ck>, <&func_96m_ck>, <&func_54m_ck>;
@@ -31,7 +31,7 @@
 		clocks = <&sys_clkout2_src_gate>, <&sys_clkout2_src_mux>;
 	};
 
-	sys_clkout2: sys_clkout2 {
+	sys_clkout2: sys_clkout2@70 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&sys_clkout2_src>;
@@ -41,7 +41,7 @@
 		ti,index-power-of-two;
 	};
 
-	dsp_gate_ick: dsp_gate_ick {
+	dsp_gate_ick: dsp_gate_ick@810 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-interface-clock";
 		clocks = <&dsp_fck>;
@@ -49,7 +49,7 @@
 		reg = <0x0810>;
 	};
 
-	dsp_div_ick: dsp_div_ick {
+	dsp_div_ick: dsp_div_ick@840 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-divider-clock";
 		clocks = <&dsp_fck>;
@@ -65,7 +65,7 @@
 		clocks = <&dsp_gate_ick>, <&dsp_div_ick>;
 	};
 
-	iva1_gate_ifck: iva1_gate_ifck {
+	iva1_gate_ifck: iva1_gate_ifck@800 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&core_ck>;
@@ -73,7 +73,7 @@
 		reg = <0x0800>;
 	};
 
-	iva1_div_ifck: iva1_div_ifck {
+	iva1_div_ifck: iva1_div_ifck@840 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-divider-clock";
 		clocks = <&core_ck>;
@@ -96,7 +96,7 @@
 		clock-div = <2>;
 	};
 
-	iva1_mpu_int_ifck: iva1_mpu_int_ifck {
+	iva1_mpu_int_ifck: iva1_mpu_int_ifck@800 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&iva1_ifck_div>;
@@ -104,7 +104,7 @@
 		reg = <0x0800>;
 	};
 
-	wdt3_ick: wdt3_ick {
+	wdt3_ick: wdt3_ick@210 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -112,7 +112,7 @@
 		reg = <0x0210>;
 	};
 
-	wdt3_fck: wdt3_fck {
+	wdt3_fck: wdt3_fck@200 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&func_32k_ck>;
@@ -120,7 +120,7 @@
 		reg = <0x0200>;
 	};
 
-	mmc_ick: mmc_ick {
+	mmc_ick: mmc_ick@210 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -128,7 +128,7 @@
 		reg = <0x0210>;
 	};
 
-	mmc_fck: mmc_fck {
+	mmc_fck: mmc_fck@200 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&func_96m_ck>;
@@ -136,7 +136,7 @@
 		reg = <0x0200>;
 	};
 
-	eac_ick: eac_ick {
+	eac_ick: eac_ick@210 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -144,7 +144,7 @@
 		reg = <0x0210>;
 	};
 
-	eac_fck: eac_fck {
+	eac_fck: eac_fck@200 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&func_96m_ck>;
@@ -152,7 +152,7 @@
 		reg = <0x0200>;
 	};
 
-	i2c1_fck: i2c1_fck {
+	i2c1_fck: i2c1_fck@200 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&func_12m_ck>;
@@ -160,7 +160,7 @@
 		reg = <0x0200>;
 	};
 
-	i2c2_fck: i2c2_fck {
+	i2c2_fck: i2c2_fck@200 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&func_12m_ck>;
@@ -168,7 +168,7 @@
 		reg = <0x0200>;
 	};
 
-	vlynq_ick: vlynq_ick {
+	vlynq_ick: vlynq_ick@210 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&core_l3_ck>;
@@ -176,7 +176,7 @@
 		reg = <0x0210>;
 	};
 
-	vlynq_gate_fck: vlynq_gate_fck {
+	vlynq_gate_fck: vlynq_gate_fck@200 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&core_ck>;
@@ -192,7 +192,7 @@
 		clock-div = <18>;
 	};
 
-	vlynq_mux_fck: vlynq_mux_fck {
+	vlynq_mux_fck: vlynq_mux_fck@240 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&func_96m_ck>, <&core_ck>, <&core_d2_ck>, <&core_d3_ck>, <&core_d4_ck>, <&dummy_ck>, <&core_d6_ck>, <&dummy_ck>, <&core_d8_ck>, <&core_d9_ck>, <&dummy_ck>, <&dummy_ck>, <&core_d12_ck>, <&dummy_ck>, <&dummy_ck>, <&dummy_ck>, <&core_d16_ck>, <&dummy_ck>, <&core_d18_ck>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/omap2420.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/omap2420.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/omap2420.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/omap2420.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -130,6 +130,10 @@
 			gpmc,num-cs = <8>;
 			gpmc,num-waitpins = <4>;
 			ti,hwmods = "gpmc";
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			gpio-controller;
+			#gpio-cells = <2>;
 		};
 
 		mcbsp1: mcbsp@48074000 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/omap2420-n8x0-common.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/omap2420-n8x0-common.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/omap2420-n8x0-common.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/omap2420-n8x0-common.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -7,7 +7,7 @@
 	};
 
 	ocp {
-		i2c@0 {
+		i2c0 {
 			compatible = "i2c-cbus-gpio";
 			gpios = <&gpio3 2 GPIO_ACTIVE_HIGH /* gpio66 clk */
 				 &gpio3 1 GPIO_ACTIVE_HIGH /* gpio65 dat */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/omap2430-clocks.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/omap2430-clocks.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/omap2430-clocks.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/omap2430-clocks.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -9,7 +9,7 @@
  */
 
 &scm_clocks {
-	mcbsp3_mux_fck: mcbsp3_mux_fck {
+	mcbsp3_mux_fck: mcbsp3_mux_fck@78 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&func_96m_ck>, <&mcbsp_clks>;
@@ -22,7 +22,7 @@
 		clocks = <&mcbsp3_gate_fck>, <&mcbsp3_mux_fck>;
 	};
 
-	mcbsp4_mux_fck: mcbsp4_mux_fck {
+	mcbsp4_mux_fck: mcbsp4_mux_fck@78 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&func_96m_ck>, <&mcbsp_clks>;
@@ -36,7 +36,7 @@
 		clocks = <&mcbsp4_gate_fck>, <&mcbsp4_mux_fck>;
 	};
 
-	mcbsp5_mux_fck: mcbsp5_mux_fck {
+	mcbsp5_mux_fck: mcbsp5_mux_fck@78 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&func_96m_ck>, <&mcbsp_clks>;
@@ -52,7 +52,7 @@
 };
 
 &prcm_clocks {
-	iva2_1_gate_ick: iva2_1_gate_ick {
+	iva2_1_gate_ick: iva2_1_gate_ick@800 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&dsp_fck>;
@@ -60,7 +60,7 @@
 		reg = <0x0800>;
 	};
 
-	iva2_1_div_ick: iva2_1_div_ick {
+	iva2_1_div_ick: iva2_1_div_ick@840 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-divider-clock";
 		clocks = <&dsp_fck>;
@@ -76,7 +76,7 @@
 		clocks = <&iva2_1_gate_ick>, <&iva2_1_div_ick>;
 	};
 
-	mdm_gate_ick: mdm_gate_ick {
+	mdm_gate_ick: mdm_gate_ick@c10 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-interface-clock";
 		clocks = <&core_ck>;
@@ -84,7 +84,7 @@
 		reg = <0x0c10>;
 	};
 
-	mdm_div_ick: mdm_div_ick {
+	mdm_div_ick: mdm_div_ick@c40 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-divider-clock";
 		clocks = <&core_ck>;
@@ -98,7 +98,7 @@
 		clocks = <&mdm_gate_ick>, <&mdm_div_ick>;
 	};
 
-	mdm_osc_ck: mdm_osc_ck {
+	mdm_osc_ck: mdm_osc_ck@c00 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&osc_ck>;
@@ -106,7 +106,7 @@
 		reg = <0x0c00>;
 	};
 
-	mcbsp3_ick: mcbsp3_ick {
+	mcbsp3_ick: mcbsp3_ick@214 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -114,7 +114,7 @@
 		reg = <0x0214>;
 	};
 
-	mcbsp3_gate_fck: mcbsp3_gate_fck {
+	mcbsp3_gate_fck: mcbsp3_gate_fck@204 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&mcbsp_clks>;
@@ -122,7 +122,7 @@
 		reg = <0x0204>;
 	};
 
-	mcbsp4_ick: mcbsp4_ick {
+	mcbsp4_ick: mcbsp4_ick@214 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -130,7 +130,7 @@
 		reg = <0x0214>;
 	};
 
-	mcbsp4_gate_fck: mcbsp4_gate_fck {
+	mcbsp4_gate_fck: mcbsp4_gate_fck@204 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&mcbsp_clks>;
@@ -138,7 +138,7 @@
 		reg = <0x0204>;
 	};
 
-	mcbsp5_ick: mcbsp5_ick {
+	mcbsp5_ick: mcbsp5_ick@214 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -146,7 +146,7 @@
 		reg = <0x0214>;
 	};
 
-	mcbsp5_gate_fck: mcbsp5_gate_fck {
+	mcbsp5_gate_fck: mcbsp5_gate_fck@204 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&mcbsp_clks>;
@@ -154,7 +154,7 @@
 		reg = <0x0204>;
 	};
 
-	mcspi3_ick: mcspi3_ick {
+	mcspi3_ick: mcspi3_ick@214 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -162,7 +162,7 @@
 		reg = <0x0214>;
 	};
 
-	mcspi3_fck: mcspi3_fck {
+	mcspi3_fck: mcspi3_fck@204 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&func_48m_ck>;
@@ -170,7 +170,7 @@
 		reg = <0x0204>;
 	};
 
-	icr_ick: icr_ick {
+	icr_ick: icr_ick@410 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&sys_ck>;
@@ -178,7 +178,7 @@
 		reg = <0x0410>;
 	};
 
-	i2chs1_fck: i2chs1_fck {
+	i2chs1_fck: i2chs1_fck@204 {
 		#clock-cells = <0>;
 		compatible = "ti,omap2430-interface-clock";
 		clocks = <&func_96m_ck>;
@@ -186,7 +186,7 @@
 		reg = <0x0204>;
 	};
 
-	i2chs2_fck: i2chs2_fck {
+	i2chs2_fck: i2chs2_fck@204 {
 		#clock-cells = <0>;
 		compatible = "ti,omap2430-interface-clock";
 		clocks = <&func_96m_ck>;
@@ -194,7 +194,7 @@
 		reg = <0x0204>;
 	};
 
-	usbhs_ick: usbhs_ick {
+	usbhs_ick: usbhs_ick@214 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&core_l3_ck>;
@@ -202,7 +202,7 @@
 		reg = <0x0214>;
 	};
 
-	mmchs1_ick: mmchs1_ick {
+	mmchs1_ick: mmchs1_ick@214 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -210,7 +210,7 @@
 		reg = <0x0214>;
 	};
 
-	mmchs1_fck: mmchs1_fck {
+	mmchs1_fck: mmchs1_fck@204 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&func_96m_ck>;
@@ -218,7 +218,7 @@
 		reg = <0x0204>;
 	};
 
-	mmchs2_ick: mmchs2_ick {
+	mmchs2_ick: mmchs2_ick@214 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -226,7 +226,7 @@
 		reg = <0x0214>;
 	};
 
-	mmchs2_fck: mmchs2_fck {
+	mmchs2_fck: mmchs2_fck@204 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&func_96m_ck>;
@@ -234,7 +234,7 @@
 		reg = <0x0204>;
 	};
 
-	gpio5_ick: gpio5_ick {
+	gpio5_ick: gpio5_ick@214 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -242,7 +242,7 @@
 		reg = <0x0214>;
 	};
 
-	gpio5_fck: gpio5_fck {
+	gpio5_fck: gpio5_fck@204 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&func_32k_ck>;
@@ -250,7 +250,7 @@
 		reg = <0x0204>;
 	};
 
-	mdm_intc_ick: mdm_intc_ick {
+	mdm_intc_ick: mdm_intc_ick@214 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -258,7 +258,7 @@
 		reg = <0x0214>;
 	};
 
-	mmchsdb1_fck: mmchsdb1_fck {
+	mmchsdb1_fck: mmchsdb1_fck@204 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&func_32k_ck>;
@@ -266,7 +266,7 @@
 		reg = <0x0204>;
 	};
 
-	mmchsdb2_fck: mmchsdb2_fck {
+	mmchsdb2_fck: mmchsdb2_fck@204 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&func_32k_ck>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/omap2430.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/omap2430.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/omap2430.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/omap2430.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -63,7 +63,7 @@
 						#size-cells = <0>;
 					};
 
-					pbias_regulator: pbias_regulator {
+					pbias_regulator: pbias_regulator@230 {
 						compatible = "ti,pbias-omap2", "ti,pbias-omap";
 						reg = <0x230 0x4>;
 						syscon = <&scm_conf>;
@@ -154,6 +154,10 @@
 			gpmc,num-cs = <8>;
 			gpmc,num-waitpins = <4>;
 			ti,hwmods = "gpmc";
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			gpio-controller;
+			#gpio-cells = <2>;
 		};
 
 		mcbsp1: mcbsp@48074000 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/omap24xx-clocks.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/omap24xx-clocks.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/omap24xx-clocks.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/omap24xx-clocks.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -8,7 +8,7 @@
  * published by the Free Software Foundation.
  */
 &scm_clocks {
-	mcbsp1_mux_fck: mcbsp1_mux_fck {
+	mcbsp1_mux_fck: mcbsp1_mux_fck@4 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&func_96m_ck>, <&mcbsp_clks>;
@@ -22,7 +22,7 @@
 		clocks = <&mcbsp1_gate_fck>, <&mcbsp1_mux_fck>;
 	};
 
-	mcbsp2_mux_fck: mcbsp2_mux_fck {
+	mcbsp2_mux_fck: mcbsp2_mux_fck@4 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&func_96m_ck>, <&mcbsp_clks>;
@@ -74,7 +74,7 @@
 		clock-frequency = <26000000>;
 	};
 
-	aplls_clkin_ck: aplls_clkin_ck {
+	aplls_clkin_ck: aplls_clkin_ck@540 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&virt_19200000_ck>, <&virt_26m_ck>, <&virt_13m_ck>, <&virt_12m_ck>;
@@ -90,7 +90,7 @@
 		clock-div = <1>;
 	};
 
-	osc_ck: osc_ck {
+	osc_ck: osc_ck@60 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&aplls_clkin_ck>, <&aplls_clkin_x2_ck>;
@@ -99,7 +99,7 @@
 		ti,index-starts-at-one;
 	};
 
-	sys_ck: sys_ck {
+	sys_ck: sys_ck@60 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&osc_ck>;
@@ -121,14 +121,14 @@
 		clock-frequency = <0x0>;
 	};
 
-	dpll_ck: dpll_ck {
+	dpll_ck: dpll_ck@500 {
 		#clock-cells = <0>;
 		compatible = "ti,omap2-dpll-core-clock";
 		clocks = <&sys_ck>, <&sys_ck>;
 		reg = <0x0500>, <0x0540>;
 	};
 
-	apll96_ck: apll96_ck {
+	apll96_ck: apll96_ck@500 {
 		#clock-cells = <0>;
 		compatible = "ti,omap2-apll-clock";
 		clocks = <&sys_ck>;
@@ -138,7 +138,7 @@
 		reg = <0x0500>, <0x0530>, <0x0520>;
 	};
 
-	apll54_ck: apll54_ck {
+	apll54_ck: apll54_ck@500 {
 		#clock-cells = <0>;
 		compatible = "ti,omap2-apll-clock";
 		clocks = <&sys_ck>;
@@ -148,7 +148,7 @@
 		reg = <0x0500>, <0x0530>, <0x0520>;
 	};
 
-	func_54m_ck: func_54m_ck {
+	func_54m_ck: func_54m_ck@540 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&apll54_ck>, <&alt_ck>;
@@ -176,7 +176,7 @@
 		clock-div = <2>;
 	};
 
-	func_48m_ck: func_48m_ck {
+	func_48m_ck: func_48m_ck@540 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&apll96_d2_ck>, <&alt_ck>;
@@ -192,7 +192,7 @@
 		clock-div = <4>;
 	};
 
-	sys_clkout_src_gate: sys_clkout_src_gate {
+	sys_clkout_src_gate: sys_clkout_src_gate@70 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-no-wait-gate-clock";
 		clocks = <&core_ck>;
@@ -200,7 +200,7 @@
 		reg = <0x0070>;
 	};
 
-	sys_clkout_src_mux: sys_clkout_src_mux {
+	sys_clkout_src_mux: sys_clkout_src_mux@70 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&core_ck>, <&sys_ck>, <&func_96m_ck>, <&func_54m_ck>;
@@ -213,7 +213,7 @@
 		clocks = <&sys_clkout_src_gate>, <&sys_clkout_src_mux>;
 	};
 
-	sys_clkout: sys_clkout {
+	sys_clkout: sys_clkout@70 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&sys_clkout_src>;
@@ -223,7 +223,7 @@
 		ti,index-power-of-two;
 	};
 
-	emul_ck: emul_ck {
+	emul_ck: emul_ck@78 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&func_54m_ck>;
@@ -231,7 +231,7 @@
 		reg = <0x0078>;
 	};
 
-	mpu_ck: mpu_ck {
+	mpu_ck: mpu_ck@140 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&core_ck>;
@@ -240,7 +240,7 @@
 		ti,index-starts-at-one;
 	};
 
-	dsp_gate_fck: dsp_gate_fck {
+	dsp_gate_fck: dsp_gate_fck@800 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&core_ck>;
@@ -248,7 +248,7 @@
 		reg = <0x0800>;
 	};
 
-	dsp_div_fck: dsp_div_fck {
+	dsp_div_fck: dsp_div_fck@840 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-divider-clock";
 		clocks = <&core_ck>;
@@ -261,7 +261,7 @@
 		clocks = <&dsp_gate_fck>, <&dsp_div_fck>;
 	};
 
-	core_l3_ck: core_l3_ck {
+	core_l3_ck: core_l3_ck@240 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&core_ck>;
@@ -270,7 +270,7 @@
 		ti,index-starts-at-one;
 	};
 
-	gfx_3d_gate_fck: gfx_3d_gate_fck {
+	gfx_3d_gate_fck: gfx_3d_gate_fck@300 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&core_l3_ck>;
@@ -278,7 +278,7 @@
 		reg = <0x0300>;
 	};
 
-	gfx_3d_div_fck: gfx_3d_div_fck {
+	gfx_3d_div_fck: gfx_3d_div_fck@340 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-divider-clock";
 		clocks = <&core_l3_ck>;
@@ -293,7 +293,7 @@
 		clocks = <&gfx_3d_gate_fck>, <&gfx_3d_div_fck>;
 	};
 
-	gfx_2d_gate_fck: gfx_2d_gate_fck {
+	gfx_2d_gate_fck: gfx_2d_gate_fck@300 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&core_l3_ck>;
@@ -301,7 +301,7 @@
 		reg = <0x0300>;
 	};
 
-	gfx_2d_div_fck: gfx_2d_div_fck {
+	gfx_2d_div_fck: gfx_2d_div_fck@340 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-divider-clock";
 		clocks = <&core_l3_ck>;
@@ -316,7 +316,7 @@
 		clocks = <&gfx_2d_gate_fck>, <&gfx_2d_div_fck>;
 	};
 
-	gfx_ick: gfx_ick {
+	gfx_ick: gfx_ick@310 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&core_l3_ck>;
@@ -324,7 +324,7 @@
 		reg = <0x0310>;
 	};
 
-	l4_ck: l4_ck {
+	l4_ck: l4_ck@240 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&core_l3_ck>;
@@ -334,7 +334,7 @@
 		ti,index-starts-at-one;
 	};
 
-	dss_ick: dss_ick {
+	dss_ick: dss_ick@210 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-no-wait-interface-clock";
 		clocks = <&l4_ck>;
@@ -342,7 +342,7 @@
 		reg = <0x0210>;
 	};
 
-	dss1_gate_fck: dss1_gate_fck {
+	dss1_gate_fck: dss1_gate_fck@200 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-no-wait-gate-clock";
 		clocks = <&core_ck>;
@@ -428,7 +428,7 @@
 		clock-div = <16>;
 	};
 
-	dss1_mux_fck: dss1_mux_fck {
+	dss1_mux_fck: dss1_mux_fck@240 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&sys_ck>, <&core_ck>, <&core_d2_ck>, <&core_d3_ck>, <&core_d4_ck>, <&core_d5_ck>, <&core_d6_ck>, <&core_d8_ck>, <&core_d9_ck>, <&core_d12_ck>, <&core_d16_ck>;
@@ -442,7 +442,7 @@
 		clocks = <&dss1_gate_fck>, <&dss1_mux_fck>;
 	};
 
-	dss2_gate_fck: dss2_gate_fck {
+	dss2_gate_fck: dss2_gate_fck@200 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-no-wait-gate-clock";
 		clocks = <&func_48m_ck>;
@@ -450,7 +450,7 @@
 		reg = <0x0200>;
 	};
 
-	dss2_mux_fck: dss2_mux_fck {
+	dss2_mux_fck: dss2_mux_fck@240 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&sys_ck>, <&func_48m_ck>;
@@ -464,7 +464,7 @@
 		clocks = <&dss2_gate_fck>, <&dss2_mux_fck>;
 	};
 
-	dss_54m_fck: dss_54m_fck {
+	dss_54m_fck: dss_54m_fck@200 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&func_54m_ck>;
@@ -472,7 +472,7 @@
 		reg = <0x0200>;
 	};
 
-	ssi_ssr_sst_gate_fck: ssi_ssr_sst_gate_fck {
+	ssi_ssr_sst_gate_fck: ssi_ssr_sst_gate_fck@204 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&core_ck>;
@@ -480,7 +480,7 @@
 		reg = <0x0204>;
 	};
 
-	ssi_ssr_sst_div_fck: ssi_ssr_sst_div_fck {
+	ssi_ssr_sst_div_fck: ssi_ssr_sst_div_fck@240 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-divider-clock";
 		clocks = <&core_ck>;
@@ -494,7 +494,7 @@
 		clocks = <&ssi_ssr_sst_gate_fck>, <&ssi_ssr_sst_div_fck>;
 	};
 
-	usb_l4_gate_ick: usb_l4_gate_ick {
+	usb_l4_gate_ick: usb_l4_gate_ick@214 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-interface-clock";
 		clocks = <&core_l3_ck>;
@@ -502,7 +502,7 @@
 		reg = <0x0214>;
 	};
 
-	usb_l4_div_ick: usb_l4_div_ick {
+	usb_l4_div_ick: usb_l4_div_ick@240 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-divider-clock";
 		clocks = <&core_l3_ck>;
@@ -517,7 +517,7 @@
 		clocks = <&usb_l4_gate_ick>, <&usb_l4_div_ick>;
 	};
 
-	ssi_l4_ick: ssi_l4_ick {
+	ssi_l4_ick: ssi_l4_ick@214 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -525,7 +525,7 @@
 		reg = <0x0214>;
 	};
 
-	gpt1_ick: gpt1_ick {
+	gpt1_ick: gpt1_ick@410 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&sys_ck>;
@@ -533,7 +533,7 @@
 		reg = <0x0410>;
 	};
 
-	gpt1_gate_fck: gpt1_gate_fck {
+	gpt1_gate_fck: gpt1_gate_fck@400 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&func_32k_ck>;
@@ -541,7 +541,7 @@
 		reg = <0x0400>;
 	};
 
-	gpt1_mux_fck: gpt1_mux_fck {
+	gpt1_mux_fck: gpt1_mux_fck@440 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&func_32k_ck>, <&sys_ck>, <&alt_ck>;
@@ -554,7 +554,7 @@
 		clocks = <&gpt1_gate_fck>, <&gpt1_mux_fck>;
 	};
 
-	gpt2_ick: gpt2_ick {
+	gpt2_ick: gpt2_ick@210 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -562,7 +562,7 @@
 		reg = <0x0210>;
 	};
 
-	gpt2_gate_fck: gpt2_gate_fck {
+	gpt2_gate_fck: gpt2_gate_fck@200 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&func_32k_ck>;
@@ -570,7 +570,7 @@
 		reg = <0x0200>;
 	};
 
-	gpt2_mux_fck: gpt2_mux_fck {
+	gpt2_mux_fck: gpt2_mux_fck@244 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&func_32k_ck>, <&sys_ck>, <&alt_ck>;
@@ -584,7 +584,7 @@
 		clocks = <&gpt2_gate_fck>, <&gpt2_mux_fck>;
 	};
 
-	gpt3_ick: gpt3_ick {
+	gpt3_ick: gpt3_ick@210 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -592,7 +592,7 @@
 		reg = <0x0210>;
 	};
 
-	gpt3_gate_fck: gpt3_gate_fck {
+	gpt3_gate_fck: gpt3_gate_fck@200 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&func_32k_ck>;
@@ -600,7 +600,7 @@
 		reg = <0x0200>;
 	};
 
-	gpt3_mux_fck: gpt3_mux_fck {
+	gpt3_mux_fck: gpt3_mux_fck@244 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&func_32k_ck>, <&sys_ck>, <&alt_ck>;
@@ -614,7 +614,7 @@
 		clocks = <&gpt3_gate_fck>, <&gpt3_mux_fck>;
 	};
 
-	gpt4_ick: gpt4_ick {
+	gpt4_ick: gpt4_ick@210 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -622,7 +622,7 @@
 		reg = <0x0210>;
 	};
 
-	gpt4_gate_fck: gpt4_gate_fck {
+	gpt4_gate_fck: gpt4_gate_fck@200 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&func_32k_ck>;
@@ -630,7 +630,7 @@
 		reg = <0x0200>;
 	};
 
-	gpt4_mux_fck: gpt4_mux_fck {
+	gpt4_mux_fck: gpt4_mux_fck@244 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&func_32k_ck>, <&sys_ck>, <&alt_ck>;
@@ -644,7 +644,7 @@
 		clocks = <&gpt4_gate_fck>, <&gpt4_mux_fck>;
 	};
 
-	gpt5_ick: gpt5_ick {
+	gpt5_ick: gpt5_ick@210 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -652,7 +652,7 @@
 		reg = <0x0210>;
 	};
 
-	gpt5_gate_fck: gpt5_gate_fck {
+	gpt5_gate_fck: gpt5_gate_fck@200 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&func_32k_ck>;
@@ -660,7 +660,7 @@
 		reg = <0x0200>;
 	};
 
-	gpt5_mux_fck: gpt5_mux_fck {
+	gpt5_mux_fck: gpt5_mux_fck@244 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&func_32k_ck>, <&sys_ck>, <&alt_ck>;
@@ -674,7 +674,7 @@
 		clocks = <&gpt5_gate_fck>, <&gpt5_mux_fck>;
 	};
 
-	gpt6_ick: gpt6_ick {
+	gpt6_ick: gpt6_ick@210 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -682,7 +682,7 @@
 		reg = <0x0210>;
 	};
 
-	gpt6_gate_fck: gpt6_gate_fck {
+	gpt6_gate_fck: gpt6_gate_fck@200 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&func_32k_ck>;
@@ -690,7 +690,7 @@
 		reg = <0x0200>;
 	};
 
-	gpt6_mux_fck: gpt6_mux_fck {
+	gpt6_mux_fck: gpt6_mux_fck@244 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&func_32k_ck>, <&sys_ck>, <&alt_ck>;
@@ -704,7 +704,7 @@
 		clocks = <&gpt6_gate_fck>, <&gpt6_mux_fck>;
 	};
 
-	gpt7_ick: gpt7_ick {
+	gpt7_ick: gpt7_ick@210 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -712,7 +712,7 @@
 		reg = <0x0210>;
 	};
 
-	gpt7_gate_fck: gpt7_gate_fck {
+	gpt7_gate_fck: gpt7_gate_fck@200 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&func_32k_ck>;
@@ -720,7 +720,7 @@
 		reg = <0x0200>;
 	};
 
-	gpt7_mux_fck: gpt7_mux_fck {
+	gpt7_mux_fck: gpt7_mux_fck@244 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&func_32k_ck>, <&sys_ck>, <&alt_ck>;
@@ -734,7 +734,7 @@
 		clocks = <&gpt7_gate_fck>, <&gpt7_mux_fck>;
 	};
 
-	gpt8_ick: gpt8_ick {
+	gpt8_ick: gpt8_ick@210 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -742,7 +742,7 @@
 		reg = <0x0210>;
 	};
 
-	gpt8_gate_fck: gpt8_gate_fck {
+	gpt8_gate_fck: gpt8_gate_fck@200 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&func_32k_ck>;
@@ -750,7 +750,7 @@
 		reg = <0x0200>;
 	};
 
-	gpt8_mux_fck: gpt8_mux_fck {
+	gpt8_mux_fck: gpt8_mux_fck@244 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&func_32k_ck>, <&sys_ck>, <&alt_ck>;
@@ -764,7 +764,7 @@
 		clocks = <&gpt8_gate_fck>, <&gpt8_mux_fck>;
 	};
 
-	gpt9_ick: gpt9_ick {
+	gpt9_ick: gpt9_ick@210 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -772,7 +772,7 @@
 		reg = <0x0210>;
 	};
 
-	gpt9_gate_fck: gpt9_gate_fck {
+	gpt9_gate_fck: gpt9_gate_fck@200 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&func_32k_ck>;
@@ -780,7 +780,7 @@
 		reg = <0x0200>;
 	};
 
-	gpt9_mux_fck: gpt9_mux_fck {
+	gpt9_mux_fck: gpt9_mux_fck@244 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&func_32k_ck>, <&sys_ck>, <&alt_ck>;
@@ -794,7 +794,7 @@
 		clocks = <&gpt9_gate_fck>, <&gpt9_mux_fck>;
 	};
 
-	gpt10_ick: gpt10_ick {
+	gpt10_ick: gpt10_ick@210 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -802,7 +802,7 @@
 		reg = <0x0210>;
 	};
 
-	gpt10_gate_fck: gpt10_gate_fck {
+	gpt10_gate_fck: gpt10_gate_fck@200 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&func_32k_ck>;
@@ -810,7 +810,7 @@
 		reg = <0x0200>;
 	};
 
-	gpt10_mux_fck: gpt10_mux_fck {
+	gpt10_mux_fck: gpt10_mux_fck@244 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&func_32k_ck>, <&sys_ck>, <&alt_ck>;
@@ -824,7 +824,7 @@
 		clocks = <&gpt10_gate_fck>, <&gpt10_mux_fck>;
 	};
 
-	gpt11_ick: gpt11_ick {
+	gpt11_ick: gpt11_ick@210 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -832,7 +832,7 @@
 		reg = <0x0210>;
 	};
 
-	gpt11_gate_fck: gpt11_gate_fck {
+	gpt11_gate_fck: gpt11_gate_fck@200 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&func_32k_ck>;
@@ -840,7 +840,7 @@
 		reg = <0x0200>;
 	};
 
-	gpt11_mux_fck: gpt11_mux_fck {
+	gpt11_mux_fck: gpt11_mux_fck@244 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&func_32k_ck>, <&sys_ck>, <&alt_ck>;
@@ -854,7 +854,7 @@
 		clocks = <&gpt11_gate_fck>, <&gpt11_mux_fck>;
 	};
 
-	gpt12_ick: gpt12_ick {
+	gpt12_ick: gpt12_ick@210 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -862,7 +862,7 @@
 		reg = <0x0210>;
 	};
 
-	gpt12_gate_fck: gpt12_gate_fck {
+	gpt12_gate_fck: gpt12_gate_fck@200 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&func_32k_ck>;
@@ -870,7 +870,7 @@
 		reg = <0x0200>;
 	};
 
-	gpt12_mux_fck: gpt12_mux_fck {
+	gpt12_mux_fck: gpt12_mux_fck@244 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&func_32k_ck>, <&sys_ck>, <&alt_ck>;
@@ -884,7 +884,7 @@
 		clocks = <&gpt12_gate_fck>, <&gpt12_mux_fck>;
 	};
 
-	mcbsp1_ick: mcbsp1_ick {
+	mcbsp1_ick: mcbsp1_ick@210 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -892,7 +892,7 @@
 		reg = <0x0210>;
 	};
 
-	mcbsp1_gate_fck: mcbsp1_gate_fck {
+	mcbsp1_gate_fck: mcbsp1_gate_fck@200 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&mcbsp_clks>;
@@ -900,7 +900,7 @@
 		reg = <0x0200>;
 	};
 
-	mcbsp2_ick: mcbsp2_ick {
+	mcbsp2_ick: mcbsp2_ick@210 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -908,7 +908,7 @@
 		reg = <0x0210>;
 	};
 
-	mcbsp2_gate_fck: mcbsp2_gate_fck {
+	mcbsp2_gate_fck: mcbsp2_gate_fck@200 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&mcbsp_clks>;
@@ -916,7 +916,7 @@
 		reg = <0x0200>;
 	};
 
-	mcspi1_ick: mcspi1_ick {
+	mcspi1_ick: mcspi1_ick@210 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -924,7 +924,7 @@
 		reg = <0x0210>;
 	};
 
-	mcspi1_fck: mcspi1_fck {
+	mcspi1_fck: mcspi1_fck@200 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&func_48m_ck>;
@@ -932,7 +932,7 @@
 		reg = <0x0200>;
 	};
 
-	mcspi2_ick: mcspi2_ick {
+	mcspi2_ick: mcspi2_ick@210 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -940,7 +940,7 @@
 		reg = <0x0210>;
 	};
 
-	mcspi2_fck: mcspi2_fck {
+	mcspi2_fck: mcspi2_fck@200 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&func_48m_ck>;
@@ -948,7 +948,7 @@
 		reg = <0x0200>;
 	};
 
-	uart1_ick: uart1_ick {
+	uart1_ick: uart1_ick@210 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -956,7 +956,7 @@
 		reg = <0x0210>;
 	};
 
-	uart1_fck: uart1_fck {
+	uart1_fck: uart1_fck@200 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&func_48m_ck>;
@@ -964,7 +964,7 @@
 		reg = <0x0200>;
 	};
 
-	uart2_ick: uart2_ick {
+	uart2_ick: uart2_ick@210 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -972,7 +972,7 @@
 		reg = <0x0210>;
 	};
 
-	uart2_fck: uart2_fck {
+	uart2_fck: uart2_fck@200 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&func_48m_ck>;
@@ -980,7 +980,7 @@
 		reg = <0x0200>;
 	};
 
-	uart3_ick: uart3_ick {
+	uart3_ick: uart3_ick@214 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -988,7 +988,7 @@
 		reg = <0x0214>;
 	};
 
-	uart3_fck: uart3_fck {
+	uart3_fck: uart3_fck@204 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&func_48m_ck>;
@@ -996,7 +996,7 @@
 		reg = <0x0204>;
 	};
 
-	gpios_ick: gpios_ick {
+	gpios_ick: gpios_ick@410 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&sys_ck>;
@@ -1004,7 +1004,7 @@
 		reg = <0x0410>;
 	};
 
-	gpios_fck: gpios_fck {
+	gpios_fck: gpios_fck@400 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&func_32k_ck>;
@@ -1012,7 +1012,7 @@
 		reg = <0x0400>;
 	};
 
-	mpu_wdt_ick: mpu_wdt_ick {
+	mpu_wdt_ick: mpu_wdt_ick@410 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&sys_ck>;
@@ -1020,7 +1020,7 @@
 		reg = <0x0410>;
 	};
 
-	mpu_wdt_fck: mpu_wdt_fck {
+	mpu_wdt_fck: mpu_wdt_fck@400 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&func_32k_ck>;
@@ -1028,7 +1028,7 @@
 		reg = <0x0400>;
 	};
 
-	sync_32k_ick: sync_32k_ick {
+	sync_32k_ick: sync_32k_ick@410 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&sys_ck>;
@@ -1036,7 +1036,7 @@
 		reg = <0x0410>;
 	};
 
-	wdt1_ick: wdt1_ick {
+	wdt1_ick: wdt1_ick@410 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&sys_ck>;
@@ -1044,7 +1044,7 @@
 		reg = <0x0410>;
 	};
 
-	omapctrl_ick: omapctrl_ick {
+	omapctrl_ick: omapctrl_ick@410 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&sys_ck>;
@@ -1052,7 +1052,7 @@
 		reg = <0x0410>;
 	};
 
-	cam_fck: cam_fck {
+	cam_fck: cam_fck@200 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&func_96m_ck>;
@@ -1060,7 +1060,7 @@
 		reg = <0x0200>;
 	};
 
-	cam_ick: cam_ick {
+	cam_ick: cam_ick@210 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-no-wait-interface-clock";
 		clocks = <&l4_ck>;
@@ -1068,7 +1068,7 @@
 		reg = <0x0210>;
 	};
 
-	mailboxes_ick: mailboxes_ick {
+	mailboxes_ick: mailboxes_ick@210 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -1076,7 +1076,7 @@
 		reg = <0x0210>;
 	};
 
-	wdt4_ick: wdt4_ick {
+	wdt4_ick: wdt4_ick@210 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -1084,7 +1084,7 @@
 		reg = <0x0210>;
 	};
 
-	wdt4_fck: wdt4_fck {
+	wdt4_fck: wdt4_fck@200 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&func_32k_ck>;
@@ -1092,7 +1092,7 @@
 		reg = <0x0200>;
 	};
 
-	mspro_ick: mspro_ick {
+	mspro_ick: mspro_ick@210 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -1100,7 +1100,7 @@
 		reg = <0x0210>;
 	};
 
-	mspro_fck: mspro_fck {
+	mspro_fck: mspro_fck@200 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&func_96m_ck>;
@@ -1108,7 +1108,7 @@
 		reg = <0x0200>;
 	};
 
-	fac_ick: fac_ick {
+	fac_ick: fac_ick@210 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -1116,7 +1116,7 @@
 		reg = <0x0210>;
 	};
 
-	fac_fck: fac_fck {
+	fac_fck: fac_fck@200 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&func_12m_ck>;
@@ -1124,7 +1124,7 @@
 		reg = <0x0200>;
 	};
 
-	hdq_ick: hdq_ick {
+	hdq_ick: hdq_ick@210 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -1132,7 +1132,7 @@
 		reg = <0x0210>;
 	};
 
-	hdq_fck: hdq_fck {
+	hdq_fck: hdq_fck@200 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&func_12m_ck>;
@@ -1140,7 +1140,7 @@
 		reg = <0x0200>;
 	};
 
-	i2c1_ick: i2c1_ick {
+	i2c1_ick: i2c1_ick@210 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -1148,7 +1148,7 @@
 		reg = <0x0210>;
 	};
 
-	i2c2_ick: i2c2_ick {
+	i2c2_ick: i2c2_ick@210 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -1156,7 +1156,7 @@
 		reg = <0x0210>;
 	};
 
-	gpmc_fck: gpmc_fck {
+	gpmc_fck: gpmc_fck@238 {
 		#clock-cells = <0>;
 		compatible = "ti,fixed-factor-clock";
 		clocks = <&core_l3_ck>;
@@ -1174,7 +1174,7 @@
 		clock-div = <1>;
 	};
 
-	sdma_ick: sdma_ick {
+	sdma_ick: sdma_ick@238 {
 		#clock-cells = <0>;
 		compatible = "ti,fixed-factor-clock";
 		clocks = <&core_l3_ck>;
@@ -1184,7 +1184,7 @@
 		ti,clock-mult = <1>;
 	};
 
-	sdrc_ick: sdrc_ick {
+	sdrc_ick: sdrc_ick@238 {
 		#clock-cells = <0>;
 		compatible = "ti,fixed-factor-clock";
 		clocks = <&core_l3_ck>;
@@ -1194,7 +1194,7 @@
 		ti,clock-mult = <1>;
 	};
 
-	des_ick: des_ick {
+	des_ick: des_ick@21c {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -1202,7 +1202,7 @@
 		reg = <0x021c>;
 	};
 
-	sha_ick: sha_ick {
+	sha_ick: sha_ick@21c {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -1210,7 +1210,7 @@
 		reg = <0x021c>;
 	};
 
-	rng_ick: rng_ick {
+	rng_ick: rng_ick@21c {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -1218,7 +1218,7 @@
 		reg = <0x021c>;
 	};
 
-	aes_ick: aes_ick {
+	aes_ick: aes_ick@21c {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -1226,7 +1226,7 @@
 		reg = <0x021c>;
 	};
 
-	pka_ick: pka_ick {
+	pka_ick: pka_ick@21c {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l4_ck>;
@@ -1234,7 +1234,7 @@
 		reg = <0x021c>;
 	};
 
-	usb_fck: usb_fck {
+	usb_fck: usb_fck@204 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&func_48m_ck>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/omap3430es1-clocks.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/omap3430es1-clocks.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/omap3430es1-clocks.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/omap3430es1-clocks.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -8,7 +8,7 @@
  * published by the Free Software Foundation.
  */
 &cm_clocks {
-	gfx_l3_ck: gfx_l3_ck {
+	gfx_l3_ck: gfx_l3_ck@b10 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&l3_ick>;
@@ -16,7 +16,7 @@
 		ti,bit-shift = <0>;
 	};
 
-	gfx_l3_fck: gfx_l3_fck {
+	gfx_l3_fck: gfx_l3_fck@b40 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&l3_ick>;
@@ -33,7 +33,7 @@
 		clock-div = <1>;
 	};
 
-	gfx_cg1_ck: gfx_cg1_ck {
+	gfx_cg1_ck: gfx_cg1_ck@b00 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&gfx_l3_fck>;
@@ -41,7 +41,7 @@
 		ti,bit-shift = <1>;
 	};
 
-	gfx_cg2_ck: gfx_cg2_ck {
+	gfx_cg2_ck: gfx_cg2_ck@b00 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&gfx_l3_fck>;
@@ -49,7 +49,7 @@
 		ti,bit-shift = <2>;
 	};
 
-	d2d_26m_fck: d2d_26m_fck {
+	d2d_26m_fck: d2d_26m_fck@a00 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&sys_ck>;
@@ -57,7 +57,7 @@
 		ti,bit-shift = <3>;
 	};
 
-	fshostusb_fck: fshostusb_fck {
+	fshostusb_fck: fshostusb_fck@a00 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&core_48m_fck>;
@@ -65,7 +65,7 @@
 		ti,bit-shift = <5>;
 	};
 
-	ssi_ssr_gate_fck_3430es1: ssi_ssr_gate_fck_3430es1 {
+	ssi_ssr_gate_fck_3430es1: ssi_ssr_gate_fck_3430es1@a00 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-no-wait-gate-clock";
 		clocks = <&corex2_fck>;
@@ -73,7 +73,7 @@
 		reg = <0x0a00>;
 	};
 
-	ssi_ssr_div_fck_3430es1: ssi_ssr_div_fck_3430es1 {
+	ssi_ssr_div_fck_3430es1: ssi_ssr_div_fck_3430es1@a40 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-divider-clock";
 		clocks = <&corex2_fck>;
@@ -96,7 +96,7 @@
 		clock-div = <2>;
 	};
 
-	hsotgusb_ick_3430es1: hsotgusb_ick_3430es1 {
+	hsotgusb_ick_3430es1: hsotgusb_ick_3430es1@a10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-no-wait-interface-clock";
 		clocks = <&core_l3_ick>;
@@ -104,7 +104,7 @@
 		ti,bit-shift = <4>;
 	};
 
-	fac_ick: fac_ick {
+	fac_ick: fac_ick@a10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&core_l4_ick>;
@@ -120,7 +120,7 @@
 		clock-div = <1>;
 	};
 
-	ssi_ick: ssi_ick_3430es1 {
+	ssi_ick: ssi_ick_3430es1@a10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-no-wait-interface-clock";
 		clocks = <&ssi_l4_ick>;
@@ -128,7 +128,7 @@
 		ti,bit-shift = <0>;
 	};
 
-	usb_l4_gate_ick: usb_l4_gate_ick {
+	usb_l4_gate_ick: usb_l4_gate_ick@a10 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-interface-clock";
 		clocks = <&l4_ick>;
@@ -136,7 +136,7 @@
 		reg = <0x0a10>;
 	};
 
-	usb_l4_div_ick: usb_l4_div_ick {
+	usb_l4_div_ick: usb_l4_div_ick@a40 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-divider-clock";
 		clocks = <&l4_ick>;
@@ -152,7 +152,7 @@
 		clocks = <&usb_l4_gate_ick>, <&usb_l4_div_ick>;
 	};
 
-	dss1_alwon_fck: dss1_alwon_fck_3430es1 {
+	dss1_alwon_fck: dss1_alwon_fck_3430es1@e00 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&dpll4_m4x2_ck>;
@@ -161,7 +161,7 @@
 		ti,set-rate-parent;
 	};
 
-	dss_ick: dss_ick_3430es1 {
+	dss_ick: dss_ick_3430es1@e10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-no-wait-interface-clock";
 		clocks = <&l4_ick>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/omap34xx.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/omap34xx.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/omap34xx.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/omap34xx.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -55,7 +55,7 @@
 			};
 		};
 
-		bandgap {
+		bandgap@48002524 {
 			reg = <0x48002524 0x4>;
 			compatible = "ti,omap34xx-bandgap";
 			#thermal-sensor-cells = <0>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/omap34xx-omap36xx-clocks.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/omap34xx-omap36xx-clocks.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/omap34xx-omap36xx-clocks.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/omap34xx-omap36xx-clocks.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -16,7 +16,7 @@
 		clock-div = <1>;
 	};
 
-	aes1_ick: aes1_ick {
+	aes1_ick: aes1_ick@a14 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&security_l4_ick2>;
@@ -24,7 +24,7 @@
 		reg = <0x0a14>;
 	};
 
-	rng_ick: rng_ick {
+	rng_ick: rng_ick@a14 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&security_l4_ick2>;
@@ -32,7 +32,7 @@
 		ti,bit-shift = <2>;
 	};
 
-	sha11_ick: sha11_ick {
+	sha11_ick: sha11_ick@a14 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&security_l4_ick2>;
@@ -40,7 +40,7 @@
 		ti,bit-shift = <1>;
 	};
 
-	des1_ick: des1_ick {
+	des1_ick: des1_ick@a14 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&security_l4_ick2>;
@@ -48,7 +48,7 @@
 		ti,bit-shift = <0>;
 	};
 
-	cam_mclk: cam_mclk {
+	cam_mclk: cam_mclk@f00 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&dpll4_m5x2_ck>;
@@ -57,7 +57,7 @@
 		ti,set-rate-parent;
 	};
 
-	cam_ick: cam_ick {
+	cam_ick: cam_ick@f10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-no-wait-interface-clock";
 		clocks = <&l4_ick>;
@@ -65,7 +65,7 @@
 		ti,bit-shift = <0>;
 	};
 
-	csi2_96m_fck: csi2_96m_fck {
+	csi2_96m_fck: csi2_96m_fck@f00 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&core_96m_fck>;
@@ -81,7 +81,7 @@
 		clock-div = <1>;
 	};
 
-	pka_ick: pka_ick {
+	pka_ick: pka_ick@a14 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&security_l3_ick>;
@@ -89,7 +89,7 @@
 		ti,bit-shift = <4>;
 	};
 
-	icr_ick: icr_ick {
+	icr_ick: icr_ick@a10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&core_l4_ick>;
@@ -97,7 +97,7 @@
 		ti,bit-shift = <29>;
 	};
 
-	des2_ick: des2_ick {
+	des2_ick: des2_ick@a10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&core_l4_ick>;
@@ -105,7 +105,7 @@
 		ti,bit-shift = <26>;
 	};
 
-	mspro_ick: mspro_ick {
+	mspro_ick: mspro_ick@a10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&core_l4_ick>;
@@ -113,7 +113,7 @@
 		ti,bit-shift = <23>;
 	};
 
-	mailboxes_ick: mailboxes_ick {
+	mailboxes_ick: mailboxes_ick@a10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&core_l4_ick>;
@@ -129,7 +129,7 @@
 		clock-div = <1>;
 	};
 
-	sr1_fck: sr1_fck {
+	sr1_fck: sr1_fck@c00 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&sys_ck>;
@@ -137,7 +137,7 @@
 		ti,bit-shift = <6>;
 	};
 
-	sr2_fck: sr2_fck {
+	sr2_fck: sr2_fck@c00 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&sys_ck>;
@@ -153,7 +153,7 @@
 		clock-div = <1>;
 	};
 
-	dpll2_fck: dpll2_fck {
+	dpll2_fck: dpll2_fck@40 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&core_ck>;
@@ -163,7 +163,7 @@
 		ti,index-starts-at-one;
 	};
 
-	dpll2_ck: dpll2_ck {
+	dpll2_ck: dpll2_ck@4 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-dpll-clock";
 		clocks = <&sys_ck>, <&dpll2_fck>;
@@ -173,7 +173,7 @@
 		ti,low-power-bypass;
 	};
 
-	dpll2_m2_ck: dpll2_m2_ck {
+	dpll2_m2_ck: dpll2_m2_ck@44 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll2_ck>;
@@ -182,7 +182,7 @@
 		ti,index-starts-at-one;
 	};
 
-	iva2_ck: iva2_ck {
+	iva2_ck: iva2_ck@0 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&dpll2_m2_ck>;
@@ -190,7 +190,7 @@
 		ti,bit-shift = <0>;
 	};
 
-	modem_fck: modem_fck {
+	modem_fck: modem_fck@a00 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&sys_ck>;
@@ -198,7 +198,7 @@
 		ti,bit-shift = <31>;
 	};
 
-	sad2d_ick: sad2d_ick {
+	sad2d_ick: sad2d_ick@a10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l3_ick>;
@@ -206,7 +206,7 @@
 		ti,bit-shift = <3>;
 	};
 
-	mad2d_ick: mad2d_ick {
+	mad2d_ick: mad2d_ick@a18 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&l3_ick>;
@@ -214,7 +214,7 @@
 		ti,bit-shift = <3>;
 	};
 
-	mspro_fck: mspro_fck {
+	mspro_fck: mspro_fck@a00 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&core_96m_fck>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/omap36xx-am35xx-omap3430es2plus-clocks.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -25,7 +25,7 @@
 	};
 };
 &cm_clocks {
-	dpll5_ck: dpll5_ck {
+	dpll5_ck: dpll5_ck@d04 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-dpll-clock";
 		clocks = <&sys_ck>, <&sys_ck>;
@@ -34,7 +34,7 @@
 		ti,lock;
 	};
 
-	dpll5_m2_ck: dpll5_m2_ck {
+	dpll5_m2_ck: dpll5_m2_ck@d50 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll5_ck>;
@@ -43,7 +43,7 @@
 		ti,index-starts-at-one;
 	};
 
-	sgx_gate_fck: sgx_gate_fck {
+	sgx_gate_fck: sgx_gate_fck@b00 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&core_ck>;
@@ -91,7 +91,7 @@
 		clock-div = <2>;
 	};
 
-	sgx_mux_fck: sgx_mux_fck {
+	sgx_mux_fck: sgx_mux_fck@b40 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&core_d3_ck>, <&core_d4_ck>, <&core_d6_ck>, <&cm_96m_fck>, <&omap_192m_alwon_fck>, <&core_d2_ck>, <&corex2_d3_fck>, <&corex2_d5_fck>;
@@ -104,7 +104,7 @@
 		clocks = <&sgx_gate_fck>, <&sgx_mux_fck>;
 	};
 
-	sgx_ick: sgx_ick {
+	sgx_ick: sgx_ick@b10 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&l3_ick>;
@@ -112,7 +112,7 @@
 		ti,bit-shift = <0>;
 	};
 
-	cpefuse_fck: cpefuse_fck {
+	cpefuse_fck: cpefuse_fck@a08 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_ck>;
@@ -120,7 +120,7 @@
 		ti,bit-shift = <0>;
 	};
 
-	ts_fck: ts_fck {
+	ts_fck: ts_fck@a08 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&omap_32k_fck>;
@@ -128,7 +128,7 @@
 		ti,bit-shift = <1>;
 	};
 
-	usbtll_fck: usbtll_fck {
+	usbtll_fck: usbtll_fck@a08 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&dpll5_m2_ck>;
@@ -136,7 +136,7 @@
 		ti,bit-shift = <2>;
 	};
 
-	usbtll_ick: usbtll_ick {
+	usbtll_ick: usbtll_ick@a18 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&core_l4_ick>;
@@ -144,7 +144,7 @@
 		ti,bit-shift = <2>;
 	};
 
-	mmchs3_ick: mmchs3_ick {
+	mmchs3_ick: mmchs3_ick@a10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&core_l4_ick>;
@@ -152,7 +152,7 @@
 		ti,bit-shift = <30>;
 	};
 
-	mmchs3_fck: mmchs3_fck {
+	mmchs3_fck: mmchs3_fck@a00 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&core_96m_fck>;
@@ -160,7 +160,7 @@
 		ti,bit-shift = <30>;
 	};
 
-	dss1_alwon_fck: dss1_alwon_fck_3430es2 {
+	dss1_alwon_fck: dss1_alwon_fck_3430es2@e00 {
 		#clock-cells = <0>;
 		compatible = "ti,dss-gate-clock";
 		clocks = <&dpll4_m4x2_ck>;
@@ -169,7 +169,7 @@
 		ti,set-rate-parent;
 	};
 
-	dss_ick: dss_ick_3430es2 {
+	dss_ick: dss_ick_3430es2@e10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-dss-interface-clock";
 		clocks = <&l4_ick>;
@@ -177,7 +177,7 @@
 		ti,bit-shift = <0>;
 	};
 
-	usbhost_120m_fck: usbhost_120m_fck {
+	usbhost_120m_fck: usbhost_120m_fck@1400 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&dpll5_m2_ck>;
@@ -185,7 +185,7 @@
 		ti,bit-shift = <1>;
 	};
 
-	usbhost_48m_fck: usbhost_48m_fck {
+	usbhost_48m_fck: usbhost_48m_fck@1400 {
 		#clock-cells = <0>;
 		compatible = "ti,dss-gate-clock";
 		clocks = <&omap_48m_fck>;
@@ -193,7 +193,7 @@
 		ti,bit-shift = <0>;
 	};
 
-	usbhost_ick: usbhost_ick {
+	usbhost_ick: usbhost_ick@1410 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-dss-interface-clock";
 		clocks = <&l4_ick>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/omap36xx-clocks.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/omap36xx-clocks.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/omap36xx-clocks.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/omap36xx-clocks.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -8,14 +8,14 @@
  * published by the Free Software Foundation.
  */
 &cm_clocks {
-	dpll4_ck: dpll4_ck {
+	dpll4_ck: dpll4_ck@d00 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-dpll-per-j-type-clock";
 		clocks = <&sys_ck>, <&sys_ck>;
 		reg = <0x0d00>, <0x0d20>, <0x0d44>, <0x0d30>;
 	};
 
-	dpll4_m5x2_ck: dpll4_m5x2_ck {
+	dpll4_m5x2_ck: dpll4_m5x2_ck@d00 {
 		#clock-cells = <0>;
 		compatible = "ti,hsdiv-gate-clock";
 		clocks = <&dpll4_m5x2_mul_ck>;
@@ -25,7 +25,7 @@
 		ti,set-bit-to-disable;
 	};
 
-	dpll4_m2x2_ck: dpll4_m2x2_ck {
+	dpll4_m2x2_ck: dpll4_m2x2_ck@d00 {
 		#clock-cells = <0>;
 		compatible = "ti,hsdiv-gate-clock";
 		clocks = <&dpll4_m2x2_mul_ck>;
@@ -34,7 +34,7 @@
 		ti,set-bit-to-disable;
 	};
 
-	dpll3_m3x2_ck: dpll3_m3x2_ck {
+	dpll3_m3x2_ck: dpll3_m3x2_ck@d00 {
 		#clock-cells = <0>;
 		compatible = "ti,hsdiv-gate-clock";
 		clocks = <&dpll3_m3x2_mul_ck>;
@@ -43,7 +43,7 @@
 		ti,set-bit-to-disable;
 	};
 
-	dpll4_m3x2_ck: dpll4_m3x2_ck {
+	dpll4_m3x2_ck: dpll4_m3x2_ck@d00 {
 		#clock-cells = <0>;
 		compatible = "ti,hsdiv-gate-clock";
 		clocks = <&dpll4_m3x2_mul_ck>;
@@ -52,7 +52,7 @@
 		ti,set-bit-to-disable;
 	};
 
-	dpll4_m6x2_ck: dpll4_m6x2_ck {
+	dpll4_m6x2_ck: dpll4_m6x2_ck@d00 {
 		#clock-cells = <0>;
 		compatible = "ti,hsdiv-gate-clock";
 		clocks = <&dpll4_m6x2_mul_ck>;
@@ -61,7 +61,7 @@
 		ti,set-bit-to-disable;
 	};
 
-	uart4_fck: uart4_fck {
+	uart4_fck: uart4_fck@1000 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&per_48m_fck>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/omap36xx.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/omap36xx.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/omap36xx.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/omap36xx.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -44,7 +44,7 @@
 		abb_mpu_iva: regulator-abb-mpu {
 			compatible = "ti,abb-v1";
 			regulator-name = "abb_mpu_iva";
-			#address-cell = <0>;
+			#address-cells = <0>;
 			#size-cells = <0>;
 			reg = <0x483072f0 0x8>, <0x48306818 0x4>;
 			reg-names = "base-address", "int-address";
@@ -87,7 +87,7 @@
 			};
 		};
 
-		bandgap {
+		bandgap@48002524 {
 			reg = <0x48002524 0x4>;
 			compatible = "ti,omap36xx-bandgap";
 			#thermal-sensor-cells = <0>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/omap36xx-omap3430es2plus-clocks.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/omap36xx-omap3430es2plus-clocks.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/omap36xx-omap3430es2plus-clocks.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/omap36xx-omap3430es2plus-clocks.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -8,7 +8,7 @@
  * published by the Free Software Foundation.
  */
 &cm_clocks {
-	ssi_ssr_gate_fck_3430es2: ssi_ssr_gate_fck_3430es2 {
+	ssi_ssr_gate_fck_3430es2: ssi_ssr_gate_fck_3430es2@a00 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-no-wait-gate-clock";
 		clocks = <&corex2_fck>;
@@ -16,7 +16,7 @@
 		reg = <0x0a00>;
 	};
 
-	ssi_ssr_div_fck_3430es2: ssi_ssr_div_fck_3430es2 {
+	ssi_ssr_div_fck_3430es2: ssi_ssr_div_fck_3430es2@a40 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-divider-clock";
 		clocks = <&corex2_fck>;
@@ -39,7 +39,7 @@
 		clock-div = <2>;
 	};
 
-	hsotgusb_ick_3430es2: hsotgusb_ick_3430es2 {
+	hsotgusb_ick_3430es2: hsotgusb_ick_3430es2@a10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-hsotgusb-interface-clock";
 		clocks = <&core_l3_ick>;
@@ -55,7 +55,7 @@
 		clock-div = <1>;
 	};
 
-	ssi_ick: ssi_ick_3430es2 {
+	ssi_ick: ssi_ick_3430es2@a10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-ssi-interface-clock";
 		clocks = <&ssi_l4_ick>;
@@ -63,7 +63,7 @@
 		ti,bit-shift = <0>;
 	};
 
-	usim_gate_fck: usim_gate_fck {
+	usim_gate_fck: usim_gate_fck@c00 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&omap_96m_fck>;
@@ -143,7 +143,7 @@
 		clock-div = <20>;
 	};
 
-	usim_mux_fck: usim_mux_fck {
+	usim_mux_fck: usim_mux_fck@c40 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&sys_ck>, <&sys_d2_ck>, <&omap_96m_d2_fck>, <&omap_96m_d4_fck>, <&omap_96m_d8_fck>, <&omap_96m_d10_fck>, <&dpll5_m2_d4_ck>, <&dpll5_m2_d8_ck>, <&dpll5_m2_d16_ck>, <&dpll5_m2_d20_ck>;
@@ -158,7 +158,7 @@
 		clocks = <&usim_gate_fck>, <&usim_mux_fck>;
 	};
 
-	usim_ick: usim_ick {
+	usim_ick: usim_ick@c10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&wkup_l4_ick>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/omap3-beagle.dts linux-libre-4.7-gnu/arch/arm/boot/dts/omap3-beagle.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/omap3-beagle.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/omap3-beagle.dts	2016-07-24 15:23:50.000000000 -0400
@@ -390,6 +390,7 @@
 		interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
 			     <1 IRQ_TYPE_NONE>;	/* termcount */
 		ti,nand-ecc-opt = "ham1";
+		rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */
 		nand-bus-width = <16>;
 		#address-cells = <1>;
 		#size-cells = <1>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/omap3.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/omap3.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/omap3.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/omap3.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -43,7 +43,7 @@
 		};
 	};
 
-	pmu {
+	pmu@54000000 {
 		compatible = "arm,cortex-a8-pmu";
 		reg = <0x54000000 0x800000>;
 		interrupts = <3>;
@@ -119,7 +119,7 @@
 					#size-cells = <1>;
 					ranges = <0 0x270 0x330>;
 
-					pbias_regulator: pbias_regulator {
+					pbias_regulator: pbias_regulator@2b0 {
 						compatible = "ti,pbias-omap3", "ti,pbias-omap";
 						reg = <0x2b0 0x4>;
 						syscon = <&scm_conf>;
@@ -725,6 +725,8 @@
 			#size-cells = <1>;
 			interrupt-controller;
 			#interrupt-cells = <2>;
+			gpio-controller;
+			#gpio-cells = <2>;
 		};
 
 		usb_otg_hs: usb_otg_hs@480ab000 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/omap3-evm-37xx.dts linux-libre-4.7-gnu/arch/arm/boot/dts/omap3-evm-37xx.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/omap3-evm-37xx.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/omap3-evm-37xx.dts	2016-07-24 15:23:50.000000000 -0400
@@ -85,7 +85,7 @@
 			OMAP3_CORE1_IOPAD(0x2158, PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc2_clk.sdmmc2_clk */
 			OMAP3_CORE1_IOPAD(0x215a, PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc2_cmd.sdmmc2_cmd */
 			OMAP3_CORE1_IOPAD(0x215c, PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc2_dat0.sdmmc2_dat0 */
-			OMAP3_CORE1_IOPAD(0x215e, WAKEUP_EN | PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat1.sdmmc2_dat1 */
+			OMAP3_CORE1_IOPAD(0x215e, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat1.sdmmc2_dat1 */
 			OMAP3_CORE1_IOPAD(0x2160, PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc2_dat2.sdmmc2_dat2 */
 			OMAP3_CORE1_IOPAD(0x2162, PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc2_dat3.sdmmc2_dat3 */
 		>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/omap3-igep0020-common.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/omap3-igep0020-common.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/omap3-igep0020-common.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/omap3-igep0020-common.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -194,6 +194,12 @@
 			OMAP3630_CORE2_IOPAD(0x25f8, PIN_OUTPUT | MUX_MODE4) /* etk_d14.gpio_28 */
 		>;
 	};
+
+	mmc1_wp_pins: pinmux_mmc1_cd_pins {
+		pinctrl-single,pins = <
+			OMAP3630_CORE2_IOPAD(0x25fa, PIN_INPUT | MUX_MODE4)   /* etk_d15.gpio_29 */
+		>;
+	};
 };
 
 &i2c3 {
@@ -250,3 +256,8 @@
 		};
 	};
 };
+
+&mmc1 {
+	pinctrl-0 = <&mmc1_pins &mmc1_wp_pins>;
+	wp-gpios = <&gpio1 29 GPIO_ACTIVE_LOW>;	/* gpio_29 */
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/omap3-igep.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/omap3-igep.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/omap3-igep.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/omap3-igep.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -188,6 +188,7 @@
 	vmmc-supply = <&vmmc1>;
 	vmmc_aux-supply = <&vsim>;
 	bus-width = <4>;
+	cd-gpios = <&twl_gpio 0 GPIO_ACTIVE_LOW>;
 };
 
 &mmc3 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/omap3-n900.dts linux-libre-4.7-gnu/arch/arm/boot/dts/omap3-n900.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/omap3-n900.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/omap3-n900.dts	2016-07-24 15:23:50.000000000 -0400
@@ -288,7 +288,7 @@
 		pinctrl-single,pins = <
 			OMAP3_CORE1_IOPAD(0x2180, PIN_INPUT_PULLUP | MUX_MODE1)	/* ssi1_rdy_tx */
 			OMAP3_CORE1_IOPAD(0x217e, PIN_OUTPUT | MUX_MODE1)		/* ssi1_flag_tx */
-			OMAP3_CORE1_IOPAD(0x2182, PIN_INPUT | WAKEUP_EN | MUX_MODE4) /* ssi1_wake_tx (cawake) */
+			OMAP3_CORE1_IOPAD(0x2182, PIN_INPUT | MUX_MODE4)		/* ssi1_wake_tx (cawake) */
 			OMAP3_CORE1_IOPAD(0x217c, PIN_OUTPUT | MUX_MODE1)		/* ssi1_dat_tx */
 			OMAP3_CORE1_IOPAD(0x2184, PIN_INPUT | MUX_MODE1)		/* ssi1_dat_rx */
 			OMAP3_CORE1_IOPAD(0x2186, PIN_INPUT | MUX_MODE1)		/* ssi1_flag_rx */
@@ -300,7 +300,7 @@
 	modem_pins: pinmux_modem {
 		pinctrl-single,pins = <
 			OMAP3_CORE1_IOPAD(0x20dc, PIN_OUTPUT | MUX_MODE4)		/* gpio 70 => cmt_apeslpx */
-			OMAP3_CORE1_IOPAD(0x20e0, PIN_INPUT | WAKEUP_EN | MUX_MODE4) /* gpio 72 => ape_rst_rq */
+			OMAP3_CORE1_IOPAD(0x20e0, PIN_INPUT | MUX_MODE4)		/* gpio 72 => ape_rst_rq */
 			OMAP3_CORE1_IOPAD(0x20e2, PIN_OUTPUT | MUX_MODE4)		/* gpio 73 => cmt_rst_rq */
 			OMAP3_CORE1_IOPAD(0x20e4, PIN_OUTPUT | MUX_MODE4)		/* gpio 74 => cmt_en */
 			OMAP3_CORE1_IOPAD(0x20e6, PIN_OUTPUT | MUX_MODE4)		/* gpio 75 => cmt_rst */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/omap3-n950.dts linux-libre-4.7-gnu/arch/arm/boot/dts/omap3-n950.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/omap3-n950.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/omap3-n950.dts	2016-07-24 15:23:50.000000000 -0400
@@ -11,10 +11,33 @@
 /dts-v1/;
 
 #include "omap3-n950-n9.dtsi"
+#include <dt-bindings/input/input.h>
 
 / {
 	model = "Nokia N950";
 	compatible = "nokia,omap3-n950", "ti,omap36xx", "ti,omap3";
+
+	keys {
+		compatible = "gpio-keys";
+
+		keypad_slide {
+			label = "Keypad Slide";
+			gpios = <&gpio4 13 GPIO_ACTIVE_LOW>; /* 109 */
+			linux,input-type = <EV_SW>;
+			linux,code = <SW_KEYPAD_SLIDE>;
+			wakeup-source;
+			pinctrl-names = "default";
+			pinctrl-0 = <&keypad_slide_pins>;
+		};
+	};
+};
+
+&omap3_pmx_core {
+	keypad_slide_pins: pinmux_debug_led_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x212a, PIN_INPUT | MUX_MODE4)       /* cam_d10.gpio_109 */
+		>;
+	};
 };
 
 &omap3_pmx_core {
@@ -86,3 +109,79 @@
 &modem {
 	compatible = "nokia,n950-modem";
 };
+
+&twl {
+	twl_audio: audio {
+		compatible = "ti,twl4030-audio";
+		ti,enable-vibra = <1>;
+	};
+};
+
+&twl_keypad {
+	linux,keymap = < MATRIX_KEY(0x00, 0x00, KEY_BACKSLASH)
+			 MATRIX_KEY(0x01, 0x00, KEY_LEFTSHIFT)
+			 MATRIX_KEY(0x02, 0x00, KEY_COMPOSE)
+			 MATRIX_KEY(0x03, 0x00, KEY_LEFTMETA)
+			 MATRIX_KEY(0x04, 0x00, KEY_RIGHTCTRL)
+			 MATRIX_KEY(0x05, 0x00, KEY_BACKSPACE)
+			 MATRIX_KEY(0x06, 0x00, KEY_VOLUMEDOWN)
+			 MATRIX_KEY(0x07, 0x00, KEY_VOLUMEUP)
+
+			 MATRIX_KEY(0x03, 0x01, KEY_Z)
+			 MATRIX_KEY(0x04, 0x01, KEY_A)
+			 MATRIX_KEY(0x05, 0x01, KEY_Q)
+			 MATRIX_KEY(0x06, 0x01, KEY_W)
+			 MATRIX_KEY(0x07, 0x01, KEY_E)
+
+			 MATRIX_KEY(0x03, 0x02, KEY_X)
+			 MATRIX_KEY(0x04, 0x02, KEY_S)
+			 MATRIX_KEY(0x05, 0x02, KEY_D)
+			 MATRIX_KEY(0x06, 0x02, KEY_C)
+			 MATRIX_KEY(0x07, 0x02, KEY_V)
+
+			 MATRIX_KEY(0x03, 0x03, KEY_O)
+			 MATRIX_KEY(0x04, 0x03, KEY_I)
+			 MATRIX_KEY(0x05, 0x03, KEY_U)
+			 MATRIX_KEY(0x06, 0x03, KEY_L)
+			 MATRIX_KEY(0x07, 0x03, KEY_APOSTROPHE)
+
+			 MATRIX_KEY(0x03, 0x04, KEY_Y)
+			 MATRIX_KEY(0x04, 0x04, KEY_K)
+			 MATRIX_KEY(0x05, 0x04, KEY_J)
+			 MATRIX_KEY(0x06, 0x04, KEY_H)
+			 MATRIX_KEY(0x07, 0x04, KEY_G)
+
+			 MATRIX_KEY(0x03, 0x05, KEY_B)
+			 MATRIX_KEY(0x04, 0x05, KEY_COMMA)
+			 MATRIX_KEY(0x05, 0x05, KEY_M)
+			 MATRIX_KEY(0x06, 0x05, KEY_N)
+			 MATRIX_KEY(0x07, 0x05, KEY_DOT)
+
+			 MATRIX_KEY(0x00, 0x06, KEY_SPACE)
+			 MATRIX_KEY(0x03, 0x06, KEY_T)
+			 MATRIX_KEY(0x04, 0x06, KEY_UP)
+			 MATRIX_KEY(0x05, 0x06, KEY_LEFT)
+			 MATRIX_KEY(0x06, 0x06, KEY_RIGHT)
+			 MATRIX_KEY(0x07, 0x06, KEY_DOWN)
+
+			 MATRIX_KEY(0x03, 0x07, KEY_P)
+			 MATRIX_KEY(0x04, 0x07, KEY_ENTER)
+			 MATRIX_KEY(0x05, 0x07, KEY_SLASH)
+			 MATRIX_KEY(0x06, 0x07, KEY_F)
+			 MATRIX_KEY(0x07, 0x07, KEY_R)
+			 >;
+};
+
+&lis302 {
+	st,axis-x = <(-2)>; /* LIS3_INV_DEV_Y */
+	st,axis-y = <(-1)>; /* LIS3_INV_DEV_X */
+	st,axis-z = <(-3)>; /* LIS3_INV_DEV_Z */
+
+	st,min-limit-x = <(-32)>;
+	st,min-limit-y = <3>;
+	st,min-limit-z = <3>;
+
+	st,max-limit-x = <(-3)>;
+	st,max-limit-y = <32>;
+	st,max-limit-z = <32>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/omap3-n950-n9.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/omap3-n950-n9.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/omap3-n950-n9.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/omap3-n950-n9.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -14,6 +14,13 @@
 	cpus {
 		cpu@0 {
 			cpu0-supply = <&vcc>;
+			operating-points = <
+				/* kHz    uV */
+				300000  1012500
+				600000  1200000
+				800000  1325000
+				1000000	1375000
+			>;
 		};
 	};
 
@@ -39,9 +46,34 @@
 		enable-active-high;
 		regulator-boot-off;
 	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		heartbeat {
+			label = "debug::sleep";
+			gpios = <&gpio3 28 GPIO_ACTIVE_HIGH>;  /* gpio92 */
+			linux,default-trigger = "default-on";
+			pinctrl-names = "default";
+			pinctrl-0 = <&debug_leds>;
+		};
+	};
 };
 
 &omap3_pmx_core {
+	accelerator_pins: pinmux_accelerator_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x21da, PIN_INPUT | MUX_MODE4)	/* mcspi2_somi.gpio_180 -> LIS302 INT1 */
+			OMAP3_CORE1_IOPAD(0x21dc, PIN_INPUT | MUX_MODE4)	/* mcspi2_cs0.gpio_181 -> LIS302 INT2 */
+		>;
+	};
+
+	debug_leds: pinmux_debug_led_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x2108, PIN_OUTPUT | MUX_MODE4)       /* dss_data22.gpio_92 */
+		>;
+	};
+
 	mmc2_pins: pinmux_mmc2_pins {
 		pinctrl-single,pins = <
 			OMAP3_CORE1_IOPAD(0x2158, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_clk */
@@ -65,7 +97,7 @@
 			OMAP3_CORE1_IOPAD(0x217c, PIN_OUTPUT | MUX_MODE1)            /* ssi1_dat_tx */
 			OMAP3_CORE1_IOPAD(0x217e, PIN_OUTPUT | MUX_MODE1)            /* ssi1_flag_tx */
 			OMAP3_CORE1_IOPAD(0x2180, PIN_INPUT_PULLUP | MUX_MODE1)      /* ssi1_rdy_tx */
-			OMAP3_CORE1_IOPAD(0x2182, PIN_INPUT | WAKEUP_EN | MUX_MODE4) /* ssi1_wake_tx (cawake) */
+			OMAP3_CORE1_IOPAD(0x2182, PIN_INPUT | MUX_MODE4)	/* ssi1_wake_tx (cawake) */
 			OMAP3_CORE1_IOPAD(0x2184, PIN_INPUT | MUX_MODE1)             /* ssi1_dat_rx */
 			OMAP3_CORE1_IOPAD(0x2186, PIN_INPUT | MUX_MODE1)             /* ssi1_flag_rx */
 			OMAP3_CORE1_IOPAD(0x2188, PIN_OUTPUT | MUX_MODE1)            /* ssi1_rdy_rx */
@@ -78,7 +110,7 @@
 			OMAP3_CORE1_IOPAD(0x217c, PIN_OUTPUT | MUX_MODE7)            /* ssi1_dat_tx */
 			OMAP3_CORE1_IOPAD(0x217e, PIN_OUTPUT | MUX_MODE7)            /* ssi1_flag_tx */
 			OMAP3_CORE1_IOPAD(0x2180, PIN_INPUT_PULLDOWN | MUX_MODE7)    /* ssi1_rdy_tx */
-			OMAP3_CORE1_IOPAD(0x2182, PIN_INPUT | WAKEUP_EN | MUX_MODE4) /* ssi1_wake_tx (cawake) */
+			OMAP3_CORE1_IOPAD(0x2182, PIN_INPUT | MUX_MODE4)	/* ssi1_wake_tx (cawake) */
 			OMAP3_CORE1_IOPAD(0x2184, PIN_INPUT | MUX_MODE7)             /* ssi1_dat_rx */
 			OMAP3_CORE1_IOPAD(0x2186, PIN_INPUT | MUX_MODE7)             /* ssi1_flag_rx */
 			OMAP3_CORE1_IOPAD(0x2188, PIN_OUTPUT | MUX_MODE4)            /* ssi1_rdy_rx */
@@ -88,7 +120,7 @@
 
 	modem_pins1: pinmux_modem_core1_pins {
 		pinctrl-single,pins = <
-			OMAP3_CORE1_IOPAD(0x207a, PIN_INPUT | WAKEUP_EN | MUX_MODE4) /* gpio_34 (ape_rst_rq) */
+			OMAP3_CORE1_IOPAD(0x207a, PIN_INPUT | MUX_MODE4)	/* gpio_34 (ape_rst_rq) */
 			OMAP3_CORE1_IOPAD(0x2100, PIN_OUTPUT | MUX_MODE4)            /* gpio_88 (cmt_rst_rq) */
 			OMAP3_CORE1_IOPAD(0x210a, PIN_OUTPUT | MUX_MODE4)            /* gpio_93 (cmt_apeslpx) */
 		>;
@@ -129,6 +161,30 @@
 	ti,pulldowns	= <0x008106>; /* BIT(1) | BIT(2) | BIT(8) | BIT(15) */
 };
 
+&vdac {
+	regulator-name = "vdac";
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+};
+
+&vpll1 {
+	regulator-name = "vpll1";
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+};
+
+&vpll2 {
+	regulator-name = "vpll2";
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+};
+
+&vaux1 {
+	regulator-name = "vaux1";
+	regulator-min-microvolt = <2800000>;
+	regulator-max-microvolt = <2800000>;
+};
+
 /* CSI-2 receiver */
 &vaux2 {
 	regulator-name = "vaux2";
@@ -143,12 +199,107 @@
 	regulator-max-microvolt = <2800000>;
 };
 
+&vaux4 {
+	regulator-name = "vaux4";
+	regulator-min-microvolt = <2800000>;
+	regulator-max-microvolt = <2800000>;
+};
+
+&vmmc1 {
+	regulator-name = "vmmc1";
+	regulator-min-microvolt = <1850000>;
+	regulator-max-microvolt = <3150000>;
+};
+
+&vmmc2 {
+	regulator-name = "vmmc2";
+	regulator-min-microvolt = <3000000>;
+	regulator-max-microvolt = <3000000>;
+};
+
+&vintana1 {
+	regulator-name = "vintana1";
+	regulator-min-microvolt = <1500000>;
+	regulator-max-microvolt = <1500000>;
+};
+
+&vintana2 {
+	regulator-name = "vintana2";
+	regulator-min-microvolt = <2750000>;
+	regulator-max-microvolt = <2750000>;
+};
+
+&vintdig {
+	regulator-name = "vintdig";
+	regulator-min-microvolt = <1500000>;
+	regulator-max-microvolt = <1500000>;
+};
+
+&vsim {
+	regulator-name = "vsim";
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+};
+
+&vio {
+	regulator-name = "vio";
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+};
+
 &i2c2 {
 	clock-frequency = <400000>;
 };
 
 &i2c3 {
 	clock-frequency = <400000>;
+
+	lis302: lis302@1d {
+		compatible = "st,lis3lv02d";
+		reg = <0x1d>;
+
+		Vdd-supply = <&vaux1>;
+		Vdd_IO-supply = <&vio>;
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&accelerator_pins>;
+
+                interrupts-extended = <&gpio6 20 IRQ_TYPE_EDGE_FALLING>, <&gpio6 21 IRQ_TYPE_EDGE_FALLING>; /* 180, 181 */
+
+		/* click flags */
+		st,click-single-x;
+		st,click-single-y;
+		st,click-single-z;
+
+		/* Limits are 0.5g * value */
+		st,click-threshold-x = <8>;
+		st,click-threshold-y = <8>;
+		st,click-threshold-z = <10>;
+
+		/* Click must be longer than time limit */
+		st,click-time-limit = <9>;
+
+		/* Kind of debounce filter */
+		st,click-latency = <50>;
+
+		st,wakeup-x-hi;
+		st,wakeup-y-hi;
+		st,wakeup-threshold = <(800/18)>; /* millig-value / 18 to get HW values */
+
+		st,wakeup2-z-hi;
+		st,wakeup2-threshold = <(1000/18)>; /* millig-value / 18 to get HW values */
+
+		st,highpass-cutoff-hz = <2>;
+
+		/* Interrupt line 1 for thresholds */
+		st,irq1-ff-wu-1;
+		st,irq1-ff-wu-2;
+		/* Interrupt line 2 for click detection */
+		st,irq2-click;
+
+		st,wu-duration-1 = <8>;
+		st,wu-duration-2 = <8>;
+	};
 };
 
 &mmc1 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/omap3-n9.dts linux-libre-4.7-gnu/arch/arm/boot/dts/omap3-n9.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/omap3-n9.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/omap3-n9.dts	2016-07-24 15:23:50.000000000 -0400
@@ -57,3 +57,17 @@
 &modem {
 	compatible = "nokia,n9-modem";
 };
+
+&lis302 {
+	st,axis-x = <1>;    /* LIS3_DEV_X */
+	st,axis-y = <(-2)>; /* LIS3_INV_DEV_Y */
+	st,axis-z = <(-3)>; /* LIS3_INV_DEV_Z */
+
+	st,min-limit-x = <(-46)>;
+	st,min-limit-y = <3>;
+	st,min-limit-z = <3>;
+
+	st,max-limit-x = <(-3)>;
+	st,max-limit-y = <46>;
+	st,max-limit-z = <46>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/omap3xxx-clocks.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/omap3xxx-clocks.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/omap3xxx-clocks.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/omap3xxx-clocks.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -14,14 +14,14 @@
 		clock-frequency = <16800000>;
 	};
 
-	osc_sys_ck: osc_sys_ck {
+	osc_sys_ck: osc_sys_ck@d40 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&virt_12m_ck>, <&virt_13m_ck>, <&virt_19200000_ck>, <&virt_26000000_ck>, <&virt_38_4m_ck>, <&virt_16_8m_ck>;
 		reg = <0x0d40>;
 	};
 
-	sys_ck: sys_ck {
+	sys_ck: sys_ck@1270 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&osc_sys_ck>;
@@ -31,7 +31,7 @@
 		ti,index-starts-at-one;
 	};
 
-	sys_clkout1: sys_clkout1 {
+	sys_clkout1: sys_clkout1@d70 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&osc_sys_ck>;
@@ -81,7 +81,7 @@
 };
 
 &scm_clocks {
-	mcbsp5_mux_fck: mcbsp5_mux_fck {
+	mcbsp5_mux_fck: mcbsp5_mux_fck@68 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&core_96m_fck>, <&mcbsp_clks>;
@@ -95,7 +95,7 @@
 		clocks = <&mcbsp5_gate_fck>, <&mcbsp5_mux_fck>;
 	};
 
-	mcbsp1_mux_fck: mcbsp1_mux_fck {
+	mcbsp1_mux_fck: mcbsp1_mux_fck@4 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&core_96m_fck>, <&mcbsp_clks>;
@@ -109,7 +109,7 @@
 		clocks = <&mcbsp1_gate_fck>, <&mcbsp1_mux_fck>;
 	};
 
-	mcbsp2_mux_fck: mcbsp2_mux_fck {
+	mcbsp2_mux_fck: mcbsp2_mux_fck@4 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&per_96m_fck>, <&mcbsp_clks>;
@@ -123,7 +123,7 @@
 		clocks = <&mcbsp2_gate_fck>, <&mcbsp2_mux_fck>;
 	};
 
-	mcbsp3_mux_fck: mcbsp3_mux_fck {
+	mcbsp3_mux_fck: mcbsp3_mux_fck@68 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&per_96m_fck>, <&mcbsp_clks>;
@@ -136,7 +136,7 @@
 		clocks = <&mcbsp3_gate_fck>, <&mcbsp3_mux_fck>;
 	};
 
-	mcbsp4_mux_fck: mcbsp4_mux_fck {
+	mcbsp4_mux_fck: mcbsp4_mux_fck@68 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&per_96m_fck>, <&mcbsp_clks>;
@@ -193,14 +193,14 @@
 		clock-frequency = <38400000>;
 	};
 
-	dpll4_ck: dpll4_ck {
+	dpll4_ck: dpll4_ck@d00 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-dpll-per-clock";
 		clocks = <&sys_ck>, <&sys_ck>;
 		reg = <0x0d00>, <0x0d20>, <0x0d44>, <0x0d30>;
 	};
 
-	dpll4_m2_ck: dpll4_m2_ck {
+	dpll4_m2_ck: dpll4_m2_ck@d48 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll4_ck>;
@@ -217,7 +217,7 @@
 		clock-div = <1>;
 	};
 
-	dpll4_m2x2_ck: dpll4_m2x2_ck {
+	dpll4_m2x2_ck: dpll4_m2x2_ck@d00 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&dpll4_m2x2_mul_ck>;
@@ -234,14 +234,14 @@
 		clock-div = <1>;
 	};
 
-	dpll3_ck: dpll3_ck {
+	dpll3_ck: dpll3_ck@d00 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-dpll-core-clock";
 		clocks = <&sys_ck>, <&sys_ck>;
 		reg = <0x0d00>, <0x0d20>, <0x0d40>, <0x0d30>;
 	};
 
-	dpll3_m3_ck: dpll3_m3_ck {
+	dpll3_m3_ck: dpll3_m3_ck@1140 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll3_ck>;
@@ -259,7 +259,7 @@
 		clock-div = <1>;
 	};
 
-	dpll3_m3x2_ck: dpll3_m3x2_ck {
+	dpll3_m3x2_ck: dpll3_m3x2_ck@d00 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&dpll3_m3x2_mul_ck>;
@@ -288,7 +288,7 @@
 		clock-frequency = <0x0>;
 	};
 
-	dpll3_m2_ck: dpll3_m2_ck {
+	dpll3_m2_ck: dpll3_m2_ck@d40 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll3_ck>;
@@ -306,7 +306,7 @@
 		clock-div = <1>;
 	};
 
-	dpll1_fck: dpll1_fck {
+	dpll1_fck: dpll1_fck@940 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&core_ck>;
@@ -316,7 +316,7 @@
 		ti,index-starts-at-one;
 	};
 
-	dpll1_ck: dpll1_ck {
+	dpll1_ck: dpll1_ck@904 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-dpll-clock";
 		clocks = <&sys_ck>, <&dpll1_fck>;
@@ -331,7 +331,7 @@
 		clock-div = <1>;
 	};
 
-	dpll1_x2m2_ck: dpll1_x2m2_ck {
+	dpll1_x2m2_ck: dpll1_x2m2_ck@944 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll1_x2_ck>;
@@ -348,7 +348,7 @@
 		clock-div = <1>;
 	};
 
-	omap_96m_fck: omap_96m_fck {
+	omap_96m_fck: omap_96m_fck@d40 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&cm_96m_fck>, <&sys_ck>;
@@ -356,7 +356,7 @@
 		reg = <0x0d40>;
 	};
 
-	dpll4_m3_ck: dpll4_m3_ck {
+	dpll4_m3_ck: dpll4_m3_ck@e40 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll4_ck>;
@@ -374,7 +374,7 @@
 		clock-div = <1>;
 	};
 
-	dpll4_m3x2_ck: dpll4_m3x2_ck {
+	dpll4_m3x2_ck: dpll4_m3x2_ck@d00 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&dpll4_m3x2_mul_ck>;
@@ -383,7 +383,7 @@
 		ti,set-bit-to-disable;
 	};
 
-	omap_54m_fck: omap_54m_fck {
+	omap_54m_fck: omap_54m_fck@d40 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&dpll4_m3x2_ck>, <&sys_altclk>;
@@ -399,7 +399,7 @@
 		clock-div = <2>;
 	};
 
-	omap_48m_fck: omap_48m_fck {
+	omap_48m_fck: omap_48m_fck@d40 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&cm_96m_d2_fck>, <&sys_altclk>;
@@ -415,7 +415,7 @@
 		clock-div = <4>;
 	};
 
-	dpll4_m4_ck: dpll4_m4_ck {
+	dpll4_m4_ck: dpll4_m4_ck@e40 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll4_ck>;
@@ -433,7 +433,7 @@
 		ti,set-rate-parent;
 	};
 
-	dpll4_m4x2_ck: dpll4_m4x2_ck {
+	dpll4_m4x2_ck: dpll4_m4x2_ck@d00 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&dpll4_m4x2_mul_ck>;
@@ -443,7 +443,7 @@
 		ti,set-rate-parent;
 	};
 
-	dpll4_m5_ck: dpll4_m5_ck {
+	dpll4_m5_ck: dpll4_m5_ck@f40 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll4_ck>;
@@ -461,7 +461,7 @@
 		ti,set-rate-parent;
 	};
 
-	dpll4_m5x2_ck: dpll4_m5x2_ck {
+	dpll4_m5x2_ck: dpll4_m5x2_ck@d00 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&dpll4_m5x2_mul_ck>;
@@ -471,7 +471,7 @@
 		ti,set-rate-parent;
 	};
 
-	dpll4_m6_ck: dpll4_m6_ck {
+	dpll4_m6_ck: dpll4_m6_ck@1140 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll4_ck>;
@@ -489,7 +489,7 @@
 		clock-div = <1>;
 	};
 
-	dpll4_m6x2_ck: dpll4_m6x2_ck {
+	dpll4_m6x2_ck: dpll4_m6x2_ck@d00 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&dpll4_m6x2_mul_ck>;
@@ -506,7 +506,7 @@
 		clock-div = <1>;
 	};
 
-	clkout2_src_gate_ck: clkout2_src_gate_ck {
+	clkout2_src_gate_ck: clkout2_src_gate_ck@d70 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-no-wait-gate-clock";
 		clocks = <&core_ck>;
@@ -514,7 +514,7 @@
 		reg = <0x0d70>;
 	};
 
-	clkout2_src_mux_ck: clkout2_src_mux_ck {
+	clkout2_src_mux_ck: clkout2_src_mux_ck@d70 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&core_ck>, <&sys_ck>, <&cm_96m_fck>, <&omap_54m_fck>;
@@ -527,7 +527,7 @@
 		clocks = <&clkout2_src_gate_ck>, <&clkout2_src_mux_ck>;
 	};
 
-	sys_clkout2: sys_clkout2 {
+	sys_clkout2: sys_clkout2@d70 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&clkout2_src_ck>;
@@ -545,7 +545,7 @@
 		clock-div = <1>;
 	};
 
-	arm_fck: arm_fck {
+	arm_fck: arm_fck@924 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&mpu_ck>;
@@ -561,7 +561,7 @@
 		clock-div = <1>;
 	};
 
-	l3_ick: l3_ick {
+	l3_ick: l3_ick@a40 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&core_ck>;
@@ -570,7 +570,7 @@
 		ti,index-starts-at-one;
 	};
 
-	l4_ick: l4_ick {
+	l4_ick: l4_ick@a40 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&l3_ick>;
@@ -580,7 +580,7 @@
 		ti,index-starts-at-one;
 	};
 
-	rm_ick: rm_ick {
+	rm_ick: rm_ick@c40 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&l4_ick>;
@@ -590,7 +590,7 @@
 		ti,index-starts-at-one;
 	};
 
-	gpt10_gate_fck: gpt10_gate_fck {
+	gpt10_gate_fck: gpt10_gate_fck@a00 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&sys_ck>;
@@ -598,7 +598,7 @@
 		reg = <0x0a00>;
 	};
 
-	gpt10_mux_fck: gpt10_mux_fck {
+	gpt10_mux_fck: gpt10_mux_fck@a40 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&omap_32k_fck>, <&sys_ck>;
@@ -612,7 +612,7 @@
 		clocks = <&gpt10_gate_fck>, <&gpt10_mux_fck>;
 	};
 
-	gpt11_gate_fck: gpt11_gate_fck {
+	gpt11_gate_fck: gpt11_gate_fck@a00 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&sys_ck>;
@@ -620,7 +620,7 @@
 		reg = <0x0a00>;
 	};
 
-	gpt11_mux_fck: gpt11_mux_fck {
+	gpt11_mux_fck: gpt11_mux_fck@a40 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&omap_32k_fck>, <&sys_ck>;
@@ -642,7 +642,7 @@
 		clock-div = <1>;
 	};
 
-	mmchs2_fck: mmchs2_fck {
+	mmchs2_fck: mmchs2_fck@a00 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&core_96m_fck>;
@@ -650,7 +650,7 @@
 		ti,bit-shift = <25>;
 	};
 
-	mmchs1_fck: mmchs1_fck {
+	mmchs1_fck: mmchs1_fck@a00 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&core_96m_fck>;
@@ -658,7 +658,7 @@
 		ti,bit-shift = <24>;
 	};
 
-	i2c3_fck: i2c3_fck {
+	i2c3_fck: i2c3_fck@a00 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&core_96m_fck>;
@@ -666,7 +666,7 @@
 		ti,bit-shift = <17>;
 	};
 
-	i2c2_fck: i2c2_fck {
+	i2c2_fck: i2c2_fck@a00 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&core_96m_fck>;
@@ -674,7 +674,7 @@
 		ti,bit-shift = <16>;
 	};
 
-	i2c1_fck: i2c1_fck {
+	i2c1_fck: i2c1_fck@a00 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&core_96m_fck>;
@@ -682,7 +682,7 @@
 		ti,bit-shift = <15>;
 	};
 
-	mcbsp5_gate_fck: mcbsp5_gate_fck {
+	mcbsp5_gate_fck: mcbsp5_gate_fck@a00 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&mcbsp_clks>;
@@ -690,7 +690,7 @@
 		reg = <0x0a00>;
 	};
 
-	mcbsp1_gate_fck: mcbsp1_gate_fck {
+	mcbsp1_gate_fck: mcbsp1_gate_fck@a00 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&mcbsp_clks>;
@@ -706,7 +706,7 @@
 		clock-div = <1>;
 	};
 
-	mcspi4_fck: mcspi4_fck {
+	mcspi4_fck: mcspi4_fck@a00 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&core_48m_fck>;
@@ -714,7 +714,7 @@
 		ti,bit-shift = <21>;
 	};
 
-	mcspi3_fck: mcspi3_fck {
+	mcspi3_fck: mcspi3_fck@a00 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&core_48m_fck>;
@@ -722,7 +722,7 @@
 		ti,bit-shift = <20>;
 	};
 
-	mcspi2_fck: mcspi2_fck {
+	mcspi2_fck: mcspi2_fck@a00 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&core_48m_fck>;
@@ -730,7 +730,7 @@
 		ti,bit-shift = <19>;
 	};
 
-	mcspi1_fck: mcspi1_fck {
+	mcspi1_fck: mcspi1_fck@a00 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&core_48m_fck>;
@@ -738,7 +738,7 @@
 		ti,bit-shift = <18>;
 	};
 
-	uart2_fck: uart2_fck {
+	uart2_fck: uart2_fck@a00 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&core_48m_fck>;
@@ -746,7 +746,7 @@
 		ti,bit-shift = <14>;
 	};
 
-	uart1_fck: uart1_fck {
+	uart1_fck: uart1_fck@a00 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&core_48m_fck>;
@@ -762,7 +762,7 @@
 		clock-div = <1>;
 	};
 
-	hdq_fck: hdq_fck {
+	hdq_fck: hdq_fck@a00 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&core_12m_fck>;
@@ -778,7 +778,7 @@
 		clock-div = <1>;
 	};
 
-	sdrc_ick: sdrc_ick {
+	sdrc_ick: sdrc_ick@a10 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&core_l3_ick>;
@@ -802,7 +802,7 @@
 		clock-div = <1>;
 	};
 
-	mmchs2_ick: mmchs2_ick {
+	mmchs2_ick: mmchs2_ick@a10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&core_l4_ick>;
@@ -810,7 +810,7 @@
 		ti,bit-shift = <25>;
 	};
 
-	mmchs1_ick: mmchs1_ick {
+	mmchs1_ick: mmchs1_ick@a10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&core_l4_ick>;
@@ -818,7 +818,7 @@
 		ti,bit-shift = <24>;
 	};
 
-	hdq_ick: hdq_ick {
+	hdq_ick: hdq_ick@a10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&core_l4_ick>;
@@ -826,7 +826,7 @@
 		ti,bit-shift = <22>;
 	};
 
-	mcspi4_ick: mcspi4_ick {
+	mcspi4_ick: mcspi4_ick@a10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&core_l4_ick>;
@@ -834,7 +834,7 @@
 		ti,bit-shift = <21>;
 	};
 
-	mcspi3_ick: mcspi3_ick {
+	mcspi3_ick: mcspi3_ick@a10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&core_l4_ick>;
@@ -842,7 +842,7 @@
 		ti,bit-shift = <20>;
 	};
 
-	mcspi2_ick: mcspi2_ick {
+	mcspi2_ick: mcspi2_ick@a10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&core_l4_ick>;
@@ -850,7 +850,7 @@
 		ti,bit-shift = <19>;
 	};
 
-	mcspi1_ick: mcspi1_ick {
+	mcspi1_ick: mcspi1_ick@a10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&core_l4_ick>;
@@ -858,7 +858,7 @@
 		ti,bit-shift = <18>;
 	};
 
-	i2c3_ick: i2c3_ick {
+	i2c3_ick: i2c3_ick@a10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&core_l4_ick>;
@@ -866,7 +866,7 @@
 		ti,bit-shift = <17>;
 	};
 
-	i2c2_ick: i2c2_ick {
+	i2c2_ick: i2c2_ick@a10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&core_l4_ick>;
@@ -874,7 +874,7 @@
 		ti,bit-shift = <16>;
 	};
 
-	i2c1_ick: i2c1_ick {
+	i2c1_ick: i2c1_ick@a10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&core_l4_ick>;
@@ -882,7 +882,7 @@
 		ti,bit-shift = <15>;
 	};
 
-	uart2_ick: uart2_ick {
+	uart2_ick: uart2_ick@a10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&core_l4_ick>;
@@ -890,7 +890,7 @@
 		ti,bit-shift = <14>;
 	};
 
-	uart1_ick: uart1_ick {
+	uart1_ick: uart1_ick@a10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&core_l4_ick>;
@@ -898,7 +898,7 @@
 		ti,bit-shift = <13>;
 	};
 
-	gpt11_ick: gpt11_ick {
+	gpt11_ick: gpt11_ick@a10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&core_l4_ick>;
@@ -906,7 +906,7 @@
 		ti,bit-shift = <12>;
 	};
 
-	gpt10_ick: gpt10_ick {
+	gpt10_ick: gpt10_ick@a10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&core_l4_ick>;
@@ -914,7 +914,7 @@
 		ti,bit-shift = <11>;
 	};
 
-	mcbsp5_ick: mcbsp5_ick {
+	mcbsp5_ick: mcbsp5_ick@a10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&core_l4_ick>;
@@ -922,7 +922,7 @@
 		ti,bit-shift = <10>;
 	};
 
-	mcbsp1_ick: mcbsp1_ick {
+	mcbsp1_ick: mcbsp1_ick@a10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&core_l4_ick>;
@@ -930,7 +930,7 @@
 		ti,bit-shift = <9>;
 	};
 
-	omapctrl_ick: omapctrl_ick {
+	omapctrl_ick: omapctrl_ick@a10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&core_l4_ick>;
@@ -938,7 +938,7 @@
 		ti,bit-shift = <6>;
 	};
 
-	dss_tv_fck: dss_tv_fck {
+	dss_tv_fck: dss_tv_fck@e00 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&omap_54m_fck>;
@@ -946,7 +946,7 @@
 		ti,bit-shift = <2>;
 	};
 
-	dss_96m_fck: dss_96m_fck {
+	dss_96m_fck: dss_96m_fck@e00 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&omap_96m_fck>;
@@ -954,7 +954,7 @@
 		ti,bit-shift = <2>;
 	};
 
-	dss2_alwon_fck: dss2_alwon_fck {
+	dss2_alwon_fck: dss2_alwon_fck@e00 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_ck>;
@@ -968,7 +968,7 @@
 		clock-frequency = <0>;
 	};
 
-	gpt1_gate_fck: gpt1_gate_fck {
+	gpt1_gate_fck: gpt1_gate_fck@c00 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&sys_ck>;
@@ -976,7 +976,7 @@
 		reg = <0x0c00>;
 	};
 
-	gpt1_mux_fck: gpt1_mux_fck {
+	gpt1_mux_fck: gpt1_mux_fck@c40 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&omap_32k_fck>, <&sys_ck>;
@@ -989,7 +989,7 @@
 		clocks = <&gpt1_gate_fck>, <&gpt1_mux_fck>;
 	};
 
-	aes2_ick: aes2_ick {
+	aes2_ick: aes2_ick@a10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&core_l4_ick>;
@@ -1005,7 +1005,7 @@
 		clock-div = <1>;
 	};
 
-	gpio1_dbck: gpio1_dbck {
+	gpio1_dbck: gpio1_dbck@c00 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&wkup_32k_fck>;
@@ -1013,7 +1013,7 @@
 		ti,bit-shift = <3>;
 	};
 
-	sha12_ick: sha12_ick {
+	sha12_ick: sha12_ick@a10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&core_l4_ick>;
@@ -1021,7 +1021,7 @@
 		ti,bit-shift = <27>;
 	};
 
-	wdt2_fck: wdt2_fck {
+	wdt2_fck: wdt2_fck@c00 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&wkup_32k_fck>;
@@ -1029,7 +1029,7 @@
 		ti,bit-shift = <5>;
 	};
 
-	wdt2_ick: wdt2_ick {
+	wdt2_ick: wdt2_ick@c10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&wkup_l4_ick>;
@@ -1037,7 +1037,7 @@
 		ti,bit-shift = <5>;
 	};
 
-	wdt1_ick: wdt1_ick {
+	wdt1_ick: wdt1_ick@c10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&wkup_l4_ick>;
@@ -1045,7 +1045,7 @@
 		ti,bit-shift = <4>;
 	};
 
-	gpio1_ick: gpio1_ick {
+	gpio1_ick: gpio1_ick@c10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&wkup_l4_ick>;
@@ -1053,7 +1053,7 @@
 		ti,bit-shift = <3>;
 	};
 
-	omap_32ksync_ick: omap_32ksync_ick {
+	omap_32ksync_ick: omap_32ksync_ick@c10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&wkup_l4_ick>;
@@ -1061,7 +1061,7 @@
 		ti,bit-shift = <2>;
 	};
 
-	gpt12_ick: gpt12_ick {
+	gpt12_ick: gpt12_ick@c10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&wkup_l4_ick>;
@@ -1069,7 +1069,7 @@
 		ti,bit-shift = <1>;
 	};
 
-	gpt1_ick: gpt1_ick {
+	gpt1_ick: gpt1_ick@c10 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&wkup_l4_ick>;
@@ -1093,7 +1093,7 @@
 		clock-div = <1>;
 	};
 
-	uart3_fck: uart3_fck {
+	uart3_fck: uart3_fck@1000 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&per_48m_fck>;
@@ -1101,7 +1101,7 @@
 		ti,bit-shift = <11>;
 	};
 
-	gpt2_gate_fck: gpt2_gate_fck {
+	gpt2_gate_fck: gpt2_gate_fck@1000 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&sys_ck>;
@@ -1109,7 +1109,7 @@
 		reg = <0x1000>;
 	};
 
-	gpt2_mux_fck: gpt2_mux_fck {
+	gpt2_mux_fck: gpt2_mux_fck@1040 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&omap_32k_fck>, <&sys_ck>;
@@ -1122,7 +1122,7 @@
 		clocks = <&gpt2_gate_fck>, <&gpt2_mux_fck>;
 	};
 
-	gpt3_gate_fck: gpt3_gate_fck {
+	gpt3_gate_fck: gpt3_gate_fck@1000 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&sys_ck>;
@@ -1130,7 +1130,7 @@
 		reg = <0x1000>;
 	};
 
-	gpt3_mux_fck: gpt3_mux_fck {
+	gpt3_mux_fck: gpt3_mux_fck@1040 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&omap_32k_fck>, <&sys_ck>;
@@ -1144,7 +1144,7 @@
 		clocks = <&gpt3_gate_fck>, <&gpt3_mux_fck>;
 	};
 
-	gpt4_gate_fck: gpt4_gate_fck {
+	gpt4_gate_fck: gpt4_gate_fck@1000 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&sys_ck>;
@@ -1152,7 +1152,7 @@
 		reg = <0x1000>;
 	};
 
-	gpt4_mux_fck: gpt4_mux_fck {
+	gpt4_mux_fck: gpt4_mux_fck@1040 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&omap_32k_fck>, <&sys_ck>;
@@ -1166,7 +1166,7 @@
 		clocks = <&gpt4_gate_fck>, <&gpt4_mux_fck>;
 	};
 
-	gpt5_gate_fck: gpt5_gate_fck {
+	gpt5_gate_fck: gpt5_gate_fck@1000 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&sys_ck>;
@@ -1174,7 +1174,7 @@
 		reg = <0x1000>;
 	};
 
-	gpt5_mux_fck: gpt5_mux_fck {
+	gpt5_mux_fck: gpt5_mux_fck@1040 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&omap_32k_fck>, <&sys_ck>;
@@ -1188,7 +1188,7 @@
 		clocks = <&gpt5_gate_fck>, <&gpt5_mux_fck>;
 	};
 
-	gpt6_gate_fck: gpt6_gate_fck {
+	gpt6_gate_fck: gpt6_gate_fck@1000 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&sys_ck>;
@@ -1196,7 +1196,7 @@
 		reg = <0x1000>;
 	};
 
-	gpt6_mux_fck: gpt6_mux_fck {
+	gpt6_mux_fck: gpt6_mux_fck@1040 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&omap_32k_fck>, <&sys_ck>;
@@ -1210,7 +1210,7 @@
 		clocks = <&gpt6_gate_fck>, <&gpt6_mux_fck>;
 	};
 
-	gpt7_gate_fck: gpt7_gate_fck {
+	gpt7_gate_fck: gpt7_gate_fck@1000 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&sys_ck>;
@@ -1218,7 +1218,7 @@
 		reg = <0x1000>;
 	};
 
-	gpt7_mux_fck: gpt7_mux_fck {
+	gpt7_mux_fck: gpt7_mux_fck@1040 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&omap_32k_fck>, <&sys_ck>;
@@ -1232,7 +1232,7 @@
 		clocks = <&gpt7_gate_fck>, <&gpt7_mux_fck>;
 	};
 
-	gpt8_gate_fck: gpt8_gate_fck {
+	gpt8_gate_fck: gpt8_gate_fck@1000 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&sys_ck>;
@@ -1240,7 +1240,7 @@
 		reg = <0x1000>;
 	};
 
-	gpt8_mux_fck: gpt8_mux_fck {
+	gpt8_mux_fck: gpt8_mux_fck@1040 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&omap_32k_fck>, <&sys_ck>;
@@ -1254,7 +1254,7 @@
 		clocks = <&gpt8_gate_fck>, <&gpt8_mux_fck>;
 	};
 
-	gpt9_gate_fck: gpt9_gate_fck {
+	gpt9_gate_fck: gpt9_gate_fck@1000 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&sys_ck>;
@@ -1262,7 +1262,7 @@
 		reg = <0x1000>;
 	};
 
-	gpt9_mux_fck: gpt9_mux_fck {
+	gpt9_mux_fck: gpt9_mux_fck@1040 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&omap_32k_fck>, <&sys_ck>;
@@ -1284,7 +1284,7 @@
 		clock-div = <1>;
 	};
 
-	gpio6_dbck: gpio6_dbck {
+	gpio6_dbck: gpio6_dbck@1000 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&per_32k_alwon_fck>;
@@ -1292,7 +1292,7 @@
 		ti,bit-shift = <17>;
 	};
 
-	gpio5_dbck: gpio5_dbck {
+	gpio5_dbck: gpio5_dbck@1000 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&per_32k_alwon_fck>;
@@ -1300,7 +1300,7 @@
 		ti,bit-shift = <16>;
 	};
 
-	gpio4_dbck: gpio4_dbck {
+	gpio4_dbck: gpio4_dbck@1000 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&per_32k_alwon_fck>;
@@ -1308,7 +1308,7 @@
 		ti,bit-shift = <15>;
 	};
 
-	gpio3_dbck: gpio3_dbck {
+	gpio3_dbck: gpio3_dbck@1000 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&per_32k_alwon_fck>;
@@ -1316,7 +1316,7 @@
 		ti,bit-shift = <14>;
 	};
 
-	gpio2_dbck: gpio2_dbck {
+	gpio2_dbck: gpio2_dbck@1000 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&per_32k_alwon_fck>;
@@ -1324,7 +1324,7 @@
 		ti,bit-shift = <13>;
 	};
 
-	wdt3_fck: wdt3_fck {
+	wdt3_fck: wdt3_fck@1000 {
 		#clock-cells = <0>;
 		compatible = "ti,wait-gate-clock";
 		clocks = <&per_32k_alwon_fck>;
@@ -1340,7 +1340,7 @@
 		clock-div = <1>;
 	};
 
-	gpio6_ick: gpio6_ick {
+	gpio6_ick: gpio6_ick@1010 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&per_l4_ick>;
@@ -1348,7 +1348,7 @@
 		ti,bit-shift = <17>;
 	};
 
-	gpio5_ick: gpio5_ick {
+	gpio5_ick: gpio5_ick@1010 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&per_l4_ick>;
@@ -1356,7 +1356,7 @@
 		ti,bit-shift = <16>;
 	};
 
-	gpio4_ick: gpio4_ick {
+	gpio4_ick: gpio4_ick@1010 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&per_l4_ick>;
@@ -1364,7 +1364,7 @@
 		ti,bit-shift = <15>;
 	};
 
-	gpio3_ick: gpio3_ick {
+	gpio3_ick: gpio3_ick@1010 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&per_l4_ick>;
@@ -1372,7 +1372,7 @@
 		ti,bit-shift = <14>;
 	};
 
-	gpio2_ick: gpio2_ick {
+	gpio2_ick: gpio2_ick@1010 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&per_l4_ick>;
@@ -1380,7 +1380,7 @@
 		ti,bit-shift = <13>;
 	};
 
-	wdt3_ick: wdt3_ick {
+	wdt3_ick: wdt3_ick@1010 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&per_l4_ick>;
@@ -1388,7 +1388,7 @@
 		ti,bit-shift = <12>;
 	};
 
-	uart3_ick: uart3_ick {
+	uart3_ick: uart3_ick@1010 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&per_l4_ick>;
@@ -1396,7 +1396,7 @@
 		ti,bit-shift = <11>;
 	};
 
-	uart4_ick: uart4_ick {
+	uart4_ick: uart4_ick@1010 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&per_l4_ick>;
@@ -1404,7 +1404,7 @@
 		ti,bit-shift = <18>;
 	};
 
-	gpt9_ick: gpt9_ick {
+	gpt9_ick: gpt9_ick@1010 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&per_l4_ick>;
@@ -1412,7 +1412,7 @@
 		ti,bit-shift = <10>;
 	};
 
-	gpt8_ick: gpt8_ick {
+	gpt8_ick: gpt8_ick@1010 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&per_l4_ick>;
@@ -1420,7 +1420,7 @@
 		ti,bit-shift = <9>;
 	};
 
-	gpt7_ick: gpt7_ick {
+	gpt7_ick: gpt7_ick@1010 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&per_l4_ick>;
@@ -1428,7 +1428,7 @@
 		ti,bit-shift = <8>;
 	};
 
-	gpt6_ick: gpt6_ick {
+	gpt6_ick: gpt6_ick@1010 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&per_l4_ick>;
@@ -1436,7 +1436,7 @@
 		ti,bit-shift = <7>;
 	};
 
-	gpt5_ick: gpt5_ick {
+	gpt5_ick: gpt5_ick@1010 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&per_l4_ick>;
@@ -1444,7 +1444,7 @@
 		ti,bit-shift = <6>;
 	};
 
-	gpt4_ick: gpt4_ick {
+	gpt4_ick: gpt4_ick@1010 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&per_l4_ick>;
@@ -1452,7 +1452,7 @@
 		ti,bit-shift = <5>;
 	};
 
-	gpt3_ick: gpt3_ick {
+	gpt3_ick: gpt3_ick@1010 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&per_l4_ick>;
@@ -1460,7 +1460,7 @@
 		ti,bit-shift = <4>;
 	};
 
-	gpt2_ick: gpt2_ick {
+	gpt2_ick: gpt2_ick@1010 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&per_l4_ick>;
@@ -1468,7 +1468,7 @@
 		ti,bit-shift = <3>;
 	};
 
-	mcbsp2_ick: mcbsp2_ick {
+	mcbsp2_ick: mcbsp2_ick@1010 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&per_l4_ick>;
@@ -1476,7 +1476,7 @@
 		ti,bit-shift = <0>;
 	};
 
-	mcbsp3_ick: mcbsp3_ick {
+	mcbsp3_ick: mcbsp3_ick@1010 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&per_l4_ick>;
@@ -1484,7 +1484,7 @@
 		ti,bit-shift = <1>;
 	};
 
-	mcbsp4_ick: mcbsp4_ick {
+	mcbsp4_ick: mcbsp4_ick@1010 {
 		#clock-cells = <0>;
 		compatible = "ti,omap3-interface-clock";
 		clocks = <&per_l4_ick>;
@@ -1492,7 +1492,7 @@
 		ti,bit-shift = <2>;
 	};
 
-	mcbsp2_gate_fck: mcbsp2_gate_fck {
+	mcbsp2_gate_fck: mcbsp2_gate_fck@1000 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&mcbsp_clks>;
@@ -1500,7 +1500,7 @@
 		reg = <0x1000>;
 	};
 
-	mcbsp3_gate_fck: mcbsp3_gate_fck {
+	mcbsp3_gate_fck: mcbsp3_gate_fck@1000 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&mcbsp_clks>;
@@ -1508,7 +1508,7 @@
 		reg = <0x1000>;
 	};
 
-	mcbsp4_gate_fck: mcbsp4_gate_fck {
+	mcbsp4_gate_fck: mcbsp4_gate_fck@1000 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-gate-clock";
 		clocks = <&mcbsp_clks>;
@@ -1516,7 +1516,7 @@
 		reg = <0x1000>;
 	};
 
-	emu_src_mux_ck: emu_src_mux_ck {
+	emu_src_mux_ck: emu_src_mux_ck@1140 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_ck>, <&emu_core_alwon_ck>, <&emu_per_alwon_ck>, <&emu_mpu_alwon_ck>;
@@ -1529,7 +1529,7 @@
 		clocks = <&emu_src_mux_ck>;
 	};
 
-	pclk_fck: pclk_fck {
+	pclk_fck: pclk_fck@1140 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&emu_src_ck>;
@@ -1539,7 +1539,7 @@
 		ti,index-starts-at-one;
 	};
 
-	pclkx2_fck: pclkx2_fck {
+	pclkx2_fck: pclkx2_fck@1140 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&emu_src_ck>;
@@ -1549,7 +1549,7 @@
 		ti,index-starts-at-one;
 	};
 
-	atclk_fck: atclk_fck {
+	atclk_fck: atclk_fck@1140 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&emu_src_ck>;
@@ -1559,7 +1559,7 @@
 		ti,index-starts-at-one;
 	};
 
-	traceclk_src_fck: traceclk_src_fck {
+	traceclk_src_fck: traceclk_src_fck@1140 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_ck>, <&emu_core_alwon_ck>, <&emu_per_alwon_ck>, <&emu_mpu_alwon_ck>;
@@ -1567,7 +1567,7 @@
 		reg = <0x1140>;
 	};
 
-	traceclk_fck: traceclk_fck {
+	traceclk_fck: traceclk_fck@1140 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&traceclk_src_fck>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/omap3-zoom3.dts linux-libre-4.7-gnu/arch/arm/boot/dts/omap3-zoom3.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/omap3-zoom3.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/omap3-zoom3.dts	2016-07-24 15:23:50.000000000 -0400
@@ -98,7 +98,7 @@
 		pinctrl-single,pins = <
                         OMAP3_CORE1_IOPAD(0x2174, PIN_INPUT_PULLUP | MUX_MODE0)	/* uart2_cts.uart2_cts */
                         OMAP3_CORE1_IOPAD(0x2176, PIN_OUTPUT | MUX_MODE0)		/* uart2_rts.uart2_rts */
-                        OMAP3_CORE1_IOPAD(0x217a, WAKEUP_EN | PIN_INPUT | MUX_MODE0) /* uart2_rx.uart2_rx */
+                        OMAP3_CORE1_IOPAD(0x217a, PIN_INPUT | MUX_MODE0)		/* uart2_rx.uart2_rx */
                         OMAP3_CORE1_IOPAD(0x2178, PIN_OUTPUT | MUX_MODE0)		/* uart2_tx.uart2_tx */
 		>;
 	};
@@ -107,7 +107,7 @@
 		pinctrl-single,pins = <
                         OMAP3_CORE1_IOPAD(0x219a, PIN_INPUT_PULLDOWN | MUX_MODE0)	/* uart3_cts_rctx.uart3_cts_rctx */
                         OMAP3_CORE1_IOPAD(0x219c, PIN_OUTPUT | MUX_MODE0)		/* uart3_rts_sd.uart3_rts_sd */
-                        OMAP3_CORE1_IOPAD(0x219e, WAKEUP_EN | PIN_INPUT | MUX_MODE0) /* uart3_rx_irrx.uart3_rx_irrx */
+                        OMAP3_CORE1_IOPAD(0x219e, PIN_INPUT | MUX_MODE0)		/* uart3_rx_irrx.uart3_rx_irrx */
                         OMAP3_CORE1_IOPAD(0x21a0, PIN_OUTPUT | MUX_MODE0)		/* uart3_tx_irtx.uart3_tx_irtx */
 		>;
 	};
@@ -125,7 +125,7 @@
 		pinctrl-single,pins = <
 			OMAP3630_CORE2_IOPAD(0x25d8, PIN_INPUT_PULLUP | MUX_MODE2)	/* etk_clk.sdmmc3_clk */
 			OMAP3630_CORE2_IOPAD(0x25e4, PIN_INPUT_PULLUP | MUX_MODE2)	/* etk_d4.sdmmc3_dat0 */
-			OMAP3630_CORE2_IOPAD(0x25e6, WAKEUP_EN | PIN_INPUT_PULLUP | MUX_MODE2) /* etk_d5.sdmmc3_dat1 */
+			OMAP3630_CORE2_IOPAD(0x25e6, PIN_INPUT_PULLUP | MUX_MODE2)	/* etk_d5.sdmmc3_dat1 */
 			OMAP3630_CORE2_IOPAD(0x25e8, PIN_INPUT_PULLUP | MUX_MODE2)	/* etk_d6.sdmmc3_dat2 */
 			OMAP3630_CORE2_IOPAD(0x25e2, PIN_INPUT_PULLUP | MUX_MODE2)	/* etk_d3.sdmmc3_dat3 */
 		>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/omap443x-clocks.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/omap443x-clocks.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/omap443x-clocks.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/omap443x-clocks.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -8,7 +8,7 @@
  * published by the Free Software Foundation.
  */
 &prm_clocks {
-	bandgap_fclk: bandgap_fclk {
+	bandgap_fclk: bandgap_fclk@1888 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_32k_ck>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/omap443x.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/omap443x.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/omap443x.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/omap443x.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -35,7 +35,7 @@
 	};
 
 	ocp {
-		bandgap: bandgap {
+		bandgap: bandgap@4a002260 {
 			reg = <0x4a002260 0x4
 			       0x4a00232C 0x4>;
 			compatible = "ti,omap4430-bandgap";
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/omap4460.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/omap4460.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/omap4460.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/omap4460.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -40,7 +40,7 @@
 	};
 
 	ocp {
-		bandgap: bandgap {
+		bandgap: bandgap@4a002260 {
 			reg = <0x4a002260 0x4
 			       0x4a00232C 0x4
 			       0x4a002378 0x18>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/omap446x-clocks.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/omap446x-clocks.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/omap446x-clocks.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/omap446x-clocks.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -8,7 +8,7 @@
  * published by the Free Software Foundation.
  */
 &prm_clocks {
-	div_ts_ck: div_ts_ck {
+	div_ts_ck: div_ts_ck@1888 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&l4_wkup_clk_mux_ck>;
@@ -17,7 +17,7 @@
 		ti,dividers = <8>, <16>, <32>;
 	};
 
-	bandgap_ts_fclk: bandgap_ts_fclk {
+	bandgap_ts_fclk: bandgap_ts_fclk@1888 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&div_ts_ck>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/omap44xx-clocks.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/omap44xx-clocks.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/omap44xx-clocks.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/omap44xx-clocks.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -20,7 +20,7 @@
 		clock-frequency = <12000000>;
 	};
 
-	pad_clks_ck: pad_clks_ck {
+	pad_clks_ck: pad_clks_ck@108 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&pad_clks_src_ck>;
@@ -46,7 +46,7 @@
 		clock-frequency = <12000000>;
 	};
 
-	slimbus_clk: slimbus_clk {
+	slimbus_clk: slimbus_clk@108 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&slimbus_src_clk>;
@@ -132,21 +132,21 @@
 		clock-frequency = <60000000>;
 	};
 
-	dpll_abe_ck: dpll_abe_ck {
+	dpll_abe_ck: dpll_abe_ck@1e0 {
 		#clock-cells = <0>;
 		compatible = "ti,omap4-dpll-m4xen-clock";
 		clocks = <&abe_dpll_refclk_mux_ck>, <&abe_dpll_bypass_clk_mux_ck>;
 		reg = <0x01e0>, <0x01e4>, <0x01ec>, <0x01e8>;
 	};
 
-	dpll_abe_x2_ck: dpll_abe_x2_ck {
+	dpll_abe_x2_ck: dpll_abe_x2_ck@1f0 {
 		#clock-cells = <0>;
 		compatible = "ti,omap4-dpll-x2-clock";
 		clocks = <&dpll_abe_ck>;
 		reg = <0x01f0>;
 	};
 
-	dpll_abe_m2x2_ck: dpll_abe_m2x2_ck {
+	dpll_abe_m2x2_ck: dpll_abe_m2x2_ck@1f0 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_abe_x2_ck>;
@@ -165,7 +165,7 @@
 		clock-div = <8>;
 	};
 
-	abe_clk: abe_clk {
+	abe_clk: abe_clk@108 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_abe_m2x2_ck>;
@@ -174,7 +174,7 @@
 		ti,index-power-of-two;
 	};
 
-	aess_fclk: aess_fclk {
+	aess_fclk: aess_fclk@528 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&abe_clk>;
@@ -183,7 +183,7 @@
 		reg = <0x0528>;
 	};
 
-	dpll_abe_m3x2_ck: dpll_abe_m3x2_ck {
+	dpll_abe_m3x2_ck: dpll_abe_m3x2_ck@1f4 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_abe_x2_ck>;
@@ -194,7 +194,7 @@
 		ti,invert-autoidle-bit;
 	};
 
-	core_hsd_byp_clk_mux_ck: core_hsd_byp_clk_mux_ck {
+	core_hsd_byp_clk_mux_ck: core_hsd_byp_clk_mux_ck@12c {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin_ck>, <&dpll_abe_m3x2_ck>;
@@ -202,7 +202,7 @@
 		reg = <0x012c>;
 	};
 
-	dpll_core_ck: dpll_core_ck {
+	dpll_core_ck: dpll_core_ck@120 {
 		#clock-cells = <0>;
 		compatible = "ti,omap4-dpll-core-clock";
 		clocks = <&sys_clkin_ck>, <&core_hsd_byp_clk_mux_ck>;
@@ -215,7 +215,7 @@
 		clocks = <&dpll_core_ck>;
 	};
 
-	dpll_core_m6x2_ck: dpll_core_m6x2_ck {
+	dpll_core_m6x2_ck: dpll_core_m6x2_ck@140 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_core_x2_ck>;
@@ -226,7 +226,7 @@
 		ti,invert-autoidle-bit;
 	};
 
-	dpll_core_m2_ck: dpll_core_m2_ck {
+	dpll_core_m2_ck: dpll_core_m2_ck@130 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_core_ck>;
@@ -245,7 +245,7 @@
 		clock-div = <2>;
 	};
 
-	dpll_core_m5x2_ck: dpll_core_m5x2_ck {
+	dpll_core_m5x2_ck: dpll_core_m5x2_ck@13c {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_core_x2_ck>;
@@ -256,7 +256,7 @@
 		ti,invert-autoidle-bit;
 	};
 
-	div_core_ck: div_core_ck {
+	div_core_ck: div_core_ck@100 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_core_m5x2_ck>;
@@ -264,7 +264,7 @@
 		ti,max-div = <2>;
 	};
 
-	div_iva_hs_clk: div_iva_hs_clk {
+	div_iva_hs_clk: div_iva_hs_clk@1dc {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_core_m5x2_ck>;
@@ -273,7 +273,7 @@
 		ti,index-power-of-two;
 	};
 
-	div_mpu_hs_clk: div_mpu_hs_clk {
+	div_mpu_hs_clk: div_mpu_hs_clk@19c {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_core_m5x2_ck>;
@@ -282,7 +282,7 @@
 		ti,index-power-of-two;
 	};
 
-	dpll_core_m4x2_ck: dpll_core_m4x2_ck {
+	dpll_core_m4x2_ck: dpll_core_m4x2_ck@138 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_core_x2_ck>;
@@ -301,7 +301,7 @@
 		clock-div = <2>;
 	};
 
-	dpll_abe_m2_ck: dpll_abe_m2_ck {
+	dpll_abe_m2_ck: dpll_abe_m2_ck@1f0 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_abe_ck>;
@@ -310,7 +310,7 @@
 		ti,index-starts-at-one;
 	};
 
-	dpll_core_m3x2_gate_ck: dpll_core_m3x2_gate_ck {
+	dpll_core_m3x2_gate_ck: dpll_core_m3x2_gate_ck@134 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-no-wait-gate-clock";
 		clocks = <&dpll_core_x2_ck>;
@@ -318,7 +318,7 @@
 		reg = <0x0134>;
 	};
 
-	dpll_core_m3x2_div_ck: dpll_core_m3x2_div_ck {
+	dpll_core_m3x2_div_ck: dpll_core_m3x2_div_ck@134 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-divider-clock";
 		clocks = <&dpll_core_x2_ck>;
@@ -333,7 +333,7 @@
 		clocks = <&dpll_core_m3x2_gate_ck>, <&dpll_core_m3x2_div_ck>;
 	};
 
-	dpll_core_m7x2_ck: dpll_core_m7x2_ck {
+	dpll_core_m7x2_ck: dpll_core_m7x2_ck@144 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_core_x2_ck>;
@@ -344,7 +344,7 @@
 		ti,invert-autoidle-bit;
 	};
 
-	iva_hsd_byp_clk_mux_ck: iva_hsd_byp_clk_mux_ck {
+	iva_hsd_byp_clk_mux_ck: iva_hsd_byp_clk_mux_ck@1ac {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin_ck>, <&div_iva_hs_clk>;
@@ -352,7 +352,7 @@
 		reg = <0x01ac>;
 	};
 
-	dpll_iva_ck: dpll_iva_ck {
+	dpll_iva_ck: dpll_iva_ck@1a0 {
 		#clock-cells = <0>;
 		compatible = "ti,omap4-dpll-clock";
 		clocks = <&sys_clkin_ck>, <&iva_hsd_byp_clk_mux_ck>;
@@ -365,7 +365,7 @@
 		clocks = <&dpll_iva_ck>;
 	};
 
-	dpll_iva_m4x2_ck: dpll_iva_m4x2_ck {
+	dpll_iva_m4x2_ck: dpll_iva_m4x2_ck@1b8 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_iva_x2_ck>;
@@ -376,7 +376,7 @@
 		ti,invert-autoidle-bit;
 	};
 
-	dpll_iva_m5x2_ck: dpll_iva_m5x2_ck {
+	dpll_iva_m5x2_ck: dpll_iva_m5x2_ck@1bc {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_iva_x2_ck>;
@@ -387,14 +387,14 @@
 		ti,invert-autoidle-bit;
 	};
 
-	dpll_mpu_ck: dpll_mpu_ck {
+	dpll_mpu_ck: dpll_mpu_ck@160 {
 		#clock-cells = <0>;
 		compatible = "ti,omap4-dpll-clock";
 		clocks = <&sys_clkin_ck>, <&div_mpu_hs_clk>;
 		reg = <0x0160>, <0x0164>, <0x016c>, <0x0168>;
 	};
 
-	dpll_mpu_m2_ck: dpll_mpu_m2_ck {
+	dpll_mpu_m2_ck: dpll_mpu_m2_ck@170 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_mpu_ck>;
@@ -421,7 +421,7 @@
 		clock-div = <3>;
 	};
 
-	l3_div_ck: l3_div_ck {
+	l3_div_ck: l3_div_ck@100 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&div_core_ck>;
@@ -430,7 +430,7 @@
 		reg = <0x0100>;
 	};
 
-	l4_div_ck: l4_div_ck {
+	l4_div_ck: l4_div_ck@100 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&l3_div_ck>;
@@ -455,7 +455,7 @@
 		clock-div = <2>;
 	};
 
-	ocp_abe_iclk: ocp_abe_iclk {
+	ocp_abe_iclk: ocp_abe_iclk@528 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&aess_fclk>;
@@ -472,7 +472,7 @@
 		clock-div = <4>;
 	};
 
-	dmic_sync_mux_ck: dmic_sync_mux_ck {
+	dmic_sync_mux_ck: dmic_sync_mux_ck@538 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&abe_24m_fclk>, <&syc_clk_div_ck>, <&func_24m_clk>;
@@ -480,7 +480,7 @@
 		reg = <0x0538>;
 	};
 
-	func_dmic_abe_gfclk: func_dmic_abe_gfclk {
+	func_dmic_abe_gfclk: func_dmic_abe_gfclk@538 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&dmic_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>;
@@ -488,7 +488,7 @@
 		reg = <0x0538>;
 	};
 
-	mcasp_sync_mux_ck: mcasp_sync_mux_ck {
+	mcasp_sync_mux_ck: mcasp_sync_mux_ck@540 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&abe_24m_fclk>, <&syc_clk_div_ck>, <&func_24m_clk>;
@@ -496,7 +496,7 @@
 		reg = <0x0540>;
 	};
 
-	func_mcasp_abe_gfclk: func_mcasp_abe_gfclk {
+	func_mcasp_abe_gfclk: func_mcasp_abe_gfclk@540 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&mcasp_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>;
@@ -504,7 +504,7 @@
 		reg = <0x0540>;
 	};
 
-	mcbsp1_sync_mux_ck: mcbsp1_sync_mux_ck {
+	mcbsp1_sync_mux_ck: mcbsp1_sync_mux_ck@548 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&abe_24m_fclk>, <&syc_clk_div_ck>, <&func_24m_clk>;
@@ -512,7 +512,7 @@
 		reg = <0x0548>;
 	};
 
-	func_mcbsp1_gfclk: func_mcbsp1_gfclk {
+	func_mcbsp1_gfclk: func_mcbsp1_gfclk@548 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&mcbsp1_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>;
@@ -520,7 +520,7 @@
 		reg = <0x0548>;
 	};
 
-	mcbsp2_sync_mux_ck: mcbsp2_sync_mux_ck {
+	mcbsp2_sync_mux_ck: mcbsp2_sync_mux_ck@550 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&abe_24m_fclk>, <&syc_clk_div_ck>, <&func_24m_clk>;
@@ -528,7 +528,7 @@
 		reg = <0x0550>;
 	};
 
-	func_mcbsp2_gfclk: func_mcbsp2_gfclk {
+	func_mcbsp2_gfclk: func_mcbsp2_gfclk@550 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&mcbsp2_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>;
@@ -536,7 +536,7 @@
 		reg = <0x0550>;
 	};
 
-	mcbsp3_sync_mux_ck: mcbsp3_sync_mux_ck {
+	mcbsp3_sync_mux_ck: mcbsp3_sync_mux_ck@558 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&abe_24m_fclk>, <&syc_clk_div_ck>, <&func_24m_clk>;
@@ -544,7 +544,7 @@
 		reg = <0x0558>;
 	};
 
-	func_mcbsp3_gfclk: func_mcbsp3_gfclk {
+	func_mcbsp3_gfclk: func_mcbsp3_gfclk@558 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&mcbsp3_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>;
@@ -552,7 +552,7 @@
 		reg = <0x0558>;
 	};
 
-	slimbus1_fclk_1: slimbus1_fclk_1 {
+	slimbus1_fclk_1: slimbus1_fclk_1@560 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&func_24m_clk>;
@@ -560,7 +560,7 @@
 		reg = <0x0560>;
 	};
 
-	slimbus1_fclk_0: slimbus1_fclk_0 {
+	slimbus1_fclk_0: slimbus1_fclk_0@560 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&abe_24m_fclk>;
@@ -568,7 +568,7 @@
 		reg = <0x0560>;
 	};
 
-	slimbus1_fclk_2: slimbus1_fclk_2 {
+	slimbus1_fclk_2: slimbus1_fclk_2@560 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&pad_clks_ck>;
@@ -576,7 +576,7 @@
 		reg = <0x0560>;
 	};
 
-	slimbus1_slimbus_clk: slimbus1_slimbus_clk {
+	slimbus1_slimbus_clk: slimbus1_slimbus_clk@560 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&slimbus_clk>;
@@ -584,7 +584,7 @@
 		reg = <0x0560>;
 	};
 
-	timer5_sync_mux: timer5_sync_mux {
+	timer5_sync_mux: timer5_sync_mux@568 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&syc_clk_div_ck>, <&sys_32k_ck>;
@@ -592,7 +592,7 @@
 		reg = <0x0568>;
 	};
 
-	timer6_sync_mux: timer6_sync_mux {
+	timer6_sync_mux: timer6_sync_mux@570 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&syc_clk_div_ck>, <&sys_32k_ck>;
@@ -600,7 +600,7 @@
 		reg = <0x0570>;
 	};
 
-	timer7_sync_mux: timer7_sync_mux {
+	timer7_sync_mux: timer7_sync_mux@578 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&syc_clk_div_ck>, <&sys_32k_ck>;
@@ -608,7 +608,7 @@
 		reg = <0x0578>;
 	};
 
-	timer8_sync_mux: timer8_sync_mux {
+	timer8_sync_mux: timer8_sync_mux@580 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&syc_clk_div_ck>, <&sys_32k_ck>;
@@ -623,7 +623,7 @@
 	};
 };
 &prm_clocks {
-	sys_clkin_ck: sys_clkin_ck {
+	sys_clkin_ck: sys_clkin_ck@110 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&virt_12000000_ck>, <&virt_13000000_ck>, <&virt_16800000_ck>, <&virt_19200000_ck>, <&virt_26000000_ck>, <&virt_27000000_ck>, <&virt_38400000_ck>;
@@ -631,7 +631,7 @@
 		ti,index-starts-at-one;
 	};
 
-	abe_dpll_bypass_clk_mux_ck: abe_dpll_bypass_clk_mux_ck {
+	abe_dpll_bypass_clk_mux_ck: abe_dpll_bypass_clk_mux_ck@108 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin_ck>, <&sys_32k_ck>;
@@ -639,7 +639,7 @@
 		reg = <0x0108>;
 	};
 
-	abe_dpll_refclk_mux_ck: abe_dpll_refclk_mux_ck {
+	abe_dpll_refclk_mux_ck: abe_dpll_refclk_mux_ck@10c {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin_ck>, <&sys_32k_ck>;
@@ -654,14 +654,14 @@
 		clock-div = <1>;
 	};
 
-	l4_wkup_clk_mux_ck: l4_wkup_clk_mux_ck {
+	l4_wkup_clk_mux_ck: l4_wkup_clk_mux_ck@108 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin_ck>, <&lp_clk_div_ck>;
 		reg = <0x0108>;
 	};
 
-	syc_clk_div_ck: syc_clk_div_ck {
+	syc_clk_div_ck: syc_clk_div_ck@100 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&sys_clkin_ck>;
@@ -669,7 +669,7 @@
 		ti,max-div = <2>;
 	};
 
-	gpio1_dbclk: gpio1_dbclk {
+	gpio1_dbclk: gpio1_dbclk@1838 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_32k_ck>;
@@ -677,7 +677,7 @@
 		reg = <0x1838>;
 	};
 
-	dmt1_clk_mux: dmt1_clk_mux {
+	dmt1_clk_mux: dmt1_clk_mux@1840 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin_ck>, <&sys_32k_ck>;
@@ -685,7 +685,7 @@
 		reg = <0x1840>;
 	};
 
-	usim_ck: usim_ck {
+	usim_ck: usim_ck@1858 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_per_m4x2_ck>;
@@ -694,7 +694,7 @@
 		ti,dividers = <14>, <18>;
 	};
 
-	usim_fclk: usim_fclk {
+	usim_fclk: usim_fclk@1858 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&usim_ck>;
@@ -702,7 +702,7 @@
 		reg = <0x1858>;
 	};
 
-	pmd_stm_clock_mux_ck: pmd_stm_clock_mux_ck {
+	pmd_stm_clock_mux_ck: pmd_stm_clock_mux_ck@1a20 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin_ck>, <&dpll_core_m6x2_ck>, <&tie_low_clock_ck>;
@@ -710,7 +710,7 @@
 		reg = <0x1a20>;
 	};
 
-	pmd_trace_clk_mux_ck: pmd_trace_clk_mux_ck {
+	pmd_trace_clk_mux_ck: pmd_trace_clk_mux_ck@1a20 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin_ck>, <&dpll_core_m6x2_ck>, <&tie_low_clock_ck>;
@@ -718,7 +718,7 @@
 		reg = <0x1a20>;
 	};
 
-	stm_clk_div_ck: stm_clk_div_ck {
+	stm_clk_div_ck: stm_clk_div_ck@1a20 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&pmd_stm_clock_mux_ck>;
@@ -728,7 +728,7 @@
 		ti,index-power-of-two;
 	};
 
-	trace_clk_div_div_ck: trace_clk_div_div_ck {
+	trace_clk_div_div_ck: trace_clk_div_div_ck@1a20 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&pmd_trace_clk_mux_ck>;
@@ -752,7 +752,7 @@
 };
 
 &cm2_clocks {
-	per_hsd_byp_clk_mux_ck: per_hsd_byp_clk_mux_ck {
+	per_hsd_byp_clk_mux_ck: per_hsd_byp_clk_mux_ck@14c {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin_ck>, <&per_hs_clk_div_ck>;
@@ -760,14 +760,14 @@
 		reg = <0x014c>;
 	};
 
-	dpll_per_ck: dpll_per_ck {
+	dpll_per_ck: dpll_per_ck@140 {
 		#clock-cells = <0>;
 		compatible = "ti,omap4-dpll-clock";
 		clocks = <&sys_clkin_ck>, <&per_hsd_byp_clk_mux_ck>;
 		reg = <0x0140>, <0x0144>, <0x014c>, <0x0148>;
 	};
 
-	dpll_per_m2_ck: dpll_per_m2_ck {
+	dpll_per_m2_ck: dpll_per_m2_ck@150 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_per_ck>;
@@ -776,14 +776,14 @@
 		ti,index-starts-at-one;
 	};
 
-	dpll_per_x2_ck: dpll_per_x2_ck {
+	dpll_per_x2_ck: dpll_per_x2_ck@150 {
 		#clock-cells = <0>;
 		compatible = "ti,omap4-dpll-x2-clock";
 		clocks = <&dpll_per_ck>;
 		reg = <0x0150>;
 	};
 
-	dpll_per_m2x2_ck: dpll_per_m2x2_ck {
+	dpll_per_m2x2_ck: dpll_per_m2x2_ck@150 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_per_x2_ck>;
@@ -794,7 +794,7 @@
 		ti,invert-autoidle-bit;
 	};
 
-	dpll_per_m3x2_gate_ck: dpll_per_m3x2_gate_ck {
+	dpll_per_m3x2_gate_ck: dpll_per_m3x2_gate_ck@154 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-no-wait-gate-clock";
 		clocks = <&dpll_per_x2_ck>;
@@ -802,7 +802,7 @@
 		reg = <0x0154>;
 	};
 
-	dpll_per_m3x2_div_ck: dpll_per_m3x2_div_ck {
+	dpll_per_m3x2_div_ck: dpll_per_m3x2_div_ck@154 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-divider-clock";
 		clocks = <&dpll_per_x2_ck>;
@@ -817,7 +817,7 @@
 		clocks = <&dpll_per_m3x2_gate_ck>, <&dpll_per_m3x2_div_ck>;
 	};
 
-	dpll_per_m4x2_ck: dpll_per_m4x2_ck {
+	dpll_per_m4x2_ck: dpll_per_m4x2_ck@158 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_per_x2_ck>;
@@ -828,7 +828,7 @@
 		ti,invert-autoidle-bit;
 	};
 
-	dpll_per_m5x2_ck: dpll_per_m5x2_ck {
+	dpll_per_m5x2_ck: dpll_per_m5x2_ck@15c {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_per_x2_ck>;
@@ -839,7 +839,7 @@
 		ti,invert-autoidle-bit;
 	};
 
-	dpll_per_m6x2_ck: dpll_per_m6x2_ck {
+	dpll_per_m6x2_ck: dpll_per_m6x2_ck@160 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_per_x2_ck>;
@@ -850,7 +850,7 @@
 		ti,invert-autoidle-bit;
 	};
 
-	dpll_per_m7x2_ck: dpll_per_m7x2_ck {
+	dpll_per_m7x2_ck: dpll_per_m7x2_ck@164 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_per_x2_ck>;
@@ -861,14 +861,14 @@
 		ti,invert-autoidle-bit;
 	};
 
-	dpll_usb_ck: dpll_usb_ck {
+	dpll_usb_ck: dpll_usb_ck@180 {
 		#clock-cells = <0>;
 		compatible = "ti,omap4-dpll-j-type-clock";
 		clocks = <&sys_clkin_ck>, <&usb_hs_clk_div_ck>;
 		reg = <0x0180>, <0x0184>, <0x018c>, <0x0188>;
 	};
 
-	dpll_usb_clkdcoldo_ck: dpll_usb_clkdcoldo_ck {
+	dpll_usb_clkdcoldo_ck: dpll_usb_clkdcoldo_ck@1b4 {
 		#clock-cells = <0>;
 		compatible = "ti,fixed-factor-clock";
 		clocks = <&dpll_usb_ck>;
@@ -879,7 +879,7 @@
 		ti,invert-autoidle-bit;
 	};
 
-	dpll_usb_m2_ck: dpll_usb_m2_ck {
+	dpll_usb_m2_ck: dpll_usb_m2_ck@190 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_usb_ck>;
@@ -890,7 +890,7 @@
 		ti,invert-autoidle-bit;
 	};
 
-	ducati_clk_mux_ck: ducati_clk_mux_ck {
+	ducati_clk_mux_ck: ducati_clk_mux_ck@100 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&div_core_ck>, <&dpll_per_m6x2_ck>;
@@ -921,7 +921,7 @@
 		clock-div = <8>;
 	};
 
-	func_48m_fclk: func_48m_fclk {
+	func_48m_fclk: func_48m_fclk@108 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_per_m2x2_ck>;
@@ -937,7 +937,7 @@
 		clock-div = <4>;
 	};
 
-	func_64m_fclk: func_64m_fclk {
+	func_64m_fclk: func_64m_fclk@108 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_per_m4x2_ck>;
@@ -945,7 +945,7 @@
 		ti,dividers = <2>, <4>;
 	};
 
-	func_96m_fclk: func_96m_fclk {
+	func_96m_fclk: func_96m_fclk@108 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_per_m2x2_ck>;
@@ -953,7 +953,7 @@
 		ti,dividers = <2>, <4>;
 	};
 
-	init_60m_fclk: init_60m_fclk {
+	init_60m_fclk: init_60m_fclk@104 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_usb_m2_ck>;
@@ -961,7 +961,7 @@
 		ti,dividers = <1>, <8>;
 	};
 
-	per_abe_nc_fclk: per_abe_nc_fclk {
+	per_abe_nc_fclk: per_abe_nc_fclk@108 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_abe_m2_ck>;
@@ -969,7 +969,7 @@
 		ti,max-div = <2>;
 	};
 
-	aes1_fck: aes1_fck {
+	aes1_fck: aes1_fck@15a0 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&l3_div_ck>;
@@ -977,7 +977,7 @@
 		reg = <0x15a0>;
 	};
 
-	aes2_fck: aes2_fck {
+	aes2_fck: aes2_fck@15a8 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&l3_div_ck>;
@@ -985,7 +985,7 @@
 		reg = <0x15a8>;
 	};
 
-	dss_sys_clk: dss_sys_clk {
+	dss_sys_clk: dss_sys_clk@1120 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&syc_clk_div_ck>;
@@ -993,7 +993,7 @@
 		reg = <0x1120>;
 	};
 
-	dss_tv_clk: dss_tv_clk {
+	dss_tv_clk: dss_tv_clk@1120 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&extalt_clkin_ck>;
@@ -1001,7 +1001,7 @@
 		reg = <0x1120>;
 	};
 
-	dss_dss_clk: dss_dss_clk {
+	dss_dss_clk: dss_dss_clk@1120 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&dpll_per_m5x2_ck>;
@@ -1010,7 +1010,7 @@
 		ti,set-rate-parent;
 	};
 
-	dss_48mhz_clk: dss_48mhz_clk {
+	dss_48mhz_clk: dss_48mhz_clk@1120 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&func_48mc_fclk>;
@@ -1018,7 +1018,7 @@
 		reg = <0x1120>;
 	};
 
-	fdif_fck: fdif_fck {
+	fdif_fck: fdif_fck@1028 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_per_m4x2_ck>;
@@ -1028,7 +1028,7 @@
 		ti,index-power-of-two;
 	};
 
-	gpio2_dbclk: gpio2_dbclk {
+	gpio2_dbclk: gpio2_dbclk@1460 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_32k_ck>;
@@ -1036,7 +1036,7 @@
 		reg = <0x1460>;
 	};
 
-	gpio3_dbclk: gpio3_dbclk {
+	gpio3_dbclk: gpio3_dbclk@1468 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_32k_ck>;
@@ -1044,7 +1044,7 @@
 		reg = <0x1468>;
 	};
 
-	gpio4_dbclk: gpio4_dbclk {
+	gpio4_dbclk: gpio4_dbclk@1470 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_32k_ck>;
@@ -1052,7 +1052,7 @@
 		reg = <0x1470>;
 	};
 
-	gpio5_dbclk: gpio5_dbclk {
+	gpio5_dbclk: gpio5_dbclk@1478 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_32k_ck>;
@@ -1060,7 +1060,7 @@
 		reg = <0x1478>;
 	};
 
-	gpio6_dbclk: gpio6_dbclk {
+	gpio6_dbclk: gpio6_dbclk@1480 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_32k_ck>;
@@ -1068,7 +1068,7 @@
 		reg = <0x1480>;
 	};
 
-	sgx_clk_mux: sgx_clk_mux {
+	sgx_clk_mux: sgx_clk_mux@1220 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&dpll_core_m7x2_ck>, <&dpll_per_m7x2_ck>;
@@ -1076,7 +1076,7 @@
 		reg = <0x1220>;
 	};
 
-	hsi_fck: hsi_fck {
+	hsi_fck: hsi_fck@1338 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_per_m2x2_ck>;
@@ -1086,7 +1086,7 @@
 		ti,index-power-of-two;
 	};
 
-	iss_ctrlclk: iss_ctrlclk {
+	iss_ctrlclk: iss_ctrlclk@1020 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&func_96m_fclk>;
@@ -1094,7 +1094,7 @@
 		reg = <0x1020>;
 	};
 
-	mcbsp4_sync_mux_ck: mcbsp4_sync_mux_ck {
+	mcbsp4_sync_mux_ck: mcbsp4_sync_mux_ck@14e0 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&func_96m_fclk>, <&per_abe_nc_fclk>;
@@ -1102,7 +1102,7 @@
 		reg = <0x14e0>;
 	};
 
-	per_mcbsp4_gfclk: per_mcbsp4_gfclk {
+	per_mcbsp4_gfclk: per_mcbsp4_gfclk@14e0 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&mcbsp4_sync_mux_ck>, <&pad_clks_ck>;
@@ -1110,7 +1110,7 @@
 		reg = <0x14e0>;
 	};
 
-	hsmmc1_fclk: hsmmc1_fclk {
+	hsmmc1_fclk: hsmmc1_fclk@1328 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&func_64m_fclk>, <&func_96m_fclk>;
@@ -1118,7 +1118,7 @@
 		reg = <0x1328>;
 	};
 
-	hsmmc2_fclk: hsmmc2_fclk {
+	hsmmc2_fclk: hsmmc2_fclk@1330 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&func_64m_fclk>, <&func_96m_fclk>;
@@ -1126,7 +1126,7 @@
 		reg = <0x1330>;
 	};
 
-	ocp2scp_usb_phy_phy_48m: ocp2scp_usb_phy_phy_48m {
+	ocp2scp_usb_phy_phy_48m: ocp2scp_usb_phy_phy_48m@13e0 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&func_48m_fclk>;
@@ -1134,7 +1134,7 @@
 		reg = <0x13e0>;
 	};
 
-	sha2md5_fck: sha2md5_fck {
+	sha2md5_fck: sha2md5_fck@15c8 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&l3_div_ck>;
@@ -1142,7 +1142,7 @@
 		reg = <0x15c8>;
 	};
 
-	slimbus2_fclk_1: slimbus2_fclk_1 {
+	slimbus2_fclk_1: slimbus2_fclk_1@1538 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&per_abe_24m_fclk>;
@@ -1150,7 +1150,7 @@
 		reg = <0x1538>;
 	};
 
-	slimbus2_fclk_0: slimbus2_fclk_0 {
+	slimbus2_fclk_0: slimbus2_fclk_0@1538 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&func_24mc_fclk>;
@@ -1158,7 +1158,7 @@
 		reg = <0x1538>;
 	};
 
-	slimbus2_slimbus_clk: slimbus2_slimbus_clk {
+	slimbus2_slimbus_clk: slimbus2_slimbus_clk@1538 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&pad_slimbus_core_clks_ck>;
@@ -1166,7 +1166,7 @@
 		reg = <0x1538>;
 	};
 
-	smartreflex_core_fck: smartreflex_core_fck {
+	smartreflex_core_fck: smartreflex_core_fck@638 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&l4_wkup_clk_mux_ck>;
@@ -1174,7 +1174,7 @@
 		reg = <0x0638>;
 	};
 
-	smartreflex_iva_fck: smartreflex_iva_fck {
+	smartreflex_iva_fck: smartreflex_iva_fck@630 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&l4_wkup_clk_mux_ck>;
@@ -1182,7 +1182,7 @@
 		reg = <0x0630>;
 	};
 
-	smartreflex_mpu_fck: smartreflex_mpu_fck {
+	smartreflex_mpu_fck: smartreflex_mpu_fck@628 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&l4_wkup_clk_mux_ck>;
@@ -1190,7 +1190,7 @@
 		reg = <0x0628>;
 	};
 
-	cm2_dm10_mux: cm2_dm10_mux {
+	cm2_dm10_mux: cm2_dm10_mux@1428 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin_ck>, <&sys_32k_ck>;
@@ -1198,7 +1198,7 @@
 		reg = <0x1428>;
 	};
 
-	cm2_dm11_mux: cm2_dm11_mux {
+	cm2_dm11_mux: cm2_dm11_mux@1430 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin_ck>, <&sys_32k_ck>;
@@ -1206,7 +1206,7 @@
 		reg = <0x1430>;
 	};
 
-	cm2_dm2_mux: cm2_dm2_mux {
+	cm2_dm2_mux: cm2_dm2_mux@1438 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin_ck>, <&sys_32k_ck>;
@@ -1214,7 +1214,7 @@
 		reg = <0x1438>;
 	};
 
-	cm2_dm3_mux: cm2_dm3_mux {
+	cm2_dm3_mux: cm2_dm3_mux@1440 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin_ck>, <&sys_32k_ck>;
@@ -1222,7 +1222,7 @@
 		reg = <0x1440>;
 	};
 
-	cm2_dm4_mux: cm2_dm4_mux {
+	cm2_dm4_mux: cm2_dm4_mux@1448 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin_ck>, <&sys_32k_ck>;
@@ -1230,7 +1230,7 @@
 		reg = <0x1448>;
 	};
 
-	cm2_dm9_mux: cm2_dm9_mux {
+	cm2_dm9_mux: cm2_dm9_mux@1450 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin_ck>, <&sys_32k_ck>;
@@ -1238,7 +1238,7 @@
 		reg = <0x1450>;
 	};
 
-	usb_host_fs_fck: usb_host_fs_fck {
+	usb_host_fs_fck: usb_host_fs_fck@13d0 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&func_48mc_fclk>;
@@ -1246,7 +1246,7 @@
 		reg = <0x13d0>;
 	};
 
-	utmi_p1_gfclk: utmi_p1_gfclk {
+	utmi_p1_gfclk: utmi_p1_gfclk@1358 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&init_60m_fclk>, <&xclk60mhsp1_ck>;
@@ -1254,7 +1254,7 @@
 		reg = <0x1358>;
 	};
 
-	usb_host_hs_utmi_p1_clk: usb_host_hs_utmi_p1_clk {
+	usb_host_hs_utmi_p1_clk: usb_host_hs_utmi_p1_clk@1358 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&utmi_p1_gfclk>;
@@ -1262,7 +1262,7 @@
 		reg = <0x1358>;
 	};
 
-	utmi_p2_gfclk: utmi_p2_gfclk {
+	utmi_p2_gfclk: utmi_p2_gfclk@1358 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&init_60m_fclk>, <&xclk60mhsp2_ck>;
@@ -1270,7 +1270,7 @@
 		reg = <0x1358>;
 	};
 
-	usb_host_hs_utmi_p2_clk: usb_host_hs_utmi_p2_clk {
+	usb_host_hs_utmi_p2_clk: usb_host_hs_utmi_p2_clk@1358 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&utmi_p2_gfclk>;
@@ -1278,7 +1278,7 @@
 		reg = <0x1358>;
 	};
 
-	usb_host_hs_utmi_p3_clk: usb_host_hs_utmi_p3_clk {
+	usb_host_hs_utmi_p3_clk: usb_host_hs_utmi_p3_clk@1358 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&init_60m_fclk>;
@@ -1286,7 +1286,7 @@
 		reg = <0x1358>;
 	};
 
-	usb_host_hs_hsic480m_p1_clk: usb_host_hs_hsic480m_p1_clk {
+	usb_host_hs_hsic480m_p1_clk: usb_host_hs_hsic480m_p1_clk@1358 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&dpll_usb_m2_ck>;
@@ -1294,7 +1294,7 @@
 		reg = <0x1358>;
 	};
 
-	usb_host_hs_hsic60m_p1_clk: usb_host_hs_hsic60m_p1_clk {
+	usb_host_hs_hsic60m_p1_clk: usb_host_hs_hsic60m_p1_clk@1358 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&init_60m_fclk>;
@@ -1302,7 +1302,7 @@
 		reg = <0x1358>;
 	};
 
-	usb_host_hs_hsic60m_p2_clk: usb_host_hs_hsic60m_p2_clk {
+	usb_host_hs_hsic60m_p2_clk: usb_host_hs_hsic60m_p2_clk@1358 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&init_60m_fclk>;
@@ -1310,7 +1310,7 @@
 		reg = <0x1358>;
 	};
 
-	usb_host_hs_hsic480m_p2_clk: usb_host_hs_hsic480m_p2_clk {
+	usb_host_hs_hsic480m_p2_clk: usb_host_hs_hsic480m_p2_clk@1358 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&dpll_usb_m2_ck>;
@@ -1318,7 +1318,7 @@
 		reg = <0x1358>;
 	};
 
-	usb_host_hs_func48mclk: usb_host_hs_func48mclk {
+	usb_host_hs_func48mclk: usb_host_hs_func48mclk@1358 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&func_48mc_fclk>;
@@ -1326,7 +1326,7 @@
 		reg = <0x1358>;
 	};
 
-	usb_host_hs_fck: usb_host_hs_fck {
+	usb_host_hs_fck: usb_host_hs_fck@1358 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&init_60m_fclk>;
@@ -1334,7 +1334,7 @@
 		reg = <0x1358>;
 	};
 
-	otg_60m_gfclk: otg_60m_gfclk {
+	otg_60m_gfclk: otg_60m_gfclk@1360 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&utmi_phy_clkout_ck>, <&xclk60motg_ck>;
@@ -1342,7 +1342,7 @@
 		reg = <0x1360>;
 	};
 
-	usb_otg_hs_xclk: usb_otg_hs_xclk {
+	usb_otg_hs_xclk: usb_otg_hs_xclk@1360 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&otg_60m_gfclk>;
@@ -1350,7 +1350,7 @@
 		reg = <0x1360>;
 	};
 
-	usb_otg_hs_ick: usb_otg_hs_ick {
+	usb_otg_hs_ick: usb_otg_hs_ick@1360 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&l3_div_ck>;
@@ -1358,7 +1358,7 @@
 		reg = <0x1360>;
 	};
 
-	usb_phy_cm_clk32k: usb_phy_cm_clk32k {
+	usb_phy_cm_clk32k: usb_phy_cm_clk32k@640 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_32k_ck>;
@@ -1366,7 +1366,7 @@
 		reg = <0x0640>;
 	};
 
-	usb_tll_hs_usb_ch2_clk: usb_tll_hs_usb_ch2_clk {
+	usb_tll_hs_usb_ch2_clk: usb_tll_hs_usb_ch2_clk@1368 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&init_60m_fclk>;
@@ -1374,7 +1374,7 @@
 		reg = <0x1368>;
 	};
 
-	usb_tll_hs_usb_ch0_clk: usb_tll_hs_usb_ch0_clk {
+	usb_tll_hs_usb_ch0_clk: usb_tll_hs_usb_ch0_clk@1368 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&init_60m_fclk>;
@@ -1382,7 +1382,7 @@
 		reg = <0x1368>;
 	};
 
-	usb_tll_hs_usb_ch1_clk: usb_tll_hs_usb_ch1_clk {
+	usb_tll_hs_usb_ch1_clk: usb_tll_hs_usb_ch1_clk@1368 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&init_60m_fclk>;
@@ -1390,7 +1390,7 @@
 		reg = <0x1368>;
 	};
 
-	usb_tll_hs_ick: usb_tll_hs_ick {
+	usb_tll_hs_ick: usb_tll_hs_ick@1368 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&l4_div_ck>;
@@ -1407,7 +1407,7 @@
 };
 
 &scrm_clocks {
-	auxclk0_src_gate_ck: auxclk0_src_gate_ck {
+	auxclk0_src_gate_ck: auxclk0_src_gate_ck@310 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-no-wait-gate-clock";
 		clocks = <&dpll_core_m3x2_ck>;
@@ -1415,7 +1415,7 @@
 		reg = <0x0310>;
 	};
 
-	auxclk0_src_mux_ck: auxclk0_src_mux_ck {
+	auxclk0_src_mux_ck: auxclk0_src_mux_ck@310 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&sys_clkin_ck>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>;
@@ -1429,7 +1429,7 @@
 		clocks = <&auxclk0_src_gate_ck>, <&auxclk0_src_mux_ck>;
 	};
 
-	auxclk0_ck: auxclk0_ck {
+	auxclk0_ck: auxclk0_ck@310 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&auxclk0_src_ck>;
@@ -1438,7 +1438,7 @@
 		reg = <0x0310>;
 	};
 
-	auxclk1_src_gate_ck: auxclk1_src_gate_ck {
+	auxclk1_src_gate_ck: auxclk1_src_gate_ck@314 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-no-wait-gate-clock";
 		clocks = <&dpll_core_m3x2_ck>;
@@ -1446,7 +1446,7 @@
 		reg = <0x0314>;
 	};
 
-	auxclk1_src_mux_ck: auxclk1_src_mux_ck {
+	auxclk1_src_mux_ck: auxclk1_src_mux_ck@314 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&sys_clkin_ck>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>;
@@ -1460,7 +1460,7 @@
 		clocks = <&auxclk1_src_gate_ck>, <&auxclk1_src_mux_ck>;
 	};
 
-	auxclk1_ck: auxclk1_ck {
+	auxclk1_ck: auxclk1_ck@314 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&auxclk1_src_ck>;
@@ -1469,7 +1469,7 @@
 		reg = <0x0314>;
 	};
 
-	auxclk2_src_gate_ck: auxclk2_src_gate_ck {
+	auxclk2_src_gate_ck: auxclk2_src_gate_ck@318 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-no-wait-gate-clock";
 		clocks = <&dpll_core_m3x2_ck>;
@@ -1477,7 +1477,7 @@
 		reg = <0x0318>;
 	};
 
-	auxclk2_src_mux_ck: auxclk2_src_mux_ck {
+	auxclk2_src_mux_ck: auxclk2_src_mux_ck@318 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&sys_clkin_ck>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>;
@@ -1491,7 +1491,7 @@
 		clocks = <&auxclk2_src_gate_ck>, <&auxclk2_src_mux_ck>;
 	};
 
-	auxclk2_ck: auxclk2_ck {
+	auxclk2_ck: auxclk2_ck@318 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&auxclk2_src_ck>;
@@ -1500,7 +1500,7 @@
 		reg = <0x0318>;
 	};
 
-	auxclk3_src_gate_ck: auxclk3_src_gate_ck {
+	auxclk3_src_gate_ck: auxclk3_src_gate_ck@31c {
 		#clock-cells = <0>;
 		compatible = "ti,composite-no-wait-gate-clock";
 		clocks = <&dpll_core_m3x2_ck>;
@@ -1508,7 +1508,7 @@
 		reg = <0x031c>;
 	};
 
-	auxclk3_src_mux_ck: auxclk3_src_mux_ck {
+	auxclk3_src_mux_ck: auxclk3_src_mux_ck@31c {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&sys_clkin_ck>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>;
@@ -1522,7 +1522,7 @@
 		clocks = <&auxclk3_src_gate_ck>, <&auxclk3_src_mux_ck>;
 	};
 
-	auxclk3_ck: auxclk3_ck {
+	auxclk3_ck: auxclk3_ck@31c {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&auxclk3_src_ck>;
@@ -1531,7 +1531,7 @@
 		reg = <0x031c>;
 	};
 
-	auxclk4_src_gate_ck: auxclk4_src_gate_ck {
+	auxclk4_src_gate_ck: auxclk4_src_gate_ck@320 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-no-wait-gate-clock";
 		clocks = <&dpll_core_m3x2_ck>;
@@ -1539,7 +1539,7 @@
 		reg = <0x0320>;
 	};
 
-	auxclk4_src_mux_ck: auxclk4_src_mux_ck {
+	auxclk4_src_mux_ck: auxclk4_src_mux_ck@320 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&sys_clkin_ck>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>;
@@ -1553,7 +1553,7 @@
 		clocks = <&auxclk4_src_gate_ck>, <&auxclk4_src_mux_ck>;
 	};
 
-	auxclk4_ck: auxclk4_ck {
+	auxclk4_ck: auxclk4_ck@320 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&auxclk4_src_ck>;
@@ -1562,7 +1562,7 @@
 		reg = <0x0320>;
 	};
 
-	auxclk5_src_gate_ck: auxclk5_src_gate_ck {
+	auxclk5_src_gate_ck: auxclk5_src_gate_ck@324 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-no-wait-gate-clock";
 		clocks = <&dpll_core_m3x2_ck>;
@@ -1570,7 +1570,7 @@
 		reg = <0x0324>;
 	};
 
-	auxclk5_src_mux_ck: auxclk5_src_mux_ck {
+	auxclk5_src_mux_ck: auxclk5_src_mux_ck@324 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&sys_clkin_ck>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>;
@@ -1584,7 +1584,7 @@
 		clocks = <&auxclk5_src_gate_ck>, <&auxclk5_src_mux_ck>;
 	};
 
-	auxclk5_ck: auxclk5_ck {
+	auxclk5_ck: auxclk5_ck@324 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&auxclk5_src_ck>;
@@ -1593,7 +1593,7 @@
 		reg = <0x0324>;
 	};
 
-	auxclkreq0_ck: auxclkreq0_ck {
+	auxclkreq0_ck: auxclkreq0_ck@210 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>, <&auxclk5_ck>;
@@ -1601,7 +1601,7 @@
 		reg = <0x0210>;
 	};
 
-	auxclkreq1_ck: auxclkreq1_ck {
+	auxclkreq1_ck: auxclkreq1_ck@214 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>, <&auxclk5_ck>;
@@ -1609,7 +1609,7 @@
 		reg = <0x0214>;
 	};
 
-	auxclkreq2_ck: auxclkreq2_ck {
+	auxclkreq2_ck: auxclkreq2_ck@218 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>, <&auxclk5_ck>;
@@ -1617,7 +1617,7 @@
 		reg = <0x0218>;
 	};
 
-	auxclkreq3_ck: auxclkreq3_ck {
+	auxclkreq3_ck: auxclkreq3_ck@21c {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>, <&auxclk5_ck>;
@@ -1625,7 +1625,7 @@
 		reg = <0x021c>;
 	};
 
-	auxclkreq4_ck: auxclkreq4_ck {
+	auxclkreq4_ck: auxclkreq4_ck@220 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>, <&auxclk5_ck>;
@@ -1633,7 +1633,7 @@
 		reg = <0x0220>;
 	};
 
-	auxclkreq5_ck: auxclkreq5_ck {
+	auxclkreq5_ck: auxclkreq5_ck@224 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>, <&auxclk5_ck>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/omap4.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/omap4.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/omap4.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/omap4.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -198,7 +198,7 @@
 					#size-cells = <1>;
 					ranges = <0 0x5a0 0x170>;
 
-					pbias_regulator: pbias_regulator {
+					pbias_regulator: pbias_regulator@60 {
 						compatible = "ti,pbias-omap4", "ti,pbias-omap";
 						reg = <0x60 0x4>;
 						syscon = <&omap4_padconf_global>;
@@ -370,6 +370,10 @@
 			ti,no-idle-on-init;
 			clocks = <&l3_div_ck>;
 			clock-names = "fck";
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			gpio-controller;
+			#gpio-cells = <2>;
 		};
 
 		uart1: serial@4806a000 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/omap4-kc1.dts linux-libre-4.7-gnu/arch/arm/boot/dts/omap4-kc1.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/omap4-kc1.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/omap4-kc1.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2016 Paul Kocialkowski <contact@paulk.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+#include "omap443x.dtsi"
+
+/ {
+	model = "Amazon Kindle Fire (first generation)";
+	compatible = "amazon,omap4-kc1", "ti,omap4430", "ti,omap4";
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x20000000>; /* 512 MB */
+	};
+
+	pwmleds {
+		compatible = "pwm-leds";
+
+		green {
+			label = "green";
+			pwms = <&twl_pwm 0 7812500>;
+			max-brightness = <127>;
+		};
+
+		orange {
+			label = "orange";
+			pwms = <&twl_pwm 1 7812500>;
+			max-brightness = <127>;
+		};
+	};
+};
+
+&omap4_pmx_core {
+	pinctrl-names = "default";
+
+	uart3_pins: pinmux_uart3_pins {
+		pinctrl-single,pins = <
+			OMAP4_IOPAD(0x144, PIN_INPUT | MUX_MODE0)		/* uart3_rx_irrx */
+			OMAP4_IOPAD(0x146, PIN_OUTPUT | MUX_MODE0)		/* uart3_tx_irtx */
+		>;
+	};
+
+	i2c1_pins: pinmux_i2c1_pins {
+		pinctrl-single,pins = <
+			OMAP4_IOPAD(0x122, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c1_scl */
+			OMAP4_IOPAD(0x124, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c1_sda */
+		>;
+	};
+
+	i2c2_pins: pinmux_i2c2_pins {
+		pinctrl-single,pins = <
+			OMAP4_IOPAD(0x126, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c2_scl */
+			OMAP4_IOPAD(0x128, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c2_sda */
+		>;
+	};
+
+	i2c3_pins: pinmux_i2c3_pins {
+		pinctrl-single,pins = <
+			OMAP4_IOPAD(0x12a, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c3_scl */
+			OMAP4_IOPAD(0x12c, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c3_sda */
+		>;
+	};
+
+	i2c4_pins: pinmux_i2c4_pins {
+		pinctrl-single,pins = <
+			OMAP4_IOPAD(0x12e, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c4_scl */
+			OMAP4_IOPAD(0x130, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c4_sda */
+		>;
+	};
+
+	mmc2_pins: pinmux_mmc2_pins {
+		pinctrl-single,pins = <
+			OMAP4_IOPAD(0x040, PIN_INPUT_PULLUP | MUX_MODE1)	/* sdmmc2_dat0 */
+			OMAP4_IOPAD(0x042, PIN_INPUT_PULLUP | MUX_MODE1)	/* sdmmc2_dat1 */
+			OMAP4_IOPAD(0x044, PIN_INPUT_PULLUP | MUX_MODE1)	/* sdmmc2_dat2 */
+			OMAP4_IOPAD(0x046, PIN_INPUT_PULLUP | MUX_MODE1)	/* sdmmc2_dat3 */
+			OMAP4_IOPAD(0x048, PIN_INPUT_PULLUP | MUX_MODE1)	/* sdmmc2_dat4 */
+			OMAP4_IOPAD(0x04a, PIN_INPUT_PULLUP | MUX_MODE1)	/* sdmmc2_dat5 */
+			OMAP4_IOPAD(0x04c, PIN_INPUT_PULLUP | MUX_MODE1)	/* sdmmc2_dat6 */
+			OMAP4_IOPAD(0x04e, PIN_INPUT_PULLUP | MUX_MODE1)	/* sdmmc2_dat7 */
+			OMAP4_IOPAD(0x082, PIN_INPUT_PULLUP | MUX_MODE1)	/* sdmmc2_clk */
+			OMAP4_IOPAD(0x084, PIN_INPUT_PULLUP | MUX_MODE1)	/* sdmmc2_cmd */
+		>;
+	};
+
+	usb_otg_hs_pins: pinmux_usb_otg_hs_pins {
+		pinctrl-single,pins = <
+			OMAP4_IOPAD(0x194, PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* usba0_otg_ce */
+			OMAP4_IOPAD(0x196, PIN_INPUT | MUX_MODE0)		/* usba0_otg_dp */
+			OMAP4_IOPAD(0x198, PIN_INPUT | MUX_MODE0)		/* usba0_otg_dm */
+		>;
+	};
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart3_pins>;
+
+	interrupts-extended = <&wakeupgen GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH
+			       &omap4_pmx_core OMAP4_UART3_RX>;
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
+
+	clock-frequency = <400000>;
+
+	twl: twl@48 {
+		reg = <0x48>;
+		/* IRQ# = 7 */
+		interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; /* IRQ_SYS_1N cascaded to gic */
+
+		twl_power: power {
+			compatible = "ti,twl6030-power";
+			ti,system-power-controller;
+		};
+	};
+};
+
+&i2c2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c2_pins>;
+
+	clock-frequency = <400000>;
+};
+
+&i2c3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c3_pins>;
+
+	clock-frequency = <400000>;
+};
+
+&i2c4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c4_pins>;
+
+	clock-frequency = <400000>;
+};
+
+&mmc1 {
+	status = "disabled";
+};
+
+&mmc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc2_pins>;
+
+	vmmc-supply = <&vaux1>;
+	ti,non-removable;
+	bus-width = <8>;
+};
+
+&mmc3 {
+	status = "disabled";
+};
+
+&mmc4 {
+	status = "disabled";
+};
+
+&usb_otg_hs {
+	pinctrl-names = "default";
+	pinctrl-0 = <&usb_otg_hs_pins>;
+
+	interface-type = <1>;
+	mode = <3>;
+	power = <50>;
+};
+
+#include "twl6030.dtsi"
+#include "twl6030_omap4.dtsi"
+
+&twl_usb_comparator {
+	usb-supply = <&vusb>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/omap4-var-som-om44.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/omap4-var-som-om44.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/omap4-var-som-om44.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/omap4-var-som-om44.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -17,7 +17,7 @@
 		reg = <0x80000000 0x40000000>; /* 1 GB */
 	};
 
-	sound: sound@0 {
+	sound: sound {
 		compatible = "ti,abe-twl6040";
 		ti,model = "VAR-SOM-OM44";
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/omap54xx-clocks.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/omap54xx-clocks.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/omap54xx-clocks.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/omap54xx-clocks.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -14,7 +14,7 @@
 		clock-frequency = <12000000>;
 	};
 
-	pad_clks_ck: pad_clks_ck {
+	pad_clks_ck: pad_clks_ck@108 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&pad_clks_src_ck>;
@@ -34,7 +34,7 @@
 		clock-frequency = <12000000>;
 	};
 
-	slimbus_clk: slimbus_clk {
+	slimbus_clk: slimbus_clk@108 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&slimbus_src_clk>;
@@ -102,7 +102,7 @@
 		clock-frequency = <60000000>;
 	};
 
-	dpll_abe_ck: dpll_abe_ck {
+	dpll_abe_ck: dpll_abe_ck@1e0 {
 		#clock-cells = <0>;
 		compatible = "ti,omap4-dpll-m4xen-clock";
 		clocks = <&abe_dpll_clk_mux>, <&abe_dpll_bypass_clk_mux>;
@@ -115,7 +115,7 @@
 		clocks = <&dpll_abe_ck>;
 	};
 
-	dpll_abe_m2x2_ck: dpll_abe_m2x2_ck {
+	dpll_abe_m2x2_ck: dpll_abe_m2x2_ck@1f0 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_abe_x2_ck>;
@@ -132,7 +132,7 @@
 		clock-div = <8>;
 	};
 
-	abe_clk: abe_clk {
+	abe_clk: abe_clk@108 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_abe_m2x2_ck>;
@@ -141,7 +141,7 @@
 		ti,index-power-of-two;
 	};
 
-	abe_iclk: abe_iclk {
+	abe_iclk: abe_iclk@528 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&aess_fclk>;
@@ -158,7 +158,7 @@
 		clock-div = <16>;
 	};
 
-	dpll_abe_m3x2_ck: dpll_abe_m3x2_ck {
+	dpll_abe_m3x2_ck: dpll_abe_m3x2_ck@1f4 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_abe_x2_ck>;
@@ -167,7 +167,7 @@
 		ti,index-starts-at-one;
 	};
 
-	dpll_core_byp_mux: dpll_core_byp_mux {
+	dpll_core_byp_mux: dpll_core_byp_mux@12c {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin>, <&dpll_abe_m3x2_ck>;
@@ -175,7 +175,7 @@
 		reg = <0x012c>;
 	};
 
-	dpll_core_ck: dpll_core_ck {
+	dpll_core_ck: dpll_core_ck@120 {
 		#clock-cells = <0>;
 		compatible = "ti,omap4-dpll-core-clock";
 		clocks = <&sys_clkin>, <&dpll_core_byp_mux>;
@@ -188,7 +188,7 @@
 		clocks = <&dpll_core_ck>;
 	};
 
-	dpll_core_h21x2_ck: dpll_core_h21x2_ck {
+	dpll_core_h21x2_ck: dpll_core_h21x2_ck@150 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_core_x2_ck>;
@@ -213,7 +213,7 @@
 		clock-div = <2>;
 	};
 
-	dpll_core_h11x2_ck: dpll_core_h11x2_ck {
+	dpll_core_h11x2_ck: dpll_core_h11x2_ck@138 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_core_x2_ck>;
@@ -222,7 +222,7 @@
 		ti,index-starts-at-one;
 	};
 
-	dpll_core_h12x2_ck: dpll_core_h12x2_ck {
+	dpll_core_h12x2_ck: dpll_core_h12x2_ck@13c {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_core_x2_ck>;
@@ -231,7 +231,7 @@
 		ti,index-starts-at-one;
 	};
 
-	dpll_core_h13x2_ck: dpll_core_h13x2_ck {
+	dpll_core_h13x2_ck: dpll_core_h13x2_ck@140 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_core_x2_ck>;
@@ -240,7 +240,7 @@
 		ti,index-starts-at-one;
 	};
 
-	dpll_core_h14x2_ck: dpll_core_h14x2_ck {
+	dpll_core_h14x2_ck: dpll_core_h14x2_ck@144 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_core_x2_ck>;
@@ -249,7 +249,7 @@
 		ti,index-starts-at-one;
 	};
 
-	dpll_core_h22x2_ck: dpll_core_h22x2_ck {
+	dpll_core_h22x2_ck: dpll_core_h22x2_ck@154 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_core_x2_ck>;
@@ -258,7 +258,7 @@
 		ti,index-starts-at-one;
 	};
 
-	dpll_core_h23x2_ck: dpll_core_h23x2_ck {
+	dpll_core_h23x2_ck: dpll_core_h23x2_ck@158 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_core_x2_ck>;
@@ -267,7 +267,7 @@
 		ti,index-starts-at-one;
 	};
 
-	dpll_core_h24x2_ck: dpll_core_h24x2_ck {
+	dpll_core_h24x2_ck: dpll_core_h24x2_ck@15c {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_core_x2_ck>;
@@ -276,7 +276,7 @@
 		ti,index-starts-at-one;
 	};
 
-	dpll_core_m2_ck: dpll_core_m2_ck {
+	dpll_core_m2_ck: dpll_core_m2_ck@130 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_core_ck>;
@@ -285,7 +285,7 @@
 		ti,index-starts-at-one;
 	};
 
-	dpll_core_m3x2_ck: dpll_core_m3x2_ck {
+	dpll_core_m3x2_ck: dpll_core_m3x2_ck@134 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_core_x2_ck>;
@@ -302,7 +302,7 @@
 		clock-div = <1>;
 	};
 
-	dpll_iva_byp_mux: dpll_iva_byp_mux {
+	dpll_iva_byp_mux: dpll_iva_byp_mux@1ac {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin>, <&iva_dpll_hs_clk_div>;
@@ -310,7 +310,7 @@
 		reg = <0x01ac>;
 	};
 
-	dpll_iva_ck: dpll_iva_ck {
+	dpll_iva_ck: dpll_iva_ck@1a0 {
 		#clock-cells = <0>;
 		compatible = "ti,omap4-dpll-clock";
 		clocks = <&sys_clkin>, <&dpll_iva_byp_mux>;
@@ -323,7 +323,7 @@
 		clocks = <&dpll_iva_ck>;
 	};
 
-	dpll_iva_h11x2_ck: dpll_iva_h11x2_ck {
+	dpll_iva_h11x2_ck: dpll_iva_h11x2_ck@1b8 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_iva_x2_ck>;
@@ -332,7 +332,7 @@
 		ti,index-starts-at-one;
 	};
 
-	dpll_iva_h12x2_ck: dpll_iva_h12x2_ck {
+	dpll_iva_h12x2_ck: dpll_iva_h12x2_ck@1bc {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_iva_x2_ck>;
@@ -349,14 +349,14 @@
 		clock-div = <1>;
 	};
 
-	dpll_mpu_ck: dpll_mpu_ck {
+	dpll_mpu_ck: dpll_mpu_ck@160 {
 		#clock-cells = <0>;
 		compatible = "ti,omap5-mpu-dpll-clock";
 		clocks = <&sys_clkin>, <&mpu_dpll_hs_clk_div>;
 		reg = <0x0160>, <0x0164>, <0x016c>, <0x0168>;
 	};
 
-	dpll_mpu_m2_ck: dpll_mpu_m2_ck {
+	dpll_mpu_m2_ck: dpll_mpu_m2_ck@170 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_mpu_ck>;
@@ -381,7 +381,7 @@
 		clock-div = <3>;
 	};
 
-	l3_iclk_div: l3_iclk_div {
+	l3_iclk_div: l3_iclk_div@100 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		ti,max-div = <2>;
@@ -399,7 +399,7 @@
 		clock-div = <1>;
 	};
 
-	l4_root_clk_div: l4_root_clk_div {
+	l4_root_clk_div: l4_root_clk_div@100 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		ti,max-div = <2>;
@@ -409,7 +409,7 @@
 		ti,index-power-of-two;
 	};
 
-	slimbus1_slimbus_clk: slimbus1_slimbus_clk {
+	slimbus1_slimbus_clk: slimbus1_slimbus_clk@560 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&slimbus_clk>;
@@ -417,7 +417,7 @@
 		reg = <0x0560>;
 	};
 
-	aess_fclk: aess_fclk {
+	aess_fclk: aess_fclk@528 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&abe_clk>;
@@ -426,7 +426,7 @@
 		reg = <0x0528>;
 	};
 
-	dmic_sync_mux_ck: dmic_sync_mux_ck {
+	dmic_sync_mux_ck: dmic_sync_mux_ck@538 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&abe_24m_fclk>, <&dss_syc_gfclk_div>, <&func_24m_clk>;
@@ -434,7 +434,7 @@
 		reg = <0x0538>;
 	};
 
-	dmic_gfclk: dmic_gfclk {
+	dmic_gfclk: dmic_gfclk@538 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&dmic_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>;
@@ -442,7 +442,7 @@
 		reg = <0x0538>;
 	};
 
-	mcasp_sync_mux_ck: mcasp_sync_mux_ck {
+	mcasp_sync_mux_ck: mcasp_sync_mux_ck@540 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&abe_24m_fclk>, <&dss_syc_gfclk_div>, <&func_24m_clk>;
@@ -450,7 +450,7 @@
 		reg = <0x0540>;
 	};
 
-	mcasp_gfclk: mcasp_gfclk {
+	mcasp_gfclk: mcasp_gfclk@540 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&mcasp_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>;
@@ -458,7 +458,7 @@
 		reg = <0x0540>;
 	};
 
-	mcbsp1_sync_mux_ck: mcbsp1_sync_mux_ck {
+	mcbsp1_sync_mux_ck: mcbsp1_sync_mux_ck@548 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&abe_24m_fclk>, <&dss_syc_gfclk_div>, <&func_24m_clk>;
@@ -466,7 +466,7 @@
 		reg = <0x0548>;
 	};
 
-	mcbsp1_gfclk: mcbsp1_gfclk {
+	mcbsp1_gfclk: mcbsp1_gfclk@548 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&mcbsp1_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>;
@@ -474,7 +474,7 @@
 		reg = <0x0548>;
 	};
 
-	mcbsp2_sync_mux_ck: mcbsp2_sync_mux_ck {
+	mcbsp2_sync_mux_ck: mcbsp2_sync_mux_ck@550 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&abe_24m_fclk>, <&dss_syc_gfclk_div>, <&func_24m_clk>;
@@ -482,7 +482,7 @@
 		reg = <0x0550>;
 	};
 
-	mcbsp2_gfclk: mcbsp2_gfclk {
+	mcbsp2_gfclk: mcbsp2_gfclk@550 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&mcbsp2_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>;
@@ -490,7 +490,7 @@
 		reg = <0x0550>;
 	};
 
-	mcbsp3_sync_mux_ck: mcbsp3_sync_mux_ck {
+	mcbsp3_sync_mux_ck: mcbsp3_sync_mux_ck@558 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&abe_24m_fclk>, <&dss_syc_gfclk_div>, <&func_24m_clk>;
@@ -498,7 +498,7 @@
 		reg = <0x0558>;
 	};
 
-	mcbsp3_gfclk: mcbsp3_gfclk {
+	mcbsp3_gfclk: mcbsp3_gfclk@558 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&mcbsp3_sync_mux_ck>, <&pad_clks_ck>, <&slimbus_clk>;
@@ -506,7 +506,7 @@
 		reg = <0x0558>;
 	};
 
-	timer5_gfclk_mux: timer5_gfclk_mux {
+	timer5_gfclk_mux: timer5_gfclk_mux@568 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&dss_syc_gfclk_div>, <&sys_32k_ck>;
@@ -514,7 +514,7 @@
 		reg = <0x0568>;
 	};
 
-	timer6_gfclk_mux: timer6_gfclk_mux {
+	timer6_gfclk_mux: timer6_gfclk_mux@570 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&dss_syc_gfclk_div>, <&sys_32k_ck>;
@@ -522,7 +522,7 @@
 		reg = <0x0570>;
 	};
 
-	timer7_gfclk_mux: timer7_gfclk_mux {
+	timer7_gfclk_mux: timer7_gfclk_mux@578 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&dss_syc_gfclk_div>, <&sys_32k_ck>;
@@ -530,7 +530,7 @@
 		reg = <0x0578>;
 	};
 
-	timer8_gfclk_mux: timer8_gfclk_mux {
+	timer8_gfclk_mux: timer8_gfclk_mux@580 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&dss_syc_gfclk_div>, <&sys_32k_ck>;
@@ -545,7 +545,7 @@
 	};
 };
 &prm_clocks {
-	sys_clkin: sys_clkin {
+	sys_clkin: sys_clkin@110 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&virt_12000000_ck>, <&virt_13000000_ck>, <&virt_16800000_ck>, <&virt_19200000_ck>, <&virt_26000000_ck>, <&virt_27000000_ck>, <&virt_38400000_ck>;
@@ -553,14 +553,14 @@
 		ti,index-starts-at-one;
 	};
 
-	abe_dpll_bypass_clk_mux: abe_dpll_bypass_clk_mux {
+	abe_dpll_bypass_clk_mux: abe_dpll_bypass_clk_mux@108 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin>, <&sys_32k_ck>;
 		reg = <0x0108>;
 	};
 
-	abe_dpll_clk_mux: abe_dpll_clk_mux {
+	abe_dpll_clk_mux: abe_dpll_clk_mux@10c {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin>, <&sys_32k_ck>;
@@ -583,7 +583,7 @@
 		clock-div = <1>;
 	};
 
-	wkupaon_iclk_mux: wkupaon_iclk_mux {
+	wkupaon_iclk_mux: wkupaon_iclk_mux@108 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin>, <&abe_lp_clk_div>;
@@ -598,7 +598,7 @@
 		clock-div = <1>;
 	};
 
-	gpio1_dbclk: gpio1_dbclk {
+	gpio1_dbclk: gpio1_dbclk@1938 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_32k_ck>;
@@ -606,7 +606,7 @@
 		reg = <0x1938>;
 	};
 
-	timer1_gfclk_mux: timer1_gfclk_mux {
+	timer1_gfclk_mux: timer1_gfclk_mux@1940 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin>, <&sys_32k_ck>;
@@ -616,7 +616,7 @@
 };
 &cm_core_clocks {
 
-	dpll_per_byp_mux: dpll_per_byp_mux {
+	dpll_per_byp_mux: dpll_per_byp_mux@14c {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin>, <&per_dpll_hs_clk_div>;
@@ -624,7 +624,7 @@
 		reg = <0x014c>;
 	};
 
-	dpll_per_ck: dpll_per_ck {
+	dpll_per_ck: dpll_per_ck@140 {
 		#clock-cells = <0>;
 		compatible = "ti,omap4-dpll-clock";
 		clocks = <&sys_clkin>, <&dpll_per_byp_mux>;
@@ -637,7 +637,7 @@
 		clocks = <&dpll_per_ck>;
 	};
 
-	dpll_per_h11x2_ck: dpll_per_h11x2_ck {
+	dpll_per_h11x2_ck: dpll_per_h11x2_ck@158 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_per_x2_ck>;
@@ -646,7 +646,7 @@
 		ti,index-starts-at-one;
 	};
 
-	dpll_per_h12x2_ck: dpll_per_h12x2_ck {
+	dpll_per_h12x2_ck: dpll_per_h12x2_ck@15c {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_per_x2_ck>;
@@ -655,7 +655,7 @@
 		ti,index-starts-at-one;
 	};
 
-	dpll_per_h14x2_ck: dpll_per_h14x2_ck {
+	dpll_per_h14x2_ck: dpll_per_h14x2_ck@164 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_per_x2_ck>;
@@ -664,7 +664,7 @@
 		ti,index-starts-at-one;
 	};
 
-	dpll_per_m2_ck: dpll_per_m2_ck {
+	dpll_per_m2_ck: dpll_per_m2_ck@150 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_per_ck>;
@@ -673,7 +673,7 @@
 		ti,index-starts-at-one;
 	};
 
-	dpll_per_m2x2_ck: dpll_per_m2x2_ck {
+	dpll_per_m2x2_ck: dpll_per_m2x2_ck@150 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_per_x2_ck>;
@@ -682,7 +682,7 @@
 		ti,index-starts-at-one;
 	};
 
-	dpll_per_m3x2_ck: dpll_per_m3x2_ck {
+	dpll_per_m3x2_ck: dpll_per_m3x2_ck@154 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_per_x2_ck>;
@@ -691,7 +691,7 @@
 		ti,index-starts-at-one;
 	};
 
-	dpll_unipro1_ck: dpll_unipro1_ck {
+	dpll_unipro1_ck: dpll_unipro1_ck@200 {
 		#clock-cells = <0>;
 		compatible = "ti,omap4-dpll-clock";
 		clocks = <&sys_clkin>, <&sys_clkin>;
@@ -706,7 +706,7 @@
 		clock-div = <1>;
 	};
 
-	dpll_unipro1_m2_ck: dpll_unipro1_m2_ck {
+	dpll_unipro1_m2_ck: dpll_unipro1_m2_ck@210 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_unipro1_ck>;
@@ -715,7 +715,7 @@
 		ti,index-starts-at-one;
 	};
 
-	dpll_unipro2_ck: dpll_unipro2_ck {
+	dpll_unipro2_ck: dpll_unipro2_ck@1c0 {
 		#clock-cells = <0>;
 		compatible = "ti,omap4-dpll-clock";
 		clocks = <&sys_clkin>, <&sys_clkin>;
@@ -730,7 +730,7 @@
 		clock-div = <1>;
 	};
 
-	dpll_unipro2_m2_ck: dpll_unipro2_m2_ck {
+	dpll_unipro2_m2_ck: dpll_unipro2_m2_ck@1d0 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_unipro2_ck>;
@@ -739,7 +739,7 @@
 		ti,index-starts-at-one;
 	};
 
-	dpll_usb_byp_mux: dpll_usb_byp_mux {
+	dpll_usb_byp_mux: dpll_usb_byp_mux@18c {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin>, <&usb_dpll_hs_clk_div>;
@@ -747,7 +747,7 @@
 		reg = <0x018c>;
 	};
 
-	dpll_usb_ck: dpll_usb_ck {
+	dpll_usb_ck: dpll_usb_ck@180 {
 		#clock-cells = <0>;
 		compatible = "ti,omap4-dpll-j-type-clock";
 		clocks = <&sys_clkin>, <&dpll_usb_byp_mux>;
@@ -762,7 +762,7 @@
 		clock-div = <1>;
 	};
 
-	dpll_usb_m2_ck: dpll_usb_m2_ck {
+	dpll_usb_m2_ck: dpll_usb_m2_ck@190 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_usb_ck>;
@@ -811,7 +811,7 @@
 		clock-div = <2>;
 	};
 
-	l3init_60m_fclk: l3init_60m_fclk {
+	l3init_60m_fclk: l3init_60m_fclk@104 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_usb_m2_ck>;
@@ -819,7 +819,7 @@
 		ti,dividers = <1>, <8>;
 	};
 
-	dss_32khz_clk: dss_32khz_clk {
+	dss_32khz_clk: dss_32khz_clk@1420 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_32k_ck>;
@@ -827,7 +827,7 @@
 		reg = <0x1420>;
 	};
 
-	dss_48mhz_clk: dss_48mhz_clk {
+	dss_48mhz_clk: dss_48mhz_clk@1420 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&func_48m_fclk>;
@@ -835,7 +835,7 @@
 		reg = <0x1420>;
 	};
 
-	dss_dss_clk: dss_dss_clk {
+	dss_dss_clk: dss_dss_clk@1420 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&dpll_per_h12x2_ck>;
@@ -844,7 +844,7 @@
 		ti,set-rate-parent;
 	};
 
-	dss_sys_clk: dss_sys_clk {
+	dss_sys_clk: dss_sys_clk@1420 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&dss_syc_gfclk_div>;
@@ -852,7 +852,7 @@
 		reg = <0x1420>;
 	};
 
-	gpio2_dbclk: gpio2_dbclk {
+	gpio2_dbclk: gpio2_dbclk@1060 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_32k_ck>;
@@ -860,7 +860,7 @@
 		reg = <0x1060>;
 	};
 
-	gpio3_dbclk: gpio3_dbclk {
+	gpio3_dbclk: gpio3_dbclk@1068 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_32k_ck>;
@@ -868,7 +868,7 @@
 		reg = <0x1068>;
 	};
 
-	gpio4_dbclk: gpio4_dbclk {
+	gpio4_dbclk: gpio4_dbclk@1070 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_32k_ck>;
@@ -876,7 +876,7 @@
 		reg = <0x1070>;
 	};
 
-	gpio5_dbclk: gpio5_dbclk {
+	gpio5_dbclk: gpio5_dbclk@1078 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_32k_ck>;
@@ -884,7 +884,7 @@
 		reg = <0x1078>;
 	};
 
-	gpio6_dbclk: gpio6_dbclk {
+	gpio6_dbclk: gpio6_dbclk@1080 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_32k_ck>;
@@ -892,7 +892,7 @@
 		reg = <0x1080>;
 	};
 
-	gpio7_dbclk: gpio7_dbclk {
+	gpio7_dbclk: gpio7_dbclk@1110 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_32k_ck>;
@@ -900,7 +900,7 @@
 		reg = <0x1110>;
 	};
 
-	gpio8_dbclk: gpio8_dbclk {
+	gpio8_dbclk: gpio8_dbclk@1118 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_32k_ck>;
@@ -908,7 +908,7 @@
 		reg = <0x1118>;
 	};
 
-	iss_ctrlclk: iss_ctrlclk {
+	iss_ctrlclk: iss_ctrlclk@1320 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&func_96m_fclk>;
@@ -916,7 +916,7 @@
 		reg = <0x1320>;
 	};
 
-	lli_txphy_clk: lli_txphy_clk {
+	lli_txphy_clk: lli_txphy_clk@f20 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&dpll_unipro1_clkdcoldo>;
@@ -924,7 +924,7 @@
 		reg = <0x0f20>;
 	};
 
-	lli_txphy_ls_clk: lli_txphy_ls_clk {
+	lli_txphy_ls_clk: lli_txphy_ls_clk@f20 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&dpll_unipro1_m2_ck>;
@@ -932,7 +932,7 @@
 		reg = <0x0f20>;
 	};
 
-	mmc1_32khz_clk: mmc1_32khz_clk {
+	mmc1_32khz_clk: mmc1_32khz_clk@1628 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_32k_ck>;
@@ -940,7 +940,7 @@
 		reg = <0x1628>;
 	};
 
-	sata_ref_clk: sata_ref_clk {
+	sata_ref_clk: sata_ref_clk@1688 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_clkin>;
@@ -948,7 +948,7 @@
 		reg = <0x1688>;
 	};
 
-	usb_host_hs_hsic480m_p1_clk: usb_host_hs_hsic480m_p1_clk {
+	usb_host_hs_hsic480m_p1_clk: usb_host_hs_hsic480m_p1_clk@1658 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&dpll_usb_m2_ck>;
@@ -956,7 +956,7 @@
 		reg = <0x1658>;
 	};
 
-	usb_host_hs_hsic480m_p2_clk: usb_host_hs_hsic480m_p2_clk {
+	usb_host_hs_hsic480m_p2_clk: usb_host_hs_hsic480m_p2_clk@1658 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&dpll_usb_m2_ck>;
@@ -964,7 +964,7 @@
 		reg = <0x1658>;
 	};
 
-	usb_host_hs_hsic480m_p3_clk: usb_host_hs_hsic480m_p3_clk {
+	usb_host_hs_hsic480m_p3_clk: usb_host_hs_hsic480m_p3_clk@1658 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&dpll_usb_m2_ck>;
@@ -972,7 +972,7 @@
 		reg = <0x1658>;
 	};
 
-	usb_host_hs_hsic60m_p1_clk: usb_host_hs_hsic60m_p1_clk {
+	usb_host_hs_hsic60m_p1_clk: usb_host_hs_hsic60m_p1_clk@1658 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&l3init_60m_fclk>;
@@ -980,7 +980,7 @@
 		reg = <0x1658>;
 	};
 
-	usb_host_hs_hsic60m_p2_clk: usb_host_hs_hsic60m_p2_clk {
+	usb_host_hs_hsic60m_p2_clk: usb_host_hs_hsic60m_p2_clk@1658 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&l3init_60m_fclk>;
@@ -988,7 +988,7 @@
 		reg = <0x1658>;
 	};
 
-	usb_host_hs_hsic60m_p3_clk: usb_host_hs_hsic60m_p3_clk {
+	usb_host_hs_hsic60m_p3_clk: usb_host_hs_hsic60m_p3_clk@1658 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&l3init_60m_fclk>;
@@ -996,7 +996,7 @@
 		reg = <0x1658>;
 	};
 
-	utmi_p1_gfclk: utmi_p1_gfclk {
+	utmi_p1_gfclk: utmi_p1_gfclk@1658 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&l3init_60m_fclk>, <&xclk60mhsp1_ck>;
@@ -1004,7 +1004,7 @@
 		reg = <0x1658>;
 	};
 
-	usb_host_hs_utmi_p1_clk: usb_host_hs_utmi_p1_clk {
+	usb_host_hs_utmi_p1_clk: usb_host_hs_utmi_p1_clk@1658 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&utmi_p1_gfclk>;
@@ -1012,7 +1012,7 @@
 		reg = <0x1658>;
 	};
 
-	utmi_p2_gfclk: utmi_p2_gfclk {
+	utmi_p2_gfclk: utmi_p2_gfclk@1658 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&l3init_60m_fclk>, <&xclk60mhsp2_ck>;
@@ -1020,7 +1020,7 @@
 		reg = <0x1658>;
 	};
 
-	usb_host_hs_utmi_p2_clk: usb_host_hs_utmi_p2_clk {
+	usb_host_hs_utmi_p2_clk: usb_host_hs_utmi_p2_clk@1658 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&utmi_p2_gfclk>;
@@ -1028,7 +1028,7 @@
 		reg = <0x1658>;
 	};
 
-	usb_host_hs_utmi_p3_clk: usb_host_hs_utmi_p3_clk {
+	usb_host_hs_utmi_p3_clk: usb_host_hs_utmi_p3_clk@1658 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&l3init_60m_fclk>;
@@ -1036,7 +1036,7 @@
 		reg = <0x1658>;
 	};
 
-	usb_otg_ss_refclk960m: usb_otg_ss_refclk960m {
+	usb_otg_ss_refclk960m: usb_otg_ss_refclk960m@16f0 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&dpll_usb_clkdcoldo>;
@@ -1044,7 +1044,7 @@
 		reg = <0x16f0>;
 	};
 
-	usb_phy_cm_clk32k: usb_phy_cm_clk32k {
+	usb_phy_cm_clk32k: usb_phy_cm_clk32k@640 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&sys_32k_ck>;
@@ -1052,7 +1052,7 @@
 		reg = <0x0640>;
 	};
 
-	usb_tll_hs_usb_ch0_clk: usb_tll_hs_usb_ch0_clk {
+	usb_tll_hs_usb_ch0_clk: usb_tll_hs_usb_ch0_clk@1668 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&l3init_60m_fclk>;
@@ -1060,7 +1060,7 @@
 		reg = <0x1668>;
 	};
 
-	usb_tll_hs_usb_ch1_clk: usb_tll_hs_usb_ch1_clk {
+	usb_tll_hs_usb_ch1_clk: usb_tll_hs_usb_ch1_clk@1668 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&l3init_60m_fclk>;
@@ -1068,7 +1068,7 @@
 		reg = <0x1668>;
 	};
 
-	usb_tll_hs_usb_ch2_clk: usb_tll_hs_usb_ch2_clk {
+	usb_tll_hs_usb_ch2_clk: usb_tll_hs_usb_ch2_clk@1668 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
 		clocks = <&l3init_60m_fclk>;
@@ -1076,7 +1076,7 @@
 		reg = <0x1668>;
 	};
 
-	fdif_fclk: fdif_fclk {
+	fdif_fclk: fdif_fclk@1328 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_per_h11x2_ck>;
@@ -1085,7 +1085,7 @@
 		reg = <0x1328>;
 	};
 
-	gpu_core_gclk_mux: gpu_core_gclk_mux {
+	gpu_core_gclk_mux: gpu_core_gclk_mux@1520 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&dpll_core_h14x2_ck>, <&dpll_per_h14x2_ck>;
@@ -1093,7 +1093,7 @@
 		reg = <0x1520>;
 	};
 
-	gpu_hyd_gclk_mux: gpu_hyd_gclk_mux {
+	gpu_hyd_gclk_mux: gpu_hyd_gclk_mux@1520 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&dpll_core_h14x2_ck>, <&dpll_per_h14x2_ck>;
@@ -1101,7 +1101,7 @@
 		reg = <0x1520>;
 	};
 
-	hsi_fclk: hsi_fclk {
+	hsi_fclk: hsi_fclk@1638 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&dpll_per_m2x2_ck>;
@@ -1110,7 +1110,7 @@
 		reg = <0x1638>;
 	};
 
-	mmc1_fclk_mux: mmc1_fclk_mux {
+	mmc1_fclk_mux: mmc1_fclk_mux@1628 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&func_128m_clk>, <&dpll_per_m2x2_ck>;
@@ -1118,7 +1118,7 @@
 		reg = <0x1628>;
 	};
 
-	mmc1_fclk: mmc1_fclk {
+	mmc1_fclk: mmc1_fclk@1628 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&mmc1_fclk_mux>;
@@ -1127,7 +1127,7 @@
 		reg = <0x1628>;
 	};
 
-	mmc2_fclk_mux: mmc2_fclk_mux {
+	mmc2_fclk_mux: mmc2_fclk_mux@1630 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&func_128m_clk>, <&dpll_per_m2x2_ck>;
@@ -1135,7 +1135,7 @@
 		reg = <0x1630>;
 	};
 
-	mmc2_fclk: mmc2_fclk {
+	mmc2_fclk: mmc2_fclk@1630 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&mmc2_fclk_mux>;
@@ -1144,7 +1144,7 @@
 		reg = <0x1630>;
 	};
 
-	timer10_gfclk_mux: timer10_gfclk_mux {
+	timer10_gfclk_mux: timer10_gfclk_mux@1028 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin>, <&sys_32k_ck>;
@@ -1152,7 +1152,7 @@
 		reg = <0x1028>;
 	};
 
-	timer11_gfclk_mux: timer11_gfclk_mux {
+	timer11_gfclk_mux: timer11_gfclk_mux@1030 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin>, <&sys_32k_ck>;
@@ -1160,7 +1160,7 @@
 		reg = <0x1030>;
 	};
 
-	timer2_gfclk_mux: timer2_gfclk_mux {
+	timer2_gfclk_mux: timer2_gfclk_mux@1038 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin>, <&sys_32k_ck>;
@@ -1168,7 +1168,7 @@
 		reg = <0x1038>;
 	};
 
-	timer3_gfclk_mux: timer3_gfclk_mux {
+	timer3_gfclk_mux: timer3_gfclk_mux@1040 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin>, <&sys_32k_ck>;
@@ -1176,7 +1176,7 @@
 		reg = <0x1040>;
 	};
 
-	timer4_gfclk_mux: timer4_gfclk_mux {
+	timer4_gfclk_mux: timer4_gfclk_mux@1048 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin>, <&sys_32k_ck>;
@@ -1184,7 +1184,7 @@
 		reg = <0x1048>;
 	};
 
-	timer9_gfclk_mux: timer9_gfclk_mux {
+	timer9_gfclk_mux: timer9_gfclk_mux@1050 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&sys_clkin>, <&sys_32k_ck>;
@@ -1201,7 +1201,7 @@
 };
 
 &scrm_clocks {
-	auxclk0_src_gate_ck: auxclk0_src_gate_ck {
+	auxclk0_src_gate_ck: auxclk0_src_gate_ck@310 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-no-wait-gate-clock";
 		clocks = <&dpll_core_m3x2_ck>;
@@ -1209,7 +1209,7 @@
 		reg = <0x0310>;
 	};
 
-	auxclk0_src_mux_ck: auxclk0_src_mux_ck {
+	auxclk0_src_mux_ck: auxclk0_src_mux_ck@310 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&sys_clkin>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>;
@@ -1223,7 +1223,7 @@
 		clocks = <&auxclk0_src_gate_ck>, <&auxclk0_src_mux_ck>;
 	};
 
-	auxclk0_ck: auxclk0_ck {
+	auxclk0_ck: auxclk0_ck@310 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&auxclk0_src_ck>;
@@ -1232,7 +1232,7 @@
 		reg = <0x0310>;
 	};
 
-	auxclk1_src_gate_ck: auxclk1_src_gate_ck {
+	auxclk1_src_gate_ck: auxclk1_src_gate_ck@314 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-no-wait-gate-clock";
 		clocks = <&dpll_core_m3x2_ck>;
@@ -1240,7 +1240,7 @@
 		reg = <0x0314>;
 	};
 
-	auxclk1_src_mux_ck: auxclk1_src_mux_ck {
+	auxclk1_src_mux_ck: auxclk1_src_mux_ck@314 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&sys_clkin>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>;
@@ -1254,7 +1254,7 @@
 		clocks = <&auxclk1_src_gate_ck>, <&auxclk1_src_mux_ck>;
 	};
 
-	auxclk1_ck: auxclk1_ck {
+	auxclk1_ck: auxclk1_ck@314 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&auxclk1_src_ck>;
@@ -1263,7 +1263,7 @@
 		reg = <0x0314>;
 	};
 
-	auxclk2_src_gate_ck: auxclk2_src_gate_ck {
+	auxclk2_src_gate_ck: auxclk2_src_gate_ck@318 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-no-wait-gate-clock";
 		clocks = <&dpll_core_m3x2_ck>;
@@ -1271,7 +1271,7 @@
 		reg = <0x0318>;
 	};
 
-	auxclk2_src_mux_ck: auxclk2_src_mux_ck {
+	auxclk2_src_mux_ck: auxclk2_src_mux_ck@318 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&sys_clkin>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>;
@@ -1285,7 +1285,7 @@
 		clocks = <&auxclk2_src_gate_ck>, <&auxclk2_src_mux_ck>;
 	};
 
-	auxclk2_ck: auxclk2_ck {
+	auxclk2_ck: auxclk2_ck@318 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&auxclk2_src_ck>;
@@ -1294,7 +1294,7 @@
 		reg = <0x0318>;
 	};
 
-	auxclk3_src_gate_ck: auxclk3_src_gate_ck {
+	auxclk3_src_gate_ck: auxclk3_src_gate_ck@31c {
 		#clock-cells = <0>;
 		compatible = "ti,composite-no-wait-gate-clock";
 		clocks = <&dpll_core_m3x2_ck>;
@@ -1302,7 +1302,7 @@
 		reg = <0x031c>;
 	};
 
-	auxclk3_src_mux_ck: auxclk3_src_mux_ck {
+	auxclk3_src_mux_ck: auxclk3_src_mux_ck@31c {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&sys_clkin>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>;
@@ -1316,7 +1316,7 @@
 		clocks = <&auxclk3_src_gate_ck>, <&auxclk3_src_mux_ck>;
 	};
 
-	auxclk3_ck: auxclk3_ck {
+	auxclk3_ck: auxclk3_ck@31c {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&auxclk3_src_ck>;
@@ -1325,7 +1325,7 @@
 		reg = <0x031c>;
 	};
 
-	auxclk4_src_gate_ck: auxclk4_src_gate_ck {
+	auxclk4_src_gate_ck: auxclk4_src_gate_ck@320 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-no-wait-gate-clock";
 		clocks = <&dpll_core_m3x2_ck>;
@@ -1333,7 +1333,7 @@
 		reg = <0x0320>;
 	};
 
-	auxclk4_src_mux_ck: auxclk4_src_mux_ck {
+	auxclk4_src_mux_ck: auxclk4_src_mux_ck@320 {
 		#clock-cells = <0>;
 		compatible = "ti,composite-mux-clock";
 		clocks = <&sys_clkin>, <&dpll_core_m3x2_ck>, <&dpll_per_m3x2_ck>;
@@ -1347,7 +1347,7 @@
 		clocks = <&auxclk4_src_gate_ck>, <&auxclk4_src_mux_ck>;
 	};
 
-	auxclk4_ck: auxclk4_ck {
+	auxclk4_ck: auxclk4_ck@320 {
 		#clock-cells = <0>;
 		compatible = "ti,divider-clock";
 		clocks = <&auxclk4_src_ck>;
@@ -1356,7 +1356,7 @@
 		reg = <0x0320>;
 	};
 
-	auxclkreq0_ck: auxclkreq0_ck {
+	auxclkreq0_ck: auxclkreq0_ck@210 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>;
@@ -1364,7 +1364,7 @@
 		reg = <0x0210>;
 	};
 
-	auxclkreq1_ck: auxclkreq1_ck {
+	auxclkreq1_ck: auxclkreq1_ck@214 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>;
@@ -1372,7 +1372,7 @@
 		reg = <0x0214>;
 	};
 
-	auxclkreq2_ck: auxclkreq2_ck {
+	auxclkreq2_ck: auxclkreq2_ck@218 {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>;
@@ -1380,7 +1380,7 @@
 		reg = <0x0218>;
 	};
 
-	auxclkreq3_ck: auxclkreq3_ck {
+	auxclkreq3_ck: auxclkreq3_ck@21c {
 		#clock-cells = <0>;
 		compatible = "ti,mux-clock";
 		clocks = <&auxclk0_ck>, <&auxclk1_ck>, <&auxclk2_ck>, <&auxclk3_ck>, <&auxclk4_ck>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/omap5-board-common.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/omap5-board-common.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/omap5-board-common.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/omap5-board-common.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -14,6 +14,29 @@
 		display0 = &hdmi0;
 	};
 
+	vmain: fixedregulator-vmain {
+		compatible = "regulator-fixed";
+		regulator-name = "vmain";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+	};
+
+	vsys_cobra: fixedregulator-vsys_cobra {
+		compatible = "regulator-fixed";
+		regulator-name = "vsys_cobra";
+		vin-supply = <&vmain>;
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+	};
+
+	vdds_1v8_main: fixedregulator-vdds_1v8_main {
+		compatible = "regulator-fixed";
+		regulator-name = "vdds_1v8_main";
+		vin-supply = <&smps7_reg>;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+	};
+
 	vmmcsd_fixed: fixedregulator-mmcsd {
 		compatible = "regulator-fixed";
 		regulator-name = "vmmcsd_fixed";
@@ -309,7 +332,7 @@
 
 	wlcore_irq_pin: pinmux_wlcore_irq_pin {
 		pinctrl-single,pins = <
-			OMAP5_IOPAD(0x40, WAKEUP_EN | PIN_INPUT_PULLUP | MUX_MODE6)	/* llia_wakereqin.gpio1_wk14 */
+			OMAP5_IOPAD(0x40, PIN_INPUT_PULLUP | MUX_MODE6)	/* llia_wakereqin.gpio1_wk14 */
 		>;
 	};
 };
@@ -391,14 +414,44 @@
 			ti,backup-battery-charge-high-current;
 		};
 
+		gpadc {
+			compatible = "ti,palmas-gpadc";
+			interrupts = <18 0
+				      16 0
+				      17 0>;
+			#io-channel-cells = <1>;
+			ti,channel0-current-microamp = <5>;
+			ti,channel3-current-microamp = <10>;
+		};
+
 		palmas_pmic {
 			compatible = "ti,palmas-pmic";
 			interrupt-parent = <&palmas>;
 			interrupts = <14 IRQ_TYPE_NONE>;
-			interrupt-name = "short-irq";
+			interrupt-names = "short-irq";
 
 			ti,ldo6-vibrator;
 
+			smps123-in-supply = <&vsys_cobra>;
+			smps45-in-supply = <&vsys_cobra>;
+			smps6-in-supply = <&vsys_cobra>;
+			smps7-in-supply = <&vsys_cobra>;
+			smps8-in-supply = <&vsys_cobra>;
+			smps9-in-supply = <&vsys_cobra>;
+			smps10_out2-in-supply = <&vsys_cobra>;
+			smps10_out1-in-supply = <&vsys_cobra>;
+			ldo1-in-supply = <&vsys_cobra>;
+			ldo2-in-supply = <&vsys_cobra>;
+			ldo3-in-supply = <&vdds_1v8_main>;
+			ldo4-in-supply = <&vdds_1v8_main>;
+			ldo5-in-supply = <&vsys_cobra>;
+			ldo6-in-supply = <&vdds_1v8_main>;
+			ldo7-in-supply = <&vsys_cobra>;
+			ldo8-in-supply = <&vsys_cobra>;
+			ldo9-in-supply = <&vmmcsd_fixed>;
+			ldoln-in-supply = <&vsys_cobra>;
+			ldousb-in-supply = <&vsys_cobra>;
+
 			regulators {
 				smps123_reg: smps123 {
 					/* VDD_OPP_MPU */
@@ -590,7 +643,8 @@
 		pinctrl-0 = <&twl6040_pins>;
 
 		interrupts = <GIC_SPI 119 IRQ_TYPE_NONE>; /* IRQ_SYS_2N cascaded to gic */
-		ti,audpwron-gpio = <&gpio5 13 GPIO_ACTIVE_HIGH>;  /* gpio line 141 */
+
+		/* audpwron gpio defined in the board specific dts */
 
 		vio-supply = <&smps7_reg>;
 		v2v1-supply = <&smps9_reg>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/omap5-cm-t54.dts linux-libre-4.7-gnu/arch/arm/boot/dts/omap5-cm-t54.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/omap5-cm-t54.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/omap5-cm-t54.dts	2016-07-24 15:23:50.000000000 -0400
@@ -434,7 +434,7 @@
 			compatible = "ti,palmas-pmic";
 			interrupt-parent = <&palmas>;
 			interrupts = <14 IRQ_TYPE_NONE>;
-			interrupt-name = "short-irq";
+			interrupt-names = "short-irq";
 
 			ti,ldo6-vibrator;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/omap5.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/omap5.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/omap5.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/omap5.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -187,7 +187,7 @@
 					#size-cells = <1>;
 					ranges = <0 0x5a0 0xec>;
 
-					pbias_regulator: pbias_regulator {
+					pbias_regulator: pbias_regulator@60 {
 						compatible = "ti,pbias-omap5", "ti,pbias-omap";
 						reg = <0x60 0x4>;
 						syscon = <&omap5_padconf_global>;
@@ -398,6 +398,10 @@
 			ti,hwmods = "gpmc";
 			clocks = <&l3_iclk_div>;
 			clock-names = "fck";
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			gpio-controller;
+			#gpio-cells = <2>;
 		};
 
 		i2c1: i2c@48070000 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/omap5-igep0050.dts linux-libre-4.7-gnu/arch/arm/boot/dts/omap5-igep0050.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/omap5-igep0050.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/omap5-igep0050.dts	2016-07-24 15:23:50.000000000 -0400
@@ -35,6 +35,22 @@
 	};
 };
 
+/* LDO4 is VPP1 - ball AD9 */
+&ldo4_reg {
+	regulator-min-microvolt = <2000000>;
+	regulator-max-microvolt = <2000000>;
+};
+
+/*
+ * LDO7 is used for HDMI: VDDA_DSIPORTA - ball AA33, VDDA_DSIPORTC - ball AE33,
+ * VDDA_HDMI - ball AN25
+ */
+&ldo7_reg {
+	status = "okay";
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+};
+
 &omap5_pmx_core {
 	i2c4_pins: pinmux_i2c4_pins {
 		pinctrl-single,pins = <
@@ -52,3 +68,13 @@
 		<&gpio7 3 0>;		/* 195, SDA */
 };
 
+&twl6040 {
+	ti,audpwron-gpio = <&gpio5 16 GPIO_ACTIVE_HIGH>;  /* gpio line 144 */
+};
+
+&twl6040_pins {
+	pinctrl-single,pins = <
+		OMAP5_IOPAD(0x1c4, PIN_OUTPUT | MUX_MODE6)	/* mcspi1_somi.gpio5_144 */
+		OMAP5_IOPAD(0x1ca, PIN_OUTPUT | MUX_MODE6)	/* perslimbus2_clock.gpio5_145 */
+	>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/omap5-uevm.dts linux-libre-4.7-gnu/arch/arm/boot/dts/omap5-uevm.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/omap5-uevm.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/omap5-uevm.dts	2016-07-24 15:23:50.000000000 -0400
@@ -51,3 +51,13 @@
 		<&gpio9 1 GPIO_ACTIVE_HIGH>,	/* TCA6424A P00, LS OE */
 		<&gpio7 1 GPIO_ACTIVE_HIGH>;	/* GPIO 193, HPD */
 };
+
+&twl6040 {
+	ti,audpwron-gpio = <&gpio5 13 GPIO_ACTIVE_HIGH>;  /* gpio line 141 */
+};
+
+&twl6040_pins {
+	pinctrl-single,pins = <
+		OMAP5_IOPAD(0x1be, PIN_OUTPUT | MUX_MODE6)	/* mcspi1_somi.gpio5_141 */
+	>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/orion5x-kuroboxpro.dts linux-libre-4.7-gnu/arch/arm/boot/dts/orion5x-kuroboxpro.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/orion5x-kuroboxpro.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/orion5x-kuroboxpro.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,127 @@
+/*
+ * Device Tree file for Buffalo/Revogear Kurobox Pro
+ *
+ * Copyright (C) 2016
+ * Roger Shimizu <rogershimizu@gmail.com>
+ *
+ * Based on the board file arch/arm/mach-orion5x/kurobox_pro-setup.c
+ * Copyright (C) Ronen Shitrit <rshitrit@marvell.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include "orion5x-linkstation.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	model = "Buffalo/Revogear Kurobox Pro";
+	compatible = "buffalo,kurobox-pro", "marvell,orion5x-88f5182", "marvell,orion5x";
+
+	soc {
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000>,
+				 <MBUS_ID(0x09, 0x00) 0 0xf2200000 0x800>,
+				 <MBUS_ID(0x01, 0x0f) 0 0xf4000000 0x40000>,
+				 <MBUS_ID(0x01, 0x1e) 0 0xfc000000 0x1000000>;
+	};
+
+	memory { /* 128 MB */
+		device_type = "memory";
+		reg = <0x00000000 0x8000000>;
+	};
+};
+
+&pinctrl {
+	pmx_power_hdd: pmx-power-hdd {
+		marvell,pins = "mpp1";
+		marvell,function = "gpio";
+	};
+
+	pmx_power_usb: pmx-power-usb {
+		marvell,pins = "mpp9";
+		marvell,function = "gpio";
+	};
+};
+
+&devbus_cs0 {
+	status = "okay";
+	compatible = "marvell,orion-nand";
+	reg = <MBUS_ID(0x01, 0x1e) 0 0x400>;
+	cle = <0>;
+	ale = <1>;
+	bank-width = <1>;
+
+	partitions {
+		compatible = "fixed-partitions";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		uImage@0 { /* 4 MB */
+			reg = <0 0x400000>;
+			read-only;
+		};
+
+		rootfs@400000 { /* 64 MB */
+			reg = <0x400000 0x4000000>;
+			read-only;
+		};
+
+		extra@4400000 { /* 188 MB */
+			reg = <0x4400000 0xBC00000>;
+			read-only;
+		};
+	};
+};
+
+&hdd_power {
+	gpios = <&gpio0 1 GPIO_ACTIVE_HIGH>;
+};
+
+&usb_power {
+	gpios = <&gpio0 9 GPIO_ACTIVE_HIGH>;
+};
+
+&sata {
+	nr-ports = <2>;
+};
+
+&ehci1 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/ox810se.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/ox810se.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/ox810se.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/ox810se.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,336 @@
+/*
+ * ox810se.dtsi - Device tree file for Oxford Semiconductor OX810SE SoC
+ *
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * Licensed under GPLv2 or later
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	compatible = "oxsemi,ox810se";
+
+	cpus {
+		#address-cells = <0>;
+		#size-cells = <0>;
+
+		cpu {
+			device_type = "cpu";
+			compatible = "arm,arm926ej-s";
+			clocks = <&armclk>;
+		};
+	};
+
+	memory {
+		/* Max 256MB @ 0x48000000 */
+		reg = <0x48000000 0x10000000>;
+	};
+
+	clocks {
+		osc: oscillator {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <25000000>;
+		};
+
+		gmacclk: gmacclk {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <125000000>;
+		};
+
+		rpsclk: rpsclk {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clock-div = <1>;
+			clock-mult = <1>;
+			clocks = <&osc>;
+		};
+
+		pll400: pll400 {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <733333333>;
+		};
+
+		sysclk: sysclk {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clock-div = <4>;
+			clock-mult = <1>;
+			clocks = <&pll400>;
+		};
+
+		armclk: armclk {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clock-div = <2>;
+			clock-mult = <1>;
+			clocks = <&pll400>;
+		};
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		ranges;
+		interrupt-parent = <&intc>;
+
+		apb-bridge@44000000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "simple-bus";
+			ranges = <0 0x44000000 0x1000000>;
+
+			pinctrl: pinctrl {
+				compatible = "oxsemi,ox810se-pinctrl";
+
+				/* Regmap for sys registers */
+				oxsemi,sys-ctrl = <&sys>;
+
+				pinctrl_uart0: uart0 {
+					uart0a {
+						pins = "gpio31";
+						function = "fct3";
+					};
+					uart0b {
+						pins = "gpio32";
+						function = "fct3";
+					};
+				};
+
+				pinctrl_uart0_modem: uart0_modem {
+					uart0c {
+						pins = "gpio27";
+						function = "fct3";
+					};
+					uart0d {
+						pins = "gpio28";
+						function = "fct3";
+					};
+					uart0e {
+						pins = "gpio29";
+						function = "fct3";
+					};
+					uart0f {
+						pins = "gpio30";
+						function = "fct3";
+					};
+					uart0g {
+						pins = "gpio33";
+						function = "fct3";
+					};
+					uart0h {
+						pins = "gpio34";
+						function = "fct3";
+					};
+				};
+
+				pinctrl_uart1: uart1 {
+					uart1a {
+						pins = "gpio20";
+						function = "fct3";
+					};
+					uart1b {
+						pins = "gpio22";
+						function = "fct3";
+					};
+				};
+
+				pinctrl_uart1_modem: uart1_modem {
+					uart1c {
+						pins = "gpio8";
+						function = "fct3";
+					};
+					uart1d {
+						pins = "gpio9";
+						function = "fct3";
+					};
+					uart1e {
+						pins = "gpio23";
+						function = "fct3";
+					};
+					uart1f {
+						pins = "gpio24";
+						function = "fct3";
+					};
+					uart1g {
+						pins = "gpio25";
+						function = "fct3";
+					};
+					uart1h {
+						pins = "gpio26";
+						function = "fct3";
+					};
+				};
+
+				pinctrl_uart2: uart2 {
+					uart2a {
+						pins = "gpio6";
+						function = "fct3";
+					};
+					uart2b {
+						pins = "gpio7";
+						function = "fct3";
+					};
+				};
+
+				pinctrl_uart2_modem: uart2_modem {
+					uart2c {
+						pins = "gpio0";
+						function = "fct3";
+					};
+					uart2d {
+						pins = "gpio1";
+						function = "fct3";
+					};
+					uart2e {
+						pins = "gpio2";
+						function = "fct3";
+					};
+					uart2f {
+						pins = "gpio3";
+						function = "fct3";
+					};
+					uart2g {
+						pins = "gpio4";
+						function = "fct3";
+					};
+					uart2h {
+						pins = "gpio5";
+						function = "fct3";
+					};
+				};
+			};
+
+			gpio0: gpio@000000 {
+				compatible = "oxsemi,ox810se-gpio";
+				reg = <0x000000 0x100000>;
+				interrupts = <21>;
+				#gpio-cells = <2>;
+				gpio-controller;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				ngpios = <32>;
+				oxsemi,gpio-bank = <0>;
+				gpio-ranges = <&pinctrl 0 0 32>;
+			};
+
+			gpio1: gpio@100000 {
+				compatible = "oxsemi,ox810se-gpio";
+				reg = <0x100000 0x100000>;
+				interrupts = <22>;
+				#gpio-cells = <2>;
+				gpio-controller;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				ngpios = <3>;
+				oxsemi,gpio-bank = <1>;
+				gpio-ranges = <&pinctrl 0 32 3>;
+			};
+
+			uart0: serial@200000 {
+			       compatible = "ns16550a";
+			       reg = <0x200000 0x100000>;
+			       clocks = <&sysclk>;
+			       interrupts = <23>;
+			       reg-shift = <0>;
+			       fifo-size = <16>;
+			       reg-io-width = <1>;
+			       current-speed = <115200>;
+			       no-loopback-test;
+			       status = "disabled";
+			       resets = <&reset 17>;
+			};
+
+			uart1: serial@300000 {
+			       compatible = "ns16550a";
+			       reg = <0x300000 0x100000>;
+			       clocks = <&sysclk>;
+			       interrupts = <24>;
+			       reg-shift = <0>;
+			       fifo-size = <16>;
+			       reg-io-width = <1>;
+			       current-speed = <115200>;
+			       no-loopback-test;
+			       status = "disabled";
+			       resets = <&reset 18>;
+			};
+
+			uart2: serial@900000 {
+			       compatible = "ns16550a";
+			       reg = <0x900000 0x100000>;
+			       clocks = <&sysclk>;
+			       interrupts = <29>;
+			       reg-shift = <0>;
+			       fifo-size = <16>;
+			       reg-io-width = <1>;
+			       current-speed = <115200>;
+			       no-loopback-test;
+			       status = "disabled";
+			       resets = <&reset 22>;
+			};
+
+			uart3: serial@a00000 {
+			       compatible = "ns16550a";
+			       reg = <0xa00000 0x100000>;
+			       clocks = <&sysclk>;
+			       interrupts = <30>;
+			       reg-shift = <0>;
+			       fifo-size = <16>;
+			       reg-io-width = <1>;
+			       current-speed = <115200>;
+			       no-loopback-test;
+			       status = "disabled";
+			       resets = <&reset 23>;
+			};
+		};
+
+		apb-bridge@45000000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "simple-bus";
+			ranges = <0 0x45000000 0x1000000>;
+
+			sys: sys-ctrl@000000 {
+				compatible = "oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd";
+				reg = <0x000000 0x100000>;
+
+				reset: reset-controller {
+					compatible = "oxsemi,ox810se-reset";
+					#reset-cells = <1>;
+				};
+
+				stdclk: stdclk {
+					compatible = "oxsemi,ox810se-stdclk";
+					#clock-cells = <1>;
+				};
+			};
+
+			rps@300000 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "simple-bus";
+				ranges = <0 0x300000 0x100000>;
+
+				intc: interrupt-controller@0 {
+					compatible = "oxsemi,ox810se-rps-irq";
+					interrupt-controller;
+					reg = <0 0x200>;
+					#interrupt-cells = <1>;
+					valid-mask = <0xFFFFFFFF>;
+					clear-mask = <0>;
+				};
+
+				timer0: timer@200 {
+					compatible = "oxsemi,ox810se-rps-timer";
+					reg = <0x200 0x40>;
+					clocks = <&rpsclk>;
+					interrupts = <4 5>;
+				};
+			};
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/phy3250.dts linux-libre-4.7-gnu/arch/arm/boot/dts/phy3250.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/phy3250.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/phy3250.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,227 +0,0 @@
-/*
- * PHYTEC phyCORE-LPC3250 board
- *
- * Copyright 2012 Roland Stigge <stigge@antcom.de>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-/dts-v1/;
-#include "lpc32xx.dtsi"
-
-/ {
-	model = "PHYTEC phyCORE-LPC3250 board based on NXP LPC3250";
-	compatible = "phytec,phy3250", "nxp,lpc3250";
-	#address-cells = <1>;
-	#size-cells = <1>;
-
-	memory {
-		device_type = "memory";
-		reg = <0x80000000 0x4000000>;
-	};
-
-	regulators {
-		backlight_reg: regulator@0 {
-			compatible = "regulator-fixed";
-			regulator-name = "backlight_reg";
-			regulator-min-microvolt = <1800000>;
-			regulator-max-microvolt = <1800000>;
-			gpio = <&gpio 5 4 0>;
-			enable-active-high;
-			regulator-boot-on;
-		};
-
-		lcd_reg: regulator@1 {
-			compatible = "regulator-fixed";
-			regulator-name = "lcd_reg";
-			regulator-min-microvolt = <1800000>;
-			regulator-max-microvolt = <1800000>;
-			gpio = <&gpio 5 0 0>;
-			enable-active-high;
-			regulator-boot-on;
-		};
-
-		sd_reg: regulator@2 {
-			compatible = "regulator-fixed";
-			regulator-name = "sd_reg";
-			regulator-min-microvolt = <1800000>;
-			regulator-max-microvolt = <1800000>;
-			gpio = <&gpio 5 5 0>;
-			enable-active-high;
-		};
-	};
-
-	ahb {
-		mac: ethernet@31060000 {
-			phy-mode = "rmii";
-			use-iram;
-		};
-
-		clcd@31040000 {
-			status = "okay";
-		};
-
-		/* 64MB Flash via SLC NAND controller */
-		slc: flash@20020000 {
-			status = "okay";
-			#address-cells = <1>;
-			#size-cells = <1>;
-
-			nxp,wdr-clks = <14>;
-			nxp,wwidth = <40000000>;
-			nxp,whold = <100000000>;
-			nxp,wsetup = <100000000>;
-			nxp,rdr-clks = <14>;
-			nxp,rwidth = <40000000>;
-			nxp,rhold = <66666666>;
-			nxp,rsetup = <100000000>;
-			nand-on-flash-bbt;
-			gpios = <&gpio 5 19 1>; /* GPO_P3 19, active low */
-
-			mtd0@00000000 {
-				label = "phy3250-boot";
-				reg = <0x00000000 0x00064000>;
-				read-only;
-			};
-
-			mtd1@00064000 {
-				label = "phy3250-uboot";
-				reg = <0x00064000 0x00190000>;
-				read-only;
-			};
-
-			mtd2@001f4000 {
-				label = "phy3250-ubt-prms";
-				reg = <0x001f4000 0x00010000>;
-			};
-
-			mtd3@00204000 {
-				label = "phy3250-kernel";
-				reg = <0x00204000 0x00400000>;
-			};
-
-			mtd4@00604000 {
-				label = "phy3250-rootfs";
-				reg = <0x00604000 0x039fc000>;
-			};
-		};
-
-		apb {
-			uart5: serial@40090000 {
-				status = "okay";
-			};
-
-			uart3: serial@40080000 {
-				status = "okay";
-			};
-
-			i2c1: i2c@400A0000 {
-				clock-frequency = <100000>;
-
-				pcf8563: rtc@51 {
-					compatible = "nxp,pcf8563";
-					reg = <0x51>;
-				};
-
-				uda1380: uda1380@18 {
-					compatible = "nxp,uda1380";
-					reg = <0x18>;
-					power-gpio = <&gpio 0x59 0>;
-					reset-gpio = <&gpio 0x51 0>;
-					dac-clk = "wspll";
-				};
-			};
-
-			i2c2: i2c@400A8000 {
-				clock-frequency = <100000>;
-			};
-
-			ssp0: ssp@20084000 {
-				#address-cells = <1>;
-				#size-cells = <0>;
-				num-cs = <1>;
-				cs-gpios = <&gpio 3 5 0>;
-
-				eeprom: at25@0 {
-					pl022,interface = <0>;
-					pl022,com-mode = <0>;
-					pl022,rx-level-trig = <1>;
-					pl022,tx-level-trig = <1>;
-					pl022,ctrl-len = <11>;
-					pl022,wait-state = <0>;
-					pl022,duplex = <0>;
-
-					at25,byte-len = <0x8000>;
-					at25,addr-mode = <2>;
-					at25,page-size = <64>;
-
-					compatible = "atmel,at25";
-					reg = <0>;
-					spi-max-frequency = <5000000>;
-				};
-			};
-
-			sd@20098000 {
-				wp-gpios = <&gpio 3 0 0>;
-				cd-gpios = <&gpio 3 1 0>;
-				cd-inverted;
-				bus-width = <4>;
-				vmmc-supply = <&sd_reg>;
-				status = "okay";
-			};
-		};
-
-		fab {
-			uart2: serial@40018000 {
-				status = "okay";
-			};
-
-			tsc@40048000 {
-				status = "okay";
-			};
-
-			key@40050000 {
-				status = "okay";
-				keypad,num-rows = <1>;
-				keypad,num-columns = <1>;
-				nxp,debounce-delay-ms = <3>;
-				nxp,scan-delay-ms = <34>;
-				linux,keymap = <0x00000002>;
-			};
-		};
-	};
-
-	leds {
-		compatible = "gpio-leds";
-
-		led0 { /* red */
-			gpios = <&gpio 5 1 0>; /* GPO_P3 1, GPIO 80, active high */
-			default-state = "off";
-		};
-
-		led1 { /* green */
-			gpios = <&gpio 5 14 0>; /* GPO_P3 14, GPIO 93, active high */
-			linux,default-trigger = "heartbeat";
-		};
-	};
-};
-
-/* Here, choose exactly one from: ohci, usbd */
-&ohci /* &usbd */ {
-	transceiver = <&isp1301>;
-	status = "okay";
-};
-
-&i2cusb {
-	clock-frequency = <100000>;
-
-	isp1301: usb-transceiver@2c {
-		compatible = "nxp,isp1301";
-		reg = <0x2c>;
-	};
-};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts linux-libre-4.7-gnu/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/qcom-apq8064-arrow-db600c.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,349 @@
+#include "qcom-apq8064-v2.0.dtsi"
+#include "qcom-apq8064-arrow-db600c-pins.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	model = "Arrow Electronics, APQ8064 DB600c";
+	compatible = "arrow,db600c", "qcom,apq8064";
+
+	aliases {
+		serial0 = &gsbi7_serial;
+		serial1 = &gsbi1_serial;
+		i2c0 = &gsbi2_i2c;
+		i2c1 = &gsbi3_i2c;
+		i2c2 = &gsbi4_i2c;
+		i2c3 = &gsbi7_i2c;
+		spi0 = &gsbi5_spi;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		vph: regulator-fixed@1 {
+			compatible = "regulator-fixed";
+			regulator-min-microvolt = <4500000>;
+			regulator-max-microvolt = <4500000>;
+			regulator-name = "VPH";
+			regulator-type = "voltage";
+			regulator-boot-on;
+		};
+
+		/* on board fixed 3.3v supply */
+		vcc3v3: vcc3v3 {
+			compatible = "regulator-fixed";
+			regulator-name = "VCC3V3";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+		};
+
+	};
+
+	soc {
+		rpm@108000 {
+			regulators {
+				vdd_s1-supply = <&vph>;
+				vdd_s2-supply = <&vph>;
+				vdd_s3-supply = <&vph>;
+				vdd_s4-supply = <&vph>;
+				vdd_s5-supply = <&vph>;
+				vdd_s6-supply = <&vph>;
+				vdd_s7-supply = <&vph>;
+				vdd_l1_l2_l12_l18-supply = <&pm8921_s4>;
+				vdd_l3_l15_l17-supply = <&vph>;
+				vdd_l4_l14-supply = <&vph>;
+				vdd_l5_l8_l16-supply = <&vph>;
+				vdd_l6_l7-supply = <&vph>;
+				vdd_l9_l11-supply = <&vph>;
+				vdd_l10_l22-supply = <&vph>;
+				vdd_l21_l23_l29-supply = <&vph>;
+				vdd_l24-supply = <&pm8921_s1>;
+				vdd_l25-supply = <&pm8921_s1>;
+				vdd_l26-supply = <&pm8921_s7>;
+				vdd_l27-supply = <&pm8921_s7>;
+				vdd_l28-supply = <&pm8921_s7>;
+				vin_lvs1_3_6-supply = <&pm8921_s4>;
+				vin_lvs2-supply = <&pm8921_s1>;
+				vin_lvs4_5_7-supply = <&pm8921_s4>;
+
+				s1 {
+					regulator-always-on;
+					regulator-min-microvolt = <1225000>;
+					regulator-max-microvolt = <1225000>;
+					qcom,switch-mode-frequency = <3200000>;
+					bias-pull-down;
+				};
+
+				s3 {
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1400000>;
+					qcom,switch-mode-frequency = <4800000>;
+				};
+
+				s4 {
+					regulator-min-microvolt	= <1800000>;
+					regulator-max-microvolt	= <1800000>;
+					qcom,switch-mode-frequency = <3200000>;
+					bias-pull-down;
+					regulator-always-on;
+				};
+
+				s7 {
+					regulator-min-microvolt = <1300000>;
+					regulator-max-microvolt = <1300000>;
+					qcom,switch-mode-frequency = <3200000>;
+				 };
+
+				l3 {
+					regulator-min-microvolt = <3050000>;
+					regulator-max-microvolt = <3300000>;
+					bias-pull-down;
+				};
+
+				l4 {
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1800000>;
+					bias-pull-down;
+				};
+
+				l5 {
+					regulator-min-microvolt = <2750000>;
+					regulator-max-microvolt = <3000000>;
+					bias-pull-down;
+					regulator-boot-on;
+					regulator-always-on;
+				};
+
+				l6 {
+					regulator-min-microvolt = <2950000>;
+					regulator-max-microvolt = <2950000>;
+					bias-pull-down;
+				};
+
+				l23 {
+					regulator-min-microvolt = <1700000>;
+					regulator-max-microvolt = <1900000>;
+					bias-pull-down;
+				};
+
+				lvs6 {
+					bias-pull-down;
+				};
+
+				lvs7 {
+					bias-pull-down;
+				};
+			};
+		};
+
+		gsbi@12440000 {
+			status = "okay";
+			qcom,mode = <GSBI_PROT_UART_W_FC>;
+			serial@12450000 {
+				label = "LS-UART1";
+				status = "okay";
+				pinctrl-names = "default";
+				pinctrl-0 = <&gsbi1_uart_4pins>;
+			};
+		};
+
+		gsbi@12480000 {
+			status = "okay";
+			qcom,mode = <GSBI_PROT_I2C>;
+			i2c@124a0000 {
+				/* On Low speed expansion and Sensors */
+				label = "LS-I2C0";
+				status = "okay";
+				lis3mdl_mag@1e {
+					compatible = "st,lis3mdl-magn";
+					reg = <0x1e>;
+					vdd-supply = <&vcc3v3>;
+					vddio-supply = <&pm8921_s4>;
+					pinctrl-names = "default";
+					pinctrl-0 = <&magneto_pins>;
+					interrupt-parent = <&tlmm_pinmux>;
+
+					st,drdy-int-pin = <2>;
+					interrupts = <48 IRQ_TYPE_EDGE_RISING>, /* DRDY line */
+						     <31 IRQ_TYPE_EDGE_RISING>; /* INT */
+				};
+			};
+		};
+
+		gsbi@16200000 {
+			status = "okay";
+			qcom,mode = <GSBI_PROT_I2C>;
+			i2c@16280000 {
+			/* On Low speed expansion */
+				status = "okay";
+				label = "LS-I2C1";
+				clock-frequency = <200000>;
+				eeprom@52 {
+					compatible = "atmel,24c128";
+					reg = <0x52>;
+					pagesize = <64>;
+				};
+			};
+		};
+
+		gsbi@16300000 {
+			status = "okay";
+			qcom,mode = <GSBI_PROT_I2C>;
+			i2c@16380000 {
+				/* On High speed expansion */
+				label = "HS-CAM-I2C3";
+				status = "okay";
+			};
+		};
+
+		gsbi@1a200000 {
+			status = "okay";
+			spi@1a280000 {
+				/* On Low speed expansion */
+				label = "LS-SPI0";
+				status = "okay";
+			};
+		};
+
+		/* DEBUG UART  */
+		gsbi@16600000 {
+			status = "okay";
+			qcom,mode = <GSBI_PROT_I2C_UART>;
+			serial@16640000 {
+				label = "LS-UART0";
+				status = "okay";
+				pinctrl-names = "default";
+				pinctrl-0 = <&gsbi7_uart_2pins>;
+			};
+
+			i2c@16680000 {
+				/* On High speed expansion */
+				status = "okay";
+				label = "HS-CAM-I2C2";
+			};
+		};
+
+		leds {
+			pinctrl-names = "default";
+			pinctrl-0 = <&user_leds>, <&mpp_leds>;
+
+			compatible = "gpio-leds";
+
+			user-led0 {
+				label = "user0-led";
+				gpios = <&tlmm_pinmux 3 GPIO_ACTIVE_HIGH>;
+				linux,default-trigger = "heartbeat";
+				default-state = "off";
+			};
+
+			user-led1 {
+				label = "user1-led";
+				gpios = <&tlmm_pinmux 7 GPIO_ACTIVE_HIGH>;
+				linux,default-trigger = "mmc0";
+				default-state = "off";
+			};
+
+			user-led2 {
+				label = "user2-led";
+				gpios = <&tlmm_pinmux 10 GPIO_ACTIVE_HIGH>;
+				linux,default-trigger = "mmc1";
+				default-state = "off";
+			};
+
+			user-led3 {
+				label = "user3-led";
+				gpios = <&tlmm_pinmux 11 GPIO_ACTIVE_HIGH>;
+				linux,default-trigger = "none";
+				default-state = "off";
+			};
+
+			wifi-led {
+				label = "WiFi-led";
+				gpios = <&pm8921_mpps 7 GPIO_ACTIVE_HIGH>;
+				default-state = "off";
+			};
+
+			bt-led {
+				label = "BT-led";
+				gpios = <&pm8921_mpps 8 GPIO_ACTIVE_HIGH>;
+				default-state = "off";
+			};
+		};
+
+		pci@1b500000 {
+			status = "okay";
+			vdda-supply = <&pm8921_s3>;
+			vdda_phy-supply = <&pm8921_lvs6>;
+			vdda_refclk-supply = <&vcc3v3>;
+			pinctrl-0 = <&pcie_pins>;
+			pinctrl-names = "default";
+			perst-gpio = <&tlmm_pinmux 27 GPIO_ACTIVE_LOW>;
+		};
+
+		phy@1b400000 {
+			status = "okay";
+		};
+
+		sata@29000000 {
+			status	= "okay";
+			target-supply	= <&pm8921_lvs7>;
+		};
+
+		/* OTG */
+		phy@12500000 {
+			status		= "okay";
+			dr_mode		= "peripheral";
+			vddcx-supply	= <&pm8921_s3>;
+			v3p3-supply	= <&pm8921_l3>;
+			v1p8-supply	= <&pm8921_l4>;
+		};
+
+		phy@12520000 {
+			status		= "okay";
+			vddcx-supply	= <&pm8921_s3>;
+			v3p3-supply	= <&pm8921_l3>;
+			v1p8-supply	= <&pm8921_l23>;
+		};
+
+		phy@12530000 {
+			status		= "okay";
+			vddcx-supply	= <&pm8921_s3>;
+			v3p3-supply	= <&pm8921_l3>;
+			v1p8-supply	= <&pm8921_l23>;
+		};
+
+		gadget@12500000 {
+			status = "okay";
+		};
+
+		/* OTG */
+		usb@12500000 {
+			status = "okay";
+		};
+
+		usb@12520000 {
+			status = "okay";
+		};
+
+		usb@12530000 {
+			status = "okay";
+		};
+
+		amba {
+			/* eMMC */
+			sdcc@12400000 {
+				status = "okay";
+				vmmc-supply = <&pm8921_l5>;
+				vqmmc-supply = <&pm8921_s4>;
+			};
+
+			/* External micro SD card */
+			sdcc@12180000 {
+				status = "okay";
+				vmmc-supply = <&pm8921_l6>;
+				pinctrl-names	= "default";
+				pinctrl-0	= <&card_detect>;
+				cd-gpios	= <&tlmm_pinmux 26 GPIO_ACTIVE_HIGH>;
+			};
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/qcom-apq8064-arrow-db600c-pins.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/qcom-apq8064-arrow-db600c-pins.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/qcom-apq8064-arrow-db600c-pins.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/qcom-apq8064-arrow-db600c-pins.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,52 @@
+&tlmm_pinmux {
+	card_detect: card-detect {
+		mux {
+			pins = "gpio26";
+			function = "gpio";
+			bias-disable;
+		};
+	};
+
+	pcie_pins: pcie-pinmux {
+		mux {
+			pins = "gpio27";
+			function = "gpio";
+		};
+		conf {
+			pins = "gpio27";
+			drive-strength = <12>;
+			bias-disable;
+		};
+	};
+
+	user_leds: user-leds {
+		mux {
+			pins = "gpio3", "gpio7", "gpio10", "gpio11";
+			function = "gpio";
+		};
+
+		conf {
+			pins = "gpio3", "gpio7", "gpio10", "gpio11";
+			function = "gpio";
+			output-low;
+		};
+	};
+
+	magneto_pins: magneto-pins {
+		mux {
+			pins = "gpio31", "gpio48";
+			function = "gpio";
+			bias-disable;
+		};
+	};
+};
+
+&pm8921_mpps {
+	mpp_leds: mpp-leds {
+		pinconf {
+			pins = "mpp7", "mpp8";
+			function = "digital";
+			output-low;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/qcom-apq8064-asus-nexus7-flo.dts linux-libre-4.7-gnu/arch/arm/boot/dts/qcom-apq8064-asus-nexus7-flo.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/qcom-apq8064-asus-nexus7-flo.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/qcom-apq8064-asus-nexus7-flo.dts	2016-07-24 15:23:50.000000000 -0400
@@ -224,6 +224,12 @@
 					reg = <0x52>;
 					pagesize = <32>;
 				};
+
+				bq27541@55 {
+					compatible = "ti,bq27541";
+					reg = <0x55>;
+				};
+
 			};
 		};
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/qcom-apq8064.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/qcom-apq8064.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/qcom-apq8064.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/qcom-apq8064.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -124,6 +124,95 @@
 		hwlocks = <&sfpb_mutex 3>;
 	};
 
+	smd {
+		compatible = "qcom,smd";
+
+		modem@0 {
+			interrupts = <0 37 IRQ_TYPE_EDGE_RISING>;
+
+			qcom,ipc = <&l2cc 8 3>;
+			qcom,smd-edge = <0>;
+
+			status = "disabled";
+		};
+
+		q6@1 {
+			interrupts = <0 90 IRQ_TYPE_EDGE_RISING>;
+
+			qcom,ipc = <&l2cc 8 15>;
+			qcom,smd-edge = <1>;
+
+			status = "disabled";
+		};
+
+		dsps@3 {
+			interrupts = <0 138 IRQ_TYPE_EDGE_RISING>;
+
+			qcom,ipc = <&sps_sic_non_secure 0x4080 0>;
+			qcom,smd-edge = <3>;
+
+			status = "disabled";
+		};
+
+		riva@6 {
+			interrupts = <0 198 IRQ_TYPE_EDGE_RISING>;
+
+			qcom,ipc = <&l2cc 8 25>;
+			qcom,smd-edge = <6>;
+
+			status = "disabled";
+		};
+	};
+
+	smsm {
+		compatible = "qcom,smsm";
+
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		qcom,ipc-1 = <&l2cc 8 4>;
+		qcom,ipc-2 = <&l2cc 8 14>;
+		qcom,ipc-3 = <&l2cc 8 23>;
+		qcom,ipc-4 = <&sps_sic_non_secure 0x4094 0>;
+
+		apps_smsm: apps@0 {
+			reg = <0>;
+			#qcom,state-cells = <1>;
+		};
+
+		modem_smsm: modem@1 {
+			reg = <1>;
+			interrupts = <0 38 IRQ_TYPE_EDGE_RISING>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		q6_smsm: q6@2 {
+			reg = <2>;
+			interrupts = <0 89 IRQ_TYPE_EDGE_RISING>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		wcnss_smsm: wcnss@3 {
+			reg = <3>;
+			interrupts = <0 204 IRQ_TYPE_EDGE_RISING>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		dsps_smsm: dsps@4 {
+			reg = <4>;
+			interrupts = <0 137 IRQ_TYPE_EDGE_RISING>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+	};
+
 	soc: soc {
 		#address-cells = <1>;
 		#size-cells = <1>;
@@ -212,6 +301,11 @@
 			regulator;
 		};
 
+		sps_sic_non_secure: sps-sic-non-secure@12100000 {
+			compatible	= "syscon";
+			reg		= <0x12100000 0x10000>;
+		};
+
 		gsbi1: gsbi@12440000 {
 			status = "disabled";
 			compatible = "qcom,gsbi-v1.0.0";
@@ -225,9 +319,20 @@
 
 			syscon-tcsr = <&tcsr>;
 
+			gsbi1_serial: serial@12450000 {
+				compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
+				reg = <0x12450000 0x100>,
+				      <0x12400000 0x03>;
+				interrupts = <0 193 0x0>;
+				clocks = <&gcc GSBI1_UART_CLK>, <&gcc GSBI1_H_CLK>;
+				clock-names = "core", "iface";
+				status = "disabled";
+			};
+
 			gsbi1_i2c: i2c@12460000 {
 				compatible = "qcom,i2c-qup-v1.1.1";
-				pinctrl-0 = <&i2c1_pins &i2c1_pins_sleep>;
+				pinctrl-0 = <&i2c1_pins>;
+				pinctrl-1 = <&i2c1_pins_sleep>;
 				pinctrl-names = "default", "sleep";
 				reg = <0x12460000 0x1000>;
 				interrupts = <0 194 IRQ_TYPE_NONE>;
@@ -255,7 +360,8 @@
 			gsbi2_i2c: i2c@124a0000 {
 				compatible = "qcom,i2c-qup-v1.1.1";
 				reg = <0x124a0000 0x1000>;
-				pinctrl-0 = <&i2c2_pins &i2c2_pins_sleep>;
+				pinctrl-0 = <&i2c2_pins>;
+				pinctrl-1 = <&i2c2_pins_sleep>;
 				pinctrl-names = "default", "sleep";
 				interrupts = <0 196 IRQ_TYPE_NONE>;
 				clocks = <&gcc GSBI2_QUP_CLK>, <&gcc GSBI2_H_CLK>;
@@ -277,7 +383,8 @@
 			ranges;
 			gsbi3_i2c: i2c@16280000 {
 				compatible = "qcom,i2c-qup-v1.1.1";
-				pinctrl-0 = <&i2c3_pins &i2c3_pins_sleep>;
+				pinctrl-0 = <&i2c3_pins>;
+				pinctrl-1 = <&i2c3_pins_sleep>;
 				pinctrl-names = "default", "sleep";
 				reg = <0x16280000 0x1000>;
 				interrupts = <GIC_SPI 151 IRQ_TYPE_NONE>;
@@ -302,7 +409,8 @@
 
 			gsbi4_i2c: i2c@16380000 {
 				compatible = "qcom,i2c-qup-v1.1.1";
-				pinctrl-0 = <&i2c4_pins &i2c4_pins_sleep>;
+				pinctrl-0 = <&i2c4_pins>;
+				pinctrl-1 = <&i2c4_pins_sleep>;
 				pinctrl-names = "default", "sleep";
 				reg = <0x16380000 0x1000>;
 				interrupts = <GIC_SPI 153 IRQ_TYPE_NONE>;
@@ -337,7 +445,8 @@
 				compatible = "qcom,spi-qup-v1.1.1";
 				reg = <0x1a280000 0x1000>;
 				interrupts = <0 155 0>;
-				pinctrl-0 = <&spi5_default &spi5_sleep>;
+				pinctrl-0 = <&spi5_default>;
+				pinctrl-1 = <&spi5_sleep>;
 				pinctrl-names = "default", "sleep";
 				clocks = <&gcc GSBI5_QUP_CLK>, <&gcc GSBI5_H_CLK>;
 				clock-names = "core", "iface";
@@ -370,7 +479,8 @@
 
 			gsbi6_i2c: i2c@16580000 {
 				compatible = "qcom,i2c-qup-v1.1.1";
-				pinctrl-0 = <&i2c6_pins &i2c6_pins_sleep>;
+				pinctrl-0 = <&i2c6_pins>;
+				pinctrl-1 = <&i2c6_pins_sleep>;
 				pinctrl-names = "default", "sleep";
 				reg = <0x16580000 0x1000>;
 				interrupts = <GIC_SPI 157 IRQ_TYPE_NONE>;
@@ -401,6 +511,19 @@
 				clock-names = "core", "iface";
 				status = "disabled";
 			};
+
+			gsbi7_i2c: i2c@16680000 {
+				compatible = "qcom,i2c-qup-v1.1.1";
+				pinctrl-0 = <&i2c7_pins>;
+				pinctrl-1 = <&i2c7_pins_sleep>;
+				pinctrl-names = "default", "sleep";
+				reg = <0x16680000 0x1000>;
+				interrupts = <GIC_SPI 159 IRQ_TYPE_NONE>;
+				clocks = <&gcc GSBI7_QUP_CLK>,
+					 <&gcc GSBI7_H_CLK>;
+				clock-names = "core", "iface";
+				status = "disabled";
+			};
 		};
 
 		rng@1a500000 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/qcom-apq8064-pins.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/qcom-apq8064-pins.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/qcom-apq8064-pins.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/qcom-apq8064-pins.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -39,6 +39,20 @@
 		};
 	};
 
+	gsbi1_uart_2pins: gsbi1_uart_2pins {
+		mux {
+			pins = "gpio18", "gpio19";
+			function = "gsbi1";
+		};
+	};
+
+	gsbi1_uart_4pins: gsbi1_uart_4pins {
+		mux {
+			pins = "gpio18", "gpio19", "gpio20", "gpio21";
+			function = "gsbi1";
+		};
+	};
+
 	i2c2_pins: i2c2 {
 		mux {
 			pins = "gpio24", "gpio25";
@@ -205,4 +219,29 @@
 			function = "gsbi7";
 		};
 	};
+
+	i2c7_pins: i2c7 {
+		mux {
+			pins = "gpio84", "gpio85";
+			function = "gsbi7";
+		};
+
+		pinconf {
+			pins = "gpio84", "gpio85";
+			drive-strength = <16>;
+			bias-disable;
+		};
+	};
+
+	i2c7_pins_sleep: i2c7_pins_sleep {
+		mux {
+			pins = "gpio84", "gpio85";
+			function = "gpio";
+		};
+		pinconf {
+			pins = "gpio84", "gpio85";
+			drive-strength = <2>;
+			bias-disable = <0>;
+		};
+	};
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1-c1.dts linux-libre-4.7-gnu/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1-c1.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1-c1.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1-c1.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,22 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "qcom-ipq4019-ap.dk01.1.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. IPQ40xx/AP-DK01.1-C1";
+
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,112 @@
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "qcom-ipq4019.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. IPQ4019/AP-DK01.1";
+	compatible = "qcom,ipq4019";
+
+	clocks {
+                xo: xo {
+                        compatible = "fixed-clock";
+                        clock-frequency = <48000000>;
+                        #clock-cells = <0>;
+                };
+	};
+
+	soc {
+
+
+		timer {
+			compatible = "arm,armv7-timer";
+			interrupts = <1 2 0xf08>,
+				     <1 3 0xf08>,
+				     <1 4 0xf08>,
+				     <1 1 0xf08>;
+			clock-frequency = <48000000>;
+		};
+
+		pinctrl@0x01000000 {
+			serial_pins: serial_pinmux {
+				mux {
+					pins = "gpio60", "gpio61";
+					function = "blsp_uart0";
+					bias-disable;
+				};
+			};
+
+			spi_0_pins: spi_0_pinmux {
+				pinmux {
+					function = "blsp_spi0";
+					pins = "gpio55", "gpio56", "gpio57";
+				};
+				pinmux_cs {
+					function = "gpio";
+					pins = "gpio54";
+				};
+				pinconf {
+					pins = "gpio55", "gpio56", "gpio57";
+					drive-strength = <12>;
+					bias-disable;
+				};
+				pinconf_cs {
+					pins = "gpio54";
+					drive-strength = <2>;
+					bias-disable;
+					output-high;
+				};
+			};
+		};
+
+		blsp_dma: dma@7884000 {
+			status = "ok";
+		};
+
+		spi_0: spi@78b5000 {
+			pinctrl-0 = <&spi_0_pins>;
+			pinctrl-names = "default";
+			status = "ok";
+			cs-gpios = <&tlmm 54 0>;
+
+			mx25l25635e@0 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				reg = <0>;
+				compatible = "mx25l25635e";
+				spi-max-frequency = <24000000>;
+			};
+		};
+
+		serial@78af000 {
+			pinctrl-0 = <&serial_pins>;
+			pinctrl-names = "default";
+			status = "ok";
+		};
+
+		cryptobam: dma@8e04000 {
+			status = "ok";
+		};
+
+		crypto@8e3a000 {
+			status = "ok";
+		};
+
+		watchdog@b017000 {
+			status = "ok";
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/qcom-ipq4019.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/qcom-ipq4019.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/qcom-ipq4019.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/qcom-ipq4019.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 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.
+ */
+
+/dts-v1/;
+
+#include "skeleton.dtsi"
+#include <dt-bindings/clock/qcom,gcc-ipq4019.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	model = "Qualcomm Technologies, Inc. IPQ4019";
+	compatible = "qcom,ipq4019";
+	interrupt-parent = <&intc>;
+
+	aliases {
+		spi0 = &spi_0;
+		i2c0 = &i2c_0;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			enable-method = "qcom,kpss-acc-v1";
+			qcom,acc = <&acc0>;
+			qcom,saw = <&saw0>;
+			reg = <0x0>;
+			clocks = <&gcc GCC_APPS_CLK_SRC>;
+			clock-frequency = <0>;
+			operating-points = <
+				/* kHz	uV (fixed) */
+				48000	1100000
+				200000	1100000
+				500000	1100000
+				666000	1100000
+			>;
+			clock-latency = <256000>;
+		};
+
+		cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			enable-method = "qcom,kpss-acc-v1";
+			qcom,acc = <&acc1>;
+			qcom,saw = <&saw1>;
+			reg = <0x1>;
+			clocks = <&gcc GCC_APPS_CLK_SRC>;
+			clock-frequency = <0>;
+		};
+
+		cpu@2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			enable-method = "qcom,kpss-acc-v1";
+			qcom,acc = <&acc2>;
+			qcom,saw = <&saw2>;
+			reg = <0x2>;
+			clocks = <&gcc GCC_APPS_CLK_SRC>;
+			clock-frequency = <0>;
+		};
+
+		cpu@3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			enable-method = "qcom,kpss-acc-v1";
+			qcom,acc = <&acc3>;
+			qcom,saw = <&saw3>;
+			reg = <0x3>;
+			clocks = <&gcc GCC_APPS_CLK_SRC>;
+			clock-frequency = <0>;
+		};
+	};
+
+	clocks {
+		sleep_clk: sleep_clk {
+			compatible = "fixed-clock";
+			clock-frequency = <32768>;
+			#clock-cells = <0>;
+		};
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		compatible = "simple-bus";
+
+		intc: interrupt-controller@b000000 {
+			compatible = "qcom,msm-qgic2";
+			interrupt-controller;
+			#interrupt-cells = <3>;
+			reg = <0x0b000000 0x1000>,
+			<0x0b002000 0x1000>;
+		};
+
+		gcc: clock-controller@1800000 {
+			compatible = "qcom,gcc-ipq4019";
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+			reg = <0x1800000 0x60000>;
+		};
+
+		tlmm: pinctrl@0x01000000 {
+			compatible = "qcom,ipq4019-pinctrl";
+			reg = <0x01000000 0x300000>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			interrupts = <0 208 0>;
+		};
+
+		blsp_dma: dma@7884000 {
+			compatible = "qcom,bam-v1.7.0";
+			reg = <0x07884000 0x23000>;
+			interrupts = <GIC_SPI 238 IRQ_TYPE_NONE>;
+			clocks = <&gcc GCC_BLSP1_AHB_CLK>;
+			clock-names = "bam_clk";
+			#dma-cells = <1>;
+			qcom,ee = <0>;
+			status = "disabled";
+		};
+
+		spi_0: spi@78b5000 {
+			compatible = "qcom,spi-qup-v2.2.1";
+			reg = <0x78b5000 0x600>;
+			interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&gcc GCC_BLSP1_QUP1_SPI_APPS_CLK>,
+				 <&gcc GCC_BLSP1_AHB_CLK>;
+			clock-names = "core", "iface";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		i2c_0: i2c@78b7000 {
+			compatible = "qcom,i2c-qup-v2.2.1";
+			reg = <0x78b7000 0x6000>;
+			interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&gcc GCC_BLSP1_AHB_CLK>,
+				 <&gcc GCC_BLSP1_QUP2_I2C_APPS_CLK>;
+			clock-names = "iface", "core";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+
+		cryptobam: dma@8e04000 {
+			compatible = "qcom,bam-v1.7.0";
+			reg = <0x08e04000 0x20000>;
+			interrupts = <GIC_SPI 207 0>;
+			clocks = <&gcc GCC_CRYPTO_AHB_CLK>;
+			clock-names = "bam_clk";
+			#dma-cells = <1>;
+			qcom,ee = <1>;
+			qcom,controlled-remotely;
+			status = "disabled";
+		};
+
+		crypto@8e3a000 {
+			compatible = "qcom,crypto-v5.1";
+			reg = <0x08e3a000 0x6000>;
+			clocks = <&gcc GCC_CRYPTO_AHB_CLK>,
+				 <&gcc GCC_CRYPTO_AXI_CLK>,
+				 <&gcc GCC_CRYPTO_CLK>;
+			clock-names = "iface", "bus", "core";
+			dmas = <&cryptobam 2>, <&cryptobam 3>;
+			dma-names = "rx", "tx";
+			status = "disabled";
+		};
+
+                acc0: clock-controller@b088000 {
+                        compatible = "qcom,kpss-acc-v1";
+                        reg = <0x0b088000 0x1000>, <0xb008000 0x1000>;
+                };
+
+                acc1: clock-controller@b098000 {
+                        compatible = "qcom,kpss-acc-v1";
+                        reg = <0x0b098000 0x1000>, <0xb008000 0x1000>;
+                };
+
+                acc2: clock-controller@b0a8000 {
+                        compatible = "qcom,kpss-acc-v1";
+                        reg = <0x0b0a8000 0x1000>, <0xb008000 0x1000>;
+                };
+
+                acc3: clock-controller@b0b8000 {
+                        compatible = "qcom,kpss-acc-v1";
+                        reg = <0x0b0b8000 0x1000>, <0xb008000 0x1000>;
+                };
+
+                saw0: regulator@b089000 {
+                        compatible = "qcom,saw2";
+                        reg = <0x02089000 0x1000>, <0x0b009000 0x1000>;
+                        regulator;
+                };
+
+                saw1: regulator@b099000 {
+                        compatible = "qcom,saw2";
+                        reg = <0x0b099000 0x1000>, <0x0b009000 0x1000>;
+                        regulator;
+                };
+
+                saw2: regulator@b0a9000 {
+                        compatible = "qcom,saw2";
+                        reg = <0x0b0a9000 0x1000>, <0x0b009000 0x1000>;
+                        regulator;
+                };
+
+                saw3: regulator@b0b9000 {
+                        compatible = "qcom,saw2";
+                        reg = <0x0b0b9000 0x1000>, <0x0b009000 0x1000>;
+                        regulator;
+                };
+
+		serial@78af000 {
+			compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
+			reg = <0x78af000 0x200>;
+			interrupts = <0 107 0>;
+			status = "disabled";
+			clocks = <&gcc GCC_BLSP1_UART1_APPS_CLK>,
+				<&gcc GCC_BLSP1_AHB_CLK>;
+			clock-names = "core", "iface";
+			dmas = <&blsp_dma 1>, <&blsp_dma 0>;
+			dma-names = "rx", "tx";
+		};
+
+		serial@78b0000 {
+			compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
+			reg = <0x78b0000 0x200>;
+			interrupts = <0 108 0>;
+			status = "disabled";
+			clocks = <&gcc GCC_BLSP1_UART2_APPS_CLK>,
+				<&gcc GCC_BLSP1_AHB_CLK>;
+			clock-names = "core", "iface";
+			dmas = <&blsp_dma 3>, <&blsp_dma 2>;
+			dma-names = "rx", "tx";
+		};
+
+		watchdog@b017000 {
+			compatible = "qcom,kpss-standalone";
+			reg = <0xb017000 0x40>;
+			clocks = <&sleep_clk>;
+			timeout-sec = <10>;
+			status = "disabled";
+		};
+
+		restart@4ab000 {
+			compatible = "qcom,pshold";
+			reg = <0x4ab000 0x4>;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/qcom-msm8974.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/qcom-msm8974.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/qcom-msm8974.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/qcom-msm8974.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -49,8 +49,13 @@
 			no-map;
 		};
 
-		efs@0fd600000 {
-			reg = <0x0fd60000 0x1a0000>;
+		rfsa@0fd60000 {
+			reg = <0x0fd60000 0x20000>;
+			no-map;
+		};
+
+		rmtfs@0fd80000 {
+			reg = <0x0fd80000 0x180000>;
 			no-map;
 		};
 
@@ -163,6 +168,31 @@
 		hwlocks = <&tcsr_mutex 3>;
 	};
 
+	smp2p-modem {
+		compatible = "qcom,smp2p";
+		qcom,smem = <435>, <428>;
+
+		interrupt-parent = <&intc>;
+		interrupts = <0 27 IRQ_TYPE_EDGE_RISING>;
+
+		qcom,ipc = <&apcs 8 14>;
+
+		qcom,local-pid = <0>;
+		qcom,remote-pid = <1>;
+
+		modem_smp2p_out: master-kernel {
+			qcom,entry-name = "master-kernel";
+			#qcom,state-cells = <1>;
+		};
+
+		modem_smp2p_in: slave-kernel {
+			qcom,entry-name = "slave-kernel";
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+	};
+
 	smp2p-wcnss {
 		compatible = "qcom,smp2p";
 		qcom,smem = <451>, <431>;
@@ -440,6 +470,17 @@
 			interrupts = <0 208 0>;
 		};
 
+		i2c@f9924000 {
+			status = "disabled";
+			compatible = "qcom,i2c-qup-v2.1.1";
+			reg = <0xf9924000 0x1000>;
+			interrupts = <0 96 IRQ_TYPE_NONE>;
+			clocks = <&gcc GCC_BLSP1_QUP2_I2C_APPS_CLK>, <&gcc GCC_BLSP1_AHB_CLK>;
+			clock-names = "core", "iface";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
 		blsp_i2c8: i2c@f9964000 {
 			status = "disabled";
 			compatible = "qcom,i2c-qup-v2.1.1";
@@ -482,6 +523,13 @@
 	smd {
 		compatible = "qcom,smd";
 
+		modem {
+			interrupts = <0 25 IRQ_TYPE_EDGE_RISING>;
+
+			qcom,ipc = <&apcs 8 12>;
+			qcom,smd-edge = <0>;
+		};
+
 		rpm {
 			interrupts = <0 168 1>;
 			qcom,ipc = <&apcs 8 0>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/r7s72100.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/r7s72100.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/r7s72100.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/r7s72100.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -37,46 +37,41 @@
 		#size-cells = <1>;
 
 		/* External clocks */
-		extal_clk: extal_clk {
+		extal_clk: extal {
 			#clock-cells = <0>;
 			compatible = "fixed-clock";
 			/* If clk present, value must be set by board */
 			clock-frequency = <0>;
-			clock-output-names = "extal";
 		};
 
-		usb_x1_clk: usb_x1_clk {
+		usb_x1_clk: usb_x1 {
 			#clock-cells = <0>;
 			compatible = "fixed-clock";
 			/* If clk present, value must be set by board */
 			clock-frequency = <0>;
-			clock-output-names = "usb_x1";
 		};
 
 		/* Fixed factor clocks */
-		b_clk: b_clk {
+		b_clk: b {
 			#clock-cells = <0>;
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R7S72100_CLK_PLL>;
 			clock-mult = <1>;
 			clock-div = <3>;
-			clock-output-names = "b";
 		};
-		p1_clk: p1_clk {
+		p1_clk: p1 {
 			#clock-cells = <0>;
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R7S72100_CLK_PLL>;
 			clock-mult = <1>;
 			clock-div = <6>;
-			clock-output-names = "p1";
 		};
-		p0_clk: p0_clk {
+		p0_clk: p0 {
 			#clock-cells = <0>;
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R7S72100_CLK_PLL>;
 			clock-mult = <1>;
 			clock-div = <12>;
-			clock-output-names = "p0";
 		};
 
 		/* Special CPG clocks */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/r8a73a4-ape6evm.dts linux-libre-4.7-gnu/arch/arm/boot/dts/r8a73a4-ape6evm.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/r8a73a4-ape6evm.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/r8a73a4-ape6evm.dts	2016-07-24 15:23:50.000000000 -0400
@@ -189,28 +189,28 @@
 
 &pfc {
 	scifa0_pins: serial0 {
-		renesas,groups = "scifa0_data";
-		renesas,function = "scifa0";
+		groups = "scifa0_data";
+		function = "scifa0";
 	};
 
 	mmc0_pins: mmc {
-		renesas,groups = "mmc0_data8", "mmc0_ctrl";
-		renesas,function = "mmc0";
+		groups = "mmc0_data8", "mmc0_ctrl";
+		function = "mmc0";
 	};
 
 	sdhi0_pins: sd0 {
-		renesas,groups = "sdhi0_data4", "sdhi0_ctrl", "sdhi0_cd";
-		renesas,function = "sdhi0";
+		groups = "sdhi0_data4", "sdhi0_ctrl", "sdhi0_cd";
+		function = "sdhi0";
 	};
 
 	sdhi1_pins: sd1 {
-		renesas,groups = "sdhi1_data4", "sdhi1_ctrl";
-		renesas,function = "sdhi1";
+		groups = "sdhi1_data4", "sdhi1_ctrl";
+		function = "sdhi1";
 	};
 
 	keyboard_pins: keyboard {
-		renesas,pins = "PORT324", "PORT325", "PORT326", "PORT327",
-			       "PORT328", "PORT329";
+		pins = "PORT324", "PORT325", "PORT326", "PORT327", "PORT328",
+		       "PORT329";
 		bias-pull-up;
 	};
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/r8a73a4.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/r8a73a4.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/r8a73a4.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/r8a73a4.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -486,37 +486,32 @@
 		ranges;
 
 		/* External root clocks */
-		extalr_clk: extalr_clk {
+		extalr_clk: extalr {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <32768>;
-			clock-output-names = "extalr";
 		};
-		extal1_clk: extal1_clk {
+		extal1_clk: extal1 {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <25000000>;
-			clock-output-names = "extal1";
 		};
-		extal2_clk: extal2_clk {
+		extal2_clk: extal2 {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <48000000>;
-			clock-output-names = "extal2";
 		};
-		fsiack_clk: fsiack_clk {
+		fsiack_clk: fsiack {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			/* This value must be overridden by the board. */
 			clock-frequency = <0>;
-			clock-output-names = "fsiack";
 		};
-		fsibck_clk: fsibck_clk {
+		fsibck_clk: fsibck {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			/* This value must be overridden by the board. */
 			clock-frequency = <0>;
-			clock-output-names = "fsibck";
 		};
 
 		/* Special CPG clocks */
@@ -540,171 +535,151 @@
 			#clock-cells = <0>;
 			clock-output-names = "zb";
 		};
-		sdhi0_clk: sdhi0_clk@e6150074 {
+		sdhi0_clk: sdhi0ck@e6150074 {
 			compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0 0xe6150074 0 4>;
 			clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>,
 				 <0>, <&extal2_clk>;
 			#clock-cells = <0>;
-			clock-output-names = "sdhi0ck";
 		};
-		sdhi1_clk: sdhi1_clk@e6150078 {
+		sdhi1_clk: sdhi1ck@e6150078 {
 			compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0 0xe6150078 0 4>;
 			clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>,
 				 <0>, <&extal2_clk>;
 			#clock-cells = <0>;
-			clock-output-names = "sdhi1ck";
 		};
-		sdhi2_clk: sdhi2_clk@e615007c {
+		sdhi2_clk: sdhi2ck@e615007c {
 			compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0 0xe615007c 0 4>;
 			clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>,
 				 <0>, <&extal2_clk>;
 			#clock-cells = <0>;
-			clock-output-names = "sdhi2ck";
 		};
-		mmc0_clk: mmc0_clk@e6150240 {
+		mmc0_clk: mmc0@e6150240 {
 			compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0 0xe6150240 0 4>;
 			clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>,
 				 <0>, <&extal2_clk>;
 			#clock-cells = <0>;
-			clock-output-names = "mmc0";
 		};
-		mmc1_clk: mmc1_clk@e6150244 {
+		mmc1_clk: mmc1@e6150244 {
 			compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0 0xe6150244 0 4>;
 			clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>,
 				 <0>, <&extal2_clk>;
 			#clock-cells = <0>;
-			clock-output-names = "mmc1";
 		};
-		vclk1_clk: vclk1_clk@e6150008 {
+		vclk1_clk: vclk1@e6150008 {
 			compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0 0xe6150008 0 4>;
 			clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>,
 				 <0>, <&extal2_clk>, <&main_div2_clk>,
 				 <&extalr_clk>, <0>, <0>;
 			#clock-cells = <0>;
-			clock-output-names = "vclk1";
 		};
-		vclk2_clk: vclk2_clk@e615000c {
+		vclk2_clk: vclk2@e615000c {
 			compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0 0xe615000c 0 4>;
 			clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>,
 				 <0>, <&extal2_clk>, <&main_div2_clk>,
 				 <&extalr_clk>, <0>, <0>;
 			#clock-cells = <0>;
-			clock-output-names = "vclk2";
 		};
-		vclk3_clk: vclk3_clk@e615001c {
+		vclk3_clk: vclk3@e615001c {
 			compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0 0xe615001c 0 4>;
 			clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>,
 				 <0>, <&extal2_clk>, <&main_div2_clk>,
 				 <&extalr_clk>, <0>, <0>;
 			#clock-cells = <0>;
-			clock-output-names = "vclk3";
 		};
-		vclk4_clk: vclk4_clk@e6150014 {
+		vclk4_clk: vclk4@e6150014 {
 			compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0 0xe6150014 0 4>;
 			clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>,
 				 <0>, <&extal2_clk>, <&main_div2_clk>,
 				 <&extalr_clk>, <0>, <0>;
 			#clock-cells = <0>;
-			clock-output-names = "vclk4";
 		};
-		vclk5_clk: vclk5_clk@e6150034 {
+		vclk5_clk: vclk5@e6150034 {
 			compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0 0xe6150034 0 4>;
 			clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>,
 				 <0>, <&extal2_clk>, <&main_div2_clk>,
 				 <&extalr_clk>, <0>, <0>;
 			#clock-cells = <0>;
-			clock-output-names = "vclk5";
 		};
-		fsia_clk: fsia_clk@e6150018 {
+		fsia_clk: fsia@e6150018 {
 			compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0 0xe6150018 0 4>;
 			clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>,
 				 <&fsiack_clk>, <0>;
 			#clock-cells = <0>;
-			clock-output-names = "fsia";
 		};
-		fsib_clk: fsib_clk@e6150090 {
+		fsib_clk: fsib@e6150090 {
 			compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0 0xe6150090 0 4>;
 			clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>,
 				 <&fsibck_clk>, <0>;
 			#clock-cells = <0>;
-			clock-output-names = "fsib";
 		};
-		mp_clk: mp_clk@e6150080 {
+		mp_clk: mp@e6150080 {
 			compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0 0xe6150080 0 4>;
 			clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>,
 				 <&extal2_clk>, <&extal2_clk>;
 			#clock-cells = <0>;
-			clock-output-names = "mp";
 		};
-		m4_clk: m4_clk@e6150098 {
+		m4_clk: m4@e6150098 {
 			compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0 0xe6150098 0 4>;
 			clocks = <&cpg_clocks R8A73A4_CLK_PLL2S>;
 			#clock-cells = <0>;
-			clock-output-names = "m4";
 		};
-		hsi_clk: hsi_clk@e615026c {
+		hsi_clk: hsi@e615026c {
 			compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0 0xe615026c 0 4>;
 			clocks = <&cpg_clocks R8A73A4_CLK_PLL2H>, <&pll1_div2_clk>,
 				 <&cpg_clocks R8A73A4_CLK_PLL2S>, <0>;
 			#clock-cells = <0>;
-			clock-output-names = "hsi";
 		};
-		spuv_clk: spuv_clk@e6150094 {
+		spuv_clk: spuv@e6150094 {
 			compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0 0xe6150094 0 4>;
 			clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>,
 				 <&extal2_clk>, <&extal2_clk>;
 			#clock-cells = <0>;
-			clock-output-names = "spuv";
 		};
 
 		/* Fixed factor clocks */
-		main_div2_clk: main_div2_clk {
+		main_div2_clk: main_div2 {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A73A4_CLK_MAIN>;
 			#clock-cells = <0>;
 			clock-div = <2>;
 			clock-mult = <1>;
-			clock-output-names = "main_div2";
 		};
-		pll0_div2_clk: pll0_div2_clk {
+		pll0_div2_clk: pll0_div2 {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A73A4_CLK_PLL0>;
 			#clock-cells = <0>;
 			clock-div = <2>;
 			clock-mult = <1>;
-			clock-output-names = "pll0_div2";
 		};
-		pll1_div2_clk: pll1_div2_clk {
+		pll1_div2_clk: pll1_div2 {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A73A4_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <2>;
 			clock-mult = <1>;
-			clock-output-names = "pll1_div2";
 		};
-		extal1_div2_clk: extal1_div2_clk {
+		extal1_div2_clk: extal1_div2 {
 			compatible = "fixed-factor-clock";
 			clocks = <&extal1_clk>;
 			#clock-cells = <0>;
 			clock-div = <2>;
 			clock-mult = <1>;
-			clock-output-names = "extal1_div2";
 		};
 
 		/* Gate clocks */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/r8a7740-armadillo800eva.dts linux-libre-4.7-gnu/arch/arm/boot/dts/r8a7740-armadillo800eva.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/r8a7740-armadillo800eva.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/r8a7740-armadillo800eva.dts	2016-07-24 15:23:50.000000000 -0400
@@ -228,44 +228,44 @@
 	pinctrl-names = "default";
 
 	ether_pins: ether {
-		renesas,groups = "gether_mii", "gether_int";
-		renesas,function = "gether";
+		groups = "gether_mii", "gether_int";
+		function = "gether";
 	};
 
 	scifa1_pins: serial1 {
-		renesas,groups = "scifa1_data";
-		renesas,function = "scifa1";
+		groups = "scifa1_data";
+		function = "scifa1";
 	};
 
 	st1232_pins: touchscreen {
-		renesas,groups = "intc_irq10";
-		renesas,function = "intc";
+		groups = "intc_irq10";
+		function = "intc";
 	};
 
 	backlight_pins: backlight {
-		renesas,groups = "tpu0_to2_1";
-		renesas,function = "tpu0";
+		groups = "tpu0_to2_1";
+		function = "tpu0";
 	};
 
 	mmc0_pins: mmc0 {
-		renesas,groups = "mmc0_data8_1", "mmc0_ctrl_1";
-		renesas,function = "mmc0";
+		groups = "mmc0_data8_1", "mmc0_ctrl_1";
+		function = "mmc0";
 	};
 
 	sdhi0_pins: sd0 {
-		renesas,groups = "sdhi0_data4", "sdhi0_ctrl", "sdhi0_wp";
-		renesas,function = "sdhi0";
+		groups = "sdhi0_data4", "sdhi0_ctrl", "sdhi0_wp";
+		function = "sdhi0";
 	};
 
 	fsia_pins: sounda {
-		renesas,groups = "fsia_sclk_in", "fsia_mclk_out",
-				 "fsia_data_in_1", "fsia_data_out_0";
-		renesas,function = "fsia";
+		groups = "fsia_sclk_in", "fsia_mclk_out",
+			 "fsia_data_in_1", "fsia_data_out_0";
+		function = "fsia";
 	};
 
 	lcd0_pins: lcd0 {
-		renesas,groups = "lcd0_data24_0", "lcd0_lclk_1", "lcd0_sync";
-		renesas,function = "lcd0";
+		groups = "lcd0_data24_0", "lcd0_lclk_1", "lcd0_sync";
+		function = "lcd0";
 
 		/* DBGMD/LCDC0/FSIA MUX */
 		gpio-hog;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/r8a7740.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/r8a7740.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/r8a7740.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/r8a7740.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -422,53 +422,45 @@
 		ranges;
 
 		/* External root clock */
-		extalr_clk: extalr_clk {
+		extalr_clk: extalr {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <32768>;
-			clock-output-names = "extalr";
 		};
-		extal1_clk: extal1_clk {
+		extal1_clk: extal1 {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <0>;
-			clock-output-names = "extal1";
 		};
-		extal2_clk: extal2_clk {
+		extal2_clk: extal2 {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <0>;
-			clock-output-names = "extal2";
 		};
-		dv_clk: dv_clk {
+		dv_clk: dv {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <27000000>;
-			clock-output-names = "dv";
 		};
-		fmsick_clk: fmsick_clk {
+		fmsick_clk: fmsick {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <0>;
-			clock-output-names = "fmsick";
 		};
-		fmsock_clk: fmsock_clk {
+		fmsock_clk: fmsock {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <0>;
-			clock-output-names = "fmsock";
 		};
-		fsiack_clk: fsiack_clk {
+		fsiack_clk: fsiack {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <0>;
-			clock-output-names = "fsiack";
 		};
-		fsibck_clk: fsibck_clk {
+		fsibck_clk: fsibck {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <0>;
-			clock-output-names = "fsibck";
 		};
 
 		/* Special CPG clocks */
@@ -486,7 +478,7 @@
 		};
 
 		/* Variable factor clocks (DIV6) */
-		vclk1_clk: vclk1_clk@e6150008 {
+		vclk1_clk: vclk1@e6150008 {
 			compatible = "renesas,r8a7740-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0xe6150008 4>;
 			clocks = <&pllc1_div2_clk>, <0>, <&dv_clk>,
@@ -494,9 +486,8 @@
 				 <&extal1_div2_clk>, <&extalr_clk>, <0>,
 				 <0>;
 			#clock-cells = <0>;
-			clock-output-names = "vclk1";
 		};
-		vclk2_clk: vclk2_clk@e615000c {
+		vclk2_clk: vclk2@e615000c {
 			compatible = "renesas,r8a7740-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0xe615000c 4>;
 			clocks = <&pllc1_div2_clk>, <0>, <&dv_clk>,
@@ -504,77 +495,67 @@
 				 <&extal1_div2_clk>, <&extalr_clk>, <0>,
 				 <0>;
 			#clock-cells = <0>;
-			clock-output-names = "vclk2";
 		};
-		fmsi_clk: fmsi_clk@e6150010 {
+		fmsi_clk: fmsi@e6150010 {
 			compatible = "renesas,r8a7740-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0xe6150010 4>;
 			clocks = <&pllc1_div2_clk>, <&fmsick_clk>, <0>, <0>;
 			#clock-cells = <0>;
-			clock-output-names = "fmsi";
 		};
-		fmso_clk: fmso_clk@e6150014 {
+		fmso_clk: fmso@e6150014 {
 			compatible = "renesas,r8a7740-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0xe6150014 4>;
 			clocks = <&pllc1_div2_clk>, <&fmsock_clk>, <0>, <0>;
 			#clock-cells = <0>;
-			clock-output-names = "fmso";
 		};
-		fsia_clk: fsia_clk@e6150018 {
+		fsia_clk: fsia@e6150018 {
 			compatible = "renesas,r8a7740-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0xe6150018 4>;
 			clocks = <&pllc1_div2_clk>, <&fsiack_clk>, <0>, <0>;
 			#clock-cells = <0>;
-			clock-output-names = "fsia";
 		};
-		sub_clk: sub_clk@e6150080 {
+		sub_clk: sub@e6150080 {
 			compatible = "renesas,r8a7740-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0xe6150080 4>;
 			clocks = <&pllc1_div2_clk>,
 				 <&cpg_clocks R8A7740_CLK_USB24S>, <0>, <0>;
 			#clock-cells = <0>;
-			clock-output-names = "sub";
 		};
-		spu_clk: spu_clk@e6150084 {
+		spu_clk: spu@e6150084 {
 			compatible = "renesas,r8a7740-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0xe6150084 4>;
 			clocks = <&pllc1_div2_clk>,
 				 <&cpg_clocks R8A7740_CLK_USB24S>, <0>, <0>;
 			#clock-cells = <0>;
-			clock-output-names = "spu";
 		};
-		vou_clk: vou_clk@e6150088 {
+		vou_clk: vou@e6150088 {
 			compatible = "renesas,r8a7740-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0xe6150088 4>;
 			clocks = <&pllc1_div2_clk>, <&extal1_clk>, <&dv_clk>,
 				 <0>;
 			#clock-cells = <0>;
-			clock-output-names = "vou";
 		};
-		stpro_clk: stpro_clk@e615009c {
+		stpro_clk: stpro@e615009c {
 			compatible = "renesas,r8a7740-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0xe615009c 4>;
 			clocks = <&cpg_clocks R8A7740_CLK_PLLC0>;
 			#clock-cells = <0>;
-			clock-output-names = "stpro";
 		};
 
 		/* Fixed factor clocks */
-		pllc1_div2_clk: pllc1_div2_clk {
+		pllc1_div2_clk: pllc1_div2 {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7740_CLK_PLLC1>;
 			#clock-cells = <0>;
 			clock-div = <2>;
 			clock-mult = <1>;
-			clock-output-names = "pllc1_div2";
 		};
-		extal1_div2_clk: extal1_div2_clk {
+		extal1_div2_clk: extal1_div2 {
 			compatible = "fixed-factor-clock";
 			clocks = <&extal1_clk>;
 			#clock-cells = <0>;
 			clock-div = <2>;
 			clock-mult = <1>;
-			clock-output-names = "extal1_div2";
 		};
 
 		/* Gate clocks */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/r8a7778-bockw.dts linux-libre-4.7-gnu/arch/arm/boot/dts/r8a7778-bockw.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/r8a7778-bockw.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/r8a7778-bockw.dts	2016-07-24 15:23:50.000000000 -0400
@@ -130,53 +130,53 @@
 	pinctrl-names = "default";
 
 	scif0_pins: serial0 {
-		renesas,groups = "scif0_data_a", "scif0_ctrl";
-		renesas,function = "scif0";
+		groups = "scif0_data_a", "scif0_ctrl";
+		function = "scif0";
 	};
 
 	scif_clk_pins: scif_clk {
-		renesas,groups = "scif_clk";
-		renesas,function = "scif_clk";
+		groups = "scif_clk";
+		function = "scif_clk";
 	};
 
 	mmc_pins: mmc {
-		renesas,groups = "mmc_data8", "mmc_ctrl";
-		renesas,function = "mmc";
+		groups = "mmc_data8", "mmc_ctrl";
+		function = "mmc";
 	};
 
 	sdhi0_pins: sd0 {
-		renesas,groups = "sdhi0_data4", "sdhi0_ctrl";
-		renesas,function = "sdhi0";
+		groups = "sdhi0_data4", "sdhi0_ctrl";
+		function = "sdhi0";
 	};
 	sdhi0_pup_pins: sd0_pup {
-		renesas,groups = "sdhi0_cd", "sdhi0_wp";
-		renesas,function = "sdhi0";
+		groups = "sdhi0_cd", "sdhi0_wp";
+		function = "sdhi0";
 		bias-pull-up;
 	};
 
 	hspi0_pins: hspi0 {
-		renesas,groups = "hspi0_a";
-		renesas,function = "hspi0";
+		groups = "hspi0_a";
+		function = "hspi0";
 	};
 
 	usb0_pins: usb0 {
-		renesas,groups = "usb0";
-		renesas,function = "usb0";
+		groups = "usb0";
+		function = "usb0";
 	};
 
 	usb1_pins: usb1 {
-		renesas,groups = "usb1";
-		renesas,function = "usb1";
+		groups = "usb1";
+		function = "usb1";
 	};
 
 	vin0_pins: vin0 {
-		renesas,groups = "vin0_data8", "vin0_clk";
-		renesas,function = "vin0";
+		groups = "vin0_data8", "vin0_clk";
+		function = "vin0";
 	};
 
 	vin1_pins: vin1 {
-		renesas,groups = "vin1_data8", "vin1_clk";
-		renesas,function = "vin1";
+		groups = "vin1_data8", "vin1_clk";
+		function = "vin1";
 	};
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/r8a7778.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/r8a7778.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/r8a7778.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/r8a7778.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -443,11 +443,10 @@
 		ranges;
 
 		/* External input clock */
-		extal_clk: extal_clk {
+		extal_clk: extal {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <0>;
-			clock-output-names = "extal";
 		};
 
 		/* External SCIF clock */
@@ -456,7 +455,6 @@
 			#clock-cells = <0>;
 			/* This value must be overridden by the board. */
 			clock-frequency = <0>;
-			status = "disabled";
 		};
 
 		/* Special CPG clocks */
@@ -474,59 +472,51 @@
 		audio_clk_a: audio_clk_a {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
-			clock-output-names = "audio_clk_a";
 		};
 		audio_clk_b: audio_clk_b {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
-			clock-output-names = "audio_clk_b";
 		};
 		audio_clk_c: audio_clk_c {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
-			clock-output-names = "audio_clk_c";
 		};
 
 		/* Fixed ratio clocks */
-		g_clk: g_clk {
+		g_clk: g {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7778_CLK_PLLA>;
 			#clock-cells = <0>;
 			clock-div = <12>;
 			clock-mult = <1>;
-			clock-output-names = "g";
 		};
-		i_clk: i_clk {
+		i_clk: i {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7778_CLK_PLLA>;
 			#clock-cells = <0>;
 			clock-div = <1>;
 			clock-mult = <1>;
-			clock-output-names = "i";
 		};
-		s3_clk: s3_clk {
+		s3_clk: s3 {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7778_CLK_PLLA>;
 			#clock-cells = <0>;
 			clock-div = <4>;
 			clock-mult = <1>;
-			clock-output-names = "s3";
 		};
-		s4_clk: s4_clk {
+		s4_clk: s4 {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7778_CLK_PLLA>;
 			#clock-cells = <0>;
 			clock-div = <8>;
 			clock-mult = <1>;
-			clock-output-names = "s4";
 		};
-		z_clk: z_clk {
+		z_clk: z {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7778_CLK_PLLB>;
 			#clock-cells = <0>;
 			clock-div = <1>;
 			clock-mult = <1>;
-			clock-output-names = "z";
 		};
 
 		/* Gate clocks */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/r8a7779.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/r8a7779.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/r8a7779.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/r8a7779.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -14,6 +14,7 @@
 #include <dt-bindings/clock/r8a7779-clock.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/power/r8a7779-sysc.h>
 
 / {
 	compatible = "renesas,r8a7779";
@@ -34,18 +35,21 @@
 			compatible = "arm,cortex-a9";
 			reg = <1>;
 			clock-frequency = <1000000000>;
+			power-domains = <&sysc R8A7779_PD_ARM1>;
 		};
 		cpu@2 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a9";
 			reg = <2>;
 			clock-frequency = <1000000000>;
+			power-domains = <&sysc R8A7779_PD_ARM2>;
 		};
 		cpu@3 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a9";
 			reg = <3>;
 			clock-frequency = <1000000000>;
+			power-domains = <&sysc R8A7779_PD_ARM3>;
 		};
 	};
 
@@ -67,7 +71,7 @@
 		compatible = "arm,cortex-a9-twd-timer";
 		reg = <0xf0000600 0x20>;
 		interrupts = <GIC_PPI 13
-			(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+			(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_EDGE_RISING)>;
 		clocks = <&cpg_clocks R8A7779_CLK_ZS>;
 	};
 
@@ -173,7 +177,7 @@
 		reg = <0xffc70000 0x1000>;
 		interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp0_clks R8A7779_CLK_I2C0>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7779_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -184,7 +188,7 @@
 		reg = <0xffc71000 0x1000>;
 		interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp0_clks R8A7779_CLK_I2C1>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7779_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -195,7 +199,7 @@
 		reg = <0xffc72000 0x1000>;
 		interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp0_clks R8A7779_CLK_I2C2>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7779_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -206,7 +210,7 @@
 		reg = <0xffc73000 0x1000>;
 		interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp0_clks R8A7779_CLK_I2C3>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7779_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -218,7 +222,7 @@
 		clocks = <&mstp0_clks R8A7779_CLK_SCIF0>,
 			 <&cpg_clocks R8A7779_CLK_S1>, <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7779_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -230,7 +234,7 @@
 		clocks = <&mstp0_clks R8A7779_CLK_SCIF1>,
 			 <&cpg_clocks R8A7779_CLK_S1>, <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7779_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -242,7 +246,7 @@
 		clocks = <&mstp0_clks R8A7779_CLK_SCIF2>,
 			 <&cpg_clocks R8A7779_CLK_S1>, <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7779_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -254,7 +258,7 @@
 		clocks = <&mstp0_clks R8A7779_CLK_SCIF3>,
 			 <&cpg_clocks R8A7779_CLK_S1>, <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7779_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -266,7 +270,7 @@
 		clocks = <&mstp0_clks R8A7779_CLK_SCIF4>,
 			 <&cpg_clocks R8A7779_CLK_S1>, <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7779_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -278,7 +282,7 @@
 		clocks = <&mstp0_clks R8A7779_CLK_SCIF5>,
 			 <&cpg_clocks R8A7779_CLK_S1>, <&scif_clk>;
 		clock-names = "fck", "brg_int", "scif_clk";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7779_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -300,7 +304,7 @@
 			     <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp0_clks R8A7779_CLK_TMU0>;
 		clock-names = "fck";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7779_PD_ALWAYS_ON>;
 
 		#renesas,channels = <3>;
 
@@ -315,7 +319,7 @@
 			     <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp0_clks R8A7779_CLK_TMU1>;
 		clock-names = "fck";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7779_PD_ALWAYS_ON>;
 
 		#renesas,channels = <3>;
 
@@ -330,7 +334,7 @@
 			     <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp0_clks R8A7779_CLK_TMU2>;
 		clock-names = "fck";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7779_PD_ALWAYS_ON>;
 
 		#renesas,channels = <3>;
 
@@ -342,7 +346,7 @@
 		reg = <0xfc600000 0x2000>;
 		interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp1_clks R8A7779_CLK_SATA>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7779_PD_ALWAYS_ON>;
 	};
 
 	sdhi0: sd@ffe4c000 {
@@ -350,7 +354,7 @@
 		reg = <0xffe4c000 0x100>;
 		interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7779_CLK_SDHI0>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7779_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -359,7 +363,7 @@
 		reg = <0xffe4d000 0x100>;
 		interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7779_CLK_SDHI1>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7779_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -368,7 +372,7 @@
 		reg = <0xffe4e000 0x100>;
 		interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7779_CLK_SDHI2>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7779_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -377,7 +381,7 @@
 		reg = <0xffe4f000 0x100>;
 		interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7779_CLK_SDHI3>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7779_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -388,7 +392,7 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 		clocks = <&mstp0_clks R8A7779_CLK_HSPI>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7779_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -399,7 +403,7 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 		clocks = <&mstp0_clks R8A7779_CLK_HSPI>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7779_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -410,7 +414,7 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 		clocks = <&mstp0_clks R8A7779_CLK_HSPI>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7779_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -419,7 +423,7 @@
 		reg = <0 0xfff80000 0 0x40000>;
 		interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp1_clks R8A7779_CLK_DU>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7779_PD_ALWAYS_ON>;
 		status = "disabled";
 
 		ports {
@@ -445,12 +449,11 @@
 		ranges;
 
 		/* External root clock */
-		extal_clk: extal_clk {
+		extal_clk: extal {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			/* This value must be overriden by the board. */
 			clock-frequency = <0>;
-			clock-output-names = "extal";
 		};
 
 		/* External SCIF clock */
@@ -459,7 +462,6 @@
 			#clock-cells = <0>;
 			/* This value must be overridden by the board. */
 			clock-frequency = <0>;
-			status = "disabled";
 		};
 
 		/* Special CPG clocks */
@@ -474,37 +476,33 @@
 		};
 
 		/* Fixed factor clocks */
-		i_clk: i_clk {
+		i_clk: i {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7779_CLK_PLLA>;
 			#clock-cells = <0>;
 			clock-div = <2>;
 			clock-mult = <1>;
-			clock-output-names = "i";
 		};
-		s3_clk: s3_clk {
+		s3_clk: s3 {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7779_CLK_PLLA>;
 			#clock-cells = <0>;
 			clock-div = <8>;
 			clock-mult = <1>;
-			clock-output-names = "s3";
 		};
-		s4_clk: s4_clk {
+		s4_clk: s4 {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7779_CLK_PLLA>;
 			#clock-cells = <0>;
 			clock-div = <16>;
 			clock-mult = <1>;
-			clock-output-names = "s4";
 		};
-		g_clk: g_clk {
+		g_clk: g {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7779_CLK_PLLA>;
 			#clock-cells = <0>;
 			clock-div = <24>;
 			clock-mult = <1>;
-			clock-output-names = "g";
 		};
 
 		/* Gate clocks */
@@ -591,4 +589,10 @@
 				"mmc1", "mmc0";
 		};
 	};
+
+	sysc: system-controller@ffd85000 {
+		compatible = "renesas,r8a7779-sysc";
+		reg = <0xffd85000 0x0200>;
+		#power-domain-cells = <1>;
+	};
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/r8a7779-marzen.dts linux-libre-4.7-gnu/arch/arm/boot/dts/r8a7779-marzen.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/r8a7779-marzen.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/r8a7779-marzen.dts	2016-07-24 15:23:50.000000000 -0400
@@ -170,49 +170,49 @@
 
 	du_pins: du {
 		du0 {
-			renesas,groups = "du0_rgb888", "du0_sync_1", "du0_clk_out_0";
-			renesas,function = "du0";
+			groups = "du0_rgb888", "du0_sync_1", "du0_clk_out_0";
+			function = "du0";
 		};
 		du1 {
-			renesas,groups = "du1_rgb666", "du1_sync_1", "du1_clk_out";
-			renesas,function = "du1";
+			groups = "du1_rgb666", "du1_sync_1", "du1_clk_out";
+			function = "du1";
 		};
 	};
 
 	scif_clk_pins: scif_clk {
-		renesas,groups = "scif_clk_b";
-		renesas,function = "scif_clk";
+		groups = "scif_clk_b";
+		function = "scif_clk";
 	};
 
 	ethernet_pins: ethernet {
 		intc {
-			renesas,groups = "intc_irq1_b";
-			renesas,function = "intc";
+			groups = "intc_irq1_b";
+			function = "intc";
 		};
 		lbsc {
-			renesas,groups = "lbsc_ex_cs0";
-			renesas,function = "lbsc";
+			groups = "lbsc_ex_cs0";
+			function = "lbsc";
 		};
 	};
 
 	scif2_pins: serial2 {
-		renesas,groups = "scif2_data_c";
-		renesas,function = "scif2";
+		groups = "scif2_data_c";
+		function = "scif2";
 	};
 
 	scif4_pins: serial4 {
-		renesas,groups = "scif4_data";
-		renesas,function = "scif4";
+		groups = "scif4_data";
+		function = "scif4";
 	};
 
 	sdhi0_pins: sd0 {
-		renesas,groups = "sdhi0_data4", "sdhi0_ctrl", "sdhi0_cd";
-		renesas,function = "sdhi0";
+		groups = "sdhi0_data4", "sdhi0_ctrl", "sdhi0_cd";
+		function = "sdhi0";
 	};
 
 	hspi0_pins: hspi0 {
-		renesas,groups = "hspi0";
-		renesas,function = "hspi0";
+		groups = "hspi0";
+		function = "hspi0";
 	};
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/r8a7790.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/r8a7790.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/r8a7790.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/r8a7790.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -13,6 +13,7 @@
 #include <dt-bindings/clock/r8a7790-clock.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/power/r8a7790-sysc.h>
 
 / {
 	compatible = "renesas,r8a7790";
@@ -52,6 +53,7 @@
 			voltage-tolerance = <1>; /* 1% */
 			clocks = <&cpg_clocks R8A7790_CLK_Z>;
 			clock-latency = <300000>; /* 300 us */
+			power-domains = <&sysc R8A7790_PD_CA15_CPU0>;
 			next-level-cache = <&L2_CA15>;
 
 			/* kHz - uV - OPPs unknown yet */
@@ -68,6 +70,7 @@
 			compatible = "arm,cortex-a15";
 			reg = <1>;
 			clock-frequency = <1300000000>;
+			power-domains = <&sysc R8A7790_PD_CA15_CPU1>;
 			next-level-cache = <&L2_CA15>;
 		};
 
@@ -76,6 +79,7 @@
 			compatible = "arm,cortex-a15";
 			reg = <2>;
 			clock-frequency = <1300000000>;
+			power-domains = <&sysc R8A7790_PD_CA15_CPU2>;
 			next-level-cache = <&L2_CA15>;
 		};
 
@@ -84,6 +88,7 @@
 			compatible = "arm,cortex-a15";
 			reg = <3>;
 			clock-frequency = <1300000000>;
+			power-domains = <&sysc R8A7790_PD_CA15_CPU3>;
 			next-level-cache = <&L2_CA15>;
 		};
 
@@ -92,6 +97,7 @@
 			compatible = "arm,cortex-a7";
 			reg = <0x100>;
 			clock-frequency = <780000000>;
+			power-domains = <&sysc R8A7790_PD_CA7_CPU0>;
 			next-level-cache = <&L2_CA7>;
 		};
 
@@ -100,6 +106,7 @@
 			compatible = "arm,cortex-a7";
 			reg = <0x101>;
 			clock-frequency = <780000000>;
+			power-domains = <&sysc R8A7790_PD_CA7_CPU1>;
 			next-level-cache = <&L2_CA7>;
 		};
 
@@ -108,6 +115,7 @@
 			compatible = "arm,cortex-a7";
 			reg = <0x102>;
 			clock-frequency = <780000000>;
+			power-domains = <&sysc R8A7790_PD_CA7_CPU2>;
 			next-level-cache = <&L2_CA7>;
 		};
 
@@ -116,6 +124,7 @@
 			compatible = "arm,cortex-a7";
 			reg = <0x103>;
 			clock-frequency = <780000000>;
+			power-domains = <&sysc R8A7790_PD_CA7_CPU3>;
 			next-level-cache = <&L2_CA7>;
 		};
 	};
@@ -141,12 +150,14 @@
 
 	L2_CA15: cache-controller@0 {
 		compatible = "cache";
+		power-domains = <&sysc R8A7790_PD_CA15_SCU>;
 		cache-unified;
 		cache-level = <2>;
 	};
 
 	L2_CA7: cache-controller@1 {
 		compatible = "cache";
+		power-domains = <&sysc R8A7790_PD_CA7_SCU>;
 		cache-unified;
 		cache-level = <2>;
 	};
@@ -173,7 +184,7 @@
 		#interrupt-cells = <2>;
 		interrupt-controller;
 		clocks = <&mstp9_clks R8A7790_CLK_GPIO0>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 	};
 
 	gpio1: gpio@e6051000 {
@@ -186,7 +197,7 @@
 		#interrupt-cells = <2>;
 		interrupt-controller;
 		clocks = <&mstp9_clks R8A7790_CLK_GPIO1>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 	};
 
 	gpio2: gpio@e6052000 {
@@ -199,7 +210,7 @@
 		#interrupt-cells = <2>;
 		interrupt-controller;
 		clocks = <&mstp9_clks R8A7790_CLK_GPIO2>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 	};
 
 	gpio3: gpio@e6053000 {
@@ -212,7 +223,7 @@
 		#interrupt-cells = <2>;
 		interrupt-controller;
 		clocks = <&mstp9_clks R8A7790_CLK_GPIO3>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 	};
 
 	gpio4: gpio@e6054000 {
@@ -225,7 +236,7 @@
 		#interrupt-cells = <2>;
 		interrupt-controller;
 		clocks = <&mstp9_clks R8A7790_CLK_GPIO4>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 	};
 
 	gpio5: gpio@e6055000 {
@@ -238,7 +249,7 @@
 		#interrupt-cells = <2>;
 		interrupt-controller;
 		clocks = <&mstp9_clks R8A7790_CLK_GPIO5>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 	};
 
 	thermal: thermal@e61f0000 {
@@ -248,7 +259,7 @@
 		reg = <0 0xe61f0000 0 0x14>, <0 0xe61f0100 0 0x38>;
 		interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp5_clks R8A7790_CLK_THERMAL>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		#thermal-sensor-cells = <0>;
 	};
 
@@ -267,7 +278,7 @@
 			     <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp1_clks R8A7790_CLK_CMT0>;
 		clock-names = "fck";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 
 		renesas,channels-mask = <0x60>;
 
@@ -287,7 +298,7 @@
 			     <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7790_CLK_CMT1>;
 		clock-names = "fck";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 
 		renesas,channels-mask = <0xff>;
 
@@ -304,7 +315,7 @@
 			     <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>,
 			     <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp4_clks R8A7790_CLK_IRQC>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 	};
 
 	dmac0: dma-controller@e6700000 {
@@ -333,7 +344,7 @@
 				"ch12", "ch13", "ch14";
 		clocks = <&mstp2_clks R8A7790_CLK_SYS_DMAC0>;
 		clock-names = "fck";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		#dma-cells = <1>;
 		dma-channels = <15>;
 	};
@@ -364,7 +375,7 @@
 				"ch12", "ch13", "ch14";
 		clocks = <&mstp2_clks R8A7790_CLK_SYS_DMAC1>;
 		clock-names = "fck";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		#dma-cells = <1>;
 		dma-channels = <15>;
 	};
@@ -393,7 +404,7 @@
 				"ch12";
 		clocks = <&mstp5_clks R8A7790_CLK_AUDIO_DMAC0>;
 		clock-names = "fck";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		#dma-cells = <1>;
 		dma-channels = <13>;
 	};
@@ -422,7 +433,7 @@
 				"ch12";
 		clocks = <&mstp5_clks R8A7790_CLK_AUDIO_DMAC1>;
 		clock-names = "fck";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		#dma-cells = <1>;
 		dma-channels = <13>;
 	};
@@ -434,7 +445,7 @@
 			      GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "ch0", "ch1";
 		clocks = <&mstp3_clks R8A7790_CLK_USBDMAC0>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		#dma-cells = <1>;
 		dma-channels = <2>;
 	};
@@ -446,7 +457,7 @@
 			      GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "ch0", "ch1";
 		clocks = <&mstp3_clks R8A7790_CLK_USBDMAC1>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		#dma-cells = <1>;
 		dma-channels = <2>;
 	};
@@ -458,7 +469,7 @@
 		reg = <0 0xe6508000 0 0x40>;
 		interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7790_CLK_I2C0>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		i2c-scl-internal-delay-ns = <110>;
 		status = "disabled";
 	};
@@ -470,7 +481,7 @@
 		reg = <0 0xe6518000 0 0x40>;
 		interrupts = <GIC_SPI 288 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7790_CLK_I2C1>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		i2c-scl-internal-delay-ns = <6>;
 		status = "disabled";
 	};
@@ -482,7 +493,7 @@
 		reg = <0 0xe6530000 0 0x40>;
 		interrupts = <GIC_SPI 286 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7790_CLK_I2C2>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		i2c-scl-internal-delay-ns = <6>;
 		status = "disabled";
 	};
@@ -494,7 +505,7 @@
 		reg = <0 0xe6540000 0 0x40>;
 		interrupts = <GIC_SPI 290 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7790_CLK_I2C3>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		i2c-scl-internal-delay-ns = <110>;
 		status = "disabled";
 	};
@@ -508,7 +519,7 @@
 		clocks = <&mstp3_clks R8A7790_CLK_IIC0>;
 		dmas = <&dmac0 0x61>, <&dmac0 0x62>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -521,7 +532,7 @@
 		clocks = <&mstp3_clks R8A7790_CLK_IIC1>;
 		dmas = <&dmac0 0x65>, <&dmac0 0x66>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -534,7 +545,7 @@
 		clocks = <&mstp3_clks R8A7790_CLK_IIC2>;
 		dmas = <&dmac0 0x69>, <&dmac0 0x6a>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -547,7 +558,7 @@
 		clocks = <&mstp9_clks R8A7790_CLK_IICDVFS>;
 		dmas = <&dmac0 0x77>, <&dmac0 0x78>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -558,7 +569,7 @@
 		clocks = <&mstp3_clks R8A7790_CLK_MMCIF0>;
 		dmas = <&dmac0 0xd1>, <&dmac0 0xd2>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		reg-io-width = <4>;
 		status = "disabled";
 		max-frequency = <97500000>;
@@ -571,7 +582,7 @@
 		clocks = <&mstp3_clks R8A7790_CLK_MMCIF1>;
 		dmas = <&dmac0 0xe1>, <&dmac0 0xe2>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		reg-io-width = <4>;
 		status = "disabled";
 		max-frequency = <97500000>;
@@ -589,7 +600,8 @@
 		clocks = <&mstp3_clks R8A7790_CLK_SDHI0>;
 		dmas = <&dmac1 0xcd>, <&dmac1 0xce>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		max-frequency = <195000000>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -600,7 +612,8 @@
 		clocks = <&mstp3_clks R8A7790_CLK_SDHI1>;
 		dmas = <&dmac1 0xc9>, <&dmac1 0xca>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		max-frequency = <195000000>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -611,7 +624,8 @@
 		clocks = <&mstp3_clks R8A7790_CLK_SDHI2>;
 		dmas = <&dmac1 0xc1>, <&dmac1 0xc2>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		max-frequency = <97500000>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -622,7 +636,8 @@
 		clocks = <&mstp3_clks R8A7790_CLK_SDHI3>;
 		dmas = <&dmac1 0xd3>, <&dmac1 0xd4>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		max-frequency = <97500000>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -635,7 +650,7 @@
 		clock-names = "fck";
 		dmas = <&dmac0 0x21>, <&dmac0 0x22>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -648,7 +663,7 @@
 		clock-names = "fck";
 		dmas = <&dmac0 0x25>, <&dmac0 0x26>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -661,7 +676,7 @@
 		clock-names = "fck";
 		dmas = <&dmac0 0x27>, <&dmac0 0x28>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -674,7 +689,7 @@
 		clock-names = "fck";
 		dmas = <&dmac0 0x3d>, <&dmac0 0x3e>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -687,7 +702,7 @@
 		clock-names = "fck";
 		dmas = <&dmac0 0x19>, <&dmac0 0x1a>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -700,7 +715,7 @@
 		clock-names = "fck";
 		dmas = <&dmac0 0x1d>, <&dmac0 0x1e>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -714,7 +729,7 @@
 		clock-names = "fck", "brg_int", "scif_clk";
 		dmas = <&dmac0 0x29>, <&dmac0 0x2a>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -728,7 +743,21 @@
 		clock-names = "fck", "brg_int", "scif_clk";
 		dmas = <&dmac0 0x2d>, <&dmac0 0x2e>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
+		status = "disabled";
+	};
+
+	scif2: serial@e6e56000 {
+		compatible = "renesas,scif-r8a7790", "renesas,rcar-gen2-scif",
+			     "renesas,scif";
+		reg = <0 0xe6e56000 0 64>;
+		interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp3_clks R8A7790_CLK_SCIF2>, <&zs_clk>,
+			 <&scif_clk>;
+		clock-names = "fck", "brg_int", "scif_clk";
+		dmas = <&dmac0 0x2b>, <&dmac0 0x2c>;
+		dma-names = "tx", "rx";
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -742,7 +771,7 @@
 		clock-names = "fck", "brg_int", "scif_clk";
 		dmas = <&dmac0 0x39>, <&dmac0 0x3a>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -756,7 +785,7 @@
 		clock-names = "fck", "brg_int", "scif_clk";
 		dmas = <&dmac0 0x4d>, <&dmac0 0x4e>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -765,7 +794,7 @@
 		reg = <0 0xee700000 0 0x400>;
 		interrupts = <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp8_clks R8A7790_CLK_ETHER>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		phy-mode = "rmii";
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -778,7 +807,7 @@
 		reg = <0 0xe6800000 0 0x800>, <0 0xee0e8000 0 0x4000>;
 		interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp8_clks R8A7790_CLK_ETHERAVB>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		#address-cells = <1>;
 		#size-cells = <0>;
 		status = "disabled";
@@ -789,7 +818,7 @@
 		reg = <0 0xee300000 0 0x2000>;
 		interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp8_clks R8A7790_CLK_SATA0>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -798,7 +827,7 @@
 		reg = <0 0xee500000 0 0x2000>;
 		interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp8_clks R8A7790_CLK_SATA1>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -810,7 +839,7 @@
 		dmas = <&usb_dmac0 0>, <&usb_dmac0 1>,
 		       <&usb_dmac1 0>, <&usb_dmac1 1>;
 		dma-names = "ch0", "ch1", "ch2", "ch3";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		renesas,buswait = <4>;
 		phys = <&usb0 1>;
 		phy-names = "usb";
@@ -824,7 +853,7 @@
 		#size-cells = <0>;
 		clocks = <&mstp7_clks R8A7790_CLK_HSUSB>;
 		clock-names = "usbhs";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 
 		usb0: usb-channel@0 {
@@ -842,7 +871,7 @@
 		reg = <0 0xe6ef0000 0 0x1000>;
 		interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp8_clks R8A7790_CLK_VIN0>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -851,7 +880,7 @@
 		reg = <0 0xe6ef1000 0 0x1000>;
 		interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp8_clks R8A7790_CLK_VIN1>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -860,7 +889,7 @@
 		reg = <0 0xe6ef2000 0 0x1000>;
 		interrupts = <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp8_clks R8A7790_CLK_VIN2>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -869,7 +898,7 @@
 		reg = <0 0xe6ef3000 0 0x1000>;
 		interrupts = <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp8_clks R8A7790_CLK_VIN3>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -878,7 +907,7 @@
 		reg = <0 0xfe920000 0 0x8000>;
 		interrupts = <GIC_SPI 266 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp1_clks R8A7790_CLK_VSP1_R>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 
 		renesas,has-sru;
 		renesas,#rpf = <5>;
@@ -891,7 +920,7 @@
 		reg = <0 0xfe928000 0 0x8000>;
 		interrupts = <GIC_SPI 267 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp1_clks R8A7790_CLK_VSP1_S>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 
 		renesas,has-lut;
 		renesas,has-sru;
@@ -905,7 +934,7 @@
 		reg = <0 0xfe930000 0 0x8000>;
 		interrupts = <GIC_SPI 246 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp1_clks R8A7790_CLK_VSP1_DU0>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 
 		renesas,has-lif;
 		renesas,has-lut;
@@ -919,7 +948,7 @@
 		reg = <0 0xfe938000 0 0x8000>;
 		interrupts = <GIC_SPI 247 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp1_clks R8A7790_CLK_VSP1_DU1>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 
 		renesas,has-lif;
 		renesas,has-lut;
@@ -968,33 +997,33 @@
 	};
 
 	can0: can@e6e80000 {
-		compatible = "renesas,can-r8a7790";
+		compatible = "renesas,can-r8a7790", "renesas,rcar-gen2-can";
 		reg = <0 0xe6e80000 0 0x1000>;
 		interrupts = <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7790_CLK_RCAN0>,
 			 <&cpg_clocks R8A7790_CLK_RCAN>, <&can_clk>;
 		clock-names = "clkp1", "clkp2", "can_clk";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
 	can1: can@e6e88000 {
-		compatible = "renesas,can-r8a7790";
+		compatible = "renesas,can-r8a7790", "renesas,rcar-gen2-can";
 		reg = <0 0xe6e88000 0 0x1000>;
 		interrupts = <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7790_CLK_RCAN1>,
 			 <&cpg_clocks R8A7790_CLK_RCAN>, <&can_clk>;
 		clock-names = "clkp1", "clkp2", "can_clk";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
 	jpu: jpeg-codec@fe980000 {
-		compatible = "renesas,jpu-r8a7790";
+		compatible = "renesas,jpu-r8a7790", "renesas,rcar-gen2-jpu";
 		reg = <0 0xfe980000 0 0x10300>;
 		interrupts = <GIC_SPI 272 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp1_clks R8A7790_CLK_JPU>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 	};
 
 	clocks {
@@ -1003,21 +1032,18 @@
 		ranges;
 
 		/* External root clock */
-		extal_clk: extal_clk {
+		extal_clk: extal {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			/* This value must be overriden by the board. */
 			clock-frequency = <0>;
-			clock-output-names = "extal";
 		};
 
 		/* External PCIe clock - can be overridden by the board */
-		pcie_bus_clk: pcie_bus_clk {
+		pcie_bus_clk: pcie_bus {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
-			clock-frequency = <100000000>;
-			clock-output-names = "pcie_bus";
-			status = "disabled";
+			clock-frequency = <0>;
 		};
 
 		/*
@@ -1028,19 +1054,16 @@
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <0>;
-			clock-output-names = "audio_clk_a";
 		};
 		audio_clk_b: audio_clk_b {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <0>;
-			clock-output-names = "audio_clk_b";
 		};
 		audio_clk_c: audio_clk_c {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <0>;
-			clock-output-names = "audio_clk_c";
 		};
 
 		/* External SCIF clock */
@@ -1049,15 +1072,13 @@
 			#clock-cells = <0>;
 			/* This value must be overridden by the board. */
 			clock-frequency = <0>;
-			status = "disabled";
 		};
 
 		/* External USB clock - can be overridden by the board */
-		usb_extal_clk: usb_extal_clk {
+		usb_extal_clk: usb_extal {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <48000000>;
-			clock-output-names = "usb_extal";
 		};
 
 		/* External CAN clock */
@@ -1066,8 +1087,6 @@
 			#clock-cells = <0>;
 			/* This value must be overridden by the board. */
 			clock-frequency = <0>;
-			clock-output-names = "can_clk";
-			status = "disabled";
 		};
 
 		/* Special CPG clocks */
@@ -1084,201 +1103,176 @@
 		};
 
 		/* Variable factor clocks */
-		sd2_clk: sd2_clk@e6150078 {
+		sd2_clk: sd2@e6150078 {
 			compatible = "renesas,r8a7790-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0 0xe6150078 0 4>;
 			clocks = <&pll1_div2_clk>;
 			#clock-cells = <0>;
-			clock-output-names = "sd2";
 		};
-		sd3_clk: sd3_clk@e615026c {
+		sd3_clk: sd3@e615026c {
 			compatible = "renesas,r8a7790-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0 0xe615026c 0 4>;
 			clocks = <&pll1_div2_clk>;
 			#clock-cells = <0>;
-			clock-output-names = "sd3";
 		};
-		mmc0_clk: mmc0_clk@e6150240 {
+		mmc0_clk: mmc0@e6150240 {
 			compatible = "renesas,r8a7790-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0 0xe6150240 0 4>;
 			clocks = <&pll1_div2_clk>;
 			#clock-cells = <0>;
-			clock-output-names = "mmc0";
 		};
-		mmc1_clk: mmc1_clk@e6150244 {
+		mmc1_clk: mmc1@e6150244 {
 			compatible = "renesas,r8a7790-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0 0xe6150244 0 4>;
 			clocks = <&pll1_div2_clk>;
 			#clock-cells = <0>;
-			clock-output-names = "mmc1";
 		};
-		ssp_clk: ssp_clk@e6150248 {
+		ssp_clk: ssp@e6150248 {
 			compatible = "renesas,r8a7790-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0 0xe6150248 0 4>;
 			clocks = <&pll1_div2_clk>;
 			#clock-cells = <0>;
-			clock-output-names = "ssp";
 		};
-		ssprs_clk: ssprs_clk@e615024c {
+		ssprs_clk: ssprs@e615024c {
 			compatible = "renesas,r8a7790-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0 0xe615024c 0 4>;
 			clocks = <&pll1_div2_clk>;
 			#clock-cells = <0>;
-			clock-output-names = "ssprs";
 		};
 
 		/* Fixed factor clocks */
-		pll1_div2_clk: pll1_div2_clk {
+		pll1_div2_clk: pll1_div2 {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7790_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <2>;
 			clock-mult = <1>;
-			clock-output-names = "pll1_div2";
 		};
-		z2_clk: z2_clk {
+		z2_clk: z2 {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7790_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <2>;
 			clock-mult = <1>;
-			clock-output-names = "z2";
 		};
-		zg_clk: zg_clk {
+		zg_clk: zg {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7790_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <3>;
 			clock-mult = <1>;
-			clock-output-names = "zg";
 		};
-		zx_clk: zx_clk {
+		zx_clk: zx {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7790_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <3>;
 			clock-mult = <1>;
-			clock-output-names = "zx";
 		};
-		zs_clk: zs_clk {
+		zs_clk: zs {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7790_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <6>;
 			clock-mult = <1>;
-			clock-output-names = "zs";
 		};
-		hp_clk: hp_clk {
+		hp_clk: hp {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7790_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <12>;
 			clock-mult = <1>;
-			clock-output-names = "hp";
 		};
-		i_clk: i_clk {
+		i_clk: i {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7790_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <2>;
 			clock-mult = <1>;
-			clock-output-names = "i";
 		};
-		b_clk: b_clk {
+		b_clk: b {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7790_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <12>;
 			clock-mult = <1>;
-			clock-output-names = "b";
 		};
-		p_clk: p_clk {
+		p_clk: p {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7790_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <24>;
 			clock-mult = <1>;
-			clock-output-names = "p";
 		};
-		cl_clk: cl_clk {
+		cl_clk: cl {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7790_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <48>;
 			clock-mult = <1>;
-			clock-output-names = "cl";
 		};
-		m2_clk: m2_clk {
+		m2_clk: m2 {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7790_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <8>;
 			clock-mult = <1>;
-			clock-output-names = "m2";
 		};
-		imp_clk: imp_clk {
+		imp_clk: imp {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7790_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <4>;
 			clock-mult = <1>;
-			clock-output-names = "imp";
 		};
-		rclk_clk: rclk_clk {
+		rclk_clk: rclk {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7790_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <(48 * 1024)>;
 			clock-mult = <1>;
-			clock-output-names = "rclk";
 		};
-		oscclk_clk: oscclk_clk {
+		oscclk_clk: oscclk {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7790_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <(12 * 1024)>;
 			clock-mult = <1>;
-			clock-output-names = "oscclk";
 		};
-		zb3_clk: zb3_clk {
+		zb3_clk: zb3 {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7790_CLK_PLL3>;
 			#clock-cells = <0>;
 			clock-div = <4>;
 			clock-mult = <1>;
-			clock-output-names = "zb3";
 		};
-		zb3d2_clk: zb3d2_clk {
+		zb3d2_clk: zb3d2 {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7790_CLK_PLL3>;
 			#clock-cells = <0>;
 			clock-div = <8>;
 			clock-mult = <1>;
-			clock-output-names = "zb3d2";
 		};
-		ddr_clk: ddr_clk {
+		ddr_clk: ddr {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7790_CLK_PLL3>;
 			#clock-cells = <0>;
 			clock-div = <8>;
 			clock-mult = <1>;
-			clock-output-names = "ddr";
 		};
-		mp_clk: mp_clk {
+		mp_clk: mp {
 			compatible = "fixed-factor-clock";
 			clocks = <&pll1_div2_clk>;
 			#clock-cells = <0>;
 			clock-div = <15>;
 			clock-mult = <1>;
-			clock-output-names = "mp";
 		};
-		cp_clk: cp_clk {
+		cp_clk: cp {
 			compatible = "fixed-factor-clock";
 			clocks = <&extal_clk>;
 			#clock-cells = <0>;
 			clock-div = <2>;
 			clock-mult = <1>;
-			clock-output-names = "cp";
 		};
 
 		/* Gate clocks */
@@ -1334,19 +1328,19 @@
 		mstp3_clks: mstp3_clks@e615013c {
 			compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks";
 			reg = <0 0xe615013c 0 4>, <0 0xe6150048 0 4>;
-			clocks = <&hp_clk>, <&cp_clk>, <&mmc1_clk>, <&sd3_clk>,
+			clocks = <&hp_clk>, <&cp_clk>, <&mmc1_clk>, <&p_clk>, <&sd3_clk>,
 				 <&sd2_clk>, <&cpg_clocks R8A7790_CLK_SD1>, <&cpg_clocks R8A7790_CLK_SD0>, <&mmc0_clk>,
 				 <&hp_clk>, <&mp_clk>, <&hp_clk>, <&mp_clk>, <&rclk_clk>,
 				 <&hp_clk>, <&hp_clk>;
 			#clock-cells = <1>;
 			clock-indices = <
-				R8A7790_CLK_IIC2 R8A7790_CLK_TPU0 R8A7790_CLK_MMCIF1 R8A7790_CLK_SDHI3
+				R8A7790_CLK_IIC2 R8A7790_CLK_TPU0 R8A7790_CLK_MMCIF1 R8A7790_CLK_SCIF2 R8A7790_CLK_SDHI3
 				R8A7790_CLK_SDHI2 R8A7790_CLK_SDHI1 R8A7790_CLK_SDHI0 R8A7790_CLK_MMCIF0
 				R8A7790_CLK_IIC0 R8A7790_CLK_PCIEC R8A7790_CLK_IIC1 R8A7790_CLK_SSUSB R8A7790_CLK_CMT1
 				R8A7790_CLK_USBDMAC0 R8A7790_CLK_USBDMAC1
 			>;
 			clock-output-names =
-				"iic2", "tpu0", "mmcif1", "sdhi3",
+				"iic2", "tpu0", "mmcif1", "scif2", "sdhi3",
 				"sdhi2", "sdhi1", "sdhi0", "mmcif0",
 				"iic0", "pciec", "iic1", "ssusb", "cmt1",
 				"usbdmac0", "usbdmac1";
@@ -1464,6 +1458,12 @@
 		};
 	};
 
+	sysc: system-controller@e6180000 {
+		compatible = "renesas,r8a7790-sysc";
+		reg = <0 0xe6180000 0 0x0200>;
+		#power-domain-cells = <1>;
+	};
+
 	qspi: spi@e6b10000 {
 		compatible = "renesas,qspi-r8a7790", "renesas,qspi";
 		reg = <0 0xe6b10000 0 0x2c>;
@@ -1471,7 +1471,7 @@
 		clocks = <&mstp9_clks R8A7790_CLK_QSPI_MOD>;
 		dmas = <&dmac0 0x17>, <&dmac0 0x18>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		num-cs = <1>;
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -1485,7 +1485,7 @@
 		clocks = <&mstp0_clks R8A7790_CLK_MSIOF0>;
 		dmas = <&dmac0 0x51>, <&dmac0 0x52>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		#address-cells = <1>;
 		#size-cells = <0>;
 		status = "disabled";
@@ -1498,7 +1498,7 @@
 		clocks = <&mstp2_clks R8A7790_CLK_MSIOF1>;
 		dmas = <&dmac0 0x55>, <&dmac0 0x56>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		#address-cells = <1>;
 		#size-cells = <0>;
 		status = "disabled";
@@ -1511,7 +1511,7 @@
 		clocks = <&mstp2_clks R8A7790_CLK_MSIOF2>;
 		dmas = <&dmac0 0x41>, <&dmac0 0x42>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		#address-cells = <1>;
 		#size-cells = <0>;
 		status = "disabled";
@@ -1524,18 +1524,18 @@
 		clocks = <&mstp2_clks R8A7790_CLK_MSIOF3>;
 		dmas = <&dmac0 0x45>, <&dmac0 0x46>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		#address-cells = <1>;
 		#size-cells = <0>;
 		status = "disabled";
 	};
 
 	xhci: usb@ee000000 {
-		compatible = "renesas,xhci-r8a7790";
+		compatible = "renesas,xhci-r8a7790", "renesas,rcar-gen2-xhci";
 		reg = <0 0xee000000 0 0xc00>;
 		interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7790_CLK_SSUSB>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		phys = <&usb2 1>;
 		phy-names = "usb";
 		status = "disabled";
@@ -1548,7 +1548,7 @@
 		      <0 0xee080000 0 0x1100>;
 		interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp7_clks R8A7790_CLK_EHCI>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 
 		bus-range = <0 0>;
@@ -1583,7 +1583,7 @@
 		      <0 0xee0a0000 0 0x1100>;
 		interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp7_clks R8A7790_CLK_EHCI>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 
 		bus-range = <1 1>;
@@ -1601,7 +1601,7 @@
 		compatible = "renesas,pci-r8a7790", "renesas,pci-rcar-gen2";
 		device_type = "pci";
 		clocks = <&mstp7_clks R8A7790_CLK_EHCI>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		reg = <0 0xee0d0000 0 0xc00>,
 		      <0 0xee0c0000 0 0x1100>;
 		interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
@@ -1654,7 +1654,7 @@
 		interrupt-map = <0 0 0 0 &gic GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7790_CLK_PCIEC>, <&pcie_bus_clk>;
 		clock-names = "pcie", "pcie_bus";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -1697,7 +1697,7 @@
 				"mix.0", "mix.1",
 				"dvc.0", "dvc.1",
 				"clk_a", "clk_b", "clk_c", "clk_i";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
 
 		status = "disabled";
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/r8a7790-lager.dts linux-libre-4.7-gnu/arch/arm/boot/dts/r8a7790-lager.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/r8a7790-lager.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/r8a7790-lager.dts	2016-07-24 15:23:50.000000000 -0400
@@ -176,11 +176,10 @@
 			  1800000 0>;
 	};
 
-	audio_clock: clock {
+	audio_clock: audio_clock {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
 		clock-frequency = <11289600>;
-		clock-output-names = "audio_clock";
 	};
 
 	rsnd_ak4643: sound {
@@ -314,119 +313,133 @@
 	pinctrl-names = "default";
 
 	du_pins: du {
-		renesas,groups = "du_rgb666", "du_sync_1", "du_clk_out_0";
-		renesas,function = "du";
+		groups = "du_rgb666", "du_sync_1", "du_clk_out_0";
+		function = "du";
 	};
 
 	scif0_pins: serial0 {
-		renesas,groups = "scif0_data";
-		renesas,function = "scif0";
+		groups = "scif0_data";
+		function = "scif0";
 	};
 
 	scif_clk_pins: scif_clk {
-		renesas,groups = "scif_clk";
-		renesas,function = "scif_clk";
+		groups = "scif_clk";
+		function = "scif_clk";
 	};
 
 	ether_pins: ether {
-		renesas,groups = "eth_link", "eth_mdio", "eth_rmii";
-		renesas,function = "eth";
+		groups = "eth_link", "eth_mdio", "eth_rmii";
+		function = "eth";
 	};
 
 	phy1_pins: phy1 {
-		renesas,groups = "intc_irq0";
-		renesas,function = "intc";
+		groups = "intc_irq0";
+		function = "intc";
 	};
 
 	scifa1_pins: serial1 {
-		renesas,groups = "scifa1_data";
-		renesas,function = "scifa1";
+		groups = "scifa1_data";
+		function = "scifa1";
 	};
 
 	sdhi0_pins: sd0 {
-		renesas,groups = "sdhi0_data4", "sdhi0_ctrl";
-		renesas,function = "sdhi0";
+		groups = "sdhi0_data4", "sdhi0_ctrl";
+		function = "sdhi0";
+		power-source = <3300>;
+	};
+
+	sdhi0_pins_uhs: sd0_uhs {
+		groups = "sdhi0_data4", "sdhi0_ctrl";
+		function = "sdhi0";
+		power-source = <1800>;
 	};
 
 	sdhi2_pins: sd2 {
-		renesas,groups = "sdhi2_data4", "sdhi2_ctrl";
-		renesas,function = "sdhi2";
+		groups = "sdhi2_data4", "sdhi2_ctrl";
+		function = "sdhi2";
+		power-source = <3300>;
+	};
+
+	sdhi2_pins_uhs: sd2_uhs {
+		groups = "sdhi2_data4", "sdhi2_ctrl";
+		function = "sdhi2";
+		power-source = <1800>;
 	};
 
 	mmc1_pins: mmc1 {
-		renesas,groups = "mmc1_data8", "mmc1_ctrl";
-		renesas,function = "mmc1";
+		groups = "mmc1_data8", "mmc1_ctrl";
+		function = "mmc1";
 	};
 
 	qspi_pins: spi0 {
-		renesas,groups = "qspi_ctrl", "qspi_data4";
-		renesas,function = "qspi";
+		groups = "qspi_ctrl", "qspi_data4";
+		function = "qspi";
 	};
 
 	msiof1_pins: spi2 {
-		renesas,groups = "msiof1_clk", "msiof1_sync", "msiof1_rx",
+		groups = "msiof1_clk", "msiof1_sync", "msiof1_rx",
 				 "msiof1_tx";
-		renesas,function = "msiof1";
+		function = "msiof1";
 	};
 
 	i2c0_pins: i2c0 {
-		renesas,groups = "i2c0";
-		renesas,function = "i2c0";
+		groups = "i2c0";
+		function = "i2c0";
 	};
 
 	iic0_pins: iic0 {
-		renesas,groups = "iic0";
-		renesas,function = "iic0";
+		groups = "iic0";
+		function = "iic0";
 	};
 
 	iic1_pins: iic1 {
-		renesas,groups = "iic1";
-		renesas,function = "iic1";
+		groups = "iic1";
+		function = "iic1";
 	};
 
 	iic2_pins: iic2 {
-		renesas,groups = "iic2";
-		renesas,function = "iic2";
+		groups = "iic2";
+		function = "iic2";
 	};
 
 	iic3_pins: iic3 {
-		renesas,groups = "iic3";
-		renesas,function = "iic3";
+		groups = "iic3";
+		function = "iic3";
 	};
 
 	hsusb_pins: hsusb {
-		renesas,groups = "usb0_ovc_vbus";
-		renesas,function = "usb0";
+		groups = "usb0_ovc_vbus";
+		function = "usb0";
 	};
 
 	usb0_pins: usb0 {
-		renesas,groups = "usb0";
-		renesas,function = "usb0";
+		groups = "usb0";
+		function = "usb0";
 	};
 
 	usb1_pins: usb1 {
-		renesas,groups = "usb1";
-		renesas,function = "usb1";
+		groups = "usb1";
+		function = "usb1";
 	};
 
 	usb2_pins: usb2 {
-		renesas,groups = "usb2";
-		renesas,function = "usb2";
+		groups = "usb2";
+		function = "usb2";
 	};
 
 	vin1_pins: vin {
-		renesas,groups = "vin1_data8", "vin1_clk";
-		renesas,function = "vin1";
+		groups = "vin1_data8", "vin1_clk";
+		function = "vin1";
 	};
 
 	sound_pins: sound {
-		renesas,groups = "ssi0129_ctrl", "ssi0_data", "ssi1_data";
-		renesas,function = "ssi";
+		groups = "ssi0129_ctrl", "ssi0_data", "ssi1_data";
+		function = "ssi";
 	};
 
 	sound_clk_pins: sound_clk {
-		renesas,groups = "audio_clk_a";
-		renesas,function = "audio_clk";
+		groups = "audio_clk_a";
+		function = "audio_clk";
 	};
 };
 
@@ -539,21 +552,25 @@
 
 &sdhi0 {
 	pinctrl-0 = <&sdhi0_pins>;
-	pinctrl-names = "default";
+	pinctrl-1 = <&sdhi0_pins_uhs>;
+	pinctrl-names = "default", "state_uhs";
 
 	vmmc-supply = <&vcc_sdhi0>;
 	vqmmc-supply = <&vccq_sdhi0>;
 	cd-gpios = <&gpio3 6 GPIO_ACTIVE_LOW>;
+	sd-uhs-sdr50;
 	status = "okay";
 };
 
 &sdhi2 {
 	pinctrl-0 = <&sdhi2_pins>;
-	pinctrl-names = "default";
+	pinctrl-1 = <&sdhi2_pins_uhs>;
+	pinctrl-names = "default", "state_uhs";
 
 	vmmc-supply = <&vcc_sdhi2>;
 	vqmmc-supply = <&vccq_sdhi2>;
 	cd-gpios = <&gpio3 22 GPIO_ACTIVE_LOW>;
+	sd-uhs-sdr50;
 	status = "okay";
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/r8a7791.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/r8a7791.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/r8a7791.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/r8a7791.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -13,6 +13,7 @@
 #include <dt-bindings/clock/r8a7791-clock.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/power/r8a7791-sysc.h>
 
 / {
 	compatible = "renesas,r8a7791";
@@ -51,6 +52,7 @@
 			voltage-tolerance = <1>; /* 1% */
 			clocks = <&cpg_clocks R8A7791_CLK_Z>;
 			clock-latency = <300000>; /* 300 us */
+			power-domains = <&sysc R8A7791_PD_CA15_CPU0>;
 			next-level-cache = <&L2_CA15>;
 
 			/* kHz - uV - OPPs unknown yet */
@@ -67,6 +69,7 @@
 			compatible = "arm,cortex-a15";
 			reg = <1>;
 			clock-frequency = <1500000000>;
+			power-domains = <&sysc R8A7791_PD_CA15_CPU1>;
 			next-level-cache = <&L2_CA15>;
 		};
 	};
@@ -92,6 +95,7 @@
 
 	L2_CA15: cache-controller@0 {
 		compatible = "cache";
+		power-domains = <&sysc R8A7791_PD_CA15_SCU>;
 		cache-unified;
 		cache-level = <2>;
 	};
@@ -118,7 +122,7 @@
 		#interrupt-cells = <2>;
 		interrupt-controller;
 		clocks = <&mstp9_clks R8A7791_CLK_GPIO0>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 	};
 
 	gpio1: gpio@e6051000 {
@@ -131,7 +135,7 @@
 		#interrupt-cells = <2>;
 		interrupt-controller;
 		clocks = <&mstp9_clks R8A7791_CLK_GPIO1>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 	};
 
 	gpio2: gpio@e6052000 {
@@ -144,7 +148,7 @@
 		#interrupt-cells = <2>;
 		interrupt-controller;
 		clocks = <&mstp9_clks R8A7791_CLK_GPIO2>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 	};
 
 	gpio3: gpio@e6053000 {
@@ -157,7 +161,7 @@
 		#interrupt-cells = <2>;
 		interrupt-controller;
 		clocks = <&mstp9_clks R8A7791_CLK_GPIO3>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 	};
 
 	gpio4: gpio@e6054000 {
@@ -170,7 +174,7 @@
 		#interrupt-cells = <2>;
 		interrupt-controller;
 		clocks = <&mstp9_clks R8A7791_CLK_GPIO4>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 	};
 
 	gpio5: gpio@e6055000 {
@@ -183,7 +187,7 @@
 		#interrupt-cells = <2>;
 		interrupt-controller;
 		clocks = <&mstp9_clks R8A7791_CLK_GPIO5>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 	};
 
 	gpio6: gpio@e6055400 {
@@ -196,7 +200,7 @@
 		#interrupt-cells = <2>;
 		interrupt-controller;
 		clocks = <&mstp9_clks R8A7791_CLK_GPIO6>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 	};
 
 	gpio7: gpio@e6055800 {
@@ -209,7 +213,7 @@
 		#interrupt-cells = <2>;
 		interrupt-controller;
 		clocks = <&mstp9_clks R8A7791_CLK_GPIO7>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 	};
 
 	thermal: thermal@e61f0000 {
@@ -219,7 +223,7 @@
 		reg = <0 0xe61f0000 0 0x14>, <0 0xe61f0100 0 0x38>;
 		interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp5_clks R8A7791_CLK_THERMAL>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		#thermal-sensor-cells = <0>;
 	};
 
@@ -238,7 +242,7 @@
 			     <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp1_clks R8A7791_CLK_CMT0>;
 		clock-names = "fck";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 
 		renesas,channels-mask = <0x60>;
 
@@ -258,7 +262,7 @@
 			     <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7791_CLK_CMT1>;
 		clock-names = "fck";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 
 		renesas,channels-mask = <0xff>;
 
@@ -281,7 +285,7 @@
 			     <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>,
 			     <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp4_clks R8A7791_CLK_IRQC>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 	};
 
 	dmac0: dma-controller@e6700000 {
@@ -310,7 +314,7 @@
 				"ch12", "ch13", "ch14";
 		clocks = <&mstp2_clks R8A7791_CLK_SYS_DMAC0>;
 		clock-names = "fck";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		#dma-cells = <1>;
 		dma-channels = <15>;
 	};
@@ -341,7 +345,7 @@
 				"ch12", "ch13", "ch14";
 		clocks = <&mstp2_clks R8A7791_CLK_SYS_DMAC1>;
 		clock-names = "fck";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		#dma-cells = <1>;
 		dma-channels = <15>;
 	};
@@ -370,7 +374,7 @@
 				"ch12";
 		clocks = <&mstp5_clks R8A7791_CLK_AUDIO_DMAC0>;
 		clock-names = "fck";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		#dma-cells = <1>;
 		dma-channels = <13>;
 	};
@@ -399,7 +403,7 @@
 				"ch12";
 		clocks = <&mstp5_clks R8A7791_CLK_AUDIO_DMAC1>;
 		clock-names = "fck";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		#dma-cells = <1>;
 		dma-channels = <13>;
 	};
@@ -411,7 +415,7 @@
 			      GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "ch0", "ch1";
 		clocks = <&mstp3_clks R8A7791_CLK_USBDMAC0>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		#dma-cells = <1>;
 		dma-channels = <2>;
 	};
@@ -423,7 +427,7 @@
 			      GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "ch0", "ch1";
 		clocks = <&mstp3_clks R8A7791_CLK_USBDMAC1>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		#dma-cells = <1>;
 		dma-channels = <2>;
 	};
@@ -436,7 +440,7 @@
 		reg = <0 0xe6508000 0 0x40>;
 		interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7791_CLK_I2C0>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		i2c-scl-internal-delay-ns = <6>;
 		status = "disabled";
 	};
@@ -448,7 +452,7 @@
 		reg = <0 0xe6518000 0 0x40>;
 		interrupts = <GIC_SPI 288 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7791_CLK_I2C1>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		i2c-scl-internal-delay-ns = <6>;
 		status = "disabled";
 	};
@@ -460,7 +464,7 @@
 		reg = <0 0xe6530000 0 0x40>;
 		interrupts = <GIC_SPI 286 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7791_CLK_I2C2>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		i2c-scl-internal-delay-ns = <6>;
 		status = "disabled";
 	};
@@ -472,7 +476,7 @@
 		reg = <0 0xe6540000 0 0x40>;
 		interrupts = <GIC_SPI 290 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7791_CLK_I2C3>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		i2c-scl-internal-delay-ns = <6>;
 		status = "disabled";
 	};
@@ -484,7 +488,7 @@
 		reg = <0 0xe6520000 0 0x40>;
 		interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7791_CLK_I2C4>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		i2c-scl-internal-delay-ns = <6>;
 		status = "disabled";
 	};
@@ -497,7 +501,7 @@
 		reg = <0 0xe6528000 0 0x40>;
 		interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7791_CLK_I2C5>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		i2c-scl-internal-delay-ns = <110>;
 		status = "disabled";
 	};
@@ -512,7 +516,7 @@
 		clocks = <&mstp9_clks R8A7791_CLK_IICDVFS>;
 		dmas = <&dmac0 0x77>, <&dmac0 0x78>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -525,7 +529,7 @@
 		clocks = <&mstp3_clks R8A7791_CLK_IIC0>;
 		dmas = <&dmac0 0x61>, <&dmac0 0x62>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -538,7 +542,7 @@
 		clocks = <&mstp3_clks R8A7791_CLK_IIC1>;
 		dmas = <&dmac0 0x65>, <&dmac0 0x66>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -554,7 +558,7 @@
 		clocks = <&mstp3_clks R8A7791_CLK_MMCIF0>;
 		dmas = <&dmac0 0xd1>, <&dmac0 0xd2>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		reg-io-width = <4>;
 		status = "disabled";
 		max-frequency = <97500000>;
@@ -567,7 +571,7 @@
 		clocks = <&mstp3_clks R8A7791_CLK_SDHI0>;
 		dmas = <&dmac1 0xcd>, <&dmac1 0xce>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -578,7 +582,7 @@
 		clocks = <&mstp3_clks R8A7791_CLK_SDHI1>;
 		dmas = <&dmac1 0xc1>, <&dmac1 0xc2>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -589,7 +593,7 @@
 		clocks = <&mstp3_clks R8A7791_CLK_SDHI2>;
 		dmas = <&dmac1 0xd3>, <&dmac1 0xd4>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -602,7 +606,7 @@
 		clock-names = "fck";
 		dmas = <&dmac0 0x21>, <&dmac0 0x22>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -615,7 +619,7 @@
 		clock-names = "fck";
 		dmas = <&dmac0 0x25>, <&dmac0 0x26>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -628,7 +632,7 @@
 		clock-names = "fck";
 		dmas = <&dmac0 0x27>, <&dmac0 0x28>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -641,7 +645,7 @@
 		clock-names = "fck";
 		dmas = <&dmac0 0x1b>, <&dmac0 0x1c>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -654,7 +658,7 @@
 		clock-names = "fck";
 		dmas = <&dmac0 0x1f>, <&dmac0 0x20>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -667,7 +671,7 @@
 		clock-names = "fck";
 		dmas = <&dmac0 0x23>, <&dmac0 0x24>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -680,7 +684,7 @@
 		clock-names = "fck";
 		dmas = <&dmac0 0x3d>, <&dmac0 0x3e>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -693,7 +697,7 @@
 		clock-names = "fck";
 		dmas = <&dmac0 0x19>, <&dmac0 0x1a>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -706,7 +710,7 @@
 		clock-names = "fck";
 		dmas = <&dmac0 0x1d>, <&dmac0 0x1e>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -720,7 +724,7 @@
 		clock-names = "fck", "brg_int", "scif_clk";
 		dmas = <&dmac0 0x29>, <&dmac0 0x2a>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -734,7 +738,7 @@
 		clock-names = "fck", "brg_int", "scif_clk";
 		dmas = <&dmac0 0x2d>, <&dmac0 0x2e>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -748,7 +752,7 @@
 		clock-names = "fck", "brg_int", "scif_clk";
 		dmas = <&dmac0 0x2b>, <&dmac0 0x2c>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -762,7 +766,7 @@
 		clock-names = "fck", "brg_int", "scif_clk";
 		dmas = <&dmac0 0x2f>, <&dmac0 0x30>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -776,7 +780,7 @@
 		clock-names = "fck", "brg_int", "scif_clk";
 		dmas = <&dmac0 0xfb>, <&dmac0 0xfc>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -790,7 +794,7 @@
 		clock-names = "fck", "brg_int", "scif_clk";
 		dmas = <&dmac0 0xfd>, <&dmac0 0xfe>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -804,7 +808,7 @@
 		clock-names = "fck", "brg_int", "scif_clk";
 		dmas = <&dmac0 0x39>, <&dmac0 0x3a>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -818,7 +822,7 @@
 		clock-names = "fck", "brg_int", "scif_clk";
 		dmas = <&dmac0 0x4d>, <&dmac0 0x4e>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -832,7 +836,7 @@
 		clock-names = "fck", "brg_int", "scif_clk";
 		dmas = <&dmac0 0x3b>, <&dmac0 0x3c>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -841,7 +845,7 @@
 		reg = <0 0xee700000 0 0x400>;
 		interrupts = <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp8_clks R8A7791_CLK_ETHER>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		phy-mode = "rmii";
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -854,7 +858,7 @@
 		reg = <0 0xe6800000 0 0x800>, <0 0xee0e8000 0 0x4000>;
 		interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp8_clks R8A7791_CLK_ETHERAVB>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		#address-cells = <1>;
 		#size-cells = <0>;
 		status = "disabled";
@@ -865,7 +869,7 @@
 		reg = <0 0xee300000 0 0x2000>;
 		interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp8_clks R8A7791_CLK_SATA0>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -874,7 +878,7 @@
 		reg = <0 0xee500000 0 0x2000>;
 		interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp8_clks R8A7791_CLK_SATA1>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -886,7 +890,7 @@
 		dmas = <&usb_dmac0 0>, <&usb_dmac0 1>,
 		       <&usb_dmac1 0>, <&usb_dmac1 1>;
 		dma-names = "ch0", "ch1", "ch2", "ch3";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		renesas,buswait = <4>;
 		phys = <&usb0 1>;
 		phy-names = "usb";
@@ -900,7 +904,7 @@
 		#size-cells = <0>;
 		clocks = <&mstp7_clks R8A7791_CLK_HSUSB>;
 		clock-names = "usbhs";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 
 		usb0: usb-channel@0 {
@@ -918,7 +922,7 @@
 		reg = <0 0xe6ef0000 0 0x1000>;
 		interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp8_clks R8A7791_CLK_VIN0>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -927,7 +931,7 @@
 		reg = <0 0xe6ef1000 0 0x1000>;
 		interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp8_clks R8A7791_CLK_VIN1>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -936,7 +940,7 @@
 		reg = <0 0xe6ef2000 0 0x1000>;
 		interrupts = <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp8_clks R8A7791_CLK_VIN2>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -945,7 +949,7 @@
 		reg = <0 0xfe928000 0 0x8000>;
 		interrupts = <GIC_SPI 267 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp1_clks R8A7791_CLK_VSP1_S>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 
 		renesas,has-lut;
 		renesas,has-sru;
@@ -959,7 +963,7 @@
 		reg = <0 0xfe930000 0 0x8000>;
 		interrupts = <GIC_SPI 246 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp1_clks R8A7791_CLK_VSP1_DU0>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 
 		renesas,has-lif;
 		renesas,has-lut;
@@ -973,7 +977,7 @@
 		reg = <0 0xfe938000 0 0x8000>;
 		interrupts = <GIC_SPI 247 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp1_clks R8A7791_CLK_VSP1_DU1>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 
 		renesas,has-lif;
 		renesas,has-lut;
@@ -1013,33 +1017,33 @@
 	};
 
 	can0: can@e6e80000 {
-		compatible = "renesas,can-r8a7791";
+		compatible = "renesas,can-r8a7791", "renesas,rcar-gen2-can";
 		reg = <0 0xe6e80000 0 0x1000>;
 		interrupts = <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7791_CLK_RCAN0>,
 			 <&cpg_clocks R8A7791_CLK_RCAN>, <&can_clk>;
 		clock-names = "clkp1", "clkp2", "can_clk";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
 	can1: can@e6e88000 {
-		compatible = "renesas,can-r8a7791";
+		compatible = "renesas,can-r8a7791", "renesas,rcar-gen2-can";
 		reg = <0 0xe6e88000 0 0x1000>;
 		interrupts = <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7791_CLK_RCAN1>,
 			 <&cpg_clocks R8A7791_CLK_RCAN>, <&can_clk>;
 		clock-names = "clkp1", "clkp2", "can_clk";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
 	jpu: jpeg-codec@fe980000 {
-		compatible = "renesas,jpu-r8a7791";
+		compatible = "renesas,jpu-r8a7791", "renesas,rcar-gen2-jpu";
 		reg = <0 0xfe980000 0 0x10300>;
 		interrupts = <GIC_SPI 272 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp1_clks R8A7791_CLK_JPU>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 	};
 
 	clocks {
@@ -1048,12 +1052,11 @@
 		ranges;
 
 		/* External root clock */
-		extal_clk: extal_clk {
+		extal_clk: extal {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			/* This value must be overriden by the board. */
 			clock-frequency = <0>;
-			clock-output-names = "extal";
 		};
 
 		/*
@@ -1064,27 +1067,23 @@
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <0>;
-			clock-output-names = "audio_clk_a";
 		};
 		audio_clk_b: audio_clk_b {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <0>;
-			clock-output-names = "audio_clk_b";
 		};
 		audio_clk_c: audio_clk_c {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <0>;
-			clock-output-names = "audio_clk_c";
 		};
 
 		/* External PCIe clock - can be overridden by the board */
-		pcie_bus_clk: pcie_bus_clk {
+		pcie_bus_clk: pcie_bus {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <0>;
-			clock-output-names = "pcie_bus";
 		};
 
 		/* External SCIF clock */
@@ -1096,11 +1095,10 @@
 		};
 
 		/* External USB clock - can be overridden by the board */
-		usb_extal_clk: usb_extal_clk {
+		usb_extal_clk: usb_extal {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <48000000>;
-			clock-output-names = "usb_extal";
 		};
 
 		/* External CAN clock */
@@ -1109,7 +1107,6 @@
 			#clock-cells = <0>;
 			/* This value must be overridden by the board. */
 			clock-frequency = <0>;
-			clock-output-names = "can_clk";
 		};
 
 		/* Special CPG clocks */
@@ -1126,178 +1123,156 @@
 		};
 
 		/* Variable factor clocks */
-		sd2_clk: sd2_clk@e6150078 {
+		sd2_clk: sd2@e6150078 {
 			compatible = "renesas,r8a7791-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0 0xe6150078 0 4>;
 			clocks = <&pll1_div2_clk>;
 			#clock-cells = <0>;
-			clock-output-names = "sd2";
 		};
-		sd3_clk: sd3_clk@e615026c {
+		sd3_clk: sd3@e615026c {
 			compatible = "renesas,r8a7791-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0 0xe615026c 0 4>;
 			clocks = <&pll1_div2_clk>;
 			#clock-cells = <0>;
-			clock-output-names = "sd3";
 		};
-		mmc0_clk: mmc0_clk@e6150240 {
+		mmc0_clk: mmc0@e6150240 {
 			compatible = "renesas,r8a7791-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0 0xe6150240 0 4>;
 			clocks = <&pll1_div2_clk>;
 			#clock-cells = <0>;
-			clock-output-names = "mmc0";
 		};
-		ssp_clk: ssp_clk@e6150248 {
+		ssp_clk: ssp@e6150248 {
 			compatible = "renesas,r8a7791-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0 0xe6150248 0 4>;
 			clocks = <&pll1_div2_clk>;
 			#clock-cells = <0>;
-			clock-output-names = "ssp";
 		};
-		ssprs_clk: ssprs_clk@e615024c {
+		ssprs_clk: ssprs@e615024c {
 			compatible = "renesas,r8a7791-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0 0xe615024c 0 4>;
 			clocks = <&pll1_div2_clk>;
 			#clock-cells = <0>;
-			clock-output-names = "ssprs";
 		};
 
 		/* Fixed factor clocks */
-		pll1_div2_clk: pll1_div2_clk {
+		pll1_div2_clk: pll1_div2 {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7791_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <2>;
 			clock-mult = <1>;
-			clock-output-names = "pll1_div2";
 		};
-		zg_clk: zg_clk {
+		zg_clk: zg {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7791_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <3>;
 			clock-mult = <1>;
-			clock-output-names = "zg";
 		};
-		zx_clk: zx_clk {
+		zx_clk: zx {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7791_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <3>;
 			clock-mult = <1>;
-			clock-output-names = "zx";
 		};
-		zs_clk: zs_clk {
+		zs_clk: zs {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7791_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <6>;
 			clock-mult = <1>;
-			clock-output-names = "zs";
 		};
-		hp_clk: hp_clk {
+		hp_clk: hp {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7791_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <12>;
 			clock-mult = <1>;
-			clock-output-names = "hp";
 		};
-		i_clk: i_clk {
+		i_clk: i {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7791_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <2>;
 			clock-mult = <1>;
-			clock-output-names = "i";
 		};
-		b_clk: b_clk {
+		b_clk: b {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7791_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <12>;
 			clock-mult = <1>;
-			clock-output-names = "b";
 		};
-		p_clk: p_clk {
+		p_clk: p {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7791_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <24>;
 			clock-mult = <1>;
-			clock-output-names = "p";
 		};
-		cl_clk: cl_clk {
+		cl_clk: cl {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7791_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <48>;
 			clock-mult = <1>;
-			clock-output-names = "cl";
 		};
-		m2_clk: m2_clk {
+		m2_clk: m2 {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7791_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <8>;
 			clock-mult = <1>;
-			clock-output-names = "m2";
 		};
-		rclk_clk: rclk_clk {
+		rclk_clk: rclk {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7791_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <(48 * 1024)>;
 			clock-mult = <1>;
-			clock-output-names = "rclk";
 		};
-		oscclk_clk: oscclk_clk {
+		oscclk_clk: oscclk {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7791_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <(12 * 1024)>;
 			clock-mult = <1>;
-			clock-output-names = "oscclk";
 		};
-		zb3_clk: zb3_clk {
+		zb3_clk: zb3 {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7791_CLK_PLL3>;
 			#clock-cells = <0>;
 			clock-div = <4>;
 			clock-mult = <1>;
-			clock-output-names = "zb3";
 		};
-		zb3d2_clk: zb3d2_clk {
+		zb3d2_clk: zb3d2 {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7791_CLK_PLL3>;
 			#clock-cells = <0>;
 			clock-div = <8>;
 			clock-mult = <1>;
-			clock-output-names = "zb3d2";
 		};
-		ddr_clk: ddr_clk {
+		ddr_clk: ddr {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7791_CLK_PLL3>;
 			#clock-cells = <0>;
 			clock-div = <8>;
 			clock-mult = <1>;
-			clock-output-names = "ddr";
 		};
-		mp_clk: mp_clk {
+		mp_clk: mp {
 			compatible = "fixed-factor-clock";
 			clocks = <&pll1_div2_clk>;
 			#clock-cells = <0>;
 			clock-div = <15>;
 			clock-mult = <1>;
-			clock-output-names = "mp";
 		};
-		cp_clk: cp_clk {
+		cp_clk: cp {
 			compatible = "fixed-factor-clock";
 			clocks = <&extal_clk>;
 			#clock-cells = <0>;
 			clock-div = <2>;
 			clock-mult = <1>;
-			clock-output-names = "cp";
 		};
 
 		/* Gate clocks */
@@ -1492,6 +1467,12 @@
 		};
 	};
 
+	sysc: system-controller@e6180000 {
+		compatible = "renesas,r8a7791-sysc";
+		reg = <0 0xe6180000 0 0x0200>;
+		#power-domain-cells = <1>;
+	};
+
 	qspi: spi@e6b10000 {
 		compatible = "renesas,qspi-r8a7791", "renesas,qspi";
 		reg = <0 0xe6b10000 0 0x2c>;
@@ -1499,7 +1480,7 @@
 		clocks = <&mstp9_clks R8A7791_CLK_QSPI_MOD>;
 		dmas = <&dmac0 0x17>, <&dmac0 0x18>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		num-cs = <1>;
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -1513,7 +1494,7 @@
 		clocks = <&mstp0_clks R8A7791_CLK_MSIOF0>;
 		dmas = <&dmac0 0x51>, <&dmac0 0x52>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		#address-cells = <1>;
 		#size-cells = <0>;
 		status = "disabled";
@@ -1526,7 +1507,7 @@
 		clocks = <&mstp2_clks R8A7791_CLK_MSIOF1>;
 		dmas = <&dmac0 0x55>, <&dmac0 0x56>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		#address-cells = <1>;
 		#size-cells = <0>;
 		status = "disabled";
@@ -1539,18 +1520,18 @@
 		clocks = <&mstp2_clks R8A7791_CLK_MSIOF2>;
 		dmas = <&dmac0 0x41>, <&dmac0 0x42>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		#address-cells = <1>;
 		#size-cells = <0>;
 		status = "disabled";
 	};
 
 	xhci: usb@ee000000 {
-		compatible = "renesas,xhci-r8a7791";
+		compatible = "renesas,xhci-r8a7791", "renesas,rcar-gen2-xhci";
 		reg = <0 0xee000000 0 0xc00>;
 		interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7791_CLK_SSUSB>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		phys = <&usb2 1>;
 		phy-names = "usb";
 		status = "disabled";
@@ -1563,7 +1544,7 @@
 		      <0 0xee080000 0 0x1100>;
 		interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp7_clks R8A7791_CLK_EHCI>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 
 		bus-range = <0 0>;
@@ -1598,7 +1579,7 @@
 		      <0 0xee0c0000 0 0x1100>;
 		interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp7_clks R8A7791_CLK_EHCI>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 
 		bus-range = <1 1>;
@@ -1648,7 +1629,7 @@
 		interrupt-map = <0 0 0 0 &gic GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7791_CLK_PCIEC>, <&pcie_bus_clk>;
 		clock-names = "pcie", "pcie_bus";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -1751,7 +1732,7 @@
 				"mix.0", "mix.1",
 				"dvc.0", "dvc.1",
 				"clk_a", "clk_b", "clk_c", "clk_i";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 
 		status = "disabled";
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/r8a7791-koelsch.dts linux-libre-4.7-gnu/arch/arm/boot/dts/r8a7791-koelsch.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/r8a7791-koelsch.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/r8a7791-koelsch.dts	2016-07-24 15:23:50.000000000 -0400
@@ -242,11 +242,10 @@
 			  1800000 0>;
 	};
 
-	audio_clock: clock {
+	audio_clock: audio_clock {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
 		clock-frequency = <11289600>;
-		clock-output-names = "audio_clock";
 	};
 
 	rsnd_ak4643: sound {
@@ -324,89 +323,89 @@
 	pinctrl-names = "default";
 
 	i2c2_pins: i2c2 {
-		renesas,groups = "i2c2";
-		renesas,function = "i2c2";
+		groups = "i2c2";
+		function = "i2c2";
 	};
 
 	du_pins: du {
-		renesas,groups = "du_rgb888", "du_sync", "du_disp", "du_clk_out_0";
-		renesas,function = "du";
+		groups = "du_rgb888", "du_sync", "du_disp", "du_clk_out_0";
+		function = "du";
 	};
 
 	scif0_pins: serial0 {
-		renesas,groups = "scif0_data_d";
-		renesas,function = "scif0";
+		groups = "scif0_data_d";
+		function = "scif0";
 	};
 
 	scif1_pins: serial1 {
-		renesas,groups = "scif1_data_d";
-		renesas,function = "scif1";
+		groups = "scif1_data_d";
+		function = "scif1";
 	};
 
 	scif_clk_pins: scif_clk {
-		renesas,groups = "scif_clk";
-		renesas,function = "scif_clk";
+		groups = "scif_clk";
+		function = "scif_clk";
 	};
 
 	ether_pins: ether {
-		renesas,groups = "eth_link", "eth_mdio", "eth_rmii";
-		renesas,function = "eth";
+		groups = "eth_link", "eth_mdio", "eth_rmii";
+		function = "eth";
 	};
 
 	phy1_pins: phy1 {
-		renesas,groups = "intc_irq0";
-		renesas,function = "intc";
+		groups = "intc_irq0";
+		function = "intc";
 	};
 
 	sdhi0_pins: sd0 {
-		renesas,groups = "sdhi0_data4", "sdhi0_ctrl";
-		renesas,function = "sdhi0";
+		groups = "sdhi0_data4", "sdhi0_ctrl";
+		function = "sdhi0";
 	};
 
 	sdhi1_pins: sd1 {
-		renesas,groups = "sdhi1_data4", "sdhi1_ctrl";
-		renesas,function = "sdhi1";
+		groups = "sdhi1_data4", "sdhi1_ctrl";
+		function = "sdhi1";
 	};
 
 	sdhi2_pins: sd2 {
-		renesas,groups = "sdhi2_data4", "sdhi2_ctrl";
-		renesas,function = "sdhi2";
+		groups = "sdhi2_data4", "sdhi2_ctrl";
+		function = "sdhi2";
 	};
 
 	qspi_pins: spi0 {
-		renesas,groups = "qspi_ctrl", "qspi_data4";
-		renesas,function = "qspi";
+		groups = "qspi_ctrl", "qspi_data4";
+		function = "qspi";
 	};
 
 	msiof0_pins: spi1 {
-		renesas,groups = "msiof0_clk", "msiof0_sync", "msiof0_rx",
+		groups = "msiof0_clk", "msiof0_sync", "msiof0_rx",
 				 "msiof0_tx";
-		renesas,function = "msiof0";
+		function = "msiof0";
 	};
 
 	usb0_pins: usb0 {
-		renesas,groups = "usb0";
-		renesas,function = "usb0";
+		groups = "usb0";
+		function = "usb0";
 	};
 
 	usb1_pins: usb1 {
-		renesas,groups = "usb1";
-		renesas,function = "usb1";
+		groups = "usb1";
+		function = "usb1";
 	};
 
 	vin1_pins: vin1 {
-		renesas,groups = "vin1_data8", "vin1_clk";
-		renesas,function = "vin1";
+		groups = "vin1_data8", "vin1_clk";
+		function = "vin1";
 	};
 
 	sound_pins: sound {
-		renesas,groups = "ssi0129_ctrl", "ssi0_data", "ssi1_data";
-		renesas,function = "ssi";
+		groups = "ssi0129_ctrl", "ssi0_data", "ssi1_data";
+		function = "ssi";
 	};
 
 	sound_clk_pins: sound_clk {
-		renesas,groups = "audio_clk_a";
-		renesas,function = "audio_clk";
+		groups = "audio_clk_a";
+		function = "audio_clk";
 	};
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/r8a7791-porter.dts linux-libre-4.7-gnu/arch/arm/boot/dts/r8a7791-porter.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/r8a7791-porter.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/r8a7791-porter.dts	2016-07-24 15:23:50.000000000 -0400
@@ -113,11 +113,10 @@
 		clock-frequency = <74250000>;
 	};
 
-	x14_clk: x14-clock {
+	x14_clk: audio_clock {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
 		clock-frequency = <11289600>;
-		clock-output-names = "audio_clock";
 	};
 
 	sound {
@@ -144,73 +143,73 @@
 
 &pfc {
 	scif0_pins: serial0 {
-		renesas,groups = "scif0_data_d";
-		renesas,function = "scif0";
+		groups = "scif0_data_d";
+		function = "scif0";
 	};
 
 	ether_pins: ether {
-		renesas,groups = "eth_link", "eth_mdio", "eth_rmii";
-		renesas,function = "eth";
+		groups = "eth_link", "eth_mdio", "eth_rmii";
+		function = "eth";
 	};
 
 	phy1_pins: phy1 {
-		renesas,groups = "intc_irq0";
-		renesas,function = "intc";
+		groups = "intc_irq0";
+		function = "intc";
 	};
 
 	sdhi0_pins: sd0 {
-		renesas,groups = "sdhi0_data4", "sdhi0_ctrl";
-		renesas,function = "sdhi0";
+		groups = "sdhi0_data4", "sdhi0_ctrl";
+		function = "sdhi0";
 	};
 
 	sdhi2_pins: sd2 {
-		renesas,groups = "sdhi2_data4", "sdhi2_ctrl";
-		renesas,function = "sdhi2";
+		groups = "sdhi2_data4", "sdhi2_ctrl";
+		function = "sdhi2";
 	};
 
 	qspi_pins: spi0 {
-		renesas,groups = "qspi_ctrl", "qspi_data4";
-		renesas,function = "qspi";
+		groups = "qspi_ctrl", "qspi_data4";
+		function = "qspi";
 	};
 
 	i2c2_pins: i2c2 {
-		renesas,groups = "i2c2";
-		renesas,function = "i2c2";
+		groups = "i2c2";
+		function = "i2c2";
 	};
 
 	usb0_pins: usb0 {
-		renesas,groups = "usb0";
-		renesas,function = "usb0";
+		groups = "usb0";
+		function = "usb0";
 	};
 
 	usb1_pins: usb1 {
-		renesas,groups = "usb1";
-		renesas,function = "usb1";
+		groups = "usb1";
+		function = "usb1";
 	};
 
 	vin0_pins: vin0 {
-		renesas,groups = "vin0_data8", "vin0_clk";
-		renesas,function = "vin0";
+		groups = "vin0_data8", "vin0_clk";
+		function = "vin0";
 	};
 
 	can0_pins: can0 {
-		renesas,groups = "can0_data";
-		renesas,function = "can0";
+		groups = "can0_data";
+		function = "can0";
 	};
 
 	du_pins: du {
-		renesas,groups = "du_rgb888", "du_sync", "du_disp", "du_clk_out_0";
-		renesas,function = "du";
+		groups = "du_rgb888", "du_sync", "du_disp", "du_clk_out_0";
+		function = "du";
 	};
 
 	ssi_pins: sound {
-		renesas,groups = "ssi0129_ctrl", "ssi0_data", "ssi1_data";
-		renesas,function = "ssi";
+		groups = "ssi0129_ctrl", "ssi0_data", "ssi1_data";
+		function = "ssi";
 	};
 
 	audio_clk_pins: audio_clk {
-		renesas,groups = "audio_clk_a";
-		renesas,function = "audio_clk";
+		groups = "audio_clk_a";
+		function = "audio_clk";
 	};
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/r8a7793.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/r8a7793.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/r8a7793.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/r8a7793.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -11,6 +11,7 @@
 #include <dt-bindings/clock/r8a7793-clock.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/power/r8a7793-sysc.h>
 
 / {
 	compatible = "renesas,r8a7793";
@@ -43,6 +44,7 @@
 			voltage-tolerance = <1>; /* 1% */
 			clocks = <&cpg_clocks R8A7793_CLK_Z>;
 			clock-latency = <300000>; /* 300 us */
+			power-domains = <&sysc R8A7793_PD_CA15_CPU0>;
 
 			/* kHz - uV - OPPs unknown yet */
 			operating-points = <1500000 1000000>,
@@ -76,6 +78,7 @@
 
 	L2_CA15: cache-controller@0 {
 		compatible = "cache";
+		power-domains = <&sysc R8A7793_PD_CA15_SCU>;
 		cache-unified;
 		cache-level = <2>;
 	};
@@ -102,7 +105,7 @@
 		#interrupt-cells = <2>;
 		interrupt-controller;
 		clocks = <&mstp9_clks R8A7793_CLK_GPIO0>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 	};
 
 	gpio1: gpio@e6051000 {
@@ -115,7 +118,7 @@
 		#interrupt-cells = <2>;
 		interrupt-controller;
 		clocks = <&mstp9_clks R8A7793_CLK_GPIO1>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 	};
 
 	gpio2: gpio@e6052000 {
@@ -128,7 +131,7 @@
 		#interrupt-cells = <2>;
 		interrupt-controller;
 		clocks = <&mstp9_clks R8A7793_CLK_GPIO2>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 	};
 
 	gpio3: gpio@e6053000 {
@@ -141,7 +144,7 @@
 		#interrupt-cells = <2>;
 		interrupt-controller;
 		clocks = <&mstp9_clks R8A7793_CLK_GPIO3>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 	};
 
 	gpio4: gpio@e6054000 {
@@ -154,7 +157,7 @@
 		#interrupt-cells = <2>;
 		interrupt-controller;
 		clocks = <&mstp9_clks R8A7793_CLK_GPIO4>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 	};
 
 	gpio5: gpio@e6055000 {
@@ -167,7 +170,7 @@
 		#interrupt-cells = <2>;
 		interrupt-controller;
 		clocks = <&mstp9_clks R8A7793_CLK_GPIO5>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 	};
 
 	gpio6: gpio@e6055400 {
@@ -180,7 +183,7 @@
 		#interrupt-cells = <2>;
 		interrupt-controller;
 		clocks = <&mstp9_clks R8A7793_CLK_GPIO6>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 	};
 
 	gpio7: gpio@e6055800 {
@@ -193,7 +196,7 @@
 		#interrupt-cells = <2>;
 		interrupt-controller;
 		clocks = <&mstp9_clks R8A7793_CLK_GPIO7>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 	};
 
 	thermal: thermal@e61f0000 {
@@ -203,7 +206,7 @@
 		reg = <0 0xe61f0000 0 0x14>, <0 0xe61f0100 0 0x38>;
 		interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp5_clks R8A7793_CLK_THERMAL>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		#thermal-sensor-cells = <0>;
 	};
 
@@ -222,7 +225,7 @@
 			     <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp1_clks R8A7793_CLK_CMT0>;
 		clock-names = "fck";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 
 		renesas,channels-mask = <0x60>;
 
@@ -242,7 +245,7 @@
 			     <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7793_CLK_CMT1>;
 		clock-names = "fck";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 
 		renesas,channels-mask = <0xff>;
 
@@ -265,7 +268,7 @@
 			     <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>,
 			     <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp4_clks R8A7793_CLK_IRQC>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 	};
 
 	dmac0: dma-controller@e6700000 {
@@ -294,7 +297,7 @@
 				"ch12", "ch13", "ch14";
 		clocks = <&mstp2_clks R8A7793_CLK_SYS_DMAC0>;
 		clock-names = "fck";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		#dma-cells = <1>;
 		dma-channels = <15>;
 	};
@@ -325,7 +328,7 @@
 				"ch12", "ch13", "ch14";
 		clocks = <&mstp2_clks R8A7793_CLK_SYS_DMAC1>;
 		clock-names = "fck";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		#dma-cells = <1>;
 		dma-channels = <15>;
 	};
@@ -354,7 +357,7 @@
 				"ch12";
 		clocks = <&mstp5_clks R8A7793_CLK_AUDIO_DMAC0>;
 		clock-names = "fck";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		#dma-cells = <1>;
 		dma-channels = <13>;
 	};
@@ -383,7 +386,7 @@
 				"ch12";
 		clocks = <&mstp5_clks R8A7793_CLK_AUDIO_DMAC1>;
 		clock-names = "fck";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		#dma-cells = <1>;
 		dma-channels = <13>;
 	};
@@ -396,7 +399,7 @@
 		reg = <0 0xe6508000 0 0x40>;
 		interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7793_CLK_I2C0>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		i2c-scl-internal-delay-ns = <6>;
 		status = "disabled";
 	};
@@ -408,7 +411,7 @@
 		reg = <0 0xe6518000 0 0x40>;
 		interrupts = <GIC_SPI 288 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7793_CLK_I2C1>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		i2c-scl-internal-delay-ns = <6>;
 		status = "disabled";
 	};
@@ -420,7 +423,7 @@
 		reg = <0 0xe6530000 0 0x40>;
 		interrupts = <GIC_SPI 286 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7793_CLK_I2C2>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		i2c-scl-internal-delay-ns = <6>;
 		status = "disabled";
 	};
@@ -432,7 +435,7 @@
 		reg = <0 0xe6540000 0 0x40>;
 		interrupts = <GIC_SPI 290 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7793_CLK_I2C3>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		i2c-scl-internal-delay-ns = <6>;
 		status = "disabled";
 	};
@@ -444,7 +447,7 @@
 		reg = <0 0xe6520000 0 0x40>;
 		interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7793_CLK_I2C4>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		i2c-scl-internal-delay-ns = <6>;
 		status = "disabled";
 	};
@@ -457,7 +460,7 @@
 		reg = <0 0xe6528000 0 0x40>;
 		interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7793_CLK_I2C5>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		i2c-scl-internal-delay-ns = <110>;
 		status = "disabled";
 	};
@@ -472,7 +475,7 @@
 		clocks = <&mstp9_clks R8A7793_CLK_IICDVFS>;
 		dmas = <&dmac0 0x77>, <&dmac0 0x78>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -485,7 +488,7 @@
 		clocks = <&mstp3_clks R8A7793_CLK_IIC0>;
 		dmas = <&dmac0 0x61>, <&dmac0 0x62>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -498,7 +501,7 @@
 		clocks = <&mstp3_clks R8A7793_CLK_IIC1>;
 		dmas = <&dmac0 0x65>, <&dmac0 0x66>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -507,6 +510,39 @@
 		reg = <0 0xe6060000 0 0x250>;
 	};
 
+	sdhi0: sd@ee100000 {
+		compatible = "renesas,sdhi-r8a7793";
+		reg = <0 0xee100000 0 0x328>;
+		interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp3_clks R8A7793_CLK_SDHI0>;
+		dmas = <&dmac0 0xcd>, <&dmac0 0xce>;
+		dma-names = "tx", "rx";
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
+		status = "disabled";
+	};
+
+	sdhi1: sd@ee140000 {
+		compatible = "renesas,sdhi-r8a7793";
+		reg = <0 0xee140000 0 0x100>;
+		interrupts = <GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp3_clks R8A7793_CLK_SDHI1>;
+		dmas = <&dmac0 0xc1>, <&dmac0 0xc2>;
+		dma-names = "tx", "rx";
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
+		status = "disabled";
+	};
+
+	sdhi2: sd@ee160000 {
+		compatible = "renesas,sdhi-r8a7793";
+		reg = <0 0xee160000 0 0x100>;
+		interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp3_clks R8A7793_CLK_SDHI2>;
+		dmas = <&dmac0 0xd3>, <&dmac0 0xd4>;
+		dma-names = "tx", "rx";
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
+		status = "disabled";
+	};
+
 	scifa0: serial@e6c40000 {
 		compatible = "renesas,scifa-r8a7793",
 			     "renesas,rcar-gen2-scifa", "renesas,scifa";
@@ -516,7 +552,7 @@
 		clock-names = "fck";
 		dmas = <&dmac0 0x21>, <&dmac0 0x22>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -529,7 +565,7 @@
 		clock-names = "fck";
 		dmas = <&dmac0 0x25>, <&dmac0 0x26>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -542,7 +578,7 @@
 		clock-names = "fck";
 		dmas = <&dmac0 0x27>, <&dmac0 0x28>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -555,7 +591,7 @@
 		clock-names = "fck";
 		dmas = <&dmac0 0x1b>, <&dmac0 0x1c>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -568,7 +604,7 @@
 		clock-names = "fck";
 		dmas = <&dmac0 0x1f>, <&dmac0 0x20>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -581,7 +617,7 @@
 		clock-names = "fck";
 		dmas = <&dmac0 0x23>, <&dmac0 0x24>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -594,7 +630,7 @@
 		clock-names = "fck";
 		dmas = <&dmac0 0x3d>, <&dmac0 0x3e>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -607,7 +643,7 @@
 		clock-names = "fck";
 		dmas = <&dmac0 0x19>, <&dmac0 0x1a>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -620,7 +656,7 @@
 		clock-names = "fck";
 		dmas = <&dmac0 0x1d>, <&dmac0 0x1e>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -634,7 +670,7 @@
 		clock-names = "fck", "brg_int", "scif_clk";
 		dmas = <&dmac0 0x29>, <&dmac0 0x2a>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -648,7 +684,7 @@
 		clock-names = "fck", "brg_int", "scif_clk";
 		dmas = <&dmac0 0x2d>, <&dmac0 0x2e>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -662,7 +698,7 @@
 		clock-names = "fck", "brg_int", "scif_clk";
 		dmas = <&dmac0 0x2b>, <&dmac0 0x2c>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -676,7 +712,7 @@
 		clock-names = "fck", "brg_int", "scif_clk";
 		dmas = <&dmac0 0x2f>, <&dmac0 0x30>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -690,7 +726,7 @@
 		clock-names = "fck", "brg_int", "scif_clk";
 		dmas = <&dmac0 0xfb>, <&dmac0 0xfc>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -704,7 +740,7 @@
 		clock-names = "fck", "brg_int", "scif_clk";
 		dmas = <&dmac0 0xfd>, <&dmac0 0xfe>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -718,7 +754,7 @@
 		clock-names = "fck", "brg_int", "scif_clk";
 		dmas = <&dmac0 0x39>, <&dmac0 0x3a>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -732,7 +768,7 @@
 		clock-names = "fck", "brg_int", "scif_clk";
 		dmas = <&dmac0 0x4d>, <&dmac0 0x4e>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -746,7 +782,7 @@
 		clock-names = "fck", "brg_int", "scif_clk";
 		dmas = <&dmac0 0x3b>, <&dmac0 0x3c>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -755,7 +791,7 @@
 		reg = <0 0xee700000 0 0x400>;
 		interrupts = <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp8_clks R8A7793_CLK_ETHER>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		phy-mode = "rmii";
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -769,7 +805,7 @@
 		clocks = <&mstp9_clks R8A7793_CLK_QSPI_MOD>;
 		dmas = <&dmac0 0x17>, <&dmac0 0x18>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 		num-cs = <1>;
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -806,18 +842,39 @@
 		};
 	};
 
+	can0: can@e6e80000 {
+		compatible = "renesas,can-r8a7793", "renesas,rcar-gen2-can";
+		reg = <0 0xe6e80000 0 0x1000>;
+		interrupts = <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp9_clks R8A7793_CLK_RCAN0>,
+			 <&cpg_clocks R8A7793_CLK_RCAN>, <&can_clk>;
+		clock-names = "clkp1", "clkp2", "can_clk";
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
+		status = "disabled";
+	};
+
+	can1: can@e6e88000 {
+		compatible = "renesas,can-r8a7793", "renesas,rcar-gen2-can";
+		reg = <0 0xe6e88000 0 0x1000>;
+		interrupts = <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp9_clks R8A7793_CLK_RCAN1>,
+			 <&cpg_clocks R8A7793_CLK_RCAN>, <&can_clk>;
+		clock-names = "clkp1", "clkp2", "can_clk";
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
+		status = "disabled";
+	};
+
 	clocks {
 		#address-cells = <2>;
 		#size-cells = <2>;
 		ranges;
 
 		/* External root clock */
-		extal_clk: extal_clk {
+		extal_clk: extal {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			/* This value must be overridden by the board. */
 			clock-frequency = <0>;
-			clock-output-names = "extal";
 		};
 
 		/*
@@ -828,19 +885,31 @@
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <0>;
-			clock-output-names = "audio_clk_a";
 		};
 		audio_clk_b: audio_clk_b {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <0>;
-			clock-output-names = "audio_clk_b";
 		};
 		audio_clk_c: audio_clk_c {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <0>;
-			clock-output-names = "audio_clk_c";
+		};
+
+		/* External USB clock - can be overridden by the board */
+		usb_extal_clk: usb_extal {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <48000000>;
+		};
+
+		/* External CAN clock */
+		can_clk: can {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			/* This value must be overridden by the board. */
+			clock-frequency = <0>;
 		};
 
 		/* External SCIF clock */
@@ -849,7 +918,6 @@
 			#clock-cells = <0>;
 			/* This value must be overridden by the board. */
 			clock-frequency = <0>;
-			status = "disabled";
 		};
 
 		/* Special CPG clocks */
@@ -857,7 +925,7 @@
 			compatible = "renesas,r8a7793-cpg-clocks",
 				     "renesas,rcar-gen2-cpg-clocks";
 			reg = <0 0xe6150000 0 0x1000>;
-			clocks = <&extal_clk>;
+			clocks = <&extal_clk &usb_extal_clk>;
 			#clock-cells = <1>;
 			clock-output-names = "main", "pll0", "pll1", "pll3",
 					     "lb", "qspi", "sdh", "sd0", "z",
@@ -866,111 +934,98 @@
 		};
 
 		/* Variable factor clocks */
-		sd2_clk: sd2_clk@e6150078 {
+		sd2_clk: sd2@e6150078 {
 			compatible = "renesas,r8a7793-div6-clock",
 				     "renesas,cpg-div6-clock";
 			reg = <0 0xe6150078 0 4>;
 			clocks = <&pll1_div2_clk>;
 			#clock-cells = <0>;
-			clock-output-names = "sd2";
 		};
-		sd3_clk: sd3_clk@e615026c {
+		sd3_clk: sd3@e615026c {
 			compatible = "renesas,r8a7793-div6-clock",
 				     "renesas,cpg-div6-clock";
 			reg = <0 0xe615026c 0 4>;
 			clocks = <&pll1_div2_clk>;
 			#clock-cells = <0>;
-			clock-output-names = "sd3";
 		};
-		mmc0_clk: mmc0_clk@e6150240 {
+		mmc0_clk: mmc0@e6150240 {
 			compatible = "renesas,r8a7793-div6-clock",
 				     "renesas,cpg-div6-clock";
 			reg = <0 0xe6150240 0 4>;
 			clocks = <&pll1_div2_clk>;
 			#clock-cells = <0>;
-			clock-output-names = "mmc0";
 		};
 
 		/* Fixed factor clocks */
-		pll1_div2_clk: pll1_div2_clk {
+		pll1_div2_clk: pll1_div2 {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7793_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <2>;
 			clock-mult = <1>;
-			clock-output-names = "pll1_div2";
 		};
-		zg_clk: zg_clk {
+		zg_clk: zg {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7793_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <5>;
 			clock-mult = <1>;
-			clock-output-names = "zg";
 		};
-		zx_clk: zx_clk {
+		zx_clk: zx {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7793_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <3>;
 			clock-mult = <1>;
-			clock-output-names = "zx";
 		};
-		zs_clk: zs_clk {
+		zs_clk: zs {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7793_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <6>;
 			clock-mult = <1>;
-			clock-output-names = "zs";
 		};
-		hp_clk: hp_clk {
+		hp_clk: hp {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7793_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <12>;
 			clock-mult = <1>;
-			clock-output-names = "hp";
 		};
-		p_clk: p_clk {
+		p_clk: p {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7793_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <24>;
 			clock-mult = <1>;
-			clock-output-names = "p";
 		};
-		m2_clk: m2_clk {
+		m2_clk: m2 {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7793_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <8>;
 			clock-mult = <1>;
-			clock-output-names = "m2";
 		};
-		rclk_clk: rclk_clk {
+		rclk_clk: rclk {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7793_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <(48 * 1024)>;
 			clock-mult = <1>;
-			clock-output-names = "rclk";
 		};
-		mp_clk: mp_clk {
+		mp_clk: mp {
 			compatible = "fixed-factor-clock";
 			clocks = <&pll1_div2_clk>;
 			#clock-cells = <0>;
 			clock-div = <15>;
 			clock-mult = <1>;
-			clock-output-names = "mp";
 		};
-		cp_clk: cp_clk {
+		cp_clk: cp {
 			compatible = "fixed-factor-clock";
 			clocks = <&extal_clk>;
 			#clock-cells = <0>;
 			clock-div = <2>;
 			clock-mult = <1>;
-			clock-output-names = "cp";
 		};
 
 		/* Gate clocks */
@@ -1098,6 +1153,7 @@
 			reg = <0 0xe6150994 0 4>, <0 0xe61509a4 0 4>;
 			clocks = <&cp_clk>, <&cp_clk>, <&cp_clk>, <&cp_clk>,
 				 <&cp_clk>, <&cp_clk>, <&cp_clk>, <&cp_clk>,
+				 <&p_clk>, <&p_clk>,
 				 <&cpg_clocks R8A7793_CLK_QSPI>, <&hp_clk>,
 				 <&cp_clk>, <&hp_clk>, <&hp_clk>, <&hp_clk>,
 				 <&hp_clk>, <&hp_clk>;
@@ -1107,7 +1163,8 @@
 				R8A7793_CLK_GPIO5 R8A7793_CLK_GPIO4
 				R8A7793_CLK_GPIO3 R8A7793_CLK_GPIO2
 				R8A7793_CLK_GPIO1 R8A7793_CLK_GPIO0
-				R8A7793_CLK_QSPI_MOD R8A7793_CLK_I2C5
+				R8A7793_CLK_QSPI_MOD R8A7793_CLK_RCAN1
+				R8A7793_CLK_RCAN0 R8A7793_CLK_I2C5
 				R8A7793_CLK_IICDVFS R8A7793_CLK_I2C4
 				R8A7793_CLK_I2C3 R8A7793_CLK_I2C2
 				R8A7793_CLK_I2C1 R8A7793_CLK_I2C0
@@ -1115,8 +1172,9 @@
 			clock-output-names =
 				"gpio7", "gpio6", "gpio5", "gpio4",
 				"gpio3", "gpio2", "gpio1", "gpio0",
-				"qspi_mod", "i2c5", "i2c6", "i2c4",
-				"i2c3", "i2c2", "i2c1", "i2c0";
+				"rcan1", "rcan0", "qspi_mod", "i2c5",
+				"i2c6", "i2c4", "i2c3", "i2c2", "i2c1",
+				"i2c0";
 		};
 		mstp10_clks: mstp10_clks@e6150998 {
 			compatible = "renesas,r8a7793-mstp-clocks", "renesas,cpg-mstp-clocks";
@@ -1166,6 +1224,12 @@
 		};
 	};
 
+	sysc: system-controller@e6180000 {
+		compatible = "renesas,r8a7793-sysc";
+		reg = <0 0xe6180000 0 0x0200>;
+		#power-domain-cells = <1>;
+	};
+
 	ipmmu_sy0: mmu@e6280000 {
 		compatible = "renesas,ipmmu-r8a7793", "renesas,ipmmu-vmsa";
 		reg = <0 0xe6280000 0 0x1000>;
@@ -1261,7 +1325,7 @@
 				"src.4", "src.3", "src.2", "src.1", "src.0",
 				"dvc.0", "dvc.1",
 				"clk_a", "clk_b", "clk_c", "clk_i";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
 
 		status = "disabled";
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/r8a7793-gose.dts linux-libre-4.7-gnu/arch/arm/boot/dts/r8a7793-gose.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/r8a7793-gose.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/r8a7793-gose.dts	2016-07-24 15:23:50.000000000 -0400
@@ -158,11 +158,82 @@
 		};
 	};
 
-	audio_clock: clock {
+	vcc_sdhi0: regulator@0 {
+		compatible = "regulator-fixed";
+
+		regulator-name = "SDHI0 Vcc";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpio = <&gpio7 17 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	vccq_sdhi0: regulator@1 {
+		compatible = "regulator-gpio";
+
+		regulator-name = "SDHI0 VccQ";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpios = <&gpio2 12 GPIO_ACTIVE_HIGH>;
+		gpios-states = <1>;
+		states = <3300000 1
+			  1800000 0>;
+	};
+
+	vcc_sdhi1: regulator@2 {
+		compatible = "regulator-fixed";
+
+		regulator-name = "SDHI1 Vcc";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpio = <&gpio7 18 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	vccq_sdhi1: regulator@3 {
+		compatible = "regulator-gpio";
+
+		regulator-name = "SDHI1 VccQ";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpios = <&gpio2 13 GPIO_ACTIVE_HIGH>;
+		gpios-states = <1>;
+		states = <3300000 1
+			  1800000 0>;
+	};
+
+	vcc_sdhi2: regulator@4 {
+		compatible = "regulator-fixed";
+
+		regulator-name = "SDHI2 Vcc";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpio = <&gpio7 19 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	vccq_sdhi2: regulator@5 {
+		compatible = "regulator-gpio";
+
+		regulator-name = "SDHI2 VccQ";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpios = <&gpio2 26 GPIO_ACTIVE_HIGH>;
+		gpios-states = <1>;
+		states = <3300000 1
+			  1800000 0>;
+	};
+
+	audio_clock: audio_clock {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
 		clock-frequency = <11289600>;
-		clock-output-names = "audio_clock";
 	};
 
 	rsnd_ak4643: sound {
@@ -240,53 +311,68 @@
 	pinctrl-names = "default";
 
 	i2c2_pins: i2c2 {
-		renesas,groups = "i2c2";
-		renesas,function = "i2c2";
+		groups = "i2c2";
+		function = "i2c2";
 	};
 
 	du_pins: du {
-		renesas,groups = "du_rgb888", "du_sync", "du_disp", "du_clk_out_0";
-		renesas,function = "du";
+		groups = "du_rgb888", "du_sync", "du_disp", "du_clk_out_0";
+		function = "du";
 	};
 
 	scif0_pins: serial0 {
-		renesas,groups = "scif0_data_d";
-		renesas,function = "scif0";
+		groups = "scif0_data_d";
+		function = "scif0";
 	};
 
 	scif1_pins: serial1 {
-		renesas,groups = "scif1_data_d";
-		renesas,function = "scif1";
+		groups = "scif1_data_d";
+		function = "scif1";
 	};
 
 	scif_clk_pins: scif_clk {
-		renesas,groups = "scif_clk";
-		renesas,function = "scif_clk";
+		groups = "scif_clk";
+		function = "scif_clk";
 	};
 
 	ether_pins: ether {
-		renesas,groups = "eth_link", "eth_mdio", "eth_rmii";
-		renesas,function = "eth";
+		groups = "eth_link", "eth_mdio", "eth_rmii";
+		function = "eth";
 	};
 
 	phy1_pins: phy1 {
-		renesas,groups = "intc_irq0";
-		renesas,function = "intc";
+		groups = "intc_irq0";
+		function = "intc";
+	};
+
+	sdhi0_pins: sd0 {
+		renesas,groups = "sdhi0_data4", "sdhi0_ctrl";
+		renesas,function = "sdhi0";
+	};
+
+	sdhi1_pins: sd1 {
+		renesas,groups = "sdhi1_data4", "sdhi1_ctrl";
+		renesas,function = "sdhi1";
+	};
+
+	sdhi2_pins: sd2 {
+		renesas,groups = "sdhi2_data4", "sdhi2_ctrl";
+		renesas,function = "sdhi2";
 	};
 
 	qspi_pins: spi0 {
-		renesas,groups = "qspi_ctrl", "qspi_data4";
-		renesas,function = "qspi";
+		groups = "qspi_ctrl", "qspi_data4";
+		function = "qspi";
 	};
 
 	sound_pins: sound {
-		renesas,groups = "ssi0129_ctrl", "ssi0_data", "ssi1_data";
-		renesas,function = "ssi";
+		groups = "ssi0129_ctrl", "ssi0_data", "ssi1_data";
+		function = "ssi";
 	};
 
 	sound_clk_pins: sound_clk {
-		renesas,groups = "audio_clk_a";
-		renesas,function = "audio_clk";
+		groups = "audio_clk_a";
+		function = "audio_clk";
 	};
 };
 
@@ -329,6 +415,38 @@
 	status = "okay";
 };
 
+&sdhi0 {
+	pinctrl-0 = <&sdhi0_pins>;
+	pinctrl-names = "default";
+
+	vmmc-supply = <&vcc_sdhi0>;
+	vqmmc-supply = <&vccq_sdhi0>;
+	cd-gpios = <&gpio6 6 GPIO_ACTIVE_LOW>;
+	wp-gpios = <&gpio6 7 GPIO_ACTIVE_HIGH>;
+	status = "okay";
+};
+
+&sdhi1 {
+	pinctrl-0 = <&sdhi1_pins>;
+	pinctrl-names = "default";
+
+	vmmc-supply = <&vcc_sdhi1>;
+	vqmmc-supply = <&vccq_sdhi1>;
+	cd-gpios = <&gpio6 14 GPIO_ACTIVE_LOW>;
+	wp-gpios = <&gpio6 15 GPIO_ACTIVE_HIGH>;
+	status = "okay";
+};
+
+&sdhi2 {
+	pinctrl-0 = <&sdhi2_pins>;
+	pinctrl-names = "default";
+
+	vmmc-supply = <&vcc_sdhi2>;
+	vqmmc-supply = <&vccq_sdhi2>;
+	cd-gpios = <&gpio6 22 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
 &qspi {
 	pinctrl-0 = <&qspi_pins>;
 	pinctrl-names = "default";
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/r8a7794-alt.dts linux-libre-4.7-gnu/arch/arm/boot/dts/r8a7794-alt.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/r8a7794-alt.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/r8a7794-alt.dts	2016-07-24 15:23:50.000000000 -0400
@@ -107,38 +107,38 @@
 	pinctrl-names = "default";
 
 	du_pins: du {
-		renesas,groups = "du1_rgb666", "du1_sync", "du1_disp", "du1_dotclkout0";
-		renesas,function = "du";
+		groups = "du1_rgb666", "du1_sync", "du1_disp", "du1_dotclkout0";
+		function = "du";
 	};
 
 	scif2_pins: serial2 {
-		renesas,groups = "scif2_data";
-		renesas,function = "scif2";
+		groups = "scif2_data";
+		function = "scif2";
 	};
 
 	scif_clk_pins: scif_clk {
-		renesas,groups = "scif_clk";
-		renesas,function = "scif_clk";
+		groups = "scif_clk";
+		function = "scif_clk";
 	};
 
 	ether_pins: ether {
-		renesas,groups = "eth_link", "eth_mdio", "eth_rmii";
-		renesas,function = "eth";
+		groups = "eth_link", "eth_mdio", "eth_rmii";
+		function = "eth";
 	};
 
 	phy1_pins: phy1 {
-		renesas,groups = "intc_irq8";
-		renesas,function = "intc";
+		groups = "intc_irq8";
+		function = "intc";
 	};
 
 	i2c1_pins: i2c1 {
-		renesas,groups = "i2c1";
-		renesas,function = "i2c1";
+		groups = "i2c1";
+		function = "i2c1";
 	};
 
 	vin0_pins: vin0 {
-		renesas,groups = "vin0_data8", "vin0_clk";
-		renesas,function = "vin0";
+		groups = "vin0_data8", "vin0_clk";
+		function = "vin0";
 	};
 };
 
@@ -148,8 +148,8 @@
 
 &pfc {
 	qspi_pins: spi0 {
-		renesas,groups = "qspi_ctrl", "qspi_data4";
-		renesas,function = "qspi";
+		groups = "qspi_ctrl", "qspi_data4";
+		function = "qspi";
 	};
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/r8a7794.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/r8a7794.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/r8a7794.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/r8a7794.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -12,6 +12,7 @@
 #include <dt-bindings/clock/r8a7794-clock.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/power/r8a7794-sysc.h>
 
 / {
 	compatible = "renesas,r8a7794";
@@ -26,6 +27,8 @@
 		i2c3 = &i2c3;
 		i2c4 = &i2c4;
 		i2c5 = &i2c5;
+		i2c6 = &i2c6;
+		i2c7 = &i2c7;
 		spi0 = &qspi;
 		vin0 = &vin0;
 		vin1 = &vin1;
@@ -40,6 +43,7 @@
 			compatible = "arm,cortex-a7";
 			reg = <0>;
 			clock-frequency = <1000000000>;
+			power-domains = <&sysc R8A7794_PD_CA7_CPU0>;
 			next-level-cache = <&L2_CA7>;
 		};
 
@@ -48,12 +52,14 @@
 			compatible = "arm,cortex-a7";
 			reg = <1>;
 			clock-frequency = <1000000000>;
+			power-domains = <&sysc R8A7794_PD_CA7_CPU1>;
 			next-level-cache = <&L2_CA7>;
 		};
 	};
 
 	L2_CA7: cache-controller@1 {
 		compatible = "cache";
+		power-domains = <&sysc R8A7794_PD_CA7_SCU>;
 		cache-unified;
 		cache-level = <2>;
 	};
@@ -80,7 +86,7 @@
 		#interrupt-cells = <2>;
 		interrupt-controller;
 		clocks = <&mstp9_clks R8A7794_CLK_GPIO0>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 	};
 
 	gpio1: gpio@e6051000 {
@@ -93,7 +99,7 @@
 		#interrupt-cells = <2>;
 		interrupt-controller;
 		clocks = <&mstp9_clks R8A7794_CLK_GPIO1>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 	};
 
 	gpio2: gpio@e6052000 {
@@ -106,7 +112,7 @@
 		#interrupt-cells = <2>;
 		interrupt-controller;
 		clocks = <&mstp9_clks R8A7794_CLK_GPIO2>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 	};
 
 	gpio3: gpio@e6053000 {
@@ -119,7 +125,7 @@
 		#interrupt-cells = <2>;
 		interrupt-controller;
 		clocks = <&mstp9_clks R8A7794_CLK_GPIO3>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 	};
 
 	gpio4: gpio@e6054000 {
@@ -132,7 +138,7 @@
 		#interrupt-cells = <2>;
 		interrupt-controller;
 		clocks = <&mstp9_clks R8A7794_CLK_GPIO4>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 	};
 
 	gpio5: gpio@e6055000 {
@@ -145,7 +151,7 @@
 		#interrupt-cells = <2>;
 		interrupt-controller;
 		clocks = <&mstp9_clks R8A7794_CLK_GPIO5>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 	};
 
 	gpio6: gpio@e6055400 {
@@ -158,7 +164,7 @@
 		#interrupt-cells = <2>;
 		interrupt-controller;
 		clocks = <&mstp9_clks R8A7794_CLK_GPIO6>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 	};
 
 	cmt0: timer@ffca0000 {
@@ -168,7 +174,7 @@
 			     <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp1_clks R8A7794_CLK_CMT0>;
 		clock-names = "fck";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 
 		renesas,channels-mask = <0x60>;
 
@@ -188,7 +194,7 @@
 			     <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7794_CLK_CMT1>;
 		clock-names = "fck";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 
 		renesas,channels-mask = <0xff>;
 
@@ -219,7 +225,7 @@
 			     <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>,
 			     <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp4_clks R8A7794_CLK_IRQC>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 	};
 
 	pfc: pin-controller@e6060000 {
@@ -253,7 +259,7 @@
 				"ch12", "ch13", "ch14";
 		clocks = <&mstp2_clks R8A7794_CLK_SYS_DMAC0>;
 		clock-names = "fck";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		#dma-cells = <1>;
 		dma-channels = <15>;
 	};
@@ -284,7 +290,7 @@
 				"ch12", "ch13", "ch14";
 		clocks = <&mstp2_clks R8A7794_CLK_SYS_DMAC1>;
 		clock-names = "fck";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		#dma-cells = <1>;
 		dma-channels = <15>;
 	};
@@ -298,7 +304,7 @@
 		clock-names = "fck";
 		dmas = <&dmac0 0x21>, <&dmac0 0x22>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -311,7 +317,7 @@
 		clock-names = "fck";
 		dmas = <&dmac0 0x25>, <&dmac0 0x26>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -324,7 +330,7 @@
 		clock-names = "fck";
 		dmas = <&dmac0 0x27>, <&dmac0 0x28>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -337,7 +343,7 @@
 		clock-names = "fck";
 		dmas = <&dmac0 0x1b>, <&dmac0 0x1c>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -350,7 +356,7 @@
 		clock-names = "fck";
 		dmas = <&dmac0 0x1f>, <&dmac0 0x20>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -363,7 +369,7 @@
 		clock-names = "fck";
 		dmas = <&dmac0 0x23>, <&dmac0 0x24>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -376,7 +382,7 @@
 		clock-names = "fck";
 		dmas = <&dmac0 0x3d>, <&dmac0 0x3e>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -389,7 +395,7 @@
 		clock-names = "fck";
 		dmas = <&dmac0 0x19>, <&dmac0 0x1a>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -402,7 +408,7 @@
 		clock-names = "fck";
 		dmas = <&dmac0 0x1d>, <&dmac0 0x1e>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -416,7 +422,7 @@
 		clock-names = "fck", "brg_int", "scif_clk";
 		dmas = <&dmac0 0x29>, <&dmac0 0x2a>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -430,7 +436,7 @@
 		clock-names = "fck", "brg_int", "scif_clk";
 		dmas = <&dmac0 0x2d>, <&dmac0 0x2e>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -444,7 +450,7 @@
 		clock-names = "fck", "brg_int", "scif_clk";
 		dmas = <&dmac0 0x2b>, <&dmac0 0x2c>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -458,7 +464,7 @@
 		clock-names = "fck", "brg_int", "scif_clk";
 		dmas = <&dmac0 0x2f>, <&dmac0 0x30>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -472,7 +478,7 @@
 		clock-names = "fck", "brg_int", "scif_clk";
 		dmas = <&dmac0 0xfb>, <&dmac0 0xfc>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -486,7 +492,7 @@
 		clock-names = "fck", "brg_int", "scif_clk";
 		dmas = <&dmac0 0xfd>, <&dmac0 0xfe>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -500,7 +506,7 @@
 		clock-names = "fck", "brg_int", "scif_clk";
 		dmas = <&dmac0 0x39>, <&dmac0 0x3a>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -514,7 +520,7 @@
 		clock-names = "fck", "brg_int", "scif_clk";
 		dmas = <&dmac0 0x4d>, <&dmac0 0x4e>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -528,7 +534,7 @@
 		clock-names = "fck", "brg_int", "scif_clk";
 		dmas = <&dmac0 0x3b>, <&dmac0 0x3c>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -537,7 +543,7 @@
 		reg = <0 0xee700000 0 0x400>;
 		interrupts = <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp8_clks R8A7794_CLK_ETHER>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		phy-mode = "rmii";
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -550,7 +556,7 @@
 		reg = <0 0xe6800000 0 0x800>, <0 0xee0e8000 0 0x4000>;
 		interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp8_clks R8A7794_CLK_ETHERAVB>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		#address-cells = <1>;
 		#size-cells = <0>;
 		status = "disabled";
@@ -562,7 +568,7 @@
 		reg = <0 0xe6508000 0 0x40>;
 		interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7794_CLK_I2C0>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		#address-cells = <1>;
 		#size-cells = <0>;
 		i2c-scl-internal-delay-ns = <6>;
@@ -574,7 +580,7 @@
 		reg = <0 0xe6518000 0 0x40>;
 		interrupts = <GIC_SPI 288 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7794_CLK_I2C1>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		#address-cells = <1>;
 		#size-cells = <0>;
 		i2c-scl-internal-delay-ns = <6>;
@@ -586,7 +592,7 @@
 		reg = <0 0xe6530000 0 0x40>;
 		interrupts = <GIC_SPI 286 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7794_CLK_I2C2>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		#address-cells = <1>;
 		#size-cells = <0>;
 		i2c-scl-internal-delay-ns = <6>;
@@ -598,7 +604,7 @@
 		reg = <0 0xe6540000 0 0x40>;
 		interrupts = <GIC_SPI 290 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7794_CLK_I2C3>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		#address-cells = <1>;
 		#size-cells = <0>;
 		i2c-scl-internal-delay-ns = <6>;
@@ -610,7 +616,7 @@
 		reg = <0 0xe6520000 0 0x40>;
 		interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7794_CLK_I2C4>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		#address-cells = <1>;
 		#size-cells = <0>;
 		i2c-scl-internal-delay-ns = <6>;
@@ -622,13 +628,39 @@
 		reg = <0 0xe6528000 0 0x40>;
 		interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp9_clks R8A7794_CLK_I2C5>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		#address-cells = <1>;
 		#size-cells = <0>;
 		i2c-scl-internal-delay-ns = <6>;
 		status = "disabled";
 	};
 
+	i2c6: i2c@e6500000 {
+		compatible = "renesas,iic-r8a7794", "renesas,rmobile-iic";
+		reg = <0 0xe6500000 0 0x425>;
+		interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp3_clks R8A7794_CLK_IIC0>;
+		dmas = <&dmac0 0x61>, <&dmac0 0x62>;
+		dma-names = "tx", "rx";
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	i2c7: i2c@e6510000 {
+		compatible = "renesas,iic-r8a7794", "renesas,rmobile-iic";
+		reg = <0 0xe6510000 0 0x425>;
+		interrupts = <GIC_SPI 175 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp3_clks R8A7794_CLK_IIC1>;
+		dmas = <&dmac0 0x65>, <&dmac0 0x66>;
+		dma-names = "tx", "rx";
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
 	mmcif0: mmc@ee200000 {
 		compatible = "renesas,mmcif-r8a7794", "renesas,sh-mmcif";
 		reg = <0 0xee200000 0 0x80>;
@@ -636,7 +668,7 @@
 		clocks = <&mstp3_clks R8A7794_CLK_MMCIF0>;
 		dmas = <&dmac0 0xd1>, <&dmac0 0xd2>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		reg-io-width = <4>;
 		status = "disabled";
 	};
@@ -646,7 +678,7 @@
 		reg = <0 0xee100000 0 0x200>;
 		interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7794_CLK_SDHI0>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -655,7 +687,7 @@
 		reg = <0 0xee140000 0 0x100>;
 		interrupts = <GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7794_CLK_SDHI1>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -664,7 +696,7 @@
 		reg = <0 0xee160000 0 0x100>;
 		interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7794_CLK_SDHI2>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -675,7 +707,7 @@
 		clocks = <&mstp9_clks R8A7794_CLK_QSPI_MOD>;
 		dmas = <&dmac0 0x17>, <&dmac0 0x18>;
 		dma-names = "tx", "rx";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		num-cs = <1>;
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -687,7 +719,7 @@
 		reg = <0 0xe6ef0000 0 0x1000>;
 		interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp8_clks R8A7794_CLK_VIN0>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -696,7 +728,7 @@
 		reg = <0 0xe6ef1000 0 0x1000>;
 		interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp8_clks R8A7794_CLK_VIN1>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
 
@@ -707,7 +739,7 @@
 		      <0 0xee080000 0 0x1100>;
 		interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp7_clks R8A7794_CLK_EHCI>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 
 		bus-range = <0 0>;
@@ -742,7 +774,7 @@
 		      <0 0xee0c0000 0 0x1100>;
 		interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp7_clks R8A7794_CLK_EHCI>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 
 		bus-range = <1 1>;
@@ -775,7 +807,7 @@
 		reg = <0 0xe6590000 0 0x100>;
 		interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp7_clks R8A7794_CLK_HSUSB>;
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		renesas,buswait = <4>;
 		phys = <&usb0 1>;
 		phy-names = "usb";
@@ -789,7 +821,7 @@
 		#size-cells = <0>;
 		clocks = <&mstp7_clks R8A7794_CLK_HSUSB>;
 		clock-names = "usbhs";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 
 		usb0: usb-channel@0 {
@@ -830,18 +862,54 @@
 		};
 	};
 
+	can0: can@e6e80000 {
+		compatible = "renesas,can-r8a7794", "renesas,rcar-gen2-can";
+		reg = <0 0xe6e80000 0 0x1000>;
+		interrupts = <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp9_clks R8A7794_CLK_RCAN0>,
+			 <&cpg_clocks R8A7794_CLK_RCAN>, <&can_clk>;
+		clock-names = "clkp1", "clkp2", "can_clk";
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
+		status = "disabled";
+	};
+
+	can1: can@e6e88000 {
+		compatible = "renesas,can-r8a7794", "renesas,rcar-gen2-can";
+		reg = <0 0xe6e88000 0 0x1000>;
+		interrupts = <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp9_clks R8A7794_CLK_RCAN1>,
+			 <&cpg_clocks R8A7794_CLK_RCAN>, <&can_clk>;
+		clock-names = "clkp1", "clkp2", "can_clk";
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
+		status = "disabled";
+	};
+
 	clocks {
 		#address-cells = <2>;
 		#size-cells = <2>;
 		ranges;
 
 		/* External root clock */
-		extal_clk: extal_clk {
+		extal_clk: extal {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			/* This value must be overriden by the board. */
 			clock-frequency = <0>;
-			clock-output-names = "extal";
+		};
+
+		/* External USB clock - can be overridden by the board */
+		usb_extal_clk: usb_extal {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <48000000>;
+		};
+
+		/* External CAN clock */
+		can_clk: can {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			/* This value must be overridden by the board. */
+			clock-frequency = <0>;
 		};
 
 		/* External SCIF clock */
@@ -850,7 +918,6 @@
 			#clock-cells = <0>;
 			/* This value must be overridden by the board. */
 			clock-frequency = <0>;
-			status = "disabled";
 		};
 
 		/* Special CPG clocks */
@@ -858,180 +925,160 @@
 			compatible = "renesas,r8a7794-cpg-clocks",
 				     "renesas,rcar-gen2-cpg-clocks";
 			reg = <0 0xe6150000 0 0x1000>;
-			clocks = <&extal_clk>;
+			clocks = <&extal_clk &usb_extal_clk>;
 			#clock-cells = <1>;
 			clock-output-names = "main", "pll0", "pll1", "pll3",
-					     "lb", "qspi", "sdh", "sd0", "z";
+					     "lb", "qspi", "sdh", "sd0", "z",
+					     "rcan";
 			#power-domain-cells = <0>;
 		};
 		/* Variable factor clocks */
-		sd2_clk: sd2_clk@e6150078 {
+		sd2_clk: sd2@e6150078 {
 			compatible = "renesas,r8a7794-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0 0xe6150078 0 4>;
 			clocks = <&pll1_div2_clk>;
 			#clock-cells = <0>;
-			clock-output-names = "sd2";
 		};
-		sd3_clk: sd3_clk@e615026c {
+		sd3_clk: sd3@e615026c {
 			compatible = "renesas,r8a7794-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0 0xe615026c 0 4>;
 			clocks = <&pll1_div2_clk>;
 			#clock-cells = <0>;
-			clock-output-names = "sd3";
 		};
-		mmc0_clk: mmc0_clk@e6150240 {
+		mmc0_clk: mmc0@e6150240 {
 			compatible = "renesas,r8a7794-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0 0xe6150240 0 4>;
 			clocks = <&pll1_div2_clk>;
 			#clock-cells = <0>;
-			clock-output-names = "mmc0";
 		};
 
 		/* Fixed factor clocks */
-		pll1_div2_clk: pll1_div2_clk {
+		pll1_div2_clk: pll1_div2 {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7794_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <2>;
 			clock-mult = <1>;
-			clock-output-names = "pll1_div2";
 		};
-		zg_clk: zg_clk {
+		zg_clk: zg {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7794_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <6>;
 			clock-mult = <1>;
-			clock-output-names = "zg";
 		};
-		zx_clk: zx_clk {
+		zx_clk: zx {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7794_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <3>;
 			clock-mult = <1>;
-			clock-output-names = "zx";
 		};
-		zs_clk: zs_clk {
+		zs_clk: zs {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7794_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <6>;
 			clock-mult = <1>;
-			clock-output-names = "zs";
 		};
-		hp_clk: hp_clk {
+		hp_clk: hp {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7794_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <12>;
 			clock-mult = <1>;
-			clock-output-names = "hp";
 		};
-		i_clk: i_clk {
+		i_clk: i {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7794_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <2>;
 			clock-mult = <1>;
-			clock-output-names = "i";
 		};
-		b_clk: b_clk {
+		b_clk: b {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7794_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <12>;
 			clock-mult = <1>;
-			clock-output-names = "b";
 		};
-		p_clk: p_clk {
+		p_clk: p {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7794_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <24>;
 			clock-mult = <1>;
-			clock-output-names = "p";
 		};
-		cl_clk: cl_clk {
+		cl_clk: cl {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7794_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <48>;
 			clock-mult = <1>;
-			clock-output-names = "cl";
 		};
-		m2_clk: m2_clk {
+		m2_clk: m2 {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7794_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <8>;
 			clock-mult = <1>;
-			clock-output-names = "m2";
 		};
-		rclk_clk: rclk_clk {
+		rclk_clk: rclk {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7794_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <(48 * 1024)>;
 			clock-mult = <1>;
-			clock-output-names = "rclk";
 		};
-		oscclk_clk: oscclk_clk {
+		oscclk_clk: oscclk {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7794_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <(12 * 1024)>;
 			clock-mult = <1>;
-			clock-output-names = "oscclk";
 		};
-		zb3_clk: zb3_clk {
+		zb3_clk: zb3 {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7794_CLK_PLL3>;
 			#clock-cells = <0>;
 			clock-div = <4>;
 			clock-mult = <1>;
-			clock-output-names = "zb3";
 		};
-		zb3d2_clk: zb3d2_clk {
+		zb3d2_clk: zb3d2 {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7794_CLK_PLL3>;
 			#clock-cells = <0>;
 			clock-div = <8>;
 			clock-mult = <1>;
-			clock-output-names = "zb3d2";
 		};
-		ddr_clk: ddr_clk {
+		ddr_clk: ddr {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7794_CLK_PLL3>;
 			#clock-cells = <0>;
 			clock-div = <8>;
 			clock-mult = <1>;
-			clock-output-names = "ddr";
 		};
-		mp_clk: mp_clk {
+		mp_clk: mp {
 			compatible = "fixed-factor-clock";
 			clocks = <&pll1_div2_clk>;
 			#clock-cells = <0>;
 			clock-div = <15>;
 			clock-mult = <1>;
-			clock-output-names = "mp";
 		};
-		cp_clk: cp_clk {
+		cp_clk: cp {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7794_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <48>;
 			clock-mult = <1>;
-			clock-output-names = "cp";
 		};
 
-		acp_clk: acp_clk {
+		acp_clk: acp {
 			compatible = "fixed-factor-clock";
 			clocks = <&extal_clk>;
 			#clock-cells = <0>;
 			clock-div = <2>;
 			clock-mult = <1>;
-			clock-output-names = "acp";
 		};
 
 		/* Gate clocks */
@@ -1082,16 +1129,19 @@
 			compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks";
 			reg = <0 0xe615013c 0 4>, <0 0xe6150048 0 4>;
 			clocks = <&sd3_clk>, <&sd2_clk>, <&cpg_clocks R8A7794_CLK_SD0>,
-			         <&mmc0_clk>, <&rclk_clk>, <&hp_clk>, <&hp_clk>;
+				 <&mmc0_clk>, <&hp_clk>, <&hp_clk>, <&rclk_clk>,
+				 <&hp_clk>, <&hp_clk>;
 			#clock-cells = <1>;
 			clock-indices = <
 			        R8A7794_CLK_SDHI2 R8A7794_CLK_SDHI1 R8A7794_CLK_SDHI0
-				R8A7794_CLK_MMCIF0 R8A7794_CLK_CMT1
+				R8A7794_CLK_MMCIF0 R8A7794_CLK_IIC0
+				R8A7794_CLK_IIC1 R8A7794_CLK_CMT1
 				R8A7794_CLK_USBDMAC0 R8A7794_CLK_USBDMAC1
 			>;
 			clock-output-names =
 			        "sdhi2", "sdhi1", "sdhi0",
-				"mmcif0", "cmt1", "usbdmac0", "usbdmac1";
+				"mmcif0", "i2c6", "i2c7",
+				"cmt1", "usbdmac0", "usbdmac1";
 		};
 		mstp4_clks: mstp4_clks@e6150140 {
 			compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks";
@@ -1137,20 +1187,22 @@
 			compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks";
 			reg = <0 0xe6150994 0 4>, <0 0xe61509a4 0 4>;
 			clocks = <&cp_clk>, <&cp_clk>, <&cp_clk>, <&cp_clk>,
-				 <&cp_clk>, <&cp_clk>, <&cp_clk>,
-				 <&cpg_clocks R8A7794_CLK_QSPI>, <&hp_clk>, <&hp_clk>,
-				 <&hp_clk>, <&hp_clk>, <&hp_clk>, <&hp_clk>;
+				 <&cp_clk>, <&cp_clk>, <&cp_clk>, <&p_clk>,
+				 <&p_clk>, <&cpg_clocks R8A7794_CLK_QSPI>,
+				 <&hp_clk>, <&hp_clk>, <&hp_clk>, <&hp_clk>,
+				 <&hp_clk>, <&hp_clk>;
 			#clock-cells = <1>;
 			clock-indices = <R8A7794_CLK_GPIO6 R8A7794_CLK_GPIO5
 					 R8A7794_CLK_GPIO4 R8A7794_CLK_GPIO3
 					 R8A7794_CLK_GPIO2 R8A7794_CLK_GPIO1
-					 R8A7794_CLK_GPIO0 R8A7794_CLK_QSPI_MOD
+					 R8A7794_CLK_GPIO0 R8A7794_CLK_RCAN1
+					 R8A7794_CLK_RCAN0 R8A7794_CLK_QSPI_MOD
 					 R8A7794_CLK_I2C5 R8A7794_CLK_I2C4
 					 R8A7794_CLK_I2C3 R8A7794_CLK_I2C2
 					 R8A7794_CLK_I2C1 R8A7794_CLK_I2C0>;
 			clock-output-names =
 				"gpio6", "gpio5", "gpio4", "gpio3", "gpio2",
-				"gpio1", "gpio0", "qspi_mod",
+				"gpio1", "gpio0", "rcan1", "rcan0", "qspi_mod",
 				"i2c5", "i2c4", "i2c3", "i2c2", "i2c1", "i2c0";
 		};
 		mstp11_clks: mstp11_clks@e615099c {
@@ -1165,6 +1217,12 @@
 		};
 	};
 
+	sysc: system-controller@e6180000 {
+		compatible = "renesas,r8a7794-sysc";
+		reg = <0 0xe6180000 0 0x0200>;
+		#power-domain-cells = <1>;
+	};
+
 	ipmmu_sy0: mmu@e6280000 {
 		compatible = "renesas,ipmmu-r8a7794", "renesas,ipmmu-vmsa";
 		reg = <0 0xe6280000 0 0x1000>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/r8a7794-silk.dts linux-libre-4.7-gnu/arch/arm/boot/dts/r8a7794-silk.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/r8a7794-silk.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/r8a7794-silk.dts	2016-07-24 15:23:50.000000000 -0400
@@ -130,58 +130,58 @@
 	pinctrl-names = "default";
 
 	scif2_pins: serial2 {
-		renesas,groups = "scif2_data";
-		renesas,function = "scif2";
+		groups = "scif2_data";
+		function = "scif2";
 	};
 
 	scif_clk_pins: scif_clk {
-		renesas,groups = "scif_clk";
-		renesas,function = "scif_clk";
+		groups = "scif_clk";
+		function = "scif_clk";
 	};
 
 	ether_pins: ether {
-		renesas,groups = "eth_link", "eth_mdio", "eth_rmii";
-		renesas,function = "eth";
+		groups = "eth_link", "eth_mdio", "eth_rmii";
+		function = "eth";
 	};
 
 	phy1_pins: phy1 {
-		renesas,groups = "intc_irq8";
-		renesas,function = "intc";
+		groups = "intc_irq8";
+		function = "intc";
 	};
 
 	i2c1_pins: i2c1 {
-		renesas,groups = "i2c1";
-		renesas,function = "i2c1";
+		groups = "i2c1";
+		function = "i2c1";
 	};
 
 	mmcif0_pins: mmcif0 {
-		renesas,groups = "mmc_data8", "mmc_ctrl";
-		renesas,function = "mmc";
+		groups = "mmc_data8", "mmc_ctrl";
+		function = "mmc";
 	};
 
 	sdhi1_pins: sd1 {
-		renesas,groups = "sdhi1_data4", "sdhi1_ctrl";
-		renesas,function = "sdhi1";
+		groups = "sdhi1_data4", "sdhi1_ctrl";
+		function = "sdhi1";
 	};
 
 	qspi_pins: spi0 {
-		renesas,groups = "qspi_ctrl", "qspi_data4";
-		renesas,function = "qspi";
+		groups = "qspi_ctrl", "qspi_data4";
+		function = "qspi";
 	};
 
 	vin0_pins: vin0 {
-		renesas,groups = "vin0_data8", "vin0_clk";
-		renesas,function = "vin0";
+		groups = "vin0_data8", "vin0_clk";
+		function = "vin0";
 	};
 
 	usb0_pins: usb0 {
-		renesas,groups = "usb0";
-		renesas,function = "usb0";
+		groups = "usb0";
+		function = "usb0";
 	};
 
 	usb1_pins: usb1 {
-		renesas,groups = "usb1";
-		renesas,function = "usb1";
+		groups = "usb1";
+		function = "usb1";
 	};
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/rk3036.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/rk3036.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/rk3036.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/rk3036.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -63,11 +63,6 @@
 		spi = &spi;
 	};
 
-	memory {
-		device_type = "memory";
-		reg = <0x60000000 0x40000000>;
-	};
-
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -119,6 +114,11 @@
 		interrupt-affinity = <&cpu0>, <&cpu1>;
 	};
 
+	display-subsystem {
+		compatible = "rockchip,display-subsystem";
+		ports = <&vop_out>;
+	};
+
 	timer {
 		compatible = "arm,armv7-timer";
 		arm,cpu-registers-not-fw-configured;
@@ -149,6 +149,36 @@
 		};
 	};
 
+	vop: vop@10118000 {
+		compatible = "rockchip,rk3036-vop";
+		reg = <0x10118000 0x19c>;
+		interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru ACLK_LCDC>, <&cru SCLK_LCDC>, <&cru HCLK_LCDC>;
+		clock-names = "aclk_vop", "dclk_vop", "hclk_vop";
+		resets = <&cru SRST_LCDC1_A>, <&cru SRST_LCDC1_H>, <&cru SRST_LCDC1_D>;
+		reset-names = "axi", "ahb", "dclk";
+		iommus = <&vop_mmu>;
+		status = "disabled";
+
+		vop_out: port {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			vop_out_hdmi: endpoint@0 {
+				reg = <0>;
+				remote-endpoint = <&hdmi_in_vop>;
+			};
+		};
+	};
+
+	vop_mmu: iommu@10118300 {
+		compatible = "rockchip,iommu";
+		reg = <0x10118300 0x100>;
+		interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "vop_mmu";
+		#iommu-cells = <0>;
+		status = "disabled";
+	};
+
 	gic: interrupt-controller@10139000 {
 		compatible = "arm,gic-400";
 		interrupt-controller;
@@ -237,7 +267,6 @@
 		compatible = "rockchip,rk3036-dw-mshc", "rockchip,rk3288-dw-mshc";
 		reg = <0x1021c000 0x4000>;
 		interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
-		broken-cd;
 		bus-width = <8>;
 		cap-mmc-highspeed;
 		clock-frequency = <37500000>;
@@ -297,6 +326,27 @@
 		status = "disabled";
 	};
 
+	hdmi: hdmi@20034000 {
+		compatible = "rockchip,rk3036-inno-hdmi";
+		reg = <0x20034000 0x4000>;
+		interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru  PCLK_HDMI>;
+		clock-names = "pclk";
+		rockchip,grf = <&grf>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&hdmi_ctl>;
+		status = "disabled";
+
+		hdmi_in: port {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			hdmi_in_vop: endpoint@0 {
+				reg = <0>;
+				remote-endpoint = <&vop_out_hdmi>;
+			};
+		};
+	};
+
 	timer: timer@20044000 {
 		compatible = "rockchip,rk3036-timer", "rockchip,rk3288-timer";
 		reg = <0x20044000 0x20>;
@@ -644,6 +694,15 @@
 			};
 		};
 
+		hdmi {
+			hdmi_ctl: hdmi-ctl {
+				rockchip,pins = <1 8  RK_FUNC_1 &pcfg_pull_none>,
+						<1 9  RK_FUNC_1 &pcfg_pull_none>,
+						<1 10 RK_FUNC_1 &pcfg_pull_none>,
+						<1 11 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
 		uart0 {
 			uart0_xfer: uart0-xfer {
 				rockchip,pins = <0 16 RK_FUNC_1 &pcfg_pull_default>,
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/rk3036-evb.dts linux-libre-4.7-gnu/arch/arm/boot/dts/rk3036-evb.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/rk3036-evb.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/rk3036-evb.dts	2016-07-24 15:23:50.000000000 -0400
@@ -45,6 +45,11 @@
 / {
 	model = "Rockchip RK3036 Evaluation board";
 	compatible = "rockchip,rk3036-evb", "rockchip,rk3036";
+
+	memory {
+		device_type = "memory";
+		reg = <0x60000000 0x40000000>;
+	};
 };
 
 &emac {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/rk3036-kylin.dts linux-libre-4.7-gnu/arch/arm/boot/dts/rk3036-kylin.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/rk3036-kylin.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/rk3036-kylin.dts	2016-07-24 15:23:50.000000000 -0400
@@ -46,6 +46,11 @@
 	model = "Rockchip RK3036 KylinBoard";
 	compatible = "rockchip,rk3036-kylin", "rockchip,rk3036";
 
+	memory {
+		device_type = "memory";
+		reg = <0x60000000 0x20000000>;
+	};
+
 	leds: gpio-leds {
 		compatible = "gpio-leds";
 
@@ -130,6 +135,10 @@
 	status = "okay";
 };
 
+&hdmi {
+	status = "okay";
+};
+
 &i2c1 {
 	clock-frequency = <400000>;
 
@@ -341,7 +350,6 @@
 &sdio {
 	status = "okay";
 
-	broken-cd;
 	bus-width = <4>;
 	cap-sd-highspeed;
 	cap-sdio-irq;
@@ -385,6 +393,14 @@
 	status = "okay";
 };
 
+&vop {
+	status = "okay";
+};
+
+&vop_mmu {
+	status = "okay";
+};
+
 &pinctrl {
 	leds {
 		led_ctl: led-ctl {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/rk3066a-bqcurie2.dts linux-libre-4.7-gnu/arch/arm/boot/dts/rk3066a-bqcurie2.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/rk3066a-bqcurie2.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/rk3066a-bqcurie2.dts	2016-07-24 15:23:50.000000000 -0400
@@ -42,6 +42,7 @@
  */
 
 /dts-v1/;
+#include <dt-bindings/input/input.h>
 #include "rk3066a.dtsi"
 
 / {
@@ -77,21 +78,19 @@
 
 	gpio-keys {
 		compatible = "gpio-keys";
-		#address-cells = <1>;
-		#size-cells = <0>;
 		autorepeat;
 
-		button@0 {
+		power {
 			gpios = <&gpio6 2 GPIO_ACTIVE_LOW>; /* GPIO6_A2 */
-			linux,code = <116>;
+			linux,code = <KEY_POWER>;
 			label = "GPIO Key Power";
 			linux,input-type = <1>;
 			wakeup-source;
 			debounce-interval = <100>;
 		};
-		button@1 {
+		volume-down {
 			gpios = <&gpio4 21 GPIO_ACTIVE_LOW>; /* GPIO4_C5 */
-			linux,code = <104>;
+			linux,code = <KEY_VOLUMEDOWN>;
 			label = "GPIO Key Vol-";
 			linux,input-type = <1>;
 			debounce-interval = <100>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/rk3066a.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/rk3066a.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/rk3066a.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/rk3066a.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -169,7 +169,7 @@
 		clocks = <&cru PCLK_EFUSE>;
 		clock-names = "pclk_efuse";
 
-		cpu_leakage: cpu_leakage {
+		cpu_leakage: cpu_leakage@17 {
 			reg = <0x17 0x1>;
 		};
 	};
@@ -207,7 +207,7 @@
 		#size-cells = <0>;
 		status = "disabled";
 
-		usbphy0: usb-phy0 {
+		usbphy0: usb-phy@17c {
 			#phy-cells = <0>;
 			reg = <0x17c>;
 			clocks = <&cru SCLK_OTGPHY0>;
@@ -215,7 +215,7 @@
 			#clock-cells = <0>;
 		};
 
-		usbphy1: usb-phy1 {
+		usbphy1: usb-phy@188 {
 			#phy-cells = <0>;
 			reg = <0x188>;
 			clocks = <&cru SCLK_OTGPHY1>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/rk3066a-rayeager.dts linux-libre-4.7-gnu/arch/arm/boot/dts/rk3066a-rayeager.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/rk3066a-rayeager.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/rk3066a-rayeager.dts	2016-07-24 15:23:50.000000000 -0400
@@ -41,6 +41,7 @@
  */
 
 /dts-v1/;
+#include <dt-bindings/input/input.h>
 #include "rk3066a.dtsi"
 
 / {
@@ -61,14 +62,12 @@
 
 	keys: gpio-keys {
 		compatible = "gpio-keys";
-		#address-cells = <1>;
-		#size-cells = <0>;
 
-		button@0 {
+		power {
 			wakeup-source;
 			gpios = <&gpio6 2 GPIO_ACTIVE_LOW>;
 			label = "GPIO Power";
-			linux,code = <116>;
+			linux,code = <KEY_POWER>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pwr_key>;
 		};
@@ -182,7 +181,6 @@
 };
 
 &emmc {
-	broken-cd;
 	bus-width = <8>;
 	cap-mmc-highspeed;
 	disable-wp;
@@ -348,7 +346,6 @@
 };
 
 &mmc1 {
-	broken-cd;
 	bus-width = <4>;
 	disable-wp;
 	non-removable;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/rk3188.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/rk3188.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/rk3188.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/rk3188.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -154,7 +154,7 @@
 		clocks = <&cru PCLK_EFUSE>;
 		clock-names = "pclk_efuse";
 
-		cpu_leakage: cpu_leakage {
+		cpu_leakage: cpu_leakage@17 {
 			reg = <0x17 0x1>;
 		};
 	};
@@ -166,7 +166,7 @@
 		#size-cells = <0>;
 		status = "disabled";
 
-		usbphy0: usb-phy0 {
+		usbphy0: usb-phy@10c {
 			#phy-cells = <0>;
 			reg = <0x10c>;
 			clocks = <&cru SCLK_OTGPHY0>;
@@ -174,7 +174,7 @@
 			#clock-cells = <0>;
 		};
 
-		usbphy1: usb-phy1 {
+		usbphy1: usb-phy@11c {
 			#phy-cells = <0>;
 			reg = <0x11c>;
 			clocks = <&cru SCLK_OTGPHY1>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/rk3188-radxarock.dts linux-libre-4.7-gnu/arch/arm/boot/dts/rk3188-radxarock.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/rk3188-radxarock.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/rk3188-radxarock.dts	2016-07-24 15:23:50.000000000 -0400
@@ -41,6 +41,7 @@
  */
 
 /dts-v1/;
+#include <dt-bindings/input/input.h>
 #include "rk3188.dtsi"
 
 / {
@@ -54,13 +55,11 @@
 
 	gpio-keys {
 		compatible = "gpio-keys";
-		#address-cells = <1>;
-		#size-cells = <0>;
 		autorepeat;
 
-		button@0 {
+		power {
 			gpios = <&gpio0 4 GPIO_ACTIVE_LOW>;
-			linux,code = <116>;
+			linux,code = <KEY_POWER>;
 			label = "GPIO Key Power";
 			linux,input-type = <1>;
 			wakeup-source;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/rk3228.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/rk3228.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/rk3228.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/rk3228.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -43,6 +43,7 @@
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/pinctrl/rockchip.h>
 #include <dt-bindings/clock/rk3228-cru.h>
+#include <dt-bindings/thermal/thermal.h>
 #include "skeleton.dtsi"
 
 / {
@@ -69,6 +70,7 @@
 				/* KHz    uV */
 				 816000 1000000
 			>;
+			#cooling-cells = <2>; /* min followed by max */
 			clock-latency = <40000>;
 			clocks = <&cru ARMCLK>;
 		};
@@ -185,6 +187,58 @@
 		status = "disabled";
 	};
 
+	i2c0: i2c@11050000 {
+		compatible = "rockchip,rk3228-i2c";
+		reg = <0x11050000 0x1000>;
+		interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "i2c";
+		clocks = <&cru PCLK_I2C0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c0_xfer>;
+		status = "disabled";
+	};
+
+	i2c1: i2c@11060000 {
+		compatible = "rockchip,rk3228-i2c";
+		reg = <0x11060000 0x1000>;
+		interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "i2c";
+		clocks = <&cru PCLK_I2C1>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c1_xfer>;
+		status = "disabled";
+	};
+
+	i2c2: i2c@11070000 {
+		compatible = "rockchip,rk3228-i2c";
+		reg = <0x11070000 0x1000>;
+		interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "i2c";
+		clocks = <&cru PCLK_I2C2>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c2_xfer>;
+		status = "disabled";
+	};
+
+	i2c3: i2c@11080000 {
+		compatible = "rockchip,rk3228-i2c";
+		reg = <0x11080000 0x1000>;
+		interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "i2c";
+		clocks = <&cru PCLK_I2C3>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c3_xfer>;
+		status = "disabled";
+	};
+
 	pwm0: pwm@110b0000 {
 		compatible = "rockchip,rk3288-pwm";
 		reg = <0x110b0000 0x10>;
@@ -247,6 +301,63 @@
 		assigned-clock-rates = <594000000>;
 	};
 
+	thermal-zones {
+		cpu_thermal: cpu-thermal {
+			polling-delay-passive = <100>; /* milliseconds */
+			polling-delay = <5000>; /* milliseconds */
+
+			thermal-sensors = <&tsadc 0>;
+
+			trips {
+				cpu_alert0: cpu_alert0 {
+					temperature = <70000>; /* millicelsius */
+					hysteresis = <2000>; /* millicelsius */
+					type = "passive";
+				};
+				cpu_alert1: cpu_alert1 {
+					temperature = <75000>; /* millicelsius */
+					hysteresis = <2000>; /* millicelsius */
+					type = "passive";
+				};
+				cpu_crit: cpu_crit {
+					temperature = <90000>; /* millicelsius */
+					hysteresis = <2000>; /* millicelsius */
+					type = "critical";
+				};
+			};
+
+			cooling-maps {
+				map0 {
+					trip = <&cpu_alert0>;
+					cooling-device =
+						<&cpu0 THERMAL_NO_LIMIT 6>;
+				};
+				map1 {
+					trip = <&cpu_alert1>;
+					cooling-device =
+						<&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+				};
+			};
+		};
+	};
+
+	tsadc: tsadc@11150000 {
+		compatible = "rockchip,rk3228-tsadc";
+		reg = <0x11150000 0x100>;
+		interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru SCLK_TSADC>, <&cru PCLK_TSADC>;
+		clock-names = "tsadc", "apb_pclk";
+		resets = <&cru SRST_TSADC>;
+		reset-names = "tsadc-apb";
+		pinctrl-names = "init", "default", "sleep";
+		pinctrl-0 = <&otp_gpio>;
+		pinctrl-1 = <&otp_out>;
+		pinctrl-2 = <&otp_gpio>;
+		#thermal-sensor-cells = <0>;
+		rockchip,hw-tshut-temp = <95000>;
+		status = "disabled";
+	};
+
 	emmc: dwmmc@30020000 {
 		compatible = "rockchip,rk3288-dw-mshc";
 		reg = <0x30020000 0x4000>;
@@ -370,6 +481,34 @@
 			};
 		};
 
+		i2c0 {
+			i2c0_xfer: i2c0-xfer {
+				rockchip,pins = <0 0 RK_FUNC_1 &pcfg_pull_none>,
+						<0 1 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		i2c1 {
+			i2c1_xfer: i2c1-xfer {
+				rockchip,pins = <0 2 RK_FUNC_1 &pcfg_pull_none>,
+						<0 3 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		i2c2 {
+			i2c2_xfer: i2c2-xfer {
+				rockchip,pins = <2 20 RK_FUNC_1 &pcfg_pull_none>,
+						<2 21 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		i2c3 {
+			i2c3_xfer: i2c3-xfer {
+				rockchip,pins = <0 6 RK_FUNC_1 &pcfg_pull_none>,
+						<0 7 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
 		pwm0 {
 			pwm0_pin: pwm0-pin {
 				rockchip,pins = <3 21 RK_FUNC_1 &pcfg_pull_none>;
@@ -394,6 +533,16 @@
 			};
 		};
 
+		tsadc {
+			otp_gpio: otp-gpio {
+				rockchip,pins = <0 24 RK_FUNC_GPIO &pcfg_pull_none>;
+			};
+
+			otp_out: otp-out {
+				rockchip,pins = <0 24 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+
 		uart0 {
 			uart0_xfer: uart0-xfer {
 				rockchip,pins = <2 26 RK_FUNC_1 &pcfg_pull_none>,
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/rk3228-evb.dts linux-libre-4.7-gnu/arch/arm/boot/dts/rk3228-evb.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/rk3228-evb.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/rk3228-evb.dts	2016-07-24 15:23:50.000000000 -0400
@@ -53,7 +53,6 @@
 };
 
 &emmc {
-	broken-cd;
 	cap-mmc-highspeed;
 	mmc-ddr-1_8v;
 	disable-wp;
@@ -61,6 +60,13 @@
 	status = "okay";
 };
 
+&tsadc {
+	status = "okay";
+
+	rockchip,hw-tshut-mode = <0>; /* tshut mode 0:CRU 1:GPIO */
+	rockchip,hw-tshut-polarity = <1>; /* tshut polarity 0:LOW 1:HIGH */
+};
+
 &uart2 {
 	status = "okay";
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/rk3288.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/rk3288.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/rk3288.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/rk3288.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -445,7 +445,78 @@
 	};
 
 	thermal-zones {
-		#include "rk3288-thermal.dtsi"
+		reserve_thermal: reserve_thermal {
+			polling-delay-passive = <1000>; /* milliseconds */
+			polling-delay = <5000>; /* milliseconds */
+
+			thermal-sensors = <&tsadc 0>;
+		};
+
+		cpu_thermal: cpu_thermal {
+			polling-delay-passive = <100>; /* milliseconds */
+			polling-delay = <5000>; /* milliseconds */
+
+			thermal-sensors = <&tsadc 1>;
+
+			trips {
+				cpu_alert0: cpu_alert0 {
+					temperature = <70000>; /* millicelsius */
+					hysteresis = <2000>; /* millicelsius */
+					type = "passive";
+				};
+				cpu_alert1: cpu_alert1 {
+					temperature = <75000>; /* millicelsius */
+					hysteresis = <2000>; /* millicelsius */
+					type = "passive";
+				};
+				cpu_crit: cpu_crit {
+					temperature = <90000>; /* millicelsius */
+					hysteresis = <2000>; /* millicelsius */
+					type = "critical";
+				};
+			};
+
+			cooling-maps {
+				map0 {
+					trip = <&cpu_alert0>;
+					cooling-device =
+						<&cpu0 THERMAL_NO_LIMIT 6>;
+				};
+				map1 {
+					trip = <&cpu_alert1>;
+					cooling-device =
+						<&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+				};
+			};
+		};
+
+		gpu_thermal: gpu_thermal {
+			polling-delay-passive = <100>; /* milliseconds */
+			polling-delay = <5000>; /* milliseconds */
+
+			thermal-sensors = <&tsadc 2>;
+
+			trips {
+				gpu_alert0: gpu_alert0 {
+					temperature = <70000>; /* millicelsius */
+					hysteresis = <2000>; /* millicelsius */
+					type = "passive";
+				};
+				gpu_crit: gpu_crit {
+					temperature = <90000>; /* millicelsius */
+					hysteresis = <2000>; /* millicelsius */
+					type = "critical";
+				};
+			};
+
+			cooling-maps {
+				map0 {
+					trip = <&gpu_alert0>;
+					cooling-device =
+						<&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+				};
+			};
+		};
 	};
 
 	tsadc: tsadc@ff280000 {
@@ -659,7 +730,7 @@
 			 *	*_HDMI		HDMI
 			 *	*_MIPI_*	MIPI
 			 */
-			pd_vio {
+			pd_vio@RK3288_PD_VIO {
 				reg = <RK3288_PD_VIO>;
 				clocks = <&cru ACLK_IEP>,
 					 <&cru ACLK_ISP>,
@@ -692,7 +763,7 @@
 			 * Note: The following 3 are HEVC(H.265) clocks,
 			 * and on the ACLK_HEVC_NIU (NOC).
 			 */
-			pd_hevc {
+			pd_hevc@RK3288_PD_HEVC {
 				reg = <RK3288_PD_HEVC>;
 				clocks = <&cru ACLK_HEVC>,
 					 <&cru SCLK_HEVC_CABAC>,
@@ -704,7 +775,7 @@
 			 * (video endecoder & decoder) clocks that on the
 			 * ACLK_VCODEC_NIU and HCLK_VCODEC_NIU (NOC).
 			 */
-			pd_video {
+			pd_video@RK3288_PD_VIDEO {
 				reg = <RK3288_PD_VIDEO>;
 				clocks = <&cru ACLK_VCODEC>,
 					 <&cru HCLK_VCODEC>;
@@ -714,7 +785,7 @@
 			 * Note: ACLK_GPU is the GPU clock,
 			 * and on the ACLK_GPU_NIU (NOC).
 			 */
-			pd_gpu {
+			pd_gpu@RK3288_PD_GPU {
 				reg = <RK3288_PD_GPU>;
 				clocks = <&cru ACLK_GPU>;
 			};
@@ -745,8 +816,16 @@
 	};
 
 	grf: syscon@ff770000 {
-		compatible = "rockchip,rk3288-grf", "syscon";
+		compatible = "rockchip,rk3288-grf", "syscon", "simple-mfd";
 		reg = <0xff770000 0x1000>;
+
+		edp_phy: edp-phy {
+			compatible = "rockchip,rk3288-dp-phy";
+			clocks = <&cru SCLK_EDP_24M>;
+			clock-names = "24m";
+			#phy-cells = <0>;
+			status = "disabled";
+		};
 	};
 
 	wdt: watchdog@ff800000 {
@@ -765,7 +844,7 @@
 		clocks = <&cru HCLK_SPDIF8CH>, <&cru SCLK_SPDIF8CH>;
 		dmas = <&dmac_bus_s 3>;
 		dma-names = "tx";
-		interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&spdif_tx>;
 		rockchip,grf = <&grf>;
@@ -775,7 +854,7 @@
 	i2s: i2s@ff890000 {
 		compatible = "rockchip,rk3288-i2s", "rockchip,rk3066-i2s";
 		reg = <0xff890000 0x10000>;
-		interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
 		#address-cells = <1>;
 		#size-cells = <0>;
 		dmas = <&dmac_bus_s 0>, <&dmac_bus_s 1>;
@@ -821,6 +900,12 @@
 				reg = <0>;
 				remote-endpoint = <&hdmi_in_vopb>;
 			};
+
+			vopb_out_edp: endpoint@1 {
+				reg = <1>;
+				remote-endpoint = <&edp_in_vopb>;
+			};
+
 			vopb_out_mipi: endpoint@2 {
 				reg = <2>;
 				remote-endpoint = <&mipi_in_vopb>;
@@ -858,6 +943,12 @@
 				reg = <0>;
 				remote-endpoint = <&hdmi_in_vopl>;
 			};
+
+			vopl_out_edp: endpoint@1 {
+				reg = <1>;
+				remote-endpoint = <&edp_in_vopl>;
+			};
+
 			vopl_out_mipi: endpoint@2 {
 				reg = <2>;
 				remote-endpoint = <&mipi_in_vopl>;
@@ -878,19 +969,16 @@
 	mipi_dsi: mipi@ff960000 {
 		compatible = "rockchip,rk3288-mipi-dsi", "snps,dw-mipi-dsi";
 		reg = <0xff960000 0x4000>;
-		interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&cru SCLK_MIPIDSI_24M>, <&cru PCLK_MIPI_DSI0>;
 		clock-names = "ref", "pclk";
+		power-domains = <&power RK3288_PD_VIO>;
 		rockchip,grf = <&grf>;
 		#address-cells = <1>;
 		#size-cells = <0>;
 		status = "disabled";
 
 		ports {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			reg = <1>;
-
 			mipi_in: port {
 				#address-cells = <1>;
 				#size-cells = <0>;
@@ -906,6 +994,38 @@
 		};
 	};
 
+	edp: dp@ff970000 {
+		compatible = "rockchip,rk3288-dp";
+		reg = <0xff970000 0x4000>;
+		interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru SCLK_EDP>, <&cru PCLK_EDP_CTRL>;
+		clock-names = "dp", "pclk";
+		phys = <&edp_phy>;
+		phy-names = "dp";
+		resets = <&cru SRST_EDP>;
+		reset-names = "dp";
+		rockchip,grf = <&grf>;
+		status = "disabled";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			edp_in: port@0 {
+				reg = <0>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				edp_in_vopb: endpoint@0 {
+					reg = <0>;
+					remote-endpoint = <&vopb_out_edp>;
+				};
+				edp_in_vopl: endpoint@1 {
+					reg = <1>;
+					remote-endpoint = <&vopl_out_edp>;
+				};
+			};
+		};
+	};
+
 	hdmi: hdmi@ff980000 {
 		compatible = "rockchip,rk3288-dw-hdmi";
 		reg = <0xff980000 0x20000>;
@@ -966,7 +1086,7 @@
 		#size-cells = <0>;
 		status = "disabled";
 
-		usbphy0: usb-phy0 {
+		usbphy0: usb-phy@320 {
 			#phy-cells = <0>;
 			reg = <0x320>;
 			clocks = <&cru SCLK_OTGPHY0>;
@@ -974,7 +1094,7 @@
 			#clock-cells = <0>;
 		};
 
-		usbphy1: usb-phy1 {
+		usbphy1: usb-phy@334 {
 			#phy-cells = <0>;
 			reg = <0x334>;
 			clocks = <&cru SCLK_OTGPHY1>;
@@ -982,7 +1102,7 @@
 			#clock-cells = <0>;
 		};
 
-		usbphy2: usb-phy2 {
+		usbphy2: usb-phy@348 {
 			#phy-cells = <0>;
 			reg = <0x348>;
 			clocks = <&cru SCLK_OTGPHY2>;
@@ -1158,6 +1278,12 @@
 			};
 		};
 
+		edp {
+			edp_hpd: edp-hpd {
+				rockchip,pins = <7 11 RK_FUNC_2 &pcfg_pull_down>;
+			};
+		};
+
 		i2c0 {
 			i2c0_xfer: i2c0-xfer {
 				rockchip,pins = <0 15 RK_FUNC_1 &pcfg_pull_none>,
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/rk3288-evb.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/rk3288-evb.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/rk3288-evb.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/rk3288-evb.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -38,6 +38,7 @@
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
+#include <dt-bindings/input/input.h>
 #include <dt-bindings/pwm/pwm.h>
 #include "rk3288.dtsi"
 
@@ -98,16 +99,14 @@
 
 	gpio-keys {
 		compatible = "gpio-keys";
-		#address-cells = <1>;
-		#size-cells = <0>;
 		autorepeat;
 
 		pinctrl-names = "default";
 		pinctrl-0 = <&pwrbtn>;
 
-		button@0 {
+		power {
 			gpios = <&gpio0 5 GPIO_ACTIVE_LOW>;
-			linux,code = <116>;
+			linux,code = <KEY_POWER>;
 			label = "GPIO Key Power";
 			linux,input-type = <1>;
 			wakeup-source;
@@ -172,7 +171,6 @@
 };
 
 &emmc {
-	broken-cd;
 	bus-width = <8>;
 	cap-mmc-highspeed;
 	disable-wp;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/rk3288-firefly.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/rk3288-firefly.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/rk3288-firefly.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/rk3288-firefly.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -40,6 +40,7 @@
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
+#include <dt-bindings/input/input.h>
 #include "rk3288.dtsi"
 
 / {
@@ -87,14 +88,12 @@
 
 	keys: gpio-keys {
 		compatible = "gpio-keys";
-		#address-cells = <1>;
-		#size-cells = <0>;
 
-		button@0 {
+		power {
 			wakeup-source;
 			gpios = <&gpio0 5 GPIO_ACTIVE_LOW>;
 			label = "GPIO Power";
-			linux,code = <116>;
+			linux,code = <KEY_POWER>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pwr_key>;
 		};
@@ -208,7 +207,6 @@
 };
 
 &emmc {
-	broken-cd;
 	bus-width = <8>;
 	cap-mmc-highspeed;
 	disable-wp;
@@ -509,7 +507,6 @@
 };
 
 &sdio0 {
-	broken-cd;
 	bus-width = <4>;
 	disable-wp;
 	non-removable;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/rk3288-miqi.dts linux-libre-4.7-gnu/arch/arm/boot/dts/rk3288-miqi.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/rk3288-miqi.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/rk3288-miqi.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,472 @@
+/*
+ * Copyright (c) 2016 Heiko Stuebner <heiko@sntech.de>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include <dt-bindings/input/input.h>
+#include "rk3288.dtsi"
+
+/ {
+	model = "mqmaker MiQi";
+	compatible = "mqmaker,miqi", "rockchip,rk3288";
+
+	chosen {
+		stdout-path = "serial2:115200n8";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0 0x80000000>;
+	};
+
+	ext_gmac: external-gmac-clock {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <125000000>;
+		clock-output-names = "ext_gmac";
+	};
+
+	io_domains: io-domains {
+		compatible = "rockchip,rk3288-io-voltage-domain";
+
+		audio-supply = <&vcca_33>;
+		flash0-supply = <&vcc_flash>;
+		flash1-supply = <&vcc_lan>;
+		gpio30-supply = <&vcc_io>;
+		gpio1830-supply = <&vcc_io>;
+		lcdc-supply = <&vcc_io>;
+		sdcard-supply = <&vccio_sd>;
+		wifi-supply = <&vcc_18>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		work {
+			gpios = <&gpio7 4 GPIO_ACTIVE_LOW>;
+			label = "miqi:green:user";
+			linux,default-trigger = "default-on";
+			pinctrl-names = "default";
+			pinctrl-0 = <&led_ctl>;
+		};
+	};
+
+	vcc_flash: flash-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_flash";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		vin-supply = <&vcc_io>;
+	};
+
+	vcc_host: usb-host-regulator {
+		compatible = "regulator-fixed";
+		enable-active-high;
+		gpio = <&gpio0 14 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&host_vbus_drv>;
+		regulator-name = "vcc_host";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+		vin-supply = <&vcc_sys>;
+	};
+
+	vcc_sd: sdmmc-regulator {
+		compatible = "regulator-fixed";
+		gpio = <&gpio7 11 GPIO_ACTIVE_LOW>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sdmmc_pwr>;
+		regulator-name = "vcc_sd";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		startup-delay-us = <100000>;
+		vin-supply = <&vcc_io>;
+	};
+
+	vcc_sys: vsys-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_sys";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+};
+
+&cpu0 {
+	cpu0-supply = <&vdd_cpu>;
+};
+
+&emmc {
+	bus-width = <8>;
+	cap-mmc-highspeed;
+	disable-wp;
+	non-removable;
+	num-slots = <1>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&emmc_clk>, <&emmc_cmd>, <&emmc_pwr>, <&emmc_bus8>;
+	vmmc-supply = <&vcc_io>;
+	vqmmc-supply = <&vcc_flash>;
+	status = "okay";
+};
+
+&gmac {
+	assigned-clocks = <&cru SCLK_MAC>;
+	assigned-clock-parents = <&ext_gmac>;
+	clock_in_out = "input";
+	pinctrl-names = "default";
+	pinctrl-0 = <&rgmii_pins>, <&phy_rst>, <&phy_pmeb>, <&phy_int>;
+	phy-supply = <&vcc_lan>;
+	phy-mode = "rgmii";
+	snps,reset-active-low;
+	snps,reset-delays-us = <0 10000 1000000>;
+	snps,reset-gpio = <&gpio4 8 GPIO_ACTIVE_LOW>;
+	tx_delay = <0x30>;
+	rx_delay = <0x10>;
+	status = "ok";
+};
+
+&hdmi {
+	ddc-i2c-bus = <&i2c5>;
+	status = "okay";
+};
+
+&i2c0 {
+	clock-frequency = <400000>;
+	status = "okay";
+
+	vdd_cpu: syr827@40 {
+		compatible = "silergy,syr827";
+		fcs,suspend-voltage-selector = <1>;
+		reg = <0x40>;
+		regulator-name = "vdd_cpu";
+		regulator-min-microvolt = <850000>;
+		regulator-max-microvolt = <1350000>;
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-enable-ramp-delay = <300>;
+		regulator-ramp-delay = <8000>;
+		vin-supply = <&vcc_sys>;
+	};
+
+	vdd_gpu: syr828@41 {
+		compatible = "silergy,syr828";
+		fcs,suspend-voltage-selector = <1>;
+		reg = <0x41>;
+		regulator-name = "vdd_gpu";
+		regulator-min-microvolt = <850000>;
+		regulator-max-microvolt = <1350000>;
+		regulator-always-on;
+		vin-supply = <&vcc_sys>;
+	};
+
+	hym8563: hym8563@51 {
+		compatible = "haoyu,hym8563";
+		reg = <0x51>;
+		#clock-cells = <0>;
+		clock-frequency = <32768>;
+		clock-output-names = "xin32k";
+	};
+
+	act8846: act8846@5a {
+		compatible = "active-semi,act8846";
+		reg = <0x5a>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pmic_vsel>;
+		system-power-controller;
+
+		vp1-supply = <&vcc_sys>;
+		vp2-supply = <&vcc_sys>;
+		vp3-supply = <&vcc_sys>;
+		vp4-supply = <&vcc_sys>;
+		inl1-supply = <&vcc_sys>;
+		inl2-supply = <&vcc_sys>;
+		inl3-supply = <&vcc_20>;
+
+		regulators {
+			vcc_ddr: REG1 {
+				regulator-name = "vcc_ddr";
+				regulator-always-on;
+			};
+
+			vcc_io: REG2 {
+				regulator-name = "vcc_io";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vdd_log: REG3 {
+				regulator-name = "vdd_log";
+				regulator-min-microvolt = <1100000>;
+				regulator-max-microvolt = <1100000>;
+				regulator-always-on;
+			};
+
+			vcc_20: REG4 {
+				regulator-name = "vcc_20";
+				regulator-min-microvolt = <2000000>;
+				regulator-max-microvolt = <2000000>;
+				regulator-always-on;
+			};
+
+			vccio_sd: REG5 {
+				regulator-name = "vccio_sd";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vdd10_lcd: REG6 {
+				regulator-name = "vdd10_lcd";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-always-on;
+			};
+
+			vcca_18: REG7 {
+				regulator-name = "vcca_18";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+			};
+
+			vcca_33: REG8 {
+				regulator-name = "vcca_33";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			vcc_lan: REG9 {
+				regulator-name = "vcc_lan";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			vdd_10: REG10 {
+				regulator-name = "vdd_10";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-always-on;
+			};
+
+			vcc_18: REG11 {
+				regulator-name = "vcc_18";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+			};
+
+			vcc18_lcd: REG12 {
+				regulator-name = "vcc18_lcd";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+			};
+		};
+	};
+};
+
+&i2c1 {
+	status = "okay";
+};
+
+&i2c2 {
+	status = "okay";
+};
+
+&i2c4 {
+	status = "okay";
+};
+
+&i2c5 {
+	status = "okay";
+};
+
+&pinctrl {
+	pcfg_output_high: pcfg-output-high {
+		output-high;
+	};
+
+	pcfg_output_low: pcfg-output-low {
+		output-low;
+	};
+
+	pcfg_pull_up_drv_12ma: pcfg-pull-up-drv-12ma {
+		bias-pull-up;
+		drive-strength = <12>;
+	};
+
+	act8846 {
+		pmic_int: pmic-int {
+			rockchip,pins = <0 4 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+
+		pmic_sleep: pmic-sleep {
+			rockchip,pins = <0 0 RK_FUNC_GPIO &pcfg_output_low>;
+		};
+
+		pmic_vsel: pmic-vsel {
+			rockchip,pins = <7 1 RK_FUNC_GPIO &pcfg_output_low>;
+		};
+	};
+
+	gmac {
+		phy_int: phy-int {
+			rockchip,pins = <0 9 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+
+		phy_pmeb: phy-pmeb {
+			rockchip,pins = <0 8 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+
+		phy_rst: phy-rst {
+			rockchip,pins = <4 8 RK_FUNC_GPIO &pcfg_output_high>;
+		};
+	};
+
+	leds {
+		led_ctl: led-ctl {
+			rockchip,pins = <7 4 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	sdmmc {
+		/*
+		 * Default drive strength isn't enough to achieve even
+		 * high-speed mode on firefly board so bump up to 12ma.
+		 */
+		sdmmc_bus4: sdmmc-bus4 {
+			rockchip,pins = <6 16 RK_FUNC_1 &pcfg_pull_up_drv_12ma>,
+					<6 17 RK_FUNC_1 &pcfg_pull_up_drv_12ma>,
+					<6 18 RK_FUNC_1 &pcfg_pull_up_drv_12ma>,
+					<6 19 RK_FUNC_1 &pcfg_pull_up_drv_12ma>;
+		};
+
+		sdmmc_clk: sdmmc-clk {
+			rockchip,pins = <6 20 RK_FUNC_1 &pcfg_pull_none_12ma>;
+		};
+
+		sdmmc_cmd: sdmmc-cmd {
+			rockchip,pins = <6 21 RK_FUNC_1 &pcfg_pull_up_drv_12ma>;
+		};
+
+		sdmmc_pwr: sdmmc-pwr {
+			rockchip,pins = <7 11 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	usb_host {
+		host_vbus_drv: host-vbus-drv {
+			rockchip,pins = <0 14 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+};
+
+&saradc {
+	vref-supply = <&vcc_18>;
+	status = "okay";
+};
+
+&sdmmc {
+	bus-width = <4>;
+	cap-mmc-highspeed;
+	cap-sd-highspeed;
+	card-detect-delay = <200>;
+	disable-wp;
+	num-slots = <1>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&sdmmc_clk>, <&sdmmc_cmd>, <&sdmmc_cd>, <&sdmmc_bus4>;
+	vmmc-supply = <&vcc_sd>;
+	vqmmc-supply = <&vccio_sd>;
+	status = "okay";
+};
+
+&tsadc {
+	rockchip,hw-tshut-mode = <0>;
+	rockchip,hw-tshut-polarity = <0>;
+	status = "okay";
+};
+
+&uart2 {
+	status = "okay";
+};
+
+&uart3 {
+	status = "okay";
+};
+
+&usbphy {
+	status = "okay";
+};
+
+&usb_host1 {
+	status = "okay";
+};
+
+&usb_otg {
+	/*
+	 * The otg controller is the only system power source,
+	 * so needs to always stay in device mode.
+	 */
+	dr_mode = "peripheral";
+	status = "okay";
+};
+
+&vopb {
+	status = "okay";
+};
+
+&vopb_mmu {
+	status = "okay";
+};
+
+&vopl {
+	status = "okay";
+};
+
+&vopl_mmu {
+	status = "okay";
+};
+
+&wdt {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/rk3288-popmetal.dts linux-libre-4.7-gnu/arch/arm/boot/dts/rk3288-popmetal.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/rk3288-popmetal.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/rk3288-popmetal.dts	2016-07-24 15:23:50.000000000 -0400
@@ -41,7 +41,7 @@
  */
 
 /dts-v1/;
-
+#include <dt-bindings/input/input.h>
 #include "rk3288.dtsi"
 
 / {
@@ -62,16 +62,14 @@
 
 	gpio-keys {
 		compatible = "gpio-keys";
-		#address-cells = <1>;
-		#size-cells = <0>;
 		autorepeat;
 
 		pinctrl-names = "default";
 		pinctrl-0 = <&pwrbtn>;
 
-		button@0 {
+		power {
 			gpios = <&gpio0 5 GPIO_ACTIVE_LOW>;
-			linux,code = <116>;
+			linux,code = <KEY_POWER>;
 			label = "GPIO Key Power";
 			linux,input-type = <1>;
 			wakeup-source;
@@ -162,7 +160,6 @@
 };
 
 &emmc {
-	broken-cd;
 	bus-width = <8>;
 	cap-mmc-highspeed;
 	disable-wp;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/rk3288-r89.dts linux-libre-4.7-gnu/arch/arm/boot/dts/rk3288-r89.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/rk3288-r89.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/rk3288-r89.dts	2016-07-24 15:23:50.000000000 -0400
@@ -41,6 +41,7 @@
  */
 
 /dts-v1/;
+#include <dt-bindings/input/input.h>
 #include <dt-bindings/pwm/pwm.h>
 #include "rk3288.dtsi"
 
@@ -61,16 +62,14 @@
 
 	gpio-keys {
 		compatible = "gpio-keys";
-		#address-cells = <1>;
-		#size-cells = <0>;
 		autorepeat;
 
 		pinctrl-names = "default";
 		pinctrl-0 = <&pwrbtn>;
 
-		button@0 {
+		power {
 			gpios = <&gpio0 5 GPIO_ACTIVE_LOW>;
-			linux,code = <116>;
+			linux,code = <KEY_POWER>;
 			label = "GPIO Key Power";
 			linux,input-type = <1>;
 			wakeup-source;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/rk3288-thermal.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/rk3288-thermal.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/rk3288-thermal.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/rk3288-thermal.dtsi	1969-12-31 19:00:00.000000000 -0500
@@ -1,118 +0,0 @@
-/*
- * Device Tree Source for RK3288 SoC thermal
- *
- * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This file is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- * Or, alternatively,
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use,
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *     OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <dt-bindings/thermal/thermal.h>
-
-reserve_thermal: reserve_thermal {
-	polling-delay-passive = <1000>; /* milliseconds */
-	polling-delay = <5000>; /* milliseconds */
-
-	thermal-sensors = <&tsadc 0>;
-};
-
-cpu_thermal: cpu_thermal {
-	polling-delay-passive = <100>; /* milliseconds */
-	polling-delay = <5000>; /* milliseconds */
-
-	thermal-sensors = <&tsadc 1>;
-
-	trips {
-		cpu_alert0: cpu_alert0 {
-			temperature = <70000>; /* millicelsius */
-			hysteresis = <2000>; /* millicelsius */
-			type = "passive";
-		};
-		cpu_alert1: cpu_alert1 {
-			temperature = <75000>; /* millicelsius */
-			hysteresis = <2000>; /* millicelsius */
-			type = "passive";
-		};
-		cpu_crit: cpu_crit {
-			temperature = <90000>; /* millicelsius */
-			hysteresis = <2000>; /* millicelsius */
-			type = "critical";
-		};
-	};
-
-	cooling-maps {
-		map0 {
-			trip = <&cpu_alert0>;
-			cooling-device =
-				<&cpu0 THERMAL_NO_LIMIT 6>;
-		};
-		map1 {
-			trip = <&cpu_alert1>;
-			cooling-device =
-				<&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
-		};
-	};
-};
-
-gpu_thermal: gpu_thermal {
-	polling-delay-passive = <100>; /* milliseconds */
-	polling-delay = <5000>; /* milliseconds */
-
-	thermal-sensors = <&tsadc 2>;
-
-	trips {
-		gpu_alert0: gpu_alert0 {
-			temperature = <70000>; /* millicelsius */
-			hysteresis = <2000>; /* millicelsius */
-			type = "passive";
-		};
-		gpu_crit: gpu_crit {
-			temperature = <90000>; /* millicelsius */
-			hysteresis = <2000>; /* millicelsius */
-			type = "critical";
-		};
-	};
-
-	cooling-maps {
-		map0 {
-			trip = <&gpu_alert0>;
-			cooling-device =
-				<&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
-		};
-	};
-};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -54,6 +54,50 @@
 		i2c20 = &i2c_tunnel;
 	};
 
+	backlight: backlight {
+		compatible = "pwm-backlight";
+		brightness-levels = <
+			  0   1   2   3   4   5   6   7
+			  8   9  10  11  12  13  14  15
+			 16  17  18  19  20  21  22  23
+			 24  25  26  27  28  29  30  31
+			 32  33  34  35  36  37  38  39
+			 40  41  42  43  44  45  46  47
+			 48  49  50  51  52  53  54  55
+			 56  57  58  59  60  61  62  63
+			 64  65  66  67  68  69  70  71
+			 72  73  74  75  76  77  78  79
+			 80  81  82  83  84  85  86  87
+			 88  89  90  91  92  93  94  95
+			 96  97  98  99 100 101 102 103
+			104 105 106 107 108 109 110 111
+			112 113 114 115 116 117 118 119
+			120 121 122 123 124 125 126 127
+			128 129 130 131 132 133 134 135
+			136 137 138 139 140 141 142 143
+			144 145 146 147 148 149 150 151
+			152 153 154 155 156 157 158 159
+			160 161 162 163 164 165 166 167
+			168 169 170 171 172 173 174 175
+			176 177 178 179 180 181 182 183
+			184 185 186 187 188 189 190 191
+			192 193 194 195 196 197 198 199
+			200 201 202 203 204 205 206 207
+			208 209 210 211 212 213 214 215
+			216 217 218 219 220 221 222 223
+			224 225 226 227 228 229 230 231
+			232 233 234 235 236 237 238 239
+			240 241 242 243 244 245 246 247
+			248 249 250 251 252 253 254 255>;
+		default-brightness-level = <128>;
+		enable-gpios = <&gpio7 2 GPIO_ACTIVE_HIGH>;
+		backlight-boot-off;
+		pinctrl-names = "default";
+		pinctrl-0 = <&bl_en>;
+		pwms = <&pwm0 0 1000000 0>;
+		pwm-delay-us = <10000>;
+	};
+
 	gpio-charger {
 		compatible = "gpio-charger";
 		charger-type = "mains";
@@ -62,6 +106,21 @@
 		pinctrl-0 = <&ac_present_ap>;
 	};
 
+	panel: panel {
+		compatible ="innolux,n116bge", "simple-panel";
+		status = "okay";
+		power-supply = <&vcc33_lcd>;
+		backlight = <&backlight>;
+
+		ports {
+			panel_in: port {
+				panel_in_edp: endpoint {
+					remote-endpoint = <&edp_out_panel>;
+				};
+			};
+		};
+	};
+
 	/* A non-regulated voltage from power supply or battery */
 	vccsys: vccsys {
 		compatible = "regulator-fixed";
@@ -103,6 +162,29 @@
 	};
 };
 
+&edp {
+	status = "okay";
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&edp_hpd>;
+
+	ports {
+		edp_out: port@1 {
+			reg = <1>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			edp_out_panel: endpoint {
+				reg = <0>;
+				remote-endpoint = <&panel_in_edp>;
+			};
+		};
+	};
+};
+
+&edp_phy {
+	status = "okay";
+};
+
 &gpio_keys {
 	pinctrl-0 = <&pwr_key_l &ap_lid_int_l>;
 	lid {
@@ -115,6 +197,10 @@
 	};
 };
 
+&pwm0 {
+	status = "okay";
+};
+
 &rk808 {
 	vcc11-supply = <&vcc_5v>;
 
@@ -168,6 +254,14 @@
 	};
 };
 
+&vopl {
+	status = "okay";
+};
+
+&vopl_mmu {
+	status = "okay";
+};
+
 &pinctrl {
 	pinctrl-0 = <
 		/* Common for sleep and wake, but no owners */
@@ -184,6 +278,12 @@
 		&suspend_l_sleep
 	>;
 
+	backlight {
+		bl_en: bl-en {
+			rockchip,pins = <7 2 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
 	buttons {
 		ap_lid_int_l: ap-lid-int-l {
 			rockchip,pins = <0 6 RK_FUNC_GPIO &pcfg_pull_up>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/rk3288-veyron.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/rk3288-veyron.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/rk3288-veyron.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/rk3288-veyron.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -141,12 +141,27 @@
 
 &cpu0 {
 	cpu0-supply = <&vdd_cpu>;
+	operating-points = <
+		/* KHz    uV */
+		1800000 1400000
+		1704000 1350000
+		1608000 1300000
+		1512000 1250000
+		1416000 1200000
+		1200000 1100000
+		1008000 1050000
+		 816000 1000000
+		 696000  950000
+		 600000  900000
+		 408000  900000
+		 216000  900000
+		 126000  900000
+	>;
 };
 
 &emmc {
 	status = "okay";
 
-	broken-cd;
 	bus-width = <8>;
 	cap-mmc-highspeed;
 	rockchip,default-sample-phase = <158>;
@@ -347,7 +362,6 @@
 &sdio0 {
 	status = "okay";
 
-	broken-cd;
 	bus-width = <4>;
 	cap-sd-highspeed;
 	cap-sdio-irq;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/rk3288-veyron-jaq.dts linux-libre-4.7-gnu/arch/arm/boot/dts/rk3288-veyron-jaq.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/rk3288-veyron-jaq.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/rk3288-veyron-jaq.dts	2016-07-24 15:23:50.000000000 -0400
@@ -61,6 +61,7 @@
 		pinctrl-names = "default";
 		pinctrl-0 = <&lcd_enable_h>;
 		regulator-name = "panel_regulator";
+		startup-delay-us = <100000>;
 		vin-supply = <&vcc33_sys>;
 	};
 
@@ -88,6 +89,48 @@
 	};
 };
 
+&backlight {
+	/* Jaq panel PWM must be >= 3%, so start non-zero brightness at 8 */
+	brightness-levels = <
+		  0
+		  8   9  10  11  12  13  14  15
+		 16  17  18  19  20  21  22  23
+		 24  25  26  27  28  29  30  31
+		 32  33  34  35  36  37  38  39
+		 40  41  42  43  44  45  46  47
+		 48  49  50  51  52  53  54  55
+		 56  57  58  59  60  61  62  63
+		 64  65  66  67  68  69  70  71
+		 72  73  74  75  76  77  78  79
+		 80  81  82  83  84  85  86  87
+		 88  89  90  91  92  93  94  95
+		 96  97  98  99 100 101 102 103
+		104 105 106 107 108 109 110 111
+		112 113 114 115 116 117 118 119
+		120 121 122 123 124 125 126 127
+		128 129 130 131 132 133 134 135
+		136 137 138 139 140 141 142 143
+		144 145 146 147 148 149 150 151
+		152 153 154 155 156 157 158 159
+		160 161 162 163 164 165 166 167
+		168 169 170 171 172 173 174 175
+		176 177 178 179 180 181 182 183
+		184 185 186 187 188 189 190 191
+		192 193 194 195 196 197 198 199
+		200 201 202 203 204 205 206 207
+		208 209 210 211 212 213 214 215
+		216 217 218 219 220 221 222 223
+		224 225 226 227 228 229 230 231
+		232 233 234 235 236 237 238 239
+		240 241 242 243 244 245 246 247
+		248 249 250 251 252 253 254 255>;
+	power-supply = <&backlight_regulator>;
+};
+
+&panel {
+	power-supply = <&panel_regulator>;
+};
+
 &rk808 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pmic_int_l &dvs_1 &dvs_2>;
@@ -142,12 +185,6 @@
 		};
 	};
 
-	edp {
-		edp_hpd: edp_hpd {
-			rockchip,pins = <7 11 RK_FUNC_2 &pcfg_pull_down>;
-		};
-	};
-
 	hdmi {
 		vcc50_hdmi_en: vcc50-hdmi-en {
 			rockchip,pins = <5 19 RK_FUNC_GPIO &pcfg_pull_none>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/rk3288-veyron-jerry.dts linux-libre-4.7-gnu/arch/arm/boot/dts/rk3288-veyron-jerry.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/rk3288-veyron-jerry.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/rk3288-veyron-jerry.dts	2016-07-24 15:23:50.000000000 -0400
@@ -60,6 +60,7 @@
 		pinctrl-names = "default";
 		pinctrl-0 = <&lcd_enable_h>;
 		regulator-name = "panel_regulator";
+		startup-delay-us = <100000>;
 		vin-supply = <&vcc33_sys>;
 	};
 
@@ -87,6 +88,14 @@
 	};
 };
 
+&backlight {
+	power-supply = <&backlight_regulator>;
+};
+
+&panel {
+	power-supply= <&panel_regulator>;
+};
+
 &rk808 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pmic_int_l>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/rk3288-veyron-minnie.dts linux-libre-4.7-gnu/arch/arm/boot/dts/rk3288-veyron-minnie.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/rk3288-veyron-minnie.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/rk3288-veyron-minnie.dts	2016-07-24 15:23:50.000000000 -0400
@@ -70,6 +70,7 @@
 		pinctrl-names = "default";
 		pinctrl-0 = <&lcd_enable_h>;
 		regulator-name = "panel_regulator";
+		startup-delay-us = <100000>;
 		vin-supply = <&vcc33_sys>;
 	};
 
@@ -86,6 +87,44 @@
 	};
 };
 
+&backlight {
+	/* Minnie panel PWM must be >= 1%, so start non-zero brightness at 3 */
+	brightness-levels = <
+			  0   3   4   5   6   7
+			  8   9  10  11  12  13  14  15
+			 16  17  18  19  20  21  22  23
+			 24  25  26  27  28  29  30  31
+			 32  33  34  35  36  37  38  39
+			 40  41  42  43  44  45  46  47
+			 48  49  50  51  52  53  54  55
+			 56  57  58  59  60  61  62  63
+			 64  65  66  67  68  69  70  71
+			 72  73  74  75  76  77  78  79
+			 80  81  82  83  84  85  86  87
+			 88  89  90  91  92  93  94  95
+			 96  97  98  99 100 101 102 103
+			104 105 106 107 108 109 110 111
+			112 113 114 115 116 117 118 119
+			120 121 122 123 124 125 126 127
+			128 129 130 131 132 133 134 135
+			136 137 138 139 140 141 142 143
+			144 145 146 147 148 149 150 151
+			152 153 154 155 156 157 158 159
+			160 161 162 163 164 165 166 167
+			168 169 170 171 172 173 174 175
+			176 177 178 179 180 181 182 183
+			184 185 186 187 188 189 190 191
+			192 193 194 195 196 197 198 199
+			200 201 202 203 204 205 206 207
+			208 209 210 211 212 213 214 215
+			216 217 218 219 220 221 222 223
+			224 225 226 227 228 229 230 231
+			232 233 234 235 236 237 238 239
+			240 241 242 243 244 245 246 247
+			248 249 250 251 252 253 254 255>;
+	power-supply = <&backlight_regulator>;
+};
+
 &emmc {
 	/delete-property/mmc-hs200-1_8v;
 };
@@ -135,6 +174,11 @@
 	};
 };
 
+&panel {
+	compatible = "auo,b101ean01", "simple-panel";
+	power-supply= <&panel_regulator>;
+};
+
 &rk808 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pmic_int_l &dvs_1 &dvs_2>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/rk3288-veyron-pinky.dts linux-libre-4.7-gnu/arch/arm/boot/dts/rk3288-veyron-pinky.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/rk3288-veyron-pinky.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/rk3288-veyron-pinky.dts	2016-07-24 15:23:50.000000000 -0400
@@ -65,6 +65,13 @@
 	pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8 &emmc_reset>;
 };
 
+&edp {
+	/delete-property/pinctrl-names;
+	/delete-property/pinctrl-0;
+
+	force-hpd;
+};
+
 &gpio_keys {
 	pinctrl-0 = <&pwr_key_h &ap_lid_int_l>;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/rk3288-veyron-speedy.dts linux-libre-4.7-gnu/arch/arm/boot/dts/rk3288-veyron-speedy.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/rk3288-veyron-speedy.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/rk3288-veyron-speedy.dts	2016-07-24 15:23:50.000000000 -0400
@@ -61,6 +61,7 @@
 		pinctrl-names = "default";
 		pinctrl-0 = <&lcd_enable_h>;
 		regulator-name = "panel_regulator";
+		startup-delay-us = <100000>;
 		vin-supply = <&vcc33_sys>;
 	};
 
@@ -88,6 +89,10 @@
 	};
 };
 
+&backlight {
+	power-supply = <&backlight_regulator>;
+};
+
 &cpu_alert0 {
 	temperature = <65000>;
 };
@@ -96,6 +101,17 @@
 	temperature = <70000>;
 };
 
+&edp {
+	/delete-property/pinctrl-names;
+	/delete-property/pinctrl-0;
+
+	force-hpd;
+};
+
+&panel {
+	power-supply= <&panel_regulator>;
+};
+
 &rk808 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pmic_int_l>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/s5pv210-smdkv210.dts linux-libre-4.7-gnu/arch/arm/boot/dts/s5pv210-smdkv210.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/s5pv210-smdkv210.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/s5pv210-smdkv210.dts	2016-07-24 15:23:50.000000000 -0400
@@ -197,7 +197,7 @@
 	display-timings {
 		native-mode = <&timing0>;
 
-		timing0: timing@0 {
+		timing0: timing {
 			/* 800x480@60Hz */
 			clock-frequency = <24373920>;
 			hactive = <800>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/sama5d2.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/sama5d2.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/sama5d2.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/sama5d2.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -319,6 +319,32 @@
 			#size-cells = <1>;
 			ranges;
 
+			hlcdc: hlcdc@f0000000 {
+				compatible = "atmel,sama5d2-hlcdc";
+				reg = <0xf0000000 0x2000>;
+				interrupts = <45 IRQ_TYPE_LEVEL_HIGH 0>;
+				clocks = <&lcdc_clk>, <&lcdck>, <&clk32k>;
+				clock-names = "periph_clk","sys_clk", "slow_clk";
+				status = "disabled";
+
+				hlcdc-display-controller {
+					compatible = "atmel,hlcdc-display-controller";
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					port@0 {
+						#address-cells = <1>;
+						#size-cells = <0>;
+						reg = <0>;
+					};
+				};
+
+				hlcdc_pwm: hlcdc-pwm {
+					compatible = "atmel,hlcdc-pwm";
+					#pwm-cells = <3>;
+				};
+			};
+
 			ramc0: ramc@f000c000 {
 				compatible = "atmel,sama5d3-ddramc";
 				reg = <0xf000c000 0x200>;
@@ -973,6 +999,11 @@
 				status = "disabled";
 			};
 
+			sfr: sfr@f8030000 {
+				compatible = "atmel,sama5d2-sfr", "syscon";
+				reg = <0xf8030000 0x98>;
+			};
+
 			flx0: flexcom@f8034000 {
 				compatible = "atmel,sama5d2-flexcom";
 				reg = <0xf8034000 0x200>;
@@ -999,6 +1030,15 @@
 				clocks = <&clk32k>;
 			};
 
+			shdwc@f8048010 {
+				compatible = "atmel,sama5d2-shdwc";
+				reg = <0xf8048010 0x10>;
+				clocks = <&clk32k>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				atmel,wakeup-rtc-timer;
+			};
+
 			pit: timer@f8048030 {
 				compatible = "atmel,at91sam9260-pit";
 				reg = <0xf8048030 0x10>;
@@ -1010,6 +1050,7 @@
 				compatible = "atmel,sama5d4-wdt";
 				reg = <0xf8048040 0x10>;
 				interrupts = <4 IRQ_TYPE_LEVEL_HIGH 7>;
+				clocks = <&clk32k>;
 				status = "disabled";
 			};
 
@@ -1127,6 +1168,13 @@
 				status = "disabled";
 			};
 
+			trng@fc01c000 {
+				compatible = "atmel,at91sam9g45-trng";
+				reg = <0xfc01c000 0x100>;
+				interrupts = <47 IRQ_TYPE_LEVEL_HIGH 0>;
+				clocks = <&trng_clk>;
+			};
+
 			aic: interrupt-controller@fc020000 {
 				#interrupt-cells = <3>;
 				compatible = "atmel,sama5d2-aic";
@@ -1193,6 +1241,11 @@
 				clock-names = "tdes_clk";
 				status = "okay";
 			};
+
+			chipid@fc069000 {
+				compatible = "atmel,sama5d2-chipid";
+				reg = <0xfc069000 0x8>;
+			};
 		};
 	};
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/sama5d2-pinfunc.h linux-libre-4.7-gnu/arch/arm/boot/dts/sama5d2-pinfunc.h
--- linux-libre-4.6-gnu/arch/arm/boot/dts/sama5d2-pinfunc.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/sama5d2-pinfunc.h	2016-07-24 15:23:50.000000000 -0400
@@ -837,8 +837,8 @@
 #define PIN_PD23__ISC_FIELD		PINMUX_PIN(PIN_PD23, 6, 4)
 #define PIN_PD24			120
 #define PIN_PD24__GPIO			PINMUX_PIN(PIN_PD24, 0, 0)
-#define PIN_PD24__UTXD2			PINMUX_PIN(PIN_PD23, 1, 2)
-#define PIN_PD24__FLEXCOM4_IO3		PINMUX_PIN(PIN_PD23, 3, 3)
+#define PIN_PD24__UTXD2			PINMUX_PIN(PIN_PD24, 1, 2)
+#define PIN_PD24__FLEXCOM4_IO3		PINMUX_PIN(PIN_PD24, 3, 3)
 #define PIN_PD25			121
 #define PIN_PD25__GPIO			PINMUX_PIN(PIN_PD25, 0, 0)
 #define PIN_PD25__SPI1_SPCK		PINMUX_PIN(PIN_PD25, 1, 3)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/sama5d3.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/sama5d3.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/sama5d3.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/sama5d3.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -426,6 +426,13 @@
 				clock-names = "tdes_clk";
 			};
 
+			trng@f8040000 {
+				compatible = "atmel,at91sam9g45-trng";
+				reg = <0xf8040000 0x100>;
+				interrupts = <45 IRQ_TYPE_LEVEL_HIGH 0>;
+				clocks = <&trng_clk>;
+			};
+
 			dma0: dma-controller@ffffe600 {
 				compatible = "atmel,at91sam9g45-dma";
 				reg = <0xffffe600 0x200>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/sama5d4.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/sama5d4.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/sama5d4.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/sama5d4.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -1202,6 +1202,13 @@
 				status = "disabled";
 			};
 
+			trng@fc030000 {
+				compatible = "atmel,at91sam9g45-trng";
+				reg = <0xfc030000 0x100>;
+				interrupts = <53 IRQ_TYPE_LEVEL_HIGH 0>;
+				clocks = <&trng_clk>;
+			};
+
 			adc0: adc@fc034000 {
 				compatible = "atmel,at91sam9x5-adc";
 				reg = <0xfc034000 0x100>;
@@ -1302,6 +1309,7 @@
 			watchdog@fc068640 {
 				compatible = "atmel,sama5d4-wdt";
 				reg = <0xfc068640 0x10>;
+				interrupts = <4 IRQ_TYPE_LEVEL_HIGH 7>;
 				clocks = <&clk32k>;
 				status = "disabled";
 			};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/sh73a0.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/sh73a0.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/sh73a0.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/sh73a0.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -43,7 +43,7 @@
 	timer@f0000600 {
 		compatible = "arm,cortex-a9-twd-timer";
 		reg = <0xf0000600 0x20>;
-		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
+		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_EDGE_RISING)>;
 		clocks = <&twd_clk>;
 	};
 
@@ -602,39 +602,33 @@
 		ranges;
 
 		/* External root clocks */
-		extalr_clk: extalr_clk {
+		extalr_clk: extalr {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <32768>;
-			clock-output-names = "extalr";
 		};
-		extal1_clk: extal1_clk {
+		extal1_clk: extal1 {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <26000000>;
-			clock-output-names = "extal1";
 		};
-		extal2_clk: extal2_clk {
+		extal2_clk: extal2 {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
-			clock-output-names = "extal2";
 		};
-		extcki_clk: extcki_clk {
+		extcki_clk: extcki {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
-			clock-output-names = "extcki";
 		};
-		fsiack_clk: fsiack_clk {
+		fsiack_clk: fsiack {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <0>;
-			clock-output-names = "fsiack";
 		};
-		fsibck_clk: fsibck_clk {
+		fsibck_clk: fsibck {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <0>;
-			clock-output-names = "fsibck";
 		};
 
 		/* Special CPG clocks */
@@ -650,7 +644,7 @@
 		};
 
 		/* Variable factor clocks (DIV6) */
-		vclk1_clk: vclk1_clk@e6150008 {
+		vclk1_clk: vclk1@e6150008 {
 			compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0xe6150008 4>;
 			clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>,
@@ -658,9 +652,8 @@
 				 <&extalr_clk>, <&cpg_clocks SH73A0_CLK_MAIN>,
 				 <0>;
 			#clock-cells = <0>;
-			clock-output-names = "vclk1";
 		};
-		vclk2_clk: vclk2_clk@e615000c {
+		vclk2_clk: vclk2@e615000c {
 			compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0xe615000c 4>;
 			clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>,
@@ -668,9 +661,8 @@
 				 <&extalr_clk>, <&cpg_clocks SH73A0_CLK_MAIN>,
 				 <0>;
 			#clock-cells = <0>;
-			clock-output-names = "vclk2";
 		};
-		vclk3_clk: vclk3_clk@e615001c {
+		vclk3_clk: vclk3@e615001c {
 			compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0xe615001c 4>;
 			clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>,
@@ -678,7 +670,6 @@
 				 <&extalr_clk>, <&cpg_clocks SH73A0_CLK_MAIN>,
 				 <0>;
 			#clock-cells = <0>;
-			clock-output-names = "vclk3";
 		};
 		zb_clk: zb_clk@e6150010 {
 			compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
@@ -688,168 +679,148 @@
 			#clock-cells = <0>;
 			clock-output-names = "zb";
 		};
-		flctl_clk: flctl_clk@e6150014 {
+		flctl_clk: flctlck@e6150014 {
 			compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0xe6150014 4>;
 			clocks = <&pll1_div2_clk>, <0>,
 				 <&cpg_clocks SH73A0_CLK_PLL2>, <0>;
 			#clock-cells = <0>;
-			clock-output-names = "flctlck";
 		};
-		sdhi0_clk: sdhi0_clk@e6150074 {
+		sdhi0_clk: sdhi0ck@e6150074 {
 			compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0xe6150074 4>;
 			clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>,
 				 <&pll1_div13_clk>, <0>;
 			#clock-cells = <0>;
-			clock-output-names = "sdhi0ck";
 		};
-		sdhi1_clk: sdhi1_clk@e6150078 {
+		sdhi1_clk: sdhi1ck@e6150078 {
 			compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0xe6150078 4>;
 			clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>,
 				 <&pll1_div13_clk>, <0>;
 			#clock-cells = <0>;
-			clock-output-names = "sdhi1ck";
 		};
-		sdhi2_clk: sdhi2_clk@e615007c {
+		sdhi2_clk: sdhi2ck@e615007c {
 			compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0xe615007c 4>;
 			clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>,
 				 <&pll1_div13_clk>, <0>;
 			#clock-cells = <0>;
-			clock-output-names = "sdhi2ck";
 		};
-		fsia_clk: fsia_clk@e6150018 {
+		fsia_clk: fsia@e6150018 {
 			compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0xe6150018 4>;
 			clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>,
 				 <&fsiack_clk>, <&fsiack_clk>;
 			#clock-cells = <0>;
-			clock-output-names = "fsia";
 		};
-		fsib_clk: fsib_clk@e6150090 {
+		fsib_clk: fsib@e6150090 {
 			compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0xe6150090 4>;
 			clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>,
 				 <&fsibck_clk>, <&fsibck_clk>;
 			#clock-cells = <0>;
-			clock-output-names = "fsib";
 		};
-		sub_clk: sub_clk@e6150080 {
+		sub_clk: sub@e6150080 {
 			compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0xe6150080 4>;
 			clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>,
 				 <&extal2_clk>, <&extal2_clk>;
 			#clock-cells = <0>;
-			clock-output-names = "sub";
 		};
-		spua_clk: spua_clk@e6150084 {
+		spua_clk: spua@e6150084 {
 			compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0xe6150084 4>;
 			clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>,
 				 <&extal2_clk>, <&extal2_clk>;
 			#clock-cells = <0>;
-			clock-output-names = "spua";
 		};
-		spuv_clk: spuv_clk@e6150094 {
+		spuv_clk: spuv@e6150094 {
 			compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0xe6150094 4>;
 			clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>,
 				 <&extal2_clk>, <&extal2_clk>;
 			#clock-cells = <0>;
-			clock-output-names = "spuv";
 		};
-		msu_clk: msu_clk@e6150088 {
+		msu_clk: msu@e6150088 {
 			compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0xe6150088 4>;
 			clocks = <&pll1_div2_clk>, <0>,
 				 <&cpg_clocks SH73A0_CLK_PLL2>, <0>;
 			#clock-cells = <0>;
-			clock-output-names = "msu";
 		};
-		hsi_clk: hsi_clk@e615008c {
+		hsi_clk: hsi@e615008c {
 			compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0xe615008c 4>;
 			clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>,
 				 <&pll1_div7_clk>, <0>;
 			#clock-cells = <0>;
-			clock-output-names = "hsi";
 		};
-		mfg1_clk: mfg1_clk@e6150098 {
+		mfg1_clk: mfg1@e6150098 {
 			compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0xe6150098 4>;
 			clocks = <&pll1_div2_clk>, <0>,
 				 <&cpg_clocks SH73A0_CLK_PLL2>, <0>;
 			#clock-cells = <0>;
-			clock-output-names = "mfg1";
 		};
-		mfg2_clk: mfg2_clk@e615009c {
+		mfg2_clk: mfg2@e615009c {
 			compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0xe615009c 4>;
 			clocks = <&pll1_div2_clk>, <0>,
 				 <&cpg_clocks SH73A0_CLK_PLL2>, <0>;
 			#clock-cells = <0>;
-			clock-output-names = "mfg2";
 		};
-		dsit_clk: dsit_clk@e6150060 {
+		dsit_clk: dsit@e6150060 {
 			compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0xe6150060 4>;
 			clocks = <&pll1_div2_clk>, <0>,
 				 <&cpg_clocks SH73A0_CLK_PLL2>, <0>;
 			#clock-cells = <0>;
-			clock-output-names = "dsit";
 		};
-		dsi0p_clk: dsi0p_clk@e6150064 {
+		dsi0p_clk: dsi0pck@e6150064 {
 			compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
 			reg = <0xe6150064 4>;
 			clocks = <&pll1_div2_clk>, <&cpg_clocks SH73A0_CLK_PLL2>,
 				 <&cpg_clocks SH73A0_CLK_MAIN>, <&extal2_clk>,
 				 <&extcki_clk>, <0>, <0>, <0>;
 			#clock-cells = <0>;
-			clock-output-names = "dsi0pck";
 		};
 
 		/* Fixed factor clocks */
-		main_div2_clk: main_div2_clk {
+		main_div2_clk: main_div2 {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks SH73A0_CLK_MAIN>;
 			#clock-cells = <0>;
 			clock-div = <2>;
 			clock-mult = <1>;
-			clock-output-names = "main_div2";
 		};
-		pll1_div2_clk: pll1_div2_clk {
+		pll1_div2_clk: pll1_div2 {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks SH73A0_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <2>;
 			clock-mult = <1>;
-			clock-output-names = "pll1_div2";
 		};
-		pll1_div7_clk: pll1_div7_clk {
+		pll1_div7_clk: pll1_div7 {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks SH73A0_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <7>;
 			clock-mult = <1>;
-			clock-output-names = "pll1_div7";
 		};
-		pll1_div13_clk: pll1_div13_clk {
+		pll1_div13_clk: pll1_div13 {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks SH73A0_CLK_PLL1>;
 			#clock-cells = <0>;
 			clock-div = <13>;
 			clock-mult = <1>;
-			clock-output-names = "pll1_div13";
 		};
-		twd_clk: twd_clk {
+		twd_clk: twd {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks SH73A0_CLK_Z>;
 			#clock-cells = <0>;
 			clock-div = <4>;
 			clock-mult = <1>;
-			clock-output-names = "twd";
 		};
 
 		/* Gate clocks */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/sh73a0-kzm9g.dts linux-libre-4.7-gnu/arch/arm/boot/dts/sh73a0-kzm9g.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/sh73a0-kzm9g.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/sh73a0-kzm9g.dts	2016-07-24 15:23:50.000000000 -0400
@@ -149,6 +149,13 @@
 			label = "SW1";
 			wakeup-source;
 		};
+
+		wakeup-key {
+			gpios = <&pfc 159 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_WAKEUP>;
+			label = "NMI";
+			wakeup-source;
+		};
 	};
 
 	sound {
@@ -329,41 +336,41 @@
 
 &pfc {
 	i2c3_pins: i2c3 {
-		renesas,groups = "i2c3_1";
-		renesas,function = "i2c3";
+		groups = "i2c3_1";
+		function = "i2c3";
 	};
 
 	mmcif_pins: mmc {
 		mux {
-			renesas,groups = "mmc0_data8_0", "mmc0_ctrl_0";
-			renesas,function = "mmc0";
+			groups = "mmc0_data8_0", "mmc0_ctrl_0";
+			function = "mmc0";
 		};
 		cfg {
-			renesas,groups = "mmc0_data8_0";
-			renesas,pins = "PORT279";
+			groups = "mmc0_data8_0";
+			pins = "PORT279";
 			bias-pull-up;
 		};
 	};
 
 	scifa4_pins: serial4 {
-		renesas,groups = "scifa4_data", "scifa4_ctrl";
-		renesas,function = "scifa4";
+		groups = "scifa4_data", "scifa4_ctrl";
+		function = "scifa4";
 	};
 
 	sdhi0_pins: sd0 {
-		renesas,groups = "sdhi0_data4", "sdhi0_ctrl", "sdhi0_cd", "sdhi0_wp";
-		renesas,function = "sdhi0";
+		groups = "sdhi0_data4", "sdhi0_ctrl", "sdhi0_cd", "sdhi0_wp";
+		function = "sdhi0";
 	};
 
 	sdhi2_pins: sd2 {
-		renesas,groups = "sdhi2_data4", "sdhi2_ctrl";
-		renesas,function = "sdhi2";
+		groups = "sdhi2_data4", "sdhi2_ctrl";
+		function = "sdhi2";
 	};
 
 	fsia_pins: sounda {
-		renesas,groups = "fsia_mclk_in", "fsia_sclk_in",
-				 "fsia_data_in", "fsia_data_out";
-		renesas,function = "fsia";
+		groups = "fsia_mclk_in", "fsia_sclk_in",
+			 "fsia_data_in", "fsia_data_out";
+		function = "fsia";
 	};
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/socfpga_arria10.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/socfpga_arria10.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/socfpga_arria10.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/socfpga_arria10.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -78,10 +78,13 @@
 					     <0 87 IRQ_TYPE_LEVEL_HIGH>,
 					     <0 88 IRQ_TYPE_LEVEL_HIGH>,
 					     <0 89 IRQ_TYPE_LEVEL_HIGH>,
-					     <0 90 IRQ_TYPE_LEVEL_HIGH>;
+					     <0 90 IRQ_TYPE_LEVEL_HIGH>,
+					     <0 91 IRQ_TYPE_LEVEL_HIGH>;
 				#dma-cells = <1>;
 				#dma-channels = <8>;
 				#dma-requests = <32>;
+				clocks = <&l4_main_clk>;
+				clock-names = "apb_pclk";
 			};
 		};
 
@@ -362,6 +365,7 @@
 						compatible = "altr,socfpga-a10-gate-clk";
 						clocks = <&sdmmc_free_clk>;
 						clk-gate = <0xC8 5>;
+						clk-phase = <0 135>;
 					};
 
 					qspi_clk: qspi_clk {
@@ -589,7 +593,7 @@
 			reg = <0xff808000 0x1000>;
 			interrupts = <0 98 IRQ_TYPE_LEVEL_HIGH>;
 			fifo-depth = <0x400>;
-			clocks = <&l4_mp_clk>, <&sdmmc_free_clk>;
+			clocks = <&l4_mp_clk>, <&sdmmc_clk>;
 			clock-names = "biu", "ciu";
 			status = "disabled";
 		};
@@ -599,6 +603,26 @@
 			reg = <0xffe00000 0x40000>;
 		};
 
+		eccmgr: eccmgr@ffd06000 {
+			compatible = "altr,socfpga-a10-ecc-manager";
+			altr,sysmgr-syscon = <&sysmgr>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			interrupts = <0 2 IRQ_TYPE_LEVEL_HIGH>,
+				     <0 0 IRQ_TYPE_LEVEL_HIGH>;
+			ranges;
+
+			l2-ecc@ffd06010 {
+				compatible = "altr,socfpga-a10-l2-ecc";
+				reg = <0xffd06010 0x4>;
+			};
+
+			ocram-ecc@ff8c3000 {
+				compatible = "altr,socfpga-a10-ocram-ecc";
+				reg = <0xff8c3000 0x400>;
+			};
+		};
+
 		rst: rstmgr@ffd05000 {
 			#reset-cells = <1>;
 			compatible = "altr,rst-mgr";
@@ -689,6 +713,8 @@
 			interrupts = <0 95 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&usb_clk>;
 			clock-names = "otg";
+			resets = <&rst USB0_RESET>;
+			reset-names = "dwc2";
 			phys = <&usbphy0>;
 			phy-names = "usb2-phy";
 			status = "disabled";
@@ -700,6 +726,8 @@
 			interrupts = <0 96 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&usb_clk>;
 			clock-names = "otg";
+			resets = <&rst USB1_RESET>;
+			reset-names = "dwc2";
 			phys = <&usbphy0>;
 			phy-names = "usb2-phy";
 			status = "disabled";
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/socfpga_arria10_socdk_sdmmc.dts linux-libre-4.7-gnu/arch/arm/boot/dts/socfpga_arria10_socdk_sdmmc.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/socfpga_arria10_socdk_sdmmc.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/socfpga_arria10_socdk_sdmmc.dts	2016-07-24 15:23:50.000000000 -0400
@@ -21,6 +21,7 @@
 &mmc {
 	status = "okay";
 	num-slots = <1>;
+	cap-sd-highspeed;
 	broken-cd;
 	bus-width = <4>;
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/socfpga_cyclone5.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/socfpga_cyclone5.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/socfpga_cyclone5.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/socfpga_cyclone5.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -38,12 +38,6 @@
 			cap-sd-highspeed;
 		};
 
-		ethernet@ff702000 {
-			phy-mode = "rgmii";
-			phy-addr = <0xffffffff>; /* probe for phy addr */
-			status = "okay";
-		};
-
 		sysmgr@ffd08000 {
 			cpu1-start-addr = <0xffd080c4>;
 		};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts linux-libre-4.7-gnu/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts	2016-07-24 15:23:50.000000000 -0400
@@ -39,6 +39,90 @@
 		ethernet0 = &gmac1;
 	};
 
+	leds {
+		compatible = "gpio-leds";
+
+		hps_led0 {
+			label = "hps:blue:led0";
+			gpios = <&portb 24 0>;	/* HPS_GPIO53 */
+			linux,default-trigger = "heartbeat";
+		};
+
+		hps_led1 {
+			label = "hps:blue:led1";
+			gpios = <&portb 25 0>;	/* HPS_GPIO54 */
+			linux,default-trigger = "heartbeat";
+		};
+
+		hps_led2 {
+			label = "hps:blue:led2";
+			gpios = <&portb 26 0>;	/* HPS_GPIO55 */
+			linux,default-trigger = "heartbeat";
+		};
+
+		hps_led3 {
+			label = "hps:blue:led3";
+			gpios = <&portb 27 0>;	/* HPS_GPIO56 */
+			linux,default-trigger = "heartbeat";
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		hps_sw0 {
+			label = "hps_sw0";
+			gpios = <&portc 20 0>;	/* HPS_GPI7 */
+			linux,input-type = <5>;	/* EV_SW */
+			linux,code = <0x0>;	/* SW_LID */
+		};
+
+		hps_sw1 {
+			label = "hps_sw1";
+			gpios = <&portc 19 0>;	/* HPS_GPI6 */
+			linux,input-type = <5>;	/* EV_SW */
+			linux,code = <0x5>;	/* SW_DOCK */
+		};
+
+		hps_sw2 {
+			label = "hps_sw2";
+			gpios = <&portc 18 0>;	/* HPS_GPI5 */
+			linux,input-type = <5>;	/* EV_SW */
+			linux,code = <0xa>;	/* SW_KEYPAD_SLIDE */
+		};
+
+		hps_sw3 {
+			label = "hps_sw3";
+			gpios = <&portc 17 0>;	/* HPS_GPI4 */
+			linux,input-type = <5>;	/* EV_SW */
+			linux,code = <0xc>;	/* SW_ROTATE_LOCK */
+		};
+
+		hps_hkey0 {
+			label = "hps_hkey0";
+			gpios = <&portc 21 1>;	/* HPS_GPI8 */
+			linux,code = <187>;	/* KEY_F17 */
+		};
+
+		hps_hkey1 {
+			label = "hps_hkey1";
+			gpios = <&portc 22 1>;	/* HPS_GPI9 */
+			linux,code = <188>;	/* KEY_F18 */
+		};
+
+		hps_hkey2 {
+			label = "hps_hkey2";
+			gpios = <&portc 23 1>;	/* HPS_GPI10 */
+			linux,code = <189>;	/* KEY_F19 */
+		};
+
+		hps_hkey3 {
+			label = "hps_hkey3";
+			gpios = <&portc 24 1>;	/* HPS_GPI11 */
+			linux,code = <190>;	/* KEY_F20 */
+		};
+	};
+
 	regulator_3_3v: vcc3p3-regulator {
 		compatible = "regulator-fixed";
 		regulator-name = "VCC3P3";
@@ -61,7 +145,15 @@
 	rxc-skew-ps = <2000>;
 };
 
-&gpio2 {
+&gpio0 {	/* GPIO 0..29 */
+	status = "okay";
+};
+
+&gpio1 {	/* GPIO 30..57 */
+	status = "okay";
+};
+
+&gpio2 {	/* GPIO 58..66 (HLGPI 0..13 at offset 13) */
 	status = "okay";
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/socfpga_cyclone5_socrates.dts linux-libre-4.7-gnu/arch/arm/boot/dts/socfpga_cyclone5_socrates.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/socfpga_cyclone5_socrates.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/socfpga_cyclone5_socrates.dts	2016-07-24 15:23:50.000000000 -0400
@@ -36,6 +36,7 @@
 };
 
 &gmac1 {
+	phy-mode = "rgmii";
 	status = "okay";
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts linux-libre-4.7-gnu/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,311 @@
+/*
+ *  Copyright (C) 2015 Marek Vasut <marex@denx.de>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
+ *     the License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this file; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "socfpga_cyclone5.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	model = "samtec VIN|ING FPGA";
+	compatible = "altr,socfpga-cyclone5", "altr,socfpga";
+
+	chosen {
+		bootargs = "console=ttyS0,115200";
+	};
+
+	memory {
+		name = "memory";
+		device_type = "memory";
+		reg = <0x0 0x40000000>; /* 1GB */
+	};
+
+	aliases {
+		/*
+		 * This allow the ethaddr uboot environment variable contents
+		 * to be added to the gmac1 device tree blob.
+		 */
+		ethernet0 = &gmac1;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		hps_led0 {
+			label = "hps:green:led0";	/* ALIVE_LED_GR */
+			gpios = <&portb 19 0>;	/* HPS_GPIO48 */
+			linux,default-trigger = "heartbeat";
+		};
+
+		hps_led1 {
+			label = "hps:red:led0";		/* ALIVE_LED_RD */
+			gpios = <&portb 24 0>;	/* HPS_GPIO53 */
+			linux,default-trigger = "none";
+		};
+
+		hps_led2 {
+			label = "hps:green:led1";	/* LINK2HOST_LED_GR */
+			gpios = <&portb 25 0>;	/* HPS_GPIO54 */
+			linux,default-trigger = "heartbeat";
+		};
+
+		hps_led3 {
+			label = "hps:red:led1";		/* LINK2HOST_LED_RD */
+			gpios = <&portc 7 0>;	/* HPS_GPIO65 */
+			linux,default-trigger = "none";
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		hps_temp0 {
+			label = "BTN_0";			/* TEMP_OS */
+			gpios = <&portc 18 GPIO_ACTIVE_LOW>;	/* HPS_GPIO60 */
+			linux,code = <BTN_0>;
+		};
+
+		hps_hkey0 {
+			label = "BTN_1";			/* DIS_PWR */
+			gpios = <&portc 19 GPIO_ACTIVE_LOW>;	/* HPS_GPIO61 */
+			linux,code = <BTN_1>;
+		};
+
+		hps_hkey1 {
+			label = "hps_hkey1";			/* POWER_DOWN */
+			gpios = <&portc 20 GPIO_ACTIVE_LOW>;	/* HPS_GPIO62 */
+			linux,code = <KEY_POWER>;
+		};
+	};
+
+	regulator-usb-nrst {
+		compatible = "regulator-fixed";
+		regulator-name = "usb_nrst";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&portb 5 GPIO_ACTIVE_HIGH>;
+		startup-delay-us = <70000>;
+		enable-active-high;
+		regulator-always-on;
+	};
+};
+
+&gmac1 {
+	status = "okay";
+	phy-mode = "rgmii";
+	phy-handle = <&phy1>;
+
+	snps,reset-gpio = <&porta 0 GPIO_ACTIVE_LOW>;
+	snps,reset-active-low;
+	snps,reset-delays-us = <10000 10000 10000>;
+
+	mdio0 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "snps,dwmac-mdio";
+		phy1: ethernet-phy@1 {
+			reg = <1>;
+			rxd0-skew-ps = <0>;
+			rxd1-skew-ps = <0>;
+			rxd2-skew-ps = <0>;
+			rxd3-skew-ps = <0>;
+			txen-skew-ps = <0>;
+			txc-skew-ps = <2600>;
+			rxdv-skew-ps = <0>;
+			rxc-skew-ps = <2000>;
+		};
+	};
+};
+
+&gpio0 {	/* GPIO 0..29 */
+	status = "okay";
+};
+
+&gpio1 {	/* GPIO 30..57 */
+	status = "okay";
+};
+
+&gpio2 {	/* GPIO 58..66 (HLGPI 0..13 at offset 13) */
+	status = "okay";
+};
+
+&i2c0 {
+	status = "okay";
+
+	gpio: pca9557@1f {
+		compatible = "nxp,pca9557";
+		reg = <0x1f>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	temp: lm75@48 {
+		compatible = "lm75";
+		reg = <0x48>;
+	};
+
+	at24@50 {
+		compatible = "at24,24c01";
+		pagesize = <8>;
+		reg = <0x50>;
+	};
+
+	i2cswitch@70 {
+		compatible = "nxp,pca9548";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x70>;
+
+		i2c@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+			eeprom@51 {
+				compatible = "at,24c01";
+				pagesize = <8>;
+				reg = <0x51>;
+			};
+		};
+
+		i2c@1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+			eeprom@51 {
+				compatible = "at,24c01";
+				pagesize = <8>;
+				reg = <0x51>;
+			};
+		};
+
+		i2c@2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+			eeprom@51 {
+				compatible = "at,24c01";
+				pagesize = <8>;
+				reg = <0x51>;
+			};
+		};
+
+		i2c@3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+			eeprom@51 {
+				compatible = "at,24c01";
+				pagesize = <8>;
+				reg = <0x51>;
+			};
+		};
+
+		i2c@4 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <4>;
+			eeprom@51 {
+				compatible = "at,24c01";
+				pagesize = <8>;
+				reg = <0x51>;
+			};
+		};
+
+		i2c@5 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <5>;
+			eeprom@51 {
+				compatible = "at,24c01";
+				pagesize = <8>;
+				reg = <0x51>;
+			};
+		};
+
+		i2c@6 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <6>;
+			eeprom@51 {
+				compatible = "at,24c01";
+				pagesize = <8>;
+				reg = <0x51>;
+			};
+		};
+
+		i2c@7 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <7>;
+			eeprom@51 {
+				compatible = "at,24c01";
+				pagesize = <8>;
+				reg = <0x51>;
+			};
+		};
+	};
+};
+
+&i2c1 {
+	status = "okay";
+	clock-frequency = <100000>;
+
+	at24@50 {
+		compatible = "at24,24c02";
+		pagesize = <8>;
+		reg = <0x50>;
+	};
+};
+
+&usb0 {
+	dr_mode = "host";
+	status = "okay";
+};
+
+&usb1 {
+	dr_mode = "peripheral";
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/socfpga.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/socfpga.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/socfpga.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/socfpga.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -831,6 +831,8 @@
 			interrupts = <0 125 4>;
 			clocks = <&usb_mp_clk>;
 			clock-names = "otg";
+			resets = <&rst USB0_RESET>;
+			reset-names = "dwc2";
 			phys = <&usbphy0>;
 			phy-names = "usb2-phy";
 			status = "disabled";
@@ -842,6 +844,8 @@
 			interrupts = <0 128 4>;
 			clocks = <&usb_mp_clk>;
 			clock-names = "otg";
+			resets = <&rst USB1_RESET>;
+			reset-names = "dwc2";
 			phys = <&usbphy0>;
 			phy-names = "usb2-phy";
 			status = "disabled";
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/spear13xx.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/spear13xx.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/spear13xx.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/spear13xx.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -117,7 +117,7 @@
 			chan_priority = <1>;
 			block_size = <0xfff>;
 			dma-masters = <2>;
-			data_width = <3 3>;
+			data-width = <8 8>;
 		};
 
 		dma@eb000000 {
@@ -133,7 +133,7 @@
 			chan_allocation_order = <1>;
 			chan_priority = <1>;
 			block_size = <0xfff>;
-			data_width = <3 3>;
+			data-width = <8 8>;
 		};
 
 		fsmc: flash@b0000000 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/ste-ccu9540.dts linux-libre-4.7-gnu/arch/arm/boot/dts/ste-ccu9540.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/ste-ccu9540.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/ste-ccu9540.dts	2016-07-24 15:23:50.000000000 -0400
@@ -49,7 +49,7 @@
 			cap-mmc-highspeed;
 			vmmc-supply = <&ab8500_ldo_aux3_reg>;
 
-			cd-gpios  = <&gpio7 6 0x4>; // 230
+			cd-gpios  = <&gpio7 6 GPIO_ACTIVE_HIGH>; // 230
 			cd-inverted;
 
 			status = "okay";
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/ste-dbx5x0.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/ste-dbx5x0.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/ste-dbx5x0.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/ste-dbx5x0.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -10,8 +10,10 @@
  */
 
 #include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/mfd/dbx500-prcmu.h>
 #include <dt-bindings/arm/ux500_pm_domains.h>
+#include <dt-bindings/gpio/gpio.h>
 #include "skeleton.dtsi"
 
 / {
@@ -203,14 +205,14 @@
 		L2: l2-cache {
 			compatible = "arm,pl310-cache";
 			reg = <0xa0412000 0x1000>;
-			interrupts = <0 13 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
 			cache-unified;
 			cache-level = <2>;
 		};
 
 		pmu {
 			compatible = "arm,cortex-a9-pmu";
-			interrupts = <0 7 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
 		pm_domains: pm_domains0 {
@@ -253,7 +255,7 @@
 			/* Nomadik System Timer */
 			compatible = "st,nomadik-mtu";
 			reg = <0xa03c6000 0x1000>;
-			interrupts = <0 4 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
 
 			clocks = <&prcmu_clk PRCMU_TIMCLK>, <&prcc_pclk 6 6>;
 			clock-names = "timclk", "apb_pclk";
@@ -262,7 +264,7 @@
 		timer@a0410600 {
 			compatible = "arm,cortex-a9-twd-timer";
 			reg = <0xa0410600 0x20>;
-			interrupts = <1 13 0x304>; /* IRQ level high per-CPU */
+			interrupts = <GIC_PPI 13 (GIC_CPU_MASK_RAW(3) | IRQ_TYPE_LEVEL_HIGH)>;
 
 			clocks = <&smp_twd_clk>;
 		};
@@ -270,14 +272,14 @@
 		watchdog@a0410620 {
 			compatible = "arm,cortex-a9-twd-wdt";
 			reg = <0xa0410620 0x20>;
-			interrupts = <1 14 0x304>;
+			interrupts = <GIC_PPI 14 (GIC_CPU_MASK_RAW(3) | IRQ_TYPE_LEVEL_HIGH)>;
 			clocks = <&smp_twd_clk>;
 		};
 
 		rtc@80154000 {
 			compatible = "arm,rtc-pl031", "arm,primecell";
 			reg = <0x80154000 0x1000>;
-			interrupts = <0 18 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
 
 			clocks = <&rtc_clk>;
 			clock-names = "apb_pclk";
@@ -287,7 +289,7 @@
 			compatible = "stericsson,db8500-gpio",
 				"st,nomadik-gpio";
 			reg =  <0x8012e000 0x80>;
-			interrupts = <0 119 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
 			interrupt-controller;
 			#interrupt-cells = <2>;
 			st,supports-sleepmode;
@@ -302,7 +304,7 @@
 			compatible = "stericsson,db8500-gpio",
 				"st,nomadik-gpio";
 			reg =  <0x8012e080 0x80>;
-			interrupts = <0 120 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
 			interrupt-controller;
 			#interrupt-cells = <2>;
 			st,supports-sleepmode;
@@ -317,7 +319,7 @@
 			compatible = "stericsson,db8500-gpio",
 				"st,nomadik-gpio";
 			reg =  <0x8000e000 0x80>;
-			interrupts = <0 121 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
 			interrupt-controller;
 			#interrupt-cells = <2>;
 			st,supports-sleepmode;
@@ -332,7 +334,7 @@
 			compatible = "stericsson,db8500-gpio",
 				"st,nomadik-gpio";
 			reg =  <0x8000e080 0x80>;
-			interrupts = <0 122 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
 			interrupt-controller;
 			#interrupt-cells = <2>;
 			st,supports-sleepmode;
@@ -347,7 +349,7 @@
 			compatible = "stericsson,db8500-gpio",
 				"st,nomadik-gpio";
 			reg =  <0x8000e100 0x80>;
-			interrupts = <0 123 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
 			interrupt-controller;
 			#interrupt-cells = <2>;
 			st,supports-sleepmode;
@@ -362,7 +364,7 @@
 			compatible = "stericsson,db8500-gpio",
 				"st,nomadik-gpio";
 			reg =  <0x8000e180 0x80>;
-			interrupts = <0 124 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>;
 			interrupt-controller;
 			#interrupt-cells = <2>;
 			st,supports-sleepmode;
@@ -377,7 +379,7 @@
 			compatible = "stericsson,db8500-gpio",
 				"st,nomadik-gpio";
 			reg =  <0x8011e000 0x80>;
-			interrupts = <0 125 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>;
 			interrupt-controller;
 			#interrupt-cells = <2>;
 			st,supports-sleepmode;
@@ -392,7 +394,7 @@
 			compatible = "stericsson,db8500-gpio",
 				"st,nomadik-gpio";
 			reg =  <0x8011e080 0x80>;
-			interrupts = <0 126 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
 			interrupt-controller;
 			#interrupt-cells = <2>;
 			st,supports-sleepmode;
@@ -407,7 +409,7 @@
 			compatible = "stericsson,db8500-gpio",
 				"st,nomadik-gpio";
 			reg =  <0xa03fe000 0x80>;
-			interrupts = <0 127 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
 			interrupt-controller;
 			#interrupt-cells = <2>;
 			st,supports-sleepmode;
@@ -429,7 +431,7 @@
 		usb_per5@a03e0000 {
 			compatible = "stericsson,db8500-musb";
 			reg = <0xa03e0000 0x10000>;
-			interrupts = <0 23 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
 			interrupt-names = "mc";
 
 			dr_mode = "otg";
@@ -467,7 +469,7 @@
 			compatible = "stericsson,db8500-dma40", "stericsson,dma40";
 			reg = <0x801C0000 0x1000 0x40010000 0x800>;
 			reg-names = "base", "lcpa";
-			interrupts = <0 25 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
 
 			#dma-cells = <3>;
 			memcpy-channels = <56 57 58 59 60>;
@@ -479,7 +481,7 @@
 			compatible = "stericsson,db8500-prcmu";
 			reg = <0x80157000 0x2000>, <0x801b0000 0x8000>, <0x801b8000 0x1000>;
 			reg-names = "prcmu", "prcmu-tcpm", "prcmu-tcdm";
-			interrupts = <0 47 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <1>;
 			interrupt-controller;
@@ -597,7 +599,7 @@
 			ab8500 {
 				compatible = "stericsson,ab8500";
 				interrupt-parent = <&intc>;
-				interrupts = <0 40 IRQ_TYPE_LEVEL_HIGH>;
+				interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
 				interrupt-controller;
 				#interrupt-cells = <2>;
 
@@ -785,7 +787,7 @@
 		i2c@80004000 {
 			compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";
 			reg = <0x80004000 0x1000>;
-			interrupts = <0 21 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
 
 			#address-cells = <1>;
 			#size-cells = <0>;
@@ -800,7 +802,7 @@
 		i2c@80122000 {
 			compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";
 			reg = <0x80122000 0x1000>;
-			interrupts = <0 22 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
 
 			#address-cells = <1>;
 			#size-cells = <0>;
@@ -816,7 +818,7 @@
 		i2c@80128000 {
 			compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";
 			reg = <0x80128000 0x1000>;
-			interrupts = <0 55 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
 
 			#address-cells = <1>;
 			#size-cells = <0>;
@@ -832,7 +834,7 @@
 		i2c@80110000 {
 			compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";
 			reg = <0x80110000 0x1000>;
-			interrupts = <0 12 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
 
 			#address-cells = <1>;
 			#size-cells = <0>;
@@ -848,7 +850,7 @@
 		i2c@8012a000 {
 			compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";
 			reg = <0x8012a000 0x1000>;
-			interrupts = <0 51 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
 
 			#address-cells = <1>;
 			#size-cells = <0>;
@@ -864,7 +866,7 @@
 		ssp@80002000 {
 			compatible = "arm,pl022", "arm,primecell";
 			reg = <0x80002000 0x1000>;
-			interrupts = <0 14 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			clocks = <&prcc_kclk 3 1>, <&prcc_pclk 3 1>;
@@ -878,7 +880,7 @@
 		ssp@80003000 {
 			compatible = "arm,pl022", "arm,primecell";
 			reg = <0x80003000 0x1000>;
-			interrupts = <0 52 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			clocks = <&prcc_kclk 3 2>, <&prcc_pclk 3 2>;
@@ -892,7 +894,7 @@
 		spi@8011a000 {
 			compatible = "arm,pl022", "arm,primecell";
 			reg = <0x8011a000 0x1000>;
-			interrupts = <0 8 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			/* Same clock wired to kernel and pclk */
@@ -907,7 +909,7 @@
 		spi@80112000 {
 			compatible = "arm,pl022", "arm,primecell";
 			reg = <0x80112000 0x1000>;
-			interrupts = <0 96 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			/* Same clock wired to kernel and pclk */
@@ -922,7 +924,7 @@
 		spi@80111000 {
 			compatible = "arm,pl022", "arm,primecell";
 			reg = <0x80111000 0x1000>;
-			interrupts = <0 6 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			/* Same clock wired to kernel and pclk */
@@ -937,7 +939,7 @@
 		spi@80129000 {
 			compatible = "arm,pl022", "arm,primecell";
 			reg = <0x80129000 0x1000>;
-			interrupts = <0 49 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			/* Same clock wired to kernel and pclk */
@@ -952,7 +954,7 @@
 		ux500_serial0: uart@80120000 {
 			compatible = "arm,pl011", "arm,primecell";
 			reg = <0x80120000 0x1000>;
-			interrupts = <0 11 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
 
 			dmas = <&dma 13 0 0x2>, /* Logical - DevToMem */
 			       <&dma 13 0 0x0>; /* Logical - MemToDev */
@@ -967,7 +969,7 @@
 		ux500_serial1: uart@80121000 {
 			compatible = "arm,pl011", "arm,primecell";
 			reg = <0x80121000 0x1000>;
-			interrupts = <0 19 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
 
 			dmas = <&dma 12 0 0x2>, /* Logical - DevToMem */
 			       <&dma 12 0 0x0>; /* Logical - MemToDev */
@@ -982,7 +984,7 @@
 		ux500_serial2: uart@80007000 {
 			compatible = "arm,pl011", "arm,primecell";
 			reg = <0x80007000 0x1000>;
-			interrupts = <0 26 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
 
 			dmas = <&dma 11 0 0x2>, /* Logical - DevToMem */
 			       <&dma 11 0 0x0>; /* Logical - MemToDev */
@@ -997,7 +999,7 @@
 		sdi0_per1@80126000 {
 			compatible = "arm,pl18x", "arm,primecell";
 			reg = <0x80126000 0x1000>;
-			interrupts = <0 60 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
 
 			dmas = <&dma 29 0 0x2>, /* Logical - DevToMem */
 			       <&dma 29 0 0x0>; /* Logical - MemToDev */
@@ -1013,7 +1015,7 @@
 		sdi1_per2@80118000 {
 			compatible = "arm,pl18x", "arm,primecell";
 			reg = <0x80118000 0x1000>;
-			interrupts = <0 50 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
 
 			dmas = <&dma 32 0 0x2>, /* Logical - DevToMem */
 			       <&dma 32 0 0x0>; /* Logical - MemToDev */
@@ -1029,7 +1031,7 @@
 		sdi2_per3@80005000 {
 			compatible = "arm,pl18x", "arm,primecell";
 			reg = <0x80005000 0x1000>;
-			interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
 
 			dmas = <&dma 28 0 0x2>, /* Logical - DevToMem */
 			       <&dma 28 0 0x0>; /* Logical - MemToDev */
@@ -1045,7 +1047,7 @@
 		sdi3_per2@80119000 {
 			compatible = "arm,pl18x", "arm,primecell";
 			reg = <0x80119000 0x1000>;
-			interrupts = <0 59 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
 
 			dmas = <&dma 41 0 0x2>, /* Logical - DevToMem */
 			       <&dma 41 0 0x0>; /* Logical - MemToDev */
@@ -1061,7 +1063,7 @@
 		sdi4_per2@80114000 {
 			compatible = "arm,pl18x", "arm,primecell";
 			reg = <0x80114000 0x1000>;
-			interrupts = <0 99 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>;
 
 			dmas = <&dma 42 0 0x2>, /* Logical - DevToMem */
 			       <&dma 42 0 0x0>; /* Logical - MemToDev */
@@ -1077,7 +1079,7 @@
 		sdi5_per3@80008000 {
 			compatible = "arm,pl18x", "arm,primecell";
 			reg = <0x80008000 0x1000>;
-			interrupts = <0 100 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
 
 			dmas = <&dma 43 0 0x2>, /* Logical - DevToMem */
 			       <&dma 43 0 0x0>; /* Logical - MemToDev */
@@ -1093,7 +1095,7 @@
 		msp0: msp@80123000 {
 			compatible = "stericsson,ux500-msp-i2s";
 			reg = <0x80123000 0x1000>;
-			interrupts = <0 31 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
 			v-ape-supply = <&db8500_vape_reg>;
 
 			dmas = <&dma 31 0 0x12>, /* Logical - DevToMem - HighPrio */
@@ -1109,7 +1111,7 @@
 		msp1: msp@80124000 {
 			compatible = "stericsson,ux500-msp-i2s";
 			reg = <0x80124000 0x1000>;
-			interrupts = <0 62 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
 			v-ape-supply = <&db8500_vape_reg>;
 
 			/* This DMA channel only exist on DB8500 v1 */
@@ -1126,7 +1128,7 @@
 		msp2: msp@80117000 {
 			compatible = "stericsson,ux500-msp-i2s";
 			reg = <0x80117000 0x1000>;
-			interrupts = <0 98 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
 			v-ape-supply = <&db8500_vape_reg>;
 
 			dmas = <&dma 14 0 0x12>, /* Logical  - DevToMem - HighPrio */
@@ -1143,7 +1145,7 @@
 		msp3: msp@80125000 {
 			compatible = "stericsson,ux500-msp-i2s";
 			reg = <0x80125000 0x1000>;
-			interrupts = <0 62 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
 			v-ape-supply = <&db8500_vape_reg>;
 
 			/* This DMA channel only exist on DB8500 v2 */
@@ -1176,7 +1178,7 @@
 			      <0xa0351000 0x1000>, /* DSI link 1 */
 			      <0xa0352000 0x1000>, /* DSI link 2 */
 			      <0xa0353000 0x1000>; /* DSI link 3 */
-			interrupts = <0 48 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&prcmu_clk PRCMU_MCDECLK>, /* Main MCDE clock */
 				 <&prcmu_clk PRCMU_LCDCLK>, /* LCD clock */
 				 <&prcmu_clk PRCMU_PLLDSI>, /* HDMI clock */
@@ -1190,7 +1192,7 @@
 		cryp@a03cb000 {
 			compatible = "stericsson,ux500-cryp";
 			reg = <0xa03cb000 0x1000>;
-			interrupts = <0 15 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
 
 			v-ape-supply = <&db8500_vape_reg>;
 			clocks = <&prcc_pclk 6 1>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/ste-hrefprev60.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/ste-hrefprev60.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/ste-hrefprev60.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/ste-hrefprev60.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -18,7 +18,7 @@
 / {
 	gpio_keys {
 		button@1 {
-			gpios = <&tc3589x_gpio 7 0x4>;
+			gpios = <&tc3589x_gpio 7 GPIO_ACTIVE_HIGH>;
 		};
 	};
 
@@ -68,12 +68,12 @@
 
 		// External Micro SD slot
 		sdi0_per1@80126000 {
-			cd-gpios  = <&tc3589x_gpio 3 0x4>;
+			cd-gpios  = <&tc3589x_gpio 3 GPIO_ACTIVE_HIGH>;
 		};
 
 		vmmci: regulator-gpio {
-			gpios = <&tc3589x_gpio 18 0x4>;
-			enable-gpio = <&tc3589x_gpio 17 0x4>;
+			gpios = <&tc3589x_gpio 18 GPIO_ACTIVE_HIGH>;
+			enable-gpio = <&tc3589x_gpio 17 GPIO_ACTIVE_HIGH>;
 		};
 
 		pinctrl {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/ste-href-stuib.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/ste-href-stuib.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/ste-href-stuib.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/ste-href-stuib.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -22,13 +22,13 @@
 
 		button@139 {
 			/* Proximity sensor */
-			gpios = <&gpio6 25 0x4>;
+			gpios = <&gpio6 25 GPIO_ACTIVE_HIGH>;
 			linux,code = <11>; /* SW_FRONT_PROXIMITY */
 			label = "SFH7741 Proximity Sensor";
 		};
 		button@145 {
 			/* Hall sensor */
-			gpios = <&gpio4 17 0x4>;
+			gpios = <&gpio4 17 GPIO_ACTIVE_HIGH>;
 			linux,code = <0>; /* SW_LID */
 			label = "HED54XXU11 Hall Effect Sensor";
 		};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/ste-href-tvk1281618.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/ste-href-tvk1281618.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/ste-href-tvk1281618.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/ste-href-tvk1281618.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -24,13 +24,13 @@
 
 		button@139 {
 			/* Proximity sensor */
-			gpios = <&gpio6 25 0x4>;
+			gpios = <&gpio6 25 GPIO_ACTIVE_HIGH>;
 			linux,code = <11>; /* SW_FRONT_PROXIMITY */
 			label = "SFH7741 Proximity Sensor";
 		};
 		button@145 {
 			/* Hall sensor */
-			gpios = <&gpio4 17 0x4>;
+			gpios = <&gpio4 17 GPIO_ACTIVE_HIGH>;
 			linux,code = <0>; /* SW_LID */
 			label = "HED54XXU11 Hall Effect Sensor";
 		};
@@ -93,14 +93,15 @@
 				/* Accelerometer */
 				compatible = "st,lsm303dlh-accel";
 				st,drdy-int-pin = <1>;
+				drive-open-drain;
 				reg = <0x18>;
 				vdd-supply = <&ab8500_ldo_aux1_reg>;
 				vddio-supply = <&db8500_vsmps2_reg>;
 				pinctrl-names = "default";
 				pinctrl-0 = <&accel_tvk_mode>;
 				interrupt-parent = <&gpio2>;
-				interrupts = <18 IRQ_TYPE_EDGE_RISING>,
-					     <19 IRQ_TYPE_EDGE_RISING>;
+				interrupts = <18 IRQ_TYPE_EDGE_FALLING>,
+					     <19 IRQ_TYPE_EDGE_FALLING>;
 			};
 			lsm303dlh@1e {
 				/*
@@ -118,14 +119,15 @@
 				/* Accelerometer */
 				compatible = "st,lis331dl-accel";
 				st,drdy-int-pin = <1>;
+				drive-open-drain;
 				reg = <0x1c>;
 				vdd-supply = <&ab8500_ldo_aux1_reg>;
 				vddio-supply = <&db8500_vsmps2_reg>;
 				pinctrl-names = "default";
 				pinctrl-0 = <&accel_tvk_mode>;
 				interrupt-parent = <&gpio2>;
-				interrupts = <18 IRQ_TYPE_EDGE_RISING>,
-					     <19 IRQ_TYPE_EDGE_RISING>;
+				interrupts = <18 IRQ_TYPE_EDGE_FALLING>,
+					     <19 IRQ_TYPE_EDGE_FALLING>;
 			};
 			ak8974@0f {
 				/* Magnetometer */
@@ -216,7 +218,7 @@
 					/* Accelerometer interrupt lines 1 & 2 */
 					tvk_cfg {
 						pins = "GPIO82_C1", "GPIO83_D3";
-						ste,config = <&gpio_in_pd>;
+						ste,config = <&gpio_in_pu>;
 					};
 				};
 			};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/ste-hrefv60plus.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/ste-hrefv60plus.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/ste-hrefv60plus.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/ste-hrefv60plus.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -20,12 +20,12 @@
 	soc {
 		// External Micro SD slot
 		sdi0_per1@80126000 {
-			cd-gpios  = <&gpio2 31 0x4>; // 95
+			cd-gpios  = <&gpio2 31 GPIO_ACTIVE_HIGH>; // 95
 		};
 
 		vmmci: regulator-gpio {
-			gpios = <&gpio0 5 0x4>;
-			enable-gpio = <&gpio5 9 0x4>;
+			gpios = <&gpio0 5 GPIO_ACTIVE_HIGH>;
+			enable-gpio = <&gpio5 9 GPIO_ACTIVE_HIGH>;
 		};
 
 		pinctrl {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/ste-nomadik-nhk15.dts linux-libre-4.7-gnu/arch/arm/boot/dts/ste-nomadik-nhk15.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/ste-nomadik-nhk15.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/ste-nomadik-nhk15.dts	2016-07-24 15:23:50.000000000 -0400
@@ -57,8 +57,15 @@
 				};
 			};
 		};
+		lis3lv02dl {
+			lis3lv02dl_nhk_mode: lis3lv02dl_nhk {
+				nhk_cfg1 {
+					pins = "GPIO82_C10"; // IRQ line
+					ste,input = <0>;
+				};
+			};
+		};
 	};
-
 	src@101e0000 {
 		/* These chrystal outputs are not used on this board */
 		disable-sxtalo;
@@ -86,6 +93,10 @@
 		lis3lv02dl@1d {
 			/* Accelerometer */
 			compatible = "st,lis3lv02dl-accel";
+			interrupt-parent = <&gpio2>;
+			interrupts = <18 IRQ_TYPE_EDGE_RISING>; // GPIO 82
+			pinctrl-0 = <&lis3lv02dl_nhk_mode>;
+			pinctrl-names = "default";
 			reg = <0x1d>;
 		};
 		stmpe0: stmpe2401@43 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/ste-nomadik-stn8815.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/ste-nomadik-stn8815.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/ste-nomadik-stn8815.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/ste-nomadik-stn8815.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -748,6 +748,9 @@
 			clocks = <&uart0clk>, <&pclkuart0>;
 			clock-names = "uartclk", "apb_pclk";
 			status = "disabled";
+			dmas = <&dmac0 14 1>,
+			       <&dmac0 15 1>;
+			dma-names = "rx", "tx";
 		};
 
 		uart1: uart@101fb000 {
@@ -759,6 +762,9 @@
 			clock-names = "uartclk", "apb_pclk";
 			pinctrl-names = "default";
 			pinctrl-0 = <&uart1_default_mux>;
+			dmas = <&dmac1 22 1>,
+			       <&dmac1 23 1>;
+			dma-names = "rx", "tx";
 		};
 
 		uart2: uart@101f2000 {
@@ -769,6 +775,9 @@
 			clocks = <&uart2clk>, <&pclkuart2>;
 			clock-names = "uartclk", "apb_pclk";
 			status = "disabled";
+			dmas = <&dmac1 30 1>,
+			       <&dmac1 31 1>;
+			dma-names = "rx", "tx";
 		};
 
 		rng: rng@101b0000 {
@@ -813,5 +822,34 @@
 			pinctrl-0 = <&mmcsd_default_mux>, <&mmcsd_default_mode>;
 			vmmc-supply = <&vmmc_regulator>;
 		};
+
+		dmac0: dma-controller@10130000 {
+			compatible = "arm,pl080", "arm,primecell";
+			reg = <0x10130000 0x1000>;
+			interrupt-parent = <&vica>;
+			interrupts = <15>;
+			clocks = <&hclkdma0>;
+			clock-names = "apb_pclk";
+			lli-bus-interface-ahb1;
+			lli-bus-interface-ahb2;
+			mem-bus-interface-ahb2;
+			memcpy-burst-size = <256>;
+			memcpy-bus-width = <32>;
+			#dma-cells = <2>;
+		};
+		dmac1: dma-controller@10150000 {
+			compatible = "arm,pl080", "arm,primecell";
+			reg = <0x10150000 0x1000>;
+			interrupt-parent = <&vica>;
+			interrupts = <13>;
+			clocks = <&hclkdma1>;
+			clock-names = "apb_pclk";
+			lli-bus-interface-ahb1;
+			lli-bus-interface-ahb2;
+			mem-bus-interface-ahb2;
+			memcpy-burst-size = <256>;
+			memcpy-bus-width = <32>;
+			#dma-cells = <2>;
+		};
 	};
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/ste-snowball.dts linux-libre-4.7-gnu/arch/arm/boot/dts/ste-snowball.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/ste-snowball.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/ste-snowball.dts	2016-07-24 15:23:50.000000000 -0400
@@ -50,35 +50,35 @@
 			wakeup-source;
 			linux,code = <2>;
 			label = "userpb";
-			gpios = <&gpio1 0 0x4>;
+			gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>;
 		};
 		button@2 {
 			debounce_interval = <50>;
 			wakeup-source;
 			linux,code = <3>;
 			label = "extkb1";
-			gpios = <&gpio4 23 0x4>;
+			gpios = <&gpio4 23 GPIO_ACTIVE_HIGH>;
 		};
 		button@3 {
 			debounce_interval = <50>;
 			wakeup-source;
 			linux,code = <4>;
 			label = "extkb2";
-			gpios = <&gpio4 24 0x4>;
+			gpios = <&gpio4 24 GPIO_ACTIVE_HIGH>;
 		};
 		button@4 {
 			debounce_interval = <50>;
 			wakeup-source;
 			linux,code = <5>;
 			label = "extkb3";
-			gpios = <&gpio5 1 0x4>;
+			gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>;
 		};
 		button@5 {
 			debounce_interval = <50>;
 			wakeup-source;
 			linux,code = <6>;
 			label = "extkb4";
-			gpios = <&gpio5 2 0x4>;
+			gpios = <&gpio5 2 GPIO_ACTIVE_HIGH>;
 		};
 	};
 
@@ -88,7 +88,7 @@
 		pinctrl-0 = <&gpioled_snowball_mode>;
 		used-led {
 			label = "user_led";
-			gpios = <&gpio4 14 0x4>;
+			gpios = <&gpio4 14 GPIO_ACTIVE_HIGH>;
 			default-state = "on";
 			linux,default-trigger = "heartbeat";
 		};
@@ -155,8 +155,8 @@
 		vmmci: regulator-gpio {
 			compatible = "regulator-gpio";
 
-			gpios = <&gpio7 4 0x4>;
-			enable-gpio = <&gpio6 25 0x4>;
+			gpios = <&gpio7 4 GPIO_ACTIVE_HIGH>;
+			enable-gpio = <&gpio6 25 GPIO_ACTIVE_HIGH>;
 
 			regulator-min-microvolt = <1800000>;
 			regulator-max-microvolt = <2900000>;
@@ -182,8 +182,7 @@
 			pinctrl-0 = <&sdi0_default_mode>;
 			pinctrl-1 = <&sdi0_sleep_mode>;
 
-			cd-gpios  = <&gpio6 26 0x4>; // 218
-			cd-inverted;
+			cd-gpios  = <&gpio6 26 GPIO_ACTIVE_LOW>; // 218
 
 			status = "okay";
 		};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/stih407-family.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/stih407-family.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/stih407-family.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/stih407-family.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -15,6 +15,39 @@
 	#address-cells = <1>;
 	#size-cells = <1>;
 
+	reserved-memory {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		gp0_reserved: rproc@40000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x40000000 0x01000000>;
+			no-map;
+			status = "disabled";
+		};
+
+		gp1_reserved: rproc@41000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x41000000 0x01000000>;
+			no-map;
+			status = "disabled";
+		};
+
+		audio_reserved: rproc@42000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x42000000 0x01000000>;
+			no-map;
+			status = "disabled";
+		};
+
+		dmu_reserved: rproc@43000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x43000000 0x01000000>;
+			no-map;
+		};
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -22,15 +55,35 @@
 			device_type = "cpu";
 			compatible = "arm,cortex-a9";
 			reg = <0>;
+
 			/* u-boot puts hpen in SBC dmem at 0xa4 offset */
 			cpu-release-addr = <0x94100A4>;
+
+					 /* kHz     uV   */
+			operating-points = <1500000 0
+					    1200000 0
+					    800000  0
+					    500000  0>;
+
+			clocks = <&clk_m_a9>;
+			clock-names = "cpu";
+			clock-latency = <100000>;
+			cpu0-supply = <&pwm_regulator>;
+			st,syscfg = <&syscfg_core 0x8e0>;
 		};
 		cpu@1 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a9";
 			reg = <1>;
+
 			/* u-boot puts hpen in SBC dmem at 0xa4 offset */
 			cpu-release-addr = <0x94100A4>;
+
+					 /* kHz     uV   */
+			operating-points = <1500000 0
+					    1200000 0
+					    800000  0
+					    500000  0>;
 		};
 	};
 
@@ -534,7 +587,7 @@
 			reg = <0x8788000 0x1000>;
 			interrupts = <GIC_SPI 130 IRQ_TYPE_EDGE_RISING>;
 			clocks = <&clk_s_d3_flexgen CLK_LPC_1>;
-			st,lpc-mode = <ST_LPC_MODE_RTC>;
+			st,lpc-mode = <ST_LPC_MODE_CLKSRC>;
 		};
 
 		sata0: sata@9b20000 {
@@ -694,5 +747,79 @@
 			clocks          = <&clk_sysin>;
 			status		= "okay";
 		};
+
+		mailbox0: mailbox@8f00000  {
+			compatible	= "st,stih407-mailbox";
+			reg		= <0x8f00000 0x1000>;
+			interrupts	= <GIC_SPI 1 IRQ_TYPE_NONE>;
+			#mbox-cells	= <2>;
+			mbox-name	= "a9";
+			status		= "okay";
+		};
+
+		mailbox1: mailbox@8f01000 {
+			compatible	= "st,stih407-mailbox";
+			reg		= <0x8f01000 0x1000>;
+			#mbox-cells	= <2>;
+			mbox-name	= "st231_gp_1";
+			status		= "okay";
+		};
+
+		mailbox2: mailbox@8f02000 {
+			compatible	= "st,stih407-mailbox";
+			reg		= <0x8f02000 0x1000>;
+			#mbox-cells	= <2>;
+			mbox-name	= "st231_gp_0";
+			status		= "okay";
+		};
+
+		mailbox3: mailbox@8f03000 {
+			compatible	= "st,stih407-mailbox";
+			reg		= <0x8f03000 0x1000>;
+			#mbox-cells	= <2>;
+			mbox-name	= "st231_audio_video";
+			status		= "okay";
+		};
+
+		st231_gp0: remote-processor {
+			compatible	= "st,st231-rproc";
+			memory-region	= <&gp0_reserved>;
+			resets		= <&softreset STIH407_ST231_GP0_SOFTRESET>;
+			reset-names	= "sw_reset";
+			clocks		= <&clk_s_c0_flexgen CLK_ST231_GP_0>;
+			clock-frequency	= <600000000>;
+			st,syscfg	= <&syscfg_core 0x22c>;
+		};
+
+
+		st231_gp1: remote-processor {
+			compatible	= "st,st231-rproc";
+			memory-region	= <&gp1_reserved>;
+			resets		= <&softreset STIH407_ST231_GP1_SOFTRESET>;
+			reset-names	= "sw_reset";
+			clocks		= <&clk_s_c0_flexgen CLK_ST231_GP_1>;
+			clock-frequency = <600000000>;
+			st,syscfg	= <&syscfg_core 0x220>;
+		};
+
+		st231_audio: remote-processor {
+			compatible	= "st,st231-rproc";
+			memory-region	= <&audio_reserved>;
+			resets		= <&softreset STIH407_ST231_AUD_SOFTRESET>;
+			reset-names	= "sw_reset";
+			clocks		= <&clk_s_c0_flexgen CLK_ST231_AUD_0>;
+			clock-frequency	= <600000000>;
+			st,syscfg	= <&syscfg_core 0x228>;
+		};
+
+		st231_dmu: remote-processor {
+			compatible	= "st,st231-rproc";
+			memory-region	= <&dmu_reserved>;
+			resets		= <&softreset STIH407_ST231_DMU_SOFTRESET>;
+			reset-names	= "sw_reset";
+			clocks		= <&clk_s_c0_flexgen CLK_ST231_DMU>;
+			clock-frequency	= <600000000>;
+			st,syscfg	= <&syscfg_core 0x224>;
+		};
 	};
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/sun4i-a10-a1000.dts linux-libre-4.7-gnu/arch/arm/boot/dts/sun4i-a10-a1000.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/sun4i-a10-a1000.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/sun4i-a10-a1000.dts	2016-07-24 15:23:50.000000000 -0400
@@ -87,6 +87,24 @@
 		enable-active-high;
 		gpio = <&pio 7 15 GPIO_ACTIVE_HIGH>;
 	};
+
+	sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,name = "On-board SPDIF";
+
+		simple-audio-card,cpu {
+			sound-dai = <&spdif>;
+		};
+
+		simple-audio-card,codec {
+			sound-dai = <&spdif_out>;
+		};
+	};
+
+	spdif_out: spdif-out {
+		#sound-dai-cells = <0>;
+		compatible = "linux,spdif-dit";
+	};
 };
 
 &ahci {
@@ -188,6 +206,12 @@
 	status = "okay";
 };
 
+&spdif {
+	pinctrl-names = "default";
+	pinctrl-0 = <&spdif_tx_pins_a>;
+	status = "okay";
+};
+
 &uart0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart0_pins_a>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/sun4i-a10-dserve-dsrv9703c.dts linux-libre-4.7-gnu/arch/arm/boot/dts/sun4i-a10-dserve-dsrv9703c.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/sun4i-a10-dserve-dsrv9703c.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/sun4i-a10-dserve-dsrv9703c.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,281 @@
+/*
+ * Copyright 2016 Hans de Goede <hdegoede@redhat.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "sun4i-a10.dtsi"
+#include "sunxi-common-regulators.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/pinctrl/sun4i-a10.h>
+#include <dt-bindings/pwm/pwm.h>
+
+/ {
+	model = "Dserve DSRV9703C";
+	compatible = "dserve,dsrv9703c", "allwinner,sun4i-a10";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	backlight: backlight {
+		compatible = "pwm-backlight";
+		pinctrl-names = "default";
+		pinctrl-0 = <&bl_en_pin_dsrv9703c>;
+		pwms = <&pwm 0 50000 PWM_POLARITY_INVERTED>;
+		brightness-levels = <0 10 20 30 40 50 60 70 80 90 100>;
+		default-brightness-level = <8>;
+		enable-gpios = <&pio 7 7 GPIO_ACTIVE_HIGH>; /* PH7 */
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	haptics {
+		compatible = "regulator-haptic";
+		haptic-supply = <&reg_motor>;
+		min-microvolt = <3000000>;
+		max-microvolt = <3000000>;
+	};
+
+	reg_motor: reg_motor {
+		compatible = "regulator-fixed";
+		pinctrl-names = "default";
+		pinctrl-0 = <&motor_pins>;
+		regulator-name = "vcc-motor";
+		regulator-min-microvolt = <3000000>;
+		regulator-max-microvolt = <3000000>;
+		enable-active-high;
+		gpio = <&pio 1 3 GPIO_ACTIVE_HIGH>; /* PB3 */
+	};
+};
+
+&codec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&codec_pa_pin>;
+	allwinner,pa-gpios = <&pio 7 15 GPIO_ACTIVE_HIGH>; /* PH15 */
+	status = "okay";
+};
+
+&cpu0 {
+	cpu-supply = <&reg_dcdc2>;
+};
+
+&ehci1 {
+	status = "okay";
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins_a>;
+	status = "okay";
+
+	axp209: pmic@34 {
+		reg = <0x34>;
+		interrupts = <0>;
+	};
+};
+
+#include "axp209.dtsi"
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins_a>;
+	/* pull-ups and devices require AXP209 LDO3 */
+	status = "failed";
+};
+
+&i2c2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c2_pins_a>;
+	status = "okay";
+
+	ft5406ee8: touchscreen@38 {
+		compatible = "edt,edt-ft5406";
+		reg = <0x38>;
+		interrupt-parent = <&pio>;
+		interrupts = <7 21 IRQ_TYPE_EDGE_FALLING>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&touchscreen_pins>;
+		reset-gpios = <&pio 1 13 GPIO_ACTIVE_LOW>;
+		touchscreen-size-x = <1024>;
+		touchscreen-size-y = <768>;
+	};
+};
+
+&lradc {
+	vref-supply = <&reg_ldo2>;
+	status = "okay";
+
+	button@400 {
+		label = "Volume Down";
+		linux,code = <KEY_VOLUMEDOWN>;
+		channel = <0>;
+		voltage = <400000>;
+	};
+
+	button@800 {
+		label = "Volume Up";
+		linux,code = <KEY_VOLUMEUP>;
+		channel = <0>;
+		voltage = <800000>;
+	};
+};
+
+&mmc0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_reference_design>;
+	vmmc-supply = <&reg_vcc3v3>;
+	bus-width = <4>;
+	cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */
+	cd-inverted;
+	status = "okay";
+};
+
+&otg_sram {
+	status = "okay";
+};
+
+&pio {
+	bl_en_pin_dsrv9703c: bl_en_pin@0 {
+		allwinner,pins = "PH7";
+		allwinner,function = "gpio_out";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+
+	codec_pa_pin: codec_pa_pin@0 {
+		allwinner,pins = "PH15";
+		allwinner,function = "gpio_out";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+
+	motor_pins: motor_pins@0 {
+		allwinner,pins = "PB3";
+		allwinner,function = "gpio_out";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+
+	touchscreen_pins: touchscreen_pins@0 {
+		allwinner,pins = "PB13";
+		allwinner,function = "gpio_out";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+
+	usb0_id_detect_pin: usb0_id_detect_pin@0 {
+		allwinner,pins = "PH4";
+		allwinner,function = "gpio_in";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
+	};
+
+	usb0_vbus_detect_pin: usb0_vbus_detect_pin@0 {
+		allwinner,pins = "PH5";
+		allwinner,function = "gpio_in";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_PULL_DOWN>;
+	};
+};
+
+&pwm {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pwm0_pins_a>;
+	status = "okay";
+};
+
+&reg_dcdc2 {
+	regulator-always-on;
+	regulator-min-microvolt = <1000000>;
+	regulator-max-microvolt = <1400000>;
+	regulator-name = "vdd-cpu";
+};
+
+&reg_dcdc3 {
+	regulator-always-on;
+	regulator-min-microvolt = <1250000>;
+	regulator-max-microvolt = <1250000>;
+	regulator-name = "vdd-int-dll";
+};
+
+&reg_ldo1 {
+	regulator-name = "vdd-rtc";
+};
+
+&reg_ldo2 {
+	regulator-always-on;
+	regulator-min-microvolt = <3000000>;
+	regulator-max-microvolt = <3000000>;
+	regulator-name = "avcc";
+};
+
+&reg_usb0_vbus {
+	status = "okay";
+};
+
+&reg_usb2_vbus {
+	status = "okay";
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins_a>;
+	status = "okay";
+};
+
+&usb_otg {
+	dr_mode = "otg";
+	status = "okay";
+};
+
+&usbphy {
+	pinctrl-names = "default";
+	pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>;
+	usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */
+	usb0_vbus_det-gpio = <&pio 7 5 GPIO_ACTIVE_HIGH>; /* PH5 */
+	usb0_vbus-supply = <&reg_usb0_vbus>;
+	usb2_vbus-supply = <&reg_usb2_vbus>;
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/sun4i-a10.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/sun4i-a10.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/sun4i-a10.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/sun4i-a10.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -65,8 +65,9 @@
 			compatible = "allwinner,simple-framebuffer",
 				     "simple-framebuffer";
 			allwinner,pipeline = "de_be0-lcd0-hdmi";
-			clocks = <&pll5 1>, <&ahb_gates 36>, <&ahb_gates 43>,
-				 <&ahb_gates 44>, <&dram_gates 26>;
+			clocks = <&pll3>, <&pll5 1>, <&ahb_gates 36>,
+				 <&ahb_gates 43>, <&ahb_gates 44>,
+				 <&dram_gates 26>;
 			status = "disabled";
 		};
 
@@ -74,8 +75,9 @@
 			compatible = "allwinner,simple-framebuffer",
 				     "simple-framebuffer";
 			allwinner,pipeline = "de_fe0-de_be0-lcd0-hdmi";
-			clocks = <&pll5 1>, <&ahb_gates 36>, <&ahb_gates 43>,
-				 <&ahb_gates 44>, <&ahb_gates 46>,
+			clocks = <&pll3>, <&pll5 1>, <&ahb_gates 36>,
+				 <&ahb_gates 43>, <&ahb_gates 44>,
+				 <&ahb_gates 46>,
 				 <&dram_gates 25>, <&dram_gates 26>;
 			status = "disabled";
 		};
@@ -84,9 +86,9 @@
 			compatible = "allwinner,simple-framebuffer",
 				     "simple-framebuffer";
 			allwinner,pipeline = "de_fe0-de_be0-lcd0";
-			clocks = <&pll5 1>, <&ahb_gates 36>, <&ahb_gates 44>,
-				 <&ahb_gates 46>, <&dram_gates 25>,
-				 <&dram_gates 26>;
+			clocks = <&pll3>, <&pll5 1>, <&ahb_gates 36>,
+				 <&ahb_gates 44>, <&ahb_gates 46>,
+				 <&dram_gates 25>, <&dram_gates 26>;
 			status = "disabled";
 		};
 
@@ -94,9 +96,10 @@
 			compatible = "allwinner,simple-framebuffer",
 				     "simple-framebuffer";
 			allwinner,pipeline = "de_fe0-de_be0-lcd0-tve0";
-			clocks = <&pll5 1>, <&ahb_gates 34>, <&ahb_gates 36>,
-				 <&ahb_gates 44>, <&ahb_gates 46>,
-				 <&dram_gates 25>, <&dram_gates 26>;
+			clocks = <&pll3>, <&pll5 1>, <&ahb_gates 34>,
+				 <&ahb_gates 36>, <&ahb_gates 44>,
+				 <&ahb_gates 46>,
+				 <&dram_gates 5>, <&dram_gates 25>, <&dram_gates 26>;
 			status = "disabled";
 		};
 	};
@@ -184,6 +187,15 @@
 			clock-output-names = "osc24M";
 		};
 
+		osc3M: osc3M_clk {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clock-div = <8>;
+			clock-mult = <1>;
+			clocks = <&osc24M>;
+			clock-output-names = "osc3M";
+		};
+
 		osc32k: clk@0 {
 			#clock-cells = <0>;
 			compatible = "fixed-clock";
@@ -208,6 +220,23 @@
 					     "pll2-4x", "pll2-8x";
 		};
 
+		pll3: clk@01c20010 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-pll3-clk";
+			reg = <0x01c20010 0x4>;
+			clocks = <&osc3M>;
+			clock-output-names = "pll3";
+		};
+
+		pll3x2: pll3x2_clk {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clock-div = <1>;
+			clock-mult = <2>;
+			clocks = <&pll3>;
+			clock-output-names = "pll3-2x";
+		};
+
 		pll4: clk@01c20018 {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-pll1-clk";
@@ -232,6 +261,23 @@
 			clock-output-names = "pll6_sata", "pll6_other", "pll6";
 		};
 
+		pll7: clk@01c20030 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-pll3-clk";
+			reg = <0x01c20030 0x4>;
+			clocks = <&osc3M>;
+			clock-output-names = "pll7";
+		};
+
+		pll7x2: pll7x2_clk {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clock-div = <1>;
+			clock-mult = <2>;
+			clocks = <&pll7>;
+			clock-output-names = "pll7-2x";
+		};
+
 		/* dummy is 200M */
 		cpu: cpu@01c20054 {
 			#clock-cells = <0>;
@@ -477,6 +523,17 @@
 			clock-output-names = "ir1";
 		};
 
+		spdif_clk: clk@01c200c0 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mod1-clk";
+			reg = <0x01c200c0 0x4>;
+			clocks = <&pll2 SUN4I_A10_PLL2_8X>,
+				 <&pll2 SUN4I_A10_PLL2_4X>,
+				 <&pll2 SUN4I_A10_PLL2_2X>,
+				 <&pll2 SUN4I_A10_PLL2_1X>;
+			clock-output-names = "spdif";
+		};
+
 		usb_clk: clk@01c200cc {
 			#clock-cells = <1>;
 			#reset-cells = <1>;
@@ -1006,6 +1063,13 @@
 				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
 				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
 			};
+
+			spdif_tx_pins_a: spdif@0 {
+				allwinner,pins = "PB13";
+				allwinner,function = "spdif";
+				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+				allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
+			};
 		};
 
 		timer@01c20c00 {
@@ -1034,6 +1098,19 @@
 			status = "disabled";
 		};
 
+		spdif: spdif@01c21000 {
+			#sound-dai-cells = <0>;
+			compatible = "allwinner,sun4i-a10-spdif";
+			reg = <0x01c21000 0x400>;
+			interrupts = <13>;
+			clocks = <&apb0_gates 1>, <&spdif_clk>;
+			clock-names = "apb", "spdif";
+			dmas = <&dma SUN4I_DMA_NORMAL 2>,
+			       <&dma SUN4I_DMA_NORMAL 2>;
+			dma-names = "rx", "tx";
+			status = "disabled";
+		};
+
 		ir0: ir@01c21800 {
 			compatible = "allwinner,sun4i-a10-ir";
 			clocks = <&apb0_gates 6>, <&ir0_clk>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/sun5i-a10s.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/sun5i-a10s.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/sun5i-a10s.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/sun5i-a10s.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -65,8 +65,8 @@
 			compatible = "allwinner,simple-framebuffer",
 				     "simple-framebuffer";
 			allwinner,pipeline = "de_be0-lcd0-hdmi";
-			clocks = <&pll5 1>, <&ahb_gates 36>, <&ahb_gates 43>,
-				 <&ahb_gates 44>;
+			clocks = <&pll3>, <&pll5 1>, <&ahb_gates 36>,
+				 <&ahb_gates 43>, <&ahb_gates 44>;
 			status = "disabled";
 		};
 
@@ -74,7 +74,8 @@
 			compatible = "allwinner,simple-framebuffer",
 				     "simple-framebuffer";
 			allwinner,pipeline = "de_be0-lcd0";
-			clocks = <&pll5 1>, <&ahb_gates 36>, <&ahb_gates 44>;
+			clocks = <&pll3>, <&pll5 1>, <&ahb_gates 36>,
+				 <&ahb_gates 44>;
 			status = "disabled";
 		};
 
@@ -82,8 +83,8 @@
 			compatible = "allwinner,simple-framebuffer",
 				     "simple-framebuffer";
 			allwinner,pipeline = "de_be0-lcd0-tve0";
-			clocks = <&pll5 1>, <&ahb_gates 34>, <&ahb_gates 36>,
-				 <&ahb_gates 44>;
+			clocks = <&pll3>, <&pll5 1>, <&ahb_gates 34>,
+				 <&ahb_gates 36>, <&ahb_gates 44>;
 			status = "disabled";
 		};
 	};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/sun5i-a13-difrnce-dit4350.dts linux-libre-4.7-gnu/arch/arm/boot/dts/sun5i-a13-difrnce-dit4350.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/sun5i-a13-difrnce-dit4350.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/sun5i-a13-difrnce-dit4350.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,226 @@
+/*
+ * Copyright 2016 Hans de Goede <hdegoede@redhat.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "sun5i-a13.dtsi"
+#include "sunxi-common-regulators.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/pinctrl/sun4i-a10.h>
+#include <dt-bindings/pwm/pwm.h>
+
+/ {
+	model = "Difrnce DIT4350";
+	compatible = "difrnce,dit4350", "allwinner,sun5i-a13";
+
+	aliases {
+		serial0 = &uart1;
+	};
+
+	backlight: backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm 0 50000 PWM_POLARITY_INVERTED>;
+		brightness-levels = <0 10 20 30 40 50 60 70 80 90 100>;
+		default-brightness-level = <8>;
+		/* TODO: backlight uses axp gpio1 as enable pin */
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&cpu0 {
+	cpu-supply = <&reg_dcdc2>;
+};
+
+&ehci0 {
+	status = "okay";
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins_a>;
+	status = "okay";
+
+	axp209: pmic@34 {
+		reg = <0x34>;
+		interrupts = <0>;
+	};
+};
+
+#include "axp209.dtsi"
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins_a>;
+	status = "okay";
+
+	pcf8563: rtc@51 {
+		compatible = "nxp,pcf8563";
+		reg = <0x51>;
+	};
+};
+
+&lradc {
+	vref-supply = <&reg_ldo2>;
+	status = "okay";
+
+	button@200 {
+		label = "Volume Up";
+		linux,code = <KEY_VOLUMEUP>;
+		channel = <0>;
+		voltage = <200000>;
+	};
+
+	button@400 {
+		label = "Volume Down";
+		linux,code = <KEY_VOLUMEDOWN>;
+		channel = <0>;
+		voltage = <400000>;
+	};
+};
+
+&mmc0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_d709>;
+	vmmc-supply = <&reg_vcc3v3>;
+	bus-width = <4>;
+	cd-gpios = <&pio 6 0 GPIO_ACTIVE_HIGH>; /* PG0 */
+	cd-inverted;
+	status = "okay";
+};
+
+&otg_sram {
+	status = "okay";
+};
+
+&pio {
+	mmc0_cd_pin_d709: mmc0_cd_pin@0 {
+		allwinner,pins = "PG0";
+		allwinner,function = "gpio_in";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
+	};
+
+	usb0_vbus_detect_pin: usb0_vbus_detect_pin@0 {
+		allwinner,pins = "PG1";
+		allwinner,function = "gpio_in";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_PULL_DOWN>;
+	};
+
+	usb0_id_detect_pin: usb0_id_detect_pin@0 {
+		allwinner,pins = "PG2";
+		allwinner,function = "gpio_in";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
+	};
+};
+
+&pwm {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pwm0_pins>;
+	status = "okay";
+};
+
+&reg_dcdc2 {
+	regulator-always-on;
+	regulator-min-microvolt = <1000000>;
+	regulator-max-microvolt = <1400000>;
+	regulator-name = "vdd-cpu";
+};
+
+&reg_dcdc3 {
+	regulator-always-on;
+	regulator-min-microvolt = <1250000>;
+	regulator-max-microvolt = <1250000>;
+	regulator-name = "vdd-int-pll";
+};
+
+&reg_ldo1 {
+	regulator-name = "vdd-rtc";
+};
+
+&reg_ldo2 {
+	regulator-always-on;
+	regulator-min-microvolt = <3000000>;
+	regulator-max-microvolt = <3000000>;
+	regulator-name = "avcc";
+};
+
+&reg_ldo3 {
+	regulator-min-microvolt = <3300000>;
+	regulator-max-microvolt = <3300000>;
+	regulator-name = "vcc-wifi";
+};
+
+&reg_usb0_vbus {
+	gpio = <&pio 6 12 GPIO_ACTIVE_HIGH>; /* PG12 */
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_pins_b>;
+	status = "okay";
+};
+
+&usb_otg {
+	dr_mode = "otg";
+	status = "okay";
+};
+
+&usb0_vbus_pin_a {
+	allwinner,pins = "PG12";
+};
+
+&usbphy {
+	pinctrl-names = "default";
+	pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>;
+	usb0_id_det-gpio = <&pio 6 2 GPIO_ACTIVE_HIGH>; /* PG2 */
+	usb0_vbus_det-gpio = <&pio 6 1 GPIO_ACTIVE_HIGH>; /* PG1 */
+	usb0_vbus-supply = <&reg_usb0_vbus>;
+	usb1_vbus-supply = <&reg_ldo3>;
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/sun5i-a13.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/sun5i-a13.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/sun5i-a13.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/sun5i-a13.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -61,7 +61,8 @@
 			compatible = "allwinner,simple-framebuffer",
 				     "simple-framebuffer";
 			allwinner,pipeline = "de_be0-lcd0";
-			clocks = <&pll5 1>, <&ahb_gates 36>, <&ahb_gates 44>;
+			clocks = <&ahb_gates 36>, <&ahb_gates 44>, <&de_be_clk>,
+				 <&tcon_ch0_clk>, <&dram_gates 26>;
 			status = "disabled";
 		};
 	};
@@ -110,8 +111,8 @@
 					<10>, <13>,
 					<14>, <20>,
 					<21>, <22>,
-				        <28>, <32>, <36>,
-				        <40>, <44>,
+					<28>, <32>, <34>,
+					<36>, <40>, <44>,
 					<46>, <51>,
 					<52>;
 			clock-output-names = "ahb_usbotg", "ahb_ehci",
@@ -120,8 +121,8 @@
 					     "ahb_mmc2", "ahb_nand",
 					     "ahb_sdram", "ahb_spi0",
 					     "ahb_spi1", "ahb_spi2",
-					     "ahb_stimer", "ahb_ve", "ahb_lcd",
-					     "ahb_csi", "ahb_de_be",
+					     "ahb_stimer", "ahb_ve", "ahb_tve",
+					     "ahb_lcd", "ahb_csi", "ahb_de_be",
 					     "ahb_de_fe", "ahb_iep",
 					     "ahb_mali400";
 		};
@@ -149,6 +150,61 @@
 					     "apb1_i2c2", "apb1_uart1",
 					     "apb1_uart3";
 		};
+
+		dram_gates: clk@01c20100 {
+			#clock-cells = <1>;
+			compatible = "allwinner,sun5i-a13-dram-gates-clk",
+				     "allwinner,sun4i-a10-gates-clk";
+			reg = <0x01c20100 0x4>;
+			clocks = <&pll5 0>;
+			clock-indices = <0>,
+					<1>,
+					<25>,
+					<26>,
+					<29>,
+					<31>;
+			clock-output-names = "dram_ve",
+					     "dram_csi",
+					     "dram_de_fe",
+					     "dram_de_be",
+					     "dram_ace",
+					     "dram_iep";
+		};
+
+		de_be_clk: clk@01c20104 {
+			#clock-cells = <0>;
+			#reset-cells = <0>;
+			compatible = "allwinner,sun4i-a10-display-clk";
+			reg = <0x01c20104 0x4>;
+			clocks = <&pll3>, <&pll7>, <&pll5 1>;
+			clock-output-names = "de-be";
+		};
+
+		de_fe_clk: clk@01c2010c {
+			#clock-cells = <0>;
+			#reset-cells = <0>;
+			compatible = "allwinner,sun4i-a10-display-clk";
+			reg = <0x01c2010c 0x4>;
+			clocks = <&pll3>, <&pll7>, <&pll5 1>;
+			clock-output-names = "de-fe";
+		};
+
+		tcon_ch0_clk: clk@01c20118 {
+			#clock-cells = <0>;
+			#reset-cells = <1>;
+			compatible = "allwinner,sun4i-a10-tcon-ch0-clk";
+			reg = <0x01c20118 0x4>;
+			clocks = <&pll3>, <&pll7>, <&pll3x2>, <&pll7x2>;
+			clock-output-names = "tcon-ch0-sclk";
+		};
+
+		tcon_ch1_clk: clk@01c2012c {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-tcon-ch1-clk";
+			reg = <0x01c2012c 0x4>;
+			clocks = <&pll3>, <&pll7>, <&pll3x2>, <&pll7x2>;
+			clock-output-names = "tcon-ch1-sclk";
+		};
 	};
 
 	soc@01c00000 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/sun5i-a13-empire-electronix-d709.dts linux-libre-4.7-gnu/arch/arm/boot/dts/sun5i-a13-empire-electronix-d709.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/sun5i-a13-empire-electronix-d709.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/sun5i-a13-empire-electronix-d709.dts	2016-07-24 15:23:50.000000000 -0400
@@ -123,7 +123,7 @@
 
 &mmc0 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_inet98fv2>;
+	pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_d709>;
 	vmmc-supply = <&reg_vcc3v3>;
 	bus-width = <4>;
 	cd-gpios = <&pio 6 0 GPIO_ACTIVE_HIGH>; /* PG0 */
@@ -131,27 +131,12 @@
 	status = "okay";
 };
 
-&mmc2 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&mmc2_pins_a>;
-	vmmc-supply = <&reg_vcc3v3>;
-	bus-width = <8>;
-	non-removable;
-	status = "okay";
-
-	mmccard: mmccard@0 {
-		reg = <0>;
-		compatible = "mmc-card";
-		broken-hpi;
-	};
-};
-
 &otg_sram {
 	status = "okay";
 };
 
 &pio {
-	mmc0_cd_pin_inet98fv2: mmc0_cd_pin@0 {
+	mmc0_cd_pin_d709: mmc0_cd_pin@0 {
 		allwinner,pins = "PG0";
 		allwinner,function = "gpio_in";
 		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/sun5i-a13-inet-98v-rev2.dts linux-libre-4.7-gnu/arch/arm/boot/dts/sun5i-a13-inet-98v-rev2.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/sun5i-a13-inet-98v-rev2.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/sun5i-a13-inet-98v-rev2.dts	2016-07-24 15:23:50.000000000 -0400
@@ -123,21 +123,6 @@
 	status = "okay";
 };
 
-&mmc2 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&mmc2_pins_a>;
-	vmmc-supply = <&reg_vcc3v3>;
-	bus-width = <8>;
-	non-removable;
-	status = "okay";
-
-	mmccard: mmccard@0 {
-		reg = <0>;
-		compatible = "mmc-card";
-		broken-hpi;
-	};
-};
-
 &otg_sram {
 	status = "okay";
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts linux-libre-4.7-gnu/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts	2016-07-24 15:23:50.000000000 -0400
@@ -109,6 +109,10 @@
 	status = "okay";
 };
 
+&otg_sram {
+	status = "okay";
+};
+
 &pio {
 	mmc0_cd_pin_olinuxinom: mmc0_cd_pin@0 {
 		allwinner,pins = "PG0";
@@ -124,6 +128,27 @@
 		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
 	};
 
+	usb0_id_detect_pin: usb0_id_detect_pin@0 {
+		allwinner,pins = "PG2";
+		allwinner,function = "gpio_in";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
+	};
+
+	usb0_vbus_detect_pin: usb0_vbus_detect_pin@0 {
+		allwinner,pins = "PG1";
+		allwinner,function = "gpio_in";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_PULL_DOWN>;
+	};
+
+	usb0_vbus_pin_olinuxinom: usb0_vbus_pin@0 {
+		allwinner,pins = "PG12";
+		allwinner,function = "gpio_out";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+
 	usb1_vbus_pin_olinuxinom: usb1_vbus_pin@0 {
 		allwinner,pins = "PG11";
 		allwinner,function = "gpio_out";
@@ -132,6 +157,12 @@
 	};
 };
 
+&reg_usb0_vbus {
+	pinctrl-0 = <&usb0_vbus_pin_olinuxinom>;
+	gpio = <&pio 6 12 GPIO_ACTIVE_HIGH>;
+	status = "okay";
+};
+
 &reg_usb1_vbus {
 	pinctrl-0 = <&usb1_vbus_pin_olinuxinom>;
 	gpio = <&pio 6 11 GPIO_ACTIVE_HIGH>;
@@ -144,7 +175,17 @@
 	status = "okay";
 };
 
+&usb_otg {
+	dr_mode = "otg";
+	status = "okay";
+};
+
 &usbphy {
+	pinctrl-names = "default";
+	pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>;
+	usb0_id_det-gpio = <&pio 6 2 GPIO_ACTIVE_HIGH>; /* PG2 */
+	usb0_vbus_det-gpio = <&pio 6 1 GPIO_ACTIVE_HIGH>; /* PG1 */
+	usb0_vbus-supply = <&reg_usb0_vbus>;
 	usb1_vbus-supply = <&reg_usb1_vbus>;
 	status = "okay";
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/sun5i.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/sun5i.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/sun5i.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/sun5i.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -88,6 +88,15 @@
 			clock-output-names = "osc24M";
 		};
 
+		osc3M: osc3M_clk {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clock-div = <8>;
+			clock-mult = <1>;
+			clocks = <&osc24M>;
+			clock-output-names = "osc3M";
+		};
+
 		osc32k: clk@0 {
 			#clock-cells = <0>;
 			compatible = "fixed-clock";
@@ -112,6 +121,23 @@
 					     "pll2-4x", "pll2-8x";
 		};
 
+		pll3: clk@01c20010 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-pll3-clk";
+			reg = <0x01c20010 0x4>;
+			clocks = <&osc3M>;
+			clock-output-names = "pll3";
+		};
+
+		pll3x2: pll3x2_clk {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clock-div = <1>;
+			clock-mult = <2>;
+			clocks = <&pll3>;
+			clock-output-names = "pll3-2x";
+		};
+
 		pll4: clk@01c20018 {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-pll1-clk";
@@ -136,6 +162,23 @@
 			clock-output-names = "pll6_sata", "pll6_other", "pll6";
 		};
 
+		pll7: clk@01c20030 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-pll3-clk";
+			reg = <0x01c20030 0x4>;
+			clocks = <&osc3M>;
+			clock-output-names = "pll7";
+		};
+
+		pll7x2: pll7x2_clk {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clock-div = <1>;
+			clock-mult = <2>;
+			clocks = <&pll7>;
+			clock-output-names = "pll7-2x";
+		};
+
 		/* dummy is 200M */
 		cpu: cpu@01c20054 {
 			#clock-cells = <0>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/sun5i-r8-chip.dts linux-libre-4.7-gnu/arch/arm/boot/dts/sun5i-r8-chip.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/sun5i-r8-chip.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/sun5i-r8-chip.dts	2016-07-24 15:23:50.000000000 -0400
@@ -52,7 +52,7 @@
 
 / {
 	model = "NextThing C.H.I.P.";
-	compatible = "nextthing,chip", "allwinner,sun5i-r8";
+	compatible = "nextthing,chip", "allwinner,sun5i-r8", "allwinner,sun5i-a13";
 
 	aliases {
 		i2c0 = &i2c0;
@@ -66,6 +66,10 @@
 	};
 };
 
+&be0 {
+	status = "okay";
+};
+
 &codec {
 	status = "okay";
 };
@@ -188,6 +192,14 @@
 	status = "okay";
 };
 
+&tcon0 {
+	status = "okay";
+};
+
+&tve0 {
+	status = "okay";
+};
+
 &uart1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart1_pins_b>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/sun5i-r8.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/sun5i-r8.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/sun5i-r8.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/sun5i-r8.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -51,9 +51,147 @@
 			compatible = "allwinner,simple-framebuffer",
 				     "simple-framebuffer";
 			allwinner,pipeline = "de_be0-lcd0-tve0";
-			clocks = <&pll5 1>, <&ahb_gates 34>, <&ahb_gates 36>,
-				 <&ahb_gates 44>;
+			clocks = <&ahb_gates 34>, <&ahb_gates 36>,
+				 <&ahb_gates 44>, <&de_be_clk>,
+				 <&tcon_ch1_clk>, <&dram_gates 26>;
+			status = "disabled";
+		};
+	};
+
+	soc@01c00000 {
+		tve0: tv-encoder@01c0a000 {
+			compatible = "allwinner,sun4i-a10-tv-encoder";
+			reg = <0x01c0a000 0x1000>;
+			clocks = <&ahb_gates 34>;
+			resets = <&tcon_ch0_clk 0>;
+			status = "disabled";
+
+			port {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				tve0_in_tcon0: endpoint@0 {
+					reg = <0>;
+					remote-endpoint = <&tcon0_out_tve0>;
+				};
+			};
+		};
+
+		tcon0: lcd-controller@01c0c000 {
+			compatible = "allwinner,sun5i-a13-tcon";
+			reg = <0x01c0c000 0x1000>;
+			interrupts = <44>;
+			resets = <&tcon_ch0_clk 1>;
+			reset-names = "lcd";
+			clocks = <&ahb_gates 36>,
+				 <&tcon_ch0_clk>,
+				 <&tcon_ch1_clk>;
+			clock-names = "ahb",
+				      "tcon-ch0",
+				      "tcon-ch1";
+			clock-output-names = "tcon-pixel-clock";
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				tcon0_in: port@0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0>;
+
+					tcon0_in_be0: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&be0_out_tcon0>;
+					};
+				};
+
+				tcon0_out: port@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+
+					tcon0_out_tve0: endpoint@1 {
+						reg = <1>;
+						remote-endpoint = <&tve0_in_tcon0>;
+					};
+				};
+			};
+		};
+
+		fe0: display-frontend@01e00000 {
+			compatible = "allwinner,sun5i-a13-display-frontend";
+			reg = <0x01e00000 0x20000>;
+			interrupts = <47>;
+			clocks = <&ahb_gates 46>, <&de_fe_clk>,
+				 <&dram_gates 25>;
+			clock-names = "ahb", "mod",
+				      "ram";
+			resets = <&de_fe_clk>;
 			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				fe0_out: port@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+
+					fe0_out_be0: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&be0_in_fe0>;
+					};
+				};
+			};
 		};
+
+		be0: display-backend@01e60000 {
+			compatible = "allwinner,sun5i-a13-display-backend";
+			reg = <0x01e60000 0x10000>;
+			clocks = <&ahb_gates 44>, <&de_be_clk>,
+				 <&dram_gates 26>;
+			clock-names = "ahb", "mod",
+				      "ram";
+			resets = <&de_be_clk>;
+			status = "disabled";
+
+			assigned-clocks = <&de_be_clk>;
+			assigned-clock-rates = <300000000>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				be0_in: port@0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0>;
+
+					be0_in_fe0: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&fe0_out_be0>;
+					};
+				};
+
+				be0_out: port@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+
+					be0_out_tcon0: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&tcon0_in_be0>;
+					};
+				};
+			};
+		};
+	};
+
+	display-engine {
+		compatible = "allwinner,sun5i-a13-display-engine";
+		allwinner,pipelines = <&fe0>;
 	};
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/sun6i-a31s-colorfly-e708-q1.dts linux-libre-4.7-gnu/arch/arm/boot/dts/sun6i-a31s-colorfly-e708-q1.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/sun6i-a31s-colorfly-e708-q1.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/sun6i-a31s-colorfly-e708-q1.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,208 @@
+/*
+ * Copyright 2016 Hans de Goede <hdegoede@redhat.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "sun6i-a31s.dtsi"
+#include "sunxi-common-regulators.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/pinctrl/sun4i-a10.h>
+
+/ {
+	model = "Colorfly E708 Q1 tablet";
+	compatible = "colorfly,e708-q1", "allwinner,sun6i-a31s";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&cpu0 {
+	cpu-supply = <&reg_dcdc3>;
+};
+
+&ehci0 {
+	/* rtl8188etv wifi is connected here */
+	status = "okay";
+};
+
+&lradc {
+	vref-supply = <&reg_aldo3>;
+	status = "okay";
+
+	button@1000 {
+		label = "Home";
+		linux,code = <KEY_HOMEPAGE>;
+		channel = <0>;
+		voltage = <1000000>;
+	};
+};
+
+&mmc0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_e708_q1>;
+	vmmc-supply = <&reg_dcdc1>;
+	bus-width = <4>;
+	cd-gpios = <&pio 0 8 GPIO_ACTIVE_HIGH>; /* PA8 */
+	cd-inverted;
+	status = "okay";
+};
+
+&pio {
+	mma8452_int_e708_q1: mma8452_int_pin@0 {
+		allwinner,pins = "PA9";
+		allwinner,function = "gpio_in";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
+	};
+
+	mmc0_cd_pin_e708_q1: mmc0_cd_pin@0 {
+		allwinner,pins = "PA8";
+		allwinner,function = "gpio_in";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
+	};
+};
+
+&p2wi {
+	status = "okay";
+
+	axp22x: pmic@68 {
+		compatible = "x-powers,axp221";
+		reg = <0x68>;
+		interrupt-parent = <&nmi_intc>;
+		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+	};
+};
+
+#include "axp22x.dtsi"
+
+&reg_aldo3 {
+	regulator-always-on;
+	regulator-min-microvolt = <2700000>;
+	regulator-max-microvolt = <3300000>;
+	regulator-name = "avcc";
+};
+
+&reg_dc1sw {
+	regulator-name = "vcc-lcd";
+};
+
+&reg_dc5ldo {
+	regulator-always-on;
+	regulator-min-microvolt = <700000>;
+	regulator-max-microvolt = <1320000>;
+	regulator-name = "vdd-cpus"; /* This is an educated guess */
+};
+
+&reg_dcdc1 {
+	regulator-always-on;
+	regulator-min-microvolt = <3000000>;
+	regulator-max-microvolt = <3000000>;
+	regulator-name = "vcc-3v0";
+};
+
+&reg_dcdc2 {
+	regulator-min-microvolt = <700000>;
+	regulator-max-microvolt = <1320000>;
+	regulator-name = "vdd-gpu";
+};
+
+&reg_dcdc3 {
+	regulator-always-on;
+	regulator-min-microvolt = <700000>;
+	regulator-max-microvolt = <1320000>;
+	regulator-name = "vdd-cpu";
+};
+
+&reg_dcdc4 {
+	regulator-always-on;
+	regulator-min-microvolt = <700000>;
+	regulator-max-microvolt = <1320000>;
+	regulator-name = "vdd-sys-dll";
+};
+
+&reg_dcdc5 {
+	regulator-always-on;
+	regulator-min-microvolt = <1500000>;
+	regulator-max-microvolt = <1500000>;
+	regulator-name = "vcc-dram";
+};
+
+&reg_dldo1 {
+	regulator-min-microvolt = <3300000>;
+	regulator-max-microvolt = <3300000>;
+	regulator-name = "vcc-wifi";
+};
+
+&reg_dldo2 {
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-name = "vcc-pg";
+};
+
+&simplefb_lcd {
+	vcc-lcd-supply = <&reg_dc1sw>;
+	vcc-pg-supply = <&reg_dldo2>;
+};
+
+/*
+ * FIXME for now we only support host mode and rely on u-boot to have
+ * turned on Vbus which is controlled by the axp221 pmic on the board.
+ *
+ * Once we have axp221 power-supply and vbus-usb support we should switch
+ * to fully supporting otg.
+ */
+&usb_otg {
+	dr_mode = "host";
+	status = "okay";
+};
+
+&usbphy {
+	usb1_vbus-supply = <&reg_dldo1>;
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/sun6i-a31s-primo81.dts linux-libre-4.7-gnu/arch/arm/boot/dts/sun6i-a31s-primo81.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/sun6i-a31s-primo81.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/sun6i-a31s-primo81.dts	2016-07-24 15:23:50.000000000 -0400
@@ -176,8 +176,6 @@
 };
 
 &reg_dc1sw {
-	regulator-min-microvolt = <3000000>;
-	regulator-max-microvolt = <3000000>;
 	regulator-name = "vcc-lcd";
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/sun6i-a31s-yones-toptech-bs1078-v2.dts linux-libre-4.7-gnu/arch/arm/boot/dts/sun6i-a31s-yones-toptech-bs1078-v2.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/sun6i-a31s-yones-toptech-bs1078-v2.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/sun6i-a31s-yones-toptech-bs1078-v2.dts	2016-07-24 15:23:50.000000000 -0400
@@ -135,8 +135,6 @@
 
 &reg_dc1sw {
 	regulator-name = "vcc-lcd-usb2";
-	regulator-min-microvolt = <3000000>;
-	regulator-max-microvolt = <3000000>;
 };
 
 &reg_dc5ldo {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/sun7i-a20-cubietruck.dts linux-libre-4.7-gnu/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/sun7i-a20-cubietruck.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/sun7i-a20-cubietruck.dts	2016-07-24 15:23:50.000000000 -0400
@@ -94,6 +94,24 @@
 		pinctrl-0 = <&mmc3_pwrseq_pin_cubietruck>;
 		reset-gpios = <&pio 7 9 GPIO_ACTIVE_LOW>; /* PH9 WIFI_EN */
 	};
+
+	sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,name = "On-board SPDIF";
+
+		simple-audio-card,cpu {
+			sound-dai = <&spdif>;
+		};
+
+		simple-audio-card,codec {
+			sound-dai = <&spdif_out>;
+		};
+	};
+
+	spdif_out: spdif-out {
+		#sound-dai-cells = <0>;
+		compatible = "linux,spdif-dit";
+	};
 };
 
 &ahci {
@@ -301,6 +319,12 @@
 	status = "okay";
 };
 
+&spdif {
+	pinctrl-names = "default";
+	pinctrl-0 = <&spdif_tx_pins_a>;
+	status = "okay";
+};
+
 &uart0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart0_pins_a>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/sun7i-a20.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/sun7i-a20.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/sun7i-a20.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/sun7i-a20.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -67,8 +67,9 @@
 			compatible = "allwinner,simple-framebuffer",
 				     "simple-framebuffer";
 			allwinner,pipeline = "de_be0-lcd0-hdmi";
-			clocks = <&pll5 1>, <&ahb_gates 36>, <&ahb_gates 43>,
-				 <&ahb_gates 44>, <&dram_gates 26>;
+			clocks = <&pll3>, <&pll5 1>, <&ahb_gates 36>,
+				 <&ahb_gates 43>, <&ahb_gates 44>,
+				 <&dram_gates 26>;
 			status = "disabled";
 		};
 
@@ -76,8 +77,8 @@
 			compatible = "allwinner,simple-framebuffer",
 				     "simple-framebuffer";
 			allwinner,pipeline = "de_be0-lcd0";
-			clocks = <&pll5 1>, <&ahb_gates 36>, <&ahb_gates 44>,
-				 <&dram_gates 26>;
+			clocks = <&pll3>, <&pll5 1>, <&ahb_gates 36>,
+				 <&ahb_gates 44>, <&dram_gates 26>;
 			status = "disabled";
 		};
 
@@ -85,8 +86,9 @@
 			compatible = "allwinner,simple-framebuffer",
 				     "simple-framebuffer";
 			allwinner,pipeline = "de_be0-lcd0-tve0";
-			clocks = <&pll5 1>, <&ahb_gates 34>, <&ahb_gates 36>,
-				 <&ahb_gates 44>, <&dram_gates 26>;
+			clocks = <&pll3>, <&pll5 1>,
+				 <&ahb_gates 34>, <&ahb_gates 36>, <&ahb_gates 44>,
+				 <&dram_gates 5>, <&dram_gates 26>;
 			status = "disabled";
 		};
 	};
@@ -186,6 +188,15 @@
 			clock-output-names = "osc24M";
 		};
 
+		osc3M: osc3M_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clock-div = <8>;
+			clock-mult = <1>;
+			clocks = <&osc24M>;
+			clock-output-names = "osc3M";
+		};
+
 		osc32k: clk@0 {
 			#clock-cells = <0>;
 			compatible = "fixed-clock";
@@ -210,6 +221,23 @@
 					     "pll2-4x", "pll2-8x";
 		};
 
+		pll3: clk@01c20010 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-pll3-clk";
+			reg = <0x01c20010 0x4>;
+			clocks = <&osc3M>;
+			clock-output-names = "pll3";
+		};
+
+		pll3x2: pll3x2_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll3>;
+			clock-div = <1>;
+			clock-mult = <2>;
+			clock-output-names = "pll3-2x";
+		};
+
 		pll4: clk@01c20018 {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun7i-a20-pll4-clk";
@@ -235,6 +263,23 @@
 					     "pll6_div_4";
 		};
 
+		pll7: clk@01c20030 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-pll3-clk";
+			reg = <0x01c20030 0x4>;
+			clocks = <&osc3M>;
+			clock-output-names = "pll7";
+		};
+
+		pll7x2: pll7x2_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-factor-clock";
+			clocks = <&pll7>;
+			clock-div = <1>;
+			clock-mult = <2>;
+			clock-output-names = "pll7-2x";
+		};
+
 		pll8: clk@01c20040 {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun7i-a20-pll4-clk";
@@ -476,6 +521,17 @@
 			clock-output-names = "ir1";
 		};
 
+		spdif_clk: clk@01c200c0 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mod1-clk";
+			reg = <0x01c200c0 0x4>;
+			clocks = <&pll2 SUN4I_A10_PLL2_8X>,
+				 <&pll2 SUN4I_A10_PLL2_4X>,
+				 <&pll2 SUN4I_A10_PLL2_2X>,
+				 <&pll2 SUN4I_A10_PLL2_1X>;
+			clock-output-names = "spdif";
+		};
+
 		keypad_clk: clk@01c200c4 {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-mod0-clk";
@@ -1193,6 +1249,13 @@
 				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
 				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
 			};
+
+			spdif_tx_pins_a: spdif@0 {
+				allwinner,pins = "PB13";
+				allwinner,function = "spdif";
+				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+				allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
+			};
 		};
 
 		timer@01c20c00 {
@@ -1226,6 +1289,19 @@
 			status = "disabled";
 		};
 
+		spdif: spdif@01c21000 {
+			#sound-dai-cells = <0>;
+			compatible = "allwinner,sun4i-a10-spdif";
+			reg = <0x01c21000 0x400>;
+			interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&apb0_gates 1>, <&spdif_clk>;
+			clock-names = "apb", "spdif";
+			dmas = <&dma SUN4I_DMA_NORMAL 2>,
+			       <&dma SUN4I_DMA_NORMAL 2>;
+			dma-names = "rx", "tx";
+			status = "disabled";
+		};
+
 		ir0: ir@01c21800 {
 			compatible = "allwinner,sun4i-a10-ir";
 			clocks = <&apb0_gates 6>, <&ir0_clk>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/sun7i-a20-itead-ibox.dts linux-libre-4.7-gnu/arch/arm/boot/dts/sun7i-a20-itead-ibox.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/sun7i-a20-itead-ibox.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/sun7i-a20-itead-ibox.dts	2016-07-24 15:23:50.000000000 -0400
@@ -65,6 +65,24 @@
 			default-state = "on";
 		};
 	};
+
+	sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,name = "On-board SPDIF";
+
+		simple-audio-card,cpu {
+			sound-dai = <&spdif>;
+		};
+
+		simple-audio-card,codec {
+			sound-dai = <&spdif_out>;
+		};
+	};
+
+	spdif_out: spdif-out {
+		#sound-dai-cells = <0>;
+		compatible = "linux,spdif-dit";
+	};
 };
 
 &ahci {
@@ -123,3 +141,9 @@
 &reg_ahci_5v {
 	status = "okay";
 };
+
+&spdif {
+	pinctrl-names = "default";
+	pinctrl-0 = <&spdif_tx_pins_a>;
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts linux-libre-4.7-gnu/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,82 @@
+ /*
+ * Copyright 2015 - Ultimaker B.V.
+ * Author Olliver Schinagl <oliver@schinagl.nl>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "sun7i-a20-olinuxino-lime2.dts"
+
+/ {
+	model = "Olimex A20-OLinuXino-LIME2-eMMC";
+	compatible = "olimex,a20-olinuxino-lime2-emmc", "allwinner,sun7i-a20";
+
+	mmc2_pwrseq: pwrseq {
+		pinctrl-0 = <&mmc2_pins_nrst>;
+		pinctrl-names = "default";
+		compatible = "mmc-pwrseq-emmc";
+		reset-gpios = <&pio 2 16 GPIO_ACTIVE_LOW>;
+	};
+};
+
+&pio {
+	mmc2_pins_nrst: mmc2@0 {
+		allwinner,pins = "PC16";
+		allwinner,function = "gpio_out";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+};
+
+&mmc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc2_pins_a>;
+	vmmc-supply = <&reg_vcc3v3>;
+	vqmmc-supply = <&reg_vcc3v3>;
+	bus-width = <4>;
+	non-removable;
+	mmc-pwrseq = <&mmc2_pwrseq>;
+	status = "okay";
+
+	emmc: emmc@0 {
+		reg = <0>;
+		compatible = "mmc-card";
+		broken-hpi;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/sun8i-a23-gt90h-v4.dts linux-libre-4.7-gnu/arch/arm/boot/dts/sun8i-a23-gt90h-v4.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/sun8i-a23-gt90h-v4.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/sun8i-a23-gt90h-v4.dts	2016-07-24 15:23:50.000000000 -0400
@@ -47,15 +47,26 @@
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/pinctrl/sun4i-a10.h>
+#include <dt-bindings/pwm/pwm.h>
 
 / {
-	model = "Allwinner GT90H Quad Core Tablet (v4)";
-	compatible = "allwinner,gt90h-v4", "allwinner,sun8i-a33";
+	model = "Allwinner GT90H Dual Core Tablet (v4)";
+	compatible = "allwinner,gt90h-v4", "allwinner,sun8i-a23";
 
 	aliases {
 		serial0 = &r_uart;
 	};
 
+	backlight: backlight {
+		compatible = "pwm-backlight";
+		pinctrl-names = "default";
+		pinctrl-0 = <&bl_en_pin_gt90h>;
+		pwms = <&pwm 0 50000 PWM_POLARITY_INVERTED>;
+		brightness-levels = <0 10 20 30 40 50 60 70 80 90 100>;
+		default-brightness-level = <8>;
+		enable-gpios = <&pio 7 6 GPIO_ACTIVE_HIGH>; /* PH6 */
+	};
+
 	chosen {
 		stdout-path = "serial0:115200n8";
 	};
@@ -106,8 +117,7 @@
 &mmc0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_gt90h>;
-	/* FIXME this really is aldo1, correct once we've pmic support */
-	vmmc-supply = <&reg_vcc3v0>;
+	vmmc-supply = <&reg_aldo1>;
 	bus-width = <4>;
 	cd-gpios = <&pio 1 4 GPIO_ACTIVE_HIGH>; /* PB4 */
 	cd-inverted;
@@ -115,6 +125,13 @@
 };
 
 &pio {
+	bl_en_pin_gt90h: bl_en_pin@0 {
+		allwinner,pins = "PH6";
+		allwinner,function = "gpio_in";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+
 	mmc0_cd_pin_gt90h: mmc0_cd_pin@0 {
 		allwinner,pins = "PB4";
 		allwinner,function = "gpio_in";
@@ -123,12 +140,106 @@
 	};
 };
 
+&pwm {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pwm0_pins>;
+	status = "okay";
+};
+
+&r_rsb {
+	status = "okay";
+
+	axp22x: pmic@3a3 {
+		compatible = "x-powers,axp223";
+		reg = <0x3a3>;
+		interrupt-parent = <&nmi_intc>;
+		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+		eldoin-supply = <&reg_dcdc1>;
+	};
+};
+
 &r_uart {
 	pinctrl-names = "default";
 	pinctrl-0 = <&r_uart_pins_a>;
 	status = "okay";
 };
 
+#include "axp22x.dtsi"
+
+&reg_aldo1 {
+	regulator-always-on;
+	regulator-min-microvolt = <3000000>;
+	regulator-max-microvolt = <3000000>;
+	regulator-name = "vcc-io";
+};
+
+&reg_aldo2 {
+	regulator-always-on;
+	regulator-min-microvolt = <2350000>;
+	regulator-max-microvolt = <2650000>;
+	regulator-name = "vdd-dll";
+};
+
+&reg_aldo3 {
+	regulator-always-on;
+	regulator-min-microvolt = <2700000>;
+	regulator-max-microvolt = <3300000>;
+	regulator-name = "vcc-pll-avcc";
+};
+
+&reg_dc1sw {
+	regulator-name = "vcc-lcd";
+};
+
+&reg_dc5ldo {
+	regulator-always-on;
+	regulator-min-microvolt = <900000>;
+	regulator-max-microvolt = <1400000>;
+	regulator-name = "vdd-cpus";
+};
+
+&reg_dcdc1 {
+	regulator-always-on;
+	regulator-min-microvolt = <3000000>;
+	regulator-max-microvolt = <3000000>;
+	regulator-name = "vcc-3v0";
+};
+
+&reg_dcdc2 {
+	regulator-always-on;
+	regulator-min-microvolt = <900000>;
+	regulator-max-microvolt = <1400000>;
+	regulator-name = "vdd-sys";
+};
+
+&reg_dcdc3 {
+	regulator-always-on;
+	regulator-min-microvolt = <900000>;
+	regulator-max-microvolt = <1400000>;
+	regulator-name = "vdd-cpu";
+};
+
+&reg_dcdc5 {
+	regulator-always-on;
+	regulator-min-microvolt = <1500000>;
+	regulator-max-microvolt = <1500000>;
+	regulator-name = "vcc-dram";
+};
+
+&reg_dldo1 {
+	regulator-min-microvolt = <3300000>;
+	regulator-max-microvolt = <3300000>;
+	regulator-name = "vcc-wifi";
+};
+
+&reg_rtc_ldo {
+	regulator-name = "vcc-rtc";
+};
+
+&simplefb_lcd {
+	vcc-lcd-supply = <&reg_dc1sw>;
+};
+
 /*
  * FIXME for now we only support host mode and rely on u-boot to have
  * turned on Vbus which is controlled by the axp223 pmic on the board.
@@ -141,5 +252,6 @@
 };
 
 &usbphy {
+	usb1_vbus-supply = <&reg_dldo1>;
 	status = "okay";
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/sun8i-a23-polaroid-mid2809pxe04.dts linux-libre-4.7-gnu/arch/arm/boot/dts/sun8i-a23-polaroid-mid2809pxe04.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/sun8i-a23-polaroid-mid2809pxe04.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/sun8i-a23-polaroid-mid2809pxe04.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,243 @@
+/*
+ * Copyright 2016 Hans de Goede <hdegoede@redhat.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "sun8i-a23.dtsi"
+#include "sunxi-common-regulators.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/pinctrl/sun4i-a10.h>
+#include <dt-bindings/pwm/pwm.h>
+
+/ {
+	model = "Polaroid MID2809PXE04 tablet";
+	compatible = "polaroid,mid2809pxe04", "allwinner,sun8i-a23";
+
+	aliases {
+		serial0 = &r_uart;
+	};
+
+	backlight: backlight {
+		compatible = "pwm-backlight";
+		pinctrl-names = "default";
+		pinctrl-0 = <&bl_en_pin_mid2809>;
+		pwms = <&pwm 0 50000 PWM_POLARITY_INVERTED>;
+		brightness-levels = <0 10 20 30 40 50 60 70 80 90 100>;
+		default-brightness-level = <8>;
+		enable-gpios = <&pio 7 6 GPIO_ACTIVE_HIGH>; /* PH6 */
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&ehci0 {
+	status = "okay";
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins_a>;
+	status = "okay";
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins_a>;
+	status = "okay";
+};
+
+&lradc {
+	vref-supply = <&reg_vcc3v0>;
+	status = "okay";
+
+	button@200 {
+		label = "Volume Up";
+		linux,code = <KEY_VOLUMEUP>;
+		channel = <0>;
+		voltage = <200000>;
+	};
+
+	button@400 {
+		label = "Volume Down";
+		linux,code = <KEY_VOLUMEDOWN>;
+		channel = <0>;
+		voltage = <400000>;
+	};
+};
+
+&mmc0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin_mid2809>;
+	vmmc-supply = <&reg_dcdc1>;
+	bus-width = <4>;
+	cd-gpios = <&pio 1 4 GPIO_ACTIVE_HIGH>; /* PB4 */
+	cd-inverted;
+	status = "okay";
+};
+
+&pio {
+	bl_en_pin_mid2809: bl_en_pin@0 {
+		allwinner,pins = "PH6";
+		allwinner,function = "gpio_in";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+
+	mmc0_cd_pin_mid2809: mmc0_cd_pin@0 {
+		allwinner,pins = "PB4";
+		allwinner,function = "gpio_in";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
+	};
+};
+
+&pwm {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pwm0_pins>;
+	status = "okay";
+};
+
+&r_rsb {
+	status = "okay";
+
+	axp22x: pmic@3a3 {
+		compatible = "x-powers,axp223";
+		reg = <0x3a3>;
+		interrupt-parent = <&nmi_intc>;
+		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+		eldoin-supply = <&reg_dcdc1>;
+	};
+};
+
+&r_uart {
+	pinctrl-names = "default";
+	pinctrl-0 = <&r_uart_pins_a>;
+	status = "okay";
+};
+
+#include "axp22x.dtsi"
+
+&reg_aldo1 {
+	regulator-always-on;
+	regulator-min-microvolt = <3000000>;
+	regulator-max-microvolt = <3000000>;
+	regulator-name = "vcc-io";
+};
+
+&reg_aldo2 {
+	regulator-always-on;
+	regulator-min-microvolt = <2350000>;
+	regulator-max-microvolt = <2650000>;
+	regulator-name = "vdd-dll";
+};
+
+&reg_aldo3 {
+	regulator-always-on;
+	regulator-min-microvolt = <2700000>;
+	regulator-max-microvolt = <3300000>;
+	regulator-name = "vcc-pll-avcc";
+};
+
+&reg_dc1sw {
+	regulator-name = "vcc-lcd";
+};
+
+&reg_dc5ldo {
+	regulator-always-on;
+	regulator-min-microvolt = <900000>;
+	regulator-max-microvolt = <1400000>;
+	regulator-name = "vdd-cpus";
+};
+
+&reg_dcdc1 {
+	regulator-always-on;
+	regulator-min-microvolt = <3000000>;
+	regulator-max-microvolt = <3000000>;
+	regulator-name = "vcc-3v0";
+};
+
+&reg_dcdc2 {
+	regulator-always-on;
+	regulator-min-microvolt = <900000>;
+	regulator-max-microvolt = <1400000>;
+	regulator-name = "vdd-sys";
+};
+
+&reg_dcdc3 {
+	regulator-always-on;
+	regulator-min-microvolt = <900000>;
+	regulator-max-microvolt = <1400000>;
+	regulator-name = "vdd-cpu";
+};
+
+&reg_dcdc5 {
+	regulator-always-on;
+	regulator-min-microvolt = <1500000>;
+	regulator-max-microvolt = <1500000>;
+	regulator-name = "vcc-dram";
+};
+
+&reg_rtc_ldo {
+	regulator-name = "vcc-rtc";
+};
+
+&simplefb_lcd {
+	vcc-lcd-supply = <&reg_dc1sw>;
+};
+
+/*
+ * FIXME for now we only support host mode and rely on u-boot to have
+ * turned on Vbus which is controlled by the axp223 pmic on the board.
+ *
+ * Once we have axp223 support we should switch to fully supporting otg.
+ */
+&usb_otg {
+	dr_mode = "host";
+	status = "okay";
+};
+
+&usbphy {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/sun8i-h3.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/sun8i-h3.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/sun8i-h3.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/sun8i-h3.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -269,6 +269,18 @@
 					     "mmc2_sample";
 		};
 
+		usb_clk: clk@01c200cc {
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+			compatible = "allwinner,sun8i-h3-usb-clk";
+			reg = <0x01c200cc 0x4>;
+			clocks = <&osc24M>;
+			clock-output-names = "usb_phy0", "usb_phy1",
+					     "usb_phy2", "usb_phy3",
+					     "usb_ohci0", "usb_ohci1",
+					     "usb_ohci2", "usb_ohci3";
+		};
+
 		mbus_clk: clk@01c2015c {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun8i-a23-mbus-clk";
@@ -377,6 +389,107 @@
 			#size-cells = <0>;
 		};
 
+		usbphy: phy@01c19400 {
+			compatible = "allwinner,sun8i-h3-usb-phy";
+			reg = <0x01c19400 0x2c>,
+			      <0x01c1a800 0x4>,
+			      <0x01c1b800 0x4>,
+			      <0x01c1c800 0x4>,
+			      <0x01c1d800 0x4>;
+			reg-names = "phy_ctrl",
+				    "pmu0",
+				    "pmu1",
+				    "pmu2",
+				    "pmu3";
+			clocks = <&usb_clk 8>,
+				 <&usb_clk 9>,
+				 <&usb_clk 10>,
+				 <&usb_clk 11>;
+			clock-names = "usb0_phy",
+				      "usb1_phy",
+				      "usb2_phy",
+				      "usb3_phy";
+			resets = <&usb_clk 0>,
+				 <&usb_clk 1>,
+				 <&usb_clk 2>,
+				 <&usb_clk 3>;
+			reset-names = "usb0_reset",
+				      "usb1_reset",
+				      "usb2_reset",
+				      "usb3_reset";
+			status = "disabled";
+			#phy-cells = <1>;
+		};
+
+		ehci1: usb@01c1b000 {
+			compatible = "allwinner,sun8i-h3-ehci", "generic-ehci";
+			reg = <0x01c1b000 0x100>;
+			interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&bus_gates 25>, <&bus_gates 29>;
+			resets = <&ahb_rst 25>, <&ahb_rst 29>;
+			phys = <&usbphy 1>;
+			phy-names = "usb";
+			status = "disabled";
+		};
+
+		ohci1: usb@01c1b400 {
+			compatible = "allwinner,sun8i-h3-ohci", "generic-ohci";
+			reg = <0x01c1b400 0x100>;
+			interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&bus_gates 29>, <&bus_gates 25>,
+				 <&usb_clk 17>;
+			resets = <&ahb_rst 29>, <&ahb_rst 25>;
+			phys = <&usbphy 1>;
+			phy-names = "usb";
+			status = "disabled";
+		};
+
+		ehci2: usb@01c1c000 {
+			compatible = "allwinner,sun8i-h3-ehci", "generic-ehci";
+			reg = <0x01c1c000 0x100>;
+			interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&bus_gates 26>, <&bus_gates 30>;
+			resets = <&ahb_rst 26>, <&ahb_rst 30>;
+			phys = <&usbphy 2>;
+			phy-names = "usb";
+			status = "disabled";
+		};
+
+		ohci2: usb@01c1c400 {
+			compatible = "allwinner,sun8i-h3-ohci", "generic-ohci";
+			reg = <0x01c1c400 0x100>;
+			interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&bus_gates 30>, <&bus_gates 26>,
+				 <&usb_clk 18>;
+			resets = <&ahb_rst 30>, <&ahb_rst 26>;
+			phys = <&usbphy 2>;
+			phy-names = "usb";
+			status = "disabled";
+		};
+
+		ehci3: usb@01c1d000 {
+			compatible = "allwinner,sun8i-h3-ehci", "generic-ehci";
+			reg = <0x01c1d000 0x100>;
+			interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&bus_gates 27>, <&bus_gates 31>;
+			resets = <&ahb_rst 27>, <&ahb_rst 31>;
+			phys = <&usbphy 3>;
+			phy-names = "usb";
+			status = "disabled";
+		};
+
+		ohci3: usb@01c1d400 {
+			compatible = "allwinner,sun8i-h3-ohci", "generic-ohci";
+			reg = <0x01c1d400 0x100>;
+			interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&bus_gates 31>, <&bus_gates 27>,
+				 <&usb_clk 19>;
+			resets = <&ahb_rst 31>, <&ahb_rst 27>;
+			phys = <&usbphy 3>;
+			phy-names = "usb";
+			status = "disabled";
+		};
+
 		pio: pinctrl@01c20800 {
 			compatible = "allwinner,sun8i-h3-pinctrl";
 			reg = <0x01c20800 0x400>;
@@ -417,6 +530,16 @@
 				allwinner,drive = <SUN4I_PINCTRL_30_MA>;
 				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
 			};
+
+			mmc2_8bit_pins: mmc2_8bit {
+				allwinner,pins = "PC5", "PC6", "PC8",
+						 "PC9", "PC10", "PC11",
+						 "PC12", "PC13", "PC14",
+						 "PC15", "PC16";
+				allwinner,function = "mmc2";
+				allwinner,drive = <SUN4I_PINCTRL_30_MA>;
+				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+			};
 		};
 
 		ahb_rst: reset@01c202c0 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts linux-libre-4.7-gnu/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2016 Hans de Goede <hdegoede@redhat.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "sun8i-h3.dtsi"
+#include "sunxi-common-regulators.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/pinctrl/sun4i-a10.h>
+
+/ {
+	model = "Xunlong Orange Pi 2";
+	compatible = "xunlong,orangepi-2", "allwinner,sun8i-h3";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&leds_opc>, <&leds_r_opc>;
+
+		status_led {
+			label = "orangepi:red:status";
+			gpios = <&pio 0 15 GPIO_ACTIVE_HIGH>;
+		};
+
+		pwr_led {
+			label = "orangepi:green:pwr";
+			gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>;
+			default-state = "on";
+		};
+	};
+
+	r_gpio_keys {
+		compatible = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&sw_r_opc>;
+
+		sw2 {
+			label = "sw2";
+			linux,code = <BTN_1>;
+			gpios = <&r_pio 0 4 GPIO_ACTIVE_LOW>;
+		};
+
+		sw4 {
+			label = "sw4";
+			linux,code = <BTN_0>;
+			gpios = <&r_pio 0 3 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	wifi_pwrseq: wifi_pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		pinctrl-names = "default";
+		pinctrl-0 = <&wifi_pwrseq_pin_orangepi>;
+		reset-gpios = <&r_pio 0 7 GPIO_ACTIVE_LOW>; /* PL7 WIFI_EN */
+	};
+};
+
+&ehci1 {
+	status = "okay";
+};
+
+&ir {
+	pinctrl-names = "default";
+	pinctrl-0 = <&ir_pins_a>;
+	status = "okay";
+};
+
+&mmc0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
+	vmmc-supply = <&reg_vcc3v3>;
+	bus-width = <4>;
+	cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>; /* PF6 */
+	cd-inverted;
+	status = "okay";
+};
+
+&mmc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins_a>;
+	vmmc-supply = <&reg_vcc3v3>;
+	mmc-pwrseq = <&wifi_pwrseq>;
+	bus-width = <4>;
+	non-removable;
+	status = "okay";
+};
+
+&pio {
+	leds_opc: led_pins@0 {
+		allwinner,pins = "PA15";
+		allwinner,function = "gpio_out";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+};
+
+&r_pio {
+	leds_r_opc: led_pins@0 {
+		allwinner,pins = "PL10";
+		allwinner,function = "gpio_out";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+
+	sw_r_opc: key_pins@0 {
+		allwinner,pins = "PL3", "PL4";
+		allwinner,function = "gpio_in";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+
+	wifi_pwrseq_pin_orangepi: wifi_pwrseq_pin@0 {
+		allwinner,pins = "PL7";
+		allwinner,function = "gpio_out";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+};
+
+&reg_usb1_vbus {
+	gpio = <&pio 6 13 GPIO_ACTIVE_HIGH>;
+	status = "okay";
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins_a>;
+	status = "okay";
+};
+
+&usb1_vbus_pin_a {
+	allwinner,pins = "PG13";
+};
+
+&usbphy {
+	usb1_vbus-supply = <&reg_usb1_vbus>;
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts linux-libre-4.7-gnu/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2016 Hans de Goede <hdegoede@redhat.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "sun8i-h3.dtsi"
+#include "sunxi-common-regulators.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/pinctrl/sun4i-a10.h>
+
+/ {
+	model = "Xunlong Orange Pi One";
+	compatible = "xunlong,orangepi-one", "allwinner,sun8i-h3";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&leds_opc>, <&leds_r_opc>;
+
+		pwr_led {
+			label = "orangepi:green:pwr";
+			gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>;
+			default-state = "on";
+		};
+
+		status_led {
+			label = "orangepi:red:status";
+			gpios = <&pio 0 15 GPIO_ACTIVE_HIGH>;
+		};
+	};
+
+	r_gpio_keys {
+		compatible = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&sw_r_opc>;
+
+		sw4 {
+			label = "sw4";
+			linux,code = <BTN_0>;
+			gpios = <&r_pio 0 3 GPIO_ACTIVE_LOW>;
+		};
+	};
+};
+
+&ehci1 {
+	status = "okay";
+};
+
+&mmc0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
+	vmmc-supply = <&reg_vcc3v3>;
+	bus-width = <4>;
+	cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>; /* PF6 */
+	cd-inverted;
+	status = "okay";
+};
+
+&ohci1 {
+	status = "okay";
+};
+
+&pio {
+	leds_opc: led_pins@0 {
+		allwinner,pins = "PA15";
+		allwinner,function = "gpio_out";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+};
+
+&r_pio {
+	leds_r_opc: led_pins@0 {
+		allwinner,pins = "PL10";
+		allwinner,function = "gpio_out";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+
+	sw_r_opc: key_pins@0 {
+		allwinner,pins = "PL3";
+		allwinner,function = "gpio_in";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins_a>;
+	status = "okay";
+};
+
+&usbphy {
+	/* USB VBUS is always on */
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts linux-libre-4.7-gnu/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2015 Chen-Yu Tsai <wens@csie.org>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "sun8i-h3.dtsi"
+#include "sunxi-common-regulators.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/pinctrl/sun4i-a10.h>
+
+/ {
+	model = "Xunlong Orange Pi PC";
+	compatible = "xunlong,orangepi-pc", "allwinner,sun8i-h3";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&leds_opc>, <&leds_r_opc>;
+
+		pwr_led {
+			label = "orangepi:green:pwr";
+			gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>;
+			default-state = "on";
+		};
+
+		status_led {
+			label = "orangepi:red:status";
+			gpios = <&pio 0 15 GPIO_ACTIVE_HIGH>;
+		};
+	};
+
+	r_gpio_keys {
+		compatible = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&sw_r_opc>;
+
+		sw4 {
+			label = "sw4";
+			linux,code = <BTN_0>;
+			gpios = <&r_pio 0 3 GPIO_ACTIVE_LOW>;
+		};
+	};
+};
+
+&ehci1 {
+	status = "okay";
+};
+
+&ehci2 {
+	status = "okay";
+};
+
+&ehci3 {
+	status = "okay";
+};
+
+&ir {
+	pinctrl-names = "default";
+	pinctrl-0 = <&ir_pins_a>;
+	status = "okay";
+};
+
+&mmc0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
+	vmmc-supply = <&reg_vcc3v3>;
+	bus-width = <4>;
+	cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>; /* PF6 */
+	cd-inverted;
+	status = "okay";
+};
+
+&ohci1 {
+	status = "okay";
+};
+
+&ohci2 {
+	status = "okay";
+};
+
+&ohci3 {
+	status = "okay";
+};
+
+&pio {
+	leds_opc: led_pins@0 {
+		allwinner,pins = "PA15";
+		allwinner,function = "gpio_out";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+};
+
+&r_pio {
+	leds_r_opc: led_pins@0 {
+		allwinner,pins = "PL10";
+		allwinner,function = "gpio_out";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+
+	sw_r_opc: key_pins@0 {
+		allwinner,pins = "PL3";
+		allwinner,function = "gpio_in";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins_a>;
+	status = "okay";
+};
+
+&usbphy {
+	/* USB VBUS is always on */
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts linux-libre-4.7-gnu/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts	2016-07-24 15:23:50.000000000 -0400
@@ -40,95 +40,56 @@
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
-/dts-v1/;
-#include "sun8i-h3.dtsi"
-#include "sunxi-common-regulators.dtsi"
-
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/input/input.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
+/* The Orange Pi Plus is an extended version of the Orange Pi 2 */
+#include "sun8i-h3-orangepi-2.dts"
 
 / {
 	model = "Xunlong Orange Pi Plus";
 	compatible = "xunlong,orangepi-plus", "allwinner,sun8i-h3";
 
-	aliases {
-		serial0 = &uart0;
-	};
-
-	chosen {
-		stdout-path = "serial0:115200n8";
-	};
-
-	leds {
-		compatible = "gpio-leds";
+	reg_usb3_vbus: usb3-vbus {
+		compatible = "regulator-fixed";
 		pinctrl-names = "default";
-		pinctrl-0 = <&leds_opc>, <&leds_r_opc>;
-
-		status_led {
-			label = "orangepi-plus:red:status";
-			gpios = <&pio 0 15 GPIO_ACTIVE_HIGH>;
-		};
-
-		pwr_led {
-			label = "orangepi-plus:green:pwr";
-			gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>;
-			default-state = "on";
-		};
+		pinctrl-0 = <&usb3_vbus_pin_a>;
+		regulator-name = "usb3-vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-boot-on;
+		enable-active-high;
+		gpio = <&pio 6 11 GPIO_ACTIVE_HIGH>;
 	};
+};
 
-	r_gpio_keys {
-		compatible = "gpio-keys";
-		input-name = "sw4";
-
-		pinctrl-names = "default";
-		pinctrl-0 = <&sw_r_opc>;
+&ehci3 {
+	status = "okay";
+};
 
-		sw4@0 {
-			label = "sw4";
-			linux,code = <BTN_0>;
-			gpios = <&r_pio 0 3 GPIO_ACTIVE_LOW>;
-		};
-	};
+&mmc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc2_8bit_pins>;
+	vmmc-supply = <&reg_vcc3v3>;
+	bus-width = <8>;
+	non-removable;
+	cap-mmc-hw-reset;
+	status = "okay";
 };
 
-&pio {
-	leds_opc: led_pins@0 {
-		allwinner,pins = "PA15";
-		allwinner,function = "gpio_out";
-		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
-	};
+&mmc2_8bit_pins {
+	/* Increase drive strength for DDR modes */
+	allwinner,drive = <SUN4I_PINCTRL_40_MA>;
+	/* eMMC is missing pull-ups */
+	allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
 };
 
-&r_pio {
-	leds_r_opc: led_pins@0 {
-		allwinner,pins = "PL10";
+&pio {
+	usb3_vbus_pin_a: usb3_vbus_pin@0 {
+		allwinner,pins = "PG11";
 		allwinner,function = "gpio_out";
 		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
 		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
 	};
-
-	sw_r_opc: key_pins@0 {
-		allwinner,pins = "PL03";
-		allwinner,function = "gpio_in";
-		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
-	};
-};
-
-&mmc0 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
-	vmmc-supply = <&reg_vcc3v3>;
-	bus-width = <4>;
-	cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>; /* PF6 */
-	cd-inverted;
-	status = "okay";
 };
 
-&uart0 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&uart0_pins_a>;
-	status = "okay";
+&usbphy {
+	usb3_vbus-supply = <&reg_usb3_vbus>;
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/tango4-common.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/tango4-common.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/tango4-common.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/tango4-common.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -3,11 +3,13 @@
  * https://github.com/mansr/linux-tangox
  */
 
-#define CPU_CLK 0
-#define SYS_CLK 1
-
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 
+#define  CPU_CLK	0
+#define  SYS_CLK	1
+#define  USB_CLK	2
+#define SDIO_CLK	3
+
 / {
 	interrupt-parent = <&gic>;
 	#address-cells = <1>;
@@ -70,7 +72,7 @@
 
 		clkgen: clkgen@10000 {
 			compatible = "sigma,tango4-clkgen";
-			reg = <0x10000 0x40>;
+			reg = <0x10000 0x100>;
 			clocks = <&xtal>;
 			#clock-cells = <1>;
 		};
@@ -89,6 +91,12 @@
 			reg-shift = <2>;
 		};
 
+		watchdog@1fd00 {
+			compatible = "sigma,smp8759-wdt";
+			reg = <0x1fd00 8>;
+			clocks = <&xtal>;
+		};
+
 		eth0: ethernet@26000 {
 			compatible = "sigma,smp8734-ethernet";
 			reg = <0x26000 0x800>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/tango4-smp8758.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/tango4-smp8758.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/tango4-smp8758.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/tango4-smp8758.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -1,4 +1,4 @@
-#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "tango4-common.dtsi"
 
 / {
 	cpus {
@@ -11,6 +11,9 @@
 			next-level-cache = <&l2cc>;
 			device_type = "cpu";
 			reg = <0>;
+			clocks = <&clkgen CPU_CLK>;
+			clock-latency = <1>;
+			operating-points = <1215000 0 607500 0 405000 0 243000 0 135000 0>;
 		};
 
 		cpu1: cpu@1 {
@@ -28,4 +31,27 @@
 			<GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
 			<GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
 	};
+
+	soc {
+		cpu_temp: thermal@920100 {
+			#thermal-sensor-cells = <0>;
+			compatible = "sigma,smp8758-thermal";
+			reg = <0x920100 12>;
+		};
+	};
+
+	thermal-zones {
+		cpu_thermal: cpu-thermal {
+			polling-delay = <997>;		/* milliseconds */
+			polling-delay-passive = <499>;	/* milliseconds */
+			thermal-sensors = <&cpu_temp>;
+			trips {
+				cpu_critical {
+					temperature = <120000>;
+					hysteresis = <2500>;
+					type = "critical";
+				};
+			};
+		};
+	};
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/tango4-vantage-1172.dts linux-libre-4.7-gnu/arch/arm/boot/dts/tango4-vantage-1172.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/tango4-vantage-1172.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/tango4-vantage-1172.dts	2016-07-24 15:23:50.000000000 -0400
@@ -1,7 +1,6 @@
 /dts-v1/;
 
 #include "tango4-smp8758.dtsi"
-#include "tango4-common.dtsi"
 
 / {
 	model = "Sigma Designs SMP8758 Vantage-1172 Rev E1";
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/tegra114-dalmore.dts linux-libre-4.7-gnu/arch/arm/boot/dts/tegra114-dalmore.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/tegra114-dalmore.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/tegra114-dalmore.dts	2016-07-24 15:23:50.000000000 -0400
@@ -18,6 +18,10 @@
 		serial0 = &uartd;
 	};
 
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
 	memory {
 		reg = <0x80000000 0x40000000>;
 	};
@@ -1164,7 +1168,7 @@
 			label = "Power";
 			gpios = <&gpio TEGRA_GPIO(Q, 0) GPIO_ACTIVE_LOW>;
 			linux,code = <KEY_POWER>;
-			gpio-key,wakeup;
+			wakeup-source;
 		};
 
 		volume_down {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/tegra114.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/tegra114.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/tegra114.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/tegra114.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -150,7 +150,7 @@
 	};
 
 	timer@60005000 {
-		compatible = "nvidia,tegra114-timer", "nvidia,tegra20-timer";
+		compatible = "nvidia,tegra114-timer", "nvidia,tegra30-timer", "nvidia,tegra20-timer";
 		reg = <0x60005000 0x400>;
 		interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
 			     <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>,
@@ -256,7 +256,7 @@
 	 * driver and APB DMA based serial driver for higher baudrate
 	 * and performace. To enable the 8250 based driver, the compatible
 	 * is "nvidia,tegra114-uart", "nvidia,tegra20-uart" and to enable
-	 * the APB DMA based serial driver, the comptible is
+	 * the APB DMA based serial driver, the compatible is
 	 * "nvidia,tegra114-hsuart", "nvidia,tegra30-hsuart".
 	 */
 	uarta: serial@70006000 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/tegra114-roth.dts linux-libre-4.7-gnu/arch/arm/boot/dts/tegra114-roth.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/tegra114-roth.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/tegra114-roth.dts	2016-07-24 15:23:50.000000000 -0400
@@ -1047,7 +1047,7 @@
 			label = "Power";
 			gpios = <&gpio TEGRA_GPIO(Q, 0) GPIO_ACTIVE_LOW>;
 			linux,code = <KEY_POWER>;
-			gpio-key,wakeup;
+			wakeup-source;
 		};
 	};
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/tegra114-tn7.dts linux-libre-4.7-gnu/arch/arm/boot/dts/tegra114-tn7.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/tegra114-tn7.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/tegra114-tn7.dts	2016-07-24 15:23:50.000000000 -0400
@@ -292,7 +292,7 @@
 			label = "Power";
 			gpios = <&gpio TEGRA_GPIO(Q, 0) GPIO_ACTIVE_LOW>;
 			linux,code = <KEY_POWER>;
-			gpio-key,wakeup;
+			wakeup-source;
 		};
 
 		volume_down {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/tegra124.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/tegra124.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/tegra124.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/tegra124.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -2,7 +2,6 @@
 #include <dt-bindings/gpio/tegra-gpio.h>
 #include <dt-bindings/memory/tegra124-mc.h>
 #include <dt-bindings/pinctrl/pinctrl-tegra.h>
-#include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/reset/tegra124-car.h>
 #include <dt-bindings/thermal/tegra124-soctherm.h>
@@ -51,9 +50,6 @@
 		reset-names = "pex", "afi", "pcie_x";
 		status = "disabled";
 
-		phys = <&padctl TEGRA_XUSB_PADCTL_PCIE>;
-		phy-names = "pcie";
-
 		pci@1,0 {
 			device_type = "pci";
 			assigned-addresses = <0x82000800 0 0x01000000 0 0x1000>;
@@ -208,7 +204,7 @@
 	};
 
 	timer@0,60005000 {
-		compatible = "nvidia,tegra124-timer", "nvidia,tegra20-timer";
+		compatible = "nvidia,tegra124-timer", "nvidia,tegra30-timer", "nvidia,tegra20-timer";
 		reg = <0x0 0x60005000 0x0 0x400>;
 		interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
 			     <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>,
@@ -322,7 +318,7 @@
 	 * driver and APB DMA based serial driver for higher baudrate
 	 * and performace. To enable the 8250 based driver, the compatible
 	 * is "nvidia,tegra124-uart", "nvidia,tegra20-uart" and to enable
-	 * the APB DMA based serial driver, the comptible is
+	 * the APB DMA based serial driver, the compatible is
 	 * "nvidia,tegra124-hsuart", "nvidia,tegra30-hsuart".
 	 */
 	uarta: serial@0,70006000 {
@@ -622,8 +618,6 @@
 			 <&tegra_car 123>,
 			 <&tegra_car 129>;
 		reset-names = "sata", "sata-oob", "sata-cold";
-		phys = <&padctl TEGRA_XUSB_PADCTL_SATA>;
-		phy-names = "sata-phy";
 		status = "disabled";
 	};
 
@@ -642,13 +636,172 @@
 		status = "disabled";
 	};
 
+	usb@0,70090000 {
+		compatible = "nvidia,tegra124-xusb";
+		reg = <0x0 0x70090000 0x0 0x8000>,
+		      <0x0 0x70098000 0x0 0x1000>,
+		      <0x0 0x70099000 0x0 0x1000>;
+		reg-names = "hcd", "fpci", "ipfs";
+
+		interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+
+		clocks = <&tegra_car TEGRA124_CLK_XUSB_HOST>,
+			 <&tegra_car TEGRA124_CLK_XUSB_HOST_SRC>,
+			 <&tegra_car TEGRA124_CLK_XUSB_FALCON_SRC>,
+			 <&tegra_car TEGRA124_CLK_XUSB_SS>,
+			 <&tegra_car TEGRA124_CLK_XUSB_SS_DIV2>,
+			 <&tegra_car TEGRA124_CLK_XUSB_SS_SRC>,
+			 <&tegra_car TEGRA124_CLK_XUSB_HS_SRC>,
+			 <&tegra_car TEGRA124_CLK_XUSB_FS_SRC>,
+			 <&tegra_car TEGRA124_CLK_PLL_U_480M>,
+			 <&tegra_car TEGRA124_CLK_CLK_M>,
+			 <&tegra_car TEGRA124_CLK_PLL_E>;
+		clock-names = "xusb_host", "xusb_host_src",
+			      "xusb_falcon_src", "xusb_ss",
+			      "xusb_ss_div2", "xusb_ss_src",
+			      "xusb_hs_src", "xusb_fs_src",
+			      "pll_u_480m", "clk_m", "pll_e";
+		resets = <&tegra_car 89>, <&tegra_car 156>,
+			 <&tegra_car 143>;
+		reset-names = "xusb_host", "xusb_ss", "xusb_src";
+
+		nvidia,xusb-padctl = <&padctl>;
+
+		status = "disabled";
+	};
+
 	padctl: padctl@0,7009f000 {
 		compatible = "nvidia,tegra124-xusb-padctl";
 		reg = <0x0 0x7009f000 0x0 0x1000>;
 		resets = <&tegra_car 142>;
 		reset-names = "padctl";
 
-		#phy-cells = <1>;
+		pads {
+			usb2 {
+				status = "disabled";
+
+				lanes {
+					usb2-0 {
+						status = "disabled";
+						#phy-cells = <0>;
+					};
+
+					usb2-1 {
+						status = "disabled";
+						#phy-cells = <0>;
+					};
+
+					usb2-2 {
+						status = "disabled";
+						#phy-cells = <0>;
+					};
+				};
+			};
+
+			ulpi {
+				status = "disabled";
+
+				lanes {
+					ulpi-0 {
+						status = "disabled";
+						#phy-cells = <0>;
+					};
+				};
+			};
+
+			hsic {
+				status = "disabled";
+
+				lanes {
+					hsic-0 {
+						status = "disabled";
+						#phy-cells = <0>;
+					};
+
+					hsic-1 {
+						status = "disabled";
+						#phy-cells = <0>;
+					};
+				};
+			};
+
+			pcie {
+				status = "disabled";
+
+				lanes {
+					pcie-0 {
+						status = "disabled";
+						#phy-cells = <0>;
+					};
+
+					pcie-1 {
+						status = "disabled";
+						#phy-cells = <0>;
+					};
+
+					pcie-2 {
+						status = "disabled";
+						#phy-cells = <0>;
+					};
+
+					pcie-3 {
+						status = "disabled";
+						#phy-cells = <0>;
+					};
+
+					pcie-4 {
+						status = "disabled";
+						#phy-cells = <0>;
+					};
+				};
+			};
+
+			sata {
+				status = "disabled";
+
+				lanes {
+					sata-0 {
+						status = "disabled";
+						#phy-cells = <0>;
+					};
+				};
+			};
+		};
+
+		ports {
+			usb2-0 {
+				status = "disabled";
+			};
+
+			usb2-1 {
+				status = "disabled";
+			};
+
+			usb2-2 {
+				status = "disabled";
+			};
+
+			ulpi-0 {
+				status = "disabled";
+			};
+
+			hsic-0 {
+				status = "disabled";
+			};
+
+			hsic-1 {
+				status = "disabled";
+			};
+
+			usb3-0 {
+				status = "disabled";
+			};
+
+			usb3-1 {
+				status = "disabled";
+			};
+		};
 	};
 
 	sdhci@0,700b0000 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/tegra124-jetson-tk1.dts linux-libre-4.7-gnu/arch/arm/boot/dts/tegra124-jetson-tk1.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/tegra124-jetson-tk1.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/tegra124-jetson-tk1.dts	2016-07-24 15:23:50.000000000 -0400
@@ -12,7 +12,15 @@
 	aliases {
 		rtc0 = "/i2c@0,7000d000/pmic@40";
 		rtc1 = "/rtc@0,7000e000";
+
+		/* This order keeps the mapping DB9 connector <-> ttyS0 */
 		serial0 = &uartd;
+		serial1 = &uarta;
+		serial2 = &uartb;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
 	};
 
 	memory {
@@ -30,11 +38,17 @@
 		vddio-pex-ctl-supply = <&vdd_3v3_lp0>;
 		avdd-pll-erefe-supply = <&avdd_1v05_run>;
 
+		/* Mini PCIe */
 		pci@1,0 {
+			phys = <&{/padctl@0,7009f000/pads/pcie/lanes/pcie-4}>;
+			phy-names = "pcie-0";
 			status = "okay";
 		};
 
+		/* Gigabit Ethernet */
 		pci@2,0 {
+			phys = <&{/padctl@0,7009f000/pads/pcie/lanes/pcie-2}>;
+			phy-names = "pcie-0";
 			status = "okay";
 		};
 	};
@@ -1367,6 +1381,28 @@
 		};
 	};
 
+	/*
+	 * First high speed UART, exposed on the expansion connector J3A2
+	 *   Pin 41: BR_UART1_TXD
+	 *   Pin 44: BR_UART1_RXD
+	 */
+	serial@70006000 {
+		compatible = "nvidia,tegra124-hsuart", "nvidia,tegra30-hsuart";
+		status = "okay";
+	};
+
+	/*
+	 * Second high speed UART, exposed on the expansion connector J3A2
+	 *   Pin 65: UART2_RXD
+	 *   Pin 68: UART2_TXD
+	 *   Pin 71: UART2_CTS_L
+	 *   Pin 74: UART2_RTS_L
+	 */
+	serial@70006040 {
+		compatible = "nvidia,tegra124-hsuart", "nvidia,tegra30-hsuart";
+		status = "okay";
+	};
+
 	/* DB9 serial port */
 	serial@0,70006300 {
 		status = "okay";
@@ -1647,6 +1683,9 @@
 	sata@0,70020000 {
 		status = "okay";
 
+		phys = <&{/padctl@0,7009f000/pads/sata/lanes/sata-0}>;
+		phy-names = "sata-0";
+
 		hvdd-supply = <&vdd_3v3_lp0>;
 		vddio-supply = <&vdd_1v05_run>;
 		avdd-supply = <&vdd_1v05_run>;
@@ -1659,28 +1698,107 @@
 		status = "okay";
 	};
 
+	usb@0,70090000 {
+		phys = <&{/padctl@0,7009f000/pads/usb2/lanes/usb2-0}>, /* Micro A/B */
+		       <&{/padctl@0,7009f000/pads/usb2/lanes/usb2-1}>, /* Mini PCIe */
+		       <&{/padctl@0,7009f000/pads/usb2/lanes/usb2-2}>, /* USB3 */
+		       <&{/padctl@0,7009f000/pads/pcie/lanes/pcie-0}>; /* USB3 */
+		phy-names = "usb2-0", "usb2-1", "usb2-2", "usb3-0";
+
+		avddio-pex-supply = <&vdd_1v05_run>;
+		dvddio-pex-supply = <&vdd_1v05_run>;
+		avdd-usb-supply = <&vdd_3v3_lp0>;
+		avdd-pll-utmip-supply = <&vddio_1v8>;
+		avdd-pll-erefe-supply = <&avdd_1v05_run>;
+		avdd-usb-ss-pll-supply = <&vdd_1v05_run>;
+		hvdd-usb-ss-supply = <&vdd_3v3_lp0>;
+		hvdd-usb-ss-pll-e-supply = <&vdd_3v3_lp0>;
+
+		status = "okay";
+	};
+
 	padctl@0,7009f000 {
-		pinctrl-0 = <&padctl_default>;
-		pinctrl-names = "default";
+		status = "okay";
 
-		padctl_default: pinmux {
-			usb3 {
-				nvidia,lanes = "pcie-0", "pcie-1";
-				nvidia,function = "usb3";
-				nvidia,iddq = <0>;
+		pads {
+			usb2 {
+				status = "okay";
+
+				lanes {
+					usb2-0 {
+						nvidia,function = "xusb";
+						status = "okay";
+					};
+
+					usb2-1 {
+						nvidia,function = "xusb";
+						status = "okay";
+					};
+
+					usb2-2 {
+						nvidia,function = "xusb";
+						status = "okay";
+					};
+				};
 			};
 
 			pcie {
-				nvidia,lanes = "pcie-2", "pcie-3",
-					       "pcie-4";
-				nvidia,function = "pcie";
-				nvidia,iddq = <0>;
+				status = "okay";
+
+				lanes {
+					pcie-0 {
+						nvidia,function = "usb3-ss";
+						status = "okay";
+					};
+
+					pcie-2 {
+						nvidia,function = "pcie";
+						status = "okay";
+					};
+
+					pcie-4 {
+						nvidia,function = "pcie";
+						status = "okay";
+					};
+				};
 			};
 
 			sata {
-				nvidia,lanes = "sata-0";
-				nvidia,function = "sata";
-				nvidia,iddq = <0>;
+				status = "okay";
+
+				lanes {
+					sata-0 {
+						nvidia,function = "sata";
+						status = "okay";
+					};
+				};
+			};
+		};
+
+		ports {
+			/* Micro A/B */
+			usb2-0 {
+				status = "okay";
+				mode = "otg";
+			};
+
+			/* Mini PCIe */
+			usb2-1 {
+				status = "okay";
+				mode = "host";
+			};
+
+			/* USB3 */
+			usb2-2 {
+				status = "okay";
+				mode = "host";
+
+				vbus-supply = <&vdd_usb3_vbus>;
+			};
+
+			usb3-0 {
+				nvidia,usb2-companion = <2>;
+				status = "okay";
 			};
 		};
 	};
@@ -1761,7 +1879,7 @@
 			gpios = <&gpio TEGRA_GPIO(Q, 0) GPIO_ACTIVE_LOW>;
 			linux,code = <KEY_POWER>;
 			debounce-interval = <10>;
-			gpio-key,wakeup;
+			wakeup-source;
 		};
 	};
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/tegra124-nyan.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/tegra124-nyan.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/tegra124-nyan.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/tegra124-nyan.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -8,6 +8,10 @@
 		serial0 = &uarta;
 	};
 
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
 	memory {
 		reg = <0x0 0x80000000 0x0 0x80000000>;
 	};
@@ -220,7 +224,7 @@
 					regulator-always-on;
 				};
 
-				ldo0 {
+				avdd_1v05_run: ldo0 {
 					regulator-name = "+1.05V_RUN_AVDD";
 					regulator-min-microvolt = <1050000>;
 					regulator-max-microvolt = <1050000>;
@@ -364,6 +368,99 @@
 		status = "okay";
 	};
 
+	usb@0,70090000 {
+		phys = <&{/padctl@0,7009f000/pads/usb2/lanes/usb2-0}>, /* 1st USB A */
+		       <&{/padctl@0,7009f000/pads/usb2/lanes/usb2-1}>, /* Internal USB */
+		       <&{/padctl@0,7009f000/pads/usb2/lanes/usb2-2}>, /* 2nd USB A */
+		       <&{/padctl@0,7009f000/pads/pcie/lanes/pcie-0}>, /* 1st USB A */
+		       <&{/padctl@0,7009f000/pads/pcie/lanes/pcie-1}>; /* 2nd USB A */
+		phy-names = "usb2-0", "usb2-1", "usb2-2", "usb3-0", "usb3-1";
+
+		avddio-pex-supply = <&vdd_1v05_run>;
+		dvddio-pex-supply = <&vdd_1v05_run>;
+		avdd-usb-supply = <&vdd_3v3_lp0>;
+		avdd-pll-utmip-supply = <&vddio_1v8>;
+		avdd-pll-erefe-supply = <&avdd_1v05_run>;
+		avdd-usb-ss-pll-supply = <&vdd_1v05_run>;
+		hvdd-usb-ss-supply = <&vdd_3v3_lp0>;
+		hvdd-usb-ss-pll-e-supply = <&vdd_3v3_lp0>;
+
+		status = "okay";
+	};
+
+	padctl@0,7009f000 {
+		status = "okay";
+
+		pads {
+			usb2 {
+				status = "okay";
+
+				lanes {
+					usb2-0 {
+						nvidia,function = "xusb";
+						status = "okay";
+					};
+
+					usb2-1 {
+						nvidia,function = "xusb";
+						status = "okay";
+					};
+
+					usb2-2 {
+						nvidia,function = "xusb";
+						status = "okay";
+					};
+				};
+			};
+
+			pcie {
+				status = "okay";
+
+				lanes {
+					pcie-0 {
+						nvidia,function = "usb3-ss";
+						status = "okay";
+					};
+
+					pcie-1 {
+						nvidia,function = "usb3-ss";
+						status = "okay";
+					};
+				};
+			};
+		};
+
+		ports {
+			usb2-0 {
+				vbus-supply = <&vdd_usb1_vbus>;
+				status = "okay";
+				mode = "otg";
+			};
+
+			usb2-1 {
+				vbus-supply = <&vdd_run_cam>;
+				status = "okay";
+				mode = "host";
+			};
+
+			usb2-2 {
+				vbus-supply = <&vdd_usb3_vbus>;
+				status = "okay";
+				mode = "host";
+			};
+
+			usb3-0 {
+				nvidia,usb2-companion = <0>;
+				status = "okay";
+			};
+
+			usb3-1 {
+				nvidia,usb2-companion = <1>;
+				status = "okay";
+			};
+		};
+	};
+
 	sdhci0_pwrseq: sdhci0_pwrseq {
 		compatible = "mmc-pwrseq-simple";
 
@@ -410,33 +507,6 @@
 		};
 	};
 
-	usb@0,7d000000 { /* Rear external USB port. */
-		status = "okay";
-	};
-
-	usb-phy@0,7d000000 {
-		status = "okay";
-		vbus-supply = <&vdd_usb1_vbus>;
-	};
-
-	usb@0,7d004000 { /* Internal webcam. */
-		status = "okay";
-	};
-
-	usb-phy@0,7d004000 {
-		status = "okay";
-		vbus-supply = <&vdd_run_cam>;
-	};
-
-	usb@0,7d008000 { /* Left external USB port. */
-		status = "okay";
-	};
-
-	usb-phy@0,7d008000 {
-		status = "okay";
-		vbus-supply = <&vdd_usb3_vbus>;
-	};
-
 	backlight: backlight {
 		compatible = "pwm-backlight";
 
@@ -509,7 +579,7 @@
 			linux,input-type = <5>;
 			linux,code = <KEY_RESERVED>;
 			debounce-interval = <1>;
-			gpio-key,wakeup;
+			wakeup-source;
 		};
 
 		power {
@@ -517,7 +587,7 @@
 			gpios = <&gpio TEGRA_GPIO(Q, 0) GPIO_ACTIVE_LOW>;
 			linux,code = <KEY_POWER>;
 			debounce-interval = <30>;
-			gpio-key,wakeup;
+			wakeup-source;
 		};
 	};
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/tegra124-venice2.dts linux-libre-4.7-gnu/arch/arm/boot/dts/tegra124-venice2.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/tegra124-venice2.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/tegra124-venice2.dts	2016-07-24 15:23:50.000000000 -0400
@@ -13,6 +13,10 @@
 		serial0 = &uarta;
 	};
 
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
 	memory {
 		reg = <0x0 0x80000000 0x0 0x80000000>;
 	};
@@ -753,7 +757,7 @@
 					regulator-always-on;
 				};
 
-				ldo0 {
+				avdd_1v05_run: ldo0 {
 					regulator-name = "+1.05V_RUN_AVDD";
 					regulator-min-microvolt = <1050000>;
 					regulator-max-microvolt = <1050000>;
@@ -895,6 +899,105 @@
 		status = "okay";
 	};
 
+	usb@0,70090000 {
+		phys = <&{/padctl@0,7009f000/pads/usb2/lanes/usb2-0}>, /* 1st USB A */
+		       <&{/padctl@0,7009f000/pads/usb2/lanes/usb2-1}>, /* Internal USB */
+		       <&{/padctl@0,7009f000/pads/usb2/lanes/usb2-2}>, /* 2nd USB A */
+		       <&{/padctl@0,7009f000/pads/pcie/lanes/pcie-0}>, /* 1st USB A */
+		       <&{/padctl@0,7009f000/pads/pcie/lanes/pcie-1}>; /* 2nd USB A */
+		phy-names = "usb2-0", "usb2-1", "usb2-2", "usb3-0", "usb3-1";
+
+		avddio-pex-supply = <&vdd_1v05_run>;
+		dvddio-pex-supply = <&vdd_1v05_run>;
+		avdd-usb-supply = <&vdd_3v3_lp0>;
+		avdd-pll-utmip-supply = <&vddio_1v8>;
+		avdd-pll-erefe-supply = <&avdd_1v05_run>;
+		avdd-usb-ss-pll-supply = <&vdd_1v05_run>;
+		hvdd-usb-ss-supply = <&vdd_3v3_lp0>;
+		hvdd-usb-ss-pll-e-supply = <&vdd_3v3_lp0>;
+
+		status = "okay";
+	};
+
+	padctl@0,7009f000 {
+		pads {
+			usb2 {
+				status = "okay";
+
+				lanes {
+					usb2-0 {
+						nvidia,function = "xusb";
+						status = "okay";
+					};
+
+					usb2-1 {
+						nvidia,function = "xusb";
+						status = "okay";
+					};
+
+					usb2-2 {
+						nvidia,function = "xusb";
+						status = "okay";
+					};
+				};
+			};
+
+			pcie {
+				status = "okay";
+
+				lanes {
+					pcie-0 {
+						nvidia,function = "usb3-ss";
+						status = "okay";
+					};
+
+					pcie-1 {
+						nvidia,function = "usb3-ss";
+						status = "okay";
+					};
+
+					pcie-1 {
+						nvidia,function = "usb3-ss";
+						status = "okay";
+					};
+				};
+			};
+		};
+
+		ports {
+			usb2-0 {
+				status = "okay";
+				mode = "otg";
+
+				vbus-supply = <&vdd_usb1_vbus>;
+			};
+
+			usb2-1 {
+				status = "okay";
+				mode = "host";
+
+				vbus-supply = <&vdd_run_cam>;
+			};
+
+			usb2-2 {
+				status = "okay";
+				mode = "host";
+
+				vbus-supply = <&vdd_usb3_vbus>;
+			};
+
+			usb3-0 {
+				nvidia,usb2-companion = <0>;
+				status = "okay";
+			};
+
+			usb3-1 {
+				nvidia,usb2-companion = <2>;
+				status = "okay";
+			};
+		};
+	};
+
 	sdhci@0,700b0400 {
 		cd-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_HIGH>;
 		power-gpios = <&gpio TEGRA_GPIO(R, 0) GPIO_ACTIVE_HIGH>;
@@ -975,7 +1078,7 @@
 			gpios = <&gpio TEGRA_GPIO(Q, 0) GPIO_ACTIVE_LOW>;
 			linux,code = <KEY_POWER>;
 			debounce-interval = <10>;
-			gpio-key,wakeup;
+			wakeup-source;
 		};
 	};
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/tegra20.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/tegra20.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/tegra20.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/tegra20.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -145,7 +145,7 @@
 		interrupt-parent = <&intc>;
 		reg = <0x50040600 0x20>;
 		interrupts = <GIC_PPI 13
-			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
+			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_EDGE_RISING)>;
 		clocks = <&tegra_car TEGRA20_CLK_TWD>;
 	};
 
@@ -309,7 +309,7 @@
 	 * driver and APB DMA based serial driver for higher baudrate
 	 * and performace. To enable the 8250 based driver, the compatible
 	 * is "nvidia,tegra20-uart" and to enable the APB DMA based serial
-	 * driver, the comptible is "nvidia,tegra20-hsuart".
+	 * driver, the compatible is "nvidia,tegra20-hsuart".
 	 */
 	uarta: serial@70006000 {
 		compatible = "nvidia,tegra20-uart";
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/tegra20-harmony.dts linux-libre-4.7-gnu/arch/arm/boot/dts/tegra20-harmony.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/tegra20-harmony.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/tegra20-harmony.dts	2016-07-24 15:23:50.000000000 -0400
@@ -13,6 +13,10 @@
 		serial0 = &uartd;
 	};
 
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
 	memory {
 		reg = <0x00000000 0x40000000>;
 	};
@@ -655,7 +659,7 @@
 			label = "Power";
 			gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_LOW>;
 			linux,code = <KEY_POWER>;
-			gpio-key,wakeup;
+			wakeup-source;
 		};
 	};
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/tegra20-iris-512.dts linux-libre-4.7-gnu/arch/arm/boot/dts/tegra20-iris-512.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/tegra20-iris-512.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/tegra20-iris-512.dts	2016-07-24 15:23:50.000000000 -0400
@@ -11,6 +11,10 @@
 		serial1 = &uartd;
 	};
 
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
 	host1x@50000000 {
 		hdmi@54280000 {
 			status = "okay";
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/tegra20-medcom-wide.dts linux-libre-4.7-gnu/arch/arm/boot/dts/tegra20-medcom-wide.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/tegra20-medcom-wide.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/tegra20-medcom-wide.dts	2016-07-24 15:23:50.000000000 -0400
@@ -10,6 +10,10 @@
 		serial0 = &uartd;
 	};
 
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
 	pwm@7000a000 {
 		status = "okay";
 	};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/tegra20-paz00.dts linux-libre-4.7-gnu/arch/arm/boot/dts/tegra20-paz00.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/tegra20-paz00.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/tegra20-paz00.dts	2016-07-24 15:23:50.000000000 -0400
@@ -14,6 +14,10 @@
 		serial1 = &uartc;
 	};
 
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
 	memory {
 		reg = <0x00000000 0x20000000>;
 	};
@@ -521,7 +525,7 @@
 			label = "Power";
 			gpios = <&gpio TEGRA_GPIO(J, 7) GPIO_ACTIVE_LOW>;
 			linux,code = <KEY_POWER>;
-			gpio-key,wakeup;
+			wakeup-source;
 		};
 	};
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/tegra20-seaboard.dts linux-libre-4.7-gnu/arch/arm/boot/dts/tegra20-seaboard.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/tegra20-seaboard.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/tegra20-seaboard.dts	2016-07-24 15:23:50.000000000 -0400
@@ -13,6 +13,10 @@
 		serial0 = &uartd;
 	};
 
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
 	memory {
 		reg = <0x00000000 0x40000000>;
 	};
@@ -807,7 +811,7 @@
 			label = "Power";
 			gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_LOW>;
 			linux,code = <KEY_POWER>;
-			gpio-key,wakeup;
+			wakeup-source;
 		};
 
 		lid {
@@ -816,7 +820,7 @@
 			linux,input-type = <5>; /* EV_SW */
 			linux,code = <0>; /* SW_LID */
 			debounce-interval = <1>;
-			gpio-key,wakeup;
+			wakeup-source;
 		};
 	};
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/tegra20-tamonten.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/tegra20-tamonten.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/tegra20-tamonten.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/tegra20-tamonten.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -10,6 +10,10 @@
 		serial0 = &uartd;
 	};
 
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
 	memory {
 		reg = <0x00000000 0x20000000>;
 	};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/tegra20-trimslice.dts linux-libre-4.7-gnu/arch/arm/boot/dts/tegra20-trimslice.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/tegra20-trimslice.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/tegra20-trimslice.dts	2016-07-24 15:23:50.000000000 -0400
@@ -13,6 +13,10 @@
 		serial0 = &uarta;
 	};
 
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
 	memory {
 		reg = <0x00000000 0x40000000>;
 	};
@@ -392,7 +396,7 @@
 			label = "Power";
 			gpios = <&gpio TEGRA_GPIO(X, 6) GPIO_ACTIVE_LOW>;
 			linux,code = <KEY_POWER>;
-			gpio-key,wakeup;
+			wakeup-source;
 		};
 	};
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/tegra20-ventana.dts linux-libre-4.7-gnu/arch/arm/boot/dts/tegra20-ventana.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/tegra20-ventana.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/tegra20-ventana.dts	2016-07-24 15:23:50.000000000 -0400
@@ -13,6 +13,10 @@
 		serial0 = &uartd;
 	};
 
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
 	memory {
 		reg = <0x00000000 0x40000000>;
 	};
@@ -601,7 +605,7 @@
 			label = "Power";
 			gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_LOW>;
 			linux,code = <KEY_POWER>;
-			gpio-key,wakeup;
+			wakeup-source;
 		};
 	};
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/tegra20-whistler.dts linux-libre-4.7-gnu/arch/arm/boot/dts/tegra20-whistler.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/tegra20-whistler.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/tegra20-whistler.dts	2016-07-24 15:23:50.000000000 -0400
@@ -13,6 +13,10 @@
 		serial0 = &uarta;
 	};
 
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
 	memory {
 		reg = <0x00000000 0x20000000>;
 	};
@@ -508,7 +512,7 @@
 		nvidia,repeat-delay-ms = <160>;
 		nvidia,kbc-row-pins = <0 1 2>;
 		nvidia,kbc-col-pins = <16 17>;
-		nvidia,wakeup-source;
+		wakeup-source;
 		linux,keymap = <MATRIX_KEY(0x00, 0x00, KEY_POWER)
 				MATRIX_KEY(0x01, 0x00, KEY_HOME)
 				MATRIX_KEY(0x01, 0x01, KEY_BACK)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/tegra30-apalis-eval.dts linux-libre-4.7-gnu/arch/arm/boot/dts/tegra30-apalis-eval.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/tegra30-apalis-eval.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/tegra30-apalis-eval.dts	2016-07-24 15:23:50.000000000 -0400
@@ -17,6 +17,10 @@
 		serial3 = &uartd;
 	};
 
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
 	pcie-controller@00003000 {
 		status = "okay";
 
@@ -196,7 +200,7 @@
 			gpios = <&gpio TEGRA_GPIO(V, 1) GPIO_ACTIVE_LOW>;
 			linux,code = <KEY_WAKEUP>;
 			debounce-interval = <10>;
-			gpio-key,wakeup;
+			wakeup-source;
 		};
 	};
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/tegra30-beaver.dts linux-libre-4.7-gnu/arch/arm/boot/dts/tegra30-beaver.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/tegra30-beaver.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/tegra30-beaver.dts	2016-07-24 15:23:50.000000000 -0400
@@ -12,6 +12,10 @@
 		serial0 = &uarta;
 	};
 
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
 	memory {
 		reg = <0x80000000 0x7ff00000>;
 	};
@@ -1839,7 +1843,7 @@
 
 				ldo5_reg: ldo5 {
 					regulator-name = "vddio_sdmmc,avdd_vdac";
-					regulator-min-microvolt = <3300000>;
+					regulator-min-microvolt = <1800000>;
 					regulator-max-microvolt = <3300000>;
 					regulator-always-on;
 				};
@@ -1910,6 +1914,7 @@
 
 	sdhci@78000000 {
 		status = "okay";
+		vqmmc-supply = <&ldo5_reg>;
 		cd-gpios = <&gpio TEGRA_GPIO(I, 5) GPIO_ACTIVE_LOW>;
 		wp-gpios = <&gpio TEGRA_GPIO(T, 3) GPIO_ACTIVE_HIGH>;
 		power-gpios = <&gpio TEGRA_GPIO(D, 7) GPIO_ACTIVE_HIGH>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/tegra30-cardhu.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/tegra30-cardhu.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/tegra30-cardhu.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/tegra30-cardhu.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -35,6 +35,10 @@
 		serial1 = &uartc;
 	};
 
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
 	memory {
 		reg = <0x80000000 0x40000000>;
 	};
@@ -626,7 +630,7 @@
 			interrupts = <2 0>;
 			linux,code = <KEY_POWER>;
 			debounce-interval = <100>;
-			gpio-key,wakeup;
+			wakeup-source;
 		};
 
 		volume-down {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/tegra30-colibri-eval-v3.dts linux-libre-4.7-gnu/arch/arm/boot/dts/tegra30-colibri-eval-v3.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/tegra30-colibri-eval-v3.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/tegra30-colibri-eval-v3.dts	2016-07-24 15:23:50.000000000 -0400
@@ -15,6 +15,10 @@
 		serial2 = &uartd;
 	};
 
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
 	host1x@50000000 {
 		dc@54200000 {
 			rgb {
@@ -142,7 +146,7 @@
 			gpios = <&gpio TEGRA_GPIO(V, 1) GPIO_ACTIVE_HIGH>;
 			linux,code = <KEY_WAKEUP>;
 			debounce-interval = <10>;
-			gpio-key,wakeup;
+			wakeup-source;
 		};
 	};
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/tegra30.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/tegra30.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/tegra30.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/tegra30.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -230,7 +230,7 @@
 		reg = <0x50040600 0x20>;
 		interrupt-parent = <&intc>;
 		interrupts = <GIC_PPI 13
-			(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+			(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_EDGE_RISING)>;
 		clocks = <&tegra_car TEGRA30_CLK_TWD>;
 	};
 
@@ -371,7 +371,7 @@
 	 * driver and APB DMA based serial driver for higher baudrate
 	 * and performace. To enable the 8250 based driver, the compatible
 	 * is "nvidia,tegra30-uart", "nvidia,tegra20-uart" and to enable
-	 * the APB DMA based serial driver, the comptible is
+	 * the APB DMA based serial driver, the compatible is
 	 * "nvidia,tegra30-hsuart", "nvidia,tegra20-hsuart".
 	 */
 	uarta: serial@70006000 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/twl6030.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/twl6030.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/twl6030.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/twl6030.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -99,4 +99,10 @@
 		compatible = "ti,twl6030-pwmled";
 		#pwm-cells = <2>;
 	};
+
+	gpadc {
+		compatible = "ti,twl6030-gpadc";
+		interrupts = <3>;
+		#io-channel-cells = <1>;
+	};
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/uniphier-pinctrl.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/uniphier-pinctrl.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/uniphier-pinctrl.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/uniphier-pinctrl.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -68,6 +68,16 @@
 		function = "i2c4";
 	};
 
+	pinctrl_nand: nand_grp {
+		groups = "nand";
+		function = "nand";
+	};
+
+	pinctrl_nand2cs: nand2cs_grp {
+		groups = "nand", "nand_cs1";
+		function = "nand";
+	};
+
 	pinctrl_uart0: uart0_grp {
 		groups = "uart0";
 		function = "uart0";
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/versatile-ab.dts linux-libre-4.7-gnu/arch/arm/boot/dts/versatile-ab.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/versatile-ab.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/versatile-ab.dts	2016-07-24 15:23:50.000000000 -0400
@@ -119,8 +119,9 @@
 	};
 
 	flash@34000000 {
-		compatible = "arm,versatile-flash";
-		reg = <0x34000000 0x4000000>;
+		/* 64 MiB NOR flash in non-interleaved chips */
+		compatible = "arm,versatile-flash", "cfi-flash";
+		reg = <0x34000000 0x04000000>;
 		bank-width = <4>;
 	};
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/vexpress-v2m.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/vexpress-v2m.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/vexpress-v2m.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/vexpress-v2m.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -74,19 +74,19 @@
 				compatible = "arm,vexpress-sysreg";
 				reg = <0x00000 0x1000>;
 
-				v2m_led_gpios: sys_led@08 {
+				v2m_led_gpios: sys_led {
 					compatible = "arm,vexpress-sysreg,sys_led";
 					gpio-controller;
 					#gpio-cells = <2>;
 				};
 
-				v2m_mmc_gpios: sys_mci@48 {
+				v2m_mmc_gpios: sys_mci {
 					compatible = "arm,vexpress-sysreg,sys_mci";
 					gpio-controller;
 					#gpio-cells = <2>;
 				};
 
-				v2m_flash_gpios: sys_flash@4c {
+				v2m_flash_gpios: sys_flash {
 					compatible = "arm,vexpress-sysreg,sys_flash";
 					gpio-controller;
 					#gpio-cells = <2>;
@@ -285,7 +285,7 @@
 			};
 		};
 
-		v2m_fixed_3v3: fixedregulator@0 {
+		v2m_fixed_3v3: fixed-regulator-0 {
 			compatible = "regulator-fixed";
 			regulator-name = "3V3";
 			regulator-min-microvolt = <3300000>;
@@ -317,49 +317,49 @@
 		leds {
 			compatible = "gpio-leds";
 
-			user@1 {
+			user1 {
 				label = "v2m:green:user1";
 				gpios = <&v2m_led_gpios 0 0>;
 				linux,default-trigger = "heartbeat";
 			};
 
-			user@2 {
+			user2 {
 				label = "v2m:green:user2";
 				gpios = <&v2m_led_gpios 1 0>;
 				linux,default-trigger = "mmc0";
 			};
 
-			user@3 {
+			user3 {
 				label = "v2m:green:user3";
 				gpios = <&v2m_led_gpios 2 0>;
 				linux,default-trigger = "cpu0";
 			};
 
-			user@4 {
+			user4 {
 				label = "v2m:green:user4";
 				gpios = <&v2m_led_gpios 3 0>;
 				linux,default-trigger = "cpu1";
 			};
 
-			user@5 {
+			user5 {
 				label = "v2m:green:user5";
 				gpios = <&v2m_led_gpios 4 0>;
 				linux,default-trigger = "cpu2";
 			};
 
-			user@6 {
+			user6 {
 				label = "v2m:green:user6";
 				gpios = <&v2m_led_gpios 5 0>;
 				linux,default-trigger = "cpu3";
 			};
 
-			user@7 {
+			user7 {
 				label = "v2m:green:user7";
 				gpios = <&v2m_led_gpios 6 0>;
 				linux,default-trigger = "cpu4";
 			};
 
-			user@8 {
+			user8 {
 				label = "v2m:green:user8";
 				gpios = <&v2m_led_gpios 7 0>;
 				linux,default-trigger = "cpu5";
@@ -370,7 +370,7 @@
 			compatible = "arm,vexpress,config-bus";
 			arm,vexpress,config-bridge = <&v2m_sysreg>;
 
-			osc@0 {
+			oscclk0 {
 				/* MCC static memory clock */
 				compatible = "arm,vexpress-osc";
 				arm,vexpress-sysreg,func = <1 0>;
@@ -379,7 +379,7 @@
 				clock-output-names = "v2m:oscclk0";
 			};
 
-			v2m_oscclk1: osc@1 {
+			v2m_oscclk1: oscclk1 {
 				/* CLCD clock */
 				compatible = "arm,vexpress-osc";
 				arm,vexpress-sysreg,func = <1 1>;
@@ -388,7 +388,7 @@
 				clock-output-names = "v2m:oscclk1";
 			};
 
-			v2m_oscclk2: osc@2 {
+			v2m_oscclk2: oscclk2 {
 				/* IO FPGA peripheral clock */
 				compatible = "arm,vexpress-osc";
 				arm,vexpress-sysreg,func = <1 2>;
@@ -397,7 +397,7 @@
 				clock-output-names = "v2m:oscclk2";
 			};
 
-			volt@0 {
+			volt-vio {
 				/* Logic level voltage */
 				compatible = "arm,vexpress-volt";
 				arm,vexpress-sysreg,func = <2 0>;
@@ -406,34 +406,34 @@
 				label = "VIO";
 			};
 
-			temp@0 {
+			temp-mcc {
 				/* MCC internal operating temperature */
 				compatible = "arm,vexpress-temp";
 				arm,vexpress-sysreg,func = <4 0>;
 				label = "MCC";
 			};
 
-			reset@0 {
+			reset {
 				compatible = "arm,vexpress-reset";
 				arm,vexpress-sysreg,func = <5 0>;
 			};
 
-			muxfpga@0 {
+			muxfpga {
 				compatible = "arm,vexpress-muxfpga";
 				arm,vexpress-sysreg,func = <7 0>;
 			};
 
-			shutdown@0 {
+			shutdown {
 				compatible = "arm,vexpress-shutdown";
 				arm,vexpress-sysreg,func = <8 0>;
 			};
 
-			reboot@0 {
+			reboot {
 				compatible = "arm,vexpress-reboot";
 				arm,vexpress-sysreg,func = <9 0>;
 			};
 
-			dvimode@0 {
+			dvimode {
 				compatible = "arm,vexpress-dvimode";
 				arm,vexpress-sysreg,func = <11 0>;
 			};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -75,19 +75,19 @@
 				compatible = "arm,vexpress-sysreg";
 				reg = <0x010000 0x1000>;
 
-				v2m_led_gpios: sys_led@08 {
+				v2m_led_gpios: sys_led {
 					compatible = "arm,vexpress-sysreg,sys_led";
 					gpio-controller;
 					#gpio-cells = <2>;
 				};
 
-				v2m_mmc_gpios: sys_mci@48 {
+				v2m_mmc_gpios: sys_mci {
 					compatible = "arm,vexpress-sysreg,sys_mci";
 					gpio-controller;
 					#gpio-cells = <2>;
 				};
 
-				v2m_flash_gpios: sys_flash@4c {
+				v2m_flash_gpios: sys_flash {
 					compatible = "arm,vexpress-sysreg,sys_flash";
 					gpio-controller;
 					#gpio-cells = <2>;
@@ -286,7 +286,7 @@
 			};
 		};
 
-		v2m_fixed_3v3: fixedregulator@0 {
+		v2m_fixed_3v3: fixed-regulator-0 {
 			compatible = "regulator-fixed";
 			regulator-name = "3V3";
 			regulator-min-microvolt = <3300000>;
@@ -318,49 +318,49 @@
 		leds {
 			compatible = "gpio-leds";
 
-			user@1 {
+			user1 {
 				label = "v2m:green:user1";
 				gpios = <&v2m_led_gpios 0 0>;
 				linux,default-trigger = "heartbeat";
 			};
 
-			user@2 {
+			user2 {
 				label = "v2m:green:user2";
 				gpios = <&v2m_led_gpios 1 0>;
 				linux,default-trigger = "mmc0";
 			};
 
-			user@3 {
+			user3 {
 				label = "v2m:green:user3";
 				gpios = <&v2m_led_gpios 2 0>;
 				linux,default-trigger = "cpu0";
 			};
 
-			user@4 {
+			user4 {
 				label = "v2m:green:user4";
 				gpios = <&v2m_led_gpios 3 0>;
 				linux,default-trigger = "cpu1";
 			};
 
-			user@5 {
+			user5 {
 				label = "v2m:green:user5";
 				gpios = <&v2m_led_gpios 4 0>;
 				linux,default-trigger = "cpu2";
 			};
 
-			user@6 {
+			user6 {
 				label = "v2m:green:user6";
 				gpios = <&v2m_led_gpios 5 0>;
 				linux,default-trigger = "cpu3";
 			};
 
-			user@7 {
+			user7 {
 				label = "v2m:green:user7";
 				gpios = <&v2m_led_gpios 6 0>;
 				linux,default-trigger = "cpu4";
 			};
 
-			user@8 {
+			user8 {
 				label = "v2m:green:user8";
 				gpios = <&v2m_led_gpios 7 0>;
 				linux,default-trigger = "cpu5";
@@ -371,7 +371,7 @@
 			compatible = "arm,vexpress,config-bus";
 			arm,vexpress,config-bridge = <&v2m_sysreg>;
 
-			osc@0 {
+			oscclk0 {
 				/* MCC static memory clock */
 				compatible = "arm,vexpress-osc";
 				arm,vexpress-sysreg,func = <1 0>;
@@ -380,7 +380,7 @@
 				clock-output-names = "v2m:oscclk0";
 			};
 
-			v2m_oscclk1: osc@1 {
+			v2m_oscclk1: oscclk1 {
 				/* CLCD clock */
 				compatible = "arm,vexpress-osc";
 				arm,vexpress-sysreg,func = <1 1>;
@@ -389,7 +389,7 @@
 				clock-output-names = "v2m:oscclk1";
 			};
 
-			v2m_oscclk2: osc@2 {
+			v2m_oscclk2: oscclk2 {
 				/* IO FPGA peripheral clock */
 				compatible = "arm,vexpress-osc";
 				arm,vexpress-sysreg,func = <1 2>;
@@ -398,7 +398,7 @@
 				clock-output-names = "v2m:oscclk2";
 			};
 
-			volt@0 {
+			volt-vio {
 				/* Logic level voltage */
 				compatible = "arm,vexpress-volt";
 				arm,vexpress-sysreg,func = <2 0>;
@@ -407,34 +407,34 @@
 				label = "VIO";
 			};
 
-			temp@0 {
+			temp-mcc {
 				/* MCC internal operating temperature */
 				compatible = "arm,vexpress-temp";
 				arm,vexpress-sysreg,func = <4 0>;
 				label = "MCC";
 			};
 
-			reset@0 {
+			reset {
 				compatible = "arm,vexpress-reset";
 				arm,vexpress-sysreg,func = <5 0>;
 			};
 
-			muxfpga@0 {
+			muxfpga {
 				compatible = "arm,vexpress-muxfpga";
 				arm,vexpress-sysreg,func = <7 0>;
 			};
 
-			shutdown@0 {
+			shutdown {
 				compatible = "arm,vexpress-shutdown";
 				arm,vexpress-sysreg,func = <8 0>;
 			};
 
-			reboot@0 {
+			reboot {
 				compatible = "arm,vexpress-reboot";
 				arm,vexpress-sysreg,func = <9 0>;
 			};
 
-			dvimode@0 {
+			dvimode {
 				compatible = "arm,vexpress-dvimode";
 				arm,vexpress-sysreg,func = <11 0>;
 			};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts linux-libre-4.7-gnu/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts	2016-07-24 15:23:50.000000000 -0400
@@ -109,7 +109,7 @@
 		compatible = "arm,hdlcd";
 		reg = <0 0x2b000000 0 0x1000>;
 		interrupts = <0 85 4>;
-		clocks = <&oscclk5>;
+		clocks = <&hdlcd_clk>;
 		clock-names = "pxlclk";
 	};
 
@@ -227,7 +227,7 @@
 		compatible = "arm,vexpress,config-bus";
 		arm,vexpress,config-bridge = <&v2m_sysreg>;
 
-		osc@0 {
+		oscclk0 {
 			/* A15 PLL 0 reference clock */
 			compatible = "arm,vexpress-osc";
 			arm,vexpress-sysreg,func = <1 0>;
@@ -236,7 +236,7 @@
 			clock-output-names = "oscclk0";
 		};
 
-		osc@1 {
+		oscclk1 {
 			/* A15 PLL 1 reference clock */
 			compatible = "arm,vexpress-osc";
 			arm,vexpress-sysreg,func = <1 1>;
@@ -245,7 +245,7 @@
 			clock-output-names = "oscclk1";
 		};
 
-		osc@2 {
+		oscclk2 {
 			/* A7 PLL 0 reference clock */
 			compatible = "arm,vexpress-osc";
 			arm,vexpress-sysreg,func = <1 2>;
@@ -254,7 +254,7 @@
 			clock-output-names = "oscclk2";
 		};
 
-		osc@3 {
+		oscclk3 {
 			/* A7 PLL 1 reference clock */
 			compatible = "arm,vexpress-osc";
 			arm,vexpress-sysreg,func = <1 3>;
@@ -263,7 +263,7 @@
 			clock-output-names = "oscclk3";
 		};
 
-		osc@4 {
+		oscclk4 {
 			/* External AXI master clock */
 			compatible = "arm,vexpress-osc";
 			arm,vexpress-sysreg,func = <1 4>;
@@ -272,7 +272,7 @@
 			clock-output-names = "oscclk4";
 		};
 
-		oscclk5: osc@5 {
+		hdlcd_clk: oscclk5 {
 			/* HDLCD PLL reference clock */
 			compatible = "arm,vexpress-osc";
 			arm,vexpress-sysreg,func = <1 5>;
@@ -281,7 +281,7 @@
 			clock-output-names = "oscclk5";
 		};
 
-		smbclk: osc@6 {
+		smbclk: oscclk6 {
 			/* Static memory controller clock */
 			compatible = "arm,vexpress-osc";
 			arm,vexpress-sysreg,func = <1 6>;
@@ -290,7 +290,7 @@
 			clock-output-names = "oscclk6";
 		};
 
-		osc@7 {
+		oscclk7 {
 			/* SYS PLL reference clock */
 			compatible = "arm,vexpress-osc";
 			arm,vexpress-sysreg,func = <1 7>;
@@ -299,7 +299,7 @@
 			clock-output-names = "oscclk7";
 		};
 
-		osc@8 {
+		oscclk8 {
 			/* DDR2 PLL reference clock */
 			compatible = "arm,vexpress-osc";
 			arm,vexpress-sysreg,func = <1 8>;
@@ -308,7 +308,7 @@
 			clock-output-names = "oscclk8";
 		};
 
-		volt@0 {
+		volt-a15 {
 			/* A15 CPU core voltage */
 			compatible = "arm,vexpress-volt";
 			arm,vexpress-sysreg,func = <2 0>;
@@ -319,7 +319,7 @@
 			label = "A15 Vcore";
 		};
 
-		volt@1 {
+		volt-a7 {
 			/* A7 CPU core voltage */
 			compatible = "arm,vexpress-volt";
 			arm,vexpress-sysreg,func = <2 1>;
@@ -330,49 +330,49 @@
 			label = "A7 Vcore";
 		};
 
-		amp@0 {
+		amp-a15 {
 			/* Total current for the two A15 cores */
 			compatible = "arm,vexpress-amp";
 			arm,vexpress-sysreg,func = <3 0>;
 			label = "A15 Icore";
 		};
 
-		amp@1 {
+		amp-a7 {
 			/* Total current for the three A7 cores */
 			compatible = "arm,vexpress-amp";
 			arm,vexpress-sysreg,func = <3 1>;
 			label = "A7 Icore";
 		};
 
-		temp@0 {
+		temp-dcc {
 			/* DCC internal temperature */
 			compatible = "arm,vexpress-temp";
 			arm,vexpress-sysreg,func = <4 0>;
 			label = "DCC";
 		};
 
-		power@0 {
+		power-a15 {
 			/* Total power for the two A15 cores */
 			compatible = "arm,vexpress-power";
 			arm,vexpress-sysreg,func = <12 0>;
 			label = "A15 Pcore";
 		};
 
-		power@1 {
+		power-a7 {
 			/* Total power for the three A7 cores */
 			compatible = "arm,vexpress-power";
 			arm,vexpress-sysreg,func = <12 1>;
 			label = "A7 Pcore";
 		};
 
-		energy@0 {
+		energy-a15 {
 			/* Total energy for the two A15 cores */
 			compatible = "arm,vexpress-energy";
 			arm,vexpress-sysreg,func = <13 0>, <13 1>;
 			label = "A15 Jcore";
 		};
 
-		energy@2 {
+		energy-a7 {
 			/* Total energy for the three A7 cores */
 			compatible = "arm,vexpress-energy";
 			arm,vexpress-sysreg,func = <13 2>, <13 3>;
@@ -387,7 +387,7 @@
 		clocks = <&oscclk6a>;
 		clock-names = "apb_pclk";
 		port {
-			etb_in_port: endpoint@0 {
+			etb_in_port: endpoint {
 				slave-mode;
 				remote-endpoint = <&replicator_out_port0>;
 			};
@@ -401,7 +401,7 @@
 		clocks = <&oscclk6a>;
 		clock-names = "apb_pclk";
 		port {
-			tpiu_in_port: endpoint@0 {
+			tpiu_in_port: endpoint {
 				slave-mode;
 				remote-endpoint = <&replicator_out_port1>;
 			};
@@ -578,7 +578,7 @@
 		};
 	};
 
-	smb {
+	smb@08000000 {
 		compatible = "simple-bus";
 
 		#address-cells = <2>;
@@ -638,4 +638,17 @@
 
 		/include/ "vexpress-v2m-rs1.dtsi"
 	};
+
+	site2: hsb@40000000 {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0 0x40000000 0x3fef0000>;
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 3>;
+		interrupt-map = <0 0 &gic 0 36 4>,
+				<0 1 &gic 0 37 4>,
+				<0 2 &gic 0 38 4>,
+				<0 3 &gic 0 39 4>;
+	};
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts linux-libre-4.7-gnu/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts	2016-07-24 15:23:50.000000000 -0400
@@ -55,14 +55,14 @@
 		compatible = "arm,hdlcd";
 		reg = <0 0x2b000000 0 0x1000>;
 		interrupts = <0 85 4>;
-		clocks = <&oscclk5>;
+		clocks = <&hdlcd_clk>;
 		clock-names = "pxlclk";
 	};
 
 	memory-controller@2b0a0000 {
 		compatible = "arm,pl341", "arm,primecell";
 		reg = <0 0x2b0a0000 0 0x1000>;
-		clocks = <&oscclk7>;
+		clocks = <&sys_pll>;
 		clock-names = "apb_pclk";
 	};
 
@@ -71,7 +71,7 @@
 		status = "disabled";
 		reg = <0 0x2b060000 0 0x1000>;
 		interrupts = <0 98 4>;
-		clocks = <&oscclk7>;
+		clocks = <&sys_pll>;
 		clock-names = "apb_pclk";
 	};
 
@@ -92,7 +92,7 @@
 		reg = <0 0x7ffd0000 0 0x1000>;
 		interrupts = <0 86 4>,
 			     <0 87 4>;
-		clocks = <&oscclk7>;
+		clocks = <&sys_pll>;
 		clock-names = "apb_pclk";
 	};
 
@@ -104,7 +104,7 @@
 			     <0 89 4>,
 			     <0 90 4>,
 			     <0 91 4>;
-		clocks = <&oscclk7>;
+		clocks = <&sys_pll>;
 		clock-names = "apb_pclk";
 	};
 
@@ -126,7 +126,7 @@
 		compatible = "arm,vexpress,config-bus";
 		arm,vexpress,config-bridge = <&v2m_sysreg>;
 
-		osc@0 {
+		oscclk0 {
 			/* CPU PLL reference clock */
 			compatible = "arm,vexpress-osc";
 			arm,vexpress-sysreg,func = <1 0>;
@@ -135,7 +135,7 @@
 			clock-output-names = "oscclk0";
 		};
 
-		osc@4 {
+		oscclk4 {
 			/* Multiplexed AXI master clock */
 			compatible = "arm,vexpress-osc";
 			arm,vexpress-sysreg,func = <1 4>;
@@ -144,7 +144,7 @@
 			clock-output-names = "oscclk4";
 		};
 
-		oscclk5: osc@5 {
+		hdlcd_clk: oscclk5 {
 			/* HDLCD PLL reference clock */
 			compatible = "arm,vexpress-osc";
 			arm,vexpress-sysreg,func = <1 5>;
@@ -153,7 +153,7 @@
 			clock-output-names = "oscclk5";
 		};
 
-		smbclk: osc@6 {
+		smbclk: oscclk6 {
 			/* SMB clock */
 			compatible = "arm,vexpress-osc";
 			arm,vexpress-sysreg,func = <1 6>;
@@ -162,7 +162,7 @@
 			clock-output-names = "oscclk6";
 		};
 
-		oscclk7: osc@7 {
+		sys_pll: oscclk7 {
 			/* SYS PLL reference clock */
 			compatible = "arm,vexpress-osc";
 			arm,vexpress-sysreg,func = <1 7>;
@@ -171,7 +171,7 @@
 			clock-output-names = "oscclk7";
 		};
 
-		osc@8 {
+		oscclk8 {
 			/* DDR2 PLL reference clock */
 			compatible = "arm,vexpress-osc";
 			arm,vexpress-sysreg,func = <1 8>;
@@ -180,7 +180,7 @@
 			clock-output-names = "oscclk8";
 		};
 
-		volt@0 {
+		volt-cores {
 			/* CPU core voltage */
 			compatible = "arm,vexpress-volt";
 			arm,vexpress-sysreg,func = <2 0>;
@@ -191,28 +191,28 @@
 			label = "Cores";
 		};
 
-		amp@0 {
+		amp-cores {
 			/* Total current for the two cores */
 			compatible = "arm,vexpress-amp";
 			arm,vexpress-sysreg,func = <3 0>;
 			label = "Cores";
 		};
 
-		temp@0 {
+		temp-dcc {
 			/* DCC internal temperature */
 			compatible = "arm,vexpress-temp";
 			arm,vexpress-sysreg,func = <4 0>;
 			label = "DCC";
 		};
 
-		power@0 {
+		power-cores {
 			/* Total power */
 			compatible = "arm,vexpress-power";
 			arm,vexpress-sysreg,func = <12 0>;
 			label = "Cores";
 		};
 
-		energy@0 {
+		energy {
 			/* Total energy */
 			compatible = "arm,vexpress-energy";
 			arm,vexpress-sysreg,func = <13 0>;
@@ -220,7 +220,7 @@
 		};
 	};
 
-	smb {
+	smb@08000000 {
 		compatible = "simple-bus";
 
 		#address-cells = <2>;
@@ -280,4 +280,17 @@
 
 		/include/ "vexpress-v2m-rs1.dtsi"
 	};
+
+	site2: hsb@40000000 {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0 0x40000000 0x3fef0000>;
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 3>;
+		interrupt-map = <0 0 &gic 0 36 4>,
+				<0 1 &gic 0 37 4>,
+				<0 2 &gic 0 38 4>,
+				<0 3 &gic 0 39 4>;
+	};
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/vexpress-v2p-ca5s.dts linux-libre-4.7-gnu/arch/arm/boot/dts/vexpress-v2p-ca5s.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/vexpress-v2p-ca5s.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/vexpress-v2p-ca5s.dts	2016-07-24 15:23:50.000000000 -0400
@@ -57,14 +57,14 @@
 		compatible = "arm,hdlcd";
 		reg = <0x2a110000 0x1000>;
 		interrupts = <0 85 4>;
-		clocks = <&oscclk3>;
+		clocks = <&hdlcd_clk>;
 		clock-names = "pxlclk";
 	};
 
 	memory-controller@2a150000 {
 		compatible = "arm,pl341", "arm,primecell";
 		reg = <0x2a150000 0x1000>;
-		clocks = <&oscclk1>;
+		clocks = <&axi_clk>;
 		clock-names = "apb_pclk";
 	};
 
@@ -73,7 +73,7 @@
 		reg = <0x2a190000 0x1000>;
 		interrupts = <0 86 4>,
 			     <0 87 4>;
-		clocks = <&oscclk1>;
+		clocks = <&axi_clk>;
 		clock-names = "apb_pclk";
 	};
 
@@ -93,7 +93,7 @@
 		             "arm,cortex-a9-global-timer";
 		reg = <0x2c000200 0x20>;
 		interrupts = <1 11 0x304>;
-		clocks = <&oscclk0>;
+		clocks = <&cpu_clk>;
 	};
 
 	watchdog@2c000620 {
@@ -128,7 +128,7 @@
 		compatible = "arm,vexpress,config-bus";
 		arm,vexpress,config-bridge = <&v2m_sysreg>;
 
-		oscclk0: osc@0 {
+		cpu_clk: oscclk0 {
 			/* CPU and internal AXI reference clock */
 			compatible = "arm,vexpress-osc";
 			arm,vexpress-sysreg,func = <1 0>;
@@ -137,7 +137,7 @@
 			clock-output-names = "oscclk0";
 		};
 
-		oscclk1: osc@1 {
+		axi_clk: oscclk1 {
 			/* Multiplexed AXI master clock */
 			compatible = "arm,vexpress-osc";
 			arm,vexpress-sysreg,func = <1 1>;
@@ -146,7 +146,7 @@
 			clock-output-names = "oscclk1";
 		};
 
-		osc@2 {
+		oscclk2 {
 			/* DDR2 */
 			compatible = "arm,vexpress-osc";
 			arm,vexpress-sysreg,func = <1 2>;
@@ -155,7 +155,7 @@
 			clock-output-names = "oscclk2";
 		};
 
-		oscclk3: osc@3 {
+		hdlcd_clk: oscclk3 {
 			/* HDLCD */
 			compatible = "arm,vexpress-osc";
 			arm,vexpress-sysreg,func = <1 3>;
@@ -164,7 +164,7 @@
 			clock-output-names = "oscclk3";
 		};
 
-		osc@4 {
+		oscclk4 {
 			/* Test chip gate configuration */
 			compatible = "arm,vexpress-osc";
 			arm,vexpress-sysreg,func = <1 4>;
@@ -173,7 +173,7 @@
 			clock-output-names = "oscclk4";
 		};
 
-		smbclk: osc@5 {
+		smbclk: oscclk5 {
 			/* SMB clock */
 			compatible = "arm,vexpress-osc";
 			arm,vexpress-sysreg,func = <1 5>;
@@ -182,7 +182,7 @@
 			clock-output-names = "oscclk5";
 		};
 
-		temp@0 {
+		temp-dcc {
 			/* DCC internal operating temperature */
 			compatible = "arm,vexpress-temp";
 			arm,vexpress-sysreg,func = <4 0>;
@@ -190,7 +190,7 @@
 		};
 	};
 
-	smb {
+	smb@08000000 {
 		compatible = "simple-bus";
 
 		#address-cells = <2>;
@@ -250,4 +250,17 @@
 
 		/include/ "vexpress-v2m-rs1.dtsi"
 	};
+
+	site2: hsb@40000000 {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0x40000000 0x40000000>;
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 3>;
+		interrupt-map = <0 0 &gic 0 36 4>,
+				<0 1 &gic 0 37 4>,
+				<0 2 &gic 0 38 4>,
+				<0 3 &gic 0 39 4>;
+	};
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/vexpress-v2p-ca9.dts linux-libre-4.7-gnu/arch/arm/boot/dts/vexpress-v2p-ca9.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/vexpress-v2p-ca9.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/vexpress-v2p-ca9.dts	2016-07-24 15:23:50.000000000 -0400
@@ -190,7 +190,7 @@
 		compatible = "arm,vexpress,config-bus";
 		arm,vexpress,config-bridge = <&v2m_sysreg>;
 
-		osc@0 {
+		oscclk0: extsaxiclk {
 			/* ACLK clock to the AXI master port on the test chip */
 			compatible = "arm,vexpress-osc";
 			arm,vexpress-sysreg,func = <1 0>;
@@ -199,7 +199,7 @@
 			clock-output-names = "extsaxiclk";
 		};
 
-		oscclk1: osc@1 {
+		oscclk1: clcdclk {
 			/* Reference clock for the CLCD */
 			compatible = "arm,vexpress-osc";
 			arm,vexpress-sysreg,func = <1 1>;
@@ -208,7 +208,7 @@
 			clock-output-names = "clcdclk";
 		};
 
-		smbclk: oscclk2: osc@2 {
+		smbclk: oscclk2: tcrefclk {
 			/* Reference clock for the test chip internal PLLs */
 			compatible = "arm,vexpress-osc";
 			arm,vexpress-sysreg,func = <1 2>;
@@ -217,7 +217,7 @@
 			clock-output-names = "tcrefclk";
 		};
 
-		volt@0 {
+		volt-vd10 {
 			/* Test Chip internal logic voltage */
 			compatible = "arm,vexpress-volt";
 			arm,vexpress-sysreg,func = <2 0>;
@@ -226,7 +226,7 @@
 			label = "VD10";
 		};
 
-		volt@1 {
+		volt-vd10-s2 {
 			/* PL310, L2 cache, RAM cell supply (not PL310 logic) */
 			compatible = "arm,vexpress-volt";
 			arm,vexpress-sysreg,func = <2 1>;
@@ -235,7 +235,7 @@
 			label = "VD10_S2";
 		};
 
-		volt@2 {
+		volt-vd10-s3 {
 			/* Cortex-A9 system supply, Cores, MPEs, SCU and PL310 logic */
 			compatible = "arm,vexpress-volt";
 			arm,vexpress-sysreg,func = <2 2>;
@@ -244,7 +244,7 @@
 			label = "VD10_S3";
 		};
 
-		volt@3 {
+		volt-vcc1v8 {
 			/* DDR2 SDRAM and Test Chip DDR2 I/O supply */
 			compatible = "arm,vexpress-volt";
 			arm,vexpress-sysreg,func = <2 3>;
@@ -253,7 +253,7 @@
 			label = "VCC1V8";
 		};
 
-		volt@4 {
+		volt-ddr2vtt {
 			/* DDR2 SDRAM VTT termination voltage */
 			compatible = "arm,vexpress-volt";
 			arm,vexpress-sysreg,func = <2 4>;
@@ -262,7 +262,7 @@
 			label = "DDR2VTT";
 		};
 
-		volt@5 {
+		volt-vcc3v3 {
 			/* Local board supply for miscellaneous logic external to the Test Chip */
 			arm,vexpress-sysreg,func = <2 5>;
 			compatible = "arm,vexpress-volt";
@@ -271,28 +271,28 @@
 			label = "VCC3V3";
 		};
 
-		amp@0 {
+		amp-vd10-s2 {
 			/* PL310, L2 cache, RAM cell supply (not PL310 logic) */
 			compatible = "arm,vexpress-amp";
 			arm,vexpress-sysreg,func = <3 0>;
 			label = "VD10_S2";
 		};
 
-		amp@1 {
+		amp-vd10-s3 {
 			/* Cortex-A9 system supply, Cores, MPEs, SCU and PL310 logic */
 			compatible = "arm,vexpress-amp";
 			arm,vexpress-sysreg,func = <3 1>;
 			label = "VD10_S3";
 		};
 
-		power@0 {
+		power-vd10-s2 {
 			/* PL310, L2 cache, RAM cell supply (not PL310 logic) */
 			compatible = "arm,vexpress-power";
 			arm,vexpress-sysreg,func = <12 0>;
 			label = "PVD10_S2";
 		};
 
-		power@1 {
+		power-vd10-s3 {
 			/* Cortex-A9 system supply, Cores, MPEs, SCU and PL310 logic */
 			compatible = "arm,vexpress-power";
 			arm,vexpress-sysreg,func = <12 1>;
@@ -300,7 +300,7 @@
 		};
 	};
 
-	smb {
+	smb@04000000 {
 		compatible = "simple-bus";
 
 		#address-cells = <2>;
@@ -359,4 +359,17 @@
 
 		/include/ "vexpress-v2m.dtsi"
 	};
+
+	site2: hsb@e0000000 {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0xe0000000 0x20000000>;
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 3>;
+		interrupt-map = <0 0 &gic 0 36 4>,
+				<0 1 &gic 0 37 4>,
+				<0 2 &gic 0 38 4>,
+				<0 3 &gic 0 39 4>;
+	};
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/vf500-colibri.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/vf500-colibri.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/vf500-colibri.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/vf500-colibri.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -69,6 +69,11 @@
 	};
 };
 
+&nfc {
+	assigned-clocks = <&clks VF610_CLK_NFC>;
+	assigned-clock-rates = <33000000>;
+};
+
 &iomuxc {
 	vf610-colibri {
 		pinctrl_touchctrl_idle: touchctrl_idle {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/vf500.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/vf500.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/vf500.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/vf500.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -81,6 +81,7 @@
 				compatible = "arm,cortex-a5-pmu";
 				interrupts = <7 IRQ_TYPE_LEVEL_HIGH>;
 				interrupt-affinity = <&a5_cpu>;
+				reg = <0x40089000 0x1000>;
 			};
 		};
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/vf610-colibri.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/vf610-colibri.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/vf610-colibri.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/vf610-colibri.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -50,3 +50,8 @@
 		reg = <0x80000000 0x10000000>;
 	};
 };
+
+&nfc {
+	assigned-clocks = <&clks VF610_CLK_NFC>;
+	assigned-clock-rates = <50000000>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/vf610-zii-dev-rev-b.dts linux-libre-4.7-gnu/arch/arm/boot/dts/vf610-zii-dev-rev-b.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/vf610-zii-dev-rev-b.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/vf610-zii-dev-rev-b.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,734 @@
+/*
+ * Copyright (C) 2015, 2016 Zodiac Inflight Innovations
+ *
+ * Based on an original 'vf610-twr.dts' which is Copyright 2015,
+ * Freescale Semiconductor, Inc.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "vf610.dtsi"
+
+/ {
+	model = "ZII VF610 Development Board, Rev B";
+	compatible = "zii,vf610dev-b", "zii,vf610dev", "fsl,vf610";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory {
+		reg = <0x80000000 0x20000000>;
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+		pinctrl-0 = <&pinctrl_leds_debug>;
+		pinctrl-names = "default";
+
+		debug {
+			label = "zii:green:debug1";
+			gpios = <&gpio2 10 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+
+	mdio-mux {
+		compatible = "mdio-mux-gpio";
+		pinctrl-0 = <&pinctrl_mdio_mux>;
+		pinctrl-names = "default";
+		gpios = <&gpio0 8  GPIO_ACTIVE_HIGH
+			 &gpio0 9  GPIO_ACTIVE_HIGH
+			 &gpio0 24 GPIO_ACTIVE_HIGH
+			 &gpio0 25 GPIO_ACTIVE_HIGH>;
+		mdio-parent-bus = <&mdio1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		mdio_mux_1: mdio@1 {
+			reg = <1>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		mdio_mux_2: mdio@2 {
+			reg = <2>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		mdio_mux_4: mdio@4 {
+			reg = <4>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		mdio_mux_8: mdio@8 {
+			reg = <8>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+	};
+
+	dsa {
+		compatible = "marvell,dsa";
+		#address-cells = <2>;
+		#size-cells = <0>;
+		dsa,ethernet = <&fec1>;
+		dsa,mii-bus = <&mdio_mux_1>;
+
+		/* 6352 - Primary - 7 ports */
+		switch0: switch@0-0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x00 0>;
+			eeprom-length = <512>;
+
+			port@0 {
+				reg = <0>;
+				label = "lan0";
+			};
+
+			port@1 {
+				reg = <1>;
+				label = "lan1";
+			};
+
+			port@2 {
+				reg = <2>;
+				label = "lan2";
+			};
+
+			switch0port5: port@5 {
+				reg = <5>;
+				label = "dsa";
+				phy-mode = "rgmii-txid";
+				link = <&switch1port6
+					&switch2port9>;
+
+				fixed-link {
+					speed = <1000>;
+					full-duplex;
+				};
+			};
+
+			port@6 {
+				reg = <6>;
+				label = "cpu";
+
+				fixed-link {
+					speed = <100>;
+					full-duplex;
+				};
+			};
+
+		};
+
+		/* 6352 - Secondary - 7 ports */
+		switch1: switch@0-1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x00 1>;
+			eeprom-length = <512>;
+			mii-bus = <&mdio_mux_2>;
+
+			port@0 {
+				reg = <0>;
+				label = "lan3";
+			};
+
+			port@1 {
+				reg = <1>;
+				label = "lan4";
+			};
+
+			port@2 {
+				reg = <2>;
+				label = "lan5";
+			};
+
+			switch1port5: port@5 {
+				reg = <5>;
+				label = "dsa";
+				link = <&switch2port9>;
+				phy-mode = "rgmii-txid";
+
+				fixed-link {
+					speed = <1000>;
+					full-duplex;
+				};
+			};
+
+			switch1port6: port@6 {
+				reg = <6>;
+				label = "dsa";
+				phy-mode = "rgmii-txid";
+				link = <&switch0port5>;
+
+				fixed-link {
+					speed = <1000>;
+					full-duplex;
+				};
+			};
+		};
+
+		/* 6185 - 10 ports */
+		switch2: switch@0-2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x00 2>;
+			mii-bus = <&mdio_mux_4>;
+
+			port@0 {
+				reg = <0>;
+				label = "lan6";
+			};
+
+			port@1 {
+				reg = <1>;
+				label = "lan7";
+			};
+
+			port@2 {
+				reg = <2>;
+				label = "lan8";
+			};
+
+			port@3 {
+				reg = <3>;
+				label = "optical3";
+
+				fixed-link {
+					speed = <1000>;
+					full-duplex;
+					link-gpios = <&gpio6 2
+						      GPIO_ACTIVE_HIGH>;
+				};
+			};
+
+			port@4 {
+				reg = <4>;
+				label = "optical4";
+
+				fixed-link {
+					speed = <1000>;
+					full-duplex;
+					link-gpios = <&gpio6 3
+						      GPIO_ACTIVE_HIGH>;
+				};
+			};
+
+			switch2port9: port@9 {
+				reg = <9>;
+				label = "dsa";
+				phy-mode = "rgmii-txid";
+				link = <&switch1port5
+					&switch0port5>;
+
+				fixed-link {
+					speed = <1000>;
+					full-duplex;
+				};
+			};
+		};
+	};
+
+	reg_vcc_3v3_mcu: regulator-vcc-3v3-mcu {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_3v3_mcu";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	usb0_vbus: regulator-usb0-vbus {
+		compatible = "regulator-fixed";
+		pinctrl-0 = <&pinctrl_usb_vbus>;
+		regulator-name = "usb_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		enable-active-high;
+		regulator-always-on;
+		regulator-boot-on;
+		gpio = <&gpio0 6 0>;
+	};
+
+	spi0 {
+		compatible = "spi-gpio";
+		pinctrl-0 = <&pinctrl_gpio_spi0>;
+		pinctrl-names = "default";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		gpio-sck  = <&gpio1 12 GPIO_ACTIVE_HIGH>;
+		gpio-mosi = <&gpio1 11 GPIO_ACTIVE_HIGH>;
+		gpio-miso = <&gpio1 10 GPIO_ACTIVE_HIGH>;
+		cs-gpios  = <&gpio1  9 GPIO_ACTIVE_HIGH
+			     &gpio1  8 GPIO_ACTIVE_HIGH>;
+		num-chipselects = <2>;
+
+		m25p128@0 {
+			compatible = "m25p128", "jedec,spi-nor";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0>;
+			spi-max-frequency = <1000000>;
+		};
+
+		at93c46d@1 {
+			compatible = "atmel,at93c46d";
+			pinctrl-0 = <&pinctrl_gpio_e6185_eeprom_sel>;
+			pinctrl-names = "default";
+			#address-cells = <0>;
+			#size-cells = <0>;
+			reg = <1>;
+			spi-max-frequency = <500000>;
+			spi-cs-high;
+			data-size = <16>;
+			select-gpios = <&gpio4 4 GPIO_ACTIVE_HIGH>;
+		};
+	};
+};
+
+&adc0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_adc0_ad5>;
+	vref-supply = <&reg_vcc_3v3_mcu>;
+	status = "okay";
+};
+
+&edma0 {
+	status = "okay";
+};
+
+&esdhc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_esdhc1>;
+	bus-width = <4>;
+	status = "okay";
+};
+
+&fec0 {
+	phy-mode = "rmii";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_fec0>;
+	status = "okay";
+};
+
+&fec1 {
+	phy-mode = "rmii";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_fec1>;
+	status = "okay";
+
+	fixed-link {
+		   speed = <100>;
+		   full-duplex;
+	};
+
+	mdio1: mdio {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "okay";
+	};
+};
+
+&i2c0 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c0>;
+	status = "okay";
+
+	gpio5: pca9554@20 {
+		compatible = "nxp,pca9554";
+		reg = <0x20>;
+		gpio-controller;
+		#gpio-cells = <2>;
+
+	};
+
+	gpio6: pca9554@22 {
+		compatible = "nxp,pca9554";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_pca9554_22>;
+		reg = <0x22>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&gpio2>;
+		interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+	};
+
+	lm75@48 {
+		compatible = "national,lm75";
+		reg = <0x48>;
+	};
+
+	at24c04@50 {
+		compatible = "atmel,24c04";
+		reg = <0x50>;
+	};
+
+	at24c04@52 {
+		compatible = "atmel,24c04";
+		reg = <0x52>;
+	};
+
+	ds1682@6b {
+		compatible = "dallas,ds1682";
+		reg = <0x6b>;
+	};
+};
+
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+
+	tca9548@70 {
+		compatible = "nxp,pca9548";
+		pinctrl-0 = <&pinctrl_i2c_mux_reset>;
+		pinctrl-names = "default";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x70>;
+		reset-gpios = <&gpio3 23 GPIO_ACTIVE_LOW>;
+
+		i2c@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+
+			sfp1: at24c04@50 {
+				compatible = "atmel,24c02";
+				reg = <0x50>;
+			};
+		};
+
+		i2c@1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+
+			sfp2: at24c04@50 {
+				compatible = "atmel,24c02";
+				reg = <0x50>;
+			};
+		};
+
+		i2c@2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+
+			sfp3: at24c04@50 {
+				compatible = "atmel,24c02";
+				reg = <0x50>;
+			};
+		};
+
+		i2c@3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+
+			sfp4: at24c04@50 {
+				compatible = "atmel,24c02";
+				reg = <0x50>;
+			};
+		};
+
+		i2c@4 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <4>;
+		};
+	};
+};
+
+&i2c3 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart0>;
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+&usbdev0 {
+	disable-over-current;
+	vbus-supply = <&usb0_vbus>;
+	dr_mode = "host";
+	status = "okay";
+};
+
+&usbh1 {
+	disable-over-current;
+	status = "okay";
+};
+
+&usbmisc0 {
+	status = "okay";
+};
+
+&usbmisc1 {
+	status = "okay";
+};
+
+&usbphy0 {
+	status = "okay";
+};
+
+&usbphy1 {
+	status = "okay";
+};
+
+&iomuxc {
+	pinctrl_adc0_ad5: adc0ad5grp {
+		fsl,pins = <
+			VF610_PAD_PTC30__ADC0_SE5	0x00a1
+		>;
+	};
+
+	pinctrl_dspi0: dspi0grp {
+		fsl,pins = <
+			VF610_PAD_PTB18__DSPI0_CS1	0x1182
+			VF610_PAD_PTB19__DSPI0_CS0	0x1182
+			VF610_PAD_PTB20__DSPI0_SIN	0x1181
+			VF610_PAD_PTB21__DSPI0_SOUT	0x1182
+			VF610_PAD_PTB22__DSPI0_SCK	0x1182
+		>;
+	};
+
+	pinctrl_dspi2: dspi2grp {
+		fsl,pins = <
+			VF610_PAD_PTD31__DSPI2_CS1	0x1182
+			VF610_PAD_PTD30__DSPI2_CS0	0x1182
+			VF610_PAD_PTD29__DSPI2_SIN	0x1181
+			VF610_PAD_PTD28__DSPI2_SOUT	0x1182
+			VF610_PAD_PTD27__DSPI2_SCK	0x1182
+		>;
+	};
+
+	pinctrl_esdhc1: esdhc1grp {
+		fsl,pins = <
+			VF610_PAD_PTA24__ESDHC1_CLK	0x31ef
+			VF610_PAD_PTA25__ESDHC1_CMD	0x31ef
+			VF610_PAD_PTA26__ESDHC1_DAT0	0x31ef
+			VF610_PAD_PTA27__ESDHC1_DAT1	0x31ef
+			VF610_PAD_PTA28__ESDHC1_DATA2	0x31ef
+			VF610_PAD_PTA29__ESDHC1_DAT3	0x31ef
+			VF610_PAD_PTA7__GPIO_134	0x219d
+		>;
+	};
+
+	pinctrl_fec0: fec0grp {
+		fsl,pins = <
+			VF610_PAD_PTC0__ENET_RMII0_MDC	0x30d2
+			VF610_PAD_PTC1__ENET_RMII0_MDIO	0x30d3
+			VF610_PAD_PTC2__ENET_RMII0_CRS	0x30d1
+			VF610_PAD_PTC3__ENET_RMII0_RXD1	0x30d1
+			VF610_PAD_PTC4__ENET_RMII0_RXD0	0x30d1
+			VF610_PAD_PTC5__ENET_RMII0_RXER	0x30d1
+			VF610_PAD_PTC6__ENET_RMII0_TXD1	0x30d2
+			VF610_PAD_PTC7__ENET_RMII0_TXD0	0x30d2
+			VF610_PAD_PTC8__ENET_RMII0_TXEN	0x30d2
+		>;
+	};
+
+	pinctrl_fec1: fec1grp {
+		fsl,pins = <
+			VF610_PAD_PTA6__RMII_CLKIN		0x30d1
+			VF610_PAD_PTC9__ENET_RMII1_MDC		0x30d2
+			VF610_PAD_PTC10__ENET_RMII1_MDIO	0x30d3
+			VF610_PAD_PTC11__ENET_RMII1_CRS		0x30d1
+			VF610_PAD_PTC12__ENET_RMII1_RXD1	0x30d1
+			VF610_PAD_PTC13__ENET_RMII1_RXD0	0x30d1
+			VF610_PAD_PTC14__ENET_RMII1_RXER	0x30d1
+			VF610_PAD_PTC15__ENET_RMII1_TXD1	0x30d2
+			VF610_PAD_PTC16__ENET_RMII1_TXD0	0x30d2
+			VF610_PAD_PTC17__ENET_RMII1_TXEN	0x30d2
+		>;
+	};
+
+	pinctrl_gpio_e6185_eeprom_sel: pinctrl-gpio-e6185-eeprom-spi0 {
+		fsl,pins = <
+			VF610_PAD_PTE27__GPIO_132	0x33e2
+		>;
+	};
+
+	pinctrl_gpio_spi0: pinctrl-gpio-spi0 {
+		fsl,pins = <
+			VF610_PAD_PTB22__GPIO_44	0x33e2
+			VF610_PAD_PTB21__GPIO_43	0x33e2
+			VF610_PAD_PTB20__GPIO_42	0x33e1
+			VF610_PAD_PTB19__GPIO_41	0x33e2
+			VF610_PAD_PTB18__GPIO_40	0x33e2
+		>;
+	};
+
+	pinctrl_i2c_mux_reset: pinctrl-i2c-mux-reset {
+		fsl,pins = <
+			 VF610_PAD_PTE14__GPIO_119	0x31c2
+			 >;
+	};
+
+	pinctrl_i2c0: i2c0grp {
+		fsl,pins = <
+			VF610_PAD_PTB14__I2C0_SCL	0x37ff
+			VF610_PAD_PTB15__I2C0_SDA	0x37ff
+		>;
+	};
+
+	pinctrl_i2c1: i2c1grp {
+		fsl,pins = <
+			VF610_PAD_PTB16__I2C1_SCL	0x37ff
+			VF610_PAD_PTB17__I2C1_SDA	0x37ff
+		>;
+	};
+
+	pinctrl_i2c2: i2c2grp {
+		fsl,pins = <
+			VF610_PAD_PTA22__I2C2_SCL	0x37ff
+			VF610_PAD_PTA23__I2C2_SDA	0x37ff
+		>;
+	};
+
+	pinctrl_i2c3: i2c3grp {
+		fsl,pins = <
+			VF610_PAD_PTA30__I2C3_SCL	0x37ff
+			VF610_PAD_PTA31__I2C3_SDA	0x37ff
+		>;
+	};
+
+	pinctrl_leds_debug: pinctrl-leds-debug {
+		fsl,pins = <
+			 VF610_PAD_PTD20__GPIO_74	0x31c2
+			 >;
+	};
+
+	pinctrl_mdio_mux: pinctrl-mdio-mux {
+		fsl,pins = <
+			VF610_PAD_PTA18__GPIO_8		0x31c2
+			VF610_PAD_PTA19__GPIO_9		0x31c2
+			VF610_PAD_PTB2__GPIO_24		0x31c2
+			VF610_PAD_PTB3__GPIO_25		0x31c2
+		>;
+	};
+
+	pinctrl_pca9554_22: pinctrl-pca95540-22 {
+		fsl,pins = <
+			VF610_PAD_PTB28__GPIO_98	0x219d
+		>;
+	};
+
+	pinctrl_pwm0: pwm0grp {
+		fsl,pins = <
+			VF610_PAD_PTB0__FTM0_CH0	0x1582
+			VF610_PAD_PTB1__FTM0_CH1	0x1582
+			VF610_PAD_PTB2__FTM0_CH2	0x1582
+			VF610_PAD_PTB3__FTM0_CH3	0x1582
+		>;
+	};
+
+	pinctrl_qspi0: qspi0grp {
+		fsl,pins = <
+			VF610_PAD_PTD7__QSPI0_B_QSCK	0x31c3
+			VF610_PAD_PTD8__QSPI0_B_CS0	0x31ff
+			VF610_PAD_PTD9__QSPI0_B_DATA3	0x31c3
+			VF610_PAD_PTD10__QSPI0_B_DATA2	0x31c3
+			VF610_PAD_PTD11__QSPI0_B_DATA1	0x31c3
+			VF610_PAD_PTD12__QSPI0_B_DATA0	0x31c3
+		>;
+	};
+
+	pinctrl_uart0: uart0grp {
+		fsl,pins = <
+			VF610_PAD_PTB10__UART0_TX	0x21a2
+			VF610_PAD_PTB11__UART0_RX	0x21a1
+		>;
+	};
+
+	pinctrl_uart1: uart1grp {
+		fsl,pins = <
+			VF610_PAD_PTB23__UART1_TX	0x21a2
+			VF610_PAD_PTB24__UART1_RX	0x21a1
+		>;
+	};
+
+	pinctrl_uart2: uart2grp {
+		fsl,pins = <
+			VF610_PAD_PTD0__UART2_TX	0x21a2
+			VF610_PAD_PTD1__UART2_RX	0x21a1
+		>;
+	};
+
+	pinctrl_usb_vbus: pinctrl-usb-vbus {
+		fsl,pins = <
+			VF610_PAD_PTA16__GPIO_6	0x31c2
+		>;
+	};
+
+	pinctrl_usb0_host: usb0-host-grp {
+		fsl,pins = <
+			VF610_PAD_PTD6__GPIO_85		0x0062
+		>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/vf-colibri.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/vf-colibri.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/vf-colibri.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/vf-colibri.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -40,6 +40,11 @@
  */
 
 / {
+	aliases {
+		ethernet0 = &fec1;
+		ethernet1 = &fec0;
+	};
+
 	bl: backlight {
 		compatible = "pwm-backlight";
 		pinctrl-names = "default";
@@ -125,8 +130,6 @@
 };
 
 &nfc {
-	assigned-clocks = <&clks VF610_CLK_NFC>;
-	assigned-clock-rates = <33000000>;
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_nfc>;
 	status = "okay";
@@ -219,6 +222,39 @@
 			>;
 		};
 
+		pinctrl_dcu0_1: dcu0grp_1 {
+			fsl,pins = <
+				VF610_PAD_PTE0__DCU0_HSYNC	0x1902
+				VF610_PAD_PTE1__DCU0_VSYNC	0x1902
+				VF610_PAD_PTE2__DCU0_PCLK	0x1902
+				VF610_PAD_PTE4__DCU0_DE		0x1902
+				VF610_PAD_PTE5__DCU0_R0		0x1902
+				VF610_PAD_PTE6__DCU0_R1		0x1902
+				VF610_PAD_PTE7__DCU0_R2		0x1902
+				VF610_PAD_PTE8__DCU0_R3		0x1902
+				VF610_PAD_PTE9__DCU0_R4		0x1902
+				VF610_PAD_PTE10__DCU0_R5	0x1902
+				VF610_PAD_PTE11__DCU0_R6	0x1902
+				VF610_PAD_PTE12__DCU0_R7	0x1902
+				VF610_PAD_PTE13__DCU0_G0	0x1902
+				VF610_PAD_PTE14__DCU0_G1	0x1902
+				VF610_PAD_PTE15__DCU0_G2	0x1902
+				VF610_PAD_PTE16__DCU0_G3	0x1902
+				VF610_PAD_PTE17__DCU0_G4	0x1902
+				VF610_PAD_PTE18__DCU0_G5	0x1902
+				VF610_PAD_PTE19__DCU0_G6	0x1902
+				VF610_PAD_PTE20__DCU0_G7	0x1902
+				VF610_PAD_PTE21__DCU0_B0	0x1902
+				VF610_PAD_PTE22__DCU0_B1	0x1902
+				VF610_PAD_PTE23__DCU0_B2	0x1902
+				VF610_PAD_PTE24__DCU0_B3	0x1902
+				VF610_PAD_PTE25__DCU0_B4	0x1902
+				VF610_PAD_PTE26__DCU0_B5	0x1902
+				VF610_PAD_PTE27__DCU0_B6	0x1902
+				VF610_PAD_PTE28__DCU0_B7	0x1902
+			>;
+		};
+
 		pinctrl_dspi1: dspi1grp {
 			fsl,pins = <
 				VF610_PAD_PTD5__DSPI1_CS0		0x33e2
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -50,6 +50,11 @@
 		clock-frequency = <16000000>;
 	};
 
+	panel: panel {
+		compatible = "edt,et057090dhu";
+		backlight = <&bl>;
+	};
+
 	reg_3v3: regulator-3v3 {
 		compatible = "regulator-fixed";
 		regulator-name = "3.3V";
@@ -83,6 +88,13 @@
 	status  = "okay";
 };
 
+&dcu0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_dcu0_1>;
+	fsl,panel = <&panel>;
+	status = "okay";
+};
+
 &dspi1 {
 	status = "okay";
 
@@ -134,6 +146,10 @@
 	vin-supply = <&reg_3v3>;
 };
 
+&tcon0 {
+	status = "okay";
+};
+
 &uart0 {
 	status = "okay";
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/vfxxx.dtsi linux-libre-4.7-gnu/arch/arm/boot/dts/vfxxx.dtsi
--- linux-libre-4.6-gnu/arch/arm/boot/dts/vfxxx.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/vfxxx.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -95,6 +95,7 @@
 			compatible = "fsl,aips-bus", "simple-bus";
 			#address-cells = <1>;
 			#size-cells = <1>;
+			reg = <0x40000000 0x00070000>;
 			ranges;
 
 			mscm_cpucfg: cpucfg@40001000 {
@@ -310,6 +311,14 @@
 							<20000000>;
 			};
 
+			tcon0: timing-controller@4003d000 {
+				compatible = "fsl,vf610-tcon";
+				reg = <0x4003d000 0x1000>;
+				clocks = <&clks VF610_CLK_TCON0>;
+				clock-names = "ipg";
+				status = "disabled";
+			};
+
 			wdoga5: wdog@4003e000 {
 				compatible = "fsl,vf610-wdt", "fsl,imx21-wdt";
 				reg = <0x4003e000 0x1000>;
@@ -415,6 +424,17 @@
 				status = "disabled";
 			};
 
+			dcu0: dcu@40058000 {
+				compatible = "fsl,vf610-dcu";
+				reg = <0x40058000 0x1200>;
+				interrupts = <30 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks VF610_CLK_DCU0>,
+					<&clks VF610_CLK_DCU0_DIV>;
+				clock-names = "dcu", "pix";
+				fsl,tcon = <&tcon0>;
+				status = "disabled";
+			};
+
 			i2c0: i2c@40066000 {
 				#address-cells = <1>;
 				#size-cells = <0>;
@@ -481,6 +501,7 @@
 			compatible = "fsl,aips-bus", "simple-bus";
 			#address-cells = <1>;
 			#size-cells = <1>;
+			reg = <0x40080000 0x0007f000>;
 			ranges;
 
 			edma1: dma-controller@40098000 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/dts/wd-mbwe.dts linux-libre-4.7-gnu/arch/arm/boot/dts/wd-mbwe.dts
--- linux-libre-4.6-gnu/arch/arm/boot/dts/wd-mbwe.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/boot/dts/wd-mbwe.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,112 @@
+/*
+ * wd-mbwe.dtsi - Device tree file for Western Digital My Book World Edition
+ *
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * Licensed under GPLv2 or later
+ */
+
+/dts-v1/;
+#include "ox810se.dtsi"
+
+/ {
+	model = "Western Digital My Book World Edition";
+
+	compatible = "wd,mbwe", "oxsemi,ox810se";
+
+	chosen {
+		bootargs = "console=ttyS1,115200n8 earlyprintk=serial";
+	};
+
+	memory {
+		/* 128Mbytes DDR */
+		reg = <0x48000000 0x8000000>;
+	};
+
+	aliases {
+		serial1 = &uart1;
+		gpio0 = &gpio0;
+		gpio1 = &gpio1;
+	};
+
+	gpio-keys-polled {
+		compatible = "gpio-keys-polled";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		poll-interval = <100>;
+
+		power {
+			label = "power";
+			gpios = <&gpio0 0 1>;
+			linux,code = <0x198>;
+		};
+
+		recovery {
+			label = "recovery";
+			gpios = <&gpio0 4 1>;
+			linux,code = <0xab>;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		a0 {
+			label = "activity0";
+			gpios = <&gpio0 25 0>;
+			default-state = "keep";
+		};
+
+		a1 {
+			label = "activity1";
+			gpios = <&gpio0 26 0>;
+			default-state = "keep";
+		};
+
+		a2 {
+			label = "activity2";
+			gpios = <&gpio0 5 0>;
+			default-state = "keep";
+		};
+
+		a3 {
+			label = "activity3";
+			gpios = <&gpio0 6 0>;
+			default-state = "keep";
+		};
+
+		a4 {
+			label = "activity4";
+			gpios = <&gpio0 7 0>;
+			default-state = "keep";
+		};
+
+		a5 {
+			label = "activity5";
+			gpios = <&gpio1 2 0>;
+			default-state = "keep";
+		};
+	};
+
+	i2c-gpio {
+		compatible = "i2c-gpio";
+		gpios = <&gpio0 3 0 /* sda */
+			 &gpio0 2 0 /* scl */
+			 >;
+		i2c-gpio,delay-us = <2>;        /* ~100 kHz */
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		rtc0: rtc@48 {
+			compatible = "st,m41t00";
+			reg = <0x68>;
+		};
+	};
+};
+
+&uart1 {
+	status = "okay";
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/boot/Makefile linux-libre-4.7-gnu/arch/arm/boot/Makefile
--- linux-libre-4.6-gnu/arch/arm/boot/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/boot/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -82,13 +82,12 @@ $(obj)/uImage:	$(obj)/zImage FORCE
 
 $(obj)/bootp/bootp: $(obj)/zImage initrd FORCE
 	$(Q)$(MAKE) $(build)=$(obj)/bootp $@
-	@:
 
 $(obj)/bootpImage: $(obj)/bootp/bootp FORCE
 	$(call if_changed,objcopy)
 	@$(kecho) '  Kernel: $@ is ready'
 
-PHONY += initrd
+PHONY += initrd install zinstall uinstall
 initrd:
 	@test "$(INITRD_PHYS)" != "" || \
 	(echo This machine does not support INITRD; exit -1)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/configs/aspeed_g4_defconfig linux-libre-4.7-gnu/arch/arm/configs/aspeed_g4_defconfig
--- linux-libre-4.6-gnu/arch/arm/configs/aspeed_g4_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/configs/aspeed_g4_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,86 @@
+CONFIG_KERNEL_XZ=y
+CONFIG_SYSVIPC=y
+CONFIG_USELIB=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_NO_HZ_IDLE=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_CGROUPS=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_BPF_SYSCALL=y
+# CONFIG_SHMEM is not set
+# CONFIG_AIO is not set
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+CONFIG_CC_STACKPROTECTOR_STRONG=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLOCK is not set
+# CONFIG_ARCH_MULTI_V7 is not set
+CONFIG_ARCH_ASPEED=y
+CONFIG_MACH_ASPEED_G4=y
+CONFIG_DEBUG_RODATA=y
+CONFIG_AEABI=y
+CONFIG_UACCESS_WITH_MEMCPY=y
+CONFIG_SECCOMP=y
+# CONFIG_ATAGS is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_KEXEC=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_INPUT is not set
+# CONFIG_SERIO is not set
+# CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=6
+CONFIG_SERIAL_8250_RUNTIME_UARTS=6
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_HW_RANDOM is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_FIRMWARE_MEMMAP=y
+CONFIG_FANOTIFY=y
+CONFIG_PRINTK_TIME=1
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_STRIP_ASM_SYMS=y
+CONFIG_PAGE_POISONING=y
+CONFIG_DEBUG_KMEMLEAK=y
+CONFIG_DEBUG_SHIRQ=y
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_WQ_WATCHDOG=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_SCHED_STACK_END_CHECK=y
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_WW_MUTEX_SLOWPATH=y
+# CONFIG_FTRACE is not set
+CONFIG_MEMTEST=y
+CONFIG_UBSAN=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_LL=y
+CONFIG_DEBUG_LL_UART_8250=y
+CONFIG_DEBUG_UART_PHYS=0x1e784000
+CONFIG_DEBUG_UART_VIRT=0xe8784000
+CONFIG_EARLY_PRINTK=y
+CONFIG_DEBUG_SET_MODULE_RONX=y
+# CONFIG_XZ_DEC_X86 is not set
+# CONFIG_XZ_DEC_POWERPC is not set
+# CONFIG_XZ_DEC_IA64 is not set
+# CONFIG_XZ_DEC_SPARC is not set
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/configs/aspeed_g5_defconfig linux-libre-4.7-gnu/arch/arm/configs/aspeed_g5_defconfig
--- linux-libre-4.6-gnu/arch/arm/configs/aspeed_g5_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/configs/aspeed_g5_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,88 @@
+CONFIG_KERNEL_XZ=y
+CONFIG_SYSVIPC=y
+CONFIG_USELIB=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_NO_HZ_IDLE=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_CGROUPS=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_BPF_SYSCALL=y
+# CONFIG_SHMEM is not set
+# CONFIG_AIO is not set
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+CONFIG_CC_STACKPROTECTOR_STRONG=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLOCK is not set
+CONFIG_ARCH_MULTI_V6=y
+# CONFIG_ARCH_MULTI_V7 is not set
+CONFIG_ARCH_ASPEED=y
+CONFIG_MACH_ASPEED_G5=y
+CONFIG_DEBUG_RODATA=y
+CONFIG_AEABI=y
+CONFIG_UACCESS_WITH_MEMCPY=y
+CONFIG_SECCOMP=y
+# CONFIG_ATAGS is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_KEXEC=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_INPUT is not set
+# CONFIG_SERIO is not set
+# CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=6
+CONFIG_SERIAL_8250_RUNTIME_UARTS=6
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_HW_RANDOM is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_FIRMWARE_MEMMAP=y
+CONFIG_FANOTIFY=y
+CONFIG_PRINTK_TIME=1
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_STRIP_ASM_SYMS=y
+CONFIG_PAGE_POISONING=y
+CONFIG_DEBUG_KMEMLEAK=y
+CONFIG_DEBUG_SHIRQ=y
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_WQ_WATCHDOG=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_SCHED_STACK_END_CHECK=y
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_WW_MUTEX_SLOWPATH=y
+# CONFIG_FTRACE is not set
+CONFIG_MEMTEST=y
+CONFIG_UBSAN=y
+CONFIG_UBSAN_ALIGNMENT=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_LL=y
+CONFIG_DEBUG_LL_UART_8250=y
+CONFIG_DEBUG_UART_PHYS=0x1e784000
+CONFIG_DEBUG_UART_VIRT=0xe8784000
+CONFIG_EARLY_PRINTK=y
+CONFIG_DEBUG_SET_MODULE_RONX=y
+# CONFIG_XZ_DEC_X86 is not set
+# CONFIG_XZ_DEC_POWERPC is not set
+# CONFIG_XZ_DEC_IA64 is not set
+# CONFIG_XZ_DEC_SPARC is not set
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/configs/bcm2835_defconfig linux-libre-4.7-gnu/arch/arm/configs/bcm2835_defconfig
--- linux-libre-4.6-gnu/arch/arm/configs/bcm2835_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/configs/bcm2835_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -38,10 +38,13 @@ CONFIG_CRASH_DUMP=y
 CONFIG_VFP=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 # CONFIG_SUSPEND is not set
+CONFIG_PM=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
 CONFIG_NETWORK_SECMARK=y
 CONFIG_NETFILTER=y
 CONFIG_CFG80211=y
@@ -63,7 +66,6 @@ CONFIG_INPUT_EVDEV=y
 CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
 CONFIG_TTY_PRINTK=y
-CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_BCM2835=y
 CONFIG_SPI=y
@@ -73,10 +75,10 @@ CONFIG_GPIO_SYSFS=y
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
 CONFIG_BCM2835_WDT=y
-CONFIG_FB=y
+CONFIG_DRM=y
+CONFIG_DRM_VC4=y
 CONFIG_FB_SIMPLE=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
 CONFIG_SOUND=y
 CONFIG_SND=y
 CONFIG_SND_SOC=y
@@ -87,7 +89,7 @@ CONFIG_USB_DWC2=y
 CONFIG_MMC=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
-CONFIG_MMC_SDHCI_BCM2835=y
+CONFIG_MMC_SDHCI_IPROC=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_GPIO=y
@@ -122,6 +124,7 @@ CONFIG_TMPFS=y
 CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_MISC_FILESYSTEMS is not set
 CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
 CONFIG_NFSD=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ASCII=y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/configs/bcm_defconfig linux-libre-4.7-gnu/arch/arm/configs/bcm_defconfig
--- linux-libre-4.6-gnu/arch/arm/configs/bcm_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/configs/bcm_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -12,7 +12,6 @@ CONFIG_CGROUPS=y
 CONFIG_CGROUP_FREEZER=y
 CONFIG_CGROUP_DEVICE=y
 CONFIG_CGROUP_CPUACCT=y
-CONFIG_RESOURCE_COUNTERS=y
 CONFIG_CGROUP_SCHED=y
 CONFIG_BLK_CGROUP=y
 CONFIG_NAMESPACES=y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/configs/davinci_all_defconfig linux-libre-4.7-gnu/arch/arm/configs/davinci_all_defconfig
--- linux-libre-4.6-gnu/arch/arm/configs/davinci_all_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/configs/davinci_all_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -2,6 +2,7 @@ CONFIG_EXPERIMENTAL=y
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
@@ -70,8 +71,10 @@ CONFIG_MTD_CFI=m
 CONFIG_MTD_CFI_INTELEXT=m
 CONFIG_MTD_CFI_AMDSTD=m
 CONFIG_MTD_PHYSMAP=m
+CONFIG_MTD_M25P80=m
 CONFIG_MTD_NAND=m
 CONFIG_MTD_NAND_DAVINCI=m
+CONFIG_MTD_SPI_NOR=m
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_RAM=y
@@ -117,7 +120,10 @@ CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_DAVINCI=y
+CONFIG_SPI=y
+CONFIG_SPI_DAVINCI=m
 CONFIG_PINCTRL_SINGLE=y
+CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_PCF857X=y
 CONFIG_WATCHDOG=y
 CONFIG_DAVINCI_WATCHDOG=m
@@ -187,7 +193,6 @@ CONFIG_TI_EDMA=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 CONFIG_XFS_FS=m
-CONFIG_INOTIFY=y
 CONFIG_AUTOFS4_FS=m
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/configs/exynos_defconfig linux-libre-4.7-gnu/arch/arm/configs/exynos_defconfig
--- linux-libre-4.6-gnu/arch/arm/configs/exynos_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/configs/exynos_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -28,6 +28,10 @@ CONFIG_CMDLINE="root=/dev/ram0 rw ramdis
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_STAT_DETAILS=y
 CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=m
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=m
 CONFIG_CPUFREQ_DT=y
 CONFIG_CPU_IDLE=y
 CONFIG_ARM_EXYNOS_CPUIDLE=y
@@ -74,9 +78,11 @@ CONFIG_KEYBOARD_CROS_EC=y
 CONFIG_MOUSE_CYAPA=y
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_ATMEL_MXT=y
+CONFIG_TOUCHSCREEN_MMS114=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_MAX77693_HAPTIC=y
 CONFIG_INPUT_MAX8997_HAPTIC=y
+CONFIG_KEYBOARD_SAMSUNG=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_SAMSUNG=y
 CONFIG_SERIAL_SAMSUNG_CONSOLE=y
@@ -93,6 +99,7 @@ CONFIG_SPI=y
 CONFIG_SPI_GPIO=y
 CONFIG_SPI_S3C64XX=y
 CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_WM8994=y
 CONFIG_POWER_SUPPLY=y
 CONFIG_BATTERY_SBS=y
 CONFIG_BATTERY_MAX17040=y
@@ -134,6 +141,7 @@ CONFIG_REGULATOR_S2MPA01=y
 CONFIG_REGULATOR_S2MPS11=y
 CONFIG_REGULATOR_S5M8767=y
 CONFIG_REGULATOR_TPS65090=y
+CONFIG_REGULATOR_WM8994=y
 CONFIG_MEDIA_SUPPORT=m
 CONFIG_MEDIA_CAMERA_SUPPORT=y
 CONFIG_MEDIA_USB_SUPPORT=y
@@ -160,6 +168,8 @@ CONFIG_SOUND=y
 CONFIG_SND=y
 CONFIG_SND_SOC=y
 CONFIG_SND_SOC_SAMSUNG=y
+CONFIG_SND_SOC_SAMSUNG_SMDK_WM8994=y
+CONFIG_SND_SOC_SMDK_WM8994_PCM=y
 CONFIG_SND_SOC_SNOW=y
 CONFIG_SND_SOC_ODROIDX2=y
 CONFIG_SND_SIMPLE_CARD=y
@@ -210,6 +220,8 @@ CONFIG_EXTCON_MAX77693=y
 CONFIG_EXTCON_MAX8997=y
 CONFIG_IIO=y
 CONFIG_EXYNOS_ADC=y
+CONFIG_CM36651=y
+CONFIG_AK8975=y
 CONFIG_PWM=y
 CONFIG_PWM_SAMSUNG=y
 CONFIG_PHY_EXYNOS5250_SATA=y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/configs/imx_v6_v7_defconfig linux-libre-4.7-gnu/arch/arm/configs/imx_v6_v7_defconfig
--- linux-libre-4.6-gnu/arch/arm/configs/imx_v6_v7_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/configs/imx_v6_v7_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -142,6 +142,7 @@ CONFIG_SMC911X=y
 CONFIG_SMSC911X=y
 # CONFIG_NET_VENDOR_STMICRO is not set
 CONFIG_AT803X_PHY=y
+CONFIG_MICREL_PHY=y
 CONFIG_USB_PEGASUS=m
 CONFIG_USB_RTL8150=m
 CONFIG_USB_RTL8152=m
@@ -162,7 +163,9 @@ CONFIG_MOUSE_PS2_ELANTECH=y
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_EGALAX=y
 CONFIG_TOUCHSCREEN_IMX6UL_TSC=y
+CONFIG_TOUCHSCREEN_EDT_FT5X06=y
 CONFIG_TOUCHSCREEN_MC13783=y
+CONFIG_TOUCHSCREEN_TSC2004=y
 CONFIG_TOUCHSCREEN_TSC2007=y
 CONFIG_TOUCHSCREEN_STMPE=y
 CONFIG_TOUCHSCREEN_SX8654=y
@@ -178,9 +181,11 @@ CONFIG_SERIAL_FSL_LPUART=y
 CONFIG_SERIAL_FSL_LPUART_CONSOLE=y
 # CONFIG_I2C_COMPAT is not set
 CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MUX_GPIO=y
 # CONFIG_I2C_HELPER_AUTO is not set
 CONFIG_I2C_ALGOPCF=m
 CONFIG_I2C_ALGOPCA=m
+CONFIG_I2C_GPIO=y
 CONFIG_I2C_IMX=y
 CONFIG_SPI=y
 CONFIG_SPI_IMX=y
@@ -313,6 +318,7 @@ CONFIG_RTC_DRV_DS1307=y
 CONFIG_RTC_DRV_ISL1208=y
 CONFIG_RTC_DRV_PCF8523=y
 CONFIG_RTC_DRV_PCF8563=y
+CONFIG_RTC_DRV_M41T80=y
 CONFIG_RTC_DRV_MC13XXX=y
 CONFIG_RTC_DRV_MXC=y
 CONFIG_RTC_DRV_SNVS=y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/configs/keystone_defconfig linux-libre-4.7-gnu/arch/arm/configs/keystone_defconfig
--- linux-libre-4.6-gnu/arch/arm/configs/keystone_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/configs/keystone_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -30,6 +30,8 @@ CONFIG_PCI=y
 CONFIG_PCI_MSI=y
 CONFIG_PCI_KEYSTONE=y
 CONFIG_SMP=y
+CONFIG_HOTPLUG_CPU=y
+CONFIG_ARM_PSCI=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/configs/lpc32xx_defconfig linux-libre-4.7-gnu/arch/arm/configs/lpc32xx_defconfig
--- linux-libre-4.6-gnu/arch/arm/configs/lpc32xx_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/configs/lpc32xx_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -17,8 +17,6 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_ARCH_LPC32XX=y
-CONFIG_GPIO_PCA953X=y
-CONFIG_KEYBOARD_GPIO_POLLED=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
@@ -27,10 +25,8 @@ CONFIG_ARM_APPENDED_DTB=y
 CONFIG_ARM_ATAG_DTB_COMPAT=y
 CONFIG_CMDLINE="console=ttyS0,115200n81 root=/dev/ram0"
 CONFIG_CPU_IDLE=y
-CONFIG_FPE_NWFPE=y
 CONFIG_VFP=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_BINFMT_AOUT=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -42,10 +38,7 @@ CONFIG_IP_PNP_BOOTP=y
 # CONFIG_INET_XFRM_MODE_TRANSPORT is not set
 # CONFIG_INET_XFRM_MODE_TUNNEL is not set
 # CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
 # CONFIG_INET_DIAG is not set
-CONFIG_IPV6=y
-CONFIG_IPV6_PRIVACY=y
 # CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
@@ -53,9 +46,7 @@ CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
-CONFIG_MTD_M25P80=y
 CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_SLC_LPC32XX=y
 CONFIG_MTD_NAND_MLC_LPC32XX=y
@@ -70,7 +61,6 @@ CONFIG_EEPROM_AT25=y
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_NETDEVICES=y
-CONFIG_MII=y
 # CONFIG_NET_VENDOR_BROADCOM is not set
 # CONFIG_NET_VENDOR_CIRRUS is not set
 # CONFIG_NET_VENDOR_FARADAY is not set
@@ -91,6 +81,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=320
 CONFIG_INPUT_EVDEV=y
 # CONFIG_KEYBOARD_ATKBD is not set
 CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_GPIO_POLLED=y
 CONFIG_KEYBOARD_LPC32XX=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_TOUCHSCREEN=y
@@ -99,8 +90,8 @@ CONFIG_SERIO_LIBPS2=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_HS_LPC32XX=y
 CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_SERIAL_HS_LPC32XX=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
@@ -108,19 +99,20 @@ CONFIG_I2C_PNX=y
 CONFIG_SPI=y
 CONFIG_SPI_PL022=y
 CONFIG_GPIO_SYSFS=y
-CONFIG_GPIO_GENERIC_PLATFORM=y
 CONFIG_GPIO_EM=y
+CONFIG_GPIO_GENERIC_PLATFORM=y
 CONFIG_GPIO_PL061=y
+CONFIG_GPIO_ADP5588=y
+CONFIG_GPIO_ADNP=y
 CONFIG_GPIO_MAX7300=y
 CONFIG_GPIO_MAX732X=y
+CONFIG_GPIO_PCA953X=y
 CONFIG_GPIO_PCF857X=y
 CONFIG_GPIO_SX150X=y
-CONFIG_GPIO_ADP5588=y
-CONFIG_GPIO_ADNP=y
+CONFIG_GPIO_74X164=y
 CONFIG_GPIO_MAX7301=y
-CONFIG_GPIO_MCP23S08=y
 CONFIG_GPIO_MC33880=y
-CONFIG_GPIO_74X164=y
+CONFIG_GPIO_MCP23S08=y
 CONFIG_SENSORS_DS620=y
 CONFIG_SENSORS_MAX6639=y
 CONFIG_WATCHDOG=y
@@ -147,7 +139,6 @@ CONFIG_SND_DEBUG_VERBOSE=y
 # CONFIG_SND_SPI is not set
 CONFIG_SND_SOC=y
 CONFIG_USB=y
-CONFIG_USB_PHY=y
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
@@ -179,6 +170,8 @@ CONFIG_DMADEVICES=y
 CONFIG_AMBA_PL08X=y
 CONFIG_STAGING=y
 CONFIG_LPC32XX_ADC=y
+CONFIG_MEMORY=y
+CONFIG_ARM_PL172_MPMC=y
 CONFIG_IIO=y
 CONFIG_MAX517=y
 CONFIG_PWM=y
@@ -198,9 +191,9 @@ CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ASCII=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_NLS_UTF8=y
+CONFIG_DEBUG_INFO=y
 # CONFIG_SCHED_DEBUG is not set
 # CONFIG_DEBUG_PREEMPT is not set
-CONFIG_DEBUG_INFO=y
 # CONFIG_FTRACE is not set
 # CONFIG_ARM_UNWIND is not set
 CONFIG_DEBUG_LL=y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/configs/mps2_defconfig linux-libre-4.7-gnu/arch/arm/configs/mps2_defconfig
--- linux-libre-4.6-gnu/arch/arm/configs/mps2_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/configs/mps2_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,109 @@
+CONFIG_NO_HZ_IDLE=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EXPERT=y
+# CONFIG_UID16 is not set
+# CONFIG_BASE_FULL is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+# CONFIG_SIGNALFD is not set
+# CONFIG_EVENTFD is not set
+# CONFIG_AIO is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_BLOCK is not set
+# CONFIG_MMU is not set
+CONFIG_ARCH_MPS2=y
+CONFIG_SET_MEM_PARAM=y
+CONFIG_DRAM_BASE=0x21000000
+CONFIG_DRAM_SIZE=0x1000000
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_ATAGS is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_BINFMT_FLAT=y
+CONFIG_BINFMT_SHARED_FLAT=y
+# CONFIG_COREDUMP is not set
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_FW_LOADER is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NET_CORE is not set
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_HISILICON is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS 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_SMSC911X=y
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+# CONFIG_WLAN is not set
+# CONFIG_INPUT is not set
+# CONFIG_SERIO is not set
+# CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_MPS2_UART_CONSOLE=y
+CONFIG_SERIAL_MPS2_UART=y
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_ARM_SP805_WATCHDOG=y
+CONFIG_MFD_SYSCON=y
+# CONFIG_USB_SUPPORT is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_SYSCON=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_ONESHOT=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_CPU=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_ARM_TIMER_SP804=y
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY_USER is not set
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NFS_FS=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_V4_1=y
+CONFIG_NFS_V4_2=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_MEMTEST=y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/configs/multi_v5_defconfig linux-libre-4.7-gnu/arch/arm/configs/multi_v5_defconfig
--- linux-libre-4.6-gnu/arch/arm/configs/multi_v5_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/configs/multi_v5_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -1,18 +1,26 @@
 CONFIG_SYSVIPC=y
+CONFIG_FHANDLE=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_LOG_BUF_SHIFT=19
+CONFIG_CGROUPS=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=y
 CONFIG_KPROBES=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
 # CONFIG_ARCH_MULTI_V7 is not set
 CONFIG_ARCH_MVEBU=y
 CONFIG_MACH_KIRKWOOD=y
+CONFIG_ARCH_ASPEED=y
+CONFIG_MACH_ASPEED_G4=y
 CONFIG_ARCH_MXC=y
+CONFIG_MACH_MX21ADS=y
+CONFIG_MACH_MX27ADS=y
+CONFIG_MACH_MX27_3DS=y
+CONFIG_MACH_IMX27_VISSTRIM_M10=y
+CONFIG_MACH_PCA100=y
 CONFIG_MACH_IMX27_DT=y
 CONFIG_SOC_IMX25=y
 CONFIG_ARCH_ORION5X=y
@@ -60,13 +68,15 @@ CONFIG_IP_MULTICAST=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IPV6 is not set
 CONFIG_NET_DSA=y
 CONFIG_NET_SWITCHDEV=y
 CONFIG_NET_PKTGEN=m
 CONFIG_CFG80211=y
 CONFIG_MAC80211=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_IMX_WEIM=y
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_BLOCK=y
@@ -91,10 +101,7 @@ CONFIG_SATA_AHCI=y
 CONFIG_SATA_MV=y
 CONFIG_NETDEVICES=y
 CONFIG_NET_DSA_MV88E6060=y
-CONFIG_NET_DSA_MV88E6131=y
-CONFIG_NET_DSA_MV88E6123=y
-CONFIG_NET_DSA_MV88E6171=y
-CONFIG_NET_DSA_MV88E6352=y
+CONFIG_NET_DSA_MV88E6XXX=y
 CONFIG_MV643XX_ETH=y
 CONFIG_R8169=y
 CONFIG_MARVELL_PHY=y
@@ -108,15 +115,22 @@ CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_DEVKMEM is not set
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+CONFIG_SERIAL_8250_NR_UARTS=6
+CONFIG_SERIAL_8250_RUNTIME_UARTS=6
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
 CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_SERIAL_IMX=y
+CONFIG_SERIAL_IMX_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 # CONFIG_I2C_COMPAT is not set
 CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_IMX=y
 CONFIG_I2C_MV64XXX=y
 CONFIG_I2C_NOMADIK=y
 CONFIG_SPI=y
+CONFIG_SPI_IMX=y
 CONFIG_SPI_ORION=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_POWER_RESET=y
@@ -129,12 +143,13 @@ CONFIG_SENSORS_LM75=y
 CONFIG_SENSORS_LM85=y
 CONFIG_THERMAL=y
 CONFIG_KIRKWOOD_THERMAL=y
-CONFIG_WATCHDOG=y
 CONFIG_ORION_WATCHDOG=y
+CONFIG_IMX2_WDT=y
 # CONFIG_ABX500_CORE is not set
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_FB=y
+CONFIG_FB_IMX=y
 CONFIG_SOUND=y
 CONFIG_SND=y
 CONFIG_SND_SOC=y
@@ -158,7 +173,6 @@ CONFIG_HID_ZEROPLUS=y
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_ROOT_HUB_TT=y
 CONFIG_USB_PRINTER=m
 CONFIG_USB_STORAGE=y
 CONFIG_USB_STORAGE_DATAFAB=y
@@ -166,6 +180,8 @@ CONFIG_USB_STORAGE_FREECOM=y
 CONFIG_USB_STORAGE_SDDR09=y
 CONFIG_USB_STORAGE_SDDR55=y
 CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_CHIPIDEA=y
+CONFIG_USB_CHIPIDEA_HOST=y
 CONFIG_MMC=y
 CONFIG_SDIO_UART=y
 CONFIG_MMC_MVSDIO=y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/configs/multi_v7_defconfig linux-libre-4.7-gnu/arch/arm/configs/multi_v7_defconfig
--- linux-libre-4.6-gnu/arch/arm/configs/multi_v7_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/configs/multi_v7_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -105,7 +105,6 @@ CONFIG_ARCH_UNIPHIER=y
 CONFIG_ARCH_U8500=y
 CONFIG_MACH_HREFV60=y
 CONFIG_MACH_SNOWBALL=y
-CONFIG_MACH_UX500_DT=y
 CONFIG_ARCH_VEXPRESS=y
 CONFIG_ARCH_VEXPRESS_CA9X4=y
 CONFIG_ARCH_VEXPRESS_TC2_PM=y
@@ -119,7 +118,7 @@ CONFIG_PCI_MSI=y
 CONFIG_PCI_MVEBU=y
 CONFIG_PCI_TEGRA=y
 CONFIG_PCI_RCAR_GEN2=y
-CONFIG_PCI_RCAR_GEN2_PCIE=y
+CONFIG_PCIE_RCAR=y
 CONFIG_PCIEPORTBUS=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=16
@@ -131,6 +130,10 @@ CONFIG_KEXEC=y
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_STAT_DETAILS=y
 CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=m
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=m
 CONFIG_QORIQ_CPUFREQ=y
 CONFIG_CPU_IDLE=y
 CONFIG_ARM_CPUIDLE=y
@@ -183,6 +186,7 @@ CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_M25P80=y
 CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_DENALI_DT=y
 CONFIG_MTD_NAND_ATMEL=y
 CONFIG_MTD_NAND_BRCMNAND=y
 CONFIG_MTD_NAND_VF610_NFC=y
@@ -260,6 +264,7 @@ CONFIG_KEYBOARD_TEGRA=y
 CONFIG_KEYBOARD_SPEAR=y
 CONFIG_KEYBOARD_ST_KEYSCAN=y
 CONFIG_KEYBOARD_CROS_EC=m
+CONFIG_KEYBOARD_SAMSUNG=m
 CONFIG_MOUSE_PS2_ELANTECH=y
 CONFIG_MOUSE_CYAPA=m
 CONFIG_MOUSE_ELAN_I2C=y
@@ -322,6 +327,7 @@ CONFIG_I2C_MUX=y
 CONFIG_I2C_ARB_GPIO_CHALLENGE=m
 CONFIG_I2C_MUX_PCA954x=y
 CONFIG_I2C_MUX_PINCTRL=y
+CONFIG_I2C_DEMUX_PINCTRL=y
 CONFIG_I2C_AT91=m
 CONFIG_I2C_BCM2835=y
 CONFIG_I2C_CADENCE=y
@@ -345,6 +351,7 @@ CONFIG_I2C_UNIPHIER_F=y
 CONFIG_I2C_XILINX=y
 CONFIG_I2C_RCAR=y
 CONFIG_I2C_CROS_EC_TUNNEL=m
+CONFIG_I2C_SLAVE_EEPROM=y
 CONFIG_SPI=y
 CONFIG_SPI_ATMEL=m
 CONFIG_SPI_BCM2835=y
@@ -410,6 +417,7 @@ CONFIG_POWER_RESET_GPIO=y
 CONFIG_POWER_RESET_GPIO_RESTART=y
 CONFIG_POWER_RESET_KEYSTONE=y
 CONFIG_POWER_RESET_RMOBILE=y
+CONFIG_POWER_RESET_ST=y
 CONFIG_POWER_AVS=y
 CONFIG_ROCKCHIP_IODOMAIN=y
 CONFIG_SENSORS_IIO_HWMON=y
@@ -430,6 +438,8 @@ CONFIG_WATCHDOG=y
 CONFIG_DA9063_WATCHDOG=m
 CONFIG_XILINX_WATCHDOG=y
 CONFIG_ARM_SP805_WATCHDOG=y
+CONFIG_AT91SAM9X_WATCHDOG=y
+CONFIG_SAMA5D4_WATCHDOG=y
 CONFIG_ORION_WATCHDOG=y
 CONFIG_ST_LPC_WATCHDOG=y
 CONFIG_SUNXI_WATCHDOG=y
@@ -438,9 +448,11 @@ CONFIG_TEGRA_WATCHDOG=m
 CONFIG_MESON_WATCHDOG=y
 CONFIG_DW_WATCHDOG=y
 CONFIG_DIGICOLOR_WATCHDOG=y
+CONFIG_BCM2835_WDT=y
 CONFIG_MFD_AS3711=y
 CONFIG_MFD_AS3722=y
 CONFIG_MFD_ATMEL_FLEXCOM=y
+CONFIG_MFD_ATMEL_HLCDC=m
 CONFIG_MFD_BCM590XX=y
 CONFIG_MFD_AXP20X=y
 CONFIG_MFD_AXP20X_I2C=m
@@ -488,7 +500,7 @@ CONFIG_REGULATOR_MAX77693=m
 CONFIG_REGULATOR_MAX77802=m
 CONFIG_REGULATOR_PALMAS=y
 CONFIG_REGULATOR_PBIAS=y
-CONFIG_REGULATOR_PWM=m
+CONFIG_REGULATOR_PWM=y
 CONFIG_REGULATOR_QCOM_RPM=y
 CONFIG_REGULATOR_QCOM_SMD_RPM=y
 CONFIG_REGULATOR_S2MPS11=y
@@ -514,6 +526,7 @@ CONFIG_V4L_PLATFORM_DRIVERS=y
 CONFIG_SOC_CAMERA=m
 CONFIG_SOC_CAMERA_PLATFORM=m
 CONFIG_VIDEO_RCAR_VIN=m
+CONFIG_VIDEO_ATMEL_ISI=m
 CONFIG_V4L_MEM2MEM_DRIVERS=y
 CONFIG_VIDEO_RENESAS_JPU=m
 CONFIG_VIDEO_RENESAS_VSP1=m
@@ -532,7 +545,11 @@ CONFIG_DRM_EXYNOS_DSI=y
 CONFIG_DRM_EXYNOS_FIMD=y
 CONFIG_DRM_EXYNOS_HDMI=y
 CONFIG_DRM_ROCKCHIP=m
+CONFIG_ROCKCHIP_ANALOGIX_DP=m
 CONFIG_ROCKCHIP_DW_HDMI=m
+CONFIG_ROCKCHIP_DW_MIPI_DSI=m
+CONFIG_ROCKCHIP_INNO_HDMI=m
+CONFIG_DRM_ATMEL_HLCDC=m
 CONFIG_DRM_RCAR_DU=m
 CONFIG_DRM_RCAR_HDMI=y
 CONFIG_DRM_RCAR_LVDS=y
@@ -564,6 +581,8 @@ CONFIG_SND_USB_AUDIO=m
 CONFIG_SND_SOC=m
 CONFIG_SND_ATMEL_SOC=m
 CONFIG_SND_ATMEL_SOC_WM8904=m
+CONFIG_SND_ATMEL_SOC_PDMIC=m
+CONFIG_SND_BCM2835_SOC_I2S=m
 CONFIG_SND_SOC_FSL_SAI=m
 CONFIG_SND_SOC_ROCKCHIP=m
 CONFIG_SND_SOC_ROCKCHIP_SPDIF=m
@@ -592,6 +611,7 @@ CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_MVEBU=y
 CONFIG_USB_XHCI_RCAR=m
+CONFIG_USB_XHCI_TEGRA=m
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_MSM=m
 CONFIG_USB_EHCI_EXYNOS=y
@@ -609,7 +629,7 @@ CONFIG_USB_STORAGE=y
 CONFIG_USB_MUSB_HDRC=m
 CONFIG_USB_MUSB_SUNXI=m
 CONFIG_USB_DWC3=y
-CONFIG_USB_DWC2=m
+CONFIG_USB_DWC2=y
 CONFIG_USB_CHIPIDEA=y
 CONFIG_USB_CHIPIDEA_UDC=y
 CONFIG_USB_CHIPIDEA_HOST=y
@@ -640,7 +660,6 @@ CONFIG_MMC_SDHCI_SPEAR=y
 CONFIG_MMC_SDHCI_S3C=y
 CONFIG_MMC_SDHCI_S3C_DMA=y
 CONFIG_MMC_SDHCI_BCM_KONA=y
-CONFIG_MMC_SDHCI_BCM2835=y
 CONFIG_MMC_SDHCI_ST=y
 CONFIG_MMC_OMAP=y
 CONFIG_MMC_OMAP_HS=y
@@ -767,6 +786,7 @@ CONFIG_EXTCON=y
 CONFIG_TI_AEMIF=y
 CONFIG_IIO=y
 CONFIG_AT91_ADC=m
+CONFIG_AT91_SAMA5D2_ADC=m
 CONFIG_BERLIN2_ADC=m
 CONFIG_EXYNOS_ADC=m
 CONFIG_VF610_ADC=m
@@ -775,6 +795,7 @@ CONFIG_AK8975=y
 CONFIG_RASPBERRYPI_POWER=y
 CONFIG_PWM=y
 CONFIG_PWM_ATMEL=m
+CONFIG_PWM_ATMEL_HLCDC_PWM=m
 CONFIG_PWM_ATMEL_TCB=m
 CONFIG_PWM_FSL_FTM=m
 CONFIG_PWM_RENESAS_TPU=y
@@ -784,12 +805,13 @@ CONFIG_PWM_SUN4I=y
 CONFIG_PWM_TEGRA=y
 CONFIG_PWM_VT8500=y
 CONFIG_PHY_HIX5HD2_SATA=y
-CONFIG_PWM_STI=m
+CONFIG_PWM_STI=y
 CONFIG_PWM_BCM2835=y
 CONFIG_OMAP_USB2=y
 CONFIG_TI_PIPE3=y
 CONFIG_PHY_BERLIN_USB=y
 CONFIG_PHY_BERLIN_SATA=y
+CONFIG_PHY_ROCKCHIP_DP=m
 CONFIG_PHY_ROCKCHIP_USB=m
 CONFIG_PHY_QCOM_APQ8064_SATA=m
 CONFIG_PHY_MIPHY28LP=y
@@ -800,6 +822,7 @@ CONFIG_PHY_STIH407_USB=y
 CONFIG_PHY_SUN4I_USB=y
 CONFIG_PHY_SUN9I_USB=y
 CONFIG_PHY_SAMSUNG_USB2=m
+CONFIG_PHY_TEGRA_XUSB=y
 CONFIG_NVMEM=y
 CONFIG_NVMEM_SUNXI_SID=y
 CONFIG_BCM2835_MBOX=y
@@ -829,6 +852,9 @@ CONFIG_LOCKUP_DETECTOR=y
 CONFIG_CRYPTO_DEV_TEGRA_AES=y
 CONFIG_CPUFREQ_DT=y
 CONFIG_KEYSTONE_IRQ=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_ST=y
+CONFIG_CRYPTO_DEV_MARVELL_CESA=m
 CONFIG_CRYPTO_DEV_SUN4I_SS=m
 CONFIG_CRYPTO_DEV_ROCKCHIP=m
 CONFIG_ARM_CRYPTO=y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/configs/mvebu_v5_defconfig linux-libre-4.7-gnu/arch/arm/configs/mvebu_v5_defconfig
--- linux-libre-4.6-gnu/arch/arm/configs/mvebu_v5_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/configs/mvebu_v5_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -208,8 +208,8 @@ CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_PREEMPT is not set
 # CONFIG_FTRACE is not set
 CONFIG_DEBUG_USER=y
+CONFIG_CRYPTO_DEV_MARVELL_CESA=y
 CONFIG_CRYPTO_CBC=m
 CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_DEV_MV_CESA=y
 CONFIG_CRC_CCITT=y
 CONFIG_LIBCRC32C=y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/configs/mvebu_v7_defconfig linux-libre-4.7-gnu/arch/arm/configs/mvebu_v7_defconfig
--- linux-libre-4.6-gnu/arch/arm/configs/mvebu_v7_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/configs/mvebu_v7_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -66,7 +66,7 @@ CONFIG_SATA_AHCI=y
 CONFIG_AHCI_MVEBU=y
 CONFIG_SATA_MV=y
 CONFIG_NETDEVICES=y
-CONFIG_NET_DSA_MV88E6171=y
+CONFIG_NET_DSA_MV88E6XXX=y
 CONFIG_MV643XX_ETH=y
 CONFIG_MVNETA=y
 CONFIG_MVPP2=y
@@ -155,3 +155,4 @@ CONFIG_MAGIC_SYSRQ=y
 CONFIG_TIMER_STATS=y
 # CONFIG_DEBUG_BUGVERBOSE is not set
 CONFIG_DEBUG_USER=y
+CONFIG_CRYPTO_DEV_MARVELL_CESA=y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/configs/omap2plus_defconfig linux-libre-4.7-gnu/arch/arm/configs/omap2plus_defconfig
--- linux-libre-4.6-gnu/arch/arm/configs/omap2plus_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/configs/omap2plus_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -10,18 +10,17 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=16
 CONFIG_CGROUPS=y
-CONFIG_CGROUP_FREEZER=y
-CONFIG_CGROUP_DEVICE=y
-CONFIG_CPUSETS=y
-CONFIG_CGROUP_CPUACCT=y
 CONFIG_MEMCG=y
 CONFIG_MEMCG_SWAP=y
-CONFIG_MEMCG_KMEM=y
-CONFIG_CGROUP_PERF=y
+CONFIG_BLK_CGROUP=y
 CONFIG_CGROUP_SCHED=y
 CONFIG_CFS_BANDWIDTH=y
 CONFIG_RT_GROUP_SCHED=y
-CONFIG_BLK_CGROUP=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_PERF=y
 CONFIG_NAMESPACES=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_EXPERT=y
@@ -50,7 +49,6 @@ CONFIG_SOC_AM33XX=y
 CONFIG_SOC_AM43XX=y
 CONFIG_SOC_DRA7XX=y
 CONFIG_ARM_THUMBEE=y
-CONFIG_ARM_KERNMEM_PERMS=y
 CONFIG_ARM_ERRATA_411920=y
 CONFIG_ARM_ERRATA_430973=y
 CONFIG_SMP=y
@@ -69,7 +67,7 @@ CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
 CONFIG_CPU_FREQ_GOV_POWERSAVE=y
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
 CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
-CONFIG_CPUFREQ_DT=y
+CONFIG_CPUFREQ_DT=m
 # CONFIG_ARM_OMAP2PLUS_CPUFREQ is not set
 CONFIG_CPU_IDLE=y
 CONFIG_BINFMT_MISC=y
@@ -86,7 +84,6 @@ CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
 CONFIG_IP_PNP_RARP=y
-# CONFIG_INET_LRO is not set
 CONFIG_NETFILTER=y
 CONFIG_PHONET=m
 CONFIG_CAN=m
@@ -102,19 +99,18 @@ CONFIG_BT_HIDP=m
 CONFIG_BT_HCIBTUSB=m
 CONFIG_BT_HCIBTSDIO=m
 CONFIG_BT_HCIUART=m
-CONFIG_BT_HCIUART_H4=y
 CONFIG_BT_HCIUART_BCSP=y
 CONFIG_BT_HCIUART_LL=y
 CONFIG_BT_HCIUART_3WIRE=y
 CONFIG_BT_HCIBCM203X=m
 CONFIG_BT_HCIBPA10X=m
-CONFIG_CFG80211=m
 CONFIG_BT_HCIBFUSB=m
 CONFIG_BT_HCIVHCI=m
 CONFIG_BT_MRVL=m
 CONFIG_BT_MRVL_SDIO=m
 CONFIG_AF_RXRPC=m
-CONFIG_RXKAD=m
+CONFIG_RXKAD=y
+CONFIG_CFG80211=m
 CONFIG_MAC80211=m
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
@@ -129,6 +125,7 @@ CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_PHYSMAP=y
 CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_M25P80=m
 CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_ECC_BCH=y
 CONFIG_MTD_NAND_OMAP2=y
@@ -136,9 +133,8 @@ CONFIG_MTD_NAND_OMAP_BCH=y
 CONFIG_MTD_ONENAND=y
 CONFIG_MTD_ONENAND_VERIFY_WRITE=y
 CONFIG_MTD_ONENAND_OMAP2=y
-CONFIG_MTD_UBI=y
 CONFIG_MTD_SPI_NOR=m
-CONFIG_MTD_M25P80=m
+CONFIG_MTD_UBI=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=16384
@@ -184,22 +180,19 @@ CONFIG_USB_NET_SMSC95XX=m
 CONFIG_USB_ALI_M5632=y
 CONFIG_USB_AN2720=y
 CONFIG_USB_EPSON2888=y
-CONFIG_USB_EHCI_HCD=m
-CONFIG_USB_OHCI_HCD=m
 CONFIG_USB_KC2190=y
 CONFIG_USB_CDC_PHONET=m
 CONFIG_LIBERTAS=m
 CONFIG_LIBERTAS_USB=m
 CONFIG_LIBERTAS_SDIO=m
 CONFIG_LIBERTAS_DEBUG=y
-CONFIG_WL_TI=y
+CONFIG_MWIFIEX=m
+CONFIG_MWIFIEX_SDIO=m
+CONFIG_MWIFIEX_USB=m
 CONFIG_WL12XX=m
 CONFIG_WL18XX=m
 CONFIG_WLCORE_SPI=m
 CONFIG_WLCORE_SDIO=m
-CONFIG_MWIFIEX=m
-CONFIG_MWIFIEX_SDIO=m
-CONFIG_MWIFIEX_USB=m
 CONFIG_INPUT_JOYDEV=m
 CONFIG_INPUT_EVDEV=m
 CONFIG_KEYBOARD_ATKBD=m
@@ -211,10 +204,10 @@ CONFIG_KEYBOARD_TWL4030=m
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_ADS7846=m
 CONFIG_TOUCHSCREEN_EDT_FT5X06=m
+CONFIG_TOUCHSCREEN_TI_AM335X_TSC=m
 CONFIG_TOUCHSCREEN_PIXCIR=m
 CONFIG_TOUCHSCREEN_TSC2005=m
 CONFIG_TOUCHSCREEN_TSC2007=m
-CONFIG_TOUCHSCREEN_TI_AM335X_TSC=m
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_TPS65218_PWRBUTTON=m
 CONFIG_INPUT_TWL4030_PWRBUTTON=m
@@ -238,15 +231,14 @@ CONFIG_SPI_OMAP24XX=y
 CONFIG_SPI_TI_QSPI=m
 CONFIG_HSI=m
 CONFIG_OMAP_SSI=m
-CONFIG_NOKIA_MODEM=m
 CONFIG_SSI_PROTOCOL=m
 CONFIG_PINCTRL_SINGLE=y
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_PCA953X=m
 CONFIG_GPIO_PCF857X=y
-CONFIG_GPIO_TWL4030=y
 CONFIG_GPIO_PALMAS=y
+CONFIG_GPIO_TWL4030=y
 CONFIG_W1=m
 CONFIG_HDQ_MASTER_OMAP=m
 CONFIG_BATTERY_BQ27XXX=m
@@ -273,11 +265,11 @@ CONFIG_DRA752_THERMAL=y
 CONFIG_WATCHDOG=y
 CONFIG_OMAP_WATCHDOG=m
 CONFIG_TWL4030_WATCHDOG=m
+CONFIG_MFD_TI_AM335X_TSCADC=m
 CONFIG_MFD_PALMAS=y
 CONFIG_MFD_TPS65217=y
 CONFIG_MFD_TPS65218=y
 CONFIG_MFD_TPS65910=y
-CONFIG_MFD_TI_AM335X_TSCADC=m
 CONFIG_TWL6040_CORE=y
 CONFIG_REGULATOR_LP872X=y
 CONFIG_REGULATOR_PALMAS=y
@@ -292,8 +284,12 @@ CONFIG_REGULATOR_TPS65910=y
 CONFIG_REGULATOR_TWL4030=y
 CONFIG_MEDIA_SUPPORT=m
 CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_RC_SUPPORT=y
 CONFIG_MEDIA_CONTROLLER=y
 CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_LIRC=m
+CONFIG_RC_DEVICES=y
+CONFIG_IR_RX51=m
 CONFIG_V4L_PLATFORM_DRIVERS=y
 CONFIG_VIDEO_OMAP3=m
 # CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set
@@ -302,10 +298,10 @@ CONFIG_FB=y
 CONFIG_FIRMWARE_EDID=y
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_TILEBLITTING=y
+CONFIG_FB_OMAP2=m
 CONFIG_FB_OMAP5_DSS_HDMI=y
 CONFIG_FB_OMAP2_DSS_SDI=y
 CONFIG_FB_OMAP2_DSS_DSI=y
-CONFIG_FB_OMAP2=m
 CONFIG_FB_OMAP2_ENCODER_TFP410=m
 CONFIG_FB_OMAP2_ENCODER_TPD12S015=m
 CONFIG_FB_OMAP2_CONNECTOR_DVI=m
@@ -341,13 +337,11 @@ CONFIG_SND_USB_AUDIO=m
 CONFIG_SND_SOC=m
 CONFIG_SND_EDMA_SOC=m
 CONFIG_SND_AM33XX_SOC_EVM=m
-CONFIG_SND_DAVINCI_SOC_MCASP=m
 CONFIG_SND_OMAP_SOC=m
 CONFIG_SND_OMAP_SOC_OMAP_TWL4030=m
 CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040=m
 CONFIG_SND_OMAP_SOC_OMAP3_PANDORA=m
 CONFIG_SND_SIMPLE_CARD=m
-CONFIG_SND_SOC_TLV320AIC3X=m
 CONFIG_HID_GENERIC=m
 CONFIG_USB_HIDDEV=y
 CONFIG_USB_KBD=m
@@ -356,6 +350,8 @@ CONFIG_USB=m
 CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
 CONFIG_USB_MON=m
 CONFIG_USB_XHCI_HCD=m
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_OHCI_HCD=m
 CONFIG_USB_WDM=m
 CONFIG_USB_STORAGE=m
 CONFIG_USB_MUSB_HDRC=m
@@ -372,6 +368,7 @@ CONFIG_USB_SERIAL_FTDI_SIO=m
 CONFIG_USB_SERIAL_PL2303=m
 CONFIG_USB_TEST=m
 CONFIG_AM335X_PHY_USB=y
+CONFIG_TWL6030_USB=m
 CONFIG_USB_GADGET=m
 CONFIG_USB_GADGET_DEBUG=y
 CONFIG_USB_GADGET_DEBUG_FILES=y
@@ -402,8 +399,8 @@ CONFIG_MMC_OMAP_HS=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=m
 CONFIG_LEDS_GPIO=m
-CONFIG_LEDS_PWM=m
 CONFIG_LEDS_PCA963X=m
+CONFIG_LEDS_PWM=m
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=m
 CONFIG_LEDS_TRIGGER_ONESHOT=m
@@ -414,22 +411,22 @@ CONFIG_LEDS_TRIGGER_GPIO=m
 CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_DS1307=m
-CONFIG_RTC_DRV_PALMAS=m
 CONFIG_RTC_DRV_TWL92330=y
 CONFIG_RTC_DRV_TWL4030=m
+CONFIG_RTC_DRV_PALMAS=m
 CONFIG_RTC_DRV_OMAP=m
 CONFIG_DMADEVICES=y
-CONFIG_TI_EDMA=y
 CONFIG_DMA_OMAP=y
-CONFIG_IOMMU_SUPPORT=y
+CONFIG_TI_EDMA=y
 CONFIG_OMAP_IOMMU=y
 CONFIG_EXTCON=m
-CONFIG_EXTCON_USB_GPIO=m
 CONFIG_EXTCON_PALMAS=m
+CONFIG_EXTCON_USB_GPIO=m
 CONFIG_TI_EMIF=m
 CONFIG_IIO=m
 CONFIG_TI_AM335X_ADC=m
 CONFIG_PWM=y
+CONFIG_PWM_OMAP_DMTIMER=m
 CONFIG_PWM_TIECAP=m
 CONFIG_PWM_TIEHRPWM=m
 CONFIG_PWM_TWL=m
@@ -440,8 +437,6 @@ CONFIG_TI_PIPE3=y
 CONFIG_TWL4030_USB=m
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
-# CONFIG_EXT3_FS_XATTR is not set
-CONFIG_EXT4_FS=y
 CONFIG_FANOTIFY=y
 CONFIG_QUOTA=y
 CONFIG_QFMT_V2=y
@@ -476,7 +471,6 @@ CONFIG_PROVE_LOCKING=y
 # CONFIG_DEBUG_BUGVERBOSE is not set
 CONFIG_SECURITY=y
 CONFIG_CRYPTO_MICHAEL_MIC=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRC_CCITT=y
 CONFIG_CRC_T10DIF=y
 CONFIG_CRC_ITU_T=y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/configs/orion5x_defconfig linux-libre-4.7-gnu/arch/arm/configs/orion5x_defconfig
--- linux-libre-4.6-gnu/arch/arm/configs/orion5x_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/configs/orion5x_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -85,8 +85,7 @@ CONFIG_ATA=y
 CONFIG_SATA_MV=y
 CONFIG_NETDEVICES=y
 CONFIG_MII=y
-CONFIG_NET_DSA_MV88E6131=y
-CONFIG_NET_DSA_MV88E6123=y
+CONFIG_NET_DSA_MV88E6XXX=y
 CONFIG_MV643XX_ETH=y
 CONFIG_MARVELL_PHY=y
 # CONFIG_INPUT_MOUSEDEV is not set
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/configs/sama5_defconfig linux-libre-4.7-gnu/arch/arm/configs/sama5_defconfig
--- linux-libre-4.6-gnu/arch/arm/configs/sama5_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/configs/sama5_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -1,8 +1,10 @@
 # CONFIG_LOCALVERSION_AUTO is not set
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
+CONFIG_FHANDLE=y
 CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_LOG_BUF_SHIFT=14
+CONFIG_CGROUPS=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_EMBEDDED=y
 CONFIG_SLAB=y
@@ -133,6 +135,7 @@ CONFIG_WATCHDOG=y
 CONFIG_AT91SAM9X_WATCHDOG=y
 CONFIG_SAMA5D4_WATCHDOG=y
 CONFIG_MFD_ATMEL_FLEXCOM=y
+CONFIG_MFD_ATMEL_HLCDC=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_ACT8865=y
@@ -142,11 +145,14 @@ CONFIG_V4L_PLATFORM_DRIVERS=y
 CONFIG_SOC_CAMERA=y
 CONFIG_VIDEO_ATMEL_ISI=y
 CONFIG_SOC_CAMERA_OV2640=y
-CONFIG_FB=y
+CONFIG_DRM=y
+CONFIG_DRM_ATMEL_HLCDC=y
+CONFIG_DRM_PANEL_SIMPLE=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
-# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_LCD_CLASS_DEVICE=y
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
 # CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_BACKLIGHT_PWM=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_SOUND=y
 CONFIG_SND=y
@@ -154,6 +160,7 @@ CONFIG_SND_SOC=y
 CONFIG_SND_ATMEL_SOC=y
 CONFIG_SND_ATMEL_SOC_WM8904=y
 # CONFIG_HID_GENERIC is not set
+CONFIG_SND_ATMEL_SOC_PDMIC=y
 CONFIG_USB=y
 CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
 CONFIG_USB_EHCI_HCD=y
@@ -183,6 +190,7 @@ CONFIG_LEDS_TRIGGER_GPIO=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_AT91RM9200=y
 CONFIG_DMADEVICES=y
+CONFIG_AT_HDMAC=y
 CONFIG_AT_XDMAC=y
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_IIO=y
@@ -190,6 +198,7 @@ CONFIG_AT91_ADC=y
 CONFIG_AT91_SAMA5D2_ADC=y
 CONFIG_PWM=y
 CONFIG_PWM_ATMEL=y
+CONFIG_PWM_ATMEL_HLCDC_PWM=y
 CONFIG_PWM_ATMEL_TCB=y
 CONFIG_EXT4_FS=y
 CONFIG_FANOTIFY=y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/configs/shmobile_defconfig linux-libre-4.7-gnu/arch/arm/configs/shmobile_defconfig
--- linux-libre-4.6-gnu/arch/arm/configs/shmobile_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/configs/shmobile_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -24,7 +24,7 @@ CONFIG_PL310_ERRATA_588369=y
 CONFIG_ARM_ERRATA_754322=y
 CONFIG_PCI=y
 CONFIG_PCI_RCAR_GEN2=y
-CONFIG_PCI_RCAR_GEN2_PCIE=y
+CONFIG_PCIE_RCAR=y
 CONFIG_SMP=y
 CONFIG_SCHED_MC=y
 CONFIG_HAVE_ARM_ARCH_TIMER=y
@@ -99,11 +99,14 @@ CONFIG_SERIAL_SH_SCI=y
 CONFIG_SERIAL_SH_SCI_NR_UARTS=20
 CONFIG_SERIAL_SH_SCI_CONSOLE=y
 CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MUX=y
+CONFIG_I2C_DEMUX_PINCTRL=y
 CONFIG_I2C_EMEV2=y
 CONFIG_I2C_GPIO=y
 CONFIG_I2C_RIIC=y
 CONFIG_I2C_SH_MOBILE=y
 CONFIG_I2C_RCAR=y
+CONFIG_I2C_SLAVE_EEPROM=y
 CONFIG_SPI=y
 CONFIG_SPI_RSPI=y
 CONFIG_SPI_SH_MSIOF=y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/configs/tegra_defconfig linux-libre-4.7-gnu/arch/arm/configs/tegra_defconfig
--- linux-libre-4.6-gnu/arch/arm/configs/tegra_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/configs/tegra_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -218,6 +218,7 @@ CONFIG_SND_SOC_TEGRA_ALC5632=y
 CONFIG_SND_SOC_TEGRA_MAX98090=y
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_TEGRA=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_TEGRA=y
 CONFIG_USB_ACM=y
@@ -266,6 +267,7 @@ CONFIG_IIO=y
 CONFIG_AK8975=y
 CONFIG_PWM=y
 CONFIG_PWM_TEGRA=y
+CONFIG_PHY_TEGRA_XUSB=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/configs/u8500_defconfig linux-libre-4.7-gnu/arch/arm/configs/u8500_defconfig
--- linux-libre-4.6-gnu/arch/arm/configs/u8500_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/configs/u8500_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -45,7 +45,6 @@ CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=65536
-CONFIG_SENSORS_BH1780=y
 CONFIG_NETDEVICES=y
 CONFIG_SMSC911X=y
 CONFIG_SMSC_PHY=y
@@ -107,12 +106,12 @@ CONFIG_RTC_DRV_AB8500=y
 CONFIG_RTC_DRV_PL031=y
 CONFIG_DMADEVICES=y
 CONFIG_STE_DMA40=y
-CONFIG_STAGING=y
-CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y
 CONFIG_HSEM_U8500=y
 CONFIG_IIO=y
+CONFIG_IIO_BUFFER=y
 CONFIG_IIO_ST_ACCEL_3AXIS=y
 CONFIG_IIO_ST_GYRO_3AXIS=y
+CONFIG_BH1780=y
 CONFIG_IIO_ST_MAGN_3AXIS=y
 CONFIG_IIO_ST_PRESS=y
 CONFIG_EXT2_FS=y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/configs/zx_defconfig linux-libre-4.7-gnu/arch/arm/configs/zx_defconfig
--- linux-libre-4.6-gnu/arch/arm/configs/zx_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/configs/zx_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -7,7 +7,6 @@ CONFIG_CGROUPS=y
 CONFIG_CGROUP_DEBUG=y
 CONFIG_CGROUP_FREEZER=y
 CONFIG_CGROUP_CPUACCT=y
-CONFIG_RESOURCE_COUNTERS=y
 CONFIG_CGROUP_SCHED=y
 CONFIG_RT_GROUP_SCHED=y
 CONFIG_NAMESPACES=y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/include/asm/cpuidle.h linux-libre-4.7-gnu/arch/arm/include/asm/cpuidle.h
--- linux-libre-4.6-gnu/arch/arm/include/asm/cpuidle.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/include/asm/cpuidle.h	2016-07-24 15:23:50.000000000 -0400
@@ -36,7 +36,7 @@ struct cpuidle_ops {
 
 struct of_cpuidle_method {
 	const char *method;
-	struct cpuidle_ops *ops;
+	const struct cpuidle_ops *ops;
 };
 
 #define CPUIDLE_METHOD_OF_DECLARE(name, _method, _ops)			\
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/include/asm/dma-mapping.h linux-libre-4.7-gnu/arch/arm/include/asm/dma-mapping.h
--- linux-libre-4.6-gnu/arch/arm/include/asm/dma-mapping.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/include/asm/dma-mapping.h	2016-07-24 15:23:50.000000000 -0400
@@ -118,7 +118,7 @@ static inline unsigned long dma_max_pfn(
 
 #define arch_setup_dma_ops arch_setup_dma_ops
 extern void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
-			       struct iommu_ops *iommu, bool coherent);
+			       const struct iommu_ops *iommu, bool coherent);
 
 #define arch_teardown_dma_ops arch_teardown_dma_ops
 extern void arch_teardown_dma_ops(struct device *dev);
@@ -162,8 +162,6 @@ static inline bool dma_capable(struct de
 
 static inline void dma_mark_clean(void *addr, size_t size) { }
 
-extern int arm_dma_set_mask(struct device *dev, u64 dma_mask);
-
 /**
  * arm_dma_alloc - allocate consistent memory for DMA
  * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/include/asm/efi.h linux-libre-4.7-gnu/arch/arm/include/asm/efi.h
--- linux-libre-4.6-gnu/arch/arm/include/asm/efi.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/include/asm/efi.h	2016-07-24 15:23:50.000000000 -0400
@@ -17,34 +17,28 @@
 #include <asm/mach/map.h>
 #include <asm/mmu_context.h>
 #include <asm/pgtable.h>
+#include <asm/ptrace.h>
 
 #ifdef CONFIG_EFI
 void efi_init(void);
 
 int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md);
+int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md);
 
-#define efi_call_virt(f, ...)						\
-({									\
-	efi_##f##_t *__f;						\
-	efi_status_t __s;						\
-									\
-	efi_virtmap_load();						\
-	__f = efi.systab->runtime->f;					\
-	__s = __f(__VA_ARGS__);						\
-	efi_virtmap_unload();						\
-	__s;								\
-})
+#define arch_efi_call_virt_setup()	efi_virtmap_load()
+#define arch_efi_call_virt_teardown()	efi_virtmap_unload()
 
-#define __efi_call_virt(f, ...)						\
+#define arch_efi_call_virt(f, args...)					\
 ({									\
 	efi_##f##_t *__f;						\
-									\
-	efi_virtmap_load();						\
 	__f = efi.systab->runtime->f;					\
-	__f(__VA_ARGS__);						\
-	efi_virtmap_unload();						\
+	__f(args);							\
 })
 
+#define ARCH_EFI_IRQ_FLAGS_MASK \
+	(PSR_J_BIT | PSR_E_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT | \
+	 PSR_T_BIT | MODE_MASK)
+
 static inline void efi_set_pgd(struct mm_struct *mm)
 {
 	check_and_switch_context(mm, NULL);
@@ -59,7 +53,16 @@ void efi_virtmap_unload(void);
 
 /* arch specific definitions used by the stub code */
 
-#define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__)
+#define efi_call_early(f, ...)		sys_table_arg->boottime->f(__VA_ARGS__)
+#define __efi_call_early(f, ...)	f(__VA_ARGS__)
+#define efi_is_64bit()			(false)
+
+struct screen_info *alloc_screen_info(efi_system_table_t *sys_table_arg);
+void free_screen_info(efi_system_table_t *sys_table, struct screen_info *si);
+
+static inline void efifb_setup_from_dmi(struct screen_info *si, const char *opt)
+{
+}
 
 /*
  * A reasonable upper bound for the uncompressed kernel size is 32 MBytes,
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/include/asm/io.h linux-libre-4.7-gnu/arch/arm/include/asm/io.h
--- linux-libre-4.6-gnu/arch/arm/include/asm/io.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/include/asm/io.h	2016-07-24 15:23:50.000000000 -0400
@@ -392,9 +392,18 @@ void __iomem *ioremap(resource_size_t re
 #define ioremap ioremap
 #define ioremap_nocache ioremap
 
+/*
+ * Do not use ioremap_cache for mapping memory. Use memremap instead.
+ */
 void __iomem *ioremap_cache(resource_size_t res_cookie, size_t size);
 #define ioremap_cache ioremap_cache
 
+/*
+ * Do not use ioremap_cached in new code. Provided for the benefit of
+ * the pxa2xx-flash MTD driver only.
+ */
+void __iomem *ioremap_cached(resource_size_t res_cookie, size_t size);
+
 void __iomem *ioremap_wc(resource_size_t res_cookie, size_t size);
 #define ioremap_wc ioremap_wc
 #define ioremap_wt ioremap_wc
@@ -402,6 +411,9 @@ void __iomem *ioremap_wc(resource_size_t
 void iounmap(volatile void __iomem *iomem_cookie);
 #define iounmap iounmap
 
+void *arch_memremap_wb(phys_addr_t phys_addr, size_t size);
+#define arch_memremap_wb arch_memremap_wb
+
 /*
  * io{read,write}{16,32}be() macros
  */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/include/asm/kvm_host.h linux-libre-4.7-gnu/arch/arm/include/asm/kvm_host.h
--- linux-libre-4.6-gnu/arch/arm/include/asm/kvm_host.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/include/asm/kvm_host.h	2016-07-24 15:23:50.000000000 -0400
@@ -41,6 +41,8 @@
 
 #define KVM_MAX_VCPUS VGIC_V2_MAX_CPUS
 
+#define KVM_REQ_VCPU_EXIT	8
+
 u32 *kvm_vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num, u32 mode);
 int __attribute_const__ kvm_target_cpu(void);
 int kvm_reset_vcpu(struct kvm_vcpu *vcpu);
@@ -187,6 +189,7 @@ struct kvm_vm_stat {
 struct kvm_vcpu_stat {
 	u32 halt_successful_poll;
 	u32 halt_attempted_poll;
+	u32 halt_poll_invalid;
 	u32 halt_wakeup;
 	u32 hvc_exit_stat;
 	u64 wfe_exit_stat;
@@ -225,6 +228,10 @@ static inline void kvm_arch_mmu_notifier
 
 struct kvm_vcpu *kvm_arm_get_running_vcpu(void);
 struct kvm_vcpu __percpu **kvm_get_running_vcpus(void);
+void kvm_arm_halt_guest(struct kvm *kvm);
+void kvm_arm_resume_guest(struct kvm *kvm);
+void kvm_arm_halt_vcpu(struct kvm_vcpu *vcpu);
+void kvm_arm_resume_vcpu(struct kvm_vcpu *vcpu);
 
 int kvm_arm_copy_coproc_indices(struct kvm_vcpu *vcpu, u64 __user *uindices);
 unsigned long kvm_arm_num_coproc_regs(struct kvm_vcpu *vcpu);
@@ -265,6 +272,15 @@ static inline void __cpu_init_stage2(voi
 	kvm_call_hyp(__init_stage2_translation);
 }
 
+static inline void __cpu_reset_hyp_mode(phys_addr_t boot_pgd_ptr,
+					phys_addr_t phys_idmap_start)
+{
+	/*
+	 * TODO
+	 * kvm_call_reset(boot_pgd_ptr, phys_idmap_start);
+	 */
+}
+
 static inline int kvm_arch_dev_ioctl_check_extension(long ext)
 {
 	return 0;
@@ -277,11 +293,11 @@ void kvm_mmu_wp_memory_region(struct kvm
 
 struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr);
 
-static inline void kvm_arch_hardware_disable(void) {}
 static inline void kvm_arch_hardware_unsetup(void) {}
 static inline void kvm_arch_sync_events(struct kvm *kvm) {}
 static inline void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu) {}
 static inline void kvm_arch_sched_in(struct kvm_vcpu *vcpu, int cpu) {}
+static inline void kvm_arch_vcpu_block_finish(struct kvm_vcpu *vcpu) {}
 
 static inline void kvm_arm_init_debug(void) {}
 static inline void kvm_arm_setup_debug(struct kvm_vcpu *vcpu) {}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/include/asm/kvm_mmio.h linux-libre-4.7-gnu/arch/arm/include/asm/kvm_mmio.h
--- linux-libre-4.6-gnu/arch/arm/include/asm/kvm_mmio.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/include/asm/kvm_mmio.h	2016-07-24 15:23:50.000000000 -0400
@@ -28,6 +28,9 @@ struct kvm_decode {
 	bool sign_extend;
 };
 
+void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data);
+unsigned long kvm_mmio_read_buf(const void *buf, unsigned int len);
+
 int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run);
 int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
 		 phys_addr_t fault_ipa);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/include/asm/kvm_mmu.h linux-libre-4.7-gnu/arch/arm/include/asm/kvm_mmu.h
--- linux-libre-4.6-gnu/arch/arm/include/asm/kvm_mmu.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/include/asm/kvm_mmu.h	2016-07-24 15:23:50.000000000 -0400
@@ -47,6 +47,7 @@
 #include <linux/highmem.h>
 #include <asm/cacheflush.h>
 #include <asm/pgalloc.h>
+#include <asm/stage2_pgtable.h>
 
 int create_hyp_mappings(void *from, void *to);
 int create_hyp_io_mappings(void *from, void *to, phys_addr_t);
@@ -66,6 +67,7 @@ void kvm_mmu_free_memory_caches(struct k
 phys_addr_t kvm_mmu_get_httbr(void);
 phys_addr_t kvm_mmu_get_boot_httbr(void);
 phys_addr_t kvm_get_idmap_vector(void);
+phys_addr_t kvm_get_idmap_start(void);
 int kvm_mmu_init(void);
 void kvm_clear_hyp_idmap(void);
 
@@ -105,14 +107,16 @@ static inline void kvm_clean_pte(pte_t *
 	clean_pte_table(pte);
 }
 
-static inline void kvm_set_s2pte_writable(pte_t *pte)
+static inline pte_t kvm_s2pte_mkwrite(pte_t pte)
 {
-	pte_val(*pte) |= L_PTE_S2_RDWR;
+	pte_val(pte) |= L_PTE_S2_RDWR;
+	return pte;
 }
 
-static inline void kvm_set_s2pmd_writable(pmd_t *pmd)
+static inline pmd_t kvm_s2pmd_mkwrite(pmd_t pmd)
 {
-	pmd_val(*pmd) |= L_PMD_S2_RDWR;
+	pmd_val(pmd) |= L_PMD_S2_RDWR;
+	return pmd;
 }
 
 static inline void kvm_set_s2pte_readonly(pte_t *pte)
@@ -135,22 +139,6 @@ static inline bool kvm_s2pmd_readonly(pm
 	return (pmd_val(*pmd) & L_PMD_S2_RDWR) == L_PMD_S2_RDONLY;
 }
 
-
-/* Open coded p*d_addr_end that can deal with 64bit addresses */
-#define kvm_pgd_addr_end(addr, end)					\
-({	u64 __boundary = ((addr) + PGDIR_SIZE) & PGDIR_MASK;		\
-	(__boundary - 1 < (end) - 1)? __boundary: (end);		\
-})
-
-#define kvm_pud_addr_end(addr,end)		(end)
-
-#define kvm_pmd_addr_end(addr, end)					\
-({	u64 __boundary = ((addr) + PMD_SIZE) & PMD_MASK;		\
-	(__boundary - 1 < (end) - 1)? __boundary: (end);		\
-})
-
-#define kvm_pgd_index(addr)			pgd_index(addr)
-
 static inline bool kvm_page_empty(void *ptr)
 {
 	struct page *ptr_page = virt_to_page(ptr);
@@ -159,19 +147,11 @@ static inline bool kvm_page_empty(void *
 
 #define kvm_pte_table_empty(kvm, ptep) kvm_page_empty(ptep)
 #define kvm_pmd_table_empty(kvm, pmdp) kvm_page_empty(pmdp)
-#define kvm_pud_table_empty(kvm, pudp) (0)
-
-#define KVM_PREALLOC_LEVEL	0
-
-static inline void *kvm_get_hwpgd(struct kvm *kvm)
-{
-	return kvm->arch.pgd;
-}
+#define kvm_pud_table_empty(kvm, pudp) false
 
-static inline unsigned int kvm_get_hwpgd_size(void)
-{
-	return PTRS_PER_S2_PGD * sizeof(pgd_t);
-}
+#define hyp_pte_table_empty(ptep) kvm_page_empty(ptep)
+#define hyp_pmd_table_empty(pmdp) kvm_page_empty(pmdp)
+#define hyp_pud_table_empty(pudp) false
 
 struct kvm;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/include/asm/memory.h linux-libre-4.7-gnu/arch/arm/include/asm/memory.h
--- linux-libre-4.6-gnu/arch/arm/include/asm/memory.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/include/asm/memory.h	2016-07-24 15:23:50.000000000 -0400
@@ -288,19 +288,43 @@ static inline void *phys_to_virt(phys_ad
 #define __va(x)			((void *)__phys_to_virt((phys_addr_t)(x)))
 #define pfn_to_kaddr(pfn)	__va((phys_addr_t)(pfn) << PAGE_SHIFT)
 
-extern unsigned long (*arch_virt_to_idmap)(unsigned long x);
+extern long long arch_phys_to_idmap_offset;
 
 /*
- * These are for systems that have a hardware interconnect supported alias of
- * physical memory for idmap purposes.  Most cases should leave these
+ * These are for systems that have a hardware interconnect supported alias
+ * of physical memory for idmap purposes.  Most cases should leave these
  * untouched.  Note: this can only return addresses less than 4GiB.
  */
+static inline bool arm_has_idmap_alias(void)
+{
+	return IS_ENABLED(CONFIG_MMU) && arch_phys_to_idmap_offset != 0;
+}
+
+#define IDMAP_INVALID_ADDR ((u32)~0)
+
+static inline unsigned long phys_to_idmap(phys_addr_t addr)
+{
+	if (IS_ENABLED(CONFIG_MMU) && arch_phys_to_idmap_offset) {
+		addr += arch_phys_to_idmap_offset;
+		if (addr > (u32)~0)
+			addr = IDMAP_INVALID_ADDR;
+	}
+	return addr;
+}
+
+static inline phys_addr_t idmap_to_phys(unsigned long idmap)
+{
+	phys_addr_t addr = idmap;
+
+	if (IS_ENABLED(CONFIG_MMU) && arch_phys_to_idmap_offset)
+		addr -= arch_phys_to_idmap_offset;
+
+	return addr;
+}
+
 static inline unsigned long __virt_to_idmap(unsigned long x)
 {
-	if (IS_ENABLED(CONFIG_MMU) && arch_virt_to_idmap)
-		return arch_virt_to_idmap(x);
-	else
-		return __virt_to_phys(x);
+	return phys_to_idmap(__virt_to_phys(x));
 }
 
 #define virt_to_idmap(x)	__virt_to_idmap((unsigned long)(x))
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/include/asm/mmu_context.h linux-libre-4.7-gnu/arch/arm/include/asm/mmu_context.h
--- linux-libre-4.6-gnu/arch/arm/include/asm/mmu_context.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/include/asm/mmu_context.h	2016-07-24 15:23:50.000000000 -0400
@@ -15,6 +15,7 @@
 
 #include <linux/compiler.h>
 #include <linux/sched.h>
+#include <linux/preempt.h>
 #include <asm/cacheflush.h>
 #include <asm/cachetype.h>
 #include <asm/proc-fns.h>
@@ -66,6 +67,7 @@ static inline void check_and_switch_cont
 		cpu_switch_mm(mm->pgd, mm);
 }
 
+#ifndef MODULE
 #define finish_arch_post_lock_switch \
 	finish_arch_post_lock_switch
 static inline void finish_arch_post_lock_switch(void)
@@ -87,6 +89,7 @@ static inline void finish_arch_post_lock
 		preempt_enable_no_resched();
 	}
 }
+#endif /* !MODULE */
 
 #endif	/* CONFIG_MMU */
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/include/asm/pgalloc.h linux-libre-4.7-gnu/arch/arm/include/asm/pgalloc.h
--- linux-libre-4.6-gnu/arch/arm/include/asm/pgalloc.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/include/asm/pgalloc.h	2016-07-24 15:23:50.000000000 -0400
@@ -29,7 +29,7 @@
 
 static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
 {
-	return (pmd_t *)get_zeroed_page(GFP_KERNEL | __GFP_REPEAT);
+	return (pmd_t *)get_zeroed_page(GFP_KERNEL);
 }
 
 static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/include/asm/pgtable-2level.h linux-libre-4.7-gnu/arch/arm/include/asm/pgtable-2level.h
--- linux-libre-4.6-gnu/arch/arm/include/asm/pgtable-2level.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/include/asm/pgtable-2level.h	2016-07-24 15:23:50.000000000 -0400
@@ -193,6 +193,7 @@ static inline pmd_t *pmd_offset(pud_t *p
 
 #define pmd_large(pmd)		(pmd_val(pmd) & 2)
 #define pmd_bad(pmd)		(pmd_val(pmd) & 2)
+#define pmd_present(pmd)	(pmd_val(pmd))
 
 #define copy_pmd(pmdpd,pmdps)		\
 	do {				\
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/include/asm/pgtable-3level.h linux-libre-4.7-gnu/arch/arm/include/asm/pgtable-3level.h
--- linux-libre-4.6-gnu/arch/arm/include/asm/pgtable-3level.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/include/asm/pgtable-3level.h	2016-07-24 15:23:50.000000000 -0400
@@ -211,6 +211,7 @@ static inline pmd_t *pmd_offset(pud_t *p
 						: !!(pmd_val(pmd) & (val)))
 #define pmd_isclear(pmd, val)	(!(pmd_val(pmd) & (val)))
 
+#define pmd_present(pmd)	(pmd_isset((pmd), L_PMD_SECT_VALID))
 #define pmd_young(pmd)		(pmd_isset((pmd), PMD_SECT_AF))
 #define pte_special(pte)	(pte_isset((pte), L_PTE_SPECIAL))
 static inline pte_t pte_mkspecial(pte_t pte)
@@ -249,10 +250,10 @@ PMD_BIT_FUNC(mkyoung,   |= PMD_SECT_AF);
 #define pfn_pmd(pfn,prot)	(__pmd(((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot)))
 #define mk_pmd(page,prot)	pfn_pmd(page_to_pfn(page),prot)
 
-/* represent a notpresent pmd by zero, this is used by pmdp_invalidate */
+/* represent a notpresent pmd by faulting entry, this is used by pmdp_invalidate */
 static inline pmd_t pmd_mknotpresent(pmd_t pmd)
 {
-	return __pmd(0);
+	return __pmd(pmd_val(pmd) & ~L_PMD_SECT_VALID);
 }
 
 static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
@@ -281,11 +282,6 @@ static inline void set_pmd_at(struct mm_
 	flush_pmd_entry(pmdp);
 }
 
-static inline int has_transparent_hugepage(void)
-{
-	return 1;
-}
-
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_PGTABLE_3LEVEL_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/include/asm/pgtable.h linux-libre-4.7-gnu/arch/arm/include/asm/pgtable.h
--- linux-libre-4.6-gnu/arch/arm/include/asm/pgtable.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/include/asm/pgtable.h	2016-07-24 15:23:50.000000000 -0400
@@ -182,7 +182,6 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD
 #define pgd_offset_k(addr)	pgd_offset(&init_mm, addr)
 
 #define pmd_none(pmd)		(!pmd_val(pmd))
-#define pmd_present(pmd)	(pmd_val(pmd))
 
 static inline pte_t *pmd_page_vaddr(pmd_t pmd)
 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/include/asm/stage2_pgtable.h linux-libre-4.7-gnu/arch/arm/include/asm/stage2_pgtable.h
--- linux-libre-4.6-gnu/arch/arm/include/asm/stage2_pgtable.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/include/asm/stage2_pgtable.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2016 - ARM Ltd
+ *
+ * stage2 page table helpers
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ARM_S2_PGTABLE_H_
+#define __ARM_S2_PGTABLE_H_
+
+#define stage2_pgd_none(pgd)			pgd_none(pgd)
+#define stage2_pgd_clear(pgd)			pgd_clear(pgd)
+#define stage2_pgd_present(pgd)			pgd_present(pgd)
+#define stage2_pgd_populate(pgd, pud)		pgd_populate(NULL, pgd, pud)
+#define stage2_pud_offset(pgd, address)		pud_offset(pgd, address)
+#define stage2_pud_free(pud)			pud_free(NULL, pud)
+
+#define stage2_pud_none(pud)			pud_none(pud)
+#define stage2_pud_clear(pud)			pud_clear(pud)
+#define stage2_pud_present(pud)			pud_present(pud)
+#define stage2_pud_populate(pud, pmd)		pud_populate(NULL, pud, pmd)
+#define stage2_pmd_offset(pud, address)		pmd_offset(pud, address)
+#define stage2_pmd_free(pmd)			pmd_free(NULL, pmd)
+
+#define stage2_pud_huge(pud)			pud_huge(pud)
+
+/* Open coded p*d_addr_end that can deal with 64bit addresses */
+static inline phys_addr_t stage2_pgd_addr_end(phys_addr_t addr, phys_addr_t end)
+{
+	phys_addr_t boundary = (addr + PGDIR_SIZE) & PGDIR_MASK;
+
+	return (boundary - 1 < end - 1) ? boundary : end;
+}
+
+#define stage2_pud_addr_end(addr, end)		(end)
+
+static inline phys_addr_t stage2_pmd_addr_end(phys_addr_t addr, phys_addr_t end)
+{
+	phys_addr_t boundary = (addr + PMD_SIZE) & PMD_MASK;
+
+	return (boundary - 1 < end - 1) ? boundary : end;
+}
+
+#define stage2_pgd_index(addr)				pgd_index(addr)
+
+#define stage2_pte_table_empty(ptep)			kvm_page_empty(ptep)
+#define stage2_pmd_table_empty(pmdp)			kvm_page_empty(pmdp)
+#define stage2_pud_table_empty(pudp)			false
+
+#endif	/* __ARM_S2_PGTABLE_H_ */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/Kconfig linux-libre-4.7-gnu/arch/arm/Kconfig
--- linux-libre-4.6-gnu/arch/arm/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -41,7 +41,7 @@ config ARM
 	select HAVE_ARCH_SECCOMP_FILTER if (AEABI && !OABI_COMPAT)
 	select HAVE_ARCH_TRACEHOOK
 	select HAVE_ARM_SMCCC if CPU_V7
-	select HAVE_BPF_JIT
+	select HAVE_CBPF_JIT
 	select HAVE_CC_STACKPROTECTOR
 	select HAVE_CONTEXT_TRACKING
 	select HAVE_C_RECORDMCOUNT
@@ -50,6 +50,7 @@ config ARM
 	select HAVE_DMA_CONTIGUOUS if MMU
 	select HAVE_DYNAMIC_FTRACE if (!XIP_KERNEL) && !CPU_ENDIAN_BE32 && MMU
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS if (CPU_V6 || CPU_V6K || CPU_V7) && MMU
+	select HAVE_EXIT_THREAD
 	select HAVE_FTRACE_MCOUNT_RECORD if (!XIP_KERNEL)
 	select HAVE_FUNCTION_GRAPH_TRACER if (!THUMB2_KERNEL)
 	select HAVE_FUNCTION_TRACER if (!XIP_KERNEL)
@@ -66,6 +67,7 @@ config ARM
 	select HAVE_KRETPROBES if (HAVE_KPROBES)
 	select HAVE_MEMBLOCK
 	select HAVE_MOD_ARCH_SPECIFIC
+	select HAVE_NMI
 	select HAVE_OPROFILE if (HAVE_PERF_EVENTS)
 	select HAVE_OPTPROBES if !THUMB2_KERNEL
 	select HAVE_PERF_EVENTS
@@ -531,6 +533,8 @@ config ARCH_LPC32XX
 	select COMMON_CLK
 	select CPU_ARM926T
 	select GENERIC_CLOCKEVENTS
+	select MULTI_IRQ_HANDLER
+	select SPARSE_IRQ
 	select USE_OF
 	help
 	  Support for the NXP LPC32XX family of processors
@@ -775,6 +779,8 @@ source "arch/arm/mach-meson/Kconfig"
 
 source "arch/arm/mach-moxart/Kconfig"
 
+source "arch/arm/mach-aspeed/Kconfig"
+
 source "arch/arm/mach-mv78xx0/Kconfig"
 
 source "arch/arm/mach-imx/Kconfig"
@@ -804,6 +810,8 @@ source "arch/arm/plat-pxa/Kconfig"
 
 source "arch/arm/mach-mmp/Kconfig"
 
+source "arch/arm/mach-oxnas/Kconfig"
+
 source "arch/arm/mach-qcom/Kconfig"
 
 source "arch/arm/mach-realview/Kconfig"
@@ -892,6 +900,18 @@ config MACH_STM32F429
 	depends on ARCH_STM32
 	default y
 
+config ARCH_MPS2
+	bool "ARM MPS2 paltform"
+	depends on ARM_SINGLE_ARMV7M
+	select ARM_AMBA
+	select CLKSRC_MPS2
+	help
+	  Support for Cortex-M Prototyping System (or V2M-MPS2) which comes
+	  with a range of available cores like Cortex-M3/M4/M7.
+
+	  Please, note that depends which Application Note is used memory map
+	  for the platform may vary, so adjustment of RAM base might be needed.
+
 # Definitions to make life easier
 config ARCH_ACORN
 	bool
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/Kconfig.debug linux-libre-4.7-gnu/arch/arm/Kconfig.debug
--- linux-libre-4.6-gnu/arch/arm/Kconfig.debug	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/Kconfig.debug	2016-07-24 15:23:50.000000000 -0400
@@ -268,14 +268,6 @@ choice
 		  Say Y here if you want kernel low-level debugging support
 		  on HI3620 UART.
 
-	config DEBUG_HI3716_UART
-		bool "Hisilicon Hi3716 Debug UART"
-		depends on ARCH_HI3xxx
-		select DEBUG_UART_PL01X
-		help
-		  Say Y here if you want kernel low-level debugging support
-		  on HI3716 UART.
-
 	config DEBUG_HIGHBANK_UART
 		bool "Kernel low-level debugging messages via Highbank UART"
 		depends on ARCH_HIGHBANK
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/kernel/bios32.c linux-libre-4.7-gnu/arch/arm/kernel/bios32.c
--- linux-libre-4.6-gnu/arch/arm/kernel/bios32.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/kernel/bios32.c	2016-07-24 15:23:50.000000000 -0400
@@ -550,9 +550,6 @@ char * __init pcibios_setup(char *str)
 	if (!strcmp(str, "debug")) {
 		debug_pci = 1;
 		return NULL;
-	} else if (!strcmp(str, "firmware")) {
-		pci_add_flags(PCI_PROBE_ONLY);
-		return NULL;
 	}
 	return str;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/kernel/cpuidle.c linux-libre-4.7-gnu/arch/arm/kernel/cpuidle.c
--- linux-libre-4.6-gnu/arch/arm/kernel/cpuidle.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/kernel/cpuidle.c	2016-07-24 15:23:50.000000000 -0400
@@ -70,7 +70,7 @@ int arm_cpuidle_suspend(int index)
  *
  * Returns a struct cpuidle_ops pointer, NULL if not found.
  */
-static struct cpuidle_ops *__init arm_cpuidle_get_ops(const char *method)
+static const struct cpuidle_ops *__init arm_cpuidle_get_ops(const char *method)
 {
 	struct of_cpuidle_method *m = __cpuidle_method_of_table;
 
@@ -88,7 +88,7 @@ static struct cpuidle_ops *__init arm_cp
  *
  * Get the method name defined in the 'enable-method' property, retrieve the
  * associated cpuidle_ops and do a struct copy. This copy is needed because all
- * cpuidle_ops are tagged __initdata and will be unloaded after the init
+ * cpuidle_ops are tagged __initconst and will be unloaded after the init
  * process.
  *
  * Return 0 on sucess, -ENOENT if no 'enable-method' is defined, -EOPNOTSUPP if
@@ -97,7 +97,7 @@ static struct cpuidle_ops *__init arm_cp
 static int __init arm_cpuidle_read_ops(struct device_node *dn, int cpu)
 {
 	const char *enable_method;
-	struct cpuidle_ops *ops;
+	const struct cpuidle_ops *ops;
 
 	enable_method = of_get_property(dn, "enable-method", NULL);
 	if (!enable_method)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/kernel/efi.c linux-libre-4.7-gnu/arch/arm/kernel/efi.c
--- linux-libre-4.6-gnu/arch/arm/kernel/efi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/kernel/efi.c	2016-07-24 15:23:50.000000000 -0400
@@ -11,6 +11,41 @@
 #include <asm/mach/map.h>
 #include <asm/mmu_context.h>
 
+static int __init set_permissions(pte_t *ptep, pgtable_t token,
+				  unsigned long addr, void *data)
+{
+	efi_memory_desc_t *md = data;
+	pte_t pte = *ptep;
+
+	if (md->attribute & EFI_MEMORY_RO)
+		pte = set_pte_bit(pte, __pgprot(L_PTE_RDONLY));
+	if (md->attribute & EFI_MEMORY_XP)
+		pte = set_pte_bit(pte, __pgprot(L_PTE_XN));
+	set_pte_ext(ptep, pte, PTE_EXT_NG);
+	return 0;
+}
+
+int __init efi_set_mapping_permissions(struct mm_struct *mm,
+				       efi_memory_desc_t *md)
+{
+	unsigned long base, size;
+
+	base = md->virt_addr;
+	size = md->num_pages << EFI_PAGE_SHIFT;
+
+	/*
+	 * We can only use apply_to_page_range() if we can guarantee that the
+	 * entire region was mapped using pages. This should be the case if the
+	 * region does not cover any naturally aligned SECTION_SIZE sized
+	 * blocks.
+	 */
+	if (round_down(base + size, SECTION_SIZE) <
+	    round_up(base, SECTION_SIZE) + SECTION_SIZE)
+		return apply_to_page_range(mm, base, size, set_permissions, md);
+
+	return 0;
+}
+
 int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md)
 {
 	struct map_desc desc = {
@@ -34,5 +69,11 @@ int __init efi_create_mapping(struct mm_
 		desc.type = MT_DEVICE;
 
 	create_mapping_late(mm, &desc, true);
+
+	/*
+	 * If stricter permissions were specified, apply them now.
+	 */
+	if (md->attribute & (EFI_MEMORY_RO | EFI_MEMORY_XP))
+		return efi_set_mapping_permissions(mm, md);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/kernel/hw_breakpoint.c linux-libre-4.7-gnu/arch/arm/kernel/hw_breakpoint.c
--- linux-libre-4.6-gnu/arch/arm/kernel/hw_breakpoint.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/kernel/hw_breakpoint.c	2016-07-24 15:23:50.000000000 -0400
@@ -631,7 +631,7 @@ int arch_validate_hwbkpt_settings(struct
 	info->address &= ~alignment_mask;
 	info->ctrl.len <<= offset;
 
-	if (!bp->overflow_handler) {
+	if (is_default_overflow_handler(bp)) {
 		/*
 		 * Mismatch breakpoints are required for single-stepping
 		 * breakpoints.
@@ -754,7 +754,7 @@ static void watchpoint_handler(unsigned
 		 * mismatch breakpoint so we can single-step over the
 		 * watchpoint trigger.
 		 */
-		if (!wp->overflow_handler)
+		if (is_default_overflow_handler(wp))
 			enable_single_step(wp, instruction_pointer(regs));
 
 unlock:
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/kernel/perf_callchain.c linux-libre-4.7-gnu/arch/arm/kernel/perf_callchain.c
--- linux-libre-4.6-gnu/arch/arm/kernel/perf_callchain.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/kernel/perf_callchain.c	2016-07-24 15:23:50.000000000 -0400
@@ -31,7 +31,7 @@ struct frame_tail {
  */
 static struct frame_tail __user *
 user_backtrace(struct frame_tail __user *tail,
-	       struct perf_callchain_entry *entry)
+	       struct perf_callchain_entry_ctx *entry)
 {
 	struct frame_tail buftail;
 	unsigned long err;
@@ -59,7 +59,7 @@ user_backtrace(struct frame_tail __user
 }
 
 void
-perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
+perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs)
 {
 	struct frame_tail __user *tail;
 
@@ -75,7 +75,7 @@ perf_callchain_user(struct perf_callchai
 
 	tail = (struct frame_tail __user *)regs->ARM_fp - 1;
 
-	while ((entry->nr < PERF_MAX_STACK_DEPTH) &&
+	while ((entry->nr < entry->max_stack) &&
 	       tail && !((unsigned long)tail & 0x3))
 		tail = user_backtrace(tail, entry);
 }
@@ -89,13 +89,13 @@ static int
 callchain_trace(struct stackframe *fr,
 		void *data)
 {
-	struct perf_callchain_entry *entry = data;
+	struct perf_callchain_entry_ctx *entry = data;
 	perf_callchain_store(entry, fr->pc);
 	return 0;
 }
 
 void
-perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs)
+perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs)
 {
 	struct stackframe fr;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/kernel/process.c linux-libre-4.7-gnu/arch/arm/kernel/process.c
--- linux-libre-4.6-gnu/arch/arm/kernel/process.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/kernel/process.c	2016-07-24 15:23:50.000000000 -0400
@@ -193,9 +193,9 @@ EXPORT_SYMBOL_GPL(thread_notify_head);
 /*
  * Free current thread data structures etc..
  */
-void exit_thread(void)
+void exit_thread(struct task_struct *tsk)
 {
-	thread_notify(THREAD_NOTIFY_EXIT, current_thread_info());
+	thread_notify(THREAD_NOTIFY_EXIT, task_thread_info(tsk));
 }
 
 void flush_thread(void)
@@ -420,7 +420,8 @@ int arch_setup_additional_pages(struct l
 	npages = 1; /* for sigpage */
 	npages += vdso_total_pages;
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
 	hint = sigpage_addr(mm, npages);
 	addr = get_unmapped_area(NULL, hint, npages << PAGE_SHIFT, 0, 0);
 	if (IS_ERR_VALUE(addr)) {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/kernel/ptrace.c linux-libre-4.7-gnu/arch/arm/kernel/ptrace.c
--- linux-libre-4.6-gnu/arch/arm/kernel/ptrace.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/kernel/ptrace.c	2016-07-24 15:23:50.000000000 -0400
@@ -733,8 +733,8 @@ static int vfp_set(struct task_struct *t
 	if (ret)
 		return ret;
 
-	vfp_flush_hwstate(thread);
 	thread->vfpstate.hard = new_vfp;
+	vfp_flush_hwstate(thread);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/kernel/reboot.c linux-libre-4.7-gnu/arch/arm/kernel/reboot.c
--- linux-libre-4.6-gnu/arch/arm/kernel/reboot.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/kernel/reboot.c	2016-07-24 15:23:50.000000000 -0400
@@ -104,8 +104,6 @@ void machine_halt(void)
 {
 	local_irq_disable();
 	smp_send_stop();
-
-	local_irq_disable();
 	while (1);
 }
 
@@ -150,6 +148,5 @@ void machine_restart(char *cmd)
 
 	/* Whoops - the platform was unable to reboot. Tell the user! */
 	printk("Reboot failed -- System halted\n");
-	local_irq_disable();
 	while (1);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/kernel/setup.c linux-libre-4.7-gnu/arch/arm/kernel/setup.c
--- linux-libre-4.6-gnu/arch/arm/kernel/setup.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/kernel/setup.c	2016-07-24 15:23:50.000000000 -0400
@@ -883,7 +883,8 @@ static void __init request_standard_reso
 		request_resource(&ioport_resource, &lp2);
 }
 
-#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
+#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE) || \
+    defined(CONFIG_EFI)
 struct screen_info screen_info = {
  .orig_video_lines	= 30,
  .orig_video_cols	= 80,
@@ -940,6 +941,12 @@ static int __init init_machine_late(void
 late_initcall(init_machine_late);
 
 #ifdef CONFIG_KEXEC
+/*
+ * The crash region must be aligned to 128MB to avoid
+ * zImage relocating below the reserved region.
+ */
+#define CRASH_ALIGN	(128 << 20)
+
 static inline unsigned long long get_total_mem(void)
 {
 	unsigned long total;
@@ -967,6 +974,26 @@ static void __init reserve_crashkernel(v
 	if (ret)
 		return;
 
+	if (crash_base <= 0) {
+		unsigned long long crash_max = idmap_to_phys((u32)~0);
+		crash_base = memblock_find_in_range(CRASH_ALIGN, crash_max,
+						    crash_size, CRASH_ALIGN);
+		if (!crash_base) {
+			pr_err("crashkernel reservation failed - No suitable area found.\n");
+			return;
+		}
+	} else {
+		unsigned long long start;
+
+		start = memblock_find_in_range(crash_base,
+					       crash_base + crash_size,
+					       crash_size, SECTION_SIZE);
+		if (start != crash_base) {
+			pr_err("crashkernel reservation failed - memory is in use.\n");
+			return;
+		}
+	}
+
 	ret = memblock_reserve(crash_base, crash_size);
 	if (ret < 0) {
 		pr_warn("crashkernel reservation failed - memory is in use (0x%lx)\n",
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/kernel/smp.c linux-libre-4.7-gnu/arch/arm/kernel/smp.c
--- linux-libre-4.6-gnu/arch/arm/kernel/smp.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/kernel/smp.c	2016-07-24 15:23:50.000000000 -0400
@@ -486,7 +486,7 @@ static const char *ipi_types[NR_IPI] __t
 
 static void smp_cross_call(const struct cpumask *target, unsigned int ipinr)
 {
-	trace_ipi_raise(target, ipi_types[ipinr]);
+	trace_ipi_raise_rcuidle(target, ipi_types[ipinr]);
 	__smp_cross_call(target, ipinr);
 }
 
@@ -644,9 +644,11 @@ void handle_IPI(int ipinr, struct pt_reg
 		break;
 
 	case IPI_CPU_BACKTRACE:
+		printk_nmi_enter();
 		irq_enter();
 		nmi_cpu_backtrace(regs);
 		irq_exit();
+		printk_nmi_exit();
 		break;
 
 	default:
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/kvm/arm.c linux-libre-4.7-gnu/arch/arm/kvm/arm.c
--- linux-libre-4.6-gnu/arch/arm/kvm/arm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/kvm/arm.c	2016-07-24 15:23:50.000000000 -0400
@@ -16,7 +16,6 @@
  * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
-#include <linux/cpu.h>
 #include <linux/cpu_pm.h>
 #include <linux/errno.h>
 #include <linux/err.h>
@@ -66,6 +65,8 @@ static DEFINE_SPINLOCK(kvm_vmid_lock);
 
 static bool vgic_present;
 
+static DEFINE_PER_CPU(unsigned char, kvm_arm_hardware_enabled);
+
 static void kvm_arm_set_running_vcpu(struct kvm_vcpu *vcpu)
 {
 	BUG_ON(preemptible());
@@ -90,11 +91,6 @@ struct kvm_vcpu * __percpu *kvm_get_runn
 	return &kvm_arm_running_vcpu;
 }
 
-int kvm_arch_hardware_enable(void)
-{
-	return 0;
-}
-
 int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
 {
 	return kvm_vcpu_exiting_guest_mode(vcpu) == IN_GUEST_MODE;
@@ -267,6 +263,7 @@ void kvm_arch_vcpu_free(struct kvm_vcpu
 	kvm_timer_vcpu_terminate(vcpu);
 	kvm_vgic_vcpu_destroy(vcpu);
 	kvm_pmu_vcpu_destroy(vcpu);
+	kvm_vcpu_uninit(vcpu);
 	kmem_cache_free(kvm_vcpu_cache, vcpu);
 }
 
@@ -448,7 +445,7 @@ static void update_vttbr(struct kvm *kvm
 	kvm_next_vmid &= (1 << kvm_vmid_bits) - 1;
 
 	/* update vttbr to be used with the new vmid */
-	pgd_phys = virt_to_phys(kvm_get_hwpgd(kvm));
+	pgd_phys = virt_to_phys(kvm->arch.pgd);
 	BUG_ON(pgd_phys & ~VTTBR_BADDR_MASK);
 	vmid = ((u64)(kvm->arch.vmid) << VTTBR_VMID_SHIFT) & VTTBR_VMID_MASK(kvm_vmid_bits);
 	kvm->arch.vttbr = pgd_phys | vmid;
@@ -459,7 +456,7 @@ static void update_vttbr(struct kvm *kvm
 static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu)
 {
 	struct kvm *kvm = vcpu->kvm;
-	int ret;
+	int ret = 0;
 
 	if (likely(vcpu->arch.has_run_once))
 		return 0;
@@ -482,9 +479,9 @@ static int kvm_vcpu_first_run_init(struc
 	 * interrupts from the virtual timer with a userspace gic.
 	 */
 	if (irqchip_in_kernel(kvm) && vgic_initialized(kvm))
-		kvm_timer_enable(kvm);
+		ret = kvm_timer_enable(vcpu);
 
-	return 0;
+	return ret;
 }
 
 bool kvm_arch_intc_initialized(struct kvm *kvm)
@@ -492,30 +489,37 @@ bool kvm_arch_intc_initialized(struct kv
 	return vgic_initialized(kvm);
 }
 
-static void kvm_arm_halt_guest(struct kvm *kvm) __maybe_unused;
-static void kvm_arm_resume_guest(struct kvm *kvm) __maybe_unused;
-
-static void kvm_arm_halt_guest(struct kvm *kvm)
+void kvm_arm_halt_guest(struct kvm *kvm)
 {
 	int i;
 	struct kvm_vcpu *vcpu;
 
 	kvm_for_each_vcpu(i, vcpu, kvm)
 		vcpu->arch.pause = true;
-	force_vm_exit(cpu_all_mask);
+	kvm_make_all_cpus_request(kvm, KVM_REQ_VCPU_EXIT);
 }
 
-static void kvm_arm_resume_guest(struct kvm *kvm)
+void kvm_arm_halt_vcpu(struct kvm_vcpu *vcpu)
+{
+	vcpu->arch.pause = true;
+	kvm_vcpu_kick(vcpu);
+}
+
+void kvm_arm_resume_vcpu(struct kvm_vcpu *vcpu)
+{
+	struct swait_queue_head *wq = kvm_arch_vcpu_wq(vcpu);
+
+	vcpu->arch.pause = false;
+	swake_up(wq);
+}
+
+void kvm_arm_resume_guest(struct kvm *kvm)
 {
 	int i;
 	struct kvm_vcpu *vcpu;
 
-	kvm_for_each_vcpu(i, vcpu, kvm) {
-		struct swait_queue_head *wq = kvm_arch_vcpu_wq(vcpu);
-
-		vcpu->arch.pause = false;
-		swake_up(wq);
-	}
+	kvm_for_each_vcpu(i, vcpu, kvm)
+		kvm_arm_resume_vcpu(vcpu);
 }
 
 static void vcpu_sleep(struct kvm_vcpu *vcpu)
@@ -1033,11 +1037,6 @@ long kvm_arch_vm_ioctl(struct file *filp
 	}
 }
 
-static void cpu_init_stage2(void *dummy)
-{
-	__cpu_init_stage2();
-}
-
 static void cpu_init_hyp_mode(void *dummy)
 {
 	phys_addr_t boot_pgd_ptr;
@@ -1065,43 +1064,87 @@ static void cpu_hyp_reinit(void)
 {
 	if (is_kernel_in_hyp_mode()) {
 		/*
-		 * cpu_init_stage2() is safe to call even if the PM
+		 * __cpu_init_stage2() is safe to call even if the PM
 		 * event was cancelled before the CPU was reset.
 		 */
-		cpu_init_stage2(NULL);
+		__cpu_init_stage2();
 	} else {
 		if (__hyp_get_vectors() == hyp_default_vectors)
 			cpu_init_hyp_mode(NULL);
 	}
 }
 
-static int hyp_init_cpu_notify(struct notifier_block *self,
-			       unsigned long action, void *cpu)
+static void cpu_hyp_reset(void)
 {
-	switch (action) {
-	case CPU_STARTING:
-	case CPU_STARTING_FROZEN:
+	phys_addr_t boot_pgd_ptr;
+	phys_addr_t phys_idmap_start;
+
+	if (!is_kernel_in_hyp_mode()) {
+		boot_pgd_ptr = kvm_mmu_get_boot_httbr();
+		phys_idmap_start = kvm_get_idmap_start();
+
+		__cpu_reset_hyp_mode(boot_pgd_ptr, phys_idmap_start);
+	}
+}
+
+static void _kvm_arch_hardware_enable(void *discard)
+{
+	if (!__this_cpu_read(kvm_arm_hardware_enabled)) {
 		cpu_hyp_reinit();
+		__this_cpu_write(kvm_arm_hardware_enabled, 1);
 	}
+}
 
-	return NOTIFY_OK;
+int kvm_arch_hardware_enable(void)
+{
+	_kvm_arch_hardware_enable(NULL);
+	return 0;
 }
 
-static struct notifier_block hyp_init_cpu_nb = {
-	.notifier_call = hyp_init_cpu_notify,
-};
+static void _kvm_arch_hardware_disable(void *discard)
+{
+	if (__this_cpu_read(kvm_arm_hardware_enabled)) {
+		cpu_hyp_reset();
+		__this_cpu_write(kvm_arm_hardware_enabled, 0);
+	}
+}
+
+void kvm_arch_hardware_disable(void)
+{
+	_kvm_arch_hardware_disable(NULL);
+}
 
 #ifdef CONFIG_CPU_PM
 static int hyp_init_cpu_pm_notifier(struct notifier_block *self,
 				    unsigned long cmd,
 				    void *v)
 {
-	if (cmd == CPU_PM_EXIT) {
-		cpu_hyp_reinit();
+	/*
+	 * kvm_arm_hardware_enabled is left with its old value over
+	 * PM_ENTER->PM_EXIT. It is used to indicate PM_EXIT should
+	 * re-enable hyp.
+	 */
+	switch (cmd) {
+	case CPU_PM_ENTER:
+		if (__this_cpu_read(kvm_arm_hardware_enabled))
+			/*
+			 * don't update kvm_arm_hardware_enabled here
+			 * so that the hardware will be re-enabled
+			 * when we resume. See below.
+			 */
+			cpu_hyp_reset();
+
 		return NOTIFY_OK;
-	}
+	case CPU_PM_EXIT:
+		if (__this_cpu_read(kvm_arm_hardware_enabled))
+			/* The hardware was enabled before suspend. */
+			cpu_hyp_reinit();
 
-	return NOTIFY_DONE;
+		return NOTIFY_OK;
+
+	default:
+		return NOTIFY_DONE;
+	}
 }
 
 static struct notifier_block hyp_init_cpu_pm_nb = {
@@ -1143,16 +1186,12 @@ static int init_common_resources(void)
 
 static int init_subsystems(void)
 {
-	int err;
+	int err = 0;
 
 	/*
-	 * Register CPU Hotplug notifier
+	 * Enable hardware so that subsystem initialisation can access EL2.
 	 */
-	err = register_cpu_notifier(&hyp_init_cpu_nb);
-	if (err) {
-		kvm_err("Cannot register KVM init CPU notifier (%d)\n", err);
-		return err;
-	}
+	on_each_cpu(_kvm_arch_hardware_enable, NULL, 1);
 
 	/*
 	 * Register CPU lower-power notifier
@@ -1170,9 +1209,10 @@ static int init_subsystems(void)
 	case -ENODEV:
 	case -ENXIO:
 		vgic_present = false;
+		err = 0;
 		break;
 	default:
-		return err;
+		goto out;
 	}
 
 	/*
@@ -1180,12 +1220,15 @@ static int init_subsystems(void)
 	 */
 	err = kvm_timer_hyp_init();
 	if (err)
-		return err;
+		goto out;
 
 	kvm_perf_init();
 	kvm_coproc_table_init();
 
-	return 0;
+out:
+	on_each_cpu(_kvm_arch_hardware_disable, NULL, 1);
+
+	return err;
 }
 
 static void teardown_hyp_mode(void)
@@ -1198,17 +1241,11 @@ static void teardown_hyp_mode(void)
 	free_hyp_pgds();
 	for_each_possible_cpu(cpu)
 		free_page(per_cpu(kvm_arm_hyp_stack_page, cpu));
-	unregister_cpu_notifier(&hyp_init_cpu_nb);
 	hyp_cpu_pm_exit();
 }
 
 static int init_vhe_mode(void)
 {
-	/*
-	 * Execute the init code on each CPU.
-	 */
-	on_each_cpu(cpu_init_stage2, NULL, 1);
-
 	/* set size of VMID supported by CPU */
 	kvm_vmid_bits = kvm_get_vmid_bits();
 	kvm_info("%d-bit VMID\n", kvm_vmid_bits);
@@ -1295,11 +1332,6 @@ static int init_hyp_mode(void)
 		}
 	}
 
-	/*
-	 * Execute the init code on each CPU.
-	 */
-	on_each_cpu(cpu_init_hyp_mode, NULL, 1);
-
 #ifndef CONFIG_HOTPLUG_CPU
 	free_boot_hyp_pgd();
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/kvm/Kconfig linux-libre-4.7-gnu/arch/arm/kvm/Kconfig
--- linux-libre-4.6-gnu/arch/arm/kvm/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/kvm/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -46,6 +46,13 @@ config KVM_ARM_HOST
 	---help---
 	  Provides host support for ARM processors.
 
+config KVM_NEW_VGIC
+	bool "New VGIC implementation"
+	depends on KVM
+	default y
+	---help---
+	  uses the new VGIC implementation
+
 source drivers/vhost/Kconfig
 
 endif # VIRTUALIZATION
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/kvm/Makefile linux-libre-4.7-gnu/arch/arm/kvm/Makefile
--- linux-libre-4.6-gnu/arch/arm/kvm/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/kvm/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -21,7 +21,18 @@ obj-$(CONFIG_KVM_ARM_HOST) += hyp/
 obj-y += kvm-arm.o init.o interrupts.o
 obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o
 obj-y += coproc.o coproc_a15.o coproc_a7.o mmio.o psci.o perf.o
+
+ifeq ($(CONFIG_KVM_NEW_VGIC),y)
+obj-y += $(KVM)/arm/vgic/vgic.o
+obj-y += $(KVM)/arm/vgic/vgic-init.o
+obj-y += $(KVM)/arm/vgic/vgic-irqfd.o
+obj-y += $(KVM)/arm/vgic/vgic-v2.o
+obj-y += $(KVM)/arm/vgic/vgic-mmio.o
+obj-y += $(KVM)/arm/vgic/vgic-mmio-v2.o
+obj-y += $(KVM)/arm/vgic/vgic-kvm-device.o
+else
 obj-y += $(KVM)/arm/vgic.o
 obj-y += $(KVM)/arm/vgic-v2.o
 obj-y += $(KVM)/arm/vgic-v2-emul.o
+endif
 obj-y += $(KVM)/arm/arch_timer.o
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/kvm/mmio.c linux-libre-4.7-gnu/arch/arm/kvm/mmio.c
--- linux-libre-4.6-gnu/arch/arm/kvm/mmio.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/kvm/mmio.c	2016-07-24 15:23:50.000000000 -0400
@@ -23,7 +23,7 @@
 
 #include "trace.h"
 
-static void mmio_write_buf(char *buf, unsigned int len, unsigned long data)
+void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data)
 {
 	void *datap = NULL;
 	union {
@@ -55,7 +55,7 @@ static void mmio_write_buf(char *buf, un
 	memcpy(buf, datap, len);
 }
 
-static unsigned long mmio_read_buf(char *buf, unsigned int len)
+unsigned long kvm_mmio_read_buf(const void *buf, unsigned int len)
 {
 	unsigned long data = 0;
 	union {
@@ -66,7 +66,7 @@ static unsigned long mmio_read_buf(char
 
 	switch (len) {
 	case 1:
-		data = buf[0];
+		data = *(u8 *)buf;
 		break;
 	case 2:
 		memcpy(&tmp.hword, buf, len);
@@ -87,11 +87,10 @@ static unsigned long mmio_read_buf(char
 
 /**
  * kvm_handle_mmio_return -- Handle MMIO loads after user space emulation
+ *			     or in-kernel IO emulation
+ *
  * @vcpu: The VCPU pointer
  * @run:  The VCPU run struct containing the mmio data
- *
- * This should only be called after returning from userspace for MMIO load
- * emulation.
  */
 int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run)
 {
@@ -104,7 +103,7 @@ int kvm_handle_mmio_return(struct kvm_vc
 		if (len > sizeof(unsigned long))
 			return -EINVAL;
 
-		data = mmio_read_buf(run->mmio.data, len);
+		data = kvm_mmio_read_buf(run->mmio.data, len);
 
 		if (vcpu->arch.mmio_decode.sign_extend &&
 		    len < sizeof(unsigned long)) {
@@ -190,7 +189,7 @@ int io_mem_abort(struct kvm_vcpu *vcpu,
 					       len);
 
 		trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, len, fault_ipa, data);
-		mmio_write_buf(data_buf, len, data);
+		kvm_mmio_write_buf(data_buf, len, data);
 
 		ret = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, fault_ipa, len,
 				       data_buf);
@@ -206,18 +205,19 @@ int io_mem_abort(struct kvm_vcpu *vcpu,
 	run->mmio.is_write	= is_write;
 	run->mmio.phys_addr	= fault_ipa;
 	run->mmio.len		= len;
-	if (is_write)
-		memcpy(run->mmio.data, data_buf, len);
 
 	if (!ret) {
 		/* We handled the access successfully in the kernel. */
+		if (!is_write)
+			memcpy(run->mmio.data, data_buf, len);
 		vcpu->stat.mmio_exit_kernel++;
 		kvm_handle_mmio_return(vcpu, run);
 		return 1;
-	} else {
-		vcpu->stat.mmio_exit_user++;
 	}
 
+	if (is_write)
+		memcpy(run->mmio.data, data_buf, len);
+	vcpu->stat.mmio_exit_user++;
 	run->exit_reason	= KVM_EXIT_MMIO;
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/kvm/mmu.c linux-libre-4.7-gnu/arch/arm/kvm/mmu.c
--- linux-libre-4.6-gnu/arch/arm/kvm/mmu.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/kvm/mmu.c	2016-07-24 15:23:50.000000000 -0400
@@ -43,11 +43,9 @@ static unsigned long hyp_idmap_start;
 static unsigned long hyp_idmap_end;
 static phys_addr_t hyp_idmap_vector;
 
+#define S2_PGD_SIZE	(PTRS_PER_S2_PGD * sizeof(pgd_t))
 #define hyp_pgd_order get_order(PTRS_PER_PGD * sizeof(pgd_t))
 
-#define kvm_pmd_huge(_x)	(pmd_huge(_x) || pmd_trans_huge(_x))
-#define kvm_pud_huge(_x)	pud_huge(_x)
-
 #define KVM_S2PTE_FLAG_IS_IOMAP		(1UL << 0)
 #define KVM_S2_FLAG_LOGGING_ACTIVE	(1UL << 1)
 
@@ -69,14 +67,7 @@ void kvm_flush_remote_tlbs(struct kvm *k
 
 static void kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa)
 {
-	/*
-	 * This function also gets called when dealing with HYP page
-	 * tables. As HYP doesn't have an associated struct kvm (and
-	 * the HYP page tables are fairly static), we don't do
-	 * anything there.
-	 */
-	if (kvm)
-		kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, kvm, ipa);
+	kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, kvm, ipa);
 }
 
 /*
@@ -115,7 +106,7 @@ static bool kvm_is_device_pfn(unsigned l
  */
 static void stage2_dissolve_pmd(struct kvm *kvm, phys_addr_t addr, pmd_t *pmd)
 {
-	if (!kvm_pmd_huge(*pmd))
+	if (!pmd_thp_or_huge(*pmd))
 		return;
 
 	pmd_clear(pmd);
@@ -155,29 +146,29 @@ static void *mmu_memory_cache_alloc(stru
 	return p;
 }
 
-static void clear_pgd_entry(struct kvm *kvm, pgd_t *pgd, phys_addr_t addr)
+static void clear_stage2_pgd_entry(struct kvm *kvm, pgd_t *pgd, phys_addr_t addr)
 {
-	pud_t *pud_table __maybe_unused = pud_offset(pgd, 0);
-	pgd_clear(pgd);
+	pud_t *pud_table __maybe_unused = stage2_pud_offset(pgd, 0UL);
+	stage2_pgd_clear(pgd);
 	kvm_tlb_flush_vmid_ipa(kvm, addr);
-	pud_free(NULL, pud_table);
+	stage2_pud_free(pud_table);
 	put_page(virt_to_page(pgd));
 }
 
-static void clear_pud_entry(struct kvm *kvm, pud_t *pud, phys_addr_t addr)
+static void clear_stage2_pud_entry(struct kvm *kvm, pud_t *pud, phys_addr_t addr)
 {
-	pmd_t *pmd_table = pmd_offset(pud, 0);
-	VM_BUG_ON(pud_huge(*pud));
-	pud_clear(pud);
+	pmd_t *pmd_table __maybe_unused = stage2_pmd_offset(pud, 0);
+	VM_BUG_ON(stage2_pud_huge(*pud));
+	stage2_pud_clear(pud);
 	kvm_tlb_flush_vmid_ipa(kvm, addr);
-	pmd_free(NULL, pmd_table);
+	stage2_pmd_free(pmd_table);
 	put_page(virt_to_page(pud));
 }
 
-static void clear_pmd_entry(struct kvm *kvm, pmd_t *pmd, phys_addr_t addr)
+static void clear_stage2_pmd_entry(struct kvm *kvm, pmd_t *pmd, phys_addr_t addr)
 {
 	pte_t *pte_table = pte_offset_kernel(pmd, 0);
-	VM_BUG_ON(kvm_pmd_huge(*pmd));
+	VM_BUG_ON(pmd_thp_or_huge(*pmd));
 	pmd_clear(pmd);
 	kvm_tlb_flush_vmid_ipa(kvm, addr);
 	pte_free_kernel(NULL, pte_table);
@@ -204,7 +195,7 @@ static void clear_pmd_entry(struct kvm *
  * the corresponding TLBs, we call kvm_flush_dcache_p*() to make sure
  * the IO subsystem will never hit in the cache.
  */
-static void unmap_ptes(struct kvm *kvm, pmd_t *pmd,
+static void unmap_stage2_ptes(struct kvm *kvm, pmd_t *pmd,
 		       phys_addr_t addr, phys_addr_t end)
 {
 	phys_addr_t start_addr = addr;
@@ -226,21 +217,21 @@ static void unmap_ptes(struct kvm *kvm,
 		}
 	} while (pte++, addr += PAGE_SIZE, addr != end);
 
-	if (kvm_pte_table_empty(kvm, start_pte))
-		clear_pmd_entry(kvm, pmd, start_addr);
+	if (stage2_pte_table_empty(start_pte))
+		clear_stage2_pmd_entry(kvm, pmd, start_addr);
 }
 
-static void unmap_pmds(struct kvm *kvm, pud_t *pud,
+static void unmap_stage2_pmds(struct kvm *kvm, pud_t *pud,
 		       phys_addr_t addr, phys_addr_t end)
 {
 	phys_addr_t next, start_addr = addr;
 	pmd_t *pmd, *start_pmd;
 
-	start_pmd = pmd = pmd_offset(pud, addr);
+	start_pmd = pmd = stage2_pmd_offset(pud, addr);
 	do {
-		next = kvm_pmd_addr_end(addr, end);
+		next = stage2_pmd_addr_end(addr, end);
 		if (!pmd_none(*pmd)) {
-			if (kvm_pmd_huge(*pmd)) {
+			if (pmd_thp_or_huge(*pmd)) {
 				pmd_t old_pmd = *pmd;
 
 				pmd_clear(pmd);
@@ -250,57 +241,64 @@ static void unmap_pmds(struct kvm *kvm,
 
 				put_page(virt_to_page(pmd));
 			} else {
-				unmap_ptes(kvm, pmd, addr, next);
+				unmap_stage2_ptes(kvm, pmd, addr, next);
 			}
 		}
 	} while (pmd++, addr = next, addr != end);
 
-	if (kvm_pmd_table_empty(kvm, start_pmd))
-		clear_pud_entry(kvm, pud, start_addr);
+	if (stage2_pmd_table_empty(start_pmd))
+		clear_stage2_pud_entry(kvm, pud, start_addr);
 }
 
-static void unmap_puds(struct kvm *kvm, pgd_t *pgd,
+static void unmap_stage2_puds(struct kvm *kvm, pgd_t *pgd,
 		       phys_addr_t addr, phys_addr_t end)
 {
 	phys_addr_t next, start_addr = addr;
 	pud_t *pud, *start_pud;
 
-	start_pud = pud = pud_offset(pgd, addr);
+	start_pud = pud = stage2_pud_offset(pgd, addr);
 	do {
-		next = kvm_pud_addr_end(addr, end);
-		if (!pud_none(*pud)) {
-			if (pud_huge(*pud)) {
+		next = stage2_pud_addr_end(addr, end);
+		if (!stage2_pud_none(*pud)) {
+			if (stage2_pud_huge(*pud)) {
 				pud_t old_pud = *pud;
 
-				pud_clear(pud);
+				stage2_pud_clear(pud);
 				kvm_tlb_flush_vmid_ipa(kvm, addr);
-
 				kvm_flush_dcache_pud(old_pud);
-
 				put_page(virt_to_page(pud));
 			} else {
-				unmap_pmds(kvm, pud, addr, next);
+				unmap_stage2_pmds(kvm, pud, addr, next);
 			}
 		}
 	} while (pud++, addr = next, addr != end);
 
-	if (kvm_pud_table_empty(kvm, start_pud))
-		clear_pgd_entry(kvm, pgd, start_addr);
+	if (stage2_pud_table_empty(start_pud))
+		clear_stage2_pgd_entry(kvm, pgd, start_addr);
 }
 
-
-static void unmap_range(struct kvm *kvm, pgd_t *pgdp,
-			phys_addr_t start, u64 size)
+/**
+ * unmap_stage2_range -- Clear stage2 page table entries to unmap a range
+ * @kvm:   The VM pointer
+ * @start: The intermediate physical base address of the range to unmap
+ * @size:  The size of the area to unmap
+ *
+ * Clear a range of stage-2 mappings, lowering the various ref-counts.  Must
+ * be called while holding mmu_lock (unless for freeing the stage2 pgd before
+ * destroying the VM), otherwise another faulting VCPU may come in and mess
+ * with things behind our backs.
+ */
+static void unmap_stage2_range(struct kvm *kvm, phys_addr_t start, u64 size)
 {
 	pgd_t *pgd;
 	phys_addr_t addr = start, end = start + size;
 	phys_addr_t next;
 
-	pgd = pgdp + kvm_pgd_index(addr);
+	pgd = kvm->arch.pgd + stage2_pgd_index(addr);
 	do {
-		next = kvm_pgd_addr_end(addr, end);
-		if (!pgd_none(*pgd))
-			unmap_puds(kvm, pgd, addr, next);
+		next = stage2_pgd_addr_end(addr, end);
+		if (!stage2_pgd_none(*pgd))
+			unmap_stage2_puds(kvm, pgd, addr, next);
 	} while (pgd++, addr = next, addr != end);
 }
 
@@ -322,11 +320,11 @@ static void stage2_flush_pmds(struct kvm
 	pmd_t *pmd;
 	phys_addr_t next;
 
-	pmd = pmd_offset(pud, addr);
+	pmd = stage2_pmd_offset(pud, addr);
 	do {
-		next = kvm_pmd_addr_end(addr, end);
+		next = stage2_pmd_addr_end(addr, end);
 		if (!pmd_none(*pmd)) {
-			if (kvm_pmd_huge(*pmd))
+			if (pmd_thp_or_huge(*pmd))
 				kvm_flush_dcache_pmd(*pmd);
 			else
 				stage2_flush_ptes(kvm, pmd, addr, next);
@@ -340,11 +338,11 @@ static void stage2_flush_puds(struct kvm
 	pud_t *pud;
 	phys_addr_t next;
 
-	pud = pud_offset(pgd, addr);
+	pud = stage2_pud_offset(pgd, addr);
 	do {
-		next = kvm_pud_addr_end(addr, end);
-		if (!pud_none(*pud)) {
-			if (pud_huge(*pud))
+		next = stage2_pud_addr_end(addr, end);
+		if (!stage2_pud_none(*pud)) {
+			if (stage2_pud_huge(*pud))
 				kvm_flush_dcache_pud(*pud);
 			else
 				stage2_flush_pmds(kvm, pud, addr, next);
@@ -360,9 +358,9 @@ static void stage2_flush_memslot(struct
 	phys_addr_t next;
 	pgd_t *pgd;
 
-	pgd = kvm->arch.pgd + kvm_pgd_index(addr);
+	pgd = kvm->arch.pgd + stage2_pgd_index(addr);
 	do {
-		next = kvm_pgd_addr_end(addr, end);
+		next = stage2_pgd_addr_end(addr, end);
 		stage2_flush_puds(kvm, pgd, addr, next);
 	} while (pgd++, addr = next, addr != end);
 }
@@ -391,6 +389,100 @@ static void stage2_flush_vm(struct kvm *
 	srcu_read_unlock(&kvm->srcu, idx);
 }
 
+static void clear_hyp_pgd_entry(pgd_t *pgd)
+{
+	pud_t *pud_table __maybe_unused = pud_offset(pgd, 0UL);
+	pgd_clear(pgd);
+	pud_free(NULL, pud_table);
+	put_page(virt_to_page(pgd));
+}
+
+static void clear_hyp_pud_entry(pud_t *pud)
+{
+	pmd_t *pmd_table __maybe_unused = pmd_offset(pud, 0);
+	VM_BUG_ON(pud_huge(*pud));
+	pud_clear(pud);
+	pmd_free(NULL, pmd_table);
+	put_page(virt_to_page(pud));
+}
+
+static void clear_hyp_pmd_entry(pmd_t *pmd)
+{
+	pte_t *pte_table = pte_offset_kernel(pmd, 0);
+	VM_BUG_ON(pmd_thp_or_huge(*pmd));
+	pmd_clear(pmd);
+	pte_free_kernel(NULL, pte_table);
+	put_page(virt_to_page(pmd));
+}
+
+static void unmap_hyp_ptes(pmd_t *pmd, phys_addr_t addr, phys_addr_t end)
+{
+	pte_t *pte, *start_pte;
+
+	start_pte = pte = pte_offset_kernel(pmd, addr);
+	do {
+		if (!pte_none(*pte)) {
+			kvm_set_pte(pte, __pte(0));
+			put_page(virt_to_page(pte));
+		}
+	} while (pte++, addr += PAGE_SIZE, addr != end);
+
+	if (hyp_pte_table_empty(start_pte))
+		clear_hyp_pmd_entry(pmd);
+}
+
+static void unmap_hyp_pmds(pud_t *pud, phys_addr_t addr, phys_addr_t end)
+{
+	phys_addr_t next;
+	pmd_t *pmd, *start_pmd;
+
+	start_pmd = pmd = pmd_offset(pud, addr);
+	do {
+		next = pmd_addr_end(addr, end);
+		/* Hyp doesn't use huge pmds */
+		if (!pmd_none(*pmd))
+			unmap_hyp_ptes(pmd, addr, next);
+	} while (pmd++, addr = next, addr != end);
+
+	if (hyp_pmd_table_empty(start_pmd))
+		clear_hyp_pud_entry(pud);
+}
+
+static void unmap_hyp_puds(pgd_t *pgd, phys_addr_t addr, phys_addr_t end)
+{
+	phys_addr_t next;
+	pud_t *pud, *start_pud;
+
+	start_pud = pud = pud_offset(pgd, addr);
+	do {
+		next = pud_addr_end(addr, end);
+		/* Hyp doesn't use huge puds */
+		if (!pud_none(*pud))
+			unmap_hyp_pmds(pud, addr, next);
+	} while (pud++, addr = next, addr != end);
+
+	if (hyp_pud_table_empty(start_pud))
+		clear_hyp_pgd_entry(pgd);
+}
+
+static void unmap_hyp_range(pgd_t *pgdp, phys_addr_t start, u64 size)
+{
+	pgd_t *pgd;
+	phys_addr_t addr = start, end = start + size;
+	phys_addr_t next;
+
+	/*
+	 * We don't unmap anything from HYP, except at the hyp tear down.
+	 * Hence, we don't have to invalidate the TLBs here.
+	 */
+	pgd = pgdp + pgd_index(addr);
+	do {
+		next = pgd_addr_end(addr, end);
+		if (!pgd_none(*pgd))
+			unmap_hyp_puds(pgd, addr, next);
+	} while (pgd++, addr = next, addr != end);
+}
+
 /**
  * free_boot_hyp_pgd - free HYP boot page tables
  *
@@ -401,14 +493,14 @@ void free_boot_hyp_pgd(void)
 	mutex_lock(&kvm_hyp_pgd_mutex);
 
 	if (boot_hyp_pgd) {
-		unmap_range(NULL, boot_hyp_pgd, hyp_idmap_start, PAGE_SIZE);
-		unmap_range(NULL, boot_hyp_pgd, TRAMPOLINE_VA, PAGE_SIZE);
+		unmap_hyp_range(boot_hyp_pgd, hyp_idmap_start, PAGE_SIZE);
+		unmap_hyp_range(boot_hyp_pgd, TRAMPOLINE_VA, PAGE_SIZE);
 		free_pages((unsigned long)boot_hyp_pgd, hyp_pgd_order);
 		boot_hyp_pgd = NULL;
 	}
 
 	if (hyp_pgd)
-		unmap_range(NULL, hyp_pgd, TRAMPOLINE_VA, PAGE_SIZE);
+		unmap_hyp_range(hyp_pgd, TRAMPOLINE_VA, PAGE_SIZE);
 
 	mutex_unlock(&kvm_hyp_pgd_mutex);
 }
@@ -433,9 +525,9 @@ void free_hyp_pgds(void)
 
 	if (hyp_pgd) {
 		for (addr = PAGE_OFFSET; virt_addr_valid(addr); addr += PGDIR_SIZE)
-			unmap_range(NULL, hyp_pgd, KERN_TO_HYP(addr), PGDIR_SIZE);
+			unmap_hyp_range(hyp_pgd, KERN_TO_HYP(addr), PGDIR_SIZE);
 		for (addr = VMALLOC_START; is_vmalloc_addr((void*)addr); addr += PGDIR_SIZE)
-			unmap_range(NULL, hyp_pgd, KERN_TO_HYP(addr), PGDIR_SIZE);
+			unmap_hyp_range(hyp_pgd, KERN_TO_HYP(addr), PGDIR_SIZE);
 
 		free_pages((unsigned long)hyp_pgd, hyp_pgd_order);
 		hyp_pgd = NULL;
@@ -645,20 +737,6 @@ int create_hyp_io_mappings(void *from, v
 				     __phys_to_pfn(phys_addr), PAGE_HYP_DEVICE);
 }
 
-/* Free the HW pgd, one page at a time */
-static void kvm_free_hwpgd(void *hwpgd)
-{
-	free_pages_exact(hwpgd, kvm_get_hwpgd_size());
-}
-
-/* Allocate the HW PGD, making sure that each page gets its own refcount */
-static void *kvm_alloc_hwpgd(void)
-{
-	unsigned int size = kvm_get_hwpgd_size();
-
-	return alloc_pages_exact(size, GFP_KERNEL | __GFP_ZERO);
-}
-
 /**
  * kvm_alloc_stage2_pgd - allocate level-1 table for stage-2 translation.
  * @kvm:	The KVM struct pointer for the VM.
@@ -673,81 +751,22 @@ static void *kvm_alloc_hwpgd(void)
 int kvm_alloc_stage2_pgd(struct kvm *kvm)
 {
 	pgd_t *pgd;
-	void *hwpgd;
 
 	if (kvm->arch.pgd != NULL) {
 		kvm_err("kvm_arch already initialized?\n");
 		return -EINVAL;
 	}
 
-	hwpgd = kvm_alloc_hwpgd();
-	if (!hwpgd)
+	/* Allocate the HW PGD, making sure that each page gets its own refcount */
+	pgd = alloc_pages_exact(S2_PGD_SIZE, GFP_KERNEL | __GFP_ZERO);
+	if (!pgd)
 		return -ENOMEM;
 
-	/* When the kernel uses more levels of page tables than the
-	 * guest, we allocate a fake PGD and pre-populate it to point
-	 * to the next-level page table, which will be the real
-	 * initial page table pointed to by the VTTBR.
-	 *
-	 * When KVM_PREALLOC_LEVEL==2, we allocate a single page for
-	 * the PMD and the kernel will use folded pud.
-	 * When KVM_PREALLOC_LEVEL==1, we allocate 2 consecutive PUD
-	 * pages.
-	 */
-	if (KVM_PREALLOC_LEVEL > 0) {
-		int i;
-
-		/*
-		 * Allocate fake pgd for the page table manipulation macros to
-		 * work.  This is not used by the hardware and we have no
-		 * alignment requirement for this allocation.
-		 */
-		pgd = kmalloc(PTRS_PER_S2_PGD * sizeof(pgd_t),
-				GFP_KERNEL | __GFP_ZERO);
-
-		if (!pgd) {
-			kvm_free_hwpgd(hwpgd);
-			return -ENOMEM;
-		}
-
-		/* Plug the HW PGD into the fake one. */
-		for (i = 0; i < PTRS_PER_S2_PGD; i++) {
-			if (KVM_PREALLOC_LEVEL == 1)
-				pgd_populate(NULL, pgd + i,
-					     (pud_t *)hwpgd + i * PTRS_PER_PUD);
-			else if (KVM_PREALLOC_LEVEL == 2)
-				pud_populate(NULL, pud_offset(pgd, 0) + i,
-					     (pmd_t *)hwpgd + i * PTRS_PER_PMD);
-		}
-	} else {
-		/*
-		 * Allocate actual first-level Stage-2 page table used by the
-		 * hardware for Stage-2 page table walks.
-		 */
-		pgd = (pgd_t *)hwpgd;
-	}
-
 	kvm_clean_pgd(pgd);
 	kvm->arch.pgd = pgd;
 	return 0;
 }
 
-/**
- * unmap_stage2_range -- Clear stage2 page table entries to unmap a range
- * @kvm:   The VM pointer
- * @start: The intermediate physical base address of the range to unmap
- * @size:  The size of the area to unmap
- *
- * Clear a range of stage-2 mappings, lowering the various ref-counts.  Must
- * be called while holding mmu_lock (unless for freeing the stage2 pgd before
- * destroying the VM), otherwise another faulting VCPU may come in and mess
- * with things behind our backs.
- */
-static void unmap_stage2_range(struct kvm *kvm, phys_addr_t start, u64 size)
-{
-	unmap_range(kvm, kvm->arch.pgd, start, size);
-}
-
 static void stage2_unmap_memslot(struct kvm *kvm,
 				 struct kvm_memory_slot *memslot)
 {
@@ -830,10 +849,8 @@ void kvm_free_stage2_pgd(struct kvm *kvm
 		return;
 
 	unmap_stage2_range(kvm, 0, KVM_PHYS_SIZE);
-	kvm_free_hwpgd(kvm_get_hwpgd(kvm));
-	if (KVM_PREALLOC_LEVEL > 0)
-		kfree(kvm->arch.pgd);
-
+	/* Free the HW pgd, one page at a time */
+	free_pages_exact(kvm->arch.pgd, S2_PGD_SIZE);
 	kvm->arch.pgd = NULL;
 }
 
@@ -843,16 +860,16 @@ static pud_t *stage2_get_pud(struct kvm
 	pgd_t *pgd;
 	pud_t *pud;
 
-	pgd = kvm->arch.pgd + kvm_pgd_index(addr);
-	if (WARN_ON(pgd_none(*pgd))) {
+	pgd = kvm->arch.pgd + stage2_pgd_index(addr);
+	if (WARN_ON(stage2_pgd_none(*pgd))) {
 		if (!cache)
 			return NULL;
 		pud = mmu_memory_cache_alloc(cache);
-		pgd_populate(NULL, pgd, pud);
+		stage2_pgd_populate(pgd, pud);
 		get_page(virt_to_page(pgd));
 	}
 
-	return pud_offset(pgd, addr);
+	return stage2_pud_offset(pgd, addr);
 }
 
 static pmd_t *stage2_get_pmd(struct kvm *kvm, struct kvm_mmu_memory_cache *cache,
@@ -862,15 +879,15 @@ static pmd_t *stage2_get_pmd(struct kvm
 	pmd_t *pmd;
 
 	pud = stage2_get_pud(kvm, cache, addr);
-	if (pud_none(*pud)) {
+	if (stage2_pud_none(*pud)) {
 		if (!cache)
 			return NULL;
 		pmd = mmu_memory_cache_alloc(cache);
-		pud_populate(NULL, pud, pmd);
+		stage2_pud_populate(pud, pmd);
 		get_page(virt_to_page(pud));
 	}
 
-	return pmd_offset(pud, addr);
+	return stage2_pmd_offset(pud, addr);
 }
 
 static int stage2_set_pmd_huge(struct kvm *kvm, struct kvm_mmu_memory_cache
@@ -893,11 +910,14 @@ static int stage2_set_pmd_huge(struct kv
 	VM_BUG_ON(pmd_present(*pmd) && pmd_pfn(*pmd) != pmd_pfn(*new_pmd));
 
 	old_pmd = *pmd;
-	kvm_set_pmd(pmd, *new_pmd);
-	if (pmd_present(old_pmd))
+	if (pmd_present(old_pmd)) {
+		pmd_clear(pmd);
 		kvm_tlb_flush_vmid_ipa(kvm, addr);
-	else
+	} else {
 		get_page(virt_to_page(pmd));
+	}
+
+	kvm_set_pmd(pmd, *new_pmd);
 	return 0;
 }
 
@@ -946,15 +966,38 @@ static int stage2_set_pte(struct kvm *kv
 
 	/* Create 2nd stage page table mapping - Level 3 */
 	old_pte = *pte;
-	kvm_set_pte(pte, *new_pte);
-	if (pte_present(old_pte))
+	if (pte_present(old_pte)) {
+		kvm_set_pte(pte, __pte(0));
 		kvm_tlb_flush_vmid_ipa(kvm, addr);
-	else
+	} else {
 		get_page(virt_to_page(pte));
+	}
 
+	kvm_set_pte(pte, *new_pte);
 	return 0;
 }
 
+#ifndef __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
+static int stage2_ptep_test_and_clear_young(pte_t *pte)
+{
+	if (pte_young(*pte)) {
+		*pte = pte_mkold(*pte);
+		return 1;
+	}
+	return 0;
+}
+#else
+static int stage2_ptep_test_and_clear_young(pte_t *pte)
+{
+	return __ptep_test_and_clear_young(pte);
+}
+#endif
+
+static int stage2_pmdp_test_and_clear_young(pmd_t *pmd)
+{
+	return stage2_ptep_test_and_clear_young((pte_t *)pmd);
+}
+
 /**
  * kvm_phys_addr_ioremap - map a device range to guest IPA
  *
@@ -978,7 +1021,7 @@ int kvm_phys_addr_ioremap(struct kvm *kv
 		pte_t pte = pfn_pte(pfn, PAGE_S2_DEVICE);
 
 		if (writable)
-			kvm_set_s2pte_writable(&pte);
+			pte = kvm_s2pte_mkwrite(pte);
 
 		ret = mmu_topup_memory_cache(&cache, KVM_MMU_CACHE_MIN_PAGES,
 						KVM_NR_MEM_OBJS);
@@ -1078,12 +1121,12 @@ static void stage2_wp_pmds(pud_t *pud, p
 	pmd_t *pmd;
 	phys_addr_t next;
 
-	pmd = pmd_offset(pud, addr);
+	pmd = stage2_pmd_offset(pud, addr);
 
 	do {
-		next = kvm_pmd_addr_end(addr, end);
+		next = stage2_pmd_addr_end(addr, end);
 		if (!pmd_none(*pmd)) {
-			if (kvm_pmd_huge(*pmd)) {
+			if (pmd_thp_or_huge(*pmd)) {
 				if (!kvm_s2pmd_readonly(pmd))
 					kvm_set_s2pmd_readonly(pmd);
 			} else {
@@ -1106,12 +1149,12 @@ static void  stage2_wp_puds(pgd_t *pgd,
 	pud_t *pud;
 	phys_addr_t next;
 
-	pud = pud_offset(pgd, addr);
+	pud = stage2_pud_offset(pgd, addr);
 	do {
-		next = kvm_pud_addr_end(addr, end);
-		if (!pud_none(*pud)) {
+		next = stage2_pud_addr_end(addr, end);
+		if (!stage2_pud_none(*pud)) {
 			/* TODO:PUD not supported, revisit later if supported */
-			BUG_ON(kvm_pud_huge(*pud));
+			BUG_ON(stage2_pud_huge(*pud));
 			stage2_wp_pmds(pud, addr, next);
 		}
 	} while (pud++, addr = next, addr != end);
@@ -1128,7 +1171,7 @@ static void stage2_wp_range(struct kvm *
 	pgd_t *pgd;
 	phys_addr_t next;
 
-	pgd = kvm->arch.pgd + kvm_pgd_index(addr);
+	pgd = kvm->arch.pgd + stage2_pgd_index(addr);
 	do {
 		/*
 		 * Release kvm_mmu_lock periodically if the memory region is
@@ -1140,8 +1183,8 @@ static void stage2_wp_range(struct kvm *
 		if (need_resched() || spin_needbreak(&kvm->mmu_lock))
 			cond_resched_lock(&kvm->mmu_lock);
 
-		next = kvm_pgd_addr_end(addr, end);
-		if (pgd_present(*pgd))
+		next = stage2_pgd_addr_end(addr, end);
+		if (stage2_pgd_present(*pgd))
 			stage2_wp_puds(pgd, addr, next);
 	} while (pgd++, addr = next, addr != end);
 }
@@ -1320,7 +1363,7 @@ static int user_mem_abort(struct kvm_vcp
 		pmd_t new_pmd = pfn_pmd(pfn, mem_type);
 		new_pmd = pmd_mkhuge(new_pmd);
 		if (writable) {
-			kvm_set_s2pmd_writable(&new_pmd);
+			new_pmd = kvm_s2pmd_mkwrite(new_pmd);
 			kvm_set_pfn_dirty(pfn);
 		}
 		coherent_cache_guest_page(vcpu, pfn, PMD_SIZE, fault_ipa_uncached);
@@ -1329,7 +1372,7 @@ static int user_mem_abort(struct kvm_vcp
 		pte_t new_pte = pfn_pte(pfn, mem_type);
 
 		if (writable) {
-			kvm_set_s2pte_writable(&new_pte);
+			new_pte = kvm_s2pte_mkwrite(new_pte);
 			kvm_set_pfn_dirty(pfn);
 			mark_page_dirty(kvm, gfn);
 		}
@@ -1348,6 +1391,8 @@ out_unlock:
  * Resolve the access fault by making the page young again.
  * Note that because the faulting entry is guaranteed not to be
  * cached in the TLB, we don't need to invalidate anything.
+ * Only the HW Access Flag updates are supported for Stage 2 (no DBM),
+ * so there is no need for atomic (pte|pmd)_mkyoung operations.
  */
 static void handle_access_fault(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa)
 {
@@ -1364,7 +1409,7 @@ static void handle_access_fault(struct k
 	if (!pmd || pmd_none(*pmd))	/* Nothing there */
 		goto out;
 
-	if (kvm_pmd_huge(*pmd)) {	/* THP, HugeTLB */
+	if (pmd_thp_or_huge(*pmd)) {	/* THP, HugeTLB */
 		*pmd = pmd_mkyoung(*pmd);
 		pfn = pmd_pfn(*pmd);
 		pfn_valid = true;
@@ -1588,25 +1633,14 @@ static int kvm_age_hva_handler(struct kv
 	if (!pmd || pmd_none(*pmd))	/* Nothing there */
 		return 0;
 
-	if (kvm_pmd_huge(*pmd)) {	/* THP, HugeTLB */
-		if (pmd_young(*pmd)) {
-			*pmd = pmd_mkold(*pmd);
-			return 1;
-		}
-
-		return 0;
-	}
+	if (pmd_thp_or_huge(*pmd))	/* THP, HugeTLB */
+		return stage2_pmdp_test_and_clear_young(pmd);
 
 	pte = pte_offset_kernel(pmd, gpa);
 	if (pte_none(*pte))
 		return 0;
 
-	if (pte_young(*pte)) {
-		*pte = pte_mkold(*pte);	/* Just a page... */
-		return 1;
-	}
-
-	return 0;
+	return stage2_ptep_test_and_clear_young(pte);
 }
 
 static int kvm_test_age_hva_handler(struct kvm *kvm, gpa_t gpa, void *data)
@@ -1618,7 +1652,7 @@ static int kvm_test_age_hva_handler(stru
 	if (!pmd || pmd_none(*pmd))	/* Nothing there */
 		return 0;
 
-	if (kvm_pmd_huge(*pmd))		/* THP, HugeTLB */
+	if (pmd_thp_or_huge(*pmd))		/* THP, HugeTLB */
 		return pmd_young(*pmd);
 
 	pte = pte_offset_kernel(pmd, gpa);
@@ -1666,6 +1700,11 @@ phys_addr_t kvm_get_idmap_vector(void)
 	return hyp_idmap_vector;
 }
 
+phys_addr_t kvm_get_idmap_start(void)
+{
+	return hyp_idmap_start;
+}
+
 int kvm_mmu_init(void)
 {
 	int err;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-aspeed/Kconfig linux-libre-4.7-gnu/arch/arm/mach-aspeed/Kconfig
--- linux-libre-4.6-gnu/arch/arm/mach-aspeed/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/mach-aspeed/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,30 @@
+menuconfig ARCH_ASPEED
+	bool "Aspeed BMC architectures"
+	depends on ARCH_MULTI_V5 || ARCH_MULTI_V6
+	select SRAM
+	select WATCHDOG
+	select ASPEED_WATCHDOG
+	select MOXART_TIMER
+	help
+	  Say Y here if you want to run your kernel on an ASpeed BMC SoC.
+
+if ARCH_ASPEED
+
+config MACH_ASPEED_G4
+	bool "Aspeed SoC 4th Generation"
+	depends on ARCH_MULTI_V5
+	select CPU_ARM926T
+	help
+	 Say yes if you intend to run on an Aspeed ast2400 or similar
+	 fourth generation BMCs, such as those used by OpenPower Power8
+	 systems.
+
+config MACH_ASPEED_G5
+	bool "Aspeed SoC 5th Generation"
+	depends on ARCH_MULTI_V6
+	select CPU_V6
+	help
+	 Say yes if you intend to run on an Aspeed ast2500 or similar
+	 fifth generation Aspeed BMCs.
+
+endif
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-at91/sama5.c linux-libre-4.7-gnu/arch/arm/mach-at91/sama5.c
--- linux-libre-4.6-gnu/arch/arm/mach-at91/sama5.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-at91/sama5.c	2016-07-24 15:23:50.000000000 -0400
@@ -18,8 +18,26 @@
 #include "soc.h"
 
 static const struct at91_soc sama5_socs[] = {
-	AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27_EXID_MATCH,
+	AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D21CU_EXID_MATCH,
+		 "sama5d21", "sama5d2"),
+	AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D22CU_EXID_MATCH,
+		 "sama5d22", "sama5d2"),
+	AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D23CU_EXID_MATCH,
+		 "sama5d23", "sama5d2"),
+	AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D24CX_EXID_MATCH,
+		 "sama5d24", "sama5d2"),
+	AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D24CU_EXID_MATCH,
+		 "sama5d24", "sama5d2"),
+	AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D26CU_EXID_MATCH,
+		 "sama5d26", "sama5d2"),
+	AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27CU_EXID_MATCH,
+		 "sama5d27", "sama5d2"),
+	AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27CN_EXID_MATCH,
 		 "sama5d27", "sama5d2"),
+	AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28CU_EXID_MATCH,
+		 "sama5d28", "sama5d2"),
+	AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28CN_EXID_MATCH,
+		 "sama5d28", "sama5d2"),
 	AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D31_EXID_MATCH,
 		 "sama5d31", "sama5d3"),
 	AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D33_EXID_MATCH,
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-at91/soc.c linux-libre-4.7-gnu/arch/arm/mach-at91/soc.c
--- linux-libre-4.6-gnu/arch/arm/mach-at91/soc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-at91/soc.c	2016-07-24 15:23:50.000000000 -0400
@@ -22,48 +22,93 @@
 #include "soc.h"
 
 #define AT91_DBGU_CIDR			0x40
-#define AT91_DBGU_CIDR_VERSION(x)	((x) & 0x1f)
-#define AT91_DBGU_CIDR_EXT		BIT(31)
-#define AT91_DBGU_CIDR_MATCH_MASK	0x7fffffe0
 #define AT91_DBGU_EXID			0x44
+#define AT91_CHIPID_CIDR		0x00
+#define AT91_CHIPID_EXID		0x04
+#define AT91_CIDR_VERSION(x)		((x) & 0x1f)
+#define AT91_CIDR_EXT			BIT(31)
+#define AT91_CIDR_MATCH_MASK		0x7fffffe0
 
-struct soc_device * __init at91_soc_init(const struct at91_soc *socs)
+static int __init at91_get_cidr_exid_from_dbgu(u32 *cidr, u32 *exid)
 {
-	struct soc_device_attribute *soc_dev_attr;
-	const struct at91_soc *soc;
-	struct soc_device *soc_dev;
 	struct device_node *np;
 	void __iomem *regs;
-	u32 cidr, exid;
 
 	np = of_find_compatible_node(NULL, NULL, "atmel,at91rm9200-dbgu");
 	if (!np)
 		np = of_find_compatible_node(NULL, NULL,
 					     "atmel,at91sam9260-dbgu");
+	if (!np)
+		return -ENODEV;
 
-	if (!np) {
-		pr_warn("Could not find DBGU node");
-		return NULL;
+	regs = of_iomap(np, 0);
+	of_node_put(np);
+
+	if (!regs) {
+		pr_warn("Could not map DBGU iomem range");
+		return -ENXIO;
 	}
 
+	*cidr = readl(regs + AT91_DBGU_CIDR);
+	*exid = readl(regs + AT91_DBGU_EXID);
+
+	iounmap(regs);
+
+	return 0;
+}
+
+static int __init at91_get_cidr_exid_from_chipid(u32 *cidr, u32 *exid)
+{
+	struct device_node *np;
+	void __iomem *regs;
+
+	np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-chipid");
+	if (!np)
+		return -ENODEV;
+
 	regs = of_iomap(np, 0);
 	of_node_put(np);
 
 	if (!regs) {
 		pr_warn("Could not map DBGU iomem range");
-		return NULL;
+		return -ENXIO;
 	}
 
-	cidr = readl(regs + AT91_DBGU_CIDR);
-	exid = readl(regs + AT91_DBGU_EXID);
+	*cidr = readl(regs + AT91_CHIPID_CIDR);
+	*exid = readl(regs + AT91_CHIPID_EXID);
 
 	iounmap(regs);
 
+	return 0;
+}
+
+struct soc_device * __init at91_soc_init(const struct at91_soc *socs)
+{
+	struct soc_device_attribute *soc_dev_attr;
+	const struct at91_soc *soc;
+	struct soc_device *soc_dev;
+	u32 cidr, exid;
+	int ret;
+
+	/*
+	 * With SAMA5D2 and later SoCs, CIDR and EXID registers are no more
+	 * in the dbgu device but in the chipid device whose purpose is only
+	 * to expose these two registers.
+	 */
+	ret = at91_get_cidr_exid_from_dbgu(&cidr, &exid);
+	if (ret)
+		ret = at91_get_cidr_exid_from_chipid(&cidr, &exid);
+	if (ret) {
+		if (ret == -ENODEV)
+			pr_warn("Could not find identification node");
+		return NULL;
+	}
+
 	for (soc = socs; soc->name; soc++) {
-		if (soc->cidr_match != (cidr & AT91_DBGU_CIDR_MATCH_MASK))
+		if (soc->cidr_match != (cidr & AT91_CIDR_MATCH_MASK))
 			continue;
 
-		if (!(cidr & AT91_DBGU_CIDR_EXT) || soc->exid_match == exid)
+		if (!(cidr & AT91_CIDR_EXT) || soc->exid_match == exid)
 			break;
 	}
 
@@ -79,7 +124,7 @@ struct soc_device * __init at91_soc_init
 	soc_dev_attr->family = soc->family;
 	soc_dev_attr->soc_id = soc->name;
 	soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%X",
-					   AT91_DBGU_CIDR_VERSION(cidr));
+					   AT91_CIDR_VERSION(cidr));
 	soc_dev = soc_device_register(soc_dev_attr);
 	if (IS_ERR(soc_dev)) {
 		kfree(soc_dev_attr->revision);
@@ -91,7 +136,7 @@ struct soc_device * __init at91_soc_init
 	if (soc->family)
 		pr_info("Detected SoC family: %s\n", soc->family);
 	pr_info("Detected SoC: %s, revision %X\n", soc->name,
-		AT91_DBGU_CIDR_VERSION(cidr));
+		AT91_CIDR_VERSION(cidr));
 
 	return soc_dev;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-at91/soc.h linux-libre-4.7-gnu/arch/arm/mach-at91/soc.h
--- linux-libre-4.6-gnu/arch/arm/mach-at91/soc.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-at91/soc.h	2016-07-24 15:23:50.000000000 -0400
@@ -63,7 +63,17 @@ at91_soc_init(const struct at91_soc *soc
 #define AT91SAM9XE512_CIDR_MATCH	0x329aa3a0
 
 #define SAMA5D2_CIDR_MATCH		0x0a5c08c0
-#define SAMA5D27_EXID_MATCH		0x00000021
+#define SAMA5D21CU_EXID_MATCH		0x0000005a
+#define SAMA5D22CU_EXID_MATCH		0x00000059
+#define SAMA5D22CN_EXID_MATCH		0x00000069
+#define SAMA5D23CU_EXID_MATCH		0x00000058
+#define SAMA5D24CX_EXID_MATCH		0x00000004
+#define SAMA5D24CU_EXID_MATCH		0x00000014
+#define SAMA5D26CU_EXID_MATCH		0x00000012
+#define SAMA5D27CU_EXID_MATCH		0x00000011
+#define SAMA5D27CN_EXID_MATCH		0x00000021
+#define SAMA5D28CU_EXID_MATCH		0x00000010
+#define SAMA5D28CN_EXID_MATCH		0x00000020
 
 #define SAMA5D3_CIDR_MATCH		0x0a5c07c0
 #define SAMA5D31_EXID_MATCH		0x00444300
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-bcm/Kconfig linux-libre-4.7-gnu/arch/arm/mach-bcm/Kconfig
--- linux-libre-4.6-gnu/arch/arm/mach-bcm/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-bcm/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -173,12 +173,12 @@ config ARCH_BRCMSTB
 	select ARM_GIC
 	select ARM_ERRATA_798181 if SMP
 	select HAVE_ARM_ARCH_TIMER
-	select BRCMSTB_GISB_ARB
 	select BRCMSTB_L2_IRQ
 	select BCM7120_L2_IRQ
 	select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
 	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select SOC_BRCMSTB
+	select SOC_BUS
 	help
 	  Say Y if you intend to run the kernel on a Broadcom ARM-based STB
 	  chipset.
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-berlin/berlin.c linux-libre-4.7-gnu/arch/arm/mach-berlin/berlin.c
--- linux-libre-4.6-gnu/arch/arm/mach-berlin/berlin.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-berlin/berlin.c	2016-07-24 15:23:50.000000000 -0400
@@ -18,11 +18,6 @@
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/mach/arch.h>
 
-static void __init berlin_init_late(void)
-{
-	platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
-}
-
 static const char * const berlin_dt_compat[] = {
 	"marvell,berlin",
 	NULL,
@@ -30,7 +25,6 @@ static const char * const berlin_dt_comp
 
 DT_MACHINE_START(BERLIN_DT, "Marvell Berlin")
 	.dt_compat	= berlin_dt_compat,
-	.init_late	= berlin_init_late,
 	/*
 	 * with DT probing for L2CCs, berlin_init_machine can be removed.
 	 * Note: 88DE3005 (Armada 1500-mini) uses pl310 l2cc
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-davinci/clock.c linux-libre-4.7-gnu/arch/arm/mach-davinci/clock.c
--- linux-libre-4.6-gnu/arch/arm/mach-davinci/clock.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-davinci/clock.c	2016-07-24 15:23:50.000000000 -0400
@@ -195,6 +195,14 @@ int clk_set_parent(struct clk *clk, stru
 		return -EINVAL;
 
 	mutex_lock(&clocks_mutex);
+	if (clk->set_parent) {
+		int ret = clk->set_parent(clk, parent);
+
+		if (ret) {
+			mutex_unlock(&clocks_mutex);
+			return ret;
+		}
+	}
 	clk->parent = parent;
 	list_del_init(&clk->childnode);
 	list_add(&clk->childnode, &clk->parent->children);
@@ -224,8 +232,17 @@ int clk_register(struct clk *clk)
 
 	mutex_lock(&clocks_mutex);
 	list_add_tail(&clk->node, &clocks);
-	if (clk->parent)
+	if (clk->parent) {
+		if (clk->set_parent) {
+			int ret = clk->set_parent(clk, clk->parent);
+
+			if (ret) {
+				mutex_unlock(&clocks_mutex);
+				return ret;
+			}
+		}
 		list_add_tail(&clk->childnode, &clk->parent->children);
+	}
 	mutex_unlock(&clocks_mutex);
 
 	/* If rate is already set, use it */
@@ -560,7 +577,7 @@ EXPORT_SYMBOL(davinci_set_pllrate);
  * than that used by default in <soc>.c file. The reference clock rate
  * should be updated early in the boot process; ideally soon after the
  * clock tree has been initialized once with the default reference clock
- * rate (davinci_common_init()).
+ * rate (davinci_clk_init()).
  *
  * Returns 0 on success, error otherwise.
  */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-davinci/clock.h linux-libre-4.7-gnu/arch/arm/mach-davinci/clock.h
--- linux-libre-4.6-gnu/arch/arm/mach-davinci/clock.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-davinci/clock.h	2016-07-24 15:23:50.000000000 -0400
@@ -106,6 +106,7 @@ struct clk {
 	int (*reset) (struct clk *clk, bool reset);
 	void (*clk_enable) (struct clk *clk);
 	void (*clk_disable) (struct clk *clk);
+	int (*set_parent) (struct clk *clk, struct clk *parent);
 };
 
 /* Clock flags: SoC-specific flags start at BIT(16) */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-davinci/common.c linux-libre-4.7-gnu/arch/arm/mach-davinci/common.c
--- linux-libre-4.6-gnu/arch/arm/mach-davinci/common.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-davinci/common.c	2016-07-24 15:23:50.000000000 -0400
@@ -108,12 +108,6 @@ void __init davinci_common_init(struct d
 	if (ret < 0)
 		goto err;
 
-	if (davinci_soc_info.cpu_clks) {
-		ret = davinci_clk_init(davinci_soc_info.cpu_clks);
-
-		if (ret != 0)
-			goto err;
-	}
 
 	return;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-davinci/cp_intc.c linux-libre-4.7-gnu/arch/arm/mach-davinci/cp_intc.c
--- linux-libre-4.6-gnu/arch/arm/mach-davinci/cp_intc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-davinci/cp_intc.c	2016-07-24 15:23:50.000000000 -0400
@@ -12,6 +12,7 @@
 #include <linux/export.h>
 #include <linux/init.h>
 #include <linux/irq.h>
+#include <linux/irqchip.h>
 #include <linux/irqdomain.h>
 #include <linux/io.h>
 #include <linux/of.h>
@@ -210,3 +211,5 @@ void __init cp_intc_init(void)
 {
 	cp_intc_of_init(NULL, NULL);
 }
+
+IRQCHIP_DECLARE(cp_intc, "ti,cp-intc", cp_intc_of_init);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-davinci/da830.c linux-libre-4.7-gnu/arch/arm/mach-davinci/da830.c
--- linux-libre-4.6-gnu/arch/arm/mach-davinci/da830.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-davinci/da830.c	2016-07-24 15:23:50.000000000 -0400
@@ -1214,4 +1214,6 @@ void __init da830_init(void)
 
 	da8xx_syscfg0_base = ioremap(DA8XX_SYSCFG0_BASE, SZ_4K);
 	WARN(!da8xx_syscfg0_base, "Unable to map syscfg0 module");
+
+	davinci_clk_init(davinci_soc_info_da830.cpu_clks);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-davinci/da850.c linux-libre-4.7-gnu/arch/arm/mach-davinci/da850.c
--- linux-libre-4.6-gnu/arch/arm/mach-davinci/da850.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-davinci/da850.c	2016-07-24 15:23:50.000000000 -0400
@@ -34,9 +34,6 @@
 #include "clock.h"
 #include "mux.h"
 
-/* SoC specific clock flags */
-#define DA850_CLK_ASYNC3	BIT(16)
-
 #define DA850_PLL1_BASE		0x01e1a000
 #define DA850_TIMER64P2_BASE	0x01f0c000
 #define DA850_TIMER64P3_BASE	0x01f0d000
@@ -161,6 +158,32 @@ static struct clk pll1_sysclk3 = {
 	.div_reg	= PLLDIV3,
 };
 
+static int da850_async3_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 val;
+
+	val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG));
+
+	if (parent == &pll0_sysclk2) {
+		val &= ~CFGCHIP3_ASYNC3_CLKSRC;
+	} else if (parent == &pll1_sysclk2) {
+		val |= CFGCHIP3_ASYNC3_CLKSRC;
+	} else {
+		pr_err("Bad parent on async3 clock mux\n");
+		return -EINVAL;
+	}
+
+	writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG));
+
+	return 0;
+}
+
+static struct clk async3_clk = {
+	.name		= "async3",
+	.parent		= &pll1_sysclk2,
+	.set_parent	= da850_async3_set_parent,
+};
+
 static struct clk i2c0_clk = {
 	.name		= "i2c0",
 	.parent		= &pll0_aux_clk,
@@ -234,18 +257,16 @@ static struct clk uart0_clk = {
 
 static struct clk uart1_clk = {
 	.name		= "uart1",
-	.parent		= &pll0_sysclk2,
+	.parent		= &async3_clk,
 	.lpsc		= DA8XX_LPSC1_UART1,
 	.gpsc		= 1,
-	.flags		= DA850_CLK_ASYNC3,
 };
 
 static struct clk uart2_clk = {
 	.name		= "uart2",
-	.parent		= &pll0_sysclk2,
+	.parent		= &async3_clk,
 	.lpsc		= DA8XX_LPSC1_UART2,
 	.gpsc		= 1,
-	.flags		= DA850_CLK_ASYNC3,
 };
 
 static struct clk aintc_clk = {
@@ -300,10 +321,9 @@ static struct clk emac_clk = {
 
 static struct clk mcasp_clk = {
 	.name		= "mcasp",
-	.parent		= &pll0_sysclk2,
+	.parent		= &async3_clk,
 	.lpsc		= DA8XX_LPSC1_McASP0,
 	.gpsc		= 1,
-	.flags		= DA850_CLK_ASYNC3,
 };
 
 static struct clk lcdc_clk = {
@@ -355,10 +375,9 @@ static struct clk spi0_clk = {
 
 static struct clk spi1_clk = {
 	.name		= "spi1",
-	.parent		= &pll0_sysclk2,
+	.parent		= &async3_clk,
 	.lpsc		= DA8XX_LPSC1_SPI1,
 	.gpsc		= 1,
-	.flags		= DA850_CLK_ASYNC3,
 };
 
 static struct clk vpif_clk = {
@@ -386,10 +405,9 @@ static struct clk dsp_clk = {
 
 static struct clk ehrpwm_clk = {
 	.name		= "ehrpwm",
-	.parent		= &pll0_sysclk2,
+	.parent		= &async3_clk,
 	.lpsc		= DA8XX_LPSC1_PWM,
 	.gpsc		= 1,
-	.flags		= DA850_CLK_ASYNC3,
 };
 
 #define DA8XX_EHRPWM_TBCLKSYNC	BIT(12)
@@ -421,10 +439,9 @@ static struct clk ehrpwm_tbclk = {
 
 static struct clk ecap_clk = {
 	.name		= "ecap",
-	.parent		= &pll0_sysclk2,
+	.parent		= &async3_clk,
 	.lpsc		= DA8XX_LPSC1_ECAP,
 	.gpsc		= 1,
-	.flags		= DA850_CLK_ASYNC3,
 };
 
 static struct clk_lookup da850_clks[] = {
@@ -442,6 +459,7 @@ static struct clk_lookup da850_clks[] =
 	CLK(NULL,		"pll1_aux",	&pll1_aux_clk),
 	CLK(NULL,		"pll1_sysclk2",	&pll1_sysclk2),
 	CLK(NULL,		"pll1_sysclk3",	&pll1_sysclk3),
+	CLK(NULL,		"async3",	&async3_clk),
 	CLK("i2c_davinci.1",	NULL,		&i2c0_clk),
 	CLK(NULL,		"timer0",	&timerp64_0_clk),
 	CLK("davinci-wdt",	NULL,		&timerp64_1_clk),
@@ -909,30 +927,6 @@ static struct davinci_timer_info da850_t
 	.clocksource_id	= T0_TOP,
 };
 
-static void da850_set_async3_src(int pllnum)
-{
-	struct clk *clk, *newparent = pllnum ? &pll1_sysclk2 : &pll0_sysclk2;
-	struct clk_lookup *c;
-	unsigned int v;
-	int ret;
-
-	for (c = da850_clks; c->clk; c++) {
-		clk = c->clk;
-		if (clk->flags & DA850_CLK_ASYNC3) {
-			ret = clk_set_parent(clk, newparent);
-			WARN(ret, "DA850: unable to re-parent clock %s",
-								clk->name);
-		}
-       }
-
-	v = __raw_readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG));
-	if (pllnum)
-		v |= CFGCHIP3_ASYNC3_CLKSRC;
-	else
-		v &= ~CFGCHIP3_ASYNC3_CLKSRC;
-	__raw_writel(v, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG));
-}
-
 #ifdef CONFIG_CPU_FREQ
 /*
  * Notes:
@@ -1328,15 +1322,6 @@ void __init da850_init(void)
 	if (WARN(!da8xx_syscfg1_base, "Unable to map syscfg1 module"))
 		return;
 
-	/*
-	 * Move the clock source of Async3 domain to PLL1 SYSCLK2.
-	 * This helps keeping the peripherals on this domain insulated
-	 * from CPU frequency changes caused by DVFS. The firmware sets
-	 * both PLL0 and PLL1 to the same frequency so, there should not
-	 * be any noticeable change even in non-DVFS use cases.
-	 */
-	da850_set_async3_src(1);
-
 	/* Unlock writing to PLL0 registers */
 	v = __raw_readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP0_REG));
 	v &= ~CFGCHIP0_PLL_MASTER_LOCK;
@@ -1346,4 +1331,6 @@ void __init da850_init(void)
 	v = __raw_readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG));
 	v &= ~CFGCHIP3_PLL1_MASTER_LOCK;
 	__raw_writel(v, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG));
+
+	davinci_clk_init(davinci_soc_info_da850.cpu_clks);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-davinci/da8xx-dt.c linux-libre-4.7-gnu/arch/arm/mach-davinci/da8xx-dt.c
--- linux-libre-4.6-gnu/arch/arm/mach-davinci/da8xx-dt.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-davinci/da8xx-dt.c	2016-07-24 15:23:50.000000000 -0400
@@ -18,20 +18,9 @@
 #include "cp_intc.h"
 #include <mach/da8xx.h>
 
-#define DA8XX_NUM_UARTS	3
-
-static const struct of_device_id const da8xx_irq_match[] __initconst = {
-	{ .compatible = "ti,cp-intc", .data = cp_intc_of_init, },
-	{ }
-};
-
-static void __init da8xx_init_irq(void)
-{
-	of_irq_init(da8xx_irq_match);
-}
-
 static struct of_dev_auxdata da850_auxdata_lookup[] __initdata = {
 	OF_DEV_AUXDATA("ti,davinci-i2c", 0x01c22000, "i2c_davinci.1", NULL),
+	OF_DEV_AUXDATA("ti,davinci-i2c", 0x01e28000, "i2c_davinci.2", NULL),
 	OF_DEV_AUXDATA("ti,davinci-wdt", 0x01c21000, "davinci-wdt", NULL),
 	OF_DEV_AUXDATA("ti,da830-mmc", 0x01c40000, "da830-mmc.0", NULL),
 	OF_DEV_AUXDATA("ti,da850-ehrpwm", 0x01f00000, "ehrpwm", NULL),
@@ -39,6 +28,7 @@ static struct of_dev_auxdata da850_auxda
 	OF_DEV_AUXDATA("ti,da850-ecap", 0x01f06000, "ecap", NULL),
 	OF_DEV_AUXDATA("ti,da850-ecap", 0x01f07000, "ecap", NULL),
 	OF_DEV_AUXDATA("ti,da850-ecap", 0x01f08000, "ecap", NULL),
+	OF_DEV_AUXDATA("ti,da830-spi", 0x01c41000, "spi_davinci.0", NULL),
 	OF_DEV_AUXDATA("ti,da830-spi", 0x01f0e000, "spi_davinci.1", NULL),
 	OF_DEV_AUXDATA("ns16550a", 0x01c42000, "serial8250.0", NULL),
 	OF_DEV_AUXDATA("ns16550a", 0x01d0c000, "serial8250.1", NULL),
@@ -54,9 +44,7 @@ static struct of_dev_auxdata da850_auxda
 
 static void __init da850_init_machine(void)
 {
-	of_platform_populate(NULL, of_default_bus_match_table,
-			     da850_auxdata_lookup, NULL);
-
+	of_platform_default_populate(NULL, da850_auxdata_lookup, NULL);
 }
 
 static const char *const da850_boards_compat[] __initconst = {
@@ -68,7 +56,6 @@ static const char *const da850_boards_co
 
 DT_MACHINE_START(DA850_DT, "Generic DA850/OMAP-L138/AM18x")
 	.map_io		= da850_init,
-	.init_irq	= da8xx_init_irq,
 	.init_time	= davinci_timer_init,
 	.init_machine	= da850_init_machine,
 	.dt_compat	= da850_boards_compat,
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-davinci/devices.c linux-libre-4.7-gnu/arch/arm/mach-davinci/devices.c
--- linux-libre-4.6-gnu/arch/arm/mach-davinci/devices.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-davinci/devices.c	2016-07-24 15:23:50.000000000 -0400
@@ -144,14 +144,6 @@ static struct resource mmcsd0_resources[
 		.start = IRQ_SDIOINT,
 		.flags = IORESOURCE_IRQ,
 	},
-	/* DMA channels: RX, then TX */
-	{
-		.start = EDMA_CTLR_CHAN(0, DAVINCI_DMA_MMCRXEVT),
-		.flags = IORESOURCE_DMA,
-	}, {
-		.start = EDMA_CTLR_CHAN(0, DAVINCI_DMA_MMCTXEVT),
-		.flags = IORESOURCE_DMA,
-	},
 };
 
 static struct platform_device davinci_mmcsd0_device = {
@@ -181,14 +173,6 @@ static struct resource mmcsd1_resources[
 		.start = IRQ_DM355_SDIOINT1,
 		.flags = IORESOURCE_IRQ,
 	},
-	/* DMA channels: RX, then TX */
-	{
-		.start = EDMA_CTLR_CHAN(0, 30),	/* rx */
-		.flags = IORESOURCE_DMA,
-	}, {
-		.start = EDMA_CTLR_CHAN(0, 31),	/* tx */
-		.flags = IORESOURCE_DMA,
-	},
 };
 
 static struct platform_device davinci_mmcsd1_device = {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-davinci/devices-da8xx.c linux-libre-4.7-gnu/arch/arm/mach-davinci/devices-da8xx.c
--- linux-libre-4.6-gnu/arch/arm/mach-davinci/devices-da8xx.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-davinci/devices-da8xx.c	2016-07-24 15:23:50.000000000 -0400
@@ -751,16 +751,6 @@ static struct resource da8xx_mmcsd0_reso
 		.end	= IRQ_DA8XX_MMCSDINT0,
 		.flags	= IORESOURCE_IRQ,
 	},
-	{		/* DMA RX */
-		.start	= DA8XX_DMA_MMCSD0_RX,
-		.end	= DA8XX_DMA_MMCSD0_RX,
-		.flags	= IORESOURCE_DMA,
-	},
-	{		/* DMA TX */
-		.start	= DA8XX_DMA_MMCSD0_TX,
-		.end	= DA8XX_DMA_MMCSD0_TX,
-		.flags	= IORESOURCE_DMA,
-	},
 };
 
 static struct platform_device da8xx_mmcsd0_device = {
@@ -788,16 +778,6 @@ static struct resource da850_mmcsd1_reso
 		.end	= IRQ_DA850_MMCSDINT0_1,
 		.flags	= IORESOURCE_IRQ,
 	},
-	{		/* DMA RX */
-		.start	= DA850_DMA_MMCSD1_RX,
-		.end	= DA850_DMA_MMCSD1_RX,
-		.flags	= IORESOURCE_DMA,
-	},
-	{		/* DMA TX */
-		.start	= DA850_DMA_MMCSD1_TX,
-		.end	= DA850_DMA_MMCSD1_TX,
-		.flags	= IORESOURCE_DMA,
-	},
 };
 
 static struct platform_device da850_mmcsd1_device = {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-davinci/dm355.c linux-libre-4.7-gnu/arch/arm/mach-davinci/dm355.c
--- linux-libre-4.6-gnu/arch/arm/mach-davinci/dm355.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-davinci/dm355.c	2016-07-24 15:23:50.000000000 -0400
@@ -1052,6 +1052,7 @@ void __init dm355_init(void)
 {
 	davinci_common_init(&davinci_soc_info_dm355);
 	davinci_map_sysmod();
+	davinci_clk_init(davinci_soc_info_dm355.cpu_clks);
 }
 
 int __init dm355_init_video(struct vpfe_config *vpfe_cfg,
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-davinci/dm365.c linux-libre-4.7-gnu/arch/arm/mach-davinci/dm365.c
--- linux-libre-4.6-gnu/arch/arm/mach-davinci/dm365.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-davinci/dm365.c	2016-07-24 15:23:50.000000000 -0400
@@ -1176,6 +1176,7 @@ void __init dm365_init(void)
 {
 	davinci_common_init(&davinci_soc_info_dm365);
 	davinci_map_sysmod();
+	davinci_clk_init(davinci_soc_info_dm365.cpu_clks);
 }
 
 static struct resource dm365_vpss_resources[] = {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-davinci/dm644x.c linux-libre-4.7-gnu/arch/arm/mach-davinci/dm644x.c
--- linux-libre-4.6-gnu/arch/arm/mach-davinci/dm644x.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-davinci/dm644x.c	2016-07-24 15:23:50.000000000 -0400
@@ -932,6 +932,7 @@ void __init dm644x_init(void)
 {
 	davinci_common_init(&davinci_soc_info_dm644x);
 	davinci_map_sysmod();
+	davinci_clk_init(davinci_soc_info_dm644x.cpu_clks);
 }
 
 int __init dm644x_init_video(struct vpfe_config *vpfe_cfg,
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-davinci/dm646x.c linux-libre-4.7-gnu/arch/arm/mach-davinci/dm646x.c
--- linux-libre-4.6-gnu/arch/arm/mach-davinci/dm646x.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-davinci/dm646x.c	2016-07-24 15:23:50.000000000 -0400
@@ -956,6 +956,7 @@ void __init dm646x_init(void)
 {
 	davinci_common_init(&davinci_soc_info_dm646x);
 	davinci_map_sysmod();
+	davinci_clk_init(davinci_soc_info_dm646x.cpu_clks);
 }
 
 static int __init dm646x_init_devices(void)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-davinci/Makefile linux-libre-4.7-gnu/arch/arm/mach-davinci/Makefile
--- linux-libre-4.6-gnu/arch/arm/mach-davinci/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-davinci/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -14,8 +14,8 @@ obj-$(CONFIG_ARCH_DAVINCI_DM644x)
 obj-$(CONFIG_ARCH_DAVINCI_DM355)        += dm355.o devices.o
 obj-$(CONFIG_ARCH_DAVINCI_DM646x)       += dm646x.o devices.o
 obj-$(CONFIG_ARCH_DAVINCI_DM365)	+= dm365.o devices.o
-obj-$(CONFIG_ARCH_DAVINCI_DA830)        += da830.o devices-da8xx.o
-obj-$(CONFIG_ARCH_DAVINCI_DA850)        += da850.o devices-da8xx.o
+obj-$(CONFIG_ARCH_DAVINCI_DA830)	+= da830.o devices-da8xx.o usb-da8xx.o
+obj-$(CONFIG_ARCH_DAVINCI_DA850)	+= da850.o devices-da8xx.o usb-da8xx.o
 
 obj-$(CONFIG_AINTC)			+= irq.o
 obj-$(CONFIG_CP_INTC)			+= cp_intc.o
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-davinci/usb.c linux-libre-4.7-gnu/arch/arm/mach-davinci/usb.c
--- linux-libre-4.6-gnu/arch/arm/mach-davinci/usb.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-davinci/usb.c	2016-07-24 15:23:50.000000000 -0400
@@ -10,36 +10,16 @@
 #include <mach/common.h>
 #include <mach/irqs.h>
 #include <mach/cputype.h>
-#include <mach/da8xx.h>
 #include <linux/platform_data/usb-davinci.h>
 
 #define DAVINCI_USB_OTG_BASE	0x01c64000
 
-#define DA8XX_USB0_BASE 	0x01e00000
-#define DA8XX_USB1_BASE 	0x01e25000
-
 #if IS_ENABLED(CONFIG_USB_MUSB_HDRC)
-static struct musb_hdrc_eps_bits musb_eps[] = {
-	{ "ep1_tx", 8, },
-	{ "ep1_rx", 8, },
-	{ "ep2_tx", 8, },
-	{ "ep2_rx", 8, },
-	{ "ep3_tx", 5, },
-	{ "ep3_rx", 5, },
-	{ "ep4_tx", 5, },
-	{ "ep4_rx", 5, },
-};
-
 static struct musb_hdrc_config musb_config = {
 	.multipoint	= true,
-	.dyn_fifo	= true,
-	.soft_con	= true,
-	.dma		= true,
 
 	.num_eps	= 5,
-	.dma_channels	= 8,
 	.ram_bits	= 10,
-	.eps_bits	= musb_eps,
 };
 
 static struct musb_hdrc_platform_data usb_data = {
@@ -97,79 +77,10 @@ void __init davinci_setup_usb(unsigned m
 	platform_device_register(&usb_dev);
 }
 
-#ifdef CONFIG_ARCH_DAVINCI_DA8XX
-static struct resource da8xx_usb20_resources[] = {
-	{
-		.start		= DA8XX_USB0_BASE,
-		.end		= DA8XX_USB0_BASE + SZ_64K - 1,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.start		= IRQ_DA8XX_USB_INT,
-		.flags		= IORESOURCE_IRQ,
-		.name		= "mc",
-	},
-};
-
-int __init da8xx_register_usb20(unsigned mA, unsigned potpgt)
-{
-	usb_data.clock  = "usb20";
-	usb_data.power	= mA > 510 ? 255 : mA / 2;
-	usb_data.potpgt = (potpgt + 1) / 2;
-
-	usb_dev.resource = da8xx_usb20_resources;
-	usb_dev.num_resources = ARRAY_SIZE(da8xx_usb20_resources);
-	usb_dev.name = "musb-da8xx";
-
-	return platform_device_register(&usb_dev);
-}
-#endif	/* CONFIG_DAVINCI_DA8XX */
-
 #else
 
 void __init davinci_setup_usb(unsigned mA, unsigned potpgt_ms)
 {
 }
 
-#ifdef CONFIG_ARCH_DAVINCI_DA8XX
-int __init da8xx_register_usb20(unsigned mA, unsigned potpgt)
-{
-	return 0;
-}
-#endif
-
 #endif  /* CONFIG_USB_MUSB_HDRC */
-
-#ifdef	CONFIG_ARCH_DAVINCI_DA8XX
-static struct resource da8xx_usb11_resources[] = {
-	[0] = {
-		.start	= DA8XX_USB1_BASE,
-		.end	= DA8XX_USB1_BASE + SZ_4K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_DA8XX_IRQN,
-		.end	= IRQ_DA8XX_IRQN,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static u64 da8xx_usb11_dma_mask = DMA_BIT_MASK(32);
-
-static struct platform_device da8xx_usb11_device = {
-	.name		= "ohci",
-	.id		= 0,
-	.dev = {
-		.dma_mask		= &da8xx_usb11_dma_mask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-	.num_resources	= ARRAY_SIZE(da8xx_usb11_resources),
-	.resource	= da8xx_usb11_resources,
-};
-
-int __init da8xx_register_usb11(struct da8xx_ohci_root_hub *pdata)
-{
-	da8xx_usb11_device.dev.platform_data = pdata;
-	return platform_device_register(&da8xx_usb11_device);
-}
-#endif	/* CONFIG_DAVINCI_DA8XX */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-davinci/usb-da8xx.c linux-libre-4.7-gnu/arch/arm/mach-davinci/usb-da8xx.c
--- linux-libre-4.6-gnu/arch/arm/mach-davinci/usb-da8xx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/mach-davinci/usb-da8xx.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,107 @@
+/*
+ * DA8xx USB
+ */
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/platform_data/usb-davinci.h>
+#include <linux/platform_device.h>
+#include <linux/usb/musb.h>
+
+#include <mach/common.h>
+#include <mach/cputype.h>
+#include <mach/da8xx.h>
+#include <mach/irqs.h>
+
+#define DA8XX_USB0_BASE		0x01e00000
+#define DA8XX_USB1_BASE		0x01e25000
+
+#if IS_ENABLED(CONFIG_USB_MUSB_HDRC)
+
+static struct musb_hdrc_config musb_config = {
+	.multipoint	= true,
+	.num_eps	= 5,
+	.ram_bits	= 10,
+};
+
+static struct musb_hdrc_platform_data usb_data = {
+	/* OTG requires a Mini-AB connector */
+	.mode           = MUSB_OTG,
+	.clock		= "usb20",
+	.config		= &musb_config,
+};
+
+static struct resource da8xx_usb20_resources[] = {
+	{
+		.start		= DA8XX_USB0_BASE,
+		.end		= DA8XX_USB0_BASE + SZ_64K - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= IRQ_DA8XX_USB_INT,
+		.flags		= IORESOURCE_IRQ,
+		.name		= "mc",
+	},
+};
+
+static u64 usb_dmamask = DMA_BIT_MASK(32);
+
+static struct platform_device usb_dev = {
+	.name		= "musb-da8xx",
+	.id             = -1,
+	.dev = {
+		.platform_data		= &usb_data,
+		.dma_mask		= &usb_dmamask,
+		.coherent_dma_mask      = DMA_BIT_MASK(32),
+	},
+	.resource	= da8xx_usb20_resources,
+	.num_resources	= ARRAY_SIZE(da8xx_usb20_resources),
+};
+
+int __init da8xx_register_usb20(unsigned int mA, unsigned int potpgt)
+{
+	usb_data.power	= mA > 510 ? 255 : mA / 2;
+	usb_data.potpgt = (potpgt + 1) / 2;
+
+	return platform_device_register(&usb_dev);
+}
+
+#else
+
+int __init da8xx_register_usb20(unsigned int mA, unsigned int potpgt)
+{
+	return 0;
+}
+
+#endif  /* CONFIG_USB_MUSB_HDRC */
+
+static struct resource da8xx_usb11_resources[] = {
+	[0] = {
+		.start	= DA8XX_USB1_BASE,
+		.end	= DA8XX_USB1_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_DA8XX_IRQN,
+		.end	= IRQ_DA8XX_IRQN,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static u64 da8xx_usb11_dma_mask = DMA_BIT_MASK(32);
+
+static struct platform_device da8xx_usb11_device = {
+	.name		= "ohci",
+	.id		= 0,
+	.dev = {
+		.dma_mask		= &da8xx_usb11_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+	.num_resources	= ARRAY_SIZE(da8xx_usb11_resources),
+	.resource	= da8xx_usb11_resources,
+};
+
+int __init da8xx_register_usb11(struct da8xx_ohci_root_hub *pdata)
+{
+	da8xx_usb11_device.dev.platform_data = pdata;
+	return platform_device_register(&da8xx_usb11_device);
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-dove/common.c linux-libre-4.7-gnu/arch/arm/mach-dove/common.c
--- linux-libre-4.6-gnu/arch/arm/mach-dove/common.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-dove/common.c	2016-07-24 15:23:50.000000000 -0400
@@ -88,8 +88,7 @@ static void __init dove_clk_init(void)
 	struct clk *nand, *camera, *i2s0, *i2s1, *crypto, *ac97, *pdma;
 	struct clk *xor0, *xor1, *ge, *gephy;
 
-	tclk = clk_register_fixed_rate(NULL, "tclk", NULL, CLK_IS_ROOT,
-				       dove_tclk);
+	tclk = clk_register_fixed_rate(NULL, "tclk", NULL, 0, dove_tclk);
 
 	usb0 = dove_register_gate("usb0", "tclk", CLOCK_GATING_BIT_USB0);
 	usb1 = dove_register_gate("usb1", "tclk", CLOCK_GATING_BIT_USB1);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-exynos/exynos.c linux-libre-4.7-gnu/arch/arm/mach-exynos/exynos.c
--- linux-libre-4.6-gnu/arch/arm/mach-exynos/exynos.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-exynos/exynos.c	2016-07-24 15:23:50.000000000 -0400
@@ -31,11 +31,6 @@
 
 static struct map_desc exynos4_iodesc[] __initdata = {
 	{
-		.virtual	= (unsigned long)S5P_VA_SROMC,
-		.pfn		= __phys_to_pfn(EXYNOS4_PA_SROMC),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
 		.virtual	= (unsigned long)S5P_VA_CMU,
 		.pfn		= __phys_to_pfn(EXYNOS4_PA_CMU),
 		.length		= SZ_128K,
@@ -58,15 +53,6 @@ static struct map_desc exynos4_iodesc[]
 	},
 };
 
-static struct map_desc exynos5_iodesc[] __initdata = {
-	{
-		.virtual	= (unsigned long)S5P_VA_SROMC,
-		.pfn		= __phys_to_pfn(EXYNOS5_PA_SROMC),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	},
-};
-
 static struct platform_device exynos_cpuidle = {
 	.name              = "exynos_cpuidle",
 #ifdef CONFIG_ARM_EXYNOS_CPUIDLE
@@ -138,9 +124,6 @@ static void __init exynos_map_io(void)
 {
 	if (soc_is_exynos4())
 		iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc));
-
-	if (soc_is_exynos5())
-		iotable_init(exynos5_iodesc, ARRAY_SIZE(exynos5_iodesc));
 }
 
 static void __init exynos_init_io(void)
@@ -213,33 +196,6 @@ static void __init exynos_init_irq(void)
 	exynos_map_pmu();
 }
 
-static const struct of_device_id exynos_cpufreq_matches[] = {
-	{ .compatible = "samsung,exynos3250", .data = "cpufreq-dt" },
-	{ .compatible = "samsung,exynos4210", .data = "cpufreq-dt" },
-	{ .compatible = "samsung,exynos4212", .data = "cpufreq-dt" },
-	{ .compatible = "samsung,exynos4412", .data = "cpufreq-dt" },
-	{ .compatible = "samsung,exynos5250", .data = "cpufreq-dt" },
-#ifndef CONFIG_BL_SWITCHER
-	{ .compatible = "samsung,exynos5420", .data = "cpufreq-dt" },
-	{ .compatible = "samsung,exynos5800", .data = "cpufreq-dt" },
-#endif
-	{ /* sentinel */ }
-};
-
-static void __init exynos_cpufreq_init(void)
-{
-	struct device_node *root = of_find_node_by_path("/");
-	const struct of_device_id *match;
-
-	match = of_match_node(exynos_cpufreq_matches, root);
-	if (!match) {
-		platform_device_register_simple("exynos-cpufreq", -1, NULL, 0);
-		return;
-	}
-
-	platform_device_register_simple(match->data, -1, NULL, 0);
-}
-
 static void __init exynos_dt_machine_init(void)
 {
 	/*
@@ -262,8 +218,6 @@ static void __init exynos_dt_machine_ini
 	    of_machine_is_compatible("samsung,exynos5250"))
 		platform_device_register(&exynos_cpuidle);
 
-	exynos_cpufreq_init();
-
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-exynos/include/mach/map.h linux-libre-4.7-gnu/arch/arm/mach-exynos/include/mach/map.h
--- linux-libre-4.6-gnu/arch/arm/mach-exynos/include/mach/map.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-exynos/include/mach/map.h	2016-07-24 15:23:50.000000000 -0400
@@ -25,7 +25,4 @@
 
 #define EXYNOS4_PA_COREPERI		0x10500000
 
-#define EXYNOS4_PA_SROMC		0x12570000
-#define EXYNOS5_PA_SROMC		0x12250000
-
 #endif /* __ASM_ARCH_MAP_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-exynos/Kconfig linux-libre-4.7-gnu/arch/arm/mach-exynos/Kconfig
--- linux-libre-4.6-gnu/arch/arm/mach-exynos/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-exynos/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -18,6 +18,7 @@ menuconfig ARCH_EXYNOS
 	select COMMON_CLK_SAMSUNG
 	select EXYNOS_THERMAL
 	select EXYNOS_PMU
+	select EXYNOS_SROM
 	select HAVE_ARM_SCU if SMP
 	select HAVE_S3C2410_I2C if I2C
 	select HAVE_S3C2410_WATCHDOG if WATCHDOG
@@ -26,11 +27,13 @@ menuconfig ARCH_EXYNOS
 	select PINCTRL_EXYNOS
 	select PM_GENERIC_DOMAINS if PM
 	select S5P_DEV_MFC
+	select SAMSUNG_MC
 	select SOC_SAMSUNG
 	select SRAM
 	select THERMAL
 	select THERMAL_OF
 	select MFD_SYSCON
+	select MEMORY
 	select CLKSRC_EXYNOS_MCT
 	select POWER_RESET
 	select POWER_RESET_SYSCON
@@ -58,7 +61,6 @@ config ARCH_EXYNOS4
 	select CLKSRC_SAMSUNG_PWM if CPU_EXYNOS4210
 	select CPU_EXYNOS4210
 	select GIC_NON_BANKED
-	select KEYBOARD_SAMSUNG if INPUT_KEYBOARD
 	select MIGHT_HAVE_CACHE_L2X0
 	help
 	  Samsung EXYNOS4 (Cortex-A9) SoC based systems
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-exynos/regs-srom.h linux-libre-4.7-gnu/arch/arm/mach-exynos/regs-srom.h
--- linux-libre-4.6-gnu/arch/arm/mach-exynos/regs-srom.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-exynos/regs-srom.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5P SROMC register definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __PLAT_SAMSUNG_REGS_SROM_H
-#define __PLAT_SAMSUNG_REGS_SROM_H __FILE__
-
-#include <mach/map.h>
-
-#define S5P_SROMREG(x)		(S5P_VA_SROMC + (x))
-
-#define S5P_SROM_BW		S5P_SROMREG(0x0)
-#define S5P_SROM_BC0		S5P_SROMREG(0x4)
-#define S5P_SROM_BC1		S5P_SROMREG(0x8)
-#define S5P_SROM_BC2		S5P_SROMREG(0xc)
-#define S5P_SROM_BC3		S5P_SROMREG(0x10)
-#define S5P_SROM_BC4		S5P_SROMREG(0x14)
-#define S5P_SROM_BC5		S5P_SROMREG(0x18)
-
-/* one register BW holds 4 x 4-bit packed settings for NCS0 - NCS3 */
-
-#define S5P_SROM_BW__DATAWIDTH__SHIFT		0
-#define S5P_SROM_BW__ADDRMODE__SHIFT		1
-#define S5P_SROM_BW__WAITENABLE__SHIFT		2
-#define S5P_SROM_BW__BYTEENABLE__SHIFT		3
-
-#define S5P_SROM_BW__CS_MASK			0xf
-
-#define S5P_SROM_BW__NCS0__SHIFT		0
-#define S5P_SROM_BW__NCS1__SHIFT		4
-#define S5P_SROM_BW__NCS2__SHIFT		8
-#define S5P_SROM_BW__NCS3__SHIFT		12
-#define S5P_SROM_BW__NCS4__SHIFT		16
-#define S5P_SROM_BW__NCS5__SHIFT		20
-
-/* applies to same to BCS0 - BCS3 */
-
-#define S5P_SROM_BCX__PMC__SHIFT		0
-#define S5P_SROM_BCX__TACP__SHIFT		4
-#define S5P_SROM_BCX__TCAH__SHIFT		8
-#define S5P_SROM_BCX__TCOH__SHIFT		12
-#define S5P_SROM_BCX__TACC__SHIFT		16
-#define S5P_SROM_BCX__TCOS__SHIFT		24
-#define S5P_SROM_BCX__TACS__SHIFT		28
-
-#endif /* __PLAT_SAMSUNG_REGS_SROM_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-exynos/suspend.c linux-libre-4.7-gnu/arch/arm/mach-exynos/suspend.c
--- linux-libre-4.6-gnu/arch/arm/mach-exynos/suspend.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-exynos/suspend.c	2016-07-24 15:23:50.000000000 -0400
@@ -34,10 +34,11 @@
 #include <asm/smp_scu.h>
 #include <asm/suspend.h>
 
+#include <mach/map.h>
+
 #include <plat/pm-common.h>
 
 #include "common.h"
-#include "regs-srom.h"
 
 #define REG_TABLE_END (-1U)
 
@@ -53,15 +54,6 @@ struct exynos_wkup_irq {
 	u32 mask;
 };
 
-static struct sleep_save exynos_core_save[] = {
-	/* SROM side */
-	SAVE_ITEM(S5P_SROM_BW),
-	SAVE_ITEM(S5P_SROM_BC0),
-	SAVE_ITEM(S5P_SROM_BC1),
-	SAVE_ITEM(S5P_SROM_BC2),
-	SAVE_ITEM(S5P_SROM_BC3),
-};
-
 struct exynos_pm_data {
 	const struct exynos_wkup_irq *wkup_irq;
 	unsigned int wake_disable_mask;
@@ -343,8 +335,6 @@ static void exynos_pm_prepare(void)
 	/* Set wake-up mask registers */
 	exynos_pm_set_wakeup_mask();
 
-	s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save));
-
 	exynos_pm_enter_sleep_mode();
 
 	/* ensure at least INFORM0 has the resume address */
@@ -375,8 +365,6 @@ static void exynos5420_pm_prepare(void)
 	/* Set wake-up mask registers */
 	exynos_pm_set_wakeup_mask();
 
-	s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save));
-
 	exynos_pmu_spare3 = pmu_raw_readl(S5P_PMU_SPARE3);
 	/*
 	 * The cpu state needs to be saved and restored so that the
@@ -467,8 +455,6 @@ static void exynos_pm_resume(void)
 	/* For release retention */
 	exynos_pm_release_retention();
 
-	s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save));
-
 	if (cpuid == ARM_CPU_PART_CORTEX_A9)
 		scu_enable(S5P_VA_SCU);
 
@@ -535,8 +521,6 @@ static void exynos5420_pm_resume(void)
 
 	pmu_raw_writel(exynos_pmu_spare3, S5P_PMU_SPARE3);
 
-	s3c_pm_do_restore_core(exynos_core_save, ARRAY_SIZE(exynos_core_save));
-
 early_wakeup:
 
 	tmp = pmu_raw_readl(EXYNOS5420_SFR_AXI_CGDIS1);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-imx/imx27-dt.c linux-libre-4.7-gnu/arch/arm/mach-imx/imx27-dt.c
--- linux-libre-4.6-gnu/arch/arm/mach-imx/imx27-dt.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-imx/imx27-dt.c	2016-07-24 15:23:50.000000000 -0400
@@ -18,15 +18,6 @@
 #include "common.h"
 #include "mx27.h"
 
-static void __init imx27_dt_init(void)
-{
-	struct platform_device_info devinfo = { .name = "cpufreq-dt", };
-
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-
-	platform_device_register_full(&devinfo);
-}
-
 static const char * const imx27_dt_board_compat[] __initconst = {
 	"fsl,imx27",
 	NULL
@@ -36,6 +27,5 @@ DT_MACHINE_START(IMX27_DT, "Freescale i.
 	.map_io		= mx27_map_io,
 	.init_early	= imx27_init_early,
 	.init_irq	= mx27_init_irq,
-	.init_machine	= imx27_dt_init,
 	.dt_compat	= imx27_dt_board_compat,
 MACHINE_END
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-imx/Kconfig linux-libre-4.7-gnu/arch/arm/mach-imx/Kconfig
--- linux-libre-4.6-gnu/arch/arm/mach-imx/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-imx/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -526,7 +526,7 @@ config SOC_IMX6Q
 	bool "i.MX6 Quad/DualLite support"
 	select ARM_ERRATA_764369 if SMP
 	select HAVE_ARM_SCU if SMP
-	select HAVE_ARM_TWD if SMP
+	select HAVE_ARM_TWD
 	select PCI_DOMAINS if PCI
 	select PINCTRL_IMX6Q
 	select SOC_IMX6
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-imx/mach-imx51.c linux-libre-4.7-gnu/arch/arm/mach-imx/mach-imx51.c
--- linux-libre-4.6-gnu/arch/arm/mach-imx/mach-imx51.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-imx/mach-imx51.c	2016-07-24 15:23:50.000000000 -0400
@@ -50,13 +50,10 @@ static void __init imx51_ipu_mipi_setup(
 
 static void __init imx51_dt_init(void)
 {
-	struct platform_device_info devinfo = { .name = "cpufreq-dt", };
-
 	imx51_ipu_mipi_setup();
 	imx_src_init();
 
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-	platform_device_register_full(&devinfo);
 }
 
 static void __init imx51_init_late(void)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-imx/mach-imx53.c linux-libre-4.7-gnu/arch/arm/mach-imx/mach-imx53.c
--- linux-libre-4.6-gnu/arch/arm/mach-imx/mach-imx53.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-imx/mach-imx53.c	2016-07-24 15:23:50.000000000 -0400
@@ -40,8 +40,6 @@ static void __init imx53_dt_init(void)
 static void __init imx53_init_late(void)
 {
 	imx53_pm_init();
-
-	platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
 }
 
 static const char * const imx53_dt_board_compat[] __initconst = {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-imx/mach-imx6ul.c linux-libre-4.7-gnu/arch/arm/mach-imx/mach-imx6ul.c
--- linux-libre-4.6-gnu/arch/arm/mach-imx/mach-imx6ul.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-imx/mach-imx6ul.c	2016-07-24 15:23:50.000000000 -0400
@@ -46,7 +46,7 @@ static int ksz8081_phy_fixup(struct phy_
 static void __init imx6ul_enet_phy_init(void)
 {
 	if (IS_BUILTIN(CONFIG_PHYLIB))
-		phy_register_fixup_for_uid(PHY_ID_KSZ8081, 0xffffffff,
+		phy_register_fixup_for_uid(PHY_ID_KSZ8081, MICREL_PHY_ID_MASK,
 					   ksz8081_phy_fixup);
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-imx/mach-imx7d.c linux-libre-4.7-gnu/arch/arm/mach-imx/mach-imx7d.c
--- linux-libre-4.6-gnu/arch/arm/mach-imx/mach-imx7d.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-imx/mach-imx7d.c	2016-07-24 15:23:50.000000000 -0400
@@ -105,11 +105,6 @@ static void __init imx7d_init_irq(void)
 	irqchip_init();
 }
 
-static void __init imx7d_init_late(void)
-{
-	platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
-}
-
 static const char *const imx7d_dt_compat[] __initconst = {
 	"fsl,imx7d",
 	NULL,
@@ -117,7 +112,6 @@ static const char *const imx7d_dt_compat
 
 DT_MACHINE_START(IMX7D, "Freescale i.MX7 Dual (Device Tree)")
 	.init_irq	= imx7d_init_irq,
-	.init_late	= imx7d_init_late,
 	.init_machine	= imx7d_init_machine,
 	.dt_compat	= imx7d_dt_compat,
 MACHINE_END
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-integrator/integrator_ap.c linux-libre-4.7-gnu/arch/arm/mach-integrator/integrator_ap.c
--- linux-libre-4.6-gnu/arch/arm/mach-integrator/integrator_ap.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-integrator/integrator_ap.c	2016-07-24 15:23:50.000000000 -0400
@@ -29,7 +29,6 @@
 #include <linux/amba/kmi.h>
 #include <linux/io.h>
 #include <linux/irqchip.h>
-#include <linux/mtd/physmap.h>
 #include <linux/platform_data/clk-integrator.h>
 #include <linux/of_irq.h>
 #include <linux/of_address.h>
@@ -147,65 +146,6 @@ static int __init irq_syscore_init(void)
 device_initcall(irq_syscore_init);
 
 /*
- * Flash handling.
- */
-static int ap_flash_init(struct platform_device *dev)
-{
-	u32 tmp;
-
-	writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP,
-	       ap_syscon_base + INTEGRATOR_SC_CTRLC_OFFSET);
-
-	tmp = readl(ebi_base + INTEGRATOR_EBI_CSR1_OFFSET) |
-		INTEGRATOR_EBI_WRITE_ENABLE;
-	writel(tmp, ebi_base + INTEGRATOR_EBI_CSR1_OFFSET);
-
-	if (!(readl(ebi_base + INTEGRATOR_EBI_CSR1_OFFSET)
-	      & INTEGRATOR_EBI_WRITE_ENABLE)) {
-		writel(0xa05f, ebi_base + INTEGRATOR_EBI_LOCK_OFFSET);
-		writel(tmp, ebi_base + INTEGRATOR_EBI_CSR1_OFFSET);
-		writel(0, ebi_base + INTEGRATOR_EBI_LOCK_OFFSET);
-	}
-	return 0;
-}
-
-static void ap_flash_exit(struct platform_device *dev)
-{
-	u32 tmp;
-
-	writel(INTEGRATOR_SC_CTRL_nFLVPPEN | INTEGRATOR_SC_CTRL_nFLWP,
-	       ap_syscon_base + INTEGRATOR_SC_CTRLC_OFFSET);
-
-	tmp = readl(ebi_base + INTEGRATOR_EBI_CSR1_OFFSET) &
-		~INTEGRATOR_EBI_WRITE_ENABLE;
-	writel(tmp, ebi_base + INTEGRATOR_EBI_CSR1_OFFSET);
-
-	if (readl(ebi_base + INTEGRATOR_EBI_CSR1_OFFSET) &
-	    INTEGRATOR_EBI_WRITE_ENABLE) {
-		writel(0xa05f, ebi_base + INTEGRATOR_EBI_LOCK_OFFSET);
-		writel(tmp, ebi_base + INTEGRATOR_EBI_CSR1_OFFSET);
-		writel(0, ebi_base + INTEGRATOR_EBI_LOCK_OFFSET);
-	}
-}
-
-static void ap_flash_set_vpp(struct platform_device *pdev, int on)
-{
-	if (on)
-		writel(INTEGRATOR_SC_CTRL_nFLVPPEN,
-		       ap_syscon_base + INTEGRATOR_SC_CTRLS_OFFSET);
-	else
-		writel(INTEGRATOR_SC_CTRL_nFLVPPEN,
-		       ap_syscon_base + INTEGRATOR_SC_CTRLC_OFFSET);
-}
-
-static struct physmap_flash_data ap_flash_data = {
-	.width		= 4,
-	.init		= ap_flash_init,
-	.exit		= ap_flash_exit,
-	.set_vpp	= ap_flash_set_vpp,
-};
-
-/*
  * For the PL010 found in the Integrator/AP some of the UART control is
  * implemented in the system controller and accessed using a callback
  * from the driver.
@@ -266,8 +206,6 @@ static struct of_dev_auxdata ap_auxdata_
 		"kmi0", NULL),
 	OF_DEV_AUXDATA("arm,primecell", KMI1_BASE,
 		"kmi1", NULL),
-	OF_DEV_AUXDATA("cfi-flash", INTEGRATOR_FLASH_BASE,
-		"physmap-flash", &ap_flash_data),
 	{ /* sentinel */ },
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-integrator/integrator_cp.c linux-libre-4.7-gnu/arch/arm/mach-integrator/integrator_cp.c
--- linux-libre-4.6-gnu/arch/arm/mach-integrator/integrator_cp.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-integrator/integrator_cp.c	2016-07-24 15:23:50.000000000 -0400
@@ -23,7 +23,6 @@
 #include <linux/io.h>
 #include <linux/irqchip.h>
 #include <linux/gfp.h>
-#include <linux/mtd/physmap.h>
 #include <linux/of_irq.h>
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
@@ -43,14 +42,8 @@
 /* Base address to the CP controller */
 static void __iomem *intcp_con_base;
 
-#define INTCP_PA_FLASH_BASE		0x24000000
-
 #define INTCP_PA_CLCD_BASE		0xc0000000
 
-#define INTCP_FLASHPROG			0x04
-#define CINTEGRATOR_FLASHPROG_FLVPPEN	(1 << 0)
-#define CINTEGRATOR_FLASHPROG_FLWREN	(1 << 1)
-
 /*
  * Logical      Physical
  * f1000000	10000000	Core module registers
@@ -108,48 +101,6 @@ static void __init intcp_map_io(void)
 }
 
 /*
- * Flash handling.
- */
-static int intcp_flash_init(struct platform_device *dev)
-{
-	u32 val;
-
-	val = readl(intcp_con_base + INTCP_FLASHPROG);
-	val |= CINTEGRATOR_FLASHPROG_FLWREN;
-	writel(val, intcp_con_base + INTCP_FLASHPROG);
-
-	return 0;
-}
-
-static void intcp_flash_exit(struct platform_device *dev)
-{
-	u32 val;
-
-	val = readl(intcp_con_base + INTCP_FLASHPROG);
-	val &= ~(CINTEGRATOR_FLASHPROG_FLVPPEN|CINTEGRATOR_FLASHPROG_FLWREN);
-	writel(val, intcp_con_base + INTCP_FLASHPROG);
-}
-
-static void intcp_flash_set_vpp(struct platform_device *pdev, int on)
-{
-	u32 val;
-
-	val = readl(intcp_con_base + INTCP_FLASHPROG);
-	if (on)
-		val |= CINTEGRATOR_FLASHPROG_FLVPPEN;
-	else
-		val &= ~CINTEGRATOR_FLASHPROG_FLVPPEN;
-	writel(val, intcp_con_base + INTCP_FLASHPROG);
-}
-
-static struct physmap_flash_data intcp_flash_data = {
-	.width		= 4,
-	.init		= intcp_flash_init,
-	.exit		= intcp_flash_exit,
-	.set_vpp	= intcp_flash_set_vpp,
-};
-
-/*
  * It seems that the card insertion interrupt remains active after
  * we've acknowledged it.  We therefore ignore the interrupt, and
  * rely on reading it from the SIC.  This also means that we must
@@ -260,8 +211,6 @@ static struct of_dev_auxdata intcp_auxda
 		"aaci", &mmc_data),
 	OF_DEV_AUXDATA("arm,primecell", INTCP_PA_CLCD_BASE,
 		"clcd", &clcd_data),
-	OF_DEV_AUXDATA("cfi-flash", INTCP_PA_FLASH_BASE,
-		"physmap-flash", &intcp_flash_data),
 	{ /* sentinel */ },
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-keystone/keystone.c linux-libre-4.7-gnu/arch/arm/mach-keystone/keystone.c
--- linux-libre-4.6-gnu/arch/arm/mach-keystone/keystone.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-keystone/keystone.c	2016-07-24 15:23:50.000000000 -0400
@@ -63,11 +63,6 @@ static void __init keystone_init(void)
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
-static unsigned long keystone_virt_to_idmap(unsigned long x)
-{
-	return (phys_addr_t)(x) - CONFIG_PAGE_OFFSET + KEYSTONE_LOW_PHYS_START;
-}
-
 static long long __init keystone_pv_fixup(void)
 {
 	long long offset;
@@ -91,7 +86,7 @@ static long long __init keystone_pv_fixu
 	offset = KEYSTONE_HIGH_PHYS_START - KEYSTONE_LOW_PHYS_START;
 
 	/* Populate the arch idmap hook */
-	arch_virt_to_idmap = keystone_virt_to_idmap;
+	arch_phys_to_idmap_offset = -offset;
 
 	return offset;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-lpc32xx/common.c linux-libre-4.7-gnu/arch/arm/mach-lpc32xx/common.c
--- linux-libre-4.6-gnu/arch/arm/mach-lpc32xx/common.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-lpc32xx/common.c	2016-07-24 15:23:50.000000000 -0400
@@ -17,13 +17,6 @@
  */
 
 #include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/err.h>
-#include <linux/i2c.h>
-#include <linux/i2c-pnx.h>
-#include <linux/io.h>
 
 #include <asm/mach/map.h>
 #include <asm/system_info.h>
@@ -44,19 +37,6 @@ void lpc32xx_get_uid(u32 devid[4])
 }
 
 /*
- * Returns SYSCLK source
- * 0 = PLL397, 1 = main oscillator
- */
-int clk_is_sysclk_mainosc(void)
-{
-	if ((__raw_readl(LPC32XX_CLKPWR_SYSCLK_CTRL) &
-		LPC32XX_CLKPWR_SYSCTRL_SYSCLKMUX) == 0)
-		return 1;
-
-	return 0;
-}
-
-/*
  * Detects and returns IRAM size for the device variation
  */
 #define LPC32XX_IRAM_BANK_SIZE SZ_128K
@@ -87,81 +67,6 @@ u32 lpc32xx_return_iram_size(void)
 }
 EXPORT_SYMBOL_GPL(lpc32xx_return_iram_size);
 
-/*
- * Computes PLL rate from PLL register and input clock
- */
-u32 clk_check_pll_setup(u32 ifreq, struct clk_pll_setup *pllsetup)
-{
-	u32 ilfreq, p, m, n, fcco, fref, cfreq;
-	int mode;
-
-	/*
-	 * PLL requirements
-	 * ifreq must be >= 1MHz and <= 20MHz
-	 * FCCO must be >= 156MHz and <= 320MHz
-	 * FREF must be >= 1MHz and <= 27MHz
-	 * Assume the passed input data is not valid
-	 */
-
-	ilfreq = ifreq;
-	m = pllsetup->pll_m;
-	n = pllsetup->pll_n;
-	p = pllsetup->pll_p;
-
-	mode = (pllsetup->cco_bypass_b15 << 2) |
-		(pllsetup->direct_output_b14 << 1) |
-	pllsetup->fdbk_div_ctrl_b13;
-
-	switch (mode) {
-	case 0x0: /* Non-integer mode */
-		cfreq = (m * ilfreq) / (2 * p * n);
-		fcco = (m * ilfreq) / n;
-		fref = ilfreq / n;
-		break;
-
-	case 0x1: /* integer mode */
-		cfreq = (m * ilfreq) / n;
-		fcco = (m * ilfreq) / (n * 2 * p);
-		fref = ilfreq / n;
-		break;
-
-	case 0x2:
-	case 0x3: /* Direct mode */
-		cfreq = (m * ilfreq) / n;
-		fcco = cfreq;
-		fref = ilfreq / n;
-		break;
-
-	case 0x4:
-	case 0x5: /* Bypass mode */
-		cfreq = ilfreq / (2 * p);
-		fcco = 156000000;
-		fref = 1000000;
-		break;
-
-	case 0x6:
-	case 0x7: /* Direct bypass mode */
-	default:
-		cfreq = ilfreq;
-		fcco = 156000000;
-		fref = 1000000;
-		break;
-	}
-
-	if (fcco < 156000000 || fcco > 320000000)
-		cfreq = 0;
-
-	if (fref < 1000000 || fref > 27000000)
-		cfreq = 0;
-
-	return (u32) cfreq;
-}
-
-u32 clk_get_pclk_div(void)
-{
-	return 1 + ((__raw_readl(LPC32XX_CLKPWR_HCLK_DIV) >> 2) & 0x1F);
-}
-
 static struct map_desc lpc32xx_io_desc[] __initdata = {
 	{
 		.virtual	= (unsigned long)IO_ADDRESS(LPC32XX_AHB0_START),
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-lpc32xx/common.h linux-libre-4.7-gnu/arch/arm/mach-lpc32xx/common.h
--- linux-libre-4.6-gnu/arch/arm/mach-lpc32xx/common.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-lpc32xx/common.h	2016-07-24 15:23:50.000000000 -0400
@@ -19,37 +19,15 @@
 #ifndef __LPC32XX_COMMON_H
 #define __LPC32XX_COMMON_H
 
-#include <mach/board.h>
-#include <linux/platform_device.h>
-#include <linux/reboot.h>
+#include <linux/init.h>
 
 /*
  * Other arch specific structures and functions
  */
-extern void lpc32xx_timer_init(void);
 extern void __init lpc32xx_init_irq(void);
 extern void __init lpc32xx_map_io(void);
 extern void __init lpc32xx_serial_init(void);
 
-
-/*
- * Structure used for setting up and querying the PLLS
- */
-struct clk_pll_setup {
-	int analog_on;
-	int cco_bypass_b15;
-	int direct_output_b14;
-	int fdbk_div_ctrl_b13;
-	int pll_p;
-	int pll_n;
-	u32 pll_m;
-};
-
-extern int clk_is_sysclk_mainosc(void);
-extern u32 clk_check_pll_setup(u32 ifreq, struct clk_pll_setup *pllsetup);
-extern u32 clk_get_pllrate_from_reg(u32 inputclk, u32 regval);
-extern u32 clk_get_pclk_div(void);
-
 /*
  * Returns the LPC32xx unique 128-bit chip ID
  */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-lpc32xx/include/mach/irqs.h linux-libre-4.7-gnu/arch/arm/mach-lpc32xx/include/mach/irqs.h
--- linux-libre-4.6-gnu/arch/arm/mach-lpc32xx/include/mach/irqs.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-lpc32xx/include/mach/irqs.h	2016-07-24 15:23:50.000000000 -0400
@@ -112,6 +112,6 @@
 #define IRQ_LPC32XX_GPI_06		LPC32XX_SIC2_IRQ(28)
 #define IRQ_LPC32XX_SYSCLK		LPC32XX_SIC2_IRQ(31)
 
-#define NR_IRQS				96
+#define LPC32XX_NR_IRQS			96
 
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-lpc32xx/irq.c linux-libre-4.7-gnu/arch/arm/mach-lpc32xx/irq.c
--- linux-libre-4.6-gnu/arch/arm/mach-lpc32xx/irq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-lpc32xx/irq.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,477 +0,0 @@
-/*
- * arch/arm/mach-lpc32xx/irq.c
- *
- * Author: Kevin Wells <kevin.wells@nxp.com>
- *
- * Copyright (C) 2010 NXP Semiconductors
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/irqdomain.h>
-#include <linux/module.h>
-
-#include <mach/irqs.h>
-#include <mach/hardware.h>
-#include <mach/platform.h>
-#include "common.h"
-
-/*
- * Default value representing the Activation polarity of all internal
- * interrupt sources
- */
-#define MIC_APR_DEFAULT		0x3FF0EFE0
-#define SIC1_APR_DEFAULT	0xFBD27186
-#define SIC2_APR_DEFAULT	0x801810C0
-
-/*
- * Default value representing the Activation Type of all internal
- * interrupt sources. All are level sensitive.
- */
-#define MIC_ATR_DEFAULT		0x00000000
-#define SIC1_ATR_DEFAULT	0x00026000
-#define SIC2_ATR_DEFAULT	0x00000000
-
-static struct irq_domain *lpc32xx_mic_domain;
-static struct device_node *lpc32xx_mic_np;
-
-struct lpc32xx_event_group_regs {
-	void __iomem *enab_reg;
-	void __iomem *edge_reg;
-	void __iomem *maskstat_reg;
-	void __iomem *rawstat_reg;
-};
-
-static const struct lpc32xx_event_group_regs lpc32xx_event_int_regs = {
-	.enab_reg = LPC32XX_CLKPWR_INT_ER,
-	.edge_reg = LPC32XX_CLKPWR_INT_AP,
-	.maskstat_reg = LPC32XX_CLKPWR_INT_SR,
-	.rawstat_reg = LPC32XX_CLKPWR_INT_RS,
-};
-
-static const struct lpc32xx_event_group_regs lpc32xx_event_pin_regs = {
-	.enab_reg = LPC32XX_CLKPWR_PIN_ER,
-	.edge_reg = LPC32XX_CLKPWR_PIN_AP,
-	.maskstat_reg = LPC32XX_CLKPWR_PIN_SR,
-	.rawstat_reg = LPC32XX_CLKPWR_PIN_RS,
-};
-
-struct lpc32xx_event_info {
-	const struct lpc32xx_event_group_regs *event_group;
-	u32 mask;
-};
-
-/*
- * Maps an IRQ number to and event mask and register
- */
-static const struct lpc32xx_event_info lpc32xx_events[NR_IRQS] = {
-	[IRQ_LPC32XX_GPI_08] = {
-		.event_group = &lpc32xx_event_pin_regs,
-		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_08_BIT,
-	},
-	[IRQ_LPC32XX_GPI_09] = {
-		.event_group = &lpc32xx_event_pin_regs,
-		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_09_BIT,
-	},
-	[IRQ_LPC32XX_GPI_19] = {
-		.event_group = &lpc32xx_event_pin_regs,
-		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_19_BIT,
-	},
-	[IRQ_LPC32XX_GPI_07] = {
-		.event_group = &lpc32xx_event_pin_regs,
-		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_07_BIT,
-	},
-	[IRQ_LPC32XX_GPI_00] = {
-		.event_group = &lpc32xx_event_pin_regs,
-		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_00_BIT,
-	},
-	[IRQ_LPC32XX_GPI_01] = {
-		.event_group = &lpc32xx_event_pin_regs,
-		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_01_BIT,
-	},
-	[IRQ_LPC32XX_GPI_02] = {
-		.event_group = &lpc32xx_event_pin_regs,
-		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_02_BIT,
-	},
-	[IRQ_LPC32XX_GPI_03] = {
-		.event_group = &lpc32xx_event_pin_regs,
-		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_03_BIT,
-	},
-	[IRQ_LPC32XX_GPI_04] = {
-		.event_group = &lpc32xx_event_pin_regs,
-		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_04_BIT,
-	},
-	[IRQ_LPC32XX_GPI_05] = {
-		.event_group = &lpc32xx_event_pin_regs,
-		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_05_BIT,
-	},
-	[IRQ_LPC32XX_GPI_06] = {
-		.event_group = &lpc32xx_event_pin_regs,
-		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_06_BIT,
-	},
-	[IRQ_LPC32XX_GPI_28] = {
-		.event_group = &lpc32xx_event_pin_regs,
-		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_28_BIT,
-	},
-	[IRQ_LPC32XX_GPIO_00] = {
-		.event_group = &lpc32xx_event_int_regs,
-		.mask = LPC32XX_CLKPWR_INTSRC_GPIO_00_BIT,
-	},
-	[IRQ_LPC32XX_GPIO_01] = {
-		.event_group = &lpc32xx_event_int_regs,
-		.mask = LPC32XX_CLKPWR_INTSRC_GPIO_01_BIT,
-	},
-	[IRQ_LPC32XX_GPIO_02] = {
-		.event_group = &lpc32xx_event_int_regs,
-		.mask = LPC32XX_CLKPWR_INTSRC_GPIO_02_BIT,
-	},
-	[IRQ_LPC32XX_GPIO_03] = {
-		.event_group = &lpc32xx_event_int_regs,
-		.mask = LPC32XX_CLKPWR_INTSRC_GPIO_03_BIT,
-	},
-	[IRQ_LPC32XX_GPIO_04] = {
-		.event_group = &lpc32xx_event_int_regs,
-		.mask = LPC32XX_CLKPWR_INTSRC_GPIO_04_BIT,
-	},
-	[IRQ_LPC32XX_GPIO_05] = {
-		.event_group = &lpc32xx_event_int_regs,
-		.mask = LPC32XX_CLKPWR_INTSRC_GPIO_05_BIT,
-	},
-	[IRQ_LPC32XX_KEY] = {
-		.event_group = &lpc32xx_event_int_regs,
-		.mask = LPC32XX_CLKPWR_INTSRC_KEY_BIT,
-	},
-	[IRQ_LPC32XX_ETHERNET] = {
-		.event_group = &lpc32xx_event_int_regs,
-		.mask = LPC32XX_CLKPWR_INTSRC_MAC_BIT,
-	},
-	[IRQ_LPC32XX_USB_OTG_ATX] = {
-		.event_group = &lpc32xx_event_int_regs,
-		.mask = LPC32XX_CLKPWR_INTSRC_USBATXINT_BIT,
-	},
-	[IRQ_LPC32XX_USB_HOST] = {
-		.event_group = &lpc32xx_event_int_regs,
-		.mask = LPC32XX_CLKPWR_INTSRC_USB_BIT,
-	},
-	[IRQ_LPC32XX_RTC] = {
-		.event_group = &lpc32xx_event_int_regs,
-		.mask = LPC32XX_CLKPWR_INTSRC_RTC_BIT,
-	},
-	[IRQ_LPC32XX_MSTIMER] = {
-		.event_group = &lpc32xx_event_int_regs,
-		.mask = LPC32XX_CLKPWR_INTSRC_MSTIMER_BIT,
-	},
-	[IRQ_LPC32XX_TS_AUX] = {
-		.event_group = &lpc32xx_event_int_regs,
-		.mask = LPC32XX_CLKPWR_INTSRC_TS_AUX_BIT,
-	},
-	[IRQ_LPC32XX_TS_P] = {
-		.event_group = &lpc32xx_event_int_regs,
-		.mask = LPC32XX_CLKPWR_INTSRC_TS_P_BIT,
-	},
-	[IRQ_LPC32XX_TS_IRQ] = {
-		.event_group = &lpc32xx_event_int_regs,
-		.mask = LPC32XX_CLKPWR_INTSRC_ADC_BIT,
-	},
-};
-
-static void get_controller(unsigned int irq, unsigned int *base,
-	unsigned int *irqbit)
-{
-	if (irq < 32) {
-		*base = LPC32XX_MIC_BASE;
-		*irqbit = 1 << irq;
-	} else if (irq < 64) {
-		*base = LPC32XX_SIC1_BASE;
-		*irqbit = 1 << (irq - 32);
-	} else {
-		*base = LPC32XX_SIC2_BASE;
-		*irqbit = 1 << (irq - 64);
-	}
-}
-
-static void lpc32xx_mask_irq(struct irq_data *d)
-{
-	unsigned int reg, ctrl, mask;
-
-	get_controller(d->hwirq, &ctrl, &mask);
-
-	reg = __raw_readl(LPC32XX_INTC_MASK(ctrl)) & ~mask;
-	__raw_writel(reg, LPC32XX_INTC_MASK(ctrl));
-}
-
-static void lpc32xx_unmask_irq(struct irq_data *d)
-{
-	unsigned int reg, ctrl, mask;
-
-	get_controller(d->hwirq, &ctrl, &mask);
-
-	reg = __raw_readl(LPC32XX_INTC_MASK(ctrl)) | mask;
-	__raw_writel(reg, LPC32XX_INTC_MASK(ctrl));
-}
-
-static void lpc32xx_ack_irq(struct irq_data *d)
-{
-	unsigned int ctrl, mask;
-
-	get_controller(d->hwirq, &ctrl, &mask);
-
-	__raw_writel(mask, LPC32XX_INTC_RAW_STAT(ctrl));
-
-	/* Also need to clear pending wake event */
-	if (lpc32xx_events[d->hwirq].mask != 0)
-		__raw_writel(lpc32xx_events[d->hwirq].mask,
-			lpc32xx_events[d->hwirq].event_group->rawstat_reg);
-}
-
-static void __lpc32xx_set_irq_type(unsigned int irq, int use_high_level,
-	int use_edge)
-{
-	unsigned int reg, ctrl, mask;
-
-	get_controller(irq, &ctrl, &mask);
-
-	/* Activation level, high or low */
-	reg = __raw_readl(LPC32XX_INTC_POLAR(ctrl));
-	if (use_high_level)
-		reg |= mask;
-	else
-		reg &= ~mask;
-	__raw_writel(reg, LPC32XX_INTC_POLAR(ctrl));
-
-	/* Activation type, edge or level */
-	reg = __raw_readl(LPC32XX_INTC_ACT_TYPE(ctrl));
-	if (use_edge)
-		reg |= mask;
-	else
-		reg &= ~mask;
-	__raw_writel(reg, LPC32XX_INTC_ACT_TYPE(ctrl));
-
-	/* Use same polarity for the wake events */
-	if (lpc32xx_events[irq].mask != 0) {
-		reg = __raw_readl(lpc32xx_events[irq].event_group->edge_reg);
-
-		if (use_high_level)
-			reg |= lpc32xx_events[irq].mask;
-		else
-			reg &= ~lpc32xx_events[irq].mask;
-
-		__raw_writel(reg, lpc32xx_events[irq].event_group->edge_reg);
-	}
-}
-
-static int lpc32xx_set_irq_type(struct irq_data *d, unsigned int type)
-{
-	switch (type) {
-	case IRQ_TYPE_EDGE_RISING:
-		/* Rising edge sensitive */
-		__lpc32xx_set_irq_type(d->hwirq, 1, 1);
-		irq_set_handler_locked(d, handle_edge_irq);
-		break;
-
-	case IRQ_TYPE_EDGE_FALLING:
-		/* Falling edge sensitive */
-		__lpc32xx_set_irq_type(d->hwirq, 0, 1);
-		irq_set_handler_locked(d, handle_edge_irq);
-		break;
-
-	case IRQ_TYPE_LEVEL_LOW:
-		/* Low level sensitive */
-		__lpc32xx_set_irq_type(d->hwirq, 0, 0);
-		irq_set_handler_locked(d, handle_level_irq);
-		break;
-
-	case IRQ_TYPE_LEVEL_HIGH:
-		/* High level sensitive */
-		__lpc32xx_set_irq_type(d->hwirq, 1, 0);
-		irq_set_handler_locked(d, handle_level_irq);
-		break;
-
-	/* Other modes are not supported */
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int lpc32xx_irq_wake(struct irq_data *d, unsigned int state)
-{
-	unsigned long eventreg;
-
-	if (lpc32xx_events[d->hwirq].mask != 0) {
-		eventreg = __raw_readl(lpc32xx_events[d->hwirq].
-			event_group->enab_reg);
-
-		if (state)
-			eventreg |= lpc32xx_events[d->hwirq].mask;
-		else {
-			eventreg &= ~lpc32xx_events[d->hwirq].mask;
-
-			/*
-			 * When disabling the wakeup, clear the latched
-			 * event
-			 */
-			__raw_writel(lpc32xx_events[d->hwirq].mask,
-				lpc32xx_events[d->hwirq].
-				event_group->rawstat_reg);
-		}
-
-		__raw_writel(eventreg,
-			lpc32xx_events[d->hwirq].event_group->enab_reg);
-
-		return 0;
-	}
-
-	/* Clear event */
-	__raw_writel(lpc32xx_events[d->hwirq].mask,
-		lpc32xx_events[d->hwirq].event_group->rawstat_reg);
-
-	return -ENODEV;
-}
-
-static void __init lpc32xx_set_default_mappings(unsigned int apr,
-	unsigned int atr, unsigned int offset)
-{
-	unsigned int i;
-
-	/* Set activation levels for each interrupt */
-	i = 0;
-	while (i < 32) {
-		__lpc32xx_set_irq_type(offset + i, ((apr >> i) & 0x1),
-			((atr >> i) & 0x1));
-		i++;
-	}
-}
-
-static struct irq_chip lpc32xx_irq_chip = {
-	.name = "MIC",
-	.irq_ack = lpc32xx_ack_irq,
-	.irq_mask = lpc32xx_mask_irq,
-	.irq_unmask = lpc32xx_unmask_irq,
-	.irq_set_type = lpc32xx_set_irq_type,
-	.irq_set_wake = lpc32xx_irq_wake
-};
-
-static void lpc32xx_sic1_handler(struct irq_desc *desc)
-{
-	unsigned long ints = __raw_readl(LPC32XX_INTC_STAT(LPC32XX_SIC1_BASE));
-
-	while (ints != 0) {
-		int irqno = fls(ints) - 1;
-
-		ints &= ~(1 << irqno);
-
-		generic_handle_irq(LPC32XX_SIC1_IRQ(irqno));
-	}
-}
-
-static void lpc32xx_sic2_handler(struct irq_desc *desc)
-{
-	unsigned long ints = __raw_readl(LPC32XX_INTC_STAT(LPC32XX_SIC2_BASE));
-
-	while (ints != 0) {
-		int irqno = fls(ints) - 1;
-
-		ints &= ~(1 << irqno);
-
-		generic_handle_irq(LPC32XX_SIC2_IRQ(irqno));
-	}
-}
-
-static int __init __lpc32xx_mic_of_init(struct device_node *node,
-					struct device_node *parent)
-{
-	lpc32xx_mic_np = node;
-
-	return 0;
-}
-
-static const struct of_device_id mic_of_match[] __initconst = {
-	{ .compatible = "nxp,lpc3220-mic", .data = __lpc32xx_mic_of_init },
-	{ }
-};
-
-void __init lpc32xx_init_irq(void)
-{
-	unsigned int i;
-
-	/* Setup MIC */
-	__raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_MIC_BASE));
-	__raw_writel(MIC_APR_DEFAULT, LPC32XX_INTC_POLAR(LPC32XX_MIC_BASE));
-	__raw_writel(MIC_ATR_DEFAULT, LPC32XX_INTC_ACT_TYPE(LPC32XX_MIC_BASE));
-
-	/* Setup SIC1 */
-	__raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_SIC1_BASE));
-	__raw_writel(SIC1_APR_DEFAULT, LPC32XX_INTC_POLAR(LPC32XX_SIC1_BASE));
-	__raw_writel(SIC1_ATR_DEFAULT,
-				LPC32XX_INTC_ACT_TYPE(LPC32XX_SIC1_BASE));
-
-	/* Setup SIC2 */
-	__raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_SIC2_BASE));
-	__raw_writel(SIC2_APR_DEFAULT, LPC32XX_INTC_POLAR(LPC32XX_SIC2_BASE));
-	__raw_writel(SIC2_ATR_DEFAULT,
-				LPC32XX_INTC_ACT_TYPE(LPC32XX_SIC2_BASE));
-
-	/* Configure supported IRQ's */
-	for (i = 0; i < NR_IRQS; i++) {
-		irq_set_chip_and_handler(i, &lpc32xx_irq_chip,
-					 handle_level_irq);
-		irq_clear_status_flags(i, IRQ_NOREQUEST);
-	}
-
-	/* Set default mappings */
-	lpc32xx_set_default_mappings(MIC_APR_DEFAULT, MIC_ATR_DEFAULT, 0);
-	lpc32xx_set_default_mappings(SIC1_APR_DEFAULT, SIC1_ATR_DEFAULT, 32);
-	lpc32xx_set_default_mappings(SIC2_APR_DEFAULT, SIC2_ATR_DEFAULT, 64);
-
-	/* Initially disable all wake events */
-	__raw_writel(0, LPC32XX_CLKPWR_P01_ER);
-	__raw_writel(0, LPC32XX_CLKPWR_INT_ER);
-	__raw_writel(0, LPC32XX_CLKPWR_PIN_ER);
-
-	/*
-	 * Default wake activation polarities, all pin sources are low edge
-	 * triggered
-	 */
-	__raw_writel(LPC32XX_CLKPWR_INTSRC_TS_P_BIT |
-		LPC32XX_CLKPWR_INTSRC_MSTIMER_BIT |
-		LPC32XX_CLKPWR_INTSRC_RTC_BIT,
-		LPC32XX_CLKPWR_INT_AP);
-	__raw_writel(0, LPC32XX_CLKPWR_PIN_AP);
-
-	/* Clear latched wake event states */
-	__raw_writel(__raw_readl(LPC32XX_CLKPWR_PIN_RS),
-		LPC32XX_CLKPWR_PIN_RS);
-	__raw_writel(__raw_readl(LPC32XX_CLKPWR_INT_RS),
-		LPC32XX_CLKPWR_INT_RS);
-
-	of_irq_init(mic_of_match);
-
-	lpc32xx_mic_domain = irq_domain_add_legacy(lpc32xx_mic_np, NR_IRQS,
-						   0, 0, &irq_domain_simple_ops,
-						   NULL);
-	if (!lpc32xx_mic_domain)
-		panic("Unable to add MIC irq domain\n");
-
-	/* MIC SUBIRQx interrupts will route handling to the chain handlers */
-	irq_set_chained_handler(IRQ_LPC32XX_SUB1IRQ, lpc32xx_sic1_handler);
-	irq_set_chained_handler(IRQ_LPC32XX_SUB2IRQ, lpc32xx_sic2_handler);
-}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-lpc32xx/Makefile linux-libre-4.7-gnu/arch/arm/mach-lpc32xx/Makefile
--- linux-libre-4.6-gnu/arch/arm/mach-lpc32xx/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-lpc32xx/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -2,6 +2,6 @@
 # Makefile for the linux kernel.
 #
 
-obj-y	:= irq.o common.o serial.o
+obj-y	:= common.o serial.o
 obj-y	+= pm.o suspend.o
 obj-y	+= phy3250.o
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-lpc32xx/phy3250.c linux-libre-4.7-gnu/arch/arm/mach-lpc32xx/phy3250.c
--- linux-libre-4.6-gnu/arch/arm/mach-lpc32xx/phy3250.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-lpc32xx/phy3250.c	2016-07-24 15:23:50.000000000 -0400
@@ -159,7 +159,7 @@ static struct lpc32xx_mlc_platform_data
 	.dma_filter = pl08x_filter_id,
 };
 
-static const struct of_dev_auxdata const lpc32xx_auxdata_lookup[] __initconst = {
+static const struct of_dev_auxdata lpc32xx_auxdata_lookup[] __initconst = {
 	OF_DEV_AUXDATA("arm,pl022", 0x20084000, "dev:ssp0", NULL),
 	OF_DEV_AUXDATA("arm,pl022", 0x2008C000, "dev:ssp1", NULL),
 	OF_DEV_AUXDATA("arm,pl110", 0x31040000, "dev:clcd", &lpc32xx_clcd_data),
@@ -206,7 +206,6 @@ static const char *const lpc32xx_dt_comp
 DT_MACHINE_START(LPC32XX_DT, "LPC32XX SoC (Flattened Device Tree)")
 	.atag_offset	= 0x100,
 	.map_io		= lpc32xx_map_io,
-	.init_irq	= lpc32xx_init_irq,
 	.init_machine	= lpc3250_machine_init,
 	.dt_compat	= lpc32xx_dt_compat,
 MACHINE_END
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-mediatek/Kconfig linux-libre-4.7-gnu/arch/arm/mach-mediatek/Kconfig
--- linux-libre-4.6-gnu/arch/arm/mach-mediatek/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-mediatek/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -10,6 +10,10 @@ menuconfig ARCH_MEDIATEK
 
 if ARCH_MEDIATEK
 
+config MACH_MT2701
+	bool "MediaTek MT2701 SoCs support"
+	default ARCH_MEDIATEK
+
 config MACH_MT6589
 	bool "MediaTek MT6589 SoCs support"
 	default ARCH_MEDIATEK
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-mediatek/mediatek.c linux-libre-4.7-gnu/arch/arm/mach-mediatek/mediatek.c
--- linux-libre-4.6-gnu/arch/arm/mach-mediatek/mediatek.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-mediatek/mediatek.c	2016-07-24 15:23:50.000000000 -0400
@@ -29,6 +29,7 @@ static void __init mediatek_timer_init(v
 	void __iomem *gpt_base;
 
 	if (of_machine_is_compatible("mediatek,mt6589") ||
+	    of_machine_is_compatible("mediatek,mt7623") ||
 	    of_machine_is_compatible("mediatek,mt8135") ||
 	    of_machine_is_compatible("mediatek,mt8127")) {
 		/* turn on GPT6 which ungates arch timer clocks */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-mv78xx0/common.c linux-libre-4.7-gnu/arch/arm/mach-mv78xx0/common.c
--- linux-libre-4.6-gnu/arch/arm/mach-mv78xx0/common.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-mv78xx0/common.c	2016-07-24 15:23:50.000000000 -0400
@@ -168,8 +168,7 @@ static struct clk *tclk;
 
 static void __init clk_init(void)
 {
-	tclk = clk_register_fixed_rate(NULL, "tclk", NULL, CLK_IS_ROOT,
-				       get_tclk());
+	tclk = clk_register_fixed_rate(NULL, "tclk", NULL, 0, get_tclk());
 
 	orion_clkdev_init(tclk);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-mvebu/coherency.c linux-libre-4.7-gnu/arch/arm/mach-mvebu/coherency.c
--- linux-libre-4.6-gnu/arch/arm/mach-mvebu/coherency.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-mvebu/coherency.c	2016-07-24 15:23:50.000000000 -0400
@@ -162,22 +162,16 @@ exit:
 }
 
 /*
- * This ioremap hook is used on Armada 375/38x to ensure that PCIe
- * memory areas are mapped as MT_UNCACHED instead of MT_DEVICE. This
- * is needed as a workaround for a deadlock issue between the PCIe
- * interface and the cache controller.
+ * This ioremap hook is used on Armada 375/38x to ensure that all MMIO
+ * areas are mapped as MT_UNCACHED instead of MT_DEVICE. This is
+ * needed for the HW I/O coherency mechanism to work properly without
+ * deadlock.
  */
 static void __iomem *
-armada_pcie_wa_ioremap_caller(phys_addr_t phys_addr, size_t size,
-			      unsigned int mtype, void *caller)
+armada_wa_ioremap_caller(phys_addr_t phys_addr, size_t size,
+			 unsigned int mtype, void *caller)
 {
-	struct resource pcie_mem;
-
-	mvebu_mbus_get_pcie_mem_aperture(&pcie_mem);
-
-	if (pcie_mem.start <= phys_addr && (phys_addr + size) <= pcie_mem.end)
-		mtype = MT_UNCACHED;
-
+	mtype = MT_UNCACHED;
 	return __arm_ioremap_caller(phys_addr, size, mtype, caller);
 }
 
@@ -186,7 +180,8 @@ static void __init armada_375_380_cohere
 	struct device_node *cache_dn;
 
 	coherency_cpu_base = of_iomap(np, 0);
-	arch_ioremap_caller = armada_pcie_wa_ioremap_caller;
+	arch_ioremap_caller = armada_wa_ioremap_caller;
+	pci_ioremap_set_mem_type(MT_UNCACHED);
 
 	/*
 	 * We should switch the PL310 to I/O coherency mode only if
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-mvebu/Makefile linux-libre-4.7-gnu/arch/arm/mach-mvebu/Makefile
--- linux-libre-4.6-gnu/arch/arm/mach-mvebu/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-mvebu/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -7,9 +7,15 @@ CFLAGS_pmsu.o			:= -march=armv7-a
 obj-$(CONFIG_MACH_MVEBU_ANY)	 += system-controller.o mvebu-soc-id.o
 
 ifeq ($(CONFIG_MACH_MVEBU_V7),y)
-obj-y				 += cpu-reset.o board-v7.o coherency.o coherency_ll.o pmsu.o pmsu_ll.o pm.o pm-board.o
+obj-y				 += cpu-reset.o board-v7.o coherency.o coherency_ll.o pmsu.o pmsu_ll.o
+
+obj-$(CONFIG_PM)		 += pm.o pm-board.o
 obj-$(CONFIG_SMP)		 += platsmp.o headsmp.o platsmp-a9.o headsmp-a9.o
 endif
 
 obj-$(CONFIG_MACH_DOVE)		 += dove.o
-obj-$(CONFIG_MACH_KIRKWOOD)	 += kirkwood.o kirkwood-pm.o
+
+ifeq ($(CONFIG_MACH_KIRKWOOD),y)
+obj-y				 += kirkwood.o
+obj-$(CONFIG_PM)		 += kirkwood-pm.o
+endif
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-mvebu/pmsu.c linux-libre-4.7-gnu/arch/arm/mach-mvebu/pmsu.c
--- linux-libre-4.6-gnu/arch/arm/mach-mvebu/pmsu.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-mvebu/pmsu.c	2016-07-24 15:23:50.000000000 -0400
@@ -20,7 +20,6 @@
 
 #include <linux/clk.h>
 #include <linux/cpu_pm.h>
-#include <linux/cpufreq-dt.h>
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/io.h>
@@ -29,7 +28,6 @@
 #include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
-#include <linux/pm_opp.h>
 #include <linux/resource.h>
 #include <linux/slab.h>
 #include <linux/smp.h>
@@ -608,86 +606,3 @@ int mvebu_pmsu_dfs_request(int cpu)
 
 	return 0;
 }
-
-struct cpufreq_dt_platform_data cpufreq_dt_pd = {
-	.independent_clocks = true,
-};
-
-static int __init armada_xp_pmsu_cpufreq_init(void)
-{
-	struct device_node *np;
-	struct resource res;
-	int ret, cpu;
-
-	if (!of_machine_is_compatible("marvell,armadaxp"))
-		return 0;
-
-	/*
-	 * In order to have proper cpufreq handling, we need to ensure
-	 * that the Device Tree description of the CPU clock includes
-	 * the definition of the PMU DFS registers. If not, we do not
-	 * register the clock notifier and the cpufreq driver. This
-	 * piece of code is only for compatibility with old Device
-	 * Trees.
-	 */
-	np = of_find_compatible_node(NULL, NULL, "marvell,armada-xp-cpu-clock");
-	if (!np)
-		return 0;
-
-	ret = of_address_to_resource(np, 1, &res);
-	if (ret) {
-		pr_warn(FW_WARN "not enabling cpufreq, deprecated armada-xp-cpu-clock binding\n");
-		of_node_put(np);
-		return 0;
-	}
-
-	of_node_put(np);
-
-	/*
-	 * For each CPU, this loop registers the operating points
-	 * supported (which are the nominal CPU frequency and half of
-	 * it), and registers the clock notifier that will take care
-	 * of doing the PMSU part of a frequency transition.
-	 */
-	for_each_possible_cpu(cpu) {
-		struct device *cpu_dev;
-		struct clk *clk;
-		int ret;
-
-		cpu_dev = get_cpu_device(cpu);
-		if (!cpu_dev) {
-			pr_err("Cannot get CPU %d\n", cpu);
-			continue;
-		}
-
-		clk = clk_get(cpu_dev, 0);
-		if (IS_ERR(clk)) {
-			pr_err("Cannot get clock for CPU %d\n", cpu);
-			return PTR_ERR(clk);
-		}
-
-		/*
-		 * In case of a failure of dev_pm_opp_add(), we don't
-		 * bother with cleaning up the registered OPP (there's
-		 * no function to do so), and simply cancel the
-		 * registration of the cpufreq device.
-		 */
-		ret = dev_pm_opp_add(cpu_dev, clk_get_rate(clk), 0);
-		if (ret) {
-			clk_put(clk);
-			return ret;
-		}
-
-		ret = dev_pm_opp_add(cpu_dev, clk_get_rate(clk) / 2, 0);
-		if (ret) {
-			clk_put(clk);
-			return ret;
-		}
-	}
-
-	platform_device_register_data(NULL, "cpufreq-dt", -1,
-				      &cpufreq_dt_pd, sizeof(cpufreq_dt_pd));
-	return 0;
-}
-
-device_initcall(armada_xp_pmsu_cpufreq_init);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-omap1/ams-delta-fiq.c linux-libre-4.7-gnu/arch/arm/mach-omap1/ams-delta-fiq.c
--- linux-libre-4.6-gnu/arch/arm/mach-omap1/ams-delta-fiq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-omap1/ams-delta-fiq.c	2016-07-24 15:23:50.000000000 -0400
@@ -109,7 +109,8 @@ void __init ams_delta_init_fiq(void)
 	 * Since no set_type() method is provided by OMAP irq chip,
 	 * switch to edge triggered interrupt type manually.
 	 */
-	offset = IRQ_ILR0_REG_OFFSET + INT_DEFERRED_FIQ * 0x4;
+	offset = IRQ_ILR0_REG_OFFSET +
+			((INT_DEFERRED_FIQ - NR_IRQS_LEGACY) & 0x1f) * 0x4;
 	val = omap_readl(DEFERRED_FIQ_IH_BASE + offset) & ~(1 << 1);
 	omap_writel(val, DEFERRED_FIQ_IH_BASE + offset);
 
@@ -149,7 +150,7 @@ void __init ams_delta_init_fiq(void)
 	/*
 	 * Redirect GPIO interrupts to FIQ
 	 */
-	offset = IRQ_ILR0_REG_OFFSET + INT_GPIO_BANK1 * 0x4;
+	offset = IRQ_ILR0_REG_OFFSET + (INT_GPIO_BANK1 - NR_IRQS_LEGACY) * 0x4;
 	val = omap_readl(OMAP_IH1_BASE + offset) | 1;
 	omap_writel(val, OMAP_IH1_BASE + offset);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-omap1/ams-delta-fiq-handler.S linux-libre-4.7-gnu/arch/arm/mach-omap1/ams-delta-fiq-handler.S
--- linux-libre-4.6-gnu/arch/arm/mach-omap1/ams-delta-fiq-handler.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-omap1/ams-delta-fiq-handler.S	2016-07-24 15:23:50.000000000 -0400
@@ -43,8 +43,8 @@
 #define OTHERS_MASK			(MODEM_IRQ_MASK | HOOK_SWITCH_MASK)
 
 /* IRQ handler register bitmasks */
-#define DEFERRED_FIQ_MASK		(0x1 << (INT_DEFERRED_FIQ % IH2_BASE))
-#define GPIO_BANK1_MASK  		(0x1 << INT_GPIO_BANK1)
+#define DEFERRED_FIQ_MASK		OMAP_IRQ_BIT(INT_DEFERRED_FIQ)
+#define GPIO_BANK1_MASK  		OMAP_IRQ_BIT(INT_GPIO_BANK1)
 
 /* Driver buffer byte offsets */
 #define BUF_MASK			(FIQ_MASK * 4)
@@ -110,7 +110,7 @@ ENTRY(qwerty_fiqin_start)
 	mov r8, #2				@ reset FIQ agreement
 	str r8, [r12, #IRQ_CONTROL_REG_OFFSET]
 
-	cmp r10, #INT_GPIO_BANK1		@ is it GPIO bank interrupt?
+	cmp r10, #(INT_GPIO_BANK1 - NR_IRQS_LEGACY)	@ is it GPIO interrupt?
 	beq gpio				@ yes - process it
 
 	mov r8, #1
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-omap1/include/mach/ams-delta-fiq.h linux-libre-4.7-gnu/arch/arm/mach-omap1/include/mach/ams-delta-fiq.h
--- linux-libre-4.6-gnu/arch/arm/mach-omap1/include/mach/ams-delta-fiq.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-omap1/include/mach/ams-delta-fiq.h	2016-07-24 15:23:50.000000000 -0400
@@ -14,6 +14,8 @@
 #ifndef __AMS_DELTA_FIQ_H
 #define __AMS_DELTA_FIQ_H
 
+#include <mach/irqs.h>
+
 /*
  * Interrupt number used for passing control from FIQ to IRQ.
  * IRQ12, described as reserved, has been selected.
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-omap2/board-rx51-peripherals.c linux-libre-4.7-gnu/arch/arm/mach-omap2/board-rx51-peripherals.c
--- linux-libre-4.6-gnu/arch/arm/mach-omap2/board-rx51-peripherals.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-omap2/board-rx51-peripherals.c	2016-07-24 15:23:50.000000000 -0400
@@ -30,6 +30,8 @@
 #include <linux/platform_data/spi-omap2-mcspi.h>
 #include <linux/platform_data/mtd-onenand-omap2.h>
 
+#include <plat/dmtimer.h>
+
 #include <asm/system_info.h>
 
 #include "common.h"
@@ -47,9 +49,8 @@
 
 #include <video/omap-panel-data.h>
 
-#if defined(CONFIG_IR_RX51) || defined(CONFIG_IR_RX51_MODULE)
+#include <linux/platform_data/pwm_omap_dmtimer.h>
 #include <linux/platform_data/media/ir-rx51.h>
-#endif
 
 #include "mux.h"
 #include "omap-pm.h"
@@ -1212,10 +1213,40 @@ static void __init rx51_init_tsc2005(voi
 				gpio_to_irq(RX51_TSC2005_IRQ_GPIO);
 }
 
+#if IS_ENABLED(CONFIG_OMAP_DM_TIMER)
+static struct pwm_omap_dmtimer_pdata __maybe_unused pwm_dmtimer_pdata = {
+	.request_by_node = omap_dm_timer_request_by_node,
+	.request_specific = omap_dm_timer_request_specific,
+	.request = omap_dm_timer_request,
+	.set_source = omap_dm_timer_set_source,
+	.get_irq = omap_dm_timer_get_irq,
+	.set_int_enable = omap_dm_timer_set_int_enable,
+	.set_int_disable = omap_dm_timer_set_int_disable,
+	.free = omap_dm_timer_free,
+	.enable = omap_dm_timer_enable,
+	.disable = omap_dm_timer_disable,
+	.get_fclk = omap_dm_timer_get_fclk,
+	.start = omap_dm_timer_start,
+	.stop = omap_dm_timer_stop,
+	.set_load = omap_dm_timer_set_load,
+	.set_match = omap_dm_timer_set_match,
+	.set_pwm = omap_dm_timer_set_pwm,
+	.set_prescaler = omap_dm_timer_set_prescaler,
+	.read_counter = omap_dm_timer_read_counter,
+	.write_counter = omap_dm_timer_write_counter,
+	.read_status = omap_dm_timer_read_status,
+	.write_status = omap_dm_timer_write_status,
+};
+#endif
+
 #if defined(CONFIG_IR_RX51) || defined(CONFIG_IR_RX51_MODULE)
 static struct lirc_rx51_platform_data rx51_lirc_data = {
 	.set_max_mpu_wakeup_lat = omap_pm_set_max_mpu_wakeup_lat,
 	.pwm_timer = 9, /* Use GPT 9 for CIR */
+#if IS_ENABLED(CONFIG_OMAP_DM_TIMER)
+	.dmtimer = &pwm_dmtimer_pdata,
+#endif
+
 };
 
 static struct platform_device rx51_lirc_device = {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-omap2/gpmc-nand.c linux-libre-4.7-gnu/arch/arm/mach-omap2/gpmc-nand.c
--- linux-libre-4.6-gnu/arch/arm/mach-omap2/gpmc-nand.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-omap2/gpmc-nand.c	2016-07-24 15:23:50.000000000 -0400
@@ -97,10 +97,7 @@ int gpmc_nand_init(struct omap_nand_plat
 	gpmc_nand_res[2].start = gpmc_get_client_irq(GPMC_IRQ_COUNT_EVENT);
 
 	memset(&s, 0, sizeof(struct gpmc_settings));
-	if (gpmc_nand_data->of_node)
-		gpmc_read_settings_dt(gpmc_nand_data->of_node, &s);
-	else
-		gpmc_set_legacy(gpmc_nand_data, &s);
+	gpmc_set_legacy(gpmc_nand_data, &s);
 
 	s.device_nand = true;
 
@@ -121,8 +118,6 @@ int gpmc_nand_init(struct omap_nand_plat
 	if (err < 0)
 		goto out_free_cs;
 
-	gpmc_update_nand_reg(&gpmc_nand_data->reg, gpmc_nand_data->cs);
-
 	if (!gpmc_hwecc_bch_capable(gpmc_nand_data->ecc_opt)) {
 		pr_err("omap2-nand: Unsupported NAND ECC scheme selected\n");
 		err = -EINVAL;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-omap2/Kconfig linux-libre-4.7-gnu/arch/arm/mach-omap2/Kconfig
--- linux-libre-4.6-gnu/arch/arm/mach-omap2/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-omap2/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -17,6 +17,7 @@ config ARCH_OMAP3
 	select PM_OPP if PM
 	select PM if CPU_IDLE
 	select SOC_HAS_OMAP2_SDRC
+	select ARM_ERRATA_430973
 
 config ARCH_OMAP4
 	bool "TI OMAP4"
@@ -36,6 +37,7 @@ config ARCH_OMAP4
 	select PM if CPU_IDLE
 	select ARM_ERRATA_754322
 	select ARM_ERRATA_775420
+	select OMAP_INTERCONNECT
 
 config SOC_OMAP5
 	bool "TI OMAP5"
@@ -67,6 +69,8 @@ config SOC_AM43XX
 	select HAVE_ARM_SCU
 	select GENERIC_CLOCKEVENTS_BROADCAST
 	select HAVE_ARM_TWD
+	select ARM_ERRATA_754322
+	select ARM_ERRATA_775420
 
 config SOC_DRA7XX
 	bool "TI DRA7XX"
@@ -240,4 +244,12 @@ endmenu
 
 endif
 
+config OMAP5_ERRATA_801819
+	bool "Errata 801819: An eviction from L1 data cache might stall indefinitely"
+	depends on SOC_OMAP5 || SOC_DRA7XX
+	help
+	  A livelock can occur in the L2 cache arbitration that might prevent
+	  a snoop from completing. Under certain conditions this can cause the
+	  system to deadlock.
+
 endmenu
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-omap2/Makefile linux-libre-4.7-gnu/arch/arm/mach-omap2/Makefile
--- linux-libre-4.6-gnu/arch/arm/mach-omap2/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-omap2/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -2,7 +2,7 @@
 # Makefile for the linux kernel.
 #
 
-ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include \
+ccflags-y := -I$(srctree)/$(src)/include \
 	-I$(srctree)/arch/arm/plat-omap/include
 
 # Common support
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c linux-libre-4.7-gnu/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c
--- linux-libre-4.6-gnu/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c	2016-07-24 15:23:50.000000000 -0400
@@ -918,6 +918,8 @@ static struct omap_hwmod_class_sysconfig
 static struct omap_hwmod_class am33xx_rtc_hwmod_class = {
 	.name		= "rtc",
 	.sysc		= &am33xx_rtc_sysc,
+	.unlock		= &omap_hwmod_rtc_unlock,
+	.lock		= &omap_hwmod_rtc_lock,
 };
 
 struct omap_hwmod am33xx_rtc_hwmod = {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-omap2/omap_hwmod_7xx_data.c linux-libre-4.7-gnu/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
--- linux-libre-4.6-gnu/arch/arm/mach-omap2/omap_hwmod_7xx_data.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-omap2/omap_hwmod_7xx_data.c	2016-07-24 15:23:50.000000000 -0400
@@ -383,6 +383,68 @@ static struct omap_hwmod dra7xx_dcan2_hw
 	},
 };
 
+/* pwmss  */
+static struct omap_hwmod_class_sysconfig dra7xx_epwmss_sysc = {
+	.rev_offs	= 0x0,
+	.sysc_offs	= 0x4,
+	.sysc_flags	= SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET,
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type2,
+};
+
+/*
+ * epwmss class
+ */
+static struct omap_hwmod_class dra7xx_epwmss_hwmod_class = {
+	.name		= "epwmss",
+	.sysc		= &dra7xx_epwmss_sysc,
+};
+
+/* epwmss0 */
+static struct omap_hwmod dra7xx_epwmss0_hwmod = {
+	.name		= "epwmss0",
+	.class		= &dra7xx_epwmss_hwmod_class,
+	.clkdm_name	= "l4per2_clkdm",
+	.main_clk	= "l4_root_clk_div",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+			.clkctrl_offs	= DRA7XX_CM_L4PER2_PWMSS1_CLKCTRL_OFFSET,
+			.context_offs	= DRA7XX_RM_L4PER2_PWMSS1_CONTEXT_OFFSET,
+		},
+	},
+};
+
+/* epwmss1 */
+static struct omap_hwmod dra7xx_epwmss1_hwmod = {
+	.name		= "epwmss1",
+	.class		= &dra7xx_epwmss_hwmod_class,
+	.clkdm_name	= "l4per2_clkdm",
+	.main_clk	= "l4_root_clk_div",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+			.clkctrl_offs	= DRA7XX_CM_L4PER2_PWMSS2_CLKCTRL_OFFSET,
+			.context_offs	= DRA7XX_RM_L4PER2_PWMSS2_CONTEXT_OFFSET,
+		},
+	},
+};
+
+/* epwmss2 */
+static struct omap_hwmod dra7xx_epwmss2_hwmod = {
+	.name		= "epwmss2",
+	.class		= &dra7xx_epwmss_hwmod_class,
+	.clkdm_name	= "l4per2_clkdm",
+	.main_clk	= "l4_root_clk_div",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+			.clkctrl_offs	= DRA7XX_CM_L4PER2_PWMSS3_CLKCTRL_OFFSET,
+			.context_offs	= DRA7XX_RM_L4PER2_PWMSS3_CONTEXT_OFFSET,
+		},
+	},
+};
+
 /*
  * 'dma' class
  *
@@ -1374,6 +1436,52 @@ static struct omap_hwmod_class dra7xx_mc
 	.sysc	= &dra7xx_mcasp_sysc,
 };
 
+/* mcasp1 */
+static struct omap_hwmod_opt_clk mcasp1_opt_clks[] = {
+	{ .role = "ahclkx", .clk = "mcasp1_ahclkx_mux" },
+	{ .role = "ahclkr", .clk = "mcasp1_ahclkr_mux" },
+};
+
+static struct omap_hwmod dra7xx_mcasp1_hwmod = {
+	.name		= "mcasp1",
+	.class		= &dra7xx_mcasp_hwmod_class,
+	.clkdm_name	= "ipu_clkdm",
+	.main_clk	= "mcasp1_aux_gfclk_mux",
+	.flags		= HWMOD_OPT_CLKS_NEEDED,
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = DRA7XX_CM_IPU_MCASP1_CLKCTRL_OFFSET,
+			.context_offs = DRA7XX_RM_IPU_MCASP1_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
+		},
+	},
+	.opt_clks	= mcasp1_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(mcasp1_opt_clks),
+};
+
+/* mcasp2 */
+static struct omap_hwmod_opt_clk mcasp2_opt_clks[] = {
+	{ .role = "ahclkx", .clk = "mcasp2_ahclkx_mux" },
+	{ .role = "ahclkr", .clk = "mcasp2_ahclkr_mux" },
+};
+
+static struct omap_hwmod dra7xx_mcasp2_hwmod = {
+	.name		= "mcasp2",
+	.class		= &dra7xx_mcasp_hwmod_class,
+	.clkdm_name	= "l4per2_clkdm",
+	.main_clk	= "mcasp2_aux_gfclk_mux",
+	.flags		= HWMOD_OPT_CLKS_NEEDED,
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = DRA7XX_CM_L4PER2_MCASP2_CLKCTRL_OFFSET,
+			.context_offs = DRA7XX_RM_L4PER2_MCASP2_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
+		},
+	},
+	.opt_clks	= mcasp2_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(mcasp2_opt_clks),
+};
+
 /* mcasp3 */
 static struct omap_hwmod_opt_clk mcasp3_opt_clks[] = {
 	{ .role = "ahclkx", .clk = "mcasp3_ahclkx_mux" },
@@ -1396,6 +1504,116 @@ static struct omap_hwmod dra7xx_mcasp3_h
 	.opt_clks_cnt	= ARRAY_SIZE(mcasp3_opt_clks),
 };
 
+/* mcasp4 */
+static struct omap_hwmod_opt_clk mcasp4_opt_clks[] = {
+	{ .role = "ahclkx", .clk = "mcasp4_ahclkx_mux" },
+};
+
+static struct omap_hwmod dra7xx_mcasp4_hwmod = {
+	.name		= "mcasp4",
+	.class		= &dra7xx_mcasp_hwmod_class,
+	.clkdm_name	= "l4per2_clkdm",
+	.main_clk	= "mcasp4_aux_gfclk_mux",
+	.flags		= HWMOD_OPT_CLKS_NEEDED,
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = DRA7XX_CM_L4PER2_MCASP4_CLKCTRL_OFFSET,
+			.context_offs = DRA7XX_RM_L4PER2_MCASP4_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
+		},
+	},
+	.opt_clks	= mcasp4_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(mcasp4_opt_clks),
+};
+
+/* mcasp5 */
+static struct omap_hwmod_opt_clk mcasp5_opt_clks[] = {
+	{ .role = "ahclkx", .clk = "mcasp5_ahclkx_mux" },
+};
+
+static struct omap_hwmod dra7xx_mcasp5_hwmod = {
+	.name		= "mcasp5",
+	.class		= &dra7xx_mcasp_hwmod_class,
+	.clkdm_name	= "l4per2_clkdm",
+	.main_clk	= "mcasp5_aux_gfclk_mux",
+	.flags		= HWMOD_OPT_CLKS_NEEDED,
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = DRA7XX_CM_L4PER2_MCASP5_CLKCTRL_OFFSET,
+			.context_offs = DRA7XX_RM_L4PER2_MCASP5_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
+		},
+	},
+	.opt_clks	= mcasp5_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(mcasp5_opt_clks),
+};
+
+/* mcasp6 */
+static struct omap_hwmod_opt_clk mcasp6_opt_clks[] = {
+	{ .role = "ahclkx", .clk = "mcasp6_ahclkx_mux" },
+};
+
+static struct omap_hwmod dra7xx_mcasp6_hwmod = {
+	.name		= "mcasp6",
+	.class		= &dra7xx_mcasp_hwmod_class,
+	.clkdm_name	= "l4per2_clkdm",
+	.main_clk	= "mcasp6_aux_gfclk_mux",
+	.flags		= HWMOD_OPT_CLKS_NEEDED,
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = DRA7XX_CM_L4PER2_MCASP6_CLKCTRL_OFFSET,
+			.context_offs = DRA7XX_RM_L4PER2_MCASP6_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
+		},
+	},
+	.opt_clks	= mcasp6_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(mcasp6_opt_clks),
+};
+
+/* mcasp7 */
+static struct omap_hwmod_opt_clk mcasp7_opt_clks[] = {
+	{ .role = "ahclkx", .clk = "mcasp7_ahclkx_mux" },
+};
+
+static struct omap_hwmod dra7xx_mcasp7_hwmod = {
+	.name		= "mcasp7",
+	.class		= &dra7xx_mcasp_hwmod_class,
+	.clkdm_name	= "l4per2_clkdm",
+	.main_clk	= "mcasp7_aux_gfclk_mux",
+	.flags		= HWMOD_OPT_CLKS_NEEDED,
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = DRA7XX_CM_L4PER2_MCASP7_CLKCTRL_OFFSET,
+			.context_offs = DRA7XX_RM_L4PER2_MCASP7_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
+		},
+	},
+	.opt_clks	= mcasp7_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(mcasp7_opt_clks),
+};
+
+/* mcasp8 */
+static struct omap_hwmod_opt_clk mcasp8_opt_clks[] = {
+	{ .role = "ahclkx", .clk = "mcasp8_ahclkx_mux" },
+};
+
+static struct omap_hwmod dra7xx_mcasp8_hwmod = {
+	.name		= "mcasp8",
+	.class		= &dra7xx_mcasp_hwmod_class,
+	.clkdm_name	= "l4per2_clkdm",
+	.main_clk	= "mcasp8_aux_gfclk_mux",
+	.flags		= HWMOD_OPT_CLKS_NEEDED,
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = DRA7XX_CM_L4PER2_MCASP8_CLKCTRL_OFFSET,
+			.context_offs = DRA7XX_RM_L4PER2_MCASP8_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_SWCTRL,
+		},
+	},
+	.opt_clks	= mcasp8_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(mcasp8_opt_clks),
+};
+
 /*
  * 'mmc' class
  *
@@ -1707,6 +1925,8 @@ static struct omap_hwmod_class_sysconfig
 static struct omap_hwmod_class dra7xx_rtcss_hwmod_class = {
 	.name	= "rtcss",
 	.sysc	= &dra7xx_rtcss_sysc,
+	.unlock	= &omap_hwmod_rtc_unlock,
+	.lock	= &omap_hwmod_rtc_lock,
 };
 
 /* rtcss */
@@ -2065,6 +2285,20 @@ static struct omap_hwmod dra7xx_timer11_
 	},
 };
 
+/* timer12 */
+static struct omap_hwmod dra7xx_timer12_hwmod = {
+	.name		= "timer12",
+	.class		= &dra7xx_timer_hwmod_class,
+	.clkdm_name	= "wkupaon_clkdm",
+	.main_clk	= "secure_32k_clk_src_ck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = DRA7XX_CM_WKUPAON_TIMER12_CLKCTRL_OFFSET,
+			.context_offs = DRA7XX_RM_WKUPAON_TIMER12_CONTEXT_OFFSET,
+		},
+	},
+};
+
 /* timer13 */
 static struct omap_hwmod dra7xx_timer13_hwmod = {
 	.name		= "timer13",
@@ -2726,6 +2960,38 @@ static struct omap_hwmod_ocp_if dra7xx_l
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* l4_per2 -> mcasp1 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per2__mcasp1 = {
+	.master		= &dra7xx_l4_per2_hwmod,
+	.slave		= &dra7xx_mcasp1_hwmod,
+	.clk		= "l4_root_clk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_main_1 -> mcasp1 */
+static struct omap_hwmod_ocp_if dra7xx_l3_main_1__mcasp1 = {
+	.master		= &dra7xx_l3_main_1_hwmod,
+	.slave		= &dra7xx_mcasp1_hwmod,
+	.clk		= "l3_iclk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per2 -> mcasp2 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per2__mcasp2 = {
+	.master		= &dra7xx_l4_per2_hwmod,
+	.slave		= &dra7xx_mcasp2_hwmod,
+	.clk		= "l4_root_clk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_main_1 -> mcasp2 */
+static struct omap_hwmod_ocp_if dra7xx_l3_main_1__mcasp2 = {
+	.master		= &dra7xx_l3_main_1_hwmod,
+	.slave		= &dra7xx_mcasp2_hwmod,
+	.clk		= "l3_iclk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* l4_per2 -> mcasp3 */
 static struct omap_hwmod_ocp_if dra7xx_l4_per2__mcasp3 = {
 	.master		= &dra7xx_l4_per2_hwmod,
@@ -2742,6 +3008,46 @@ static struct omap_hwmod_ocp_if dra7xx_l
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* l4_per2 -> mcasp4 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per2__mcasp4 = {
+	.master		= &dra7xx_l4_per2_hwmod,
+	.slave		= &dra7xx_mcasp4_hwmod,
+	.clk		= "l4_root_clk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per2 -> mcasp5 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per2__mcasp5 = {
+	.master		= &dra7xx_l4_per2_hwmod,
+	.slave		= &dra7xx_mcasp5_hwmod,
+	.clk		= "l4_root_clk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per2 -> mcasp6 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per2__mcasp6 = {
+	.master		= &dra7xx_l4_per2_hwmod,
+	.slave		= &dra7xx_mcasp6_hwmod,
+	.clk		= "l4_root_clk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per2 -> mcasp7 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per2__mcasp7 = {
+	.master		= &dra7xx_l4_per2_hwmod,
+	.slave		= &dra7xx_mcasp7_hwmod,
+	.clk		= "l4_root_clk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per2 -> mcasp8 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per2__mcasp8 = {
+	.master		= &dra7xx_l4_per2_hwmod,
+	.slave		= &dra7xx_mcasp8_hwmod,
+	.clk		= "l4_root_clk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* l4_per1 -> elm */
 static struct omap_hwmod_ocp_if dra7xx_l4_per1__elm = {
 	.master		= &dra7xx_l4_per1_hwmod,
@@ -3281,6 +3587,14 @@ static struct omap_hwmod_ocp_if dra7xx_l
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* l4_wkup -> timer12 */
+static struct omap_hwmod_ocp_if dra7xx_l4_wkup__timer12 = {
+	.master		= &dra7xx_l4_wkup_hwmod,
+	.slave		= &dra7xx_timer12_hwmod,
+	.clk		= "wkupaon_iclk_mux",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* l4_per3 -> timer13 */
 static struct omap_hwmod_ocp_if dra7xx_l4_per3__timer13 = {
 	.master		= &dra7xx_l4_per3_hwmod,
@@ -3465,6 +3779,30 @@ static struct omap_hwmod_ocp_if dra7xx_l
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* l4_per2 -> epwmss0 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per2__epwmss0 = {
+	.master		= &dra7xx_l4_per2_hwmod,
+	.slave		= &dra7xx_epwmss0_hwmod,
+	.clk		= "l4_root_clk_div",
+	.user		= OCP_USER_MPU,
+};
+
+/* l4_per2 -> epwmss1 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per2__epwmss1 = {
+	.master		= &dra7xx_l4_per2_hwmod,
+	.slave		= &dra7xx_epwmss1_hwmod,
+	.clk		= "l4_root_clk_div",
+	.user		= OCP_USER_MPU,
+};
+
+/* l4_per2 -> epwmss2 */
+static struct omap_hwmod_ocp_if dra7xx_l4_per2__epwmss2 = {
+	.master		= &dra7xx_l4_per2_hwmod,
+	.slave		= &dra7xx_epwmss2_hwmod,
+	.clk		= "l4_root_clk_div",
+	.user		= OCP_USER_MPU,
+};
+
 static struct omap_hwmod_ocp_if *dra7xx_hwmod_ocp_ifs[] __initdata = {
 	&dra7xx_l3_main_1__dmm,
 	&dra7xx_l3_main_2__l3_instr,
@@ -3484,8 +3822,17 @@ static struct omap_hwmod_ocp_if *dra7xx_
 	&dra7xx_l4_wkup__dcan1,
 	&dra7xx_l4_per2__dcan2,
 	&dra7xx_l4_per2__cpgmac0,
+	&dra7xx_l4_per2__mcasp1,
+	&dra7xx_l3_main_1__mcasp1,
+	&dra7xx_l4_per2__mcasp2,
+	&dra7xx_l3_main_1__mcasp2,
 	&dra7xx_l4_per2__mcasp3,
 	&dra7xx_l3_main_1__mcasp3,
+	&dra7xx_l4_per2__mcasp4,
+	&dra7xx_l4_per2__mcasp5,
+	&dra7xx_l4_per2__mcasp6,
+	&dra7xx_l4_per2__mcasp7,
+	&dra7xx_l4_per2__mcasp8,
 	&dra7xx_gmac__mdio,
 	&dra7xx_l4_cfg__dma_system,
 	&dra7xx_l3_main_1__tpcc,
@@ -3577,9 +3924,19 @@ static struct omap_hwmod_ocp_if *dra7xx_
 	&dra7xx_l3_main_1__vcp2,
 	&dra7xx_l4_per2__vcp2,
 	&dra7xx_l4_wkup__wd_timer2,
+	&dra7xx_l4_per2__epwmss0,
+	&dra7xx_l4_per2__epwmss1,
+	&dra7xx_l4_per2__epwmss2,
+	NULL,
+};
+
+/* GP-only hwmod links */
+static struct omap_hwmod_ocp_if *dra7xx_gp_hwmod_ocp_ifs[] __initdata = {
+	&dra7xx_l4_wkup__timer12,
 	NULL,
 };
 
+/* SoC variant specific hwmod links */
 static struct omap_hwmod_ocp_if *dra74x_hwmod_ocp_ifs[] __initdata = {
 	&dra7xx_l4_per3__usb_otg_ss4,
 	NULL,
@@ -3597,9 +3954,12 @@ int __init dra7xx_hwmod_init(void)
 	ret = omap_hwmod_register_links(dra7xx_hwmod_ocp_ifs);
 
 	if (!ret && soc_is_dra74x())
-		return omap_hwmod_register_links(dra74x_hwmod_ocp_ifs);
+		ret = omap_hwmod_register_links(dra74x_hwmod_ocp_ifs);
 	else if (!ret && soc_is_dra72x())
-		return omap_hwmod_register_links(dra72x_hwmod_ocp_ifs);
+		ret = omap_hwmod_register_links(dra72x_hwmod_ocp_ifs);
+
+	if (!ret && omap_type() == OMAP2_DEVICE_TYPE_GP)
+		ret = omap_hwmod_register_links(dra7xx_gp_hwmod_ocp_ifs);
 
 	return ret;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-omap2/omap_hwmod.c linux-libre-4.7-gnu/arch/arm/mach-omap2/omap_hwmod.c
--- linux-libre-4.6-gnu/arch/arm/mach-omap2/omap_hwmod.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-omap2/omap_hwmod.c	2016-07-24 15:23:50.000000000 -0400
@@ -2207,15 +2207,15 @@ static int _idle(struct omap_hwmod *oh)
 
 	pr_debug("omap_hwmod: %s: idling\n", oh->name);
 
+	if (_are_all_hardreset_lines_asserted(oh))
+		return 0;
+
 	if (oh->_state != _HWMOD_STATE_ENABLED) {
 		WARN(1, "omap_hwmod: %s: idle state can only be entered from enabled state\n",
 			oh->name);
 		return -EINVAL;
 	}
 
-	if (_are_all_hardreset_lines_asserted(oh))
-		return 0;
-
 	if (oh->class->sysc)
 		_idle_sysc(oh);
 	_del_initiator_dep(oh, mpu_oh);
@@ -2262,6 +2262,9 @@ static int _shutdown(struct omap_hwmod *
 	int ret, i;
 	u8 prev_state;
 
+	if (_are_all_hardreset_lines_asserted(oh))
+		return 0;
+
 	if (oh->_state != _HWMOD_STATE_IDLE &&
 	    oh->_state != _HWMOD_STATE_ENABLED) {
 		WARN(1, "omap_hwmod: %s: disabled state can only be entered from idle, or enabled state\n",
@@ -2269,9 +2272,6 @@ static int _shutdown(struct omap_hwmod *
 		return -EINVAL;
 	}
 
-	if (_are_all_hardreset_lines_asserted(oh))
-		return 0;
-
 	pr_debug("omap_hwmod: %s: disabling\n", oh->name);
 
 	if (oh->class->pre_shutdown) {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-omap2/omap_hwmod.h linux-libre-4.7-gnu/arch/arm/mach-omap2/omap_hwmod.h
--- linux-libre-4.6-gnu/arch/arm/mach-omap2/omap_hwmod.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-omap2/omap_hwmod.h	2016-07-24 15:23:50.000000000 -0400
@@ -754,6 +754,8 @@ const char *omap_hwmod_get_main_clk(stru
  */
 
 extern int omap_hwmod_aess_preprogram(struct omap_hwmod *oh);
+void omap_hwmod_rtc_unlock(struct omap_hwmod *oh);
+void omap_hwmod_rtc_lock(struct omap_hwmod *oh);
 
 /*
  * Chip variant-specific hwmod init routines - XXX should be converted
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-omap2/omap_hwmod_reset.c linux-libre-4.7-gnu/arch/arm/mach-omap2/omap_hwmod_reset.c
--- linux-libre-4.6-gnu/arch/arm/mach-omap2/omap_hwmod_reset.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-omap2/omap_hwmod_reset.c	2016-07-24 15:23:50.000000000 -0400
@@ -29,6 +29,16 @@
 #include <sound/aess.h>
 
 #include "omap_hwmod.h"
+#include "common.h"
+
+#define OMAP_RTC_STATUS_REG	0x44
+#define OMAP_RTC_KICK0_REG	0x6c
+#define OMAP_RTC_KICK1_REG	0x70
+
+#define OMAP_RTC_KICK0_VALUE	0x83E70B13
+#define OMAP_RTC_KICK1_VALUE	0x95A4F1E0
+#define OMAP_RTC_STATUS_BUSY	BIT(0)
+#define OMAP_RTC_MAX_READY_TIME	50
 
 /**
  * omap_hwmod_aess_preprogram - enable AESS internal autogating
@@ -51,3 +61,58 @@ int omap_hwmod_aess_preprogram(struct om
 
 	return 0;
 }
+
+/**
+ * omap_rtc_wait_not_busy - Wait for the RTC BUSY flag
+ * @oh: struct omap_hwmod *
+ *
+ * For updating certain RTC registers, the MPU must wait
+ * for the BUSY status in OMAP_RTC_STATUS_REG to become zero.
+ * Once the BUSY status is zero, there is a 15 microseconds access
+ * period in which the MPU can program.
+ */
+static void omap_rtc_wait_not_busy(struct omap_hwmod *oh)
+{
+	int i;
+
+	/* BUSY may stay active for 1/32768 second (~30 usec) */
+	omap_test_timeout(omap_hwmod_read(oh, OMAP_RTC_STATUS_REG)
+			  & OMAP_RTC_STATUS_BUSY, OMAP_RTC_MAX_READY_TIME, i);
+	/* now we have ~15 microseconds to read/write various registers */
+}
+
+/**
+ * omap_hwmod_rtc_unlock - Unlock the Kicker mechanism.
+ * @oh: struct omap_hwmod *
+ *
+ * RTC IP have kicker feature. This prevents spurious writes to its registers.
+ * In order to write into any of the RTC registers, KICK values has te be
+ * written in respective KICK registers. This is needed for hwmod to write into
+ * sysconfig register.
+ */
+void omap_hwmod_rtc_unlock(struct omap_hwmod *oh)
+{
+	local_irq_disable();
+	omap_rtc_wait_not_busy(oh);
+	omap_hwmod_write(OMAP_RTC_KICK0_VALUE, oh, OMAP_RTC_KICK0_REG);
+	omap_hwmod_write(OMAP_RTC_KICK1_VALUE, oh, OMAP_RTC_KICK1_REG);
+	local_irq_enable();
+}
+
+/**
+ * omap_hwmod_rtc_lock - Lock the Kicker mechanism.
+ * @oh: struct omap_hwmod *
+ *
+ * RTC IP have kicker feature. This prevents spurious writes to its registers.
+ * Once the RTC registers are written, KICK mechanism needs to be locked,
+ * in order to prevent any spurious writes. This function locks back the RTC
+ * registers once hwmod completes its write into sysconfig register.
+ */
+void omap_hwmod_rtc_lock(struct omap_hwmod *oh)
+{
+	local_irq_disable();
+	omap_rtc_wait_not_busy(oh);
+	omap_hwmod_write(0x0, oh, OMAP_RTC_KICK0_REG);
+	omap_hwmod_write(0x0, oh, OMAP_RTC_KICK1_REG);
+	local_irq_enable();
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-omap2/omap-secure.h linux-libre-4.7-gnu/arch/arm/mach-omap2/omap-secure.h
--- linux-libre-4.6-gnu/arch/arm/mach-omap2/omap-secure.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-omap2/omap-secure.h	2016-07-24 15:23:50.000000000 -0400
@@ -46,6 +46,7 @@
 
 #define OMAP5_DRA7_MON_SET_CNTFRQ_INDEX	0x109
 #define OMAP5_MON_AMBA_IF_INDEX		0x108
+#define OMAP5_DRA7_MON_SET_ACR_INDEX	0x107
 
 /* Secure PPA(Primary Protected Application) APIs */
 #define OMAP4_PPA_L2_POR_INDEX		0x23
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-omap2/omap-smp.c linux-libre-4.7-gnu/arch/arm/mach-omap2/omap-smp.c
--- linux-libre-4.6-gnu/arch/arm/mach-omap2/omap-smp.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-omap2/omap-smp.c	2016-07-24 15:23:50.000000000 -0400
@@ -50,6 +50,39 @@ void __iomem *omap4_get_scu_base(void)
 	return scu_base;
 }
 
+#ifdef CONFIG_OMAP5_ERRATA_801819
+void omap5_erratum_workaround_801819(void)
+{
+	u32 acr, revidr;
+	u32 acr_mask;
+
+	/* REVIDR[3] indicates erratum fix available on silicon */
+	asm volatile ("mrc p15, 0, %0, c0, c0, 6" : "=r" (revidr));
+	if (revidr & (0x1 << 3))
+		return;
+
+	asm volatile ("mrc p15, 0, %0, c1, c0, 1" : "=r" (acr));
+	/*
+	 * BIT(27) - Disables streaming. All write-allocate lines allocate in
+	 * the L1 or L2 cache.
+	 * BIT(25) - Disables streaming. All write-allocate lines allocate in
+	 * the L1 cache.
+	 */
+	acr_mask = (0x3 << 25) | (0x3 << 27);
+	/* do we already have it done.. if yes, skip expensive smc */
+	if ((acr & acr_mask) == acr_mask)
+		return;
+
+	acr |= acr_mask;
+	omap_smc1(OMAP5_DRA7_MON_SET_ACR_INDEX, acr);
+
+	pr_debug("%s: ARM erratum workaround 801819 applied on CPU%d\n",
+		 __func__, smp_processor_id());
+}
+#else
+static inline void omap5_erratum_workaround_801819(void) { }
+#endif
+
 static void omap4_secondary_init(unsigned int cpu)
 {
 	/*
@@ -64,12 +97,15 @@ static void omap4_secondary_init(unsigne
 		omap_secure_dispatcher(OMAP4_PPA_CPU_ACTRL_SMP_INDEX,
 							4, 0, 0, 0, 0, 0);
 
-	/*
-	 * Configure the CNTFRQ register for the secondary cpu's which
-	 * indicates the frequency of the cpu local timers.
-	 */
-	if (soc_is_omap54xx() || soc_is_dra7xx())
+	if (soc_is_omap54xx() || soc_is_dra7xx()) {
+		/*
+		 * Configure the CNTFRQ register for the secondary cpu's which
+		 * indicates the frequency of the cpu local timers.
+		 */
 		set_cntfreq();
+		/* Configure ACR to disable streaming WA for 801819 */
+		omap5_erratum_workaround_801819();
+	}
 
 	/*
 	 * Synchronise with the boot thread.
@@ -218,6 +254,8 @@ static void __init omap4_smp_prepare_cpu
 
 	if (cpu_is_omap446x())
 		startup_addr = omap4460_secondary_startup;
+	if (soc_is_dra74x() || soc_is_omap54xx())
+		omap5_erratum_workaround_801819();
 
 	/*
 	 * Write the address of secondary startup routine into the
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-omap2/omap-wakeupgen.c linux-libre-4.7-gnu/arch/arm/mach-omap2/omap-wakeupgen.c
--- linux-libre-4.6-gnu/arch/arm/mach-omap2/omap-wakeupgen.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-omap2/omap-wakeupgen.c	2016-07-24 15:23:50.000000000 -0400
@@ -327,6 +327,11 @@ static int irq_cpu_hotplug_notify(struct
 {
 	unsigned int cpu = (unsigned int)hcpu;
 
+	/*
+	 * Corresponding FROZEN transitions do not have to be handled,
+	 * they are handled by at a higher level
+	 * (drivers/cpuidle/coupled.c).
+	 */
 	switch (action) {
 	case CPU_ONLINE:
 		wakeupgen_irqmask_all(cpu, 0);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-omap2/pdata-quirks.c linux-libre-4.7-gnu/arch/arm/mach-omap2/pdata-quirks.c
--- linux-libre-4.6-gnu/arch/arm/mach-omap2/pdata-quirks.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-omap2/pdata-quirks.c	2016-07-24 15:23:50.000000000 -0400
@@ -21,9 +21,11 @@
 #include <linux/regulator/fixed.h>
 
 #include <linux/platform_data/pinctrl-single.h>
+#include <linux/platform_data/hsmmc-omap.h>
 #include <linux/platform_data/iommu-omap.h>
 #include <linux/platform_data/wkup_m3.h>
 #include <linux/platform_data/pwm_omap_dmtimer.h>
+#include <linux/platform_data/media/ir-rx51.h>
 #include <plat/dmtimer.h>
 
 #include "common.h"
@@ -31,10 +33,13 @@
 #include "dss-common.h"
 #include "control.h"
 #include "omap_device.h"
+#include "omap-pm.h"
 #include "omap-secure.h"
 #include "soc.h"
 #include "hsmmc.h"
 
+static struct omap_hsmmc_platform_data __maybe_unused mmc_pdata[2];
+
 struct pdata_init {
 	const char *compatible;
 	void (*fn)(void);
@@ -268,9 +273,13 @@ static struct platform_device omap3_rom_
 	},
 };
 
+static struct platform_device rx51_lirc_device;
+
 static void __init nokia_n900_legacy_init(void)
 {
 	hsmmc2_internal_input_clk();
+	mmc_pdata[0].name = "external";
+	mmc_pdata[1].name = "internal";
 
 	if (omap_type() == OMAP2_DEVICE_TYPE_SEC) {
 		if (IS_ENABLED(CONFIG_ARM_ERRATA_430973)) {
@@ -286,6 +295,8 @@ static void __init nokia_n900_legacy_ini
 		platform_device_register(&omap3_rom_rng_device);
 
 	}
+
+	platform_device_register(&rx51_lirc_device);
 }
 
 static void __init omap3_tao3530_legacy_init(void)
@@ -453,8 +464,14 @@ void omap_auxdata_legacy_init(struct dev
 
 /* Dual mode timer PWM callbacks platdata */
 #if IS_ENABLED(CONFIG_OMAP_DM_TIMER)
-struct pwm_omap_dmtimer_pdata pwm_dmtimer_pdata = {
+static struct pwm_omap_dmtimer_pdata pwm_dmtimer_pdata = {
 	.request_by_node = omap_dm_timer_request_by_node,
+	.request_specific = omap_dm_timer_request_specific,
+	.request = omap_dm_timer_request,
+	.set_source = omap_dm_timer_set_source,
+	.get_irq = omap_dm_timer_get_irq,
+	.set_int_enable = omap_dm_timer_set_int_enable,
+	.set_int_disable = omap_dm_timer_set_int_disable,
 	.free = omap_dm_timer_free,
 	.enable = omap_dm_timer_enable,
 	.disable = omap_dm_timer_disable,
@@ -465,10 +482,29 @@ struct pwm_omap_dmtimer_pdata pwm_dmtime
 	.set_match = omap_dm_timer_set_match,
 	.set_pwm = omap_dm_timer_set_pwm,
 	.set_prescaler = omap_dm_timer_set_prescaler,
+	.read_counter = omap_dm_timer_read_counter,
 	.write_counter = omap_dm_timer_write_counter,
+	.read_status = omap_dm_timer_read_status,
+	.write_status = omap_dm_timer_write_status,
 };
 #endif
 
+static struct lirc_rx51_platform_data __maybe_unused rx51_lirc_data = {
+	.set_max_mpu_wakeup_lat = omap_pm_set_max_mpu_wakeup_lat,
+	.pwm_timer = 9, /* Use GPT 9 for CIR */
+#if IS_ENABLED(CONFIG_OMAP_DM_TIMER)
+	.dmtimer = &pwm_dmtimer_pdata,
+#endif
+};
+
+static struct platform_device __maybe_unused rx51_lirc_device = {
+	.name           = "lirc_rx51",
+	.id             = -1,
+	.dev            = {
+		.platform_data = &rx51_lirc_data,
+	},
+};
+
 /*
  * Few boards still need auxdata populated before we populate
  * the dev entries in of_platform_populate().
@@ -492,11 +528,10 @@ static struct of_dev_auxdata omap_auxdat
 	OF_DEV_AUXDATA("tlv320aic3x", 0x18, "2-0018", &n810_aic33_data),
 #endif
 #ifdef CONFIG_ARCH_OMAP3
-	OF_DEV_AUXDATA("ti,omap3-padconf", 0x48002030, "48002030.pinmux", &pcs_pdata),
-	OF_DEV_AUXDATA("ti,omap3-padconf", 0x480025a0, "480025a0.pinmux", &pcs_pdata),
-	OF_DEV_AUXDATA("ti,omap3-padconf", 0x48002a00, "48002a00.pinmux", &pcs_pdata),
 	OF_DEV_AUXDATA("ti,omap2-iommu", 0x5d000000, "5d000000.mmu",
 		       &omap3_iommu_pdata),
+	OF_DEV_AUXDATA("ti,omap3-hsmmc", 0x4809c000, "4809c000.mmc", &mmc_pdata[0]),
+	OF_DEV_AUXDATA("ti,omap3-hsmmc", 0x480b4000, "480b4000.mmc", &mmc_pdata[1]),
 	/* Only on am3517 */
 	OF_DEV_AUXDATA("ti,davinci_mdio", 0x5c030000, "davinci_mdio.0", NULL),
 	OF_DEV_AUXDATA("ti,am3517-emac", 0x5c000000, "davinci_emac.0",
@@ -506,19 +541,7 @@ static struct of_dev_auxdata omap_auxdat
 	OF_DEV_AUXDATA("ti,am3352-wkup-m3", 0x44d00000, "44d00000.wkup_m3",
 		       &wkup_m3_data),
 #endif
-#ifdef CONFIG_ARCH_OMAP4
-	OF_DEV_AUXDATA("ti,omap4-padconf", 0x4a100040, "4a100040.pinmux", &pcs_pdata),
-	OF_DEV_AUXDATA("ti,omap4-padconf", 0x4a31e040, "4a31e040.pinmux", &pcs_pdata),
-#endif
-#ifdef CONFIG_SOC_OMAP5
-	OF_DEV_AUXDATA("ti,omap5-padconf", 0x4a002840, "4a002840.pinmux", &pcs_pdata),
-	OF_DEV_AUXDATA("ti,omap5-padconf", 0x4ae0c840, "4ae0c840.pinmux", &pcs_pdata),
-#endif
-#ifdef CONFIG_SOC_DRA7XX
-	OF_DEV_AUXDATA("ti,dra7-padconf", 0x4a003400, "4a003400.pinmux", &pcs_pdata),
-#endif
 #ifdef CONFIG_SOC_AM43XX
-	OF_DEV_AUXDATA("ti,am437-padconf", 0x44e10800, "44e10800.pinmux", &pcs_pdata),
 	OF_DEV_AUXDATA("ti,am4372-wkup-m3", 0x44d00000, "44d00000.wkup_m3",
 		       &wkup_m3_data),
 #endif
@@ -531,6 +554,8 @@ static struct of_dev_auxdata omap_auxdat
 	OF_DEV_AUXDATA("ti,omap4-iommu", 0x55082000, "55082000.mmu",
 		       &omap4_iommu_pdata),
 #endif
+	/* Common auxdata */
+	OF_DEV_AUXDATA("pinctrl-single", 0, NULL, &pcs_pdata),
 	{ /* sentinel */ },
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-omap2/pm.c linux-libre-4.7-gnu/arch/arm/mach-omap2/pm.c
--- linux-libre-4.6-gnu/arch/arm/mach-omap2/pm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-omap2/pm.c	2016-07-24 15:23:50.000000000 -0400
@@ -277,13 +277,10 @@ static void __init omap4_init_voltages(v
 
 static inline void omap_init_cpufreq(void)
 {
-	struct platform_device_info devinfo = { };
+	struct platform_device_info devinfo = { .name = "omap-cpufreq" };
 
 	if (!of_have_populated_dt())
-		devinfo.name = "omap-cpufreq";
-	else
-		devinfo.name = "cpufreq-dt";
-	platform_device_register_full(&devinfo);
+		platform_device_register_full(&devinfo);
 }
 
 static int __init omap2_common_pm_init(void)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-omap2/powerdomain.c linux-libre-4.7-gnu/arch/arm/mach-omap2/powerdomain.c
--- linux-libre-4.6-gnu/arch/arm/mach-omap2/powerdomain.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-omap2/powerdomain.c	2016-07-24 15:23:50.000000000 -0400
@@ -186,8 +186,9 @@ static int _pwrdm_state_switch(struct po
 			trace_state = (PWRDM_TRACE_STATES_FLAG |
 				       ((next & OMAP_POWERSTATE_MASK) << 8) |
 				       ((prev & OMAP_POWERSTATE_MASK) << 0));
-			trace_power_domain_target(pwrdm->name, trace_state,
-						  smp_processor_id());
+			trace_power_domain_target_rcuidle(pwrdm->name,
+							  trace_state,
+							  smp_processor_id());
 		}
 		break;
 	default:
@@ -523,8 +524,8 @@ int pwrdm_set_next_pwrst(struct powerdom
 
 	if (arch_pwrdm && arch_pwrdm->pwrdm_set_next_pwrst) {
 		/* Trace the pwrdm desired target state */
-		trace_power_domain_target(pwrdm->name, pwrst,
-					  smp_processor_id());
+		trace_power_domain_target_rcuidle(pwrdm->name, pwrst,
+						  smp_processor_id());
 		/* Program the pwrdm desired target state */
 		ret = arch_pwrdm->pwrdm_set_next_pwrst(pwrdm, pwrst);
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-omap2/powerdomains7xx_data.c linux-libre-4.7-gnu/arch/arm/mach-omap2/powerdomains7xx_data.c
--- linux-libre-4.6-gnu/arch/arm/mach-omap2/powerdomains7xx_data.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-omap2/powerdomains7xx_data.c	2016-07-24 15:23:50.000000000 -0400
@@ -35,20 +35,13 @@ static struct powerdomain iva_7xx_pwrdm
 	.name		  = "iva_pwrdm",
 	.prcm_offs	  = DRA7XX_PRM_IVA_INST,
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
-	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRSTS_OFF,
+	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 4,
-	.pwrsts_mem_ret	= {
-		[0] = PWRSTS_OFF_RET,	/* hwa_mem */
-		[1] = PWRSTS_OFF_RET,	/* sl2_mem */
-		[2] = PWRSTS_OFF_RET,	/* tcm1_mem */
-		[3] = PWRSTS_OFF_RET,	/* tcm2_mem */
-	},
 	.pwrsts_mem_on	= {
-		[0] = PWRSTS_OFF_RET,	/* hwa_mem */
-		[1] = PWRSTS_OFF_RET,	/* sl2_mem */
-		[2] = PWRSTS_OFF_RET,	/* tcm1_mem */
-		[3] = PWRSTS_OFF_RET,	/* tcm2_mem */
+		[0] = PWRSTS_ON,	/* hwa_mem */
+		[1] = PWRSTS_ON,	/* sl2_mem */
+		[2] = PWRSTS_ON,	/* tcm1_mem */
+		[3] = PWRSTS_ON,	/* tcm2_mem */
 	},
 	.flags		  = PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -75,16 +68,11 @@ static struct powerdomain ipu_7xx_pwrdm
 	.name		  = "ipu_pwrdm",
 	.prcm_offs	  = DRA7XX_PRM_IPU_INST,
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
-	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRSTS_OFF,
+	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 2,
-	.pwrsts_mem_ret	= {
-		[0] = PWRSTS_OFF_RET,	/* aessmem */
-		[1] = PWRSTS_OFF_RET,	/* periphmem */
-	},
 	.pwrsts_mem_on	= {
-		[0] = PWRSTS_OFF_RET,	/* aessmem */
-		[1] = PWRSTS_OFF_RET,	/* periphmem */
+		[0] = PWRSTS_ON,	/* aessmem */
+		[1] = PWRSTS_ON,	/* periphmem */
 	},
 	.flags		  = PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -94,14 +82,10 @@ static struct powerdomain dss_7xx_pwrdm
 	.name		  = "dss_pwrdm",
 	.prcm_offs	  = DRA7XX_PRM_DSS_INST,
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
-	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRSTS_OFF,
+	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 1,
-	.pwrsts_mem_ret	= {
-		[0] = PWRSTS_OFF_RET,	/* dss_mem */
-	},
 	.pwrsts_mem_on	= {
-		[0] = PWRSTS_OFF_RET,	/* dss_mem */
+		[0] = PWRSTS_ON,	/* dss_mem */
 	},
 	.flags		  = PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -111,16 +95,11 @@ static struct powerdomain l4per_7xx_pwrd
 	.name		  = "l4per_pwrdm",
 	.prcm_offs	  = DRA7XX_PRM_L4PER_INST,
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
-	.pwrsts		  = PWRSTS_RET_ON,
-	.pwrsts_logic_ret = PWRSTS_OFF_RET,
+	.pwrsts		  = PWRSTS_ON,
 	.banks		  = 2,
-	.pwrsts_mem_ret	= {
-		[0] = PWRSTS_OFF_RET,	/* nonretained_bank */
-		[1] = PWRSTS_OFF_RET,	/* retained_bank */
-	},
 	.pwrsts_mem_on	= {
-		[0] = PWRSTS_OFF_RET,	/* nonretained_bank */
-		[1] = PWRSTS_OFF_RET,	/* retained_bank */
+		[0] = PWRSTS_ON,	/* nonretained_bank */
+		[1] = PWRSTS_ON,	/* retained_bank */
 	},
 	.flags		  = PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -132,11 +111,8 @@ static struct powerdomain gpu_7xx_pwrdm
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 1,
-	.pwrsts_mem_ret	= {
-		[0] = PWRSTS_OFF_RET,	/* gpu_mem */
-	},
 	.pwrsts_mem_on	= {
-		[0] = PWRSTS_OFF_RET,	/* gpu_mem */
+		[0] = PWRSTS_ON,	/* gpu_mem */
 	},
 	.flags		  = PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -148,8 +124,6 @@ static struct powerdomain wkupaon_7xx_pw
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
 	.pwrsts		  = PWRSTS_ON,
 	.banks		  = 1,
-	.pwrsts_mem_ret	= {
-	},
 	.pwrsts_mem_on	= {
 		[0] = PWRSTS_ON,	/* wkup_bank */
 	},
@@ -160,22 +134,14 @@ static struct powerdomain core_7xx_pwrdm
 	.name		  = "core_pwrdm",
 	.prcm_offs	  = DRA7XX_PRM_CORE_INST,
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
-	.pwrsts		  = PWRSTS_INA_ON,
-	.pwrsts_logic_ret = PWRSTS_RET,
+	.pwrsts		  = PWRSTS_ON,
 	.banks		  = 5,
-	.pwrsts_mem_ret	= {
-		[0] = PWRSTS_OFF_RET,	/* core_nret_bank */
-		[1] = PWRSTS_OFF_RET,	/* core_ocmram */
-		[2] = PWRSTS_OFF_RET,	/* core_other_bank */
-		[3] = PWRSTS_OFF_RET,	/* ipu_l2ram */
-		[4] = PWRSTS_OFF_RET,	/* ipu_unicache */
-	},
 	.pwrsts_mem_on	= {
-		[0] = PWRSTS_OFF_RET,	/* core_nret_bank */
-		[1] = PWRSTS_OFF_RET,	/* core_ocmram */
-		[2] = PWRSTS_OFF_RET,	/* core_other_bank */
-		[3] = PWRSTS_OFF_RET,	/* ipu_l2ram */
-		[4] = PWRSTS_OFF_RET,	/* ipu_unicache */
+		[0] = PWRSTS_ON,	/* core_nret_bank */
+		[1] = PWRSTS_ON,	/* core_ocmram */
+		[2] = PWRSTS_ON,	/* core_other_bank */
+		[3] = PWRSTS_ON,	/* ipu_l2ram */
+		[4] = PWRSTS_ON,	/* ipu_unicache */
 	},
 	.flags		  = PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -225,14 +191,10 @@ static struct powerdomain vpe_7xx_pwrdm
 	.name		  = "vpe_pwrdm",
 	.prcm_offs	  = DRA7XX_PRM_VPE_INST,
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
-	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRSTS_OFF_RET,
+	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 1,
-	.pwrsts_mem_ret	= {
-		[0] = PWRSTS_OFF_RET,	/* vpe_bank */
-	},
 	.pwrsts_mem_on	= {
-		[0] = PWRSTS_OFF_RET,	/* vpe_bank */
+		[0] = PWRSTS_ON,	/* vpe_bank */
 	},
 	.flags		  = PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -250,8 +212,8 @@ static struct powerdomain mpu_7xx_pwrdm
 		[1] = PWRSTS_RET,	/* mpu_ram */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRSTS_OFF_RET,	/* mpu_l2 */
-		[1] = PWRSTS_OFF_RET,	/* mpu_ram */
+		[0] = PWRSTS_ON,	/* mpu_l2 */
+		[1] = PWRSTS_ON,	/* mpu_ram */
 	},
 };
 
@@ -260,18 +222,12 @@ static struct powerdomain l3init_7xx_pwr
 	.name		  = "l3init_pwrdm",
 	.prcm_offs	  = DRA7XX_PRM_L3INIT_INST,
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
-	.pwrsts		  = PWRSTS_RET_ON,
-	.pwrsts_logic_ret = PWRSTS_OFF_RET,
+	.pwrsts		  = PWRSTS_ON,
 	.banks		  = 3,
-	.pwrsts_mem_ret	= {
-		[0] = PWRSTS_OFF_RET,	/* gmac_bank */
-		[1] = PWRSTS_OFF_RET,	/* l3init_bank1 */
-		[2] = PWRSTS_OFF_RET,	/* l3init_bank2 */
-	},
 	.pwrsts_mem_on	= {
-		[0] = PWRSTS_OFF_RET,	/* gmac_bank */
-		[1] = PWRSTS_OFF_RET,	/* l3init_bank1 */
-		[2] = PWRSTS_OFF_RET,	/* l3init_bank2 */
+		[0] = PWRSTS_ON,	/* gmac_bank */
+		[1] = PWRSTS_ON,	/* l3init_bank1 */
+		[2] = PWRSTS_ON,	/* l3init_bank2 */
 	},
 	.flags		  = PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -283,11 +239,8 @@ static struct powerdomain eve3_7xx_pwrdm
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 1,
-	.pwrsts_mem_ret	= {
-		[0] = PWRSTS_OFF_RET,	/* eve3_bank */
-	},
 	.pwrsts_mem_on	= {
-		[0] = PWRSTS_OFF_RET,	/* eve3_bank */
+		[0] = PWRSTS_ON,	/* eve3_bank */
 	},
 	.flags		  = PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -299,11 +252,8 @@ static struct powerdomain emu_7xx_pwrdm
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 1,
-	.pwrsts_mem_ret	= {
-		[0] = PWRSTS_OFF_RET,	/* emu_bank */
-	},
 	.pwrsts_mem_on	= {
-		[0] = PWRSTS_OFF_RET,	/* emu_bank */
+		[0] = PWRSTS_ON,	/* emu_bank */
 	},
 };
 
@@ -314,15 +264,10 @@ static struct powerdomain dsp2_7xx_pwrdm
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 3,
-	.pwrsts_mem_ret	= {
-		[0] = PWRSTS_OFF_RET,	/* dsp2_edma */
-		[1] = PWRSTS_OFF_RET,	/* dsp2_l1 */
-		[2] = PWRSTS_OFF_RET,	/* dsp2_l2 */
-	},
 	.pwrsts_mem_on	= {
-		[0] = PWRSTS_OFF_RET,	/* dsp2_edma */
-		[1] = PWRSTS_OFF_RET,	/* dsp2_l1 */
-		[2] = PWRSTS_OFF_RET,	/* dsp2_l2 */
+		[0] = PWRSTS_ON,	/* dsp2_edma */
+		[1] = PWRSTS_ON,	/* dsp2_l1 */
+		[2] = PWRSTS_ON,	/* dsp2_l2 */
 	},
 	.flags		  = PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -334,15 +279,10 @@ static struct powerdomain dsp1_7xx_pwrdm
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 3,
-	.pwrsts_mem_ret	= {
-		[0] = PWRSTS_OFF_RET,	/* dsp1_edma */
-		[1] = PWRSTS_OFF_RET,	/* dsp1_l1 */
-		[2] = PWRSTS_OFF_RET,	/* dsp1_l2 */
-	},
 	.pwrsts_mem_on	= {
-		[0] = PWRSTS_OFF_RET,	/* dsp1_edma */
-		[1] = PWRSTS_OFF_RET,	/* dsp1_l1 */
-		[2] = PWRSTS_OFF_RET,	/* dsp1_l2 */
+		[0] = PWRSTS_ON,	/* dsp1_edma */
+		[1] = PWRSTS_ON,	/* dsp1_l1 */
+		[2] = PWRSTS_ON,	/* dsp1_l2 */
 	},
 	.flags		  = PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -354,11 +294,8 @@ static struct powerdomain cam_7xx_pwrdm
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 1,
-	.pwrsts_mem_ret	= {
-		[0] = PWRSTS_OFF_RET,	/* vip_bank */
-	},
 	.pwrsts_mem_on	= {
-		[0] = PWRSTS_OFF_RET,	/* vip_bank */
+		[0] = PWRSTS_ON,	/* vip_bank */
 	},
 	.flags		  = PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -370,11 +307,8 @@ static struct powerdomain eve4_7xx_pwrdm
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 1,
-	.pwrsts_mem_ret	= {
-		[0] = PWRSTS_OFF_RET,	/* eve4_bank */
-	},
 	.pwrsts_mem_on	= {
-		[0] = PWRSTS_OFF_RET,	/* eve4_bank */
+		[0] = PWRSTS_ON,	/* eve4_bank */
 	},
 	.flags		  = PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -386,11 +320,8 @@ static struct powerdomain eve2_7xx_pwrdm
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 1,
-	.pwrsts_mem_ret	= {
-		[0] = PWRSTS_OFF_RET,	/* eve2_bank */
-	},
 	.pwrsts_mem_on	= {
-		[0] = PWRSTS_OFF_RET,	/* eve2_bank */
+		[0] = PWRSTS_ON,	/* eve2_bank */
 	},
 	.flags		  = PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -402,11 +333,8 @@ static struct powerdomain eve1_7xx_pwrdm
 	.prcm_partition	  = DRA7XX_PRM_PARTITION,
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 1,
-	.pwrsts_mem_ret	= {
-		[0] = PWRSTS_OFF_RET,	/* eve1_bank */
-	},
 	.pwrsts_mem_on	= {
-		[0] = PWRSTS_OFF_RET,	/* eve1_bank */
+		[0] = PWRSTS_ON,	/* eve1_bank */
 	},
 	.flags		  = PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-omap2/soc.h linux-libre-4.7-gnu/arch/arm/mach-omap2/soc.h
--- linux-libre-4.6-gnu/arch/arm/mach-omap2/soc.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-omap2/soc.h	2016-07-24 15:23:50.000000000 -0400
@@ -39,82 +39,10 @@
 #include <linux/of.h>
 
 /*
- * Test if multicore OMAP support is needed
+ * OMAP2+ is always defined as ARCH_MULTIPLATFORM in Kconfig
  */
 #undef MULTI_OMAP2
-#undef OMAP_NAME
-
-#ifdef CONFIG_ARCH_MULTIPLATFORM
 #define MULTI_OMAP2
-#endif
-#ifdef CONFIG_SOC_OMAP2420
-# ifdef OMAP_NAME
-#  undef  MULTI_OMAP2
-#  define MULTI_OMAP2
-# else
-#  define OMAP_NAME omap2420
-# endif
-#endif
-#ifdef CONFIG_SOC_OMAP2430
-# ifdef OMAP_NAME
-#  undef  MULTI_OMAP2
-#  define MULTI_OMAP2
-# else
-#  define OMAP_NAME omap2430
-# endif
-#endif
-#ifdef CONFIG_ARCH_OMAP3
-# ifdef OMAP_NAME
-#  undef  MULTI_OMAP2
-#  define MULTI_OMAP2
-# else
-#  define OMAP_NAME omap3
-# endif
-#endif
-#ifdef CONFIG_ARCH_OMAP4
-# ifdef OMAP_NAME
-#  undef  MULTI_OMAP2
-#  define MULTI_OMAP2
-# else
-#  define OMAP_NAME omap4
-# endif
-#endif
-
-#ifdef CONFIG_SOC_OMAP5
-# ifdef OMAP_NAME
-#  undef  MULTI_OMAP2
-#  define MULTI_OMAP2
-# else
-#  define OMAP_NAME omap5
-# endif
-#endif
-
-#ifdef CONFIG_SOC_AM33XX
-# ifdef OMAP_NAME
-#  undef  MULTI_OMAP2
-#  define MULTI_OMAP2
-# else
-#  define OMAP_NAME am33xx
-# endif
-#endif
-
-#ifdef CONFIG_SOC_AM43XX
-# ifdef OMAP_NAME
-#  undef  MULTI_OMAP2
-#  define MULTI_OMAP2
-# else
-#  define OMAP_NAME am43xx
-# endif
-#endif
-
-#ifdef CONFIG_SOC_DRA7XX
-# ifdef OMAP_NAME
-#  undef MULTI_OMAP2
-#  define MULTI_OMAP2
-# else
-#  define OMAP_NAME DRA7XX
-# endif
-#endif
 
 /*
  * Omap device type i.e. EMU/HS/TST/GP/BAD
@@ -242,11 +170,6 @@ IS_AM_SUBCLASS(437x, 0x437)
 IS_DRA_SUBCLASS(75x, 0x75)
 IS_DRA_SUBCLASS(72x, 0x72)
 
-#define soc_is_omap24xx()		0
-#define soc_is_omap242x()		0
-#define soc_is_omap243x()		0
-#define soc_is_omap34xx()		0
-#define soc_is_omap343x()		0
 #define soc_is_ti81xx()			0
 #define soc_is_ti816x()			0
 #define soc_is_ti814x()			0
@@ -265,46 +188,27 @@ IS_DRA_SUBCLASS(72x, 0x72)
 #define soc_is_dra74x()			0
 #define soc_is_dra72x()			0
 
-#if defined(MULTI_OMAP2)
-# if defined(CONFIG_ARCH_OMAP2)
-#  undef  soc_is_omap24xx
-#  define soc_is_omap24xx()		is_omap24xx()
-# endif
-# if defined (CONFIG_SOC_OMAP2420)
-#  undef  soc_is_omap242x
-#  define soc_is_omap242x()		is_omap242x()
-# endif
-# if defined (CONFIG_SOC_OMAP2430)
-#  undef  soc_is_omap243x
-#  define soc_is_omap243x()		is_omap243x()
-# endif
-# if defined(CONFIG_ARCH_OMAP3)
-#  undef  soc_is_omap34xx
-#  undef  soc_is_omap343x
-#  define soc_is_omap34xx()		is_omap34xx()
-#  define soc_is_omap343x()		is_omap343x()
-# endif
+#if defined(CONFIG_ARCH_OMAP2)
+# define soc_is_omap24xx()		is_omap24xx()
 #else
-# if defined(CONFIG_ARCH_OMAP2)
-#  undef  soc_is_omap24xx
-#  define soc_is_omap24xx()		1
-# endif
-# if defined(CONFIG_SOC_OMAP2420)
-#  undef  soc_is_omap242x
-#  define soc_is_omap242x()		1
-# endif
-# if defined(CONFIG_SOC_OMAP2430)
-#  undef  soc_is_omap243x
-#  define soc_is_omap243x()		1
-# endif
-# if defined(CONFIG_ARCH_OMAP3)
-#  undef  soc_is_omap34xx
-#  define soc_is_omap34xx()		1
-# endif
-# if defined(CONFIG_SOC_OMAP3430)
-#  undef  soc_is_omap343x
-#  define soc_is_omap343x()		1
-# endif
+# define soc_is_omap24xx()		0
+#endif
+#if defined(CONFIG_SOC_OMAP2420)
+# define soc_is_omap242x()		is_omap242x()
+#else
+# define soc_is_omap242x()		0
+#endif
+#if defined(CONFIG_SOC_OMAP2430)
+# define soc_is_omap243x()		is_omap243x()
+#else
+# define soc_is_omap243x()		0
+#endif
+#if defined(CONFIG_ARCH_OMAP3)
+# define soc_is_omap34xx()		is_omap34xx()
+# define soc_is_omap343x()		is_omap343x()
+#else
+# define soc_is_omap34xx()		0
+# define soc_is_omap343x()		0
 #endif
 
 /*
@@ -339,7 +243,6 @@ IS_OMAP_TYPE(3430, 0x3430)
 #define soc_is_omap5430()		0
 
 /* These are needed for the common code */
-#ifdef CONFIG_ARCH_OMAP2PLUS
 #define soc_is_omap7xx()		0
 #define soc_is_omap15xx()		0
 #define soc_is_omap16xx()		0
@@ -350,7 +253,6 @@ IS_OMAP_TYPE(3430, 0x3430)
 #define soc_is_omap1710()		0
 #define cpu_class_is_omap1()		0
 #define cpu_class_is_omap2()		1
-#endif
 
 #if defined(CONFIG_ARCH_OMAP2)
 # undef  soc_is_omap2420
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-omap2/timer.c linux-libre-4.7-gnu/arch/arm/mach-omap2/timer.c
--- linux-libre-4.6-gnu/arch/arm/mach-omap2/timer.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-omap2/timer.c	2016-07-24 15:23:50.000000000 -0400
@@ -496,8 +496,7 @@ void __init omap_init_time(void)
 	__omap_sync32k_timer_init(1, "timer_32k_ck", "ti,timer-alwon",
 			2, "timer_sys_ck", NULL, false);
 
-	if (of_have_populated_dt())
-		clocksource_probe();
+	clocksource_probe();
 }
 
 #if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_AM43XX)
@@ -505,6 +504,8 @@ void __init omap3_secure_sync32k_timer_i
 {
 	__omap_sync32k_timer_init(12, "secure_32k_fck", "ti,timer-secure",
 			2, "timer_sys_ck", NULL, false);
+
+	clocksource_probe();
 }
 #endif /* CONFIG_ARCH_OMAP3 */
 
@@ -513,6 +514,8 @@ void __init omap3_gptimer_timer_init(voi
 {
 	__omap_sync32k_timer_init(2, "timer_sys_ck", NULL,
 			1, "timer_sys_ck", "ti,timer-alwon", true);
+
+	clocksource_probe();
 }
 #endif
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-orion5x/common.c linux-libre-4.7-gnu/arch/arm/mach-orion5x/common.c
--- linux-libre-4.6-gnu/arch/arm/mach-orion5x/common.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-orion5x/common.c	2016-07-24 15:23:50.000000000 -0400
@@ -66,8 +66,7 @@ static struct clk *tclk;
 
 void __init clk_init(void)
 {
-	tclk = clk_register_fixed_rate(NULL, "tclk", NULL, CLK_IS_ROOT,
-				       orion5x_tclk);
+	tclk = clk_register_fixed_rate(NULL, "tclk", NULL, 0, orion5x_tclk);
 
 	orion_clkdev_init(tclk);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-oxnas/Kconfig linux-libre-4.7-gnu/arch/arm/mach-oxnas/Kconfig
--- linux-libre-4.6-gnu/arch/arm/mach-oxnas/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/mach-oxnas/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,24 @@
+menuconfig ARCH_OXNAS
+	bool "Oxford Semiconductor OXNAS Family SoCs"
+	select ARCH_REQUIRE_GPIOLIB
+	select ARCH_HAS_RESET_CONTROLLER
+	select PINCTRL
+	depends on ARCH_MULTI_V5
+	help
+	  Support for OxNas SoC family developed by Oxford Semiconductor.
+
+if ARCH_OXNAS
+
+config MACH_OX810SE
+	bool "Support OX810SE Based Products"
+	select ARM_TIMER_SP804
+	select COMMON_CLK_OXNAS
+	select CPU_ARM926T
+	select MFD_SYSCON
+	select PINCTRL_OXNAS
+	select RESET_OXNAS
+	select VERSATILE_FPGA_IRQ
+	help
+	  Include Support for the Oxford Semiconductor OX810SE SoC Based Products.
+
+endif
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-pxa/eseries.c linux-libre-4.7-gnu/arch/arm/mach-pxa/eseries.c
--- linux-libre-4.6-gnu/arch/arm/mach-pxa/eseries.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-pxa/eseries.c	2016-07-24 15:23:50.000000000 -0400
@@ -128,7 +128,7 @@ struct resource eseries_tmio_resources[]
 /* Some e-series hardware cannot control the 32K clock */
 static void __init __maybe_unused eseries_register_clks(void)
 {
-	clk_register_fixed_rate(NULL, "CLK_CK32K", NULL, CLK_IS_ROOT, 32768);
+	clk_register_fixed_rate(NULL, "CLK_CK32K", NULL, 0, 32768);
 }
 
 #ifdef CONFIG_MACH_E330
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-pxa/Kconfig linux-libre-4.7-gnu/arch/arm/mach-pxa/Kconfig
--- linux-libre-4.6-gnu/arch/arm/mach-pxa/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-pxa/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -6,6 +6,7 @@ comment "Intel/Marvell Dev Platforms (so
 
 config MACH_PXA27X_DT
 	bool "Support PXA27x platforms from device tree"
+	select PINCTRL
 	select POWER_SUPPLY
 	select PXA27x
 	select USE_OF
@@ -17,6 +18,7 @@ config MACH_PXA27X_DT
 config MACH_PXA3XX_DT
 	bool "Support PXA3xx platforms from device tree"
 	select CPU_PXA300
+	select PINCTRL
 	select POWER_SUPPLY
 	select PXA3xx
 	select USE_OF
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-pxa/raumfeld.c linux-libre-4.7-gnu/arch/arm/mach-pxa/raumfeld.c
--- linux-libre-4.6-gnu/arch/arm/mach-pxa/raumfeld.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-pxa/raumfeld.c	2016-07-24 15:23:50.000000000 -0400
@@ -385,10 +385,6 @@ static struct property_entry raumfeld_ro
 	{ },
 };
 
-static struct property_set raumfeld_rotary_property_set = {
-	.properties = raumfeld_rotary_properties,
-};
-
 static struct platform_device rotary_encoder_device = {
 	.name		= "rotary-encoder",
 	.id		= 0,
@@ -1063,8 +1059,8 @@ static void __init __maybe_unused raumfe
 	pxa3xx_mfp_config(ARRAY_AND_SIZE(raumfeld_controller_pin_config));
 
 	gpiod_add_lookup_table(&raumfeld_rotary_gpios_table);
-	device_add_property_set(&rotary_encoder_device.dev,
-				&raumfeld_rotary_property_set);
+	device_add_properties(&rotary_encoder_device.dev,
+			      raumfeld_rotary_properties);
 	platform_device_register(&rotary_encoder_device);
 
 	spi_register_board_info(ARRAY_AND_SIZE(controller_spi_devices));
@@ -1103,8 +1099,8 @@ static void __init __maybe_unused raumfe
 	platform_device_register(&smc91x_device);
 
 	gpiod_add_lookup_table(&raumfeld_rotary_gpios_table);
-	device_add_property_set(&rotary_encoder_device.dev,
-				&raumfeld_rotary_property_set);
+	device_add_properties(&rotary_encoder_device.dev,
+			      raumfeld_rotary_properties);
 	platform_device_register(&rotary_encoder_device);
 
 	raumfeld_audio_init();
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-pxa/spitz.c linux-libre-4.7-gnu/arch/arm/mach-pxa/spitz.c
--- linux-libre-4.6-gnu/arch/arm/mach-pxa/spitz.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-pxa/spitz.c	2016-07-24 15:23:50.000000000 -0400
@@ -763,14 +763,49 @@ static struct nand_bbt_descr spitz_nand_
 	.pattern	= scan_ff_pattern
 };
 
-static struct nand_ecclayout akita_oobinfo = {
-	.oobfree	= { {0x08, 0x09} },
-	.eccbytes	= 24,
-	.eccpos		= {
-			0x05, 0x01, 0x02, 0x03, 0x06, 0x07, 0x15, 0x11,
-			0x12, 0x13, 0x16, 0x17, 0x25, 0x21, 0x22, 0x23,
-			0x26, 0x27, 0x35, 0x31, 0x32, 0x33, 0x36, 0x37,
-	},
+static int akita_ooblayout_ecc(struct mtd_info *mtd, int section,
+			       struct mtd_oob_region *oobregion)
+{
+	if (section > 12)
+		return -ERANGE;
+
+	switch (section % 3) {
+	case 0:
+		oobregion->offset = 5;
+		oobregion->length = 1;
+		break;
+
+	case 1:
+		oobregion->offset = 1;
+		oobregion->length = 3;
+		break;
+
+	case 2:
+		oobregion->offset = 6;
+		oobregion->length = 2;
+		break;
+	}
+
+	oobregion->offset += (section / 3) * 0x10;
+
+	return 0;
+}
+
+static int akita_ooblayout_free(struct mtd_info *mtd, int section,
+				struct mtd_oob_region *oobregion)
+{
+	if (section)
+		return -ERANGE;
+
+	oobregion->offset = 8;
+	oobregion->length = 9;
+
+	return 0;
+}
+
+static const struct mtd_ooblayout_ops akita_ooblayout_ops = {
+	.ecc = akita_ooblayout_ecc,
+	.free = akita_ooblayout_free,
 };
 
 static struct sharpsl_nand_platform_data spitz_nand_pdata = {
@@ -804,11 +839,11 @@ static void __init spitz_nand_init(void)
 	} else if (machine_is_akita()) {
 		spitz_nand_partitions[1].size = 58 * 1024 * 1024;
 		spitz_nand_bbt.len = 1;
-		spitz_nand_pdata.ecc_layout = &akita_oobinfo;
+		spitz_nand_pdata.ecc_layout = &akita_ooblayout_ops;
 	} else if (machine_is_borzoi()) {
 		spitz_nand_partitions[1].size = 32 * 1024 * 1024;
 		spitz_nand_bbt.len = 1;
-		spitz_nand_pdata.ecc_layout = &akita_oobinfo;
+		spitz_nand_pdata.ecc_layout = &akita_ooblayout_ops;
 	}
 
 	platform_device_register(&spitz_nand_device);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-realview/realview_pbx.c linux-libre-4.7-gnu/arch/arm/mach-realview/realview_pbx.c
--- linux-libre-4.6-gnu/arch/arm/mach-realview/realview_pbx.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-realview/realview_pbx.c	2016-07-24 15:23:50.000000000 -0400
@@ -248,6 +248,7 @@ static struct resource realview_pbx_isp1
 	},
 };
 
+#ifdef CONFIG_CACHE_L2X0
 static struct resource pmu_resources[] = {
 	[0] = {
 		.start		= IRQ_PBX_PMU_CPU0,
@@ -277,6 +278,7 @@ static struct platform_device pmu_device
 	.num_resources		= ARRAY_SIZE(pmu_resources),
 	.resource		= pmu_resources,
 };
+#endif
 
 static void __init gic_init_irq(void)
 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-rockchip/platsmp.c linux-libre-4.7-gnu/arch/arm/mach-rockchip/platsmp.c
--- linux-libre-4.6-gnu/arch/arm/mach-rockchip/platsmp.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-rockchip/platsmp.c	2016-07-24 15:23:50.000000000 -0400
@@ -65,7 +65,7 @@ static struct reset_control *rockchip_ge
 	if (dev)
 		np = dev->of_node;
 	else
-		np = of_get_cpu_node(cpu, 0);
+		np = of_get_cpu_node(cpu, NULL);
 
 	return of_reset_control_get(np, NULL);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-rockchip/rockchip.c linux-libre-4.7-gnu/arch/arm/mach-rockchip/rockchip.c
--- linux-libre-4.6-gnu/arch/arm/mach-rockchip/rockchip.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-rockchip/rockchip.c	2016-07-24 15:23:50.000000000 -0400
@@ -74,7 +74,6 @@ static void __init rockchip_dt_init(void
 {
 	rockchip_suspend_init();
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-	platform_device_register_simple("cpufreq-dt", 0, NULL, 0);
 }
 
 static const char * const rockchip_board_dt_compat[] = {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-s3c24xx/mach-rx1950.c linux-libre-4.7-gnu/arch/arm/mach-s3c24xx/mach-rx1950.c
--- linux-libre-4.6-gnu/arch/arm/mach-s3c24xx/mach-rx1950.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-s3c24xx/mach-rx1950.c	2016-07-24 15:23:50.000000000 -0400
@@ -496,6 +496,12 @@ static int rx1950_backlight_init(struct
 		return PTR_ERR(lcd_pwm);
 	}
 
+	/*
+	 * FIXME: pwm_apply_args() should be removed when switching to
+	 * the atomic PWM API.
+	 */
+	pwm_apply_args(lcd_pwm);
+
 	rx1950_lcd_power(1);
 	rx1950_bl_power(1);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-shmobile/common.h linux-libre-4.7-gnu/arch/arm/mach-shmobile/common.h
--- linux-libre-4.6-gnu/arch/arm/mach-shmobile/common.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-shmobile/common.h	2016-07-24 15:23:50.000000000 -0400
@@ -25,16 +25,9 @@ static inline int shmobile_suspend_init(
 static inline void shmobile_smp_apmu_suspend_init(void) { }
 #endif
 
-#ifdef CONFIG_CPU_FREQ
-int shmobile_cpufreq_init(void);
-#else
-static inline int shmobile_cpufreq_init(void) { return 0; }
-#endif
-
 static inline void __init shmobile_init_late(void)
 {
 	shmobile_suspend_init();
-	shmobile_cpufreq_init();
 }
 
 #endif /* __ARCH_MACH_COMMON_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-shmobile/cpufreq.c linux-libre-4.7-gnu/arch/arm/mach-shmobile/cpufreq.c
--- linux-libre-4.6-gnu/arch/arm/mach-shmobile/cpufreq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-shmobile/cpufreq.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,19 +0,0 @@
-/*
- * CPUFreq support code for SH-Mobile ARM
- *
- *  Copyright (C) 2014 Gaku Inami
- *
- * 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/platform_device.h>
-
-#include "common.h"
-
-int __init shmobile_cpufreq_init(void)
-{
-	platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
-	return 0;
-}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-shmobile/Kconfig linux-libre-4.7-gnu/arch/arm/mach-shmobile/Kconfig
--- linux-libre-4.6-gnu/arch/arm/mach-shmobile/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-shmobile/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -4,11 +4,6 @@ config ARCH_SHMOBILE
 config ARCH_SHMOBILE_MULTI
 	bool
 
-config PM_RCAR
-	bool
-	select PM
-	select PM_GENERIC_DOMAINS
-
 config PM_RMOBILE
 	bool
 	select PM
@@ -16,13 +11,15 @@ config PM_RMOBILE
 
 config ARCH_RCAR_GEN1
 	bool
-	select PM_RCAR
+	select PM
+	select PM_GENERIC_DOMAINS
 	select RENESAS_INTC_IRQPIN
 	select SYS_SUPPORTS_SH_TMU
 
 config ARCH_RCAR_GEN2
 	bool
-	select PM_RCAR
+	select PM
+	select PM_GENERIC_DOMAINS
 	select RENESAS_IRQC
 	select SYS_SUPPORTS_SH_CMT
 	select PCI_DOMAINS if PCI
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-shmobile/Makefile linux-libre-4.7-gnu/arch/arm/mach-shmobile/Makefile
--- linux-libre-4.6-gnu/arch/arm/mach-shmobile/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-shmobile/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -38,8 +38,6 @@ smp-$(CONFIG_ARCH_EMEV2)	+= smp-emev2.o
 
 # PM objects
 obj-$(CONFIG_SUSPEND)		+= suspend.o
-obj-$(CONFIG_CPU_FREQ)		+= cpufreq.o
-obj-$(CONFIG_PM_RCAR)		+= pm-rcar.o
 obj-$(CONFIG_PM_RMOBILE)	+= pm-rmobile.o
 obj-$(CONFIG_ARCH_RCAR_GEN2)	+= pm-rcar-gen2.o
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-shmobile/pm-r8a7779.c linux-libre-4.7-gnu/arch/arm/mach-shmobile/pm-r8a7779.c
--- linux-libre-4.6-gnu/arch/arm/mach-shmobile/pm-r8a7779.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-shmobile/pm-r8a7779.c	2016-07-24 15:23:50.000000000 -0400
@@ -9,9 +9,10 @@
  * for more details.
  */
 
+#include <linux/soc/renesas/rcar-sysc.h>
+
 #include <asm/io.h>
 
-#include "pm-rcar.h"
 #include "r8a7779.h"
 
 /* SYSC */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-shmobile/pm-rcar.c linux-libre-4.7-gnu/arch/arm/mach-shmobile/pm-rcar.c
--- linux-libre-4.6-gnu/arch/arm/mach-shmobile/pm-rcar.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-shmobile/pm-rcar.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,164 +0,0 @@
-/*
- * R-Car SYSC Power management support
- *
- * Copyright (C) 2014  Magnus Damm
- *
- * 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/delay.h>
-#include <linux/err.h>
-#include <linux/mm.h>
-#include <linux/spinlock.h>
-#include <linux/io.h>
-#include "pm-rcar.h"
-
-/* SYSC Common */
-#define SYSCSR			0x00	/* SYSC Status Register */
-#define SYSCISR			0x04	/* Interrupt Status Register */
-#define SYSCISCR		0x08	/* Interrupt Status Clear Register */
-#define SYSCIER			0x0c	/* Interrupt Enable Register */
-#define SYSCIMR			0x10	/* Interrupt Mask Register */
-
-/* SYSC Status Register */
-#define SYSCSR_PONENB		1	/* Ready for power resume requests */
-#define SYSCSR_POFFENB		0	/* Ready for power shutoff requests */
-
-/*
- * Power Control Register Offsets inside the register block for each domain
- * Note: The "CR" registers for ARM cores exist on H1 only
- *       Use WFI to power off, CPG/APMU to resume ARM cores on R-Car Gen2
- */
-#define PWRSR_OFFS		0x00	/* Power Status Register */
-#define PWROFFCR_OFFS		0x04	/* Power Shutoff Control Register */
-#define PWROFFSR_OFFS		0x08	/* Power Shutoff Status Register */
-#define PWRONCR_OFFS		0x0c	/* Power Resume Control Register */
-#define PWRONSR_OFFS		0x10	/* Power Resume Status Register */
-#define PWRER_OFFS		0x14	/* Power Shutoff/Resume Error */
-
-
-#define SYSCSR_RETRIES		100
-#define SYSCSR_DELAY_US		1
-
-#define PWRER_RETRIES		100
-#define PWRER_DELAY_US		1
-
-#define SYSCISR_RETRIES		1000
-#define SYSCISR_DELAY_US	1
-
-static void __iomem *rcar_sysc_base;
-static DEFINE_SPINLOCK(rcar_sysc_lock); /* SMP CPUs + I/O devices */
-
-static int rcar_sysc_pwr_on_off(const struct rcar_sysc_ch *sysc_ch, bool on)
-{
-	unsigned int sr_bit, reg_offs;
-	int k;
-
-	if (on) {
-		sr_bit = SYSCSR_PONENB;
-		reg_offs = PWRONCR_OFFS;
-	} else {
-		sr_bit = SYSCSR_POFFENB;
-		reg_offs = PWROFFCR_OFFS;
-	}
-
-	/* Wait until SYSC is ready to accept a power request */
-	for (k = 0; k < SYSCSR_RETRIES; k++) {
-		if (ioread32(rcar_sysc_base + SYSCSR) & BIT(sr_bit))
-			break;
-		udelay(SYSCSR_DELAY_US);
-	}
-
-	if (k == SYSCSR_RETRIES)
-		return -EAGAIN;
-
-	/* Submit power shutoff or power resume request */
-	iowrite32(BIT(sysc_ch->chan_bit),
-		  rcar_sysc_base + sysc_ch->chan_offs + reg_offs);
-
-	return 0;
-}
-
-static int rcar_sysc_power(const struct rcar_sysc_ch *sysc_ch, bool on)
-{
-	unsigned int isr_mask = BIT(sysc_ch->isr_bit);
-	unsigned int chan_mask = BIT(sysc_ch->chan_bit);
-	unsigned int status;
-	unsigned long flags;
-	int ret = 0;
-	int k;
-
-	spin_lock_irqsave(&rcar_sysc_lock, flags);
-
-	iowrite32(isr_mask, rcar_sysc_base + SYSCISCR);
-
-	/* Submit power shutoff or resume request until it was accepted */
-	for (k = 0; k < PWRER_RETRIES; k++) {
-		ret = rcar_sysc_pwr_on_off(sysc_ch, on);
-		if (ret)
-			goto out;
-
-		status = ioread32(rcar_sysc_base +
-				  sysc_ch->chan_offs + PWRER_OFFS);
-		if (!(status & chan_mask))
-			break;
-
-		udelay(PWRER_DELAY_US);
-	}
-
-	if (k == PWRER_RETRIES) {
-		ret = -EIO;
-		goto out;
-	}
-
-	/* Wait until the power shutoff or resume request has completed * */
-	for (k = 0; k < SYSCISR_RETRIES; k++) {
-		if (ioread32(rcar_sysc_base + SYSCISR) & isr_mask)
-			break;
-		udelay(SYSCISR_DELAY_US);
-	}
-
-	if (k == SYSCISR_RETRIES)
-		ret = -EIO;
-
-	iowrite32(isr_mask, rcar_sysc_base + SYSCISCR);
-
- out:
-	spin_unlock_irqrestore(&rcar_sysc_lock, flags);
-
-	pr_debug("sysc power domain %d: %08x -> %d\n",
-		 sysc_ch->isr_bit, ioread32(rcar_sysc_base + SYSCISR), ret);
-	return ret;
-}
-
-int rcar_sysc_power_down(const struct rcar_sysc_ch *sysc_ch)
-{
-	return rcar_sysc_power(sysc_ch, false);
-}
-
-int rcar_sysc_power_up(const struct rcar_sysc_ch *sysc_ch)
-{
-	return rcar_sysc_power(sysc_ch, true);
-}
-
-bool rcar_sysc_power_is_off(const struct rcar_sysc_ch *sysc_ch)
-{
-	unsigned int st;
-
-	st = ioread32(rcar_sysc_base + sysc_ch->chan_offs + PWRSR_OFFS);
-	if (st & BIT(sysc_ch->chan_bit))
-		return true;
-
-	return false;
-}
-
-void __iomem *rcar_sysc_init(phys_addr_t base)
-{
-	rcar_sysc_base = ioremap_nocache(base, PAGE_SIZE);
-	if (!rcar_sysc_base)
-		panic("unable to ioremap R-Car SYSC hardware block\n");
-
-	return rcar_sysc_base;
-}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-shmobile/pm-rcar-gen2.c linux-libre-4.7-gnu/arch/arm/mach-shmobile/pm-rcar-gen2.c
--- linux-libre-4.6-gnu/arch/arm/mach-shmobile/pm-rcar-gen2.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-shmobile/pm-rcar-gen2.c	2016-07-24 15:23:50.000000000 -0400
@@ -13,9 +13,9 @@
 #include <linux/kernel.h>
 #include <linux/of.h>
 #include <linux/smp.h>
+#include <linux/soc/renesas/rcar-sysc.h>
 #include <asm/io.h>
 #include "common.h"
-#include "pm-rcar.h"
 #include "rcar-gen2.h"
 
 /* RST */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-shmobile/pm-rcar.h linux-libre-4.7-gnu/arch/arm/mach-shmobile/pm-rcar.h
--- linux-libre-4.6-gnu/arch/arm/mach-shmobile/pm-rcar.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-shmobile/pm-rcar.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,15 +0,0 @@
-#ifndef PM_RCAR_H
-#define PM_RCAR_H
-
-struct rcar_sysc_ch {
-	u16 chan_offs;
-	u8 chan_bit;
-	u8 isr_bit;
-};
-
-int rcar_sysc_power_down(const struct rcar_sysc_ch *sysc_ch);
-int rcar_sysc_power_up(const struct rcar_sysc_ch *sysc_ch);
-bool rcar_sysc_power_is_off(const struct rcar_sysc_ch *sysc_ch);
-void __iomem *rcar_sysc_init(phys_addr_t base);
-
-#endif /* PM_RCAR_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-shmobile/smp-r8a7779.c linux-libre-4.7-gnu/arch/arm/mach-shmobile/smp-r8a7779.c
--- linux-libre-4.6-gnu/arch/arm/mach-shmobile/smp-r8a7779.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-shmobile/smp-r8a7779.c	2016-07-24 15:23:50.000000000 -0400
@@ -19,13 +19,13 @@
 #include <linux/spinlock.h>
 #include <linux/io.h>
 #include <linux/delay.h>
+#include <linux/soc/renesas/rcar-sysc.h>
 
 #include <asm/cacheflush.h>
 #include <asm/smp_plat.h>
 #include <asm/smp_scu.h>
 
 #include "common.h"
-#include "pm-rcar.h"
 #include "r8a7779.h"
 
 #define AVECR IOMEM(0xfe700040)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-shmobile/smp-r8a7790.c linux-libre-4.7-gnu/arch/arm/mach-shmobile/smp-r8a7790.c
--- linux-libre-4.6-gnu/arch/arm/mach-shmobile/smp-r8a7790.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-shmobile/smp-r8a7790.c	2016-07-24 15:23:50.000000000 -0400
@@ -17,12 +17,12 @@
 #include <linux/init.h>
 #include <linux/smp.h>
 #include <linux/io.h>
+#include <linux/soc/renesas/rcar-sysc.h>
 
 #include <asm/smp_plat.h>
 
 #include "common.h"
 #include "platsmp-apmu.h"
-#include "pm-rcar.h"
 #include "rcar-gen2.h"
 #include "r8a7790.h"
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-shmobile/timer.c linux-libre-4.7-gnu/arch/arm/mach-shmobile/timer.c
--- linux-libre-4.6-gnu/arch/arm/mach-shmobile/timer.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-shmobile/timer.c	2016-07-24 15:23:50.000000000 -0400
@@ -20,28 +20,9 @@
 
 #include "common.h"
 
-static void __init shmobile_setup_delay_hz(unsigned int max_cpu_core_hz,
-					   unsigned int mult, unsigned int div)
-{
-	/* calculate a worst-case loops-per-jiffy value
-	 * based on maximum cpu core hz setting and the
-	 * __delay() implementation in arch/arm/lib/delay.S
-	 *
-	 * this will result in a longer delay than expected
-	 * when the cpu core runs on lower frequencies.
-	 */
-
-	unsigned int value = HZ * div / mult;
-
-	if (!preset_lpj)
-		preset_lpj = max_cpu_core_hz / value;
-}
-
 void __init shmobile_init_delay(void)
 {
 	struct device_node *np, *cpus;
-	unsigned int div = 0;
-	bool has_arch_timer = false;
 	u32 max_freq = 0;
 
 	cpus = of_find_node_by_path("/cpus");
@@ -51,25 +32,32 @@ void __init shmobile_init_delay(void)
 	for_each_child_of_node(cpus, np) {
 		u32 freq;
 
+		if (IS_ENABLED(CONFIG_ARM_ARCH_TIMER) &&
+		    (of_device_is_compatible(np, "arm,cortex-a7") ||
+		     of_device_is_compatible(np, "arm,cortex-a15"))) {
+			of_node_put(np);
+			of_node_put(cpus);
+			return;
+		}
+
 		if (!of_property_read_u32(np, "clock-frequency", &freq))
 			max_freq = max(max_freq, freq);
-
-		if (of_device_is_compatible(np, "arm,cortex-a8")) {
-			div = 2;
-		} else if (of_device_is_compatible(np, "arm,cortex-a9")) {
-			div = 1;
-		} else if (of_device_is_compatible(np, "arm,cortex-a7") ||
-			 of_device_is_compatible(np, "arm,cortex-a15")) {
-			div = 1;
-			has_arch_timer = true;
-		}
 	}
 
 	of_node_put(cpus);
 
-	if (!max_freq || !div)
+	if (!max_freq)
 		return;
 
-	if (!has_arch_timer || !IS_ENABLED(CONFIG_ARM_ARCH_TIMER))
-		shmobile_setup_delay_hz(max_freq, 1, div);
+	/*
+	 * Calculate a worst-case loops-per-jiffy value
+	 * based on maximum cpu core hz setting and the
+	 * __delay() implementation in arch/arm/lib/delay.S.
+	 *
+	 * This will result in a longer delay than expected
+	 * when the cpu core runs on lower frequencies.
+	 */
+
+	if (!preset_lpj)
+		preset_lpj = max_freq / HZ;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-socfpga/core.h linux-libre-4.7-gnu/arch/arm/mach-socfpga/core.h
--- linux-libre-4.6-gnu/arch/arm/mach-socfpga/core.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-socfpga/core.h	2016-07-24 15:23:50.000000000 -0400
@@ -38,6 +38,8 @@ extern void socfpga_init_clocks(void);
 extern void socfpga_sysmgr_init(void);
 void socfpga_init_l2_ecc(void);
 void socfpga_init_ocram_ecc(void);
+void socfpga_init_arria10_l2_ecc(void);
+void socfpga_init_arria10_ocram_ecc(void);
 
 extern void __iomem *sys_manager_base_addr;
 extern void __iomem *rst_manager_base_addr;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-socfpga/l2_cache.c linux-libre-4.7-gnu/arch/arm/mach-socfpga/l2_cache.c
--- linux-libre-4.6-gnu/arch/arm/mach-socfpga/l2_cache.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-socfpga/l2_cache.c	2016-07-24 15:23:50.000000000 -0400
@@ -17,6 +17,20 @@
 #include <linux/of_platform.h>
 #include <linux/of_address.h>
 
+#include "core.h"
+
+/* A10 System Manager L2 ECC Control register */
+#define A10_MPU_CTRL_L2_ECC_OFST          0x0
+#define A10_MPU_CTRL_L2_ECC_EN            BIT(0)
+
+/* A10 System Manager Global IRQ Mask register */
+#define A10_SYSMGR_ECC_INTMASK_CLR_OFST   0x98
+#define A10_SYSMGR_ECC_INTMASK_CLR_L2     BIT(0)
+
+/* A10 System Manager L2 ECC IRQ Clear register */
+#define A10_SYSMGR_MPU_CLEAR_L2_ECC_OFST  0xA8
+#define A10_SYSMGR_MPU_CLEAR_L2_ECC       (BIT(31) | BIT(15))
+
 void socfpga_init_l2_ecc(void)
 {
 	struct device_node *np;
@@ -39,3 +53,38 @@ void socfpga_init_l2_ecc(void)
 	writel(0x01, mapped_l2_edac_addr);
 	iounmap(mapped_l2_edac_addr);
 }
+
+void socfpga_init_arria10_l2_ecc(void)
+{
+	struct device_node *np;
+	void __iomem *mapped_l2_edac_addr;
+
+	/* Find the L2 EDAC device tree node */
+	np = of_find_compatible_node(NULL, NULL, "altr,socfpga-a10-l2-ecc");
+	if (!np) {
+		pr_err("Unable to find socfpga-a10-l2-ecc in dtb\n");
+		return;
+	}
+
+	mapped_l2_edac_addr = of_iomap(np, 0);
+	of_node_put(np);
+	if (!mapped_l2_edac_addr) {
+		pr_err("Unable to find L2 ECC mapping in dtb\n");
+		return;
+	}
+
+	if (!sys_manager_base_addr) {
+		pr_err("System Mananger not mapped for L2 ECC\n");
+		goto exit;
+	}
+	/* Clear any pending IRQs */
+	writel(A10_SYSMGR_MPU_CLEAR_L2_ECC, (sys_manager_base_addr +
+	       A10_SYSMGR_MPU_CLEAR_L2_ECC_OFST));
+	/* Enable ECC */
+	writel(A10_SYSMGR_ECC_INTMASK_CLR_L2, sys_manager_base_addr +
+	       A10_SYSMGR_ECC_INTMASK_CLR_OFST);
+	writel(A10_MPU_CTRL_L2_ECC_EN, mapped_l2_edac_addr +
+	       A10_MPU_CTRL_L2_ECC_OFST);
+exit:
+	iounmap(mapped_l2_edac_addr);
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-socfpga/ocram.c linux-libre-4.7-gnu/arch/arm/mach-socfpga/ocram.c
--- linux-libre-4.6-gnu/arch/arm/mach-socfpga/ocram.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-socfpga/ocram.c	2016-07-24 15:23:50.000000000 -0400
@@ -13,12 +13,15 @@
  * You should have received a copy of the GNU General Public License along with
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
+#include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/genalloc.h>
 #include <linux/module.h>
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
 
+#include "core.h"
+
 #define ALTR_OCRAM_CLEAR_ECC          0x00000018
 #define ALTR_OCRAM_ECC_EN             0x00000019
 
@@ -47,3 +50,133 @@ void socfpga_init_ocram_ecc(void)
 
 	iounmap(mapped_ocr_edac_addr);
 }
+
+/* Arria10 OCRAM Section */
+#define ALTR_A10_ECC_CTRL_OFST          0x08
+#define ALTR_A10_OCRAM_ECC_EN_CTL       (BIT(1) | BIT(0))
+#define ALTR_A10_ECC_INITA              BIT(16)
+
+#define ALTR_A10_ECC_INITSTAT_OFST      0x0C
+#define ALTR_A10_ECC_INITCOMPLETEA      BIT(0)
+#define ALTR_A10_ECC_INITCOMPLETEB      BIT(8)
+
+#define ALTR_A10_ECC_ERRINTEN_OFST      0x10
+#define ALTR_A10_ECC_SERRINTEN          BIT(0)
+
+#define ALTR_A10_ECC_INTSTAT_OFST       0x20
+#define ALTR_A10_ECC_SERRPENA           BIT(0)
+#define ALTR_A10_ECC_DERRPENA           BIT(8)
+#define ALTR_A10_ECC_ERRPENA_MASK       (ALTR_A10_ECC_SERRPENA | \
+					 ALTR_A10_ECC_DERRPENA)
+/* ECC Manager Defines */
+#define A10_SYSMGR_ECC_INTMASK_SET_OFST   0x94
+#define A10_SYSMGR_ECC_INTMASK_CLR_OFST   0x98
+#define A10_SYSMGR_ECC_INTMASK_OCRAM      BIT(1)
+
+#define ALTR_A10_ECC_INIT_WATCHDOG_10US   10000
+
+static inline void ecc_set_bits(u32 bit_mask, void __iomem *ioaddr)
+{
+	u32 value = readl(ioaddr);
+
+	value |= bit_mask;
+	writel(value, ioaddr);
+}
+
+static inline void ecc_clear_bits(u32 bit_mask, void __iomem *ioaddr)
+{
+	u32 value = readl(ioaddr);
+
+	value &= ~bit_mask;
+	writel(value, ioaddr);
+}
+
+static inline int ecc_test_bits(u32 bit_mask, void __iomem *ioaddr)
+{
+	u32 value = readl(ioaddr);
+
+	return (value & bit_mask) ? 1 : 0;
+}
+
+/*
+ * This function uses the memory initialization block in the Arria10 ECC
+ * controller to initialize/clear the entire memory data and ECC data.
+ */
+static int altr_init_memory_port(void __iomem *ioaddr)
+{
+	int limit = ALTR_A10_ECC_INIT_WATCHDOG_10US;
+
+	ecc_set_bits(ALTR_A10_ECC_INITA, (ioaddr + ALTR_A10_ECC_CTRL_OFST));
+	while (limit--) {
+		if (ecc_test_bits(ALTR_A10_ECC_INITCOMPLETEA,
+				  (ioaddr + ALTR_A10_ECC_INITSTAT_OFST)))
+			break;
+		udelay(1);
+	}
+	if (limit < 0)
+		return -EBUSY;
+
+	/* Clear any pending ECC interrupts */
+	writel(ALTR_A10_ECC_ERRPENA_MASK,
+	       (ioaddr + ALTR_A10_ECC_INTSTAT_OFST));
+
+	return 0;
+}
+
+void socfpga_init_arria10_ocram_ecc(void)
+{
+	struct device_node *np;
+	int ret = 0;
+	void __iomem *ecc_block_base;
+
+	if (!sys_manager_base_addr) {
+		pr_err("SOCFPGA: sys-mgr is not initialized\n");
+		return;
+	}
+
+	/* Find the OCRAM EDAC device tree node */
+	np = of_find_compatible_node(NULL, NULL, "altr,socfpga-a10-ocram-ecc");
+	if (!np) {
+		pr_err("Unable to find socfpga-a10-ocram-ecc\n");
+		return;
+	}
+
+	/* Map the ECC Block */
+	ecc_block_base = of_iomap(np, 0);
+	of_node_put(np);
+	if (!ecc_block_base) {
+		pr_err("Unable to map OCRAM ECC block\n");
+		return;
+	}
+
+	/* Disable ECC */
+	writel(ALTR_A10_OCRAM_ECC_EN_CTL,
+	       sys_manager_base_addr + A10_SYSMGR_ECC_INTMASK_SET_OFST);
+	ecc_clear_bits(ALTR_A10_ECC_SERRINTEN,
+		       (ecc_block_base + ALTR_A10_ECC_ERRINTEN_OFST));
+	ecc_clear_bits(ALTR_A10_OCRAM_ECC_EN_CTL,
+		       (ecc_block_base + ALTR_A10_ECC_CTRL_OFST));
+
+	/* Ensure all writes complete */
+	wmb();
+
+	/* Use HW initialization block to initialize memory for ECC */
+	ret = altr_init_memory_port(ecc_block_base);
+	if (ret) {
+		pr_err("ECC: cannot init OCRAM PORTA memory\n");
+		goto exit;
+	}
+
+	/* Enable ECC */
+	ecc_set_bits(ALTR_A10_OCRAM_ECC_EN_CTL,
+		     (ecc_block_base + ALTR_A10_ECC_CTRL_OFST));
+	ecc_set_bits(ALTR_A10_ECC_SERRINTEN,
+		     (ecc_block_base + ALTR_A10_ECC_ERRINTEN_OFST));
+	writel(ALTR_A10_OCRAM_ECC_EN_CTL,
+	       sys_manager_base_addr + A10_SYSMGR_ECC_INTMASK_CLR_OFST);
+
+	/* Ensure all writes complete */
+	wmb();
+exit:
+	iounmap(ecc_block_base);
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-socfpga/socfpga.c linux-libre-4.7-gnu/arch/arm/mach-socfpga/socfpga.c
--- linux-libre-4.6-gnu/arch/arm/mach-socfpga/socfpga.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-socfpga/socfpga.c	2016-07-24 15:23:50.000000000 -0400
@@ -66,6 +66,16 @@ static void __init socfpga_init_irq(void
 		socfpga_init_ocram_ecc();
 }
 
+static void __init socfpga_arria10_init_irq(void)
+{
+	irqchip_init();
+	socfpga_sysmgr_init();
+	if (IS_ENABLED(CONFIG_EDAC_ALTERA_L2C))
+		socfpga_init_arria10_l2_ecc();
+	if (IS_ENABLED(CONFIG_EDAC_ALTERA_OCRAM))
+		socfpga_init_arria10_ocram_ecc();
+}
+
 static void socfpga_cyclone5_restart(enum reboot_mode mode, const char *cmd)
 {
 	u32 temp;
@@ -113,7 +123,7 @@ static const char *altera_a10_dt_match[]
 DT_MACHINE_START(SOCFPGA_A10, "Altera SOCFPGA Arria10")
 	.l2c_aux_val	= 0,
 	.l2c_aux_mask	= ~0,
-	.init_irq	= socfpga_init_irq,
+	.init_irq	= socfpga_arria10_init_irq,
 	.restart	= socfpga_arria10_restart,
 	.dt_compat	= altera_a10_dt_match,
 MACHINE_END
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-sti/Kconfig linux-libre-4.7-gnu/arch/arm/mach-sti/Kconfig
--- linux-libre-4.6-gnu/arch/arm/mach-sti/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-sti/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -18,11 +18,10 @@ menuconfig ARCH_STI
 	select PL310_ERRATA_769419 if CACHE_L2X0
 	select RESET_CONTROLLER
 	help
-	  Include support for STiH41x SOCs like STiH415/416 using the device tree
-	  for discovery
-	  More information at Documentation/arm/STiH41x and
-	  at Documentation/devicetree
-
+	  Include support for STMicroelectronics' STiH415/416, STiH407/10 and
+	  STiH418 family SoCs using the Device Tree for discovery.  More
+	  information can be found in Documentation/arm/sti/ and
+	  Documentation/devicetree.
 
 if ARCH_STI
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-sunxi/sunxi.c linux-libre-4.7-gnu/arch/arm/mach-sunxi/sunxi.c
--- linux-libre-4.6-gnu/arch/arm/mach-sunxi/sunxi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-sunxi/sunxi.c	2016-07-24 15:23:50.000000000 -0400
@@ -17,11 +17,6 @@
 
 #include <asm/mach/arch.h>
 
-static void __init sunxi_dt_cpufreq_init(void)
-{
-	platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
-}
-
 static const char * const sunxi_board_dt_compat[] = {
 	"allwinner,sun4i-a10",
 	"allwinner,sun5i-a10s",
@@ -32,7 +27,6 @@ static const char * const sunxi_board_dt
 
 DT_MACHINE_START(SUNXI_DT, "Allwinner sun4i/sun5i Families")
 	.dt_compat	= sunxi_board_dt_compat,
-	.init_late	= sunxi_dt_cpufreq_init,
 MACHINE_END
 
 static const char * const sun6i_board_dt_compat[] = {
@@ -53,7 +47,6 @@ static void __init sun6i_timer_init(void
 DT_MACHINE_START(SUN6I_DT, "Allwinner sun6i (A31) Family")
 	.init_time	= sun6i_timer_init,
 	.dt_compat	= sun6i_board_dt_compat,
-	.init_late	= sunxi_dt_cpufreq_init,
 MACHINE_END
 
 static const char * const sun7i_board_dt_compat[] = {
@@ -63,7 +56,6 @@ static const char * const sun7i_board_dt
 
 DT_MACHINE_START(SUN7I_DT, "Allwinner sun7i (A20) Family")
 	.dt_compat	= sun7i_board_dt_compat,
-	.init_late	= sunxi_dt_cpufreq_init,
 MACHINE_END
 
 static const char * const sun8i_board_dt_compat[] = {
@@ -77,7 +69,6 @@ static const char * const sun8i_board_dt
 DT_MACHINE_START(SUN8I_DT, "Allwinner sun8i Family")
 	.init_time	= sun6i_timer_init,
 	.dt_compat	= sun8i_board_dt_compat,
-	.init_late	= sunxi_dt_cpufreq_init,
 MACHINE_END
 
 static const char * const sun9i_board_dt_compat[] = {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-tegra/board-paz00.c linux-libre-4.7-gnu/arch/arm/mach-tegra/board-paz00.c
--- linux-libre-4.6-gnu/arch/arm/mach-tegra/board-paz00.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-tegra/board-paz00.c	2016-07-24 15:23:50.000000000 -0400
@@ -29,10 +29,6 @@ static struct property_entry __initdata
 	{ },
 };
 
-static struct property_set __initdata wifi_rfkill_pset = {
-	.properties = wifi_rfkill_prop,
-};
-
 static struct platform_device wifi_rfkill_device = {
 	.name	= "rfkill_gpio",
 	.id	= -1,
@@ -49,7 +45,7 @@ static struct gpiod_lookup_table wifi_gp
 
 void __init tegra_paz00_wifikill_init(void)
 {
-	platform_device_add_properties(&wifi_rfkill_device, &wifi_rfkill_pset);
+	platform_device_add_properties(&wifi_rfkill_device, wifi_rfkill_prop);
 	gpiod_add_lookup_table(&wifi_gpio_lookup);
 	platform_device_register(&wifi_rfkill_device);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-tegra/platsmp.c linux-libre-4.7-gnu/arch/arm/mach-tegra/platsmp.c
--- linux-libre-4.6-gnu/arch/arm/mach-tegra/platsmp.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-tegra/platsmp.c	2016-07-24 15:23:50.000000000 -0400
@@ -108,19 +108,9 @@ static int tegra30_boot_secondary(unsign
 	 * be un-gated by un-toggling the power gate register
 	 * manually.
 	 */
-	if (!tegra_pmc_cpu_is_powered(cpu)) {
-		ret = tegra_pmc_cpu_power_on(cpu);
-		if (ret)
-			return ret;
-
-		/* Wait for the power to come up. */
-		timeout = jiffies + msecs_to_jiffies(100);
-		while (!tegra_pmc_cpu_is_powered(cpu)) {
-			if (time_after(jiffies, timeout))
-				return -ETIMEDOUT;
-			udelay(10);
-		}
-	}
+	ret = tegra_pmc_cpu_power_on(cpu);
+	if (ret)
+		return ret;
 
 remove_clamps:
 	/* CPU partition is powered. Enable the CPU clock. */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-uniphier/platsmp.c linux-libre-4.7-gnu/arch/arm/mach-uniphier/platsmp.c
--- linux-libre-4.6-gnu/arch/arm/mach-uniphier/platsmp.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-uniphier/platsmp.c	2016-07-24 15:23:50.000000000 -0400
@@ -99,16 +99,16 @@ static int __init uniphier_smp_prepare_t
 	int ret;
 
 	np = of_find_compatible_node(NULL, NULL, "socionext,uniphier-smpctrl");
-	of_node_put(np);
 	ret = of_address_to_resource(np, 0, &res);
+	of_node_put(np);
 	if (!ret) {
 		rom_rsv2_phys = res.start + UNIPHIER_SMPCTRL_ROM_RSV2;
 	} else {
 		/* try old binding too */
 		np = of_find_compatible_node(NULL, NULL,
 					     "socionext,uniphier-system-bus-controller");
-		of_node_put(np);
 		ret = of_address_to_resource(np, 1, &res);
+		of_node_put(np);
 		if (ret) {
 			pr_err("failed to get resource of SMP control\n");
 			return ret;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-versatile/versatile_dt.c linux-libre-4.7-gnu/arch/arm/mach-versatile/versatile_dt.c
--- linux-libre-4.6-gnu/arch/arm/mach-versatile/versatile_dt.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-versatile/versatile_dt.c	2016-07-24 15:23:50.000000000 -0400
@@ -32,7 +32,6 @@
 #include <linux/amba/clcd.h>
 #include <linux/platform_data/video-clcd-versatile.h>
 #include <linux/amba/mmci.h>
-#include <linux/mtd/physmap.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -42,27 +41,15 @@
 #define __io_address(n)		((void __iomem __force *)IO_ADDRESS(n))
 
 /*
- * Memory definitions
- */
-#define VERSATILE_FLASH_BASE           0x34000000
-#define VERSATILE_FLASH_SIZE           SZ_64M
-
-/*
  * ------------------------------------------------------------------------
  *  Versatile Registers
  * ------------------------------------------------------------------------
  */
 #define VERSATILE_SYS_PCICTL_OFFSET           0x44
 #define VERSATILE_SYS_MCI_OFFSET              0x48
-#define VERSATILE_SYS_FLASH_OFFSET            0x4C
 #define VERSATILE_SYS_CLCD_OFFSET             0x50
 
 /*
- * VERSATILE_SYS_FLASH
- */
-#define VERSATILE_FLASHPROG_FLVPPEN	(1 << 0)	/* Enable writing to flash */
-
-/*
  * VERSATILE peripheral addresses
  */
 #define VERSATILE_MMCI0_BASE           0x10005000	/* MMC interface */
@@ -86,39 +73,6 @@
 static void __iomem *versatile_sys_base;
 static void __iomem *versatile_ib2_ctrl;
 
-static void versatile_flash_set_vpp(struct platform_device *pdev, int on)
-{
-	u32 val;
-
-	val = readl(versatile_sys_base + VERSATILE_SYS_FLASH_OFFSET);
-	if (on)
-		val |= VERSATILE_FLASHPROG_FLVPPEN;
-	else
-		val &= ~VERSATILE_FLASHPROG_FLVPPEN;
-	writel(val, versatile_sys_base + VERSATILE_SYS_FLASH_OFFSET);
-}
-
-static struct physmap_flash_data versatile_flash_data = {
-	.width			= 4,
-	.set_vpp		= versatile_flash_set_vpp,
-};
-
-static struct resource versatile_flash_resource = {
-	.start			= VERSATILE_FLASH_BASE,
-	.end			= VERSATILE_FLASH_BASE + VERSATILE_FLASH_SIZE - 1,
-	.flags			= IORESOURCE_MEM,
-};
-
-struct platform_device versatile_flash_device = {
-	.name			= "physmap-flash",
-	.id			= 0,
-	.dev			= {
-		.platform_data	= &versatile_flash_data,
-	},
-	.num_resources		= 1,
-	.resource		= &versatile_flash_resource,
-};
-
 unsigned int mmc_status(struct device *dev)
 {
 	struct amba_device *adev = container_of(dev, struct amba_device, dev);
@@ -390,7 +344,6 @@ static void __init versatile_dt_init(voi
 
 	versatile_dt_pci_init();
 
-	platform_device_register(&versatile_flash_device);
 	of_platform_populate(NULL, of_default_bus_match_table,
 			     versatile_auxdata_lookup, NULL);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-vexpress/Makefile linux-libre-4.7-gnu/arch/arm/mach-vexpress/Makefile
--- linux-libre-4.6-gnu/arch/arm/mach-vexpress/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-vexpress/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -4,7 +4,7 @@
 ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := \
 	-I$(srctree)/arch/arm/plat-versatile/include
 
-obj-y					:= v2m.o
+obj-$(CONFIG_ARCH_VEXPRESS)		:= v2m.o
 obj-$(CONFIG_ARCH_VEXPRESS_DCSCB)	+= dcscb.o	dcscb_setup.o
 CFLAGS_dcscb.o				+= -march=armv7-a
 CFLAGS_REMOVE_dcscb.o			= -pg
@@ -15,3 +15,5 @@ CFLAGS_tc2_pm.o				+= -march=armv7-a
 CFLAGS_REMOVE_tc2_pm.o			= -pg
 obj-$(CONFIG_SMP)			+= platsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)		+= hotplug.o
+
+obj-$(CONFIG_ARCH_MPS2)			+= v2m-mps2.o
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-vexpress/Makefile.boot linux-libre-4.7-gnu/arch/arm/mach-vexpress/Makefile.boot
--- linux-libre-4.6-gnu/arch/arm/mach-vexpress/Makefile.boot	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/mach-vexpress/Makefile.boot	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,3 @@
+# Empty file waiting for deletion once Makefile.boot isn't needed any more.
+# Patch waits for application at
+# http://www.arm.linux.org.uk/developer/patches/viewpatch.php?id=7889/1 .
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-vexpress/spc.c linux-libre-4.7-gnu/arch/arm/mach-vexpress/spc.c
--- linux-libre-4.6-gnu/arch/arm/mach-vexpress/spc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-vexpress/spc.c	2016-07-24 15:23:50.000000000 -0400
@@ -547,7 +547,7 @@ static struct clk *ve_spc_clk_register(s
 
 	init.name = dev_name(cpu_dev);
 	init.ops = &clk_spc_ops;
-	init.flags = CLK_IS_ROOT | CLK_GET_RATE_NOCACHE;
+	init.flags = CLK_GET_RATE_NOCACHE;
 	init.num_parents = 0;
 
 	return devm_clk_register(cpu_dev, &spc->hw);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-vexpress/v2m-mps2.c linux-libre-4.7-gnu/arch/arm/mach-vexpress/v2m-mps2.c
--- linux-libre-4.6-gnu/arch/arm/mach-vexpress/v2m-mps2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm/mach-vexpress/v2m-mps2.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2015 ARM Limited
+ *
+ * Author: Vladimir Murzin <vladimir.murzin@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <asm/mach/arch.h>
+
+static const char *const mps2_compat[] __initconst = {
+	"arm,mps2",
+	NULL
+};
+
+DT_MACHINE_START(MPS2DT, "MPS2 (Device Tree Support)")
+	.dt_compat = mps2_compat,
+MACHINE_END
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mach-zynq/common.c linux-libre-4.7-gnu/arch/arm/mach-zynq/common.c
--- linux-libre-4.6-gnu/arch/arm/mach-zynq/common.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mach-zynq/common.c	2016-07-24 15:23:50.000000000 -0400
@@ -110,7 +110,6 @@ static void __init zynq_init_late(void)
  */
 static void __init zynq_init_machine(void)
 {
-	struct platform_device_info devinfo = { .name = "cpufreq-dt", };
 	struct soc_device_attribute *soc_dev_attr;
 	struct soc_device *soc_dev;
 	struct device *parent = NULL;
@@ -145,7 +144,6 @@ out:
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, parent);
 
 	platform_device_register(&zynq_cpuidle_device);
-	platform_device_register_full(&devinfo);
 }
 
 static void __init zynq_timer_init(void)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/Makefile linux-libre-4.7-gnu/arch/arm/Makefile
--- linux-libre-4.6-gnu/arch/arm/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -183,6 +183,7 @@ machine-$(CONFIG_ARCH_LPC18XX)		+= lpc18
 machine-$(CONFIG_ARCH_LPC32XX)		+= lpc32xx
 machine-$(CONFIG_ARCH_MESON)		+= meson
 machine-$(CONFIG_ARCH_MMP)		+= mmp
+machine-$(CONFIG_ARCH_MPS2)		+= vexpress
 machine-$(CONFIG_ARCH_MOXART)		+= moxart
 machine-$(CONFIG_ARCH_MV78XX0)		+= mv78xx0
 machine-$(CONFIG_ARCH_MVEBU)		+= mvebu
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mm/cache-l2x0.c linux-libre-4.7-gnu/arch/arm/mm/cache-l2x0.c
--- linux-libre-4.6-gnu/arch/arm/mm/cache-l2x0.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mm/cache-l2x0.c	2016-07-24 15:23:50.000000000 -0400
@@ -647,11 +647,6 @@ static void __init l2c310_enable(void __
 		aux &= ~(L310_AUX_CTRL_FULL_LINE_ZERO | L310_AUX_CTRL_EARLY_BRESP);
 	}
 
-	/* r3p0 or later has power control register */
-	if (rev >= L310_CACHE_ID_RTL_R3P0)
-		l2x0_saved_regs.pwr_ctrl = L310_DYNAMIC_CLK_GATING_EN |
-						L310_STNDBY_MODE_EN;
-
 	/*
 	 * Always enable non-secure access to the lockdown registers -
 	 * we write to them as part of the L2C enable sequence so they
@@ -1141,6 +1136,7 @@ static void __init l2c310_of_parse(const
 	u32 filter[2] = { 0, 0 };
 	u32 assoc;
 	u32 prefetch;
+	u32 power;
 	u32 val;
 	int ret;
 
@@ -1271,6 +1267,26 @@ static void __init l2c310_of_parse(const
 	}
 
 	l2x0_saved_regs.prefetch_ctrl = prefetch;
+
+	power = l2x0_saved_regs.pwr_ctrl |
+		L310_DYNAMIC_CLK_GATING_EN | L310_STNDBY_MODE_EN;
+
+	ret = of_property_read_u32(np, "arm,dynamic-clock-gating", &val);
+	if (!ret) {
+		if (!val)
+			power &= ~L310_DYNAMIC_CLK_GATING_EN;
+	} else if (ret != -EINVAL) {
+		pr_err("L2C-310 OF dynamic-clock-gating property value is missing or invalid\n");
+	}
+	ret = of_property_read_u32(np, "arm,standby-mode", &val);
+	if (!ret) {
+		if (!val)
+			power &= ~L310_STNDBY_MODE_EN;
+	} else if (ret != -EINVAL) {
+		pr_err("L2C-310 OF standby-mode property value is missing or invalid\n");
+	}
+
+	l2x0_saved_regs.pwr_ctrl = power;
 }
 
 static const struct l2c_init_data of_l2c310_data __initconst = {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mm/cache-uniphier.c linux-libre-4.7-gnu/arch/arm/mm/cache-uniphier.c
--- linux-libre-4.6-gnu/arch/arm/mm/cache-uniphier.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mm/cache-uniphier.c	2016-07-24 15:23:50.000000000 -0400
@@ -96,6 +96,7 @@ struct uniphier_cache_data {
 	void __iomem *ctrl_base;
 	void __iomem *rev_base;
 	void __iomem *op_base;
+	void __iomem *way_ctrl_base;
 	u32 way_present_mask;
 	u32 way_locked_mask;
 	u32 nsets;
@@ -256,10 +257,13 @@ static void __init __uniphier_cache_set_
 					struct uniphier_cache_data *data,
 					u32 way_mask)
 {
+	unsigned int cpu;
+
 	data->way_locked_mask = way_mask & data->way_present_mask;
 
-	writel_relaxed(~data->way_locked_mask & data->way_present_mask,
-		       data->ctrl_base + UNIPHIER_SSCLPDAWCR);
+	for_each_possible_cpu(cpu)
+		writel_relaxed(~data->way_locked_mask & data->way_present_mask,
+			       data->way_ctrl_base + 4 * cpu);
 }
 
 static void uniphier_cache_maint_range(unsigned long start, unsigned long end,
@@ -459,6 +463,8 @@ static int __init __uniphier_cache_init(
 		goto err;
 	}
 
+	data->way_ctrl_base = data->ctrl_base + 0xc00;
+
 	if (*cache_level == 2) {
 		u32 revision = readl(data->rev_base + UNIPHIER_SSCID);
 		/*
@@ -467,6 +473,22 @@ static int __init __uniphier_cache_init(
 		 */
 		if (revision <= 0x16)
 			data->range_op_max_size = (u32)1 << 22;
+
+		/*
+		 * Unfortunatly, the offset address of active way control base
+		 * varies from SoC to SoC.
+		 */
+		switch (revision) {
+		case 0x11:	/* sLD3 */
+			data->way_ctrl_base = data->ctrl_base + 0x870;
+			break;
+		case 0x12:	/* LD4 */
+		case 0x16:	/* sld8 */
+			data->way_ctrl_base = data->ctrl_base + 0x840;
+			break;
+		default:
+			break;
+		}
 	}
 
 	data->range_op_max_size -= data->line_size;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mm/dma-mapping.c linux-libre-4.7-gnu/arch/arm/mm/dma-mapping.c
--- linux-libre-4.6-gnu/arch/arm/mm/dma-mapping.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mm/dma-mapping.c	2016-07-24 15:23:50.000000000 -0400
@@ -190,7 +190,6 @@ struct dma_map_ops arm_dma_ops = {
 	.sync_single_for_device	= arm_dma_sync_single_for_device,
 	.sync_sg_for_cpu	= arm_dma_sync_sg_for_cpu,
 	.sync_sg_for_device	= arm_dma_sync_sg_for_device,
-	.set_dma_mask		= arm_dma_set_mask,
 };
 EXPORT_SYMBOL(arm_dma_ops);
 
@@ -209,7 +208,6 @@ struct dma_map_ops arm_coherent_dma_ops
 	.get_sgtable		= arm_dma_get_sgtable,
 	.map_page		= arm_coherent_dma_map_page,
 	.map_sg			= arm_dma_map_sg,
-	.set_dma_mask		= arm_dma_set_mask,
 };
 EXPORT_SYMBOL(arm_coherent_dma_ops);
 
@@ -1143,16 +1141,6 @@ int dma_supported(struct device *dev, u6
 }
 EXPORT_SYMBOL(dma_supported);
 
-int arm_dma_set_mask(struct device *dev, u64 dma_mask)
-{
-	if (!dev->dma_mask || !dma_supported(dev, dma_mask))
-		return -EIO;
-
-	*dev->dma_mask = dma_mask;
-
-	return 0;
-}
-
 #define PREALLOC_DMA_DEBUG_ENTRIES	4096
 
 static int __init dma_debug_do_init(void)
@@ -2006,8 +1994,6 @@ struct dma_map_ops iommu_ops = {
 	.unmap_sg		= arm_iommu_unmap_sg,
 	.sync_sg_for_cpu	= arm_iommu_sync_sg_for_cpu,
 	.sync_sg_for_device	= arm_iommu_sync_sg_for_device,
-
-	.set_dma_mask		= arm_dma_set_mask,
 };
 
 struct dma_map_ops iommu_coherent_ops = {
@@ -2021,8 +2007,6 @@ struct dma_map_ops iommu_coherent_ops =
 
 	.map_sg		= arm_coherent_iommu_map_sg,
 	.unmap_sg	= arm_coherent_iommu_unmap_sg,
-
-	.set_dma_mask	= arm_dma_set_mask,
 };
 
 /**
@@ -2215,7 +2199,7 @@ static struct dma_map_ops *arm_get_iommu
 }
 
 static bool arm_setup_iommu_dma_ops(struct device *dev, u64 dma_base, u64 size,
-				    struct iommu_ops *iommu)
+				    const struct iommu_ops *iommu)
 {
 	struct dma_iommu_mapping *mapping;
 
@@ -2253,7 +2237,7 @@ static void arm_teardown_iommu_dma_ops(s
 #else
 
 static bool arm_setup_iommu_dma_ops(struct device *dev, u64 dma_base, u64 size,
-				    struct iommu_ops *iommu)
+				    const struct iommu_ops *iommu)
 {
 	return false;
 }
@@ -2270,7 +2254,7 @@ static struct dma_map_ops *arm_get_dma_m
 }
 
 void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
-			struct iommu_ops *iommu, bool coherent)
+			const struct iommu_ops *iommu, bool coherent)
 {
 	struct dma_map_ops *dma_ops;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mm/idmap.c linux-libre-4.7-gnu/arch/arm/mm/idmap.c
--- linux-libre-4.6-gnu/arch/arm/mm/idmap.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mm/idmap.c	2016-07-24 15:23:50.000000000 -0400
@@ -15,7 +15,7 @@
  * page tables.
  */
 pgd_t *idmap_pgd;
-unsigned long (*arch_virt_to_idmap)(unsigned long x);
+long long arch_phys_to_idmap_offset;
 
 #ifdef CONFIG_ARM_LPAE
 static void idmap_add_pmd(pud_t *pud, unsigned long addr, unsigned long end,
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mm/ioremap.c linux-libre-4.7-gnu/arch/arm/mm/ioremap.c
--- linux-libre-4.6-gnu/arch/arm/mm/ioremap.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mm/ioremap.c	2016-07-24 15:23:50.000000000 -0400
@@ -297,9 +297,10 @@ static void __iomem * __arm_ioremap_pfn_
 	}
 
 	/*
-	 * Don't allow RAM to be mapped - this causes problems with ARMv6+
+	 * Don't allow RAM to be mapped with mismatched attributes - this
+	 * causes problems with ARMv6+
 	 */
-	if (WARN_ON(pfn_valid(pfn)))
+	if (WARN_ON(pfn_valid(pfn) && mtype != MT_MEMORY_RW))
 		return NULL;
 
 	area = get_vm_area_caller(size, VM_IOREMAP, caller);
@@ -380,11 +381,15 @@ void __iomem *ioremap(resource_size_t re
 EXPORT_SYMBOL(ioremap);
 
 void __iomem *ioremap_cache(resource_size_t res_cookie, size_t size)
+	__alias(ioremap_cached);
+
+void __iomem *ioremap_cached(resource_size_t res_cookie, size_t size)
 {
 	return arch_ioremap_caller(res_cookie, size, MT_DEVICE_CACHED,
 				   __builtin_return_address(0));
 }
 EXPORT_SYMBOL(ioremap_cache);
+EXPORT_SYMBOL(ioremap_cached);
 
 void __iomem *ioremap_wc(resource_size_t res_cookie, size_t size)
 {
@@ -414,6 +419,13 @@ __arm_ioremap_exec(phys_addr_t phys_addr
 			__builtin_return_address(0));
 }
 
+void *arch_memremap_wb(phys_addr_t phys_addr, size_t size)
+{
+	return (__force void *)arch_ioremap_caller(phys_addr, size,
+						   MT_MEMORY_RW,
+						   __builtin_return_address(0));
+}
+
 void __iounmap(volatile void __iomem *io_addr)
 {
 	void *addr = (void *)(PAGE_MASK & (unsigned long)io_addr);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mm/Kconfig linux-libre-4.7-gnu/arch/arm/mm/Kconfig
--- linux-libre-4.6-gnu/arch/arm/mm/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mm/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -421,18 +421,21 @@ config CPU_32v3
 	select CPU_USE_DOMAINS if MMU
 	select NEED_KUSER_HELPERS
 	select TLS_REG_EMUL if SMP || !MMU
+	select CPU_NO_EFFICIENT_FFS
 
 config CPU_32v4
 	bool
 	select CPU_USE_DOMAINS if MMU
 	select NEED_KUSER_HELPERS
 	select TLS_REG_EMUL if SMP || !MMU
+	select CPU_NO_EFFICIENT_FFS
 
 config CPU_32v4T
 	bool
 	select CPU_USE_DOMAINS if MMU
 	select NEED_KUSER_HELPERS
 	select TLS_REG_EMUL if SMP || !MMU
+	select CPU_NO_EFFICIENT_FFS
 
 config CPU_32v5
 	bool
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/mm/nommu.c linux-libre-4.7-gnu/arch/arm/mm/nommu.c
--- linux-libre-4.6-gnu/arch/arm/mm/nommu.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/mm/nommu.c	2016-07-24 15:23:50.000000000 -0400
@@ -368,11 +368,15 @@ void __iomem *ioremap(resource_size_t re
 EXPORT_SYMBOL(ioremap);
 
 void __iomem *ioremap_cache(resource_size_t res_cookie, size_t size)
+	__alias(ioremap_cached);
+
+void __iomem *ioremap_cached(resource_size_t res_cookie, size_t size)
 {
 	return __arm_ioremap_caller(res_cookie, size, MT_DEVICE_CACHED,
 				    __builtin_return_address(0));
 }
 EXPORT_SYMBOL(ioremap_cache);
+EXPORT_SYMBOL(ioremap_cached);
 
 void __iomem *ioremap_wc(resource_size_t res_cookie, size_t size)
 {
@@ -381,6 +385,11 @@ void __iomem *ioremap_wc(resource_size_t
 }
 EXPORT_SYMBOL(ioremap_wc);
 
+void *arch_memremap_wb(phys_addr_t phys_addr, size_t size)
+{
+	return (void *)phys_addr;
+}
+
 void __iounmap(volatile void __iomem *addr)
 {
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/plat-samsung/devs.c linux-libre-4.7-gnu/arch/arm/plat-samsung/devs.c
--- linux-libre-4.6-gnu/arch/arm/plat-samsung/devs.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/plat-samsung/devs.c	2016-07-24 15:23:50.000000000 -0400
@@ -68,7 +68,7 @@
 #include <linux/platform_data/asoc-s3c.h>
 #include <linux/platform_data/spi-s3c64xx.h>
 
-static u64 samsung_device_dma_mask = DMA_BIT_MASK(32);
+#define samsung_device_dma_mask (*((u64[]) { DMA_BIT_MASK(32) }))
 
 /* AC97 */
 #ifdef CONFIG_CPU_S3C2440
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/plat-samsung/include/plat/map-s5p.h linux-libre-4.7-gnu/arch/arm/plat-samsung/include/plat/map-s5p.h
--- linux-libre-4.6-gnu/arch/arm/plat-samsung/include/plat/map-s5p.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/plat-samsung/include/plat/map-s5p.h	2016-07-24 15:23:50.000000000 -0400
@@ -18,7 +18,6 @@
 
 #define S5P_VA_DMC0		S3C_ADDR(0x02440000)
 #define S5P_VA_DMC1		S3C_ADDR(0x02480000)
-#define S5P_VA_SROMC		S3C_ADDR(0x024C0000)
 
 #define S5P_VA_COREPERI_BASE	S3C_ADDR(0x02800000)
 #define S5P_VA_COREPERI(x)	(S5P_VA_COREPERI_BASE + (x))
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/tools/Makefile linux-libre-4.7-gnu/arch/arm/tools/Makefile
--- linux-libre-4.6-gnu/arch/arm/tools/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/tools/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -4,7 +4,10 @@
 # Copyright (C) 2001 Russell King
 #
 
-include/generated/mach-types.h: $(src)/gen-mach-types $(src)/mach-types
-	@$(kecho) '  Generating $@'
-	@mkdir -p $(dir $@)
-	$(Q)$(AWK) -f $^ > $@ || { rm -f $@; /bin/false; }
+quiet_cmd_gen_mach = GEN     $@
+      cmd_gen_mach = mkdir -p $(dir $@) && \
+		     $(AWK) -f $(filter-out $(PHONY),$^) > $@ || \
+		     { rm -f $@; /bin/false; }
+
+include/generated/mach-types.h: $(src)/gen-mach-types $(src)/mach-types FORCE
+	$(call if_changed,gen_mach)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/vdso/Makefile linux-libre-4.7-gnu/arch/arm/vdso/Makefile
--- linux-libre-4.6-gnu/arch/arm/vdso/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/vdso/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -74,5 +74,5 @@ $(MODLIB)/vdso: FORCE
 	@mkdir -p $(MODLIB)/vdso
 
 PHONY += vdso_install
-vdso_install: $(obj)/vdso.so.dbg $(MODLIB)/vdso FORCE
+vdso_install: $(obj)/vdso.so.dbg $(MODLIB)/vdso
 	$(call cmd,vdso_install)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm/vfp/vfpmodule.c linux-libre-4.7-gnu/arch/arm/vfp/vfpmodule.c
--- linux-libre-4.6-gnu/arch/arm/vfp/vfpmodule.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm/vfp/vfpmodule.c	2016-07-24 15:23:50.000000000 -0400
@@ -156,10 +156,6 @@ static void vfp_thread_copy(struct threa
  *   - we could be preempted if tree preempt rcu is enabled, so
  *	it is unsafe to use thread->cpu.
  *  THREAD_NOTIFY_EXIT
- *   - the thread (v) will be running on the local CPU, so
- *	v === current_thread_info()
- *   - thread->cpu is the local CPU number at the time it is accessed,
- *	but may change at any time.
  *   - we could be preempted if tree preempt rcu is enabled, so
  *	it is unsafe to use thread->cpu.
  */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/amlogic/Makefile linux-libre-4.7-gnu/arch/arm64/boot/dts/amlogic/Makefile
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/amlogic/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/amlogic/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -1,3 +1,6 @@
+dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-odroidc2.dtb
+dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-p200.dtb
+dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-p201.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-vega-s95-pro.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-vega-s95-meta.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-vega-s95-telos.dtb
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -50,11 +50,6 @@
 	#address-cells = <2>;
 	#size-cells = <2>;
 
-	aliases {
-		serial0 = &uart_AO;
-		serial1 = &uart_A;
-	};
-
 	cpus {
 		#address-cells = <0x2>;
 		#size-cells = <0x0>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts linux-libre-4.7-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2016 Andreas Färber
+ * Copyright (c) 2016 BayLibre, Inc.
+ * Author: Kevin Hilman <khilman@kernel.org>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include "meson-gxbb.dtsi"
+
+/ {
+	compatible = "hardkernel,odroid-c2", "amlogic,meson-gxbb";
+	model = "Hardkernel ODROID-C2";
+	
+	aliases {
+		serial0 = &uart_AO;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x0 0x0 0x0 0x80000000>;
+	};
+};
+
+&uart_AO {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts linux-libre-4.7-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2016 Andreas Färber
+ * Copyright (c) 2016 BayLibre, Inc.
+ * Author: Kevin Hilman <khilman@kernel.org>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include "meson-gxbb-p20x.dtsi"
+
+/ {
+	compatible = "amlogic,p200", "amlogic,meson-gxbb";
+	model = "Amlogic Meson GXBB P200 Development Board";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts linux-libre-4.7-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2016 Andreas Färber
+ * Copyright (c) 2016 BayLibre, Inc.
+ * Author: Kevin Hilman <khilman@kernel.org>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include "meson-gxbb-p20x.dtsi"
+
+/ {
+	compatible = "amlogic,p201", "amlogic,meson-gxbb";
+	model = "Amlogic Meson GXBB P201 Development Board";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2016 Andreas Färber
+ * Copyright (c) 2016 BayLibre, Inc.
+ * Author: Kevin Hilman <khilman@kernel.org>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "meson-gxbb.dtsi"
+
+/ {
+	aliases {
+		serial0 = &uart_AO;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x0 0x0 0x0 0x40000000>;
+	};
+};
+
+/* This UART is brought out to the DB9 connector */
+&uart_AO {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -45,6 +45,10 @@
 / {
 	compatible = "tronsmart,vega-s95", "amlogic,meson-gxbb";
 
+	aliases {
+		serial0 = &uart_AO;
+	};
+
 	chosen {
 		stdout-path = "serial0:115200n8";
 	};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-meta.dts linux-libre-4.7-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-meta.dts
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-meta.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-meta.dts	2016-07-24 15:23:50.000000000 -0400
@@ -48,7 +48,7 @@
 	compatible = "tronsmart,vega-s95-meta", "tronsmart,vega-s95", "amlogic,meson-gxbb";
 	model = "Tronsmart Vega S95 Meta";
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0x0 0x0 0x0 0x80000000>;
 	};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-pro.dts linux-libre-4.7-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-pro.dts
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-pro.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-pro.dts	2016-07-24 15:23:50.000000000 -0400
@@ -48,7 +48,7 @@
 	compatible = "tronsmart,vega-s95-pro", "tronsmart,vega-s95", "amlogic,meson-gxbb";
 	model = "Tronsmart Vega S95 Pro";
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0x0 0x0 0x0 0x40000000>;
 	};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-telos.dts linux-libre-4.7-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-telos.dts
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-telos.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95-telos.dts	2016-07-24 15:23:50.000000000 -0400
@@ -48,7 +48,7 @@
 	compatible = "tronsmart,vega-s95-telos", "tronsmart,vega-s95", "amlogic,meson-gxbb";
 	model = "Tronsmart Vega S95 Telos";
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0x0 0x0 0x0 0x80000000>;
 	};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/apm/apm-shadowcat.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -543,7 +543,7 @@
 		};
 
 		sata1: sata@1a000000 {
-			compatible = "apm,xgene-ahci";
+			compatible = "apm,xgene-ahci-v2";
 			reg = <0x0 0x1a000000 0x0 0x1000>,
 			      <0x0 0x1f200000 0x0 0x1000>,
 			      <0x0 0x1f20d000 0x0 0x1000>,
@@ -553,7 +553,7 @@
 		};
 
 		sata2: sata@1a200000 {
-			compatible = "apm,xgene-ahci";
+			compatible = "apm,xgene-ahci-v2";
 			reg = <0x0 0x1a200000 0x0 0x1000>,
 			      <0x0 0x1f210000 0x0 0x1000>,
 			      <0x0 0x1f21d000 0x0 0x1000>,
@@ -563,7 +563,7 @@
 		};
 
 		sata3: sata@1a400000 {
-			compatible = "apm,xgene-ahci";
+			compatible = "apm,xgene-ahci-v2";
 			reg = <0x0 0x1a400000 0x0 0x1000>,
 			      <0x0 0x1f220000 0x0 0x1000>,
 			      <0x0 0x1f22d000 0x0 0x1000>,
@@ -653,6 +653,7 @@
 				     <0 113 4>,
 				     <0 114 4>,
 				     <0 115 4>;
+			channel = <12>;
 			port-id = <1>;
 			dma-coherent;
 			clocks = <&xge1clk 0>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/apm/apm-storm.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/apm/apm-storm.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/apm/apm-storm.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/apm/apm-storm.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -993,6 +993,7 @@
 				     <0x0 0x65 0x4>,
 				     <0x0 0x66 0x4>,
 				     <0x0 0x67 0x4>;
+			channel = <0>;
 			dma-coherent;
 			clocks = <&xge0clk 0>;
 			/* mac address will be overwritten by the bootloader */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/arm/juno-base.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/arm/juno-base.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/arm/juno-base.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/arm/juno-base.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -272,3 +272,13 @@
 
 		/include/ "juno-motherboard.dtsi"
 	};
+
+	site2: tlx@60000000 {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0 0x60000000 0x10000000>;
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0>;
+		interrupt-map = <0 0 &gic 0 0 0 168 IRQ_TYPE_LEVEL_HIGH>;
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/broadcom/ns2-clock.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/broadcom/ns2-clock.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/broadcom/ns2-clock.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/broadcom/ns2-clock.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,105 @@
+/*
+ *  BSD LICENSE
+ *
+ *  Copyright (c) 2016 Broadcom.  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in
+ *      the documentation and/or other materials provided with the
+ *      distribution.
+ *    * Neither the name of Broadcom Corporation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <dt-bindings/clock/bcm-ns2.h>
+
+	osc: oscillator {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <25000000>;
+	};
+
+	lcpll_ddr: lcpll_ddr@6501d058 {
+		#clock-cells = <1>;
+		compatible = "brcm,ns2-lcpll-ddr";
+		reg = <0x6501d058 0x20>,
+		      <0x6501c020 0x4>,
+		      <0x6501d04c 0x4>;
+		clocks = <&osc>;
+		clock-output-names = "lcpll_ddr", "pcie_sata_usb",
+				     "ddr", "ddr_ch2_unused",
+				     "ddr_ch3_unused", "ddr_ch4_unused",
+				     "ddr_ch5_unused";
+	};
+
+	lcpll_ports: lcpll_ports@6501d078 {
+		#clock-cells = <1>;
+		compatible = "brcm,ns2-lcpll-ports";
+		reg = <0x6501d078 0x20>,
+		      <0x6501c020 0x4>,
+		      <0x6501d054 0x4>;
+		clocks = <&osc>;
+		clock-output-names = "lcpll_ports", "wan", "rgmii",
+				     "ports_ch2_unused",
+				     "ports_ch3_unused",
+				     "ports_ch4_unused",
+				     "ports_ch5_unused";
+	};
+
+	genpll_scr: genpll_scr@6501d098 {
+		#clock-cells = <1>;
+		compatible = "brcm,ns2-genpll-scr";
+		reg = <0x6501d098 0x32>,
+		      <0x6501c020 0x4>,
+		      <0x6501d044 0x4>;
+		clocks = <&osc>;
+		clock-output-names = "genpll_scr", "scr", "fs",
+				     "audio_ref", "scr_ch3_unused",
+				     "scr_ch4_unused", "scr_ch5_unused";
+	};
+
+	iprocmed: iprocmed {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&genpll_scr BCM_NS2_GENPLL_SCR_SCR_CLK>;
+		clock-div = <2>;
+		clock-mult = <1>;
+	};
+
+	iprocslow: iprocslow {
+		#clock-cells = <0>;
+		compatible = "fixed-factor-clock";
+		clocks = <&genpll_scr BCM_NS2_GENPLL_SCR_SCR_CLK>;
+		clock-div = <4>;
+		clock-mult = <1>;
+	};
+
+	genpll_sw: genpll_sw@6501d0c4 {
+		#clock-cells = <1>;
+		compatible = "brcm,ns2-genpll-sw";
+		reg = <0x6501d0c4 0x32>,
+		      <0x6501c020 0x4>,
+		      <0x6501d044 0x4>;
+		clocks = <&osc>;
+		clock-output-names = "genpll_sw", "rpe", "250", "nic",
+				     "chimp", "port", "sdio";
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/broadcom/ns2.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/broadcom/ns2.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/broadcom/ns2.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/broadcom/ns2.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  BSD LICENSE
  *
- *  Copyright(c) 2015 Broadcom Corporation.  All rights reserved.
+ *  Copyright (c) 2015 Broadcom.  All rights reserved.
  *
  *  Redistribution and use in source and binary forms, with or without
  *  modification, are permitted provided that the following conditions
@@ -33,8 +33,6 @@
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/clock/bcm-ns2.h>
 
-/memreserve/ 0x84b00000 0x00000008;
-
 / {
 	compatible = "brcm,ns2";
 	interrupt-parent = <&gic>;
@@ -49,8 +47,7 @@
 			device_type = "cpu";
 			compatible = "arm,cortex-a57", "arm,armv8";
 			reg = <0 0>;
-			enable-method = "spin-table";
-			cpu-release-addr = <0 0x84b00000>;
+			enable-method = "psci";
 			next-level-cache = <&CLUSTER0_L2>;
 		};
 
@@ -58,8 +55,7 @@
 			device_type = "cpu";
 			compatible = "arm,cortex-a57", "arm,armv8";
 			reg = <0 1>;
-			enable-method = "spin-table";
-			cpu-release-addr = <0 0x84b00000>;
+			enable-method = "psci";
 			next-level-cache = <&CLUSTER0_L2>;
 		};
 
@@ -67,8 +63,7 @@
 			device_type = "cpu";
 			compatible = "arm,cortex-a57", "arm,armv8";
 			reg = <0 2>;
-			enable-method = "spin-table";
-			cpu-release-addr = <0 0x84b00000>;
+			enable-method = "psci";
 			next-level-cache = <&CLUSTER0_L2>;
 		};
 
@@ -76,8 +71,7 @@
 			device_type = "cpu";
 			compatible = "arm,cortex-a57", "arm,armv8";
 			reg = <0 3>;
-			enable-method = "spin-table";
-			cpu-release-addr = <0 0x84b00000>;
+			enable-method = "psci";
 			next-level-cache = <&CLUSTER0_L2>;
 		};
 
@@ -86,6 +80,11 @@
 		};
 	};
 
+	psci {
+		compatible = "arm,psci-1.0";
+		method = "smc";
+	};
+
 	timer {
 		compatible = "arm,armv8-timer";
 		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_RAW(0xff) |
@@ -110,33 +109,6 @@
 				     <&A57_3>;
 	};
 
-	clocks {
-		#address-cells = <1>;
-		#size-cells = <1>;
-
-		osc: oscillator {
-			#clock-cells = <0>;
-			compatible = "fixed-clock";
-			clock-frequency = <25000000>;
-		};
-
-		iprocmed: iprocmed {
-			#clock-cells = <0>;
-			compatible = "fixed-factor-clock";
-			clocks = <&genpll_scr BCM_NS2_GENPLL_SCR_SCR_CLK>;
-			clock-div = <2>;
-			clock-mult = <1>;
-		};
-
-		iprocslow: iprocslow {
-			#clock-cells = <0>;
-			compatible = "fixed-factor-clock";
-			clocks = <&genpll_scr BCM_NS2_GENPLL_SCR_SCR_CLK>;
-			clock-div = <4>;
-			clock-mult = <1>;
-		};
-	};
-
 	pcie0: pcie@20020000 {
 		compatible = "brcm,iproc-pcie";
 		reg = <0 0x20020000 0 0x1000>;
@@ -217,6 +189,27 @@
 		#size-cells = <1>;
 		ranges = <0 0 0 0xffffffff>;
 
+		#include "ns2-clock.dtsi"
+
+		dma0: dma@61360000 {
+			compatible = "arm,pl330", "arm,primecell";
+			reg = <0x61360000 0x1000>;
+			interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 209 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 210 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 213 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 214 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH>;
+			#dma-cells = <1>;
+			#dma-channels = <8>;
+			#dma-requests = <32>;
+			clocks = <&iprocslow>;
+			clock-names = "apb_pclk";
+		};
+
 		smmu: mmu@64000000 {
 			compatible = "arm,mmu-500";
 			reg = <0x64000000 0x40000>;
@@ -258,68 +251,6 @@
 			mmu-masters;
 		};
 
-		lcpll_ddr: lcpll_ddr@6501d058 {
-			#clock-cells = <1>;
-			compatible = "brcm,ns2-lcpll-ddr";
-			reg = <0x6501d058 0x20>,
-			      <0x6501c020 0x4>,
-			      <0x6501d04c 0x4>;
-			clocks = <&osc>;
-			clock-output-names = "lcpll_ddr", "pcie_sata_usb",
-					     "ddr", "ddr_ch2_unused",
-					     "ddr_ch3_unused", "ddr_ch4_unused",
-					     "ddr_ch5_unused";
-		};
-
-		lcpll_ports: lcpll_ports@6501d078 {
-			#clock-cells = <1>;
-			compatible = "brcm,ns2-lcpll-ports";
-			reg = <0x6501d078 0x20>,
-			      <0x6501c020 0x4>,
-			      <0x6501d054 0x4>;
-			clocks = <&osc>;
-			clock-output-names = "lcpll_ports", "wan", "rgmii",
-					     "ports_ch2_unused",
-					     "ports_ch3_unused",
-					     "ports_ch4_unused",
-					     "ports_ch5_unused";
-		};
-
-		genpll_scr: genpll_scr@6501d098 {
-			#clock-cells = <1>;
-			compatible = "brcm,ns2-genpll-scr";
-			reg = <0x6501d098 0x32>,
-			      <0x6501c020 0x4>,
-			      <0x6501d044 0x4>;
-			clocks = <&osc>;
-			clock-output-names = "genpll_scr", "scr", "fs",
-					     "audio_ref", "scr_ch3_unused",
-					     "scr_ch4_unused", "scr_ch5_unused";
-		};
-
-		genpll_sw: genpll_sw@6501d0c4 {
-			#clock-cells = <1>;
-			compatible = "brcm,ns2-genpll-sw";
-			reg = <0x6501d0c4 0x32>,
-			      <0x6501c020 0x4>,
-			      <0x6501d044 0x4>;
-			clocks = <&osc>;
-			clock-output-names = "genpll_sw", "rpe", "250", "nic",
-					     "chimp", "port", "sdio";
-		};
-
-		crmu: crmu@65024000 {
-			compatible = "syscon";
-			reg = <0x65024000 0x100>;
-		};
-
-		reboot@65024000 {
-			compatible ="syscon-reboot";
-			regmap = <&crmu>;
-			offset = <0x90>;
-			mask = <0xfffffffd>;
-		};
-
 		gic: interrupt-controller@65210000 {
 			compatible = "arm,gic-400";
 			#interrupt-cells = <3>;
@@ -328,6 +259,8 @@
 			      <0x65220000 0x1000>,
 			      <0x65240000 0x2000>,
 			      <0x65260000 0x1000>;
+			interrupts = <GIC_PPI 9 (GIC_CPU_MASK_RAW(0xf) |
+				      IRQ_TYPE_LEVEL_HIGH)>;
 		};
 
 		timer0: timer@66030000 {
@@ -408,6 +341,28 @@
 			status = "disabled";
 		};
 
+		ssp0: ssp@66180000 {
+			compatible = "arm,pl022", "arm,primecell";
+			reg = <0x66180000 0x1000>;
+			interrupts = <GIC_SPI 404 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&iprocslow>, <&iprocslow>;
+			clock-names = "spiclk", "apb_pclk";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		ssp1: ssp@66190000 {
+			compatible = "arm,pl022", "arm,primecell";
+			reg = <0x66190000 0x1000>;
+			interrupts = <GIC_SPI 405 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&iprocslow>, <&iprocslow>;
+			clock-names = "spiclk", "apb_pclk";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
 		hwrng: hwrng@66220000 {
 			compatible = "brcm,iproc-rng200";
 			reg = <0x66220000 0x28>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/broadcom/ns2-svk.dts linux-libre-4.7-gnu/arch/arm64/boot/dts/broadcom/ns2-svk.dts
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/broadcom/ns2-svk.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/broadcom/ns2-svk.dts	2016-07-24 15:23:50.000000000 -0400
@@ -72,6 +72,51 @@
 	status = "ok";
 };
 
+&ssp0 {
+	status = "ok";
+
+	slic@0 {
+		compatible = "silabs,si3226x";
+		reg = <0>;
+		spi-max-frequency = <5000000>;
+		spi-cpha = <1>;
+		spi-cpol = <1>;
+		pl022,hierarchy = <0>;
+		pl022,interface = <0>;
+		pl022,slave-tx-disable = <0>;
+		pl022,com-mode = <0>;
+		pl022,rx-level-trig = <1>;
+		pl022,tx-level-trig = <1>;
+		pl022,ctrl-len = <11>;
+		pl022,wait-state = <0>;
+		pl022,duplex = <0>;
+	};
+};
+
+&ssp1 {
+	status = "ok";
+
+	at25@0 {
+		compatible = "atmel,at25";
+		reg = <0>;
+		spi-max-frequency = <5000000>;
+		at25,byte-len = <0x8000>;
+		at25,addr-mode = <2>;
+		at25,page-size = <64>;
+		spi-cpha = <1>;
+		spi-cpol = <1>;
+		pl022,hierarchy = <0>;
+		pl022,interface = <0>;
+		pl022,slave-tx-disable = <0>;
+		pl022,com-mode = <0>;
+		pl022,rx-level-trig = <1>;
+		pl022,tx-level-trig = <1>;
+		pl022,ctrl-len = <11>;
+		pl022,wait-state = <0>;
+		pl022,duplex = <0>;
+	};
+};
+
 &sdio0 {
 	status = "ok";
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/broadcom/vulcan.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/broadcom/vulcan.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/broadcom/vulcan.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/broadcom/vulcan.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -86,7 +86,7 @@
 	};
 
 	pmu {
-		compatible = "arm,armv8-pmuv3";
+		compatible = "brcm,vulcan-pmu", "arm,armv8-pmuv3";
 		interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>; /* PMU overflow */
 	};
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/exynos/exynos7.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/exynos/exynos7.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/exynos/exynos7.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/exynos/exynos7.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -27,6 +27,7 @@
 		pinctrl6 = &pinctrl_fsys0;
 		pinctrl7 = &pinctrl_fsys1;
 		pinctrl8 = &pinctrl_bus1;
+		tmuctrl0 = &tmuctrl_0;
 	};
 
 	cpus {
@@ -95,6 +96,35 @@
 				<0x11006000 0x2000>;
 		};
 
+		amba {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+
+			pdma0: pdma@10E10000 {
+				compatible = "arm,pl330", "arm,primecell";
+				reg = <0x10E10000 0x1000>;
+				interrupts = <0 225 0>;
+				clocks = <&clock_fsys0 ACLK_PDMA0>;
+				clock-names = "apb_pclk";
+				#dma-cells = <1>;
+				#dma-channels = <8>;
+				#dma-requests = <32>;
+			};
+
+			pdma1: pdma@10EB0000 {
+				compatible = "arm,pl330", "arm,primecell";
+				reg = <0x10EB0000 0x1000>;
+				interrupts = <0 226 0>;
+				clocks = <&clock_fsys0 ACLK_PDMA1>;
+				clock-names = "apb_pclk";
+				#dma-cells = <1>;
+				#dma-channels = <8>;
+				#dma-requests = <32>;
+			};
+		};
+
 		clock_topc: clock-controller@10570000 {
 			compatible = "samsung,exynos7-clock-topc";
 			reg = <0x10570000 0x10000>;
@@ -538,6 +568,25 @@
 			clocks = <&clock_peric0 PCLK_PWM>;
 			clock-names = "timers";
 		};
+
+		tmuctrl_0: tmu@10060000 {
+			compatible = "samsung,exynos7-tmu";
+			reg = <0x10060000 0x200>;
+			interrupts = <0 108 0>;
+			clocks = <&clock_peris PCLK_TMU>,
+				 <&clock_peris SCLK_TMU>;
+			clock-names = "tmu_apbif", "tmu_sclk";
+			#include "exynos7-tmu-sensor-conf.dtsi"
+		};
+
+		thermal-zones {
+			atlas_thermal: cluster0-thermal {
+				polling-delay-passive = <0>; /* milliseconds */
+				polling-delay = <0>; /* milliseconds */
+				thermal-sensors = <&tmuctrl_0>;
+				#include "exynos7-trip-points.dtsi"
+			};
+		};
 	};
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/exynos/exynos7-tmu-sensor-conf.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/exynos/exynos7-tmu-sensor-conf.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/exynos/exynos7-tmu-sensor-conf.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/exynos/exynos7-tmu-sensor-conf.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,25 @@
+/*
+ * Device tree sources for Exynos7 TMU sensor configuration
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <dt-bindings/thermal/thermal_exynos.h>
+
+#thermal-sensor-cells = <0>;
+samsung,tmu_gain = <9>;
+samsung,tmu_reference_voltage = <17>;
+samsung,tmu_noise_cancel_mode = <4>;
+samsung,tmu_efuse_value = <75>;
+samsung,tmu_min_efuse_value = <15>;
+samsung,tmu_max_efuse_value = <100>;
+samsung,tmu_first_point_trim = <25>;
+samsung,tmu_second_point_trim = <85>;
+samsung,tmu_default_temp_offset = <50>;
+samsung,tmu_cal_type = <TYPE_ONE_POINT_TRIMMING>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/exynos/exynos7-trip-points.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/exynos/exynos7-trip-points.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/exynos/exynos7-trip-points.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/exynos/exynos7-trip-points.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,54 @@
+/*
+ * Device tree sources for default Exynos7 thermal zone definition
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+trips {
+	cpu-alert-0 {
+		temperature = <75000>; /* millicelsius */
+		hysteresis = <10000>; /* millicelsius */
+		type = "passive";
+	};
+	cpu-alert-1 {
+		temperature = <80000>; /* millicelsius */
+		hysteresis = <10000>; /* millicelsius */
+		type = "passive";
+	};
+	cpu-alert-2 {
+		temperature = <85000>; /* millicelsius */
+		hysteresis = <10000>; /* millicelsius */
+		type = "passive";
+	};
+	cpu-alert-3 {
+		temperature = <90000>; /* millicelsius */
+		hysteresis = <10000>; /* millicelsius */
+		type = "passive";
+	};
+	cpu-alert-4 {
+		temperature = <95000>; /* millicelsius */
+		hysteresis = <10000>; /* millicelsius */
+		type = "passive";
+	};
+	cpu-alert-5 {
+		temperature = <100000>; /* millicelsius */
+		hysteresis = <10000>; /* millicelsius */
+		type = "passive";
+	};
+	cpu-alert-6 {
+		temperature = <110000>; /* millicelsius */
+		hysteresis = <10000>; /* millicelsius */
+		type = "passive";
+	};
+	cpu-crit-0 {
+		temperature = <115000>; /* millicelsius */
+		hysteresis = <0>; /* millicelsius */
+		type = "critical";
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -171,6 +171,20 @@
 			interrupts = <0 43 0x4>;
 		};
 
+		qspi: quadspi@1550000 {
+			compatible = "fsl,ls1043a-qspi", "fsl,ls1021a-qspi";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x0 0x1550000 0x0 0x10000>,
+				<0x0 0x40000000 0x0 0x4000000>;
+			reg-names = "QuadSPI", "QuadSPI-memory";
+			interrupts = <0 99 0x4>;
+			clock-names = "qspi_en", "qspi";
+			clocks = <&clockgen 4 0>, <&clockgen 4 0>;
+			big-endian;
+			status = "disabled";
+		};
+
 		esdhc: esdhc@1560000 {
 			compatible = "fsl,ls1043a-esdhc", "fsl,esdhc";
 			reg = <0x0 0x1560000 0x0 0x10000>;
@@ -284,7 +298,7 @@
 		};
 
 		gpio1: gpio@2300000 {
-			compatible = "fsl,ls1043a-gpio";
+			compatible = "fsl,ls1043a-gpio", "fsl,qoriq-gpio";
 			reg = <0x0 0x2300000 0x0 0x10000>;
 			interrupts = <0 66 0x4>;
 			gpio-controller;
@@ -294,7 +308,7 @@
 		};
 
 		gpio2: gpio@2310000 {
-			compatible = "fsl,ls1043a-gpio";
+			compatible = "fsl,ls1043a-gpio", "fsl,qoriq-gpio";
 			reg = <0x0 0x2310000 0x0 0x10000>;
 			interrupts = <0 67 0x4>;
 			gpio-controller;
@@ -304,7 +318,7 @@
 		};
 
 		gpio3: gpio@2320000 {
-			compatible = "fsl,ls1043a-gpio";
+			compatible = "fsl,ls1043a-gpio", "fsl,qoriq-gpio";
 			reg = <0x0 0x2320000 0x0 0x10000>;
 			interrupts = <0 68 0x4>;
 			gpio-controller;
@@ -314,7 +328,7 @@
 		};
 
 		gpio4: gpio@2330000 {
-			compatible = "fsl,ls1043a-gpio";
+			compatible = "fsl,ls1043a-gpio", "fsl,qoriq-gpio";
 			reg = <0x0 0x2330000 0x0 0x10000>;
 			interrupts = <0 134 0x4>;
 			gpio-controller;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts linux-libre-4.7-gnu/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,181 @@
+/*
+ * Device Tree Include file for Freescale Layerscape-1043A family SoC.
+ *
+ * Copyright 2014-2015, Freescale Semiconductor
+ *
+ * Mingkai Hu <Mingkai.hu@freescale.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPLv2 or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+/include/ "fsl-ls1043a.dtsi"
+
+/ {
+	model = "LS1043A QDS Board";
+	compatible = "fsl,ls1043a-qds", "fsl,ls1043a";
+
+	aliases {
+		gpio0 = &gpio1;
+		gpio1 = &gpio2;
+		gpio2 = &gpio3;
+		gpio3 = &gpio4;
+		serial0 = &lpuart0;
+		serial1 = &lpuart1;
+		serial2 = &lpuart2;
+		serial3 = &lpuart3;
+		serial4 = &lpuart4;
+		serial5 = &lpuart5;
+	};
+};
+
+&duart0 {
+	status = "okay";
+};
+
+&duart1 {
+	status = "okay";
+};
+
+&ifc {
+	#address-cells = <2>;
+	#size-cells = <1>;
+	/* NOR, NAND Flashes and FPGA on board */
+	ranges = <0x0 0x0 0x0 0x60000000 0x08000000
+		  0x1 0x0 0x0 0x7e800000 0x00010000
+		  0x2 0x0 0x0 0x7fb00000 0x00000100>;
+	status = "okay";
+
+	nor@0,0 {
+		compatible = "cfi-flash";
+		reg = <0x0 0x0 0x8000000>;
+		bank-width = <2>;
+		device-width = <1>;
+	};
+
+	nand@1,0 {
+		compatible = "fsl,ifc-nand";
+		reg = <0x1 0x0 0x10000>;
+	};
+
+	fpga: board-control@2,0 {
+		compatible = "fsl,ls1043aqds-fpga", "fsl,fpga-qixis";
+		reg = <0x2 0x0 0x0000100>;
+	};
+};
+
+&i2c0 {
+	status = "okay";
+
+	pca9547@77 {
+		compatible = "nxp,pca9547";
+		reg = <0x77>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		i2c@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x0>;
+
+			rtc@68 {
+				compatible = "dallas,ds3232";
+				reg = <0x68>;
+				/* IRQ10_B */
+				interrupts = <0 150 0x4>;
+			};
+		};
+
+		i2c@2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x2>;
+
+			ina220@40 {
+				compatible = "ti,ina220";
+				reg = <0x40>;
+				shunt-resistor = <1000>;
+			};
+
+			ina220@41 {
+				compatible = "ti,ina220";
+				reg = <0x41>;
+				shunt-resistor = <1000>;
+			};
+		};
+
+		i2c@3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x3>;
+
+			eeprom@56 {
+				compatible = "atmel,24c512";
+				reg = <0x56>;
+			};
+
+			eeprom@57 {
+				compatible = "atmel,24c512";
+				reg = <0x57>;
+			};
+
+			temp-sensor@4c {
+				compatible = "adi,adt7461a";
+				reg = <0x4c>;
+			};
+		};
+	};
+};
+
+&lpuart0 {
+	status = "okay";
+};
+
+&qspi {
+	bus-num = <0>;
+	status = "okay";
+
+	qflash0: s25fl128s@0 {
+		compatible = "spansion,m25p80";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		spi-max-frequency = <20000000>;
+		reg = <0>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts linux-libre-4.7-gnu/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts	2016-07-24 15:23:50.000000000 -0400
@@ -107,6 +107,19 @@
 		};
 };
 
+&dspi0 {
+	bus-num = <0>;
+	status = "okay";
+
+	flash@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "n25q128a13", "jedec,spi-nor";  /* 16MB */
+		reg = <0>;
+		spi-max-frequency = <1000000>; /* input clock */
+	};
+};
+
 &duart0 {
 	status = "okay";
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -265,6 +265,104 @@
 			compatible = "fsl,qoriq-mc";
 			reg = <0x00000008 0x0c000000 0 0x40>,	 /* MC portal base */
 			      <0x00000000 0x08340000 0 0x40000>; /* MC control reg */
+			msi-parent = <&its>;
+			#address-cells = <3>;
+			#size-cells = <1>;
+
+			/*
+			 * Region type 0x0 - MC portals
+			 * Region type 0x1 - QBMAN portals
+			 */
+			ranges = <0x0 0x0 0x0 0x8 0x0c000000 0x4000000
+				  0x1 0x0 0x0 0x8 0x18000000 0x8000000>;
+
+			/*
+			 * Define the maximum number of MACs present on the SoC.
+			 */
+			dpmacs {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				dpmac1: dpmac@1 {
+					compatible = "fsl,qoriq-mc-dpmac";
+					reg = <0x1>;
+				};
+
+				dpmac2: dpmac@2 {
+					compatible = "fsl,qoriq-mc-dpmac";
+					reg = <0x2>;
+				};
+
+				dpmac3: dpmac@3 {
+					compatible = "fsl,qoriq-mc-dpmac";
+					reg = <0x3>;
+				};
+
+				dpmac4: dpmac@4 {
+					compatible = "fsl,qoriq-mc-dpmac";
+					reg = <0x4>;
+				};
+
+				dpmac5: dpmac@5 {
+					compatible = "fsl,qoriq-mc-dpmac";
+					reg = <0x5>;
+				};
+
+				dpmac6: dpmac@6 {
+					compatible = "fsl,qoriq-mc-dpmac";
+					reg = <0x6>;
+				};
+
+				dpmac7: dpmac@7 {
+					compatible = "fsl,qoriq-mc-dpmac";
+					reg = <0x7>;
+				};
+
+				dpmac8: dpmac@8 {
+					compatible = "fsl,qoriq-mc-dpmac";
+					reg = <0x8>;
+				};
+
+				dpmac9: dpmac@9 {
+					compatible = "fsl,qoriq-mc-dpmac";
+					reg = <0x9>;
+				};
+
+				dpmac10: dpmac@a {
+					compatible = "fsl,qoriq-mc-dpmac";
+					reg = <0xa>;
+				};
+
+				dpmac11: dpmac@b {
+					compatible = "fsl,qoriq-mc-dpmac";
+					reg = <0xb>;
+				};
+
+				dpmac12: dpmac@c {
+					compatible = "fsl,qoriq-mc-dpmac";
+					reg = <0xc>;
+				};
+
+				dpmac13: dpmac@d {
+					compatible = "fsl,qoriq-mc-dpmac";
+					reg = <0xd>;
+				};
+
+				dpmac14: dpmac@e {
+					compatible = "fsl,qoriq-mc-dpmac";
+					reg = <0xe>;
+				};
+
+				dpmac15: dpmac@f {
+					compatible = "fsl,qoriq-mc-dpmac";
+					reg = <0xf>;
+				};
+
+				dpmac16: dpmac@10 {
+					compatible = "fsl,qoriq-mc-dpmac";
+					reg = <0x10>;
+				};
+			};
 		};
 
 		smmu: iommu@5000000 {
@@ -318,7 +416,7 @@
 
 		dspi: dspi@2100000 {
 			status = "disabled";
-			compatible = "fsl,vf610-dspi";
+			compatible = "fsl,ls2080a-dspi", "fsl,ls2085a-dspi";
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <0x0 0x2100000 0x0 0x10000>;
@@ -342,7 +440,7 @@
 		};
 
 		gpio0: gpio@2300000 {
-			compatible = "fsl,qoriq-gpio";
+			compatible = "fsl,ls2080a-gpio", "fsl,qoriq-gpio";
 			reg = <0x0 0x2300000 0x0 0x10000>;
 			interrupts = <0 36 0x4>; /* Level high type */
 			gpio-controller;
@@ -353,7 +451,7 @@
 		};
 
 		gpio1: gpio@2310000 {
-			compatible = "fsl,qoriq-gpio";
+			compatible = "fsl,ls2080a-gpio", "fsl,qoriq-gpio";
 			reg = <0x0 0x2310000 0x0 0x10000>;
 			interrupts = <0 36 0x4>; /* Level high type */
 			gpio-controller;
@@ -364,7 +462,7 @@
 		};
 
 		gpio2: gpio@2320000 {
-			compatible = "fsl,qoriq-gpio";
+			compatible = "fsl,ls2080a-gpio", "fsl,qoriq-gpio";
 			reg = <0x0 0x2320000 0x0 0x10000>;
 			interrupts = <0 37 0x4>; /* Level high type */
 			gpio-controller;
@@ -375,7 +473,7 @@
 		};
 
 		gpio3: gpio@2330000 {
-			compatible = "fsl,qoriq-gpio";
+			compatible = "fsl,ls2080a-gpio", "fsl,qoriq-gpio";
 			reg = <0x0 0x2330000 0x0 0x10000>;
 			interrupts = <0 37 0x4>; /* Level high type */
 			gpio-controller;
@@ -444,7 +542,7 @@
 
 		qspi: quadspi@20c0000 {
 			status = "disabled";
-			compatible = "fsl,vf610-qspi";
+			compatible = "fsl,ls2080a-qspi", "fsl,ls1021a-qspi";
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <0x0 0x20c0000 0x0 0x10000>,
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts linux-libre-4.7-gnu/arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts	2016-07-24 15:23:50.000000000 -0400
@@ -178,7 +178,14 @@
 
 &qspi {
 	status = "okay";
-	qflash0: s25fl008k {
+	flash0: s25fl256s1@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "st,m25p80";
+		spi-max-frequency = <20000000>;
+		reg = <0>;
+	};
+	flash2: s25fl256s1@2 {
 		#address-cells = <1>;
 		#size-cells = <1>;
 		compatible = "st,m25p80";
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/freescale/Makefile linux-libre-4.7-gnu/arch/arm64/boot/dts/freescale/Makefile
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/freescale/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/freescale/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -1,7 +1,8 @@
+dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1043a-qds.dtb
+dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1043a-rdb.dtb
 dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2080a-qds.dtb
 dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2080a-rdb.dtb
 dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2080a-simu.dtb
-dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1043a-rdb.dtb
  
 always		:= $(dtb-y)
 subdir-y	:= $(dts-dirs)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/hisilicon/hi6220.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/hisilicon/hi6220.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/hisilicon/hi6220.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/hisilicon/hi6220.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -6,6 +6,8 @@
 
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/clock/hi6220-clock.h>
+#include <dt-bindings/pinctrl/hisi.h>
+#include <dt-bindings/thermal/thermal.h>
 
 / {
 	compatible = "hisilicon,hi6220";
@@ -53,11 +55,42 @@
 			};
 		};
 
+		idle-states {
+			entry-method = "psci";
+
+			CPU_SLEEP: cpu-sleep {
+				compatible = "arm,idle-state";
+				local-timer-stop;
+				arm,psci-suspend-param = <0x0010000>;
+				entry-latency-us = <700>;
+				exit-latency-us = <250>;
+				min-residency-us = <1000>;
+			};
+
+			CLUSTER_SLEEP: cluster-sleep {
+				compatible = "arm,idle-state";
+				local-timer-stop;
+				arm,psci-suspend-param = <0x1010000>;
+				entry-latency-us = <1000>;
+				exit-latency-us = <700>;
+				min-residency-us = <2700>;
+				wakeup-latency-us = <1500>;
+			};
+		};
+
 		cpu0: cpu@0 {
 			compatible = "arm,cortex-a53", "arm,armv8";
 			device_type = "cpu";
 			reg = <0x0 0x0>;
 			enable-method = "psci";
+			next-level-cache = <&CLUSTER0_L2>;
+			clocks = <&stub_clock 0>;
+			operating-points-v2 = <&cpu_opp_table>;
+			cooling-min-level = <4>;
+			cooling-max-level = <0>;
+			#cooling-cells = <2>; /* min followed by max */
+			cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>;
+			dynamic-power-coefficient = <311>;
 		};
 
 		cpu1: cpu@1 {
@@ -65,6 +98,9 @@
 			device_type = "cpu";
 			reg = <0x0 0x1>;
 			enable-method = "psci";
+			next-level-cache = <&CLUSTER0_L2>;
+			operating-points-v2 = <&cpu_opp_table>;
+			cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>;
 		};
 
 		cpu2: cpu@2 {
@@ -72,6 +108,9 @@
 			device_type = "cpu";
 			reg = <0x0 0x2>;
 			enable-method = "psci";
+			next-level-cache = <&CLUSTER0_L2>;
+			operating-points-v2 = <&cpu_opp_table>;
+			cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>;
 		};
 
 		cpu3: cpu@3 {
@@ -79,6 +118,9 @@
 			device_type = "cpu";
 			reg = <0x0 0x3>;
 			enable-method = "psci";
+			next-level-cache = <&CLUSTER0_L2>;
+			operating-points-v2 = <&cpu_opp_table>;
+			cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>;
 		};
 
 		cpu4: cpu@100 {
@@ -86,6 +128,9 @@
 			device_type = "cpu";
 			reg = <0x0 0x100>;
 			enable-method = "psci";
+			next-level-cache = <&CLUSTER1_L2>;
+			operating-points-v2 = <&cpu_opp_table>;
+			cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>;
 		};
 
 		cpu5: cpu@101 {
@@ -93,6 +138,9 @@
 			device_type = "cpu";
 			reg = <0x0 0x101>;
 			enable-method = "psci";
+			next-level-cache = <&CLUSTER1_L2>;
+			operating-points-v2 = <&cpu_opp_table>;
+			cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>;
 		};
 
 		cpu6: cpu@102 {
@@ -100,6 +148,9 @@
 			device_type = "cpu";
 			reg = <0x0 0x102>;
 			enable-method = "psci";
+			next-level-cache = <&CLUSTER1_L2>;
+			operating-points-v2 = <&cpu_opp_table>;
+			cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>;
 		};
 
 		cpu7: cpu@103 {
@@ -107,6 +158,48 @@
 			device_type = "cpu";
 			reg = <0x0 0x103>;
 			enable-method = "psci";
+			next-level-cache = <&CLUSTER1_L2>;
+			operating-points-v2 = <&cpu_opp_table>;
+			cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>;
+		};
+
+		CLUSTER0_L2: l2-cache0 {
+			compatible = "cache";
+		};
+
+		CLUSTER1_L2: l2-cache1 {
+			compatible = "cache";
+		};
+	};
+
+	cpu_opp_table: cpu_opp_table {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp00 {
+			opp-hz = /bits/ 64 <208000000>;
+			opp-microvolt = <1040000>;
+			clock-latency-ns = <500000>;
+		};
+		opp01 {
+			opp-hz = /bits/ 64 <432000000>;
+			opp-microvolt = <1040000>;
+			clock-latency-ns = <500000>;
+		};
+		opp02 {
+			opp-hz = /bits/ 64 <729000000>;
+			opp-microvolt = <1090000>;
+			clock-latency-ns = <500000>;
+		};
+		opp03 {
+			opp-hz = /bits/ 64 <960000000>;
+			opp-microvolt = <1180000>;
+			clock-latency-ns = <500000>;
+		};
+		opp04 {
+			opp-hz = /bits/ 64 <1200000000>;
+			opp-microvolt = <1330000>;
+			clock-latency-ns = <500000>;
 		};
 	};
 
@@ -137,6 +230,11 @@
 		#size-cells = <2>;
 		ranges;
 
+		sram: sram@fff80000 {
+			compatible = "hisilicon,hi6220-sramctrl", "syscon";
+			reg = <0x0 0xfff80000 0x0 0x12000>;
+		};
+
 		ao_ctrl: ao_ctrl@f7800000 {
 			compatible = "hisilicon,hi6220-aoctrl", "syscon";
 			reg = <0x0 0xf7800000 0x0 0x2000>;
@@ -162,6 +260,14 @@
 			#clock-cells = <1>;
 		};
 
+		stub_clock: stub_clock {
+			compatible = "hisilicon,hi6220-stub-clk";
+			hisilicon,hi6220-clk-sram = <&sram>;
+			#clock-cells = <1>;
+			mbox-names = "mbox-tx";
+			mboxes = <&mailbox 1 0 11>;
+		};
+
 		uart0: uart@f8015000 {	/* console */
 			compatible = "arm,pl011", "arm,primecell";
 			reg = <0x0 0xf8015000 0x0 0x1000>;
@@ -178,6 +284,8 @@
 			clocks = <&sys_ctrl HI6220_UART1_PCLK>,
 				 <&sys_ctrl HI6220_UART1_PCLK>;
 			clock-names = "uartclk", "apb_pclk";
+			pinctrl-names = "default";
+			pinctrl-0 = <&uart1_pmx_func &uart1_cfg_func1 &uart1_cfg_func2>;
 			status = "disabled";
 		};
 
@@ -188,6 +296,8 @@
 			clocks = <&sys_ctrl HI6220_UART2_PCLK>,
 				 <&sys_ctrl HI6220_UART2_PCLK>;
 			clock-names = "uartclk", "apb_pclk";
+			pinctrl-names = "default";
+			pinctrl-0 = <&uart2_pmx_func &uart2_cfg_func>;
 			status = "disabled";
 		};
 
@@ -198,6 +308,9 @@
 			clocks = <&sys_ctrl HI6220_UART3_PCLK>,
 				 <&sys_ctrl HI6220_UART3_PCLK>;
 			clock-names = "uartclk", "apb_pclk";
+			pinctrl-names = "default";
+			pinctrl-0 = <&uart3_pmx_func &uart3_cfg_func>;
+			status = "disabled";
 		};
 
 		uart4: uart@f7114000 {
@@ -207,7 +320,517 @@
 			clocks = <&sys_ctrl HI6220_UART4_PCLK>,
 				 <&sys_ctrl HI6220_UART4_PCLK>;
 			clock-names = "uartclk", "apb_pclk";
+			pinctrl-names = "default";
+			pinctrl-0 = <&uart4_pmx_func &uart4_cfg_func>;
 			status = "disabled";
 		};
+
+		dual_timer0: timer@f8008000 {
+			compatible = "arm,sp804", "arm,primecell";
+			reg = <0x0 0xf8008000 0x0 0x1000>;
+			interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ao_ctrl HI6220_TIMER0_PCLK>,
+				 <&ao_ctrl HI6220_TIMER0_PCLK>,
+				 <&ao_ctrl HI6220_TIMER0_PCLK>;
+			clock-names = "timer1", "timer2", "apb_pclk";
+		};
+
+		pmx0: pinmux@f7010000 {
+			compatible = "pinctrl-single";
+			reg = <0x0 0xf7010000  0x0 0x27c>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			#gpio-range-cells = <3>;
+			pinctrl-single,register-width = <32>;
+			pinctrl-single,function-mask = <7>;
+			pinctrl-single,gpio-range = <
+				&range  80  8 MUX_M0 /* gpio  3: [0..7] */
+				&range  88  8 MUX_M0 /* gpio  4: [0..7] */
+				&range  96  8 MUX_M0 /* gpio  5: [0..7] */
+				&range 104  8 MUX_M0 /* gpio  6: [0..7] */
+				&range 112  8 MUX_M0 /* gpio  7: [0..7] */
+				&range 120  2 MUX_M0 /* gpio  8: [0..1] */
+				&range   2  6 MUX_M1 /* gpio  8: [2..7] */
+				&range   8  8 MUX_M1 /* gpio  9: [0..7] */
+				&range   0  1 MUX_M1 /* gpio 10: [0]    */
+				&range  16  7 MUX_M1 /* gpio 10: [1..7] */
+				&range  23  3 MUX_M1 /* gpio 11: [0..2] */
+				&range  28  5 MUX_M1 /* gpio 11: [3..7] */
+				&range  33  3 MUX_M1 /* gpio 12: [0..2] */
+				&range  43  5 MUX_M1 /* gpio 12: [3..7] */
+				&range  48  8 MUX_M1 /* gpio 13: [0..7] */
+				&range  56  8 MUX_M1 /* gpio 14: [0..7] */
+				&range  74  6 MUX_M1 /* gpio 15: [0..5] */
+				&range 122  1 MUX_M1 /* gpio 15: [6]    */
+				&range 126  1 MUX_M1 /* gpio 15: [7]    */
+				&range 127  8 MUX_M1 /* gpio 16: [0..7] */
+				&range 135  8 MUX_M1 /* gpio 17: [0..7] */
+				&range 143  8 MUX_M1 /* gpio 18: [0..7] */
+				&range 151  8 MUX_M1 /* gpio 19: [0..7] */
+			>;
+			range: gpio-range {
+				#pinctrl-single,gpio-range-cells = <3>;
+			};
+		};
+
+		pmx1: pinmux@f7010800 {
+			compatible = "pinconf-single";
+			reg = <0x0 0xf7010800 0x0 0x28c>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			pinctrl-single,register-width = <32>;
+		};
+
+		pmx2: pinmux@f8001800 {
+			compatible = "pinconf-single";
+			reg = <0x0 0xf8001800 0x0 0x78>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			pinctrl-single,register-width = <32>;
+		};
+
+		gpio0: gpio@f8011000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0x0 0xf8011000 0x0 0x1000>;
+			interrupts = <0 52 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&ao_ctrl 2>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio1: gpio@f8012000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0x0 0xf8012000 0x0 0x1000>;
+			interrupts = <0 53 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&ao_ctrl 2>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio2: gpio@f8013000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0x0 0xf8013000 0x0 0x1000>;
+			interrupts = <0 54 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&ao_ctrl 2>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio3: gpio@f8014000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0x0 0xf8014000 0x0 0x1000>;
+			interrupts = <0 55 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&pmx0 0 80 8>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&ao_ctrl 2>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio4: gpio@f7020000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0x0 0xf7020000 0x0 0x1000>;
+			interrupts = <0 56 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&pmx0 0 88 8>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&ao_ctrl 2>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio5: gpio@f7021000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0x0 0xf7021000 0x0 0x1000>;
+			interrupts = <0 57 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&pmx0 0 96 8>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&ao_ctrl 2>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio6: gpio@f7022000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0x0 0xf7022000 0x0 0x1000>;
+			interrupts = <0 58 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&pmx0 0 104 8>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&ao_ctrl 2>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio7: gpio@f7023000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0x0 0xf7023000 0x0 0x1000>;
+			interrupts = <0 59 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&pmx0 0 112 8>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&ao_ctrl 2>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio8: gpio@f7024000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0x0 0xf7024000 0x0 0x1000>;
+			interrupts = <0 60 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&pmx0 0 120 2 &pmx0 2 2 6>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&ao_ctrl 2>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio9: gpio@f7025000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0x0 0xf7025000 0x0 0x1000>;
+			interrupts = <0 61 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&pmx0 0 8 8>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&ao_ctrl 2>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio10: gpio@f7026000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0x0 0xf7026000 0x0 0x1000>;
+			interrupts = <0 62 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&pmx0 0 0 1 &pmx0 1 16 7>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&ao_ctrl 2>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio11: gpio@f7027000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0x0 0xf7027000 0x0 0x1000>;
+			interrupts = <0 63 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&pmx0 0 23 3 &pmx0 3 28 5>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&ao_ctrl 2>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio12: gpio@f7028000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0x0 0xf7028000 0x0 0x1000>;
+			interrupts = <0 64 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&pmx0 0 33 3 &pmx0 3 43 5>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&ao_ctrl 2>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio13: gpio@f7029000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0x0 0xf7029000 0x0 0x1000>;
+			interrupts = <0 65 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&pmx0 0 48 8>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&ao_ctrl 2>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio14: gpio@f702a000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0x0 0xf702a000 0x0 0x1000>;
+			interrupts = <0 66 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&pmx0 0 56 8>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&ao_ctrl 2>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio15: gpio@f702b000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0x0 0xf702b000 0x0 0x1000>;
+			interrupts = <0 67 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <
+				&pmx0 0 74 6
+				&pmx0 6 122 1
+				&pmx0 7 126 1
+			>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&ao_ctrl 2>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio16: gpio@f702c000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0x0 0xf702c000 0x0 0x1000>;
+			interrupts = <0 68 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&pmx0 0 127 8>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&ao_ctrl 2>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio17: gpio@f702d000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0x0 0xf702d000 0x0 0x1000>;
+			interrupts = <0 69 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&pmx0 0 135 8>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&ao_ctrl 2>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio18: gpio@f702e000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0x0 0xf702e000 0x0 0x1000>;
+			interrupts = <0 70 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&pmx0 0 143 8>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&ao_ctrl 2>;
+			clock-names = "apb_pclk";
+		};
+
+		gpio19: gpio@f702f000 {
+			compatible = "arm,pl061", "arm,primecell";
+			reg = <0x0 0xf702f000 0x0 0x1000>;
+			interrupts = <0 71 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&pmx0 0 151 8>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			clocks = <&ao_ctrl 2>;
+			clock-names = "apb_pclk";
+		};
+
+		spi0: spi@f7106000 {
+			compatible = "arm,pl022", "arm,primecell";
+			reg = <0x0 0xf7106000 0x0 0x1000>;
+			interrupts = <0 50 4>;
+			bus-id = <0>;
+			enable-dma = <0>;
+			clocks = <&sys_ctrl HI6220_SPI_CLK>;
+			clock-names = "apb_pclk";
+			pinctrl-names = "default";
+			pinctrl-0 = <&spi0_pmx_func &spi0_cfg_func>;
+			num-cs = <1>;
+			cs-gpios = <&gpio6 2 0>;
+			status = "disabled";
+		};
+
+		i2c0: i2c@f7100000 {
+			compatible = "snps,designware-i2c";
+			reg = <0x0 0xf7100000 0x0 0x1000>;
+			interrupts = <0 44 4>;
+			clocks = <&sys_ctrl HI6220_I2C0_CLK>;
+			i2c-sda-hold-time-ns = <300>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&i2c0_pmx_func &i2c0_cfg_func>;
+			status = "disabled";
+		};
+
+		i2c1: i2c@f7101000 {
+			compatible = "snps,designware-i2c";
+			reg = <0x0 0xf7101000 0x0 0x1000>;
+			clocks = <&sys_ctrl HI6220_I2C1_CLK>;
+			interrupts = <0 45 4>;
+			i2c-sda-hold-time-ns = <300>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&i2c1_pmx_func &i2c1_cfg_func>;
+			status = "disabled";
+		};
+
+		i2c2: i2c@f7102000 {
+			compatible = "snps,designware-i2c";
+			reg = <0x0 0xf7102000 0x0 0x1000>;
+			clocks = <&sys_ctrl HI6220_I2C2_CLK>;
+			interrupts = <0 46 4>;
+			i2c-sda-hold-time-ns = <300>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&i2c2_pmx_func &i2c2_cfg_func>;
+			status = "disabled";
+		};
+
+		fixed_5v_hub: regulator@0 {
+			compatible = "regulator-fixed";
+			regulator-name = "fixed_5v_hub";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-boot-on;
+			gpio = <&gpio0 7 0>;
+			regulator-always-on;
+		};
+
+		usb_phy: usbphy {
+			compatible = "hisilicon,hi6220-usb-phy";
+			#phy-cells = <0>;
+			phy-supply = <&fixed_5v_hub>;
+			hisilicon,peripheral-syscon = <&sys_ctrl>;
+		};
+
+		usb: usb@f72c0000 {
+			compatible = "hisilicon,hi6220-usb";
+			reg = <0x0 0xf72c0000 0x0 0x40000>;
+			phys = <&usb_phy>;
+			phy-names = "usb2-phy";
+			clocks = <&sys_ctrl HI6220_USBOTG_HCLK>;
+			clock-names = "otg";
+			dr_mode = "otg";
+			g-use-dma;
+			g-rx-fifo-size = <512>;
+			g-np-tx-fifo-size = <128>;
+			g-tx-fifo-size = <128 128 128 128 128 128>;
+			interrupts = <0 77 0x4>;
+		};
+
+		mailbox: mailbox@f7510000 {
+			compatible = "hisilicon,hi6220-mbox";
+			reg = <0x0 0xf7510000 0x0 0x1000>, /* IPC_S */
+			      <0x0 0x06dff800 0x0 0x0800>; /* Mailbox buffer */
+			interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
+			#mbox-cells = <3>;
+		};
+
+		dwmmc_0: dwmmc0@f723d000 {
+			compatible = "hisilicon,hi6220-dw-mshc";
+			num-slots = <0x1>;
+			cap-mmc-highspeed;
+			non-removable;
+			reg = <0x0 0xf723d000 0x0 0x1000>;
+			interrupts = <0x0 0x48 0x4>;
+			clocks = <&sys_ctrl 2>, <&sys_ctrl 1>;
+			clock-names = "ciu", "biu";
+			bus-width = <0x8>;
+			vmmc-supply = <&ldo19>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&emmc_pmx_func &emmc_clk_cfg_func
+				     &emmc_cfg_func &emmc_rst_cfg_func>;
+		};
+
+		dwmmc_1: dwmmc1@f723e000 {
+			compatible = "hisilicon,hi6220-dw-mshc";
+			num-slots = <0x1>;
+			card-detect-delay = <200>;
+			hisilicon,peripheral-syscon = <&ao_ctrl>;
+			cap-sd-highspeed;
+			reg = <0x0 0xf723e000 0x0 0x1000>;
+			interrupts = <0x0 0x49 0x4>;
+			#address-cells = <0x1>;
+			#size-cells = <0x0>;
+			clocks = <&sys_ctrl 4>, <&sys_ctrl 3>;
+			clock-names = "ciu", "biu";
+			vqmmc-supply = <&ldo7>;
+			vmmc-supply = <&ldo10>;
+			bus-width = <0x4>;
+			disable-wp;
+			cd-gpios = <&gpio1 0 1>;
+			pinctrl-names = "default", "idle";
+			pinctrl-0 = <&sd_pmx_func &sd_clk_cfg_func &sd_cfg_func>;
+			pinctrl-1 = <&sd_pmx_idle &sd_clk_cfg_idle &sd_cfg_idle>;
+		};
+
+		dwmmc_2: dwmmc2@f723f000 {
+			compatible = "hisilicon,hi6220-dw-mshc";
+			num-slots = <0x1>;
+			reg = <0x0 0xf723f000 0x0 0x1000>;
+			interrupts = <0x0 0x4a 0x4>;
+			clocks = <&sys_ctrl HI6220_MMC2_CIUCLK>, <&sys_ctrl HI6220_MMC2_CLK>;
+			clock-names = "ciu", "biu";
+			bus-width = <0x4>;
+			broken-cd;
+			pinctrl-names = "default", "idle";
+			pinctrl-0 = <&sdio_pmx_func &sdio_clk_cfg_func &sdio_cfg_func>;
+			pinctrl-1 = <&sdio_pmx_idle &sdio_clk_cfg_idle &sdio_cfg_idle>;
+		};
+
+		tsensor: tsensor@0,f7030700 {
+			compatible = "hisilicon,tsensor";
+			reg = <0x0 0xf7030700 0x0 0x1000>;
+			interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&sys_ctrl 22>;
+			clock-names = "thermal_clk";
+			#thermal-sensor-cells = <1>;
+		};
+
+		thermal-zones {
+
+			cls0: cls0 {
+				polling-delay = <1000>;
+				polling-delay-passive = <100>;
+				sustainable-power = <3326>;
+
+				/* sensor ID */
+				thermal-sensors = <&tsensor 2>;
+
+				trips {
+					threshold: trip-point@0 {
+						temperature = <65000>;
+						hysteresis = <0>;
+						type = "passive";
+					};
+
+					target: trip-point@1 {
+						temperature = <75000>;
+						hysteresis = <0>;
+						type = "passive";
+					};
+				};
+
+				cooling-maps {
+					map0 {
+						trip = <&target>;
+						cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+					};
+				};
+			};
+		};
 	};
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts linux-libre-4.7-gnu/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts	2016-07-24 15:23:50.000000000 -0400
@@ -6,11 +6,9 @@
  */
 
 /dts-v1/;
-
-/*Reserved 1MB memory for MCU*/
-/memreserve/ 0x05e00000 0x00100000;
-
 #include "hi6220.dtsi"
+#include "hikey-pinctrl.dtsi"
+#include <dt-bindings/gpio/gpio.h>
 
 / {
 	model = "HiKey Development Board";
@@ -27,9 +25,201 @@
 		stdout-path = "serial3:115200n8";
 	};
 
+	/*
+	 * Reserve below regions from memory node:
+	 *
+	 *  0x05e0,0000 - 0x05ef,ffff: MCU firmware runtime using
+	 *  0x06df,f000 - 0x06df,ffff: Mailbox message data
+	 *  0x0740,f000 - 0x0740,ffff: MCU firmware section
+	 *  0x3e00,0000 - 0x3fff,ffff: OP-TEE
+	 */
 	memory@0 {
 		device_type = "memory";
-		reg = <0x0 0x0 0x0 0x40000000>;
+		reg = <0x00000000 0x00000000 0x00000000 0x05e00000>,
+		      <0x00000000 0x05f00000 0x00000000 0x00eff000>,
+		      <0x00000000 0x06e00000 0x00000000 0x0060f000>,
+		      <0x00000000 0x07410000 0x00000000 0x36bf0000>;
+	};
+
+	soc {
+		spi0: spi@f7106000 {
+			status = "ok";
+		};
+
+		i2c0: i2c@f7100000 {
+			status = "ok";
+		};
+
+		i2c1: i2c@f7101000 {
+			status = "ok";
+		};
+
+		uart1: uart@f7111000 {
+			status = "ok";
+		};
+
+		uart2: uart@f7112000 {
+			status = "ok";
+		};
+
+		uart3: uart@f7113000 {
+			status = "ok";
+		};
+
+		dwmmc_2: dwmmc2@f723f000 {
+			ti,non-removable;
+			non-removable;
+			/* WL_EN */
+			vmmc-supply = <&wlan_en_reg>;
+
+			#address-cells = <0x1>;
+			#size-cells = <0x0>;
+			wlcore: wlcore@2 {
+				compatible = "ti,wl1835";
+				reg = <2>;	/* sdio func num */
+				/* WL_IRQ, WL_HOST_WAKE_GPIO1_3 */
+				interrupt-parent = <&gpio1>;
+				interrupts = <3 IRQ_TYPE_EDGE_RISING>;
+			};
+		};
+
+		wlan_en_reg: regulator@1 {
+			compatible = "regulator-fixed";
+			regulator-name = "wlan-en-regulator";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			/* WLAN_EN GPIO */
+			gpio = <&gpio0 5 0>;
+			/* WLAN card specific delay */
+			startup-delay-us = <70000>;
+			enable-active-high;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		user_led4 {
+			label = "user_led4";
+			gpios = <&gpio4 0 0>; /* <&gpio_user_led_1>; */
+			linux,default-trigger = "heartbeat";
+		};
+
+		user_led3 {
+			label = "user_led3";
+			gpios = <&gpio4 1 0>; /* <&gpio_user_led_2>; */
+			linux,default-trigger = "mmc0";
+		};
+
+		user_led2 {
+			label = "user_led2";
+			gpios = <&gpio4 2 0>; /* <&gpio_user_led_3>; */
+			linux,default-trigger = "mmc1";
+		};
+
+		user_led1 {
+			label = "user_led1";
+			gpios = <&gpio4 3 0>; /* <&gpio_user_led_4>; */
+			linux,default-trigger = "cpu0";
+		};
+
+		wlan_active_led {
+			label = "wifi_active";
+			gpios = <&gpio3 5 0>; /* <&gpio_wlan_active_led>; */
+			linux,default-trigger = "phy0tx";
+			default-state = "off";
+		};
+
+		bt_active_led {
+			label = "bt_active";
+			gpios = <&gpio4 7 0>; /* <&gpio_bt_active_led>; */
+			linux,default-trigger = "hci0rx";
+			default-state = "off";
+		};
+	};
+
+	pmic: pmic@f8000000 {
+		compatible = "hisilicon,hi655x-pmic";
+		reg = <0x0 0xf8000000 0x0 0x1000>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		pmic-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
+
+		regulators {
+			ldo2: LDO2 {
+				regulator-name = "LDO2_2V8";
+				regulator-min-microvolt = <2500000>;
+				regulator-max-microvolt = <3200000>;
+				regulator-enable-ramp-delay = <120>;
+			};
+
+			ldo7: LDO7 {
+				regulator-name = "LDO7_SDIO";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-enable-ramp-delay = <120>;
+			};
+
+			ldo10: LDO10 {
+				regulator-name = "LDO10_2V85";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-enable-ramp-delay = <360>;
+			};
+
+			ldo13: LDO13 {
+				regulator-name = "LDO13_1V8";
+				regulator-min-microvolt = <1600000>;
+				regulator-max-microvolt = <1950000>;
+				regulator-enable-ramp-delay = <120>;
+			};
+
+			ldo14: LDO14 {
+				regulator-name = "LDO14_2V8";
+				regulator-min-microvolt = <2500000>;
+				regulator-max-microvolt = <3200000>;
+				regulator-enable-ramp-delay = <120>;
+			};
+
+			ldo15: LDO15 {
+				regulator-name = "LDO15_1V8";
+				regulator-min-microvolt = <1600000>;
+				regulator-max-microvolt = <1950000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-enable-ramp-delay = <120>;
+			};
+
+			ldo17: LDO17 {
+				regulator-name = "LDO17_2V5";
+				regulator-min-microvolt = <2500000>;
+				regulator-max-microvolt = <3200000>;
+				regulator-enable-ramp-delay = <120>;
+			};
+
+			ldo19: LDO19 {
+				regulator-name = "LDO19_3V0";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-enable-ramp-delay = <360>;
+			};
+
+			ldo21: LDO21 {
+				regulator-name = "LDO21_1V8";
+				regulator-min-microvolt = <1650000>;
+				regulator-max-microvolt = <2000000>;
+				regulator-always-on;
+				regulator-enable-ramp-delay = <120>;
+			};
+
+			ldo22: LDO22 {
+				regulator-name = "LDO22_1V2";
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <1200000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-enable-ramp-delay = <120>;
+			};
+		};
 	};
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/hisilicon/hikey-pinctrl.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/hisilicon/hikey-pinctrl.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/hisilicon/hikey-pinctrl.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/hisilicon/hikey-pinctrl.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,705 @@
+/*
+ * pinctrl dts fils for Hislicon HiKey development board
+ *
+ */
+#include <dt-bindings/pinctrl/hisi.h>
+
+/ {
+	soc {
+		pmx0: pinmux@f7010000 {
+			pinctrl-names = "default";
+			pinctrl-0 = <
+				&boot_sel_pmx_func
+				&hkadc_ssi_pmx_func
+				&codec_clk_pmx_func
+				&pwm_in_pmx_func
+				&bl_pwm_pmx_func
+				>;
+
+			boot_sel_pmx_func: boot_sel_pmx_func {
+				pinctrl-single,pins = <
+					0x0    MUX_M0	/* BOOT_SEL     (IOMG000) */
+				>;
+			};
+
+			emmc_pmx_func: emmc_pmx_func {
+				pinctrl-single,pins = <
+					0x100  MUX_M0	/* EMMC_CLK     (IOMG064) */
+					0x104  MUX_M0	/* EMMC_CMD     (IOMG065) */
+					0x108  MUX_M0	/* EMMC_DATA0   (IOMG066) */
+					0x10c  MUX_M0	/* EMMC_DATA1   (IOMG067) */
+					0x110  MUX_M0	/* EMMC_DATA2   (IOMG068) */
+					0x114  MUX_M0	/* EMMC_DATA3   (IOMG069) */
+					0x118  MUX_M0	/* EMMC_DATA4   (IOMG070) */
+					0x11c  MUX_M0	/* EMMC_DATA5   (IOMG071) */
+					0x120  MUX_M0	/* EMMC_DATA6   (IOMG072) */
+					0x124  MUX_M0	/* EMMC_DATA7   (IOMG073) */
+				>;
+			};
+
+			sd_pmx_func: sd_pmx_func {
+				pinctrl-single,pins = <
+					0xc    MUX_M0	/* SD_CLK       (IOMG003) */
+					0x10   MUX_M0	/* SD_CMD       (IOMG004) */
+					0x14   MUX_M0	/* SD_DATA0     (IOMG005) */
+					0x18   MUX_M0	/* SD_DATA1     (IOMG006) */
+					0x1c   MUX_M0	/* SD_DATA2     (IOMG007) */
+					0x20   MUX_M0	/* SD_DATA3     (IOMG008) */
+				>;
+			};
+			sd_pmx_idle: sd_pmx_idle {
+				pinctrl-single,pins = <
+					0xc    MUX_M1	/* SD_CLK       (IOMG003) */
+					0x10   MUX_M1	/* SD_CMD       (IOMG004) */
+					0x14   MUX_M1	/* SD_DATA0     (IOMG005) */
+					0x18   MUX_M1	/* SD_DATA1     (IOMG006) */
+					0x1c   MUX_M1	/* SD_DATA2     (IOMG007) */
+					0x20   MUX_M1	/* SD_DATA3     (IOMG008) */
+				>;
+			};
+
+			sdio_pmx_func: sdio_pmx_func {
+				pinctrl-single,pins = <
+					0x128  MUX_M0	/* SDIO_CLK     (IOMG074) */
+					0x12c  MUX_M0	/* SDIO_CMD     (IOMG075) */
+					0x130  MUX_M0	/* SDIO_DATA0   (IOMG076) */
+					0x134  MUX_M0	/* SDIO_DATA1   (IOMG077) */
+					0x138  MUX_M0	/* SDIO_DATA2   (IOMG078) */
+					0x13c  MUX_M0	/* SDIO_DATA3   (IOMG079) */
+				>;
+			};
+			sdio_pmx_idle: sdio_pmx_idle {
+				pinctrl-single,pins = <
+					0x128  MUX_M1	/* SDIO_CLK     (IOMG074) */
+					0x12c  MUX_M1	/* SDIO_CMD     (IOMG075) */
+					0x130  MUX_M1	/* SDIO_DATA0   (IOMG076) */
+					0x134  MUX_M1	/* SDIO_DATA1   (IOMG077) */
+					0x138  MUX_M1	/* SDIO_DATA2   (IOMG078) */
+					0x13c  MUX_M1	/* SDIO_DATA3   (IOMG079) */
+				>;
+			};
+
+			isp_pmx_func: isp_pmx_func {
+				pinctrl-single,pins = <
+					0x24   MUX_M0	/* ISP_PWDN0    (IOMG009) */
+					0x28   MUX_M0	/* ISP_PWDN1    (IOMG010) */
+					0x2c   MUX_M0	/* ISP_PWDN2    (IOMG011) */
+					0x30   MUX_M1	/* ISP_SHUTTER0 (IOMG012) */
+					0x34   MUX_M1	/* ISP_SHUTTER1 (IOMG013) */
+					0x38   MUX_M1	/* ISP_PWM      (IOMG014) */
+					0x3c   MUX_M0	/* ISP_CCLK0    (IOMG015) */
+					0x40   MUX_M0	/* ISP_CCLK1    (IOMG016) */
+					0x44   MUX_M0	/* ISP_RESETB0  (IOMG017) */
+					0x48   MUX_M0	/* ISP_RESETB1  (IOMG018) */
+					0x4c   MUX_M1	/* ISP_STROBE0  (IOMG019) */
+					0x50   MUX_M1	/* ISP_STROBE1  (IOMG020) */
+					0x54   MUX_M0	/* ISP_SDA0     (IOMG021) */
+					0x58   MUX_M0	/* ISP_SCL0     (IOMG022) */
+					0x5c   MUX_M0	/* ISP_SDA1     (IOMG023) */
+					0x60   MUX_M0	/* ISP_SCL1     (IOMG024) */
+				>;
+			};
+
+			hkadc_ssi_pmx_func: hkadc_ssi_pmx_func {
+				pinctrl-single,pins = <
+					0x68   MUX_M0	/* HKADC_SSI    (IOMG026) */
+				>;
+			};
+
+			codec_clk_pmx_func: codec_clk_pmx_func {
+				pinctrl-single,pins = <
+					0x6c   MUX_M0	/* CODEC_CLK    (IOMG027) */
+				>;
+			};
+
+			codec_pmx_func: codec_pmx_func {
+				pinctrl-single,pins = <
+					0x70   MUX_M1	/* DMIC_CLK     (IOMG028) */
+					0x74   MUX_M0	/* CODEC_SYNC   (IOMG029) */
+					0x78   MUX_M0	/* CODEC_DI     (IOMG030) */
+					0x7c   MUX_M0	/* CODEC_DO     (IOMG031) */
+				>;
+			};
+
+			fm_pmx_func: fm_pmx_func {
+				pinctrl-single,pins = <
+					0x80   MUX_M1	/* FM_XCLK      (IOMG032) */
+					0x84   MUX_M1	/* FM_XFS       (IOMG033) */
+					0x88   MUX_M1	/* FM_DI        (IOMG034) */
+					0x8c   MUX_M1	/* FM_DO        (IOMG035) */
+				>;
+			};
+
+			bt_pmx_func: bt_pmx_func {
+				pinctrl-single,pins = <
+					0x90   MUX_M0	/* BT_XCLK      (IOMG036) */
+					0x94   MUX_M0	/* BT_XFS       (IOMG037) */
+					0x98   MUX_M0	/* BT_DI        (IOMG038) */
+					0x9c   MUX_M0	/* BT_DO        (IOMG039) */
+				>;
+			};
+
+			pwm_in_pmx_func: pwm_in_pmx_func {
+				pinctrl-single,pins = <
+					0xb8   MUX_M1	/* PWM_IN       (IOMG046) */
+				>;
+			};
+
+			bl_pwm_pmx_func: bl_pwm_pmx_func {
+				pinctrl-single,pins = <
+					0xbc   MUX_M1	/* BL_PWM       (IOMG047) */
+				>;
+			};
+
+			uart0_pmx_func: uart0_pmx_func {
+				pinctrl-single,pins = <
+					0xc0   MUX_M0	/* UART0_RXD    (IOMG048) */
+					0xc4   MUX_M0	/* UART0_TXD    (IOMG049) */
+				>;
+			};
+
+			uart1_pmx_func: uart1_pmx_func {
+				pinctrl-single,pins = <
+					0xc8   MUX_M0	/* UART1_CTS_N  (IOMG050) */
+					0xcc   MUX_M0	/* UART1_RTS_N  (IOMG051) */
+					0xd0   MUX_M0	/* UART1_RXD    (IOMG052) */
+					0xd4   MUX_M0	/* UART1_TXD    (IOMG053) */
+				>;
+			};
+
+			uart2_pmx_func: uart2_pmx_func {
+				pinctrl-single,pins = <
+					0xd8   MUX_M0	/* UART2_CTS_N  (IOMG054) */
+					0xdc   MUX_M0	/* UART2_RTS_N  (IOMG055) */
+					0xe0   MUX_M0	/* UART2_RXD    (IOMG056) */
+					0xe4   MUX_M0	/* UART2_TXD    (IOMG057) */
+				>;
+			};
+
+			uart3_pmx_func: uart3_pmx_func {
+				pinctrl-single,pins = <
+					0x180  MUX_M1	/* UART3_CTS_N  (IOMG096) */
+					0x184  MUX_M1	/* UART3_RTS_N  (IOMG097) */
+					0x188  MUX_M1	/* UART3_RXD    (IOMG098) */
+					0x18c  MUX_M1	/* UART3_TXD    (IOMG099) */
+				>;
+			};
+
+			uart4_pmx_func: uart4_pmx_func {
+				pinctrl-single,pins = <
+					0x1d0  MUX_M1	/* UART4_CTS_N  (IOMG116) */
+					0x1d4  MUX_M1	/* UART4_RTS_N  (IOMG117) */
+					0x1d8  MUX_M1	/* UART4_RXD    (IOMG118) */
+					0x1dc  MUX_M1	/* UART4_TXD    (IOMG119) */
+				>;
+			};
+
+			uart5_pmx_func: uart5_pmx_func {
+				pinctrl-single,pins = <
+					0x1c8  MUX_M1	/* UART5_RXD    (IOMG114) */
+					0x1cc  MUX_M1	/* UART5_TXD    (IOMG115) */
+				>;
+			};
+
+			i2c0_pmx_func: i2c0_pmx_func {
+				pinctrl-single,pins = <
+					0xe8   MUX_M0	/* I2C0_SCL     (IOMG058) */
+					0xec   MUX_M0	/* I2C0_SDA     (IOMG059) */
+				>;
+			};
+
+			i2c1_pmx_func: i2c1_pmx_func {
+				pinctrl-single,pins = <
+					0xf0   MUX_M0	/* I2C1_SCL     (IOMG060) */
+					0xf4   MUX_M0	/* I2C1_SDA     (IOMG061) */
+				>;
+			};
+
+			i2c2_pmx_func: i2c2_pmx_func {
+				pinctrl-single,pins = <
+					0xf8   MUX_M0	/* I2C2_SCL     (IOMG062) */
+					0xfc   MUX_M0	/* I2C2_SDA     (IOMG063) */
+				>;
+			};
+
+			spi0_pmx_func: spi0_pmx_func {
+				pinctrl-single,pins = <
+					0x1a0  MUX_M1   /* SPI0_DI      (IOMG104) */
+					0x1a4  MUX_M1	/* SPI0_DO	(IOMG105) */
+					0x1a8  MUX_M1	/* SPI0_CS_N	(IOMG106) */
+					0x1ac  MUX_M1	/* SPI0_CLK	(IOMG107) */
+				>;
+			};
+		};
+
+		pmx1: pinmux@f7010800 {
+
+			pinctrl-names = "default";
+			pinctrl-0 = <
+				&boot_sel_cfg_func
+				&hkadc_ssi_cfg_func
+				&codec_clk_cfg_func
+				&pwm_in_cfg_func
+				&bl_pwm_cfg_func
+				>;
+
+			boot_sel_cfg_func: boot_sel_cfg_func {
+				pinctrl-single,pins = <
+					0x0    0x0	/* BOOT_SEL     (IOCFG000) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DIS  PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_UP   PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_02MA DRIVE_MASK>;
+			};
+
+			hkadc_ssi_cfg_func: hkadc_ssi_cfg_func {
+				pinctrl-single,pins = <
+					0x6c   0x0	/* HKADC_SSI    (IOCFG027) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DIS  PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_DIS  PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_02MA DRIVE_MASK>;
+			};
+
+			emmc_clk_cfg_func: emmc_clk_cfg_func {
+				pinctrl-single,pins = <
+					0x104  0x0	/* EMMC_CLK     (IOCFG065) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DIS  PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_DIS  PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_08MA DRIVE_MASK>;
+			};
+
+			emmc_cfg_func: emmc_cfg_func {
+				pinctrl-single,pins = <
+					0x108  0x0	/* EMMC_CMD     (IOCFG066) */
+					0x10c  0x0	/* EMMC_DATA0   (IOCFG067) */
+					0x110  0x0	/* EMMC_DATA1   (IOCFG068) */
+					0x114  0x0	/* EMMC_DATA2   (IOCFG069) */
+					0x118  0x0	/* EMMC_DATA3   (IOCFG070) */
+					0x11c  0x0	/* EMMC_DATA4   (IOCFG071) */
+					0x120  0x0	/* EMMC_DATA5   (IOCFG072) */
+					0x124  0x0	/* EMMC_DATA6   (IOCFG073) */
+					0x128  0x0	/* EMMC_DATA7   (IOCFG074) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DIS  PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_UP   PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_04MA DRIVE_MASK>;
+			};
+
+			emmc_rst_cfg_func: emmc_rst_cfg_func {
+				pinctrl-single,pins = <
+					0x12c  0x0	/* EMMC_RST_N   (IOCFG075) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DIS  PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_DIS  PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_04MA DRIVE_MASK>;
+			};
+
+			sd_clk_cfg_func: sd_clk_cfg_func {
+				pinctrl-single,pins = <
+					0xc    0x0	/* SD_CLK       (IOCFG003) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DIS  PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_DIS  PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_10MA DRIVE_MASK>;
+			};
+			sd_clk_cfg_idle: sd_clk_cfg_idle {
+				pinctrl-single,pins = <
+					0xc    0x0	/* SD_CLK       (IOCFG003) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DOWN PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_DIS  PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_02MA DRIVE_MASK>;
+			};
+
+			sd_cfg_func: sd_cfg_func {
+				pinctrl-single,pins = <
+					0x10   0x0	/* SD_CMD       (IOCFG004) */
+					0x14   0x0	/* SD_DATA0     (IOCFG005) */
+					0x18   0x0	/* SD_DATA1     (IOCFG006) */
+					0x1c   0x0	/* SD_DATA2     (IOCFG007) */
+					0x20   0x0	/* SD_DATA3     (IOCFG008) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DIS  PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_DIS  PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_08MA DRIVE_MASK>;
+			};
+			sd_cfg_idle: sd_cfg_idle {
+				pinctrl-single,pins = <
+					0x10   0x0	/* SD_CMD       (IOCFG004) */
+					0x14   0x0	/* SD_DATA0     (IOCFG005) */
+					0x18   0x0	/* SD_DATA1     (IOCFG006) */
+					0x1c   0x0	/* SD_DATA2     (IOCFG007) */
+					0x20   0x0	/* SD_DATA3     (IOCFG008) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DOWN PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_DIS  PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_02MA DRIVE_MASK>;
+			};
+
+			sdio_clk_cfg_func: sdio_clk_cfg_func {
+				pinctrl-single,pins = <
+					0x134  0x0	/* SDIO_CLK     (IOCFG077) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DIS  PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_DIS  PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_08MA DRIVE_MASK>;
+			};
+			sdio_clk_cfg_idle: sdio_clk_cfg_idle {
+				pinctrl-single,pins = <
+					0x134  0x0	/* SDIO_CLK     (IOCFG077) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DOWN PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_DIS  PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_02MA DRIVE_MASK>;
+			};
+
+			sdio_cfg_func: sdio_cfg_func {
+				pinctrl-single,pins = <
+					0x138  0x0	/* SDIO_CMD     (IOCFG078) */
+					0x13c  0x0	/* SDIO_DATA0   (IOCFG079) */
+					0x140  0x0	/* SDIO_DATA1   (IOCFG080) */
+					0x144  0x0	/* SDIO_DATA2   (IOCFG081) */
+					0x148  0x0	/* SDIO_DATA3   (IOCFG082) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DIS  PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_UP   PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_04MA DRIVE_MASK>;
+			};
+			sdio_cfg_idle: sdio_cfg_idle {
+				pinctrl-single,pins = <
+					0x138  0x0	/* SDIO_CMD     (IOCFG078) */
+					0x13c  0x0	/* SDIO_DATA0   (IOCFG079) */
+					0x140  0x0	/* SDIO_DATA1   (IOCFG080) */
+					0x144  0x0	/* SDIO_DATA2   (IOCFG081) */
+					0x148  0x0	/* SDIO_DATA3   (IOCFG082) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DIS  PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_UP   PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_02MA DRIVE_MASK>;
+			};
+
+			isp_cfg_func1: isp_cfg_func1 {
+				pinctrl-single,pins = <
+					0x28   0x0	/* ISP_PWDN0    (IOCFG010) */
+					0x2c   0x0	/* ISP_PWDN1    (IOCFG011) */
+					0x30   0x0	/* ISP_PWDN2    (IOCFG012) */
+					0x34   0x0	/* ISP_SHUTTER0 (IOCFG013) */
+					0x38   0x0	/* ISP_SHUTTER1 (IOCFG014) */
+					0x3c   0x0	/* ISP_PWM      (IOCFG015) */
+					0x40   0x0	/* ISP_CCLK0    (IOCFG016) */
+					0x44   0x0	/* ISP_CCLK1    (IOCFG017) */
+					0x48   0x0	/* ISP_RESETB0  (IOCFG018) */
+					0x4c   0x0	/* ISP_RESETB1  (IOCFG019) */
+					0x50   0x0	/* ISP_STROBE0  (IOCFG020) */
+					0x58   0x0	/* ISP_SDA0     (IOCFG022) */
+					0x5c   0x0	/* ISP_SCL0     (IOCFG023) */
+					0x60   0x0	/* ISP_SDA1     (IOCFG024) */
+					0x64   0x0	/* ISP_SCL1     (IOCFG025) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DIS  PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_DIS  PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_02MA DRIVE_MASK>;
+			};
+			isp_cfg_idle1: isp_cfg_idle1 {
+				pinctrl-single,pins = <
+					0x34   0x0	/* ISP_SHUTTER0 (IOCFG013) */
+					0x38   0x0	/* ISP_SHUTTER1 (IOCFG014) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DOWN PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_DIS  PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_02MA DRIVE_MASK>;
+			};
+
+			isp_cfg_func2: isp_cfg_func2 {
+				pinctrl-single,pins = <
+					0x54   0x0	/* ISP_STROBE1  (IOCFG021) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DOWN PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_DIS  PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_02MA DRIVE_MASK>;
+			};
+
+			codec_clk_cfg_func: codec_clk_cfg_func {
+				pinctrl-single,pins = <
+					0x70   0x0	/* CODEC_CLK    (IOCFG028) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DIS  PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_DIS  PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_04MA DRIVE_MASK>;
+			};
+			codec_clk_cfg_idle: codec_clk_cfg_idle {
+				pinctrl-single,pins = <
+					0x70   0x0	/* CODEC_CLK    (IOCFG028) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DIS  PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_DIS  PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_02MA DRIVE_MASK>;
+			};
+
+			codec_cfg_func1: codec_cfg_func1 {
+				pinctrl-single,pins = <
+					0x74   0x0	/* DMIC_CLK     (IOCFG029) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DOWN PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_DIS  PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_02MA DRIVE_MASK>;
+			};
+
+			codec_cfg_func2: codec_cfg_func2 {
+				pinctrl-single,pins = <
+					0x78   0x0	/* CODEC_SYNC   (IOCFG030) */
+					0x7c   0x0	/* CODEC_DI     (IOCFG031) */
+					0x80   0x0	/* CODEC_DO     (IOCFG032) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DIS  PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_DIS  PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_04MA DRIVE_MASK>;
+			};
+			codec_cfg_idle2: codec_cfg_idle2 {
+				pinctrl-single,pins = <
+					0x78   0x0	/* CODEC_SYNC   (IOCFG030) */
+					0x7c   0x0	/* CODEC_DI     (IOCFG031) */
+					0x80   0x0	/* CODEC_DO     (IOCFG032) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DIS  PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_DIS  PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_02MA DRIVE_MASK>;
+			};
+
+			fm_cfg_func: fm_cfg_func {
+				pinctrl-single,pins = <
+					0x84   0x0	/* FM_XCLK      (IOCFG033) */
+					0x88   0x0	/* FM_XFS       (IOCFG034) */
+					0x8c   0x0	/* FM_DI        (IOCFG035) */
+					0x90   0x0	/* FM_DO        (IOCFG036) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DOWN PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_DIS  PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_02MA DRIVE_MASK>;
+			};
+
+			bt_cfg_func: bt_cfg_func {
+				pinctrl-single,pins = <
+					0x94   0x0	/* BT_XCLK      (IOCFG037) */
+					0x98   0x0	/* BT_XFS       (IOCFG038) */
+					0x9c   0x0	/* BT_DI        (IOCFG039) */
+					0xa0   0x0	/* BT_DO        (IOCFG040) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DIS  PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_DIS  PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_02MA DRIVE_MASK>;
+			};
+			bt_cfg_idle: bt_cfg_idle {
+				pinctrl-single,pins = <
+					0x94   0x0	/* BT_XCLK      (IOCFG037) */
+					0x98   0x0	/* BT_XFS       (IOCFG038) */
+					0x9c   0x0	/* BT_DI        (IOCFG039) */
+					0xa0   0x0	/* BT_DO        (IOCFG040) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DOWN PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_DIS  PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_02MA DRIVE_MASK>;
+			};
+
+			pwm_in_cfg_func: pwm_in_cfg_func {
+				pinctrl-single,pins = <
+					0xbc   0x0	/* PWM_IN       (IOCFG047) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DOWN PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_DIS  PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_02MA DRIVE_MASK>;
+			};
+
+			bl_pwm_cfg_func: bl_pwm_cfg_func {
+				pinctrl-single,pins = <
+					0xc0   0x0	/* BL_PWM       (IOCFG048) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DOWN PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_DIS  PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_02MA DRIVE_MASK>;
+			};
+
+			uart0_cfg_func1: uart0_cfg_func1 {
+				pinctrl-single,pins = <
+					0xc4   0x0	/* UART0_RXD    (IOCFG049) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DIS  PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_UP   PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_02MA DRIVE_MASK>;
+			};
+
+			uart0_cfg_func2: uart0_cfg_func2 {
+				pinctrl-single,pins = <
+					0xc8   0x0	/* UART0_TXD    (IOCFG050) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DIS  PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_DIS  PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_04MA DRIVE_MASK>;
+			};
+
+			uart1_cfg_func1: uart1_cfg_func1 {
+				pinctrl-single,pins = <
+					0xcc   0x0	/* UART1_CTS_N  (IOCFG051) */
+					0xd4   0x0	/* UART1_RXD    (IOCFG053) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DIS  PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_UP   PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_02MA DRIVE_MASK>;
+			};
+
+			uart1_cfg_func2: uart1_cfg_func2 {
+				pinctrl-single,pins = <
+					0xd0   0x0	/* UART1_RTS_N  (IOCFG052) */
+					0xd8   0x0	/* UART1_TXD    (IOCFG054) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DIS  PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_DIS  PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_02MA DRIVE_MASK>;
+			};
+
+			uart2_cfg_func: uart2_cfg_func {
+				pinctrl-single,pins = <
+					0xdc   0x0	/* UART2_CTS_N  (IOCFG055) */
+					0xe0   0x0	/* UART2_RTS_N  (IOCFG056) */
+					0xe4   0x0	/* UART2_RXD    (IOCFG057) */
+					0xe8   0x0	/* UART2_TXD    (IOCFG058) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DIS  PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_DIS  PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_02MA DRIVE_MASK>;
+			};
+
+			uart3_cfg_func: uart3_cfg_func {
+				pinctrl-single,pins = <
+					0x190  0x0	/* UART3_CTS_N  (IOCFG100) */
+					0x194  0x0	/* UART3_RTS_N  (IOCFG101) */
+					0x198  0x0	/* UART3_RXD    (IOCFG102) */
+					0x19c  0x0	/* UART3_TXD    (IOCFG103) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DOWN PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_DIS  PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_02MA DRIVE_MASK>;
+			};
+
+			uart4_cfg_func: uart4_cfg_func {
+				pinctrl-single,pins = <
+					0x1e0  0x0	/* UART4_CTS_N  (IOCFG120) */
+					0x1e4  0x0	/* UART4_RTS_N  (IOCFG121) */
+					0x1e8  0x0	/* UART4_RXD    (IOCFG122) */
+					0x1ec  0x0	/* UART4_TXD    (IOCFG123) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DOWN PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_DIS  PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_02MA DRIVE_MASK>;
+			};
+
+			uart5_cfg_func: uart5_cfg_func {
+				pinctrl-single,pins = <
+					0x1d8  0x0	/* UART4_RXD    (IOCFG118) */
+					0x1dc  0x0	/* UART4_TXD    (IOCFG119) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DOWN PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_DIS  PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_02MA DRIVE_MASK>;
+			};
+
+			i2c0_cfg_func: i2c0_cfg_func {
+				pinctrl-single,pins = <
+					0xec   0x0	/* I2C0_SCL     (IOCFG059) */
+					0xf0   0x0	/* I2C0_SDA     (IOCFG060) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DIS  PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_DIS  PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_02MA DRIVE_MASK>;
+			};
+
+			i2c1_cfg_func: i2c1_cfg_func {
+				pinctrl-single,pins = <
+					0xf4   0x0	/* I2C1_SCL     (IOCFG061) */
+					0xf8   0x0	/* I2C1_SDA     (IOCFG062) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DIS  PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_DIS  PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_02MA DRIVE_MASK>;
+			};
+
+			i2c2_cfg_func: i2c2_cfg_func {
+				pinctrl-single,pins = <
+					0xfc   0x0	/* I2C2_SCL     (IOCFG063) */
+					0x100  0x0	/* I2C2_SDA     (IOCFG064) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DIS  PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_DIS  PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_02MA DRIVE_MASK>;
+			};
+
+			spi0_cfg_func: spi0_cfg_func {
+				pinctrl-single,pins = <
+					0x1b0  0x0	/* SPI0_DI	(IOCFG108) */
+					0x1b4  0x0	/* SPI0_DO	(IOCFG109) */
+					0x1b8  0x0	/* SPI0_CS_N	(IOCFG110) */
+					0x1bc  0x0	/* SPI0_CLK	(IOCFG111) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DIS  PULL_DOWN PULL_DIS PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_DIS  PULL_UP   PULL_DIS PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_02MA DRIVE_MASK>;
+			};
+		};
+
+		pmx2: pinmux@f8001800 {
+
+			pinctrl-names = "default";
+			pinctrl-0 = <
+				&rstout_n_cfg_func
+				>;
+
+			rstout_n_cfg_func: rstout_n_cfg_func {
+				pinctrl-single,pins = <
+					0x0    0x0	/* RSTOUT_N     (IOCFG000) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DIS  PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_DIS  PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_02MA DRIVE_MASK>;
+			};
+
+			pmu_peri_en_cfg_func: pmu_peri_en_cfg_func {
+				pinctrl-single,pins = <
+					0x4    0x0	/* PMU_PERI_EN  (IOCFG001) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DIS  PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_DIS  PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_02MA DRIVE_MASK>;
+			};
+
+			sysclk0_en_cfg_func: sysclk0_en_cfg_func {
+				pinctrl-single,pins = <
+					0x8    0x0	/* SYSCLK0_EN   (IOCFG002) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DIS  PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_DIS  PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_02MA DRIVE_MASK>;
+			};
+
+			jtag_tdo_cfg_func: jtag_tdo_cfg_func {
+				pinctrl-single,pins = <
+					0xc    0x0	/* JTAG_TDO     (IOCFG003) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DIS  PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_DIS  PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_08MA DRIVE_MASK>;
+			};
+
+			rf_reset_cfg_func: rf_reset_cfg_func {
+				pinctrl-single,pins = <
+					0x70   0x0	/* RF_RESET0    (IOCFG028) */
+					0x74   0x0	/* RF_RESET1    (IOCFG029) */
+				>;
+				pinctrl-single,bias-pulldown  = <PULL_DIS  PULL_DOWN PULL_DIS  PULL_DOWN>;
+				pinctrl-single,bias-pullup    = <PULL_DIS  PULL_UP   PULL_DIS  PULL_UP>;
+				pinctrl-single,drive-strength = <DRIVE1_02MA DRIVE_MASK>;
+			};
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/hisilicon/hip05-d02.dts linux-libre-4.7-gnu/arch/arm64/boot/dts/hisilicon/hip05-d02.dts
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/hisilicon/hip05-d02.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/hisilicon/hip05-d02.dts	2016-07-24 15:23:50.000000000 -0400
@@ -52,3 +52,37 @@
 &peri_gpio0 {
 	status = "ok";
 };
+
+&lbc {
+	status = "ok";
+	#address-cells = <2>;
+	#size-cells = <1>;
+	ranges = <0 0 0x0 0x90000000 0x08000000>,
+		 <1 0 0x0 0x98000000 0x08000000>;
+
+	nor-flash@0,0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "numonyx,js28f00a", "cfi-flash";
+		reg = <0 0x0 0x08000000>;
+		bank-width = <2>;
+		/* The three parts may not used */
+		partition@0 {
+			label = "BIOS";
+			reg = <0x0 0x300000>;
+		};
+		partition@300000 {
+			label = "Linux";
+			reg = <0x300000 0xa00000>;
+		};
+		partition@1000000 {
+			label = "Rootfs";
+			reg = <0x01000000 0x02000000>;
+		};
+	};
+
+	cpld@1,0 {
+		compatible = "hisilicon,hip05-cpld";
+		reg = <1 0x0 0x100>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/hisilicon/hip05.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/hisilicon/hip05.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/hisilicon/hip05.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/hisilicon/hip05.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -249,24 +249,28 @@
 		its_peri: interrupt-controller@8c000000 {
 			compatible = "arm,gic-v3-its";
 			msi-controller;
+			#msi-cells = <1>;
 			reg = <0x0 0x8c000000 0x0 0x40000>;
 		};
 
 		its_m3: interrupt-controller@a3000000 {
 			compatible = "arm,gic-v3-its";
 			msi-controller;
+			#msi-cells = <1>;
 			reg = <0x0 0xa3000000 0x0 0x40000>;
 		};
 
 		its_pcie: interrupt-controller@b7000000 {
 			compatible = "arm,gic-v3-its";
 			msi-controller;
+			#msi-cells = <1>;
 			reg = <0x0 0xb7000000 0x0 0x40000>;
 		};
 
 		its_dsa: interrupt-controller@c6000000 {
 			compatible = "arm,gic-v3-its";
 			msi-controller;
+			#msi-cells = <1>;
 			reg = <0x0 0xc6000000 0x0 0x40000>;
 		};
 	};
@@ -323,6 +327,12 @@
 			status = "disabled";
 		};
 
+		lbc: localbus@80380000 {
+			compatible = "hisilicon,hisi-localbus", "simple-bus";
+			reg = <0x0 0x80380000 0x0 0x10000>;
+			status = "disabled";
+		};
+
 		peri_gpio0: gpio@802e0000 {
 			#address-cells = <1>;
 			#size-cells = <0>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/hisilicon/hip05_hns.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/hisilicon/hip05_hns.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/hisilicon/hip05_hns.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/hisilicon/hip05_hns.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -24,17 +24,19 @@ soc0: soc@000000000 {
 	};
 
 	dsaf0: dsa@c7000000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
 		compatible = "hisilicon,hns-dsaf-v1";
 		mode = "6port-16rss";
 		interrupt-parent = <&mbigen_dsa>;
 
-		reg = <0x0 0xC0000000 0x0 0x420000
-		       0x0 0xC2000000 0x0 0x300000
-		       0x0 0xc5000000 0x0 0x890000
+		reg = <0x0 0xc5000000 0x0 0x890000
 		       0x0 0xc7000000 0x0 0x60000
 		       >;
 
-		phy-handle = <0 0 0 0 &soc0_phy0 &soc0_phy1 0 0>;
+		reg-names = "ppe-base","dsaf-base";
+		subctrl-syscon = <&dsaf_subctrl>;
+		reset-field-offset = <0>;
 		interrupts = <
 			/* [14] ge fifo err 8 / xge 6**/
 			149 0x4 150 0x4 151 0x4 152 0x4
@@ -122,12 +124,31 @@ soc0: soc@000000000 {
 		buf-size = <4096>;
 		desc-num = <1024>;
 		dma-coherent;
+
+		port@0 {
+			reg = <0>;
+			serdes-syscon = <&serdes_ctrl0>;
+		};
+		port@1 {
+			reg = <1>;
+			serdes-syscon = <&serdes_ctrl0>;
+		};
+		port@4 {
+			reg = <4>;
+			phy-handle = <&soc0_phy0>;
+			serdes-syscon = <&serdes_ctrl1>;
+		};
+		port@5 {
+			reg = <5>;
+			phy-handle = <&soc0_phy1>;
+			serdes-syscon = <&serdes_ctrl1>;
+		};
 	};
 
 	eth0: ethernet@0{
 		compatible = "hisilicon,hns-nic-v1";
 		ae-handle = <&dsaf0>;
-		port-id = <0>;
+		port-idx-in-ae = <0>;
 		local-mac-address = [00 00 00 01 00 58];
 		status = "disabled";
 		dma-coherent;
@@ -135,56 +156,25 @@ soc0: soc@000000000 {
 	eth1: ethernet@1{
 		compatible = "hisilicon,hns-nic-v1";
 		ae-handle = <&dsaf0>;
-		port-id = <1>;
+		port-idx-in-ae = <1>;
+		local-mac-address = [00 00 00 01 00 59];
 		status = "disabled";
 		dma-coherent;
 	};
-	eth2: ethernet@2{
+	eth2: ethernet@4{
 		compatible = "hisilicon,hns-nic-v1";
 		ae-handle = <&dsaf0>;
-		port-id = <2>;
+		port-idx-in-ae = <4>;
 		local-mac-address = [00 00 00 01 00 5a];
 		status = "disabled";
 		dma-coherent;
 	};
-	eth3: ethernet@3{
+	eth3: ethernet@5{
 		compatible = "hisilicon,hns-nic-v1";
 		ae-handle = <&dsaf0>;
-		port-id = <3>;
+		port-idx-in-ae = <5>;
 		local-mac-address = [00 00 00 01 00 5b];
 		status = "disabled";
 		dma-coherent;
 	};
-	eth4: ethernet@4{
-		compatible = "hisilicon,hns-nic-v1";
-		ae-handle = <&dsaf0>;
-		port-id = <4>;
-		local-mac-address = [00 00 00 01 00 5c];
-		status = "disabled";
-		dma-coherent;
-	};
-	eth5: ethernet@5{
-		compatible = "hisilicon,hns-nic-v1";
-		ae-handle = <&dsaf0>;
-		port-id = <5>;
-		local-mac-address = [00 00 00 01 00 5d];
-		status = "disabled";
-		dma-coherent;
-	};
-	eth6: ethernet@6{
-		compatible = "hisilicon,hns-nic-v1";
-		ae-handle = <&dsaf0>;
-		port-id = <6>;
-		local-mac-address = [00 00 00 01 00 5e];
-		status = "disabled";
-		dma-coherent;
-	};
-	eth7: ethernet@7{
-		compatible = "hisilicon,hns-nic-v1";
-		ae-handle = <&dsaf0>;
-		port-id = <7>;
-		local-mac-address = [00 00 00 01 00 5f];
-		status = "disabled";
-		dma-coherent;
-	};
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/hisilicon/hip06-d03.dts linux-libre-4.7-gnu/arch/arm64/boot/dts/hisilicon/hip06-d03.dts
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/hisilicon/hip06-d03.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/hisilicon/hip06-d03.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,34 @@
+/**
+ * dts file for Hisilicon D03 Development Board
+ *
+ * Copyright (C) 2016 Hisilicon Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * publishhed by the Free Software Foundation.
+ *
+ */
+
+/dts-v1/;
+
+#include "hip06.dtsi"
+
+/ {
+	model = "Hisilicon Hip06 D03 Development Board";
+	compatible = "hisilicon,hip06-d03";
+
+	memory@00000000 {
+		device_type = "memory";
+		reg = <0x0 0x00000000 0x0 0x40000000>;
+	};
+
+	chosen { };
+};
+
+&usb_ohci {
+	status = "ok";
+};
+
+&usb_ehci {
+	status = "ok";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/hisilicon/hip06.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/hisilicon/hip06.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/hisilicon/hip06.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/hisilicon/hip06.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,307 @@
+/**
+ * dts file for Hisilicon D03 Development Board
+ *
+ * Copyright (C) 2016 Hisilicon Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * publishhed by the Free Software Foundation.
+ *
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+	compatible = "hisilicon,hip06-d03";
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	psci {
+		compatible = "arm,psci-0.2";
+		method = "smc";
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu-map {
+			cluster0 {
+				core0 {
+					cpu = <&cpu0>;
+				};
+				core1 {
+					cpu = <&cpu1>;
+				};
+				core2 {
+					cpu = <&cpu2>;
+				};
+				core3 {
+					cpu = <&cpu3>;
+				};
+			};
+			cluster1 {
+				core0 {
+					cpu = <&cpu4>;
+				};
+				core1 {
+					cpu = <&cpu5>;
+				};
+				core2 {
+					cpu = <&cpu6>;
+				};
+				core3 {
+					cpu = <&cpu7>;
+				};
+			};
+			cluster2 {
+				core0 {
+					cpu = <&cpu8>;
+				};
+				core1 {
+					cpu = <&cpu9>;
+				};
+				core2 {
+					cpu = <&cpu10>;
+				};
+				core3 {
+					cpu = <&cpu11>;
+				};
+			};
+			cluster3 {
+				core0 {
+					cpu = <&cpu12>;
+				};
+				core1 {
+					cpu = <&cpu13>;
+				};
+				core2 {
+					cpu = <&cpu14>;
+				};
+				core3 {
+					cpu = <&cpu15>;
+				};
+			};
+		};
+
+		cpu0: cpu@10000 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a57", "arm,armv8";
+			reg = <0x10000>;
+			enable-method = "psci";
+			next-level-cache = <&cluster0_l2>;
+		};
+
+		cpu1: cpu@10001 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a57", "arm,armv8";
+			reg = <0x10001>;
+			enable-method = "psci";
+			next-level-cache = <&cluster0_l2>;
+		};
+
+		cpu2: cpu@10002 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a57", "arm,armv8";
+			reg = <0x10002>;
+			enable-method = "psci";
+			next-level-cache = <&cluster0_l2>;
+		};
+
+		cpu3: cpu@10003 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a57", "arm,armv8";
+			reg = <0x10003>;
+			enable-method = "psci";
+			next-level-cache = <&cluster0_l2>;
+		};
+
+		cpu4: cpu@10100 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a57", "arm,armv8";
+			reg = <0x10100>;
+			enable-method = "psci";
+			next-level-cache = <&cluster1_l2>;
+		};
+
+		cpu5: cpu@10101 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a57", "arm,armv8";
+			reg = <0x10101>;
+			enable-method = "psci";
+			next-level-cache = <&cluster1_l2>;
+		};
+
+		cpu6: cpu@10102 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a57", "arm,armv8";
+			reg = <0x10102>;
+			enable-method = "psci";
+			next-level-cache = <&cluster1_l2>;
+		};
+
+		cpu7: cpu@10103 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a57", "arm,armv8";
+			reg = <0x10103>;
+			enable-method = "psci";
+			next-level-cache = <&cluster1_l2>;
+		};
+
+		cpu8: cpu@10200 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a57", "arm,armv8";
+			reg = <0x10200>;
+			enable-method = "psci";
+			next-level-cache = <&cluster2_l2>;
+		};
+
+		cpu9: cpu@10201 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a57", "arm,armv8";
+			reg = <0x10201>;
+			enable-method = "psci";
+			next-level-cache = <&cluster2_l2>;
+		};
+
+		cpu10: cpu@10202 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a57", "arm,armv8";
+			reg = <0x10202>;
+			enable-method = "psci";
+			next-level-cache = <&cluster2_l2>;
+		};
+
+		cpu11: cpu@10203 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a57", "arm,armv8";
+			reg = <0x10203>;
+			enable-method = "psci";
+			next-level-cache = <&cluster2_l2>;
+		};
+
+		cpu12: cpu@10300 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a57", "arm,armv8";
+			reg = <0x10300>;
+			enable-method = "psci";
+			next-level-cache = <&cluster3_l2>;
+		};
+
+		cpu13: cpu@10301 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a57", "arm,armv8";
+			reg = <0x10301>;
+			enable-method = "psci";
+			next-level-cache = <&cluster3_l2>;
+		};
+
+		cpu14: cpu@10302 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a57", "arm,armv8";
+			reg = <0x10302>;
+			enable-method = "psci";
+			next-level-cache = <&cluster3_l2>;
+		};
+
+		cpu15: cpu@10303 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a57", "arm,armv8";
+			reg = <0x10303>;
+			enable-method = "psci";
+			next-level-cache = <&cluster3_l2>;
+		};
+
+		cluster0_l2: l2-cache0 {
+			compatible = "cache";
+		};
+
+		cluster1_l2: l2-cache1 {
+			compatible = "cache";
+		};
+
+		cluster2_l2: l2-cache2 {
+			compatible = "cache";
+		};
+
+		cluster3_l2: l2-cache3 {
+			compatible = "cache";
+		};
+	};
+
+	gic: interrupt-controller@4d000000 {
+		compatible = "arm,gic-v3";
+		#interrupt-cells = <3>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+		interrupt-controller;
+		#redistributor-regions = <1>;
+		redistributor-stride = <0x0 0x30000>;
+		reg = <0x0 0x4d000000 0 0x10000>,	/* GICD */
+		      <0x0 0x4d100000 0 0x300000>,	/* GICR */
+		      <0x0 0xfe000000 0 0x10000>,	/* GICC */
+		      <0x0 0xfe010000 0 0x10000>,       /* GICH */
+		      <0x0 0xfe020000 0 0x10000>;       /* GICV */
+		interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+
+		its_dsa: interrupt-controller@c6000000 {
+			compatible = "arm,gic-v3-its";
+			msi-controller;
+			#msi-cells = <1>;
+			reg = <0x0 0xc6000000 0x0 0x40000>;
+		};
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+	};
+
+	pmu {
+		compatible = "arm,cortex-a57-pmu";
+		interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	mbigen_pcie@a0080000 {
+		compatible = "hisilicon,mbigen-v2";
+		reg = <0x0 0xa0080000 0x0 0x10000>;
+
+		mbigen_usb: intc_usb {
+			msi-parent = <&its_dsa 0x40080>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			num-pins = <2>;
+		};
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		usb_ohci: ohci@a7030000 {
+			compatible = "generic-ohci";
+			reg = <0x0 0xa7030000 0x0 0x10000>;
+			interrupt-parent = <&mbigen_usb>;
+			interrupts = <64 4>;
+			dma-coherent;
+			status = "disabled";
+		};
+
+		usb_ehci: ehci@a7020000 {
+			compatible = "generic-ehci";
+			reg = <0x0 0xa7020000 0x0 0x10000>;
+			interrupt-parent = <&mbigen_usb>;
+			interrupts = <65 4>;
+			dma-coherent;
+			status = "disabled";
+		};
+	};
+
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/hisilicon/Makefile linux-libre-4.7-gnu/arch/arm64/boot/dts/hisilicon/Makefile
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/hisilicon/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/hisilicon/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -1,4 +1,6 @@
-dtb-$(CONFIG_ARCH_HISI) += hi6220-hikey.dtb hip05-d02.dtb
+dtb-$(CONFIG_ARCH_HISI) += hi6220-hikey.dtb
+dtb-$(CONFIG_ARCH_HISI) += hip05-d02.dtb
+dtb-$(CONFIG_ARCH_HISI) += hip06-d03.dtb
 
 always		:= $(dtb-y)
 subdir-y	:= $(dts-dirs)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/lg/lg1312.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/lg/lg1312.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/lg/lg1312.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/lg/lg1312.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,351 @@
+/*
+ * dts file for lg1312 SoC
+ *
+ * Copyright (C) 2016, LG Electronics
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	compatible = "lge,lg1312";
+	interrupt-parent = <&gic>;
+
+	cpus {
+		#address-cells = <2>;
+		#size-cells = <0>;
+
+		cpu0: cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x0>;
+			next-level-cache = <&L2_0>;
+		};
+		cpu1: cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x1>;
+			enable-method = "psci";
+			next-level-cache = <&L2_0>;
+		};
+		cpu2: cpu@2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x2>;
+			enable-method = "psci";
+			next-level-cache = <&L2_0>;
+		};
+		cpu3: cpu@3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x3>;
+			enable-method = "psci";
+			next-level-cache = <&L2_0>;
+		};
+		L2_0: l2-cache0 {
+			compatible = "cache";
+		};
+	};
+
+	psci {
+		compatible  = "arm,psci-0.2", "arm,psci";
+		method = "smc";
+		cpu_suspend = <0x84000001>;
+		cpu_off = <0x84000002>;
+		cpu_on = <0x84000003>;
+	};
+
+	gic: interrupt-controller@c0001000 {
+		#interrupt-cells = <3>;
+		compatible = "arm,gic-400";
+		interrupt-controller;
+		reg = <0x0 0xc0001000 0x1000>,
+		      <0x0 0xc0002000 0x2000>,
+		      <0x0 0xc0004000 0x2000>,
+		      <0x0 0xc0006000 0x2000>;
+	};
+
+	pmu {
+		compatible = "arm,cortex-a53-pmu";
+		interrupts = <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-affinity = <&cpu0>,
+				     <&cpu1>,
+				     <&cpu2>,
+				     <&cpu3>;
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_RAW(0x0f) |
+			      IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 14 (GIC_CPU_MASK_RAW(0x0f) |
+			      IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 11 (GIC_CPU_MASK_RAW(0x0f) |
+			      IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 10 (GIC_CPU_MASK_RAW(0x0f) |
+			      IRQ_TYPE_LEVEL_LOW)>;
+	};
+
+	clk_bus: clk_bus {
+		#clock-cells = <0>;
+
+		compatible = "fixed-clock";
+		clock-frequency = <198000000>;
+		clock-output-names = "BUSCLK";
+	};
+
+	soc {
+		#address-cells = <2>;
+		#size-cells = <1>;
+
+		compatible = "simple-bus";
+		interrupt-parent = <&gic>;
+		ranges;
+
+		eth0: ethernet@c1b00000 {
+			compatible = "cdns,gem";
+			reg = <0x0 0xc1b00000 0x1000>;
+			interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clk_bus>, <&clk_bus>;
+			clock-names = "hclk", "pclk";
+			phy-mode = "rmii";
+			/* Filled in by boot */
+			mac-address = [ 00 00 00 00 00 00 ];
+		};
+	};
+
+	amba {
+		#address-cells = <2>;
+		#size-cells = <1>;
+		#interrupts-cells = <3>;
+
+		compatible = "simple-bus";
+		interrupt-parent = <&gic>;
+		ranges;
+
+		timers: timer@fd100000 {
+			compatible = "arm,sp804";
+			reg = <0x0 0xfd100000 0x1000>;
+			interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+		};
+		wdog: watchdog@fd200000 {
+			compatible = "arm,sp805", "arm,primecell";
+			reg = <0x0 0xfd200000 0x1000>;
+			interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+		};
+		uart0: serial@fe000000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0x0 0xfe000000 0x1000>;
+			interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+			status="disabled";
+		};
+		uart1: serial@fe100000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0x0 0xfe100000 0x1000>;
+			interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+			status="disabled";
+		};
+		uart2: serial@fe200000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0x0 0xfe200000 0x1000>;
+			interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+			status="disabled";
+		};
+		spi0: ssp@fe800000 {
+			compatible = "arm,pl022", "arm,primecell";
+			reg = <0x0 0xfe800000 0x1000>;
+			interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+		};
+		spi1: ssp@fe900000 {
+			compatible = "arm,pl022", "arm,primecell";
+			reg = <0x0 0xfe900000 0x1000>;
+			interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+		};
+		dmac0: dma@c1128000 {
+			compatible = "arm,pl330", "arm,primecell";
+			reg = <0x0 0xc1128000 0x1000>;
+			interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+		};
+		gpio0: gpio@fd400000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0x0 0xfd400000 0x1000>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+			status="disabled";
+		};
+		gpio1: gpio@fd410000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0x0 0xfd410000 0x1000>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+			status="disabled";
+		};
+		gpio2: gpio@fd420000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0x0 0xfd420000 0x1000>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+			status="disabled";
+		};
+		gpio3: gpio@fd430000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0x0 0xfd430000 0x1000>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+		};
+		gpio4: gpio@fd440000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0x0 0xfd440000 0x1000>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+			status="disabled";
+		};
+		gpio5: gpio@fd450000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0x0 0xfd450000 0x1000>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+			status="disabled";
+		};
+		gpio6: gpio@fd460000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0x0 0xfd460000 0x1000>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+			status="disabled";
+		};
+		gpio7: gpio@fd470000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0x0 0xfd470000 0x1000>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+			status="disabled";
+		};
+		gpio8: gpio@fd480000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0x0 0xfd480000 0x1000>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+			status="disabled";
+		};
+		gpio9: gpio@fd490000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0x0 0xfd490000 0x1000>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+			status="disabled";
+		};
+		gpio10: gpio@fd4a0000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0x0 0xfd4a0000 0x1000>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+			status="disabled";
+		};
+		gpio11: gpio@fd4b0000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0x0 0xfd4b0000 0x1000>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+		};
+		gpio12: gpio@fd4c0000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0x0 0xfd4c0000 0x1000>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+			status="disabled";
+		};
+		gpio13: gpio@fd4d0000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0x0 0xfd4d0000 0x1000>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+			status="disabled";
+		};
+		gpio14: gpio@fd4e0000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0x0 0xfd4e0000 0x1000>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+			status="disabled";
+		};
+		gpio15: gpio@fd4f0000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0x0 0xfd4f0000 0x1000>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+			status="disabled";
+		};
+		gpio16: gpio@fd500000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0x0 0xfd500000 0x1000>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+			status="disabled";
+		};
+		gpio17: gpio@fd510000 {
+			#gpio-cells = <2>;
+			compatible = "arm,pl061", "arm,primecell";
+			gpio-controller;
+			reg = <0x0 0xfd510000 0x1000>;
+			clocks = <&clk_bus>;
+			clock-names = "apb_pclk";
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/lg/lg1312-ref.dts linux-libre-4.7-gnu/arch/arm64/boot/dts/lg/lg1312-ref.dts
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/lg/lg1312-ref.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/lg/lg1312-ref.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,36 @@
+/*
+ * dts file for lg1312 Reference Board.
+ *
+ * Copyright (C) 2016, LG Electronics
+ */
+
+/dts-v1/;
+
+#include "lg1312.dtsi"
+
+/ {
+	#address-cells = <2>;
+	#size-cells = <1>;
+
+	model = "LG Electronics, DTV SoC LG1312 Reference Board";
+	compatible = "lge,lg1312-ref", "lge,lg1312";
+
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x0 0x00000000 0x20000000>;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/lg/Makefile linux-libre-4.7-gnu/arch/arm64/boot/dts/lg/Makefile
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/lg/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/lg/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,5 @@
+dtb-$(CONFIG_ARCH_LG1K) += lg1312-ref.dtb
+
+always		:= $(dtb-y)
+subdir-y	:= $(dts-dirs)
+clean-files	:= *.dtb
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/Makefile linux-libre-4.7-gnu/arch/arm64/boot/dts/Makefile
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -18,6 +18,7 @@ dts-dirs += rockchip
 dts-dirs += socionext
 dts-dirs += sprd
 dts-dirs += xilinx
+dts-dirs += lg
 
 subdir-y	:= $(dts-dirs)
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/marvell/armada-3720-db.dts linux-libre-4.7-gnu/arch/arm64/boot/dts/marvell/armada-3720-db.dts
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/marvell/armada-3720-db.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/marvell/armada-3720-db.dts	2016-07-24 15:23:50.000000000 -0400
@@ -60,27 +60,19 @@
 		device_type = "memory";
 		reg = <0x00000000 0x00000000 0x00000000 0x20000000>;
 	};
+};
 
-	soc {
-		internal-regs {
-			/*
-			* Exported on the micro USB connector CON32
-			* through an FTDI
-			*/
-			uart0: serial@12000 {
-				status = "okay";
-			};
-
-			/* CON31 */
-			usb3@58000 {
-				status = "okay";
-			};
+/* CON3 */
+&sata {
+	status = "okay";
+};
 
-			/* CON3 */
-			sata@e0000 {
-			       status = "okay";
-			};
-		};
-	};
+/* Exported on the micro USB connector CON32 through an FTDI */
+&uart0 {
+	status = "okay";
 };
 
+/* CON31 */
+&usb3 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/marvell/armada-372x.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/marvell/armada-372x.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/marvell/armada-372x.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/marvell/armada-372x.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -59,5 +59,4 @@
 			enable-method = "psci";
 		};
 	};
-
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/marvell/armada-37xx.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/marvell/armada-37xx.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/marvell/armada-37xx.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -105,14 +105,28 @@
 				status = "disabled";
 			};
 
-			usb3@58000 {
-				compatible = "generic-xhci";
+			usb3: usb@58000 {
+				compatible = "marvell,armada3700-xhci",
+				"generic-xhci";
 				reg = <0x58000 0x4000>;
 				interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
 				status = "disabled";
 			};
 
-			sata@e0000 {
+			xor@60900 {
+				compatible = "marvell,armada-3700-xor";
+				reg = <0x60900 0x100
+				       0x60b00 0x100>;
+
+				xor10 {
+					interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
+				};
+				xor11 {
+					interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+				};
+			};
+
+			sata: sata@e0000 {
 				compatible = "marvell,armada-3700-ahci";
 				reg = <0xe0000 0x2000>;
 				interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/marvell/armada-7020.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/marvell/armada-7020.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/marvell/armada-7020.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/marvell/armada-7020.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -46,6 +46,7 @@
  */
 
 #include "armada-ap806-dual.dtsi"
+#include "armada-cp110-master.dtsi"
 
 / {
 	model = "Marvell Armada 7020";
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/marvell/armada-7040-db.dts linux-libre-4.7-gnu/arch/arm64/boot/dts/marvell/armada-7040-db.dts
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/marvell/armada-7040-db.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/marvell/armada-7040-db.dts	2016-07-24 15:23:50.000000000 -0400
@@ -51,42 +51,98 @@
 	compatible = "marvell,armada7040-db", "marvell,armada7040",
 		     "marvell,armada-ap806-quad", "marvell,armada-ap806";
 
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
 	memory@00000000 {
 		device_type = "memory";
 		reg = <0x0 0x0 0x0 0x80000000>;
 	};
+};
 
-	ap806 {
-		config-space {
-			spi@510600 {
-				status = "okay";
+&i2c0 {
+	status = "okay";
+	clock-frequency = <100000>;
+};
 
-				spi-flash@0 {
-					#address-cells = <1>;
-					#size-cells = <1>;
-					compatible = "n25q128a13";
-					reg = <0>; /* Chip select 0 */
-					spi-max-frequency = <10000000>;
+&spi0 {
+	status = "okay";
 
-					partition@0 {
-						label = "U-Boot";
-						reg = <0 0x200000>;
-					};
-					partition@400000 {
-						label = "Filesystem";
-						reg = <0x200000 0xce0000>;
-					};
-				};
+	spi-flash@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-max-frequency = <10000000>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "U-Boot";
+				reg = <0 0x200000>;
 			};
+			partition@400000 {
+				label = "Filesystem";
+				reg = <0x200000 0xce0000>;
+			};
+		};
+	};
+};
 
-			i2c@511000 {
-				status = "okay";
-				clock-frequency = <100000>;
+&uart0 {
+	status = "okay";
+};
+
+
+&cpm_pcie2 {
+	status = "okay";
+};
+
+&cpm_i2c0 {
+	status = "okay";
+	clock-frequency = <100000>;
+};
+
+&cpm_spi1 {
+	status = "okay";
+
+	spi-flash@0 {
+		#address-cells = <0x1>;
+		#size-cells = <0x1>;
+		compatible = "jedec,spi-nor";
+		reg = <0x0>;
+		spi-max-frequency = <20000000>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "U-Boot";
+				reg = <0x0 0x200000>;
 			};
 
-			serial@512000 {
-				status = "okay";
+			partition@400000 {
+				label = "Filesystem";
+				reg = <0x200000 0xe00000>;
 			};
 		};
 	};
 };
+
+&cpm_sata0 {
+	status = "okay";
+};
+
+&cpm_usb3_0 {
+	status = "okay";
+};
+
+&cpm_usb3_1 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/marvell/armada-7040.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/marvell/armada-7040.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/marvell/armada-7040.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/marvell/armada-7040.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -46,6 +46,7 @@
  */
 
 #include "armada-ap806-quad.dtsi"
+#include "armada-cp110-master.dtsi"
 
 / {
 	model = "Marvell Armada 7040";
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/marvell/armada-8020.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/marvell/armada-8020.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/marvell/armada-8020.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/marvell/armada-8020.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -46,6 +46,7 @@
  */
 
 #include "armada-ap806-dual.dtsi"
+#include "armada-cp110-master.dtsi"
 
 / {
 	model = "Marvell Armada 8020";
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/marvell/armada-8040.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/marvell/armada-8040.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/marvell/armada-8040.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/marvell/armada-8040.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -46,6 +46,7 @@
  */
 
 #include "armada-ap806-quad.dtsi"
+#include "armada-cp110-master.dtsi"
 
 / {
 	model = "Marvell Armada 8040";
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/marvell/armada-ap806.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/marvell/armada-ap806.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/marvell/armada-ap806.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/marvell/armada-ap806.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -54,12 +54,16 @@
 	#address-cells = <2>;
 	#size-cells = <2>;
 
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+	};
+
 	psci {
 		compatible = "arm,psci-0.2";
 		method = "smc";
 	};
 
-
 	ap806 {
 		#address-cells = <2>;
 		#size-cells = <2>;
@@ -136,7 +140,7 @@
 				marvell,spi-base = <128>, <136>, <144>, <152>;
 			};
 
-			xor0@400000 {
+			xor@400000 {
 				compatible = "marvell,mv-xor-v2";
 				reg = <0x400000 0x1000>,
 				      <0x410000 0x1000>;
@@ -144,7 +148,7 @@
 				dma-coherent;
 			};
 
-			xor1@420000 {
+			xor@420000 {
 				compatible = "marvell,mv-xor-v2";
 				reg = <0x420000 0x1000>,
 				      <0x430000 0x1000>;
@@ -152,7 +156,7 @@
 				dma-coherent;
 			};
 
-			xor2@440000 {
+			xor@440000 {
 				compatible = "marvell,mv-xor-v2";
 				reg = <0x440000 0x1000>,
 				      <0x450000 0x1000>;
@@ -160,7 +164,7 @@
 				dma-coherent;
 			};
 
-			xor3@460000 {
+			xor@460000 {
 				compatible = "marvell,mv-xor-v2";
 				reg = <0x460000 0x1000>,
 				      <0x470000 0x1000>;
@@ -175,63 +179,51 @@
 				#size-cells = <0>;
 				cell-index = <0>;
 				interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&ringclk 2>;
+				clocks = <&ap_syscon 3>;
 				status = "disabled";
 			};
 
 			i2c0: i2c@511000 {
-				compatible = "marvell,mv64xxx-i2c";
+				compatible = "marvell,mv78230-i2c";
 				reg = <0x511000 0x20>;
 				#address-cells = <1>;
 				#size-cells = <0>;
 				interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
 				timeout-ms = <1000>;
-				clocks = <&ringclk 2>;
+				clocks = <&ap_syscon 3>;
 				status = "disabled";
 			};
 
-			serial@512000 {
+			uart0: serial@512000 {
 				compatible = "snps,dw-apb-uart";
 				reg = <0x512000 0x100>;
 				reg-shift = <2>;
 				interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
 				reg-io-width = <1>;
-				clocks = <&ringclk 2>;
+				clocks = <&ap_syscon 3>;
 				status = "disabled";
 			};
 
-			serial@512100 {
+			uart1: serial@512100 {
 				compatible = "snps,dw-apb-uart";
 				reg = <0x512100 0x100>;
 				reg-shift = <2>;
 				interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
 				reg-io-width = <1>;
-				clocks = <&ringclk 2>;
+				clocks = <&ap_syscon 3>;
 				status = "disabled";
 
 			};
 
-			dfx-server@6f8000 {
-				compatible = "simple-mfd", "syscon";
-				reg = <0x6f8000 0x70000>;
-
-				coreclk: clk@204 {
-					compatible = "marvell,armada-ap806-core-clock";
-					#clock-cells = <1>;
-					clock-output-names = "ddr", "ring", "cpu";
-				};
-
-				ringclk: clk@250 {
-					compatible = "marvell,armada-ap806-ring-clock";
-					#clock-cells = <1>;
-					clock-output-names = "ring-0", "ring-2",
-							     "ring-3", "ring-4",
-							     "ring-5";
-					clocks = <&coreclk 1>;
-				};
+			ap_syscon: system-controller@6f4000 {
+				compatible = "marvell,ap806-system-controller",
+					     "syscon";
+				#clock-cells = <1>;
+				clock-output-names = "ap-cpu-cluster-0",
+						     "ap-cpu-cluster-1",
+						     "ap-fixed", "ap-mss";
+				reg = <0x6f4000 0x1000>;
 			};
 		};
 	};
-
 };
-
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/marvell/armada-ap806-dual.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/marvell/armada-ap806-dual.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/marvell/armada-ap806-dual.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/marvell/armada-ap806-dual.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -68,4 +68,3 @@
 		};
 	};
 };
-
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/marvell/armada-ap806-quad.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/marvell/armada-ap806-quad.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/marvell/armada-ap806-quad.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/marvell/armada-ap806-quad.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -79,6 +79,4 @@
 			enable-method = "psci";
 		};
 	};
-
 };
-
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2016 Marvell Technology Group Ltd.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPLv2 or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Device Tree file for Marvell Armada CP110 Master.
+ */
+
+/ {
+	cp110-master {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		compatible = "simple-bus";
+		interrupt-parent = <&gic>;
+		ranges;
+
+		config-space {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "simple-bus";
+			interrupt-parent = <&gic>;
+			ranges = <0x0 0x0 0xf2000000 0x2000000>;
+
+			cpm_syscon0: system-controller@440000 {
+				compatible = "marvell,cp110-system-controller0",
+					     "syscon";
+				reg = <0x440000 0x1000>;
+				#clock-cells = <2>;
+				core-clock-output-names =
+					"cpm-apll", "cpm-ppv2-core", "cpm-eip",
+					"cpm-core", "cpm-nand-core";
+				gate-clock-output-names =
+					"cpm-audio", "cpm-communit", "cpm-nand",
+					"cpm-ppv2", "cpm-sdio", "cpm-mg-domain",
+					"cpm-mg-core", "cpm-xor1", "cpm-xor0",
+					"cpm-gop-dp", "none", "cpm-pcie_x10",
+					"cpm-pcie_x11", "cpm-pcie_x4", "cpm-pcie-xor",
+					"cpm-sata", "cpm-sata-usb", "cpm-main",
+					"cpm-sd-mmc", "none", "none",
+					"cpm-slow-io", "cpm-usb3h0", "cpm-usb3h1",
+					"cpm-usb3dev", "cpm-eip150", "cpm-eip197";
+			};
+
+			cpm_sata0: sata@540000 {
+				compatible = "marvell,armada-8k-ahci";
+				reg = <0x540000 0x30000>;
+				interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&cpm_syscon0 1 15>;
+				status = "disabled";
+			};
+
+			cpm_usb3_0: usb3@500000 {
+				compatible = "marvell,armada-8k-xhci",
+					     "generic-xhci";
+				reg = <0x500000 0x4000>;
+				dma-coherent;
+				interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&cpm_syscon0 1 22>;
+				status = "disabled";
+			};
+
+			cpm_usb3_1: usb3@510000 {
+				compatible = "marvell,armada-8k-xhci",
+					     "generic-xhci";
+				reg = <0x510000 0x4000>;
+				dma-coherent;
+				interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&cpm_syscon0 1 23>;
+				status = "disabled";
+			};
+
+			cpm_spi0: spi@700600 {
+				compatible = "marvell,armada-380-spi";
+				reg = <0x700600 0x50>;
+				#address-cells = <0x1>;
+				#size-cells = <0x0>;
+				cell-index = <1>;
+				clocks = <&cpm_syscon0 0 3>;
+				status = "disabled";
+			};
+
+			cpm_spi1: spi@700680 {
+				compatible = "marvell,armada-380-spi";
+				reg = <0x700680 0x50>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				cell-index = <2>;
+				clocks = <&cpm_syscon0 1 21>;
+				status = "disabled";
+			};
+
+			cpm_i2c0: i2c@701000 {
+				compatible = "marvell,mv78230-i2c";
+				reg = <0x701000 0x20>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&cpm_syscon0 1 21>;
+				status = "disabled";
+			};
+
+			cpm_i2c1: i2c@701100 {
+				compatible = "marvell,mv78230-i2c";
+				reg = <0x701100 0x20>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&cpm_syscon0 1 21>;
+				status = "disabled";
+			};
+		};
+
+		cpm_pcie0: pcie@f2600000 {
+			compatible = "marvell,armada8k-pcie", "snps,dw-pcie";
+			reg = <0 0xf2600000 0 0x10000>,
+			      <0 0xf6f00000 0 0x80000>;
+			reg-names = "ctrl", "config";
+			#address-cells = <3>;
+			#size-cells = <2>;
+			#interrupt-cells = <1>;
+			device_type = "pci";
+			dma-coherent;
+
+			bus-range = <0 0xff>;
+			ranges =
+				/* downstream I/O */
+				<0x81000000 0 0xf9000000 0  0xf9000000 0 0x10000
+				/* non-prefetchable memory */
+				0x82000000 0 0xf6000000 0  0xf6000000 0 0xf00000>;
+			interrupt-map-mask = <0 0 0 0>;
+			interrupt-map = <0 0 0 0 &gic 0 GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+			num-lanes = <1>;
+			clocks = <&cpm_syscon0 1 13>;
+			status = "disabled";
+		};
+
+		cpm_pcie1: pcie@f2620000 {
+			compatible = "marvell,armada8k-pcie", "snps,dw-pcie";
+			reg = <0 0xf2620000 0 0x10000>,
+			      <0 0xf7f00000 0 0x80000>;
+			reg-names = "ctrl", "config";
+			#address-cells = <3>;
+			#size-cells = <2>;
+			#interrupt-cells = <1>;
+			device_type = "pci";
+			dma-coherent;
+
+			bus-range = <0 0xff>;
+			ranges =
+				/* downstream I/O */
+				<0x81000000 0 0xf9010000 0  0xf9010000 0 0x10000
+				/* non-prefetchable memory */
+				0x82000000 0 0xf7000000 0  0xf7000000 0 0xf00000>;
+			interrupt-map-mask = <0 0 0 0>;
+			interrupt-map = <0 0 0 0 &gic 0 GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+
+			num-lanes = <1>;
+			clocks = <&cpm_syscon0 1 11>;
+			status = "disabled";
+		};
+
+		cpm_pcie2: pcie@f2640000 {
+			compatible = "marvell,armada8k-pcie", "snps,dw-pcie";
+			reg = <0 0xf2640000 0 0x10000>,
+			      <0 0xf8f00000 0 0x80000>;
+			reg-names = "ctrl", "config";
+			#address-cells = <3>;
+			#size-cells = <2>;
+			#interrupt-cells = <1>;
+			device_type = "pci";
+			dma-coherent;
+
+			bus-range = <0 0xff>;
+			ranges =
+				/* downstream I/O */
+				<0x81000000 0 0xf9020000 0  0xf9020000 0 0x10000
+				/* non-prefetchable memory */
+				0x82000000 0 0xf8000000 0  0xf8000000 0 0xf00000>;
+			interrupt-map-mask = <0 0 0 0>;
+			interrupt-map = <0 0 0 0 &gic 0 GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+
+			num-lanes = <1>;
+			clocks = <&cpm_syscon0 1 12>;
+			status = "disabled";
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/mediatek/mt8173.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/mediatek/mt8173.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/mediatek/mt8173.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/mediatek/mt8173.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -125,6 +125,49 @@
 		clock-output-names = "cpum_ck";
 	};
 
+	thermal-zones {
+		cpu_thermal: cpu_thermal {
+			polling-delay-passive = <1000>; /* milliseconds */
+			polling-delay = <1000>; /* milliseconds */
+
+			thermal-sensors = <&thermal>;
+			sustainable-power = <1500>; /* milliwatts */
+
+			trips {
+				threshold: trip-point@0 {
+					temperature = <68000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+
+				target: trip-point@1 {
+					temperature = <85000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+
+				cpu_crit: cpu_crit@0 {
+					temperature = <115000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+
+			cooling-maps {
+				map@0 {
+					trip = <&target>;
+					cooling-device = <&cpu0 0 0>;
+					contribution = <1024>;
+				};
+				map@1 {
+					trip = <&target>;
+					cooling-device = <&cpu2 0 0>;
+					contribution = <2048>;
+				};
+			};
+		};
+	};
+
 	timer {
 		compatible = "arm,armv8-timer";
 		interrupt-parent = <&gic>;
@@ -313,6 +356,11 @@
 				(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
 		};
 
+		auxadc: auxadc@11001000 {
+			compatible = "mediatek,mt8173-auxadc";
+			reg = <0 0x11001000 0 0x1000>;
+		};
+
 		uart0: serial@11002000 {
 			compatible = "mediatek,mt8173-uart",
 				     "mediatek,mt6577-uart";
@@ -414,6 +462,18 @@
 			status = "disabled";
 		};
 
+		thermal: thermal@1100b000 {
+			#thermal-sensor-cells = <0>;
+			compatible = "mediatek,mt8173-thermal";
+			reg = <0 0x1100b000 0 0x1000>;
+			interrupts = <0 70 IRQ_TYPE_LEVEL_LOW>;
+			clocks = <&pericfg CLK_PERI_THERM>, <&pericfg CLK_PERI_AUXADC>;
+			clock-names = "therm", "auxadc";
+			resets = <&pericfg MT8173_PERI_THERM_SW_RST>;
+			mediatek,auxadc = <&auxadc>;
+			mediatek,apmixedsys = <&apmixedsys>;
+		};
+
 		nor_flash: spi@1100d000 {
 			compatible = "mediatek,mt8173-nor";
 			reg = <0 0x1100d000 0 0xe0>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/nvidia/Makefile linux-libre-4.7-gnu/arch/arm64/boot/dts/nvidia/Makefile
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/nvidia/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/nvidia/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -2,6 +2,7 @@ dtb-$(CONFIG_ARCH_TEGRA_132_SOC) += tegr
 dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2371-0000.dtb
 dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2371-2180.dtb
 dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2571.dtb
+dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-smaug.dtb
 
 always		:= $(dtb-y)
 clean-files	:= *.dtb
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/nvidia/tegra132.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/nvidia/tegra132.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/nvidia/tegra132.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/nvidia/tegra132.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -11,7 +11,7 @@
 	#address-cells = <2>;
 	#size-cells = <2>;
 
-	pcie-controller@0,01003000 {
+	pcie-controller@01003000 {
 		compatible = "nvidia,tegra124-pcie";
 		device_type = "pci";
 		reg = <0x0 0x01003000 0x0 0x00000800   /* PADS registers */
@@ -77,7 +77,7 @@
 		};
 	};
 
-	host1x@0,50000000 {
+	host1x@50000000 {
 		compatible = "nvidia,tegra124-host1x", "simple-bus";
 		reg = <0x0 0x50000000 0x0 0x00034000>;
 		interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>, /* syncpt */
@@ -92,7 +92,7 @@
 
 		ranges = <0 0x54000000 0 0x54000000 0 0x01000000>;
 
-		dc@0,54200000 {
+		dc@54200000 {
 			compatible = "nvidia,tegra124-dc";
 			reg = <0x0 0x54200000 0x0 0x00040000>;
 			interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
@@ -107,7 +107,7 @@
 			nvidia,head = <0>;
 		};
 
-		dc@0,54240000 {
+		dc@54240000 {
 			compatible = "nvidia,tegra124-dc";
 			reg = <0x0 0x54240000 0x0 0x00040000>;
 			interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
@@ -122,7 +122,7 @@
 			nvidia,head = <1>;
 		};
 
-		hdmi@0,54280000 {
+		hdmi@54280000 {
 			compatible = "nvidia,tegra124-hdmi";
 			reg = <0x0 0x54280000 0x0 0x00040000>;
 			interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
@@ -134,7 +134,7 @@
 			status = "disabled";
 		};
 
-		sor@0,54540000 {
+		sor@54540000 {
 			compatible = "nvidia,tegra124-sor";
 			reg = <0x0 0x54540000 0x0 0x00040000>;
 			interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
@@ -148,7 +148,7 @@
 			status = "disabled";
 		};
 
-		dpaux: dpaux@0,545c0000 {
+		dpaux: dpaux@545c0000 {
 			compatible = "nvidia,tegra124-dpaux";
 			reg = <0x0 0x545c0000 0x0 0x00040000>;
 			interrupts = <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>;
@@ -161,7 +161,7 @@
 		};
 	};
 
-	gic: interrupt-controller@0,50041000 {
+	gic: interrupt-controller@50041000 {
 		compatible = "arm,cortex-a15-gic";
 		#interrupt-cells = <3>;
 		interrupt-controller;
@@ -174,7 +174,7 @@
 		interrupt-parent = <&gic>;
 	};
 
-	gpu@0,57000000 {
+	gpu@57000000 {
 		compatible = "nvidia,gk20a";
 		reg = <0x0 0x57000000 0x0 0x01000000>,
 		      <0x0 0x58000000 0x0 0x01000000>;
@@ -201,7 +201,7 @@
 		interrupt-parent = <&gic>;
 	};
 
-	timer@0,60005000 {
+	timer@60005000 {
 		compatible = "nvidia,tegra124-timer", "nvidia,tegra20-timer";
 		reg = <0x0 0x60005000 0x0 0x400>;
 		interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
@@ -214,7 +214,7 @@
 		clock-names = "timer";
 	};
 
-	tegra_car: clock@0,60006000 {
+	tegra_car: clock@60006000 {
 		compatible = "nvidia,tegra132-car";
 		reg = <0x0 0x60006000 0x0 0x1000>;
 		#clock-cells = <1>;
@@ -222,12 +222,12 @@
 		nvidia,external-memory-controller = <&emc>;
 	};
 
-	flow-controller@0,60007000 {
+	flow-controller@60007000 {
 		compatible = "nvidia,tegra124-flowctrl";
 		reg = <0x0 0x60007000 0x0 0x1000>;
 	};
 
-	actmon@0,6000c800 {
+	actmon@6000c800 {
 		compatible = "nvidia,tegra124-actmon";
 		reg = <0x0 0x6000c800 0x0 0x400>;
 		interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
@@ -238,7 +238,7 @@
 		reset-names = "actmon";
 	};
 
-	gpio: gpio@0,6000d000 {
+	gpio: gpio@6000d000 {
 		compatible = "nvidia,tegra124-gpio", "nvidia,tegra30-gpio";
 		reg = <0x0 0x6000d000 0x0 0x1000>;
 		interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>,
@@ -255,7 +255,7 @@
 		interrupt-controller;
 	};
 
-	apbdma: dma@0,60020000 {
+	apbdma: dma@60020000 {
 		compatible = "nvidia,tegra124-apbdma", "nvidia,tegra148-apbdma";
 		reg = <0x0 0x60020000 0x0 0x1400>;
 		interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>,
@@ -297,13 +297,13 @@
 		#dma-cells = <1>;
 	};
 
-	apbmisc@0,70000800 {
+	apbmisc@70000800 {
 		compatible = "nvidia,tegra124-apbmisc", "nvidia,tegra20-apbmisc";
 		reg = <0x0 0x70000800 0x0 0x64>,   /* Chip revision */
 		      <0x0 0x7000e864 0x0 0x04>;   /* Strapping options */
 	};
 
-	pinmux: pinmux@0,70000868 {
+	pinmux: pinmux@70000868 {
 		compatible = "nvidia,tegra124-pinmux";
 		reg = <0x0 0x70000868 0x0 0x164>, /* Pad control registers */
 		      <0x0 0x70003000 0x0 0x434>, /* Mux registers */
@@ -315,10 +315,10 @@
 	 * driver and APB DMA based serial driver for higher baudrate
 	 * and performance. To enable the 8250 based driver, the compatible
 	 * is "nvidia,tegra124-uart", "nvidia,tegra20-uart" and to enable
-	 * the APB DMA based serial driver, the comptible is
+	 * the APB DMA based serial driver, the compatible is
 	 * "nvidia,tegra124-hsuart", "nvidia,tegra30-hsuart".
 	 */
-	uarta: serial@0,70006000 {
+	uarta: serial@70006000 {
 		compatible = "nvidia,tegra124-uart", "nvidia,tegra20-uart";
 		reg = <0x0 0x70006000 0x0 0x40>;
 		reg-shift = <2>;
@@ -332,7 +332,7 @@
 		status = "disabled";
 	};
 
-	uartb: serial@0,70006040 {
+	uartb: serial@70006040 {
 		compatible = "nvidia,tegra124-uart", "nvidia,tegra20-uart";
 		reg = <0x0 0x70006040 0x0 0x40>;
 		reg-shift = <2>;
@@ -346,7 +346,7 @@
 		status = "disabled";
 	};
 
-	uartc: serial@0,70006200 {
+	uartc: serial@70006200 {
 		compatible = "nvidia,tegra124-uart", "nvidia,tegra20-uart";
 		reg = <0x0 0x70006200 0x0 0x40>;
 		reg-shift = <2>;
@@ -360,7 +360,7 @@
 		status = "disabled";
 	};
 
-	uartd: serial@0,70006300 {
+	uartd: serial@70006300 {
 		compatible = "nvidia,tegra124-uart", "nvidia,tegra20-uart";
 		reg = <0x0 0x70006300 0x0 0x40>;
 		reg-shift = <2>;
@@ -374,7 +374,7 @@
 		status = "disabled";
 	};
 
-	pwm: pwm@0,7000a000 {
+	pwm: pwm@7000a000 {
 		compatible = "nvidia,tegra124-pwm", "nvidia,tegra20-pwm";
 		reg = <0x0 0x7000a000 0x0 0x100>;
 		#pwm-cells = <2>;
@@ -385,7 +385,7 @@
 		status = "disabled";
 	};
 
-	i2c@0,7000c000 {
+	i2c@7000c000 {
 		compatible = "nvidia,tegra124-i2c", "nvidia,tegra114-i2c";
 		reg = <0x0 0x7000c000 0x0 0x100>;
 		interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
@@ -400,7 +400,7 @@
 		status = "disabled";
 	};
 
-	i2c@0,7000c400 {
+	i2c@7000c400 {
 		compatible = "nvidia,tegra124-i2c", "nvidia,tegra114-i2c";
 		reg = <0x0 0x7000c400 0x0 0x100>;
 		interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
@@ -415,7 +415,7 @@
 		status = "disabled";
 	};
 
-	i2c@0,7000c500 {
+	i2c@7000c500 {
 		compatible = "nvidia,tegra124-i2c", "nvidia,tegra114-i2c";
 		reg = <0x0 0x7000c500 0x0 0x100>;
 		interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
@@ -430,7 +430,7 @@
 		status = "disabled";
 	};
 
-	i2c@0,7000c700 {
+	i2c@7000c700 {
 		compatible = "nvidia,tegra124-i2c", "nvidia,tegra114-i2c";
 		reg = <0x0 0x7000c700 0x0 0x100>;
 		interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
@@ -445,7 +445,7 @@
 		status = "disabled";
 	};
 
-	i2c@0,7000d000 {
+	i2c@7000d000 {
 		compatible = "nvidia,tegra124-i2c", "nvidia,tegra114-i2c";
 		reg = <0x0 0x7000d000 0x0 0x100>;
 		interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
@@ -460,7 +460,7 @@
 		status = "disabled";
 	};
 
-	i2c@0,7000d100 {
+	i2c@7000d100 {
 		compatible = "nvidia,tegra124-i2c", "nvidia,tegra114-i2c";
 		reg = <0x0 0x7000d100 0x0 0x100>;
 		interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
@@ -475,7 +475,7 @@
 		status = "disabled";
 	};
 
-	spi@0,7000d400 {
+	spi@7000d400 {
 		compatible = "nvidia,tegra124-spi", "nvidia,tegra114-spi";
 		reg = <0x0 0x7000d400 0x0 0x200>;
 		interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
@@ -490,7 +490,7 @@
 		status = "disabled";
 	};
 
-	spi@0,7000d600 {
+	spi@7000d600 {
 		compatible = "nvidia,tegra124-spi", "nvidia,tegra114-spi";
 		reg = <0x0 0x7000d600 0x0 0x200>;
 		interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
@@ -505,7 +505,7 @@
 		status = "disabled";
 	};
 
-	spi@0,7000d800 {
+	spi@7000d800 {
 		compatible = "nvidia,tegra124-spi", "nvidia,tegra114-spi";
 		reg = <0x0 0x7000d800 0x0 0x200>;
 		interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
@@ -520,7 +520,7 @@
 		status = "disabled";
 	};
 
-	spi@0,7000da00 {
+	spi@7000da00 {
 		compatible = "nvidia,tegra124-spi", "nvidia,tegra114-spi";
 		reg = <0x0 0x7000da00 0x0 0x200>;
 		interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
@@ -535,7 +535,7 @@
 		status = "disabled";
 	};
 
-	spi@0,7000dc00 {
+	spi@7000dc00 {
 		compatible = "nvidia,tegra124-spi", "nvidia,tegra114-spi";
 		reg = <0x0 0x7000dc00 0x0 0x200>;
 		interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
@@ -550,7 +550,7 @@
 		status = "disabled";
 	};
 
-	spi@0,7000de00 {
+	spi@7000de00 {
 		compatible = "nvidia,tegra124-spi", "nvidia,tegra114-spi";
 		reg = <0x0 0x7000de00 0x0 0x200>;
 		interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
@@ -565,7 +565,7 @@
 		status = "disabled";
 	};
 
-	rtc@0,7000e000 {
+	rtc@7000e000 {
 		compatible = "nvidia,tegra124-rtc", "nvidia,tegra20-rtc";
 		reg = <0x0 0x7000e000 0x0 0x100>;
 		interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
@@ -573,14 +573,14 @@
 		clock-names = "rtc";
 	};
 
-	pmc@0,7000e400 {
+	pmc@7000e400 {
 		compatible = "nvidia,tegra124-pmc";
 		reg = <0x0 0x7000e400 0x0 0x400>;
 		clocks = <&tegra_car TEGRA124_CLK_PCLK>, <&clk32k_in>;
 		clock-names = "pclk", "clk32k_in";
 	};
 
-	fuse@0,7000f800 {
+	fuse@7000f800 {
 		compatible = "nvidia,tegra124-efuse";
 		reg = <0x0 0x7000f800 0x0 0x400>;
 		clocks = <&tegra_car TEGRA124_CLK_FUSE>;
@@ -589,7 +589,7 @@
 		reset-names = "fuse";
 	};
 
-	mc: memory-controller@0,70019000 {
+	mc: memory-controller@70019000 {
 		compatible = "nvidia,tegra132-mc";
 		reg = <0x0 0x70019000 0x0 0x1000>;
 		clocks = <&tegra_car TEGRA124_CLK_MC>;
@@ -600,14 +600,14 @@
 		#iommu-cells = <1>;
 	};
 
-	emc: emc@0,7001b000 {
+	emc: emc@7001b000 {
 		compatible = "nvidia,tegra132-emc", "nvidia,tegra124-emc";
 		reg = <0x0 0x7001b000 0x0 0x1000>;
 
 		nvidia,memory-controller = <&mc>;
 	};
 
-	sata@0,70020000 {
+	sata@70020000 {
 		compatible = "nvidia,tegra124-ahci";
 		reg = <0x0 0x70027000 0x0 0x2000>, /* AHCI */
 		      <0x0 0x70020000 0x0 0x7000>; /* SATA */
@@ -626,7 +626,7 @@
 		status = "disabled";
 	};
 
-	hda@0,70030000 {
+	hda@70030000 {
 		compatible = "nvidia,tegra132-hda", "nvidia,tegra124-hda",
 			     "nvidia,tegra30-hda";
 		reg = <0x0 0x70030000 0x0 0x10000>;
@@ -642,7 +642,7 @@
 		status = "disabled";
 	};
 
-	padctl: padctl@0,7009f000 {
+	padctl: padctl@7009f000 {
 		compatible = "nvidia,tegra132-xusb-padctl",
 			     "nvidia,tegra124-xusb-padctl";
 		reg = <0x0 0x7009f000 0x0 0x1000>;
@@ -682,7 +682,7 @@
 		};
 	};
 
-	sdhci@0,700b0000 {
+	sdhci@700b0000 {
 		compatible = "nvidia,tegra124-sdhci";
 		reg = <0x0 0x700b0000 0x0 0x200>;
 		interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
@@ -693,7 +693,7 @@
 		status = "disabled";
 	};
 
-	sdhci@0,700b0200 {
+	sdhci@700b0200 {
 		compatible = "nvidia,tegra124-sdhci";
 		reg = <0x0 0x700b0200 0x0 0x200>;
 		interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
@@ -704,7 +704,7 @@
 		status = "disabled";
 	};
 
-	sdhci@0,700b0400 {
+	sdhci@700b0400 {
 		compatible = "nvidia,tegra124-sdhci";
 		reg = <0x0 0x700b0400 0x0 0x200>;
 		interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
@@ -715,7 +715,7 @@
 		status = "disabled";
 	};
 
-	sdhci@0,700b0600 {
+	sdhci@700b0600 {
 		compatible = "nvidia,tegra124-sdhci";
 		reg = <0x0 0x700b0600 0x0 0x200>;
 		interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
@@ -726,7 +726,7 @@
 		status = "disabled";
 	};
 
-	soctherm: thermal-sensor@0,700e2000 {
+	soctherm: thermal-sensor@700e2000 {
 		compatible = "nvidia,tegra124-soctherm";
 		reg = <0x0 0x700e2000 0x0 0x1000>;
 		interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
@@ -738,7 +738,7 @@
 		#thermal-sensor-cells = <1>;
 	};
 
-	ahub@0,70300000 {
+	ahub@70300000 {
 		compatible = "nvidia,tegra124-ahub";
 		reg = <0x0 0x70300000 0x0 0x200>,
 		      <0x0 0x70300800 0x0 0x800>,
@@ -790,7 +790,7 @@
 		#address-cells = <2>;
 		#size-cells = <2>;
 
-		tegra_i2s0: i2s@0,70301000 {
+		tegra_i2s0: i2s@70301000 {
 			compatible = "nvidia,tegra124-i2s";
 			reg = <0x0 0x70301000 0x0 0x100>;
 			nvidia,ahub-cif-ids = <4 4>;
@@ -801,7 +801,7 @@
 			status = "disabled";
 		};
 
-		tegra_i2s1: i2s@0,70301100 {
+		tegra_i2s1: i2s@70301100 {
 			compatible = "nvidia,tegra124-i2s";
 			reg = <0x0 0x70301100 0x0 0x100>;
 			nvidia,ahub-cif-ids = <5 5>;
@@ -812,7 +812,7 @@
 			status = "disabled";
 		};
 
-		tegra_i2s2: i2s@0,70301200 {
+		tegra_i2s2: i2s@70301200 {
 			compatible = "nvidia,tegra124-i2s";
 			reg = <0x0 0x70301200 0x0 0x100>;
 			nvidia,ahub-cif-ids = <6 6>;
@@ -823,7 +823,7 @@
 			status = "disabled";
 		};
 
-		tegra_i2s3: i2s@0,70301300 {
+		tegra_i2s3: i2s@70301300 {
 			compatible = "nvidia,tegra124-i2s";
 			reg = <0x0 0x70301300 0x0 0x100>;
 			nvidia,ahub-cif-ids = <7 7>;
@@ -834,7 +834,7 @@
 			status = "disabled";
 		};
 
-		tegra_i2s4: i2s@0,70301400 {
+		tegra_i2s4: i2s@70301400 {
 			compatible = "nvidia,tegra124-i2s";
 			reg = <0x0 0x70301400 0x0 0x100>;
 			nvidia,ahub-cif-ids = <8 8>;
@@ -846,7 +846,7 @@
 		};
 	};
 
-	usb@0,7d000000 {
+	usb@7d000000 {
 		compatible = "nvidia,tegra124-ehci", "nvidia,tegra30-ehci", "usb-ehci";
 		reg = <0x0 0x7d000000 0x0 0x4000>;
 		interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
@@ -859,7 +859,7 @@
 		status = "disabled";
 	};
 
-	phy1: usb-phy@0,7d000000 {
+	phy1: usb-phy@7d000000 {
 		compatible = "nvidia,tegra124-usb-phy", "nvidia,tegra30-usb-phy";
 		reg = <0x0 0x7d000000 0x0 0x4000>,
 		      <0x0 0x7d000000 0x0 0x4000>;
@@ -884,7 +884,7 @@
 		status = "disabled";
 	};
 
-	usb@0,7d004000 {
+	usb@7d004000 {
 		compatible = "nvidia,tegra124-ehci", "nvidia,tegra30-ehci", "usb-ehci";
 		reg = <0x0 0x7d004000 0x0 0x4000>;
 		interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
@@ -897,7 +897,7 @@
 		status = "disabled";
 	};
 
-	phy2: usb-phy@0,7d004000 {
+	phy2: usb-phy@7d004000 {
 		compatible = "nvidia,tegra124-usb-phy", "nvidia,tegra30-usb-phy";
 		reg = <0x0 0x7d004000 0x0 0x4000>,
 		      <0x0 0x7d000000 0x0 0x4000>;
@@ -921,7 +921,7 @@
 		status = "disabled";
 	};
 
-	usb@0,7d008000 {
+	usb@7d008000 {
 		compatible = "nvidia,tegra124-ehci", "nvidia,tegra30-ehci", "usb-ehci";
 		reg = <0x0 0x7d008000 0x0 0x4000>;
 		interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
@@ -934,7 +934,7 @@
 		status = "disabled";
 	};
 
-	phy3: usb-phy@0,7d008000 {
+	phy3: usb-phy@7d008000 {
 		compatible = "nvidia,tegra124-usb-phy", "nvidia,tegra30-usb-phy";
 		reg = <0x0 0x7d008000 0x0 0x4000>,
 		      <0x0 0x7d000000 0x0 0x4000>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/nvidia/tegra132-norrin.dts linux-libre-4.7-gnu/arch/arm64/boot/dts/nvidia/tegra132-norrin.dts
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/nvidia/tegra132-norrin.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/nvidia/tegra132-norrin.dts	2016-07-24 15:23:50.000000000 -0400
@@ -8,19 +8,22 @@
 	compatible = "nvidia,norrin", "nvidia,tegra132", "nvidia,tegra124";
 
 	aliases {
-		rtc0 = "/i2c@0,7000d000/as3722@40";
-		rtc1 = "/rtc@0,7000e000";
+		rtc0 = "/i2c@7000d000/as3722@40";
+		rtc1 = "/rtc@7000e000";
+		serial0 = &uarta;
 	};
 
-	chosen { };
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
 
 	memory {
 		device_type = "memory";
 		reg = <0x0 0x80000000 0x0 0x80000000>;
 	};
 
-	host1x@0,50000000 {
-		hdmi@0,54280000 {
+	host1x@50000000 {
+		hdmi@54280000 {
 			status = "disabled";
 
 			vdd-supply = <&vdd_3v3_hdmi>;
@@ -32,26 +35,26 @@
 				<&gpio TEGRA_GPIO(N, 7) GPIO_ACTIVE_HIGH>;
 		};
 
-		sor@0,54540000 {
+		sor@54540000 {
 			status = "okay";
 
 			nvidia,dpaux = <&dpaux>;
 			nvidia,panel = <&panel>;
 		};
 
-		dpaux: dpaux@0,545c0000 {
+		dpaux: dpaux@545c0000 {
 			vdd-supply = <&vdd_3v3_panel>;
 			status = "okay";
 		};
 	};
 
-	gpu@0,57000000 {
+	gpu@57000000 {
 		status = "okay";
 
 		vdd-supply = <&vdd_gpu>;
 	};
 
-	pinmux@0,70000868 {
+	pinmux@70000868 {
 		pinctrl-names = "default";
 		pinctrl-0 = <&pinmux_default>;
 
@@ -523,21 +526,21 @@
 		};
 	};
 
-	serial@0,70006000 {
+	serial@70006000 {
 		status = "okay";
 	};
 
-	pwm: pwm@0,7000a000 {
+	pwm: pwm@7000a000 {
 		status = "okay";
 	};
 
 	/* HDMI DDC */
-	hdmi_ddc: i2c@0,7000c700 {
+	hdmi_ddc: i2c@7000c700 {
 		status = "okay";
 		clock-frequency = <100000>;
 	};
 
-	i2c@0,7000d000 {
+	i2c@7000d000 {
 		status = "okay";
 		clock-frequency = <400000>;
 
@@ -744,7 +747,7 @@
 		};
 	};
 
-	spi@0,7000d400 {
+	spi@7000d400 {
 		status = "okay";
 
 		ec: cros-ec@0 {
@@ -876,7 +879,7 @@
 		};
 	};
 
-	pmc@0,7000e400 {
+	pmc@7000e400 {
 		nvidia,invert-interrupt;
 		nvidia,suspend-mode = <0>;
 		#wake-cells = <3>;
@@ -890,12 +893,12 @@
 	};
 
 	/* WIFI/BT module */
-	sdhci@0,700b0000 {
+	sdhci@700b0000 {
 		status = "disabled";
 	};
 
 	/* external SD/MMC */
-	sdhci@0,700b0400 {
+	sdhci@700b0400 {
 		cd-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_LOW>;
 		power-gpios = <&gpio TEGRA_GPIO(R, 0) GPIO_ACTIVE_HIGH>;
 		wp-gpios = <&gpio TEGRA_GPIO(Q, 4) GPIO_ACTIVE_HIGH>;
@@ -905,35 +908,35 @@
 	};
 
 	/* EMMC 4.51 */
-	sdhci@0,700b0600 {
+	sdhci@700b0600 {
 		status = "okay";
 		bus-width = <8>;
 		non-removable;
 	};
 
-	usb@0,7d000000 {
+	usb@7d000000 {
 		status = "okay";
 	};
 
-	usb-phy@0,7d000000 {
+	usb-phy@7d000000 {
 		status = "okay";
 		vbus-supply = <&vdd_usb1_vbus>;
 	};
 
-	usb@0,7d004000 {
+	usb@7d004000 {
 		status = "okay";
 	};
 
-	usb-phy@0,7d004000 {
+	usb-phy@7d004000 {
 		status = "okay";
 		vbus-supply = <&vdd_run_cam>;
 	};
 
-	usb@0,7d008000 {
+	usb@7d008000 {
 		status = "okay";
 	};
 
-	usb-phy@0,7d008000 {
+	usb-phy@7d008000 {
 		status = "okay";
 		vbus-supply = <&vdd_usb3_vbus>;
 	};
@@ -973,7 +976,7 @@
 			linux,input-type = <5>;
 			linux,code = <0>;
 			debounce-interval = <1>;
-			gpio-key,wakeup;
+			wakeup-source;
 		};
 
 		power {
@@ -981,7 +984,7 @@
 			gpios = <&gpio TEGRA_GPIO(Q, 0) GPIO_ACTIVE_LOW>;
 			linux,code = <KEY_POWER>;
 			debounce-interval = <10>;
-			gpio-key,wakeup;
+			wakeup-source;
 		};
 	};
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/nvidia/tegra210.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/nvidia/tegra210.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/nvidia/tegra210.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/nvidia/tegra210.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -10,7 +10,7 @@
 	#address-cells = <2>;
 	#size-cells = <2>;
 
-	host1x@0,50000000 {
+	host1x@50000000 {
 		compatible = "nvidia,tegra210-host1x", "simple-bus";
 		reg = <0x0 0x50000000 0x0 0x00034000>;
 		interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>, /* syncpt */
@@ -25,7 +25,7 @@
 
 		ranges = <0x0 0x54000000 0x0 0x54000000 0x0 0x01000000>;
 
-		dpaux1: dpaux@0,54040000 {
+		dpaux1: dpaux@54040000 {
 			compatible = "nvidia,tegra210-dpaux";
 			reg = <0x0 0x54040000 0x0 0x00040000>;
 			interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
@@ -37,19 +37,19 @@
 			status = "disabled";
 		};
 
-		vi@0,54080000 {
+		vi@54080000 {
 			compatible = "nvidia,tegra210-vi";
 			reg = <0x0 0x54080000 0x0 0x00040000>;
 			interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
 			status = "disabled";
 		};
 
-		tsec@0,54100000 {
+		tsec@54100000 {
 			compatible = "nvidia,tegra210-tsec";
 			reg = <0x0 0x54100000 0x0 0x00040000>;
 		};
 
-		dc@0,54200000 {
+		dc@54200000 {
 			compatible = "nvidia,tegra210-dc";
 			reg = <0x0 0x54200000 0x0 0x00040000>;
 			interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
@@ -64,7 +64,7 @@
 			nvidia,head = <0>;
 		};
 
-		dc@0,54240000 {
+		dc@54240000 {
 			compatible = "nvidia,tegra210-dc";
 			reg = <0x0 0x54240000 0x0 0x00040000>;
 			interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
@@ -79,7 +79,7 @@
 			nvidia,head = <1>;
 		};
 
-		dsi@0,54300000 {
+		dsi@54300000 {
 			compatible = "nvidia,tegra210-dsi";
 			reg = <0x0 0x54300000 0x0 0x00040000>;
 			clocks = <&tegra_car TEGRA210_CLK_DSIA>,
@@ -96,19 +96,19 @@
 			#size-cells = <0>;
 		};
 
-		vic@0,54340000 {
+		vic@54340000 {
 			compatible = "nvidia,tegra210-vic";
 			reg = <0x0 0x54340000 0x0 0x00040000>;
 			status = "disabled";
 		};
 
-		nvjpg@0,54380000 {
+		nvjpg@54380000 {
 			compatible = "nvidia,tegra210-nvjpg";
 			reg = <0x0 0x54380000 0x0 0x00040000>;
 			status = "disabled";
 		};
 
-		dsi@0,54400000 {
+		dsi@54400000 {
 			compatible = "nvidia,tegra210-dsi";
 			reg = <0x0 0x54400000 0x0 0x00040000>;
 			clocks = <&tegra_car TEGRA210_CLK_DSIB>,
@@ -125,25 +125,25 @@
 			#size-cells = <0>;
 		};
 
-		nvdec@0,54480000 {
+		nvdec@54480000 {
 			compatible = "nvidia,tegra210-nvdec";
 			reg = <0x0 0x54480000 0x0 0x00040000>;
 			status = "disabled";
 		};
 
-		nvenc@0,544c0000 {
+		nvenc@544c0000 {
 			compatible = "nvidia,tegra210-nvenc";
 			reg = <0x0 0x544c0000 0x0 0x00040000>;
 			status = "disabled";
 		};
 
-		tsec@0,54500000 {
+		tsec@54500000 {
 			compatible = "nvidia,tegra210-tsec";
 			reg = <0x0 0x54500000 0x0 0x00040000>;
 			status = "disabled";
 		};
 
-		sor@0,54540000 {
+		sor@54540000 {
 			compatible = "nvidia,tegra210-sor";
 			reg = <0x0 0x54540000 0x0 0x00040000>;
 			interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
@@ -157,7 +157,7 @@
 			status = "disabled";
 		};
 
-		sor@0,54580000 {
+		sor@54580000 {
 			compatible = "nvidia,tegra210-sor1";
 			reg = <0x0 0x54580000 0x0 0x00040000>;
 			interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
@@ -171,7 +171,7 @@
 			status = "disabled";
 		};
 
-		dpaux: dpaux@0,545c0000 {
+		dpaux: dpaux@545c0000 {
 			compatible = "nvidia,tegra124-dpaux";
 			reg = <0x0 0x545c0000 0x0 0x00040000>;
 			interrupts = <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>;
@@ -183,21 +183,21 @@
 			status = "disabled";
 		};
 
-		isp@0,54600000 {
+		isp@54600000 {
 			compatible = "nvidia,tegra210-isp";
 			reg = <0x0 0x54600000 0x0 0x00040000>;
 			interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
 			status = "disabled";
 		};
 
-		isp@0,54680000 {
+		isp@54680000 {
 			compatible = "nvidia,tegra210-isp";
 			reg = <0x0 0x54680000 0x0 0x00040000>;
 			interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
 			status = "disabled";
 		};
 
-		i2c@0,546c0000 {
+		i2c@546c0000 {
 			compatible = "nvidia,tegra210-i2c-vi";
 			reg = <0x0 0x546c0000 0x0 0x00040000>;
 			interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
@@ -205,7 +205,7 @@
 		};
 	};
 
-	gic: interrupt-controller@0,50041000 {
+	gic: interrupt-controller@50041000 {
 		compatible = "arm,gic-400";
 		#interrupt-cells = <3>;
 		interrupt-controller;
@@ -218,7 +218,7 @@
 		interrupt-parent = <&gic>;
 	};
 
-	gpu@0,57000000 {
+	gpu@57000000 {
 		compatible = "nvidia,gm20b";
 		reg = <0x0 0x57000000 0x0 0x01000000>,
 		      <0x0 0x58000000 0x0 0x01000000>;
@@ -226,14 +226,18 @@
 			     <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "stall", "nonstall";
 		clocks = <&tegra_car TEGRA210_CLK_GPU>,
-			 <&tegra_car TEGRA210_CLK_PLL_P_OUT5>;
-		clock-names = "gpu", "pwr";
+			 <&tegra_car TEGRA210_CLK_PLL_P_OUT5>,
+			 <&tegra_car TEGRA210_CLK_PLL_G_REF>;
+		clock-names = "gpu", "pwr", "ref";
 		resets = <&tegra_car 184>;
 		reset-names = "gpu";
+
+		iommus = <&mc TEGRA_SWGROUP_GPU>;
+
 		status = "disabled";
 	};
 
-	lic: interrupt-controller@0,60004000 {
+	lic: interrupt-controller@60004000 {
 		compatible = "nvidia,tegra210-ictlr";
 		reg = <0x0 0x60004000 0x0 0x40>, /* primary controller */
 		      <0x0 0x60004100 0x0 0x40>, /* secondary controller */
@@ -246,7 +250,7 @@
 		interrupt-parent = <&gic>;
 	};
 
-	timer@0,60005000 {
+	timer@60005000 {
 		compatible = "nvidia,tegra210-timer", "nvidia,tegra20-timer";
 		reg = <0x0 0x60005000 0x0 0x400>;
 		interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
@@ -259,19 +263,19 @@
 		clock-names = "timer";
 	};
 
-	tegra_car: clock@0,60006000 {
+	tegra_car: clock@60006000 {
 		compatible = "nvidia,tegra210-car";
 		reg = <0x0 0x60006000 0x0 0x1000>;
 		#clock-cells = <1>;
 		#reset-cells = <1>;
 	};
 
-	flow-controller@0,60007000 {
+	flow-controller@60007000 {
 		compatible = "nvidia,tegra210-flowctrl";
 		reg = <0x0 0x60007000 0x0 0x1000>;
 	};
 
-	gpio: gpio@0,6000d000 {
+	gpio: gpio@6000d000 {
 		compatible = "nvidia,tegra210-gpio", "nvidia,tegra124-gpio", "nvidia,tegra30-gpio";
 		reg = <0x0 0x6000d000 0x0 0x1000>;
 		interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>,
@@ -288,7 +292,7 @@
 		interrupt-controller;
 	};
 
-	apbdma: dma@0,60020000 {
+	apbdma: dma@60020000 {
 		compatible = "nvidia,tegra210-apbdma", "nvidia,tegra148-apbdma";
 		reg = <0x0 0x60020000 0x0 0x1400>;
 		interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>,
@@ -330,13 +334,13 @@
 		#dma-cells = <1>;
 	};
 
-	apbmisc@0,70000800 {
+	apbmisc@70000800 {
 		compatible = "nvidia,tegra210-apbmisc", "nvidia,tegra20-apbmisc";
 		reg = <0x0 0x70000800 0x0 0x64>,   /* Chip revision */
 		      <0x0 0x7000e864 0x0 0x04>;   /* Strapping options */
 	};
 
-	pinmux: pinmux@0,700008d4 {
+	pinmux: pinmux@700008d4 {
 		compatible = "nvidia,tegra210-pinmux";
 		reg = <0x0 0x700008d4 0x0 0x29c>, /* Pad control registers */
 		      <0x0 0x70003000 0x0 0x294>; /* Mux registers */
@@ -347,10 +351,10 @@
 	 * driver and APB DMA based serial driver for higher baudrate
 	 * and performance. To enable the 8250 based driver, the compatible
 	 * is "nvidia,tegra124-uart", "nvidia,tegra20-uart" and to enable
-	 * the APB DMA based serial driver, the comptible is
+	 * the APB DMA based serial driver, the compatible is
 	 * "nvidia,tegra124-hsuart", "nvidia,tegra30-hsuart".
 	 */
-	uarta: serial@0,70006000 {
+	uarta: serial@70006000 {
 		compatible = "nvidia,tegra210-uart", "nvidia,tegra20-uart";
 		reg = <0x0 0x70006000 0x0 0x40>;
 		reg-shift = <2>;
@@ -364,7 +368,7 @@
 		status = "disabled";
 	};
 
-	uartb: serial@0,70006040 {
+	uartb: serial@70006040 {
 		compatible = "nvidia,tegra210-uart", "nvidia,tegra20-uart";
 		reg = <0x0 0x70006040 0x0 0x40>;
 		reg-shift = <2>;
@@ -378,7 +382,7 @@
 		status = "disabled";
 	};
 
-	uartc: serial@0,70006200 {
+	uartc: serial@70006200 {
 		compatible = "nvidia,tegra210-uart", "nvidia,tegra20-uart";
 		reg = <0x0 0x70006200 0x0 0x40>;
 		reg-shift = <2>;
@@ -392,7 +396,7 @@
 		status = "disabled";
 	};
 
-	uartd: serial@0,70006300 {
+	uartd: serial@70006300 {
 		compatible = "nvidia,tegra210-uart", "nvidia,tegra20-uart";
 		reg = <0x0 0x70006300 0x0 0x40>;
 		reg-shift = <2>;
@@ -406,7 +410,7 @@
 		status = "disabled";
 	};
 
-	pwm: pwm@0,7000a000 {
+	pwm: pwm@7000a000 {
 		compatible = "nvidia,tegra210-pwm", "nvidia,tegra20-pwm";
 		reg = <0x0 0x7000a000 0x0 0x100>;
 		#pwm-cells = <2>;
@@ -417,7 +421,7 @@
 		status = "disabled";
 	};
 
-	i2c@0,7000c000 {
+	i2c@7000c000 {
 		compatible = "nvidia,tegra210-i2c", "nvidia,tegra114-i2c";
 		reg = <0x0 0x7000c000 0x0 0x100>;
 		interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
@@ -432,7 +436,7 @@
 		status = "disabled";
 	};
 
-	i2c@0,7000c400 {
+	i2c@7000c400 {
 		compatible = "nvidia,tegra210-i2c", "nvidia,tegra114-i2c";
 		reg = <0x0 0x7000c400 0x0 0x100>;
 		interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
@@ -447,7 +451,7 @@
 		status = "disabled";
 	};
 
-	i2c@0,7000c500 {
+	i2c@7000c500 {
 		compatible = "nvidia,tegra210-i2c", "nvidia,tegra114-i2c";
 		reg = <0x0 0x7000c500 0x0 0x100>;
 		interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
@@ -462,7 +466,7 @@
 		status = "disabled";
 	};
 
-	i2c@0,7000c700 {
+	i2c@7000c700 {
 		compatible = "nvidia,tegra210-i2c", "nvidia,tegra114-i2c";
 		reg = <0x0 0x7000c700 0x0 0x100>;
 		interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
@@ -477,7 +481,7 @@
 		status = "disabled";
 	};
 
-	i2c@0,7000d000 {
+	i2c@7000d000 {
 		compatible = "nvidia,tegra210-i2c", "nvidia,tegra114-i2c";
 		reg = <0x0 0x7000d000 0x0 0x100>;
 		interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
@@ -492,7 +496,7 @@
 		status = "disabled";
 	};
 
-	i2c@0,7000d100 {
+	i2c@7000d100 {
 		compatible = "nvidia,tegra210-i2c", "nvidia,tegra114-i2c";
 		reg = <0x0 0x7000d100 0x0 0x100>;
 		interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
@@ -507,7 +511,7 @@
 		status = "disabled";
 	};
 
-	spi@0,7000d400 {
+	spi@7000d400 {
 		compatible = "nvidia,tegra210-spi", "nvidia,tegra114-spi";
 		reg = <0x0 0x7000d400 0x0 0x200>;
 		interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
@@ -522,7 +526,7 @@
 		status = "disabled";
 	};
 
-	spi@0,7000d600 {
+	spi@7000d600 {
 		compatible = "nvidia,tegra210-spi", "nvidia,tegra114-spi";
 		reg = <0x0 0x7000d600 0x0 0x200>;
 		interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
@@ -537,7 +541,7 @@
 		status = "disabled";
 	};
 
-	spi@0,7000d800 {
+	spi@7000d800 {
 		compatible = "nvidia,tegra210-spi", "nvidia,tegra114-spi";
 		reg = <0x0 0x7000d800 0x0 0x200>;
 		interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
@@ -552,7 +556,7 @@
 		status = "disabled";
 	};
 
-	spi@0,7000da00 {
+	spi@7000da00 {
 		compatible = "nvidia,tegra210-spi", "nvidia,tegra114-spi";
 		reg = <0x0 0x7000da00 0x0 0x200>;
 		interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
@@ -567,7 +571,7 @@
 		status = "disabled";
 	};
 
-	rtc@0,7000e000 {
+	rtc@7000e000 {
 		compatible = "nvidia,tegra210-rtc", "nvidia,tegra20-rtc";
 		reg = <0x0 0x7000e000 0x0 0x100>;
 		interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
@@ -575,16 +579,14 @@
 		clock-names = "rtc";
 	};
 
-	pmc: pmc@0,7000e400 {
+	pmc: pmc@7000e400 {
 		compatible = "nvidia,tegra210-pmc";
 		reg = <0x0 0x7000e400 0x0 0x400>;
 		clocks = <&tegra_car TEGRA210_CLK_PCLK>, <&clk32k_in>;
 		clock-names = "pclk", "clk32k_in";
-
-		#power-domain-cells = <1>;
 	};
 
-	fuse@0,7000f800 {
+	fuse@7000f800 {
 		compatible = "nvidia,tegra210-efuse";
 		reg = <0x0 0x7000f800 0x0 0x400>;
 		clocks = <&tegra_car TEGRA210_CLK_FUSE>;
@@ -593,7 +595,7 @@
 		reset-names = "fuse";
 	};
 
-	mc: memory-controller@0,70019000 {
+	mc: memory-controller@70019000 {
 		compatible = "nvidia,tegra210-mc";
 		reg = <0x0 0x70019000 0x0 0x1000>;
 		clocks = <&tegra_car TEGRA210_CLK_MC>;
@@ -604,7 +606,7 @@
 		#iommu-cells = <1>;
 	};
 
-	hda@0,70030000 {
+	hda@70030000 {
 		compatible = "nvidia,tegra210-hda", "nvidia,tegra30-hda";
 		reg = <0x0 0x70030000 0x0 0x10000>;
 		interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
@@ -619,7 +621,7 @@
 		status = "disabled";
 	};
 
-	sdhci@0,700b0000 {
+	sdhci@700b0000 {
 		compatible = "nvidia,tegra210-sdhci", "nvidia,tegra124-sdhci";
 		reg = <0x0 0x700b0000 0x0 0x200>;
 		interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
@@ -630,7 +632,7 @@
 		status = "disabled";
 	};
 
-	sdhci@0,700b0200 {
+	sdhci@700b0200 {
 		compatible = "nvidia,tegra210-sdhci", "nvidia,tegra124-sdhci";
 		reg = <0x0 0x700b0200 0x0 0x200>;
 		interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
@@ -641,7 +643,7 @@
 		status = "disabled";
 	};
 
-	sdhci@0,700b0400 {
+	sdhci@700b0400 {
 		compatible = "nvidia,tegra210-sdhci", "nvidia,tegra124-sdhci";
 		reg = <0x0 0x700b0400 0x0 0x200>;
 		interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
@@ -652,7 +654,7 @@
 		status = "disabled";
 	};
 
-	sdhci@0,700b0600 {
+	sdhci@700b0600 {
 		compatible = "nvidia,tegra210-sdhci", "nvidia,tegra124-sdhci";
 		reg = <0x0 0x700b0600 0x0 0x200>;
 		interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
@@ -663,7 +665,7 @@
 		status = "disabled";
 	};
 
-	mipi: mipi@0,700e3000 {
+	mipi: mipi@700e3000 {
 		compatible = "nvidia,tegra210-mipi";
 		reg = <0x0 0x700e3000 0x0 0x100>;
 		clocks = <&tegra_car TEGRA210_CLK_MIPI_CAL>;
@@ -671,7 +673,7 @@
 		#nvidia,mipi-calibrate-cells = <1>;
 	};
 
-	spi@0,70410000 {
+	spi@70410000 {
 		compatible = "nvidia,tegra210-qspi";
 		reg = <0x0 0x70410000 0x0 0x1000>;
 		interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
@@ -686,7 +688,7 @@
 		status = "disabled";
 	};
 
-	usb@0,7d000000 {
+	usb@7d000000 {
 		compatible = "nvidia,tegra210-ehci", "nvidia,tegra30-ehci", "usb-ehci";
 		reg = <0x0 0x7d000000 0x0 0x4000>;
 		interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
@@ -699,7 +701,7 @@
 		status = "disabled";
 	};
 
-	phy1: usb-phy@0,7d000000 {
+	phy1: usb-phy@7d000000 {
 		compatible = "nvidia,tegra210-usb-phy", "nvidia,tegra30-usb-phy";
 		reg = <0x0 0x7d000000 0x0 0x4000>,
 		      <0x0 0x7d000000 0x0 0x4000>;
@@ -724,7 +726,7 @@
 		status = "disabled";
 	};
 
-	usb@0,7d004000 {
+	usb@7d004000 {
 		compatible = "nvidia,tegra210-ehci", "nvidia,tegra30-ehci", "usb-ehci";
 		reg = <0x0 0x7d004000 0x0 0x4000>;
 		interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
@@ -737,7 +739,7 @@
 		status = "disabled";
 	};
 
-	phy2: usb-phy@0,7d004000 {
+	phy2: usb-phy@7d004000 {
 		compatible = "nvidia,tegra210-usb-phy", "nvidia,tegra30-usb-phy";
 		reg = <0x0 0x7d004000 0x0 0x4000>,
 		      <0x0 0x7d000000 0x0 0x4000>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -5,7 +5,7 @@
 	compatible = "nvidia,p2180", "nvidia,tegra210";
 
 	aliases {
-		rtc1 = "/rtc@0,7000e000";
+		rtc1 = "/rtc@7000e000";
 		serial0 = &uarta;
 	};
 
@@ -15,16 +15,16 @@
 	};
 
 	/* debug port */
-	serial@0,70006000 {
+	serial@70006000 {
 		status = "okay";
 	};
 
-	pmc@0,7000e400 {
+	pmc@7000e400 {
 		nvidia,invert-interrupt;
 	};
 
 	/* eMMC */
-	sdhci@0,700b0600 {
+	sdhci@700b0600 {
 		status = "okay";
 		bus-width = <8>;
 		non-removable;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/nvidia/tegra210-p2530.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/nvidia/tegra210-p2530.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/nvidia/tegra210-p2530.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/nvidia/tegra210-p2530.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -5,31 +5,35 @@
 	compatible = "nvidia,p2530", "nvidia,tegra210";
 
 	aliases {
-		rtc1 = "/rtc@0,7000e000";
+		rtc1 = "/rtc@7000e000";
 		serial0 = &uarta;
 	};
 
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
 	memory {
 		device_type = "memory";
 		reg = <0x0 0x80000000 0x0 0xc0000000>;
 	};
 
 	/* debug port */
-	serial@0,70006000 {
+	serial@70006000 {
 		status = "okay";
 	};
 
-	i2c@0,7000d000 {
+	i2c@7000d000 {
 		status = "okay";
 		clock-frequency = <400000>;
 	};
 
-	pmc@0,7000e400 {
+	pmc@7000e400 {
 		nvidia,invert-interrupt;
 	};
 
 	/* eMMC */
-	sdhci@0,700b0600 {
+	sdhci@700b0600 {
 		status = "okay";
 		bus-width = <8>;
 		non-removable;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/nvidia/tegra210-p2571.dts linux-libre-4.7-gnu/arch/arm64/boot/dts/nvidia/tegra210-p2571.dts
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/nvidia/tegra210-p2571.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/nvidia/tegra210-p2571.dts	2016-07-24 15:23:50.000000000 -0400
@@ -7,7 +7,7 @@
 	model = "NVIDIA Tegra210 P2571 reference design";
 	compatible = "nvidia,p2571", "nvidia,tegra210";
 
-	pinmux: pinmux@0,700008d4 {
+	pinmux: pinmux@700008d4 {
 		pinctrl-names = "boot";
 		pinctrl-0 = <&state_boot>;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/nvidia/tegra210-p2595.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/nvidia/tegra210-p2595.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/nvidia/tegra210-p2595.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/nvidia/tegra210-p2595.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -2,7 +2,7 @@
 	model = "NVIDIA Tegra210 P2595 I/O board";
 	compatible = "nvidia,p2595", "nvidia,tegra210";
 
-	pinmux: pinmux@0,700008d4 {
+	pinmux: pinmux@700008d4 {
 		pinctrl-names = "boot";
 		pinctrl-0 = <&state_boot>;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -1,8 +1,10 @@
+#include <dt-bindings/input/input.h>
+
 / {
 	model = "NVIDIA Tegra210 P2597 I/O board";
 	compatible = "nvidia,p2597", "nvidia,tegra210";
 
-	pinmux: pinmux@0,700008d4 {
+	pinmux: pinmux@700008d4 {
 		pinctrl-names = "boot";
 		pinctrl-0 = <&state_boot>;
 
@@ -1260,11 +1262,35 @@
 	};
 
 	/* MMC/SD */
-	sdhci@0,700b0000 {
+	sdhci@700b0000 {
 		status = "okay";
 		bus-width = <4>;
 		no-1-8-v;
 
 		cd-gpios = <&gpio TEGRA_GPIO(Z, 1) GPIO_ACTIVE_LOW>;
 	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		label = "gpio-keys";
+
+		power {
+			label = "Power";
+			gpios = <&gpio TEGRA_GPIO(X, 5) GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_POWER>;
+			wakeup-source;
+		};
+
+		volume_down {
+			label = "Volume Down";
+			gpios = <&gpio TEGRA_GPIO(Y, 0) GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_VOLUMEDOWN>;
+		};
+
+		volume_up {
+			label = "Volume Up";
+			gpios = <&gpio TEGRA_GPIO(X, 6) GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_VOLUMEUP>;
+		};
+	};
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts linux-libre-4.7-gnu/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,1424 @@
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/pinctrl/pinctrl-tegra.h>
+
+#include "tegra210.dtsi"
+
+/ {
+	model = "Google Pixel C";
+	compatible = "google,smaug-rev8", "google,smaug-rev7",
+		     "google,smaug-rev6", "google,smaug-rev5",
+		     "google,smaug-rev4", "google,smaug-rev3",
+		     "google,smaug-rev1", "google,smaug", "nvidia,tegra210";
+
+	aliases {
+		serial0 = &uarta;
+	};
+
+	chosen {
+		bootargs = "earlycon";
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x0 0x80000000 0x0 0xc0000000>;
+	};
+
+	pinmux: pinmux@700008d4 {
+		pinctrl-names = "boot";
+		pinctrl-0 = <&state_boot>;
+
+		state_boot: pinmux {
+			pex_l0_rst_n_pa0 {
+				nvidia,pins = "pex_l0_rst_n_pa0";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+				nvidia,io-hv = <TEGRA_PIN_DISABLE>;
+			};
+			pex_l0_clkreq_n_pa1 {
+				nvidia,pins = "pex_l0_clkreq_n_pa1";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+				nvidia,io-hv = <TEGRA_PIN_DISABLE>;
+			};
+			pex_wake_n_pa2 {
+				nvidia,pins = "pex_wake_n_pa2";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+				nvidia,io-hv = <TEGRA_PIN_DISABLE>;
+			};
+			pex_l1_rst_n_pa3 {
+				nvidia,pins = "pex_l1_rst_n_pa3";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+				nvidia,io-hv = <TEGRA_PIN_DISABLE>;
+			};
+			pex_l1_clkreq_n_pa4 {
+				nvidia,pins = "pex_l1_clkreq_n_pa4";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+				nvidia,io-hv = <TEGRA_PIN_DISABLE>;
+			};
+			sata_led_active_pa5 {
+				nvidia,pins = "sata_led_active_pa5";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			pa6 {
+				nvidia,pins = "pa6";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			dap1_fs_pb0 {
+				nvidia,pins = "dap1_fs_pb0";
+				nvidia,function = "i2s1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			dap1_din_pb1 {
+				nvidia,pins = "dap1_din_pb1";
+				nvidia,function = "i2s1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			dap1_dout_pb2 {
+				nvidia,pins = "dap1_dout_pb2";
+				nvidia,function = "i2s1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			dap1_sclk_pb3 {
+				nvidia,pins = "dap1_sclk_pb3";
+				nvidia,function = "i2s1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			spi2_mosi_pb4 {
+				nvidia,pins = "spi2_mosi_pb4";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			spi2_miso_pb5 {
+				nvidia,pins = "spi2_miso_pb5";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			spi2_sck_pb6 {
+				nvidia,pins = "spi2_sck_pb6";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			spi2_cs0_pb7 {
+				nvidia,pins = "spi2_cs0_pb7";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			spi1_mosi_pc0 {
+				nvidia,pins = "spi1_mosi_pc0";
+				nvidia,function = "spi1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			spi1_miso_pc1 {
+				nvidia,pins = "spi1_miso_pc1";
+				nvidia,function = "spi1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			spi1_sck_pc2 {
+				nvidia,pins = "spi1_sck_pc2";
+				nvidia,function = "spi1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			spi1_cs0_pc3 {
+				nvidia,pins = "spi1_cs0_pc3";
+				nvidia,function = "spi1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			spi1_cs1_pc4 {
+				nvidia,pins = "spi1_cs1_pc4";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			spi4_sck_pc5 {
+				nvidia,pins = "spi4_sck_pc5";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			spi4_cs0_pc6 {
+				nvidia,pins = "spi4_cs0_pc6";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			spi4_mosi_pc7 {
+				nvidia,pins = "spi4_mosi_pc7";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			spi4_miso_pd0 {
+				nvidia,pins = "spi4_miso_pd0";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			uart3_tx_pd1 {
+				nvidia,pins = "uart3_tx_pd1";
+				nvidia,function = "uartc";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			uart3_rx_pd2 {
+				nvidia,pins = "uart3_rx_pd2";
+				nvidia,function = "uartc";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			uart3_rts_pd3 {
+				nvidia,pins = "uart3_rts_pd3";
+				nvidia,function = "uartc";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			uart3_cts_pd4 {
+				nvidia,pins = "uart3_cts_pd4";
+				nvidia,function = "uartc";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			dmic1_clk_pe0 {
+				nvidia,pins = "dmic1_clk_pe0";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			dmic1_dat_pe1 {
+				nvidia,pins = "dmic1_dat_pe1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			dmic2_clk_pe2 {
+				nvidia,pins = "dmic2_clk_pe2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			dmic2_dat_pe3 {
+				nvidia,pins = "dmic2_dat_pe3";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			dmic3_clk_pe4 {
+				nvidia,pins = "dmic3_clk_pe4";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			dmic3_dat_pe5 {
+				nvidia,pins = "dmic3_dat_pe5";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			pe6 {
+				nvidia,pins = "pe6";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			pe7 {
+				nvidia,pins = "pe7";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			gen3_i2c_scl_pf0 {
+				nvidia,pins = "gen3_i2c_scl_pf0";
+				nvidia,function = "i2c3";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+				nvidia,io-hv = <TEGRA_PIN_DISABLE>;
+			};
+			gen3_i2c_sda_pf1 {
+				nvidia,pins = "gen3_i2c_sda_pf1";
+				nvidia,function = "i2c3";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+				nvidia,io-hv = <TEGRA_PIN_DISABLE>;
+			};
+			uart2_tx_pg0 {
+				nvidia,pins = "uart2_tx_pg0";
+				nvidia,function = "uartb";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			uart2_rx_pg1 {
+				nvidia,pins = "uart2_rx_pg1";
+				nvidia,function = "uartb";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			uart2_rts_pg2 {
+				nvidia,pins = "uart2_rts_pg2";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			uart2_cts_pg3 {
+				nvidia,pins = "uart2_cts_pg3";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			wifi_en_ph0 {
+				nvidia,pins = "wifi_en_ph0";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			wifi_rst_ph1 {
+				nvidia,pins = "wifi_rst_ph1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			wifi_wake_ap_ph2 {
+				nvidia,pins = "wifi_wake_ap_ph2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			ap_wake_bt_ph3 {
+				nvidia,pins = "ap_wake_bt_ph3";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			bt_rst_ph4 {
+				nvidia,pins = "bt_rst_ph4";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			bt_wake_ap_ph5 {
+				nvidia,pins = "bt_wake_ap_ph5";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			ph6 {
+				nvidia,pins = "ph6";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			ap_wake_nfc_ph7 {
+				nvidia,pins = "ap_wake_nfc_ph7";
+				nvidia,function = "rsvd0";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			nfc_en_pi0 {
+				nvidia,pins = "nfc_en_pi0";
+				nvidia,function = "rsvd0";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			nfc_int_pi1 {
+				nvidia,pins = "nfc_int_pi1";
+				nvidia,function = "rsvd0";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			gps_en_pi2 {
+				nvidia,pins = "gps_en_pi2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			gps_rst_pi3 {
+				nvidia,pins = "gps_rst_pi3";
+				nvidia,function = "rsvd0";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			uart4_tx_pi4 {
+				nvidia,pins = "uart4_tx_pi4";
+				nvidia,function = "uartd";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			uart4_rx_pi5 {
+				nvidia,pins = "uart4_rx_pi5";
+				nvidia,function = "uartd";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			uart4_rts_pi6 {
+				nvidia,pins = "uart4_rts_pi6";
+				nvidia,function = "uartd";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			uart4_cts_pi7 {
+				nvidia,pins = "uart4_cts_pi7";
+				nvidia,function = "uartd";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			gen1_i2c_sda_pj0 {
+				nvidia,pins = "gen1_i2c_sda_pj0";
+				nvidia,function = "i2c1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+				nvidia,io-hv = <TEGRA_PIN_DISABLE>;
+			};
+			gen1_i2c_scl_pj1 {
+				nvidia,pins = "gen1_i2c_scl_pj1";
+				nvidia,function = "i2c1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+				nvidia,io-hv = <TEGRA_PIN_DISABLE>;
+			};
+			gen2_i2c_scl_pj2 {
+				nvidia,pins = "gen2_i2c_scl_pj2";
+				nvidia,function = "i2c2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+				nvidia,io-hv = <TEGRA_PIN_ENABLE>;
+			};
+			gen2_i2c_sda_pj3 {
+				nvidia,pins = "gen2_i2c_sda_pj3";
+				nvidia,function = "i2c2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+				nvidia,io-hv = <TEGRA_PIN_ENABLE>;
+			};
+			dap4_fs_pj4 {
+				nvidia,pins = "dap4_fs_pj4";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			dap4_din_pj5 {
+				nvidia,pins = "dap4_din_pj5";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			dap4_dout_pj6 {
+				nvidia,pins = "dap4_dout_pj6";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			dap4_sclk_pj7 {
+				nvidia,pins = "dap4_sclk_pj7";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			pk0 {
+				nvidia,pins = "pk0";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			pk1 {
+				nvidia,pins = "pk1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			pk2 {
+				nvidia,pins = "pk2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			pk3 {
+				nvidia,pins = "pk3";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			pk4 {
+				nvidia,pins = "pk4";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			pk5 {
+				nvidia,pins = "pk5";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			pk6 {
+				nvidia,pins = "pk6";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			pk7 {
+				nvidia,pins = "pk7";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			pl0 {
+				nvidia,pins = "pl0";
+				nvidia,function = "rsvd0";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			pl1 {
+				nvidia,pins = "pl1";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			sdmmc1_clk_pm0 {
+				nvidia,pins = "sdmmc1_clk_pm0";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			sdmmc1_cmd_pm1 {
+				nvidia,pins = "sdmmc1_cmd_pm1";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			sdmmc1_dat3_pm2 {
+				nvidia,pins = "sdmmc1_dat3_pm2";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			sdmmc1_dat2_pm3 {
+				nvidia,pins = "sdmmc1_dat2_pm3";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			sdmmc1_dat1_pm4 {
+				nvidia,pins = "sdmmc1_dat1_pm4";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			sdmmc1_dat0_pm5 {
+				nvidia,pins = "sdmmc1_dat0_pm5";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			sdmmc3_clk_pp0 {
+				nvidia,pins = "sdmmc3_clk_pp0";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			sdmmc3_cmd_pp1 {
+				nvidia,pins = "sdmmc3_cmd_pp1";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			sdmmc3_dat3_pp2 {
+				nvidia,pins = "sdmmc3_dat3_pp2";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			sdmmc3_dat2_pp3 {
+				nvidia,pins = "sdmmc3_dat2_pp3";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			sdmmc3_dat1_pp4 {
+				nvidia,pins = "sdmmc3_dat1_pp4";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			sdmmc3_dat0_pp5 {
+				nvidia,pins = "sdmmc3_dat0_pp5";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			cam1_mclk_ps0 {
+				nvidia,pins = "cam1_mclk_ps0";
+				nvidia,function = "extperiph3";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			cam2_mclk_ps1 {
+				nvidia,pins = "cam2_mclk_ps1";
+				nvidia,function = "extperiph3";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			cam_i2c_scl_ps2 {
+				nvidia,pins = "cam_i2c_scl_ps2";
+				nvidia,function = "i2cvi";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+				nvidia,io-hv = <TEGRA_PIN_DISABLE>;
+			};
+			cam_i2c_sda_ps3 {
+				nvidia,pins = "cam_i2c_sda_ps3";
+				nvidia,function = "i2cvi";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+				nvidia,io-hv = <TEGRA_PIN_DISABLE>;
+			};
+			cam_rst_ps4 {
+				nvidia,pins = "cam_rst_ps4";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			cam_af_en_ps5 {
+				nvidia,pins = "cam_af_en_ps5";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			cam_flash_en_ps6 {
+				nvidia,pins = "cam_flash_en_ps6";
+				nvidia,function = "rsvd2";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			cam1_pwdn_ps7 {
+				nvidia,pins = "cam1_pwdn_ps7";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			cam2_pwdn_pt0 {
+				nvidia,pins = "cam2_pwdn_pt0";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			cam1_strobe_pt1 {
+				nvidia,pins = "cam1_strobe_pt1";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			uart1_tx_pu0 {
+				nvidia,pins = "uart1_tx_pu0";
+				nvidia,function = "uarta";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			uart1_rx_pu1 {
+				nvidia,pins = "uart1_rx_pu1";
+				nvidia,function = "uarta";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			uart1_rts_pu2 {
+				nvidia,pins = "uart1_rts_pu2";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			uart1_cts_pu3 {
+				nvidia,pins = "uart1_cts_pu3";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			lcd_bl_pwm_pv0 {
+				nvidia,pins = "lcd_bl_pwm_pv0";
+				nvidia,function = "rsvd3";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			lcd_bl_en_pv1 {
+				nvidia,pins = "lcd_bl_en_pv1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			lcd_rst_pv2 {
+				nvidia,pins = "lcd_rst_pv2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			lcd_gpio1_pv3 {
+				nvidia,pins = "lcd_gpio1_pv3";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			lcd_gpio2_pv4 {
+				nvidia,pins = "lcd_gpio2_pv4";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			ap_ready_pv5 {
+				nvidia,pins = "ap_ready_pv5";
+				nvidia,function = "rsvd0";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			touch_rst_pv6 {
+				nvidia,pins = "touch_rst_pv6";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			touch_clk_pv7 {
+				nvidia,pins = "touch_clk_pv7";
+				nvidia,function = "touch";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			modem_wake_ap_px0 {
+				nvidia,pins = "modem_wake_ap_px0";
+				nvidia,function = "rsvd0";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			touch_int_px1 {
+				nvidia,pins = "touch_int_px1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			motion_int_px2 {
+				nvidia,pins = "motion_int_px2";
+				nvidia,function = "rsvd0";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			als_prox_int_px3 {
+				nvidia,pins = "als_prox_int_px3";
+				nvidia,function = "rsvd0";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			temp_alert_px4 {
+				nvidia,pins = "temp_alert_px4";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			button_power_on_px5 {
+				nvidia,pins = "button_power_on_px5";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			button_vol_up_px6 {
+				nvidia,pins = "button_vol_up_px6";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			button_vol_down_px7 {
+				nvidia,pins = "button_vol_down_px7";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			button_slide_sw_py0 {
+				nvidia,pins = "button_slide_sw_py0";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			button_home_py1 {
+				nvidia,pins = "button_home_py1";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			lcd_te_py2 {
+				nvidia,pins = "lcd_te_py2";
+				nvidia,function = "displaya";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			pwr_i2c_scl_py3 {
+				nvidia,pins = "pwr_i2c_scl_py3";
+				nvidia,function = "i2cpmu";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+				nvidia,io-hv = <TEGRA_PIN_DISABLE>;
+			};
+			pwr_i2c_sda_py4 {
+				nvidia,pins = "pwr_i2c_sda_py4";
+				nvidia,function = "i2cpmu";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+				nvidia,io-hv = <TEGRA_PIN_DISABLE>;
+			};
+			clk_32k_out_py5 {
+				nvidia,pins = "clk_32k_out_py5";
+				nvidia,function = "soc";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			pz0 {
+				nvidia,pins = "pz0";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			pz1 {
+				nvidia,pins = "pz1";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			pz2 {
+				nvidia,pins = "pz2";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			pz3 {
+				nvidia,pins = "pz3";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			pz4 {
+				nvidia,pins = "pz4";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			pz5 {
+				nvidia,pins = "pz5";
+				nvidia,function = "soc";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			dap2_fs_paa0 {
+				nvidia,pins = "dap2_fs_paa0";
+				nvidia,function = "i2s2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			dap2_sclk_paa1 {
+				nvidia,pins = "dap2_sclk_paa1";
+				nvidia,function = "i2s2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			dap2_din_paa2 {
+				nvidia,pins = "dap2_din_paa2";
+				nvidia,function = "i2s2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			dap2_dout_paa3 {
+				nvidia,pins = "dap2_dout_paa3";
+				nvidia,function = "i2s2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			aud_mclk_pbb0 {
+				nvidia,pins = "aud_mclk_pbb0";
+				nvidia,function = "aud";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			dvfs_pwm_pbb1 {
+				nvidia,pins = "dvfs_pwm_pbb1";
+				nvidia,function = "rsvd0";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			dvfs_clk_pbb2 {
+				nvidia,pins = "dvfs_clk_pbb2";
+				nvidia,function = "rsvd0";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			gpio_x1_aud_pbb3 {
+				nvidia,pins = "gpio_x1_aud_pbb3";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			gpio_x3_aud_pbb4 {
+				nvidia,pins = "gpio_x3_aud_pbb4";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			hdmi_cec_pcc0 {
+				nvidia,pins = "hdmi_cec_pcc0";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+				nvidia,io-hv = <TEGRA_PIN_DISABLE>;
+			};
+			hdmi_int_dp_hpd_pcc1 {
+				nvidia,pins = "hdmi_int_dp_hpd_pcc1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+				nvidia,io-hv = <TEGRA_PIN_DISABLE>;
+			};
+			spdif_out_pcc2 {
+				nvidia,pins = "spdif_out_pcc2";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			spdif_in_pcc3 {
+				nvidia,pins = "spdif_in_pcc3";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			usb_vbus_en0_pcc4 {
+				nvidia,pins = "usb_vbus_en0_pcc4";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+				nvidia,io-hv = <TEGRA_PIN_DISABLE>;
+			};
+			usb_vbus_en1_pcc5 {
+				nvidia,pins = "usb_vbus_en1_pcc5";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+				nvidia,io-hv = <TEGRA_PIN_DISABLE>;
+			};
+			dp_hpd0_pcc6 {
+				nvidia,pins = "dp_hpd0_pcc6";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			pcc7 {
+				nvidia,pins = "pcc7";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+				nvidia,io-hv = <TEGRA_PIN_DISABLE>;
+			};
+			spi2_cs1_pdd0 {
+				nvidia,pins = "spi2_cs1_pdd0";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			qspi_sck_pee0 {
+				nvidia,pins = "qspi_sck_pee0";
+				nvidia,function = "qspi";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			qspi_cs_n_pee1 {
+				nvidia,pins = "qspi_cs_n_pee1";
+				nvidia,function = "qspi";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			qspi_io0_pee2 {
+				nvidia,pins = "qspi_io0_pee2";
+				nvidia,function = "qspi";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			qspi_io1_pee3 {
+				nvidia,pins = "qspi_io1_pee3";
+				nvidia,function = "qspi";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			qspi_io2_pee4 {
+				nvidia,pins = "qspi_io2_pee4";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			qspi_io3_pee5 {
+				nvidia,pins = "qspi_io3_pee5";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			core_pwr_req {
+				nvidia,pins = "core_pwr_req";
+				nvidia,function = "core";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			cpu_pwr_req {
+				nvidia,pins = "cpu_pwr_req";
+				nvidia,function = "cpu";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			pwr_int_n {
+				nvidia,pins = "pwr_int_n";
+				nvidia,function = "pmi";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			clk_32k_in {
+				nvidia,pins = "clk_32k_in";
+				nvidia,function = "clk";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			jtag_rtck {
+				nvidia,pins = "jtag_rtck";
+				nvidia,function = "jtag";
+				nvidia,pull = <TEGRA_PIN_PULL_UP>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			clk_req {
+				nvidia,pins = "clk_req";
+				nvidia,function = "rsvd1";
+				nvidia,pull = <TEGRA_PIN_PULL_DOWN>;
+				nvidia,tristate = <TEGRA_PIN_ENABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+			shutdown {
+				nvidia,pins = "shutdown";
+				nvidia,function = "shutdown";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+				nvidia,open-drain = <TEGRA_PIN_DISABLE>;
+			};
+		};
+	};
+
+	serial@70006000 {
+		status = "okay";
+	};
+
+	i2c@7000c400 {
+		status = "okay";
+		clock-frequency = <1000000>;
+
+		ec@1e {
+			compatible = "google,cros-ec-i2c";
+			reg = <0x1e>;
+			interrupt-parent = <&gpio>;
+			interrupts = <TEGRA_GPIO(Z, 1) IRQ_TYPE_LEVEL_LOW>;
+			wakeup-source;
+
+			ec_i2c_0: i2c-tunnel {
+				compatible = "google,cros-ec-i2c-tunnel";
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				google,remote-bus = <0>;
+
+				battery: bq27742@55 {
+					compatible = "ti,bq27742";
+					reg = <0x55>;
+					battery-name = "battery";
+				};
+			};
+		};
+	};
+
+	pmc@7000e400 {
+		nvidia,invert-interrupt;
+		nvidia,suspend-mode = <0>;
+		nvidia,cpu-pwr-good-time = <0>;
+		nvidia,cpu-pwr-off-time = <0>;
+		nvidia,core-pwr-good-time = <12000 6000>;
+		nvidia,core-pwr-off-time = <39053>;
+		nvidia,core-power-req-active-high;
+		nvidia,sys-clock-req-active-high;
+		status = "okay";
+	};
+
+	sdhci@700b0600 {
+		bus-width = <8>;
+		non-removable;
+		status = "okay";
+	};
+
+	clocks {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		clk32k_in: clock@0 {
+			compatible = "fixed-clock";
+			reg = <0>;
+			#clock-cells = <0>;
+			clock-frequency = <32768>;
+		};
+	};
+
+	cpus {
+		cpu@0 {
+			enable-method = "psci";
+		};
+
+		cpu@1 {
+			enable-method = "psci";
+		};
+
+		cpu@2 {
+			enable-method = "psci";
+		};
+
+		cpu@3 {
+			enable-method = "psci";
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		gpio-keys,name = "gpio-keys";
+
+		power {
+			label = "Power";
+			gpios = <&gpio TEGRA_GPIO(X, 5) GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_POWER>;
+			debounce-interval = <30>;
+			wakeup-source;
+		};
+
+		lid {
+			label = "Lid";
+			gpios = <&gpio TEGRA_GPIO(B, 4) GPIO_ACTIVE_LOW>;
+			linux,input-type = <EV_SW>;
+			linux,code = <SW_LID>;
+			wakeup-source;
+		};
+
+		tablet_mode {
+			label = "Tablet Mode";
+			gpios = <&gpio TEGRA_GPIO(Z, 2) GPIO_ACTIVE_HIGH>;
+			linux,input-type = <EV_SW>;
+			linux,code = <SW_TABLET_MODE>;
+			wakeup-source;
+		};
+
+		volume_down {
+			label = "Volume Down";
+			gpios = <&gpio TEGRA_GPIO(X, 7) GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_VOLUMEDOWN>;
+		};
+
+		volume_up {
+			label = "Volume Up";
+			gpios = <&gpio TEGRA_GPIO(M, 4) GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_VOLUMEUP>;
+		};
+	};
+
+	psci {
+		compatible = "arm,psci-1.0";
+		method = "smc";
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/renesas/r8a7795.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/renesas/r8a7795.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/renesas/r8a7795.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/renesas/r8a7795.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -10,6 +10,7 @@
 
 #include <dt-bindings/clock/r8a7795-cpg-mssr.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/power/r8a7795-sysc.h>
 
 / {
 	compatible = "renesas,r8a7795";
@@ -39,6 +40,7 @@
 			compatible = "arm,cortex-a57", "arm,armv8";
 			reg = <0x0>;
 			device_type = "cpu";
+			power-domains = <&sysc R8A7795_PD_CA57_CPU0>;
 			next-level-cache = <&L2_CA57>;
 			enable-method = "psci";
 		};
@@ -47,6 +49,7 @@
 			compatible = "arm,cortex-a57","arm,armv8";
 			reg = <0x1>;
 			device_type = "cpu";
+			power-domains = <&sysc R8A7795_PD_CA57_CPU1>;
 			next-level-cache = <&L2_CA57>;
 			enable-method = "psci";
 		};
@@ -54,6 +57,7 @@
 			compatible = "arm,cortex-a57","arm,armv8";
 			reg = <0x2>;
 			device_type = "cpu";
+			power-domains = <&sysc R8A7795_PD_CA57_CPU2>;
 			next-level-cache = <&L2_CA57>;
 			enable-method = "psci";
 		};
@@ -61,6 +65,7 @@
 			compatible = "arm,cortex-a57","arm,armv8";
 			reg = <0x3>;
 			device_type = "cpu";
+			power-domains = <&sysc R8A7795_PD_CA57_CPU3>;
 			next-level-cache = <&L2_CA57>;
 			enable-method = "psci";
 		};
@@ -68,12 +73,14 @@
 
 	L2_CA57: cache-controller@0 {
 		compatible = "cache";
+		power-domains = <&sysc R8A7795_PD_CA57_SCU>;
 		cache-unified;
 		cache-level = <2>;
 	};
 
 	L2_CA53: cache-controller@1 {
 		compatible = "cache";
+		power-domains = <&sysc R8A7795_PD_CA53_SCU>;
 		cache-unified;
 		cache-level = <2>;
 	};
@@ -115,6 +122,13 @@
 		clock-frequency = <0>;
 	};
 
+	/* External CAN clock - to be overridden by boards that provide it */
+	can_clk: can {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <0>;
+	};
+
 	/* External SCIF clock - to be overridden by boards that provide it */
 	scif_clk: scif {
 		compatible = "fixed-clock";
@@ -122,6 +136,13 @@
 		clock-frequency = <0>;
 	};
 
+	/* External PCIe clock - can be overridden by the board */
+	pcie_bus_clk: pcie_bus {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <0>;
+	};
+
 	soc {
 		compatible = "simple-bus";
 		interrupt-parent = <&gic>;
@@ -154,7 +175,7 @@
 			#interrupt-cells = <2>;
 			interrupt-controller;
 			clocks = <&cpg CPG_MOD 912>;
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 		};
 
 		gpio1: gpio@e6051000 {
@@ -168,7 +189,7 @@
 			#interrupt-cells = <2>;
 			interrupt-controller;
 			clocks = <&cpg CPG_MOD 911>;
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 		};
 
 		gpio2: gpio@e6052000 {
@@ -182,7 +203,7 @@
 			#interrupt-cells = <2>;
 			interrupt-controller;
 			clocks = <&cpg CPG_MOD 910>;
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 		};
 
 		gpio3: gpio@e6053000 {
@@ -196,7 +217,7 @@
 			#interrupt-cells = <2>;
 			interrupt-controller;
 			clocks = <&cpg CPG_MOD 909>;
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 		};
 
 		gpio4: gpio@e6054000 {
@@ -210,7 +231,7 @@
 			#interrupt-cells = <2>;
 			interrupt-controller;
 			clocks = <&cpg CPG_MOD 908>;
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 		};
 
 		gpio5: gpio@e6055000 {
@@ -224,7 +245,7 @@
 			#interrupt-cells = <2>;
 			interrupt-controller;
 			clocks = <&cpg CPG_MOD 907>;
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 		};
 
 		gpio6: gpio@e6055400 {
@@ -238,7 +259,7 @@
 			#interrupt-cells = <2>;
 			interrupt-controller;
 			clocks = <&cpg CPG_MOD 906>;
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 		};
 
 		gpio7: gpio@e6055800 {
@@ -252,7 +273,7 @@
 			#interrupt-cells = <2>;
 			interrupt-controller;
 			clocks = <&cpg CPG_MOD 905>;
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 		};
 
 		pmu_a57 {
@@ -288,6 +309,12 @@
 			#power-domain-cells = <0>;
 		};
 
+		sysc: system-controller@e6180000 {
+			compatible = "renesas,r8a7795-sysc";
+			reg = <0 0xe6180000 0 0x0400>;
+			#power-domain-cells = <1>;
+		};
+
 		audma0: dma-controller@ec700000 {
 			compatible = "renesas,rcar-dmac";
 			reg = <0 0xec700000 0 0x10000>;
@@ -315,7 +342,7 @@
 					"ch12", "ch13", "ch14", "ch15";
 			clocks = <&cpg CPG_MOD 502>;
 			clock-names = "fck";
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			#dma-cells = <1>;
 			dma-channels = <16>;
 		};
@@ -347,7 +374,7 @@
 					"ch12", "ch13", "ch14", "ch15";
 			clocks = <&cpg CPG_MOD 501>;
 			clock-names = "fck";
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			#dma-cells = <1>;
 			dma-channels = <16>;
 		};
@@ -369,7 +396,7 @@
 				      GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH
 				      GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&cpg CPG_MOD 407>;
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 		};
 
 		dmac0: dma-controller@e6700000 {
@@ -400,7 +427,7 @@
 					"ch12", "ch13", "ch14", "ch15";
 			clocks = <&cpg CPG_MOD 219>;
 			clock-names = "fck";
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			#dma-cells = <1>;
 			dma-channels = <16>;
 		};
@@ -433,7 +460,7 @@
 					"ch12", "ch13", "ch14", "ch15";
 			clocks = <&cpg CPG_MOD 218>;
 			clock-names = "fck";
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			#dma-cells = <1>;
 			dma-channels = <16>;
 		};
@@ -466,7 +493,7 @@
 					"ch12", "ch13", "ch14", "ch15";
 			clocks = <&cpg CPG_MOD 217>;
 			clock-names = "fck";
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			#dma-cells = <1>;
 			dma-channels = <16>;
 		};
@@ -508,12 +535,42 @@
 					  "ch20", "ch21", "ch22", "ch23",
 					  "ch24";
 			clocks = <&cpg CPG_MOD 812>;
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			phy-mode = "rgmii-id";
 			#address-cells = <1>;
 			#size-cells = <0>;
 		};
 
+		can0: can@e6c30000 {
+			compatible = "renesas,can-r8a7795",
+				     "renesas,rcar-gen3-can";
+			reg = <0 0xe6c30000 0 0x1000>;
+			interrupts = <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 916>,
+			       <&cpg CPG_CORE R8A7795_CLK_CANFD>,
+			       <&can_clk>;
+			clock-names = "clkp1", "clkp2", "can_clk";
+			assigned-clocks = <&cpg CPG_CORE R8A7795_CLK_CANFD>;
+			assigned-clock-rates = <40000000>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		can1: can@e6c38000 {
+			compatible = "renesas,can-r8a7795",
+				     "renesas,rcar-gen3-can";
+			reg = <0 0xe6c38000 0 0x1000>;
+			interrupts = <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 915>,
+			       <&cpg CPG_CORE R8A7795_CLK_CANFD>,
+			       <&can_clk>;
+			clock-names = "clkp1", "clkp2", "can_clk";
+			assigned-clocks = <&cpg CPG_CORE R8A7795_CLK_CANFD>;
+			assigned-clock-rates = <40000000>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
 		hscif0: serial@e6540000 {
 			compatible = "renesas,hscif-r8a7795",
 				     "renesas,rcar-gen3-hscif",
@@ -526,7 +583,7 @@
 			clock-names = "fck", "brg_int", "scif_clk";
 			dmas = <&dmac1 0x31>, <&dmac1 0x30>;
 			dma-names = "tx", "rx";
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			status = "disabled";
 		};
 
@@ -542,7 +599,7 @@
 			clock-names = "fck", "brg_int", "scif_clk";
 			dmas = <&dmac1 0x33>, <&dmac1 0x32>;
 			dma-names = "tx", "rx";
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			status = "disabled";
 		};
 
@@ -558,7 +615,7 @@
 			clock-names = "fck", "brg_int", "scif_clk";
 			dmas = <&dmac1 0x35>, <&dmac1 0x34>;
 			dma-names = "tx", "rx";
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			status = "disabled";
 		};
 
@@ -574,7 +631,7 @@
 			clock-names = "fck", "brg_int", "scif_clk";
 			dmas = <&dmac0 0x37>, <&dmac0 0x36>;
 			dma-names = "tx", "rx";
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			status = "disabled";
 		};
 
@@ -590,7 +647,7 @@
 			clock-names = "fck", "brg_int", "scif_clk";
 			dmas = <&dmac0 0x39>, <&dmac0 0x38>;
 			dma-names = "tx", "rx";
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			status = "disabled";
 		};
 
@@ -605,7 +662,7 @@
 			clock-names = "fck", "brg_int", "scif_clk";
 			dmas = <&dmac1 0x51>, <&dmac1 0x50>;
 			dma-names = "tx", "rx";
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			status = "disabled";
 		};
 
@@ -620,7 +677,7 @@
 			clock-names = "fck", "brg_int", "scif_clk";
 			dmas = <&dmac1 0x53>, <&dmac1 0x52>;
 			dma-names = "tx", "rx";
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			status = "disabled";
 		};
 
@@ -635,7 +692,7 @@
 			clock-names = "fck", "brg_int", "scif_clk";
 			dmas = <&dmac1 0x13>, <&dmac1 0x12>;
 			dma-names = "tx", "rx";
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			status = "disabled";
 		};
 
@@ -650,7 +707,7 @@
 			clock-names = "fck", "brg_int", "scif_clk";
 			dmas = <&dmac0 0x57>, <&dmac0 0x56>;
 			dma-names = "tx", "rx";
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			status = "disabled";
 		};
 
@@ -665,7 +722,7 @@
 			clock-names = "fck", "brg_int", "scif_clk";
 			dmas = <&dmac0 0x59>, <&dmac0 0x58>;
 			dma-names = "tx", "rx";
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			status = "disabled";
 		};
 
@@ -680,7 +737,7 @@
 			clock-names = "fck", "brg_int", "scif_clk";
 			dmas = <&dmac1 0x5b>, <&dmac1 0x5a>;
 			dma-names = "tx", "rx";
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			status = "disabled";
 		};
 
@@ -691,7 +748,7 @@
 			reg = <0 0xe6500000 0 0x40>;
 			interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&cpg CPG_MOD 931>;
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			i2c-scl-internal-delay-ns = <110>;
 			status = "disabled";
 		};
@@ -703,7 +760,7 @@
 			reg = <0 0xe6508000 0 0x40>;
 			interrupts = <GIC_SPI 288 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&cpg CPG_MOD 930>;
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			i2c-scl-internal-delay-ns = <6>;
 			status = "disabled";
 		};
@@ -715,7 +772,7 @@
 			reg = <0 0xe6510000 0 0x40>;
 			interrupts = <GIC_SPI 286 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&cpg CPG_MOD 929>;
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			i2c-scl-internal-delay-ns = <6>;
 			status = "disabled";
 		};
@@ -727,7 +784,7 @@
 			reg = <0 0xe66d0000 0 0x40>;
 			interrupts = <GIC_SPI 290 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&cpg CPG_MOD 928>;
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			i2c-scl-internal-delay-ns = <110>;
 			status = "disabled";
 		};
@@ -739,7 +796,7 @@
 			reg = <0 0xe66d8000 0 0x40>;
 			interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&cpg CPG_MOD 927>;
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			i2c-scl-internal-delay-ns = <110>;
 			status = "disabled";
 		};
@@ -751,7 +808,7 @@
 			reg = <0 0xe66e0000 0 0x40>;
 			interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&cpg CPG_MOD 919>;
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			i2c-scl-internal-delay-ns = <110>;
 			status = "disabled";
 		};
@@ -763,7 +820,7 @@
 			reg = <0 0xe66e8000 0 0x40>;
 			interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&cpg CPG_MOD 918>;
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			i2c-scl-internal-delay-ns = <6>;
 			status = "disabled";
 		};
@@ -813,7 +870,7 @@
 				      "src.1", "src.0",
 				      "dvc.0", "dvc.1",
 				      "clk_a", "clk_b", "clk_c", "clk_i";
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			status = "disabled";
 
 			rcar_sound,dvc {
@@ -943,20 +1000,20 @@
 		};
 
 		xhci0: usb@ee000000 {
-			compatible = "renesas,xhci-r8a7795";
+			compatible = "renesas,xhci-r8a7795", "renesas,rcar-gen3-xhci";
 			reg = <0 0xee000000 0 0xc00>;
 			interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&cpg CPG_MOD 328>;
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			status = "disabled";
 		};
 
 		xhci1: usb@ee0400000 {
-			compatible = "renesas,xhci-r8a7795";
+			compatible = "renesas,xhci-r8a7795", "renesas,rcar-gen3-xhci";
 			reg = <0 0xee040000 0 0xc00>;
 			interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&cpg CPG_MOD 327>;
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			status = "disabled";
 		};
 
@@ -968,7 +1025,7 @@
 				      GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
 			interrupt-names = "ch0", "ch1";
 			clocks = <&cpg CPG_MOD 330>;
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			#dma-cells = <1>;
 			dma-channels = <2>;
 		};
@@ -981,7 +1038,7 @@
 				      GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
 			interrupt-names = "ch0", "ch1";
 			clocks = <&cpg CPG_MOD 331>;
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			#dma-cells = <1>;
 			dma-channels = <2>;
 		};
@@ -991,7 +1048,7 @@
 			reg = <0 0xee100000 0 0x2000>;
 			interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&cpg CPG_MOD 314>;
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			status = "disabled";
 		};
 
@@ -1000,7 +1057,7 @@
 			reg = <0 0xee120000 0 0x2000>;
 			interrupts = <GIC_SPI 166 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&cpg CPG_MOD 313>;
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			status = "disabled";
 		};
 
@@ -1009,7 +1066,7 @@
 			reg = <0 0xee140000 0 0x2000>;
 			interrupts = <GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&cpg CPG_MOD 312>;
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			cap-mmc-highspeed;
 			status = "disabled";
 		};
@@ -1019,7 +1076,7 @@
 			reg = <0 0xee160000 0 0x2000>;
 			interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&cpg CPG_MOD 311>;
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			cap-mmc-highspeed;
 			status = "disabled";
 		};
@@ -1029,7 +1086,7 @@
 			reg = <0 0xee080200 0 0x700>;
 			interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&cpg CPG_MOD 703>;
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			#phy-cells = <0>;
 			status = "disabled";
 		};
@@ -1038,7 +1095,7 @@
 			compatible = "renesas,usb2-phy-r8a7795";
 			reg = <0 0xee0a0200 0 0x700>;
 			clocks = <&cpg CPG_MOD 702>;
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			#phy-cells = <0>;
 			status = "disabled";
 		};
@@ -1047,7 +1104,7 @@
 			compatible = "renesas,usb2-phy-r8a7795";
 			reg = <0 0xee0c0200 0 0x700>;
 			clocks = <&cpg CPG_MOD 701>;
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			#phy-cells = <0>;
 			status = "disabled";
 		};
@@ -1059,7 +1116,7 @@
 			clocks = <&cpg CPG_MOD 703>;
 			phys = <&usb2_phy0>;
 			phy-names = "usb";
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			status = "disabled";
 		};
 
@@ -1070,7 +1127,7 @@
 			clocks = <&cpg CPG_MOD 702>;
 			phys = <&usb2_phy1>;
 			phy-names = "usb";
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			status = "disabled";
 		};
 
@@ -1081,7 +1138,7 @@
 			clocks = <&cpg CPG_MOD 701>;
 			phys = <&usb2_phy2>;
 			phy-names = "usb";
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			status = "disabled";
 		};
 
@@ -1092,7 +1149,7 @@
 			clocks = <&cpg CPG_MOD 703>;
 			phys = <&usb2_phy0>;
 			phy-names = "usb";
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			status = "disabled";
 		};
 
@@ -1103,7 +1160,7 @@
 			clocks = <&cpg CPG_MOD 702>;
 			phys = <&usb2_phy1>;
 			phy-names = "usb";
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			status = "disabled";
 		};
 
@@ -1114,7 +1171,56 @@
 			clocks = <&cpg CPG_MOD 701>;
 			phys = <&usb2_phy2>;
 			phy-names = "usb";
-			power-domains = <&cpg>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+		pciec0: pcie@fe000000 {
+			compatible = "renesas,pcie-r8a7795";
+			reg = <0 0xfe000000 0 0x80000>;
+			#address-cells = <3>;
+			#size-cells = <2>;
+			bus-range = <0x00 0xff>;
+			device_type = "pci";
+			ranges = <0x01000000 0 0x00000000 0 0xfe100000 0 0x00100000
+				0x02000000 0 0xfe200000 0 0xfe200000 0 0x00200000
+				0x02000000 0 0x30000000 0 0x30000000 0 0x08000000
+				0x42000000 0 0x38000000 0 0x38000000 0 0x08000000>;
+			/* Map all possible DDR as inbound ranges */
+			dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x40000000>;
+			interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
+			#interrupt-cells = <1>;
+			interrupt-map-mask = <0 0 0 0>;
+			interrupt-map = <0 0 0 0 &gic GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 319>, <&pcie_bus_clk>;
+			clock-names = "pcie", "pcie_bus";
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		pciec1: pcie@ee800000 {
+			compatible = "renesas,pcie-r8a7795";
+			reg = <0 0xee800000 0 0x80000>;
+			#address-cells = <3>;
+			#size-cells = <2>;
+			bus-range = <0x00 0xff>;
+			device_type = "pci";
+			ranges = <0x01000000 0 0x00000000 0 0xee900000 0 0x00100000
+				0x02000000 0 0xeea00000 0 0xeea00000 0 0x00200000
+				0x02000000 0 0xc0000000 0 0xc0000000 0 0x08000000
+				0x42000000 0 0xc8000000 0 0xc8000000 0 0x08000000>;
+			/* Map all possible DDR as inbound ranges */
+			dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x40000000>;
+			interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>;
+			#interrupt-cells = <1>;
+			interrupt-map-mask = <0 0 0 0>;
+			interrupt-map = <0 0 0 0 &gic GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 318>, <&pcie_bus_clk>;
+			clock-names = "pcie", "pcie_bus";
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 			status = "disabled";
 		};
 	};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts linux-libre-4.7-gnu/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts	2016-07-24 15:23:50.000000000 -0400
@@ -141,62 +141,66 @@
 	clock-frequency = <16666666>;
 };
 
+&extalr_clk {
+	clock-frequency = <32768>;
+};
+
 &pfc {
 	pinctrl-0 = <&scif_clk_pins>;
 	pinctrl-names = "default";
 
 	scif1_pins: scif1 {
-		renesas,groups = "scif1_data_a", "scif1_ctrl";
-		renesas,function = "scif1";
+		groups = "scif1_data_a", "scif1_ctrl";
+		function = "scif1";
 	};
 	scif2_pins: scif2 {
-		renesas,groups = "scif2_data_a";
-		renesas,function = "scif2";
+		groups = "scif2_data_a";
+		function = "scif2";
 	};
 	scif_clk_pins: scif_clk {
-		renesas,groups = "scif_clk_a";
-		renesas,function = "scif_clk";
+		groups = "scif_clk_a";
+		function = "scif_clk";
 	};
 
 	i2c2_pins: i2c2 {
-		renesas,groups = "i2c2_a";
-		renesas,function = "i2c2";
+		groups = "i2c2_a";
+		function = "i2c2";
 	};
 
 	avb_pins: avb {
-		renesas,groups = "avb_mdc";
-		renesas,function = "avb";
+		groups = "avb_mdc";
+		function = "avb";
 	};
 
 	sdhi0_pins: sd0 {
-		renesas,groups = "sdhi0_data4", "sdhi0_ctrl";
-		renesas,function = "sdhi0";
+		groups = "sdhi0_data4", "sdhi0_ctrl";
+		function = "sdhi0";
 	};
 
 	sdhi3_pins: sd3 {
-		renesas,groups = "sdhi3_data4", "sdhi3_ctrl";
-		renesas,function = "sdhi3";
+		groups = "sdhi3_data4", "sdhi3_ctrl";
+		function = "sdhi3";
 	};
 
 	sound_pins: sound {
-		renesas,groups = "ssi01239_ctrl", "ssi0_data", "ssi1_data_a";
-		renesas,function = "ssi";
+		groups = "ssi01239_ctrl", "ssi0_data", "ssi1_data_a";
+		function = "ssi";
 	};
 
 	sound_clk_pins: sound_clk {
-		renesas,groups = "audio_clk_a_a", "audio_clk_b_a", "audio_clk_c_a",
-				 "audio_clkout_a", "audio_clkout3_a";
-		renesas,function = "audio_clk";
+		groups = "audio_clk_a_a", "audio_clk_b_a", "audio_clk_c_a",
+			 "audio_clkout_a", "audio_clkout3_a";
+		function = "audio_clk";
 	};
 
 	usb1_pins: usb1 {
-		renesas,groups = "usb1";
-		renesas,function = "usb1";
+		groups = "usb1";
+		function = "usb1";
 	};
 
 	usb2_pins: usb2 {
-		renesas,groups = "usb2";
-		renesas,function = "usb2";
+		groups = "usb2";
+		function = "usb2";
 	};
 };
 
@@ -388,3 +392,16 @@
 &ohci2 {
 	status = "okay";
 };
+
+&pcie_bus_clk {
+	clock-frequency = <100000000>;
+	status = "okay";
+};
+
+&pciec0 {
+	status = "okay";
+};
+
+&pciec1 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/rockchip/Makefile linux-libre-4.7-gnu/arch/arm64/boot/dts/rockchip/Makefile
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/rockchip/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/rockchip/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -1,5 +1,7 @@
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-evb-act8846.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-geekbox.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-r88.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-evb.dtb
 
 always		:= $(dtb-y)
 subdir-y	:= $(dts-dirs)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/rockchip/rk3368.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/rockchip/rk3368.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/rockchip/rk3368.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/rockchip/rk3368.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -413,7 +413,71 @@
 	};
 
 	thermal-zones {
-		#include "rk3368-thermal.dtsi"
+		cpu {
+			polling-delay-passive = <100>; /* milliseconds */
+			polling-delay = <5000>; /* milliseconds */
+
+			thermal-sensors = <&tsadc 0>;
+
+			trips {
+				cpu_alert0: cpu_alert0 {
+					temperature = <75000>; /* millicelsius */
+					hysteresis = <2000>; /* millicelsius */
+					type = "passive";
+				};
+				cpu_alert1: cpu_alert1 {
+					temperature = <80000>; /* millicelsius */
+					hysteresis = <2000>; /* millicelsius */
+					type = "passive";
+				};
+				cpu_crit: cpu_crit {
+					temperature = <95000>; /* millicelsius */
+					hysteresis = <2000>; /* millicelsius */
+					type = "critical";
+				};
+			};
+
+			cooling-maps {
+				map0 {
+					trip = <&cpu_alert0>;
+					cooling-device =
+					<&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+				};
+				map1 {
+					trip = <&cpu_alert1>;
+					cooling-device =
+					<&cpu_l0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+				};
+			};
+		};
+
+		gpu {
+			polling-delay-passive = <100>; /* milliseconds */
+			polling-delay = <5000>; /* milliseconds */
+
+			thermal-sensors = <&tsadc 1>;
+
+			trips {
+				gpu_alert0: gpu_alert0 {
+					temperature = <80000>; /* millicelsius */
+					hysteresis = <2000>; /* millicelsius */
+					type = "passive";
+				};
+				gpu_crit: gpu_crit {
+					temperature = <115000>; /* millicelsius */
+					hysteresis = <2000>; /* millicelsius */
+					type = "critical";
+				};
+			};
+
+			cooling-maps {
+				map0 {
+					trip = <&gpu_alert0>;
+					cooling-device =
+					<&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+				};
+			};
+		};
 	};
 
 	tsadc: tsadc@ff280000 {
@@ -555,6 +619,18 @@
 		status = "disabled";
 	};
 
+	mbox: mbox@ff6b0000 {
+		compatible = "rockchip,rk3368-mailbox";
+		reg = <0x0 0xff6b0000 0x0 0x1000>;
+		interrupts = <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru PCLK_MAILBOX>;
+		clock-names = "pclk_mailbox";
+		#mbox-cells = <1>;
+	};
+
 	pmugrf: syscon@ff738000 {
 		compatible = "rockchip,rk3368-pmugrf", "syscon";
 		reg = <0x0 0xff738000 0x0 0x1000>;
@@ -926,11 +1002,11 @@
 
 		tsadc {
 			otp_gpio: otp-gpio {
-				rockchip,pins = <0 10 RK_FUNC_GPIO &pcfg_pull_none>;
+				rockchip,pins = <0 3 RK_FUNC_GPIO &pcfg_pull_none>;
 			};
 
 			otp_out: otp-out {
-				rockchip,pins = <0 10 RK_FUNC_1 &pcfg_pull_none>;
+				rockchip,pins = <0 3 RK_FUNC_1 &pcfg_pull_none>;
 			};
 		};
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/rockchip/rk3368-evb.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/rockchip/rk3368-evb.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/rockchip/rk3368-evb.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/rockchip/rk3368-evb.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -40,6 +40,7 @@
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
+#include <dt-bindings/input/input.h>
 #include <dt-bindings/pwm/pwm.h>
 #include "rk3368.dtsi"
 
@@ -105,16 +106,14 @@
 
 	keys: gpio-keys {
 		compatible = "gpio-keys";
-		#address-cells = <1>;
-		#size-cells = <0>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&pwr_key>;
 
-		button@0 {
+		power {
 			wakeup-source;
 			gpios = <&gpio0 2 GPIO_ACTIVE_LOW>;
 			label = "GPIO Power";
-			linux,code = <116>;
+			linux,code = <KEY_POWER>;
 		};
 	};
 
@@ -152,7 +151,6 @@
 };
 
 &emmc {
-	broken-cd;
 	bus-width = <8>;
 	cap-mmc-highspeed;
 	disable-wp;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/rockchip/rk3368-geekbox.dts linux-libre-4.7-gnu/arch/arm64/boot/dts/rockchip/rk3368-geekbox.dts
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/rockchip/rk3368-geekbox.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/rockchip/rk3368-geekbox.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,319 @@
+/*
+ * Copyright (c) 2016 Andreas Färber
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "rk3368.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+	model = "GeekBox";
+	compatible = "geekbuying,geekbox", "rockchip,rk3368";
+
+	chosen {
+		stdout-path = "serial2:115200n8";
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x0 0x0 0x0 0x80000000>;
+	};
+
+	ext_gmac: gmac-clk {
+		compatible = "fixed-clock";
+		clock-frequency = <125000000>;
+		clock-output-names = "ext_gmac";
+		#clock-cells = <0>;
+	};
+
+	ir: ir-receiver {
+		compatible = "gpio-ir-receiver";
+		gpios = <&gpio3 30 GPIO_ACTIVE_LOW>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&ir_int>;
+	};
+
+	keys: gpio-keys {
+		compatible = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwr_key>;
+
+		power {
+			gpios = <&gpio0 2 GPIO_ACTIVE_LOW>;
+			label = "GPIO Power";
+			linux,code = <KEY_POWER>;
+			wakeup-source;
+		};
+	};
+
+	leds: gpio-leds {
+		compatible = "gpio-leds";
+
+		blue {
+			gpios = <&gpio2 2 GPIO_ACTIVE_HIGH>;
+			label = "geekbox:blue:led";
+			default-state = "on";
+		};
+
+		red {
+			gpios = <&gpio2 3 GPIO_ACTIVE_HIGH>;
+			label = "geekbox:red:led";
+			default-state = "off";
+		};
+	};
+
+	vcc_sys: vcc-sys-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_sys";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+};
+
+&emmc {
+	status = "okay";
+	bus-width = <8>;
+	cap-mmc-highspeed;
+	clock-frequency = <150000000>;
+	disable-wp;
+	keep-power-in-suspend;
+	non-removable;
+	num-slots = <1>;
+	vmmc-supply = <&vcc_io>;
+	vqmmc-supply = <&vcc18_flash>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&emmc_clk>, <&emmc_cmd>, <&emmc_bus8>;
+};
+
+&gmac {
+	status = "okay";
+	phy-supply = <&vcc_lan>;
+	phy-mode = "rgmii";
+	clock_in_out = "input";
+	assigned-clocks = <&cru SCLK_MAC>;
+	assigned-clock-parents = <&ext_gmac>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&rgmii_pins>;
+	tx_delay = <0x30>;
+	rx_delay = <0x10>;
+};
+
+&i2c0 {
+	status = "okay";
+
+	rk808: pmic@1b {
+		compatible = "rockchip,rk808";
+		reg = <0x1b>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pmic_int>, <&pmic_sleep>;
+		interrupt-parent = <&gpio0>;
+		interrupts = <5 IRQ_TYPE_LEVEL_LOW>;
+		rockchip,system-power-controller;
+		vcc1-supply = <&vcc_sys>;
+		vcc2-supply = <&vcc_sys>;
+		vcc3-supply = <&vcc_sys>;
+		vcc4-supply = <&vcc_sys>;
+		vcc6-supply = <&vcc_sys>;
+		vcc7-supply = <&vcc_sys>;
+		vcc8-supply = <&vcc_io>;
+		vcc9-supply = <&vcc_sys>;
+		vcc10-supply = <&vcc_sys>;
+		vcc11-supply = <&vcc_sys>;
+		vcc12-supply = <&vcc_io>;
+		clock-output-names = "xin32k", "rk808-clkout2";
+		#clock-cells = <1>;
+
+		regulators {
+			vdd_cpu: DCDC_REG1 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <700000>;
+				regulator-max-microvolt = <1500000>;
+				regulator-name = "vdd_cpu";
+			};
+
+			vdd_log: DCDC_REG2 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <700000>;
+				regulator-max-microvolt = <1500000>;
+				regulator-name = "vdd_log";
+			};
+
+			vcc_ddr: DCDC_REG3 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-name = "vcc_ddr";
+			};
+
+			vcc_io: DCDC_REG4 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc_io";
+			};
+
+			vcc18_flash: LDO_REG1 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc18_flash";
+			};
+
+			vcc33_lcd: LDO_REG2 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc33_lcd";
+			};
+
+			vdd_10: LDO_REG3 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-name = "vdd_10";
+			};
+
+			vcca_18: LDO_REG4 {
+				regulator-boot-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcca_18";
+			};
+
+			vccio_sd: LDO_REG5 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vccio_sd";
+			};
+
+			vdd10_lcd: LDO_REG6 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-name = "vdd10_lcd";
+			};
+
+			vcc_18: LDO_REG7 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc_18";
+			};
+
+			vcc18_lcd: LDO_REG8 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc18_lcd";
+			};
+
+			vcc_sd: SWITCH_REG1 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-name = "vcc_sd";
+			};
+
+			vcc_lan: SWITCH_REG2 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-name = "vcc_lan";
+			};
+		};
+	};
+};
+
+&pinctrl {
+	ir {
+		ir_int: ir-int {
+			rockchip,pins = <3 30 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	keys {
+		pwr_key: pwr-key {
+			rockchip,pins = <0 2 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	pmic {
+		pmic_sleep: pmic-sleep {
+			rockchip,pins = <0 0 RK_FUNC_2 &pcfg_pull_none>;
+		};
+
+		pmic_int: pmic-int {
+			rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+	};
+};
+
+&tsadc {
+	status = "okay";
+	rockchip,hw-tshut-mode = <0>; /* CRU */
+	rockchip,hw-tshut-polarity = <1>; /* high */
+};
+
+&uart2 {
+	status = "okay";
+};
+
+&usb_host0_ehci {
+	status = "okay";
+};
+
+&usb_otg {
+	status = "okay";
+};
+
+&wdt {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/rockchip/rk3368-r88.dts linux-libre-4.7-gnu/arch/arm64/boot/dts/rockchip/rk3368-r88.dts
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/rockchip/rk3368-r88.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/rockchip/rk3368-r88.dts	2016-07-24 15:23:50.000000000 -0400
@@ -42,6 +42,7 @@
 
 /dts-v1/;
 #include "rk3368.dtsi"
+#include <dt-bindings/input/input.h>
 
 / {
 	model = "Rockchip R88";
@@ -65,16 +66,14 @@
 
 	keys: gpio-keys {
 		compatible = "gpio-keys";
-		#address-cells = <1>;
-		#size-cells = <0>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&pwr_key>;
 
-		button@0 {
+		power {
 			wakeup-source;
 			gpios = <&gpio0 2 GPIO_ACTIVE_LOW>;
 			label = "GPIO Power";
-			linux,code = <116>;
+			linux,code = <KEY_POWER>;
 		};
 	};
 
@@ -185,7 +184,6 @@
 };
 
 &emmc {
-	broken-cd;
 	bus-width = <8>;
 	cap-mmc-highspeed;
 	disable-wp;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/rockchip/rk3368-thermal.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/rockchip/rk3368-thermal.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/rockchip/rk3368-thermal.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/rockchip/rk3368-thermal.dtsi	1969-12-31 19:00:00.000000000 -0500
@@ -1,112 +0,0 @@
-/*
- * Device Tree Source for RK3368 SoC thermal
- *
- * Copyright (c) 2015, Fuzhou Rockchip Electronics Co., Ltd
- * Caesar Wang <wxt@rock-chips.com>
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This file is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- * Or, alternatively,
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use,
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *     OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <dt-bindings/thermal/thermal.h>
-
-cpu_thermal: cpu_thermal {
-	polling-delay-passive = <100>; /* milliseconds */
-	polling-delay = <5000>; /* milliseconds */
-
-	thermal-sensors = <&tsadc 0>;
-
-	trips {
-		cpu_alert0: cpu_alert0 {
-			temperature = <75000>; /* millicelsius */
-			hysteresis = <2000>; /* millicelsius */
-			type = "passive";
-		};
-		cpu_alert1: cpu_alert1 {
-			temperature = <80000>; /* millicelsius */
-			hysteresis = <2000>; /* millicelsius */
-			type = "passive";
-		};
-		cpu_crit: cpu_crit {
-			temperature = <95000>; /* millicelsius */
-			hysteresis = <2000>; /* millicelsius */
-			type = "critical";
-		};
-	};
-
-	cooling-maps {
-		map0 {
-			trip = <&cpu_alert0>;
-			cooling-device =
-				<&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
-		};
-		map1 {
-			trip = <&cpu_alert1>;
-			cooling-device =
-				<&cpu_l0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
-		};
-	};
-};
-
-gpu_thermal: gpu_thermal {
-	polling-delay-passive = <100>; /* milliseconds */
-	polling-delay = <5000>; /* milliseconds */
-
-	thermal-sensors = <&tsadc 1>;
-
-	trips {
-		gpu_alert0: gpu_alert0 {
-			temperature = <80000>; /* millicelsius */
-			hysteresis = <2000>; /* millicelsius */
-			type = "passive";
-		};
-		gpu_crit: gpu_crit {
-			temperature = <1150000>; /* millicelsius */
-			hysteresis = <2000>; /* millicelsius */
-			type = "critical";
-		};
-	};
-
-	cooling-maps {
-		map0 {
-			trip = <&gpu_alert0>;
-			cooling-device =
-				<&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
-		};
-	};
-};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/rockchip/rk3399.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/rockchip/rk3399.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/rockchip/rk3399.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/rockchip/rk3399.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,1013 @@
+/*
+ * Copyright (c) 2016 Fuzhou Rockchip Electronics Co., Ltd
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <dt-bindings/clock/rk3399-cru.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+
+/ {
+	compatible = "rockchip,rk3399";
+
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+		serial3 = &uart3;
+		serial4 = &uart4;
+	};
+
+	cpus {
+		#address-cells = <2>;
+		#size-cells = <0>;
+
+		cpu-map {
+			cluster0 {
+				core0 {
+					cpu = <&cpu_l0>;
+				};
+				core1 {
+					cpu = <&cpu_l1>;
+				};
+				core2 {
+					cpu = <&cpu_l2>;
+				};
+				core3 {
+					cpu = <&cpu_l3>;
+				};
+			};
+
+			cluster1 {
+				core0 {
+					cpu = <&cpu_b0>;
+				};
+				core1 {
+					cpu = <&cpu_b1>;
+				};
+			};
+		};
+
+		cpu_l0: cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x0>;
+			enable-method = "psci";
+			#cooling-cells = <2>; /* min followed by max */
+			clocks = <&cru ARMCLKL>;
+		};
+
+		cpu_l1: cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x1>;
+			enable-method = "psci";
+			clocks = <&cru ARMCLKL>;
+		};
+
+		cpu_l2: cpu@2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x2>;
+			enable-method = "psci";
+			clocks = <&cru ARMCLKL>;
+		};
+
+		cpu_l3: cpu@3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x3>;
+			enable-method = "psci";
+			clocks = <&cru ARMCLKL>;
+		};
+
+		cpu_b0: cpu@100 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x0 0x100>;
+			enable-method = "psci";
+			#cooling-cells = <2>; /* min followed by max */
+			clocks = <&cru ARMCLKB>;
+		};
+
+		cpu_b1: cpu@101 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x0 0x101>;
+			enable-method = "psci";
+			clocks = <&cru ARMCLKB>;
+		};
+	};
+
+	psci {
+		compatible = "arm,psci-1.0";
+		method = "smc";
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+	};
+
+	xin24m: xin24m {
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+		clock-output-names = "xin24m";
+		#clock-cells = <0>;
+	};
+
+	amba {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		dmac_bus: dma-controller@ff6d0000 {
+			compatible = "arm,pl330", "arm,primecell";
+			reg = <0x0 0xff6d0000 0x0 0x4000>;
+			interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
+			#dma-cells = <1>;
+			clocks = <&cru ACLK_DMAC0_PERILP>;
+			clock-names = "apb_pclk";
+		};
+
+		dmac_peri: dma-controller@ff6e0000 {
+			compatible = "arm,pl330", "arm,primecell";
+			reg = <0x0 0xff6e0000 0x0 0x4000>;
+			interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
+			#dma-cells = <1>;
+			clocks = <&cru ACLK_DMAC1_PERILP>;
+			clock-names = "apb_pclk";
+		};
+	};
+
+	sdio0: dwmmc@fe310000 {
+		compatible = "rockchip,rk3399-dw-mshc",
+			     "rockchip,rk3288-dw-mshc";
+		reg = <0x0 0xfe310000 0x0 0x4000>;
+		interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
+		clock-freq-min-max = <400000 150000000>;
+		clocks = <&cru HCLK_SDIO>, <&cru SCLK_SDIO>,
+			 <&cru SCLK_SDIO_DRV>, <&cru SCLK_SDIO_SAMPLE>;
+		clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
+		fifo-depth = <0x100>;
+		status = "disabled";
+	};
+
+	sdmmc: dwmmc@fe320000 {
+		compatible = "rockchip,rk3399-dw-mshc",
+			     "rockchip,rk3288-dw-mshc";
+		reg = <0x0 0xfe320000 0x0 0x4000>;
+		interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+		clock-freq-min-max = <400000 150000000>;
+		clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>,
+			 <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>;
+		clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
+		fifo-depth = <0x100>;
+		status = "disabled";
+	};
+
+	usb_host0_ehci: usb@fe380000 {
+		compatible = "generic-ehci";
+		reg = <0x0 0xfe380000 0x0 0x20000>;
+		interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru HCLK_HOST0>, <&cru HCLK_HOST0_ARB>;
+		clock-names = "hclk_host0", "hclk_host0_arb";
+		status = "disabled";
+	};
+
+	usb_host0_ohci: usb@fe3a0000 {
+		compatible = "generic-ohci";
+		reg = <0x0 0xfe3a0000 0x0 0x20000>;
+		interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru HCLK_HOST0>, <&cru HCLK_HOST0_ARB>;
+		clock-names = "hclk_host0", "hclk_host0_arb";
+		status = "disabled";
+	};
+
+	usb_host1_ehci: usb@fe3c0000 {
+		compatible = "generic-ehci";
+		reg = <0x0 0xfe3c0000 0x0 0x20000>;
+		interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru HCLK_HOST1>, <&cru HCLK_HOST1_ARB>;
+		clock-names = "hclk_host1", "hclk_host1_arb";
+		status = "disabled";
+	};
+
+	usb_host1_ohci: usb@fe3e0000 {
+		compatible = "generic-ohci";
+		reg = <0x0 0xfe3e0000 0x0 0x20000>;
+		interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru HCLK_HOST1>, <&cru HCLK_HOST1_ARB>;
+		clock-names = "hclk_host1", "hclk_host1_arb";
+		status = "disabled";
+	};
+
+	gic: interrupt-controller@fee00000 {
+		compatible = "arm,gic-v3";
+		#interrupt-cells = <3>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+		interrupt-controller;
+
+		reg = <0x0 0xfee00000 0 0x10000>, /* GICD */
+		      <0x0 0xfef00000 0 0xc0000>, /* GICR */
+		      <0x0 0xfff00000 0 0x10000>, /* GICC */
+		      <0x0 0xfff10000 0 0x10000>, /* GICH */
+		      <0x0 0xfff20000 0 0x10000>; /* GICV */
+		interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+		its: interrupt-controller@fee20000 {
+			compatible = "arm,gic-v3-its";
+			msi-controller;
+			reg = <0x0 0xfee20000 0x0 0x20000>;
+		};
+	};
+
+	uart0: serial@ff180000 {
+		compatible = "rockchip,rk3399-uart", "snps,dw-apb-uart";
+		reg = <0x0 0xff180000 0x0 0x100>;
+		clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>;
+		clock-names = "baudclk", "apb_pclk";
+		interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart0_xfer>;
+		status = "disabled";
+	};
+
+	uart1: serial@ff190000 {
+		compatible = "rockchip,rk3399-uart", "snps,dw-apb-uart";
+		reg = <0x0 0xff190000 0x0 0x100>;
+		clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>;
+		clock-names = "baudclk", "apb_pclk";
+		interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart1_xfer>;
+		status = "disabled";
+	};
+
+	uart2: serial@ff1a0000 {
+		compatible = "rockchip,rk3399-uart", "snps,dw-apb-uart";
+		reg = <0x0 0xff1a0000 0x0 0x100>;
+		clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>;
+		clock-names = "baudclk", "apb_pclk";
+		interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart2c_xfer>;
+		status = "disabled";
+	};
+
+	uart3: serial@ff1b0000 {
+		compatible = "rockchip,rk3399-uart", "snps,dw-apb-uart";
+		reg = <0x0 0xff1b0000 0x0 0x100>;
+		clocks = <&cru SCLK_UART3>, <&cru PCLK_UART3>;
+		clock-names = "baudclk", "apb_pclk";
+		interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart3_xfer>;
+		status = "disabled";
+	};
+
+	spi0: spi@ff1c0000 {
+		compatible = "rockchip,rk3399-spi", "rockchip,rk3066-spi";
+		reg = <0x0 0xff1c0000 0x0 0x1000>;
+		clocks = <&cru SCLK_SPI0>, <&cru PCLK_SPI0>;
+		clock-names = "spiclk", "apb_pclk";
+		interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&spi0_clk &spi0_tx &spi0_rx &spi0_cs0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	spi1: spi@ff1d0000 {
+		compatible = "rockchip,rk3399-spi", "rockchip,rk3066-spi";
+		reg = <0x0 0xff1d0000 0x0 0x1000>;
+		clocks = <&cru SCLK_SPI1>, <&cru PCLK_SPI1>;
+		clock-names = "spiclk", "apb_pclk";
+		interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&spi1_clk &spi1_tx &spi1_rx &spi1_cs0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	spi2: spi@ff1e0000 {
+		compatible = "rockchip,rk3399-spi", "rockchip,rk3066-spi";
+		reg = <0x0 0xff1e0000 0x0 0x1000>;
+		clocks = <&cru SCLK_SPI2>, <&cru PCLK_SPI2>;
+		clock-names = "spiclk", "apb_pclk";
+		interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&spi2_clk &spi2_tx &spi2_rx &spi2_cs0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	spi4: spi@ff1f0000 {
+		compatible = "rockchip,rk3399-spi", "rockchip,rk3066-spi";
+		reg = <0x0 0xff1f0000 0x0 0x1000>;
+		clocks = <&cru SCLK_SPI4>, <&cru PCLK_SPI4>;
+		clock-names = "spiclk", "apb_pclk";
+		interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&spi4_clk &spi4_tx &spi4_rx &spi4_cs0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	spi5: spi@ff200000 {
+		compatible = "rockchip,rk3399-spi", "rockchip,rk3066-spi";
+		reg = <0x0 0xff200000 0x0 0x1000>;
+		clocks = <&cru SCLK_SPI5>, <&cru PCLK_SPI5>;
+		clock-names = "spiclk", "apb_pclk";
+		interrupts = <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&spi5_clk &spi5_tx &spi5_rx &spi5_cs0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	pmugrf: syscon@ff320000 {
+		compatible = "rockchip,rk3399-pmugrf", "syscon";
+		reg = <0x0 0xff320000 0x0 0x1000>;
+	};
+
+	spi3: spi@ff350000 {
+		compatible = "rockchip,rk3399-spi", "rockchip,rk3066-spi";
+		reg = <0x0 0xff350000 0x0 0x1000>;
+		clocks = <&pmucru SCLK_SPI3_PMU>, <&pmucru PCLK_SPI3_PMU>;
+		clock-names = "spiclk", "apb_pclk";
+		interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&spi3_clk &spi3_tx &spi3_rx &spi3_cs0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	uart4: serial@ff370000 {
+		compatible = "rockchip,rk3399-uart", "snps,dw-apb-uart";
+		reg = <0x0 0xff370000 0x0 0x100>;
+		clocks = <&pmucru SCLK_UART4_PMU>, <&pmucru PCLK_UART4_PMU>;
+		clock-names = "baudclk", "apb_pclk";
+		interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart4_xfer>;
+		status = "disabled";
+	};
+
+	pwm0: pwm@ff420000 {
+		compatible = "rockchip,rk3399-pwm", "rockchip,rk3288-pwm";
+		reg = <0x0 0xff420000 0x0 0x10>;
+		#pwm-cells = <3>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm0_pin>;
+		clocks = <&pmucru PCLK_RKPWM_PMU>;
+		clock-names = "pwm";
+		status = "disabled";
+	};
+
+	pwm1: pwm@ff420010 {
+		compatible = "rockchip,rk3399-pwm", "rockchip,rk3288-pwm";
+		reg = <0x0 0xff420010 0x0 0x10>;
+		#pwm-cells = <3>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm1_pin>;
+		clocks = <&pmucru PCLK_RKPWM_PMU>;
+		clock-names = "pwm";
+		status = "disabled";
+	};
+
+	pwm2: pwm@ff420020 {
+		compatible = "rockchip,rk3399-pwm", "rockchip,rk3288-pwm";
+		reg = <0x0 0xff420020 0x0 0x10>;
+		#pwm-cells = <3>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm2_pin>;
+		clocks = <&pmucru PCLK_RKPWM_PMU>;
+		clock-names = "pwm";
+		status = "disabled";
+	};
+
+	pwm3: pwm@ff420030 {
+		compatible = "rockchip,rk3399-pwm", "rockchip,rk3288-pwm";
+		reg = <0x0 0xff420030 0x0 0x10>;
+		#pwm-cells = <3>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm3a_pin>;
+		clocks = <&pmucru PCLK_RKPWM_PMU>;
+		clock-names = "pwm";
+		status = "disabled";
+	};
+
+	pmucru: pmu-clock-controller@ff750000 {
+		compatible = "rockchip,rk3399-pmucru";
+		reg = <0x0 0xff750000 0x0 0x1000>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+		assigned-clocks = <&pmucru PLL_PPLL>;
+		assigned-clock-rates = <676000000>;
+	};
+
+	cru: clock-controller@ff760000 {
+		compatible = "rockchip,rk3399-cru";
+		reg = <0x0 0xff760000 0x0 0x1000>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
+	grf: syscon@ff770000 {
+		compatible = "rockchip,rk3399-grf", "syscon";
+		reg = <0x0 0xff770000 0x0 0x10000>;
+	};
+
+	watchdog@ff840000 {
+		compatible = "snps,dw-wdt";
+		reg = <0x0 0xff840000 0x0 0x100>;
+		clocks = <&cru PCLK_WDT>;
+		interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	spdif: spdif@ff870000 {
+		compatible = "rockchip,rk3399-spdif";
+		reg = <0x0 0xff870000 0x0 0x1000>;
+		interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
+		dmas = <&dmac_bus 7>;
+		dma-names = "tx";
+		clock-names = "mclk", "hclk";
+		clocks = <&cru SCLK_SPDIF_8CH>, <&cru HCLK_SPDIF>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&spdif_bus>;
+		status = "disabled";
+	};
+
+	i2s0: i2s@ff880000 {
+		compatible = "rockchip,rk3399-i2s", "rockchip,rk3066-i2s";
+		reg = <0x0 0xff880000 0x0 0x1000>;
+		rockchip,grf = <&grf>;
+		interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+		dmas = <&dmac_bus 0>, <&dmac_bus 1>;
+		dma-names = "tx", "rx";
+		clock-names = "i2s_clk", "i2s_hclk";
+		clocks = <&cru SCLK_I2S0_8CH>, <&cru HCLK_I2S0_8CH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2s0_8ch_bus>;
+		status = "disabled";
+	};
+
+	i2s1: i2s@ff890000 {
+		compatible = "rockchip,rk3399-i2s", "rockchip,rk3066-i2s";
+		reg = <0x0 0xff890000 0x0 0x1000>;
+		interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+		dmas = <&dmac_bus 2>, <&dmac_bus 3>;
+		dma-names = "tx", "rx";
+		clock-names = "i2s_clk", "i2s_hclk";
+		clocks = <&cru SCLK_I2S1_8CH>, <&cru HCLK_I2S1_8CH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2s1_2ch_bus>;
+		status = "disabled";
+	};
+
+	i2s2: i2s@ff8a0000 {
+		compatible = "rockchip,rk3399-i2s", "rockchip,rk3066-i2s";
+		reg = <0x0 0xff8a0000 0x0 0x1000>;
+		interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+		dmas = <&dmac_bus 4>, <&dmac_bus 5>;
+		dma-names = "tx", "rx";
+		clock-names = "i2s_clk", "i2s_hclk";
+		clocks = <&cru SCLK_I2S2_8CH>, <&cru HCLK_I2S2_8CH>;
+		status = "disabled";
+	};
+
+	pinctrl: pinctrl {
+		compatible = "rockchip,rk3399-pinctrl";
+		rockchip,grf = <&grf>;
+		rockchip,pmu = <&pmugrf>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		gpio0: gpio0@ff720000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x0 0xff720000 0x0 0x100>;
+			clocks = <&pmucru PCLK_GPIO0_PMU>;
+			interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+
+			gpio-controller;
+			#gpio-cells = <0x2>;
+
+			interrupt-controller;
+			#interrupt-cells = <0x2>;
+		};
+
+		gpio1: gpio1@ff730000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x0 0xff730000 0x0 0x100>;
+			clocks = <&pmucru PCLK_GPIO1_PMU>;
+			interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+
+			gpio-controller;
+			#gpio-cells = <0x2>;
+
+			interrupt-controller;
+			#interrupt-cells = <0x2>;
+		};
+
+		gpio2: gpio2@ff780000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x0 0xff780000 0x0 0x100>;
+			clocks = <&cru PCLK_GPIO2>;
+			interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+
+			gpio-controller;
+			#gpio-cells = <0x2>;
+
+			interrupt-controller;
+			#interrupt-cells = <0x2>;
+		};
+
+		gpio3: gpio3@ff788000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x0 0xff788000 0x0 0x100>;
+			clocks = <&cru PCLK_GPIO3>;
+			interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+
+			gpio-controller;
+			#gpio-cells = <0x2>;
+
+			interrupt-controller;
+			#interrupt-cells = <0x2>;
+		};
+
+		gpio4: gpio4@ff790000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x0 0xff790000 0x0 0x100>;
+			clocks = <&cru PCLK_GPIO4>;
+			interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
+
+			gpio-controller;
+			#gpio-cells = <0x2>;
+
+			interrupt-controller;
+			#interrupt-cells = <0x2>;
+		};
+
+		pcfg_pull_up: pcfg-pull-up {
+			bias-pull-up;
+		};
+
+		pcfg_pull_down: pcfg-pull-down {
+			bias-pull-down;
+		};
+
+		pcfg_pull_none: pcfg-pull-none {
+			bias-disable;
+		};
+
+		pcfg_pull_none_12ma: pcfg-pull-none-12ma {
+			bias-disable;
+			drive-strength = <12>;
+		};
+
+		pcfg_pull_up_8ma: pcfg-pull-up-8ma {
+			bias-pull-up;
+			drive-strength = <8>;
+		};
+
+		pcfg_pull_down_4ma: pcfg-pull-down-4ma {
+			bias-pull-down;
+			drive-strength = <4>;
+		};
+
+		pcfg_pull_up_2ma: pcfg-pull-up-2ma {
+			bias-pull-up;
+			drive-strength = <2>;
+		};
+
+		pcfg_pull_down_12ma: pcfg-pull-down-12ma {
+			bias-pull-down;
+			drive-strength = <12>;
+		};
+
+		pcfg_pull_none_13ma: pcfg-pull-none-13ma {
+			bias-disable;
+			drive-strength = <13>;
+		};
+
+		i2c0 {
+			i2c0_xfer: i2c0-xfer {
+				rockchip,pins =
+					<1 15 RK_FUNC_2 &pcfg_pull_none>,
+					<1 16 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+
+		i2c1 {
+			i2c1_xfer: i2c1-xfer {
+				rockchip,pins =
+					<4 2 RK_FUNC_1 &pcfg_pull_none>,
+					<4 1 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		i2c2 {
+			i2c2_xfer: i2c2-xfer {
+				rockchip,pins =
+					<2 1 RK_FUNC_2 &pcfg_pull_none_12ma>,
+					<2 0 RK_FUNC_2 &pcfg_pull_none_12ma>;
+			};
+		};
+
+		i2c3 {
+			i2c3_xfer: i2c3-xfer {
+				rockchip,pins =
+					<4 17 RK_FUNC_1 &pcfg_pull_none>,
+					<4 16 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		i2c4 {
+			i2c4_xfer: i2c4-xfer {
+				rockchip,pins =
+					<1 12 RK_FUNC_1 &pcfg_pull_none>,
+					<1 11 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		i2c5 {
+			i2c5_xfer: i2c5-xfer {
+				rockchip,pins =
+					<3 11 RK_FUNC_2 &pcfg_pull_none>,
+					<3 10 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+
+		i2c6 {
+			i2c6_xfer: i2c6-xfer {
+				rockchip,pins =
+					<2 10 RK_FUNC_2 &pcfg_pull_none>,
+					<2 9 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+
+		i2c7 {
+			i2c7_xfer: i2c7-xfer {
+				rockchip,pins =
+					<2 8 RK_FUNC_2 &pcfg_pull_none>,
+					<2 7 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+
+		i2c8 {
+			i2c8_xfer: i2c8-xfer {
+				rockchip,pins =
+					<1 21 RK_FUNC_1 &pcfg_pull_none>,
+					<1 20 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		i2s0 {
+			i2s0_8ch_bus: i2s0-8ch-bus {
+				rockchip,pins =
+					<3 24 RK_FUNC_1 &pcfg_pull_none>,
+					<3 25 RK_FUNC_1 &pcfg_pull_none>,
+					<3 26 RK_FUNC_1 &pcfg_pull_none>,
+					<3 27 RK_FUNC_1 &pcfg_pull_none>,
+					<3 28 RK_FUNC_1 &pcfg_pull_none>,
+					<3 29 RK_FUNC_1 &pcfg_pull_none>,
+					<3 30 RK_FUNC_1 &pcfg_pull_none>,
+					<3 31 RK_FUNC_1 &pcfg_pull_none>,
+					<4 0 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		i2s1 {
+			i2s1_2ch_bus: i2s1-2ch-bus {
+				rockchip,pins =
+					<4 3 RK_FUNC_1 &pcfg_pull_none>,
+					<4 4 RK_FUNC_1 &pcfg_pull_none>,
+					<4 5 RK_FUNC_1 &pcfg_pull_none>,
+					<4 6 RK_FUNC_1 &pcfg_pull_none>,
+					<4 7 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		spdif {
+			spdif_bus: spdif-bus {
+				rockchip,pins =
+					<4 21 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		spi0 {
+			spi0_clk: spi0-clk {
+				rockchip,pins =
+					<3 6 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi0_cs0: spi0-cs0 {
+				rockchip,pins =
+					<3 7 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi0_cs1: spi0-cs1 {
+				rockchip,pins =
+					<3 8 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi0_tx: spi0-tx {
+				rockchip,pins =
+					<3 5 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi0_rx: spi0-rx {
+				rockchip,pins =
+					<3 4 RK_FUNC_2 &pcfg_pull_up>;
+			};
+		};
+
+		spi1 {
+			spi1_clk: spi1-clk {
+				rockchip,pins =
+					<1 9 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi1_cs0: spi1-cs0 {
+				rockchip,pins =
+					<1 10 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi1_rx: spi1-rx {
+				rockchip,pins =
+					<1 7 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi1_tx: spi1-tx {
+				rockchip,pins =
+					<1 8 RK_FUNC_2 &pcfg_pull_up>;
+			};
+		};
+
+		spi2 {
+			spi2_clk: spi2-clk {
+				rockchip,pins =
+					<2 11 RK_FUNC_1 &pcfg_pull_up>;
+			};
+			spi2_cs0: spi2-cs0 {
+				rockchip,pins =
+					<2 12 RK_FUNC_1 &pcfg_pull_up>;
+			};
+			spi2_rx: spi2-rx {
+				rockchip,pins =
+					<2 9 RK_FUNC_1 &pcfg_pull_up>;
+			};
+			spi2_tx: spi2-tx {
+				rockchip,pins =
+					<2 10 RK_FUNC_1 &pcfg_pull_up>;
+			};
+		};
+
+		spi3 {
+			spi3_clk: spi3-clk {
+				rockchip,pins =
+					<1 17 RK_FUNC_1 &pcfg_pull_up>;
+			};
+			spi3_cs0: spi3-cs0 {
+				rockchip,pins =
+					<1 18 RK_FUNC_1 &pcfg_pull_up>;
+			};
+			spi3_rx: spi3-rx {
+				rockchip,pins =
+					<1 15 RK_FUNC_1 &pcfg_pull_up>;
+			};
+			spi3_tx: spi3-tx {
+				rockchip,pins =
+					<1 16 RK_FUNC_1 &pcfg_pull_up>;
+			};
+		};
+
+		spi4 {
+			spi4_clk: spi4-clk {
+				rockchip,pins =
+					<3 2 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi4_cs0: spi4-cs0 {
+				rockchip,pins =
+					<3 3 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi4_rx: spi4-rx {
+				rockchip,pins =
+					<3 0 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi4_tx: spi4-tx {
+				rockchip,pins =
+					<3 1 RK_FUNC_2 &pcfg_pull_up>;
+			};
+		};
+
+		spi5 {
+			spi5_clk: spi5-clk {
+				rockchip,pins =
+					<2 22 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi5_cs0: spi5-cs0 {
+				rockchip,pins =
+					<2 23 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi5_rx: spi5-rx {
+				rockchip,pins =
+					<2 20 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi5_tx: spi5-tx {
+				rockchip,pins =
+					<2 21 RK_FUNC_2 &pcfg_pull_up>;
+			};
+		};
+
+		uart0 {
+			uart0_xfer: uart0-xfer {
+				rockchip,pins =
+					<2 16 RK_FUNC_1 &pcfg_pull_up>,
+					<2 17 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			uart0_cts: uart0-cts {
+				rockchip,pins =
+					<2 18 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			uart0_rts: uart0-rts {
+				rockchip,pins =
+					<2 19 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		uart1 {
+			uart1_xfer: uart1-xfer {
+				rockchip,pins =
+					<3 12 RK_FUNC_2 &pcfg_pull_up>,
+					<3 13 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+
+		uart2a {
+			uart2a_xfer: uart2a-xfer {
+				rockchip,pins =
+					<4 8 RK_FUNC_2 &pcfg_pull_up>,
+					<4 9 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+
+		uart2b {
+			uart2b_xfer: uart2b-xfer {
+				rockchip,pins =
+					<4 16 RK_FUNC_2 &pcfg_pull_up>,
+					<4 17 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+
+		uart2c {
+			uart2c_xfer: uart2c-xfer {
+				rockchip,pins =
+					<4 19 RK_FUNC_1 &pcfg_pull_up>,
+					<4 20 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		uart3 {
+			uart3_xfer: uart3-xfer {
+				rockchip,pins =
+					<3 14 RK_FUNC_2 &pcfg_pull_up>,
+					<3 15 RK_FUNC_2 &pcfg_pull_none>;
+			};
+
+			uart3_cts: uart3-cts {
+				rockchip,pins =
+					<3 18 RK_FUNC_2 &pcfg_pull_none>;
+			};
+
+			uart3_rts: uart3-rts {
+				rockchip,pins =
+					<3 19 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+
+		uart4 {
+			uart4_xfer: uart4-xfer {
+				rockchip,pins =
+					<1 7 RK_FUNC_1 &pcfg_pull_up>,
+					<1 8 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		uarthdcp {
+			uarthdcp_xfer: uarthdcp-xfer {
+				rockchip,pins =
+					<4 21 RK_FUNC_2 &pcfg_pull_up>,
+					<4 22 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+
+		pwm0 {
+			pwm0_pin: pwm0-pin {
+				rockchip,pins =
+					<4 18 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			vop0_pwm_pin: vop0-pwm-pin {
+				rockchip,pins =
+					<4 18 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+
+		pwm1 {
+			pwm1_pin: pwm1-pin {
+				rockchip,pins =
+					<4 22 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			vop1_pwm_pin: vop1-pwm-pin {
+				rockchip,pins =
+					<4 18 RK_FUNC_3 &pcfg_pull_none>;
+			};
+		};
+
+		pwm2 {
+			pwm2_pin: pwm2-pin {
+				rockchip,pins =
+					<1 19 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		pwm3a {
+			pwm3a_pin: pwm3a-pin {
+				rockchip,pins =
+					<0 6 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		pwm3b {
+			pwm3b_pin: pwm3b-pin {
+				rockchip,pins =
+					<1 14 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/rockchip/rk3399-evb.dts linux-libre-4.7-gnu/arch/arm64/boot/dts/rockchip/rk3399-evb.dts
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/rockchip/rk3399-evb.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/rockchip/rk3399-evb.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2016 Fuzhou Rockchip Electronics Co., Ltd
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include <dt-bindings/pwm/pwm.h>
+#include "rk3399.dtsi"
+
+/ {
+	model = "Rockchip RK3399 Evaluation Board";
+	compatible = "rockchip,rk3399-evb", "rockchip,rk3399",
+		     "google,rk3399evb-rev2";
+
+	vdd_center: vdd-center {
+		compatible = "pwm-regulator";
+		pwms = <&pwm3 0 25000 0>;
+		regulator-name = "vdd_center";
+		regulator-min-microvolt = <800000>;
+		regulator-max-microvolt = <1400000>;
+		regulator-always-on;
+		regulator-boot-on;
+		status = "okay";
+	};
+
+	vcc3v3_sys: vcc3v3-sys {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc3v3_sys";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	vcc_phy: vcc-phy-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_phy";
+		regulator-always-on;
+		regulator-boot-on;
+	};
+};
+
+&pwm0 {
+	status = "okay";
+};
+
+&pwm2 {
+	status = "okay";
+};
+
+&pwm3 {
+	status = "okay";
+};
+
+&uart2 {
+	status = "okay";
+};
+
+&usb_host0_ehci {
+	status = "okay";
+};
+
+&usb_host0_ohci {
+	status = "okay";
+};
+
+&usb_host1_ehci {
+	status = "okay";
+};
+
+&usb_host1_ohci {
+	status = "okay";
+};
+
+&pinctrl {
+	pmic {
+		pmic_int_l: pmic-int-l {
+			rockchip,pins =
+				<1 21 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+
+		pmic_dvs2: pmic-dvs2 {
+			rockchip,pins =
+				<1 18 RK_FUNC_GPIO &pcfg_pull_down>;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/socionext/uniphier-ph1-ld20.dtsi linux-libre-4.7-gnu/arch/arm64/boot/dts/socionext/uniphier-ph1-ld20.dtsi
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/socionext/uniphier-ph1-ld20.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/socionext/uniphier-ph1-ld20.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -106,6 +106,12 @@
 	};
 
 	clocks {
+		refclk: ref {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <25000000>;
+		};
+
 		uart_clk: uart_clk {
 			#clock-cells = <0>;
 			compatible = "fixed-clock";
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/boot/dts/socionext/uniphier-ph1-ld20-ref.dts linux-libre-4.7-gnu/arch/arm64/boot/dts/socionext/uniphier-ph1-ld20-ref.dts
--- linux-libre-4.6-gnu/arch/arm64/boot/dts/socionext/uniphier-ph1-ld20-ref.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/boot/dts/socionext/uniphier-ph1-ld20-ref.dts	2016-07-24 15:23:50.000000000 -0400
@@ -44,6 +44,7 @@
 
 /dts-v1/;
 /include/ "uniphier-ph1-ld20.dtsi"
+/include/ "uniphier-ref-daughter.dtsi"
 /include/ "uniphier-support-card.dtsi"
 
 / {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/configs/defconfig linux-libre-4.7-gnu/arch/arm64/configs/defconfig
--- linux-libre-4.6-gnu/arch/arm64/configs/defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/configs/defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -1,7 +1,6 @@
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
-CONFIG_FHANDLE=y
 CONFIG_AUDIT=y
 CONFIG_NO_HZ_IDLE=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -36,8 +35,10 @@ CONFIG_ARCH_BCM_IPROC=y
 CONFIG_ARCH_BERLIN=y
 CONFIG_ARCH_EXYNOS=y
 CONFIG_ARCH_LAYERSCAPE=y
+CONFIG_ARCH_LG1K=y
 CONFIG_ARCH_HISI=y
 CONFIG_ARCH_MEDIATEK=y
+CONFIG_ARCH_MESON=y
 CONFIG_ARCH_MVEBU=y
 CONFIG_ARCH_QCOM=y
 CONFIG_ARCH_ROCKCHIP=y
@@ -56,12 +57,13 @@ CONFIG_ARCH_ZYNQMP=y
 CONFIG_PCI=y
 CONFIG_PCI_MSI=y
 CONFIG_PCI_IOV=y
-CONFIG_PCI_RCAR_GEN2_PCIE=y
+CONFIG_PCIE_RCAR=y
 CONFIG_PCI_HOST_GENERIC=y
 CONFIG_PCI_XGENE=y
 CONFIG_PCI_LAYERSCAPE=y
 CONFIG_PCI_HISI=y
 CONFIG_PCIE_QCOM=y
+CONFIG_ARM64_VA_BITS_48=y
 CONFIG_SCHED_MC=y
 CONFIG_PREEMPT=y
 CONFIG_KSM=y
@@ -84,13 +86,19 @@ CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
 # CONFIG_IPV6 is not set
 CONFIG_BPF_JIT=y
-# CONFIG_WIRELESS is not set
+CONFIG_CFG80211=m
+CONFIG_MAC80211=m
+CONFIG_MAC80211_LEDS=y
+CONFIG_RFKILL=m
 CONFIG_NET_9P=y
 CONFIG_NET_9P_VIRTIO=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_DMA_CMA=y
+CONFIG_MTD=y
+CONFIG_MTD_M25P80=y
+CONFIG_MTD_SPI_NOR=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_VIRTIO_BLK=y
 # CONFIG_SCSI_PROC_FS is not set
@@ -102,7 +110,9 @@ CONFIG_SATA_AHCI_PLATFORM=y
 CONFIG_AHCI_CEVA=y
 CONFIG_AHCI_MVEBU=y
 CONFIG_AHCI_XGENE=y
+CONFIG_AHCI_QORIQ=y
 CONFIG_SATA_RCAR=y
+CONFIG_SATA_SIL24=y
 CONFIG_PATA_PLATFORM=y
 CONFIG_PATA_OF_PLATFORM=y
 CONFIG_NETDEVICES=y
@@ -118,7 +128,18 @@ CONFIG_RAVB=y
 CONFIG_SMC91X=y
 CONFIG_SMSC911X=y
 CONFIG_MICREL_PHY=y
-# CONFIG_WLAN is not set
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_RTL8152=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_DM9601=m
+CONFIG_USB_NET_SR9800=m
+CONFIG_USB_NET_SMSC75XX=m
+CONFIG_USB_NET_SMSC95XX=m
+CONFIG_USB_NET_PLUSB=m
+CONFIG_USB_NET_MCS7830=m
+CONFIG_WL18XX=m
+CONFIG_WLCORE_SDIO=m
 CONFIG_INPUT_EVDEV=y
 CONFIG_KEYBOARD_GPIO=y
 # CONFIG_SERIO_SERPORT is not set
@@ -138,6 +159,8 @@ CONFIG_SERIAL_TEGRA=y
 CONFIG_SERIAL_SH_SCI=y
 CONFIG_SERIAL_SH_SCI_NR_UARTS=11
 CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_MESON=y
+CONFIG_SERIAL_MESON_CONSOLE=y
 CONFIG_SERIAL_MSM=y
 CONFIG_SERIAL_MSM_CONSOLE=y
 CONFIG_SERIAL_XILINX_PS_UART=y
@@ -146,15 +169,20 @@ CONFIG_SERIAL_MVEBU_UART=y
 CONFIG_VIRTIO_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MUX=y
+CONFIG_I2C_MUX_PCA954x=y
 CONFIG_I2C_DESIGNWARE_PLATFORM=y
+CONFIG_I2C_IMX=y
 CONFIG_I2C_MV64XXX=y
 CONFIG_I2C_QUP=y
 CONFIG_I2C_TEGRA=y
 CONFIG_I2C_UNIPHIER_F=y
 CONFIG_I2C_RCAR=y
 CONFIG_SPI=y
+CONFIG_SPI_ORION=y
 CONFIG_SPI_PL022=y
 CONFIG_SPI_QUP=y
+CONFIG_SPI_SPIDEV=m
 CONFIG_SPMI=y
 CONFIG_PINCTRL_SINGLE=y
 CONFIG_PINCTRL_MSM8916=y
@@ -167,14 +195,19 @@ CONFIG_GPIO_XGENE=y
 CONFIG_POWER_RESET_MSM=y
 CONFIG_POWER_RESET_XGENE=y
 CONFIG_POWER_RESET_SYSCON=y
-# CONFIG_HWMON is not set
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_INA2XX=m
 CONFIG_THERMAL=y
 CONFIG_THERMAL_EMULATION=y
 CONFIG_EXYNOS_THERMAL=y
+CONFIG_WATCHDOG=y
+CONFIG_RENESAS_WDT=y
 CONFIG_MFD_SPMI_PMIC=y
 CONFIG_MFD_SEC_CORE=y
+CONFIG_MFD_HI655X_PMIC=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_HI655X=y
 CONFIG_REGULATOR_QCOM_SMD_RPM=y
 CONFIG_REGULATOR_QCOM_SPMI=y
 CONFIG_REGULATOR_S2MPS11=y
@@ -192,7 +225,7 @@ CONFIG_SND_SOC_AK4613=y
 CONFIG_USB=y
 CONFIG_USB_OTG=y
 CONFIG_USB_XHCI_HCD=y
-CONFIG_USB_XHCI_PLATFORM=y
+CONFIG_USB_XHCI_RCAR=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_MSM=y
 CONFIG_USB_EHCI_HCD_PLATFORM=y
@@ -213,6 +246,7 @@ CONFIG_MMC_BLOCK_MINORS=32
 CONFIG_MMC_ARMMMCI=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_OF_ESDHC=y
 CONFIG_MMC_SDHCI_TEGRA=y
 CONFIG_MMC_SDHCI_MSM=y
 CONFIG_MMC_SPI=y
@@ -229,11 +263,13 @@ CONFIG_LEDS_TRIGGER_HEARTBEAT=y
 CONFIG_LEDS_TRIGGER_CPU=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_S5M=y
+CONFIG_RTC_DRV_DS3232=y
 CONFIG_RTC_DRV_EFI=y
 CONFIG_RTC_DRV_PL031=y
 CONFIG_RTC_DRV_SUN6I=y
 CONFIG_RTC_DRV_XGENE=y
 CONFIG_DMADEVICES=y
+CONFIG_PL330_DMA=y
 CONFIG_TEGRA20_APB_DMA=y
 CONFIG_QCOM_BAM_DMA=y
 CONFIG_RCAR_DMAC=y
@@ -246,6 +282,7 @@ CONFIG_XEN_GNTDEV=y
 CONFIG_XEN_GRANT_DEV_ALLOC=y
 CONFIG_COMMON_CLK_SCPI=y
 CONFIG_COMMON_CLK_CS2000_CP=y
+CONFIG_CLK_QORIQ=y
 CONFIG_COMMON_CLK_QCOM=y
 CONFIG_MSM_GCC_8916=y
 CONFIG_HWSPINLOCK_QCOM=y
@@ -264,6 +301,7 @@ CONFIG_PHY_RCAR_GEN3_USB2=y
 CONFIG_PHY_HI6220_USB=y
 CONFIG_PHY_XGENE=y
 CONFIG_ARM_SCPI_PROTOCOL=y
+CONFIG_ACPI=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 CONFIG_FANOTIFY=y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/include/asm/assembler.h linux-libre-4.7-gnu/arch/arm64/include/asm/assembler.h
--- linux-libre-4.6-gnu/arch/arm64/include/asm/assembler.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/include/asm/assembler.h	2016-07-24 15:23:50.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Based on arch/arm/include/asm/assembler.h
+ * Based on arch/arm/include/asm/assembler.h, arch/arm/mm/proc-macros.S
  *
  * Copyright (C) 1996-2000 Russell King
  * Copyright (C) 2012 ARM Ltd.
@@ -23,22 +23,13 @@
 #ifndef __ASM_ASSEMBLER_H
 #define __ASM_ASSEMBLER_H
 
+#include <asm/asm-offsets.h>
+#include <asm/page.h>
+#include <asm/pgtable-hwdef.h>
 #include <asm/ptrace.h>
 #include <asm/thread_info.h>
 
 /*
- * Stack pushing/popping (register pairs only). Equivalent to store decrement
- * before, load increment after.
- */
-	.macro	push, xreg1, xreg2
-	stp	\xreg1, \xreg2, [sp, #-16]!
-	.endm
-
-	.macro	pop, xreg1, xreg2
-	ldp	\xreg1, \xreg2, [sp], #16
-	.endm
-
-/*
  * Enable and disable interrupts.
  */
 	.macro	disable_irq
@@ -212,6 +203,102 @@ lr	.req	x30		// link register
 	.endm
 
 /*
+ * vma_vm_mm - get mm pointer from vma pointer (vma->vm_mm)
+ */
+	.macro	vma_vm_mm, rd, rn
+	ldr	\rd, [\rn, #VMA_VM_MM]
+	.endm
+
+/*
+ * mmid - get context id from mm pointer (mm->context.id)
+ */
+	.macro	mmid, rd, rn
+	ldr	\rd, [\rn, #MM_CONTEXT_ID]
+	.endm
+
+/*
+ * dcache_line_size - get the minimum D-cache line size from the CTR register.
+ */
+	.macro	dcache_line_size, reg, tmp
+	mrs	\tmp, ctr_el0			// read CTR
+	ubfm	\tmp, \tmp, #16, #19		// cache line size encoding
+	mov	\reg, #4			// bytes per word
+	lsl	\reg, \reg, \tmp		// actual cache line size
+	.endm
+
+/*
+ * icache_line_size - get the minimum I-cache line size from the CTR register.
+ */
+	.macro	icache_line_size, reg, tmp
+	mrs	\tmp, ctr_el0			// read CTR
+	and	\tmp, \tmp, #0xf		// cache line size encoding
+	mov	\reg, #4			// bytes per word
+	lsl	\reg, \reg, \tmp		// actual cache line size
+	.endm
+
+/*
+ * tcr_set_idmap_t0sz - update TCR.T0SZ so that we can load the ID map
+ */
+	.macro	tcr_set_idmap_t0sz, valreg, tmpreg
+#ifndef CONFIG_ARM64_VA_BITS_48
+	ldr_l	\tmpreg, idmap_t0sz
+	bfi	\valreg, \tmpreg, #TCR_T0SZ_OFFSET, #TCR_TxSZ_WIDTH
+#endif
+	.endm
+
+/*
+ * Macro to perform a data cache maintenance for the interval
+ * [kaddr, kaddr + size)
+ *
+ * 	op:		operation passed to dc instruction
+ * 	domain:		domain used in dsb instruciton
+ * 	kaddr:		starting virtual address of the region
+ * 	size:		size of the region
+ * 	Corrupts:	kaddr, size, tmp1, tmp2
+ */
+	.macro dcache_by_line_op op, domain, kaddr, size, tmp1, tmp2
+	dcache_line_size \tmp1, \tmp2
+	add	\size, \kaddr, \size
+	sub	\tmp2, \tmp1, #1
+	bic	\kaddr, \kaddr, \tmp2
+9998:	dc	\op, \kaddr
+	add	\kaddr, \kaddr, \tmp1
+	cmp	\kaddr, \size
+	b.lo	9998b
+	dsb	\domain
+	.endm
+
+/*
+ * reset_pmuserenr_el0 - reset PMUSERENR_EL0 if PMUv3 present
+ */
+	.macro	reset_pmuserenr_el0, tmpreg
+	mrs	\tmpreg, id_aa64dfr0_el1	// Check ID_AA64DFR0_EL1 PMUVer
+	sbfx	\tmpreg, \tmpreg, #8, #4
+	cmp	\tmpreg, #1			// Skip if no PMU present
+	b.lt	9000f
+	msr	pmuserenr_el0, xzr		// Disable PMU access from EL0
+9000:
+	.endm
+
+/*
+ * copy_page - copy src to dest using temp registers t1-t8
+ */
+	.macro copy_page dest:req src:req t1:req t2:req t3:req t4:req t5:req t6:req t7:req t8:req
+9998:	ldp	\t1, \t2, [\src]
+	ldp	\t3, \t4, [\src, #16]
+	ldp	\t5, \t6, [\src, #32]
+	ldp	\t7, \t8, [\src, #48]
+	add	\src, \src, #64
+	stnp	\t1, \t2, [\dest]
+	stnp	\t3, \t4, [\dest, #16]
+	stnp	\t5, \t6, [\dest, #32]
+	stnp	\t7, \t8, [\dest, #48]
+	add	\dest, \dest, #64
+	tst	\src, #(PAGE_SIZE - 1)
+	b.ne	9998b
+	.endm
+
+/*
  * Annotate a function as position independent, i.e., safe to be called before
  * the kernel virtual mapping is activated.
  */
@@ -233,4 +320,24 @@ lr	.req	x30		// link register
 	.long	\sym\()_hi32
 	.endm
 
+	/*
+	 * mov_q - move an immediate constant into a 64-bit register using
+	 *         between 2 and 4 movz/movk instructions (depending on the
+	 *         magnitude and sign of the operand)
+	 */
+	.macro	mov_q, reg, val
+	.if (((\val) >> 31) == 0 || ((\val) >> 31) == 0x1ffffffff)
+	movz	\reg, :abs_g1_s:\val
+	.else
+	.if (((\val) >> 47) == 0 || ((\val) >> 47) == 0x1ffff)
+	movz	\reg, :abs_g2_s:\val
+	.else
+	movz	\reg, :abs_g3:\val
+	movk	\reg, :abs_g2_nc:\val
+	.endif
+	movk	\reg, :abs_g1_nc:\val
+	.endif
+	movk	\reg, :abs_g0_nc:\val
+	.endm
+
 #endif	/* __ASM_ASSEMBLER_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/include/asm/cpufeature.h linux-libre-4.7-gnu/arch/arm64/include/asm/cpufeature.h
--- linux-libre-4.6-gnu/arch/arm64/include/asm/cpufeature.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/include/asm/cpufeature.h	2016-07-24 15:23:50.000000000 -0400
@@ -35,8 +35,9 @@
 #define ARM64_ALT_PAN_NOT_UAO			10
 #define ARM64_HAS_VIRT_HOST_EXTN		11
 #define ARM64_WORKAROUND_CAVIUM_27456		12
+#define ARM64_HAS_32BIT_EL0			13
 
-#define ARM64_NCAPS				13
+#define ARM64_NCAPS				14
 
 #ifndef __ASSEMBLY__
 
@@ -77,10 +78,17 @@ struct arm64_ftr_reg {
 	struct arm64_ftr_bits	*ftr_bits;
 };
 
+/* scope of capability check */
+enum {
+	SCOPE_SYSTEM,
+	SCOPE_LOCAL_CPU,
+};
+
 struct arm64_cpu_capabilities {
 	const char *desc;
 	u16 capability;
-	bool (*matches)(const struct arm64_cpu_capabilities *);
+	int def_scope;			/* default scope */
+	bool (*matches)(const struct arm64_cpu_capabilities *caps, int scope);
 	void (*enable)(void *);		/* Called on all active CPUs */
 	union {
 		struct {	/* To be used for erratum handling only */
@@ -101,6 +109,8 @@ struct arm64_cpu_capabilities {
 
 extern DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
 
+bool this_cpu_has_cap(unsigned int cap);
+
 static inline bool cpu_have_feature(unsigned int num)
 {
 	return elf_hwcap & (1UL << num);
@@ -170,12 +180,20 @@ static inline bool id_aa64mmfr0_mixed_en
 		cpuid_feature_extract_unsigned_field(mmfr0, ID_AA64MMFR0_BIGENDEL0_SHIFT) == 0x1;
 }
 
+static inline bool id_aa64pfr0_32bit_el0(u64 pfr0)
+{
+	u32 val = cpuid_feature_extract_unsigned_field(pfr0, ID_AA64PFR0_EL0_SHIFT);
+
+	return val == ID_AA64PFR0_EL0_32BIT_64BIT;
+}
+
 void __init setup_cpu_features(void);
 
 void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
 			    const char *info);
 void check_local_cpu_errata(void);
 
+void verify_local_cpu_errata(void);
 void verify_local_cpu_capabilities(void);
 
 u64 read_system_reg(u32 id);
@@ -185,6 +203,11 @@ static inline bool cpu_supports_mixed_en
 	return id_aa64mmfr0_mixed_endian_el0(read_cpuid(ID_AA64MMFR0_EL1));
 }
 
+static inline bool system_supports_32bit_el0(void)
+{
+	return cpus_have_cap(ARM64_HAS_32BIT_EL0);
+}
+
 static inline bool system_supports_mixed_endian_el0(void)
 {
 	return id_aa64mmfr0_mixed_endian_el0(read_system_reg(SYS_ID_AA64MMFR0_EL1));
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/include/asm/cputype.h linux-libre-4.7-gnu/arch/arm64/include/asm/cputype.h
--- linux-libre-4.6-gnu/arch/arm64/include/asm/cputype.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/include/asm/cputype.h	2016-07-24 15:23:50.000000000 -0400
@@ -80,12 +80,14 @@
 #define APM_CPU_PART_POTENZA		0x000
 
 #define CAVIUM_CPU_PART_THUNDERX	0x0A1
+#define CAVIUM_CPU_PART_THUNDERX_81XX	0x0A2
 
 #define BRCM_CPU_PART_VULCAN		0x516
 
 #define MIDR_CORTEX_A53 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A53)
 #define MIDR_CORTEX_A57 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A57)
 #define MIDR_THUNDERX	MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX)
+#define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX)
 
 #ifndef __ASSEMBLY__
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/include/asm/dma-mapping.h linux-libre-4.7-gnu/arch/arm64/include/asm/dma-mapping.h
--- linux-libre-4.6-gnu/arch/arm64/include/asm/dma-mapping.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/include/asm/dma-mapping.h	2016-07-24 15:23:50.000000000 -0400
@@ -48,7 +48,7 @@ static inline struct dma_map_ops *get_dm
 }
 
 void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
-			struct iommu_ops *iommu, bool coherent);
+			const struct iommu_ops *iommu, bool coherent);
 #define arch_setup_dma_ops	arch_setup_dma_ops
 
 #ifdef CONFIG_IOMMU_DMA
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/include/asm/efi.h linux-libre-4.7-gnu/arch/arm64/include/asm/efi.h
--- linux-libre-4.6-gnu/arch/arm64/include/asm/efi.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/include/asm/efi.h	2016-07-24 15:23:50.000000000 -0400
@@ -4,6 +4,7 @@
 #include <asm/io.h>
 #include <asm/mmu_context.h>
 #include <asm/neon.h>
+#include <asm/ptrace.h>
 #include <asm/tlbflush.h>
 
 #ifdef CONFIG_EFI
@@ -14,32 +15,29 @@ extern void efi_init(void);
 
 int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md);
 
-#define efi_call_virt(f, ...)						\
+#define efi_set_mapping_permissions	efi_create_mapping
+
+#define arch_efi_call_virt_setup()					\
 ({									\
-	efi_##f##_t *__f;						\
-	efi_status_t __s;						\
-									\
 	kernel_neon_begin();						\
 	efi_virtmap_load();						\
-	__f = efi.systab->runtime->f;					\
-	__s = __f(__VA_ARGS__);						\
-	efi_virtmap_unload();						\
-	kernel_neon_end();						\
-	__s;								\
 })
 
-#define __efi_call_virt(f, ...)						\
+#define arch_efi_call_virt(f, args...)					\
 ({									\
 	efi_##f##_t *__f;						\
-									\
-	kernel_neon_begin();						\
-	efi_virtmap_load();						\
 	__f = efi.systab->runtime->f;					\
-	__f(__VA_ARGS__);						\
+	__f(args);							\
+})
+
+#define arch_efi_call_virt_teardown()					\
+({									\
 	efi_virtmap_unload();						\
 	kernel_neon_end();						\
 })
 
+#define ARCH_EFI_IRQ_FLAGS_MASK (PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT)
+
 /* arch specific definitions used by the stub code */
 
 /*
@@ -50,7 +48,16 @@ int efi_create_mapping(struct mm_struct
 #define EFI_FDT_ALIGN	SZ_2M   /* used by allocate_new_fdt_and_exit_boot() */
 #define MAX_FDT_OFFSET	SZ_512M
 
-#define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__)
+#define efi_call_early(f, ...)		sys_table_arg->boottime->f(__VA_ARGS__)
+#define __efi_call_early(f, ...)	f(__VA_ARGS__)
+#define efi_is_64bit()			(true)
+
+#define alloc_screen_info(x...)		&screen_info
+#define free_screen_info(x...)
+
+static inline void efifb_setup_from_dmi(struct screen_info *si, const char *opt)
+{
+}
 
 #define EFI_ALLOC_ALIGN		SZ_64K
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/include/asm/elf.h linux-libre-4.7-gnu/arch/arm64/include/asm/elf.h
--- linux-libre-4.6-gnu/arch/arm64/include/asm/elf.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/include/asm/elf.h	2016-07-24 15:23:50.000000000 -0400
@@ -160,14 +160,14 @@ extern int arch_setup_additional_pages(s
 #define STACK_RND_MASK			(0x3ffff >> (PAGE_SHIFT - 12))
 #endif
 
-#ifdef CONFIG_COMPAT
-
 #ifdef __AARCH64EB__
 #define COMPAT_ELF_PLATFORM		("v8b")
 #else
 #define COMPAT_ELF_PLATFORM		("v8l")
 #endif
 
+#ifdef CONFIG_COMPAT
+
 #define COMPAT_ELF_ET_DYN_BASE		(2 * TASK_SIZE_32 / 3)
 
 /* AArch32 registers. */
@@ -177,7 +177,8 @@ typedef compat_elf_greg_t		compat_elf_gr
 
 /* AArch32 EABI. */
 #define EF_ARM_EABI_MASK		0xff000000
-#define compat_elf_check_arch(x)	(((x)->e_machine == EM_ARM) && \
+#define compat_elf_check_arch(x)	(system_supports_32bit_el0() && \
+					 ((x)->e_machine == EM_ARM) && \
 					 ((x)->e_flags & EF_ARM_EABI_MASK))
 
 #define compat_start_thread		compat_start_thread
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/include/asm/kernel-pgtable.h linux-libre-4.7-gnu/arch/arm64/include/asm/kernel-pgtable.h
--- linux-libre-4.6-gnu/arch/arm64/include/asm/kernel-pgtable.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/include/asm/kernel-pgtable.h	2016-07-24 15:23:50.000000000 -0400
@@ -19,6 +19,7 @@
 #ifndef __ASM_KERNEL_PGTABLE_H
 #define __ASM_KERNEL_PGTABLE_H
 
+#include <asm/sparsemem.h>
 
 /*
  * The linear mapping and the start of memory are both 2M aligned (per
@@ -86,10 +87,24 @@
  * (64k granule), or a multiple that can be mapped using contiguous bits
  * in the page tables: 32 * PMD_SIZE (16k granule)
  */
-#ifdef CONFIG_ARM64_64K_PAGES
-#define ARM64_MEMSTART_ALIGN	SZ_512M
+#if defined(CONFIG_ARM64_4K_PAGES)
+#define ARM64_MEMSTART_SHIFT		PUD_SHIFT
+#elif defined(CONFIG_ARM64_16K_PAGES)
+#define ARM64_MEMSTART_SHIFT		(PMD_SHIFT + 5)
 #else
-#define ARM64_MEMSTART_ALIGN	SZ_1G
+#define ARM64_MEMSTART_SHIFT		PMD_SHIFT
+#endif
+
+/*
+ * sparsemem vmemmap imposes an additional requirement on the alignment of
+ * memstart_addr, due to the fact that the base of the vmemmap region
+ * has a direct correspondence, and needs to appear sufficiently aligned
+ * in the virtual address space.
+ */
+#if defined(CONFIG_SPARSEMEM_VMEMMAP) && ARM64_MEMSTART_SHIFT < SECTION_SIZE_BITS
+#define ARM64_MEMSTART_ALIGN	(1UL << SECTION_SIZE_BITS)
+#else
+#define ARM64_MEMSTART_ALIGN	(1UL << ARM64_MEMSTART_SHIFT)
 #endif
 
 #endif	/* __ASM_KERNEL_PGTABLE_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/include/asm/kgdb.h linux-libre-4.7-gnu/arch/arm64/include/asm/kgdb.h
--- linux-libre-4.6-gnu/arch/arm64/include/asm/kgdb.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/include/asm/kgdb.h	2016-07-24 15:23:50.000000000 -0400
@@ -38,25 +38,54 @@ extern int kgdb_fault_expected;
 #endif /* !__ASSEMBLY__ */
 
 /*
- * gdb is expecting the following registers layout.
+ * gdb remote procotol (well most versions of it) expects the following
+ * register layout.
  *
  * General purpose regs:
  *     r0-r30: 64 bit
  *     sp,pc : 64 bit
- *     pstate  : 64 bit
- *     Total: 34
+ *     pstate  : 32 bit
+ *     Total: 33 + 1
  * FPU regs:
  *     f0-f31: 128 bit
- *     Total: 32
- * Extra regs
  *     fpsr & fpcr: 32 bit
- *     Total: 2
+ *     Total: 32 + 2
  *
+ * To expand a little on the "most versions of it"... when the gdb remote
+ * protocol for AArch64 was developed it depended on a statement in the
+ * Architecture Reference Manual that claimed "SPSR_ELx is a 32-bit register".
+ * and, as a result, allocated only 32-bits for the PSTATE in the remote
+ * protocol. In fact this statement is still present in ARM DDI 0487A.i.
+ *
+ * Unfortunately "is a 32-bit register" has a very special meaning for
+ * system registers. It means that "the upper bits, bits[63:32], are
+ * RES0.". RES0 is heavily used in the ARM architecture documents as a
+ * way to leave space for future architecture changes. So to translate a
+ * little for people who don't spend their spare time reading ARM architecture
+ * manuals, what "is a 32-bit register" actually means in this context is
+ * "is a 64-bit register but one with no meaning allocated to any of the
+ * upper 32-bits... *yet*".
+ *
+ * Perhaps then we should not be surprised that this has led to some
+ * confusion. Specifically a patch, influenced by the above translation,
+ * that extended PSTATE to 64-bit was accepted into gdb-7.7 but the patch
+ * was reverted in gdb-7.8.1 and all later releases, when this was
+ * discovered to be an undocumented protocol change.
+ *
+ * So... it is *not* wrong for us to only allocate 32-bits to PSTATE
+ * here even though the kernel itself allocates 64-bits for the same
+ * state. That is because this bit of code tells the kernel how the gdb
+ * remote protocol (well most versions of it) describes the register state.
+ *
+ * Note that if you are using one of the versions of gdb that supports
+ * the gdb-7.7 version of the protocol you cannot use kgdb directly
+ * without providing a custom register description (gdb can load new
+ * protocol descriptions at runtime).
  */
 
-#define _GP_REGS		34
+#define _GP_REGS		33
 #define _FP_REGS		32
-#define _EXTRA_REGS		2
+#define _EXTRA_REGS		3
 /*
  * general purpose registers size in bytes.
  * pstate is only 4 bytes. subtract 4 bytes
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/include/asm/kvm_arm.h linux-libre-4.7-gnu/arch/arm64/include/asm/kvm_arm.h
--- linux-libre-4.6-gnu/arch/arm64/include/asm/kvm_arm.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/include/asm/kvm_arm.h	2016-07-24 15:23:50.000000000 -0400
@@ -84,44 +84,38 @@
 #define HCR_INT_OVERRIDE   (HCR_FMO | HCR_IMO)
 #define HCR_HOST_VHE_FLAGS (HCR_RW | HCR_TGE | HCR_E2H)
 
-/* Hyp System Control Register (SCTLR_EL2) bits */
-#define SCTLR_EL2_EE	(1 << 25)
-#define SCTLR_EL2_WXN	(1 << 19)
-#define SCTLR_EL2_I	(1 << 12)
-#define SCTLR_EL2_SA	(1 << 3)
-#define SCTLR_EL2_C	(1 << 2)
-#define SCTLR_EL2_A	(1 << 1)
-#define SCTLR_EL2_M	1
-#define SCTLR_EL2_FLAGS	(SCTLR_EL2_M | SCTLR_EL2_A | SCTLR_EL2_C |	\
-			 SCTLR_EL2_SA | SCTLR_EL2_I)
-
 /* TCR_EL2 Registers bits */
-#define TCR_EL2_RES1	((1 << 31) | (1 << 23))
-#define TCR_EL2_TBI	(1 << 20)
-#define TCR_EL2_PS	(7 << 16)
-#define TCR_EL2_PS_40B	(2 << 16)
-#define TCR_EL2_TG0	(1 << 14)
-#define TCR_EL2_SH0	(3 << 12)
-#define TCR_EL2_ORGN0	(3 << 10)
-#define TCR_EL2_IRGN0	(3 << 8)
-#define TCR_EL2_T0SZ	0x3f
-#define TCR_EL2_MASK	(TCR_EL2_TG0 | TCR_EL2_SH0 | \
-			 TCR_EL2_ORGN0 | TCR_EL2_IRGN0 | TCR_EL2_T0SZ)
+#define TCR_EL2_RES1		((1 << 31) | (1 << 23))
+#define TCR_EL2_TBI		(1 << 20)
+#define TCR_EL2_PS_SHIFT	16
+#define TCR_EL2_PS_MASK		(7 << TCR_EL2_PS_SHIFT)
+#define TCR_EL2_PS_40B		(2 << TCR_EL2_PS_SHIFT)
+#define TCR_EL2_TG0_MASK	TCR_TG0_MASK
+#define TCR_EL2_SH0_MASK	TCR_SH0_MASK
+#define TCR_EL2_ORGN0_MASK	TCR_ORGN0_MASK
+#define TCR_EL2_IRGN0_MASK	TCR_IRGN0_MASK
+#define TCR_EL2_T0SZ_MASK	0x3f
+#define TCR_EL2_MASK	(TCR_EL2_TG0_MASK | TCR_EL2_SH0_MASK | \
+			 TCR_EL2_ORGN0_MASK | TCR_EL2_IRGN0_MASK | TCR_EL2_T0SZ_MASK)
 
 /* VTCR_EL2 Registers bits */
 #define VTCR_EL2_RES1		(1 << 31)
-#define VTCR_EL2_PS_MASK	(7 << 16)
-#define VTCR_EL2_TG0_MASK	(1 << 14)
-#define VTCR_EL2_TG0_4K		(0 << 14)
-#define VTCR_EL2_TG0_64K	(1 << 14)
-#define VTCR_EL2_SH0_MASK	(3 << 12)
-#define VTCR_EL2_SH0_INNER	(3 << 12)
-#define VTCR_EL2_ORGN0_MASK	(3 << 10)
-#define VTCR_EL2_ORGN0_WBWA	(1 << 10)
-#define VTCR_EL2_IRGN0_MASK	(3 << 8)
-#define VTCR_EL2_IRGN0_WBWA	(1 << 8)
-#define VTCR_EL2_SL0_MASK	(3 << 6)
-#define VTCR_EL2_SL0_LVL1	(1 << 6)
+#define VTCR_EL2_HD		(1 << 22)
+#define VTCR_EL2_HA		(1 << 21)
+#define VTCR_EL2_PS_MASK	TCR_EL2_PS_MASK
+#define VTCR_EL2_TG0_MASK	TCR_TG0_MASK
+#define VTCR_EL2_TG0_4K		TCR_TG0_4K
+#define VTCR_EL2_TG0_16K	TCR_TG0_16K
+#define VTCR_EL2_TG0_64K	TCR_TG0_64K
+#define VTCR_EL2_SH0_MASK	TCR_SH0_MASK
+#define VTCR_EL2_SH0_INNER	TCR_SH0_INNER
+#define VTCR_EL2_ORGN0_MASK	TCR_ORGN0_MASK
+#define VTCR_EL2_ORGN0_WBWA	TCR_ORGN0_WBWA
+#define VTCR_EL2_IRGN0_MASK	TCR_IRGN0_MASK
+#define VTCR_EL2_IRGN0_WBWA	TCR_IRGN0_WBWA
+#define VTCR_EL2_SL0_SHIFT	6
+#define VTCR_EL2_SL0_MASK	(3 << VTCR_EL2_SL0_SHIFT)
+#define VTCR_EL2_SL0_LVL1	(1 << VTCR_EL2_SL0_SHIFT)
 #define VTCR_EL2_T0SZ_MASK	0x3f
 #define VTCR_EL2_T0SZ_40B	24
 #define VTCR_EL2_VS_SHIFT	19
@@ -137,35 +131,45 @@
  * (see hyp-init.S).
  *
  * Note that when using 4K pages, we concatenate two first level page tables
- * together.
+ * together. With 16K pages, we concatenate 16 first level page tables.
  *
  * The magic numbers used for VTTBR_X in this patch can be found in Tables
  * D4-23 and D4-25 in ARM DDI 0487A.b.
  */
+
+#define VTCR_EL2_T0SZ_IPA	VTCR_EL2_T0SZ_40B
+#define VTCR_EL2_COMMON_BITS	(VTCR_EL2_SH0_INNER | VTCR_EL2_ORGN0_WBWA | \
+				 VTCR_EL2_IRGN0_WBWA | VTCR_EL2_RES1)
+
 #ifdef CONFIG_ARM64_64K_PAGES
 /*
  * Stage2 translation configuration:
- * 40bits input  (T0SZ = 24)
  * 64kB pages (TG0 = 1)
  * 2 level page tables (SL = 1)
  */
-#define VTCR_EL2_FLAGS		(VTCR_EL2_TG0_64K | VTCR_EL2_SH0_INNER | \
-				 VTCR_EL2_ORGN0_WBWA | VTCR_EL2_IRGN0_WBWA | \
-				 VTCR_EL2_SL0_LVL1 | VTCR_EL2_RES1)
-#define VTTBR_X		(38 - VTCR_EL2_T0SZ_40B)
-#else
+#define VTCR_EL2_TGRAN_FLAGS		(VTCR_EL2_TG0_64K | VTCR_EL2_SL0_LVL1)
+#define VTTBR_X_TGRAN_MAGIC		38
+#elif defined(CONFIG_ARM64_16K_PAGES)
+/*
+ * Stage2 translation configuration:
+ * 16kB pages (TG0 = 2)
+ * 2 level page tables (SL = 1)
+ */
+#define VTCR_EL2_TGRAN_FLAGS		(VTCR_EL2_TG0_16K | VTCR_EL2_SL0_LVL1)
+#define VTTBR_X_TGRAN_MAGIC		42
+#else	/* 4K */
 /*
  * Stage2 translation configuration:
- * 40bits input  (T0SZ = 24)
  * 4kB pages (TG0 = 0)
  * 3 level page tables (SL = 1)
  */
-#define VTCR_EL2_FLAGS		(VTCR_EL2_TG0_4K | VTCR_EL2_SH0_INNER | \
-				 VTCR_EL2_ORGN0_WBWA | VTCR_EL2_IRGN0_WBWA | \
-				 VTCR_EL2_SL0_LVL1 | VTCR_EL2_RES1)
-#define VTTBR_X		(37 - VTCR_EL2_T0SZ_40B)
+#define VTCR_EL2_TGRAN_FLAGS		(VTCR_EL2_TG0_4K | VTCR_EL2_SL0_LVL1)
+#define VTTBR_X_TGRAN_MAGIC		37
 #endif
 
+#define VTCR_EL2_FLAGS			(VTCR_EL2_COMMON_BITS | VTCR_EL2_TGRAN_FLAGS)
+#define VTTBR_X				(VTTBR_X_TGRAN_MAGIC - VTCR_EL2_T0SZ_IPA)
+
 #define VTTBR_BADDR_SHIFT (VTTBR_X - 1)
 #define VTTBR_BADDR_MASK  (((UL(1) << (PHYS_MASK_SHIFT - VTTBR_X)) - 1) << VTTBR_BADDR_SHIFT)
 #define VTTBR_VMID_SHIFT  (UL(48))
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/include/asm/kvm_asm.h linux-libre-4.7-gnu/arch/arm64/include/asm/kvm_asm.h
--- linux-libre-4.6-gnu/arch/arm64/include/asm/kvm_asm.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/include/asm/kvm_asm.h	2016-07-24 15:23:50.000000000 -0400
@@ -22,6 +22,8 @@
 
 #define ARM_EXCEPTION_IRQ	  0
 #define ARM_EXCEPTION_TRAP	  1
+/* The hyp-stub will return this for any kvm_call_hyp() call */
+#define ARM_EXCEPTION_HYP_GONE	  2
 
 #define KVM_ARM64_DEBUG_DIRTY_SHIFT	0
 #define KVM_ARM64_DEBUG_DIRTY		(1 << KVM_ARM64_DEBUG_DIRTY_SHIFT)
@@ -40,6 +42,7 @@ struct kvm_vcpu;
 
 extern char __kvm_hyp_init[];
 extern char __kvm_hyp_init_end[];
+extern char __kvm_hyp_reset[];
 
 extern char __kvm_hyp_vector[];
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/include/asm/kvm_host.h linux-libre-4.7-gnu/arch/arm64/include/asm/kvm_host.h
--- linux-libre-4.6-gnu/arch/arm64/include/asm/kvm_host.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/include/asm/kvm_host.h	2016-07-24 15:23:50.000000000 -0400
@@ -43,9 +43,13 @@
 
 #define KVM_VCPU_MAX_FEATURES 4
 
+#define KVM_REQ_VCPU_EXIT	8
+
 int __attribute_const__ kvm_target_cpu(void);
 int kvm_reset_vcpu(struct kvm_vcpu *vcpu);
 int kvm_arch_dev_ioctl_check_extension(long ext);
+unsigned long kvm_hyp_reset_entry(void);
+void __extended_idmap_trampoline(phys_addr_t boot_pgd, phys_addr_t idmap_start);
 
 struct kvm_arch {
 	/* The VMID generation used for the virt. memory system */
@@ -293,6 +297,7 @@ struct kvm_vm_stat {
 struct kvm_vcpu_stat {
 	u32 halt_successful_poll;
 	u32 halt_attempted_poll;
+	u32 halt_poll_invalid;
 	u32 halt_wakeup;
 	u32 hvc_exit_stat;
 	u64 wfe_exit_stat;
@@ -324,6 +329,10 @@ static inline void kvm_arch_mmu_notifier
 
 struct kvm_vcpu *kvm_arm_get_running_vcpu(void);
 struct kvm_vcpu * __percpu *kvm_get_running_vcpus(void);
+void kvm_arm_halt_guest(struct kvm *kvm);
+void kvm_arm_resume_guest(struct kvm *kvm);
+void kvm_arm_halt_vcpu(struct kvm_vcpu *vcpu);
+void kvm_arm_resume_vcpu(struct kvm_vcpu *vcpu);
 
 u64 __kvm_call_hyp(void *hypfn, ...);
 #define kvm_call_hyp(f, ...) __kvm_call_hyp(kvm_ksym_ref(f), ##__VA_ARGS__)
@@ -352,11 +361,22 @@ static inline void __cpu_init_hyp_mode(p
 		       hyp_stack_ptr, vector_ptr);
 }
 
-static inline void kvm_arch_hardware_disable(void) {}
+static inline void __cpu_reset_hyp_mode(phys_addr_t boot_pgd_ptr,
+					phys_addr_t phys_idmap_start)
+{
+	/*
+	 * Call reset code, and switch back to stub hyp vectors.
+	 * Uses __kvm_call_hyp() to avoid kaslr's kvm_ksym_ref() translation.
+	 */
+	__kvm_call_hyp((void *)kvm_hyp_reset_entry(),
+		       boot_pgd_ptr, phys_idmap_start);
+}
+
 static inline void kvm_arch_hardware_unsetup(void) {}
 static inline void kvm_arch_sync_events(struct kvm *kvm) {}
 static inline void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu) {}
 static inline void kvm_arch_sched_in(struct kvm_vcpu *vcpu, int cpu) {}
+static inline void kvm_arch_vcpu_block_finish(struct kvm_vcpu *vcpu) {}
 
 void kvm_arm_init_debug(void);
 void kvm_arm_setup_debug(struct kvm_vcpu *vcpu);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/include/asm/kvm_mmio.h linux-libre-4.7-gnu/arch/arm64/include/asm/kvm_mmio.h
--- linux-libre-4.6-gnu/arch/arm64/include/asm/kvm_mmio.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/include/asm/kvm_mmio.h	2016-07-24 15:23:50.000000000 -0400
@@ -30,6 +30,9 @@ struct kvm_decode {
 	bool sign_extend;
 };
 
+void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data);
+unsigned long kvm_mmio_read_buf(const void *buf, unsigned int len);
+
 int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run);
 int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
 		 phys_addr_t fault_ipa);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/include/asm/kvm_mmu.h linux-libre-4.7-gnu/arch/arm64/include/asm/kvm_mmu.h
--- linux-libre-4.6-gnu/arch/arm64/include/asm/kvm_mmu.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/include/asm/kvm_mmu.h	2016-07-24 15:23:50.000000000 -0400
@@ -45,18 +45,6 @@
  */
 #define TRAMPOLINE_VA		(HYP_PAGE_OFFSET_MASK & PAGE_MASK)
 
-/*
- * KVM_MMU_CACHE_MIN_PAGES is the number of stage2 page table translation
- * levels in addition to the PGD and potentially the PUD which are
- * pre-allocated (we pre-allocate the fake PGD and the PUD when the Stage-2
- * tables use one level of tables less than the kernel.
- */
-#ifdef CONFIG_ARM64_64K_PAGES
-#define KVM_MMU_CACHE_MIN_PAGES	1
-#else
-#define KVM_MMU_CACHE_MIN_PAGES	2
-#endif
-
 #ifdef __ASSEMBLY__
 
 #include <asm/alternative.h>
@@ -91,6 +79,8 @@ alternative_endif
 #define KVM_PHYS_SIZE	(1UL << KVM_PHYS_SHIFT)
 #define KVM_PHYS_MASK	(KVM_PHYS_SIZE - 1UL)
 
+#include <asm/stage2_pgtable.h>
+
 int create_hyp_mappings(void *from, void *to);
 int create_hyp_io_mappings(void *from, void *to, phys_addr_t);
 void free_boot_hyp_pgd(void);
@@ -109,6 +99,7 @@ void kvm_mmu_free_memory_caches(struct k
 phys_addr_t kvm_mmu_get_httbr(void);
 phys_addr_t kvm_mmu_get_boot_httbr(void);
 phys_addr_t kvm_get_idmap_vector(void);
+phys_addr_t kvm_get_idmap_start(void);
 int kvm_mmu_init(void);
 void kvm_clear_hyp_idmap(void);
 
@@ -121,19 +112,32 @@ static inline void kvm_clean_pmd_entry(p
 static inline void kvm_clean_pte(pte_t *pte) {}
 static inline void kvm_clean_pte_entry(pte_t *pte) {}
 
-static inline void kvm_set_s2pte_writable(pte_t *pte)
+static inline pte_t kvm_s2pte_mkwrite(pte_t pte)
 {
-	pte_val(*pte) |= PTE_S2_RDWR;
+	pte_val(pte) |= PTE_S2_RDWR;
+	return pte;
 }
 
-static inline void kvm_set_s2pmd_writable(pmd_t *pmd)
+static inline pmd_t kvm_s2pmd_mkwrite(pmd_t pmd)
 {
-	pmd_val(*pmd) |= PMD_S2_RDWR;
+	pmd_val(pmd) |= PMD_S2_RDWR;
+	return pmd;
 }
 
 static inline void kvm_set_s2pte_readonly(pte_t *pte)
 {
-	pte_val(*pte) = (pte_val(*pte) & ~PTE_S2_RDWR) | PTE_S2_RDONLY;
+	pteval_t pteval;
+	unsigned long tmp;
+
+	asm volatile("//	kvm_set_s2pte_readonly\n"
+	"	prfm	pstl1strm, %2\n"
+	"1:	ldxr	%0, %2\n"
+	"	and	%0, %0, %3		// clear PTE_S2_RDWR\n"
+	"	orr	%0, %0, %4		// set PTE_S2_RDONLY\n"
+	"	stxr	%w1, %0, %2\n"
+	"	cbnz	%w1, 1b\n"
+	: "=&r" (pteval), "=&r" (tmp), "+Q" (pte_val(*pte))
+	: "L" (~PTE_S2_RDWR), "L" (PTE_S2_RDONLY));
 }
 
 static inline bool kvm_s2pte_readonly(pte_t *pte)
@@ -143,69 +147,12 @@ static inline bool kvm_s2pte_readonly(pt
 
 static inline void kvm_set_s2pmd_readonly(pmd_t *pmd)
 {
-	pmd_val(*pmd) = (pmd_val(*pmd) & ~PMD_S2_RDWR) | PMD_S2_RDONLY;
+	kvm_set_s2pte_readonly((pte_t *)pmd);
 }
 
 static inline bool kvm_s2pmd_readonly(pmd_t *pmd)
 {
-	return (pmd_val(*pmd) & PMD_S2_RDWR) == PMD_S2_RDONLY;
-}
-
-
-#define kvm_pgd_addr_end(addr, end)	pgd_addr_end(addr, end)
-#define kvm_pud_addr_end(addr, end)	pud_addr_end(addr, end)
-#define kvm_pmd_addr_end(addr, end)	pmd_addr_end(addr, end)
-
-/*
- * In the case where PGDIR_SHIFT is larger than KVM_PHYS_SHIFT, we can address
- * the entire IPA input range with a single pgd entry, and we would only need
- * one pgd entry.  Note that in this case, the pgd is actually not used by
- * the MMU for Stage-2 translations, but is merely a fake pgd used as a data
- * structure for the kernel pgtable macros to work.
- */
-#if PGDIR_SHIFT > KVM_PHYS_SHIFT
-#define PTRS_PER_S2_PGD_SHIFT	0
-#else
-#define PTRS_PER_S2_PGD_SHIFT	(KVM_PHYS_SHIFT - PGDIR_SHIFT)
-#endif
-#define PTRS_PER_S2_PGD		(1 << PTRS_PER_S2_PGD_SHIFT)
-
-#define kvm_pgd_index(addr)	(((addr) >> PGDIR_SHIFT) & (PTRS_PER_S2_PGD - 1))
-
-/*
- * If we are concatenating first level stage-2 page tables, we would have less
- * than or equal to 16 pointers in the fake PGD, because that's what the
- * architecture allows.  In this case, (4 - CONFIG_PGTABLE_LEVELS)
- * represents the first level for the host, and we add 1 to go to the next
- * level (which uses contatenation) for the stage-2 tables.
- */
-#if PTRS_PER_S2_PGD <= 16
-#define KVM_PREALLOC_LEVEL	(4 - CONFIG_PGTABLE_LEVELS + 1)
-#else
-#define KVM_PREALLOC_LEVEL	(0)
-#endif
-
-static inline void *kvm_get_hwpgd(struct kvm *kvm)
-{
-	pgd_t *pgd = kvm->arch.pgd;
-	pud_t *pud;
-
-	if (KVM_PREALLOC_LEVEL == 0)
-		return pgd;
-
-	pud = pud_offset(pgd, 0);
-	if (KVM_PREALLOC_LEVEL == 1)
-		return pud;
-
-	BUG_ON(KVM_PREALLOC_LEVEL != 2);
-	return pmd_offset(pud, 0);
-}
-
-static inline unsigned int kvm_get_hwpgd_size(void)
-{
-	if (KVM_PREALLOC_LEVEL > 0)
-		return PTRS_PER_S2_PGD * PAGE_SIZE;
-	return PTRS_PER_S2_PGD * sizeof(pgd_t);
+	return kvm_s2pte_readonly((pte_t *)pmd);
 }
 
 static inline bool kvm_page_empty(void *ptr)
@@ -214,23 +161,20 @@ static inline bool kvm_page_empty(void *
 	return page_count(ptr_page) == 1;
 }
 
-#define kvm_pte_table_empty(kvm, ptep) kvm_page_empty(ptep)
+#define hyp_pte_table_empty(ptep) kvm_page_empty(ptep)
 
 #ifdef __PAGETABLE_PMD_FOLDED
-#define kvm_pmd_table_empty(kvm, pmdp) (0)
+#define hyp_pmd_table_empty(pmdp) (0)
 #else
-#define kvm_pmd_table_empty(kvm, pmdp) \
-	(kvm_page_empty(pmdp) && (!(kvm) || KVM_PREALLOC_LEVEL < 2))
+#define hyp_pmd_table_empty(pmdp) kvm_page_empty(pmdp)
 #endif
 
 #ifdef __PAGETABLE_PUD_FOLDED
-#define kvm_pud_table_empty(kvm, pudp) (0)
+#define hyp_pud_table_empty(pudp) (0)
 #else
-#define kvm_pud_table_empty(kvm, pudp) \
-	(kvm_page_empty(pudp) && (!(kvm) || KVM_PREALLOC_LEVEL < 1))
+#define hyp_pud_table_empty(pudp) kvm_page_empty(pudp)
 #endif
 
-
 struct kvm;
 
 #define kvm_flush_dcache_to_poc(a,l)	__flush_dcache_area((a), (l))
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/include/asm/memory.h linux-libre-4.7-gnu/arch/arm64/include/asm/memory.h
--- linux-libre-4.6-gnu/arch/arm64/include/asm/memory.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/include/asm/memory.h	2016-07-24 15:23:50.000000000 -0400
@@ -40,8 +40,24 @@
 #define PCI_IO_SIZE		SZ_16M
 
 /*
- * PAGE_OFFSET - the virtual address of the start of the kernel image (top
+ * Log2 of the upper bound of the size of a struct page. Used for sizing
+ * the vmemmap region only, does not affect actual memory footprint.
+ * We don't use sizeof(struct page) directly since taking its size here
+ * requires its definition to be available at this point in the inclusion
+ * chain, and it may not be a power of 2 in the first place.
+ */
+#define STRUCT_PAGE_MAX_SHIFT	6
+
+/*
+ * VMEMMAP_SIZE - allows the whole linear region to be covered by
+ *                a struct page array
+ */
+#define VMEMMAP_SIZE (UL(1) << (VA_BITS - PAGE_SHIFT - 1 + STRUCT_PAGE_MAX_SHIFT))
+
+/*
+ * PAGE_OFFSET - the virtual address of the start of the linear map (top
  *		 (VA_BITS - 1))
+ * KIMAGE_VADDR - the virtual address of the start of the kernel image
  * VA_BITS - the maximum number of bits for virtual addresses.
  * VA_START - the first kernel virtual address.
  * TASK_SIZE - the maximum size of a user space task.
@@ -54,7 +70,8 @@
 #define MODULES_END		(MODULES_VADDR + MODULES_VSIZE)
 #define MODULES_VADDR		(VA_START + KASAN_SHADOW_SIZE)
 #define MODULES_VSIZE		(SZ_128M)
-#define PCI_IO_END		(PAGE_OFFSET - SZ_2M)
+#define VMEMMAP_START		(PAGE_OFFSET - VMEMMAP_SIZE)
+#define PCI_IO_END		(VMEMMAP_START - SZ_2M)
 #define PCI_IO_START		(PCI_IO_END - PCI_IO_SIZE)
 #define FIXADDR_TOP		(PCI_IO_START - SZ_2M)
 #define TASK_SIZE_64		(UL(1) << VA_BITS)
@@ -71,6 +88,9 @@
 
 #define TASK_UNMAPPED_BASE	(PAGE_ALIGN(TASK_SIZE / 4))
 
+#define KERNEL_START      _text
+#define KERNEL_END        _end
+
 /*
  * The size of the KASAN shadow region. This should be 1/8th of the
  * size of the entire kernel virtual address space.
@@ -192,9 +212,19 @@ static inline void *phys_to_virt(phys_ad
  */
 #define ARCH_PFN_OFFSET		((unsigned long)PHYS_PFN_OFFSET)
 
+#ifndef CONFIG_SPARSEMEM_VMEMMAP
 #define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
-#define	virt_addr_valid(kaddr)	pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
+#define virt_addr_valid(kaddr)	pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
+#else
+#define __virt_to_pgoff(kaddr)	(((u64)(kaddr) & ~PAGE_OFFSET) / PAGE_SIZE * sizeof(struct page))
+#define __page_to_voff(kaddr)	(((u64)(page) & ~VMEMMAP_START) * PAGE_SIZE / sizeof(struct page))
 
+#define page_to_virt(page)	((void *)((__page_to_voff(page)) | PAGE_OFFSET))
+#define virt_to_page(vaddr)	((struct page *)((__virt_to_pgoff(vaddr)) | VMEMMAP_START))
+
+#define virt_addr_valid(kaddr)	pfn_valid((((u64)(kaddr) & ~PAGE_OFFSET) \
+					   + PHYS_OFFSET) >> PAGE_SHIFT)
+#endif
 #endif
 
 #include <asm-generic/memory_model.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/include/asm/mmu.h linux-libre-4.7-gnu/arch/arm64/include/asm/mmu.h
--- linux-libre-4.6-gnu/arch/arm64/include/asm/mmu.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/include/asm/mmu.h	2016-07-24 15:23:50.000000000 -0400
@@ -29,6 +29,7 @@ typedef struct {
 #define ASID(mm)	((mm)->context.id.counter & 0xffff)
 
 extern void paging_init(void);
+extern void bootmem_init(void);
 extern void __iomem *early_io_map(phys_addr_t phys, unsigned long virt);
 extern void init_mem_pgprot(void);
 extern void create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys,
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/include/asm/mmzone.h linux-libre-4.7-gnu/arch/arm64/include/asm/mmzone.h
--- linux-libre-4.6-gnu/arch/arm64/include/asm/mmzone.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm64/include/asm/mmzone.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,12 @@
+#ifndef __ASM_MMZONE_H
+#define __ASM_MMZONE_H
+
+#ifdef CONFIG_NUMA
+
+#include <asm/numa.h>
+
+extern struct pglist_data *node_data[];
+#define NODE_DATA(nid)		(node_data[(nid)])
+
+#endif /* CONFIG_NUMA */
+#endif /* __ASM_MMZONE_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/include/asm/numa.h linux-libre-4.7-gnu/arch/arm64/include/asm/numa.h
--- linux-libre-4.6-gnu/arch/arm64/include/asm/numa.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm64/include/asm/numa.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,45 @@
+#ifndef __ASM_NUMA_H
+#define __ASM_NUMA_H
+
+#include <asm/topology.h>
+
+#ifdef CONFIG_NUMA
+
+/* currently, arm64 implements flat NUMA topology */
+#define parent_node(node)	(node)
+
+int __node_distance(int from, int to);
+#define node_distance(a, b) __node_distance(a, b)
+
+extern nodemask_t numa_nodes_parsed __initdata;
+
+/* Mappings between node number and cpus on that node. */
+extern cpumask_var_t node_to_cpumask_map[MAX_NUMNODES];
+void numa_clear_node(unsigned int cpu);
+
+#ifdef CONFIG_DEBUG_PER_CPU_MAPS
+const struct cpumask *cpumask_of_node(int node);
+#else
+/* Returns a pointer to the cpumask of CPUs on Node 'node'. */
+static inline const struct cpumask *cpumask_of_node(int node)
+{
+	return node_to_cpumask_map[node];
+}
+#endif
+
+void __init arm64_numa_init(void);
+int __init numa_add_memblk(int nodeid, u64 start, u64 end);
+void __init numa_set_distance(int from, int to, int distance);
+void __init numa_free_distance(void);
+void __init early_map_cpu_to_node(unsigned int cpu, int nid);
+void numa_store_cpu_info(unsigned int cpu);
+
+#else	/* CONFIG_NUMA */
+
+static inline void numa_store_cpu_info(unsigned int cpu) { }
+static inline void arm64_numa_init(void) { }
+static inline void early_map_cpu_to_node(unsigned int cpu, int nid) { }
+
+#endif	/* CONFIG_NUMA */
+
+#endif	/* __ASM_NUMA_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/include/asm/page.h linux-libre-4.7-gnu/arch/arm64/include/asm/page.h
--- linux-libre-4.6-gnu/arch/arm64/include/asm/page.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/include/asm/page.h	2016-07-24 15:23:50.000000000 -0400
@@ -19,18 +19,12 @@
 #ifndef __ASM_PAGE_H
 #define __ASM_PAGE_H
 
+#include <linux/const.h>
+
 /* PAGE_SHIFT determines the page size */
 /* CONT_SHIFT determines the number of pages which can be tracked together  */
-#ifdef CONFIG_ARM64_64K_PAGES
-#define PAGE_SHIFT		16
-#define CONT_SHIFT		5
-#elif defined(CONFIG_ARM64_16K_PAGES)
-#define PAGE_SHIFT		14
-#define CONT_SHIFT		7
-#else
-#define PAGE_SHIFT		12
-#define CONT_SHIFT		4
-#endif
+#define PAGE_SHIFT		CONFIG_ARM64_PAGE_SHIFT
+#define CONT_SHIFT		CONFIG_ARM64_CONT_SHIFT
 #define PAGE_SIZE		(_AC(1, UL) << PAGE_SHIFT)
 #define PAGE_MASK		(~(PAGE_SIZE-1))
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/include/asm/pgalloc.h linux-libre-4.7-gnu/arch/arm64/include/asm/pgalloc.h
--- linux-libre-4.6-gnu/arch/arm64/include/asm/pgalloc.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/include/asm/pgalloc.h	2016-07-24 15:23:50.000000000 -0400
@@ -26,7 +26,7 @@
 
 #define check_pgt_cache()		do { } while (0)
 
-#define PGALLOC_GFP	(GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO)
+#define PGALLOC_GFP	(GFP_KERNEL | __GFP_NOTRACK | __GFP_ZERO)
 #define PGD_SIZE	(PTRS_PER_PGD * sizeof(pgd_t))
 
 #if CONFIG_PGTABLE_LEVELS > 2
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/include/asm/pgtable.h linux-libre-4.7-gnu/arch/arm64/include/asm/pgtable.h
--- linux-libre-4.6-gnu/arch/arm64/include/asm/pgtable.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/include/asm/pgtable.h	2016-07-24 15:23:50.000000000 -0400
@@ -24,22 +24,16 @@
 #include <asm/pgtable-prot.h>
 
 /*
- * VMALLOC and SPARSEMEM_VMEMMAP ranges.
+ * VMALLOC range.
  *
- * VMEMAP_SIZE: allows the whole linear region to be covered by a struct page array
- *	(rounded up to PUD_SIZE).
  * VMALLOC_START: beginning of the kernel vmalloc space
- * VMALLOC_END: extends to the available space below vmmemmap, PCI I/O space,
- *	fixed mappings and modules
+ * VMALLOC_END: extends to the available space below vmmemmap, PCI I/O space
+ *	and fixed mappings
  */
-#define VMEMMAP_SIZE		ALIGN((1UL << (VA_BITS - PAGE_SHIFT)) * sizeof(struct page), PUD_SIZE)
-
 #define VMALLOC_START		(MODULES_END)
 #define VMALLOC_END		(PAGE_OFFSET - PUD_SIZE - VMEMMAP_SIZE - SZ_64K)
 
-#define VMEMMAP_START		(VMALLOC_END + SZ_64K)
-#define vmemmap			((struct page *)VMEMMAP_START - \
-				 SECTION_ALIGN_DOWN(memstart_addr >> PAGE_SHIFT))
+#define vmemmap			((struct page *)VMEMMAP_START - (memstart_addr >> PAGE_SHIFT))
 
 #define FIRST_USER_ADDRESS	0UL
 
@@ -58,7 +52,7 @@ extern void __pgd_error(const char *file
  * for zero-mapped memory areas etc..
  */
 extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
-#define ZERO_PAGE(vaddr)	virt_to_page(empty_zero_page)
+#define ZERO_PAGE(vaddr)	pfn_to_page(PHYS_PFN(__pa(empty_zero_page)))
 
 #define pte_ERROR(pte)		__pte_error(__FILE__, __LINE__, pte_val(pte))
 
@@ -272,6 +266,21 @@ static inline pgprot_t mk_sect_prot(pgpr
 	return __pgprot(pgprot_val(prot) & ~PTE_TABLE_BIT);
 }
 
+#ifdef CONFIG_NUMA_BALANCING
+/*
+ * See the comment in include/asm-generic/pgtable.h
+ */
+static inline int pte_protnone(pte_t pte)
+{
+	return (pte_val(pte) & (PTE_VALID | PTE_PROT_NONE)) == PTE_PROT_NONE;
+}
+
+static inline int pmd_protnone(pmd_t pmd)
+{
+	return pte_protnone(pmd_pte(pmd));
+}
+#endif
+
 /*
  * THP definitions.
  */
@@ -280,15 +289,18 @@ static inline pgprot_t mk_sect_prot(pgpr
 #define pmd_trans_huge(pmd)	(pmd_val(pmd) && !(pmd_val(pmd) & PMD_TABLE_BIT))
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
 
+#define pmd_present(pmd)	pte_present(pmd_pte(pmd))
 #define pmd_dirty(pmd)		pte_dirty(pmd_pte(pmd))
 #define pmd_young(pmd)		pte_young(pmd_pte(pmd))
 #define pmd_wrprotect(pmd)	pte_pmd(pte_wrprotect(pmd_pte(pmd)))
 #define pmd_mkold(pmd)		pte_pmd(pte_mkold(pmd_pte(pmd)))
 #define pmd_mkwrite(pmd)	pte_pmd(pte_mkwrite(pmd_pte(pmd)))
-#define pmd_mkclean(pmd)       pte_pmd(pte_mkclean(pmd_pte(pmd)))
+#define pmd_mkclean(pmd)	pte_pmd(pte_mkclean(pmd_pte(pmd)))
 #define pmd_mkdirty(pmd)	pte_pmd(pte_mkdirty(pmd_pte(pmd)))
 #define pmd_mkyoung(pmd)	pte_pmd(pte_mkyoung(pmd_pte(pmd)))
-#define pmd_mknotpresent(pmd)	(__pmd(pmd_val(pmd) & ~PMD_TYPE_MASK))
+#define pmd_mknotpresent(pmd)	(__pmd(pmd_val(pmd) & ~PMD_SECT_VALID))
+
+#define pmd_thp_or_huge(pmd)	(pmd_huge(pmd) || pmd_trans_huge(pmd))
 
 #define __HAVE_ARCH_PMD_WRITE
 #define pmd_write(pmd)		pte_write(pmd_pte(pmd))
@@ -304,11 +316,6 @@ static inline pgprot_t mk_sect_prot(pgpr
 
 #define set_pmd_at(mm, addr, pmdp, pmd)	set_pte_at(mm, addr, (pte_t *)pmdp, pmd_pte(pmd))
 
-static inline int has_transparent_hugepage(void)
-{
-	return 1;
-}
-
 #define __pgprot_modify(prot,mask,bits) \
 	__pgprot((pgprot_val(prot) & ~(mask)) | (bits))
 
@@ -327,9 +334,8 @@ extern pgprot_t phys_mem_access_prot(str
 				     unsigned long size, pgprot_t vma_prot);
 
 #define pmd_none(pmd)		(!pmd_val(pmd))
-#define pmd_present(pmd)	(pmd_val(pmd))
 
-#define pmd_bad(pmd)		(!(pmd_val(pmd) & 2))
+#define pmd_bad(pmd)		(!(pmd_val(pmd) & PMD_TABLE_BIT))
 
 #define pmd_table(pmd)		((pmd_val(pmd) & PMD_TYPE_MASK) == \
 				 PMD_TYPE_TABLE)
@@ -394,7 +400,7 @@ static inline phys_addr_t pmd_page_paddr
 #define pmd_ERROR(pmd)		__pmd_error(__FILE__, __LINE__, pmd_val(pmd))
 
 #define pud_none(pud)		(!pud_val(pud))
-#define pud_bad(pud)		(!(pud_val(pud) & 2))
+#define pud_bad(pud)		(!(pud_val(pud) & PUD_TABLE_BIT))
 #define pud_present(pud)	(pud_val(pud))
 
 static inline void set_pud(pud_t *pudp, pud_t pud)
@@ -526,18 +532,31 @@ static inline pmd_t pmd_modify(pmd_t pmd
 }
 
 #ifdef CONFIG_ARM64_HW_AFDBM
+#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
+extern int ptep_set_access_flags(struct vm_area_struct *vma,
+				 unsigned long address, pte_t *ptep,
+				 pte_t entry, int dirty);
+
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+#define __HAVE_ARCH_PMDP_SET_ACCESS_FLAGS
+static inline int pmdp_set_access_flags(struct vm_area_struct *vma,
+					unsigned long address, pmd_t *pmdp,
+					pmd_t entry, int dirty)
+{
+	return ptep_set_access_flags(vma, address, (pte_t *)pmdp, pmd_pte(entry), dirty);
+}
+#endif
+
 /*
  * Atomic pte/pmd modifications.
  */
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
-static inline int ptep_test_and_clear_young(struct vm_area_struct *vma,
-					    unsigned long address,
-					    pte_t *ptep)
+static inline int __ptep_test_and_clear_young(pte_t *ptep)
 {
 	pteval_t pteval;
 	unsigned int tmp, res;
 
-	asm volatile("//	ptep_test_and_clear_young\n"
+	asm volatile("//	__ptep_test_and_clear_young\n"
 	"	prfm	pstl1strm, %2\n"
 	"1:	ldxr	%0, %2\n"
 	"	ubfx	%w3, %w0, %5, #1	// extract PTE_AF (young)\n"
@@ -550,6 +569,13 @@ static inline int ptep_test_and_clear_yo
 	return res;
 }
 
+static inline int ptep_test_and_clear_young(struct vm_area_struct *vma,
+					    unsigned long address,
+					    pte_t *ptep)
+{
+	return __ptep_test_and_clear_young(ptep);
+}
+
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 #define __HAVE_ARCH_PMDP_TEST_AND_CLEAR_YOUNG
 static inline int pmdp_test_and_clear_young(struct vm_area_struct *vma,
@@ -578,9 +604,9 @@ static inline pte_t ptep_get_and_clear(s
 }
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
-#define __HAVE_ARCH_PMDP_GET_AND_CLEAR
-static inline pmd_t pmdp_get_and_clear(struct mm_struct *mm,
-				       unsigned long address, pmd_t *pmdp)
+#define __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR
+static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
+					    unsigned long address, pmd_t *pmdp)
 {
 	return pte_pmd(ptep_get_and_clear(mm, address, (pte_t *)pmdp));
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/include/asm/pgtable-hwdef.h linux-libre-4.7-gnu/arch/arm64/include/asm/pgtable-hwdef.h
--- linux-libre-4.6-gnu/arch/arm64/include/asm/pgtable-hwdef.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/include/asm/pgtable-hwdef.h	2016-07-24 15:23:50.000000000 -0400
@@ -133,7 +133,6 @@
  * Section
  */
 #define PMD_SECT_VALID		(_AT(pmdval_t, 1) << 0)
-#define PMD_SECT_PROT_NONE	(_AT(pmdval_t, 1) << 58)
 #define PMD_SECT_USER		(_AT(pmdval_t, 1) << 6)		/* AP[1] */
 #define PMD_SECT_RDONLY		(_AT(pmdval_t, 1) << 7)		/* AP[2] */
 #define PMD_SECT_S		(_AT(pmdval_t, 3) << 8)
@@ -208,23 +207,69 @@
 #define TCR_T1SZ(x)		((UL(64) - (x)) << TCR_T1SZ_OFFSET)
 #define TCR_TxSZ(x)		(TCR_T0SZ(x) | TCR_T1SZ(x))
 #define TCR_TxSZ_WIDTH		6
-#define TCR_IRGN_NC		((UL(0) << 8) | (UL(0) << 24))
-#define TCR_IRGN_WBWA		((UL(1) << 8) | (UL(1) << 24))
-#define TCR_IRGN_WT		((UL(2) << 8) | (UL(2) << 24))
-#define TCR_IRGN_WBnWA		((UL(3) << 8) | (UL(3) << 24))
-#define TCR_IRGN_MASK		((UL(3) << 8) | (UL(3) << 24))
-#define TCR_ORGN_NC		((UL(0) << 10) | (UL(0) << 26))
-#define TCR_ORGN_WBWA		((UL(1) << 10) | (UL(1) << 26))
-#define TCR_ORGN_WT		((UL(2) << 10) | (UL(2) << 26))
-#define TCR_ORGN_WBnWA		((UL(3) << 10) | (UL(3) << 26))
-#define TCR_ORGN_MASK		((UL(3) << 10) | (UL(3) << 26))
-#define TCR_SHARED		((UL(3) << 12) | (UL(3) << 28))
-#define TCR_TG0_4K		(UL(0) << 14)
-#define TCR_TG0_64K		(UL(1) << 14)
-#define TCR_TG0_16K		(UL(2) << 14)
-#define TCR_TG1_16K		(UL(1) << 30)
-#define TCR_TG1_4K		(UL(2) << 30)
-#define TCR_TG1_64K		(UL(3) << 30)
+
+#define TCR_IRGN0_SHIFT		8
+#define TCR_IRGN0_MASK		(UL(3) << TCR_IRGN0_SHIFT)
+#define TCR_IRGN0_NC		(UL(0) << TCR_IRGN0_SHIFT)
+#define TCR_IRGN0_WBWA		(UL(1) << TCR_IRGN0_SHIFT)
+#define TCR_IRGN0_WT		(UL(2) << TCR_IRGN0_SHIFT)
+#define TCR_IRGN0_WBnWA		(UL(3) << TCR_IRGN0_SHIFT)
+
+#define TCR_IRGN1_SHIFT		24
+#define TCR_IRGN1_MASK		(UL(3) << TCR_IRGN1_SHIFT)
+#define TCR_IRGN1_NC		(UL(0) << TCR_IRGN1_SHIFT)
+#define TCR_IRGN1_WBWA		(UL(1) << TCR_IRGN1_SHIFT)
+#define TCR_IRGN1_WT		(UL(2) << TCR_IRGN1_SHIFT)
+#define TCR_IRGN1_WBnWA		(UL(3) << TCR_IRGN1_SHIFT)
+
+#define TCR_IRGN_NC		(TCR_IRGN0_NC | TCR_IRGN1_NC)
+#define TCR_IRGN_WBWA		(TCR_IRGN0_WBWA | TCR_IRGN1_WBWA)
+#define TCR_IRGN_WT		(TCR_IRGN0_WT | TCR_IRGN1_WT)
+#define TCR_IRGN_WBnWA		(TCR_IRGN0_WBnWA | TCR_IRGN1_WBnWA)
+#define TCR_IRGN_MASK		(TCR_IRGN0_MASK | TCR_IRGN1_MASK)
+
+
+#define TCR_ORGN0_SHIFT		10
+#define TCR_ORGN0_MASK		(UL(3) << TCR_ORGN0_SHIFT)
+#define TCR_ORGN0_NC		(UL(0) << TCR_ORGN0_SHIFT)
+#define TCR_ORGN0_WBWA		(UL(1) << TCR_ORGN0_SHIFT)
+#define TCR_ORGN0_WT		(UL(2) << TCR_ORGN0_SHIFT)
+#define TCR_ORGN0_WBnWA		(UL(3) << TCR_ORGN0_SHIFT)
+
+#define TCR_ORGN1_SHIFT		26
+#define TCR_ORGN1_MASK		(UL(3) << TCR_ORGN1_SHIFT)
+#define TCR_ORGN1_NC		(UL(0) << TCR_ORGN1_SHIFT)
+#define TCR_ORGN1_WBWA		(UL(1) << TCR_ORGN1_SHIFT)
+#define TCR_ORGN1_WT		(UL(2) << TCR_ORGN1_SHIFT)
+#define TCR_ORGN1_WBnWA		(UL(3) << TCR_ORGN1_SHIFT)
+
+#define TCR_ORGN_NC		(TCR_ORGN0_NC | TCR_ORGN1_NC)
+#define TCR_ORGN_WBWA		(TCR_ORGN0_WBWA | TCR_ORGN1_WBWA)
+#define TCR_ORGN_WT		(TCR_ORGN0_WT | TCR_ORGN1_WT)
+#define TCR_ORGN_WBnWA		(TCR_ORGN0_WBnWA | TCR_ORGN1_WBnWA)
+#define TCR_ORGN_MASK		(TCR_ORGN0_MASK | TCR_ORGN1_MASK)
+
+#define TCR_SH0_SHIFT		12
+#define TCR_SH0_MASK		(UL(3) << TCR_SH0_SHIFT)
+#define TCR_SH0_INNER		(UL(3) << TCR_SH0_SHIFT)
+
+#define TCR_SH1_SHIFT		28
+#define TCR_SH1_MASK		(UL(3) << TCR_SH1_SHIFT)
+#define TCR_SH1_INNER		(UL(3) << TCR_SH1_SHIFT)
+#define TCR_SHARED		(TCR_SH0_INNER | TCR_SH1_INNER)
+
+#define TCR_TG0_SHIFT		14
+#define TCR_TG0_MASK		(UL(3) << TCR_TG0_SHIFT)
+#define TCR_TG0_4K		(UL(0) << TCR_TG0_SHIFT)
+#define TCR_TG0_64K		(UL(1) << TCR_TG0_SHIFT)
+#define TCR_TG0_16K		(UL(2) << TCR_TG0_SHIFT)
+
+#define TCR_TG1_SHIFT		30
+#define TCR_TG1_MASK		(UL(3) << TCR_TG1_SHIFT)
+#define TCR_TG1_16K		(UL(1) << TCR_TG1_SHIFT)
+#define TCR_TG1_4K		(UL(2) << TCR_TG1_SHIFT)
+#define TCR_TG1_64K		(UL(3) << TCR_TG1_SHIFT)
+
 #define TCR_ASID16		(UL(1) << 36)
 #define TCR_TBI0		(UL(1) << 37)
 #define TCR_HA			(UL(1) << 39)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/include/asm/pgtable-types.h linux-libre-4.7-gnu/arch/arm64/include/asm/pgtable-types.h
--- linux-libre-4.6-gnu/arch/arm64/include/asm/pgtable-types.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/include/asm/pgtable-types.h	2016-07-24 15:23:50.000000000 -0400
@@ -27,10 +27,6 @@ typedef u64 pmdval_t;
 typedef u64 pudval_t;
 typedef u64 pgdval_t;
 
-#undef STRICT_MM_TYPECHECKS
-
-#ifdef STRICT_MM_TYPECHECKS
-
 /*
  * These are used to make use of C type-checking..
  */
@@ -58,34 +54,6 @@ typedef struct { pteval_t pgprot; } pgpr
 #define pgprot_val(x)	((x).pgprot)
 #define __pgprot(x)	((pgprot_t) { (x) } )
 
-#else	/* !STRICT_MM_TYPECHECKS */
-
-typedef pteval_t pte_t;
-#define pte_val(x)	(x)
-#define __pte(x)	(x)
-
-#if CONFIG_PGTABLE_LEVELS > 2
-typedef pmdval_t pmd_t;
-#define pmd_val(x)	(x)
-#define __pmd(x)	(x)
-#endif
-
-#if CONFIG_PGTABLE_LEVELS > 3
-typedef pudval_t pud_t;
-#define pud_val(x)	(x)
-#define __pud(x)	(x)
-#endif
-
-typedef pgdval_t pgd_t;
-#define pgd_val(x)	(x)
-#define __pgd(x)	(x)
-
-typedef pteval_t pgprot_t;
-#define pgprot_val(x)	(x)
-#define __pgprot(x)	(x)
-
-#endif /* STRICT_MM_TYPECHECKS */
-
 #if CONFIG_PGTABLE_LEVELS == 2
 #include <asm-generic/pgtable-nopmd.h>
 #elif CONFIG_PGTABLE_LEVELS == 3
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/include/asm/ptrace.h linux-libre-4.7-gnu/arch/arm64/include/asm/ptrace.h
--- linux-libre-4.6-gnu/arch/arm64/include/asm/ptrace.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/include/asm/ptrace.h	2016-07-24 15:23:50.000000000 -0400
@@ -117,6 +117,8 @@ struct pt_regs {
 	};
 	u64 orig_x0;
 	u64 syscallno;
+	u64 orig_addr_limit;
+	u64 unused;	// maintain 16 byte alignment
 };
 
 #define arch_has_single_step()	(1)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/include/asm/smp.h linux-libre-4.7-gnu/arch/arm64/include/asm/smp.h
--- linux-libre-4.6-gnu/arch/arm64/include/asm/smp.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/include/asm/smp.h	2016-07-24 15:23:50.000000000 -0400
@@ -113,6 +113,29 @@ static inline void update_cpu_boot_statu
 	dsb(ishst);
 }
 
+/*
+ * The calling secondary CPU has detected serious configuration mismatch,
+ * which calls for a kernel panic. Update the boot status and park the calling
+ * CPU.
+ */
+static inline void cpu_panic_kernel(void)
+{
+	update_cpu_boot_status(CPU_PANIC_KERNEL);
+	cpu_park_loop();
+}
+
+/*
+ * If a secondary CPU enters the kernel but fails to come online,
+ * (e.g. due to mismatched features), and cannot exit the kernel,
+ * we increment cpus_stuck_in_kernel and leave the CPU in a
+ * quiesecent loop within the kernel text. The memory containing
+ * this loop must not be re-used for anything else as the 'stuck'
+ * core is executing it.
+ *
+ * This function is used to inhibit features like kexec and hibernate.
+ */
+bool cpus_are_stuck_in_kernel(void);
+
 #endif /* ifndef __ASSEMBLY__ */
 
 #endif /* ifndef __ASM_SMP_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/include/asm/spinlock.h linux-libre-4.7-gnu/arch/arm64/include/asm/spinlock.h
--- linux-libre-4.6-gnu/arch/arm64/include/asm/spinlock.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/include/asm/spinlock.h	2016-07-24 15:23:50.000000000 -0400
@@ -30,22 +30,53 @@ static inline void arch_spin_unlock_wait
 {
 	unsigned int tmp;
 	arch_spinlock_t lockval;
+	u32 owner;
+
+	/*
+	 * Ensure prior spin_lock operations to other locks have completed
+	 * on this CPU before we test whether "lock" is locked.
+	 */
+	smp_mb();
+	owner = READ_ONCE(lock->owner) << 16;
 
 	asm volatile(
 "	sevl\n"
 "1:	wfe\n"
 "2:	ldaxr	%w0, %2\n"
+	/* Is the lock free? */
 "	eor	%w1, %w0, %w0, ror #16\n"
-"	cbnz	%w1, 1b\n"
+"	cbz	%w1, 3f\n"
+	/* Lock taken -- has there been a subsequent unlock->lock transition? */
+"	eor	%w1, %w3, %w0, lsl #16\n"
+"	cbz	%w1, 1b\n"
+	/*
+	 * The owner has been updated, so there was an unlock->lock
+	 * transition that we missed. That means we can rely on the
+	 * store-release of the unlock operation paired with the
+	 * load-acquire of the lock operation to publish any of our
+	 * previous stores to the new lock owner and therefore don't
+	 * need to bother with the writeback below.
+	 */
+"	b	4f\n"
+"3:\n"
+	/*
+	 * Serialise against any concurrent lockers by writing back the
+	 * unlocked lock value
+	 */
 	ARM64_LSE_ATOMIC_INSN(
 	/* LL/SC */
 "	stxr	%w1, %w0, %2\n"
-"	cbnz	%w1, 2b\n", /* Serialise against any concurrent lockers */
-	/* LSE atomics */
 "	nop\n"
-"	nop\n")
+"	nop\n",
+	/* LSE atomics */
+"	mov	%w1, %w0\n"
+"	cas	%w0, %w0, %2\n"
+"	eor	%w1, %w1, %w0\n")
+	/* Somebody else wrote to the lock, GOTO 10 and reload the value */
+"	cbnz	%w1, 2b\n"
+"4:"
 	: "=&r" (lockval), "=&r" (tmp), "+Q" (*lock)
-	:
+	: "r" (owner)
 	: "memory");
 }
 
@@ -148,6 +179,7 @@ static inline int arch_spin_value_unlock
 
 static inline int arch_spin_is_locked(arch_spinlock_t *lock)
 {
+	smp_mb(); /* See arch_spin_unlock_wait */
 	return !arch_spin_value_unlocked(READ_ONCE(*lock));
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/include/asm/stage2_pgtable.h linux-libre-4.7-gnu/arch/arm64/include/asm/stage2_pgtable.h
--- linux-libre-4.6-gnu/arch/arm64/include/asm/stage2_pgtable.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm64/include/asm/stage2_pgtable.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2016 - ARM Ltd
+ *
+ * stage2 page table helpers
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ARM64_S2_PGTABLE_H_
+#define __ARM64_S2_PGTABLE_H_
+
+#include <asm/pgtable.h>
+
+/*
+ * The hardware supports concatenation of up to 16 tables at stage2 entry level
+ * and we use the feature whenever possible.
+ *
+ * Now, the minimum number of bits resolved at any level is (PAGE_SHIFT - 3).
+ * On arm64, the smallest PAGE_SIZE supported is 4k, which means
+ *             (PAGE_SHIFT - 3) > 4 holds for all page sizes.
+ * This implies, the total number of page table levels at stage2 expected
+ * by the hardware is actually the number of levels required for (KVM_PHYS_SHIFT - 4)
+ * in normal translations(e.g, stage1), since we cannot have another level in
+ * the range (KVM_PHYS_SHIFT, KVM_PHYS_SHIFT - 4).
+ */
+#define STAGE2_PGTABLE_LEVELS		ARM64_HW_PGTABLE_LEVELS(KVM_PHYS_SHIFT - 4)
+
+/*
+ * With all the supported VA_BITs and 40bit guest IPA, the following condition
+ * is always true:
+ *
+ *       STAGE2_PGTABLE_LEVELS <= CONFIG_PGTABLE_LEVELS
+ *
+ * We base our stage-2 page table walker helpers on this assumption and
+ * fall back to using the host version of the helper wherever possible.
+ * i.e, if a particular level is not folded (e.g, PUD) at stage2, we fall back
+ * to using the host version, since it is guaranteed it is not folded at host.
+ *
+ * If the condition breaks in the future, we can rearrange the host level
+ * definitions and reuse them for stage2. Till then...
+ */
+#if STAGE2_PGTABLE_LEVELS > CONFIG_PGTABLE_LEVELS
+#error "Unsupported combination of guest IPA and host VA_BITS."
+#endif
+
+/* S2_PGDIR_SHIFT is the size mapped by top-level stage2 entry */
+#define S2_PGDIR_SHIFT			ARM64_HW_PGTABLE_LEVEL_SHIFT(4 - STAGE2_PGTABLE_LEVELS)
+#define S2_PGDIR_SIZE			(_AC(1, UL) << S2_PGDIR_SHIFT)
+#define S2_PGDIR_MASK			(~(S2_PGDIR_SIZE - 1))
+
+/*
+ * The number of PTRS across all concatenated stage2 tables given by the
+ * number of bits resolved at the initial level.
+ */
+#define PTRS_PER_S2_PGD			(1 << (KVM_PHYS_SHIFT - S2_PGDIR_SHIFT))
+
+/*
+ * KVM_MMU_CACHE_MIN_PAGES is the number of stage2 page table translation
+ * levels in addition to the PGD.
+ */
+#define KVM_MMU_CACHE_MIN_PAGES		(STAGE2_PGTABLE_LEVELS - 1)
+
+
+#if STAGE2_PGTABLE_LEVELS > 3
+
+#define S2_PUD_SHIFT			ARM64_HW_PGTABLE_LEVEL_SHIFT(1)
+#define S2_PUD_SIZE			(_AC(1, UL) << S2_PUD_SHIFT)
+#define S2_PUD_MASK			(~(S2_PUD_SIZE - 1))
+
+#define stage2_pgd_none(pgd)				pgd_none(pgd)
+#define stage2_pgd_clear(pgd)				pgd_clear(pgd)
+#define stage2_pgd_present(pgd)				pgd_present(pgd)
+#define stage2_pgd_populate(pgd, pud)			pgd_populate(NULL, pgd, pud)
+#define stage2_pud_offset(pgd, address)			pud_offset(pgd, address)
+#define stage2_pud_free(pud)				pud_free(NULL, pud)
+
+#define stage2_pud_table_empty(pudp)			kvm_page_empty(pudp)
+
+static inline phys_addr_t stage2_pud_addr_end(phys_addr_t addr, phys_addr_t end)
+{
+	phys_addr_t boundary = (addr + S2_PUD_SIZE) & S2_PUD_MASK;
+
+	return (boundary - 1 < end - 1) ? boundary : end;
+}
+
+#endif		/* STAGE2_PGTABLE_LEVELS > 3 */
+
+
+#if STAGE2_PGTABLE_LEVELS > 2
+
+#define S2_PMD_SHIFT			ARM64_HW_PGTABLE_LEVEL_SHIFT(2)
+#define S2_PMD_SIZE			(_AC(1, UL) << S2_PMD_SHIFT)
+#define S2_PMD_MASK			(~(S2_PMD_SIZE - 1))
+
+#define stage2_pud_none(pud)				pud_none(pud)
+#define stage2_pud_clear(pud)				pud_clear(pud)
+#define stage2_pud_present(pud)				pud_present(pud)
+#define stage2_pud_populate(pud, pmd)			pud_populate(NULL, pud, pmd)
+#define stage2_pmd_offset(pud, address)			pmd_offset(pud, address)
+#define stage2_pmd_free(pmd)				pmd_free(NULL, pmd)
+
+#define stage2_pud_huge(pud)				pud_huge(pud)
+#define stage2_pmd_table_empty(pmdp)			kvm_page_empty(pmdp)
+
+static inline phys_addr_t stage2_pmd_addr_end(phys_addr_t addr, phys_addr_t end)
+{
+	phys_addr_t boundary = (addr + S2_PMD_SIZE) & S2_PMD_MASK;
+
+	return (boundary - 1 < end - 1) ? boundary : end;
+}
+
+#endif		/* STAGE2_PGTABLE_LEVELS > 2 */
+
+#define stage2_pte_table_empty(ptep)			kvm_page_empty(ptep)
+
+#if STAGE2_PGTABLE_LEVELS == 2
+#include <asm/stage2_pgtable-nopmd.h>
+#elif STAGE2_PGTABLE_LEVELS == 3
+#include <asm/stage2_pgtable-nopud.h>
+#endif
+
+
+#define stage2_pgd_index(addr)				(((addr) >> S2_PGDIR_SHIFT) & (PTRS_PER_S2_PGD - 1))
+
+static inline phys_addr_t stage2_pgd_addr_end(phys_addr_t addr, phys_addr_t end)
+{
+	phys_addr_t boundary = (addr + S2_PGDIR_SIZE) & S2_PGDIR_MASK;
+
+	return (boundary - 1 < end - 1) ? boundary : end;
+}
+
+#endif	/* __ARM64_S2_PGTABLE_H_ */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/include/asm/stage2_pgtable-nopmd.h linux-libre-4.7-gnu/arch/arm64/include/asm/stage2_pgtable-nopmd.h
--- linux-libre-4.6-gnu/arch/arm64/include/asm/stage2_pgtable-nopmd.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm64/include/asm/stage2_pgtable-nopmd.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2016 - ARM Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ARM64_S2_PGTABLE_NOPMD_H_
+#define __ARM64_S2_PGTABLE_NOPMD_H_
+
+#include <asm/stage2_pgtable-nopud.h>
+
+#define __S2_PGTABLE_PMD_FOLDED
+
+#define S2_PMD_SHIFT		S2_PUD_SHIFT
+#define S2_PTRS_PER_PMD		1
+#define S2_PMD_SIZE		(1UL << S2_PMD_SHIFT)
+#define S2_PMD_MASK		(~(S2_PMD_SIZE-1))
+
+#define stage2_pud_none(pud)			(0)
+#define stage2_pud_present(pud)			(1)
+#define stage2_pud_clear(pud)			do { } while (0)
+#define stage2_pud_populate(pud, pmd)		do { } while (0)
+#define stage2_pmd_offset(pud, address)		((pmd_t *)(pud))
+
+#define stage2_pmd_free(pmd)			do { } while (0)
+
+#define stage2_pmd_addr_end(addr, end)		(end)
+
+#define stage2_pud_huge(pud)			(0)
+#define stage2_pmd_table_empty(pmdp)		(0)
+
+#endif
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/include/asm/stage2_pgtable-nopud.h linux-libre-4.7-gnu/arch/arm64/include/asm/stage2_pgtable-nopud.h
--- linux-libre-4.6-gnu/arch/arm64/include/asm/stage2_pgtable-nopud.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm64/include/asm/stage2_pgtable-nopud.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2016 - ARM Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ARM64_S2_PGTABLE_NOPUD_H_
+#define __ARM64_S2_PGTABLE_NOPUD_H_
+
+#define __S2_PGTABLE_PUD_FOLDED
+
+#define S2_PUD_SHIFT		S2_PGDIR_SHIFT
+#define S2_PTRS_PER_PUD		1
+#define S2_PUD_SIZE		(_AC(1, UL) << S2_PUD_SHIFT)
+#define S2_PUD_MASK		(~(S2_PUD_SIZE-1))
+
+#define stage2_pgd_none(pgd)			(0)
+#define stage2_pgd_present(pgd)			(1)
+#define stage2_pgd_clear(pgd)			do { } while (0)
+#define stage2_pgd_populate(pgd, pud)	do { } while (0)
+
+#define stage2_pud_offset(pgd, address)		((pud_t *)(pgd))
+
+#define stage2_pud_free(x)			do { } while (0)
+
+#define stage2_pud_addr_end(addr, end)		(end)
+#define stage2_pud_table_empty(pmdp)		(0)
+
+#endif
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/include/asm/suspend.h linux-libre-4.7-gnu/arch/arm64/include/asm/suspend.h
--- linux-libre-4.6-gnu/arch/arm64/include/asm/suspend.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/include/asm/suspend.h	2016-07-24 15:23:50.000000000 -0400
@@ -1,7 +1,8 @@
 #ifndef __ASM_SUSPEND_H
 #define __ASM_SUSPEND_H
 
-#define NR_CTX_REGS 11
+#define NR_CTX_REGS 10
+#define NR_CALLEE_SAVED_REGS 12
 
 /*
  * struct cpu_suspend_ctx must be 16-byte aligned since it is allocated on
@@ -16,11 +17,34 @@ struct cpu_suspend_ctx {
 	u64 sp;
 } __aligned(16);
 
-struct sleep_save_sp {
-	phys_addr_t *save_ptr_stash;
-	phys_addr_t save_ptr_stash_phys;
+/*
+ * Memory to save the cpu state is allocated on the stack by
+ * __cpu_suspend_enter()'s caller, and populated by __cpu_suspend_enter().
+ * This data must survive until cpu_resume() is called.
+ *
+ * This struct desribes the size and the layout of the saved cpu state.
+ * The layout of the callee_saved_regs is defined by the implementation
+ * of __cpu_suspend_enter(), and cpu_resume(). This struct must be passed
+ * in by the caller as __cpu_suspend_enter()'s stack-frame is gone once it
+ * returns, and the data would be subsequently corrupted by the call to the
+ * finisher.
+ */
+struct sleep_stack_data {
+	struct cpu_suspend_ctx	system_regs;
+	unsigned long		callee_saved_regs[NR_CALLEE_SAVED_REGS];
 };
 
+extern unsigned long *sleep_save_stash;
+
 extern int cpu_suspend(unsigned long arg, int (*fn)(unsigned long));
 extern void cpu_resume(void);
+int __cpu_suspend_enter(struct sleep_stack_data *state);
+void __cpu_suspend_exit(void);
+void _cpu_resume(void);
+
+int swsusp_arch_suspend(void);
+int swsusp_arch_resume(void);
+int arch_hibernation_header_save(void *addr, unsigned int max_size);
+int arch_hibernation_header_restore(void *addr);
+
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/include/asm/sysreg.h linux-libre-4.7-gnu/arch/arm64/include/asm/sysreg.h
--- linux-libre-4.6-gnu/arch/arm64/include/asm/sysreg.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/include/asm/sysreg.h	2016-07-24 15:23:50.000000000 -0400
@@ -86,10 +86,21 @@
 #define SET_PSTATE_UAO(x) __inst_arm(0xd5000000 | REG_PSTATE_UAO_IMM |\
 				     (!!x)<<8 | 0x1f)
 
-/* SCTLR_EL1 */
-#define SCTLR_EL1_CP15BEN	(0x1 << 5)
-#define SCTLR_EL1_SED		(0x1 << 8)
-#define SCTLR_EL1_SPAN		(0x1 << 23)
+/* Common SCTLR_ELx flags. */
+#define SCTLR_ELx_EE    (1 << 25)
+#define SCTLR_ELx_I	(1 << 12)
+#define SCTLR_ELx_SA	(1 << 3)
+#define SCTLR_ELx_C	(1 << 2)
+#define SCTLR_ELx_A	(1 << 1)
+#define SCTLR_ELx_M	1
+
+#define SCTLR_ELx_FLAGS	(SCTLR_ELx_M | SCTLR_ELx_A | SCTLR_ELx_C | \
+			 SCTLR_ELx_SA | SCTLR_ELx_I)
+
+/* SCTLR_EL1 specific flags. */
+#define SCTLR_EL1_SPAN		(1 << 23)
+#define SCTLR_EL1_SED		(1 << 8)
+#define SCTLR_EL1_CP15BEN	(1 << 5)
 
 
 /* id_aa64isar0 */
@@ -115,6 +126,7 @@
 #define ID_AA64PFR0_ASIMD_SUPPORTED	0x0
 #define ID_AA64PFR0_EL1_64BIT_ONLY	0x1
 #define ID_AA64PFR0_EL0_64BIT_ONLY	0x1
+#define ID_AA64PFR0_EL0_32BIT_64BIT	0x2
 
 /* id_aa64mmfr0 */
 #define ID_AA64MMFR0_TGRAN4_SHIFT	28
@@ -145,7 +157,11 @@
 #define ID_AA64MMFR1_VMIDBITS_16	2
 
 /* id_aa64mmfr2 */
+#define ID_AA64MMFR2_LVA_SHIFT		16
+#define ID_AA64MMFR2_IESB_SHIFT		12
+#define ID_AA64MMFR2_LSM_SHIFT		8
 #define ID_AA64MMFR2_UAO_SHIFT		4
+#define ID_AA64MMFR2_CNP_SHIFT		0
 
 /* id_aa64dfr0 */
 #define ID_AA64DFR0_CTX_CMPS_SHIFT	28
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/include/asm/topology.h linux-libre-4.7-gnu/arch/arm64/include/asm/topology.h
--- linux-libre-4.6-gnu/arch/arm64/include/asm/topology.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/include/asm/topology.h	2016-07-24 15:23:50.000000000 -0400
@@ -22,6 +22,16 @@ void init_cpu_topology(void);
 void store_cpu_topology(unsigned int cpuid);
 const struct cpumask *cpu_coregroup_mask(int cpu);
 
+#ifdef CONFIG_NUMA
+
+struct pci_bus;
+int pcibus_to_node(struct pci_bus *bus);
+#define cpumask_of_pcibus(bus)	(pcibus_to_node(bus) == -1 ?		\
+				 cpu_all_mask :				\
+				 cpumask_of_node(pcibus_to_node(bus)))
+
+#endif /* CONFIG_NUMA */
+
 #include <asm-generic/topology.h>
 
 #endif /* _ASM_ARM_TOPOLOGY_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/include/asm/uaccess.h linux-libre-4.7-gnu/arch/arm64/include/asm/uaccess.h
--- linux-libre-4.6-gnu/arch/arm64/include/asm/uaccess.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/include/asm/uaccess.h	2016-07-24 15:23:50.000000000 -0400
@@ -81,19 +81,6 @@ static inline void set_fs(mm_segment_t f
 #define segment_eq(a, b)	((a) == (b))
 
 /*
- * Return 1 if addr < current->addr_limit, 0 otherwise.
- */
-#define __addr_ok(addr)							\
-({									\
-	unsigned long flag;						\
-	asm("cmp %1, %0; cset %0, lo"					\
-		: "=&r" (flag)						\
-		: "r" (addr), "0" (current_thread_info()->addr_limit)	\
-		: "cc");						\
-	flag;								\
-})
-
-/*
  * Test whether a block of memory is a valid user space address.
  * Returns 1 if the range is valid, 0 otherwise.
  *
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/include/asm/unistd32.h linux-libre-4.7-gnu/arch/arm64/include/asm/unistd32.h
--- linux-libre-4.6-gnu/arch/arm64/include/asm/unistd32.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/include/asm/unistd32.h	2016-07-24 15:23:50.000000000 -0400
@@ -801,6 +801,14 @@ __SYSCALL(__NR_execveat, compat_sys_exec
 __SYSCALL(__NR_userfaultfd, sys_userfaultfd)
 #define __NR_membarrier 389
 __SYSCALL(__NR_membarrier, sys_membarrier)
+#define __NR_mlock2 390
+__SYSCALL(__NR_mlock2, sys_mlock2)
+#define __NR_copy_file_range 391
+__SYSCALL(__NR_copy_file_range, sys_copy_file_range)
+#define __NR_preadv2 392
+__SYSCALL(__NR_preadv2, compat_sys_preadv2)
+#define __NR_pwritev2 393
+__SYSCALL(__NR_pwritev2, compat_sys_pwritev2)
 
 /*
  * Please add new compat syscalls above this comment and update
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/include/asm/unistd.h linux-libre-4.7-gnu/arch/arm64/include/asm/unistd.h
--- linux-libre-4.6-gnu/arch/arm64/include/asm/unistd.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/include/asm/unistd.h	2016-07-24 15:23:50.000000000 -0400
@@ -44,7 +44,7 @@
 #define __ARM_NR_compat_cacheflush	(__ARM_NR_COMPAT_BASE+2)
 #define __ARM_NR_compat_set_tls		(__ARM_NR_COMPAT_BASE+5)
 
-#define __NR_compat_syscalls		390
+#define __NR_compat_syscalls		394
 #endif
 
 #define __ARCH_WANT_SYS_CLONE
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/include/asm/virt.h linux-libre-4.7-gnu/arch/arm64/include/asm/virt.h
--- linux-libre-4.6-gnu/arch/arm64/include/asm/virt.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/include/asm/virt.h	2016-07-24 15:23:50.000000000 -0400
@@ -18,6 +18,22 @@
 #ifndef __ASM__VIRT_H
 #define __ASM__VIRT_H
 
+/*
+ * The arm64 hcall implementation uses x0 to specify the hcall type. A value
+ * less than 0xfff indicates a special hcall, such as get/set vector.
+ * Any other value is used as a pointer to the function to call.
+ */
+
+/* HVC_GET_VECTORS - Return the value of the vbar_el2 register. */
+#define HVC_GET_VECTORS 0
+
+/*
+ * HVC_SET_VECTORS - Set the value of the vbar_el2 register.
+ *
+ * @x1: Physical address of the new vector table.
+ */
+#define HVC_SET_VECTORS 1
+
 #define BOOT_CPU_MODE_EL1	(0xe11)
 #define BOOT_CPU_MODE_EL2	(0xe12)
 
@@ -60,6 +76,12 @@ static inline bool is_kernel_in_hyp_mode
 	return el == CurrentEL_EL2;
 }
 
+#ifdef CONFIG_ARM64_VHE
+extern void verify_cpu_run_el(void);
+#else
+static inline void verify_cpu_run_el(void) {}
+#endif
+
 /* The section containing the hypervisor text */
 extern char __hyp_text_start[];
 extern char __hyp_text_end[];
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/include/uapi/asm/unistd.h linux-libre-4.7-gnu/arch/arm64/include/uapi/asm/unistd.h
--- linux-libre-4.6-gnu/arch/arm64/include/uapi/asm/unistd.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/include/uapi/asm/unistd.h	2016-07-24 15:23:50.000000000 -0400
@@ -13,4 +13,7 @@
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
+
+#define __ARCH_WANT_RENAMEAT
+
 #include <asm-generic/unistd.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/Kconfig linux-libre-4.7-gnu/arch/arm64/Kconfig
--- linux-libre-4.6-gnu/arch/arm64/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -11,6 +11,7 @@ config ARM64
 	select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
 	select ARCH_USE_CMPXCHG_LOCKREF
 	select ARCH_SUPPORTS_ATOMIC_RMW
+	select ARCH_SUPPORTS_NUMA_BALANCING
 	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select ARCH_WANT_COMPAT_IPC_PARSE_VERSION
 	select ARCH_WANT_FRAME_POINTERS
@@ -58,11 +59,14 @@ config ARM64
 	select HAVE_ARCH_MMAP_RND_COMPAT_BITS if COMPAT
 	select HAVE_ARCH_SECCOMP_FILTER
 	select HAVE_ARCH_TRACEHOOK
-	select HAVE_BPF_JIT
+	select HAVE_ARCH_TRANSPARENT_HUGEPAGE
+	select HAVE_ARM_SMCCC
+	select HAVE_EBPF_JIT
 	select HAVE_C_RECORDMCOUNT
 	select HAVE_CC_STACKPROTECTOR
 	select HAVE_CMPXCHG_DOUBLE
 	select HAVE_CMPXCHG_LOCAL
+	select HAVE_CONTEXT_TRACKING
 	select HAVE_DEBUG_BUGVERBOSE
 	select HAVE_DEBUG_KMEMLEAK
 	select HAVE_DMA_API_DEBUG
@@ -76,6 +80,7 @@ config ARM64
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS
 	select HAVE_IRQ_TIME_ACCOUNTING
 	select HAVE_MEMBLOCK
+	select HAVE_MEMBLOCK_NODE_MAP if NUMA
 	select HAVE_PATA_PLATFORM
 	select HAVE_PERF_EVENTS
 	select HAVE_PERF_REGS
@@ -89,15 +94,13 @@ config ARM64
 	select NO_BOOTMEM
 	select OF
 	select OF_EARLY_FLATTREE
+	select OF_NUMA if NUMA && OF
 	select OF_RESERVED_MEM
 	select PERF_USE_VMALLOC
 	select POWER_RESET
 	select POWER_SUPPLY
-	select RTC_LIB
 	select SPARSE_IRQ
 	select SYSCTL_EXCEPTION_TRACE
-	select HAVE_CONTEXT_TRACKING
-	select HAVE_ARM_SMCCC
 	help
 	  ARM 64-bit (AArch64) Linux support.
 
@@ -110,6 +113,18 @@ config ARCH_PHYS_ADDR_T_64BIT
 config MMU
 	def_bool y
 
+config ARM64_PAGE_SHIFT
+	int
+	default 16 if ARM64_64K_PAGES
+	default 14 if ARM64_16K_PAGES
+	default 12
+
+config ARM64_CONT_SHIFT
+	int
+	default 5 if ARM64_64K_PAGES
+	default 7 if ARM64_16K_PAGES
+	default 4
+
 config ARCH_MMAP_RND_BITS_MIN
        default 14 if ARM64_64K_PAGES
        default 16 if ARM64_16K_PAGES
@@ -423,6 +438,15 @@ config CAVIUM_ERRATUM_22375
 
 	  If unsure, say Y.
 
+config CAVIUM_ERRATUM_23144
+	bool "Cavium erratum 23144: ITS SYNC hang on dual socket system"
+	depends on NUMA
+	default y
+	help
+	  ITS SYNC command hang for cross node io and collections/cpu mapping.
+
+	  If unsure, say Y.
+
 config CAVIUM_ERRATUM_23154
 	bool "Cavium erratum 23154: Access to ICC_IAR1_EL1 is not sync'ed"
 	default y
@@ -546,10 +570,35 @@ config HOTPLUG_CPU
 	  Say Y here to experiment with turning CPUs off and on.  CPUs
 	  can be controlled through /sys/devices/system/cpu.
 
+# Common NUMA Features
+config NUMA
+	bool "Numa Memory Allocation and Scheduler Support"
+	depends on SMP
+	help
+	  Enable NUMA (Non Uniform Memory Access) support.
+
+	  The kernel will try to allocate memory used by a CPU on the
+	  local memory of the CPU and add some more
+	  NUMA awareness to the kernel.
+
+config NODES_SHIFT
+	int "Maximum NUMA Nodes (as a power of 2)"
+	range 1 10
+	default "2"
+	depends on NEED_MULTIPLE_NODES
+	help
+	  Specify the maximum number of NUMA Nodes available on the target
+	  system.  Increases memory reserved to accommodate various tables.
+
+config USE_PERCPU_NUMA_NODE_ID
+	def_bool y
+	depends on NUMA
+
 source kernel/Kconfig.preempt
 source kernel/Kconfig.hz
 
 config ARCH_SUPPORTS_DEBUG_PAGEALLOC
+	depends on !HIBERNATION
 	def_bool y
 
 config ARCH_HAS_HOLES_MEMORYMODEL
@@ -578,9 +627,6 @@ config SYS_SUPPORTS_HUGETLBFS
 config ARCH_WANT_HUGE_PMD_SHARE
 	def_bool y if ARM64_4K_PAGES || (ARM64_16K_PAGES && !ARM64_VA_BITS_36)
 
-config HAVE_ARCH_TRANSPARENT_HUGEPAGE
-	def_bool y
-
 config ARCH_HAS_CACHE_LINE_SIZE
 	def_bool y
 
@@ -953,6 +999,14 @@ menu "Power management options"
 
 source "kernel/power/Kconfig"
 
+config ARCH_HIBERNATION_POSSIBLE
+	def_bool y
+	depends on CPU_PM
+
+config ARCH_HIBERNATION_HEADER
+	def_bool y
+	depends on HIBERNATION
+
 config ARCH_SUSPEND_POSSIBLE
 	def_bool y
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/Kconfig.debug linux-libre-4.7-gnu/arch/arm64/Kconfig.debug
--- linux-libre-4.6-gnu/arch/arm64/Kconfig.debug	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/Kconfig.debug	2016-07-24 15:23:50.000000000 -0400
@@ -12,7 +12,8 @@ config ARM64_PTDUMP
 	  who are working in architecture specific areas of the kernel.
 	  It is probably not a good idea to enable this feature in a production
 	  kernel.
-	  If in doubt, say "N"
+
+	  If in doubt, say N.
 
 config PID_IN_CONTEXTIDR
 	bool "Write the current PID to the CONTEXTIDR register"
@@ -38,15 +39,15 @@ config ARM64_RANDOMIZE_TEXT_OFFSET
 	  value.
 
 config DEBUG_SET_MODULE_RONX
-        bool "Set loadable kernel module data as NX and text as RO"
-        depends on MODULES
-        help
-          This option helps catch unintended modifications to loadable
-          kernel module's text and read-only data. It also prevents execution
-          of module data. Such protection may interfere with run-time code
-          patching and dynamic kernel tracing - and they might also protect
-          against certain classes of kernel exploits.
-          If in doubt, say "N".
+	bool "Set loadable kernel module data as NX and text as RO"
+	depends on MODULES
+	default y
+	help
+	  Is this is set, kernel module text and rodata will be made read-only.
+	  This is to help catch accidental or malicious attempts to change the
+	  kernel's executable code.
+
+	  If in doubt, say Y.
 
 config DEBUG_RODATA
 	bool "Make kernel text and rodata read-only"
@@ -56,10 +57,10 @@ config DEBUG_RODATA
 	  is to help catch accidental or malicious attempts to change the
 	  kernel's executable code.
 
-	  If in doubt, say Y
+	  If in doubt, say Y.
 
 config DEBUG_ALIGN_RODATA
-	depends on DEBUG_RODATA && ARM64_4K_PAGES
+	depends on DEBUG_RODATA
 	bool "Align linker sections up to SECTION_SIZE"
 	help
 	  If this option is enabled, sections that may potentially be marked as
@@ -69,7 +70,7 @@ config DEBUG_ALIGN_RODATA
 	  alignment and potentially wasted space. Turn on this option if
 	  performance is more important than memory pressure.
 
-	  If in doubt, say N
+	  If in doubt, say N.
 
 source "drivers/hwtracing/coresight/Kconfig"
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/Kconfig.platforms linux-libre-4.7-gnu/arch/arm64/Kconfig.platforms
--- linux-libre-4.6-gnu/arch/arm64/Kconfig.platforms	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/Kconfig.platforms	2016-07-24 15:23:50.000000000 -0400
@@ -44,8 +44,14 @@ config ARCH_LAYERSCAPE
 	help
 	  This enables support for the Freescale Layerscape SoC family.
 
+config ARCH_LG1K
+	bool "LG Electronics LG1K SoC Family"
+	help
+	  This enables support for LG Electronics LG1K SoC Family
+
 config ARCH_HISI
 	bool "Hisilicon SoC Family"
+	select ARM_TIMER_SP804
 	select HISILICON_IRQ_MBIGEN
 	help
 	  This enables support for Hisilicon ARMv8 SoC family
@@ -65,8 +71,8 @@ config ARCH_MESON
 
 config ARCH_MVEBU
 	bool "Marvell EBU SoC Family"
-	select ARMADA_AP806_CORE_CLK
-	select ARMADA_AP806_RING_CLK
+	select ARMADA_AP806_SYSCON
+	select ARMADA_CP110_SYSCON
 	select MVEBU_ODMI
 	help
 	  This enables support for Marvell EBU familly, including:
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kernel/acpi.c linux-libre-4.7-gnu/arch/arm64/kernel/acpi.c
--- linux-libre-4.6-gnu/arch/arm64/kernel/acpi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kernel/acpi.c	2016-07-24 15:23:50.000000000 -0400
@@ -42,6 +42,7 @@ int acpi_pci_disabled = 1;	/* skip ACPI
 EXPORT_SYMBOL(acpi_pci_disabled);
 
 static bool param_acpi_off __initdata;
+static bool param_acpi_on __initdata;
 static bool param_acpi_force __initdata;
 
 static int __init parse_acpi(char *arg)
@@ -52,6 +53,8 @@ static int __init parse_acpi(char *arg)
 	/* "acpi=off" disables both ACPI table parsing and interpreter */
 	if (strcmp(arg, "off") == 0)
 		param_acpi_off = true;
+	else if (strcmp(arg, "on") == 0) /* prefer ACPI over DT */
+		param_acpi_on = true;
 	else if (strcmp(arg, "force") == 0) /* force ACPI to be enabled */
 		param_acpi_force = true;
 	else
@@ -66,12 +69,24 @@ static int __init dt_scan_depth1_nodes(u
 				       void *data)
 {
 	/*
-	 * Return 1 as soon as we encounter a node at depth 1 that is
-	 * not the /chosen node.
+	 * Ignore anything not directly under the root node; we'll
+	 * catch its parent instead.
 	 */
-	if (depth == 1 && (strcmp(uname, "chosen") != 0))
-		return 1;
-	return 0;
+	if (depth != 1)
+		return 0;
+
+	if (strcmp(uname, "chosen") == 0)
+		return 0;
+
+	if (strcmp(uname, "hypervisor") == 0 &&
+	    of_flat_dt_is_compatible(node, "xen,xen"))
+		return 0;
+
+	/*
+	 * This node at depth 1 is neither a chosen node nor a xen node,
+	 * which we do not expect.
+	 */
+	return 1;
 }
 
 /*
@@ -184,11 +199,13 @@ void __init acpi_boot_table_init(void)
 	/*
 	 * Enable ACPI instead of device tree unless
 	 * - ACPI has been disabled explicitly (acpi=off), or
-	 * - the device tree is not empty (it has more than just a /chosen node)
-	 *   and ACPI has not been force enabled (acpi=force)
+	 * - the device tree is not empty (it has more than just a /chosen node,
+	 *   and a /hypervisor node when running on Xen)
+	 *   and ACPI has not been [force] enabled (acpi=on|force)
 	 */
 	if (param_acpi_off ||
-	    (!param_acpi_force && of_scan_flat_dt(dt_scan_depth1_nodes, NULL)))
+	    (!param_acpi_on && !param_acpi_force &&
+	     of_scan_flat_dt(dt_scan_depth1_nodes, NULL)))
 		return;
 
 	/*
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kernel/asm-offsets.c linux-libre-4.7-gnu/arch/arm64/kernel/asm-offsets.c
--- linux-libre-4.6-gnu/arch/arm64/kernel/asm-offsets.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kernel/asm-offsets.c	2016-07-24 15:23:50.000000000 -0400
@@ -22,6 +22,7 @@
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
 #include <linux/kvm_host.h>
+#include <linux/suspend.h>
 #include <asm/thread_info.h>
 #include <asm/memory.h>
 #include <asm/smp_plat.h>
@@ -59,6 +60,7 @@ int main(void)
   DEFINE(S_PC,			offsetof(struct pt_regs, pc));
   DEFINE(S_ORIG_X0,		offsetof(struct pt_regs, orig_x0));
   DEFINE(S_SYSCALLNO,		offsetof(struct pt_regs, syscallno));
+  DEFINE(S_ORIG_ADDR_LIMIT,	offsetof(struct pt_regs, orig_addr_limit));
   DEFINE(S_FRAME_SIZE,		sizeof(struct pt_regs));
   BLANK();
   DEFINE(MM_CONTEXT_ID,		offsetof(struct mm_struct, context.id.counter));
@@ -119,11 +121,14 @@ int main(void)
   DEFINE(CPU_CTX_SP,		offsetof(struct cpu_suspend_ctx, sp));
   DEFINE(MPIDR_HASH_MASK,	offsetof(struct mpidr_hash, mask));
   DEFINE(MPIDR_HASH_SHIFTS,	offsetof(struct mpidr_hash, shift_aff));
-  DEFINE(SLEEP_SAVE_SP_SZ,	sizeof(struct sleep_save_sp));
-  DEFINE(SLEEP_SAVE_SP_PHYS,	offsetof(struct sleep_save_sp, save_ptr_stash_phys));
-  DEFINE(SLEEP_SAVE_SP_VIRT,	offsetof(struct sleep_save_sp, save_ptr_stash));
+  DEFINE(SLEEP_STACK_DATA_SYSTEM_REGS,	offsetof(struct sleep_stack_data, system_regs));
+  DEFINE(SLEEP_STACK_DATA_CALLEE_REGS,	offsetof(struct sleep_stack_data, callee_saved_regs));
 #endif
   DEFINE(ARM_SMCCC_RES_X0_OFFS,	offsetof(struct arm_smccc_res, a0));
   DEFINE(ARM_SMCCC_RES_X2_OFFS,	offsetof(struct arm_smccc_res, a2));
+  BLANK();
+  DEFINE(HIBERN_PBE_ORIG,	offsetof(struct pbe, orig_address));
+  DEFINE(HIBERN_PBE_ADDR,	offsetof(struct pbe, address));
+  DEFINE(HIBERN_PBE_NEXT,	offsetof(struct pbe, next));
   return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kernel/cpu_errata.c linux-libre-4.7-gnu/arch/arm64/kernel/cpu_errata.c
--- linux-libre-4.6-gnu/arch/arm64/kernel/cpu_errata.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kernel/cpu_errata.c	2016-07-24 15:23:50.000000000 -0400
@@ -22,14 +22,16 @@
 #include <asm/cpufeature.h>
 
 static bool __maybe_unused
-is_affected_midr_range(const struct arm64_cpu_capabilities *entry)
+is_affected_midr_range(const struct arm64_cpu_capabilities *entry, int scope)
 {
+	WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible());
 	return MIDR_IS_CPU_MODEL_RANGE(read_cpuid_id(), entry->midr_model,
 				       entry->midr_range_min,
 				       entry->midr_range_max);
 }
 
 #define MIDR_RANGE(model, min, max) \
+	.def_scope = SCOPE_LOCAL_CPU, \
 	.matches = is_affected_midr_range, \
 	.midr_model = model, \
 	.midr_range_min = min, \
@@ -96,11 +98,37 @@ const struct arm64_cpu_capabilities arm6
 		MIDR_RANGE(MIDR_THUNDERX, 0x00,
 			   (1 << MIDR_VARIANT_SHIFT) | 1),
 	},
+	{
+	/* Cavium ThunderX, T81 pass 1.0 */
+		.desc = "Cavium erratum 27456",
+		.capability = ARM64_WORKAROUND_CAVIUM_27456,
+		MIDR_RANGE(MIDR_THUNDERX_81XX, 0x00, 0x00),
+	},
 #endif
 	{
 	}
 };
 
+/*
+ * The CPU Errata work arounds are detected and applied at boot time
+ * and the related information is freed soon after. If the new CPU requires
+ * an errata not detected at boot, fail this CPU.
+ */
+void verify_local_cpu_errata(void)
+{
+	const struct arm64_cpu_capabilities *caps = arm64_errata;
+
+	for (; caps->matches; caps++)
+		if (!cpus_have_cap(caps->capability) &&
+			caps->matches(caps, SCOPE_LOCAL_CPU)) {
+			pr_crit("CPU%d: Requires work around for %s, not detected"
+					" at boot time\n",
+				smp_processor_id(),
+				caps->desc ? : "an erratum");
+			cpu_die_early();
+		}
+}
+
 void check_local_cpu_errata(void)
 {
 	update_cpu_capabilities(arm64_errata, "enabling workaround for");
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kernel/cpufeature.c linux-libre-4.7-gnu/arch/arm64/kernel/cpufeature.c
--- linux-libre-4.6-gnu/arch/arm64/kernel/cpufeature.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kernel/cpufeature.c	2016-07-24 15:23:50.000000000 -0400
@@ -71,7 +71,8 @@ DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
 
 /* meta feature for alternatives */
 static bool __maybe_unused
-cpufeature_pan_not_uao(const struct arm64_cpu_capabilities *entry);
+cpufeature_pan_not_uao(const struct arm64_cpu_capabilities *entry, int __unused);
+
 
 static struct arm64_ftr_bits ftr_id_aa64isar0[] = {
 	ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, 32, 32, 0),
@@ -130,7 +131,11 @@ static struct arm64_ftr_bits ftr_id_aa64
 };
 
 static struct arm64_ftr_bits ftr_id_aa64mmfr2[] = {
+	ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR2_LVA_SHIFT, 4, 0),
+	ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR2_IESB_SHIFT, 4, 0),
+	ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR2_LSM_SHIFT, 4, 0),
 	ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR2_UAO_SHIFT, 4, 0),
+	ARM64_FTR_BITS(FTR_STRICT, FTR_EXACT, ID_AA64MMFR2_CNP_SHIFT, 4, 0),
 	ARM64_FTR_END,
 };
 
@@ -435,22 +440,26 @@ void __init init_cpu_features(struct cpu
 	init_cpu_ftr_reg(SYS_ID_AA64MMFR2_EL1, info->reg_id_aa64mmfr2);
 	init_cpu_ftr_reg(SYS_ID_AA64PFR0_EL1, info->reg_id_aa64pfr0);
 	init_cpu_ftr_reg(SYS_ID_AA64PFR1_EL1, info->reg_id_aa64pfr1);
-	init_cpu_ftr_reg(SYS_ID_DFR0_EL1, info->reg_id_dfr0);
-	init_cpu_ftr_reg(SYS_ID_ISAR0_EL1, info->reg_id_isar0);
-	init_cpu_ftr_reg(SYS_ID_ISAR1_EL1, info->reg_id_isar1);
-	init_cpu_ftr_reg(SYS_ID_ISAR2_EL1, info->reg_id_isar2);
-	init_cpu_ftr_reg(SYS_ID_ISAR3_EL1, info->reg_id_isar3);
-	init_cpu_ftr_reg(SYS_ID_ISAR4_EL1, info->reg_id_isar4);
-	init_cpu_ftr_reg(SYS_ID_ISAR5_EL1, info->reg_id_isar5);
-	init_cpu_ftr_reg(SYS_ID_MMFR0_EL1, info->reg_id_mmfr0);
-	init_cpu_ftr_reg(SYS_ID_MMFR1_EL1, info->reg_id_mmfr1);
-	init_cpu_ftr_reg(SYS_ID_MMFR2_EL1, info->reg_id_mmfr2);
-	init_cpu_ftr_reg(SYS_ID_MMFR3_EL1, info->reg_id_mmfr3);
-	init_cpu_ftr_reg(SYS_ID_PFR0_EL1, info->reg_id_pfr0);
-	init_cpu_ftr_reg(SYS_ID_PFR1_EL1, info->reg_id_pfr1);
-	init_cpu_ftr_reg(SYS_MVFR0_EL1, info->reg_mvfr0);
-	init_cpu_ftr_reg(SYS_MVFR1_EL1, info->reg_mvfr1);
-	init_cpu_ftr_reg(SYS_MVFR2_EL1, info->reg_mvfr2);
+
+	if (id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0)) {
+		init_cpu_ftr_reg(SYS_ID_DFR0_EL1, info->reg_id_dfr0);
+		init_cpu_ftr_reg(SYS_ID_ISAR0_EL1, info->reg_id_isar0);
+		init_cpu_ftr_reg(SYS_ID_ISAR1_EL1, info->reg_id_isar1);
+		init_cpu_ftr_reg(SYS_ID_ISAR2_EL1, info->reg_id_isar2);
+		init_cpu_ftr_reg(SYS_ID_ISAR3_EL1, info->reg_id_isar3);
+		init_cpu_ftr_reg(SYS_ID_ISAR4_EL1, info->reg_id_isar4);
+		init_cpu_ftr_reg(SYS_ID_ISAR5_EL1, info->reg_id_isar5);
+		init_cpu_ftr_reg(SYS_ID_MMFR0_EL1, info->reg_id_mmfr0);
+		init_cpu_ftr_reg(SYS_ID_MMFR1_EL1, info->reg_id_mmfr1);
+		init_cpu_ftr_reg(SYS_ID_MMFR2_EL1, info->reg_id_mmfr2);
+		init_cpu_ftr_reg(SYS_ID_MMFR3_EL1, info->reg_id_mmfr3);
+		init_cpu_ftr_reg(SYS_ID_PFR0_EL1, info->reg_id_pfr0);
+		init_cpu_ftr_reg(SYS_ID_PFR1_EL1, info->reg_id_pfr1);
+		init_cpu_ftr_reg(SYS_MVFR0_EL1, info->reg_mvfr0);
+		init_cpu_ftr_reg(SYS_MVFR1_EL1, info->reg_mvfr1);
+		init_cpu_ftr_reg(SYS_MVFR2_EL1, info->reg_mvfr2);
+	}
+
 }
 
 static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
@@ -555,47 +564,51 @@ void update_cpu_features(int cpu,
 				      info->reg_id_aa64pfr1, boot->reg_id_aa64pfr1);
 
 	/*
-	 * If we have AArch32, we care about 32-bit features for compat. These
-	 * registers should be RES0 otherwise.
+	 * If we have AArch32, we care about 32-bit features for compat.
+	 * If the system doesn't support AArch32, don't update them.
 	 */
-	taint |= check_update_ftr_reg(SYS_ID_DFR0_EL1, cpu,
+	if (id_aa64pfr0_32bit_el0(read_system_reg(SYS_ID_AA64PFR0_EL1)) &&
+		id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0)) {
+
+		taint |= check_update_ftr_reg(SYS_ID_DFR0_EL1, cpu,
 					info->reg_id_dfr0, boot->reg_id_dfr0);
-	taint |= check_update_ftr_reg(SYS_ID_ISAR0_EL1, cpu,
+		taint |= check_update_ftr_reg(SYS_ID_ISAR0_EL1, cpu,
 					info->reg_id_isar0, boot->reg_id_isar0);
-	taint |= check_update_ftr_reg(SYS_ID_ISAR1_EL1, cpu,
+		taint |= check_update_ftr_reg(SYS_ID_ISAR1_EL1, cpu,
 					info->reg_id_isar1, boot->reg_id_isar1);
-	taint |= check_update_ftr_reg(SYS_ID_ISAR2_EL1, cpu,
+		taint |= check_update_ftr_reg(SYS_ID_ISAR2_EL1, cpu,
 					info->reg_id_isar2, boot->reg_id_isar2);
-	taint |= check_update_ftr_reg(SYS_ID_ISAR3_EL1, cpu,
+		taint |= check_update_ftr_reg(SYS_ID_ISAR3_EL1, cpu,
 					info->reg_id_isar3, boot->reg_id_isar3);
-	taint |= check_update_ftr_reg(SYS_ID_ISAR4_EL1, cpu,
+		taint |= check_update_ftr_reg(SYS_ID_ISAR4_EL1, cpu,
 					info->reg_id_isar4, boot->reg_id_isar4);
-	taint |= check_update_ftr_reg(SYS_ID_ISAR5_EL1, cpu,
+		taint |= check_update_ftr_reg(SYS_ID_ISAR5_EL1, cpu,
 					info->reg_id_isar5, boot->reg_id_isar5);
 
-	/*
-	 * Regardless of the value of the AuxReg field, the AIFSR, ADFSR, and
-	 * ACTLR formats could differ across CPUs and therefore would have to
-	 * be trapped for virtualization anyway.
-	 */
-	taint |= check_update_ftr_reg(SYS_ID_MMFR0_EL1, cpu,
+		/*
+		 * Regardless of the value of the AuxReg field, the AIFSR, ADFSR, and
+		 * ACTLR formats could differ across CPUs and therefore would have to
+		 * be trapped for virtualization anyway.
+		 */
+		taint |= check_update_ftr_reg(SYS_ID_MMFR0_EL1, cpu,
 					info->reg_id_mmfr0, boot->reg_id_mmfr0);
-	taint |= check_update_ftr_reg(SYS_ID_MMFR1_EL1, cpu,
+		taint |= check_update_ftr_reg(SYS_ID_MMFR1_EL1, cpu,
 					info->reg_id_mmfr1, boot->reg_id_mmfr1);
-	taint |= check_update_ftr_reg(SYS_ID_MMFR2_EL1, cpu,
+		taint |= check_update_ftr_reg(SYS_ID_MMFR2_EL1, cpu,
 					info->reg_id_mmfr2, boot->reg_id_mmfr2);
-	taint |= check_update_ftr_reg(SYS_ID_MMFR3_EL1, cpu,
+		taint |= check_update_ftr_reg(SYS_ID_MMFR3_EL1, cpu,
 					info->reg_id_mmfr3, boot->reg_id_mmfr3);
-	taint |= check_update_ftr_reg(SYS_ID_PFR0_EL1, cpu,
+		taint |= check_update_ftr_reg(SYS_ID_PFR0_EL1, cpu,
 					info->reg_id_pfr0, boot->reg_id_pfr0);
-	taint |= check_update_ftr_reg(SYS_ID_PFR1_EL1, cpu,
+		taint |= check_update_ftr_reg(SYS_ID_PFR1_EL1, cpu,
 					info->reg_id_pfr1, boot->reg_id_pfr1);
-	taint |= check_update_ftr_reg(SYS_MVFR0_EL1, cpu,
+		taint |= check_update_ftr_reg(SYS_MVFR0_EL1, cpu,
 					info->reg_mvfr0, boot->reg_mvfr0);
-	taint |= check_update_ftr_reg(SYS_MVFR1_EL1, cpu,
+		taint |= check_update_ftr_reg(SYS_MVFR1_EL1, cpu,
 					info->reg_mvfr1, boot->reg_mvfr1);
-	taint |= check_update_ftr_reg(SYS_MVFR2_EL1, cpu,
+		taint |= check_update_ftr_reg(SYS_MVFR2_EL1, cpu,
 					info->reg_mvfr2, boot->reg_mvfr2);
+	}
 
 	/*
 	 * Mismatched CPU features are a recipe for disaster. Don't even
@@ -614,6 +627,49 @@ u64 read_system_reg(u32 id)
 	return regp->sys_val;
 }
 
+/*
+ * __raw_read_system_reg() - Used by a STARTING cpu before cpuinfo is populated.
+ * Read the system register on the current CPU
+ */
+static u64 __raw_read_system_reg(u32 sys_id)
+{
+	switch (sys_id) {
+	case SYS_ID_PFR0_EL1:		return read_cpuid(ID_PFR0_EL1);
+	case SYS_ID_PFR1_EL1:		return read_cpuid(ID_PFR1_EL1);
+	case SYS_ID_DFR0_EL1:		return read_cpuid(ID_DFR0_EL1);
+	case SYS_ID_MMFR0_EL1:		return read_cpuid(ID_MMFR0_EL1);
+	case SYS_ID_MMFR1_EL1:		return read_cpuid(ID_MMFR1_EL1);
+	case SYS_ID_MMFR2_EL1:		return read_cpuid(ID_MMFR2_EL1);
+	case SYS_ID_MMFR3_EL1:		return read_cpuid(ID_MMFR3_EL1);
+	case SYS_ID_ISAR0_EL1:		return read_cpuid(ID_ISAR0_EL1);
+	case SYS_ID_ISAR1_EL1:		return read_cpuid(ID_ISAR1_EL1);
+	case SYS_ID_ISAR2_EL1:		return read_cpuid(ID_ISAR2_EL1);
+	case SYS_ID_ISAR3_EL1:		return read_cpuid(ID_ISAR3_EL1);
+	case SYS_ID_ISAR4_EL1:		return read_cpuid(ID_ISAR4_EL1);
+	case SYS_ID_ISAR5_EL1:		return read_cpuid(ID_ISAR4_EL1);
+	case SYS_MVFR0_EL1:		return read_cpuid(MVFR0_EL1);
+	case SYS_MVFR1_EL1:		return read_cpuid(MVFR1_EL1);
+	case SYS_MVFR2_EL1:		return read_cpuid(MVFR2_EL1);
+
+	case SYS_ID_AA64PFR0_EL1:	return read_cpuid(ID_AA64PFR0_EL1);
+	case SYS_ID_AA64PFR1_EL1:	return read_cpuid(ID_AA64PFR0_EL1);
+	case SYS_ID_AA64DFR0_EL1:	return read_cpuid(ID_AA64DFR0_EL1);
+	case SYS_ID_AA64DFR1_EL1:	return read_cpuid(ID_AA64DFR0_EL1);
+	case SYS_ID_AA64MMFR0_EL1:	return read_cpuid(ID_AA64MMFR0_EL1);
+	case SYS_ID_AA64MMFR1_EL1:	return read_cpuid(ID_AA64MMFR1_EL1);
+	case SYS_ID_AA64MMFR2_EL1:	return read_cpuid(ID_AA64MMFR2_EL1);
+	case SYS_ID_AA64ISAR0_EL1:	return read_cpuid(ID_AA64ISAR0_EL1);
+	case SYS_ID_AA64ISAR1_EL1:	return read_cpuid(ID_AA64ISAR1_EL1);
+
+	case SYS_CNTFRQ_EL0:		return read_cpuid(CNTFRQ_EL0);
+	case SYS_CTR_EL0:		return read_cpuid(CTR_EL0);
+	case SYS_DCZID_EL0:		return read_cpuid(DCZID_EL0);
+	default:
+		BUG();
+		return 0;
+	}
+}
+
 #include <linux/irqchip/arm-gic-v3.h>
 
 static bool
@@ -625,19 +681,24 @@ feature_matches(u64 reg, const struct ar
 }
 
 static bool
-has_cpuid_feature(const struct arm64_cpu_capabilities *entry)
+has_cpuid_feature(const struct arm64_cpu_capabilities *entry, int scope)
 {
 	u64 val;
 
-	val = read_system_reg(entry->sys_reg);
+	WARN_ON(scope == SCOPE_LOCAL_CPU && preemptible());
+	if (scope == SCOPE_SYSTEM)
+		val = read_system_reg(entry->sys_reg);
+	else
+		val = __raw_read_system_reg(entry->sys_reg);
+
 	return feature_matches(val, entry);
 }
 
-static bool has_useable_gicv3_cpuif(const struct arm64_cpu_capabilities *entry)
+static bool has_useable_gicv3_cpuif(const struct arm64_cpu_capabilities *entry, int scope)
 {
 	bool has_sre;
 
-	if (!has_cpuid_feature(entry))
+	if (!has_cpuid_feature(entry, scope))
 		return false;
 
 	has_sre = gic_enable_sre();
@@ -648,7 +709,7 @@ static bool has_useable_gicv3_cpuif(cons
 	return has_sre;
 }
 
-static bool has_no_hw_prefetch(const struct arm64_cpu_capabilities *entry)
+static bool has_no_hw_prefetch(const struct arm64_cpu_capabilities *entry, int __unused)
 {
 	u32 midr = read_cpuid_id();
 	u32 rv_min, rv_max;
@@ -660,7 +721,7 @@ static bool has_no_hw_prefetch(const str
 	return MIDR_IS_CPU_MODEL_RANGE(midr, MIDR_THUNDERX, rv_min, rv_max);
 }
 
-static bool runs_at_el2(const struct arm64_cpu_capabilities *entry)
+static bool runs_at_el2(const struct arm64_cpu_capabilities *entry, int __unused)
 {
 	return is_kernel_in_hyp_mode();
 }
@@ -669,6 +730,7 @@ static const struct arm64_cpu_capabiliti
 	{
 		.desc = "GIC system register CPU interface",
 		.capability = ARM64_HAS_SYSREG_GIC_CPUIF,
+		.def_scope = SCOPE_SYSTEM,
 		.matches = has_useable_gicv3_cpuif,
 		.sys_reg = SYS_ID_AA64PFR0_EL1,
 		.field_pos = ID_AA64PFR0_GIC_SHIFT,
@@ -679,6 +741,7 @@ static const struct arm64_cpu_capabiliti
 	{
 		.desc = "Privileged Access Never",
 		.capability = ARM64_HAS_PAN,
+		.def_scope = SCOPE_SYSTEM,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64MMFR1_EL1,
 		.field_pos = ID_AA64MMFR1_PAN_SHIFT,
@@ -691,6 +754,7 @@ static const struct arm64_cpu_capabiliti
 	{
 		.desc = "LSE atomic instructions",
 		.capability = ARM64_HAS_LSE_ATOMICS,
+		.def_scope = SCOPE_SYSTEM,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64ISAR0_EL1,
 		.field_pos = ID_AA64ISAR0_ATOMICS_SHIFT,
@@ -701,12 +765,14 @@ static const struct arm64_cpu_capabiliti
 	{
 		.desc = "Software prefetching using PRFM",
 		.capability = ARM64_HAS_NO_HW_PREFETCH,
+		.def_scope = SCOPE_SYSTEM,
 		.matches = has_no_hw_prefetch,
 	},
 #ifdef CONFIG_ARM64_UAO
 	{
 		.desc = "User Access Override",
 		.capability = ARM64_HAS_UAO,
+		.def_scope = SCOPE_SYSTEM,
 		.matches = has_cpuid_feature,
 		.sys_reg = SYS_ID_AA64MMFR2_EL1,
 		.field_pos = ID_AA64MMFR2_UAO_SHIFT,
@@ -717,20 +783,33 @@ static const struct arm64_cpu_capabiliti
 #ifdef CONFIG_ARM64_PAN
 	{
 		.capability = ARM64_ALT_PAN_NOT_UAO,
+		.def_scope = SCOPE_SYSTEM,
 		.matches = cpufeature_pan_not_uao,
 	},
 #endif /* CONFIG_ARM64_PAN */
 	{
 		.desc = "Virtualization Host Extensions",
 		.capability = ARM64_HAS_VIRT_HOST_EXTN,
+		.def_scope = SCOPE_SYSTEM,
 		.matches = runs_at_el2,
 	},
+	{
+		.desc = "32-bit EL0 Support",
+		.capability = ARM64_HAS_32BIT_EL0,
+		.def_scope = SCOPE_SYSTEM,
+		.matches = has_cpuid_feature,
+		.sys_reg = SYS_ID_AA64PFR0_EL1,
+		.sign = FTR_UNSIGNED,
+		.field_pos = ID_AA64PFR0_EL0_SHIFT,
+		.min_field_value = ID_AA64PFR0_EL0_32BIT_64BIT,
+	},
 	{},
 };
 
 #define HWCAP_CAP(reg, field, s, min_value, type, cap)	\
 	{							\
 		.desc = #cap,					\
+		.def_scope = SCOPE_SYSTEM,			\
 		.matches = has_cpuid_feature,			\
 		.sys_reg = reg,					\
 		.field_pos = field,				\
@@ -740,7 +819,7 @@ static const struct arm64_cpu_capabiliti
 		.hwcap = cap,					\
 	}
 
-static const struct arm64_cpu_capabilities arm64_hwcaps[] = {
+static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = {
 	HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_AES_SHIFT, FTR_UNSIGNED, 2, CAP_HWCAP, HWCAP_PMULL),
 	HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_AES_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_AES),
 	HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_SHA1_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_SHA1),
@@ -751,6 +830,10 @@ static const struct arm64_cpu_capabiliti
 	HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_FP_SHIFT, FTR_SIGNED, 1, CAP_HWCAP, HWCAP_FPHP),
 	HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_ASIMD_SHIFT, FTR_SIGNED, 0, CAP_HWCAP, HWCAP_ASIMD),
 	HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_ASIMD_SHIFT, FTR_SIGNED, 1, CAP_HWCAP, HWCAP_ASIMDHP),
+	{},
+};
+
+static const struct arm64_cpu_capabilities compat_elf_hwcaps[] = {
 #ifdef CONFIG_COMPAT
 	HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_AES_SHIFT, FTR_UNSIGNED, 2, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_PMULL),
 	HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_AES_SHIFT, FTR_UNSIGNED, 1, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_AES),
@@ -761,7 +844,7 @@ static const struct arm64_cpu_capabiliti
 	{},
 };
 
-static void __init cap_set_hwcap(const struct arm64_cpu_capabilities *cap)
+static void __init cap_set_elf_hwcap(const struct arm64_cpu_capabilities *cap)
 {
 	switch (cap->hwcap_type) {
 	case CAP_HWCAP:
@@ -782,7 +865,7 @@ static void __init cap_set_hwcap(const s
 }
 
 /* Check if we have a particular HWCAP enabled */
-static bool __maybe_unused cpus_have_hwcap(const struct arm64_cpu_capabilities *cap)
+static bool cpus_have_elf_hwcap(const struct arm64_cpu_capabilities *cap)
 {
 	bool rc;
 
@@ -806,28 +889,23 @@ static bool __maybe_unused cpus_have_hwc
 	return rc;
 }
 
-static void __init setup_cpu_hwcaps(void)
+static void __init setup_elf_hwcaps(const struct arm64_cpu_capabilities *hwcaps)
 {
-	int i;
-	const struct arm64_cpu_capabilities *hwcaps = arm64_hwcaps;
-
-	for (i = 0; hwcaps[i].matches; i++)
-		if (hwcaps[i].matches(&hwcaps[i]))
-			cap_set_hwcap(&hwcaps[i]);
+	for (; hwcaps->matches; hwcaps++)
+		if (hwcaps->matches(hwcaps, hwcaps->def_scope))
+			cap_set_elf_hwcap(hwcaps);
 }
 
 void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
 			    const char *info)
 {
-	int i;
-
-	for (i = 0; caps[i].matches; i++) {
-		if (!caps[i].matches(&caps[i]))
+	for (; caps->matches; caps++) {
+		if (!caps->matches(caps, caps->def_scope))
 			continue;
 
-		if (!cpus_have_cap(caps[i].capability) && caps[i].desc)
-			pr_info("%s %s\n", info, caps[i].desc);
-		cpus_set_cap(caps[i].capability);
+		if (!cpus_have_cap(caps->capability) && caps->desc)
+			pr_info("%s %s\n", info, caps->desc);
+		cpus_set_cap(caps->capability);
 	}
 }
 
@@ -838,11 +916,9 @@ void update_cpu_capabilities(const struc
 static void __init
 enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps)
 {
-	int i;
-
-	for (i = 0; caps[i].matches; i++)
-		if (caps[i].enable && cpus_have_cap(caps[i].capability))
-			on_each_cpu(caps[i].enable, NULL, true);
+	for (; caps->matches; caps++)
+		if (caps->enable && cpus_have_cap(caps->capability))
+			on_each_cpu(caps->enable, NULL, true);
 }
 
 /*
@@ -861,54 +937,45 @@ static inline void set_sys_caps_initiali
 }
 
 /*
- * __raw_read_system_reg() - Used by a STARTING cpu before cpuinfo is populated.
+ * Check for CPU features that are used in early boot
+ * based on the Boot CPU value.
  */
-static u64 __raw_read_system_reg(u32 sys_id)
+static void check_early_cpu_features(void)
 {
-	switch (sys_id) {
-	case SYS_ID_PFR0_EL1:		return read_cpuid(ID_PFR0_EL1);
-	case SYS_ID_PFR1_EL1:		return read_cpuid(ID_PFR1_EL1);
-	case SYS_ID_DFR0_EL1:		return read_cpuid(ID_DFR0_EL1);
-	case SYS_ID_MMFR0_EL1:		return read_cpuid(ID_MMFR0_EL1);
-	case SYS_ID_MMFR1_EL1:		return read_cpuid(ID_MMFR1_EL1);
-	case SYS_ID_MMFR2_EL1:		return read_cpuid(ID_MMFR2_EL1);
-	case SYS_ID_MMFR3_EL1:		return read_cpuid(ID_MMFR3_EL1);
-	case SYS_ID_ISAR0_EL1:		return read_cpuid(ID_ISAR0_EL1);
-	case SYS_ID_ISAR1_EL1:		return read_cpuid(ID_ISAR1_EL1);
-	case SYS_ID_ISAR2_EL1:		return read_cpuid(ID_ISAR2_EL1);
-	case SYS_ID_ISAR3_EL1:		return read_cpuid(ID_ISAR3_EL1);
-	case SYS_ID_ISAR4_EL1:		return read_cpuid(ID_ISAR4_EL1);
-	case SYS_ID_ISAR5_EL1:		return read_cpuid(ID_ISAR4_EL1);
-	case SYS_MVFR0_EL1:		return read_cpuid(MVFR0_EL1);
-	case SYS_MVFR1_EL1:		return read_cpuid(MVFR1_EL1);
-	case SYS_MVFR2_EL1:		return read_cpuid(MVFR2_EL1);
+	verify_cpu_run_el();
+	verify_cpu_asid_bits();
+}
 
-	case SYS_ID_AA64PFR0_EL1:	return read_cpuid(ID_AA64PFR0_EL1);
-	case SYS_ID_AA64PFR1_EL1:	return read_cpuid(ID_AA64PFR0_EL1);
-	case SYS_ID_AA64DFR0_EL1:	return read_cpuid(ID_AA64DFR0_EL1);
-	case SYS_ID_AA64DFR1_EL1:	return read_cpuid(ID_AA64DFR0_EL1);
-	case SYS_ID_AA64MMFR0_EL1:	return read_cpuid(ID_AA64MMFR0_EL1);
-	case SYS_ID_AA64MMFR1_EL1:	return read_cpuid(ID_AA64MMFR1_EL1);
-	case SYS_ID_AA64MMFR2_EL1:	return read_cpuid(ID_AA64MMFR2_EL1);
-	case SYS_ID_AA64ISAR0_EL1:	return read_cpuid(ID_AA64ISAR0_EL1);
-	case SYS_ID_AA64ISAR1_EL1:	return read_cpuid(ID_AA64ISAR1_EL1);
+static void
+verify_local_elf_hwcaps(const struct arm64_cpu_capabilities *caps)
+{
 
-	case SYS_CNTFRQ_EL0:		return read_cpuid(CNTFRQ_EL0);
-	case SYS_CTR_EL0:		return read_cpuid(CTR_EL0);
-	case SYS_DCZID_EL0:		return read_cpuid(DCZID_EL0);
-	default:
-		BUG();
-		return 0;
-	}
+	for (; caps->matches; caps++)
+		if (cpus_have_elf_hwcap(caps) && !caps->matches(caps, SCOPE_LOCAL_CPU)) {
+			pr_crit("CPU%d: missing HWCAP: %s\n",
+					smp_processor_id(), caps->desc);
+			cpu_die_early();
+		}
 }
 
-/*
- * Check for CPU features that are used in early boot
- * based on the Boot CPU value.
- */
-static void check_early_cpu_features(void)
+static void
+verify_local_cpu_features(const struct arm64_cpu_capabilities *caps)
 {
-	verify_cpu_asid_bits();
+	for (; caps->matches; caps++) {
+		if (!cpus_have_cap(caps->capability))
+			continue;
+		/*
+		 * If the new CPU misses an advertised feature, we cannot proceed
+		 * further, park the cpu.
+		 */
+		if (!caps->matches(caps, SCOPE_LOCAL_CPU)) {
+			pr_crit("CPU%d: missing feature: %s\n",
+					smp_processor_id(), caps->desc);
+			cpu_die_early();
+		}
+		if (caps->enable)
+			caps->enable(NULL);
+	}
 }
 
 /*
@@ -921,8 +988,6 @@ static void check_early_cpu_features(voi
  */
 void verify_local_cpu_capabilities(void)
 {
-	int i;
-	const struct arm64_cpu_capabilities *caps;
 
 	check_early_cpu_features();
 
@@ -933,32 +998,11 @@ void verify_local_cpu_capabilities(void)
 	if (!sys_caps_initialised)
 		return;
 
-	caps = arm64_features;
-	for (i = 0; caps[i].matches; i++) {
-		if (!cpus_have_cap(caps[i].capability) || !caps[i].sys_reg)
-			continue;
-		/*
-		 * If the new CPU misses an advertised feature, we cannot proceed
-		 * further, park the cpu.
-		 */
-		if (!feature_matches(__raw_read_system_reg(caps[i].sys_reg), &caps[i])) {
-			pr_crit("CPU%d: missing feature: %s\n",
-					smp_processor_id(), caps[i].desc);
-			cpu_die_early();
-		}
-		if (caps[i].enable)
-			caps[i].enable(NULL);
-	}
-
-	for (i = 0, caps = arm64_hwcaps; caps[i].matches; i++) {
-		if (!cpus_have_hwcap(&caps[i]))
-			continue;
-		if (!feature_matches(__raw_read_system_reg(caps[i].sys_reg), &caps[i])) {
-			pr_crit("CPU%d: missing HWCAP: %s\n",
-					smp_processor_id(), caps[i].desc);
-			cpu_die_early();
-		}
-	}
+	verify_local_cpu_errata();
+	verify_local_cpu_features(arm64_features);
+	verify_local_elf_hwcaps(arm64_elf_hwcaps);
+	if (system_supports_32bit_el0())
+		verify_local_elf_hwcaps(compat_elf_hwcaps);
 }
 
 static void __init setup_feature_capabilities(void)
@@ -967,6 +1011,24 @@ static void __init setup_feature_capabil
 	enable_cpu_capabilities(arm64_features);
 }
 
+/*
+ * Check if the current CPU has a given feature capability.
+ * Should be called from non-preemptible context.
+ */
+bool this_cpu_has_cap(unsigned int cap)
+{
+	const struct arm64_cpu_capabilities *caps;
+
+	if (WARN_ON(preemptible()))
+		return false;
+
+	for (caps = arm64_features; caps->desc; caps++)
+		if (caps->capability == cap && caps->matches)
+			return caps->matches(caps, SCOPE_LOCAL_CPU);
+
+	return false;
+}
+
 void __init setup_cpu_features(void)
 {
 	u32 cwg;
@@ -974,7 +1036,10 @@ void __init setup_cpu_features(void)
 
 	/* Set the CPU feature capabilies */
 	setup_feature_capabilities();
-	setup_cpu_hwcaps();
+	setup_elf_hwcaps(arm64_elf_hwcaps);
+
+	if (system_supports_32bit_el0())
+		setup_elf_hwcaps(compat_elf_hwcaps);
 
 	/* Advertise that we have computed the system capabilities */
 	set_sys_caps_initialised();
@@ -993,7 +1058,7 @@ void __init setup_cpu_features(void)
 }
 
 static bool __maybe_unused
-cpufeature_pan_not_uao(const struct arm64_cpu_capabilities *entry)
+cpufeature_pan_not_uao(const struct arm64_cpu_capabilities *entry, int __unused)
 {
 	return (cpus_have_cap(ARM64_HAS_PAN) && !cpus_have_cap(ARM64_HAS_UAO));
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kernel/cpuidle.c linux-libre-4.7-gnu/arch/arm64/kernel/cpuidle.c
--- linux-libre-4.6-gnu/arch/arm64/kernel/cpuidle.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kernel/cpuidle.c	2016-07-24 15:23:50.000000000 -0400
@@ -19,7 +19,8 @@ int __init arm_cpuidle_init(unsigned int
 {
 	int ret = -EOPNOTSUPP;
 
-	if (cpu_ops[cpu] && cpu_ops[cpu]->cpu_init_idle)
+	if (cpu_ops[cpu] && cpu_ops[cpu]->cpu_suspend &&
+			cpu_ops[cpu]->cpu_init_idle)
 		ret = cpu_ops[cpu]->cpu_init_idle(cpu);
 
 	return ret;
@@ -36,11 +37,5 @@ int arm_cpuidle_suspend(int index)
 {
 	int cpu = smp_processor_id();
 
-	/*
-	 * If cpu_ops have not been registered or suspend
-	 * has not been initialized, cpu_suspend call fails early.
-	 */
-	if (!cpu_ops[cpu] || !cpu_ops[cpu]->cpu_suspend)
-		return -EOPNOTSUPP;
 	return cpu_ops[cpu]->cpu_suspend(index);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kernel/cpuinfo.c linux-libre-4.7-gnu/arch/arm64/kernel/cpuinfo.c
--- linux-libre-4.6-gnu/arch/arm64/kernel/cpuinfo.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kernel/cpuinfo.c	2016-07-24 15:23:50.000000000 -0400
@@ -22,6 +22,8 @@
 
 #include <linux/bitops.h>
 #include <linux/bug.h>
+#include <linux/compat.h>
+#include <linux/elf.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/personality.h>
@@ -87,7 +89,8 @@ static const char *const compat_hwcap_st
 	"idivt",
 	"vfpd32",
 	"lpae",
-	"evtstrm"
+	"evtstrm",
+	NULL
 };
 
 static const char *const compat_hwcap2_str[] = {
@@ -103,6 +106,7 @@ static const char *const compat_hwcap2_s
 static int c_show(struct seq_file *m, void *v)
 {
 	int i, j;
+	bool compat = personality(current->personality) == PER_LINUX32;
 
 	for_each_online_cpu(i) {
 		struct cpuinfo_arm64 *cpuinfo = &per_cpu(cpu_data, i);
@@ -114,6 +118,9 @@ static int c_show(struct seq_file *m, vo
 		 * "processor".  Give glibc what it expects.
 		 */
 		seq_printf(m, "processor\t: %d\n", i);
+		if (compat)
+			seq_printf(m, "model name\t: ARMv8 Processor rev %d (%s)\n",
+				   MIDR_REVISION(midr), COMPAT_ELF_PLATFORM);
 
 		seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
 			   loops_per_jiffy / (500000UL/HZ),
@@ -126,7 +133,7 @@ static int c_show(struct seq_file *m, vo
 		 * software which does already (at least for 32-bit).
 		 */
 		seq_puts(m, "Features\t:");
-		if (personality(current->personality) == PER_LINUX32) {
+		if (compat) {
 #ifdef CONFIG_COMPAT
 			for (j = 0; compat_hwcap_str[j]; j++)
 				if (compat_elf_hwcap & (1 << j))
@@ -216,23 +223,26 @@ static void __cpuinfo_store_cpu(struct c
 	info->reg_id_aa64pfr0 = read_cpuid(ID_AA64PFR0_EL1);
 	info->reg_id_aa64pfr1 = read_cpuid(ID_AA64PFR1_EL1);
 
-	info->reg_id_dfr0 = read_cpuid(ID_DFR0_EL1);
-	info->reg_id_isar0 = read_cpuid(ID_ISAR0_EL1);
-	info->reg_id_isar1 = read_cpuid(ID_ISAR1_EL1);
-	info->reg_id_isar2 = read_cpuid(ID_ISAR2_EL1);
-	info->reg_id_isar3 = read_cpuid(ID_ISAR3_EL1);
-	info->reg_id_isar4 = read_cpuid(ID_ISAR4_EL1);
-	info->reg_id_isar5 = read_cpuid(ID_ISAR5_EL1);
-	info->reg_id_mmfr0 = read_cpuid(ID_MMFR0_EL1);
-	info->reg_id_mmfr1 = read_cpuid(ID_MMFR1_EL1);
-	info->reg_id_mmfr2 = read_cpuid(ID_MMFR2_EL1);
-	info->reg_id_mmfr3 = read_cpuid(ID_MMFR3_EL1);
-	info->reg_id_pfr0 = read_cpuid(ID_PFR0_EL1);
-	info->reg_id_pfr1 = read_cpuid(ID_PFR1_EL1);
+	/* Update the 32bit ID registers only if AArch32 is implemented */
+	if (id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0)) {
+		info->reg_id_dfr0 = read_cpuid(ID_DFR0_EL1);
+		info->reg_id_isar0 = read_cpuid(ID_ISAR0_EL1);
+		info->reg_id_isar1 = read_cpuid(ID_ISAR1_EL1);
+		info->reg_id_isar2 = read_cpuid(ID_ISAR2_EL1);
+		info->reg_id_isar3 = read_cpuid(ID_ISAR3_EL1);
+		info->reg_id_isar4 = read_cpuid(ID_ISAR4_EL1);
+		info->reg_id_isar5 = read_cpuid(ID_ISAR5_EL1);
+		info->reg_id_mmfr0 = read_cpuid(ID_MMFR0_EL1);
+		info->reg_id_mmfr1 = read_cpuid(ID_MMFR1_EL1);
+		info->reg_id_mmfr2 = read_cpuid(ID_MMFR2_EL1);
+		info->reg_id_mmfr3 = read_cpuid(ID_MMFR3_EL1);
+		info->reg_id_pfr0 = read_cpuid(ID_PFR0_EL1);
+		info->reg_id_pfr1 = read_cpuid(ID_PFR1_EL1);
 
-	info->reg_mvfr0 = read_cpuid(MVFR0_EL1);
-	info->reg_mvfr1 = read_cpuid(MVFR1_EL1);
-	info->reg_mvfr2 = read_cpuid(MVFR2_EL1);
+		info->reg_mvfr0 = read_cpuid(MVFR0_EL1);
+		info->reg_mvfr1 = read_cpuid(MVFR1_EL1);
+		info->reg_mvfr2 = read_cpuid(MVFR2_EL1);
+	}
 
 	cpuinfo_detect_icache_policy(info);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kernel/debug-monitors.c linux-libre-4.7-gnu/arch/arm64/kernel/debug-monitors.c
--- linux-libre-4.6-gnu/arch/arm64/kernel/debug-monitors.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kernel/debug-monitors.c	2016-07-24 15:23:50.000000000 -0400
@@ -135,9 +135,8 @@ static void clear_os_lock(void *unused)
 static int os_lock_notify(struct notifier_block *self,
 				    unsigned long action, void *data)
 {
-	int cpu = (unsigned long)data;
 	if ((action & ~CPU_TASKS_FROZEN) == CPU_ONLINE)
-		smp_call_function_single(cpu, clear_os_lock, NULL, 1);
+		clear_os_lock(NULL);
 	return NOTIFY_OK;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kernel/efi.c linux-libre-4.7-gnu/arch/arm64/kernel/efi.c
--- linux-libre-4.6-gnu/arch/arm64/kernel/efi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kernel/efi.c	2016-07-24 15:23:50.000000000 -0400
@@ -17,22 +17,51 @@
 
 #include <asm/efi.h>
 
-int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md)
+/*
+ * Only regions of type EFI_RUNTIME_SERVICES_CODE need to be
+ * executable, everything else can be mapped with the XN bits
+ * set. Also take the new (optional) RO/XP bits into account.
+ */
+static __init pteval_t create_mapping_protection(efi_memory_desc_t *md)
 {
-	pteval_t prot_val;
+	u64 attr = md->attribute;
+	u32 type = md->type;
 
-	/*
-	 * Only regions of type EFI_RUNTIME_SERVICES_CODE need to be
-	 * executable, everything else can be mapped with the XN bits
-	 * set.
-	 */
-	if ((md->attribute & EFI_MEMORY_WB) == 0)
-		prot_val = PROT_DEVICE_nGnRE;
-	else if (md->type == EFI_RUNTIME_SERVICES_CODE ||
-		 !PAGE_ALIGNED(md->phys_addr))
-		prot_val = pgprot_val(PAGE_KERNEL_EXEC);
-	else
-		prot_val = pgprot_val(PAGE_KERNEL);
+	if (type == EFI_MEMORY_MAPPED_IO)
+		return PROT_DEVICE_nGnRE;
+
+	if (WARN_ONCE(!PAGE_ALIGNED(md->phys_addr),
+		      "UEFI Runtime regions are not aligned to 64 KB -- buggy firmware?"))
+		/*
+		 * If the region is not aligned to the page size of the OS, we
+		 * can not use strict permissions, since that would also affect
+		 * the mapping attributes of the adjacent regions.
+		 */
+		return pgprot_val(PAGE_KERNEL_EXEC);
+
+	/* R-- */
+	if ((attr & (EFI_MEMORY_XP | EFI_MEMORY_RO)) ==
+	    (EFI_MEMORY_XP | EFI_MEMORY_RO))
+		return pgprot_val(PAGE_KERNEL_RO);
+
+	/* R-X */
+	if (attr & EFI_MEMORY_RO)
+		return pgprot_val(PAGE_KERNEL_ROX);
+
+	/* RW- */
+	if (attr & EFI_MEMORY_XP || type != EFI_RUNTIME_SERVICES_CODE)
+		return pgprot_val(PAGE_KERNEL);
+
+	/* RWX */
+	return pgprot_val(PAGE_KERNEL_EXEC);
+}
+
+/* we will fill this structure from the stub, so don't put it in .bss */
+struct screen_info screen_info __section(.data);
+
+int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md)
+{
+	pteval_t prot_val = create_mapping_protection(md);
 
 	create_pgd_mapping(mm, md->phys_addr, md->virt_addr,
 			   md->num_pages << EFI_PAGE_SHIFT,
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kernel/efi-entry.S linux-libre-4.7-gnu/arch/arm64/kernel/efi-entry.S
--- linux-libre-4.6-gnu/arch/arm64/kernel/efi-entry.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kernel/efi-entry.S	2016-07-24 15:23:50.000000000 -0400
@@ -62,7 +62,7 @@ ENTRY(entry)
 	 */
 	mov	x20, x0		// DTB address
 	ldr	x0, [sp, #16]	// relocated _text address
-	movz	x21, #:abs_g0:stext_offset
+	ldr	w21, =stext_offset
 	add	x21, x0, x21
 
 	/*
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kernel/entry.S linux-libre-4.7-gnu/arch/arm64/kernel/entry.S
--- linux-libre-4.6-gnu/arch/arm64/kernel/entry.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kernel/entry.S	2016-07-24 15:23:50.000000000 -0400
@@ -28,6 +28,7 @@
 #include <asm/errno.h>
 #include <asm/esr.h>
 #include <asm/irq.h>
+#include <asm/memory.h>
 #include <asm/thread_info.h>
 #include <asm/unistd.h>
 
@@ -97,7 +98,14 @@
 	mov	x29, xzr			// fp pointed to user-space
 	.else
 	add	x21, sp, #S_FRAME_SIZE
-	.endif
+	get_thread_info tsk
+	/* Save the task's original addr_limit and set USER_DS (TASK_SIZE_64) */
+	ldr	x20, [tsk, #TI_ADDR_LIMIT]
+	str	x20, [sp, #S_ORIG_ADDR_LIMIT]
+	mov	x20, #TASK_SIZE_64
+	str	x20, [tsk, #TI_ADDR_LIMIT]
+	ALTERNATIVE(nop, SET_PSTATE_UAO(0), ARM64_HAS_UAO, CONFIG_ARM64_UAO)
+	.endif /* \el == 0 */
 	mrs	x22, elr_el1
 	mrs	x23, spsr_el1
 	stp	lr, x21, [sp, #S_LR]
@@ -128,6 +136,14 @@
 	.endm
 
 	.macro	kernel_exit, el
+	.if	\el != 0
+	/* Restore the task's original addr_limit. */
+	ldr	x20, [sp, #S_ORIG_ADDR_LIMIT]
+	str	x20, [tsk, #TI_ADDR_LIMIT]
+
+	/* No need to restore UAO, it will be restored from SPSR_EL1 */
+	.endif
+
 	ldp	x21, x22, [sp, #S_PC]		// load ELR, SPSR
 	.if	\el == 0
 	ct_user_enter
@@ -406,7 +422,6 @@ el1_irq:
 	bl	trace_hardirqs_off
 #endif
 
-	get_thread_info tsk
 	irq_handler
 
 #ifdef CONFIG_PREEMPT
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kernel/head.S linux-libre-4.7-gnu/arch/arm64/kernel/head.S
--- linux-libre-4.6-gnu/arch/arm64/kernel/head.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kernel/head.S	2016-07-24 15:23:50.000000000 -0400
@@ -25,6 +25,7 @@
 #include <linux/irqchip/arm-gic-v3.h>
 
 #include <asm/assembler.h>
+#include <asm/boot.h>
 #include <asm/ptrace.h>
 #include <asm/asm-offsets.h>
 #include <asm/cache.h>
@@ -51,9 +52,6 @@
 #error TEXT_OFFSET must be less than 2MB
 #endif
 
-#define KERNEL_START	_text
-#define KERNEL_END	_end
-
 /*
  * Kernel startup entry point.
  * ---------------------------
@@ -102,8 +100,6 @@ _head:
 #endif
 
 #ifdef CONFIG_EFI
-	.globl	__efistub_stext_offset
-	.set	__efistub_stext_offset, stext - _head
 	.align 3
 pe_header:
 	.ascii	"PE"
@@ -123,11 +119,11 @@ optional_header:
 	.short	0x20b				// PE32+ format
 	.byte	0x02				// MajorLinkerVersion
 	.byte	0x14				// MinorLinkerVersion
-	.long	_end - stext			// SizeOfCode
+	.long	_end - efi_header_end		// SizeOfCode
 	.long	0				// SizeOfInitializedData
 	.long	0				// SizeOfUninitializedData
 	.long	__efistub_entry - _head		// AddressOfEntryPoint
-	.long	__efistub_stext_offset		// BaseOfCode
+	.long	efi_header_end - _head		// BaseOfCode
 
 extra_header_fields:
 	.quad	0				// ImageBase
@@ -144,7 +140,7 @@ extra_header_fields:
 	.long	_end - _head			// SizeOfImage
 
 	// Everything before the kernel image is considered part of the header
-	.long	__efistub_stext_offset		// SizeOfHeaders
+	.long	efi_header_end - _head		// SizeOfHeaders
 	.long	0				// CheckSum
 	.short	0xa				// Subsystem (EFI application)
 	.short	0				// DllCharacteristics
@@ -188,10 +184,10 @@ section_table:
 	.byte	0
 	.byte	0
 	.byte	0        		// end of 0 padding of section name
-	.long	_end - stext		// VirtualSize
-	.long	__efistub_stext_offset	// VirtualAddress
-	.long	_edata - stext		// SizeOfRawData
-	.long	__efistub_stext_offset	// PointerToRawData
+	.long	_end - efi_header_end	// VirtualSize
+	.long	efi_header_end - _head	// VirtualAddress
+	.long	_edata - efi_header_end	// SizeOfRawData
+	.long	efi_header_end - _head	// PointerToRawData
 
 	.long	0		// PointerToRelocations (0 for executables)
 	.long	0		// PointerToLineNumbers (0 for executables)
@@ -200,20 +196,23 @@ section_table:
 	.long	0xe0500020	// Characteristics (section flags)
 
 	/*
-	 * EFI will load stext onwards at the 4k section alignment
+	 * EFI will load .text onwards at the 4k section alignment
 	 * described in the PE/COFF header. To ensure that instruction
 	 * sequences using an adrp and a :lo12: immediate will function
-	 * correctly at this alignment, we must ensure that stext is
+	 * correctly at this alignment, we must ensure that .text is
 	 * placed at a 4k boundary in the Image to begin with.
 	 */
 	.align 12
+efi_header_end:
 #endif
 
+	__INIT
+
 ENTRY(stext)
 	bl	preserve_boot_args
 	bl	el2_setup			// Drop to EL1, w20=cpu_boot_mode
-	mov	x23, xzr			// KASLR offset, defaults to 0
 	adrp	x24, __PHYS_OFFSET
+	and	x23, x24, MIN_KIMG_ALIGN - 1	// KASLR offset, defaults to 0
 	bl	set_cpu_boot_mode_flag
 	bl	__create_page_tables		// x25=TTBR0, x26=TTBR1
 	/*
@@ -222,13 +221,11 @@ ENTRY(stext)
 	 * On return, the CPU will be ready for the MMU to be turned on and
 	 * the TCR will have been set.
 	 */
-	ldr	x27, 0f				// address to jump to after
+	bl	__cpu_setup			// initialise processor
+	adr_l	x27, __primary_switch		// address to jump to after
 						// MMU has been enabled
-	adr_l	lr, __enable_mmu		// return (PIC) address
-	b	__cpu_setup			// initialise processor
+	b	__enable_mmu
 ENDPROC(stext)
-	.align	3
-0:	.quad	__mmap_switched - (_head - TEXT_OFFSET) + KIMAGE_VADDR
 
 /*
  * Preserve the arguments passed by the bootloader in x0 .. x3
@@ -338,7 +335,7 @@ __create_page_tables:
 	cmp	x0, x6
 	b.lo	1b
 
-	ldr	x7, =SWAPPER_MM_MMUFLAGS
+	mov	x7, SWAPPER_MM_MMUFLAGS
 
 	/*
 	 * Create the identity mapping.
@@ -394,12 +391,13 @@ __create_page_tables:
 	 * Map the kernel image (starting with PHYS_OFFSET).
 	 */
 	mov	x0, x26				// swapper_pg_dir
-	ldr	x5, =KIMAGE_VADDR
+	mov_q	x5, KIMAGE_VADDR + TEXT_OFFSET	// compile time __va(_text)
 	add	x5, x5, x23			// add KASLR displacement
 	create_pgd_entry x0, x5, x3, x6
-	ldr	w6, kernel_img_size
-	add	x6, x6, x5
-	mov	x3, x24				// phys offset
+	adrp	x6, _end			// runtime __pa(_end)
+	adrp	x3, _text			// runtime __pa(_text)
+	sub	x6, x6, x3			// _end - _text
+	add	x6, x6, x5			// runtime __va(_end)
 	create_block_map x0, x7, x3, x5, x6
 
 	/*
@@ -414,16 +412,13 @@ __create_page_tables:
 
 	ret	x28
 ENDPROC(__create_page_tables)
-
-kernel_img_size:
-	.long	_end - (_head - TEXT_OFFSET)
 	.ltorg
 
 /*
  * The following fragment of code is executed with the MMU enabled.
  */
 	.set	initial_sp, init_thread_union + THREAD_START_SP
-__mmap_switched:
+__primary_switched:
 	mov	x28, lr				// preserve LR
 	adr_l	x8, vectors			// load VBAR_EL1 with virtual
 	msr	vbar_el1, x8			// vector table address
@@ -437,44 +432,6 @@ __mmap_switched:
 	bl	__pi_memset
 	dsb	ishst				// Make zero page visible to PTW
 
-#ifdef CONFIG_RELOCATABLE
-
-	/*
-	 * Iterate over each entry in the relocation table, and apply the
-	 * relocations in place.
-	 */
-	adr_l	x8, __dynsym_start		// start of symbol table
-	adr_l	x9, __reloc_start		// start of reloc table
-	adr_l	x10, __reloc_end		// end of reloc table
-
-0:	cmp	x9, x10
-	b.hs	2f
-	ldp	x11, x12, [x9], #24
-	ldr	x13, [x9, #-8]
-	cmp	w12, #R_AARCH64_RELATIVE
-	b.ne	1f
-	add	x13, x13, x23			// relocate
-	str	x13, [x11, x23]
-	b	0b
-
-1:	cmp	w12, #R_AARCH64_ABS64
-	b.ne	0b
-	add	x12, x12, x12, lsl #1		// symtab offset: 24x top word
-	add	x12, x8, x12, lsr #(32 - 3)	// ... shifted into bottom word
-	ldrsh	w14, [x12, #6]			// Elf64_Sym::st_shndx
-	ldr	x15, [x12, #8]			// Elf64_Sym::st_value
-	cmp	w14, #-0xf			// SHN_ABS (0xfff1) ?
-	add	x14, x15, x23			// relocate
-	csel	x15, x14, x15, ne
-	add	x15, x13, x15
-	str	x15, [x11, x23]
-	b	0b
-
-2:	adr_l	x8, kimage_vaddr		// make relocated kimage_vaddr
-	dc	cvac, x8			// value visible to secondaries
-	dsb	sy				// with MMU off
-#endif
-
 	adr_l	sp, initial_sp, x4
 	mov	x4, sp
 	and	x4, x4, #~(THREAD_SIZE - 1)
@@ -490,17 +447,19 @@ __mmap_switched:
 	bl	kasan_early_init
 #endif
 #ifdef CONFIG_RANDOMIZE_BASE
-	cbnz	x23, 0f				// already running randomized?
+	tst	x23, ~(MIN_KIMG_ALIGN - 1)	// already running randomized?
+	b.ne	0f
 	mov	x0, x21				// pass FDT address in x0
+	mov	x1, x23				// pass modulo offset in x1
 	bl	kaslr_early_init		// parse FDT for KASLR options
 	cbz	x0, 0f				// KASLR disabled? just proceed
-	mov	x23, x0				// record KASLR offset
+	orr	x23, x23, x0			// record KASLR offset
 	ret	x28				// we must enable KASLR, return
 						// to __enable_mmu()
 0:
 #endif
 	b	start_kernel
-ENDPROC(__mmap_switched)
+ENDPROC(__primary_switched)
 
 /*
  * end early head section, begin head code that is also used for
@@ -650,7 +609,7 @@ ENDPROC(el2_setup)
  * Sets the __boot_cpu_mode flag depending on the CPU boot mode passed
  * in x20. See arch/arm64/include/asm/virt.h for more info.
  */
-ENTRY(set_cpu_boot_mode_flag)
+set_cpu_boot_mode_flag:
 	adr_l	x1, __boot_cpu_mode
 	cmp	w20, #BOOT_CPU_MODE_EL2
 	b.ne	1f
@@ -683,7 +642,7 @@ ENTRY(secondary_holding_pen)
 	bl	el2_setup			// Drop to EL1, w20=cpu_boot_mode
 	bl	set_cpu_boot_mode_flag
 	mrs	x0, mpidr_el1
-	ldr     x1, =MPIDR_HWID_BITMASK
+	mov_q	x1, MPIDR_HWID_BITMASK
 	and	x0, x0, x1
 	adr_l	x3, secondary_holding_pen_release
 pen:	ldr	x4, [x3]
@@ -703,7 +662,7 @@ ENTRY(secondary_entry)
 	b	secondary_startup
 ENDPROC(secondary_entry)
 
-ENTRY(secondary_startup)
+secondary_startup:
 	/*
 	 * Common entry point for secondary CPUs.
 	 */
@@ -711,14 +670,11 @@ ENTRY(secondary_startup)
 	adrp	x26, swapper_pg_dir
 	bl	__cpu_setup			// initialise processor
 
-	ldr	x8, kimage_vaddr
-	ldr	w9, 0f
-	sub	x27, x8, w9, sxtw		// address to jump to after enabling the MMU
+	adr_l	x27, __secondary_switch		// address to jump to after enabling the MMU
 	b	__enable_mmu
 ENDPROC(secondary_startup)
-0:	.long	(_text - TEXT_OFFSET) - __secondary_switched
 
-ENTRY(__secondary_switched)
+__secondary_switched:
 	adr_l	x5, vectors
 	msr	vbar_el1, x5
 	isb
@@ -768,7 +724,7 @@ ENTRY(__early_cpu_boot_status)
  * If it isn't, park the CPU
  */
 	.section	".idmap.text", "ax"
-__enable_mmu:
+ENTRY(__enable_mmu)
 	mrs	x22, sctlr_el1			// preserve old SCTLR_EL1 value
 	mrs	x1, ID_AA64MMFR0_EL1
 	ubfx	x2, x1, #ID_AA64MMFR0_TGRAN_SHIFT, 4
@@ -806,7 +762,6 @@ __enable_mmu:
 	ic	iallu				// flush instructions fetched
 	dsb	nsh				// via old mapping
 	isb
-	add	x27, x27, x23			// relocated __mmap_switched
 #endif
 	br	x27
 ENDPROC(__enable_mmu)
@@ -819,3 +774,53 @@ __no_granule_support:
 	wfi
 	b 1b
 ENDPROC(__no_granule_support)
+
+__primary_switch:
+#ifdef CONFIG_RELOCATABLE
+	/*
+	 * Iterate over each entry in the relocation table, and apply the
+	 * relocations in place.
+	 */
+	ldr	w8, =__dynsym_offset		// offset to symbol table
+	ldr	w9, =__rela_offset		// offset to reloc table
+	ldr	w10, =__rela_size		// size of reloc table
+
+	mov_q	x11, KIMAGE_VADDR		// default virtual offset
+	add	x11, x11, x23			// actual virtual offset
+	add	x8, x8, x11			// __va(.dynsym)
+	add	x9, x9, x11			// __va(.rela)
+	add	x10, x9, x10			// __va(.rela) + sizeof(.rela)
+
+0:	cmp	x9, x10
+	b.hs	2f
+	ldp	x11, x12, [x9], #24
+	ldr	x13, [x9, #-8]
+	cmp	w12, #R_AARCH64_RELATIVE
+	b.ne	1f
+	add	x13, x13, x23			// relocate
+	str	x13, [x11, x23]
+	b	0b
+
+1:	cmp	w12, #R_AARCH64_ABS64
+	b.ne	0b
+	add	x12, x12, x12, lsl #1		// symtab offset: 24x top word
+	add	x12, x8, x12, lsr #(32 - 3)	// ... shifted into bottom word
+	ldrsh	w14, [x12, #6]			// Elf64_Sym::st_shndx
+	ldr	x15, [x12, #8]			// Elf64_Sym::st_value
+	cmp	w14, #-0xf			// SHN_ABS (0xfff1) ?
+	add	x14, x15, x23			// relocate
+	csel	x15, x14, x15, ne
+	add	x15, x13, x15
+	str	x15, [x11, x23]
+	b	0b
+
+2:
+#endif
+	ldr	x8, =__primary_switched
+	br	x8
+ENDPROC(__primary_switch)
+
+__secondary_switch:
+	ldr	x8, =__secondary_switched
+	br	x8
+ENDPROC(__secondary_switch)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kernel/hibernate-asm.S linux-libre-4.7-gnu/arch/arm64/kernel/hibernate-asm.S
--- linux-libre-4.6-gnu/arch/arm64/kernel/hibernate-asm.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm64/kernel/hibernate-asm.S	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,176 @@
+/*
+ * Hibernate low-level support
+ *
+ * Copyright (C) 2016 ARM Ltd.
+ * Author:	James Morse <james.morse@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/linkage.h>
+#include <linux/errno.h>
+
+#include <asm/asm-offsets.h>
+#include <asm/assembler.h>
+#include <asm/cputype.h>
+#include <asm/memory.h>
+#include <asm/page.h>
+#include <asm/virt.h>
+
+/*
+ * To prevent the possibility of old and new partial table walks being visible
+ * in the tlb, switch the ttbr to a zero page when we invalidate the old
+ * records. D4.7.1 'General TLB maintenance requirements' in ARM DDI 0487A.i
+ * Even switching to our copied tables will cause a changed output address at
+ * each stage of the walk.
+ */
+.macro break_before_make_ttbr_switch zero_page, page_table
+	msr	ttbr1_el1, \zero_page
+	isb
+	tlbi	vmalle1is
+	dsb	ish
+	msr	ttbr1_el1, \page_table
+	isb
+.endm
+
+
+/*
+ * Resume from hibernate
+ *
+ * Loads temporary page tables then restores the memory image.
+ * Finally branches to cpu_resume() to restore the state saved by
+ * swsusp_arch_suspend().
+ *
+ * Because this code has to be copied to a 'safe' page, it can't call out to
+ * other functions by PC-relative address. Also remember that it may be
+ * mid-way through over-writing other functions. For this reason it contains
+ * code from flush_icache_range() and uses the copy_page() macro.
+ *
+ * This 'safe' page is mapped via ttbr0, and executed from there. This function
+ * switches to a copy of the linear map in ttbr1, performs the restore, then
+ * switches ttbr1 to the original kernel's swapper_pg_dir.
+ *
+ * All of memory gets written to, including code. We need to clean the kernel
+ * text to the Point of Coherence (PoC) before secondary cores can be booted.
+ * Because the kernel modules and executable pages mapped to user space are
+ * also written as data, we clean all pages we touch to the Point of
+ * Unification (PoU).
+ *
+ * x0: physical address of temporary page tables
+ * x1: physical address of swapper page tables
+ * x2: address of cpu_resume
+ * x3: linear map address of restore_pblist in the current kernel
+ * x4: physical address of __hyp_stub_vectors, or 0
+ * x5: physical address of a  zero page that remains zero after resume
+ */
+.pushsection    ".hibernate_exit.text", "ax"
+ENTRY(swsusp_arch_suspend_exit)
+	/*
+	 * We execute from ttbr0, change ttbr1 to our copied linear map tables
+	 * with a break-before-make via the zero page
+	 */
+	break_before_make_ttbr_switch	x5, x0
+
+	mov	x21, x1
+	mov	x30, x2
+	mov	x24, x4
+	mov	x25, x5
+
+	/* walk the restore_pblist and use copy_page() to over-write memory */
+	mov	x19, x3
+
+1:	ldr	x10, [x19, #HIBERN_PBE_ORIG]
+	mov	x0, x10
+	ldr	x1, [x19, #HIBERN_PBE_ADDR]
+
+	copy_page	x0, x1, x2, x3, x4, x5, x6, x7, x8, x9
+
+	add	x1, x10, #PAGE_SIZE
+	/* Clean the copied page to PoU - based on flush_icache_range() */
+	dcache_line_size x2, x3
+	sub	x3, x2, #1
+	bic	x4, x10, x3
+2:	dc	cvau, x4	/* clean D line / unified line */
+	add	x4, x4, x2
+	cmp	x4, x1
+	b.lo	2b
+
+	ldr	x19, [x19, #HIBERN_PBE_NEXT]
+	cbnz	x19, 1b
+	dsb	ish		/* wait for PoU cleaning to finish */
+
+	/* switch to the restored kernels page tables */
+	break_before_make_ttbr_switch	x25, x21
+
+	ic	ialluis
+	dsb	ish
+	isb
+
+	cbz	x24, 3f		/* Do we need to re-initialise EL2? */
+	hvc	#0
+3:	ret
+
+	.ltorg
+ENDPROC(swsusp_arch_suspend_exit)
+
+/*
+ * Restore the hyp stub.
+ * This must be done before the hibernate page is unmapped by _cpu_resume(),
+ * but happens before any of the hyp-stub's code is cleaned to PoC.
+ *
+ * x24: The physical address of __hyp_stub_vectors
+ */
+el1_sync:
+	msr	vbar_el2, x24
+	eret
+ENDPROC(el1_sync)
+
+.macro invalid_vector	label
+\label:
+	b \label
+ENDPROC(\label)
+.endm
+
+	invalid_vector	el2_sync_invalid
+	invalid_vector	el2_irq_invalid
+	invalid_vector	el2_fiq_invalid
+	invalid_vector	el2_error_invalid
+	invalid_vector	el1_sync_invalid
+	invalid_vector	el1_irq_invalid
+	invalid_vector	el1_fiq_invalid
+	invalid_vector	el1_error_invalid
+
+/* el2 vectors - switch el2 here while we restore the memory image. */
+	.align 11
+ENTRY(hibernate_el2_vectors)
+	ventry	el2_sync_invalid		// Synchronous EL2t
+	ventry	el2_irq_invalid			// IRQ EL2t
+	ventry	el2_fiq_invalid			// FIQ EL2t
+	ventry	el2_error_invalid		// Error EL2t
+
+	ventry	el2_sync_invalid		// Synchronous EL2h
+	ventry	el2_irq_invalid			// IRQ EL2h
+	ventry	el2_fiq_invalid			// FIQ EL2h
+	ventry	el2_error_invalid		// Error EL2h
+
+	ventry	el1_sync			// Synchronous 64-bit EL1
+	ventry	el1_irq_invalid			// IRQ 64-bit EL1
+	ventry	el1_fiq_invalid			// FIQ 64-bit EL1
+	ventry	el1_error_invalid		// Error 64-bit EL1
+
+	ventry	el1_sync_invalid		// Synchronous 32-bit EL1
+	ventry	el1_irq_invalid			// IRQ 32-bit EL1
+	ventry	el1_fiq_invalid			// FIQ 32-bit EL1
+	ventry	el1_error_invalid		// Error 32-bit EL1
+END(hibernate_el2_vectors)
+
+.popsection
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kernel/hibernate.c linux-libre-4.7-gnu/arch/arm64/kernel/hibernate.c
--- linux-libre-4.6-gnu/arch/arm64/kernel/hibernate.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm64/kernel/hibernate.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,493 @@
+/*:
+ * Hibernate support specific for ARM64
+ *
+ * Derived from work on ARM hibernation support by:
+ *
+ * Ubuntu project, hibernation support for mach-dove
+ * Copyright (C) 2010 Nokia Corporation (Hiroshi Doyu)
+ * Copyright (C) 2010 Texas Instruments, Inc. (Teerth Reddy et al.)
+ *  https://lkml.org/lkml/2010/6/18/4
+ *  https://lists.linux-foundation.org/pipermail/linux-pm/2010-June/027422.html
+ *  https://patchwork.kernel.org/patch/96442/
+ *
+ * Copyright (C) 2006 Rafael J. Wysocki <rjw@sisk.pl>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+#define pr_fmt(x) "hibernate: " x
+#include <linux/kvm_host.h>
+#include <linux/mm.h>
+#include <linux/notifier.h>
+#include <linux/pm.h>
+#include <linux/sched.h>
+#include <linux/suspend.h>
+#include <linux/utsname.h>
+#include <linux/version.h>
+
+#include <asm/barrier.h>
+#include <asm/cacheflush.h>
+#include <asm/irqflags.h>
+#include <asm/memory.h>
+#include <asm/mmu_context.h>
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
+#include <asm/pgtable-hwdef.h>
+#include <asm/sections.h>
+#include <asm/smp.h>
+#include <asm/suspend.h>
+#include <asm/virt.h>
+
+/*
+ * Hibernate core relies on this value being 0 on resume, and marks it
+ * __nosavedata assuming it will keep the resume kernel's '0' value. This
+ * doesn't happen with either KASLR.
+ *
+ * defined as "__visible int in_suspend __nosavedata" in
+ * kernel/power/hibernate.c
+ */
+extern int in_suspend;
+
+/* Find a symbols alias in the linear map */
+#define LMADDR(x)	phys_to_virt(virt_to_phys(x))
+
+/* Do we need to reset el2? */
+#define el2_reset_needed() (is_hyp_mode_available() && !is_kernel_in_hyp_mode())
+
+/*
+ * Start/end of the hibernate exit code, this must be copied to a 'safe'
+ * location in memory, and executed from there.
+ */
+extern char __hibernate_exit_text_start[], __hibernate_exit_text_end[];
+
+/* temporary el2 vectors in the __hibernate_exit_text section. */
+extern char hibernate_el2_vectors[];
+
+/* hyp-stub vectors, used to restore el2 during resume from hibernate. */
+extern char __hyp_stub_vectors[];
+
+/*
+ * Values that may not change over hibernate/resume. We put the build number
+ * and date in here so that we guarantee not to resume with a different
+ * kernel.
+ */
+struct arch_hibernate_hdr_invariants {
+	char		uts_version[__NEW_UTS_LEN + 1];
+};
+
+/* These values need to be know across a hibernate/restore. */
+static struct arch_hibernate_hdr {
+	struct arch_hibernate_hdr_invariants invariants;
+
+	/* These are needed to find the relocated kernel if built with kaslr */
+	phys_addr_t	ttbr1_el1;
+	void		(*reenter_kernel)(void);
+
+	/*
+	 * We need to know where the __hyp_stub_vectors are after restore to
+	 * re-configure el2.
+	 */
+	phys_addr_t	__hyp_stub_vectors;
+} resume_hdr;
+
+static inline void arch_hdr_invariants(struct arch_hibernate_hdr_invariants *i)
+{
+	memset(i, 0, sizeof(*i));
+	memcpy(i->uts_version, init_utsname()->version, sizeof(i->uts_version));
+}
+
+int pfn_is_nosave(unsigned long pfn)
+{
+	unsigned long nosave_begin_pfn = virt_to_pfn(&__nosave_begin);
+	unsigned long nosave_end_pfn = virt_to_pfn(&__nosave_end - 1);
+
+	return (pfn >= nosave_begin_pfn) && (pfn <= nosave_end_pfn);
+}
+
+void notrace save_processor_state(void)
+{
+	WARN_ON(num_online_cpus() != 1);
+}
+
+void notrace restore_processor_state(void)
+{
+}
+
+int arch_hibernation_header_save(void *addr, unsigned int max_size)
+{
+	struct arch_hibernate_hdr *hdr = addr;
+
+	if (max_size < sizeof(*hdr))
+		return -EOVERFLOW;
+
+	arch_hdr_invariants(&hdr->invariants);
+	hdr->ttbr1_el1		= virt_to_phys(swapper_pg_dir);
+	hdr->reenter_kernel	= _cpu_resume;
+
+	/* We can't use __hyp_get_vectors() because kvm may still be loaded */
+	if (el2_reset_needed())
+		hdr->__hyp_stub_vectors = virt_to_phys(__hyp_stub_vectors);
+	else
+		hdr->__hyp_stub_vectors = 0;
+
+	return 0;
+}
+EXPORT_SYMBOL(arch_hibernation_header_save);
+
+int arch_hibernation_header_restore(void *addr)
+{
+	struct arch_hibernate_hdr_invariants invariants;
+	struct arch_hibernate_hdr *hdr = addr;
+
+	arch_hdr_invariants(&invariants);
+	if (memcmp(&hdr->invariants, &invariants, sizeof(invariants))) {
+		pr_crit("Hibernate image not generated by this kernel!\n");
+		return -EINVAL;
+	}
+
+	resume_hdr = *hdr;
+
+	return 0;
+}
+EXPORT_SYMBOL(arch_hibernation_header_restore);
+
+/*
+ * Copies length bytes, starting at src_start into an new page,
+ * perform cache maintentance, then maps it at the specified address low
+ * address as executable.
+ *
+ * This is used by hibernate to copy the code it needs to execute when
+ * overwriting the kernel text. This function generates a new set of page
+ * tables, which it loads into ttbr0.
+ *
+ * Length is provided as we probably only want 4K of data, even on a 64K
+ * page system.
+ */
+static int create_safe_exec_page(void *src_start, size_t length,
+				 unsigned long dst_addr,
+				 phys_addr_t *phys_dst_addr,
+				 void *(*allocator)(gfp_t mask),
+				 gfp_t mask)
+{
+	int rc = 0;
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
+	pte_t *pte;
+	unsigned long dst = (unsigned long)allocator(mask);
+
+	if (!dst) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	memcpy((void *)dst, src_start, length);
+	flush_icache_range(dst, dst + length);
+
+	pgd = pgd_offset_raw(allocator(mask), dst_addr);
+	if (pgd_none(*pgd)) {
+		pud = allocator(mask);
+		if (!pud) {
+			rc = -ENOMEM;
+			goto out;
+		}
+		pgd_populate(&init_mm, pgd, pud);
+	}
+
+	pud = pud_offset(pgd, dst_addr);
+	if (pud_none(*pud)) {
+		pmd = allocator(mask);
+		if (!pmd) {
+			rc = -ENOMEM;
+			goto out;
+		}
+		pud_populate(&init_mm, pud, pmd);
+	}
+
+	pmd = pmd_offset(pud, dst_addr);
+	if (pmd_none(*pmd)) {
+		pte = allocator(mask);
+		if (!pte) {
+			rc = -ENOMEM;
+			goto out;
+		}
+		pmd_populate_kernel(&init_mm, pmd, pte);
+	}
+
+	pte = pte_offset_kernel(pmd, dst_addr);
+	set_pte(pte, __pte(virt_to_phys((void *)dst) |
+			 pgprot_val(PAGE_KERNEL_EXEC)));
+
+	/* Load our new page tables */
+	asm volatile("msr	ttbr0_el1, %0;"
+		     "isb;"
+		     "tlbi	vmalle1is;"
+		     "dsb	ish;"
+		     "isb" : : "r"(virt_to_phys(pgd)));
+
+	*phys_dst_addr = virt_to_phys((void *)dst);
+
+out:
+	return rc;
+}
+
+
+int swsusp_arch_suspend(void)
+{
+	int ret = 0;
+	unsigned long flags;
+	struct sleep_stack_data state;
+
+	if (cpus_are_stuck_in_kernel()) {
+		pr_err("Can't hibernate: no mechanism to offline secondary CPUs.\n");
+		return -EBUSY;
+	}
+
+	local_dbg_save(flags);
+
+	if (__cpu_suspend_enter(&state)) {
+		ret = swsusp_save();
+	} else {
+		/* Clean kernel to PoC for secondary core startup */
+		__flush_dcache_area(LMADDR(KERNEL_START), KERNEL_END - KERNEL_START);
+
+		/*
+		 * Tell the hibernation core that we've just restored
+		 * the memory
+		 */
+		in_suspend = 0;
+
+		__cpu_suspend_exit();
+	}
+
+	local_dbg_restore(flags);
+
+	return ret;
+}
+
+static int copy_pte(pmd_t *dst_pmd, pmd_t *src_pmd, unsigned long start,
+		    unsigned long end)
+{
+	pte_t *src_pte;
+	pte_t *dst_pte;
+	unsigned long addr = start;
+
+	dst_pte = (pte_t *)get_safe_page(GFP_ATOMIC);
+	if (!dst_pte)
+		return -ENOMEM;
+	pmd_populate_kernel(&init_mm, dst_pmd, dst_pte);
+	dst_pte = pte_offset_kernel(dst_pmd, start);
+
+	src_pte = pte_offset_kernel(src_pmd, start);
+	do {
+		if (!pte_none(*src_pte))
+			/*
+			 * Resume will overwrite areas that may be marked
+			 * read only (code, rodata). Clear the RDONLY bit from
+			 * the temporary mappings we use during restore.
+			 */
+			set_pte(dst_pte, __pte(pte_val(*src_pte) & ~PTE_RDONLY));
+	} while (dst_pte++, src_pte++, addr += PAGE_SIZE, addr != end);
+
+	return 0;
+}
+
+static int copy_pmd(pud_t *dst_pud, pud_t *src_pud, unsigned long start,
+		    unsigned long end)
+{
+	pmd_t *src_pmd;
+	pmd_t *dst_pmd;
+	unsigned long next;
+	unsigned long addr = start;
+
+	if (pud_none(*dst_pud)) {
+		dst_pmd = (pmd_t *)get_safe_page(GFP_ATOMIC);
+		if (!dst_pmd)
+			return -ENOMEM;
+		pud_populate(&init_mm, dst_pud, dst_pmd);
+	}
+	dst_pmd = pmd_offset(dst_pud, start);
+
+	src_pmd = pmd_offset(src_pud, start);
+	do {
+		next = pmd_addr_end(addr, end);
+		if (pmd_none(*src_pmd))
+			continue;
+		if (pmd_table(*src_pmd)) {
+			if (copy_pte(dst_pmd, src_pmd, addr, next))
+				return -ENOMEM;
+		} else {
+			set_pmd(dst_pmd,
+				__pmd(pmd_val(*src_pmd) & ~PMD_SECT_RDONLY));
+		}
+	} while (dst_pmd++, src_pmd++, addr = next, addr != end);
+
+	return 0;
+}
+
+static int copy_pud(pgd_t *dst_pgd, pgd_t *src_pgd, unsigned long start,
+		    unsigned long end)
+{
+	pud_t *dst_pud;
+	pud_t *src_pud;
+	unsigned long next;
+	unsigned long addr = start;
+
+	if (pgd_none(*dst_pgd)) {
+		dst_pud = (pud_t *)get_safe_page(GFP_ATOMIC);
+		if (!dst_pud)
+			return -ENOMEM;
+		pgd_populate(&init_mm, dst_pgd, dst_pud);
+	}
+	dst_pud = pud_offset(dst_pgd, start);
+
+	src_pud = pud_offset(src_pgd, start);
+	do {
+		next = pud_addr_end(addr, end);
+		if (pud_none(*src_pud))
+			continue;
+		if (pud_table(*(src_pud))) {
+			if (copy_pmd(dst_pud, src_pud, addr, next))
+				return -ENOMEM;
+		} else {
+			set_pud(dst_pud,
+				__pud(pud_val(*src_pud) & ~PMD_SECT_RDONLY));
+		}
+	} while (dst_pud++, src_pud++, addr = next, addr != end);
+
+	return 0;
+}
+
+static int copy_page_tables(pgd_t *dst_pgd, unsigned long start,
+			    unsigned long end)
+{
+	unsigned long next;
+	unsigned long addr = start;
+	pgd_t *src_pgd = pgd_offset_k(start);
+
+	dst_pgd = pgd_offset_raw(dst_pgd, start);
+	do {
+		next = pgd_addr_end(addr, end);
+		if (pgd_none(*src_pgd))
+			continue;
+		if (copy_pud(dst_pgd, src_pgd, addr, next))
+			return -ENOMEM;
+	} while (dst_pgd++, src_pgd++, addr = next, addr != end);
+
+	return 0;
+}
+
+/*
+ * Setup then Resume from the hibernate image using swsusp_arch_suspend_exit().
+ *
+ * Memory allocated by get_safe_page() will be dealt with by the hibernate code,
+ * we don't need to free it here.
+ */
+int swsusp_arch_resume(void)
+{
+	int rc = 0;
+	void *zero_page;
+	size_t exit_size;
+	pgd_t *tmp_pg_dir;
+	void *lm_restore_pblist;
+	phys_addr_t phys_hibernate_exit;
+	void __noreturn (*hibernate_exit)(phys_addr_t, phys_addr_t, void *,
+					  void *, phys_addr_t, phys_addr_t);
+
+	/*
+	 * Locate the exit code in the bottom-but-one page, so that *NULL
+	 * still has disastrous affects.
+	 */
+	hibernate_exit = (void *)PAGE_SIZE;
+	exit_size = __hibernate_exit_text_end - __hibernate_exit_text_start;
+	/*
+	 * Copy swsusp_arch_suspend_exit() to a safe page. This will generate
+	 * a new set of ttbr0 page tables and load them.
+	 */
+	rc = create_safe_exec_page(__hibernate_exit_text_start, exit_size,
+				   (unsigned long)hibernate_exit,
+				   &phys_hibernate_exit,
+				   (void *)get_safe_page, GFP_ATOMIC);
+	if (rc) {
+		pr_err("Failed to create safe executable page for hibernate_exit code.");
+		goto out;
+	}
+
+	/*
+	 * The hibernate exit text contains a set of el2 vectors, that will
+	 * be executed at el2 with the mmu off in order to reload hyp-stub.
+	 */
+	__flush_dcache_area(hibernate_exit, exit_size);
+
+	/*
+	 * Restoring the memory image will overwrite the ttbr1 page tables.
+	 * Create a second copy of just the linear map, and use this when
+	 * restoring.
+	 */
+	tmp_pg_dir = (pgd_t *)get_safe_page(GFP_ATOMIC);
+	if (!tmp_pg_dir) {
+		pr_err("Failed to allocate memory for temporary page tables.");
+		rc = -ENOMEM;
+		goto out;
+	}
+	rc = copy_page_tables(tmp_pg_dir, PAGE_OFFSET, 0);
+	if (rc)
+		goto out;
+
+	/*
+	 * Since we only copied the linear map, we need to find restore_pblist's
+	 * linear map address.
+	 */
+	lm_restore_pblist = LMADDR(restore_pblist);
+
+	/*
+	 * KASLR will cause the el2 vectors to be in a different location in
+	 * the resumed kernel. Load hibernate's temporary copy into el2.
+	 *
+	 * We can skip this step if we booted at EL1, or are running with VHE.
+	 */
+	if (el2_reset_needed()) {
+		phys_addr_t el2_vectors = phys_hibernate_exit;  /* base */
+		el2_vectors += hibernate_el2_vectors -
+			       __hibernate_exit_text_start;     /* offset */
+
+		__hyp_set_vectors(el2_vectors);
+	}
+
+	/*
+	 * We need a zero page that is zero before & after resume in order to
+	 * to break before make on the ttbr1 page tables.
+	 */
+	zero_page = (void *)get_safe_page(GFP_ATOMIC);
+
+	hibernate_exit(virt_to_phys(tmp_pg_dir), resume_hdr.ttbr1_el1,
+		       resume_hdr.reenter_kernel, lm_restore_pblist,
+		       resume_hdr.__hyp_stub_vectors, virt_to_phys(zero_page));
+
+out:
+	return rc;
+}
+
+static int check_boot_cpu_online_pm_callback(struct notifier_block *nb,
+					     unsigned long action, void *ptr)
+{
+	if (action == PM_HIBERNATION_PREPARE &&
+	     cpumask_first(cpu_online_mask) != 0) {
+		pr_warn("CPU0 is offline.\n");
+		return notifier_from_errno(-ENODEV);
+	}
+
+	return NOTIFY_OK;
+}
+
+static int __init check_boot_cpu_online_init(void)
+{
+	/*
+	 * Set this pm_notifier callback with a lower priority than
+	 * cpu_hotplug_pm_callback, so that cpu_hotplug_pm_callback will be
+	 * called earlier to disable cpu hotplug before the cpu online check.
+	 */
+	pm_notifier(check_boot_cpu_online_pm_callback, -INT_MAX);
+
+	return 0;
+}
+core_initcall(check_boot_cpu_online_init);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kernel/hw_breakpoint.c linux-libre-4.7-gnu/arch/arm64/kernel/hw_breakpoint.c
--- linux-libre-4.6-gnu/arch/arm64/kernel/hw_breakpoint.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kernel/hw_breakpoint.c	2016-07-24 15:23:50.000000000 -0400
@@ -616,7 +616,7 @@ static int breakpoint_handler(unsigned l
 		perf_bp_event(bp, regs);
 
 		/* Do we need to handle the stepping? */
-		if (!bp->overflow_handler)
+		if (is_default_overflow_handler(bp))
 			step = 1;
 unlock:
 		rcu_read_unlock();
@@ -712,7 +712,7 @@ static int watchpoint_handler(unsigned l
 		perf_bp_event(wp, regs);
 
 		/* Do we need to handle the stepping? */
-		if (!wp->overflow_handler)
+		if (is_default_overflow_handler(wp))
 			step = 1;
 
 unlock:
@@ -886,9 +886,11 @@ static int hw_breakpoint_reset_notify(st
 						unsigned long action,
 						void *hcpu)
 {
-	int cpu = (long)hcpu;
-	if ((action & ~CPU_TASKS_FROZEN) == CPU_ONLINE)
-		smp_call_function_single(cpu, hw_breakpoint_reset, NULL, 1);
+	if ((action & ~CPU_TASKS_FROZEN) == CPU_ONLINE) {
+		local_irq_disable();
+		hw_breakpoint_reset(NULL);
+		local_irq_enable();
+	}
 	return NOTIFY_OK;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kernel/hyp-stub.S linux-libre-4.7-gnu/arch/arm64/kernel/hyp-stub.S
--- linux-libre-4.6-gnu/arch/arm64/kernel/hyp-stub.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kernel/hyp-stub.S	2016-07-24 15:23:50.000000000 -0400
@@ -22,6 +22,8 @@
 #include <linux/irqchip/arm-gic-v3.h>
 
 #include <asm/assembler.h>
+#include <asm/kvm_arm.h>
+#include <asm/kvm_asm.h>
 #include <asm/ptrace.h>
 #include <asm/virt.h>
 
@@ -53,15 +55,26 @@ ENDPROC(__hyp_stub_vectors)
 	.align 11
 
 el1_sync:
-	mrs	x1, esr_el2
-	lsr	x1, x1, #26
-	cmp	x1, #0x16
-	b.ne	2f				// Not an HVC trap
-	cbz	x0, 1f
-	msr	vbar_el2, x0			// Set vbar_el2
-	b	2f
-1:	mrs	x0, vbar_el2			// Return vbar_el2
-2:	eret
+	mrs	x30, esr_el2
+	lsr	x30, x30, #ESR_ELx_EC_SHIFT
+
+	cmp	x30, #ESR_ELx_EC_HVC64
+	b.ne	9f				// Not an HVC trap
+
+	cmp	x0, #HVC_GET_VECTORS
+	b.ne	1f
+	mrs	x0, vbar_el2
+	b	9f
+
+1:	cmp	x0, #HVC_SET_VECTORS
+	b.ne	2f
+	msr	vbar_el2, x1
+	b	9f
+
+	/* Someone called kvm_call_hyp() against the hyp-stub... */
+2:	mov     x0, #ARM_EXCEPTION_HYP_GONE
+
+9:	eret
 ENDPROC(el1_sync)
 
 .macro invalid_vector	label
@@ -101,10 +114,18 @@ ENDPROC(\label)
  */
 
 ENTRY(__hyp_get_vectors)
-	mov	x0, xzr
-	// fall through
-ENTRY(__hyp_set_vectors)
+	str	lr, [sp, #-16]!
+	mov	x0, #HVC_GET_VECTORS
 	hvc	#0
+	ldr	lr, [sp], #16
 	ret
 ENDPROC(__hyp_get_vectors)
+
+ENTRY(__hyp_set_vectors)
+	str	lr, [sp, #-16]!
+	mov	x1, x0
+	mov	x0, #HVC_SET_VECTORS
+	hvc	#0
+	ldr	lr, [sp], #16
+	ret
 ENDPROC(__hyp_set_vectors)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kernel/image.h linux-libre-4.7-gnu/arch/arm64/kernel/image.h
--- linux-libre-4.6-gnu/arch/arm64/kernel/image.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kernel/image.h	2016-07-24 15:23:50.000000000 -0400
@@ -73,6 +73,8 @@
 
 #ifdef CONFIG_EFI
 
+__efistub_stext_offset = stext - _text;
+
 /*
  * Prevent the symbol aliases below from being emitted into the kallsyms
  * table, by forcing them to be absolute symbols (which are conveniently
@@ -112,6 +114,7 @@ __efistub___memset		= KALLSYMS_HIDE(__pi
 __efistub__text			= KALLSYMS_HIDE(_text);
 __efistub__end			= KALLSYMS_HIDE(_end);
 __efistub__edata		= KALLSYMS_HIDE(_edata);
+__efistub_screen_info		= KALLSYMS_HIDE(screen_info);
 
 #endif
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kernel/insn.c linux-libre-4.7-gnu/arch/arm64/kernel/insn.c
--- linux-libre-4.6-gnu/arch/arm64/kernel/insn.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kernel/insn.c	2016-07-24 15:23:50.000000000 -0400
@@ -96,7 +96,7 @@ static void __kprobes *patch_map(void *a
 	if (module && IS_ENABLED(CONFIG_DEBUG_SET_MODULE_RONX))
 		page = vmalloc_to_page(addr);
 	else if (!module && IS_ENABLED(CONFIG_DEBUG_RODATA))
-		page = virt_to_page(addr);
+		page = pfn_to_page(PHYS_PFN(__pa(addr)));
 	else
 		return addr;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kernel/kaslr.c linux-libre-4.7-gnu/arch/arm64/kernel/kaslr.c
--- linux-libre-4.6-gnu/arch/arm64/kernel/kaslr.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kernel/kaslr.c	2016-07-24 15:23:50.000000000 -0400
@@ -74,7 +74,7 @@ extern void *__init __fixmap_remap_fdt(p
  * containing function pointers) to be reinitialized, and zero-initialized
  * .bss variables will be reset to 0.
  */
-u64 __init kaslr_early_init(u64 dt_phys)
+u64 __init kaslr_early_init(u64 dt_phys, u64 modulo_offset)
 {
 	void *fdt;
 	u64 seed, offset, mask, module_range;
@@ -132,8 +132,8 @@ u64 __init kaslr_early_init(u64 dt_phys)
 	 * boundary (for 4KB/16KB/64KB granule kernels, respectively). If this
 	 * happens, increase the KASLR offset by the size of the kernel image.
 	 */
-	if ((((u64)_text + offset) >> SWAPPER_TABLE_SHIFT) !=
-	    (((u64)_end + offset) >> SWAPPER_TABLE_SHIFT))
+	if ((((u64)_text + offset + modulo_offset) >> SWAPPER_TABLE_SHIFT) !=
+	    (((u64)_end + offset + modulo_offset) >> SWAPPER_TABLE_SHIFT))
 		offset = (offset + (u64)(_end - _text)) & mask;
 
 	if (IS_ENABLED(CONFIG_KASAN))
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kernel/kgdb.c linux-libre-4.7-gnu/arch/arm64/kernel/kgdb.c
--- linux-libre-4.6-gnu/arch/arm64/kernel/kgdb.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kernel/kgdb.c	2016-07-24 15:23:50.000000000 -0400
@@ -58,7 +58,17 @@ struct dbg_reg_def_t dbg_reg_def[DBG_MAX
 	{ "x30", 8, offsetof(struct pt_regs, regs[30])},
 	{ "sp", 8, offsetof(struct pt_regs, sp)},
 	{ "pc", 8, offsetof(struct pt_regs, pc)},
-	{ "pstate", 8, offsetof(struct pt_regs, pstate)},
+	/*
+	 * struct pt_regs thinks PSTATE is 64-bits wide but gdb remote
+	 * protocol disagrees. Therefore we must extract only the lower
+	 * 32-bits. Look for the big comment in asm/kgdb.h for more
+	 * detail.
+	 */
+	{ "pstate", 4, offsetof(struct pt_regs, pstate)
+#ifdef CONFIG_CPU_BIG_ENDIAN
+							+ 4
+#endif
+	},
 	{ "v0", 16, -1 },
 	{ "v1", 16, -1 },
 	{ "v2", 16, -1 },
@@ -128,6 +138,8 @@ sleeping_thread_to_gdb_regs(unsigned lon
 	memset((char *)gdb_regs, 0, NUMREGBYTES);
 	thread_regs = task_pt_regs(task);
 	memcpy((void *)gdb_regs, (void *)thread_regs->regs, GP_REG_BYTES);
+	/* Special case for PSTATE (check comments in asm/kgdb.h for details) */
+	dbg_get_reg(33, gdb_regs + GP_REG_BYTES, thread_regs);
 }
 
 void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kernel/Makefile linux-libre-4.7-gnu/arch/arm64/kernel/Makefile
--- linux-libre-4.6-gnu/arch/arm64/kernel/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kernel/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -45,6 +45,7 @@ arm64-obj-$(CONFIG_ACPI)		+= acpi.o
 arm64-obj-$(CONFIG_ARM64_ACPI_PARKING_PROTOCOL)	+= acpi_parking_protocol.o
 arm64-obj-$(CONFIG_PARAVIRT)		+= paravirt.o
 arm64-obj-$(CONFIG_RANDOMIZE_BASE)	+= kaslr.o
+arm64-obj-$(CONFIG_HIBERNATION)		+= hibernate.o hibernate-asm.o
 
 obj-y					+= $(arm64-obj-y) vdso/
 obj-m					+= $(arm64-obj-m)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kernel/pci.c linux-libre-4.7-gnu/arch/arm64/kernel/pci.c
--- linux-libre-4.6-gnu/arch/arm64/kernel/pci.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kernel/pci.c	2016-07-24 15:23:50.000000000 -0400
@@ -74,6 +74,16 @@ int raw_pci_write(unsigned int domain, u
 	return -ENXIO;
 }
 
+#ifdef CONFIG_NUMA
+
+int pcibus_to_node(struct pci_bus *bus)
+{
+	return dev_to_node(&bus->dev);
+}
+EXPORT_SYMBOL(pcibus_to_node);
+
+#endif
+
 #ifdef CONFIG_ACPI
 /* Root bridge scanning */
 struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kernel/perf_callchain.c linux-libre-4.7-gnu/arch/arm64/kernel/perf_callchain.c
--- linux-libre-4.6-gnu/arch/arm64/kernel/perf_callchain.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kernel/perf_callchain.c	2016-07-24 15:23:50.000000000 -0400
@@ -31,7 +31,7 @@ struct frame_tail {
  */
 static struct frame_tail __user *
 user_backtrace(struct frame_tail __user *tail,
-	       struct perf_callchain_entry *entry)
+	       struct perf_callchain_entry_ctx *entry)
 {
 	struct frame_tail buftail;
 	unsigned long err;
@@ -76,7 +76,7 @@ struct compat_frame_tail {
 
 static struct compat_frame_tail __user *
 compat_user_backtrace(struct compat_frame_tail __user *tail,
-		      struct perf_callchain_entry *entry)
+		      struct perf_callchain_entry_ctx *entry)
 {
 	struct compat_frame_tail buftail;
 	unsigned long err;
@@ -106,7 +106,7 @@ compat_user_backtrace(struct compat_fram
 }
 #endif /* CONFIG_COMPAT */
 
-void perf_callchain_user(struct perf_callchain_entry *entry,
+void perf_callchain_user(struct perf_callchain_entry_ctx *entry,
 			 struct pt_regs *regs)
 {
 	if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
@@ -122,7 +122,7 @@ void perf_callchain_user(struct perf_cal
 
 		tail = (struct frame_tail __user *)regs->regs[29];
 
-		while (entry->nr < PERF_MAX_STACK_DEPTH &&
+		while (entry->nr < entry->max_stack &&
 		       tail && !((unsigned long)tail & 0xf))
 			tail = user_backtrace(tail, entry);
 	} else {
@@ -132,7 +132,7 @@ void perf_callchain_user(struct perf_cal
 
 		tail = (struct compat_frame_tail __user *)regs->compat_fp - 1;
 
-		while ((entry->nr < PERF_MAX_STACK_DEPTH) &&
+		while ((entry->nr < entry->max_stack) &&
 			tail && !((unsigned long)tail & 0x3))
 			tail = compat_user_backtrace(tail, entry);
 #endif
@@ -146,12 +146,12 @@ void perf_callchain_user(struct perf_cal
  */
 static int callchain_trace(struct stackframe *frame, void *data)
 {
-	struct perf_callchain_entry *entry = data;
+	struct perf_callchain_entry_ctx *entry = data;
 	perf_callchain_store(entry, frame->pc);
 	return 0;
 }
 
-void perf_callchain_kernel(struct perf_callchain_entry *entry,
+void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
 			   struct pt_regs *regs)
 {
 	struct stackframe frame;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kernel/perf_event.c linux-libre-4.7-gnu/arch/arm64/kernel/perf_event.c
--- linux-libre-4.6-gnu/arch/arm64/kernel/perf_event.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kernel/perf_event.c	2016-07-24 15:23:50.000000000 -0400
@@ -21,6 +21,7 @@
 
 #include <asm/irq_regs.h>
 #include <asm/perf_event.h>
+#include <asm/sysreg.h>
 #include <asm/virt.h>
 
 #include <linux/of.h>
@@ -33,43 +34,43 @@
  */
 
 /* Required events. */
-#define ARMV8_PMUV3_PERFCTR_PMNC_SW_INCR			0x00
-#define ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL			0x03
-#define ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS			0x04
-#define ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED			0x10
-#define ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES			0x11
-#define ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED			0x12
+#define ARMV8_PMUV3_PERFCTR_SW_INCR				0x00
+#define ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL			0x03
+#define ARMV8_PMUV3_PERFCTR_L1D_CACHE				0x04
+#define ARMV8_PMUV3_PERFCTR_BR_MIS_PRED				0x10
+#define ARMV8_PMUV3_PERFCTR_CPU_CYCLES				0x11
+#define ARMV8_PMUV3_PERFCTR_BR_PRED				0x12
 
 /* At least one of the following is required. */
-#define ARMV8_PMUV3_PERFCTR_INSTR_EXECUTED			0x08
-#define ARMV8_PMUV3_PERFCTR_OP_SPEC				0x1B
+#define ARMV8_PMUV3_PERFCTR_INST_RETIRED			0x08
+#define ARMV8_PMUV3_PERFCTR_INST_SPEC				0x1B
 
 /* Common architectural events. */
-#define ARMV8_PMUV3_PERFCTR_MEM_READ				0x06
-#define ARMV8_PMUV3_PERFCTR_MEM_WRITE				0x07
+#define ARMV8_PMUV3_PERFCTR_LD_RETIRED				0x06
+#define ARMV8_PMUV3_PERFCTR_ST_RETIRED				0x07
 #define ARMV8_PMUV3_PERFCTR_EXC_TAKEN				0x09
-#define ARMV8_PMUV3_PERFCTR_EXC_EXECUTED			0x0A
-#define ARMV8_PMUV3_PERFCTR_CID_WRITE				0x0B
-#define ARMV8_PMUV3_PERFCTR_PC_WRITE				0x0C
-#define ARMV8_PMUV3_PERFCTR_PC_IMM_BRANCH			0x0D
-#define ARMV8_PMUV3_PERFCTR_PC_PROC_RETURN			0x0E
-#define ARMV8_PMUV3_PERFCTR_MEM_UNALIGNED_ACCESS		0x0F
-#define ARMV8_PMUV3_PERFCTR_TTBR_WRITE				0x1C
+#define ARMV8_PMUV3_PERFCTR_EXC_RETURN				0x0A
+#define ARMV8_PMUV3_PERFCTR_CID_WRITE_RETIRED			0x0B
+#define ARMV8_PMUV3_PERFCTR_PC_WRITE_RETIRED			0x0C
+#define ARMV8_PMUV3_PERFCTR_BR_IMMED_RETIRED			0x0D
+#define ARMV8_PMUV3_PERFCTR_BR_RETURN_RETIRED			0x0E
+#define ARMV8_PMUV3_PERFCTR_UNALIGNED_LDST_RETIRED		0x0F
+#define ARMV8_PMUV3_PERFCTR_TTBR_WRITE_RETIRED			0x1C
 #define ARMV8_PMUV3_PERFCTR_CHAIN				0x1E
 #define ARMV8_PMUV3_PERFCTR_BR_RETIRED				0x21
 
 /* Common microarchitectural events. */
-#define ARMV8_PMUV3_PERFCTR_L1_ICACHE_REFILL			0x01
-#define ARMV8_PMUV3_PERFCTR_ITLB_REFILL				0x02
-#define ARMV8_PMUV3_PERFCTR_DTLB_REFILL				0x05
+#define ARMV8_PMUV3_PERFCTR_L1I_CACHE_REFILL			0x01
+#define ARMV8_PMUV3_PERFCTR_L1I_TLB_REFILL			0x02
+#define ARMV8_PMUV3_PERFCTR_L1D_TLB_REFILL			0x05
 #define ARMV8_PMUV3_PERFCTR_MEM_ACCESS				0x13
-#define ARMV8_PMUV3_PERFCTR_L1_ICACHE_ACCESS			0x14
-#define ARMV8_PMUV3_PERFCTR_L1_DCACHE_WB			0x15
-#define ARMV8_PMUV3_PERFCTR_L2_CACHE_ACCESS			0x16
-#define ARMV8_PMUV3_PERFCTR_L2_CACHE_REFILL			0x17
-#define ARMV8_PMUV3_PERFCTR_L2_CACHE_WB				0x18
+#define ARMV8_PMUV3_PERFCTR_L1I_CACHE				0x14
+#define ARMV8_PMUV3_PERFCTR_L1D_CACHE_WB			0x15
+#define ARMV8_PMUV3_PERFCTR_L2D_CACHE				0x16
+#define ARMV8_PMUV3_PERFCTR_L2D_CACHE_REFILL			0x17
+#define ARMV8_PMUV3_PERFCTR_L2D_CACHE_WB			0x18
 #define ARMV8_PMUV3_PERFCTR_BUS_ACCESS				0x19
-#define ARMV8_PMUV3_PERFCTR_MEM_ERROR				0x1A
+#define ARMV8_PMUV3_PERFCTR_MEMORY_ERROR			0x1A
 #define ARMV8_PMUV3_PERFCTR_BUS_CYCLES				0x1D
 #define ARMV8_PMUV3_PERFCTR_L1D_CACHE_ALLOCATE			0x1F
 #define ARMV8_PMUV3_PERFCTR_L2D_CACHE_ALLOCATE			0x20
@@ -85,89 +86,182 @@
 #define ARMV8_PMUV3_PERFCTR_L3D_CACHE				0x2B
 #define ARMV8_PMUV3_PERFCTR_L3D_CACHE_WB			0x2C
 #define ARMV8_PMUV3_PERFCTR_L2D_TLB_REFILL			0x2D
-#define ARMV8_PMUV3_PERFCTR_L21_TLB_REFILL			0x2E
+#define ARMV8_PMUV3_PERFCTR_L2I_TLB_REFILL			0x2E
 #define ARMV8_PMUV3_PERFCTR_L2D_TLB				0x2F
-#define ARMV8_PMUV3_PERFCTR_L21_TLB				0x30
+#define ARMV8_PMUV3_PERFCTR_L2I_TLB				0x30
 
-/* ARMv8 implementation defined event types. */
-#define ARMV8_IMPDEF_PERFCTR_L1_DCACHE_ACCESS_LD		0x40
-#define ARMV8_IMPDEF_PERFCTR_L1_DCACHE_ACCESS_ST		0x41
-#define ARMV8_IMPDEF_PERFCTR_L1_DCACHE_REFILL_LD		0x42
-#define ARMV8_IMPDEF_PERFCTR_L1_DCACHE_REFILL_ST		0x43
-#define ARMV8_IMPDEF_PERFCTR_DTLB_REFILL_LD			0x4C
-#define ARMV8_IMPDEF_PERFCTR_DTLB_REFILL_ST			0x4D
-#define ARMV8_IMPDEF_PERFCTR_DTLB_ACCESS_LD			0x4E
-#define ARMV8_IMPDEF_PERFCTR_DTLB_ACCESS_ST			0x4F
+/* ARMv8 recommended implementation defined event types */
+#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_RD			0x40
+#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WR			0x41
+#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_RD		0x42
+#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_WR		0x43
+#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_INNER		0x44
+#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_OUTER		0x45
+#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WB_VICTIM		0x46
+#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WB_CLEAN			0x47
+#define ARMV8_IMPDEF_PERFCTR_L1D_CACHE_INVAL			0x48
+
+#define ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_RD			0x4C
+#define ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_WR			0x4D
+#define ARMV8_IMPDEF_PERFCTR_L1D_TLB_RD				0x4E
+#define ARMV8_IMPDEF_PERFCTR_L1D_TLB_WR				0x4F
+#define ARMV8_IMPDEF_PERFCTR_L2D_CACHE_RD			0x50
+#define ARMV8_IMPDEF_PERFCTR_L2D_CACHE_WR			0x51
+#define ARMV8_IMPDEF_PERFCTR_L2D_CACHE_REFILL_RD		0x52
+#define ARMV8_IMPDEF_PERFCTR_L2D_CACHE_REFILL_WR		0x53
+
+#define ARMV8_IMPDEF_PERFCTR_L2D_CACHE_WB_VICTIM		0x56
+#define ARMV8_IMPDEF_PERFCTR_L2D_CACHE_WB_CLEAN			0x57
+#define ARMV8_IMPDEF_PERFCTR_L2D_CACHE_INVAL			0x58
+
+#define ARMV8_IMPDEF_PERFCTR_L2D_TLB_REFILL_RD			0x5C
+#define ARMV8_IMPDEF_PERFCTR_L2D_TLB_REFILL_WR			0x5D
+#define ARMV8_IMPDEF_PERFCTR_L2D_TLB_RD				0x5E
+#define ARMV8_IMPDEF_PERFCTR_L2D_TLB_WR				0x5F
+
+#define ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_RD			0x60
+#define ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_WR			0x61
+#define ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_SHARED			0x62
+#define ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_NOT_SHARED		0x63
+#define ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_NORMAL			0x64
+#define ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_PERIPH			0x65
+
+#define ARMV8_IMPDEF_PERFCTR_MEM_ACCESS_RD			0x66
+#define ARMV8_IMPDEF_PERFCTR_MEM_ACCESS_WR			0x67
+#define ARMV8_IMPDEF_PERFCTR_UNALIGNED_LD_SPEC			0x68
+#define ARMV8_IMPDEF_PERFCTR_UNALIGNED_ST_SPEC			0x69
+#define ARMV8_IMPDEF_PERFCTR_UNALIGNED_LDST_SPEC		0x6A
+
+#define ARMV8_IMPDEF_PERFCTR_LDREX_SPEC				0x6C
+#define ARMV8_IMPDEF_PERFCTR_STREX_PASS_SPEC			0x6D
+#define ARMV8_IMPDEF_PERFCTR_STREX_FAIL_SPEC			0x6E
+#define ARMV8_IMPDEF_PERFCTR_STREX_SPEC				0x6F
+#define ARMV8_IMPDEF_PERFCTR_LD_SPEC				0x70
+#define ARMV8_IMPDEF_PERFCTR_ST_SPEC				0x71
+#define ARMV8_IMPDEF_PERFCTR_LDST_SPEC				0x72
+#define ARMV8_IMPDEF_PERFCTR_DP_SPEC				0x73
+#define ARMV8_IMPDEF_PERFCTR_ASE_SPEC				0x74
+#define ARMV8_IMPDEF_PERFCTR_VFP_SPEC				0x75
+#define ARMV8_IMPDEF_PERFCTR_PC_WRITE_SPEC			0x76
+#define ARMV8_IMPDEF_PERFCTR_CRYPTO_SPEC			0x77
+#define ARMV8_IMPDEF_PERFCTR_BR_IMMED_SPEC			0x78
+#define ARMV8_IMPDEF_PERFCTR_BR_RETURN_SPEC			0x79
+#define ARMV8_IMPDEF_PERFCTR_BR_INDIRECT_SPEC			0x7A
+
+#define ARMV8_IMPDEF_PERFCTR_ISB_SPEC				0x7C
+#define ARMV8_IMPDEF_PERFCTR_DSB_SPEC				0x7D
+#define ARMV8_IMPDEF_PERFCTR_DMB_SPEC				0x7E
+
+#define ARMV8_IMPDEF_PERFCTR_EXC_UNDEF				0x81
+#define ARMV8_IMPDEF_PERFCTR_EXC_SVC				0x82
+#define ARMV8_IMPDEF_PERFCTR_EXC_PABORT				0x83
+#define ARMV8_IMPDEF_PERFCTR_EXC_DABORT				0x84
+
+#define ARMV8_IMPDEF_PERFCTR_EXC_IRQ				0x86
+#define ARMV8_IMPDEF_PERFCTR_EXC_FIQ				0x87
+#define ARMV8_IMPDEF_PERFCTR_EXC_SMC				0x88
+
+#define ARMV8_IMPDEF_PERFCTR_EXC_HVC				0x8A
+#define ARMV8_IMPDEF_PERFCTR_EXC_TRAP_PABORT			0x8B
+#define ARMV8_IMPDEF_PERFCTR_EXC_TRAP_DABORT			0x8C
+#define ARMV8_IMPDEF_PERFCTR_EXC_TRAP_OTHER			0x8D
+#define ARMV8_IMPDEF_PERFCTR_EXC_TRAP_IRQ			0x8E
+#define ARMV8_IMPDEF_PERFCTR_EXC_TRAP_FIQ			0x8F
+#define ARMV8_IMPDEF_PERFCTR_RC_LD_SPEC				0x90
+#define ARMV8_IMPDEF_PERFCTR_RC_ST_SPEC				0x91
+
+#define ARMV8_IMPDEF_PERFCTR_L3D_CACHE_RD			0xA0
+#define ARMV8_IMPDEF_PERFCTR_L3D_CACHE_WR			0xA1
+#define ARMV8_IMPDEF_PERFCTR_L3D_CACHE_REFILL_RD		0xA2
+#define ARMV8_IMPDEF_PERFCTR_L3D_CACHE_REFILL_WR		0xA3
+
+#define ARMV8_IMPDEF_PERFCTR_L3D_CACHE_WB_VICTIM		0xA6
+#define ARMV8_IMPDEF_PERFCTR_L3D_CACHE_WB_CLEAN			0xA7
+#define ARMV8_IMPDEF_PERFCTR_L3D_CACHE_INVAL			0xA8
 
 /* ARMv8 Cortex-A53 specific event types. */
-#define ARMV8_A53_PERFCTR_PREFETCH_LINEFILL			0xC2
+#define ARMV8_A53_PERFCTR_PREF_LINEFILL				0xC2
 
 /* ARMv8 Cavium ThunderX specific event types. */
-#define ARMV8_THUNDER_PERFCTR_L1_DCACHE_MISS_ST			0xE9
-#define ARMV8_THUNDER_PERFCTR_L1_DCACHE_PREF_ACCESS		0xEA
-#define ARMV8_THUNDER_PERFCTR_L1_DCACHE_PREF_MISS		0xEB
-#define ARMV8_THUNDER_PERFCTR_L1_ICACHE_PREF_ACCESS		0xEC
-#define ARMV8_THUNDER_PERFCTR_L1_ICACHE_PREF_MISS		0xED
+#define ARMV8_THUNDER_PERFCTR_L1D_CACHE_MISS_ST			0xE9
+#define ARMV8_THUNDER_PERFCTR_L1D_CACHE_PREF_ACCESS		0xEA
+#define ARMV8_THUNDER_PERFCTR_L1D_CACHE_PREF_MISS		0xEB
+#define ARMV8_THUNDER_PERFCTR_L1I_CACHE_PREF_ACCESS		0xEC
+#define ARMV8_THUNDER_PERFCTR_L1I_CACHE_PREF_MISS		0xED
 
 /* PMUv3 HW events mapping. */
 static const unsigned armv8_pmuv3_perf_map[PERF_COUNT_HW_MAX] = {
 	PERF_MAP_ALL_UNSUPPORTED,
-	[PERF_COUNT_HW_CPU_CYCLES]		= ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES,
-	[PERF_COUNT_HW_INSTRUCTIONS]		= ARMV8_PMUV3_PERFCTR_INSTR_EXECUTED,
-	[PERF_COUNT_HW_CACHE_REFERENCES]	= ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS,
-	[PERF_COUNT_HW_CACHE_MISSES]		= ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL,
-	[PERF_COUNT_HW_BRANCH_MISSES]		= ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,
+	[PERF_COUNT_HW_CPU_CYCLES]		= ARMV8_PMUV3_PERFCTR_CPU_CYCLES,
+	[PERF_COUNT_HW_INSTRUCTIONS]		= ARMV8_PMUV3_PERFCTR_INST_RETIRED,
+	[PERF_COUNT_HW_CACHE_REFERENCES]	= ARMV8_PMUV3_PERFCTR_L1D_CACHE,
+	[PERF_COUNT_HW_CACHE_MISSES]		= ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL,
+	[PERF_COUNT_HW_BRANCH_MISSES]		= ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
 };
 
 /* ARM Cortex-A53 HW events mapping. */
 static const unsigned armv8_a53_perf_map[PERF_COUNT_HW_MAX] = {
 	PERF_MAP_ALL_UNSUPPORTED,
-	[PERF_COUNT_HW_CPU_CYCLES]		= ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES,
-	[PERF_COUNT_HW_INSTRUCTIONS]		= ARMV8_PMUV3_PERFCTR_INSTR_EXECUTED,
-	[PERF_COUNT_HW_CACHE_REFERENCES]	= ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS,
-	[PERF_COUNT_HW_CACHE_MISSES]		= ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL,
-	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS]	= ARMV8_PMUV3_PERFCTR_PC_WRITE,
-	[PERF_COUNT_HW_BRANCH_MISSES]		= ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,
+	[PERF_COUNT_HW_CPU_CYCLES]		= ARMV8_PMUV3_PERFCTR_CPU_CYCLES,
+	[PERF_COUNT_HW_INSTRUCTIONS]		= ARMV8_PMUV3_PERFCTR_INST_RETIRED,
+	[PERF_COUNT_HW_CACHE_REFERENCES]	= ARMV8_PMUV3_PERFCTR_L1D_CACHE,
+	[PERF_COUNT_HW_CACHE_MISSES]		= ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL,
+	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS]	= ARMV8_PMUV3_PERFCTR_PC_WRITE_RETIRED,
+	[PERF_COUNT_HW_BRANCH_MISSES]		= ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
 	[PERF_COUNT_HW_BUS_CYCLES]		= ARMV8_PMUV3_PERFCTR_BUS_CYCLES,
 };
 
 /* ARM Cortex-A57 and Cortex-A72 events mapping. */
 static const unsigned armv8_a57_perf_map[PERF_COUNT_HW_MAX] = {
 	PERF_MAP_ALL_UNSUPPORTED,
-	[PERF_COUNT_HW_CPU_CYCLES]		= ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES,
-	[PERF_COUNT_HW_INSTRUCTIONS]		= ARMV8_PMUV3_PERFCTR_INSTR_EXECUTED,
-	[PERF_COUNT_HW_CACHE_REFERENCES]	= ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS,
-	[PERF_COUNT_HW_CACHE_MISSES]		= ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL,
-	[PERF_COUNT_HW_BRANCH_MISSES]		= ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,
+	[PERF_COUNT_HW_CPU_CYCLES]		= ARMV8_PMUV3_PERFCTR_CPU_CYCLES,
+	[PERF_COUNT_HW_INSTRUCTIONS]		= ARMV8_PMUV3_PERFCTR_INST_RETIRED,
+	[PERF_COUNT_HW_CACHE_REFERENCES]	= ARMV8_PMUV3_PERFCTR_L1D_CACHE,
+	[PERF_COUNT_HW_CACHE_MISSES]		= ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL,
+	[PERF_COUNT_HW_BRANCH_MISSES]		= ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
 	[PERF_COUNT_HW_BUS_CYCLES]		= ARMV8_PMUV3_PERFCTR_BUS_CYCLES,
 };
 
 static const unsigned armv8_thunder_perf_map[PERF_COUNT_HW_MAX] = {
 	PERF_MAP_ALL_UNSUPPORTED,
-	[PERF_COUNT_HW_CPU_CYCLES]		= ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES,
-	[PERF_COUNT_HW_INSTRUCTIONS]		= ARMV8_PMUV3_PERFCTR_INSTR_EXECUTED,
-	[PERF_COUNT_HW_CACHE_REFERENCES]	= ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS,
-	[PERF_COUNT_HW_CACHE_MISSES]		= ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL,
-	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS]	= ARMV8_PMUV3_PERFCTR_PC_WRITE,
-	[PERF_COUNT_HW_BRANCH_MISSES]		= ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,
+	[PERF_COUNT_HW_CPU_CYCLES]		= ARMV8_PMUV3_PERFCTR_CPU_CYCLES,
+	[PERF_COUNT_HW_INSTRUCTIONS]		= ARMV8_PMUV3_PERFCTR_INST_RETIRED,
+	[PERF_COUNT_HW_CACHE_REFERENCES]	= ARMV8_PMUV3_PERFCTR_L1D_CACHE,
+	[PERF_COUNT_HW_CACHE_MISSES]		= ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL,
+	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS]	= ARMV8_PMUV3_PERFCTR_PC_WRITE_RETIRED,
+	[PERF_COUNT_HW_BRANCH_MISSES]		= ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
 	[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = ARMV8_PMUV3_PERFCTR_STALL_FRONTEND,
 	[PERF_COUNT_HW_STALLED_CYCLES_BACKEND]	= ARMV8_PMUV3_PERFCTR_STALL_BACKEND,
 };
 
+/* Broadcom Vulcan events mapping */
+static const unsigned armv8_vulcan_perf_map[PERF_COUNT_HW_MAX] = {
+	PERF_MAP_ALL_UNSUPPORTED,
+	[PERF_COUNT_HW_CPU_CYCLES]		= ARMV8_PMUV3_PERFCTR_CPU_CYCLES,
+	[PERF_COUNT_HW_INSTRUCTIONS]		= ARMV8_PMUV3_PERFCTR_INST_RETIRED,
+	[PERF_COUNT_HW_CACHE_REFERENCES]	= ARMV8_PMUV3_PERFCTR_L1D_CACHE,
+	[PERF_COUNT_HW_CACHE_MISSES]		= ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL,
+	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS]	= ARMV8_PMUV3_PERFCTR_BR_RETIRED,
+	[PERF_COUNT_HW_BRANCH_MISSES]		= ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
+	[PERF_COUNT_HW_BUS_CYCLES]		= ARMV8_PMUV3_PERFCTR_BUS_CYCLES,
+	[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND]	= ARMV8_PMUV3_PERFCTR_STALL_FRONTEND,
+	[PERF_COUNT_HW_STALLED_CYCLES_BACKEND]	= ARMV8_PMUV3_PERFCTR_STALL_BACKEND,
+};
+
 static const unsigned armv8_pmuv3_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
 						[PERF_COUNT_HW_CACHE_OP_MAX]
 						[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
 	PERF_CACHE_MAP_ALL_UNSUPPORTED,
 
-	[C(L1D)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS,
-	[C(L1D)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL,
-	[C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS,
-	[C(L1D)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL,
+	[C(L1D)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_L1D_CACHE,
+	[C(L1D)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL,
+	[C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_L1D_CACHE,
+	[C(L1D)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL,
 
-	[C(BPU)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED,
-	[C(BPU)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,
-	[C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED,
-	[C(BPU)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,
+	[C(BPU)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_BR_PRED,
+	[C(BPU)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
+	[C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_BR_PRED,
+	[C(BPU)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
 };
 
 static const unsigned armv8_a53_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
@@ -175,21 +269,21 @@ static const unsigned armv8_a53_perf_cac
 					      [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
 	PERF_CACHE_MAP_ALL_UNSUPPORTED,
 
-	[C(L1D)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS,
-	[C(L1D)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL,
-	[C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS,
-	[C(L1D)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL,
-	[C(L1D)][C(OP_PREFETCH)][C(RESULT_MISS)] = ARMV8_A53_PERFCTR_PREFETCH_LINEFILL,
+	[C(L1D)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_L1D_CACHE,
+	[C(L1D)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL,
+	[C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_L1D_CACHE,
+	[C(L1D)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL,
+	[C(L1D)][C(OP_PREFETCH)][C(RESULT_MISS)] = ARMV8_A53_PERFCTR_PREF_LINEFILL,
 
-	[C(L1I)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_L1_ICACHE_ACCESS,
-	[C(L1I)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_L1_ICACHE_REFILL,
+	[C(L1I)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_L1I_CACHE,
+	[C(L1I)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_L1I_CACHE_REFILL,
 
-	[C(ITLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_ITLB_REFILL,
+	[C(ITLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_L1I_TLB_REFILL,
 
-	[C(BPU)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED,
-	[C(BPU)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,
-	[C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED,
-	[C(BPU)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,
+	[C(BPU)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_BR_PRED,
+	[C(BPU)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
+	[C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_BR_PRED,
+	[C(BPU)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
 };
 
 static const unsigned armv8_a57_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
@@ -197,23 +291,23 @@ static const unsigned armv8_a57_perf_cac
 					      [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
 	PERF_CACHE_MAP_ALL_UNSUPPORTED,
 
-	[C(L1D)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_IMPDEF_PERFCTR_L1_DCACHE_ACCESS_LD,
-	[C(L1D)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_IMPDEF_PERFCTR_L1_DCACHE_REFILL_LD,
-	[C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV8_IMPDEF_PERFCTR_L1_DCACHE_ACCESS_ST,
-	[C(L1D)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_IMPDEF_PERFCTR_L1_DCACHE_REFILL_ST,
+	[C(L1D)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_IMPDEF_PERFCTR_L1D_CACHE_RD,
+	[C(L1D)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_RD,
+	[C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WR,
+	[C(L1D)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_WR,
 
-	[C(L1I)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_L1_ICACHE_ACCESS,
-	[C(L1I)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_L1_ICACHE_REFILL,
+	[C(L1I)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_L1I_CACHE,
+	[C(L1I)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_L1I_CACHE_REFILL,
 
-	[C(DTLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_IMPDEF_PERFCTR_DTLB_REFILL_LD,
-	[C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_IMPDEF_PERFCTR_DTLB_REFILL_ST,
+	[C(DTLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_RD,
+	[C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_WR,
 
-	[C(ITLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_ITLB_REFILL,
+	[C(ITLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_L1I_TLB_REFILL,
 
-	[C(BPU)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED,
-	[C(BPU)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,
-	[C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED,
-	[C(BPU)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,
+	[C(BPU)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_BR_PRED,
+	[C(BPU)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
+	[C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_BR_PRED,
+	[C(BPU)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
 };
 
 static const unsigned armv8_thunder_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
@@ -221,67 +315,108 @@ static const unsigned armv8_thunder_perf
 						   [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
 	PERF_CACHE_MAP_ALL_UNSUPPORTED,
 
-	[C(L1D)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_IMPDEF_PERFCTR_L1_DCACHE_ACCESS_LD,
-	[C(L1D)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_IMPDEF_PERFCTR_L1_DCACHE_REFILL_LD,
-	[C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV8_IMPDEF_PERFCTR_L1_DCACHE_ACCESS_ST,
-	[C(L1D)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_THUNDER_PERFCTR_L1_DCACHE_MISS_ST,
-	[C(L1D)][C(OP_PREFETCH)][C(RESULT_ACCESS)] = ARMV8_THUNDER_PERFCTR_L1_DCACHE_PREF_ACCESS,
-	[C(L1D)][C(OP_PREFETCH)][C(RESULT_MISS)] = ARMV8_THUNDER_PERFCTR_L1_DCACHE_PREF_MISS,
+	[C(L1D)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_IMPDEF_PERFCTR_L1D_CACHE_RD,
+	[C(L1D)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_RD,
+	[C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WR,
+	[C(L1D)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_THUNDER_PERFCTR_L1D_CACHE_MISS_ST,
+	[C(L1D)][C(OP_PREFETCH)][C(RESULT_ACCESS)] = ARMV8_THUNDER_PERFCTR_L1D_CACHE_PREF_ACCESS,
+	[C(L1D)][C(OP_PREFETCH)][C(RESULT_MISS)] = ARMV8_THUNDER_PERFCTR_L1D_CACHE_PREF_MISS,
 
-	[C(L1I)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_L1_ICACHE_ACCESS,
-	[C(L1I)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_L1_ICACHE_REFILL,
-	[C(L1I)][C(OP_PREFETCH)][C(RESULT_ACCESS)] = ARMV8_THUNDER_PERFCTR_L1_ICACHE_PREF_ACCESS,
-	[C(L1I)][C(OP_PREFETCH)][C(RESULT_MISS)] = ARMV8_THUNDER_PERFCTR_L1_ICACHE_PREF_MISS,
+	[C(L1I)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_L1I_CACHE,
+	[C(L1I)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_L1I_CACHE_REFILL,
+	[C(L1I)][C(OP_PREFETCH)][C(RESULT_ACCESS)] = ARMV8_THUNDER_PERFCTR_L1I_CACHE_PREF_ACCESS,
+	[C(L1I)][C(OP_PREFETCH)][C(RESULT_MISS)] = ARMV8_THUNDER_PERFCTR_L1I_CACHE_PREF_MISS,
 
-	[C(DTLB)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_IMPDEF_PERFCTR_DTLB_ACCESS_LD,
-	[C(DTLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_IMPDEF_PERFCTR_DTLB_REFILL_LD,
-	[C(DTLB)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_DTLB_ACCESS_ST,
-	[C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_IMPDEF_PERFCTR_DTLB_REFILL_ST,
+	[C(DTLB)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_IMPDEF_PERFCTR_L1D_TLB_RD,
+	[C(DTLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_RD,
+	[C(DTLB)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_TLB_WR,
+	[C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_WR,
 
-	[C(ITLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_ITLB_REFILL,
+	[C(ITLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_L1I_TLB_REFILL,
 
-	[C(BPU)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED,
-	[C(BPU)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,
-	[C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED,
-	[C(BPU)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,
+	[C(BPU)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_BR_PRED,
+	[C(BPU)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
+	[C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_BR_PRED,
+	[C(BPU)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
 };
 
+static const unsigned armv8_vulcan_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+					      [PERF_COUNT_HW_CACHE_OP_MAX]
+					      [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+	PERF_CACHE_MAP_ALL_UNSUPPORTED,
+
+	[C(L1D)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_IMPDEF_PERFCTR_L1D_CACHE_RD,
+	[C(L1D)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_RD,
+	[C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV8_IMPDEF_PERFCTR_L1D_CACHE_WR,
+	[C(L1D)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_IMPDEF_PERFCTR_L1D_CACHE_REFILL_WR,
+
+	[C(L1I)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_L1I_CACHE,
+	[C(L1I)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_L1I_CACHE_REFILL,
+
+	[C(ITLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_L1I_TLB_REFILL,
+	[C(ITLB)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_L1I_TLB,
+
+	[C(DTLB)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_IMPDEF_PERFCTR_L1D_TLB_RD,
+	[C(DTLB)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_L1D_TLB_WR,
+	[C(DTLB)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_RD,
+	[C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_IMPDEF_PERFCTR_L1D_TLB_REFILL_WR,
+
+	[C(BPU)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_BR_PRED,
+	[C(BPU)][C(OP_READ)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
+	[C(BPU)][C(OP_WRITE)][C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_BR_PRED,
+	[C(BPU)][C(OP_WRITE)][C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
+
+	[C(NODE)][C(OP_READ)][C(RESULT_ACCESS)]	= ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_RD,
+	[C(NODE)][C(OP_WRITE)][C(RESULT_ACCESS)] = ARMV8_IMPDEF_PERFCTR_BUS_ACCESS_WR,
+};
+
+static ssize_t
+armv8pmu_events_sysfs_show(struct device *dev,
+			   struct device_attribute *attr, char *page)
+{
+	struct perf_pmu_events_attr *pmu_attr;
+
+	pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr);
+
+	return sprintf(page, "event=0x%03llx\n", pmu_attr->id);
+}
+
 #define ARMV8_EVENT_ATTR_RESOLVE(m) #m
 #define ARMV8_EVENT_ATTR(name, config) \
-	PMU_EVENT_ATTR_STRING(name, armv8_event_attr_##name, \
-			      "event=" ARMV8_EVENT_ATTR_RESOLVE(config))
+	PMU_EVENT_ATTR(name, armv8_event_attr_##name, \
+		       config, armv8pmu_events_sysfs_show)
 
-ARMV8_EVENT_ATTR(sw_incr, ARMV8_PMUV3_PERFCTR_PMNC_SW_INCR);
-ARMV8_EVENT_ATTR(l1i_cache_refill, ARMV8_PMUV3_PERFCTR_L1_ICACHE_REFILL);
-ARMV8_EVENT_ATTR(l1i_tlb_refill, ARMV8_PMUV3_PERFCTR_ITLB_REFILL);
-ARMV8_EVENT_ATTR(l1d_cache_refill, ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL);
-ARMV8_EVENT_ATTR(l1d_cache, ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS);
-ARMV8_EVENT_ATTR(l1d_tlb_refill, ARMV8_PMUV3_PERFCTR_DTLB_REFILL);
-ARMV8_EVENT_ATTR(ld_retired, ARMV8_PMUV3_PERFCTR_MEM_READ);
-ARMV8_EVENT_ATTR(st_retired, ARMV8_PMUV3_PERFCTR_MEM_WRITE);
-ARMV8_EVENT_ATTR(inst_retired, ARMV8_PMUV3_PERFCTR_INSTR_EXECUTED);
+ARMV8_EVENT_ATTR(sw_incr, ARMV8_PMUV3_PERFCTR_SW_INCR);
+ARMV8_EVENT_ATTR(l1i_cache_refill, ARMV8_PMUV3_PERFCTR_L1I_CACHE_REFILL);
+ARMV8_EVENT_ATTR(l1i_tlb_refill, ARMV8_PMUV3_PERFCTR_L1I_TLB_REFILL);
+ARMV8_EVENT_ATTR(l1d_cache_refill, ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL);
+ARMV8_EVENT_ATTR(l1d_cache, ARMV8_PMUV3_PERFCTR_L1D_CACHE);
+ARMV8_EVENT_ATTR(l1d_tlb_refill, ARMV8_PMUV3_PERFCTR_L1D_TLB_REFILL);
+ARMV8_EVENT_ATTR(ld_retired, ARMV8_PMUV3_PERFCTR_LD_RETIRED);
+ARMV8_EVENT_ATTR(st_retired, ARMV8_PMUV3_PERFCTR_ST_RETIRED);
+ARMV8_EVENT_ATTR(inst_retired, ARMV8_PMUV3_PERFCTR_INST_RETIRED);
 ARMV8_EVENT_ATTR(exc_taken, ARMV8_PMUV3_PERFCTR_EXC_TAKEN);
-ARMV8_EVENT_ATTR(exc_return, ARMV8_PMUV3_PERFCTR_EXC_EXECUTED);
-ARMV8_EVENT_ATTR(cid_write_retired, ARMV8_PMUV3_PERFCTR_CID_WRITE);
-ARMV8_EVENT_ATTR(pc_write_retired, ARMV8_PMUV3_PERFCTR_PC_WRITE);
-ARMV8_EVENT_ATTR(br_immed_retired, ARMV8_PMUV3_PERFCTR_PC_IMM_BRANCH);
-ARMV8_EVENT_ATTR(br_return_retired, ARMV8_PMUV3_PERFCTR_PC_PROC_RETURN);
-ARMV8_EVENT_ATTR(unaligned_ldst_retired, ARMV8_PMUV3_PERFCTR_MEM_UNALIGNED_ACCESS);
-ARMV8_EVENT_ATTR(br_mis_pred, ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED);
-ARMV8_EVENT_ATTR(cpu_cycles, ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES);
-ARMV8_EVENT_ATTR(br_pred, ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED);
+ARMV8_EVENT_ATTR(exc_return, ARMV8_PMUV3_PERFCTR_EXC_RETURN);
+ARMV8_EVENT_ATTR(cid_write_retired, ARMV8_PMUV3_PERFCTR_CID_WRITE_RETIRED);
+ARMV8_EVENT_ATTR(pc_write_retired, ARMV8_PMUV3_PERFCTR_PC_WRITE_RETIRED);
+ARMV8_EVENT_ATTR(br_immed_retired, ARMV8_PMUV3_PERFCTR_BR_IMMED_RETIRED);
+ARMV8_EVENT_ATTR(br_return_retired, ARMV8_PMUV3_PERFCTR_BR_RETURN_RETIRED);
+ARMV8_EVENT_ATTR(unaligned_ldst_retired, ARMV8_PMUV3_PERFCTR_UNALIGNED_LDST_RETIRED);
+ARMV8_EVENT_ATTR(br_mis_pred, ARMV8_PMUV3_PERFCTR_BR_MIS_PRED);
+ARMV8_EVENT_ATTR(cpu_cycles, ARMV8_PMUV3_PERFCTR_CPU_CYCLES);
+ARMV8_EVENT_ATTR(br_pred, ARMV8_PMUV3_PERFCTR_BR_PRED);
 ARMV8_EVENT_ATTR(mem_access, ARMV8_PMUV3_PERFCTR_MEM_ACCESS);
-ARMV8_EVENT_ATTR(l1i_cache, ARMV8_PMUV3_PERFCTR_L1_ICACHE_ACCESS);
-ARMV8_EVENT_ATTR(l1d_cache_wb, ARMV8_PMUV3_PERFCTR_L1_DCACHE_WB);
-ARMV8_EVENT_ATTR(l2d_cache, ARMV8_PMUV3_PERFCTR_L2_CACHE_ACCESS);
-ARMV8_EVENT_ATTR(l2d_cache_refill, ARMV8_PMUV3_PERFCTR_L2_CACHE_REFILL);
-ARMV8_EVENT_ATTR(l2d_cache_wb, ARMV8_PMUV3_PERFCTR_L2_CACHE_WB);
+ARMV8_EVENT_ATTR(l1i_cache, ARMV8_PMUV3_PERFCTR_L1I_CACHE);
+ARMV8_EVENT_ATTR(l1d_cache_wb, ARMV8_PMUV3_PERFCTR_L1D_CACHE_WB);
+ARMV8_EVENT_ATTR(l2d_cache, ARMV8_PMUV3_PERFCTR_L2D_CACHE);
+ARMV8_EVENT_ATTR(l2d_cache_refill, ARMV8_PMUV3_PERFCTR_L2D_CACHE_REFILL);
+ARMV8_EVENT_ATTR(l2d_cache_wb, ARMV8_PMUV3_PERFCTR_L2D_CACHE_WB);
 ARMV8_EVENT_ATTR(bus_access, ARMV8_PMUV3_PERFCTR_BUS_ACCESS);
-ARMV8_EVENT_ATTR(memory_error, ARMV8_PMUV3_PERFCTR_MEM_ERROR);
-ARMV8_EVENT_ATTR(inst_spec, ARMV8_PMUV3_PERFCTR_OP_SPEC);
-ARMV8_EVENT_ATTR(ttbr_write_retired, ARMV8_PMUV3_PERFCTR_TTBR_WRITE);
+ARMV8_EVENT_ATTR(memory_error, ARMV8_PMUV3_PERFCTR_MEMORY_ERROR);
+ARMV8_EVENT_ATTR(inst_spec, ARMV8_PMUV3_PERFCTR_INST_SPEC);
+ARMV8_EVENT_ATTR(ttbr_write_retired, ARMV8_PMUV3_PERFCTR_TTBR_WRITE_RETIRED);
 ARMV8_EVENT_ATTR(bus_cycles, ARMV8_PMUV3_PERFCTR_BUS_CYCLES);
-ARMV8_EVENT_ATTR(chain, ARMV8_PMUV3_PERFCTR_CHAIN);
+/* Don't expose the chain event in /sys, since it's useless in isolation */
 ARMV8_EVENT_ATTR(l1d_cache_allocate, ARMV8_PMUV3_PERFCTR_L1D_CACHE_ALLOCATE);
 ARMV8_EVENT_ATTR(l2d_cache_allocate, ARMV8_PMUV3_PERFCTR_L2D_CACHE_ALLOCATE);
 ARMV8_EVENT_ATTR(br_retired, ARMV8_PMUV3_PERFCTR_BR_RETIRED);
@@ -297,9 +432,9 @@ ARMV8_EVENT_ATTR(l3d_cache_refill, ARMV8
 ARMV8_EVENT_ATTR(l3d_cache, ARMV8_PMUV3_PERFCTR_L3D_CACHE);
 ARMV8_EVENT_ATTR(l3d_cache_wb, ARMV8_PMUV3_PERFCTR_L3D_CACHE_WB);
 ARMV8_EVENT_ATTR(l2d_tlb_refill, ARMV8_PMUV3_PERFCTR_L2D_TLB_REFILL);
-ARMV8_EVENT_ATTR(l21_tlb_refill, ARMV8_PMUV3_PERFCTR_L21_TLB_REFILL);
+ARMV8_EVENT_ATTR(l2i_tlb_refill, ARMV8_PMUV3_PERFCTR_L2I_TLB_REFILL);
 ARMV8_EVENT_ATTR(l2d_tlb, ARMV8_PMUV3_PERFCTR_L2D_TLB);
-ARMV8_EVENT_ATTR(l21_tlb, ARMV8_PMUV3_PERFCTR_L21_TLB);
+ARMV8_EVENT_ATTR(l2i_tlb, ARMV8_PMUV3_PERFCTR_L2I_TLB);
 
 static struct attribute *armv8_pmuv3_event_attrs[] = {
 	&armv8_event_attr_sw_incr.attr.attr,
@@ -332,7 +467,6 @@ static struct attribute *armv8_pmuv3_eve
 	&armv8_event_attr_inst_spec.attr.attr,
 	&armv8_event_attr_ttbr_write_retired.attr.attr,
 	&armv8_event_attr_bus_cycles.attr.attr,
-	&armv8_event_attr_chain.attr.attr,
 	&armv8_event_attr_l1d_cache_allocate.attr.attr,
 	&armv8_event_attr_l2d_cache_allocate.attr.attr,
 	&armv8_event_attr_br_retired.attr.attr,
@@ -348,15 +482,33 @@ static struct attribute *armv8_pmuv3_eve
 	&armv8_event_attr_l3d_cache.attr.attr,
 	&armv8_event_attr_l3d_cache_wb.attr.attr,
 	&armv8_event_attr_l2d_tlb_refill.attr.attr,
-	&armv8_event_attr_l21_tlb_refill.attr.attr,
+	&armv8_event_attr_l2i_tlb_refill.attr.attr,
 	&armv8_event_attr_l2d_tlb.attr.attr,
-	&armv8_event_attr_l21_tlb.attr.attr,
+	&armv8_event_attr_l2i_tlb.attr.attr,
 	NULL,
 };
 
+static umode_t
+armv8pmu_event_attr_is_visible(struct kobject *kobj,
+			       struct attribute *attr, int unused)
+{
+	struct device *dev = kobj_to_dev(kobj);
+	struct pmu *pmu = dev_get_drvdata(dev);
+	struct arm_pmu *cpu_pmu = container_of(pmu, struct arm_pmu, pmu);
+	struct perf_pmu_events_attr *pmu_attr;
+
+	pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr.attr);
+
+	if (test_bit(pmu_attr->id, cpu_pmu->pmceid_bitmap))
+		return attr->mode;
+
+	return 0;
+}
+
 static struct attribute_group armv8_pmuv3_events_attr_group = {
 	.name = "events",
 	.attrs = armv8_pmuv3_event_attrs,
+	.is_visible = armv8pmu_event_attr_is_visible,
 };
 
 PMU_FORMAT_ATTR(event, "config:0-9");
@@ -397,16 +549,14 @@ static const struct attribute_group *arm
 
 static inline u32 armv8pmu_pmcr_read(void)
 {
-	u32 val;
-	asm volatile("mrs %0, pmcr_el0" : "=r" (val));
-	return val;
+	return read_sysreg(pmcr_el0);
 }
 
 static inline void armv8pmu_pmcr_write(u32 val)
 {
 	val &= ARMV8_PMU_PMCR_MASK;
 	isb();
-	asm volatile("msr pmcr_el0, %0" :: "r" (val));
+	write_sysreg(val, pmcr_el0);
 }
 
 static inline int armv8pmu_has_overflowed(u32 pmovsr)
@@ -428,7 +578,7 @@ static inline int armv8pmu_counter_has_o
 static inline int armv8pmu_select_counter(int idx)
 {
 	u32 counter = ARMV8_IDX_TO_COUNTER(idx);
-	asm volatile("msr pmselr_el0, %0" :: "r" (counter));
+	write_sysreg(counter, pmselr_el0);
 	isb();
 
 	return idx;
@@ -445,9 +595,9 @@ static inline u32 armv8pmu_read_counter(
 		pr_err("CPU%u reading wrong counter %d\n",
 			smp_processor_id(), idx);
 	else if (idx == ARMV8_IDX_CYCLE_COUNTER)
-		asm volatile("mrs %0, pmccntr_el0" : "=r" (value));
+		value = read_sysreg(pmccntr_el0);
 	else if (armv8pmu_select_counter(idx) == idx)
-		asm volatile("mrs %0, pmxevcntr_el0" : "=r" (value));
+		value = read_sysreg(pmxevcntr_el0);
 
 	return value;
 }
@@ -469,47 +619,47 @@ static inline void armv8pmu_write_counte
 		 */
 		u64 value64 = 0xffffffff00000000ULL | value;
 
-		asm volatile("msr pmccntr_el0, %0" :: "r" (value64));
+		write_sysreg(value64, pmccntr_el0);
 	} else if (armv8pmu_select_counter(idx) == idx)
-		asm volatile("msr pmxevcntr_el0, %0" :: "r" (value));
+		write_sysreg(value, pmxevcntr_el0);
 }
 
 static inline void armv8pmu_write_evtype(int idx, u32 val)
 {
 	if (armv8pmu_select_counter(idx) == idx) {
 		val &= ARMV8_PMU_EVTYPE_MASK;
-		asm volatile("msr pmxevtyper_el0, %0" :: "r" (val));
+		write_sysreg(val, pmxevtyper_el0);
 	}
 }
 
 static inline int armv8pmu_enable_counter(int idx)
 {
 	u32 counter = ARMV8_IDX_TO_COUNTER(idx);
-	asm volatile("msr pmcntenset_el0, %0" :: "r" (BIT(counter)));
+	write_sysreg(BIT(counter), pmcntenset_el0);
 	return idx;
 }
 
 static inline int armv8pmu_disable_counter(int idx)
 {
 	u32 counter = ARMV8_IDX_TO_COUNTER(idx);
-	asm volatile("msr pmcntenclr_el0, %0" :: "r" (BIT(counter)));
+	write_sysreg(BIT(counter), pmcntenclr_el0);
 	return idx;
 }
 
 static inline int armv8pmu_enable_intens(int idx)
 {
 	u32 counter = ARMV8_IDX_TO_COUNTER(idx);
-	asm volatile("msr pmintenset_el1, %0" :: "r" (BIT(counter)));
+	write_sysreg(BIT(counter), pmintenset_el1);
 	return idx;
 }
 
 static inline int armv8pmu_disable_intens(int idx)
 {
 	u32 counter = ARMV8_IDX_TO_COUNTER(idx);
-	asm volatile("msr pmintenclr_el1, %0" :: "r" (BIT(counter)));
+	write_sysreg(BIT(counter), pmintenclr_el1);
 	isb();
 	/* Clear the overflow flag in case an interrupt is pending. */
-	asm volatile("msr pmovsclr_el0, %0" :: "r" (BIT(counter)));
+	write_sysreg(BIT(counter), pmovsclr_el0);
 	isb();
 
 	return idx;
@@ -520,11 +670,11 @@ static inline u32 armv8pmu_getreset_flag
 	u32 value;
 
 	/* Read */
-	asm volatile("mrs %0, pmovsclr_el0" : "=r" (value));
+	value = read_sysreg(pmovsclr_el0);
 
 	/* Write to clear flags */
 	value &= ARMV8_PMU_OVSR_MASK;
-	asm volatile("msr pmovsclr_el0, %0" :: "r" (value));
+	write_sysreg(value, pmovsclr_el0);
 
 	return value;
 }
@@ -685,7 +835,7 @@ static int armv8pmu_get_event_idx(struct
 	unsigned long evtype = hwc->config_base & ARMV8_PMU_EVTYPE_EVENT;
 
 	/* Always place a cycle counter into the cycle counter. */
-	if (evtype == ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES) {
+	if (evtype == ARMV8_PMUV3_PERFCTR_CPU_CYCLES) {
 		if (test_and_set_bit(ARMV8_IDX_CYCLE_COUNTER, cpuc->used_mask))
 			return -EAGAIN;
 
@@ -781,22 +931,38 @@ static int armv8_thunder_map_event(struc
 				ARMV8_PMU_EVTYPE_EVENT);
 }
 
-static void armv8pmu_read_num_pmnc_events(void *info)
+static int armv8_vulcan_map_event(struct perf_event *event)
 {
-	int *nb_cnt = info;
+	return armpmu_map_event(event, &armv8_vulcan_perf_map,
+				&armv8_vulcan_perf_cache_map,
+				ARMV8_PMU_EVTYPE_EVENT);
+}
+
+static void __armv8pmu_probe_pmu(void *info)
+{
+	struct arm_pmu *cpu_pmu = info;
+	u32 pmceid[2];
 
 	/* Read the nb of CNTx counters supported from PMNC */
-	*nb_cnt = (armv8pmu_pmcr_read() >> ARMV8_PMU_PMCR_N_SHIFT) & ARMV8_PMU_PMCR_N_MASK;
+	cpu_pmu->num_events = (armv8pmu_pmcr_read() >> ARMV8_PMU_PMCR_N_SHIFT)
+		& ARMV8_PMU_PMCR_N_MASK;
 
 	/* Add the CPU cycles counter */
-	*nb_cnt += 1;
+	cpu_pmu->num_events += 1;
+
+	pmceid[0] = read_sysreg(pmceid0_el0);
+	pmceid[1] = read_sysreg(pmceid1_el0);
+
+	bitmap_from_u32array(cpu_pmu->pmceid_bitmap,
+			     ARMV8_PMUV3_MAX_COMMON_EVENTS, pmceid,
+			     ARRAY_SIZE(pmceid));
 }
 
-static int armv8pmu_probe_num_events(struct arm_pmu *arm_pmu)
+static int armv8pmu_probe_pmu(struct arm_pmu *cpu_pmu)
 {
-	return smp_call_function_any(&arm_pmu->supported_cpus,
-				    armv8pmu_read_num_pmnc_events,
-				    &arm_pmu->num_events, 1);
+	return smp_call_function_any(&cpu_pmu->supported_cpus,
+				    __armv8pmu_probe_pmu,
+				    cpu_pmu, 1);
 }
 
 static void armv8_pmu_init(struct arm_pmu *cpu_pmu)
@@ -819,7 +985,8 @@ static int armv8_pmuv3_init(struct arm_p
 	armv8_pmu_init(cpu_pmu);
 	cpu_pmu->name			= "armv8_pmuv3";
 	cpu_pmu->map_event		= armv8_pmuv3_map_event;
-	return armv8pmu_probe_num_events(cpu_pmu);
+	cpu_pmu->pmu.attr_groups	= armv8_pmuv3_attr_groups;
+	return armv8pmu_probe_pmu(cpu_pmu);
 }
 
 static int armv8_a53_pmu_init(struct arm_pmu *cpu_pmu)
@@ -828,7 +995,7 @@ static int armv8_a53_pmu_init(struct arm
 	cpu_pmu->name			= "armv8_cortex_a53";
 	cpu_pmu->map_event		= armv8_a53_map_event;
 	cpu_pmu->pmu.attr_groups	= armv8_pmuv3_attr_groups;
-	return armv8pmu_probe_num_events(cpu_pmu);
+	return armv8pmu_probe_pmu(cpu_pmu);
 }
 
 static int armv8_a57_pmu_init(struct arm_pmu *cpu_pmu)
@@ -837,7 +1004,7 @@ static int armv8_a57_pmu_init(struct arm
 	cpu_pmu->name			= "armv8_cortex_a57";
 	cpu_pmu->map_event		= armv8_a57_map_event;
 	cpu_pmu->pmu.attr_groups	= armv8_pmuv3_attr_groups;
-	return armv8pmu_probe_num_events(cpu_pmu);
+	return armv8pmu_probe_pmu(cpu_pmu);
 }
 
 static int armv8_a72_pmu_init(struct arm_pmu *cpu_pmu)
@@ -846,7 +1013,7 @@ static int armv8_a72_pmu_init(struct arm
 	cpu_pmu->name			= "armv8_cortex_a72";
 	cpu_pmu->map_event		= armv8_a57_map_event;
 	cpu_pmu->pmu.attr_groups	= armv8_pmuv3_attr_groups;
-	return armv8pmu_probe_num_events(cpu_pmu);
+	return armv8pmu_probe_pmu(cpu_pmu);
 }
 
 static int armv8_thunder_pmu_init(struct arm_pmu *cpu_pmu)
@@ -855,7 +1022,16 @@ static int armv8_thunder_pmu_init(struct
 	cpu_pmu->name			= "armv8_cavium_thunder";
 	cpu_pmu->map_event		= armv8_thunder_map_event;
 	cpu_pmu->pmu.attr_groups	= armv8_pmuv3_attr_groups;
-	return armv8pmu_probe_num_events(cpu_pmu);
+	return armv8pmu_probe_pmu(cpu_pmu);
+}
+
+static int armv8_vulcan_pmu_init(struct arm_pmu *cpu_pmu)
+{
+	armv8_pmu_init(cpu_pmu);
+	cpu_pmu->name			= "armv8_brcm_vulcan";
+	cpu_pmu->map_event		= armv8_vulcan_map_event;
+	cpu_pmu->pmu.attr_groups	= armv8_pmuv3_attr_groups;
+	return armv8pmu_probe_pmu(cpu_pmu);
 }
 
 static const struct of_device_id armv8_pmu_of_device_ids[] = {
@@ -864,6 +1040,7 @@ static const struct of_device_id armv8_p
 	{.compatible = "arm,cortex-a57-pmu",	.data = armv8_a57_pmu_init},
 	{.compatible = "arm,cortex-a72-pmu",	.data = armv8_a72_pmu_init},
 	{.compatible = "cavium,thunder-pmu",	.data = armv8_thunder_pmu_init},
+	{.compatible = "brcm,vulcan-pmu",	.data = armv8_vulcan_pmu_init},
 	{},
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kernel/process.c linux-libre-4.7-gnu/arch/arm64/kernel/process.c
--- linux-libre-4.6-gnu/arch/arm64/kernel/process.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kernel/process.c	2016-07-24 15:23:50.000000000 -0400
@@ -200,13 +200,6 @@ void show_regs(struct pt_regs * regs)
 	__show_regs(regs);
 }
 
-/*
- * Free current thread data structures etc..
- */
-void exit_thread(void)
-{
-}
-
 static void tls_thread_flush(void)
 {
 	asm ("msr tpidr_el0, xzr");
@@ -265,9 +258,6 @@ int copy_thread(unsigned long clone_flag
 		if (stack_start) {
 			if (is_compat_thread(task_thread_info(p)))
 				childregs->compat_sp = stack_start;
-			/* 16-byte aligned stack mandatory on AArch64 */
-			else if (stack_start & 15)
-				return -EINVAL;
 			else
 				childregs->sp = stack_start;
 		}
@@ -382,13 +372,14 @@ unsigned long arch_align_stack(unsigned
 	return sp & ~0xf;
 }
 
-static unsigned long randomize_base(unsigned long base)
-{
-	unsigned long range_end = base + (STACK_RND_MASK << PAGE_SHIFT) + 1;
-	return randomize_range(base, range_end, 0) ? : base;
-}
-
 unsigned long arch_randomize_brk(struct mm_struct *mm)
 {
-	return randomize_base(mm->brk);
+	unsigned long range_end = mm->brk;
+
+	if (is_compat_task())
+		range_end += 0x02000000;
+	else
+		range_end += 0x40000000;
+
+	return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kernel/setup.c linux-libre-4.7-gnu/arch/arm64/kernel/setup.c
--- linux-libre-4.6-gnu/arch/arm64/kernel/setup.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kernel/setup.c	2016-07-24 15:23:50.000000000 -0400
@@ -53,6 +53,7 @@
 #include <asm/cpufeature.h>
 #include <asm/cpu_ops.h>
 #include <asm/kasan.h>
+#include <asm/numa.h>
 #include <asm/sections.h>
 #include <asm/setup.h>
 #include <asm/smp_plat.h>
@@ -175,7 +176,6 @@ static void __init smp_build_mpidr_hash(
 	 */
 	if (mpidr_hash_size() > 4 * num_possible_cpus())
 		pr_warn("Large number of MPIDR hash buckets detected\n");
-	__flush_dcache_area(&mpidr_hash, sizeof(struct mpidr_hash));
 }
 
 static void __init setup_machine_fdt(phys_addr_t dt_phys)
@@ -224,69 +224,6 @@ static void __init request_standard_reso
 	}
 }
 
-#ifdef CONFIG_BLK_DEV_INITRD
-/*
- * Relocate initrd if it is not completely within the linear mapping.
- * This would be the case if mem= cuts out all or part of it.
- */
-static void __init relocate_initrd(void)
-{
-	phys_addr_t orig_start = __virt_to_phys(initrd_start);
-	phys_addr_t orig_end = __virt_to_phys(initrd_end);
-	phys_addr_t ram_end = memblock_end_of_DRAM();
-	phys_addr_t new_start;
-	unsigned long size, to_free = 0;
-	void *dest;
-
-	if (orig_end <= ram_end)
-		return;
-
-	/*
-	 * Any of the original initrd which overlaps the linear map should
-	 * be freed after relocating.
-	 */
-	if (orig_start < ram_end)
-		to_free = ram_end - orig_start;
-
-	size = orig_end - orig_start;
-	if (!size)
-		return;
-
-	/* initrd needs to be relocated completely inside linear mapping */
-	new_start = memblock_find_in_range(0, PFN_PHYS(max_pfn),
-					   size, PAGE_SIZE);
-	if (!new_start)
-		panic("Cannot relocate initrd of size %ld\n", size);
-	memblock_reserve(new_start, size);
-
-	initrd_start = __phys_to_virt(new_start);
-	initrd_end   = initrd_start + size;
-
-	pr_info("Moving initrd from [%llx-%llx] to [%llx-%llx]\n",
-		orig_start, orig_start + size - 1,
-		new_start, new_start + size - 1);
-
-	dest = (void *)initrd_start;
-
-	if (to_free) {
-		memcpy(dest, (void *)__phys_to_virt(orig_start), to_free);
-		dest += to_free;
-	}
-
-	copy_from_early_mem(dest, orig_start + to_free, size - to_free);
-
-	if (to_free) {
-		pr_info("Freeing original RAMDISK from [%llx-%llx]\n",
-			orig_start, orig_start + to_free - 1);
-		memblock_free(orig_start, to_free);
-	}
-}
-#else
-static inline void __init relocate_initrd(void)
-{
-}
-#endif
-
 u64 __cpu_logical_map[NR_CPUS] = { [0 ... NR_CPUS-1] = INVALID_HWID };
 
 void __init setup_arch(char **cmdline_p)
@@ -327,7 +264,11 @@ void __init setup_arch(char **cmdline_p)
 	acpi_boot_table_init();
 
 	paging_init();
-	relocate_initrd();
+
+	if (acpi_disabled)
+		unflatten_device_tree();
+
+	bootmem_init();
 
 	kasan_init();
 
@@ -335,12 +276,11 @@ void __init setup_arch(char **cmdline_p)
 
 	early_ioremap_reset();
 
-	if (acpi_disabled) {
-		unflatten_device_tree();
+	if (acpi_disabled)
 		psci_dt_init();
-	} else {
+	else
 		psci_acpi_init();
-	}
+
 	xen_early_init();
 
 	cpu_read_bootcpu_ops();
@@ -379,6 +319,9 @@ static int __init topology_init(void)
 {
 	int i;
 
+	for_each_online_node(i)
+		register_one_node(i);
+
 	for_each_possible_cpu(i) {
 		struct cpu *cpu = &per_cpu(cpu_data.cpu, i);
 		cpu->hotpluggable = 1;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kernel/sleep.S linux-libre-4.7-gnu/arch/arm64/kernel/sleep.S
--- linux-libre-4.6-gnu/arch/arm64/kernel/sleep.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kernel/sleep.S	2016-07-24 15:23:50.000000000 -0400
@@ -49,39 +49,32 @@
 	orr	\dst, \dst, \mask		// dst|=(aff3>>rs3)
 	.endm
 /*
- * Save CPU state for a suspend and execute the suspend finisher.
- * On success it will return 0 through cpu_resume - ie through a CPU
- * soft/hard reboot from the reset vector.
- * On failure it returns the suspend finisher return value or force
- * -EOPNOTSUPP if the finisher erroneously returns 0 (the suspend finisher
- * is not allowed to return, if it does this must be considered failure).
- * It saves callee registers, and allocates space on the kernel stack
- * to save the CPU specific registers + some other data for resume.
+ * Save CPU state in the provided sleep_stack_data area, and publish its
+ * location for cpu_resume()'s use in sleep_save_stash.
  *
- *  x0 = suspend finisher argument
- *  x1 = suspend finisher function pointer
+ * cpu_resume() will restore this saved state, and return. Because the
+ * link-register is saved and restored, it will appear to return from this
+ * function. So that the caller can tell the suspend/resume paths apart,
+ * __cpu_suspend_enter() will always return a non-zero value, whereas the
+ * path through cpu_resume() will return 0.
+ *
+ *  x0 = struct sleep_stack_data area
  */
 ENTRY(__cpu_suspend_enter)
-	stp	x29, lr, [sp, #-96]!
-	stp	x19, x20, [sp,#16]
-	stp	x21, x22, [sp,#32]
-	stp	x23, x24, [sp,#48]
-	stp	x25, x26, [sp,#64]
-	stp	x27, x28, [sp,#80]
-	/*
-	 * Stash suspend finisher and its argument in x20 and x19
-	 */
-	mov	x19, x0
-	mov	x20, x1
+	stp	x29, lr, [x0, #SLEEP_STACK_DATA_CALLEE_REGS]
+	stp	x19, x20, [x0,#SLEEP_STACK_DATA_CALLEE_REGS+16]
+	stp	x21, x22, [x0,#SLEEP_STACK_DATA_CALLEE_REGS+32]
+	stp	x23, x24, [x0,#SLEEP_STACK_DATA_CALLEE_REGS+48]
+	stp	x25, x26, [x0,#SLEEP_STACK_DATA_CALLEE_REGS+64]
+	stp	x27, x28, [x0,#SLEEP_STACK_DATA_CALLEE_REGS+80]
+
+	/* save the sp in cpu_suspend_ctx */
 	mov	x2, sp
-	sub	sp, sp, #CPU_SUSPEND_SZ	// allocate cpu_suspend_ctx
-	mov	x0, sp
-	/*
-	 * x0 now points to struct cpu_suspend_ctx allocated on the stack
-	 */
-	str	x2, [x0, #CPU_CTX_SP]
-	ldr	x1, =sleep_save_sp
-	ldr	x1, [x1, #SLEEP_SAVE_SP_VIRT]
+	str	x2, [x0, #SLEEP_STACK_DATA_SYSTEM_REGS + CPU_CTX_SP]
+
+	/* find the mpidr_hash */
+	ldr	x1, =sleep_save_stash
+	ldr	x1, [x1]
 	mrs	x7, mpidr_el1
 	ldr	x9, =mpidr_hash
 	ldr	x10, [x9, #MPIDR_HASH_MASK]
@@ -93,74 +86,28 @@ ENTRY(__cpu_suspend_enter)
 	ldp	w5, w6, [x9, #(MPIDR_HASH_SHIFTS + 8)]
 	compute_mpidr_hash x8, x3, x4, x5, x6, x7, x10
 	add	x1, x1, x8, lsl #3
-	bl	__cpu_suspend_save
-	/*
-	 * Grab suspend finisher in x20 and its argument in x19
-	 */
-	mov	x0, x19
-	mov	x1, x20
-	/*
-	 * We are ready for power down, fire off the suspend finisher
-	 * in x1, with argument in x0
-	 */
-	blr	x1
-        /*
-	 * Never gets here, unless suspend finisher fails.
-	 * Successful cpu_suspend should return from cpu_resume, returning
-	 * through this code path is considered an error
-	 * If the return value is set to 0 force x0 = -EOPNOTSUPP
-	 * to make sure a proper error condition is propagated
-	 */
-	cmp	x0, #0
-	mov	x3, #-EOPNOTSUPP
-	csel	x0, x3, x0, eq
-	add	sp, sp, #CPU_SUSPEND_SZ	// rewind stack pointer
-	ldp	x19, x20, [sp, #16]
-	ldp	x21, x22, [sp, #32]
-	ldp	x23, x24, [sp, #48]
-	ldp	x25, x26, [sp, #64]
-	ldp	x27, x28, [sp, #80]
-	ldp	x29, lr, [sp], #96
+
+	str	x0, [x1]
+	add	x0, x0, #SLEEP_STACK_DATA_SYSTEM_REGS
+	stp	x29, lr, [sp, #-16]!
+	bl	cpu_do_suspend
+	ldp	x29, lr, [sp], #16
+	mov	x0, #1
 	ret
 ENDPROC(__cpu_suspend_enter)
 	.ltorg
 
-/*
- * x0 must contain the sctlr value retrieved from restored context
- */
-	.pushsection	".idmap.text", "ax"
-ENTRY(cpu_resume_mmu)
-	ldr	x3, =cpu_resume_after_mmu
-	msr	sctlr_el1, x0		// restore sctlr_el1
-	isb
-	/*
-	 * Invalidate the local I-cache so that any instructions fetched
-	 * speculatively from the PoC are discarded, since they may have
-	 * been dynamically patched at the PoU.
-	 */
-	ic	iallu
-	dsb	nsh
-	isb
-	br	x3			// global jump to virtual address
-ENDPROC(cpu_resume_mmu)
-	.popsection
-cpu_resume_after_mmu:
-#ifdef CONFIG_KASAN
-	mov	x0, sp
-	bl	kasan_unpoison_remaining_stack
-#endif
-	mov	x0, #0			// return zero on success
-	ldp	x19, x20, [sp, #16]
-	ldp	x21, x22, [sp, #32]
-	ldp	x23, x24, [sp, #48]
-	ldp	x25, x26, [sp, #64]
-	ldp	x27, x28, [sp, #80]
-	ldp	x29, lr, [sp], #96
-	ret
-ENDPROC(cpu_resume_after_mmu)
-
 ENTRY(cpu_resume)
 	bl	el2_setup		// if in EL2 drop to EL1 cleanly
+	/* enable the MMU early - so we can access sleep_save_stash by va */
+	adr_l	lr, __enable_mmu	/* __cpu_setup will return here */
+	ldr	x27, =_cpu_resume	/* __enable_mmu will branch here */
+	adrp	x25, idmap_pg_dir
+	adrp	x26, swapper_pg_dir
+	b	__cpu_setup
+ENDPROC(cpu_resume)
+
+ENTRY(_cpu_resume)
 	mrs	x1, mpidr_el1
 	adrp	x8, mpidr_hash
 	add x8, x8, #:lo12:mpidr_hash // x8 = struct mpidr_hash phys address
@@ -170,20 +117,32 @@ ENTRY(cpu_resume)
 	ldp	w5, w6, [x8, #(MPIDR_HASH_SHIFTS + 8)]
 	compute_mpidr_hash x7, x3, x4, x5, x6, x1, x2
         /* x7 contains hash index, let's use it to grab context pointer */
-	ldr_l	x0, sleep_save_sp + SLEEP_SAVE_SP_PHYS
+	ldr_l	x0, sleep_save_stash
 	ldr	x0, [x0, x7, lsl #3]
+	add	x29, x0, #SLEEP_STACK_DATA_CALLEE_REGS
+	add	x0, x0, #SLEEP_STACK_DATA_SYSTEM_REGS
 	/* load sp from context */
 	ldr	x2, [x0, #CPU_CTX_SP]
-	/* load physical address of identity map page table in x1 */
-	adrp	x1, idmap_pg_dir
 	mov	sp, x2
 	/* save thread_info */
 	and	x2, x2, #~(THREAD_SIZE - 1)
 	msr	sp_el0, x2
 	/*
-	 * cpu_do_resume expects x0 to contain context physical address
-	 * pointer and x1 to contain physical address of 1:1 page tables
+	 * cpu_do_resume expects x0 to contain context address pointer
 	 */
-	bl	cpu_do_resume		// PC relative jump, MMU off
-	b	cpu_resume_mmu		// Resume MMU, never returns
-ENDPROC(cpu_resume)
+	bl	cpu_do_resume
+
+#ifdef CONFIG_KASAN
+	mov	x0, sp
+	bl	kasan_unpoison_remaining_stack
+#endif
+
+	ldp	x19, x20, [x29, #16]
+	ldp	x21, x22, [x29, #32]
+	ldp	x23, x24, [x29, #48]
+	ldp	x25, x26, [x29, #64]
+	ldp	x27, x28, [x29, #80]
+	ldp	x29, lr, [x29]
+	mov	x0, #0
+	ret
+ENDPROC(_cpu_resume)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kernel/smp.c linux-libre-4.7-gnu/arch/arm64/kernel/smp.c
--- linux-libre-4.6-gnu/arch/arm64/kernel/smp.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kernel/smp.c	2016-07-24 15:23:50.000000000 -0400
@@ -45,6 +45,7 @@
 #include <asm/cputype.h>
 #include <asm/cpu_ops.h>
 #include <asm/mmu_context.h>
+#include <asm/numa.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/processor.h>
@@ -75,6 +76,43 @@ enum ipi_msg_type {
 	IPI_WAKEUP
 };
 
+#ifdef CONFIG_ARM64_VHE
+
+/* Whether the boot CPU is running in HYP mode or not*/
+static bool boot_cpu_hyp_mode;
+
+static inline void save_boot_cpu_run_el(void)
+{
+	boot_cpu_hyp_mode = is_kernel_in_hyp_mode();
+}
+
+static inline bool is_boot_cpu_in_hyp_mode(void)
+{
+	return boot_cpu_hyp_mode;
+}
+
+/*
+ * Verify that a secondary CPU is running the kernel at the same
+ * EL as that of the boot CPU.
+ */
+void verify_cpu_run_el(void)
+{
+	bool in_el2 = is_kernel_in_hyp_mode();
+	bool boot_cpu_el2 = is_boot_cpu_in_hyp_mode();
+
+	if (in_el2 ^ boot_cpu_el2) {
+		pr_crit("CPU%d: mismatched Exception Level(EL%d) with boot CPU(EL%d)\n",
+					smp_processor_id(),
+					in_el2 ? 2 : 1,
+					boot_cpu_el2 ? 2 : 1);
+		cpu_panic_kernel();
+	}
+}
+
+#else
+static inline void save_boot_cpu_run_el(void) {}
+#endif
+
 #ifdef CONFIG_HOTPLUG_CPU
 static int op_cpu_kill(unsigned int cpu);
 #else
@@ -166,6 +204,7 @@ int __cpu_up(unsigned int cpu, struct ta
 static void smp_store_cpu_info(unsigned int cpuid)
 {
 	store_cpu_topology(cpuid);
+	numa_store_cpu_info(cpuid);
 }
 
 /*
@@ -225,8 +264,6 @@ asmlinkage void secondary_start_kernel(v
 	pr_info("CPU%u: Booted secondary processor [%08x]\n",
 					 cpu, read_cpuid_id());
 	update_cpu_boot_status(CPU_BOOT_SUCCESS);
-	/* Make sure the status update is visible before we complete */
-	smp_wmb();
 	set_cpu_online(cpu, true);
 	complete(&cpu_running);
 
@@ -401,6 +438,7 @@ void __init smp_cpus_done(unsigned int m
 void __init smp_prepare_boot_cpu(void)
 {
 	cpuinfo_store_boot_cpu();
+	save_boot_cpu_run_el();
 	set_my_cpu_offset(per_cpu_offset(smp_processor_id()));
 }
 
@@ -595,6 +633,8 @@ static void __init of_parse_and_init_cpu
 
 		pr_debug("cpu logical map 0x%llx\n", hwid);
 		cpu_logical_map(cpu_count) = hwid;
+
+		early_map_cpu_to_node(cpu_count, of_node_to_nid(dn));
 next:
 		cpu_count++;
 	}
@@ -647,33 +687,18 @@ void __init smp_init_cpus(void)
 void __init smp_prepare_cpus(unsigned int max_cpus)
 {
 	int err;
-	unsigned int cpu, ncores = num_possible_cpus();
+	unsigned int cpu;
 
 	init_cpu_topology();
 
 	smp_store_cpu_info(smp_processor_id());
 
 	/*
-	 * are we trying to boot more cores than exist?
-	 */
-	if (max_cpus > ncores)
-		max_cpus = ncores;
-
-	/* Don't bother if we're effectively UP */
-	if (max_cpus <= 1)
-		return;
-
-	/*
 	 * Initialise the present map (which describes the set of CPUs
 	 * actually populated at the present time) and release the
 	 * secondaries from the bootloader.
-	 *
-	 * Make sure we online at most (max_cpus - 1) additional CPUs.
 	 */
-	max_cpus--;
 	for_each_possible_cpu(cpu) {
-		if (max_cpus == 0)
-			break;
 
 		if (cpu == smp_processor_id())
 			continue;
@@ -686,7 +711,6 @@ void __init smp_prepare_cpus(unsigned in
 			continue;
 
 		set_cpu_present(cpu, true);
-		max_cpus--;
 	}
 }
 
@@ -763,21 +787,11 @@ void arch_irq_work_raise(void)
 }
 #endif
 
-static DEFINE_RAW_SPINLOCK(stop_lock);
-
 /*
  * ipi_cpu_stop - handle IPI from smp_send_stop()
  */
 static void ipi_cpu_stop(unsigned int cpu)
 {
-	if (system_state == SYSTEM_BOOTING ||
-	    system_state == SYSTEM_RUNNING) {
-		raw_spin_lock(&stop_lock);
-		pr_crit("CPU%u: stopping\n", cpu);
-		dump_stack();
-		raw_spin_unlock(&stop_lock);
-	}
-
 	set_cpu_online(cpu, false);
 
 	local_irq_disable();
@@ -872,6 +886,9 @@ void smp_send_stop(void)
 		cpumask_copy(&mask, cpu_online_mask);
 		cpumask_clear_cpu(smp_processor_id(), &mask);
 
+		if (system_state == SYSTEM_BOOTING ||
+		    system_state == SYSTEM_RUNNING)
+			pr_crit("SMP: stopping secondary CPUs\n");
 		smp_cross_call(&mask, IPI_CPU_STOP);
 	}
 
@@ -881,7 +898,8 @@ void smp_send_stop(void)
 		udelay(1);
 
 	if (num_online_cpus() > 1)
-		pr_warning("SMP: failed to stop secondary CPUs\n");
+		pr_warning("SMP: failed to stop secondary CPUs %*pbl\n",
+			   cpumask_pr_args(cpu_online_mask));
 }
 
 /*
@@ -891,3 +909,21 @@ int setup_profiling_timer(unsigned int m
 {
 	return -EINVAL;
 }
+
+static bool have_cpu_die(void)
+{
+#ifdef CONFIG_HOTPLUG_CPU
+	int any_cpu = raw_smp_processor_id();
+
+	if (cpu_ops[any_cpu]->cpu_die)
+		return true;
+#endif
+	return false;
+}
+
+bool cpus_are_stuck_in_kernel(void)
+{
+	bool smp_spin_tables = (num_possible_cpus() > 1 && !have_cpu_die());
+
+	return !!cpus_stuck_in_kernel || smp_spin_tables;
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kernel/suspend.c linux-libre-4.7-gnu/arch/arm64/kernel/suspend.c
--- linux-libre-4.6-gnu/arch/arm64/kernel/suspend.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kernel/suspend.c	2016-07-24 15:23:50.000000000 -0400
@@ -10,30 +10,11 @@
 #include <asm/suspend.h>
 #include <asm/tlbflush.h>
 
-extern int __cpu_suspend_enter(unsigned long arg, int (*fn)(unsigned long));
 /*
- * This is called by __cpu_suspend_enter() to save the state, and do whatever
- * flushing is required to ensure that when the CPU goes to sleep we have
- * the necessary data available when the caches are not searched.
- *
- * ptr: CPU context virtual address
- * save_ptr: address of the location where the context physical address
- *           must be saved
+ * This is allocated by cpu_suspend_init(), and used to store a pointer to
+ * the 'struct sleep_stack_data' the contains a particular CPUs state.
  */
-void notrace __cpu_suspend_save(struct cpu_suspend_ctx *ptr,
-				phys_addr_t *save_ptr)
-{
-	*save_ptr = virt_to_phys(ptr);
-
-	cpu_do_suspend(ptr);
-	/*
-	 * Only flush the context that must be retrieved with the MMU
-	 * off. VA primitives ensure the flush is applied to all
-	 * cache levels so context is pushed to DRAM.
-	 */
-	__flush_dcache_area(ptr, sizeof(*ptr));
-	__flush_dcache_area(save_ptr, sizeof(*save_ptr));
-}
+unsigned long *sleep_save_stash;
 
 /*
  * This hook is provided so that cpu_suspend code can restore HW
@@ -51,6 +32,30 @@ void __init cpu_suspend_set_dbg_restorer
 	hw_breakpoint_restore = hw_bp_restore;
 }
 
+void notrace __cpu_suspend_exit(void)
+{
+	/*
+	 * We are resuming from reset with the idmap active in TTBR0_EL1.
+	 * We must uninstall the idmap and restore the expected MMU
+	 * state before we can possibly return to userspace.
+	 */
+	cpu_uninstall_idmap();
+
+	/*
+	 * Restore per-cpu offset before any kernel
+	 * subsystem relying on it has a chance to run.
+	 */
+	set_my_cpu_offset(per_cpu_offset(smp_processor_id()));
+
+	/*
+	 * Restore HW breakpoint registers to sane values
+	 * before debug exceptions are possibly reenabled
+	 * through local_dbg_restore.
+	 */
+	if (hw_breakpoint_restore)
+		hw_breakpoint_restore(NULL);
+}
+
 /*
  * cpu_suspend
  *
@@ -60,8 +65,9 @@ void __init cpu_suspend_set_dbg_restorer
  */
 int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
 {
-	int ret;
+	int ret = 0;
 	unsigned long flags;
+	struct sleep_stack_data state;
 
 	/*
 	 * From this point debug exceptions are disabled to prevent
@@ -77,34 +83,21 @@ int cpu_suspend(unsigned long arg, int (
 	 */
 	pause_graph_tracing();
 
-	/*
-	 * mm context saved on the stack, it will be restored when
-	 * the cpu comes out of reset through the identity mapped
-	 * page tables, so that the thread address space is properly
-	 * set-up on function return.
-	 */
-	ret = __cpu_suspend_enter(arg, fn);
-	if (ret == 0) {
-		/*
-		 * We are resuming from reset with the idmap active in TTBR0_EL1.
-		 * We must uninstall the idmap and restore the expected MMU
-		 * state before we can possibly return to userspace.
-		 */
-		cpu_uninstall_idmap();
-
-		/*
-		 * Restore per-cpu offset before any kernel
-		 * subsystem relying on it has a chance to run.
-		 */
-		set_my_cpu_offset(per_cpu_offset(smp_processor_id()));
+	if (__cpu_suspend_enter(&state)) {
+		/* Call the suspend finisher */
+		ret = fn(arg);
 
 		/*
-		 * Restore HW breakpoint registers to sane values
-		 * before debug exceptions are possibly reenabled
-		 * through local_dbg_restore.
+		 * Never gets here, unless the suspend finisher fails.
+		 * Successful cpu_suspend() should return from cpu_resume(),
+		 * returning through this code path is considered an error
+		 * If the return value is set to 0 force ret = -EOPNOTSUPP
+		 * to make sure a proper error condition is propagated
 		 */
-		if (hw_breakpoint_restore)
-			hw_breakpoint_restore(NULL);
+		if (!ret)
+			ret = -EOPNOTSUPP;
+	} else {
+		__cpu_suspend_exit();
 	}
 
 	unpause_graph_tracing();
@@ -119,22 +112,15 @@ int cpu_suspend(unsigned long arg, int (
 	return ret;
 }
 
-struct sleep_save_sp sleep_save_sp;
-
 static int __init cpu_suspend_init(void)
 {
-	void *ctx_ptr;
-
 	/* ctx_ptr is an array of physical addresses */
-	ctx_ptr = kcalloc(mpidr_hash_size(), sizeof(phys_addr_t), GFP_KERNEL);
+	sleep_save_stash = kcalloc(mpidr_hash_size(), sizeof(*sleep_save_stash),
+				   GFP_KERNEL);
 
-	if (WARN_ON(!ctx_ptr))
+	if (WARN_ON(!sleep_save_stash))
 		return -ENOMEM;
 
-	sleep_save_sp.save_ptr_stash = ctx_ptr;
-	sleep_save_sp.save_ptr_stash_phys = virt_to_phys(ctx_ptr);
-	__flush_dcache_area(&sleep_save_sp, sizeof(struct sleep_save_sp));
-
 	return 0;
 }
 early_initcall(cpu_suspend_init);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kernel/sys.c linux-libre-4.7-gnu/arch/arm64/kernel/sys.c
--- linux-libre-4.6-gnu/arch/arm64/kernel/sys.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kernel/sys.c	2016-07-24 15:23:50.000000000 -0400
@@ -25,6 +25,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/syscalls.h>
+#include <asm/cpufeature.h>
 
 asmlinkage long sys_mmap(unsigned long addr, unsigned long len,
 			 unsigned long prot, unsigned long flags,
@@ -36,11 +37,20 @@ asmlinkage long sys_mmap(unsigned long a
 	return sys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
 }
 
+SYSCALL_DEFINE1(arm64_personality, unsigned int, personality)
+{
+	if (personality(personality) == PER_LINUX32 &&
+		!system_supports_32bit_el0())
+		return -EINVAL;
+	return sys_personality(personality);
+}
+
 /*
  * Wrappers to pass the pt_regs argument.
  */
 asmlinkage long sys_rt_sigreturn_wrapper(void);
 #define sys_rt_sigreturn	sys_rt_sigreturn_wrapper
+#define sys_personality		sys_arm64_personality
 
 #undef __SYSCALL
 #define __SYSCALL(nr, sym)	[nr] = sym,
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kernel/traps.c linux-libre-4.7-gnu/arch/arm64/kernel/traps.c
--- linux-libre-4.6-gnu/arch/arm64/kernel/traps.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kernel/traps.c	2016-07-24 15:23:50.000000000 -0400
@@ -64,8 +64,7 @@ static void dump_mem(const char *lvl, co
 
 	/*
 	 * We need to switch to kernel mode so that we can use __get_user
-	 * to safely read from kernel space.  Note that we now dump the
-	 * code first, just in case the backtrace kills us.
+	 * to safely read from kernel space.
 	 */
 	fs = get_fs();
 	set_fs(KERNEL_DS);
@@ -111,21 +110,12 @@ static void dump_backtrace_entry(unsigne
 	print_ip_sym(where);
 }
 
-static void dump_instr(const char *lvl, struct pt_regs *regs)
+static void __dump_instr(const char *lvl, struct pt_regs *regs)
 {
 	unsigned long addr = instruction_pointer(regs);
-	mm_segment_t fs;
 	char str[sizeof("00000000 ") * 5 + 2 + 1], *p = str;
 	int i;
 
-	/*
-	 * We need to switch to kernel mode so that we can use __get_user
-	 * to safely read from kernel space.  Note that we now dump the
-	 * code first, just in case the backtrace kills us.
-	 */
-	fs = get_fs();
-	set_fs(KERNEL_DS);
-
 	for (i = -4; i < 1; i++) {
 		unsigned int val, bad;
 
@@ -139,8 +129,18 @@ static void dump_instr(const char *lvl,
 		}
 	}
 	printk("%sCode: %s\n", lvl, str);
+}
 
-	set_fs(fs);
+static void dump_instr(const char *lvl, struct pt_regs *regs)
+{
+	if (!user_mode(regs)) {
+		mm_segment_t fs = get_fs();
+		set_fs(KERNEL_DS);
+		__dump_instr(lvl, regs);
+		set_fs(fs);
+	} else {
+		__dump_instr(lvl, regs);
+	}
 }
 
 static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
@@ -477,8 +477,9 @@ asmlinkage void bad_mode(struct pt_regs
 	void __user *pc = (void __user *)instruction_pointer(regs);
 	console_verbose();
 
-	pr_crit("Bad mode in %s handler detected, code 0x%08x -- %s\n",
-		handler[reason], esr, esr_get_class_string(esr));
+	pr_crit("Bad mode in %s handler detected on CPU%d, code 0x%08x -- %s\n",
+		handler[reason], smp_processor_id(), esr,
+		esr_get_class_string(esr));
 	__show_regs(regs);
 
 	info.si_signo = SIGILL;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kernel/vdso.c linux-libre-4.7-gnu/arch/arm64/kernel/vdso.c
--- linux-libre-4.6-gnu/arch/arm64/kernel/vdso.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kernel/vdso.c	2016-07-24 15:23:50.000000000 -0400
@@ -95,7 +95,8 @@ int aarch32_setup_vectors_page(struct li
 	};
 	void *ret;
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
 	current->mm->context.vdso = (void *)addr;
 
 	/* Map vectors page at the high address. */
@@ -131,11 +132,11 @@ static int __init vdso_init(void)
 		return -ENOMEM;
 
 	/* Grab the vDSO data page. */
-	vdso_pagelist[0] = virt_to_page(vdso_data);
+	vdso_pagelist[0] = pfn_to_page(PHYS_PFN(__pa(vdso_data)));
 
 	/* Grab the vDSO code pages. */
 	for (i = 0; i < vdso_pages; i++)
-		vdso_pagelist[i + 1] = virt_to_page(&vdso_start + i * PAGE_SIZE);
+		vdso_pagelist[i + 1] = pfn_to_page(PHYS_PFN(__pa(&vdso_start)) + i);
 
 	/* Populate the special mapping structures */
 	vdso_spec[0] = (struct vm_special_mapping) {
@@ -163,7 +164,8 @@ int arch_setup_additional_pages(struct l
 	/* Be sure to map the data page */
 	vdso_mapping_len = vdso_text_len + PAGE_SIZE;
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
 	vdso_base = get_unmapped_area(NULL, 0, vdso_mapping_len, 0, 0);
 	if (IS_ERR_VALUE(vdso_base)) {
 		ret = ERR_PTR(vdso_base);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kernel/vmlinux.lds.S linux-libre-4.7-gnu/arch/arm64/kernel/vmlinux.lds.S
--- linux-libre-4.6-gnu/arch/arm64/kernel/vmlinux.lds.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kernel/vmlinux.lds.S	2016-07-24 15:23:50.000000000 -0400
@@ -46,6 +46,16 @@ jiffies = jiffies_64;
 	*(.idmap.text)					\
 	VMLINUX_SYMBOL(__idmap_text_end) = .;
 
+#ifdef CONFIG_HIBERNATION
+#define HIBERNATE_TEXT					\
+	. = ALIGN(SZ_4K);				\
+	VMLINUX_SYMBOL(__hibernate_exit_text_start) = .;\
+	*(.hibernate_exit.text)				\
+	VMLINUX_SYMBOL(__hibernate_exit_text_end) = .;
+#else
+#define HIBERNATE_TEXT
+#endif
+
 /*
  * The size of the PE/COFF section that covers the kernel image, which
  * runs from stext to _edata, must be a round multiple of the PE/COFF
@@ -63,14 +73,19 @@ PECOFF_FILE_ALIGNMENT = 0x200;
 #endif
 
 #if defined(CONFIG_DEBUG_ALIGN_RODATA)
-#define ALIGN_DEBUG_RO			. = ALIGN(1<<SECTION_SHIFT);
-#define ALIGN_DEBUG_RO_MIN(min)		ALIGN_DEBUG_RO
-#elif defined(CONFIG_DEBUG_RODATA)
-#define ALIGN_DEBUG_RO			. = ALIGN(1<<PAGE_SHIFT);
-#define ALIGN_DEBUG_RO_MIN(min)		ALIGN_DEBUG_RO
+/*
+ *  4 KB granule:   1 level 2 entry
+ * 16 KB granule: 128 level 3 entries, with contiguous bit
+ * 64 KB granule:  32 level 3 entries, with contiguous bit
+ */
+#define SEGMENT_ALIGN			SZ_2M
 #else
-#define ALIGN_DEBUG_RO
-#define ALIGN_DEBUG_RO_MIN(min)		. = ALIGN(min);
+/*
+ *  4 KB granule:  16 level 3 entries, with contiguous bit
+ * 16 KB granule:   4 level 3 entries, without contiguous bit
+ * 64 KB granule:   1 level 3 entry
+ */
+#define SEGMENT_ALIGN			SZ_64K
 #endif
 
 SECTIONS
@@ -96,7 +111,6 @@ SECTIONS
 		_text = .;
 		HEAD_TEXT
 	}
-	ALIGN_DEBUG_RO_MIN(PAGE_SIZE)
 	.text : {			/* Real text segment		*/
 		_stext = .;		/* Text and read-only data	*/
 			__exception_text_start = .;
@@ -109,18 +123,19 @@ SECTIONS
 			LOCK_TEXT
 			HYPERVISOR_TEXT
 			IDMAP_TEXT
+			HIBERNATE_TEXT
 			*(.fixup)
 			*(.gnu.warning)
 		. = ALIGN(16);
 		*(.got)			/* Global offset table		*/
 	}
 
-	ALIGN_DEBUG_RO_MIN(PAGE_SIZE)
+	. = ALIGN(SEGMENT_ALIGN);
 	RO_DATA(PAGE_SIZE)		/* everything from this point to */
 	EXCEPTION_TABLE(8)		/* _etext will be marked RO NX   */
 	NOTES
 
-	ALIGN_DEBUG_RO_MIN(PAGE_SIZE)
+	. = ALIGN(SEGMENT_ALIGN);
 	_etext = .;			/* End of text and rodata section */
 	__init_begin = .;
 
@@ -154,12 +169,9 @@ SECTIONS
 		*(.altinstr_replacement)
 	}
 	.rela : ALIGN(8) {
-		__reloc_start = .;
 		*(.rela .rela*)
-		__reloc_end = .;
 	}
 	.dynsym : ALIGN(8) {
-		__dynsym_start = .;
 		*(.dynsym)
 	}
 	.dynstr : {
@@ -169,7 +181,11 @@ SECTIONS
 		*(.hash)
 	}
 
-	. = ALIGN(PAGE_SIZE);
+	__rela_offset	= ADDR(.rela) - KIMAGE_VADDR;
+	__rela_size	= SIZEOF(.rela);
+	__dynsym_offset	= ADDR(.dynsym) - KIMAGE_VADDR;
+
+	. = ALIGN(SEGMENT_ALIGN);
 	__init_end = .;
 
 	_data = .;
@@ -201,6 +217,10 @@ ASSERT(__hyp_idmap_text_end - (__hyp_idm
 	"HYP init code too big or misaligned")
 ASSERT(__idmap_text_end - (__idmap_text_start & ~(SZ_4K - 1)) <= SZ_4K,
 	"ID map text too big or misaligned")
+#ifdef CONFIG_HIBERNATION
+ASSERT(__hibernate_exit_text_end - (__hibernate_exit_text_start & ~(SZ_4K - 1))
+	<= SZ_4K, "Hibernate exit text too big or misaligned")
+#endif
 
 /*
  * If padding is applied before .head.text, virt<->phys conversions will fail.
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kvm/handle_exit.c linux-libre-4.7-gnu/arch/arm64/kvm/handle_exit.c
--- linux-libre-4.6-gnu/arch/arm64/kvm/handle_exit.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kvm/handle_exit.c	2016-07-24 15:23:50.000000000 -0400
@@ -186,6 +186,13 @@ int handle_exit(struct kvm_vcpu *vcpu, s
 		exit_handler = kvm_get_exit_handler(vcpu);
 
 		return exit_handler(vcpu, run);
+	case ARM_EXCEPTION_HYP_GONE:
+		/*
+		 * EL2 has been reset to the hyp-stub. This happens when a guest
+		 * is pre-empted by kvm_reboot()'s shutdown call.
+		 */
+		run->exit_reason = KVM_EXIT_FAIL_ENTRY;
+		return 0;
 	default:
 		kvm_pr_unimpl("Unsupported exception type: %d",
 			      exception_index);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kvm/hyp/entry.S linux-libre-4.7-gnu/arch/arm64/kvm/hyp/entry.S
--- linux-libre-4.6-gnu/arch/arm64/kvm/hyp/entry.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kvm/hyp/entry.S	2016-07-24 15:23:50.000000000 -0400
@@ -164,3 +164,22 @@ alternative_endif
 
 	eret
 ENDPROC(__fpsimd_guest_restore)
+
+/*
+ * When using the extended idmap, we don't have a trampoline page we can use
+ * while we switch pages tables during __kvm_hyp_reset. Accessing the idmap
+ * directly would be ideal, but if we're using the extended idmap then the
+ * idmap is located above HYP_PAGE_OFFSET, and the address will be masked by
+ * kvm_call_hyp using kern_hyp_va.
+ *
+ * x0: HYP boot pgd
+ * x1: HYP phys_idmap_start
+ */
+ENTRY(__extended_idmap_trampoline)
+	mov	x4, x1
+	adr_l	x3, __kvm_hyp_reset
+
+	/* insert __kvm_hyp_reset()s offset into phys_idmap_start */
+	bfi	x4, x3, #0, #PAGE_SHIFT
+	br	x4
+ENDPROC(__extended_idmap_trampoline)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kvm/hyp/hyp-entry.S linux-libre-4.7-gnu/arch/arm64/kvm/hyp/hyp-entry.S
--- linux-libre-4.6-gnu/arch/arm64/kvm/hyp/hyp-entry.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kvm/hyp/hyp-entry.S	2016-07-24 15:23:50.000000000 -0400
@@ -42,19 +42,17 @@
 	 * Shuffle the parameters before calling the function
 	 * pointed to in x0. Assumes parameters in x[1,2,3].
 	 */
-	sub	sp, sp, #16
-	str	lr, [sp]
 	mov	lr, x0
 	mov	x0, x1
 	mov	x1, x2
 	mov	x2, x3
 	blr	lr
-	ldr	lr, [sp]
-	add	sp, sp, #16
 .endm
 
 ENTRY(__vhe_hyp_call)
+	str	lr, [sp, #-16]!
 	do_el2_call
+	ldr	lr, [sp], #16
 	/*
 	 * We used to rely on having an exception return to get
 	 * an implicit isb. In the E2H case, we don't have it anymore.
@@ -84,8 +82,8 @@ alternative_endif
 	/* Here, we're pretty sure the host called HVC. */
 	restore_x0_to_x3
 
-	/* Check for __hyp_get_vectors */
-	cbnz	x0, 1f
+	cmp	x0, #HVC_GET_VECTORS
+	b.ne	1f
 	mrs	x0, vbar_el2
 	b	2f
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kvm/hyp/s2-setup.c linux-libre-4.7-gnu/arch/arm64/kvm/hyp/s2-setup.c
--- linux-libre-4.6-gnu/arch/arm64/kvm/hyp/s2-setup.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kvm/hyp/s2-setup.c	2016-07-24 15:23:50.000000000 -0400
@@ -66,6 +66,14 @@ u32 __hyp_text __init_stage2_translation
 	val |= 64 - (parange > 40 ? 40 : parange);
 
 	/*
+	 * Check the availability of Hardware Access Flag / Dirty Bit
+	 * Management in ID_AA64MMFR1_EL1 and enable the feature in VTCR_EL2.
+	 */
+	tmp = (read_sysreg(id_aa64mmfr1_el1) >> ID_AA64MMFR1_HADBS_SHIFT) & 0xf;
+	if (IS_ENABLED(CONFIG_ARM64_HW_AFDBM) && tmp)
+		val |= VTCR_EL2_HA;
+
+	/*
 	 * Read the VMIDBits bits from ID_AA64MMFR1_EL1 and set the VS
 	 * bit in VTCR_EL2.
 	 */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kvm/hyp/vgic-v3-sr.c linux-libre-4.7-gnu/arch/arm64/kvm/hyp/vgic-v3-sr.c
--- linux-libre-4.6-gnu/arch/arm64/kvm/hyp/vgic-v3-sr.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kvm/hyp/vgic-v3-sr.c	2016-07-24 15:23:50.000000000 -0400
@@ -169,7 +169,8 @@ void __hyp_text __vgic_v3_save_state(str
 	 * Make sure stores to the GIC via the memory mapped interface
 	 * are now visible to the system register interface.
 	 */
-	dsb(st);
+	if (!cpu_if->vgic_sre)
+		dsb(st);
 
 	cpu_if->vgic_vmcr  = read_gicreg(ICH_VMCR_EL2);
 
@@ -190,12 +191,11 @@ void __hyp_text __vgic_v3_save_state(str
 			if (!(vcpu->arch.vgic_cpu.live_lrs & (1UL << i)))
 				continue;
 
-			if (cpu_if->vgic_elrsr & (1 << i)) {
+			if (cpu_if->vgic_elrsr & (1 << i))
 				cpu_if->vgic_lr[i] &= ~ICH_LR_STATE;
-				continue;
-			}
+			else
+				cpu_if->vgic_lr[i] = __gic_v3_get_lr(i);
 
-			cpu_if->vgic_lr[i] = __gic_v3_get_lr(i);
 			__gic_v3_set_lr(0, i);
 		}
 
@@ -236,8 +236,12 @@ void __hyp_text __vgic_v3_save_state(str
 
 	val = read_gicreg(ICC_SRE_EL2);
 	write_gicreg(val | ICC_SRE_EL2_ENABLE, ICC_SRE_EL2);
-	isb(); /* Make sure ENABLE is set at EL2 before setting SRE at EL1 */
-	write_gicreg(1, ICC_SRE_EL1);
+
+	if (!cpu_if->vgic_sre) {
+		/* Make sure ENABLE is set at EL2 before setting SRE at EL1 */
+		isb();
+		write_gicreg(1, ICC_SRE_EL1);
+	}
 }
 
 void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
@@ -256,8 +260,10 @@ void __hyp_text __vgic_v3_restore_state(
 	 * been actually programmed with the value we want before
 	 * starting to mess with the rest of the GIC.
 	 */
-	write_gicreg(cpu_if->vgic_sre, ICC_SRE_EL1);
-	isb();
+	if (!cpu_if->vgic_sre) {
+		write_gicreg(0, ICC_SRE_EL1);
+		isb();
+	}
 
 	val = read_gicreg(ICH_VTR_EL2);
 	max_lr_idx = vtr_to_max_lr_idx(val);
@@ -306,18 +312,18 @@ void __hyp_text __vgic_v3_restore_state(
 	 * (re)distributors. This ensure the guest will read the
 	 * correct values from the memory-mapped interface.
 	 */
-	isb();
-	dsb(sy);
+	if (!cpu_if->vgic_sre) {
+		isb();
+		dsb(sy);
+	}
 	vcpu->arch.vgic_cpu.live_lrs = live_lrs;
 
 	/*
 	 * Prevent the guest from touching the GIC system registers if
 	 * SRE isn't enabled for GICv3 emulation.
 	 */
-	if (!cpu_if->vgic_sre) {
-		write_gicreg(read_gicreg(ICC_SRE_EL2) & ~ICC_SRE_EL2_ENABLE,
-			     ICC_SRE_EL2);
-	}
+	write_gicreg(read_gicreg(ICC_SRE_EL2) & ~ICC_SRE_EL2_ENABLE,
+		     ICC_SRE_EL2);
 }
 
 void __hyp_text __vgic_v3_init_lrs(void)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kvm/hyp-init.S linux-libre-4.7-gnu/arch/arm64/kvm/hyp-init.S
--- linux-libre-4.6-gnu/arch/arm64/kvm/hyp-init.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kvm/hyp-init.S	2016-07-24 15:23:50.000000000 -0400
@@ -21,6 +21,7 @@
 #include <asm/kvm_arm.h>
 #include <asm/kvm_mmu.h>
 #include <asm/pgtable-hwdef.h>
+#include <asm/sysreg.h>
 
 	.text
 	.pushsection	.hyp.idmap.text, "ax"
@@ -103,8 +104,8 @@ __do_hyp_init:
 	dsb	sy
 
 	mrs	x4, sctlr_el2
-	and	x4, x4, #SCTLR_EL2_EE	// preserve endianness of EL2
-	ldr	x5, =SCTLR_EL2_FLAGS
+	and	x4, x4, #SCTLR_ELx_EE	// preserve endianness of EL2
+	ldr	x5, =SCTLR_ELx_FLAGS
 	orr	x4, x4, x5
 	msr	sctlr_el2, x4
 	isb
@@ -138,6 +139,49 @@ merged:
 	eret
 ENDPROC(__kvm_hyp_init)
 
+	/*
+	 * Reset kvm back to the hyp stub. This is the trampoline dance in
+	 * reverse. If kvm used an extended idmap, __extended_idmap_trampoline
+	 * calls this code directly in the idmap. In this case switching to the
+	 * boot tables is a no-op.
+	 *
+	 * x0: HYP boot pgd
+	 * x1: HYP phys_idmap_start
+	 */
+ENTRY(__kvm_hyp_reset)
+	/* We're in trampoline code in VA, switch back to boot page tables */
+	msr	ttbr0_el2, x0
+	isb
+
+	/* Ensure the PA branch doesn't find a stale tlb entry or stale code. */
+	ic	iallu
+	tlbi	alle2
+	dsb	sy
+	isb
+
+	/* Branch into PA space */
+	adr	x0, 1f
+	bfi	x1, x0, #0, #PAGE_SHIFT
+	br	x1
+
+	/* We're now in idmap, disable MMU */
+1:	mrs	x0, sctlr_el2
+	ldr	x1, =SCTLR_ELx_FLAGS
+	bic	x0, x0, x1		// Clear SCTL_M and etc
+	msr	sctlr_el2, x0
+	isb
+
+	/* Invalidate the old TLBs */
+	tlbi	alle2
+	dsb	sy
+
+	/* Install stub vectors */
+	adr_l	x0, __hyp_stub_vectors
+	msr	vbar_el2, x0
+
+	eret
+ENDPROC(__kvm_hyp_reset)
+
 	.ltorg
 
 	.popsection
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kvm/hyp.S linux-libre-4.7-gnu/arch/arm64/kvm/hyp.S
--- linux-libre-4.6-gnu/arch/arm64/kvm/hyp.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kvm/hyp.S	2016-07-24 15:23:50.000000000 -0400
@@ -35,16 +35,21 @@
  * in Hyp mode (see init_hyp_mode in arch/arm/kvm/arm.c).  Return values are
  * passed in x0.
  *
- * A function pointer with a value of 0 has a special meaning, and is
- * used to implement __hyp_get_vectors in the same way as in
+ * A function pointer with a value less than 0xfff has a special meaning,
+ * and is used to implement __hyp_get_vectors in the same way as in
  * arch/arm64/kernel/hyp_stub.S.
+ * HVC behaves as a 'bl' call and will clobber lr.
  */
 ENTRY(__kvm_call_hyp)
-alternative_if_not ARM64_HAS_VIRT_HOST_EXTN	
+alternative_if_not ARM64_HAS_VIRT_HOST_EXTN
+	str     lr, [sp, #-16]!
 	hvc	#0
+	ldr     lr, [sp], #16
 	ret
 alternative_else
 	b	__vhe_hyp_call
 	nop
+	nop
+	nop
 alternative_endif
 ENDPROC(__kvm_call_hyp)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kvm/inject_fault.c linux-libre-4.7-gnu/arch/arm64/kvm/inject_fault.c
--- linux-libre-4.6-gnu/arch/arm64/kvm/inject_fault.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kvm/inject_fault.c	2016-07-24 15:23:50.000000000 -0400
@@ -162,7 +162,7 @@ static void inject_abt64(struct kvm_vcpu
 		esr |= (ESR_ELx_EC_IABT_CUR << ESR_ELx_EC_SHIFT);
 
 	if (!is_iabt)
-		esr |= ESR_ELx_EC_DABT_LOW;
+		esr |= ESR_ELx_EC_DABT_LOW << ESR_ELx_EC_SHIFT;
 
 	vcpu_sys_reg(vcpu, ESR_EL1) = esr | ESR_ELx_FSC_EXTABT;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kvm/Kconfig linux-libre-4.7-gnu/arch/arm64/kvm/Kconfig
--- linux-libre-4.6-gnu/arch/arm64/kvm/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kvm/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -22,7 +22,6 @@ config KVM_ARM_VGIC_V3
 config KVM
 	bool "Kernel-based Virtual Machine (KVM) support"
 	depends on OF
-	depends on !ARM64_16K_PAGES
 	select MMU_NOTIFIER
 	select PREEMPT_NOTIFIERS
 	select ANON_INODES
@@ -55,6 +54,13 @@ config KVM_ARM_PMU
 	  Adds support for a virtual Performance Monitoring Unit (PMU) in
 	  virtual machines.
 
+config KVM_NEW_VGIC
+	bool "New VGIC implementation"
+	depends on KVM
+	default y
+        ---help---
+          uses the new VGIC implementation
+
 source drivers/vhost/Kconfig
 
 endif # VIRTUALIZATION
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kvm/Makefile linux-libre-4.7-gnu/arch/arm64/kvm/Makefile
--- linux-libre-4.6-gnu/arch/arm64/kvm/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kvm/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -20,10 +20,22 @@ kvm-$(CONFIG_KVM_ARM_HOST) += emulate.o
 kvm-$(CONFIG_KVM_ARM_HOST) += hyp.o hyp-init.o handle_exit.o
 kvm-$(CONFIG_KVM_ARM_HOST) += guest.o debug.o reset.o sys_regs.o sys_regs_generic_v8.o
 
+ifeq ($(CONFIG_KVM_NEW_VGIC),y)
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-init.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-irqfd.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-v2.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-v3.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio-v2.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio-v3.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-kvm-device.o
+else
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic-v2.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic-v2-emul.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic-v3.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic-v3-emul.o
+endif
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/arch_timer.o
 kvm-$(CONFIG_KVM_ARM_PMU) += $(KVM)/arm/pmu.o
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kvm/reset.c linux-libre-4.7-gnu/arch/arm64/kvm/reset.c
--- linux-libre-4.6-gnu/arch/arm64/kvm/reset.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kvm/reset.c	2016-07-24 15:23:50.000000000 -0400
@@ -29,7 +29,9 @@
 #include <asm/cputype.h>
 #include <asm/ptrace.h>
 #include <asm/kvm_arm.h>
+#include <asm/kvm_asm.h>
 #include <asm/kvm_coproc.h>
+#include <asm/kvm_mmu.h>
 
 /*
  * ARMv8 Reset Values
@@ -130,3 +132,31 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu
 	/* Reset timer */
 	return kvm_timer_vcpu_reset(vcpu, cpu_vtimer_irq);
 }
+
+extern char __hyp_idmap_text_start[];
+
+unsigned long kvm_hyp_reset_entry(void)
+{
+	if (!__kvm_cpu_uses_extended_idmap()) {
+		unsigned long offset;
+
+		/*
+		 * Find the address of __kvm_hyp_reset() in the trampoline page.
+		 * This is present in the running page tables, and the boot page
+		 * tables, so we call the code here to start the trampoline
+		 * dance in reverse.
+		 */
+		offset = (unsigned long)__kvm_hyp_reset
+			 - ((unsigned long)__hyp_idmap_text_start & PAGE_MASK);
+
+		return TRAMPOLINE_VA + offset;
+	} else {
+		/*
+		 * KVM is running with merged page tables, which don't have the
+		 * trampoline page mapped. We know the idmap is still mapped,
+		 * but can't be called into directly. Use
+		 * __extended_idmap_trampoline to do the call.
+		 */
+		return (unsigned long)kvm_ksym_ref(__extended_idmap_trampoline);
+	}
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/kvm/sys_regs.c linux-libre-4.7-gnu/arch/arm64/kvm/sys_regs.c
--- linux-libre-4.6-gnu/arch/arm64/kvm/sys_regs.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/kvm/sys_regs.c	2016-07-24 15:23:50.000000000 -0400
@@ -134,6 +134,17 @@ static bool access_gic_sgi(struct kvm_vc
 	return true;
 }
 
+static bool access_gic_sre(struct kvm_vcpu *vcpu,
+			   struct sys_reg_params *p,
+			   const struct sys_reg_desc *r)
+{
+	if (p->is_write)
+		return ignore_write(vcpu, p);
+
+	p->regval = vcpu->arch.vgic_cpu.vgic_v3.vgic_sre;
+	return true;
+}
+
 static bool trap_raz_wi(struct kvm_vcpu *vcpu,
 			struct sys_reg_params *p,
 			const struct sys_reg_desc *r)
@@ -958,7 +969,7 @@ static const struct sys_reg_desc sys_reg
 	  access_gic_sgi },
 	/* ICC_SRE_EL1 */
 	{ Op0(0b11), Op1(0b000), CRn(0b1100), CRm(0b1100), Op2(0b101),
-	  trap_raz_wi },
+	  access_gic_sre },
 
 	/* CONTEXTIDR_EL1 */
 	{ Op0(0b11), Op1(0b000), CRn(0b1101), CRm(0b0000), Op2(0b001),
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/Makefile linux-libre-4.7-gnu/arch/arm64/Makefile
--- linux-libre-4.6-gnu/arch/arm64/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -60,7 +60,9 @@ head-y		:= arch/arm64/kernel/head.o
 
 # The byte offset of the kernel image in RAM from the start of RAM.
 ifeq ($(CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET), y)
-TEXT_OFFSET := $(shell awk 'BEGIN {srand(); printf "0x%03x000\n", int(512 * rand())}')
+TEXT_OFFSET := $(shell awk "BEGIN {srand(); printf \"0x%06x\n\", \
+		 int(2 * 1024 * 1024 / (2 ^ $(CONFIG_ARM64_PAGE_SHIFT)) * \
+		 rand()) * (2 ^ $(CONFIG_ARM64_PAGE_SHIFT))}")
 else
 TEXT_OFFSET := 0x00080000
 endif
@@ -93,7 +95,7 @@ boot := arch/arm64/boot
 Image: vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
 
-Image.%: vmlinux
+Image.%: Image
 	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
 
 zinstall install:
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/mm/cache.S linux-libre-4.7-gnu/arch/arm64/mm/cache.S
--- linux-libre-4.6-gnu/arch/arm64/mm/cache.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/mm/cache.S	2016-07-24 15:23:50.000000000 -0400
@@ -24,8 +24,6 @@
 #include <asm/cpufeature.h>
 #include <asm/alternative.h>
 
-#include "proc-macros.S"
-
 /*
  *	flush_icache_range(start,end)
  *
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/mm/context.c linux-libre-4.7-gnu/arch/arm64/mm/context.c
--- linux-libre-4.6-gnu/arch/arm64/mm/context.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/mm/context.c	2016-07-24 15:23:50.000000000 -0400
@@ -75,8 +75,7 @@ void verify_cpu_asid_bits(void)
 		 */
 		pr_crit("CPU%d: smaller ASID size(%u) than boot CPU (%u)\n",
 				smp_processor_id(), asid, asid_bits);
-		update_cpu_boot_status(CPU_PANIC_KERNEL);
-		cpu_park_loop();
+		cpu_panic_kernel();
 	}
 }
 
@@ -180,7 +179,7 @@ static u64 new_context(struct mm_struct
 						 &asid_generation);
 	flush_context(cpu);
 
-	/* We have at least 1 ASID per CPU, so this will always succeed */
+	/* We have more ASIDs than CPUs, so this will always succeed */
 	asid = find_next_zero_bit(asid_map, NUM_USER_ASIDS, 1);
 
 set_asid:
@@ -228,8 +227,11 @@ switch_mm_fastpath:
 static int asids_init(void)
 {
 	asid_bits = get_cpu_asid_bits();
-	/* If we end up with more CPUs than ASIDs, expect things to crash */
-	WARN_ON(NUM_USER_ASIDS < num_possible_cpus());
+	/*
+	 * Expect allocation after rollover to fail if we don't have at least
+	 * one more ASID than CPUs. ASID #0 is reserved for init_mm.
+	 */
+	WARN_ON(NUM_USER_ASIDS - 1 <= num_possible_cpus());
 	atomic64_set(&asid_generation, ASID_FIRST_VERSION);
 	asid_map = kzalloc(BITS_TO_LONGS(NUM_USER_ASIDS) * sizeof(*asid_map),
 			   GFP_KERNEL);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/mm/dma-mapping.c linux-libre-4.7-gnu/arch/arm64/mm/dma-mapping.c
--- linux-libre-4.6-gnu/arch/arm64/mm/dma-mapping.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/mm/dma-mapping.c	2016-07-24 15:23:50.000000000 -0400
@@ -562,8 +562,8 @@ static void *__iommu_alloc_attrs(struct
 		struct page **pages;
 		pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL, coherent);
 
-		pages = iommu_dma_alloc(dev, iosize, gfp, ioprot, handle,
-					flush_page);
+		pages = iommu_dma_alloc(dev, iosize, gfp, attrs, ioprot,
+					handle, flush_page);
 		if (!pages)
 			return NULL;
 
@@ -804,57 +804,24 @@ struct iommu_dma_notifier_data {
 static LIST_HEAD(iommu_dma_masters);
 static DEFINE_MUTEX(iommu_dma_notifier_lock);
 
-/*
- * Temporarily "borrow" a domain feature flag to to tell if we had to resort
- * to creating our own domain here, in case we need to clean it up again.
- */
-#define __IOMMU_DOMAIN_FAKE_DEFAULT		(1U << 31)
-
 static bool do_iommu_attach(struct device *dev, const struct iommu_ops *ops,
 			   u64 dma_base, u64 size)
 {
 	struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
 
 	/*
-	 * Best case: The device is either part of a group which was
-	 * already attached to a domain in a previous call, or it's
-	 * been put in a default DMA domain by the IOMMU core.
+	 * If the IOMMU driver has the DMA domain support that we require,
+	 * then the IOMMU core will have already configured a group for this
+	 * device, and allocated the default domain for that group.
 	 */
-	if (!domain) {
-		/*
-		 * Urgh. The IOMMU core isn't going to do default domains
-		 * for non-PCI devices anyway, until it has some means of
-		 * abstracting the entirely implementation-specific
-		 * sideband data/SoC topology/unicorn dust that may or
-		 * may not differentiate upstream masters.
-		 * So until then, HORRIBLE HACKS!
-		 */
-		domain = ops->domain_alloc(IOMMU_DOMAIN_DMA);
-		if (!domain)
-			goto out_no_domain;
-
-		domain->ops = ops;
-		domain->type = IOMMU_DOMAIN_DMA | __IOMMU_DOMAIN_FAKE_DEFAULT;
-
-		if (iommu_attach_device(domain, dev))
-			goto out_put_domain;
+	if (!domain || iommu_dma_init_domain(domain, dma_base, size)) {
+		pr_warn("Failed to set up IOMMU for device %s; retaining platform DMA ops\n",
+			dev_name(dev));
+		return false;
 	}
 
-	if (iommu_dma_init_domain(domain, dma_base, size))
-		goto out_detach;
-
 	dev->archdata.dma_ops = &iommu_dma_ops;
 	return true;
-
-out_detach:
-	iommu_detach_device(domain, dev);
-out_put_domain:
-	if (domain->type & __IOMMU_DOMAIN_FAKE_DEFAULT)
-		iommu_domain_free(domain);
-out_no_domain:
-	pr_warn("Failed to set up IOMMU for device %s; retaining platform DMA ops\n",
-		dev_name(dev));
-	return false;
 }
 
 static void queue_iommu_attach(struct device *dev, const struct iommu_ops *ops,
@@ -933,6 +900,10 @@ static int __init __iommu_dma_init(void)
 		ret = register_iommu_dma_ops_notifier(&platform_bus_type);
 	if (!ret)
 		ret = register_iommu_dma_ops_notifier(&amba_bustype);
+#ifdef CONFIG_PCI
+	if (!ret)
+		ret = register_iommu_dma_ops_notifier(&pci_bus_type);
+#endif
 
 	/* handle devices queued before this arch_initcall */
 	if (!ret)
@@ -967,11 +938,8 @@ void arch_teardown_dma_ops(struct device
 {
 	struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
 
-	if (domain) {
+	if (WARN_ON(domain))
 		iommu_detach_device(domain, dev);
-		if (domain->type & __IOMMU_DOMAIN_FAKE_DEFAULT)
-			iommu_domain_free(domain);
-	}
 
 	dev->archdata.dma_ops = NULL;
 }
@@ -979,13 +947,13 @@ void arch_teardown_dma_ops(struct device
 #else
 
 static void __iommu_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
-				  struct iommu_ops *iommu)
+				  const struct iommu_ops *iommu)
 { }
 
 #endif  /* CONFIG_IOMMU_DMA */
 
 void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
-			struct iommu_ops *iommu, bool coherent)
+			const struct iommu_ops *iommu, bool coherent)
 {
 	if (!dev->archdata.dma_ops)
 		dev->archdata.dma_ops = &swiotlb_dma_ops;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/mm/dump.c linux-libre-4.7-gnu/arch/arm64/mm/dump.c
--- linux-libre-4.6-gnu/arch/arm64/mm/dump.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/mm/dump.c	2016-07-24 15:23:50.000000000 -0400
@@ -23,6 +23,7 @@
 #include <linux/seq_file.h>
 
 #include <asm/fixmap.h>
+#include <asm/kasan.h>
 #include <asm/memory.h>
 #include <asm/pgtable.h>
 #include <asm/pgtable-hwdef.h>
@@ -32,37 +33,25 @@ struct addr_marker {
 	const char *name;
 };
 
-enum address_markers_idx {
-	MODULES_START_NR = 0,
-	MODULES_END_NR,
-	VMALLOC_START_NR,
-	VMALLOC_END_NR,
-#ifdef CONFIG_SPARSEMEM_VMEMMAP
-	VMEMMAP_START_NR,
-	VMEMMAP_END_NR,
+static const struct addr_marker address_markers[] = {
+#ifdef CONFIG_KASAN
+	{ KASAN_SHADOW_START,		"Kasan shadow start" },
+	{ KASAN_SHADOW_END,		"Kasan shadow end" },
 #endif
-	FIXADDR_START_NR,
-	FIXADDR_END_NR,
-	PCI_START_NR,
-	PCI_END_NR,
-	KERNEL_SPACE_NR,
-};
-
-static struct addr_marker address_markers[] = {
-	{ MODULES_VADDR,	"Modules start" },
-	{ MODULES_END,		"Modules end" },
-	{ VMALLOC_START,	"vmalloc() Area" },
-	{ VMALLOC_END,		"vmalloc() End" },
+	{ MODULES_VADDR,		"Modules start" },
+	{ MODULES_END,			"Modules end" },
+	{ VMALLOC_START,		"vmalloc() Area" },
+	{ VMALLOC_END,			"vmalloc() End" },
+	{ FIXADDR_START,		"Fixmap start" },
+	{ FIXADDR_TOP,			"Fixmap end" },
+	{ PCI_IO_START,			"PCI I/O start" },
+	{ PCI_IO_END,			"PCI I/O end" },
 #ifdef CONFIG_SPARSEMEM_VMEMMAP
-	{ 0,			"vmemmap start" },
-	{ 0,			"vmemmap end" },
+	{ VMEMMAP_START,		"vmemmap start" },
+	{ VMEMMAP_START + VMEMMAP_SIZE,	"vmemmap end" },
 #endif
-	{ FIXADDR_START,	"Fixmap start" },
-	{ FIXADDR_TOP,		"Fixmap end" },
-	{ PCI_IO_START,		"PCI I/O start" },
-	{ PCI_IO_END,		"PCI I/O end" },
-	{ PAGE_OFFSET,		"Linear Mapping" },
-	{ -1,			NULL },
+	{ PAGE_OFFSET,			"Linear Mapping" },
+	{ -1,				NULL },
 };
 
 /*
@@ -161,6 +150,7 @@ static const struct prot_bits pte_bits[]
 
 struct pg_level {
 	const struct prot_bits *bits;
+	const char *name;
 	size_t num;
 	u64 mask;
 };
@@ -168,15 +158,19 @@ struct pg_level {
 static struct pg_level pg_level[] = {
 	{
 	}, { /* pgd */
+		.name	= "PGD",
 		.bits	= pte_bits,
 		.num	= ARRAY_SIZE(pte_bits),
 	}, { /* pud */
+		.name	= (CONFIG_PGTABLE_LEVELS > 3) ? "PUD" : "PGD",
 		.bits	= pte_bits,
 		.num	= ARRAY_SIZE(pte_bits),
 	}, { /* pmd */
+		.name	= (CONFIG_PGTABLE_LEVELS > 2) ? "PMD" : "PGD",
 		.bits	= pte_bits,
 		.num	= ARRAY_SIZE(pte_bits),
 	}, { /* pte */
+		.name	= "PTE",
 		.bits	= pte_bits,
 		.num	= ARRAY_SIZE(pte_bits),
 	},
@@ -225,7 +219,8 @@ static void note_page(struct pg_state *s
 				delta >>= 10;
 				unit++;
 			}
-			seq_printf(st->seq, "%9lu%c", delta, *unit);
+			seq_printf(st->seq, "%9lu%c %s", delta, *unit,
+				   pg_level[st->level].name);
 			if (pg_level[st->level].bits)
 				dump_prot(st, pg_level[st->level].bits,
 					  pg_level[st->level].num);
@@ -347,13 +342,6 @@ static int ptdump_init(void)
 			for (j = 0; j < pg_level[i].num; j++)
 				pg_level[i].mask |= pg_level[i].bits[j].mask;
 
-#ifdef CONFIG_SPARSEMEM_VMEMMAP
-	address_markers[VMEMMAP_START_NR].start_address =
-				(unsigned long)virt_to_page(PAGE_OFFSET);
-	address_markers[VMEMMAP_END_NR].start_address =
-				(unsigned long)virt_to_page(high_memory);
-#endif
-
 	pe = debugfs_create_file("kernel_page_tables", 0400, NULL, NULL,
 				 &ptdump_fops);
 	return pe ? 0 : -ENOMEM;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/mm/fault.c linux-libre-4.7-gnu/arch/arm64/mm/fault.c
--- linux-libre-4.6-gnu/arch/arm64/mm/fault.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/mm/fault.c	2016-07-24 15:23:50.000000000 -0400
@@ -81,6 +81,56 @@ void show_pte(struct mm_struct *mm, unsi
 	printk("\n");
 }
 
+#ifdef CONFIG_ARM64_HW_AFDBM
+/*
+ * This function sets the access flags (dirty, accessed), as well as write
+ * permission, and only to a more permissive setting.
+ *
+ * It needs to cope with hardware update of the accessed/dirty state by other
+ * agents in the system and can safely skip the __sync_icache_dcache() call as,
+ * like set_pte_at(), the PTE is never changed from no-exec to exec here.
+ *
+ * Returns whether or not the PTE actually changed.
+ */
+int ptep_set_access_flags(struct vm_area_struct *vma,
+			  unsigned long address, pte_t *ptep,
+			  pte_t entry, int dirty)
+{
+	pteval_t old_pteval;
+	unsigned int tmp;
+
+	if (pte_same(*ptep, entry))
+		return 0;
+
+	/* only preserve the access flags and write permission */
+	pte_val(entry) &= PTE_AF | PTE_WRITE | PTE_DIRTY;
+
+	/*
+	 * PTE_RDONLY is cleared by default in the asm below, so set it in
+	 * back if necessary (read-only or clean PTE).
+	 */
+	if (!pte_write(entry) || !pte_sw_dirty(entry))
+		pte_val(entry) |= PTE_RDONLY;
+
+	/*
+	 * Setting the flags must be done atomically to avoid racing with the
+	 * hardware update of the access/dirty state.
+	 */
+	asm volatile("//	ptep_set_access_flags\n"
+	"	prfm	pstl1strm, %2\n"
+	"1:	ldxr	%0, %2\n"
+	"	and	%0, %0, %3		// clear PTE_RDONLY\n"
+	"	orr	%0, %0, %4		// set flags\n"
+	"	stxr	%w1, %0, %2\n"
+	"	cbnz	%w1, 1b\n"
+	: "=&r" (old_pteval), "=&r" (tmp), "+Q" (pte_val(*ptep))
+	: "L" (~PTE_RDONLY), "r" (pte_val(entry)));
+
+	flush_tlb_fix_spurious_fault(vma, address);
+	return 1;
+}
+#endif
+
 /*
  * The kernel tried to access some page that wasn't present.
  */
@@ -212,10 +262,6 @@ static int __kprobes do_page_fault(unsig
 	tsk = current;
 	mm  = tsk->mm;
 
-	/* Enable interrupts if they were enabled in the parent context. */
-	if (interrupts_enabled(regs))
-		local_irq_enable();
-
 	/*
 	 * If we're in an interrupt or have no user context, we must not take
 	 * the fault.
@@ -234,7 +280,8 @@ static int __kprobes do_page_fault(unsig
 	}
 
 	if (permission_fault(esr) && (addr < USER_DS)) {
-		if (get_fs() == KERNEL_DS)
+		/* regs->orig_addr_limit may be 0 if we entered from EL0 */
+		if (regs->orig_addr_limit == KERNEL_DS)
 			die("Accessing user space memory with fs=KERNEL_DS", regs, esr);
 
 		if (!search_exception_tables(regs->pc))
@@ -395,7 +442,7 @@ static int do_bad(unsigned long addr, un
 	return 1;
 }
 
-static struct fault_info {
+static const struct fault_info {
 	int	(*fn)(unsigned long addr, unsigned int esr, struct pt_regs *regs);
 	int	sig;
 	int	code;
@@ -555,20 +602,33 @@ asmlinkage int __exception do_debug_exce
 {
 	const struct fault_info *inf = debug_fault_info + DBG_ESR_EVT(esr);
 	struct siginfo info;
+	int rv;
 
-	if (!inf->fn(addr, esr, regs))
-		return 1;
+	/*
+	 * Tell lockdep we disabled irqs in entry.S. Do nothing if they were
+	 * already disabled to preserve the last enabled/disabled addresses.
+	 */
+	if (interrupts_enabled(regs))
+		trace_hardirqs_off();
 
-	pr_alert("Unhandled debug exception: %s (0x%08x) at 0x%016lx\n",
-		 inf->name, esr, addr);
+	if (!inf->fn(addr, esr, regs)) {
+		rv = 1;
+	} else {
+		pr_alert("Unhandled debug exception: %s (0x%08x) at 0x%016lx\n",
+			 inf->name, esr, addr);
 
-	info.si_signo = inf->sig;
-	info.si_errno = 0;
-	info.si_code  = inf->code;
-	info.si_addr  = (void __user *)addr;
-	arm64_notify_die("", regs, &info, 0);
+		info.si_signo = inf->sig;
+		info.si_errno = 0;
+		info.si_code  = inf->code;
+		info.si_addr  = (void __user *)addr;
+		arm64_notify_die("", regs, &info, 0);
+		rv = 0;
+	}
 
-	return 0;
+	if (interrupts_enabled(regs))
+		trace_hardirqs_on();
+
+	return rv;
 }
 
 #ifdef CONFIG_ARM64_PAN
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/mm/flush.c linux-libre-4.7-gnu/arch/arm64/mm/flush.c
--- linux-libre-4.6-gnu/arch/arm64/mm/flush.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/mm/flush.c	2016-07-24 15:23:50.000000000 -0400
@@ -71,10 +71,6 @@ void __sync_icache_dcache(pte_t pte, uns
 {
 	struct page *page = pte_page(pte);
 
-	/* no flushing needed for anonymous pages */
-	if (!page_mapping(page))
-		return;
-
 	if (!test_and_set_bit(PG_dcache_clean, &page->flags))
 		sync_icache_aliases(page_address(page),
 				    PAGE_SIZE << compound_order(page));
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/mm/hugetlbpage.c linux-libre-4.7-gnu/arch/arm64/mm/hugetlbpage.c
--- linux-libre-4.6-gnu/arch/arm64/mm/hugetlbpage.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/mm/hugetlbpage.c	2016-07-24 15:23:50.000000000 -0400
@@ -306,10 +306,25 @@ static __init int setup_hugepagesz(char
 		hugetlb_add_hstate(PMD_SHIFT - PAGE_SHIFT);
 	} else if (ps == PUD_SIZE) {
 		hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT);
+	} else if (ps == (PAGE_SIZE * CONT_PTES)) {
+		hugetlb_add_hstate(CONT_PTE_SHIFT);
+	} else if (ps == (PMD_SIZE * CONT_PMDS)) {
+		hugetlb_add_hstate((PMD_SHIFT + CONT_PMD_SHIFT) - PAGE_SHIFT);
 	} else {
+		hugetlb_bad_size();
 		pr_err("hugepagesz: Unsupported page size %lu K\n", ps >> 10);
 		return 0;
 	}
 	return 1;
 }
 __setup("hugepagesz=", setup_hugepagesz);
+
+#ifdef CONFIG_ARM64_64K_PAGES
+static __init int add_default_hugepagesz(void)
+{
+	if (size_to_hstate(CONT_PTES * PAGE_SIZE) == NULL)
+		hugetlb_add_hstate(CONT_PMD_SHIFT);
+	return 0;
+}
+arch_initcall(add_default_hugepagesz);
+#endif
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/mm/init.c linux-libre-4.7-gnu/arch/arm64/mm/init.c
--- linux-libre-4.6-gnu/arch/arm64/mm/init.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/mm/init.c	2016-07-24 15:23:50.000000000 -0400
@@ -40,6 +40,7 @@
 #include <asm/kasan.h>
 #include <asm/kernel-pgtable.h>
 #include <asm/memory.h>
+#include <asm/numa.h>
 #include <asm/sections.h>
 #include <asm/setup.h>
 #include <asm/sizes.h>
@@ -86,6 +87,21 @@ static phys_addr_t __init max_zone_dma_p
 	return min(offset + (1ULL << 32), memblock_end_of_DRAM());
 }
 
+#ifdef CONFIG_NUMA
+
+static void __init zone_sizes_init(unsigned long min, unsigned long max)
+{
+	unsigned long max_zone_pfns[MAX_NR_ZONES]  = {0};
+
+	if (IS_ENABLED(CONFIG_ZONE_DMA))
+		max_zone_pfns[ZONE_DMA] = PFN_DOWN(max_zone_dma_phys());
+	max_zone_pfns[ZONE_NORMAL] = max;
+
+	free_area_init_nodes(max_zone_pfns);
+}
+
+#else
+
 static void __init zone_sizes_init(unsigned long min, unsigned long max)
 {
 	struct memblock_region *reg;
@@ -126,6 +142,8 @@ static void __init zone_sizes_init(unsig
 	free_area_init_node(0, zone_size, min, zhole_size);
 }
 
+#endif /* CONFIG_NUMA */
+
 #ifdef CONFIG_HAVE_ARCH_PFN_VALID
 int pfn_valid(unsigned long pfn)
 {
@@ -142,10 +160,15 @@ static void __init arm64_memory_present(
 static void __init arm64_memory_present(void)
 {
 	struct memblock_region *reg;
+	int nid = 0;
 
-	for_each_memblock(memory, reg)
-		memory_present(0, memblock_region_memory_base_pfn(reg),
-			       memblock_region_memory_end_pfn(reg));
+	for_each_memblock(memory, reg) {
+#ifdef CONFIG_NUMA
+		nid = reg->nid;
+#endif
+		memory_present(nid, memblock_region_memory_base_pfn(reg),
+				memblock_region_memory_end_pfn(reg));
+	}
 }
 #endif
 
@@ -190,8 +213,12 @@ void __init arm64_memblock_init(void)
 	 */
 	memblock_remove(max_t(u64, memstart_addr + linear_region_size, __pa(_end)),
 			ULLONG_MAX);
-	if (memblock_end_of_DRAM() > linear_region_size)
-		memblock_remove(0, memblock_end_of_DRAM() - linear_region_size);
+	if (memstart_addr + linear_region_size < memblock_end_of_DRAM()) {
+		/* ensure that memstart_addr remains sufficiently aligned */
+		memstart_addr = round_up(memblock_end_of_DRAM() - linear_region_size,
+					 ARM64_MEMSTART_ALIGN);
+		memblock_remove(0, memstart_addr);
+	}
 
 	/*
 	 * Apply the memory limit if it was set. Since the kernel may be loaded
@@ -203,6 +230,35 @@ void __init arm64_memblock_init(void)
 		memblock_add(__pa(_text), (u64)(_end - _text));
 	}
 
+	if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) && initrd_start) {
+		/*
+		 * Add back the memory we just removed if it results in the
+		 * initrd to become inaccessible via the linear mapping.
+		 * Otherwise, this is a no-op
+		 */
+		u64 base = initrd_start & PAGE_MASK;
+		u64 size = PAGE_ALIGN(initrd_end) - base;
+
+		/*
+		 * We can only add back the initrd memory if we don't end up
+		 * with more memory than we can address via the linear mapping.
+		 * It is up to the bootloader to position the kernel and the
+		 * initrd reasonably close to each other (i.e., within 32 GB of
+		 * each other) so that all granule/#levels combinations can
+		 * always access both.
+		 */
+		if (WARN(base < memblock_start_of_DRAM() ||
+			 base + size > memblock_start_of_DRAM() +
+				       linear_region_size,
+			"initrd not fully accessible via the linear mapping -- please check your bootloader ...\n")) {
+			initrd_start = 0;
+		} else {
+			memblock_remove(base, size); /* clear MEMBLOCK_ flags */
+			memblock_add(base, size);
+			memblock_reserve(base, size);
+		}
+	}
+
 	if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
 		extern u16 memstart_offset_seed;
 		u64 range = linear_region_size -
@@ -245,7 +301,6 @@ void __init arm64_memblock_init(void)
 	dma_contiguous_reserve(arm64_dma_phys_limit);
 
 	memblock_allow_resize();
-	memblock_dump_all();
 }
 
 void __init bootmem_init(void)
@@ -257,6 +312,9 @@ void __init bootmem_init(void)
 
 	early_memtest(min << PAGE_SHIFT, max << PAGE_SHIFT);
 
+	max_pfn = max_low_pfn = max;
+
+	arm64_numa_init();
 	/*
 	 * Sparsemem tries to allocate bootmem in memory_present(), so must be
 	 * done after the fixed reservations.
@@ -267,7 +325,7 @@ void __init bootmem_init(void)
 	zone_sizes_init(min, max);
 
 	high_memory = __va((max << PAGE_SHIFT) - 1) + 1;
-	max_pfn = max_low_pfn = max;
+	memblock_dump_all();
 }
 
 #ifndef CONFIG_SPARSEMEM_VMEMMAP
@@ -371,26 +429,27 @@ void __init mem_init(void)
 		MLM(MODULES_VADDR, MODULES_END));
 	pr_cont("    vmalloc : 0x%16lx - 0x%16lx   (%6ld GB)\n",
 		MLG(VMALLOC_START, VMALLOC_END));
-	pr_cont("      .text : 0x%p" " - 0x%p" "   (%6ld KB)\n"
-		"    .rodata : 0x%p" " - 0x%p" "   (%6ld KB)\n"
-		"      .init : 0x%p" " - 0x%p" "   (%6ld KB)\n"
-		"      .data : 0x%p" " - 0x%p" "   (%6ld KB)\n",
-		MLK_ROUNDUP(_text, __start_rodata),
-		MLK_ROUNDUP(__start_rodata, _etext),
-		MLK_ROUNDUP(__init_begin, __init_end),
+	pr_cont("      .text : 0x%p" " - 0x%p" "   (%6ld KB)\n",
+		MLK_ROUNDUP(_text, __start_rodata));
+	pr_cont("    .rodata : 0x%p" " - 0x%p" "   (%6ld KB)\n",
+		MLK_ROUNDUP(__start_rodata, _etext));
+	pr_cont("      .init : 0x%p" " - 0x%p" "   (%6ld KB)\n",
+		MLK_ROUNDUP(__init_begin, __init_end));
+	pr_cont("      .data : 0x%p" " - 0x%p" "   (%6ld KB)\n",
 		MLK_ROUNDUP(_sdata, _edata));
-#ifdef CONFIG_SPARSEMEM_VMEMMAP
-	pr_cont("    vmemmap : 0x%16lx - 0x%16lx   (%6ld GB maximum)\n"
-		"              0x%16lx - 0x%16lx   (%6ld MB actual)\n",
-		MLG(VMEMMAP_START,
-		    VMEMMAP_START + VMEMMAP_SIZE),
-		MLM((unsigned long)phys_to_page(memblock_start_of_DRAM()),
-		    (unsigned long)virt_to_page(high_memory)));
-#endif
+	pr_cont("       .bss : 0x%p" " - 0x%p" "   (%6ld KB)\n",
+		MLK_ROUNDUP(__bss_start, __bss_stop));
 	pr_cont("    fixed   : 0x%16lx - 0x%16lx   (%6ld KB)\n",
 		MLK(FIXADDR_START, FIXADDR_TOP));
 	pr_cont("    PCI I/O : 0x%16lx - 0x%16lx   (%6ld MB)\n",
 		MLM(PCI_IO_START, PCI_IO_END));
+#ifdef CONFIG_SPARSEMEM_VMEMMAP
+	pr_cont("    vmemmap : 0x%16lx - 0x%16lx   (%6ld GB maximum)\n",
+		MLG(VMEMMAP_START, VMEMMAP_START + VMEMMAP_SIZE));
+	pr_cont("              0x%16lx - 0x%16lx   (%6ld MB actual)\n",
+		MLM((unsigned long)phys_to_page(memblock_start_of_DRAM()),
+		    (unsigned long)virt_to_page(high_memory)));
+#endif
 	pr_cont("    memory  : 0x%16lx - 0x%16lx   (%6ld MB)\n",
 		MLM(__phys_to_virt(memblock_start_of_DRAM()),
 		    (unsigned long)high_memory));
@@ -407,6 +466,12 @@ void __init mem_init(void)
 	BUILD_BUG_ON(TASK_SIZE_32			> TASK_SIZE_64);
 #endif
 
+	/*
+	 * Make sure we chose the upper bound of sizeof(struct page)
+	 * correctly.
+	 */
+	BUILD_BUG_ON(sizeof(struct page) > (1 << STRUCT_PAGE_MAX_SHIFT));
+
 	if (PAGE_SIZE >= 16384 && get_num_physpages() <= 128) {
 		extern int sysctl_overcommit_memory;
 		/*
@@ -419,7 +484,8 @@ void __init mem_init(void)
 
 void free_initmem(void)
 {
-	free_initmem_default(0);
+	free_reserved_area(__va(__pa(__init_begin)), __va(__pa(__init_end)),
+			   0, "unused kernel");
 	fixup_init();
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/mm/Makefile linux-libre-4.7-gnu/arch/arm64/mm/Makefile
--- linux-libre-4.6-gnu/arch/arm64/mm/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/mm/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -4,6 +4,7 @@ obj-y				:= dma-mapping.o extable.o faul
 				   context.o proc.o pageattr.o
 obj-$(CONFIG_HUGETLB_PAGE)	+= hugetlbpage.o
 obj-$(CONFIG_ARM64_PTDUMP)	+= dump.o
+obj-$(CONFIG_NUMA)		+= numa.o
 
 obj-$(CONFIG_KASAN)		+= kasan_init.o
 KASAN_SANITIZE_kasan_init.o	:= n
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/mm/mmap.c linux-libre-4.7-gnu/arch/arm64/mm/mmap.c
--- linux-libre-4.6-gnu/arch/arm64/mm/mmap.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/mm/mmap.c	2016-07-24 15:23:50.000000000 -0400
@@ -95,8 +95,6 @@ void arch_pick_mmap_layout(struct mm_str
 		mm->get_unmapped_area = arch_get_unmapped_area_topdown;
 	}
 }
-EXPORT_SYMBOL_GPL(arch_pick_mmap_layout);
-
 
 /*
  * You really shouldn't be using read() or write() on /dev/mem.  This might go
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/mm/mm.h linux-libre-4.7-gnu/arch/arm64/mm/mm.h
--- linux-libre-4.6-gnu/arch/arm64/mm/mm.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/mm/mm.h	2016-07-24 15:23:50.000000000 -0400
@@ -1,3 +1,2 @@
-extern void __init bootmem_init(void);
 
 void fixup_init(void);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/mm/mmu.c linux-libre-4.7-gnu/arch/arm64/mm/mmu.c
--- linux-libre-4.6-gnu/arch/arm64/mm/mmu.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/mm/mmu.c	2016-07-24 15:23:50.000000000 -0400
@@ -385,7 +385,7 @@ static void create_mapping_late(phys_add
 
 static void __init __map_memblock(pgd_t *pgd, phys_addr_t start, phys_addr_t end)
 {
-	unsigned long kernel_start = __pa(_stext);
+	unsigned long kernel_start = __pa(_text);
 	unsigned long kernel_end = __pa(_etext);
 
 	/*
@@ -417,7 +417,7 @@ static void __init __map_memblock(pgd_t
 				     early_pgtable_alloc);
 
 	/*
-	 * Map the linear alias of the [_stext, _etext) interval as
+	 * Map the linear alias of the [_text, _etext) interval as
 	 * read-only/non-executable. This makes the contents of the
 	 * region accessible to subsystems such as hibernate, but
 	 * protects it from inadvertent modification or execution.
@@ -449,8 +449,8 @@ void mark_rodata_ro(void)
 {
 	unsigned long section_size;
 
-	section_size = (unsigned long)__start_rodata - (unsigned long)_stext;
-	create_mapping_late(__pa(_stext), (unsigned long)_stext,
+	section_size = (unsigned long)__start_rodata - (unsigned long)_text;
+	create_mapping_late(__pa(_text), (unsigned long)_text,
 			    section_size, PAGE_KERNEL_ROX);
 	/*
 	 * mark .rodata as read only. Use _etext rather than __end_rodata to
@@ -471,8 +471,8 @@ void fixup_init(void)
 	unmap_kernel_range((u64)__init_begin, (u64)(__init_end - __init_begin));
 }
 
-static void __init map_kernel_chunk(pgd_t *pgd, void *va_start, void *va_end,
-				    pgprot_t prot, struct vm_struct *vma)
+static void __init map_kernel_segment(pgd_t *pgd, void *va_start, void *va_end,
+				      pgprot_t prot, struct vm_struct *vma)
 {
 	phys_addr_t pa_start = __pa(va_start);
 	unsigned long size = va_end - va_start;
@@ -499,11 +499,11 @@ static void __init map_kernel(pgd_t *pgd
 {
 	static struct vm_struct vmlinux_text, vmlinux_rodata, vmlinux_init, vmlinux_data;
 
-	map_kernel_chunk(pgd, _stext, __start_rodata, PAGE_KERNEL_EXEC, &vmlinux_text);
-	map_kernel_chunk(pgd, __start_rodata, _etext, PAGE_KERNEL, &vmlinux_rodata);
-	map_kernel_chunk(pgd, __init_begin, __init_end, PAGE_KERNEL_EXEC,
-			 &vmlinux_init);
-	map_kernel_chunk(pgd, _data, _end, PAGE_KERNEL, &vmlinux_data);
+	map_kernel_segment(pgd, _text, __start_rodata, PAGE_KERNEL_EXEC, &vmlinux_text);
+	map_kernel_segment(pgd, __start_rodata, _etext, PAGE_KERNEL, &vmlinux_rodata);
+	map_kernel_segment(pgd, __init_begin, __init_end, PAGE_KERNEL_EXEC,
+			   &vmlinux_init);
+	map_kernel_segment(pgd, _data, _end, PAGE_KERNEL, &vmlinux_data);
 
 	if (!pgd_val(*pgd_offset_raw(pgd, FIXADDR_START))) {
 		/*
@@ -564,8 +564,6 @@ void __init paging_init(void)
 	 */
 	memblock_free(__pa(swapper_pg_dir) + PAGE_SIZE,
 		      SWAPPER_DIR_SIZE - PAGE_SIZE);
-
-	bootmem_init();
 }
 
 /*
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/mm/numa.c linux-libre-4.7-gnu/arch/arm64/mm/numa.c
--- linux-libre-4.6-gnu/arch/arm64/mm/numa.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/arm64/mm/numa.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,396 @@
+/*
+ * NUMA support, based on the x86 implementation.
+ *
+ * Copyright (C) 2015 Cavium Inc.
+ * Author: Ganapatrao Kulkarni <gkulkarni@cavium.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/bootmem.h>
+#include <linux/memblock.h>
+#include <linux/module.h>
+#include <linux/of.h>
+
+struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
+EXPORT_SYMBOL(node_data);
+nodemask_t numa_nodes_parsed __initdata;
+static int cpu_to_node_map[NR_CPUS] = { [0 ... NR_CPUS-1] = NUMA_NO_NODE };
+
+static int numa_distance_cnt;
+static u8 *numa_distance;
+static int numa_off;
+
+static __init int numa_parse_early_param(char *opt)
+{
+	if (!opt)
+		return -EINVAL;
+	if (!strncmp(opt, "off", 3)) {
+		pr_info("%s\n", "NUMA turned off");
+		numa_off = 1;
+	}
+	return 0;
+}
+early_param("numa", numa_parse_early_param);
+
+cpumask_var_t node_to_cpumask_map[MAX_NUMNODES];
+EXPORT_SYMBOL(node_to_cpumask_map);
+
+#ifdef CONFIG_DEBUG_PER_CPU_MAPS
+
+/*
+ * Returns a pointer to the bitmask of CPUs on Node 'node'.
+ */
+const struct cpumask *cpumask_of_node(int node)
+{
+	if (WARN_ON(node >= nr_node_ids))
+		return cpu_none_mask;
+
+	if (WARN_ON(node_to_cpumask_map[node] == NULL))
+		return cpu_online_mask;
+
+	return node_to_cpumask_map[node];
+}
+EXPORT_SYMBOL(cpumask_of_node);
+
+#endif
+
+static void map_cpu_to_node(unsigned int cpu, int nid)
+{
+	set_cpu_numa_node(cpu, nid);
+	if (nid >= 0)
+		cpumask_set_cpu(cpu, node_to_cpumask_map[nid]);
+}
+
+void numa_clear_node(unsigned int cpu)
+{
+	int nid = cpu_to_node(cpu);
+
+	if (nid >= 0)
+		cpumask_clear_cpu(cpu, node_to_cpumask_map[nid]);
+	set_cpu_numa_node(cpu, NUMA_NO_NODE);
+}
+
+/*
+ * Allocate node_to_cpumask_map based on number of available nodes
+ * Requires node_possible_map to be valid.
+ *
+ * Note: cpumask_of_node() is not valid until after this is done.
+ * (Use CONFIG_DEBUG_PER_CPU_MAPS to check this.)
+ */
+static void __init setup_node_to_cpumask_map(void)
+{
+	unsigned int cpu;
+	int node;
+
+	/* setup nr_node_ids if not done yet */
+	if (nr_node_ids == MAX_NUMNODES)
+		setup_nr_node_ids();
+
+	/* allocate and clear the mapping */
+	for (node = 0; node < nr_node_ids; node++) {
+		alloc_bootmem_cpumask_var(&node_to_cpumask_map[node]);
+		cpumask_clear(node_to_cpumask_map[node]);
+	}
+
+	for_each_possible_cpu(cpu)
+		set_cpu_numa_node(cpu, NUMA_NO_NODE);
+
+	/* cpumask_of_node() will now work */
+	pr_debug("NUMA: Node to cpumask map for %d nodes\n", nr_node_ids);
+}
+
+/*
+ *  Set the cpu to node and mem mapping
+ */
+void numa_store_cpu_info(unsigned int cpu)
+{
+	map_cpu_to_node(cpu, numa_off ? 0 : cpu_to_node_map[cpu]);
+}
+
+void __init early_map_cpu_to_node(unsigned int cpu, int nid)
+{
+	/* fallback to node 0 */
+	if (nid < 0 || nid >= MAX_NUMNODES)
+		nid = 0;
+
+	cpu_to_node_map[cpu] = nid;
+}
+
+/**
+ * numa_add_memblk - Set node id to memblk
+ * @nid: NUMA node ID of the new memblk
+ * @start: Start address of the new memblk
+ * @size:  Size of the new memblk
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
+ */
+int __init numa_add_memblk(int nid, u64 start, u64 size)
+{
+	int ret;
+
+	ret = memblock_set_node(start, size, &memblock.memory, nid);
+	if (ret < 0) {
+		pr_err("NUMA: memblock [0x%llx - 0x%llx] failed to add on node %d\n",
+			start, (start + size - 1), nid);
+		return ret;
+	}
+
+	node_set(nid, numa_nodes_parsed);
+	pr_info("NUMA: Adding memblock [0x%llx - 0x%llx] on node %d\n",
+			start, (start + size - 1), nid);
+	return ret;
+}
+
+/**
+ * Initialize NODE_DATA for a node on the local memory
+ */
+static void __init setup_node_data(int nid, u64 start_pfn, u64 end_pfn)
+{
+	const size_t nd_size = roundup(sizeof(pg_data_t), SMP_CACHE_BYTES);
+	u64 nd_pa;
+	void *nd;
+	int tnid;
+
+	pr_info("NUMA: Initmem setup node %d [mem %#010Lx-%#010Lx]\n",
+			nid, start_pfn << PAGE_SHIFT,
+			(end_pfn << PAGE_SHIFT) - 1);
+
+	nd_pa = memblock_alloc_try_nid(nd_size, SMP_CACHE_BYTES, nid);
+	nd = __va(nd_pa);
+
+	/* report and initialize */
+	pr_info("NUMA: NODE_DATA [mem %#010Lx-%#010Lx]\n",
+		nd_pa, nd_pa + nd_size - 1);
+	tnid = early_pfn_to_nid(nd_pa >> PAGE_SHIFT);
+	if (tnid != nid)
+		pr_info("NUMA: NODE_DATA(%d) on node %d\n", nid, tnid);
+
+	node_data[nid] = nd;
+	memset(NODE_DATA(nid), 0, sizeof(pg_data_t));
+	NODE_DATA(nid)->node_id = nid;
+	NODE_DATA(nid)->node_start_pfn = start_pfn;
+	NODE_DATA(nid)->node_spanned_pages = end_pfn - start_pfn;
+}
+
+/**
+ * numa_free_distance
+ *
+ * The current table is freed.
+ */
+void __init numa_free_distance(void)
+{
+	size_t size;
+
+	if (!numa_distance)
+		return;
+
+	size = numa_distance_cnt * numa_distance_cnt *
+		sizeof(numa_distance[0]);
+
+	memblock_free(__pa(numa_distance), size);
+	numa_distance_cnt = 0;
+	numa_distance = NULL;
+}
+
+/**
+ *
+ * Create a new NUMA distance table.
+ *
+ */
+static int __init numa_alloc_distance(void)
+{
+	size_t size;
+	u64 phys;
+	int i, j;
+
+	size = nr_node_ids * nr_node_ids * sizeof(numa_distance[0]);
+	phys = memblock_find_in_range(0, PFN_PHYS(max_pfn),
+				      size, PAGE_SIZE);
+	if (WARN_ON(!phys))
+		return -ENOMEM;
+
+	memblock_reserve(phys, size);
+
+	numa_distance = __va(phys);
+	numa_distance_cnt = nr_node_ids;
+
+	/* fill with the default distances */
+	for (i = 0; i < numa_distance_cnt; i++)
+		for (j = 0; j < numa_distance_cnt; j++)
+			numa_distance[i * numa_distance_cnt + j] = i == j ?
+				LOCAL_DISTANCE : REMOTE_DISTANCE;
+
+	pr_debug("NUMA: Initialized distance table, cnt=%d\n",
+			numa_distance_cnt);
+
+	return 0;
+}
+
+/**
+ * numa_set_distance - Set inter node NUMA distance from node to node.
+ * @from: the 'from' node to set distance
+ * @to: the 'to'  node to set distance
+ * @distance: NUMA distance
+ *
+ * Set the distance from node @from to @to to @distance.
+ * If distance table doesn't exist, a warning is printed.
+ *
+ * If @from or @to is higher than the highest known node or lower than zero
+ * or @distance doesn't make sense, the call is ignored.
+ *
+ */
+void __init numa_set_distance(int from, int to, int distance)
+{
+	if (!numa_distance) {
+		pr_warn_once("NUMA: Warning: distance table not allocated yet\n");
+		return;
+	}
+
+	if (from >= numa_distance_cnt || to >= numa_distance_cnt ||
+			from < 0 || to < 0) {
+		pr_warn_once("NUMA: Warning: node ids are out of bound, from=%d to=%d distance=%d\n",
+			    from, to, distance);
+		return;
+	}
+
+	if ((u8)distance != distance ||
+	    (from == to && distance != LOCAL_DISTANCE)) {
+		pr_warn_once("NUMA: Warning: invalid distance parameter, from=%d to=%d distance=%d\n",
+			     from, to, distance);
+		return;
+	}
+
+	numa_distance[from * numa_distance_cnt + to] = distance;
+}
+
+/**
+ * Return NUMA distance @from to @to
+ */
+int __node_distance(int from, int to)
+{
+	if (from >= numa_distance_cnt || to >= numa_distance_cnt)
+		return from == to ? LOCAL_DISTANCE : REMOTE_DISTANCE;
+	return numa_distance[from * numa_distance_cnt + to];
+}
+EXPORT_SYMBOL(__node_distance);
+
+static int __init numa_register_nodes(void)
+{
+	int nid;
+	struct memblock_region *mblk;
+
+	/* Check that valid nid is set to memblks */
+	for_each_memblock(memory, mblk)
+		if (mblk->nid == NUMA_NO_NODE || mblk->nid >= MAX_NUMNODES) {
+			pr_warn("NUMA: Warning: invalid memblk node %d [mem %#010Lx-%#010Lx]\n",
+				mblk->nid, mblk->base,
+				mblk->base + mblk->size - 1);
+			return -EINVAL;
+		}
+
+	/* Finally register nodes. */
+	for_each_node_mask(nid, numa_nodes_parsed) {
+		unsigned long start_pfn, end_pfn;
+
+		get_pfn_range_for_nid(nid, &start_pfn, &end_pfn);
+		setup_node_data(nid, start_pfn, end_pfn);
+		node_set_online(nid);
+	}
+
+	/* Setup online nodes to actual nodes*/
+	node_possible_map = numa_nodes_parsed;
+
+	return 0;
+}
+
+static int __init numa_init(int (*init_func)(void))
+{
+	int ret;
+
+	nodes_clear(numa_nodes_parsed);
+	nodes_clear(node_possible_map);
+	nodes_clear(node_online_map);
+	numa_free_distance();
+
+	ret = numa_alloc_distance();
+	if (ret < 0)
+		return ret;
+
+	ret = init_func();
+	if (ret < 0)
+		return ret;
+
+	if (nodes_empty(numa_nodes_parsed))
+		return -EINVAL;
+
+	ret = numa_register_nodes();
+	if (ret < 0)
+		return ret;
+
+	setup_node_to_cpumask_map();
+
+	/* init boot processor */
+	cpu_to_node_map[0] = 0;
+	map_cpu_to_node(0, 0);
+
+	return 0;
+}
+
+/**
+ * dummy_numa_init - Fallback dummy NUMA init
+ *
+ * Used if there's no underlying NUMA architecture, NUMA initialization
+ * fails, or NUMA is disabled on the command line.
+ *
+ * Must online at least one node (node 0) and add memory blocks that cover all
+ * allowed memory. It is unlikely that this function fails.
+ */
+static int __init dummy_numa_init(void)
+{
+	int ret;
+	struct memblock_region *mblk;
+
+	pr_info("%s\n", "No NUMA configuration found");
+	pr_info("NUMA: Faking a node at [mem %#018Lx-%#018Lx]\n",
+	       0LLU, PFN_PHYS(max_pfn) - 1);
+
+	for_each_memblock(memory, mblk) {
+		ret = numa_add_memblk(0, mblk->base, mblk->size);
+		if (!ret)
+			continue;
+
+		pr_err("NUMA init failed\n");
+		return ret;
+	}
+
+	numa_off = 1;
+	return 0;
+}
+
+/**
+ * arm64_numa_init - Initialize NUMA
+ *
+ * Try each configured NUMA initialization method until one succeeds.  The
+ * last fallback is dummy single node config encomapssing whole memory.
+ */
+void __init arm64_numa_init(void)
+{
+	if (!numa_off) {
+		if (!numa_init(of_numa_init))
+			return;
+	}
+
+	numa_init(dummy_numa_init);
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/mm/proc-macros.S linux-libre-4.7-gnu/arch/arm64/mm/proc-macros.S
--- linux-libre-4.6-gnu/arch/arm64/mm/proc-macros.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/mm/proc-macros.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,98 +0,0 @@
-/*
- * Based on arch/arm/mm/proc-macros.S
- *
- * Copyright (C) 2012 ARM Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-#include <asm/asm-offsets.h>
-#include <asm/thread_info.h>
-
-/*
- * vma_vm_mm - get mm pointer from vma pointer (vma->vm_mm)
- */
-	.macro	vma_vm_mm, rd, rn
-	ldr	\rd, [\rn, #VMA_VM_MM]
-	.endm
-
-/*
- * mmid - get context id from mm pointer (mm->context.id)
- */
-	.macro	mmid, rd, rn
-	ldr	\rd, [\rn, #MM_CONTEXT_ID]
-	.endm
-
-/*
- * dcache_line_size - get the minimum D-cache line size from the CTR register.
- */
-	.macro	dcache_line_size, reg, tmp
-	mrs	\tmp, ctr_el0			// read CTR
-	ubfm	\tmp, \tmp, #16, #19		// cache line size encoding
-	mov	\reg, #4			// bytes per word
-	lsl	\reg, \reg, \tmp		// actual cache line size
-	.endm
-
-/*
- * icache_line_size - get the minimum I-cache line size from the CTR register.
- */
-	.macro	icache_line_size, reg, tmp
-	mrs	\tmp, ctr_el0			// read CTR
-	and	\tmp, \tmp, #0xf		// cache line size encoding
-	mov	\reg, #4			// bytes per word
-	lsl	\reg, \reg, \tmp		// actual cache line size
-	.endm
-
-/*
- * tcr_set_idmap_t0sz - update TCR.T0SZ so that we can load the ID map
- */
-	.macro	tcr_set_idmap_t0sz, valreg, tmpreg
-#ifndef CONFIG_ARM64_VA_BITS_48
-	ldr_l	\tmpreg, idmap_t0sz
-	bfi	\valreg, \tmpreg, #TCR_T0SZ_OFFSET, #TCR_TxSZ_WIDTH
-#endif
-	.endm
-
-/*
- * Macro to perform a data cache maintenance for the interval
- * [kaddr, kaddr + size)
- *
- * 	op:		operation passed to dc instruction
- * 	domain:		domain used in dsb instruciton
- * 	kaddr:		starting virtual address of the region
- * 	size:		size of the region
- * 	Corrupts: 	kaddr, size, tmp1, tmp2
- */
-	.macro dcache_by_line_op op, domain, kaddr, size, tmp1, tmp2
-	dcache_line_size \tmp1, \tmp2
-	add	\size, \kaddr, \size
-	sub	\tmp2, \tmp1, #1
-	bic	\kaddr, \kaddr, \tmp2
-9998:	dc	\op, \kaddr
-	add	\kaddr, \kaddr, \tmp1
-	cmp	\kaddr, \size
-	b.lo	9998b
-	dsb	\domain
-	.endm
-
-/*
- * reset_pmuserenr_el0 - reset PMUSERENR_EL0 if PMUv3 present
- */
-	.macro	reset_pmuserenr_el0, tmpreg
-	mrs	\tmpreg, id_aa64dfr0_el1	// Check ID_AA64DFR0_EL1 PMUVer
-	sbfx	\tmpreg, \tmpreg, #8, #4
-	cmp	\tmpreg, #1			// Skip if no PMU present
-	b.lt	9000f
-	msr	pmuserenr_el0, xzr		// Disable PMU access from EL0
-9000:
-	.endm
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/mm/proc.S linux-libre-4.7-gnu/arch/arm64/mm/proc.S
--- linux-libre-4.6-gnu/arch/arm64/mm/proc.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/mm/proc.S	2016-07-24 15:23:50.000000000 -0400
@@ -23,13 +23,11 @@
 #include <asm/assembler.h>
 #include <asm/asm-offsets.h>
 #include <asm/hwcap.h>
-#include <asm/pgtable-hwdef.h>
 #include <asm/pgtable.h>
+#include <asm/pgtable-hwdef.h>
 #include <asm/cpufeature.h>
 #include <asm/alternative.h>
 
-#include "proc-macros.S"
-
 #ifdef CONFIG_ARM64_64K_PAGES
 #define TCR_TG_FLAGS	TCR_TG0_64K | TCR_TG1_64K
 #elif defined(CONFIG_ARM64_16K_PAGES)
@@ -66,62 +64,50 @@ ENTRY(cpu_do_suspend)
 	mrs	x2, tpidr_el0
 	mrs	x3, tpidrro_el0
 	mrs	x4, contextidr_el1
-	mrs	x5, mair_el1
-	mrs	x6, cpacr_el1
-	mrs	x7, ttbr1_el1
-	mrs	x8, tcr_el1
-	mrs	x9, vbar_el1
-	mrs	x10, mdscr_el1
-	mrs	x11, oslsr_el1
-	mrs	x12, sctlr_el1
+	mrs	x5, cpacr_el1
+	mrs	x6, tcr_el1
+	mrs	x7, vbar_el1
+	mrs	x8, mdscr_el1
+	mrs	x9, oslsr_el1
+	mrs	x10, sctlr_el1
 	stp	x2, x3, [x0]
-	stp	x4, x5, [x0, #16]
-	stp	x6, x7, [x0, #32]
-	stp	x8, x9, [x0, #48]
-	stp	x10, x11, [x0, #64]
-	str	x12, [x0, #80]
+	stp	x4, xzr, [x0, #16]
+	stp	x5, x6, [x0, #32]
+	stp	x7, x8, [x0, #48]
+	stp	x9, x10, [x0, #64]
 	ret
 ENDPROC(cpu_do_suspend)
 
 /**
  * cpu_do_resume - restore CPU register context
  *
- * x0: Physical address of context pointer
- * x1: ttbr0_el1 to be restored
- *
- * Returns:
- *	sctlr_el1 value in x0
+ * x0: Address of context pointer
  */
 ENTRY(cpu_do_resume)
-	/*
-	 * Invalidate local tlb entries before turning on MMU
-	 */
-	tlbi	vmalle1
 	ldp	x2, x3, [x0]
 	ldp	x4, x5, [x0, #16]
-	ldp	x6, x7, [x0, #32]
-	ldp	x8, x9, [x0, #48]
-	ldp	x10, x11, [x0, #64]
-	ldr	x12, [x0, #80]
+	ldp	x6, x8, [x0, #32]
+	ldp	x9, x10, [x0, #48]
+	ldp	x11, x12, [x0, #64]
 	msr	tpidr_el0, x2
 	msr	tpidrro_el0, x3
 	msr	contextidr_el1, x4
-	msr	mair_el1, x5
 	msr	cpacr_el1, x6
-	msr	ttbr0_el1, x1
-	msr	ttbr1_el1, x7
-	tcr_set_idmap_t0sz x8, x7
+
+	/* Don't change t0sz here, mask those bits when restoring */
+	mrs	x5, tcr_el1
+	bfi	x8, x5, TCR_T0SZ_OFFSET, TCR_TxSZ_WIDTH
+
 	msr	tcr_el1, x8
 	msr	vbar_el1, x9
 	msr	mdscr_el1, x10
+	msr	sctlr_el1, x12
 	/*
 	 * Restore oslsr_el1 by writing oslar_el1
 	 */
 	ubfx	x11, x11, #1, #1
 	msr	oslar_el1, x11
 	reset_pmuserenr_el0 x0			// Disable PMU access from EL0
-	mov	x0, x12
-	dsb	nsh		// Make sure local tlb invalidation completed
 	isb
 	ret
 ENDPROC(cpu_do_resume)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/arm64/net/bpf_jit_comp.c linux-libre-4.7-gnu/arch/arm64/net/bpf_jit_comp.c
--- linux-libre-4.6-gnu/arch/arm64/net/bpf_jit_comp.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/arm64/net/bpf_jit_comp.c	2016-07-24 15:23:50.000000000 -0400
@@ -31,8 +31,8 @@
 
 int bpf_jit_enable __read_mostly;
 
-#define TMP_REG_1 (MAX_BPF_REG + 0)
-#define TMP_REG_2 (MAX_BPF_REG + 1)
+#define TMP_REG_1 (MAX_BPF_JIT_REG + 0)
+#define TMP_REG_2 (MAX_BPF_JIT_REG + 1)
 
 /* Map BPF registers to A64 registers */
 static const int bpf2a64[] = {
@@ -51,15 +51,16 @@ static const int bpf2a64[] = {
 	[BPF_REG_9] = A64_R(22),
 	/* read-only frame pointer to access stack */
 	[BPF_REG_FP] = A64_R(25),
-	/* temporary register for internal BPF JIT */
-	[TMP_REG_1] = A64_R(23),
-	[TMP_REG_2] = A64_R(24),
+	/* temporary registers for internal BPF JIT */
+	[TMP_REG_1] = A64_R(10),
+	[TMP_REG_2] = A64_R(11),
+	/* temporary register for blinding constants */
+	[BPF_REG_AX] = A64_R(9),
 };
 
 struct jit_ctx {
 	const struct bpf_prog *prog;
 	int idx;
-	int tmp_used;
 	int epilogue_offset;
 	int *offset;
 	u32 *image;
@@ -152,8 +153,6 @@ static void build_prologue(struct jit_ct
 	const u8 r8 = bpf2a64[BPF_REG_8];
 	const u8 r9 = bpf2a64[BPF_REG_9];
 	const u8 fp = bpf2a64[BPF_REG_FP];
-	const u8 tmp1 = bpf2a64[TMP_REG_1];
-	const u8 tmp2 = bpf2a64[TMP_REG_2];
 
 	/*
 	 * BPF prog stack layout
@@ -165,7 +164,7 @@ static void build_prologue(struct jit_ct
 	 *                        | ... | callee saved registers
 	 *                        +-----+
 	 *                        |     | x25/x26
-	 * BPF fp register => -80:+-----+ <= (BPF_FP)
+	 * BPF fp register => -64:+-----+ <= (BPF_FP)
 	 *                        |     |
 	 *                        | ... | BPF prog stack
 	 *                        |     |
@@ -187,8 +186,6 @@ static void build_prologue(struct jit_ct
 	/* Save callee-saved register */
 	emit(A64_PUSH(r6, r7, A64_SP), ctx);
 	emit(A64_PUSH(r8, r9, A64_SP), ctx);
-	if (ctx->tmp_used)
-		emit(A64_PUSH(tmp1, tmp2, A64_SP), ctx);
 
 	/* Save fp (x25) and x26. SP requires 16 bytes alignment */
 	emit(A64_PUSH(fp, A64_R(26), A64_SP), ctx);
@@ -208,8 +205,6 @@ static void build_epilogue(struct jit_ct
 	const u8 r8 = bpf2a64[BPF_REG_8];
 	const u8 r9 = bpf2a64[BPF_REG_9];
 	const u8 fp = bpf2a64[BPF_REG_FP];
-	const u8 tmp1 = bpf2a64[TMP_REG_1];
-	const u8 tmp2 = bpf2a64[TMP_REG_2];
 
 	/* We're done with BPF stack */
 	emit(A64_ADD_I(1, A64_SP, A64_SP, STACK_SIZE), ctx);
@@ -218,8 +213,6 @@ static void build_epilogue(struct jit_ct
 	emit(A64_POP(fp, A64_R(26), A64_SP), ctx);
 
 	/* Restore callee-saved register */
-	if (ctx->tmp_used)
-		emit(A64_POP(tmp1, tmp2, A64_SP), ctx);
 	emit(A64_POP(r8, r9, A64_SP), ctx);
 	emit(A64_POP(r6, r7, A64_SP), ctx);
 
@@ -315,7 +308,6 @@ static int build_insn(const struct bpf_i
 			emit(A64_UDIV(is64, dst, dst, src), ctx);
 			break;
 		case BPF_MOD:
-			ctx->tmp_used = 1;
 			emit(A64_UDIV(is64, tmp, dst, src), ctx);
 			emit(A64_MUL(is64, tmp, tmp, src), ctx);
 			emit(A64_SUB(is64, dst, dst, tmp), ctx);
@@ -388,49 +380,41 @@ emit_bswap_uxt:
 	/* dst = dst OP imm */
 	case BPF_ALU | BPF_ADD | BPF_K:
 	case BPF_ALU64 | BPF_ADD | BPF_K:
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(is64, tmp, imm, ctx);
 		emit(A64_ADD(is64, dst, dst, tmp), ctx);
 		break;
 	case BPF_ALU | BPF_SUB | BPF_K:
 	case BPF_ALU64 | BPF_SUB | BPF_K:
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(is64, tmp, imm, ctx);
 		emit(A64_SUB(is64, dst, dst, tmp), ctx);
 		break;
 	case BPF_ALU | BPF_AND | BPF_K:
 	case BPF_ALU64 | BPF_AND | BPF_K:
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(is64, tmp, imm, ctx);
 		emit(A64_AND(is64, dst, dst, tmp), ctx);
 		break;
 	case BPF_ALU | BPF_OR | BPF_K:
 	case BPF_ALU64 | BPF_OR | BPF_K:
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(is64, tmp, imm, ctx);
 		emit(A64_ORR(is64, dst, dst, tmp), ctx);
 		break;
 	case BPF_ALU | BPF_XOR | BPF_K:
 	case BPF_ALU64 | BPF_XOR | BPF_K:
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(is64, tmp, imm, ctx);
 		emit(A64_EOR(is64, dst, dst, tmp), ctx);
 		break;
 	case BPF_ALU | BPF_MUL | BPF_K:
 	case BPF_ALU64 | BPF_MUL | BPF_K:
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(is64, tmp, imm, ctx);
 		emit(A64_MUL(is64, dst, dst, tmp), ctx);
 		break;
 	case BPF_ALU | BPF_DIV | BPF_K:
 	case BPF_ALU64 | BPF_DIV | BPF_K:
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(is64, tmp, imm, ctx);
 		emit(A64_UDIV(is64, dst, dst, tmp), ctx);
 		break;
 	case BPF_ALU | BPF_MOD | BPF_K:
 	case BPF_ALU64 | BPF_MOD | BPF_K:
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(is64, tmp2, imm, ctx);
 		emit(A64_UDIV(is64, tmp, dst, tmp2), ctx);
 		emit(A64_MUL(is64, tmp, tmp, tmp2), ctx);
@@ -501,12 +485,10 @@ emit_cond_jmp:
 	case BPF_JMP | BPF_JNE | BPF_K:
 	case BPF_JMP | BPF_JSGT | BPF_K:
 	case BPF_JMP | BPF_JSGE | BPF_K:
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(1, tmp, imm, ctx);
 		emit(A64_CMP(1, dst, tmp), ctx);
 		goto emit_cond_jmp;
 	case BPF_JMP | BPF_JSET | BPF_K:
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(1, tmp, imm, ctx);
 		emit(A64_TST(1, dst, tmp), ctx);
 		goto emit_cond_jmp;
@@ -516,7 +498,6 @@ emit_cond_jmp:
 		const u8 r0 = bpf2a64[BPF_REG_0];
 		const u64 func = (u64)__bpf_call_base + imm;
 
-		ctx->tmp_used = 1;
 		emit_a64_mov_i64(tmp, func, ctx);
 		emit(A64_PUSH(A64_FP, A64_LR, A64_SP), ctx);
 		emit(A64_MOV(1, A64_FP, A64_SP), ctx);
@@ -562,7 +543,6 @@ emit_cond_jmp:
 	case BPF_LDX | BPF_MEM | BPF_H:
 	case BPF_LDX | BPF_MEM | BPF_B:
 	case BPF_LDX | BPF_MEM | BPF_DW:
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(1, tmp, off, ctx);
 		switch (BPF_SIZE(code)) {
 		case BPF_W:
@@ -586,7 +566,6 @@ emit_cond_jmp:
 	case BPF_ST | BPF_MEM | BPF_B:
 	case BPF_ST | BPF_MEM | BPF_DW:
 		/* Load imm to a register then store it */
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(1, tmp2, off, ctx);
 		emit_a64_mov_i(1, tmp, imm, ctx);
 		switch (BPF_SIZE(code)) {
@@ -610,7 +589,6 @@ emit_cond_jmp:
 	case BPF_STX | BPF_MEM | BPF_H:
 	case BPF_STX | BPF_MEM | BPF_B:
 	case BPF_STX | BPF_MEM | BPF_DW:
-		ctx->tmp_used = 1;
 		emit_a64_mov_i(1, tmp, off, ctx);
 		switch (BPF_SIZE(code)) {
 		case BPF_W:
@@ -762,31 +740,45 @@ void bpf_jit_compile(struct bpf_prog *pr
 	/* Nothing to do here. We support Internal BPF. */
 }
 
-void bpf_int_jit_compile(struct bpf_prog *prog)
+struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
 {
+	struct bpf_prog *tmp, *orig_prog = prog;
 	struct bpf_binary_header *header;
+	bool tmp_blinded = false;
 	struct jit_ctx ctx;
 	int image_size;
 	u8 *image_ptr;
 
 	if (!bpf_jit_enable)
-		return;
+		return orig_prog;
 
-	if (!prog || !prog->len)
-		return;
+	tmp = bpf_jit_blind_constants(prog);
+	/* If blinding was requested and we failed during blinding,
+	 * we must fall back to the interpreter.
+	 */
+	if (IS_ERR(tmp))
+		return orig_prog;
+	if (tmp != prog) {
+		tmp_blinded = true;
+		prog = tmp;
+	}
 
 	memset(&ctx, 0, sizeof(ctx));
 	ctx.prog = prog;
 
 	ctx.offset = kcalloc(prog->len, sizeof(int), GFP_KERNEL);
-	if (ctx.offset == NULL)
-		return;
+	if (ctx.offset == NULL) {
+		prog = orig_prog;
+		goto out;
+	}
 
 	/* 1. Initial fake pass to compute ctx->idx. */
 
-	/* Fake pass to fill in ctx->offset and ctx->tmp_used. */
-	if (build_body(&ctx))
-		goto out;
+	/* Fake pass to fill in ctx->offset. */
+	if (build_body(&ctx)) {
+		prog = orig_prog;
+		goto out_off;
+	}
 
 	build_prologue(&ctx);
 
@@ -797,8 +789,10 @@ void bpf_int_jit_compile(struct bpf_prog
 	image_size = sizeof(u32) * ctx.idx;
 	header = bpf_jit_binary_alloc(image_size, &image_ptr,
 				      sizeof(u32), jit_fill_hole);
-	if (header == NULL)
-		goto out;
+	if (header == NULL) {
+		prog = orig_prog;
+		goto out_off;
+	}
 
 	/* 2. Now, the actual pass. */
 
@@ -809,7 +803,8 @@ void bpf_int_jit_compile(struct bpf_prog
 
 	if (build_body(&ctx)) {
 		bpf_jit_binary_free(header);
-		goto out;
+		prog = orig_prog;
+		goto out_off;
 	}
 
 	build_epilogue(&ctx);
@@ -817,7 +812,8 @@ void bpf_int_jit_compile(struct bpf_prog
 	/* 3. Extra pass to validate JITed code. */
 	if (validate_code(&ctx)) {
 		bpf_jit_binary_free(header);
-		goto out;
+		prog = orig_prog;
+		goto out_off;
 	}
 
 	/* And we're done. */
@@ -829,8 +825,14 @@ void bpf_int_jit_compile(struct bpf_prog
 	set_memory_ro((unsigned long)header, header->pages);
 	prog->bpf_func = (void *)ctx.image;
 	prog->jited = 1;
-out:
+
+out_off:
 	kfree(ctx.offset);
+out:
+	if (tmp_blinded)
+		bpf_jit_prog_release_other(prog, prog == orig_prog ?
+					   tmp : orig_prog);
+	return prog;
 }
 
 void bpf_jit_free(struct bpf_prog *prog)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/avr32/include/asm/addrspace.h linux-libre-4.7-gnu/arch/avr32/include/asm/addrspace.h
--- linux-libre-4.6-gnu/arch/avr32/include/asm/addrspace.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/avr32/include/asm/addrspace.h	2016-07-24 15:23:50.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Defitions for the address spaces of the AVR32 CPUs. Heavily based on
+ * Definitions for the address spaces of the AVR32 CPUs. Heavily based on
  * include/asm-sh/addrspace.h
  *
  * Copyright (C) 2004-2006 Atmel Corporation
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/avr32/include/asm/pgalloc.h linux-libre-4.7-gnu/arch/avr32/include/asm/pgalloc.h
--- linux-libre-4.6-gnu/arch/avr32/include/asm/pgalloc.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/avr32/include/asm/pgalloc.h	2016-07-24 15:23:50.000000000 -0400
@@ -43,7 +43,7 @@ static inline void pgd_ctor(void *x)
  */
 static inline pgd_t *pgd_alloc(struct mm_struct *mm)
 {
-	return quicklist_alloc(QUICK_PGD, GFP_KERNEL | __GFP_REPEAT, pgd_ctor);
+	return quicklist_alloc(QUICK_PGD, GFP_KERNEL, pgd_ctor);
 }
 
 static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
@@ -54,7 +54,7 @@ static inline void pgd_free(struct mm_st
 static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
 					  unsigned long address)
 {
-	return quicklist_alloc(QUICK_PT, GFP_KERNEL | __GFP_REPEAT, NULL);
+	return quicklist_alloc(QUICK_PT, GFP_KERNEL, NULL);
 }
 
 static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
@@ -63,7 +63,7 @@ static inline pgtable_t pte_alloc_one(st
 	struct page *page;
 	void *pg;
 
-	pg = quicklist_alloc(QUICK_PT, GFP_KERNEL | __GFP_REPEAT, NULL);
+	pg = quicklist_alloc(QUICK_PT, GFP_KERNEL, NULL);
 	if (!pg)
 		return NULL;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/avr32/Kconfig linux-libre-4.7-gnu/arch/avr32/Kconfig
--- linux-libre-4.6-gnu/arch/avr32/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/avr32/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -4,6 +4,7 @@ config AVR32
 	# that we usually don't need on AVR32.
 	select EXPERT
 	select HAVE_CLK
+	select HAVE_EXIT_THREAD
 	select HAVE_OPROFILE
 	select HAVE_KPROBES
 	select VIRT_TO_BUS
@@ -17,6 +18,7 @@ config AVR32
 	select GENERIC_CLOCKEVENTS
 	select HAVE_MOD_ARCH_SPECIFIC
 	select MODULES_USE_ELF_RELA
+	select HAVE_NMI
 	help
 	  AVR32 is a high-performance 32-bit RISC microprocessor core,
 	  designed for cost-sensitive embedded applications, with particular
@@ -74,7 +76,7 @@ config PLATFORM_AT32AP
 	select SUBARCH_AVR32B
 	select MMU
 	select PERFORMANCE_COUNTERS
-	select ARCH_REQUIRE_GPIOLIB
+	select GPIOLIB
 	select GENERIC_ALLOCATOR
 	select HAVE_FB_ATMEL
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/avr32/kernel/process.c linux-libre-4.7-gnu/arch/avr32/kernel/process.c
--- linux-libre-4.6-gnu/arch/avr32/kernel/process.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/avr32/kernel/process.c	2016-07-24 15:23:50.000000000 -0400
@@ -62,9 +62,9 @@ void machine_restart(char *cmd)
 /*
  * Free current thread data structures etc
  */
-void exit_thread(void)
+void exit_thread(struct task_struct *tsk)
 {
-	ocd_disable(current);
+	ocd_disable(tsk);
 }
 
 void flush_thread(void)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/avr32/mach-at32ap/at32ap700x.c linux-libre-4.7-gnu/arch/avr32/mach-at32ap/at32ap700x.c
--- linux-libre-4.6-gnu/arch/avr32/mach-at32ap/at32ap700x.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/avr32/mach-at32ap/at32ap700x.c	2016-07-24 15:23:50.000000000 -0400
@@ -1365,8 +1365,8 @@ at32_add_device_mci(unsigned int id, str
 	slave->dma_dev = &dw_dmac0_device.dev;
 	slave->src_id = 0;
 	slave->dst_id = 1;
-	slave->src_master = 1;
-	slave->dst_master = 0;
+	slave->m_master = 1;
+	slave->p_master = 0;
 
 	data->dma_slave = slave;
 	data->dma_filter = at32_mci_dma_filter;
@@ -2061,16 +2061,16 @@ at32_add_device_ac97c(unsigned int id, s
 	if (flags & AC97C_CAPTURE) {
 		rx_dws->dma_dev = &dw_dmac0_device.dev;
 		rx_dws->src_id = 3;
-		rx_dws->src_master = 0;
-		rx_dws->dst_master = 1;
+		rx_dws->m_master = 0;
+		rx_dws->p_master = 1;
 	}
 
 	/* Check if DMA slave interface for playback should be configured. */
 	if (flags & AC97C_PLAYBACK) {
 		tx_dws->dma_dev = &dw_dmac0_device.dev;
 		tx_dws->dst_id = 4;
-		tx_dws->src_master = 0;
-		tx_dws->dst_master = 1;
+		tx_dws->m_master = 0;
+		tx_dws->p_master = 1;
 	}
 
 	if (platform_device_add_data(pdev, data,
@@ -2141,8 +2141,8 @@ at32_add_device_abdac(unsigned int id, s
 
 	dws->dma_dev = &dw_dmac0_device.dev;
 	dws->dst_id = 2;
-	dws->src_master = 0;
-	dws->dst_master = 1;
+	dws->m_master = 0;
+	dws->p_master = 1;
 
 	if (platform_device_add_data(pdev, data,
 				sizeof(struct atmel_abdac_pdata)))
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/blackfin/include/asm/processor.h linux-libre-4.7-gnu/arch/blackfin/include/asm/processor.h
--- linux-libre-4.6-gnu/arch/blackfin/include/asm/processor.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/blackfin/include/asm/processor.h	2016-07-24 15:23:50.000000000 -0400
@@ -76,13 +76,6 @@ static inline void release_thread(struct
 }
 
 /*
- * Free current thread data structures etc..
- */
-static inline void exit_thread(void)
-{
-}
-
-/*
  * Return saved PC of a blocked thread.
  */
 #define thread_saved_pc(tsk)	(tsk->thread.pc)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/blackfin/Kconfig linux-libre-4.7-gnu/arch/blackfin/Kconfig
--- linux-libre-4.6-gnu/arch/blackfin/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/blackfin/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -40,6 +40,7 @@ config BLACKFIN
 	select HAVE_MOD_ARCH_SPECIFIC
 	select MODULES_USE_ELF_RELA
 	select HAVE_DEBUG_STACKOVERFLOW
+	select HAVE_NMI
 
 config GENERIC_CSUM
 	def_bool y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/blackfin/lib/udivsi3.S linux-libre-4.7-gnu/arch/blackfin/lib/udivsi3.S
--- linux-libre-4.6-gnu/arch/blackfin/lib/udivsi3.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/blackfin/lib/udivsi3.S	2016-07-24 15:23:50.000000000 -0400
@@ -154,7 +154,7 @@ ENTRY(___udivsi3)
        CC = R7 < 0;               /* Check quotient(AQ) */
                                   /* If AQ==0, we'll sub divisor */
        IF CC R5 = R1;             /* and if AQ==1, we'll add it. */
-       R3 = R3 + R5;              /* Add/sub divsor to partial remainder */
+       R3 = R3 + R5;              /* Add/sub divisor to partial remainder */
        R7 = R3 ^ R1;              /* Generate next quotient bit */
 
        R5 = R7 >> 31;             /* Get AQ */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/blackfin/mach-bf609/include/mach/defBF60x_base.h linux-libre-4.7-gnu/arch/blackfin/mach-bf609/include/mach/defBF60x_base.h
--- linux-libre-4.6-gnu/arch/blackfin/mach-bf609/include/mach/defBF60x_base.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/blackfin/mach-bf609/include/mach/defBF60x_base.h	2016-07-24 15:23:50.000000000 -0400
@@ -2689,7 +2689,7 @@
 #define L2CTL0_STAT                 0xFFCA3010         /* L2CTL0 L2 Status Register */
 #define L2CTL0_RPCR                 0xFFCA3014         /* L2CTL0 L2 Read Priority Count Register */
 #define L2CTL0_WPCR                 0xFFCA3018         /* L2CTL0 L2 Write Priority Count Register */
-#define L2CTL0_RFA                  0xFFCA3024         /* L2CTL0 L2 Refresh Address Regsiter */
+#define L2CTL0_RFA                  0xFFCA3024         /* L2CTL0 L2 Refresh Address Register */
 #define L2CTL0_ERRADDR0             0xFFCA3040         /* L2CTL0 L2 Bank 0 ECC Error Address Register */
 #define L2CTL0_ERRADDR1             0xFFCA3044         /* L2CTL0 L2 Bank 1 ECC Error Address Register */
 #define L2CTL0_ERRADDR2             0xFFCA3048         /* L2CTL0 L2 Bank 2 ECC Error Address Register */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/c6x/include/asm/clock.h linux-libre-4.7-gnu/arch/c6x/include/asm/clock.h
--- linux-libre-4.6-gnu/arch/c6x/include/asm/clock.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/c6x/include/asm/clock.h	2016-07-24 15:23:50.000000000 -0400
@@ -101,7 +101,7 @@ struct clk {
 #define CLK_PLL			BIT(2) /* PLL-derived clock */
 #define PRE_PLL			BIT(3) /* source is before PLL mult/div */
 #define FIXED_DIV_PLL		BIT(4) /* fixed divisor from PLL */
-#define FIXED_RATE_PLL		BIT(5) /* fixed ouput rate PLL */
+#define FIXED_RATE_PLL		BIT(5) /* fixed output rate PLL */
 
 #define MAX_PLL_SYSCLKS 16
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/c6x/include/uapi/asm/unistd.h linux-libre-4.7-gnu/arch/c6x/include/uapi/asm/unistd.h
--- linux-libre-4.6-gnu/arch/c6x/include/uapi/asm/unistd.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/c6x/include/uapi/asm/unistd.h	2016-07-24 15:23:50.000000000 -0400
@@ -14,6 +14,7 @@
  *   more details.
  */
 
+#define __ARCH_WANT_RENAMEAT
 #define __ARCH_WANT_SYS_CLONE
 
 /* Use the standard ABI for syscalls. */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/c6x/kernel/process.c linux-libre-4.7-gnu/arch/c6x/kernel/process.c
--- linux-libre-4.6-gnu/arch/c6x/kernel/process.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/c6x/kernel/process.c	2016-07-24 15:23:50.000000000 -0400
@@ -82,10 +82,6 @@ void flush_thread(void)
 {
 }
 
-void exit_thread(void)
-{
-}
-
 /*
  * Do necessary setup to start up a newly executed thread.
  */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/c6x/platforms/cache.c linux-libre-4.7-gnu/arch/c6x/platforms/cache.c
--- linux-libre-4.6-gnu/arch/c6x/platforms/cache.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/c6x/platforms/cache.c	2016-07-24 15:23:50.000000000 -0400
@@ -145,7 +145,7 @@ loop:
 		spin_lock_irqsave(&cache_lock, flags);
 
 		/*
-		 * If another cache operation is occuring
+		 * If another cache operation is occurring
 		 */
 		if (unlikely(imcr_get(wc_reg))) {
 			spin_unlock_irqrestore(&cache_lock, flags);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/cris/arch-v10/drivers/axisflashmap.c linux-libre-4.7-gnu/arch/cris/arch-v10/drivers/axisflashmap.c
--- linux-libre-4.6-gnu/arch/cris/arch-v10/drivers/axisflashmap.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/cris/arch-v10/drivers/axisflashmap.c	2016-07-24 15:23:50.000000000 -0400
@@ -212,7 +212,7 @@ static struct mtd_info *probe_cs(struct
 /*
  * Probe each chip select individually for flash chips. If there are chips on
  * both cse0 and cse1, the mtd_info structs will be concatenated to one struct
- * so that MTD partitions can cross chip boundries.
+ * so that MTD partitions can cross chip boundaries.
  *
  * The only known restriction to how you can mount your chips is that each
  * chip select must hold similar flash chips. But you need external hardware
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/cris/arch-v10/kernel/process.c linux-libre-4.7-gnu/arch/cris/arch-v10/kernel/process.c
--- linux-libre-4.6-gnu/arch/cris/arch-v10/kernel/process.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/cris/arch-v10/kernel/process.c	2016-07-24 15:23:50.000000000 -0400
@@ -35,15 +35,6 @@ void default_idle(void)
 	local_irq_enable();
 }
 
-/*
- * Free current thread data structures etc..
- */
-
-void exit_thread(void)
-{
-	/* Nothing needs to be done.  */
-}
-
 /* if the watchdog is enabled, we can simply disable interrupts and go
  * into an eternal loop, and the watchdog will reset the CPU after 0.1s
  * if on the other hand the watchdog wasn't enabled, we just enable it and wait
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/cris/arch-v32/drivers/axisflashmap.c linux-libre-4.7-gnu/arch/cris/arch-v32/drivers/axisflashmap.c
--- linux-libre-4.6-gnu/arch/cris/arch-v32/drivers/axisflashmap.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/cris/arch-v32/drivers/axisflashmap.c	2016-07-24 15:23:50.000000000 -0400
@@ -246,7 +246,7 @@ static struct mtd_info *probe_cs(struct
 /*
  * Probe each chip select individually for flash chips. If there are chips on
  * both cse0 and cse1, the mtd_info structs will be concatenated to one struct
- * so that MTD partitions can cross chip boundries.
+ * so that MTD partitions can cross chip boundaries.
  *
  * The only known restriction to how you can mount your chips is that each
  * chip select must hold similar flash chips. But you need external hardware
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/cris/arch-v32/drivers/cryptocop.c linux-libre-4.7-gnu/arch/cris/arch-v32/drivers/cryptocop.c
--- linux-libre-4.6-gnu/arch/cris/arch-v32/drivers/cryptocop.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/cris/arch-v32/drivers/cryptocop.c	2016-07-24 15:23:50.000000000 -0400
@@ -525,7 +525,7 @@ static int setup_cipher_iv_desc(struct c
 	return 0;
 }
 
-/* Map the ouput length of the transform to operation output starting on the inject index. */
+/* Map the output length of the transform to operation output starting on the inject index. */
 static int create_input_descriptors(struct cryptocop_operation *operation, struct cryptocop_tfrm_ctx *tc, struct cryptocop_dma_desc **id, int alloc_flag)
 {
 	int                        err = 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/cris/arch-v32/drivers/mach-a3/nandflash.c linux-libre-4.7-gnu/arch/cris/arch-v32/drivers/mach-a3/nandflash.c
--- linux-libre-4.6-gnu/arch/cris/arch-v32/drivers/mach-a3/nandflash.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/cris/arch-v32/drivers/mach-a3/nandflash.c	2016-07-24 15:23:50.000000000 -0400
@@ -157,6 +157,7 @@ struct mtd_info *__init crisv32_nand_fla
 	/* 20 us command delay time */
 	this->chip_delay = 20;
 	this->ecc.mode = NAND_ECC_SOFT;
+	this->ecc.algo = NAND_ECC_HAMMING;
 
 	/* Enable the following for a flash based bad block table */
 	/* this->bbt_options = NAND_BBT_USE_FLASH; */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/cris/arch-v32/drivers/mach-fs/nandflash.c linux-libre-4.7-gnu/arch/cris/arch-v32/drivers/mach-fs/nandflash.c
--- linux-libre-4.6-gnu/arch/cris/arch-v32/drivers/mach-fs/nandflash.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/cris/arch-v32/drivers/mach-fs/nandflash.c	2016-07-24 15:23:50.000000000 -0400
@@ -148,6 +148,7 @@ struct mtd_info *__init crisv32_nand_fla
 	/* 20 us command delay time */
 	this->chip_delay = 20;
 	this->ecc.mode = NAND_ECC_SOFT;
+	this->ecc.algo = NAND_ECC_HAMMING;
 
 	/* Enable the following for a flash based bad block table */
 	/* this->bbt_options = NAND_BBT_USE_FLASH; */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/cris/arch-v32/kernel/process.c linux-libre-4.7-gnu/arch/cris/arch-v32/kernel/process.c
--- linux-libre-4.6-gnu/arch/cris/arch-v32/kernel/process.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/cris/arch-v32/kernel/process.c	2016-07-24 15:23:50.000000000 -0400
@@ -33,9 +33,9 @@ void default_idle(void)
  */
 
 extern void deconfigure_bp(long pid);
-void exit_thread(void)
+void exit_thread(struct task_struct *tsk)
 {
-	deconfigure_bp(current->pid);
+	deconfigure_bp(tsk->pid);
 }
 
 /*
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/cris/arch-v32/mach-a3/dram_init.S linux-libre-4.7-gnu/arch/cris/arch-v32/mach-a3/dram_init.S
--- linux-libre-4.6-gnu/arch/cris/arch-v32/mach-a3/dram_init.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/cris/arch-v32/mach-a3/dram_init.S	2016-07-24 15:23:50.000000000 -0400
@@ -11,7 +11,7 @@
  */
 
 /* Just to be certain the config file is included, we include it here
- * explicitely instead of depending on it being included in the file that
+ * explicitly instead of depending on it being included in the file that
  * uses this code.
  */
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/cris/arch-v32/mach-fs/dram_init.S linux-libre-4.7-gnu/arch/cris/arch-v32/mach-fs/dram_init.S
--- linux-libre-4.6-gnu/arch/cris/arch-v32/mach-fs/dram_init.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/cris/arch-v32/mach-fs/dram_init.S	2016-07-24 15:23:50.000000000 -0400
@@ -11,7 +11,7 @@
  */
 
 /* Just to be certain the config file is included, we include it here
- * explicitely instead of depending on it being included in the file that
+ * explicitly instead of depending on it being included in the file that
  * uses this code.
  */
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/cris/include/asm/pgalloc.h linux-libre-4.7-gnu/arch/cris/include/asm/pgalloc.h
--- linux-libre-4.6-gnu/arch/cris/include/asm/pgalloc.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/cris/include/asm/pgalloc.h	2016-07-24 15:23:50.000000000 -0400
@@ -24,14 +24,14 @@ static inline void pgd_free(struct mm_st
 
 static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
 {
-  	pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
+	pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_ZERO);
  	return pte;
 }
 
 static inline pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
 {
 	struct page *pte;
-	pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
+	pte = alloc_pages(GFP_KERNEL|__GFP_ZERO, 0);
 	if (!pte)
 		return NULL;
 	if (!pgtable_page_ctor(pte)) {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/cris/Kconfig linux-libre-4.7-gnu/arch/cris/Kconfig
--- linux-libre-4.6-gnu/arch/cris/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/cris/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -59,9 +59,10 @@ config CRIS
 	select GENERIC_IOMAP
 	select MODULES_USE_ELF_RELA
 	select CLONE_BACKWARDS2
+	select HAVE_EXIT_THREAD if ETRAX_ARCH_V32
 	select OLD_SIGSUSPEND
 	select OLD_SIGACTION
-	select ARCH_REQUIRE_GPIOLIB
+	select GPIOLIB
 	select IRQ_DOMAIN if ETRAX_ARCH_V32
 	select OF if ETRAX_ARCH_V32
 	select OF_EARLY_FLATTREE if ETRAX_ARCH_V32
@@ -69,6 +70,7 @@ config CRIS
 	select GENERIC_CLOCKEVENTS if ETRAX_ARCH_V32
 	select GENERIC_SCHED_CLOCK if ETRAX_ARCH_V32
 	select HAVE_DEBUG_BUGVERBOSE if ETRAX_ARCH_V32
+	select HAVE_NMI
 
 config HZ
 	int
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/frv/include/asm/processor.h linux-libre-4.7-gnu/arch/frv/include/asm/processor.h
--- linux-libre-4.6-gnu/arch/frv/include/asm/processor.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/frv/include/asm/processor.h	2016-07-24 15:23:50.000000000 -0400
@@ -97,13 +97,6 @@ extern asmlinkage void *restore_user_reg
 #define forget_segments()		do { } while (0)
 
 /*
- * Free current thread data structures etc..
- */
-static inline void exit_thread(void)
-{
-}
-
-/*
  * Return saved PC of a blocked thread.
  */
 extern unsigned long thread_saved_pc(struct task_struct *tsk);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/frv/mm/pgalloc.c linux-libre-4.7-gnu/arch/frv/mm/pgalloc.c
--- linux-libre-4.6-gnu/arch/frv/mm/pgalloc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/frv/mm/pgalloc.c	2016-07-24 15:23:50.000000000 -0400
@@ -22,7 +22,7 @@ pgd_t swapper_pg_dir[PTRS_PER_PGD] __att
 
 pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
 {
-	pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT);
+	pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL);
 	if (pte)
 		clear_page(pte);
 	return pte;
@@ -33,9 +33,9 @@ pgtable_t pte_alloc_one(struct mm_struct
 	struct page *page;
 
 #ifdef CONFIG_HIGHPTE
-	page = alloc_pages(GFP_KERNEL|__GFP_HIGHMEM|__GFP_REPEAT, 0);
+	page = alloc_pages(GFP_KERNEL|__GFP_HIGHMEM, 0);
 #else
-	page = alloc_pages(GFP_KERNEL|__GFP_REPEAT, 0);
+	page = alloc_pages(GFP_KERNEL, 0);
 #endif
 	if (!page)
 		return NULL;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/h8300/boot/compressed/Makefile linux-libre-4.7-gnu/arch/h8300/boot/compressed/Makefile
--- linux-libre-4.6-gnu/arch/h8300/boot/compressed/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/h8300/boot/compressed/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -23,7 +23,6 @@ LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET
 
 $(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o $(LIBGCC) FORCE
 	$(call if_changed,ld)
-	@:
 
 $(obj)/vmlinux.bin: vmlinux FORCE
 	$(call if_changed,objcopy)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/h8300/include/asm/hash.h linux-libre-4.7-gnu/arch/h8300/include/asm/hash.h
--- linux-libre-4.6-gnu/arch/h8300/include/asm/hash.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/h8300/include/asm/hash.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,53 @@
+#ifndef _ASM_HASH_H
+#define _ASM_HASH_H
+
+/*
+ * The later H8SX models have a 32x32-bit multiply, but the H8/300H
+ * and H8S have only 16x16->32.  Since it's tolerably compact, this is
+ * basically an inlined version of the __mulsi3 code.  Since the inputs
+ * are not expected to be small, it's also simplfied by skipping the
+ * early-out checks.
+ *
+ * (Since neither CPU has any multi-bit shift instructions, a
+ * shift-and-add version is a non-starter.)
+ *
+ * TODO: come up with an arch-specific version of the hashing in fs/namei.c,
+ * since that is heavily dependent on rotates.  Which, as mentioned, suck
+ * horribly on H8.
+ */
+
+#if defined(CONFIG_CPU_H300H) || defined(CONFIG_CPU_H8S)
+
+#define HAVE_ARCH__HASH_32 1
+
+/*
+ * Multiply by k = 0x61C88647.  Fitting this into three registers requires
+ * one extra instruction, but reducing register pressure will probably
+ * make that back and then some.
+ *
+ * GCC asm note: %e1 is the high half of operand %1, while %f1 is the
+ * low half.  So if %1 is er4, then %e1 is e4 and %f1 is r4.
+ *
+ * This has been designed to modify x in place, since that's the most
+ * common usage, but preserve k, since hash_64() makes two calls in
+ * quick succession.
+ */
+static inline u32 __attribute_const__ __hash_32(u32 x)
+{
+	u32 temp;
+
+	asm(   "mov.w	%e1,%f0"
+	"\n	mulxu.w	%f2,%0"		/* klow * xhigh */
+	"\n	mov.w	%f0,%e1"	/* The extra instruction */
+	"\n	mov.w	%f1,%f0"
+	"\n	mulxu.w	%e2,%0"		/* khigh * xlow */
+	"\n	add.w	%e1,%f0"
+	"\n	mulxu.w	%f2,%1"		/* klow * xlow */
+	"\n	add.w	%f0,%e1"
+	: "=&r" (temp), "=r" (x)
+	: "%r" (GOLDEN_RATIO_32), "1" (x));
+	return x;
+}
+
+#endif
+#endif /* _ASM_HASH_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/h8300/include/asm/processor.h linux-libre-4.7-gnu/arch/h8300/include/asm/processor.h
--- linux-libre-4.6-gnu/arch/h8300/include/asm/processor.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/h8300/include/asm/processor.h	2016-07-24 15:23:50.000000000 -0400
@@ -111,13 +111,6 @@ static inline void release_thread(struct
 }
 
 /*
- * Free current thread data structures etc..
- */
-static inline void exit_thread(void)
-{
-}
-
-/*
  * Return saved PC of a blocked thread.
  */
 unsigned long thread_saved_pc(struct task_struct *tsk);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/h8300/include/uapi/asm/unistd.h linux-libre-4.7-gnu/arch/h8300/include/uapi/asm/unistd.h
--- linux-libre-4.6-gnu/arch/h8300/include/uapi/asm/unistd.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/h8300/include/uapi/asm/unistd.h	2016-07-24 15:23:50.000000000 -0400
@@ -1,3 +1,5 @@
 #define __ARCH_NOMMU
 
+#define __ARCH_WANT_RENAMEAT
+
 #include <asm-generic/unistd.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/h8300/Kconfig linux-libre-4.7-gnu/arch/h8300/Kconfig
--- linux-libre-4.6-gnu/arch/h8300/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/h8300/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -20,6 +20,8 @@ config H8300
 	select HAVE_KERNEL_GZIP
 	select HAVE_KERNEL_LZO
 	select HAVE_ARCH_KGDB
+	select HAVE_ARCH_HASH
+	select CPU_NO_EFFICIENT_FFS
 
 config RWSEM_GENERIC_SPINLOCK
 	def_bool y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/hexagon/include/asm/hexagon_vm.h linux-libre-4.7-gnu/arch/hexagon/include/asm/hexagon_vm.h
--- linux-libre-4.6-gnu/arch/hexagon/include/asm/hexagon_vm.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/hexagon/include/asm/hexagon_vm.h	2016-07-24 15:23:50.000000000 -0400
@@ -237,7 +237,7 @@ static inline long __vmintop_clear(long
 
 /*
  * The initial program gets to find a system environment descriptor
- * on its stack when it begins exection. The first word is a version
+ * on its stack when it begins execution. The first word is a version
  * code to indicate what is there.  Zero means nothing more.
  */
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/hexagon/include/asm/pgalloc.h linux-libre-4.7-gnu/arch/hexagon/include/asm/pgalloc.h
--- linux-libre-4.6-gnu/arch/hexagon/include/asm/pgalloc.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/hexagon/include/asm/pgalloc.h	2016-07-24 15:23:50.000000000 -0400
@@ -64,7 +64,7 @@ static inline struct page *pte_alloc_one
 {
 	struct page *pte;
 
-	pte = alloc_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO);
+	pte = alloc_page(GFP_KERNEL | __GFP_ZERO);
 	if (!pte)
 		return NULL;
 	if (!pgtable_page_ctor(pte)) {
@@ -78,7 +78,7 @@ static inline struct page *pte_alloc_one
 static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
 					  unsigned long address)
 {
-	gfp_t flags =  GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO;
+	gfp_t flags =  GFP_KERNEL | __GFP_ZERO;
 	return (pte_t *) __get_free_page(flags);
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/hexagon/include/asm/vm_mmu.h linux-libre-4.7-gnu/arch/hexagon/include/asm/vm_mmu.h
--- linux-libre-4.6-gnu/arch/hexagon/include/asm/vm_mmu.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/hexagon/include/asm/vm_mmu.h	2016-07-24 15:23:50.000000000 -0400
@@ -78,7 +78,7 @@
 #define	__HEXAGON_C_WB_L2	0x7	/* Write-back, with L2 */
 
 /*
- * This can be overriden, but we're defaulting to the most aggressive
+ * This can be overridden, but we're defaulting to the most aggressive
  * cache policy, the better to find bugs sooner.
  */
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/hexagon/include/uapi/asm/unistd.h linux-libre-4.7-gnu/arch/hexagon/include/uapi/asm/unistd.h
--- linux-libre-4.6-gnu/arch/hexagon/include/uapi/asm/unistd.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/hexagon/include/uapi/asm/unistd.h	2016-07-24 15:23:50.000000000 -0400
@@ -27,6 +27,7 @@
  */
 
 #define sys_mmap2 sys_mmap_pgoff
+#define __ARCH_WANT_RENAMEAT
 #define __ARCH_WANT_SYS_EXECVE
 #define __ARCH_WANT_SYS_CLONE
 #define __ARCH_WANT_SYS_VFORK
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/hexagon/kernel/kgdb.c linux-libre-4.7-gnu/arch/hexagon/kernel/kgdb.c
--- linux-libre-4.6-gnu/arch/hexagon/kernel/kgdb.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/hexagon/kernel/kgdb.c	2016-07-24 15:23:50.000000000 -0400
@@ -236,9 +236,9 @@ static struct notifier_block kgdb_notifi
 };
 
 /**
- * kgdb_arch_init - Perform any architecture specific initalization.
+ * kgdb_arch_init - Perform any architecture specific initialization.
  *
- * This function will handle the initalization of any architecture
+ * This function will handle the initialization of any architecture
  * specific callbacks.
  */
 int kgdb_arch_init(void)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/hexagon/kernel/process.c linux-libre-4.7-gnu/arch/hexagon/kernel/process.c
--- linux-libre-4.6-gnu/arch/hexagon/kernel/process.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/hexagon/kernel/process.c	2016-07-24 15:23:50.000000000 -0400
@@ -137,13 +137,6 @@ void release_thread(struct task_struct *
 }
 
 /*
- * Free any architecture-specific thread data structures, etc.
- */
-void exit_thread(void)
-{
-}
-
-/*
  * Some archs flush debug and FPU info here
  */
 void flush_thread(void)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/hexagon/kernel/vdso.c linux-libre-4.7-gnu/arch/hexagon/kernel/vdso.c
--- linux-libre-4.6-gnu/arch/hexagon/kernel/vdso.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/hexagon/kernel/vdso.c	2016-07-24 15:23:50.000000000 -0400
@@ -65,7 +65,8 @@ int arch_setup_additional_pages(struct l
 	unsigned long vdso_base;
 	struct mm_struct *mm = current->mm;
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
 
 	/* Try to get it loaded right near ld.so/glibc. */
 	vdso_base = STACK_TOP;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/hexagon/kernel/vm_ops.S linux-libre-4.7-gnu/arch/hexagon/kernel/vm_ops.S
--- linux-libre-4.6-gnu/arch/hexagon/kernel/vm_ops.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/hexagon/kernel/vm_ops.S	2016-07-24 15:23:50.000000000 -0400
@@ -26,7 +26,7 @@
  * could be, and perhaps some day will be, handled as in-line
  * macros, but for tracing/debugging it's handy to have
  * a single point of invocation for each of them.
- * Conveniently, they take paramters and return values
+ * Conveniently, they take parameters and return values
  * consistent with the ABI calling convention.
  */
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/hexagon/lib/memcpy.S linux-libre-4.7-gnu/arch/hexagon/lib/memcpy.S
--- linux-libre-4.6-gnu/arch/hexagon/lib/memcpy.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/hexagon/lib/memcpy.S	2016-07-24 15:23:50.000000000 -0400
@@ -39,7 +39,7 @@
  *   DJH 10/14/09 Version 1.3 added special loop for aligned case, was
  *                            overreading bloated codesize back up to 892
  *   DJH  4/20/10 Version 1.4 fixed Ldword_loop_epilog loop to prevent loads
- *                            occuring if only 1 left outstanding, fixes bug
+ *                            occurring if only 1 left outstanding, fixes bug
  *                            # 3888, corrected for all alignments. Peeled off
  *                            1 32byte chunk from kernel loop and extended 8byte
  *                            loop at end to solve all combinations and prevent
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/ia64/hp/sim/simserial.c linux-libre-4.7-gnu/arch/ia64/hp/sim/simserial.c
--- linux-libre-4.6-gnu/arch/ia64/hp/sim/simserial.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/ia64/hp/sim/simserial.c	2016-07-24 15:23:50.000000000 -0400
@@ -300,7 +300,7 @@ static int rs_ioctl(struct tty_struct *t
 	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
 	    (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
 	    (cmd != TIOCMIWAIT)) {
-		if (tty->flags & (1 << TTY_IO_ERROR))
+		if (tty_io_error(tty))
 		    return -EIO;
 	}
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/ia64/include/asm/iommu.h linux-libre-4.7-gnu/arch/ia64/include/asm/iommu.h
--- linux-libre-4.6-gnu/arch/ia64/include/asm/iommu.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/ia64/include/asm/iommu.h	2016-07-24 15:23:50.000000000 -0400
@@ -1,7 +1,6 @@
 #ifndef _ASM_IA64_IOMMU_H
 #define _ASM_IA64_IOMMU_H 1
 
-#define cpu_has_x2apic 0
 /* 10 seconds */
 #define DMAR_OPERATION_TIMEOUT (((cycles_t) local_cpu_data->itc_freq)*10)
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/ia64/include/asm/rwsem.h linux-libre-4.7-gnu/arch/ia64/include/asm/rwsem.h
--- linux-libre-4.6-gnu/arch/ia64/include/asm/rwsem.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/ia64/include/asm/rwsem.h	2016-07-24 15:23:50.000000000 -0400
@@ -49,8 +49,8 @@ __down_read (struct rw_semaphore *sem)
 /*
  * lock for writing
  */
-static inline void
-__down_write (struct rw_semaphore *sem)
+static inline long
+___down_write (struct rw_semaphore *sem)
 {
 	long old, new;
 
@@ -59,10 +59,26 @@ __down_write (struct rw_semaphore *sem)
 		new = old + RWSEM_ACTIVE_WRITE_BIAS;
 	} while (cmpxchg_acq(&sem->count, old, new) != old);
 
-	if (old != 0)
+	return old;
+}
+
+static inline void
+__down_write (struct rw_semaphore *sem)
+{
+	if (___down_write(sem))
 		rwsem_down_write_failed(sem);
 }
 
+static inline int
+__down_write_killable (struct rw_semaphore *sem)
+{
+	if (___down_write(sem))
+		if (IS_ERR(rwsem_down_write_failed_killable(sem)))
+			return -EINTR;
+
+	return 0;
+}
+
 /*
  * unlock after reading
  */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/ia64/include/asm/sn/ioc3.h linux-libre-4.7-gnu/arch/ia64/include/asm/sn/ioc3.h
--- linux-libre-4.6-gnu/arch/ia64/include/asm/sn/ioc3.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/ia64/include/asm/sn/ioc3.h	2016-07-24 15:23:50.000000000 -0400
@@ -131,7 +131,7 @@ struct ioc3 {
 #define SSCR_PAUSE_STATE	0x40000000	/* set when PAUSE takes effect*/
 #define SSCR_RESET		0x80000000	/* reset DMA channels */
 
-/* all producer/comsumer pointers are the same bitfield */
+/* all producer/consumer pointers are the same bitfield */
 #define PROD_CONS_PTR_4K	0x00000ff8	/* for 4K buffers */
 #define PROD_CONS_PTR_1K	0x000003f8	/* for 1K buffers */
 #define PROD_CONS_PTR_OFF	3
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/ia64/include/asm/sn/shubio.h linux-libre-4.7-gnu/arch/ia64/include/asm/sn/shubio.h
--- linux-libre-4.6-gnu/arch/ia64/include/asm/sn/shubio.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/ia64/include/asm/sn/shubio.h	2016-07-24 15:23:50.000000000 -0400
@@ -1385,7 +1385,7 @@ typedef union ii_ibcr_u {
  * respones are captured until IXSS[VALID] is cleared by setting the    *
  * appropriate bit in IECLR. Every time a spurious read response is     *
  * detected, the SPUR_RD bit of the PRB corresponding to the incoming   *
- * message's SIDN field is set. This always happens, regarless of       *
+ * message's SIDN field is set. This always happens, regardless of       *
  * whether a header is captured. The programmer should check            *
  * IXSM[SIDN] to determine which widget sent the spurious response,     *
  * because there may be more than one SPUR_RD bit set in the PRB        *
@@ -2997,7 +2997,7 @@ typedef union ii_ippr_u {
 /*
  * Values for field imsgtype
  */
-#define IIO_ICRB_IMSGT_XTALK    0	/* Incoming Meessage from Xtalk */
+#define IIO_ICRB_IMSGT_XTALK    0	/* Incoming message from Xtalk */
 #define IIO_ICRB_IMSGT_BTE      1	/* Incoming message from BTE    */
 #define IIO_ICRB_IMSGT_SN1NET   2	/* Incoming message from SN1 net */
 #define IIO_ICRB_IMSGT_CRB      3	/* Incoming message from CRB ???  */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/ia64/include/asm/thread_info.h linux-libre-4.7-gnu/arch/ia64/include/asm/thread_info.h
--- linux-libre-4.6-gnu/arch/ia64/include/asm/thread_info.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/ia64/include/asm/thread_info.h	2016-07-24 15:23:50.000000000 -0400
@@ -48,15 +48,15 @@ struct thread_info {
 #ifndef ASM_OFFSETS_C
 /* how to get the thread information struct from C */
 #define current_thread_info()	((struct thread_info *) ((char *) current + IA64_TASK_SIZE))
-#define alloc_thread_info_node(tsk, node)	\
-		((struct thread_info *) ((char *) (tsk) + IA64_TASK_SIZE))
+#define alloc_thread_stack_node(tsk, node)	\
+		((unsigned long *) ((char *) (tsk) + IA64_TASK_SIZE))
 #define task_thread_info(tsk)	((struct thread_info *) ((char *) (tsk) + IA64_TASK_SIZE))
 #else
 #define current_thread_info()	((struct thread_info *) 0)
-#define alloc_thread_info_node(tsk, node)	((struct thread_info *) 0)
+#define alloc_thread_stack_node(tsk, node)	((unsigned long *) 0)
 #define task_thread_info(tsk)	((struct thread_info *) 0)
 #endif
-#define free_thread_info(ti)	/* nothing */
+#define free_thread_stack(ti)	/* nothing */
 #define task_stack_page(tsk)	((void *)(tsk))
 
 #define __HAVE_THREAD_FUNCTIONS
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/ia64/Kconfig linux-libre-4.7-gnu/arch/ia64/Kconfig
--- linux-libre-4.6-gnu/arch/ia64/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/ia64/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -18,6 +18,7 @@ config IA64
 	select ACPI_SYSTEM_POWER_STATES_SUPPORT if ACPI
 	select ARCH_MIGHT_HAVE_ACPI_PDC if ACPI
 	select HAVE_UNSTABLE_SCHED_CLOCK
+	select HAVE_EXIT_THREAD
 	select HAVE_IDE
 	select HAVE_OPROFILE
 	select HAVE_KPROBES
@@ -44,7 +45,7 @@ config IA64
 	select GENERIC_SMP_IDLE_THREAD
 	select ARCH_INIT_TASK
 	select ARCH_TASK_STRUCT_ALLOCATOR
-	select ARCH_THREAD_INFO_ALLOCATOR
+	select ARCH_THREAD_STACK_ALLOCATOR
 	select ARCH_CLOCKSOURCE_DATA
 	select GENERIC_TIME_VSYSCALL_OLD
 	select SYSCTL_ARCH_UNALIGN_NO_WARN
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/ia64/kernel/efi.c linux-libre-4.7-gnu/arch/ia64/kernel/efi.c
--- linux-libre-4.6-gnu/arch/ia64/kernel/efi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/ia64/kernel/efi.c	2016-07-24 15:23:50.000000000 -0400
@@ -531,8 +531,6 @@ efi_init (void)
 	       efi.systab->hdr.revision >> 16,
 	       efi.systab->hdr.revision & 0xffff, vendor);
 
-	set_bit(EFI_SYSTEM_TABLES, &efi.flags);
-
 	palo_phys      = EFI_INVALID_TABLE_ADDR;
 
 	if (efi_config_init(arch_tables) != 0)
@@ -966,7 +964,7 @@ efi_uart_console_only(void)
 /*
  * Look for the first granule aligned memory descriptor memory
  * that is big enough to hold EFI memory map. Make sure this
- * descriptor is atleast granule sized so it does not get trimmed
+ * descriptor is at least granule sized so it does not get trimmed
  */
 struct kern_memdesc *
 find_memmap_space (void)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/ia64/kernel/init_task.c linux-libre-4.7-gnu/arch/ia64/kernel/init_task.c
--- linux-libre-4.6-gnu/arch/ia64/kernel/init_task.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/ia64/kernel/init_task.c	2016-07-24 15:23:50.000000000 -0400
@@ -26,6 +26,7 @@ static struct sighand_struct init_sighan
  * handled. This is done by having a special ".data..init_task" section...
  */
 #define init_thread_info	init_task_mem.s.thread_info
+#define init_stack		init_task_mem.stack
 
 union {
 	struct {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/ia64/kernel/mca.c linux-libre-4.7-gnu/arch/ia64/kernel/mca.c
--- linux-libre-4.6-gnu/arch/ia64/kernel/mca.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/ia64/kernel/mca.c	2016-07-24 15:23:50.000000000 -0400
@@ -1904,13 +1904,10 @@ static int mca_cpu_callback(struct notif
 				      unsigned long action,
 				      void *hcpu)
 {
-	int hotcpu = (unsigned long) hcpu;
-
 	switch (action) {
 	case CPU_ONLINE:
 	case CPU_ONLINE_FROZEN:
-		smp_call_function_single(hotcpu, ia64_mca_cmc_vector_adjust,
-					 NULL, 0);
+		ia64_mca_cmc_vector_adjust(NULL);
 		break;
 	}
 	return NOTIFY_OK;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/ia64/kernel/perfmon.c linux-libre-4.7-gnu/arch/ia64/kernel/perfmon.c
--- linux-libre-4.6-gnu/arch/ia64/kernel/perfmon.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/ia64/kernel/perfmon.c	2016-07-24 15:23:50.000000000 -0400
@@ -4542,8 +4542,8 @@ pfm_context_unload(pfm_context_t *ctx, v
 
 
 /*
- * called only from exit_thread(): task == current
- * we come here only if current has a context attached (loaded or masked)
+ * called only from exit_thread()
+ * we come here only if the task has a context attached (loaded or masked)
  */
 void
 pfm_exit_thread(struct task_struct *task)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/ia64/kernel/process.c linux-libre-4.7-gnu/arch/ia64/kernel/process.c
--- linux-libre-4.6-gnu/arch/ia64/kernel/process.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/ia64/kernel/process.c	2016-07-24 15:23:50.000000000 -0400
@@ -570,22 +570,22 @@ flush_thread (void)
 }
 
 /*
- * Clean up state associated with current thread.  This is called when
+ * Clean up state associated with a thread.  This is called when
  * the thread calls exit().
  */
 void
-exit_thread (void)
+exit_thread (struct task_struct *tsk)
 {
 
-	ia64_drop_fpu(current);
+	ia64_drop_fpu(tsk);
 #ifdef CONFIG_PERFMON
        /* if needed, stop monitoring and flush state to perfmon context */
-	if (current->thread.pfm_context)
-		pfm_exit_thread(current);
+	if (tsk->thread.pfm_context)
+		pfm_exit_thread(tsk);
 
 	/* free debug register resources */
-	if (current->thread.flags & IA64_THREAD_DBG_VALID)
-		pfm_release_debug_registers(current);
+	if (tsk->thread.flags & IA64_THREAD_DBG_VALID)
+		pfm_release_debug_registers(tsk);
 #endif
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/ia64/kernel/traps.c linux-libre-4.7-gnu/arch/ia64/kernel/traps.c
--- linux-libre-4.6-gnu/arch/ia64/kernel/traps.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/ia64/kernel/traps.c	2016-07-24 15:23:50.000000000 -0400
@@ -548,6 +548,7 @@ ia64_fault (unsigned long vector, unsign
 			return;
 		}
 		switch (vector) {
+		      default:
 		      case 29:
 			siginfo.si_code = TRAP_HWBKPT;
 #ifdef CONFIG_ITANIUM
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/ia64/kernel/unaligned.c linux-libre-4.7-gnu/arch/ia64/kernel/unaligned.c
--- linux-libre-4.6-gnu/arch/ia64/kernel/unaligned.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/ia64/kernel/unaligned.c	2016-07-24 15:23:50.000000000 -0400
@@ -1378,6 +1378,7 @@ ia64_handle_unaligned (unsigned long ifa
 	 * extract the instruction from the bundle given the slot number
 	 */
 	switch (ipsr->ri) {
+	      default:
 	      case 0: u.l = (bundle[0] >>  5); break;
 	      case 1: u.l = (bundle[0] >> 46) | (bundle[1] << 18); break;
 	      case 2: u.l = (bundle[1] >> 23); break;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/ia64/lib/idiv32.S linux-libre-4.7-gnu/arch/ia64/lib/idiv32.S
--- linux-libre-4.6-gnu/arch/ia64/lib/idiv32.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/ia64/lib/idiv32.S	2016-07-24 15:23:50.000000000 -0400
@@ -11,7 +11,7 @@
  *
  * For more details on the theory behind these algorithms, see "IA-64
  * and Elementary Functions" by Peter Markstein; HP Professional Books
- * (http://www.hp.com/go/retailbooks/)
+ * (http://www.goodreads.com/book/show/2019887.Ia_64_and_Elementary_Functions)
  */
 
 #include <asm/asmmacro.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/ia64/lib/idiv64.S linux-libre-4.7-gnu/arch/ia64/lib/idiv64.S
--- linux-libre-4.6-gnu/arch/ia64/lib/idiv64.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/ia64/lib/idiv64.S	2016-07-24 15:23:50.000000000 -0400
@@ -11,7 +11,7 @@
  *
  * For more details on the theory behind these algorithms, see "IA-64
  * and Elementary Functions" by Peter Markstein; HP Professional Books
- * (http://www.hp.com/go/retailbooks/)
+ * (http://www.goodreads.com/book/show/2019887.Ia_64_and_Elementary_Functions)
  */
 
 #include <asm/asmmacro.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/ia64/Makefile linux-libre-4.7-gnu/arch/ia64/Makefile
--- linux-libre-4.6-gnu/arch/ia64/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/ia64/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -95,8 +95,8 @@ define archhelp
   echo '* unwcheck	- Check vmlinux for invalid unwind info'
 endef
 
-archprepare: make_nr_irqs_h FORCE
-PHONY += make_nr_irqs_h FORCE
+archprepare: make_nr_irqs_h
+PHONY += make_nr_irqs_h
 
-make_nr_irqs_h: FORCE
+make_nr_irqs_h:
 	$(Q)$(MAKE) $(build)=arch/ia64/kernel include/generated/nr-irqs.h
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/ia64/sn/kernel/io_acpi_init.c linux-libre-4.7-gnu/arch/ia64/sn/kernel/io_acpi_init.c
--- linux-libre-4.6-gnu/arch/ia64/sn/kernel/io_acpi_init.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/ia64/sn/kernel/io_acpi_init.c	2016-07-24 15:23:50.000000000 -0400
@@ -426,7 +426,6 @@ sn_acpi_get_pcidev_info(struct pci_dev *
 void
 sn_acpi_slot_fixup(struct pci_dev *dev)
 {
-	void __iomem *addr;
 	struct pcidev_info *pcidev_info = NULL;
 	struct sn_irq_info *sn_irq_info = NULL;
 	struct resource *res;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/ia64/sn/kernel/io_init.c linux-libre-4.7-gnu/arch/ia64/sn/kernel/io_init.c
--- linux-libre-4.6-gnu/arch/ia64/sn/kernel/io_init.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/ia64/sn/kernel/io_init.c	2016-07-24 15:23:50.000000000 -0400
@@ -151,7 +151,7 @@ sn_io_slot_fixup(struct pci_dev *dev)
 {
 	int idx;
 	struct resource *res;
-	unsigned long addr, size;
+	unsigned long size;
 	struct pcidev_info *pcidev_info;
 	struct sn_irq_info *sn_irq_info;
 	int status;
@@ -186,7 +186,7 @@ sn_io_slot_fixup(struct pci_dev *dev)
 			continue;
 
 		res->start = pcidev_info->pdi_pio_mapped_addr[idx];
-		res->end = addr + size;
+		res->end = res->start + size;
 
 		/*
 		 * if it's already in the device structure, remove it before
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/ia64/sn/kernel/sn2/sn2_smp.c linux-libre-4.7-gnu/arch/ia64/sn/kernel/sn2/sn2_smp.c
--- linux-libre-4.6-gnu/arch/ia64/sn/kernel/sn2/sn2_smp.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/ia64/sn/kernel/sn2/sn2_smp.c	2016-07-24 15:23:50.000000000 -0400
@@ -54,7 +54,7 @@ sn2_ptc_deadlock_recovery_core(volatile
 			       volatile unsigned long *, unsigned long,
 			       volatile unsigned long *, unsigned long);
 void
-sn2_ptc_deadlock_recovery(short *, short, short, int,
+sn2_ptc_deadlock_recovery(nodemask_t, short, short, int,
 			  volatile unsigned long *, unsigned long,
 			  volatile unsigned long *, unsigned long);
 
@@ -169,7 +169,7 @@ sn2_global_tlb_purge(struct mm_struct *m
 	int use_cpu_ptcga;
 	volatile unsigned long *ptc0, *ptc1;
 	unsigned long itc, itc2, flags, data0 = 0, data1 = 0, rr_value, old_rr = 0;
-	short nasids[MAX_NUMNODES], nix;
+	short nix;
 	nodemask_t nodes_flushed;
 	int active, max_active, deadlock, flush_opt = sn2_flush_opt;
 
@@ -218,9 +218,7 @@ sn2_global_tlb_purge(struct mm_struct *m
 	}
 
 	itc = ia64_get_itc();
-	nix = 0;
-	for_each_node_mask(cnode, nodes_flushed)
-		nasids[nix++] = cnodeid_to_nasid(cnode);
+	nix = nodes_weight(nodes_flushed);
 
 	rr_value = (mm->context << 3) | REGION_NUMBER(start);
 
@@ -270,8 +268,10 @@ sn2_global_tlb_purge(struct mm_struct *m
 			data0 = (data0 & ~SH2_PTC_ADDR_MASK) | (start & SH2_PTC_ADDR_MASK);
 		deadlock = 0;
 		active = 0;
-		for (ibegin = 0, i = 0; i < nix; i++) {
-			nasid = nasids[i];
+		ibegin = 0;
+		i = 0;
+		for_each_node_mask(cnode, nodes_flushed) {
+			nasid = cnodeid_to_nasid(cnode);
 			if (use_cpu_ptcga && unlikely(nasid == mynasid)) {
 				ia64_ptcga(start, nbits << 2);
 				ia64_srlz_i();
@@ -286,13 +286,14 @@ sn2_global_tlb_purge(struct mm_struct *m
 				if ((deadlock = wait_piowc())) {
 					if (flush_opt == 1)
 						goto done;
-					sn2_ptc_deadlock_recovery(nasids, ibegin, i, mynasid, ptc0, data0, ptc1, data1);
+					sn2_ptc_deadlock_recovery(nodes_flushed, ibegin, i, mynasid, ptc0, data0, ptc1, data1);
 					if (reset_max_active_on_deadlock())
 						max_active = 1;
 				}
 				active = 0;
 				ibegin = i + 1;
 			}
+			i++;
 		}
 		start += (1UL << nbits);
 	} while (start < end);
@@ -327,11 +328,12 @@ done:
  */
 
 void
-sn2_ptc_deadlock_recovery(short *nasids, short ib, short ie, int mynasid,
+sn2_ptc_deadlock_recovery(nodemask_t nodes, short ib, short ie, int mynasid,
 			  volatile unsigned long *ptc0, unsigned long data0,
 			  volatile unsigned long *ptc1, unsigned long data1)
 {
 	short nasid, i;
+	int cnode;
 	unsigned long *piows, zeroval, n;
 
 	__this_cpu_inc(ptcstats.deadlocks);
@@ -339,17 +341,26 @@ sn2_ptc_deadlock_recovery(short *nasids,
 	piows = (unsigned long *) pda->pio_write_status_addr;
 	zeroval = pda->pio_write_status_val;
 
+	i = 0;
+	for_each_node_mask(cnode, nodes) {
+		if (i < ib)
+			goto next;
 
-	for (i=ib; i <= ie; i++) {
-		nasid = nasids[i];
+		if (i > ie)
+			break;
+
+		nasid = cnodeid_to_nasid(cnode);
 		if (local_node_uses_ptc_ga(is_shub1()) && nasid == mynasid)
-			continue;
+			goto next;
+
 		ptc0 = CHANGE_NASID(nasid, ptc0);
 		if (ptc1)
 			ptc1 = CHANGE_NASID(nasid, ptc1);
 
 		n = sn2_ptc_deadlock_recovery_core(ptc0, data0, ptc1, data1, piows, zeroval);
 		__this_cpu_add(ptcstats.deadlocks2, n);
+next:
+		i++;
 	}
 
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/Kconfig linux-libre-4.7-gnu/arch/Kconfig
--- linux-libre-4.6-gnu/arch/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -187,7 +187,11 @@ config HAVE_OPTPROBES
 config HAVE_KPROBES_ON_FTRACE
 	bool
 
+config HAVE_NMI
+	bool
+
 config HAVE_NMI_WATCHDOG
+	depends on HAVE_NMI
 	bool
 #
 # An arch should select this if it provides all these things:
@@ -222,8 +226,8 @@ config ARCH_INIT_TASK
 config ARCH_TASK_STRUCT_ALLOCATOR
 	bool
 
-# Select if arch has its private alloc_thread_info() function
-config ARCH_THREAD_INFO_ALLOCATOR
+# Select if arch has its private alloc_thread_stack() function
+config ARCH_THREAD_STACK_ALLOCATOR
 	bool
 
 # Select if arch wants to size task_struct dynamically via arch_task_struct_size:
@@ -517,6 +521,11 @@ config HAVE_ARCH_MMAP_RND_BITS
 	  - ARCH_MMAP_RND_BITS_MIN
 	  - ARCH_MMAP_RND_BITS_MAX
 
+config HAVE_EXIT_THREAD
+	bool
+	help
+	  An architecture implements exit_thread.
+
 config ARCH_MMAP_RND_BITS_MIN
 	int
 
@@ -589,6 +598,17 @@ config HAVE_STACK_VALIDATION
 	  Architecture supports the 'objtool check' host tool command, which
 	  performs compile-time stack metadata validation.
 
+config HAVE_ARCH_HASH
+	bool
+	default n
+	help
+	  If this is set, the architecture provides an <asm/hash.h>
+	  file which provides platform-specific implementations of some
+	  functions in <linux/hash.h> or fs/namei.c.
+
+config ISA_BUS_API
+	def_bool ISA
+
 #
 # ABI hall of shame
 #
@@ -638,4 +658,7 @@ config COMPAT_OLD_SIGACTION
 config ARCH_NO_COHERENT_DMA_MMAP
 	bool
 
+config CPU_NO_EFFICIENT_FFS
+	def_bool n
+
 source "kernel/gcov/Kconfig"
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/m32r/boot/compressed/m32r_sio.c linux-libre-4.7-gnu/arch/m32r/boot/compressed/m32r_sio.c
--- linux-libre-4.6-gnu/arch/m32r/boot/compressed/m32r_sio.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/m32r/boot/compressed/m32r_sio.c	2016-07-24 15:23:50.000000000 -0400
@@ -8,12 +8,13 @@
 
 #include <asm/processor.h>
 
-static void putc(char c);
+static void m32r_putc(char c);
 
 static int puts(const char *s)
 {
 	char c;
-	while ((c = *s++)) putc(c);
+	while ((c = *s++))
+		m32r_putc(c);
 	return 0;
 }
 
@@ -41,7 +42,7 @@ static int puts(const char *s)
 #define BOOT_SIO0TXB	PLD_ESIO0TXB
 #endif
 
-static void putc(char c)
+static void m32r_putc(char c)
 {
 	while ((*BOOT_SIO0STS & 0x3) != 0x3)
 		cpu_relax();
@@ -61,7 +62,7 @@ static void putc(char c)
 #define SIO0TXB	(volatile unsigned short *)(0x00efd000 + 30)
 #endif
 
-static void putc(char c)
+static void m32r_putc(char c)
 {
 	while ((*SIO0STS & 0x1) == 0)
 		cpu_relax();
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/m32r/boot/compressed/Makefile linux-libre-4.7-gnu/arch/m32r/boot/compressed/Makefile
--- linux-libre-4.6-gnu/arch/m32r/boot/compressed/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/m32r/boot/compressed/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -19,7 +19,6 @@ LDFLAGS_vmlinux := -T
 
 $(obj)/vmlinux: $(obj)/vmlinux.lds $(OBJECTS) $(obj)/piggy.o FORCE
 	$(call if_changed,ld)
-	@:
 
 $(obj)/vmlinux.bin: vmlinux FORCE
 	$(call if_changed,objcopy)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/m32r/Kconfig linux-libre-4.7-gnu/arch/m32r/Kconfig
--- linux-libre-4.6-gnu/arch/m32r/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/m32r/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -17,6 +17,7 @@ config M32R
 	select ARCH_USES_GETTIMEOFFSET
 	select MODULES_USE_ELF_RELA
 	select HAVE_DEBUG_STACKOVERFLOW
+	select CPU_NO_EFFICIENT_FFS
 
 config SBUS
 	bool
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/m32r/kernel/process.c linux-libre-4.7-gnu/arch/m32r/kernel/process.c
--- linux-libre-4.6-gnu/arch/m32r/kernel/process.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/m32r/kernel/process.c	2016-07-24 15:23:50.000000000 -0400
@@ -101,15 +101,6 @@ void show_regs(struct pt_regs * regs)
 #endif
 }
 
-/*
- * Free current thread data structures etc..
- */
-void exit_thread(void)
-{
-	/* Nothing to do. */
-	DPRINTK("pid = %d\n", current->pid);
-}
-
 void flush_thread(void)
 {
 	DPRINTK("pid = %d\n", current->pid);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/m32r/kernel/smp.c linux-libre-4.7-gnu/arch/m32r/kernel/smp.c
--- linux-libre-4.6-gnu/arch/m32r/kernel/smp.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/m32r/kernel/smp.c	2016-07-24 15:23:50.000000000 -0400
@@ -164,6 +164,7 @@ void smp_flush_cache_all(void)
 	spin_unlock(&flushcache_lock);
 	preempt_enable();
 }
+EXPORT_SYMBOL(smp_flush_cache_all);
 
 void smp_flush_cache_all_interrupt(void)
 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/m68k/bvme6000/rtc.c linux-libre-4.7-gnu/arch/m68k/bvme6000/rtc.c
--- linux-libre-4.6-gnu/arch/m68k/bvme6000/rtc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/m68k/bvme6000/rtc.c	2016-07-24 15:23:50.000000000 -0400
@@ -15,7 +15,7 @@
 #include <linux/init.h>
 #include <linux/poll.h>
 #include <linux/module.h>
-#include <linux/mc146818rtc.h>	/* For struct rtc_time and ioctls, etc */
+#include <linux/rtc.h>	/* For struct rtc_time and ioctls, etc */
 #include <linux/bcd.h>
 #include <asm/bvme6000hw.h>
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/m68k/coldfire/head.S linux-libre-4.7-gnu/arch/m68k/coldfire/head.S
--- linux-libre-4.6-gnu/arch/m68k/coldfire/head.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/m68k/coldfire/head.S	2016-07-24 15:23:50.000000000 -0400
@@ -288,7 +288,7 @@ _clear_bss:
 #endif
 
 	/*
-	 *	Assember start up done, start code proper.
+	 *	Assembler start up done, start code proper.
 	 */
 	jsr	start_kernel			/* start Linux kernel */
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/m68k/coldfire/m5272.c linux-libre-4.7-gnu/arch/m68k/coldfire/m5272.c
--- linux-libre-4.6-gnu/arch/m68k/coldfire/m5272.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/m68k/coldfire/m5272.c	2016-07-24 15:23:50.000000000 -0400
@@ -111,7 +111,7 @@ void __init config_BSP(char *commandp, i
 /***************************************************************************/
 
 /*
- * Some 5272 based boards have the FEC ethernet diectly connected to
+ * Some 5272 based boards have the FEC ethernet directly connected to
  * an ethernet switch. In this case we need to use the fixed phy type,
  * and we need to declare it early in boot.
  */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/m68k/coldfire/pci.c linux-libre-4.7-gnu/arch/m68k/coldfire/pci.c
--- linux-libre-4.6-gnu/arch/m68k/coldfire/pci.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/m68k/coldfire/pci.c	2016-07-24 15:23:50.000000000 -0400
@@ -42,7 +42,7 @@ static unsigned long iospace;
 
 /*
  * We need to be carefull probing on bus 0 (directly connected to host
- * bridge). We should only acccess the well defined possible devices in
+ * bridge). We should only access the well defined possible devices in
  * use, ignore aliases and the like.
  */
 static unsigned char mcf_host_slot2sid[32] = {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/m68k/configs/amiga_defconfig linux-libre-4.7-gnu/arch/m68k/configs/amiga_defconfig
--- linux-libre-4.6-gnu/arch/m68k/configs/amiga_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/m68k/configs/amiga_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -9,6 +9,7 @@ CONFIG_LOG_BUF_SHIFT=16
 # CONFIG_PID_NS is not set
 # CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_USERFAULTFD=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
@@ -359,6 +360,7 @@ CONFIG_MACVTAP=m
 CONFIG_IPVLAN=m
 CONFIG_VXLAN=m
 CONFIG_GENEVE=m
+CONFIG_GTP=m
 CONFIG_MACSEC=m
 CONFIG_NETCONSOLE=m
 CONFIG_NETCONSOLE_DYNAMIC=y
@@ -553,7 +555,9 @@ CONFIG_TEST_STRING_HELPERS=m
 CONFIG_TEST_KSTRTOX=m
 CONFIG_TEST_PRINTF=m
 CONFIG_TEST_BITMAP=m
+CONFIG_TEST_UUID=m
 CONFIG_TEST_RHASHTABLE=m
+CONFIG_TEST_HASH=m
 CONFIG_TEST_LKM=m
 CONFIG_TEST_USER_COPY=m
 CONFIG_TEST_BPF=m
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/m68k/configs/apollo_defconfig linux-libre-4.7-gnu/arch/m68k/configs/apollo_defconfig
--- linux-libre-4.6-gnu/arch/m68k/configs/apollo_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/m68k/configs/apollo_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -9,6 +9,7 @@ CONFIG_LOG_BUF_SHIFT=16
 # CONFIG_PID_NS is not set
 # CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_USERFAULTFD=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
@@ -341,6 +342,7 @@ CONFIG_MACVTAP=m
 CONFIG_IPVLAN=m
 CONFIG_VXLAN=m
 CONFIG_GENEVE=m
+CONFIG_GTP=m
 CONFIG_MACSEC=m
 CONFIG_NETCONSOLE=m
 CONFIG_NETCONSOLE_DYNAMIC=y
@@ -512,7 +514,9 @@ CONFIG_TEST_STRING_HELPERS=m
 CONFIG_TEST_KSTRTOX=m
 CONFIG_TEST_PRINTF=m
 CONFIG_TEST_BITMAP=m
+CONFIG_TEST_UUID=m
 CONFIG_TEST_RHASHTABLE=m
+CONFIG_TEST_HASH=m
 CONFIG_TEST_LKM=m
 CONFIG_TEST_USER_COPY=m
 CONFIG_TEST_BPF=m
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/m68k/configs/atari_defconfig linux-libre-4.7-gnu/arch/m68k/configs/atari_defconfig
--- linux-libre-4.6-gnu/arch/m68k/configs/atari_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/m68k/configs/atari_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -9,6 +9,7 @@ CONFIG_LOG_BUF_SHIFT=16
 # CONFIG_PID_NS is not set
 # CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_USERFAULTFD=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
@@ -350,6 +351,7 @@ CONFIG_MACVTAP=m
 CONFIG_IPVLAN=m
 CONFIG_VXLAN=m
 CONFIG_GENEVE=m
+CONFIG_GTP=m
 CONFIG_MACSEC=m
 CONFIG_NETCONSOLE=m
 CONFIG_NETCONSOLE_DYNAMIC=y
@@ -533,7 +535,9 @@ CONFIG_TEST_STRING_HELPERS=m
 CONFIG_TEST_KSTRTOX=m
 CONFIG_TEST_PRINTF=m
 CONFIG_TEST_BITMAP=m
+CONFIG_TEST_UUID=m
 CONFIG_TEST_RHASHTABLE=m
+CONFIG_TEST_HASH=m
 CONFIG_TEST_LKM=m
 CONFIG_TEST_USER_COPY=m
 CONFIG_TEST_BPF=m
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/m68k/configs/bvme6000_defconfig linux-libre-4.7-gnu/arch/m68k/configs/bvme6000_defconfig
--- linux-libre-4.6-gnu/arch/m68k/configs/bvme6000_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/m68k/configs/bvme6000_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -9,6 +9,7 @@ CONFIG_LOG_BUF_SHIFT=16
 # CONFIG_PID_NS is not set
 # CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_USERFAULTFD=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
@@ -340,6 +341,7 @@ CONFIG_MACVTAP=m
 CONFIG_IPVLAN=m
 CONFIG_VXLAN=m
 CONFIG_GENEVE=m
+CONFIG_GTP=m
 CONFIG_MACSEC=m
 CONFIG_NETCONSOLE=m
 CONFIG_NETCONSOLE_DYNAMIC=y
@@ -504,7 +506,9 @@ CONFIG_TEST_STRING_HELPERS=m
 CONFIG_TEST_KSTRTOX=m
 CONFIG_TEST_PRINTF=m
 CONFIG_TEST_BITMAP=m
+CONFIG_TEST_UUID=m
 CONFIG_TEST_RHASHTABLE=m
+CONFIG_TEST_HASH=m
 CONFIG_TEST_LKM=m
 CONFIG_TEST_USER_COPY=m
 CONFIG_TEST_BPF=m
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/m68k/configs/hp300_defconfig linux-libre-4.7-gnu/arch/m68k/configs/hp300_defconfig
--- linux-libre-4.6-gnu/arch/m68k/configs/hp300_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/m68k/configs/hp300_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -9,6 +9,7 @@ CONFIG_LOG_BUF_SHIFT=16
 # CONFIG_PID_NS is not set
 # CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_USERFAULTFD=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
@@ -341,6 +342,7 @@ CONFIG_MACVTAP=m
 CONFIG_IPVLAN=m
 CONFIG_VXLAN=m
 CONFIG_GENEVE=m
+CONFIG_GTP=m
 CONFIG_MACSEC=m
 CONFIG_NETCONSOLE=m
 CONFIG_NETCONSOLE_DYNAMIC=y
@@ -514,7 +516,9 @@ CONFIG_TEST_STRING_HELPERS=m
 CONFIG_TEST_KSTRTOX=m
 CONFIG_TEST_PRINTF=m
 CONFIG_TEST_BITMAP=m
+CONFIG_TEST_UUID=m
 CONFIG_TEST_RHASHTABLE=m
+CONFIG_TEST_HASH=m
 CONFIG_TEST_LKM=m
 CONFIG_TEST_USER_COPY=m
 CONFIG_TEST_BPF=m
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/m68k/configs/mac_defconfig linux-libre-4.7-gnu/arch/m68k/configs/mac_defconfig
--- linux-libre-4.6-gnu/arch/m68k/configs/mac_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/m68k/configs/mac_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -9,6 +9,7 @@ CONFIG_LOG_BUF_SHIFT=16
 # CONFIG_PID_NS is not set
 # CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_USERFAULTFD=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
@@ -357,6 +358,7 @@ CONFIG_MACVTAP=m
 CONFIG_IPVLAN=m
 CONFIG_VXLAN=m
 CONFIG_GENEVE=m
+CONFIG_GTP=m
 CONFIG_MACSEC=m
 CONFIG_NETCONSOLE=m
 CONFIG_NETCONSOLE_DYNAMIC=y
@@ -536,7 +538,9 @@ CONFIG_TEST_STRING_HELPERS=m
 CONFIG_TEST_KSTRTOX=m
 CONFIG_TEST_PRINTF=m
 CONFIG_TEST_BITMAP=m
+CONFIG_TEST_UUID=m
 CONFIG_TEST_RHASHTABLE=m
+CONFIG_TEST_HASH=m
 CONFIG_TEST_LKM=m
 CONFIG_TEST_USER_COPY=m
 CONFIG_TEST_BPF=m
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/m68k/configs/multi_defconfig linux-libre-4.7-gnu/arch/m68k/configs/multi_defconfig
--- linux-libre-4.6-gnu/arch/m68k/configs/multi_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/m68k/configs/multi_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -9,6 +9,7 @@ CONFIG_LOG_BUF_SHIFT=16
 # CONFIG_PID_NS is not set
 # CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_USERFAULTFD=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
@@ -390,6 +391,7 @@ CONFIG_MACVTAP=m
 CONFIG_IPVLAN=m
 CONFIG_VXLAN=m
 CONFIG_GENEVE=m
+CONFIG_GTP=m
 CONFIG_MACSEC=m
 CONFIG_NETCONSOLE=m
 CONFIG_NETCONSOLE_DYNAMIC=y
@@ -616,7 +618,9 @@ CONFIG_TEST_STRING_HELPERS=m
 CONFIG_TEST_KSTRTOX=m
 CONFIG_TEST_PRINTF=m
 CONFIG_TEST_BITMAP=m
+CONFIG_TEST_UUID=m
 CONFIG_TEST_RHASHTABLE=m
+CONFIG_TEST_HASH=m
 CONFIG_TEST_LKM=m
 CONFIG_TEST_USER_COPY=m
 CONFIG_TEST_BPF=m
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/m68k/configs/mvme147_defconfig linux-libre-4.7-gnu/arch/m68k/configs/mvme147_defconfig
--- linux-libre-4.6-gnu/arch/m68k/configs/mvme147_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/m68k/configs/mvme147_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -9,6 +9,7 @@ CONFIG_LOG_BUF_SHIFT=16
 # CONFIG_PID_NS is not set
 # CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_USERFAULTFD=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
@@ -339,6 +340,7 @@ CONFIG_MACVTAP=m
 CONFIG_IPVLAN=m
 CONFIG_VXLAN=m
 CONFIG_GENEVE=m
+CONFIG_GTP=m
 CONFIG_MACSEC=m
 CONFIG_NETCONSOLE=m
 CONFIG_NETCONSOLE_DYNAMIC=y
@@ -504,7 +506,9 @@ CONFIG_TEST_STRING_HELPERS=m
 CONFIG_TEST_KSTRTOX=m
 CONFIG_TEST_PRINTF=m
 CONFIG_TEST_BITMAP=m
+CONFIG_TEST_UUID=m
 CONFIG_TEST_RHASHTABLE=m
+CONFIG_TEST_HASH=m
 CONFIG_TEST_LKM=m
 CONFIG_TEST_USER_COPY=m
 CONFIG_TEST_BPF=m
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/m68k/configs/mvme16x_defconfig linux-libre-4.7-gnu/arch/m68k/configs/mvme16x_defconfig
--- linux-libre-4.6-gnu/arch/m68k/configs/mvme16x_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/m68k/configs/mvme16x_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -9,6 +9,7 @@ CONFIG_LOG_BUF_SHIFT=16
 # CONFIG_PID_NS is not set
 # CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_USERFAULTFD=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
@@ -340,6 +341,7 @@ CONFIG_MACVTAP=m
 CONFIG_IPVLAN=m
 CONFIG_VXLAN=m
 CONFIG_GENEVE=m
+CONFIG_GTP=m
 CONFIG_MACSEC=m
 CONFIG_NETCONSOLE=m
 CONFIG_NETCONSOLE_DYNAMIC=y
@@ -504,7 +506,9 @@ CONFIG_TEST_STRING_HELPERS=m
 CONFIG_TEST_KSTRTOX=m
 CONFIG_TEST_PRINTF=m
 CONFIG_TEST_BITMAP=m
+CONFIG_TEST_UUID=m
 CONFIG_TEST_RHASHTABLE=m
+CONFIG_TEST_HASH=m
 CONFIG_TEST_LKM=m
 CONFIG_TEST_USER_COPY=m
 CONFIG_TEST_BPF=m
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/m68k/configs/q40_defconfig linux-libre-4.7-gnu/arch/m68k/configs/q40_defconfig
--- linux-libre-4.6-gnu/arch/m68k/configs/q40_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/m68k/configs/q40_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -9,6 +9,7 @@ CONFIG_LOG_BUF_SHIFT=16
 # CONFIG_PID_NS is not set
 # CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_USERFAULTFD=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
@@ -346,6 +347,7 @@ CONFIG_MACVTAP=m
 CONFIG_IPVLAN=m
 CONFIG_VXLAN=m
 CONFIG_GENEVE=m
+CONFIG_GTP=m
 CONFIG_MACSEC=m
 CONFIG_NETCONSOLE=m
 CONFIG_NETCONSOLE_DYNAMIC=y
@@ -527,7 +529,9 @@ CONFIG_TEST_STRING_HELPERS=m
 CONFIG_TEST_KSTRTOX=m
 CONFIG_TEST_PRINTF=m
 CONFIG_TEST_BITMAP=m
+CONFIG_TEST_UUID=m
 CONFIG_TEST_RHASHTABLE=m
+CONFIG_TEST_HASH=m
 CONFIG_TEST_LKM=m
 CONFIG_TEST_USER_COPY=m
 CONFIG_TEST_BPF=m
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/m68k/configs/sun3_defconfig linux-libre-4.7-gnu/arch/m68k/configs/sun3_defconfig
--- linux-libre-4.6-gnu/arch/m68k/configs/sun3_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/m68k/configs/sun3_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -9,6 +9,7 @@ CONFIG_LOG_BUF_SHIFT=16
 # CONFIG_PID_NS is not set
 # CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_USERFAULTFD=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
@@ -337,6 +338,7 @@ CONFIG_MACVTAP=m
 CONFIG_IPVLAN=m
 CONFIG_VXLAN=m
 CONFIG_GENEVE=m
+CONFIG_GTP=m
 CONFIG_MACSEC=m
 CONFIG_NETCONSOLE=m
 CONFIG_NETCONSOLE_DYNAMIC=y
@@ -506,7 +508,9 @@ CONFIG_TEST_STRING_HELPERS=m
 CONFIG_TEST_KSTRTOX=m
 CONFIG_TEST_PRINTF=m
 CONFIG_TEST_BITMAP=m
+CONFIG_TEST_UUID=m
 CONFIG_TEST_RHASHTABLE=m
+CONFIG_TEST_HASH=m
 CONFIG_TEST_LKM=m
 CONFIG_TEST_USER_COPY=m
 CONFIG_TEST_BPF=m
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/m68k/configs/sun3x_defconfig linux-libre-4.7-gnu/arch/m68k/configs/sun3x_defconfig
--- linux-libre-4.6-gnu/arch/m68k/configs/sun3x_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/m68k/configs/sun3x_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -9,6 +9,7 @@ CONFIG_LOG_BUF_SHIFT=16
 # CONFIG_PID_NS is not set
 # CONFIG_NET_NS is not set
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_USERFAULTFD=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
@@ -337,6 +338,7 @@ CONFIG_MACVTAP=m
 CONFIG_IPVLAN=m
 CONFIG_VXLAN=m
 CONFIG_GENEVE=m
+CONFIG_GTP=m
 CONFIG_MACSEC=m
 CONFIG_NETCONSOLE=m
 CONFIG_NETCONSOLE_DYNAMIC=y
@@ -506,7 +508,9 @@ CONFIG_TEST_STRING_HELPERS=m
 CONFIG_TEST_KSTRTOX=m
 CONFIG_TEST_PRINTF=m
 CONFIG_TEST_BITMAP=m
+CONFIG_TEST_UUID=m
 CONFIG_TEST_RHASHTABLE=m
+CONFIG_TEST_HASH=m
 CONFIG_TEST_LKM=m
 CONFIG_TEST_USER_COPY=m
 CONFIG_TEST_BPF=m
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/m68k/ifpsp060/src/fpsp.S linux-libre-4.7-gnu/arch/m68k/ifpsp060/src/fpsp.S
--- linux-libre-4.6-gnu/arch/m68k/ifpsp060/src/fpsp.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/m68k/ifpsp060/src/fpsp.S	2016-07-24 15:23:50.000000000 -0400
@@ -10191,7 +10191,7 @@ xdnrm_con:
 xdnrm_sd:
 	mov.l		%a1,-(%sp)
 	tst.b		LOCAL_EX(%a0)		# is denorm pos or neg?
-	smi.b		%d1			# set d0 accodingly
+	smi.b		%d1			# set d0 accordingly
 	bsr.l		unf_sub
 	mov.l		(%sp)+,%a1
 xdnrm_exit:
@@ -10990,7 +10990,7 @@ src_qnan_m:
 # routines where an instruction is selected by an index into
 # a large jump table corresponding to a given instruction which
 # has been decoded. Flow continues here where we now decode
-# further accoding to the source operand type.
+# further according to the source operand type.
 #
 
 	global		fsinh
@@ -23196,14 +23196,14 @@ m_sign:
 #
 #  1. Branch on the sign of the adjusted exponent.
 #  2p.(positive exp)
-#   2. Check M16 and the digits in lwords 2 and 3 in decending order.
+#   2. Check M16 and the digits in lwords 2 and 3 in descending order.
 #   3. Add one for each zero encountered until a non-zero digit.
 #   4. Subtract the count from the exp.
 #   5. Check if the exp has crossed zero in #3 above; make the exp abs
 #	   and set SE.
 #	6. Multiply the mantissa by 10**count.
 #  2n.(negative exp)
-#   2. Check the digits in lwords 3 and 2 in decending order.
+#   2. Check the digits in lwords 3 and 2 in descending order.
 #   3. Add one for each zero encountered until a non-zero digit.
 #   4. Add the count to the exp.
 #   5. Check if the exp has crossed zero in #3 above; clear SE.
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/m68k/ifpsp060/src/pfpsp.S linux-libre-4.7-gnu/arch/m68k/ifpsp060/src/pfpsp.S
--- linux-libre-4.6-gnu/arch/m68k/ifpsp060/src/pfpsp.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/m68k/ifpsp060/src/pfpsp.S	2016-07-24 15:23:50.000000000 -0400
@@ -13156,14 +13156,14 @@ m_sign:
 #
 #  1. Branch on the sign of the adjusted exponent.
 #  2p.(positive exp)
-#   2. Check M16 and the digits in lwords 2 and 3 in decending order.
+#   2. Check M16 and the digits in lwords 2 and 3 in descending order.
 #   3. Add one for each zero encountered until a non-zero digit.
 #   4. Subtract the count from the exp.
 #   5. Check if the exp has crossed zero in #3 above; make the exp abs
 #	   and set SE.
 #	6. Multiply the mantissa by 10**count.
 #  2n.(negative exp)
-#   2. Check the digits in lwords 3 and 2 in decending order.
+#   2. Check the digits in lwords 3 and 2 in descending order.
 #   3. Add one for each zero encountered until a non-zero digit.
 #   4. Add the count to the exp.
 #   5. Check if the exp has crossed zero in #3 above; clear SE.
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/m68k/include/asm/dma.h linux-libre-4.7-gnu/arch/m68k/include/asm/dma.h
--- linux-libre-4.6-gnu/arch/m68k/include/asm/dma.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/m68k/include/asm/dma.h	2016-07-24 15:23:50.000000000 -0400
@@ -18,7 +18,7 @@
  * AUG/22/2000 : added support for 32-bit Dual-Address-Mode (K) 2000
  *               Oliver Kamphenkel (O.Kamphenkel@tu-bs.de)
  *
- * AUG/25/2000 : addad support for 8, 16 and 32-bit Single-Address-Mode (K)2000
+ * AUG/25/2000 : added support for 8, 16 and 32-bit Single-Address-Mode (K)2000
  *               Oliver Kamphenkel (O.Kamphenkel@tu-bs.de)
  *
  * APR/18/2002 : added proper support for MCF5272 DMA controller.
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/m68k/include/asm/hash.h linux-libre-4.7-gnu/arch/m68k/include/asm/hash.h
--- linux-libre-4.6-gnu/arch/m68k/include/asm/hash.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/m68k/include/asm/hash.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,59 @@
+#ifndef _ASM_HASH_H
+#define _ASM_HASH_H
+
+/*
+ * If CONFIG_M68000=y (original mc68000/010), this file is #included
+ * to work around the lack of a MULU.L instruction.
+ */
+
+#define HAVE_ARCH__HASH_32 1
+/*
+ * While it would be legal to substitute a different hash operation
+ * entirely, let's keep it simple and just use an optimized multiply
+ * by GOLDEN_RATIO_32 = 0x61C88647.
+ *
+ * The best way to do that appears to be to multiply by 0x8647 with
+ * shifts and adds, and use mulu.w to multiply the high half by 0x61C8.
+ *
+ * Because the 68000 has multi-cycle shifts, this addition chain is
+ * chosen to minimise the shift distances.
+ *
+ * Despite every attempt to spoon-feed it simple operations, GCC
+ * 6.1.1 doggedly insists on doing annoying things like converting
+ * "lsl.l #2,<reg>" (12 cycles) to two adds (8+8 cycles).
+ *
+ * It also likes to notice two shifts in a row, like "a = x << 2" and
+ * "a <<= 7", and convert that to "a = x << 9".  But shifts longer
+ * than 8 bits are extra-slow on m68k, so that's a lose.
+ *
+ * Since the 68000 is a very simple in-order processor with no
+ * instruction scheduling effects on execution time, we can safely
+ * take it out of GCC's hands and write one big asm() block.
+ *
+ * Without calling overhead, this operation is 30 bytes (14 instructions
+ * plus one immediate constant) and 166 cycles.
+ *
+ * (Because %2 is fetched twice, it can't be postincrement, and thus it
+ * can't be a fully general "g" or "m".  Register is preferred, but
+ * offsettable memory or immediate will work.)
+ */
+static inline u32 __attribute_const__ __hash_32(u32 x)
+{
+	u32 a, b;
+
+	asm(   "move.l %2,%0"	/* a = x * 0x0001 */
+	"\n	lsl.l #2,%0"	/* a = x * 0x0004 */
+	"\n	move.l %0,%1"
+	"\n	lsl.l #7,%0"	/* a = x * 0x0200 */
+	"\n	add.l %2,%0"	/* a = x * 0x0201 */
+	"\n	add.l %0,%1"	/* b = x * 0x0205 */
+	"\n	add.l %0,%0"	/* a = x * 0x0402 */
+	"\n	add.l %0,%1"	/* b = x * 0x0607 */
+	"\n	lsl.l #5,%0"	/* a = x * 0x8040 */
+	: "=&d,d" (a), "=&r,r" (b)
+	: "r,roi?" (x));	/* a+b = x*0x8647 */
+
+	return ((u16)(x*0x61c8) << 16) + a + b;
+}
+
+#endif	/* _ASM_HASH_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/m68k/include/asm/m525xsim.h linux-libre-4.7-gnu/arch/m68k/include/asm/m525xsim.h
--- linux-libre-4.6-gnu/arch/m68k/include/asm/m525xsim.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/m68k/include/asm/m525xsim.h	2016-07-24 15:23:50.000000000 -0400
@@ -123,10 +123,10 @@
 /*
  *	I2C module.
  */
-#define MCFI2C_BASE0		(MCF_MBAR + 0x280)	/* Base addreess I2C0 */
+#define MCFI2C_BASE0		(MCF_MBAR + 0x280)	/* Base address I2C0 */
 #define MCFI2C_SIZE0		0x20			/* Register set size */
 
-#define MCFI2C_BASE1		(MCF_MBAR2 + 0x440)	/* Base addreess I2C1 */
+#define MCFI2C_BASE1		(MCF_MBAR2 + 0x440)	/* Base address I2C1 */
 #define MCFI2C_SIZE1		0x20			/* Register set size */
 
 /*
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/m68k/include/asm/mcfmmu.h linux-libre-4.7-gnu/arch/m68k/include/asm/mcfmmu.h
--- linux-libre-4.6-gnu/arch/m68k/include/asm/mcfmmu.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/m68k/include/asm/mcfmmu.h	2016-07-24 15:23:50.000000000 -0400
@@ -38,7 +38,7 @@
 /*
  *	MMU Operation register.
  */
-#define	MMUOR_UAA	0x00000001		/* Update allocatiom address */
+#define	MMUOR_UAA	0x00000001		/* Update allocation address */
 #define	MMUOR_ACC	0x00000002		/* TLB access */
 #define	MMUOR_RD	0x00000004		/* TLB access read */
 #define	MMUOR_WR	0x00000000		/* TLB access write */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/m68k/include/asm/mcf_pgalloc.h linux-libre-4.7-gnu/arch/m68k/include/asm/mcf_pgalloc.h
--- linux-libre-4.6-gnu/arch/m68k/include/asm/mcf_pgalloc.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/m68k/include/asm/mcf_pgalloc.h	2016-07-24 15:23:50.000000000 -0400
@@ -14,7 +14,7 @@ extern const char bad_pmd_string[];
 extern inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
 	unsigned long address)
 {
-	unsigned long page = __get_free_page(GFP_DMA|__GFP_REPEAT);
+	unsigned long page = __get_free_page(GFP_DMA);
 
 	if (!page)
 		return NULL;
@@ -51,7 +51,7 @@ static inline void __pte_free_tlb(struct
 static inline struct page *pte_alloc_one(struct mm_struct *mm,
 	unsigned long address)
 {
-	struct page *page = alloc_pages(GFP_DMA|__GFP_REPEAT, 0);
+	struct page *page = alloc_pages(GFP_DMA, 0);
 	pte_t *pte;
 
 	if (!page)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/m68k/include/asm/motorola_pgalloc.h linux-libre-4.7-gnu/arch/m68k/include/asm/motorola_pgalloc.h
--- linux-libre-4.6-gnu/arch/m68k/include/asm/motorola_pgalloc.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/m68k/include/asm/motorola_pgalloc.h	2016-07-24 15:23:50.000000000 -0400
@@ -11,7 +11,7 @@ static inline pte_t *pte_alloc_one_kerne
 {
 	pte_t *pte;
 
-	pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
+	pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_ZERO);
 	if (pte) {
 		__flush_page_to_ram(pte);
 		flush_tlb_kernel_page(pte);
@@ -32,7 +32,7 @@ static inline pgtable_t pte_alloc_one(st
 	struct page *page;
 	pte_t *pte;
 
-	page = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
+	page = alloc_pages(GFP_KERNEL|__GFP_ZERO, 0);
 	if(!page)
 		return NULL;
 	if (!pgtable_page_ctor(page)) {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/m68k/include/asm/processor.h linux-libre-4.7-gnu/arch/m68k/include/asm/processor.h
--- linux-libre-4.6-gnu/arch/m68k/include/asm/processor.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/m68k/include/asm/processor.h	2016-07-24 15:23:50.000000000 -0400
@@ -153,13 +153,6 @@ static inline void release_thread(struct
 {
 }
 
-/*
- * Free current thread data structures etc..
- */
-static inline void exit_thread(void)
-{
-}
-
 extern unsigned long thread_saved_pc(struct task_struct *tsk);
 
 unsigned long get_wchan(struct task_struct *p);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/m68k/include/asm/q40_master.h linux-libre-4.7-gnu/arch/m68k/include/asm/q40_master.h
--- linux-libre-4.6-gnu/arch/m68k/include/asm/q40_master.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/m68k/include/asm/q40_master.h	2016-07-24 15:23:50.000000000 -0400
@@ -1,6 +1,6 @@
 /*
  * Q40 master Chip Control
- * RTC stuff merged for compactnes..
+ * RTC stuff merged for compactness.
 */
 
 #ifndef _Q40_MASTER_H
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/m68k/include/asm/sun3_pgalloc.h linux-libre-4.7-gnu/arch/m68k/include/asm/sun3_pgalloc.h
--- linux-libre-4.6-gnu/arch/m68k/include/asm/sun3_pgalloc.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/m68k/include/asm/sun3_pgalloc.h	2016-07-24 15:23:50.000000000 -0400
@@ -37,7 +37,7 @@ do {							\
 static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
 					  unsigned long address)
 {
-	unsigned long page = __get_free_page(GFP_KERNEL|__GFP_REPEAT);
+	unsigned long page = __get_free_page(GFP_KERNEL);
 
 	if (!page)
 		return NULL;
@@ -49,7 +49,7 @@ static inline pte_t *pte_alloc_one_kerne
 static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
 					unsigned long address)
 {
-        struct page *page = alloc_pages(GFP_KERNEL|__GFP_REPEAT, 0);
+        struct page *page = alloc_pages(GFP_KERNEL, 0);
 
 	if (page == NULL)
 		return NULL;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/m68k/Kconfig.cpu linux-libre-4.7-gnu/arch/m68k/Kconfig.cpu
--- linux-libre-4.6-gnu/arch/m68k/Kconfig.cpu	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/m68k/Kconfig.cpu	2016-07-24 15:23:50.000000000 -0400
@@ -22,11 +22,11 @@ config M68KCLASSIC
 
 config COLDFIRE
 	bool "Coldfire CPU family support"
-	select ARCH_REQUIRE_GPIOLIB
 	select ARCH_HAVE_CUSTOM_GPIO_H
 	select CPU_HAS_NO_BITFIELDS
 	select CPU_HAS_NO_MULDIV64
 	select GENERIC_CSUM
+	select GPIOLIB
 	select HAVE_CLK
 
 endchoice
@@ -40,6 +40,8 @@ config M68000
 	select CPU_HAS_NO_MULDIV64
 	select CPU_HAS_NO_UNALIGNED
 	select GENERIC_CSUM
+	select CPU_NO_EFFICIENT_FFS
+	select HAVE_ARCH_HASH
 	help
 	  The Freescale (was Motorola) 68000 CPU is the first generation of
 	  the well known M68K family of processors. The CPU core as well as
@@ -51,6 +53,7 @@ config MCPU32
 	bool
 	select CPU_HAS_NO_BITFIELDS
 	select CPU_HAS_NO_UNALIGNED
+	select CPU_NO_EFFICIENT_FFS
 	help
 	  The Freescale (was then Motorola) CPU32 is a CPU core that is
 	  based on the 68020 processor. For the most part it is used in
@@ -130,6 +133,7 @@ config M5206
 	depends on !MMU
 	select COLDFIRE_SW_A7
 	select HAVE_MBAR
+	select CPU_NO_EFFICIENT_FFS
 	help
 	  Motorola ColdFire 5206 processor support.
 
@@ -138,6 +142,7 @@ config M5206e
 	depends on !MMU
 	select COLDFIRE_SW_A7
 	select HAVE_MBAR
+	select CPU_NO_EFFICIENT_FFS
 	help
 	  Motorola ColdFire 5206e processor support.
 
@@ -163,6 +168,7 @@ config M5249
 	depends on !MMU
 	select COLDFIRE_SW_A7
 	select HAVE_MBAR
+	select CPU_NO_EFFICIENT_FFS
 	help
 	  Motorola ColdFire 5249 processor support.
 
@@ -171,6 +177,7 @@ config M525x
 	depends on !MMU
 	select COLDFIRE_SW_A7
 	select HAVE_MBAR
+	select CPU_NO_EFFICIENT_FFS
 	help
 	  Freescale (Motorola) Coldfire 5251/5253 processor support.
 
@@ -189,6 +196,7 @@ config M5272
 	depends on !MMU
 	select COLDFIRE_SW_A7
 	select HAVE_MBAR
+	select CPU_NO_EFFICIENT_FFS
 	help
 	  Motorola ColdFire 5272 processor support.
 
@@ -217,6 +225,7 @@ config M5307
 	select COLDFIRE_SW_A7
 	select HAVE_CACHE_CB
 	select HAVE_MBAR
+	select CPU_NO_EFFICIENT_FFS
 	help
 	  Motorola ColdFire 5307 processor support.
 
@@ -242,6 +251,7 @@ config M5407
 	select COLDFIRE_SW_A7
 	select HAVE_CACHE_CB
 	select HAVE_MBAR
+	select CPU_NO_EFFICIENT_FFS
 	help
 	  Motorola ColdFire 5407 processor support.
 
@@ -251,6 +261,7 @@ config M547x
 	select MMU_COLDFIRE if MMU
 	select HAVE_CACHE_CB
 	select HAVE_MBAR
+	select CPU_NO_EFFICIENT_FFS
 	help
 	  Freescale ColdFire 5470/5471/5472/5473/5474/5475 processor support.
 
@@ -260,6 +271,7 @@ config M548x
 	select M54xx
 	select HAVE_CACHE_CB
 	select HAVE_MBAR
+	select CPU_NO_EFFICIENT_FFS
 	help
 	  Freescale ColdFire 5480/5481/5482/5483/5484/5485 processor support.
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/m68k/mac/iop.c linux-libre-4.7-gnu/arch/m68k/mac/iop.c
--- linux-libre-4.6-gnu/arch/m68k/mac/iop.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/m68k/mac/iop.c	2016-07-24 15:23:50.000000000 -0400
@@ -60,7 +60,7 @@
  *
  * The host talks to the IOPs using a rather simple message-passing scheme via
  * a shared memory area in the IOP RAM. Each IOP has seven "channels"; each
- * channel is conneced to a specific software driver on the IOP. For example
+ * channel is connected to a specific software driver on the IOP. For example
  * on the SCC IOP there is one channel for each serial port. Each channel has
  * an incoming and and outgoing message queue with a depth of one.
  *
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/m68k/math-emu/fp_decode.h linux-libre-4.7-gnu/arch/m68k/math-emu/fp_decode.h
--- linux-libre-4.6-gnu/arch/m68k/math-emu/fp_decode.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/m68k/math-emu/fp_decode.h	2016-07-24 15:23:50.000000000 -0400
@@ -130,7 +130,7 @@ do_fscc=0
 	bfextu	%d2{#13,#3},%d0
 .endm
 
-| decode the 8bit diplacement from the brief extension word
+| decode the 8bit displacement from the brief extension word
 .macro	fp_decode_disp8
 	move.b	%d2,%d0
 	ext.w	%d0
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/m68k/mvme16x/rtc.c linux-libre-4.7-gnu/arch/m68k/mvme16x/rtc.c
--- linux-libre-4.6-gnu/arch/m68k/mvme16x/rtc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/m68k/mvme16x/rtc.c	2016-07-24 15:23:50.000000000 -0400
@@ -14,7 +14,7 @@
 #include <linux/fcntl.h>
 #include <linux/init.h>
 #include <linux/poll.h>
-#include <linux/mc146818rtc.h>	/* For struct rtc_time and ioctls, etc */
+#include <linux/rtc.h>	/* For struct rtc_time and ioctls, etc */
 #include <linux/bcd.h>
 #include <asm/mvme16xhw.h>
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/metag/include/asm/atomic_lnkget.h linux-libre-4.7-gnu/arch/metag/include/asm/atomic_lnkget.h
--- linux-libre-4.6-gnu/arch/metag/include/asm/atomic_lnkget.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/metag/include/asm/atomic_lnkget.h	2016-07-24 15:23:50.000000000 -0400
@@ -61,7 +61,7 @@ static inline int atomic_##op##_return(i
 		"	CMPT	%0, #HI(0x02000000)\n"			\
 		"	BNZ 1b\n"					\
 		: "=&d" (temp), "=&da" (result)				\
-		: "da" (&v->counter), "bd" (i)				\
+		: "da" (&v->counter), "br" (i)				\
 		: "cc");						\
 									\
 	smp_mb();							\
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/metag/include/asm/metag_regs.h linux-libre-4.7-gnu/arch/metag/include/asm/metag_regs.h
--- linux-libre-4.6-gnu/arch/metag/include/asm/metag_regs.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/metag/include/asm/metag_regs.h	2016-07-24 15:23:50.000000000 -0400
@@ -1165,7 +1165,7 @@
 #define TXSTATUS_IPTOGGLE_BIT           0x80000000 /* Prev PToggle of TXPRIVEXT */
 #define TXSTATUS_ISTATE_BIT             0x40000000 /* IState bit */
 #define TXSTATUS_IWAIT_BIT              0x20000000 /* wait indefinitely in decision step*/
-#define TXSTATUS_IEXCEPT_BIT            0x10000000 /* Indicate an exception occured */
+#define TXSTATUS_IEXCEPT_BIT            0x10000000 /* Indicate an exception occurred */
 #define TXSTATUS_IRPCOUNT_BITS          0x0E000000 /* Number of 'dirty' date entries*/
 #define TXSTATUS_IRPCOUNT_S             25
 #define TXSTATUS_IRQSTAT_BITS           0x0000F000 /* IRQEnc bits, trigger or interrupts */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/metag/include/asm/pgalloc.h linux-libre-4.7-gnu/arch/metag/include/asm/pgalloc.h
--- linux-libre-4.6-gnu/arch/metag/include/asm/pgalloc.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/metag/include/asm/pgalloc.h	2016-07-24 15:23:50.000000000 -0400
@@ -42,8 +42,7 @@ static inline void pgd_free(struct mm_st
 static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
 					  unsigned long address)
 {
-	pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL | __GFP_REPEAT |
-					      __GFP_ZERO);
+	pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
 	return pte;
 }
 
@@ -51,7 +50,7 @@ static inline pgtable_t pte_alloc_one(st
 				      unsigned long address)
 {
 	struct page *pte;
-	pte = alloc_pages(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO, 0);
+	pte = alloc_pages(GFP_KERNEL  | __GFP_ZERO, 0);
 	if (!pte)
 		return NULL;
 	if (!pgtable_page_ctor(pte)) {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/metag/include/asm/processor.h linux-libre-4.7-gnu/arch/metag/include/asm/processor.h
--- linux-libre-4.6-gnu/arch/metag/include/asm/processor.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/metag/include/asm/processor.h	2016-07-24 15:23:50.000000000 -0400
@@ -134,8 +134,6 @@ static inline void release_thread(struct
 #define copy_segments(tsk, mm)		do { } while (0)
 #define release_segments(mm)		do { } while (0)
 
-extern void exit_thread(void);
-
 /*
  * Return saved PC of a blocked thread.
  */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/metag/include/asm/tbx.h linux-libre-4.7-gnu/arch/metag/include/asm/tbx.h
--- linux-libre-4.6-gnu/arch/metag/include/asm/tbx.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/metag/include/asm/tbx.h	2016-07-24 15:23:50.000000000 -0400
@@ -668,7 +668,7 @@ typedef union _tbires_tag_ {
    
    State.Sig.TrigMask will indicate the bits set within TXMASKI at
           the time of the handler call that have all been cleared to prevent
-          nested interrupt occuring immediately.
+          nested interrupt occurring immediately.
    
    State.Sig.SaveMask is a bit-mask which will be set to Zero when a trigger
           occurs at background level and TBICTX_CRIT_BIT and optionally
@@ -1083,7 +1083,7 @@ TBIRES __TBINestInts( TBIRES State, void
 /* This routine causes the TBICTX structure specified in State.Sig.pCtx to
    be restored. This implies that execution will not return to the caller.
    The State.Sig.TrigMask field will be restored during the context switch
-   such that any immediately occuring interrupts occur in the context of the
+   such that any immediately occurring interrupts occur in the context of the
    newly specified task. The State.Sig.SaveMask parameter is ignored. */
 void __TBIASyncResume( TBIRES State );
 
@@ -1305,7 +1305,7 @@ extern const char __TBISigNames[];
 
 /* 
  * Calculate linear PC value from real PC and Minim mode control, the LSB of
- * the result returned indicates if address compression has occured.
+ * the result returned indicates if address compression has occurred.
  */
 #ifndef __ASSEMBLY__
 #define METAG_LINPC( PCVal )                                              (\
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/metag/include/uapi/asm/unistd.h linux-libre-4.7-gnu/arch/metag/include/uapi/asm/unistd.h
--- linux-libre-4.6-gnu/arch/metag/include/uapi/asm/unistd.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/metag/include/uapi/asm/unistd.h	2016-07-24 15:23:50.000000000 -0400
@@ -7,6 +7,8 @@
  * (at your option) any later version.
  */
 
+#define __ARCH_WANT_RENAMEAT
+
 /* Use the standard ABI for syscalls. */
 #include <asm-generic/unistd.h>
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/metag/Kconfig linux-libre-4.7-gnu/arch/metag/Kconfig
--- linux-libre-4.6-gnu/arch/metag/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/metag/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -11,6 +11,7 @@ config METAG
 	select HAVE_DEBUG_KMEMLEAK
 	select HAVE_DEBUG_STACKOVERFLOW
 	select HAVE_DYNAMIC_FTRACE
+	select HAVE_EXIT_THREAD
 	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_FUNCTION_TRACER
 	select HAVE_KERNEL_BZIP2
@@ -29,6 +30,7 @@ config METAG
 	select OF
 	select OF_EARLY_FLATTREE
 	select SPARSE_IRQ
+	select CPU_NO_EFFICIENT_FFS
 
 config STACKTRACE_SUPPORT
 	def_bool y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/metag/Kconfig.soc linux-libre-4.7-gnu/arch/metag/Kconfig.soc
--- linux-libre-4.6-gnu/arch/metag/Kconfig.soc	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/metag/Kconfig.soc	2016-07-24 15:23:50.000000000 -0400
@@ -16,7 +16,6 @@ config META21_FPGA
 
 config SOC_TZ1090
 	bool "Toumaz Xenif TZ1090 SoC (Comet)"
-	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select IMGPDC_IRQ
 	select METAG_LNKGET_AROUND_CACHE
 	select METAG_META21
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/metag/kernel/ftrace.c linux-libre-4.7-gnu/arch/metag/kernel/ftrace.c
--- linux-libre-4.6-gnu/arch/metag/kernel/ftrace.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/metag/kernel/ftrace.c	2016-07-24 15:23:50.000000000 -0400
@@ -115,7 +115,6 @@ int ftrace_make_call(struct dyn_ftrace *
 	return ftrace_modify_code(ip, old, new);
 }
 
-/* run from kstop_machine */
 int __init ftrace_dyn_arch_init(void)
 {
 	return 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/metag/kernel/perf/perf_event.c linux-libre-4.7-gnu/arch/metag/kernel/perf/perf_event.c
--- linux-libre-4.6-gnu/arch/metag/kernel/perf/perf_event.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/metag/kernel/perf/perf_event.c	2016-07-24 15:23:50.000000000 -0400
@@ -618,6 +618,8 @@ static void metag_pmu_enable_counter(str
 
 	/* Check for a core internal or performance channel event. */
 	if (tmp) {
+		/* PERF_ICORE/PERF_CHAN only exist since Meta2 */
+#ifdef METAC_2_1
 		void *perf_addr;
 
 		/*
@@ -640,6 +642,7 @@ static void metag_pmu_enable_counter(str
 
 		if (perf_addr)
 			metag_out32((config & 0x0f), perf_addr);
+#endif
 
 		/*
 		 * Now we use the high nibble as the performance event to
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/metag/kernel/perf_callchain.c linux-libre-4.7-gnu/arch/metag/kernel/perf_callchain.c
--- linux-libre-4.6-gnu/arch/metag/kernel/perf_callchain.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/metag/kernel/perf_callchain.c	2016-07-24 15:23:50.000000000 -0400
@@ -29,7 +29,7 @@ static bool is_valid_call(unsigned long
 
 static struct metag_frame __user *
 user_backtrace(struct metag_frame __user *user_frame,
-	       struct perf_callchain_entry *entry)
+	       struct perf_callchain_entry_ctx *entry)
 {
 	struct metag_frame frame;
 	unsigned long calladdr;
@@ -56,7 +56,7 @@ user_backtrace(struct metag_frame __user
 }
 
 void
-perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
+perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs)
 {
 	unsigned long sp = regs->ctx.AX[0].U0;
 	struct metag_frame __user *frame;
@@ -65,7 +65,7 @@ perf_callchain_user(struct perf_callchai
 
 	--frame;
 
-	while ((entry->nr < PERF_MAX_STACK_DEPTH) && frame)
+	while ((entry->nr < entry->max_stack) && frame)
 		frame = user_backtrace(frame, entry);
 }
 
@@ -78,13 +78,13 @@ static int
 callchain_trace(struct stackframe *fr,
 		void *data)
 {
-	struct perf_callchain_entry *entry = data;
+	struct perf_callchain_entry_ctx *entry = data;
 	perf_callchain_store(entry, fr->pc);
 	return 0;
 }
 
 void
-perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs)
+perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs)
 {
 	struct stackframe fr;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/metag/kernel/process.c linux-libre-4.7-gnu/arch/metag/kernel/process.c
--- linux-libre-4.6-gnu/arch/metag/kernel/process.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/metag/kernel/process.c	2016-07-24 15:23:50.000000000 -0400
@@ -345,10 +345,10 @@ void flush_thread(void)
 /*
  * Free current thread data structures etc.
  */
-void exit_thread(void)
+void exit_thread(struct task_struct *tsk)
 {
-	clear_fpu(&current->thread);
-	clear_dsp(&current->thread);
+	clear_fpu(&tsk->thread);
+	clear_dsp(&tsk->thread);
 }
 
 /* TODO: figure out how to unwind the kernel stack here to figure out
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/metag/mm/hugetlbpage.c linux-libre-4.7-gnu/arch/metag/mm/hugetlbpage.c
--- linux-libre-4.6-gnu/arch/metag/mm/hugetlbpage.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/metag/mm/hugetlbpage.c	2016-07-24 15:23:50.000000000 -0400
@@ -239,6 +239,7 @@ static __init int setup_hugepagesz(char
 	if (ps == (1 << HPAGE_SHIFT)) {
 		hugetlb_add_hstate(HPAGE_SHIFT - PAGE_SHIFT);
 	} else {
+		hugetlb_bad_size();
 		pr_err("hugepagesz: Unsupported page size %lu M\n",
 		       ps >> 20);
 		return 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/metag/tbx/tbipcx.S linux-libre-4.7-gnu/arch/metag/tbx/tbipcx.S
--- linux-libre-4.6-gnu/arch/metag/tbx/tbipcx.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/metag/tbx/tbipcx.S	2016-07-24 15:23:50.000000000 -0400
@@ -15,7 +15,7 @@
 #include <asm/tbx.h>
 
 /* BEGIN HACK */
-/* define these for now while doing inital conversion to GAS 
+/* define these for now while doing initial conversion to GAS
    will fix properly later */
 
 /* Signal identifiers always have the TBID_SIGNAL_BIT set and contain the
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/metag/tbx/tbisoft.S linux-libre-4.7-gnu/arch/metag/tbx/tbisoft.S
--- linux-libre-4.6-gnu/arch/metag/tbx/tbisoft.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/metag/tbx/tbisoft.S	2016-07-24 15:23:50.000000000 -0400
@@ -56,7 +56,7 @@ ___TBIJumpX:
 /*
  * TBIRES __TBISwitch( TBIRES Switch, PTBICTX *rpSaveCtx )
  *
- * Software syncronous context switch between soft threads, save only the
+ * Software synchronous context switch between soft threads, save only the
  * registers which are actually valid on call entry.
  *
  *	A0FrP, D0RtP, D0.5, D0.6, D0.7      - Saved on stack
@@ -76,7 +76,7 @@ $LSwitchStart:
 	SETL	[A0StP+#8++],D0FrT,D1RtP
 /*
  * Save current frame state - we save all regs because we don't want
- * uninitialised crap in the TBICTX structure that the asyncronous resumption
+ * uninitialised crap in the TBICTX structure that the asynchronous resumption
  * of a thread will restore.
  */
 	MOVT	D1Re0,#HI($LSwitchExit)		/* ASync resume point here */
@@ -117,7 +117,7 @@ $LSwitchExit:
  * This routine causes the TBICTX structure specified in State.Sig.pCtx to
  * be restored. This implies that execution will not return to the caller.
  * The State.Sig.TrigMask field will be ored into TXMASKI during the
- * context switch such that any immediately occuring interrupts occur in
+ * context switch such that any immediately occurring interrupts occur in
  * the context of the newly specified task. The State.Sig.SaveMask parameter
  * is ignored.
  */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/microblaze/include/asm/hash.h linux-libre-4.7-gnu/arch/microblaze/include/asm/hash.h
--- linux-libre-4.6-gnu/arch/microblaze/include/asm/hash.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/microblaze/include/asm/hash.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,81 @@
+#ifndef _ASM_HASH_H
+#define _ASM_HASH_H
+
+/*
+ * Fortunately, most people who want to run Linux on Microblaze enable
+ * both multiplier and barrel shifter, but omitting them is technically
+ * a supported configuration.
+ *
+ * With just a barrel shifter, we can implement an efficient constant
+ * multiply using shifts and adds.  GCC can find a 9-step solution, but
+ * this 6-step solution was found by Yevgen Voronenko's implementation
+ * of the Hcub algorithm at http://spiral.ece.cmu.edu/mcm/gen.html.
+ *
+ * That software is really not designed for a single multiplier this large,
+ * but if you run it enough times with different seeds, it'll find several
+ * 6-shift, 6-add sequences for computing x * 0x61C88647.  They are all
+ *	c = (x << 19) + x;
+ *	a = (x <<  9) + c;
+ *	b = (x << 23) + a;
+ *	return (a<<11) + (b<<6) + (c<<3) - b;
+ * with variations on the order of the final add.
+ *
+ * Without even a shifter, it's hopless; any hash function will suck.
+ */
+
+#if CONFIG_XILINX_MICROBLAZE0_USE_HW_MUL == 0
+
+#define HAVE_ARCH__HASH_32 1
+
+/* Multiply by GOLDEN_RATIO_32 = 0x61C88647 */
+static inline u32 __attribute_const__ __hash_32(u32 a)
+{
+#if CONFIG_XILINX_MICROBLAZE0_USE_BARREL
+	unsigned int b, c;
+
+	/* Phase 1: Compute three intermediate values */
+	b =  a << 23;
+	c = (a << 19) + a;
+	a = (a <<  9) + c;
+	b += a;
+
+	/* Phase 2: Compute (a << 11) + (b << 6) + (c << 3) - b */
+	a <<= 5;
+	a += b;		/* (a << 5) + b */
+	a <<= 3;
+	a += c;		/* (a << 8) + (b << 3) + c */
+	a <<= 3;
+	return a - b;	/* (a << 11) + (b << 6) + (c << 3) - b */
+#else
+	/*
+	 * "This is really going to hurt."
+	 *
+	 * Without a barrel shifter, left shifts are implemented as
+	 * repeated additions, and the best we can do is an optimal
+	 * addition-subtraction chain.  This one is not known to be
+	 * optimal, but at 37 steps, it's decent for a 31-bit multiplier.
+	 *
+	 * Question: given its size (37*4 = 148 bytes per instance),
+	 * and slowness, is this worth having inline?
+	 */
+	unsigned int b, c, d;
+
+	b = a << 4;	/* 4    */
+	c = b << 1;	/* 1  5 */
+	b += a;		/* 1  6 */
+	c += b;		/* 1  7 */
+	c <<= 3;	/* 3 10 */
+	c -= a;		/* 1 11 */
+	d = c << 7;	/* 7 18 */
+	d += b;		/* 1 19 */
+	d <<= 8;	/* 8 27 */
+	d += a;		/* 1 28 */
+	d <<= 1;	/* 1 29 */
+	d += b;		/* 1 30 */
+	d <<= 6;	/* 6 36 */
+	return d + c;	/* 1 37 total instructions*/
+#endif
+}
+
+#endif /* !CONFIG_XILINX_MICROBLAZE0_USE_HW_MUL */
+#endif /* _ASM_HASH_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/microblaze/include/asm/pgalloc.h linux-libre-4.7-gnu/arch/microblaze/include/asm/pgalloc.h
--- linux-libre-4.6-gnu/arch/microblaze/include/asm/pgalloc.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/microblaze/include/asm/pgalloc.h	2016-07-24 15:23:50.000000000 -0400
@@ -116,9 +116,9 @@ static inline struct page *pte_alloc_one
 	struct page *ptepage;
 
 #ifdef CONFIG_HIGHPTE
-	int flags = GFP_KERNEL | __GFP_HIGHMEM | __GFP_REPEAT;
+	int flags = GFP_KERNEL | __GFP_HIGHMEM;
 #else
-	int flags = GFP_KERNEL | __GFP_REPEAT;
+	int flags = GFP_KERNEL;
 #endif
 
 	ptepage = alloc_pages(flags, 0);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/microblaze/include/asm/processor.h linux-libre-4.7-gnu/arch/microblaze/include/asm/processor.h
--- linux-libre-4.6-gnu/arch/microblaze/include/asm/processor.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/microblaze/include/asm/processor.h	2016-07-24 15:23:50.000000000 -0400
@@ -70,11 +70,6 @@ static inline void release_thread(struct
 {
 }
 
-/* Free all resources held by a thread. */
-static inline void exit_thread(void)
-{
-}
-
 extern unsigned long thread_saved_pc(struct task_struct *t);
 
 extern unsigned long get_wchan(struct task_struct *p);
@@ -127,11 +122,6 @@ static inline void release_thread(struct
 {
 }
 
-/* Free current thread data structures etc.  */
-static inline void exit_thread(void)
-{
-}
-
 /* Return saved (kernel) PC of a blocked thread.  */
 #  define thread_saved_pc(tsk)	\
 	((tsk)->thread.regs ? (tsk)->thread.regs->r15 : 0)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/microblaze/include/asm/unistd.h linux-libre-4.7-gnu/arch/microblaze/include/asm/unistd.h
--- linux-libre-4.6-gnu/arch/microblaze/include/asm/unistd.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/microblaze/include/asm/unistd.h	2016-07-24 15:23:50.000000000 -0400
@@ -38,6 +38,6 @@
 
 #endif /* __ASSEMBLY__ */
 
-#define __NR_syscalls         389
+#define __NR_syscalls         392
 
 #endif /* _ASM_MICROBLAZE_UNISTD_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/microblaze/include/uapi/asm/unistd.h linux-libre-4.7-gnu/arch/microblaze/include/uapi/asm/unistd.h
--- linux-libre-4.6-gnu/arch/microblaze/include/uapi/asm/unistd.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/microblaze/include/uapi/asm/unistd.h	2016-07-24 15:23:50.000000000 -0400
@@ -404,5 +404,8 @@
 #define __NR_memfd_create	386
 #define __NR_bpf		387
 #define __NR_execveat		388
+#define __NR_userfaultfd	389
+#define __NR_membarrier		390
+#define __NR_mlock2		391
 
 #endif /* _UAPI_ASM_MICROBLAZE_UNISTD_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/microblaze/Kconfig linux-libre-4.7-gnu/arch/microblaze/Kconfig
--- linux-libre-4.6-gnu/arch/microblaze/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/microblaze/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -16,6 +16,7 @@ config MICROBLAZE
 	select GENERIC_IRQ_SHOW
 	select GENERIC_PCI_IOMAP
 	select GENERIC_SCHED_CLOCK
+	select HAVE_ARCH_HASH
 	select HAVE_ARCH_KGDB
 	select HAVE_DEBUG_KMEMLEAK
 	select HAVE_DMA_API_DEBUG
@@ -32,6 +33,7 @@ config MICROBLAZE
 	select OF_EARLY_FLATTREE
 	select TRACING_SUPPORT
 	select VIRT_TO_BUS
+	select CPU_NO_EFFICIENT_FFS
 
 config SWAP
 	def_bool n
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/microblaze/kernel/syscall_table.S linux-libre-4.7-gnu/arch/microblaze/kernel/syscall_table.S
--- linux-libre-4.6-gnu/arch/microblaze/kernel/syscall_table.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/microblaze/kernel/syscall_table.S	2016-07-24 15:23:50.000000000 -0400
@@ -389,3 +389,6 @@ ENTRY(sys_call_table)
 	.long sys_memfd_create
 	.long sys_bpf
 	.long sys_execveat
+	.long sys_userfaultfd
+	.long sys_membarrier		/* 390 */
+	.long sys_mlock2
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/microblaze/mm/pgtable.c linux-libre-4.7-gnu/arch/microblaze/mm/pgtable.c
--- linux-libre-4.6-gnu/arch/microblaze/mm/pgtable.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/microblaze/mm/pgtable.c	2016-07-24 15:23:50.000000000 -0400
@@ -239,8 +239,7 @@ __init_refok pte_t *pte_alloc_one_kernel
 {
 	pte_t *pte;
 	if (mem_init_done) {
-		pte = (pte_t *)__get_free_page(GFP_KERNEL |
-					__GFP_REPEAT | __GFP_ZERO);
+		pte = (pte_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
 	} else {
 		pte = (pte_t *)early_get_page();
 		if (pte)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/microblaze/pci/pci-common.c linux-libre-4.7-gnu/arch/microblaze/pci/pci-common.c
--- linux-libre-4.6-gnu/arch/microblaze/pci/pci-common.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/microblaze/pci/pci-common.c	2016-07-24 15:23:50.000000000 -0400
@@ -48,6 +48,8 @@ static int global_phb_number;		/* Global
 resource_size_t isa_mem_base;
 
 unsigned long isa_io_base;
+EXPORT_SYMBOL(isa_io_base);
+
 static int pci_bus_count;
 
 struct pci_controller *pcibios_alloc_controller(struct device_node *dev)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/alchemy/common/clock.c linux-libre-4.7-gnu/arch/mips/alchemy/common/clock.c
--- linux-libre-4.6-gnu/arch/mips/alchemy/common/clock.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/alchemy/common/clock.c	2016-07-24 15:23:50.000000000 -0400
@@ -1043,8 +1043,7 @@ static int __init alchemy_clk_init(void)
 
 	/* Root of the Alchemy clock tree: external 12MHz crystal osc */
 	c = clk_register_fixed_rate(NULL, ALCHEMY_ROOT_CLK, NULL,
-					   CLK_IS_ROOT,
-					   ALCHEMY_ROOTCLK_RATE);
+					   0, ALCHEMY_ROOTCLK_RATE);
 	ERRCK(c)
 
 	/* CPU core clock */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/alchemy/Kconfig linux-libre-4.7-gnu/arch/mips/alchemy/Kconfig
--- linux-libre-4.6-gnu/arch/mips/alchemy/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/alchemy/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -20,7 +20,7 @@ config MIPS_MTX1
 
 config MIPS_DB1XXX
 	bool "Alchemy DB1XXX / PB1XXX boards"
-	select ARCH_REQUIRE_GPIOLIB
+	select GPIOLIB
 	select HW_HAS_PCI
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_HAS_EARLY_PRINTK
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/ath79/clock.c linux-libre-4.7-gnu/arch/mips/ath79/clock.c
--- linux-libre-4.6-gnu/arch/mips/ath79/clock.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/ath79/clock.c	2016-07-24 15:23:50.000000000 -0400
@@ -18,17 +18,21 @@
 #include <linux/clk.h>
 #include <linux/clkdev.h>
 #include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <dt-bindings/clock/ath79-clk.h>
 
 #include <asm/div64.h>
 
 #include <asm/mach-ath79/ath79.h>
 #include <asm/mach-ath79/ar71xx_regs.h>
 #include "common.h"
+#include "machtypes.h"
 
 #define AR71XX_BASE_FREQ	40000000
 #define AR724X_BASE_FREQ	40000000
 
-static struct clk *clks[3];
+static struct clk *clks[ATH79_CLK_END];
 static struct clk_onecell_data clk_data = {
 	.clks = clks,
 	.clk_num = ARRAY_SIZE(clks),
@@ -40,7 +44,7 @@ static struct clk *__init ath79_add_sys_
 	struct clk *clk;
 	int err;
 
-	clk = clk_register_fixed_rate(NULL, id, NULL, CLK_IS_ROOT, rate);
+	clk = clk_register_fixed_rate(NULL, id, NULL, 0, rate);
 	if (!clk)
 		panic("failed to allocate %s clock structure", id);
 
@@ -78,107 +82,139 @@ static void __init ar71xx_clocks_init(vo
 	ahb_rate = cpu_rate / div;
 
 	ath79_add_sys_clkdev("ref", ref_rate);
-	clks[0] = ath79_add_sys_clkdev("cpu", cpu_rate);
-	clks[1] = ath79_add_sys_clkdev("ddr", ddr_rate);
-	clks[2] = ath79_add_sys_clkdev("ahb", ahb_rate);
+	clks[ATH79_CLK_CPU] = ath79_add_sys_clkdev("cpu", cpu_rate);
+	clks[ATH79_CLK_DDR] = ath79_add_sys_clkdev("ddr", ddr_rate);
+	clks[ATH79_CLK_AHB] = ath79_add_sys_clkdev("ahb", ahb_rate);
 
 	clk_add_alias("wdt", NULL, "ahb", NULL);
 	clk_add_alias("uart", NULL, "ahb", NULL);
 }
 
-static void __init ar724x_clocks_init(void)
+static struct clk * __init ath79_reg_ffclk(const char *name,
+		const char *parent_name, unsigned int mult, unsigned int div)
 {
-	unsigned long ref_rate;
-	unsigned long cpu_rate;
-	unsigned long ddr_rate;
-	unsigned long ahb_rate;
-	u32 pll;
-	u32 freq;
-	u32 div;
+	struct clk *clk;
 
-	ref_rate = AR724X_BASE_FREQ;
-	pll = ath79_pll_rr(AR724X_PLL_REG_CPU_CONFIG);
+	clk = clk_register_fixed_factor(NULL, name, parent_name, 0, mult, div);
+	if (!clk)
+		panic("failed to allocate %s clock structure", name);
 
-	div = ((pll >> AR724X_PLL_FB_SHIFT) & AR724X_PLL_FB_MASK);
-	freq = div * ref_rate;
+	return clk;
+}
+
+static void __init ar724x_clk_init(struct clk *ref_clk, void __iomem *pll_base)
+{
+	u32 pll;
+	u32 mult, div, ddr_div, ahb_div;
+
+	pll = __raw_readl(pll_base + AR724X_PLL_REG_CPU_CONFIG);
 
+	mult = ((pll >> AR724X_PLL_FB_SHIFT) & AR724X_PLL_FB_MASK);
 	div = ((pll >> AR724X_PLL_REF_DIV_SHIFT) & AR724X_PLL_REF_DIV_MASK) * 2;
-	freq /= div;
 
-	cpu_rate = freq;
+	ddr_div = ((pll >> AR724X_DDR_DIV_SHIFT) & AR724X_DDR_DIV_MASK) + 1;
+	ahb_div = (((pll >> AR724X_AHB_DIV_SHIFT) & AR724X_AHB_DIV_MASK) + 1) * 2;
 
-	div = ((pll >> AR724X_DDR_DIV_SHIFT) & AR724X_DDR_DIV_MASK) + 1;
-	ddr_rate = freq / div;
+	clks[ATH79_CLK_CPU] = ath79_reg_ffclk("cpu", "ref", mult, div);
+	clks[ATH79_CLK_DDR] = ath79_reg_ffclk("ddr", "ref", mult, div * ddr_div);
+	clks[ATH79_CLK_AHB] = ath79_reg_ffclk("ahb", "ref", mult, div * ahb_div);
+}
 
-	div = (((pll >> AR724X_AHB_DIV_SHIFT) & AR724X_AHB_DIV_MASK) + 1) * 2;
-	ahb_rate = cpu_rate / div;
+static void __init ar724x_clocks_init(void)
+{
+	struct clk *ref_clk;
 
-	ath79_add_sys_clkdev("ref", ref_rate);
-	clks[0] = ath79_add_sys_clkdev("cpu", cpu_rate);
-	clks[1] = ath79_add_sys_clkdev("ddr", ddr_rate);
-	clks[2] = ath79_add_sys_clkdev("ahb", ahb_rate);
+	ref_clk = ath79_add_sys_clkdev("ref", AR724X_BASE_FREQ);
+
+	ar724x_clk_init(ref_clk, ath79_pll_base);
+
+	/* just make happy plat_time_init() from arch/mips/ath79/setup.c */
+	clk_register_clkdev(clks[ATH79_CLK_CPU], "cpu", NULL);
+	clk_register_clkdev(clks[ATH79_CLK_DDR], "ddr", NULL);
+	clk_register_clkdev(clks[ATH79_CLK_AHB], "ahb", NULL);
 
 	clk_add_alias("wdt", NULL, "ahb", NULL);
 	clk_add_alias("uart", NULL, "ahb", NULL);
 }
 
-static void __init ar933x_clocks_init(void)
+static void __init ar9330_clk_init(struct clk *ref_clk, void __iomem *pll_base)
 {
-	unsigned long ref_rate;
-	unsigned long cpu_rate;
-	unsigned long ddr_rate;
-	unsigned long ahb_rate;
 	u32 clock_ctrl;
-	u32 cpu_config;
-	u32 freq;
-	u32 t;
+	u32 ref_div;
+	u32 ninit_mul;
+	u32 out_div;
 
-	t = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP);
-	if (t & AR933X_BOOTSTRAP_REF_CLK_40)
-		ref_rate = (40 * 1000 * 1000);
-	else
-		ref_rate = (25 * 1000 * 1000);
+	u32 cpu_div;
+	u32 ddr_div;
+	u32 ahb_div;
 
-	clock_ctrl = ath79_pll_rr(AR933X_PLL_CLOCK_CTRL_REG);
+	clock_ctrl = __raw_readl(pll_base + AR933X_PLL_CLOCK_CTRL_REG);
 	if (clock_ctrl & AR933X_PLL_CLOCK_CTRL_BYPASS) {
-		cpu_rate = ref_rate;
-		ahb_rate = ref_rate;
-		ddr_rate = ref_rate;
+		ref_div = 1;
+		ninit_mul = 1;
+		out_div = 1;
+
+		cpu_div = 1;
+		ddr_div = 1;
+		ahb_div = 1;
 	} else {
-		cpu_config = ath79_pll_rr(AR933X_PLL_CPU_CONFIG_REG);
+		u32 cpu_config;
+		u32 t;
+
+		cpu_config = __raw_readl(pll_base + AR933X_PLL_CPU_CONFIG_REG);
 
 		t = (cpu_config >> AR933X_PLL_CPU_CONFIG_REFDIV_SHIFT) &
 		    AR933X_PLL_CPU_CONFIG_REFDIV_MASK;
-		freq = ref_rate / t;
+		ref_div = t;
 
-		t = (cpu_config >> AR933X_PLL_CPU_CONFIG_NINT_SHIFT) &
+		ninit_mul = (cpu_config >> AR933X_PLL_CPU_CONFIG_NINT_SHIFT) &
 		    AR933X_PLL_CPU_CONFIG_NINT_MASK;
-		freq *= t;
 
 		t = (cpu_config >> AR933X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
 		    AR933X_PLL_CPU_CONFIG_OUTDIV_MASK;
 		if (t == 0)
 			t = 1;
 
-		freq >>= t;
+		out_div = (1 << t);
 
-		t = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_CPU_DIV_SHIFT) &
+		cpu_div = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_CPU_DIV_SHIFT) &
 		     AR933X_PLL_CLOCK_CTRL_CPU_DIV_MASK) + 1;
-		cpu_rate = freq / t;
 
-		t = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_DDR_DIV_SHIFT) &
+		ddr_div = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_DDR_DIV_SHIFT) &
 		      AR933X_PLL_CLOCK_CTRL_DDR_DIV_MASK) + 1;
-		ddr_rate = freq / t;
 
-		t = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_AHB_DIV_SHIFT) &
+		ahb_div = ((clock_ctrl >> AR933X_PLL_CLOCK_CTRL_AHB_DIV_SHIFT) &
 		     AR933X_PLL_CLOCK_CTRL_AHB_DIV_MASK) + 1;
-		ahb_rate = freq / t;
 	}
 
-	ath79_add_sys_clkdev("ref", ref_rate);
-	clks[0] = ath79_add_sys_clkdev("cpu", cpu_rate);
-	clks[1] = ath79_add_sys_clkdev("ddr", ddr_rate);
-	clks[2] = ath79_add_sys_clkdev("ahb", ahb_rate);
+	clks[ATH79_CLK_CPU] = ath79_reg_ffclk("cpu", "ref",
+					ninit_mul, ref_div * out_div * cpu_div);
+	clks[ATH79_CLK_DDR] = ath79_reg_ffclk("ddr", "ref",
+					ninit_mul, ref_div * out_div * ddr_div);
+	clks[ATH79_CLK_AHB] = ath79_reg_ffclk("ahb", "ref",
+					ninit_mul, ref_div * out_div * ahb_div);
+}
+
+static void __init ar933x_clocks_init(void)
+{
+	struct clk *ref_clk;
+	unsigned long ref_rate;
+	u32 t;
+
+	t = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP);
+	if (t & AR933X_BOOTSTRAP_REF_CLK_40)
+		ref_rate = (40 * 1000 * 1000);
+	else
+		ref_rate = (25 * 1000 * 1000);
+
+	ref_clk = ath79_add_sys_clkdev("ref", ref_rate);
+
+	ar9330_clk_init(ref_clk, ath79_pll_base);
+
+	/* just make happy plat_time_init() from arch/mips/ath79/setup.c */
+	clk_register_clkdev(clks[ATH79_CLK_CPU], "cpu", NULL);
+	clk_register_clkdev(clks[ATH79_CLK_DDR], "ddr", NULL);
+	clk_register_clkdev(clks[ATH79_CLK_AHB], "ahb", NULL);
 
 	clk_add_alias("wdt", NULL, "ahb", NULL);
 	clk_add_alias("uart", NULL, "ref", NULL);
@@ -310,9 +346,9 @@ static void __init ar934x_clocks_init(vo
 		ahb_rate = cpu_pll / (postdiv + 1);
 
 	ath79_add_sys_clkdev("ref", ref_rate);
-	clks[0] = ath79_add_sys_clkdev("cpu", cpu_rate);
-	clks[1] = ath79_add_sys_clkdev("ddr", ddr_rate);
-	clks[2] = ath79_add_sys_clkdev("ahb", ahb_rate);
+	clks[ATH79_CLK_CPU] = ath79_add_sys_clkdev("cpu", cpu_rate);
+	clks[ATH79_CLK_DDR] = ath79_add_sys_clkdev("ddr", ddr_rate);
+	clks[ATH79_CLK_AHB] = ath79_add_sys_clkdev("ahb", ahb_rate);
 
 	clk_add_alias("wdt", NULL, "ref", NULL);
 	clk_add_alias("uart", NULL, "ref", NULL);
@@ -397,9 +433,9 @@ static void __init qca955x_clocks_init(v
 		ahb_rate = cpu_pll / (postdiv + 1);
 
 	ath79_add_sys_clkdev("ref", ref_rate);
-	clks[0] = ath79_add_sys_clkdev("cpu", cpu_rate);
-	clks[1] = ath79_add_sys_clkdev("ddr", ddr_rate);
-	clks[2] = ath79_add_sys_clkdev("ahb", ahb_rate);
+	clks[ATH79_CLK_CPU] = ath79_add_sys_clkdev("cpu", cpu_rate);
+	clks[ATH79_CLK_DDR] = ath79_add_sys_clkdev("ddr", ddr_rate);
+	clks[ATH79_CLK_AHB] = ath79_add_sys_clkdev("ahb", ahb_rate);
 
 	clk_add_alias("wdt", NULL, "ref", NULL);
 	clk_add_alias("uart", NULL, "ref", NULL);
@@ -419,8 +455,6 @@ void __init ath79_clocks_init(void)
 		qca955x_clocks_init();
 	else
 		BUG();
-
-	of_clk_init(NULL);
 }
 
 unsigned long __init
@@ -447,8 +481,49 @@ static void __init ath79_clocks_init_dt(
 
 CLK_OF_DECLARE(ar7100, "qca,ar7100-pll", ath79_clocks_init_dt);
 CLK_OF_DECLARE(ar7240, "qca,ar7240-pll", ath79_clocks_init_dt);
-CLK_OF_DECLARE(ar9130, "qca,ar9130-pll", ath79_clocks_init_dt);
-CLK_OF_DECLARE(ar9330, "qca,ar9330-pll", ath79_clocks_init_dt);
 CLK_OF_DECLARE(ar9340, "qca,ar9340-pll", ath79_clocks_init_dt);
 CLK_OF_DECLARE(ar9550, "qca,qca9550-pll", ath79_clocks_init_dt);
+
+static void __init ath79_clocks_init_dt_ng(struct device_node *np)
+{
+	struct clk *ref_clk;
+	void __iomem *pll_base;
+	const char *dnfn = of_node_full_name(np);
+
+	ref_clk = of_clk_get(np, 0);
+	if (IS_ERR(ref_clk)) {
+		pr_err("%s: of_clk_get failed\n", dnfn);
+		goto err;
+	}
+
+	pll_base = of_iomap(np, 0);
+	if (!pll_base) {
+		pr_err("%s: can't map pll registers\n", dnfn);
+		goto err_clk;
+	}
+
+	if (of_device_is_compatible(np, "qca,ar9130-pll"))
+		ar724x_clk_init(ref_clk, pll_base);
+	else if (of_device_is_compatible(np, "qca,ar9330-pll"))
+		ar9330_clk_init(ref_clk, pll_base);
+	else {
+		pr_err("%s: could not find any appropriate clk_init()\n", dnfn);
+		goto err_clk;
+	}
+
+	if (of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data)) {
+		pr_err("%s: could not register clk provider\n", dnfn);
+		goto err_clk;
+	}
+
+	return;
+
+err_clk:
+	clk_put(ref_clk);
+
+err:
+	return;
+}
+CLK_OF_DECLARE(ar9130_clk, "qca,ar9130-pll", ath79_clocks_init_dt_ng);
+CLK_OF_DECLARE(ar9330_clk, "qca,ar9330-pll", ath79_clocks_init_dt_ng);
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/ath79/common.c linux-libre-4.7-gnu/arch/mips/ath79/common.c
--- linux-libre-4.6-gnu/arch/mips/ath79/common.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/ath79/common.c	2016-07-24 15:23:50.000000000 -0400
@@ -46,12 +46,12 @@ void ath79_ddr_ctrl_init(void)
 {
 	ath79_ddr_base = ioremap_nocache(AR71XX_DDR_CTRL_BASE,
 					 AR71XX_DDR_CTRL_SIZE);
-	if (soc_is_ar71xx() || soc_is_ar934x()) {
-		ath79_ddr_wb_flush_base = ath79_ddr_base + 0x9c;
-		ath79_ddr_pci_win_base = ath79_ddr_base + 0x7c;
-	} else {
+	if (soc_is_ar913x() || soc_is_ar724x() || soc_is_ar933x()) {
 		ath79_ddr_wb_flush_base = ath79_ddr_base + 0x7c;
 		ath79_ddr_pci_win_base = 0;
+	} else {
+		ath79_ddr_wb_flush_base = ath79_ddr_base + 0x9c;
+		ath79_ddr_pci_win_base = ath79_ddr_base + 0x7c;
 	}
 }
 EXPORT_SYMBOL_GPL(ath79_ddr_ctrl_init);
@@ -76,14 +76,14 @@ void ath79_ddr_set_pci_windows(void)
 {
 	BUG_ON(!ath79_ddr_pci_win_base);
 
-	__raw_writel(AR71XX_PCI_WIN0_OFFS, ath79_ddr_pci_win_base + 0);
-	__raw_writel(AR71XX_PCI_WIN1_OFFS, ath79_ddr_pci_win_base + 1);
-	__raw_writel(AR71XX_PCI_WIN2_OFFS, ath79_ddr_pci_win_base + 2);
-	__raw_writel(AR71XX_PCI_WIN3_OFFS, ath79_ddr_pci_win_base + 3);
-	__raw_writel(AR71XX_PCI_WIN4_OFFS, ath79_ddr_pci_win_base + 4);
-	__raw_writel(AR71XX_PCI_WIN5_OFFS, ath79_ddr_pci_win_base + 5);
-	__raw_writel(AR71XX_PCI_WIN6_OFFS, ath79_ddr_pci_win_base + 6);
-	__raw_writel(AR71XX_PCI_WIN7_OFFS, ath79_ddr_pci_win_base + 7);
+	__raw_writel(AR71XX_PCI_WIN0_OFFS, ath79_ddr_pci_win_base + 0x0);
+	__raw_writel(AR71XX_PCI_WIN1_OFFS, ath79_ddr_pci_win_base + 0x4);
+	__raw_writel(AR71XX_PCI_WIN2_OFFS, ath79_ddr_pci_win_base + 0x8);
+	__raw_writel(AR71XX_PCI_WIN3_OFFS, ath79_ddr_pci_win_base + 0xc);
+	__raw_writel(AR71XX_PCI_WIN4_OFFS, ath79_ddr_pci_win_base + 0x10);
+	__raw_writel(AR71XX_PCI_WIN5_OFFS, ath79_ddr_pci_win_base + 0x14);
+	__raw_writel(AR71XX_PCI_WIN6_OFFS, ath79_ddr_pci_win_base + 0x18);
+	__raw_writel(AR71XX_PCI_WIN7_OFFS, ath79_ddr_pci_win_base + 0x1c);
 }
 EXPORT_SYMBOL_GPL(ath79_ddr_set_pci_windows);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/ath79/early_printk.c linux-libre-4.7-gnu/arch/mips/ath79/early_printk.c
--- linux-libre-4.6-gnu/arch/mips/ath79/early_printk.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/ath79/early_printk.c	2016-07-24 15:23:50.000000000 -0400
@@ -31,13 +31,15 @@ static inline void prom_putchar_wait(voi
 	} while (1);
 }
 
+#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+
 static void prom_putchar_ar71xx(unsigned char ch)
 {
 	void __iomem *base = (void __iomem *)(KSEG1ADDR(AR71XX_UART_BASE));
 
-	prom_putchar_wait(base + UART_LSR * 4, UART_LSR_THRE, UART_LSR_THRE);
+	prom_putchar_wait(base + UART_LSR * 4, BOTH_EMPTY, BOTH_EMPTY);
 	__raw_writel(ch, base + UART_TX * 4);
-	prom_putchar_wait(base + UART_LSR * 4, UART_LSR_THRE, UART_LSR_THRE);
+	prom_putchar_wait(base + UART_LSR * 4, BOTH_EMPTY, BOTH_EMPTY);
 }
 
 static void prom_putchar_ar933x(unsigned char ch)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/ath79/Kconfig linux-libre-4.7-gnu/arch/mips/ath79/Kconfig
--- linux-libre-4.6-gnu/arch/mips/ath79/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/ath79/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -71,18 +71,6 @@ config ATH79_MACH_UBNT_XM
 	  Say 'Y' here if you want your kernel to support the
 	  Ubiquiti Networks XM (rev 1.0) board.
 
-choice
-	prompt "Build a DTB in the kernel"
-	optional
-	help
-	  Select a devicetree that should be built into the kernel.
-
-	config DTB_TL_WR1043ND_V1
-		bool "TL-WR1043ND Version 1"
-		select BUILTIN_DTB
-		select SOC_AR913X
-endchoice
-
 endmenu
 
 config SOC_AR71XX
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/ath79/setup.c linux-libre-4.7-gnu/arch/mips/ath79/setup.c
--- linux-libre-4.6-gnu/arch/mips/ath79/setup.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/ath79/setup.c	2016-07-24 15:23:50.000000000 -0400
@@ -17,6 +17,7 @@
 #include <linux/bootmem.h>
 #include <linux/err.h>
 #include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/of_platform.h>
 #include <linux/of_fdt.h>
 
@@ -203,26 +204,57 @@ void __init plat_mem_setup(void)
 	fdt_start = fw_getenvl("fdt_start");
 	if (fdt_start)
 		__dt_setup_arch((void *)KSEG0ADDR(fdt_start));
-#ifdef CONFIG_BUILTIN_DTB
-	else
-		__dt_setup_arch(__dtb_start);
-#endif
+	else if (fw_arg0 == -2)
+		__dt_setup_arch((void *)KSEG0ADDR(fw_arg1));
 
-	ath79_reset_base = ioremap_nocache(AR71XX_RESET_BASE,
-					   AR71XX_RESET_SIZE);
-	ath79_pll_base = ioremap_nocache(AR71XX_PLL_BASE,
-					 AR71XX_PLL_SIZE);
-	ath79_detect_sys_type();
-	ath79_ddr_ctrl_init();
+	if (mips_machtype != ATH79_MACH_GENERIC_OF) {
+		ath79_reset_base = ioremap_nocache(AR71XX_RESET_BASE,
+						   AR71XX_RESET_SIZE);
+		ath79_pll_base = ioremap_nocache(AR71XX_PLL_BASE,
+						 AR71XX_PLL_SIZE);
+		ath79_detect_sys_type();
+		ath79_ddr_ctrl_init();
 
-	if (mips_machtype != ATH79_MACH_GENERIC_OF)
 		detect_memory_region(0, ATH79_MEM_SIZE_MIN, ATH79_MEM_SIZE_MAX);
 
-	_machine_restart = ath79_restart;
+		/* OF machines should use the reset driver */
+		_machine_restart = ath79_restart;
+	}
+
 	_machine_halt = ath79_halt;
 	pm_power_off = ath79_halt;
 }
 
+static void __init ath79_of_plat_time_init(void)
+{
+	struct device_node *np;
+	struct clk *clk;
+	unsigned long cpu_clk_rate;
+
+	of_clk_init(NULL);
+
+	np = of_get_cpu_node(0, NULL);
+	if (!np) {
+		pr_err("Failed to get CPU node\n");
+		return;
+	}
+
+	clk = of_clk_get(np, 0);
+	if (IS_ERR(clk)) {
+		pr_err("Failed to get CPU clock: %ld\n", PTR_ERR(clk));
+		return;
+	}
+
+	cpu_clk_rate = clk_get_rate(clk);
+
+	pr_info("CPU clock: %lu.%03lu MHz\n",
+		cpu_clk_rate / 1000000, (cpu_clk_rate / 1000) % 1000);
+
+	mips_hpt_frequency = cpu_clk_rate / 2;
+
+	clk_put(clk);
+}
+
 void __init plat_time_init(void)
 {
 	unsigned long cpu_clk_rate;
@@ -230,6 +262,11 @@ void __init plat_time_init(void)
 	unsigned long ddr_clk_rate;
 	unsigned long ref_clk_rate;
 
+	if (IS_ENABLED(CONFIG_OF) && mips_machtype == ATH79_MACH_GENERIC_OF) {
+		ath79_of_plat_time_init();
+		return;
+	}
+
 	ath79_clocks_init();
 
 	cpu_clk_rate = ath79_get_sys_clk_rate("cpu");
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/bcm47xx/bcm47xx_private.h linux-libre-4.7-gnu/arch/mips/bcm47xx/bcm47xx_private.h
--- linux-libre-4.6-gnu/arch/mips/bcm47xx/bcm47xx_private.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/bcm47xx/bcm47xx_private.h	2016-07-24 15:23:50.000000000 -0400
@@ -10,9 +10,6 @@
 /* prom.c */
 void __init bcm47xx_prom_highmem_init(void);
 
-/* sprom.c */
-void bcm47xx_sprom_register_fallbacks(void);
-
 /* buttons.c */
 int __init bcm47xx_buttons_register(void);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/bcm47xx/Makefile linux-libre-4.7-gnu/arch/mips/bcm47xx/Makefile
--- linux-libre-4.6-gnu/arch/mips/bcm47xx/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/bcm47xx/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -3,5 +3,5 @@
 # under Linux.
 #
 
-obj-y				+= irq.o prom.o serial.o setup.o time.o sprom.o
+obj-y				+= irq.o prom.o serial.o setup.o time.o
 obj-y				+= board.o buttons.o leds.o workarounds.o
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/bcm47xx/setup.c linux-libre-4.7-gnu/arch/mips/bcm47xx/setup.c
--- linux-libre-4.6-gnu/arch/mips/bcm47xx/setup.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/bcm47xx/setup.c	2016-07-24 15:23:50.000000000 -0400
@@ -28,6 +28,7 @@
 
 #include "bcm47xx_private.h"
 
+#include <linux/bcm47xx_sprom.h>
 #include <linux/export.h>
 #include <linux/types.h>
 #include <linux/ethtool.h>
@@ -151,7 +152,6 @@ void __init plat_mem_setup(void)
 		pr_info("Using bcma bus\n");
 #ifdef CONFIG_BCM47XX_BCMA
 		bcm47xx_bus_type = BCM47XX_BUS_TYPE_BCMA;
-		bcm47xx_sprom_register_fallbacks();
 		bcm47xx_register_bcma();
 		bcm47xx_set_system_type(bcm47xx_bus.bcma.bus.chipinfo.id);
 #ifdef CONFIG_HIGHMEM
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/bcm47xx/sprom.c linux-libre-4.7-gnu/arch/mips/bcm47xx/sprom.c
--- linux-libre-4.6-gnu/arch/mips/bcm47xx/sprom.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/bcm47xx/sprom.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,724 +0,0 @@
-/*
- *  Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
- *  Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
- *  Copyright (C) 2006 Michael Buesch <m@bues.ch>
- *  Copyright (C) 2010 Waldemar Brodkorb <wbx@openadk.org>
- *  Copyright (C) 2010-2012 Hauke Mehrtens <hauke@hauke-m.de>
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <bcm47xx.h>
-#include <linux/if_ether.h>
-#include <linux/etherdevice.h>
-
-static void create_key(const char *prefix, const char *postfix,
-		       const char *name, char *buf, int len)
-{
-	if (prefix && postfix)
-		snprintf(buf, len, "%s%s%s", prefix, name, postfix);
-	else if (prefix)
-		snprintf(buf, len, "%s%s", prefix, name);
-	else if (postfix)
-		snprintf(buf, len, "%s%s", name, postfix);
-	else
-		snprintf(buf, len, "%s", name);
-}
-
-static int get_nvram_var(const char *prefix, const char *postfix,
-			 const char *name, char *buf, int len, bool fallback)
-{
-	char key[40];
-	int err;
-
-	create_key(prefix, postfix, name, key, sizeof(key));
-
-	err = bcm47xx_nvram_getenv(key, buf, len);
-	if (fallback && err == -ENOENT && prefix) {
-		create_key(NULL, postfix, name, key, sizeof(key));
-		err = bcm47xx_nvram_getenv(key, buf, len);
-	}
-	return err;
-}
-
-#define NVRAM_READ_VAL(type)						\
-static void nvram_read_ ## type(const char *prefix,			\
-				const char *postfix, const char *name,	\
-				type *val, type allset, bool fallback)	\
-{									\
-	char buf[100];							\
-	int err;							\
-	type var;							\
-									\
-	err = get_nvram_var(prefix, postfix, name, buf, sizeof(buf),	\
-			    fallback);					\
-	if (err < 0)							\
-		return;							\
-	err = kstrto ## type(strim(buf), 0, &var);			\
-	if (err) {							\
-		pr_warn("can not parse nvram name %s%s%s with value %s got %i\n",	\
-			prefix, name, postfix, buf, err);		\
-		return;							\
-	}								\
-	if (allset && var == allset)					\
-		return;							\
-	*val = var;							\
-}
-
-NVRAM_READ_VAL(u8)
-NVRAM_READ_VAL(s8)
-NVRAM_READ_VAL(u16)
-NVRAM_READ_VAL(u32)
-
-#undef NVRAM_READ_VAL
-
-static void nvram_read_u32_2(const char *prefix, const char *name,
-			     u16 *val_lo, u16 *val_hi, bool fallback)
-{
-	char buf[100];
-	int err;
-	u32 val;
-
-	err = get_nvram_var(prefix, NULL, name, buf, sizeof(buf), fallback);
-	if (err < 0)
-		return;
-	err = kstrtou32(strim(buf), 0, &val);
-	if (err) {
-		pr_warn("can not parse nvram name %s%s with value %s got %i\n",
-			prefix, name, buf, err);
-		return;
-	}
-	*val_lo = (val & 0x0000FFFFU);
-	*val_hi = (val & 0xFFFF0000U) >> 16;
-}
-
-static void nvram_read_leddc(const char *prefix, const char *name,
-			     u8 *leddc_on_time, u8 *leddc_off_time,
-			     bool fallback)
-{
-	char buf[100];
-	int err;
-	u32 val;
-
-	err = get_nvram_var(prefix, NULL, name, buf, sizeof(buf), fallback);
-	if (err < 0)
-		return;
-	err = kstrtou32(strim(buf), 0, &val);
-	if (err) {
-		pr_warn("can not parse nvram name %s%s with value %s got %i\n",
-			prefix, name, buf, err);
-		return;
-	}
-
-	if (val == 0xffff || val == 0xffffffff)
-		return;
-
-	*leddc_on_time = val & 0xff;
-	*leddc_off_time = (val >> 16) & 0xff;
-}
-
-static void bcm47xx_nvram_parse_macaddr(char *buf, u8 macaddr[6])
-{
-	if (strchr(buf, ':'))
-		sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0],
-			&macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4],
-			&macaddr[5]);
-	else if (strchr(buf, '-'))
-		sscanf(buf, "%hhx-%hhx-%hhx-%hhx-%hhx-%hhx", &macaddr[0],
-			&macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4],
-			&macaddr[5]);
-	else
-		pr_warn("Can not parse mac address: %s\n", buf);
-}
-
-static void nvram_read_macaddr(const char *prefix, const char *name,
-			       u8 val[6], bool fallback)
-{
-	char buf[100];
-	int err;
-
-	err = get_nvram_var(prefix, NULL, name, buf, sizeof(buf), fallback);
-	if (err < 0)
-		return;
-
-	bcm47xx_nvram_parse_macaddr(buf, val);
-}
-
-static void nvram_read_alpha2(const char *prefix, const char *name,
-			     char val[2], bool fallback)
-{
-	char buf[10];
-	int err;
-
-	err = get_nvram_var(prefix, NULL, name, buf, sizeof(buf), fallback);
-	if (err < 0)
-		return;
-	if (buf[0] == '0')
-		return;
-	if (strlen(buf) > 2) {
-		pr_warn("alpha2 is too long %s\n", buf);
-		return;
-	}
-	memcpy(val, buf, 2);
-}
-
-/* This is one-function-only macro, it uses local "sprom" variable! */
-#define ENTRY(_revmask, _type, _prefix, _name, _val, _allset, _fallback) \
-	if (_revmask & BIT(sprom->revision)) \
-		nvram_read_ ## _type(_prefix, NULL, _name, &sprom->_val, \
-				     _allset, _fallback)
-/*
- * Special version of filling function that can be safely called for any SPROM
- * revision. For every NVRAM to SPROM mapping it contains bitmask of revisions
- * for which the mapping is valid.
- * It obviously requires some hexadecimal/bitmasks knowledge, but allows
- * writing cleaner code (easy revisions handling).
- * Note that while SPROM revision 0 was never used, we still keep BIT(0)
- * reserved for it, just to keep numbering sane.
- */
-static void bcm47xx_sprom_fill_auto(struct ssb_sprom *sprom,
-				    const char *prefix, bool fallback)
-{
-	const char *pre = prefix;
-	bool fb = fallback;
-
-	/* Broadcom extracts it for rev 8+ but it was found on 2 and 4 too */
-	ENTRY(0xfffffffe, u16, pre, "devid", dev_id, 0, fallback);
-
-	ENTRY(0xfffffffe, u16, pre, "boardrev", board_rev, 0, true);
-	ENTRY(0xfffffffe, u32, pre, "boardflags", boardflags, 0, fb);
-	ENTRY(0xfffffff0, u32, pre, "boardflags2", boardflags2, 0, fb);
-	ENTRY(0xfffff800, u32, pre, "boardflags3", boardflags3, 0, fb);
-	ENTRY(0x00000002, u16, pre, "boardflags", boardflags_lo, 0, fb);
-	ENTRY(0xfffffffc, u16, pre, "boardtype", board_type, 0, true);
-	ENTRY(0xfffffffe, u16, pre, "boardnum", board_num, 0, fb);
-	ENTRY(0x00000002, u8, pre, "cc", country_code, 0, fb);
-	ENTRY(0xfffffff8, u8, pre, "regrev", regrev, 0, fb);
-
-	ENTRY(0xfffffffe, u8, pre, "ledbh0", gpio0, 0xff, fb);
-	ENTRY(0xfffffffe, u8, pre, "ledbh1", gpio1, 0xff, fb);
-	ENTRY(0xfffffffe, u8, pre, "ledbh2", gpio2, 0xff, fb);
-	ENTRY(0xfffffffe, u8, pre, "ledbh3", gpio3, 0xff, fb);
-
-	ENTRY(0x0000070e, u16, pre, "pa0b0", pa0b0, 0, fb);
-	ENTRY(0x0000070e, u16, pre, "pa0b1", pa0b1, 0, fb);
-	ENTRY(0x0000070e, u16, pre, "pa0b2", pa0b2, 0, fb);
-	ENTRY(0x0000070e, u8, pre, "pa0itssit", itssi_bg, 0, fb);
-	ENTRY(0x0000070e, u8, pre, "pa0maxpwr", maxpwr_bg, 0, fb);
-
-	ENTRY(0x0000070c, u8, pre, "opo", opo, 0, fb);
-	ENTRY(0xfffffffe, u8, pre, "aa2g", ant_available_bg, 0, fb);
-	ENTRY(0xfffffffe, u8, pre, "aa5g", ant_available_a, 0, fb);
-	ENTRY(0x000007fe, s8, pre, "ag0", antenna_gain.a0, 0, fb);
-	ENTRY(0x000007fe, s8, pre, "ag1", antenna_gain.a1, 0, fb);
-	ENTRY(0x000007f0, s8, pre, "ag2", antenna_gain.a2, 0, fb);
-	ENTRY(0x000007f0, s8, pre, "ag3", antenna_gain.a3, 0, fb);
-
-	ENTRY(0x0000070e, u16, pre, "pa1b0", pa1b0, 0, fb);
-	ENTRY(0x0000070e, u16, pre, "pa1b1", pa1b1, 0, fb);
-	ENTRY(0x0000070e, u16, pre, "pa1b2", pa1b2, 0, fb);
-	ENTRY(0x0000070c, u16, pre, "pa1lob0", pa1lob0, 0, fb);
-	ENTRY(0x0000070c, u16, pre, "pa1lob1", pa1lob1, 0, fb);
-	ENTRY(0x0000070c, u16, pre, "pa1lob2", pa1lob2, 0, fb);
-	ENTRY(0x0000070c, u16, pre, "pa1hib0", pa1hib0, 0, fb);
-	ENTRY(0x0000070c, u16, pre, "pa1hib1", pa1hib1, 0, fb);
-	ENTRY(0x0000070c, u16, pre, "pa1hib2", pa1hib2, 0, fb);
-	ENTRY(0x0000070e, u8, pre, "pa1itssit", itssi_a, 0, fb);
-	ENTRY(0x0000070e, u8, pre, "pa1maxpwr", maxpwr_a, 0, fb);
-	ENTRY(0x0000070c, u8, pre, "pa1lomaxpwr", maxpwr_al, 0, fb);
-	ENTRY(0x0000070c, u8, pre, "pa1himaxpwr", maxpwr_ah, 0, fb);
-
-	ENTRY(0x00000708, u8, pre, "bxa2g", bxa2g, 0, fb);
-	ENTRY(0x00000708, u8, pre, "rssisav2g", rssisav2g, 0, fb);
-	ENTRY(0x00000708, u8, pre, "rssismc2g", rssismc2g, 0, fb);
-	ENTRY(0x00000708, u8, pre, "rssismf2g", rssismf2g, 0, fb);
-	ENTRY(0x00000708, u8, pre, "bxa5g", bxa5g, 0, fb);
-	ENTRY(0x00000708, u8, pre, "rssisav5g", rssisav5g, 0, fb);
-	ENTRY(0x00000708, u8, pre, "rssismc5g", rssismc5g, 0, fb);
-	ENTRY(0x00000708, u8, pre, "rssismf5g", rssismf5g, 0, fb);
-	ENTRY(0x00000708, u8, pre, "tri2g", tri2g, 0, fb);
-	ENTRY(0x00000708, u8, pre, "tri5g", tri5g, 0, fb);
-	ENTRY(0x00000708, u8, pre, "tri5gl", tri5gl, 0, fb);
-	ENTRY(0x00000708, u8, pre, "tri5gh", tri5gh, 0, fb);
-	ENTRY(0x00000708, s8, pre, "rxpo2g", rxpo2g, 0, fb);
-	ENTRY(0x00000708, s8, pre, "rxpo5g", rxpo5g, 0, fb);
-	ENTRY(0xfffffff0, u8, pre, "txchain", txchain, 0xf, fb);
-	ENTRY(0xfffffff0, u8, pre, "rxchain", rxchain, 0xf, fb);
-	ENTRY(0xfffffff0, u8, pre, "antswitch", antswitch, 0xff, fb);
-	ENTRY(0x00000700, u8, pre, "tssipos2g", fem.ghz2.tssipos, 0, fb);
-	ENTRY(0x00000700, u8, pre, "extpagain2g", fem.ghz2.extpa_gain, 0, fb);
-	ENTRY(0x00000700, u8, pre, "pdetrange2g", fem.ghz2.pdet_range, 0, fb);
-	ENTRY(0x00000700, u8, pre, "triso2g", fem.ghz2.tr_iso, 0, fb);
-	ENTRY(0x00000700, u8, pre, "antswctl2g", fem.ghz2.antswlut, 0, fb);
-	ENTRY(0x00000700, u8, pre, "tssipos5g", fem.ghz5.tssipos, 0, fb);
-	ENTRY(0x00000700, u8, pre, "extpagain5g", fem.ghz5.extpa_gain, 0, fb);
-	ENTRY(0x00000700, u8, pre, "pdetrange5g", fem.ghz5.pdet_range, 0, fb);
-	ENTRY(0x00000700, u8, pre, "triso5g", fem.ghz5.tr_iso, 0, fb);
-	ENTRY(0x00000700, u8, pre, "antswctl5g", fem.ghz5.antswlut, 0, fb);
-	ENTRY(0x000000f0, u8, pre, "txpid2ga0", txpid2g[0], 0, fb);
-	ENTRY(0x000000f0, u8, pre, "txpid2ga1", txpid2g[1], 0, fb);
-	ENTRY(0x000000f0, u8, pre, "txpid2ga2", txpid2g[2], 0, fb);
-	ENTRY(0x000000f0, u8, pre, "txpid2ga3", txpid2g[3], 0, fb);
-	ENTRY(0x000000f0, u8, pre, "txpid5ga0", txpid5g[0], 0, fb);
-	ENTRY(0x000000f0, u8, pre, "txpid5ga1", txpid5g[1], 0, fb);
-	ENTRY(0x000000f0, u8, pre, "txpid5ga2", txpid5g[2], 0, fb);
-	ENTRY(0x000000f0, u8, pre, "txpid5ga3", txpid5g[3], 0, fb);
-	ENTRY(0x000000f0, u8, pre, "txpid5gla0", txpid5gl[0], 0, fb);
-	ENTRY(0x000000f0, u8, pre, "txpid5gla1", txpid5gl[1], 0, fb);
-	ENTRY(0x000000f0, u8, pre, "txpid5gla2", txpid5gl[2], 0, fb);
-	ENTRY(0x000000f0, u8, pre, "txpid5gla3", txpid5gl[3], 0, fb);
-	ENTRY(0x000000f0, u8, pre, "txpid5gha0", txpid5gh[0], 0, fb);
-	ENTRY(0x000000f0, u8, pre, "txpid5gha1", txpid5gh[1], 0, fb);
-	ENTRY(0x000000f0, u8, pre, "txpid5gha2", txpid5gh[2], 0, fb);
-	ENTRY(0x000000f0, u8, pre, "txpid5gha3", txpid5gh[3], 0, fb);
-
-	ENTRY(0xffffff00, u8, pre, "tempthresh", tempthresh, 0, fb);
-	ENTRY(0xffffff00, u8, pre, "tempoffset", tempoffset, 0, fb);
-	ENTRY(0xffffff00, u16, pre, "rawtempsense", rawtempsense, 0, fb);
-	ENTRY(0xffffff00, u8, pre, "measpower", measpower, 0, fb);
-	ENTRY(0xffffff00, u8, pre, "tempsense_slope", tempsense_slope, 0, fb);
-	ENTRY(0xffffff00, u8, pre, "tempcorrx", tempcorrx, 0, fb);
-	ENTRY(0xffffff00, u8, pre, "tempsense_option", tempsense_option, 0, fb);
-	ENTRY(0x00000700, u8, pre, "freqoffset_corr", freqoffset_corr, 0, fb);
-	ENTRY(0x00000700, u8, pre, "iqcal_swp_dis", iqcal_swp_dis, 0, fb);
-	ENTRY(0x00000700, u8, pre, "hw_iqcal_en", hw_iqcal_en, 0, fb);
-	ENTRY(0x00000700, u8, pre, "elna2g", elna2g, 0, fb);
-	ENTRY(0x00000700, u8, pre, "elna5g", elna5g, 0, fb);
-	ENTRY(0xffffff00, u8, pre, "phycal_tempdelta", phycal_tempdelta, 0, fb);
-	ENTRY(0xffffff00, u8, pre, "temps_period", temps_period, 0, fb);
-	ENTRY(0xffffff00, u8, pre, "temps_hysteresis", temps_hysteresis, 0, fb);
-	ENTRY(0xffffff00, u8, pre, "measpower1", measpower1, 0, fb);
-	ENTRY(0xffffff00, u8, pre, "measpower2", measpower2, 0, fb);
-
-	ENTRY(0x000001f0, u16, pre, "cck2gpo", cck2gpo, 0, fb);
-	ENTRY(0x000001f0, u32, pre, "ofdm2gpo", ofdm2gpo, 0, fb);
-	ENTRY(0x000001f0, u32, pre, "ofdm5gpo", ofdm5gpo, 0, fb);
-	ENTRY(0x000001f0, u32, pre, "ofdm5glpo", ofdm5glpo, 0, fb);
-	ENTRY(0x000001f0, u32, pre, "ofdm5ghpo", ofdm5ghpo, 0, fb);
-	ENTRY(0x000001f0, u16, pre, "mcs2gpo0", mcs2gpo[0], 0, fb);
-	ENTRY(0x000001f0, u16, pre, "mcs2gpo1", mcs2gpo[1], 0, fb);
-	ENTRY(0x000001f0, u16, pre, "mcs2gpo2", mcs2gpo[2], 0, fb);
-	ENTRY(0x000001f0, u16, pre, "mcs2gpo3", mcs2gpo[3], 0, fb);
-	ENTRY(0x000001f0, u16, pre, "mcs2gpo4", mcs2gpo[4], 0, fb);
-	ENTRY(0x000001f0, u16, pre, "mcs2gpo5", mcs2gpo[5], 0, fb);
-	ENTRY(0x000001f0, u16, pre, "mcs2gpo6", mcs2gpo[6], 0, fb);
-	ENTRY(0x000001f0, u16, pre, "mcs2gpo7", mcs2gpo[7], 0, fb);
-	ENTRY(0x000001f0, u16, pre, "mcs5gpo0", mcs5gpo[0], 0, fb);
-	ENTRY(0x000001f0, u16, pre, "mcs5gpo1", mcs5gpo[1], 0, fb);
-	ENTRY(0x000001f0, u16, pre, "mcs5gpo2", mcs5gpo[2], 0, fb);
-	ENTRY(0x000001f0, u16, pre, "mcs5gpo3", mcs5gpo[3], 0, fb);
-	ENTRY(0x000001f0, u16, pre, "mcs5gpo4", mcs5gpo[4], 0, fb);
-	ENTRY(0x000001f0, u16, pre, "mcs5gpo5", mcs5gpo[5], 0, fb);
-	ENTRY(0x000001f0, u16, pre, "mcs5gpo6", mcs5gpo[6], 0, fb);
-	ENTRY(0x000001f0, u16, pre, "mcs5gpo7", mcs5gpo[7], 0, fb);
-	ENTRY(0x000001f0, u16, pre, "mcs5glpo0", mcs5glpo[0], 0, fb);
-	ENTRY(0x000001f0, u16, pre, "mcs5glpo1", mcs5glpo[1], 0, fb);
-	ENTRY(0x000001f0, u16, pre, "mcs5glpo2", mcs5glpo[2], 0, fb);
-	ENTRY(0x000001f0, u16, pre, "mcs5glpo3", mcs5glpo[3], 0, fb);
-	ENTRY(0x000001f0, u16, pre, "mcs5glpo4", mcs5glpo[4], 0, fb);
-	ENTRY(0x000001f0, u16, pre, "mcs5glpo5", mcs5glpo[5], 0, fb);
-	ENTRY(0x000001f0, u16, pre, "mcs5glpo6", mcs5glpo[6], 0, fb);
-	ENTRY(0x000001f0, u16, pre, "mcs5glpo7", mcs5glpo[7], 0, fb);
-	ENTRY(0x000001f0, u16, pre, "mcs5ghpo0", mcs5ghpo[0], 0, fb);
-	ENTRY(0x000001f0, u16, pre, "mcs5ghpo1", mcs5ghpo[1], 0, fb);
-	ENTRY(0x000001f0, u16, pre, "mcs5ghpo2", mcs5ghpo[2], 0, fb);
-	ENTRY(0x000001f0, u16, pre, "mcs5ghpo3", mcs5ghpo[3], 0, fb);
-	ENTRY(0x000001f0, u16, pre, "mcs5ghpo4", mcs5ghpo[4], 0, fb);
-	ENTRY(0x000001f0, u16, pre, "mcs5ghpo5", mcs5ghpo[5], 0, fb);
-	ENTRY(0x000001f0, u16, pre, "mcs5ghpo6", mcs5ghpo[6], 0, fb);
-	ENTRY(0x000001f0, u16, pre, "mcs5ghpo7", mcs5ghpo[7], 0, fb);
-	ENTRY(0x000001f0, u16, pre, "cddpo", cddpo, 0, fb);
-	ENTRY(0x000001f0, u16, pre, "stbcpo", stbcpo, 0, fb);
-	ENTRY(0x000001f0, u16, pre, "bw40po", bw40po, 0, fb);
-	ENTRY(0x000001f0, u16, pre, "bwduppo", bwduppo, 0, fb);
-
-	ENTRY(0xfffffe00, u16, pre, "cckbw202gpo", cckbw202gpo, 0, fb);
-	ENTRY(0xfffffe00, u16, pre, "cckbw20ul2gpo", cckbw20ul2gpo, 0, fb);
-	ENTRY(0x00000600, u32, pre, "legofdmbw202gpo", legofdmbw202gpo, 0, fb);
-	ENTRY(0x00000600, u32, pre, "legofdmbw20ul2gpo", legofdmbw20ul2gpo, 0, fb);
-	ENTRY(0x00000600, u32, pre, "legofdmbw205glpo", legofdmbw205glpo, 0, fb);
-	ENTRY(0x00000600, u32, pre, "legofdmbw20ul5glpo", legofdmbw20ul5glpo, 0, fb);
-	ENTRY(0x00000600, u32, pre, "legofdmbw205gmpo", legofdmbw205gmpo, 0, fb);
-	ENTRY(0x00000600, u32, pre, "legofdmbw20ul5gmpo", legofdmbw20ul5gmpo, 0, fb);
-	ENTRY(0x00000600, u32, pre, "legofdmbw205ghpo", legofdmbw205ghpo, 0, fb);
-	ENTRY(0x00000600, u32, pre, "legofdmbw20ul5ghpo", legofdmbw20ul5ghpo, 0, fb);
-	ENTRY(0xfffffe00, u32, pre, "mcsbw202gpo", mcsbw202gpo, 0, fb);
-	ENTRY(0x00000600, u32, pre, "mcsbw20ul2gpo", mcsbw20ul2gpo, 0, fb);
-	ENTRY(0xfffffe00, u32, pre, "mcsbw402gpo", mcsbw402gpo, 0, fb);
-	ENTRY(0xfffffe00, u32, pre, "mcsbw205glpo", mcsbw205glpo, 0, fb);
-	ENTRY(0x00000600, u32, pre, "mcsbw20ul5glpo", mcsbw20ul5glpo, 0, fb);
-	ENTRY(0xfffffe00, u32, pre, "mcsbw405glpo", mcsbw405glpo, 0, fb);
-	ENTRY(0xfffffe00, u32, pre, "mcsbw205gmpo", mcsbw205gmpo, 0, fb);
-	ENTRY(0x00000600, u32, pre, "mcsbw20ul5gmpo", mcsbw20ul5gmpo, 0, fb);
-	ENTRY(0xfffffe00, u32, pre, "mcsbw405gmpo", mcsbw405gmpo, 0, fb);
-	ENTRY(0xfffffe00, u32, pre, "mcsbw205ghpo", mcsbw205ghpo, 0, fb);
-	ENTRY(0x00000600, u32, pre, "mcsbw20ul5ghpo", mcsbw20ul5ghpo, 0, fb);
-	ENTRY(0xfffffe00, u32, pre, "mcsbw405ghpo", mcsbw405ghpo, 0, fb);
-	ENTRY(0x00000600, u16, pre, "mcs32po", mcs32po, 0, fb);
-	ENTRY(0x00000600, u16, pre, "legofdm40duppo", legofdm40duppo, 0, fb);
-	ENTRY(0x00000700, u8, pre, "pcieingress_war", pcieingress_war, 0, fb);
-
-	/* TODO: rev 11 support */
-	ENTRY(0x00000700, u8, pre, "rxgainerr2ga0", rxgainerr2ga[0], 0, fb);
-	ENTRY(0x00000700, u8, pre, "rxgainerr2ga1", rxgainerr2ga[1], 0, fb);
-	ENTRY(0x00000700, u8, pre, "rxgainerr2ga2", rxgainerr2ga[2], 0, fb);
-	ENTRY(0x00000700, u8, pre, "rxgainerr5gla0", rxgainerr5gla[0], 0, fb);
-	ENTRY(0x00000700, u8, pre, "rxgainerr5gla1", rxgainerr5gla[1], 0, fb);
-	ENTRY(0x00000700, u8, pre, "rxgainerr5gla2", rxgainerr5gla[2], 0, fb);
-	ENTRY(0x00000700, u8, pre, "rxgainerr5gma0", rxgainerr5gma[0], 0, fb);
-	ENTRY(0x00000700, u8, pre, "rxgainerr5gma1", rxgainerr5gma[1], 0, fb);
-	ENTRY(0x00000700, u8, pre, "rxgainerr5gma2", rxgainerr5gma[2], 0, fb);
-	ENTRY(0x00000700, u8, pre, "rxgainerr5gha0", rxgainerr5gha[0], 0, fb);
-	ENTRY(0x00000700, u8, pre, "rxgainerr5gha1", rxgainerr5gha[1], 0, fb);
-	ENTRY(0x00000700, u8, pre, "rxgainerr5gha2", rxgainerr5gha[2], 0, fb);
-	ENTRY(0x00000700, u8, pre, "rxgainerr5gua0", rxgainerr5gua[0], 0, fb);
-	ENTRY(0x00000700, u8, pre, "rxgainerr5gua1", rxgainerr5gua[1], 0, fb);
-	ENTRY(0x00000700, u8, pre, "rxgainerr5gua2", rxgainerr5gua[2], 0, fb);
-
-	ENTRY(0xfffffe00, u8, pre, "sar2g", sar2g, 0, fb);
-	ENTRY(0xfffffe00, u8, pre, "sar5g", sar5g, 0, fb);
-
-	/* TODO: rev 11 support */
-	ENTRY(0x00000700, u8, pre, "noiselvl2ga0", noiselvl2ga[0], 0, fb);
-	ENTRY(0x00000700, u8, pre, "noiselvl2ga1", noiselvl2ga[1], 0, fb);
-	ENTRY(0x00000700, u8, pre, "noiselvl2ga2", noiselvl2ga[2], 0, fb);
-	ENTRY(0x00000700, u8, pre, "noiselvl5gla0", noiselvl5gla[0], 0, fb);
-	ENTRY(0x00000700, u8, pre, "noiselvl5gla1", noiselvl5gla[1], 0, fb);
-	ENTRY(0x00000700, u8, pre, "noiselvl5gla2", noiselvl5gla[2], 0, fb);
-	ENTRY(0x00000700, u8, pre, "noiselvl5gma0", noiselvl5gma[0], 0, fb);
-	ENTRY(0x00000700, u8, pre, "noiselvl5gma1", noiselvl5gma[1], 0, fb);
-	ENTRY(0x00000700, u8, pre, "noiselvl5gma2", noiselvl5gma[2], 0, fb);
-	ENTRY(0x00000700, u8, pre, "noiselvl5gha0", noiselvl5gha[0], 0, fb);
-	ENTRY(0x00000700, u8, pre, "noiselvl5gha1", noiselvl5gha[1], 0, fb);
-	ENTRY(0x00000700, u8, pre, "noiselvl5gha2", noiselvl5gha[2], 0, fb);
-	ENTRY(0x00000700, u8, pre, "noiselvl5gua0", noiselvl5gua[0], 0, fb);
-	ENTRY(0x00000700, u8, pre, "noiselvl5gua1", noiselvl5gua[1], 0, fb);
-	ENTRY(0x00000700, u8, pre, "noiselvl5gua2", noiselvl5gua[2], 0, fb);
-}
-#undef ENTRY /* It's specififc, uses local variable, don't use it (again). */
-
-static void bcm47xx_fill_sprom_path_r4589(struct ssb_sprom *sprom,
-					  const char *prefix, bool fallback)
-{
-	char postfix[2];
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(sprom->core_pwr_info); i++) {
-		struct ssb_sprom_core_pwr_info *pwr_info;
-
-		pwr_info = &sprom->core_pwr_info[i];
-
-		snprintf(postfix, sizeof(postfix), "%i", i);
-		nvram_read_u8(prefix, postfix, "maxp2ga",
-			      &pwr_info->maxpwr_2g, 0, fallback);
-		nvram_read_u8(prefix, postfix, "itt2ga",
-			      &pwr_info->itssi_2g, 0, fallback);
-		nvram_read_u8(prefix, postfix, "itt5ga",
-			      &pwr_info->itssi_5g, 0, fallback);
-		nvram_read_u16(prefix, postfix, "pa2gw0a",
-			       &pwr_info->pa_2g[0], 0, fallback);
-		nvram_read_u16(prefix, postfix, "pa2gw1a",
-			       &pwr_info->pa_2g[1], 0, fallback);
-		nvram_read_u16(prefix, postfix, "pa2gw2a",
-			       &pwr_info->pa_2g[2], 0, fallback);
-		nvram_read_u8(prefix, postfix, "maxp5ga",
-			      &pwr_info->maxpwr_5g, 0, fallback);
-		nvram_read_u8(prefix, postfix, "maxp5gha",
-			      &pwr_info->maxpwr_5gh, 0, fallback);
-		nvram_read_u8(prefix, postfix, "maxp5gla",
-			      &pwr_info->maxpwr_5gl, 0, fallback);
-		nvram_read_u16(prefix, postfix, "pa5gw0a",
-			       &pwr_info->pa_5g[0], 0, fallback);
-		nvram_read_u16(prefix, postfix, "pa5gw1a",
-			       &pwr_info->pa_5g[1], 0, fallback);
-		nvram_read_u16(prefix, postfix, "pa5gw2a",
-			       &pwr_info->pa_5g[2], 0, fallback);
-		nvram_read_u16(prefix, postfix, "pa5glw0a",
-			       &pwr_info->pa_5gl[0], 0, fallback);
-		nvram_read_u16(prefix, postfix, "pa5glw1a",
-			       &pwr_info->pa_5gl[1], 0, fallback);
-		nvram_read_u16(prefix, postfix, "pa5glw2a",
-			       &pwr_info->pa_5gl[2], 0, fallback);
-		nvram_read_u16(prefix, postfix, "pa5ghw0a",
-			       &pwr_info->pa_5gh[0], 0, fallback);
-		nvram_read_u16(prefix, postfix, "pa5ghw1a",
-			       &pwr_info->pa_5gh[1], 0, fallback);
-		nvram_read_u16(prefix, postfix, "pa5ghw2a",
-			       &pwr_info->pa_5gh[2], 0, fallback);
-	}
-}
-
-static void bcm47xx_fill_sprom_path_r45(struct ssb_sprom *sprom,
-					const char *prefix, bool fallback)
-{
-	char postfix[2];
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(sprom->core_pwr_info); i++) {
-		struct ssb_sprom_core_pwr_info *pwr_info;
-
-		pwr_info = &sprom->core_pwr_info[i];
-
-		snprintf(postfix, sizeof(postfix), "%i", i);
-		nvram_read_u16(prefix, postfix, "pa2gw3a",
-			       &pwr_info->pa_2g[3], 0, fallback);
-		nvram_read_u16(prefix, postfix, "pa5gw3a",
-			       &pwr_info->pa_5g[3], 0, fallback);
-		nvram_read_u16(prefix, postfix, "pa5glw3a",
-			       &pwr_info->pa_5gl[3], 0, fallback);
-		nvram_read_u16(prefix, postfix, "pa5ghw3a",
-			       &pwr_info->pa_5gh[3], 0, fallback);
-	}
-}
-
-static bool bcm47xx_is_valid_mac(u8 *mac)
-{
-	return mac && !(mac[0] == 0x00 && mac[1] == 0x90 && mac[2] == 0x4c);
-}
-
-static int bcm47xx_increase_mac_addr(u8 *mac, u8 num)
-{
-	u8 *oui = mac + ETH_ALEN/2 - 1;
-	u8 *p = mac + ETH_ALEN - 1;
-
-	do {
-		(*p) += num;
-		if (*p > num)
-			break;
-		p--;
-		num = 1;
-	} while (p != oui);
-
-	if (p == oui) {
-		pr_err("unable to fetch mac address\n");
-		return -ENOENT;
-	}
-	return 0;
-}
-
-static int mac_addr_used = 2;
-
-static void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom,
-					const char *prefix, bool fallback)
-{
-	bool fb = fallback;
-
-	nvram_read_macaddr(prefix, "et0macaddr", sprom->et0mac, fallback);
-	nvram_read_u8(prefix, NULL, "et0mdcport", &sprom->et0mdcport, 0,
-		      fallback);
-	nvram_read_u8(prefix, NULL, "et0phyaddr", &sprom->et0phyaddr, 0,
-		      fallback);
-
-	nvram_read_macaddr(prefix, "et1macaddr", sprom->et1mac, fallback);
-	nvram_read_u8(prefix, NULL, "et1mdcport", &sprom->et1mdcport, 0,
-		      fallback);
-	nvram_read_u8(prefix, NULL, "et1phyaddr", &sprom->et1phyaddr, 0,
-		      fallback);
-
-	nvram_read_macaddr(prefix, "et2macaddr", sprom->et2mac, fb);
-	nvram_read_u8(prefix, NULL, "et2mdcport", &sprom->et2mdcport, 0, fb);
-	nvram_read_u8(prefix, NULL, "et2phyaddr", &sprom->et2phyaddr, 0, fb);
-
-	nvram_read_macaddr(prefix, "macaddr", sprom->il0mac, fallback);
-	nvram_read_macaddr(prefix, "il0macaddr", sprom->il0mac, fallback);
-
-	/* The address prefix 00:90:4C is used by Broadcom in their initial
-	 * configuration. When a mac address with the prefix 00:90:4C is used
-	 * all devices from the same series are sharing the same mac address.
-	 * To prevent mac address collisions we replace them with a mac address
-	 * based on the base address.
-	 */
-	if (!bcm47xx_is_valid_mac(sprom->il0mac)) {
-		u8 mac[6];
-
-		nvram_read_macaddr(NULL, "et0macaddr", mac, false);
-		if (bcm47xx_is_valid_mac(mac)) {
-			int err = bcm47xx_increase_mac_addr(mac, mac_addr_used);
-
-			if (!err) {
-				ether_addr_copy(sprom->il0mac, mac);
-				mac_addr_used++;
-			}
-		}
-	}
-}
-
-static void bcm47xx_fill_board_data(struct ssb_sprom *sprom, const char *prefix,
-				    bool fallback)
-{
-	nvram_read_u32_2(prefix, "boardflags", &sprom->boardflags_lo,
-			 &sprom->boardflags_hi, fallback);
-	nvram_read_u32_2(prefix, "boardflags2", &sprom->boardflags2_lo,
-			 &sprom->boardflags2_hi, fallback);
-}
-
-void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix,
-			bool fallback)
-{
-	bcm47xx_fill_sprom_ethernet(sprom, prefix, fallback);
-	bcm47xx_fill_board_data(sprom, prefix, fallback);
-
-	nvram_read_u8(prefix, NULL, "sromrev", &sprom->revision, 0, fallback);
-
-	/* Entries requiring custom functions */
-	nvram_read_alpha2(prefix, "ccode", sprom->alpha2, fallback);
-	if (sprom->revision >= 3)
-		nvram_read_leddc(prefix, "leddc", &sprom->leddc_on_time,
-				 &sprom->leddc_off_time, fallback);
-
-	switch (sprom->revision) {
-	case 4:
-	case 5:
-		bcm47xx_fill_sprom_path_r4589(sprom, prefix, fallback);
-		bcm47xx_fill_sprom_path_r45(sprom, prefix, fallback);
-		break;
-	case 8:
-	case 9:
-		bcm47xx_fill_sprom_path_r4589(sprom, prefix, fallback);
-		break;
-	}
-
-	bcm47xx_sprom_fill_auto(sprom, prefix, fallback);
-}
-
-#if defined(CONFIG_BCM47XX_SSB)
-static int bcm47xx_get_sprom_ssb(struct ssb_bus *bus, struct ssb_sprom *out)
-{
-	char prefix[10];
-
-	switch (bus->bustype) {
-	case SSB_BUSTYPE_SSB:
-		bcm47xx_fill_sprom(out, NULL, false);
-		return 0;
-	case SSB_BUSTYPE_PCI:
-		memset(out, 0, sizeof(struct ssb_sprom));
-		snprintf(prefix, sizeof(prefix), "pci/%u/%u/",
-			 bus->host_pci->bus->number + 1,
-			 PCI_SLOT(bus->host_pci->devfn));
-		bcm47xx_fill_sprom(out, prefix, false);
-		return 0;
-	default:
-		pr_warn("Unable to fill SPROM for given bustype.\n");
-		return -EINVAL;
-	}
-}
-#endif
-
-#if defined(CONFIG_BCM47XX_BCMA)
-/*
- * Having many NVRAM entries for PCI devices led to repeating prefixes like
- * pci/1/1/ all the time and wasting flash space. So at some point Broadcom
- * decided to introduce prefixes like 0: 1: 2: etc.
- * If we find e.g. devpath0=pci/2/1 or devpath0=pci/2/1/ we should use 0:
- * instead of pci/2/1/.
- */
-static void bcm47xx_sprom_apply_prefix_alias(char *prefix, size_t prefix_size)
-{
-	size_t prefix_len = strlen(prefix);
-	size_t short_len = prefix_len - 1;
-	char nvram_var[10];
-	char buf[20];
-	int i;
-
-	/* Passed prefix has to end with a slash */
-	if (prefix_len <= 0 || prefix[prefix_len - 1] != '/')
-		return;
-
-	for (i = 0; i < 3; i++) {
-		if (snprintf(nvram_var, sizeof(nvram_var), "devpath%d", i) <= 0)
-			continue;
-		if (bcm47xx_nvram_getenv(nvram_var, buf, sizeof(buf)) < 0)
-			continue;
-		if (!strcmp(buf, prefix) ||
-		    (short_len && strlen(buf) == short_len && !strncmp(buf, prefix, short_len))) {
-			snprintf(prefix, prefix_size, "%d:", i);
-			return;
-		}
-	}
-}
-
-static int bcm47xx_get_sprom_bcma(struct bcma_bus *bus, struct ssb_sprom *out)
-{
-	struct bcma_boardinfo *binfo = &bus->boardinfo;
-	struct bcma_device *core;
-	char buf[10];
-	char *prefix;
-	bool fallback = false;
-
-	switch (bus->hosttype) {
-	case BCMA_HOSTTYPE_PCI:
-		memset(out, 0, sizeof(struct ssb_sprom));
-		/* On BCM47XX all PCI buses share the same domain */
-		if (config_enabled(CONFIG_BCM47XX))
-			snprintf(buf, sizeof(buf), "pci/%u/%u/",
-				 bus->host_pci->bus->number + 1,
-				 PCI_SLOT(bus->host_pci->devfn));
-		else
-			snprintf(buf, sizeof(buf), "pci/%u/%u/",
-				 pci_domain_nr(bus->host_pci->bus) + 1,
-				 bus->host_pci->bus->number);
-		bcm47xx_sprom_apply_prefix_alias(buf, sizeof(buf));
-		prefix = buf;
-		break;
-	case BCMA_HOSTTYPE_SOC:
-		memset(out, 0, sizeof(struct ssb_sprom));
-		core = bcma_find_core(bus, BCMA_CORE_80211);
-		if (core) {
-			snprintf(buf, sizeof(buf), "sb/%u/",
-				 core->core_index);
-			prefix = buf;
-			fallback = true;
-		} else {
-			prefix = NULL;
-		}
-		break;
-	default:
-		pr_warn("Unable to fill SPROM for given bustype.\n");
-		return -EINVAL;
-	}
-
-	nvram_read_u16(prefix, NULL, "boardvendor", &binfo->vendor, 0, true);
-	if (!binfo->vendor)
-		binfo->vendor = SSB_BOARDVENDOR_BCM;
-	nvram_read_u16(prefix, NULL, "boardtype", &binfo->type, 0, true);
-
-	bcm47xx_fill_sprom(out, prefix, fallback);
-
-	return 0;
-}
-#endif
-
-/*
- * On bcm47xx we need to register SPROM fallback handler very early, so we can't
- * use anything like platform device / driver for this.
- */
-void bcm47xx_sprom_register_fallbacks(void)
-{
-#if defined(CONFIG_BCM47XX_SSB)
-	if (ssb_arch_register_fallback_sprom(&bcm47xx_get_sprom_ssb))
-		pr_warn("Failed to register ssb SPROM handler\n");
-#endif
-
-#if defined(CONFIG_BCM47XX_BCMA)
-	if (bcma_arch_register_fallback_sprom(&bcm47xx_get_sprom_bcma))
-		pr_warn("Failed to register bcma SPROM handler\n");
-#endif
-}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/bmips/Kconfig linux-libre-4.7-gnu/arch/mips/bmips/Kconfig
--- linux-libre-4.6-gnu/arch/mips/bmips/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/bmips/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -21,6 +21,10 @@ config DT_BCM93384WVG_VIPER
 	bool "BCM93384WVG Viper CPU (EXPERIMENTAL)"
 	select BUILTIN_DTB
 
+config DT_BCM96358NB4SER
+	bool "BCM96358NB4SER"
+	select BUILTIN_DTB
+
 config DT_BCM96368MVWG
 	bool "BCM96368MVWG"
 	select BUILTIN_DTB
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/bmips/setup.c linux-libre-4.7-gnu/arch/mips/bmips/setup.c
--- linux-libre-4.6-gnu/arch/mips/bmips/setup.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/bmips/setup.c	2016-07-24 15:23:50.000000000 -0400
@@ -95,6 +95,15 @@ static void bcm6328_quirks(void)
 		bcm63xx_fixup_cpu1();
 }
 
+static void bcm6358_quirks(void)
+{
+	/*
+	 * BCM6358 needs special handling for its shared TLB, so
+	 * disable SMP for now
+	 */
+	bmips_smp_enabled = 0;
+}
+
 static void bcm6368_quirks(void)
 {
 	bcm63xx_fixup_cpu1();
@@ -104,13 +113,16 @@ static const struct bmips_quirk bmips_qu
 	{ "brcm,bcm3384-viper",		&bcm3384_viper_quirks		},
 	{ "brcm,bcm33843-viper",	&bcm3384_viper_quirks		},
 	{ "brcm,bcm6328",		&bcm6328_quirks			},
+	{ "brcm,bcm6358",		&bcm6358_quirks			},
 	{ "brcm,bcm6368",		&bcm6368_quirks			},
 	{ "brcm,bcm63168",		&bcm6368_quirks			},
+	{ "brcm,bcm63268",		&bcm6368_quirks			},
 	{ },
 };
 
 void __init prom_init(void)
 {
+	bmips_cpu_setup();
 	register_bmips_smp_ops();
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/compressed/Makefile linux-libre-4.7-gnu/arch/mips/boot/compressed/Makefile
--- linux-libre-4.6-gnu/arch/mips/boot/compressed/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/boot/compressed/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -37,8 +37,13 @@ vmlinuzobjs-$(CONFIG_DEBUG_ZBOOT)		   +=
 vmlinuzobjs-$(CONFIG_SYS_SUPPORTS_ZBOOT_UART16550) += $(obj)/uart-16550.o
 vmlinuzobjs-$(CONFIG_SYS_SUPPORTS_ZBOOT_UART_PROM) += $(obj)/uart-prom.o
 vmlinuzobjs-$(CONFIG_MIPS_ALCHEMY)		   += $(obj)/uart-alchemy.o
+vmlinuzobjs-$(CONFIG_ATH79)			   += $(obj)/uart-ath79.o
 endif
 
+extra-y += uart-ath79.c
+$(obj)/uart-ath79.c: $(srctree)/arch/mips/ath79/early_printk.c
+	$(call cmd,shipped)
+
 vmlinuzobjs-$(CONFIG_KERNEL_XZ) += $(obj)/ashldi3.o $(obj)/bswapsi.o
 
 extra-y += ashldi3.c bswapsi.c
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/brcm/bcm6328.dtsi linux-libre-4.7-gnu/arch/mips/boot/dts/brcm/bcm6328.dtsi
--- linux-libre-4.6-gnu/arch/mips/boot/dts/brcm/bcm6328.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/brcm/bcm6328.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -23,7 +23,7 @@
 	};
 
 	clocks {
-		periph_clk: periph_clk {
+		periph_clk: periph-clk {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <50000000>;
@@ -31,11 +31,11 @@
 	};
 
 	aliases {
-		leds0 = &leds0;
-		uart0 = &uart0;
+		serial0 = &uart0;
+		serial1 = &uart1;
 	};
 
-	cpu_intc: cpu_intc {
+	cpu_intc: interrupt-controller {
 		#address-cells = <0>;
 		compatible = "mti,cpu-interrupt-controller";
 
@@ -50,16 +50,16 @@
 		compatible = "simple-bus";
 		ranges;
 
-		periph_intc: periph_intc@10000020 {
-			compatible = "brcm,bcm3380-l2-intc";
-			reg = <0x10000024 0x4 0x1000002c 0x4>,
-			      <0x10000020 0x4 0x10000028 0x4>;
+		periph_intc: interrupt-controller@10000020 {
+			compatible = "brcm,bcm6345-l1-intc";
+			reg = <0x10000020 0x10>,
+			      <0x10000030 0x10>;
 
 			interrupt-controller;
 			#interrupt-cells = <1>;
 
 			interrupt-parent = <&cpu_intc>;
-			interrupts = <2>;
+			interrupts = <2>, <3>;
 		};
 
 		uart0: serial@10000100 {
@@ -71,13 +71,22 @@
 			status = "disabled";
 		};
 
-		timer: timer@10000040 {
+		uart1: serial@10000120 {
+			compatible = "brcm,bcm6345-uart";
+			reg = <0x10000120 0x18>;
+			interrupt-parent = <&periph_intc>;
+			interrupts = <39>;
+			clocks = <&periph_clk>;
+			status = "disabled";
+		};
+
+		timer: syscon@10000040 {
 			compatible = "syscon";
 			reg = <0x10000040 0x2c>;
 			native-endian;
 		};
 
-		reboot {
+		reboot: syscon-reboot@10000068 {
 			compatible = "syscon-reboot";
 			regmap = <&timer>;
 			offset = <0x28>;
@@ -91,5 +100,24 @@
 			reg = <0x10000800 0x24>;
 			status = "disabled";
 		};
+
+		ehci: usb@10002500 {
+			compatible = "brcm,bcm6328-ehci", "generic-ehci";
+			reg = <0x10002500 0x100>;
+			big-endian;
+			interrupt-parent = <&periph_intc>;
+			interrupts = <42>;
+			status = "disabled";
+		};
+
+		ohci: usb@10002600 {
+			compatible = "brcm,bcm6328-ohci", "generic-ohci";
+			reg = <0x10002600 0x100>;
+			big-endian;
+			no-big-frame-no;
+			interrupt-parent = <&periph_intc>;
+			interrupts = <41>;
+			status = "disabled";
+		};
 	};
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/brcm/bcm6358.dtsi linux-libre-4.7-gnu/arch/mips/boot/dts/brcm/bcm6358.dtsi
--- linux-libre-4.6-gnu/arch/mips/boot/dts/brcm/bcm6358.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/brcm/bcm6358.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,130 @@
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	compatible = "brcm,bcm6358";
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		mips-hpt-frequency = <150000000>;
+
+		cpu@0 {
+			compatible = "brcm,bmips4350";
+			device_type = "cpu";
+			reg = <0>;
+		};
+
+		cpu@1 {
+			compatible = "brcm,bmips4350";
+			device_type = "cpu";
+			reg = <1>;
+		};
+	};
+
+	clocks {
+		periph_clk: periph-clk {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <50000000>;
+		};
+	};
+
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+	};
+
+	cpu_intc: interrupt-controller {
+		#address-cells = <0>;
+		compatible = "mti,cpu-interrupt-controller";
+
+		interrupt-controller;
+		#interrupt-cells = <1>;
+	};
+
+	ubus {
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		compatible = "simple-bus";
+		ranges;
+
+		periph_cntl: syscon@fffe0000 {
+			compatible = "syscon";
+			reg = <0xfffe0000 0xc>;
+			native-endian;
+		};
+
+		reboot: syscon-reboot@fffe0008 {
+			compatible = "syscon-reboot";
+			regmap = <&periph_cntl>;
+			offset = <0x8>;
+			mask = <0x1>;
+		};
+
+		periph_intc: interrupt-controller@fffe000c {
+			compatible = "brcm,bcm6345-l1-intc";
+			reg = <0xfffe000c 0x8>,
+			      <0xfffe0038 0x8>;
+
+			interrupt-controller;
+			#interrupt-cells = <1>;
+
+			interrupt-parent = <&cpu_intc>;
+			interrupts = <2>, <3>;
+		};
+
+		leds0: led-controller@fffe00d0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "brcm,bcm6358-leds";
+			reg = <0xfffe00d0 0x8>;
+
+			status = "disabled";
+		};
+
+		uart0: serial@fffe0100 {
+			compatible = "brcm,bcm6345-uart";
+			reg = <0xfffe0100 0x18>;
+
+			interrupt-parent = <&periph_intc>;
+			interrupts = <2>;
+
+			clocks = <&periph_clk>;
+
+			status = "disabled";
+		};
+
+		uart1: serial@fffe0120 {
+			compatible = "brcm,bcm6345-uart";
+			reg = <0xfffe0120 0x18>;
+
+			interrupt-parent = <&periph_intc>;
+			interrupts = <3>;
+
+			clocks = <&periph_clk>;
+
+			status = "disabled";
+		};
+
+		ehci: usb@fffe1300 {
+			compatible = "brcm,bcm6358-ehci", "generic-ehci";
+			reg = <0xfffe1300 0x100>;
+			big-endian;
+			interrupt-parent = <&periph_intc>;
+			interrupts = <10>;
+			status = "disabled";
+		};
+
+		ohci: usb@fffe1400 {
+			compatible = "brcm,bcm6358-ohci", "generic-ohci";
+			reg = <0xfffe1400 0x100>;
+			big-endian;
+			no-big-frame-no;
+			interrupt-parent = <&periph_intc>;
+			interrupts = <5>;
+			status = "disabled";
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/brcm/bcm6368.dtsi linux-libre-4.7-gnu/arch/mips/boot/dts/brcm/bcm6368.dtsi
--- linux-libre-4.6-gnu/arch/mips/boot/dts/brcm/bcm6368.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/brcm/bcm6368.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -20,11 +20,10 @@
 			device_type = "cpu";
 			reg = <1>;
 		};
-
 	};
 
 	clocks {
-		periph_clk: periph_clk {
+		periph_clk: periph-clk {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <50000000>;
@@ -32,11 +31,11 @@
 	};
 
 	aliases {
-		leds0 = &leds0;
-		uart0 = &uart0;
+		serial0 = &uart0;
+		serial1 = &uart1;
 	};
 
-	cpu_intc: cpu_intc {
+	cpu_intc: interrupt-controller {
 		#address-cells = <0>;
 		compatible = "mti,cpu-interrupt-controller";
 
@@ -64,16 +63,16 @@
 			mask = <0x1>;
 		};
 
-		periph_intc: periph_intc@10000020 {
-			compatible = "brcm,bcm3380-l2-intc";
-			reg = <0x10000024 0x4 0x1000002c 0x4>,
-			      <0x10000020 0x4 0x10000028 0x4>;
+		periph_intc: interrupt-controller@10000020 {
+			compatible = "brcm,bcm6345-l1-intc";
+			reg = <0x10000020 0x10>,
+			      <0x10000030 0x10>;
 
 			interrupt-controller;
 			#interrupt-cells = <1>;
 
 			interrupt-parent = <&cpu_intc>;
-			interrupts = <2>;
+			interrupts = <2>, <3>;
 		};
 
 		leds0: led-controller@100000d0 {
@@ -93,7 +92,16 @@
 			status = "disabled";
 		};
 
-		ehci0: usb@10001500 {
+		uart1: serial@10000120 {
+			compatible = "brcm,bcm6345-uart";
+			reg = <0x10000120 0x18>;
+			interrupt-parent = <&periph_intc>;
+			interrupts = <3>;
+			clocks = <&periph_clk>;
+			status = "disabled";
+		};
+
+		ehci: usb@10001500 {
 			compatible = "brcm,bcm6368-ehci", "generic-ehci";
 			reg = <0x10001500 0x100>;
 			big-endian;
@@ -102,7 +110,7 @@
 			status = "disabled";
 		};
 
-		ohci0: usb@10001600 {
+		ohci: usb@10001600 {
 			compatible = "brcm,bcm6368-ohci", "generic-ohci";
 			reg = <0x10001600 0x100>;
 			big-endian;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/brcm/bcm7125.dtsi linux-libre-4.7-gnu/arch/mips/boot/dts/brcm/bcm7125.dtsi
--- linux-libre-4.6-gnu/arch/mips/boot/dts/brcm/bcm7125.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/brcm/bcm7125.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -85,14 +85,15 @@
 			compatible = "brcm,bcm7120-l2-intc";
 			reg = <0x406780 0x8>;
 
-			brcm,int-map-mask = <0x44>;
+			brcm,int-map-mask = <0x44>, <0xf000000>;
 			brcm,int-fwd-mask = <0x70000>;
 
 			interrupt-controller;
 			#interrupt-cells = <1>;
 
 			interrupt-parent = <&periph_intc>;
-			interrupts = <18>;
+			interrupts = <18>, <19>;
+			interrupt-names = "upg_main", "upg_bsc";
 		};
 
 		sun_top_ctrl: syscon@404000 {
@@ -118,6 +119,70 @@
 			status = "disabled";
 		};
 
+		uart1: serial@406b40 {
+			compatible = "ns16550a";
+			reg = <0x406b40 0x20>;
+			reg-io-width = <0x4>;
+			reg-shift = <0x2>;
+			native-endian;
+			interrupt-parent = <&periph_intc>;
+			interrupts = <64>;
+			clocks = <&uart_clk>;
+			status = "disabled";
+		};
+
+		uart2: serial@406b80 {
+			compatible = "ns16550a";
+			reg = <0x406b80 0x20>;
+			reg-io-width = <0x4>;
+			reg-shift = <0x2>;
+			native-endian;
+			interrupt-parent = <&periph_intc>;
+			interrupts = <65>;
+			clocks = <&uart_clk>;
+			status = "disabled";
+		};
+
+		bsca: i2c@406200 {
+		      clock-frequency = <390000>;
+		      compatible = "brcm,brcmstb-i2c";
+		      interrupt-parent = <&upg_irq0_intc>;
+		      reg = <0x406200 0x58>;
+		      interrupts = <24>;
+		      interrupt-names = "upg_bsca";
+		      status = "disabled";
+		};
+
+		bscb: i2c@406280 {
+		      clock-frequency = <390000>;
+		      compatible = "brcm,brcmstb-i2c";
+		      interrupt-parent = <&upg_irq0_intc>;
+		      reg = <0x406280 0x58>;
+		      interrupts = <25>;
+		      interrupt-names = "upg_bscb";
+		      status = "disabled";
+		};
+
+		bscc: i2c@406300 {
+		      clock-frequency = <390000>;
+		      compatible = "brcm,brcmstb-i2c";
+		      interrupt-parent = <&upg_irq0_intc>;
+		      reg = <0x406300 0x58>;
+		      interrupts = <26>;
+		      interrupt-names = "upg_bscc";
+		      status = "disabled";
+		};
+
+		bscd: i2c@406380 {
+		      clock-frequency = <390000>;
+		      compatible = "brcm,brcmstb-i2c";
+		      interrupt-parent = <&upg_irq0_intc>;
+		      reg = <0x406380 0x58>;
+		      interrupts = <27>;
+		      interrupt-names = "upg_bscd";
+		      status = "disabled";
+		};
+
 		ehci0: usb@488300 {
 			compatible = "brcm,bcm7125-ehci", "generic-ehci";
 			reg = <0x488300 0x100>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/brcm/bcm7346.dtsi linux-libre-4.7-gnu/arch/mips/boot/dts/brcm/bcm7346.dtsi
--- linux-libre-4.6-gnu/arch/mips/boot/dts/brcm/bcm7346.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/brcm/bcm7346.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -24,8 +24,6 @@
 
 	aliases {
 		uart0 = &uart0;
-		uart1 = &uart1;
-		uart2 = &uart2;
 	};
 
 	cpu_intc: cpu_intc {
@@ -323,8 +321,6 @@
 			interrupts = <40>;
 			#address-cells = <1>;
 			#size-cells = <0>;
-			brcm,broken-ncq;
-			brcm,broken-phy;
 			status = "disabled";
 
 			sata0: sata-port@0 {
@@ -338,7 +334,7 @@
 			};
 		};
 
-		sata_phy: sata-phy@1800000 {
+		sata_phy: sata-phy@180100 {
 			compatible = "brcm,bcm7425-sata-phy", "brcm,phy-sata3";
 			reg = <0x180100 0x0eff>;
 			reg-names = "phy";
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/brcm/bcm7358.dtsi linux-libre-4.7-gnu/arch/mips/boot/dts/brcm/bcm7358.dtsi
--- linux-libre-4.6-gnu/arch/mips/boot/dts/brcm/bcm7358.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/brcm/bcm7358.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -18,8 +18,6 @@
 
 	aliases {
 		uart0 = &uart0;
-		uart1 = &uart1;
-		uart2 = &uart2;
 	};
 
 	cpu_intc: cpu_intc {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/brcm/bcm7360.dtsi linux-libre-4.7-gnu/arch/mips/boot/dts/brcm/bcm7360.dtsi
--- linux-libre-4.6-gnu/arch/mips/boot/dts/brcm/bcm7360.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/brcm/bcm7360.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -18,8 +18,6 @@
 
 	aliases {
 		uart0 = &uart0;
-		uart1 = &uart1;
-		uart2 = &uart2;
 	};
 
 	cpu_intc: cpu_intc {
@@ -241,5 +239,45 @@
 			interrupts = <66>;
 			status = "disabled";
 		};
+
+		sata: sata@181000 {
+			compatible = "brcm,bcm7425-ahci", "brcm,sata3-ahci";
+			reg-names = "ahci", "top-ctrl";
+			reg = <0x181000 0xa9c>, <0x180020 0x1c>;
+			interrupt-parent = <&periph_intc>;
+			interrupts = <86>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+
+			sata0: sata-port@0 {
+				reg = <0>;
+				phys = <&sata_phy0>;
+			};
+
+			sata1: sata-port@1 {
+				reg = <1>;
+				phys = <&sata_phy1>;
+			};
+		};
+
+		sata_phy: sata-phy@180100 {
+			compatible = "brcm,bcm7425-sata-phy", "brcm,phy-sata3";
+			reg = <0x180100 0x0eff>;
+			reg-names = "phy";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+
+			sata_phy0: sata-phy@0 {
+				reg = <0>;
+				#phy-cells = <0>;
+			};
+
+			sata_phy1: sata-phy@1 {
+				reg = <1>;
+				#phy-cells = <0>;
+			};
+		};
 	};
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/brcm/bcm7362.dtsi linux-libre-4.7-gnu/arch/mips/boot/dts/brcm/bcm7362.dtsi
--- linux-libre-4.6-gnu/arch/mips/boot/dts/brcm/bcm7362.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/brcm/bcm7362.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -24,8 +24,6 @@
 
 	aliases {
 		uart0 = &uart0;
-		uart1 = &uart1;
-		uart2 = &uart2;
 	};
 
 	cpu_intc: cpu_intc {
@@ -246,8 +244,6 @@
 			interrupts = <86>;
 			#address-cells = <1>;
 			#size-cells = <0>;
-			brcm,broken-ncq;
-			brcm,broken-phy;
 			status = "disabled";
 
 			sata0: sata-port@0 {
@@ -261,7 +257,7 @@
 			};
 		};
 
-		sata_phy: sata-phy@1800000 {
+		sata_phy: sata-phy@180100 {
 			compatible = "brcm,bcm7425-sata-phy", "brcm,phy-sata3";
 			reg = <0x180100 0x0eff>;
 			reg-names = "phy";
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/brcm/bcm7420.dtsi linux-libre-4.7-gnu/arch/mips/boot/dts/brcm/bcm7420.dtsi
--- linux-libre-4.6-gnu/arch/mips/boot/dts/brcm/bcm7420.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/brcm/bcm7420.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -86,14 +86,15 @@
 			compatible = "brcm,bcm7120-l2-intc";
 			reg = <0x406780 0x8>;
 
-			brcm,int-map-mask = <0x44>;
+			brcm,int-map-mask = <0x44>, <0x1f000000>;
 			brcm,int-fwd-mask = <0x70000>;
 
 			interrupt-controller;
 			#interrupt-cells = <1>;
 
 			interrupt-parent = <&periph_intc>;
-			interrupts = <18>;
+			interrupts = <18>, <19>;
+			interrupt-names = "upg_main", "upg_bsc";
 		};
 
 		sun_top_ctrl: syscon@404000 {
@@ -118,6 +119,78 @@
 			status = "disabled";
 		};
 
+		uart1: serial@406b40 {
+			compatible = "ns16550a";
+			reg = <0x406b40 0x20>;
+			reg-io-width = <0x4>;
+			reg-shift = <0x2>;
+			interrupt-parent = <&periph_intc>;
+			interrupts = <64>;
+			clocks = <&uart_clk>;
+			status = "disabled";
+		};
+
+		uart2: serial@406b80 {
+			compatible = "ns16550a";
+			reg = <0x406b80 0x20>;
+			reg-io-width = <0x4>;
+			reg-shift = <0x2>;
+			interrupt-parent = <&periph_intc>;
+			interrupts = <65>;
+			clocks = <&uart_clk>;
+			status = "disabled";
+		};
+
+		bsca: i2c@406200 {
+		      clock-frequency = <390000>;
+		      compatible = "brcm,brcmstb-i2c";
+		      interrupt-parent = <&upg_irq0_intc>;
+		      reg = <0x406200 0x58>;
+		      interrupts = <24>;
+		      interrupt-names = "upg_bsca";
+		      status = "disabled";
+		};
+
+		bscb: i2c@406280 {
+		      clock-frequency = <390000>;
+		      compatible = "brcm,brcmstb-i2c";
+		      interrupt-parent = <&upg_irq0_intc>;
+		      reg = <0x406280 0x58>;
+		      interrupts = <25>;
+		      interrupt-names = "upg_bscb";
+		      status = "disabled";
+		};
+
+		bscc: i2c@406300 {
+		      clock-frequency = <390000>;
+		      compatible = "brcm,brcmstb-i2c";
+		      interrupt-parent = <&upg_irq0_intc>;
+		      reg = <0x406300 0x58>;
+		      interrupts = <26>;
+		      interrupt-names = "upg_bscc";
+		      status = "disabled";
+		};
+
+		bscd: i2c@406380 {
+		      clock-frequency = <390000>;
+		      compatible = "brcm,brcmstb-i2c";
+		      interrupt-parent = <&upg_irq0_intc>;
+		      reg = <0x406380 0x58>;
+		      interrupts = <27>;
+		      interrupt-names = "upg_bscd";
+		      status = "disabled";
+		};
+
+		bsce: i2c@406800 {
+		      clock-frequency = <390000>;
+		      compatible = "brcm,brcmstb-i2c";
+		      interrupt-parent = <&upg_irq0_intc>;
+		      reg = <0x406800 0x58>;
+		      interrupts = <28>;
+		      interrupt-names = "upg_bsce";
+		      status = "disabled";
+		};
+
 		enet0: ethernet@468000 {
 			phy-mode = "internal";
 			phy-handle = <&phy1>;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/brcm/bcm7425.dtsi linux-libre-4.7-gnu/arch/mips/boot/dts/brcm/bcm7425.dtsi
--- linux-libre-4.6-gnu/arch/mips/boot/dts/brcm/bcm7425.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/brcm/bcm7425.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -87,14 +87,32 @@
 			compatible = "brcm,bcm7120-l2-intc";
 			reg = <0x406780 0x8>;
 
-			brcm,int-map-mask = <0x44>;
+			brcm,int-map-mask = <0x44>, <0x7000000>;
 			brcm,int-fwd-mask = <0x70000>;
 
 			interrupt-controller;
 			#interrupt-cells = <1>;
 
 			interrupt-parent = <&periph_intc>;
-			interrupts = <55>;
+			interrupts = <55>, <53>;
+			interrupt-names = "upg_main", "upg_bsc";
+		};
+
+		upg_aon_irq0_intc: upg_aon_irq0_intc@409480 {
+			compatible = "brcm,bcm7120-l2-intc";
+			reg = <0x409480 0x8>;
+
+			brcm,int-map-mask = <0x40>, <0x18000000>, <0x100000>;
+			brcm,int-fwd-mask = <0>;
+			brcm,irq-can-wake;
+
+			interrupt-controller;
+			#interrupt-cells = <1>;
+
+			interrupt-parent = <&periph_intc>;
+			interrupts = <56>, <54>, <59>;
+			interrupt-names = "upg_main_aon", "upg_bsc_aon",
+					  "upg_spi";
 		};
 
 		sun_top_ctrl: syscon@404000 {
@@ -119,6 +137,78 @@
 			status = "disabled";
 		};
 
+		uart1: serial@406b40 {
+			compatible = "ns16550a";
+			reg = <0x406b40 0x20>;
+			reg-io-width = <0x4>;
+			reg-shift = <0x2>;
+			interrupt-parent = <&periph_intc>;
+			interrupts = <62>;
+			clocks = <&uart_clk>;
+			status = "disabled";
+		};
+
+		uart2: serial@406b80 {
+			compatible = "ns16550a";
+			reg = <0x406b80 0x20>;
+			reg-io-width = <0x4>;
+			reg-shift = <0x2>;
+			interrupt-parent = <&periph_intc>;
+			interrupts = <63>;
+			clocks = <&uart_clk>;
+			status = "disabled";
+		};
+
+		bsca: i2c@409180 {
+		      clock-frequency = <390000>;
+		      compatible = "brcm,brcmstb-i2c";
+		      interrupt-parent = <&upg_aon_irq0_intc>;
+		      reg = <0x409180 0x58>;
+		      interrupts = <27>;
+		      interrupt-names = "upg_bsca";
+		      status = "disabled";
+		};
+
+		bscb: i2c@409400 {
+		      clock-frequency = <390000>;
+		      compatible = "brcm,brcmstb-i2c";
+		      interrupt-parent = <&upg_aon_irq0_intc>;
+		      reg = <0x409400 0x58>;
+		      interrupts = <28>;
+		      interrupt-names = "upg_bscb";
+		      status = "disabled";
+		};
+
+		bscc: i2c@406200 {
+		      clock-frequency = <390000>;
+		      compatible = "brcm,brcmstb-i2c";
+		      interrupt-parent = <&upg_irq0_intc>;
+		      reg = <0x406200 0x58>;
+		      interrupts = <24>;
+		      interrupt-names = "upg_bscc";
+		      status = "disabled";
+		};
+
+		bscd: i2c@406280 {
+		      clock-frequency = <390000>;
+		      compatible = "brcm,brcmstb-i2c";
+		      interrupt-parent = <&upg_irq0_intc>;
+		      reg = <0x406280 0x58>;
+		      interrupts = <25>;
+		      interrupt-names = "upg_bscd";
+		      status = "disabled";
+		};
+
+		bsce: i2c@406300 {
+		      clock-frequency = <390000>;
+		      compatible = "brcm,brcmstb-i2c";
+		      interrupt-parent = <&upg_irq0_intc>;
+		      reg = <0x406300 0x58>;
+		      interrupts = <26>;
+		      interrupt-names = "upg_bsce";
+		      status = "disabled";
+		};
+
 		enet0: ethernet@b80000 {
 			phy-mode = "internal";
 			phy-handle = <&phy1>;
@@ -227,11 +317,9 @@
 			reg-names = "ahci", "top-ctrl";
 			reg = <0x181000 0xa9c>, <0x180020 0x1c>;
 			interrupt-parent = <&periph_intc>;
-			interrupts = <40>;
+			interrupts = <41>;
 			#address-cells = <1>;
 			#size-cells = <0>;
-			brcm,broken-ncq;
-			brcm,broken-phy;
 			status = "disabled";
 
 			sata0: sata-port@0 {
@@ -245,7 +333,7 @@
 			};
 		};
 
-		sata_phy: sata-phy@1800000 {
+		sata_phy: sata-phy@180100 {
 			compatible = "brcm,bcm7425-sata-phy", "brcm,phy-sata3";
 			reg = <0x180100 0x0eff>;
 			reg-names = "phy";
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/brcm/bcm7435.dtsi linux-libre-4.7-gnu/arch/mips/boot/dts/brcm/bcm7435.dtsi
--- linux-libre-4.6-gnu/arch/mips/boot/dts/brcm/bcm7435.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/brcm/bcm7435.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -7,7 +7,7 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		mips-hpt-frequency = <163125000>;
+		mips-hpt-frequency = <175625000>;
 
 		cpu@0 {
 			compatible = "brcm,bmips5200";
@@ -63,13 +63,14 @@
 
 		periph_intc: periph_intc@41b500 {
 			compatible = "brcm,bcm7038-l1-intc";
-			reg = <0x41b500 0x40>, <0x41b600 0x40>;
+			reg = <0x41b500 0x40>, <0x41b600 0x40>,
+				<0x41b700 0x40>, <0x41b800 0x40>;
 
 			interrupt-controller;
 			#interrupt-cells = <1>;
 
 			interrupt-parent = <&cpu_intc>;
-			interrupts = <2>, <3>;
+			interrupts = <2>, <3>, <2>, <3>;
 		};
 
 		sun_l2_intc: sun_l2_intc@403000 {
@@ -101,14 +102,32 @@
 			compatible = "brcm,bcm7120-l2-intc";
 			reg = <0x406780 0x8>;
 
-			brcm,int-map-mask = <0x44>;
+			brcm,int-map-mask = <0x44>, <0x7000000>;
 			brcm,int-fwd-mask = <0x70000>;
 
 			interrupt-controller;
 			#interrupt-cells = <1>;
 
 			interrupt-parent = <&periph_intc>;
-			interrupts = <60>;
+			interrupts = <60>, <58>;
+			interrupt-names = "upg_main", "upg_bsc";
+		};
+
+		upg_aon_irq0_intc: upg_aon_irq0_intc@409480 {
+			compatible = "brcm,bcm7120-l2-intc";
+			reg = <0x409480 0x8>;
+
+			brcm,int-map-mask = <0x40>, <0x18000000>, <0x100000>;
+			brcm,int-fwd-mask = <0>;
+			brcm,irq-can-wake;
+
+			interrupt-controller;
+			#interrupt-cells = <1>;
+
+			interrupt-parent = <&periph_intc>;
+			interrupts = <61>, <59>, <64>;
+			interrupt-names = "upg_main_aon", "upg_bsc_aon",
+					  "upg_spi";
 		};
 
 		sun_top_ctrl: syscon@404000 {
@@ -133,6 +152,78 @@
 			status = "disabled";
 		};
 
+		uart1: serial@406b40 {
+			compatible = "ns16550a";
+			reg = <0x406b40 0x20>;
+			reg-io-width = <0x4>;
+			reg-shift = <0x2>;
+			interrupt-parent = <&periph_intc>;
+			interrupts = <67>;
+			clocks = <&uart_clk>;
+			status = "disabled";
+		};
+
+		uart2: serial@406b80 {
+			compatible = "ns16550a";
+			reg = <0x406b80 0x20>;
+			reg-io-width = <0x4>;
+			reg-shift = <0x2>;
+			interrupt-parent = <&periph_intc>;
+			interrupts = <68>;
+			clocks = <&uart_clk>;
+			status = "disabled";
+		};
+
+		bsca: i2c@406300 {
+		      clock-frequency = <390000>;
+		      compatible = "brcm,brcmstb-i2c";
+		      interrupt-parent = <&upg_irq0_intc>;
+		      reg = <0x406300 0x58>;
+		      interrupts = <26>;
+		      interrupt-names = "upg_bsca";
+		      status = "disabled";
+		};
+
+		bscb: i2c@409400 {
+		      clock-frequency = <390000>;
+		      compatible = "brcm,brcmstb-i2c";
+		      interrupt-parent = <&upg_aon_irq0_intc>;
+		      reg = <0x409400 0x58>;
+		      interrupts = <28>;
+		      interrupt-names = "upg_bscb";
+		      status = "disabled";
+		};
+
+		bscc: i2c@406200 {
+		      clock-frequency = <390000>;
+		      compatible = "brcm,brcmstb-i2c";
+		      interrupt-parent = <&upg_irq0_intc>;
+		      reg = <0x406200 0x58>;
+		      interrupts = <24>;
+		      interrupt-names = "upg_bscc";
+		      status = "disabled";
+		};
+
+		bscd: i2c@406280 {
+		      clock-frequency = <390000>;
+		      compatible = "brcm,brcmstb-i2c";
+		      interrupt-parent = <&upg_irq0_intc>;
+		      reg = <0x406280 0x58>;
+		      interrupts = <25>;
+		      interrupt-names = "upg_bscd";
+		      status = "disabled";
+		};
+
+		bsce: i2c@409180 {
+		      clock-frequency = <390000>;
+		      compatible = "brcm,brcmstb-i2c";
+		      interrupt-parent = <&upg_aon_irq0_intc>;
+		      reg = <0x409180 0x58>;
+		      interrupts = <27>;
+		      interrupt-names = "upg_bsce";
+		      status = "disabled";
+		};
+
 		enet0: ethernet@b80000 {
 			phy-mode = "internal";
 			phy-handle = <&phy1>;
@@ -235,5 +326,45 @@
 			interrupts = <78>;
 			status = "disabled";
 		};
+
+		sata: sata@181000 {
+			compatible = "brcm,bcm7425-ahci", "brcm,sata3-ahci";
+			reg-names = "ahci", "top-ctrl";
+			reg = <0x181000 0xa9c>, <0x180020 0x1c>;
+			interrupt-parent = <&periph_intc>;
+			interrupts = <45>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+
+			sata0: sata-port@0 {
+				reg = <0>;
+				phys = <&sata_phy0>;
+			};
+
+			sata1: sata-port@1 {
+				reg = <1>;
+				phys = <&sata_phy1>;
+			};
+		};
+
+		sata_phy: sata-phy@180100 {
+			compatible = "brcm,bcm7425-sata-phy", "brcm,phy-sata3";
+			reg = <0x180100 0x0eff>;
+			reg-names = "phy";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+
+			sata_phy0: sata-phy@0 {
+				reg = <0>;
+				#phy-cells = <0>;
+			};
+
+			sata_phy1: sata-phy@1 {
+				reg = <1>;
+				#phy-cells = <0>;
+			};
+		};
 	};
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/brcm/bcm96358nb4ser.dts linux-libre-4.7-gnu/arch/mips/boot/dts/brcm/bcm96358nb4ser.dts
--- linux-libre-4.6-gnu/arch/mips/boot/dts/brcm/bcm96358nb4ser.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/brcm/bcm96358nb4ser.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,46 @@
+/dts-v1/;
+
+/include/ "bcm6358.dtsi"
+
+/ {
+	compatible = "sfr,nb4-ser", "brcm,bcm6358";
+	model = "SFR Neufbox 4 (Sercomm)";
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x00000000 0x02000000>;
+	};
+
+	chosen {
+		stdout-path = &uart0;
+	};
+};
+
+&leds0 {
+	status = "ok";
+
+	led@0 {
+		reg = <0>;
+		active-low;
+		label = "nb4-ser:white:alarm";
+	};
+	led@2 {
+		reg = <2>;
+		active-low;
+		label = "nb4-ser:white:tv";
+	};
+	led@3 {
+		reg = <3>;
+		active-low;
+		label = "nb4-ser:white:tel";
+	};
+	led@4 {
+		reg = <4>;
+		active-low;
+		label = "nb4-ser:white:adsl";
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/brcm/bcm96368mvwg.dts linux-libre-4.7-gnu/arch/mips/boot/dts/brcm/bcm96368mvwg.dts
--- linux-libre-4.6-gnu/arch/mips/boot/dts/brcm/bcm96368mvwg.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/brcm/bcm96368mvwg.dts	2016-07-24 15:23:50.000000000 -0400
@@ -22,10 +22,10 @@
 };
 
 /* FIXME: need to set up USB_CTRL registers first */
-&ehci0 {
+&ehci {
 	status = "disabled";
 };
 
-&ohci0 {
+&ohci {
 	status = "disabled";
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/brcm/bcm97125cbmb.dts linux-libre-4.7-gnu/arch/mips/boot/dts/brcm/bcm97125cbmb.dts
--- linux-libre-4.6-gnu/arch/mips/boot/dts/brcm/bcm97125cbmb.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/brcm/bcm97125cbmb.dts	2016-07-24 15:23:50.000000000 -0400
@@ -21,6 +21,30 @@
 	status = "okay";
 };
 
+&uart1 {
+	status = "okay";
+};
+
+&uart2 {
+	status = "okay";
+};
+
+&bsca {
+	status = "okay";
+};
+
+&bscb {
+	status = "okay";
+};
+
+&bscc {
+	status = "okay";
+};
+
+&bscd {
+	status = "okay";
+};
+
 /* FIXME: USB is wonky; disable it for now */
 &ehci0 {
 	status = "disabled";
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/brcm/bcm97360svmb.dts linux-libre-4.7-gnu/arch/mips/boot/dts/brcm/bcm97360svmb.dts
--- linux-libre-4.6-gnu/arch/mips/boot/dts/brcm/bcm97360svmb.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/brcm/bcm97360svmb.dts	2016-07-24 15:23:50.000000000 -0400
@@ -56,3 +56,11 @@
 &ohci0 {
 	status = "okay";
 };
+
+&sata {
+	status = "okay";
+};
+
+&sata_phy {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/brcm/bcm97420c.dts linux-libre-4.7-gnu/arch/mips/boot/dts/brcm/bcm97420c.dts
--- linux-libre-4.6-gnu/arch/mips/boot/dts/brcm/bcm97420c.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/brcm/bcm97420c.dts	2016-07-24 15:23:50.000000000 -0400
@@ -23,6 +23,34 @@
 	status = "okay";
 };
 
+&uart1 {
+	status = "okay";
+};
+
+&uart2 {
+	status = "okay";
+};
+
+&bsca {
+	status = "okay";
+};
+
+&bscb {
+	status = "okay";
+};
+
+&bscc {
+	status = "okay";
+};
+
+&bscd {
+	status = "okay";
+};
+
+&bsce {
+	status = "okay";
+};
+
 /* FIXME: MAC driver comes up but cannot attach to PHY */
 &enet0 {
 	status = "disabled";
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/brcm/bcm97425svmb.dts linux-libre-4.7-gnu/arch/mips/boot/dts/brcm/bcm97425svmb.dts
--- linux-libre-4.6-gnu/arch/mips/boot/dts/brcm/bcm97425svmb.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/brcm/bcm97425svmb.dts	2016-07-24 15:23:50.000000000 -0400
@@ -23,6 +23,34 @@
 	status = "okay";
 };
 
+&uart1 {
+	status = "okay";
+};
+
+&uart2 {
+	status = "okay";
+};
+
+&bsca {
+	status = "okay";
+};
+
+&bscb {
+	status = "okay";
+};
+
+&bscc {
+	status = "okay";
+};
+
+&bscd {
+	status = "okay";
+};
+
+&bsce {
+	status = "okay";
+};
+
 &enet0 {
 	status = "okay";
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/brcm/bcm97435svmb.dts linux-libre-4.7-gnu/arch/mips/boot/dts/brcm/bcm97435svmb.dts
--- linux-libre-4.6-gnu/arch/mips/boot/dts/brcm/bcm97435svmb.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/brcm/bcm97435svmb.dts	2016-07-24 15:23:50.000000000 -0400
@@ -14,7 +14,7 @@
 	};
 
 	chosen {
-		bootargs = "console=ttyS0,115200 maxcpus=1";
+		bootargs = "console=ttyS0,115200";
 		stdout-path = &uart0;
 	};
 };
@@ -23,6 +23,34 @@
 	status = "okay";
 };
 
+&uart1 {
+	status = "okay";
+};
+
+&uart2 {
+	status = "okay";
+};
+
+&bsca {
+	status = "okay";
+};
+
+&bscb {
+	status = "okay";
+};
+
+&bscc {
+	status = "okay";
+};
+
+&bscd {
+	status = "okay";
+};
+
+&bsce {
+	status = "okay";
+};
+
 &enet0 {
 	status = "okay";
 };
@@ -58,3 +86,11 @@
 &ohci3 {
 	status = "okay";
 };
+
+&sata {
+	status = "okay";
+};
+
+&sata_phy {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/brcm/Makefile linux-libre-4.7-gnu/arch/mips/boot/dts/brcm/Makefile
--- linux-libre-4.6-gnu/arch/mips/boot/dts/brcm/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/brcm/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -1,5 +1,6 @@
 dtb-$(CONFIG_DT_BCM93384WVG)		+= bcm93384wvg.dtb
 dtb-$(CONFIG_DT_BCM93384WVG_VIPER)	+= bcm93384wvg_viper.dtb
+dtb-$(CONFIG_DT_BCM96358NB4SER)		+= bcm96358nb4ser.dtb
 dtb-$(CONFIG_DT_BCM96368MVWG)		+= bcm96368mvwg.dtb
 dtb-$(CONFIG_DT_BCM9EJTAGPRB)		+= bcm9ejtagprb.dtb
 dtb-$(CONFIG_DT_BCM97125CBMB)		+= bcm97125cbmb.dtb
@@ -14,6 +15,7 @@ dtb-$(CONFIG_DT_BCM97435SVMB)		+= bcm974
 dtb-$(CONFIG_DT_NONE)			+= \
 						bcm93384wvg.dtb		\
 						bcm93384wvg_viper.dtb	\
+						bcm96358nb4ser.dtb	\
 						bcm96368mvwg.dtb	\
 						bcm9ejtagprb.dtb	\
 						bcm97125cbmb.dtb	\
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/cavium-octeon/dlink_dsr-1000n.dts linux-libre-4.7-gnu/arch/mips/boot/dts/cavium-octeon/dlink_dsr-1000n.dts
--- linux-libre-4.6-gnu/arch/mips/boot/dts/cavium-octeon/dlink_dsr-1000n.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/cavium-octeon/dlink_dsr-1000n.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,78 @@
+/*
+ * Device tree source for D-Link DSR-1000N.
+ *
+ * Written by: Aaro Koskinen <aaro.koskinen@iki.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/include/ "octeon_3xxx.dtsi"
+
+/ {
+	model = "dlink,dsr-1000n";
+
+	soc@0 {
+		smi0: mdio@1180000001800 {
+			phy8: ethernet-phy@8 {
+				reg = <8>;
+				compatible = "ethernet-phy-ieee802.3-c22";
+			};
+		};
+
+		pip: pip@11800a0000000 {
+			interface@0 {
+				ethernet@0 {
+					fixed-link {
+						speed = <1000>;
+						full-duplex;
+					};
+				};
+				ethernet@1 {
+					fixed-link {
+						speed = <1000>;
+						full-duplex;
+					};
+				};
+				ethernet@2 {
+					phy-handle = <&phy8>;
+				};
+			};
+		};
+
+		twsi0: i2c@1180000001000 {
+			rtc@68 {
+				compatible = "dallas,ds1337";
+				reg = <0x68>;
+			};
+		};
+
+		uart0: serial@1180000000800 {
+			clock-frequency = <500000000>;
+		};
+
+		usbn: usbn@1180068000000 {
+			refclk-frequency = <12000000>;
+			refclk-type = "crystal";
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		usb1 {
+			label = "usb1";
+			gpios = <&gpio 9 1>; /* Active low */
+		};
+
+		usb2 {
+			label = "usb2";
+			gpios = <&gpio 10 1>; /* Active low */
+		};
+	};
+
+	aliases {
+		pip = &pip;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/cavium-octeon/octeon_3xxx.dts linux-libre-4.7-gnu/arch/mips/boot/dts/cavium-octeon/octeon_3xxx.dts
--- linux-libre-4.6-gnu/arch/mips/boot/dts/cavium-octeon/octeon_3xxx.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/cavium-octeon/octeon_3xxx.dts	2016-07-24 15:23:50.000000000 -0400
@@ -1,4 +1,3 @@
-/dts-v1/;
 /*
  * OCTEON 3XXX, 5XXX, 63XX device tree skeleton.
  *
@@ -6,56 +5,12 @@
  * use.	 Because of this, it contains a super-set of the available
  * devices and properties.
  */
-/ {
-	compatible = "cavium,octeon-3860";
-	#address-cells = <2>;
-	#size-cells = <2>;
-	interrupt-parent = <&ciu>;
-
-	soc@0 {
-		compatible = "simple-bus";
-		#address-cells = <2>;
-		#size-cells = <2>;
-		ranges; /* Direct mapping */
-
-		ciu: interrupt-controller@1070000000000 {
-			compatible = "cavium,octeon-3860-ciu";
-			interrupt-controller;
-			/* Interrupts are specified by two parts:
-			 * 1) Controller register (0 or 1)
-			 * 2) Bit within the register (0..63)
-			 */
-			#interrupt-cells = <2>;
-			reg = <0x10700 0x00000000 0x0 0x7000>;
-		};
 
-		gpio: gpio-controller@1070000000800 {
-			#gpio-cells = <2>;
-			compatible = "cavium,octeon-3860-gpio";
-			reg = <0x10700 0x00000800 0x0 0x100>;
-			gpio-controller;
-			/* Interrupts are specified by two parts:
-			 * 1) GPIO pin number (0..15)
-			 * 2) Triggering (1 - edge rising
-			 *		  2 - edge falling
-			 *		  4 - level active high
-			 *		  8 - level active low)
-			 */
-			interrupt-controller;
-			#interrupt-cells = <2>;
-			/* The GPIO pin connect to 16 consecutive CUI bits */
-			interrupts = <0 16>, <0 17>, <0 18>, <0 19>,
-				     <0 20>, <0 21>, <0 22>, <0 23>,
-				     <0 24>, <0 25>, <0 26>, <0 27>,
-				     <0 28>, <0 29>, <0 30>, <0 31>;
-		};
+/include/ "octeon_3xxx.dtsi"
 
+/ {
+	soc@0 {
 		smi0: mdio@1180000001800 {
-			compatible = "cavium,octeon-3860-mdio";
-			#address-cells = <1>;
-			#size-cells = <0>;
-			reg = <0x11800 0x00001800 0x0 0x40>;
-
 			phy0: ethernet-phy@0 {
 				compatible = "marvell,88e1118";
 				marvell,reg-init =
@@ -220,35 +175,16 @@
 		};
 
 		pip: pip@11800a0000000 {
-			compatible = "cavium,octeon-3860-pip";
-			#address-cells = <1>;
-			#size-cells = <0>;
-			reg = <0x11800 0xa0000000 0x0 0x2000>;
-
 			interface@0 {
-				compatible = "cavium,octeon-3860-pip-interface";
-				#address-cells = <1>;
-				#size-cells = <0>;
-				reg = <0>; /* interface */
-
 				ethernet@0 {
-					compatible = "cavium,octeon-3860-pip-port";
-					reg = <0x0>; /* Port */
-					local-mac-address = [ 00 00 00 00 00 00 ];
 					phy-handle = <&phy2>;
 					cavium,alt-phy-handle = <&phy100>;
 				};
 				ethernet@1 {
-					compatible = "cavium,octeon-3860-pip-port";
-					reg = <0x1>; /* Port */
-					local-mac-address = [ 00 00 00 00 00 00 ];
 					phy-handle = <&phy3>;
 					cavium,alt-phy-handle = <&phy101>;
 				};
 				ethernet@2 {
-					compatible = "cavium,octeon-3860-pip-port";
-					reg = <0x2>; /* Port */
-					local-mac-address = [ 00 00 00 00 00 00 ];
 					phy-handle = <&phy4>;
 					cavium,alt-phy-handle = <&phy102>;
 				};
@@ -322,11 +258,6 @@
 			};
 
 			interface@1 {
-				compatible = "cavium,octeon-3860-pip-interface";
-				#address-cells = <1>;
-				#size-cells = <0>;
-				reg = <1>; /* interface */
-
 				ethernet@0 {
 					compatible = "cavium,octeon-3860-pip-port";
 					reg = <0x0>; /* Port */
@@ -355,13 +286,6 @@
 		};
 
 		twsi0: i2c@1180000001000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "cavium,octeon-3860-twsi";
-			reg = <0x11800 0x00001000 0x0 0x200>;
-			interrupts = <0 45>;
-			clock-frequency = <100000>;
-
 			rtc@68 {
 				compatible = "dallas,ds1337";
 				reg = <0x68>;
@@ -381,15 +305,6 @@
 			clock-frequency = <100000>;
 		};
 
-		uart0: serial@1180000000800 {
-			compatible = "cavium,octeon-3860-uart","ns16550";
-			reg = <0x11800 0x00000800 0x0 0x400>;
-			clock-frequency = <0>;
-			current-speed = <115200>;
-			reg-shift = <3>;
-			interrupts = <0 34>;
-		};
-
 		uart1: serial@1180000000c00 {
 			compatible = "cavium,octeon-3860-uart","ns16550";
 			reg = <0x11800 0x00000c00 0x0 0x400>;
@@ -409,98 +324,6 @@
 		};
 
 		bootbus: bootbus@1180000000000 {
-			compatible = "cavium,octeon-3860-bootbus";
-			reg = <0x11800 0x00000000 0x0 0x200>;
-			/* The chip select number and offset */
-			#address-cells = <2>;
-			/* The size of the chip select region */
-			#size-cells = <1>;
-			ranges = <0 0  0x0 0x1f400000  0xc00000>,
-				 <1 0  0x10000 0x30000000  0>,
-				 <2 0  0x10000 0x40000000  0>,
-				 <3 0  0x10000 0x50000000  0>,
-				 <4 0  0x0 0x1d020000  0x10000>,
-				 <5 0  0x0 0x1d040000  0x10000>,
-				 <6 0  0x0 0x1d050000  0x10000>,
-				 <7 0  0x10000 0x90000000  0>;
-
-			cavium,cs-config@0 {
-				compatible = "cavium,octeon-3860-bootbus-config";
-				cavium,cs-index = <0>;
-				cavium,t-adr  = <20>;
-				cavium,t-ce   = <60>;
-				cavium,t-oe   = <60>;
-				cavium,t-we   = <45>;
-				cavium,t-rd-hld = <35>;
-				cavium,t-wr-hld = <45>;
-				cavium,t-pause	= <0>;
-				cavium,t-wait	= <0>;
-				cavium,t-page	= <35>;
-				cavium,t-rd-dly = <0>;
-
-				cavium,pages	 = <0>;
-				cavium,bus-width = <8>;
-			};
-			cavium,cs-config@4 {
-				compatible = "cavium,octeon-3860-bootbus-config";
-				cavium,cs-index = <4>;
-				cavium,t-adr  = <320>;
-				cavium,t-ce   = <320>;
-				cavium,t-oe   = <320>;
-				cavium,t-we   = <320>;
-				cavium,t-rd-hld = <320>;
-				cavium,t-wr-hld = <320>;
-				cavium,t-pause	= <320>;
-				cavium,t-wait	= <320>;
-				cavium,t-page	= <320>;
-				cavium,t-rd-dly = <0>;
-
-				cavium,pages	 = <0>;
-				cavium,bus-width = <8>;
-			};
-			cavium,cs-config@5 {
-				compatible = "cavium,octeon-3860-bootbus-config";
-				cavium,cs-index = <5>;
-				cavium,t-adr  = <5>;
-				cavium,t-ce   = <300>;
-				cavium,t-oe   = <125>;
-				cavium,t-we   = <150>;
-				cavium,t-rd-hld = <100>;
-				cavium,t-wr-hld = <30>;
-				cavium,t-pause	= <0>;
-				cavium,t-wait	= <30>;
-				cavium,t-page	= <320>;
-				cavium,t-rd-dly = <0>;
-
-				cavium,pages	 = <0>;
-				cavium,bus-width = <16>;
-			};
-			cavium,cs-config@6 {
-				compatible = "cavium,octeon-3860-bootbus-config";
-				cavium,cs-index = <6>;
-				cavium,t-adr  = <5>;
-				cavium,t-ce   = <300>;
-				cavium,t-oe   = <270>;
-				cavium,t-we   = <150>;
-				cavium,t-rd-hld = <100>;
-				cavium,t-wr-hld = <70>;
-				cavium,t-pause	= <0>;
-				cavium,t-wait	= <0>;
-				cavium,t-page	= <320>;
-				cavium,t-rd-dly = <0>;
-
-				cavium,pages	 = <0>;
-				cavium,wait-mode;
-				cavium,bus-width = <16>;
-			};
-
-			flash0: nor@0,0 {
-				compatible = "cfi-flash";
-				reg = <0 0 0x800000>;
-				#address-cells = <1>;
-				#size-cells = <1>;
-			};
-
 			led0: led-display@4,0 {
 				compatible = "avago,hdsp-253x";
 				reg = <4 0x20 0x20>, <4 0 0x20>;
@@ -515,17 +338,6 @@
 			};
 		};
 
-		dma0: dma-engine@1180000000100 {
-			compatible = "cavium,octeon-5750-bootbus-dma";
-			reg = <0x11800 0x00000100 0x0 0x8>;
-			interrupts = <0 63>;
-		};
-		dma1: dma-engine@1180000000108 {
-			compatible = "cavium,octeon-5750-bootbus-dma";
-			reg = <0x11800 0x00000108 0x0 0x8>;
-			interrupts = <0 63>;
-		};
-
 		uctl: uctl@118006f000000 {
 			compatible = "cavium,octeon-6335-uctl";
 			reg = <0x11800 0x6f000000 0x0 0x100>;
@@ -552,21 +364,10 @@
 		};
 
 		usbn: usbn@1180068000000 {
-			compatible = "cavium,octeon-5750-usbn";
-			reg = <0x11800 0x68000000 0x0 0x1000>;
-			ranges; /* Direct mapping */
-			#address-cells = <2>;
-			#size-cells = <2>;
 			/* 12MHz, 24MHz and 48MHz allowed */
 			refclk-frequency = <12000000>;
 			/* Either "crystal" or "external" */
 			refclk-type = "crystal";
-
-			usbc@16f0010000000 {
-				compatible = "cavium,octeon-5750-usbc";
-				reg = <0x16f00 0x10000000 0x0 0x80000>;
-				interrupts = <0 56>;
-			};
 		};
 	};
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/cavium-octeon/octeon_3xxx.dtsi linux-libre-4.7-gnu/arch/mips/boot/dts/cavium-octeon/octeon_3xxx.dtsi
--- linux-libre-4.6-gnu/arch/mips/boot/dts/cavium-octeon/octeon_3xxx.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/cavium-octeon/octeon_3xxx.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,231 @@
+/* OCTEON 3XXX DTS common parts. */
+
+/dts-v1/;
+
+/ {
+	compatible = "cavium,octeon-3860";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	interrupt-parent = <&ciu>;
+
+	soc@0 {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges; /* Direct mapping */
+
+		ciu: interrupt-controller@1070000000000 {
+			compatible = "cavium,octeon-3860-ciu";
+			interrupt-controller;
+			/* Interrupts are specified by two parts:
+			 * 1) Controller register (0 or 1)
+			 * 2) Bit within the register (0..63)
+			 */
+			#interrupt-cells = <2>;
+			reg = <0x10700 0x00000000 0x0 0x7000>;
+		};
+
+		gpio: gpio-controller@1070000000800 {
+			#gpio-cells = <2>;
+			compatible = "cavium,octeon-3860-gpio";
+			reg = <0x10700 0x00000800 0x0 0x100>;
+			gpio-controller;
+			/* Interrupts are specified by two parts:
+			 * 1) GPIO pin number (0..15)
+			 * 2) Triggering (1 - edge rising
+			 *		  2 - edge falling
+			 *		  4 - level active high
+			 *		  8 - level active low)
+			 */
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			/* The GPIO pin connect to 16 consecutive CUI bits */
+			interrupts = <0 16>, <0 17>, <0 18>, <0 19>,
+				     <0 20>, <0 21>, <0 22>, <0 23>,
+				     <0 24>, <0 25>, <0 26>, <0 27>,
+				     <0 28>, <0 29>, <0 30>, <0 31>;
+		};
+
+		smi0: mdio@1180000001800 {
+			compatible = "cavium,octeon-3860-mdio";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x11800 0x00001800 0x0 0x40>;
+		};
+
+		pip: pip@11800a0000000 {
+			compatible = "cavium,octeon-3860-pip";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x11800 0xa0000000 0x0 0x2000>;
+
+			interface@0 {
+				compatible = "cavium,octeon-3860-pip-interface";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0>; /* interface */
+
+				ethernet@0 {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0x0>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+				};
+				ethernet@1 {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0x1>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+				};
+				ethernet@2 {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0x2>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+				};
+			};
+
+			interface@1 {
+				compatible = "cavium,octeon-3860-pip-interface";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <1>; /* interface */
+			};
+		};
+
+		twsi0: i2c@1180000001000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "cavium,octeon-3860-twsi";
+			reg = <0x11800 0x00001000 0x0 0x200>;
+			interrupts = <0 45>;
+			clock-frequency = <100000>;
+		};
+
+		uart0: serial@1180000000800 {
+			compatible = "cavium,octeon-3860-uart","ns16550";
+			reg = <0x11800 0x00000800 0x0 0x400>;
+			clock-frequency = <0>;
+			current-speed = <115200>;
+			reg-shift = <3>;
+			interrupts = <0 34>;
+		};
+
+		bootbus: bootbus@1180000000000 {
+			compatible = "cavium,octeon-3860-bootbus";
+			reg = <0x11800 0x00000000 0x0 0x200>;
+			/* The chip select number and offset */
+			#address-cells = <2>;
+			/* The size of the chip select region */
+			#size-cells = <1>;
+			ranges = <0 0  0x0 0x1f400000  0xc00000>,
+				 <1 0  0x10000 0x30000000  0>,
+				 <2 0  0x10000 0x40000000  0>,
+				 <3 0  0x10000 0x50000000  0>,
+				 <4 0  0x0 0x1d020000  0x10000>,
+				 <5 0  0x0 0x1d040000  0x10000>,
+				 <6 0  0x0 0x1d050000  0x10000>,
+				 <7 0  0x10000 0x90000000  0>;
+
+			cavium,cs-config@0 {
+				compatible = "cavium,octeon-3860-bootbus-config";
+				cavium,cs-index = <0>;
+				cavium,t-adr  = <20>;
+				cavium,t-ce   = <60>;
+				cavium,t-oe   = <60>;
+				cavium,t-we   = <45>;
+				cavium,t-rd-hld = <35>;
+				cavium,t-wr-hld = <45>;
+				cavium,t-pause	= <0>;
+				cavium,t-wait	= <0>;
+				cavium,t-page	= <35>;
+				cavium,t-rd-dly = <0>;
+
+				cavium,pages	 = <0>;
+				cavium,bus-width = <8>;
+			};
+			cavium,cs-config@4 {
+				compatible = "cavium,octeon-3860-bootbus-config";
+				cavium,cs-index = <4>;
+				cavium,t-adr  = <320>;
+				cavium,t-ce   = <320>;
+				cavium,t-oe   = <320>;
+				cavium,t-we   = <320>;
+				cavium,t-rd-hld = <320>;
+				cavium,t-wr-hld = <320>;
+				cavium,t-pause	= <320>;
+				cavium,t-wait	= <320>;
+				cavium,t-page	= <320>;
+				cavium,t-rd-dly = <0>;
+
+				cavium,pages	 = <0>;
+				cavium,bus-width = <8>;
+			};
+			cavium,cs-config@5 {
+				compatible = "cavium,octeon-3860-bootbus-config";
+				cavium,cs-index = <5>;
+				cavium,t-adr  = <5>;
+				cavium,t-ce   = <300>;
+				cavium,t-oe   = <125>;
+				cavium,t-we   = <150>;
+				cavium,t-rd-hld = <100>;
+				cavium,t-wr-hld = <30>;
+				cavium,t-pause	= <0>;
+				cavium,t-wait	= <30>;
+				cavium,t-page	= <320>;
+				cavium,t-rd-dly = <0>;
+
+				cavium,pages	 = <0>;
+				cavium,bus-width = <16>;
+			};
+			cavium,cs-config@6 {
+				compatible = "cavium,octeon-3860-bootbus-config";
+				cavium,cs-index = <6>;
+				cavium,t-adr  = <5>;
+				cavium,t-ce   = <300>;
+				cavium,t-oe   = <270>;
+				cavium,t-we   = <150>;
+				cavium,t-rd-hld = <100>;
+				cavium,t-wr-hld = <70>;
+				cavium,t-pause	= <0>;
+				cavium,t-wait	= <0>;
+				cavium,t-page	= <320>;
+				cavium,t-rd-dly = <0>;
+
+				cavium,pages	 = <0>;
+				cavium,wait-mode;
+				cavium,bus-width = <16>;
+			};
+
+			flash0: nor@0,0 {
+				compatible = "cfi-flash";
+				reg = <0 0 0x800000>;
+				#address-cells = <1>;
+				#size-cells = <1>;
+			};
+		};
+
+		dma0: dma-engine@1180000000100 {
+			compatible = "cavium,octeon-5750-bootbus-dma";
+			reg = <0x11800 0x00000100 0x0 0x8>;
+			interrupts = <0 63>;
+		};
+
+		dma1: dma-engine@1180000000108 {
+			compatible = "cavium,octeon-5750-bootbus-dma";
+			reg = <0x11800 0x00000108 0x0 0x8>;
+			interrupts = <0 63>;
+		};
+
+		usbn: usbn@1180068000000 {
+			compatible = "cavium,octeon-5750-usbn";
+			reg = <0x11800 0x68000000 0x0 0x1000>;
+			ranges; /* Direct mapping */
+			#address-cells = <2>;
+			#size-cells = <2>;
+
+			usbc@16f0010000000 {
+				compatible = "cavium,octeon-5750-usbc";
+				reg = <0x16f00 0x10000000 0x0 0x80000>;
+				interrupts = <0 56>;
+			};
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/cavium-octeon/ubnt_e100.dts linux-libre-4.7-gnu/arch/mips/boot/dts/cavium-octeon/ubnt_e100.dts
--- linux-libre-4.6-gnu/arch/mips/boot/dts/cavium-octeon/ubnt_e100.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/cavium-octeon/ubnt_e100.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,59 @@
+/*
+ * Device tree source for EdgeRouter Lite.
+ *
+ * Written by: Aaro Koskinen <aaro.koskinen@iki.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/include/ "octeon_3xxx.dtsi"
+
+/ {
+	model = "ubnt,e100";
+
+	soc@0 {
+		smi0: mdio@1180000001800 {
+			phy5: ethernet-phy@5 {
+				reg = <5>;
+				compatible = "ethernet-phy-ieee802.3-c22";
+			};
+			phy6: ethernet-phy@6 {
+				reg = <6>;
+				compatible = "ethernet-phy-ieee802.3-c22";
+			};
+			phy7: ethernet-phy@7 {
+				reg = <7>;
+				compatible = "ethernet-phy-ieee802.3-c22";
+			};
+		};
+
+		pip: pip@11800a0000000 {
+			interface@0 {
+				ethernet@0 {
+					phy-handle = <&phy7>;
+				};
+				ethernet@1 {
+					phy-handle = <&phy6>;
+				};
+				ethernet@2 {
+					phy-handle = <&phy5>;
+				};
+			};
+		};
+
+		uart0: serial@1180000000800 {
+			clock-frequency = <500000000>;
+		};
+
+		usbn: usbn@1180068000000 {
+			refclk-frequency = <12000000>;
+			refclk-type = "crystal";
+		};
+	};
+
+	aliases {
+		pip = &pip;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/ingenic/jz4740.dtsi linux-libre-4.7-gnu/arch/mips/boot/dts/ingenic/jz4740.dtsi
--- linux-libre-4.6-gnu/arch/mips/boot/dts/ingenic/jz4740.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/ingenic/jz4740.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -5,7 +5,7 @@
 	#size-cells = <1>;
 	compatible = "ingenic,jz4740";
 
-	cpuintc: interrupt-controller@0 {
+	cpuintc: interrupt-controller {
 		#address-cells = <0>;
 		#interrupt-cells = <1>;
 		interrupt-controller;
@@ -65,4 +65,18 @@
 		clocks = <&ext>, <&cgu JZ4740_CLK_UART1>;
 		clock-names = "baud", "module";
 	};
+
+	uhc: uhc@13030000 {
+		compatible = "ingenic,jz4740-ohci", "generic-ohci";
+		reg = <0x13030000 0x1000>;
+
+		clocks = <&cgu JZ4740_CLK_UHC>;
+		assigned-clocks = <&cgu JZ4740_CLK_UHC>;
+		assigned-clock-rates = <48000000>;
+
+		interrupt-parent = <&intc>;
+		interrupts = <3>;
+
+		status = "disabled";
+	};
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/lantiq/easy50712.dts linux-libre-4.7-gnu/arch/mips/boot/dts/lantiq/easy50712.dts
--- linux-libre-4.6-gnu/arch/mips/boot/dts/lantiq/easy50712.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/lantiq/easy50712.dts	2016-07-24 15:23:50.000000000 -0400
@@ -52,7 +52,7 @@
 		};
 
 		gpio: pinmux@E100B10 {
-			compatible = "lantiq,pinctrl-xway";
+			compatible = "lantiq,danube-pinctrl";
 			pinctrl-names = "default";
 			pinctrl-0 = <&state_default>;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/pic32/pic32mzda-clk.dtsi linux-libre-4.7-gnu/arch/mips/boot/dts/pic32/pic32mzda-clk.dtsi
--- linux-libre-4.6-gnu/arch/mips/boot/dts/pic32/pic32mzda-clk.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/pic32/pic32mzda-clk.dtsi	1969-12-31 19:00:00.000000000 -0500
@@ -1,236 +0,0 @@
-/*
- * Device Tree Source for PIC32MZDA clock data
- *
- * Purna Chandra Mandal <purna.mandal@microchip.com>
- * Copyright (C) 2015 Microchip Technology Inc.  All rights reserved.
- *
- * Licensed under GPLv2 or later.
- */
-
-/* all fixed rate clocks */
-
-/ {
-	POSC:posc_clk { /* On-chip primary oscillator */
-		#clock-cells = <0>;
-		compatible = "fixed-clock";
-		clock-frequency = <24000000>;
-	};
-
-	FRC:frc_clk { /* internal FRC oscillator */
-		#clock-cells = <0>;
-		compatible = "fixed-clock";
-		clock-frequency = <8000000>;
-	};
-
-	BFRC:bfrc_clk { /* internal backup FRC oscillator */
-		#clock-cells = <0>;
-		compatible = "fixed-clock";
-		clock-frequency = <8000000>;
-	};
-
-	LPRC:lprc_clk { /* internal low-power FRC oscillator */
-		#clock-cells = <0>;
-		compatible = "fixed-clock";
-		clock-frequency = <32000>;
-	};
-
-	/* UPLL provides clock to USBCORE */
-	UPLL:usb_phy_clk {
-		#clock-cells = <0>;
-		compatible = "fixed-clock";
-		clock-frequency = <24000000>;
-		clock-output-names = "usbphy_clk";
-	};
-
-	TxCKI:txcki_clk { /* external clock input on TxCLKI pin */
-		#clock-cells = <0>;
-		compatible = "fixed-clock";
-		clock-frequency = <4000000>;
-		status = "disabled";
-	};
-
-	/* external clock input on REFCLKIx pin */
-	REFIx:refix_clk {
-		#clock-cells = <0>;
-		compatible = "fixed-clock";
-		clock-frequency = <24000000>;
-		status = "disabled";
-	};
-
-	/* PIC32 specific clks */
-	pic32_clktree {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		reg = <0x1f801200 0x200>;
-		compatible = "microchip,pic32mzda-clk";
-		ranges = <0 0x1f801200 0x200>;
-
-		/* secondary oscillator; external input on SOSCI pin */
-		SOSC:sosc_clk@0 {
-			#clock-cells = <0>;
-			compatible = "microchip,pic32mzda-sosc";
-			clock-frequency = <32768>;
-			reg = <0x000 0x10>,   /* enable reg */
-			      <0x1d0 0x10>; /* status reg */
-			microchip,bit-mask = <0x02>; /* enable mask */
-			microchip,status-bit-mask = <0x10>; /* status-mask*/
-		};
-
-		FRCDIV:frcdiv_clk {
-			#clock-cells = <0>;
-			compatible = "microchip,pic32mzda-frcdivclk";
-			clocks = <&FRC>;
-			clock-output-names = "frcdiv_clk";
-		};
-
-		/* System PLL clock */
-		SYSPLL:spll_clk@020 {
-			#clock-cells = <0>;
-			compatible = "microchip,pic32mzda-syspll";
-			reg = <0x020 0x10>, /* SPLL register */
-			      <0x1d0 0x10>; /* CLKSTAT register */
-			clocks = <&POSC>, <&FRC>;
-			clock-output-names = "sys_pll";
-			microchip,status-bit-mask = <0x80>; /* SPLLRDY */
-		};
-
-		/* system clock; mux with postdiv & slew */
-		SYSCLK:sys_clk@1c0 {
-			#clock-cells = <0>;
-			compatible = "microchip,pic32mzda-sysclk-v2";
-			reg = <0x1c0 0x04>; /* SLEWCON */
-			clocks = <&FRCDIV>, <&SYSPLL>, <&POSC>, <&SOSC>,
-				 <&LPRC>, <&FRCDIV>;
-			microchip,clock-indices = <0>, <1>, <2>, <4>,
-						  <5>, <7>;
-			clock-output-names = "sys_clk";
-		};
-
-		/* Peripheral bus1 clock */
-		PBCLK1:pb1_clk@140 {
-			reg = <0x140 0x10>;
-			#clock-cells = <0>;
-			compatible = "microchip,pic32mzda-pbclk";
-			clocks = <&SYSCLK>;
-			clock-output-names = "pb1_clk";
-			/* used by system modules, not gateable */
-			microchip,ignore-unused;
-		};
-
-		/* Peripheral bus2 clock */
-		PBCLK2:pb2_clk@150 {
-			reg = <0x150 0x10>;
-			#clock-cells = <0>;
-			compatible = "microchip,pic32mzda-pbclk";
-			clocks = <&SYSCLK>;
-			clock-output-names = "pb2_clk";
-			/* avoid gating even if unused */
-			microchip,ignore-unused;
-		};
-
-		/* Peripheral bus3 clock */
-		PBCLK3:pb3_clk@160 {
-			reg = <0x160 0x10>;
-			#clock-cells = <0>;
-			compatible = "microchip,pic32mzda-pbclk";
-			clocks = <&SYSCLK>;
-			clock-output-names = "pb3_clk";
-		};
-
-		/* Peripheral bus4 clock(I/O ports, GPIO) */
-		PBCLK4:pb4_clk@170 {
-			reg = <0x170 0x10>;
-			#clock-cells = <0>;
-			compatible = "microchip,pic32mzda-pbclk";
-			clocks = <&SYSCLK>;
-			clock-output-names = "pb4_clk";
-		};
-
-		/* Peripheral bus clock */
-		PBCLK5:pb5_clk@180 {
-			reg = <0x180 0x10>;
-			#clock-cells = <0>;
-			compatible = "microchip,pic32mzda-pbclk";
-			clocks = <&SYSCLK>;
-			clock-output-names = "pb5_clk";
-		};
-
-		/* Peripheral Bus6 clock; */
-		PBCLK6:pb6_clk@190 {
-			reg = <0x190 0x10>;
-			compatible = "microchip,pic32mzda-pbclk";
-			clocks = <&SYSCLK>;
-			#clock-cells = <0>;
-		};
-
-		/* Peripheral bus7 clock */
-		PBCLK7:pb7_clk@1a0 {
-			reg = <0x1a0 0x10>;
-			#clock-cells = <0>;
-			compatible = "microchip,pic32mzda-pbclk";
-			/* CPU is driven by this clock; so named */
-			clock-output-names = "cpu_clk";
-			clocks = <&SYSCLK>;
-		};
-
-		/* Reference Oscillator clock for SPI/I2S */
-		REFCLKO1:refo1_clk@80 {
-			reg = <0x080 0x20>;
-			#clock-cells = <0>;
-			compatible = "microchip,pic32mzda-refoclk";
-			clocks = <&SYSCLK>, <&PBCLK1>, <&POSC>, <&FRC>, <&LPRC>,
-				 <&SOSC>, <&SYSPLL>, <&REFIx>, <&BFRC>;
-			microchip,clock-indices = <0>, <1>, <2>, <3>, <4>,
-						  <5>, <7>, <8>, <9>;
-			clock-output-names = "refo1_clk";
-		};
-
-		/* Reference Oscillator clock for SQI */
-		REFCLKO2:refo2_clk@a0 {
-			reg = <0x0a0 0x20>;
-			#clock-cells = <0>;
-			compatible = "microchip,pic32mzda-refoclk";
-			clocks = <&SYSCLK>, <&PBCLK1>, <&POSC>, <&FRC>, <&LPRC>,
-				 <&SOSC>, <&SYSPLL>, <&REFIx>, <&BFRC>;
-			microchip,clock-indices = <0>, <1>, <2>, <3>, <4>,
-						  <5>, <7>, <8>, <9>;
-			clock-output-names = "refo2_clk";
-		};
-
-		/* Reference Oscillator clock, ADC */
-		REFCLKO3:refo3_clk@c0 {
-			reg = <0x0c0 0x20>;
-			compatible = "microchip,pic32mzda-refoclk";
-			clocks = <&SYSCLK>, <&PBCLK1>, <&POSC>, <&FRC>, <&LPRC>,
-				 <&SOSC>, <&SYSPLL>, <&REFIx>, <&BFRC>;
-			microchip,clock-indices = <0>, <1>, <2>, <3>, <4>,
-						  <5>, <7>, <8>, <9>;
-			#clock-cells = <0>;
-			clock-output-names = "refo3_clk";
-		};
-
-		/* Reference Oscillator clock */
-		REFCLKO4:refo4_clk@e0 {
-			reg = <0x0e0 0x20>;
-			compatible = "microchip,pic32mzda-refoclk";
-			clocks = <&SYSCLK>, <&PBCLK1>, <&POSC>, <&FRC>, <&LPRC>,
-				 <&SOSC>, <&SYSPLL>, <&REFIx>, <&BFRC>;
-			microchip,clock-indices = <0>, <1>, <2>, <3>, <4>,
-						  <5>, <7>, <8>, <9>;
-			#clock-cells = <0>;
-			clock-output-names = "refo4_clk";
-		};
-
-		/* Reference Oscillator clock, LCD */
-		REFCLKO5:refo5_clk@100 {
-			reg = <0x100 0x20>;
-			compatible = "microchip,pic32mzda-refoclk";
-			clocks = <&SYSCLK>,<&PBCLK1>,<&POSC>,<&FRC>,<&LPRC>,
-				 <&SOSC>,<&SYSPLL>,<&REFIx>,<&BFRC>;
-			microchip,clock-indices = <0>, <1>, <2>, <3>, <4>,
-						  <5>, <7>, <8>, <9>;
-			#clock-cells = <0>;
-			clock-output-names = "refo5_clk";
-		};
-	};
-};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/pic32/pic32mzda.dtsi linux-libre-4.7-gnu/arch/mips/boot/dts/pic32/pic32mzda.dtsi
--- linux-libre-4.6-gnu/arch/mips/boot/dts/pic32/pic32mzda.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/pic32/pic32mzda.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -6,11 +6,9 @@
  * published by the Free Software Foundation.
  *
  */
-
+#include <dt-bindings/clock/microchip,pic32-clock.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 
-#include "pic32mzda-clk.dtsi"
-
 / {
 	#address-cells = <1>;
 	#size-cells = <1>;
@@ -50,6 +48,29 @@
 		interrupts = <0 IRQ_TYPE_EDGE_RISING>;
 	};
 
+	/* external clock input on TxCLKI pin */
+	txcki: txcki_clk {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <4000000>;
+		status = "disabled";
+	};
+
+	/* external input on REFCLKIx pin */
+	refix: refix_clk {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+		status = "disabled";
+	};
+
+	rootclk: clock-controller@1f801200 {
+		compatible = "microchip,pic32mzda-clk";
+		reg = <0x1f801200 0x200>;
+		#clock-cells = <1>;
+		microchip,pic32mzda-sosc;
+	};
+
 	evic: interrupt-controller@1f810000 {
 		compatible = "microchip,pic32mzda-evic";
 		interrupt-controller;
@@ -63,7 +84,7 @@
 		#size-cells = <1>;
 		compatible = "microchip,pic32mzda-pinctrl";
 		reg = <0x1f801400 0x400>;
-		clocks = <&PBCLK1>;
+		clocks = <&rootclk PB1CLK>;
 	};
 
 	/* PORTA */
@@ -75,7 +96,7 @@
 		gpio-controller;
 		interrupt-controller;
 		#interrupt-cells = <2>;
-		clocks = <&PBCLK4>;
+		clocks = <&rootclk PB4CLK>;
 		microchip,gpio-bank = <0>;
 		gpio-ranges = <&pic32_pinctrl 0 0 16>;
 	};
@@ -89,7 +110,7 @@
 		gpio-controller;
 		interrupt-controller;
 		#interrupt-cells = <2>;
-		clocks = <&PBCLK4>;
+		clocks = <&rootclk PB4CLK>;
 		microchip,gpio-bank = <1>;
 		gpio-ranges = <&pic32_pinctrl 0 16 16>;
 	};
@@ -103,7 +124,7 @@
 		gpio-controller;
 		interrupt-controller;
 		#interrupt-cells = <2>;
-		clocks = <&PBCLK4>;
+		clocks = <&rootclk PB4CLK>;
 		microchip,gpio-bank = <2>;
 		gpio-ranges = <&pic32_pinctrl 0 32 16>;
 	};
@@ -117,7 +138,7 @@
 		gpio-controller;
 		interrupt-controller;
 		#interrupt-cells = <2>;
-		clocks = <&PBCLK4>;
+		clocks = <&rootclk PB4CLK>;
 		microchip,gpio-bank = <3>;
 		gpio-ranges = <&pic32_pinctrl 0 48 16>;
 	};
@@ -131,7 +152,7 @@
 		gpio-controller;
 		interrupt-controller;
 		#interrupt-cells = <2>;
-		clocks = <&PBCLK4>;
+		clocks = <&rootclk PB4CLK>;
 		microchip,gpio-bank = <4>;
 		gpio-ranges = <&pic32_pinctrl 0 64 16>;
 	};
@@ -145,7 +166,7 @@
 		gpio-controller;
 		interrupt-controller;
 		#interrupt-cells = <2>;
-		clocks = <&PBCLK4>;
+		clocks = <&rootclk PB4CLK>;
 		microchip,gpio-bank = <5>;
 		gpio-ranges = <&pic32_pinctrl 0 80 16>;
 	};
@@ -159,7 +180,7 @@
 		gpio-controller;
 		interrupt-controller;
 		#interrupt-cells = <2>;
-		clocks = <&PBCLK4>;
+		clocks = <&rootclk PB4CLK>;
 		microchip,gpio-bank = <6>;
 		gpio-ranges = <&pic32_pinctrl 0 96 16>;
 	};
@@ -173,7 +194,7 @@
 		gpio-controller;
 		interrupt-controller;
 		#interrupt-cells = <2>;
-		clocks = <&PBCLK4>;
+		clocks = <&rootclk PB4CLK>;
 		microchip,gpio-bank = <7>;
 		gpio-ranges = <&pic32_pinctrl 0 112 16>;
 	};
@@ -189,7 +210,7 @@
 		gpio-controller;
 		interrupt-controller;
 		#interrupt-cells = <2>;
-		clocks = <&PBCLK4>;
+		clocks = <&rootclk PB4CLK>;
 		microchip,gpio-bank = <8>;
 		gpio-ranges = <&pic32_pinctrl 0 128 16>;
 	};
@@ -203,7 +224,7 @@
 		gpio-controller;
 		interrupt-controller;
 		#interrupt-cells = <2>;
-		clocks = <&PBCLK4>;
+		clocks = <&rootclk PB4CLK>;
 		microchip,gpio-bank = <9>;
 		gpio-ranges = <&pic32_pinctrl 0 144 16>;
 	};
@@ -212,7 +233,7 @@
 		compatible = "microchip,pic32mzda-sdhci";
 		reg = <0x1f8ec000 0x100>;
 		interrupts = <191 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&REFCLKO4>, <&PBCLK5>;
+		clocks = <&rootclk REF4CLK>, <&rootclk PB5CLK>;
 		clock-names = "base_clk", "sys_clk";
 		bus-width = <4>;
 		cap-sd-highspeed;
@@ -225,7 +246,7 @@
 		interrupts = <112 IRQ_TYPE_LEVEL_HIGH>,
 			<113 IRQ_TYPE_LEVEL_HIGH>,
 			<114 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&PBCLK2>;
+		clocks = <&rootclk PB2CLK>;
 		status = "disabled";
 	};
 
@@ -235,7 +256,7 @@
 		interrupts = <145 IRQ_TYPE_LEVEL_HIGH>,
 			<146 IRQ_TYPE_LEVEL_HIGH>,
 			<147 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&PBCLK2>;
+		clocks = <&rootclk PB2CLK>;
 		status = "disabled";
 	};
 
@@ -245,7 +266,7 @@
 		interrupts = <157 IRQ_TYPE_LEVEL_HIGH>,
 			<158 IRQ_TYPE_LEVEL_HIGH>,
 			<159 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&PBCLK2>;
+		clocks = <&rootclk PB2CLK>;
 		status = "disabled";
 	};
 
@@ -255,7 +276,7 @@
 		interrupts = <170 IRQ_TYPE_LEVEL_HIGH>,
 			<171 IRQ_TYPE_LEVEL_HIGH>,
 			<172 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&PBCLK2>;
+		clocks = <&rootclk PB2CLK>;
 		status = "disabled";
 	};
 
@@ -265,7 +286,7 @@
 		interrupts = <179 IRQ_TYPE_LEVEL_HIGH>,
 			<180 IRQ_TYPE_LEVEL_HIGH>,
 			<181 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&PBCLK2>;
+		clocks = <&rootclk PB2CLK>;
 		status = "disabled";
 	};
 
@@ -275,7 +296,7 @@
 		interrupts = <188 IRQ_TYPE_LEVEL_HIGH>,
 			<189 IRQ_TYPE_LEVEL_HIGH>,
 			<190 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&PBCLK2>;
+		clocks = <&rootclk PB2CLK>;
 		status = "disabled";
 	};
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/pic32/pic32mzda_sk.dts linux-libre-4.7-gnu/arch/mips/boot/dts/pic32/pic32mzda_sk.dts
--- linux-libre-4.6-gnu/arch/mips/boot/dts/pic32/pic32mzda_sk.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/pic32/pic32mzda_sk.dts	2016-07-24 15:23:50.000000000 -0400
@@ -95,8 +95,9 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_sdhc1>;
 	status = "okay";
-	assigned-clocks = <&REFCLKO2>,<&REFCLKO4>,<&REFCLKO5>;
-	assigned-clock-rates = <50000000>,<25000000>,<40000000>;
+	assigned-clocks = <&rootclk REF2CLK>, <&rootclk REF4CLK>,
+		<&rootclk REF5CLK>;
+	assigned-clock-rates = <50000000>, <25000000>, <40000000>;
 };
 
 &pic32_pinctrl {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/qca/ar9132.dtsi linux-libre-4.7-gnu/arch/mips/boot/dts/qca/ar9132.dtsi
--- linux-libre-4.6-gnu/arch/mips/boot/dts/qca/ar9132.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/qca/ar9132.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -1,3 +1,5 @@
+#include <dt-bindings/clock/ath79-clk.h>
+
 / {
 	compatible = "qca,ar9132";
 
@@ -11,6 +13,7 @@
 		cpu@0 {
 			device_type = "cpu";
 			compatible = "mips,mips24Kc";
+			clocks = <&pll ATH79_CLK_CPU>;
 			reg = <0>;
 		};
 	};
@@ -52,12 +55,12 @@
 				#qca,ddr-wb-channel-cells = <1>;
 			};
 
-			uart@18020000 {
+			uart: uart@18020000 {
 				compatible = "ns8250";
 				reg = <0x18020000 0x20>;
 				interrupts = <3>;
 
-				clocks = <&pll 2>;
+				clocks = <&pll ATH79_CLK_AHB>;
 				clock-names = "uart";
 
 				reg-io-width = <4>;
@@ -94,13 +97,13 @@
 				clock-output-names = "cpu", "ddr", "ahb";
 			};
 
-			wdt@18060008 {
+			wdt: wdt@18060008 {
 				compatible = "qca,ar7130-wdt";
 				reg = <0x18060008 0x8>;
 
 				interrupts = <4>;
 
-				clocks = <&pll 2>;
+				clocks = <&pll ATH79_CLK_AHB>;
 				clock-names = "wdt";
 			};
 
@@ -125,7 +128,7 @@
 			};
 		};
 
-		usb@1b000100 {
+		usb: usb@1b000100 {
 			compatible = "qca,ar7100-ehci", "generic-ehci";
 			reg = <0x1b000100 0x100>;
 
@@ -140,11 +143,11 @@
 			status = "disabled";
 		};
 
-		spi@1f000000 {
+		spi: spi@1f000000 {
 			compatible = "qca,ar9132-spi", "qca,ar7100-spi";
 			reg = <0x1f000000 0x10>;
 
-			clocks = <&pll 2>;
+			clocks = <&pll ATH79_CLK_AHB>;
 			clock-names = "ahb";
 
 			status = "disabled";
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/qca/ar9132_tl_wr1043nd_v1.dts linux-libre-4.7-gnu/arch/mips/boot/dts/qca/ar9132_tl_wr1043nd_v1.dts
--- linux-libre-4.6-gnu/arch/mips/boot/dts/qca/ar9132_tl_wr1043nd_v1.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/qca/ar9132_tl_wr1043nd_v1.dts	2016-07-24 15:23:50.000000000 -0400
@@ -9,10 +9,6 @@
 	compatible = "tplink,tl-wr1043nd-v1", "qca,ar9132";
 	model = "TP-Link TL-WR1043ND Version 1";
 
-	alias {
-		serial0 = "/ahb/apb/uart@18020000";
-	};
-
 	memory@0 {
 		device_type = "memory";
 		reg = <0x0 0x2000000>;
@@ -24,55 +20,6 @@
 		clock-frequency = <40000000>;
 	};
 
-	ahb {
-		apb {
-			uart@18020000 {
-				status = "okay";
-			};
-
-			pll-controller@18050000 {
-				clocks = <&extosc>;
-			};
-		};
-
-		usb@1b000100 {
-			status = "okay";
-		};
-
-		spi@1f000000 {
-			status = "okay";
-			num-cs = <1>;
-
-			flash@0 {
-				#address-cells = <1>;
-				#size-cells = <1>;
-				compatible = "s25sl064a";
-				reg = <0>;
-				spi-max-frequency = <25000000>;
-
-				partition@0 {
-					label = "u-boot";
-					reg = <0x000000 0x020000>;
-				};
-
-				partition@1 {
-					label = "firmware";
-					reg = <0x020000 0x7D0000>;
-				};
-
-				partition@2 {
-					label = "art";
-					reg = <0x7F0000 0x010000>;
-					read-only;
-				};
-			};
-		};
-	};
-
-	usb-phy {
-		status = "okay";
-	};
-
 	gpio-keys {
 		compatible = "gpio-keys-polled";
 		#address-cells = <1>;
@@ -118,3 +65,48 @@
 		};
 	};
 };
+
+&uart {
+	status = "okay";
+};
+
+&pll {
+	clocks = <&extosc>;
+};
+
+&usb {
+	status = "okay";
+};
+
+&usb_phy {
+	status = "okay";
+};
+
+&spi {
+	status = "okay";
+	num-cs = <1>;
+
+	flash@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "s25sl064a";
+		reg = <0>;
+		spi-max-frequency = <25000000>;
+
+		partition@0 {
+			label = "u-boot";
+			reg = <0x000000 0x020000>;
+		};
+
+		partition@1 {
+			label = "firmware";
+			reg = <0x020000 0x7D0000>;
+		};
+
+		partition@2 {
+			label = "art";
+			reg = <0x7F0000 0x010000>;
+			read-only;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/qca/ar9331_dpt_module.dts linux-libre-4.7-gnu/arch/mips/boot/dts/qca/ar9331_dpt_module.dts
--- linux-libre-4.6-gnu/arch/mips/boot/dts/qca/ar9331_dpt_module.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/qca/ar9331_dpt_module.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,78 @@
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+#include "ar9331.dtsi"
+
+/ {
+	model = "DPTechnics DPT-Module";
+	compatible = "dptechnics,dpt-module";
+
+	aliases {
+		serial0 = &uart;
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x0 0x4000000>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		system {
+			label = "dpt-module:green:system";
+			gpios = <&gpio 27 GPIO_ACTIVE_LOW>;
+			default-state = "off";
+		};
+	};
+
+	gpio-keys-polled {
+		compatible = "gpio-keys-polled";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		poll-interval = <100>;
+
+		button@0 {
+			label = "reset";
+			linux,code = <KEY_RESTART>;
+			gpios = <&gpio 11 GPIO_ACTIVE_LOW>;
+		};
+	};
+};
+
+&ref {
+	clock-frequency = <25000000>;
+};
+
+&uart {
+	status = "okay";
+};
+
+&gpio {
+	status = "okay";
+};
+
+&usb {
+	dr_mode = "host";
+	status = "okay";
+};
+
+&usb_phy {
+	status = "okay";
+};
+
+&spi {
+	num-chipselects = <1>;
+	status = "okay";
+
+	/* Winbond 25Q128FVSG SPI flash */
+	spiflash: w25q128@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "winbond,w25q128", "jedec,spi-nor";
+		spi-max-frequency = <104000000>;
+		reg = <0>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/qca/ar9331_dragino_ms14.dts linux-libre-4.7-gnu/arch/mips/boot/dts/qca/ar9331_dragino_ms14.dts
--- linux-libre-4.6-gnu/arch/mips/boot/dts/qca/ar9331_dragino_ms14.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/qca/ar9331_dragino_ms14.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,102 @@
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+#include "ar9331.dtsi"
+
+/ {
+	model = "Dragino MS14 (Dragino 2)";
+	compatible = "dragino,ms14";
+
+	aliases {
+		serial0 = &uart;
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x0 0x4000000>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		wlan {
+			label = "dragino2:red:wlan";
+			gpios = <&gpio 0 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		lan {
+			label = "dragino2:red:lan";
+			gpios = <&gpio 13 GPIO_ACTIVE_LOW>;
+			default-state = "off";
+		};
+
+		wan {
+			label = "dragino2:red:wan";
+			gpios = <&gpio 17 GPIO_ACTIVE_LOW>;
+			default-state = "off";
+		};
+
+		system {
+			label = "dragino2:red:system";
+			gpios = <&gpio 28 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+	};
+
+	gpio-keys-polled {
+		compatible = "gpio-keys-polled";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		poll-interval = <100>;
+
+		button@0 {
+			label = "jumpstart";
+			linux,code = <KEY_WPS_BUTTON>;
+			gpios = <&gpio 11 GPIO_ACTIVE_LOW>;
+		};
+
+		button@1 {
+			label = "reset";
+			linux,code = <KEY_RESTART>;
+			gpios = <&gpio 12 GPIO_ACTIVE_LOW>;
+		};
+	};
+};
+
+&ref {
+	clock-frequency = <25000000>;
+};
+
+&uart {
+	status = "okay";
+};
+
+&gpio {
+	status = "okay";
+};
+
+&usb {
+	dr_mode = "host";
+	status = "okay";
+};
+
+&usb_phy {
+	status = "okay";
+};
+
+&spi {
+	num-chipselects = <1>;
+	status = "okay";
+
+	/* Winbond 25Q128BVFG SPI flash */
+	spiflash: w25q128@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "winbond,w25q128", "jedec,spi-nor";
+		spi-max-frequency = <104000000>;
+		reg = <0>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/qca/ar9331.dtsi linux-libre-4.7-gnu/arch/mips/boot/dts/qca/ar9331.dtsi
--- linux-libre-4.6-gnu/arch/mips/boot/dts/qca/ar9331.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/qca/ar9331.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,155 @@
+#include <dt-bindings/clock/ath79-clk.h>
+
+/ {
+	compatible = "qca,ar9331";
+
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "mips,mips24Kc";
+			clocks = <&pll ATH79_CLK_CPU>;
+			reg = <0>;
+		};
+	};
+
+	cpuintc: interrupt-controller {
+		compatible = "qca,ar7100-cpu-intc";
+
+		interrupt-controller;
+		#interrupt-cells = <1>;
+
+		qca,ddr-wb-channel-interrupts = <2>, <3>;
+		qca,ddr-wb-channels = <&ddr_ctrl 3>, <&ddr_ctrl 2>;
+	};
+
+	ref: ref {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+	};
+
+	ahb {
+		compatible = "simple-bus";
+		ranges;
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		interrupt-parent = <&cpuintc>;
+
+		apb {
+			compatible = "simple-bus";
+			ranges;
+
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			interrupt-parent = <&miscintc>;
+
+			ddr_ctrl: memory-controller@18000000 {
+				compatible = "qca,ar7240-ddr-controller";
+				reg = <0x18000000 0x100>;
+
+				#qca,ddr-wb-channel-cells = <1>;
+			};
+
+			uart: uart@18020000 {
+				compatible = "qca,ar9330-uart";
+				reg = <0x18020000 0x14>;
+
+				interrupts = <3>;
+
+				clocks = <&ref>;
+				clock-names = "uart";
+
+				status = "disabled";
+			};
+
+			gpio: gpio@18040000 {
+				compatible = "qca,ar7100-gpio";
+				reg = <0x18040000 0x34>;
+				interrupts = <2>;
+
+				ngpios = <30>;
+
+				gpio-controller;
+				#gpio-cells = <2>;
+
+				interrupt-controller;
+				#interrupt-cells = <2>;
+
+				status = "disabled";
+			};
+
+			pll: pll-controller@18050000 {
+				compatible = "qca,ar9330-pll";
+				reg = <0x18050000 0x100>;
+
+				clocks = <&ref>;
+				clock-names = "ref";
+
+				#clock-cells = <1>;
+			};
+
+			miscintc: interrupt-controller@18060010 {
+				compatible = "qca,ar7240-misc-intc";
+				reg = <0x18060010 0x4>;
+
+				interrupt-parent = <&cpuintc>;
+				interrupts = <6>;
+
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+
+			rst: reset-controller@1806001c {
+				compatible = "qca,ar7100-reset";
+				reg = <0x1806001c 0x4>;
+
+				#reset-cells = <1>;
+			};
+		};
+
+		usb: usb@1b000100 {
+			compatible = "chipidea,usb2";
+			reg = <0x1b000000 0x200>;
+
+			interrupts = <3>;
+			resets = <&rst 5>;
+
+			phy-names = "usb-phy";
+			phys = <&usb_phy>;
+
+			status = "disabled";
+		};
+
+		spi: spi@1f000000 {
+			compatible = "qca,ar7100-spi";
+			reg = <0x1f000000 0x10>;
+
+			clocks = <&pll ATH79_CLK_AHB>;
+			clock-names = "ahb";
+
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			status = "disabled";
+		};
+	};
+
+	usb_phy: usb-phy {
+		compatible = "qca,ar7100-usb-phy";
+
+		reset-names = "usb-phy", "usb-suspend-override";
+		resets = <&rst 4>, <&rst 3>;
+
+		#phy-cells = <0>;
+
+		status = "disabled";
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/qca/ar9331_omega.dts linux-libre-4.7-gnu/arch/mips/boot/dts/qca/ar9331_omega.dts
--- linux-libre-4.6-gnu/arch/mips/boot/dts/qca/ar9331_omega.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/qca/ar9331_omega.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,78 @@
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+#include "ar9331.dtsi"
+
+/ {
+	model = "Onion Omega";
+	compatible = "onion,omega";
+
+	aliases {
+		serial0 = &uart;
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x0 0x4000000>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		system {
+			label = "onion:amber:system";
+			gpios = <&gpio 27 GPIO_ACTIVE_LOW>;
+			default-state = "off";
+		};
+	};
+
+	gpio-keys-polled {
+		compatible = "gpio-keys-polled";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		poll-interval = <100>;
+
+		button@0 {
+			label = "reset";
+			linux,code = <KEY_RESTART>;
+			gpios = <&gpio 11 GPIO_ACTIVE_HIGH>;
+		};
+	};
+};
+
+&ref {
+	clock-frequency = <25000000>;
+};
+
+&uart {
+	status = "okay";
+};
+
+&gpio {
+	status = "okay";
+};
+
+&usb {
+	dr_mode = "host";
+	status = "okay";
+};
+
+&usb_phy {
+	status = "okay";
+};
+
+&spi {
+	num-chipselects = <1>;
+	status = "okay";
+
+	/* Winbond 25Q128FVSG SPI flash */
+	spiflash: w25q128@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "winbond,w25q128", "jedec,spi-nor";
+		spi-max-frequency = <104000000>;
+		reg = <0>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/qca/ar9331_tl_mr3020.dts linux-libre-4.7-gnu/arch/mips/boot/dts/qca/ar9331_tl_mr3020.dts
--- linux-libre-4.6-gnu/arch/mips/boot/dts/qca/ar9331_tl_mr3020.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/qca/ar9331_tl_mr3020.dts	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,118 @@
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+#include "ar9331.dtsi"
+
+/ {
+	model = "TP-Link TL-MR3020";
+	compatible = "tplink,tl-mr3020";
+
+	aliases {
+		serial0 = &uart;
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x0 0x2000000>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		wlan {
+			label = "tp-link:green:wlan";
+			gpios = <&gpio 0 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		lan {
+			label = "tp-link:green:lan";
+			gpios = <&gpio 17 GPIO_ACTIVE_LOW>;
+			default-state = "off";
+		};
+
+		wps {
+			label = "tp-link:green:wps";
+			gpios = <&gpio 26 GPIO_ACTIVE_LOW>;
+			default-state = "off";
+		};
+
+		led3g {
+			label = "tp-link:green:3g";
+			gpios = <&gpio 27 GPIO_ACTIVE_LOW>;
+			default-state = "off";
+		};
+	};
+
+	gpio-keys-polled {
+		compatible = "gpio-keys-polled";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		poll-interval = <100>;
+
+		button@0 {
+			label = "wps";
+			linux,code = <KEY_WPS_BUTTON>;
+			gpios = <&gpio 11 GPIO_ACTIVE_HIGH>;
+		};
+
+		button@1 {
+			label = "sw1";
+			linux,code = <BTN_0>;
+			gpios = <&gpio 18 GPIO_ACTIVE_HIGH>;
+		};
+
+		button@2 {
+			label = "sw2";
+			linux,code = <BTN_1>;
+			gpios = <&gpio 20 GPIO_ACTIVE_HIGH>;
+		};
+	};
+
+	reg_usb_vbus: reg_usb_vbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usb_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&gpio 8 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+};
+
+&ref {
+	clock-frequency = <25000000>;
+};
+
+&uart {
+	status = "okay";
+};
+
+&gpio {
+	status = "okay";
+};
+
+&usb {
+	dr_mode = "host";
+	vbus-supply = <&reg_usb_vbus>;
+	status = "okay";
+};
+
+&usb_phy {
+	status = "okay";
+};
+
+&spi {
+	num-chipselects = <1>;
+	status = "okay";
+
+	/* Spansion S25FL032PIF SPI flash */
+	spiflash: s25sl032p@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "spansion,s25sl032p", "jedec,spi-nor";
+		spi-max-frequency = <104000000>;
+		reg = <0>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/qca/Makefile linux-libre-4.7-gnu/arch/mips/boot/dts/qca/Makefile
--- linux-libre-4.6-gnu/arch/mips/boot/dts/qca/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/qca/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -1,8 +1,9 @@
 # All DTBs
 dtb-$(CONFIG_ATH79)			+= ar9132_tl_wr1043nd_v1.dtb
-
-# Select a DTB to build in the kernel
-obj-$(CONFIG_DTB_TL_WR1043ND_V1)	+= ar9132_tl_wr1043nd_v1.dtb.o
+dtb-$(CONFIG_ATH79)			+= ar9331_dpt_module.dtb
+dtb-$(CONFIG_ATH79)			+= ar9331_dragino_ms14.dtb
+dtb-$(CONFIG_ATH79)			+= ar9331_omega.dtb
+dtb-$(CONFIG_ATH79)			+= ar9331_tl_mr3020.dtb
 
 # Force kbuild to make empty built-in.o if necessary
 obj-				+= dummy.o
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/ralink/mt7620a.dtsi linux-libre-4.7-gnu/arch/mips/boot/dts/ralink/mt7620a.dtsi
--- linux-libre-4.6-gnu/arch/mips/boot/dts/ralink/mt7620a.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/ralink/mt7620a.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -9,7 +9,7 @@
 		};
 	};
 
-	cpuintc: cpuintc@0 {
+	cpuintc: cpuintc {
 		#address-cells = <0>;
 		#interrupt-cells = <1>;
 		interrupt-controller;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/ralink/rt2880.dtsi linux-libre-4.7-gnu/arch/mips/boot/dts/ralink/rt2880.dtsi
--- linux-libre-4.6-gnu/arch/mips/boot/dts/ralink/rt2880.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/ralink/rt2880.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -9,7 +9,7 @@
 		};
 	};
 
-	cpuintc: cpuintc@0 {
+	cpuintc: cpuintc {
 		#address-cells = <0>;
 		#interrupt-cells = <1>;
 		interrupt-controller;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/ralink/rt3050.dtsi linux-libre-4.7-gnu/arch/mips/boot/dts/ralink/rt3050.dtsi
--- linux-libre-4.6-gnu/arch/mips/boot/dts/ralink/rt3050.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/ralink/rt3050.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -9,7 +9,7 @@
 		};
 	};
 
-	cpuintc: cpuintc@0 {
+	cpuintc: cpuintc {
 		#address-cells = <0>;
 		#interrupt-cells = <1>;
 		interrupt-controller;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/ralink/rt3883.dtsi linux-libre-4.7-gnu/arch/mips/boot/dts/ralink/rt3883.dtsi
--- linux-libre-4.6-gnu/arch/mips/boot/dts/ralink/rt3883.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/ralink/rt3883.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -9,7 +9,7 @@
 		};
 	};
 
-	cpuintc: cpuintc@0 {
+	cpuintc: cpuintc {
 		#address-cells = <0>;
 		#interrupt-cells = <1>;
 		interrupt-controller;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/dts/xilfpga/nexys4ddr.dts linux-libre-4.7-gnu/arch/mips/boot/dts/xilfpga/nexys4ddr.dts
--- linux-libre-4.6-gnu/arch/mips/boot/dts/xilfpga/nexys4ddr.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/boot/dts/xilfpga/nexys4ddr.dts	2016-07-24 15:23:50.000000000 -0400
@@ -10,7 +10,7 @@
 		reg = <0x0 0x08000000>;
 	};
 
-	cpuintc: interrupt-controller@0 {
+	cpuintc: interrupt-controller {
 		#address-cells = <0>;
 		#interrupt-cells = <1>;
 		interrupt-controller;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/tools/.gitignore linux-libre-4.7-gnu/arch/mips/boot/tools/.gitignore
--- linux-libre-4.6-gnu/arch/mips/boot/tools/.gitignore	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/mips/boot/tools/.gitignore	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1 @@
+relocs
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/tools/Makefile linux-libre-4.7-gnu/arch/mips/boot/tools/Makefile
--- linux-libre-4.6-gnu/arch/mips/boot/tools/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/mips/boot/tools/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,8 @@
+
+hostprogs-y	+= relocs
+relocs-objs	+= relocs_32.o
+relocs-objs	+= relocs_64.o
+relocs-objs	+= relocs_main.o
+PHONY += relocs
+relocs: $(obj)/relocs
+	@:
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/tools/relocs_32.c linux-libre-4.7-gnu/arch/mips/boot/tools/relocs_32.c
--- linux-libre-4.6-gnu/arch/mips/boot/tools/relocs_32.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/mips/boot/tools/relocs_32.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,17 @@
+#include "relocs.h"
+
+#define ELF_BITS 32
+
+#define ELF_MACHINE		EM_MIPS
+#define ELF_MACHINE_NAME	"MIPS"
+#define SHT_REL_TYPE		SHT_REL
+#define Elf_Rel			ElfW(Rel)
+
+#define ELF_CLASS		ELFCLASS32
+#define ELF_R_SYM(val)		ELF32_R_SYM(val)
+#define ELF_R_TYPE(val)		ELF32_R_TYPE(val)
+#define ELF_ST_TYPE(o)		ELF32_ST_TYPE(o)
+#define ELF_ST_BIND(o)		ELF32_ST_BIND(o)
+#define ELF_ST_VISIBILITY(o)	ELF32_ST_VISIBILITY(o)
+
+#include "relocs.c"
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/tools/relocs_64.c linux-libre-4.7-gnu/arch/mips/boot/tools/relocs_64.c
--- linux-libre-4.6-gnu/arch/mips/boot/tools/relocs_64.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/mips/boot/tools/relocs_64.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,27 @@
+#include "relocs.h"
+
+#define ELF_BITS 64
+
+#define ELF_MACHINE             EM_MIPS
+#define ELF_MACHINE_NAME        "MIPS64"
+#define SHT_REL_TYPE            SHT_RELA
+#define Elf_Rel                 Elf64_Rela
+
+typedef uint8_t Elf64_Byte;
+
+typedef struct {
+	Elf64_Word r_sym;	/* Symbol index.  */
+	Elf64_Byte r_ssym;	/* Special symbol.  */
+	Elf64_Byte r_type3;	/* Third relocation.  */
+	Elf64_Byte r_type2;	/* Second relocation.  */
+	Elf64_Byte r_type;	/* First relocation.  */
+} Elf64_Mips_Rela;
+
+#define ELF_CLASS               ELFCLASS64
+#define ELF_R_SYM(val)          (((Elf64_Mips_Rela *)(&val))->r_sym)
+#define ELF_R_TYPE(val)         (((Elf64_Mips_Rela *)(&val))->r_type)
+#define ELF_ST_TYPE(o)          ELF64_ST_TYPE(o)
+#define ELF_ST_BIND(o)          ELF64_ST_BIND(o)
+#define ELF_ST_VISIBILITY(o)    ELF64_ST_VISIBILITY(o)
+
+#include "relocs.c"
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/tools/relocs.c linux-libre-4.7-gnu/arch/mips/boot/tools/relocs.c
--- linux-libre-4.6-gnu/arch/mips/boot/tools/relocs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/mips/boot/tools/relocs.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,680 @@
+/* This is included from relocs_32/64.c */
+
+#define ElfW(type)		_ElfW(ELF_BITS, type)
+#define _ElfW(bits, type)	__ElfW(bits, type)
+#define __ElfW(bits, type)	Elf##bits##_##type
+
+#define Elf_Addr		ElfW(Addr)
+#define Elf_Ehdr		ElfW(Ehdr)
+#define Elf_Phdr		ElfW(Phdr)
+#define Elf_Shdr		ElfW(Shdr)
+#define Elf_Sym			ElfW(Sym)
+
+static Elf_Ehdr ehdr;
+
+struct relocs {
+	uint32_t	*offset;
+	unsigned long	count;
+	unsigned long	size;
+};
+
+static struct relocs relocs;
+
+struct section {
+	Elf_Shdr       shdr;
+	struct section *link;
+	Elf_Sym        *symtab;
+	Elf_Rel        *reltab;
+	char           *strtab;
+	long           shdr_offset;
+};
+static struct section *secs;
+
+static const char * const regex_sym_kernel = {
+/* Symbols matching these regex's should never be relocated */
+	"^(__crc_)",
+};
+
+static regex_t sym_regex_c;
+
+static int regex_skip_reloc(const char *sym_name)
+{
+	return !regexec(&sym_regex_c, sym_name, 0, NULL, 0);
+}
+
+static void regex_init(void)
+{
+	char errbuf[128];
+	int err;
+
+	err = regcomp(&sym_regex_c, regex_sym_kernel,
+			REG_EXTENDED|REG_NOSUB);
+
+	if (err) {
+		regerror(err, &sym_regex_c, errbuf, sizeof(errbuf));
+		die("%s", errbuf);
+	}
+}
+
+static const char *rel_type(unsigned type)
+{
+	static const char * const type_name[] = {
+#define REL_TYPE(X)[X] = #X
+		REL_TYPE(R_MIPS_NONE),
+		REL_TYPE(R_MIPS_16),
+		REL_TYPE(R_MIPS_32),
+		REL_TYPE(R_MIPS_REL32),
+		REL_TYPE(R_MIPS_26),
+		REL_TYPE(R_MIPS_HI16),
+		REL_TYPE(R_MIPS_LO16),
+		REL_TYPE(R_MIPS_GPREL16),
+		REL_TYPE(R_MIPS_LITERAL),
+		REL_TYPE(R_MIPS_GOT16),
+		REL_TYPE(R_MIPS_PC16),
+		REL_TYPE(R_MIPS_CALL16),
+		REL_TYPE(R_MIPS_GPREL32),
+		REL_TYPE(R_MIPS_64),
+		REL_TYPE(R_MIPS_HIGHER),
+		REL_TYPE(R_MIPS_HIGHEST),
+		REL_TYPE(R_MIPS_PC21_S2),
+		REL_TYPE(R_MIPS_PC26_S2),
+#undef REL_TYPE
+	};
+	const char *name = "unknown type rel type name";
+
+	if (type < ARRAY_SIZE(type_name) && type_name[type])
+		name = type_name[type];
+	return name;
+}
+
+static const char *sec_name(unsigned shndx)
+{
+	const char *sec_strtab;
+	const char *name;
+
+	sec_strtab = secs[ehdr.e_shstrndx].strtab;
+	if (shndx < ehdr.e_shnum)
+		name = sec_strtab + secs[shndx].shdr.sh_name;
+	else if (shndx == SHN_ABS)
+		name = "ABSOLUTE";
+	else if (shndx == SHN_COMMON)
+		name = "COMMON";
+	else
+		name = "<noname>";
+	return name;
+}
+
+static struct section *sec_lookup(const char *secname)
+{
+	int i;
+
+	for (i = 0; i < ehdr.e_shnum; i++)
+		if (strcmp(secname, sec_name(i)) == 0)
+			return &secs[i];
+
+	return NULL;
+}
+
+static const char *sym_name(const char *sym_strtab, Elf_Sym *sym)
+{
+	const char *name;
+
+	if (sym->st_name)
+		name = sym_strtab + sym->st_name;
+	else
+		name = sec_name(sym->st_shndx);
+	return name;
+}
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define le16_to_cpu(val) (val)
+#define le32_to_cpu(val) (val)
+#define le64_to_cpu(val) (val)
+#define be16_to_cpu(val) bswap_16(val)
+#define be32_to_cpu(val) bswap_32(val)
+#define be64_to_cpu(val) bswap_64(val)
+
+#define cpu_to_le16(val) (val)
+#define cpu_to_le32(val) (val)
+#define cpu_to_le64(val) (val)
+#define cpu_to_be16(val) bswap_16(val)
+#define cpu_to_be32(val) bswap_32(val)
+#define cpu_to_be64(val) bswap_64(val)
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+#define le16_to_cpu(val) bswap_16(val)
+#define le32_to_cpu(val) bswap_32(val)
+#define le64_to_cpu(val) bswap_64(val)
+#define be16_to_cpu(val) (val)
+#define be32_to_cpu(val) (val)
+#define be64_to_cpu(val) (val)
+
+#define cpu_to_le16(val) bswap_16(val)
+#define cpu_to_le32(val) bswap_32(val)
+#define cpu_to_le64(val) bswap_64(val)
+#define cpu_to_be16(val) (val)
+#define cpu_to_be32(val) (val)
+#define cpu_to_be64(val) (val)
+#endif
+
+static uint16_t elf16_to_cpu(uint16_t val)
+{
+	if (ehdr.e_ident[EI_DATA] == ELFDATA2LSB)
+		return le16_to_cpu(val);
+	else
+		return be16_to_cpu(val);
+}
+
+static uint32_t elf32_to_cpu(uint32_t val)
+{
+	if (ehdr.e_ident[EI_DATA] == ELFDATA2LSB)
+		return le32_to_cpu(val);
+	else
+		return be32_to_cpu(val);
+}
+
+static uint32_t cpu_to_elf32(uint32_t val)
+{
+	if (ehdr.e_ident[EI_DATA] == ELFDATA2LSB)
+		return cpu_to_le32(val);
+	else
+		return cpu_to_be32(val);
+}
+
+#define elf_half_to_cpu(x)	elf16_to_cpu(x)
+#define elf_word_to_cpu(x)	elf32_to_cpu(x)
+
+#if ELF_BITS == 64
+static uint64_t elf64_to_cpu(uint64_t val)
+{
+	if (ehdr.e_ident[EI_DATA] == ELFDATA2LSB)
+		return le64_to_cpu(val);
+	else
+		return be64_to_cpu(val);
+}
+#define elf_addr_to_cpu(x)	elf64_to_cpu(x)
+#define elf_off_to_cpu(x)	elf64_to_cpu(x)
+#define elf_xword_to_cpu(x)	elf64_to_cpu(x)
+#else
+#define elf_addr_to_cpu(x)	elf32_to_cpu(x)
+#define elf_off_to_cpu(x)	elf32_to_cpu(x)
+#define elf_xword_to_cpu(x)	elf32_to_cpu(x)
+#endif
+
+static void read_ehdr(FILE *fp)
+{
+	if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1)
+		die("Cannot read ELF header: %s\n", strerror(errno));
+
+	if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0)
+		die("No ELF magic\n");
+
+	if (ehdr.e_ident[EI_CLASS] != ELF_CLASS)
+		die("Not a %d bit executable\n", ELF_BITS);
+
+	if ((ehdr.e_ident[EI_DATA] != ELFDATA2LSB) &&
+	    (ehdr.e_ident[EI_DATA] != ELFDATA2MSB))
+		die("Unknown ELF Endianness\n");
+
+	if (ehdr.e_ident[EI_VERSION] != EV_CURRENT)
+		die("Unknown ELF version\n");
+
+	/* Convert the fields to native endian */
+	ehdr.e_type      = elf_half_to_cpu(ehdr.e_type);
+	ehdr.e_machine   = elf_half_to_cpu(ehdr.e_machine);
+	ehdr.e_version   = elf_word_to_cpu(ehdr.e_version);
+	ehdr.e_entry     = elf_addr_to_cpu(ehdr.e_entry);
+	ehdr.e_phoff     = elf_off_to_cpu(ehdr.e_phoff);
+	ehdr.e_shoff     = elf_off_to_cpu(ehdr.e_shoff);
+	ehdr.e_flags     = elf_word_to_cpu(ehdr.e_flags);
+	ehdr.e_ehsize    = elf_half_to_cpu(ehdr.e_ehsize);
+	ehdr.e_phentsize = elf_half_to_cpu(ehdr.e_phentsize);
+	ehdr.e_phnum     = elf_half_to_cpu(ehdr.e_phnum);
+	ehdr.e_shentsize = elf_half_to_cpu(ehdr.e_shentsize);
+	ehdr.e_shnum     = elf_half_to_cpu(ehdr.e_shnum);
+	ehdr.e_shstrndx  = elf_half_to_cpu(ehdr.e_shstrndx);
+
+	if ((ehdr.e_type != ET_EXEC) && (ehdr.e_type != ET_DYN))
+		die("Unsupported ELF header type\n");
+
+	if (ehdr.e_machine != ELF_MACHINE)
+		die("Not for %s\n", ELF_MACHINE_NAME);
+
+	if (ehdr.e_version != EV_CURRENT)
+		die("Unknown ELF version\n");
+
+	if (ehdr.e_ehsize != sizeof(Elf_Ehdr))
+		die("Bad Elf header size\n");
+
+	if (ehdr.e_phentsize != sizeof(Elf_Phdr))
+		die("Bad program header entry\n");
+
+	if (ehdr.e_shentsize != sizeof(Elf_Shdr))
+		die("Bad section header entry\n");
+
+	if (ehdr.e_shstrndx >= ehdr.e_shnum)
+		die("String table index out of bounds\n");
+}
+
+static void read_shdrs(FILE *fp)
+{
+	int i;
+	Elf_Shdr shdr;
+
+	secs = calloc(ehdr.e_shnum, sizeof(struct section));
+	if (!secs)
+		die("Unable to allocate %d section headers\n", ehdr.e_shnum);
+
+	if (fseek(fp, ehdr.e_shoff, SEEK_SET) < 0)
+		die("Seek to %d failed: %s\n", ehdr.e_shoff, strerror(errno));
+
+	for (i = 0; i < ehdr.e_shnum; i++) {
+		struct section *sec = &secs[i];
+
+		sec->shdr_offset = ftell(fp);
+		if (fread(&shdr, sizeof(shdr), 1, fp) != 1)
+			die("Cannot read ELF section headers %d/%d: %s\n",
+			    i, ehdr.e_shnum, strerror(errno));
+		sec->shdr.sh_name      = elf_word_to_cpu(shdr.sh_name);
+		sec->shdr.sh_type      = elf_word_to_cpu(shdr.sh_type);
+		sec->shdr.sh_flags     = elf_xword_to_cpu(shdr.sh_flags);
+		sec->shdr.sh_addr      = elf_addr_to_cpu(shdr.sh_addr);
+		sec->shdr.sh_offset    = elf_off_to_cpu(shdr.sh_offset);
+		sec->shdr.sh_size      = elf_xword_to_cpu(shdr.sh_size);
+		sec->shdr.sh_link      = elf_word_to_cpu(shdr.sh_link);
+		sec->shdr.sh_info      = elf_word_to_cpu(shdr.sh_info);
+		sec->shdr.sh_addralign = elf_xword_to_cpu(shdr.sh_addralign);
+		sec->shdr.sh_entsize   = elf_xword_to_cpu(shdr.sh_entsize);
+		if (sec->shdr.sh_link < ehdr.e_shnum)
+			sec->link = &secs[sec->shdr.sh_link];
+	}
+}
+
+static void read_strtabs(FILE *fp)
+{
+	int i;
+
+	for (i = 0; i < ehdr.e_shnum; i++) {
+		struct section *sec = &secs[i];
+
+		if (sec->shdr.sh_type != SHT_STRTAB)
+			continue;
+
+		sec->strtab = malloc(sec->shdr.sh_size);
+		if (!sec->strtab)
+			die("malloc of %d bytes for strtab failed\n",
+			    sec->shdr.sh_size);
+
+		if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0)
+			die("Seek to %d failed: %s\n",
+			    sec->shdr.sh_offset, strerror(errno));
+
+		if (fread(sec->strtab, 1, sec->shdr.sh_size, fp) !=
+		    sec->shdr.sh_size)
+			die("Cannot read symbol table: %s\n", strerror(errno));
+	}
+}
+
+static void read_symtabs(FILE *fp)
+{
+	int i, j;
+
+	for (i = 0; i < ehdr.e_shnum; i++) {
+		struct section *sec = &secs[i];
+		if (sec->shdr.sh_type != SHT_SYMTAB)
+			continue;
+
+		sec->symtab = malloc(sec->shdr.sh_size);
+		if (!sec->symtab)
+			die("malloc of %d bytes for symtab failed\n",
+			    sec->shdr.sh_size);
+
+		if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0)
+			die("Seek to %d failed: %s\n",
+			    sec->shdr.sh_offset, strerror(errno));
+
+		if (fread(sec->symtab, 1, sec->shdr.sh_size, fp) !=
+		    sec->shdr.sh_size)
+			die("Cannot read symbol table: %s\n", strerror(errno));
+
+		for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Sym); j++) {
+			Elf_Sym *sym = &sec->symtab[j];
+
+			sym->st_name  = elf_word_to_cpu(sym->st_name);
+			sym->st_value = elf_addr_to_cpu(sym->st_value);
+			sym->st_size  = elf_xword_to_cpu(sym->st_size);
+			sym->st_shndx = elf_half_to_cpu(sym->st_shndx);
+		}
+	}
+}
+
+static void read_relocs(FILE *fp)
+{
+	static unsigned long base = 0;
+	int i, j;
+
+	if (!base) {
+		struct section *sec = sec_lookup(".text");
+
+		if (!sec)
+			die("Could not find .text section\n");
+
+		base = sec->shdr.sh_addr;
+	}
+
+	for (i = 0; i < ehdr.e_shnum; i++) {
+		struct section *sec = &secs[i];
+
+		if (sec->shdr.sh_type != SHT_REL_TYPE)
+			continue;
+
+		sec->reltab = malloc(sec->shdr.sh_size);
+		if (!sec->reltab)
+			die("malloc of %d bytes for relocs failed\n",
+			    sec->shdr.sh_size);
+
+		if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0)
+			die("Seek to %d failed: %s\n",
+			    sec->shdr.sh_offset, strerror(errno));
+
+		if (fread(sec->reltab, 1, sec->shdr.sh_size, fp) !=
+		    sec->shdr.sh_size)
+			die("Cannot read symbol table: %s\n", strerror(errno));
+
+		for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Rel); j++) {
+			Elf_Rel *rel = &sec->reltab[j];
+
+			rel->r_offset = elf_addr_to_cpu(rel->r_offset);
+			/* Set offset into kernel image */
+			rel->r_offset -= base;
+#if (ELF_BITS == 32)
+			rel->r_info   = elf_xword_to_cpu(rel->r_info);
+#else
+			/* Convert MIPS64 RELA format - only the symbol
+			 * index needs converting to native endianness
+			 */
+			rel->r_info   = rel->r_info;
+			ELF_R_SYM(rel->r_info) = elf32_to_cpu(ELF_R_SYM(rel->r_info));
+#endif
+#if (SHT_REL_TYPE == SHT_RELA)
+			rel->r_addend = elf_xword_to_cpu(rel->r_addend);
+#endif
+		}
+	}
+}
+
+static void remove_relocs(FILE *fp)
+{
+	int i;
+	Elf_Shdr shdr;
+
+	for (i = 0; i < ehdr.e_shnum; i++) {
+		struct section *sec = &secs[i];
+
+		if (sec->shdr.sh_type != SHT_REL_TYPE)
+			continue;
+
+		if (fseek(fp, sec->shdr_offset, SEEK_SET) < 0)
+			die("Seek to %d failed: %s\n",
+			    sec->shdr_offset, strerror(errno));
+
+		if (fread(&shdr, sizeof(shdr), 1, fp) != 1)
+			die("Cannot read ELF section headers %d/%d: %s\n",
+			    i, ehdr.e_shnum, strerror(errno));
+
+		/* Set relocation section size to 0, effectively removing it.
+		 * This is necessary due to lack of support for relocations
+		 * in objcopy when creating 32bit elf from 64bit elf.
+		 */
+		shdr.sh_size = 0;
+
+		if (fseek(fp, sec->shdr_offset, SEEK_SET) < 0)
+			die("Seek to %d failed: %s\n",
+			    sec->shdr_offset, strerror(errno));
+
+		if (fwrite(&shdr, sizeof(shdr), 1, fp) != 1)
+			die("Cannot write ELF section headers %d/%d: %s\n",
+			    i, ehdr.e_shnum, strerror(errno));
+	}
+}
+
+static void add_reloc(struct relocs *r, uint32_t offset, unsigned type)
+{
+	/* Relocation representation in binary table:
+	 * |76543210|76543210|76543210|76543210|
+	 * |  Type  |  offset from _text >> 2  |
+	 */
+	offset >>= 2;
+	if (offset > 0x00FFFFFF)
+		die("Kernel image exceeds maximum size for relocation!\n");
+
+	offset = (offset & 0x00FFFFFF) | ((type & 0xFF) << 24);
+
+	if (r->count == r->size) {
+		unsigned long newsize = r->size + 50000;
+		void *mem = realloc(r->offset, newsize * sizeof(r->offset[0]));
+
+		if (!mem)
+			die("realloc failed\n");
+
+		r->offset = mem;
+		r->size = newsize;
+	}
+	r->offset[r->count++] = offset;
+}
+
+static void walk_relocs(int (*process)(struct section *sec, Elf_Rel *rel,
+			Elf_Sym *sym, const char *symname))
+{
+	int i;
+
+	/* Walk through the relocations */
+	for (i = 0; i < ehdr.e_shnum; i++) {
+		char *sym_strtab;
+		Elf_Sym *sh_symtab;
+		struct section *sec_applies, *sec_symtab;
+		int j;
+		struct section *sec = &secs[i];
+
+		if (sec->shdr.sh_type != SHT_REL_TYPE)
+			continue;
+
+		sec_symtab  = sec->link;
+		sec_applies = &secs[sec->shdr.sh_info];
+		if (!(sec_applies->shdr.sh_flags & SHF_ALLOC))
+			continue;
+
+		sh_symtab = sec_symtab->symtab;
+		sym_strtab = sec_symtab->link->strtab;
+		for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Rel); j++) {
+			Elf_Rel *rel = &sec->reltab[j];
+			Elf_Sym *sym = &sh_symtab[ELF_R_SYM(rel->r_info)];
+			const char *symname = sym_name(sym_strtab, sym);
+
+			process(sec, rel, sym, symname);
+		}
+	}
+}
+
+static int do_reloc(struct section *sec, Elf_Rel *rel, Elf_Sym *sym,
+		      const char *symname)
+{
+	unsigned r_type = ELF_R_TYPE(rel->r_info);
+	unsigned bind = ELF_ST_BIND(sym->st_info);
+
+	if ((bind == STB_WEAK) && (sym->st_value == 0)) {
+		/* Don't relocate weak symbols without a target */
+		return 0;
+	}
+
+	if (regex_skip_reloc(symname))
+		return 0;
+
+	switch (r_type) {
+	case R_MIPS_NONE:
+	case R_MIPS_REL32:
+	case R_MIPS_PC16:
+	case R_MIPS_PC21_S2:
+	case R_MIPS_PC26_S2:
+		/*
+		 * NONE can be ignored and PC relative relocations don't
+		 * need to be adjusted.
+		 */
+	case R_MIPS_HIGHEST:
+	case R_MIPS_HIGHER:
+		/* We support relocating within the same 4Gb segment only,
+		 * thus leaving the top 32bits unchanged
+		 */
+	case R_MIPS_LO16:
+		/* We support relocating by 64k jumps only
+		 * thus leaving the bottom 16bits unchanged
+		 */
+		break;
+
+	case R_MIPS_64:
+	case R_MIPS_32:
+	case R_MIPS_26:
+	case R_MIPS_HI16:
+		add_reloc(&relocs, rel->r_offset, r_type);
+		break;
+
+	default:
+		die("Unsupported relocation type: %s (%d)\n",
+		    rel_type(r_type), r_type);
+		break;
+	}
+
+	return 0;
+}
+
+static int write_reloc_as_bin(uint32_t v, FILE *f)
+{
+	unsigned char buf[4];
+
+	v = cpu_to_elf32(v);
+
+	memcpy(buf, &v, sizeof(uint32_t));
+	return fwrite(buf, 1, 4, f);
+}
+
+static int write_reloc_as_text(uint32_t v, FILE *f)
+{
+	int res;
+
+	res = fprintf(f, "\t.long 0x%08"PRIx32"\n", v);
+	if (res < 0)
+		return res;
+	else
+		return sizeof(uint32_t);
+}
+
+static void emit_relocs(int as_text, int as_bin, FILE *outf)
+{
+	int i;
+	int (*write_reloc)(uint32_t, FILE *) = write_reloc_as_bin;
+	int size = 0;
+	int size_reserved;
+	struct section *sec_reloc;
+
+	sec_reloc = sec_lookup(".data.reloc");
+	if (!sec_reloc)
+		die("Could not find relocation section\n");
+
+	size_reserved = sec_reloc->shdr.sh_size;
+
+	/* Collect up the relocations */
+	walk_relocs(do_reloc);
+
+	/* Print the relocations */
+	if (as_text) {
+		/* Print the relocations in a form suitable that
+		 * gas will like.
+		 */
+		printf(".section \".data.reloc\",\"a\"\n");
+		printf(".balign 4\n");
+		/* Output text to stdout */
+		write_reloc = write_reloc_as_text;
+		outf = stdout;
+	} else if (as_bin) {
+		/* Output raw binary to stdout */
+		outf = stdout;
+	} else {
+		/* Seek to offset of the relocation section.
+		* Each relocation is then written into the
+		* vmlinux kernel image.
+		*/
+		if (fseek(outf, sec_reloc->shdr.sh_offset, SEEK_SET) < 0) {
+			die("Seek to %d failed: %s\n",
+				sec_reloc->shdr.sh_offset, strerror(errno));
+		}
+	}
+
+	for (i = 0; i < relocs.count; i++)
+		size += write_reloc(relocs.offset[i], outf);
+
+	/* Print a stop, but only if we've actually written some relocs */
+	if (size)
+		size += write_reloc(0, outf);
+
+	if (size > size_reserved)
+		/* Die, but suggest a value for CONFIG_RELOCATION_TABLE_SIZE
+		 * which will fix this problem and allow a bit of headroom
+		 * if more kernel features are enabled
+		 */
+		die("Relocations overflow available space!\n" \
+		    "Please adjust CONFIG_RELOCATION_TABLE_SIZE " \
+		    "to at least 0x%08x\n", (size + 0x1000) & ~0xFFF);
+}
+
+/*
+ * As an aid to debugging problems with different linkers
+ * print summary information about the relocs.
+ * Since different linkers tend to emit the sections in
+ * different orders we use the section names in the output.
+ */
+static int do_reloc_info(struct section *sec, Elf_Rel *rel, ElfW(Sym) *sym,
+				const char *symname)
+{
+	printf("%16s  0x%08x  %16s  %40s  %16s\n",
+		sec_name(sec->shdr.sh_info),
+		(unsigned int)rel->r_offset,
+		rel_type(ELF_R_TYPE(rel->r_info)),
+		symname,
+		sec_name(sym->st_shndx));
+	return 0;
+}
+
+static void print_reloc_info(void)
+{
+	printf("%16s  %10s  %16s  %40s  %16s\n",
+		"reloc section",
+		"offset",
+		"reloc type",
+		"symbol",
+		"symbol section");
+	walk_relocs(do_reloc_info);
+}
+
+#if ELF_BITS == 64
+# define process process_64
+#else
+# define process process_32
+#endif
+
+void process(FILE *fp, int as_text, int as_bin,
+	     int show_reloc_info, int keep_relocs)
+{
+	regex_init();
+	read_ehdr(fp);
+	read_shdrs(fp);
+	read_strtabs(fp);
+	read_symtabs(fp);
+	read_relocs(fp);
+	if (show_reloc_info) {
+		print_reloc_info();
+		return;
+	}
+	emit_relocs(as_text, as_bin, fp);
+	if (!keep_relocs)
+		remove_relocs(fp);
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/tools/relocs.h linux-libre-4.7-gnu/arch/mips/boot/tools/relocs.h
--- linux-libre-4.6-gnu/arch/mips/boot/tools/relocs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/mips/boot/tools/relocs.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,45 @@
+#ifndef RELOCS_H
+#define RELOCS_H
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <elf.h>
+#include <byteswap.h>
+#define USE_BSD
+#include <endian.h>
+#include <regex.h>
+
+void die(char *fmt, ...);
+
+/*
+ * Introduced for MIPSr6
+ */
+#ifndef R_MIPS_PC21_S2
+#define R_MIPS_PC21_S2		60
+#endif
+
+#ifndef R_MIPS_PC26_S2
+#define R_MIPS_PC26_S2		61
+#endif
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+enum symtype {
+	S_ABS,
+	S_REL,
+	S_SEG,
+	S_LIN,
+	S_NSYMTYPES
+};
+
+void process_32(FILE *fp, int as_text, int as_bin,
+		int show_reloc_info, int keep_relocs);
+void process_64(FILE *fp, int as_text, int as_bin,
+		int show_reloc_info, int keep_relocs);
+#endif /* RELOCS_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/boot/tools/relocs_main.c linux-libre-4.7-gnu/arch/mips/boot/tools/relocs_main.c
--- linux-libre-4.6-gnu/arch/mips/boot/tools/relocs_main.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/mips/boot/tools/relocs_main.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,84 @@
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <endian.h>
+#include <elf.h>
+
+#include "relocs.h"
+
+void die(char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	vfprintf(stderr, fmt, ap);
+	va_end(ap);
+	exit(1);
+}
+
+static void usage(void)
+{
+	die("relocs [--reloc-info|--text|--bin|--keep] vmlinux\n");
+}
+
+int main(int argc, char **argv)
+{
+	int show_reloc_info, as_text, as_bin, keep_relocs;
+	const char *fname;
+	FILE *fp;
+	int i;
+	unsigned char e_ident[EI_NIDENT];
+
+	show_reloc_info = 0;
+	as_text = 0;
+	as_bin = 0;
+	keep_relocs = 0;
+	fname = NULL;
+	for (i = 1; i < argc; i++) {
+		char *arg = argv[i];
+
+		if (*arg == '-') {
+			if (strcmp(arg, "--reloc-info") == 0) {
+				show_reloc_info = 1;
+				continue;
+			}
+			if (strcmp(arg, "--text") == 0) {
+				as_text = 1;
+				continue;
+			}
+			if (strcmp(arg, "--bin") == 0) {
+				as_bin = 1;
+				continue;
+			}
+			if (strcmp(arg, "--keep") == 0) {
+				keep_relocs = 1;
+				continue;
+			}
+		} else if (!fname) {
+			fname = arg;
+			continue;
+		}
+		usage();
+	}
+	if (!fname)
+		usage();
+
+	fp = fopen(fname, "r+");
+	if (!fp)
+		die("Cannot open %s: %s\n", fname, strerror(errno));
+
+	if (fread(&e_ident, 1, EI_NIDENT, fp) != EI_NIDENT)
+		die("Cannot read %s: %s", fname, strerror(errno));
+
+	rewind(fp);
+	if (e_ident[EI_CLASS] == ELFCLASS64)
+		process_64(fp, as_text,  as_bin, show_reloc_info, keep_relocs);
+	else
+		process_32(fp, as_text, as_bin, show_reloc_info, keep_relocs);
+	fclose(fp);
+	return 0;
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/cavium-octeon/csrc-octeon.c linux-libre-4.7-gnu/arch/mips/cavium-octeon/csrc-octeon.c
--- linux-libre-4.6-gnu/arch/mips/cavium-octeon/csrc-octeon.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/cavium-octeon/csrc-octeon.c	2016-07-24 15:23:50.000000000 -0400
@@ -19,6 +19,7 @@
 #include <asm/octeon/cvmx-ipd-defs.h>
 #include <asm/octeon/cvmx-mio-defs.h>
 #include <asm/octeon/cvmx-rst-defs.h>
+#include <asm/octeon/cvmx-fpa-defs.h>
 
 static u64 f;
 static u64 rdiv;
@@ -65,9 +66,13 @@ void __init octeon_setup_delays(void)
  */
 void octeon_init_cvmcount(void)
 {
+	u64 clk_reg;
 	unsigned long flags;
 	unsigned loops = 2;
 
+	clk_reg = octeon_has_feature(OCTEON_FEATURE_FPA3) ?
+		CVMX_FPA_CLK_COUNT : CVMX_IPD_CLK_COUNT;
+
 	/* Clobber loops so GCC will not unroll the following while loop. */
 	asm("" : "+r" (loops));
 
@@ -77,18 +82,18 @@ void octeon_init_cvmcount(void)
 	 * which should give more deterministic timing.
 	 */
 	while (loops--) {
-		u64 ipd_clk_count = cvmx_read_csr(CVMX_IPD_CLK_COUNT);
+		u64 clk_count = cvmx_read_csr(clk_reg);
 		if (rdiv != 0) {
-			ipd_clk_count *= rdiv;
+			clk_count *= rdiv;
 			if (f != 0) {
 				asm("dmultu\t%[cnt],%[f]\n\t"
 				    "mfhi\t%[cnt]"
-				    : [cnt] "+r" (ipd_clk_count)
+				    : [cnt] "+r" (clk_count)
 				    : [f] "r" (f)
 				    : "hi", "lo");
 			}
 		}
-		write_c0_cvmcount(ipd_clk_count);
+		write_c0_cvmcount(clk_count);
 	}
 	local_irq_restore(flags);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/cavium-octeon/executive/cvmx-helper.c linux-libre-4.7-gnu/arch/mips/cavium-octeon/executive/cvmx-helper.c
--- linux-libre-4.6-gnu/arch/mips/cavium-octeon/executive/cvmx-helper.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/cavium-octeon/executive/cvmx-helper.c	2016-07-24 15:23:50.000000000 -0400
@@ -87,6 +87,8 @@ int cvmx_helper_get_number_of_interfaces
 		return 9;
 	if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX))
 		return 4;
+	if (OCTEON_IS_MODEL(OCTEON_CN7XXX))
+		return 5;
 	else
 		return 3;
 }
@@ -260,6 +262,41 @@ static cvmx_helper_interface_mode_t __cv
 }
 
 /**
+ * @INTERNAL
+ * Return interface mode for CN7XXX.
+ */
+static cvmx_helper_interface_mode_t __cvmx_get_mode_cn7xxx(int interface)
+{
+	union cvmx_gmxx_inf_mode mode;
+
+	mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
+
+	switch (interface) {
+	case 0:
+	case 1:
+		switch (mode.cn68xx.mode) {
+		case 0:
+			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+		case 1:
+		case 2:
+			return CVMX_HELPER_INTERFACE_MODE_SGMII;
+		case 3:
+			return CVMX_HELPER_INTERFACE_MODE_XAUI;
+		default:
+			return CVMX_HELPER_INTERFACE_MODE_SGMII;
+		}
+	case 2:
+		return CVMX_HELPER_INTERFACE_MODE_NPI;
+	case 3:
+		return CVMX_HELPER_INTERFACE_MODE_LOOP;
+	case 4:
+		return CVMX_HELPER_INTERFACE_MODE_RGMII;
+	default:
+		return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+	}
+}
+
+/**
  * Get the operating mode of an interface. Depending on the Octeon
  * chip and configuration, this function returns an enumeration
  * of the type of packet I/O supported by an interface.
@@ -278,6 +315,12 @@ cvmx_helper_interface_mode_t cvmx_helper
 		return CVMX_HELPER_INTERFACE_MODE_DISABLED;
 
 	/*
+	 * OCTEON III models
+	 */
+	if (OCTEON_IS_MODEL(OCTEON_CN7XXX))
+		return __cvmx_get_mode_cn7xxx(interface);
+
+	/*
 	 * Octeon II models
 	 */
 	if (OCTEON_IS_MODEL(OCTEON_CN6XXX) || OCTEON_IS_MODEL(OCTEON_CNF71XX))
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/cavium-octeon/executive/cvmx-sysinfo.c linux-libre-4.7-gnu/arch/mips/cavium-octeon/executive/cvmx-sysinfo.c
--- linux-libre-4.6-gnu/arch/mips/cavium-octeon/executive/cvmx-sysinfo.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/cavium-octeon/executive/cvmx-sysinfo.c	2016-07-24 15:23:50.000000000 -0400
@@ -32,86 +32,22 @@
 #include <linux/module.h>
 
 #include <asm/octeon/cvmx.h>
-#include <asm/octeon/cvmx-spinlock.h>
 #include <asm/octeon/cvmx-sysinfo.h>
 
-/**
+/*
  * This structure defines the private state maintained by sysinfo module.
- *
  */
-static struct {
-	struct cvmx_sysinfo sysinfo;	   /* system information */
-	cvmx_spinlock_t lock;	   /* mutex spinlock */
-
-} state = {
-	.lock = CVMX_SPINLOCK_UNLOCKED_INITIALIZER
-};
-
+static struct cvmx_sysinfo sysinfo;	   /* system information */
 
 /*
- * Global variables that define the min/max of the memory region set
- * up for 32 bit userspace access.
- */
-uint64_t linux_mem32_min;
-uint64_t linux_mem32_max;
-uint64_t linux_mem32_wired;
-uint64_t linux_mem32_offset;
-
-/**
- * This function returns the application information as obtained
+ * Returns the application information as obtained
  * by the bootloader.  This provides the core mask of the cores
  * running the same application image, as well as the physical
  * memory regions available to the core.
- *
- * Returns  Pointer to the boot information structure
- *
  */
 struct cvmx_sysinfo *cvmx_sysinfo_get(void)
 {
-	return &(state.sysinfo);
+	return &sysinfo;
 }
 EXPORT_SYMBOL(cvmx_sysinfo_get);
 
-/**
- * This function is used in non-simple executive environments (such as
- * Linux kernel, u-boot, etc.)	to configure the minimal fields that
- * are required to use simple executive files directly.
- *
- * Locking (if required) must be handled outside of this
- * function
- *
- * @phy_mem_desc_ptr:
- *		     Pointer to global physical memory descriptor
- *		     (bootmem descriptor) @board_type: Octeon board
- *		     type enumeration
- *
- * @board_rev_major:
- *		     Board major revision
- * @board_rev_minor:
- *		     Board minor revision
- * @cpu_clock_hz:
- *		     CPU clock freqency in hertz
- *
- * Returns 0: Failure
- *	   1: success
- */
-int cvmx_sysinfo_minimal_initialize(void *phy_mem_desc_ptr,
-				    uint16_t board_type,
-				    uint8_t board_rev_major,
-				    uint8_t board_rev_minor,
-				    uint32_t cpu_clock_hz)
-{
-
-	/* The sysinfo structure was already initialized */
-	if (state.sysinfo.board_type)
-		return 0;
-
-	memset(&(state.sysinfo), 0x0, sizeof(state.sysinfo));
-	state.sysinfo.phy_mem_desc_ptr = phy_mem_desc_ptr;
-	state.sysinfo.board_type = board_type;
-	state.sysinfo.board_rev_major = board_rev_major;
-	state.sysinfo.board_rev_minor = board_rev_minor;
-	state.sysinfo.cpu_clock_hz = cpu_clock_hz;
-
-	return 1;
-}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/cavium-octeon/executive/octeon-model.c linux-libre-4.7-gnu/arch/mips/cavium-octeon/executive/octeon-model.c
--- linux-libre-4.6-gnu/arch/mips/cavium-octeon/executive/octeon-model.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/cavium-octeon/executive/octeon-model.c	2016-07-24 15:23:50.000000000 -0400
@@ -71,11 +71,11 @@ static const char *__init octeon_model_g
 	uint32_t fuse_data = 0;
 
 	fus3.u64 = 0;
-	if (!OCTEON_IS_MODEL(OCTEON_CN6XXX))
+	if (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN5XXX))
 		fus3.u64 = cvmx_read_csr(CVMX_L2D_FUS3);
 	fus_dat2.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT2);
 	fus_dat3.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT3);
-	num_cores = cvmx_pop(cvmx_read_csr(CVMX_CIU_FUSE));
+	num_cores = cvmx_octeon_num_cores();
 
 	/* Make sure the non existent devices look disabled */
 	switch ((chip_id >> 8) & 0xff) {
@@ -121,6 +121,15 @@ static const char *__init octeon_model_g
 	 * later.
 	 */
 	switch (num_cores) {
+	case 48:
+		core_model = "90";
+		break;
+	case 44:
+		core_model = "88";
+		break;
+	case 40:
+		core_model = "85";
+		break;
 	case 32:
 		core_model = "80";
 		break;
@@ -297,7 +306,7 @@ static const char *__init octeon_model_g
 				if (fus_dat3.s.nozip)
 					suffix = "SCP";
 
-				if (fus_dat3.s.bar2_en)
+				if (fus_dat3.cn56xx.bar2_en)
 					suffix = "NSPB2";
 			}
 			if (fus3.cn56xx.crip_1024k)
@@ -369,6 +378,73 @@ static const char *__init octeon_model_g
 		else
 			suffix = "AAP";
 		break;
+	case 0x94:		/* CNF71XX */
+		family = "F71";
+		if (fus_dat3.cnf71xx.nozip)
+			suffix = "SCP";
+		else
+			suffix = "AAP";
+		break;
+	case 0x95:		/* CN78XX */
+		if (num_cores == 6)	/* Other core counts match generic */
+			core_model = "35";
+		if (OCTEON_IS_MODEL(OCTEON_CN76XX))
+			family = "76";
+		else
+			family = "78";
+		if (fus_dat3.cn78xx.l2c_crip == 2)
+			family = "77";
+		if (fus_dat3.cn78xx.nozip
+		    && fus_dat3.cn78xx.nodfa_dte
+		    && fus_dat3.cn78xx.nohna_dte) {
+			if (fus_dat3.cn78xx.nozip &&
+				!fus_dat2.cn78xx.raid_en &&
+				fus_dat3.cn78xx.nohna_dte) {
+				suffix = "CP";
+			} else {
+				suffix = "SCP";
+			}
+		} else if (fus_dat2.cn78xx.raid_en == 0)
+			suffix = "HCP";
+		else
+			suffix = "AAP";
+		break;
+	case 0x96:		/* CN70XX */
+		family = "70";
+		if (cvmx_read_csr(CVMX_MIO_FUS_PDF) & (0x1ULL << 32))
+			family = "71";
+		if (fus_dat2.cn70xx.nocrypto)
+			suffix = "CP";
+		else if (fus_dat3.cn70xx.nodfa_dte)
+			suffix = "SCP";
+		else
+			suffix = "AAP";
+		break;
+	case 0x97:		/* CN73XX */
+		if (num_cores == 6)	/* Other core counts match generic */
+			core_model = "35";
+		family = "73";
+		if (fus_dat3.cn73xx.l2c_crip == 2)
+			family = "72";
+		if (fus_dat3.cn73xx.nozip
+				&& fus_dat3.cn73xx.nodfa_dte
+				&& fus_dat3.cn73xx.nohna_dte) {
+			if (!fus_dat2.cn73xx.raid_en)
+				suffix = "CP";
+			else
+				suffix = "SCP";
+		} else
+			suffix = "AAP";
+		break;
+	case 0x98:		/* CN75XX */
+		family = "F75";
+		if (fus_dat3.cn78xx.nozip
+		    && fus_dat3.cn78xx.nodfa_dte
+		    && fus_dat3.cn78xx.nohna_dte)
+			suffix = "SCP";
+		else
+			suffix = "AAP";
+		break;
 	default:
 		family = "XX";
 		core_model = "XX";
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/cavium-octeon/octeon-irq.c linux-libre-4.7-gnu/arch/mips/cavium-octeon/octeon-irq.c
--- linux-libre-4.6-gnu/arch/mips/cavium-octeon/octeon-irq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/cavium-octeon/octeon-irq.c	2016-07-24 15:23:50.000000000 -0400
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2004-2014 Cavium, Inc.
+ * Copyright (C) 2004-2016 Cavium, Inc.
  */
 
 #include <linux/of_address.h>
@@ -19,16 +19,53 @@
 
 #include <asm/octeon/octeon.h>
 #include <asm/octeon/cvmx-ciu2-defs.h>
+#include <asm/octeon/cvmx-ciu3-defs.h>
 
 static DEFINE_PER_CPU(unsigned long, octeon_irq_ciu0_en_mirror);
 static DEFINE_PER_CPU(unsigned long, octeon_irq_ciu1_en_mirror);
 static DEFINE_PER_CPU(raw_spinlock_t, octeon_irq_ciu_spinlock);
+static DEFINE_PER_CPU(unsigned int, octeon_irq_ciu3_idt_ip2);
+
+static DEFINE_PER_CPU(unsigned int, octeon_irq_ciu3_idt_ip3);
+static DEFINE_PER_CPU(struct octeon_ciu3_info *, octeon_ciu3_info);
+#define CIU3_MBOX_PER_CORE 10
+
+/*
+ * The 8 most significant bits of the intsn identify the interrupt major block.
+ * Each major block might use its own interrupt domain. Thus 256 domains are
+ * needed.
+ */
+#define MAX_CIU3_DOMAINS		256
+
+typedef irq_hw_number_t (*octeon_ciu3_intsn2hw_t)(struct irq_domain *, unsigned int);
+
+/* Information for each ciu3 in the system */
+struct octeon_ciu3_info {
+	u64			ciu3_addr;
+	int			node;
+	struct irq_domain	*domain[MAX_CIU3_DOMAINS];
+	octeon_ciu3_intsn2hw_t	intsn2hw[MAX_CIU3_DOMAINS];
+};
+
+/* Each ciu3 in the system uses its own data (one ciu3 per node) */
+static struct octeon_ciu3_info	*octeon_ciu3_info_per_node[4];
 
 struct octeon_irq_ciu_domain_data {
 	int num_sum;  /* number of sum registers (2 or 3). */
 };
 
-static __read_mostly u8 octeon_irq_ciu_to_irq[8][64];
+/* Register offsets from ciu3_addr */
+#define CIU3_CONST		0x220
+#define CIU3_IDT_CTL(_idt)	((_idt) * 8 + 0x110000)
+#define CIU3_IDT_PP(_idt, _idx)	((_idt) * 32 + (_idx) * 8 + 0x120000)
+#define CIU3_IDT_IO(_idt)	((_idt) * 8 + 0x130000)
+#define CIU3_DEST_PP_INT(_pp_ip) ((_pp_ip) * 8 + 0x200000)
+#define CIU3_DEST_IO_INT(_io)	((_io) * 8 + 0x210000)
+#define CIU3_ISC_CTL(_intsn)	((_intsn) * 8 + 0x80000000)
+#define CIU3_ISC_W1C(_intsn)	((_intsn) * 8 + 0x90000000)
+#define CIU3_ISC_W1S(_intsn)	((_intsn) * 8 + 0xa0000000)
+
+static __read_mostly int octeon_irq_ciu_to_irq[8][64];
 
 struct octeon_ciu_chip_data {
 	union {
@@ -39,10 +76,11 @@ struct octeon_ciu_chip_data {
 		struct {		/* only used for ciu/ciu2 */
 			u8 line;
 			u8 bit;
-			u8 gpio_line;
 		};
 	};
+	int gpio_line;
 	int current_cpu;	/* Next CPU expected to take this irq */
+	int ciu_node; /* NUMA node number of the CIU */
 };
 
 struct octeon_core_chip_data {
@@ -626,6 +664,18 @@ static void octeon_irq_ciu_enable_all_v2
 	}
 }
 
+static int octeon_irq_ciu_set_type(struct irq_data *data, unsigned int t)
+{
+	irqd_set_trigger_type(data, t);
+
+	if (t & IRQ_TYPE_EDGE_BOTH)
+		irq_set_handler_locked(data, handle_edge_irq);
+	else
+		irq_set_handler_locked(data, handle_level_irq);
+
+	return IRQ_SET_MASK_OK;
+}
+
 static void octeon_irq_gpio_setup(struct irq_data *data)
 {
 	union cvmx_gpio_bit_cfgx cfg;
@@ -663,7 +713,7 @@ static int octeon_irq_ciu_gpio_set_type(
 	irqd_set_trigger_type(data, t);
 	octeon_irq_gpio_setup(data);
 
-	if (irqd_get_trigger_type(data) & IRQ_TYPE_EDGE_BOTH)
+	if (t & IRQ_TYPE_EDGE_BOTH)
 		irq_set_handler_locked(data, handle_edge_irq);
 	else
 		irq_set_handler_locked(data, handle_level_irq);
@@ -863,6 +913,16 @@ static int octeon_irq_ciu_set_affinity_s
 }
 #endif
 
+static unsigned int edge_startup(struct irq_data *data)
+{
+	/* ack any pending edge-irq at startup, so there is
+	 * an _edge_ to fire on when the event reappears.
+	 */
+	data->chip->irq_ack(data);
+	data->chip->irq_enable(data);
+	return 0;
+}
+
 /*
  * Newer octeon chips have support for lockless CIU operation.
  */
@@ -1158,16 +1218,6 @@ static struct irq_chip *octeon_irq_ciu_c
 static struct irq_chip *octeon_irq_ciu_chip_edge;
 static struct irq_chip *octeon_irq_gpio_chip;
 
-static bool octeon_irq_virq_in_range(unsigned int virq)
-{
-	/* We cannot let it overflow the mapping array. */
-	if (virq < (1ul << 8 * sizeof(octeon_irq_ciu_to_irq[0][0])))
-		return true;
-
-	WARN_ONCE(true, "virq out of range %u.\n", virq);
-	return false;
-}
-
 static int octeon_irq_ciu_map(struct irq_domain *d,
 			      unsigned int virq, irq_hw_number_t hw)
 {
@@ -1176,13 +1226,6 @@ static int octeon_irq_ciu_map(struct irq
 	unsigned int bit = hw & 63;
 	struct octeon_irq_ciu_domain_data *dd = d->host_data;
 
-	if (!octeon_irq_virq_in_range(virq))
-		return -EINVAL;
-
-	/* Don't map irq if it is reserved for GPIO. */
-	if (line == 0 && bit >= 16 && bit <32)
-		return 0;
-
 	if (line >= dd->num_sum || octeon_irq_ciu_to_irq[line][bit] != 0)
 		return -EINVAL;
 
@@ -1215,9 +1258,6 @@ static int octeon_irq_gpio_map(struct ir
 	unsigned int line, bit;
 	int r;
 
-	if (!octeon_irq_virq_in_range(virq))
-		return -EINVAL;
-
 	line = (hw + gpiod->base_hwirq) >> 6;
 	bit = (hw + gpiod->base_hwirq) & 63;
 	if (line > ARRAY_SIZE(octeon_irq_ciu_to_irq) ||
@@ -1899,9 +1939,6 @@ static int octeon_irq_ciu2_map(struct ir
 	unsigned int line = hw >> 6;
 	unsigned int bit = hw & 63;
 
-	if (!octeon_irq_virq_in_range(virq))
-		return -EINVAL;
-
 	/*
 	 * Don't map irq if it is reserved for GPIO.
 	 * (Line 7 are the GPIO lines.)
@@ -2294,10 +2331,598 @@ static int __init octeon_irq_init_cib(st
 	return 0;
 }
 
+int octeon_irq_ciu3_xlat(struct irq_domain *d,
+			 struct device_node *node,
+			 const u32 *intspec,
+			 unsigned int intsize,
+			 unsigned long *out_hwirq,
+			 unsigned int *out_type)
+{
+	struct octeon_ciu3_info *ciu3_info = d->host_data;
+	unsigned int hwirq, type, intsn_major;
+	union cvmx_ciu3_iscx_ctl isc;
+
+	if (intsize < 2)
+		return -EINVAL;
+	hwirq = intspec[0];
+	type = intspec[1];
+
+	if (hwirq >= (1 << 20))
+		return -EINVAL;
+
+	intsn_major = hwirq >> 12;
+	switch (intsn_major) {
+	case 0x04: /* Software handled separately. */
+		return -EINVAL;
+	default:
+		break;
+	}
+
+	isc.u64 =  cvmx_read_csr(ciu3_info->ciu3_addr + CIU3_ISC_CTL(hwirq));
+	if (!isc.s.imp)
+		return -EINVAL;
+
+	switch (type) {
+	case 4: /* official value for level triggering. */
+		*out_type = IRQ_TYPE_LEVEL_HIGH;
+		break;
+	case 0: /* unofficial value, but we might as well let it work. */
+	case 1: /* official value for edge triggering. */
+		*out_type = IRQ_TYPE_EDGE_RISING;
+		break;
+	default: /* Nothing else is acceptable. */
+		return -EINVAL;
+	}
+
+	*out_hwirq = hwirq;
+
+	return 0;
+}
+
+void octeon_irq_ciu3_enable(struct irq_data *data)
+{
+	int cpu;
+	union cvmx_ciu3_iscx_ctl isc_ctl;
+	union cvmx_ciu3_iscx_w1c isc_w1c;
+	u64 isc_ctl_addr;
+
+	struct octeon_ciu_chip_data *cd;
+
+	cpu = next_cpu_for_irq(data);
+
+	cd = irq_data_get_irq_chip_data(data);
+
+	isc_w1c.u64 = 0;
+	isc_w1c.s.en = 1;
+	cvmx_write_csr(cd->ciu3_addr + CIU3_ISC_W1C(cd->intsn), isc_w1c.u64);
+
+	isc_ctl_addr = cd->ciu3_addr + CIU3_ISC_CTL(cd->intsn);
+	isc_ctl.u64 = 0;
+	isc_ctl.s.en = 1;
+	isc_ctl.s.idt = per_cpu(octeon_irq_ciu3_idt_ip2, cpu);
+	cvmx_write_csr(isc_ctl_addr, isc_ctl.u64);
+	cvmx_read_csr(isc_ctl_addr);
+}
+
+void octeon_irq_ciu3_disable(struct irq_data *data)
+{
+	u64 isc_ctl_addr;
+	union cvmx_ciu3_iscx_w1c isc_w1c;
+
+	struct octeon_ciu_chip_data *cd;
+
+	cd = irq_data_get_irq_chip_data(data);
+
+	isc_w1c.u64 = 0;
+	isc_w1c.s.en = 1;
+
+	isc_ctl_addr = cd->ciu3_addr + CIU3_ISC_CTL(cd->intsn);
+	cvmx_write_csr(cd->ciu3_addr + CIU3_ISC_W1C(cd->intsn), isc_w1c.u64);
+	cvmx_write_csr(isc_ctl_addr, 0);
+	cvmx_read_csr(isc_ctl_addr);
+}
+
+void octeon_irq_ciu3_ack(struct irq_data *data)
+{
+	u64 isc_w1c_addr;
+	union cvmx_ciu3_iscx_w1c isc_w1c;
+	struct octeon_ciu_chip_data *cd;
+	u32 trigger_type = irqd_get_trigger_type(data);
+
+	/*
+	 * We use a single irq_chip, so we have to do nothing to ack a
+	 * level interrupt.
+	 */
+	if (!(trigger_type & IRQ_TYPE_EDGE_BOTH))
+		return;
+
+	cd = irq_data_get_irq_chip_data(data);
+
+	isc_w1c.u64 = 0;
+	isc_w1c.s.raw = 1;
+
+	isc_w1c_addr = cd->ciu3_addr + CIU3_ISC_W1C(cd->intsn);
+	cvmx_write_csr(isc_w1c_addr, isc_w1c.u64);
+	cvmx_read_csr(isc_w1c_addr);
+}
+
+void octeon_irq_ciu3_mask(struct irq_data *data)
+{
+	union cvmx_ciu3_iscx_w1c isc_w1c;
+	u64 isc_w1c_addr;
+	struct octeon_ciu_chip_data *cd;
+
+	cd = irq_data_get_irq_chip_data(data);
+
+	isc_w1c.u64 = 0;
+	isc_w1c.s.en = 1;
+
+	isc_w1c_addr = cd->ciu3_addr + CIU3_ISC_W1C(cd->intsn);
+	cvmx_write_csr(isc_w1c_addr, isc_w1c.u64);
+	cvmx_read_csr(isc_w1c_addr);
+}
+
+void octeon_irq_ciu3_mask_ack(struct irq_data *data)
+{
+	union cvmx_ciu3_iscx_w1c isc_w1c;
+	u64 isc_w1c_addr;
+	struct octeon_ciu_chip_data *cd;
+	u32 trigger_type = irqd_get_trigger_type(data);
+
+	cd = irq_data_get_irq_chip_data(data);
+
+	isc_w1c.u64 = 0;
+	isc_w1c.s.en = 1;
+
+	/*
+	 * We use a single irq_chip, so only ack an edge (!level)
+	 * interrupt.
+	 */
+	if (trigger_type & IRQ_TYPE_EDGE_BOTH)
+		isc_w1c.s.raw = 1;
+
+	isc_w1c_addr = cd->ciu3_addr + CIU3_ISC_W1C(cd->intsn);
+	cvmx_write_csr(isc_w1c_addr, isc_w1c.u64);
+	cvmx_read_csr(isc_w1c_addr);
+}
+
+#ifdef CONFIG_SMP
+int octeon_irq_ciu3_set_affinity(struct irq_data *data,
+				 const struct cpumask *dest, bool force)
+{
+	union cvmx_ciu3_iscx_ctl isc_ctl;
+	union cvmx_ciu3_iscx_w1c isc_w1c;
+	u64 isc_ctl_addr;
+	int cpu;
+	bool enable_one = !irqd_irq_disabled(data) && !irqd_irq_masked(data);
+	struct octeon_ciu_chip_data *cd = irq_data_get_irq_chip_data(data);
+
+	if (!cpumask_subset(dest, cpumask_of_node(cd->ciu_node)))
+		return -EINVAL;
+
+	if (!enable_one)
+		return IRQ_SET_MASK_OK;
+
+	cd = irq_data_get_irq_chip_data(data);
+	cpu = cpumask_first(dest);
+	if (cpu >= nr_cpu_ids)
+		cpu = smp_processor_id();
+	cd->current_cpu = cpu;
+
+	isc_w1c.u64 = 0;
+	isc_w1c.s.en = 1;
+	cvmx_write_csr(cd->ciu3_addr + CIU3_ISC_W1C(cd->intsn), isc_w1c.u64);
+
+	isc_ctl_addr = cd->ciu3_addr + CIU3_ISC_CTL(cd->intsn);
+	isc_ctl.u64 = 0;
+	isc_ctl.s.en = 1;
+	isc_ctl.s.idt = per_cpu(octeon_irq_ciu3_idt_ip2, cpu);
+	cvmx_write_csr(isc_ctl_addr, isc_ctl.u64);
+	cvmx_read_csr(isc_ctl_addr);
+
+	return IRQ_SET_MASK_OK;
+}
+#endif
+
+static struct irq_chip octeon_irq_chip_ciu3 = {
+	.name = "CIU3",
+	.irq_startup = edge_startup,
+	.irq_enable = octeon_irq_ciu3_enable,
+	.irq_disable = octeon_irq_ciu3_disable,
+	.irq_ack = octeon_irq_ciu3_ack,
+	.irq_mask = octeon_irq_ciu3_mask,
+	.irq_mask_ack = octeon_irq_ciu3_mask_ack,
+	.irq_unmask = octeon_irq_ciu3_enable,
+	.irq_set_type = octeon_irq_ciu_set_type,
+#ifdef CONFIG_SMP
+	.irq_set_affinity = octeon_irq_ciu3_set_affinity,
+	.irq_cpu_offline = octeon_irq_cpu_offline_ciu,
+#endif
+};
+
+int octeon_irq_ciu3_mapx(struct irq_domain *d, unsigned int virq,
+			 irq_hw_number_t hw, struct irq_chip *chip)
+{
+	struct octeon_ciu3_info *ciu3_info = d->host_data;
+	struct octeon_ciu_chip_data *cd = kzalloc_node(sizeof(*cd), GFP_KERNEL,
+						       ciu3_info->node);
+	if (!cd)
+		return -ENOMEM;
+	cd->intsn = hw;
+	cd->current_cpu = -1;
+	cd->ciu3_addr = ciu3_info->ciu3_addr;
+	cd->ciu_node = ciu3_info->node;
+	irq_set_chip_and_handler(virq, chip, handle_edge_irq);
+	irq_set_chip_data(virq, cd);
+
+	return 0;
+}
+
+static int octeon_irq_ciu3_map(struct irq_domain *d,
+			       unsigned int virq, irq_hw_number_t hw)
+{
+	return octeon_irq_ciu3_mapx(d, virq, hw, &octeon_irq_chip_ciu3);
+}
+
+static struct irq_domain_ops octeon_dflt_domain_ciu3_ops = {
+	.map = octeon_irq_ciu3_map,
+	.unmap = octeon_irq_free_cd,
+	.xlate = octeon_irq_ciu3_xlat,
+};
+
+static void octeon_irq_ciu3_ip2(void)
+{
+	union cvmx_ciu3_destx_pp_int dest_pp_int;
+	struct octeon_ciu3_info *ciu3_info;
+	u64 ciu3_addr;
+
+	ciu3_info = __this_cpu_read(octeon_ciu3_info);
+	ciu3_addr = ciu3_info->ciu3_addr;
+
+	dest_pp_int.u64 = cvmx_read_csr(ciu3_addr + CIU3_DEST_PP_INT(3 * cvmx_get_local_core_num()));
+
+	if (likely(dest_pp_int.s.intr)) {
+		irq_hw_number_t intsn = dest_pp_int.s.intsn;
+		irq_hw_number_t hw;
+		struct irq_domain *domain;
+		/* Get the domain to use from the major block */
+		int block = intsn >> 12;
+		int ret;
+
+		domain = ciu3_info->domain[block];
+		if (ciu3_info->intsn2hw[block])
+			hw = ciu3_info->intsn2hw[block](domain, intsn);
+		else
+			hw = intsn;
+
+		ret = handle_domain_irq(domain, hw, NULL);
+		if (ret < 0) {
+			union cvmx_ciu3_iscx_w1c isc_w1c;
+			u64 isc_w1c_addr = ciu3_addr + CIU3_ISC_W1C(intsn);
+
+			isc_w1c.u64 = 0;
+			isc_w1c.s.en = 1;
+			cvmx_write_csr(isc_w1c_addr, isc_w1c.u64);
+			cvmx_read_csr(isc_w1c_addr);
+			spurious_interrupt();
+		}
+	} else {
+		spurious_interrupt();
+	}
+}
+
+/*
+ * 10 mbox per core starting from zero.
+ * Base mbox is core * 10
+ */
+static unsigned int octeon_irq_ciu3_base_mbox_intsn(int core)
+{
+	/* SW (mbox) are 0x04 in bits 12..19 */
+	return 0x04000 + CIU3_MBOX_PER_CORE * core;
+}
+
+static unsigned int octeon_irq_ciu3_mbox_intsn_for_core(int core, unsigned int mbox)
+{
+	return octeon_irq_ciu3_base_mbox_intsn(core) + mbox;
+}
+
+static unsigned int octeon_irq_ciu3_mbox_intsn_for_cpu(int cpu, unsigned int mbox)
+{
+	int local_core = octeon_coreid_for_cpu(cpu) & 0x3f;
+
+	return octeon_irq_ciu3_mbox_intsn_for_core(local_core, mbox);
+}
+
+static void octeon_irq_ciu3_mbox(void)
+{
+	union cvmx_ciu3_destx_pp_int dest_pp_int;
+	struct octeon_ciu3_info *ciu3_info;
+	u64 ciu3_addr;
+	int core = cvmx_get_local_core_num();
+
+	ciu3_info = __this_cpu_read(octeon_ciu3_info);
+	ciu3_addr = ciu3_info->ciu3_addr;
+
+	dest_pp_int.u64 = cvmx_read_csr(ciu3_addr + CIU3_DEST_PP_INT(1 + 3 * core));
+
+	if (likely(dest_pp_int.s.intr)) {
+		irq_hw_number_t intsn = dest_pp_int.s.intsn;
+		int mbox = intsn - octeon_irq_ciu3_base_mbox_intsn(core);
+
+		if (likely(mbox >= 0 && mbox < CIU3_MBOX_PER_CORE)) {
+			do_IRQ(mbox + OCTEON_IRQ_MBOX0);
+		} else {
+			union cvmx_ciu3_iscx_w1c isc_w1c;
+			u64 isc_w1c_addr = ciu3_addr + CIU3_ISC_W1C(intsn);
+
+			isc_w1c.u64 = 0;
+			isc_w1c.s.en = 1;
+			cvmx_write_csr(isc_w1c_addr, isc_w1c.u64);
+			cvmx_read_csr(isc_w1c_addr);
+			spurious_interrupt();
+		}
+	} else {
+		spurious_interrupt();
+	}
+}
+
+void octeon_ciu3_mbox_send(int cpu, unsigned int mbox)
+{
+	struct octeon_ciu3_info *ciu3_info;
+	unsigned int intsn;
+	union cvmx_ciu3_iscx_w1s isc_w1s;
+	u64 isc_w1s_addr;
+
+	if (WARN_ON_ONCE(mbox >= CIU3_MBOX_PER_CORE))
+		return;
+
+	intsn = octeon_irq_ciu3_mbox_intsn_for_cpu(cpu, mbox);
+	ciu3_info = per_cpu(octeon_ciu3_info, cpu);
+	isc_w1s_addr = ciu3_info->ciu3_addr + CIU3_ISC_W1S(intsn);
+
+	isc_w1s.u64 = 0;
+	isc_w1s.s.raw = 1;
+
+	cvmx_write_csr(isc_w1s_addr, isc_w1s.u64);
+	cvmx_read_csr(isc_w1s_addr);
+}
+
+static void octeon_irq_ciu3_mbox_set_enable(struct irq_data *data, int cpu, bool en)
+{
+	struct octeon_ciu3_info *ciu3_info;
+	unsigned int intsn;
+	u64 isc_ctl_addr, isc_w1c_addr;
+	union cvmx_ciu3_iscx_ctl isc_ctl;
+	unsigned int mbox = data->irq - OCTEON_IRQ_MBOX0;
+
+	intsn = octeon_irq_ciu3_mbox_intsn_for_cpu(cpu, mbox);
+	ciu3_info = per_cpu(octeon_ciu3_info, cpu);
+	isc_w1c_addr = ciu3_info->ciu3_addr + CIU3_ISC_W1C(intsn);
+	isc_ctl_addr = ciu3_info->ciu3_addr + CIU3_ISC_CTL(intsn);
+
+	isc_ctl.u64 = 0;
+	isc_ctl.s.en = 1;
+
+	cvmx_write_csr(isc_w1c_addr, isc_ctl.u64);
+	cvmx_write_csr(isc_ctl_addr, 0);
+	if (en) {
+		unsigned int idt = per_cpu(octeon_irq_ciu3_idt_ip3, cpu);
+
+		isc_ctl.u64 = 0;
+		isc_ctl.s.en = 1;
+		isc_ctl.s.idt = idt;
+		cvmx_write_csr(isc_ctl_addr, isc_ctl.u64);
+	}
+	cvmx_read_csr(isc_ctl_addr);
+}
+
+static void octeon_irq_ciu3_mbox_enable(struct irq_data *data)
+{
+	int cpu;
+	unsigned int mbox = data->irq - OCTEON_IRQ_MBOX0;
+
+	WARN_ON(mbox >= CIU3_MBOX_PER_CORE);
+
+	for_each_online_cpu(cpu)
+		octeon_irq_ciu3_mbox_set_enable(data, cpu, true);
+}
+
+static void octeon_irq_ciu3_mbox_disable(struct irq_data *data)
+{
+	int cpu;
+	unsigned int mbox = data->irq - OCTEON_IRQ_MBOX0;
+
+	WARN_ON(mbox >= CIU3_MBOX_PER_CORE);
+
+	for_each_online_cpu(cpu)
+		octeon_irq_ciu3_mbox_set_enable(data, cpu, false);
+}
+
+static void octeon_irq_ciu3_mbox_ack(struct irq_data *data)
+{
+	struct octeon_ciu3_info *ciu3_info;
+	unsigned int intsn;
+	u64 isc_w1c_addr;
+	union cvmx_ciu3_iscx_w1c isc_w1c;
+	unsigned int mbox = data->irq - OCTEON_IRQ_MBOX0;
+
+	intsn = octeon_irq_ciu3_mbox_intsn_for_core(cvmx_get_local_core_num(), mbox);
+
+	isc_w1c.u64 = 0;
+	isc_w1c.s.raw = 1;
+
+	ciu3_info = __this_cpu_read(octeon_ciu3_info);
+	isc_w1c_addr = ciu3_info->ciu3_addr + CIU3_ISC_W1C(intsn);
+	cvmx_write_csr(isc_w1c_addr, isc_w1c.u64);
+	cvmx_read_csr(isc_w1c_addr);
+}
+
+static void octeon_irq_ciu3_mbox_cpu_online(struct irq_data *data)
+{
+	octeon_irq_ciu3_mbox_set_enable(data, smp_processor_id(), true);
+}
+
+static void octeon_irq_ciu3_mbox_cpu_offline(struct irq_data *data)
+{
+	octeon_irq_ciu3_mbox_set_enable(data, smp_processor_id(), false);
+}
+
+static int octeon_irq_ciu3_alloc_resources(struct octeon_ciu3_info *ciu3_info)
+{
+	u64 b = ciu3_info->ciu3_addr;
+	int idt_ip2, idt_ip3, idt_ip4;
+	int unused_idt2;
+	int core = cvmx_get_local_core_num();
+	int i;
+
+	__this_cpu_write(octeon_ciu3_info, ciu3_info);
+
+	/*
+	 * 4 idt per core starting from 1 because zero is reserved.
+	 * Base idt per core is 4 * core + 1
+	 */
+	idt_ip2 = core * 4 + 1;
+	idt_ip3 = core * 4 + 2;
+	idt_ip4 = core * 4 + 3;
+	unused_idt2 = core * 4 + 4;
+	__this_cpu_write(octeon_irq_ciu3_idt_ip2, idt_ip2);
+	__this_cpu_write(octeon_irq_ciu3_idt_ip3, idt_ip3);
+
+	/* ip2 interrupts for this CPU */
+	cvmx_write_csr(b + CIU3_IDT_CTL(idt_ip2), 0);
+	cvmx_write_csr(b + CIU3_IDT_PP(idt_ip2, 0), 1ull << core);
+	cvmx_write_csr(b + CIU3_IDT_IO(idt_ip2), 0);
+
+	/* ip3 interrupts for this CPU */
+	cvmx_write_csr(b + CIU3_IDT_CTL(idt_ip3), 1);
+	cvmx_write_csr(b + CIU3_IDT_PP(idt_ip3, 0), 1ull << core);
+	cvmx_write_csr(b + CIU3_IDT_IO(idt_ip3), 0);
+
+	/* ip4 interrupts for this CPU */
+	cvmx_write_csr(b + CIU3_IDT_CTL(idt_ip4), 2);
+	cvmx_write_csr(b + CIU3_IDT_PP(idt_ip4, 0), 0);
+	cvmx_write_csr(b + CIU3_IDT_IO(idt_ip4), 0);
+
+	cvmx_write_csr(b + CIU3_IDT_CTL(unused_idt2), 0);
+	cvmx_write_csr(b + CIU3_IDT_PP(unused_idt2, 0), 0);
+	cvmx_write_csr(b + CIU3_IDT_IO(unused_idt2), 0);
+
+	for (i = 0; i < CIU3_MBOX_PER_CORE; i++) {
+		unsigned int intsn = octeon_irq_ciu3_mbox_intsn_for_core(core, i);
+
+		cvmx_write_csr(b + CIU3_ISC_W1C(intsn), 2);
+		cvmx_write_csr(b + CIU3_ISC_CTL(intsn), 0);
+	}
+
+	return 0;
+}
+
+static void octeon_irq_setup_secondary_ciu3(void)
+{
+	struct octeon_ciu3_info *ciu3_info;
+
+	ciu3_info = octeon_ciu3_info_per_node[cvmx_get_node_num()];
+	octeon_irq_ciu3_alloc_resources(ciu3_info);
+	irq_cpu_online();
+
+	/* Enable the CIU lines */
+	set_c0_status(STATUSF_IP3 | STATUSF_IP2);
+	if (octeon_irq_use_ip4)
+		set_c0_status(STATUSF_IP4);
+	else
+		clear_c0_status(STATUSF_IP4);
+}
+
+static struct irq_chip octeon_irq_chip_ciu3_mbox = {
+	.name = "CIU3-M",
+	.irq_enable = octeon_irq_ciu3_mbox_enable,
+	.irq_disable = octeon_irq_ciu3_mbox_disable,
+	.irq_ack = octeon_irq_ciu3_mbox_ack,
+
+	.irq_cpu_online = octeon_irq_ciu3_mbox_cpu_online,
+	.irq_cpu_offline = octeon_irq_ciu3_mbox_cpu_offline,
+	.flags = IRQCHIP_ONOFFLINE_ENABLED,
+};
+
+static int __init octeon_irq_init_ciu3(struct device_node *ciu_node,
+				       struct device_node *parent)
+{
+	int i;
+	int node;
+	struct irq_domain *domain;
+	struct octeon_ciu3_info *ciu3_info;
+	const __be32 *zero_addr;
+	u64 base_addr;
+	union cvmx_ciu3_const consts;
+
+	node = 0; /* of_node_to_nid(ciu_node); */
+	ciu3_info = kzalloc_node(sizeof(*ciu3_info), GFP_KERNEL, node);
+
+	if (!ciu3_info)
+		return -ENOMEM;
+
+	zero_addr = of_get_address(ciu_node, 0, NULL, NULL);
+	if (WARN_ON(!zero_addr))
+		return -EINVAL;
+
+	base_addr = of_translate_address(ciu_node, zero_addr);
+	base_addr = (u64)phys_to_virt(base_addr);
+
+	ciu3_info->ciu3_addr = base_addr;
+	ciu3_info->node = node;
+
+	consts.u64 = cvmx_read_csr(base_addr + CIU3_CONST);
+
+	octeon_irq_setup_secondary = octeon_irq_setup_secondary_ciu3;
+
+	octeon_irq_ip2 = octeon_irq_ciu3_ip2;
+	octeon_irq_ip3 = octeon_irq_ciu3_mbox;
+	octeon_irq_ip4 = octeon_irq_ip4_mask;
+
+	if (node == cvmx_get_node_num()) {
+		/* Mips internal */
+		octeon_irq_init_core();
+
+		/* Only do per CPU things if it is the CIU of the boot node. */
+		i = irq_alloc_descs_from(OCTEON_IRQ_MBOX0, 8, node);
+		WARN_ON(i < 0);
+
+		for (i = 0; i < 8; i++)
+			irq_set_chip_and_handler(i + OCTEON_IRQ_MBOX0,
+						 &octeon_irq_chip_ciu3_mbox, handle_percpu_irq);
+	}
+
+	/*
+	 * Initialize all domains to use the default domain. Specific major
+	 * blocks will overwrite the default domain as needed.
+	 */
+	domain = irq_domain_add_tree(ciu_node, &octeon_dflt_domain_ciu3_ops,
+				     ciu3_info);
+	for (i = 0; i < MAX_CIU3_DOMAINS; i++)
+		ciu3_info->domain[i] = domain;
+
+	octeon_ciu3_info_per_node[node] = ciu3_info;
+
+	if (node == cvmx_get_node_num()) {
+		/* Only do per CPU things if it is the CIU of the boot node. */
+		octeon_irq_ciu3_alloc_resources(ciu3_info);
+		if (node == 0)
+			irq_set_default_host(domain);
+
+		octeon_irq_use_ip4 = false;
+		/* Enable the CIU lines */
+		set_c0_status(STATUSF_IP2 | STATUSF_IP3);
+		clear_c0_status(STATUSF_IP4);
+	}
+
+	return 0;
+}
+
 static struct of_device_id ciu_types[] __initdata = {
 	{.compatible = "cavium,octeon-3860-ciu", .data = octeon_irq_init_ciu},
 	{.compatible = "cavium,octeon-3860-gpio", .data = octeon_irq_init_gpio},
 	{.compatible = "cavium,octeon-6880-ciu2", .data = octeon_irq_init_ciu2},
+	{.compatible = "cavium,octeon-7890-ciu3", .data = octeon_irq_init_ciu3},
 	{.compatible = "cavium,octeon-7130-cib", .data = octeon_irq_init_cib},
 	{}
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/cavium-octeon/octeon-platform.c linux-libre-4.7-gnu/arch/mips/cavium-octeon/octeon-platform.c
--- linux-libre-4.6-gnu/arch/mips/cavium-octeon/octeon-platform.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/cavium-octeon/octeon-platform.c	2016-07-24 15:23:50.000000000 -0400
@@ -13,6 +13,7 @@
 #include <linux/i2c.h>
 #include <linux/usb.h>
 #include <linux/dma-mapping.h>
+#include <linux/etherdevice.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
@@ -525,10 +526,17 @@ static void __init octeon_fdt_set_phy(in
 
 static void __init octeon_fdt_set_mac_addr(int n, u64 *pmac)
 {
+	const u8 *old_mac;
+	int old_len;
 	u8 new_mac[6];
 	u64 mac = *pmac;
 	int r;
 
+	old_mac = fdt_getprop(initial_boot_params, n, "local-mac-address",
+			      &old_len);
+	if (!old_mac || old_len != 6 || is_valid_ether_addr(old_mac))
+		return;
+
 	new_mac[0] = (mac >> 40) & 0xff;
 	new_mac[1] = (mac >> 32) & 0xff;
 	new_mac[2] = (mac >> 24) & 0xff;
@@ -560,7 +568,7 @@ static void __init octeon_fdt_rm_etherne
 	fdt_nop_node(initial_boot_params, node);
 }
 
-static void __init octeon_fdt_pip_port(int iface, int i, int p, int max, u64 *pmac)
+static void __init octeon_fdt_pip_port(int iface, int i, int p, int max)
 {
 	char name_buffer[20];
 	int eth;
@@ -583,10 +591,9 @@ static void __init octeon_fdt_pip_port(i
 
 	phy_addr = cvmx_helper_board_get_mii_address(ipd_port);
 	octeon_fdt_set_phy(eth, phy_addr);
-	octeon_fdt_set_mac_addr(eth, pmac);
 }
 
-static void __init octeon_fdt_pip_iface(int pip, int idx, u64 *pmac)
+static void __init octeon_fdt_pip_iface(int pip, int idx)
 {
 	char name_buffer[20];
 	int iface;
@@ -602,7 +609,73 @@ static void __init octeon_fdt_pip_iface(
 		count = cvmx_helper_ports_on_interface(idx);
 
 	for (p = 0; p < 16; p++)
-		octeon_fdt_pip_port(iface, idx, p, count - 1, pmac);
+		octeon_fdt_pip_port(iface, idx, p, count - 1);
+}
+
+void __init octeon_fill_mac_addresses(void)
+{
+	const char *alias_prop;
+	char name_buffer[20];
+	u64 mac_addr_base;
+	int aliases;
+	int pip;
+	int i;
+
+	aliases = fdt_path_offset(initial_boot_params, "/aliases");
+	if (aliases < 0)
+		return;
+
+	mac_addr_base =
+		((octeon_bootinfo->mac_addr_base[0] & 0xffull)) << 40 |
+		((octeon_bootinfo->mac_addr_base[1] & 0xffull)) << 32 |
+		((octeon_bootinfo->mac_addr_base[2] & 0xffull)) << 24 |
+		((octeon_bootinfo->mac_addr_base[3] & 0xffull)) << 16 |
+		((octeon_bootinfo->mac_addr_base[4] & 0xffull)) << 8 |
+		 (octeon_bootinfo->mac_addr_base[5] & 0xffull);
+
+	for (i = 0; i < 2; i++) {
+		int mgmt;
+
+		snprintf(name_buffer, sizeof(name_buffer), "mix%d", i);
+		alias_prop = fdt_getprop(initial_boot_params, aliases,
+					 name_buffer, NULL);
+		if (!alias_prop)
+			continue;
+		mgmt = fdt_path_offset(initial_boot_params, alias_prop);
+		if (mgmt < 0)
+			continue;
+		octeon_fdt_set_mac_addr(mgmt, &mac_addr_base);
+	}
+
+	alias_prop = fdt_getprop(initial_boot_params, aliases, "pip", NULL);
+	if (!alias_prop)
+		return;
+
+	pip = fdt_path_offset(initial_boot_params, alias_prop);
+	if (pip < 0)
+		return;
+
+	for (i = 0; i <= 4; i++) {
+		int iface;
+		int p;
+
+		snprintf(name_buffer, sizeof(name_buffer), "interface@%d", i);
+		iface = fdt_subnode_offset(initial_boot_params, pip,
+					   name_buffer);
+		if (iface < 0)
+			continue;
+		for (p = 0; p < 16; p++) {
+			int eth;
+
+			snprintf(name_buffer, sizeof(name_buffer),
+				 "ethernet@%x", p);
+			eth = fdt_subnode_offset(initial_boot_params, iface,
+						 name_buffer);
+			if (eth < 0)
+				continue;
+			octeon_fdt_set_mac_addr(eth, &mac_addr_base);
+		}
+	}
 }
 
 int __init octeon_prune_device_tree(void)
@@ -612,7 +685,6 @@ int __init octeon_prune_device_tree(void
 	const char *alias_prop;
 	char name_buffer[20];
 	int aliases;
-	u64 mac_addr_base;
 
 	if (fdt_check_header(initial_boot_params))
 		panic("Corrupt Device Tree.");
@@ -623,15 +695,6 @@ int __init octeon_prune_device_tree(void
 		return -EINVAL;
 	}
 
-
-	mac_addr_base =
-		((octeon_bootinfo->mac_addr_base[0] & 0xffull)) << 40 |
-		((octeon_bootinfo->mac_addr_base[1] & 0xffull)) << 32 |
-		((octeon_bootinfo->mac_addr_base[2] & 0xffull)) << 24 |
-		((octeon_bootinfo->mac_addr_base[3] & 0xffull)) << 16 |
-		((octeon_bootinfo->mac_addr_base[4] & 0xffull)) << 8 |
-		(octeon_bootinfo->mac_addr_base[5] & 0xffull);
-
 	if (OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CN63XX))
 		max_port = 2;
 	else if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN68XX))
@@ -660,7 +723,6 @@ int __init octeon_prune_device_tree(void
 			} else {
 				int phy_addr = cvmx_helper_board_get_mii_address(CVMX_HELPER_BOARD_MGMT_IPD_PORT + i);
 				octeon_fdt_set_phy(mgmt, phy_addr);
-				octeon_fdt_set_mac_addr(mgmt, &mac_addr_base);
 			}
 		}
 	}
@@ -670,7 +732,7 @@ int __init octeon_prune_device_tree(void
 		int pip = fdt_path_offset(initial_boot_params, pip_path);
 		if (pip	 >= 0)
 			for (i = 0; i <= 4; i++)
-				octeon_fdt_pip_iface(pip, i, &mac_addr_base);
+				octeon_fdt_pip_iface(pip, i);
 	}
 
 	/* I2C */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/cavium-octeon/setup.c linux-libre-4.7-gnu/arch/mips/cavium-octeon/setup.c
--- linux-libre-4.6-gnu/arch/mips/cavium-octeon/setup.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/cavium-octeon/setup.c	2016-07-24 15:23:50.000000000 -0400
@@ -43,8 +43,6 @@
 #include <asm/octeon/cvmx-mio-defs.h>
 #include <asm/octeon/cvmx-rst-defs.h>
 
-extern struct plat_smp_ops octeon_smp_ops;
-
 #ifdef CONFIG_PCI
 extern void pci_console_init(const char *arg);
 #endif
@@ -466,15 +464,25 @@ static void octeon_halt(void)
 
 static char __read_mostly octeon_system_type[80];
 
-static int __init init_octeon_system_type(void)
+static void __init init_octeon_system_type(void)
 {
-	snprintf(octeon_system_type, sizeof(octeon_system_type), "%s (%s)",
-		cvmx_board_type_to_string(octeon_bootinfo->board_type),
-		octeon_model_get_string(read_c0_prid()));
+	char const *board_type;
 
-	return 0;
+	board_type = cvmx_board_type_to_string(octeon_bootinfo->board_type);
+	if (board_type == NULL) {
+		struct device_node *root;
+		int ret;
+
+		root = of_find_node_by_path("/");
+		ret = of_property_read_string(root, "model", &board_type);
+		of_node_put(root);
+		if (ret)
+			board_type = "Unsupported Board";
+	}
+
+	snprintf(octeon_system_type, sizeof(octeon_system_type), "%s (%s)",
+		 board_type, octeon_model_get_string(read_c0_prid()));
 }
-early_initcall(init_octeon_system_type);
 
 /**
  * Return a string representing the system type
@@ -492,8 +500,6 @@ const char *get_system_type(void)
 void octeon_user_io_init(void)
 {
 	union octeon_cvmemctl cvmmemctl;
-	union cvmx_iob_fau_timeout fau_timeout;
-	union cvmx_pow_nw_tim nm_tim;
 
 	/* Get the current settings for CP0_CVMMEMCTL_REG */
 	cvmmemctl.u64 = read_c0_cvmmemctl();
@@ -595,17 +601,27 @@ void octeon_user_io_init(void)
 			  CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE,
 			  CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE * 128);
 
-	/* Set a default for the hardware timeouts */
-	fau_timeout.u64 = 0;
-	fau_timeout.s.tout_val = 0xfff;
-	/* Disable tagwait FAU timeout */
-	fau_timeout.s.tout_enb = 0;
-	cvmx_write_csr(CVMX_IOB_FAU_TIMEOUT, fau_timeout.u64);
+	if (octeon_has_feature(OCTEON_FEATURE_FAU)) {
+		union cvmx_iob_fau_timeout fau_timeout;
 
-	nm_tim.u64 = 0;
-	/* 4096 cycles */
-	nm_tim.s.nw_tim = 3;
-	cvmx_write_csr(CVMX_POW_NW_TIM, nm_tim.u64);
+		/* Set a default for the hardware timeouts */
+		fau_timeout.u64 = 0;
+		fau_timeout.s.tout_val = 0xfff;
+		/* Disable tagwait FAU timeout */
+		fau_timeout.s.tout_enb = 0;
+		cvmx_write_csr(CVMX_IOB_FAU_TIMEOUT, fau_timeout.u64);
+	}
+
+	if ((!OCTEON_IS_MODEL(OCTEON_CN68XX) &&
+	     !OCTEON_IS_MODEL(OCTEON_CN7XXX)) ||
+	    OCTEON_IS_MODEL(OCTEON_CN70XX)) {
+		union cvmx_pow_nw_tim nm_tim;
+
+		nm_tim.u64 = 0;
+		/* 4096 cycles */
+		nm_tim.s.nw_tim = 3;
+		cvmx_write_csr(CVMX_POW_NW_TIM, nm_tim.u64);
+	}
 
 	write_octeon_c0_icacheerr(0);
 	write_c0_derraddr1(0);
@@ -637,9 +653,22 @@ void __init prom_init(void)
 	sysinfo = cvmx_sysinfo_get();
 	memset(sysinfo, 0, sizeof(*sysinfo));
 	sysinfo->system_dram_size = octeon_bootinfo->dram_size << 20;
-	sysinfo->phy_mem_desc_ptr =
-		cvmx_phys_to_ptr(octeon_bootinfo->phy_mem_desc_addr);
-	sysinfo->core_mask = octeon_bootinfo->core_mask;
+	sysinfo->phy_mem_desc_addr = (u64)phys_to_virt(octeon_bootinfo->phy_mem_desc_addr);
+
+	if ((octeon_bootinfo->major_version > 1) ||
+	    (octeon_bootinfo->major_version == 1 &&
+	     octeon_bootinfo->minor_version >= 4))
+		cvmx_coremask_copy(&sysinfo->core_mask,
+				   &octeon_bootinfo->ext_core_mask);
+	else
+		cvmx_coremask_set64(&sysinfo->core_mask,
+				    octeon_bootinfo->core_mask);
+
+	/* Some broken u-boot pass garbage in upper bits, clear them out */
+	if (!OCTEON_IS_MODEL(OCTEON_CN78XX))
+		for (i = 512; i < 1024; i++)
+			cvmx_coremask_clear_core(&sysinfo->core_mask, i);
+
 	sysinfo->exception_base_addr = octeon_bootinfo->exception_base_addr;
 	sysinfo->cpu_clock_hz = octeon_bootinfo->eclock_hz;
 	sysinfo->dram_data_rate_hz = octeon_bootinfo->dclock_hz * 2;
@@ -867,7 +896,7 @@ void __init prom_init(void)
 #endif
 
 	octeon_user_io_init();
-	register_smp_ops(&octeon_smp_ops);
+	octeon_setup_smp();
 }
 
 /* Exclude a single page from the regions obtained in plat_mem_setup. */
@@ -1079,6 +1108,7 @@ void __init prom_free_prom_memory(void)
 	}
 }
 
+void __init octeon_fill_mac_addresses(void);
 int octeon_prune_device_tree(void);
 
 extern const char __appended_dtb;
@@ -1088,11 +1118,13 @@ void __init device_tree_init(void)
 {
 	const void *fdt;
 	bool do_prune;
+	bool fill_mac;
 
 #ifdef CONFIG_MIPS_ELF_APPENDED_DTB
 	if (!fdt_check_header(&__appended_dtb)) {
 		fdt = &__appended_dtb;
 		do_prune = false;
+		fill_mac = true;
 		pr_info("Using appended Device Tree.\n");
 	} else
 #endif
@@ -1101,13 +1133,16 @@ void __init device_tree_init(void)
 		if (fdt_check_header(fdt))
 			panic("Corrupt Device Tree passed to kernel.");
 		do_prune = false;
+		fill_mac = false;
 		pr_info("Using passed Device Tree.\n");
 	} else if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
 		fdt = &__dtb_octeon_68xx_begin;
 		do_prune = true;
+		fill_mac = true;
 	} else {
 		fdt = &__dtb_octeon_3xxx_begin;
 		do_prune = true;
+		fill_mac = true;
 	}
 
 	initial_boot_params = (void *)fdt;
@@ -1116,7 +1151,10 @@ void __init device_tree_init(void)
 		octeon_prune_device_tree();
 		pr_info("Using internal Device Tree.\n");
 	}
+	if (fill_mac)
+		octeon_fill_mac_addresses();
 	unflatten_and_copy_device_tree();
+	init_octeon_system_type();
 }
 
 static int __initdata disable_octeon_edac_p;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/cavium-octeon/smp.c linux-libre-4.7-gnu/arch/mips/cavium-octeon/smp.c
--- linux-libre-4.6-gnu/arch/mips/cavium-octeon/smp.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/cavium-octeon/smp.c	2016-07-24 15:23:50.000000000 -0400
@@ -30,25 +30,55 @@ uint64_t octeon_bootloader_entry_addr;
 EXPORT_SYMBOL(octeon_bootloader_entry_addr);
 #endif
 
+static void octeon_icache_flush(void)
+{
+	asm volatile ("synci 0($0)\n");
+}
+
+static void (*octeon_message_functions[8])(void) = {
+	scheduler_ipi,
+	generic_smp_call_function_interrupt,
+	octeon_icache_flush,
+};
+
 static irqreturn_t mailbox_interrupt(int irq, void *dev_id)
 {
-	const int coreid = cvmx_get_core_num();
-	uint64_t action;
+	u64 mbox_clrx = CVMX_CIU_MBOX_CLRX(cvmx_get_core_num());
+	u64 action;
+	int i;
 
-	/* Load the mailbox register to figure out what we're supposed to do */
-	action = cvmx_read_csr(CVMX_CIU_MBOX_CLRX(coreid)) & 0xffff;
+	/*
+	 * Make sure the function array initialization remains
+	 * correct.
+	 */
+	BUILD_BUG_ON(SMP_RESCHEDULE_YOURSELF != (1 << 0));
+	BUILD_BUG_ON(SMP_CALL_FUNCTION       != (1 << 1));
+	BUILD_BUG_ON(SMP_ICACHE_FLUSH        != (1 << 2));
+
+	/*
+	 * Load the mailbox register to figure out what we're supposed
+	 * to do.
+	 */
+	action = cvmx_read_csr(mbox_clrx);
+
+	if (OCTEON_IS_MODEL(OCTEON_CN68XX))
+		action &= 0xff;
+	else
+		action &= 0xffff;
 
 	/* Clear the mailbox to clear the interrupt */
-	cvmx_write_csr(CVMX_CIU_MBOX_CLRX(coreid), action);
+	cvmx_write_csr(mbox_clrx, action);
 
-	if (action & SMP_CALL_FUNCTION)
-		generic_smp_call_function_interrupt();
-	if (action & SMP_RESCHEDULE_YOURSELF)
-		scheduler_ipi();
+	for (i = 0; i < ARRAY_SIZE(octeon_message_functions) && action;) {
+		if (action & 1) {
+			void (*fn)(void) = octeon_message_functions[i];
 
-	/* Check if we've been told to flush the icache */
-	if (action & SMP_ICACHE_FLUSH)
-		asm volatile ("synci 0($0)\n");
+			if (fn)
+				fn();
+		}
+		action >>= 1;
+		i++;
+	}
 	return IRQ_HANDLED;
 }
 
@@ -97,13 +127,15 @@ static void octeon_smp_hotplug_setup(voi
 #endif
 }
 
-static void octeon_smp_setup(void)
+static void __init octeon_smp_setup(void)
 {
 	const int coreid = cvmx_get_core_num();
 	int cpus;
 	int id;
-	int core_mask = octeon_get_boot_coremask();
+	struct cvmx_sysinfo *sysinfo = cvmx_sysinfo_get();
+
 #ifdef CONFIG_HOTPLUG_CPU
+	int core_mask = octeon_get_boot_coremask();
 	unsigned int num_cores = cvmx_octeon_num_cores();
 #endif
 
@@ -119,7 +151,7 @@ static void octeon_smp_setup(void)
 	/* The present CPUs get the lowest CPU numbers. */
 	cpus = 1;
 	for (id = 0; id < NR_CPUS; id++) {
-		if ((id != coreid) && (core_mask & (1 << id))) {
+		if ((id != coreid) && cvmx_coremask_is_core_set(&sysinfo->core_mask, id)) {
 			set_cpu_possible(cpus, true);
 			set_cpu_present(cpus, true);
 			__cpu_number_map[id] = cpus;
@@ -196,7 +228,7 @@ static void octeon_init_secondary(void)
  * Callout to firmware before smp_init
  *
  */
-void octeon_prepare_cpus(unsigned int max_cpus)
+static void __init octeon_prepare_cpus(unsigned int max_cpus)
 {
 	/*
 	 * Only the low order mailbox bits are used for IPIs, leave
@@ -242,7 +274,7 @@ static int octeon_cpu_disable(void)
 	cpumask_clear_cpu(cpu, &cpu_callin_map);
 	octeon_fixup_irqs();
 
-	flush_cache_all();
+	__flush_cache_all();
 	local_flush_tlb_all();
 
 	return 0;
@@ -352,7 +384,7 @@ static int octeon_cpu_callback(struct no
 {
 	unsigned int cpu = (unsigned long)hcpu;
 
-	switch (action) {
+	switch (action & ~CPU_TASKS_FROZEN) {
 	case CPU_UP_PREPARE:
 		octeon_update_boot_vector(cpu);
 		break;
@@ -388,3 +420,92 @@ struct plat_smp_ops octeon_smp_ops = {
 	.cpu_die		= octeon_cpu_die,
 #endif
 };
+
+static irqreturn_t octeon_78xx_reched_interrupt(int irq, void *dev_id)
+{
+	scheduler_ipi();
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t octeon_78xx_call_function_interrupt(int irq, void *dev_id)
+{
+	generic_smp_call_function_interrupt();
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t octeon_78xx_icache_flush_interrupt(int irq, void *dev_id)
+{
+	octeon_icache_flush();
+	return IRQ_HANDLED;
+}
+
+/*
+ * Callout to firmware before smp_init
+ */
+static void octeon_78xx_prepare_cpus(unsigned int max_cpus)
+{
+	if (request_irq(OCTEON_IRQ_MBOX0 + 0,
+			octeon_78xx_reched_interrupt,
+			IRQF_PERCPU | IRQF_NO_THREAD, "Scheduler",
+			octeon_78xx_reched_interrupt)) {
+		panic("Cannot request_irq for SchedulerIPI");
+	}
+	if (request_irq(OCTEON_IRQ_MBOX0 + 1,
+			octeon_78xx_call_function_interrupt,
+			IRQF_PERCPU | IRQF_NO_THREAD, "SMP-Call",
+			octeon_78xx_call_function_interrupt)) {
+		panic("Cannot request_irq for SMP-Call");
+	}
+	if (request_irq(OCTEON_IRQ_MBOX0 + 2,
+			octeon_78xx_icache_flush_interrupt,
+			IRQF_PERCPU | IRQF_NO_THREAD, "ICache-Flush",
+			octeon_78xx_icache_flush_interrupt)) {
+		panic("Cannot request_irq for ICache-Flush");
+	}
+}
+
+static void octeon_78xx_send_ipi_single(int cpu, unsigned int action)
+{
+	int i;
+
+	for (i = 0; i < 8; i++) {
+		if (action & 1)
+			octeon_ciu3_mbox_send(cpu, i);
+		action >>= 1;
+	}
+}
+
+static void octeon_78xx_send_ipi_mask(const struct cpumask *mask,
+				      unsigned int action)
+{
+	unsigned int cpu;
+
+	for_each_cpu(cpu, mask)
+		octeon_78xx_send_ipi_single(cpu, action);
+}
+
+static struct plat_smp_ops octeon_78xx_smp_ops = {
+	.send_ipi_single	= octeon_78xx_send_ipi_single,
+	.send_ipi_mask		= octeon_78xx_send_ipi_mask,
+	.init_secondary		= octeon_init_secondary,
+	.smp_finish		= octeon_smp_finish,
+	.boot_secondary		= octeon_boot_secondary,
+	.smp_setup		= octeon_smp_setup,
+	.prepare_cpus		= octeon_78xx_prepare_cpus,
+#ifdef CONFIG_HOTPLUG_CPU
+	.cpu_disable		= octeon_cpu_disable,
+	.cpu_die		= octeon_cpu_die,
+#endif
+};
+
+void __init octeon_setup_smp(void)
+{
+	struct plat_smp_ops *ops;
+
+	if (octeon_has_feature(OCTEON_FEATURE_CIU3))
+		ops = &octeon_78xx_smp_ops;
+	else
+		ops = &octeon_smp_ops;
+
+	register_smp_ops(ops);
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/configs/bcm47xx_defconfig linux-libre-4.7-gnu/arch/mips/configs/bcm47xx_defconfig
--- linux-libre-4.6-gnu/arch/mips/configs/bcm47xx_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/configs/bcm47xx_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -23,7 +23,6 @@ CONFIG_IP_MROUTE=y
 CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
 CONFIG_SYN_COOKIES=y
 CONFIG_TCP_CONG_ADVANCED=y
-CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_MULTIPLE_TABLES=y
 CONFIG_IPV6_SUBTREES=y
 CONFIG_IPV6_MROUTE=y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/configs/bcm63xx_defconfig linux-libre-4.7-gnu/arch/mips/configs/bcm63xx_defconfig
--- linux-libre-4.6-gnu/arch/mips/configs/bcm63xx_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/configs/bcm63xx_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -44,6 +44,7 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 CONFIG_MTD=y
+CONFIG_MTD_BCM63XX_PARTS=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_CFI_AMDSTD=y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/configs/bigsur_defconfig linux-libre-4.7-gnu/arch/mips/configs/bigsur_defconfig
--- linux-libre-4.6-gnu/arch/mips/configs/bigsur_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/configs/bigsur_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -62,7 +62,6 @@ CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
 # CONFIG_INET_LRO is not set
 CONFIG_TCP_MD5SIG=y
-CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_IPV6_ROUTE_INFO=y
 CONFIG_IPV6_OPTIMISTIC_DAD=y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/configs/bmips_be_defconfig linux-libre-4.7-gnu/arch/mips/configs/bmips_be_defconfig
--- linux-libre-4.6-gnu/arch/mips/configs/bmips_be_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/configs/bmips_be_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -36,6 +36,7 @@ CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_PRINTK_TIME=y
 CONFIG_BRCMSTB_GISB_ARB=y
 CONFIG_MTD=y
+CONFIG_MTD_BCM63XX_PARTS=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_CFI_AMDSTD=y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/configs/cavium_octeon_defconfig linux-libre-4.7-gnu/arch/mips/configs/cavium_octeon_defconfig
--- linux-libre-4.6-gnu/arch/mips/configs/cavium_octeon_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/configs/cavium_octeon_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -119,14 +119,16 @@ CONFIG_SPI=y
 CONFIG_SPI_OCTEON=y
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
-# CONFIG_USB_SUPPORT is not set
-CONFIG_USB_EHCI_BIG_ENDIAN_MMIO=y
-CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
-CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB=m
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_HCD_PLATFORM=m
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_OHCI_HCD_PLATFORM=m
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_DS1307=y
 CONFIG_STAGING=y
 CONFIG_OCTEON_ETHERNET=y
+CONFIG_OCTEON_USB=m
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
@@ -152,6 +154,9 @@ CONFIG_SECURITY=y
 CONFIG_SECURITY_NETWORK=y
 CONFIG_CRYPTO_CBC=y
 CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MD5_OCTEON=y
+CONFIG_CRYPTO_SHA1_OCTEON=m
+CONFIG_CRYPTO_SHA256_OCTEON=m
+CONFIG_CRYPTO_SHA512_OCTEON=m
 CONFIG_CRYPTO_DES=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/configs/db1xxx_defconfig linux-libre-4.7-gnu/arch/mips/configs/db1xxx_defconfig
--- linux-libre-4.6-gnu/arch/mips/configs/db1xxx_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/configs/db1xxx_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -18,7 +18,6 @@ CONFIG_CGROUP_FREEZER=y
 CONFIG_CGROUP_DEVICE=y
 CONFIG_CPUSETS=y
 CONFIG_CGROUP_CPUACCT=y
-CONFIG_RESOURCE_COUNTERS=y
 CONFIG_MEMCG=y
 CONFIG_MEMCG_SWAP=y
 CONFIG_MEMCG_KMEM=y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/configs/decstation_defconfig linux-libre-4.7-gnu/arch/mips/configs/decstation_defconfig
--- linux-libre-4.6-gnu/arch/mips/configs/decstation_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/configs/decstation_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -30,7 +30,6 @@ CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
 CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_TCP_MD5SIG=y
-CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_IPV6_ROUTE_INFO=y
 CONFIG_INET6_AH=m
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/configs/ip22_defconfig linux-libre-4.7-gnu/arch/mips/configs/ip22_defconfig
--- linux-libre-4.6-gnu/arch/mips/configs/ip22_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/configs/ip22_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -48,7 +48,6 @@ CONFIG_INET_XFRM_MODE_TUNNEL=m
 CONFIG_INET_XFRM_MODE_BEET=m
 # CONFIG_INET_LRO is not set
 CONFIG_TCP_MD5SIG=y
-CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_IPV6_ROUTE_INFO=y
 CONFIG_IPV6_OPTIMISTIC_DAD=y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/configs/ip27_defconfig linux-libre-4.7-gnu/arch/mips/configs/ip27_defconfig
--- linux-libre-4.6-gnu/arch/mips/configs/ip27_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/configs/ip27_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -43,7 +43,6 @@ CONFIG_INET_XFRM_MODE_TUNNEL=m
 CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_TCP_MD5SIG=y
 CONFIG_IPV6=y
-CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_IPV6_ROUTE_INFO=y
 CONFIG_IPV6_OPTIMISTIC_DAD=y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/configs/jazz_defconfig linux-libre-4.7-gnu/arch/mips/configs/jazz_defconfig
--- linux-libre-4.6-gnu/arch/mips/configs/jazz_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/configs/jazz_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -34,7 +34,6 @@ CONFIG_IP_PIMSM_V2=y
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
 CONFIG_TCP_MD5SIG=y
-CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_IPV6_ROUTE_INFO=y
 CONFIG_INET6_AH=m
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/configs/lemote2f_defconfig linux-libre-4.7-gnu/arch/mips/configs/lemote2f_defconfig
--- linux-libre-4.6-gnu/arch/mips/configs/lemote2f_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/configs/lemote2f_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -71,7 +71,6 @@ CONFIG_TCP_CONG_ADVANCED=y
 CONFIG_TCP_CONG_BIC=y
 CONFIG_DEFAULT_BIC=y
 CONFIG_TCP_MD5SIG=y
-CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_IPV6_TUNNEL=m
 CONFIG_IPV6_MULTIPLE_TABLES=y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/configs/loongson1b_defconfig linux-libre-4.7-gnu/arch/mips/configs/loongson1b_defconfig
--- linux-libre-4.6-gnu/arch/mips/configs/loongson1b_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/mips/configs/loongson1b_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,125 @@
+CONFIG_MACH_LOONGSON32=y
+CONFIG_PREEMPT=y
+# CONFIG_SECCOMP is not set
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_KERNEL_XZ=y
+CONFIG_SYSVIPC=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_NAMESPACES=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EXPERT=y
+CONFIG_PERF_EVENTS=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_LOONGSON1=y
+CONFIG_MTD_UBI=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_SCSI=m
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=m
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+CONFIG_STMMAC_ETH=y
+# CONFIG_NET_VENDOR_WIZNET is not set
+# CONFIG_WLAN is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_LEGACY_PTY_COUNT=8
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_LOONGSON1=y
+# CONFIG_HWMON is not set
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_HID_GENERIC=m
+CONFIG_USB_HID=m
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_STORAGE=m
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_LOONGSON1=y
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_DNOTIFY is not set
+CONFIG_VFAT_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_UBIFS_FS=y
+CONFIG_UBIFS_FS_ADVANCED_COMPR=y
+CONFIG_UBIFS_ATIME_SUPPORT=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_DYNAMIC_DEBUG=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_DEBUG_FS=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_FTRACE is not set
+# CONFIG_EARLY_PRINTK is not set
+# CONFIG_CRYPTO_ECHAINIV is not set
+# CONFIG_CRYPTO_HW is not set
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/configs/loongson3_defconfig linux-libre-4.7-gnu/arch/mips/configs/loongson3_defconfig
--- linux-libre-4.6-gnu/arch/mips/configs/loongson3_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/configs/loongson3_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -25,7 +25,6 @@ CONFIG_TASK_XACCT=y
 CONFIG_TASK_IO_ACCOUNTING=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CPUSETS=y
-CONFIG_RESOURCE_COUNTERS=y
 CONFIG_MEMCG=y
 CONFIG_MEMCG_SWAP=y
 CONFIG_BLK_CGROUP=y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/configs/ls1b_defconfig linux-libre-4.7-gnu/arch/mips/configs/ls1b_defconfig
--- linux-libre-4.6-gnu/arch/mips/configs/ls1b_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/configs/ls1b_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,110 +0,0 @@
-CONFIG_MACH_LOONGSON32=y
-CONFIG_PREEMPT=y
-# CONFIG_SECCOMP is not set
-CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_BSD_PROCESS_ACCT_V3=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=16
-CONFIG_NAMESPACES=y
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_RD_BZIP2=y
-CONFIG_RD_LZMA=y
-CONFIG_EXPERT=y
-CONFIG_PERF_EVENTS=y
-# CONFIG_COMPAT_BRK is not set
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-# CONFIG_LBDAF is not set
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-# CONFIG_SUSPEND is not set
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_DIAG is not set
-# CONFIG_IPV6 is not set
-# CONFIG_WIRELESS is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_DEVTMPFS=y
-CONFIG_DEVTMPFS_MOUNT=y
-# CONFIG_STANDALONE is not set
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_SCSI=m
-# CONFIG_SCSI_PROC_FS is not set
-CONFIG_BLK_DEV_SD=m
-# CONFIG_SCSI_LOWLEVEL is not set
-CONFIG_NETDEVICES=y
-# CONFIG_NET_VENDOR_BROADCOM is not set
-# CONFIG_NET_VENDOR_CHELSIO is not set
-# CONFIG_NET_VENDOR_INTEL is not set
-# CONFIG_NET_VENDOR_MARVELL is not set
-# CONFIG_NET_VENDOR_MICREL is not set
-# CONFIG_NET_VENDOR_NATSEMI is not set
-# CONFIG_NET_VENDOR_SEEQ is not set
-# CONFIG_NET_VENDOR_SMSC is not set
-CONFIG_STMMAC_ETH=y
-CONFIG_STMMAC_DA=y
-# CONFIG_NET_VENDOR_WIZNET is not set
-# CONFIG_WLAN is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-CONFIG_VT_HW_CONSOLE_BINDING=y
-CONFIG_LEGACY_PTY_COUNT=8
-# CONFIG_DEVKMEM is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_HW_RANDOM is not set
-# CONFIG_HWMON is not set
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_USB_HID=m
-CONFIG_HID_GENERIC=m
-CONFIG_USB=y
-CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_HCD_PLATFORM=y
-# CONFIG_USB_EHCI_TT_NEWSCHED is not set
-CONFIG_USB_STORAGE=m
-CONFIG_USB_SERIAL=m
-CONFIG_USB_SERIAL_PL2303=m
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_LOONGSON1=y
-# CONFIG_IOMMU_SUPPORT is not set
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_POSIX_ACL=y
-CONFIG_EXT2_FS_SECURITY=y
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_POSIX_ACL=y
-CONFIG_EXT3_FS_SECURITY=y
-# CONFIG_DNOTIFY is not set
-CONFIG_VFAT_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
-# CONFIG_MISC_FILESYSTEMS is not set
-CONFIG_NFS_FS=y
-CONFIG_ROOT_NFS=y
-CONFIG_NLS_CODEPAGE_437=m
-CONFIG_NLS_ISO8859_1=m
-# CONFIG_ENABLE_WARN_DEPRECATED is not set
-# CONFIG_ENABLE_MUST_CHECK is not set
-CONFIG_MAGIC_SYSRQ=y
-# CONFIG_SCHED_DEBUG is not set
-# CONFIG_DEBUG_PREEMPT is not set
-# CONFIG_FTRACE is not set
-# CONFIG_EARLY_PRINTK is not set
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/configs/mtx1_defconfig linux-libre-4.7-gnu/arch/mips/configs/mtx1_defconfig
--- linux-libre-4.6-gnu/arch/mips/configs/mtx1_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/configs/mtx1_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -51,7 +51,6 @@ CONFIG_INET_IPCOMP=m
 CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
 CONFIG_INET_XFRM_MODE_BEET=m
-CONFIG_IPV6_PRIVACY=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/configs/nlm_xlp_defconfig linux-libre-4.7-gnu/arch/mips/configs/nlm_xlp_defconfig
--- linux-libre-4.6-gnu/arch/mips/configs/nlm_xlp_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/configs/nlm_xlp_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -95,7 +95,6 @@ CONFIG_TCP_CONG_YEAH=m
 CONFIG_TCP_CONG_ILLINOIS=m
 CONFIG_TCP_MD5SIG=y
 CONFIG_IPV6=y
-CONFIG_IPV6_PRIVACY=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/configs/nlm_xlr_defconfig linux-libre-4.7-gnu/arch/mips/configs/nlm_xlr_defconfig
--- linux-libre-4.6-gnu/arch/mips/configs/nlm_xlr_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/configs/nlm_xlr_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -75,7 +75,6 @@ CONFIG_TCP_CONG_YEAH=m
 CONFIG_TCP_CONG_ILLINOIS=m
 CONFIG_TCP_MD5SIG=y
 CONFIG_IPV6=y
-CONFIG_IPV6_PRIVACY=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/configs/rm200_defconfig linux-libre-4.7-gnu/arch/mips/configs/rm200_defconfig
--- linux-libre-4.6-gnu/arch/mips/configs/rm200_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/configs/rm200_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -37,7 +37,6 @@ CONFIG_INET_XFRM_MODE_TRANSPORT=m
 CONFIG_INET_XFRM_MODE_TUNNEL=m
 CONFIG_INET_XFRM_MODE_BEET=m
 CONFIG_TCP_MD5SIG=y
-CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_IPV6_ROUTE_INFO=y
 CONFIG_INET6_AH=m
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/dec/setup.c linux-libre-4.7-gnu/arch/mips/dec/setup.c
--- linux-libre-4.6-gnu/arch/mips/dec/setup.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/dec/setup.c	2016-07-24 15:23:50.000000000 -0400
@@ -60,6 +60,7 @@ EXPORT_SYMBOL(dec_kn_slot_size);
 int dec_tc_bus;
 
 DEFINE_SPINLOCK(ioasic_ssr_lock);
+EXPORT_SYMBOL(ioasic_ssr_lock);
 
 volatile u32 *ioasic_base;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/asmmacro.h linux-libre-4.7-gnu/arch/mips/include/asm/asmmacro.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/asmmacro.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/asmmacro.h	2016-07-24 15:23:50.000000000 -0400
@@ -19,6 +19,28 @@
 #include <asm/asmmacro-64.h>
 #endif
 
+/*
+ * Helper macros for generating raw instruction encodings.
+ */
+#ifdef CONFIG_CPU_MICROMIPS
+	.macro	insn32_if_mm enc
+	.insn
+	.hword ((\enc) >> 16)
+	.hword ((\enc) & 0xffff)
+	.endm
+
+	.macro	insn_if_mips enc
+	.endm
+#else
+	.macro	insn32_if_mm enc
+	.endm
+
+	.macro	insn_if_mips enc
+	.insn
+	.word (\enc)
+	.endm
+#endif
+
 #if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
 	.macro	local_irq_enable reg=t0
 	ei
@@ -235,6 +257,7 @@
 	.macro	ld_b	wd, off, base
 	.set	push
 	.set	mips32r2
+	.set	fp=64
 	.set	msa
 	ld.b	$w\wd, \off(\base)
 	.set	pop
@@ -243,6 +266,7 @@
 	.macro	ld_h	wd, off, base
 	.set	push
 	.set	mips32r2
+	.set	fp=64
 	.set	msa
 	ld.h	$w\wd, \off(\base)
 	.set	pop
@@ -251,6 +275,7 @@
 	.macro	ld_w	wd, off, base
 	.set	push
 	.set	mips32r2
+	.set	fp=64
 	.set	msa
 	ld.w	$w\wd, \off(\base)
 	.set	pop
@@ -268,6 +293,7 @@
 	.macro	st_b	wd, off, base
 	.set	push
 	.set	mips32r2
+	.set	fp=64
 	.set	msa
 	st.b	$w\wd, \off(\base)
 	.set	pop
@@ -276,6 +302,7 @@
 	.macro	st_h	wd, off, base
 	.set	push
 	.set	mips32r2
+	.set	fp=64
 	.set	msa
 	st.h	$w\wd, \off(\base)
 	.set	pop
@@ -284,6 +311,7 @@
 	.macro	st_w	wd, off, base
 	.set	push
 	.set	mips32r2
+	.set	fp=64
 	.set	msa
 	st.w	$w\wd, \off(\base)
 	.set	pop
@@ -298,21 +326,21 @@
 	.set	pop
 	.endm
 
-	.macro	copy_u_w	ws, n
+	.macro	copy_s_w	ws, n
 	.set	push
 	.set	mips32r2
 	.set	fp=64
 	.set	msa
-	copy_u.w $1, $w\ws[\n]
+	copy_s.w $1, $w\ws[\n]
 	.set	pop
 	.endm
 
-	.macro	copy_u_d	ws, n
+	.macro	copy_s_d	ws, n
 	.set	push
 	.set	mips64r2
 	.set	fp=64
 	.set	msa
-	copy_u.d $1, $w\ws[\n]
+	copy_s.d $1, $w\ws[\n]
 	.set	pop
 	.endm
 
@@ -335,38 +363,6 @@
 	.endm
 #else
 
-#ifdef CONFIG_CPU_MICROMIPS
-#define CFC_MSA_INSN		0x587e0056
-#define CTC_MSA_INSN		0x583e0816
-#define LDB_MSA_INSN		0x58000807
-#define LDH_MSA_INSN		0x58000817
-#define LDW_MSA_INSN		0x58000827
-#define LDD_MSA_INSN		0x58000837
-#define STB_MSA_INSN		0x5800080f
-#define STH_MSA_INSN		0x5800081f
-#define STW_MSA_INSN		0x5800082f
-#define STD_MSA_INSN		0x5800083f
-#define COPY_UW_MSA_INSN	0x58f00056
-#define COPY_UD_MSA_INSN	0x58f80056
-#define INSERT_W_MSA_INSN	0x59300816
-#define INSERT_D_MSA_INSN	0x59380816
-#else
-#define CFC_MSA_INSN		0x787e0059
-#define CTC_MSA_INSN		0x783e0819
-#define LDB_MSA_INSN		0x78000820
-#define LDH_MSA_INSN		0x78000821
-#define LDW_MSA_INSN		0x78000822
-#define LDD_MSA_INSN		0x78000823
-#define STB_MSA_INSN		0x78000824
-#define STH_MSA_INSN		0x78000825
-#define STW_MSA_INSN		0x78000826
-#define STD_MSA_INSN		0x78000827
-#define COPY_UW_MSA_INSN	0x78f00059
-#define COPY_UD_MSA_INSN	0x78f80059
-#define INSERT_W_MSA_INSN	0x79300819
-#define INSERT_D_MSA_INSN	0x79380819
-#endif
-
 	/*
 	 * Temporary until all toolchains in use include MSA support.
 	 */
@@ -374,8 +370,8 @@
 	.set	push
 	.set	noat
 	SET_HARDFLOAT
-	.insn
-	.word	CFC_MSA_INSN | (\cs << 11)
+	insn_if_mips 0x787e0059 | (\cs << 11)
+	insn32_if_mm 0x587e0056 | (\cs << 11)
 	move	\rd, $1
 	.set	pop
 	.endm
@@ -385,7 +381,8 @@
 	.set	noat
 	SET_HARDFLOAT
 	move	$1, \rs
-	.word	CTC_MSA_INSN | (\cd << 6)
+	insn_if_mips 0x783e0819 | (\cd << 6)
+	insn32_if_mm 0x583e0816 | (\cd << 6)
 	.set	pop
 	.endm
 
@@ -393,8 +390,9 @@
 	.set	push
 	.set	noat
 	SET_HARDFLOAT
-	addu	$1, \base, \off
-	.word	LDB_MSA_INSN | (\wd << 6)
+	PTR_ADDU $1, \base, \off
+	insn_if_mips 0x78000820 | (\wd << 6)
+	insn32_if_mm 0x58000807 | (\wd << 6)
 	.set	pop
 	.endm
 
@@ -402,8 +400,9 @@
 	.set	push
 	.set	noat
 	SET_HARDFLOAT
-	addu	$1, \base, \off
-	.word	LDH_MSA_INSN | (\wd << 6)
+	PTR_ADDU $1, \base, \off
+	insn_if_mips 0x78000821 | (\wd << 6)
+	insn32_if_mm 0x58000817 | (\wd << 6)
 	.set	pop
 	.endm
 
@@ -411,8 +410,9 @@
 	.set	push
 	.set	noat
 	SET_HARDFLOAT
-	addu	$1, \base, \off
-	.word	LDW_MSA_INSN | (\wd << 6)
+	PTR_ADDU $1, \base, \off
+	insn_if_mips 0x78000822 | (\wd << 6)
+	insn32_if_mm 0x58000827 | (\wd << 6)
 	.set	pop
 	.endm
 
@@ -420,8 +420,9 @@
 	.set	push
 	.set	noat
 	SET_HARDFLOAT
-	addu	$1, \base, \off
-	.word	LDD_MSA_INSN | (\wd << 6)
+	PTR_ADDU $1, \base, \off
+	insn_if_mips 0x78000823 | (\wd << 6)
+	insn32_if_mm 0x58000837 | (\wd << 6)
 	.set	pop
 	.endm
 
@@ -429,8 +430,9 @@
 	.set	push
 	.set	noat
 	SET_HARDFLOAT
-	addu	$1, \base, \off
-	.word	STB_MSA_INSN | (\wd << 6)
+	PTR_ADDU $1, \base, \off
+	insn_if_mips 0x78000824 | (\wd << 6)
+	insn32_if_mm 0x5800080f | (\wd << 6)
 	.set	pop
 	.endm
 
@@ -438,8 +440,9 @@
 	.set	push
 	.set	noat
 	SET_HARDFLOAT
-	addu	$1, \base, \off
-	.word	STH_MSA_INSN | (\wd << 6)
+	PTR_ADDU $1, \base, \off
+	insn_if_mips 0x78000825 | (\wd << 6)
+	insn32_if_mm 0x5800081f | (\wd << 6)
 	.set	pop
 	.endm
 
@@ -447,8 +450,9 @@
 	.set	push
 	.set	noat
 	SET_HARDFLOAT
-	addu	$1, \base, \off
-	.word	STW_MSA_INSN | (\wd << 6)
+	PTR_ADDU $1, \base, \off
+	insn_if_mips 0x78000826 | (\wd << 6)
+	insn32_if_mm 0x5800082f | (\wd << 6)
 	.set	pop
 	.endm
 
@@ -456,26 +460,27 @@
 	.set	push
 	.set	noat
 	SET_HARDFLOAT
-	addu	$1, \base, \off
-	.word	STD_MSA_INSN | (\wd << 6)
+	PTR_ADDU $1, \base, \off
+	insn_if_mips 0x78000827 | (\wd << 6)
+	insn32_if_mm 0x5800083f | (\wd << 6)
 	.set	pop
 	.endm
 
-	.macro	copy_u_w	ws, n
+	.macro	copy_s_w	ws, n
 	.set	push
 	.set	noat
 	SET_HARDFLOAT
-	.insn
-	.word	COPY_UW_MSA_INSN | (\n << 16) | (\ws << 11)
+	insn_if_mips 0x78b00059 | (\n << 16) | (\ws << 11)
+	insn32_if_mm 0x58b00056 | (\n << 16) | (\ws << 11)
 	.set	pop
 	.endm
 
-	.macro	copy_u_d	ws, n
+	.macro	copy_s_d	ws, n
 	.set	push
 	.set	noat
 	SET_HARDFLOAT
-	.insn
-	.word	COPY_UD_MSA_INSN | (\n << 16) | (\ws << 11)
+	insn_if_mips 0x78b80059 | (\n << 16) | (\ws << 11)
+	insn32_if_mm 0x58b80056 | (\n << 16) | (\ws << 11)
 	.set	pop
 	.endm
 
@@ -483,7 +488,8 @@
 	.set	push
 	.set	noat
 	SET_HARDFLOAT
-	.word	INSERT_W_MSA_INSN | (\n << 16) | (\wd << 6)
+	insn_if_mips 0x79300819 | (\n << 16) | (\wd << 6)
+	insn32_if_mm 0x59300816 | (\n << 16) | (\wd << 6)
 	.set	pop
 	.endm
 
@@ -491,46 +497,58 @@
 	.set	push
 	.set	noat
 	SET_HARDFLOAT
-	.word	INSERT_D_MSA_INSN | (\n << 16) | (\wd << 6)
+	insn_if_mips 0x79380819 | (\n << 16) | (\wd << 6)
+	insn32_if_mm 0x59380816 | (\n << 16) | (\wd << 6)
 	.set	pop
 	.endm
 #endif
 
+#ifdef TOOLCHAIN_SUPPORTS_MSA
+#define FPR_BASE_OFFS	THREAD_FPR0
+#define FPR_BASE	$1
+#else
+#define FPR_BASE_OFFS	0
+#define FPR_BASE	\thread
+#endif
+
 	.macro	msa_save_all	thread
-	st_d	0, THREAD_FPR0, \thread
-	st_d	1, THREAD_FPR1, \thread
-	st_d	2, THREAD_FPR2, \thread
-	st_d	3, THREAD_FPR3, \thread
-	st_d	4, THREAD_FPR4, \thread
-	st_d	5, THREAD_FPR5, \thread
-	st_d	6, THREAD_FPR6, \thread
-	st_d	7, THREAD_FPR7, \thread
-	st_d	8, THREAD_FPR8, \thread
-	st_d	9, THREAD_FPR9, \thread
-	st_d	10, THREAD_FPR10, \thread
-	st_d	11, THREAD_FPR11, \thread
-	st_d	12, THREAD_FPR12, \thread
-	st_d	13, THREAD_FPR13, \thread
-	st_d	14, THREAD_FPR14, \thread
-	st_d	15, THREAD_FPR15, \thread
-	st_d	16, THREAD_FPR16, \thread
-	st_d	17, THREAD_FPR17, \thread
-	st_d	18, THREAD_FPR18, \thread
-	st_d	19, THREAD_FPR19, \thread
-	st_d	20, THREAD_FPR20, \thread
-	st_d	21, THREAD_FPR21, \thread
-	st_d	22, THREAD_FPR22, \thread
-	st_d	23, THREAD_FPR23, \thread
-	st_d	24, THREAD_FPR24, \thread
-	st_d	25, THREAD_FPR25, \thread
-	st_d	26, THREAD_FPR26, \thread
-	st_d	27, THREAD_FPR27, \thread
-	st_d	28, THREAD_FPR28, \thread
-	st_d	29, THREAD_FPR29, \thread
-	st_d	30, THREAD_FPR30, \thread
-	st_d	31, THREAD_FPR31, \thread
 	.set	push
 	.set	noat
+#ifdef TOOLCHAIN_SUPPORTS_MSA
+	PTR_ADDU FPR_BASE, \thread, FPR_BASE_OFFS
+#endif
+	st_d	 0, THREAD_FPR0  - FPR_BASE_OFFS, FPR_BASE
+	st_d	 1, THREAD_FPR1  - FPR_BASE_OFFS, FPR_BASE
+	st_d	 2, THREAD_FPR2  - FPR_BASE_OFFS, FPR_BASE
+	st_d	 3, THREAD_FPR3  - FPR_BASE_OFFS, FPR_BASE
+	st_d	 4, THREAD_FPR4  - FPR_BASE_OFFS, FPR_BASE
+	st_d	 5, THREAD_FPR5  - FPR_BASE_OFFS, FPR_BASE
+	st_d	 6, THREAD_FPR6  - FPR_BASE_OFFS, FPR_BASE
+	st_d	 7, THREAD_FPR7  - FPR_BASE_OFFS, FPR_BASE
+	st_d	 8, THREAD_FPR8  - FPR_BASE_OFFS, FPR_BASE
+	st_d	 9, THREAD_FPR9  - FPR_BASE_OFFS, FPR_BASE
+	st_d	10, THREAD_FPR10 - FPR_BASE_OFFS, FPR_BASE
+	st_d	11, THREAD_FPR11 - FPR_BASE_OFFS, FPR_BASE
+	st_d	12, THREAD_FPR12 - FPR_BASE_OFFS, FPR_BASE
+	st_d	13, THREAD_FPR13 - FPR_BASE_OFFS, FPR_BASE
+	st_d	14, THREAD_FPR14 - FPR_BASE_OFFS, FPR_BASE
+	st_d	15, THREAD_FPR15 - FPR_BASE_OFFS, FPR_BASE
+	st_d	16, THREAD_FPR16 - FPR_BASE_OFFS, FPR_BASE
+	st_d	17, THREAD_FPR17 - FPR_BASE_OFFS, FPR_BASE
+	st_d	18, THREAD_FPR18 - FPR_BASE_OFFS, FPR_BASE
+	st_d	19, THREAD_FPR19 - FPR_BASE_OFFS, FPR_BASE
+	st_d	20, THREAD_FPR20 - FPR_BASE_OFFS, FPR_BASE
+	st_d	21, THREAD_FPR21 - FPR_BASE_OFFS, FPR_BASE
+	st_d	22, THREAD_FPR22 - FPR_BASE_OFFS, FPR_BASE
+	st_d	23, THREAD_FPR23 - FPR_BASE_OFFS, FPR_BASE
+	st_d	24, THREAD_FPR24 - FPR_BASE_OFFS, FPR_BASE
+	st_d	25, THREAD_FPR25 - FPR_BASE_OFFS, FPR_BASE
+	st_d	26, THREAD_FPR26 - FPR_BASE_OFFS, FPR_BASE
+	st_d	27, THREAD_FPR27 - FPR_BASE_OFFS, FPR_BASE
+	st_d	28, THREAD_FPR28 - FPR_BASE_OFFS, FPR_BASE
+	st_d	29, THREAD_FPR29 - FPR_BASE_OFFS, FPR_BASE
+	st_d	30, THREAD_FPR30 - FPR_BASE_OFFS, FPR_BASE
+	st_d	31, THREAD_FPR31 - FPR_BASE_OFFS, FPR_BASE
 	SET_HARDFLOAT
 	_cfcmsa	$1, MSA_CSR
 	sw	$1, THREAD_MSA_CSR(\thread)
@@ -543,41 +561,47 @@
 	SET_HARDFLOAT
 	lw	$1, THREAD_MSA_CSR(\thread)
 	_ctcmsa	MSA_CSR, $1
-	.set	pop
-	ld_d	0, THREAD_FPR0, \thread
-	ld_d	1, THREAD_FPR1, \thread
-	ld_d	2, THREAD_FPR2, \thread
-	ld_d	3, THREAD_FPR3, \thread
-	ld_d	4, THREAD_FPR4, \thread
-	ld_d	5, THREAD_FPR5, \thread
-	ld_d	6, THREAD_FPR6, \thread
-	ld_d	7, THREAD_FPR7, \thread
-	ld_d	8, THREAD_FPR8, \thread
-	ld_d	9, THREAD_FPR9, \thread
-	ld_d	10, THREAD_FPR10, \thread
-	ld_d	11, THREAD_FPR11, \thread
-	ld_d	12, THREAD_FPR12, \thread
-	ld_d	13, THREAD_FPR13, \thread
-	ld_d	14, THREAD_FPR14, \thread
-	ld_d	15, THREAD_FPR15, \thread
-	ld_d	16, THREAD_FPR16, \thread
-	ld_d	17, THREAD_FPR17, \thread
-	ld_d	18, THREAD_FPR18, \thread
-	ld_d	19, THREAD_FPR19, \thread
-	ld_d	20, THREAD_FPR20, \thread
-	ld_d	21, THREAD_FPR21, \thread
-	ld_d	22, THREAD_FPR22, \thread
-	ld_d	23, THREAD_FPR23, \thread
-	ld_d	24, THREAD_FPR24, \thread
-	ld_d	25, THREAD_FPR25, \thread
-	ld_d	26, THREAD_FPR26, \thread
-	ld_d	27, THREAD_FPR27, \thread
-	ld_d	28, THREAD_FPR28, \thread
-	ld_d	29, THREAD_FPR29, \thread
-	ld_d	30, THREAD_FPR30, \thread
-	ld_d	31, THREAD_FPR31, \thread
+#ifdef TOOLCHAIN_SUPPORTS_MSA
+	PTR_ADDU FPR_BASE, \thread, FPR_BASE_OFFS
+#endif
+	ld_d	 0, THREAD_FPR0  - FPR_BASE_OFFS, FPR_BASE
+	ld_d	 1, THREAD_FPR1  - FPR_BASE_OFFS, FPR_BASE
+	ld_d	 2, THREAD_FPR2  - FPR_BASE_OFFS, FPR_BASE
+	ld_d	 3, THREAD_FPR3  - FPR_BASE_OFFS, FPR_BASE
+	ld_d	 4, THREAD_FPR4  - FPR_BASE_OFFS, FPR_BASE
+	ld_d	 5, THREAD_FPR5  - FPR_BASE_OFFS, FPR_BASE
+	ld_d	 6, THREAD_FPR6  - FPR_BASE_OFFS, FPR_BASE
+	ld_d	 7, THREAD_FPR7  - FPR_BASE_OFFS, FPR_BASE
+	ld_d	 8, THREAD_FPR8  - FPR_BASE_OFFS, FPR_BASE
+	ld_d	 9, THREAD_FPR9  - FPR_BASE_OFFS, FPR_BASE
+	ld_d	10, THREAD_FPR10 - FPR_BASE_OFFS, FPR_BASE
+	ld_d	11, THREAD_FPR11 - FPR_BASE_OFFS, FPR_BASE
+	ld_d	12, THREAD_FPR12 - FPR_BASE_OFFS, FPR_BASE
+	ld_d	13, THREAD_FPR13 - FPR_BASE_OFFS, FPR_BASE
+	ld_d	14, THREAD_FPR14 - FPR_BASE_OFFS, FPR_BASE
+	ld_d	15, THREAD_FPR15 - FPR_BASE_OFFS, FPR_BASE
+	ld_d	16, THREAD_FPR16 - FPR_BASE_OFFS, FPR_BASE
+	ld_d	17, THREAD_FPR17 - FPR_BASE_OFFS, FPR_BASE
+	ld_d	18, THREAD_FPR18 - FPR_BASE_OFFS, FPR_BASE
+	ld_d	19, THREAD_FPR19 - FPR_BASE_OFFS, FPR_BASE
+	ld_d	20, THREAD_FPR20 - FPR_BASE_OFFS, FPR_BASE
+	ld_d	21, THREAD_FPR21 - FPR_BASE_OFFS, FPR_BASE
+	ld_d	22, THREAD_FPR22 - FPR_BASE_OFFS, FPR_BASE
+	ld_d	23, THREAD_FPR23 - FPR_BASE_OFFS, FPR_BASE
+	ld_d	24, THREAD_FPR24 - FPR_BASE_OFFS, FPR_BASE
+	ld_d	25, THREAD_FPR25 - FPR_BASE_OFFS, FPR_BASE
+	ld_d	26, THREAD_FPR26 - FPR_BASE_OFFS, FPR_BASE
+	ld_d	27, THREAD_FPR27 - FPR_BASE_OFFS, FPR_BASE
+	ld_d	28, THREAD_FPR28 - FPR_BASE_OFFS, FPR_BASE
+	ld_d	29, THREAD_FPR29 - FPR_BASE_OFFS, FPR_BASE
+	ld_d	30, THREAD_FPR30 - FPR_BASE_OFFS, FPR_BASE
+	ld_d	31, THREAD_FPR31 - FPR_BASE_OFFS, FPR_BASE
+	.set pop
 	.endm
 
+#undef FPR_BASE_OFFS
+#undef FPR_BASE
+
 	.macro	msa_init_upper wd
 #ifdef CONFIG_64BIT
 	insert_d \wd, 1
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/bitops.h linux-libre-4.7-gnu/arch/mips/include/asm/bitops.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/bitops.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/bitops.h	2016-07-24 15:23:50.000000000 -0400
@@ -19,25 +19,10 @@
 #include <asm/byteorder.h>		/* sigh ... */
 #include <asm/compiler.h>
 #include <asm/cpu-features.h>
+#include <asm/llsc.h>
 #include <asm/sgidefs.h>
 #include <asm/war.h>
 
-#if _MIPS_SZLONG == 32
-#define SZLONG_LOG 5
-#define SZLONG_MASK 31UL
-#define __LL		"ll	"
-#define __SC		"sc	"
-#define __INS		"ins	"
-#define __EXT		"ext	"
-#elif _MIPS_SZLONG == 64
-#define SZLONG_LOG 6
-#define SZLONG_MASK 63UL
-#define __LL		"lld	"
-#define __SC		"scd	"
-#define __INS		"dins	 "
-#define __EXT		"dext	 "
-#endif
-
 /*
  * These are the "slower" versions of the functions and are in bitops.c.
  * These functions call raw_local_irq_{save,restore}().
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/bitrev.h linux-libre-4.7-gnu/arch/mips/include/asm/bitrev.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/bitrev.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/mips/include/asm/bitrev.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,30 @@
+#ifndef __MIPS_ASM_BITREV_H__
+#define __MIPS_ASM_BITREV_H__
+
+#include <linux/swab.h>
+
+static __always_inline __attribute_const__ u32 __arch_bitrev32(u32 x)
+{
+	u32 ret;
+
+	asm("bitswap	%0, %1" : "=r"(ret) : "r"(__swab32(x)));
+	return ret;
+}
+
+static __always_inline __attribute_const__ u16 __arch_bitrev16(u16 x)
+{
+	u16 ret;
+
+	asm("bitswap	%0, %1" : "=r"(ret) : "r"(__swab16(x)));
+	return ret;
+}
+
+static __always_inline __attribute_const__ u8 __arch_bitrev8(u8 x)
+{
+	u8 ret;
+
+	asm("bitswap	%0, %1" : "=r"(ret) : "r"(x));
+	return ret;
+}
+
+#endif /* __MIPS_ASM_BITREV_H__ */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/bmips.h linux-libre-4.7-gnu/arch/mips/include/asm/bmips.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/bmips.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/bmips.h	2016-07-24 15:23:50.000000000 -0400
@@ -88,6 +88,7 @@ extern unsigned long bmips_tp1_irqs;
 
 extern void bmips_ebase_setup(void);
 extern asmlinkage void plat_wired_tlb_setup(void);
+extern void bmips_cpu_setup(void);
 
 static inline unsigned long bmips_read_zscm_reg(unsigned int offset)
 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/bootinfo.h linux-libre-4.7-gnu/arch/mips/include/asm/bootinfo.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/bootinfo.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/bootinfo.h	2016-07-24 15:23:50.000000000 -0400
@@ -144,4 +144,22 @@ static inline void plat_swiotlb_setup(vo
 
 #endif /* CONFIG_SWIOTLB */
 
+#ifdef CONFIG_USE_OF
+/**
+ * plat_get_fdt() - Return a pointer to the platform's device tree blob
+ *
+ * This function provides a platform independent API to get a pointer to the
+ * flattened device tree blob. The interface between bootloader and kernel
+ * is not consistent across platforms so it is necessary to provide this
+ * API such that common startup code can locate the FDT.
+ *
+ * This is used by the KASLR code to get command line arguments and random
+ * seed from the device tree. Any platform wishing to use KASLR should
+ * provide this API and select SYS_SUPPORTS_RELOCATABLE.
+ *
+ * Return: Pointer to the flattened device tree blob.
+ */
+extern void *plat_get_fdt(void);
+#endif /* CONFIG_USE_OF */
+
 #endif /* _ASM_BOOTINFO_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/cacheflush.h linux-libre-4.7-gnu/arch/mips/include/asm/cacheflush.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/cacheflush.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/cacheflush.h	2016-07-24 15:23:50.000000000 -0400
@@ -51,7 +51,6 @@ extern void (*flush_cache_range)(struct
 	unsigned long start, unsigned long end);
 extern void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, unsigned long pfn);
 extern void __flush_dcache_page(struct page *page);
-extern void __flush_icache_page(struct vm_area_struct *vma, struct page *page);
 
 #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
 static inline void flush_dcache_page(struct page *page)
@@ -77,11 +76,6 @@ static inline void flush_anon_page(struc
 static inline void flush_icache_page(struct vm_area_struct *vma,
 	struct page *page)
 {
-	if (!cpu_has_ic_fills_f_dc && (vma->vm_flags & VM_EXEC) &&
-	    Page_dcache_dirty(page)) {
-		__flush_icache_page(vma, page);
-		ClearPageDcacheDirty(page);
-	}
 }
 
 extern void (*flush_icache_range)(unsigned long start, unsigned long end);
@@ -132,6 +126,7 @@ static inline void kunmap_noncoherent(vo
 static inline void flush_kernel_dcache_page(struct page *page)
 {
 	BUG_ON(cpu_has_dc_aliases && PageHighMem(page));
+	flush_dcache_page(page);
 }
 
 /*
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/cacheops.h linux-libre-4.7-gnu/arch/mips/include/asm/cacheops.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/cacheops.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/cacheops.h	2016-07-24 15:23:50.000000000 -0400
@@ -21,6 +21,7 @@
 #define Cache_I				0x00
 #define Cache_D				0x01
 #define Cache_T				0x02
+#define Cache_V				0x02 /* Loongson-3 */
 #define Cache_S				0x03
 
 #define Index_Writeback_Inv		0x00
@@ -107,4 +108,9 @@
  */
 #define Hit_Invalidate_I_Loongson2	(Cache_I | 0x00)
 
+/*
+ * Loongson3-specific cacheops
+ */
+#define Index_Writeback_Inv_V		(Cache_V | Index_Writeback_Inv)
+
 #endif	/* __ASM_CACHEOPS_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/clkdev.h linux-libre-4.7-gnu/arch/mips/include/asm/clkdev.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/clkdev.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/clkdev.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,27 +0,0 @@
-/*
- *  based on arch/arm/include/asm/clkdev.h
- *
- *  Copyright (C) 2008 Russell King.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Helper for the clk API to assist looking up a struct clk.
- */
-#ifndef __ASM_CLKDEV_H
-#define __ASM_CLKDEV_H
-
-#include <linux/slab.h>
-
-#ifndef CONFIG_COMMON_CLK
-#define __clk_get(clk)	({ 1; })
-#define __clk_put(clk)	do { } while (0)
-#endif
-
-static inline struct clk_lookup_alloc *__clkdev_alloc(size_t size)
-{
-	return kzalloc(size, GFP_KERNEL);
-}
-
-#endif
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/cpu-features.h linux-libre-4.7-gnu/arch/mips/include/asm/cpu-features.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/cpu-features.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/cpu-features.h	2016-07-24 15:23:50.000000000 -0400
@@ -35,6 +35,9 @@
 #ifndef cpu_has_htw
 #define cpu_has_htw		(cpu_data[0].options & MIPS_CPU_HTW)
 #endif
+#ifndef cpu_has_ldpte
+#define cpu_has_ldpte		(cpu_data[0].options & MIPS_CPU_LDPTE)
+#endif
 #ifndef cpu_has_rixiex
 #define cpu_has_rixiex		(cpu_data[0].options & MIPS_CPU_RIXIEX)
 #endif
@@ -117,6 +120,21 @@
 #ifndef kernel_uses_llsc
 #define kernel_uses_llsc	cpu_has_llsc
 #endif
+#ifndef cpu_has_guestctl0ext
+#define cpu_has_guestctl0ext	(cpu_data[0].options & MIPS_CPU_GUESTCTL0EXT)
+#endif
+#ifndef cpu_has_guestctl1
+#define cpu_has_guestctl1	(cpu_data[0].options & MIPS_CPU_GUESTCTL1)
+#endif
+#ifndef cpu_has_guestctl2
+#define cpu_has_guestctl2	(cpu_data[0].options & MIPS_CPU_GUESTCTL2)
+#endif
+#ifndef cpu_has_guestid
+#define cpu_has_guestid		(cpu_data[0].options & MIPS_CPU_GUESTID)
+#endif
+#ifndef cpu_has_drg
+#define cpu_has_drg		(cpu_data[0].options & MIPS_CPU_DRG)
+#endif
 #ifndef cpu_has_mips16
 #define cpu_has_mips16		(cpu_data[0].ases & MIPS_ASE_MIPS16)
 #endif
@@ -142,8 +160,14 @@
 # endif
 #endif
 
+#ifndef cpu_has_lpa
+#define cpu_has_lpa		(cpu_data[0].options & MIPS_CPU_LPA)
+#endif
+#ifndef cpu_has_mvh
+#define cpu_has_mvh		(cpu_data[0].options & MIPS_CPU_MVH)
+#endif
 #ifndef cpu_has_xpa
-#define cpu_has_xpa		(cpu_data[0].options & MIPS_CPU_XPA)
+#define cpu_has_xpa		(cpu_has_lpa && cpu_has_mvh)
 #endif
 #ifndef cpu_has_vtag_icache
 #define cpu_has_vtag_icache	(cpu_data[0].icache.flags & MIPS_CACHE_VTAG)
@@ -180,6 +204,16 @@
 #endif
 #endif
 
+/* __builtin_constant_p(cpu_has_mips_r) && cpu_has_mips_r */
+#if !((defined(cpu_has_mips32r1) && cpu_has_mips32r1) || \
+	  (defined(cpu_has_mips32r2) && cpu_has_mips32r2) || \
+	  (defined(cpu_has_mips32r6) && cpu_has_mips32r6) || \
+	  (defined(cpu_has_mips64r1) && cpu_has_mips64r1) || \
+	  (defined(cpu_has_mips64r2) && cpu_has_mips64r2) || \
+	  (defined(cpu_has_mips64r6) && cpu_has_mips64r6))
+#define CPU_NO_EFFICIENT_FFS 1
+#endif
+
 #ifndef cpu_has_mips_1
 # define cpu_has_mips_1		(!cpu_has_mips_r6)
 #endif
@@ -307,10 +341,18 @@
 #define cpu_has_dsp2		(cpu_data[0].ases & MIPS_ASE_DSP2P)
 #endif
 
+#ifndef cpu_has_dsp3
+#define cpu_has_dsp3		(cpu_data[0].ases & MIPS_ASE_DSP3)
+#endif
+
 #ifndef cpu_has_mipsmt
 #define cpu_has_mipsmt		(cpu_data[0].ases & MIPS_ASE_MIPSMT)
 #endif
 
+#ifndef cpu_has_vp
+#define cpu_has_vp		(cpu_data[0].options & MIPS_CPU_VP)
+#endif
+
 #ifndef cpu_has_userlocal
 #define cpu_has_userlocal	(cpu_data[0].options & MIPS_CPU_ULRI)
 #endif
@@ -421,4 +463,107 @@
 #define cpu_has_nan_2008	(cpu_data[0].options & MIPS_CPU_NAN_2008)
 #endif
 
+#ifndef cpu_has_ebase_wg
+# define cpu_has_ebase_wg	(cpu_data[0].options & MIPS_CPU_EBASE_WG)
+#endif
+
+#ifndef cpu_has_badinstr
+# define cpu_has_badinstr	(cpu_data[0].options & MIPS_CPU_BADINSTR)
+#endif
+
+#ifndef cpu_has_badinstrp
+# define cpu_has_badinstrp	(cpu_data[0].options & MIPS_CPU_BADINSTRP)
+#endif
+
+#ifndef cpu_has_contextconfig
+# define cpu_has_contextconfig	(cpu_data[0].options & MIPS_CPU_CTXTC)
+#endif
+
+#ifndef cpu_has_perf
+# define cpu_has_perf		(cpu_data[0].options & MIPS_CPU_PERF)
+#endif
+
+/*
+ * Guest capabilities
+ */
+#ifndef cpu_guest_has_conf1
+#define cpu_guest_has_conf1	(cpu_data[0].guest.conf & (1 << 1))
+#endif
+#ifndef cpu_guest_has_conf2
+#define cpu_guest_has_conf2	(cpu_data[0].guest.conf & (1 << 2))
+#endif
+#ifndef cpu_guest_has_conf3
+#define cpu_guest_has_conf3	(cpu_data[0].guest.conf & (1 << 3))
+#endif
+#ifndef cpu_guest_has_conf4
+#define cpu_guest_has_conf4	(cpu_data[0].guest.conf & (1 << 4))
+#endif
+#ifndef cpu_guest_has_conf5
+#define cpu_guest_has_conf5	(cpu_data[0].guest.conf & (1 << 5))
+#endif
+#ifndef cpu_guest_has_conf6
+#define cpu_guest_has_conf6	(cpu_data[0].guest.conf & (1 << 6))
+#endif
+#ifndef cpu_guest_has_conf7
+#define cpu_guest_has_conf7	(cpu_data[0].guest.conf & (1 << 7))
+#endif
+#ifndef cpu_guest_has_fpu
+#define cpu_guest_has_fpu	(cpu_data[0].guest.options & MIPS_CPU_FPU)
+#endif
+#ifndef cpu_guest_has_watch
+#define cpu_guest_has_watch	(cpu_data[0].guest.options & MIPS_CPU_WATCH)
+#endif
+#ifndef cpu_guest_has_contextconfig
+#define cpu_guest_has_contextconfig (cpu_data[0].guest.options & MIPS_CPU_CTXTC)
+#endif
+#ifndef cpu_guest_has_segments
+#define cpu_guest_has_segments	(cpu_data[0].guest.options & MIPS_CPU_SEGMENTS)
+#endif
+#ifndef cpu_guest_has_badinstr
+#define cpu_guest_has_badinstr	(cpu_data[0].guest.options & MIPS_CPU_BADINSTR)
+#endif
+#ifndef cpu_guest_has_badinstrp
+#define cpu_guest_has_badinstrp	(cpu_data[0].guest.options & MIPS_CPU_BADINSTRP)
+#endif
+#ifndef cpu_guest_has_htw
+#define cpu_guest_has_htw	(cpu_data[0].guest.options & MIPS_CPU_HTW)
+#endif
+#ifndef cpu_guest_has_msa
+#define cpu_guest_has_msa	(cpu_data[0].guest.ases & MIPS_ASE_MSA)
+#endif
+#ifndef cpu_guest_has_kscr
+#define cpu_guest_has_kscr(n)	(cpu_data[0].guest.kscratch_mask & (1u << (n)))
+#endif
+#ifndef cpu_guest_has_rw_llb
+#define cpu_guest_has_rw_llb	(cpu_has_mips_r6 || (cpu_data[0].guest.options & MIPS_CPU_RW_LLB))
+#endif
+#ifndef cpu_guest_has_perf
+#define cpu_guest_has_perf	(cpu_data[0].guest.options & MIPS_CPU_PERF)
+#endif
+#ifndef cpu_guest_has_maar
+#define cpu_guest_has_maar	(cpu_data[0].guest.options & MIPS_CPU_MAAR)
+#endif
+
+/*
+ * Guest dynamic capabilities
+ */
+#ifndef cpu_guest_has_dyn_fpu
+#define cpu_guest_has_dyn_fpu	(cpu_data[0].guest.options_dyn & MIPS_CPU_FPU)
+#endif
+#ifndef cpu_guest_has_dyn_watch
+#define cpu_guest_has_dyn_watch	(cpu_data[0].guest.options_dyn & MIPS_CPU_WATCH)
+#endif
+#ifndef cpu_guest_has_dyn_contextconfig
+#define cpu_guest_has_dyn_contextconfig (cpu_data[0].guest.options_dyn & MIPS_CPU_CTXTC)
+#endif
+#ifndef cpu_guest_has_dyn_perf
+#define cpu_guest_has_dyn_perf	(cpu_data[0].guest.options_dyn & MIPS_CPU_PERF)
+#endif
+#ifndef cpu_guest_has_dyn_msa
+#define cpu_guest_has_dyn_msa	(cpu_data[0].guest.ases_dyn & MIPS_ASE_MSA)
+#endif
+#ifndef cpu_guest_has_dyn_maar
+#define cpu_guest_has_dyn_maar	(cpu_data[0].guest.options_dyn & MIPS_CPU_MAAR)
+#endif
+
 #endif /* __ASM_CPU_FEATURES_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/cpu.h linux-libre-4.7-gnu/arch/mips/include/asm/cpu.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/cpu.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/cpu.h	2016-07-24 15:23:50.000000000 -0400
@@ -42,6 +42,7 @@
 #define PRID_COMP_LEXRA		0x0b0000
 #define PRID_COMP_NETLOGIC	0x0c0000
 #define PRID_COMP_CAVIUM	0x0d0000
+#define PRID_COMP_LOONGSON	0x140000
 #define PRID_COMP_INGENIC_D0	0xd00000	/* JZ4740, JZ4750 */
 #define PRID_COMP_INGENIC_D1	0xd10000	/* JZ4770, JZ4775 */
 #define PRID_COMP_INGENIC_E1	0xe10000	/* JZ4780 */
@@ -118,9 +119,11 @@
 #define PRID_IMP_INTERAPTIV_MP	0xa100
 #define PRID_IMP_PROAPTIV_UP	0xa200
 #define PRID_IMP_PROAPTIV_MP	0xa300
+#define PRID_IMP_P6600		0xa400
 #define PRID_IMP_M5150		0xa700
 #define PRID_IMP_P5600		0xa800
 #define PRID_IMP_I6400		0xa900
+#define PRID_IMP_M6250		0xab00
 
 /*
  * These are the PRID's for when 23:16 == PRID_COMP_SIBYTE
@@ -169,6 +172,8 @@
 #define PRID_IMP_CAVIUM_CNF71XX 0x9400
 #define PRID_IMP_CAVIUM_CN78XX 0x9500
 #define PRID_IMP_CAVIUM_CN70XX 0x9600
+#define PRID_IMP_CAVIUM_CN73XX 0x9700
+#define PRID_IMP_CAVIUM_CNF75XX 0x9800
 
 /*
  * These are the PRID's for when 23:16 == PRID_COMP_INGENIC_*
@@ -237,9 +242,10 @@
 #define PRID_REV_LOONGSON1B	0x0020
 #define PRID_REV_LOONGSON2E	0x0002
 #define PRID_REV_LOONGSON2F	0x0003
-#define PRID_REV_LOONGSON3A	0x0005
+#define PRID_REV_LOONGSON3A_R1	0x0005
 #define PRID_REV_LOONGSON3B_R1	0x0006
 #define PRID_REV_LOONGSON3B_R2	0x0007
+#define PRID_REV_LOONGSON3A_R2	0x0008
 
 /*
  * Older processors used to encode processor version and revision in two
@@ -307,8 +313,8 @@ enum cpu_type_enum {
 	CPU_4KC, CPU_4KEC, CPU_4KSC, CPU_24K, CPU_34K, CPU_1004K, CPU_74K,
 	CPU_ALCHEMY, CPU_PR4450, CPU_BMIPS32, CPU_BMIPS3300, CPU_BMIPS4350,
 	CPU_BMIPS4380, CPU_BMIPS5000, CPU_JZRISC, CPU_LOONGSON1, CPU_M14KC,
-	CPU_M14KEC, CPU_INTERAPTIV, CPU_P5600, CPU_PROAPTIV, CPU_1074K, CPU_M5150,
-	CPU_I6400,
+	CPU_M14KEC, CPU_INTERAPTIV, CPU_P5600, CPU_PROAPTIV, CPU_1074K,
+	CPU_M5150, CPU_I6400, CPU_P6600, CPU_M6250,
 
 	/*
 	 * MIPS64 class processors
@@ -346,48 +352,68 @@ enum cpu_type_enum {
 	MIPS_CPU_ISA_M64R6)
 
 /*
+ * Private version of BIT_ULL() to escape include file recursion hell.
+ * We soon will have to switch to another mechanism that will work with
+ * more than 64 bits anyway.
+ */
+#define MBIT_ULL(bit)		(1ULL << (bit))
+
+/*
  * CPU Option encodings
  */
-#define MIPS_CPU_TLB		0x00000001ull /* CPU has TLB */
-#define MIPS_CPU_4KEX		0x00000002ull /* "R4K" exception model */
-#define MIPS_CPU_3K_CACHE	0x00000004ull /* R3000-style caches */
-#define MIPS_CPU_4K_CACHE	0x00000008ull /* R4000-style caches */
-#define MIPS_CPU_TX39_CACHE	0x00000010ull /* TX3900-style caches */
-#define MIPS_CPU_FPU		0x00000020ull /* CPU has FPU */
-#define MIPS_CPU_32FPR		0x00000040ull /* 32 dbl. prec. FP registers */
-#define MIPS_CPU_COUNTER	0x00000080ull /* Cycle count/compare */
-#define MIPS_CPU_WATCH		0x00000100ull /* watchpoint registers */
-#define MIPS_CPU_DIVEC		0x00000200ull /* dedicated interrupt vector */
-#define MIPS_CPU_VCE		0x00000400ull /* virt. coherence conflict possible */
-#define MIPS_CPU_CACHE_CDEX_P	0x00000800ull /* Create_Dirty_Exclusive CACHE op */
-#define MIPS_CPU_CACHE_CDEX_S	0x00001000ull /* ... same for seconary cache ... */
-#define MIPS_CPU_MCHECK		0x00002000ull /* Machine check exception */
-#define MIPS_CPU_EJTAG		0x00004000ull /* EJTAG exception */
-#define MIPS_CPU_NOFPUEX	0x00008000ull /* no FPU exception */
-#define MIPS_CPU_LLSC		0x00010000ull /* CPU has ll/sc instructions */
-#define MIPS_CPU_INCLUSIVE_CACHES	0x00020000ull /* P-cache subset enforced */
-#define MIPS_CPU_PREFETCH	0x00040000ull /* CPU has usable prefetch */
-#define MIPS_CPU_VINT		0x00080000ull /* CPU supports MIPSR2 vectored interrupts */
-#define MIPS_CPU_VEIC		0x00100000ull /* CPU supports MIPSR2 external interrupt controller mode */
-#define MIPS_CPU_ULRI		0x00200000ull /* CPU has ULRI feature */
-#define MIPS_CPU_PCI		0x00400000ull /* CPU has Perf Ctr Int indicator */
-#define MIPS_CPU_RIXI		0x00800000ull /* CPU has TLB Read/eXec Inhibit */
-#define MIPS_CPU_MICROMIPS	0x01000000ull /* CPU has microMIPS capability */
-#define MIPS_CPU_TLBINV		0x02000000ull /* CPU supports TLBINV/F */
-#define MIPS_CPU_SEGMENTS	0x04000000ull /* CPU supports Segmentation Control registers */
-#define MIPS_CPU_EVA		0x80000000ull /* CPU supports Enhanced Virtual Addressing */
-#define MIPS_CPU_HTW		0x100000000ull /* CPU support Hardware Page Table Walker */
-#define MIPS_CPU_RIXIEX		0x200000000ull /* CPU has unique exception codes for {Read, Execute}-Inhibit exceptions */
-#define MIPS_CPU_MAAR		0x400000000ull /* MAAR(I) registers are present */
-#define MIPS_CPU_FRE		0x800000000ull /* FRE & UFE bits implemented */
-#define MIPS_CPU_RW_LLB		0x1000000000ull /* LLADDR/LLB writes are allowed */
-#define MIPS_CPU_XPA		0x2000000000ull /* CPU supports Extended Physical Addressing */
-#define MIPS_CPU_CDMM		0x4000000000ull	/* CPU has Common Device Memory Map */
-#define MIPS_CPU_BP_GHIST	0x8000000000ull /* R12K+ Branch Prediction Global History */
-#define MIPS_CPU_SP		0x10000000000ull /* Small (1KB) page support */
-#define MIPS_CPU_FTLB		0x20000000000ull /* CPU has Fixed-page-size TLB */
-#define MIPS_CPU_NAN_LEGACY	0x40000000000ull /* Legacy NaN implemented */
-#define MIPS_CPU_NAN_2008	0x80000000000ull /* 2008 NaN implemented */
+#define MIPS_CPU_TLB		MBIT_ULL( 0)	/* CPU has TLB */
+#define MIPS_CPU_4KEX		MBIT_ULL( 1)	/* "R4K" exception model */
+#define MIPS_CPU_3K_CACHE	MBIT_ULL( 2)	/* R3000-style caches */
+#define MIPS_CPU_4K_CACHE	MBIT_ULL( 3)	/* R4000-style caches */
+#define MIPS_CPU_TX39_CACHE	MBIT_ULL( 4)	/* TX3900-style caches */
+#define MIPS_CPU_FPU		MBIT_ULL( 5)	/* CPU has FPU */
+#define MIPS_CPU_32FPR		MBIT_ULL( 6)	/* 32 dbl. prec. FP registers */
+#define MIPS_CPU_COUNTER	MBIT_ULL( 7)	/* Cycle count/compare */
+#define MIPS_CPU_WATCH		MBIT_ULL( 8)	/* watchpoint registers */
+#define MIPS_CPU_DIVEC		MBIT_ULL( 9)	/* dedicated interrupt vector */
+#define MIPS_CPU_VCE		MBIT_ULL(10)	/* virt. coherence conflict possible */
+#define MIPS_CPU_CACHE_CDEX_P	MBIT_ULL(11)	/* Create_Dirty_Exclusive CACHE op */
+#define MIPS_CPU_CACHE_CDEX_S	MBIT_ULL(12)	/* ... same for seconary cache ... */
+#define MIPS_CPU_MCHECK		MBIT_ULL(13)	/* Machine check exception */
+#define MIPS_CPU_EJTAG		MBIT_ULL(14)	/* EJTAG exception */
+#define MIPS_CPU_NOFPUEX	MBIT_ULL(15)	/* no FPU exception */
+#define MIPS_CPU_LLSC		MBIT_ULL(16)	/* CPU has ll/sc instructions */
+#define MIPS_CPU_INCLUSIVE_CACHES	MBIT_ULL(17)	/* P-cache subset enforced */
+#define MIPS_CPU_PREFETCH	MBIT_ULL(18)	/* CPU has usable prefetch */
+#define MIPS_CPU_VINT		MBIT_ULL(19)	/* CPU supports MIPSR2 vectored interrupts */
+#define MIPS_CPU_VEIC		MBIT_ULL(20)	/* CPU supports MIPSR2 external interrupt controller mode */
+#define MIPS_CPU_ULRI		MBIT_ULL(21)	/* CPU has ULRI feature */
+#define MIPS_CPU_PCI		MBIT_ULL(22)	/* CPU has Perf Ctr Int indicator */
+#define MIPS_CPU_RIXI		MBIT_ULL(23)	/* CPU has TLB Read/eXec Inhibit */
+#define MIPS_CPU_MICROMIPS	MBIT_ULL(24)	/* CPU has microMIPS capability */
+#define MIPS_CPU_TLBINV		MBIT_ULL(25)	/* CPU supports TLBINV/F */
+#define MIPS_CPU_SEGMENTS	MBIT_ULL(26)	/* CPU supports Segmentation Control registers */
+#define MIPS_CPU_EVA		MBIT_ULL(27)	/* CPU supports Enhanced Virtual Addressing */
+#define MIPS_CPU_HTW		MBIT_ULL(28)	/* CPU support Hardware Page Table Walker */
+#define MIPS_CPU_RIXIEX		MBIT_ULL(29)	/* CPU has unique exception codes for {Read, Execute}-Inhibit exceptions */
+#define MIPS_CPU_MAAR		MBIT_ULL(30)	/* MAAR(I) registers are present */
+#define MIPS_CPU_FRE		MBIT_ULL(31)	/* FRE & UFE bits implemented */
+#define MIPS_CPU_RW_LLB		MBIT_ULL(32)	/* LLADDR/LLB writes are allowed */
+#define MIPS_CPU_LPA		MBIT_ULL(33)	/* CPU supports Large Physical Addressing */
+#define MIPS_CPU_CDMM		MBIT_ULL(34)	/* CPU has Common Device Memory Map */
+#define MIPS_CPU_BP_GHIST	MBIT_ULL(35)	/* R12K+ Branch Prediction Global History */
+#define MIPS_CPU_SP		MBIT_ULL(36)	/* Small (1KB) page support */
+#define MIPS_CPU_FTLB		MBIT_ULL(37)	/* CPU has Fixed-page-size TLB */
+#define MIPS_CPU_NAN_LEGACY	MBIT_ULL(38)	/* Legacy NaN implemented */
+#define MIPS_CPU_NAN_2008	MBIT_ULL(39)	/* 2008 NaN implemented */
+#define MIPS_CPU_VP		MBIT_ULL(40)	/* MIPSr6 Virtual Processors (multi-threading) */
+#define MIPS_CPU_LDPTE		MBIT_ULL(41)	/* CPU has ldpte/lddir instructions */
+#define MIPS_CPU_MVH		MBIT_ULL(42)	/* CPU supports MFHC0/MTHC0 */
+#define MIPS_CPU_EBASE_WG	MBIT_ULL(43)	/* CPU has EBase.WG */
+#define MIPS_CPU_BADINSTR	MBIT_ULL(44)	/* CPU has BadInstr register */
+#define MIPS_CPU_BADINSTRP	MBIT_ULL(45)	/* CPU has BadInstrP register */
+#define MIPS_CPU_CTXTC		MBIT_ULL(46)	/* CPU has [X]ConfigContext registers */
+#define MIPS_CPU_PERF		MBIT_ULL(47)	/* CPU has MIPS performance counters */
+#define MIPS_CPU_GUESTCTL0EXT	MBIT_ULL(48)	/* CPU has VZ GuestCtl0Ext register */
+#define MIPS_CPU_GUESTCTL1	MBIT_ULL(49)	/* CPU has VZ GuestCtl1 register */
+#define MIPS_CPU_GUESTCTL2	MBIT_ULL(50)	/* CPU has VZ GuestCtl2 register */
+#define MIPS_CPU_GUESTID	MBIT_ULL(51)	/* CPU uses VZ ASE GuestID feature */
+#define MIPS_CPU_DRG		MBIT_ULL(52)	/* CPU has VZ Direct Root to Guest (DRG) */
 
 /*
  * CPU ASE encodings
@@ -401,5 +427,6 @@ enum cpu_type_enum {
 #define MIPS_ASE_DSP2P		0x00000040 /* Signal Processing ASE Rev 2 */
 #define MIPS_ASE_VZ		0x00000080 /* Virtualization ASE */
 #define MIPS_ASE_MSA		0x00000100 /* MIPS SIMD Architecture */
+#define MIPS_ASE_DSP3		0x00000200 /* Signal Processing ASE Rev 3*/
 
 #endif /* _ASM_CPU_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/cpu-info.h linux-libre-4.7-gnu/arch/mips/include/asm/cpu-info.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/cpu-info.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/cpu-info.h	2016-07-24 15:23:50.000000000 -0400
@@ -28,6 +28,15 @@ struct cache_desc {
 	unsigned char flags;	/* Flags describing cache properties */
 };
 
+struct guest_info {
+	unsigned long		ases;
+	unsigned long		ases_dyn;
+	unsigned long long	options;
+	unsigned long long	options_dyn;
+	u8			conf;
+	u8			kscratch_mask;
+};
+
 /*
  * Flag definitions
  */
@@ -40,6 +49,9 @@ struct cache_desc {
 
 struct cpuinfo_mips {
 	unsigned long		asid_cache;
+#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE
+	unsigned long		asid_mask;
+#endif
 
 	/*
 	 * Capability and feature descriptor structure for MIPS CPU
@@ -60,6 +72,7 @@ struct cpuinfo_mips {
 	int			tlbsizeftlbways;
 	struct cache_desc	icache; /* Primary I-cache */
 	struct cache_desc	dcache; /* Primary D or combined I/D cache */
+	struct cache_desc	vcache; /* Victim cache, between pcache and scache */
 	struct cache_desc	scache; /* Secondary cache */
 	struct cache_desc	tcache; /* Tertiary/split secondary cache */
 	int			srsets; /* Shadow register sets */
@@ -68,7 +81,7 @@ struct cpuinfo_mips {
 #ifdef CONFIG_64BIT
 	int			vmbits; /* Virtual memory size in bits */
 #endif
-#ifdef CONFIG_MIPS_MT_SMP
+#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_CPU_MIPSR6)
 	/*
 	 * There is not necessarily a 1:1 mapping of VPE num to CPU number
 	 * in particular on multi-core systems.
@@ -91,6 +104,11 @@ struct cpuinfo_mips {
 	 * htw_start/htw_stop calls
 	 */
 	unsigned int		htw_seq;
+
+	/* VZ & Guest features */
+	struct guest_info	guest;
+	unsigned int		gtoffset_mask;
+	unsigned int		guestid_mask;
 } __attribute__((aligned(SMP_CACHE_BYTES)));
 
 extern struct cpuinfo_mips cpu_data[];
@@ -125,10 +143,31 @@ struct proc_cpuinfo_notifier_args {
 	unsigned long n;
 };
 
-#ifdef CONFIG_MIPS_MT_SMP
+#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_CPU_MIPSR6)
 # define cpu_vpe_id(cpuinfo)	((cpuinfo)->vpe_id)
 #else
 # define cpu_vpe_id(cpuinfo)	({ (void)cpuinfo; 0; })
 #endif
 
+static inline unsigned long cpu_asid_inc(void)
+{
+	return 1 << CONFIG_MIPS_ASID_SHIFT;
+}
+
+static inline unsigned long cpu_asid_mask(struct cpuinfo_mips *cpuinfo)
+{
+#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE
+	return cpuinfo->asid_mask;
+#endif
+	return ((1 << CONFIG_MIPS_ASID_BITS) - 1) << CONFIG_MIPS_ASID_SHIFT;
+}
+
+static inline void set_cpu_asid_mask(struct cpuinfo_mips *cpuinfo,
+				     unsigned long asid_mask)
+{
+#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE
+	cpuinfo->asid_mask = asid_mask;
+#endif
+}
+
 #endif /* __ASM_CPU_INFO_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/cpu-type.h linux-libre-4.7-gnu/arch/mips/include/asm/cpu-type.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/cpu-type.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/cpu-type.h	2016-07-24 15:23:50.000000000 -0400
@@ -77,8 +77,13 @@ static inline int __pure __get_cpu_type(
 	 */
 #endif
 
+#ifdef CONFIG_SYS_HAS_CPU_MIPS32_R6
+	case CPU_M6250:
+#endif
+
 #ifdef CONFIG_SYS_HAS_CPU_MIPS64_R6
 	case CPU_I6400:
+	case CPU_P6600:
 #endif
 
 #ifdef CONFIG_SYS_HAS_CPU_R3000
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/elf.h linux-libre-4.7-gnu/arch/mips/include/asm/elf.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/elf.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/elf.h	2016-07-24 15:23:50.000000000 -0400
@@ -111,6 +111,11 @@
 #define R_MIPS_CALLHI16		30
 #define R_MIPS_CALLLO16		31
 /*
+ * Introduced for MIPSr6.
+ */
+#define R_MIPS_PC21_S2		60
+#define R_MIPS_PC26_S2		61
+/*
  * This range is reserved for vendor specific relocations.
  */
 #define R_MIPS_LOVENDOR		100
@@ -170,16 +175,14 @@
 #define SHF_MIPS_NAMES		0x02000000
 #define SHF_MIPS_NODUPES	0x01000000
 
-#ifndef ELF_ARCH
-/* ELF register definitions */
-#define ELF_NGREG	45
-#define ELF_NFPREG	33
-
-typedef unsigned long elf_greg_t;
-typedef elf_greg_t elf_gregset_t[ELF_NGREG];
-
-typedef double elf_fpreg_t;
-typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
+#define MIPS_ABI_FP_ANY		0	/* FP ABI doesn't matter */
+#define MIPS_ABI_FP_DOUBLE	1	/* -mdouble-float */
+#define MIPS_ABI_FP_SINGLE	2	/* -msingle-float */
+#define MIPS_ABI_FP_SOFT	3	/* -msoft-float */
+#define MIPS_ABI_FP_OLD_64	4	/* -mips32r2 -mfp64 */
+#define MIPS_ABI_FP_XX		5	/* -mfpxx */
+#define MIPS_ABI_FP_64		6	/* -mips32r2 -mfp64 */
+#define MIPS_ABI_FP_64A		7	/* -mips32r2 -mfp64 -mno-odd-spreg */
 
 struct mips_elf_abiflags_v0 {
 	uint16_t version;	/* Version of flags structure */
@@ -196,16 +199,54 @@ struct mips_elf_abiflags_v0 {
 	uint32_t flags2;
 };
 
-#define MIPS_ABI_FP_ANY		0	/* FP ABI doesn't matter */
-#define MIPS_ABI_FP_DOUBLE	1	/* -mdouble-float */
-#define MIPS_ABI_FP_SINGLE	2	/* -msingle-float */
-#define MIPS_ABI_FP_SOFT	3	/* -msoft-float */
-#define MIPS_ABI_FP_OLD_64	4	/* -mips32r2 -mfp64 */
-#define MIPS_ABI_FP_XX		5	/* -mfpxx */
-#define MIPS_ABI_FP_64		6	/* -mips32r2 -mfp64 */
-#define MIPS_ABI_FP_64A		7	/* -mips32r2 -mfp64 -mno-odd-spreg */
+#ifndef ELF_ARCH
+/* ELF register definitions */
+#define ELF_NGREG	45
+#define ELF_NFPREG	33
+
+typedef unsigned long elf_greg_t;
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+typedef double elf_fpreg_t;
+typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
 
 #ifdef CONFIG_32BIT
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch elfo32_check_arch
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_CLASS	ELFCLASS32
+
+#endif /* CONFIG_32BIT */
+
+#ifdef CONFIG_64BIT
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch elfn64_check_arch
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_CLASS	ELFCLASS64
+
+#endif /* CONFIG_64BIT */
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#ifdef __MIPSEB__
+#define ELF_DATA	ELFDATA2MSB
+#elif defined(__MIPSEL__)
+#define ELF_DATA	ELFDATA2LSB
+#endif
+#define ELF_ARCH	EM_MIPS
+
+#endif /* !defined(ELF_ARCH) */
 
 /*
  * In order to be sure that we don't attempt to execute an O32 binary which
@@ -219,10 +260,15 @@ struct mips_elf_abiflags_v0 {
 # define __MIPS_O32_FP64_MUST_BE_ZERO	EF_MIPS_FP64
 #endif
 
+#define mips_elf_check_machine(x) ((x)->e_machine == EM_MIPS)
+
+#define vmcore_elf32_check_arch mips_elf_check_machine
+#define vmcore_elf64_check_arch mips_elf_check_machine
+
 /*
- * This is used to ensure we don't load something for the wrong architecture.
+ * Return non-zero if HDR identifies an o32 ELF binary.
  */
-#define elf_check_arch(hdr)						\
+#define elfo32_check_arch(hdr)						\
 ({									\
 	int __res = 1;							\
 	struct elfhdr *__h = (hdr);					\
@@ -243,17 +289,9 @@ struct mips_elf_abiflags_v0 {
 })
 
 /*
- * These are used to set parameters in the core dumps.
- */
-#define ELF_CLASS	ELFCLASS32
-
-#endif /* CONFIG_32BIT */
-
-#ifdef CONFIG_64BIT
-/*
- * This is used to ensure we don't load something for the wrong architecture.
+ * Return non-zero if HDR identifies an n64 ELF binary.
  */
-#define elf_check_arch(hdr)						\
+#define elfn64_check_arch(hdr)						\
 ({									\
 	int __res = 1;							\
 	struct elfhdr *__h = (hdr);					\
@@ -267,28 +305,23 @@ struct mips_elf_abiflags_v0 {
 })
 
 /*
- * These are used to set parameters in the core dumps.
- */
-#define ELF_CLASS	ELFCLASS64
-
-#endif /* CONFIG_64BIT */
-
-/*
- * These are used to set parameters in the core dumps.
+ * Return non-zero if HDR identifies an n32 ELF binary.
  */
-#ifdef __MIPSEB__
-#define ELF_DATA	ELFDATA2MSB
-#elif defined(__MIPSEL__)
-#define ELF_DATA	ELFDATA2LSB
-#endif
-#define ELF_ARCH	EM_MIPS
-
-#endif /* !defined(ELF_ARCH) */
-
-#define mips_elf_check_machine(x) ((x)->e_machine == EM_MIPS)
-
-#define vmcore_elf32_check_arch mips_elf_check_machine
-#define vmcore_elf64_check_arch mips_elf_check_machine
+#define elfn32_check_arch(hdr)						\
+({									\
+	int __res = 1;							\
+	struct elfhdr *__h = (hdr);					\
+									\
+	if (!mips_elf_check_machine(__h))				\
+		__res = 0;						\
+	if (__h->e_ident[EI_CLASS] != ELFCLASS32)			\
+		__res = 0;						\
+	if (((__h->e_flags & EF_MIPS_ABI2) == 0) ||			\
+	    ((__h->e_flags & EF_MIPS_ABI) != 0))			\
+		__res = 0;						\
+									\
+	__res;								\
+})
 
 struct mips_abi;
 
@@ -300,17 +333,16 @@ extern struct mips_abi mips_abi_n32;
 
 #define SET_PERSONALITY2(ex, state)					\
 do {									\
-	if (personality(current->personality) != PER_LINUX)		\
-		set_personality(PER_LINUX);				\
-									\
 	clear_thread_flag(TIF_HYBRID_FPREGS);				\
 	set_thread_flag(TIF_32BIT_FPREGS);				\
 									\
-	mips_set_personality_fp(state);					\
-									\
 	current->thread.abi = &mips_abi;				\
 									\
+	mips_set_personality_fp(state);					\
 	mips_set_personality_nan(state);				\
+									\
+	if (personality(current->personality) != PER_LINUX)		\
+		set_personality(PER_LINUX);				\
 } while (0)
 
 #endif /* CONFIG_32BIT */
@@ -321,6 +353,7 @@ do {									\
 #define __SET_PERSONALITY32_N32()					\
 	do {								\
 		set_thread_flag(TIF_32BIT_ADDR);			\
+									\
 		current->thread.abi = &mips_abi_n32;			\
 	} while (0)
 #else
@@ -336,9 +369,9 @@ do {									\
 		clear_thread_flag(TIF_HYBRID_FPREGS);			\
 		set_thread_flag(TIF_32BIT_FPREGS);			\
 									\
-		mips_set_personality_fp(state);				\
-									\
 		current->thread.abi = &mips_abi_32;			\
+									\
+		mips_set_personality_fp(state);				\
 	} while (0)
 #else
 #define __SET_PERSONALITY32_O32(ex, state)				\
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/hazards.h linux-libre-4.7-gnu/arch/mips/include/asm/hazards.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/hazards.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/hazards.h	2016-07-24 15:23:50.000000000 -0400
@@ -22,7 +22,8 @@
 /*
  * TLB hazards
  */
-#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) && !defined(CONFIG_CPU_CAVIUM_OCTEON)
+#if (defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)) && \
+	!defined(CONFIG_CPU_CAVIUM_OCTEON) && !defined(CONFIG_LOONGSON3_ENHANCEMENT)
 
 /*
  * MIPSR2 defines ehb for hazard avoidance
@@ -57,8 +58,8 @@
  * address of a label as argument to inline assembler.	Gas otoh has the
  * annoying difference between la and dla which are only usable for 32-bit
  * rsp. 64-bit code, so can't be used without conditional compilation.
- * The alterantive is switching the assembler to 64-bit code which happens
- * to work right even for 32-bit code ...
+ * The alternative is switching the assembler to 64-bit code which happens
+ * to work right even for 32-bit code...
  */
 #define instruction_hazard()						\
 do {									\
@@ -132,8 +133,8 @@ do {									\
  * address of a label as argument to inline assembler.	Gas otoh has the
  * annoying difference between la and dla which are only usable for 32-bit
  * rsp. 64-bit code, so can't be used without conditional compilation.
- * The alterantive is switching the assembler to 64-bit code which happens
- * to work right even for 32-bit code ...
+ * The alternative is switching the assembler to 64-bit code which happens
+ * to work right even for 32-bit code...
  */
 #define __instruction_hazard()						\
 do {									\
@@ -155,8 +156,8 @@ do {									\
 } while (0)
 
 #elif defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_CPU_CAVIUM_OCTEON) || \
-	defined(CONFIG_CPU_LOONGSON2) || defined(CONFIG_CPU_R10000) || \
-	defined(CONFIG_CPU_R5500) || defined(CONFIG_CPU_XLR)
+	defined(CONFIG_CPU_LOONGSON2) || defined(CONFIG_LOONGSON3_ENHANCEMENT) || \
+	defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_R5500) || defined(CONFIG_CPU_XLR)
 
 /*
  * R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer.
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/highmem.h linux-libre-4.7-gnu/arch/mips/include/asm/highmem.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/highmem.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/highmem.h	2016-07-24 15:23:50.000000000 -0400
@@ -19,8 +19,10 @@
 
 #ifdef __KERNEL__
 
+#include <linux/bug.h>
 #include <linux/interrupt.h>
 #include <linux/uaccess.h>
+#include <asm/cpu-features.h>
 #include <asm/kmap_types.h>
 
 /* undef for production */
@@ -50,7 +52,7 @@ extern void *kmap_atomic(struct page *pa
 extern void __kunmap_atomic(void *kvaddr);
 extern void *kmap_atomic_pfn(unsigned long pfn);
 
-#define flush_cache_kmaps()	flush_cache_all()
+#define flush_cache_kmaps()	BUG_ON(cpu_has_dc_aliases)
 
 extern void kmap_init(void);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/io.h linux-libre-4.7-gnu/arch/mips/include/asm/io.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/io.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/io.h	2016-07-24 15:23:50.000000000 -0400
@@ -304,10 +304,10 @@ static inline void iounmap(const volatil
 #undef __IS_KSEG1
 }
 
-#ifdef CONFIG_CPU_CAVIUM_OCTEON
-#define war_octeon_io_reorder_wmb()		wmb()
+#if defined(CONFIG_CPU_CAVIUM_OCTEON) || defined(CONFIG_LOONGSON3_ENHANCEMENT)
+#define war_io_reorder_wmb()		wmb()
 #else
-#define war_octeon_io_reorder_wmb()		do { } while (0)
+#define war_io_reorder_wmb()		do { } while (0)
 #endif
 
 #define __BUILD_MEMORY_SINGLE(pfx, bwlq, type, irq)			\
@@ -318,7 +318,7 @@ static inline void pfx##write##bwlq(type
 	volatile type *__mem;						\
 	type __val;							\
 									\
-	war_octeon_io_reorder_wmb();					\
+	war_io_reorder_wmb();					\
 									\
 	__mem = (void *)__swizzle_addr_##bwlq((unsigned long)(mem));	\
 									\
@@ -387,7 +387,7 @@ static inline void pfx##out##bwlq##p(typ
 	volatile type *__addr;						\
 	type __val;							\
 									\
-	war_octeon_io_reorder_wmb();					\
+	war_io_reorder_wmb();					\
 									\
 	__addr = (void *)__swizzle_addr_##bwlq(mips_io_port_base + port); \
 									\
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/irqflags.h linux-libre-4.7-gnu/arch/mips/include/asm/irqflags.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/irqflags.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/irqflags.h	2016-07-24 15:23:50.000000000 -0400
@@ -41,7 +41,12 @@ static inline unsigned long arch_local_i
 	"	.set	push						\n"
 	"	.set	reorder						\n"
 	"	.set	noat						\n"
+#if defined(CONFIG_CPU_LOONGSON3)
+	"	mfc0	%[flags], $12					\n"
+	"	di							\n"
+#else
 	"	di	%[flags]					\n"
+#endif
 	"	andi	%[flags], 1					\n"
 	"	" __stringify(__irq_disable_hazard) "			\n"
 	"	.set	pop						\n"
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/irq_regs.h linux-libre-4.7-gnu/arch/mips/include/asm/irq_regs.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/irq_regs.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/irq_regs.h	2016-07-24 15:23:50.000000000 -0400
@@ -18,4 +18,14 @@ static inline struct pt_regs *get_irq_re
 	return current_thread_info()->regs;
 }
 
+static inline struct pt_regs *set_irq_regs(struct pt_regs *new_regs)
+{
+	struct pt_regs *old_regs;
+
+	old_regs = get_irq_regs();
+	current_thread_info()->regs = new_regs;
+
+	return old_regs;
+}
+
 #endif /* __ASM_IRQ_REGS_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/Kbuild linux-libre-4.7-gnu/arch/mips/include/asm/Kbuild
--- linux-libre-4.6-gnu/arch/mips/include/asm/Kbuild	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/Kbuild	2016-07-24 15:23:50.000000000 -0400
@@ -1,5 +1,6 @@
 # MIPS headers
 generic-(CONFIG_GENERIC_CSUM) += checksum.h
+generic-y += clkdev.h
 generic-y += cputime.h
 generic-y += current.h
 generic-y += dma-contiguous.h
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/kvm_host.h linux-libre-4.7-gnu/arch/mips/include/asm/kvm_host.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/kvm_host.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/kvm_host.h	2016-07-24 15:23:50.000000000 -0400
@@ -74,7 +74,7 @@
 #define KVM_GUEST_KUSEG			0x00000000UL
 #define KVM_GUEST_KSEG0			0x40000000UL
 #define KVM_GUEST_KSEG23		0x60000000UL
-#define KVM_GUEST_KSEGX(a)		((_ACAST32_(a)) & 0x60000000)
+#define KVM_GUEST_KSEGX(a)		((_ACAST32_(a)) & 0xe0000000)
 #define KVM_GUEST_CPHYSADDR(a)		((_ACAST32_(a)) & 0x1fffffff)
 
 #define KVM_GUEST_CKSEG0ADDR(a)		(KVM_GUEST_CPHYSADDR(a) | KVM_GUEST_KSEG0)
@@ -122,6 +122,7 @@ struct kvm_vcpu_stat {
 	u32 flush_dcache_exits;
 	u32 halt_successful_poll;
 	u32 halt_attempted_poll;
+	u32 halt_poll_invalid;
 	u32 halt_wakeup;
 };
 
@@ -311,17 +312,18 @@ enum emulation_result {
 #define MIPS3_PG_FRAME		0x3fffffc0
 
 #define VPN2_MASK		0xffffe000
+#define KVM_ENTRYHI_ASID	MIPS_ENTRYHI_ASID
 #define TLB_IS_GLOBAL(x)	(((x).tlb_lo0 & MIPS3_PG_G) &&		\
 				 ((x).tlb_lo1 & MIPS3_PG_G))
 #define TLB_VPN2(x)		((x).tlb_hi & VPN2_MASK)
-#define TLB_ASID(x)		((x).tlb_hi & ASID_MASK)
+#define TLB_ASID(x)		((x).tlb_hi & KVM_ENTRYHI_ASID)
 #define TLB_IS_VALID(x, va)	(((va) & (1 << PAGE_SHIFT))		\
 				 ? ((x).tlb_lo1 & MIPS3_PG_V)		\
 				 : ((x).tlb_lo0 & MIPS3_PG_V))
 #define TLB_HI_VPN2_HIT(x, y)	((TLB_VPN2(x) & ~(x).tlb_mask) ==	\
 				 ((y) & VPN2_MASK & ~(x).tlb_mask))
 #define TLB_HI_ASID_HIT(x, y)	(TLB_IS_GLOBAL(x) ||			\
-				 TLB_ASID(x) == ((y) & ASID_MASK))
+				 TLB_ASID(x) == ((y) & KVM_ENTRYHI_ASID))
 
 struct kvm_mips_tlb {
 	long tlb_mask;
@@ -336,6 +338,7 @@ struct kvm_mips_tlb {
 #define KVM_MIPS_GUEST_TLB_SIZE	64
 struct kvm_vcpu_arch {
 	void *host_ebase, *guest_ebase;
+	int (*vcpu_run)(struct kvm_run *run, struct kvm_vcpu *vcpu);
 	unsigned long host_stack;
 	unsigned long host_gp;
 
@@ -747,7 +750,7 @@ extern enum emulation_result kvm_mips_co
 
 uint32_t kvm_mips_read_count(struct kvm_vcpu *vcpu);
 void kvm_mips_write_count(struct kvm_vcpu *vcpu, uint32_t count);
-void kvm_mips_write_compare(struct kvm_vcpu *vcpu, uint32_t compare);
+void kvm_mips_write_compare(struct kvm_vcpu *vcpu, uint32_t compare, bool ack);
 void kvm_mips_init_count(struct kvm_vcpu *vcpu);
 int kvm_mips_set_count_ctl(struct kvm_vcpu *vcpu, s64 count_ctl);
 int kvm_mips_set_count_resume(struct kvm_vcpu *vcpu, s64 count_resume);
@@ -812,5 +815,6 @@ static inline void kvm_arch_vcpu_uninit(
 static inline void kvm_arch_sched_in(struct kvm_vcpu *vcpu, int cpu) {}
 static inline void kvm_arch_vcpu_blocking(struct kvm_vcpu *vcpu) {}
 static inline void kvm_arch_vcpu_unblocking(struct kvm_vcpu *vcpu) {}
+static inline void kvm_arch_vcpu_block_finish(struct kvm_vcpu *vcpu) {}
 
 #endif /* __MIPS_KVM_HOST_H__ */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/llsc.h linux-libre-4.7-gnu/arch/mips/include/asm/llsc.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/llsc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/mips/include/asm/llsc.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ *
+ * Macros for 32/64-bit neutral inline assembler
+ */
+
+#ifndef __ASM_LLSC_H
+#define __ASM_LLSC_H
+
+#if _MIPS_SZLONG == 32
+#define SZLONG_LOG 5
+#define SZLONG_MASK 31UL
+#define __LL		"ll	"
+#define __SC		"sc	"
+#define __INS		"ins	"
+#define __EXT		"ext	"
+#elif _MIPS_SZLONG == 64
+#define SZLONG_LOG 6
+#define SZLONG_MASK 63UL
+#define __LL		"lld	"
+#define __SC		"scd	"
+#define __INS		"dins	"
+#define __EXT		"dext	"
+#endif
+
+#endif /* __ASM_LLSC_H  */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mach-au1x00/au1xxx_dbdma.h linux-libre-4.7-gnu/arch/mips/include/asm/mach-au1x00/au1xxx_dbdma.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mach-au1x00/au1xxx_dbdma.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mach-au1x00/au1xxx_dbdma.h	2016-07-24 15:23:50.000000000 -0400
@@ -100,7 +100,7 @@ typedef volatile struct au1xxx_ddma_desc
 	u32	dscr_nxtptr;		/* Next descriptor pointer (mostly) */
 	/*
 	 * First 32 bytes are HW specific!!!
-	 * Lets have some SW data following -- make sure it's 32 bytes.
+	 * Let's have some SW data following -- make sure it's 32 bytes.
 	 */
 	u32	sw_status;
 	u32	sw_context;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mach-au1x00/gpio-au1300.h linux-libre-4.7-gnu/arch/mips/include/asm/mach-au1x00/gpio-au1300.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mach-au1x00/gpio-au1300.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mach-au1x00/gpio-au1300.h	2016-07-24 15:23:50.000000000 -0400
@@ -140,7 +140,7 @@ static inline int au1300_gpio_getinitlvl
 * Cases 1 and 3 are intended for boards which want to provide their own
 * GPIO namespace and -operations (i.e. for example you have 8 GPIOs
 * which are in part provided by spare Au1300 GPIO pins and in part by
-* an external FPGA but you still want them to be accssible in linux
+* an external FPGA but you still want them to be accessible in linux
 * as gpio0-7. The board can of course use the alchemy_gpioX_* functions
 * as required).
 */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h linux-libre-4.7-gnu/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_enet.h	2016-07-24 15:23:50.000000000 -0400
@@ -22,7 +22,7 @@ struct bcm63xx_enet_platform_data {
 	int has_phy_interrupt;
 	int phy_interrupt;
 
-	/* if has_phy, use autonegociated pause parameters or force
+	/* if has_phy, use autonegotiated pause parameters or force
 	 * them */
 	int pause_auto;
 	int pause_rx;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mach-bmips/cpu-feature-overrides.h linux-libre-4.7-gnu/arch/mips/include/asm/mach-bmips/cpu-feature-overrides.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mach-bmips/cpu-feature-overrides.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mach-bmips/cpu-feature-overrides.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,14 @@
+#ifndef __ASM_MACH_BMIPS_CPU_FEATURE_OVERRIDES_H
+#define __ASM_MACH_BMIPS_CPU_FEATURE_OVERRIDES_H
+
+/* Invariants across all BMIPS processors */
+#define cpu_has_vtag_icache		0
+#define cpu_icache_snoops_remote_store	1
+
+/* Processor ISA compatibility is MIPS32R1 */
+#define cpu_has_mips32r1		1
+#define cpu_has_mips32r2		0
+#define cpu_has_mips64r1		0
+#define cpu_has_mips64r2		0
+
+#endif /* __ASM_MACH_BMIPS_CPU_FEATURE_OVERRIDES_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mach-bmips/ioremap.h linux-libre-4.7-gnu/arch/mips/include/asm/mach-bmips/ioremap.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mach-bmips/ioremap.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mach-bmips/ioremap.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,33 @@
+#ifndef __ASM_MACH_BMIPS_IOREMAP_H
+#define __ASM_MACH_BMIPS_IOREMAP_H
+
+#include <linux/types.h>
+
+static inline phys_addr_t fixup_bigphys_addr(phys_addr_t phys_addr, phys_addr_t size)
+{
+	return phys_addr;
+}
+
+static inline int is_bmips_internal_registers(phys_addr_t offset)
+{
+	if (offset >= 0xfff80000)
+		return 1;
+
+	return 0;
+}
+
+static inline void __iomem *plat_ioremap(phys_addr_t offset, unsigned long size,
+					 unsigned long flags)
+{
+	if (is_bmips_internal_registers(offset))
+		return (void __iomem *)offset;
+
+	return NULL;
+}
+
+static inline int plat_iounmap(const volatile void __iomem *addr)
+{
+	return is_bmips_internal_registers((unsigned long)addr);
+}
+
+#endif /* __ASM_MACH_BMIPS_IOREMAP_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mach-ip27/dma-coherence.h linux-libre-4.7-gnu/arch/mips/include/asm/mach-ip27/dma-coherence.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mach-ip27/dma-coherence.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mach-ip27/dma-coherence.h	2016-07-24 15:23:50.000000000 -0400
@@ -64,7 +64,7 @@ static inline void plat_post_dma_flush(s
 
 static inline int plat_device_is_coherent(struct device *dev)
 {
-	return 1;		/* IP27 non-cohernet mode is unsupported */
+	return 1;		/* IP27 non-coherent mode is unsupported */
 }
 
 #endif /* __ASM_MACH_IP27_DMA_COHERENCE_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mach-ip32/dma-coherence.h linux-libre-4.7-gnu/arch/mips/include/asm/mach-ip32/dma-coherence.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mach-ip32/dma-coherence.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mach-ip32/dma-coherence.h	2016-07-24 15:23:50.000000000 -0400
@@ -86,7 +86,7 @@ static inline void plat_post_dma_flush(s
 
 static inline int plat_device_is_coherent(struct device *dev)
 {
-	return 0;		/* IP32 is non-cohernet */
+	return 0;		/* IP32 is non-coherent */
 }
 
 #endif /* __ASM_MACH_IP32_DMA_COHERENCE_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mach-jz4740/jz4740_nand.h linux-libre-4.7-gnu/arch/mips/include/asm/mach-jz4740/jz4740_nand.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mach-jz4740/jz4740_nand.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mach-jz4740/jz4740_nand.h	2016-07-24 15:23:50.000000000 -0400
@@ -27,7 +27,7 @@ struct jz_nand_platform_data {
 
 	unsigned char banks[JZ_NAND_NUM_BANKS];
 
-	void (*ident_callback)(struct platform_device *, struct nand_chip *,
+	void (*ident_callback)(struct platform_device *, struct mtd_info *,
 				struct mtd_partition **, int *num_partitions);
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mach-jz4740/platform.h linux-libre-4.7-gnu/arch/mips/include/asm/mach-jz4740/platform.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mach-jz4740/platform.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mach-jz4740/platform.h	2016-07-24 15:23:50.000000000 -0400
@@ -19,7 +19,6 @@
 
 #include <linux/platform_device.h>
 
-extern struct platform_device jz4740_usb_ohci_device;
 extern struct platform_device jz4740_udc_device;
 extern struct platform_device jz4740_udc_xceiv_device;
 extern struct platform_device jz4740_mmc_device;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h linux-libre-4.7-gnu/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h	2016-07-24 15:23:50.000000000 -0400
@@ -3,7 +3,7 @@
  * under the terms of the GNU General Public License version 2 as published
  * by the Free Software Foundation.
  *
- * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2010 John Crispin <john@phrozen.org>
  */
 
 #ifndef _LTQ_FALCON_H__
@@ -22,7 +22,7 @@
 
 /*
  * during early_printk no ioremap possible at this early stage
- * lets use KSEG1 instead
+ * let's use KSEG1 instead
  */
 #define LTQ_ASC0_BASE_ADDR	0x1E100C00
 #define LTQ_EARLY_ASC		KSEG1ADDR(LTQ_ASC0_BASE_ADDR)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mach-lantiq/lantiq.h linux-libre-4.7-gnu/arch/mips/include/asm/mach-lantiq/lantiq.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mach-lantiq/lantiq.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mach-lantiq/lantiq.h	2016-07-24 15:23:50.000000000 -0400
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2010 John Crispin <john@phrozen.org>
  */
 #ifndef _LANTIQ_H__
 #define _LANTIQ_H__
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mach-lantiq/lantiq_platform.h linux-libre-4.7-gnu/arch/mips/include/asm/mach-lantiq/lantiq_platform.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mach-lantiq/lantiq_platform.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mach-lantiq/lantiq_platform.h	2016-07-24 15:23:50.000000000 -0400
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2010 John Crispin <john@phrozen.org>
  */
 
 #ifndef _LANTIQ_PLATFORM_H__
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mach-lantiq/xway/irq.h linux-libre-4.7-gnu/arch/mips/include/asm/mach-lantiq/xway/irq.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mach-lantiq/xway/irq.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mach-lantiq/xway/irq.h	2016-07-24 15:23:50.000000000 -0400
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2010 John Crispin <john@phrozen.org>
  */
 
 #ifndef __LANTIQ_IRQ_H
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h linux-libre-4.7-gnu/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h	2016-07-24 15:23:50.000000000 -0400
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2010 John Crispin <john@phrozen.org>
  */
 
 #ifndef _LANTIQ_XWAY_IRQ_H__
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h linux-libre-4.7-gnu/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h	2016-07-24 15:23:50.000000000 -0400
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2010 John Crispin <john@phrozen.org>
  */
 
 #ifndef _LTQ_XWAY_H__
@@ -75,7 +75,7 @@ extern __iomem void *ltq_cgu_membase;
 
 /*
  * during early_printk no ioremap is possible
- * lets use KSEG1 instead
+ * let's use KSEG1 instead
  */
 #define LTQ_ASC1_BASE_ADDR	0x1E100C00
 #define LTQ_EARLY_ASC		KSEG1ADDR(LTQ_ASC1_BASE_ADDR)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mach-lantiq/xway/xway_dma.h linux-libre-4.7-gnu/arch/mips/include/asm/mach-lantiq/xway/xway_dma.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mach-lantiq/xway/xway_dma.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mach-lantiq/xway/xway_dma.h	2016-07-24 15:23:50.000000000 -0400
@@ -12,7 +12,7 @@
  *   along with this program; if not, write to the Free Software
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  *
- *   Copyright (C) 2011 John Crispin <blogic@openwrt.org>
+ *   Copyright (C) 2011 John Crispin <john@phrozen.org>
  */
 
 #ifndef LTQ_DMA_H__
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mach-loongson32/cpufreq.h linux-libre-4.7-gnu/arch/mips/include/asm/mach-loongson32/cpufreq.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mach-loongson32/cpufreq.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mach-loongson32/cpufreq.h	2016-07-24 15:23:50.000000000 -0400
@@ -9,7 +9,6 @@
  * option) any later version.
  */
 
-
 #ifndef __ASM_MACH_LOONGSON32_CPUFREQ_H
 #define __ASM_MACH_LOONGSON32_CPUFREQ_H
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mach-loongson32/dma.h linux-libre-4.7-gnu/arch/mips/include/asm/mach-loongson32/dma.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mach-loongson32/dma.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mach-loongson32/dma.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2015 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * Loongson 1 NAND platform support.
+ *
+ * This program is free software; you can redistribute	it and/or modify it
+ * under  the terms of	the GNU General	 Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __ASM_MACH_LOONGSON32_DMA_H
+#define __ASM_MACH_LOONGSON32_DMA_H
+
+#define LS1X_DMA_CHANNEL0	0
+#define LS1X_DMA_CHANNEL1	1
+#define LS1X_DMA_CHANNEL2	2
+
+struct plat_ls1x_dma {
+	int nr_channels;
+};
+
+extern struct plat_ls1x_dma ls1b_dma_pdata;
+
+#endif /* __ASM_MACH_LOONGSON32_DMA_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mach-loongson32/irq.h linux-libre-4.7-gnu/arch/mips/include/asm/mach-loongson32/irq.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mach-loongson32/irq.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mach-loongson32/irq.h	2016-07-24 15:23:50.000000000 -0400
@@ -9,7 +9,6 @@
  * option) any later version.
  */
 
-
 #ifndef __ASM_MACH_LOONGSON32_IRQ_H
 #define __ASM_MACH_LOONGSON32_IRQ_H
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mach-loongson32/loongson1.h linux-libre-4.7-gnu/arch/mips/include/asm/mach-loongson32/loongson1.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mach-loongson32/loongson1.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mach-loongson32/loongson1.h	2016-07-24 15:23:50.000000000 -0400
@@ -9,7 +9,6 @@
  * option) any later version.
  */
 
-
 #ifndef __ASM_MACH_LOONGSON32_LOONGSON1_H
 #define __ASM_MACH_LOONGSON32_LOONGSON1_H
 
@@ -18,6 +17,9 @@
 /* Loongson 1 Register Bases */
 #define LS1X_MUX_BASE			0x1fd00420
 #define LS1X_INTC_BASE			0x1fd01040
+#define LS1X_GPIO0_BASE			0x1fd010c0
+#define LS1X_GPIO1_BASE			0x1fd010c4
+#define LS1X_DMAC_BASE			0x1fd01160
 #define LS1X_EHCI_BASE			0x1fe00000
 #define LS1X_OHCI_BASE			0x1fe08000
 #define LS1X_GMAC0_BASE			0x1fe10000
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mach-loongson32/nand.h linux-libre-4.7-gnu/arch/mips/include/asm/mach-loongson32/nand.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mach-loongson32/nand.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mach-loongson32/nand.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * Loongson 1 NAND platform support.
+ *
+ * This program is free software; you can redistribute	it and/or modify it
+ * under  the terms of	the GNU General	 Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __ASM_MACH_LOONGSON32_NAND_H
+#define __ASM_MACH_LOONGSON32_NAND_H
+
+#include <linux/dmaengine.h>
+#include <linux/mtd/partitions.h>
+
+struct plat_ls1x_nand {
+	struct mtd_partition *parts;
+	unsigned int nr_parts;
+
+	int hold_cycle;
+	int wait_cycle;
+};
+
+extern struct plat_ls1x_nand ls1b_nand_pdata;
+
+bool ls1x_dma_filter_fn(struct dma_chan *chan, void *param);
+
+#endif /* __ASM_MACH_LOONGSON32_NAND_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mach-loongson32/platform.h linux-libre-4.7-gnu/arch/mips/include/asm/mach-loongson32/platform.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mach-loongson32/platform.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mach-loongson32/platform.h	2016-07-24 15:23:50.000000000 -0400
@@ -7,20 +7,28 @@
  * option) any later version.
  */
 
-
 #ifndef __ASM_MACH_LOONGSON32_PLATFORM_H
 #define __ASM_MACH_LOONGSON32_PLATFORM_H
 
 #include <linux/platform_device.h>
 
+#include <dma.h>
+#include <nand.h>
+
 extern struct platform_device ls1x_uart_pdev;
 extern struct platform_device ls1x_cpufreq_pdev;
+extern struct platform_device ls1x_dma_pdev;
 extern struct platform_device ls1x_eth0_pdev;
 extern struct platform_device ls1x_eth1_pdev;
 extern struct platform_device ls1x_ehci_pdev;
+extern struct platform_device ls1x_gpio0_pdev;
+extern struct platform_device ls1x_gpio1_pdev;
+extern struct platform_device ls1x_nand_pdev;
 extern struct platform_device ls1x_rtc_pdev;
 
-extern void __init ls1x_clk_init(void);
-extern void __init ls1x_serial_setup(struct platform_device *pdev);
+void __init ls1x_clk_init(void);
+void __init ls1x_dma_set_platdata(struct plat_ls1x_dma *pdata);
+void __init ls1x_nand_set_platdata(struct plat_ls1x_nand *pdata);
+void __init ls1x_serial_set_uartclk(struct platform_device *pdev);
 
 #endif /* __ASM_MACH_LOONGSON32_PLATFORM_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mach-loongson32/regs-clk.h linux-libre-4.7-gnu/arch/mips/include/asm/mach-loongson32/regs-clk.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mach-loongson32/regs-clk.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mach-loongson32/regs-clk.h	2016-07-24 15:23:50.000000000 -0400
@@ -19,18 +19,18 @@
 #define LS1X_CLK_PLL_DIV		LS1X_CLK_REG(0x4)
 
 /* Clock PLL Divisor Register Bits */
-#define DIV_DC_EN			(0x1 << 31)
-#define DIV_DC_RST			(0x1 << 30)
-#define DIV_CPU_EN			(0x1 << 25)
-#define DIV_CPU_RST			(0x1 << 24)
-#define DIV_DDR_EN			(0x1 << 19)
-#define DIV_DDR_RST			(0x1 << 18)
-#define RST_DC_EN			(0x1 << 5)
-#define RST_DC				(0x1 << 4)
-#define RST_DDR_EN			(0x1 << 3)
-#define RST_DDR				(0x1 << 2)
-#define RST_CPU_EN			(0x1 << 1)
-#define RST_CPU				0x1
+#define DIV_DC_EN			BIT(31)
+#define DIV_DC_RST			BIT(30)
+#define DIV_CPU_EN			BIT(25)
+#define DIV_CPU_RST			BIT(24)
+#define DIV_DDR_EN			BIT(19)
+#define DIV_DDR_RST			BIT(18)
+#define RST_DC_EN			BIT(5)
+#define RST_DC				BIT(4)
+#define RST_DDR_EN			BIT(3)
+#define RST_DDR				BIT(2)
+#define RST_CPU_EN			BIT(1)
+#define RST_CPU				BIT(0)
 
 #define DIV_DC_SHIFT			26
 #define DIV_CPU_SHIFT			20
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mach-loongson32/regs-mux.h linux-libre-4.7-gnu/arch/mips/include/asm/mach-loongson32/regs-mux.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mach-loongson32/regs-mux.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mach-loongson32/regs-mux.h	2016-07-24 15:23:50.000000000 -0400
@@ -19,49 +19,49 @@
 #define LS1X_MUX_CTRL1			LS1X_MUX_REG(0x4)
 
 /* MUX CTRL0 Register Bits */
-#define UART0_USE_PWM23			(0x1 << 28)
-#define UART0_USE_PWM01			(0x1 << 27)
-#define UART1_USE_LCD0_5_6_11		(0x1 << 26)
-#define I2C2_USE_CAN1			(0x1 << 25)
-#define I2C1_USE_CAN0			(0x1 << 24)
-#define NAND3_USE_UART5			(0x1 << 23)
-#define NAND3_USE_UART4			(0x1 << 22)
-#define NAND3_USE_UART1_DAT		(0x1 << 21)
-#define NAND3_USE_UART1_CTS		(0x1 << 20)
-#define NAND3_USE_PWM23			(0x1 << 19)
-#define NAND3_USE_PWM01			(0x1 << 18)
-#define NAND2_USE_UART5			(0x1 << 17)
-#define NAND2_USE_UART4			(0x1 << 16)
-#define NAND2_USE_UART1_DAT		(0x1 << 15)
-#define NAND2_USE_UART1_CTS		(0x1 << 14)
-#define NAND2_USE_PWM23			(0x1 << 13)
-#define NAND2_USE_PWM01			(0x1 << 12)
-#define NAND1_USE_UART5			(0x1 << 11)
-#define NAND1_USE_UART4			(0x1 << 10)
-#define NAND1_USE_UART1_DAT		(0x1 << 9)
-#define NAND1_USE_UART1_CTS		(0x1 << 8)
-#define NAND1_USE_PWM23			(0x1 << 7)
-#define NAND1_USE_PWM01			(0x1 << 6)
-#define GMAC1_USE_UART1			(0x1 << 4)
-#define GMAC1_USE_UART0			(0x1 << 3)
-#define LCD_USE_UART0_DAT		(0x1 << 2)
-#define LCD_USE_UART15			(0x1 << 1)
-#define LCD_USE_UART0			0x1
+#define UART0_USE_PWM23			BIT(28)
+#define UART0_USE_PWM01			BIT(27)
+#define UART1_USE_LCD0_5_6_11		BIT(26)
+#define I2C2_USE_CAN1			BIT(25)
+#define I2C1_USE_CAN0			BIT(24)
+#define NAND3_USE_UART5			BIT(23)
+#define NAND3_USE_UART4			BIT(22)
+#define NAND3_USE_UART1_DAT		BIT(21)
+#define NAND3_USE_UART1_CTS		BIT(20)
+#define NAND3_USE_PWM23			BIT(19)
+#define NAND3_USE_PWM01			BIT(18)
+#define NAND2_USE_UART5			BIT(17)
+#define NAND2_USE_UART4			BIT(16)
+#define NAND2_USE_UART1_DAT		BIT(15)
+#define NAND2_USE_UART1_CTS		BIT(14)
+#define NAND2_USE_PWM23			BIT(13)
+#define NAND2_USE_PWM01			BIT(12)
+#define NAND1_USE_UART5			BIT(11)
+#define NAND1_USE_UART4			BIT(10)
+#define NAND1_USE_UART1_DAT		BIT(9)
+#define NAND1_USE_UART1_CTS		BIT(8)
+#define NAND1_USE_PWM23			BIT(7)
+#define NAND1_USE_PWM01			BIT(6)
+#define GMAC1_USE_UART1			BIT(4)
+#define GMAC1_USE_UART0			BIT(3)
+#define LCD_USE_UART0_DAT		BIT(2)
+#define LCD_USE_UART15			BIT(1)
+#define LCD_USE_UART0			BIT(0)
 
 /* MUX CTRL1 Register Bits */
-#define USB_RESET			(0x1 << 31)
-#define SPI1_CS_USE_PWM01		(0x1 << 24)
-#define SPI1_USE_CAN			(0x1 << 23)
-#define DISABLE_DDR_CONFSPACE		(0x1 << 20)
-#define DDR32TO16EN			(0x1 << 16)
-#define GMAC1_SHUT			(0x1 << 13)
-#define GMAC0_SHUT			(0x1 << 12)
-#define USB_SHUT			(0x1 << 11)
-#define UART1_3_USE_CAN1		(0x1 << 5)
-#define UART1_2_USE_CAN0		(0x1 << 4)
-#define GMAC1_USE_TXCLK			(0x1 << 3)
-#define GMAC0_USE_TXCLK			(0x1 << 2)
-#define GMAC1_USE_PWM23			(0x1 << 1)
-#define GMAC0_USE_PWM01			0x1
+#define USB_RESET			BIT(31)
+#define SPI1_CS_USE_PWM01		BIT(24)
+#define SPI1_USE_CAN			BIT(23)
+#define DISABLE_DDR_CONFSPACE		BIT(20)
+#define DDR32TO16EN			BIT(16)
+#define GMAC1_SHUT			BIT(13)
+#define GMAC0_SHUT			BIT(12)
+#define USB_SHUT			BIT(11)
+#define UART1_3_USE_CAN1		BIT(5)
+#define UART1_2_USE_CAN0		BIT(4)
+#define GMAC1_USE_TXCLK			BIT(3)
+#define GMAC0_USE_TXCLK			BIT(2)
+#define GMAC1_USE_PWM23			BIT(1)
+#define GMAC0_USE_PWM01			BIT(0)
 
 #endif /* __ASM_MACH_LOONGSON32_REGS_MUX_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mach-loongson32/regs-pwm.h linux-libre-4.7-gnu/arch/mips/include/asm/mach-loongson32/regs-pwm.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mach-loongson32/regs-pwm.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mach-loongson32/regs-pwm.h	2016-07-24 15:23:50.000000000 -0400
@@ -19,11 +19,11 @@
 #define PWM_CTRL		0xc
 
 /* PWM Control Register Bits */
-#define CNT_RST			(0x1 << 7)
-#define INT_SR			(0x1 << 6)
-#define INT_EN			(0x1 << 5)
-#define PWM_SINGLE		(0x1 << 4)
-#define PWM_OE			(0x1 << 3)
-#define CNT_EN			0x1
+#define CNT_RST			BIT(7)
+#define INT_SR			BIT(6)
+#define INT_EN			BIT(5)
+#define PWM_SINGLE		BIT(4)
+#define PWM_OE			BIT(3)
+#define CNT_EN			BIT(0)
 
 #endif /* __ASM_MACH_LOONGSON32_REGS_PWM_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mach-loongson64/cpu-feature-overrides.h linux-libre-4.7-gnu/arch/mips/include/asm/mach-loongson64/cpu-feature-overrides.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mach-loongson64/cpu-feature-overrides.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mach-loongson64/cpu-feature-overrides.h	2016-07-24 15:23:50.000000000 -0400
@@ -16,11 +16,6 @@
 #ifndef __ASM_MACH_LOONGSON64_CPU_FEATURE_OVERRIDES_H
 #define __ASM_MACH_LOONGSON64_CPU_FEATURE_OVERRIDES_H
 
-#define cpu_dcache_line_size()	32
-#define cpu_icache_line_size()	32
-#define cpu_scache_line_size()	32
-
-
 #define cpu_has_32fpr		1
 #define cpu_has_3k_cache	0
 #define cpu_has_4k_cache	1
@@ -31,24 +26,17 @@
 #define cpu_has_counter		1
 #define cpu_has_dc_aliases	(PAGE_SIZE < 0x4000)
 #define cpu_has_divec		0
-#define cpu_has_dsp		0
-#define cpu_has_dsp2		0
 #define cpu_has_ejtag		0
-#define cpu_has_ic_fills_f_dc	0
 #define cpu_has_inclusive_pcaches	1
 #define cpu_has_llsc		1
 #define cpu_has_mcheck		0
 #define cpu_has_mdmx		0
 #define cpu_has_mips16		0
-#define cpu_has_mips32r2	0
 #define cpu_has_mips3d		0
-#define cpu_has_mips64r2	0
 #define cpu_has_mipsmt		0
-#define cpu_has_prefetch	0
 #define cpu_has_smartmips	0
 #define cpu_has_tlb		1
 #define cpu_has_tx39_cache	0
-#define cpu_has_userlocal	0
 #define cpu_has_vce		0
 #define cpu_has_veic		0
 #define cpu_has_vint		0
@@ -56,6 +44,10 @@
 #define cpu_has_watch		1
 #define cpu_has_local_ebase	0
 
-#define cpu_has_wsbh		IS_ENABLED(CONFIG_CPU_LOONGSON3)
+#ifdef CONFIG_CPU_LOONGSON3
+#define cpu_has_wsbh		1
+#define cpu_has_ic_fills_f_dc	1
+#define cpu_hwrena_impl_bits	0xc0000000
+#endif
 
 #endif /* __ASM_MACH_LOONGSON64_CPU_FEATURE_OVERRIDES_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h linux-libre-4.7-gnu/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mach-loongson64/kernel-entry-init.h	2016-07-24 15:23:50.000000000 -0400
@@ -23,8 +23,15 @@
 	or	t0, (0x1 << 7)
 	mtc0	t0, $16, 3
 	/* Set ELPA on LOONGSON3 pagegrain */
-	li	t0, (0x1 << 29)
+	mfc0	t0, $5, 1
+	or	t0, (0x1 << 29)
 	mtc0	t0, $5, 1
+#ifdef CONFIG_LOONGSON3_ENHANCEMENT
+	/* Enable STFill Buffer */
+	mfc0	t0, $16, 6
+	or	t0, 0x100
+	mtc0	t0, $16, 6
+#endif
 	_ehb
 	.set	pop
 #endif
@@ -42,8 +49,15 @@
 	or	t0, (0x1 << 7)
 	mtc0	t0, $16, 3
 	/* Set ELPA on LOONGSON3 pagegrain */
-	li	t0, (0x1 << 29)
+	mfc0	t0, $5, 1
+	or	t0, (0x1 << 29)
 	mtc0	t0, $5, 1
+#ifdef CONFIG_LOONGSON3_ENHANCEMENT
+	/* Enable STFill Buffer */
+	mfc0	t0, $16, 6
+	or	t0, 0x100
+	mtc0	t0, $16, 6
+#endif
 	_ehb
 	.set	pop
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mach-loongson64/loongson_hwmon.h linux-libre-4.7-gnu/arch/mips/include/asm/mach-loongson64/loongson_hwmon.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mach-loongson64/loongson_hwmon.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mach-loongson64/loongson_hwmon.h	2016-07-24 15:23:50.000000000 -0400
@@ -24,7 +24,7 @@ struct temp_range {
 	u8 level;
 };
 
-#define CONSTANT_SPEED_POLICY	0  /* at constent speed */
+#define CONSTANT_SPEED_POLICY	0  /* at constant speed */
 #define STEP_SPEED_POLICY	1  /* use up/down arrays to describe policy */
 #define KERNEL_HELPER_POLICY	2  /* kernel as a helper to fan control */
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mach-malta/kernel-entry-init.h linux-libre-4.7-gnu/arch/mips/include/asm/mach-malta/kernel-entry-init.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mach-malta/kernel-entry-init.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mach-malta/kernel-entry-init.h	2016-07-24 15:23:50.000000000 -0400
@@ -56,7 +56,7 @@
 		(0 << MIPS_SEGCFG_PA_SHIFT) |				\
 		(1 << MIPS_SEGCFG_EU_SHIFT)) << 16)
 	or	t0, t2
-	mtc0	t0, $5, 2
+	mtc0	t0, CP0_SEGCTL0
 
 	/* SegCtl1 */
 	li      t0, ((MIPS_SEGCFG_MUSUK << MIPS_SEGCFG_AM_SHIFT) |	\
@@ -67,7 +67,7 @@
 		(0 << MIPS_SEGCFG_PA_SHIFT) |				\
 		(1 << MIPS_SEGCFG_EU_SHIFT)) << 16)
 	ins	t0, t1, 16, 3
-	mtc0	t0, $5, 3
+	mtc0	t0, CP0_SEGCTL1
 
 	/* SegCtl2 */
 	li	t0, ((MIPS_SEGCFG_MUSUK << MIPS_SEGCFG_AM_SHIFT) |	\
@@ -77,7 +77,7 @@
 		(4 << MIPS_SEGCFG_PA_SHIFT) |				\
 		(1 << MIPS_SEGCFG_EU_SHIFT)) << 16)
 	or	t0, t2
-	mtc0	t0, $5, 4
+	mtc0	t0, CP0_SEGCTL2
 
 	jal	mips_ihb
 	mfc0    t0, $16, 5
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mach-ralink/mt7620.h linux-libre-4.7-gnu/arch/mips/include/asm/mach-ralink/mt7620.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mach-ralink/mt7620.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mach-ralink/mt7620.h	2016-07-24 15:23:50.000000000 -0400
@@ -7,7 +7,7 @@
  *
  * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
  * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
- * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2013 John Crispin <john@phrozen.org>
  */
 
 #ifndef _MT7620_REGS_H_
@@ -72,6 +72,7 @@
 #define SYSCFG0_DRAM_TYPE_SDRAM		0
 #define SYSCFG0_DRAM_TYPE_DDR1		1
 #define SYSCFG0_DRAM_TYPE_DDR2		2
+#define SYSCFG0_DRAM_TYPE_UNKNOWN	3
 
 #define SYSCFG0_DRAM_TYPE_DDR2_MT7628	0
 #define SYSCFG0_DRAM_TYPE_DDR1_MT7628	1
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mach-ralink/mt7621.h linux-libre-4.7-gnu/arch/mips/include/asm/mach-ralink/mt7621.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mach-ralink/mt7621.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mach-ralink/mt7621.h	2016-07-24 15:23:50.000000000 -0400
@@ -3,7 +3,7 @@
  * under the terms of the GNU General Public License version 2 as published
  * by the Free Software Foundation.
  *
- * Copyright (C) 2015 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2015 John Crispin <john@phrozen.org>
  */
 
 #ifndef _MT7621_REGS_H_
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mach-ralink/pinmux.h linux-libre-4.7-gnu/arch/mips/include/asm/mach-ralink/pinmux.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mach-ralink/pinmux.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mach-ralink/pinmux.h	2016-07-24 15:23:50.000000000 -0400
@@ -3,7 +3,7 @@
  *  it under the terms of the GNU General Public License version 2 as
  *  publishhed by the Free Software Foundation.
  *
- *  Copyright (C) 2012 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2012 John Crispin <john@phrozen.org>
  */
 
 #ifndef _RT288X_PINMUX_H__
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mach-ralink/ralink_regs.h linux-libre-4.7-gnu/arch/mips/include/asm/mach-ralink/ralink_regs.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mach-ralink/ralink_regs.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mach-ralink/ralink_regs.h	2016-07-24 15:23:50.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  Ralink SoC register definitions
  *
- *  Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2013 John Crispin <john@phrozen.org>
  *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
  *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
  *
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mach-ralink/rt288x.h linux-libre-4.7-gnu/arch/mips/include/asm/mach-ralink/rt288x.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mach-ralink/rt288x.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mach-ralink/rt288x.h	2016-07-24 15:23:50.000000000 -0400
@@ -7,7 +7,7 @@
  *
  * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
  * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
- * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2013 John Crispin <john@phrozen.org>
  */
 
 #ifndef _RT288X_REGS_H_
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mach-ralink/rt305x.h linux-libre-4.7-gnu/arch/mips/include/asm/mach-ralink/rt305x.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mach-ralink/rt305x.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mach-ralink/rt305x.h	2016-07-24 15:23:50.000000000 -0400
@@ -7,7 +7,7 @@
  *
  * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
  * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
- * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2013 John Crispin <john@phrozen.org>
  */
 
 #ifndef _RT305X_REGS_H_
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mips-cm.h linux-libre-4.7-gnu/arch/mips/include/asm/mips-cm.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mips-cm.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mips-cm.h	2016-07-24 15:23:50.000000000 -0400
@@ -208,6 +208,7 @@ BUILD_CM_RW(l2_config,		MIPS_CM_GCB_OFS
 BUILD_CM_RW(sys_config2,	MIPS_CM_GCB_OFS + 0x150)
 BUILD_CM_RW(l2_pft_control,	MIPS_CM_GCB_OFS + 0x300)
 BUILD_CM_RW(l2_pft_control_b,	MIPS_CM_GCB_OFS + 0x308)
+BUILD_CM_RW(bev_base,		MIPS_CM_GCB_OFS + 0x680)
 
 /* Core Local & Core Other register accessor functions */
 BUILD_CM_Cx_RW(reset_release,	0x00)
@@ -290,8 +291,8 @@ BUILD_CM_Cx_R_(tcid_8_priority,	0x80)
 #define CM_GCR_GIC_BASE_GICEN_MSK		(_ULCAST_(0x1) << 0)
 
 /* GCR_CPC_BASE register fields */
-#define CM_GCR_CPC_BASE_CPCBASE_SHF		17
-#define CM_GCR_CPC_BASE_CPCBASE_MSK		(_ULCAST_(0x7fff) << 17)
+#define CM_GCR_CPC_BASE_CPCBASE_SHF		15
+#define CM_GCR_CPC_BASE_CPCBASE_MSK		(_ULCAST_(0x1ffff) << 15)
 #define CM_GCR_CPC_BASE_CPCEN_SHF		0
 #define CM_GCR_CPC_BASE_CPCEN_MSK		(_ULCAST_(0x1) << 0)
 
@@ -461,7 +462,10 @@ static inline unsigned int mips_cm_max_v
 	if (mips_cm_revision() >= CM_REV_CM3)
 		return read_gcr_sys_config2() & CM_GCR_SYS_CONFIG2_MAXVPW_MSK;
 
-	return smp_num_siblings;
+	if (config_enabled(CONFIG_SMP))
+		return smp_num_siblings;
+
+	return 1;
 }
 
 /**
@@ -505,7 +509,7 @@ extern void mips_cm_unlock_other(void);
 
 #else /* !CONFIG_MIPS_CM */
 
-static inline void mips_cm_lock_other(unsigned int core) { }
+static inline void mips_cm_lock_other(unsigned int core, unsigned int vp) { }
 static inline void mips_cm_unlock_other(void) { }
 
 #endif /* !CONFIG_MIPS_CM */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mips-cpc.h linux-libre-4.7-gnu/arch/mips/include/asm/mips-cpc.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mips-cpc.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mips-cpc.h	2016-07-24 15:23:50.000000000 -0400
@@ -106,6 +106,9 @@ BUILD_CPC_R_(revision,		MIPS_CPC_GCB_OFS
 BUILD_CPC_Cx_RW(cmd,		0x00)
 BUILD_CPC_Cx_RW(stat_conf,	0x08)
 BUILD_CPC_Cx_RW(other,		0x10)
+BUILD_CPC_Cx_RW(vp_stop,	0x20)
+BUILD_CPC_Cx_RW(vp_run,		0x28)
+BUILD_CPC_Cx_RW(vp_running,	0x30)
 
 /* CPC_Cx_CMD register fields */
 #define CPC_Cx_CMD_SHF				0
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mips_mt.h linux-libre-4.7-gnu/arch/mips/include/asm/mips_mt.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mips_mt.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mips_mt.h	2016-07-24 15:23:50.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Definitions and decalrations for MIPS MT support that are common between
+ * Definitions and declarations for MIPS MT support that are common between
  * the VSMP, and AP/SP kernel models.
  */
 #ifndef __ASM_MIPS_MT_H
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mipsregs.h linux-libre-4.7-gnu/arch/mips/include/asm/mipsregs.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mipsregs.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mipsregs.h	2016-07-24 15:23:50.000000000 -0400
@@ -48,6 +48,9 @@
 #define CP0_CONF $3
 #define CP0_CONTEXT $4
 #define CP0_PAGEMASK $5
+#define CP0_SEGCTL0 $5, 2
+#define CP0_SEGCTL1 $5, 3
+#define CP0_SEGCTL2 $5, 4
 #define CP0_WIRED $6
 #define CP0_INFO $7
 #define CP0_HWRENA $7, 0
@@ -55,8 +58,14 @@
 #define CP0_BADINSTR $8, 1
 #define CP0_COUNT $9
 #define CP0_ENTRYHI $10
+#define CP0_GUESTCTL1 $10, 4
+#define CP0_GUESTCTL2 $10, 5
+#define CP0_GUESTCTL3 $10, 6
 #define CP0_COMPARE $11
+#define CP0_GUESTCTL0EXT $11, 4
 #define CP0_STATUS $12
+#define CP0_GUESTCTL0 $12, 6
+#define CP0_GTOFFSET $12, 7
 #define CP0_CAUSE $13
 #define CP0_EPC $14
 #define CP0_PRID $15
@@ -229,6 +238,8 @@
 
 /* MIPS32/64 EntryHI bit definitions */
 #define MIPS_ENTRYHI_EHINV	(_ULCAST_(1) << 10)
+#define MIPS_ENTRYHI_ASIDX	(_ULCAST_(0x3) << 8)
+#define MIPS_ENTRYHI_ASID	(_ULCAST_(0xff) << 0)
 
 /*
  * R4x00 interrupt enable / cause bits
@@ -390,6 +401,8 @@
 #define	 CAUSEF_IP7		(_ULCAST_(1)   << 15)
 #define CAUSEB_FDCI		21
 #define CAUSEF_FDCI		(_ULCAST_(1)   << 21)
+#define CAUSEB_WP		22
+#define CAUSEF_WP		(_ULCAST_(1)   << 22)
 #define CAUSEB_IV		23
 #define CAUSEF_IV		(_ULCAST_(1)   << 23)
 #define CAUSEB_PCI		26
@@ -611,7 +624,8 @@
 #define MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT (_ULCAST_(1) << 14)
 #define MIPS_CONF4_MMUEXTDEF_FTLBSIZEEXT	(_ULCAST_(2) << 14)
 #define MIPS_CONF4_MMUEXTDEF_VTLBSIZEEXT	(_ULCAST_(3) << 14)
-#define MIPS_CONF4_KSCREXIST	(_ULCAST_(255) << 16)
+#define MIPS_CONF4_KSCREXIST_SHIFT	(16)
+#define MIPS_CONF4_KSCREXIST	(_ULCAST_(255) << MIPS_CONF4_KSCREXIST_SHIFT)
 #define MIPS_CONF4_VTLBSIZEEXT_SHIFT	(24)
 #define MIPS_CONF4_VTLBSIZEEXT	(_ULCAST_(15) << MIPS_CONF4_VTLBSIZEEXT_SHIFT)
 #define MIPS_CONF4_AE		(_ULCAST_(1) << 28)
@@ -623,6 +637,7 @@
 #define MIPS_CONF5_MRP		(_ULCAST_(1) << 3)
 #define MIPS_CONF5_LLB		(_ULCAST_(1) << 4)
 #define MIPS_CONF5_MVH		(_ULCAST_(1) << 5)
+#define MIPS_CONF5_VP		(_ULCAST_(1) << 7)
 #define MIPS_CONF5_FRE		(_ULCAST_(1) << 8)
 #define MIPS_CONF5_UFE		(_ULCAST_(1) << 9)
 #define MIPS_CONF5_MSAEN	(_ULCAST_(1) << 27)
@@ -633,6 +648,8 @@
 #define MIPS_CONF6_SYND		(_ULCAST_(1) << 13)
 /* proAptiv FTLB on/off bit */
 #define MIPS_CONF6_FTLBEN	(_ULCAST_(1) << 15)
+/* Loongson-3 FTLB on/off bit */
+#define MIPS_CONF6_FTLBDIS	(_ULCAST_(1) << 22)
 /* FTLB probability bits */
 #define MIPS_CONF6_FTLBP_SHIFT	(16)
 
@@ -645,12 +662,38 @@
 /* FTLB probability bits for R6 */
 #define MIPS_CONF7_FTLBP_SHIFT	(18)
 
+/* WatchLo* register definitions */
+#define MIPS_WATCHLO_IRW	(_ULCAST_(0x7) << 0)
+
+/* WatchHi* register definitions */
+#define MIPS_WATCHHI_M		(_ULCAST_(1) << 31)
+#define MIPS_WATCHHI_G		(_ULCAST_(1) << 30)
+#define MIPS_WATCHHI_WM		(_ULCAST_(0x3) << 28)
+#define MIPS_WATCHHI_WM_R_RVA	(_ULCAST_(0) << 28)
+#define MIPS_WATCHHI_WM_R_GPA	(_ULCAST_(1) << 28)
+#define MIPS_WATCHHI_WM_G_GVA	(_ULCAST_(2) << 28)
+#define MIPS_WATCHHI_EAS	(_ULCAST_(0x3) << 24)
+#define MIPS_WATCHHI_ASID	(_ULCAST_(0xff) << 16)
+#define MIPS_WATCHHI_MASK	(_ULCAST_(0x1ff) << 3)
+#define MIPS_WATCHHI_I		(_ULCAST_(1) << 2)
+#define MIPS_WATCHHI_R		(_ULCAST_(1) << 1)
+#define MIPS_WATCHHI_W		(_ULCAST_(1) << 0)
+#define MIPS_WATCHHI_IRW	(_ULCAST_(0x7) << 0)
+
 /* MAAR bit definitions */
 #define MIPS_MAAR_ADDR		((BIT_ULL(BITS_PER_LONG - 12) - 1) << 12)
 #define MIPS_MAAR_ADDR_SHIFT	12
 #define MIPS_MAAR_S		(_ULCAST_(1) << 1)
 #define MIPS_MAAR_V		(_ULCAST_(1) << 0)
 
+/* EBase bit definitions */
+#define MIPS_EBASE_CPUNUM_SHIFT	0
+#define MIPS_EBASE_CPUNUM	(_ULCAST_(0x3ff) << 0)
+#define MIPS_EBASE_WG_SHIFT	11
+#define MIPS_EBASE_WG		(_ULCAST_(1) << 11)
+#define MIPS_EBASE_BASE_SHIFT	12
+#define MIPS_EBASE_BASE		(~_ULCAST_((1 << MIPS_EBASE_BASE_SHIFT) - 1))
+
 /* CMGCRBase bit definitions */
 #define MIPS_CMGCRB_BASE	11
 #define MIPS_CMGCRF_BASE	(~_ULCAST_((1 << MIPS_CMGCRB_BASE) - 1))
@@ -686,6 +729,8 @@
 #define MIPS_PWFIELD_PTEI_SHIFT	0
 #define MIPS_PWFIELD_PTEI_MASK	0x0000003f
 
+#define MIPS_PWSIZE_PS_SHIFT	30
+#define MIPS_PWSIZE_PS_MASK	0x40000000
 #define MIPS_PWSIZE_GDW_SHIFT	24
 #define MIPS_PWSIZE_GDW_MASK	0x3f000000
 #define MIPS_PWSIZE_UDW_SHIFT	18
@@ -699,6 +744,12 @@
 
 #define MIPS_PWCTL_PWEN_SHIFT	31
 #define MIPS_PWCTL_PWEN_MASK	0x80000000
+#define MIPS_PWCTL_XK_SHIFT	28
+#define MIPS_PWCTL_XK_MASK	0x10000000
+#define MIPS_PWCTL_XS_SHIFT	27
+#define MIPS_PWCTL_XS_MASK	0x08000000
+#define MIPS_PWCTL_XU_SHIFT	26
+#define MIPS_PWCTL_XU_MASK	0x04000000
 #define MIPS_PWCTL_DPH_SHIFT	7
 #define MIPS_PWCTL_DPH_MASK	0x00000080
 #define MIPS_PWCTL_HUGEPG_SHIFT	6
@@ -706,6 +757,94 @@
 #define MIPS_PWCTL_PSN_SHIFT	0
 #define MIPS_PWCTL_PSN_MASK	0x0000003f
 
+/* GuestCtl0 fields */
+#define MIPS_GCTL0_GM_SHIFT	31
+#define MIPS_GCTL0_GM		(_ULCAST_(1) << MIPS_GCTL0_GM_SHIFT)
+#define MIPS_GCTL0_RI_SHIFT	30
+#define MIPS_GCTL0_RI		(_ULCAST_(1) << MIPS_GCTL0_RI_SHIFT)
+#define MIPS_GCTL0_MC_SHIFT	29
+#define MIPS_GCTL0_MC		(_ULCAST_(1) << MIPS_GCTL0_MC_SHIFT)
+#define MIPS_GCTL0_CP0_SHIFT	28
+#define MIPS_GCTL0_CP0		(_ULCAST_(1) << MIPS_GCTL0_CP0_SHIFT)
+#define MIPS_GCTL0_AT_SHIFT	26
+#define MIPS_GCTL0_AT		(_ULCAST_(0x3) << MIPS_GCTL0_AT_SHIFT)
+#define MIPS_GCTL0_GT_SHIFT	25
+#define MIPS_GCTL0_GT		(_ULCAST_(1) << MIPS_GCTL0_GT_SHIFT)
+#define MIPS_GCTL0_CG_SHIFT	24
+#define MIPS_GCTL0_CG		(_ULCAST_(1) << MIPS_GCTL0_CG_SHIFT)
+#define MIPS_GCTL0_CF_SHIFT	23
+#define MIPS_GCTL0_CF		(_ULCAST_(1) << MIPS_GCTL0_CF_SHIFT)
+#define MIPS_GCTL0_G1_SHIFT	22
+#define MIPS_GCTL0_G1		(_ULCAST_(1) << MIPS_GCTL0_G1_SHIFT)
+#define MIPS_GCTL0_G0E_SHIFT	19
+#define MIPS_GCTL0_G0E		(_ULCAST_(1) << MIPS_GCTL0_G0E_SHIFT)
+#define MIPS_GCTL0_PT_SHIFT	18
+#define MIPS_GCTL0_PT		(_ULCAST_(1) << MIPS_GCTL0_PT_SHIFT)
+#define MIPS_GCTL0_RAD_SHIFT	9
+#define MIPS_GCTL0_RAD		(_ULCAST_(1) << MIPS_GCTL0_RAD_SHIFT)
+#define MIPS_GCTL0_DRG_SHIFT	8
+#define MIPS_GCTL0_DRG		(_ULCAST_(1) << MIPS_GCTL0_DRG_SHIFT)
+#define MIPS_GCTL0_G2_SHIFT	7
+#define MIPS_GCTL0_G2		(_ULCAST_(1) << MIPS_GCTL0_G2_SHIFT)
+#define MIPS_GCTL0_GEXC_SHIFT	2
+#define MIPS_GCTL0_GEXC		(_ULCAST_(0x1f) << MIPS_GCTL0_GEXC_SHIFT)
+#define MIPS_GCTL0_SFC2_SHIFT	1
+#define MIPS_GCTL0_SFC2		(_ULCAST_(1) << MIPS_GCTL0_SFC2_SHIFT)
+#define MIPS_GCTL0_SFC1_SHIFT	0
+#define MIPS_GCTL0_SFC1		(_ULCAST_(1) << MIPS_GCTL0_SFC1_SHIFT)
+
+/* GuestCtl0.AT Guest address translation control */
+#define MIPS_GCTL0_AT_ROOT	1  /* Guest MMU under Root control */
+#define MIPS_GCTL0_AT_GUEST	3  /* Guest MMU under Guest control */
+
+/* GuestCtl0.GExcCode Hypervisor exception cause codes */
+#define MIPS_GCTL0_GEXC_GPSI	0  /* Guest Privileged Sensitive Instruction */
+#define MIPS_GCTL0_GEXC_GSFC	1  /* Guest Software Field Change */
+#define MIPS_GCTL0_GEXC_HC	2  /* Hypercall */
+#define MIPS_GCTL0_GEXC_GRR	3  /* Guest Reserved Instruction Redirect */
+#define MIPS_GCTL0_GEXC_GVA	8  /* Guest Virtual Address available */
+#define MIPS_GCTL0_GEXC_GHFC	9  /* Guest Hardware Field Change */
+#define MIPS_GCTL0_GEXC_GPA	10 /* Guest Physical Address available */
+
+/* GuestCtl0Ext fields */
+#define MIPS_GCTL0EXT_RPW_SHIFT	8
+#define MIPS_GCTL0EXT_RPW	(_ULCAST_(0x3) << MIPS_GCTL0EXT_RPW_SHIFT)
+#define MIPS_GCTL0EXT_NCC_SHIFT	6
+#define MIPS_GCTL0EXT_NCC	(_ULCAST_(0x3) << MIPS_GCTL0EXT_NCC_SHIFT)
+#define MIPS_GCTL0EXT_CGI_SHIFT	4
+#define MIPS_GCTL0EXT_CGI	(_ULCAST_(1) << MIPS_GCTL0EXT_CGI_SHIFT)
+#define MIPS_GCTL0EXT_FCD_SHIFT	3
+#define MIPS_GCTL0EXT_FCD	(_ULCAST_(1) << MIPS_GCTL0EXT_FCD_SHIFT)
+#define MIPS_GCTL0EXT_OG_SHIFT	2
+#define MIPS_GCTL0EXT_OG	(_ULCAST_(1) << MIPS_GCTL0EXT_OG_SHIFT)
+#define MIPS_GCTL0EXT_BG_SHIFT	1
+#define MIPS_GCTL0EXT_BG	(_ULCAST_(1) << MIPS_GCTL0EXT_BG_SHIFT)
+#define MIPS_GCTL0EXT_MG_SHIFT	0
+#define MIPS_GCTL0EXT_MG	(_ULCAST_(1) << MIPS_GCTL0EXT_MG_SHIFT)
+
+/* GuestCtl0Ext.RPW Root page walk configuration */
+#define MIPS_GCTL0EXT_RPW_BOTH	0  /* Root PW for GPA->RPA and RVA->RPA */
+#define MIPS_GCTL0EXT_RPW_GPA	2  /* Root PW for GPA->RPA */
+#define MIPS_GCTL0EXT_RPW_RVA	3  /* Root PW for RVA->RPA */
+
+/* GuestCtl0Ext.NCC Nested cache coherency attributes */
+#define MIPS_GCTL0EXT_NCC_IND	0  /* Guest CCA independent of Root CCA */
+#define MIPS_GCTL0EXT_NCC_MOD	1  /* Guest CCA modified by Root CCA */
+
+/* GuestCtl1 fields */
+#define MIPS_GCTL1_ID_SHIFT	0
+#define MIPS_GCTL1_ID_WIDTH	8
+#define MIPS_GCTL1_ID		(_ULCAST_(0xff) << MIPS_GCTL1_ID_SHIFT)
+#define MIPS_GCTL1_RID_SHIFT	16
+#define MIPS_GCTL1_RID_WIDTH	8
+#define MIPS_GCTL1_RID		(_ULCAST_(0xff) << MIPS_GCTL1_RID_SHIFT)
+#define MIPS_GCTL1_EID_SHIFT	24
+#define MIPS_GCTL1_EID_WIDTH	8
+#define MIPS_GCTL1_EID		(_ULCAST_(0xff) << MIPS_GCTL1_EID_SHIFT)
+
+/* GuestID reserved for root context */
+#define MIPS_GCTL1_ROOT_GUESTID	0
+
 /* CDMMBase register bit definitions */
 #define MIPS_CDMMBASE_SIZE_SHIFT 0
 #define MIPS_CDMMBASE_SIZE	(_ULCAST_(511) << MIPS_CDMMBASE_SIZE_SHIFT)
@@ -757,6 +896,15 @@
 /* Disable Branch Return Cache */
 #define R10K_DIAG_D_BRC		(_ULCAST_(1) << 22)
 
+/* Flush ITLB */
+#define LOONGSON_DIAG_ITLB	(_ULCAST_(1) << 2)
+/* Flush DTLB */
+#define LOONGSON_DIAG_DTLB	(_ULCAST_(1) << 3)
+/* Flush VTLB */
+#define LOONGSON_DIAG_VTLB	(_ULCAST_(1) << 12)
+/* Flush FTLB */
+#define LOONGSON_DIAG_FTLB	(_ULCAST_(1) << 13)
+
 /*
  * Coprocessor 1 (FPU) register names
  */
@@ -909,6 +1057,33 @@ static inline int mm_insn_16bit(u16 insn
 }
 
 /*
+ * Helper macros for generating raw instruction encodings in inline asm.
+ */
+#ifdef CONFIG_CPU_MICROMIPS
+#define _ASM_INSN16_IF_MM(_enc)			\
+	".insn\n\t"				\
+	".hword (" #_enc ")\n\t"
+#define _ASM_INSN32_IF_MM(_enc)			\
+	".insn\n\t"				\
+	".hword ((" #_enc ") >> 16)\n\t"	\
+	".hword ((" #_enc ") & 0xffff)\n\t"
+#else
+#define _ASM_INSN_IF_MIPS(_enc)			\
+	".insn\n\t"				\
+	".word (" #_enc ")\n\t"
+#endif
+
+#ifndef _ASM_INSN16_IF_MM
+#define _ASM_INSN16_IF_MM(_enc)
+#endif
+#ifndef _ASM_INSN32_IF_MM
+#define _ASM_INSN32_IF_MM(_enc)
+#endif
+#ifndef _ASM_INSN_IF_MIPS
+#define _ASM_INSN_IF_MIPS(_enc)
+#endif
+
+/*
  * TLB Invalidate Flush
  */
 static inline void tlbinvf(void)
@@ -916,7 +1091,9 @@ static inline void tlbinvf(void)
 	__asm__ __volatile__(
 		".set push\n\t"
 		".set noreorder\n\t"
-		".word 0x42000004\n\t" /* tlbinvf */
+		"# tlbinvf\n\t"
+		_ASM_INSN_IF_MIPS(0x42000004)
+		_ASM_INSN32_IF_MM(0x0000537c)
 		".set pop");
 }
 
@@ -1137,9 +1314,9 @@ do {									\
 	"	.set	push					\n"	\
 	"	.set	noat					\n"	\
 	"	.set	mips32r2				\n"	\
-	"	.insn						\n"	\
 	"	# mfhc0 $1, %1					\n"	\
-	"	.word	(0x40410000 | ((%1 & 0x1f) << 11))	\n"	\
+	_ASM_INSN_IF_MIPS(0x40410000 | ((%1 & 0x1f) << 11))		\
+	_ASM_INSN32_IF_MM(0x002000f4 | ((%1 & 0x1f) << 16))		\
 	"	move	%0, $1					\n"	\
 	"	.set	pop					\n"	\
 	: "=r" (__res)							\
@@ -1155,8 +1332,8 @@ do {									\
 	"	.set	mips32r2				\n"	\
 	"	move	$1, %0					\n"	\
 	"	# mthc0 $1, %1					\n"	\
-	"	.insn						\n"	\
-	"	.word	(0x40c10000 | ((%1 & 0x1f) << 11))	\n"	\
+	_ASM_INSN_IF_MIPS(0x40c10000 | ((%1 & 0x1f) << 11))		\
+	_ASM_INSN32_IF_MM(0x002002f4 | ((%1 & 0x1f) << 16))		\
 	"	.set	pop					\n"	\
 	:								\
 	: "r" (value), "i" (register));					\
@@ -1186,9 +1363,15 @@ do {									\
 #define read_c0_context()	__read_ulong_c0_register($4, 0)
 #define write_c0_context(val)	__write_ulong_c0_register($4, 0, val)
 
+#define read_c0_contextconfig()		__read_32bit_c0_register($4, 1)
+#define write_c0_contextconfig(val)	__write_32bit_c0_register($4, 1, val)
+
 #define read_c0_userlocal()	__read_ulong_c0_register($4, 2)
 #define write_c0_userlocal(val) __write_ulong_c0_register($4, 2, val)
 
+#define read_c0_xcontextconfig()	__read_ulong_c0_register($4, 3)
+#define write_c0_xcontextconfig(val)	__write_ulong_c0_register($4, 3, val)
+
 #define read_c0_pagemask()	__read_32bit_c0_register($5, 0)
 #define write_c0_pagemask(val)	__write_32bit_c0_register($5, 0, val)
 
@@ -1206,6 +1389,9 @@ do {									\
 #define read_c0_badvaddr()	__read_ulong_c0_register($8, 0)
 #define write_c0_badvaddr(val)	__write_ulong_c0_register($8, 0, val)
 
+#define read_c0_badinstr()	__read_32bit_c0_register($8, 1)
+#define read_c0_badinstrp()	__read_32bit_c0_register($8, 2)
+
 #define read_c0_count()		__read_32bit_c0_register($9, 0)
 #define write_c0_count(val)	__write_32bit_c0_register($9, 0, val)
 
@@ -1218,9 +1404,21 @@ do {									\
 #define read_c0_entryhi()	__read_ulong_c0_register($10, 0)
 #define write_c0_entryhi(val)	__write_ulong_c0_register($10, 0, val)
 
+#define read_c0_guestctl1()	__read_32bit_c0_register($10, 4)
+#define write_c0_guestctl1(val)	__write_32bit_c0_register($10, 4, val)
+
+#define read_c0_guestctl2()	__read_32bit_c0_register($10, 5)
+#define write_c0_guestctl2(val)	__write_32bit_c0_register($10, 5, val)
+
+#define read_c0_guestctl3()	__read_32bit_c0_register($10, 6)
+#define write_c0_guestctl3(val)	__write_32bit_c0_register($10, 6, val)
+
 #define read_c0_compare()	__read_32bit_c0_register($11, 0)
 #define write_c0_compare(val)	__write_32bit_c0_register($11, 0, val)
 
+#define read_c0_guestctl0ext()	__read_32bit_c0_register($11, 4)
+#define write_c0_guestctl0ext(val) __write_32bit_c0_register($11, 4, val)
+
 #define read_c0_compare2()	__read_32bit_c0_register($11, 6) /* pnx8550 */
 #define write_c0_compare2(val)	__write_32bit_c0_register($11, 6, val)
 
@@ -1231,6 +1429,12 @@ do {									\
 
 #define write_c0_status(val)	__write_32bit_c0_register($12, 0, val)
 
+#define read_c0_guestctl0()	__read_32bit_c0_register($12, 6)
+#define write_c0_guestctl0(val)	__write_32bit_c0_register($12, 6, val)
+
+#define read_c0_gtoffset()	__read_32bit_c0_register($12, 7)
+#define write_c0_gtoffset(val)	__write_32bit_c0_register($12, 7, val)
+
 #define read_c0_cause()		__read_32bit_c0_register($13, 0)
 #define write_c0_cause(val)	__write_32bit_c0_register($13, 0, val)
 
@@ -1416,6 +1620,9 @@ do {									\
 #define read_c0_ebase()		__read_32bit_c0_register($15, 1)
 #define write_c0_ebase(val)	__write_32bit_c0_register($15, 1, val)
 
+#define read_c0_ebase_64()	__read_64bit_c0_register($15, 1)
+#define write_c0_ebase_64(val)	__write_64bit_c0_register($15, 1, val)
+
 #define read_c0_cdmmbase()	__read_ulong_c0_register($15, 2)
 #define write_c0_cdmmbase(val)	__write_ulong_c0_register($15, 2, val)
 
@@ -1442,6 +1649,12 @@ do {									\
 #define read_c0_pwctl()		__read_32bit_c0_register($6, 6)
 #define write_c0_pwctl(val)	__write_32bit_c0_register($6, 6, val)
 
+#define read_c0_pgd()		__read_64bit_c0_register($9, 7)
+#define write_c0_pgd(val)	__write_64bit_c0_register($9, 7, val)
+
+#define read_c0_kpgd()		__read_64bit_c0_register($31, 7)
+#define write_c0_kpgd(val)	__write_64bit_c0_register($31, 7, val)
+
 /* Cavium OCTEON (cnMIPS) */
 #define read_c0_cvmcount()	__read_ulong_c0_register($9, 6)
 #define write_c0_cvmcount(val)	__write_ulong_c0_register($9, 6, val)
@@ -1507,6 +1720,321 @@ do {									\
 #define write_c0_brcm_sleepcount(val)	__write_32bit_c0_register($22, 7, val)
 
 /*
+ * Macros to access the guest system control coprocessor
+ */
+
+#ifdef TOOLCHAIN_SUPPORTS_VIRT
+
+#define __read_32bit_gc0_register(source, sel)				\
+({ int __res;								\
+	__asm__ __volatile__(						\
+		".set\tpush\n\t"					\
+		".set\tmips32r2\n\t"					\
+		".set\tvirt\n\t"					\
+		"mfgc0\t%0, $%1, %2\n\t"				\
+		".set\tpop"						\
+		: "=r" (__res)						\
+		: "i" (source), "i" (sel));				\
+	__res;								\
+})
+
+#define __read_64bit_gc0_register(source, sel)				\
+({ unsigned long long __res;						\
+	__asm__ __volatile__(						\
+		".set\tpush\n\t"					\
+		".set\tmips64r2\n\t"					\
+		".set\tvirt\n\t"					\
+		"dmfgc0\t%0, $%1, %2\n\t"			\
+		".set\tpop"						\
+		: "=r" (__res)						\
+		: "i" (source), "i" (sel));				\
+	__res;								\
+})
+
+#define __write_32bit_gc0_register(register, sel, value)		\
+do {									\
+	__asm__ __volatile__(						\
+		".set\tpush\n\t"					\
+		".set\tmips32r2\n\t"					\
+		".set\tvirt\n\t"					\
+		"mtgc0\t%z0, $%1, %2\n\t"				\
+		".set\tpop"						\
+		: : "Jr" ((unsigned int)(value)),			\
+		    "i" (register), "i" (sel));				\
+} while (0)
+
+#define __write_64bit_gc0_register(register, sel, value)		\
+do {									\
+	__asm__ __volatile__(						\
+		".set\tpush\n\t"					\
+		".set\tmips64r2\n\t"					\
+		".set\tvirt\n\t"					\
+		"dmtgc0\t%z0, $%1, %2\n\t"				\
+		".set\tpop"						\
+		: : "Jr" (value),					\
+		    "i" (register), "i" (sel));				\
+} while (0)
+
+#else	/* TOOLCHAIN_SUPPORTS_VIRT */
+
+#define __read_32bit_gc0_register(source, sel)				\
+({ int __res;								\
+	__asm__ __volatile__(						\
+		".set\tpush\n\t"					\
+		".set\tnoat\n\t"					\
+		"# mfgc0\t$1, $%1, %2\n\t"				\
+		_ASM_INSN_IF_MIPS(0x40610000 | %1 << 11 | %2)		\
+		_ASM_INSN32_IF_MM(0x002004fc | %1 << 16 | %2 << 11)	\
+		"move\t%0, $1\n\t"					\
+		".set\tpop"						\
+		: "=r" (__res)						\
+		: "i" (source), "i" (sel));				\
+	__res;								\
+})
+
+#define __read_64bit_gc0_register(source, sel)				\
+({ unsigned long long __res;						\
+	__asm__ __volatile__(						\
+		".set\tpush\n\t"					\
+		".set\tnoat\n\t"					\
+		"# dmfgc0\t$1, $%1, %2\n\t"				\
+		_ASM_INSN_IF_MIPS(0x40610100 | %1 << 11 | %2)		\
+		_ASM_INSN32_IF_MM(0x582004fc | %1 << 16 | %2 << 11)	\
+		"move\t%0, $1\n\t"					\
+		".set\tpop"						\
+		: "=r" (__res)						\
+		: "i" (source), "i" (sel));				\
+	__res;								\
+})
+
+#define __write_32bit_gc0_register(register, sel, value)		\
+do {									\
+	__asm__ __volatile__(						\
+		".set\tpush\n\t"					\
+		".set\tnoat\n\t"					\
+		"move\t$1, %z0\n\t"					\
+		"# mtgc0\t$1, $%1, %2\n\t"				\
+		_ASM_INSN_IF_MIPS(0x40610200 | %1 << 11 | %2)		\
+		_ASM_INSN32_IF_MM(0x002006fc | %1 << 16 | %2 << 11)	\
+		".set\tpop"						\
+		: : "Jr" ((unsigned int)(value)),			\
+		    "i" (register), "i" (sel));				\
+} while (0)
+
+#define __write_64bit_gc0_register(register, sel, value)		\
+do {									\
+	__asm__ __volatile__(						\
+		".set\tpush\n\t"					\
+		".set\tnoat\n\t"					\
+		"move\t$1, %z0\n\t"					\
+		"# dmtgc0\t$1, $%1, %2\n\t"				\
+		_ASM_INSN_IF_MIPS(0x40610300 | %1 << 11 | %2)		\
+		_ASM_INSN32_IF_MM(0x582006fc | %1 << 16 | %2 << 11)	\
+		".set\tpop"						\
+		: : "Jr" (value),					\
+		    "i" (register), "i" (sel));				\
+} while (0)
+
+#endif	/* !TOOLCHAIN_SUPPORTS_VIRT */
+
+#define __read_ulong_gc0_register(reg, sel)				\
+	((sizeof(unsigned long) == 4) ?					\
+	(unsigned long) __read_32bit_gc0_register(reg, sel) :		\
+	(unsigned long) __read_64bit_gc0_register(reg, sel))
+
+#define __write_ulong_gc0_register(reg, sel, val)			\
+do {									\
+	if (sizeof(unsigned long) == 4)					\
+		__write_32bit_gc0_register(reg, sel, val);		\
+	else								\
+		__write_64bit_gc0_register(reg, sel, val);		\
+} while (0)
+
+#define read_gc0_index()		__read_32bit_gc0_register(0, 0)
+#define write_gc0_index(val)		__write_32bit_gc0_register(0, 0, val)
+
+#define read_gc0_entrylo0()		__read_ulong_gc0_register(2, 0)
+#define write_gc0_entrylo0(val)		__write_ulong_gc0_register(2, 0, val)
+
+#define read_gc0_entrylo1()		__read_ulong_gc0_register(3, 0)
+#define write_gc0_entrylo1(val)		__write_ulong_gc0_register(3, 0, val)
+
+#define read_gc0_context()		__read_ulong_gc0_register(4, 0)
+#define write_gc0_context(val)		__write_ulong_gc0_register(4, 0, val)
+
+#define read_gc0_contextconfig()	__read_32bit_gc0_register(4, 1)
+#define write_gc0_contextconfig(val)	__write_32bit_gc0_register(4, 1, val)
+
+#define read_gc0_userlocal()		__read_ulong_gc0_register(4, 2)
+#define write_gc0_userlocal(val)	__write_ulong_gc0_register(4, 2, val)
+
+#define read_gc0_xcontextconfig()	__read_ulong_gc0_register(4, 3)
+#define write_gc0_xcontextconfig(val)	__write_ulong_gc0_register(4, 3, val)
+
+#define read_gc0_pagemask()		__read_32bit_gc0_register(5, 0)
+#define write_gc0_pagemask(val)		__write_32bit_gc0_register(5, 0, val)
+
+#define read_gc0_pagegrain()		__read_32bit_gc0_register(5, 1)
+#define write_gc0_pagegrain(val)	__write_32bit_gc0_register(5, 1, val)
+
+#define read_gc0_segctl0()		__read_ulong_gc0_register(5, 2)
+#define write_gc0_segctl0(val)		__write_ulong_gc0_register(5, 2, val)
+
+#define read_gc0_segctl1()		__read_ulong_gc0_register(5, 3)
+#define write_gc0_segctl1(val)		__write_ulong_gc0_register(5, 3, val)
+
+#define read_gc0_segctl2()		__read_ulong_gc0_register(5, 4)
+#define write_gc0_segctl2(val)		__write_ulong_gc0_register(5, 4, val)
+
+#define read_gc0_pwbase()		__read_ulong_gc0_register(5, 5)
+#define write_gc0_pwbase(val)		__write_ulong_gc0_register(5, 5, val)
+
+#define read_gc0_pwfield()		__read_ulong_gc0_register(5, 6)
+#define write_gc0_pwfield(val)		__write_ulong_gc0_register(5, 6, val)
+
+#define read_gc0_pwsize()		__read_ulong_gc0_register(5, 7)
+#define write_gc0_pwsize(val)		__write_ulong_gc0_register(5, 7, val)
+
+#define read_gc0_wired()		__read_32bit_gc0_register(6, 0)
+#define write_gc0_wired(val)		__write_32bit_gc0_register(6, 0, val)
+
+#define read_gc0_pwctl()		__read_32bit_gc0_register(6, 6)
+#define write_gc0_pwctl(val)		__write_32bit_gc0_register(6, 6, val)
+
+#define read_gc0_hwrena()		__read_32bit_gc0_register(7, 0)
+#define write_gc0_hwrena(val)		__write_32bit_gc0_register(7, 0, val)
+
+#define read_gc0_badvaddr()		__read_ulong_gc0_register(8, 0)
+#define write_gc0_badvaddr(val)		__write_ulong_gc0_register(8, 0, val)
+
+#define read_gc0_badinstr()		__read_32bit_gc0_register(8, 1)
+#define write_gc0_badinstr(val)		__write_32bit_gc0_register(8, 1, val)
+
+#define read_gc0_badinstrp()		__read_32bit_gc0_register(8, 2)
+#define write_gc0_badinstrp(val)	__write_32bit_gc0_register(8, 2, val)
+
+#define read_gc0_count()		__read_32bit_gc0_register(9, 0)
+
+#define read_gc0_entryhi()		__read_ulong_gc0_register(10, 0)
+#define write_gc0_entryhi(val)		__write_ulong_gc0_register(10, 0, val)
+
+#define read_gc0_compare()		__read_32bit_gc0_register(11, 0)
+#define write_gc0_compare(val)		__write_32bit_gc0_register(11, 0, val)
+
+#define read_gc0_status()		__read_32bit_gc0_register(12, 0)
+#define write_gc0_status(val)		__write_32bit_gc0_register(12, 0, val)
+
+#define read_gc0_intctl()		__read_32bit_gc0_register(12, 1)
+#define write_gc0_intctl(val)		__write_32bit_gc0_register(12, 1, val)
+
+#define read_gc0_cause()		__read_32bit_gc0_register(13, 0)
+#define write_gc0_cause(val)		__write_32bit_gc0_register(13, 0, val)
+
+#define read_gc0_epc()			__read_ulong_gc0_register(14, 0)
+#define write_gc0_epc(val)		__write_ulong_gc0_register(14, 0, val)
+
+#define read_gc0_ebase()		__read_32bit_gc0_register(15, 1)
+#define write_gc0_ebase(val)		__write_32bit_gc0_register(15, 1, val)
+
+#define read_gc0_ebase_64()		__read_64bit_gc0_register(15, 1)
+#define write_gc0_ebase_64(val)		__write_64bit_gc0_register(15, 1, val)
+
+#define read_gc0_config()		__read_32bit_gc0_register(16, 0)
+#define read_gc0_config1()		__read_32bit_gc0_register(16, 1)
+#define read_gc0_config2()		__read_32bit_gc0_register(16, 2)
+#define read_gc0_config3()		__read_32bit_gc0_register(16, 3)
+#define read_gc0_config4()		__read_32bit_gc0_register(16, 4)
+#define read_gc0_config5()		__read_32bit_gc0_register(16, 5)
+#define read_gc0_config6()		__read_32bit_gc0_register(16, 6)
+#define read_gc0_config7()		__read_32bit_gc0_register(16, 7)
+#define write_gc0_config(val)		__write_32bit_gc0_register(16, 0, val)
+#define write_gc0_config1(val)		__write_32bit_gc0_register(16, 1, val)
+#define write_gc0_config2(val)		__write_32bit_gc0_register(16, 2, val)
+#define write_gc0_config3(val)		__write_32bit_gc0_register(16, 3, val)
+#define write_gc0_config4(val)		__write_32bit_gc0_register(16, 4, val)
+#define write_gc0_config5(val)		__write_32bit_gc0_register(16, 5, val)
+#define write_gc0_config6(val)		__write_32bit_gc0_register(16, 6, val)
+#define write_gc0_config7(val)		__write_32bit_gc0_register(16, 7, val)
+
+#define read_gc0_watchlo0()		__read_ulong_gc0_register(18, 0)
+#define read_gc0_watchlo1()		__read_ulong_gc0_register(18, 1)
+#define read_gc0_watchlo2()		__read_ulong_gc0_register(18, 2)
+#define read_gc0_watchlo3()		__read_ulong_gc0_register(18, 3)
+#define read_gc0_watchlo4()		__read_ulong_gc0_register(18, 4)
+#define read_gc0_watchlo5()		__read_ulong_gc0_register(18, 5)
+#define read_gc0_watchlo6()		__read_ulong_gc0_register(18, 6)
+#define read_gc0_watchlo7()		__read_ulong_gc0_register(18, 7)
+#define write_gc0_watchlo0(val)		__write_ulong_gc0_register(18, 0, val)
+#define write_gc0_watchlo1(val)		__write_ulong_gc0_register(18, 1, val)
+#define write_gc0_watchlo2(val)		__write_ulong_gc0_register(18, 2, val)
+#define write_gc0_watchlo3(val)		__write_ulong_gc0_register(18, 3, val)
+#define write_gc0_watchlo4(val)		__write_ulong_gc0_register(18, 4, val)
+#define write_gc0_watchlo5(val)		__write_ulong_gc0_register(18, 5, val)
+#define write_gc0_watchlo6(val)		__write_ulong_gc0_register(18, 6, val)
+#define write_gc0_watchlo7(val)		__write_ulong_gc0_register(18, 7, val)
+
+#define read_gc0_watchhi0()		__read_32bit_gc0_register(19, 0)
+#define read_gc0_watchhi1()		__read_32bit_gc0_register(19, 1)
+#define read_gc0_watchhi2()		__read_32bit_gc0_register(19, 2)
+#define read_gc0_watchhi3()		__read_32bit_gc0_register(19, 3)
+#define read_gc0_watchhi4()		__read_32bit_gc0_register(19, 4)
+#define read_gc0_watchhi5()		__read_32bit_gc0_register(19, 5)
+#define read_gc0_watchhi6()		__read_32bit_gc0_register(19, 6)
+#define read_gc0_watchhi7()		__read_32bit_gc0_register(19, 7)
+#define write_gc0_watchhi0(val)		__write_32bit_gc0_register(19, 0, val)
+#define write_gc0_watchhi1(val)		__write_32bit_gc0_register(19, 1, val)
+#define write_gc0_watchhi2(val)		__write_32bit_gc0_register(19, 2, val)
+#define write_gc0_watchhi3(val)		__write_32bit_gc0_register(19, 3, val)
+#define write_gc0_watchhi4(val)		__write_32bit_gc0_register(19, 4, val)
+#define write_gc0_watchhi5(val)		__write_32bit_gc0_register(19, 5, val)
+#define write_gc0_watchhi6(val)		__write_32bit_gc0_register(19, 6, val)
+#define write_gc0_watchhi7(val)		__write_32bit_gc0_register(19, 7, val)
+
+#define read_gc0_xcontext()		__read_ulong_gc0_register(20, 0)
+#define write_gc0_xcontext(val)		__write_ulong_gc0_register(20, 0, val)
+
+#define read_gc0_perfctrl0()		__read_32bit_gc0_register(25, 0)
+#define write_gc0_perfctrl0(val)	__write_32bit_gc0_register(25, 0, val)
+#define read_gc0_perfcntr0()		__read_32bit_gc0_register(25, 1)
+#define write_gc0_perfcntr0(val)	__write_32bit_gc0_register(25, 1, val)
+#define read_gc0_perfcntr0_64()		__read_64bit_gc0_register(25, 1)
+#define write_gc0_perfcntr0_64(val)	__write_64bit_gc0_register(25, 1, val)
+#define read_gc0_perfctrl1()		__read_32bit_gc0_register(25, 2)
+#define write_gc0_perfctrl1(val)	__write_32bit_gc0_register(25, 2, val)
+#define read_gc0_perfcntr1()		__read_32bit_gc0_register(25, 3)
+#define write_gc0_perfcntr1(val)	__write_32bit_gc0_register(25, 3, val)
+#define read_gc0_perfcntr1_64()		__read_64bit_gc0_register(25, 3)
+#define write_gc0_perfcntr1_64(val)	__write_64bit_gc0_register(25, 3, val)
+#define read_gc0_perfctrl2()		__read_32bit_gc0_register(25, 4)
+#define write_gc0_perfctrl2(val)	__write_32bit_gc0_register(25, 4, val)
+#define read_gc0_perfcntr2()		__read_32bit_gc0_register(25, 5)
+#define write_gc0_perfcntr2(val)	__write_32bit_gc0_register(25, 5, val)
+#define read_gc0_perfcntr2_64()		__read_64bit_gc0_register(25, 5)
+#define write_gc0_perfcntr2_64(val)	__write_64bit_gc0_register(25, 5, val)
+#define read_gc0_perfctrl3()		__read_32bit_gc0_register(25, 6)
+#define write_gc0_perfctrl3(val)	__write_32bit_gc0_register(25, 6, val)
+#define read_gc0_perfcntr3()		__read_32bit_gc0_register(25, 7)
+#define write_gc0_perfcntr3(val)	__write_32bit_gc0_register(25, 7, val)
+#define read_gc0_perfcntr3_64()		__read_64bit_gc0_register(25, 7)
+#define write_gc0_perfcntr3_64(val)	__write_64bit_gc0_register(25, 7, val)
+
+#define read_gc0_errorepc()		__read_ulong_gc0_register(30, 0)
+#define write_gc0_errorepc(val)		__write_ulong_gc0_register(30, 0, val)
+
+#define read_gc0_kscratch1()		__read_ulong_gc0_register(31, 2)
+#define read_gc0_kscratch2()		__read_ulong_gc0_register(31, 3)
+#define read_gc0_kscratch3()		__read_ulong_gc0_register(31, 4)
+#define read_gc0_kscratch4()		__read_ulong_gc0_register(31, 5)
+#define read_gc0_kscratch5()		__read_ulong_gc0_register(31, 6)
+#define read_gc0_kscratch6()		__read_ulong_gc0_register(31, 7)
+#define write_gc0_kscratch1(val)	__write_ulong_gc0_register(31, 2, val)
+#define write_gc0_kscratch2(val)	__write_ulong_gc0_register(31, 3, val)
+#define write_gc0_kscratch3(val)	__write_ulong_gc0_register(31, 4, val)
+#define write_gc0_kscratch4(val)	__write_ulong_gc0_register(31, 5, val)
+#define write_gc0_kscratch5(val)	__write_ulong_gc0_register(31, 6, val)
+#define write_gc0_kscratch6(val)	__write_ulong_gc0_register(31, 7, val)
+
+/*
  * Macros to access the floating point coprocessor control registers
  */
 #define _read_32bit_cp1_register(source, gas_hardfloat)			\
@@ -1762,7 +2290,6 @@ do {									\
 
 #else
 
-#ifdef CONFIG_CPU_MICROMIPS
 #define rddsp(mask)							\
 ({									\
 	unsigned int __res;						\
@@ -1771,8 +2298,8 @@ do {									\
 	"	.set	push					\n"	\
 	"	.set	noat					\n"	\
 	"	# rddsp $1, %x1					\n"	\
-	"	.hword	((0x0020067c | (%x1 << 14)) >> 16)	\n"	\
-	"	.hword	((0x0020067c | (%x1 << 14)) & 0xffff)	\n"	\
+	_ASM_INSN_IF_MIPS(0x7c000cb8 | (%x1 << 16))			\
+	_ASM_INSN32_IF_MM(0x0020067c | (%x1 << 14))			\
 	"	move	%0, $1					\n"	\
 	"	.set	pop					\n"	\
 	: "=r" (__res)							\
@@ -1787,22 +2314,22 @@ do {									\
 	"	.set	noat					\n"	\
 	"	move	$1, %0					\n"	\
 	"	# wrdsp $1, %x1					\n"	\
-	"	.hword	((0x0020167c | (%x1 << 14)) >> 16)	\n"	\
-	"	.hword	((0x0020167c | (%x1 << 14)) & 0xffff)	\n"	\
+	_ASM_INSN_IF_MIPS(0x7c2004f8 | (%x1 << 11))			\
+	_ASM_INSN32_IF_MM(0x0020167c | (%x1 << 14))			\
 	"	.set	pop					\n"	\
 	:								\
 	: "r" (val), "i" (mask));					\
 } while (0)
 
-#define _umips_dsp_mfxxx(ins)						\
+#define _dsp_mfxxx(ins)							\
 ({									\
 	unsigned long __treg;						\
 									\
 	__asm__ __volatile__(						\
 	"	.set	push					\n"	\
 	"	.set	noat					\n"	\
-	"	.hword	0x0001					\n"	\
-	"	.hword	%x1					\n"	\
+	_ASM_INSN_IF_MIPS(0x00000810 | %X1)				\
+	_ASM_INSN32_IF_MM(0x0001007c | %x1)				\
 	"	move	%0, $1					\n"	\
 	"	.set	pop					\n"	\
 	: "=r" (__treg)							\
@@ -1810,101 +2337,28 @@ do {									\
 	__treg;								\
 })
 
-#define _umips_dsp_mtxxx(val, ins)					\
+#define _dsp_mtxxx(val, ins)						\
 do {									\
 	__asm__ __volatile__(						\
 	"	.set	push					\n"	\
 	"	.set	noat					\n"	\
 	"	move	$1, %0					\n"	\
-	"	.hword	0x0001					\n"	\
-	"	.hword	%x1					\n"	\
+	_ASM_INSN_IF_MIPS(0x00200011 | %X1)				\
+	_ASM_INSN32_IF_MM(0x0001207c | %x1)				\
 	"	.set	pop					\n"	\
 	:								\
 	: "r" (val), "i" (ins));					\
 } while (0)
 
-#define _umips_dsp_mflo(reg) _umips_dsp_mfxxx((reg << 14) | 0x107c)
-#define _umips_dsp_mfhi(reg) _umips_dsp_mfxxx((reg << 14) | 0x007c)
-
-#define _umips_dsp_mtlo(val, reg) _umips_dsp_mtxxx(val, ((reg << 14) | 0x307c))
-#define _umips_dsp_mthi(val, reg) _umips_dsp_mtxxx(val, ((reg << 14) | 0x207c))
-
-#define mflo0() _umips_dsp_mflo(0)
-#define mflo1() _umips_dsp_mflo(1)
-#define mflo2() _umips_dsp_mflo(2)
-#define mflo3() _umips_dsp_mflo(3)
-
-#define mfhi0() _umips_dsp_mfhi(0)
-#define mfhi1() _umips_dsp_mfhi(1)
-#define mfhi2() _umips_dsp_mfhi(2)
-#define mfhi3() _umips_dsp_mfhi(3)
+#ifdef CONFIG_CPU_MICROMIPS
 
-#define mtlo0(x) _umips_dsp_mtlo(x, 0)
-#define mtlo1(x) _umips_dsp_mtlo(x, 1)
-#define mtlo2(x) _umips_dsp_mtlo(x, 2)
-#define mtlo3(x) _umips_dsp_mtlo(x, 3)
+#define _dsp_mflo(reg) _dsp_mfxxx((reg << 14) | 0x1000)
+#define _dsp_mfhi(reg) _dsp_mfxxx((reg << 14) | 0x0000)
 
-#define mthi0(x) _umips_dsp_mthi(x, 0)
-#define mthi1(x) _umips_dsp_mthi(x, 1)
-#define mthi2(x) _umips_dsp_mthi(x, 2)
-#define mthi3(x) _umips_dsp_mthi(x, 3)
+#define _dsp_mtlo(val, reg) _dsp_mtxxx(val, ((reg << 14) | 0x1000))
+#define _dsp_mthi(val, reg) _dsp_mtxxx(val, ((reg << 14) | 0x0000))
 
 #else  /* !CONFIG_CPU_MICROMIPS */
-#define rddsp(mask)							\
-({									\
-	unsigned int __res;						\
-									\
-	__asm__ __volatile__(						\
-	"	.set	push				\n"		\
-	"	.set	noat				\n"		\
-	"	# rddsp $1, %x1				\n"		\
-	"	.word	0x7c000cb8 | (%x1 << 16)	\n"		\
-	"	move	%0, $1				\n"		\
-	"	.set	pop				\n"		\
-	: "=r" (__res)							\
-	: "i" (mask));							\
-	__res;								\
-})
-
-#define wrdsp(val, mask)						\
-do {									\
-	__asm__ __volatile__(						\
-	"	.set	push					\n"	\
-	"	.set	noat					\n"	\
-	"	move	$1, %0					\n"	\
-	"	# wrdsp $1, %x1					\n"	\
-	"	.word	0x7c2004f8 | (%x1 << 11)		\n"	\
-	"	.set	pop					\n"	\
-        :								\
-	: "r" (val), "i" (mask));					\
-} while (0)
-
-#define _dsp_mfxxx(ins)							\
-({									\
-	unsigned long __treg;						\
-									\
-	__asm__ __volatile__(						\
-	"	.set	push					\n"	\
-	"	.set	noat					\n"	\
-	"	.word	(0x00000810 | %1)			\n"	\
-	"	move	%0, $1					\n"	\
-	"	.set	pop					\n"	\
-	: "=r" (__treg)							\
-	: "i" (ins));							\
-	__treg;								\
-})
-
-#define _dsp_mtxxx(val, ins)						\
-do {									\
-	__asm__ __volatile__(						\
-	"	.set	push					\n"	\
-	"	.set	noat					\n"	\
-	"	move	$1, %0					\n"	\
-	"	.word	(0x00200011 | %1)			\n"	\
-	"	.set	pop					\n"	\
-	:								\
-	: "r" (val), "i" (ins));					\
-} while (0)
 
 #define _dsp_mflo(reg) _dsp_mfxxx((reg << 21) | 0x0002)
 #define _dsp_mfhi(reg) _dsp_mfxxx((reg << 21) | 0x0000)
@@ -1912,6 +2366,8 @@ do {									\
 #define _dsp_mtlo(val, reg) _dsp_mtxxx(val, ((reg << 11) | 0x0002))
 #define _dsp_mthi(val, reg) _dsp_mtxxx(val, ((reg << 11) | 0x0000))
 
+#endif /* CONFIG_CPU_MICROMIPS */
+
 #define mflo0() _dsp_mflo(0)
 #define mflo1() _dsp_mflo(1)
 #define mflo2() _dsp_mflo(2)
@@ -1932,7 +2388,6 @@ do {									\
 #define mthi2(x) _dsp_mthi(x, 2)
 #define mthi3(x) _dsp_mthi(x, 3)
 
-#endif /* CONFIG_CPU_MICROMIPS */
 #endif
 
 /*
@@ -2001,47 +2456,164 @@ static inline void tlb_write_random(void
 		".set reorder");
 }
 
+#ifdef TOOLCHAIN_SUPPORTS_VIRT
+
 /*
- * Manipulate bits in a c0 register.
+ * Guest TLB operations.
+ *
+ * It is responsibility of the caller to take care of any TLB hazards.
  */
-#define __BUILD_SET_C0(name)					\
+static inline void guest_tlb_probe(void)
+{
+	__asm__ __volatile__(
+		".set push\n\t"
+		".set noreorder\n\t"
+		".set virt\n\t"
+		"tlbgp\n\t"
+		".set pop");
+}
+
+static inline void guest_tlb_read(void)
+{
+	__asm__ __volatile__(
+		".set push\n\t"
+		".set noreorder\n\t"
+		".set virt\n\t"
+		"tlbgr\n\t"
+		".set pop");
+}
+
+static inline void guest_tlb_write_indexed(void)
+{
+	__asm__ __volatile__(
+		".set push\n\t"
+		".set noreorder\n\t"
+		".set virt\n\t"
+		"tlbgwi\n\t"
+		".set pop");
+}
+
+static inline void guest_tlb_write_random(void)
+{
+	__asm__ __volatile__(
+		".set push\n\t"
+		".set noreorder\n\t"
+		".set virt\n\t"
+		"tlbgwr\n\t"
+		".set pop");
+}
+
+/*
+ * Guest TLB Invalidate Flush
+ */
+static inline void guest_tlbinvf(void)
+{
+	__asm__ __volatile__(
+		".set push\n\t"
+		".set noreorder\n\t"
+		".set virt\n\t"
+		"tlbginvf\n\t"
+		".set pop");
+}
+
+#else	/* TOOLCHAIN_SUPPORTS_VIRT */
+
+/*
+ * Guest TLB operations.
+ *
+ * It is responsibility of the caller to take care of any TLB hazards.
+ */
+static inline void guest_tlb_probe(void)
+{
+	__asm__ __volatile__(
+		"# tlbgp\n\t"
+		_ASM_INSN_IF_MIPS(0x42000010)
+		_ASM_INSN32_IF_MM(0x0000017c));
+}
+
+static inline void guest_tlb_read(void)
+{
+	__asm__ __volatile__(
+		"# tlbgr\n\t"
+		_ASM_INSN_IF_MIPS(0x42000009)
+		_ASM_INSN32_IF_MM(0x0000117c));
+}
+
+static inline void guest_tlb_write_indexed(void)
+{
+	__asm__ __volatile__(
+		"# tlbgwi\n\t"
+		_ASM_INSN_IF_MIPS(0x4200000a)
+		_ASM_INSN32_IF_MM(0x0000217c));
+}
+
+static inline void guest_tlb_write_random(void)
+{
+	__asm__ __volatile__(
+		"# tlbgwr\n\t"
+		_ASM_INSN_IF_MIPS(0x4200000e)
+		_ASM_INSN32_IF_MM(0x0000317c));
+}
+
+/*
+ * Guest TLB Invalidate Flush
+ */
+static inline void guest_tlbinvf(void)
+{
+	__asm__ __volatile__(
+		"# tlbginvf\n\t"
+		_ASM_INSN_IF_MIPS(0x4200000c)
+		_ASM_INSN32_IF_MM(0x0000517c));
+}
+
+#endif	/* !TOOLCHAIN_SUPPORTS_VIRT */
+
+/*
+ * Manipulate bits in a register.
+ */
+#define __BUILD_SET_COMMON(name)				\
 static inline unsigned int					\
-set_c0_##name(unsigned int set)					\
+set_##name(unsigned int set)					\
 {								\
 	unsigned int res, new;					\
 								\
-	res = read_c0_##name();					\
+	res = read_##name();					\
 	new = res | set;					\
-	write_c0_##name(new);					\
+	write_##name(new);					\
 								\
 	return res;						\
 }								\
 								\
 static inline unsigned int					\
-clear_c0_##name(unsigned int clear)				\
+clear_##name(unsigned int clear)				\
 {								\
 	unsigned int res, new;					\
 								\
-	res = read_c0_##name();					\
+	res = read_##name();					\
 	new = res & ~clear;					\
-	write_c0_##name(new);					\
+	write_##name(new);					\
 								\
 	return res;						\
 }								\
 								\
 static inline unsigned int					\
-change_c0_##name(unsigned int change, unsigned int val)		\
+change_##name(unsigned int change, unsigned int val)		\
 {								\
 	unsigned int res, new;					\
 								\
-	res = read_c0_##name();					\
+	res = read_##name();					\
 	new = res & ~change;					\
 	new |= (val & change);					\
-	write_c0_##name(new);					\
+	write_##name(new);					\
 								\
 	return res;						\
 }
 
+/*
+ * Manipulate bits in a c0 register.
+ */
+#define __BUILD_SET_C0(name)	__BUILD_SET_COMMON(c0_##name)
+
 __BUILD_SET_C0(status)
 __BUILD_SET_C0(cause)
 __BUILD_SET_C0(config)
@@ -2050,6 +2622,11 @@ __BUILD_SET_C0(intcontrol)
 __BUILD_SET_C0(intctl)
 __BUILD_SET_C0(srsmap)
 __BUILD_SET_C0(pagegrain)
+__BUILD_SET_C0(guestctl0)
+__BUILD_SET_C0(guestctl0ext)
+__BUILD_SET_C0(guestctl1)
+__BUILD_SET_C0(guestctl2)
+__BUILD_SET_C0(guestctl3)
 __BUILD_SET_C0(brcm_config_0)
 __BUILD_SET_C0(brcm_bus_pll)
 __BUILD_SET_C0(brcm_reset)
@@ -2059,12 +2636,21 @@ __BUILD_SET_C0(brcm_config)
 __BUILD_SET_C0(brcm_mode)
 
 /*
+ * Manipulate bits in a guest c0 register.
+ */
+#define __BUILD_SET_GC0(name)	__BUILD_SET_COMMON(gc0_##name)
+
+__BUILD_SET_GC0(status)
+__BUILD_SET_GC0(cause)
+__BUILD_SET_GC0(ebase)
+
+/*
  * Return low 10 bits of ebase.
  * Note that under KVM (MIPSVZ) this returns vcpu id.
  */
 static inline unsigned int get_ebase_cpunum(void)
 {
-	return read_c0_ebase() & 0x3ff;
+	return read_c0_ebase() & MIPS_EBASE_CPUNUM;
 }
 
 #endif /* !__ASSEMBLY__ */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/mmu_context.h linux-libre-4.7-gnu/arch/mips/include/asm/mmu_context.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/mmu_context.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/mmu_context.h	2016-07-24 15:23:50.000000000 -0400
@@ -65,37 +65,32 @@ extern unsigned long pgd_current[];
 	back_to_back_c0_hazard();					\
 	TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir)
 #endif /* CONFIG_MIPS_PGD_C0_CONTEXT*/
-#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
-
-#define ASID_INC	0x40
-#define ASID_MASK	0xfc0
-
-#elif defined(CONFIG_CPU_R8000)
 
-#define ASID_INC	0x10
-#define ASID_MASK	0xff0
-
-#else /* FIXME: not correct for R6000 */
+/*
+ *  All unused by hardware upper bits will be considered
+ *  as a software asid extension.
+ */
+static unsigned long asid_version_mask(unsigned int cpu)
+{
+	unsigned long asid_mask = cpu_asid_mask(&cpu_data[cpu]);
 
-#define ASID_INC	0x1
-#define ASID_MASK	0xff
+	return ~(asid_mask | (asid_mask - 1));
+}
 
-#endif
+static unsigned long asid_first_version(unsigned int cpu)
+{
+	return ~asid_version_mask(cpu) + 1;
+}
 
 #define cpu_context(cpu, mm)	((mm)->context.asid[cpu])
-#define cpu_asid(cpu, mm)	(cpu_context((cpu), (mm)) & ASID_MASK)
 #define asid_cache(cpu)		(cpu_data[cpu].asid_cache)
+#define cpu_asid(cpu, mm) \
+	(cpu_context((cpu), (mm)) & cpu_asid_mask(&cpu_data[cpu]))
 
 static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 {
 }
 
-/*
- *  All unused by hardware upper bits will be considered
- *  as a software asid extension.
- */
-#define ASID_VERSION_MASK  ((unsigned long)~(ASID_MASK|(ASID_MASK-1)))
-#define ASID_FIRST_VERSION ((unsigned long)(~ASID_VERSION_MASK) + 1)
 
 /* Normal, classic MIPS get_new_mmu_context */
 static inline void
@@ -104,7 +99,7 @@ get_new_mmu_context(struct mm_struct *mm
 	extern void kvm_local_flush_tlb_all(void);
 	unsigned long asid = asid_cache(cpu);
 
-	if (! ((asid += ASID_INC) & ASID_MASK) ) {
+	if (!((asid += cpu_asid_inc()) & cpu_asid_mask(&cpu_data[cpu]))) {
 		if (cpu_has_vtag_icache)
 			flush_icache_all();
 #ifdef CONFIG_KVM
@@ -113,7 +108,7 @@ get_new_mmu_context(struct mm_struct *mm
 		local_flush_tlb_all();	/* start new asid cycle */
 #endif
 		if (!asid)		/* fix version if needed */
-			asid = ASID_FIRST_VERSION;
+			asid = asid_first_version(cpu);
 	}
 
 	cpu_context(cpu, mm) = asid_cache(cpu) = asid;
@@ -145,7 +140,7 @@ static inline void switch_mm(struct mm_s
 
 	htw_stop();
 	/* Check if our ASID is of an older version and thus invalid */
-	if ((cpu_context(cpu, next) ^ asid_cache(cpu)) & ASID_VERSION_MASK)
+	if ((cpu_context(cpu, next) ^ asid_cache(cpu)) & asid_version_mask(cpu))
 		get_new_mmu_context(next, cpu);
 	write_c0_entryhi(cpu_asid(cpu, next));
 	TLBMISS_HANDLER_SETUP_PGD(next->pgd);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/msa.h linux-libre-4.7-gnu/arch/mips/include/asm/msa.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/msa.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/msa.h	2016-07-24 15:23:50.000000000 -0400
@@ -147,6 +147,19 @@ static inline void restore_msa(struct ta
 		_restore_msa(t);
 }
 
+static inline void init_msa_upper(void)
+{
+	/*
+	 * Check cpu_has_msa only if it's a constant. This will allow the
+	 * compiler to optimise out code for CPUs without MSA without adding
+	 * an extra redundant check for CPUs with MSA.
+	 */
+	if (__builtin_constant_p(cpu_has_msa) && !cpu_has_msa)
+		return;
+
+	_init_msa_upper();
+}
+
 #ifdef TOOLCHAIN_SUPPORTS_MSA
 
 #define __BUILD_MSA_CTL_REG(name, cs)				\
@@ -179,13 +192,6 @@ static inline void write_msa_##name(unsi
  * allow compilation with toolchains that do not support MSA. Once all
  * toolchains in use support MSA these can be removed.
  */
-#ifdef CONFIG_CPU_MICROMIPS
-#define CFC_MSA_INSN	0x587e0056
-#define CTC_MSA_INSN	0x583e0816
-#else
-#define CFC_MSA_INSN	0x787e0059
-#define CTC_MSA_INSN	0x783e0819
-#endif
 
 #define __BUILD_MSA_CTL_REG(name, cs)				\
 static inline unsigned int read_msa_##name(void)		\
@@ -194,11 +200,12 @@ static inline unsigned int read_msa_##na
 	__asm__ __volatile__(					\
 	"	.set	push\n"					\
 	"	.set	noat\n"					\
-	"	.insn\n"					\
-	"	.word	%1 | (" #cs " << 11)\n"			\
+	"	# cfcmsa $1, $%1\n"				\
+	_ASM_INSN_IF_MIPS(0x787e0059 | %1 << 11)		\
+	_ASM_INSN32_IF_MM(0x587e0056 | %1 << 11)		\
 	"	move	%0, $1\n"				\
 	"	.set	pop\n"					\
-	: "=r"(reg) : "i"(CFC_MSA_INSN));			\
+	: "=r"(reg) : "i"(cs));					\
 	return reg;						\
 }								\
 								\
@@ -208,10 +215,11 @@ static inline void write_msa_##name(unsi
 	"	.set	push\n"					\
 	"	.set	noat\n"					\
 	"	move	$1, %0\n"				\
-	"	.insn\n"					\
-	"	.word	%1 | (" #cs " << 6)\n"			\
+	"	# ctcmsa $%1, $1\n"				\
+	_ASM_INSN_IF_MIPS(0x783e0819 | %1 << 6)			\
+	_ASM_INSN32_IF_MM(0x583e0816 | %1 << 6)			\
 	"	.set	pop\n"					\
-	: : "r"(val), "i"(CTC_MSA_INSN));			\
+	: : "r"(val), "i"(cs));					\
 }
 
 #endif /* !TOOLCHAIN_SUPPORTS_MSA */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/octeon/cvmx-bootinfo.h linux-libre-4.7-gnu/arch/mips/include/asm/octeon/cvmx-bootinfo.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/octeon/cvmx-bootinfo.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/octeon/cvmx-bootinfo.h	2016-07-24 15:23:50.000000000 -0400
@@ -32,6 +32,8 @@
 #ifndef __CVMX_BOOTINFO_H__
 #define __CVMX_BOOTINFO_H__
 
+#include "cvmx-coremask.h"
+
 /*
  * Current major and minor versions of the CVMX bootinfo block that is
  * passed from the bootloader to the application.  This is versioned
@@ -39,7 +41,7 @@
  * versions.
  */
 #define CVMX_BOOTINFO_MAJ_VER 1
-#define CVMX_BOOTINFO_MIN_VER 3
+#define CVMX_BOOTINFO_MIN_VER 4
 
 #if (CVMX_BOOTINFO_MAJ_VER == 1)
 #define CVMX_BOOTINFO_OCTEON_SERIAL_LEN 20
@@ -124,6 +126,13 @@ struct cvmx_bootinfo {
 	 */
 	uint64_t fdt_addr;
 #endif
+#if (CVMX_BOOTINFO_MIN_VER >= 4)
+	/*
+	 * Coremask used for processors with more than 32 cores
+	 * or with OCI.  This replaces core_mask.
+	 */
+	struct cvmx_coremask ext_core_mask;
+#endif
 #else				/* __BIG_ENDIAN */
 	/*
 	 * Little-Endian: When the CPU mode is switched to
@@ -177,6 +186,9 @@ struct cvmx_bootinfo {
 #if (CVMX_BOOTINFO_MIN_VER >= 3)
 	uint64_t fdt_addr;
 #endif
+#if (CVMX_BOOTINFO_MIN_VER >= 4)
+	struct cvmx_coremask ext_core_mask;
+#endif
 #endif
 };
 
@@ -388,7 +400,7 @@ static inline const char *cvmx_board_typ
 		ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_KONTRON_S1901)
 		ENUM_BRD_TYPE_CASE(CVMX_BOARD_TYPE_CUST_PRIVATE_MAX)
 	}
-	return "Unsupported Board";
+	return NULL;
 }
 
 #define ENUM_CHIP_TYPE_CASE(x) \
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/octeon/cvmx-ciu3-defs.h linux-libre-4.7-gnu/arch/mips/include/asm/octeon/cvmx-ciu3-defs.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/octeon/cvmx-ciu3-defs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/mips/include/asm/octeon/cvmx-ciu3-defs.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,353 @@
+/*
+ * Copyright (c) 2003-2016 Cavium Inc.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ */
+
+#ifndef __CVMX_CIU3_DEFS_H__
+#define __CVMX_CIU3_DEFS_H__
+
+#define CVMX_CIU3_FUSE CVMX_ADD_IO_SEG(0x00010100000001A0ull)
+#define CVMX_CIU3_BIST CVMX_ADD_IO_SEG(0x00010100000001C0ull)
+#define CVMX_CIU3_CONST CVMX_ADD_IO_SEG(0x0001010000000220ull)
+#define CVMX_CIU3_CTL CVMX_ADD_IO_SEG(0x00010100000000E0ull)
+#define CVMX_CIU3_DESTX_IO_INT(offset) (CVMX_ADD_IO_SEG(0x0001010000210000ull) + ((offset) & 7) * 8)
+#define CVMX_CIU3_DESTX_PP_INT(offset) (CVMX_ADD_IO_SEG(0x0001010000200000ull) + ((offset) & 255) * 8)
+#define CVMX_CIU3_GSTOP CVMX_ADD_IO_SEG(0x0001010000000140ull)
+#define CVMX_CIU3_IDTX_CTL(offset) (CVMX_ADD_IO_SEG(0x0001010000110000ull) + ((offset) & 255) * 8)
+#define CVMX_CIU3_IDTX_IO(offset) (CVMX_ADD_IO_SEG(0x0001010000130000ull) + ((offset) & 255) * 8)
+#define CVMX_CIU3_IDTX_PPX(offset, block_id) (CVMX_ADD_IO_SEG(0x0001010000120000ull) + ((block_id) & 255) * 0x20ull)
+#define CVMX_CIU3_INTR_RAM_ECC_CTL CVMX_ADD_IO_SEG(0x0001010000000260ull)
+#define CVMX_CIU3_INTR_RAM_ECC_ST CVMX_ADD_IO_SEG(0x0001010000000280ull)
+#define CVMX_CIU3_INTR_READY CVMX_ADD_IO_SEG(0x00010100000002A0ull)
+#define CVMX_CIU3_INTR_SLOWDOWN CVMX_ADD_IO_SEG(0x0001010000000240ull)
+#define CVMX_CIU3_ISCX_CTL(offset) (CVMX_ADD_IO_SEG(0x0001010080000000ull) + ((offset) & 1048575) * 8)
+#define CVMX_CIU3_ISCX_W1C(offset) (CVMX_ADD_IO_SEG(0x0001010090000000ull) + ((offset) & 1048575) * 8)
+#define CVMX_CIU3_ISCX_W1S(offset) (CVMX_ADD_IO_SEG(0x00010100A0000000ull) + ((offset) & 1048575) * 8)
+#define CVMX_CIU3_NMI CVMX_ADD_IO_SEG(0x0001010000000160ull)
+#define CVMX_CIU3_SISCX(offset) (CVMX_ADD_IO_SEG(0x0001010000220000ull) + ((offset) & 255) * 8)
+#define CVMX_CIU3_TIMX(offset) (CVMX_ADD_IO_SEG(0x0001010000010000ull) + ((offset) & 15) * 8)
+
+union cvmx_ciu3_bist {
+	uint64_t u64;
+	struct cvmx_ciu3_bist_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+	uint64_t reserved_9_63                : 55;
+	uint64_t bist                         : 9;
+#else
+	uint64_t bist                         : 9;
+	uint64_t reserved_9_63                : 55;
+#endif
+	} s;
+};
+
+union cvmx_ciu3_const {
+	uint64_t u64;
+	struct cvmx_ciu3_const_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+	uint64_t dests_io                     : 16;
+	uint64_t pintsn                       : 16;
+	uint64_t dests_pp                     : 16;
+	uint64_t idt                          : 16;
+#else
+	uint64_t idt                          : 16;
+	uint64_t dests_pp                     : 16;
+	uint64_t pintsn                       : 16;
+	uint64_t dests_io                     : 16;
+#endif
+	} s;
+};
+
+union cvmx_ciu3_ctl {
+	uint64_t u64;
+	struct cvmx_ciu3_ctl_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+	uint64_t reserved_5_63                : 59;
+	uint64_t mcd_sel                      : 2;
+	uint64_t iscmem_le                    : 1;
+	uint64_t seq_dis                      : 1;
+	uint64_t cclk_dis                     : 1;
+#else
+	uint64_t cclk_dis                     : 1;
+	uint64_t seq_dis                      : 1;
+	uint64_t iscmem_le                    : 1;
+	uint64_t mcd_sel                      : 2;
+	uint64_t reserved_5_63                : 59;
+#endif
+	} s;
+};
+
+union cvmx_ciu3_destx_io_int {
+	uint64_t u64;
+	struct cvmx_ciu3_destx_io_int_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+	uint64_t reserved_52_63               : 12;
+	uint64_t intsn                        : 20;
+	uint64_t reserved_10_31               : 22;
+	uint64_t intidt                       : 8;
+	uint64_t newint                       : 1;
+	uint64_t intr                         : 1;
+#else
+	uint64_t intr                         : 1;
+	uint64_t newint                       : 1;
+	uint64_t intidt                       : 8;
+	uint64_t reserved_10_31               : 22;
+	uint64_t intsn                        : 20;
+	uint64_t reserved_52_63               : 12;
+#endif
+	} s;
+};
+
+union cvmx_ciu3_destx_pp_int {
+	uint64_t u64;
+	struct cvmx_ciu3_destx_pp_int_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+	uint64_t reserved_52_63               : 12;
+	uint64_t intsn                        : 20;
+	uint64_t reserved_10_31               : 22;
+	uint64_t intidt                       : 8;
+	uint64_t newint                       : 1;
+	uint64_t intr                         : 1;
+#else
+	uint64_t intr                         : 1;
+	uint64_t newint                       : 1;
+	uint64_t intidt                       : 8;
+	uint64_t reserved_10_31               : 22;
+	uint64_t intsn                        : 20;
+	uint64_t reserved_52_63               : 12;
+#endif
+	} s;
+};
+
+union cvmx_ciu3_gstop {
+	uint64_t u64;
+	struct cvmx_ciu3_gstop_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+	uint64_t reserved_1_63                : 63;
+	uint64_t gstop                        : 1;
+#else
+	uint64_t gstop                        : 1;
+	uint64_t reserved_1_63                : 63;
+#endif
+	} s;
+};
+
+union cvmx_ciu3_idtx_ctl {
+	uint64_t u64;
+	struct cvmx_ciu3_idtx_ctl_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+	uint64_t reserved_52_63               : 12;
+	uint64_t intsn                        : 20;
+	uint64_t reserved_4_31                : 28;
+	uint64_t intr                         : 1;
+	uint64_t newint                       : 1;
+	uint64_t ip_num                       : 2;
+#else
+	uint64_t ip_num                       : 2;
+	uint64_t newint                       : 1;
+	uint64_t intr                         : 1;
+	uint64_t reserved_4_31                : 28;
+	uint64_t intsn                        : 20;
+	uint64_t reserved_52_63               : 12;
+#endif
+	} s;
+};
+
+union cvmx_ciu3_idtx_io {
+	uint64_t u64;
+	struct cvmx_ciu3_idtx_io_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+	uint64_t reserved_5_63                : 59;
+	uint64_t io                           : 5;
+#else
+	uint64_t io                           : 5;
+	uint64_t reserved_5_63                : 59;
+#endif
+	} s;
+};
+
+union cvmx_ciu3_idtx_ppx {
+	uint64_t u64;
+	struct cvmx_ciu3_idtx_ppx_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+	uint64_t reserved_48_63               : 16;
+	uint64_t pp                           : 48;
+#else
+	uint64_t pp                           : 48;
+	uint64_t reserved_48_63               : 16;
+#endif
+	} s;
+};
+
+union cvmx_ciu3_intr_ram_ecc_ctl {
+	uint64_t u64;
+	struct cvmx_ciu3_intr_ram_ecc_ctl_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+	uint64_t reserved_3_63                : 61;
+	uint64_t flip_synd                    : 2;
+	uint64_t ecc_ena                      : 1;
+#else
+	uint64_t ecc_ena                      : 1;
+	uint64_t flip_synd                    : 2;
+	uint64_t reserved_3_63                : 61;
+#endif
+	} s;
+};
+
+union cvmx_ciu3_intr_ram_ecc_st {
+	uint64_t u64;
+	struct cvmx_ciu3_intr_ram_ecc_st_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+	uint64_t reserved_52_63               : 12;
+	uint64_t addr                         : 20;
+	uint64_t reserved_6_31                : 26;
+	uint64_t sisc_dbe                     : 1;
+	uint64_t sisc_sbe                     : 1;
+	uint64_t idt_dbe                      : 1;
+	uint64_t idt_sbe                      : 1;
+	uint64_t isc_dbe                      : 1;
+	uint64_t isc_sbe                      : 1;
+#else
+	uint64_t isc_sbe                      : 1;
+	uint64_t isc_dbe                      : 1;
+	uint64_t idt_sbe                      : 1;
+	uint64_t idt_dbe                      : 1;
+	uint64_t sisc_sbe                     : 1;
+	uint64_t sisc_dbe                     : 1;
+	uint64_t reserved_6_31                : 26;
+	uint64_t addr                         : 20;
+	uint64_t reserved_52_63               : 12;
+#endif
+	} s;
+};
+
+union cvmx_ciu3_intr_ready {
+	uint64_t u64;
+	struct cvmx_ciu3_intr_ready_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+	uint64_t reserved_46_63               : 18;
+	uint64_t index                        : 14;
+	uint64_t reserved_1_31                : 31;
+	uint64_t ready                        : 1;
+#else
+	uint64_t ready                        : 1;
+	uint64_t reserved_1_31                : 31;
+	uint64_t index                        : 14;
+	uint64_t reserved_46_63               : 18;
+#endif
+	} s;
+};
+
+union cvmx_ciu3_intr_slowdown {
+	uint64_t u64;
+	struct cvmx_ciu3_intr_slowdown_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+	uint64_t reserved_3_63                : 61;
+	uint64_t ctl                          : 3;
+#else
+	uint64_t ctl                          : 3;
+	uint64_t reserved_3_63                : 61;
+#endif
+	} s;
+};
+
+union cvmx_ciu3_iscx_ctl {
+	uint64_t u64;
+	struct cvmx_ciu3_iscx_ctl_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+	uint64_t reserved_24_63               : 40;
+	uint64_t idt                          : 8;
+	uint64_t imp                          : 1;
+	uint64_t reserved_2_14                : 13;
+	uint64_t en                           : 1;
+	uint64_t raw                          : 1;
+#else
+	uint64_t raw                          : 1;
+	uint64_t en                           : 1;
+	uint64_t reserved_2_14                : 13;
+	uint64_t imp                          : 1;
+	uint64_t idt                          : 8;
+	uint64_t reserved_24_63               : 40;
+#endif
+	} s;
+};
+
+union cvmx_ciu3_iscx_w1c {
+	uint64_t u64;
+	struct cvmx_ciu3_iscx_w1c_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+	uint64_t reserved_2_63                : 62;
+	uint64_t en                           : 1;
+	uint64_t raw                          : 1;
+#else
+	uint64_t raw                          : 1;
+	uint64_t en                           : 1;
+	uint64_t reserved_2_63                : 62;
+#endif
+	} s;
+};
+
+union cvmx_ciu3_iscx_w1s {
+	uint64_t u64;
+	struct cvmx_ciu3_iscx_w1s_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+	uint64_t reserved_2_63                : 62;
+	uint64_t en                           : 1;
+	uint64_t raw                          : 1;
+#else
+	uint64_t raw                          : 1;
+	uint64_t en                           : 1;
+	uint64_t reserved_2_63                : 62;
+#endif
+	} s;
+};
+
+union cvmx_ciu3_nmi {
+	uint64_t u64;
+	struct cvmx_ciu3_nmi_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+	uint64_t reserved_48_63               : 16;
+	uint64_t nmi                          : 48;
+#else
+	uint64_t nmi                          : 48;
+	uint64_t reserved_48_63               : 16;
+#endif
+	} s;
+};
+
+union cvmx_ciu3_siscx {
+	uint64_t u64;
+	struct cvmx_ciu3_siscx_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+	uint64_t en                           : 64;
+#else
+	uint64_t en                           : 64;
+#endif
+	} s;
+};
+
+union cvmx_ciu3_timx {
+	uint64_t u64;
+	struct cvmx_ciu3_timx_s {
+#ifdef __BIG_ENDIAN_BITFIELD
+	uint64_t reserved_37_63               : 27;
+	uint64_t one_shot                     : 1;
+	uint64_t len                          : 36;
+#else
+	uint64_t len                          : 36;
+	uint64_t one_shot                     : 1;
+	uint64_t reserved_37_63               : 27;
+#endif
+	} s;
+};
+
+#endif
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/octeon/cvmx-cmd-queue.h linux-libre-4.7-gnu/arch/mips/include/asm/octeon/cvmx-cmd-queue.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/octeon/cvmx-cmd-queue.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/octeon/cvmx-cmd-queue.h	2016-07-24 15:23:50.000000000 -0400
@@ -146,7 +146,7 @@ typedef struct {
  * This structure contains the global state of all command queues.
  * It is stored in a bootmem named block and shared by all
  * applications running on Octeon. Tickets are stored in a differnet
- * cahce line that queue information to reduce the contention on the
+ * cache line that queue information to reduce the contention on the
  * ll/sc used to get a ticket. If this is not the case, the update
  * of queue state causes the ll/sc to fail quite often.
  */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/octeon/cvmx-coremask.h linux-libre-4.7-gnu/arch/mips/include/asm/octeon/cvmx-coremask.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/octeon/cvmx-coremask.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/mips/include/asm/octeon/cvmx-coremask.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ *
+ * Copyright (c) 2016  Cavium Inc. (support@cavium.com).
+ *
+ */
+
+/*
+ * Module to support operations on bitmap of cores. Coremask can be used to
+ * select a specific core, a group of cores, or all available cores, for
+ * initialization and differentiation of roles within a single shared binary
+ * executable image.
+ *
+ * The core numbers used in this file are the same value as what is found in
+ * the COP0_EBASE register and the rdhwr 0 instruction.
+ *
+ * For the CN78XX and other multi-node environments the core numbers are not
+ * contiguous.  The core numbers for the CN78XX are as follows:
+ *
+ * Node 0:	Cores 0 - 47
+ * Node 1:	Cores 128 - 175
+ * Node 2:	Cores 256 - 303
+ * Node 3:	Cores 384 - 431
+ *
+ */
+
+#ifndef __CVMX_COREMASK_H__
+#define __CVMX_COREMASK_H__
+
+#define CVMX_MIPS_MAX_CORES 1024
+/* bits per holder */
+#define CVMX_COREMASK_ELTSZ 64
+
+/* cvmx_coremask_t's size in u64 */
+#define CVMX_COREMASK_BMPSZ (CVMX_MIPS_MAX_CORES / CVMX_COREMASK_ELTSZ)
+
+
+/* cvmx_coremask_t */
+struct cvmx_coremask {
+	u64 coremask_bitmap[CVMX_COREMASK_BMPSZ];
+};
+
+/*
+ * Is ``core'' set in the coremask?
+ */
+static inline bool cvmx_coremask_is_core_set(const struct cvmx_coremask *pcm,
+					    int core)
+{
+	int n, i;
+
+	n = core % CVMX_COREMASK_ELTSZ;
+	i = core / CVMX_COREMASK_ELTSZ;
+
+	return (pcm->coremask_bitmap[i] & ((u64)1 << n)) != 0;
+}
+
+/*
+ * Make a copy of a coremask
+ */
+static inline void cvmx_coremask_copy(struct cvmx_coremask *dest,
+				      const struct cvmx_coremask *src)
+{
+	memcpy(dest, src, sizeof(*dest));
+}
+
+/*
+ * Set the lower 64-bit of the coremask.
+ */
+static inline void cvmx_coremask_set64(struct cvmx_coremask *pcm,
+				       uint64_t coremask_64)
+{
+	pcm->coremask_bitmap[0] = coremask_64;
+}
+
+/*
+ * Clear ``core'' from the coremask.
+ */
+static inline void cvmx_coremask_clear_core(struct cvmx_coremask *pcm, int core)
+{
+	int n, i;
+
+	n = core % CVMX_COREMASK_ELTSZ;
+	i = core / CVMX_COREMASK_ELTSZ;
+	pcm->coremask_bitmap[i] &= ~(1ull << n);
+}
+
+#endif /* __CVMX_COREMASK_H__ */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/octeon/cvmx-fpa-defs.h linux-libre-4.7-gnu/arch/mips/include/asm/octeon/cvmx-fpa-defs.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/octeon/cvmx-fpa-defs.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/octeon/cvmx-fpa-defs.h	2016-07-24 15:23:50.000000000 -0400
@@ -66,6 +66,7 @@
 #define CVMX_FPA_WART_CTL (CVMX_ADD_IO_SEG(0x00011800280000D8ull))
 #define CVMX_FPA_WART_STATUS (CVMX_ADD_IO_SEG(0x00011800280000E0ull))
 #define CVMX_FPA_WQE_THRESHOLD (CVMX_ADD_IO_SEG(0x0001180028000468ull))
+#define CVMX_FPA_CLK_COUNT (CVMX_ADD_IO_SEG(0x00012800000000F0ull))
 
 union cvmx_fpa_addr_range_error {
 	uint64_t u64;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/octeon/cvmx.h linux-libre-4.7-gnu/arch/mips/include/asm/octeon/cvmx.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/octeon/cvmx.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/octeon/cvmx.h	2016-07-24 15:23:50.000000000 -0400
@@ -57,6 +57,7 @@ enum cvmx_mips_space {
 #include <asm/octeon/cvmx-sysinfo.h>
 
 #include <asm/octeon/cvmx-ciu-defs.h>
+#include <asm/octeon/cvmx-ciu3-defs.h>
 #include <asm/octeon/cvmx-gpio-defs.h>
 #include <asm/octeon/cvmx-iob-defs.h>
 #include <asm/octeon/cvmx-ipd-defs.h>
@@ -341,6 +342,21 @@ static inline unsigned int cvmx_get_core
 	return core_num;
 }
 
+/* Maximum # of bits to define core in node */
+#define CVMX_NODE_NO_SHIFT	7
+#define CVMX_NODE_MASK		0x3
+static inline unsigned int cvmx_get_node_num(void)
+{
+	unsigned int core_num = cvmx_get_core_num();
+
+	return (core_num >> CVMX_NODE_NO_SHIFT) & CVMX_NODE_MASK;
+}
+
+static inline unsigned int cvmx_get_local_core_num(void)
+{
+	return cvmx_get_core_num() & ((1 << CVMX_NODE_NO_SHIFT) - 1);
+}
+
 /**
  * Returns the number of bits set in the provided value.
  * Simple wrapper for POP instruction.
@@ -448,8 +464,15 @@ static inline uint64_t cvmx_get_cycle_gl
 /* Return the number of cores available in the chip */
 static inline uint32_t cvmx_octeon_num_cores(void)
 {
-	uint32_t ciu_fuse = (uint32_t) cvmx_read_csr(CVMX_CIU_FUSE) & 0xffff;
-	return cvmx_pop(ciu_fuse);
+	u64 ciu_fuse_reg;
+	u64 ciu_fuse;
+
+	if (OCTEON_IS_OCTEON3() && !OCTEON_IS_MODEL(OCTEON_CN70XX))
+		ciu_fuse_reg = CVMX_CIU3_FUSE;
+	else
+		ciu_fuse_reg = CVMX_CIU_FUSE;
+	ciu_fuse = cvmx_read_csr(ciu_fuse_reg);
+	return cvmx_dpop(ciu_fuse);
 }
 
 #endif /*  __CVMX_H__  */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/octeon/cvmx-helper-board.h linux-libre-4.7-gnu/arch/mips/include/asm/octeon/cvmx-helper-board.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/octeon/cvmx-helper-board.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/octeon/cvmx-helper-board.h	2016-07-24 15:23:50.000000000 -0400
@@ -94,7 +94,7 @@ extern int cvmx_helper_board_get_mii_add
  * @phy_addr:  The address of the PHY to program
  * @link_flags:
  *		    Flags to control autonegotiation.  Bit 0 is autonegotiation
- *		    enable/disable to maintain backware compatibility.
+ *		    enable/disable to maintain backward compatibility.
  * @link_info: Link speed to program. If the speed is zero and autonegotiation
  *		    is enabled, all possible negotiation speeds are advertised.
  *
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/octeon/cvmx-ipd.h linux-libre-4.7-gnu/arch/mips/include/asm/octeon/cvmx-ipd.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/octeon/cvmx-ipd.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/octeon/cvmx-ipd.h	2016-07-24 15:23:50.000000000 -0400
@@ -39,7 +39,7 @@
 
 enum cvmx_ipd_mode {
    CVMX_IPD_OPC_MODE_STT = 0LL,	  /* All blocks DRAM, not cached in L2 */
-   CVMX_IPD_OPC_MODE_STF = 1LL,	  /* All bloccks into  L2 */
+   CVMX_IPD_OPC_MODE_STF = 1LL,	  /* All blocks into  L2 */
    CVMX_IPD_OPC_MODE_STF1_STT = 2LL,   /* 1st block L2, rest DRAM */
    CVMX_IPD_OPC_MODE_STF2_STT = 3LL    /* 1st, 2nd blocks L2, rest DRAM */
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/octeon/cvmx-mio-defs.h linux-libre-4.7-gnu/arch/mips/include/asm/octeon/cvmx-mio-defs.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/octeon/cvmx-mio-defs.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/octeon/cvmx-mio-defs.h	2016-07-24 15:23:50.000000000 -0400
@@ -1481,7 +1481,9 @@ union cvmx_mio_fus_dat2 {
 	uint64_t u64;
 	struct cvmx_mio_fus_dat2_s {
 #ifdef __BIG_ENDIAN_BITFIELD
-		uint64_t reserved_48_63:16;
+		uint64_t reserved_59_63:5;
+		uint64_t run_platform:3;
+		uint64_t gbl_pwr_throttle:8;
 		uint64_t fus118:1;
 		uint64_t rom_info:10;
 		uint64_t power_limit:2;
@@ -1513,7 +1515,9 @@ union cvmx_mio_fus_dat2 {
 		uint64_t power_limit:2;
 		uint64_t rom_info:10;
 		uint64_t fus118:1;
-		uint64_t reserved_48_63:16;
+		uint64_t gbl_pwr_throttle:8;
+		uint64_t run_platform:3;
+		uint64_t reserved_59_63:5;
 #endif
 	} s;
 	struct cvmx_mio_fus_dat2_cn30xx {
@@ -1837,50 +1841,192 @@ union cvmx_mio_fus_dat2 {
 #endif
 	} cn68xx;
 	struct cvmx_mio_fus_dat2_cn68xx cn68xxp1;
+	struct cvmx_mio_fus_dat2_cn70xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+		uint64_t reserved_48_63:16;
+		uint64_t fus118:1;
+		uint64_t rom_info:10;
+		uint64_t power_limit:2;
+		uint64_t dorm_crypto:1;
+		uint64_t fus318:1;
+		uint64_t raid_en:1;
+		uint64_t reserved_31_29:3;
+		uint64_t nodfa_cp2:1;
+		uint64_t nomul:1;
+		uint64_t nocrypto:1;
+		uint64_t reserved_25_24:2;
+		uint64_t chip_id:8;
+		uint64_t reserved_15_0:16;
+#else
+		uint64_t reserved_15_0:16;
+		uint64_t chip_id:8;
+		uint64_t reserved_25_24:2;
+		uint64_t nocrypto:1;
+		uint64_t nomul:1;
+		uint64_t nodfa_cp2:1;
+		uint64_t reserved_31_29:3;
+		uint64_t raid_en:1;
+		uint64_t fus318:1;
+		uint64_t dorm_crypto:1;
+		uint64_t power_limit:2;
+		uint64_t rom_info:10;
+		uint64_t fus118:1;
+		uint64_t reserved_48_63:16;
+#endif
+	} cn70xx;
+	struct cvmx_mio_fus_dat2_cn70xx cn70xxp1;
+	struct cvmx_mio_fus_dat2_cn73xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+		uint64_t reserved_59_63:5;
+		uint64_t run_platform:3;
+		uint64_t gbl_pwr_throttle:8;
+		uint64_t fus118:1;
+		uint64_t rom_info:10;
+		uint64_t power_limit:2;
+		uint64_t dorm_crypto:1;
+		uint64_t fus318:1;
+		uint64_t raid_en:1;
+		uint64_t reserved_31_29:3;
+		uint64_t nodfa_cp2:1;
+		uint64_t nomul:1;
+		uint64_t nocrypto:1;
+		uint64_t reserved_25_24:2;
+		uint64_t chip_id:8;
+		uint64_t reserved_15_0:16;
+#else
+		uint64_t reserved_15_0:16;
+		uint64_t chip_id:8;
+		uint64_t reserved_25_24:2;
+		uint64_t nocrypto:1;
+		uint64_t nomul:1;
+		uint64_t nodfa_cp2:1;
+		uint64_t reserved_31_29:3;
+		uint64_t raid_en:1;
+		uint64_t fus318:1;
+		uint64_t dorm_crypto:1;
+		uint64_t power_limit:2;
+		uint64_t rom_info:10;
+		uint64_t fus118:1;
+		uint64_t gbl_pwr_throttle:8;
+		uint64_t run_platform:3;
+		uint64_t reserved_59_63:5;
+#endif
+	} cn73xx;
+	struct cvmx_mio_fus_dat2_cn78xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+		uint64_t reserved_59_63:5;
+		uint64_t run_platform:3;
+		uint64_t reserved_48_55:8;
+		uint64_t fus118:1;
+		uint64_t rom_info:10;
+		uint64_t power_limit:2;
+		uint64_t dorm_crypto:1;
+		uint64_t fus318:1;
+		uint64_t raid_en:1;
+		uint64_t reserved_31_29:3;
+		uint64_t nodfa_cp2:1;
+		uint64_t nomul:1;
+		uint64_t nocrypto:1;
+		uint64_t reserved_25_24:2;
+		uint64_t chip_id:8;
+		uint64_t reserved_0_15:16;
+#else
+		uint64_t reserved_0_15:16;
+		uint64_t chip_id:8;
+		uint64_t reserved_25_24:2;
+		uint64_t nocrypto:1;
+		uint64_t nomul:1;
+		uint64_t nodfa_cp2:1;
+		uint64_t reserved_31_29:3;
+		uint64_t raid_en:1;
+		uint64_t fus318:1;
+		uint64_t dorm_crypto:1;
+		uint64_t power_limit:2;
+		uint64_t rom_info:10;
+		uint64_t fus118:1;
+		uint64_t reserved_48_55:8;
+		uint64_t run_platform:3;
+		uint64_t reserved_59_63:5;
+#endif
+	} cn78xx;
+	struct cvmx_mio_fus_dat2_cn78xxp2 {
+#ifdef __BIG_ENDIAN_BITFIELD
+		uint64_t reserved_59_63:5;
+		uint64_t run_platform:3;
+		uint64_t gbl_pwr_throttle:8;
+		uint64_t fus118:1;
+		uint64_t rom_info:10;
+		uint64_t power_limit:2;
+		uint64_t dorm_crypto:1;
+		uint64_t fus318:1;
+		uint64_t raid_en:1;
+		uint64_t reserved_31_29:3;
+		uint64_t nodfa_cp2:1;
+		uint64_t nomul:1;
+		uint64_t nocrypto:1;
+		uint64_t reserved_25_24:2;
+		uint64_t chip_id:8;
+		uint64_t reserved_0_15:16;
+#else
+		uint64_t reserved_0_15:16;
+		uint64_t chip_id:8;
+		uint64_t reserved_25_24:2;
+		uint64_t nocrypto:1;
+		uint64_t nomul:1;
+		uint64_t nodfa_cp2:1;
+		uint64_t reserved_31_29:3;
+		uint64_t raid_en:1;
+		uint64_t fus318:1;
+		uint64_t dorm_crypto:1;
+		uint64_t power_limit:2;
+		uint64_t rom_info:10;
+		uint64_t fus118:1;
+		uint64_t gbl_pwr_throttle:8;
+		uint64_t run_platform:3;
+		uint64_t reserved_59_63:5;
+#endif
+	} cn78xxp2;
 	struct cvmx_mio_fus_dat2_cn61xx cnf71xx;
+	struct cvmx_mio_fus_dat2_cn73xx cnf75xx;
 };
 
 union cvmx_mio_fus_dat3 {
 	uint64_t u64;
 	struct cvmx_mio_fus_dat3_s {
 #ifdef __BIG_ENDIAN_BITFIELD
-		uint64_t reserved_58_63:6;
+		uint64_t ema0:6;
 		uint64_t pll_ctl:10;
 		uint64_t dfa_info_dte:3;
 		uint64_t dfa_info_clm:4;
-		uint64_t reserved_40_40:1;
-		uint64_t ema:2;
+		uint64_t pll_alt_matrix:1;
+		uint64_t reserved_38_39:2;
 		uint64_t efus_lck_rsv:1;
 		uint64_t efus_lck_man:1;
 		uint64_t pll_half_dis:1;
 		uint64_t l2c_crip:3;
-		uint64_t pll_div4:1;
-		uint64_t reserved_29_30:2;
-		uint64_t bar2_en:1;
+		uint64_t reserved_28_31:4;
 		uint64_t efus_lck:1;
 		uint64_t efus_ign:1;
 		uint64_t nozip:1;
 		uint64_t nodfa_dte:1;
-		uint64_t icache:24;
+		uint64_t reserved_0_23:24;
 #else
-		uint64_t icache:24;
+		uint64_t reserved_0_23:24;
 		uint64_t nodfa_dte:1;
 		uint64_t nozip:1;
 		uint64_t efus_ign:1;
 		uint64_t efus_lck:1;
-		uint64_t bar2_en:1;
-		uint64_t reserved_29_30:2;
-		uint64_t pll_div4:1;
+		uint64_t reserved_28_31:4;
 		uint64_t l2c_crip:3;
 		uint64_t pll_half_dis:1;
 		uint64_t efus_lck_man:1;
 		uint64_t efus_lck_rsv:1;
-		uint64_t ema:2;
-		uint64_t reserved_40_40:1;
+		uint64_t reserved_38_39:2;
+		uint64_t pll_alt_matrix:1;
 		uint64_t dfa_info_clm:4;
 		uint64_t dfa_info_dte:3;
 		uint64_t pll_ctl:10;
-		uint64_t reserved_58_63:6;
+		uint64_t ema0:6;
 #endif
 	} s;
 	struct cvmx_mio_fus_dat3_cn30xx {
@@ -2022,7 +2168,239 @@ union cvmx_mio_fus_dat3 {
 	struct cvmx_mio_fus_dat3_cn61xx cn66xx;
 	struct cvmx_mio_fus_dat3_cn61xx cn68xx;
 	struct cvmx_mio_fus_dat3_cn61xx cn68xxp1;
+	struct cvmx_mio_fus_dat3_cn70xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+		uint64_t ema0:6;
+		uint64_t pll_ctl:10;
+		uint64_t dfa_info_dte:3;
+		uint64_t dfa_info_clm:4;
+		uint64_t pll_alt_matrix:1;
+		uint64_t pll_bwadj_denom:2;
+		uint64_t efus_lck_rsv:1;
+		uint64_t efus_lck_man:1;
+		uint64_t pll_half_dis:1;
+		uint64_t l2c_crip:3;
+		uint64_t use_int_refclk:1;
+		uint64_t zip_info:2;
+		uint64_t bar2_sz_conf:1;
+		uint64_t efus_lck:1;
+		uint64_t efus_ign:1;
+		uint64_t nozip:1;
+		uint64_t nodfa_dte:1;
+		uint64_t ema1:6;
+		uint64_t reserved_0_17:18;
+#else
+		uint64_t reserved_0_17:18;
+		uint64_t ema1:6;
+		uint64_t nodfa_dte:1;
+		uint64_t nozip:1;
+		uint64_t efus_ign:1;
+		uint64_t efus_lck:1;
+		uint64_t bar2_sz_conf:1;
+		uint64_t zip_info:2;
+		uint64_t use_int_refclk:1;
+		uint64_t l2c_crip:3;
+		uint64_t pll_half_dis:1;
+		uint64_t efus_lck_man:1;
+		uint64_t efus_lck_rsv:1;
+		uint64_t pll_bwadj_denom:2;
+		uint64_t pll_alt_matrix:1;
+		uint64_t dfa_info_clm:4;
+		uint64_t dfa_info_dte:3;
+		uint64_t pll_ctl:10;
+		uint64_t ema0:6;
+#endif
+	} cn70xx;
+	struct cvmx_mio_fus_dat3_cn70xxp1 {
+#ifdef __BIG_ENDIAN_BITFIELD
+		uint64_t ema0:6;
+		uint64_t pll_ctl:10;
+		uint64_t dfa_info_dte:3;
+		uint64_t dfa_info_clm:4;
+		uint64_t reserved_38_40:3;
+		uint64_t efus_lck_rsv:1;
+		uint64_t efus_lck_man:1;
+		uint64_t pll_half_dis:1;
+		uint64_t l2c_crip:3;
+		uint64_t reserved_31_31:1;
+		uint64_t zip_info:2;
+		uint64_t bar2_sz_conf:1;
+		uint64_t efus_lck:1;
+		uint64_t efus_ign:1;
+		uint64_t nozip:1;
+		uint64_t nodfa_dte:1;
+		uint64_t ema1:6;
+		uint64_t reserved_0_17:18;
+#else
+		uint64_t reserved_0_17:18;
+		uint64_t ema1:6;
+		uint64_t nodfa_dte:1;
+		uint64_t nozip:1;
+		uint64_t efus_ign:1;
+		uint64_t efus_lck:1;
+		uint64_t bar2_sz_conf:1;
+		uint64_t zip_info:2;
+		uint64_t reserved_31_31:1;
+		uint64_t l2c_crip:3;
+		uint64_t pll_half_dis:1;
+		uint64_t efus_lck_man:1;
+		uint64_t efus_lck_rsv:1;
+		uint64_t reserved_38_40:3;
+		uint64_t dfa_info_clm:4;
+		uint64_t dfa_info_dte:3;
+		uint64_t pll_ctl:10;
+		uint64_t ema0:6;
+#endif
+	} cn70xxp1;
+	struct cvmx_mio_fus_dat3_cn73xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+		uint64_t ema0:6;
+		uint64_t pll_ctl:10;
+		uint64_t dfa_info_dte:3;
+		uint64_t dfa_info_clm:4;
+		uint64_t pll_alt_matrix:1;
+		uint64_t pll_bwadj_denom:2;
+		uint64_t efus_lck_rsv:1;
+		uint64_t efus_lck_man:1;
+		uint64_t pll_half_dis:1;
+		uint64_t l2c_crip:3;
+		uint64_t use_int_refclk:1;
+		uint64_t zip_info:2;
+		uint64_t bar2_sz_conf:1;
+		uint64_t efus_lck:1;
+		uint64_t efus_ign:1;
+		uint64_t nozip:1;
+		uint64_t nodfa_dte:1;
+		uint64_t ema1:6;
+		uint64_t nohna_dte:1;
+		uint64_t hna_info_dte:3;
+		uint64_t hna_info_clm:4;
+		uint64_t reserved_9_9:1;
+		uint64_t core_pll_mul:5;
+		uint64_t pnr_pll_mul:4;
+#else
+		uint64_t pnr_pll_mul:4;
+		uint64_t core_pll_mul:5;
+		uint64_t reserved_9_9:1;
+		uint64_t hna_info_clm:4;
+		uint64_t hna_info_dte:3;
+		uint64_t nohna_dte:1;
+		uint64_t ema1:6;
+		uint64_t nodfa_dte:1;
+		uint64_t nozip:1;
+		uint64_t efus_ign:1;
+		uint64_t efus_lck:1;
+		uint64_t bar2_sz_conf:1;
+		uint64_t zip_info:2;
+		uint64_t use_int_refclk:1;
+		uint64_t l2c_crip:3;
+		uint64_t pll_half_dis:1;
+		uint64_t efus_lck_man:1;
+		uint64_t efus_lck_rsv:1;
+		uint64_t pll_bwadj_denom:2;
+		uint64_t pll_alt_matrix:1;
+		uint64_t dfa_info_clm:4;
+		uint64_t dfa_info_dte:3;
+		uint64_t pll_ctl:10;
+		uint64_t ema0:6;
+#endif
+	} cn73xx;
+	struct cvmx_mio_fus_dat3_cn78xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+		uint64_t ema0:6;
+		uint64_t pll_ctl:10;
+		uint64_t dfa_info_dte:3;
+		uint64_t dfa_info_clm:4;
+		uint64_t reserved_38_40:3;
+		uint64_t efus_lck_rsv:1;
+		uint64_t efus_lck_man:1;
+		uint64_t pll_half_dis:1;
+		uint64_t l2c_crip:3;
+		uint64_t reserved_31_31:1;
+		uint64_t zip_info:2;
+		uint64_t bar2_sz_conf:1;
+		uint64_t efus_lck:1;
+		uint64_t efus_ign:1;
+		uint64_t nozip:1;
+		uint64_t nodfa_dte:1;
+		uint64_t ema1:6;
+		uint64_t nohna_dte:1;
+		uint64_t hna_info_dte:3;
+		uint64_t hna_info_clm:4;
+		uint64_t reserved_0_9:10;
+#else
+		uint64_t reserved_0_9:10;
+		uint64_t hna_info_clm:4;
+		uint64_t hna_info_dte:3;
+		uint64_t nohna_dte:1;
+		uint64_t ema1:6;
+		uint64_t nodfa_dte:1;
+		uint64_t nozip:1;
+		uint64_t efus_ign:1;
+		uint64_t efus_lck:1;
+		uint64_t bar2_sz_conf:1;
+		uint64_t zip_info:2;
+		uint64_t reserved_31_31:1;
+		uint64_t l2c_crip:3;
+		uint64_t pll_half_dis:1;
+		uint64_t efus_lck_man:1;
+		uint64_t efus_lck_rsv:1;
+		uint64_t reserved_38_40:3;
+		uint64_t dfa_info_clm:4;
+		uint64_t dfa_info_dte:3;
+		uint64_t pll_ctl:10;
+		uint64_t ema0:6;
+#endif
+	} cn78xx;
+	struct cvmx_mio_fus_dat3_cn73xx cn78xxp2;
 	struct cvmx_mio_fus_dat3_cn61xx cnf71xx;
+	struct cvmx_mio_fus_dat3_cnf75xx {
+#ifdef __BIG_ENDIAN_BITFIELD
+		uint64_t ema0:6;
+		uint64_t pll_ctl:10;
+		uint64_t dfa_info_dte:3;
+		uint64_t dfa_info_clm:4;
+		uint64_t pll_alt_matrix:1;
+		uint64_t pll_bwadj_denom:2;
+		uint64_t efus_lck_rsv:1;
+		uint64_t efus_lck_man:1;
+		uint64_t pll_half_dis:1;
+		uint64_t l2c_crip:3;
+		uint64_t use_int_refclk:1;
+		uint64_t zip_info:2;
+		uint64_t bar2_sz_conf:1;
+		uint64_t efus_lck:1;
+		uint64_t efus_ign:1;
+		uint64_t nozip:1;
+		uint64_t nodfa_dte:1;
+		uint64_t ema1:6;
+		uint64_t reserved_9_17:9;
+		uint64_t core_pll_mul:5;
+		uint64_t pnr_pll_mul:4;
+#else
+		uint64_t pnr_pll_mul:4;
+		uint64_t core_pll_mul:5;
+		uint64_t reserved_9_17:9;
+		uint64_t ema1:6;
+		uint64_t nodfa_dte:1;
+		uint64_t nozip:1;
+		uint64_t efus_ign:1;
+		uint64_t efus_lck:1;
+		uint64_t bar2_sz_conf:1;
+		uint64_t zip_info:2;
+		uint64_t use_int_refclk:1;
+		uint64_t l2c_crip:3;
+		uint64_t pll_half_dis:1;
+		uint64_t efus_lck_man:1;
+		uint64_t efus_lck_rsv:1;
+		uint64_t pll_bwadj_denom:2;
+		uint64_t pll_alt_matrix:1;
+		uint64_t dfa_info_clm:4;
+		uint64_t dfa_info_dte:3;
+		uint64_t pll_ctl:10;
+		uint64_t ema0:6;
+#endif
+	} cnf75xx;
 };
 
 union cvmx_mio_fus_ema {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/octeon/cvmx-pow.h linux-libre-4.7-gnu/arch/mips/include/asm/octeon/cvmx-pow.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/octeon/cvmx-pow.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/octeon/cvmx-pow.h	2016-07-24 15:23:50.000000000 -0400
@@ -2051,7 +2051,7 @@ static inline void cvmx_pow_tag_sw_desch
 }
 
 /**
- * Descchedules the current work queue entry.
+ * Deschedules the current work queue entry.
  *
  * @no_sched: no schedule flag value to be set on the work queue
  *	      entry.  If this is set the entry will not be
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/octeon/cvmx-sysinfo.h linux-libre-4.7-gnu/arch/mips/include/asm/octeon/cvmx-sysinfo.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/octeon/cvmx-sysinfo.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/octeon/cvmx-sysinfo.h	2016-07-24 15:23:50.000000000 -0400
@@ -4,7 +4,7 @@
  * Contact: support@caviumnetworks.com
  * This file is part of the OCTEON SDK
  *
- * Copyright (c) 2003-2008 Cavium Networks
+ * Copyright (c) 2003-2016 Cavium, Inc.
  *
  * This file is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License, Version 2, as
@@ -32,6 +32,8 @@
 #ifndef __CVMX_SYSINFO_H__
 #define __CVMX_SYSINFO_H__
 
+#include "cvmx-coremask.h"
+
 #define OCTEON_SERIAL_LEN 20
 /**
  * Structure describing application specific information.
@@ -50,8 +52,7 @@ struct cvmx_sysinfo {
 	uint64_t system_dram_size;
 
 	/* ptr to memory descriptor block */
-	void *phy_mem_desc_ptr;
-
+	uint64_t phy_mem_desc_addr;
 
 	/* Application image specific variables */
 	/* stack top address (virtual) */
@@ -63,7 +64,7 @@ struct cvmx_sysinfo {
 	/* heap size in bytes */
 	uint32_t heap_size;
 	/* coremask defining cores running application */
-	uint32_t core_mask;
+	struct cvmx_coremask core_mask;
 	/* Deprecated, use cvmx_coremask_first_core() to select init core */
 	uint32_t init_core;
 
@@ -121,32 +122,4 @@ struct cvmx_sysinfo {
 
 extern struct cvmx_sysinfo *cvmx_sysinfo_get(void);
 
-/**
- * This function is used in non-simple executive environments (such as
- * Linux kernel, u-boot, etc.)	to configure the minimal fields that
- * are required to use simple executive files directly.
- *
- * Locking (if required) must be handled outside of this
- * function
- *
- * @phy_mem_desc_ptr: Pointer to global physical memory descriptor
- *		     (bootmem descriptor) @board_type: Octeon board
- *		     type enumeration
- *
- * @board_rev_major:
- *		     Board major revision
- * @board_rev_minor:
- *		     Board minor revision
- * @cpu_clock_hz:
- *		     CPU clock freqency in hertz
- *
- * Returns 0: Failure
- *	   1: success
- */
-extern int cvmx_sysinfo_minimal_initialize(void *phy_mem_desc_ptr,
-					   uint16_t board_type,
-					   uint8_t board_rev_major,
-					   uint8_t board_rev_minor,
-					   uint32_t cpu_clock_hz);
-
 #endif /* __CVMX_SYSINFO_H__ */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/octeon/octeon-feature.h linux-libre-4.7-gnu/arch/mips/include/asm/octeon/octeon-feature.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/octeon/octeon-feature.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/octeon/octeon-feature.h	2016-07-24 15:23:50.000000000 -0400
@@ -81,6 +81,10 @@ enum octeon_feature {
 	OCTEON_FEATURE_HFA,
 	OCTEON_FEATURE_DFM,
 	OCTEON_FEATURE_CIU2,
+	OCTEON_FEATURE_CIU3,
+	/* Octeon has FPA first seen on 78XX */
+	OCTEON_FEATURE_FPA3,
+	OCTEON_FEATURE_FAU,
 	OCTEON_MAX_FEATURE
 };
 
@@ -110,7 +114,7 @@ static inline int octeon_has_crypto(void
  * Returns Non zero if the feature exists. Zero if the feature does not
  *	   exist.
  */
-static inline int octeon_has_feature(enum octeon_feature feature)
+static inline bool octeon_has_feature(enum octeon_feature feature)
 {
 	switch (feature) {
 	case OCTEON_FEATURE_SAAD:
@@ -122,7 +126,7 @@ static inline int octeon_has_feature(enu
 			fus_2.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT2);
 			return !fus_2.s.nocrypto && !fus_2.s.nomul && fus_2.s.dorm_crypto;
 		} else {
-			return 0;
+			return false;
 		}
 
 	case OCTEON_FEATURE_PCIE:
@@ -190,11 +194,20 @@ static inline int octeon_has_feature(enu
 
 	case OCTEON_FEATURE_CIU2:
 		return OCTEON_IS_MODEL(OCTEON_CN68XX);
+	case OCTEON_FEATURE_CIU3:
+	case OCTEON_FEATURE_FPA3:
+		return OCTEON_IS_MODEL(OCTEON_CN78XX)
+			|| OCTEON_IS_MODEL(OCTEON_CNF75XX)
+			|| OCTEON_IS_MODEL(OCTEON_CN73XX);
+	case OCTEON_FEATURE_FAU:
+		return !(OCTEON_IS_MODEL(OCTEON_CN78XX)
+			 || OCTEON_IS_MODEL(OCTEON_CNF75XX)
+			 || OCTEON_IS_MODEL(OCTEON_CN73XX));
 
 	default:
 		break;
 	}
-	return 0;
+	return false;
 }
 
 #endif /* __OCTEON_FEATURE_H__ */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/octeon/octeon.h linux-libre-4.7-gnu/arch/mips/include/asm/octeon/octeon.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/octeon/octeon.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/octeon/octeon.h	2016-07-24 15:23:50.000000000 -0400
@@ -299,6 +299,31 @@ static inline void octeon_npi_write32(ui
 	cvmx_read64_uint32(address ^ 4);
 }
 
+#ifdef CONFIG_SMP
+void octeon_setup_smp(void);
+#else
+static inline void octeon_setup_smp(void) {}
+#endif
+
+struct irq_domain;
+struct device_node;
+struct irq_data;
+struct irq_chip;
+void octeon_ciu3_mbox_send(int cpu, unsigned int mbox);
+int octeon_irq_ciu3_xlat(struct irq_domain *d,
+			 struct device_node *node,
+			 const u32 *intspec,
+			 unsigned int intsize,
+			 unsigned long *out_hwirq,
+			 unsigned int *out_type);
+void octeon_irq_ciu3_enable(struct irq_data *data);
+void octeon_irq_ciu3_disable(struct irq_data *data);
+void octeon_irq_ciu3_ack(struct irq_data *data);
+void octeon_irq_ciu3_mask(struct irq_data *data);
+void octeon_irq_ciu3_mask_ack(struct irq_data *data);
+int octeon_irq_ciu3_mapx(struct irq_domain *d, unsigned int virq,
+			 irq_hw_number_t hw, struct irq_chip *chip);
+
 /* Octeon multiplier save/restore routines from octeon_switch.S */
 void octeon_mult_save(void);
 void octeon_mult_restore(void);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/octeon/octeon-model.h linux-libre-4.7-gnu/arch/mips/include/asm/octeon/octeon-model.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/octeon/octeon-model.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/octeon/octeon-model.h	2016-07-24 15:23:50.000000000 -0400
@@ -74,7 +74,12 @@
  * CN7XXX models with new revision encoding
  */
 
+#define OCTEON_CNF75XX_PASS1_0	0x000d9800
+#define OCTEON_CNF75XX		(OCTEON_CNF75XX_PASS1_0 | OM_IGNORE_REVISION)
+#define OCTEON_CNF75XX_PASS1_X	(OCTEON_CNF75XX_PASS1_0 | OM_IGNORE_MINOR_REVISION)
+
 #define OCTEON_CN73XX_PASS1_0	0x000d9700
+#define OCTEON_CN73XX_PASS1_1	0x000d9701
 #define OCTEON_CN73XX		(OCTEON_CN73XX_PASS1_0 | OM_IGNORE_REVISION)
 #define OCTEON_CN73XX_PASS1_X	(OCTEON_CN73XX_PASS1_0 | \
 				 OM_IGNORE_MINOR_REVISION)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/pci.h linux-libre-4.7-gnu/arch/mips/include/asm/pci.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/pci.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/pci.h	2016-07-24 15:23:50.000000000 -0400
@@ -43,8 +43,6 @@ struct pci_controller {
 	   and XFree86. Eventually will be removed. */
 	unsigned int need_domain_info;
 
-	int iommu;
-
 	/* Optional access methods for reading/writing the bus number
 	   of the PCI controller */
 	int (*get_busno)(void);
@@ -106,11 +104,11 @@ static inline void pci_resource_to_user(
 struct pci_dev;
 
 /*
- * The PCI address space does equal the physical memory address space.	The
- * networking and block device layers use this boolean for bounce buffer
- * decisions.  This is set if any hose does not have an IOMMU.
+ * The PCI address space does equal the physical memory address space.
+ * The networking and block device layers use this boolean for bounce
+ * buffer decisions.
  */
-extern unsigned int PCI_DMA_BUS_IS_PHYS;
+#define PCI_DMA_BUS_IS_PHYS     (1)
 
 #ifdef CONFIG_PCI_DOMAINS
 #define pci_domain_nr(bus) ((struct pci_controller *)(bus)->sysdata)->index
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/pgalloc.h linux-libre-4.7-gnu/arch/mips/include/asm/pgalloc.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/pgalloc.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/pgalloc.h	2016-07-24 15:23:50.000000000 -0400
@@ -69,7 +69,7 @@ static inline pte_t *pte_alloc_one_kerne
 {
 	pte_t *pte;
 
-	pte = (pte_t *) __get_free_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, PTE_ORDER);
+	pte = (pte_t *) __get_free_pages(GFP_KERNEL|__GFP_ZERO, PTE_ORDER);
 
 	return pte;
 }
@@ -79,7 +79,7 @@ static inline struct page *pte_alloc_one
 {
 	struct page *pte;
 
-	pte = alloc_pages(GFP_KERNEL | __GFP_REPEAT, PTE_ORDER);
+	pte = alloc_pages(GFP_KERNEL, PTE_ORDER);
 	if (!pte)
 		return NULL;
 	clear_highpage(pte);
@@ -113,7 +113,7 @@ static inline pmd_t *pmd_alloc_one(struc
 {
 	pmd_t *pmd;
 
-	pmd = (pmd_t *) __get_free_pages(GFP_KERNEL|__GFP_REPEAT, PMD_ORDER);
+	pmd = (pmd_t *) __get_free_pages(GFP_KERNEL, PMD_ORDER);
 	if (pmd)
 		pmd_init((unsigned long)pmd, (unsigned long)invalid_pte_table);
 	return pmd;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/pgtable-32.h linux-libre-4.7-gnu/arch/mips/include/asm/pgtable-32.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/pgtable-32.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/pgtable-32.h	2016-07-24 15:23:50.000000000 -0400
@@ -103,8 +103,8 @@ static inline void pmd_clear(pmd_t *pmdp
 	pmd_val(*pmdp) = ((unsigned long) invalid_pte_table);
 }
 
-#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)
-#define pte_page(x)		pfn_to_page(pte_pfn(x))
+#if defined(CONFIG_XPA)
+
 #define pte_pfn(x)		(((unsigned long)((x).pte_high >> _PFN_SHIFT)) | (unsigned long)((x).pte_low << _PAGE_PRESENT_SHIFT))
 static inline pte_t
 pfn_pte(unsigned long pfn, pgprot_t prot)
@@ -118,9 +118,21 @@ pfn_pte(unsigned long pfn, pgprot_t prot
 	return pte;
 }
 
-#else
+#elif defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)
 
-#define pte_page(x)		pfn_to_page(pte_pfn(x))
+#define pte_pfn(x)		((unsigned long)((x).pte_high >> 6))
+
+static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot)
+{
+	pte_t pte;
+
+	pte.pte_high = (pfn << 6) | (pgprot_val(prot) & 0x3f);
+	pte.pte_low = pgprot_val(prot);
+
+	return pte;
+}
+
+#else
 
 #ifdef CONFIG_CPU_VR41XX
 #define pte_pfn(x)		((unsigned long)((x).pte >> (PAGE_SHIFT + 2)))
@@ -131,6 +143,8 @@ pfn_pte(unsigned long pfn, pgprot_t prot
 #endif
 #endif /* defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) */
 
+#define pte_page(x)		pfn_to_page(pte_pfn(x))
+
 #define __pgd_offset(address)	pgd_index(address)
 #define __pud_offset(address)	(((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1))
 #define __pmd_offset(address)	(((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
@@ -166,7 +180,7 @@ pfn_pte(unsigned long pfn, pgprot_t prot
 
 #else
 
-#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)
+#if defined(CONFIG_XPA)
 
 /* Swap entries must have VALID and GLOBAL bits cleared. */
 #define __swp_type(x)			(((x).val >> 4) & 0x1f)
@@ -175,6 +189,15 @@ pfn_pte(unsigned long pfn, pgprot_t prot
 #define __pte_to_swp_entry(pte)		((swp_entry_t) { (pte).pte_high })
 #define __swp_entry_to_pte(x)		((pte_t) { 0, (x).val })
 
+#elif defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)
+
+/* Swap entries must have VALID and GLOBAL bits cleared. */
+#define __swp_type(x)			(((x).val >> 2) & 0x1f)
+#define __swp_offset(x)			 ((x).val >> 7)
+#define __swp_entry(type, offset)	((swp_entry_t)  { ((type) << 2) | ((offset) << 7) })
+#define __pte_to_swp_entry(pte)		((swp_entry_t) { (pte).pte_high })
+#define __swp_entry_to_pte(x)		((pte_t) { 0, (x).val })
+
 #else
 /*
  * Constraints:
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/pgtable-64.h linux-libre-4.7-gnu/arch/mips/include/asm/pgtable-64.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/pgtable-64.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/pgtable-64.h	2016-07-24 15:23:50.000000000 -0400
@@ -17,7 +17,7 @@
 #include <asm/cachectl.h>
 #include <asm/fixmap.h>
 
-#ifdef CONFIG_PAGE_SIZE_64KB
+#if defined(CONFIG_PAGE_SIZE_64KB) && !defined(CONFIG_MIPS_VA_BITS_48)
 #include <asm-generic/pgtable-nopmd.h>
 #else
 #include <asm-generic/pgtable-nopud.h>
@@ -90,7 +90,11 @@
 #define PTE_ORDER		0
 #endif
 #ifdef CONFIG_PAGE_SIZE_16KB
-#define PGD_ORDER		0
+#ifdef CONFIG_MIPS_VA_BITS_48
+#define PGD_ORDER               1
+#else
+#define PGD_ORDER               0
+#endif
 #define PUD_ORDER		aieeee_attempt_to_allocate_pud
 #define PMD_ORDER		0
 #define PTE_ORDER		0
@@ -104,7 +108,11 @@
 #ifdef CONFIG_PAGE_SIZE_64KB
 #define PGD_ORDER		0
 #define PUD_ORDER		aieeee_attempt_to_allocate_pud
+#ifdef CONFIG_MIPS_VA_BITS_48
+#define PMD_ORDER		0
+#else
 #define PMD_ORDER		aieeee_attempt_to_allocate_pmd
+#endif
 #define PTE_ORDER		0
 #endif
 
@@ -114,11 +122,7 @@
 #endif
 #define PTRS_PER_PTE	((PAGE_SIZE << PTE_ORDER) / sizeof(pte_t))
 
-#if PGDIR_SIZE >= TASK_SIZE64
-#define USER_PTRS_PER_PGD	(1)
-#else
-#define USER_PTRS_PER_PGD	(TASK_SIZE64 / PGDIR_SIZE)
-#endif
+#define USER_PTRS_PER_PGD       ((TASK_SIZE64 / PGDIR_SIZE)?(TASK_SIZE64 / PGDIR_SIZE):1)
 #define FIRST_USER_ADDRESS	0UL
 
 /*
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/pgtable-bits.h linux-libre-4.7-gnu/arch/mips/include/asm/pgtable-bits.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/pgtable-bits.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/pgtable-bits.h	2016-07-24 15:23:50.000000000 -0400
@@ -32,149 +32,132 @@
  * unpredictable things.  The code (when it is written) to deal with
  * this problem will be in the update_mmu_cache() code for the r4k.
  */
-#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)
-
-/*
- * The following bits are implemented by the TLB hardware
- */
-#define _PAGE_NO_EXEC_SHIFT	0
-#define _PAGE_NO_EXEC		(1 << _PAGE_NO_EXEC_SHIFT)
-#define _PAGE_NO_READ_SHIFT	(_PAGE_NO_EXEC_SHIFT + 1)
-#define _PAGE_NO_READ		(1 << _PAGE_NO_READ_SHIFT)
-#define _PAGE_GLOBAL_SHIFT	(_PAGE_NO_READ_SHIFT + 1)
-#define _PAGE_GLOBAL		(1 << _PAGE_GLOBAL_SHIFT)
-#define _PAGE_VALID_SHIFT	(_PAGE_GLOBAL_SHIFT + 1)
-#define _PAGE_VALID		(1 << _PAGE_VALID_SHIFT)
-#define _PAGE_DIRTY_SHIFT	(_PAGE_VALID_SHIFT + 1)
-#define _PAGE_DIRTY		(1 << _PAGE_DIRTY_SHIFT)
-#define _CACHE_SHIFT		(_PAGE_DIRTY_SHIFT + 1)
-#define _CACHE_MASK		(7 << _CACHE_SHIFT)
+#if defined(CONFIG_XPA)
 
 /*
- * The following bits are implemented in software
+ * Page table bit offsets used for 64 bit physical addressing on
+ * MIPS32r5 with XPA.
  */
-#define _PAGE_PRESENT_SHIFT	(24)
-#define _PAGE_PRESENT		(1 << _PAGE_PRESENT_SHIFT)
-#define _PAGE_READ_SHIFT	(_PAGE_PRESENT_SHIFT + 1)
-#define _PAGE_READ		(1 << _PAGE_READ_SHIFT)
-#define _PAGE_WRITE_SHIFT	(_PAGE_READ_SHIFT + 1)
-#define _PAGE_WRITE		(1 << _PAGE_WRITE_SHIFT)
-#define _PAGE_ACCESSED_SHIFT	(_PAGE_WRITE_SHIFT + 1)
-#define _PAGE_ACCESSED		(1 << _PAGE_ACCESSED_SHIFT)
-#define _PAGE_MODIFIED_SHIFT	(_PAGE_ACCESSED_SHIFT + 1)
-#define _PAGE_MODIFIED		(1 << _PAGE_MODIFIED_SHIFT)
+enum pgtable_bits {
+	/* Used by TLB hardware (placed in EntryLo*) */
+	_PAGE_NO_EXEC_SHIFT,
+	_PAGE_NO_READ_SHIFT,
+	_PAGE_GLOBAL_SHIFT,
+	_PAGE_VALID_SHIFT,
+	_PAGE_DIRTY_SHIFT,
+	_CACHE_SHIFT,
 
-#define _PFN_SHIFT		(PAGE_SHIFT - 12 + _CACHE_SHIFT + 3)
+	/* Used only by software (masked out before writing EntryLo*) */
+	_PAGE_PRESENT_SHIFT = 24,
+	_PAGE_WRITE_SHIFT,
+	_PAGE_ACCESSED_SHIFT,
+	_PAGE_MODIFIED_SHIFT,
+};
 
 /*
  * Bits for extended EntryLo0/EntryLo1 registers
  */
 #define _PFNX_MASK		0xffffff
 
-#elif defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
+#elif defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)
 
 /*
- * The following bits are implemented in software
+ * Page table bit offsets used for 36 bit physical addressing on MIPS32,
+ * for example with Alchemy or Netlogic XLP/XLR.
  */
-#define _PAGE_PRESENT_SHIFT	(0)
-#define _PAGE_PRESENT		(1 << _PAGE_PRESENT_SHIFT)
-#define _PAGE_READ_SHIFT	(_PAGE_PRESENT_SHIFT + 1)
-#define _PAGE_READ		(1 << _PAGE_READ_SHIFT)
-#define _PAGE_WRITE_SHIFT	(_PAGE_READ_SHIFT + 1)
-#define _PAGE_WRITE		(1 << _PAGE_WRITE_SHIFT)
-#define _PAGE_ACCESSED_SHIFT	(_PAGE_WRITE_SHIFT + 1)
-#define _PAGE_ACCESSED		(1 << _PAGE_ACCESSED_SHIFT)
-#define _PAGE_MODIFIED_SHIFT	(_PAGE_ACCESSED_SHIFT + 1)
-#define _PAGE_MODIFIED		(1 << _PAGE_MODIFIED_SHIFT)
+enum pgtable_bits {
+	/* Used by TLB hardware (placed in EntryLo*) */
+	_PAGE_GLOBAL_SHIFT,
+	_PAGE_VALID_SHIFT,
+	_PAGE_DIRTY_SHIFT,
+	_CACHE_SHIFT,
 
-/*
- * The following bits are implemented by the TLB hardware
- */
-#define _PAGE_GLOBAL_SHIFT	(_PAGE_MODIFIED_SHIFT + 4)
-#define _PAGE_GLOBAL		(1 << _PAGE_GLOBAL_SHIFT)
-#define _PAGE_VALID_SHIFT	(_PAGE_GLOBAL_SHIFT + 1)
-#define _PAGE_VALID		(1 << _PAGE_VALID_SHIFT)
-#define _PAGE_DIRTY_SHIFT	(_PAGE_VALID_SHIFT + 1)
-#define _PAGE_DIRTY		(1 << _PAGE_DIRTY_SHIFT)
-#define _CACHE_UNCACHED_SHIFT	(_PAGE_DIRTY_SHIFT + 1)
-#define _CACHE_UNCACHED		(1 << _CACHE_UNCACHED_SHIFT)
-#define _CACHE_MASK		_CACHE_UNCACHED
+	/* Used only by software (masked out before writing EntryLo*) */
+	_PAGE_PRESENT_SHIFT = _CACHE_SHIFT + 3,
+	_PAGE_NO_READ_SHIFT,
+	_PAGE_WRITE_SHIFT,
+	_PAGE_ACCESSED_SHIFT,
+	_PAGE_MODIFIED_SHIFT,
+};
 
-#define _PFN_SHIFT		PAGE_SHIFT
+#elif defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
+
+/* Page table bits used for r3k systems */
+enum pgtable_bits {
+	/* Used only by software (writes to EntryLo ignored) */
+	_PAGE_PRESENT_SHIFT,
+	_PAGE_NO_READ_SHIFT,
+	_PAGE_WRITE_SHIFT,
+	_PAGE_ACCESSED_SHIFT,
+	_PAGE_MODIFIED_SHIFT,
+
+	/* Used by TLB hardware (placed in EntryLo) */
+	_PAGE_GLOBAL_SHIFT = 8,
+	_PAGE_VALID_SHIFT,
+	_PAGE_DIRTY_SHIFT,
+	_CACHE_UNCACHED_SHIFT,
+};
 
 #else
-/*
- * Below are the "Normal" R4K cases
- */
 
-/*
- * The following bits are implemented in software
- */
-#define _PAGE_PRESENT_SHIFT	0
+/* Page table bits used for r4k systems */
+enum pgtable_bits {
+	/* Used only by software (masked out before writing EntryLo*) */
+	_PAGE_PRESENT_SHIFT,
+#if !defined(CONFIG_CPU_HAS_RIXI)
+	_PAGE_NO_READ_SHIFT,
+#endif
+	_PAGE_WRITE_SHIFT,
+	_PAGE_ACCESSED_SHIFT,
+	_PAGE_MODIFIED_SHIFT,
+#if defined(CONFIG_64BIT) && defined(CONFIG_MIPS_HUGE_TLB_SUPPORT)
+	_PAGE_HUGE_SHIFT,
+#endif
+
+	/* Used by TLB hardware (placed in EntryLo*) */
+#if defined(CONFIG_CPU_HAS_RIXI)
+	_PAGE_NO_EXEC_SHIFT,
+	_PAGE_NO_READ_SHIFT,
+#endif
+	_PAGE_GLOBAL_SHIFT,
+	_PAGE_VALID_SHIFT,
+	_PAGE_DIRTY_SHIFT,
+	_CACHE_SHIFT,
+};
+
+#endif /* defined(CONFIG_PHYS_ADDR_T_64BIT && defined(CONFIG_CPU_MIPS32) */
+
+/* Used only by software */
 #define _PAGE_PRESENT		(1 << _PAGE_PRESENT_SHIFT)
-/* R2 or later cores check for RI/XI support to determine _PAGE_READ */
-#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
-#define _PAGE_WRITE_SHIFT	(_PAGE_PRESENT_SHIFT + 1)
-#define _PAGE_WRITE		(1 << _PAGE_WRITE_SHIFT)
-#else
-#define _PAGE_READ_SHIFT	(_PAGE_PRESENT_SHIFT + 1)
-#define _PAGE_READ		(1 << _PAGE_READ_SHIFT)
-#define _PAGE_WRITE_SHIFT	(_PAGE_READ_SHIFT + 1)
 #define _PAGE_WRITE		(1 << _PAGE_WRITE_SHIFT)
-#endif
-#define _PAGE_ACCESSED_SHIFT	(_PAGE_WRITE_SHIFT + 1)
 #define _PAGE_ACCESSED		(1 << _PAGE_ACCESSED_SHIFT)
-#define _PAGE_MODIFIED_SHIFT	(_PAGE_ACCESSED_SHIFT + 1)
 #define _PAGE_MODIFIED		(1 << _PAGE_MODIFIED_SHIFT)
-
 #if defined(CONFIG_64BIT) && defined(CONFIG_MIPS_HUGE_TLB_SUPPORT)
-/* Huge TLB page */
-#define _PAGE_HUGE_SHIFT	(_PAGE_MODIFIED_SHIFT + 1)
-#define _PAGE_HUGE		(1 << _PAGE_HUGE_SHIFT)
-#endif	/* CONFIG_64BIT && CONFIG_MIPS_HUGE_TLB_SUPPORT */
-
-#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
-/* XI - page cannot be executed */
-#ifdef _PAGE_HUGE_SHIFT
-#define _PAGE_NO_EXEC_SHIFT	(_PAGE_HUGE_SHIFT + 1)
-#else
-#define _PAGE_NO_EXEC_SHIFT	(_PAGE_MODIFIED_SHIFT + 1)
+# define _PAGE_HUGE		(1 << _PAGE_HUGE_SHIFT)
 #endif
-#define _PAGE_NO_EXEC		(cpu_has_rixi ? (1 << _PAGE_NO_EXEC_SHIFT) : 0)
-
-/* RI - page cannot be read */
-#define _PAGE_READ_SHIFT	(_PAGE_NO_EXEC_SHIFT + 1)
-#define _PAGE_READ		(cpu_has_rixi ? 0 : (1 << _PAGE_READ_SHIFT))
-#define _PAGE_NO_READ_SHIFT	_PAGE_READ_SHIFT
-#define _PAGE_NO_READ		(cpu_has_rixi ? (1 << _PAGE_READ_SHIFT) : 0)
-#endif	/* defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) */
 
-#if defined(_PAGE_NO_READ_SHIFT)
-#define _PAGE_GLOBAL_SHIFT	(_PAGE_NO_READ_SHIFT + 1)
-#elif defined(_PAGE_HUGE_SHIFT)
-#define _PAGE_GLOBAL_SHIFT	(_PAGE_HUGE_SHIFT + 1)
-#else
-#define _PAGE_GLOBAL_SHIFT	(_PAGE_MODIFIED_SHIFT + 1)
+/* Used by TLB hardware (placed in EntryLo*) */
+#if defined(CONFIG_XPA)
+# define _PAGE_NO_EXEC		(1 << _PAGE_NO_EXEC_SHIFT)
+#elif defined(CONFIG_CPU_HAS_RIXI)
+# define _PAGE_NO_EXEC		(cpu_has_rixi ? (1 << _PAGE_NO_EXEC_SHIFT) : 0)
 #endif
+#define _PAGE_NO_READ		(1 << _PAGE_NO_READ_SHIFT)
 #define _PAGE_GLOBAL		(1 << _PAGE_GLOBAL_SHIFT)
-
-#define _PAGE_VALID_SHIFT	(_PAGE_GLOBAL_SHIFT + 1)
 #define _PAGE_VALID		(1 << _PAGE_VALID_SHIFT)
-#define _PAGE_DIRTY_SHIFT	(_PAGE_VALID_SHIFT + 1)
 #define _PAGE_DIRTY		(1 << _PAGE_DIRTY_SHIFT)
-#define _CACHE_SHIFT		(_PAGE_DIRTY_SHIFT + 1)
-#define _CACHE_MASK		(7 << _CACHE_SHIFT)
-
-#define _PFN_SHIFT		(PAGE_SHIFT - 12 + _CACHE_SHIFT + 3)
-
-#endif /* defined(CONFIG_PHYS_ADDR_T_64BIT && defined(CONFIG_CPU_MIPS32) */
+#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
+# define _CACHE_UNCACHED	(1 << _CACHE_UNCACHED_SHIFT)
+# define _CACHE_MASK		_CACHE_UNCACHED
+# define _PFN_SHIFT		PAGE_SHIFT
+#else
+# define _CACHE_MASK		(7 << _CACHE_SHIFT)
+# define _PFN_SHIFT		(PAGE_SHIFT - 12 + _CACHE_SHIFT + 3)
+#endif
 
 #ifndef _PAGE_NO_EXEC
 #define _PAGE_NO_EXEC		0
 #endif
-#ifndef _PAGE_NO_READ
-#define _PAGE_NO_READ		0
-#endif
 
 #define _PAGE_SILENT_READ	_PAGE_VALID
 #define _PAGE_SILENT_WRITE	_PAGE_DIRTY
@@ -191,14 +174,13 @@
  */
 
 
-#ifndef __ASSEMBLY__
 /*
  * pte_to_entrylo converts a page table entry (PTE) into a Mips
  * entrylo0/1 value.
  */
 static inline uint64_t pte_to_entrylo(unsigned long pte_val)
 {
-#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
+#ifdef CONFIG_CPU_HAS_RIXI
 	if (cpu_has_rixi) {
 		int sa;
 #ifdef CONFIG_32BIT
@@ -218,7 +200,6 @@ static inline uint64_t pte_to_entrylo(un
 
 	return pte_val >> _PAGE_GLOBAL_SHIFT;
 }
-#endif
 
 /*
  * Cache attributes
@@ -274,7 +255,7 @@ static inline uint64_t pte_to_entrylo(un
 #define _CACHE_UNCACHED_ACCELERATED	(7<<_CACHE_SHIFT)
 #endif
 
-#define __READABLE	(_PAGE_SILENT_READ | _PAGE_READ | _PAGE_ACCESSED)
+#define __READABLE	(_PAGE_SILENT_READ | _PAGE_ACCESSED)
 #define __WRITEABLE	(_PAGE_SILENT_WRITE | _PAGE_WRITE | _PAGE_MODIFIED)
 
 #define _PAGE_CHG_MASK	(_PAGE_ACCESSED | _PAGE_MODIFIED |	\
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/pgtable.h linux-libre-4.7-gnu/arch/mips/include/asm/pgtable.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/pgtable.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/pgtable.h	2016-07-24 15:23:50.000000000 -0400
@@ -23,18 +23,19 @@
 struct mm_struct;
 struct vm_area_struct;
 
-#define PAGE_NONE	__pgprot(_PAGE_PRESENT | _CACHE_CACHABLE_NONCOHERENT)
-#define PAGE_SHARED	__pgprot(_PAGE_PRESENT | _PAGE_WRITE | _PAGE_READ | \
+#define PAGE_NONE	__pgprot(_PAGE_PRESENT | _PAGE_NO_READ | \
 				 _page_cachable_default)
-#define PAGE_COPY	__pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_NO_EXEC | \
+#define PAGE_SHARED	__pgprot(_PAGE_PRESENT | _PAGE_WRITE | \
 				 _page_cachable_default)
-#define PAGE_READONLY	__pgprot(_PAGE_PRESENT | _PAGE_READ | \
+#define PAGE_COPY	__pgprot(_PAGE_PRESENT | _PAGE_NO_EXEC | \
+				 _page_cachable_default)
+#define PAGE_READONLY	__pgprot(_PAGE_PRESENT | \
 				 _page_cachable_default)
 #define PAGE_KERNEL	__pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \
 				 _PAGE_GLOBAL | _page_cachable_default)
 #define PAGE_KERNEL_NC	__pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \
 				 _PAGE_GLOBAL | _CACHE_CACHABLE_NONCOHERENT)
-#define PAGE_USERIO	__pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \
+#define PAGE_USERIO	__pgprot(_PAGE_PRESENT | _PAGE_WRITE | \
 				 _page_cachable_default)
 #define PAGE_KERNEL_UNCACHED __pgprot(_PAGE_PRESENT | __READABLE | \
 			__WRITEABLE | _PAGE_GLOBAL | _CACHE_UNCACHED)
@@ -127,10 +128,19 @@ do {									\
 	}								\
 } while(0)
 
+static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
+			      pte_t *ptep, pte_t pteval);
+
 #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)
 
-#define pte_none(pte)		(!(((pte).pte_high) & ~_PAGE_GLOBAL))
+#ifdef CONFIG_XPA
+# define pte_none(pte)		(!(((pte).pte_high) & ~_PAGE_GLOBAL))
+#else
+# define pte_none(pte)		(!(((pte).pte_low | (pte).pte_high) & ~_PAGE_GLOBAL))
+#endif
+
 #define pte_present(pte)	((pte).pte_low & _PAGE_PRESENT)
+#define pte_no_exec(pte)	((pte).pte_low & _PAGE_NO_EXEC)
 
 static inline void set_pte(pte_t *ptep, pte_t pte)
 {
@@ -138,17 +148,23 @@ static inline void set_pte(pte_t *ptep,
 	smp_wmb();
 	ptep->pte_low = pte.pte_low;
 
+#ifdef CONFIG_XPA
 	if (pte.pte_high & _PAGE_GLOBAL) {
+#else
+	if (pte.pte_low & _PAGE_GLOBAL) {
+#endif
 		pte_t *buddy = ptep_buddy(ptep);
 		/*
 		 * Make sure the buddy is global too (if it's !none,
 		 * it better already be global)
 		 */
-		if (pte_none(*buddy))
+		if (pte_none(*buddy)) {
+			if (!config_enabled(CONFIG_XPA))
+				buddy->pte_low |= _PAGE_GLOBAL;
 			buddy->pte_high |= _PAGE_GLOBAL;
+		}
 	}
 }
-#define set_pte_at(mm, addr, ptep, pteval) set_pte(ptep, pteval)
 
 static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
@@ -156,8 +172,13 @@ static inline void pte_clear(struct mm_s
 
 	htw_stop();
 	/* Preserve global status for the pair */
-	if (ptep_buddy(ptep)->pte_high & _PAGE_GLOBAL)
-		null.pte_high = _PAGE_GLOBAL;
+	if (config_enabled(CONFIG_XPA)) {
+		if (ptep_buddy(ptep)->pte_high & _PAGE_GLOBAL)
+			null.pte_high = _PAGE_GLOBAL;
+	} else {
+		if (ptep_buddy(ptep)->pte_low & _PAGE_GLOBAL)
+			null.pte_low = null.pte_high = _PAGE_GLOBAL;
+	}
 
 	set_pte_at(mm, addr, ptep, null);
 	htw_start();
@@ -166,6 +187,7 @@ static inline void pte_clear(struct mm_s
 
 #define pte_none(pte)		(!(pte_val(pte) & ~_PAGE_GLOBAL))
 #define pte_present(pte)	(pte_val(pte) & _PAGE_PRESENT)
+#define pte_no_exec(pte)	(pte_val(pte) & _PAGE_NO_EXEC)
 
 /*
  * Certain architectures need to do special things when pte's
@@ -187,30 +209,42 @@ static inline void set_pte(pte_t *ptep,
 		 * For SMP, multiple CPUs can race, so we need to do
 		 * this atomically.
 		 */
-#ifdef CONFIG_64BIT
-#define LL_INSN "lld"
-#define SC_INSN "scd"
-#else /* CONFIG_32BIT */
-#define LL_INSN "ll"
-#define SC_INSN "sc"
-#endif
 		unsigned long page_global = _PAGE_GLOBAL;
 		unsigned long tmp;
 
-		__asm__ __volatile__ (
-			"	.set	push\n"
-			"	.set	noreorder\n"
-			"1:	" LL_INSN "	%[tmp], %[buddy]\n"
-			"	bnez	%[tmp], 2f\n"
-			"	 or	%[tmp], %[tmp], %[global]\n"
-			"	" SC_INSN "	%[tmp], %[buddy]\n"
-			"	beqz	%[tmp], 1b\n"
-			"	 nop\n"
-			"2:\n"
-			"	.set pop"
-			: [buddy] "+m" (buddy->pte),
-			  [tmp] "=&r" (tmp)
+		if (kernel_uses_llsc && R10000_LLSC_WAR) {
+			__asm__ __volatile__ (
+			"	.set	arch=r4000			\n"
+			"	.set	push				\n"
+			"	.set	noreorder			\n"
+			"1:"	__LL	"%[tmp], %[buddy]		\n"
+			"	bnez	%[tmp], 2f			\n"
+			"	 or	%[tmp], %[tmp], %[global]	\n"
+				__SC	"%[tmp], %[buddy]		\n"
+			"	beqzl	%[tmp], 1b			\n"
+			"	nop					\n"
+			"2:						\n"
+			"	.set	pop				\n"
+			"	.set	mips0				\n"
+			: [buddy] "+m" (buddy->pte), [tmp] "=&r" (tmp)
 			: [global] "r" (page_global));
+		} else if (kernel_uses_llsc) {
+			__asm__ __volatile__ (
+			"	.set	"MIPS_ISA_ARCH_LEVEL"		\n"
+			"	.set	push				\n"
+			"	.set	noreorder			\n"
+			"1:"	__LL	"%[tmp], %[buddy]		\n"
+			"	bnez	%[tmp], 2f			\n"
+			"	 or	%[tmp], %[tmp], %[global]	\n"
+				__SC	"%[tmp], %[buddy]		\n"
+			"	beqz	%[tmp], 1b			\n"
+			"	nop					\n"
+			"2:						\n"
+			"	.set	pop				\n"
+			"	.set	mips0				\n"
+			: [buddy] "+m" (buddy->pte), [tmp] "=&r" (tmp)
+			: [global] "r" (page_global));
+		}
 #else /* !CONFIG_SMP */
 		if (pte_none(*buddy))
 			pte_val(*buddy) = pte_val(*buddy) | _PAGE_GLOBAL;
@@ -218,7 +252,6 @@ static inline void set_pte(pte_t *ptep,
 	}
 #endif
 }
-#define set_pte_at(mm, addr, ptep, pteval) set_pte(ptep, pteval)
 
 static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
@@ -234,6 +267,22 @@ static inline void pte_clear(struct mm_s
 }
 #endif
 
+static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
+			      pte_t *ptep, pte_t pteval)
+{
+	extern void __update_cache(unsigned long address, pte_t pte);
+
+	if (!pte_present(pteval))
+		goto cache_sync_done;
+
+	if (pte_present(*ptep) && (pte_pfn(*ptep) == pte_pfn(pteval)))
+		goto cache_sync_done;
+
+	__update_cache(addr, pteval);
+cache_sync_done:
+	set_pte(ptep, pteval);
+}
+
 /*
  * (pmds are folded into puds so this doesn't get actually called,
  * but the define is needed for a generic inline function.)
@@ -270,6 +319,8 @@ static inline int pte_young(pte_t pte)	{
 static inline pte_t pte_wrprotect(pte_t pte)
 {
 	pte.pte_low  &= ~_PAGE_WRITE;
+	if (!config_enabled(CONFIG_XPA))
+		pte.pte_low &= ~_PAGE_SILENT_WRITE;
 	pte.pte_high &= ~_PAGE_SILENT_WRITE;
 	return pte;
 }
@@ -277,6 +328,8 @@ static inline pte_t pte_wrprotect(pte_t
 static inline pte_t pte_mkclean(pte_t pte)
 {
 	pte.pte_low  &= ~_PAGE_MODIFIED;
+	if (!config_enabled(CONFIG_XPA))
+		pte.pte_low &= ~_PAGE_SILENT_WRITE;
 	pte.pte_high &= ~_PAGE_SILENT_WRITE;
 	return pte;
 }
@@ -284,6 +337,8 @@ static inline pte_t pte_mkclean(pte_t pt
 static inline pte_t pte_mkold(pte_t pte)
 {
 	pte.pte_low  &= ~_PAGE_ACCESSED;
+	if (!config_enabled(CONFIG_XPA))
+		pte.pte_low &= ~_PAGE_SILENT_READ;
 	pte.pte_high &= ~_PAGE_SILENT_READ;
 	return pte;
 }
@@ -291,24 +346,33 @@ static inline pte_t pte_mkold(pte_t pte)
 static inline pte_t pte_mkwrite(pte_t pte)
 {
 	pte.pte_low |= _PAGE_WRITE;
-	if (pte.pte_low & _PAGE_MODIFIED)
+	if (pte.pte_low & _PAGE_MODIFIED) {
+		if (!config_enabled(CONFIG_XPA))
+			pte.pte_low |= _PAGE_SILENT_WRITE;
 		pte.pte_high |= _PAGE_SILENT_WRITE;
+	}
 	return pte;
 }
 
 static inline pte_t pte_mkdirty(pte_t pte)
 {
 	pte.pte_low |= _PAGE_MODIFIED;
-	if (pte.pte_low & _PAGE_WRITE)
+	if (pte.pte_low & _PAGE_WRITE) {
+		if (!config_enabled(CONFIG_XPA))
+			pte.pte_low |= _PAGE_SILENT_WRITE;
 		pte.pte_high |= _PAGE_SILENT_WRITE;
+	}
 	return pte;
 }
 
 static inline pte_t pte_mkyoung(pte_t pte)
 {
 	pte.pte_low |= _PAGE_ACCESSED;
-	if (pte.pte_low & _PAGE_READ)
+	if (!(pte.pte_low & _PAGE_NO_READ)) {
+		if (!config_enabled(CONFIG_XPA))
+			pte.pte_low |= _PAGE_SILENT_READ;
 		pte.pte_high |= _PAGE_SILENT_READ;
+	}
 	return pte;
 }
 #else
@@ -353,13 +417,8 @@ static inline pte_t pte_mkdirty(pte_t pt
 static inline pte_t pte_mkyoung(pte_t pte)
 {
 	pte_val(pte) |= _PAGE_ACCESSED;
-#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
 	if (!(pte_val(pte) & _PAGE_NO_READ))
 		pte_val(pte) |= _PAGE_SILENT_READ;
-	else
-#endif
-	if (pte_val(pte) & _PAGE_READ)
-		pte_val(pte) |= _PAGE_SILENT_READ;
 	return pte;
 }
 
@@ -411,34 +470,41 @@ static inline pgprot_t pgprot_writecombi
  */
 #define mk_pte(page, pgprot)	pfn_pte(page_to_pfn(page), (pgprot))
 
-#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)
+#if defined(CONFIG_XPA)
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
 	pte.pte_low  &= (_PAGE_MODIFIED | _PAGE_ACCESSED | _PFNX_MASK);
 	pte.pte_high &= (_PFN_MASK | _CACHE_MASK);
 	pte.pte_low  |= pgprot_val(newprot) & ~_PFNX_MASK;
-	pte.pte_high |= pgprot_val(newprot) & ~_PFN_MASK;
+	pte.pte_high |= pgprot_val(newprot) & ~(_PFN_MASK | _CACHE_MASK);
+	return pte;
+}
+#elif defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)
+static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{
+	pte.pte_low  &= _PAGE_CHG_MASK;
+	pte.pte_high &= (_PFN_MASK | _CACHE_MASK);
+	pte.pte_low  |= pgprot_val(newprot);
+	pte.pte_high |= pgprot_val(newprot) & ~(_PFN_MASK | _CACHE_MASK);
 	return pte;
 }
 #else
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
-	return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot));
+	return __pte((pte_val(pte) & _PAGE_CHG_MASK) |
+		     (pgprot_val(newprot) & ~_PAGE_CHG_MASK));
 }
 #endif
 
 
 extern void __update_tlb(struct vm_area_struct *vma, unsigned long address,
 	pte_t pte);
-extern void __update_cache(struct vm_area_struct *vma, unsigned long address,
-	pte_t pte);
 
 static inline void update_mmu_cache(struct vm_area_struct *vma,
 	unsigned long address, pte_t *ptep)
 {
 	pte_t pte = *ptep;
 	__update_tlb(vma, address, pte);
-	__update_cache(vma, address, pte);
 }
 
 static inline void update_mmu_cache_pmd(struct vm_area_struct *vma,
@@ -468,6 +534,7 @@ static inline int io_remap_pfn_range(str
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 
+#define has_transparent_hugepage has_transparent_hugepage
 extern int has_transparent_hugepage(void);
 
 static inline int pmd_trans_huge(pmd_t pmd)
@@ -542,13 +609,8 @@ static inline pmd_t pmd_mkyoung(pmd_t pm
 {
 	pmd_val(pmd) |= _PAGE_ACCESSED;
 
-#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
 	if (!(pmd_val(pmd) & _PAGE_NO_READ))
 		pmd_val(pmd) |= _PAGE_SILENT_READ;
-	else
-#endif
-	if (pmd_val(pmd) & _PAGE_READ)
-		pmd_val(pmd) |= _PAGE_SILENT_READ;
 
 	return pmd;
 }
@@ -571,7 +633,8 @@ static inline struct page *pmd_page(pmd_
 
 static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
 {
-	pmd_val(pmd) = (pmd_val(pmd) & _PAGE_CHG_MASK) | pgprot_val(newprot);
+	pmd_val(pmd) = (pmd_val(pmd) & (_PAGE_CHG_MASK | _PAGE_HUGE)) |
+		       (pgprot_val(newprot) & ~_PAGE_CHG_MASK);
 	return pmd;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/processor.h linux-libre-4.7-gnu/arch/mips/include/asm/processor.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/processor.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/processor.h	2016-07-24 15:23:50.000000000 -0400
@@ -63,7 +63,11 @@ extern unsigned int vced_count, vcei_cou
  * 8192EB ...
  */
 #define TASK_SIZE32	0x7fff8000UL
-#define TASK_SIZE64	0x10000000000UL
+#ifdef CONFIG_MIPS_VA_BITS_48
+#define TASK_SIZE64     (0x1UL << ((cpu_data[0].vmbits>48)?48:cpu_data[0].vmbits))
+#else
+#define TASK_SIZE64     0x10000000000UL
+#endif
 #define TASK_SIZE (test_thread_flag(TIF_32BIT_ADDR) ? TASK_SIZE32 : TASK_SIZE64)
 #define STACK_TOP_MAX	TASK_SIZE64
 
@@ -355,6 +359,10 @@ extern unsigned long thread_saved_pc(str
  */
 extern void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp);
 
+static inline void flush_thread(void)
+{
+}
+
 unsigned long get_wchan(struct task_struct *p);
 
 #define __KSTK_TOS(tsk) ((unsigned long)task_stack_page(tsk) + \
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/seccomp.h linux-libre-4.7-gnu/arch/mips/include/asm/seccomp.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/seccomp.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/seccomp.h	2016-07-24 15:23:50.000000000 -0400
@@ -2,27 +2,32 @@
 
 #include <linux/unistd.h>
 
-/*
- * Kludge alert:
- *
- * The generic seccomp code currently allows only a single compat ABI.	Until
- * this is fixed we priorize O32 as the compat ABI over N32.
- */
-#ifdef CONFIG_MIPS32_O32
+#ifdef CONFIG_COMPAT
+static inline const int *get_compat_mode1_syscalls(void)
+{
+	static const int syscalls_O32[] = {
+		__NR_O32_Linux + 3, __NR_O32_Linux + 4,
+		__NR_O32_Linux + 1, __NR_O32_Linux + 193,
+		0, /* null terminated */
+	};
+	static const int syscalls_N32[] = {
+		__NR_N32_Linux + 0, __NR_N32_Linux + 1,
+		__NR_N32_Linux + 58, __NR_N32_Linux + 211,
+		0, /* null terminated */
+	};
 
-#define __NR_seccomp_read_32		4003
-#define __NR_seccomp_write_32		4004
-#define __NR_seccomp_exit_32		4001
-#define __NR_seccomp_sigreturn_32	4193	/* rt_sigreturn */
+	if (config_enabled(CONFIG_MIPS32_O32) && test_thread_flag(TIF_32BIT_REGS))
+		return syscalls_O32;
 
-#elif defined(CONFIG_MIPS32_N32)
+	if (config_enabled(CONFIG_MIPS32_N32))
+		return syscalls_N32;
 
-#define __NR_seccomp_read_32		6000
-#define __NR_seccomp_write_32		6001
-#define __NR_seccomp_exit_32		6058
-#define __NR_seccomp_sigreturn_32	6211	/* rt_sigreturn */
+	BUG();
+}
 
-#endif /* CONFIG_MIPS32_O32 */
+#define get_compat_mode1_syscalls get_compat_mode1_syscalls
+
+#endif /* CONFIG_COMPAT */
 
 #include <asm-generic/seccomp.h>
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/sgi/hpc3.h linux-libre-4.7-gnu/arch/mips/include/asm/sgi/hpc3.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/sgi/hpc3.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/sgi/hpc3.h	2016-07-24 15:23:50.000000000 -0400
@@ -39,7 +39,7 @@ struct hpc3_pbus_dmacregs {
 	volatile u32 pbdma_dptr;	/* pbus dma channel desc ptr */
 	u32 _unused0[0x1000/4 - 2];	/* padding */
 	volatile u32 pbdma_ctrl;	/* pbus dma channel control register has
-					 * copletely different meaning for read
+					 * completely different meaning for read
 					 * compared with write */
 	/* read */
 #define HPC3_PDMACTRL_INT	0x00000001 /* interrupt (cleared after read) */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/sibyte/bcm1480_regs.h linux-libre-4.7-gnu/arch/mips/include/asm/sibyte/bcm1480_regs.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/sibyte/bcm1480_regs.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/sibyte/bcm1480_regs.h	2016-07-24 15:23:50.000000000 -0400
@@ -415,8 +415,8 @@
 					(cpu)*BCM1480_IMR_ALIAS_MAILBOX_SPACING)
 #define A_BCM1480_IMR_ALIAS_MAILBOX_REGISTER(cpu, reg) (A_BCM1480_IMR_ALIAS_MAILBOX(cpu)+(reg))
 
-#define R_BCM1480_IMR_ALIAS_MAILBOX_0		0x0000		/* 0x0x0 */
-#define R_BCM1480_IMR_ALIAS_MAILBOX_0_SET	0x0008		/* 0x0x8 */
+#define R_BCM1480_IMR_ALIAS_MAILBOX_0		0x0000
+#define R_BCM1480_IMR_ALIAS_MAILBOX_0_SET	0x0008
 
 /*
  * these macros work together to build the address of a mailbox
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/signal.h linux-libre-4.7-gnu/arch/mips/include/asm/signal.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/signal.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/signal.h	2016-07-24 15:23:50.000000000 -0400
@@ -11,11 +11,17 @@
 
 #include <uapi/asm/signal.h>
 
+#ifdef CONFIG_MIPS32_COMPAT
+extern struct mips_abi mips_abi_32;
 
-#ifdef CONFIG_TRAD_SIGNALS
-#define sig_uses_siginfo(ka)	((ka)->sa.sa_flags & SA_SIGINFO)
+#define sig_uses_siginfo(ka, abi)                               \
+	((abi != &mips_abi_32) ? 1 :                            \
+		((ka)->sa.sa_flags & SA_SIGINFO))
 #else
-#define sig_uses_siginfo(ka)	(1)
+#define sig_uses_siginfo(ka, abi)                               \
+	(config_enabled(CONFIG_64BIT) ? 1 :                     \
+		(config_enabled(CONFIG_TRAD_SIGNALS) ?          \
+			((ka)->sa.sa_flags & SA_SIGINFO) : 1) )
 #endif
 
 #include <asm/sigcontext.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/smp-cps.h linux-libre-4.7-gnu/arch/mips/include/asm/smp-cps.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/smp-cps.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/smp-cps.h	2016-07-24 15:23:50.000000000 -0400
@@ -29,7 +29,7 @@ extern struct core_boot_config *mips_cps
 extern void mips_cps_core_entry(void);
 extern void mips_cps_core_init(void);
 
-extern struct vpe_boot_config *mips_cps_boot_vpes(void);
+extern void mips_cps_boot_vpes(struct core_boot_config *cfg, unsigned vpe);
 
 extern void mips_cps_pm_save(void);
 extern void mips_cps_pm_restore(void);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/switch_to.h linux-libre-4.7-gnu/arch/mips/include/asm/switch_to.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/switch_to.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/switch_to.h	2016-07-24 15:23:50.000000000 -0400
@@ -105,7 +105,7 @@ do {									\
 	__clear_software_ll_bit();					\
 	if (cpu_has_userlocal)						\
 		write_c0_userlocal(task_thread_info(next)->tp_value);	\
-	__restore_watch();						\
+	__restore_watch(next);						\
 	(last) = resume(prev, next, task_thread_info(next));		\
 } while (0)
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/uasm.h linux-libre-4.7-gnu/arch/mips/include/asm/uasm.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/uasm.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/uasm.h	2016-07-24 15:23:50.000000000 -0400
@@ -171,7 +171,8 @@ Ip_u2u1(_wsbh);
 Ip_u3u1u2(_xor);
 Ip_u2u1u3(_xori);
 Ip_u2u1(_yield);
-
+Ip_u1u2(_ldpte);
+Ip_u2u1u3(_lddir);
 
 /* Handle labels. */
 struct uasm_label {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/asm/watch.h linux-libre-4.7-gnu/arch/mips/include/asm/watch.h
--- linux-libre-4.6-gnu/arch/mips/include/asm/watch.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/asm/watch.h	2016-07-24 15:23:50.000000000 -0400
@@ -12,21 +12,21 @@
 
 #include <asm/mipsregs.h>
 
-void mips_install_watch_registers(void);
+void mips_install_watch_registers(struct task_struct *t);
 void mips_read_watch_registers(void);
 void mips_clear_watch_registers(void);
 void mips_probe_watch_registers(struct cpuinfo_mips *c);
 
 #ifdef CONFIG_HARDWARE_WATCHPOINTS
-#define __restore_watch() do {						\
+#define __restore_watch(task) do {					\
 	if (unlikely(test_bit(TIF_LOAD_WATCH,				\
-			      &current_thread_info()->flags))) {	\
-		mips_install_watch_registers();				\
+			      &task_thread_info(task)->flags))) {	\
+		mips_install_watch_registers(task);			\
 	}								\
 } while (0)
 
 #else
-#define __restore_watch() do {} while (0)
+#define __restore_watch(task) do {} while (0)
 #endif
 
 #endif /* _ASM_WATCH_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/uapi/asm/inst.h linux-libre-4.7-gnu/arch/mips/include/uapi/asm/inst.h
--- linux-libre-4.6-gnu/arch/mips/include/uapi/asm/inst.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/uapi/asm/inst.h	2016-07-24 15:23:50.000000000 -0400
@@ -167,6 +167,7 @@ enum cop1_sdw_func {
 	fceill_op    =	0x0a, ffloorl_op   =  0x0b,
 	fround_op    =	0x0c, ftrunc_op	   =  0x0d,
 	fceil_op     =	0x0e, ffloor_op	   =  0x0f,
+	fsel_op      =  0x10,
 	fmovc_op     =	0x11, fmovz_op	   =  0x12,
 	fmovn_op     =	0x13, fseleqz_op   =  0x14,
 	frecip_op    =  0x15, frsqrt_op    =  0x16,
@@ -204,6 +205,16 @@ enum mad_func {
 };
 
 /*
+ * func field for page table walker (Loongson-3).
+ */
+enum ptw_func {
+	lwdir_op = 0x00,
+	lwpte_op = 0x01,
+	lddir_op = 0x02,
+	ldpte_op = 0x03,
+};
+
+/*
  * func field for special3 lx opcodes (Cavium Octeon).
  */
 enum lx_func {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/include/uapi/asm/siginfo.h linux-libre-4.7-gnu/arch/mips/include/uapi/asm/siginfo.h
--- linux-libre-4.6-gnu/arch/mips/include/uapi/asm/siginfo.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/include/uapi/asm/siginfo.h	2016-07-24 15:23:50.000000000 -0400
@@ -28,7 +28,7 @@
 
 #define __ARCH_SIGSYS
 
-#include <uapi/asm-generic/siginfo.h>
+#include <asm-generic/siginfo.h>
 
 /* We can't use generic siginfo_t, because our si_code and si_errno are swapped */
 typedef struct siginfo {
@@ -42,13 +42,13 @@ typedef struct siginfo {
 
 		/* kill() */
 		struct {
-			pid_t _pid;		/* sender's pid */
+			__kernel_pid_t _pid;	/* sender's pid */
 			__ARCH_SI_UID_T _uid;	/* sender's uid */
 		} _kill;
 
 		/* POSIX.1b timers */
 		struct {
-			timer_t _tid;		/* timer id */
+			__kernel_timer_t _tid;	/* timer id */
 			int _overrun;		/* overrun count */
 			char _pad[sizeof( __ARCH_SI_UID_T) - sizeof(int)];
 			sigval_t _sigval;	/* same as below */
@@ -57,26 +57,26 @@ typedef struct siginfo {
 
 		/* POSIX.1b signals */
 		struct {
-			pid_t _pid;		/* sender's pid */
+			__kernel_pid_t _pid;	/* sender's pid */
 			__ARCH_SI_UID_T _uid;	/* sender's uid */
 			sigval_t _sigval;
 		} _rt;
 
 		/* SIGCHLD */
 		struct {
-			pid_t _pid;		/* which child */
+			__kernel_pid_t _pid;	/* which child */
 			__ARCH_SI_UID_T _uid;	/* sender's uid */
 			int _status;		/* exit code */
-			clock_t _utime;
-			clock_t _stime;
+			__kernel_clock_t _utime;
+			__kernel_clock_t _stime;
 		} _sigchld;
 
 		/* IRIX SIGCHLD */
 		struct {
-			pid_t _pid;		/* which child */
-			clock_t _utime;
+			__kernel_pid_t _pid;	/* which child */
+			__kernel_clock_t _utime;
 			int _status;		/* exit code */
-			clock_t _stime;
+			__kernel_clock_t _stime;
 		} _irix_sigchld;
 
 		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
@@ -123,6 +123,4 @@ typedef struct siginfo {
 #define SI_TIMER __SI_CODE(__SI_TIMER, -3) /* sent by timer expiration */
 #define SI_MESGQ __SI_CODE(__SI_MESGQ, -4) /* sent by real time mesq state change */
 
-#include <asm-generic/siginfo.h>
-
 #endif /* _UAPI_ASM_SIGINFO_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/jz4740/board-qi_lb60.c linux-libre-4.7-gnu/arch/mips/jz4740/board-qi_lb60.c
--- linux-libre-4.6-gnu/arch/mips/jz4740/board-qi_lb60.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/jz4740/board-qi_lb60.c	2016-07-24 15:23:50.000000000 -0400
@@ -39,8 +39,6 @@
 
 #include "clock.h"
 
-static bool is_avt2;
-
 /* GPIOs */
 #define QI_LB60_GPIO_SD_CD		JZ_GPIO_PORTD(0)
 #define QI_LB60_GPIO_SD_VCC_EN_N	JZ_GPIO_PORTD(2)
@@ -50,20 +48,6 @@ static bool is_avt2;
 #define QI_LB60_GPIO_KEYIN8		JZ_GPIO_PORTD(26)
 
 /* NAND */
-static struct nand_ecclayout qi_lb60_ecclayout_1gb = {
-	.eccbytes = 36,
-	.eccpos = {
-		6,  7,	8,  9,	10, 11, 12, 13,
-		14, 15, 16, 17, 18, 19, 20, 21,
-		22, 23, 24, 25, 26, 27, 28, 29,
-		30, 31, 32, 33, 34, 35, 36, 37,
-		38, 39, 40, 41
-	},
-	.oobfree = {
-		{ .offset = 2, .length = 4 },
-		{ .offset = 42, .length = 22 }
-	},
-};
 
 /* Early prototypes of the QI LB60 had only 1GB of NAND.
  * In order to support these devices as well the partition and ecc layout is
@@ -86,25 +70,6 @@ static struct mtd_partition qi_lb60_part
 	},
 };
 
-static struct nand_ecclayout qi_lb60_ecclayout_2gb = {
-	.eccbytes = 72,
-	.eccpos = {
-		12, 13, 14, 15, 16, 17, 18, 19,
-		20, 21, 22, 23, 24, 25, 26, 27,
-		28, 29, 30, 31, 32, 33, 34, 35,
-		36, 37, 38, 39, 40, 41, 42, 43,
-		44, 45, 46, 47, 48, 49, 50, 51,
-		52, 53, 54, 55, 56, 57, 58, 59,
-		60, 61, 62, 63, 64, 65, 66, 67,
-		68, 69, 70, 71, 72, 73, 74, 75,
-		76, 77, 78, 79, 80, 81, 82, 83
-	},
-	.oobfree = {
-		{ .offset = 2, .length = 10 },
-		{ .offset = 84, .length = 44 },
-	},
-};
-
 static struct mtd_partition qi_lb60_partitions_2gb[] = {
 	{
 		.name = "NAND BOOT partition",
@@ -123,19 +88,67 @@ static struct mtd_partition qi_lb60_part
 	},
 };
 
+static int qi_lb60_ooblayout_ecc(struct mtd_info *mtd, int section,
+				 struct mtd_oob_region *oobregion)
+{
+	if (section)
+		return -ERANGE;
+
+	oobregion->length = 36;
+	oobregion->offset = 6;
+
+	if (mtd->oobsize == 128) {
+		oobregion->length *= 2;
+		oobregion->offset *= 2;
+	}
+
+	return 0;
+}
+
+static int qi_lb60_ooblayout_free(struct mtd_info *mtd, int section,
+				  struct mtd_oob_region *oobregion)
+{
+	int eccbytes = 36, eccoff = 6;
+
+	if (section > 1)
+		return -ERANGE;
+
+	if (mtd->oobsize == 128) {
+		eccbytes *= 2;
+		eccoff *= 2;
+	}
+
+	if (!section) {
+		oobregion->offset = 2;
+		oobregion->length = eccoff - 2;
+	} else {
+		oobregion->offset = eccoff + eccbytes;
+		oobregion->length = mtd->oobsize - oobregion->offset;
+	}
+
+	return 0;
+}
+
+static const struct mtd_ooblayout_ops qi_lb60_ooblayout_ops = {
+	.ecc = qi_lb60_ooblayout_ecc,
+	.free = qi_lb60_ooblayout_free,
+};
+
 static void qi_lb60_nand_ident(struct platform_device *pdev,
-		struct nand_chip *chip, struct mtd_partition **partitions,
+		struct mtd_info *mtd, struct mtd_partition **partitions,
 		int *num_partitions)
 {
+	struct nand_chip *chip = mtd_to_nand(mtd);
+
 	if (chip->page_shift == 12) {
-		chip->ecc.layout = &qi_lb60_ecclayout_2gb;
 		*partitions = qi_lb60_partitions_2gb;
 		*num_partitions = ARRAY_SIZE(qi_lb60_partitions_2gb);
 	} else {
-		chip->ecc.layout = &qi_lb60_ecclayout_1gb;
 		*partitions = qi_lb60_partitions_1gb;
 		*num_partitions = ARRAY_SIZE(qi_lb60_partitions_1gb);
 	}
+
+	mtd_set_ooblayout(mtd, &qi_lb60_ooblayout_ops);
 }
 
 static struct jz_nand_platform_data qi_lb60_nand_pdata = {
@@ -367,43 +380,12 @@ static struct jz4740_mmc_platform_data q
 	.power_active_low	= 1,
 };
 
-/* OHCI */
-static struct regulator_consumer_supply avt2_usb_regulator_consumer =
-	REGULATOR_SUPPLY("vbus", "jz4740-ohci");
-
-static struct regulator_init_data avt2_usb_regulator_init_data = {
-	.num_consumer_supplies = 1,
-	.consumer_supplies = &avt2_usb_regulator_consumer,
-	.constraints = {
-		.name = "USB power",
-		.min_uV = 5000000,
-		.max_uV = 5000000,
-		.valid_modes_mask = REGULATOR_MODE_NORMAL,
-		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
-	},
-};
-
-static struct fixed_voltage_config avt2_usb_regulator_data = {
-	.supply_name = "USB power",
-	.microvolts = 5000000,
-	.gpio = JZ_GPIO_PORTB(17),
-	.init_data = &avt2_usb_regulator_init_data,
-};
-
-static struct platform_device avt2_usb_regulator_device = {
-	.name = "reg-fixed-voltage",
-	.id = -1,
-	.dev = {
-		.platform_data = &avt2_usb_regulator_data,
-	}
-};
-
+/* beeper */
 static struct pwm_lookup qi_lb60_pwm_lookup[] = {
 	PWM_LOOKUP("jz4740-pwm", 4, "pwm-beeper", NULL, 0,
 		   PWM_POLARITY_NORMAL),
 };
 
-/* beeper */
 static struct platform_device qi_lb60_pwm_beeper = {
 	.name = "pwm-beeper",
 	.id = -1,
@@ -487,11 +469,6 @@ static int __init qi_lb60_init_platform_
 	spi_register_board_info(qi_lb60_spi_board_info,
 				ARRAY_SIZE(qi_lb60_spi_board_info));
 
-	if (is_avt2) {
-		platform_device_register(&avt2_usb_regulator_device);
-		platform_device_register(&jz4740_usb_ohci_device);
-	}
-
 	pwm_add_table(qi_lb60_pwm_lookup, ARRAY_SIZE(qi_lb60_pwm_lookup));
 
 	return platform_add_devices(jz_platform_devices,
@@ -499,19 +476,9 @@ static int __init qi_lb60_init_platform_
 
 }
 
-static __init int board_avt2(char *str)
-{
-	qi_lb60_mmc_pdata.card_detect_active_low = 1;
-	is_avt2 = true;
-
-	return 1;
-}
-__setup("avt2", board_avt2);
-
 static int __init qi_lb60_board_setup(void)
 {
-	printk(KERN_INFO "Qi Hardware JZ4740 QI %s setup\n",
-		is_avt2 ? "AVT2" : "LB60");
+	printk(KERN_INFO "Qi Hardware JZ4740 QI LB60 setup\n");
 
 	board_gpio_setup();
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/jz4740/platform.c linux-libre-4.7-gnu/arch/mips/jz4740/platform.c
--- linux-libre-4.6-gnu/arch/mips/jz4740/platform.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/jz4740/platform.c	2016-07-24 15:23:50.000000000 -0400
@@ -32,31 +32,6 @@
 
 #include "clock.h"
 
-/* OHCI controller */
-static struct resource jz4740_usb_ohci_resources[] = {
-	{
-		.start	= JZ4740_UHC_BASE_ADDR,
-		.end	= JZ4740_UHC_BASE_ADDR + 0x1000 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.start	= JZ4740_IRQ_UHC,
-		.end	= JZ4740_IRQ_UHC,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device jz4740_usb_ohci_device = {
-	.name		= "jz4740-ohci",
-	.id		= -1,
-	.dev = {
-		.dma_mask = &jz4740_usb_ohci_device.dev.coherent_dma_mask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-	},
-	.num_resources	= ARRAY_SIZE(jz4740_usb_ohci_resources),
-	.resource	= jz4740_usb_ohci_resources,
-};
-
 /* USB Device Controller */
 struct platform_device jz4740_udc_xceiv_device = {
 	.name = "usb_phy_generic",
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/Kconfig linux-libre-4.7-gnu/arch/mips/Kconfig
--- linux-libre-4.6-gnu/arch/mips/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -15,7 +15,7 @@ config MIPS
 	select HAVE_ARCH_KGDB
 	select HAVE_ARCH_SECCOMP_FILTER
 	select HAVE_ARCH_TRACEHOOK
-	select HAVE_BPF_JIT if !CPU_MICROMIPS
+	select HAVE_CBPF_JIT if !CPU_MICROMIPS
 	select HAVE_FUNCTION_TRACER
 	select HAVE_DYNAMIC_FTRACE
 	select HAVE_FTRACE_MCOUNT_RECORD
@@ -48,6 +48,7 @@ config MIPS
 	select GENERIC_SCHED_CLOCK if !CAVIUM_OCTEON_SOC
 	select GENERIC_CMOS_UPDATE
 	select HAVE_MOD_ARCH_SPECIFIC
+	select HAVE_NMI
 	select VIRT_TO_BUS
 	select MODULES_USE_ELF_REL if MODULES
 	select MODULES_USE_ELF_RELA if MODULES && 64BIT
@@ -62,6 +63,7 @@ config MIPS
 	select HAVE_IRQ_TIME_ACCOUNTING
 	select GENERIC_TIME_VSYSCALL
 	select ARCH_CLOCKSOURCE_DATA
+	select HANDLE_DOMAIN_IRQ
 
 menu "Machine selection"
 
@@ -79,7 +81,7 @@ config MIPS_ALCHEMY
 	select SYS_HAS_CPU_MIPS32_R1
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_APM_EMULATION
-	select ARCH_REQUIRE_GPIOLIB
+	select GPIOLIB
 	select SYS_SUPPORTS_ZBOOT
 	select COMMON_CLK
 
@@ -98,7 +100,7 @@ config AR7
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_SUPPORTS_MIPS16
 	select SYS_SUPPORTS_ZBOOT_UART16550
-	select ARCH_REQUIRE_GPIOLIB
+	select GPIOLIB
 	select VLYNQ
 	select HAVE_CLK
 	help
@@ -122,11 +124,11 @@ config ATH25
 config ATH79
 	bool "Atheros AR71XX/AR724X/AR913X based boards"
 	select ARCH_HAS_RESET_CONTROLLER
-	select ARCH_REQUIRE_GPIOLIB
 	select BOOT_RAW
 	select CEVT_R4K
 	select CSRC_R4K
 	select DMA_NONCOHERENT
+	select GPIOLIB
 	select HAVE_CLK
 	select COMMON_CLK
 	select CLKDEV_LOOKUP
@@ -137,7 +139,7 @@ config ATH79
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_BIG_ENDIAN
 	select SYS_SUPPORTS_MIPS16
-	select SYS_SUPPORTS_ZBOOT
+	select SYS_SUPPORTS_ZBOOT_UART_PROM
 	select USE_OF
 	help
 	  Support for the Atheros AR71XX/AR724X/AR913X SoCs.
@@ -170,7 +172,6 @@ config BMIPS_GENERIC
 	select USB_EHCI_BIG_ENDIAN_MMIO if CPU_BIG_ENDIAN
 	select USB_OHCI_BIG_ENDIAN_DESC if CPU_BIG_ENDIAN
 	select USB_OHCI_BIG_ENDIAN_MMIO if CPU_BIG_ENDIAN
-	select ARCH_WANT_OPTIONAL_GPIOLIB
 	help
 	  Build a generic DT-based kernel image that boots on select
 	  BCM33xx cable modem chips, BCM63xx DSL chips, and BCM7xxx set-top
@@ -179,7 +180,6 @@ config BMIPS_GENERIC
 
 config BCM47XX
 	bool "Broadcom BCM47XX based boards"
-	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select BOOT_RAW
 	select CEVT_R4K
 	select CSRC_R4K
@@ -196,6 +196,7 @@ config BCM47XX
 	select GPIOLIB
 	select LEDS_GPIO_REGISTER
 	select BCM47XX_NVRAM
+	select BCM47XX_SPROM
 	help
 	 Support for BCM47XX based boards
 
@@ -211,7 +212,7 @@ config BCM63XX
 	select SYS_SUPPORTS_BIG_ENDIAN
 	select SYS_HAS_EARLY_PRINTK
 	select SWAP_IO_SPACE
-	select ARCH_REQUIRE_GPIOLIB
+	select GPIOLIB
 	select HAVE_CLK
 	select MIPS_L1_CACHE_SHIFT_4
 	help
@@ -305,7 +306,7 @@ config MACH_INGENIC
 	select SYS_SUPPORTS_ZBOOT_UART16550
 	select DMA_NONCOHERENT
 	select IRQ_MIPS_CPU
-	select ARCH_REQUIRE_GPIOLIB
+	select GPIOLIB
 	select COMMON_CLK
 	select GENERIC_IRQ_CHIP
 	select BUILTIN_DTB
@@ -325,7 +326,7 @@ config LANTIQ
 	select SYS_SUPPORTS_MIPS16
 	select SYS_SUPPORTS_MULTITHREADING
 	select SYS_HAS_EARLY_PRINTK
-	select ARCH_REQUIRE_GPIOLIB
+	select GPIOLIB
 	select SWAP_IO_SPACE
 	select BOOT_RAW
 	select CLKDEV_LOOKUP
@@ -377,7 +378,6 @@ config MACH_LOONGSON64
 
 config MACH_PISTACHIO
 	bool "IMG Pistachio SoC based boards"
-	select ARCH_REQUIRE_GPIOLIB
 	select BOOT_ELF32
 	select BOOT_RAW
 	select CEVT_R4K
@@ -385,6 +385,7 @@ config MACH_PISTACHIO
 	select COMMON_CLK
 	select CSRC_R4K
 	select DMA_MAYBE_COHERENT
+	select GPIOLIB
 	select IRQ_MIPS_CPU
 	select LIBFDT
 	select MFD_SYSCON
@@ -397,6 +398,7 @@ config MACH_PISTACHIO
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_SUPPORTS_MIPS_CPS
 	select SYS_SUPPORTS_MULTITHREADING
+	select SYS_SUPPORTS_RELOCATABLE
 	select SYS_SUPPORTS_ZBOOT
 	select SYS_HAS_EARLY_PRINTK
 	select USE_GENERIC_EARLY_PRINTK_8250
@@ -406,13 +408,13 @@ config MACH_PISTACHIO
 
 config MACH_XILFPGA
 	bool "MIPSfpga Xilinx based boards"
-	select ARCH_REQUIRE_GPIOLIB
 	select BOOT_ELF32
 	select BOOT_RAW
 	select BUILTIN_DTB
 	select CEVT_R4K
 	select COMMON_CLK
 	select CSRC_R4K
+	select GPIOLIB
 	select IRQ_MIPS_CPU
 	select LIBFDT
 	select MIPS_CPU_SCACHE
@@ -473,6 +475,7 @@ config MIPS_MALTA
 	select SYS_SUPPORTS_MULTITHREADING
 	select SYS_SUPPORTS_SMARTMIPS
 	select SYS_SUPPORTS_ZBOOT
+	select SYS_SUPPORTS_RELOCATABLE
 	select USE_OF
 	select ZONE_DMA32 if 64BIT
 	select BUILTIN_DTB
@@ -507,6 +510,7 @@ config MIPS_SEAD3
 	select MIPS_MSC
 	select SYS_HAS_CPU_MIPS32_R1
 	select SYS_HAS_CPU_MIPS32_R2
+	select SYS_HAS_CPU_MIPS32_R6
 	select SYS_HAS_CPU_MIPS64_R1
 	select SYS_HAS_EARLY_PRINTK
 	select SYS_SUPPORTS_32BIT_KERNEL
@@ -516,6 +520,7 @@ config MIPS_SEAD3
 	select SYS_SUPPORTS_SMARTMIPS
 	select SYS_SUPPORTS_MICROMIPS
 	select SYS_SUPPORTS_MIPS16
+	select SYS_SUPPORTS_RELOCATABLE
 	select USB_EHCI_BIG_ENDIAN_DESC
 	select USB_EHCI_BIG_ENDIAN_MMIO
 	select USE_OF
@@ -536,7 +541,7 @@ config MACH_VR41XX
 	select CSRC_R4K
 	select SYS_HAS_CPU_VR41XX
 	select SYS_SUPPORTS_MIPS16
-	select ARCH_REQUIRE_GPIOLIB
+	select GPIOLIB
 
 config NXP_STB220
 	bool "NXP STB220 board"
@@ -856,7 +861,7 @@ config MIKROTIK_RB532
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SWAP_IO_SPACE
 	select BOOT_RAW
-	select ARCH_REQUIRE_GPIOLIB
+	select GPIOLIB
 	select MIPS_L1_CACHE_SHIFT_4
 	help
 	  Support the Mikrotik(tm) RouterBoard 532 series,
@@ -879,7 +884,7 @@ config CAVIUM_OCTEON_SOC
 	select HW_HAS_PCI
 	select ZONE_DMA32
 	select HOLES_IN_ZONE
-	select ARCH_REQUIRE_GPIOLIB
+	select GPIOLIB
 	select LIBFDT
 	select USE_OF
 	select ARCH_SPARSEMEM_ENABLE
@@ -937,7 +942,7 @@ config NLM_XLP_BOARD
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_64BIT_KERNEL
 	select ARCH_PHYS_ADDR_T_64BIT
-	select ARCH_REQUIRE_GPIOLIB
+	select GPIOLIB
 	select SYS_SUPPORTS_BIG_ENDIAN
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_SUPPORTS_HIGHMEM
@@ -1077,7 +1082,7 @@ config MIPS_CLOCK_VSYSCALL
 	def_bool CSRC_R4K || CLKSRC_MIPS_GIC
 
 config GPIO_TXX9
-	select ARCH_REQUIRE_GPIOLIB
+	select GPIOLIB
 	bool
 
 config FW_CFE
@@ -1155,6 +1160,13 @@ config ISA_DMA_API
 config HOLES_IN_ZONE
 	bool
 
+config SYS_SUPPORTS_RELOCATABLE
+	bool
+	help
+	 Selected if the platform supports relocating the kernel.
+	 The platform must provide plat_get_fdt() if it selects CONFIG_USE_OF
+	 to allow access to command line and entropy sources.
+
 #
 # Endianness selection.  Sufficiently obscure so many users don't know what to
 # answer,so we try hard to limit the available choices.  Also the use of a
@@ -1342,11 +1354,30 @@ config CPU_LOONGSON3
 	select CPU_SUPPORTS_HUGEPAGES
 	select WEAK_ORDERING
 	select WEAK_REORDERING_BEYOND_LLSC
-	select ARCH_REQUIRE_GPIOLIB
+	select MIPS_PGD_C0_CONTEXT
+	select GPIOLIB
 	help
 		The Loongson 3 processor implements the MIPS64R2 instruction
 		set with many extensions.
 
+config LOONGSON3_ENHANCEMENT
+	bool "New Loongson 3 CPU Enhancements"
+	default n
+	select CPU_MIPSR2
+	select CPU_HAS_PREFETCH
+	depends on CPU_LOONGSON3
+	help
+	  New Loongson 3 CPU (since Loongson-3A R2, as opposed to Loongson-3A
+	  R1, Loongson-3B R1 and Loongson-3B R2) has many enhancements, such as
+	  FTLB, L1-VCache, EI/DI/Wait/Prefetch instruction, DSP/DSPv2 ASE, User
+	  Local register, Read-Inhibit/Execute-Inhibit, SFB (Store Fill Buffer),
+	  Fast TLB refill support, etc.
+
+	  This option enable those enhancements which are not probed at run
+	  time. If you want a generic kernel to run on all Loongson 3 machines,
+	  please say 'N' here. If you want a high-performance kernel to run on
+	  new Loongson 3 machines only, please say 'Y' here.
+
 config CPU_LOONGSON2E
 	bool "Loongson 2E"
 	depends on SYS_HAS_CPU_LOONGSON2E
@@ -1362,7 +1393,7 @@ config CPU_LOONGSON2F
 	bool "Loongson 2F"
 	depends on SYS_HAS_CPU_LOONGSON2F
 	select CPU_LOONGSON2
-	select ARCH_REQUIRE_GPIOLIB
+	select GPIOLIB
 	help
 	  The Loongson 2F processor implements the MIPS III instruction set
 	  with many extensions.
@@ -1375,6 +1406,8 @@ config CPU_LOONGSON1B
 	bool "Loongson 1B"
 	depends on SYS_HAS_CPU_LOONGSON1B
 	select CPU_LOONGSON1
+	select ARCH_WANT_OPTIONAL_GPIOLIB
+	select LEDS_GPIO_REGISTER
 	help
 	  The Loongson 1B is a 32-bit SoC, which implements the MIPS32
 	  release 2 instruction set.
@@ -1673,6 +1706,7 @@ config CPU_XLP
 	select CPU_HAS_PREFETCH
 	select CPU_MIPSR2
 	select CPU_SUPPORTS_HUGEPAGES
+	select MIPS_ASID_BITS_VARIABLE
 	help
 	  Netlogic Microsystems XLP processors.
 endchoice
@@ -1798,6 +1832,7 @@ config CPU_BMIPS4380
 	select MIPS_L1_CACHE_SHIFT_6
 	select SYS_SUPPORTS_SMP
 	select SYS_SUPPORTS_HOTPLUG_CPU
+	select CPU_HAS_RIXI
 
 config CPU_BMIPS5000
 	bool
@@ -1805,10 +1840,12 @@ config CPU_BMIPS5000
 	select MIPS_L1_CACHE_SHIFT_7
 	select SYS_SUPPORTS_SMP
 	select SYS_SUPPORTS_HOTPLUG_CPU
+	select CPU_HAS_RIXI
 
 config SYS_HAS_CPU_LOONGSON3
 	bool
 	select CPU_SUPPORTS_CPUFREQ
+	select CPU_HAS_RIXI
 
 config SYS_HAS_CPU_LOONGSON2E
 	bool
@@ -1961,11 +1998,15 @@ config CPU_MIPSR1
 config CPU_MIPSR2
 	bool
 	default y if CPU_MIPS32_R2 || CPU_MIPS64_R2 || CPU_CAVIUM_OCTEON
+	select CPU_HAS_RIXI
 	select MIPS_SPRAM
 
 config CPU_MIPSR6
 	bool
 	default y if CPU_MIPS32_R6 || CPU_MIPS64_R6
+	select CPU_HAS_RIXI
+	select HAVE_ARCH_BITREVERSE
+	select MIPS_ASID_BITS_VARIABLE
 	select MIPS_SPRAM
 
 config EVA
@@ -1999,7 +2040,7 @@ config MIPS_PGD_C0_CONTEXT
 #
 config HARDWARE_WATCHPOINTS
        bool
-       default y if CPU_MIPSR1 || CPU_MIPSR2
+       default y if CPU_MIPSR1 || CPU_MIPSR2 || CPU_MIPSR6
 
 menu "Kernel type"
 
@@ -2042,6 +2083,16 @@ config KVM_GUEST_TIMER_FREQ
 	  emulation when determining guest CPU Frequency. Instead, the guest's
 	  timer frequency is specified directly.
 
+config MIPS_VA_BITS_48
+	bool "48 bits virtual memory"
+	depends on 64BIT
+	help
+	  Support a maximum at least 48 bits of application virtual memory.
+	  Default is 40 bits or less, depending on the CPU.
+	  This option result in a small memory overhead for page tables.
+	  This option is only supported with 16k and 64k page sizes.
+	  If unsure, say N.
+
 choice
 	prompt "Kernel page size"
 	default PAGE_SIZE_4KB
@@ -2049,6 +2100,7 @@ choice
 config PAGE_SIZE_4KB
 	bool "4kB"
 	depends on !CPU_LOONGSON2 && !CPU_LOONGSON3
+	depends on !MIPS_VA_BITS_48
 	help
 	 This option select the standard 4kB Linux page size.  On some
 	 R3000-family processors this is the only available page size.  Using
@@ -2058,6 +2110,7 @@ config PAGE_SIZE_4KB
 config PAGE_SIZE_8KB
 	bool "8kB"
 	depends on CPU_R8000 || CPU_CAVIUM_OCTEON
+	depends on !MIPS_VA_BITS_48
 	help
 	  Using 8kB page size will result in higher performance kernel at
 	  the price of higher memory consumption.  This option is available
@@ -2076,6 +2129,7 @@ config PAGE_SIZE_16KB
 config PAGE_SIZE_32KB
 	bool "32kB"
 	depends on CPU_CAVIUM_OCTEON
+	depends on !MIPS_VA_BITS_48
 	help
 	  Using 32kB page size will result in higher performance kernel at
 	  the price of higher memory consumption.  This option is available
@@ -2280,7 +2334,7 @@ config MIPS_CMP
 
 config MIPS_CPS
 	bool "MIPS Coherent Processing System support"
-	depends on SYS_SUPPORTS_MIPS_CPS && !CPU_MIPSR6
+	depends on SYS_SUPPORTS_MIPS_CPS
 	select MIPS_CM
 	select MIPS_CPC
 	select MIPS_CPS_PM if HOTPLUG_CPU
@@ -2371,6 +2425,9 @@ config CPU_HAS_WB
 config XKS01
 	bool
 
+config CPU_HAS_RIXI
+	bool
+
 #
 # Vectored interrupt mode is an R2 feature
 #
@@ -2401,6 +2458,21 @@ config CPU_R4000_WORKAROUNDS
 config CPU_R4400_WORKAROUNDS
 	bool
 
+config MIPS_ASID_SHIFT
+	int
+	default 6 if CPU_R3000 || CPU_TX39XX
+	default 4 if CPU_R8000
+	default 0
+
+config MIPS_ASID_BITS
+	int
+	default 0 if MIPS_ASID_BITS_VARIABLE
+	default 6 if CPU_R3000 || CPU_TX39XX
+	default 8
+
+config MIPS_ASID_BITS_VARIABLE
+	bool
+
 #
 # - Highmem only makes sense for the 32-bit kernel.
 # - The current highmem code will only work properly on physically indexed
@@ -2470,6 +2542,61 @@ config NUMA
 config SYS_SUPPORTS_NUMA
 	bool
 
+config RELOCATABLE
+	bool "Relocatable kernel"
+	depends on SYS_SUPPORTS_RELOCATABLE && (CPU_MIPS32_R2 || CPU_MIPS64_R2 || CPU_MIPS32_R6 || CPU_MIPS64_R6)
+	help
+	  This builds a kernel image that retains relocation information
+	  so it can be loaded someplace besides the default 1MB.
+	  The relocations make the kernel binary about 15% larger,
+	  but are discarded at runtime
+
+config RELOCATION_TABLE_SIZE
+	hex "Relocation table size"
+	depends on RELOCATABLE
+	range 0x0 0x01000000
+	default "0x00100000"
+	---help---
+	  A table of relocation data will be appended to the kernel binary
+	  and parsed at boot to fix up the relocated kernel.
+
+	  This option allows the amount of space reserved for the table to be
+	  adjusted, although the default of 1Mb should be ok in most cases.
+
+	  The build will fail and a valid size suggested if this is too small.
+
+	  If unsure, leave at the default value.
+
+config RANDOMIZE_BASE
+	bool "Randomize the address of the kernel image"
+	depends on RELOCATABLE
+	---help---
+	   Randomizes the physical and virtual address at which the
+	   kernel image is loaded, as a security feature that
+	   deters exploit attempts relying on knowledge of the location
+	   of kernel internals.
+
+	   Entropy is generated using any coprocessor 0 registers available.
+
+	   The kernel will be offset by up to RANDOMIZE_BASE_MAX_OFFSET.
+
+	   If unsure, say N.
+
+config RANDOMIZE_BASE_MAX_OFFSET
+	hex "Maximum kASLR offset" if EXPERT
+	depends on RANDOMIZE_BASE
+	range 0x0 0x40000000 if EVA || 64BIT
+	range 0x0 0x08000000
+	default "0x01000000"
+	---help---
+	  When kASLR is active, this provides the maximum offset that will
+	  be applied to the kernel image. It should be set according to the
+	  amount of physical RAM available in the target system minus
+	  PHYSICAL_START and must be a power of 2.
+
+	  This is limited by the size of KSEG0, 256Mb on 32-bit or 1Gb with
+	  EVA or 64-bit. The default is 16Mb.
+
 config NODES_SHIFT
 	int
 	default "6"
@@ -2477,7 +2604,7 @@ config NODES_SHIFT
 
 config HW_PERF_EVENTS
 	bool "Enable hardware performance counter support for perf events"
-	depends on PERF_EVENTS && OPROFILE=n && (CPU_MIPS32 || CPU_MIPS64 || CPU_R10000 || CPU_SB1 || CPU_CAVIUM_OCTEON || CPU_XLP || CPU_LOONGSON3)
+	depends on PERF_EVENTS && !OPROFILE && (CPU_MIPS32 || CPU_MIPS64 || CPU_R10000 || CPU_SB1 || CPU_CAVIUM_OCTEON || CPU_XLP || CPU_LOONGSON3)
 	default y
 	help
 	  Enable hardware performance counter support for perf events. If
@@ -2810,6 +2937,10 @@ choice
 
 	config MIPS_CMDLINE_FROM_BOOTLOADER
 		bool "Bootloader kernel arguments if available"
+
+	config MIPS_CMDLINE_BUILTIN_EXTEND
+		depends on CMDLINE_BOOL
+		bool "Extend builtin kernel arguments with bootloader arguments"
 endchoice
 
 endmenu
@@ -2987,6 +3118,7 @@ config MIPS32_N32
 config BINFMT_ELF32
 	bool
 	default y if MIPS32_O32 || MIPS32_N32
+	select ELFCORE
 
 endmenu
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/asm-offsets.c linux-libre-4.7-gnu/arch/mips/kernel/asm-offsets.c
--- linux-libre-4.6-gnu/arch/mips/kernel/asm-offsets.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/asm-offsets.c	2016-07-24 15:23:50.000000000 -0400
@@ -14,6 +14,7 @@
 #include <linux/mm.h>
 #include <linux/kbuild.h>
 #include <linux/suspend.h>
+#include <asm/cpu-info.h>
 #include <asm/pm.h>
 #include <asm/ptrace.h>
 #include <asm/processor.h>
@@ -338,6 +339,15 @@ void output_pm_defines(void)
 }
 #endif
 
+void output_cpuinfo_defines(void)
+{
+	COMMENT(" MIPS cpuinfo offsets. ");
+	DEFINE(CPUINFO_SIZE, sizeof(struct cpuinfo_mips));
+#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE
+	OFFSET(CPUINFO_ASID_MASK, cpuinfo_mips, asid_mask);
+#endif
+}
+
 void output_kvm_defines(void)
 {
 	COMMENT(" KVM/MIPS Specfic offsets. ");
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/binfmt_elfn32.c linux-libre-4.7-gnu/arch/mips/kernel/binfmt_elfn32.c
--- linux-libre-4.6-gnu/arch/mips/kernel/binfmt_elfn32.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/binfmt_elfn32.c	2016-07-24 15:23:50.000000000 -0400
@@ -30,21 +30,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N
 /*
  * This is used to ensure we don't load something for the wrong architecture.
  */
-#define elf_check_arch(hdr)						\
-({									\
-	int __res = 1;							\
-	struct elfhdr *__h = (hdr);					\
-									\
-	if (!mips_elf_check_machine(__h))				\
-		__res = 0;						\
-	if (__h->e_ident[EI_CLASS] != ELFCLASS32)			\
-		__res = 0;						\
-	if (((__h->e_flags & EF_MIPS_ABI2) == 0) ||			\
-	    ((__h->e_flags & EF_MIPS_ABI) != 0))			\
-		__res = 0;						\
-									\
-	__res;								\
-})
+#define elf_check_arch elfn32_check_arch
 
 #define TASK32_SIZE		0x7fff8000UL
 #undef ELF_ET_DYN_BASE
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/binfmt_elfo32.c linux-libre-4.7-gnu/arch/mips/kernel/binfmt_elfo32.c
--- linux-libre-4.6-gnu/arch/mips/kernel/binfmt_elfo32.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/binfmt_elfo32.c	2016-07-24 15:23:50.000000000 -0400
@@ -28,39 +28,9 @@ typedef double elf_fpreg_t;
 typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
 
 /*
- * In order to be sure that we don't attempt to execute an O32 binary which
- * requires 64 bit FP (FR=1) on a system which does not support it we refuse
- * to execute any binary which has bits specified by the following macro set
- * in its ELF header flags.
- */
-#ifdef CONFIG_MIPS_O32_FP64_SUPPORT
-# define __MIPS_O32_FP64_MUST_BE_ZERO	0
-#else
-# define __MIPS_O32_FP64_MUST_BE_ZERO	EF_MIPS_FP64
-#endif
-
-/*
  * This is used to ensure we don't load something for the wrong architecture.
  */
-#define elf_check_arch(hdr)						\
-({									\
-	int __res = 1;							\
-	struct elfhdr *__h = (hdr);					\
-									\
-	if (!mips_elf_check_machine(__h))				\
-		__res = 0;						\
-	if (__h->e_ident[EI_CLASS] != ELFCLASS32)			\
-		__res = 0;						\
-	if ((__h->e_flags & EF_MIPS_ABI2) != 0)				\
-		__res = 0;						\
-	if (((__h->e_flags & EF_MIPS_ABI) != 0) &&			\
-	    ((__h->e_flags & EF_MIPS_ABI) != EF_MIPS_ABI_O32))		\
-		__res = 0;						\
-	if (__h->e_flags & __MIPS_O32_FP64_MUST_BE_ZERO)		\
-		__res = 0;						\
-									\
-	__res;								\
-})
+#define elf_check_arch elfo32_check_arch
 
 #ifdef CONFIG_KVM_GUEST
 #define TASK32_SIZE		0x3fff8000UL
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/bmips_5xxx_init.S linux-libre-4.7-gnu/arch/mips/kernel/bmips_5xxx_init.S
--- linux-libre-4.6-gnu/arch/mips/kernel/bmips_5xxx_init.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/mips/kernel/bmips_5xxx_init.S	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,753 @@
+
+/*
+ * 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.
+ *
+ * Copyright (C) 2011-2012 by Broadcom Corporation
+ *
+ * Init for bmips 5000.
+ * Used to init second core in dual core 5000's.
+ */
+
+#include <linux/init.h>
+
+#include <asm/asm.h>
+#include <asm/asmmacro.h>
+#include <asm/cacheops.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/stackframe.h>
+#include <asm/addrspace.h>
+#include <asm/hazards.h>
+#include <asm/bmips.h>
+
+#ifdef CONFIG_CPU_BMIPS5000
+
+
+#define cacheop(kva, size, linesize, op) 	\
+	.set noreorder			;	\
+	addu		t1, kva, size	;	\
+	subu		t2, linesize, 1	;	\
+	not		t2		;	\
+	and		t0, kva, t2	;	\
+	addiu		t1, t1, -1	;	\
+	and		t1, t2		;	\
+9:	cache		op, 0(t0)	;	\
+	bne		t0, t1, 9b	;	\
+	 addu		t0, linesize	;	\
+	.set reorder			;
+
+
+
+#define	IS_SHIFT	22
+#define	IL_SHIFT	19
+#define	IA_SHIFT	16
+#define	DS_SHIFT	13
+#define	DL_SHIFT	10
+#define	DA_SHIFT	 7
+#define	IS_MASK		 7
+#define	IL_MASK		 7
+#define	IA_MASK		 7
+#define	DS_MASK		 7
+#define	DL_MASK		 7
+#define	DA_MASK		 7
+#define	ICE_MASK	0x80000000
+#define	DCE_MASK	0x40000000
+
+#define CP0_BRCM_CONFIG0	$22, 0
+#define CP0_BRCM_MODE		$22, 1
+#define	CP0_CONFIG_K0_MASK	7
+
+#define CP0_ICACHE_TAG_LO	$28
+#define CP0_ICACHE_DATA_LO	$28, 1
+#define CP0_DCACHE_TAG_LO	$28, 2
+#define CP0_D_SEC_CACHE_DATA_LO	$28, 3
+#define CP0_ICACHE_TAG_HI	$29
+#define CP0_ICACHE_DATA_HI	$29, 1
+#define CP0_DCACHE_TAG_HI	$29, 2
+
+#define CP0_BRCM_MODE_Luc_MASK		(1 << 11)
+#define	CP0_BRCM_CONFIG0_CWF_MASK	(1 << 20)
+#define	CP0_BRCM_CONFIG0_TSE_MASK	(1 << 19)
+#define CP0_BRCM_MODE_SET_MASK		(1 << 7)
+#define CP0_BRCM_MODE_ClkRATIO_MASK	(7 << 4)
+#define CP0_BRCM_MODE_BrPRED_MASK 	(3 << 24)
+#define CP0_BRCM_MODE_BrPRED_SHIFT	24
+#define CP0_BRCM_MODE_BrHIST_MASK 	(0x1f << 20)
+#define CP0_BRCM_MODE_BrHIST_SHIFT	20
+
+/* ZSC L2 Cache Register Access Register Definitions */
+#define BRCM_ZSC_ALL_REGS_SELECT		0x7 << 24
+
+#define BRCM_ZSC_CONFIG_REG			0 << 3
+#define BRCM_ZSC_REQ_BUFFER_REG			2 << 3
+#define BRCM_ZSC_RBUS_ADDR_MAPPING_REG0		4 << 3
+#define BRCM_ZSC_RBUS_ADDR_MAPPING_REG1		6 << 3
+#define BRCM_ZSC_RBUS_ADDR_MAPPING_REG2		8 << 3
+
+#define BRCM_ZSC_SCB0_ADDR_MAPPING_REG0		0xa << 3
+#define BRCM_ZSC_SCB0_ADDR_MAPPING_REG1		0xc << 3
+
+#define BRCM_ZSC_SCB1_ADDR_MAPPING_REG0		0xe << 3
+#define BRCM_ZSC_SCB1_ADDR_MAPPING_REG1		0x10 << 3
+
+#define BRCM_ZSC_CONFIG_LMB1En			1 << (15)
+#define BRCM_ZSC_CONFIG_LMB0En			1 << (14)
+
+/* branch predition values */
+
+#define BRCM_BrPRED_ALL_TAKEN		(0x0)
+#define BRCM_BrPRED_ALL_NOT_TAKEN	(0x1)
+#define BRCM_BrPRED_BHT_ENABLE		(0x2)
+#define BRCM_BrPRED_PREDICT_BACKWARD	(0x3)
+
+
+
+.align 2
+/*
+ * Function: 	size_i_cache
+ * Arguments: 	None
+ * Returns:	v0 = i cache size, v1 = I cache line size
+ * Description: compute the I-cache size and I-cache line size
+ * Trashes:	v0, v1, a0, t0
+ *
+ *	pseudo code:
+ *
+ */
+
+LEAF(size_i_cache)
+	.set	noreorder
+
+	mfc0	a0, CP0_CONFIG, 1
+	move	t0, a0
+
+	/*
+	 * Determine sets per way: IS
+	 *
+	 * This field contains the number of sets (i.e., indices) per way of
+	 * the instruction cache:
+	 * i) 0x0: 64, ii) 0x1: 128, iii) 0x2: 256, iv) 0x3: 512, v) 0x4: 1k
+	 * vi) 0x5 - 0x7: Reserved.
+	 */
+
+	srl	a0, a0, IS_SHIFT
+	and	a0, a0, IS_MASK
+
+	/* sets per way = (64<<IS) */
+
+	li	v0, 0x40
+	sllv	v0, v0, a0
+
+	/*
+	 * Determine line size
+	 *
+	 * This field contains the line size of the instruction cache:
+	 * i) 0x0: No I-cache present, i) 0x3: 16 bytes, ii) 0x4: 32 bytes, iii)
+	 * 0x5: 64 bytes, iv) the rest: Reserved.
+	 */
+
+	move	a0, t0
+
+	srl	a0, a0, IL_SHIFT
+	and	a0, a0, IL_MASK
+
+	beqz	a0, no_i_cache
+	nop
+
+	/* line size = 2 ^ (IL+1) */
+
+	addi	a0, a0, 1
+	li	v1, 1
+	sll	v1, v1, a0
+
+	/* v0 now have sets per way, multiply it by line size now
+	 * that will give the set size
+	 */
+
+	sll	v0, v0, a0
+
+	/*
+	 * Determine set associativity
+	 *
+	 * This field contains the set associativity of the instruction cache.
+	 * i) 0x0: Direct mapped, ii) 0x1: 2-way, iii) 0x2: 3-way, iv) 0x3:
+	 * 4-way, v) 0x4 - 0x7: Reserved.
+	 */
+
+	move	a0, t0
+
+	srl	a0, a0, IA_SHIFT
+	and	a0, a0, IA_MASK
+	addi	a0, a0, 0x1
+
+	/* v0 has the set size, multiply it by
+	 * set associativiy, to get the cache size
+	 */
+
+	multu	v0, a0	/*multu is interlocked, so no need to insert nops */
+	mflo	v0
+	b	1f
+	nop
+
+no_i_cache:
+	move	v0, zero
+	move	v1, zero
+1:
+	jr	ra
+	nop
+	.set	reorder
+
+END(size_i_cache)
+
+/*
+ * Function: 	size_d_cache
+ * Arguments: 	None
+ * Returns:	v0 = d cache size, v1 = d cache line size
+ * Description: compute the D-cache size and D-cache line size.
+ * Trashes:	v0, v1, a0, t0
+ *
+ */
+
+LEAF(size_d_cache)
+	.set	noreorder
+
+	mfc0	a0, CP0_CONFIG, 1
+	move	t0, a0
+
+	/*
+	 * Determine sets per way: IS
+	 *
+	 * This field contains the number of sets (i.e., indices) per way of
+	 * the instruction cache:
+	 * i) 0x0: 64, ii) 0x1: 128, iii) 0x2: 256, iv) 0x3: 512, v) 0x4: 1k
+	 * vi) 0x5 - 0x7: Reserved.
+	 */
+
+	srl	a0, a0, DS_SHIFT
+	and	a0, a0, DS_MASK
+
+	/* sets per way = (64<<IS) */
+
+	li	v0, 0x40
+	sllv	v0, v0, a0
+
+	/*
+	 * Determine line size
+	 *
+	 * This field contains the line size of the instruction cache:
+	 * i) 0x0: No I-cache present, i) 0x3: 16 bytes, ii) 0x4: 32 bytes, iii)
+	 * 0x5: 64 bytes, iv) the rest: Reserved.
+	 */
+	move	a0, t0
+
+	srl	a0, a0, DL_SHIFT
+	and	a0, a0, DL_MASK
+
+	beqz	a0, no_d_cache
+	nop
+
+	/* line size = 2 ^ (IL+1) */
+
+	addi	a0, a0, 1
+	li	v1, 1
+	sll	v1, v1, a0
+
+	/* v0 now have sets per way, multiply it by line size now
+	 * that will give the set size
+	 */
+
+	sll	v0, v0, a0
+
+	/* determine set associativity
+	 *
+	 * This field contains the set associativity of the instruction cache.
+	 * i) 0x0: Direct mapped, ii) 0x1: 2-way, iii) 0x2: 3-way, iv) 0x3:
+	 * 4-way, v) 0x4 - 0x7: Reserved.
+	 */
+
+	move	a0, t0
+
+	srl	a0, a0, DA_SHIFT
+	and	a0, a0, DA_MASK
+	addi	a0, a0, 0x1
+
+	/* v0 has the set size, multiply it by
+	 * set associativiy, to get the cache size
+	 */
+
+	multu	v0, a0	/*multu is interlocked, so no need to insert nops */
+	mflo	v0
+
+	b	1f
+	nop
+
+no_d_cache:
+	move	v0, zero
+	move	v1, zero
+1:
+	jr	ra
+	nop
+	.set	reorder
+
+END(size_d_cache)
+
+
+/*
+ * Function: enable_ID
+ * Arguments: 	None
+ * Returns:	None
+ * Description: Enable I and D caches, initialize I and D-caches, also set
+ *		hardware delay for d-cache (TP0).
+ * Trashes:	t0
+ *
+ */
+	.global	enable_ID
+	.ent	enable_ID
+	.set	noreorder
+enable_ID:
+	mfc0	t0, CP0_BRCM_CONFIG0
+	or	t0, t0, (ICE_MASK | DCE_MASK)
+	mtc0	t0, CP0_BRCM_CONFIG0
+	jr	ra
+	nop
+
+	.end	enable_ID
+	.set	reorder
+
+
+/*
+ * Function: l1_init
+ * Arguments: 	None
+ * Returns:	None
+ * Description: Enable I and D caches, and initialize I and D-caches
+ * Trashes:	a0, v0, v1, t0, t1, t2, t8
+ *
+ */
+	.globl	l1_init
+	.ent	l1_init
+	.set	noreorder
+l1_init:
+
+	/* save return address */
+	move	t8, ra
+
+
+	/* initialize I and D cache Data and Tag registers.  */
+	mtc0	zero, CP0_ICACHE_TAG_LO
+	mtc0	zero, CP0_ICACHE_TAG_HI
+	mtc0	zero, CP0_ICACHE_DATA_LO
+	mtc0	zero, CP0_ICACHE_DATA_HI
+	mtc0	zero, CP0_DCACHE_TAG_LO
+	mtc0	zero, CP0_DCACHE_TAG_HI
+
+	/* Enable Caches before Clearing. If the caches are disabled
+	 * then the cache operations to clear the cache will be ignored
+	 */
+
+	jal	enable_ID
+	nop
+
+	jal	size_i_cache	/* v0 = i-cache size, v1 = i-cache line size */
+	nop
+
+	/* run uncached in kseg 1 */
+	la	k0, 1f
+	lui	k1, 0x2000
+	or	k0, k1, k0
+	jr	k0
+	nop
+1:
+
+	/*
+	 * set K0 cache mode
+	 */
+
+	mfc0	t0, CP0_CONFIG
+	and	t0, t0, ~CP0_CONFIG_K0_MASK
+	or	t0, t0, 3	/* Write Back mode */
+	mtc0	t0, CP0_CONFIG
+
+	/*
+	 * Initialize instruction cache.
+	 */
+
+	li	a0, KSEG0
+	cacheop(a0, v0, v1, Index_Store_Tag_I)
+
+	/*
+	 * Now we can run from I-$, kseg 0
+	 */
+	la	k0, 1f
+	lui	k1, 0x2000
+	or	k0, k1, k0
+	xor	k0, k1, k0
+	jr	k0
+	nop
+1:
+	/*
+	 * Initialize data cache.
+	 */
+
+	jal	size_d_cache	/* v0 = d-cache size, v1 = d-cache line size */
+	nop
+
+
+	li	a0, KSEG0
+	cacheop(a0, v0, v1, Index_Store_Tag_D)
+
+	jr	t8
+	nop
+
+	.end 	l1_init
+	.set	reorder
+
+
+/*
+ * Function: 	set_other_config
+ * Arguments:	none
+ * Returns:	None
+ * Description: initialize other remainder configuration to defaults.
+ * Trashes:	t0, t1
+ *
+ *	pseudo code:
+ *
+ */
+LEAF(set_other_config)
+	.set noreorder
+
+	/* enable Bus error for I-fetch */
+	mfc0	t0, CP0_CACHEERR, 0
+	li	t1, 0x4
+	or	t0, t1
+	mtc0	t0, CP0_CACHEERR, 0
+
+	/* enable Bus error for Load */
+	mfc0	t0, CP0_CACHEERR, 1
+	li	t1, 0x4
+	or	t0, t1
+	mtc0	t0, CP0_CACHEERR, 1
+
+	/* enable Bus Error for Store */
+	mfc0	t0, CP0_CACHEERR, 2
+	li	t1, 0x4
+	or	t0, t1
+	mtc0	t0, CP0_CACHEERR, 2
+
+	jr	ra
+	nop
+	.set reorder
+END(set_other_config)
+
+/*
+ * Function: 	set_branch_pred
+ * Arguments:	none
+ * Returns:	None
+ * Description:
+ * Trashes:	t0, t1
+ *
+ *	pseudo code:
+ *
+ */
+
+LEAF(set_branch_pred)
+	.set noreorder
+	mfc0	t0, CP0_BRCM_MODE
+	li	t1, ~(CP0_BRCM_MODE_BrPRED_MASK | CP0_BRCM_MODE_BrHIST_MASK )
+	and	t0, t0, t1
+
+	/* enable Branch prediction */
+	li	t1, BRCM_BrPRED_BHT_ENABLE
+	sll	t1, CP0_BRCM_MODE_BrPRED_SHIFT
+	or	t0, t0, t1
+
+	/* set history count to 8 */
+	li	t1, 8
+	sll	t1, CP0_BRCM_MODE_BrHIST_SHIFT
+	or	t0, t0, t1
+
+	mtc0	t0, CP0_BRCM_MODE
+	jr	ra
+	nop
+	.set	reorder
+END(set_branch_pred)
+
+
+/*
+ * Function: 	set_luc
+ * Arguments:	set link uncached.
+ * Returns:	None
+ * Description:
+ * Trashes:	t0, t1
+ *
+ */
+LEAF(set_luc)
+	.set noreorder
+	mfc0	t0, CP0_BRCM_MODE
+	li	t1, ~(CP0_BRCM_MODE_Luc_MASK)
+	and	t0, t0, t1
+
+	/* set Luc */
+	ori	t0, t0, CP0_BRCM_MODE_Luc_MASK
+
+	mtc0	t0, CP0_BRCM_MODE
+	jr	ra
+	nop
+	.set	reorder
+END(set_luc)
+
+/*
+ * Function: 	set_cwf_tse
+ * Arguments:	set CWF and TSE bits
+ * Returns:	None
+ * Description:
+ * Trashes:	t0, t1
+ *
+ */
+LEAF(set_cwf_tse)
+	.set noreorder
+	mfc0	t0, CP0_BRCM_CONFIG0
+	li	t1, (CP0_BRCM_CONFIG0_CWF_MASK | CP0_BRCM_CONFIG0_TSE_MASK)
+	or	t0, t0, t1
+
+	mtc0	t0, CP0_BRCM_CONFIG0
+	jr	ra
+	nop
+	.set	reorder
+END(set_cwf_tse)
+
+/*
+ * Function: 	set_clock_ratio
+ * Arguments:	set clock ratio specified by a0
+ * Returns:	None
+ * Description:
+ * Trashes:	v0, v1, a0, a1
+ *
+ *	pseudo code:
+ *
+ */
+LEAF(set_clock_ratio)
+	.set noreorder
+
+	mfc0	t0, CP0_BRCM_MODE
+	li	t1, ~(CP0_BRCM_MODE_SET_MASK | CP0_BRCM_MODE_ClkRATIO_MASK)
+	and	t0, t0, t1
+	li	t1, CP0_BRCM_MODE_SET_MASK
+	or	t0, t0, t1
+	or	t0, t0, a0
+	mtc0	t0, CP0_BRCM_MODE
+	jr	ra
+	nop
+	.set	reorder
+END(set_clock_ratio)
+/*
+ * Function: set_zephyr
+ * Arguments:	None
+ * Returns:	None
+ * Description: Set any zephyr bits
+ * Trashes:	t0 & t1
+ *
+ */
+LEAF(set_zephyr)
+	.set	noreorder
+
+	/* enable read/write of CP0 #22 sel. 8 */
+	li	t0, 0x5a455048
+	.word	0x4088b00f	/* mtc0    t0, $22, 15 */
+
+	.word	0x4008b008	/* mfc0    t0, $22, 8 */
+	li	t1, 0x09008000	/* turn off pref, jtb */
+	or	t0, t0, t1
+	.word	0x4088b008	/* mtc0    t0, $22, 8 */
+	sync
+
+	/* disable read/write of CP0 #22 sel 8 */
+	li	t0, 0x0
+	.word	0x4088b00f	/* mtc0    t0, $22, 15 */
+
+
+	jr	ra
+	nop
+	.set reorder
+
+END(set_zephyr)
+
+
+/*
+ * Function:	set_llmb
+ * Arguments:	a0=0 disable llmb, a0=1 enables llmb
+ * Returns:	None
+ * Description:
+ * Trashes:	t0, t1, t2
+ *
+ *      pseudo code:
+ *
+ */
+LEAF(set_llmb)
+	.set noreorder
+
+	li	t2, 0x90000000 | BRCM_ZSC_ALL_REGS_SELECT | BRCM_ZSC_CONFIG_REG
+	sync
+	cache	0x7, 0x0(t2)
+	sync
+	mfc0	t0, CP0_D_SEC_CACHE_DATA_LO
+	li	t1, ~(BRCM_ZSC_CONFIG_LMB1En | BRCM_ZSC_CONFIG_LMB0En)
+	and	t0, t0, t1
+
+	beqz	a0, svlmb
+	nop
+
+enable_lmb:
+	li	t1, (BRCM_ZSC_CONFIG_LMB1En | BRCM_ZSC_CONFIG_LMB0En)
+	or	t0, t0, t1
+
+svlmb:
+	mtc0	t0, CP0_D_SEC_CACHE_DATA_LO
+	sync
+	cache	0xb, 0x0(t2)
+	sync
+
+	jr	ra
+	nop
+	.set reorder
+
+END(set_llmb)
+/*
+ * Function: 	core_init
+ * Arguments:	none
+ * Returns:	None
+ * Description: initialize core related configuration
+ * Trashes:	v0,v1,a0,a1,t8
+ *
+ *	pseudo code:
+ *
+ */
+	.globl	core_init
+	.ent	core_init
+	.set	noreorder
+core_init:
+	move	t8, ra
+
+	/* set Zephyr bits. */
+	bal	set_zephyr
+	nop
+
+#if ENABLE_FPU==1
+	/* initialize the Floating point unit (both TPs) */
+	bal	init_fpu
+	nop
+#endif
+
+	/* set low latency memory bus */
+	li	a0, 1
+	bal	set_llmb
+	nop
+
+	/* set branch prediction (TP0 only) */
+	bal	set_branch_pred
+	nop
+
+	/* set link uncached */
+	bal	set_luc
+	nop
+
+	/* set CWF and TSE */
+	bal	set_cwf_tse
+	nop
+
+	/*
+	 *set clock ratio by setting 1 to 'set'
+	 * and 0 to ClkRatio, (TP0 only)
+	 */
+	li	a0, 0
+	bal	set_clock_ratio
+	nop
+
+	/* set other configuration to defaults */
+	bal	set_other_config
+	nop
+
+	move	ra, t8
+	jr	ra
+	nop
+
+	.set reorder
+	.end	core_init
+
+/*
+ * Function: 	clear_jump_target_buffer
+ * Arguments:	None
+ * Returns:	None
+ * Description:
+ * Trashes:	t0, t1, t2
+ *
+ */
+#define RESET_CALL_RETURN_STACK_THIS_THREAD		(0x06<<16)
+#define RESET_JUMP_TARGET_BUFFER_THIS_THREAD		(0x04<<16)
+#define JTB_CS_CNTL_MASK				(0xFF<<16)
+
+	.globl	clear_jump_target_buffer
+	.ent	clear_jump_target_buffer
+	.set	noreorder
+clear_jump_target_buffer:
+
+	mfc0	t0, $22, 2
+	nop
+	nop
+
+	li	t1, ~JTB_CS_CNTL_MASK
+	and	t0, t0, t1
+	li	t2, RESET_CALL_RETURN_STACK_THIS_THREAD
+	or	t0, t0, t2
+	mtc0	t0, $22, 2
+	nop
+	nop
+
+	and	t0, t0, t1
+	li	t2, RESET_JUMP_TARGET_BUFFER_THIS_THREAD
+	or	t0, t0, t2
+	mtc0	t0, $22, 2
+	nop
+	nop
+	jr	ra
+	nop
+
+	.end	clear_jump_target_buffer
+	.set	reorder
+/*
+ * Function: 	bmips_cache_init
+ * Arguments: 	None
+ * Returns:	None
+ * Description: Enable I and D caches, and initialize I and D-caches
+ * Trashes:	v0, v1, t0, t1, t2, t5, t7, t8
+ *
+ */
+	.globl	bmips_5xxx_init
+	.ent	bmips_5xxx_init
+	.set	noreorder
+bmips_5xxx_init:
+
+	/* save return address and A0 */
+	move	t7, ra
+	move	t5, a0
+
+	jal	l1_init
+	nop
+
+	jal	core_init
+	nop
+
+	jal	clear_jump_target_buffer
+	nop
+
+	mtc0	zero, CP0_CAUSE
+
+	move 	a0, t5
+	jr	t7
+	nop
+
+	.end 	bmips_5xxx_init
+	.set	reorder
+
+
+#endif
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/bmips_vec.S linux-libre-4.7-gnu/arch/mips/kernel/bmips_vec.S
--- linux-libre-4.6-gnu/arch/mips/kernel/bmips_vec.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/bmips_vec.S	2016-07-24 15:23:50.000000000 -0400
@@ -88,12 +88,13 @@ NESTED(bmips_reset_nmi_vec, PT_SIZE, sp)
 	li	k1, (1 << 19)
 	mfc0	k0, CP0_STATUS
 	and	k0, k1
-	beqz	k0, bmips_smp_entry
+	beqz	k0, soft_reset
 
 #if defined(CONFIG_CPU_BMIPS5000)
 	mfc0	k0, CP0_PRID
 	li	k1, PRID_IMP_BMIPS5000
-	andi	k0, 0xff00
+	/* mask with PRID_IMP_BMIPS5000 to cover both variants */
+	andi	k0, PRID_IMP_BMIPS5000
 	bne	k0, k1, 1f
 
 	/* if we're not on core 0, this must be the SMP boot signal */
@@ -125,13 +126,48 @@ NESTED(bmips_reset_nmi_vec, PT_SIZE, sp)
 	.set	arch=r4000
 	eret
 
+#ifdef CONFIG_SMP
+soft_reset:
+
+#if defined(CONFIG_CPU_BMIPS5000)
+	mfc0	k0, CP0_PRID
+	andi	k0, 0xff00
+	li	k1, PRID_IMP_BMIPS5200
+	bne	k0, k1, bmips_smp_entry
+
+        /* if running on TP 1, jump  to  bmips_smp_entry */
+        mfc0    k0, $22
+        li      k1, (1 << 24)
+        and     k1, k0
+        bnez    k1, bmips_smp_entry
+        nop
+
+        /*
+         * running on TP0, can not be core 0 (the boot core).
+         * Check for soft reset.  Indicates a warm boot
+         */
+        mfc0    k0, $12
+        li      k1, (1 << 20)
+        and     k0, k1
+        beqz    k0, bmips_smp_entry
+
+        /*
+         * Warm boot.
+         * Cache init is only done on TP0
+         */
+        la      k0, bmips_5xxx_init
+        jalr    k0
+        nop
+
+        b       bmips_smp_entry
+        nop
+#endif
+
 /***********************************************************************
  * CPU1 reset vector (used for the initial boot only)
  * This is still part of bmips_reset_nmi_vec().
  ***********************************************************************/
 
-#ifdef CONFIG_SMP
-
 bmips_smp_entry:
 
 	/* set up CP0 STATUS; enable FPU */
@@ -166,10 +202,12 @@ bmips_smp_entry:
 2:
 #endif /* CONFIG_CPU_BMIPS4350 || CONFIG_CPU_BMIPS4380 */
 #if defined(CONFIG_CPU_BMIPS5000)
-	/* set exception vector base */
+	/* mask with PRID_IMP_BMIPS5000 to cover both variants */
 	li	k1, PRID_IMP_BMIPS5000
+	andi	k0, PRID_IMP_BMIPS5000
 	bne	k0, k1, 3f
 
+	/* set exception vector base */
 	la	k0, ebase
 	lw	k0, 0(k0)
 	mtc0	k0, $15, 1
@@ -263,6 +301,8 @@ LEAF(bmips_enable_xks01)
 #endif /* CONFIG_CPU_BMIPS4380 */
 #if defined(CONFIG_CPU_BMIPS5000)
 	li	t1, PRID_IMP_BMIPS5000
+	/* mask with PRID_IMP_BMIPS5000 to cover both variants */
+	andi	t2, PRID_IMP_BMIPS5000
 	bne	t2, t1, 2f
 
 	mfc0	t0, $22, 5
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/branch.c linux-libre-4.7-gnu/arch/mips/kernel/branch.c
--- linux-libre-4.6-gnu/arch/mips/kernel/branch.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/branch.c	2016-07-24 15:23:50.000000000 -0400
@@ -481,7 +481,7 @@ int __compute_return_epc_for_insn(struct
 			/*
 			 * OK we are here either because we hit a NAL
 			 * instruction or because we are emulating an
-			 * old bltzal{,l} one. Lets figure out what the
+			 * old bltzal{,l} one. Let's figure out what the
 			 * case really is.
 			 */
 			if (!insn.i_format.rs) {
@@ -515,7 +515,7 @@ int __compute_return_epc_for_insn(struct
 			/*
 			 * OK we are here either because we hit a BAL
 			 * instruction or because we are emulating an
-			 * old bgezal{,l} one. Lets figure out what the
+			 * old bgezal{,l} one. Let's figure out what the
 			 * case really is.
 			 */
 			if (!insn.i_format.rs) {
@@ -688,21 +688,9 @@ int __compute_return_epc_for_insn(struct
 			}
 			lose_fpu(1);    /* Save FPU state for the emulator. */
 			reg = insn.i_format.rt;
-			bit = 0;
-			switch (insn.i_format.rs) {
-			case bc1eqz_op:
-				/* Test bit 0 */
-				if (get_fpr32(&current->thread.fpu.fpr[reg], 0)
-				    & 0x1)
-					bit = 1;
-				break;
-			case bc1nez_op:
-				/* Test bit 0 */
-				if (!(get_fpr32(&current->thread.fpu.fpr[reg], 0)
-				      & 0x1))
-					bit = 1;
-				break;
-			}
+			bit = get_fpr32(&current->thread.fpu.fpr[reg], 0) & 0x1;
+			if (insn.i_format.rs == bc1eqz_op)
+				bit = !bit;
 			own_fpu(1);
 			if (bit)
 				epc = epc + 4 +
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/cevt-r4k.c linux-libre-4.7-gnu/arch/mips/kernel/cevt-r4k.c
--- linux-libre-4.6-gnu/arch/mips/kernel/cevt-r4k.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/cevt-r4k.c	2016-07-24 15:23:50.000000000 -0400
@@ -28,6 +28,83 @@ static int mips_next_event(unsigned long
 	return res;
 }
 
+/**
+ * calculate_min_delta() - Calculate a good minimum delta for mips_next_event().
+ *
+ * Running under virtualisation can introduce overhead into mips_next_event() in
+ * the form of hypervisor emulation of CP0_Count/CP0_Compare registers,
+ * potentially with an unnatural frequency, which makes a fixed min_delta_ns
+ * value inappropriate as it may be too small.
+ *
+ * It can also introduce occasional latency from the guest being descheduled.
+ *
+ * This function calculates a good minimum delta based roughly on the 75th
+ * percentile of the time taken to do the mips_next_event() sequence, in order
+ * to handle potentially higher overhead while also eliminating outliers due to
+ * unpredictable hypervisor latency (which can be handled by retries).
+ *
+ * Return:	An appropriate minimum delta for the clock event device.
+ */
+static unsigned int calculate_min_delta(void)
+{
+	unsigned int cnt, i, j, k, l;
+	unsigned int buf1[4], buf2[3];
+	unsigned int min_delta;
+
+	/*
+	 * Calculate the median of 5 75th percentiles of 5 samples of how long
+	 * it takes to set CP0_Compare = CP0_Count + delta.
+	 */
+	for (i = 0; i < 5; ++i) {
+		for (j = 0; j < 5; ++j) {
+			/*
+			 * This is like the code in mips_next_event(), and
+			 * directly measures the borderline "safe" delta.
+			 */
+			cnt = read_c0_count();
+			write_c0_compare(cnt);
+			cnt = read_c0_count() - cnt;
+
+			/* Sorted insert into buf1 */
+			for (k = 0; k < j; ++k) {
+				if (cnt < buf1[k]) {
+					l = min_t(unsigned int,
+						  j, ARRAY_SIZE(buf1) - 1);
+					for (; l > k; --l)
+						buf1[l] = buf1[l - 1];
+					break;
+				}
+			}
+			if (k < ARRAY_SIZE(buf1))
+				buf1[k] = cnt;
+		}
+
+		/* Sorted insert of 75th percentile into buf2 */
+		for (k = 0; k < i; ++k) {
+			if (buf1[ARRAY_SIZE(buf1) - 1] < buf2[k]) {
+				l = min_t(unsigned int,
+					  i, ARRAY_SIZE(buf2) - 1);
+				for (; l > k; --l)
+					buf2[l] = buf2[l - 1];
+				break;
+			}
+		}
+		if (k < ARRAY_SIZE(buf2))
+			buf2[k] = buf1[ARRAY_SIZE(buf1) - 1];
+	}
+
+	/* Use 2 * median of 75th percentiles */
+	min_delta = buf2[ARRAY_SIZE(buf2) - 1] * 2;
+
+	/* Don't go too low */
+	if (min_delta < 0x300)
+		min_delta = 0x300;
+
+	pr_debug("%s: median 75th percentile=%#x, min_delta=%#x\n",
+		 __func__, buf2[ARRAY_SIZE(buf2) - 1], min_delta);
+	return min_delta;
+}
+
 DEFINE_PER_CPU(struct clock_event_device, mips_clockevent_device);
 int cp0_timer_irq_installed;
 
@@ -177,7 +254,7 @@ int r4k_clockevent_init(void)
 {
 	unsigned int cpu = smp_processor_id();
 	struct clock_event_device *cd;
-	unsigned int irq;
+	unsigned int irq, min_delta;
 
 	if (!cpu_has_counter || !mips_hpt_frequency)
 		return -ENXIO;
@@ -203,7 +280,8 @@ int r4k_clockevent_init(void)
 
 	/* Calculate the min / max delta */
 	cd->max_delta_ns	= clockevent_delta2ns(0x7fffffff, cd);
-	cd->min_delta_ns	= clockevent_delta2ns(0x300, cd);
+	min_delta		= calculate_min_delta();
+	cd->min_delta_ns	= clockevent_delta2ns(min_delta, cd);
 
 	cd->rating		= 300;
 	cd->irq			= irq;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/cps-vec.S linux-libre-4.7-gnu/arch/mips/kernel/cps-vec.S
--- linux-libre-4.6-gnu/arch/mips/kernel/cps-vec.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/cps-vec.S	2016-07-24 15:23:50.000000000 -0400
@@ -18,9 +18,12 @@
 #include <asm/mipsmtregs.h>
 #include <asm/pm.h>
 
+#define GCR_CPC_BASE_OFS	0x0088
 #define GCR_CL_COHERENCE_OFS	0x2008
 #define GCR_CL_ID_OFS		0x2028
 
+#define CPC_CL_VC_RUN_OFS	0x2028
+
 .extern mips_cm_base
 
 .set noreorder
@@ -60,6 +63,37 @@
 	 nop
 	.endm
 
+	/*
+	 * Set dest to non-zero if the core supports MIPSr6 multithreading
+	 * (ie. VPs), else zero. If MIPSr6 multithreading is not supported then
+	 * branch to nomt.
+	 */
+	.macro	has_vp	dest, nomt
+	mfc0	\dest, CP0_CONFIG, 1
+	bgez	\dest, \nomt
+	 mfc0	\dest, CP0_CONFIG, 2
+	bgez	\dest, \nomt
+	 mfc0	\dest, CP0_CONFIG, 3
+	bgez	\dest, \nomt
+	 mfc0	\dest, CP0_CONFIG, 4
+	bgez	\dest, \nomt
+	 mfc0	\dest, CP0_CONFIG, 5
+	andi	\dest, \dest, MIPS_CONF5_VP
+	beqz	\dest, \nomt
+	 nop
+	.endm
+
+	/* Calculate an uncached address for the CM GCRs */
+	.macro	cmgcrb	dest
+	.set	push
+	.set	noat
+	MFC0	$1, CP0_CMGCRBASE
+	PTR_SLL	$1, $1, 4
+	PTR_LI	\dest, UNCAC_BASE
+	PTR_ADDU \dest, \dest, $1
+	.set	pop
+	.endm
+
 .section .text.cps-vec
 .balign 0x1000
 
@@ -90,120 +124,64 @@ not_nmi:
 	li	t0, ST0_CU1 | ST0_CU0 | ST0_BEV | STATUS_BITDEPS
 	mtc0	t0, CP0_STATUS
 
-	/*
-	 * Clear the bits used to index the caches. Note that the architecture
-	 * dictates that writing to any of TagLo or TagHi selects 0 or 2 should
-	 * be valid for all MIPS32 CPUs, even those for which said writes are
-	 * unnecessary.
-	 */
-	mtc0	zero, CP0_TAGLO, 0
-	mtc0	zero, CP0_TAGHI, 0
-	mtc0	zero, CP0_TAGLO, 2
-	mtc0	zero, CP0_TAGHI, 2
-	ehb
-
-	/* Primary cache configuration is indicated by Config1 */
-	mfc0	v0, CP0_CONFIG, 1
-
-	/* Detect I-cache line size */
-	_EXT	t0, v0, MIPS_CONF1_IL_SHF, MIPS_CONF1_IL_SZ
-	beqz	t0, icache_done
-	 li	t1, 2
-	sllv	t0, t1, t0
-
-	/* Detect I-cache size */
-	_EXT	t1, v0, MIPS_CONF1_IS_SHF, MIPS_CONF1_IS_SZ
-	xori	t2, t1, 0x7
-	beqz	t2, 1f
-	 li	t3, 32
-	addiu	t1, t1, 1
-	sllv	t1, t3, t1
-1:	/* At this point t1 == I-cache sets per way */
-	_EXT	t2, v0, MIPS_CONF1_IA_SHF, MIPS_CONF1_IA_SZ
-	addiu	t2, t2, 1
-	mul	t1, t1, t0
-	mul	t1, t1, t2
-
-	li	a0, CKSEG0
-	PTR_ADD	a1, a0, t1
-1:	cache	Index_Store_Tag_I, 0(a0)
-	PTR_ADD	a0, a0, t0
-	bne	a0, a1, 1b
+	/* Skip cache & coherence setup if we're already coherent */
+	cmgcrb	v1
+	lw	s7, GCR_CL_COHERENCE_OFS(v1)
+	bnez	s7, 1f
 	 nop
-icache_done:
 
-	/* Detect D-cache line size */
-	_EXT	t0, v0, MIPS_CONF1_DL_SHF, MIPS_CONF1_DL_SZ
-	beqz	t0, dcache_done
-	 li	t1, 2
-	sllv	t0, t1, t0
-
-	/* Detect D-cache size */
-	_EXT	t1, v0, MIPS_CONF1_DS_SHF, MIPS_CONF1_DS_SZ
-	xori	t2, t1, 0x7
-	beqz	t2, 1f
-	 li	t3, 32
-	addiu	t1, t1, 1
-	sllv	t1, t3, t1
-1:	/* At this point t1 == D-cache sets per way */
-	_EXT	t2, v0, MIPS_CONF1_DA_SHF, MIPS_CONF1_DA_SZ
-	addiu	t2, t2, 1
-	mul	t1, t1, t0
-	mul	t1, t1, t2
+	/* Initialize the L1 caches */
+	jal	mips_cps_cache_init
+	 nop
 
-	li	a0, CKSEG0
-	PTR_ADDU a1, a0, t1
-	PTR_SUBU a1, a1, t0
-1:	cache	Index_Store_Tag_D, 0(a0)
-	bne	a0, a1, 1b
-	 PTR_ADD a0, a0, t0
-dcache_done:
+	/* Enter the coherent domain */
+	li	t0, 0xff
+	sw	t0, GCR_CL_COHERENCE_OFS(v1)
+	ehb
 
 	/* Set Kseg0 CCA to that in s0 */
-	mfc0	t0, CP0_CONFIG
+1:	mfc0	t0, CP0_CONFIG
 	ori	t0, 0x7
 	xori	t0, 0x7
 	or	t0, t0, s0
 	mtc0	t0, CP0_CONFIG
 	ehb
 
-	/* Calculate an uncached address for the CM GCRs */
-	MFC0	v1, CP0_CMGCRBASE
-	PTR_SLL	v1, v1, 4
-	PTR_LI	t0, UNCAC_BASE
-	PTR_ADDU v1, v1, t0
-
-	/* Enter the coherent domain */
-	li	t0, 0xff
-	sw	t0, GCR_CL_COHERENCE_OFS(v1)
-	ehb
-
 	/* Jump to kseg0 */
 	PTR_LA	t0, 1f
 	jr	t0
 	 nop
 
 	/*
-	 * We're up, cached & coherent. Perform any further required core-level
-	 * initialisation.
+	 * We're up, cached & coherent. Perform any EVA initialization necessary
+	 * before we access memory.
 	 */
-1:	jal	mips_cps_core_init
+1:	eva_init
+
+	/* Retrieve boot configuration pointers */
+	jal	mips_cps_get_bootcfg
 	 nop
 
-	/* Do any EVA initialization if necessary */
-	eva_init
+	/* Skip core-level init if we started up coherent */
+	bnez	s7, 1f
+	 nop
+
+	/* Perform any further required core-level initialisation */
+	jal	mips_cps_core_init
+	 nop
 
 	/*
 	 * Boot any other VPEs within this core that should be online, and
 	 * deactivate this VPE if it should be offline.
 	 */
+	move	a1, t9
 	jal	mips_cps_boot_vpes
-	 nop
+	 move	a0, v0
 
 	/* Off we go! */
-	PTR_L	t1, VPEBOOTCFG_PC(v0)
-	PTR_L	gp, VPEBOOTCFG_GP(v0)
-	PTR_L	sp, VPEBOOTCFG_SP(v0)
+1:	PTR_L	t1, VPEBOOTCFG_PC(v1)
+	PTR_L	gp, VPEBOOTCFG_GP(v1)
+	PTR_L	sp, VPEBOOTCFG_SP(v1)
 	jr	t1
 	 nop
 	END(mips_cps_core_entry)
@@ -245,7 +223,6 @@ LEAF(excep_intex)
 
 .org 0x480
 LEAF(excep_ejtag)
-	DUMP_EXCEP("EJTAG")
 	PTR_LA	k0, ejtag_debug_handler
 	jr	k0
 	 nop
@@ -323,22 +300,35 @@ LEAF(mips_cps_core_init)
 	 nop
 	END(mips_cps_core_init)
 
-LEAF(mips_cps_boot_vpes)
-	/* Retrieve CM base address */
-	PTR_LA	t0, mips_cm_base
-	PTR_L	t0, 0(t0)
-
+/**
+ * mips_cps_get_bootcfg() - retrieve boot configuration pointers
+ *
+ * Returns: pointer to struct core_boot_config in v0, pointer to
+ *          struct vpe_boot_config in v1, VPE ID in t9
+ */
+LEAF(mips_cps_get_bootcfg)
 	/* Calculate a pointer to this cores struct core_boot_config */
+	cmgcrb	t0
 	lw	t0, GCR_CL_ID_OFS(t0)
 	li	t1, COREBOOTCFG_SIZE
 	mul	t0, t0, t1
 	PTR_LA	t1, mips_cps_core_bootcfg
 	PTR_L	t1, 0(t1)
-	PTR_ADDU t0, t0, t1
+	PTR_ADDU v0, t0, t1
 
 	/* Calculate this VPEs ID. If the core doesn't support MT use 0 */
 	li	t9, 0
-#ifdef CONFIG_MIPS_MT_SMP
+#if defined(CONFIG_CPU_MIPSR6)
+	has_vp	ta2, 1f
+
+	/*
+	 * Assume non-contiguous numbering. Perhaps some day we'll need
+	 * to handle contiguous VP numbering, but no such systems yet
+	 * exist.
+	 */
+	mfc0	t9, $3, 1
+	andi	t9, t9, 0xff
+#elif defined(CONFIG_MIPS_MT_SMP)
 	has_mt	ta2, 1f
 
 	/* Find the number of VPEs present in the core */
@@ -362,22 +352,43 @@ LEAF(mips_cps_boot_vpes)
 
 1:	/* Calculate a pointer to this VPEs struct vpe_boot_config */
 	li	t1, VPEBOOTCFG_SIZE
-	mul	v0, t9, t1
-	PTR_L	ta3, COREBOOTCFG_VPECONFIG(t0)
-	PTR_ADDU v0, v0, ta3
-
-#ifdef CONFIG_MIPS_MT_SMP
+	mul	v1, t9, t1
+	PTR_L	ta3, COREBOOTCFG_VPECONFIG(v0)
+	PTR_ADDU v1, v1, ta3
 
-	/* If the core doesn't support MT then return */
-	bnez	ta2, 1f
-	 nop
 	jr	ra
 	 nop
+	END(mips_cps_get_bootcfg)
+
+LEAF(mips_cps_boot_vpes)
+	PTR_L	ta2, COREBOOTCFG_VPEMASK(a0)
+	PTR_L	ta3, COREBOOTCFG_VPECONFIG(a0)
+
+#if defined(CONFIG_CPU_MIPSR6)
+
+	has_vp	t0, 5f
+
+	/* Find base address of CPC */
+	cmgcrb	t3
+	PTR_L	t1, GCR_CPC_BASE_OFS(t3)
+	PTR_LI	t2, ~0x7fff
+	and	t1, t1, t2
+	PTR_LI	t2, UNCAC_BASE
+	PTR_ADD	t1, t1, t2
+
+	/* Set VC_RUN to the VPE mask */
+	PTR_S	ta2, CPC_CL_VC_RUN_OFS(t1)
+	ehb
+
+#elif defined(CONFIG_MIPS_MT)
 
 	.set	push
 	.set	mt
 
-1:	/* Enter VPE configuration state */
+	/* If the core doesn't support MT then return */
+	has_mt	t0, 5f
+
+	/* Enter VPE configuration state */
 	dvpe
 	PTR_LA	t1, 1f
 	jr.hb	t1
@@ -388,7 +399,6 @@ LEAF(mips_cps_boot_vpes)
 	ehb
 
 	/* Loop through each VPE */
-	PTR_L	ta2, COREBOOTCFG_VPEMASK(t0)
 	move	t8, ta2
 	li	ta1, 0
 
@@ -431,6 +441,21 @@ LEAF(mips_cps_boot_vpes)
 	mfc0	t0, CP0_CONFIG
 	mttc0	t0, CP0_CONFIG
 
+	/*
+	 * Copy the EVA config from this VPE if the CPU supports it.
+	 * CONFIG3 must exist to be running MT startup - just read it.
+	 */
+	mfc0	t0, CP0_CONFIG, 3
+	and	t0, t0, MIPS_CONF3_SC
+	beqz	t0, 3f
+	 nop
+	mfc0    t0, CP0_SEGCTL0
+	mttc0	t0, CP0_SEGCTL0
+	mfc0    t0, CP0_SEGCTL1
+	mttc0	t0, CP0_SEGCTL1
+	mfc0    t0, CP0_SEGCTL2
+	mttc0	t0, CP0_SEGCTL2
+3:
 	/* Ensure no software interrupts are pending */
 	mttc0	zero, CP0_CAUSE
 	mttc0	zero, CP0_STATUS
@@ -465,7 +490,7 @@ LEAF(mips_cps_boot_vpes)
 
 	/* Check whether this VPE is meant to be running */
 	li	t0, 1
-	sll	t0, t0, t9
+	sll	t0, t0, a1
 	and	t0, t0, t8
 	bnez	t0, 2f
 	 nop
@@ -482,10 +507,84 @@ LEAF(mips_cps_boot_vpes)
 #endif /* CONFIG_MIPS_MT_SMP */
 
 	/* Return */
-	jr	ra
+5:	jr	ra
 	 nop
 	END(mips_cps_boot_vpes)
 
+LEAF(mips_cps_cache_init)
+	/*
+	 * Clear the bits used to index the caches. Note that the architecture
+	 * dictates that writing to any of TagLo or TagHi selects 0 or 2 should
+	 * be valid for all MIPS32 CPUs, even those for which said writes are
+	 * unnecessary.
+	 */
+	mtc0	zero, CP0_TAGLO, 0
+	mtc0	zero, CP0_TAGHI, 0
+	mtc0	zero, CP0_TAGLO, 2
+	mtc0	zero, CP0_TAGHI, 2
+	ehb
+
+	/* Primary cache configuration is indicated by Config1 */
+	mfc0	v0, CP0_CONFIG, 1
+
+	/* Detect I-cache line size */
+	_EXT	t0, v0, MIPS_CONF1_IL_SHF, MIPS_CONF1_IL_SZ
+	beqz	t0, icache_done
+	 li	t1, 2
+	sllv	t0, t1, t0
+
+	/* Detect I-cache size */
+	_EXT	t1, v0, MIPS_CONF1_IS_SHF, MIPS_CONF1_IS_SZ
+	xori	t2, t1, 0x7
+	beqz	t2, 1f
+	 li	t3, 32
+	addiu	t1, t1, 1
+	sllv	t1, t3, t1
+1:	/* At this point t1 == I-cache sets per way */
+	_EXT	t2, v0, MIPS_CONF1_IA_SHF, MIPS_CONF1_IA_SZ
+	addiu	t2, t2, 1
+	mul	t1, t1, t0
+	mul	t1, t1, t2
+
+	li	a0, CKSEG0
+	PTR_ADD	a1, a0, t1
+1:	cache	Index_Store_Tag_I, 0(a0)
+	PTR_ADD	a0, a0, t0
+	bne	a0, a1, 1b
+	 nop
+icache_done:
+
+	/* Detect D-cache line size */
+	_EXT	t0, v0, MIPS_CONF1_DL_SHF, MIPS_CONF1_DL_SZ
+	beqz	t0, dcache_done
+	 li	t1, 2
+	sllv	t0, t1, t0
+
+	/* Detect D-cache size */
+	_EXT	t1, v0, MIPS_CONF1_DS_SHF, MIPS_CONF1_DS_SZ
+	xori	t2, t1, 0x7
+	beqz	t2, 1f
+	 li	t3, 32
+	addiu	t1, t1, 1
+	sllv	t1, t3, t1
+1:	/* At this point t1 == D-cache sets per way */
+	_EXT	t2, v0, MIPS_CONF1_DA_SHF, MIPS_CONF1_DA_SZ
+	addiu	t2, t2, 1
+	mul	t1, t1, t0
+	mul	t1, t1, t2
+
+	li	a0, CKSEG0
+	PTR_ADDU a1, a0, t1
+	PTR_SUBU a1, a1, t0
+1:	cache	Index_Store_Tag_D, 0(a0)
+	bne	a0, a1, 1b
+	 PTR_ADD a0, a0, t0
+dcache_done:
+
+	jr	ra
+	 nop
+	END(mips_cps_cache_init)
+
 #if defined(CONFIG_MIPS_CPS_PM) && defined(CONFIG_CPU_PM)
 
 	/* Calculate a pointer to this CPUs struct mips_static_suspend_state */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/cpu-probe.c linux-libre-4.7-gnu/arch/mips/kernel/cpu-probe.c
--- linux-libre-4.6-gnu/arch/mips/kernel/cpu-probe.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/cpu-probe.c	2016-07-24 15:23:50.000000000 -0400
@@ -539,6 +539,7 @@ static int set_ftlb_enable(struct cpuinf
 	switch (c->cputype) {
 	case CPU_PROAPTIV:
 	case CPU_P5600:
+	case CPU_P6600:
 		/* proAptiv & related cores use Config6 to enable the FTLB */
 		config = read_c0_config6();
 		/* Clear the old probability value */
@@ -561,6 +562,19 @@ static int set_ftlb_enable(struct cpuinf
 		write_c0_config7(config | (calculate_ftlb_probability(c)
 					   << MIPS_CONF7_FTLBP_SHIFT));
 		break;
+	case CPU_LOONGSON3:
+		/* Flush ITLB, DTLB, VTLB and FTLB */
+		write_c0_diag(LOONGSON_DIAG_ITLB | LOONGSON_DIAG_DTLB |
+			      LOONGSON_DIAG_VTLB | LOONGSON_DIAG_FTLB);
+		/* Loongson-3 cores use Config6 to enable the FTLB */
+		config = read_c0_config6();
+		if (enable)
+			/* Enable FTLB */
+			write_c0_config6(config & ~MIPS_CONF6_FTLBDIS);
+		else
+			/* Disable FTLB */
+			write_c0_config6(config | MIPS_CONF6_FTLBDIS);
+		break;
 	default:
 		return 1;
 	}
@@ -634,6 +648,8 @@ static inline unsigned int decode_config
 
 	if (config1 & MIPS_CONF1_MD)
 		c->ases |= MIPS_ASE_MDMX;
+	if (config1 & MIPS_CONF1_PC)
+		c->options |= MIPS_CPU_PERF;
 	if (config1 & MIPS_CONF1_WR)
 		c->options |= MIPS_CPU_WATCH;
 	if (config1 & MIPS_CONF1_CA)
@@ -673,18 +689,25 @@ static inline unsigned int decode_config
 
 	if (config3 & MIPS_CONF3_SM) {
 		c->ases |= MIPS_ASE_SMARTMIPS;
-		c->options |= MIPS_CPU_RIXI;
+		c->options |= MIPS_CPU_RIXI | MIPS_CPU_CTXTC;
 	}
 	if (config3 & MIPS_CONF3_RXI)
 		c->options |= MIPS_CPU_RIXI;
+	if (config3 & MIPS_CONF3_CTXTC)
+		c->options |= MIPS_CPU_CTXTC;
 	if (config3 & MIPS_CONF3_DSP)
 		c->ases |= MIPS_ASE_DSP;
-	if (config3 & MIPS_CONF3_DSP2P)
+	if (config3 & MIPS_CONF3_DSP2P) {
 		c->ases |= MIPS_ASE_DSP2P;
+		if (cpu_has_mips_r6)
+			c->ases |= MIPS_ASE_DSP3;
+	}
 	if (config3 & MIPS_CONF3_VINT)
 		c->options |= MIPS_CPU_VINT;
 	if (config3 & MIPS_CONF3_VEIC)
 		c->options |= MIPS_CPU_VEIC;
+	if (config3 & MIPS_CONF3_LPA)
+		c->options |= MIPS_CPU_LPA;
 	if (config3 & MIPS_CONF3_MT)
 		c->ases |= MIPS_ASE_MIPSMT;
 	if (config3 & MIPS_CONF3_ULRI)
@@ -695,6 +718,10 @@ static inline unsigned int decode_config
 		c->ases |= MIPS_ASE_VZ;
 	if (config3 & MIPS_CONF3_SC)
 		c->options |= MIPS_CPU_SEGMENTS;
+	if (config3 & MIPS_CONF3_BI)
+		c->options |= MIPS_CPU_BADINSTR;
+	if (config3 & MIPS_CONF3_BP)
+		c->options |= MIPS_CPU_BADINSTRP;
 	if (config3 & MIPS_CONF3_MSA)
 		c->ases |= MIPS_ASE_MSA;
 	if (config3 & MIPS_CONF3_PW) {
@@ -715,6 +742,7 @@ static inline unsigned int decode_config
 	unsigned int newcf4;
 	unsigned int mmuextdef;
 	unsigned int ftlb_page = MIPS_CONF4_FTLBPAGESIZE;
+	unsigned long asid_mask;
 
 	config4 = read_c0_config4();
 
@@ -773,7 +801,20 @@ static inline unsigned int decode_config
 		}
 	}
 
-	c->kscratch_mask = (config4 >> 16) & 0xff;
+	c->kscratch_mask = (config4 & MIPS_CONF4_KSCREXIST)
+				>> MIPS_CONF4_KSCREXIST_SHIFT;
+
+	asid_mask = MIPS_ENTRYHI_ASID;
+	if (config4 & MIPS_CONF4_AE)
+		asid_mask |= MIPS_ENTRYHI_ASIDX;
+	set_cpu_asid_mask(c, asid_mask);
+
+	/*
+	 * Warn if the computed ASID mask doesn't match the mask the kernel
+	 * is built for. This may indicate either a serious problem or an
+	 * easy optimisation opportunity, but either way should be addressed.
+	 */
+	WARN_ON(asid_mask != cpu_asid_mask(c));
 
 	return config4 & MIPS_CONF_M;
 }
@@ -792,10 +833,10 @@ static inline unsigned int decode_config
 		c->options |= MIPS_CPU_MAAR;
 	if (config5 & MIPS_CONF5_LLB)
 		c->options |= MIPS_CPU_RW_LLB;
-#ifdef CONFIG_XPA
 	if (config5 & MIPS_CONF5_MVH)
-		c->options |= MIPS_CPU_XPA;
-#endif
+		c->options |= MIPS_CPU_MVH;
+	if (cpu_has_mips_r6 && (config5 & MIPS_CONF5_VP))
+		c->options |= MIPS_CPU_VP;
 
 	return config5 & MIPS_CONF_M;
 }
@@ -826,17 +867,43 @@ static void decode_configs(struct cpuinf
 	if (ok)
 		ok = decode_config5(c);
 
-	mips_probe_watch_registers(c);
+	/* Probe the EBase.WG bit */
+	if (cpu_has_mips_r2_r6) {
+		u64 ebase;
+		unsigned int status;
 
-	if (cpu_has_rixi) {
-		/* Enable the RIXI exceptions */
-		set_c0_pagegrain(PG_IEC);
-		back_to_back_c0_hazard();
-		/* Verify the IEC bit is set */
-		if (read_c0_pagegrain() & PG_IEC)
-			c->options |= MIPS_CPU_RIXIEX;
+		/* {read,write}_c0_ebase_64() may be UNDEFINED prior to r6 */
+		ebase = cpu_has_mips64r6 ? read_c0_ebase_64()
+					 : (s32)read_c0_ebase();
+		if (ebase & MIPS_EBASE_WG) {
+			/* WG bit already set, we can avoid the clumsy probe */
+			c->options |= MIPS_CPU_EBASE_WG;
+		} else {
+			/* Its UNDEFINED to change EBase while BEV=0 */
+			status = read_c0_status();
+			write_c0_status(status | ST0_BEV);
+			irq_enable_hazard();
+			/*
+			 * On pre-r6 cores, this may well clobber the upper bits
+			 * of EBase. This is hard to avoid without potentially
+			 * hitting UNDEFINED dm*c0 behaviour if EBase is 32-bit.
+			 */
+			if (cpu_has_mips64r6)
+				write_c0_ebase_64(ebase | MIPS_EBASE_WG);
+			else
+				write_c0_ebase(ebase | MIPS_EBASE_WG);
+			back_to_back_c0_hazard();
+			/* Restore BEV */
+			write_c0_status(status);
+			if (read_c0_ebase() & MIPS_EBASE_WG) {
+				c->options |= MIPS_CPU_EBASE_WG;
+				write_c0_ebase(ebase);
+			}
+		}
 	}
 
+	mips_probe_watch_registers(c);
+
 #ifndef CONFIG_MIPS_CPS
 	if (cpu_has_mips_r2_r6) {
 		c->core = get_ebase_cpunum();
@@ -846,6 +913,235 @@ static void decode_configs(struct cpuinf
 #endif
 }
 
+/*
+ * Probe for certain guest capabilities by writing config bits and reading back.
+ * Finally write back the original value.
+ */
+#define probe_gc0_config(name, maxconf, bits)				\
+do {									\
+	unsigned int tmp;						\
+	tmp = read_gc0_##name();					\
+	write_gc0_##name(tmp | (bits));					\
+	back_to_back_c0_hazard();					\
+	maxconf = read_gc0_##name();					\
+	write_gc0_##name(tmp);						\
+} while (0)
+
+/*
+ * Probe for dynamic guest capabilities by changing certain config bits and
+ * reading back to see if they change. Finally write back the original value.
+ */
+#define probe_gc0_config_dyn(name, maxconf, dynconf, bits)		\
+do {									\
+	maxconf = read_gc0_##name();					\
+	write_gc0_##name(maxconf ^ (bits));				\
+	back_to_back_c0_hazard();					\
+	dynconf = maxconf ^ read_gc0_##name();				\
+	write_gc0_##name(maxconf);					\
+	maxconf |= dynconf;						\
+} while (0)
+
+static inline unsigned int decode_guest_config0(struct cpuinfo_mips *c)
+{
+	unsigned int config0;
+
+	probe_gc0_config(config, config0, MIPS_CONF_M);
+
+	if (config0 & MIPS_CONF_M)
+		c->guest.conf |= BIT(1);
+	return config0 & MIPS_CONF_M;
+}
+
+static inline unsigned int decode_guest_config1(struct cpuinfo_mips *c)
+{
+	unsigned int config1, config1_dyn;
+
+	probe_gc0_config_dyn(config1, config1, config1_dyn,
+			     MIPS_CONF_M | MIPS_CONF1_PC | MIPS_CONF1_WR |
+			     MIPS_CONF1_FP);
+
+	if (config1 & MIPS_CONF1_FP)
+		c->guest.options |= MIPS_CPU_FPU;
+	if (config1_dyn & MIPS_CONF1_FP)
+		c->guest.options_dyn |= MIPS_CPU_FPU;
+
+	if (config1 & MIPS_CONF1_WR)
+		c->guest.options |= MIPS_CPU_WATCH;
+	if (config1_dyn & MIPS_CONF1_WR)
+		c->guest.options_dyn |= MIPS_CPU_WATCH;
+
+	if (config1 & MIPS_CONF1_PC)
+		c->guest.options |= MIPS_CPU_PERF;
+	if (config1_dyn & MIPS_CONF1_PC)
+		c->guest.options_dyn |= MIPS_CPU_PERF;
+
+	if (config1 & MIPS_CONF_M)
+		c->guest.conf |= BIT(2);
+	return config1 & MIPS_CONF_M;
+}
+
+static inline unsigned int decode_guest_config2(struct cpuinfo_mips *c)
+{
+	unsigned int config2;
+
+	probe_gc0_config(config2, config2, MIPS_CONF_M);
+
+	if (config2 & MIPS_CONF_M)
+		c->guest.conf |= BIT(3);
+	return config2 & MIPS_CONF_M;
+}
+
+static inline unsigned int decode_guest_config3(struct cpuinfo_mips *c)
+{
+	unsigned int config3, config3_dyn;
+
+	probe_gc0_config_dyn(config3, config3, config3_dyn,
+			     MIPS_CONF_M | MIPS_CONF3_MSA | MIPS_CONF3_CTXTC);
+
+	if (config3 & MIPS_CONF3_CTXTC)
+		c->guest.options |= MIPS_CPU_CTXTC;
+	if (config3_dyn & MIPS_CONF3_CTXTC)
+		c->guest.options_dyn |= MIPS_CPU_CTXTC;
+
+	if (config3 & MIPS_CONF3_PW)
+		c->guest.options |= MIPS_CPU_HTW;
+
+	if (config3 & MIPS_CONF3_SC)
+		c->guest.options |= MIPS_CPU_SEGMENTS;
+
+	if (config3 & MIPS_CONF3_BI)
+		c->guest.options |= MIPS_CPU_BADINSTR;
+	if (config3 & MIPS_CONF3_BP)
+		c->guest.options |= MIPS_CPU_BADINSTRP;
+
+	if (config3 & MIPS_CONF3_MSA)
+		c->guest.ases |= MIPS_ASE_MSA;
+	if (config3_dyn & MIPS_CONF3_MSA)
+		c->guest.ases_dyn |= MIPS_ASE_MSA;
+
+	if (config3 & MIPS_CONF_M)
+		c->guest.conf |= BIT(4);
+	return config3 & MIPS_CONF_M;
+}
+
+static inline unsigned int decode_guest_config4(struct cpuinfo_mips *c)
+{
+	unsigned int config4;
+
+	probe_gc0_config(config4, config4,
+			 MIPS_CONF_M | MIPS_CONF4_KSCREXIST);
+
+	c->guest.kscratch_mask = (config4 & MIPS_CONF4_KSCREXIST)
+				>> MIPS_CONF4_KSCREXIST_SHIFT;
+
+	if (config4 & MIPS_CONF_M)
+		c->guest.conf |= BIT(5);
+	return config4 & MIPS_CONF_M;
+}
+
+static inline unsigned int decode_guest_config5(struct cpuinfo_mips *c)
+{
+	unsigned int config5, config5_dyn;
+
+	probe_gc0_config_dyn(config5, config5, config5_dyn,
+			 MIPS_CONF_M | MIPS_CONF5_MRP);
+
+	if (config5 & MIPS_CONF5_MRP)
+		c->guest.options |= MIPS_CPU_MAAR;
+	if (config5_dyn & MIPS_CONF5_MRP)
+		c->guest.options_dyn |= MIPS_CPU_MAAR;
+
+	if (config5 & MIPS_CONF5_LLB)
+		c->guest.options |= MIPS_CPU_RW_LLB;
+
+	if (config5 & MIPS_CONF_M)
+		c->guest.conf |= BIT(6);
+	return config5 & MIPS_CONF_M;
+}
+
+static inline void decode_guest_configs(struct cpuinfo_mips *c)
+{
+	unsigned int ok;
+
+	ok = decode_guest_config0(c);
+	if (ok)
+		ok = decode_guest_config1(c);
+	if (ok)
+		ok = decode_guest_config2(c);
+	if (ok)
+		ok = decode_guest_config3(c);
+	if (ok)
+		ok = decode_guest_config4(c);
+	if (ok)
+		decode_guest_config5(c);
+}
+
+static inline void cpu_probe_guestctl0(struct cpuinfo_mips *c)
+{
+	unsigned int guestctl0, temp;
+
+	guestctl0 = read_c0_guestctl0();
+
+	if (guestctl0 & MIPS_GCTL0_G0E)
+		c->options |= MIPS_CPU_GUESTCTL0EXT;
+	if (guestctl0 & MIPS_GCTL0_G1)
+		c->options |= MIPS_CPU_GUESTCTL1;
+	if (guestctl0 & MIPS_GCTL0_G2)
+		c->options |= MIPS_CPU_GUESTCTL2;
+	if (!(guestctl0 & MIPS_GCTL0_RAD)) {
+		c->options |= MIPS_CPU_GUESTID;
+
+		/*
+		 * Probe for Direct Root to Guest (DRG). Set GuestCtl1.RID = 0
+		 * first, otherwise all data accesses will be fully virtualised
+		 * as if they were performed by guest mode.
+		 */
+		write_c0_guestctl1(0);
+		tlbw_use_hazard();
+
+		write_c0_guestctl0(guestctl0 | MIPS_GCTL0_DRG);
+		back_to_back_c0_hazard();
+		temp = read_c0_guestctl0();
+
+		if (temp & MIPS_GCTL0_DRG) {
+			write_c0_guestctl0(guestctl0);
+			c->options |= MIPS_CPU_DRG;
+		}
+	}
+}
+
+static inline void cpu_probe_guestctl1(struct cpuinfo_mips *c)
+{
+	if (cpu_has_guestid) {
+		/* determine the number of bits of GuestID available */
+		write_c0_guestctl1(MIPS_GCTL1_ID);
+		back_to_back_c0_hazard();
+		c->guestid_mask = (read_c0_guestctl1() & MIPS_GCTL1_ID)
+						>> MIPS_GCTL1_ID_SHIFT;
+		write_c0_guestctl1(0);
+	}
+}
+
+static inline void cpu_probe_gtoffset(struct cpuinfo_mips *c)
+{
+	/* determine the number of bits of GTOffset available */
+	write_c0_gtoffset(0xffffffff);
+	back_to_back_c0_hazard();
+	c->gtoffset_mask = read_c0_gtoffset();
+	write_c0_gtoffset(0);
+}
+
+static inline void cpu_probe_vz(struct cpuinfo_mips *c)
+{
+	cpu_probe_guestctl0(c);
+	if (cpu_has_guestctl1)
+		cpu_probe_guestctl1(c);
+
+	cpu_probe_gtoffset(c);
+
+	decode_guest_configs(c);
+}
+
 #define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE \
 		| MIPS_CPU_COUNTER)
 
@@ -1172,7 +1468,7 @@ static inline void cpu_probe_legacy(stru
 			set_isa(c, MIPS_CPU_ISA_III);
 			c->fpu_msk31 |= FPU_CSR_CONDX;
 			break;
-		case PRID_REV_LOONGSON3A:
+		case PRID_REV_LOONGSON3A_R1:
 			c->cputype = CPU_LOONGSON3;
 			__cpu_name[cpu] = "ICT Loongson-3";
 			set_elf_platform(cpu, "loongson3a");
@@ -1314,6 +1610,10 @@ static inline void cpu_probe_mips(struct
 		c->cputype = CPU_P5600;
 		__cpu_name[cpu] = "MIPS P5600";
 		break;
+	case PRID_IMP_P6600:
+		c->cputype = CPU_P6600;
+		__cpu_name[cpu] = "MIPS P6600";
+		break;
 	case PRID_IMP_I6400:
 		c->cputype = CPU_I6400;
 		__cpu_name[cpu] = "MIPS I6400";
@@ -1322,6 +1622,10 @@ static inline void cpu_probe_mips(struct
 		c->cputype = CPU_M5150;
 		__cpu_name[cpu] = "MIPS M5150";
 		break;
+	case PRID_IMP_M6250:
+		c->cputype = CPU_M6250;
+		__cpu_name[cpu] = "MIPS M6250";
+		break;
 	}
 
 	decode_configs(c);
@@ -1435,6 +1739,7 @@ static inline void cpu_probe_broadcom(st
 			c->cputype = CPU_BMIPS4380;
 			__cpu_name[cpu] = "Broadcom BMIPS4380";
 			set_elf_platform(cpu, "bmips4380");
+			c->options |= MIPS_CPU_RIXI;
 		} else {
 			c->cputype = CPU_BMIPS4350;
 			__cpu_name[cpu] = "Broadcom BMIPS4350";
@@ -1445,9 +1750,12 @@ static inline void cpu_probe_broadcom(st
 	case PRID_IMP_BMIPS5000:
 	case PRID_IMP_BMIPS5200:
 		c->cputype = CPU_BMIPS5000;
-		__cpu_name[cpu] = "Broadcom BMIPS5000";
+		if ((c->processor_id & PRID_IMP_MASK) == PRID_IMP_BMIPS5200)
+			__cpu_name[cpu] = "Broadcom BMIPS5200";
+		else
+			__cpu_name[cpu] = "Broadcom BMIPS5000";
 		set_elf_platform(cpu, "bmips5000");
-		c->options |= MIPS_CPU_ULRI;
+		c->options |= MIPS_CPU_ULRI | MIPS_CPU_RIXI;
 		break;
 	}
 }
@@ -1481,6 +1789,8 @@ platform:
 		set_elf_platform(cpu, "octeon2");
 		break;
 	case PRID_IMP_CAVIUM_CN70XX:
+	case PRID_IMP_CAVIUM_CN73XX:
+	case PRID_IMP_CAVIUM_CNF75XX:
 	case PRID_IMP_CAVIUM_CN78XX:
 		c->cputype = CPU_CAVIUM_OCTEON3;
 		__cpu_name[cpu] = "Cavium Octeon III";
@@ -1493,6 +1803,29 @@ platform:
 	}
 }
 
+static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)
+{
+	switch (c->processor_id & PRID_IMP_MASK) {
+	case PRID_IMP_LOONGSON_64:  /* Loongson-2/3 */
+		switch (c->processor_id & PRID_REV_MASK) {
+		case PRID_REV_LOONGSON3A_R2:
+			c->cputype = CPU_LOONGSON3;
+			__cpu_name[cpu] = "ICT Loongson-3";
+			set_elf_platform(cpu, "loongson3a");
+			set_isa(c, MIPS_CPU_ISA_M64R2);
+			break;
+		}
+
+		decode_configs(c);
+		c->options |= MIPS_CPU_TLBINV | MIPS_CPU_LDPTE;
+		c->writecombine = _CACHE_UNCACHED_ACCELERATED;
+		break;
+	default:
+		panic("Unknown Loongson Processor ID!");
+		break;
+	}
+}
+
 static inline void cpu_probe_ingenic(struct cpuinfo_mips *c, unsigned int cpu)
 {
 	decode_configs(c);
@@ -1640,6 +1973,9 @@ void cpu_probe(void)
 	case PRID_COMP_CAVIUM:
 		cpu_probe_cavium(c, cpu);
 		break;
+	case PRID_COMP_LOONGSON:
+		cpu_probe_loongson(c, cpu);
+		break;
 	case PRID_COMP_INGENIC_D0:
 	case PRID_COMP_INGENIC_D1:
 	case PRID_COMP_INGENIC_E1:
@@ -1660,6 +1996,15 @@ void cpu_probe(void)
 	 */
 	BUG_ON(current_cpu_type() != c->cputype);
 
+	if (cpu_has_rixi) {
+		/* Enable the RIXI exceptions */
+		set_c0_pagegrain(PG_IEC);
+		back_to_back_c0_hazard();
+		/* Verify the IEC bit is set */
+		if (read_c0_pagegrain() & PG_IEC)
+			c->options |= MIPS_CPU_RIXIEX;
+	}
+
 	if (mips_fpu_disabled)
 		c->options &= ~MIPS_CPU_FPU;
 
@@ -1699,6 +2044,9 @@ void cpu_probe(void)
 		elf_hwcap |= HWCAP_MIPS_MSA;
 	}
 
+	if (cpu_has_vz)
+		cpu_probe_vz(c);
+
 	cpu_probe_vmbits(c);
 
 #ifdef CONFIG_64BIT
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/crash.c linux-libre-4.7-gnu/arch/mips/kernel/crash.c
--- linux-libre-4.6-gnu/arch/mips/kernel/crash.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/crash.c	2016-07-24 15:23:50.000000000 -0400
@@ -14,12 +14,22 @@ static int crashing_cpu = -1;
 static cpumask_t cpus_in_crash = CPU_MASK_NONE;
 
 #ifdef CONFIG_SMP
-static void crash_shutdown_secondary(void *ignore)
+static void crash_shutdown_secondary(void *passed_regs)
 {
-	struct pt_regs *regs;
+	struct pt_regs *regs = passed_regs;
 	int cpu = smp_processor_id();
 
-	regs = task_pt_regs(current);
+	/*
+	 * If we are passed registers, use those.  Otherwise get the
+	 * regs from the last interrupt, which should be correct, as
+	 * we are in an interrupt.  But if the regs are not there,
+	 * pull them from the top of the stack.  They are probably
+	 * wrong, but we need something to keep from crashing again.
+	 */
+	if (!regs)
+		regs = get_irq_regs();
+	if (!regs)
+		regs = task_pt_regs(current);
 
 	if (!cpu_online(cpu))
 		return;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/elf.c linux-libre-4.7-gnu/arch/mips/kernel/elf.c
--- linux-libre-4.6-gnu/arch/mips/kernel/elf.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/elf.c	2016-07-24 15:23:50.000000000 -0400
@@ -88,7 +88,7 @@ int arch_elf_pt_proc(void *_ehdr, void *
 	elf32 = ehdr->e32.e_ident[EI_CLASS] == ELFCLASS32;
 	flags = elf32 ? ehdr->e32.e_flags : ehdr->e64.e_flags;
 
-	/* Lets see if this is an O32 ELF */
+	/* Let's see if this is an O32 ELF */
 	if (elf32) {
 		if (flags & EF_MIPS_FP64) {
 			/*
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/genex.S linux-libre-4.7-gnu/arch/mips/kernel/genex.S
--- linux-libre-4.6-gnu/arch/mips/kernel/genex.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/genex.S	2016-07-24 15:23:50.000000000 -0400
@@ -130,7 +130,7 @@ LEAF(__r4k_wait)
 	/* end of rollback region (the region size must be power of two) */
 1:
 	jr	ra
-	nop
+	 nop
 	.set	pop
 	END(__r4k_wait)
 
@@ -172,7 +172,7 @@ NESTED(handle_int, PT_SIZE, sp)
 	mfc0	k0, CP0_EPC
 	.set	noreorder
 	j	k0
-	rfe
+	 rfe
 #else
 	and	k0, ST0_IE
 	bnez	k0, 1f
@@ -189,7 +189,7 @@ NESTED(handle_int, PT_SIZE, sp)
 	LONG_L	s0, TI_REGS($28)
 	LONG_S	sp, TI_REGS($28)
 	PTR_LA	ra, ret_from_irq
-	PTR_LA  v0, plat_irq_dispatch
+	PTR_LA	v0, plat_irq_dispatch
 	jr	v0
 #ifdef CONFIG_CPU_MICROMIPS
 	nop
@@ -292,7 +292,7 @@ ejtag_return:
 	MFC0	k0, CP0_DESAVE
 	.set	mips32
 	deret
-	.set pop
+	.set	pop
 	END(ejtag_debug_handler)
 
 /*
@@ -329,10 +329,10 @@ NESTED(nmi_handler, PT_SIZE, sp)
 	 * Clear BEV - required for page fault exception handler to work
 	 */
 	mfc0	k0, CP0_STATUS
-	ori     k0, k0, ST0_EXL
+	ori	k0, k0, ST0_EXL
 	li	k1, ~(ST0_BEV | ST0_ERL)
-	and     k0, k0, k1
-	mtc0    k0, CP0_STATUS
+	and	k0, k0, k1
+	mtc0	k0, CP0_STATUS
 	_ehb
 	SAVE_ALL
 	move	a0, sp
@@ -396,7 +396,7 @@ NESTED(nmi_handler, PT_SIZE, sp)
 
 	.macro	__BUILD_count exception
 	LONG_L	t0,exception_count_\exception
-	LONG_ADDIU t0, 1
+	LONG_ADDIU	t0, 1
 	LONG_S	t0,exception_count_\exception
 	.comm	exception_count\exception, 8, 8
 	.endm
@@ -455,10 +455,10 @@ NESTED(nmi_handler, PT_SIZE, sp)
 	.set	noreorder
 	/* check if TLB contains a entry for EPC */
 	MFC0	k1, CP0_ENTRYHI
-	andi	k1, 0xff	/* ASID_MASK */
+	andi	k1, MIPS_ENTRYHI_ASID | MIPS_ENTRYHI_ASIDX
 	MFC0	k0, CP0_EPC
-	PTR_SRL k0, _PAGE_SHIFT + 1
-	PTR_SLL k0, _PAGE_SHIFT + 1
+	PTR_SRL	k0, _PAGE_SHIFT + 1
+	PTR_SLL	k0, _PAGE_SHIFT + 1
 	or	k1, k0
 	MTC0	k1, CP0_ENTRYHI
 	mtc0_tlbw_hazard
@@ -478,27 +478,27 @@ NESTED(nmi_handler, PT_SIZE, sp)
 	/* microMIPS: 0x007d6b3c: rdhwr v1,$29 */
 	MFC0	k1, CP0_EPC
 #if defined(CONFIG_CPU_MICROMIPS) || defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_CPU_MIPS64_R2)
-	and     k0, k1, 1
-	beqz    k0, 1f
-	xor     k1, k0
-	lhu     k0, (k1)
-	lhu     k1, 2(k1)
-	ins     k1, k0, 16, 16
-	lui     k0, 0x007d
-	b       docheck
-	ori     k0, 0x6b3c
+	and	k0, k1, 1
+	beqz	k0, 1f
+	 xor	k1, k0
+	lhu	k0, (k1)
+	lhu	k1, 2(k1)
+	ins	k1, k0, 16, 16
+	lui	k0, 0x007d
+	b	docheck
+	 ori	k0, 0x6b3c
 1:
-	lui     k0, 0x7c03
-	lw      k1, (k1)
-	ori     k0, 0xe83b
+	lui	k0, 0x7c03
+	lw	k1, (k1)
+	ori	k0, 0xe83b
 #else
-	andi    k0, k1, 1
-	bnez    k0, handle_ri
-	lui     k0, 0x7c03
-	lw      k1, (k1)
-	ori     k0, 0xe83b
+	andi	k0, k1, 1
+	bnez	k0, handle_ri
+	 lui	k0, 0x7c03
+	lw	k1, (k1)
+	ori	k0, 0xe83b
 #endif
-	.set    reorder
+	.set	reorder
 docheck:
 	bne	k0, k1, handle_ri	/* if not ours */
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/head.S linux-libre-4.7-gnu/arch/mips/kernel/head.S
--- linux-libre-4.6-gnu/arch/mips/kernel/head.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/head.S	2016-07-24 15:23:50.000000000 -0400
@@ -21,7 +21,6 @@
 #include <asm/asmmacro.h>
 #include <asm/irqflags.h>
 #include <asm/regdef.h>
-#include <asm/pgtable-bits.h>
 #include <asm/mipsregs.h>
 #include <asm/stackframe.h>
 
@@ -132,7 +131,27 @@ not_found:
 	set_saved_sp	sp, t0, t1
 	PTR_SUBU	sp, 4 * SZREG		# init stack pointer
 
+#ifdef CONFIG_RELOCATABLE
+	/* Copy kernel and apply the relocations */
+	jal		relocate_kernel
+
+	/* Repoint the sp into the new kernel image */
+	PTR_LI		sp, _THREAD_SIZE - 32 - PT_SIZE
+	PTR_ADDU	sp, $28
+	set_saved_sp	sp, t0, t1
+	PTR_SUBU	sp, 4 * SZREG		# init stack pointer
+
+	/*
+	 * relocate_kernel returns the entry point either
+	 * in the relocated kernel or the original if for
+	 * some reason relocation failed - jump there now
+	 * with instruction hazard barrier because of the
+	 * newly sync'd icache.
+	 */
+	jr.hb		v0
+#else
 	j		start_kernel
+#endif
 	END(kernel_entry)
 
 #ifdef CONFIG_SMP
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/idle.c linux-libre-4.7-gnu/arch/mips/kernel/idle.c
--- linux-libre-4.6-gnu/arch/mips/kernel/idle.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/idle.c	2016-07-24 15:23:50.000000000 -0400
@@ -181,6 +181,11 @@ void __init check_wait(void)
 	case CPU_XLP:
 		cpu_wait = r4k_wait;
 		break;
+	case CPU_LOONGSON3:
+		if ((c->processor_id & PRID_REV_MASK) >= PRID_REV_LOONGSON3A_R2)
+			cpu_wait = r4k_wait;
+		break;
+
 	case CPU_BMIPS5000:
 		cpu_wait = r4k_wait_irqoff;
 		break;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/irq.c linux-libre-4.7-gnu/arch/mips/kernel/irq.c
--- linux-libre-4.6-gnu/arch/mips/kernel/irq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/irq.c	2016-07-24 15:23:50.000000000 -0400
@@ -54,6 +54,9 @@ void __init init_IRQ(void)
 	for (i = 0; i < NR_IRQS; i++)
 		irq_set_noprobe(i);
 
+	if (cpu_has_veic)
+		clear_c0_status(ST0_IM);
+
 	arch_init_irq();
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/Makefile linux-libre-4.7-gnu/arch/mips/kernel/Makefile
--- linux-libre-4.6-gnu/arch/mips/kernel/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -44,7 +44,7 @@ obj-$(CONFIG_CPU_CAVIUM_OCTEON)	+= r4k_f
 
 obj-$(CONFIG_SMP)		+= smp.o
 obj-$(CONFIG_SMP_UP)		+= smp-up.o
-obj-$(CONFIG_CPU_BMIPS)		+= smp-bmips.o bmips_vec.o
+obj-$(CONFIG_CPU_BMIPS)		+= smp-bmips.o bmips_vec.o bmips_5xxx_init.o
 
 obj-$(CONFIG_MIPS_MT)		+= mips-mt.o
 obj-$(CONFIG_MIPS_MT_FPAFF)	+= mips-mt-fpaff.o
@@ -83,6 +83,8 @@ obj-$(CONFIG_I8253)		+= i8253.o
 
 obj-$(CONFIG_GPIO_TXX9)		+= gpio_txx9.o
 
+obj-$(CONFIG_RELOCATABLE)	+= relocate.o
+
 obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o crash.o
 obj-$(CONFIG_CRASH_DUMP)	+= crash_dump.o
 obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/mips-r2-to-r6-emul.c linux-libre-4.7-gnu/arch/mips/kernel/mips-r2-to-r6-emul.c
--- linux-libre-4.6-gnu/arch/mips/kernel/mips-r2-to-r6-emul.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/mips-r2-to-r6-emul.c	2016-07-24 15:23:50.000000000 -0400
@@ -28,6 +28,7 @@
 #include <asm/inst.h>
 #include <asm/mips-r2-to-r6-emul.h>
 #include <asm/local.h>
+#include <asm/mipsregs.h>
 #include <asm/ptrace.h>
 #include <asm/uaccess.h>
 
@@ -1251,10 +1252,10 @@ fpu_emul:
 			"	j	10b\n"
 			"	.previous\n"
 			"	.section	__ex_table,\"a\"\n"
-			"	.word	1b,8b\n"
-			"	.word	2b,8b\n"
-			"	.word	3b,8b\n"
-			"	.word	4b,8b\n"
+			STR(PTR) " 1b,8b\n"
+			STR(PTR) " 2b,8b\n"
+			STR(PTR) " 3b,8b\n"
+			STR(PTR) " 4b,8b\n"
 			"	.previous\n"
 			"	.set	pop\n"
 			: "+&r"(rt), "=&r"(rs),
@@ -1326,10 +1327,10 @@ fpu_emul:
 			"	j	10b\n"
 			"       .previous\n"
 			"	.section	__ex_table,\"a\"\n"
-			"	.word	1b,8b\n"
-			"	.word	2b,8b\n"
-			"	.word	3b,8b\n"
-			"	.word	4b,8b\n"
+			STR(PTR) " 1b,8b\n"
+			STR(PTR) " 2b,8b\n"
+			STR(PTR) " 3b,8b\n"
+			STR(PTR) " 4b,8b\n"
 			"	.previous\n"
 			"	.set	pop\n"
 			: "+&r"(rt), "=&r"(rs),
@@ -1397,10 +1398,10 @@ fpu_emul:
 			"	j	9b\n"
 			"	.previous\n"
 			"	.section        __ex_table,\"a\"\n"
-			"	.word	1b,8b\n"
-			"	.word	2b,8b\n"
-			"	.word	3b,8b\n"
-			"	.word	4b,8b\n"
+			STR(PTR) " 1b,8b\n"
+			STR(PTR) " 2b,8b\n"
+			STR(PTR) " 3b,8b\n"
+			STR(PTR) " 4b,8b\n"
 			"	.previous\n"
 			"	.set	pop\n"
 			: "+&r"(rt), "=&r"(rs),
@@ -1467,10 +1468,10 @@ fpu_emul:
 			"	j	9b\n"
 			"	.previous\n"
 			"	.section        __ex_table,\"a\"\n"
-			"	.word	1b,8b\n"
-			"	.word	2b,8b\n"
-			"	.word	3b,8b\n"
-			"	.word	4b,8b\n"
+			STR(PTR) " 1b,8b\n"
+			STR(PTR) " 2b,8b\n"
+			STR(PTR) " 3b,8b\n"
+			STR(PTR) " 4b,8b\n"
 			"	.previous\n"
 			"	.set	pop\n"
 			: "+&r"(rt), "=&r"(rs),
@@ -1582,14 +1583,14 @@ fpu_emul:
 			"	j	9b\n"
 			"	.previous\n"
 			"	.section        __ex_table,\"a\"\n"
-			"	.word	1b,8b\n"
-			"	.word	2b,8b\n"
-			"	.word	3b,8b\n"
-			"	.word	4b,8b\n"
-			"	.word	5b,8b\n"
-			"	.word	6b,8b\n"
-			"	.word	7b,8b\n"
-			"	.word	0b,8b\n"
+			STR(PTR) " 1b,8b\n"
+			STR(PTR) " 2b,8b\n"
+			STR(PTR) " 3b,8b\n"
+			STR(PTR) " 4b,8b\n"
+			STR(PTR) " 5b,8b\n"
+			STR(PTR) " 6b,8b\n"
+			STR(PTR) " 7b,8b\n"
+			STR(PTR) " 0b,8b\n"
 			"	.previous\n"
 			"	.set	pop\n"
 			: "+&r"(rt), "=&r"(rs),
@@ -1701,14 +1702,14 @@ fpu_emul:
 			"	j      9b\n"
 			"	.previous\n"
 			"	.section        __ex_table,\"a\"\n"
-			"	.word  1b,8b\n"
-			"	.word  2b,8b\n"
-			"	.word  3b,8b\n"
-			"	.word  4b,8b\n"
-			"	.word  5b,8b\n"
-			"	.word  6b,8b\n"
-			"	.word  7b,8b\n"
-			"	.word  0b,8b\n"
+			STR(PTR) " 1b,8b\n"
+			STR(PTR) " 2b,8b\n"
+			STR(PTR) " 3b,8b\n"
+			STR(PTR) " 4b,8b\n"
+			STR(PTR) " 5b,8b\n"
+			STR(PTR) " 6b,8b\n"
+			STR(PTR) " 7b,8b\n"
+			STR(PTR) " 0b,8b\n"
 			"	.previous\n"
 			"	.set    pop\n"
 			: "+&r"(rt), "=&r"(rs),
@@ -1820,14 +1821,14 @@ fpu_emul:
 			"	j	9b\n"
 			"	.previous\n"
 			"	.section        __ex_table,\"a\"\n"
-			"	.word	1b,8b\n"
-			"	.word	2b,8b\n"
-			"	.word	3b,8b\n"
-			"	.word	4b,8b\n"
-			"	.word	5b,8b\n"
-			"	.word	6b,8b\n"
-			"	.word	7b,8b\n"
-			"	.word	0b,8b\n"
+			STR(PTR) " 1b,8b\n"
+			STR(PTR) " 2b,8b\n"
+			STR(PTR) " 3b,8b\n"
+			STR(PTR) " 4b,8b\n"
+			STR(PTR) " 5b,8b\n"
+			STR(PTR) " 6b,8b\n"
+			STR(PTR) " 7b,8b\n"
+			STR(PTR) " 0b,8b\n"
 			"	.previous\n"
 			"	.set	pop\n"
 			: "+&r"(rt), "=&r"(rs),
@@ -1938,14 +1939,14 @@ fpu_emul:
 			"       j	9b\n"
 			"       .previous\n"
 			"       .section        __ex_table,\"a\"\n"
-			"       .word	1b,8b\n"
-			"       .word	2b,8b\n"
-			"       .word	3b,8b\n"
-			"       .word	4b,8b\n"
-			"       .word	5b,8b\n"
-			"       .word	6b,8b\n"
-			"       .word	7b,8b\n"
-			"       .word	0b,8b\n"
+			STR(PTR) " 1b,8b\n"
+			STR(PTR) " 2b,8b\n"
+			STR(PTR) " 3b,8b\n"
+			STR(PTR) " 4b,8b\n"
+			STR(PTR) " 5b,8b\n"
+			STR(PTR) " 6b,8b\n"
+			STR(PTR) " 7b,8b\n"
+			STR(PTR) " 0b,8b\n"
 			"       .previous\n"
 			"       .set	pop\n"
 			: "+&r"(rt), "=&r"(rs),
@@ -2000,7 +2001,7 @@ fpu_emul:
 			"j	2b\n"
 			".previous\n"
 			".section        __ex_table,\"a\"\n"
-			".word  1b, 3b\n"
+			STR(PTR) " 1b,3b\n"
 			".previous\n"
 			: "=&r"(res), "+&r"(err)
 			: "r"(vaddr), "i"(SIGSEGV)
@@ -2058,7 +2059,7 @@ fpu_emul:
 			"j	2b\n"
 			".previous\n"
 			".section        __ex_table,\"a\"\n"
-			".word	1b, 3b\n"
+			STR(PTR) " 1b,3b\n"
 			".previous\n"
 			: "+&r"(res), "+&r"(err)
 			: "r"(vaddr), "i"(SIGSEGV));
@@ -2119,7 +2120,7 @@ fpu_emul:
 			"j	2b\n"
 			".previous\n"
 			".section        __ex_table,\"a\"\n"
-			".word  1b, 3b\n"
+			STR(PTR) " 1b,3b\n"
 			".previous\n"
 			: "=&r"(res), "+&r"(err)
 			: "r"(vaddr), "i"(SIGSEGV)
@@ -2182,7 +2183,7 @@ fpu_emul:
 			"j	2b\n"
 			".previous\n"
 			".section        __ex_table,\"a\"\n"
-			".word	1b, 3b\n"
+			STR(PTR) " 1b,3b\n"
 			".previous\n"
 			: "+&r"(res), "+&r"(err)
 			: "r"(vaddr), "i"(SIGSEGV));
@@ -2201,7 +2202,7 @@ fpu_emul:
 	}
 
 	/*
-	 * Lets not return to userland just yet. It's constly and
+	 * Let's not return to userland just yet. It's costly and
 	 * it's likely we have more R2 instructions to emulate
 	 */
 	if (!err && (pass++ < MIPS_R2_EMUL_TOTAL_PASS)) {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/module.c linux-libre-4.7-gnu/arch/mips/kernel/module.c
--- linux-libre-4.6-gnu/arch/mips/kernel/module.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/module.c	2016-07-24 15:23:50.000000000 -0400
@@ -73,8 +73,7 @@ static int apply_r_mips_26_rel(struct mo
 	}
 
 	if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
-		printk(KERN_ERR
-		       "module %s: relocation overflow\n",
+		pr_err("module %s: relocation overflow\n",
 		       me->name);
 		return -ENOEXEC;
 	}
@@ -183,13 +182,62 @@ out_danger:
 	return -ENOEXEC;
 }
 
+static int apply_r_mips_pc_rel(struct module *me, u32 *location, Elf_Addr v,
+			       unsigned bits)
+{
+	unsigned long mask = GENMASK(bits - 1, 0);
+	unsigned long se_bits;
+	long offset;
+
+	if (v % 4) {
+		pr_err("module %s: dangerous R_MIPS_PC%u REL relocation\n",
+		       me->name, bits);
+		return -ENOEXEC;
+	}
+
+	/* retrieve & sign extend implicit addend */
+	offset = *location & mask;
+	offset |= (offset & BIT(bits - 1)) ? ~mask : 0;
+
+	offset += ((long)v - (long)location) >> 2;
+
+	/* check the sign bit onwards are identical - ie. we didn't overflow */
+	se_bits = (offset & BIT(bits - 1)) ? ~0ul : 0;
+	if ((offset & ~mask) != (se_bits & ~mask)) {
+		pr_err("module %s: relocation overflow\n", me->name);
+		return -ENOEXEC;
+	}
+
+	*location = (*location & ~mask) | (offset & mask);
+
+	return 0;
+}
+
+static int apply_r_mips_pc16_rel(struct module *me, u32 *location, Elf_Addr v)
+{
+	return apply_r_mips_pc_rel(me, location, v, 16);
+}
+
+static int apply_r_mips_pc21_rel(struct module *me, u32 *location, Elf_Addr v)
+{
+	return apply_r_mips_pc_rel(me, location, v, 21);
+}
+
+static int apply_r_mips_pc26_rel(struct module *me, u32 *location, Elf_Addr v)
+{
+	return apply_r_mips_pc_rel(me, location, v, 26);
+}
+
 static int (*reloc_handlers_rel[]) (struct module *me, u32 *location,
 				Elf_Addr v) = {
 	[R_MIPS_NONE]		= apply_r_mips_none,
 	[R_MIPS_32]		= apply_r_mips_32_rel,
 	[R_MIPS_26]		= apply_r_mips_26_rel,
 	[R_MIPS_HI16]		= apply_r_mips_hi16_rel,
-	[R_MIPS_LO16]		= apply_r_mips_lo16_rel
+	[R_MIPS_LO16]		= apply_r_mips_lo16_rel,
+	[R_MIPS_PC16]		= apply_r_mips_pc16_rel,
+	[R_MIPS_PC21_S2]	= apply_r_mips_pc21_rel,
+	[R_MIPS_PC26_S2]	= apply_r_mips_pc26_rel,
 };
 
 int apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
@@ -215,12 +263,12 @@ int apply_relocate(Elf_Shdr *sechdrs, co
 		/* This is the symbol it is referring to */
 		sym = (Elf_Sym *)sechdrs[symindex].sh_addr
 			+ ELF_MIPS_R_SYM(rel[i]);
-		if (IS_ERR_VALUE(sym->st_value)) {
+		if (sym->st_value >= -MAX_ERRNO) {
 			/* Ignore unresolved weak symbol */
 			if (ELF_ST_BIND(sym->st_info) == STB_WEAK)
 				continue;
-			printk(KERN_WARNING "%s: Unknown symbol %s\n",
-			       me->name, strtab + sym->st_name);
+			pr_warn("%s: Unknown symbol %s\n",
+				me->name, strtab + sym->st_name);
 			return -ENOENT;
 		}
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/module-rela.c linux-libre-4.7-gnu/arch/mips/kernel/module-rela.c
--- linux-libre-4.6-gnu/arch/mips/kernel/module-rela.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/module-rela.c	2016-07-24 15:23:50.000000000 -0400
@@ -16,6 +16,7 @@
  *  Copyright (C) 2001 Rusty Russell.
  *  Copyright (C) 2003, 2004 Ralf Baechle (ralf@linux-mips.org)
  *  Copyright (C) 2005 Thiemo Seufer
+ *  Copyright (C) 2015 Imagination Technologies Ltd.
  */
 
 #include <linux/elf.h>
@@ -35,15 +36,13 @@ static int apply_r_mips_32_rela(struct m
 static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v)
 {
 	if (v % 4) {
-		pr_err("module %s: dangerous R_MIPS_26 RELArelocation\n",
+		pr_err("module %s: dangerous R_MIPS_26 RELA relocation\n",
 		       me->name);
 		return -ENOEXEC;
 	}
 
 	if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
-		printk(KERN_ERR
-		       "module %s: relocation overflow\n",
-		       me->name);
+		pr_err("module %s: relocation overflow\n", me->name);
 		return -ENOEXEC;
 	}
 
@@ -67,6 +66,48 @@ static int apply_r_mips_lo16_rela(struct
 	return 0;
 }
 
+static int apply_r_mips_pc_rela(struct module *me, u32 *location, Elf_Addr v,
+				unsigned bits)
+{
+	unsigned long mask = GENMASK(bits - 1, 0);
+	unsigned long se_bits;
+	long offset;
+
+	if (v % 4) {
+		pr_err("module %s: dangerous R_MIPS_PC%u RELA relocation\n",
+		       me->name, bits);
+		return -ENOEXEC;
+	}
+
+	offset = ((long)v - (long)location) >> 2;
+
+	/* check the sign bit onwards are identical - ie. we didn't overflow */
+	se_bits = (offset & BIT(bits - 1)) ? ~0ul : 0;
+	if ((offset & ~mask) != (se_bits & ~mask)) {
+		pr_err("module %s: relocation overflow\n", me->name);
+		return -ENOEXEC;
+	}
+
+	*location = (*location & ~mask) | (offset & mask);
+
+	return 0;
+}
+
+static int apply_r_mips_pc16_rela(struct module *me, u32 *location, Elf_Addr v)
+{
+	return apply_r_mips_pc_rela(me, location, v, 16);
+}
+
+static int apply_r_mips_pc21_rela(struct module *me, u32 *location, Elf_Addr v)
+{
+	return apply_r_mips_pc_rela(me, location, v, 21);
+}
+
+static int apply_r_mips_pc26_rela(struct module *me, u32 *location, Elf_Addr v)
+{
+	return apply_r_mips_pc_rela(me, location, v, 26);
+}
+
 static int apply_r_mips_64_rela(struct module *me, u32 *location, Elf_Addr v)
 {
 	*(Elf_Addr *)location = v;
@@ -99,9 +140,12 @@ static int (*reloc_handlers_rela[]) (str
 	[R_MIPS_26]		= apply_r_mips_26_rela,
 	[R_MIPS_HI16]		= apply_r_mips_hi16_rela,
 	[R_MIPS_LO16]		= apply_r_mips_lo16_rela,
+	[R_MIPS_PC16]		= apply_r_mips_pc16_rela,
 	[R_MIPS_64]		= apply_r_mips_64_rela,
 	[R_MIPS_HIGHER]		= apply_r_mips_higher_rela,
-	[R_MIPS_HIGHEST]	= apply_r_mips_highest_rela
+	[R_MIPS_HIGHEST]	= apply_r_mips_highest_rela,
+	[R_MIPS_PC21_S2]	= apply_r_mips_pc21_rela,
+	[R_MIPS_PC26_S2]	= apply_r_mips_pc26_rela,
 };
 
 int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
@@ -126,11 +170,11 @@ int apply_relocate_add(Elf_Shdr *sechdrs
 		/* This is the symbol it is referring to */
 		sym = (Elf_Sym *)sechdrs[symindex].sh_addr
 			+ ELF_MIPS_R_SYM(rel[i]);
-		if (IS_ERR_VALUE(sym->st_value)) {
+		if (sym->st_value >= -MAX_ERRNO) {
 			/* Ignore unresolved weak symbol */
 			if (ELF_ST_BIND(sym->st_info) == STB_WEAK)
 				continue;
-			printk(KERN_WARNING "%s: Unknown symbol %s\n",
+			pr_warn("%s: Unknown symbol %s\n",
 			       me->name, strtab + sym->st_name);
 			return -ENOENT;
 		}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/perf_event.c linux-libre-4.7-gnu/arch/mips/kernel/perf_event.c
--- linux-libre-4.6-gnu/arch/mips/kernel/perf_event.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/perf_event.c	2016-07-24 15:23:50.000000000 -0400
@@ -25,8 +25,8 @@
  * the user stack callchains, we will add it here.
  */
 
-static void save_raw_perf_callchain(struct perf_callchain_entry *entry,
-	unsigned long reg29)
+static void save_raw_perf_callchain(struct perf_callchain_entry_ctx *entry,
+				    unsigned long reg29)
 {
 	unsigned long *sp = (unsigned long *)reg29;
 	unsigned long addr;
@@ -35,14 +35,14 @@ static void save_raw_perf_callchain(stru
 		addr = *sp++;
 		if (__kernel_text_address(addr)) {
 			perf_callchain_store(entry, addr);
-			if (entry->nr >= PERF_MAX_STACK_DEPTH)
+			if (entry->nr >= entry->max_stack)
 				break;
 		}
 	}
 }
 
-void perf_callchain_kernel(struct perf_callchain_entry *entry,
-		      struct pt_regs *regs)
+void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
+			   struct pt_regs *regs)
 {
 	unsigned long sp = regs->regs[29];
 #ifdef CONFIG_KALLSYMS
@@ -59,7 +59,7 @@ void perf_callchain_kernel(struct perf_c
 	}
 	do {
 		perf_callchain_store(entry, pc);
-		if (entry->nr >= PERF_MAX_STACK_DEPTH)
+		if (entry->nr >= entry->max_stack)
 			break;
 		pc = unwind_stack(current, &sp, pc, &ra);
 	} while (pc);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/perf_event_mipsxx.c linux-libre-4.7-gnu/arch/mips/kernel/perf_event_mipsxx.c
--- linux-libre-4.6-gnu/arch/mips/kernel/perf_event_mipsxx.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/perf_event_mipsxx.c	2016-07-24 15:23:50.000000000 -0400
@@ -101,8 +101,6 @@ struct mips_pmu {
 
 static struct mips_pmu mipspmu;
 
-#define M_CONFIG1_PC	(1 << 4)
-
 #define M_PERFCTL_EXL			(1	<<  0)
 #define M_PERFCTL_KERNEL		(1	<<  1)
 #define M_PERFCTL_SUPERVISOR		(1	<<  2)
@@ -754,7 +752,7 @@ static void handle_associated_event(stru
 
 static int __n_counters(void)
 {
-	if (!(read_c0_config1() & M_CONFIG1_PC))
+	if (!cpu_has_perf)
 		return 0;
 	if (!(read_c0_perfctrl0() & M_PERFCTL_MORE))
 		return 1;
@@ -825,6 +823,16 @@ static const struct mips_perf_event mips
 	[PERF_COUNT_HW_BRANCH_MISSES] = { 0x27, CNTR_ODD, T },
 };
 
+static const struct mips_perf_event i6400_event_map[PERF_COUNT_HW_MAX] = {
+	[PERF_COUNT_HW_CPU_CYCLES]          = { 0x00, CNTR_EVEN | CNTR_ODD },
+	[PERF_COUNT_HW_INSTRUCTIONS]        = { 0x01, CNTR_EVEN | CNTR_ODD },
+	/* These only count dcache, not icache */
+	[PERF_COUNT_HW_CACHE_REFERENCES]    = { 0x45, CNTR_EVEN | CNTR_ODD },
+	[PERF_COUNT_HW_CACHE_MISSES]        = { 0x48, CNTR_EVEN | CNTR_ODD },
+	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = { 0x15, CNTR_EVEN | CNTR_ODD },
+	[PERF_COUNT_HW_BRANCH_MISSES]       = { 0x16, CNTR_EVEN | CNTR_ODD },
+};
+
 static const struct mips_perf_event loongson3_event_map[PERF_COUNT_HW_MAX] = {
 	[PERF_COUNT_HW_CPU_CYCLES] = { 0x00, CNTR_EVEN },
 	[PERF_COUNT_HW_INSTRUCTIONS] = { 0x00, CNTR_ODD },
@@ -1015,6 +1023,46 @@ static const struct mips_perf_event mips
 },
 };
 
+static const struct mips_perf_event i6400_cache_map
+				[PERF_COUNT_HW_CACHE_MAX]
+				[PERF_COUNT_HW_CACHE_OP_MAX]
+				[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+[C(L1D)] = {
+	[C(OP_READ)] = {
+		[C(RESULT_ACCESS)]	= { 0x46, CNTR_EVEN | CNTR_ODD },
+		[C(RESULT_MISS)]	= { 0x49, CNTR_EVEN | CNTR_ODD },
+	},
+	[C(OP_WRITE)] = {
+		[C(RESULT_ACCESS)]	= { 0x47, CNTR_EVEN | CNTR_ODD },
+		[C(RESULT_MISS)]	= { 0x4a, CNTR_EVEN | CNTR_ODD },
+	},
+},
+[C(L1I)] = {
+	[C(OP_READ)] = {
+		[C(RESULT_ACCESS)]	= { 0x84, CNTR_EVEN | CNTR_ODD },
+		[C(RESULT_MISS)]	= { 0x85, CNTR_EVEN | CNTR_ODD },
+	},
+},
+[C(DTLB)] = {
+	/* Can't distinguish read & write */
+	[C(OP_READ)] = {
+		[C(RESULT_ACCESS)]	= { 0x40, CNTR_EVEN | CNTR_ODD },
+		[C(RESULT_MISS)]	= { 0x41, CNTR_EVEN | CNTR_ODD },
+	},
+	[C(OP_WRITE)] = {
+		[C(RESULT_ACCESS)]	= { 0x40, CNTR_EVEN | CNTR_ODD },
+		[C(RESULT_MISS)]	= { 0x41, CNTR_EVEN | CNTR_ODD },
+	},
+},
+[C(BPU)] = {
+	/* Conditional branches / mispredicted */
+	[C(OP_READ)] = {
+		[C(RESULT_ACCESS)]	= { 0x15, CNTR_EVEN | CNTR_ODD },
+		[C(RESULT_MISS)]	= { 0x16, CNTR_EVEN | CNTR_ODD },
+	},
+},
+};
+
 static const struct mips_perf_event loongson3_cache_map
 				[PERF_COUNT_HW_CACHE_MAX]
 				[PERF_COUNT_HW_CACHE_OP_MAX]
@@ -1556,6 +1604,7 @@ static const struct mips_perf_event *mip
 #endif
 		break;
 	case CPU_P5600:
+	case CPU_P6600:
 	case CPU_I6400:
 		/* 8-bit event numbers */
 		raw_id = config & 0x1ff;
@@ -1718,11 +1767,16 @@ init_hw_perf_events(void)
 		mipspmu.general_event_map = &mipsxxcore_event_map2;
 		mipspmu.cache_event_map = &mipsxxcore_cache_map2;
 		break;
-	case CPU_I6400:
-		mipspmu.name = "mips/I6400";
+	case CPU_P6600:
+		mipspmu.name = "mips/P6600";
 		mipspmu.general_event_map = &mipsxxcore_event_map2;
 		mipspmu.cache_event_map = &mipsxxcore_cache_map2;
 		break;
+	case CPU_I6400:
+		mipspmu.name = "mips/I6400";
+		mipspmu.general_event_map = &i6400_event_map;
+		mipspmu.cache_event_map = &i6400_cache_map;
+		break;
 	case CPU_1004K:
 		mipspmu.name = "mips/1004K";
 		mipspmu.general_event_map = &mipsxxcore_event_map;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/pm.c linux-libre-4.7-gnu/arch/mips/kernel/pm.c
--- linux-libre-4.6-gnu/arch/mips/kernel/pm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/pm.c	2016-07-24 15:23:50.000000000 -0400
@@ -56,7 +56,7 @@ static void mips_cpu_restore(void)
 		write_c0_userlocal(current_thread_info()->tp_value);
 
 	/* Restore watch registers */
-	__restore_watch();
+	__restore_watch(current);
 }
 
 /**
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/pm-cps.c linux-libre-4.7-gnu/arch/mips/kernel/pm-cps.c
--- linux-libre-4.6-gnu/arch/mips/kernel/pm-cps.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/pm-cps.c	2016-07-24 15:23:50.000000000 -0400
@@ -224,11 +224,18 @@ static void __init cps_gen_cache_routine
 	uasm_build_label(pl, *pp, lbl);
 
 	/* Generate the cache ops */
-	for (i = 0; i < unroll_lines; i++)
-		uasm_i_cache(pp, op, i * cache->linesz, t0);
+	for (i = 0; i < unroll_lines; i++) {
+		if (cpu_has_mips_r6) {
+			uasm_i_cache(pp, op, 0, t0);
+			uasm_i_addiu(pp, t0, t0, cache->linesz);
+		} else {
+			uasm_i_cache(pp, op, i * cache->linesz, t0);
+		}
+	}
 
-	/* Update the base address */
-	uasm_i_addiu(pp, t0, t0, unroll_lines * cache->linesz);
+	if (!cpu_has_mips_r6)
+		/* Update the base address */
+		uasm_i_addiu(pp, t0, t0, unroll_lines * cache->linesz);
 
 	/* Loop if we haven't reached the end address yet */
 	uasm_il_bne(pp, pr, t0, t1, lbl);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/proc.c linux-libre-4.7-gnu/arch/mips/kernel/proc.c
--- linux-libre-4.6-gnu/arch/mips/kernel/proc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/proc.c	2016-07-24 15:23:50.000000000 -0400
@@ -114,6 +114,7 @@ static int show_cpuinfo(struct seq_file
 	if (cpu_has_smartmips)	seq_printf(m, "%s", " smartmips");
 	if (cpu_has_dsp)	seq_printf(m, "%s", " dsp");
 	if (cpu_has_dsp2)	seq_printf(m, "%s", " dsp2");
+	if (cpu_has_dsp3)	seq_printf(m, "%s", " dsp3");
 	if (cpu_has_mipsmt)	seq_printf(m, "%s", " mt");
 	if (cpu_has_mmips)	seq_printf(m, "%s", " micromips");
 	if (cpu_has_vz)		seq_printf(m, "%s", " vz");
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/process.c linux-libre-4.7-gnu/arch/mips/kernel/process.c
--- linux-libre-4.6-gnu/arch/mips/kernel/process.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/process.c	2016-07-24 15:23:50.000000000 -0400
@@ -73,14 +73,6 @@ void start_thread(struct pt_regs * regs,
 	regs->regs[29] = sp;
 }
 
-void exit_thread(void)
-{
-}
-
-void flush_thread(void)
-{
-}
-
 int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
 {
 	/*
@@ -353,7 +345,7 @@ static int get_frame_info(struct mips_fr
 		return 0;
 	if (info->pc_offset < 0) /* leaf */
 		return 1;
-	/* prologue seems boggus... */
+	/* prologue seems bogus... */
 err:
 	return -1;
 }
@@ -455,7 +447,7 @@ unsigned long notrace unwind_stack_by_ad
 		    *sp + sizeof(*regs) <= stack_page + THREAD_SIZE - 32) {
 			regs = (struct pt_regs *)*sp;
 			pc = regs->cp0_epc;
-			if (__kernel_text_address(pc)) {
+			if (!user_mode(regs) && __kernel_text_address(pc)) {
 				*sp = regs->regs[29];
 				*ra = regs->regs[31];
 				return pc;
@@ -580,11 +572,19 @@ int mips_get_process_fp_mode(struct task
 	return value;
 }
 
+static void prepare_for_fp_mode_switch(void *info)
+{
+	struct mm_struct *mm = info;
+
+	if (current->mm == mm)
+		lose_fpu(1);
+}
+
 int mips_set_process_fp_mode(struct task_struct *task, unsigned int value)
 {
 	const unsigned int known_bits = PR_FP_MODE_FR | PR_FP_MODE_FRE;
-	unsigned long switch_count;
 	struct task_struct *t;
+	int max_users;
 
 	/* Check the value is valid */
 	if (value & ~known_bits)
@@ -601,6 +601,9 @@ int mips_set_process_fp_mode(struct task
 	if (!(value & PR_FP_MODE_FR) && cpu_has_fpu && cpu_has_mips_r6)
 		return -EOPNOTSUPP;
 
+	/* Proceed with the mode switch */
+	preempt_disable();
+
 	/* Save FP & vector context, then disable FPU & MSA */
 	if (task->signal == current->signal)
 		lose_fpu(1);
@@ -610,31 +613,17 @@ int mips_set_process_fp_mode(struct task
 	smp_mb__after_atomic();
 
 	/*
-	 * If there are multiple online CPUs then wait until all threads whose
-	 * FP mode is about to change have been context switched. This approach
-	 * allows us to only worry about whether an FP mode switch is in
-	 * progress when FP is first used in a tasks time slice. Pretty much all
-	 * of the mode switch overhead can thus be confined to cases where mode
-	 * switches are actually occurring. That is, to here. However for the
-	 * thread performing the mode switch it may take a while...
+	 * If there are multiple online CPUs then force any which are running
+	 * threads in this process to lose their FPU context, which they can't
+	 * regain until fp_mode_switching is cleared later.
 	 */
 	if (num_online_cpus() > 1) {
-		spin_lock_irq(&task->sighand->siglock);
-
-		for_each_thread(task, t) {
-			if (t == current)
-				continue;
-
-			switch_count = t->nvcsw + t->nivcsw;
-
-			do {
-				spin_unlock_irq(&task->sighand->siglock);
-				cond_resched();
-				spin_lock_irq(&task->sighand->siglock);
-			} while ((t->nvcsw + t->nivcsw) == switch_count);
-		}
+		/* No need to send an IPI for the local CPU */
+		max_users = (task->mm == current->mm) ? 1 : 0;
 
-		spin_unlock_irq(&task->sighand->siglock);
+		if (atomic_read(&current->mm->mm_users) > max_users)
+			smp_call_function(prepare_for_fp_mode_switch,
+					  (void *)current->mm, 1);
 	}
 
 	/*
@@ -659,6 +648,7 @@ int mips_set_process_fp_mode(struct task
 
 	/* Allow threads to use FP again */
 	atomic_set(&task->mm->context.fp_mode_switching, 0);
+	preempt_enable();
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/ptrace.c linux-libre-4.7-gnu/arch/mips/kernel/ptrace.c
--- linux-libre-4.6-gnu/arch/mips/kernel/ptrace.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/ptrace.c	2016-07-24 15:23:50.000000000 -0400
@@ -57,8 +57,7 @@ static void init_fp_ctx(struct task_stru
 	/* Begin with data registers set to all 1s... */
 	memset(&target->thread.fpu.fpr, ~0, sizeof(target->thread.fpu.fpr));
 
-	/* ...and FCSR zeroed */
-	target->thread.fpu.fcr31 = 0;
+	/* FCSR has been preset by `mips_set_personality_nan'.  */
 
 	/*
 	 * Record that the target has "used" math, such that the context
@@ -80,6 +79,22 @@ void ptrace_disable(struct task_struct *
 }
 
 /*
+ * Poke at FCSR according to its mask.  Don't set the cause bits as
+ * this is currently not handled correctly in FP context restoration
+ * and will cause an oops if a corresponding enable bit is set.
+ */
+static void ptrace_setfcr31(struct task_struct *child, u32 value)
+{
+	u32 fcr31;
+	u32 mask;
+
+	value &= ~FPU_CSR_ALL_X;
+	fcr31 = child->thread.fpu.fcr31;
+	mask = boot_cpu_data.fpu_msk31;
+	child->thread.fpu.fcr31 = (value & ~mask) | (fcr31 & mask);
+}
+
+/*
  * Read a general register set.	 We always use the 64-bit format, even
  * for 32-bit kernels and for 32-bit processes on a 64-bit kernel.
  * Registers are sign extended to fill the available space.
@@ -159,9 +174,7 @@ int ptrace_setfpregs(struct task_struct
 {
 	union fpureg *fregs;
 	u64 fpr_val;
-	u32 fcr31;
 	u32 value;
-	u32 mask;
 	int i;
 
 	if (!access_ok(VERIFY_READ, data, 33 * 8))
@@ -176,9 +189,7 @@ int ptrace_setfpregs(struct task_struct
 	}
 
 	__get_user(value, data + 64);
-	fcr31 = child->thread.fpu.fcr31;
-	mask = boot_cpu_data.fpu_msk31;
-	child->thread.fpu.fcr31 = (value & ~mask) | (fcr31 & mask);
+	ptrace_setfcr31(child, value);
 
 	/* FIR may not be written.  */
 
@@ -210,7 +221,8 @@ int ptrace_get_watch_regs(struct task_st
 	for (i = 0; i < boot_cpu_data.watch_reg_use_cnt; i++) {
 		__put_user(child->thread.watch.mips3264.watchlo[i],
 			   &addr->WATCH_STYLE.watchlo[i]);
-		__put_user(child->thread.watch.mips3264.watchhi[i] & 0xfff,
+		__put_user(child->thread.watch.mips3264.watchhi[i] &
+				(MIPS_WATCHHI_MASK | MIPS_WATCHHI_IRW),
 			   &addr->WATCH_STYLE.watchhi[i]);
 		__put_user(boot_cpu_data.watch_reg_masks[i],
 			   &addr->WATCH_STYLE.watch_masks[i]);
@@ -252,12 +264,12 @@ int ptrace_set_watch_regs(struct task_st
 		}
 #endif
 		__get_user(ht[i], &addr->WATCH_STYLE.watchhi[i]);
-		if (ht[i] & ~0xff8)
+		if (ht[i] & ~MIPS_WATCHHI_MASK)
 			return -EINVAL;
 	}
 	/* Install them. */
 	for (i = 0; i < boot_cpu_data.watch_reg_use_cnt; i++) {
-		if (lt[i] & 7)
+		if (lt[i] & MIPS_WATCHLO_IRW)
 			watch_active = 1;
 		child->thread.watch.mips3264.watchlo[i] = lt[i];
 		/* Set the G bit. */
@@ -805,7 +817,7 @@ long arch_ptrace(struct task_struct *chi
 			break;
 #endif
 		case FPC_CSR:
-			child->thread.fpu.fcr31 = data & ~FPU_CSR_ALL_X;
+			ptrace_setfcr31(child, data);
 			break;
 		case DSP_BASE ... DSP_BASE + 5: {
 			dspreg_t *dregs;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/r4k_fpu.S linux-libre-4.7-gnu/arch/mips/kernel/r4k_fpu.S
--- linux-libre-4.6-gnu/arch/mips/kernel/r4k_fpu.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/r4k_fpu.S	2016-07-24 15:23:50.000000000 -0400
@@ -244,17 +244,17 @@ LEAF(\name)
 	.set	push
 	.set	noat
 #ifdef CONFIG_64BIT
-	copy_u_d \wr, 1
+	copy_s_d \wr, 1
 	EX sd	$1, \off(\base)
 #elif defined(CONFIG_CPU_LITTLE_ENDIAN)
-	copy_u_w \wr, 2
+	copy_s_w \wr, 2
 	EX sw	$1, \off(\base)
-	copy_u_w \wr, 3
+	copy_s_w \wr, 3
 	EX sw	$1, (\off+4)(\base)
 #else /* CONFIG_CPU_BIG_ENDIAN */
-	copy_u_w \wr, 2
+	copy_s_w \wr, 2
 	EX sw	$1, (\off+4)(\base)
-	copy_u_w \wr, 3
+	copy_s_w \wr, 3
 	EX sw	$1, \off(\base)
 #endif
 	.set	pop
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/r4k_switch.S linux-libre-4.7-gnu/arch/mips/kernel/r4k_switch.S
--- linux-libre-4.6-gnu/arch/mips/kernel/r4k_switch.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/r4k_switch.S	2016-07-24 15:23:50.000000000 -0400
@@ -15,7 +15,6 @@
 #include <asm/fpregdef.h>
 #include <asm/mipsregs.h>
 #include <asm/asm-offsets.h>
-#include <asm/pgtable-bits.h>
 #include <asm/regdef.h>
 #include <asm/stackframe.h>
 #include <asm/thread_info.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/relocate.c linux-libre-4.7-gnu/arch/mips/kernel/relocate.c
--- linux-libre-4.6-gnu/arch/mips/kernel/relocate.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/mips/kernel/relocate.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,386 @@
+/*
+ * 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.
+ *
+ * Support for Kernel relocation at boot time
+ *
+ * Copyright (C) 2015, Imagination Technologies Ltd.
+ * Authors: Matt Redfearn (matt.redfearn@imgtec.com)
+ */
+#include <asm/bootinfo.h>
+#include <asm/cacheflush.h>
+#include <asm/fw/fw.h>
+#include <asm/sections.h>
+#include <asm/setup.h>
+#include <asm/timex.h>
+#include <linux/elf.h>
+#include <linux/kernel.h>
+#include <linux/libfdt.h>
+#include <linux/of_fdt.h>
+#include <linux/sched.h>
+#include <linux/start_kernel.h>
+#include <linux/string.h>
+#include <linux/printk.h>
+
+#define RELOCATED(x) ((void *)((long)x + offset))
+
+extern u32 _relocation_start[];	/* End kernel image / start relocation table */
+extern u32 _relocation_end[];	/* End relocation table */
+
+extern long __start___ex_table;	/* Start exception table */
+extern long __stop___ex_table;	/* End exception table */
+
+static inline u32 __init get_synci_step(void)
+{
+	u32 res;
+
+	__asm__("rdhwr  %0, $1" : "=r" (res));
+
+	return res;
+}
+
+static void __init sync_icache(void *kbase, unsigned long kernel_length)
+{
+	void *kend = kbase + kernel_length;
+	u32 step = get_synci_step();
+
+	do {
+		__asm__ __volatile__(
+			"synci  0(%0)"
+			: /* no output */
+			: "r" (kbase));
+
+		kbase += step;
+	} while (kbase < kend);
+
+	/* Completion barrier */
+	__sync();
+}
+
+static int __init apply_r_mips_64_rel(u32 *loc_orig, u32 *loc_new, long offset)
+{
+	*(u64 *)loc_new += offset;
+
+	return 0;
+}
+
+static int __init apply_r_mips_32_rel(u32 *loc_orig, u32 *loc_new, long offset)
+{
+	*loc_new += offset;
+
+	return 0;
+}
+
+static int __init apply_r_mips_26_rel(u32 *loc_orig, u32 *loc_new, long offset)
+{
+	unsigned long target_addr = (*loc_orig) & 0x03ffffff;
+
+	if (offset % 4) {
+		pr_err("Dangerous R_MIPS_26 REL relocation\n");
+		return -ENOEXEC;
+	}
+
+	/* Original target address */
+	target_addr <<= 2;
+	target_addr += (unsigned long)loc_orig & ~0x03ffffff;
+
+	/* Get the new target address */
+	target_addr += offset;
+
+	if ((target_addr & 0xf0000000) != ((unsigned long)loc_new & 0xf0000000)) {
+		pr_err("R_MIPS_26 REL relocation overflow\n");
+		return -ENOEXEC;
+	}
+
+	target_addr -= (unsigned long)loc_new & ~0x03ffffff;
+	target_addr >>= 2;
+
+	*loc_new = (*loc_new & ~0x03ffffff) | (target_addr & 0x03ffffff);
+
+	return 0;
+}
+
+
+static int __init apply_r_mips_hi16_rel(u32 *loc_orig, u32 *loc_new, long offset)
+{
+	unsigned long insn = *loc_orig;
+	unsigned long target = (insn & 0xffff) << 16; /* high 16bits of target */
+
+	target += offset;
+
+	*loc_new = (insn & ~0xffff) | ((target >> 16) & 0xffff);
+	return 0;
+}
+
+static int (*reloc_handlers_rel[]) (u32 *, u32 *, long) __initdata = {
+	[R_MIPS_64]		= apply_r_mips_64_rel,
+	[R_MIPS_32]		= apply_r_mips_32_rel,
+	[R_MIPS_26]		= apply_r_mips_26_rel,
+	[R_MIPS_HI16]		= apply_r_mips_hi16_rel,
+};
+
+int __init do_relocations(void *kbase_old, void *kbase_new, long offset)
+{
+	u32 *r;
+	u32 *loc_orig;
+	u32 *loc_new;
+	int type;
+	int res;
+
+	for (r = _relocation_start; r < _relocation_end; r++) {
+		/* Sentinel for last relocation */
+		if (*r == 0)
+			break;
+
+		type = (*r >> 24) & 0xff;
+		loc_orig = (void *)(kbase_old + ((*r & 0x00ffffff) << 2));
+		loc_new = RELOCATED(loc_orig);
+
+		if (reloc_handlers_rel[type] == NULL) {
+			/* Unsupported relocation */
+			pr_err("Unhandled relocation type %d at 0x%pK\n",
+			       type, loc_orig);
+			return -ENOEXEC;
+		}
+
+		res = reloc_handlers_rel[type](loc_orig, loc_new, offset);
+		if (res)
+			return res;
+	}
+
+	return 0;
+}
+
+/*
+ * The exception table is filled in by the relocs tool after vmlinux is linked.
+ * It must be relocated separately since there will not be any relocation
+ * information for it filled in by the linker.
+ */
+static int __init relocate_exception_table(long offset)
+{
+	unsigned long *etable_start, *etable_end, *e;
+
+	etable_start = RELOCATED(&__start___ex_table);
+	etable_end = RELOCATED(&__stop___ex_table);
+
+	for (e = etable_start; e < etable_end; e++)
+		*e += offset;
+
+	return 0;
+}
+
+#ifdef CONFIG_RANDOMIZE_BASE
+
+static inline __init unsigned long rotate_xor(unsigned long hash,
+					      const void *area, size_t size)
+{
+	size_t i;
+	unsigned long *ptr = (unsigned long *)area;
+
+	for (i = 0; i < size / sizeof(hash); i++) {
+		/* Rotate by odd number of bits and XOR. */
+		hash = (hash << ((sizeof(hash) * 8) - 7)) | (hash >> 7);
+		hash ^= ptr[i];
+	}
+
+	return hash;
+}
+
+static inline __init unsigned long get_random_boot(void)
+{
+	unsigned long entropy = random_get_entropy();
+	unsigned long hash = 0;
+
+	/* Attempt to create a simple but unpredictable starting entropy. */
+	hash = rotate_xor(hash, linux_banner, strlen(linux_banner));
+
+	/* Add in any runtime entropy we can get */
+	hash = rotate_xor(hash, &entropy, sizeof(entropy));
+
+#if defined(CONFIG_USE_OF)
+	/* Get any additional entropy passed in device tree */
+	{
+		int node, len;
+		u64 *prop;
+
+		node = fdt_path_offset(initial_boot_params, "/chosen");
+		if (node >= 0) {
+			prop = fdt_getprop_w(initial_boot_params, node,
+					     "kaslr-seed", &len);
+			if (prop && (len == sizeof(u64)))
+				hash = rotate_xor(hash, prop, sizeof(*prop));
+		}
+	}
+#endif /* CONFIG_USE_OF */
+
+	return hash;
+}
+
+static inline __init bool kaslr_disabled(void)
+{
+	char *str;
+
+#if defined(CONFIG_CMDLINE_BOOL)
+	const char *builtin_cmdline = CONFIG_CMDLINE;
+
+	str = strstr(builtin_cmdline, "nokaslr");
+	if (str == builtin_cmdline ||
+	    (str > builtin_cmdline && *(str - 1) == ' '))
+		return true;
+#endif
+	str = strstr(arcs_cmdline, "nokaslr");
+	if (str == arcs_cmdline || (str > arcs_cmdline && *(str - 1) == ' '))
+		return true;
+
+	return false;
+}
+
+static inline void __init *determine_relocation_address(void)
+{
+	/* Choose a new address for the kernel */
+	unsigned long kernel_length;
+	void *dest = &_text;
+	unsigned long offset;
+
+	if (kaslr_disabled())
+		return dest;
+
+	kernel_length = (long)_end - (long)(&_text);
+
+	offset = get_random_boot() << 16;
+	offset &= (CONFIG_RANDOMIZE_BASE_MAX_OFFSET - 1);
+	if (offset < kernel_length)
+		offset += ALIGN(kernel_length, 0xffff);
+
+	return RELOCATED(dest);
+}
+
+#else
+
+static inline void __init *determine_relocation_address(void)
+{
+	/*
+	 * Choose a new address for the kernel
+	 * For now we'll hard code the destination
+	 */
+	return (void *)0xffffffff81000000;
+}
+
+#endif
+
+static inline int __init relocation_addr_valid(void *loc_new)
+{
+	if ((unsigned long)loc_new & 0x0000ffff) {
+		/* Inappropriately aligned new location */
+		return 0;
+	}
+	if ((unsigned long)loc_new < (unsigned long)&_end) {
+		/* New location overlaps original kernel */
+		return 0;
+	}
+	return 1;
+}
+
+void *__init relocate_kernel(void)
+{
+	void *loc_new;
+	unsigned long kernel_length;
+	unsigned long bss_length;
+	long offset = 0;
+	int res = 1;
+	/* Default to original kernel entry point */
+	void *kernel_entry = start_kernel;
+
+	/* Get the command line */
+	fw_init_cmdline();
+#if defined(CONFIG_USE_OF)
+	/* Deal with the device tree */
+	early_init_dt_scan(plat_get_fdt());
+	if (boot_command_line[0]) {
+		/* Boot command line was passed in device tree */
+		strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
+	}
+#endif /* CONFIG_USE_OF */
+
+	kernel_length = (long)(&_relocation_start) - (long)(&_text);
+	bss_length = (long)&__bss_stop - (long)&__bss_start;
+
+	loc_new = determine_relocation_address();
+
+	/* Sanity check relocation address */
+	if (relocation_addr_valid(loc_new))
+		offset = (unsigned long)loc_new - (unsigned long)(&_text);
+
+	/* Reset the command line now so we don't end up with a duplicate */
+	arcs_cmdline[0] = '\0';
+
+	if (offset) {
+		/* Copy the kernel to it's new location */
+		memcpy(loc_new, &_text, kernel_length);
+
+		/* Perform relocations on the new kernel */
+		res = do_relocations(&_text, loc_new, offset);
+		if (res < 0)
+			goto out;
+
+		/* Sync the caches ready for execution of new kernel */
+		sync_icache(loc_new, kernel_length);
+
+		res = relocate_exception_table(offset);
+		if (res < 0)
+			goto out;
+
+		/*
+		 * The original .bss has already been cleared, and
+		 * some variables such as command line parameters
+		 * stored to it so make a copy in the new location.
+		 */
+		memcpy(RELOCATED(&__bss_start), &__bss_start, bss_length);
+
+		/* The current thread is now within the relocated image */
+		__current_thread_info = RELOCATED(&init_thread_union);
+
+		/* Return the new kernel's entry point */
+		kernel_entry = RELOCATED(start_kernel);
+	}
+out:
+	return kernel_entry;
+}
+
+/*
+ * Show relocation information on panic.
+ */
+void show_kernel_relocation(const char *level)
+{
+	unsigned long offset;
+
+	offset = __pa_symbol(_text) - __pa_symbol(VMLINUX_LOAD_ADDRESS);
+
+	if (IS_ENABLED(CONFIG_RELOCATABLE) && offset > 0) {
+		printk(level);
+		pr_cont("Kernel relocated by 0x%pK\n", (void *)offset);
+		pr_cont(" .text @ 0x%pK\n", _text);
+		pr_cont(" .data @ 0x%pK\n", _sdata);
+		pr_cont(" .bss  @ 0x%pK\n", __bss_start);
+	}
+}
+
+static int kernel_location_notifier_fn(struct notifier_block *self,
+				       unsigned long v, void *p)
+{
+	show_kernel_relocation(KERN_EMERG);
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block kernel_location_notifier = {
+	.notifier_call = kernel_location_notifier_fn
+};
+
+static int __init register_kernel_offset_dumper(void)
+{
+	atomic_notifier_chain_register(&panic_notifier_list,
+				       &kernel_location_notifier);
+	return 0;
+}
+__initcall(register_kernel_offset_dumper);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/scall32-o32.S linux-libre-4.7-gnu/arch/mips/kernel/scall32-o32.S
--- linux-libre-4.6-gnu/arch/mips/kernel/scall32-o32.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/scall32-o32.S	2016-07-24 15:23:50.000000000 -0400
@@ -35,7 +35,6 @@ NESTED(handle_sys, PT_SIZE, sp)
 
 	lw	t1, PT_EPC(sp)		# skip syscall on return
 
-	subu	v0, v0, __NR_O32_Linux	# check syscall number
 	addiu	t1, 4			# skip to next instruction
 	sw	t1, PT_EPC(sp)
 
@@ -89,6 +88,7 @@ loads_done:
 	and	t0, t1
 	bnez	t0, syscall_trace_entry # -> yes
 syscall_common:
+	subu	v0, v0, __NR_O32_Linux	# check syscall number
 	sltiu	t0, v0, __NR_O32_Linux_syscalls + 1
 	beqz	t0, illegal_syscall
 
@@ -118,24 +118,23 @@ o32_syscall_exit:
 
 syscall_trace_entry:
 	SAVE_STATIC
-	move	s0, v0
 	move	a0, sp
 
 	/*
 	 * syscall number is in v0 unless we called syscall(__NR_###)
 	 * where the real syscall number is in a0
 	 */
-	addiu	a1, v0,  __NR_O32_Linux
-	bnez	v0, 1f /* __NR_syscall at offset 0 */
+	move	a1, v0
+	subu	t2, v0,  __NR_O32_Linux
+	bnez	t2, 1f /* __NR_syscall at offset 0 */
 	lw	a1, PT_R4(sp)
 
 1:	jal	syscall_trace_enter
 
 	bltz	v0, 1f			# seccomp failed? Skip syscall
 
-	move	v0, s0			# restore syscall
-
 	RESTORE_STATIC
+	lw	v0, PT_R2(sp)		# Restore syscall (maybe modified)
 	lw	a0, PT_R4(sp)		# Restore argument registers
 	lw	a1, PT_R5(sp)
 	lw	a2, PT_R6(sp)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/scall64-64.S linux-libre-4.7-gnu/arch/mips/kernel/scall64-64.S
--- linux-libre-4.6-gnu/arch/mips/kernel/scall64-64.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/scall64-64.S	2016-07-24 15:23:50.000000000 -0400
@@ -82,15 +82,14 @@ n64_syscall_exit:
 
 syscall_trace_entry:
 	SAVE_STATIC
-	move	s0, v0
 	move	a0, sp
 	move	a1, v0
 	jal	syscall_trace_enter
 
 	bltz	v0, 1f			# seccomp failed? Skip syscall
 
-	move	v0, s0
 	RESTORE_STATIC
+	ld	v0, PT_R2(sp)		# Restore syscall (maybe modified)
 	ld	a0, PT_R4(sp)		# Restore argument registers
 	ld	a1, PT_R5(sp)
 	ld	a2, PT_R6(sp)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/scall64-n32.S linux-libre-4.7-gnu/arch/mips/kernel/scall64-n32.S
--- linux-libre-4.6-gnu/arch/mips/kernel/scall64-n32.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/scall64-n32.S	2016-07-24 15:23:50.000000000 -0400
@@ -42,9 +42,6 @@ NESTED(handle_sysn32, PT_SIZE, sp)
 #endif
 	beqz	t0, not_n32_scall
 
-	dsll	t0, v0, 3		# offset into table
-	ld	t2, (sysn32_call_table - (__NR_N32_Linux * 8))(t0)
-
 	sd	a3, PT_R26(sp)		# save a3 for syscall restarting
 
 	li	t1, _TIF_WORK_SYSCALL_ENTRY
@@ -53,6 +50,9 @@ NESTED(handle_sysn32, PT_SIZE, sp)
 	bnez	t0, n32_syscall_trace_entry
 
 syscall_common:
+	dsll	t0, v0, 3		# offset into table
+	ld	t2, (sysn32_call_table - (__NR_N32_Linux * 8))(t0)
+
 	jalr	t2			# Do The Real Thing (TM)
 
 	li	t0, -EMAXERRNO - 1	# error?
@@ -71,21 +71,25 @@ syscall_common:
 
 n32_syscall_trace_entry:
 	SAVE_STATIC
-	move	s0, t2
 	move	a0, sp
 	move	a1, v0
 	jal	syscall_trace_enter
 
 	bltz	v0, 1f			# seccomp failed? Skip syscall
 
-	move	t2, s0
 	RESTORE_STATIC
+	ld	v0, PT_R2(sp)		# Restore syscall (maybe modified)
 	ld	a0, PT_R4(sp)		# Restore argument registers
 	ld	a1, PT_R5(sp)
 	ld	a2, PT_R6(sp)
 	ld	a3, PT_R7(sp)
 	ld	a4, PT_R8(sp)
 	ld	a5, PT_R9(sp)
+
+	dsubu	t2, v0, __NR_N32_Linux	# check (new) syscall number
+	sltiu   t0, t2, __NR_N32_Linux_syscalls + 1
+	beqz	t0, not_n32_scall
+
 	j	syscall_common
 
 1:	j	syscall_exit
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/scall64-o32.S linux-libre-4.7-gnu/arch/mips/kernel/scall64-o32.S
--- linux-libre-4.6-gnu/arch/mips/kernel/scall64-o32.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/scall64-o32.S	2016-07-24 15:23:50.000000000 -0400
@@ -52,9 +52,6 @@ NESTED(handle_sys, PT_SIZE, sp)
 	sll	a2, a2, 0
 	sll	a3, a3, 0
 
-	dsll	t0, v0, 3		# offset into table
-	ld	t2, (sys32_call_table - (__NR_O32_Linux * 8))(t0)
-
 	sd	a3, PT_R26(sp)		# save a3 for syscall restarting
 
 	/*
@@ -88,6 +85,9 @@ loads_done:
 	bnez	t0, trace_a_syscall
 
 syscall_common:
+	dsll	t0, v0, 3		# offset into table
+	ld	t2, (sys32_call_table - (__NR_O32_Linux * 8))(t0)
+
 	jalr	t2			# Do The Real Thing (TM)
 
 	li	t0, -EMAXERRNO - 1	# error?
@@ -112,7 +112,6 @@ trace_a_syscall:
 	sd	a6, PT_R10(sp)
 	sd	a7, PT_R11(sp)		# For indirect syscalls
 
-	move	s0, t2			# Save syscall pointer
 	move	a0, sp
 	/*
 	 * absolute syscall number is in v0 unless we called syscall(__NR_###)
@@ -133,8 +132,8 @@ trace_a_syscall:
 
 	bltz	v0, 1f			# seccomp failed? Skip syscall
 
-	move	t2, s0
 	RESTORE_STATIC
+	ld	v0, PT_R2(sp)		# Restore syscall (maybe modified)
 	ld	a0, PT_R4(sp)		# Restore argument registers
 	ld	a1, PT_R5(sp)
 	ld	a2, PT_R6(sp)
@@ -143,6 +142,11 @@ trace_a_syscall:
 	ld	a5, PT_R9(sp)
 	ld	a6, PT_R10(sp)
 	ld	a7, PT_R11(sp)		# For indirect syscalls
+
+	dsubu	t0, v0, __NR_O32_Linux	# check (new) syscall number
+	sltiu	t0, t0, __NR_O32_Linux_syscalls + 1
+	beqz	t0, not_o32_scall
+
 	j	syscall_common
 
 1:	j	syscall_exit
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/setup.c linux-libre-4.7-gnu/arch/mips/kernel/setup.c
--- linux-libre-4.6-gnu/arch/mips/kernel/setup.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/setup.c	2016-07-24 15:23:50.000000000 -0400
@@ -26,6 +26,7 @@
 #include <linux/sizes.h>
 #include <linux/device.h>
 #include <linux/dma-contiguous.h>
+#include <linux/decompress/generic.h>
 
 #include <asm/addrspace.h>
 #include <asm/bootinfo.h>
@@ -52,13 +53,6 @@ struct screen_info screen_info;
 #endif
 
 /*
- * Despite it's name this variable is even if we don't have PCI
- */
-unsigned int PCI_DMA_BUS_IS_PHYS;
-
-EXPORT_SYMBOL(PCI_DMA_BUS_IS_PHYS);
-
-/*
  * Setup information
  *
  * These are initialized so they are in the .data section
@@ -250,6 +244,35 @@ disable:
 	return 0;
 }
 
+/* In some conditions (e.g. big endian bootloader with a little endian
+   kernel), the initrd might appear byte swapped.  Try to detect this and
+   byte swap it if needed.  */
+static void __init maybe_bswap_initrd(void)
+{
+#if defined(CONFIG_CPU_CAVIUM_OCTEON)
+	u64 buf;
+
+	/* Check for CPIO signature */
+	if (!memcmp((void *)initrd_start, "070701", 6))
+		return;
+
+	/* Check for compressed initrd */
+	if (decompress_method((unsigned char *)initrd_start, 8, NULL))
+		return;
+
+	/* Try again with a byte swapped header */
+	buf = swab64p((u64 *)initrd_start);
+	if (!memcmp(&buf, "070701", 6) ||
+	    decompress_method((unsigned char *)(&buf), 8, NULL)) {
+		unsigned long i;
+
+		pr_info("Byteswapped initrd detected\n");
+		for (i = initrd_start; i < ALIGN(initrd_end, 8); i += 8)
+			swab64s((u64 *)i);
+	}
+#endif
+}
+
 static void __init finalize_initrd(void)
 {
 	unsigned long size = initrd_end - initrd_start;
@@ -263,6 +286,8 @@ static void __init finalize_initrd(void)
 		goto disable;
 	}
 
+	maybe_bswap_initrd();
+
 	reserve_bootmem(__pa(initrd_start), size, BOOTMEM_DEFAULT);
 	initrd_below_start_ok = 1;
 
@@ -469,6 +494,29 @@ static void __init bootmem_init(void)
 	 */
 	reserve_bootmem(PFN_PHYS(mapstart), bootmap_size, BOOTMEM_DEFAULT);
 
+#ifdef CONFIG_RELOCATABLE
+	/*
+	 * The kernel reserves all memory below its _end symbol as bootmem,
+	 * but the kernel may now be at a much higher address. The memory
+	 * between the original and new locations may be returned to the system.
+	 */
+	if (__pa_symbol(_text) > __pa_symbol(VMLINUX_LOAD_ADDRESS)) {
+		unsigned long offset;
+		extern void show_kernel_relocation(const char *level);
+
+		offset = __pa_symbol(_text) - __pa_symbol(VMLINUX_LOAD_ADDRESS);
+		free_bootmem(__pa_symbol(VMLINUX_LOAD_ADDRESS), offset);
+
+#if defined(CONFIG_DEBUG_KERNEL) && defined(CONFIG_DEBUG_INFO)
+		/*
+		 * This information is necessary when debugging the kernel
+		 * But is a security vulnerability otherwise!
+		 */
+		show_kernel_relocation(KERN_INFO);
+#endif
+	}
+#endif
+
 	/*
 	 * Reserve initrd memory if needed.
 	 */
@@ -624,6 +672,8 @@ static void __init request_crashkernel(s
 #define USE_PROM_CMDLINE	IS_ENABLED(CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER)
 #define USE_DTB_CMDLINE		IS_ENABLED(CONFIG_MIPS_CMDLINE_FROM_DTB)
 #define EXTEND_WITH_PROM	IS_ENABLED(CONFIG_MIPS_CMDLINE_DTB_EXTEND)
+#define BUILTIN_EXTEND_WITH_PROM	\
+	IS_ENABLED(CONFIG_MIPS_CMDLINE_BUILTIN_EXTEND)
 
 static void __init arch_mem_init(char **cmdline_p)
 {
@@ -657,15 +707,23 @@ static void __init arch_mem_init(char **
 		strlcpy(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE);
 
 	if (EXTEND_WITH_PROM && arcs_cmdline[0]) {
-		strlcat(boot_command_line, " ", COMMAND_LINE_SIZE);
+		if (boot_command_line[0])
+			strlcat(boot_command_line, " ", COMMAND_LINE_SIZE);
 		strlcat(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE);
 	}
 
 #if defined(CONFIG_CMDLINE_BOOL)
 	if (builtin_cmdline[0]) {
-		strlcat(boot_command_line, " ", COMMAND_LINE_SIZE);
+		if (boot_command_line[0])
+			strlcat(boot_command_line, " ", COMMAND_LINE_SIZE);
 		strlcat(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
 	}
+
+	if (BUILTIN_EXTEND_WITH_PROM && arcs_cmdline[0]) {
+		if (boot_command_line[0])
+			strlcat(boot_command_line, " ", COMMAND_LINE_SIZE);
+		strlcat(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE);
+	}
 #endif
 #endif
 	strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
@@ -706,6 +764,9 @@ static void __init arch_mem_init(char **
 	for_each_memblock(reserved, reg)
 		if (reg->size != 0)
 			reserve_bootmem(reg->base, reg->size, BOOTMEM_DEFAULT);
+
+	reserve_bootmem_region(__pa_symbol(&__nosave_begin),
+			__pa_symbol(&__nosave_end)); /* Reserve for hibernation */
 }
 
 static void __init resource_init(void)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/signal32.c linux-libre-4.7-gnu/arch/mips/kernel/signal32.c
--- linux-libre-4.6-gnu/arch/mips/kernel/signal32.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/signal32.c	2016-07-24 15:23:50.000000000 -0400
@@ -227,6 +227,12 @@ int copy_siginfo_to_user32(compat_siginf
 			err |= __put_user(from->si_uid, &to->si_uid);
 			err |= __put_user(from->si_int, &to->si_int);
 			break;
+		case __SI_SYS >> 16:
+			err |= __copy_to_user(&to->si_call_addr, &from->si_call_addr,
+					      sizeof(compat_uptr_t));
+			err |= __put_user(from->si_syscall, &to->si_syscall);
+			err |= __put_user(from->si_arch, &to->si_arch);
+			break;
 		}
 	}
 	return err;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/signal.c linux-libre-4.7-gnu/arch/mips/kernel/signal.c
--- linux-libre-4.6-gnu/arch/mips/kernel/signal.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/signal.c	2016-07-24 15:23:50.000000000 -0400
@@ -195,6 +195,9 @@ static int restore_msa_extcontext(void _
 	unsigned int csr;
 	int i, err;
 
+	if (!config_enabled(CONFIG_CPU_HAS_MSA))
+		return SIGSYS;
+
 	if (size != sizeof(*msa))
 		return -EINVAL;
 
@@ -398,8 +401,8 @@ int protected_restore_fp_context(void __
 	}
 
 fp_done:
-	if (used & USED_EXTCONTEXT)
-		err |= restore_extcontext(sc_to_extcontext(sc));
+	if (!err && (used & USED_EXTCONTEXT))
+		err = restore_extcontext(sc_to_extcontext(sc));
 
 	return err ?: sig;
 }
@@ -767,15 +770,7 @@ static void handle_signal(struct ksignal
 	sigset_t *oldset = sigmask_to_save();
 	int ret;
 	struct mips_abi *abi = current->thread.abi;
-#ifdef CONFIG_CPU_MICROMIPS
-	void *vdso;
-	unsigned long tmp = (unsigned long)current->mm->context.vdso;
-
-	set_isa16_mode(tmp);
-	vdso = (void *)tmp;
-#else
 	void *vdso = current->mm->context.vdso;
-#endif
 
 	if (regs->regs[0]) {
 		switch(regs->regs[2]) {
@@ -798,7 +793,7 @@ static void handle_signal(struct ksignal
 		regs->regs[0] = 0;		/* Don't deal with this again.	*/
 	}
 
-	if (sig_uses_siginfo(&ksig->ka))
+	if (sig_uses_siginfo(&ksig->ka, abi))
 		ret = abi->setup_rt_frame(vdso + abi->vdso->off_rt_sigreturn,
 					  ksig, regs, oldset);
 	else
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/smp-bmips.c linux-libre-4.7-gnu/arch/mips/kernel/smp-bmips.c
--- linux-libre-4.6-gnu/arch/mips/kernel/smp-bmips.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/smp-bmips.c	2016-07-24 15:23:50.000000000 -0400
@@ -243,6 +243,7 @@ static void bmips_init_secondary(void)
 		break;
 	case CPU_BMIPS5000:
 		write_c0_brcm_action(ACTION_CLR_IPI(smp_processor_id(), 0));
+		current_cpu_data.core = (read_c0_brcm_config() >> 25) & 3;
 		break;
 	}
 }
@@ -565,3 +566,90 @@ asmlinkage void __weak plat_wired_tlb_se
 	 * once the wired entries are present.
 	 */
 }
+
+void __init bmips_cpu_setup(void)
+{
+	void __iomem __maybe_unused *cbr = BMIPS_GET_CBR();
+	u32 __maybe_unused cfg;
+
+	switch (current_cpu_type()) {
+	case CPU_BMIPS3300:
+		/* Set BIU to async mode */
+		set_c0_brcm_bus_pll(BIT(22));
+		__sync();
+
+		/* put the BIU back in sync mode */
+		clear_c0_brcm_bus_pll(BIT(22));
+
+		/* clear BHTD to enable branch history table */
+		clear_c0_brcm_reset(BIT(16));
+
+		/* Flush and enable RAC */
+		cfg = __raw_readl(cbr + BMIPS_RAC_CONFIG);
+		__raw_writel(cfg | 0x100, BMIPS_RAC_CONFIG);
+		__raw_readl(cbr + BMIPS_RAC_CONFIG);
+
+		cfg = __raw_readl(cbr + BMIPS_RAC_CONFIG);
+		__raw_writel(cfg | 0xf, BMIPS_RAC_CONFIG);
+		__raw_readl(cbr + BMIPS_RAC_CONFIG);
+
+		cfg = __raw_readl(cbr + BMIPS_RAC_ADDRESS_RANGE);
+		__raw_writel(cfg | 0x0fff0000, cbr + BMIPS_RAC_ADDRESS_RANGE);
+		__raw_readl(cbr + BMIPS_RAC_ADDRESS_RANGE);
+		break;
+
+	case CPU_BMIPS4380:
+		/* CBG workaround for early BMIPS4380 CPUs */
+		switch (read_c0_prid()) {
+		case 0x2a040:
+		case 0x2a042:
+		case 0x2a044:
+		case 0x2a060:
+			cfg = __raw_readl(cbr + BMIPS_L2_CONFIG);
+			__raw_writel(cfg & ~0x07000000, cbr + BMIPS_L2_CONFIG);
+			__raw_readl(cbr + BMIPS_L2_CONFIG);
+		}
+
+		/* clear BHTD to enable branch history table */
+		clear_c0_brcm_config_0(BIT(21));
+
+		/* XI/ROTR enable */
+		set_c0_brcm_config_0(BIT(23));
+		set_c0_brcm_cmt_ctrl(BIT(15));
+		break;
+
+	case CPU_BMIPS5000:
+		/* enable RDHWR, BRDHWR */
+		set_c0_brcm_config(BIT(17) | BIT(21));
+
+		/* Disable JTB */
+		__asm__ __volatile__(
+		"	.set	noreorder\n"
+		"	li	$8, 0x5a455048\n"
+		"	.word	0x4088b00f\n"	/* mtc0	t0, $22, 15 */
+		"	.word	0x4008b008\n"	/* mfc0	t0, $22, 8 */
+		"	li	$9, 0x00008000\n"
+		"	or	$8, $8, $9\n"
+		"	.word	0x4088b008\n"	/* mtc0	t0, $22, 8 */
+		"	sync\n"
+		"	li	$8, 0x0\n"
+		"	.word	0x4088b00f\n"	/* mtc0	t0, $22, 15 */
+		"	.set	reorder\n"
+		: : : "$8", "$9");
+
+		/* XI enable */
+		set_c0_brcm_config(BIT(27));
+
+		/* enable MIPS32R2 ROR instruction for XI TLB handlers */
+		__asm__ __volatile__(
+		"	li	$8, 0x5a455048\n"
+		"	.word	0x4088b00f\n"	/* mtc0 $8, $22, 15 */
+		"	nop; nop; nop\n"
+		"	.word	0x4008b008\n"	/* mfc0 $8, $22, 8 */
+		"	lui	$9, 0x0100\n"
+		"	or	$8, $9\n"
+		"	.word	0x4088b008\n"	/* mtc0 $8, $22, 8 */
+		: : : "$8", "$9");
+		break;
+	}
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/smp.c linux-libre-4.7-gnu/arch/mips/kernel/smp.c
--- linux-libre-4.6-gnu/arch/mips/kernel/smp.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/smp.c	2016-07-24 15:23:50.000000000 -0400
@@ -243,18 +243,6 @@ static int __init mips_smp_ipi_init(void
 	struct irq_domain *ipidomain;
 	struct device_node *node;
 
-	/*
-	 * In some cases like qemu-malta, it is desired to try SMP with
-	 * a single core. Qemu-malta has no GIC, so an attempt to set any IPIs
-	 * would cause a BUG_ON() to be triggered since there's no ipidomain.
-	 *
-	 * Since for a single core system IPIs aren't required really, skip the
-	 * initialisation which should generally keep any such configurations
-	 * happy and only fail hard when trying to truely run SMP.
-	 */
-	if (cpumask_weight(cpu_possible_mask) == 1)
-		return 0;
-
 	node = of_irq_find_parent(of_root);
 	ipidomain = irq_find_matching_host(node, DOMAIN_BUS_IPI);
 
@@ -266,7 +254,17 @@ static int __init mips_smp_ipi_init(void
 	if (node && !ipidomain)
 		ipidomain = irq_find_matching_host(NULL, DOMAIN_BUS_IPI);
 
-	BUG_ON(!ipidomain);
+	/*
+	 * There are systems which only use IPI domains some of the time,
+	 * depending upon configuration we don't know until runtime. An
+	 * example is Malta where we may compile in support for GIC & the
+	 * MT ASE, but run on a system which has multiple VPEs in a single
+	 * core and doesn't include a GIC. Until all IPI implementations
+	 * have been converted to use IPI domains the best we can do here
+	 * is to return & hope some other code sets up the IPIs.
+	 */
+	if (!ipidomain)
+		return 0;
 
 	call_virq = irq_reserve_ipi(ipidomain, cpu_possible_mask);
 	BUG_ON(!call_virq);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/smp-cps.c linux-libre-4.7-gnu/arch/mips/kernel/smp-cps.c
--- linux-libre-4.6-gnu/arch/mips/kernel/smp-cps.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/smp-cps.c	2016-07-24 15:23:50.000000000 -0400
@@ -27,15 +27,27 @@
 #include <asm/time.h>
 #include <asm/uasm.h>
 
+static bool threads_disabled;
 static DECLARE_BITMAP(core_power, NR_CPUS);
 
 struct core_boot_config *mips_cps_core_bootcfg;
 
+static int __init setup_nothreads(char *s)
+{
+	threads_disabled = true;
+	return 0;
+}
+early_param("nothreads", setup_nothreads);
+
 static unsigned core_vpe_count(unsigned core)
 {
 	unsigned cfg;
 
-	if (!config_enabled(CONFIG_MIPS_MT_SMP) || !cpu_has_mipsmt)
+	if (threads_disabled)
+		return 1;
+
+	if ((!config_enabled(CONFIG_MIPS_MT_SMP) || !cpu_has_mipsmt)
+		&& (!config_enabled(CONFIG_CPU_MIPSR6) || !cpu_has_vp))
 		return 1;
 
 	mips_cm_lock_other(core, 0);
@@ -47,11 +59,12 @@ static unsigned core_vpe_count(unsigned
 static void __init cps_smp_setup(void)
 {
 	unsigned int ncores, nvpes, core_vpes;
+	unsigned long core_entry;
 	int c, v;
 
 	/* Detect & record VPE topology */
 	ncores = mips_cm_numcores();
-	pr_info("VPE topology ");
+	pr_info("%s topology ", cpu_has_mips_r6 ? "VP" : "VPE");
 	for (c = nvpes = 0; c < ncores; c++) {
 		core_vpes = core_vpe_count(c);
 		pr_cont("%c%u", c ? ',' : '{', core_vpes);
@@ -62,7 +75,7 @@ static void __init cps_smp_setup(void)
 
 		for (v = 0; v < min_t(int, core_vpes, NR_CPUS - nvpes); v++) {
 			cpu_data[nvpes + v].core = c;
-#ifdef CONFIG_MIPS_MT_SMP
+#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_CPU_MIPSR6)
 			cpu_data[nvpes + v].vpe_id = v;
 #endif
 		}
@@ -91,6 +104,11 @@ static void __init cps_smp_setup(void)
 	/* Make core 0 coherent with everything */
 	write_gcr_cl_coherence(0xff);
 
+	if (mips_cm_revision() >= CM_REV_CM3) {
+		core_entry = CKSEG1ADDR((unsigned long)mips_cps_core_entry);
+		write_gcr_bev_base(core_entry);
+	}
+
 #ifdef CONFIG_MIPS_MT_FPAFF
 	/* If we have an FPU, enroll ourselves in the FPU-full mask */
 	if (cpu_has_fpu)
@@ -213,6 +231,18 @@ static void boot_core(unsigned core)
 	if (mips_cpc_present()) {
 		/* Reset the core */
 		mips_cpc_lock_other(core);
+
+		if (mips_cm_revision() >= CM_REV_CM3) {
+			/* Run VP0 following the reset */
+			write_cpc_co_vp_run(0x1);
+
+			/*
+			 * Ensure that the VP_RUN register is written before the
+			 * core leaves reset.
+			 */
+			wmb();
+		}
+
 		write_cpc_co_cmd(CPC_Cx_CMD_RESET);
 
 		timeout = 100;
@@ -250,7 +280,10 @@ static void boot_core(unsigned core)
 
 static void remote_vpe_boot(void *dummy)
 {
-	mips_cps_boot_vpes();
+	unsigned core = current_cpu_data.core;
+	struct core_boot_config *core_cfg = &mips_cps_core_bootcfg[core];
+
+	mips_cps_boot_vpes(core_cfg, cpu_vpe_id(&current_cpu_data));
 }
 
 static void cps_boot_secondary(int cpu, struct task_struct *idle)
@@ -259,6 +292,7 @@ static void cps_boot_secondary(int cpu,
 	unsigned vpe_id = cpu_vpe_id(&cpu_data[cpu]);
 	struct core_boot_config *core_cfg = &mips_cps_core_bootcfg[core];
 	struct vpe_boot_config *vpe_cfg = &core_cfg->vpe_config[vpe_id];
+	unsigned long core_entry;
 	unsigned int remote;
 	int err;
 
@@ -276,6 +310,13 @@ static void cps_boot_secondary(int cpu,
 		goto out;
 	}
 
+	if (cpu_has_vp) {
+		mips_cm_lock_other(core, vpe_id);
+		core_entry = CKSEG1ADDR((unsigned long)mips_cps_core_entry);
+		write_gcr_co_reset_base(core_entry);
+		mips_cm_unlock_other();
+	}
+
 	if (core != current_cpu_data.core) {
 		/* Boot a VPE on another powered up core */
 		for (remote = 0; remote < NR_CPUS; remote++) {
@@ -293,10 +334,10 @@ static void cps_boot_secondary(int cpu,
 		goto out;
 	}
 
-	BUG_ON(!cpu_has_mipsmt);
+	BUG_ON(!cpu_has_mipsmt && !cpu_has_vp);
 
 	/* Boot a VPE on this core */
-	mips_cps_boot_vpes();
+	mips_cps_boot_vpes(core_cfg, vpe_id);
 out:
 	preempt_enable();
 }
@@ -307,8 +348,23 @@ static void cps_init_secondary(void)
 	if (cpu_has_mipsmt)
 		dmt();
 
-	change_c0_status(ST0_IM, STATUSF_IP2 | STATUSF_IP3 | STATUSF_IP4 |
-				 STATUSF_IP5 | STATUSF_IP6 | STATUSF_IP7);
+	if (mips_cm_revision() >= CM_REV_CM3) {
+		unsigned ident = gic_read_local_vp_id();
+
+		/*
+		 * Ensure that our calculation of the VP ID matches up with
+		 * what the GIC reports, otherwise we'll have configured
+		 * interrupts incorrectly.
+		 */
+		BUG_ON(ident != mips_cm_vp_id(smp_processor_id()));
+	}
+
+	if (cpu_has_veic)
+		clear_c0_status(ST0_IM);
+	else
+		change_c0_status(ST0_IM, STATUSF_IP2 | STATUSF_IP3 |
+					 STATUSF_IP4 | STATUSF_IP5 |
+					 STATUSF_IP6 | STATUSF_IP7);
 }
 
 static void cps_smp_finish(void)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/spram.c linux-libre-4.7-gnu/arch/mips/kernel/spram.c
--- linux-libre-4.6-gnu/arch/mips/kernel/spram.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/spram.c	2016-07-24 15:23:50.000000000 -0400
@@ -210,6 +210,7 @@ void spram_config(void)
 	case CPU_P5600:
 	case CPU_QEMU_GENERIC:
 	case CPU_I6400:
+	case CPU_P6600:
 		config0 = read_c0_config();
 		/* FIXME: addresses are Malta specific */
 		if (config0 & (1<<24)) {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/traps.c linux-libre-4.7-gnu/arch/mips/kernel/traps.c
--- linux-libre-4.6-gnu/arch/mips/kernel/traps.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/traps.c	2016-07-24 15:23:50.000000000 -0400
@@ -145,7 +145,7 @@ static void show_backtrace(struct task_s
 	if (!task)
 		task = current;
 
-	if (raw_show_trace || !__kernel_text_address(pc)) {
+	if (raw_show_trace || user_mode(regs) || !__kernel_text_address(pc)) {
 		show_raw_backtrace(sp);
 		return;
 	}
@@ -399,11 +399,8 @@ void __noreturn die(const char *str, str
 	if (in_interrupt())
 		panic("Fatal exception in interrupt");
 
-	if (panic_on_oops) {
-		printk(KERN_EMERG "Fatal exception: panic in 5 seconds");
-		ssleep(5);
+	if (panic_on_oops)
 		panic("Fatal exception");
-	}
 
 	if (regs && kexec_should_crash(current))
 		crash_kexec(regs);
@@ -1249,7 +1246,7 @@ static int enable_restore_fp_context(int
 		err = init_fpu();
 		if (msa && !err) {
 			enable_msa();
-			_init_msa_upper();
+			init_msa_upper();
 			set_thread_flag(TIF_USEDMSA);
 			set_thread_flag(TIF_MSA_CTX_LIVE);
 		}
@@ -1312,7 +1309,7 @@ static int enable_restore_fp_context(int
 	 */
 	prior_msa = test_and_set_thread_flag(TIF_MSA_CTX_LIVE);
 	if (!prior_msa && was_fpu_owner) {
-		_init_msa_upper();
+		init_msa_upper();
 
 		goto out;
 	}
@@ -1329,7 +1326,7 @@ static int enable_restore_fp_context(int
 		 * of each vector register such that it cannot see data left
 		 * behind by another task.
 		 */
-		_init_msa_upper();
+		init_msa_upper();
 	} else {
 		/* We need to restore the vector context. */
 		restore_msa(current);
@@ -1356,7 +1353,6 @@ asmlinkage void do_cpu(struct pt_regs *r
 	unsigned long fcr31;
 	unsigned int cpid;
 	int status, err;
-	unsigned long __maybe_unused flags;
 	int sig;
 
 	prev_state = exception_enter();
@@ -1501,16 +1497,13 @@ asmlinkage void do_watch(struct pt_regs
 {
 	siginfo_t info = { .si_signo = SIGTRAP, .si_code = TRAP_HWBKPT };
 	enum ctx_state prev_state;
-	u32 cause;
 
 	prev_state = exception_enter();
 	/*
 	 * Clear WP (bit 22) bit of cause register so we don't loop
 	 * forever.
 	 */
-	cause = read_c0_cause();
-	cause &= ~(1 << 22);
-	write_c0_cause(cause);
+	clear_c0_cause(CAUSEF_WP);
 
 	/*
 	 * If the current thread has the watch registers loaded, save
@@ -1647,6 +1640,7 @@ static inline void parity_protection_ini
 	case CPU_P5600:
 	case CPU_QEMU_GENERIC:
 	case CPU_I6400:
+	case CPU_P6600:
 		{
 #define ERRCTL_PE	0x80000000
 #define ERRCTL_L2P	0x00800000
@@ -1777,7 +1771,8 @@ asmlinkage void do_ftlb(void)
 
 	/* For the moment, report the problem and hang. */
 	if ((cpu_has_mips_r2_r6) &&
-	    ((current_cpu_data.processor_id & 0xff0000) == PRID_COMP_MIPS)) {
+	    (((current_cpu_data.processor_id & 0xff0000) == PRID_COMP_MIPS) ||
+	    ((current_cpu_data.processor_id & 0xff0000) == PRID_COMP_LOONGSON))) {
 		pr_err("FTLB error exception, cp0_ecc=0x%08x:\n",
 		       read_c0_ecc());
 		pr_err("cp0_errorepc == %0*lx\n", field, read_c0_errorepc());
@@ -2119,6 +2114,13 @@ void per_cpu_trap_init(bool is_boot_cpu)
 	 *  o read IntCtl.IPFDC to determine the fast debug channel interrupt
 	 */
 	if (cpu_has_mips_r2_r6) {
+		/*
+		 * We shouldn't trust a secondary core has a sane EBASE register
+		 * so use the one calculated by the boot CPU.
+		 */
+		if (!is_boot_cpu)
+			write_c0_ebase(ebase);
+
 		cp0_compare_irq_shift = CAUSEB_TI - CAUSEB_IP;
 		cp0_compare_irq = (read_c0_intctl() >> INTCTLB_IPTI) & 7;
 		cp0_perfcount_irq = (read_c0_intctl() >> INTCTLB_IPPCI) & 7;
@@ -2134,7 +2136,7 @@ void per_cpu_trap_init(bool is_boot_cpu)
 	}
 
 	if (!cpu_data[cpu].asid_cache)
-		cpu_data[cpu].asid_cache = ASID_FIRST_VERSION;
+		cpu_data[cpu].asid_cache = asid_first_version(cpu);
 
 	atomic_inc(&init_mm.mm_count);
 	current->active_mm = &init_mm;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/unaligned.c linux-libre-4.7-gnu/arch/mips/kernel/unaligned.c
--- linux-libre-4.6-gnu/arch/mips/kernel/unaligned.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/unaligned.c	2016-07-24 15:23:50.000000000 -0400
@@ -1191,6 +1191,7 @@ static void emulate_load_store_insn(stru
 	case ldc1_op:
 	case swc1_op:
 	case sdc1_op:
+	case cop1x_op:
 		die_if_kernel("Unaligned FP access in kernel code", regs);
 		BUG_ON(!used_math());
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/vdso.c linux-libre-4.7-gnu/arch/mips/kernel/vdso.c
--- linux-libre-4.6-gnu/arch/mips/kernel/vdso.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/vdso.c	2016-07-24 15:23:50.000000000 -0400
@@ -104,7 +104,8 @@ int arch_setup_additional_pages(struct l
 	struct resource gic_res;
 	int ret;
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
 
 	/*
 	 * Determine total area size. This includes the VDSO data itself, the
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/vmlinux.lds.S linux-libre-4.7-gnu/arch/mips/kernel/vmlinux.lds.S
--- linux-libre-4.6-gnu/arch/mips/kernel/vmlinux.lds.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/vmlinux.lds.S	2016-07-24 15:23:50.000000000 -0400
@@ -136,6 +136,27 @@ SECTIONS
 #ifdef CONFIG_SMP
 	PERCPU_SECTION(1 << CONFIG_MIPS_L1_CACHE_SHIFT)
 #endif
+
+#ifdef CONFIG_RELOCATABLE
+	. = ALIGN(4);
+
+	.data.reloc : {
+		_relocation_start = .;
+		/*
+		 * Space for relocation table
+		 * This needs to be filled so that the
+		 * relocs tool can overwrite the content.
+		 * An invalid value is left at the start of the
+		 * section to abort relocation if the table
+		 * has not been filled in.
+		 */
+		LONG(0xFFFFFFFF);
+		FILL(0);
+		. += CONFIG_RELOCATION_TABLE_SIZE - 4;
+		_relocation_end = .;
+	}
+#endif
+
 #ifdef CONFIG_MIPS_RAW_APPENDED_DTB
 	__appended_dtb = .;
 	/* leave space for appended DTB */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kernel/watch.c linux-libre-4.7-gnu/arch/mips/kernel/watch.c
--- linux-libre-4.6-gnu/arch/mips/kernel/watch.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kernel/watch.c	2016-07-24 15:23:50.000000000 -0400
@@ -15,10 +15,9 @@
  * Install the watch registers for the current thread.	A maximum of
  * four registers are installed although the machine may have more.
  */
-void mips_install_watch_registers(void)
+void mips_install_watch_registers(struct task_struct *t)
 {
-	struct mips3264_watch_reg_state *watches =
-		&current->thread.watch.mips3264;
+	struct mips3264_watch_reg_state *watches = &t->thread.watch.mips3264;
 	switch (current_cpu_data.watch_reg_use_cnt) {
 	default:
 		BUG();
@@ -26,16 +25,20 @@ void mips_install_watch_registers(void)
 		write_c0_watchlo3(watches->watchlo[3]);
 		/* Write 1 to the I, R, and W bits to clear them, and
 		   1 to G so all ASIDs are trapped. */
-		write_c0_watchhi3(0x40000007 | watches->watchhi[3]);
+		write_c0_watchhi3(MIPS_WATCHHI_G | MIPS_WATCHHI_IRW |
+				  watches->watchhi[3]);
 	case 3:
 		write_c0_watchlo2(watches->watchlo[2]);
-		write_c0_watchhi2(0x40000007 | watches->watchhi[2]);
+		write_c0_watchhi2(MIPS_WATCHHI_G | MIPS_WATCHHI_IRW |
+				  watches->watchhi[2]);
 	case 2:
 		write_c0_watchlo1(watches->watchlo[1]);
-		write_c0_watchhi1(0x40000007 | watches->watchhi[1]);
+		write_c0_watchhi1(MIPS_WATCHHI_G | MIPS_WATCHHI_IRW |
+				  watches->watchhi[1]);
 	case 1:
 		write_c0_watchlo0(watches->watchlo[0]);
-		write_c0_watchhi0(0x40000007 | watches->watchhi[0]);
+		write_c0_watchhi0(MIPS_WATCHHI_G | MIPS_WATCHHI_IRW |
+				  watches->watchhi[0]);
 	}
 }
 
@@ -52,22 +55,26 @@ void mips_read_watch_registers(void)
 	default:
 		BUG();
 	case 4:
-		watches->watchhi[3] = (read_c0_watchhi3() & 0x0fff);
+		watches->watchhi[3] = (read_c0_watchhi3() &
+				       (MIPS_WATCHHI_MASK | MIPS_WATCHHI_IRW));
 	case 3:
-		watches->watchhi[2] = (read_c0_watchhi2() & 0x0fff);
+		watches->watchhi[2] = (read_c0_watchhi2() &
+				       (MIPS_WATCHHI_MASK | MIPS_WATCHHI_IRW));
 	case 2:
-		watches->watchhi[1] = (read_c0_watchhi1() & 0x0fff);
+		watches->watchhi[1] = (read_c0_watchhi1() &
+				       (MIPS_WATCHHI_MASK | MIPS_WATCHHI_IRW));
 	case 1:
-		watches->watchhi[0] = (read_c0_watchhi0() & 0x0fff);
+		watches->watchhi[0] = (read_c0_watchhi0() &
+				       (MIPS_WATCHHI_MASK | MIPS_WATCHHI_IRW));
 	}
 	if (current_cpu_data.watch_reg_use_cnt == 1 &&
-	    (watches->watchhi[0] & 7) == 0) {
+	    (watches->watchhi[0] & MIPS_WATCHHI_IRW) == 0) {
 		/* Pathological case of release 1 architecture that
 		 * doesn't set the condition bits.  We assume that
 		 * since we got here, the watch condition was met and
 		 * signal that the conditions requested in watchlo
 		 * were met.  */
-		watches->watchhi[0] |= (watches->watchlo[0] & 7);
+		watches->watchhi[0] |= (watches->watchlo[0] & MIPS_WATCHHI_IRW);
 	}
  }
 
@@ -110,86 +117,86 @@ void mips_probe_watch_registers(struct c
 	 * Check which of the I,R and W bits are supported, then
 	 * disable the register.
 	 */
-	write_c0_watchlo0(7);
+	write_c0_watchlo0(MIPS_WATCHLO_IRW);
 	back_to_back_c0_hazard();
 	t = read_c0_watchlo0();
 	write_c0_watchlo0(0);
-	c->watch_reg_masks[0] = t & 7;
+	c->watch_reg_masks[0] = t & MIPS_WATCHLO_IRW;
 
 	/* Write the mask bits and read them back to determine which
 	 * can be used. */
 	c->watch_reg_count = 1;
 	c->watch_reg_use_cnt = 1;
 	t = read_c0_watchhi0();
-	write_c0_watchhi0(t | 0xff8);
+	write_c0_watchhi0(t | MIPS_WATCHHI_MASK);
 	back_to_back_c0_hazard();
 	t = read_c0_watchhi0();
-	c->watch_reg_masks[0] |= (t & 0xff8);
-	if ((t & 0x80000000) == 0)
+	c->watch_reg_masks[0] |= (t & MIPS_WATCHHI_MASK);
+	if ((t & MIPS_WATCHHI_M) == 0)
 		return;
 
-	write_c0_watchlo1(7);
+	write_c0_watchlo1(MIPS_WATCHLO_IRW);
 	back_to_back_c0_hazard();
 	t = read_c0_watchlo1();
 	write_c0_watchlo1(0);
-	c->watch_reg_masks[1] = t & 7;
+	c->watch_reg_masks[1] = t & MIPS_WATCHLO_IRW;
 
 	c->watch_reg_count = 2;
 	c->watch_reg_use_cnt = 2;
 	t = read_c0_watchhi1();
-	write_c0_watchhi1(t | 0xff8);
+	write_c0_watchhi1(t | MIPS_WATCHHI_MASK);
 	back_to_back_c0_hazard();
 	t = read_c0_watchhi1();
-	c->watch_reg_masks[1] |= (t & 0xff8);
-	if ((t & 0x80000000) == 0)
+	c->watch_reg_masks[1] |= (t & MIPS_WATCHHI_MASK);
+	if ((t & MIPS_WATCHHI_M) == 0)
 		return;
 
-	write_c0_watchlo2(7);
+	write_c0_watchlo2(MIPS_WATCHLO_IRW);
 	back_to_back_c0_hazard();
 	t = read_c0_watchlo2();
 	write_c0_watchlo2(0);
-	c->watch_reg_masks[2] = t & 7;
+	c->watch_reg_masks[2] = t & MIPS_WATCHLO_IRW;
 
 	c->watch_reg_count = 3;
 	c->watch_reg_use_cnt = 3;
 	t = read_c0_watchhi2();
-	write_c0_watchhi2(t | 0xff8);
+	write_c0_watchhi2(t | MIPS_WATCHHI_MASK);
 	back_to_back_c0_hazard();
 	t = read_c0_watchhi2();
-	c->watch_reg_masks[2] |= (t & 0xff8);
-	if ((t & 0x80000000) == 0)
+	c->watch_reg_masks[2] |= (t & MIPS_WATCHHI_MASK);
+	if ((t & MIPS_WATCHHI_M) == 0)
 		return;
 
-	write_c0_watchlo3(7);
+	write_c0_watchlo3(MIPS_WATCHLO_IRW);
 	back_to_back_c0_hazard();
 	t = read_c0_watchlo3();
 	write_c0_watchlo3(0);
-	c->watch_reg_masks[3] = t & 7;
+	c->watch_reg_masks[3] = t & MIPS_WATCHLO_IRW;
 
 	c->watch_reg_count = 4;
 	c->watch_reg_use_cnt = 4;
 	t = read_c0_watchhi3();
-	write_c0_watchhi3(t | 0xff8);
+	write_c0_watchhi3(t | MIPS_WATCHHI_MASK);
 	back_to_back_c0_hazard();
 	t = read_c0_watchhi3();
-	c->watch_reg_masks[3] |= (t & 0xff8);
-	if ((t & 0x80000000) == 0)
+	c->watch_reg_masks[3] |= (t & MIPS_WATCHHI_MASK);
+	if ((t & MIPS_WATCHHI_M) == 0)
 		return;
 
 	/* We use at most 4, but probe and report up to 8. */
 	c->watch_reg_count = 5;
 	t = read_c0_watchhi4();
-	if ((t & 0x80000000) == 0)
+	if ((t & MIPS_WATCHHI_M) == 0)
 		return;
 
 	c->watch_reg_count = 6;
 	t = read_c0_watchhi5();
-	if ((t & 0x80000000) == 0)
+	if ((t & MIPS_WATCHHI_M) == 0)
 		return;
 
 	c->watch_reg_count = 7;
 	t = read_c0_watchhi6();
-	if ((t & 0x80000000) == 0)
+	if ((t & MIPS_WATCHHI_M) == 0)
 		return;
 
 	c->watch_reg_count = 8;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kvm/emulate.c linux-libre-4.7-gnu/arch/mips/kvm/emulate.c
--- linux-libre-4.6-gnu/arch/mips/kvm/emulate.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kvm/emulate.c	2016-07-24 15:23:50.000000000 -0400
@@ -302,12 +302,31 @@ static inline ktime_t kvm_mips_count_tim
  */
 static uint32_t kvm_mips_read_count_running(struct kvm_vcpu *vcpu, ktime_t now)
 {
-	ktime_t expires;
+	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	ktime_t expires, threshold;
+	uint32_t count, compare;
 	int running;
 
-	/* Is the hrtimer pending? */
+	/* Calculate the biased and scaled guest CP0_Count */
+	count = vcpu->arch.count_bias + kvm_mips_ktime_to_count(vcpu, now);
+	compare = kvm_read_c0_guest_compare(cop0);
+
+	/*
+	 * Find whether CP0_Count has reached the closest timer interrupt. If
+	 * not, we shouldn't inject it.
+	 */
+	if ((int32_t)(count - compare) < 0)
+		return count;
+
+	/*
+	 * The CP0_Count we're going to return has already reached the closest
+	 * timer interrupt. Quickly check if it really is a new interrupt by
+	 * looking at whether the interval until the hrtimer expiry time is
+	 * less than 1/4 of the timer period.
+	 */
 	expires = hrtimer_get_expires(&vcpu->arch.comparecount_timer);
-	if (ktime_compare(now, expires) >= 0) {
+	threshold = ktime_add_ns(now, vcpu->arch.count_period / 4);
+	if (ktime_before(expires, threshold)) {
 		/*
 		 * Cancel it while we handle it so there's no chance of
 		 * interference with the timeout handler.
@@ -329,8 +348,7 @@ static uint32_t kvm_mips_read_count_runn
 		}
 	}
 
-	/* Return the biased and scaled guest CP0_Count */
-	return vcpu->arch.count_bias + kvm_mips_ktime_to_count(vcpu, now);
+	return count;
 }
 
 /**
@@ -420,32 +438,6 @@ static void kvm_mips_resume_hrtimer(stru
 }
 
 /**
- * kvm_mips_update_hrtimer() - Update next expiry time of hrtimer.
- * @vcpu:	Virtual CPU.
- *
- * Recalculates and updates the expiry time of the hrtimer. This can be used
- * after timer parameters have been altered which do not depend on the time that
- * the change occurs (in those cases kvm_mips_freeze_hrtimer() and
- * kvm_mips_resume_hrtimer() are used directly).
- *
- * It is guaranteed that no timer interrupts will be lost in the process.
- *
- * Assumes !kvm_mips_count_disabled(@vcpu) (guest CP0_Count timer is running).
- */
-static void kvm_mips_update_hrtimer(struct kvm_vcpu *vcpu)
-{
-	ktime_t now;
-	uint32_t count;
-
-	/*
-	 * freeze_hrtimer takes care of a timer interrupts <= count, and
-	 * resume_hrtimer the hrtimer takes care of a timer interrupts > count.
-	 */
-	now = kvm_mips_freeze_hrtimer(vcpu, &count);
-	kvm_mips_resume_hrtimer(vcpu, now, count);
-}
-
-/**
  * kvm_mips_write_count() - Modify the count and update timer.
  * @vcpu:	Virtual CPU.
  * @count:	Guest CP0_Count value to set.
@@ -540,23 +532,42 @@ int kvm_mips_set_count_hz(struct kvm_vcp
  * kvm_mips_write_compare() - Modify compare and update timer.
  * @vcpu:	Virtual CPU.
  * @compare:	New CP0_Compare value.
+ * @ack:	Whether to acknowledge timer interrupt.
  *
  * Update CP0_Compare to a new value and update the timeout.
+ * If @ack, atomically acknowledge any pending timer interrupt, otherwise ensure
+ * any pending timer interrupt is preserved.
  */
-void kvm_mips_write_compare(struct kvm_vcpu *vcpu, uint32_t compare)
+void kvm_mips_write_compare(struct kvm_vcpu *vcpu, uint32_t compare, bool ack)
 {
 	struct mips_coproc *cop0 = vcpu->arch.cop0;
+	int dc;
+	u32 old_compare = kvm_read_c0_guest_compare(cop0);
+	ktime_t now;
+	uint32_t count;
 
 	/* if unchanged, must just be an ack */
-	if (kvm_read_c0_guest_compare(cop0) == compare)
+	if (old_compare == compare) {
+		if (!ack)
+			return;
+		kvm_mips_callbacks->dequeue_timer_int(vcpu);
+		kvm_write_c0_guest_compare(cop0, compare);
 		return;
+	}
+
+	/* freeze_hrtimer() takes care of timer interrupts <= count */
+	dc = kvm_mips_count_disabled(vcpu);
+	if (!dc)
+		now = kvm_mips_freeze_hrtimer(vcpu, &count);
+
+	if (ack)
+		kvm_mips_callbacks->dequeue_timer_int(vcpu);
 
-	/* Update compare */
 	kvm_write_c0_guest_compare(cop0, compare);
 
-	/* Update timeout if count enabled */
-	if (!kvm_mips_count_disabled(vcpu))
-		kvm_mips_update_hrtimer(vcpu);
+	/* resume_hrtimer() takes care of timer interrupts > count */
+	if (!dc)
+		kvm_mips_resume_hrtimer(vcpu, now, count);
 }
 
 /**
@@ -1068,15 +1079,15 @@ enum emulation_result kvm_mips_emulate_C
 					kvm_read_c0_guest_ebase(cop0));
 			} else if (rd == MIPS_CP0_TLB_HI && sel == 0) {
 				uint32_t nasid =
-					vcpu->arch.gprs[rt] & ASID_MASK;
+					vcpu->arch.gprs[rt] & KVM_ENTRYHI_ASID;
 				if ((KSEGX(vcpu->arch.gprs[rt]) != CKSEG0) &&
 				    ((kvm_read_c0_guest_entryhi(cop0) &
-				      ASID_MASK) != nasid)) {
+				      KVM_ENTRYHI_ASID) != nasid)) {
 					kvm_debug("MTCz, change ASID from %#lx to %#lx\n",
 						kvm_read_c0_guest_entryhi(cop0)
-						& ASID_MASK,
+						& KVM_ENTRYHI_ASID,
 						vcpu->arch.gprs[rt]
-						& ASID_MASK);
+						& KVM_ENTRYHI_ASID);
 
 					/* Blow away the shadow host TLBs */
 					kvm_mips_flush_host_tlb(1);
@@ -1095,9 +1106,9 @@ enum emulation_result kvm_mips_emulate_C
 
 				/* If we are writing to COMPARE */
 				/* Clear pending timer interrupt, if any */
-				kvm_mips_callbacks->dequeue_timer_int(vcpu);
 				kvm_mips_write_compare(vcpu,
-						       vcpu->arch.gprs[rt]);
+						       vcpu->arch.gprs[rt],
+						       true);
 			} else if ((rd == MIPS_CP0_STATUS) && (sel == 0)) {
 				unsigned int old_val, val, change;
 
@@ -1620,11 +1631,12 @@ enum emulation_result kvm_mips_emulate_c
 		 */
 		index = kvm_mips_guest_tlb_lookup(vcpu, (va & VPN2_MASK) |
 						  (kvm_read_c0_guest_entryhi
-						   (cop0) & ASID_MASK));
+						   (cop0) & KVM_ENTRYHI_ASID));
 
 		if (index < 0) {
 			vcpu->arch.host_cp0_entryhi = (va & VPN2_MASK);
 			vcpu->arch.host_cp0_badvaddr = va;
+			vcpu->arch.pc = curr_pc;
 			er = kvm_mips_emulate_tlbmiss_ld(cause, NULL, run,
 							 vcpu);
 			preempt_enable();
@@ -1636,6 +1648,8 @@ enum emulation_result kvm_mips_emulate_c
 			 * invalid exception to the guest
 			 */
 			if (!TLB_IS_VALID(*tlb, va)) {
+				vcpu->arch.host_cp0_badvaddr = va;
+				vcpu->arch.pc = curr_pc;
 				er = kvm_mips_emulate_tlbinv_ld(cause, NULL,
 								run, vcpu);
 				preempt_enable();
@@ -1655,7 +1669,7 @@ enum emulation_result kvm_mips_emulate_c
 			cache, op, base, arch->gprs[base], offset);
 		er = EMULATE_FAIL;
 		preempt_enable();
-		goto dont_update_pc;
+		goto done;
 
 	}
 
@@ -1683,16 +1697,20 @@ skip_fault:
 		kvm_err("NO-OP CACHE (cache: %#x, op: %#x, base[%d]: %#lx, offset: %#x\n",
 			cache, op, base, arch->gprs[base], offset);
 		er = EMULATE_FAIL;
-		preempt_enable();
-		goto dont_update_pc;
 	}
 
 	preempt_enable();
+done:
+	/* Rollback PC only if emulation was unsuccessful */
+	if (er == EMULATE_FAIL)
+		vcpu->arch.pc = curr_pc;
 
 dont_update_pc:
-	/* Rollback PC */
-	vcpu->arch.pc = curr_pc;
-done:
+	/*
+	 * This is for exceptions whose emulation updates the PC, so do not
+	 * overwrite the PC under any circumstances
+	 */
+
 	return er;
 }
 
@@ -1786,7 +1804,7 @@ enum emulation_result kvm_mips_emulate_t
 	struct mips_coproc *cop0 = vcpu->arch.cop0;
 	struct kvm_vcpu_arch *arch = &vcpu->arch;
 	unsigned long entryhi = (vcpu->arch.  host_cp0_badvaddr & VPN2_MASK) |
-				(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
+			(kvm_read_c0_guest_entryhi(cop0) & KVM_ENTRYHI_ASID);
 
 	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
 		/* save old pc */
@@ -1833,7 +1851,7 @@ enum emulation_result kvm_mips_emulate_t
 	struct kvm_vcpu_arch *arch = &vcpu->arch;
 	unsigned long entryhi =
 		(vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
-		(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
+		(kvm_read_c0_guest_entryhi(cop0) & KVM_ENTRYHI_ASID);
 
 	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
 		/* save old pc */
@@ -1878,7 +1896,7 @@ enum emulation_result kvm_mips_emulate_t
 	struct mips_coproc *cop0 = vcpu->arch.cop0;
 	struct kvm_vcpu_arch *arch = &vcpu->arch;
 	unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
-				(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
+			(kvm_read_c0_guest_entryhi(cop0) & KVM_ENTRYHI_ASID);
 
 	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
 		/* save old pc */
@@ -1922,7 +1940,7 @@ enum emulation_result kvm_mips_emulate_t
 	struct mips_coproc *cop0 = vcpu->arch.cop0;
 	struct kvm_vcpu_arch *arch = &vcpu->arch;
 	unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
-		(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
+		(kvm_read_c0_guest_entryhi(cop0) & KVM_ENTRYHI_ASID);
 
 	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
 		/* save old pc */
@@ -1967,7 +1985,7 @@ enum emulation_result kvm_mips_handle_tl
 #ifdef DEBUG
 	struct mips_coproc *cop0 = vcpu->arch.cop0;
 	unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
-				(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
+			(kvm_read_c0_guest_entryhi(cop0) & KVM_ENTRYHI_ASID);
 	int index;
 
 	/* If address not in the guest TLB, then we are in trouble */
@@ -1994,7 +2012,7 @@ enum emulation_result kvm_mips_emulate_t
 {
 	struct mips_coproc *cop0 = vcpu->arch.cop0;
 	unsigned long entryhi = (vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |
-				(kvm_read_c0_guest_entryhi(cop0) & ASID_MASK);
+			(kvm_read_c0_guest_entryhi(cop0) & KVM_ENTRYHI_ASID);
 	struct kvm_vcpu_arch *arch = &vcpu->arch;
 
 	if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {
@@ -2569,7 +2587,8 @@ enum emulation_result kvm_mips_handle_tl
 	 */
 	index = kvm_mips_guest_tlb_lookup(vcpu,
 		      (va & VPN2_MASK) |
-		      (kvm_read_c0_guest_entryhi(vcpu->arch.cop0) & ASID_MASK));
+		      (kvm_read_c0_guest_entryhi(vcpu->arch.cop0) &
+		       KVM_ENTRYHI_ASID));
 	if (index < 0) {
 		if (exccode == EXCCODE_TLBL) {
 			er = kvm_mips_emulate_tlbmiss_ld(cause, opc, run, vcpu);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kvm/interrupt.h linux-libre-4.7-gnu/arch/mips/kvm/interrupt.h
--- linux-libre-4.6-gnu/arch/mips/kvm/interrupt.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kvm/interrupt.h	2016-07-24 15:23:50.000000000 -0400
@@ -28,6 +28,7 @@
 #define MIPS_EXC_MAX                12
 /* XXXSL More to follow */
 
+extern char __kvm_mips_vcpu_run_end[];
 extern char mips32_exception[], mips32_exceptionEnd[];
 extern char mips32_GuestException[], mips32_GuestExceptionEnd[];
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kvm/locore.S linux-libre-4.7-gnu/arch/mips/kvm/locore.S
--- linux-libre-4.6-gnu/arch/mips/kvm/locore.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kvm/locore.S	2016-07-24 15:23:50.000000000 -0400
@@ -32,7 +32,6 @@
     EXPORT(x);
 
 /* Overload, Danger Will Robinson!! */
-#define PT_HOST_ASID        PT_BVADDR
 #define PT_HOST_USERLOCAL   PT_EPC
 
 #define CP0_DDATA_LO        $28,3
@@ -49,45 +48,18 @@
  * a1: vcpu
  */
 	.set	noreorder
-	.set	noat
 
 FEXPORT(__kvm_mips_vcpu_run)
 	/* k0/k1 not being used in host kernel context */
 	INT_ADDIU k1, sp, -PT_SIZE
-	LONG_S	$0, PT_R0(k1)
-	LONG_S	$1, PT_R1(k1)
-	LONG_S	$2, PT_R2(k1)
-	LONG_S	$3, PT_R3(k1)
-
-	LONG_S	$4, PT_R4(k1)
-	LONG_S	$5, PT_R5(k1)
-	LONG_S	$6, PT_R6(k1)
-	LONG_S	$7, PT_R7(k1)
-
-	LONG_S	$8,  PT_R8(k1)
-	LONG_S	$9,  PT_R9(k1)
-	LONG_S	$10, PT_R10(k1)
-	LONG_S	$11, PT_R11(k1)
-	LONG_S	$12, PT_R12(k1)
-	LONG_S	$13, PT_R13(k1)
-	LONG_S	$14, PT_R14(k1)
-	LONG_S	$15, PT_R15(k1)
 	LONG_S	$16, PT_R16(k1)
 	LONG_S	$17, PT_R17(k1)
-
 	LONG_S	$18, PT_R18(k1)
 	LONG_S	$19, PT_R19(k1)
 	LONG_S	$20, PT_R20(k1)
 	LONG_S	$21, PT_R21(k1)
 	LONG_S	$22, PT_R22(k1)
 	LONG_S	$23, PT_R23(k1)
-	LONG_S	$24, PT_R24(k1)
-	LONG_S	$25, PT_R25(k1)
-
-	/*
-	 * XXXKYMA k0/k1 not saved, not being used if we got here through
-	 * an ioctl()
-	 */
 
 	LONG_S	$28, PT_R28(k1)
 	LONG_S	$29, PT_R29(k1)
@@ -104,11 +76,6 @@ FEXPORT(__kvm_mips_vcpu_run)
 	mfc0	v0, CP0_STATUS
 	LONG_S	v0, PT_STATUS(k1)
 
-	/* Save host ASID, shove it into the BVADDR location */
-	mfc0	v1, CP0_ENTRYHI
-	andi	v1, 0xff
-	LONG_S	v1, PT_HOST_ASID(k1)
-
 	/* Save DDATA_LO, will be used to store pointer to vcpu */
 	mfc0	v1, CP0_DDATA_LO
 	LONG_S	v1, PT_HOST_USERLOCAL(k1)
@@ -170,13 +137,21 @@ FEXPORT(__kvm_mips_load_asid)
 	INT_SLL	t2, t2, 2                   /* x4 */
 	REG_ADDU t3, t1, t2
 	LONG_L	k0, (t3)
-	andi	k0, k0, 0xff
+#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE
+	li	t3, CPUINFO_SIZE/4
+	mul	t2, t2, t3		/* x sizeof(struct cpuinfo_mips)/4 */
+	LONG_L	t2, (cpu_data + CPUINFO_ASID_MASK)(t2)
+	and	k0, k0, t2
+#else
+	andi	k0, k0, MIPS_ENTRYHI_ASID
+#endif
 	mtc0	k0, CP0_ENTRYHI
 	ehb
 
 	/* Disable RDHWR access */
 	mtc0	zero, CP0_HWRENA
 
+	.set	noat
 	/* Now load up the Guest Context from VCPU */
 	LONG_L	$1, VCPU_R1(k1)
 	LONG_L	$2, VCPU_R2(k1)
@@ -227,6 +202,7 @@ FEXPORT(__kvm_mips_load_k0k1)
 
 	/* Jump to guest */
 	eret
+EXPORT(__kvm_mips_vcpu_run_end)
 
 VECTOR(MIPSX(exception), unknown)
 /* Find out what mode we came from and jump to the proper handler. */
@@ -288,6 +264,8 @@ NESTED (MIPSX(GuestException), CALLFRAME
 	LONG_S	$30, VCPU_R30(k1)
 	LONG_S	$31, VCPU_R31(k1)
 
+	.set at
+
 	/* We need to save hi/lo and restore them on the way out */
 	mfhi	t0
 	LONG_S	t0, VCPU_HI(k1)
@@ -339,9 +317,7 @@ NESTED (MIPSX(GuestException), CALLFRAME
 	/* load up the host EBASE */
 	mfc0	v0, CP0_STATUS
 
-	.set	at
 	or	k0, v0, ST0_BEV
-	.set	noat
 
 	mtc0	k0, CP0_STATUS
 	ehb
@@ -353,7 +329,6 @@ NESTED (MIPSX(GuestException), CALLFRAME
 	 * If FPU is enabled, save FCR31 and clear it so that later ctc1's don't
 	 * trigger FPE for pending exceptions.
 	 */
-	.set	at
 	and	v1, v0, ST0_CU1
 	beqz	v1, 1f
 	 nop
@@ -363,7 +338,6 @@ NESTED (MIPSX(GuestException), CALLFRAME
 	sw	t0, VCPU_FCR31(k1)
 	ctc1	zero,fcr31
 	.set	pop
-	.set	noat
 1:
 
 #ifdef CONFIG_CPU_HAS_MSA
@@ -386,10 +360,8 @@ NESTED (MIPSX(GuestException), CALLFRAME
 #endif
 
 	/* Now that the new EBASE has been loaded, unset BEV and KSU_USER */
-	.set	at
 	and	v0, v0, ~(ST0_EXL | KSU_USER | ST0_IE)
 	or	v0, v0, ST0_CU0
-	.set	noat
 	mtc0	v0, CP0_STATUS
 	ehb
 
@@ -456,18 +428,14 @@ __kvm_mips_return_to_guest:
 
 	/* Switch EBASE back to the one used by KVM */
 	mfc0	v1, CP0_STATUS
-	.set	at
 	or	k0, v1, ST0_BEV
-	.set	noat
 	mtc0	k0, CP0_STATUS
 	ehb
 	mtc0	t0, CP0_EBASE
 
 	/* Setup status register for running guest in UM */
-	.set	at
 	or	v1, v1, (ST0_EXL | KSU_USER | ST0_IE)
 	and	v1, v1, ~(ST0_CU0 | ST0_MX)
-	.set	noat
 	mtc0	v1, CP0_STATUS
 	ehb
 
@@ -489,13 +457,21 @@ __kvm_mips_return_to_guest:
 	INT_SLL	t2, t2, 2		/* x4 */
 	REG_ADDU t3, t1, t2
 	LONG_L	k0, (t3)
-	andi	k0, k0, 0xff
+#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE
+	li	t3, CPUINFO_SIZE/4
+	mul	t2, t2, t3		/* x sizeof(struct cpuinfo_mips)/4 */
+	LONG_L	t2, (cpu_data + CPUINFO_ASID_MASK)(t2)
+	and	k0, k0, t2
+#else
+	andi	k0, k0, MIPS_ENTRYHI_ASID
+#endif
 	mtc0	k0, CP0_ENTRYHI
 	ehb
 
 	/* Disable RDHWR access */
 	mtc0	zero, CP0_HWRENA
 
+	.set	noat
 	/* load the guest context from VCPU and return */
 	LONG_L	$0, VCPU_R0(k1)
 	LONG_L	$1, VCPU_R1(k1)
@@ -541,6 +517,7 @@ FEXPORT(__kvm_mips_skip_guest_restore)
 	LONG_L	k1, VCPU_R27(k1)
 
 	eret
+	.set	at
 
 __kvm_mips_return_to_host:
 	/* EBASE is already pointing to Linux */
@@ -551,16 +528,6 @@ __kvm_mips_return_to_host:
 	LONG_L	k0, PT_HOST_USERLOCAL(k1)
 	mtc0	k0, CP0_DDATA_LO
 
-	/* Restore host ASID */
-	LONG_L	k0, PT_HOST_ASID(sp)
-	andi	k0, 0xff
-	mtc0	k0,CP0_ENTRYHI
-	ehb
-
-	/* Load context saved on the host stack */
-	LONG_L	$0, PT_R0(k1)
-	LONG_L	$1, PT_R1(k1)
-
 	/*
 	 * r2/v0 is the return code, shift it down by 2 (arithmetic)
 	 * to recover the err code
@@ -568,19 +535,7 @@ __kvm_mips_return_to_host:
 	INT_SRA	k0, v0, 2
 	move	$2, k0
 
-	LONG_L	$3, PT_R3(k1)
-	LONG_L	$4, PT_R4(k1)
-	LONG_L	$5, PT_R5(k1)
-	LONG_L	$6, PT_R6(k1)
-	LONG_L	$7, PT_R7(k1)
-	LONG_L	$8, PT_R8(k1)
-	LONG_L	$9, PT_R9(k1)
-	LONG_L	$10, PT_R10(k1)
-	LONG_L	$11, PT_R11(k1)
-	LONG_L	$12, PT_R12(k1)
-	LONG_L	$13, PT_R13(k1)
-	LONG_L	$14, PT_R14(k1)
-	LONG_L	$15, PT_R15(k1)
+	/* Load context saved on the host stack */
 	LONG_L	$16, PT_R16(k1)
 	LONG_L	$17, PT_R17(k1)
 	LONG_L	$18, PT_R18(k1)
@@ -589,10 +544,6 @@ __kvm_mips_return_to_host:
 	LONG_L	$21, PT_R21(k1)
 	LONG_L	$22, PT_R22(k1)
 	LONG_L	$23, PT_R23(k1)
-	LONG_L	$24, PT_R24(k1)
-	LONG_L	$25, PT_R25(k1)
-
-	/* Host k0/k1 were not saved */
 
 	LONG_L	$28, PT_R28(k1)
 	LONG_L	$29, PT_R29(k1)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kvm/mips.c linux-libre-4.7-gnu/arch/mips/kvm/mips.c
--- linux-libre-4.6-gnu/arch/mips/kvm/mips.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kvm/mips.c	2016-07-24 15:23:50.000000000 -0400
@@ -56,6 +56,7 @@ struct kvm_stats_debugfs_item debugfs_en
 	{ "flush_dcache", VCPU_STAT(flush_dcache_exits), KVM_STAT_VCPU },
 	{ "halt_successful_poll", VCPU_STAT(halt_successful_poll), KVM_STAT_VCPU },
 	{ "halt_attempted_poll", VCPU_STAT(halt_attempted_poll), KVM_STAT_VCPU },
+	{ "halt_poll_invalid", VCPU_STAT(halt_poll_invalid), KVM_STAT_VCPU },
 	{ "halt_wakeup",  VCPU_STAT(halt_wakeup),	 KVM_STAT_VCPU },
 	{NULL}
 };
@@ -314,6 +315,15 @@ struct kvm_vcpu *kvm_arch_vcpu_create(st
 	memcpy(gebase + offset, mips32_GuestException,
 	       mips32_GuestExceptionEnd - mips32_GuestException);
 
+#ifdef MODULE
+	offset += mips32_GuestExceptionEnd - mips32_GuestException;
+	memcpy(gebase + offset, (char *)__kvm_mips_vcpu_run,
+	       __kvm_mips_vcpu_run_end - (char *)__kvm_mips_vcpu_run);
+	vcpu->arch.vcpu_run = gebase + offset;
+#else
+	vcpu->arch.vcpu_run = __kvm_mips_vcpu_run;
+#endif
+
 	/* Invalidate the icache for these ranges */
 	local_flush_icache_range((unsigned long)gebase,
 				(unsigned long)gebase + ALIGN(size, PAGE_SIZE));
@@ -403,7 +413,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_v
 	/* Disable hardware page table walking while in guest */
 	htw_stop();
 
-	r = __kvm_mips_vcpu_run(run, vcpu);
+	r = vcpu->arch.vcpu_run(run, vcpu);
 
 	/* Re-enable HTW before enabling interrupts */
 	htw_start();
@@ -1079,7 +1089,8 @@ int kvm_vm_ioctl_check_extension(struct
 		r = KVM_COALESCED_MMIO_PAGE_OFFSET;
 		break;
 	case KVM_CAP_MIPS_FPU:
-		r = !!cpu_has_fpu;
+		/* We don't handle systems with inconsistent cpu_has_fpu */
+		r = !!raw_cpu_has_fpu;
 		break;
 	case KVM_CAP_MIPS_MSA:
 		/*
@@ -1555,8 +1566,10 @@ void kvm_lose_fpu(struct kvm_vcpu *vcpu)
 
 		/* Disable MSA & FPU */
 		disable_msa();
-		if (vcpu->arch.fpu_inuse & KVM_MIPS_FPU_FPU)
+		if (vcpu->arch.fpu_inuse & KVM_MIPS_FPU_FPU) {
 			clear_c0_status(ST0_CU1 | ST0_FR);
+			disable_fpu_hazard();
+		}
 		vcpu->arch.fpu_inuse &= ~(KVM_MIPS_FPU_FPU | KVM_MIPS_FPU_MSA);
 	} else if (vcpu->arch.fpu_inuse & KVM_MIPS_FPU_FPU) {
 		set_c0_status(ST0_CU1);
@@ -1567,6 +1580,7 @@ void kvm_lose_fpu(struct kvm_vcpu *vcpu)
 
 		/* Disable FPU */
 		clear_c0_status(ST0_CU1 | ST0_FR);
+		disable_fpu_hazard();
 	}
 	preempt_enable();
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kvm/tlb.c linux-libre-4.7-gnu/arch/mips/kvm/tlb.c
--- linux-libre-4.6-gnu/arch/mips/kvm/tlb.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kvm/tlb.c	2016-07-24 15:23:50.000000000 -0400
@@ -49,12 +49,18 @@ EXPORT_SYMBOL_GPL(kvm_mips_is_error_pfn)
 
 uint32_t kvm_mips_get_kernel_asid(struct kvm_vcpu *vcpu)
 {
-	return vcpu->arch.guest_kernel_asid[smp_processor_id()] & ASID_MASK;
+	int cpu = smp_processor_id();
+
+	return vcpu->arch.guest_kernel_asid[cpu] &
+			cpu_asid_mask(&cpu_data[cpu]);
 }
 
 uint32_t kvm_mips_get_user_asid(struct kvm_vcpu *vcpu)
 {
-	return vcpu->arch.guest_user_asid[smp_processor_id()] & ASID_MASK;
+	int cpu = smp_processor_id();
+
+	return vcpu->arch.guest_user_asid[cpu] &
+			cpu_asid_mask(&cpu_data[cpu]);
 }
 
 inline uint32_t kvm_mips_get_commpage_asid(struct kvm_vcpu *vcpu)
@@ -78,7 +84,8 @@ void kvm_mips_dump_host_tlbs(void)
 	old_pagemask = read_c0_pagemask();
 
 	kvm_info("HOST TLBs:\n");
-	kvm_info("ASID: %#lx\n", read_c0_entryhi() & ASID_MASK);
+	kvm_info("ASID: %#lx\n", read_c0_entryhi() &
+		 cpu_asid_mask(&current_cpu_data));
 
 	for (i = 0; i < current_cpu_data.tlbsize; i++) {
 		write_c0_index(i);
@@ -268,6 +275,7 @@ int kvm_mips_handle_kseg0_tlb_fault(unsi
 	int even;
 	struct kvm *kvm = vcpu->kvm;
 	const int flush_dcache_mask = 0;
+	int ret;
 
 	if (KVM_GUEST_KSEGX(badvaddr) != KVM_GUEST_KSEG0) {
 		kvm_err("%s: Invalid BadVaddr: %#lx\n", __func__, badvaddr);
@@ -299,14 +307,18 @@ int kvm_mips_handle_kseg0_tlb_fault(unsi
 		pfn1 = kvm->arch.guest_pmap[gfn];
 	}
 
-	entryhi = (vaddr | kvm_mips_get_kernel_asid(vcpu));
 	entrylo0 = mips3_paddr_to_tlbpfn(pfn0 << PAGE_SHIFT) | (0x3 << 3) |
 		   (1 << 2) | (0x1 << 1);
 	entrylo1 = mips3_paddr_to_tlbpfn(pfn1 << PAGE_SHIFT) | (0x3 << 3) |
 		   (1 << 2) | (0x1 << 1);
 
-	return kvm_mips_host_tlb_write(vcpu, entryhi, entrylo0, entrylo1,
-				       flush_dcache_mask);
+	preempt_disable();
+	entryhi = (vaddr | kvm_mips_get_kernel_asid(vcpu));
+	ret = kvm_mips_host_tlb_write(vcpu, entryhi, entrylo0, entrylo1,
+				      flush_dcache_mask);
+	preempt_enable();
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(kvm_mips_handle_kseg0_tlb_fault);
 
@@ -361,6 +373,7 @@ int kvm_mips_handle_mapped_seg_tlb_fault
 	unsigned long entryhi = 0, entrylo0 = 0, entrylo1 = 0;
 	struct kvm *kvm = vcpu->kvm;
 	kvm_pfn_t pfn0, pfn1;
+	int ret;
 
 	if ((tlb->tlb_hi & VPN2_MASK) == 0) {
 		pfn0 = 0;
@@ -387,9 +400,6 @@ int kvm_mips_handle_mapped_seg_tlb_fault
 		*hpa1 = pfn1 << PAGE_SHIFT;
 
 	/* Get attributes from the Guest TLB */
-	entryhi = (tlb->tlb_hi & VPN2_MASK) | (KVM_GUEST_KERNEL_MODE(vcpu) ?
-					       kvm_mips_get_kernel_asid(vcpu) :
-					       kvm_mips_get_user_asid(vcpu));
 	entrylo0 = mips3_paddr_to_tlbpfn(pfn0 << PAGE_SHIFT) | (0x3 << 3) |
 		   (tlb->tlb_lo0 & MIPS3_PG_D) | (tlb->tlb_lo0 & MIPS3_PG_V);
 	entrylo1 = mips3_paddr_to_tlbpfn(pfn1 << PAGE_SHIFT) | (0x3 << 3) |
@@ -398,8 +408,15 @@ int kvm_mips_handle_mapped_seg_tlb_fault
 	kvm_debug("@ %#lx tlb_lo0: 0x%08lx tlb_lo1: 0x%08lx\n", vcpu->arch.pc,
 		  tlb->tlb_lo0, tlb->tlb_lo1);
 
-	return kvm_mips_host_tlb_write(vcpu, entryhi, entrylo0, entrylo1,
-				       tlb->tlb_mask);
+	preempt_disable();
+	entryhi = (tlb->tlb_hi & VPN2_MASK) | (KVM_GUEST_KERNEL_MODE(vcpu) ?
+					       kvm_mips_get_kernel_asid(vcpu) :
+					       kvm_mips_get_user_asid(vcpu));
+	ret = kvm_mips_host_tlb_write(vcpu, entryhi, entrylo0, entrylo1,
+				      tlb->tlb_mask);
+	preempt_enable();
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(kvm_mips_handle_mapped_seg_tlb_fault);
 
@@ -564,15 +581,15 @@ void kvm_get_new_mmu_context(struct mm_s
 {
 	unsigned long asid = asid_cache(cpu);
 
-	asid += ASID_INC;
-	if (!(asid & ASID_MASK)) {
+	asid += cpu_asid_inc();
+	if (!(asid & cpu_asid_mask(&cpu_data[cpu]))) {
 		if (cpu_has_vtag_icache)
 			flush_icache_all();
 
 		kvm_local_flush_tlb_all();      /* start new asid cycle */
 
 		if (!asid)      /* fix version if needed */
-			asid = ASID_FIRST_VERSION;
+			asid = asid_first_version(cpu);
 	}
 
 	cpu_context(cpu, mm) = asid_cache(cpu) = asid;
@@ -627,6 +644,7 @@ static void kvm_mips_migrate_count(struc
 /* Restore ASID once we are scheduled back after preemption */
 void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 {
+	unsigned long asid_mask = cpu_asid_mask(&cpu_data[cpu]);
 	unsigned long flags;
 	int newasid = 0;
 
@@ -637,7 +655,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu
 	local_irq_save(flags);
 
 	if ((vcpu->arch.guest_kernel_asid[cpu] ^ asid_cache(cpu)) &
-							ASID_VERSION_MASK) {
+						asid_version_mask(cpu)) {
 		kvm_get_new_mmu_context(&vcpu->arch.guest_kernel_mm, cpu, vcpu);
 		vcpu->arch.guest_kernel_asid[cpu] =
 		    vcpu->arch.guest_kernel_mm.context.asid[cpu];
@@ -672,7 +690,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu
 		 */
 		if (current->flags & PF_VCPU) {
 			write_c0_entryhi(vcpu->arch.
-					 preempt_entryhi & ASID_MASK);
+					 preempt_entryhi & asid_mask);
 			ehb();
 		}
 	} else {
@@ -687,11 +705,11 @@ void kvm_arch_vcpu_load(struct kvm_vcpu
 			if (KVM_GUEST_KERNEL_MODE(vcpu))
 				write_c0_entryhi(vcpu->arch.
 						 guest_kernel_asid[cpu] &
-						 ASID_MASK);
+						 asid_mask);
 			else
 				write_c0_entryhi(vcpu->arch.
 						 guest_user_asid[cpu] &
-						 ASID_MASK);
+						 asid_mask);
 			ehb();
 		}
 	}
@@ -721,7 +739,7 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *
 	kvm_mips_callbacks->vcpu_get_regs(vcpu);
 
 	if (((cpu_context(cpu, current->mm) ^ asid_cache(cpu)) &
-	     ASID_VERSION_MASK)) {
+	     asid_version_mask(cpu))) {
 		kvm_debug("%s: Dropping MMU Context:  %#lx\n", __func__,
 			  cpu_context(cpu, current->mm));
 		drop_mmu_context(current->mm, cpu);
@@ -748,7 +766,8 @@ uint32_t kvm_get_inst(uint32_t *opc, str
 			inst = *(opc);
 		} else {
 			vpn2 = (unsigned long) opc & VPN2_MASK;
-			asid = kvm_read_c0_guest_entryhi(cop0) & ASID_MASK;
+			asid = kvm_read_c0_guest_entryhi(cop0) &
+						KVM_ENTRYHI_ASID;
 			index = kvm_mips_guest_tlb_lookup(vcpu, vpn2 | asid);
 			if (index < 0) {
 				kvm_err("%s: get_user_failed for %p, vcpu: %p, ASID: %#lx\n",
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/kvm/trap_emul.c linux-libre-4.7-gnu/arch/mips/kvm/trap_emul.c
--- linux-libre-4.6-gnu/arch/mips/kvm/trap_emul.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/kvm/trap_emul.c	2016-07-24 15:23:50.000000000 -0400
@@ -505,7 +505,8 @@ static int kvm_trap_emul_vcpu_setup(stru
 	kvm_write_c0_guest_intctl(cop0, 0xFC000000);
 
 	/* Put in vcpu id as CPUNum into Ebase Reg to handle SMP Guests */
-	kvm_write_c0_guest_ebase(cop0, KVM_GUEST_KSEG0 | (vcpu_id & 0xFF));
+	kvm_write_c0_guest_ebase(cop0, KVM_GUEST_KSEG0 |
+				       (vcpu_id & MIPS_EBASE_CPUNUM));
 
 	return 0;
 }
@@ -546,7 +547,7 @@ static int kvm_trap_emul_set_one_reg(str
 		kvm_mips_write_count(vcpu, v);
 		break;
 	case KVM_REG_MIPS_CP0_COMPARE:
-		kvm_mips_write_compare(vcpu, v);
+		kvm_mips_write_compare(vcpu, v, false);
 		break;
 	case KVM_REG_MIPS_CP0_CAUSE:
 		/*
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/lantiq/clk.c linux-libre-4.7-gnu/arch/mips/lantiq/clk.c
--- linux-libre-4.6-gnu/arch/mips/lantiq/clk.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/lantiq/clk.c	2016-07-24 15:23:50.000000000 -0400
@@ -4,7 +4,7 @@
  *  by the Free Software Foundation.
  *
  * Copyright (C) 2010 Thomas Langer <thomas.langer@lantiq.com>
- * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2010 John Crispin <john@phrozen.org>
  */
 #include <linux/io.h>
 #include <linux/export.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/lantiq/clk.h linux-libre-4.7-gnu/arch/mips/lantiq/clk.h
--- linux-libre-4.6-gnu/arch/mips/lantiq/clk.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/lantiq/clk.h	2016-07-24 15:23:50.000000000 -0400
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2010 John Crispin <john@phrozen.org>
  */
 
 #ifndef _LTQ_CLK_H__
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/lantiq/early_printk.c linux-libre-4.7-gnu/arch/mips/lantiq/early_printk.c
--- linux-libre-4.6-gnu/arch/mips/lantiq/early_printk.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/lantiq/early_printk.c	2016-07-24 15:23:50.000000000 -0400
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2010 John Crispin <john@phrozen.org>
  */
 
 #include <linux/cpu.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/lantiq/falcon/prom.c linux-libre-4.7-gnu/arch/mips/lantiq/falcon/prom.c
--- linux-libre-4.6-gnu/arch/mips/lantiq/falcon/prom.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/lantiq/falcon/prom.c	2016-07-24 15:23:50.000000000 -0400
@@ -4,7 +4,7 @@
  * by the Free Software Foundation.
  *
  * Copyright (C) 2012 Thomas Langer <thomas.langer@lantiq.com>
- * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2012 John Crispin <john@phrozen.org>
  */
 
 #include <linux/kernel.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/lantiq/falcon/reset.c linux-libre-4.7-gnu/arch/mips/lantiq/falcon/reset.c
--- linux-libre-4.6-gnu/arch/mips/lantiq/falcon/reset.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/lantiq/falcon/reset.c	2016-07-24 15:23:50.000000000 -0400
@@ -4,7 +4,7 @@
  * by the Free Software Foundation.
  *
  * Copyright (C) 2012 Thomas Langer <thomas.langer@lantiq.com>
- * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2012 John Crispin <john@phrozen.org>
  */
 
 #include <linux/init.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/lantiq/falcon/sysctrl.c linux-libre-4.7-gnu/arch/mips/lantiq/falcon/sysctrl.c
--- linux-libre-4.6-gnu/arch/mips/lantiq/falcon/sysctrl.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/lantiq/falcon/sysctrl.c	2016-07-24 15:23:50.000000000 -0400
@@ -4,7 +4,7 @@
  * by the Free Software Foundation.
  *
  * Copyright (C) 2011 Thomas Langer <thomas.langer@lantiq.com>
- * Copyright (C) 2011 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2011 John Crispin <john@phrozen.org>
  */
 
 #include <linux/ioport.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/lantiq/irq.c linux-libre-4.7-gnu/arch/mips/lantiq/irq.c
--- linux-libre-4.6-gnu/arch/mips/lantiq/irq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/lantiq/irq.c	2016-07-24 15:23:50.000000000 -0400
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2010 John Crispin <john@phrozen.org>
  * Copyright (C) 2010 Thomas Langer <thomas.langer@lantiq.com>
  */
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/lantiq/Kconfig linux-libre-4.7-gnu/arch/mips/lantiq/Kconfig
--- linux-libre-4.6-gnu/arch/mips/lantiq/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/lantiq/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -25,7 +25,17 @@ config SOC_FALCON
 endchoice
 
 choice
-	prompt "Devicetree"
+	prompt "Built-in device tree"
+	help
+	  Legacy bootloaders do not pass a DTB pointer to the kernel, so
+	  if a "wrapper" is not being used, the kernel will need to include
+	  a device tree that matches the target board.
+
+	  The builtin DTB will only be used if the firmware does not supply
+	  a valid DTB.
+
+config LANTIQ_DT_NONE
+	bool "None"
 
 config DT_EASY50712
 	bool "Easy50712"
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/lantiq/Makefile linux-libre-4.7-gnu/arch/mips/lantiq/Makefile
--- linux-libre-4.6-gnu/arch/mips/lantiq/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/lantiq/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -1,4 +1,4 @@
-# Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+# Copyright (C) 2010 John Crispin <john@phrozen.org>
 #
 # This program is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License version 2 as published
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/lantiq/prom.c linux-libre-4.7-gnu/arch/mips/lantiq/prom.c
--- linux-libre-4.6-gnu/arch/mips/lantiq/prom.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/lantiq/prom.c	2016-07-24 15:23:50.000000000 -0400
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2010 John Crispin <john@phrozen.org>
  */
 
 #include <linux/export.h>
@@ -65,6 +65,8 @@ static void __init prom_init_cmdline(voi
 
 void __init plat_mem_setup(void)
 {
+	void *dtb;
+
 	ioport_resource.start = IOPORT_RESOURCE_START;
 	ioport_resource.end = IOPORT_RESOURCE_END;
 	iomem_resource.start = IOMEM_RESOURCE_START;
@@ -72,11 +74,18 @@ void __init plat_mem_setup(void)
 
 	set_io_port_base((unsigned long) KSEG1);
 
+	if (fw_arg0 == -2) /* UHI interface */
+		dtb = (void *)fw_arg1;
+	else if (__dtb_start != __dtb_end)
+		dtb = (void *)__dtb_start;
+	else
+		panic("no dtb found");
+
 	/*
-	 * Load the builtin devicetree. This causes the chosen node to be
+	 * Load the devicetree. This causes the chosen node to be
 	 * parsed resulting in our memory appearing
 	 */
-	__dt_setup_arch(__dtb_start);
+	__dt_setup_arch(dtb);
 }
 
 void __init device_tree_init(void)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/lantiq/prom.h linux-libre-4.7-gnu/arch/mips/lantiq/prom.h
--- linux-libre-4.6-gnu/arch/mips/lantiq/prom.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/lantiq/prom.h	2016-07-24 15:23:50.000000000 -0400
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2010 John Crispin <john@phrozen.org>
  */
 
 #ifndef _LTQ_PROM_H__
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/lantiq/xway/clk.c linux-libre-4.7-gnu/arch/mips/lantiq/xway/clk.c
--- linux-libre-4.6-gnu/arch/mips/lantiq/xway/clk.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/lantiq/xway/clk.c	2016-07-24 15:23:50.000000000 -0400
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2010 John Crispin <john@phrozen.org>
  *  Copyright (C) 2013-2015 Lantiq Beteiligungs-GmbH & Co.KG
  */
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/lantiq/xway/dcdc.c linux-libre-4.7-gnu/arch/mips/lantiq/xway/dcdc.c
--- linux-libre-4.6-gnu/arch/mips/lantiq/xway/dcdc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/lantiq/xway/dcdc.c	2016-07-24 15:23:50.000000000 -0400
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- *  Copyright (C) 2012 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2012 John Crispin <john@phrozen.org>
  *  Copyright (C) 2010 Sameer Ahmad, Lantiq GmbH
  */
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/lantiq/xway/dma.c linux-libre-4.7-gnu/arch/mips/lantiq/xway/dma.c
--- linux-libre-4.6-gnu/arch/mips/lantiq/xway/dma.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/lantiq/xway/dma.c	2016-07-24 15:23:50.000000000 -0400
@@ -12,7 +12,7 @@
  *   along with this program; if not, write to the Free Software
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  *
- *   Copyright (C) 2011 John Crispin <blogic@openwrt.org>
+ *   Copyright (C) 2011 John Crispin <john@phrozen.org>
  */
 
 #include <linux/init.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/lantiq/xway/gptu.c linux-libre-4.7-gnu/arch/mips/lantiq/xway/gptu.c
--- linux-libre-4.6-gnu/arch/mips/lantiq/xway/gptu.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/lantiq/xway/gptu.c	2016-07-24 15:23:50.000000000 -0400
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- *  Copyright (C) 2012 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2012 John Crispin <john@phrozen.org>
  *  Copyright (C) 2012 Lantiq GmbH
  */
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/lantiq/xway/prom.c linux-libre-4.7-gnu/arch/mips/lantiq/xway/prom.c
--- linux-libre-4.6-gnu/arch/mips/lantiq/xway/prom.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/lantiq/xway/prom.c	2016-07-24 15:23:50.000000000 -0400
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2010 John Crispin <john@phrozen.org>
  *  Copyright (C) 2013-2015 Lantiq Beteiligungs-GmbH & Co.KG
  */
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/lantiq/xway/reset.c linux-libre-4.7-gnu/arch/mips/lantiq/xway/reset.c
--- linux-libre-4.6-gnu/arch/mips/lantiq/xway/reset.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/lantiq/xway/reset.c	2016-07-24 15:23:50.000000000 -0400
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2010 John Crispin <john@phrozen.org>
  *  Copyright (C) 2013-2015 Lantiq Beteiligungs-GmbH & Co.KG
  */
 
@@ -258,7 +258,7 @@ static int ltq_reset_device(struct reset
 	return ltq_deassert_device(rcdev, id);
 }
 
-static struct reset_control_ops reset_ops = {
+static const struct reset_control_ops reset_ops = {
 	.reset = ltq_reset_device,
 	.assert = ltq_assert_device,
 	.deassert = ltq_deassert_device,
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/lantiq/xway/sysctrl.c linux-libre-4.7-gnu/arch/mips/lantiq/xway/sysctrl.c
--- linux-libre-4.6-gnu/arch/mips/lantiq/xway/sysctrl.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/lantiq/xway/sysctrl.c	2016-07-24 15:23:50.000000000 -0400
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- *  Copyright (C) 2011-2012 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2011-2012 John Crispin <john@phrozen.org>
  *  Copyright (C) 2013-2015 Lantiq Beteiligungs-GmbH & Co.KG
  */
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/lantiq/xway/vmmc.c linux-libre-4.7-gnu/arch/mips/lantiq/xway/vmmc.c
--- linux-libre-4.6-gnu/arch/mips/lantiq/xway/vmmc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/lantiq/xway/vmmc.c	2016-07-24 15:23:50.000000000 -0400
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- *  Copyright (C) 2012 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2012 John Crispin <john@phrozen.org>
  */
 
 #include <linux/module.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/lantiq/xway/xrx200_phy_fw.c linux-libre-4.7-gnu/arch/mips/lantiq/xway/xrx200_phy_fw.c
--- linux-libre-4.6-gnu/arch/mips/lantiq/xway/xrx200_phy_fw.c	2016-05-15 19:18:01.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/lantiq/xway/xrx200_phy_fw.c	2016-07-24 18:15:17.000000000 -0400
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- *  Copyright (C) 2012 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2012 John Crispin <john@phrozen.org>
  */
 
 #include <linux/delay.h>
@@ -112,6 +112,6 @@ static struct platform_driver xway_phy_d
 
 module_platform_driver(xway_phy_driver);
 
-MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
+MODULE_AUTHOR("John Crispin <john@phrozen.org>");
 MODULE_DESCRIPTION("Lantiq XRX200 PHY Firmware Loader");
 MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/lasat/picvue_proc.c linux-libre-4.7-gnu/arch/mips/lasat/picvue_proc.c
--- linux-libre-4.6-gnu/arch/mips/lasat/picvue_proc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/lasat/picvue_proc.c	2016-07-24 15:23:50.000000000 -0400
@@ -43,7 +43,7 @@ static int pvc_line_proc_show(struct seq
 {
 	int lineno = *(int *)m->private;
 
-	if (lineno < 0 || lineno > PVC_NLINES) {
+	if (lineno < 0 || lineno >= PVC_NLINES) {
 		printk(KERN_WARNING "proc_read_line: invalid lineno %d\n", lineno);
 		return 0;
 	}
@@ -67,7 +67,7 @@ static ssize_t pvc_line_proc_write(struc
 	char kbuf[PVC_LINELEN];
 	size_t len;
 
-	BUG_ON(lineno < 0 || lineno > PVC_NLINES);
+	BUG_ON(lineno < 0 || lineno >= PVC_NLINES);
 
 	len = min(count, sizeof(kbuf) - 1);
 	if (copy_from_user(kbuf, buf, len))
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/lib/ashldi3.c linux-libre-4.7-gnu/arch/mips/lib/ashldi3.c
--- linux-libre-4.6-gnu/arch/mips/lib/ashldi3.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/lib/ashldi3.c	2016-07-24 15:23:50.000000000 -0400
@@ -2,7 +2,7 @@
 
 #include "libgcc.h"
 
-long long __ashldi3(long long u, word_type b)
+long long notrace __ashldi3(long long u, word_type b)
 {
 	DWunion uu, w;
 	word_type bm;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/lib/ashrdi3.c linux-libre-4.7-gnu/arch/mips/lib/ashrdi3.c
--- linux-libre-4.6-gnu/arch/mips/lib/ashrdi3.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/lib/ashrdi3.c	2016-07-24 15:23:50.000000000 -0400
@@ -2,7 +2,7 @@
 
 #include "libgcc.h"
 
-long long __ashrdi3(long long u, word_type b)
+long long notrace __ashrdi3(long long u, word_type b)
 {
 	DWunion uu, w;
 	word_type bm;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/lib/bswapdi.c linux-libre-4.7-gnu/arch/mips/lib/bswapdi.c
--- linux-libre-4.6-gnu/arch/mips/lib/bswapdi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/lib/bswapdi.c	2016-07-24 15:23:50.000000000 -0400
@@ -1,6 +1,6 @@
 #include <linux/module.h>
 
-unsigned long long __bswapdi2(unsigned long long u)
+unsigned long long notrace __bswapdi2(unsigned long long u)
 {
 	return (((u) & 0xff00000000000000ull) >> 56) |
 	       (((u) & 0x00ff000000000000ull) >> 40) |
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/lib/bswapsi.c linux-libre-4.7-gnu/arch/mips/lib/bswapsi.c
--- linux-libre-4.6-gnu/arch/mips/lib/bswapsi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/lib/bswapsi.c	2016-07-24 15:23:50.000000000 -0400
@@ -1,6 +1,6 @@
 #include <linux/module.h>
 
-unsigned int __bswapsi2(unsigned int u)
+unsigned int notrace __bswapsi2(unsigned int u)
 {
 	return (((u) & 0xff000000) >> 24) |
 	       (((u) & 0x00ff0000) >>  8) |
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/lib/cmpdi2.c linux-libre-4.7-gnu/arch/mips/lib/cmpdi2.c
--- linux-libre-4.6-gnu/arch/mips/lib/cmpdi2.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/lib/cmpdi2.c	2016-07-24 15:23:50.000000000 -0400
@@ -2,7 +2,7 @@
 
 #include "libgcc.h"
 
-word_type __cmpdi2(long long a, long long b)
+word_type notrace __cmpdi2(long long a, long long b)
 {
 	const DWunion au = {
 		.ll = a
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/lib/dump_tlb.c linux-libre-4.7-gnu/arch/mips/lib/dump_tlb.c
--- linux-libre-4.6-gnu/arch/mips/lib/dump_tlb.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/lib/dump_tlb.c	2016-07-24 15:23:50.000000000 -0400
@@ -19,6 +19,8 @@ void dump_tlb_regs(void)
 
 	pr_info("Index    : %0x\n", read_c0_index());
 	pr_info("PageMask : %0x\n", read_c0_pagemask());
+	if (cpu_has_guestid)
+		pr_info("GuestCtl1: %0x\n", read_c0_guestctl1());
 	pr_info("EntryHi  : %0*lx\n", field, read_c0_entryhi());
 	pr_info("EntryLo0 : %0*lx\n", field, read_c0_entrylo0());
 	pr_info("EntryLo1 : %0*lx\n", field, read_c0_entrylo1());
@@ -72,7 +74,10 @@ static void dump_tlb(int first, int last
 {
 	unsigned long s_entryhi, entryhi, asid;
 	unsigned long long entrylo0, entrylo1, pa;
-	unsigned int s_index, s_pagemask, pagemask, c0, c1, i;
+	unsigned int s_index, s_pagemask, s_guestctl1 = 0;
+	unsigned int pagemask, guestctl1 = 0, c0, c1, i;
+	unsigned long asidmask = cpu_asid_mask(&current_cpu_data);
+	int asidwidth = DIV_ROUND_UP(ilog2(asidmask) + 1, 4);
 #ifdef CONFIG_32BIT
 	bool xpa = cpu_has_xpa && (read_c0_pagegrain() & PG_ELPA);
 	int pwidth = xpa ? 11 : 8;
@@ -86,7 +91,9 @@ static void dump_tlb(int first, int last
 	s_pagemask = read_c0_pagemask();
 	s_entryhi = read_c0_entryhi();
 	s_index = read_c0_index();
-	asid = s_entryhi & 0xff;
+	asid = s_entryhi & asidmask;
+	if (cpu_has_guestid)
+		s_guestctl1 = read_c0_guestctl1();
 
 	for (i = first; i <= last; i++) {
 		write_c0_index(i);
@@ -97,6 +104,8 @@ static void dump_tlb(int first, int last
 		entryhi	 = read_c0_entryhi();
 		entrylo0 = read_c0_entrylo0();
 		entrylo1 = read_c0_entrylo1();
+		if (cpu_has_guestid)
+			guestctl1 = read_c0_guestctl1();
 
 		/* EHINV bit marks entire entry as invalid */
 		if (cpu_has_tlbinv && entryhi & MIPS_ENTRYHI_EHINV)
@@ -115,7 +124,7 @@ static void dump_tlb(int first, int last
 		 * due to duplicate TLB entry.
 		 */
 		if (!((entrylo0 | entrylo1) & ENTRYLO_G) &&
-		    (entryhi & 0xff) != asid)
+		    (entryhi & asidmask) != asid)
 			continue;
 
 		/*
@@ -126,15 +135,19 @@ static void dump_tlb(int first, int last
 		c0 = (entrylo0 & ENTRYLO_C) >> ENTRYLO_C_SHIFT;
 		c1 = (entrylo1 & ENTRYLO_C) >> ENTRYLO_C_SHIFT;
 
-		printk("va=%0*lx asid=%02lx\n",
+		printk("va=%0*lx asid=%0*lx",
 		       vwidth, (entryhi & ~0x1fffUL),
-		       entryhi & 0xff);
+		       asidwidth, entryhi & asidmask);
+		if (cpu_has_guestid)
+			printk(" gid=%02lx",
+			       (guestctl1 & MIPS_GCTL1_RID)
+					>> MIPS_GCTL1_RID_SHIFT);
 		/* RI/XI are in awkward places, so mask them off separately */
 		pa = entrylo0 & ~(MIPS_ENTRYLO_RI | MIPS_ENTRYLO_XI);
 		if (xpa)
 			pa |= (unsigned long long)readx_c0_entrylo0() << 30;
 		pa = (pa << 6) & PAGE_MASK;
-		printk("\t[");
+		printk("\n\t[");
 		if (cpu_has_rixi)
 			printk("ri=%d xi=%d ",
 			       (entrylo0 & MIPS_ENTRYLO_RI) ? 1 : 0,
@@ -164,6 +177,8 @@ static void dump_tlb(int first, int last
 	write_c0_entryhi(s_entryhi);
 	write_c0_index(s_index);
 	write_c0_pagemask(s_pagemask);
+	if (cpu_has_guestid)
+		write_c0_guestctl1(s_guestctl1);
 }
 
 void dump_tlb_all(void)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/lib/lshrdi3.c linux-libre-4.7-gnu/arch/mips/lib/lshrdi3.c
--- linux-libre-4.6-gnu/arch/mips/lib/lshrdi3.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/lib/lshrdi3.c	2016-07-24 15:23:50.000000000 -0400
@@ -2,7 +2,7 @@
 
 #include "libgcc.h"
 
-long long __lshrdi3(long long u, word_type b)
+long long notrace __lshrdi3(long long u, word_type b)
 {
 	DWunion uu, w;
 	word_type bm;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/lib/memcpy.S linux-libre-4.7-gnu/arch/mips/lib/memcpy.S
--- linux-libre-4.6-gnu/arch/mips/lib/memcpy.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/lib/memcpy.S	2016-07-24 15:23:50.000000000 -0400
@@ -256,7 +256,7 @@
 
 	/*
 	 * Macro to build the __copy_user common code
-	 * Arguements:
+	 * Arguments:
 	 * mode : LEGACY_MODE or EVA_MODE
 	 * from : Source operand. USEROP or KERNELOP
 	 * to   : Destination operand. USEROP or KERNELOP
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/lib/memset.S linux-libre-4.7-gnu/arch/mips/lib/memset.S
--- linux-libre-4.6-gnu/arch/mips/lib/memset.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/lib/memset.S	2016-07-24 15:23:50.000000000 -0400
@@ -228,10 +228,12 @@
 	.hidden __memset
 	.endif
 
+#ifdef CONFIG_CPU_MIPSR6
 .Lbyte_fixup\@:
 	PTR_SUBU	a2, $0, t0
 	jr		ra
 	 PTR_ADDIU	a2, 1
+#endif /* CONFIG_CPU_MIPSR6 */
 
 .Lfirst_fixup\@:
 	jr	ra
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/lib/r3k_dump_tlb.c linux-libre-4.7-gnu/arch/mips/lib/r3k_dump_tlb.c
--- linux-libre-4.6-gnu/arch/mips/lib/r3k_dump_tlb.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/lib/r3k_dump_tlb.c	2016-07-24 15:23:50.000000000 -0400
@@ -29,9 +29,10 @@ static void dump_tlb(int first, int last
 {
 	int	i;
 	unsigned int asid;
-	unsigned long entryhi, entrylo0;
+	unsigned long entryhi, entrylo0, asid_mask;
 
-	asid = read_c0_entryhi() & ASID_MASK;
+	asid_mask = cpu_asid_mask(&current_cpu_data);
+	asid = read_c0_entryhi() & asid_mask;
 
 	for (i = first; i <= last; i++) {
 		write_c0_index(i<<8);
@@ -46,7 +47,7 @@ static void dump_tlb(int first, int last
 		/* Unused entries have a virtual address of KSEG0.  */
 		if ((entryhi & PAGE_MASK) != KSEG0 &&
 		    (entrylo0 & R3K_ENTRYLO_G ||
-		     (entryhi & ASID_MASK) == asid)) {
+		     (entryhi & asid_mask) == asid)) {
 			/*
 			 * Only print entries in use
 			 */
@@ -55,7 +56,7 @@ static void dump_tlb(int first, int last
 			printk("va=%08lx asid=%08lx"
 			       "  [pa=%06lx n=%d d=%d v=%d g=%d]",
 			       entryhi & PAGE_MASK,
-			       entryhi & ASID_MASK,
+			       entryhi & asid_mask,
 			       entrylo0 & PAGE_MASK,
 			       (entrylo0 & R3K_ENTRYLO_N) ? 1 : 0,
 			       (entrylo0 & R3K_ENTRYLO_D) ? 1 : 0,
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/lib/ucmpdi2.c linux-libre-4.7-gnu/arch/mips/lib/ucmpdi2.c
--- linux-libre-4.6-gnu/arch/mips/lib/ucmpdi2.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/lib/ucmpdi2.c	2016-07-24 15:23:50.000000000 -0400
@@ -2,7 +2,7 @@
 
 #include "libgcc.h"
 
-word_type __ucmpdi2(unsigned long long a, unsigned long long b)
+word_type notrace __ucmpdi2(unsigned long long a, unsigned long long b)
 {
 	const DWunion au = {.ll = a};
 	const DWunion bu = {.ll = b};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/loongson32/common/platform.c linux-libre-4.7-gnu/arch/mips/loongson32/common/platform.c
--- linux-libre-4.6-gnu/arch/mips/loongson32/common/platform.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/loongson32/common/platform.c	2016-07-24 15:23:50.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
+ * Copyright (c) 2011-2016 Zhang, Keguang <keguang.zhang@gmail.com>
  *
  * This program is free software; you can redistribute	it and/or modify it
  * under  the terms of	the GNU General	 Public License as published by the
@@ -10,14 +10,17 @@
 #include <linux/clk.h>
 #include <linux/dma-mapping.h>
 #include <linux/err.h>
+#include <linux/mtd/partitions.h>
+#include <linux/sizes.h>
 #include <linux/phy.h>
 #include <linux/serial_8250.h>
 #include <linux/stmmac.h>
 #include <linux/usb/ehci_pdriver.h>
-#include <asm-generic/sizes.h>
 
-#include <cpufreq.h>
 #include <loongson1.h>
+#include <cpufreq.h>
+#include <dma.h>
+#include <nand.h>
 
 /* 8250/16550 compatible UART */
 #define LS1X_UART(_id)						\
@@ -45,7 +48,7 @@ struct platform_device ls1x_uart_pdev =
 	},
 };
 
-void __init ls1x_serial_setup(struct platform_device *pdev)
+void __init ls1x_serial_set_uartclk(struct platform_device *pdev)
 {
 	struct clk *clk;
 	struct plat_serial8250_port *p;
@@ -77,6 +80,42 @@ struct platform_device ls1x_cpufreq_pdev
 	},
 };
 
+/* DMA */
+static struct resource ls1x_dma_resources[] = {
+	[0] = {
+		.start = LS1X_DMAC_BASE,
+		.end = LS1X_DMAC_BASE + SZ_4 - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = LS1X_DMA0_IRQ,
+		.end = LS1X_DMA0_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start = LS1X_DMA1_IRQ,
+		.end = LS1X_DMA1_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+	[3] = {
+		.start = LS1X_DMA2_IRQ,
+		.end = LS1X_DMA2_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device ls1x_dma_pdev = {
+	.name		= "ls1x-dma",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(ls1x_dma_resources),
+	.resource	= ls1x_dma_resources,
+};
+
+void __init ls1x_dma_set_platdata(struct plat_ls1x_dma *pdata)
+{
+	ls1x_dma_pdev.dev.platform_data = pdata;
+}
+
 /* Synopsys Ethernet GMAC */
 static struct stmmac_mdio_bus_data ls1x_mdio_bus_data = {
 	.phy_mask	= 0,
@@ -198,6 +237,64 @@ struct platform_device ls1x_eth1_pdev =
 	},
 };
 
+/* GPIO */
+static struct resource ls1x_gpio0_resources[] = {
+	[0] = {
+		.start	= LS1X_GPIO0_BASE,
+		.end	= LS1X_GPIO0_BASE + SZ_4 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+struct platform_device ls1x_gpio0_pdev = {
+	.name		= "ls1x-gpio",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(ls1x_gpio0_resources),
+	.resource	= ls1x_gpio0_resources,
+};
+
+static struct resource ls1x_gpio1_resources[] = {
+	[0] = {
+		.start	= LS1X_GPIO1_BASE,
+		.end	= LS1X_GPIO1_BASE + SZ_4 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+struct platform_device ls1x_gpio1_pdev = {
+	.name		= "ls1x-gpio",
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(ls1x_gpio1_resources),
+	.resource	= ls1x_gpio1_resources,
+};
+
+/* NAND Flash */
+static struct resource ls1x_nand_resources[] = {
+	[0] = {
+		.start	= LS1X_NAND_BASE,
+		.end	= LS1X_NAND_BASE + SZ_32 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		/* DMA channel 0 is dedicated to NAND */
+		.start	= LS1X_DMA_CHANNEL0,
+		.end	= LS1X_DMA_CHANNEL0,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+struct platform_device ls1x_nand_pdev = {
+	.name		= "ls1x-nand",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(ls1x_nand_resources),
+	.resource	= ls1x_nand_resources,
+};
+
+void __init ls1x_nand_set_platdata(struct plat_ls1x_nand *pdata)
+{
+	ls1x_nand_pdev.dev.platform_data = pdata;
+}
+
 /* USB EHCI */
 static u64 ls1x_ehci_dmamask = DMA_BIT_MASK(32);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/loongson32/common/reset.c linux-libre-4.7-gnu/arch/mips/loongson32/common/reset.c
--- linux-libre-4.6-gnu/arch/mips/loongson32/common/reset.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/loongson32/common/reset.c	2016-07-24 15:23:50.000000000 -0400
@@ -9,12 +9,13 @@
 
 #include <linux/io.h>
 #include <linux/pm.h>
+#include <linux/sizes.h>
 #include <asm/idle.h>
 #include <asm/reboot.h>
 
 #include <loongson1.h>
 
-static void __iomem *wdt_base;
+static void __iomem *wdt_reg_base;
 
 static void ls1x_halt(void)
 {
@@ -26,9 +27,9 @@ static void ls1x_halt(void)
 
 static void ls1x_restart(char *command)
 {
-	__raw_writel(0x1, wdt_base + WDT_EN);
-	__raw_writel(0x1, wdt_base + WDT_TIMER);
-	__raw_writel(0x1, wdt_base + WDT_SET);
+	__raw_writel(0x1, wdt_reg_base + WDT_EN);
+	__raw_writel(0x1, wdt_reg_base + WDT_TIMER);
+	__raw_writel(0x1, wdt_reg_base + WDT_SET);
 
 	ls1x_halt();
 }
@@ -40,8 +41,8 @@ static void ls1x_power_off(void)
 
 static int __init ls1x_reboot_setup(void)
 {
-	wdt_base = ioremap_nocache(LS1X_WDT_BASE, 0x0f);
-	if (!wdt_base)
+	wdt_reg_base = ioremap_nocache(LS1X_WDT_BASE, (SZ_4 + SZ_8));
+	if (!wdt_reg_base)
 		panic("Failed to remap watchdog registers");
 
 	_machine_restart = ls1x_restart;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/loongson32/common/time.c linux-libre-4.7-gnu/arch/mips/loongson32/common/time.c
--- linux-libre-4.6-gnu/arch/mips/loongson32/common/time.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/loongson32/common/time.c	2016-07-24 15:23:50.000000000 -0400
@@ -9,6 +9,7 @@
 
 #include <linux/clk.h>
 #include <linux/interrupt.h>
+#include <linux/sizes.h>
 #include <asm/time.h>
 
 #include <loongson1.h>
@@ -35,25 +36,25 @@
 
 DEFINE_RAW_SPINLOCK(ls1x_timer_lock);
 
-static void __iomem *timer_base;
+static void __iomem *timer_reg_base;
 static uint32_t ls1x_jiffies_per_tick;
 
 static inline void ls1x_pwmtimer_set_period(uint32_t period)
 {
-	__raw_writel(period, timer_base + PWM_HRC);
-	__raw_writel(period, timer_base + PWM_LRC);
+	__raw_writel(period, timer_reg_base + PWM_HRC);
+	__raw_writel(period, timer_reg_base + PWM_LRC);
 }
 
 static inline void ls1x_pwmtimer_restart(void)
 {
-	__raw_writel(0x0, timer_base + PWM_CNT);
-	__raw_writel(INT_EN | CNT_EN, timer_base + PWM_CTRL);
+	__raw_writel(0x0, timer_reg_base + PWM_CNT);
+	__raw_writel(INT_EN | CNT_EN, timer_reg_base + PWM_CTRL);
 }
 
 void __init ls1x_pwmtimer_init(void)
 {
-	timer_base = ioremap(LS1X_TIMER_BASE, 0xf);
-	if (!timer_base)
+	timer_reg_base = ioremap_nocache(LS1X_TIMER_BASE, SZ_16);
+	if (!timer_reg_base)
 		panic("Failed to remap timer registers");
 
 	ls1x_jiffies_per_tick = DIV_ROUND_CLOSEST(mips_hpt_frequency, HZ);
@@ -86,7 +87,7 @@ static cycle_t ls1x_clocksource_read(str
 	 */
 	jifs = jiffies;
 	/* read the count */
-	count = __raw_readl(timer_base + PWM_CNT);
+	count = __raw_readl(timer_reg_base + PWM_CNT);
 
 	/*
 	 * It's possible for count to appear to go the wrong way for this
@@ -131,7 +132,7 @@ static int ls1x_clockevent_set_state_per
 	raw_spin_lock(&ls1x_timer_lock);
 	ls1x_pwmtimer_set_period(ls1x_jiffies_per_tick);
 	ls1x_pwmtimer_restart();
-	__raw_writel(INT_EN | CNT_EN, timer_base + PWM_CTRL);
+	__raw_writel(INT_EN | CNT_EN, timer_reg_base + PWM_CTRL);
 	raw_spin_unlock(&ls1x_timer_lock);
 
 	return 0;
@@ -140,7 +141,7 @@ static int ls1x_clockevent_set_state_per
 static int ls1x_clockevent_tick_resume(struct clock_event_device *cd)
 {
 	raw_spin_lock(&ls1x_timer_lock);
-	__raw_writel(INT_EN | CNT_EN, timer_base + PWM_CTRL);
+	__raw_writel(INT_EN | CNT_EN, timer_reg_base + PWM_CTRL);
 	raw_spin_unlock(&ls1x_timer_lock);
 
 	return 0;
@@ -149,8 +150,8 @@ static int ls1x_clockevent_tick_resume(s
 static int ls1x_clockevent_set_state_shutdown(struct clock_event_device *cd)
 {
 	raw_spin_lock(&ls1x_timer_lock);
-	__raw_writel(__raw_readl(timer_base + PWM_CTRL) & ~CNT_EN,
-		     timer_base + PWM_CTRL);
+	__raw_writel(__raw_readl(timer_reg_base + PWM_CTRL) & ~CNT_EN,
+		     timer_reg_base + PWM_CTRL);
 	raw_spin_unlock(&ls1x_timer_lock);
 
 	return 0;
@@ -220,7 +221,7 @@ void __init plat_time_init(void)
 
 #ifdef CONFIG_CEVT_CSRC_LS1X
 	/* setup LS1X PWM timer */
-	clk = clk_get(NULL, "ls1x_pwmtimer");
+	clk = clk_get(NULL, "ls1x-pwmtimer");
 	if (IS_ERR(clk))
 		panic("unable to get timer clock, err=%ld", PTR_ERR(clk));
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/loongson32/ls1b/board.c linux-libre-4.7-gnu/arch/mips/loongson32/ls1b/board.c
--- linux-libre-4.6-gnu/arch/mips/loongson32/ls1b/board.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/loongson32/ls1b/board.c	2016-07-24 15:23:50.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
+ * Copyright (c) 2011-2016 Zhang, Keguang <keguang.zhang@gmail.com>
  *
  * This program is free software; you can redistribute	it and/or modify it
  * under  the terms of	the GNU General	 Public License as published by the
@@ -7,26 +7,83 @@
  * option) any later version.
  */
 
+#include <linux/leds.h>
+#include <linux/mtd/partitions.h>
+#include <linux/sizes.h>
+
+#include <loongson1.h>
+#include <dma.h>
+#include <nand.h>
 #include <platform.h>
 
+struct plat_ls1x_dma ls1x_dma_pdata = {
+	.nr_channels	= 3,
+};
+
+static struct mtd_partition ls1x_nand_parts[] = {
+	{
+		.name        = "kernel",
+		.offset      = 0,
+		.size        = SZ_16M,
+	},
+	{
+		.name        = "rootfs",
+		.offset      = MTDPART_OFS_APPEND,
+		.size        = MTDPART_SIZ_FULL,
+	},
+};
+
+struct plat_ls1x_nand ls1x_nand_pdata = {
+	.parts		= ls1x_nand_parts,
+	.nr_parts	= ARRAY_SIZE(ls1x_nand_parts),
+	.hold_cycle	= 0x2,
+	.wait_cycle	= 0xc,
+};
+
+static const struct gpio_led ls1x_gpio_leds[] __initconst = {
+	{
+		.name			= "LED9",
+		.default_trigger	= "heartbeat",
+		.gpio			= 38,
+		.active_low		= 1,
+		.default_state		= LEDS_GPIO_DEFSTATE_OFF,
+	}, {
+		.name			= "LED6",
+		.default_trigger	= "nand-disk",
+		.gpio			= 39,
+		.active_low		= 1,
+		.default_state		= LEDS_GPIO_DEFSTATE_OFF,
+	},
+};
+
+static const struct gpio_led_platform_data ls1x_led_pdata __initconst = {
+	.num_leds	= ARRAY_SIZE(ls1x_gpio_leds),
+	.leds		= ls1x_gpio_leds,
+};
+
 static struct platform_device *ls1b_platform_devices[] __initdata = {
 	&ls1x_uart_pdev,
 	&ls1x_cpufreq_pdev,
+	&ls1x_dma_pdev,
 	&ls1x_eth0_pdev,
 	&ls1x_eth1_pdev,
 	&ls1x_ehci_pdev,
+	&ls1x_gpio0_pdev,
+	&ls1x_gpio1_pdev,
+	&ls1x_nand_pdev,
 	&ls1x_rtc_pdev,
 };
 
 static int __init ls1b_platform_init(void)
 {
-	int err;
+	ls1x_serial_set_uartclk(&ls1x_uart_pdev);
+	ls1x_dma_set_platdata(&ls1x_dma_pdata);
+	ls1x_nand_set_platdata(&ls1x_nand_pdata);
 
-	ls1x_serial_setup(&ls1x_uart_pdev);
+	gpio_led_register_device(-1, &ls1x_led_pdata);
 
-	err = platform_add_devices(ls1b_platform_devices,
+	return platform_add_devices(ls1b_platform_devices,
 				   ARRAY_SIZE(ls1b_platform_devices));
-	return err;
 }
 
 arch_initcall(ls1b_platform_init);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/loongson64/common/env.c linux-libre-4.7-gnu/arch/mips/loongson64/common/env.c
--- linux-libre-4.6-gnu/arch/mips/loongson64/common/env.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/loongson64/common/env.c	2016-07-24 15:23:50.000000000 -0400
@@ -105,6 +105,10 @@ void __init prom_init_env(void)
 		loongson_chiptemp[1] = 0x900010001fe0019c;
 		loongson_chiptemp[2] = 0x900020001fe0019c;
 		loongson_chiptemp[3] = 0x900030001fe0019c;
+		loongson_freqctrl[0] = 0x900000001fe001d0;
+		loongson_freqctrl[1] = 0x900010001fe001d0;
+		loongson_freqctrl[2] = 0x900020001fe001d0;
+		loongson_freqctrl[3] = 0x900030001fe001d0;
 		loongson_sysconf.ht_control_base = 0x90000EFDFB000000;
 		loongson_sysconf.workarounds = WORKAROUND_CPUFREQ;
 	} else if (ecpu->cputype == Loongson_3B) {
@@ -187,7 +191,8 @@ void __init prom_init_env(void)
 		case PRID_REV_LOONGSON2F:
 			cpu_clock_freq = 797000000;
 			break;
-		case PRID_REV_LOONGSON3A:
+		case PRID_REV_LOONGSON3A_R1:
+		case PRID_REV_LOONGSON3A_R2:
 			cpu_clock_freq = 900000000;
 			break;
 		case PRID_REV_LOONGSON3B_R1:
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/loongson64/loongson-3/acpi_init.c linux-libre-4.7-gnu/arch/mips/loongson64/loongson-3/acpi_init.c
--- linux-libre-4.6-gnu/arch/mips/loongson64/loongson-3/acpi_init.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/mips/loongson64/loongson-3/acpi_init.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,150 @@
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/export.h>
+
+#define SBX00_ACPI_IO_BASE 0x800
+#define SBX00_ACPI_IO_SIZE 0x100
+
+#define ACPI_PM_EVT_BLK         (SBX00_ACPI_IO_BASE + 0x00) /* 4 bytes */
+#define ACPI_PM_CNT_BLK         (SBX00_ACPI_IO_BASE + 0x04) /* 2 bytes */
+#define ACPI_PMA_CNT_BLK        (SBX00_ACPI_IO_BASE + 0x0F) /* 1 byte */
+#define ACPI_PM_TMR_BLK         (SBX00_ACPI_IO_BASE + 0x18) /* 4 bytes */
+#define ACPI_GPE0_BLK           (SBX00_ACPI_IO_BASE + 0x10) /* 8 bytes */
+#define ACPI_END                (SBX00_ACPI_IO_BASE + 0x80)
+
+#define PM_INDEX        0xCD6
+#define PM_DATA         0xCD7
+#define PM2_INDEX       0xCD0
+#define PM2_DATA        0xCD1
+
+/*
+ * SCI interrupt need acpi space, allocate here
+ */
+
+static int __init register_acpi_resource(void)
+{
+	request_region(SBX00_ACPI_IO_BASE, SBX00_ACPI_IO_SIZE, "acpi");
+	return 0;
+}
+
+static void pmio_write_index(u16 index, u8 reg, u8 value)
+{
+	outb(reg, index);
+	outb(value, index + 1);
+}
+
+static u8 pmio_read_index(u16 index, u8 reg)
+{
+	outb(reg, index);
+	return inb(index + 1);
+}
+
+void pm_iowrite(u8 reg, u8 value)
+{
+	pmio_write_index(PM_INDEX, reg, value);
+}
+EXPORT_SYMBOL(pm_iowrite);
+
+u8 pm_ioread(u8 reg)
+{
+	return pmio_read_index(PM_INDEX, reg);
+}
+EXPORT_SYMBOL(pm_ioread);
+
+void pm2_iowrite(u8 reg, u8 value)
+{
+	pmio_write_index(PM2_INDEX, reg, value);
+}
+EXPORT_SYMBOL(pm2_iowrite);
+
+u8 pm2_ioread(u8 reg)
+{
+	return pmio_read_index(PM2_INDEX, reg);
+}
+EXPORT_SYMBOL(pm2_ioread);
+
+static void acpi_hw_clear_status(void)
+{
+	u16 value;
+
+	/* PMStatus: Clear WakeStatus/PwrBtnStatus */
+	value = inw(ACPI_PM_EVT_BLK);
+	value |= (1 << 8 | 1 << 15);
+	outw(value, ACPI_PM_EVT_BLK);
+
+	/* GPEStatus: Clear all generated events */
+	outl(inl(ACPI_GPE0_BLK), ACPI_GPE0_BLK);
+}
+
+void acpi_registers_setup(void)
+{
+	u32 value;
+
+	/* PM Status Base */
+	pm_iowrite(0x20, ACPI_PM_EVT_BLK & 0xff);
+	pm_iowrite(0x21, ACPI_PM_EVT_BLK >> 8);
+
+	/* PM Control Base */
+	pm_iowrite(0x22, ACPI_PM_CNT_BLK & 0xff);
+	pm_iowrite(0x23, ACPI_PM_CNT_BLK >> 8);
+
+	/* GPM Base */
+	pm_iowrite(0x28, ACPI_GPE0_BLK & 0xff);
+	pm_iowrite(0x29, ACPI_GPE0_BLK >> 8);
+
+	/* ACPI End */
+	pm_iowrite(0x2e, ACPI_END & 0xff);
+	pm_iowrite(0x2f, ACPI_END >> 8);
+
+	/* IO Decode: When AcpiDecodeEnable set, South-Bridge uses the contents
+	 * of the PM registers at index 0x20~0x2B to decode ACPI I/O address. */
+	pm_iowrite(0x0e, 1 << 3);
+
+	/* SCI_EN set */
+	outw(1, ACPI_PM_CNT_BLK);
+
+	/* Enable to generate SCI */
+	pm_iowrite(0x10, pm_ioread(0x10) | 1);
+
+	/* GPM3/GPM9 enable */
+	value = inl(ACPI_GPE0_BLK + 4);
+	outl(value | (1 << 14) | (1 << 22), ACPI_GPE0_BLK + 4);
+
+	/* Set GPM9 as input */
+	pm_iowrite(0x8d, pm_ioread(0x8d) & (~(1 << 1)));
+
+	/* Set GPM9 as non-output */
+	pm_iowrite(0x94, pm_ioread(0x94) | (1 << 3));
+
+	/* GPM3 config ACPI trigger SCIOUT */
+	pm_iowrite(0x33, pm_ioread(0x33) & (~(3 << 4)));
+
+	/* GPM9 config ACPI trigger SCIOUT */
+	pm_iowrite(0x3d, pm_ioread(0x3d) & (~(3 << 2)));
+
+	/* GPM3 config falling edge trigger */
+	pm_iowrite(0x37, pm_ioread(0x37) & (~(1 << 6)));
+
+	/* No wait for STPGNT# in ACPI Sx state */
+	pm_iowrite(0x7c, pm_ioread(0x7c) | (1 << 6));
+
+	/* Set GPM3 pull-down enable */
+	value = pm2_ioread(0xf6);
+	value |= ((1 << 7) | (1 << 3));
+	pm2_iowrite(0xf6, value);
+
+	/* Set GPM9 pull-down enable */
+	value = pm2_ioread(0xf8);
+	value |= ((1 << 5) | (1 << 1));
+	pm2_iowrite(0xf8, value);
+}
+
+int __init sbx00_acpi_init(void)
+{
+	register_acpi_resource();
+	acpi_registers_setup();
+	acpi_hw_clear_status();
+
+	return 0;
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/loongson64/loongson-3/hpet.c linux-libre-4.7-gnu/arch/mips/loongson64/loongson-3/hpet.c
--- linux-libre-4.6-gnu/arch/mips/loongson64/loongson-3/hpet.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/loongson64/loongson-3/hpet.c	2016-07-24 15:23:50.000000000 -0400
@@ -212,7 +212,7 @@ static void hpet_setup(void)
 	/* set hpet base address */
 	smbus_write(SMBUS_PCI_REGB4, HPET_ADDR);
 
-	/* enable decodeing of access to HPET MMIO*/
+	/* enable decoding of access to HPET MMIO*/
 	smbus_enable(SMBUS_PCI_REG40, (1 << 28));
 
 	/* HPET irq enable */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/loongson64/loongson-3/irq.c linux-libre-4.7-gnu/arch/mips/loongson64/loongson-3/irq.c
--- linux-libre-4.6-gnu/arch/mips/loongson64/loongson-3/irq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/loongson64/loongson-3/irq.c	2016-07-24 15:23:50.000000000 -0400
@@ -24,19 +24,21 @@ static void ht_irqdispatch(void)
 	}
 }
 
+#define UNUSED_IPS (CAUSEF_IP5 | CAUSEF_IP4 | CAUSEF_IP1 | CAUSEF_IP0)
+
 void mach_irq_dispatch(unsigned int pending)
 {
 	if (pending & CAUSEF_IP7)
 		do_IRQ(LOONGSON_TIMER_IRQ);
 #if defined(CONFIG_SMP)
-	else if (pending & CAUSEF_IP6)
+	if (pending & CAUSEF_IP6)
 		loongson3_ipi_interrupt(NULL);
 #endif
-	else if (pending & CAUSEF_IP3)
+	if (pending & CAUSEF_IP3)
 		ht_irqdispatch();
-	else if (pending & CAUSEF_IP2)
+	if (pending & CAUSEF_IP2)
 		do_IRQ(LOONGSON_UART_IRQ);
-	else {
+	if (pending & UNUSED_IPS) {
 		pr_err("%s : spurious interrupt\n", __func__);
 		spurious_interrupt();
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/loongson64/loongson-3/Makefile linux-libre-4.7-gnu/arch/mips/loongson64/loongson-3/Makefile
--- linux-libre-4.6-gnu/arch/mips/loongson64/loongson-3/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/loongson64/loongson-3/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -1,7 +1,7 @@
 #
 # Makefile for Loongson-3 family machines
 #
-obj-y			+= irq.o cop2-ex.o platform.o
+obj-y			+= irq.o cop2-ex.o platform.o acpi_init.o
 
 obj-$(CONFIG_SMP)	+= smp.o
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/loongson64/loongson-3/numa.c linux-libre-4.7-gnu/arch/mips/loongson64/loongson-3/numa.c
--- linux-libre-4.6-gnu/arch/mips/loongson64/loongson-3/numa.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/loongson64/loongson-3/numa.c	2016-07-24 15:23:50.000000000 -0400
@@ -213,10 +213,10 @@ static void __init node_mem_init(unsigne
 		BOOTMEM_DEFAULT);
 
 	if (node == 0 && node_end_pfn(0) >= (0xffffffff >> PAGE_SHIFT)) {
-		/* Reserve 0xff800000~0xffffffff for RS780E integrated GPU */
+		/* Reserve 0xfe000000~0xffffffff for RS780E integrated GPU */
 		reserve_bootmem_node(NODE_DATA(node),
-				(node_addrspace_offset | 0xff800000),
-				8 << 20, BOOTMEM_DEFAULT);
+				(node_addrspace_offset | 0xfe000000),
+				32 << 20, BOOTMEM_DEFAULT);
 	}
 
 	sparse_memory_present_with_active_regions(node);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/loongson64/loongson-3/smp.c linux-libre-4.7-gnu/arch/mips/loongson64/loongson-3/smp.c
--- linux-libre-4.6-gnu/arch/mips/loongson64/loongson-3/smp.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/loongson64/loongson-3/smp.c	2016-07-24 15:23:50.000000000 -0400
@@ -421,7 +421,6 @@ static int loongson3_cpu_disable(void)
 	local_irq_save(flags);
 	fixup_irqs();
 	local_irq_restore(flags);
-	flush_cache_all();
 	local_flush_tlb_all();
 
 	return 0;
@@ -440,7 +439,7 @@ static void loongson3_cpu_die(unsigned i
  * flush all L1 entries at first. Then, another core (usually Core 0) can
  * safely disable the clock of the target core. loongson3_play_dead() is
  * called via CKSEG1 (uncached and unmmaped) */
-static void loongson3a_play_dead(int *state_addr)
+static void loongson3a_r1_play_dead(int *state_addr)
 {
 	register int val;
 	register long cpuid, core, node, count;
@@ -502,6 +501,89 @@ static void loongson3a_play_dead(int *st
 		: "a1");
 }
 
+static void loongson3a_r2_play_dead(int *state_addr)
+{
+	register int val;
+	register long cpuid, core, node, count;
+	register void *addr, *base, *initfunc;
+
+	__asm__ __volatile__(
+		"   .set push                     \n"
+		"   .set noreorder                \n"
+		"   li %[addr], 0x80000000        \n" /* KSEG0 */
+		"1: cache 0, 0(%[addr])           \n" /* flush L1 ICache */
+		"   cache 0, 1(%[addr])           \n"
+		"   cache 0, 2(%[addr])           \n"
+		"   cache 0, 3(%[addr])           \n"
+		"   cache 1, 0(%[addr])           \n" /* flush L1 DCache */
+		"   cache 1, 1(%[addr])           \n"
+		"   cache 1, 2(%[addr])           \n"
+		"   cache 1, 3(%[addr])           \n"
+		"   addiu %[sets], %[sets], -1    \n"
+		"   bnez  %[sets], 1b             \n"
+		"   addiu %[addr], %[addr], 0x40  \n"
+		"   li %[addr], 0x80000000        \n" /* KSEG0 */
+		"2: cache 2, 0(%[addr])           \n" /* flush L1 VCache */
+		"   cache 2, 1(%[addr])           \n"
+		"   cache 2, 2(%[addr])           \n"
+		"   cache 2, 3(%[addr])           \n"
+		"   cache 2, 4(%[addr])           \n"
+		"   cache 2, 5(%[addr])           \n"
+		"   cache 2, 6(%[addr])           \n"
+		"   cache 2, 7(%[addr])           \n"
+		"   cache 2, 8(%[addr])           \n"
+		"   cache 2, 9(%[addr])           \n"
+		"   cache 2, 10(%[addr])          \n"
+		"   cache 2, 11(%[addr])          \n"
+		"   cache 2, 12(%[addr])          \n"
+		"   cache 2, 13(%[addr])          \n"
+		"   cache 2, 14(%[addr])          \n"
+		"   cache 2, 15(%[addr])          \n"
+		"   addiu %[vsets], %[vsets], -1  \n"
+		"   bnez  %[vsets], 2b            \n"
+		"   addiu %[addr], %[addr], 0x40  \n"
+		"   li    %[val], 0x7             \n" /* *state_addr = CPU_DEAD; */
+		"   sw    %[val], (%[state_addr]) \n"
+		"   sync                          \n"
+		"   cache 21, (%[state_addr])     \n" /* flush entry of *state_addr */
+		"   .set pop                      \n"
+		: [addr] "=&r" (addr), [val] "=&r" (val)
+		: [state_addr] "r" (state_addr),
+		  [sets] "r" (cpu_data[smp_processor_id()].dcache.sets),
+		  [vsets] "r" (cpu_data[smp_processor_id()].vcache.sets));
+
+	__asm__ __volatile__(
+		"   .set push                         \n"
+		"   .set noreorder                    \n"
+		"   .set mips64                       \n"
+		"   mfc0  %[cpuid], $15, 1            \n"
+		"   andi  %[cpuid], 0x3ff             \n"
+		"   dli   %[base], 0x900000003ff01000 \n"
+		"   andi  %[core], %[cpuid], 0x3      \n"
+		"   sll   %[core], 8                  \n" /* get core id */
+		"   or    %[base], %[base], %[core]   \n"
+		"   andi  %[node], %[cpuid], 0xc      \n"
+		"   dsll  %[node], 42                 \n" /* get node id */
+		"   or    %[base], %[base], %[node]   \n"
+		"1: li    %[count], 0x100             \n" /* wait for init loop */
+		"2: bnez  %[count], 2b                \n" /* limit mailbox access */
+		"   addiu %[count], -1                \n"
+		"   ld    %[initfunc], 0x20(%[base])  \n" /* get PC via mailbox */
+		"   beqz  %[initfunc], 1b             \n"
+		"   nop                               \n"
+		"   ld    $sp, 0x28(%[base])          \n" /* get SP via mailbox */
+		"   ld    $gp, 0x30(%[base])          \n" /* get GP via mailbox */
+		"   ld    $a1, 0x38(%[base])          \n"
+		"   jr    %[initfunc]                 \n" /* jump to initial PC */
+		"   nop                               \n"
+		"   .set pop                          \n"
+		: [core] "=&r" (core), [node] "=&r" (node),
+		  [base] "=&r" (base), [cpuid] "=&r" (cpuid),
+		  [count] "=&r" (count), [initfunc] "=&r" (initfunc)
+		: /* No Input */
+		: "a1");
+}
+
 static void loongson3b_play_dead(int *state_addr)
 {
 	register int val;
@@ -573,13 +655,18 @@ void play_dead(void)
 	void (*play_dead_at_ckseg1)(int *);
 
 	idle_task_exit();
-	switch (loongson_sysconf.cputype) {
-	case Loongson_3A:
+	switch (read_c0_prid() & PRID_REV_MASK) {
+	case PRID_REV_LOONGSON3A_R1:
 	default:
 		play_dead_at_ckseg1 =
-			(void *)CKSEG1ADDR((unsigned long)loongson3a_play_dead);
+			(void *)CKSEG1ADDR((unsigned long)loongson3a_r1_play_dead);
 		break;
-	case Loongson_3B:
+	case PRID_REV_LOONGSON3A_R2:
+		play_dead_at_ckseg1 =
+			(void *)CKSEG1ADDR((unsigned long)loongson3a_r2_play_dead);
+		break;
+	case PRID_REV_LOONGSON3B_R1:
+	case PRID_REV_LOONGSON3B_R2:
 		play_dead_at_ckseg1 =
 			(void *)CKSEG1ADDR((unsigned long)loongson3b_play_dead);
 		break;
@@ -594,9 +681,9 @@ void loongson3_disable_clock(int cpu)
 	uint64_t core_id = cpu_data[cpu].core;
 	uint64_t package_id = cpu_data[cpu].package;
 
-	if (loongson_sysconf.cputype == Loongson_3A) {
+	if ((read_c0_prid() & PRID_REV_MASK) == PRID_REV_LOONGSON3A_R1) {
 		LOONGSON_CHIPCFG(package_id) &= ~(1 << (12 + core_id));
-	} else if (loongson_sysconf.cputype == Loongson_3B) {
+	} else {
 		if (!(loongson_sysconf.workarounds & WORKAROUND_CPUHOTPLUG))
 			LOONGSON_FREQCTRL(package_id) &= ~(1 << (core_id * 4 + 3));
 	}
@@ -607,9 +694,9 @@ void loongson3_enable_clock(int cpu)
 	uint64_t core_id = cpu_data[cpu].core;
 	uint64_t package_id = cpu_data[cpu].package;
 
-	if (loongson_sysconf.cputype == Loongson_3A) {
+	if ((read_c0_prid() & PRID_REV_MASK) == PRID_REV_LOONGSON3A_R1) {
 		LOONGSON_CHIPCFG(package_id) |= 1 << (12 + core_id);
-	} else if (loongson_sysconf.cputype == Loongson_3B) {
+	} else {
 		if (!(loongson_sysconf.workarounds & WORKAROUND_CPUHOTPLUG))
 			LOONGSON_FREQCTRL(package_id) |= 1 << (core_id * 4 + 3);
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/loongson64/Platform linux-libre-4.7-gnu/arch/mips/loongson64/Platform
--- linux-libre-4.6-gnu/arch/mips/loongson64/Platform	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/loongson64/Platform	2016-07-24 15:23:50.000000000 -0400
@@ -31,7 +31,7 @@ cflags-$(CONFIG_CPU_LOONGSON3)	+= -Wa,--
 # can't easily be used safely within the kbuild framework.
 #
 ifeq ($(call cc-ifversion, -ge, 0409, y), y)
-  ifeq ($(call ld-ifversion, -ge, 22500000, y), y)
+  ifeq ($(call ld-ifversion, -ge, 225000000, y), y)
     cflags-$(CONFIG_CPU_LOONGSON3)  += \
       $(call cc-option,-march=loongson3a -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS64)
   else
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/Makefile linux-libre-4.7-gnu/arch/mips/Makefile
--- linux-libre-4.6-gnu/arch/mips/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -12,6 +12,9 @@
 # for "archclean" cleaning up for this architecture.
 #
 
+archscripts: scripts_basic
+	$(Q)$(MAKE) $(build)=arch/mips/boot/tools relocs
+
 KBUILD_DEFCONFIG := ip22_defconfig
 
 #
@@ -93,6 +96,10 @@ LDFLAGS_vmlinux			+= -G 0 -static -n -no
 KBUILD_AFLAGS_MODULE		+= -mlong-calls
 KBUILD_CFLAGS_MODULE		+= -mlong-calls
 
+ifeq ($(CONFIG_RELOCATABLE),y)
+LDFLAGS_vmlinux			+= --emit-relocs
+endif
+
 #
 # pass -msoft-float to GAS if it supports it.  However on newer binutils
 # (specifically newer than 2.24.51.20140728) we then also need to explicitly
@@ -193,6 +200,8 @@ ifeq ($(CONFIG_CPU_HAS_MSA),y)
 toolchain-msa				:= $(call cc-option-yn,$(mips-cflags) -mhard-float -mfp64 -Wa$(comma)-mmsa)
 cflags-$(toolchain-msa)			+= -DTOOLCHAIN_SUPPORTS_MSA
 endif
+toolchain-virt				:= $(call cc-option-yn,$(mips-cflags) -mvirt)
+cflags-$(toolchain-virt)		+= -DTOOLCHAIN_SUPPORTS_VIRT
 
 cflags-$(CONFIG_MIPS_COMPACT_BRANCHES_NEVER)	+= -mcompact-branches=never
 cflags-$(CONFIG_MIPS_COMPACT_BRANCHES_OPTIMAL)	+= -mcompact-branches=optimal
@@ -310,6 +319,10 @@ rom.bin rom.sw: vmlinux
 		$(bootvars-y) $@
 endif
 
+CMD_RELOCS = arch/mips/boot/tools/relocs
+quiet_cmd_relocs = RELOCS  $<
+      cmd_relocs = $(CMD_RELOCS) $<
+
 #
 # Some machines like the Indy need 32-bit ELF binaries for booting purposes.
 # Other need ECOFF, so we build a 32-bit ELF binary for them which we then
@@ -318,6 +331,11 @@ endif
 quiet_cmd_32 = OBJCOPY $@
 	cmd_32 = $(OBJCOPY) -O $(32bit-bfd) $(OBJCOPYFLAGS) $< $@
 vmlinux.32: vmlinux
+ifeq ($(CONFIG_RELOCATABLE)$(CONFIG_64BIT),yy)
+# Currently, objcopy fails to handle the relocations in the elf64
+# So the relocs tool must be run here to remove them first
+	$(call cmd,relocs)
+endif
 	$(call cmd,32)
 
 #
@@ -333,6 +351,9 @@ all:	$(all-y)
 
 # boot
 $(boot-y): $(vmlinux-32) FORCE
+ifeq ($(CONFIG_RELOCATABLE)$(CONFIG_32BIT),yy)
+	$(call cmd,relocs)
+endif
 	$(Q)$(MAKE) $(build)=arch/mips/boot VMLINUX=$(vmlinux-32) \
 		$(bootvars-y) arch/mips/boot/$@
 
@@ -385,6 +406,7 @@ endif
 archclean:
 	$(Q)$(MAKE) $(clean)=arch/mips/boot
 	$(Q)$(MAKE) $(clean)=arch/mips/boot/compressed
+	$(Q)$(MAKE) $(clean)=arch/mips/boot/tools
 	$(Q)$(MAKE) $(clean)=arch/mips/lasat
 
 define archhelp
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/math-emu/cp1emu.c linux-libre-4.7-gnu/arch/mips/math-emu/cp1emu.c
--- linux-libre-4.6-gnu/arch/mips/math-emu/cp1emu.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/math-emu/cp1emu.c	2016-07-24 15:23:50.000000000 -0400
@@ -445,9 +445,11 @@ static int isBranchInstr(struct pt_regs
 	case spec_op:
 		switch (insn.r_format.func) {
 		case jalr_op:
-			regs->regs[insn.r_format.rd] =
-				regs->cp0_epc + dec_insn.pc_inc +
-				dec_insn.next_pc_inc;
+			if (insn.r_format.rd != 0) {
+				regs->regs[insn.r_format.rd] =
+					regs->cp0_epc + dec_insn.pc_inc +
+					dec_insn.next_pc_inc;
+			}
 			/* Fall through */
 		case jr_op:
 			/* For R6, JR already emulated in jalr_op */
@@ -973,9 +975,10 @@ static int cop1Emulate(struct pt_regs *x
 		struct mm_decoded_insn dec_insn, void *__user *fault_addr)
 {
 	unsigned long contpc = xcp->cp0_epc + dec_insn.pc_inc;
-	unsigned int cond, cbit;
+	unsigned int cond, cbit, bit0;
 	mips_instruction ir;
 	int likely, pc_inc;
+	union fpureg *fpr;
 	u32 __user *wva;
 	u64 __user *dva;
 	u32 wval;
@@ -1187,14 +1190,14 @@ emul:
 				return SIGILL;
 
 			cond = likely = 0;
+			fpr = &current->thread.fpu.fpr[MIPSInst_RT(ir)];
+			bit0 = get_fpr32(fpr, 0) & 0x1;
 			switch (MIPSInst_RS(ir)) {
 			case bc1eqz_op:
-				if (get_fpr32(&current->thread.fpu.fpr[MIPSInst_RT(ir)], 0) & 0x1)
-				    cond = 1;
+				cond = bit0 == 0;
 				break;
 			case bc1nez_op:
-				if (!(get_fpr32(&current->thread.fpu.fpr[MIPSInst_RT(ir)], 0) & 0x1))
-				    cond = 1;
+				cond = bit0 != 0;
 				break;
 			}
 			goto branch_common;
@@ -1674,7 +1677,7 @@ static int fpu_emu(struct pt_regs *xcp,
 			union ieee754sp(*b) (union ieee754sp, union ieee754sp);
 			union ieee754sp(*u) (union ieee754sp);
 		} handler;
-		union ieee754sp fs, ft;
+		union ieee754sp fd, fs, ft;
 
 		switch (MIPSInst_FUNC(ir)) {
 			/* binary ops */
@@ -1945,6 +1948,17 @@ copcsr:
 			rfmt = w_fmt;
 			goto copcsr;
 
+		case fsel_op:
+			if (!cpu_has_mips_r6)
+				return SIGILL;
+
+			SPFROMREG(fd, MIPSInst_FD(ir));
+			if (fd.bits & 0x1)
+				SPFROMREG(rv.s, MIPSInst_FT(ir));
+			else
+				SPFROMREG(rv.s, MIPSInst_FS(ir));
+			break;
+
 		case fcvtl_op:
 			if (!cpu_has_mips_3_4_5_64_r2_r6)
 				return SIGILL;
@@ -1993,7 +2007,7 @@ copcsr:
 	}
 
 	case d_fmt: {
-		union ieee754dp fs, ft;
+		union ieee754dp fd, fs, ft;
 		union {
 			union ieee754dp(*b) (union ieee754dp, union ieee754dp);
 			union ieee754dp(*u) (union ieee754dp);
@@ -2243,6 +2257,17 @@ dcopuop:
 			rfmt = w_fmt;
 			goto copcsr;
 
+		case fsel_op:
+			if (!cpu_has_mips_r6)
+				return SIGILL;
+
+			DPFROMREG(fd, MIPSInst_FD(ir));
+			if (fd.bits & 0x1)
+				DPFROMREG(rv.d, MIPSInst_FT(ir));
+			else
+				DPFROMREG(rv.d, MIPSInst_FS(ir));
+			break;
+
 		case fcvtl_op:
 			if (!cpu_has_mips_3_4_5_64_r2_r6)
 				return SIGILL;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/math-emu/dp_maddf.c linux-libre-4.7-gnu/arch/mips/math-emu/dp_maddf.c
--- linux-libre-4.6-gnu/arch/mips/math-emu/dp_maddf.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/math-emu/dp_maddf.c	2016-07-24 15:23:50.000000000 -0400
@@ -14,8 +14,12 @@
 
 #include "ieee754dp.h"
 
-union ieee754dp ieee754dp_maddf(union ieee754dp z, union ieee754dp x,
-				union ieee754dp y)
+enum maddf_flags {
+	maddf_negate_product	= 1 << 0,
+};
+
+static union ieee754dp _dp_maddf(union ieee754dp z, union ieee754dp x,
+				 union ieee754dp y, enum maddf_flags flags)
 {
 	int re;
 	int rs;
@@ -32,16 +36,15 @@ union ieee754dp ieee754dp_maddf(union ie
 
 	COMPXDP;
 	COMPYDP;
-
-	u64 zm; int ze; int zs __maybe_unused; int zc;
+	COMPZDP;
 
 	EXPLODEXDP;
 	EXPLODEYDP;
-	EXPLODEDP(z, zc, zs, ze, zm)
+	EXPLODEZDP;
 
 	FLUSHXDP;
 	FLUSHYDP;
-	FLUSHDP(z, zc, zs, ze, zm);
+	FLUSHZDP;
 
 	ieee754_clearcx();
 
@@ -50,7 +53,7 @@ union ieee754dp ieee754dp_maddf(union ie
 		ieee754_setcx(IEEE754_INVALID_OPERATION);
 		return ieee754dp_nanxcpt(z);
 	case IEEE754_CLASS_DNORM:
-		DPDNORMx(zm, ze);
+		DPDNORMZ;
 	/* QNAN is handled separately below */
 	}
 
@@ -154,13 +157,15 @@ union ieee754dp ieee754dp_maddf(union ie
 
 	re = xe + ye;
 	rs = xs ^ ys;
+	if (flags & maddf_negate_product)
+		rs ^= 1;
 
 	/* shunt to top of word */
 	xm <<= 64 - (DP_FBITS + 1);
 	ym <<= 64 - (DP_FBITS + 1);
 
 	/*
-	 * Multiply 32 bits xm, ym to give high 32 bits rm with stickness.
+	 * Multiply 64 bits xm, ym to give high 64 bits rm with stickness.
 	 */
 
 	/* 32 * 32 => 64 */
@@ -198,7 +203,7 @@ union ieee754dp ieee754dp_maddf(union ie
 	if ((s64) rm < 0) {
 		rm = (rm >> (64 - (DP_FBITS + 1 + 3))) |
 		     ((rm << (DP_FBITS + 1 + 3)) != 0);
-			re++;
+		re++;
 	} else {
 		rm = (rm >> (64 - (DP_FBITS + 1 + 3 + 1))) |
 		     ((rm << (DP_FBITS + 1 + 3 + 1)) != 0);
@@ -263,3 +268,15 @@ union ieee754dp ieee754dp_maddf(union ie
 
 	return ieee754dp_format(zs, ze, zm);
 }
+
+union ieee754dp ieee754dp_maddf(union ieee754dp z, union ieee754dp x,
+				union ieee754dp y)
+{
+	return _dp_maddf(z, x, y, 0);
+}
+
+union ieee754dp ieee754dp_msubf(union ieee754dp z, union ieee754dp x,
+				union ieee754dp y)
+{
+	return _dp_maddf(z, x, y, maddf_negate_product);
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/math-emu/dp_msubf.c linux-libre-4.7-gnu/arch/mips/math-emu/dp_msubf.c
--- linux-libre-4.6-gnu/arch/mips/math-emu/dp_msubf.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/math-emu/dp_msubf.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,269 +0,0 @@
-/*
- * IEEE754 floating point arithmetic
- * double precision: MSUB.f (Fused Multiply Subtract)
- * MSUBF.fmt: FPR[fd] = FPR[fd] - (FPR[fs] x FPR[ft])
- *
- * MIPS floating point support
- * Copyright (C) 2015 Imagination Technologies, Ltd.
- * Author: Markos Chandras <markos.chandras@imgtec.com>
- *
- *  This program is free software; you can distribute 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.
- */
-
-#include "ieee754dp.h"
-
-union ieee754dp ieee754dp_msubf(union ieee754dp z, union ieee754dp x,
-				union ieee754dp y)
-{
-	int re;
-	int rs;
-	u64 rm;
-	unsigned lxm;
-	unsigned hxm;
-	unsigned lym;
-	unsigned hym;
-	u64 lrm;
-	u64 hrm;
-	u64 t;
-	u64 at;
-	int s;
-
-	COMPXDP;
-	COMPYDP;
-
-	u64 zm; int ze; int zs __maybe_unused; int zc;
-
-	EXPLODEXDP;
-	EXPLODEYDP;
-	EXPLODEDP(z, zc, zs, ze, zm)
-
-	FLUSHXDP;
-	FLUSHYDP;
-	FLUSHDP(z, zc, zs, ze, zm);
-
-	ieee754_clearcx();
-
-	switch (zc) {
-	case IEEE754_CLASS_SNAN:
-		ieee754_setcx(IEEE754_INVALID_OPERATION);
-		return ieee754dp_nanxcpt(z);
-	case IEEE754_CLASS_DNORM:
-		DPDNORMx(zm, ze);
-	/* QNAN is handled separately below */
-	}
-
-	switch (CLPAIR(xc, yc)) {
-	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
-	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
-	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
-	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
-	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
-		return ieee754dp_nanxcpt(y);
-
-	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
-	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
-	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
-	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
-	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
-	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
-		return ieee754dp_nanxcpt(x);
-
-	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
-	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
-	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
-	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
-		return y;
-
-	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
-	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
-	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
-	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
-	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
-		return x;
-
-
-	/*
-	 * Infinity handling
-	 */
-	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
-	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
-		if (zc == IEEE754_CLASS_QNAN)
-			return z;
-		ieee754_setcx(IEEE754_INVALID_OPERATION);
-		return ieee754dp_indef();
-
-	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
-	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
-	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
-	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
-	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
-		if (zc == IEEE754_CLASS_QNAN)
-			return z;
-		return ieee754dp_inf(xs ^ ys);
-
-	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
-	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
-	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
-	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
-	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
-		if (zc == IEEE754_CLASS_INF)
-			return ieee754dp_inf(zs);
-		/* Multiplication is 0 so just return z */
-		return z;
-
-	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
-		DPDNORMX;
-
-	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
-		if (zc == IEEE754_CLASS_QNAN)
-			return z;
-		else if (zc == IEEE754_CLASS_INF)
-			return ieee754dp_inf(zs);
-		DPDNORMY;
-		break;
-
-	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
-		if (zc == IEEE754_CLASS_QNAN)
-			return z;
-		else if (zc == IEEE754_CLASS_INF)
-			return ieee754dp_inf(zs);
-		DPDNORMX;
-		break;
-
-	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
-		if (zc == IEEE754_CLASS_QNAN)
-			return z;
-		else if (zc == IEEE754_CLASS_INF)
-			return ieee754dp_inf(zs);
-		/* fall through to real computations */
-	}
-
-	/* Finally get to do some computation */
-
-	/*
-	 * Do the multiplication bit first
-	 *
-	 * rm = xm * ym, re = xe + ye basically
-	 *
-	 * At this point xm and ym should have been normalized.
-	 */
-	assert(xm & DP_HIDDEN_BIT);
-	assert(ym & DP_HIDDEN_BIT);
-
-	re = xe + ye;
-	rs = xs ^ ys;
-
-	/* shunt to top of word */
-	xm <<= 64 - (DP_FBITS + 1);
-	ym <<= 64 - (DP_FBITS + 1);
-
-	/*
-	 * Multiply 32 bits xm, ym to give high 32 bits rm with stickness.
-	 */
-
-	/* 32 * 32 => 64 */
-#define DPXMULT(x, y)	((u64)(x) * (u64)y)
-
-	lxm = xm;
-	hxm = xm >> 32;
-	lym = ym;
-	hym = ym >> 32;
-
-	lrm = DPXMULT(lxm, lym);
-	hrm = DPXMULT(hxm, hym);
-
-	t = DPXMULT(lxm, hym);
-
-	at = lrm + (t << 32);
-	hrm += at < lrm;
-	lrm = at;
-
-	hrm = hrm + (t >> 32);
-
-	t = DPXMULT(hxm, lym);
-
-	at = lrm + (t << 32);
-	hrm += at < lrm;
-	lrm = at;
-
-	hrm = hrm + (t >> 32);
-
-	rm = hrm | (lrm != 0);
-
-	/*
-	 * Sticky shift down to normal rounding precision.
-	 */
-	if ((s64) rm < 0) {
-		rm = (rm >> (64 - (DP_FBITS + 1 + 3))) |
-		     ((rm << (DP_FBITS + 1 + 3)) != 0);
-			re++;
-	} else {
-		rm = (rm >> (64 - (DP_FBITS + 1 + 3 + 1))) |
-		     ((rm << (DP_FBITS + 1 + 3 + 1)) != 0);
-	}
-	assert(rm & (DP_HIDDEN_BIT << 3));
-
-	/* And now the subtraction */
-
-	/* flip sign of r and handle as add */
-	rs ^= 1;
-
-	assert(zm & DP_HIDDEN_BIT);
-
-	/*
-	 * Provide guard,round and stick bit space.
-	 */
-	zm <<= 3;
-
-	if (ze > re) {
-		/*
-		 * Have to shift y fraction right to align.
-		 */
-		s = ze - re;
-		rm = XDPSRS(rm, s);
-		re += s;
-	} else if (re > ze) {
-		/*
-		 * Have to shift x fraction right to align.
-		 */
-		s = re - ze;
-		zm = XDPSRS(zm, s);
-		ze += s;
-	}
-	assert(ze == re);
-	assert(ze <= DP_EMAX);
-
-	if (zs == rs) {
-		/*
-		 * Generate 28 bit result of adding two 27 bit numbers
-		 * leaving result in xm, xs and xe.
-		 */
-		zm = zm + rm;
-
-		if (zm >> (DP_FBITS + 1 + 3)) { /* carry out */
-			zm = XDPSRS1(zm);
-			ze++;
-		}
-	} else {
-		if (zm >= rm) {
-			zm = zm - rm;
-		} else {
-			zm = rm - zm;
-			zs = rs;
-		}
-		if (zm == 0)
-			return ieee754dp_zero(ieee754_csr.rm == FPU_CSR_RD);
-
-		/*
-		 * Normalize to rounding precision.
-		 */
-		while ((zm >> (DP_FBITS + 3)) == 0) {
-			zm <<= 1;
-			ze--;
-		}
-	}
-
-	return ieee754dp_format(zs, ze, zm);
-}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/math-emu/dp_mul.c linux-libre-4.7-gnu/arch/mips/math-emu/dp_mul.c
--- linux-libre-4.6-gnu/arch/mips/math-emu/dp_mul.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/math-emu/dp_mul.c	2016-07-24 15:23:50.000000000 -0400
@@ -125,7 +125,7 @@ union ieee754dp ieee754dp_mul(union ieee
 	ym <<= 64 - (DP_FBITS + 1);
 
 	/*
-	 * Multiply 32 bits xm, ym to give high 32 bits rm with stickness.
+	 * Multiply 64 bits xm, ym to give high 64 bits rm with stickness.
 	 */
 
 	/* 32 * 32 => 64 */
@@ -163,7 +163,7 @@ union ieee754dp ieee754dp_mul(union ieee
 	if ((s64) rm < 0) {
 		rm = (rm >> (64 - (DP_FBITS + 1 + 3))) |
 		     ((rm << (DP_FBITS + 1 + 3)) != 0);
-			re++;
+		re++;
 	} else {
 		rm = (rm >> (64 - (DP_FBITS + 1 + 3 + 1))) |
 		     ((rm << (DP_FBITS + 1 + 3 + 1)) != 0);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/math-emu/dsemul.c linux-libre-4.7-gnu/arch/mips/math-emu/dsemul.c
--- linux-libre-4.6-gnu/arch/mips/math-emu/dsemul.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/math-emu/dsemul.c	2016-07-24 15:23:50.000000000 -0400
@@ -8,7 +8,7 @@
 #include "ieee754.h"
 
 /*
- * Emulate the arbritrary instruction ir at xcp->cp0_epc.  Required when
+ * Emulate the arbitrary instruction ir at xcp->cp0_epc.  Required when
  * we have to emulate the instruction in a COP1 branch delay slot.  Do
  * not change cp0_epc due to the instruction
  *
@@ -60,7 +60,7 @@ int mips_dsemul(struct pt_regs *regs, mi
 			unsigned int rs;
 			s32 v;
 
-			rs = (((insn.mm_a_format.rs + 0x1e) & 0xf) + 2);
+			rs = (((insn.mm_a_format.rs + 0xe) & 0xf) + 2);
 			v = regs->cp0_epc & ~3;
 			v += insn.mm_a_format.simmediate << 2;
 			regs->regs[rs] = (long)v;
@@ -88,7 +88,7 @@ int mips_dsemul(struct pt_regs *regs, mi
 	fr = (struct emuframe __user *)
 		((regs->regs[29] - sizeof(struct emuframe)) & ~0x7);
 
-	/* Verify that the stack pointer is not competely insane */
+	/* Verify that the stack pointer is not completely insane */
 	if (unlikely(!access_ok(VERIFY_WRITE, fr, sizeof(struct emuframe))))
 		return SIGBUS;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/math-emu/ieee754dp.c linux-libre-4.7-gnu/arch/mips/math-emu/ieee754dp.c
--- linux-libre-4.6-gnu/arch/mips/math-emu/ieee754dp.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/math-emu/ieee754dp.c	2016-07-24 15:23:50.000000000 -0400
@@ -54,10 +54,13 @@ union ieee754dp __cold ieee754dp_nanxcpt
 	assert(ieee754dp_issnan(r));
 
 	ieee754_setcx(IEEE754_INVALID_OPERATION);
-	if (ieee754_csr.nan2008)
+	if (ieee754_csr.nan2008) {
 		DPMANT(r) |= DP_MBIT(DP_FBITS - 1);
-	else
-		r = ieee754dp_indef();
+	} else {
+		DPMANT(r) &= ~DP_MBIT(DP_FBITS - 1);
+		if (!ieee754dp_isnan(r))
+			DPMANT(r) |= DP_MBIT(DP_FBITS - 2);
+	}
 
 	return r;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/math-emu/ieee754dp.h linux-libre-4.7-gnu/arch/mips/math-emu/ieee754dp.h
--- linux-libre-4.6-gnu/arch/mips/math-emu/ieee754dp.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/math-emu/ieee754dp.h	2016-07-24 15:23:50.000000000 -0400
@@ -60,6 +60,7 @@ static inline int ieee754dp_finite(union
 	while ((m >> DP_FBITS) == 0) { m <<= 1; e--; }
 #define DPDNORMX	DPDNORMx(xm, xe)
 #define DPDNORMY	DPDNORMx(ym, ye)
+#define DPDNORMZ	DPDNORMx(zm, ze)
 
 static inline union ieee754dp builddp(int s, int bx, u64 m)
 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/math-emu/ieee754int.h linux-libre-4.7-gnu/arch/mips/math-emu/ieee754int.h
--- linux-libre-4.6-gnu/arch/mips/math-emu/ieee754int.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/math-emu/ieee754int.h	2016-07-24 15:23:50.000000000 -0400
@@ -55,6 +55,9 @@ static inline int ieee754_class_nan(int
 #define COMPYSP \
 	unsigned ym; int ye; int ys; int yc
 
+#define COMPZSP \
+	unsigned zm; int ze; int zs; int zc
+
 #define EXPLODESP(v, vc, vs, ve, vm)					\
 {									\
 	vs = SPSIGN(v);							\
@@ -81,6 +84,7 @@ static inline int ieee754_class_nan(int
 }
 #define EXPLODEXSP EXPLODESP(x, xc, xs, xe, xm)
 #define EXPLODEYSP EXPLODESP(y, yc, ys, ye, ym)
+#define EXPLODEZSP EXPLODESP(z, zc, zs, ze, zm)
 
 
 #define COMPXDP \
@@ -89,6 +93,9 @@ static inline int ieee754_class_nan(int
 #define COMPYDP \
 	u64 ym; int ye; int ys; int yc
 
+#define COMPZDP \
+	u64 zm; int ze; int zs; int zc
+
 #define EXPLODEDP(v, vc, vs, ve, vm)					\
 {									\
 	vm = DPMANT(v);							\
@@ -115,6 +122,7 @@ static inline int ieee754_class_nan(int
 }
 #define EXPLODEXDP EXPLODEDP(x, xc, xs, xe, xm)
 #define EXPLODEYDP EXPLODEDP(y, yc, ys, ye, ym)
+#define EXPLODEZDP EXPLODEDP(z, zc, zs, ze, zm)
 
 #define FLUSHDP(v, vc, vs, ve, vm)					\
 	if (vc==IEEE754_CLASS_DNORM) {					\
@@ -140,7 +148,9 @@ static inline int ieee754_class_nan(int
 
 #define FLUSHXDP FLUSHDP(x, xc, xs, xe, xm)
 #define FLUSHYDP FLUSHDP(y, yc, ys, ye, ym)
+#define FLUSHZDP FLUSHDP(z, zc, zs, ze, zm)
 #define FLUSHXSP FLUSHSP(x, xc, xs, xe, xm)
 #define FLUSHYSP FLUSHSP(y, yc, ys, ye, ym)
+#define FLUSHZSP FLUSHSP(z, zc, zs, ze, zm)
 
 #endif /* __IEEE754INT_H  */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/math-emu/ieee754sp.c linux-libre-4.7-gnu/arch/mips/math-emu/ieee754sp.c
--- linux-libre-4.6-gnu/arch/mips/math-emu/ieee754sp.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/math-emu/ieee754sp.c	2016-07-24 15:23:50.000000000 -0400
@@ -54,10 +54,13 @@ union ieee754sp __cold ieee754sp_nanxcpt
 	assert(ieee754sp_issnan(r));
 
 	ieee754_setcx(IEEE754_INVALID_OPERATION);
-	if (ieee754_csr.nan2008)
+	if (ieee754_csr.nan2008) {
 		SPMANT(r) |= SP_MBIT(SP_FBITS - 1);
-	else
-		r = ieee754sp_indef();
+	} else {
+		SPMANT(r) &= ~SP_MBIT(SP_FBITS - 1);
+		if (!ieee754sp_isnan(r))
+			SPMANT(r) |= SP_MBIT(SP_FBITS - 2);
+	}
 
 	return r;
 }
@@ -138,7 +141,8 @@ union ieee754sp ieee754sp_format(int sn,
 		} else {
 			/* sticky right shift es bits
 			 */
-			SPXSRSXn(es);
+			xm = XSPSRS(xm, es);
+			xe += es;
 			assert((xm & (SP_HIDDEN_BIT << 3)) == 0);
 			assert(xe == SP_EMIN);
 		}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/math-emu/ieee754sp.h linux-libre-4.7-gnu/arch/mips/math-emu/ieee754sp.h
--- linux-libre-4.6-gnu/arch/mips/math-emu/ieee754sp.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/math-emu/ieee754sp.h	2016-07-24 15:23:50.000000000 -0400
@@ -46,25 +46,24 @@ static inline int ieee754sp_finite(union
 }
 
 /* 3bit extended single precision sticky right shift */
-#define SPXSRSXn(rs)							\
-	(xe += rs,							\
-	 xm = (rs > (SP_FBITS+3))?1:((xm) >> (rs)) | ((xm) << (32-(rs)) != 0))
+#define XSPSRS(v, rs)						\
+	((rs > (SP_FBITS+3))?1:((v) >> (rs)) | ((v) << (32-(rs)) != 0))
 
-#define SPXSRSX1() \
-	(xe++, (xm = (xm >> 1) | (xm & 1)))
+#define XSPSRS1(m) \
+	((m >> 1) | (m & 1))
 
-#define SPXSRSYn(rs)								\
-	(ye+=rs,								\
-	 ym = (rs > (SP_FBITS+3))?1:((ym) >> (rs)) | ((ym) << (32-(rs)) != 0))
+#define SPXSRSX1() \
+	(xe++, (xm = XSPSRS1(xm)))
 
 #define SPXSRSY1() \
-	(ye++, (ym = (ym >> 1) | (ym & 1)))
+	(ye++, (ym = XSPSRS1(ym)))
 
 /* convert denormal to normalized with extended exponent */
 #define SPDNORMx(m,e) \
 	while ((m >> SP_FBITS) == 0) { m <<= 1; e--; }
 #define SPDNORMX	SPDNORMx(xm, xe)
 #define SPDNORMY	SPDNORMx(ym, ye)
+#define SPDNORMZ	SPDNORMx(zm, ze)
 
 static inline union ieee754sp buildsp(int s, int bx, unsigned m)
 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/math-emu/Makefile linux-libre-4.7-gnu/arch/mips/math-emu/Makefile
--- linux-libre-4.6-gnu/arch/mips/math-emu/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/math-emu/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -4,9 +4,9 @@
 
 obj-y	+= cp1emu.o ieee754dp.o ieee754sp.o ieee754.o \
 	   dp_div.o dp_mul.o dp_sub.o dp_add.o dp_fsp.o dp_cmp.o dp_simple.o \
-	   dp_tint.o dp_fint.o dp_maddf.o dp_msubf.o dp_2008class.o dp_fmin.o dp_fmax.o \
+	   dp_tint.o dp_fint.o dp_maddf.o dp_2008class.o dp_fmin.o dp_fmax.o \
 	   sp_div.o sp_mul.o sp_sub.o sp_add.o sp_fdp.o sp_cmp.o sp_simple.o \
-	   sp_tint.o sp_fint.o sp_maddf.o sp_msubf.o sp_2008class.o sp_fmin.o sp_fmax.o \
+	   sp_tint.o sp_fint.o sp_maddf.o sp_2008class.o sp_fmin.o sp_fmax.o \
 	   dsemul.o
 
 lib-y	+= ieee754d.o \
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/math-emu/sp_add.c linux-libre-4.7-gnu/arch/mips/math-emu/sp_add.c
--- linux-libre-4.6-gnu/arch/mips/math-emu/sp_add.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/math-emu/sp_add.c	2016-07-24 15:23:50.000000000 -0400
@@ -132,13 +132,15 @@ union ieee754sp ieee754sp_add(union ieee
 		 * Have to shift y fraction right to align.
 		 */
 		s = xe - ye;
-		SPXSRSYn(s);
+		ym = XSPSRS(ym, s);
+		ye += s;
 	} else if (ye > xe) {
 		/*
 		 * Have to shift x fraction right to align.
 		 */
 		s = ye - xe;
-		SPXSRSXn(s);
+		xm = XSPSRS(xm, s);
+		xe += s;
 	}
 	assert(xe == ye);
 	assert(xe <= SP_EMAX);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/math-emu/sp_maddf.c linux-libre-4.7-gnu/arch/mips/math-emu/sp_maddf.c
--- linux-libre-4.6-gnu/arch/mips/math-emu/sp_maddf.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/math-emu/sp_maddf.c	2016-07-24 15:23:50.000000000 -0400
@@ -14,8 +14,12 @@
 
 #include "ieee754sp.h"
 
-union ieee754sp ieee754sp_maddf(union ieee754sp z, union ieee754sp x,
-				union ieee754sp y)
+enum maddf_flags {
+	maddf_negate_product	= 1 << 0,
+};
+
+static union ieee754sp _sp_maddf(union ieee754sp z, union ieee754sp x,
+				 union ieee754sp y, enum maddf_flags flags)
 {
 	int re;
 	int rs;
@@ -32,15 +36,15 @@ union ieee754sp ieee754sp_maddf(union ie
 
 	COMPXSP;
 	COMPYSP;
-	u32 zm; int ze; int zs __maybe_unused; int zc;
+	COMPZSP;
 
 	EXPLODEXSP;
 	EXPLODEYSP;
-	EXPLODESP(z, zc, zs, ze, zm)
+	EXPLODEZSP;
 
 	FLUSHXSP;
 	FLUSHYSP;
-	FLUSHSP(z, zc, zs, ze, zm);
+	FLUSHZSP;
 
 	ieee754_clearcx();
 
@@ -49,7 +53,7 @@ union ieee754sp ieee754sp_maddf(union ie
 		ieee754_setcx(IEEE754_INVALID_OPERATION);
 		return ieee754sp_nanxcpt(z);
 	case IEEE754_CLASS_DNORM:
-		SPDNORMx(zm, ze);
+		SPDNORMZ;
 	/* QNAN is handled separately below */
 	}
 
@@ -154,6 +158,8 @@ union ieee754sp ieee754sp_maddf(union ie
 
 	re = xe + ye;
 	rs = xs ^ ys;
+	if (flags & maddf_negate_product)
+		rs ^= 1;
 
 	/* shunt to top of word */
 	xm <<= 32 - (SP_FBITS + 1);
@@ -208,16 +214,18 @@ union ieee754sp ieee754sp_maddf(union ie
 
 	if (ze > re) {
 		/*
-		 * Have to shift y fraction right to align.
+		 * Have to shift r fraction right to align.
 		 */
 		s = ze - re;
-		SPXSRSYn(s);
+		rm = XSPSRS(rm, s);
+		re += s;
 	} else if (re > ze) {
 		/*
-		 * Have to shift x fraction right to align.
+		 * Have to shift z fraction right to align.
 		 */
 		s = re - ze;
-		SPXSRSYn(s);
+		zm = XSPSRS(zm, s);
+		ze += s;
 	}
 	assert(ze == re);
 	assert(ze <= SP_EMAX);
@@ -230,7 +238,8 @@ union ieee754sp ieee754sp_maddf(union ie
 		zm = zm + rm;
 
 		if (zm >> (SP_FBITS + 1 + 3)) { /* carry out */
-			SPXSRSX1();
+			zm = XSPSRS1(zm);
+			ze++;
 		}
 	} else {
 		if (zm >= rm) {
@@ -253,3 +262,15 @@ union ieee754sp ieee754sp_maddf(union ie
 	}
 	return ieee754sp_format(zs, ze, zm);
 }
+
+union ieee754sp ieee754sp_maddf(union ieee754sp z, union ieee754sp x,
+				union ieee754sp y)
+{
+	return _sp_maddf(z, x, y, 0);
+}
+
+union ieee754sp ieee754sp_msubf(union ieee754sp z, union ieee754sp x,
+				union ieee754sp y)
+{
+	return _sp_maddf(z, x, y, maddf_negate_product);
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/math-emu/sp_msubf.c linux-libre-4.7-gnu/arch/mips/math-emu/sp_msubf.c
--- linux-libre-4.6-gnu/arch/mips/math-emu/sp_msubf.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/math-emu/sp_msubf.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,258 +0,0 @@
-/*
- * IEEE754 floating point arithmetic
- * single precision: MSUB.f (Fused Multiply Subtract)
- * MSUBF.fmt: FPR[fd] = FPR[fd] - (FPR[fs] x FPR[ft])
- *
- * MIPS floating point support
- * Copyright (C) 2015 Imagination Technologies, Ltd.
- * Author: Markos Chandras <markos.chandras@imgtec.com>
- *
- *  This program is free software; you can distribute 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.
- */
-
-#include "ieee754sp.h"
-
-union ieee754sp ieee754sp_msubf(union ieee754sp z, union ieee754sp x,
-				union ieee754sp y)
-{
-	int re;
-	int rs;
-	unsigned rm;
-	unsigned short lxm;
-	unsigned short hxm;
-	unsigned short lym;
-	unsigned short hym;
-	unsigned lrm;
-	unsigned hrm;
-	unsigned t;
-	unsigned at;
-	int s;
-
-	COMPXSP;
-	COMPYSP;
-	u32 zm; int ze; int zs __maybe_unused; int zc;
-
-	EXPLODEXSP;
-	EXPLODEYSP;
-	EXPLODESP(z, zc, zs, ze, zm)
-
-	FLUSHXSP;
-	FLUSHYSP;
-	FLUSHSP(z, zc, zs, ze, zm);
-
-	ieee754_clearcx();
-
-	switch (zc) {
-	case IEEE754_CLASS_SNAN:
-		ieee754_setcx(IEEE754_INVALID_OPERATION);
-		return ieee754sp_nanxcpt(z);
-	case IEEE754_CLASS_DNORM:
-		SPDNORMx(zm, ze);
-	/* QNAN is handled separately below */
-	}
-
-	switch (CLPAIR(xc, yc)) {
-	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
-	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
-	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
-	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
-	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
-		return ieee754sp_nanxcpt(y);
-
-	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
-	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
-	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
-	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
-	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
-	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
-		return ieee754sp_nanxcpt(x);
-
-	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
-	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
-	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
-	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
-		return y;
-
-	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
-	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
-	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
-	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
-	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
-		return x;
-
-	/*
-	 * Infinity handling
-	 */
-	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
-	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
-		if (zc == IEEE754_CLASS_QNAN)
-			return z;
-		ieee754_setcx(IEEE754_INVALID_OPERATION);
-		return ieee754sp_indef();
-
-	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
-	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
-	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
-	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
-	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
-		if (zc == IEEE754_CLASS_QNAN)
-			return z;
-		return ieee754sp_inf(xs ^ ys);
-
-	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
-	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
-	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
-	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
-	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
-		if (zc == IEEE754_CLASS_INF)
-			return ieee754sp_inf(zs);
-		/* Multiplication is 0 so just return z */
-		return z;
-
-	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
-		SPDNORMX;
-
-	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
-		if (zc == IEEE754_CLASS_QNAN)
-			return z;
-		else if (zc == IEEE754_CLASS_INF)
-			return ieee754sp_inf(zs);
-		SPDNORMY;
-		break;
-
-	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
-		if (zc == IEEE754_CLASS_QNAN)
-			return z;
-		else if (zc == IEEE754_CLASS_INF)
-			return ieee754sp_inf(zs);
-		SPDNORMX;
-		break;
-
-	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
-		if (zc == IEEE754_CLASS_QNAN)
-			return z;
-		else if (zc == IEEE754_CLASS_INF)
-			return ieee754sp_inf(zs);
-		/* fall through to real compuation */
-	}
-
-	/* Finally get to do some computation */
-
-	/*
-	 * Do the multiplication bit first
-	 *
-	 * rm = xm * ym, re = xe + ye basically
-	 *
-	 * At this point xm and ym should have been normalized.
-	 */
-
-	/* rm = xm * ym, re = xe+ye basically */
-	assert(xm & SP_HIDDEN_BIT);
-	assert(ym & SP_HIDDEN_BIT);
-
-	re = xe + ye;
-	rs = xs ^ ys;
-
-	/* shunt to top of word */
-	xm <<= 32 - (SP_FBITS + 1);
-	ym <<= 32 - (SP_FBITS + 1);
-
-	/*
-	 * Multiply 32 bits xm, ym to give high 32 bits rm with stickness.
-	 */
-	lxm = xm & 0xffff;
-	hxm = xm >> 16;
-	lym = ym & 0xffff;
-	hym = ym >> 16;
-
-	lrm = lxm * lym;	/* 16 * 16 => 32 */
-	hrm = hxm * hym;	/* 16 * 16 => 32 */
-
-	t = lxm * hym; /* 16 * 16 => 32 */
-	at = lrm + (t << 16);
-	hrm += at < lrm;
-	lrm = at;
-	hrm = hrm + (t >> 16);
-
-	t = hxm * lym; /* 16 * 16 => 32 */
-	at = lrm + (t << 16);
-	hrm += at < lrm;
-	lrm = at;
-	hrm = hrm + (t >> 16);
-
-	rm = hrm | (lrm != 0);
-
-	/*
-	 * Sticky shift down to normal rounding precision.
-	 */
-	if ((int) rm < 0) {
-		rm = (rm >> (32 - (SP_FBITS + 1 + 3))) |
-		    ((rm << (SP_FBITS + 1 + 3)) != 0);
-		re++;
-	} else {
-		rm = (rm >> (32 - (SP_FBITS + 1 + 3 + 1))) |
-		     ((rm << (SP_FBITS + 1 + 3 + 1)) != 0);
-	}
-	assert(rm & (SP_HIDDEN_BIT << 3));
-
-	/* And now the subtraction */
-
-	/* Flip sign of r and handle as add */
-	rs ^= 1;
-
-	assert(zm & SP_HIDDEN_BIT);
-
-	/*
-	 * Provide guard,round and stick bit space.
-	 */
-	zm <<= 3;
-
-	if (ze > re) {
-		/*
-		 * Have to shift y fraction right to align.
-		 */
-		s = ze - re;
-		SPXSRSYn(s);
-	} else if (re > ze) {
-		/*
-		 * Have to shift x fraction right to align.
-		 */
-		s = re - ze;
-		SPXSRSYn(s);
-	}
-	assert(ze == re);
-	assert(ze <= SP_EMAX);
-
-	if (zs == rs) {
-		/*
-		 * Generate 28 bit result of adding two 27 bit numbers
-		 * leaving result in zm, zs and ze.
-		 */
-		zm = zm + rm;
-
-		if (zm >> (SP_FBITS + 1 + 3)) { /* carry out */
-			SPXSRSX1(); /* shift preserving sticky */
-		}
-	} else {
-		if (zm >= rm) {
-			zm = zm - rm;
-		} else {
-			zm = rm - zm;
-			zs = rs;
-		}
-		if (zm == 0)
-			return ieee754sp_zero(ieee754_csr.rm == FPU_CSR_RD);
-
-		/*
-		 * Normalize in extended single precision
-		 */
-		while ((zm >> (SP_MBITS + 3)) == 0) {
-			zm <<= 1;
-			ze--;
-		}
-
-	}
-	return ieee754sp_format(zs, ze, zm);
-}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/math-emu/sp_sub.c linux-libre-4.7-gnu/arch/mips/math-emu/sp_sub.c
--- linux-libre-4.6-gnu/arch/mips/math-emu/sp_sub.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/math-emu/sp_sub.c	2016-07-24 15:23:50.000000000 -0400
@@ -134,13 +134,15 @@ union ieee754sp ieee754sp_sub(union ieee
 		 * have to shift y fraction right to align
 		 */
 		s = xe - ye;
-		SPXSRSYn(s);
+		ym = XSPSRS(ym, s);
+		ye += s;
 	} else if (ye > xe) {
 		/*
 		 * have to shift x fraction right to align
 		 */
 		s = ye - xe;
-		SPXSRSXn(s);
+		xm = XSPSRS(xm, s);
+		xe += s;
 	}
 	assert(xe == ye);
 	assert(xe <= SP_EMAX);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/mm/cache.c linux-libre-4.7-gnu/arch/mips/mm/cache.c
--- linux-libre-4.6-gnu/arch/mips/mm/cache.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/mm/cache.c	2016-07-24 15:23:50.000000000 -0400
@@ -16,6 +16,7 @@
 #include <linux/mm.h>
 
 #include <asm/cacheflush.h>
+#include <asm/highmem.h>
 #include <asm/processor.h>
 #include <asm/cpu.h>
 #include <asm/cpu-features.h>
@@ -83,8 +84,6 @@ void __flush_dcache_page(struct page *pa
 	struct address_space *mapping = page_mapping(page);
 	unsigned long addr;
 
-	if (PageHighMem(page))
-		return;
 	if (mapping && !mapping_mapped(mapping)) {
 		SetPageDcacheDirty(page);
 		return;
@@ -95,8 +94,15 @@ void __flush_dcache_page(struct page *pa
 	 * case is for exec env/arg pages and those are %99 certainly going to
 	 * get faulted into the tlb (and thus flushed) anyways.
 	 */
-	addr = (unsigned long) page_address(page);
+	if (PageHighMem(page))
+		addr = (unsigned long)kmap_atomic(page);
+	else
+		addr = (unsigned long)page_address(page);
+
 	flush_data_cache_page(addr);
+
+	if (PageHighMem(page))
+		__kunmap_atomic((void *)addr);
 }
 
 EXPORT_SYMBOL(__flush_dcache_page);
@@ -119,33 +125,28 @@ void __flush_anon_page(struct page *page
 
 EXPORT_SYMBOL(__flush_anon_page);
 
-void __flush_icache_page(struct vm_area_struct *vma, struct page *page)
-{
-	unsigned long addr;
-
-	if (PageHighMem(page))
-		return;
-
-	addr = (unsigned long) page_address(page);
-	flush_data_cache_page(addr);
-}
-EXPORT_SYMBOL_GPL(__flush_icache_page);
-
-void __update_cache(struct vm_area_struct *vma, unsigned long address,
-	pte_t pte)
+void __update_cache(unsigned long address, pte_t pte)
 {
 	struct page *page;
 	unsigned long pfn, addr;
-	int exec = (vma->vm_flags & VM_EXEC) && !cpu_has_ic_fills_f_dc;
+	int exec = !pte_no_exec(pte) && !cpu_has_ic_fills_f_dc;
 
 	pfn = pte_pfn(pte);
 	if (unlikely(!pfn_valid(pfn)))
 		return;
 	page = pfn_to_page(pfn);
-	if (page_mapping(page) && Page_dcache_dirty(page)) {
-		addr = (unsigned long) page_address(page);
+	if (Page_dcache_dirty(page)) {
+		if (PageHighMem(page))
+			addr = (unsigned long)kmap_atomic(page);
+		else
+			addr = (unsigned long)page_address(page);
+
 		if (exec || pages_do_alias(addr, address & PAGE_MASK))
 			flush_data_cache_page(addr);
+
+		if (PageHighMem(page))
+			__kunmap_atomic((void *)addr);
+
 		ClearPageDcacheDirty(page);
 	}
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/mm/c-r4k.c linux-libre-4.7-gnu/arch/mips/mm/c-r4k.c
--- linux-libre-4.6-gnu/arch/mips/mm/c-r4k.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/mm/c-r4k.c	2016-07-24 15:23:50.000000000 -0400
@@ -77,6 +77,7 @@ static inline void r4k_on_each_cpu(void
  */
 static unsigned long icache_size __read_mostly;
 static unsigned long dcache_size __read_mostly;
+static unsigned long vcache_size __read_mostly;
 static unsigned long scache_size __read_mostly;
 
 /*
@@ -447,6 +448,11 @@ static inline void local_r4k___flush_cac
 		r4k_blast_scache();
 		break;
 
+	case CPU_BMIPS5000:
+		r4k_blast_scache();
+		__sync();
+		break;
+
 	default:
 		r4k_blast_dcache();
 		r4k_blast_icache();
@@ -492,7 +498,14 @@ static inline void local_r4k_flush_cache
 	if (!(has_valid_asid(vma->vm_mm)))
 		return;
 
-	r4k_blast_dcache();
+	/*
+	 * If dcache can alias, we must blast it since mapping is changing.
+	 * If executable, we must ensure any dirty lines are written back far
+	 * enough to be visible to icache.
+	 */
+	if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc))
+		r4k_blast_dcache();
+	/* If executable, blast stale lines from icache */
 	if (exec)
 		r4k_blast_icache();
 }
@@ -502,7 +515,7 @@ static void r4k_flush_cache_range(struct
 {
 	int exec = vma->vm_flags & VM_EXEC;
 
-	if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc))
+	if (cpu_has_dc_aliases || exec)
 		r4k_on_each_cpu(local_r4k_flush_cache_range, vma);
 }
 
@@ -1148,6 +1161,8 @@ static void probe_pcache(void)
 					  c->dcache.ways *
 					  c->dcache.linesz;
 		c->dcache.waybit = 0;
+		if ((prid & PRID_REV_MASK) >= PRID_REV_LOONGSON3A_R2)
+			c->options |= MIPS_CPU_PREFETCH;
 		break;
 
 	case CPU_CAVIUM_OCTEON3:
@@ -1278,6 +1293,8 @@ static void probe_pcache(void)
 	case CPU_M5150:
 	case CPU_QEMU_GENERIC:
 	case CPU_I6400:
+	case CPU_P6600:
+	case CPU_M6250:
 		if (!(read_c0_config7() & MIPS_CONF7_IAR) &&
 		    (c->icache.waysize > PAGE_SIZE))
 			c->icache.flags |= MIPS_CACHE_ALIASES;
@@ -1304,9 +1321,16 @@ static void probe_pcache(void)
 		break;
 
 	case CPU_ALCHEMY:
+	case CPU_I6400:
 		c->icache.flags |= MIPS_CACHE_IC_F_DC;
 		break;
 
+	case CPU_BMIPS5000:
+		c->icache.flags |= MIPS_CACHE_IC_F_DC;
+		/* Cache aliases are handled in hardware; allow HIGHMEM */
+		c->dcache.flags &= ~MIPS_CACHE_ALIASES;
+		break;
+
 	case CPU_LOONGSON2:
 		/*
 		 * LOONGSON2 has 4 way icache, but when using indexed cache op,
@@ -1328,6 +1352,31 @@ static void probe_pcache(void)
 	       c->dcache.linesz);
 }
 
+static void probe_vcache(void)
+{
+	struct cpuinfo_mips *c = &current_cpu_data;
+	unsigned int config2, lsize;
+
+	if (current_cpu_type() != CPU_LOONGSON3)
+		return;
+
+	config2 = read_c0_config2();
+	if ((lsize = ((config2 >> 20) & 15)))
+		c->vcache.linesz = 2 << lsize;
+	else
+		c->vcache.linesz = lsize;
+
+	c->vcache.sets = 64 << ((config2 >> 24) & 15);
+	c->vcache.ways = 1 + ((config2 >> 16) & 15);
+
+	vcache_size = c->vcache.sets * c->vcache.ways * c->vcache.linesz;
+
+	c->vcache.waybit = 0;
+
+	pr_info("Unified victim cache %ldkB %s, linesize %d bytes.\n",
+		vcache_size >> 10, way_string[c->vcache.ways], c->vcache.linesz);
+}
+
 /*
  * If you even _breathe_ on this function, look at the gcc output and make sure
  * it does not pop things on and off the stack for the cache sizing loop that
@@ -1650,6 +1699,7 @@ void r4k_cache_init(void)
 	struct cpuinfo_mips *c = &current_cpu_data;
 
 	probe_pcache();
+	probe_vcache();
 	setup_scache();
 
 	r4k_blast_dcache_page_setup();
@@ -1671,7 +1721,7 @@ void r4k_cache_init(void)
 	 * This code supports virtually indexed processors and will be
 	 * unnecessarily inefficient on physically indexed processors.
 	 */
-	if (c->dcache.linesz)
+	if (c->dcache.linesz && cpu_has_dc_aliases)
 		shm_align_mask = max_t( unsigned long,
 					c->dcache.sets * c->dcache.linesz - 1,
 					PAGE_SIZE - 1);
@@ -1744,12 +1794,24 @@ void r4k_cache_init(void)
 		flush_icache_range = (void *)b5k_instruction_hazard;
 		local_flush_icache_range = (void *)b5k_instruction_hazard;
 
-		/* Cache aliases are handled in hardware; allow HIGHMEM */
-		current_cpu_data.dcache.flags &= ~MIPS_CACHE_ALIASES;
 
 		/* Optimization: an L2 flush implicitly flushes the L1 */
 		current_cpu_data.options |= MIPS_CPU_INCLUSIVE_CACHES;
 		break;
+	case CPU_LOONGSON3:
+		/* Loongson-3 maintains cache coherency by hardware */
+		__flush_cache_all	= cache_noop;
+		__flush_cache_vmap	= cache_noop;
+		__flush_cache_vunmap	= cache_noop;
+		__flush_kernel_vmap_range = (void *)cache_noop;
+		flush_cache_mm		= (void *)cache_noop;
+		flush_cache_page	= (void *)cache_noop;
+		flush_cache_range	= (void *)cache_noop;
+		flush_cache_sigtramp	= (void *)cache_noop;
+		flush_icache_all	= (void *)cache_noop;
+		flush_data_cache_page	= (void *)cache_noop;
+		local_flush_data_cache_page	= (void *)cache_noop;
+		break;
 	}
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/mm/dma-default.c linux-libre-4.7-gnu/arch/mips/mm/dma-default.c
--- linux-libre-4.6-gnu/arch/mips/mm/dma-default.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/mm/dma-default.c	2016-07-24 15:23:50.000000000 -0400
@@ -88,19 +88,20 @@ static gfp_t massage_gfp_flags(const str
 	else
 #endif
 #if defined(CONFIG_ZONE_DMA32) && defined(CONFIG_ZONE_DMA)
-	     if (dev->coherent_dma_mask < DMA_BIT_MASK(32))
+	     if (dev == NULL || dev->coherent_dma_mask < DMA_BIT_MASK(32))
 			dma_flag = __GFP_DMA;
 	else if (dev->coherent_dma_mask < DMA_BIT_MASK(64))
 			dma_flag = __GFP_DMA32;
 	else
 #endif
 #if defined(CONFIG_ZONE_DMA32) && !defined(CONFIG_ZONE_DMA)
-	     if (dev->coherent_dma_mask < DMA_BIT_MASK(64))
+	     if (dev == NULL || dev->coherent_dma_mask < DMA_BIT_MASK(64))
 		dma_flag = __GFP_DMA32;
 	else
 #endif
 #if defined(CONFIG_ZONE_DMA) && !defined(CONFIG_ZONE_DMA32)
-	     if (dev->coherent_dma_mask < DMA_BIT_MASK(sizeof(phys_addr_t) * 8))
+	     if (dev == NULL ||
+		 dev->coherent_dma_mask < DMA_BIT_MASK(sizeof(phys_addr_t) * 8))
 		dma_flag = __GFP_DMA;
 	else
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/mm/init.c linux-libre-4.7-gnu/arch/mips/mm/init.c
--- linux-libre-4.6-gnu/arch/mips/mm/init.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/mm/init.c	2016-07-24 15:23:50.000000000 -0400
@@ -98,8 +98,10 @@ static void *__kmap_pgprot(struct page *
 	idx += in_interrupt() ? FIX_N_COLOURS : 0;
 	vaddr = __fix_to_virt(FIX_CMAP_END - idx);
 	pte = mk_pte(page, prot);
-#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)
+#if defined(CONFIG_XPA)
 	entrylo = pte_to_entrylo(pte.pte_high);
+#elif defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)
+	entrylo = pte.pte_high;
 #else
 	entrylo = pte_to_entrylo(pte_val(pte));
 #endif
@@ -110,9 +112,11 @@ static void *__kmap_pgprot(struct page *
 	write_c0_entrylo0(entrylo);
 	write_c0_entrylo1(entrylo);
 #ifdef CONFIG_XPA
-	entrylo = (pte.pte_low & _PFNX_MASK);
-	writex_c0_entrylo0(entrylo);
-	writex_c0_entrylo1(entrylo);
+	if (cpu_has_xpa) {
+		entrylo = (pte.pte_low & _PFNX_MASK);
+		writex_c0_entrylo0(entrylo);
+		writex_c0_entrylo1(entrylo);
+	}
 #endif
 	tlbidx = read_c0_wired();
 	write_c0_wired(tlbidx + 1);
@@ -196,7 +200,7 @@ void copy_to_user_page(struct vm_area_st
 		if (cpu_has_dc_aliases)
 			SetPageDcacheDirty(page);
 	}
-	if ((vma->vm_flags & VM_EXEC) && !cpu_has_ic_fills_f_dc)
+	if (vma->vm_flags & VM_EXEC)
 		flush_cache_page(vma, vaddr, page_to_pfn(page));
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/mm/page.c linux-libre-4.7-gnu/arch/mips/mm/page.c
--- linux-libre-4.6-gnu/arch/mips/mm/page.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/mm/page.c	2016-07-24 15:23:50.000000000 -0400
@@ -188,6 +188,15 @@ static void set_prefetch_parameters(void
 			}
 			break;
 
+		case CPU_LOONGSON3:
+			/* Loongson-3 only support the Pref_Load/Pref_Store. */
+			pref_bias_clear_store = 128;
+			pref_bias_copy_load = 128;
+			pref_bias_copy_store = 128;
+			pref_src_mode = Pref_Load;
+			pref_dst_mode = Pref_Store;
+			break;
+
 		default:
 			pref_bias_clear_store = 128;
 			pref_bias_copy_load = 256;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/mm/sc-mips.c linux-libre-4.7-gnu/arch/mips/mm/sc-mips.c
--- linux-libre-4.6-gnu/arch/mips/mm/sc-mips.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/mm/sc-mips.c	2016-07-24 15:23:50.000000000 -0400
@@ -141,6 +141,7 @@ static inline int mips_sc_is_activated(s
 	case CPU_P5600:
 	case CPU_BMIPS5000:
 	case CPU_QEMU_GENERIC:
+	case CPU_P6600:
 		if (config2 & (1 << 12))
 			return 0;
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/mm/tlbex.c linux-libre-4.7-gnu/arch/mips/mm/tlbex.c
--- linux-libre-4.6-gnu/arch/mips/mm/tlbex.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/mm/tlbex.c	2016-07-24 15:23:50.000000000 -0400
@@ -234,20 +234,16 @@ static void output_pgtable_bits_defines(
 	pr_debug("\n");
 
 	pr_define("_PAGE_PRESENT_SHIFT %d\n", _PAGE_PRESENT_SHIFT);
-	pr_define("_PAGE_READ_SHIFT %d\n", _PAGE_READ_SHIFT);
+	pr_define("_PAGE_NO_READ_SHIFT %d\n", _PAGE_NO_READ_SHIFT);
 	pr_define("_PAGE_WRITE_SHIFT %d\n", _PAGE_WRITE_SHIFT);
 	pr_define("_PAGE_ACCESSED_SHIFT %d\n", _PAGE_ACCESSED_SHIFT);
 	pr_define("_PAGE_MODIFIED_SHIFT %d\n", _PAGE_MODIFIED_SHIFT);
 #ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
 	pr_define("_PAGE_HUGE_SHIFT %d\n", _PAGE_HUGE_SHIFT);
 #endif
-#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
-	if (cpu_has_rixi) {
 #ifdef _PAGE_NO_EXEC_SHIFT
+	if (cpu_has_rixi)
 		pr_define("_PAGE_NO_EXEC_SHIFT %d\n", _PAGE_NO_EXEC_SHIFT);
-		pr_define("_PAGE_NO_READ_SHIFT %d\n", _PAGE_NO_READ_SHIFT);
-#endif
-	}
 #endif
 	pr_define("_PAGE_GLOBAL_SHIFT %d\n", _PAGE_GLOBAL_SHIFT);
 	pr_define("_PAGE_VALID_SHIFT %d\n", _PAGE_VALID_SHIFT);
@@ -284,7 +280,12 @@ static inline void dump_handler(const ch
 #define C0_ENTRYLO1	3, 0
 #define C0_CONTEXT	4, 0
 #define C0_PAGEMASK	5, 0
+#define C0_PWBASE	5, 5
+#define C0_PWFIELD	5, 6
+#define C0_PWSIZE	5, 7
+#define C0_PWCTL	6, 6
 #define C0_BADVADDR	8, 0
+#define C0_PGD		9, 7
 #define C0_ENTRYHI	10, 0
 #define C0_EPC		14, 0
 #define C0_XCONTEXT	20, 0
@@ -630,6 +631,11 @@ static void build_tlb_write_entry(u32 **
 static __maybe_unused void build_convert_pte_to_entrylo(u32 **p,
 							unsigned int reg)
 {
+	if (_PAGE_GLOBAL_SHIFT == 0) {
+		/* pte_t is already in EntryLo format */
+		return;
+	}
+
 	if (cpu_has_rixi && _PAGE_NO_EXEC) {
 		if (fill_includes_sw_bits) {
 			UASM_i_ROTR(p, reg, reg, ilog2(_PAGE_GLOBAL));
@@ -808,7 +814,10 @@ build_get_pmde64(u32 **p, struct uasm_la
 
 	if (pgd_reg != -1) {
 		/* pgd is in pgd_reg */
-		UASM_i_MFC0(p, ptr, c0_kscratch(), pgd_reg);
+		if (cpu_has_ldpte)
+			UASM_i_MFC0(p, ptr, C0_PWBASE);
+		else
+			UASM_i_MFC0(p, ptr, c0_kscratch(), pgd_reg);
 	} else {
 #if defined(CONFIG_MIPS_PGD_C0_CONTEXT)
 		/*
@@ -1007,39 +1016,40 @@ static void build_get_ptep(u32 **p, unsi
 
 static void build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep)
 {
-	/*
-	 * 64bit address support (36bit on a 32bit CPU) in a 32bit
-	 * Kernel is a special case. Only a few CPUs use it.
-	 */
-	if (config_enabled(CONFIG_PHYS_ADDR_T_64BIT) && !cpu_has_64bits) {
-		int pte_off_even = sizeof(pte_t) / 2;
-		int pte_off_odd = pte_off_even + sizeof(pte_t);
-#ifdef CONFIG_XPA
-		const int scratch = 1; /* Our extra working register */
+	int pte_off_even = 0;
+	int pte_off_odd = sizeof(pte_t);
 
-		uasm_i_addu(p, scratch, 0, ptep);
+#if defined(CONFIG_CPU_MIPS32) && defined(CONFIG_PHYS_ADDR_T_64BIT)
+	/* The low 32 bits of EntryLo is stored in pte_high */
+	pte_off_even += offsetof(pte_t, pte_high);
+	pte_off_odd += offsetof(pte_t, pte_high);
 #endif
+
+	if (config_enabled(CONFIG_XPA)) {
 		uasm_i_lw(p, tmp, pte_off_even, ptep); /* even pte */
-		uasm_i_lw(p, ptep, pte_off_odd, ptep); /* odd pte */
 		UASM_i_ROTR(p, tmp, tmp, ilog2(_PAGE_GLOBAL));
-		UASM_i_ROTR(p, ptep, ptep, ilog2(_PAGE_GLOBAL));
 		UASM_i_MTC0(p, tmp, C0_ENTRYLO0);
-		UASM_i_MTC0(p, ptep, C0_ENTRYLO1);
-#ifdef CONFIG_XPA
-		uasm_i_lw(p, tmp, 0, scratch);
-		uasm_i_lw(p, ptep, sizeof(pte_t), scratch);
-		uasm_i_lui(p, scratch, 0xff);
-		uasm_i_ori(p, scratch, scratch, 0xffff);
-		uasm_i_and(p, tmp, scratch, tmp);
-		uasm_i_and(p, ptep, scratch, ptep);
-		uasm_i_mthc0(p, tmp, C0_ENTRYLO0);
-		uasm_i_mthc0(p, ptep, C0_ENTRYLO1);
-#endif
+
+		if (cpu_has_xpa && !mips_xpa_disabled) {
+			uasm_i_lw(p, tmp, 0, ptep);
+			uasm_i_ext(p, tmp, tmp, 0, 24);
+			uasm_i_mthc0(p, tmp, C0_ENTRYLO0);
+		}
+
+		uasm_i_lw(p, tmp, pte_off_odd, ptep); /* odd pte */
+		UASM_i_ROTR(p, tmp, tmp, ilog2(_PAGE_GLOBAL));
+		UASM_i_MTC0(p, tmp, C0_ENTRYLO1);
+
+		if (cpu_has_xpa && !mips_xpa_disabled) {
+			uasm_i_lw(p, tmp, sizeof(pte_t), ptep);
+			uasm_i_ext(p, tmp, tmp, 0, 24);
+			uasm_i_mthc0(p, tmp, C0_ENTRYLO1);
+		}
 		return;
 	}
 
-	UASM_i_LW(p, tmp, 0, ptep); /* get even pte */
-	UASM_i_LW(p, ptep, sizeof(pte_t), ptep); /* get odd pte */
+	UASM_i_LW(p, tmp, pte_off_even, ptep); /* get even pte */
+	UASM_i_LW(p, ptep, pte_off_odd, ptep); /* get odd pte */
 	if (r45k_bvahwbug())
 		build_tlb_probe_entry(p);
 	build_convert_pte_to_entrylo(p, tmp);
@@ -1421,6 +1431,108 @@ static void build_r4000_tlb_refill_handl
 	dump_handler("r4000_tlb_refill", (u32 *)ebase, 64);
 }
 
+static void setup_pw(void)
+{
+	unsigned long pgd_i, pgd_w;
+#ifndef __PAGETABLE_PMD_FOLDED
+	unsigned long pmd_i, pmd_w;
+#endif
+	unsigned long pt_i, pt_w;
+	unsigned long pte_i, pte_w;
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
+	unsigned long psn;
+
+	psn = ilog2(_PAGE_HUGE);     /* bit used to indicate huge page */
+#endif
+	pgd_i = PGDIR_SHIFT;  /* 1st level PGD */
+#ifndef __PAGETABLE_PMD_FOLDED
+	pgd_w = PGDIR_SHIFT - PMD_SHIFT + PGD_ORDER;
+
+	pmd_i = PMD_SHIFT;    /* 2nd level PMD */
+	pmd_w = PMD_SHIFT - PAGE_SHIFT;
+#else
+	pgd_w = PGDIR_SHIFT - PAGE_SHIFT + PGD_ORDER;
+#endif
+
+	pt_i  = PAGE_SHIFT;    /* 3rd level PTE */
+	pt_w  = PAGE_SHIFT - 3;
+
+	pte_i = ilog2(_PAGE_GLOBAL);
+	pte_w = 0;
+
+#ifndef __PAGETABLE_PMD_FOLDED
+	write_c0_pwfield(pgd_i << 24 | pmd_i << 12 | pt_i << 6 | pte_i);
+	write_c0_pwsize(1 << 30 | pgd_w << 24 | pmd_w << 12 | pt_w << 6 | pte_w);
+#else
+	write_c0_pwfield(pgd_i << 24 | pt_i << 6 | pte_i);
+	write_c0_pwsize(1 << 30 | pgd_w << 24 | pt_w << 6 | pte_w);
+#endif
+
+#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
+	write_c0_pwctl(1 << 6 | psn);
+#endif
+	write_c0_kpgd(swapper_pg_dir);
+	kscratch_used_mask |= (1 << 7); /* KScratch6 is used for KPGD */
+}
+
+static void build_loongson3_tlb_refill_handler(void)
+{
+	u32 *p = tlb_handler;
+	struct uasm_label *l = labels;
+	struct uasm_reloc *r = relocs;
+
+	memset(labels, 0, sizeof(labels));
+	memset(relocs, 0, sizeof(relocs));
+	memset(tlb_handler, 0, sizeof(tlb_handler));
+
+	if (check_for_high_segbits) {
+		uasm_i_dmfc0(&p, K0, C0_BADVADDR);
+		uasm_i_dsrl_safe(&p, K1, K0, PGDIR_SHIFT + PGD_ORDER + PAGE_SHIFT - 3);
+		uasm_il_beqz(&p, &r, K1, label_vmalloc);
+		uasm_i_nop(&p);
+
+		uasm_il_bgez(&p, &r, K0, label_large_segbits_fault);
+		uasm_i_nop(&p);
+		uasm_l_vmalloc(&l, p);
+	}
+
+	uasm_i_dmfc0(&p, K1, C0_PGD);
+
+	uasm_i_lddir(&p, K0, K1, 3);  /* global page dir */
+#ifndef __PAGETABLE_PMD_FOLDED
+	uasm_i_lddir(&p, K1, K0, 1);  /* middle page dir */
+#endif
+	uasm_i_ldpte(&p, K1, 0);      /* even */
+	uasm_i_ldpte(&p, K1, 1);      /* odd */
+	uasm_i_tlbwr(&p);
+
+	/* restore page mask */
+	if (PM_DEFAULT_MASK >> 16) {
+		uasm_i_lui(&p, K0, PM_DEFAULT_MASK >> 16);
+		uasm_i_ori(&p, K0, K0, PM_DEFAULT_MASK & 0xffff);
+		uasm_i_mtc0(&p, K0, C0_PAGEMASK);
+	} else if (PM_DEFAULT_MASK) {
+		uasm_i_ori(&p, K0, 0, PM_DEFAULT_MASK);
+		uasm_i_mtc0(&p, K0, C0_PAGEMASK);
+	} else {
+		uasm_i_mtc0(&p, 0, C0_PAGEMASK);
+	}
+
+	uasm_i_eret(&p);
+
+	if (check_for_high_segbits) {
+		uasm_l_large_segbits_fault(&l, p);
+		UASM_i_LA(&p, K1, (unsigned long)tlb_do_page_fault_0);
+		uasm_i_jr(&p, K1);
+		uasm_i_nop(&p);
+	}
+
+	uasm_resolve_relocs(relocs, labels);
+	memcpy((void *)(ebase + 0x80), tlb_handler, 0x80);
+	local_flush_icache_range(ebase + 0x80, ebase + 0x100);
+	dump_handler("loongson3_tlb_refill", (u32 *)(ebase + 0x80), 32);
+}
+
 extern u32 handle_tlbl[], handle_tlbl_end[];
 extern u32 handle_tlbs[], handle_tlbs_end[];
 extern u32 handle_tlbm[], handle_tlbm_end[];
@@ -1468,7 +1580,10 @@ static void build_setup_pgd(void)
 	} else {
 		/* PGD in c0_KScratch */
 		uasm_i_jr(&p, 31);
-		UASM_i_MTC0(&p, a0, c0_kscratch(), pgd_reg);
+		if (cpu_has_ldpte)
+			UASM_i_MTC0(&p, a0, C0_PWBASE);
+		else
+			UASM_i_MTC0(&p, a0, c0_kscratch(), pgd_reg);
 	}
 #else
 #ifdef CONFIG_SMP
@@ -1523,19 +1638,19 @@ iPTE_LW(u32 **p, unsigned int pte, unsig
 
 static void
 iPTE_SW(u32 **p, struct uasm_reloc **r, unsigned int pte, unsigned int ptr,
-	unsigned int mode)
+	unsigned int mode, unsigned int scratch)
 {
-#ifdef CONFIG_PHYS_ADDR_T_64BIT
 	unsigned int hwmode = mode & (_PAGE_VALID | _PAGE_DIRTY);
+	unsigned int swmode = mode & ~hwmode;
 
-	if (!cpu_has_64bits) {
-		const int scratch = 1; /* Our extra working register */
-
-		uasm_i_lui(p, scratch, (mode >> 16));
+	if (config_enabled(CONFIG_XPA) && !cpu_has_64bits) {
+		uasm_i_lui(p, scratch, swmode >> 16);
 		uasm_i_or(p, pte, pte, scratch);
-	} else
-#endif
-	uasm_i_ori(p, pte, pte, mode);
+		BUG_ON(swmode & 0xffff);
+	} else {
+		uasm_i_ori(p, pte, pte, mode);
+	}
+
 #ifdef CONFIG_SMP
 # ifdef CONFIG_PHYS_ADDR_T_64BIT
 	if (cpu_has_64bits)
@@ -1554,6 +1669,7 @@ iPTE_SW(u32 **p, struct uasm_reloc **r,
 		/* no uasm_i_nop needed */
 		uasm_i_ll(p, pte, sizeof(pte_t) / 2, ptr);
 		uasm_i_ori(p, pte, pte, hwmode);
+		BUG_ON(hwmode & ~0xffff);
 		uasm_i_sc(p, pte, sizeof(pte_t) / 2, ptr);
 		uasm_il_beqz(p, r, pte, label_smp_pgtable_change);
 		/* no uasm_i_nop needed */
@@ -1575,6 +1691,7 @@ iPTE_SW(u32 **p, struct uasm_reloc **r,
 	if (!cpu_has_64bits) {
 		uasm_i_lw(p, pte, sizeof(pte_t) / 2, ptr);
 		uasm_i_ori(p, pte, pte, hwmode);
+		BUG_ON(hwmode & ~0xffff);
 		uasm_i_sw(p, pte, sizeof(pte_t) / 2, ptr);
 		uasm_i_lw(p, pte, 0, ptr);
 	}
@@ -1615,9 +1732,8 @@ build_pte_present(u32 **p, struct uasm_r
 			cur = t;
 		}
 		uasm_i_andi(p, t, cur,
-			(_PAGE_PRESENT | _PAGE_READ) >> _PAGE_PRESENT_SHIFT);
-		uasm_i_xori(p, t, t,
-			(_PAGE_PRESENT | _PAGE_READ) >> _PAGE_PRESENT_SHIFT);
+			(_PAGE_PRESENT | _PAGE_NO_READ) >> _PAGE_PRESENT_SHIFT);
+		uasm_i_xori(p, t, t, _PAGE_PRESENT >> _PAGE_PRESENT_SHIFT);
 		uasm_il_bnez(p, r, t, lid);
 		if (pte == t)
 			/* You lose the SMP race :-(*/
@@ -1628,11 +1744,11 @@ build_pte_present(u32 **p, struct uasm_r
 /* Make PTE valid, store result in PTR. */
 static void
 build_make_valid(u32 **p, struct uasm_reloc **r, unsigned int pte,
-		 unsigned int ptr)
+		 unsigned int ptr, unsigned int scratch)
 {
 	unsigned int mode = _PAGE_VALID | _PAGE_ACCESSED;
 
-	iPTE_SW(p, r, pte, ptr, mode);
+	iPTE_SW(p, r, pte, ptr, mode, scratch);
 }
 
 /*
@@ -1668,12 +1784,12 @@ build_pte_writable(u32 **p, struct uasm_
  */
 static void
 build_make_write(u32 **p, struct uasm_reloc **r, unsigned int pte,
-		 unsigned int ptr)
+		 unsigned int ptr, unsigned int scratch)
 {
 	unsigned int mode = (_PAGE_ACCESSED | _PAGE_MODIFIED | _PAGE_VALID
 			     | _PAGE_DIRTY);
 
-	iPTE_SW(p, r, pte, ptr, mode);
+	iPTE_SW(p, r, pte, ptr, mode, scratch);
 }
 
 /*
@@ -1778,7 +1894,7 @@ static void build_r3000_tlb_load_handler
 	build_r3000_tlbchange_handler_head(&p, K0, K1);
 	build_pte_present(&p, &r, K0, K1, -1, label_nopage_tlbl);
 	uasm_i_nop(&p); /* load delay */
-	build_make_valid(&p, &r, K0, K1);
+	build_make_valid(&p, &r, K0, K1, -1);
 	build_r3000_tlb_reload_write(&p, &l, &r, K0, K1);
 
 	uasm_l_nopage_tlbl(&l, p);
@@ -1809,7 +1925,7 @@ static void build_r3000_tlb_store_handle
 	build_r3000_tlbchange_handler_head(&p, K0, K1);
 	build_pte_writable(&p, &r, K0, K1, -1, label_nopage_tlbs);
 	uasm_i_nop(&p); /* load delay */
-	build_make_write(&p, &r, K0, K1);
+	build_make_write(&p, &r, K0, K1, -1);
 	build_r3000_tlb_reload_write(&p, &l, &r, K0, K1);
 
 	uasm_l_nopage_tlbs(&l, p);
@@ -1840,7 +1956,7 @@ static void build_r3000_tlb_modify_handl
 	build_r3000_tlbchange_handler_head(&p, K0, K1);
 	build_pte_modifiable(&p, &r, K0, K1,  -1, label_nopage_tlbm);
 	uasm_i_nop(&p); /* load delay */
-	build_make_write(&p, &r, K0, K1);
+	build_make_write(&p, &r, K0, K1, -1);
 	build_r3000_pte_reload_tlbwi(&p, K0, K1);
 
 	uasm_l_nopage_tlbm(&l, p);
@@ -2008,7 +2124,7 @@ static void build_r4000_tlb_load_handler
 		}
 		uasm_l_tlbl_goaround1(&l, p);
 	}
-	build_make_valid(&p, &r, wr.r1, wr.r2);
+	build_make_valid(&p, &r, wr.r1, wr.r2, wr.r3);
 	build_r4000_tlbchange_handler_tail(&p, &l, &r, wr.r1, wr.r2);
 
 #ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
@@ -2122,7 +2238,7 @@ static void build_r4000_tlb_store_handle
 	build_pte_writable(&p, &r, wr.r1, wr.r2, wr.r3, label_nopage_tlbs);
 	if (m4kc_tlbp_war())
 		build_tlb_probe_entry(&p);
-	build_make_write(&p, &r, wr.r1, wr.r2);
+	build_make_write(&p, &r, wr.r1, wr.r2, wr.r3);
 	build_r4000_tlbchange_handler_tail(&p, &l, &r, wr.r1, wr.r2);
 
 #ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
@@ -2178,7 +2294,7 @@ static void build_r4000_tlb_modify_handl
 	if (m4kc_tlbp_war())
 		build_tlb_probe_entry(&p);
 	/* Present and writable bits set, set accessed and dirty bits. */
-	build_make_write(&p, &r, wr.r1, wr.r2);
+	build_make_write(&p, &r, wr.r1, wr.r2, wr.r3);
 	build_r4000_tlbchange_handler_tail(&p, &l, &r, wr.r1, wr.r2);
 
 #ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
@@ -2245,8 +2361,9 @@ static void print_htw_config(void)
 		(config & MIPS_PWFIELD_PTEI_MASK) >> MIPS_PWFIELD_PTEI_SHIFT);
 
 	config = read_c0_pwsize();
-	pr_debug("PWSize  (0x%0*lx): GDW: 0x%02lx  UDW: 0x%02lx  MDW: 0x%02lx  PTW: 0x%02lx  PTEW: 0x%02lx\n",
+	pr_debug("PWSize  (0x%0*lx): PS: 0x%lx  GDW: 0x%02lx  UDW: 0x%02lx  MDW: 0x%02lx  PTW: 0x%02lx  PTEW: 0x%02lx\n",
 		field, config,
+		(config & MIPS_PWSIZE_PS_MASK) >> MIPS_PWSIZE_PS_SHIFT,
 		(config & MIPS_PWSIZE_GDW_MASK) >> MIPS_PWSIZE_GDW_SHIFT,
 		(config & MIPS_PWSIZE_UDW_MASK) >> MIPS_PWSIZE_UDW_SHIFT,
 		(config & MIPS_PWSIZE_MDW_MASK) >> MIPS_PWSIZE_MDW_SHIFT,
@@ -2254,9 +2371,12 @@ static void print_htw_config(void)
 		(config & MIPS_PWSIZE_PTEW_MASK) >> MIPS_PWSIZE_PTEW_SHIFT);
 
 	pwctl = read_c0_pwctl();
-	pr_debug("PWCtl   (0x%x): PWEn: 0x%x  DPH: 0x%x  HugePg: 0x%x  Psn: 0x%x\n",
+	pr_debug("PWCtl   (0x%x): PWEn: 0x%x  XK: 0x%x  XS: 0x%x  XU: 0x%x  DPH: 0x%x  HugePg: 0x%x  Psn: 0x%x\n",
 		pwctl,
 		(pwctl & MIPS_PWCTL_PWEN_MASK) >> MIPS_PWCTL_PWEN_SHIFT,
+		(pwctl & MIPS_PWCTL_XK_MASK) >> MIPS_PWCTL_XK_SHIFT,
+		(pwctl & MIPS_PWCTL_XS_MASK) >> MIPS_PWCTL_XS_SHIFT,
+		(pwctl & MIPS_PWCTL_XU_MASK) >> MIPS_PWCTL_XU_SHIFT,
 		(pwctl & MIPS_PWCTL_DPH_MASK) >> MIPS_PWCTL_DPH_SHIFT,
 		(pwctl & MIPS_PWCTL_HUGEPG_MASK) >> MIPS_PWCTL_HUGEPG_SHIFT,
 		(pwctl & MIPS_PWCTL_PSN_MASK) >> MIPS_PWCTL_PSN_SHIFT);
@@ -2311,17 +2431,25 @@ static void config_htw_params(void)
 	if (CONFIG_PGTABLE_LEVELS >= 3)
 		pwsize |= ilog2(PTRS_PER_PMD) << MIPS_PWSIZE_MDW_SHIFT;
 
-	/* If XPA has been enabled, PTEs are 64-bit in size. */
-	if (config_enabled(CONFIG_64BITS) || (read_c0_pagegrain() & PG_ELPA))
-		pwsize |= 1;
+	/* Set pointer size to size of directory pointers */
+	if (config_enabled(CONFIG_64BIT))
+		pwsize |= MIPS_PWSIZE_PS_MASK;
+	/* PTEs may be multiple pointers long (e.g. with XPA) */
+	pwsize |= ((PTE_T_LOG2 - PGD_T_LOG2) << MIPS_PWSIZE_PTEW_SHIFT)
+			& MIPS_PWSIZE_PTEW_MASK;
 
 	write_c0_pwsize(pwsize);
 
 	/* Make sure everything is set before we enable the HTW */
 	back_to_back_c0_hazard();
 
-	/* Enable HTW and disable the rest of the pwctl fields */
+	/*
+	 * Enable HTW (and only for XUSeg on 64-bit), and disable the rest of
+	 * the pwctl fields.
+	 */
 	config = 1 << MIPS_PWCTL_PWEN_SHIFT;
+	if (config_enabled(CONFIG_64BIT))
+		config |= MIPS_PWCTL_XU_MASK;
 	write_c0_pwctl(config);
 	pr_info("Hardware Page Table Walker enabled\n");
 
@@ -2394,6 +2522,9 @@ void build_tlb_refill_handler(void)
 	 */
 	static int run_once = 0;
 
+	if (config_enabled(CONFIG_XPA) && !cpu_has_rixi)
+		panic("Kernels supporting XPA currently require CPUs with RIXI");
+
 	output_pgtable_bits_defines();
 	check_pabits();
 
@@ -2437,13 +2568,18 @@ void build_tlb_refill_handler(void)
 		break;
 
 	default:
+		if (cpu_has_ldpte)
+			setup_pw();
+
 		if (!run_once) {
 			scratch_reg = allocate_kscratch();
 			build_setup_pgd();
 			build_r4000_tlb_load_handler();
 			build_r4000_tlb_store_handler();
 			build_r4000_tlb_modify_handler();
-			if (!cpu_has_local_ebase)
+			if (cpu_has_ldpte)
+				build_loongson3_tlb_refill_handler();
+			else if (!cpu_has_local_ebase)
 				build_r4000_tlb_refill_handler();
 			flush_tlb_handlers();
 			run_once++;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/mm/tlb-r3k.c linux-libre-4.7-gnu/arch/mips/mm/tlb-r3k.c
--- linux-libre-4.6-gnu/arch/mips/mm/tlb-r3k.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/mm/tlb-r3k.c	2016-07-24 15:23:50.000000000 -0400
@@ -43,7 +43,7 @@ static void local_flush_tlb_from(int ent
 {
 	unsigned long old_ctx;
 
-	old_ctx = read_c0_entryhi() & ASID_MASK;
+	old_ctx = read_c0_entryhi() & cpu_asid_mask(&current_cpu_data);
 	write_c0_entrylo0(0);
 	while (entry < current_cpu_data.tlbsize) {
 		write_c0_index(entry << 8);
@@ -81,6 +81,7 @@ void local_flush_tlb_mm(struct mm_struct
 void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
 			   unsigned long end)
 {
+	unsigned long asid_mask = cpu_asid_mask(&current_cpu_data);
 	struct mm_struct *mm = vma->vm_mm;
 	int cpu = smp_processor_id();
 
@@ -89,13 +90,13 @@ void local_flush_tlb_range(struct vm_are
 
 #ifdef DEBUG_TLB
 		printk("[tlbrange<%lu,0x%08lx,0x%08lx>]",
-			cpu_context(cpu, mm) & ASID_MASK, start, end);
+			cpu_context(cpu, mm) & asid_mask, start, end);
 #endif
 		local_irq_save(flags);
 		size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
 		if (size <= current_cpu_data.tlbsize) {
-			int oldpid = read_c0_entryhi() & ASID_MASK;
-			int newpid = cpu_context(cpu, mm) & ASID_MASK;
+			int oldpid = read_c0_entryhi() & asid_mask;
+			int newpid = cpu_context(cpu, mm) & asid_mask;
 
 			start &= PAGE_MASK;
 			end += PAGE_SIZE - 1;
@@ -159,6 +160,7 @@ void local_flush_tlb_kernel_range(unsign
 
 void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
 {
+	unsigned long asid_mask = cpu_asid_mask(&current_cpu_data);
 	int cpu = smp_processor_id();
 
 	if (cpu_context(cpu, vma->vm_mm) != 0) {
@@ -168,10 +170,10 @@ void local_flush_tlb_page(struct vm_area
 #ifdef DEBUG_TLB
 		printk("[tlbpage<%lu,0x%08lx>]", cpu_context(cpu, vma->vm_mm), page);
 #endif
-		newpid = cpu_context(cpu, vma->vm_mm) & ASID_MASK;
+		newpid = cpu_context(cpu, vma->vm_mm) & asid_mask;
 		page &= PAGE_MASK;
 		local_irq_save(flags);
-		oldpid = read_c0_entryhi() & ASID_MASK;
+		oldpid = read_c0_entryhi() & asid_mask;
 		write_c0_entryhi(page | newpid);
 		BARRIER;
 		tlb_probe();
@@ -190,6 +192,7 @@ finish:
 
 void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte)
 {
+	unsigned long asid_mask = cpu_asid_mask(&current_cpu_data);
 	unsigned long flags;
 	int idx, pid;
 
@@ -199,10 +202,10 @@ void __update_tlb(struct vm_area_struct
 	if (current->active_mm != vma->vm_mm)
 		return;
 
-	pid = read_c0_entryhi() & ASID_MASK;
+	pid = read_c0_entryhi() & asid_mask;
 
 #ifdef DEBUG_TLB
-	if ((pid != (cpu_context(cpu, vma->vm_mm) & ASID_MASK)) || (cpu_context(cpu, vma->vm_mm) == 0)) {
+	if ((pid != (cpu_context(cpu, vma->vm_mm) & asid_mask)) || (cpu_context(cpu, vma->vm_mm) == 0)) {
 		printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%lu tlbpid=%d\n",
 		       (cpu_context(cpu, vma->vm_mm)), pid);
 	}
@@ -228,6 +231,7 @@ void __update_tlb(struct vm_area_struct
 void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
 		     unsigned long entryhi, unsigned long pagemask)
 {
+	unsigned long asid_mask = cpu_asid_mask(&current_cpu_data);
 	unsigned long flags;
 	unsigned long old_ctx;
 	static unsigned long wired = 0;
@@ -243,7 +247,7 @@ void add_wired_entry(unsigned long entry
 
 		local_irq_save(flags);
 		/* Save old context and create impossible VPN2 value */
-		old_ctx = read_c0_entryhi() & ASID_MASK;
+		old_ctx = read_c0_entryhi() & asid_mask;
 		old_pagemask = read_c0_pagemask();
 		w = read_c0_wired();
 		write_c0_wired(w + 1);
@@ -266,7 +270,7 @@ void add_wired_entry(unsigned long entry
 #endif
 
 		local_irq_save(flags);
-		old_ctx = read_c0_entryhi() & ASID_MASK;
+		old_ctx = read_c0_entryhi() & asid_mask;
 		write_c0_entrylo0(entrylo0);
 		write_c0_entryhi(entryhi);
 		write_c0_index(wired);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/mm/tlb-r4k.c linux-libre-4.7-gnu/arch/mips/mm/tlb-r4k.c
--- linux-libre-4.6-gnu/arch/mips/mm/tlb-r4k.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/mm/tlb-r4k.c	2016-07-24 15:23:50.000000000 -0400
@@ -28,25 +28,28 @@
 extern void build_tlb_refill_handler(void);
 
 /*
- * LOONGSON2/3 has a 4 entry itlb which is a subset of dtlb,
- * unfortunately, itlb is not totally transparent to software.
+ * LOONGSON-2 has a 4 entry itlb which is a subset of jtlb, LOONGSON-3 has
+ * a 4 entry itlb and a 4 entry dtlb which are subsets of jtlb. Unfortunately,
+ * itlb/dtlb are not totally transparent to software.
  */
-static inline void flush_itlb(void)
+static inline void flush_micro_tlb(void)
 {
 	switch (current_cpu_type()) {
 	case CPU_LOONGSON2:
+		write_c0_diag(LOONGSON_DIAG_ITLB);
+		break;
 	case CPU_LOONGSON3:
-		write_c0_diag(4);
+		write_c0_diag(LOONGSON_DIAG_ITLB | LOONGSON_DIAG_DTLB);
 		break;
 	default:
 		break;
 	}
 }
 
-static inline void flush_itlb_vm(struct vm_area_struct *vma)
+static inline void flush_micro_tlb_vm(struct vm_area_struct *vma)
 {
 	if (vma->vm_flags & VM_EXEC)
-		flush_itlb();
+		flush_micro_tlb();
 }
 
 void local_flush_tlb_all(void)
@@ -93,7 +96,7 @@ void local_flush_tlb_all(void)
 	tlbw_use_hazard();
 	write_c0_entryhi(old_ctx);
 	htw_start();
-	flush_itlb();
+	flush_micro_tlb();
 	local_irq_restore(flags);
 }
 EXPORT_SYMBOL(local_flush_tlb_all);
@@ -159,7 +162,7 @@ void local_flush_tlb_range(struct vm_are
 		} else {
 			drop_mmu_context(mm, cpu);
 		}
-		flush_itlb();
+		flush_micro_tlb();
 		local_irq_restore(flags);
 	}
 }
@@ -205,7 +208,7 @@ void local_flush_tlb_kernel_range(unsign
 	} else {
 		local_flush_tlb_all();
 	}
-	flush_itlb();
+	flush_micro_tlb();
 	local_irq_restore(flags);
 }
 
@@ -240,7 +243,7 @@ void local_flush_tlb_page(struct vm_area
 	finish:
 		write_c0_entryhi(oldpid);
 		htw_start();
-		flush_itlb_vm(vma);
+		flush_micro_tlb_vm(vma);
 		local_irq_restore(flags);
 	}
 }
@@ -274,7 +277,7 @@ void local_flush_tlb_one(unsigned long p
 	}
 	write_c0_entryhi(oldpid);
 	htw_start();
-	flush_itlb();
+	flush_micro_tlb();
 	local_irq_restore(flags);
 }
 
@@ -301,7 +304,7 @@ void __update_tlb(struct vm_area_struct
 	local_irq_save(flags);
 
 	htw_stop();
-	pid = read_c0_entryhi() & ASID_MASK;
+	pid = read_c0_entryhi() & cpu_asid_mask(&current_cpu_data);
 	address &= (PAGE_MASK << 1);
 	write_c0_entryhi(address | pid);
 	pgdp = pgd_offset(vma->vm_mm, address);
@@ -336,10 +339,12 @@ void __update_tlb(struct vm_area_struct
 #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)
 #ifdef CONFIG_XPA
 		write_c0_entrylo0(pte_to_entrylo(ptep->pte_high));
-		writex_c0_entrylo0(ptep->pte_low & _PFNX_MASK);
+		if (cpu_has_xpa)
+			writex_c0_entrylo0(ptep->pte_low & _PFNX_MASK);
 		ptep++;
 		write_c0_entrylo1(pte_to_entrylo(ptep->pte_high));
-		writex_c0_entrylo1(ptep->pte_low & _PFNX_MASK);
+		if (cpu_has_xpa)
+			writex_c0_entrylo1(ptep->pte_low & _PFNX_MASK);
 #else
 		write_c0_entrylo0(ptep->pte_high);
 		ptep++;
@@ -357,7 +362,7 @@ void __update_tlb(struct vm_area_struct
 	}
 	tlbw_use_hazard();
 	htw_start();
-	flush_itlb_vm(vma);
+	flush_micro_tlb_vm(vma);
 	local_irq_restore(flags);
 }
 
@@ -400,19 +405,20 @@ void add_wired_entry(unsigned long entry
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 
-int __init has_transparent_hugepage(void)
+int has_transparent_hugepage(void)
 {
-	unsigned int mask;
-	unsigned long flags;
-
-	local_irq_save(flags);
-	write_c0_pagemask(PM_HUGE_MASK);
-	back_to_back_c0_hazard();
-	mask = read_c0_pagemask();
-	write_c0_pagemask(PM_DEFAULT_MASK);
+	static unsigned int mask = -1;
 
-	local_irq_restore(flags);
+	if (mask == -1) {	/* first call comes during __init */
+		unsigned long flags;
 
+		local_irq_save(flags);
+		write_c0_pagemask(PM_HUGE_MASK);
+		back_to_back_c0_hazard();
+		mask = read_c0_pagemask();
+		write_c0_pagemask(PM_DEFAULT_MASK);
+		local_irq_restore(flags);
+	}
 	return mask == PM_HUGE_MASK;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/mm/tlb-r8k.c linux-libre-4.7-gnu/arch/mips/mm/tlb-r8k.c
--- linux-libre-4.6-gnu/arch/mips/mm/tlb-r8k.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/mm/tlb-r8k.c	2016-07-24 15:23:50.000000000 -0400
@@ -194,7 +194,7 @@ void __update_tlb(struct vm_area_struct
 	if (current->active_mm != vma->vm_mm)
 		return;
 
-	pid = read_c0_entryhi() & ASID_MASK;
+	pid = read_c0_entryhi() & cpu_asid_mask(&current_cpu_data);
 
 	local_irq_save(flags);
 	address &= PAGE_MASK;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/mm/uasm.c linux-libre-4.7-gnu/arch/mips/mm/uasm.c
--- linux-libre-4.6-gnu/arch/mips/mm/uasm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/mm/uasm.c	2016-07-24 15:23:50.000000000 -0400
@@ -60,6 +60,7 @@ enum opcode {
 	insn_sltiu, insn_sltu, insn_sra, insn_srl, insn_srlv, insn_subu,
 	insn_sw, insn_sync, insn_syscall, insn_tlbp, insn_tlbr, insn_tlbwi,
 	insn_tlbwr, insn_wait, insn_wsbh, insn_xor, insn_xori, insn_yield,
+	insn_lddir, insn_ldpte,
 };
 
 struct insn {
@@ -335,6 +336,8 @@ I_u1u2s3(_bbit0);
 I_u1u2s3(_bbit1);
 I_u3u1u2(_lwx)
 I_u3u1u2(_ldx)
+I_u1u2(_ldpte)
+I_u2u1u3(_lddir)
 
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
 #include <asm/octeon/octeon.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/mm/uasm-mips.c linux-libre-4.7-gnu/arch/mips/mm/uasm-mips.c
--- linux-libre-4.6-gnu/arch/mips/mm/uasm-mips.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/mm/uasm-mips.c	2016-07-24 15:23:50.000000000 -0400
@@ -153,6 +153,8 @@ static struct insn insn_table[] = {
 	{ insn_xori,  M(xori_op, 0, 0, 0, 0, 0),  RS | RT | UIMM },
 	{ insn_xor,  M(spec_op, 0, 0, 0, 0, xor_op),  RS | RT | RD },
 	{ insn_yield, M(spec3_op, 0, 0, 0, 0, yield_op), RS | RD },
+	{ insn_ldpte, M(lwc2_op, 0, 0, 0, ldpte_op, mult_op), RS | RD },
+	{ insn_lddir, M(lwc2_op, 0, 0, 0, lddir_op, mult_op), RS | RT | RD },
 	{ insn_invalid, 0, 0 }
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/mti-malta/malta-setup.c linux-libre-4.7-gnu/arch/mips/mti-malta/malta-setup.c
--- linux-libre-4.6-gnu/arch/mips/mti-malta/malta-setup.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/mti-malta/malta-setup.c	2016-07-24 15:23:50.000000000 -0400
@@ -248,10 +248,15 @@ static void __init bonito_quirks_setup(v
 #endif
 }
 
+void __init *plat_get_fdt(void)
+{
+	return (void *)__dtb_start;
+}
+
 void __init plat_mem_setup(void)
 {
 	unsigned int i;
-	void *fdt = __dtb_start;
+	void *fdt = plat_get_fdt();
 
 	fdt = malta_dt_shim(fdt);
 	__dt_setup_arch(fdt);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/mti-malta/malta-time.c linux-libre-4.7-gnu/arch/mips/mti-malta/malta-time.c
--- linux-libre-4.6-gnu/arch/mips/mti-malta/malta-time.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/mti-malta/malta-time.c	2016-07-24 15:23:50.000000000 -0400
@@ -21,6 +21,7 @@
 #include <linux/i8253.h>
 #include <linux/init.h>
 #include <linux/kernel_stat.h>
+#include <linux/math64.h>
 #include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
@@ -72,6 +73,8 @@ static void __init estimate_frequencies(
 {
 	unsigned long flags;
 	unsigned int count, start;
+	unsigned char secs1, secs2, ctrl;
+	int secs;
 	cycle_t giccount = 0, gicstart = 0;
 
 #if defined(CONFIG_KVM_GUEST) && CONFIG_KVM_GUEST_TIMER_FREQ
@@ -81,32 +84,51 @@ static void __init estimate_frequencies(
 
 	local_irq_save(flags);
 
-	/* Start counter exactly on falling edge of update flag. */
+	if (gic_present)
+		gic_start_count();
+
+	/*
+	 * Read counters exactly on rising edge of update flag.
+	 * This helps get an accurate reading under virtualisation.
+	 */
 	while (CMOS_READ(RTC_REG_A) & RTC_UIP);
 	while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
-
-	/* Initialize counters. */
 	start = read_c0_count();
-	if (gic_present) {
-		gic_start_count();
+	if (gic_present)
 		gicstart = gic_read_count();
-	}
 
-	/* Read counter exactly on falling edge of update flag. */
+	/* Wait for falling edge before reading RTC. */
 	while (CMOS_READ(RTC_REG_A) & RTC_UIP);
-	while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
+	secs1 = CMOS_READ(RTC_SECONDS);
 
+	/* Read counters again exactly on rising edge of update flag. */
+	while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
 	count = read_c0_count();
 	if (gic_present)
 		giccount = gic_read_count();
 
+	/* Wait for falling edge before reading RTC again. */
+	while (CMOS_READ(RTC_REG_A) & RTC_UIP);
+	secs2 = CMOS_READ(RTC_SECONDS);
+
+	ctrl = CMOS_READ(RTC_CONTROL);
+
 	local_irq_restore(flags);
 
+	if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+		secs1 = bcd2bin(secs1);
+		secs2 = bcd2bin(secs2);
+	}
+	secs = secs2 - secs1;
+	if (secs < 1)
+		secs += 60;
+
 	count -= start;
+	count /= secs;
 	mips_hpt_frequency = count;
 
 	if (gic_present) {
-		giccount -= gicstart;
+		giccount = div_u64(giccount - gicstart, secs);
 		gic_frequency = giccount;
 	}
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/mti-sead3/sead3-setup.c linux-libre-4.7-gnu/arch/mips/mti-sead3/sead3-setup.c
--- linux-libre-4.6-gnu/arch/mips/mti-sead3/sead3-setup.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/mti-sead3/sead3-setup.c	2016-07-24 15:23:50.000000000 -0400
@@ -83,6 +83,11 @@ static void __init parse_memsize_param(v
 	}
 }
 
+void __init *plat_get_fdt(void)
+{
+	return (void *)__dtb_start;
+}
+
 void __init plat_mem_setup(void)
 {
 	/* allow command line/bootloader env to override memory size in DT */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/netlogic/common/reset.S linux-libre-4.7-gnu/arch/mips/netlogic/common/reset.S
--- linux-libre-4.6-gnu/arch/mips/netlogic/common/reset.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/netlogic/common/reset.S	2016-07-24 15:23:50.000000000 -0400
@@ -50,7 +50,6 @@
 #include <asm/netlogic/xlp-hal/sys.h>
 #include <asm/netlogic/xlp-hal/cpucontrol.h>
 
-#define CP0_EBASE	$15
 #define SYS_CPU_COHERENT_BASE	CKSEG1ADDR(XLP_DEFAULT_IO_BASE) + \
 			XLP_IO_SYS_OFFSET(0) + XLP_IO_PCI_HDRSZ + \
 			SYS_CPU_NONCOHERENT_MODE * 4
@@ -92,7 +91,7 @@
  * registers. On XLPII CPUs, usual cache instructions work.
  */
 .macro	xlp_flush_l1_dcache
-	mfc0	t0, CP0_EBASE, 0
+	mfc0	t0, CP0_PRID
 	andi	t0, t0, PRID_IMP_MASK
 	slt	t1, t0, 0x1200
 	beqz	t1, 15f
@@ -171,7 +170,7 @@ FEXPORT(nlm_reset_entry)
 	nop
 
 1:	/* Entry point on core wakeup */
-	mfc0	t0, CP0_EBASE, 0	/* processor ID */
+	mfc0	t0, CP0_PRID		/* processor ID */
 	andi	t0, PRID_IMP_MASK
 	li	t1, 0x1500		/* XLP 9xx */
 	beq	t0, t1, 2f		/* does not need to set coherent */
@@ -182,8 +181,8 @@ FEXPORT(nlm_reset_entry)
 	nop
 
 	/* set bit in SYS coherent register for the core */
-	mfc0	t0, CP0_EBASE, 1
-	mfc0	t1, CP0_EBASE, 1
+	mfc0	t0, CP0_EBASE
+	mfc0	t1, CP0_EBASE
 	srl	t1, 5
 	andi	t1, 0x3			/* t1 <- node */
 	li	t2, 0x40000
@@ -232,7 +231,7 @@ EXPORT(nlm_boot_siblings)
 
 	 * NOTE: All GPR contents are lost after the mtcr above!
 	 */
-	mfc0	v0, CP0_EBASE, 1
+	mfc0	v0, CP0_EBASE
 	andi	v0, 0x3ff		/* v0 <- node/core */
 
 	/*
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/netlogic/common/smpboot.S linux-libre-4.7-gnu/arch/mips/netlogic/common/smpboot.S
--- linux-libre-4.6-gnu/arch/mips/netlogic/common/smpboot.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/netlogic/common/smpboot.S	2016-07-24 15:23:50.000000000 -0400
@@ -48,8 +48,6 @@
 #include <asm/netlogic/xlp-hal/sys.h>
 #include <asm/netlogic/xlp-hal/cpucontrol.h>
 
-#define CP0_EBASE	$15
-
 	.set	noreorder
 	.set	noat
 	.set	arch=xlr		/* for mfcr/mtcr, XLR is sufficient */
@@ -86,7 +84,7 @@ NESTED(nlm_boot_secondary_cpus, 16, sp)
 	PTR_L	gp, 0(t1)
 
 	/* a0 has the processor id */
-	mfc0	a0, CP0_EBASE, 1
+	mfc0	a0, CP0_EBASE
 	andi	a0, 0x3ff		/* a0 <- node/core */
 	PTR_LA	t0, nlm_early_init_secondary
 	jalr	t0
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/netlogic/xlp/nlm_hal.c linux-libre-4.7-gnu/arch/mips/netlogic/xlp/nlm_hal.c
--- linux-libre-4.6-gnu/arch/mips/netlogic/xlp/nlm_hal.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/netlogic/xlp/nlm_hal.c	2016-07-24 15:23:50.000000000 -0400
@@ -58,7 +58,7 @@ void nlm_node_init(int node)
 		nodep->coremask = 1;	/* node 0, boot cpu */
 	nodep->sysbase = nlm_get_sys_regbase(node);
 	nodep->picbase = nlm_get_pic_regbase(node);
-	nodep->ebase = read_c0_ebase() & (~((1 << 12) - 1));
+	nodep->ebase = read_c0_ebase() & MIPS_EBASE_BASE;
 	if (cpu_is_xlp9xx())
 		nodep->socbus = xlp9xx_get_socbus(node);
 	else
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/netlogic/xlr/setup.c linux-libre-4.7-gnu/arch/mips/netlogic/xlr/setup.c
--- linux-libre-4.6-gnu/arch/mips/netlogic/xlr/setup.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/netlogic/xlr/setup.c	2016-07-24 15:23:50.000000000 -0400
@@ -168,7 +168,7 @@ static void nlm_init_node(void)
 
 	nodep = nlm_current_node();
 	nodep->picbase = nlm_mmio_base(NETLOGIC_IO_PIC_OFFSET);
-	nodep->ebase = read_c0_ebase() & (~((1 << 12) - 1));
+	nodep->ebase = read_c0_ebase() & MIPS_EBASE_BASE;
 	spin_lock_init(&nodep->piclock);
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/oprofile/common.c linux-libre-4.7-gnu/arch/mips/oprofile/common.c
--- linux-libre-4.6-gnu/arch/mips/oprofile/common.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/oprofile/common.c	2016-07-24 15:23:50.000000000 -0400
@@ -77,7 +77,7 @@ int __init oprofile_arch_init(struct opr
 	struct op_mips_model *lmodel = NULL;
 	int res;
 
-	switch (current_cpu_type()) {
+	switch (boot_cpu_type()) {
 	case CPU_5KC:
 	case CPU_M14KC:
 	case CPU_M14KEC:
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/oprofile/op_impl.h linux-libre-4.7-gnu/arch/mips/oprofile/op_impl.h
--- linux-libre-4.6-gnu/arch/mips/oprofile/op_impl.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/oprofile/op_impl.h	2016-07-24 15:23:50.000000000 -0400
@@ -24,7 +24,7 @@ struct op_counter_config {
 	unsigned long unit_mask;
 };
 
-/* Per-architecture configury and hooks.  */
+/* Per-architecture configure and hooks.  */
 struct op_mips_model {
 	void (*reg_setup) (struct op_counter_config *);
 	void (*cpu_setup) (void *dummy);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/oprofile/op_model_mipsxx.c linux-libre-4.7-gnu/arch/mips/oprofile/op_model_mipsxx.c
--- linux-libre-4.6-gnu/arch/mips/oprofile/op_model_mipsxx.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/oprofile/op_model_mipsxx.c	2016-07-24 15:23:50.000000000 -0400
@@ -269,11 +269,9 @@ static int mipsxx_perfcount_handler(void
 	return handled;
 }
 
-#define M_CONFIG1_PC	(1 << 4)
-
 static inline int __n_counters(void)
 {
-	if (!(read_c0_config1() & M_CONFIG1_PC))
+	if (!cpu_has_perf)
 		return 0;
 	if (!(read_c0_perfctrl0() & M_PERFCTL_MORE))
 		return 1;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/pci/fixup-lantiq.c linux-libre-4.7-gnu/arch/mips/pci/fixup-lantiq.c
--- linux-libre-4.6-gnu/arch/mips/pci/fixup-lantiq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/pci/fixup-lantiq.c	2016-07-24 15:23:50.000000000 -0400
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- *  Copyright (C) 2012 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2012 John Crispin <john@phrozen.org>
  */
 
 #include <linux/of_irq.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/pci/ops-bridge.c linux-libre-4.7-gnu/arch/mips/pci/ops-bridge.c
--- linux-libre-4.6-gnu/arch/mips/pci/ops-bridge.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/pci/ops-bridge.c	2016-07-24 15:23:50.000000000 -0400
@@ -33,9 +33,9 @@ static u32 emulate_ioc3_cfg(int where, i
  * The Bridge ASIC supports both type 0 and type 1 access.  Type 1 is
  * not really documented, so right now I can't write code which uses it.
  * Therefore we use type 0 accesses for now even though they won't work
- * correcly for PCI-to-PCI bridges.
+ * correctly for PCI-to-PCI bridges.
  *
- * The function is complicated by the ultimate brokeness of the IOC3 chip
+ * The function is complicated by the ultimate brokenness of the IOC3 chip
  * which is used in SGI systems.  The IOC3 can only handle 32-bit PCI
  * accesses and does only decode parts of it's address space.
  */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/pci/ops-lantiq.c linux-libre-4.7-gnu/arch/mips/pci/ops-lantiq.c
--- linux-libre-4.6-gnu/arch/mips/pci/ops-lantiq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/pci/ops-lantiq.c	2016-07-24 15:23:50.000000000 -0400
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2010 John Crispin <john@phrozen.org>
  */
 
 #include <linux/types.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/pci/pci-alchemy.c linux-libre-4.7-gnu/arch/mips/pci/pci-alchemy.c
--- linux-libre-4.6-gnu/arch/mips/pci/pci-alchemy.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/pci/pci-alchemy.c	2016-07-24 15:23:50.000000000 -0400
@@ -76,7 +76,7 @@ static void mod_wired_entry(int entry, u
 	unsigned long old_ctx;
 
 	/* Save old context and create impossible VPN2 value */
-	old_ctx = read_c0_entryhi() & 0xff;
+	old_ctx = read_c0_entryhi() & MIPS_ENTRYHI_ASID;
 	old_pagemask = read_c0_pagemask();
 	write_c0_index(entry);
 	write_c0_pagemask(pagemask);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/pci/pci.c linux-libre-4.7-gnu/arch/mips/pci/pci.c
--- linux-libre-4.6-gnu/arch/mips/pci/pci.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/pci/pci.c	2016-07-24 15:23:50.000000000 -0400
@@ -83,9 +83,6 @@ static void pcibios_scanbus(struct pci_c
 	LIST_HEAD(resources);
 	struct pci_bus *bus;
 
-	if (!hose->iommu)
-		PCI_DMA_BUS_IS_PHYS = 1;
-
 	if (hose->get_busno && pci_has_flag(PCI_PROBE_ONLY))
 		next_busno = (*hose->get_busno)();
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/pci/pci-ip32.c linux-libre-4.7-gnu/arch/mips/pci/pci-ip32.c
--- linux-libre-4.6-gnu/arch/mips/pci/pci-ip32.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/pci/pci-ip32.c	2016-07-24 15:23:50.000000000 -0400
@@ -116,7 +116,6 @@ static struct pci_controller mace_pci_co
 	.pci_ops	= &mace_pci_ops,
 	.mem_resource	= &mace_pci_mem_resource,
 	.io_resource	= &mace_pci_io_resource,
-	.iommu		= 0,
 	.mem_offset	= MACE_PCI_MEM_OFFSET,
 	.io_offset	= 0,
 	.io_map_base	= CKSEG1ADDR(MACEPCI_LOW_IO),
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/pci/pci-lantiq.c linux-libre-4.7-gnu/arch/mips/pci/pci-lantiq.c
--- linux-libre-4.6-gnu/arch/mips/pci/pci-lantiq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/pci/pci-lantiq.c	2016-07-24 15:23:50.000000000 -0400
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2010 John Crispin <john@phrozen.org>
  */
 
 #include <linux/types.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/pci/pci-lantiq.h linux-libre-4.7-gnu/arch/mips/pci/pci-lantiq.h
--- linux-libre-4.6-gnu/arch/mips/pci/pci-lantiq.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/pci/pci-lantiq.h	2016-07-24 15:23:50.000000000 -0400
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2010 John Crispin <john@phrozen.org>
  */
 
 #ifndef _LTQ_PCI_H__
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/pci/pci-mt7620.c linux-libre-4.7-gnu/arch/mips/pci/pci-mt7620.c
--- linux-libre-4.6-gnu/arch/mips/pci/pci-mt7620.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/pci/pci-mt7620.c	2016-07-24 15:23:50.000000000 -0400
@@ -2,7 +2,7 @@
  *  Ralink MT7620A SoC PCI support
  *
  *  Copyright (C) 2007-2013 Bruce Chang (Mediatek)
- *  Copyright (C) 2013-2016 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2013-2016 John Crispin <john@phrozen.org>
  *
  *  This program is free software; you can redistribute it and/or modify it
  *  under the terms of the GNU General Public License version 2 as published
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/pci/pci-rt2880.c linux-libre-4.7-gnu/arch/mips/pci/pci-rt2880.c
--- linux-libre-4.6-gnu/arch/mips/pci/pci-rt2880.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/pci/pci-rt2880.c	2016-07-24 15:23:50.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  *  Ralink RT288x SoC PCI register definitions
  *
- *  Copyright (C) 2009 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2009 John Crispin <john@phrozen.org>
  *  Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
  *
  *  Parts of this file are based on Ralink's 2.6.21 BSP
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/pic32/Kconfig linux-libre-4.7-gnu/arch/mips/pic32/Kconfig
--- linux-libre-4.6-gnu/arch/mips/pic32/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/pic32/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -14,7 +14,7 @@ config PIC32MZDA
 	select SYS_HAS_EARLY_PRINTK
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_LITTLE_ENDIAN
-	select ARCH_REQUIRE_GPIOLIB
+	select GPIOLIB
 	select COMMON_CLK
 	select CLKDEV_LOOKUP
 	select LIBFDT
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/pic32/pic32mzda/time.c linux-libre-4.7-gnu/arch/mips/pic32/pic32mzda/time.c
--- linux-libre-4.6-gnu/arch/mips/pic32/pic32mzda/time.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/pic32/pic32mzda/time.c	2016-07-24 15:23:50.000000000 -0400
@@ -11,13 +11,12 @@
  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  *  for more details.
  */
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clocksource.h>
 #include <linux/init.h>
+#include <linux/irqdomain.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
-#include <linux/irqdomain.h>
 
 #include <asm/time.h>
 
@@ -58,16 +57,12 @@ unsigned int get_c0_compare_int(void)
 
 void __init plat_time_init(void)
 {
-	struct clk *clk;
+	unsigned long rate = pic32_get_pbclk(7);
 
 	of_clk_init(NULL);
-	clk = clk_get_sys("cpu_clk", NULL);
-	if (IS_ERR(clk))
-		panic("unable to get CPU clock, err=%ld", PTR_ERR(clk));
 
-	clk_prepare_enable(clk);
-	pr_info("CPU Clock: %ldMHz\n", clk_get_rate(clk) / 1000000);
-	mips_hpt_frequency = clk_get_rate(clk) / 2;
+	pr_info("CPU Clock: %ldMHz\n", rate / 1000000);
+	mips_hpt_frequency = rate / 2;
 
 	clocksource_probe();
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/pistachio/init.c linux-libre-4.7-gnu/arch/mips/pistachio/init.c
--- linux-libre-4.6-gnu/arch/mips/pistachio/init.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/pistachio/init.c	2016-07-24 15:23:50.000000000 -0400
@@ -2,6 +2,7 @@
  * Pistachio platform setup
  *
  * Copyright (C) 2014 Google, Inc.
+ * Copyright (C) 2016 Imagination Technologies
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -9,6 +10,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/of_address.h>
 #include <linux/of_fdt.h>
@@ -24,9 +26,38 @@
 #include <asm/smp-ops.h>
 #include <asm/traps.h>
 
+/*
+ * Core revision register decoding
+ * Bits 23 to 20: Major rev
+ * Bits 15 to 8: Minor rev
+ * Bits 7 to 0: Maintenance rev
+ */
+#define PISTACHIO_CORE_REV_REG	0xB81483D0
+#define PISTACHIO_CORE_REV_A1	0x00100006
+#define PISTACHIO_CORE_REV_B0	0x00100106
+
 const char *get_system_type(void)
 {
-	return "IMG Pistachio SoC";
+	u32 core_rev;
+	const char *sys_type;
+
+	core_rev = __raw_readl((const void *)PISTACHIO_CORE_REV_REG);
+
+	switch (core_rev) {
+	case PISTACHIO_CORE_REV_B0:
+		sys_type = "IMG Pistachio SoC (B0)";
+		break;
+
+	case PISTACHIO_CORE_REV_A1:
+		sys_type = "IMG Pistachio SoC (A1)";
+		break;
+
+	default:
+		sys_type = "IMG Pistachio SoC";
+		break;
+	}
+
+	return sys_type;
 }
 
 static void __init plat_setup_iocoherency(void)
@@ -52,12 +83,16 @@ static void __init plat_setup_iocoherenc
 	}
 }
 
-void __init plat_mem_setup(void)
+void __init *plat_get_fdt(void)
 {
 	if (fw_arg0 != -2)
 		panic("Device-tree not present");
+	return (void *)fw_arg1;
+}
 
-	__dt_setup_arch((void *)fw_arg1);
+void __init plat_mem_setup(void)
+{
+	__dt_setup_arch(plat_get_fdt());
 
 	plat_setup_iocoherency();
 }
@@ -109,6 +144,8 @@ void __init prom_init(void)
 	mips_cm_probe();
 	mips_cpc_probe();
 	register_cps_smp_ops();
+
+	pr_info("SoC Type: %s\n", get_system_type());
 }
 
 void __init prom_free_prom_memory(void)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/pmcs-msp71xx/msp_setup.c linux-libre-4.7-gnu/arch/mips/pmcs-msp71xx/msp_setup.c
--- linux-libre-4.6-gnu/arch/mips/pmcs-msp71xx/msp_setup.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/pmcs-msp71xx/msp_setup.c	2016-07-24 15:23:50.000000000 -0400
@@ -118,7 +118,7 @@ void msp_restart(char *command)
 	/* No chip-specific reset code, just jump to the ROM reset vector */
 	set_c0_status(ST0_BEV | ST0_ERL);
 	change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
-	flush_cache_all();
+	__flush_cache_all();
 	write_c0_wired(0);
 
 	__asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/pnx833x/common/setup.c linux-libre-4.7-gnu/arch/mips/pnx833x/common/setup.c
--- linux-libre-4.6-gnu/arch/mips/pnx833x/common/setup.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/pnx833x/common/setup.c	2016-07-24 15:23:50.000000000 -0400
@@ -38,9 +38,6 @@ extern void pnx833x_machine_power_off(vo
 
 int __init plat_mem_setup(void)
 {
-	/* fake pci bus to avoid bounce buffers */
-	PCI_DMA_BUS_IS_PHYS = 1;
-
 	/* set mips clock to 320MHz */
 #if defined(CONFIG_SOC_PNX8335)
 	PNX8335_WRITEFIELD(0x17, CLOCK_PLL_CPU_CTL, FREQ);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/ralink/bootrom.c linux-libre-4.7-gnu/arch/mips/ralink/bootrom.c
--- linux-libre-4.6-gnu/arch/mips/ralink/bootrom.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/ralink/bootrom.c	2016-07-24 15:23:50.000000000 -0400
@@ -3,7 +3,7 @@
  * under the terms of the GNU General Public License version 2 as published
  * by the Free Software Foundation.
  *
- * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2013 John Crispin <john@phrozen.org>
  */
 
 #include <linux/debugfs.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/ralink/cevt-rt3352.c linux-libre-4.7-gnu/arch/mips/ralink/cevt-rt3352.c
--- linux-libre-4.6-gnu/arch/mips/ralink/cevt-rt3352.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/ralink/cevt-rt3352.c	2016-07-24 15:23:50.000000000 -0400
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2013 by John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2013 by John Crispin <john@phrozen.org>
  */
 
 #include <linux/clockchips.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/ralink/clk.c linux-libre-4.7-gnu/arch/mips/ralink/clk.c
--- linux-libre-4.6-gnu/arch/mips/ralink/clk.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/ralink/clk.c	2016-07-24 15:23:50.000000000 -0400
@@ -4,7 +4,7 @@
  *  by the Free Software Foundation.
  *
  *  Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
- *  Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2013 John Crispin <john@phrozen.org>
  */
 
 #include <linux/kernel.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/ralink/common.h linux-libre-4.7-gnu/arch/mips/ralink/common.h
--- linux-libre-4.6-gnu/arch/mips/ralink/common.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/ralink/common.h	2016-07-24 15:23:50.000000000 -0400
@@ -3,7 +3,7 @@
  *  under the terms of the GNU General Public License version 2 as published
  *  by the Free Software Foundation.
  *
- * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2013 John Crispin <john@phrozen.org>
  */
 
 #ifndef _RALINK_COMMON_H__
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/ralink/ill_acc.c linux-libre-4.7-gnu/arch/mips/ralink/ill_acc.c
--- linux-libre-4.6-gnu/arch/mips/ralink/ill_acc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/ralink/ill_acc.c	2016-07-24 15:23:50.000000000 -0400
@@ -3,7 +3,7 @@
  * under the terms of the GNU General Public License version 2 as published
  * by the Free Software Foundation.
  *
- * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2013 John Crispin <john@phrozen.org>
  */
 
 #include <linux/interrupt.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/ralink/irq.c linux-libre-4.7-gnu/arch/mips/ralink/irq.c
--- linux-libre-4.6-gnu/arch/mips/ralink/irq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/ralink/irq.c	2016-07-24 15:23:50.000000000 -0400
@@ -4,7 +4,7 @@
  * by the Free Software Foundation.
  *
  * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
- * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2013 John Crispin <john@phrozen.org>
  */
 
 #include <linux/io.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/ralink/irq-gic.c linux-libre-4.7-gnu/arch/mips/ralink/irq-gic.c
--- linux-libre-4.6-gnu/arch/mips/ralink/irq-gic.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/ralink/irq-gic.c	2016-07-24 15:23:50.000000000 -0400
@@ -4,7 +4,7 @@
  * by the Free Software Foundation.
  *
  * Copyright (C) 2015 Nikolay Martynov <mar.kolya@gmail.com>
- * Copyright (C) 2015 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2015 John Crispin <john@phrozen.org>
  */
 
 #include <linux/init.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/ralink/Makefile linux-libre-4.7-gnu/arch/mips/ralink/Makefile
--- linux-libre-4.6-gnu/arch/mips/ralink/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/ralink/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -4,7 +4,7 @@
 # Makefile for the Ralink common stuff
 #
 # Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
-# Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+# Copyright (C) 2013 John Crispin <john@phrozen.org>
 
 obj-y := prom.o of.o reset.o
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/ralink/mt7620.c linux-libre-4.7-gnu/arch/mips/ralink/mt7620.c
--- linux-libre-4.6-gnu/arch/mips/ralink/mt7620.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/ralink/mt7620.c	2016-07-24 15:23:50.000000000 -0400
@@ -7,7 +7,7 @@
  *
  * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
  * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
- * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2013 John Crispin <john@phrozen.org>
  */
 
 #include <linux/kernel.h>
@@ -188,6 +188,41 @@ static struct rt2880_pmx_func gpio_grp_m
 	FUNC("gpio", 0, 11, 1),
 };
 
+static struct rt2880_pmx_func p4led_kn_grp_mt7628[] = {
+	FUNC("jtag", 3, 30, 1),
+	FUNC("util", 2, 30, 1),
+	FUNC("gpio", 1, 30, 1),
+	FUNC("p4led_kn", 0, 30, 1),
+};
+
+static struct rt2880_pmx_func p3led_kn_grp_mt7628[] = {
+	FUNC("jtag", 3, 31, 1),
+	FUNC("util", 2, 31, 1),
+	FUNC("gpio", 1, 31, 1),
+	FUNC("p3led_kn", 0, 31, 1),
+};
+
+static struct rt2880_pmx_func p2led_kn_grp_mt7628[] = {
+	FUNC("jtag", 3, 32, 1),
+	FUNC("util", 2, 32, 1),
+	FUNC("gpio", 1, 32, 1),
+	FUNC("p2led_kn", 0, 32, 1),
+};
+
+static struct rt2880_pmx_func p1led_kn_grp_mt7628[] = {
+	FUNC("jtag", 3, 33, 1),
+	FUNC("util", 2, 33, 1),
+	FUNC("gpio", 1, 33, 1),
+	FUNC("p1led_kn", 0, 33, 1),
+};
+
+static struct rt2880_pmx_func p0led_kn_grp_mt7628[] = {
+	FUNC("jtag", 3, 34, 1),
+	FUNC("rsvd", 2, 34, 1),
+	FUNC("gpio", 1, 34, 1),
+	FUNC("p0led_kn", 0, 34, 1),
+};
+
 static struct rt2880_pmx_func wled_kn_grp_mt7628[] = {
 	FUNC("rsvd", 3, 35, 1),
 	FUNC("rsvd", 2, 35, 1),
@@ -195,16 +230,61 @@ static struct rt2880_pmx_func wled_kn_gr
 	FUNC("wled_kn", 0, 35, 1),
 };
 
+static struct rt2880_pmx_func p4led_an_grp_mt7628[] = {
+	FUNC("jtag", 3, 39, 1),
+	FUNC("util", 2, 39, 1),
+	FUNC("gpio", 1, 39, 1),
+	FUNC("p4led_an", 0, 39, 1),
+};
+
+static struct rt2880_pmx_func p3led_an_grp_mt7628[] = {
+	FUNC("jtag", 3, 40, 1),
+	FUNC("util", 2, 40, 1),
+	FUNC("gpio", 1, 40, 1),
+	FUNC("p3led_an", 0, 40, 1),
+};
+
+static struct rt2880_pmx_func p2led_an_grp_mt7628[] = {
+	FUNC("jtag", 3, 41, 1),
+	FUNC("util", 2, 41, 1),
+	FUNC("gpio", 1, 41, 1),
+	FUNC("p2led_an", 0, 41, 1),
+};
+
+static struct rt2880_pmx_func p1led_an_grp_mt7628[] = {
+	FUNC("jtag", 3, 42, 1),
+	FUNC("util", 2, 42, 1),
+	FUNC("gpio", 1, 42, 1),
+	FUNC("p1led_an", 0, 42, 1),
+};
+
+static struct rt2880_pmx_func p0led_an_grp_mt7628[] = {
+	FUNC("jtag", 3, 43, 1),
+	FUNC("rsvd", 2, 43, 1),
+	FUNC("gpio", 1, 43, 1),
+	FUNC("p0led_an", 0, 43, 1),
+};
+
 static struct rt2880_pmx_func wled_an_grp_mt7628[] = {
-	FUNC("rsvd", 3, 35, 1),
-	FUNC("rsvd", 2, 35, 1),
-	FUNC("gpio", 1, 35, 1),
-	FUNC("wled_an", 0, 35, 1),
+	FUNC("rsvd", 3, 44, 1),
+	FUNC("rsvd", 2, 44, 1),
+	FUNC("gpio", 1, 44, 1),
+	FUNC("wled_an", 0, 44, 1),
 };
 
 #define MT7628_GPIO_MODE_MASK		0x3
 
+#define MT7628_GPIO_MODE_P4LED_KN	58
+#define MT7628_GPIO_MODE_P3LED_KN	56
+#define MT7628_GPIO_MODE_P2LED_KN	54
+#define MT7628_GPIO_MODE_P1LED_KN	52
+#define MT7628_GPIO_MODE_P0LED_KN	50
 #define MT7628_GPIO_MODE_WLED_KN	48
+#define MT7628_GPIO_MODE_P4LED_AN	42
+#define MT7628_GPIO_MODE_P3LED_AN	40
+#define MT7628_GPIO_MODE_P2LED_AN	38
+#define MT7628_GPIO_MODE_P1LED_AN	36
+#define MT7628_GPIO_MODE_P0LED_AN	34
 #define MT7628_GPIO_MODE_WLED_AN	32
 #define MT7628_GPIO_MODE_PWM1		30
 #define MT7628_GPIO_MODE_PWM0		28
@@ -223,9 +303,9 @@ static struct rt2880_pmx_func wled_an_gr
 #define MT7628_GPIO_MODE_GPIO		0
 
 static struct rt2880_pmx_group mt7628an_pinmux_data[] = {
-	GRP_G("pmw1", pwm1_grp_mt7628, MT7628_GPIO_MODE_MASK,
+	GRP_G("pwm1", pwm1_grp_mt7628, MT7628_GPIO_MODE_MASK,
 				1, MT7628_GPIO_MODE_PWM1),
-	GRP_G("pmw0", pwm0_grp_mt7628, MT7628_GPIO_MODE_MASK,
+	GRP_G("pwm0", pwm0_grp_mt7628, MT7628_GPIO_MODE_MASK,
 				1, MT7628_GPIO_MODE_PWM0),
 	GRP_G("uart2", uart2_grp_mt7628, MT7628_GPIO_MODE_MASK,
 				1, MT7628_GPIO_MODE_UART2),
@@ -251,8 +331,28 @@ static struct rt2880_pmx_group mt7628an_
 				1, MT7628_GPIO_MODE_GPIO),
 	GRP_G("wled_an", wled_an_grp_mt7628, MT7628_GPIO_MODE_MASK,
 				1, MT7628_GPIO_MODE_WLED_AN),
+	GRP_G("p0led_an", p0led_an_grp_mt7628, MT7628_GPIO_MODE_MASK,
+				1, MT7628_GPIO_MODE_P0LED_AN),
+	GRP_G("p1led_an", p1led_an_grp_mt7628, MT7628_GPIO_MODE_MASK,
+				1, MT7628_GPIO_MODE_P1LED_AN),
+	GRP_G("p2led_an", p2led_an_grp_mt7628, MT7628_GPIO_MODE_MASK,
+				1, MT7628_GPIO_MODE_P2LED_AN),
+	GRP_G("p3led_an", p3led_an_grp_mt7628, MT7628_GPIO_MODE_MASK,
+				1, MT7628_GPIO_MODE_P3LED_AN),
+	GRP_G("p4led_an", p4led_an_grp_mt7628, MT7628_GPIO_MODE_MASK,
+				1, MT7628_GPIO_MODE_P4LED_AN),
 	GRP_G("wled_kn", wled_kn_grp_mt7628, MT7628_GPIO_MODE_MASK,
 				1, MT7628_GPIO_MODE_WLED_KN),
+	GRP_G("p0led_kn", p0led_kn_grp_mt7628, MT7628_GPIO_MODE_MASK,
+				1, MT7628_GPIO_MODE_P0LED_KN),
+	GRP_G("p1led_kn", p1led_kn_grp_mt7628, MT7628_GPIO_MODE_MASK,
+				1, MT7628_GPIO_MODE_P1LED_KN),
+	GRP_G("p2led_kn", p2led_kn_grp_mt7628, MT7628_GPIO_MODE_MASK,
+				1, MT7628_GPIO_MODE_P2LED_KN),
+	GRP_G("p3led_kn", p3led_kn_grp_mt7628, MT7628_GPIO_MODE_MASK,
+				1, MT7628_GPIO_MODE_P3LED_KN),
+	GRP_G("p4led_kn", p4led_kn_grp_mt7628, MT7628_GPIO_MODE_MASK,
+				1, MT7628_GPIO_MODE_P4LED_KN),
 	{ 0 }
 };
 
@@ -581,11 +681,14 @@ void prom_soc_init(struct ralink_soc_inf
 		(rev & CHIP_REV_ECO_MASK));
 
 	cfg0 = __raw_readl(sysc + SYSC_REG_SYSTEM_CONFIG0);
-	if (is_mt76x8())
+	if (is_mt76x8()) {
 		dram_type = cfg0 & DRAM_TYPE_MT7628_MASK;
-	else
+	} else {
 		dram_type = (cfg0 >> SYSCFG0_DRAM_TYPE_SHIFT) &
 			    SYSCFG0_DRAM_TYPE_MASK;
+		if (dram_type == SYSCFG0_DRAM_TYPE_UNKNOWN)
+			dram_type = SYSCFG0_DRAM_TYPE_SDRAM;
+	}
 
 	soc_info->mem_base = MT7620_DRAM_BASE;
 	if (is_mt76x8())
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/ralink/mt7621.c linux-libre-4.7-gnu/arch/mips/ralink/mt7621.c
--- linux-libre-4.6-gnu/arch/mips/ralink/mt7621.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/ralink/mt7621.c	2016-07-24 15:23:50.000000000 -0400
@@ -4,7 +4,7 @@
  * by the Free Software Foundation.
  *
  * Copyright (C) 2015 Nikolay Martynov <mar.kolya@gmail.com>
- * Copyright (C) 2015 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2015 John Crispin <john@phrozen.org>
  */
 
 #include <linux/kernel.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/ralink/of.c linux-libre-4.7-gnu/arch/mips/ralink/of.c
--- linux-libre-4.6-gnu/arch/mips/ralink/of.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/ralink/of.c	2016-07-24 15:23:50.000000000 -0400
@@ -5,7 +5,7 @@
  *
  * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
  * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org>
- * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2013 John Crispin <john@phrozen.org>
  */
 
 #include <linux/io.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/ralink/prom.c linux-libre-4.7-gnu/arch/mips/ralink/prom.c
--- linux-libre-4.6-gnu/arch/mips/ralink/prom.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/ralink/prom.c	2016-07-24 15:23:50.000000000 -0400
@@ -5,7 +5,7 @@
  *
  *  Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
  *  Copyright (C) 2010 Joonas Lahtinen <joonas.lahtinen@gmail.com>
- *  Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ *  Copyright (C) 2013 John Crispin <john@phrozen.org>
  */
 
 #include <linux/string.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/ralink/reset.c linux-libre-4.7-gnu/arch/mips/ralink/reset.c
--- linux-libre-4.6-gnu/arch/mips/ralink/reset.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/ralink/reset.c	2016-07-24 15:23:50.000000000 -0400
@@ -5,7 +5,7 @@
  *
  * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org>
  * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
- * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2013 John Crispin <john@phrozen.org>
  */
 
 #include <linux/pm.h>
@@ -61,7 +61,7 @@ static int ralink_reset_device(struct re
 	return ralink_deassert_device(rcdev, id);
 }
 
-static struct reset_control_ops reset_ops = {
+static const struct reset_control_ops reset_ops = {
 	.reset = ralink_reset_device,
 	.assert = ralink_assert_device,
 	.deassert = ralink_deassert_device,
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/ralink/rt288x.c linux-libre-4.7-gnu/arch/mips/ralink/rt288x.c
--- linux-libre-4.6-gnu/arch/mips/ralink/rt288x.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/ralink/rt288x.c	2016-07-24 15:23:50.000000000 -0400
@@ -7,7 +7,7 @@
  *
  * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
  * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
- * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2013 John Crispin <john@phrozen.org>
  */
 
 #include <linux/kernel.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/ralink/rt305x.c linux-libre-4.7-gnu/arch/mips/ralink/rt305x.c
--- linux-libre-4.6-gnu/arch/mips/ralink/rt305x.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/ralink/rt305x.c	2016-07-24 15:23:50.000000000 -0400
@@ -7,7 +7,7 @@
  *
  * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
  * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
- * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2013 John Crispin <john@phrozen.org>
  */
 
 #include <linux/kernel.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/ralink/rt3883.c linux-libre-4.7-gnu/arch/mips/ralink/rt3883.c
--- linux-libre-4.6-gnu/arch/mips/ralink/rt3883.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/ralink/rt3883.c	2016-07-24 15:23:50.000000000 -0400
@@ -7,7 +7,7 @@
  *
  * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
  * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
- * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2013 John Crispin <john@phrozen.org>
  */
 
 #include <linux/kernel.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/ralink/timer.c linux-libre-4.7-gnu/arch/mips/ralink/timer.c
--- linux-libre-4.6-gnu/arch/mips/ralink/timer.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/ralink/timer.c	2016-07-24 15:23:50.000000000 -0400
@@ -3,7 +3,7 @@
  * under the terms of the GNU General Public License version 2 as published
  * by the Free Software Foundation.
  *
- * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2013 John Crispin <john@phrozen.org>
 */
 
 #include <linux/module.h>
@@ -180,5 +180,5 @@ static struct platform_driver rt_timer_d
 module_platform_driver(rt_timer_driver);
 
 MODULE_DESCRIPTION("Ralink RT2880 timer");
-MODULE_AUTHOR("John Crispin <blogic@openwrt.org");
+MODULE_AUTHOR("John Crispin <john@phrozen.org");
 MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/ralink/timer-gic.c linux-libre-4.7-gnu/arch/mips/ralink/timer-gic.c
--- linux-libre-4.6-gnu/arch/mips/ralink/timer-gic.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/ralink/timer-gic.c	2016-07-24 15:23:50.000000000 -0400
@@ -4,7 +4,7 @@
  * by the Free Software Foundation.
  *
  * Copyright (C) 2015 Nikolay Martynov <mar.kolya@gmail.com>
- * Copyright (C) 2015 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2015 John Crispin <john@phrozen.org>
  */
 
 #include <linux/init.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/sgi-ip27/ip27-hubio.c linux-libre-4.7-gnu/arch/mips/sgi-ip27/ip27-hubio.c
--- linux-libre-4.6-gnu/arch/mips/sgi-ip27/ip27-hubio.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/sgi-ip27/ip27-hubio.c	2016-07-24 15:23:50.000000000 -0400
@@ -105,7 +105,7 @@ static void hub_setup_prb(nasid_t nasid,
 	prb.iprb_ff = force_fire_and_forget ? 1 : 0;
 
 	/*
-	 * Set the appropriate number of PIO cresits for the widget.
+	 * Set the appropriate number of PIO credits for the widget.
 	 */
 	prb.iprb_xtalkctr = credits;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/sgi-ip27/ip27-nmi.c linux-libre-4.7-gnu/arch/mips/sgi-ip27/ip27-nmi.c
--- linux-libre-4.6-gnu/arch/mips/sgi-ip27/ip27-nmi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/sgi-ip27/ip27-nmi.c	2016-07-24 15:23:50.000000000 -0400
@@ -23,7 +23,7 @@ typedef unsigned long machreg_t;
 static arch_spinlock_t nmi_lock = __ARCH_SPIN_LOCK_UNLOCKED;
 
 /*
- * Lets see what else we need to do here. Set up sp, gp?
+ * Let's see what else we need to do here. Set up sp, gp?
  */
 void nmi_dump(void)
 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/sgi-ip27/ip27-xtalk.c linux-libre-4.7-gnu/arch/mips/sgi-ip27/ip27-xtalk.c
--- linux-libre-4.6-gnu/arch/mips/sgi-ip27/ip27-xtalk.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/sgi-ip27/ip27-xtalk.c	2016-07-24 15:23:50.000000000 -0400
@@ -67,7 +67,7 @@ static int xbow_probe(nasid_t nasid)
 		return -ENODEV;
 
 	/*
-	 * Okay, here's a xbow. Lets arbitrate and find
+	 * Okay, here's a xbow. Let's arbitrate and find
 	 * out if we should initialize it. Set enabled
 	 * hub connected at highest or lowest widget as
 	 * master.
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/sibyte/Kconfig linux-libre-4.7-gnu/arch/mips/sibyte/Kconfig
--- linux-libre-4.6-gnu/arch/mips/sibyte/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/sibyte/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -143,7 +143,8 @@ config SIBYTE_CFE_CONSOLE
 config SIBYTE_BUS_WATCHER
 	bool "Support for Bus Watcher statistics"
 	depends on SIBYTE_SB1xxx_SOC && \
-		(SIBYTE_BCM112X || SIBYTE_SB1250)
+		(SIBYTE_BCM112X || SIBYTE_SB1250 || \
+		 SIBYTE_BCM1x55 || SIBYTE_BCM1x80)
 	help
 	  Handle and keep statistics on the bus error interrupts (COR_ECC,
 	  BAD_ECC, IO_BUS).
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/sni/rm200.c linux-libre-4.7-gnu/arch/mips/sni/rm200.c
--- linux-libre-4.6-gnu/arch/mips/sni/rm200.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/sni/rm200.c	2016-07-24 15:23:50.000000000 -0400
@@ -263,7 +263,7 @@ spurious_8259A_irq:
 		static int spurious_irq_mask;
 		/*
 		 * At this point we can be sure the IRQ is spurious,
-		 * lets ACK and report it. [once per IRQ]
+		 * let's ACK and report it. [once per IRQ]
 		 */
 		if (!(spurious_irq_mask & irqmask)) {
 			printk(KERN_DEBUG
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/vdso/Makefile linux-libre-4.7-gnu/arch/mips/vdso/Makefile
--- linux-libre-4.6-gnu/arch/mips/vdso/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/vdso/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -5,10 +5,12 @@ obj-vdso-y := elf.o gettimeofday.o sigre
 ccflags-vdso := \
 	$(filter -I%,$(KBUILD_CFLAGS)) \
 	$(filter -E%,$(KBUILD_CFLAGS)) \
+	$(filter -mmicromips,$(KBUILD_CFLAGS)) \
 	$(filter -march=%,$(KBUILD_CFLAGS))
 cflags-vdso := $(ccflags-vdso) \
 	$(filter -W%,$(filter-out -Wa$(comma)%,$(KBUILD_CFLAGS))) \
-	-O2 -g -fPIC -fno-common -fno-builtin -G 0 -DDISABLE_BRANCH_PROFILING \
+	-O2 -g -fPIC -fno-strict-aliasing -fno-common -fno-builtin -G 0 \
+	-DDISABLE_BRANCH_PROFILING \
 	$(call cc-option, -fno-stack-protector)
 aflags-vdso := $(ccflags-vdso) \
 	$(filter -I%,$(KBUILD_CFLAGS)) \
@@ -50,13 +52,17 @@ quiet_cmd_vdsold = VDSO    $@
       cmd_vdsold = $(CC) $(c_flags) $(VDSO_LDFLAGS) \
                    -Wl,-T $(filter %.lds,$^) $(filter %.o,$^) -o $@
 
+# Strip rule for the raw .so files
+$(obj)/%.so.raw: OBJCOPYFLAGS := -S
+$(obj)/%.so.raw: $(obj)/%.so.dbg.raw FORCE
+	$(call if_changed,objcopy)
+
 hostprogs-y := genvdso
 
 quiet_cmd_genvdso = GENVDSO $@
 define cmd_genvdso
-	cp $< $(<:%.dbg=%) && \
-	$(OBJCOPY) -S $< $(<:%.dbg=%) && \
-	$(obj)/genvdso $< $(<:%.dbg=%) $@ $(VDSO_NAME)
+	$(foreach file,$(filter %.raw,$^),cp $(file) $(file:%.raw=%) &&) \
+	$(obj)/genvdso $(<:%.raw=%) $(<:%.dbg.raw=%) $@ $(VDSO_NAME)
 endef
 
 #
@@ -66,7 +72,10 @@ endef
 native-abi := $(filter -mabi=%,$(KBUILD_CFLAGS))
 
 targets += $(obj-vdso-y)
-targets += vdso.lds vdso.so.dbg vdso.so vdso-image.c
+targets += vdso.lds
+targets += vdso.so.dbg.raw vdso.so.raw
+targets += vdso.so.dbg vdso.so
+targets += vdso-image.c
 
 obj-vdso := $(obj-vdso-y:%.o=$(obj)/%.o)
 
@@ -75,10 +84,11 @@ $(obj-vdso): KBUILD_AFLAGS := $(aflags-v
 
 $(obj)/vdso.lds: KBUILD_CPPFLAGS := $(native-abi)
 
-$(obj)/vdso.so.dbg: $(obj)/vdso.lds $(obj-vdso) FORCE
+$(obj)/vdso.so.dbg.raw: $(obj)/vdso.lds $(obj-vdso) FORCE
 	$(call if_changed,vdsold)
 
-$(obj)/vdso-image.c: $(obj)/vdso.so.dbg $(obj)/genvdso FORCE
+$(obj)/vdso-image.c: $(obj)/vdso.so.dbg.raw $(obj)/vdso.so.raw \
+                     $(obj)/genvdso FORCE
 	$(call if_changed,genvdso)
 
 obj-y += vdso-image.o
@@ -89,7 +99,10 @@ obj-y += vdso-image.o
 
 # Define these outside the ifdef to ensure they are picked up by clean.
 targets += $(obj-vdso-y:%.o=%-o32.o)
-targets += vdso-o32.lds vdso-o32.so.dbg vdso-o32.so vdso-o32-image.c
+targets += vdso-o32.lds
+targets += vdso-o32.so.dbg.raw vdso-o32.so.raw
+targets += vdso-o32.so.dbg vdso-o32.so
+targets += vdso-o32-image.c
 
 ifdef CONFIG_MIPS32_O32
 
@@ -109,11 +122,12 @@ $(obj)/vdso-o32.lds: KBUILD_CPPFLAGS :=
 $(obj)/vdso-o32.lds: $(src)/vdso.lds.S FORCE
 	$(call if_changed_dep,cpp_lds_S)
 
-$(obj)/vdso-o32.so.dbg: $(obj)/vdso-o32.lds $(obj-vdso-o32) FORCE
+$(obj)/vdso-o32.so.dbg.raw: $(obj)/vdso-o32.lds $(obj-vdso-o32) FORCE
 	$(call if_changed,vdsold)
 
 $(obj)/vdso-o32-image.c: VDSO_NAME := o32
-$(obj)/vdso-o32-image.c: $(obj)/vdso-o32.so.dbg $(obj)/genvdso FORCE
+$(obj)/vdso-o32-image.c: $(obj)/vdso-o32.so.dbg.raw $(obj)/vdso-o32.so.raw \
+                         $(obj)/genvdso FORCE
 	$(call if_changed,genvdso)
 
 obj-y += vdso-o32-image.o
@@ -125,7 +139,10 @@ endif
 #
 
 targets += $(obj-vdso-y:%.o=%-n32.o)
-targets += vdso-n32.lds vdso-n32.so.dbg vdso-n32.so vdso-n32-image.c
+targets += vdso-n32.lds
+targets += vdso-n32.so.dbg.raw vdso-n32.so.raw
+targets += vdso-n32.so.dbg vdso-n32.so
+targets += vdso-n32-image.c
 
 ifdef CONFIG_MIPS32_N32
 
@@ -145,11 +162,12 @@ $(obj)/vdso-n32.lds: KBUILD_CPPFLAGS :=
 $(obj)/vdso-n32.lds: $(src)/vdso.lds.S FORCE
 	$(call if_changed_dep,cpp_lds_S)
 
-$(obj)/vdso-n32.so.dbg: $(obj)/vdso-n32.lds $(obj-vdso-n32) FORCE
+$(obj)/vdso-n32.so.dbg.raw: $(obj)/vdso-n32.lds $(obj-vdso-n32) FORCE
 	$(call if_changed,vdsold)
 
 $(obj)/vdso-n32-image.c: VDSO_NAME := n32
-$(obj)/vdso-n32-image.c: $(obj)/vdso-n32.so.dbg $(obj)/genvdso FORCE
+$(obj)/vdso-n32-image.c: $(obj)/vdso-n32.so.dbg.raw $(obj)/vdso-n32.so.raw \
+                         $(obj)/genvdso FORCE
 	$(call if_changed,genvdso)
 
 obj-y += vdso-n32-image.o
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/vr41xx/common/cmu.c linux-libre-4.7-gnu/arch/mips/vr41xx/common/cmu.c
--- linux-libre-4.6-gnu/arch/mips/vr41xx/common/cmu.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/vr41xx/common/cmu.c	2016-07-24 15:23:50.000000000 -0400
@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 2001-2002  MontaVista Software Inc.
  *    Author: Yoichi Yuasa <source@mvista.com>
- *  Copuright (C) 2003-2005  Yoichi Yuasa <yuasa@linux-mips.org>
+ *  Copyright (C) 2003-2005  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mips/vr41xx/common/pmu.c linux-libre-4.7-gnu/arch/mips/vr41xx/common/pmu.c
--- linux-libre-4.6-gnu/arch/mips/vr41xx/common/pmu.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mips/vr41xx/common/pmu.c	2016-07-24 15:23:50.000000000 -0400
@@ -73,7 +73,7 @@ static inline void software_reset(void)
 	default:
 		set_c0_status(ST0_BEV | ST0_ERL);
 		change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
-		flush_cache_all();
+		__flush_cache_all();
 		write_c0_wired(0);
 		__asm__("jr	%0"::"r"(0xbfc00000));
 		break;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mn10300/boot/compressed/Makefile linux-libre-4.7-gnu/arch/mn10300/boot/compressed/Makefile
--- linux-libre-4.6-gnu/arch/mn10300/boot/compressed/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mn10300/boot/compressed/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -8,7 +8,6 @@ LDFLAGS_vmlinux := -Ttext $(CONFIG_KERNE
 
 $(obj)/vmlinux: $(obj)/head.o $(obj)/misc.o $(obj)/piggy.o FORCE
 	$(call if_changed,ld)
-	@:
 
 $(obj)/vmlinux.bin: vmlinux FORCE
 	$(call if_changed,objcopy)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mn10300/configs/asb2364_defconfig linux-libre-4.7-gnu/arch/mn10300/configs/asb2364_defconfig
--- linux-libre-4.6-gnu/arch/mn10300/configs/asb2364_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mn10300/configs/asb2364_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -11,7 +11,6 @@ CONFIG_CGROUPS=y
 CONFIG_CGROUP_FREEZER=y
 CONFIG_CGROUP_DEVICE=y
 CONFIG_CGROUP_CPUACCT=y
-CONFIG_RESOURCE_COUNTERS=y
 CONFIG_RELAY=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EXPERT=y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mn10300/include/asm/fpu.h linux-libre-4.7-gnu/arch/mn10300/include/asm/fpu.h
--- linux-libre-4.6-gnu/arch/mn10300/include/asm/fpu.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mn10300/include/asm/fpu.h	2016-07-24 15:23:50.000000000 -0400
@@ -76,11 +76,9 @@ static inline void unlazy_fpu(struct tas
 	preempt_enable();
 }
 
-static inline void exit_fpu(void)
+static inline void exit_fpu(struct task_struct *tsk)
 {
 #ifdef CONFIG_LAZY_SAVE_FPU
-	struct task_struct *tsk = current;
-
 	preempt_disable();
 	if (fpu_state_owner == tsk)
 		fpu_state_owner = NULL;
@@ -123,7 +121,7 @@ static inline void fpu_init_state(void)
 static inline void fpu_save(struct fpu_state_struct *s) {}
 static inline void fpu_kill_state(struct task_struct *tsk) {}
 static inline void unlazy_fpu(struct task_struct *tsk) {}
-static inline void exit_fpu(void) {}
+static inline void exit_fpu(struct task_struct *tsk) {}
 static inline void flush_fpu(void) {}
 static inline int fpu_setup_sigcontext(struct fpucontext *buf) { return 0; }
 static inline int fpu_restore_sigcontext(struct fpucontext *buf) { return 0; }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mn10300/include/asm/thread_info.h linux-libre-4.7-gnu/arch/mn10300/include/asm/thread_info.h
--- linux-libre-4.6-gnu/arch/mn10300/include/asm/thread_info.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mn10300/include/asm/thread_info.h	2016-07-24 15:23:50.000000000 -0400
@@ -115,7 +115,7 @@ static inline unsigned long current_stac
 }
 
 #ifndef CONFIG_KGDB
-void arch_release_thread_info(struct thread_info *ti);
+void arch_release_thread_stack(unsigned long *stack);
 #endif
 #define get_thread_info(ti)	get_task_struct((ti)->task)
 #define put_thread_info(ti)	put_task_struct((ti)->task)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mn10300/Kconfig linux-libre-4.7-gnu/arch/mn10300/Kconfig
--- linux-libre-4.6-gnu/arch/mn10300/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mn10300/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -1,5 +1,6 @@
 config MN10300
 	def_bool y
+	select HAVE_EXIT_THREAD
 	select HAVE_OPROFILE
 	select HAVE_UID16
 	select GENERIC_IRQ_SHOW
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mn10300/kernel/kgdb.c linux-libre-4.7-gnu/arch/mn10300/kernel/kgdb.c
--- linux-libre-4.6-gnu/arch/mn10300/kernel/kgdb.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mn10300/kernel/kgdb.c	2016-07-24 15:23:50.000000000 -0400
@@ -397,8 +397,9 @@ static bool kgdb_arch_undo_singlestep(st
  * single-step state is cleared.  At this point the breakpoints should have
  * been removed by __switch_to().
  */
-void arch_release_thread_info(struct thread_info *ti)
+void arch_release_thread_stack(unsigned long *stack)
 {
+	struct thread_info *ti = (void *)stack;
 	if (kgdb_sstep_thread == ti) {
 		kgdb_sstep_thread = NULL;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mn10300/kernel/process.c linux-libre-4.7-gnu/arch/mn10300/kernel/process.c
--- linux-libre-4.6-gnu/arch/mn10300/kernel/process.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mn10300/kernel/process.c	2016-07-24 15:23:50.000000000 -0400
@@ -103,9 +103,9 @@ void show_regs(struct pt_regs *regs)
 /*
  * free current thread data structures etc..
  */
-void exit_thread(void)
+void exit_thread(struct task_struct *tsk)
 {
-	exit_fpu();
+	exit_fpu(tsk);
 }
 
 void flush_thread(void)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/mn10300/mm/pgtable.c linux-libre-4.7-gnu/arch/mn10300/mm/pgtable.c
--- linux-libre-4.6-gnu/arch/mn10300/mm/pgtable.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/mn10300/mm/pgtable.c	2016-07-24 15:23:50.000000000 -0400
@@ -63,7 +63,7 @@ void set_pmd_pfn(unsigned long vaddr, un
 
 pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
 {
-	pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT);
+	pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL);
 	if (pte)
 		clear_page(pte);
 	return pte;
@@ -74,9 +74,9 @@ struct page *pte_alloc_one(struct mm_str
 	struct page *pte;
 
 #ifdef CONFIG_HIGHPTE
-	pte = alloc_pages(GFP_KERNEL|__GFP_HIGHMEM|__GFP_REPEAT, 0);
+	pte = alloc_pages(GFP_KERNEL|__GFP_HIGHMEM, 0);
 #else
-	pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT, 0);
+	pte = alloc_pages(GFP_KERNEL, 0);
 #endif
 	if (!pte)
 		return NULL;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/nios2/boot/compressed/Makefile linux-libre-4.7-gnu/arch/nios2/boot/compressed/Makefile
--- linux-libre-4.6-gnu/arch/nios2/boot/compressed/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/nios2/boot/compressed/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -11,7 +11,6 @@ LDFLAGS_vmlinux := -T
 
 $(obj)/vmlinux: $(obj)/vmlinux.lds $(OBJECTS) $(obj)/piggy.o FORCE
 	$(call if_changed,ld)
-	@:
 
 LDFLAGS_piggy.o := -r --format binary --oformat elf32-littlenios2 -T
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/nios2/include/asm/io.h linux-libre-4.7-gnu/arch/nios2/include/asm/io.h
--- linux-libre-4.6-gnu/arch/nios2/include/asm/io.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/nios2/include/asm/io.h	2016-07-24 15:23:50.000000000 -0400
@@ -50,7 +50,6 @@ static inline void iounmap(void __iomem
 
 /* Pages to physical address... */
 #define page_to_phys(page)	virt_to_phys(page_to_virt(page))
-#define page_to_bus(page)	page_to_virt(page)
 
 /* Macros used for converting between virtual and physical mappings. */
 #define phys_to_virt(vaddr)	\
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/nios2/include/asm/page.h linux-libre-4.7-gnu/arch/nios2/include/asm/page.h
--- linux-libre-4.6-gnu/arch/nios2/include/asm/page.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/nios2/include/asm/page.h	2016-07-24 15:23:50.000000000 -0400
@@ -84,7 +84,7 @@ extern struct page *mem_map;
 	((void *)((unsigned long)(x) + PAGE_OFFSET - PHYS_OFFSET))
 
 #define page_to_virt(page)	\
-	((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET)
+	((void *)(((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET)
 
 # define pfn_to_kaddr(pfn)	__va((pfn) << PAGE_SHIFT)
 # define pfn_valid(pfn)		((pfn) >= ARCH_PFN_OFFSET &&	\
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/nios2/include/asm/pgalloc.h linux-libre-4.7-gnu/arch/nios2/include/asm/pgalloc.h
--- linux-libre-4.6-gnu/arch/nios2/include/asm/pgalloc.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/nios2/include/asm/pgalloc.h	2016-07-24 15:23:50.000000000 -0400
@@ -42,8 +42,7 @@ static inline pte_t *pte_alloc_one_kerne
 {
 	pte_t *pte;
 
-	pte = (pte_t *) __get_free_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO,
-					PTE_ORDER);
+	pte = (pte_t *) __get_free_pages(GFP_KERNEL|__GFP_ZERO, PTE_ORDER);
 
 	return pte;
 }
@@ -53,7 +52,7 @@ static inline pgtable_t pte_alloc_one(st
 {
 	struct page *pte;
 
-	pte = alloc_pages(GFP_KERNEL | __GFP_REPEAT, PTE_ORDER);
+	pte = alloc_pages(GFP_KERNEL, PTE_ORDER);
 	if (pte) {
 		if (!pgtable_page_ctor(pte)) {
 			__free_page(pte);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/nios2/include/asm/pgtable.h linux-libre-4.7-gnu/arch/nios2/include/asm/pgtable.h
--- linux-libre-4.6-gnu/arch/nios2/include/asm/pgtable.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/nios2/include/asm/pgtable.h	2016-07-24 15:23:50.000000000 -0400
@@ -209,7 +209,7 @@ static inline void set_pte(pte_t *ptep,
 static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
 			      pte_t *ptep, pte_t pteval)
 {
-	unsigned long paddr = page_to_virt(pte_page(pteval));
+	unsigned long paddr = (unsigned long)page_to_virt(pte_page(pteval));
 
 	flush_dcache_range(paddr, paddr + PAGE_SIZE);
 	set_pte(ptep, pteval);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/nios2/include/asm/processor.h linux-libre-4.7-gnu/arch/nios2/include/asm/processor.h
--- linux-libre-4.6-gnu/arch/nios2/include/asm/processor.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/nios2/include/asm/processor.h	2016-07-24 15:23:50.000000000 -0400
@@ -75,11 +75,6 @@ static inline void release_thread(struct
 {
 }
 
-/* Free current thread data structures etc.. */
-static inline void exit_thread(void)
-{
-}
-
 /* Return saved PC of a blocked thread. */
 #define thread_saved_pc(tsk)	((tsk)->thread.kregs->ea)
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/nios2/include/uapi/asm/unistd.h linux-libre-4.7-gnu/arch/nios2/include/uapi/asm/unistd.h
--- linux-libre-4.6-gnu/arch/nios2/include/uapi/asm/unistd.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/nios2/include/uapi/asm/unistd.h	2016-07-24 15:23:50.000000000 -0400
@@ -17,6 +17,8 @@
 
  #define sys_mmap2 sys_mmap_pgoff
 
+#define __ARCH_WANT_RENAMEAT
+
 /* Use the standard ABI for syscalls */
 #include <asm-generic/unistd.h>
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/nios2/Kconfig linux-libre-4.7-gnu/arch/nios2/Kconfig
--- linux-libre-4.6-gnu/arch/nios2/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/nios2/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -1,6 +1,5 @@
 config NIOS2
 	def_bool y
-	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select CLKSRC_OF
 	select GENERIC_ATOMIC64
 	select GENERIC_CLOCKEVENTS
@@ -16,6 +15,7 @@ config NIOS2
 	select SOC_BUS
 	select SPARSE_IRQ
 	select USB_ARCH_HAS_HCD if USB_SUPPORT
+	select CPU_NO_EFFICIENT_FFS
 
 config GENERIC_CSUM
 	def_bool y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/nios2/Makefile linux-libre-4.7-gnu/arch/nios2/Makefile
--- linux-libre-4.6-gnu/arch/nios2/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/nios2/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -20,7 +20,7 @@ UTS_SYSNAME = Linux
 
 export MMU
 
-LIBGCC		:= $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
+LIBGCC         := $(shell $(CC) $(KBUILD_CFLAGS) $(KCFLAGS) -print-libgcc-file-name)
 
 KBUILD_CFLAGS += -pipe -D__linux__ -D__ELF__
 KBUILD_CFLAGS += $(if $(CONFIG_NIOS2_HW_MUL_SUPPORT),-mhw-mul,-mno-hw-mul)
@@ -53,7 +53,7 @@ all: vmImage
 archclean:
 	$(Q)$(MAKE) $(clean)=$(nios2-boot)
 
-%.dtb:
+%.dtb: | scripts
 	$(Q)$(MAKE) $(build)=$(nios2-boot) $(nios2-boot)/$@
 
 dtbs:
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/openrisc/include/asm/page.h linux-libre-4.7-gnu/arch/openrisc/include/asm/page.h
--- linux-libre-4.6-gnu/arch/openrisc/include/asm/page.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/openrisc/include/asm/page.h	2016-07-24 15:23:50.000000000 -0400
@@ -81,8 +81,6 @@ typedef struct page *pgtable_t;
 
 #define virt_to_page(addr) \
 	(mem_map + (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT))
-#define page_to_virt(page) \
-	((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET)
 
 #define page_to_phys(page)      ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT)
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/openrisc/include/asm/pgalloc.h linux-libre-4.7-gnu/arch/openrisc/include/asm/pgalloc.h
--- linux-libre-4.6-gnu/arch/openrisc/include/asm/pgalloc.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/openrisc/include/asm/pgalloc.h	2016-07-24 15:23:50.000000000 -0400
@@ -77,7 +77,7 @@ static inline struct page *pte_alloc_one
 					 unsigned long address)
 {
 	struct page *pte;
-	pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT, 0);
+	pte = alloc_pages(GFP_KERNEL, 0);
 	if (!pte)
 		return NULL;
 	clear_page(page_address(pte));
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/openrisc/include/asm/processor.h linux-libre-4.7-gnu/arch/openrisc/include/asm/processor.h
--- linux-libre-4.6-gnu/arch/openrisc/include/asm/processor.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/openrisc/include/asm/processor.h	2016-07-24 15:23:50.000000000 -0400
@@ -85,15 +85,6 @@ void release_thread(struct task_struct *
 unsigned long get_wchan(struct task_struct *p);
 
 /*
- * Free current thread data structures etc..
- */
-
-extern inline void exit_thread(void)
-{
-	/* Nothing needs to be done.  */
-}
-
-/*
  * Return saved PC of a blocked thread. For now, this is the "user" PC
  */
 extern unsigned long thread_saved_pc(struct task_struct *t);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/openrisc/include/uapi/asm/unistd.h linux-libre-4.7-gnu/arch/openrisc/include/uapi/asm/unistd.h
--- linux-libre-4.6-gnu/arch/openrisc/include/uapi/asm/unistd.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/openrisc/include/uapi/asm/unistd.h	2016-07-24 15:23:50.000000000 -0400
@@ -20,6 +20,7 @@
 
 #define sys_mmap2 sys_mmap_pgoff
 
+#define __ARCH_WANT_RENAMEAT
 #define __ARCH_WANT_SYS_FORK
 #define __ARCH_WANT_SYS_CLONE
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/openrisc/Kconfig linux-libre-4.7-gnu/arch/openrisc/Kconfig
--- linux-libre-4.6-gnu/arch/openrisc/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/openrisc/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -25,6 +25,7 @@ config OPENRISC
 	select MODULES_USE_ELF_RELA
 	select HAVE_DEBUG_STACKOVERFLOW
 	select OR1K_PIC
+	select CPU_NO_EFFICIENT_FFS if !OPENRISC_HAVE_INST_FF1
 
 config MMU
 	def_bool y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/openrisc/mm/ioremap.c linux-libre-4.7-gnu/arch/openrisc/mm/ioremap.c
--- linux-libre-4.6-gnu/arch/openrisc/mm/ioremap.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/openrisc/mm/ioremap.c	2016-07-24 15:23:50.000000000 -0400
@@ -122,7 +122,7 @@ pte_t __init_refok *pte_alloc_one_kernel
 	pte_t *pte;
 
 	if (likely(mem_init_done)) {
-		pte = (pte_t *) __get_free_page(GFP_KERNEL | __GFP_REPEAT);
+		pte = (pte_t *) __get_free_page(GFP_KERNEL);
 	} else {
 		pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
 #if 0
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/parisc/include/asm/cmpxchg.h linux-libre-4.7-gnu/arch/parisc/include/asm/cmpxchg.h
--- linux-libre-4.6-gnu/arch/parisc/include/asm/cmpxchg.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/parisc/include/asm/cmpxchg.h	2016-07-24 15:23:50.000000000 -0400
@@ -52,8 +52,7 @@ extern void __cmpxchg_called_with_bad_po
 /* __cmpxchg_u32/u64 defined in arch/parisc/lib/bitops.c */
 extern unsigned long __cmpxchg_u32(volatile unsigned int *m, unsigned int old,
 				   unsigned int new_);
-extern unsigned long __cmpxchg_u64(volatile unsigned long *ptr,
-				   unsigned long old, unsigned long new_);
+extern u64 __cmpxchg_u64(volatile u64 *ptr, u64 old, u64 new_);
 
 /* don't worry...optimizer will get rid of most of this */
 static inline unsigned long
@@ -61,7 +60,7 @@ __cmpxchg(volatile void *ptr, unsigned l
 {
 	switch (size) {
 #ifdef CONFIG_64BIT
-	case 8: return __cmpxchg_u64((unsigned long *)ptr, old, new_);
+	case 8: return __cmpxchg_u64((u64 *)ptr, old, new_);
 #endif
 	case 4: return __cmpxchg_u32((unsigned int *)ptr,
 				     (unsigned int)old, (unsigned int)new_);
@@ -86,7 +85,7 @@ static inline unsigned long __cmpxchg_lo
 {
 	switch (size) {
 #ifdef CONFIG_64BIT
-	case 8:	return __cmpxchg_u64((unsigned long *)ptr, old, new_);
+	case 8:	return __cmpxchg_u64((u64 *)ptr, old, new_);
 #endif
 	case 4:	return __cmpxchg_u32(ptr, old, new_);
 	default:
@@ -111,4 +110,6 @@ static inline unsigned long __cmpxchg_lo
 #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
 #endif
 
+#define cmpxchg64(ptr, o, n) __cmpxchg_u64(ptr, o, n)
+
 #endif /* _ASM_PARISC_CMPXCHG_H_ */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/parisc/include/asm/eisa_eeprom.h linux-libre-4.7-gnu/arch/parisc/include/asm/eisa_eeprom.h
--- linux-libre-4.6-gnu/arch/parisc/include/asm/eisa_eeprom.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/parisc/include/asm/eisa_eeprom.h	2016-07-24 15:23:50.000000000 -0400
@@ -99,7 +99,7 @@ struct eeprom_eisa_slot_info
 #define HPEE_MEMORY_DECODE_24BITS 0x04
 #define HPEE_MEMORY_DECODE_32BITS 0x08
 /* byte 2 and 3 are a 16bit LE value
- * containging the memory size in kilobytes */
+ * containing the memory size in kilobytes */
 /* byte 4,5,6 are a 24bit LE value
  * containing the memory base address */
 
@@ -135,7 +135,7 @@ struct eeprom_eisa_slot_info
 #define HPEE_PORT_SHARED    0x40
 #define HPEE_PORT_MORE      0x80
 /* byte 1 and 2 is a 16bit LE value
- * conating the start port number */
+ * containing the start port number */
 
 #define HPEE_PORT_INIT_MAX_LEN     60 /* in bytes here */
 /* port init entry byte 0 */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/parisc/include/asm/ftrace.h linux-libre-4.7-gnu/arch/parisc/include/asm/ftrace.h
--- linux-libre-4.6-gnu/arch/parisc/include/asm/ftrace.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/parisc/include/asm/ftrace.h	2016-07-24 15:23:50.000000000 -0400
@@ -6,6 +6,8 @@ extern void mcount(void);
 
 #define MCOUNT_INSN_SIZE 4
 
+extern unsigned long sys_call_table[];
+
 extern unsigned long return_address(unsigned int);
 
 #define ftrace_return_address(n) return_address(n)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/parisc/include/asm/futex.h linux-libre-4.7-gnu/arch/parisc/include/asm/futex.h
--- linux-libre-4.6-gnu/arch/parisc/include/asm/futex.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/parisc/include/asm/futex.h	2016-07-24 15:23:50.000000000 -0400
@@ -35,70 +35,57 @@ static inline int
 futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 {
 	unsigned long int flags;
-	u32 val;
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
 	int oparg = (encoded_op << 8) >> 20;
 	int cmparg = (encoded_op << 20) >> 20;
-	int oldval = 0, ret;
+	int oldval, ret;
+	u32 tmp;
+
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
 	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(*uaddr)))
 		return -EFAULT;
 
+	_futex_spin_lock_irqsave(uaddr, &flags);
 	pagefault_disable();
 
-	_futex_spin_lock_irqsave(uaddr, &flags);
+	ret = -EFAULT;
+	if (unlikely(get_user(oldval, uaddr) != 0))
+		goto out_pagefault_enable;
+
+	ret = 0;
+	tmp = oldval;
 
 	switch (op) {
 	case FUTEX_OP_SET:
-		/* *(int *)UADDR2 = OPARG; */
-		ret = get_user(oldval, uaddr);
-		if (!ret)
-			ret = put_user(oparg, uaddr);
+		tmp = oparg;
 		break;
 	case FUTEX_OP_ADD:
-		/* *(int *)UADDR2 += OPARG; */
-		ret = get_user(oldval, uaddr);
-		if (!ret) {
-			val = oldval + oparg;
-			ret = put_user(val, uaddr);
-		}
+		tmp += oparg;
 		break;
 	case FUTEX_OP_OR:
-		/* *(int *)UADDR2 |= OPARG; */
-		ret = get_user(oldval, uaddr);
-		if (!ret) {
-			val = oldval | oparg;
-			ret = put_user(val, uaddr);
-		}
+		tmp |= oparg;
 		break;
 	case FUTEX_OP_ANDN:
-		/* *(int *)UADDR2 &= ~OPARG; */
-		ret = get_user(oldval, uaddr);
-		if (!ret) {
-			val = oldval & ~oparg;
-			ret = put_user(val, uaddr);
-		}
+		tmp &= ~oparg;
 		break;
 	case FUTEX_OP_XOR:
-		/* *(int *)UADDR2 ^= OPARG; */
-		ret = get_user(oldval, uaddr);
-		if (!ret) {
-			val = oldval ^ oparg;
-			ret = put_user(val, uaddr);
-		}
+		tmp ^= oparg;
 		break;
 	default:
 		ret = -ENOSYS;
 	}
 
-	_futex_spin_unlock_irqrestore(uaddr, &flags);
+	if (ret == 0 && unlikely(put_user(tmp, uaddr) != 0))
+		ret = -EFAULT;
 
+out_pagefault_enable:
 	pagefault_enable();
+	_futex_spin_unlock_irqrestore(uaddr, &flags);
 
-	if (!ret) {
+	if (ret == 0) {
 		switch (cmp) {
 		case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
 		case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
@@ -112,12 +99,10 @@ futex_atomic_op_inuser (int encoded_op,
 	return ret;
 }
 
-/* Non-atomic version */
 static inline int
 futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
 			      u32 oldval, u32 newval)
 {
-	int ret;
 	u32 val;
 	unsigned long flags;
 
@@ -137,17 +122,20 @@ futex_atomic_cmpxchg_inatomic(u32 *uval,
 	 */
 
 	_futex_spin_lock_irqsave(uaddr, &flags);
+	if (unlikely(get_user(val, uaddr) != 0)) {
+		_futex_spin_unlock_irqrestore(uaddr, &flags);
+		return -EFAULT;
+	}
 
-	ret = get_user(val, uaddr);
-
-	if (!ret && val == oldval)
-		ret = put_user(newval, uaddr);
+	if (val == oldval && unlikely(put_user(newval, uaddr) != 0)) {
+		_futex_spin_unlock_irqrestore(uaddr, &flags);
+		return -EFAULT;
+	}
 
 	*uval = val;
-
 	_futex_spin_unlock_irqrestore(uaddr, &flags);
 
-	return ret;
+	return 0;
 }
 
 #endif /*__KERNEL__*/
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/parisc/include/asm/ldcw.h linux-libre-4.7-gnu/arch/parisc/include/asm/ldcw.h
--- linux-libre-4.6-gnu/arch/parisc/include/asm/ldcw.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/parisc/include/asm/ldcw.h	2016-07-24 15:23:50.000000000 -0400
@@ -40,7 +40,7 @@
    memory to indicate to the compiler that the assembly code reads
    or writes to items other than those listed in the input and output
    operands.  This may pessimize the code somewhat but __ldcw is
-   usually used within code blocks surrounded by memory barriors.  */
+   usually used within code blocks surrounded by memory barriers.  */
 #define __ldcw(a) ({						\
 	unsigned __ret;						\
 	__asm__ __volatile__(__LDCW " 0(%1),%0"			\
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/parisc/include/asm/pgalloc.h linux-libre-4.7-gnu/arch/parisc/include/asm/pgalloc.h
--- linux-libre-4.6-gnu/arch/parisc/include/asm/pgalloc.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/parisc/include/asm/pgalloc.h	2016-07-24 15:23:50.000000000 -0400
@@ -63,8 +63,7 @@ static inline void pgd_populate(struct m
 
 static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
 {
-	pmd_t *pmd = (pmd_t *)__get_free_pages(GFP_KERNEL|__GFP_REPEAT,
-					       PMD_ORDER);
+	pmd_t *pmd = (pmd_t *)__get_free_pages(GFP_KERNEL, PMD_ORDER);
 	if (pmd)
 		memset(pmd, 0, PAGE_SIZE<<PMD_ORDER);
 	return pmd;
@@ -124,7 +123,7 @@ pmd_populate_kernel(struct mm_struct *mm
 static inline pgtable_t
 pte_alloc_one(struct mm_struct *mm, unsigned long address)
 {
-	struct page *page = alloc_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
+	struct page *page = alloc_page(GFP_KERNEL|__GFP_ZERO);
 	if (!page)
 		return NULL;
 	if (!pgtable_page_ctor(page)) {
@@ -137,7 +136,7 @@ pte_alloc_one(struct mm_struct *mm, unsi
 static inline pte_t *
 pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr)
 {
-	pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
+	pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_ZERO);
 	return pte;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/parisc/include/asm/syscall.h linux-libre-4.7-gnu/arch/parisc/include/asm/syscall.h
--- linux-libre-4.6-gnu/arch/parisc/include/asm/syscall.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/parisc/include/asm/syscall.h	2016-07-24 15:23:50.000000000 -0400
@@ -8,6 +8,8 @@
 #include <linux/err.h>
 #include <asm/ptrace.h>
 
+#define NR_syscalls (__NR_Linux_syscalls)
+
 static inline long syscall_get_nr(struct task_struct *tsk,
 				  struct pt_regs *regs)
 {
@@ -33,12 +35,19 @@ static inline void syscall_get_arguments
 		args[1] = regs->gr[25];
 	case 1:
 		args[0] = regs->gr[26];
+	case 0:
 		break;
 	default:
 		BUG();
 	}
 }
 
+static inline long syscall_get_return_value(struct task_struct *task,
+						struct pt_regs *regs)
+{
+	return regs->gr[28];
+}
+
 static inline void syscall_set_return_value(struct task_struct *task,
 					    struct pt_regs *regs,
 					    int error, long val)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/parisc/include/asm/thread_info.h linux-libre-4.7-gnu/arch/parisc/include/asm/thread_info.h
--- linux-libre-4.6-gnu/arch/parisc/include/asm/thread_info.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/parisc/include/asm/thread_info.h	2016-07-24 15:23:50.000000000 -0400
@@ -55,6 +55,7 @@ struct thread_info {
 #define TIF_SINGLESTEP		9	/* single stepping? */
 #define TIF_BLOCKSTEP		10	/* branch stepping? */
 #define TIF_SECCOMP		11	/* secure computing */
+#define TIF_SYSCALL_TRACEPOINT	12	/* syscall tracepoint instrumentation */
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
@@ -66,12 +67,13 @@ struct thread_info {
 #define _TIF_SINGLESTEP		(1 << TIF_SINGLESTEP)
 #define _TIF_BLOCKSTEP		(1 << TIF_BLOCKSTEP)
 #define _TIF_SECCOMP		(1 << TIF_SECCOMP)
+#define _TIF_SYSCALL_TRACEPOINT	(1 << TIF_SYSCALL_TRACEPOINT)
 
 #define _TIF_USER_WORK_MASK     (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | \
                                  _TIF_NEED_RESCHED)
 #define _TIF_SYSCALL_TRACE_MASK (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP |	\
 				 _TIF_BLOCKSTEP | _TIF_SYSCALL_AUDIT | \
-				 _TIF_SECCOMP)
+				 _TIF_SECCOMP | _TIF_SYSCALL_TRACEPOINT)
 
 #ifdef CONFIG_64BIT
 # ifdef CONFIG_COMPAT
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/parisc/include/asm/traps.h linux-libre-4.7-gnu/arch/parisc/include/asm/traps.h
--- linux-libre-4.6-gnu/arch/parisc/include/asm/traps.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/parisc/include/asm/traps.h	2016-07-24 15:23:50.000000000 -0400
@@ -8,6 +8,8 @@ struct pt_regs;
 void parisc_terminate(char *msg, struct pt_regs *regs,
 		int code, unsigned long offset) __noreturn __cold;
 
+void die_if_kernel(char *str, struct pt_regs *regs, long err);
+
 /* mm/fault.c */
 void do_page_fault(struct pt_regs *regs, unsigned long code,
 		unsigned long address);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/parisc/include/asm/uaccess.h linux-libre-4.7-gnu/arch/parisc/include/asm/uaccess.h
--- linux-libre-4.6-gnu/arch/parisc/include/asm/uaccess.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/parisc/include/asm/uaccess.h	2016-07-24 15:23:50.000000000 -0400
@@ -40,14 +40,10 @@ static inline long access_ok(int type, c
 #define get_user __get_user
 
 #if !defined(CONFIG_64BIT)
-#define LDD_KERNEL(ptr)		BUILD_BUG()
-#define LDD_USER(ptr)		BUILD_BUG()
-#define STD_KERNEL(x, ptr)	__put_kernel_asm64(x, ptr)
+#define LDD_USER(ptr)		__get_user_asm64(ptr)
 #define STD_USER(x, ptr)	__put_user_asm64(x, ptr)
 #else
-#define LDD_KERNEL(ptr)		__get_kernel_asm("ldd", ptr)
 #define LDD_USER(ptr)		__get_user_asm("ldd", ptr)
-#define STD_KERNEL(x, ptr)	__put_kernel_asm("std", x, ptr)
 #define STD_USER(x, ptr)	__put_user_asm("std", x, ptr)
 #endif
 
@@ -80,70 +76,70 @@ struct exception_data {
 	unsigned long fault_addr;
 };
 
+/*
+ * load_sr2() preloads the space register %%sr2 - based on the value of
+ * get_fs() - with either a value of 0 to access kernel space (KERNEL_DS which
+ * is 0), or with the current value of %%sr3 to access user space (USER_DS)
+ * memory. The following __get_user_asm() and __put_user_asm() functions have
+ * %%sr2 hard-coded to access the requested memory.
+ */
+#define load_sr2() \
+	__asm__(" or,=  %0,%%r0,%%r0\n\t"	\
+		" mfsp %%sr3,%0\n\t"		\
+		" mtsp %0,%%sr2\n\t"		\
+		: : "r"(get_fs()) : )
+
 #define __get_user(x, ptr)                               \
 ({                                                       \
 	register long __gu_err __asm__ ("r8") = 0;       \
 	register long __gu_val __asm__ ("r9") = 0;       \
 							 \
-	if (segment_eq(get_fs(), KERNEL_DS)) {           \
-	    switch (sizeof(*(ptr))) {                    \
-	    case 1: __get_kernel_asm("ldb", ptr); break; \
-	    case 2: __get_kernel_asm("ldh", ptr); break; \
-	    case 4: __get_kernel_asm("ldw", ptr); break; \
-	    case 8: LDD_KERNEL(ptr); break;		 \
-	    default: BUILD_BUG(); break;		 \
-	    }                                            \
-	}                                                \
-	else {                                           \
-	    switch (sizeof(*(ptr))) {                    \
+	load_sr2();					 \
+	switch (sizeof(*(ptr))) {			 \
 	    case 1: __get_user_asm("ldb", ptr); break;   \
 	    case 2: __get_user_asm("ldh", ptr); break;   \
 	    case 4: __get_user_asm("ldw", ptr); break;   \
 	    case 8: LDD_USER(ptr);  break;		 \
 	    default: BUILD_BUG(); break;		 \
-	    }                                            \
 	}                                                \
 							 \
 	(x) = (__force __typeof__(*(ptr))) __gu_val;	 \
 	__gu_err;                                        \
 })
 
-#define __get_kernel_asm(ldx, ptr)                      \
-	__asm__("\n1:\t" ldx "\t0(%2),%0\n\t"		\
+#define __get_user_asm(ldx, ptr)                        \
+	__asm__("\n1:\t" ldx "\t0(%%sr2,%2),%0\n\t"	\
 		ASM_EXCEPTIONTABLE_ENTRY(1b, fixup_get_user_skip_1)\
 		: "=r"(__gu_val), "=r"(__gu_err)        \
 		: "r"(ptr), "1"(__gu_err)		\
 		: "r1");
 
-#define __get_user_asm(ldx, ptr)                        \
-	__asm__("\n1:\t" ldx "\t0(%%sr3,%2),%0\n\t"	\
-		ASM_EXCEPTIONTABLE_ENTRY(1b, fixup_get_user_skip_1)\
-		: "=r"(__gu_val), "=r"(__gu_err)        \
+#if !defined(CONFIG_64BIT)
+
+#define __get_user_asm64(ptr) 				\
+	__asm__("\n1:\tldw 0(%%sr2,%2),%0"		\
+		"\n2:\tldw 4(%%sr2,%2),%R0\n\t"		\
+		ASM_EXCEPTIONTABLE_ENTRY(1b, fixup_get_user_skip_2)\
+		ASM_EXCEPTIONTABLE_ENTRY(2b, fixup_get_user_skip_1)\
+		: "=r"(__gu_val), "=r"(__gu_err)	\
 		: "r"(ptr), "1"(__gu_err)		\
 		: "r1");
 
+#endif /* !defined(CONFIG_64BIT) */
+
+
 #define __put_user(x, ptr)                                      \
 ({								\
 	register long __pu_err __asm__ ("r8") = 0;      	\
         __typeof__(*(ptr)) __x = (__typeof__(*(ptr)))(x);	\
 								\
-	if (segment_eq(get_fs(), KERNEL_DS)) {                  \
-	    switch (sizeof(*(ptr))) {                           \
-	    case 1: __put_kernel_asm("stb", __x, ptr); break;   \
-	    case 2: __put_kernel_asm("sth", __x, ptr); break;   \
-	    case 4: __put_kernel_asm("stw", __x, ptr); break;   \
-	    case 8: STD_KERNEL(__x, ptr); break;		\
-	    default: BUILD_BUG(); break;			\
-	    }                                                   \
-	}                                                       \
-	else {                                                  \
-	    switch (sizeof(*(ptr))) {                           \
+	load_sr2();						\
+	switch (sizeof(*(ptr))) {				\
 	    case 1: __put_user_asm("stb", __x, ptr); break;     \
 	    case 2: __put_user_asm("sth", __x, ptr); break;     \
 	    case 4: __put_user_asm("stw", __x, ptr); break;     \
 	    case 8: STD_USER(__x, ptr); break;			\
 	    default: BUILD_BUG(); break;			\
-	    }                                                   \
 	}                                                       \
 								\
 	__pu_err;						\
@@ -159,17 +155,9 @@ struct exception_data {
  * r8/r9 are already listed as err/val.
  */
 
-#define __put_kernel_asm(stx, x, ptr)                       \
-	__asm__ __volatile__ (                              \
-		"\n1:\t" stx "\t%2,0(%1)\n\t"		    \
-		ASM_EXCEPTIONTABLE_ENTRY(1b, fixup_put_user_skip_1)\
-		: "=r"(__pu_err)                            \
-		: "r"(ptr), "r"(x), "0"(__pu_err)	    \
-	    	: "r1")
-
 #define __put_user_asm(stx, x, ptr)                         \
 	__asm__ __volatile__ (                              \
-		"\n1:\t" stx "\t%2,0(%%sr3,%1)\n\t"	    \
+		"\n1:\t" stx "\t%2,0(%%sr2,%1)\n\t"	    \
 		ASM_EXCEPTIONTABLE_ENTRY(1b, fixup_put_user_skip_1)\
 		: "=r"(__pu_err)                            \
 		: "r"(ptr), "r"(x), "0"(__pu_err)	    \
@@ -178,21 +166,10 @@ struct exception_data {
 
 #if !defined(CONFIG_64BIT)
 
-#define __put_kernel_asm64(__val, ptr) do {		    \
-	__asm__ __volatile__ (				    \
-		"\n1:\tstw %2,0(%1)"			    \
-		"\n2:\tstw %R2,4(%1)\n\t"		    \
-		ASM_EXCEPTIONTABLE_ENTRY(1b, fixup_put_user_skip_2)\
-		ASM_EXCEPTIONTABLE_ENTRY(2b, fixup_put_user_skip_1)\
-		: "=r"(__pu_err)                            \
-		: "r"(ptr), "r"(__val), "0"(__pu_err) \
-		: "r1");				    \
-} while (0)
-
 #define __put_user_asm64(__val, ptr) do {	    	    \
 	__asm__ __volatile__ (				    \
-		"\n1:\tstw %2,0(%%sr3,%1)"		    \
-		"\n2:\tstw %R2,4(%%sr3,%1)\n\t"		    \
+		"\n1:\tstw %2,0(%%sr2,%1)"		    \
+		"\n2:\tstw %R2,4(%%sr2,%1)\n\t"		    \
 		ASM_EXCEPTIONTABLE_ENTRY(1b, fixup_put_user_skip_2)\
 		ASM_EXCEPTIONTABLE_ENTRY(2b, fixup_put_user_skip_1)\
 		: "=r"(__pu_err)                            \
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/parisc/include/uapi/asm/pdc.h linux-libre-4.7-gnu/arch/parisc/include/uapi/asm/pdc.h
--- linux-libre-4.6-gnu/arch/parisc/include/uapi/asm/pdc.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/parisc/include/uapi/asm/pdc.h	2016-07-24 15:23:50.000000000 -0400
@@ -59,7 +59,7 @@
 #define PDC_MODEL_GET_BOOT__OP	8	/* returns boot test options	*/
 #define PDC_MODEL_SET_BOOT__OP	9	/* set boot test options	*/
 
-#define PA89_INSTRUCTION_SET	0x4	/* capatibilies returned	*/
+#define PA89_INSTRUCTION_SET	0x4	/* capabilities returned	*/
 #define PA90_INSTRUCTION_SET	0x8
 
 #define PDC_CACHE	5		/* return/set cache (& TLB) info*/
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/parisc/include/uapi/asm/ptrace.h linux-libre-4.7-gnu/arch/parisc/include/uapi/asm/ptrace.h
--- linux-libre-4.6-gnu/arch/parisc/include/uapi/asm/ptrace.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/parisc/include/uapi/asm/ptrace.h	2016-07-24 15:23:50.000000000 -0400
@@ -13,6 +13,11 @@
  * N.B. gdb/strace care about the size and offsets within this
  * structure. If you change things, you may break object compatibility
  * for those applications.
+ *
+ * Please do NOT use this structure for future programs, but use
+ * user_regs_struct (see below) instead.
+ *
+ * It can be accessed through PTRACE_PEEKUSR/PTRACE_POKEUSR only.
  */
 
 struct pt_regs {
@@ -33,6 +38,45 @@ struct pt_regs {
 	unsigned long ipsw;	/* CR22 */
 };
 
+/**
+ * struct user_regs_struct - User general purpose registers
+ *
+ * This is the user-visible general purpose register state structure
+ * which is used to define the elf_gregset_t.
+ *
+ * It can be accessed through PTRACE_GETREGSET with NT_PRSTATUS
+ * and through PTRACE_GETREGS.
+ */
+struct user_regs_struct {
+	unsigned long gr[32];	/* PSW is in gr[0] */
+	unsigned long sr[8];
+	unsigned long iaoq[2];
+	unsigned long iasq[2];
+	unsigned long sar;	/* CR11 */
+	unsigned long iir;	/* CR19 */
+	unsigned long isr;	/* CR20 */
+	unsigned long ior;	/* CR21 */
+	unsigned long ipsw;	/* CR22 */
+	unsigned long cr0;
+	unsigned long cr24, cr25, cr26, cr27, cr28, cr29, cr30, cr31;
+	unsigned long cr8, cr9, cr12, cr13, cr10, cr15;
+	unsigned long _pad[80-64];	/* pad to ELF_NGREG (80) */
+};
+
+/**
+ * struct user_fp_struct - User floating point registers
+ *
+ * This is the user-visible floating point register state structure.
+ * It uses the same layout and size as elf_fpregset_t.
+ *
+ * It can be accessed through PTRACE_GETREGSET with NT_PRFPREG
+ * and through PTRACE_GETFPREGS.
+ */
+struct user_fp_struct {
+	__u64 fr[32];
+};
+
+
 /*
  * The numbers chosen here are somewhat arbitrary but absolutely MUST
  * not overlap with any of the number assigned in <linux/ptrace.h>.
@@ -43,5 +87,9 @@ struct pt_regs {
  */
 #define PTRACE_SINGLEBLOCK	12	/* resume execution until next branch */
 
+#define PTRACE_GETREGS		18
+#define PTRACE_SETREGS		19
+#define PTRACE_GETFPREGS	14
+#define PTRACE_SETFPREGS	15
 
 #endif /* _UAPI_PARISC_PTRACE_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/parisc/include/uapi/asm/unistd.h linux-libre-4.7-gnu/arch/parisc/include/uapi/asm/unistd.h
--- linux-libre-4.6-gnu/arch/parisc/include/uapi/asm/unistd.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/parisc/include/uapi/asm/unistd.h	2016-07-24 15:23:50.000000000 -0400
@@ -102,7 +102,7 @@
 #define __NR_uselib              (__NR_Linux + 86)
 #define __NR_swapon              (__NR_Linux + 87)
 #define __NR_reboot              (__NR_Linux + 88)
-#define __NR_mmap2             (__NR_Linux + 89)
+#define __NR_mmap2               (__NR_Linux + 89)
 #define __NR_mmap                (__NR_Linux + 90)
 #define __NR_munmap              (__NR_Linux + 91)
 #define __NR_truncate            (__NR_Linux + 92)
@@ -114,7 +114,7 @@
 #define __NR_recv                (__NR_Linux + 98)
 #define __NR_statfs              (__NR_Linux + 99)
 #define __NR_fstatfs            (__NR_Linux + 100)
-#define __NR_stat64           (__NR_Linux + 101)
+#define __NR_stat64             (__NR_Linux + 101)
 /* #define __NR_socketcall         (__NR_Linux + 102) */
 #define __NR_syslog             (__NR_Linux + 103)
 #define __NR_setitimer          (__NR_Linux + 104)
@@ -140,17 +140,17 @@
 #define __NR_adjtimex           (__NR_Linux + 124)
 #define __NR_mprotect           (__NR_Linux + 125)
 #define __NR_sigprocmask        (__NR_Linux + 126)
-#define __NR_create_module      (__NR_Linux + 127)
+#define __NR_create_module      (__NR_Linux + 127) /* not used */
 #define __NR_init_module        (__NR_Linux + 128)
 #define __NR_delete_module      (__NR_Linux + 129)
-#define __NR_get_kernel_syms    (__NR_Linux + 130)
+#define __NR_get_kernel_syms    (__NR_Linux + 130) /* not used */
 #define __NR_quotactl           (__NR_Linux + 131)
 #define __NR_getpgid            (__NR_Linux + 132)
 #define __NR_fchdir             (__NR_Linux + 133)
 #define __NR_bdflush            (__NR_Linux + 134)
 #define __NR_sysfs              (__NR_Linux + 135)
 #define __NR_personality        (__NR_Linux + 136)
-#define __NR_afs_syscall        (__NR_Linux + 137) /* Syscall for Andrew File System */
+#define __NR_afs_syscall        (__NR_Linux + 137) /* not used */
 #define __NR_setfsuid           (__NR_Linux + 138)
 #define __NR_setfsgid           (__NR_Linux + 139)
 #define __NR__llseek            (__NR_Linux + 140)
@@ -180,9 +180,9 @@
 #define __NR_setresuid          (__NR_Linux + 164)
 #define __NR_getresuid          (__NR_Linux + 165)
 #define __NR_sigaltstack        (__NR_Linux + 166)
-#define __NR_query_module       (__NR_Linux + 167)
+#define __NR_query_module       (__NR_Linux + 167) /* not used */
 #define __NR_poll               (__NR_Linux + 168)
-#define __NR_nfsservctl         (__NR_Linux + 169)
+#define __NR_nfsservctl         (__NR_Linux + 169) /* not used */
 #define __NR_setresgid          (__NR_Linux + 170)
 #define __NR_getresgid          (__NR_Linux + 171)
 #define __NR_prctl              (__NR_Linux + 172)
@@ -209,18 +209,16 @@
 #define __NR_shmdt              (__NR_Linux + 193)
 #define __NR_shmget             (__NR_Linux + 194)
 #define __NR_shmctl             (__NR_Linux + 195)
-
-#define __NR_getpmsg		(__NR_Linux + 196) /* Somebody *wants* streams? */
-#define __NR_putpmsg		(__NR_Linux + 197)
-
+#define __NR_getpmsg            (__NR_Linux + 196) /* not used */
+#define __NR_putpmsg            (__NR_Linux + 197) /* not used */
 #define __NR_lstat64            (__NR_Linux + 198)
 #define __NR_truncate64         (__NR_Linux + 199)
 #define __NR_ftruncate64        (__NR_Linux + 200)
 #define __NR_getdents64         (__NR_Linux + 201)
 #define __NR_fcntl64            (__NR_Linux + 202)
-#define __NR_attrctl            (__NR_Linux + 203)
-#define __NR_acl_get            (__NR_Linux + 204)
-#define __NR_acl_set            (__NR_Linux + 205)
+#define __NR_attrctl            (__NR_Linux + 203) /* not used */
+#define __NR_acl_get            (__NR_Linux + 204) /* not used */
+#define __NR_acl_set            (__NR_Linux + 205) /* not used */
 #define __NR_gettid             (__NR_Linux + 206)
 #define __NR_readahead          (__NR_Linux + 207)
 #define __NR_tkill              (__NR_Linux + 208)
@@ -228,8 +226,8 @@
 #define __NR_futex              (__NR_Linux + 210)
 #define __NR_sched_setaffinity  (__NR_Linux + 211)
 #define __NR_sched_getaffinity  (__NR_Linux + 212)
-#define __NR_set_thread_area    (__NR_Linux + 213)
-#define __NR_get_thread_area    (__NR_Linux + 214)
+#define __NR_set_thread_area    (__NR_Linux + 213) /* not used */
+#define __NR_get_thread_area    (__NR_Linux + 214) /* not used */
 #define __NR_io_setup           (__NR_Linux + 215)
 #define __NR_io_destroy         (__NR_Linux + 216)
 #define __NR_io_getevents       (__NR_Linux + 217)
@@ -278,7 +276,7 @@
 #define __NR_mbind		(__NR_Linux + 260)
 #define __NR_get_mempolicy	(__NR_Linux + 261)
 #define __NR_set_mempolicy	(__NR_Linux + 262)
-#define __NR_vserver		(__NR_Linux + 263)
+#define __NR_vserver		(__NR_Linux + 263) /* not used */
 #define __NR_add_key		(__NR_Linux + 264)
 #define __NR_request_key	(__NR_Linux + 265)
 #define __NR_keyctl		(__NR_Linux + 266)
@@ -318,7 +316,7 @@
 #define __NR_kexec_load		(__NR_Linux + 300)
 #define __NR_utimensat		(__NR_Linux + 301)
 #define __NR_signalfd		(__NR_Linux + 302)
-#define __NR_timerfd		(__NR_Linux + 303)
+#define __NR_timerfd		(__NR_Linux + 303) /* not used */
 #define __NR_eventfd		(__NR_Linux + 304)
 #define __NR_fallocate		(__NR_Linux + 305)
 #define __NR_timerfd_create	(__NR_Linux + 306)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/parisc/Kconfig linux-libre-4.7-gnu/arch/parisc/Kconfig
--- linux-libre-4.6-gnu/arch/parisc/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/parisc/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -6,6 +6,7 @@ config PARISC
 	select HAVE_OPROFILE
 	select HAVE_FUNCTION_TRACER
 	select HAVE_FUNCTION_GRAPH_TRACER
+	select HAVE_SYSCALL_TRACEPOINTS
 	select ARCH_WANT_FRAME_POINTERS
 	select RTC_CLASS
 	select RTC_DRV_GENERIC
@@ -31,7 +32,10 @@ config PARISC
 	select HAVE_DEBUG_STACKOVERFLOW
 	select HAVE_ARCH_AUDITSYSCALL
 	select HAVE_ARCH_SECCOMP_FILTER
+	select HAVE_ARCH_TRACEHOOK
+	select HAVE_UNSTABLE_SCHED_CLOCK if (SMP || !64BIT)
 	select ARCH_NO_COHERENT_DMA_MMAP
+	select CPU_NO_EFFICIENT_FFS
 
 	help
 	  The PA-RISC microprocessor is designed by Hewlett-Packard and used
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/parisc/kernel/entry.S linux-libre-4.7-gnu/arch/parisc/kernel/entry.S
--- linux-libre-4.6-gnu/arch/parisc/kernel/entry.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/parisc/kernel/entry.S	2016-07-24 15:23:50.000000000 -0400
@@ -667,7 +667,7 @@
 	 * boundary
 	 */
 
-	.text
+	.section .text.hot
 	.align 2048
 
 ENTRY(fault_vector_20)
@@ -2019,6 +2019,7 @@ ftrace_stub:
 	.procend
 ENDPROC(mcount)
 
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
 	.align 8
 	.globl return_to_handler
 	.type  return_to_handler, @function
@@ -2040,11 +2041,17 @@ parisc_return_to_handler:
 #endif
 
 	/* call ftrace_return_to_handler(0) */
+	.import ftrace_return_to_handler,code
+	load32 ftrace_return_to_handler,%ret0
+	load32 .Lftrace_ret,%r2
 #ifdef CONFIG_64BIT
 	ldo -16(%sp),%ret1		/* Reference param save area */
+	bve	(%ret0)
+#else
+	bv	%r0(%ret0)
 #endif
-	BL ftrace_return_to_handler,%r2
 	ldi 0,%r26
+.Lftrace_ret:
 	copy %ret0,%rp
 
 	/* restore original return values */
@@ -2062,6 +2069,8 @@ parisc_return_to_handler:
 	.procend
 ENDPROC(return_to_handler)
 
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+
 #endif	/* CONFIG_FUNCTION_TRACER */
 
 #ifdef CONFIG_IRQSTACKS
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/parisc/kernel/ftrace.c linux-libre-4.7-gnu/arch/parisc/kernel/ftrace.c
--- linux-libre-4.6-gnu/arch/parisc/kernel/ftrace.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/parisc/kernel/ftrace.c	2016-07-24 15:23:50.000000000 -0400
@@ -18,12 +18,15 @@
 #include <asm/ftrace.h>
 
 
+#define __hot __attribute__ ((__section__ (".text.hot")))
+
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 /*
  * Hook the return address and push it in the stack of return addrs
  * in current thread info.
  */
-static void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
+static void __hot prepare_ftrace_return(unsigned long *parent,
+					unsigned long self_addr)
 {
 	unsigned long old;
 	struct ftrace_graph_ent trace;
@@ -53,7 +56,7 @@ static void prepare_ftrace_return(unsign
 }
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
 
-void notrace ftrace_function_trampoline(unsigned long parent,
+void notrace __hot ftrace_function_trampoline(unsigned long parent,
 				unsigned long self_addr,
 				unsigned long org_sp_gr3)
 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/parisc/kernel/process.c linux-libre-4.7-gnu/arch/parisc/kernel/process.c
--- linux-libre-4.6-gnu/arch/parisc/kernel/process.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/parisc/kernel/process.c	2016-07-24 15:23:50.000000000 -0400
@@ -144,13 +144,6 @@ void machine_power_off(void)
 void (*pm_power_off)(void) = machine_power_off;
 EXPORT_SYMBOL(pm_power_off);
 
-/*
- * Free current thread data structures etc..
- */
-void exit_thread(void)
-{
-}
-
 void flush_thread(void)
 {
 	/* Only needs to handle fpu stuff or perf monitors.
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/parisc/kernel/processor.c linux-libre-4.7-gnu/arch/parisc/kernel/processor.c
--- linux-libre-4.6-gnu/arch/parisc/kernel/processor.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/parisc/kernel/processor.c	2016-07-24 15:23:50.000000000 -0400
@@ -324,8 +324,9 @@ int init_per_cpu(int cpunum)
 		per_cpu(cpu_data, cpunum).fp_rev = coproc_cfg.revision;
 		per_cpu(cpu_data, cpunum).fp_model = coproc_cfg.model;
 
-		printk(KERN_INFO  "FP[%d] enabled: Rev %ld Model %ld\n",
-			cpunum, coproc_cfg.revision, coproc_cfg.model);
+		if (cpunum == 0)
+			printk(KERN_INFO  "FP[%d] enabled: Rev %ld Model %ld\n",
+				cpunum, coproc_cfg.revision, coproc_cfg.model);
 
 		/*
 		** store status register to stack (hopefully aligned)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/parisc/kernel/ptrace.c linux-libre-4.7-gnu/arch/parisc/kernel/ptrace.c
--- linux-libre-4.6-gnu/arch/parisc/kernel/ptrace.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/parisc/kernel/ptrace.c	2016-07-24 15:23:50.000000000 -0400
@@ -4,18 +4,20 @@
  * Copyright (C) 2000 Hewlett-Packard Co, Linuxcare Inc.
  * Copyright (C) 2000 Matthew Wilcox <matthew@wil.cx>
  * Copyright (C) 2000 David Huggins-Daines <dhd@debian.org>
- * Copyright (C) 2008 Helge Deller <deller@gmx.de>
+ * Copyright (C) 2008-2016 Helge Deller <deller@gmx.de>
  */
 
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
+#include <linux/elf.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/tracehook.h>
 #include <linux/user.h>
 #include <linux/personality.h>
+#include <linux/regset.h>
 #include <linux/security.h>
 #include <linux/seccomp.h>
 #include <linux/compat.h>
@@ -30,6 +32,17 @@
 /* PSW bits we allow the debugger to modify */
 #define USER_PSW_BITS	(PSW_N | PSW_B | PSW_V | PSW_CB)
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/syscalls.h>
+
+/*
+ * These are our native regset flavors.
+ */
+enum parisc_regset {
+	REGSET_GENERAL,
+	REGSET_FP
+};
+
 /*
  * Called by kernel/ptrace.c when detaching..
  *
@@ -114,6 +127,7 @@ void user_enable_block_step(struct task_
 long arch_ptrace(struct task_struct *child, long request,
 		 unsigned long addr, unsigned long data)
 {
+	unsigned long __user *datap = (unsigned long __user *)data;
 	unsigned long tmp;
 	long ret = -EIO;
 
@@ -126,7 +140,7 @@ long arch_ptrace(struct task_struct *chi
 		     addr >= sizeof(struct pt_regs))
 			break;
 		tmp = *(unsigned long *) ((char *) task_regs(child) + addr);
-		ret = put_user(tmp, (unsigned long __user *) data);
+		ret = put_user(tmp, datap);
 		break;
 
 	/* Write the word at location addr in the USER area.  This will need
@@ -165,6 +179,34 @@ long arch_ptrace(struct task_struct *chi
 		}
 		break;
 
+	case PTRACE_GETREGS:	/* Get all gp regs from the child. */
+		return copy_regset_to_user(child,
+					   task_user_regset_view(current),
+					   REGSET_GENERAL,
+					   0, sizeof(struct user_regs_struct),
+					   datap);
+
+	case PTRACE_SETREGS:	/* Set all gp regs in the child. */
+		return copy_regset_from_user(child,
+					     task_user_regset_view(current),
+					     REGSET_GENERAL,
+					     0, sizeof(struct user_regs_struct),
+					     datap);
+
+	case PTRACE_GETFPREGS:	/* Get the child FPU state. */
+		return copy_regset_to_user(child,
+					   task_user_regset_view(current),
+					   REGSET_FP,
+					   0, sizeof(struct user_fp_struct),
+					   datap);
+
+	case PTRACE_SETFPREGS:	/* Set the child FPU state. */
+		return copy_regset_from_user(child,
+					     task_user_regset_view(current),
+					     REGSET_FP,
+					     0, sizeof(struct user_fp_struct),
+					     datap);
+
 	default:
 		ret = ptrace_request(child, request, addr, data);
 		break;
@@ -283,6 +325,10 @@ long do_syscall_trace_enter(struct pt_re
 		regs->gr[20] = -1UL;
 		goto out;
 	}
+#ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
+	if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
+		trace_sys_enter(regs, regs->gr[20]);
+#endif
 
 #ifdef CONFIG_64BIT
 	if (!is_compat_task())
@@ -311,6 +357,324 @@ void do_syscall_trace_exit(struct pt_reg
 
 	audit_syscall_exit(regs);
 
+#ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
+	if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
+		trace_sys_exit(regs, regs->gr[20]);
+#endif
+
 	if (stepping || test_thread_flag(TIF_SYSCALL_TRACE))
 		tracehook_report_syscall_exit(regs, stepping);
 }
+
+
+/*
+ * regset functions.
+ */
+
+static int fpr_get(struct task_struct *target,
+		     const struct user_regset *regset,
+		     unsigned int pos, unsigned int count,
+		     void *kbuf, void __user *ubuf)
+{
+	struct pt_regs *regs = task_regs(target);
+	__u64 *k = kbuf;
+	__u64 __user *u = ubuf;
+	__u64 reg;
+
+	pos /= sizeof(reg);
+	count /= sizeof(reg);
+
+	if (kbuf)
+		for (; count > 0 && pos < ELF_NFPREG; --count)
+			*k++ = regs->fr[pos++];
+	else
+		for (; count > 0 && pos < ELF_NFPREG; --count)
+			if (__put_user(regs->fr[pos++], u++))
+				return -EFAULT;
+
+	kbuf = k;
+	ubuf = u;
+	pos *= sizeof(reg);
+	count *= sizeof(reg);
+	return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+					ELF_NFPREG * sizeof(reg), -1);
+}
+
+static int fpr_set(struct task_struct *target,
+		     const struct user_regset *regset,
+		     unsigned int pos, unsigned int count,
+		     const void *kbuf, const void __user *ubuf)
+{
+	struct pt_regs *regs = task_regs(target);
+	const __u64 *k = kbuf;
+	const __u64 __user *u = ubuf;
+	__u64 reg;
+
+	pos /= sizeof(reg);
+	count /= sizeof(reg);
+
+	if (kbuf)
+		for (; count > 0 && pos < ELF_NFPREG; --count)
+			regs->fr[pos++] = *k++;
+	else
+		for (; count > 0 && pos < ELF_NFPREG; --count) {
+			if (__get_user(reg, u++))
+				return -EFAULT;
+			regs->fr[pos++] = reg;
+		}
+
+	kbuf = k;
+	ubuf = u;
+	pos *= sizeof(reg);
+	count *= sizeof(reg);
+	return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+					 ELF_NFPREG * sizeof(reg), -1);
+}
+
+#define RI(reg) (offsetof(struct user_regs_struct,reg) / sizeof(long))
+
+static unsigned long get_reg(struct pt_regs *regs, int num)
+{
+	switch (num) {
+	case RI(gr[0]) ... RI(gr[31]):	return regs->gr[num - RI(gr[0])];
+	case RI(sr[0]) ... RI(sr[7]):	return regs->sr[num - RI(sr[0])];
+	case RI(iasq[0]):		return regs->iasq[0];
+	case RI(iasq[1]):		return regs->iasq[1];
+	case RI(iaoq[0]):		return regs->iaoq[0];
+	case RI(iaoq[1]):		return regs->iaoq[1];
+	case RI(sar):			return regs->sar;
+	case RI(iir):			return regs->iir;
+	case RI(isr):			return regs->isr;
+	case RI(ior):			return regs->ior;
+	case RI(ipsw):			return regs->ipsw;
+	case RI(cr27):			return regs->cr27;
+	case RI(cr0):			return mfctl(0);
+	case RI(cr24):			return mfctl(24);
+	case RI(cr25):			return mfctl(25);
+	case RI(cr26):			return mfctl(26);
+	case RI(cr28):			return mfctl(28);
+	case RI(cr29):			return mfctl(29);
+	case RI(cr30):			return mfctl(30);
+	case RI(cr31):			return mfctl(31);
+	case RI(cr8):			return mfctl(8);
+	case RI(cr9):			return mfctl(9);
+	case RI(cr12):			return mfctl(12);
+	case RI(cr13):			return mfctl(13);
+	case RI(cr10):			return mfctl(10);
+	case RI(cr15):			return mfctl(15);
+	default:			return 0;
+	}
+}
+
+static void set_reg(struct pt_regs *regs, int num, unsigned long val)
+{
+	switch (num) {
+	case RI(gr[0]): /*
+			 * PSW is in gr[0].
+			 * Allow writing to Nullify, Divide-step-correction,
+			 * and carry/borrow bits.
+			 * BEWARE, if you set N, and then single step, it won't
+			 * stop on the nullified instruction.
+			 */
+			val &= USER_PSW_BITS;
+			regs->gr[0] &= ~USER_PSW_BITS;
+			regs->gr[0] |= val;
+			return;
+	case RI(gr[1]) ... RI(gr[31]):
+			regs->gr[num - RI(gr[0])] = val;
+			return;
+	case RI(iaoq[0]):
+	case RI(iaoq[1]):
+			regs->iaoq[num - RI(iaoq[0])] = val;
+			return;
+	case RI(sar):	regs->sar = val;
+			return;
+	default:	return;
+#if 0
+	/* do not allow to change any of the following registers (yet) */
+	case RI(sr[0]) ... RI(sr[7]):	return regs->sr[num - RI(sr[0])];
+	case RI(iasq[0]):		return regs->iasq[0];
+	case RI(iasq[1]):		return regs->iasq[1];
+	case RI(iir):			return regs->iir;
+	case RI(isr):			return regs->isr;
+	case RI(ior):			return regs->ior;
+	case RI(ipsw):			return regs->ipsw;
+	case RI(cr27):			return regs->cr27;
+        case cr0, cr24, cr25, cr26, cr27, cr28, cr29, cr30, cr31;
+        case cr8, cr9, cr12, cr13, cr10, cr15;
+#endif
+	}
+}
+
+static int gpr_get(struct task_struct *target,
+		     const struct user_regset *regset,
+		     unsigned int pos, unsigned int count,
+		     void *kbuf, void __user *ubuf)
+{
+	struct pt_regs *regs = task_regs(target);
+	unsigned long *k = kbuf;
+	unsigned long __user *u = ubuf;
+	unsigned long reg;
+
+	pos /= sizeof(reg);
+	count /= sizeof(reg);
+
+	if (kbuf)
+		for (; count > 0 && pos < ELF_NGREG; --count)
+			*k++ = get_reg(regs, pos++);
+	else
+		for (; count > 0 && pos < ELF_NGREG; --count)
+			if (__put_user(get_reg(regs, pos++), u++))
+				return -EFAULT;
+	kbuf = k;
+	ubuf = u;
+	pos *= sizeof(reg);
+	count *= sizeof(reg);
+	return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+					ELF_NGREG * sizeof(reg), -1);
+}
+
+static int gpr_set(struct task_struct *target,
+		     const struct user_regset *regset,
+		     unsigned int pos, unsigned int count,
+		     const void *kbuf, const void __user *ubuf)
+{
+	struct pt_regs *regs = task_regs(target);
+	const unsigned long *k = kbuf;
+	const unsigned long __user *u = ubuf;
+	unsigned long reg;
+
+	pos /= sizeof(reg);
+	count /= sizeof(reg);
+
+	if (kbuf)
+		for (; count > 0 && pos < ELF_NGREG; --count)
+			set_reg(regs, pos++, *k++);
+	else
+		for (; count > 0 && pos < ELF_NGREG; --count) {
+			if (__get_user(reg, u++))
+				return -EFAULT;
+			set_reg(regs, pos++, reg);
+		}
+
+	kbuf = k;
+	ubuf = u;
+	pos *= sizeof(reg);
+	count *= sizeof(reg);
+	return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+					 ELF_NGREG * sizeof(reg), -1);
+}
+
+static const struct user_regset native_regsets[] = {
+	[REGSET_GENERAL] = {
+		.core_note_type = NT_PRSTATUS, .n = ELF_NGREG,
+		.size = sizeof(long), .align = sizeof(long),
+		.get = gpr_get, .set = gpr_set
+	},
+	[REGSET_FP] = {
+		.core_note_type = NT_PRFPREG, .n = ELF_NFPREG,
+		.size = sizeof(__u64), .align = sizeof(__u64),
+		.get = fpr_get, .set = fpr_set
+	}
+};
+
+static const struct user_regset_view user_parisc_native_view = {
+	.name = "parisc", .e_machine = ELF_ARCH, .ei_osabi = ELFOSABI_LINUX,
+	.regsets = native_regsets, .n = ARRAY_SIZE(native_regsets)
+};
+
+#ifdef CONFIG_64BIT
+#include <linux/compat.h>
+
+static int gpr32_get(struct task_struct *target,
+		     const struct user_regset *regset,
+		     unsigned int pos, unsigned int count,
+		     void *kbuf, void __user *ubuf)
+{
+	struct pt_regs *regs = task_regs(target);
+	compat_ulong_t *k = kbuf;
+	compat_ulong_t __user *u = ubuf;
+	compat_ulong_t reg;
+
+	pos /= sizeof(reg);
+	count /= sizeof(reg);
+
+	if (kbuf)
+		for (; count > 0 && pos < ELF_NGREG; --count)
+			*k++ = get_reg(regs, pos++);
+	else
+		for (; count > 0 && pos < ELF_NGREG; --count)
+			if (__put_user((compat_ulong_t) get_reg(regs, pos++), u++))
+				return -EFAULT;
+
+	kbuf = k;
+	ubuf = u;
+	pos *= sizeof(reg);
+	count *= sizeof(reg);
+	return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+					ELF_NGREG * sizeof(reg), -1);
+}
+
+static int gpr32_set(struct task_struct *target,
+		     const struct user_regset *regset,
+		     unsigned int pos, unsigned int count,
+		     const void *kbuf, const void __user *ubuf)
+{
+	struct pt_regs *regs = task_regs(target);
+	const compat_ulong_t *k = kbuf;
+	const compat_ulong_t __user *u = ubuf;
+	compat_ulong_t reg;
+
+	pos /= sizeof(reg);
+	count /= sizeof(reg);
+
+	if (kbuf)
+		for (; count > 0 && pos < ELF_NGREG; --count)
+			set_reg(regs, pos++, *k++);
+	else
+		for (; count > 0 && pos < ELF_NGREG; --count) {
+			if (__get_user(reg, u++))
+				return -EFAULT;
+			set_reg(regs, pos++, reg);
+		}
+
+	kbuf = k;
+	ubuf = u;
+	pos *= sizeof(reg);
+	count *= sizeof(reg);
+	return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+					 ELF_NGREG * sizeof(reg), -1);
+}
+
+/*
+ * These are the regset flavors matching the 32bit native set.
+ */
+static const struct user_regset compat_regsets[] = {
+	[REGSET_GENERAL] = {
+		.core_note_type = NT_PRSTATUS, .n = ELF_NGREG,
+		.size = sizeof(compat_long_t), .align = sizeof(compat_long_t),
+		.get = gpr32_get, .set = gpr32_set
+	},
+	[REGSET_FP] = {
+		.core_note_type = NT_PRFPREG, .n = ELF_NFPREG,
+		.size = sizeof(__u64), .align = sizeof(__u64),
+		.get = fpr_get, .set = fpr_set
+	}
+};
+
+static const struct user_regset_view user_parisc_compat_view = {
+	.name = "parisc", .e_machine = EM_PARISC, .ei_osabi = ELFOSABI_LINUX,
+	.regsets = compat_regsets, .n = ARRAY_SIZE(compat_regsets)
+};
+#endif	/* CONFIG_64BIT */
+
+const struct user_regset_view *task_user_regset_view(struct task_struct *task)
+{
+	BUILD_BUG_ON(sizeof(struct user_regs_struct)/sizeof(long) != ELF_NGREG);
+	BUILD_BUG_ON(sizeof(struct user_fp_struct)/sizeof(__u64) != ELF_NFPREG);
+#ifdef CONFIG_64BIT
+	if (is_compat_task())
+		return &user_parisc_compat_view;
+#endif
+	return &user_parisc_native_view;
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/parisc/kernel/syscall.S linux-libre-4.7-gnu/arch/parisc/kernel/syscall.S
--- linux-libre-4.6-gnu/arch/parisc/kernel/syscall.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/parisc/kernel/syscall.S	2016-07-24 15:23:50.000000000 -0400
@@ -912,6 +912,7 @@ END(lws_table)
 
 	.align 8
 ENTRY(sys_call_table)
+	.export sys_call_table,data
 #include "syscall_table.S"
 END(sys_call_table)
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/parisc/kernel/time.c linux-libre-4.7-gnu/arch/parisc/kernel/time.c
--- linux-libre-4.6-gnu/arch/parisc/kernel/time.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/parisc/kernel/time.c	2016-07-24 15:23:50.000000000 -0400
@@ -38,6 +38,18 @@
 
 static unsigned long clocktick __read_mostly;	/* timer cycles per tick */
 
+#ifndef CONFIG_64BIT
+/*
+ * The processor-internal cycle counter (Control Register 16) is used as time
+ * source for the sched_clock() function.  This register is 64bit wide on a
+ * 64-bit kernel and 32bit on a 32-bit kernel. Since sched_clock() always
+ * requires a 64bit counter we emulate on the 32-bit kernel the higher 32bits
+ * with a per-cpu variable which we increase every time the counter
+ * wraps-around (which happens every ~4 secounds).
+ */
+static DEFINE_PER_CPU(unsigned long, cr16_high_32_bits);
+#endif
+
 /*
  * We keep time on PA-RISC Linux by using the Interval Timer which is
  * a pair of registers; one is read-only and one is write-only; both
@@ -108,6 +120,12 @@ irqreturn_t __irq_entry timer_interrupt(
 	 */
 	mtctl(next_tick, 16);
 
+#if !defined(CONFIG_64BIT)
+	/* check for overflow on a 32bit kernel (every ~4 seconds). */
+	if (unlikely(next_tick < now))
+		this_cpu_inc(cr16_high_32_bits);
+#endif
+
 	/* Skip one clocktick on purpose if we missed next_tick.
 	 * The new CR16 must be "later" than current CR16 otherwise
 	 * itimer would not fire until CR16 wrapped - e.g 4 seconds
@@ -219,6 +237,12 @@ void __init start_cpu_itimer(void)
 	unsigned int cpu = smp_processor_id();
 	unsigned long next_tick = mfctl(16) + clocktick;
 
+#if defined(CONFIG_HAVE_UNSTABLE_SCHED_CLOCK) && defined(CONFIG_64BIT)
+	/* With multiple 64bit CPUs online, the cr16's are not syncronized. */
+	if (cpu != 0)
+		clear_sched_clock_stable();
+#endif
+
 	mtctl(next_tick, 16);		/* kick off Interval Timer (CR16) */
 
 	per_cpu(cpu_data, cpu).it_value = next_tick;
@@ -246,15 +270,47 @@ void read_persistent_clock(struct timesp
 	}
 }
 
+
+/*
+ * sched_clock() framework
+ */
+
+static u32 cyc2ns_mul __read_mostly;
+static u32 cyc2ns_shift __read_mostly;
+
+u64 sched_clock(void)
+{
+	u64 now;
+
+	/* Get current cycle counter (Control Register 16). */
+#ifdef CONFIG_64BIT
+	now = mfctl(16);
+#else
+	now = mfctl(16) + (((u64) this_cpu_read(cr16_high_32_bits)) << 32);
+#endif
+
+	/* return the value in ns (cycles_2_ns) */
+	return mul_u64_u32_shr(now, cyc2ns_mul, cyc2ns_shift);
+}
+
+
+/*
+ * timer interrupt and sched_clock() initialization
+ */
+
 void __init time_init(void)
 {
 	unsigned long current_cr16_khz;
 
+	current_cr16_khz = PAGE0->mem_10msec/10;  /* kHz */
 	clocktick = (100 * PAGE0->mem_10msec) / HZ;
 
+	/* calculate mult/shift values for cr16 */
+	clocks_calc_mult_shift(&cyc2ns_mul, &cyc2ns_shift, current_cr16_khz,
+				NSEC_PER_MSEC, 0);
+
 	start_cpu_itimer();	/* get CPU 0 started */
 
 	/* register at clocksource framework */
-	current_cr16_khz = PAGE0->mem_10msec/10;  /* kHz */
 	clocksource_register_khz(&clocksource_cr16, current_cr16_khz);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/parisc/kernel/unaligned.c linux-libre-4.7-gnu/arch/parisc/kernel/unaligned.c
--- linux-libre-4.6-gnu/arch/parisc/kernel/unaligned.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/parisc/kernel/unaligned.c	2016-07-24 15:23:50.000000000 -0400
@@ -28,6 +28,7 @@
 #include <linux/ratelimit.h>
 #include <asm/uaccess.h>
 #include <asm/hardirq.h>
+#include <asm/traps.h>
 
 /* #define DEBUG_UNALIGNED 1 */
 
@@ -130,8 +131,6 @@
 
 int unaligned_enabled __read_mostly = 1;
 
-void die_if_kernel (char *str, struct pt_regs *regs, long err);
-
 static int emulate_ldh(struct pt_regs *regs, int toreg)
 {
 	unsigned long saddr = regs->ior;
@@ -666,7 +665,7 @@ void handle_unaligned(struct pt_regs *re
 		break;
 	}
 
-	if (modify && R1(regs->iir))
+	if (ret == 0 && modify && R1(regs->iir))
 		regs->gr[R1(regs->iir)] = newbase;
 
 
@@ -677,6 +676,14 @@ void handle_unaligned(struct pt_regs *re
 
 	if (ret)
 	{
+		/*
+		 * The unaligned handler failed.
+		 * If we were called by __get_user() or __put_user() jump
+		 * to it's exception fixup handler instead of crashing.
+		 */
+		if (!user_mode(regs) && fixup_exception(regs))
+			return;
+
 		printk(KERN_CRIT "Unaligned handler failed, ret = %d\n", ret);
 		die_if_kernel("Unaligned data reference", regs, 28);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/parisc/kernel/unwind.c linux-libre-4.7-gnu/arch/parisc/kernel/unwind.c
--- linux-libre-4.6-gnu/arch/parisc/kernel/unwind.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/parisc/kernel/unwind.c	2016-07-24 15:23:50.000000000 -0400
@@ -75,7 +75,10 @@ find_unwind_entry(unsigned long addr)
 	if (addr >= kernel_unwind_table.start && 
 	    addr <= kernel_unwind_table.end)
 		e = find_unwind_entry_in_table(&kernel_unwind_table, addr);
-	else 
+	else {
+		unsigned long flags;
+
+		spin_lock_irqsave(&unwind_lock, flags);
 		list_for_each_entry(table, &unwind_tables, list) {
 			if (addr >= table->start && 
 			    addr <= table->end)
@@ -86,6 +89,8 @@ find_unwind_entry(unsigned long addr)
 				break;
 			}
 		}
+		spin_unlock_irqrestore(&unwind_lock, flags);
+	}
 
 	return e;
 }
@@ -303,18 +308,16 @@ static void unwind_frame_regs(struct unw
 
 			insn = *(unsigned int *)npc;
 
-			if ((insn & 0xffffc000) == 0x37de0000 ||
-			    (insn & 0xffe00000) == 0x6fc00000) {
+			if ((insn & 0xffffc001) == 0x37de0000 ||
+			    (insn & 0xffe00001) == 0x6fc00000) {
 				/* ldo X(sp), sp, or stwm X,D(sp) */
-				frame_size += (insn & 0x1 ? -1 << 13 : 0) | 
-					((insn & 0x3fff) >> 1);
+				frame_size += (insn & 0x3fff) >> 1;
 				dbg("analyzing func @ %lx, insn=%08x @ "
 				    "%lx, frame_size = %ld\n", info->ip,
 				    insn, npc, frame_size);
-			} else if ((insn & 0xffe00008) == 0x73c00008) {
+			} else if ((insn & 0xffe00009) == 0x73c00008) {
 				/* std,ma X,D(sp) */
-				frame_size += (insn & 0x1 ? -1 << 13 : 0) | 
-					(((insn >> 4) & 0x3ff) << 3);
+				frame_size += ((insn >> 4) & 0x3ff) << 3;
 				dbg("analyzing func @ %lx, insn=%08x @ "
 				    "%lx, frame_size = %ld\n", info->ip,
 				    insn, npc, frame_size);
@@ -333,6 +336,9 @@ static void unwind_frame_regs(struct unw
 			}
 		}
 
+		if (frame_size > e->Total_frame_size << 3)
+			frame_size = e->Total_frame_size << 3;
+
 		if (!unwind_special(info, e->region_start, frame_size)) {
 			info->prev_sp = info->sp - frame_size;
 			if (e->Millicode)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/parisc/lib/bitops.c linux-libre-4.7-gnu/arch/parisc/lib/bitops.c
--- linux-libre-4.6-gnu/arch/parisc/lib/bitops.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/parisc/lib/bitops.c	2016-07-24 15:23:50.000000000 -0400
@@ -55,11 +55,10 @@ unsigned long __xchg8(char x, char *ptr)
 }
 
 
-#ifdef CONFIG_64BIT
-unsigned long __cmpxchg_u64(volatile unsigned long *ptr, unsigned long old, unsigned long new)
+u64 __cmpxchg_u64(volatile u64 *ptr, u64 old, u64 new)
 {
 	unsigned long flags;
-	unsigned long prev;
+	u64 prev;
 
 	_atomic_spin_lock_irqsave(ptr, flags);
 	if ((prev = *ptr) == old)
@@ -67,7 +66,6 @@ unsigned long __cmpxchg_u64(volatile uns
 	_atomic_spin_unlock_irqrestore(ptr, flags);
 	return prev;
 }
-#endif
 
 unsigned long __cmpxchg_u32(volatile unsigned int *ptr, unsigned int old, unsigned int new)
 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/parisc/math-emu/fpudispatch.c linux-libre-4.7-gnu/arch/parisc/math-emu/fpudispatch.c
--- linux-libre-4.6-gnu/arch/parisc/math-emu/fpudispatch.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/parisc/math-emu/fpudispatch.c	2016-07-24 15:23:50.000000000 -0400
@@ -184,7 +184,7 @@ static void parisc_linux_get_fpu_type(u_
 
 /*
  * this routine will decode the excepting floating point instruction and
- * call the approiate emulation routine.
+ * call the appropriate emulation routine.
  * It is called by decode_fpu with the following parameters:
  * fpudispatch(current_ir, unimplemented_code, 0, &Fpu_register)
  * where current_ir is the instruction to be emulated,
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/boot/dts/canyonlands.dts linux-libre-4.7-gnu/arch/powerpc/boot/dts/canyonlands.dts
--- linux-libre-4.6-gnu/arch/powerpc/boot/dts/canyonlands.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/boot/dts/canyonlands.dts	2016-07-24 15:23:50.000000000 -0400
@@ -190,12 +190,21 @@
 					 /* DMA */ 0x2 &UIC0 0xc 0x4>;
 		};
 
+		AHBDMA: dma@bffd0800 {
+			compatible = "snps,dma-spear1340";
+			reg = <4 0xbffd0800 0x400>;
+			interrupt-parent = <&UIC3>;
+			interrupts = <0x5 0x4>;
+			#dma-cells = <3>;
+		};
+
 		SATA0: sata@bffd1000 {
 			compatible = "amcc,sata-460ex";
-			reg = <4 0xbffd1000 0x800 4 0xbffd0800 0x400>;
+			reg = <4 0xbffd1000 0x800>;
 			interrupt-parent = <&UIC3>;
-			interrupts = <0x0 0x4       /* SATA */
-				      0x5 0x4>;     /* AHBDMA */
+			interrupts = <0x0 0x4>;
+			dmas = <&AHBDMA 0 1 0>;
+			dma-names = "sata-dma";
 		};
 
 		POB0: opb {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/boot/dts/fsl/gef_ppc9a.dts linux-libre-4.7-gnu/arch/powerpc/boot/dts/fsl/gef_ppc9a.dts
--- linux-libre-4.6-gnu/arch/powerpc/boot/dts/fsl/gef_ppc9a.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/boot/dts/fsl/gef_ppc9a.dts	2016-07-24 15:23:50.000000000 -0400
@@ -211,6 +211,10 @@
 				  0x0 0x00400000>;
 		};
 	};
+
+	pci1: pcie@fef09000 {
+		status = "disabled";
+	};
 };
 
 /include/ "mpc8641si-post.dtsi"
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/boot/dts/fsl/gef_sbc310.dts linux-libre-4.7-gnu/arch/powerpc/boot/dts/fsl/gef_sbc310.dts
--- linux-libre-4.6-gnu/arch/powerpc/boot/dts/fsl/gef_sbc310.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/boot/dts/fsl/gef_sbc310.dts	2016-07-24 15:23:50.000000000 -0400
@@ -24,10 +24,6 @@
 	model = "GEF_SBC310";
 	compatible = "gef,sbc310";
 
-	aliases {
-		pci1 = &pci1;
-	};
-
 	memory {
 		device_type = "memory";
 		reg = <0x0 0x40000000>;	// set by uboot
@@ -223,29 +219,11 @@
 	};
 
 	pci1: pcie@fef09000 {
-		compatible = "fsl,mpc8641-pcie";
-		device_type = "pci";
-		#size-cells = <2>;
-		#address-cells = <3>;
 		reg = <0xfef09000 0x1000>;
-		bus-range = <0x0 0xff>;
 		ranges = <0x02000000 0x0 0xc0000000 0xc0000000 0x0 0x20000000
 			  0x01000000 0x0 0x00000000 0xfe400000 0x0 0x00400000>;
-		clock-frequency = <100000000>;
-		interrupts = <0x19 0x2 0 0>;
-		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
-		interrupt-map = <
-			0x0000 0x0 0x0 0x1 &mpic 0x4 0x2
-			0x0000 0x0 0x0 0x2 &mpic 0x5 0x2
-			0x0000 0x0 0x0 0x3 &mpic 0x6 0x2
-			0x0000 0x0 0x0 0x4 &mpic 0x7 0x2
-			>;
 
 		pcie@0 {
-			reg = <0 0 0 0 0>;
-			#size-cells = <2>;
-			#address-cells = <3>;
-			device_type = "pci";
 			ranges = <0x02000000 0x0 0xc0000000
 				  0x02000000 0x0 0xc0000000
 				  0x0 0x20000000
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/boot/dts/fsl/gef_sbc610.dts linux-libre-4.7-gnu/arch/powerpc/boot/dts/fsl/gef_sbc610.dts
--- linux-libre-4.6-gnu/arch/powerpc/boot/dts/fsl/gef_sbc610.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/boot/dts/fsl/gef_sbc610.dts	2016-07-24 15:23:50.000000000 -0400
@@ -209,6 +209,10 @@
 				  0x0 0x00400000>;
 		};
 	};
+
+	pci1: pcie@fef09000 {
+		status = "disabled";
+	};
 };
 
 /include/ "mpc8641si-post.dtsi"
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/boot/dts/fsl/mpc8641_hpcn_36b.dts linux-libre-4.7-gnu/arch/powerpc/boot/dts/fsl/mpc8641_hpcn_36b.dts
--- linux-libre-4.6-gnu/arch/powerpc/boot/dts/fsl/mpc8641_hpcn_36b.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/boot/dts/fsl/mpc8641_hpcn_36b.dts	2016-07-24 15:23:50.000000000 -0400
@@ -17,10 +17,6 @@
 	#address-cells = <2>;
 	#size-cells = <2>;
 
-	aliases {
-		pci1 = &pci1;
-	};
-
 	memory {
 		device_type = "memory";
 		reg = <0x0 0x00000000 0x0 0x40000000>;	// 1G at 0x0
@@ -326,29 +322,11 @@
 	};
 
 	pci1: pcie@fffe09000 {
-		compatible = "fsl,mpc8641-pcie";
-		device_type = "pci";
-		#size-cells = <2>;
-		#address-cells = <3>;
 		reg = <0x0f 0xffe09000 0x0 0x1000>;
-		bus-range = <0x0 0xff>;
 		ranges = <0x02000000 0x0 0xe0000000 0x0c 0x20000000 0x0 0x20000000
 			  0x01000000 0x0 0x00000000 0x0f 0xffc10000 0x0 0x00010000>;
-		clock-frequency = <100000000>;
-		interrupts = <25 2 0 0>;
-		interrupt-map-mask = <0xf800 0 0 7>;
-		interrupt-map = <
-			/* IDSEL 0x0 */
-			0x0000 0 0 1 &mpic 4 1
-			0x0000 0 0 2 &mpic 5 1
-			0x0000 0 0 3 &mpic 6 1
-			0x0000 0 0 4 &mpic 7 1
-			>;
+
 		pcie@0 {
-			reg = <0 0 0 0 0>;
-			#size-cells = <2>;
-			#address-cells = <3>;
-			device_type = "pci";
 			ranges = <0x02000000 0x0 0xe0000000
 				  0x02000000 0x0 0xe0000000
 				  0x0 0x20000000
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/boot/dts/fsl/mpc8641_hpcn.dts linux-libre-4.7-gnu/arch/powerpc/boot/dts/fsl/mpc8641_hpcn.dts
--- linux-libre-4.6-gnu/arch/powerpc/boot/dts/fsl/mpc8641_hpcn.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/boot/dts/fsl/mpc8641_hpcn.dts	2016-07-24 15:23:50.000000000 -0400
@@ -15,10 +15,6 @@
 	model = "MPC8641HPCN";
 	compatible = "fsl,mpc8641hpcn";
 
-	aliases {
-		pci1 = &pci1;
-	};
-
 	memory {
 		device_type = "memory";
 		reg = <0x00000000 0x40000000>;	// 1G at 0x0
@@ -359,29 +355,11 @@
 	};
 
 	pci1: pcie@ffe09000 {
-		compatible = "fsl,mpc8641-pcie";
-		device_type = "pci";
-		#size-cells = <2>;
-		#address-cells = <3>;
 		reg = <0xffe09000 0x1000>;
-		bus-range = <0 0xff>;
 		ranges = <0x02000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
 			  0x01000000 0x0 0x00000000 0xffc10000 0x0 0x00010000>;
-		clock-frequency = <100000000>;
-		interrupts = <25 2 0 0>;
-		interrupt-map-mask = <0xf800 0 0 7>;
-		interrupt-map = <
-			/* IDSEL 0x0 */
-			0x0000 0 0 1 &mpic 4 1
-			0x0000 0 0 2 &mpic 5 1
-			0x0000 0 0 3 &mpic 6 1
-			0x0000 0 0 4 &mpic 7 1
-			>;
+
 		pcie@0 {
-			reg = <0 0 0 0 0>;
-			#size-cells = <2>;
-			#address-cells = <3>;
-			device_type = "pci";
 			ranges = <0x02000000 0x0 0xa0000000
 				  0x02000000 0x0 0xa0000000
 				  0x0 0x20000000
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/boot/dts/fsl/mpc8641si-post.dtsi linux-libre-4.7-gnu/arch/powerpc/boot/dts/fsl/mpc8641si-post.dtsi
--- linux-libre-4.6-gnu/arch/powerpc/boot/dts/fsl/mpc8641si-post.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/boot/dts/fsl/mpc8641si-post.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -102,19 +102,46 @@
 	bus-range = <0x0 0xff>;
 	clock-frequency = <100000000>;
 	interrupts = <24 2 0 0>;
-	interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
 
-	interrupt-map = <
-		0x0000 0x0 0x0 0x1 &mpic 0x0 0x1
-		0x0000 0x0 0x0 0x2 &mpic 0x1 0x1
-		0x0000 0x0 0x0 0x3 &mpic 0x2 0x1
-		0x0000 0x0 0x0 0x4 &mpic 0x3 0x1
-		>;
+	pcie@0 {
+		reg = <0 0 0 0 0>;
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		device_type = "pci";
+		interrupts = <24 2 0 0>;
+		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+		interrupt-map = <
+			0x0000 0x0 0x0 0x1 &mpic 0x0 0x1 0x0 0x0
+			0x0000 0x0 0x0 0x2 &mpic 0x1 0x1 0x0 0x0
+			0x0000 0x0 0x0 0x3 &mpic 0x2 0x1 0x0 0x0
+			0x0000 0x0 0x0 0x4 &mpic 0x3 0x1 0x0 0x0
+			>;
+	};
+};
+
+&pci1 {
+	compatible = "fsl,mpc8641-pcie";
+	device_type = "pci";
+	#size-cells = <2>;
+	#address-cells = <3>;
+	bus-range = <0x0 0xff>;
+	clock-frequency = <100000000>;
+	interrupts = <25 2 0 0>;
 
 	pcie@0 {
 		reg = <0 0 0 0 0>;
+		#interrupt-cells = <1>;
 		#size-cells = <2>;
 		#address-cells = <3>;
 		device_type = "pci";
+		interrupts = <25 2 0 0>;
+		interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+		interrupt-map = <
+			0x0000 0x0 0x0 0x1 &mpic 0x4 0x1 0x0 0x0
+			0x0000 0x0 0x0 0x2 &mpic 0x5 0x1 0x0 0x0
+			0x0000 0x0 0x0 0x3 &mpic 0x6 0x1 0x0 0x0
+			0x0000 0x0 0x0 0x4 &mpic 0x7 0x1 0x0 0x0
+			>;
 	};
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/boot/dts/fsl/mpc8641si-pre.dtsi linux-libre-4.7-gnu/arch/powerpc/boot/dts/fsl/mpc8641si-pre.dtsi
--- linux-libre-4.6-gnu/arch/powerpc/boot/dts/fsl/mpc8641si-pre.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/boot/dts/fsl/mpc8641si-pre.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -25,6 +25,7 @@
 		serial0 = &serial0;
 		serial1 = &serial1;
 		pci0 = &pci0;
+		pci1 = &pci1;
 	};
 
 	cpus {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/boot/dts/fsl/sbc8641d.dts linux-libre-4.7-gnu/arch/powerpc/boot/dts/fsl/sbc8641d.dts
--- linux-libre-4.6-gnu/arch/powerpc/boot/dts/fsl/sbc8641d.dts	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/boot/dts/fsl/sbc8641d.dts	2016-07-24 15:23:50.000000000 -0400
@@ -19,10 +19,6 @@
 	model = "SBC8641D";
 	compatible = "wind,sbc8641";
 
-	aliases {
-		pci1 = &pci1;
-	};
-
 	memory {
 		device_type = "memory";
 		reg = <0x00000000 0x20000000>;	// 512M at 0x0
@@ -165,30 +161,11 @@
 	};
 
 	pci1: pcie@f8009000 {
-		compatible = "fsl,mpc8641-pcie";
-		device_type = "pci";
-		#size-cells = <2>;
-		#address-cells = <3>;
 		reg = <0xf8009000 0x1000>;
-		bus-range = <0 0xff>;
 		ranges = <0x02000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
 			  0x01000000 0x0 0x00000000 0xe3000000 0x0 0x00100000>;
-		clock-frequency = <100000000>;
-		interrupts = <25 2 0 0>;
-		interrupt-map-mask = <0xf800 0 0 7>;
-		interrupt-map = <
-			/* IDSEL 0x0 */
-			0x0000 0 0 1 &mpic 4 1
-			0x0000 0 0 2 &mpic 5 1
-			0x0000 0 0 3 &mpic 6 1
-			0x0000 0 0 4 &mpic 7 1
-			>;
 
 		pcie@0 {
-			reg = <0 0 0 0 0>;
-			#size-cells = <2>;
-			#address-cells = <3>;
-			device_type = "pci";
 			ranges = <0x02000000 0x0 0xa0000000
 				  0x02000000 0x0 0xa0000000
 				  0x0 0x20000000
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/boot/dts/fsl/t1023si-post.dtsi linux-libre-4.7-gnu/arch/powerpc/boot/dts/fsl/t1023si-post.dtsi
--- linux-libre-4.6-gnu/arch/powerpc/boot/dts/fsl/t1023si-post.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/boot/dts/fsl/t1023si-post.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -263,7 +263,7 @@
 	};
 
 	rcpm: global-utilities@e2000 {
-		compatible = "fsl,t1023-rcpm", "fsl,qoriq-rcpm-2.0";
+		compatible = "fsl,t1023-rcpm", "fsl,qoriq-rcpm-2.1";
 		reg = <0xe2000 0x1000>;
 	};
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/boot/dts/fsl/t1040si-post.dtsi linux-libre-4.7-gnu/arch/powerpc/boot/dts/fsl/t1040si-post.dtsi
--- linux-libre-4.6-gnu/arch/powerpc/boot/dts/fsl/t1040si-post.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/boot/dts/fsl/t1040si-post.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -472,7 +472,7 @@
 	};
 
 	rcpm: global-utilities@e2000 {
-		compatible = "fsl,t1040-rcpm", "fsl,qoriq-rcpm-2.0";
+		compatible = "fsl,t1040-rcpm", "fsl,qoriq-rcpm-2.1";
 		reg = <0xe2000 0x1000>;
 	};
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/boot/dts/fsl/t104xrdb.dtsi linux-libre-4.7-gnu/arch/powerpc/boot/dts/fsl/t104xrdb.dtsi
--- linux-libre-4.6-gnu/arch/powerpc/boot/dts/fsl/t104xrdb.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/boot/dts/fsl/t104xrdb.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -109,7 +109,7 @@
 			flash@0 {
 				#address-cells = <1>;
 				#size-cells = <1>;
-				compatible = "micron,n25q512a", "jedec,spi-nor";
+				compatible = "micron,n25q512ax3", "jedec,spi-nor";
 				reg = <0>;
 				spi-max-frequency = <10000000>; /* input clock */
 			};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/boot/dts/fsl/t208xrdb.dtsi linux-libre-4.7-gnu/arch/powerpc/boot/dts/fsl/t208xrdb.dtsi
--- linux-libre-4.6-gnu/arch/powerpc/boot/dts/fsl/t208xrdb.dtsi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/boot/dts/fsl/t208xrdb.dtsi	2016-07-24 15:23:50.000000000 -0400
@@ -113,7 +113,7 @@
 			flash@0 {
 				#address-cells = <1>;
 				#size-cells = <1>;
-				compatible = "micron,n25q512a", "jedec,spi-nor";
+				compatible = "micron,n25q512ax3", "jedec,spi-nor";
 				reg = <0>;
 				spi-max-frequency = <10000000>; /* input clock */
 			};
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/boot/Makefile linux-libre-4.7-gnu/arch/powerpc/boot/Makefile
--- linux-libre-4.6-gnu/arch/powerpc/boot/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/boot/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -362,9 +362,6 @@ $(obj)/cuImage.initrd.%: vmlinux $(obj)/
 $(obj)/cuImage.%: vmlinux $(obj)/%.dtb $(wrapperbits)
 	$(call if_changed,wrap,cuboot-$*,,$(obj)/$*.dtb)
 
-$(obj)/cuImage.%: vmlinux $(obj)/fsl/%.dtb $(wrapperbits)
-	$(call if_changed,wrap,cuboot-$*,,$(obj)/fsl/$*.dtb)
-
 $(obj)/simpleImage.initrd.%: vmlinux $(obj)/%.dtb $(wrapperbits)
 	$(call if_changed,wrap,simpleboot-$*,,$(obj)/$*.dtb,$(obj)/ramdisk.image.gz)
 
@@ -381,6 +378,9 @@ $(obj)/treeImage.%: vmlinux $(obj)/%.dtb
 $(obj)/%.dtb: $(src)/dts/%.dts FORCE
 	$(call if_changed_dep,dtc)
 
+$(obj)/%.dtb: $(src)/dts/fsl/%.dts FORCE
+	$(call if_changed_dep,dtc)
+
 # If there isn't a platform selected then just strip the vmlinux.
 ifeq (,$(image-y))
 image-y := vmlinux.strip
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/32/hash.h linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/32/hash.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/32/hash.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/32/hash.h	2016-07-24 15:23:50.000000000 -0400
@@ -39,8 +39,5 @@
 #define _PMD_PRESENT_MASK (PAGE_MASK)
 #define _PMD_BAD	(~PAGE_MASK)
 
-/* Hash table based platforms need atomic updates of the linux PTE */
-#define PTE_ATOMIC_UPDATES	1
-
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_BOOK3S_32_HASH_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/32/mmu-hash.h linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/32/mmu-hash.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/32/mmu-hash.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/32/mmu-hash.h	2016-07-24 15:23:50.000000000 -0400
@@ -1,5 +1,5 @@
-#ifndef _ASM_POWERPC_MMU_HASH32_H_
-#define _ASM_POWERPC_MMU_HASH32_H_
+#ifndef _ASM_POWERPC_BOOK3S_32_MMU_HASH_H_
+#define _ASM_POWERPC_BOOK3S_32_MMU_HASH_H_
 /*
  * 32-bit hash table MMU support
  */
@@ -90,4 +90,4 @@ typedef struct {
 #define mmu_virtual_psize	MMU_PAGE_4K
 #define mmu_linear_psize	MMU_PAGE_256M
 
-#endif /* _ASM_POWERPC_MMU_HASH32_H_ */
+#endif /* _ASM_POWERPC_BOOK3S_32_MMU_HASH_H_ */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/32/pgalloc.h linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/32/pgalloc.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/32/pgalloc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/32/pgalloc.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,108 @@
+#ifndef _ASM_POWERPC_BOOK3S_32_PGALLOC_H
+#define _ASM_POWERPC_BOOK3S_32_PGALLOC_H
+
+#include <linux/threads.h>
+
+/* For 32-bit, all levels of page tables are just drawn from get_free_page() */
+#define MAX_PGTABLE_INDEX_SIZE	0
+
+extern void __bad_pte(pmd_t *pmd);
+
+extern pgd_t *pgd_alloc(struct mm_struct *mm);
+extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
+
+/*
+ * We don't have any real pmd's, and this code never triggers because
+ * the pgd will always be present..
+ */
+/* #define pmd_alloc_one(mm,address)       ({ BUG(); ((pmd_t *)2); }) */
+#define pmd_free(mm, x) 		do { } while (0)
+#define __pmd_free_tlb(tlb,x,a)		do { } while (0)
+/* #define pgd_populate(mm, pmd, pte)      BUG() */
+
+#ifndef CONFIG_BOOKE
+
+static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp,
+				       pte_t *pte)
+{
+	*pmdp = __pmd(__pa(pte) | _PMD_PRESENT);
+}
+
+static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmdp,
+				pgtable_t pte_page)
+{
+	*pmdp = __pmd((page_to_pfn(pte_page) << PAGE_SHIFT) | _PMD_PRESENT);
+}
+
+#define pmd_pgtable(pmd) pmd_page(pmd)
+#else
+
+static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp,
+				       pte_t *pte)
+{
+	*pmdp = __pmd((unsigned long)pte | _PMD_PRESENT);
+}
+
+static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmdp,
+				pgtable_t pte_page)
+{
+	*pmdp = __pmd((unsigned long)lowmem_page_address(pte_page) | _PMD_PRESENT);
+}
+
+#define pmd_pgtable(pmd) pmd_page(pmd)
+#endif
+
+extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr);
+extern pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long addr);
+
+static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+{
+	free_page((unsigned long)pte);
+}
+
+static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage)
+{
+	pgtable_page_dtor(ptepage);
+	__free_page(ptepage);
+}
+
+static inline void pgtable_free(void *table, unsigned index_size)
+{
+	BUG_ON(index_size); /* 32-bit doesn't use this */
+	free_page((unsigned long)table);
+}
+
+#define check_pgt_cache()	do { } while (0)
+
+#ifdef CONFIG_SMP
+static inline void pgtable_free_tlb(struct mmu_gather *tlb,
+				    void *table, int shift)
+{
+	unsigned long pgf = (unsigned long)table;
+	BUG_ON(shift > MAX_PGTABLE_INDEX_SIZE);
+	pgf |= shift;
+	tlb_remove_table(tlb, (void *)pgf);
+}
+
+static inline void __tlb_remove_table(void *_table)
+{
+	void *table = (void *)((unsigned long)_table & ~MAX_PGTABLE_INDEX_SIZE);
+	unsigned shift = (unsigned long)_table & MAX_PGTABLE_INDEX_SIZE;
+
+	pgtable_free(table, shift);
+}
+#else
+static inline void pgtable_free_tlb(struct mmu_gather *tlb,
+				    void *table, int shift)
+{
+	pgtable_free(table, shift);
+}
+#endif
+
+static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table,
+				  unsigned long address)
+{
+	pgtable_page_dtor(table);
+	pgtable_free_tlb(tlb, page_address(table), 0);
+}
+#endif /* _ASM_POWERPC_BOOK3S_32_PGALLOC_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/64/hash-4k.h linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/64/hash-4k.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/64/hash-4k.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/64/hash-4k.h	2016-07-24 15:23:50.000000000 -0400
@@ -5,58 +5,31 @@
  * for each page table entry.  The PMD and PGD level use a 32b record for
  * each entry by assuming that each entry is page aligned.
  */
-#define PTE_INDEX_SIZE  9
-#define PMD_INDEX_SIZE  7
-#define PUD_INDEX_SIZE  9
-#define PGD_INDEX_SIZE  9
+#define H_PTE_INDEX_SIZE  9
+#define H_PMD_INDEX_SIZE  7
+#define H_PUD_INDEX_SIZE  9
+#define H_PGD_INDEX_SIZE  9
 
 #ifndef __ASSEMBLY__
-#define PTE_TABLE_SIZE	(sizeof(pte_t) << PTE_INDEX_SIZE)
-#define PMD_TABLE_SIZE	(sizeof(pmd_t) << PMD_INDEX_SIZE)
-#define PUD_TABLE_SIZE	(sizeof(pud_t) << PUD_INDEX_SIZE)
-#define PGD_TABLE_SIZE	(sizeof(pgd_t) << PGD_INDEX_SIZE)
-#endif	/* __ASSEMBLY__ */
-
-#define PTRS_PER_PTE	(1 << PTE_INDEX_SIZE)
-#define PTRS_PER_PMD	(1 << PMD_INDEX_SIZE)
-#define PTRS_PER_PUD	(1 << PUD_INDEX_SIZE)
-#define PTRS_PER_PGD	(1 << PGD_INDEX_SIZE)
-
-/* PMD_SHIFT determines what a second-level page table entry can map */
-#define PMD_SHIFT	(PAGE_SHIFT + PTE_INDEX_SIZE)
-#define PMD_SIZE	(1UL << PMD_SHIFT)
-#define PMD_MASK	(~(PMD_SIZE-1))
+#define H_PTE_TABLE_SIZE	(sizeof(pte_t) << H_PTE_INDEX_SIZE)
+#define H_PMD_TABLE_SIZE	(sizeof(pmd_t) << H_PMD_INDEX_SIZE)
+#define H_PUD_TABLE_SIZE	(sizeof(pud_t) << H_PUD_INDEX_SIZE)
+#define H_PGD_TABLE_SIZE	(sizeof(pgd_t) << H_PGD_INDEX_SIZE)
 
 /* With 4k base page size, hugepage PTEs go at the PMD level */
 #define MIN_HUGEPTE_SHIFT	PMD_SHIFT
 
-/* PUD_SHIFT determines what a third-level page table entry can map */
-#define PUD_SHIFT	(PMD_SHIFT + PMD_INDEX_SIZE)
-#define PUD_SIZE	(1UL << PUD_SHIFT)
-#define PUD_MASK	(~(PUD_SIZE-1))
-
-/* PGDIR_SHIFT determines what a fourth-level page table entry can map */
-#define PGDIR_SHIFT	(PUD_SHIFT + PUD_INDEX_SIZE)
-#define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
-#define PGDIR_MASK	(~(PGDIR_SIZE-1))
-
-/* Bits to mask out from a PMD to get to the PTE page */
-#define PMD_MASKED_BITS		0
-/* Bits to mask out from a PUD to get to the PMD page */
-#define PUD_MASKED_BITS		0
-/* Bits to mask out from a PGD to get to the PUD page */
-#define PGD_MASKED_BITS		0
-
 /* PTE flags to conserve for HPTE identification */
-#define _PAGE_HPTEFLAGS (_PAGE_BUSY | _PAGE_HASHPTE | \
-			 _PAGE_F_SECOND | _PAGE_F_GIX)
-
-/* shift to put page number into pte */
-#define PTE_RPN_SHIFT	(12)
-#define PTE_RPN_SIZE	(45)	/* gives 57-bit real addresses */
-
-#define _PAGE_4K_PFN		0
-#ifndef __ASSEMBLY__
+#define _PAGE_HPTEFLAGS (H_PAGE_BUSY | H_PAGE_HASHPTE | \
+			 H_PAGE_F_SECOND | H_PAGE_F_GIX)
+/*
+ * Not supported by 4k linux page size
+ */
+#define H_PAGE_4K_PFN	0x0
+#define H_PAGE_THP_HUGE 0x0
+#define H_PAGE_COMBO	0x0
+#define H_PTE_FRAG_NR	0
+#define H_PTE_FRAG_SIZE_SHIFT  0
 /*
  * On all 4K setups, remap_4k_pfn() equates to remap_pfn_range()
  */
@@ -64,37 +37,76 @@
 	remap_pfn_range((vma), (addr), (pfn), PAGE_SIZE, (prot))
 
 #ifdef CONFIG_HUGETLB_PAGE
-/*
- * For 4k page size, we support explicit hugepage via hugepd
- */
-static inline int pmd_huge(pmd_t pmd)
+static inline int hash__hugepd_ok(hugepd_t hpd)
 {
+	/*
+	 * if it is not a pte and have hugepd shift mask
+	 * set, then it is a hugepd directory pointer
+	 */
+	if (!(hpd.pd & _PAGE_PTE) &&
+	    ((hpd.pd & HUGEPD_SHIFT_MASK) != 0))
+		return true;
+	return false;
+}
+#endif
+
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+
+static inline char *get_hpte_slot_array(pmd_t *pmdp)
+{
+	BUG();
+	return NULL;
+}
+
+static inline unsigned int hpte_valid(unsigned char *hpte_slot_array, int index)
+{
+	BUG();
 	return 0;
 }
 
-static inline int pud_huge(pud_t pud)
+static inline unsigned int hpte_hash_index(unsigned char *hpte_slot_array,
+					   int index)
 {
+	BUG();
 	return 0;
 }
 
-static inline int pgd_huge(pgd_t pgd)
+static inline void mark_hpte_slot_valid(unsigned char *hpte_slot_array,
+					unsigned int index, unsigned int hidx)
+{
+	BUG();
+}
+
+static inline int hash__pmd_trans_huge(pmd_t pmd)
 {
 	return 0;
 }
-#define pgd_huge pgd_huge
 
-static inline int hugepd_ok(hugepd_t hpd)
+static inline int hash__pmd_same(pmd_t pmd_a, pmd_t pmd_b)
 {
-	/*
-	 * if it is not a pte and have hugepd shift mask
-	 * set, then it is a hugepd directory pointer
-	 */
-	if (!(hpd.pd & _PAGE_PTE) &&
-	    ((hpd.pd & HUGEPD_SHIFT_MASK) != 0))
-		return true;
-	return false;
+	BUG();
+	return 0;
 }
-#define is_hugepd(hpd)		(hugepd_ok(hpd))
+
+static inline pmd_t hash__pmd_mkhuge(pmd_t pmd)
+{
+	BUG();
+	return pmd;
+}
+
+extern unsigned long hash__pmd_hugepage_update(struct mm_struct *mm,
+					   unsigned long addr, pmd_t *pmdp,
+					   unsigned long clr, unsigned long set);
+extern pmd_t hash__pmdp_collapse_flush(struct vm_area_struct *vma,
+				   unsigned long address, pmd_t *pmdp);
+extern void hash__pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp,
+					 pgtable_t pgtable);
+extern pgtable_t hash__pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp);
+extern void hash__pmdp_huge_split_prepare(struct vm_area_struct *vma,
+				      unsigned long address, pmd_t *pmdp);
+extern pmd_t hash__pmdp_huge_get_and_clear(struct mm_struct *mm,
+				       unsigned long addr, pmd_t *pmdp);
+extern int hash__has_transparent_hugepage(void);
 #endif
 
 #endif /* !__ASSEMBLY__ */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/64/hash-64k.h linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/64/hash-64k.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/64/hash-64k.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/64/hash-64k.h	2016-07-24 15:23:50.000000000 -0400
@@ -1,73 +1,44 @@
 #ifndef _ASM_POWERPC_BOOK3S_64_HASH_64K_H
 #define _ASM_POWERPC_BOOK3S_64_HASH_64K_H
 
-#define PTE_INDEX_SIZE  8
-#define PMD_INDEX_SIZE  5
-#define PUD_INDEX_SIZE	5
-#define PGD_INDEX_SIZE  12
-
-#define PTRS_PER_PTE	(1 << PTE_INDEX_SIZE)
-#define PTRS_PER_PMD	(1 << PMD_INDEX_SIZE)
-#define PTRS_PER_PUD	(1 << PUD_INDEX_SIZE)
-#define PTRS_PER_PGD	(1 << PGD_INDEX_SIZE)
+#define H_PTE_INDEX_SIZE  8
+#define H_PMD_INDEX_SIZE  5
+#define H_PUD_INDEX_SIZE  5
+#define H_PGD_INDEX_SIZE  12
 
 /* With 4k base page size, hugepage PTEs go at the PMD level */
 #define MIN_HUGEPTE_SHIFT	PAGE_SHIFT
 
-/* PMD_SHIFT determines what a second-level page table entry can map */
-#define PMD_SHIFT	(PAGE_SHIFT + PTE_INDEX_SIZE)
-#define PMD_SIZE	(1UL << PMD_SHIFT)
-#define PMD_MASK	(~(PMD_SIZE-1))
-
-/* PUD_SHIFT determines what a third-level page table entry can map */
-#define PUD_SHIFT	(PMD_SHIFT + PMD_INDEX_SIZE)
-#define PUD_SIZE	(1UL << PUD_SHIFT)
-#define PUD_MASK	(~(PUD_SIZE-1))
-
-/* PGDIR_SHIFT determines what a fourth-level page table entry can map */
-#define PGDIR_SHIFT	(PUD_SHIFT + PUD_INDEX_SIZE)
-#define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
-#define PGDIR_MASK	(~(PGDIR_SIZE-1))
-
-#define _PAGE_COMBO	0x00001000 /* this is a combo 4k page */
-#define _PAGE_4K_PFN	0x00002000 /* PFN is for a single 4k page */
+#define H_PAGE_COMBO	0x00001000 /* this is a combo 4k page */
+#define H_PAGE_4K_PFN	0x00002000 /* PFN is for a single 4k page */
 /*
- * Used to track subpage group valid if _PAGE_COMBO is set
- * This overloads _PAGE_F_GIX and _PAGE_F_SECOND
+ * We need to differentiate between explicit huge page and THP huge
+ * page, since THP huge page also need to track real subpage details
  */
-#define _PAGE_COMBO_VALID	(_PAGE_F_GIX | _PAGE_F_SECOND)
-
-/* PTE flags to conserve for HPTE identification */
-#define _PAGE_HPTEFLAGS (_PAGE_BUSY | _PAGE_F_SECOND | \
-			 _PAGE_F_GIX | _PAGE_HASHPTE | _PAGE_COMBO)
+#define H_PAGE_THP_HUGE  H_PAGE_4K_PFN
 
-/* Shift to put page number into pte.
- *
- * That gives us a max RPN of 41 bits, which means a max of 57 bits
- * of addressable physical space, or 53 bits for the special 4k PFNs.
+/*
+ * Used to track subpage group valid if H_PAGE_COMBO is set
+ * This overloads H_PAGE_F_GIX and H_PAGE_F_SECOND
  */
-#define PTE_RPN_SHIFT	(16)
-#define PTE_RPN_SIZE	(41)
+#define H_PAGE_COMBO_VALID	(H_PAGE_F_GIX | H_PAGE_F_SECOND)
 
+/* PTE flags to conserve for HPTE identification */
+#define _PAGE_HPTEFLAGS (H_PAGE_BUSY | H_PAGE_F_SECOND | \
+			 H_PAGE_F_GIX | H_PAGE_HASHPTE | H_PAGE_COMBO)
 /*
  * we support 16 fragments per PTE page of 64K size.
  */
-#define PTE_FRAG_NR	16
+#define H_PTE_FRAG_NR	16
 /*
  * We use a 2K PTE page fragment and another 2K for storing
  * real_pte_t hash index
  */
-#define PTE_FRAG_SIZE_SHIFT  12
+#define H_PTE_FRAG_SIZE_SHIFT  12
 #define PTE_FRAG_SIZE (1UL << PTE_FRAG_SIZE_SHIFT)
 
-/* Bits to mask out from a PMD to get to the PTE page */
-#define PMD_MASKED_BITS		0xc0000000000000ffUL
-/* Bits to mask out from a PUD to get to the PMD page */
-#define PUD_MASKED_BITS		0xc0000000000000ffUL
-/* Bits to mask out from a PGD to get to the PUD page */
-#define PGD_MASKED_BITS		0xc0000000000000ffUL
-
 #ifndef __ASSEMBLY__
+#include <asm/errno.h>
 
 /*
  * With 64K pages on hash table, we have a special PTE format that
@@ -83,9 +54,9 @@ static inline real_pte_t __real_pte(pte_
 
 	rpte.pte = pte;
 	rpte.hidx = 0;
-	if (pte_val(pte) & _PAGE_COMBO) {
+	if (pte_val(pte) & H_PAGE_COMBO) {
 		/*
-		 * Make sure we order the hidx load against the _PAGE_COMBO
+		 * Make sure we order the hidx load against the H_PAGE_COMBO
 		 * check. The store side ordering is done in __hash_page_4K
 		 */
 		smp_rmb();
@@ -97,9 +68,9 @@ static inline real_pte_t __real_pte(pte_
 
 static inline unsigned long __rpte_to_hidx(real_pte_t rpte, unsigned long index)
 {
-	if ((pte_val(rpte.pte) & _PAGE_COMBO))
+	if ((pte_val(rpte.pte) & H_PAGE_COMBO))
 		return (rpte.hidx >> (index<<2)) & 0xf;
-	return (pte_val(rpte.pte) >> _PAGE_F_GIX_SHIFT) & 0xf;
+	return (pte_val(rpte.pte) >> H_PAGE_F_GIX_SHIFT) & 0xf;
 }
 
 #define __rpte_to_pte(r)	((r).pte)
@@ -122,79 +93,32 @@ extern bool __rpte_sub_valid(real_pte_t
 #define pte_iterate_hashed_end() } while(0); } } while(0)
 
 #define pte_pagesize_index(mm, addr, pte)	\
-	(((pte) & _PAGE_COMBO)? MMU_PAGE_4K: MMU_PAGE_64K)
-
-#define remap_4k_pfn(vma, addr, pfn, prot)				\
-	(WARN_ON(((pfn) >= (1UL << PTE_RPN_SIZE))) ? -EINVAL :	\
-		remap_pfn_range((vma), (addr), (pfn), PAGE_SIZE,	\
-			__pgprot(pgprot_val((prot)) | _PAGE_4K_PFN)))
-
-#define PTE_TABLE_SIZE	PTE_FRAG_SIZE
-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
-#define PMD_TABLE_SIZE	((sizeof(pmd_t) << PMD_INDEX_SIZE) + (sizeof(unsigned long) << PMD_INDEX_SIZE))
-#else
-#define PMD_TABLE_SIZE	(sizeof(pmd_t) << PMD_INDEX_SIZE)
-#endif
-#define PUD_TABLE_SIZE	(sizeof(pud_t) << PUD_INDEX_SIZE)
-#define PGD_TABLE_SIZE	(sizeof(pgd_t) << PGD_INDEX_SIZE)
-
-#ifdef CONFIG_HUGETLB_PAGE
-/*
- * We have PGD_INDEX_SIZ = 12 and PTE_INDEX_SIZE = 8, so that we can have
- * 16GB hugepage pte in PGD and 16MB hugepage pte at PMD;
- *
- * Defined in such a way that we can optimize away code block at build time
- * if CONFIG_HUGETLB_PAGE=n.
- */
-static inline int pmd_huge(pmd_t pmd)
-{
-	/*
-	 * leaf pte for huge page
-	 */
-	return !!(pmd_val(pmd) & _PAGE_PTE);
-}
-
-static inline int pud_huge(pud_t pud)
-{
-	/*
-	 * leaf pte for huge page
-	 */
-	return !!(pud_val(pud) & _PAGE_PTE);
-}
+	(((pte) & H_PAGE_COMBO)? MMU_PAGE_4K: MMU_PAGE_64K)
 
-static inline int pgd_huge(pgd_t pgd)
+extern int remap_pfn_range(struct vm_area_struct *, unsigned long addr,
+			   unsigned long pfn, unsigned long size, pgprot_t);
+static inline int hash__remap_4k_pfn(struct vm_area_struct *vma, unsigned long addr,
+				 unsigned long pfn, pgprot_t prot)
 {
-	/*
-	 * leaf pte for huge page
-	 */
-	return !!(pgd_val(pgd) & _PAGE_PTE);
+	if (pfn > (PTE_RPN_MASK >> PAGE_SHIFT)) {
+		WARN(1, "remap_4k_pfn called with wrong pfn value\n");
+		return -EINVAL;
+	}
+	return remap_pfn_range(vma, addr, pfn, PAGE_SIZE,
+			       __pgprot(pgprot_val(prot) | H_PAGE_4K_PFN));
 }
-#define pgd_huge pgd_huge
 
-#ifdef CONFIG_DEBUG_VM
-extern int hugepd_ok(hugepd_t hpd);
-#define is_hugepd(hpd)               (hugepd_ok(hpd))
+#define H_PTE_TABLE_SIZE	PTE_FRAG_SIZE
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+#define H_PMD_TABLE_SIZE	((sizeof(pmd_t) << PMD_INDEX_SIZE) + \
+				 (sizeof(unsigned long) << PMD_INDEX_SIZE))
 #else
-/*
- * With 64k page size, we have hugepage ptes in the pgd and pmd entries. We don't
- * need to setup hugepage directory for them. Our pte and page directory format
- * enable us to have this enabled.
- */
-static inline int hugepd_ok(hugepd_t hpd)
-{
-	return 0;
-}
-#define is_hugepd(pdep)			0
-#endif /* CONFIG_DEBUG_VM */
-
-#endif /* CONFIG_HUGETLB_PAGE */
+#define H_PMD_TABLE_SIZE	(sizeof(pmd_t) << PMD_INDEX_SIZE)
+#endif
+#define H_PUD_TABLE_SIZE	(sizeof(pud_t) << PUD_INDEX_SIZE)
+#define H_PGD_TABLE_SIZE	(sizeof(pgd_t) << PGD_INDEX_SIZE)
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
-extern unsigned long pmd_hugepage_update(struct mm_struct *mm,
-					 unsigned long addr,
-					 pmd_t *pmdp,
-					 unsigned long clr,
-					 unsigned long set);
 static inline char *get_hpte_slot_array(pmd_t *pmdp)
 {
 	/*
@@ -253,50 +177,35 @@ static inline void mark_hpte_slot_valid(
  * that for explicit huge pages.
  *
  */
-static inline int pmd_trans_huge(pmd_t pmd)
-{
-	return !!((pmd_val(pmd) & (_PAGE_PTE | _PAGE_THP_HUGE)) ==
-		  (_PAGE_PTE | _PAGE_THP_HUGE));
-}
-
-static inline int pmd_large(pmd_t pmd)
-{
-	return !!(pmd_val(pmd) & _PAGE_PTE);
-}
-
-static inline pmd_t pmd_mknotpresent(pmd_t pmd)
-{
-	return __pmd(pmd_val(pmd) & ~_PAGE_PRESENT);
-}
-
-#define __HAVE_ARCH_PMD_SAME
-static inline int pmd_same(pmd_t pmd_a, pmd_t pmd_b)
+static inline int hash__pmd_trans_huge(pmd_t pmd)
 {
-	return (((pmd_val(pmd_a) ^ pmd_val(pmd_b)) & ~_PAGE_HPTEFLAGS) == 0);
+	return !!((pmd_val(pmd) & (_PAGE_PTE | H_PAGE_THP_HUGE)) ==
+		  (_PAGE_PTE | H_PAGE_THP_HUGE));
 }
 
-static inline int __pmdp_test_and_clear_young(struct mm_struct *mm,
-					      unsigned long addr, pmd_t *pmdp)
+static inline int hash__pmd_same(pmd_t pmd_a, pmd_t pmd_b)
 {
-	unsigned long old;
-
-	if ((pmd_val(*pmdp) & (_PAGE_ACCESSED | _PAGE_HASHPTE)) == 0)
-		return 0;
-	old = pmd_hugepage_update(mm, addr, pmdp, _PAGE_ACCESSED, 0);
-	return ((old & _PAGE_ACCESSED) != 0);
+	return (((pmd_raw(pmd_a) ^ pmd_raw(pmd_b)) & ~cpu_to_be64(_PAGE_HPTEFLAGS)) == 0);
 }
 
-#define __HAVE_ARCH_PMDP_SET_WRPROTECT
-static inline void pmdp_set_wrprotect(struct mm_struct *mm, unsigned long addr,
-				      pmd_t *pmdp)
+static inline pmd_t hash__pmd_mkhuge(pmd_t pmd)
 {
-
-	if ((pmd_val(*pmdp) & _PAGE_RW) == 0)
-		return;
-
-	pmd_hugepage_update(mm, addr, pmdp, _PAGE_RW, 0);
+	return __pmd(pmd_val(pmd) | (_PAGE_PTE | H_PAGE_THP_HUGE));
 }
 
+extern unsigned long hash__pmd_hugepage_update(struct mm_struct *mm,
+					   unsigned long addr, pmd_t *pmdp,
+					   unsigned long clr, unsigned long set);
+extern pmd_t hash__pmdp_collapse_flush(struct vm_area_struct *vma,
+				   unsigned long address, pmd_t *pmdp);
+extern void hash__pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp,
+					 pgtable_t pgtable);
+extern pgtable_t hash__pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp);
+extern void hash__pmdp_huge_split_prepare(struct vm_area_struct *vma,
+				      unsigned long address, pmd_t *pmdp);
+extern pmd_t hash__pmdp_huge_get_and_clear(struct mm_struct *mm,
+				       unsigned long addr, pmd_t *pmdp);
+extern int hash__has_transparent_hugepage(void);
 #endif /*  CONFIG_TRANSPARENT_HUGEPAGE */
 #endif	/* __ASSEMBLY__ */
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/64/hash.h linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/64/hash.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/64/hash.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/64/hash.h	2016-07-24 15:23:50.000000000 -0400
@@ -13,48 +13,12 @@
  * We could create separate kernel read-only if we used the 3 PP bits
  * combinations that newer processors provide but we currently don't.
  */
-#define _PAGE_BIT_SWAP_TYPE	0
-
-#define _PAGE_EXEC		0x00001 /* execute permission */
-#define _PAGE_RW		0x00002 /* read & write access allowed */
-#define _PAGE_READ		0x00004	/* read access allowed */
-#define _PAGE_USER		0x00008 /* page may be accessed by userspace */
-#define _PAGE_GUARDED		0x00010 /* G: guarded (side-effect) page */
-/* M (memory coherence) is always set in the HPTE, so we don't need it here */
-#define _PAGE_COHERENT		0x0
-#define _PAGE_NO_CACHE		0x00020 /* I: cache inhibit */
-#define _PAGE_WRITETHRU		0x00040 /* W: cache write-through */
-#define _PAGE_DIRTY		0x00080 /* C: page changed */
-#define _PAGE_ACCESSED		0x00100 /* R: page referenced */
-#define _PAGE_SPECIAL		0x00400 /* software: special page */
-#define _PAGE_BUSY		0x00800 /* software: PTE & hash are busy */
-
-#ifdef CONFIG_MEM_SOFT_DIRTY
-#define _PAGE_SOFT_DIRTY	0x200 /* software: software dirty tracking */
-#else
-#define _PAGE_SOFT_DIRTY	0x000
-#endif
-
-#define _PAGE_F_GIX_SHIFT	57
-#define _PAGE_F_GIX		(7ul << 57)	/* HPTE index within HPTEG */
-#define _PAGE_F_SECOND		(1ul << 60)	/* HPTE is in 2ndary HPTEG */
-#define _PAGE_HASHPTE		(1ul << 61)	/* PTE has associated HPTE */
-#define _PAGE_PTE		(1ul << 62)	/* distinguishes PTEs from pointers */
-#define _PAGE_PRESENT		(1ul << 63)	/* pte contains a translation */
-
-/*
- * We need to differentiate between explicit huge page and THP huge
- * page, since THP huge page also need to track real subpage details
- */
-#define _PAGE_THP_HUGE  _PAGE_4K_PFN
-
-/*
- * set of bits not changed in pmd_modify.
- */
-#define _HPAGE_CHG_MASK (PTE_RPN_MASK | _PAGE_HPTEFLAGS | _PAGE_DIRTY | \
-			 _PAGE_ACCESSED | _PAGE_THP_HUGE | _PAGE_PTE | \
-			 _PAGE_SOFT_DIRTY)
-
+#define H_PAGE_BUSY		0x00800 /* software: PTE & hash are busy */
+#define H_PTE_NONE_MASK		_PAGE_HPTEFLAGS
+#define H_PAGE_F_GIX_SHIFT	57
+#define H_PAGE_F_GIX		(7ul << 57)	/* HPTE index within HPTEG */
+#define H_PAGE_F_SECOND		(1ul << 60)	/* HPTE is in 2ndary HPTEG */
+#define H_PAGE_HASHPTE		(1ul << 61)	/* PTE has associated HPTE */
 
 #ifdef CONFIG_PPC_64K_PAGES
 #include <asm/book3s/64/hash-64k.h>
@@ -65,29 +29,33 @@
 /*
  * Size of EA range mapped by our pagetables.
  */
-#define PGTABLE_EADDR_SIZE	(PTE_INDEX_SIZE + PMD_INDEX_SIZE + \
-				 PUD_INDEX_SIZE + PGD_INDEX_SIZE + PAGE_SHIFT)
-#define PGTABLE_RANGE		(ASM_CONST(1) << PGTABLE_EADDR_SIZE)
+#define H_PGTABLE_EADDR_SIZE	(H_PTE_INDEX_SIZE + H_PMD_INDEX_SIZE + \
+				 H_PUD_INDEX_SIZE + H_PGD_INDEX_SIZE + PAGE_SHIFT)
+#define H_PGTABLE_RANGE		(ASM_CONST(1) << H_PGTABLE_EADDR_SIZE)
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
-#define PMD_CACHE_INDEX	(PMD_INDEX_SIZE + 1)
+/*
+ * only with hash we need to use the second half of pmd page table
+ * to store pointer to deposited pgtable_t
+ */
+#define H_PMD_CACHE_INDEX	(H_PMD_INDEX_SIZE + 1)
 #else
-#define PMD_CACHE_INDEX	PMD_INDEX_SIZE
+#define H_PMD_CACHE_INDEX	H_PMD_INDEX_SIZE
 #endif
 /*
  * Define the address range of the kernel non-linear virtual area
  */
-#define KERN_VIRT_START ASM_CONST(0xD000000000000000)
-#define KERN_VIRT_SIZE	ASM_CONST(0x0000100000000000)
+#define H_KERN_VIRT_START ASM_CONST(0xD000000000000000)
+#define H_KERN_VIRT_SIZE	ASM_CONST(0x0000100000000000)
 
 /*
  * The vmalloc space starts at the beginning of that region, and
  * occupies half of it on hash CPUs and a quarter of it on Book3E
  * (we keep a quarter for the virtual memmap)
  */
-#define VMALLOC_START	KERN_VIRT_START
-#define VMALLOC_SIZE	(KERN_VIRT_SIZE >> 1)
-#define VMALLOC_END	(VMALLOC_START + VMALLOC_SIZE)
+#define H_VMALLOC_START	H_KERN_VIRT_START
+#define H_VMALLOC_SIZE	(H_KERN_VIRT_SIZE >> 1)
+#define H_VMALLOC_END	(H_VMALLOC_START + H_VMALLOC_SIZE)
 
 /*
  * Region IDs
@@ -96,7 +64,7 @@
 #define REGION_MASK		(0xfUL << REGION_SHIFT)
 #define REGION_ID(ea)		(((unsigned long)(ea)) >> REGION_SHIFT)
 
-#define VMALLOC_REGION_ID	(REGION_ID(VMALLOC_START))
+#define VMALLOC_REGION_ID	(REGION_ID(H_VMALLOC_START))
 #define KERNEL_REGION_ID	(REGION_ID(PAGE_OFFSET))
 #define VMEMMAP_REGION_ID	(0xfUL)	/* Server only */
 #define USER_REGION_ID		(0UL)
@@ -105,381 +73,97 @@
  * Defines the address of the vmemap area, in its own region on
  * hash table CPUs.
  */
-#define VMEMMAP_BASE		(VMEMMAP_REGION_ID << REGION_SHIFT)
+#define H_VMEMMAP_BASE		(VMEMMAP_REGION_ID << REGION_SHIFT)
 
 #ifdef CONFIG_PPC_MM_SLICES
 #define HAVE_ARCH_UNMAPPED_AREA
 #define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
 #endif /* CONFIG_PPC_MM_SLICES */
 
-/* No separate kernel read-only */
-#define _PAGE_KERNEL_RW		(_PAGE_RW | _PAGE_DIRTY) /* user access blocked by key */
-#define _PAGE_KERNEL_RO		 _PAGE_KERNEL_RW
-#define _PAGE_KERNEL_RWX	(_PAGE_DIRTY | _PAGE_RW | _PAGE_EXEC)
-
-/* Strong Access Ordering */
-#define _PAGE_SAO		(_PAGE_WRITETHRU | _PAGE_NO_CACHE | _PAGE_COHERENT)
-
-/* No page size encoding in the linux PTE */
-#define _PAGE_PSIZE		0
 
 /* PTEIDX nibble */
 #define _PTEIDX_SECONDARY	0x8
 #define _PTEIDX_GROUP_IX	0x7
 
-/* Hash table based platforms need atomic updates of the linux PTE */
-#define PTE_ATOMIC_UPDATES	1
-#define _PTE_NONE_MASK	_PAGE_HPTEFLAGS
-/*
- * The mask convered by the RPN must be a ULL on 32-bit platforms with
- * 64-bit PTEs
- */
-#define PTE_RPN_MASK	(((1UL << PTE_RPN_SIZE) - 1) << PTE_RPN_SHIFT)
-/*
- * _PAGE_CHG_MASK masks of bits that are to be preserved across
- * pgprot changes
- */
-#define _PAGE_CHG_MASK	(PTE_RPN_MASK | _PAGE_HPTEFLAGS | _PAGE_DIRTY | \
-			 _PAGE_ACCESSED | _PAGE_SPECIAL | _PAGE_PTE | \
-			 _PAGE_SOFT_DIRTY)
-/*
- * Mask of bits returned by pte_pgprot()
- */
-#define PAGE_PROT_BITS	(_PAGE_GUARDED | _PAGE_COHERENT | _PAGE_NO_CACHE | \
-			 _PAGE_WRITETHRU | _PAGE_4K_PFN | \
-			 _PAGE_USER | _PAGE_ACCESSED |  \
-			 _PAGE_RW |  _PAGE_DIRTY | _PAGE_EXEC | \
-			 _PAGE_SOFT_DIRTY)
-/*
- * We define 2 sets of base prot bits, one for basic pages (ie,
- * cacheable kernel and user pages) and one for non cacheable
- * pages. We always set _PAGE_COHERENT when SMP is enabled or
- * the processor might need it for DMA coherency.
- */
-#define _PAGE_BASE_NC	(_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_PSIZE)
-#define _PAGE_BASE	(_PAGE_BASE_NC | _PAGE_COHERENT)
-
-/* Permission masks used to generate the __P and __S table,
- *
- * Note:__pgprot is defined in arch/powerpc/include/asm/page.h
- *
- * Write permissions imply read permissions for now (we could make write-only
- * pages on BookE but we don't bother for now). Execute permission control is
- * possible on platforms that define _PAGE_EXEC
- *
- * Note due to the way vm flags are laid out, the bits are XWR
- */
-#define PAGE_NONE	__pgprot(_PAGE_BASE)
-#define PAGE_SHARED	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW)
-#define PAGE_SHARED_X	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | \
-				 _PAGE_EXEC)
-#define PAGE_COPY	__pgprot(_PAGE_BASE | _PAGE_USER )
-#define PAGE_COPY_X	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
-#define PAGE_READONLY	__pgprot(_PAGE_BASE | _PAGE_USER )
-#define PAGE_READONLY_X	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
-
-#define __P000	PAGE_NONE
-#define __P001	PAGE_READONLY
-#define __P010	PAGE_COPY
-#define __P011	PAGE_COPY
-#define __P100	PAGE_READONLY_X
-#define __P101	PAGE_READONLY_X
-#define __P110	PAGE_COPY_X
-#define __P111	PAGE_COPY_X
-
-#define __S000	PAGE_NONE
-#define __S001	PAGE_READONLY
-#define __S010	PAGE_SHARED
-#define __S011	PAGE_SHARED
-#define __S100	PAGE_READONLY_X
-#define __S101	PAGE_READONLY_X
-#define __S110	PAGE_SHARED_X
-#define __S111	PAGE_SHARED_X
-
-/* Permission masks used for kernel mappings */
-#define PAGE_KERNEL	__pgprot(_PAGE_BASE | _PAGE_KERNEL_RW)
-#define PAGE_KERNEL_NC	__pgprot(_PAGE_BASE_NC | _PAGE_KERNEL_RW | \
-				 _PAGE_NO_CACHE)
-#define PAGE_KERNEL_NCG	__pgprot(_PAGE_BASE_NC | _PAGE_KERNEL_RW | \
-				 _PAGE_NO_CACHE | _PAGE_GUARDED)
-#define PAGE_KERNEL_X	__pgprot(_PAGE_BASE | _PAGE_KERNEL_RWX)
-#define PAGE_KERNEL_RO	__pgprot(_PAGE_BASE | _PAGE_KERNEL_RO)
-#define PAGE_KERNEL_ROX	__pgprot(_PAGE_BASE | _PAGE_KERNEL_ROX)
-
-/* Protection used for kernel text. We want the debuggers to be able to
- * set breakpoints anywhere, so don't write protect the kernel text
- * on platforms where such control is possible.
- */
-#if defined(CONFIG_KGDB) || defined(CONFIG_XMON) || defined(CONFIG_BDI_SWITCH) ||\
-	defined(CONFIG_KPROBES) || defined(CONFIG_DYNAMIC_FTRACE)
-#define PAGE_KERNEL_TEXT	PAGE_KERNEL_X
-#else
-#define PAGE_KERNEL_TEXT	PAGE_KERNEL_ROX
-#endif
-
-/* Make modules code happy. We don't set RO yet */
-#define PAGE_KERNEL_EXEC	PAGE_KERNEL_X
-#define PAGE_AGP		(PAGE_KERNEL_NC)
-
-#define PMD_BAD_BITS		(PTE_TABLE_SIZE-1)
-#define PUD_BAD_BITS		(PMD_TABLE_SIZE-1)
+#define H_PMD_BAD_BITS		(PTE_TABLE_SIZE-1)
+#define H_PUD_BAD_BITS		(PMD_TABLE_SIZE-1)
 
 #ifndef __ASSEMBLY__
-#define	pmd_bad(pmd)		(pmd_val(pmd) & PMD_BAD_BITS)
-#define pmd_page_vaddr(pmd)	__va(pmd_val(pmd) & ~PMD_MASKED_BITS)
-
-#define	pud_bad(pud)		(pud_val(pud) & PUD_BAD_BITS)
-#define pud_page_vaddr(pud)	__va(pud_val(pud) & ~PUD_MASKED_BITS)
-
-/* Pointers in the page table tree are physical addresses */
-#define __pgtable_ptr_val(ptr)	__pa(ptr)
-
-#define pgd_index(address) (((address) >> (PGDIR_SHIFT)) & (PTRS_PER_PGD - 1))
-#define pud_index(address) (((address) >> (PUD_SHIFT)) & (PTRS_PER_PUD - 1))
-#define pmd_index(address) (((address) >> (PMD_SHIFT)) & (PTRS_PER_PMD - 1))
-#define pte_index(address) (((address) >> (PAGE_SHIFT)) & (PTRS_PER_PTE - 1))
+#define	hash__pmd_bad(pmd)		(pmd_val(pmd) & H_PMD_BAD_BITS)
+#define	hash__pud_bad(pud)		(pud_val(pud) & H_PUD_BAD_BITS)
+static inline int hash__pgd_bad(pgd_t pgd)
+{
+	return (pgd_val(pgd) == 0);
+}
 
 extern void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
 			    pte_t *ptep, unsigned long pte, int huge);
 extern unsigned long htab_convert_pte_flags(unsigned long pteflags);
 /* Atomic PTE updates */
-static inline unsigned long pte_update(struct mm_struct *mm,
-				       unsigned long addr,
-				       pte_t *ptep, unsigned long clr,
-				       unsigned long set,
-				       int huge)
+static inline unsigned long hash__pte_update(struct mm_struct *mm,
+					 unsigned long addr,
+					 pte_t *ptep, unsigned long clr,
+					 unsigned long set,
+					 int huge)
 {
-	unsigned long old, tmp;
+	__be64 old_be, tmp_be;
+	unsigned long old;
 
 	__asm__ __volatile__(
 	"1:	ldarx	%0,0,%3		# pte_update\n\
-	andi.	%1,%0,%6\n\
+	and.	%1,%0,%6\n\
 	bne-	1b \n\
 	andc	%1,%0,%4 \n\
 	or	%1,%1,%7\n\
 	stdcx.	%1,0,%3 \n\
 	bne-	1b"
-	: "=&r" (old), "=&r" (tmp), "=m" (*ptep)
-	: "r" (ptep), "r" (clr), "m" (*ptep), "i" (_PAGE_BUSY), "r" (set)
+	: "=&r" (old_be), "=&r" (tmp_be), "=m" (*ptep)
+	: "r" (ptep), "r" (cpu_to_be64(clr)), "m" (*ptep),
+	  "r" (cpu_to_be64(H_PAGE_BUSY)), "r" (cpu_to_be64(set))
 	: "cc" );
 	/* huge pages use the old page table lock */
 	if (!huge)
 		assert_pte_locked(mm, addr);
 
-	if (old & _PAGE_HASHPTE)
+	old = be64_to_cpu(old_be);
+	if (old & H_PAGE_HASHPTE)
 		hpte_need_flush(mm, addr, ptep, old, huge);
 
 	return old;
 }
 
-static inline int __ptep_test_and_clear_young(struct mm_struct *mm,
-					      unsigned long addr, pte_t *ptep)
-{
-	unsigned long old;
-
-	if ((pte_val(*ptep) & (_PAGE_ACCESSED | _PAGE_HASHPTE)) == 0)
-		return 0;
-	old = pte_update(mm, addr, ptep, _PAGE_ACCESSED, 0, 0);
-	return (old & _PAGE_ACCESSED) != 0;
-}
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
-#define ptep_test_and_clear_young(__vma, __addr, __ptep)		   \
-({									   \
-	int __r;							   \
-	__r = __ptep_test_and_clear_young((__vma)->vm_mm, __addr, __ptep); \
-	__r;								   \
-})
-
-#define __HAVE_ARCH_PTEP_SET_WRPROTECT
-static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
-				      pte_t *ptep)
-{
-
-	if ((pte_val(*ptep) & _PAGE_RW) == 0)
-		return;
-
-	pte_update(mm, addr, ptep, _PAGE_RW, 0, 0);
-}
-
-static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
-					   unsigned long addr, pte_t *ptep)
-{
-	if ((pte_val(*ptep) & _PAGE_RW) == 0)
-		return;
-
-	pte_update(mm, addr, ptep, _PAGE_RW, 0, 1);
-}
-
-/*
- * We currently remove entries from the hashtable regardless of whether
- * the entry was young or dirty. The generic routines only flush if the
- * entry was young or dirty which is not good enough.
- *
- * We should be more intelligent about this but for the moment we override
- * these functions and force a tlb flush unconditionally
- */
-#define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
-#define ptep_clear_flush_young(__vma, __address, __ptep)		\
-({									\
-	int __young = __ptep_test_and_clear_young((__vma)->vm_mm, __address, \
-						  __ptep);		\
-	__young;							\
-})
-
-#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
-static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
-				       unsigned long addr, pte_t *ptep)
-{
-	unsigned long old = pte_update(mm, addr, ptep, ~0UL, 0, 0);
-	return __pte(old);
-}
-
-static inline void pte_clear(struct mm_struct *mm, unsigned long addr,
-			     pte_t * ptep)
-{
-	pte_update(mm, addr, ptep, ~0UL, 0, 0);
-}
-
-
 /* Set the dirty and/or accessed bits atomically in a linux PTE, this
  * function doesn't need to flush the hash entry
  */
-static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry)
+static inline void hash__ptep_set_access_flags(pte_t *ptep, pte_t entry)
 {
-	unsigned long bits = pte_val(entry) &
-		(_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC |
-		 _PAGE_SOFT_DIRTY);
+	__be64 old, tmp, val, mask;
 
-	unsigned long old, tmp;
+	mask = cpu_to_be64(_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_READ | _PAGE_WRITE |
+			   _PAGE_EXEC | _PAGE_SOFT_DIRTY);
+
+	val = pte_raw(entry) & mask;
 
 	__asm__ __volatile__(
 	"1:	ldarx	%0,0,%4\n\
-		andi.	%1,%0,%6\n\
+		and.	%1,%0,%6\n\
 		bne-	1b \n\
 		or	%0,%3,%0\n\
 		stdcx.	%0,0,%4\n\
 		bne-	1b"
 	:"=&r" (old), "=&r" (tmp), "=m" (*ptep)
-	:"r" (bits), "r" (ptep), "m" (*ptep), "i" (_PAGE_BUSY)
+	:"r" (val), "r" (ptep), "m" (*ptep), "r" (cpu_to_be64(H_PAGE_BUSY))
 	:"cc");
 }
 
-static inline int pgd_bad(pgd_t pgd)
-{
-	return (pgd_val(pgd) == 0);
-}
-
-#define __HAVE_ARCH_PTE_SAME
-#define pte_same(A,B)	(((pte_val(A) ^ pte_val(B)) & ~_PAGE_HPTEFLAGS) == 0)
-static inline unsigned long pgd_page_vaddr(pgd_t pgd)
-{
-	return (unsigned long)__va(pgd_val(pgd) & ~PGD_MASKED_BITS);
-}
-
-
-/* Generic accessors to PTE bits */
-static inline int pte_write(pte_t pte)		{ return !!(pte_val(pte) & _PAGE_RW);}
-static inline int pte_dirty(pte_t pte)		{ return !!(pte_val(pte) & _PAGE_DIRTY); }
-static inline int pte_young(pte_t pte)		{ return !!(pte_val(pte) & _PAGE_ACCESSED); }
-static inline int pte_special(pte_t pte)	{ return !!(pte_val(pte) & _PAGE_SPECIAL); }
-static inline int pte_none(pte_t pte)		{ return (pte_val(pte) & ~_PTE_NONE_MASK) == 0; }
-static inline pgprot_t pte_pgprot(pte_t pte)	{ return __pgprot(pte_val(pte) & PAGE_PROT_BITS); }
-
-#ifdef CONFIG_HAVE_ARCH_SOFT_DIRTY
-static inline bool pte_soft_dirty(pte_t pte)
-{
-	return !!(pte_val(pte) & _PAGE_SOFT_DIRTY);
-}
-static inline pte_t pte_mksoft_dirty(pte_t pte)
-{
-	return __pte(pte_val(pte) | _PAGE_SOFT_DIRTY);
-}
-
-static inline pte_t pte_clear_soft_dirty(pte_t pte)
-{
-	return __pte(pte_val(pte) & ~_PAGE_SOFT_DIRTY);
-}
-#endif /* CONFIG_HAVE_ARCH_SOFT_DIRTY */
-
-#ifdef CONFIG_NUMA_BALANCING
-/*
- * These work without NUMA balancing but the kernel does not care. See the
- * comment in include/asm-generic/pgtable.h . On powerpc, this will only
- * work for user pages and always return true for kernel pages.
- */
-static inline int pte_protnone(pte_t pte)
-{
-	return (pte_val(pte) &
-		(_PAGE_PRESENT | _PAGE_USER)) == _PAGE_PRESENT;
-}
-#endif /* CONFIG_NUMA_BALANCING */
-
-static inline int pte_present(pte_t pte)
-{
-	return !!(pte_val(pte) & _PAGE_PRESENT);
-}
-
-/* Conversion functions: convert a page and protection to a page entry,
- * and a page entry and page directory to the page they refer to.
- *
- * Even if PTEs can be unsigned long long, a PFN is always an unsigned
- * long for now.
- */
-static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot)
-{
-	return __pte((((pte_basic_t)(pfn) << PTE_RPN_SHIFT) & PTE_RPN_MASK) |
-		     pgprot_val(pgprot));
-}
-
-static inline unsigned long pte_pfn(pte_t pte)
-{
-	return (pte_val(pte) & PTE_RPN_MASK) >> PTE_RPN_SHIFT;
-}
-
-/* Generic modifiers for PTE bits */
-static inline pte_t pte_wrprotect(pte_t pte)
-{
-	return __pte(pte_val(pte) & ~_PAGE_RW);
-}
-
-static inline pte_t pte_mkclean(pte_t pte)
-{
-	return __pte(pte_val(pte) & ~_PAGE_DIRTY);
-}
-
-static inline pte_t pte_mkold(pte_t pte)
-{
-	return __pte(pte_val(pte) & ~_PAGE_ACCESSED);
-}
-
-static inline pte_t pte_mkwrite(pte_t pte)
-{
-	return __pte(pte_val(pte) | _PAGE_RW);
-}
-
-static inline pte_t pte_mkdirty(pte_t pte)
-{
-	return __pte(pte_val(pte) | _PAGE_DIRTY | _PAGE_SOFT_DIRTY);
-}
-
-static inline pte_t pte_mkyoung(pte_t pte)
-{
-	return __pte(pte_val(pte) | _PAGE_ACCESSED);
-}
-
-static inline pte_t pte_mkspecial(pte_t pte)
-{
-	return __pte(pte_val(pte) | _PAGE_SPECIAL);
-}
-
-static inline pte_t pte_mkhuge(pte_t pte)
+static inline int hash__pte_same(pte_t pte_a, pte_t pte_b)
 {
-	return pte;
+	return (((pte_raw(pte_a) ^ pte_raw(pte_b)) & ~cpu_to_be64(_PAGE_HPTEFLAGS)) == 0);
 }
 
-static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+static inline int hash__pte_none(pte_t pte)
 {
-	return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot));
+	return (pte_val(pte) & ~H_PTE_NONE_MASK) == 0;
 }
 
 /* This low level function performs the actual PTE insertion
@@ -487,8 +171,8 @@ static inline pte_t pte_modify(pte_t pte
  * an horrible mess that I'm not going to try to clean up now but
  * I'm keeping it in one place rather than spread around
  */
-static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
-				pte_t *ptep, pte_t pte, int percpu)
+static inline void hash__set_pte_at(struct mm_struct *mm, unsigned long addr,
+				  pte_t *ptep, pte_t pte, int percpu)
 {
 	/*
 	 * Anything else just stores the PTE normally. That covers all 64-bit
@@ -497,53 +181,6 @@ static inline void __set_pte_at(struct m
 	*ptep = pte;
 }
 
-/*
- * Macro to mark a page protection value as "uncacheable".
- */
-
-#define _PAGE_CACHE_CTL	(_PAGE_COHERENT | _PAGE_GUARDED | _PAGE_NO_CACHE | \
-			 _PAGE_WRITETHRU)
-
-#define pgprot_noncached pgprot_noncached
-static inline pgprot_t pgprot_noncached(pgprot_t prot)
-{
-	return __pgprot((pgprot_val(prot) & ~_PAGE_CACHE_CTL) |
-			_PAGE_NO_CACHE | _PAGE_GUARDED);
-}
-
-#define pgprot_noncached_wc pgprot_noncached_wc
-static inline pgprot_t pgprot_noncached_wc(pgprot_t prot)
-{
-	return __pgprot((pgprot_val(prot) & ~_PAGE_CACHE_CTL) |
-			_PAGE_NO_CACHE);
-}
-
-#define pgprot_cached pgprot_cached
-static inline pgprot_t pgprot_cached(pgprot_t prot)
-{
-	return __pgprot((pgprot_val(prot) & ~_PAGE_CACHE_CTL) |
-			_PAGE_COHERENT);
-}
-
-#define pgprot_cached_wthru pgprot_cached_wthru
-static inline pgprot_t pgprot_cached_wthru(pgprot_t prot)
-{
-	return __pgprot((pgprot_val(prot) & ~_PAGE_CACHE_CTL) |
-			_PAGE_COHERENT | _PAGE_WRITETHRU);
-}
-
-#define pgprot_cached_noncoherent pgprot_cached_noncoherent
-static inline pgprot_t pgprot_cached_noncoherent(pgprot_t prot)
-{
-	return __pgprot(pgprot_val(prot) & ~_PAGE_CACHE_CTL);
-}
-
-#define pgprot_writecombine pgprot_writecombine
-static inline pgprot_t pgprot_writecombine(pgprot_t prot)
-{
-	return pgprot_noncached_wc(prot);
-}
-
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 extern void hpte_do_hugepage_flush(struct mm_struct *mm, unsigned long addr,
 				   pmd_t *pmdp, unsigned long old_pmd);
@@ -556,6 +193,14 @@ static inline void hpte_do_hugepage_flus
 }
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
 
+
+extern int hash__map_kernel_page(unsigned long ea, unsigned long pa,
+			     unsigned long flags);
+extern int __meminit hash__vmemmap_create_mapping(unsigned long start,
+					      unsigned long page_size,
+					      unsigned long phys);
+extern void hash__vmemmap_remove_mapping(unsigned long start,
+				     unsigned long page_size);
 #endif /* !__ASSEMBLY__ */
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_BOOK3S_64_HASH_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/64/hugetlb-radix.h linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/64/hugetlb-radix.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/64/hugetlb-radix.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/64/hugetlb-radix.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,14 @@
+#ifndef _ASM_POWERPC_BOOK3S_64_HUGETLB_RADIX_H
+#define _ASM_POWERPC_BOOK3S_64_HUGETLB_RADIX_H
+/*
+ * For radix we want generic code to handle hugetlb. But then if we want
+ * both hash and radix to be enabled together we need to workaround the
+ * limitations.
+ */
+void radix__flush_hugetlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
+void radix__local_flush_hugetlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
+extern unsigned long
+radix__hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
+				unsigned long len, unsigned long pgoff,
+				unsigned long flags);
+#endif
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/64/mmu.h linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/64/mmu.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/64/mmu.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/64/mmu.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,137 @@
+#ifndef _ASM_POWERPC_BOOK3S_64_MMU_H_
+#define _ASM_POWERPC_BOOK3S_64_MMU_H_
+
+#ifndef __ASSEMBLY__
+/*
+ * Page size definition
+ *
+ *    shift : is the "PAGE_SHIFT" value for that page size
+ *    sllp  : is a bit mask with the value of SLB L || LP to be or'ed
+ *            directly to a slbmte "vsid" value
+ *    penc  : is the HPTE encoding mask for the "LP" field:
+ *
+ */
+struct mmu_psize_def {
+	unsigned int	shift;	/* number of bits */
+	int		penc[MMU_PAGE_COUNT];	/* HPTE encoding */
+	unsigned int	tlbiel;	/* tlbiel supported for that page size */
+	unsigned long	avpnm;	/* bits to mask out in AVPN in the HPTE */
+	union {
+		unsigned long	sllp;	/* SLB L||LP (exact mask to use in slbmte) */
+		unsigned long ap;	/* Ap encoding used by PowerISA 3.0 */
+	};
+};
+extern struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];
+
+#define radix_enabled() mmu_has_feature(MMU_FTR_RADIX)
+
+#endif /* __ASSEMBLY__ */
+
+/* 64-bit classic hash table MMU */
+#include <asm/book3s/64/mmu-hash.h>
+
+#ifndef __ASSEMBLY__
+/*
+ * ISA 3.0 partiton and process table entry format
+ */
+struct prtb_entry {
+	__be64 prtb0;
+	__be64 prtb1;
+};
+extern struct prtb_entry *process_tb;
+
+struct patb_entry {
+	__be64 patb0;
+	__be64 patb1;
+};
+extern struct patb_entry *partition_tb;
+
+#define PATB_HR		(1UL << 63)
+#define PATB_GR		(1UL << 63)
+#define RPDB_MASK	0x0ffffffffffff00fUL
+#define RPDB_SHIFT	(1UL << 8)
+/*
+ * Limit process table to PAGE_SIZE table. This
+ * also limit the max pid we can support.
+ * MAX_USER_CONTEXT * 16 bytes of space.
+ */
+#define PRTB_SIZE_SHIFT	(CONTEXT_BITS + 4)
+/*
+ * Power9 currently only support 64K partition table size.
+ */
+#define PATB_SIZE_SHIFT	16
+
+typedef unsigned long mm_context_id_t;
+struct spinlock;
+
+typedef struct {
+	mm_context_id_t id;
+	u16 user_psize;		/* page size index */
+
+#ifdef CONFIG_PPC_MM_SLICES
+	u64 low_slices_psize;	/* SLB page size encodings */
+	unsigned char high_slices_psize[SLICE_ARRAY_SIZE];
+#else
+	u16 sllp;		/* SLB page size encoding */
+#endif
+	unsigned long vdso_base;
+#ifdef CONFIG_PPC_SUBPAGE_PROT
+	struct subpage_prot_table spt;
+#endif /* CONFIG_PPC_SUBPAGE_PROT */
+#ifdef CONFIG_PPC_ICSWX
+	struct spinlock *cop_lockp; /* guard acop and cop_pid */
+	unsigned long acop;	/* mask of enabled coprocessor types */
+	unsigned int cop_pid;	/* pid value used with coprocessors */
+#endif /* CONFIG_PPC_ICSWX */
+#ifdef CONFIG_PPC_64K_PAGES
+	/* for 4K PTE fragment support */
+	void *pte_frag;
+#endif
+#ifdef CONFIG_SPAPR_TCE_IOMMU
+	struct list_head iommu_group_mem_list;
+#endif
+} mm_context_t;
+
+/*
+ * The current system page and segment sizes
+ */
+extern int mmu_linear_psize;
+extern int mmu_virtual_psize;
+extern int mmu_vmalloc_psize;
+extern int mmu_vmemmap_psize;
+extern int mmu_io_psize;
+
+/* MMU initialization */
+extern void radix_init_native(void);
+extern void hash__early_init_mmu(void);
+extern void radix__early_init_mmu(void);
+static inline void early_init_mmu(void)
+{
+	if (radix_enabled())
+		return radix__early_init_mmu();
+	return hash__early_init_mmu();
+}
+extern void hash__early_init_mmu_secondary(void);
+extern void radix__early_init_mmu_secondary(void);
+static inline void early_init_mmu_secondary(void)
+{
+	if (radix_enabled())
+		return radix__early_init_mmu_secondary();
+	return hash__early_init_mmu_secondary();
+}
+
+extern void hash__setup_initial_memory_limit(phys_addr_t first_memblock_base,
+					 phys_addr_t first_memblock_size);
+extern void radix__setup_initial_memory_limit(phys_addr_t first_memblock_base,
+					 phys_addr_t first_memblock_size);
+static inline void setup_initial_memory_limit(phys_addr_t first_memblock_base,
+					      phys_addr_t first_memblock_size)
+{
+	if (radix_enabled())
+		return radix__setup_initial_memory_limit(first_memblock_base,
+						   first_memblock_size);
+	return hash__setup_initial_memory_limit(first_memblock_base,
+					   first_memblock_size);
+}
+#endif /* __ASSEMBLY__ */
+#endif /* _ASM_POWERPC_BOOK3S_64_MMU_H_ */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/64/mmu-hash.h linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/64/mmu-hash.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/64/mmu-hash.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/64/mmu-hash.h	2016-07-24 15:23:50.000000000 -0400
@@ -1,5 +1,5 @@
-#ifndef _ASM_POWERPC_MMU_HASH64_H_
-#define _ASM_POWERPC_MMU_HASH64_H_
+#ifndef _ASM_POWERPC_BOOK3S_64_MMU_HASH_H_
+#define _ASM_POWERPC_BOOK3S_64_MMU_HASH_H_
 /*
  * PowerPC64 memory management structures
  *
@@ -78,12 +78,17 @@
 #define HPTE_V_SECONDARY	ASM_CONST(0x0000000000000002)
 #define HPTE_V_VALID		ASM_CONST(0x0000000000000001)
 
+/*
+ * ISA 3.0 have a different HPTE format.
+ */
+#define HPTE_R_3_0_SSIZE_SHIFT	58
 #define HPTE_R_PP0		ASM_CONST(0x8000000000000000)
 #define HPTE_R_TS		ASM_CONST(0x4000000000000000)
 #define HPTE_R_KEY_HI		ASM_CONST(0x3000000000000000)
 #define HPTE_R_RPN_SHIFT	12
 #define HPTE_R_RPN		ASM_CONST(0x0ffffffffffff000)
 #define HPTE_R_PP		ASM_CONST(0x0000000000000003)
+#define HPTE_R_PPP		ASM_CONST(0x8000000000000003)
 #define HPTE_R_N		ASM_CONST(0x0000000000000004)
 #define HPTE_R_G		ASM_CONST(0x0000000000000008)
 #define HPTE_R_M		ASM_CONST(0x0000000000000010)
@@ -115,6 +120,7 @@
 #define POWER7_TLB_SETS		128	/* # sets in POWER7 TLB */
 #define POWER8_TLB_SETS		512	/* # sets in POWER8 TLB */
 #define POWER9_TLB_SETS_HASH	256	/* # sets in POWER9 TLB Hash mode */
+#define POWER9_TLB_SETS_RADIX	128	/* # sets in POWER9 TLB Radix mode */
 
 #ifndef __ASSEMBLY__
 
@@ -127,24 +133,6 @@ extern struct hash_pte *htab_address;
 extern unsigned long htab_size_bytes;
 extern unsigned long htab_hash_mask;
 
-/*
- * Page size definition
- *
- *    shift : is the "PAGE_SHIFT" value for that page size
- *    sllp  : is a bit mask with the value of SLB L || LP to be or'ed
- *            directly to a slbmte "vsid" value
- *    penc  : is the HPTE encoding mask for the "LP" field:
- *
- */
-struct mmu_psize_def
-{
-	unsigned int	shift;	/* number of bits */
-	int		penc[MMU_PAGE_COUNT];	/* HPTE encoding */
-	unsigned int	tlbiel;	/* tlbiel supported for that page size */
-	unsigned long	avpnm;	/* bits to mask out in AVPN in the HPTE */
-	unsigned long	sllp;	/* SLB L||LP (exact mask to use in slbmte) */
-};
-extern struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];
 
 static inline int shift_to_mmu_psize(unsigned int shift)
 {
@@ -210,11 +198,6 @@ static inline int segment_shift(int ssiz
 /*
  * The current system page and segment sizes
  */
-extern int mmu_linear_psize;
-extern int mmu_virtual_psize;
-extern int mmu_vmalloc_psize;
-extern int mmu_vmemmap_psize;
-extern int mmu_io_psize;
 extern int mmu_kernel_ssize;
 extern int mmu_highuser_ssize;
 extern u16 mmu_slb_size;
@@ -247,7 +230,8 @@ static inline unsigned long hpte_encode_
 	 */
 	v = (vpn >> (23 - VPN_SHIFT)) & ~(mmu_psize_defs[psize].avpnm);
 	v <<= HPTE_V_AVPN_SHIFT;
-	v |= ((unsigned long) ssize) << HPTE_V_SSIZE_SHIFT;
+	if (!cpu_has_feature(CPU_FTR_ARCH_300))
+		v |= ((unsigned long) ssize) << HPTE_V_SSIZE_SHIFT;
 	return v;
 }
 
@@ -271,8 +255,12 @@ static inline unsigned long hpte_encode_
  * aligned for the requested page size
  */
 static inline unsigned long hpte_encode_r(unsigned long pa, int base_psize,
-					  int actual_psize)
+					  int actual_psize, int ssize)
 {
+
+	if (cpu_has_feature(CPU_FTR_ARCH_300))
+		pa |= ((unsigned long) ssize) << HPTE_R_3_0_SSIZE_SHIFT;
+
 	/* A 4K page needs no special encoding */
 	if (actual_psize == MMU_PAGE_4K)
 		return pa & HPTE_R_RPN;
@@ -476,7 +464,7 @@ extern void slb_set_size(u16 size);
 	add	rt,rt,rx
 
 /* 4 bits per slice and we have one slice per 1TB */
-#define SLICE_ARRAY_SIZE  (PGTABLE_RANGE >> 41)
+#define SLICE_ARRAY_SIZE  (H_PGTABLE_RANGE >> 41)
 
 #ifndef __ASSEMBLY__
 
@@ -512,38 +500,6 @@ static inline void subpage_prot_free(str
 static inline void subpage_prot_init_new_context(struct mm_struct *mm) { }
 #endif /* CONFIG_PPC_SUBPAGE_PROT */
 
-typedef unsigned long mm_context_id_t;
-struct spinlock;
-
-typedef struct {
-	mm_context_id_t id;
-	u16 user_psize;		/* page size index */
-
-#ifdef CONFIG_PPC_MM_SLICES
-	u64 low_slices_psize;	/* SLB page size encodings */
-	unsigned char high_slices_psize[SLICE_ARRAY_SIZE];
-#else
-	u16 sllp;		/* SLB page size encoding */
-#endif
-	unsigned long vdso_base;
-#ifdef CONFIG_PPC_SUBPAGE_PROT
-	struct subpage_prot_table spt;
-#endif /* CONFIG_PPC_SUBPAGE_PROT */
-#ifdef CONFIG_PPC_ICSWX
-	struct spinlock *cop_lockp; /* guard acop and cop_pid */
-	unsigned long acop;	/* mask of enabled coprocessor types */
-	unsigned int cop_pid;	/* pid value used with coprocessors */
-#endif /* CONFIG_PPC_ICSWX */
-#ifdef CONFIG_PPC_64K_PAGES
-	/* for 4K PTE fragment support */
-	void *pte_frag;
-#endif
-#ifdef CONFIG_SPAPR_TCE_IOMMU
-	struct list_head iommu_group_mem_list;
-#endif
-} mm_context_t;
-
-
 #if 0
 /*
  * The code below is equivalent to this function for arguments
@@ -579,7 +535,7 @@ static inline unsigned long get_vsid(uns
 	/*
 	 * Bad address. We return VSID 0 for that
 	 */
-	if ((ea & ~REGION_MASK) >= PGTABLE_RANGE)
+	if ((ea & ~REGION_MASK) >= H_PGTABLE_RANGE)
 		return 0;
 
 	if (ssize == MMU_SEGSIZE_256M)
@@ -613,4 +569,4 @@ unsigned htab_shift_for_mem_size(unsigne
 
 #endif /* __ASSEMBLY__ */
 
-#endif /* _ASM_POWERPC_MMU_HASH64_H_ */
+#endif /* _ASM_POWERPC_BOOK3S_64_MMU_HASH_H_ */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/64/pgalloc.h linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/64/pgalloc.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/64/pgalloc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/64/pgalloc.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,219 @@
+#ifndef _ASM_POWERPC_BOOK3S_64_PGALLOC_H
+#define _ASM_POWERPC_BOOK3S_64_PGALLOC_H
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/slab.h>
+#include <linux/cpumask.h>
+#include <linux/percpu.h>
+
+struct vmemmap_backing {
+	struct vmemmap_backing *list;
+	unsigned long phys;
+	unsigned long virt_addr;
+};
+extern struct vmemmap_backing *vmemmap_list;
+
+/*
+ * Functions that deal with pagetables that could be at any level of
+ * the table need to be passed an "index_size" so they know how to
+ * handle allocation.  For PTE pages (which are linked to a struct
+ * page for now, and drawn from the main get_free_pages() pool), the
+ * allocation size will be (2^index_size * sizeof(pointer)) and
+ * allocations are drawn from the kmem_cache in PGT_CACHE(index_size).
+ *
+ * The maximum index size needs to be big enough to allow any
+ * pagetable sizes we need, but small enough to fit in the low bits of
+ * any page table pointer.  In other words all pagetables, even tiny
+ * ones, must be aligned to allow at least enough low 0 bits to
+ * contain this value.  This value is also used as a mask, so it must
+ * be one less than a power of two.
+ */
+#define MAX_PGTABLE_INDEX_SIZE	0xf
+
+extern struct kmem_cache *pgtable_cache[];
+#define PGT_CACHE(shift) ({				\
+			BUG_ON(!(shift));		\
+			pgtable_cache[(shift) - 1];	\
+		})
+
+#define PGALLOC_GFP GFP_KERNEL | __GFP_NOTRACK | __GFP_ZERO
+
+extern pte_t *pte_fragment_alloc(struct mm_struct *, unsigned long, int);
+extern void pte_fragment_free(unsigned long *, int);
+extern void pgtable_free_tlb(struct mmu_gather *tlb, void *table, int shift);
+#ifdef CONFIG_SMP
+extern void __tlb_remove_table(void *_table);
+#endif
+
+static inline pgd_t *radix__pgd_alloc(struct mm_struct *mm)
+{
+#ifdef CONFIG_PPC_64K_PAGES
+	return (pgd_t *)__get_free_page(PGALLOC_GFP);
+#else
+	struct page *page;
+	page = alloc_pages(PGALLOC_GFP | __GFP_REPEAT, 4);
+	if (!page)
+		return NULL;
+	return (pgd_t *) page_address(page);
+#endif
+}
+
+static inline void radix__pgd_free(struct mm_struct *mm, pgd_t *pgd)
+{
+#ifdef CONFIG_PPC_64K_PAGES
+	free_page((unsigned long)pgd);
+#else
+	free_pages((unsigned long)pgd, 4);
+#endif
+}
+
+static inline pgd_t *pgd_alloc(struct mm_struct *mm)
+{
+	if (radix_enabled())
+		return radix__pgd_alloc(mm);
+	return kmem_cache_alloc(PGT_CACHE(PGD_INDEX_SIZE), GFP_KERNEL);
+}
+
+static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+{
+	if (radix_enabled())
+		return radix__pgd_free(mm, pgd);
+	kmem_cache_free(PGT_CACHE(PGD_INDEX_SIZE), pgd);
+}
+
+static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud)
+{
+	pgd_set(pgd, __pgtable_ptr_val(pud) | PGD_VAL_BITS);
+}
+
+static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
+{
+	return kmem_cache_alloc(PGT_CACHE(PUD_INDEX_SIZE), GFP_KERNEL);
+}
+
+static inline void pud_free(struct mm_struct *mm, pud_t *pud)
+{
+	kmem_cache_free(PGT_CACHE(PUD_INDEX_SIZE), pud);
+}
+
+static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
+{
+	pud_set(pud, __pgtable_ptr_val(pmd) | PUD_VAL_BITS);
+}
+
+static inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
+                                  unsigned long address)
+{
+	/*
+	 * By now all the pud entries should be none entries. So go
+	 * ahead and flush the page walk cache
+	 */
+	flush_tlb_pgtable(tlb, address);
+        pgtable_free_tlb(tlb, pud, PUD_INDEX_SIZE);
+}
+
+static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
+{
+	return kmem_cache_alloc(PGT_CACHE(PMD_CACHE_INDEX), GFP_KERNEL);
+}
+
+static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
+{
+	kmem_cache_free(PGT_CACHE(PMD_CACHE_INDEX), pmd);
+}
+
+static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd,
+                                  unsigned long address)
+{
+	/*
+	 * By now all the pud entries should be none entries. So go
+	 * ahead and flush the page walk cache
+	 */
+	flush_tlb_pgtable(tlb, address);
+        return pgtable_free_tlb(tlb, pmd, PMD_CACHE_INDEX);
+}
+
+static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
+				       pte_t *pte)
+{
+	pmd_set(pmd, __pgtable_ptr_val(pte) | PMD_VAL_BITS);
+}
+
+static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
+				pgtable_t pte_page)
+{
+	pmd_set(pmd, __pgtable_ptr_val(pte_page) | PMD_VAL_BITS);
+}
+
+static inline pgtable_t pmd_pgtable(pmd_t pmd)
+{
+	return (pgtable_t)pmd_page_vaddr(pmd);
+}
+
+#ifdef CONFIG_PPC_4K_PAGES
+static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
+					  unsigned long address)
+{
+	return (pte_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
+}
+
+static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
+				      unsigned long address)
+{
+	struct page *page;
+	pte_t *pte;
+
+	pte = pte_alloc_one_kernel(mm, address);
+	if (!pte)
+		return NULL;
+	page = virt_to_page(pte);
+	if (!pgtable_page_ctor(page)) {
+		__free_page(page);
+		return NULL;
+	}
+	return pte;
+}
+#else /* if CONFIG_PPC_64K_PAGES */
+
+static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
+					  unsigned long address)
+{
+	return (pte_t *)pte_fragment_alloc(mm, address, 1);
+}
+
+static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
+				      unsigned long address)
+{
+	return (pgtable_t)pte_fragment_alloc(mm, address, 0);
+}
+#endif
+
+static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+{
+	pte_fragment_free((unsigned long *)pte, 1);
+}
+
+static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage)
+{
+	pte_fragment_free((unsigned long *)ptepage, 0);
+}
+
+static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table,
+				  unsigned long address)
+{
+	/*
+	 * By now all the pud entries should be none entries. So go
+	 * ahead and flush the page walk cache
+	 */
+	flush_tlb_pgtable(tlb, address);
+	pgtable_free_tlb(tlb, table, 0);
+}
+
+#define check_pgt_cache()	do { } while (0)
+
+#endif /* _ASM_POWERPC_BOOK3S_64_PGALLOC_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/64/pgtable-4k.h linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/64/pgtable-4k.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/64/pgtable-4k.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/64/pgtable-4k.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,53 @@
+#ifndef _ASM_POWERPC_BOOK3S_64_PGTABLE_4K_H
+#define _ASM_POWERPC_BOOK3S_64_PGTABLE_4K_H
+/*
+ * hash 4k can't share hugetlb and also doesn't support THP
+ */
+#ifndef __ASSEMBLY__
+#ifdef CONFIG_HUGETLB_PAGE
+static inline int pmd_huge(pmd_t pmd)
+{
+	/*
+	 * leaf pte for huge page
+	 */
+	if (radix_enabled())
+		return !!(pmd_val(pmd) & _PAGE_PTE);
+	return 0;
+}
+
+static inline int pud_huge(pud_t pud)
+{
+	/*
+	 * leaf pte for huge page
+	 */
+	if (radix_enabled())
+		return !!(pud_val(pud) & _PAGE_PTE);
+	return 0;
+}
+
+static inline int pgd_huge(pgd_t pgd)
+{
+	/*
+	 * leaf pte for huge page
+	 */
+	if (radix_enabled())
+		return !!(pgd_val(pgd) & _PAGE_PTE);
+	return 0;
+}
+#define pgd_huge pgd_huge
+/*
+ * With radix , we have hugepage ptes in the pud and pmd entries. We don't
+ * need to setup hugepage directory for them. Our pte and page directory format
+ * enable us to have this enabled.
+ */
+static inline int hugepd_ok(hugepd_t hpd)
+{
+	if (radix_enabled())
+		return 0;
+	return hash__hugepd_ok(hpd);
+}
+#define is_hugepd(hpd)		(hugepd_ok(hpd))
+#endif /* CONFIG_HUGETLB_PAGE */
+#endif /* __ASSEMBLY__ */
+
+#endif /*_ASM_POWERPC_BOOK3S_64_PGTABLE_4K_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/64/pgtable-64k.h linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/64/pgtable-64k.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/64/pgtable-64k.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/64/pgtable-64k.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,64 @@
+#ifndef _ASM_POWERPC_BOOK3S_64_PGTABLE_64K_H
+#define _ASM_POWERPC_BOOK3S_64_PGTABLE_64K_H
+
+#ifndef __ASSEMBLY__
+#ifdef CONFIG_HUGETLB_PAGE
+/*
+ * We have PGD_INDEX_SIZ = 12 and PTE_INDEX_SIZE = 8, so that we can have
+ * 16GB hugepage pte in PGD and 16MB hugepage pte at PMD;
+ *
+ * Defined in such a way that we can optimize away code block at build time
+ * if CONFIG_HUGETLB_PAGE=n.
+ */
+static inline int pmd_huge(pmd_t pmd)
+{
+	/*
+	 * leaf pte for huge page
+	 */
+	return !!(pmd_val(pmd) & _PAGE_PTE);
+}
+
+static inline int pud_huge(pud_t pud)
+{
+	/*
+	 * leaf pte for huge page
+	 */
+	return !!(pud_val(pud) & _PAGE_PTE);
+}
+
+static inline int pgd_huge(pgd_t pgd)
+{
+	/*
+	 * leaf pte for huge page
+	 */
+	return !!(pgd_val(pgd) & _PAGE_PTE);
+}
+#define pgd_huge pgd_huge
+
+#ifdef CONFIG_DEBUG_VM
+extern int hugepd_ok(hugepd_t hpd);
+#define is_hugepd(hpd)               (hugepd_ok(hpd))
+#else
+/*
+ * With 64k page size, we have hugepage ptes in the pgd and pmd entries. We don't
+ * need to setup hugepage directory for them. Our pte and page directory format
+ * enable us to have this enabled.
+ */
+static inline int hugepd_ok(hugepd_t hpd)
+{
+	return 0;
+}
+#define is_hugepd(pdep)			0
+#endif /* CONFIG_DEBUG_VM */
+
+#endif /* CONFIG_HUGETLB_PAGE */
+
+static inline int remap_4k_pfn(struct vm_area_struct *vma, unsigned long addr,
+			       unsigned long pfn, pgprot_t prot)
+{
+	if (radix_enabled())
+		BUG();
+	return hash__remap_4k_pfn(vma, addr, pfn, prot);
+}
+#endif	/* __ASSEMBLY__ */
+#endif /*_ASM_POWERPC_BOOK3S_64_PGTABLE_64K_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/64/pgtable.h linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/64/pgtable.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/64/pgtable.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/64/pgtable.h	2016-07-24 15:23:50.000000000 -0400
@@ -1,13 +1,248 @@
 #ifndef _ASM_POWERPC_BOOK3S_64_PGTABLE_H_
 #define _ASM_POWERPC_BOOK3S_64_PGTABLE_H_
+
 /*
- * This file contains the functions and defines necessary to modify and use
- * the ppc64 hashed page table.
+ * Common bits between hash and Radix page table
+ */
+#define _PAGE_BIT_SWAP_TYPE	0
+
+#define _PAGE_EXEC		0x00001 /* execute permission */
+#define _PAGE_WRITE		0x00002 /* write access allowed */
+#define _PAGE_READ		0x00004	/* read access allowed */
+#define _PAGE_RW		(_PAGE_READ | _PAGE_WRITE)
+#define _PAGE_RWX		(_PAGE_READ | _PAGE_WRITE | _PAGE_EXEC)
+#define _PAGE_PRIVILEGED	0x00008 /* kernel access only */
+#define _PAGE_SAO		0x00010 /* Strong access order */
+#define _PAGE_NON_IDEMPOTENT	0x00020 /* non idempotent memory */
+#define _PAGE_TOLERANT		0x00030 /* tolerant memory, cache inhibited */
+#define _PAGE_DIRTY		0x00080 /* C: page changed */
+#define _PAGE_ACCESSED		0x00100 /* R: page referenced */
+/*
+ * Software bits
+ */
+#define _RPAGE_SW0		0x2000000000000000UL
+#define _RPAGE_SW1		0x00800
+#define _RPAGE_SW2		0x00400
+#define _RPAGE_SW3		0x00200
+#ifdef CONFIG_MEM_SOFT_DIRTY
+#define _PAGE_SOFT_DIRTY	_RPAGE_SW3 /* software: software dirty tracking */
+#else
+#define _PAGE_SOFT_DIRTY	0x00000
+#endif
+#define _PAGE_SPECIAL		_RPAGE_SW2 /* software: special page */
+
+
+#define _PAGE_PTE		(1ul << 62)	/* distinguishes PTEs from pointers */
+#define _PAGE_PRESENT		(1ul << 63)	/* pte contains a translation */
+/*
+ * Drivers request for cache inhibited pte mapping using _PAGE_NO_CACHE
+ * Instead of fixing all of them, add an alternate define which
+ * maps CI pte mapping.
  */
+#define _PAGE_NO_CACHE		_PAGE_TOLERANT
+/*
+ * We support 57 bit real address in pte. Clear everything above 57, and
+ * every thing below PAGE_SHIFT;
+ */
+#define PTE_RPN_MASK	(((1UL << 57) - 1) & (PAGE_MASK))
+/*
+ * set of bits not changed in pmd_modify. Even though we have hash specific bits
+ * in here, on radix we expect them to be zero.
+ */
+#define _HPAGE_CHG_MASK (PTE_RPN_MASK | _PAGE_HPTEFLAGS | _PAGE_DIRTY | \
+			 _PAGE_ACCESSED | H_PAGE_THP_HUGE | _PAGE_PTE | \
+			 _PAGE_SOFT_DIRTY)
+/*
+ * user access blocked by key
+ */
+#define _PAGE_KERNEL_RW		(_PAGE_PRIVILEGED | _PAGE_RW | _PAGE_DIRTY)
+#define _PAGE_KERNEL_RO		 (_PAGE_PRIVILEGED | _PAGE_READ)
+#define _PAGE_KERNEL_RWX	(_PAGE_PRIVILEGED | _PAGE_DIRTY |	\
+				 _PAGE_RW | _PAGE_EXEC)
+/*
+ * No page size encoding in the linux PTE
+ */
+#define _PAGE_PSIZE		0
+/*
+ * _PAGE_CHG_MASK masks of bits that are to be preserved across
+ * pgprot changes
+ */
+#define _PAGE_CHG_MASK	(PTE_RPN_MASK | _PAGE_HPTEFLAGS | _PAGE_DIRTY | \
+			 _PAGE_ACCESSED | _PAGE_SPECIAL | _PAGE_PTE |	\
+			 _PAGE_SOFT_DIRTY)
+/*
+ * Mask of bits returned by pte_pgprot()
+ */
+#define PAGE_PROT_BITS  (_PAGE_SAO | _PAGE_NON_IDEMPOTENT | _PAGE_TOLERANT | \
+			 H_PAGE_4K_PFN | _PAGE_PRIVILEGED | _PAGE_ACCESSED | \
+			 _PAGE_READ | _PAGE_WRITE |  _PAGE_DIRTY | _PAGE_EXEC | \
+			 _PAGE_SOFT_DIRTY)
+/*
+ * We define 2 sets of base prot bits, one for basic pages (ie,
+ * cacheable kernel and user pages) and one for non cacheable
+ * pages. We always set _PAGE_COHERENT when SMP is enabled or
+ * the processor might need it for DMA coherency.
+ */
+#define _PAGE_BASE_NC	(_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_PSIZE)
+#define _PAGE_BASE	(_PAGE_BASE_NC)
+
+/* Permission masks used to generate the __P and __S table,
+ *
+ * Note:__pgprot is defined in arch/powerpc/include/asm/page.h
+ *
+ * Write permissions imply read permissions for now (we could make write-only
+ * pages on BookE but we don't bother for now). Execute permission control is
+ * possible on platforms that define _PAGE_EXEC
+ *
+ * Note due to the way vm flags are laid out, the bits are XWR
+ */
+#define PAGE_NONE	__pgprot(_PAGE_BASE | _PAGE_PRIVILEGED)
+#define PAGE_SHARED	__pgprot(_PAGE_BASE | _PAGE_RW)
+#define PAGE_SHARED_X	__pgprot(_PAGE_BASE | _PAGE_RW | _PAGE_EXEC)
+#define PAGE_COPY	__pgprot(_PAGE_BASE | _PAGE_READ)
+#define PAGE_COPY_X	__pgprot(_PAGE_BASE | _PAGE_READ | _PAGE_EXEC)
+#define PAGE_READONLY	__pgprot(_PAGE_BASE | _PAGE_READ)
+#define PAGE_READONLY_X	__pgprot(_PAGE_BASE | _PAGE_READ | _PAGE_EXEC)
+
+#define __P000	PAGE_NONE
+#define __P001	PAGE_READONLY
+#define __P010	PAGE_COPY
+#define __P011	PAGE_COPY
+#define __P100	PAGE_READONLY_X
+#define __P101	PAGE_READONLY_X
+#define __P110	PAGE_COPY_X
+#define __P111	PAGE_COPY_X
+
+#define __S000	PAGE_NONE
+#define __S001	PAGE_READONLY
+#define __S010	PAGE_SHARED
+#define __S011	PAGE_SHARED
+#define __S100	PAGE_READONLY_X
+#define __S101	PAGE_READONLY_X
+#define __S110	PAGE_SHARED_X
+#define __S111	PAGE_SHARED_X
+
+/* Permission masks used for kernel mappings */
+#define PAGE_KERNEL	__pgprot(_PAGE_BASE | _PAGE_KERNEL_RW)
+#define PAGE_KERNEL_NC	__pgprot(_PAGE_BASE_NC | _PAGE_KERNEL_RW | \
+				 _PAGE_TOLERANT)
+#define PAGE_KERNEL_NCG	__pgprot(_PAGE_BASE_NC | _PAGE_KERNEL_RW | \
+				 _PAGE_NON_IDEMPOTENT)
+#define PAGE_KERNEL_X	__pgprot(_PAGE_BASE | _PAGE_KERNEL_RWX)
+#define PAGE_KERNEL_RO	__pgprot(_PAGE_BASE | _PAGE_KERNEL_RO)
+#define PAGE_KERNEL_ROX	__pgprot(_PAGE_BASE | _PAGE_KERNEL_ROX)
+
+/*
+ * Protection used for kernel text. We want the debuggers to be able to
+ * set breakpoints anywhere, so don't write protect the kernel text
+ * on platforms where such control is possible.
+ */
+#if defined(CONFIG_KGDB) || defined(CONFIG_XMON) || defined(CONFIG_BDI_SWITCH) || \
+	defined(CONFIG_KPROBES) || defined(CONFIG_DYNAMIC_FTRACE)
+#define PAGE_KERNEL_TEXT	PAGE_KERNEL_X
+#else
+#define PAGE_KERNEL_TEXT	PAGE_KERNEL_ROX
+#endif
+
+/* Make modules code happy. We don't set RO yet */
+#define PAGE_KERNEL_EXEC	PAGE_KERNEL_X
+#define PAGE_AGP		(PAGE_KERNEL_NC)
+
+#ifndef __ASSEMBLY__
+/*
+ * page table defines
+ */
+extern unsigned long __pte_index_size;
+extern unsigned long __pmd_index_size;
+extern unsigned long __pud_index_size;
+extern unsigned long __pgd_index_size;
+extern unsigned long __pmd_cache_index;
+#define PTE_INDEX_SIZE  __pte_index_size
+#define PMD_INDEX_SIZE  __pmd_index_size
+#define PUD_INDEX_SIZE  __pud_index_size
+#define PGD_INDEX_SIZE  __pgd_index_size
+#define PMD_CACHE_INDEX __pmd_cache_index
+/*
+ * Because of use of pte fragments and THP, size of page table
+ * are not always derived out of index size above.
+ */
+extern unsigned long __pte_table_size;
+extern unsigned long __pmd_table_size;
+extern unsigned long __pud_table_size;
+extern unsigned long __pgd_table_size;
+#define PTE_TABLE_SIZE	__pte_table_size
+#define PMD_TABLE_SIZE	__pmd_table_size
+#define PUD_TABLE_SIZE	__pud_table_size
+#define PGD_TABLE_SIZE	__pgd_table_size
+
+extern unsigned long __pmd_val_bits;
+extern unsigned long __pud_val_bits;
+extern unsigned long __pgd_val_bits;
+#define PMD_VAL_BITS	__pmd_val_bits
+#define PUD_VAL_BITS	__pud_val_bits
+#define PGD_VAL_BITS	__pgd_val_bits
+
+extern unsigned long __pte_frag_nr;
+#define PTE_FRAG_NR __pte_frag_nr
+extern unsigned long __pte_frag_size_shift;
+#define PTE_FRAG_SIZE_SHIFT __pte_frag_size_shift
+#define PTE_FRAG_SIZE (1UL << PTE_FRAG_SIZE_SHIFT)
+/*
+ * Pgtable size used by swapper, init in asm code
+ */
+#define MAX_PGD_TABLE_SIZE (sizeof(pgd_t) << RADIX_PGD_INDEX_SIZE)
+
+#define PTRS_PER_PTE	(1 << PTE_INDEX_SIZE)
+#define PTRS_PER_PMD	(1 << PMD_INDEX_SIZE)
+#define PTRS_PER_PUD	(1 << PUD_INDEX_SIZE)
+#define PTRS_PER_PGD	(1 << PGD_INDEX_SIZE)
+
+/* PMD_SHIFT determines what a second-level page table entry can map */
+#define PMD_SHIFT	(PAGE_SHIFT + PTE_INDEX_SIZE)
+#define PMD_SIZE	(1UL << PMD_SHIFT)
+#define PMD_MASK	(~(PMD_SIZE-1))
+
+/* PUD_SHIFT determines what a third-level page table entry can map */
+#define PUD_SHIFT	(PMD_SHIFT + PMD_INDEX_SIZE)
+#define PUD_SIZE	(1UL << PUD_SHIFT)
+#define PUD_MASK	(~(PUD_SIZE-1))
+
+/* PGDIR_SHIFT determines what a fourth-level page table entry can map */
+#define PGDIR_SHIFT	(PUD_SHIFT + PUD_INDEX_SIZE)
+#define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
+#define PGDIR_MASK	(~(PGDIR_SIZE-1))
+
+/* Bits to mask out from a PMD to get to the PTE page */
+#define PMD_MASKED_BITS		0xc0000000000000ffUL
+/* Bits to mask out from a PUD to get to the PMD page */
+#define PUD_MASKED_BITS		0xc0000000000000ffUL
+/* Bits to mask out from a PGD to get to the PUD page */
+#define PGD_MASKED_BITS		0xc0000000000000ffUL
+
+extern unsigned long __vmalloc_start;
+extern unsigned long __vmalloc_end;
+#define VMALLOC_START	__vmalloc_start
+#define VMALLOC_END	__vmalloc_end
+
+extern unsigned long __kernel_virt_start;
+extern unsigned long __kernel_virt_size;
+#define KERN_VIRT_START __kernel_virt_start
+#define KERN_VIRT_SIZE  __kernel_virt_size
+extern struct page *vmemmap;
+extern unsigned long ioremap_bot;
+extern unsigned long pci_io_base;
+#endif /* __ASSEMBLY__ */
 
 #include <asm/book3s/64/hash.h>
-#include <asm/barrier.h>
+#include <asm/book3s/64/radix.h>
 
+#ifdef CONFIG_PPC_64K_PAGES
+#include <asm/book3s/64/pgtable-64k.h>
+#else
+#include <asm/book3s/64/pgtable-4k.h>
+#endif
+
+#include <asm/barrier.h>
 /*
  * The second half of the kernel virtual space is used for IO mappings,
  * it's itself carved into the PIO region (ISA and PHB IO space) and
@@ -26,8 +261,6 @@
 #define IOREMAP_BASE	(PHB_IO_END)
 #define IOREMAP_END	(KERN_VIRT_START + KERN_VIRT_SIZE)
 
-#define vmemmap			((struct page *)VMEMMAP_BASE)
-
 /* Advertise special mapping type for AGP */
 #define HAVE_PAGE_AGP
 
@@ -45,7 +278,7 @@
 
 #define __real_pte(e,p)		((real_pte_t){(e)})
 #define __rpte_to_pte(r)	((r).pte)
-#define __rpte_to_hidx(r,index)	(pte_val(__rpte_to_pte(r)) >>_PAGE_F_GIX_SHIFT)
+#define __rpte_to_hidx(r,index)	(pte_val(__rpte_to_pte(r)) >> H_PAGE_F_GIX_SHIFT)
 
 #define pte_iterate_hashed_subpages(rpte, psize, va, index, shift)       \
 	do {							         \
@@ -62,6 +295,327 @@
 
 #endif /* __real_pte */
 
+static inline unsigned long pte_update(struct mm_struct *mm, unsigned long addr,
+				       pte_t *ptep, unsigned long clr,
+				       unsigned long set, int huge)
+{
+	if (radix_enabled())
+		return radix__pte_update(mm, addr, ptep, clr, set, huge);
+	return hash__pte_update(mm, addr, ptep, clr, set, huge);
+}
+/*
+ * For hash even if we have _PAGE_ACCESSED = 0, we do a pte_update.
+ * We currently remove entries from the hashtable regardless of whether
+ * the entry was young or dirty.
+ *
+ * We should be more intelligent about this but for the moment we override
+ * these functions and force a tlb flush unconditionally
+ * For radix: H_PAGE_HASHPTE should be zero. Hence we can use the same
+ * function for both hash and radix.
+ */
+static inline int __ptep_test_and_clear_young(struct mm_struct *mm,
+					      unsigned long addr, pte_t *ptep)
+{
+	unsigned long old;
+
+	if ((pte_val(*ptep) & (_PAGE_ACCESSED | H_PAGE_HASHPTE)) == 0)
+		return 0;
+	old = pte_update(mm, addr, ptep, _PAGE_ACCESSED, 0, 0);
+	return (old & _PAGE_ACCESSED) != 0;
+}
+
+#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
+#define ptep_test_and_clear_young(__vma, __addr, __ptep)	\
+({								\
+	int __r;						\
+	__r = __ptep_test_and_clear_young((__vma)->vm_mm, __addr, __ptep); \
+	__r;							\
+})
+
+#define __HAVE_ARCH_PTEP_SET_WRPROTECT
+static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
+				      pte_t *ptep)
+{
+
+	if ((pte_val(*ptep) & _PAGE_WRITE) == 0)
+		return;
+
+	pte_update(mm, addr, ptep, _PAGE_WRITE, 0, 0);
+}
+
+static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
+					   unsigned long addr, pte_t *ptep)
+{
+	if ((pte_val(*ptep) & _PAGE_WRITE) == 0)
+		return;
+
+	pte_update(mm, addr, ptep, _PAGE_WRITE, 0, 1);
+}
+
+#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
+static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
+				       unsigned long addr, pte_t *ptep)
+{
+	unsigned long old = pte_update(mm, addr, ptep, ~0UL, 0, 0);
+	return __pte(old);
+}
+
+static inline void pte_clear(struct mm_struct *mm, unsigned long addr,
+			     pte_t * ptep)
+{
+	pte_update(mm, addr, ptep, ~0UL, 0, 0);
+}
+static inline int pte_write(pte_t pte)		{ return !!(pte_val(pte) & _PAGE_WRITE);}
+static inline int pte_dirty(pte_t pte)		{ return !!(pte_val(pte) & _PAGE_DIRTY); }
+static inline int pte_young(pte_t pte)		{ return !!(pte_val(pte) & _PAGE_ACCESSED); }
+static inline int pte_special(pte_t pte)	{ return !!(pte_val(pte) & _PAGE_SPECIAL); }
+static inline pgprot_t pte_pgprot(pte_t pte)	{ return __pgprot(pte_val(pte) & PAGE_PROT_BITS); }
+
+#ifdef CONFIG_HAVE_ARCH_SOFT_DIRTY
+static inline bool pte_soft_dirty(pte_t pte)
+{
+	return !!(pte_val(pte) & _PAGE_SOFT_DIRTY);
+}
+static inline pte_t pte_mksoft_dirty(pte_t pte)
+{
+	return __pte(pte_val(pte) | _PAGE_SOFT_DIRTY);
+}
+
+static inline pte_t pte_clear_soft_dirty(pte_t pte)
+{
+	return __pte(pte_val(pte) & ~_PAGE_SOFT_DIRTY);
+}
+#endif /* CONFIG_HAVE_ARCH_SOFT_DIRTY */
+
+#ifdef CONFIG_NUMA_BALANCING
+/*
+ * These work without NUMA balancing but the kernel does not care. See the
+ * comment in include/asm-generic/pgtable.h . On powerpc, this will only
+ * work for user pages and always return true for kernel pages.
+ */
+static inline int pte_protnone(pte_t pte)
+{
+	return (pte_val(pte) & (_PAGE_PRESENT | _PAGE_PRIVILEGED)) ==
+		(_PAGE_PRESENT | _PAGE_PRIVILEGED);
+}
+#endif /* CONFIG_NUMA_BALANCING */
+
+static inline int pte_present(pte_t pte)
+{
+	return !!(pte_val(pte) & _PAGE_PRESENT);
+}
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ *
+ * Even if PTEs can be unsigned long long, a PFN is always an unsigned
+ * long for now.
+ */
+static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot)
+{
+	return __pte((((pte_basic_t)(pfn) << PAGE_SHIFT) & PTE_RPN_MASK) |
+		     pgprot_val(pgprot));
+}
+
+static inline unsigned long pte_pfn(pte_t pte)
+{
+	return (pte_val(pte) & PTE_RPN_MASK) >> PAGE_SHIFT;
+}
+
+/* Generic modifiers for PTE bits */
+static inline pte_t pte_wrprotect(pte_t pte)
+{
+	return __pte(pte_val(pte) & ~_PAGE_WRITE);
+}
+
+static inline pte_t pte_mkclean(pte_t pte)
+{
+	return __pte(pte_val(pte) & ~_PAGE_DIRTY);
+}
+
+static inline pte_t pte_mkold(pte_t pte)
+{
+	return __pte(pte_val(pte) & ~_PAGE_ACCESSED);
+}
+
+static inline pte_t pte_mkwrite(pte_t pte)
+{
+	/*
+	 * write implies read, hence set both
+	 */
+	return __pte(pte_val(pte) | _PAGE_RW);
+}
+
+static inline pte_t pte_mkdirty(pte_t pte)
+{
+	return __pte(pte_val(pte) | _PAGE_DIRTY | _PAGE_SOFT_DIRTY);
+}
+
+static inline pte_t pte_mkyoung(pte_t pte)
+{
+	return __pte(pte_val(pte) | _PAGE_ACCESSED);
+}
+
+static inline pte_t pte_mkspecial(pte_t pte)
+{
+	return __pte(pte_val(pte) | _PAGE_SPECIAL);
+}
+
+static inline pte_t pte_mkhuge(pte_t pte)
+{
+	return pte;
+}
+
+static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{
+	/* FIXME!! check whether this need to be a conditional */
+	return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot));
+}
+
+static inline bool pte_user(pte_t pte)
+{
+	return !(pte_val(pte) & _PAGE_PRIVILEGED);
+}
+
+/* Encode and de-code a swap entry */
+#define MAX_SWAPFILES_CHECK() do { \
+	BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > SWP_TYPE_BITS); \
+	/*							\
+	 * Don't have overlapping bits with _PAGE_HPTEFLAGS	\
+	 * We filter HPTEFLAGS on set_pte.			\
+	 */							\
+	BUILD_BUG_ON(_PAGE_HPTEFLAGS & (0x1f << _PAGE_BIT_SWAP_TYPE)); \
+	BUILD_BUG_ON(_PAGE_HPTEFLAGS & _PAGE_SWP_SOFT_DIRTY);	\
+	} while (0)
+/*
+ * on pte we don't need handle RADIX_TREE_EXCEPTIONAL_SHIFT;
+ */
+#define SWP_TYPE_BITS 5
+#define __swp_type(x)		(((x).val >> _PAGE_BIT_SWAP_TYPE) \
+				& ((1UL << SWP_TYPE_BITS) - 1))
+#define __swp_offset(x)		(((x).val & PTE_RPN_MASK) >> PAGE_SHIFT)
+#define __swp_entry(type, offset)	((swp_entry_t) { \
+				((type) << _PAGE_BIT_SWAP_TYPE) \
+				| (((offset) << PAGE_SHIFT) & PTE_RPN_MASK)})
+/*
+ * swp_entry_t must be independent of pte bits. We build a swp_entry_t from
+ * swap type and offset we get from swap and convert that to pte to find a
+ * matching pte in linux page table.
+ * Clear bits not found in swap entries here.
+ */
+#define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val((pte)) & ~_PAGE_PTE })
+#define __swp_entry_to_pte(x)	__pte((x).val | _PAGE_PTE)
+
+#ifdef CONFIG_MEM_SOFT_DIRTY
+#define _PAGE_SWP_SOFT_DIRTY   (1UL << (SWP_TYPE_BITS + _PAGE_BIT_SWAP_TYPE))
+#else
+#define _PAGE_SWP_SOFT_DIRTY	0UL
+#endif /* CONFIG_MEM_SOFT_DIRTY */
+
+#ifdef CONFIG_HAVE_ARCH_SOFT_DIRTY
+static inline pte_t pte_swp_mksoft_dirty(pte_t pte)
+{
+	return __pte(pte_val(pte) | _PAGE_SWP_SOFT_DIRTY);
+}
+static inline bool pte_swp_soft_dirty(pte_t pte)
+{
+	return !!(pte_val(pte) & _PAGE_SWP_SOFT_DIRTY);
+}
+static inline pte_t pte_swp_clear_soft_dirty(pte_t pte)
+{
+	return __pte(pte_val(pte) & ~_PAGE_SWP_SOFT_DIRTY);
+}
+#endif /* CONFIG_HAVE_ARCH_SOFT_DIRTY */
+
+static inline bool check_pte_access(unsigned long access, unsigned long ptev)
+{
+	/*
+	 * This check for _PAGE_RWX and _PAGE_PRESENT bits
+	 */
+	if (access & ~ptev)
+		return false;
+	/*
+	 * This check for access to privilege space
+	 */
+	if ((access & _PAGE_PRIVILEGED) != (ptev & _PAGE_PRIVILEGED))
+		return false;
+
+	return true;
+}
+/*
+ * Generic functions with hash/radix callbacks
+ */
+
+static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry)
+{
+	if (radix_enabled())
+		return radix__ptep_set_access_flags(ptep, entry);
+	return hash__ptep_set_access_flags(ptep, entry);
+}
+
+#define __HAVE_ARCH_PTE_SAME
+static inline int pte_same(pte_t pte_a, pte_t pte_b)
+{
+	if (radix_enabled())
+		return radix__pte_same(pte_a, pte_b);
+	return hash__pte_same(pte_a, pte_b);
+}
+
+static inline int pte_none(pte_t pte)
+{
+	if (radix_enabled())
+		return radix__pte_none(pte);
+	return hash__pte_none(pte);
+}
+
+static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
+				pte_t *ptep, pte_t pte, int percpu)
+{
+	if (radix_enabled())
+		return radix__set_pte_at(mm, addr, ptep, pte, percpu);
+	return hash__set_pte_at(mm, addr, ptep, pte, percpu);
+}
+
+#define _PAGE_CACHE_CTL	(_PAGE_NON_IDEMPOTENT | _PAGE_TOLERANT)
+
+#define pgprot_noncached pgprot_noncached
+static inline pgprot_t pgprot_noncached(pgprot_t prot)
+{
+	return __pgprot((pgprot_val(prot) & ~_PAGE_CACHE_CTL) |
+			_PAGE_NON_IDEMPOTENT);
+}
+
+#define pgprot_noncached_wc pgprot_noncached_wc
+static inline pgprot_t pgprot_noncached_wc(pgprot_t prot)
+{
+	return __pgprot((pgprot_val(prot) & ~_PAGE_CACHE_CTL) |
+			_PAGE_TOLERANT);
+}
+
+#define pgprot_cached pgprot_cached
+static inline pgprot_t pgprot_cached(pgprot_t prot)
+{
+	return __pgprot((pgprot_val(prot) & ~_PAGE_CACHE_CTL));
+}
+
+#define pgprot_writecombine pgprot_writecombine
+static inline pgprot_t pgprot_writecombine(pgprot_t prot)
+{
+	return pgprot_noncached_wc(prot);
+}
+/*
+ * check a pte mapping have cache inhibited property
+ */
+static inline bool pte_ci(pte_t pte)
+{
+	unsigned long pte_v = pte_val(pte);
+
+	if (((pte_v & _PAGE_CACHE_CTL) == _PAGE_TOLERANT) ||
+	    ((pte_v & _PAGE_CACHE_CTL) == _PAGE_NON_IDEMPOTENT))
+		return true;
+	return false;
+}
+
 static inline void pmd_set(pmd_t *pmdp, unsigned long val)
 {
 	*pmdp = __pmd(val);
@@ -75,6 +629,13 @@ static inline void pmd_clear(pmd_t *pmdp
 #define pmd_none(pmd)		(!pmd_val(pmd))
 #define	pmd_present(pmd)	(!pmd_none(pmd))
 
+static inline int pmd_bad(pmd_t pmd)
+{
+	if (radix_enabled())
+		return radix__pmd_bad(pmd);
+	return hash__pmd_bad(pmd);
+}
+
 static inline void pud_set(pud_t *pudp, unsigned long val)
 {
 	*pudp = __pud(val);
@@ -100,6 +661,15 @@ static inline pud_t pte_pud(pte_t pte)
 	return __pud(pte_val(pte));
 }
 #define pud_write(pud)		pte_write(pud_pte(pud))
+
+static inline int pud_bad(pud_t pud)
+{
+	if (radix_enabled())
+		return radix__pud_bad(pud);
+	return hash__pud_bad(pud);
+}
+
+
 #define pgd_write(pgd)		pte_write(pgd_pte(pgd))
 static inline void pgd_set(pgd_t *pgdp, unsigned long val)
 {
@@ -124,8 +694,27 @@ static inline pgd_t pte_pgd(pte_t pte)
 	return __pgd(pte_val(pte));
 }
 
+static inline int pgd_bad(pgd_t pgd)
+{
+	if (radix_enabled())
+		return radix__pgd_bad(pgd);
+	return hash__pgd_bad(pgd);
+}
+
 extern struct page *pgd_page(pgd_t pgd);
 
+/* Pointers in the page table tree are physical addresses */
+#define __pgtable_ptr_val(ptr)	__pa(ptr)
+
+#define pmd_page_vaddr(pmd)	__va(pmd_val(pmd) & ~PMD_MASKED_BITS)
+#define pud_page_vaddr(pud)	__va(pud_val(pud) & ~PUD_MASKED_BITS)
+#define pgd_page_vaddr(pgd)	__va(pgd_val(pgd) & ~PGD_MASKED_BITS)
+
+#define pgd_index(address) (((address) >> (PGDIR_SHIFT)) & (PTRS_PER_PGD - 1))
+#define pud_index(address) (((address) >> (PUD_SHIFT)) & (PTRS_PER_PUD - 1))
+#define pmd_index(address) (((address) >> (PMD_SHIFT)) & (PTRS_PER_PMD - 1))
+#define pte_index(address) (((address) >> (PAGE_SHIFT)) & (PTRS_PER_PTE - 1))
+
 /*
  * Find an entry in a page-table-directory.  We combine the address region
  * (the high order N bits) and the pgd portion of the address.
@@ -156,73 +745,42 @@ extern struct page *pgd_page(pgd_t pgd);
 #define pgd_ERROR(e) \
 	pr_err("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
 
-/* Encode and de-code a swap entry */
-#define MAX_SWAPFILES_CHECK() do { \
-	BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > SWP_TYPE_BITS); \
-	/*							\
-	 * Don't have overlapping bits with _PAGE_HPTEFLAGS	\
-	 * We filter HPTEFLAGS on set_pte.			\
-	 */							\
-	BUILD_BUG_ON(_PAGE_HPTEFLAGS & (0x1f << _PAGE_BIT_SWAP_TYPE)); \
-	BUILD_BUG_ON(_PAGE_HPTEFLAGS & _PAGE_SWP_SOFT_DIRTY);	\
-	} while (0)
-/*
- * on pte we don't need handle RADIX_TREE_EXCEPTIONAL_SHIFT;
- */
-#define SWP_TYPE_BITS 5
-#define __swp_type(x)		(((x).val >> _PAGE_BIT_SWAP_TYPE) \
-				& ((1UL << SWP_TYPE_BITS) - 1))
-#define __swp_offset(x)		(((x).val & PTE_RPN_MASK) >> PTE_RPN_SHIFT)
-#define __swp_entry(type, offset)	((swp_entry_t) { \
-				((type) << _PAGE_BIT_SWAP_TYPE) \
-				| (((offset) << PTE_RPN_SHIFT) & PTE_RPN_MASK)})
-/*
- * swp_entry_t must be independent of pte bits. We build a swp_entry_t from
- * swap type and offset we get from swap and convert that to pte to find a
- * matching pte in linux page table.
- * Clear bits not found in swap entries here.
- */
-#define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val((pte)) & ~_PAGE_PTE })
-#define __swp_entry_to_pte(x)	__pte((x).val | _PAGE_PTE)
-
-#ifdef CONFIG_MEM_SOFT_DIRTY
-#define _PAGE_SWP_SOFT_DIRTY   (1UL << (SWP_TYPE_BITS + _PAGE_BIT_SWAP_TYPE))
-#else
-#define _PAGE_SWP_SOFT_DIRTY	0UL
-#endif /* CONFIG_MEM_SOFT_DIRTY */
+void pgtable_cache_add(unsigned shift, void (*ctor)(void *));
+void pgtable_cache_init(void);
 
-#ifdef CONFIG_HAVE_ARCH_SOFT_DIRTY
-static inline pte_t pte_swp_mksoft_dirty(pte_t pte)
+static inline int map_kernel_page(unsigned long ea, unsigned long pa,
+				  unsigned long flags)
 {
-	return __pte(pte_val(pte) | _PAGE_SWP_SOFT_DIRTY);
+	if (radix_enabled()) {
+#if defined(CONFIG_PPC_RADIX_MMU) && defined(DEBUG_VM)
+		unsigned long page_size = 1 << mmu_psize_defs[mmu_io_psize].shift;
+		WARN((page_size != PAGE_SIZE), "I/O page size != PAGE_SIZE");
+#endif
+		return radix__map_kernel_page(ea, pa, __pgprot(flags), PAGE_SIZE);
+	}
+	return hash__map_kernel_page(ea, pa, flags);
 }
-static inline bool pte_swp_soft_dirty(pte_t pte)
+
+static inline int __meminit vmemmap_create_mapping(unsigned long start,
+						   unsigned long page_size,
+						   unsigned long phys)
 {
-	return !!(pte_val(pte) & _PAGE_SWP_SOFT_DIRTY);
+	if (radix_enabled())
+		return radix__vmemmap_create_mapping(start, page_size, phys);
+	return hash__vmemmap_create_mapping(start, page_size, phys);
 }
-static inline pte_t pte_swp_clear_soft_dirty(pte_t pte)
+
+#ifdef CONFIG_MEMORY_HOTPLUG
+static inline void vmemmap_remove_mapping(unsigned long start,
+					  unsigned long page_size)
 {
-	return __pte(pte_val(pte) & ~_PAGE_SWP_SOFT_DIRTY);
+	if (radix_enabled())
+		return radix__vmemmap_remove_mapping(start, page_size);
+	return hash__vmemmap_remove_mapping(start, page_size);
 }
-#endif /* CONFIG_HAVE_ARCH_SOFT_DIRTY */
-
-void pgtable_cache_add(unsigned shift, void (*ctor)(void *));
-void pgtable_cache_init(void);
-
+#endif
 struct page *realmode_pfn_to_page(unsigned long pfn);
 
-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
-extern pmd_t pfn_pmd(unsigned long pfn, pgprot_t pgprot);
-extern pmd_t mk_pmd(struct page *page, pgprot_t pgprot);
-extern pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot);
-extern void set_pmd_at(struct mm_struct *mm, unsigned long addr,
-		       pmd_t *pmdp, pmd_t pmd);
-extern void update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr,
-				 pmd_t *pmd);
-extern int has_transparent_hugepage(void);
-#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
-
-
 static inline pte_t pmd_pte(pmd_t pmd)
 {
 	return __pte(pmd_val(pmd));
@@ -237,7 +795,6 @@ static inline pte_t *pmdp_ptep(pmd_t *pm
 {
 	return (pte_t *)pmd;
 }
-
 #define pmd_pfn(pmd)		pte_pfn(pmd_pte(pmd))
 #define pmd_dirty(pmd)		pte_dirty(pmd_pte(pmd))
 #define pmd_young(pmd)		pte_young(pmd_pte(pmd))
@@ -264,9 +821,87 @@ static inline int pmd_protnone(pmd_t pmd
 #define __HAVE_ARCH_PMD_WRITE
 #define pmd_write(pmd)		pte_write(pmd_pte(pmd))
 
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+extern pmd_t pfn_pmd(unsigned long pfn, pgprot_t pgprot);
+extern pmd_t mk_pmd(struct page *page, pgprot_t pgprot);
+extern pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot);
+extern void set_pmd_at(struct mm_struct *mm, unsigned long addr,
+		       pmd_t *pmdp, pmd_t pmd);
+extern void update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr,
+				 pmd_t *pmd);
+extern int hash__has_transparent_hugepage(void);
+static inline int has_transparent_hugepage(void)
+{
+	if (radix_enabled())
+		return radix__has_transparent_hugepage();
+	return hash__has_transparent_hugepage();
+}
+#define has_transparent_hugepage has_transparent_hugepage
+
+static inline unsigned long
+pmd_hugepage_update(struct mm_struct *mm, unsigned long addr, pmd_t *pmdp,
+		    unsigned long clr, unsigned long set)
+{
+	if (radix_enabled())
+		return radix__pmd_hugepage_update(mm, addr, pmdp, clr, set);
+	return hash__pmd_hugepage_update(mm, addr, pmdp, clr, set);
+}
+
+static inline int pmd_large(pmd_t pmd)
+{
+	return !!(pmd_val(pmd) & _PAGE_PTE);
+}
+
+static inline pmd_t pmd_mknotpresent(pmd_t pmd)
+{
+	return __pmd(pmd_val(pmd) & ~_PAGE_PRESENT);
+}
+/*
+ * For radix we should always find H_PAGE_HASHPTE zero. Hence
+ * the below will work for radix too
+ */
+static inline int __pmdp_test_and_clear_young(struct mm_struct *mm,
+					      unsigned long addr, pmd_t *pmdp)
+{
+	unsigned long old;
+
+	if ((pmd_val(*pmdp) & (_PAGE_ACCESSED | H_PAGE_HASHPTE)) == 0)
+		return 0;
+	old = pmd_hugepage_update(mm, addr, pmdp, _PAGE_ACCESSED, 0);
+	return ((old & _PAGE_ACCESSED) != 0);
+}
+
+#define __HAVE_ARCH_PMDP_SET_WRPROTECT
+static inline void pmdp_set_wrprotect(struct mm_struct *mm, unsigned long addr,
+				      pmd_t *pmdp)
+{
+
+	if ((pmd_val(*pmdp) & _PAGE_WRITE) == 0)
+		return;
+
+	pmd_hugepage_update(mm, addr, pmdp, _PAGE_WRITE, 0);
+}
+
+static inline int pmd_trans_huge(pmd_t pmd)
+{
+	if (radix_enabled())
+		return radix__pmd_trans_huge(pmd);
+	return hash__pmd_trans_huge(pmd);
+}
+
+#define __HAVE_ARCH_PMD_SAME
+static inline int pmd_same(pmd_t pmd_a, pmd_t pmd_b)
+{
+	if (radix_enabled())
+		return radix__pmd_same(pmd_a, pmd_b);
+	return hash__pmd_same(pmd_a, pmd_b);
+}
+
 static inline pmd_t pmd_mkhuge(pmd_t pmd)
 {
-	return __pmd(pmd_val(pmd) | (_PAGE_PTE | _PAGE_THP_HUGE));
+	if (radix_enabled())
+		return radix__pmd_mkhuge(pmd);
+	return hash__pmd_mkhuge(pmd);
 }
 
 #define __HAVE_ARCH_PMDP_SET_ACCESS_FLAGS
@@ -277,37 +912,63 @@ extern int pmdp_set_access_flags(struct
 #define __HAVE_ARCH_PMDP_TEST_AND_CLEAR_YOUNG
 extern int pmdp_test_and_clear_young(struct vm_area_struct *vma,
 				     unsigned long address, pmd_t *pmdp);
-#define __HAVE_ARCH_PMDP_CLEAR_YOUNG_FLUSH
-extern int pmdp_clear_flush_young(struct vm_area_struct *vma,
-				  unsigned long address, pmd_t *pmdp);
 
 #define __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR
-extern pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
-				     unsigned long addr, pmd_t *pmdp);
+static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
+					    unsigned long addr, pmd_t *pmdp)
+{
+	if (radix_enabled())
+		return radix__pmdp_huge_get_and_clear(mm, addr, pmdp);
+	return hash__pmdp_huge_get_and_clear(mm, addr, pmdp);
+}
 
-extern pmd_t pmdp_collapse_flush(struct vm_area_struct *vma,
-				 unsigned long address, pmd_t *pmdp);
+static inline pmd_t pmdp_collapse_flush(struct vm_area_struct *vma,
+					unsigned long address, pmd_t *pmdp)
+{
+	if (radix_enabled())
+		return radix__pmdp_collapse_flush(vma, address, pmdp);
+	return hash__pmdp_collapse_flush(vma, address, pmdp);
+}
 #define pmdp_collapse_flush pmdp_collapse_flush
 
 #define __HAVE_ARCH_PGTABLE_DEPOSIT
-extern void pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp,
-				       pgtable_t pgtable);
+static inline void pgtable_trans_huge_deposit(struct mm_struct *mm,
+					      pmd_t *pmdp, pgtable_t pgtable)
+{
+	if (radix_enabled())
+		return radix__pgtable_trans_huge_deposit(mm, pmdp, pgtable);
+	return hash__pgtable_trans_huge_deposit(mm, pmdp, pgtable);
+}
+
 #define __HAVE_ARCH_PGTABLE_WITHDRAW
-extern pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp);
+static inline pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm,
+						    pmd_t *pmdp)
+{
+	if (radix_enabled())
+		return radix__pgtable_trans_huge_withdraw(mm, pmdp);
+	return hash__pgtable_trans_huge_withdraw(mm, pmdp);
+}
 
 #define __HAVE_ARCH_PMDP_INVALIDATE
 extern void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
 			    pmd_t *pmdp);
 
 #define __HAVE_ARCH_PMDP_HUGE_SPLIT_PREPARE
-extern void pmdp_huge_split_prepare(struct vm_area_struct *vma,
-				    unsigned long address, pmd_t *pmdp);
+static inline void pmdp_huge_split_prepare(struct vm_area_struct *vma,
+					   unsigned long address, pmd_t *pmdp)
+{
+	if (radix_enabled())
+		return radix__pmdp_huge_split_prepare(vma, address, pmdp);
+	return hash__pmdp_huge_split_prepare(vma, address, pmdp);
+}
 
 #define pmd_move_must_withdraw pmd_move_must_withdraw
 struct spinlock;
 static inline int pmd_move_must_withdraw(struct spinlock *new_pmd_ptl,
 					 struct spinlock *old_pmd_ptl)
 {
+	if (radix_enabled())
+		return false;
 	/*
 	 * Archs like ppc64 use pgtable to store per pmd
 	 * specific information. So when we switch the pmd,
@@ -315,5 +976,6 @@ static inline int pmd_move_must_withdraw
 	 */
 	return true;
 }
+#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
 #endif /* __ASSEMBLY__ */
 #endif /* _ASM_POWERPC_BOOK3S_64_PGTABLE_H_ */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/64/radix-4k.h linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/64/radix-4k.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/64/radix-4k.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/64/radix-4k.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,12 @@
+#ifndef _ASM_POWERPC_PGTABLE_RADIX_4K_H
+#define _ASM_POWERPC_PGTABLE_RADIX_4K_H
+
+/*
+ * For 4K page size supported index is 13/9/9/9
+ */
+#define RADIX_PTE_INDEX_SIZE  9  /* 2MB huge page */
+#define RADIX_PMD_INDEX_SIZE  9  /* 1G huge page */
+#define RADIX_PUD_INDEX_SIZE	 9
+#define RADIX_PGD_INDEX_SIZE  13
+
+#endif /* _ASM_POWERPC_PGTABLE_RADIX_4K_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/64/radix-64k.h linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/64/radix-64k.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/64/radix-64k.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/64/radix-64k.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,12 @@
+#ifndef _ASM_POWERPC_PGTABLE_RADIX_64K_H
+#define _ASM_POWERPC_PGTABLE_RADIX_64K_H
+
+/*
+ * For 64K page size supported index is 13/9/9/5
+ */
+#define RADIX_PTE_INDEX_SIZE  5  /* 2MB huge page */
+#define RADIX_PMD_INDEX_SIZE  9  /* 1G huge page */
+#define RADIX_PUD_INDEX_SIZE	 9
+#define RADIX_PGD_INDEX_SIZE  13
+
+#endif /* _ASM_POWERPC_PGTABLE_RADIX_64K_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/64/radix.h linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/64/radix.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/64/radix.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/64/radix.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,247 @@
+#ifndef _ASM_POWERPC_PGTABLE_RADIX_H
+#define _ASM_POWERPC_PGTABLE_RADIX_H
+
+#ifndef __ASSEMBLY__
+#include <asm/cmpxchg.h>
+#endif
+
+#ifdef CONFIG_PPC_64K_PAGES
+#include <asm/book3s/64/radix-64k.h>
+#else
+#include <asm/book3s/64/radix-4k.h>
+#endif
+
+/* An empty PTE can still have a R or C writeback */
+#define RADIX_PTE_NONE_MASK		(_PAGE_DIRTY | _PAGE_ACCESSED)
+
+/* Bits to set in a RPMD/RPUD/RPGD */
+#define RADIX_PMD_VAL_BITS		(0x8000000000000000UL | RADIX_PTE_INDEX_SIZE)
+#define RADIX_PUD_VAL_BITS		(0x8000000000000000UL | RADIX_PMD_INDEX_SIZE)
+#define RADIX_PGD_VAL_BITS		(0x8000000000000000UL | RADIX_PUD_INDEX_SIZE)
+
+/* Don't have anything in the reserved bits and leaf bits */
+#define RADIX_PMD_BAD_BITS		0x60000000000000e0UL
+#define RADIX_PUD_BAD_BITS		0x60000000000000e0UL
+#define RADIX_PGD_BAD_BITS		0x60000000000000e0UL
+
+/*
+ * Size of EA range mapped by our pagetables.
+ */
+#define RADIX_PGTABLE_EADDR_SIZE (RADIX_PTE_INDEX_SIZE + RADIX_PMD_INDEX_SIZE +	\
+			      RADIX_PUD_INDEX_SIZE + RADIX_PGD_INDEX_SIZE + PAGE_SHIFT)
+#define RADIX_PGTABLE_RANGE (ASM_CONST(1) << RADIX_PGTABLE_EADDR_SIZE)
+
+/*
+ * We support 52 bit address space, Use top bit for kernel
+ * virtual mapping. Also make sure kernel fit in the top
+ * quadrant.
+ *
+ *           +------------------+
+ *           +------------------+  Kernel virtual map (0xc008000000000000)
+ *           |                  |
+ *           |                  |
+ *           |                  |
+ * 0b11......+------------------+  Kernel linear map (0xc....)
+ *           |                  |
+ *           |     2 quadrant   |
+ *           |                  |
+ * 0b10......+------------------+
+ *           |                  |
+ *           |    1 quadrant    |
+ *           |                  |
+ * 0b01......+------------------+
+ *           |                  |
+ *           |    0 quadrant    |
+ *           |                  |
+ * 0b00......+------------------+
+ *
+ *
+ * 3rd quadrant expanded:
+ * +------------------------------+
+ * |                              |
+ * |                              |
+ * |                              |
+ * +------------------------------+  Kernel IO map end (0xc010000000000000)
+ * |                              |
+ * |                              |
+ * |      1/2 of virtual map      |
+ * |                              |
+ * |                              |
+ * +------------------------------+  Kernel IO map start
+ * |                              |
+ * |      1/4 of virtual map      |
+ * |                              |
+ * +------------------------------+  Kernel vmemap start
+ * |                              |
+ * |     1/4 of virtual map       |
+ * |                              |
+ * +------------------------------+  Kernel virt start (0xc008000000000000)
+ * |                              |
+ * |                              |
+ * |                              |
+ * +------------------------------+  Kernel linear (0xc.....)
+ */
+
+#define RADIX_KERN_VIRT_START ASM_CONST(0xc008000000000000)
+#define RADIX_KERN_VIRT_SIZE  ASM_CONST(0x0008000000000000)
+
+/*
+ * The vmalloc space starts at the beginning of that region, and
+ * occupies a quarter of it on radix config.
+ * (we keep a quarter for the virtual memmap)
+ */
+#define RADIX_VMALLOC_START	RADIX_KERN_VIRT_START
+#define RADIX_VMALLOC_SIZE	(RADIX_KERN_VIRT_SIZE >> 2)
+#define RADIX_VMALLOC_END	(RADIX_VMALLOC_START + RADIX_VMALLOC_SIZE)
+/*
+ * Defines the address of the vmemap area, in its own region on
+ * hash table CPUs.
+ */
+#define RADIX_VMEMMAP_BASE		(RADIX_VMALLOC_END)
+
+#ifndef __ASSEMBLY__
+#define RADIX_PTE_TABLE_SIZE	(sizeof(pte_t) << RADIX_PTE_INDEX_SIZE)
+#define RADIX_PMD_TABLE_SIZE	(sizeof(pmd_t) << RADIX_PMD_INDEX_SIZE)
+#define RADIX_PUD_TABLE_SIZE	(sizeof(pud_t) << RADIX_PUD_INDEX_SIZE)
+#define RADIX_PGD_TABLE_SIZE	(sizeof(pgd_t) << RADIX_PGD_INDEX_SIZE)
+
+static inline unsigned long radix__pte_update(struct mm_struct *mm,
+					unsigned long addr,
+					pte_t *ptep, unsigned long clr,
+					unsigned long set,
+					int huge)
+{
+	pte_t pte;
+	unsigned long old_pte, new_pte;
+
+	do {
+		pte = READ_ONCE(*ptep);
+		old_pte = pte_val(pte);
+		new_pte = (old_pte | set) & ~clr;
+
+	} while (!pte_xchg(ptep, __pte(old_pte), __pte(new_pte)));
+
+	/* We already do a sync in cmpxchg, is ptesync needed ?*/
+	asm volatile("ptesync" : : : "memory");
+	/* huge pages use the old page table lock */
+	if (!huge)
+		assert_pte_locked(mm, addr);
+
+	return old_pte;
+}
+
+/*
+ * Set the dirty and/or accessed bits atomically in a linux PTE, this
+ * function doesn't need to invalidate tlb.
+ */
+static inline void radix__ptep_set_access_flags(pte_t *ptep, pte_t entry)
+{
+	pte_t pte;
+	unsigned long old_pte, new_pte;
+	unsigned long set = pte_val(entry) & (_PAGE_DIRTY | _PAGE_ACCESSED |
+					      _PAGE_RW | _PAGE_EXEC);
+	do {
+		pte = READ_ONCE(*ptep);
+		old_pte = pte_val(pte);
+		new_pte = old_pte | set;
+
+	} while (!pte_xchg(ptep, __pte(old_pte), __pte(new_pte)));
+
+	/* We already do a sync in cmpxchg, is ptesync needed ?*/
+	asm volatile("ptesync" : : : "memory");
+}
+
+static inline int radix__pte_same(pte_t pte_a, pte_t pte_b)
+{
+	return ((pte_raw(pte_a) ^ pte_raw(pte_b)) == 0);
+}
+
+static inline int radix__pte_none(pte_t pte)
+{
+	return (pte_val(pte) & ~RADIX_PTE_NONE_MASK) == 0;
+}
+
+static inline void radix__set_pte_at(struct mm_struct *mm, unsigned long addr,
+				 pte_t *ptep, pte_t pte, int percpu)
+{
+	*ptep = pte;
+	asm volatile("ptesync" : : : "memory");
+}
+
+static inline int radix__pmd_bad(pmd_t pmd)
+{
+	return !!(pmd_val(pmd) & RADIX_PMD_BAD_BITS);
+}
+
+static inline int radix__pmd_same(pmd_t pmd_a, pmd_t pmd_b)
+{
+	return ((pmd_raw(pmd_a) ^ pmd_raw(pmd_b)) == 0);
+}
+
+static inline int radix__pud_bad(pud_t pud)
+{
+	return !!(pud_val(pud) & RADIX_PUD_BAD_BITS);
+}
+
+
+static inline int radix__pgd_bad(pgd_t pgd)
+{
+	return !!(pgd_val(pgd) & RADIX_PGD_BAD_BITS);
+}
+
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+
+static inline int radix__pmd_trans_huge(pmd_t pmd)
+{
+	return !!(pmd_val(pmd) & _PAGE_PTE);
+}
+
+static inline pmd_t radix__pmd_mkhuge(pmd_t pmd)
+{
+	return __pmd(pmd_val(pmd) | _PAGE_PTE);
+}
+static inline void radix__pmdp_huge_split_prepare(struct vm_area_struct *vma,
+					    unsigned long address, pmd_t *pmdp)
+{
+	/* Nothing to do for radix. */
+	return;
+}
+
+extern unsigned long radix__pmd_hugepage_update(struct mm_struct *mm, unsigned long addr,
+					  pmd_t *pmdp, unsigned long clr,
+					  unsigned long set);
+extern pmd_t radix__pmdp_collapse_flush(struct vm_area_struct *vma,
+				  unsigned long address, pmd_t *pmdp);
+extern void radix__pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp,
+					pgtable_t pgtable);
+extern pgtable_t radix__pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp);
+extern pmd_t radix__pmdp_huge_get_and_clear(struct mm_struct *mm,
+				      unsigned long addr, pmd_t *pmdp);
+extern int radix__has_transparent_hugepage(void);
+#endif
+
+extern int __meminit radix__vmemmap_create_mapping(unsigned long start,
+					     unsigned long page_size,
+					     unsigned long phys);
+extern void radix__vmemmap_remove_mapping(unsigned long start,
+				    unsigned long page_size);
+
+extern int radix__map_kernel_page(unsigned long ea, unsigned long pa,
+				 pgprot_t flags, unsigned int psz);
+
+static inline unsigned long radix__get_tree_size(void)
+{
+	unsigned long rts_field;
+	/*
+	 * we support 52 bits, hence 52-31 = 21, 0b10101
+	 * RTS encoding details
+	 * bits 0 - 3 of rts -> bits 6 - 8 unsigned long
+	 * bits 4 - 5 of rts -> bits 62 - 63 of unsigned long
+	 */
+	rts_field = (0x5UL << 5); /* 6 - 8 bits */
+	rts_field |= (0x2UL << 61);
+
+	return rts_field;
+}
+#endif /* __ASSEMBLY__ */
+#endif
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/64/tlbflush.h linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/64/tlbflush.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/64/tlbflush.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/64/tlbflush.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,90 @@
+#ifndef _ASM_POWERPC_BOOK3S_64_TLBFLUSH_H
+#define _ASM_POWERPC_BOOK3S_64_TLBFLUSH_H
+
+#define MMU_NO_CONTEXT	~0UL
+
+
+#include <asm/book3s/64/tlbflush-hash.h>
+#include <asm/book3s/64/tlbflush-radix.h>
+
+static inline void flush_tlb_range(struct vm_area_struct *vma,
+				   unsigned long start, unsigned long end)
+{
+	if (radix_enabled())
+		return radix__flush_tlb_range(vma, start, end);
+	return hash__flush_tlb_range(vma, start, end);
+}
+
+static inline void flush_tlb_kernel_range(unsigned long start,
+					  unsigned long end)
+{
+	if (radix_enabled())
+		return radix__flush_tlb_kernel_range(start, end);
+	return hash__flush_tlb_kernel_range(start, end);
+}
+
+static inline void local_flush_tlb_mm(struct mm_struct *mm)
+{
+	if (radix_enabled())
+		return radix__local_flush_tlb_mm(mm);
+	return hash__local_flush_tlb_mm(mm);
+}
+
+static inline void local_flush_tlb_page(struct vm_area_struct *vma,
+					unsigned long vmaddr)
+{
+	if (radix_enabled())
+		return radix__local_flush_tlb_page(vma, vmaddr);
+	return hash__local_flush_tlb_page(vma, vmaddr);
+}
+
+static inline void flush_tlb_page_nohash(struct vm_area_struct *vma,
+					 unsigned long vmaddr)
+{
+	if (radix_enabled())
+		return radix__flush_tlb_page(vma, vmaddr);
+	return hash__flush_tlb_page_nohash(vma, vmaddr);
+}
+
+static inline void tlb_flush(struct mmu_gather *tlb)
+{
+	if (radix_enabled())
+		return radix__tlb_flush(tlb);
+	return hash__tlb_flush(tlb);
+}
+
+#ifdef CONFIG_SMP
+static inline void flush_tlb_mm(struct mm_struct *mm)
+{
+	if (radix_enabled())
+		return radix__flush_tlb_mm(mm);
+	return hash__flush_tlb_mm(mm);
+}
+
+static inline void flush_tlb_page(struct vm_area_struct *vma,
+				  unsigned long vmaddr)
+{
+	if (radix_enabled())
+		return radix__flush_tlb_page(vma, vmaddr);
+	return hash__flush_tlb_page(vma, vmaddr);
+}
+#else
+#define flush_tlb_mm(mm)		local_flush_tlb_mm(mm)
+#define flush_tlb_page(vma, addr)	local_flush_tlb_page(vma, addr)
+#endif /* CONFIG_SMP */
+/*
+ * flush the page walk cache for the address
+ */
+static inline void flush_tlb_pgtable(struct mmu_gather *tlb, unsigned long address)
+{
+	/*
+	 * Flush the page table walk cache on freeing a page table. We already
+	 * have marked the upper/higher level page table entry none by now.
+	 * So it is safe to flush PWC here.
+	 */
+	if (!radix_enabled())
+		return;
+
+	radix__flush_tlb_pwc(tlb, address);
+}
+#endif /*  _ASM_POWERPC_BOOK3S_64_TLBFLUSH_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/64/tlbflush-hash.h linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/64/tlbflush-hash.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/64/tlbflush-hash.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/64/tlbflush-hash.h	2016-07-24 15:23:50.000000000 -0400
@@ -1,8 +1,6 @@
 #ifndef _ASM_POWERPC_BOOK3S_64_TLBFLUSH_HASH_H
 #define _ASM_POWERPC_BOOK3S_64_TLBFLUSH_HASH_H
 
-#define MMU_NO_CONTEXT		0
-
 /*
  * TLB flushing for 64-bit hash-MMU CPUs
  */
@@ -29,14 +27,21 @@ extern void __flush_tlb_pending(struct p
 
 static inline void arch_enter_lazy_mmu_mode(void)
 {
-	struct ppc64_tlb_batch *batch = this_cpu_ptr(&ppc64_tlb_batch);
+	struct ppc64_tlb_batch *batch;
 
+	if (radix_enabled())
+		return;
+	batch = this_cpu_ptr(&ppc64_tlb_batch);
 	batch->active = 1;
 }
 
 static inline void arch_leave_lazy_mmu_mode(void)
 {
-	struct ppc64_tlb_batch *batch = this_cpu_ptr(&ppc64_tlb_batch);
+	struct ppc64_tlb_batch *batch;
+
+	if (radix_enabled())
+		return;
+	batch = this_cpu_ptr(&ppc64_tlb_batch);
 
 	if (batch->index)
 		__flush_tlb_pending(batch);
@@ -52,40 +57,42 @@ extern void flush_hash_range(unsigned lo
 extern void flush_hash_hugepage(unsigned long vsid, unsigned long addr,
 				pmd_t *pmdp, unsigned int psize, int ssize,
 				unsigned long flags);
-
-static inline void local_flush_tlb_mm(struct mm_struct *mm)
+static inline void hash__local_flush_tlb_mm(struct mm_struct *mm)
 {
 }
 
-static inline void flush_tlb_mm(struct mm_struct *mm)
+static inline void hash__flush_tlb_mm(struct mm_struct *mm)
 {
 }
 
-static inline void local_flush_tlb_page(struct vm_area_struct *vma,
-					unsigned long vmaddr)
+static inline void hash__local_flush_tlb_page(struct vm_area_struct *vma,
+					  unsigned long vmaddr)
 {
 }
 
-static inline void flush_tlb_page(struct vm_area_struct *vma,
-				  unsigned long vmaddr)
+static inline void hash__flush_tlb_page(struct vm_area_struct *vma,
+				    unsigned long vmaddr)
 {
 }
 
-static inline void flush_tlb_page_nohash(struct vm_area_struct *vma,
-					 unsigned long vmaddr)
+static inline void hash__flush_tlb_page_nohash(struct vm_area_struct *vma,
+					   unsigned long vmaddr)
 {
 }
 
-static inline void flush_tlb_range(struct vm_area_struct *vma,
-				   unsigned long start, unsigned long end)
+static inline void hash__flush_tlb_range(struct vm_area_struct *vma,
+				     unsigned long start, unsigned long end)
 {
 }
 
-static inline void flush_tlb_kernel_range(unsigned long start,
-					  unsigned long end)
+static inline void hash__flush_tlb_kernel_range(unsigned long start,
+					    unsigned long end)
 {
 }
 
+
+struct mmu_gather;
+extern void hash__tlb_flush(struct mmu_gather *tlb);
 /* Private function for use by PCI IO mapping code */
 extern void __flush_hash_table_range(struct mm_struct *mm, unsigned long start,
 				     unsigned long end);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,36 @@
+#ifndef _ASM_POWERPC_TLBFLUSH_RADIX_H
+#define _ASM_POWERPC_TLBFLUSH_RADIX_H
+
+struct vm_area_struct;
+struct mm_struct;
+struct mmu_gather;
+
+static inline int mmu_get_ap(int psize)
+{
+	return mmu_psize_defs[psize].ap;
+}
+
+extern void radix__flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+			    unsigned long end);
+extern void radix__flush_tlb_kernel_range(unsigned long start, unsigned long end);
+
+extern void radix__local_flush_tlb_mm(struct mm_struct *mm);
+extern void radix__local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
+extern void radix___local_flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
+				    unsigned long ap, int nid);
+extern void radix__local_flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr);
+extern void radix__tlb_flush(struct mmu_gather *tlb);
+#ifdef CONFIG_SMP
+extern void radix__flush_tlb_mm(struct mm_struct *mm);
+extern void radix__flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
+extern void radix___flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
+			      unsigned long ap, int nid);
+extern void radix__flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr);
+#else
+#define radix__flush_tlb_mm(mm)		radix__local_flush_tlb_mm(mm)
+#define radix__flush_tlb_page(vma,addr)	radix__local_flush_tlb_page(vma,addr)
+#define radix___flush_tlb_page(mm,addr,p,i)	radix___local_flush_tlb_page(mm,addr,p,i)
+#define radix__flush_tlb_pwc(tlb, addr)	radix__local_flush_tlb_pwc(tlb, addr)
+#endif
+
+#endif
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/pgalloc.h linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/pgalloc.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/book3s/pgalloc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/book3s/pgalloc.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,14 @@
+#ifndef _ASM_POWERPC_BOOK3S_PGALLOC_H
+#define _ASM_POWERPC_BOOK3S_PGALLOC_H
+
+#include <linux/mm.h>
+
+extern void tlb_remove_table(struct mmu_gather *tlb, void *table);
+
+#ifdef CONFIG_PPC64
+#include <asm/book3s/64/pgalloc.h>
+#else
+#include <asm/book3s/32/pgalloc.h>
+#endif
+
+#endif /* _ASM_POWERPC_BOOK3S_PGALLOC_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/hugetlb.h linux-libre-4.7-gnu/arch/powerpc/include/asm/hugetlb.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/hugetlb.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/hugetlb.h	2016-07-24 15:23:50.000000000 -0400
@@ -8,6 +8,8 @@
 extern struct kmem_cache *hugepte_cache;
 
 #ifdef CONFIG_PPC_BOOK3S_64
+
+#include <asm/book3s/64/hugetlb-radix.h>
 /*
  * This should work for other subarchs too. But right now we use the
  * new format only for 64bit book3s
@@ -31,7 +33,19 @@ static inline unsigned int hugepd_shift(
 {
 	return mmu_psize_to_shift(hugepd_mmu_psize(hpd));
 }
+static inline void flush_hugetlb_page(struct vm_area_struct *vma,
+				      unsigned long vmaddr)
+{
+	if (radix_enabled())
+		return radix__flush_hugetlb_page(vma, vmaddr);
+}
 
+static inline void __local_flush_hugetlb_page(struct vm_area_struct *vma,
+					      unsigned long vmaddr)
+{
+	if (radix_enabled())
+		return radix__local_flush_hugetlb_page(vma, vmaddr);
+}
 #else
 
 static inline pte_t *hugepd_page(hugepd_t hpd)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/kvm_book3s_64.h linux-libre-4.7-gnu/arch/powerpc/include/asm/kvm_book3s_64.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/kvm_book3s_64.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/kvm_book3s_64.h	2016-07-24 15:23:50.000000000 -0400
@@ -276,19 +276,24 @@ static inline unsigned long hpte_make_re
 	return ptel;
 }
 
-static inline int hpte_cache_flags_ok(unsigned long ptel, unsigned long io_type)
+static inline bool hpte_cache_flags_ok(unsigned long hptel, bool is_ci)
 {
-	unsigned int wimg = ptel & HPTE_R_WIMG;
+	unsigned int wimg = hptel & HPTE_R_WIMG;
 
 	/* Handle SAO */
 	if (wimg == (HPTE_R_W | HPTE_R_I | HPTE_R_M) &&
 	    cpu_has_feature(CPU_FTR_ARCH_206))
 		wimg = HPTE_R_M;
 
-	if (!io_type)
+	if (!is_ci)
 		return wimg == HPTE_R_M;
-
-	return (wimg & (HPTE_R_W | HPTE_R_I)) == io_type;
+	/*
+	 * if host is mapped cache inhibited, make sure hptel also have
+	 * cache inhibited.
+	 */
+	if (wimg & HPTE_R_W) /* FIXME!! is this ok for all guest. ? */
+		return false;
+	return !!(wimg & HPTE_R_I);
 }
 
 /*
@@ -305,9 +310,9 @@ static inline pte_t kvmppc_read_update_l
 		 */
 		old_pte = READ_ONCE(*ptep);
 		/*
-		 * wait until _PAGE_BUSY is clear then set it atomically
+		 * wait until H_PAGE_BUSY is clear then set it atomically
 		 */
-		if (unlikely(pte_val(old_pte) & _PAGE_BUSY)) {
+		if (unlikely(pte_val(old_pte) & H_PAGE_BUSY)) {
 			cpu_relax();
 			continue;
 		}
@@ -319,27 +324,12 @@ static inline pte_t kvmppc_read_update_l
 		if (writing && pte_write(old_pte))
 			new_pte = pte_mkdirty(new_pte);
 
-		if (pte_val(old_pte) == __cmpxchg_u64((unsigned long *)ptep,
-						      pte_val(old_pte),
-						      pte_val(new_pte))) {
+		if (pte_xchg(ptep, old_pte, new_pte))
 			break;
-		}
 	}
 	return new_pte;
 }
 
-
-/* Return HPTE cache control bits corresponding to Linux pte bits */
-static inline unsigned long hpte_cache_bits(unsigned long pte_val)
-{
-#if _PAGE_NO_CACHE == HPTE_R_I && _PAGE_WRITETHRU == HPTE_R_W
-	return pte_val & (HPTE_R_W | HPTE_R_I);
-#else
-	return ((pte_val & _PAGE_NO_CACHE) ? HPTE_R_I : 0) +
-		((pte_val & _PAGE_WRITETHRU) ? HPTE_R_W : 0);
-#endif
-}
-
 static inline bool hpte_read_permission(unsigned long pp, unsigned long key)
 {
 	if (key)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/kvm_host.h linux-libre-4.7-gnu/arch/powerpc/include/asm/kvm_host.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/kvm_host.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/kvm_host.h	2016-07-24 15:23:50.000000000 -0400
@@ -40,6 +40,9 @@
 #define KVM_MAX_VCORES		NR_CPUS
 #define KVM_USER_MEM_SLOTS	512
 
+#include <asm/cputhreads.h>
+#define KVM_MAX_VCPU_ID                (threads_per_subcore * KVM_MAX_VCORES)
+
 #ifdef CONFIG_KVM_MMIO
 #define KVM_COALESCED_MMIO_PAGE_OFFSET 1
 #endif
@@ -113,6 +116,7 @@ struct kvm_vcpu_stat {
 	u32 ext_intr_exits;
 	u32 halt_successful_poll;
 	u32 halt_attempted_poll;
+	u32 halt_poll_invalid;
 	u32 halt_wakeup;
 	u32 dbell_exits;
 	u32 gdbell_exits;
@@ -724,5 +728,6 @@ static inline void kvm_arch_sched_in(str
 static inline void kvm_arch_exit(void) {}
 static inline void kvm_arch_vcpu_blocking(struct kvm_vcpu *vcpu) {}
 static inline void kvm_arch_vcpu_unblocking(struct kvm_vcpu *vcpu) {}
+static inline void kvm_arch_vcpu_block_finish(struct kvm_vcpu *vcpu) {}
 
 #endif /* __POWERPC_KVM_HOST_H__ */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/livepatch.h linux-libre-4.7-gnu/arch/powerpc/include/asm/livepatch.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/livepatch.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/livepatch.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,62 @@
+/*
+ * livepatch.h - powerpc-specific Kernel Live Patching Core
+ *
+ * Copyright (C) 2015-2016, SUSE, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef _ASM_POWERPC_LIVEPATCH_H
+#define _ASM_POWERPC_LIVEPATCH_H
+
+#include <linux/module.h>
+#include <linux/ftrace.h>
+
+#ifdef CONFIG_LIVEPATCH
+static inline int klp_check_compiler_support(void)
+{
+	return 0;
+}
+
+static inline int klp_write_module_reloc(struct module *mod, unsigned long
+		type, unsigned long loc, unsigned long value)
+{
+	/* This requires infrastructure changes; we need the loadinfos. */
+	return -ENOSYS;
+}
+
+static inline void klp_arch_set_pc(struct pt_regs *regs, unsigned long ip)
+{
+	regs->nip = ip;
+}
+
+#define klp_get_ftrace_location klp_get_ftrace_location
+static inline unsigned long klp_get_ftrace_location(unsigned long faddr)
+{
+	/*
+	 * Live patch works only with -mprofile-kernel on PPC. In this case,
+	 * the ftrace location is always within the first 16 bytes.
+	 */
+	return ftrace_location_range(faddr, faddr + 16);
+}
+
+static inline void klp_init_thread_info(struct thread_info *ti)
+{
+	/* + 1 to account for STACK_END_MAGIC */
+	ti->livepatch_sp = (unsigned long *)(ti + 1) + 1;
+}
+#else
+static void klp_init_thread_info(struct thread_info *ti) { }
+#endif /* CONFIG_LIVEPATCH */
+
+#endif /* _ASM_POWERPC_LIVEPATCH_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/machdep.h linux-libre-4.7-gnu/arch/powerpc/include/asm/machdep.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/machdep.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/machdep.h	2016-07-24 15:23:50.000000000 -0400
@@ -256,6 +256,7 @@ struct machdep_calls {
 #ifdef CONFIG_ARCH_RANDOM
 	int (*get_random_seed)(unsigned long *v);
 #endif
+	int (*update_partition_table)(u64);
 };
 
 extern void e500_idle(void);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/mmu_context.h linux-libre-4.7-gnu/arch/powerpc/include/asm/mmu_context.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/mmu_context.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/mmu_context.h	2016-07-24 15:23:50.000000000 -0400
@@ -33,16 +33,27 @@ extern long mm_iommu_ua_to_hpa(struct mm
 extern long mm_iommu_mapped_inc(struct mm_iommu_table_group_mem_t *mem);
 extern void mm_iommu_mapped_dec(struct mm_iommu_table_group_mem_t *mem);
 #endif
-
-extern void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next);
 extern void switch_slb(struct task_struct *tsk, struct mm_struct *mm);
 extern void set_context(unsigned long id, pgd_t *pgd);
 
 #ifdef CONFIG_PPC_BOOK3S_64
+extern void radix__switch_mmu_context(struct mm_struct *prev,
+				     struct mm_struct *next);
+static inline void switch_mmu_context(struct mm_struct *prev,
+				      struct mm_struct *next,
+				      struct task_struct *tsk)
+{
+	if (radix_enabled())
+		return radix__switch_mmu_context(prev, next);
+	return switch_slb(tsk, next);
+}
+
 extern int __init_new_context(void);
 extern void __destroy_context(int context_id);
 static inline void mmu_context_init(void) { }
 #else
+extern void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next,
+			       struct task_struct *tsk);
 extern unsigned long __init_new_context(void);
 extern void __destroy_context(unsigned long context_id);
 extern void mmu_context_init(void);
@@ -88,17 +99,11 @@ static inline void switch_mm(struct mm_s
 	if (cpu_has_feature(CPU_FTR_ALTIVEC))
 		asm volatile ("dssall");
 #endif /* CONFIG_ALTIVEC */
-
-	/* The actual HW switching method differs between the various
-	 * sub architectures.
+	/*
+	 * The actual HW switching method differs between the various
+	 * sub architectures. Out of line for now
 	 */
-#ifdef CONFIG_PPC_STD_MMU_64
-	switch_slb(tsk, next);
-#else
-	/* Out of line for now */
-	switch_mmu_context(prev, next);
-#endif
-
+	switch_mmu_context(prev, next, tsk);
 }
 
 #define deactivate_mm(tsk,mm)	do { } while (0)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/mmu.h linux-libre-4.7-gnu/arch/powerpc/include/asm/mmu.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/mmu.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/mmu.h	2016-07-24 15:23:50.000000000 -0400
@@ -88,6 +88,11 @@
  */
 #define MMU_FTR_1T_SEGMENT		ASM_CONST(0x40000000)
 
+/*
+ * Radix page table available
+ */
+#define MMU_FTR_RADIX			ASM_CONST(0x80000000)
+
 /* MMU feature bit sets for various CPUs */
 #define MMU_FTRS_DEFAULT_HPTE_ARCH_V2	\
 	MMU_FTR_HPTE_TABLE | MMU_FTR_PPCAS_ARCH_V2
@@ -110,9 +115,25 @@
 DECLARE_PER_CPU(int, next_tlbcam_idx);
 #endif
 
+enum {
+	MMU_FTRS_POSSIBLE = MMU_FTR_HPTE_TABLE | MMU_FTR_TYPE_8xx |
+		MMU_FTR_TYPE_40x | MMU_FTR_TYPE_44x | MMU_FTR_TYPE_FSL_E |
+		MMU_FTR_TYPE_47x | MMU_FTR_USE_HIGH_BATS | MMU_FTR_BIG_PHYS |
+		MMU_FTR_USE_TLBIVAX_BCAST | MMU_FTR_USE_TLBILX |
+		MMU_FTR_LOCK_BCAST_INVAL | MMU_FTR_NEED_DTLB_SW_LRU |
+		MMU_FTR_USE_TLBRSRV | MMU_FTR_USE_PAIRED_MAS |
+		MMU_FTR_NO_SLBIE_B | MMU_FTR_16M_PAGE | MMU_FTR_TLBIEL |
+		MMU_FTR_LOCKLESS_TLBIE | MMU_FTR_CI_LARGE_PAGE |
+		MMU_FTR_1T_SEGMENT |
+#ifdef CONFIG_PPC_RADIX_MMU
+		MMU_FTR_RADIX |
+#endif
+		0,
+};
+
 static inline int mmu_has_feature(unsigned long feature)
 {
-	return (cur_cpu_spec->mmu_features & feature);
+	return (MMU_FTRS_POSSIBLE & cur_cpu_spec->mmu_features & feature);
 }
 
 static inline void mmu_clear_feature(unsigned long feature)
@@ -122,13 +143,6 @@ static inline void mmu_clear_feature(uns
 
 extern unsigned int __start___mmu_ftr_fixup, __stop___mmu_ftr_fixup;
 
-/* MMU initialization */
-extern void early_init_mmu(void);
-extern void early_init_mmu_secondary(void);
-
-extern void setup_initial_memory_limit(phys_addr_t first_memblock_base,
-				       phys_addr_t first_memblock_size);
-
 #ifdef CONFIG_PPC64
 /* This is our real memory area size on ppc64 server, on embedded, we
  * make it match the size our of bolted TLB area
@@ -181,10 +195,20 @@ static inline void assert_pte_locked(str
 
 #define MMU_PAGE_COUNT	15
 
-#if defined(CONFIG_PPC_STD_MMU_64)
-/* 64-bit classic hash table MMU */
-#include <asm/book3s/64/mmu-hash.h>
-#elif defined(CONFIG_PPC_STD_MMU_32)
+#ifdef CONFIG_PPC_BOOK3S_64
+#include <asm/book3s/64/mmu.h>
+#else /* CONFIG_PPC_BOOK3S_64 */
+
+#ifndef __ASSEMBLY__
+/* MMU initialization */
+extern void early_init_mmu(void);
+extern void early_init_mmu_secondary(void);
+extern void setup_initial_memory_limit(phys_addr_t first_memblock_base,
+				       phys_addr_t first_memblock_size);
+#endif /* __ASSEMBLY__ */
+#endif
+
+#if defined(CONFIG_PPC_STD_MMU_32)
 /* 32-bit classic hash table MMU */
 #include <asm/book3s/32/mmu-hash.h>
 #elif defined(CONFIG_40x)
@@ -201,6 +225,9 @@ static inline void assert_pte_locked(str
 #  include <asm/mmu-8xx.h>
 #endif
 
+#ifndef radix_enabled
+#define radix_enabled() (0)
+#endif
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_MMU_H_ */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/nohash/32/pgalloc.h linux-libre-4.7-gnu/arch/powerpc/include/asm/nohash/32/pgalloc.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/nohash/32/pgalloc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/nohash/32/pgalloc.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,109 @@
+#ifndef _ASM_POWERPC_PGALLOC_32_H
+#define _ASM_POWERPC_PGALLOC_32_H
+
+#include <linux/threads.h>
+
+/* For 32-bit, all levels of page tables are just drawn from get_free_page() */
+#define MAX_PGTABLE_INDEX_SIZE	0
+
+extern void __bad_pte(pmd_t *pmd);
+
+extern pgd_t *pgd_alloc(struct mm_struct *mm);
+extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
+
+/*
+ * We don't have any real pmd's, and this code never triggers because
+ * the pgd will always be present..
+ */
+/* #define pmd_alloc_one(mm,address)       ({ BUG(); ((pmd_t *)2); }) */
+#define pmd_free(mm, x) 		do { } while (0)
+#define __pmd_free_tlb(tlb,x,a)		do { } while (0)
+/* #define pgd_populate(mm, pmd, pte)      BUG() */
+
+#ifndef CONFIG_BOOKE
+
+static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp,
+				       pte_t *pte)
+{
+	*pmdp = __pmd(__pa(pte) | _PMD_PRESENT);
+}
+
+static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmdp,
+				pgtable_t pte_page)
+{
+	*pmdp = __pmd((page_to_pfn(pte_page) << PAGE_SHIFT) | _PMD_PRESENT);
+}
+
+#define pmd_pgtable(pmd) pmd_page(pmd)
+#else
+
+static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp,
+				       pte_t *pte)
+{
+	*pmdp = __pmd((unsigned long)pte | _PMD_PRESENT);
+}
+
+static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmdp,
+				pgtable_t pte_page)
+{
+	*pmdp = __pmd((unsigned long)lowmem_page_address(pte_page) | _PMD_PRESENT);
+}
+
+#define pmd_pgtable(pmd) pmd_page(pmd)
+#endif
+
+extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr);
+extern pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long addr);
+
+static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+{
+	free_page((unsigned long)pte);
+}
+
+static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage)
+{
+	pgtable_page_dtor(ptepage);
+	__free_page(ptepage);
+}
+
+static inline void pgtable_free(void *table, unsigned index_size)
+{
+	BUG_ON(index_size); /* 32-bit doesn't use this */
+	free_page((unsigned long)table);
+}
+
+#define check_pgt_cache()	do { } while (0)
+
+#ifdef CONFIG_SMP
+static inline void pgtable_free_tlb(struct mmu_gather *tlb,
+				    void *table, int shift)
+{
+	unsigned long pgf = (unsigned long)table;
+	BUG_ON(shift > MAX_PGTABLE_INDEX_SIZE);
+	pgf |= shift;
+	tlb_remove_table(tlb, (void *)pgf);
+}
+
+static inline void __tlb_remove_table(void *_table)
+{
+	void *table = (void *)((unsigned long)_table & ~MAX_PGTABLE_INDEX_SIZE);
+	unsigned shift = (unsigned long)_table & MAX_PGTABLE_INDEX_SIZE;
+
+	pgtable_free(table, shift);
+}
+#else
+static inline void pgtable_free_tlb(struct mmu_gather *tlb,
+				    void *table, int shift)
+{
+	pgtable_free(table, shift);
+}
+#endif
+
+static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table,
+				  unsigned long address)
+{
+	tlb_flush_pgtable(tlb, address);
+	pgtable_page_dtor(table);
+	pgtable_free_tlb(tlb, page_address(table), 0);
+}
+#endif /* _ASM_POWERPC_PGALLOC_32_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/nohash/64/pgalloc.h linux-libre-4.7-gnu/arch/powerpc/include/asm/nohash/64/pgalloc.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/nohash/64/pgalloc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/nohash/64/pgalloc.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,210 @@
+#ifndef _ASM_POWERPC_PGALLOC_64_H
+#define _ASM_POWERPC_PGALLOC_64_H
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/slab.h>
+#include <linux/cpumask.h>
+#include <linux/percpu.h>
+
+struct vmemmap_backing {
+	struct vmemmap_backing *list;
+	unsigned long phys;
+	unsigned long virt_addr;
+};
+extern struct vmemmap_backing *vmemmap_list;
+
+/*
+ * Functions that deal with pagetables that could be at any level of
+ * the table need to be passed an "index_size" so they know how to
+ * handle allocation.  For PTE pages (which are linked to a struct
+ * page for now, and drawn from the main get_free_pages() pool), the
+ * allocation size will be (2^index_size * sizeof(pointer)) and
+ * allocations are drawn from the kmem_cache in PGT_CACHE(index_size).
+ *
+ * The maximum index size needs to be big enough to allow any
+ * pagetable sizes we need, but small enough to fit in the low bits of
+ * any page table pointer.  In other words all pagetables, even tiny
+ * ones, must be aligned to allow at least enough low 0 bits to
+ * contain this value.  This value is also used as a mask, so it must
+ * be one less than a power of two.
+ */
+#define MAX_PGTABLE_INDEX_SIZE	0xf
+
+extern struct kmem_cache *pgtable_cache[];
+#define PGT_CACHE(shift) ({				\
+			BUG_ON(!(shift));		\
+			pgtable_cache[(shift) - 1];	\
+		})
+
+static inline pgd_t *pgd_alloc(struct mm_struct *mm)
+{
+	return kmem_cache_alloc(PGT_CACHE(PGD_INDEX_SIZE), GFP_KERNEL);
+}
+
+static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+{
+	kmem_cache_free(PGT_CACHE(PGD_INDEX_SIZE), pgd);
+}
+
+#ifndef CONFIG_PPC_64K_PAGES
+
+#define pgd_populate(MM, PGD, PUD)	pgd_set(PGD, (unsigned long)PUD)
+
+static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
+{
+	return kmem_cache_alloc(PGT_CACHE(PUD_INDEX_SIZE), GFP_KERNEL);
+}
+
+static inline void pud_free(struct mm_struct *mm, pud_t *pud)
+{
+	kmem_cache_free(PGT_CACHE(PUD_INDEX_SIZE), pud);
+}
+
+static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
+{
+	pud_set(pud, (unsigned long)pmd);
+}
+
+static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
+				       pte_t *pte)
+{
+	pmd_set(pmd, (unsigned long)pte);
+}
+
+static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
+				pgtable_t pte_page)
+{
+	pmd_set(pmd, (unsigned long)page_address(pte_page));
+}
+
+#define pmd_pgtable(pmd) pmd_page(pmd)
+
+static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
+					  unsigned long address)
+{
+	return (pte_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
+}
+
+static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
+				      unsigned long address)
+{
+	struct page *page;
+	pte_t *pte;
+
+	pte = pte_alloc_one_kernel(mm, address);
+	if (!pte)
+		return NULL;
+	page = virt_to_page(pte);
+	if (!pgtable_page_ctor(page)) {
+		__free_page(page);
+		return NULL;
+	}
+	return page;
+}
+
+static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+{
+	free_page((unsigned long)pte);
+}
+
+static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage)
+{
+	pgtable_page_dtor(ptepage);
+	__free_page(ptepage);
+}
+
+extern void pgtable_free_tlb(struct mmu_gather *tlb, void *table, int shift);
+#ifdef CONFIG_SMP
+extern void __tlb_remove_table(void *_table);
+#endif
+static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table,
+				  unsigned long address)
+{
+	tlb_flush_pgtable(tlb, address);
+	pgtable_free_tlb(tlb, page_address(table), 0);
+}
+
+#else /* if CONFIG_PPC_64K_PAGES */
+
+extern pte_t *pte_fragment_alloc(struct mm_struct *, unsigned long, int);
+extern void pte_fragment_free(unsigned long *, int);
+extern void pgtable_free_tlb(struct mmu_gather *tlb, void *table, int shift);
+#ifdef CONFIG_SMP
+extern void __tlb_remove_table(void *_table);
+#endif
+
+#define pud_populate(mm, pud, pmd)	pud_set(pud, (unsigned long)pmd)
+
+static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
+				       pte_t *pte)
+{
+	pmd_set(pmd, (unsigned long)pte);
+}
+
+static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
+				pgtable_t pte_page)
+{
+	pmd_set(pmd, (unsigned long)pte_page);
+}
+
+static inline pgtable_t pmd_pgtable(pmd_t pmd)
+{
+	return (pgtable_t)(pmd_val(pmd) & ~PMD_MASKED_BITS);
+}
+
+static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
+					  unsigned long address)
+{
+	return (pte_t *)pte_fragment_alloc(mm, address, 1);
+}
+
+static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
+					unsigned long address)
+{
+	return (pgtable_t)pte_fragment_alloc(mm, address, 0);
+}
+
+static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+{
+	pte_fragment_free((unsigned long *)pte, 1);
+}
+
+static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage)
+{
+	pte_fragment_free((unsigned long *)ptepage, 0);
+}
+
+static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table,
+				  unsigned long address)
+{
+	tlb_flush_pgtable(tlb, address);
+	pgtable_free_tlb(tlb, table, 0);
+}
+#endif /* CONFIG_PPC_64K_PAGES */
+
+static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
+{
+	return kmem_cache_alloc(PGT_CACHE(PMD_CACHE_INDEX), GFP_KERNEL);
+}
+
+static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
+{
+	kmem_cache_free(PGT_CACHE(PMD_CACHE_INDEX), pmd);
+}
+
+#define __pmd_free_tlb(tlb, pmd, addr)		      \
+	pgtable_free_tlb(tlb, pmd, PMD_CACHE_INDEX)
+#ifndef CONFIG_PPC_64K_PAGES
+#define __pud_free_tlb(tlb, pud, addr)		      \
+	pgtable_free_tlb(tlb, pud, PUD_INDEX_SIZE)
+
+#endif /* CONFIG_PPC_64K_PAGES */
+
+#define check_pgt_cache()	do { } while (0)
+
+#endif /* _ASM_POWERPC_PGALLOC_64_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/nohash/64/pgtable.h linux-libre-4.7-gnu/arch/powerpc/include/asm/nohash/64/pgtable.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/nohash/64/pgtable.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/nohash/64/pgtable.h	2016-07-24 15:23:50.000000000 -0400
@@ -108,9 +108,6 @@
 #ifndef __ASSEMBLY__
 /* pte_clear moved to later in this file */
 
-/* Pointers in the page table tree are virtual addresses */
-#define __pgtable_ptr_val(ptr)	((unsigned long)(ptr))
-
 #define PMD_BAD_BITS		(PTE_TABLE_SIZE-1)
 #define PUD_BAD_BITS		(PMD_TABLE_SIZE-1)
 
@@ -362,6 +359,13 @@ static inline void __ptep_set_access_fla
 
 void pgtable_cache_add(unsigned shift, void (*ctor)(void *));
 void pgtable_cache_init(void);
+extern int map_kernel_page(unsigned long ea, unsigned long pa,
+			   unsigned long flags);
+extern int __meminit vmemmap_create_mapping(unsigned long start,
+					    unsigned long page_size,
+					    unsigned long phys);
+extern void vmemmap_remove_mapping(unsigned long start,
+				   unsigned long page_size);
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_POWERPC_NOHASH_64_PGTABLE_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/nohash/pgalloc.h linux-libre-4.7-gnu/arch/powerpc/include/asm/nohash/pgalloc.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/nohash/pgalloc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/nohash/pgalloc.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,23 @@
+#ifndef _ASM_POWERPC_NOHASH_PGALLOC_H
+#define _ASM_POWERPC_NOHASH_PGALLOC_H
+
+#include <linux/mm.h>
+
+extern void tlb_remove_table(struct mmu_gather *tlb, void *table);
+#ifdef CONFIG_PPC64
+extern void tlb_flush_pgtable(struct mmu_gather *tlb, unsigned long address);
+#else
+/* 44x etc which is BOOKE not BOOK3E */
+static inline void tlb_flush_pgtable(struct mmu_gather *tlb,
+				     unsigned long address)
+{
+
+}
+#endif /* !CONFIG_PPC_BOOK3E */
+
+#ifdef CONFIG_PPC64
+#include <asm/nohash/64/pgalloc.h>
+#else
+#include <asm/nohash/32/pgalloc.h>
+#endif
+#endif /* _ASM_POWERPC_NOHASH_PGALLOC_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/opal-api.h linux-libre-4.7-gnu/arch/powerpc/include/asm/opal-api.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/opal-api.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/opal-api.h	2016-07-24 15:23:50.000000000 -0400
@@ -368,16 +368,16 @@ enum OpalLPCAddressType {
 };
 
 enum opal_msg_type {
-	OPAL_MSG_ASYNC_COMP = 0,	/* params[0] = token, params[1] = rc,
+	OPAL_MSG_ASYNC_COMP	= 0,	/* params[0] = token, params[1] = rc,
 					 * additional params function-specific
 					 */
-	OPAL_MSG_MEM_ERR,
-	OPAL_MSG_EPOW,
-	OPAL_MSG_SHUTDOWN,		/* params[0] = 1 reboot, 0 shutdown */
-	OPAL_MSG_HMI_EVT,
-	OPAL_MSG_DPO,
-	OPAL_MSG_PRD,
-	OPAL_MSG_OCC,
+	OPAL_MSG_MEM_ERR	= 1,
+	OPAL_MSG_EPOW		= 2,
+	OPAL_MSG_SHUTDOWN	= 3,	/* params[0] = 1 reboot, 0 shutdown */
+	OPAL_MSG_HMI_EVT	= 4,
+	OPAL_MSG_DPO		= 5,
+	OPAL_MSG_PRD		= 6,
+	OPAL_MSG_OCC		= 7,
 	OPAL_MSG_TYPE_MAX,
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/page_64.h linux-libre-4.7-gnu/arch/powerpc/include/asm/page_64.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/page_64.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/page_64.h	2016-07-24 15:23:50.000000000 -0400
@@ -93,7 +93,7 @@ extern u64 ppc64_pft_size;
 
 #define SLICE_LOW_TOP		(0x100000000ul)
 #define SLICE_NUM_LOW		(SLICE_LOW_TOP >> SLICE_LOW_SHIFT)
-#define SLICE_NUM_HIGH		(PGTABLE_RANGE >> SLICE_HIGH_SHIFT)
+#define SLICE_NUM_HIGH		(H_PGTABLE_RANGE >> SLICE_HIGH_SHIFT)
 
 #define GET_LOW_SLICE_INDEX(addr)	((addr) >> SLICE_LOW_SHIFT)
 #define GET_HIGH_SLICE_INDEX(addr)	((addr) >> SLICE_HIGH_SHIFT)
@@ -128,8 +128,6 @@ extern void slice_set_user_psize(struct
 extern void slice_set_range_psize(struct mm_struct *mm, unsigned long start,
 				  unsigned long len, unsigned int psize);
 
-#define slice_mm_new_context(mm)	((mm)->context.id == MMU_NO_CONTEXT)
-
 #endif /* __ASSEMBLY__ */
 #else
 #define slice_init()
@@ -151,7 +149,6 @@ do {						\
 
 #define slice_set_range_psize(mm, start, len, psize)	\
 	slice_set_user_psize((mm), (psize))
-#define slice_mm_new_context(mm)	1
 #endif /* CONFIG_PPC_MM_SLICES */
 
 #ifdef CONFIG_HUGETLB_PAGE
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/page.h linux-libre-4.7-gnu/arch/powerpc/include/asm/page.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/page.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/page.h	2016-07-24 15:23:50.000000000 -0400
@@ -288,7 +288,11 @@ extern long long virt_phys_offset;
 
 #ifndef __ASSEMBLY__
 
+#ifdef CONFIG_PPC_BOOK3S_64
+#include <asm/pgtable-be-types.h>
+#else
 #include <asm/pgtable-types.h>
+#endif
 
 typedef struct { signed long pd; } hugepd_t;
 
@@ -312,12 +316,20 @@ void arch_free_page(struct page *page, i
 #endif
 
 struct vm_area_struct;
-
+#ifdef CONFIG_PPC_BOOK3S_64
+/*
+ * For BOOK3s 64 with 4k and 64K linux page size
+ * we want to use pointers, because the page table
+ * actually store pfn
+ */
+typedef pte_t *pgtable_t;
+#else
 #if defined(CONFIG_PPC_64K_PAGES) && defined(CONFIG_PPC64)
 typedef pte_t *pgtable_t;
 #else
 typedef struct page *pgtable_t;
 #endif
+#endif
 
 #include <asm-generic/memory_model.h>
 #endif /* __ASSEMBLY__ */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/pci-bridge.h linux-libre-4.7-gnu/arch/powerpc/include/asm/pci-bridge.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/pci-bridge.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/pci-bridge.h	2016-07-24 15:23:50.000000000 -0400
@@ -17,33 +17,34 @@ struct device_node;
  * PCI controller operations
  */
 struct pci_controller_ops {
-	void		(*dma_dev_setup)(struct pci_dev *dev);
+	void		(*dma_dev_setup)(struct pci_dev *pdev);
 	void		(*dma_bus_setup)(struct pci_bus *bus);
 
-	int		(*probe_mode)(struct pci_bus *);
+	int		(*probe_mode)(struct pci_bus *bus);
 
 	/* Called when pci_enable_device() is called. Returns true to
 	 * allow assignment/enabling of the device. */
-	bool		(*enable_device_hook)(struct pci_dev *);
+	bool		(*enable_device_hook)(struct pci_dev *pdev);
 
-	void		(*disable_device)(struct pci_dev *);
+	void		(*disable_device)(struct pci_dev *pdev);
 
-	void		(*release_device)(struct pci_dev *);
+	void		(*release_device)(struct pci_dev *pdev);
 
 	/* Called during PCI resource reassignment */
-	resource_size_t (*window_alignment)(struct pci_bus *, unsigned long type);
-	void		(*reset_secondary_bus)(struct pci_dev *dev);
+	resource_size_t (*window_alignment)(struct pci_bus *bus,
+					    unsigned long type);
+	void		(*reset_secondary_bus)(struct pci_dev *pdev);
 
 #ifdef CONFIG_PCI_MSI
-	int		(*setup_msi_irqs)(struct pci_dev *dev,
+	int		(*setup_msi_irqs)(struct pci_dev *pdev,
 					  int nvec, int type);
-	void		(*teardown_msi_irqs)(struct pci_dev *dev);
+	void		(*teardown_msi_irqs)(struct pci_dev *pdev);
 #endif
 
-	int             (*dma_set_mask)(struct pci_dev *dev, u64 dma_mask);
-	u64		(*dma_get_required_mask)(struct pci_dev *dev);
+	int             (*dma_set_mask)(struct pci_dev *pdev, u64 dma_mask);
+	u64		(*dma_get_required_mask)(struct pci_dev *pdev);
 
-	void		(*shutdown)(struct pci_controller *);
+	void		(*shutdown)(struct pci_controller *hose);
 };
 
 /*
@@ -208,14 +209,14 @@ struct pci_dn {
 #ifdef CONFIG_EEH
 	struct eeh_dev *edev;		/* eeh device */
 #endif
-#define IODA_INVALID_PE		(-1)
+#define IODA_INVALID_PE		0xFFFFFFFF
 #ifdef CONFIG_PPC_POWERNV
-	int	pe_number;
+	unsigned int pe_number;
 	int     vf_index;		/* VF index in the PF */
 #ifdef CONFIG_PCI_IOV
 	u16     vfs_expanded;		/* number of VFs IOV BAR expanded */
 	u16     num_vfs;		/* number of VFs enabled*/
-	int     *pe_num_map;		/* PE# for the first VF PE or array */
+	unsigned int *pe_num_map;	/* PE# for the first VF PE or array */
 	bool    m64_single_mode;	/* Use M64 BAR in Single Mode */
 #define IODA_INVALID_M64        (-1)
 	int     (*m64_map)[PCI_SRIOV_NUM_BARS];
@@ -234,7 +235,9 @@ extern struct pci_dn *pci_get_pdn_by_dev
 extern struct pci_dn *pci_get_pdn(struct pci_dev *pdev);
 extern struct pci_dn *add_dev_pci_data(struct pci_dev *pdev);
 extern void remove_dev_pci_data(struct pci_dev *pdev);
-extern void *update_dn_pci_info(struct device_node *dn, void *data);
+extern struct pci_dn *pci_add_device_node_info(struct pci_controller *hose,
+					       struct device_node *dn);
+extern void pci_remove_device_node_info(struct device_node *dn);
 
 static inline int pci_device_from_OF_node(struct device_node *np,
 					  u8 *bus, u8 *devfn)
@@ -256,13 +259,13 @@ static inline struct eeh_dev *pdn_to_eeh
 #endif
 
 /** Find the bus corresponding to the indicated device node */
-extern struct pci_bus *pcibios_find_pci_bus(struct device_node *dn);
+extern struct pci_bus *pci_find_bus_by_node(struct device_node *dn);
 
 /** Remove all of the PCI devices under this bus */
-extern void pcibios_remove_pci_devices(struct pci_bus *bus);
+extern void pci_hp_remove_devices(struct pci_bus *bus);
 
 /** Discover new pci devices under this bus, and add them */
-extern void pcibios_add_pci_devices(struct pci_bus *bus);
+extern void pci_hp_add_devices(struct pci_bus *bus);
 
 
 extern void isa_bridge_find_early(struct pci_controller *hose);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/pgalloc-32.h linux-libre-4.7-gnu/arch/powerpc/include/asm/pgalloc-32.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/pgalloc-32.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/pgalloc-32.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,109 +0,0 @@
-#ifndef _ASM_POWERPC_PGALLOC_32_H
-#define _ASM_POWERPC_PGALLOC_32_H
-
-#include <linux/threads.h>
-
-/* For 32-bit, all levels of page tables are just drawn from get_free_page() */
-#define MAX_PGTABLE_INDEX_SIZE	0
-
-extern void __bad_pte(pmd_t *pmd);
-
-extern pgd_t *pgd_alloc(struct mm_struct *mm);
-extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
-
-/*
- * We don't have any real pmd's, and this code never triggers because
- * the pgd will always be present..
- */
-/* #define pmd_alloc_one(mm,address)       ({ BUG(); ((pmd_t *)2); }) */
-#define pmd_free(mm, x) 		do { } while (0)
-#define __pmd_free_tlb(tlb,x,a)		do { } while (0)
-/* #define pgd_populate(mm, pmd, pte)      BUG() */
-
-#ifndef CONFIG_BOOKE
-
-static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp,
-				       pte_t *pte)
-{
-	*pmdp = __pmd(__pa(pte) | _PMD_PRESENT);
-}
-
-static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmdp,
-				pgtable_t pte_page)
-{
-	*pmdp = __pmd((page_to_pfn(pte_page) << PAGE_SHIFT) | _PMD_PRESENT);
-}
-
-#define pmd_pgtable(pmd) pmd_page(pmd)
-#else
-
-static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp,
-				       pte_t *pte)
-{
-	*pmdp = __pmd((unsigned long)pte | _PMD_PRESENT);
-}
-
-static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmdp,
-				pgtable_t pte_page)
-{
-	*pmdp = __pmd((unsigned long)lowmem_page_address(pte_page) | _PMD_PRESENT);
-}
-
-#define pmd_pgtable(pmd) pmd_page(pmd)
-#endif
-
-extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr);
-extern pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long addr);
-
-static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
-{
-	free_page((unsigned long)pte);
-}
-
-static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage)
-{
-	pgtable_page_dtor(ptepage);
-	__free_page(ptepage);
-}
-
-static inline void pgtable_free(void *table, unsigned index_size)
-{
-	BUG_ON(index_size); /* 32-bit doesn't use this */
-	free_page((unsigned long)table);
-}
-
-#define check_pgt_cache()	do { } while (0)
-
-#ifdef CONFIG_SMP
-static inline void pgtable_free_tlb(struct mmu_gather *tlb,
-				    void *table, int shift)
-{
-	unsigned long pgf = (unsigned long)table;
-	BUG_ON(shift > MAX_PGTABLE_INDEX_SIZE);
-	pgf |= shift;
-	tlb_remove_table(tlb, (void *)pgf);
-}
-
-static inline void __tlb_remove_table(void *_table)
-{
-	void *table = (void *)((unsigned long)_table & ~MAX_PGTABLE_INDEX_SIZE);
-	unsigned shift = (unsigned long)_table & MAX_PGTABLE_INDEX_SIZE;
-
-	pgtable_free(table, shift);
-}
-#else
-static inline void pgtable_free_tlb(struct mmu_gather *tlb,
-				    void *table, int shift)
-{
-	pgtable_free(table, shift);
-}
-#endif
-
-static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table,
-				  unsigned long address)
-{
-	tlb_flush_pgtable(tlb, address);
-	pgtable_page_dtor(table);
-	pgtable_free_tlb(tlb, page_address(table), 0);
-}
-#endif /* _ASM_POWERPC_PGALLOC_32_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/pgalloc-64.h linux-libre-4.7-gnu/arch/powerpc/include/asm/pgalloc-64.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/pgalloc-64.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/pgalloc-64.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,266 +0,0 @@
-#ifndef _ASM_POWERPC_PGALLOC_64_H
-#define _ASM_POWERPC_PGALLOC_64_H
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <linux/slab.h>
-#include <linux/cpumask.h>
-#include <linux/percpu.h>
-
-struct vmemmap_backing {
-	struct vmemmap_backing *list;
-	unsigned long phys;
-	unsigned long virt_addr;
-};
-extern struct vmemmap_backing *vmemmap_list;
-
-/*
- * Functions that deal with pagetables that could be at any level of
- * the table need to be passed an "index_size" so they know how to
- * handle allocation.  For PTE pages (which are linked to a struct
- * page for now, and drawn from the main get_free_pages() pool), the
- * allocation size will be (2^index_size * sizeof(pointer)) and
- * allocations are drawn from the kmem_cache in PGT_CACHE(index_size).
- *
- * The maximum index size needs to be big enough to allow any
- * pagetable sizes we need, but small enough to fit in the low bits of
- * any page table pointer.  In other words all pagetables, even tiny
- * ones, must be aligned to allow at least enough low 0 bits to
- * contain this value.  This value is also used as a mask, so it must
- * be one less than a power of two.
- */
-#define MAX_PGTABLE_INDEX_SIZE	0xf
-
-extern struct kmem_cache *pgtable_cache[];
-#define PGT_CACHE(shift) ({				\
-			BUG_ON(!(shift));		\
-			pgtable_cache[(shift) - 1];	\
-		})
-
-static inline pgd_t *pgd_alloc(struct mm_struct *mm)
-{
-	return kmem_cache_alloc(PGT_CACHE(PGD_INDEX_SIZE), GFP_KERNEL);
-}
-
-static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
-{
-	kmem_cache_free(PGT_CACHE(PGD_INDEX_SIZE), pgd);
-}
-
-#ifndef CONFIG_PPC_64K_PAGES
-
-#define pgd_populate(MM, PGD, PUD)	pgd_set(PGD, __pgtable_ptr_val(PUD))
-
-static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
-{
-	return kmem_cache_alloc(PGT_CACHE(PUD_INDEX_SIZE),
-				GFP_KERNEL|__GFP_REPEAT);
-}
-
-static inline void pud_free(struct mm_struct *mm, pud_t *pud)
-{
-	kmem_cache_free(PGT_CACHE(PUD_INDEX_SIZE), pud);
-}
-
-static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
-{
-	pud_set(pud, __pgtable_ptr_val(pmd));
-}
-
-static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
-				       pte_t *pte)
-{
-	pmd_set(pmd, __pgtable_ptr_val(pte));
-}
-
-static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
-				pgtable_t pte_page)
-{
-	pmd_set(pmd, __pgtable_ptr_val(page_address(pte_page)));
-}
-
-#define pmd_pgtable(pmd) pmd_page(pmd)
-
-static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
-					  unsigned long address)
-{
-	return (pte_t *)__get_free_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO);
-}
-
-static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
-				      unsigned long address)
-{
-	struct page *page;
-	pte_t *pte;
-
-	pte = pte_alloc_one_kernel(mm, address);
-	if (!pte)
-		return NULL;
-	page = virt_to_page(pte);
-	if (!pgtable_page_ctor(page)) {
-		__free_page(page);
-		return NULL;
-	}
-	return page;
-}
-
-static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
-{
-	free_page((unsigned long)pte);
-}
-
-static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage)
-{
-	pgtable_page_dtor(ptepage);
-	__free_page(ptepage);
-}
-
-static inline void pgtable_free(void *table, unsigned index_size)
-{
-	if (!index_size)
-		free_page((unsigned long)table);
-	else {
-		BUG_ON(index_size > MAX_PGTABLE_INDEX_SIZE);
-		kmem_cache_free(PGT_CACHE(index_size), table);
-	}
-}
-
-#ifdef CONFIG_SMP
-static inline void pgtable_free_tlb(struct mmu_gather *tlb,
-				    void *table, int shift)
-{
-	unsigned long pgf = (unsigned long)table;
-	BUG_ON(shift > MAX_PGTABLE_INDEX_SIZE);
-	pgf |= shift;
-	tlb_remove_table(tlb, (void *)pgf);
-}
-
-static inline void __tlb_remove_table(void *_table)
-{
-	void *table = (void *)((unsigned long)_table & ~MAX_PGTABLE_INDEX_SIZE);
-	unsigned shift = (unsigned long)_table & MAX_PGTABLE_INDEX_SIZE;
-
-	pgtable_free(table, shift);
-}
-#else /* !CONFIG_SMP */
-static inline void pgtable_free_tlb(struct mmu_gather *tlb,
-				    void *table, int shift)
-{
-	pgtable_free(table, shift);
-}
-#endif /* CONFIG_SMP */
-
-static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table,
-				  unsigned long address)
-{
-	tlb_flush_pgtable(tlb, address);
-	pgtable_page_dtor(table);
-	pgtable_free_tlb(tlb, page_address(table), 0);
-}
-
-#else /* if CONFIG_PPC_64K_PAGES */
-
-extern pte_t *page_table_alloc(struct mm_struct *, unsigned long, int);
-extern void page_table_free(struct mm_struct *, unsigned long *, int);
-extern void pgtable_free_tlb(struct mmu_gather *tlb, void *table, int shift);
-#ifdef CONFIG_SMP
-extern void __tlb_remove_table(void *_table);
-#endif
-
-#ifndef __PAGETABLE_PUD_FOLDED
-/* book3s 64 is 4 level page table */
-static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud)
-{
-	pgd_set(pgd, __pgtable_ptr_val(pud));
-}
-
-static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
-{
-	return kmem_cache_alloc(PGT_CACHE(PUD_INDEX_SIZE),
-				GFP_KERNEL|__GFP_REPEAT);
-}
-
-static inline void pud_free(struct mm_struct *mm, pud_t *pud)
-{
-	kmem_cache_free(PGT_CACHE(PUD_INDEX_SIZE), pud);
-}
-#endif
-
-static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
-{
-	pud_set(pud, __pgtable_ptr_val(pmd));
-}
-
-static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
-				       pte_t *pte)
-{
-	pmd_set(pmd, __pgtable_ptr_val(pte));
-}
-
-static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
-				pgtable_t pte_page)
-{
-	pmd_set(pmd, __pgtable_ptr_val(pte_page));
-}
-
-static inline pgtable_t pmd_pgtable(pmd_t pmd)
-{
-	return (pgtable_t)pmd_page_vaddr(pmd);
-}
-
-static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
-					  unsigned long address)
-{
-	return (pte_t *)page_table_alloc(mm, address, 1);
-}
-
-static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
-					unsigned long address)
-{
-	return (pgtable_t)page_table_alloc(mm, address, 0);
-}
-
-static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
-{
-	page_table_free(mm, (unsigned long *)pte, 1);
-}
-
-static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage)
-{
-	page_table_free(mm, (unsigned long *)ptepage, 0);
-}
-
-static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table,
-				  unsigned long address)
-{
-	tlb_flush_pgtable(tlb, address);
-	pgtable_free_tlb(tlb, table, 0);
-}
-#endif /* CONFIG_PPC_64K_PAGES */
-
-static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
-{
-	return kmem_cache_alloc(PGT_CACHE(PMD_CACHE_INDEX),
-				GFP_KERNEL|__GFP_REPEAT);
-}
-
-static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
-{
-	kmem_cache_free(PGT_CACHE(PMD_CACHE_INDEX), pmd);
-}
-
-#define __pmd_free_tlb(tlb, pmd, addr)		      \
-	pgtable_free_tlb(tlb, pmd, PMD_CACHE_INDEX)
-#ifndef __PAGETABLE_PUD_FOLDED
-#define __pud_free_tlb(tlb, pud, addr)		      \
-	pgtable_free_tlb(tlb, pud, PUD_INDEX_SIZE)
-
-#endif /* __PAGETABLE_PUD_FOLDED */
-
-#define check_pgt_cache()	do { } while (0)
-
-#endif /* _ASM_POWERPC_PGALLOC_64_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/pgalloc.h linux-libre-4.7-gnu/arch/powerpc/include/asm/pgalloc.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/pgalloc.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/pgalloc.h	2016-07-24 15:23:50.000000000 -0400
@@ -1,25 +1,12 @@
 #ifndef _ASM_POWERPC_PGALLOC_H
 #define _ASM_POWERPC_PGALLOC_H
-#ifdef __KERNEL__
 
 #include <linux/mm.h>
 
-#ifdef CONFIG_PPC_BOOK3E
-extern void tlb_flush_pgtable(struct mmu_gather *tlb, unsigned long address);
-#else /* CONFIG_PPC_BOOK3E */
-static inline void tlb_flush_pgtable(struct mmu_gather *tlb,
-				     unsigned long address)
-{
-}
-#endif /* !CONFIG_PPC_BOOK3E */
-
-extern void tlb_remove_table(struct mmu_gather *tlb, void *table);
-
-#ifdef CONFIG_PPC64
-#include <asm/pgalloc-64.h>
+#ifdef CONFIG_PPC_BOOK3S
+#include <asm/book3s/pgalloc.h>
 #else
-#include <asm/pgalloc-32.h>
+#include <asm/nohash/pgalloc.h>
 #endif
 
-#endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_PGALLOC_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/pgtable-be-types.h linux-libre-4.7-gnu/arch/powerpc/include/asm/pgtable-be-types.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/pgtable-be-types.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/pgtable-be-types.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,92 @@
+#ifndef _ASM_POWERPC_PGTABLE_BE_TYPES_H
+#define _ASM_POWERPC_PGTABLE_BE_TYPES_H
+
+#include <asm/cmpxchg.h>
+
+/* PTE level */
+typedef struct { __be64 pte; } pte_t;
+#define __pte(x)	((pte_t) { cpu_to_be64(x) })
+static inline unsigned long pte_val(pte_t x)
+{
+	return be64_to_cpu(x.pte);
+}
+
+static inline __be64 pte_raw(pte_t x)
+{
+	return x.pte;
+}
+
+/* PMD level */
+#ifdef CONFIG_PPC64
+typedef struct { __be64 pmd; } pmd_t;
+#define __pmd(x)	((pmd_t) { cpu_to_be64(x) })
+static inline unsigned long pmd_val(pmd_t x)
+{
+	return be64_to_cpu(x.pmd);
+}
+
+static inline __be64 pmd_raw(pmd_t x)
+{
+	return x.pmd;
+}
+
+/*
+ * 64 bit hash always use 4 level table. Everybody else use 4 level
+ * only for 4K page size.
+ */
+#if defined(CONFIG_PPC_BOOK3S_64) || !defined(CONFIG_PPC_64K_PAGES)
+typedef struct { __be64 pud; } pud_t;
+#define __pud(x)	((pud_t) { cpu_to_be64(x) })
+static inline unsigned long pud_val(pud_t x)
+{
+	return be64_to_cpu(x.pud);
+}
+#endif /* CONFIG_PPC_BOOK3S_64 || !CONFIG_PPC_64K_PAGES */
+#endif /* CONFIG_PPC64 */
+
+/* PGD level */
+typedef struct { __be64 pgd; } pgd_t;
+#define __pgd(x)	((pgd_t) { cpu_to_be64(x) })
+static inline unsigned long pgd_val(pgd_t x)
+{
+	return be64_to_cpu(x.pgd);
+}
+
+/* Page protection bits */
+typedef struct { unsigned long pgprot; } pgprot_t;
+#define pgprot_val(x)	((x).pgprot)
+#define __pgprot(x)	((pgprot_t) { (x) })
+
+/*
+ * With hash config 64k pages additionally define a bigger "real PTE" type that
+ * gathers the "second half" part of the PTE for pseudo 64k pages
+ */
+#if defined(CONFIG_PPC_64K_PAGES) && defined(CONFIG_PPC_STD_MMU_64)
+typedef struct { pte_t pte; unsigned long hidx; } real_pte_t;
+#else
+typedef struct { pte_t pte; } real_pte_t;
+#endif
+
+static inline bool pte_xchg(pte_t *ptep, pte_t old, pte_t new)
+{
+	unsigned long *p = (unsigned long *)ptep;
+	__be64 prev;
+
+	prev = (__force __be64)__cmpxchg_u64(p, (__force unsigned long)pte_raw(old),
+					     (__force unsigned long)pte_raw(new));
+
+	return pte_raw(old) == prev;
+}
+
+static inline bool pmd_xchg(pmd_t *pmdp, pmd_t old, pmd_t new)
+{
+	unsigned long *p = (unsigned long *)pmdp;
+	__be64 prev;
+
+	prev = (__force __be64)__cmpxchg_u64(p, (__force unsigned long)pmd_raw(old),
+					     (__force unsigned long)pmd_raw(new));
+
+	return pmd_raw(old) == prev;
+}
+
+#endif /* _ASM_POWERPC_PGTABLE_BE_TYPES_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/pgtable.h linux-libre-4.7-gnu/arch/powerpc/include/asm/pgtable.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/pgtable.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/pgtable.h	2016-07-24 15:23:50.000000000 -0400
@@ -65,7 +65,6 @@ extern int gup_hugepte(pte_t *ptep, unsi
 		       struct page **pages, int *nr);
 #ifndef CONFIG_TRANSPARENT_HUGEPAGE
 #define pmd_large(pmd)		0
-#define has_transparent_hugepage() 0
 #endif
 pte_t *__find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea,
 				   bool *is_thp, unsigned *shift);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/pgtable-types.h linux-libre-4.7-gnu/arch/powerpc/include/asm/pgtable-types.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/pgtable-types.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/pgtable-types.h	2016-07-24 15:23:50.000000000 -0400
@@ -1,9 +1,6 @@
 #ifndef _ASM_POWERPC_PGTABLE_TYPES_H
 #define _ASM_POWERPC_PGTABLE_TYPES_H
 
-#ifdef CONFIG_STRICT_MM_TYPECHECKS
-/* These are used to make use of C type-checking. */
-
 /* PTE level */
 typedef struct { pte_basic_t pte; } pte_t;
 #define __pte(x)	((pte_t) { (x) })
@@ -48,49 +45,6 @@ typedef struct { unsigned long pgprot; }
 #define pgprot_val(x)	((x).pgprot)
 #define __pgprot(x)	((pgprot_t) { (x) })
 
-#else
-
-/*
- * .. while these make it easier on the compiler
- */
-
-typedef pte_basic_t pte_t;
-#define __pte(x)	(x)
-static inline pte_basic_t pte_val(pte_t pte)
-{
-	return pte;
-}
-
-#ifdef CONFIG_PPC64
-typedef unsigned long pmd_t;
-#define __pmd(x)	(x)
-static inline unsigned long pmd_val(pmd_t pmd)
-{
-	return pmd;
-}
-
-#if defined(CONFIG_PPC_BOOK3S_64) || !defined(CONFIG_PPC_64K_PAGES)
-typedef unsigned long pud_t;
-#define __pud(x)	(x)
-static inline unsigned long pud_val(pud_t pud)
-{
-	return pud;
-}
-#endif /* CONFIG_PPC_BOOK3S_64 || !CONFIG_PPC_64K_PAGES */
-#endif /* CONFIG_PPC64 */
-
-typedef unsigned long pgd_t;
-#define __pgd(x)	(x)
-static inline unsigned long pgd_val(pgd_t pgd)
-{
-	return pgd;
-}
-
-typedef unsigned long pgprot_t;
-#define pgprot_val(x)	(x)
-#define __pgprot(x)	(x)
-
-#endif /* CONFIG_STRICT_MM_TYPECHECKS */
 /*
  * With hash config 64k pages additionally define a bigger "real PTE" type that
  * gathers the "second half" part of the PTE for pseudo 64k pages
@@ -100,4 +54,16 @@ typedef struct { pte_t pte; unsigned lon
 #else
 typedef struct { pte_t pte; } real_pte_t;
 #endif
+
+#ifdef CONFIG_PPC_STD_MMU_64
+#include <asm/cmpxchg.h>
+
+static inline bool pte_xchg(pte_t *ptep, pte_t old, pte_t new)
+{
+	unsigned long *p = (unsigned long *)ptep;
+
+	return pte_val(old) == __cmpxchg_u64(p, pte_val(old), pte_val(new));
+}
+#endif
+
 #endif /* _ASM_POWERPC_PGTABLE_TYPES_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/ppc_asm.h linux-libre-4.7-gnu/arch/powerpc/include/asm/ppc_asm.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/ppc_asm.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/ppc_asm.h	2016-07-24 15:23:50.000000000 -0400
@@ -427,7 +427,10 @@ END_FTR_SECTION_IFCLR(CPU_FTR_601)
 	li	r4,1024;			\
 	mtctr	r4;				\
 	lis	r4,KERNELBASE@h;		\
+	.machine push;				\
+	.machine "power4";			\
 0:	tlbie	r4;				\
+	.machine pop;				\
 	addi	r4,r4,0x1000;			\
 	bdnz	0b
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/ppc-opcode.h linux-libre-4.7-gnu/arch/powerpc/include/asm/ppc-opcode.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/ppc-opcode.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/ppc-opcode.h	2016-07-24 15:23:50.000000000 -0400
@@ -131,6 +131,7 @@
 /* sorted alphabetically */
 #define PPC_INST_BHRBE			0x7c00025c
 #define PPC_INST_CLRBHRB		0x7c00035c
+#define PPC_INST_CP_ABORT		0x7c00068c
 #define PPC_INST_DCBA			0x7c0005ec
 #define PPC_INST_DCBA_MASK		0xfc0007fe
 #define PPC_INST_DCBAL			0x7c2005ec
@@ -285,6 +286,7 @@
 #endif
 
 /* Deal with instructions that older assemblers aren't aware of */
+#define	PPC_CP_ABORT		stringify_in_c(.long PPC_INST_CP_ABORT)
 #define	PPC_DCBAL(a, b)		stringify_in_c(.long PPC_INST_DCBAL | \
 					__PPC_RA(a) | __PPC_RB(b))
 #define	PPC_DCBZL(a, b)		stringify_in_c(.long PPC_INST_DCBZL | \
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/ppc-pci.h linux-libre-4.7-gnu/arch/powerpc/include/asm/ppc-pci.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/ppc-pci.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/ppc-pci.h	2016-07-24 15:23:50.000000000 -0400
@@ -33,9 +33,9 @@ extern struct pci_dev *isa_bridge_pcidev
 struct device_node;
 struct pci_dn;
 
-typedef void *(*traverse_func)(struct device_node *me, void *data);
-void *traverse_pci_devices(struct device_node *start, traverse_func pre,
-		void *data);
+void *pci_traverse_device_nodes(struct device_node *start,
+				void *(*fn)(struct device_node *, void *),
+				void *data);
 void *traverse_pci_dn(struct pci_dn *root,
 		      void *(*fn)(struct pci_dn *, void *),
 		      void *data);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/pte-common.h linux-libre-4.7-gnu/arch/powerpc/include/asm/pte-common.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/pte-common.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/pte-common.h	2016-07-24 15:23:50.000000000 -0400
@@ -76,6 +76,16 @@
  */
 #ifndef __ASSEMBLY__
 extern unsigned long bad_call_to_PMD_PAGE_SIZE(void);
+
+/*
+ * Don't just check for any non zero bits in __PAGE_USER, since for book3e
+ * and PTE_64BIT, PAGE_KERNEL_X contains _PAGE_BAP_SR which is also in
+ * _PAGE_USER.  Need to explicitly match _PAGE_BAP_UR bit in that case too.
+ */
+static inline bool pte_user(pte_t pte)
+{
+	return (pte_val(pte) & _PAGE_USER) == _PAGE_USER;
+}
 #endif /* __ASSEMBLY__ */
 
 /* Location of the PFN in the PTE. Most 32-bit platforms use the same
@@ -184,13 +194,6 @@ extern unsigned long bad_call_to_PMD_PAG
 /* Make modules code happy. We don't set RO yet */
 #define PAGE_KERNEL_EXEC	PAGE_KERNEL_X
 
-/*
- * Don't just check for any non zero bits in __PAGE_USER, since for book3e
- * and PTE_64BIT, PAGE_KERNEL_X contains _PAGE_BAP_SR which is also in
- * _PAGE_USER.  Need to explicitly match _PAGE_BAP_UR bit in that case too.
- */
-#define pte_user(val)		((val & _PAGE_USER) == _PAGE_USER)
-
 /* Advertise special mapping type for AGP */
 #define PAGE_AGP		(PAGE_KERNEL_NC)
 #define HAVE_PAGE_AGP
@@ -198,3 +201,12 @@ extern unsigned long bad_call_to_PMD_PAG
 /* Advertise support for _PAGE_SPECIAL */
 #define __HAVE_ARCH_PTE_SPECIAL
 
+#ifndef _PAGE_READ
+/* if not defined, we should not find _PAGE_WRITE too */
+#define _PAGE_READ 0
+#define _PAGE_WRITE _PAGE_RW
+#endif
+
+#ifndef H_PAGE_4K_PFN
+#define H_PAGE_4K_PFN 0
+#endif
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/reg.h linux-libre-4.7-gnu/arch/powerpc/include/asm/reg.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/reg.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/reg.h	2016-07-24 15:23:50.000000000 -0400
@@ -347,6 +347,7 @@
 #define   LPCR_LPES_SH	2
 #define   LPCR_RMI     0x00000002      /* real mode is cache inhibit */
 #define   LPCR_HDICE   0x00000001      /* Hyp Decr enable (HV,PR,EE) */
+#define   LPCR_UPRT    0x00400000      /* Use Process Table (ISA 3) */
 #ifndef SPRN_LPID
 #define SPRN_LPID	0x13F	/* Logical Partition Identifier */
 #endif
@@ -587,6 +588,7 @@
 #define SPRN_PIR	0x3FF	/* Processor Identification Register */
 #endif
 #define SPRN_TIR	0x1BE	/* Thread Identification Register */
+#define SPRN_PTCR	0x1D0	/* Partition table control Register */
 #define SPRN_PSPB	0x09F	/* Problem State Priority Boost reg */
 #define SPRN_PTEHI	0x3D5	/* 981 7450 PTE HI word (S/W TLB load) */
 #define SPRN_PTELO	0x3D6	/* 982 7450 PTE LO word (S/W TLB load) */
@@ -715,7 +717,7 @@
 #define   MMCR0_FCWAIT	0x00000002UL /* freeze counter in WAIT state */
 #define   MMCR0_FCHV	0x00000001UL /* freeze conditions in hypervisor mode */
 #define SPRN_MMCR1	798
-#define SPRN_MMCR2	769
+#define SPRN_MMCR2	785
 #define SPRN_MMCRA	0x312
 #define   MMCRA_SDSYNC	0x80000000UL /* SDAR synced with SIAR */
 #define   MMCRA_SDAR_DCACHE_MISS 0x40000000UL
@@ -752,13 +754,13 @@
 #define SPRN_PMC6	792
 #define SPRN_PMC7	793
 #define SPRN_PMC8	794
-#define SPRN_SIAR	780
-#define SPRN_SDAR	781
 #define SPRN_SIER	784
 #define   SIER_SIPR		0x2000000	/* Sampled MSR_PR */
 #define   SIER_SIHV		0x1000000	/* Sampled MSR_HV */
 #define   SIER_SIAR_VALID	0x0400000	/* SIAR contents valid */
 #define   SIER_SDAR_VALID	0x0200000	/* SDAR contents valid */
+#define SPRN_SIAR	796
+#define SPRN_SDAR	797
 #define SPRN_TACR	888
 #define SPRN_TCSCR	889
 #define SPRN_CSIGR	890
@@ -1182,6 +1184,7 @@
 #define PVR_970GX	0x0045
 #define PVR_POWER7p	0x004A
 #define PVR_POWER8E	0x004B
+#define PVR_POWER8NVL	0x004C
 #define PVR_POWER8	0x004D
 #define PVR_BE		0x0070
 #define PVR_PA6T	0x0090
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/thread_info.h linux-libre-4.7-gnu/arch/powerpc/include/asm/thread_info.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/thread_info.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/thread_info.h	2016-07-24 15:23:50.000000000 -0400
@@ -43,7 +43,9 @@ struct thread_info {
 	int		preempt_count;		/* 0 => preemptable,
 						   <0 => BUG */
 	unsigned long	local_flags;		/* private flags for thread */
-
+#ifdef CONFIG_LIVEPATCH
+	unsigned long *livepatch_sp;
+#endif
 	/* low level flags - has atomic operations done on it */
 	unsigned long	flags ____cacheline_aligned_in_smp;
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/asm/tlbflush.h linux-libre-4.7-gnu/arch/powerpc/include/asm/tlbflush.h
--- linux-libre-4.6-gnu/arch/powerpc/include/asm/tlbflush.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/include/asm/tlbflush.h	2016-07-24 15:23:50.000000000 -0400
@@ -58,6 +58,7 @@ extern void __flush_tlb_page(struct mm_s
 
 #elif defined(CONFIG_PPC_STD_MMU_32)
 
+#define MMU_NO_CONTEXT      (0)
 /*
  * TLB flushing for "classic" hash-MMU 32-bit CPUs, 6xx, 7xx, 7xxx
  */
@@ -78,7 +79,7 @@ static inline void local_flush_tlb_mm(st
 }
 
 #elif defined(CONFIG_PPC_STD_MMU_64)
-#include <asm/book3s/64/tlbflush-hash.h>
+#include <asm/book3s/64/tlbflush.h>
 #else
 #error Unsupported MMU type
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/include/uapi/asm/perf_regs.h linux-libre-4.7-gnu/arch/powerpc/include/uapi/asm/perf_regs.h
--- linux-libre-4.6-gnu/arch/powerpc/include/uapi/asm/perf_regs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/powerpc/include/uapi/asm/perf_regs.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,50 @@
+#ifndef _UAPI_ASM_POWERPC_PERF_REGS_H
+#define _UAPI_ASM_POWERPC_PERF_REGS_H
+
+enum perf_event_powerpc_regs {
+	PERF_REG_POWERPC_R0,
+	PERF_REG_POWERPC_R1,
+	PERF_REG_POWERPC_R2,
+	PERF_REG_POWERPC_R3,
+	PERF_REG_POWERPC_R4,
+	PERF_REG_POWERPC_R5,
+	PERF_REG_POWERPC_R6,
+	PERF_REG_POWERPC_R7,
+	PERF_REG_POWERPC_R8,
+	PERF_REG_POWERPC_R9,
+	PERF_REG_POWERPC_R10,
+	PERF_REG_POWERPC_R11,
+	PERF_REG_POWERPC_R12,
+	PERF_REG_POWERPC_R13,
+	PERF_REG_POWERPC_R14,
+	PERF_REG_POWERPC_R15,
+	PERF_REG_POWERPC_R16,
+	PERF_REG_POWERPC_R17,
+	PERF_REG_POWERPC_R18,
+	PERF_REG_POWERPC_R19,
+	PERF_REG_POWERPC_R20,
+	PERF_REG_POWERPC_R21,
+	PERF_REG_POWERPC_R22,
+	PERF_REG_POWERPC_R23,
+	PERF_REG_POWERPC_R24,
+	PERF_REG_POWERPC_R25,
+	PERF_REG_POWERPC_R26,
+	PERF_REG_POWERPC_R27,
+	PERF_REG_POWERPC_R28,
+	PERF_REG_POWERPC_R29,
+	PERF_REG_POWERPC_R30,
+	PERF_REG_POWERPC_R31,
+	PERF_REG_POWERPC_NIP,
+	PERF_REG_POWERPC_MSR,
+	PERF_REG_POWERPC_ORIG_R3,
+	PERF_REG_POWERPC_CTR,
+	PERF_REG_POWERPC_LINK,
+	PERF_REG_POWERPC_XER,
+	PERF_REG_POWERPC_CCR,
+	PERF_REG_POWERPC_SOFTE,
+	PERF_REG_POWERPC_TRAP,
+	PERF_REG_POWERPC_DAR,
+	PERF_REG_POWERPC_DSISR,
+	PERF_REG_POWERPC_MAX,
+};
+#endif /* _UAPI_ASM_POWERPC_PERF_REGS_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/Kconfig linux-libre-4.7-gnu/arch/powerpc/Kconfig
--- linux-libre-4.6-gnu/arch/powerpc/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -116,6 +116,8 @@ config PPC
 	select GENERIC_ATOMIC64 if PPC32
 	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
 	select HAVE_PERF_EVENTS
+	select HAVE_PERF_REGS
+	select HAVE_PERF_USER_STACK_DUMP
 	select HAVE_REGS_AND_STACK_ACCESS_API
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS && PPC_BOOK3S_64
 	select ARCH_WANT_IPC_PARSE_VERSION
@@ -126,7 +128,7 @@ config PPC
 	select IRQ_FORCED_THREADING
 	select HAVE_RCU_TABLE_FREE if SMP
 	select HAVE_SYSCALL_TRACEPOINTS
-	select HAVE_BPF_JIT
+	select HAVE_CBPF_JIT if CPU_BIG_ENDIAN
 	select HAVE_ARCH_JUMP_LABEL
 	select ARCH_HAVE_NMI_SAFE_CMPXCHG
 	select ARCH_HAS_GCOV_PROFILE_ALL
@@ -153,6 +155,7 @@ config PPC
 	select NO_BOOTMEM
 	select HAVE_GENERIC_RCU_GUP
 	select HAVE_PERF_EVENTS_NMI if PPC64
+	select HAVE_NMI if PERF_EVENTS
 	select EDAC_SUPPORT
 	select EDAC_ATOMIC_SCRUB
 	select ARCH_HAS_DMA_SET_COHERENT_MASK
@@ -160,6 +163,7 @@ config PPC
 	select HAVE_ARCH_SECCOMP_FILTER
 	select ARCH_HAS_UBSAN_SANITIZE_ALL
 	select ARCH_SUPPORTS_DEFERRED_STRUCT_PAGE_INIT
+	select HAVE_LIVEPATCH if HAVE_DYNAMIC_FTRACE_WITH_REGS
 
 config GENERIC_CSUM
 	def_bool CPU_LITTLE_ENDIAN
@@ -605,9 +609,9 @@ endchoice
 
 config FORCE_MAX_ZONEORDER
 	int "Maximum zone order"
-	range 9 64 if PPC64 && PPC_64K_PAGES
+	range 8 9 if PPC64 && PPC_64K_PAGES
 	default "9" if PPC64 && PPC_64K_PAGES
-	range 13 64 if PPC64 && !PPC_64K_PAGES
+	range 9 13 if PPC64 && !PPC_64K_PAGES
 	default "13" if PPC64 && !PPC_64K_PAGES
 	range 9 64 if PPC32 && PPC_16K_PAGES
 	default "9" if PPC32 && PPC_16K_PAGES
@@ -794,7 +798,6 @@ config 4xx_SOC
 
 config FSL_LBC
 	bool "Freescale Local Bus support"
-	depends on FSL_SOC
 	help
 	  Enables reporting of errors from the Freescale local bus
 	  controller.  Also contains some common code used by
@@ -1107,3 +1110,5 @@ config PPC_LIB_RHEAP
 	bool
 
 source "arch/powerpc/kvm/Kconfig"
+
+source "kernel/livepatch/Kconfig"
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/Kconfig.debug linux-libre-4.7-gnu/arch/powerpc/Kconfig.debug
--- linux-libre-4.6-gnu/arch/powerpc/Kconfig.debug	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/Kconfig.debug	2016-07-24 15:23:50.000000000 -0400
@@ -19,14 +19,6 @@ config PPC_WERROR
 	depends on !PPC_DISABLE_WERROR
 	default y
 
-config STRICT_MM_TYPECHECKS
-	bool "Do extra type checking on mm types"
-	default n
-	help
-	  This option turns on extra type checking for some mm related types.
-
-	  If you don't know what this means, say N.
-
 config PRINT_STACK_DEPTH
 	int "Stack depth to print" if DEBUG_KERNEL
 	default 64
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kernel/asm-offsets.c linux-libre-4.7-gnu/arch/powerpc/kernel/asm-offsets.c
--- linux-libre-4.6-gnu/arch/powerpc/kernel/asm-offsets.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kernel/asm-offsets.c	2016-07-24 15:23:50.000000000 -0400
@@ -86,6 +86,10 @@ int main(void)
 	DEFINE(KSP_LIMIT, offsetof(struct thread_struct, ksp_limit));
 #endif /* CONFIG_PPC64 */
 
+#ifdef CONFIG_LIVEPATCH
+	DEFINE(TI_livepatch_sp, offsetof(struct thread_info, livepatch_sp));
+#endif
+
 	DEFINE(KSP, offsetof(struct thread_struct, ksp));
 	DEFINE(PT_REGS, offsetof(struct thread_struct, regs));
 #ifdef CONFIG_BOOKE
@@ -434,7 +438,11 @@ int main(void)
 	DEFINE(BUG_ENTRY_SIZE, sizeof(struct bug_entry));
 #endif
 
+#ifdef MAX_PGD_TABLE_SIZE
+	DEFINE(PGD_TABLE_SIZE, MAX_PGD_TABLE_SIZE);
+#else
 	DEFINE(PGD_TABLE_SIZE, PGD_TABLE_SIZE);
+#endif
 	DEFINE(PTE_SIZE, sizeof(pte_t));
 
 #ifdef CONFIG_KVM
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kernel/btext.c linux-libre-4.7-gnu/arch/powerpc/kernel/btext.c
--- linux-libre-4.6-gnu/arch/powerpc/kernel/btext.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kernel/btext.c	2016-07-24 15:23:50.000000000 -0400
@@ -162,7 +162,7 @@ void btext_map(void)
 	offset = ((unsigned long) dispDeviceBase) - base;
 	size = dispDeviceRowBytes * dispDeviceRect[3] + offset
 		+ dispDeviceRect[0];
-	vbase = __ioremap(base, size, _PAGE_NO_CACHE);
+	vbase = __ioremap(base, size, pgprot_val(pgprot_noncached_wc(__pgprot(0))));
 	if (vbase == 0)
 		return;
 	logicalDisplayBase = vbase + offset;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kernel/cputable.c linux-libre-4.7-gnu/arch/powerpc/kernel/cputable.c
--- linux-libre-4.6-gnu/arch/powerpc/kernel/cputable.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kernel/cputable.c	2016-07-24 15:23:50.000000000 -0400
@@ -63,7 +63,6 @@ extern void __setup_cpu_745x(unsigned lo
 extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_ppc970MP(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_pa6t(unsigned long offset, struct cpu_spec* spec);
-extern void __setup_cpu_a2(unsigned long offset, struct cpu_spec* spec);
 extern void __restore_cpu_pa6t(void);
 extern void __restore_cpu_ppc970(void);
 extern void __setup_cpu_power7(unsigned long offset, struct cpu_spec* spec);
@@ -72,7 +71,6 @@ extern void __setup_cpu_power8(unsigned
 extern void __restore_cpu_power8(void);
 extern void __setup_cpu_power9(unsigned long offset, struct cpu_spec* spec);
 extern void __restore_cpu_power9(void);
-extern void __restore_cpu_a2(void);
 extern void __flush_tlb_power7(unsigned int action);
 extern void __flush_tlb_power8(unsigned int action);
 extern void __flush_tlb_power9(unsigned int action);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kernel/eeh.c linux-libre-4.7-gnu/arch/powerpc/kernel/eeh.c
--- linux-libre-4.6-gnu/arch/powerpc/kernel/eeh.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kernel/eeh.c	2016-07-24 15:23:50.000000000 -0400
@@ -48,7 +48,7 @@
 
 
 /** Overview:
- *  EEH, or "Extended Error Handling" is a PCI bridge technology for
+ *  EEH, or "Enhanced Error Handling" is a PCI bridge technology for
  *  dealing with PCI bus errors that can't be dealt with within the
  *  usual PCI framework, except by check-stopping the CPU.  Systems
  *  that are designed for high-availability/reliability cannot afford
@@ -1068,7 +1068,7 @@ void eeh_add_device_early(struct pci_dn
 	struct pci_controller *phb;
 	struct eeh_dev *edev = pdn_to_eeh_dev(pdn);
 
-	if (!edev || !eeh_enabled())
+	if (!edev)
 		return;
 
 	if (!eeh_has_flag(EEH_PROBE_MODE_DEVTREE))
@@ -1336,14 +1336,11 @@ static int eeh_pe_change_owner(struct ee
 			    id->subdevice != pdev->subsystem_device)
 				continue;
 
-			goto reset;
+			return eeh_pe_reset_and_recover(pe);
 		}
 	}
 
 	return eeh_unfreeze_pe(pe, true);
-
-reset:
-	return eeh_pe_reset_and_recover(pe);
 }
 
 /**
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kernel/eeh_driver.c linux-libre-4.7-gnu/arch/powerpc/kernel/eeh_driver.c
--- linux-libre-4.6-gnu/arch/powerpc/kernel/eeh_driver.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kernel/eeh_driver.c	2016-07-24 15:23:50.000000000 -0400
@@ -171,6 +171,16 @@ static void *eeh_dev_save_state(void *da
 	if (!edev)
 		return NULL;
 
+	/*
+	 * We cannot access the config space on some adapters.
+	 * Otherwise, it will cause fenced PHB. We don't save
+	 * the content in their config space and will restore
+	 * from the initial config space saved when the EEH
+	 * device is created.
+	 */
+	if (edev->pe && (edev->pe->state & EEH_PE_CFG_RESTRICTED))
+		return NULL;
+
 	pdev = eeh_dev_to_pci_dev(edev);
 	if (!pdev)
 		return NULL;
@@ -312,6 +322,19 @@ static void *eeh_dev_restore_state(void
 	if (!edev)
 		return NULL;
 
+	/*
+	 * The content in the config space isn't saved because
+	 * the blocked config space on some adapters. We have
+	 * to restore the initial saved config space when the
+	 * EEH device is created.
+	 */
+	if (edev->pe && (edev->pe->state & EEH_PE_CFG_RESTRICTED)) {
+		if (list_is_last(&edev->list, &edev->pe->edevs))
+			eeh_pe_restore_bars(edev->pe);
+
+		return NULL;
+	}
+
 	pdev = eeh_dev_to_pci_dev(edev);
 	if (!pdev)
 		return NULL;
@@ -552,7 +575,7 @@ static int eeh_clear_pe_frozen_state(str
 
 int eeh_pe_reset_and_recover(struct eeh_pe *pe)
 {
-	int result, ret;
+	int ret;
 
 	/* Bail if the PE is being recovered */
 	if (pe->state & EEH_PE_RECOVERING)
@@ -564,9 +587,6 @@ int eeh_pe_reset_and_recover(struct eeh_
 	/* Save states */
 	eeh_pe_dev_traverse(pe, eeh_dev_save_state, NULL);
 
-	/* Report error */
-	eeh_pe_dev_traverse(pe, eeh_report_error, &result);
-
 	/* Issue reset */
 	ret = eeh_reset_pe(pe);
 	if (ret) {
@@ -581,15 +601,9 @@ int eeh_pe_reset_and_recover(struct eeh_
 		return ret;
 	}
 
-	/* Notify completion of reset */
-	eeh_pe_dev_traverse(pe, eeh_report_reset, &result);
-
 	/* Restore device state */
 	eeh_pe_dev_traverse(pe, eeh_dev_restore_state, NULL);
 
-	/* Resume */
-	eeh_pe_dev_traverse(pe, eeh_report_resume, NULL);
-
 	/* Clear recovery mode */
 	eeh_pe_state_clear(pe, EEH_PE_RECOVERING);
 
@@ -621,20 +635,19 @@ static int eeh_reset_device(struct eeh_p
 	 * We don't remove the corresponding PE instances because
 	 * we need the information afterwords. The attached EEH
 	 * devices are expected to be attached soon when calling
-	 * into pcibios_add_pci_devices().
+	 * into pci_hp_add_devices().
 	 */
 	eeh_pe_state_mark(pe, EEH_PE_KEEP);
 	if (bus) {
 		if (pe->type & EEH_PE_VF) {
 			eeh_pe_dev_traverse(pe, eeh_rmv_device, NULL);
 		} else {
-			eeh_pe_state_clear(pe, EEH_PE_PRI_BUS);
 			pci_lock_rescan_remove();
-			pcibios_remove_pci_devices(bus);
+			pci_hp_remove_devices(bus);
 			pci_unlock_rescan_remove();
 		}
 	} else if (frozen_bus) {
-		eeh_pe_dev_traverse(pe, eeh_rmv_device, &rmv_data);
+		eeh_pe_dev_traverse(pe, eeh_rmv_device, rmv_data);
 	}
 
 	/*
@@ -678,10 +691,12 @@ static int eeh_reset_device(struct eeh_p
 		 */
 		edev = list_first_entry(&pe->edevs, struct eeh_dev, list);
 		eeh_pe_traverse(pe, eeh_pe_detach_dev, NULL);
-		if (pe->type & EEH_PE_VF)
+		if (pe->type & EEH_PE_VF) {
 			eeh_add_virt_device(edev, NULL);
-		else
-			pcibios_add_pci_devices(bus);
+		} else {
+			eeh_pe_state_clear(pe, EEH_PE_PRI_BUS);
+			pci_hp_add_devices(bus);
+		}
 	} else if (frozen_bus && rmv_data->removed) {
 		pr_info("EEH: Sleep 5s ahead of partial hotplug\n");
 		ssleep(5);
@@ -691,7 +706,7 @@ static int eeh_reset_device(struct eeh_p
 		if (pe->type & EEH_PE_VF)
 			eeh_add_virt_device(edev, NULL);
 		else
-			pcibios_add_pci_devices(frozen_bus);
+			pci_hp_add_devices(frozen_bus);
 	}
 	eeh_pe_state_clear(pe, EEH_PE_KEEP);
 
@@ -896,7 +911,7 @@ perm_error:
 			eeh_pe_dev_mode_mark(pe, EEH_DEV_REMOVED);
 
 			pci_lock_rescan_remove();
-			pcibios_remove_pci_devices(frozen_bus);
+			pci_hp_remove_devices(frozen_bus);
 			pci_unlock_rescan_remove();
 		}
 	}
@@ -981,7 +996,7 @@ static void eeh_handle_special_event(voi
 				bus = eeh_pe_bus_get(phb_pe);
 				eeh_pe_dev_traverse(pe,
 					eeh_report_failure, NULL);
-				pcibios_remove_pci_devices(bus);
+				pci_hp_remove_devices(bus);
 			}
 			pci_unlock_rescan_remove();
 		}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kernel/eeh_event.c linux-libre-4.7-gnu/arch/powerpc/kernel/eeh_event.c
--- linux-libre-4.6-gnu/arch/powerpc/kernel/eeh_event.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kernel/eeh_event.c	2016-07-24 15:23:50.000000000 -0400
@@ -36,7 +36,7 @@
 
 static DEFINE_SPINLOCK(eeh_eventlist_lock);
 static struct semaphore eeh_eventlist_sem;
-LIST_HEAD(eeh_eventlist);
+static LIST_HEAD(eeh_eventlist);
 
 /**
  * eeh_event_handler - Dispatch EEH events.
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kernel/eeh_pe.c linux-libre-4.7-gnu/arch/powerpc/kernel/eeh_pe.c
--- linux-libre-4.6-gnu/arch/powerpc/kernel/eeh_pe.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kernel/eeh_pe.c	2016-07-24 15:23:50.000000000 -0400
@@ -249,7 +249,7 @@ static void *__eeh_pe_get(void *data, vo
 	} else {
 		if (edev->pe_config_addr &&
 		    (edev->pe_config_addr == pe->addr))
-		return pe;
+			return pe;
 	}
 
 	/* Try BDF address */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kernel/entry_64.S linux-libre-4.7-gnu/arch/powerpc/kernel/entry_64.S
--- linux-libre-4.6-gnu/arch/powerpc/kernel/entry_64.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kernel/entry_64.S	2016-07-24 15:23:50.000000000 -0400
@@ -20,6 +20,7 @@
 
 #include <linux/errno.h>
 #include <linux/err.h>
+#include <linux/magic.h>
 #include <asm/unistd.h>
 #include <asm/processor.h>
 #include <asm/page.h>
@@ -36,6 +37,7 @@
 #include <asm/hw_irq.h>
 #include <asm/context_tracking.h>
 #include <asm/tm.h>
+#include <asm/ppc-opcode.h>
 
 /*
  * System calls.
@@ -508,6 +510,14 @@ BEGIN_FTR_SECTION
 	ldarx	r6,0,r1
 END_FTR_SECTION_IFSET(CPU_FTR_STCX_CHECKS_ADDRESS)
 
+BEGIN_FTR_SECTION
+/*
+ * A cp_abort (copy paste abort) here ensures that when context switching, a
+ * copy from one process can't leak into the paste of another.
+ */
+	PPC_CP_ABORT
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
+
 #ifdef CONFIG_PPC_BOOK3S
 /* Cancel all explict user streams as they will have no use after context
  * switch and will stop the HW from creating streams itself
@@ -519,7 +529,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_STCX_CHECK
 	std	r6,PACACURRENT(r13)	/* Set new 'current' */
 
 	ld	r8,KSP(r4)	/* new stack pointer */
-#ifdef CONFIG_PPC_BOOK3S
+#ifdef CONFIG_PPC_STD_MMU_64
+BEGIN_MMU_FTR_SECTION
+	b	2f
+END_MMU_FTR_SECTION_IFSET(MMU_FTR_RADIX)
 BEGIN_FTR_SECTION
 	clrrdi	r6,r8,28	/* get its ESID */
 	clrrdi	r9,r1,28	/* get current sp ESID */
@@ -565,7 +578,7 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEG
 	slbmte	r7,r0
 	isync
 2:
-#endif /* !CONFIG_PPC_BOOK3S */
+#endif /* CONFIG_PPC_STD_MMU_64 */
 
 	CURRENT_THREAD_INFO(r7, r8)  /* base of new stack */
 	/* Note: this uses SWITCH_FRAME_SIZE rather than INT_FRAME_SIZE
@@ -1248,6 +1261,9 @@ _GLOBAL(ftrace_caller)
 	addi	r3,r3,function_trace_op@toc@l
 	ld	r5,0(r3)
 
+#ifdef CONFIG_LIVEPATCH
+	mr	r14,r7		/* remember old NIP */
+#endif
 	/* Calculate ip from nip-4 into r3 for call below */
 	subi    r3, r7, MCOUNT_INSN_SIZE
 
@@ -1272,6 +1288,9 @@ ftrace_call:
 	/* Load ctr with the possibly modified NIP */
 	ld	r3, _NIP(r1)
 	mtctr	r3
+#ifdef CONFIG_LIVEPATCH
+	cmpd	r14,r3		/* has NIP been altered? */
+#endif
 
 	/* Restore gprs */
 	REST_8GPRS(0,r1)
@@ -1289,6 +1308,11 @@ ftrace_call:
 	ld	r0, LRSAVE(r1)
 	mtlr	r0
 
+#ifdef CONFIG_LIVEPATCH
+        /* Based on the cmpd above, if the NIP was altered handle livepatch */
+	bne-	livepatch_handler
+#endif
+
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 	stdu	r1, -112(r1)
 .globl ftrace_graph_call
@@ -1305,6 +1329,91 @@ _GLOBAL(ftrace_graph_stub)
 
 _GLOBAL(ftrace_stub)
 	blr
+
+#ifdef CONFIG_LIVEPATCH
+	/*
+	 * This function runs in the mcount context, between two functions. As
+	 * such it can only clobber registers which are volatile and used in
+	 * function linkage.
+	 *
+	 * We get here when a function A, calls another function B, but B has
+	 * been live patched with a new function C.
+	 *
+	 * On entry:
+	 *  - we have no stack frame and can not allocate one
+	 *  - LR points back to the original caller (in A)
+	 *  - CTR holds the new NIP in C
+	 *  - r0 & r12 are free
+	 *
+	 * r0 can't be used as the base register for a DS-form load or store, so
+	 * we temporarily shuffle r1 (stack pointer) into r0 and then put it back.
+	 */
+livepatch_handler:
+	CURRENT_THREAD_INFO(r12, r1)
+
+	/* Save stack pointer into r0 */
+	mr	r0, r1
+
+	/* Allocate 3 x 8 bytes */
+	ld	r1, TI_livepatch_sp(r12)
+	addi	r1, r1, 24
+	std	r1, TI_livepatch_sp(r12)
+
+	/* Save toc & real LR on livepatch stack */
+	std	r2,  -24(r1)
+	mflr	r12
+	std	r12, -16(r1)
+
+	/* Store stack end marker */
+	lis     r12, STACK_END_MAGIC@h
+	ori     r12, r12, STACK_END_MAGIC@l
+	std	r12, -8(r1)
+
+	/* Restore real stack pointer */
+	mr	r1, r0
+
+	/* Put ctr in r12 for global entry and branch there */
+	mfctr	r12
+	bctrl
+
+	/*
+	 * Now we are returning from the patched function to the original
+	 * caller A. We are free to use r0 and r12, and we can use r2 until we
+	 * restore it.
+	 */
+
+	CURRENT_THREAD_INFO(r12, r1)
+
+	/* Save stack pointer into r0 */
+	mr	r0, r1
+
+	ld	r1, TI_livepatch_sp(r12)
+
+	/* Check stack marker hasn't been trashed */
+	lis     r2,  STACK_END_MAGIC@h
+	ori     r2,  r2, STACK_END_MAGIC@l
+	ld	r12, -8(r1)
+1:	tdne	r12, r2
+	EMIT_BUG_ENTRY 1b, __FILE__, __LINE__ - 1, 0
+
+	/* Restore LR & toc from livepatch stack */
+	ld	r12, -16(r1)
+	mtlr	r12
+	ld	r2,  -24(r1)
+
+	/* Pop livepatch stack frame */
+	CURRENT_THREAD_INFO(r12, r0)
+	subi	r1, r1, 24
+	std	r1, TI_livepatch_sp(r12)
+
+	/* Restore real stack pointer */
+	mr	r1, r0
+
+	/* Return to original caller of live patched function */
+	blr
+#endif
+
+
 #else
 _GLOBAL_TOC(_mcount)
 	/* Taken from output of objdump from lib64/glibc */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kernel/exceptions-64s.S linux-libre-4.7-gnu/arch/powerpc/kernel/exceptions-64s.S
--- linux-libre-4.6-gnu/arch/powerpc/kernel/exceptions-64s.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kernel/exceptions-64s.S	2016-07-24 15:23:50.000000000 -0400
@@ -189,7 +189,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | C
 #endif /* CONFIG_PPC_P7_NAP */
 	EXCEPTION_PROLOG_0(PACA_EXMC)
 BEGIN_FTR_SECTION
-	b	machine_check_pSeries_early
+	b	machine_check_powernv_early
 FTR_SECTION_ELSE
 	b	machine_check_pSeries_0
 ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE)
@@ -209,11 +209,6 @@ data_access_slb_pSeries:
 	EXCEPTION_PROLOG_1(PACA_EXSLB, KVMTEST, 0x380)
 	std	r3,PACA_EXSLB+EX_R3(r13)
 	mfspr	r3,SPRN_DAR
-#ifdef __DISABLED__
-	/* Keep that around for when we re-implement dynamic VSIDs */
-	cmpdi	r3,0
-	bge	slb_miss_user_pseries
-#endif /* __DISABLED__ */
 	mfspr	r12,SPRN_SRR1
 #ifndef CONFIG_RELOCATABLE
 	b	slb_miss_realmode
@@ -240,11 +235,6 @@ instruction_access_slb_pSeries:
 	EXCEPTION_PROLOG_1(PACA_EXSLB, KVMTEST, 0x480)
 	std	r3,PACA_EXSLB+EX_R3(r13)
 	mfspr	r3,SPRN_SRR0		/* SRR0 is faulting address */
-#ifdef __DISABLED__
-	/* Keep that around for when we re-implement dynamic VSIDs */
-	cmpdi	r3,0
-	bge	slb_miss_user_pseries
-#endif /* __DISABLED__ */
 	mfspr	r12,SPRN_SRR1
 #ifndef CONFIG_RELOCATABLE
 	b	slb_miss_realmode
@@ -443,7 +433,7 @@ denorm_exception_hv:
 
 	.align	7
 	/* moved from 0x200 */
-machine_check_pSeries_early:
+machine_check_powernv_early:
 BEGIN_FTR_SECTION
 	EXCEPTION_PROLOG_1(PACA_EXMC, NOTEST, 0x200)
 	/*
@@ -709,34 +699,6 @@ system_reset_fwnmi:
 
 #endif /* CONFIG_PPC_PSERIES */
 
-#ifdef __DISABLED__
-/*
- * This is used for when the SLB miss handler has to go virtual,
- * which doesn't happen for now anymore but will once we re-implement
- * dynamic VSIDs for shared page tables
- */
-slb_miss_user_pseries:
-	std	r10,PACA_EXGEN+EX_R10(r13)
-	std	r11,PACA_EXGEN+EX_R11(r13)
-	std	r12,PACA_EXGEN+EX_R12(r13)
-	GET_SCRATCH0(r10)
-	ld	r11,PACA_EXSLB+EX_R9(r13)
-	ld	r12,PACA_EXSLB+EX_R3(r13)
-	std	r10,PACA_EXGEN+EX_R13(r13)
-	std	r11,PACA_EXGEN+EX_R9(r13)
-	std	r12,PACA_EXGEN+EX_R3(r13)
-	clrrdi	r12,r13,32
-	mfmsr	r10
-	mfspr	r11,SRR0			/* save SRR0 */
-	ori	r12,r12,slb_miss_user_common@l	/* virt addr of handler */
-	ori	r10,r10,MSR_IR|MSR_DR|MSR_RI
-	mtspr	SRR0,r12
-	mfspr	r12,SRR1			/* and SRR1 */
-	mtspr	SRR1,r10
-	rfid
-	b	.				/* prevent spec. execution */
-#endif /* __DISABLED__ */
-
 #ifdef CONFIG_KVM_BOOK3S_64_HANDLER
 kvmppc_skip_interrupt:
 	/*
@@ -764,11 +726,10 @@ kvmppc_skip_Hinterrupt:
 #endif
 
 /*
- * Code from here down to __end_handlers is invoked from the
- * exception prologs above.  Because the prologs assemble the
- * addresses of these handlers using the LOAD_HANDLER macro,
- * which uses an ori instruction, these handlers must be in
- * the first 64k of the kernel image.
+ * Ensure that any handlers that get invoked from the exception prologs
+ * above are below the first 64KB (0x10000) of the kernel image because
+ * the prologs assemble the addresses of these handlers using the
+ * LOAD_HANDLER macro, which uses an ori instruction.
  */
 
 /*** Common interrupt handlers ***/
@@ -953,11 +914,6 @@ hv_facility_unavailable_relon_trampoline
 #endif
 	STD_RELON_EXCEPTION_PSERIES(0x5700, 0x1700, altivec_assist)
 
-	/* Other future vectors */
-	.align	7
-	.globl	__end_interrupts
-__end_interrupts:
-
 	.align	7
 system_call_entry:
 	b	system_call_common
@@ -983,7 +939,13 @@ data_access_common:
 	ld	r3,PACA_EXGEN+EX_DAR(r13)
 	lwz	r4,PACA_EXGEN+EX_DSISR(r13)
 	li	r5,0x300
+	std	r3,_DAR(r1)
+	std	r4,_DSISR(r1)
+BEGIN_MMU_FTR_SECTION
 	b	do_hash_page		/* Try to handle as hpte fault */
+MMU_FTR_SECTION_ELSE
+	b	handle_page_fault
+ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_RADIX)
 
 	.align  7
 	.globl  h_data_storage_common
@@ -1008,73 +970,15 @@ instruction_access_common:
 	ld	r3,_NIP(r1)
 	andis.	r4,r12,0x5820
 	li	r5,0x400
+	std	r3,_DAR(r1)
+	std	r4,_DSISR(r1)
+BEGIN_MMU_FTR_SECTION
 	b	do_hash_page		/* Try to handle as hpte fault */
-
-	STD_EXCEPTION_COMMON(0xe20, h_instr_storage, unknown_exception)
-
-/*
- * Here is the common SLB miss user that is used when going to virtual
- * mode for SLB misses, that is currently not used
- */
-#ifdef __DISABLED__
-	.align	7
-	.globl	slb_miss_user_common
-slb_miss_user_common:
-	mflr	r10
-	std	r3,PACA_EXGEN+EX_DAR(r13)
-	stw	r9,PACA_EXGEN+EX_CCR(r13)
-	std	r10,PACA_EXGEN+EX_LR(r13)
-	std	r11,PACA_EXGEN+EX_SRR0(r13)
-	bl	slb_allocate_user
-
-	ld	r10,PACA_EXGEN+EX_LR(r13)
-	ld	r3,PACA_EXGEN+EX_R3(r13)
-	lwz	r9,PACA_EXGEN+EX_CCR(r13)
-	ld	r11,PACA_EXGEN+EX_SRR0(r13)
-	mtlr	r10
-	beq-	slb_miss_fault
-
-	andi.	r10,r12,MSR_RI		/* check for unrecoverable exception */
-	beq-	unrecov_user_slb
-	mfmsr	r10
-
-.machine push
-.machine "power4"
-	mtcrf	0x80,r9
-.machine pop
-
-	clrrdi	r10,r10,2		/* clear RI before setting SRR0/1 */
-	mtmsrd	r10,1
-
-	mtspr	SRR0,r11
-	mtspr	SRR1,r12
-
-	ld	r9,PACA_EXGEN+EX_R9(r13)
-	ld	r10,PACA_EXGEN+EX_R10(r13)
-	ld	r11,PACA_EXGEN+EX_R11(r13)
-	ld	r12,PACA_EXGEN+EX_R12(r13)
-	ld	r13,PACA_EXGEN+EX_R13(r13)
-	rfid
-	b	.
-
-slb_miss_fault:
-	EXCEPTION_PROLOG_COMMON(0x380, PACA_EXGEN)
-	ld	r4,PACA_EXGEN+EX_DAR(r13)
-	li	r5,0
-	std	r4,_DAR(r1)
-	std	r5,_DSISR(r1)
+MMU_FTR_SECTION_ELSE
 	b	handle_page_fault
+ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_RADIX)
 
-unrecov_user_slb:
-	EXCEPTION_PROLOG_COMMON(0x4200, PACA_EXGEN)
-	RECONCILE_IRQ_STATE(r10, r11)
-	bl	save_nvgprs
-1:	addi	r3,r1,STACK_FRAME_OVERHEAD
-	bl	unrecoverable_exception
-	b	1b
-
-#endif /* __DISABLED__ */
-
+	STD_EXCEPTION_COMMON(0xe20, h_instr_storage, unknown_exception)
 
 	/*
 	 * Machine check is different because we use a different
@@ -1230,10 +1134,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
 	STD_EXCEPTION_COMMON(0xf60, facility_unavailable, facility_unavailable_exception)
 	STD_EXCEPTION_COMMON(0xf80, hv_facility_unavailable, facility_unavailable_exception)
 
-	.align	7
-	.globl	__end_handlers
-__end_handlers:
-
 	/* Equivalents to the above handlers for relocation-on interrupt vectors */
 	STD_RELON_EXCEPTION_HV_OOL(0xe40, emulation_assist)
 	MASKABLE_RELON_EXCEPTION_HV_OOL(0xe80, h_doorbell)
@@ -1244,6 +1144,17 @@ __end_handlers:
 	STD_RELON_EXCEPTION_PSERIES_OOL(0xf60, facility_unavailable)
 	STD_RELON_EXCEPTION_HV_OOL(0xf80, hv_facility_unavailable)
 
+	/*
+	 * The __end_interrupts marker must be past the out-of-line (OOL)
+	 * handlers, so that they are copied to real address 0x100 when running
+	 * a relocatable kernel. This ensures they can be reached from the short
+	 * trampoline handlers (like 0x4f00, 0x4f20, etc.) which branch
+	 * directly, without using LOAD_HANDLER().
+	 */
+	.align	7
+	.globl	__end_interrupts
+__end_interrupts:
+
 #if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
 /*
  * Data area reserved for FWNMI option.
@@ -1476,8 +1387,11 @@ slb_miss_realmode:
 	stw	r9,PACA_EXSLB+EX_CCR(r13)	/* save CR in exc. frame */
 	std	r10,PACA_EXSLB+EX_LR(r13)	/* save LR */
 
+#ifdef CONFIG_PPC_STD_MMU_64
+BEGIN_MMU_FTR_SECTION
 	bl	slb_allocate_realmode
-
+END_MMU_FTR_SECTION_IFCLR(MMU_FTR_RADIX)
+#endif
 	/* All done -- return from exception. */
 
 	ld	r10,PACA_EXSLB+EX_LR(r13)
@@ -1485,9 +1399,12 @@ slb_miss_realmode:
 	lwz	r9,PACA_EXSLB+EX_CCR(r13)	/* get saved CR */
 
 	mtlr	r10
-
 	andi.	r10,r12,MSR_RI	/* check for unrecoverable exception */
+BEGIN_MMU_FTR_SECTION
 	beq-	2f
+FTR_SECTION_ELSE
+	b	2f
+ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_RADIX)
 
 .machine	push
 .machine	"power4"
@@ -1536,9 +1453,7 @@ power4_fixup_nap:
  */
 	.align	7
 do_hash_page:
-	std	r3,_DAR(r1)
-	std	r4,_DSISR(r1)
-
+#ifdef CONFIG_PPC_STD_MMU_64
 	andis.	r0,r4,0xa410		/* weird error? */
 	bne-	handle_page_fault	/* if not, try to insert a HPTE */
 	andis.  r0,r4,DSISR_DABRMATCH@h
@@ -1566,6 +1481,7 @@ do_hash_page:
 
 	/* Error */
 	blt-	13f
+#endif /* CONFIG_PPC_STD_MMU_64 */
 
 /* Here we have a page fault that hash_page can't handle. */
 handle_page_fault:
@@ -1592,6 +1508,7 @@ handle_dabr_fault:
 12:	b       ret_from_except_lite
 
 
+#ifdef CONFIG_PPC_STD_MMU_64
 /* We have a page fault that hash_page could handle but HV refused
  * the PTE insertion
  */
@@ -1601,6 +1518,7 @@ handle_dabr_fault:
 	ld	r4,_DAR(r1)
 	bl	low_hash_fault
 	b	ret_from_except
+#endif
 
 /*
  * We come here as a result of a DSI at a point where we don't want
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kernel/ftrace.c linux-libre-4.7-gnu/arch/powerpc/kernel/ftrace.c
--- linux-libre-4.6-gnu/arch/powerpc/kernel/ftrace.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kernel/ftrace.c	2016-07-24 15:23:50.000000000 -0400
@@ -607,3 +607,13 @@ unsigned long __init arch_syscall_addr(i
 	return sys_call_table[nr*2];
 }
 #endif /* CONFIG_FTRACE_SYSCALLS && CONFIG_PPC64 */
+
+#if defined(CONFIG_PPC64) && (!defined(_CALL_ELF) || _CALL_ELF != 2)
+char *arch_ftrace_match_adjust(char *str, const char *search)
+{
+	if (str[0] == '.' && search[0] != '.')
+		return str + 1;
+	else
+		return str;
+}
+#endif /* defined(CONFIG_PPC64) && (!defined(_CALL_ELF) || _CALL_ELF != 2) */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kernel/head_64.S linux-libre-4.7-gnu/arch/powerpc/kernel/head_64.S
--- linux-libre-4.6-gnu/arch/powerpc/kernel/head_64.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kernel/head_64.S	2016-07-24 15:23:50.000000000 -0400
@@ -973,13 +973,16 @@ start_here_common:
  * This stuff goes at the beginning of the bss, which is page-aligned.
  */
 	.section ".bss"
+/*
+ * pgd dir should be aligned to PGD_TABLE_SIZE which is 64K.
+ * We will need to find a better way to fix this
+ */
+	.align	16
 
-	.align	PAGE_SHIFT
+	.globl	swapper_pg_dir
+swapper_pg_dir:
+	.space	PGD_TABLE_SIZE
 
 	.globl	empty_zero_page
 empty_zero_page:
 	.space	PAGE_SIZE
-
-	.globl	swapper_pg_dir
-swapper_pg_dir:
-	.space	PGD_TABLE_SIZE
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kernel/ibmebus.c linux-libre-4.7-gnu/arch/powerpc/kernel/ibmebus.c
--- linux-libre-4.6-gnu/arch/powerpc/kernel/ibmebus.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kernel/ibmebus.c	2016-07-24 15:23:50.000000000 -0400
@@ -408,7 +408,7 @@ static ssize_t modalias_show(struct devi
 	return len+1;
 }
 
-struct device_attribute ibmebus_bus_device_attrs[] = {
+static struct device_attribute ibmebus_bus_device_attrs[] = {
 	__ATTR_RO(devspec),
 	__ATTR_RO(name),
 	__ATTR_RO(modalias),
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kernel/irq.c linux-libre-4.7-gnu/arch/powerpc/kernel/irq.c
--- linux-libre-4.6-gnu/arch/powerpc/kernel/irq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kernel/irq.c	2016-07-24 15:23:50.000000000 -0400
@@ -66,6 +66,7 @@
 #include <asm/udbg.h>
 #include <asm/smp.h>
 #include <asm/debug.h>
+#include <asm/livepatch.h>
 
 #ifdef CONFIG_PPC64
 #include <asm/paca.h>
@@ -607,10 +608,12 @@ void irq_ctx_init(void)
 		memset((void *)softirq_ctx[i], 0, THREAD_SIZE);
 		tp = softirq_ctx[i];
 		tp->cpu = i;
+		klp_init_thread_info(tp);
 
 		memset((void *)hardirq_ctx[i], 0, THREAD_SIZE);
 		tp = hardirq_ctx[i];
 		tp->cpu = i;
+		klp_init_thread_info(tp);
 	}
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kernel/isa-bridge.c linux-libre-4.7-gnu/arch/powerpc/kernel/isa-bridge.c
--- linux-libre-4.6-gnu/arch/powerpc/kernel/isa-bridge.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kernel/isa-bridge.c	2016-07-24 15:23:50.000000000 -0400
@@ -109,14 +109,14 @@ static void pci_process_ISA_OF_ranges(st
 		size = 0x10000;
 
 	__ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE,
-		     size, _PAGE_NO_CACHE|_PAGE_GUARDED);
+		     size, pgprot_val(pgprot_noncached(__pgprot(0))));
 	return;
 
 inval_range:
 	printk(KERN_ERR "no ISA IO ranges or unexpected isa range, "
 	       "mapping 64k\n");
 	__ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE,
-		     0x10000, _PAGE_NO_CACHE|_PAGE_GUARDED);
+		     0x10000, pgprot_val(pgprot_noncached(__pgprot(0))));
 }
 
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kernel/machine_kexec_64.c linux-libre-4.7-gnu/arch/powerpc/kernel/machine_kexec_64.c
--- linux-libre-4.6-gnu/arch/powerpc/kernel/machine_kexec_64.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kernel/machine_kexec_64.c	2016-07-24 15:23:50.000000000 -0400
@@ -76,6 +76,7 @@ int default_machine_kexec_prepare(struct
 	 * end of the blocked region (begin >= high).  Use the
 	 * boolean identity !(a || b)  === (!a && !b).
 	 */
+#ifdef CONFIG_PPC_STD_MMU_64
 	if (htab_address) {
 		low = __pa(htab_address);
 		high = low + htab_size_bytes;
@@ -88,6 +89,7 @@ int default_machine_kexec_prepare(struct
 				return -ETXTBSY;
 		}
 	}
+#endif /* CONFIG_PPC_STD_MMU_64 */
 
 	/* We also should not overwrite the tce tables */
 	for_each_node_by_type(node, "pci") {
@@ -381,7 +383,7 @@ void default_machine_kexec(struct kimage
 	/* NOTREACHED */
 }
 
-#ifndef CONFIG_PPC_BOOK3E
+#ifdef CONFIG_PPC_STD_MMU_64
 /* Values we need to export to the second kernel via the device tree. */
 static unsigned long htab_base;
 static unsigned long htab_size;
@@ -401,7 +403,6 @@ static struct property htab_size_prop =
 static int __init export_htab_values(void)
 {
 	struct device_node *node;
-	struct property *prop;
 
 	/* On machines with no htab htab_address is NULL */
 	if (!htab_address)
@@ -412,12 +413,8 @@ static int __init export_htab_values(voi
 		return -ENODEV;
 
 	/* remove any stale propertys so ours can be found */
-	prop = of_find_property(node, htab_base_prop.name, NULL);
-	if (prop)
-		of_remove_property(node, prop);
-	prop = of_find_property(node, htab_size_prop.name, NULL);
-	if (prop)
-		of_remove_property(node, prop);
+	of_remove_property(node, of_find_property(node, htab_base_prop.name, NULL));
+	of_remove_property(node, of_find_property(node, htab_size_prop.name, NULL));
 
 	htab_base = cpu_to_be64(__pa(htab_address));
 	of_add_property(node, &htab_base_prop);
@@ -428,4 +425,4 @@ static int __init export_htab_values(voi
 	return 0;
 }
 late_initcall(export_htab_values);
-#endif /* !CONFIG_PPC_BOOK3E */
+#endif /* CONFIG_PPC_STD_MMU_64 */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kernel/machine_kexec.c linux-libre-4.7-gnu/arch/powerpc/kernel/machine_kexec.c
--- linux-libre-4.6-gnu/arch/powerpc/kernel/machine_kexec.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kernel/machine_kexec.c	2016-07-24 15:23:50.000000000 -0400
@@ -228,17 +228,12 @@ static struct property memory_limit_prop
 
 static void __init export_crashk_values(struct device_node *node)
 {
-	struct property *prop;
-
 	/* There might be existing crash kernel properties, but we can't
 	 * be sure what's in them, so remove them. */
-	prop = of_find_property(node, "linux,crashkernel-base", NULL);
-	if (prop)
-		of_remove_property(node, prop);
-
-	prop = of_find_property(node, "linux,crashkernel-size", NULL);
-	if (prop)
-		of_remove_property(node, prop);
+	of_remove_property(node, of_find_property(node,
+				"linux,crashkernel-base", NULL));
+	of_remove_property(node, of_find_property(node,
+				"linux,crashkernel-size", NULL));
 
 	if (crashk_res.start != 0) {
 		crashk_base = cpu_to_be_ulong(crashk_res.start),
@@ -258,16 +253,13 @@ static void __init export_crashk_values(
 static int __init kexec_setup(void)
 {
 	struct device_node *node;
-	struct property *prop;
 
 	node = of_find_node_by_path("/chosen");
 	if (!node)
 		return -ENOENT;
 
 	/* remove any stale properties so ours can be found */
-	prop = of_find_property(node, kernel_end_prop.name, NULL);
-	if (prop)
-		of_remove_property(node, prop);
+	of_remove_property(node, of_find_property(node, kernel_end_prop.name, NULL));
 
 	/* information needed by userspace when using default_machine_kexec */
 	kernel_end = cpu_to_be_ulong(__pa(_end));
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kernel/mce.c linux-libre-4.7-gnu/arch/powerpc/kernel/mce.c
--- linux-libre-4.6-gnu/arch/powerpc/kernel/mce.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kernel/mce.c	2016-07-24 15:23:50.000000000 -0400
@@ -37,7 +37,7 @@ static DEFINE_PER_CPU(int, mce_queue_cou
 static DEFINE_PER_CPU(struct machine_check_event[MAX_MC_EVT], mce_event_queue);
 
 static void machine_check_process_queued_event(struct irq_work *work);
-struct irq_work mce_event_process_work = {
+static struct irq_work mce_event_process_work = {
         .func = machine_check_process_queued_event,
 };
 
@@ -284,7 +284,7 @@ void machine_check_print_event_info(stru
 			printk("%s    Effective address: %016llx\n",
 			       level, evt->u.ue_error.effective_address);
 		if (evt->u.ue_error.physical_address_provided)
-			printk("%s      Physial address: %016llx\n",
+			printk("%s      Physical address: %016llx\n",
 			       level, evt->u.ue_error.physical_address);
 		break;
 	case MCE_ERROR_TYPE_SLB:
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kernel/mce_power.c linux-libre-4.7-gnu/arch/powerpc/kernel/mce_power.c
--- linux-libre-4.6-gnu/arch/powerpc/kernel/mce_power.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kernel/mce_power.c	2016-07-24 15:23:50.000000000 -0400
@@ -72,11 +72,15 @@ void __flush_tlb_power8(unsigned int act
 
 void __flush_tlb_power9(unsigned int action)
 {
+	if (radix_enabled())
+		flush_tlb_206(POWER9_TLB_SETS_RADIX, action);
+
 	flush_tlb_206(POWER9_TLB_SETS_HASH, action);
 }
 
 
 /* flush SLBs and reload */
+#ifdef CONFIG_PPC_STD_MMU_64
 static void flush_and_reload_slb(void)
 {
 	struct slb_shadow *slb;
@@ -110,6 +114,7 @@ static void flush_and_reload_slb(void)
 		asm volatile("slbmte %0,%1" : : "r" (rs), "r" (rb));
 	}
 }
+#endif
 
 static long mce_handle_derror(uint64_t dsisr, uint64_t slb_error_bits)
 {
@@ -120,6 +125,7 @@ static long mce_handle_derror(uint64_t d
 	 * reset the error bits whenever we handle them so that at the end
 	 * we can check whether we handled all of them or not.
 	 * */
+#ifdef CONFIG_PPC_STD_MMU_64
 	if (dsisr & slb_error_bits) {
 		flush_and_reload_slb();
 		/* reset error bits */
@@ -131,6 +137,7 @@ static long mce_handle_derror(uint64_t d
 		/* reset error bits */
 		dsisr &= ~P7_DSISR_MC_TLB_MULTIHIT_MFTLB;
 	}
+#endif
 	/* Any other errors we don't understand? */
 	if (dsisr & 0xffffffffUL)
 		handled = 0;
@@ -150,6 +157,7 @@ static long mce_handle_common_ierror(uin
 	switch (P7_SRR1_MC_IFETCH(srr1)) {
 	case 0:
 		break;
+#ifdef CONFIG_PPC_STD_MMU_64
 	case P7_SRR1_MC_IFETCH_SLB_PARITY:
 	case P7_SRR1_MC_IFETCH_SLB_MULTIHIT:
 		/* flush and reload SLBs for SLB errors. */
@@ -162,6 +170,7 @@ static long mce_handle_common_ierror(uin
 			handled = 1;
 		}
 		break;
+#endif
 	default:
 		break;
 	}
@@ -175,10 +184,12 @@ static long mce_handle_ierror_p7(uint64_
 
 	handled = mce_handle_common_ierror(srr1);
 
+#ifdef CONFIG_PPC_STD_MMU_64
 	if (P7_SRR1_MC_IFETCH(srr1) == P7_SRR1_MC_IFETCH_SLB_BOTH) {
 		flush_and_reload_slb();
 		handled = 1;
 	}
+#endif
 	return handled;
 }
 
@@ -321,10 +332,12 @@ static long mce_handle_ierror_p8(uint64_
 
 	handled = mce_handle_common_ierror(srr1);
 
+#ifdef CONFIG_PPC_STD_MMU_64
 	if (P7_SRR1_MC_IFETCH(srr1) == P8_SRR1_MC_IFETCH_ERAT_MULTIHIT) {
 		flush_and_reload_slb();
 		handled = 1;
 	}
+#endif
 	return handled;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kernel/misc_32.S linux-libre-4.7-gnu/arch/powerpc/kernel/misc_32.S
--- linux-libre-4.6-gnu/arch/powerpc/kernel/misc_32.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kernel/misc_32.S	2016-07-24 15:23:50.000000000 -0400
@@ -599,12 +599,6 @@ _GLOBAL(__bswapdi2)
 	mr      r4,r10
 	blr
 
-_GLOBAL(abs)
-	srawi	r4,r3,31
-	xor	r3,r3,r4
-	sub	r3,r3,r4
-	blr
-
 #ifdef CONFIG_SMP
 _GLOBAL(start_secondary_resume)
 	/* Reset stack */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kernel/nvram_64.c linux-libre-4.7-gnu/arch/powerpc/kernel/nvram_64.c
--- linux-libre-4.6-gnu/arch/powerpc/kernel/nvram_64.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kernel/nvram_64.c	2016-07-24 15:23:50.000000000 -0400
@@ -15,8 +15,6 @@
  *       parsing code.
  */
 
-#include <linux/module.h>
-
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
@@ -1231,12 +1229,4 @@ static int __init nvram_init(void)
   	
   	return rc;
 }
-
-static void __exit nvram_cleanup(void)
-{
-        misc_deregister( &nvram_dev );
-}
-
-module_init(nvram_init);
-module_exit(nvram_cleanup);
-MODULE_LICENSE("GPL");
+device_initcall(nvram_init);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kernel/pci_64.c linux-libre-4.7-gnu/arch/powerpc/kernel/pci_64.c
--- linux-libre-4.6-gnu/arch/powerpc/kernel/pci_64.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kernel/pci_64.c	2016-07-24 15:23:50.000000000 -0400
@@ -38,7 +38,7 @@
  * ISA drivers use hard coded offsets.  If no ISA bus exists nothing
  * is mapped on the first 64K of IO space
  */
-unsigned long pci_io_base = ISA_IO_BASE;
+unsigned long pci_io_base;
 EXPORT_SYMBOL(pci_io_base);
 
 static int __init pcibios_init(void)
@@ -159,7 +159,7 @@ static int pcibios_map_phb_io_space(stru
 
 	/* Establish the mapping */
 	if (__ioremap_at(phys_page, area->addr, size_page,
-			 _PAGE_NO_CACHE | _PAGE_GUARDED) == NULL)
+			 pgprot_val(pgprot_noncached(__pgprot(0)))) == NULL)
 		return -ENOMEM;
 
 	/* Fixup hose IO resource */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kernel/pci_dn.c linux-libre-4.7-gnu/arch/powerpc/kernel/pci_dn.c
--- linux-libre-4.6-gnu/arch/powerpc/kernel/pci_dn.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kernel/pci_dn.c	2016-07-24 15:23:50.000000000 -0400
@@ -282,13 +282,9 @@ void remove_dev_pci_data(struct pci_dev
 #endif /* CONFIG_PCI_IOV */
 }
 
-/*
- * Traverse_func that inits the PCI fields of the device node.
- * NOTE: this *must* be done before read/write config to the device.
- */
-void *update_dn_pci_info(struct device_node *dn, void *data)
+struct pci_dn *pci_add_device_node_info(struct pci_controller *hose,
+					struct device_node *dn)
 {
-	struct pci_controller *phb = data;
 	const __be32 *type = of_get_property(dn, "ibm,pci-config-space-type", NULL);
 	const __be32 *regs;
 	struct device_node *parent;
@@ -299,7 +295,7 @@ void *update_dn_pci_info(struct device_n
 		return NULL;
 	dn->data = pdn;
 	pdn->node = dn;
-	pdn->phb = phb;
+	pdn->phb = hose;
 #ifdef CONFIG_PPC_POWERNV
 	pdn->pe_number = IODA_INVALID_PE;
 #endif
@@ -331,8 +327,32 @@ void *update_dn_pci_info(struct device_n
 	if (pdn->parent)
 		list_add_tail(&pdn->list, &pdn->parent->child_list);
 
-	return NULL;
+	return pdn;
+}
+EXPORT_SYMBOL_GPL(pci_add_device_node_info);
+
+void pci_remove_device_node_info(struct device_node *dn)
+{
+	struct pci_dn *pdn = dn ? PCI_DN(dn) : NULL;
+#ifdef CONFIG_EEH
+	struct eeh_dev *edev = pdn_to_eeh_dev(pdn);
+
+	if (edev)
+		edev->pdn = NULL;
+#endif
+
+	if (!pdn)
+		return;
+
+	WARN_ON(!list_empty(&pdn->child_list));
+	list_del(&pdn->list);
+	if (pdn->parent)
+		of_node_put(pdn->parent->node);
+
+	dn->data = NULL;
+	kfree(pdn);
 }
+EXPORT_SYMBOL_GPL(pci_remove_device_node_info);
 
 /*
  * Traverse a device tree stopping each PCI device in the tree.
@@ -352,8 +372,9 @@ void *update_dn_pci_info(struct device_n
  * one of these nodes we also assume its siblings are non-pci for
  * performance.
  */
-void *traverse_pci_devices(struct device_node *start, traverse_func pre,
-		void *data)
+void *pci_traverse_device_nodes(struct device_node *start,
+				void *(*fn)(struct device_node *, void *),
+				void *data)
 {
 	struct device_node *dn, *nextdn;
 	void *ret;
@@ -368,8 +389,11 @@ void *traverse_pci_devices(struct device
 		if (classp)
 			class = of_read_number(classp, 1);
 
-		if (pre && ((ret = pre(dn, data)) != NULL))
-			return ret;
+		if (fn) {
+			ret = fn(dn, data);
+			if (ret)
+				return ret;
+		}
 
 		/* If we are a PCI bridge, go down */
 		if (dn->child && ((class >> 8) == PCI_CLASS_BRIDGE_PCI ||
@@ -391,6 +415,7 @@ void *traverse_pci_devices(struct device
 	}
 	return NULL;
 }
+EXPORT_SYMBOL_GPL(pci_traverse_device_nodes);
 
 static struct pci_dn *pci_dn_next_one(struct pci_dn *root,
 				      struct pci_dn *pdn)
@@ -432,6 +457,18 @@ void *traverse_pci_dn(struct pci_dn *roo
 	return NULL;
 }
 
+static void *add_pdn(struct device_node *dn, void *data)
+{
+	struct pci_controller *hose = data;
+	struct pci_dn *pdn;
+
+	pdn = pci_add_device_node_info(hose, dn);
+	if (!pdn)
+		return ERR_PTR(-ENOMEM);
+
+	return NULL;
+}
+
 /** 
  * pci_devs_phb_init_dynamic - setup pci devices under this PHB
  * phb: pci-to-host bridge (top-level bridge connecting to cpu)
@@ -446,8 +483,7 @@ void pci_devs_phb_init_dynamic(struct pc
 	struct pci_dn *pdn;
 
 	/* PHB nodes themselves must not match */
-	update_dn_pci_info(dn, phb);
-	pdn = dn->data;
+	pdn = pci_add_device_node_info(phb, dn);
 	if (pdn) {
 		pdn->devfn = pdn->busno = -1;
 		pdn->vendor_id = pdn->device_id = pdn->class_code = 0;
@@ -456,7 +492,7 @@ void pci_devs_phb_init_dynamic(struct pc
 	}
 
 	/* Update dn->phb ptrs for new phb and children devices */
-	traverse_pci_devices(dn, update_dn_pci_info, phb);
+	pci_traverse_device_nodes(dn, add_pdn, phb);
 }
 
 /** 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kernel/pci-hotplug.c linux-libre-4.7-gnu/arch/powerpc/kernel/pci-hotplug.c
--- linux-libre-4.6-gnu/arch/powerpc/kernel/pci-hotplug.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kernel/pci-hotplug.c	2016-07-24 15:23:50.000000000 -0400
@@ -21,6 +21,35 @@
 #include <asm/firmware.h>
 #include <asm/eeh.h>
 
+static struct pci_bus *find_bus_among_children(struct pci_bus *bus,
+					       struct device_node *dn)
+{
+	struct pci_bus *child = NULL;
+	struct pci_bus *tmp;
+
+	if (pci_bus_to_OF_node(bus) == dn)
+		return bus;
+
+	list_for_each_entry(tmp, &bus->children, node) {
+		child = find_bus_among_children(tmp, dn);
+		if (child)
+			break;
+	}
+
+	return child;
+}
+
+struct pci_bus *pci_find_bus_by_node(struct device_node *dn)
+{
+	struct pci_dn *pdn = PCI_DN(dn);
+
+	if (!pdn  || !pdn->phb || !pdn->phb->bus)
+		return NULL;
+
+	return find_bus_among_children(pdn->phb->bus, dn);
+}
+EXPORT_SYMBOL_GPL(pci_find_bus_by_node);
+
 /**
  * pcibios_release_device - release PCI device
  * @dev: PCI device
@@ -38,20 +67,20 @@ void pcibios_release_device(struct pci_d
 }
 
 /**
- * pcibios_remove_pci_devices - remove all devices under this bus
+ * pci_hp_remove_devices - remove all devices under this bus
  * @bus: the indicated PCI bus
  *
  * Remove all of the PCI devices under this bus both from the
  * linux pci device tree, and from the powerpc EEH address cache.
  */
-void pcibios_remove_pci_devices(struct pci_bus *bus)
+void pci_hp_remove_devices(struct pci_bus *bus)
 {
 	struct pci_dev *dev, *tmp;
 	struct pci_bus *child_bus;
 
 	/* First go down child busses */
 	list_for_each_entry(child_bus, &bus->children, node)
-		pcibios_remove_pci_devices(child_bus);
+		pci_hp_remove_devices(child_bus);
 
 	pr_debug("PCI: Removing devices on bus %04x:%02x\n",
 		 pci_domain_nr(bus),  bus->number);
@@ -60,11 +89,10 @@ void pcibios_remove_pci_devices(struct p
 		pci_stop_and_remove_bus_device(dev);
 	}
 }
-
-EXPORT_SYMBOL_GPL(pcibios_remove_pci_devices);
+EXPORT_SYMBOL_GPL(pci_hp_remove_devices);
 
 /**
- * pcibios_add_pci_devices - adds new pci devices to bus
+ * pci_hp_add_devices - adds new pci devices to bus
  * @bus: the indicated PCI bus
  *
  * This routine will find and fixup new pci devices under
@@ -74,7 +102,7 @@ EXPORT_SYMBOL_GPL(pcibios_remove_pci_dev
  * is how this routine differs from other, similar pcibios
  * routines.)
  */
-void pcibios_add_pci_devices(struct pci_bus * bus)
+void pci_hp_add_devices(struct pci_bus *bus)
 {
 	int slotno, mode, pass, max;
 	struct pci_dev *dev;
@@ -92,7 +120,8 @@ void pcibios_add_pci_devices(struct pci_
 	if (mode == PCI_PROBE_DEVTREE) {
 		/* use ofdt-based probe */
 		of_rescan_bus(dn, bus);
-	} else if (mode == PCI_PROBE_NORMAL) {
+	} else if (mode == PCI_PROBE_NORMAL &&
+		   dn->child && PCI_DN(dn->child)) {
 		/*
 		 * Use legacy probe. In the partial hotplug case, we
 		 * probably have grandchildren devices unplugged. So
@@ -114,4 +143,4 @@ void pcibios_add_pci_devices(struct pci_
 	}
 	pcibios_finish_adding_to_bus(bus);
 }
-EXPORT_SYMBOL_GPL(pcibios_add_pci_devices);
+EXPORT_SYMBOL_GPL(pci_hp_add_devices);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kernel/process.c linux-libre-4.7-gnu/arch/powerpc/kernel/process.c
--- linux-libre-4.6-gnu/arch/powerpc/kernel/process.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kernel/process.c	2016-07-24 15:23:50.000000000 -0400
@@ -38,6 +38,7 @@
 #include <linux/random.h>
 #include <linux/hw_breakpoint.h>
 #include <linux/uaccess.h>
+#include <linux/elf-randomize.h>
 
 #include <asm/pgtable.h>
 #include <asm/io.h>
@@ -55,6 +56,9 @@
 #include <asm/firmware.h>
 #endif
 #include <asm/code-patching.h>
+#include <asm/exec.h>
+#include <asm/livepatch.h>
+
 #include <linux/kprobes.h>
 #include <linux/kdebug.h>
 
@@ -1075,7 +1079,7 @@ struct task_struct *__switch_to(struct t
 	}
 #endif /* CONFIG_PPC64 */
 
-#ifdef CONFIG_PPC_BOOK3S_64
+#ifdef CONFIG_PPC_STD_MMU_64
 	batch = this_cpu_ptr(&ppc64_tlb_batch);
 	if (batch->active) {
 		current_thread_info()->local_flags |= _TLF_LAZY_MMU;
@@ -1083,7 +1087,7 @@ struct task_struct *__switch_to(struct t
 			__flush_tlb_pending(batch);
 		batch->active = 0;
 	}
-#endif /* CONFIG_PPC_BOOK3S_64 */
+#endif /* CONFIG_PPC_STD_MMU_64 */
 
 #ifdef CONFIG_PPC_ADV_DEBUG_REGS
 	switch_booke_debug_regs(&new->thread.debug);
@@ -1129,7 +1133,7 @@ struct task_struct *__switch_to(struct t
 
 	last = _switch(old_thread, new_thread);
 
-#ifdef CONFIG_PPC_BOOK3S_64
+#ifdef CONFIG_PPC_STD_MMU_64
 	if (current_thread_info()->local_flags & _TLF_LAZY_MMU) {
 		current_thread_info()->local_flags &= ~_TLF_LAZY_MMU;
 		batch = this_cpu_ptr(&ppc64_tlb_batch);
@@ -1138,8 +1142,7 @@ struct task_struct *__switch_to(struct t
 
 	if (current_thread_info()->task->thread.regs)
 		restore_math(current_thread_info()->task->thread.regs);
-
-#endif /* CONFIG_PPC_BOOK3S_64 */
+#endif /* CONFIG_PPC_STD_MMU_64 */
 
 	return last;
 }
@@ -1326,10 +1329,6 @@ void show_regs(struct pt_regs * regs)
 		show_instructions(regs);
 }
 
-void exit_thread(void)
-{
-}
-
 void flush_thread(void)
 {
 #ifdef CONFIG_HAVE_HW_BREAKPOINT
@@ -1374,6 +1373,9 @@ static void setup_ksp_vsid(struct task_s
 	unsigned long sp_vsid;
 	unsigned long llp = mmu_psize_defs[mmu_linear_psize].sllp;
 
+	if (radix_enabled())
+		return;
+
 	if (mmu_has_feature(MMU_FTR_1T_SEGMENT))
 		sp_vsid = get_kernel_vsid(sp, MMU_SEGSIZE_1T)
 			<< SLB_VSID_SHIFT_1T;
@@ -1400,13 +1402,15 @@ int copy_thread(unsigned long clone_flag
 	extern void ret_from_kernel_thread(void);
 	void (*f)(void);
 	unsigned long sp = (unsigned long)task_stack_page(p) + THREAD_SIZE;
+	struct thread_info *ti = task_thread_info(p);
+
+	klp_init_thread_info(ti);
 
 	/* Copy registers */
 	sp -= sizeof(struct pt_regs);
 	childregs = (struct pt_regs *) sp;
 	if (unlikely(p->flags & PF_KTHREAD)) {
 		/* kernel thread */
-		struct thread_info *ti = (void *)task_stack_page(p);
 		memset(childregs, 0, sizeof(struct pt_regs));
 		childregs->gpr[1] = sp + sizeof(struct pt_regs);
 		/* function */
@@ -1501,6 +1505,16 @@ void start_thread(struct pt_regs *regs,
 		current->thread.regs = regs - 1;
 	}
 
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+	/*
+	 * Clear any transactional state, we're exec()ing. The cause is
+	 * not important as there will never be a recheckpoint so it's not
+	 * user visible.
+	 */
+	if (MSR_TM_SUSPENDED(mfmsr()))
+		tm_reclaim_current(0);
+#endif
+
 	memset(regs->gpr, 0, sizeof(regs->gpr));
 	regs->ctr = 0;
 	regs->link = 0;
@@ -1920,7 +1934,8 @@ unsigned long arch_randomize_brk(struct
 	 * the heap, we can put it above 1TB so it is backed by a 1TB
 	 * segment. Otherwise the heap will be in the bottom 1TB
 	 * which always uses 256MB segments and this may result in a
-	 * performance penalty.
+	 * performance penalty. We don't need to worry about radix. For
+	 * radix, mmu_highuser_ssize remains unchanged from 256MB.
 	 */
 	if (!is_32bit_task() && (mmu_highuser_ssize == MMU_SEGSIZE_1T))
 		base = max_t(unsigned long, mm->brk, 1UL << SID_SHIFT_1T);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kernel/prom.c linux-libre-4.7-gnu/arch/powerpc/kernel/prom.c
--- linux-libre-4.6-gnu/arch/powerpc/kernel/prom.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kernel/prom.c	2016-07-24 15:23:50.000000000 -0400
@@ -34,6 +34,7 @@
 #include <linux/of.h>
 #include <linux/of_fdt.h>
 #include <linux/libfdt.h>
+#include <linux/cpu.h>
 
 #include <asm/prom.h>
 #include <asm/rtas.h>
@@ -167,6 +168,7 @@ static struct ibm_pa_feature {
 	 */
 	{CPU_FTR_TM_COMP, 0, 0,
 	 PPC_FEATURE2_HTM_COMP|PPC_FEATURE2_HTM_NOSC_COMP, 22, 0, 0},
+	{0, MMU_FTR_RADIX, 0, 0,		40, 0, 0},
 };
 
 static void __init scan_features(unsigned long node, const unsigned char *ftrs,
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kernel/prom_init.c linux-libre-4.7-gnu/arch/powerpc/kernel/prom_init.c
--- linux-libre-4.6-gnu/arch/powerpc/kernel/prom_init.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kernel/prom_init.c	2016-07-24 15:23:50.000000000 -0400
@@ -656,6 +656,7 @@ unsigned char ibm_architecture_vec[] = {
 	W(0xffff0000), W(0x003e0000),	/* POWER6 */
 	W(0xffff0000), W(0x003f0000),	/* POWER7 */
 	W(0xffff0000), W(0x004b0000),	/* POWER8E */
+	W(0xffff0000), W(0x004c0000),   /* POWER8NVL */
 	W(0xffff0000), W(0x004d0000),	/* POWER8 */
 	W(0xffffffff), W(0x0f000004),	/* all 2.07-compliant */
 	W(0xffffffff), W(0x0f000003),	/* all 2.06-compliant */
@@ -718,7 +719,7 @@ unsigned char ibm_architecture_vec[] = {
 	 * must match by the macro below. Update the definition if
 	 * the structure layout changes.
 	 */
-#define IBM_ARCH_VEC_NRCORES_OFFSET	125
+#define IBM_ARCH_VEC_NRCORES_OFFSET	133
 	W(NR_CPUS),			/* number of cores supported */
 	0,
 	0,
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kernel/ptrace.c linux-libre-4.7-gnu/arch/powerpc/kernel/ptrace.c
--- linux-libre-4.6-gnu/arch/powerpc/kernel/ptrace.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kernel/ptrace.c	2016-07-24 15:23:50.000000000 -0400
@@ -377,7 +377,7 @@ static int fpr_get(struct task_struct *t
 
 #else
 	BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) !=
-		     offsetof(struct thread_fp_state, fpr[32][0]));
+		     offsetof(struct thread_fp_state, fpr[32]));
 
 	return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
 				   &target->thread.fp_state, 0, -1);
@@ -405,7 +405,7 @@ static int fpr_set(struct task_struct *t
 	return 0;
 #else
 	BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) !=
-		     offsetof(struct thread_fp_state, fpr[32][0]));
+		     offsetof(struct thread_fp_state, fpr[32]));
 
 	return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 				  &target->thread.fp_state, 0, -1);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kernel/rtasd.c linux-libre-4.7-gnu/arch/powerpc/kernel/rtasd.c
--- linux-libre-4.6-gnu/arch/powerpc/kernel/rtasd.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kernel/rtasd.c	2016-07-24 15:23:50.000000000 -0400
@@ -442,7 +442,7 @@ static void do_event_scan(void)
 }
 
 static void rtas_event_scan(struct work_struct *w);
-DECLARE_DELAYED_WORK(event_scan_work, rtas_event_scan);
+static DECLARE_DELAYED_WORK(event_scan_work, rtas_event_scan);
 
 /*
  * Delay should be at least one second since some machines have problems if
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kernel/setup_64.c linux-libre-4.7-gnu/arch/powerpc/kernel/setup_64.c
--- linux-libre-4.6-gnu/arch/powerpc/kernel/setup_64.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kernel/setup_64.c	2016-07-24 15:23:50.000000000 -0400
@@ -69,6 +69,7 @@
 #include <asm/kvm_ppc.h>
 #include <asm/hugetlb.h>
 #include <asm/epapr_hcalls.h>
+#include <asm/livepatch.h>
 
 #ifdef DEBUG
 #define DBG(fmt...) udbg_printf(fmt)
@@ -667,16 +668,16 @@ static void __init emergency_stack_init(
 	limit = min(safe_stack_limit(), ppc64_rma_size);
 
 	for_each_possible_cpu(i) {
-		unsigned long sp;
-		sp  = memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit);
-		sp += THREAD_SIZE;
-		paca[i].emergency_sp = __va(sp);
+		struct thread_info *ti;
+		ti = __va(memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit));
+		klp_init_thread_info(ti);
+		paca[i].emergency_sp = (void *)ti + THREAD_SIZE;
 
 #ifdef CONFIG_PPC_BOOK3S_64
 		/* emergency stack for machine check exception handling. */
-		sp  = memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit);
-		sp += THREAD_SIZE;
-		paca[i].mc_emergency_sp = __va(sp);
+		ti = __va(memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit));
+		klp_init_thread_info(ti);
+		paca[i].mc_emergency_sp = (void *)ti + THREAD_SIZE;
 #endif
 	}
 }
@@ -700,6 +701,8 @@ void __init setup_arch(char **cmdline_p)
 	if (ppc_md.panic)
 		setup_panic();
 
+	klp_init_thread_info(&init_thread_info);
+
 	init_mm.start_code = (unsigned long)_stext;
 	init_mm.end_code = (unsigned long) _etext;
 	init_mm.end_data = (unsigned long) _edata;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kernel/setup-common.c linux-libre-4.7-gnu/arch/powerpc/kernel/setup-common.c
--- linux-libre-4.6-gnu/arch/powerpc/kernel/setup-common.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kernel/setup-common.c	2016-07-24 15:23:50.000000000 -0400
@@ -128,9 +128,7 @@ void machine_restart(char *cmd)
 	machine_shutdown();
 	if (ppc_md.restart)
 		ppc_md.restart(cmd);
-#ifdef CONFIG_SMP
 	smp_send_stop();
-#endif
 	printk(KERN_EMERG "System Halted, OK to turn off power\n");
 	local_irq_disable();
 	while (1) ;
@@ -141,9 +139,7 @@ void machine_power_off(void)
 	machine_shutdown();
 	if (pm_power_off)
 		pm_power_off();
-#ifdef CONFIG_SMP
 	smp_send_stop();
-#endif
 	printk(KERN_EMERG "System Halted, OK to turn off power\n");
 	local_irq_disable();
 	while (1) ;
@@ -159,9 +155,7 @@ void machine_halt(void)
 	machine_shutdown();
 	if (ppc_md.halt)
 		ppc_md.halt();
-#ifdef CONFIG_SMP
 	smp_send_stop();
-#endif
 	printk(KERN_EMERG "System Halted, OK to turn off power\n");
 	local_irq_disable();
 	while (1) ;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kernel/smp.c linux-libre-4.7-gnu/arch/powerpc/kernel/smp.c
--- linux-libre-4.6-gnu/arch/powerpc/kernel/smp.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kernel/smp.c	2016-07-24 15:23:50.000000000 -0400
@@ -565,7 +565,7 @@ int __cpu_up(unsigned int cpu, struct ta
 		smp_ops->give_timebase();
 
 	/* Wait until cpu puts itself in the online & active maps */
-	while (!cpu_online(cpu) || !cpu_active(cpu))
+	while (!cpu_online(cpu))
 		cpu_relax();
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kernel/swsusp.c linux-libre-4.7-gnu/arch/powerpc/kernel/swsusp.c
--- linux-libre-4.6-gnu/arch/powerpc/kernel/swsusp.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kernel/swsusp.c	2016-07-24 15:23:50.000000000 -0400
@@ -31,6 +31,6 @@ void save_processor_state(void)
 void restore_processor_state(void)
 {
 #ifdef CONFIG_PPC32
-	switch_mmu_context(current->active_mm, current->active_mm);
+	switch_mmu_context(current->active_mm, current->active_mm, NULL);
 #endif
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kernel/time.c linux-libre-4.7-gnu/arch/powerpc/kernel/time.c
--- linux-libre-4.6-gnu/arch/powerpc/kernel/time.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kernel/time.c	2016-07-24 15:23:50.000000000 -0400
@@ -55,6 +55,7 @@
 #include <linux/delay.h>
 #include <linux/irq_work.h>
 #include <linux/clk-provider.h>
+#include <linux/suspend.h>
 #include <asm/trace.h>
 
 #include <asm/io.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kernel/tm.S linux-libre-4.7-gnu/arch/powerpc/kernel/tm.S
--- linux-libre-4.6-gnu/arch/powerpc/kernel/tm.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kernel/tm.S	2016-07-24 15:23:50.000000000 -0400
@@ -110,17 +110,11 @@ _GLOBAL(tm_reclaim)
 	std	r3, STK_PARAM(R3)(r1)
 	SAVE_NVGPRS(r1)
 
-	/* We need to setup MSR for VSX register save instructions.  Here we
-	 * also clear the MSR RI since when we do the treclaim, we won't have a
-	 * valid kernel pointer for a while.  We clear RI here as it avoids
-	 * adding another mtmsr closer to the treclaim.  This makes the region
-	 * maked as non-recoverable wider than it needs to be but it saves on
-	 * inserting another mtmsrd later.
-	 */
+	/* We need to setup MSR for VSX register save instructions. */
 	mfmsr	r14
 	mr	r15, r14
 	ori	r15, r15, MSR_FP
-	li	r16, MSR_RI
+	li	r16, 0
 	ori	r16, r16, MSR_EE /* IRQs hard off */
 	andc	r15, r15, r16
 	oris	r15, r15, MSR_VEC@h
@@ -176,7 +170,17 @@ dont_backup_fp:
 1:	tdeqi   r6, 0
 	EMIT_BUG_ENTRY 1b,__FILE__,__LINE__,0
 
-	/* The moment we treclaim, ALL of our GPRs will switch
+	/* Clear MSR RI since we are about to change r1, EE is already off. */
+	li	r4, 0
+	mtmsrd	r4, 1
+
+	/*
+	 * BE CAREFUL HERE:
+	 * At this point we can't take an SLB miss since we have MSR_RI
+	 * off. Load only to/from the stack/paca which are in SLB bolted regions
+	 * until we turn MSR RI back on.
+	 *
+	 * The moment we treclaim, ALL of our GPRs will switch
 	 * to user register state.  (FPRs, CCR etc. also!)
 	 * Use an sprg and a tm_scratch in the PACA to shuffle.
 	 */
@@ -197,6 +201,11 @@ dont_backup_fp:
 
 	/* Store the PPR in r11 and reset to decent value */
 	std	r11, GPR11(r1)			/* Temporary stash */
+
+	/* Reset MSR RI so we can take SLB faults again */
+	li	r11, MSR_RI
+	mtmsrd	r11, 1
+
 	mfspr	r11, SPRN_PPR
 	HMT_MEDIUM
 
@@ -397,11 +406,6 @@ restore_gprs:
 	ld	r5, THREAD_TM_DSCR(r3)
 	ld	r6, THREAD_TM_PPR(r3)
 
-	/* Clear the MSR RI since we are about to change R1.  EE is already off
-	 */
-	li	r4, 0
-	mtmsrd	r4, 1
-
 	REST_GPR(0, r7)				/* GPR0 */
 	REST_2GPRS(2, r7)			/* GPR2-3 */
 	REST_GPR(4, r7)				/* GPR4 */
@@ -439,10 +443,33 @@ restore_gprs:
 	ld	r6, _CCR(r7)
 	mtcr    r6
 
-	REST_GPR(1, r7)				/* GPR1 */
-	REST_GPR(5, r7)				/* GPR5-7 */
 	REST_GPR(6, r7)
-	ld	r7, GPR7(r7)
+
+	/*
+	 * Store r1 and r5 on the stack so that we can access them
+	 * after we clear MSR RI.
+	 */
+
+	REST_GPR(5, r7)
+	std	r5, -8(r1)
+	ld	r5, GPR1(r7)
+	std	r5, -16(r1)
+
+	REST_GPR(7, r7)
+
+	/* Clear MSR RI since we are about to change r1. EE is already off */
+	li	r5, 0
+	mtmsrd	r5, 1
+
+	/*
+	 * BE CAREFUL HERE:
+	 * At this point we can't take an SLB miss since we have MSR_RI
+	 * off. Load only to/from the stack/paca which are in SLB bolted regions
+	 * until we turn MSR RI back on.
+	 */
+
+	ld	r5, -8(r1)
+	ld	r1, -16(r1)
 
 	/* Commit register state as checkpointed state: */
 	TRECHKPT
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kernel/vdso.c linux-libre-4.7-gnu/arch/powerpc/kernel/vdso.c
--- linux-libre-4.6-gnu/arch/powerpc/kernel/vdso.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kernel/vdso.c	2016-07-24 15:23:50.000000000 -0400
@@ -195,7 +195,8 @@ int arch_setup_additional_pages(struct l
 	 * and end up putting it elsewhere.
 	 * Add enough to the size so that the result can be aligned.
 	 */
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
 	vdso_base = get_unmapped_area(NULL, vdso_base,
 				      (vdso_pages << PAGE_SHIFT) +
 				      ((VDSO_ALIGNMENT - 1) & PAGE_MASK),
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kernel/vio.c linux-libre-4.7-gnu/arch/powerpc/kernel/vio.c
--- linux-libre-4.6-gnu/arch/powerpc/kernel/vio.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kernel/vio.c	2016-07-24 15:23:50.000000000 -0400
@@ -87,7 +87,7 @@ struct vio_cmo_dev_entry {
  * @curr: bytes currently allocated
  * @high: high water mark for IO data usage
  */
-struct vio_cmo {
+static struct vio_cmo {
 	spinlock_t lock;
 	struct delayed_work balance_q;
 	struct list_head device_list;
@@ -615,7 +615,7 @@ static u64 vio_dma_get_required_mask(str
         return dma_iommu_ops.get_required_mask(dev);
 }
 
-struct dma_map_ops vio_dma_mapping_ops = {
+static struct dma_map_ops vio_dma_mapping_ops = {
 	.alloc             = vio_dma_iommu_alloc_coherent,
 	.free              = vio_dma_iommu_free_coherent,
 	.mmap		   = dma_direct_mmap_coherent,
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kvm/book3s_64_mmu_hv.c linux-libre-4.7-gnu/arch/powerpc/kvm/book3s_64_mmu_hv.c
--- linux-libre-4.6-gnu/arch/powerpc/kvm/book3s_64_mmu_hv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kvm/book3s_64_mmu_hv.c	2016-07-24 15:23:50.000000000 -0400
@@ -447,7 +447,7 @@ int kvmppc_book3s_hv_page_fault(struct k
 	struct revmap_entry *rev;
 	struct page *page, *pages[1];
 	long index, ret, npages;
-	unsigned long is_io;
+	bool is_ci;
 	unsigned int writing, write_ok;
 	struct vm_area_struct *vma;
 	unsigned long rcbits;
@@ -503,7 +503,7 @@ int kvmppc_book3s_hv_page_fault(struct k
 	smp_rmb();
 
 	ret = -EFAULT;
-	is_io = 0;
+	is_ci = false;
 	pfn = 0;
 	page = NULL;
 	pte_size = PAGE_SIZE;
@@ -521,7 +521,7 @@ int kvmppc_book3s_hv_page_fault(struct k
 			pfn = vma->vm_pgoff +
 				((hva - vma->vm_start) >> PAGE_SHIFT);
 			pte_size = psize;
-			is_io = hpte_cache_bits(pgprot_val(vma->vm_page_prot));
+			is_ci = pte_ci(__pte((pgprot_val(vma->vm_page_prot))));
 			write_ok = vma->vm_flags & VM_WRITE;
 		}
 		up_read(&current->mm->mmap_sem);
@@ -558,10 +558,9 @@ int kvmppc_book3s_hv_page_fault(struct k
 		goto out_put;
 
 	/* Check WIMG vs. the actual page we're accessing */
-	if (!hpte_cache_flags_ok(r, is_io)) {
-		if (is_io)
+	if (!hpte_cache_flags_ok(r, is_ci)) {
+		if (is_ci)
 			goto out_put;
-
 		/*
 		 * Allow guest to map emulated device memory as
 		 * uncacheable, but actually make it cacheable.
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kvm/book3s.c linux-libre-4.7-gnu/arch/powerpc/kvm/book3s.c
--- linux-libre-4.6-gnu/arch/powerpc/kvm/book3s.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kvm/book3s.c	2016-07-24 15:23:50.000000000 -0400
@@ -54,6 +54,7 @@ struct kvm_stats_debugfs_item debugfs_en
 	{ "queue_intr",  VCPU_STAT(queue_intr) },
 	{ "halt_successful_poll", VCPU_STAT(halt_successful_poll), },
 	{ "halt_attempted_poll", VCPU_STAT(halt_attempted_poll), },
+	{ "halt_poll_invalid", VCPU_STAT(halt_poll_invalid) },
 	{ "halt_wakeup", VCPU_STAT(halt_wakeup) },
 	{ "pf_storage",  VCPU_STAT(pf_storage) },
 	{ "sp_storage",  VCPU_STAT(sp_storage) },
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kvm/book3s_hv.c linux-libre-4.7-gnu/arch/powerpc/kvm/book3s_hv.c
--- linux-libre-4.6-gnu/arch/powerpc/kvm/book3s_hv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kvm/book3s_hv.c	2016-07-24 15:23:50.000000000 -0400
@@ -27,6 +27,7 @@
 #include <linux/export.h>
 #include <linux/fs.h>
 #include <linux/anon_inodes.h>
+#include <linux/cpu.h>
 #include <linux/cpumask.h>
 #include <linux/spinlock.h>
 #include <linux/page-flags.h>
@@ -3271,6 +3272,12 @@ static int kvmppc_core_check_processor_c
 	if (!cpu_has_feature(CPU_FTR_HVMODE) ||
 	    !cpu_has_feature(CPU_FTR_ARCH_206))
 		return -EIO;
+	/*
+	 * Disable KVM for Power9, untill the required bits merged.
+	 */
+	if (cpu_has_feature(CPU_FTR_ARCH_300))
+		return -EIO;
+
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kvm/book3s_hv_rm_mmu.c linux-libre-4.7-gnu/arch/powerpc/kvm/book3s_hv_rm_mmu.c
--- linux-libre-4.6-gnu/arch/powerpc/kvm/book3s_hv_rm_mmu.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kvm/book3s_hv_rm_mmu.c	2016-07-24 15:23:50.000000000 -0400
@@ -175,7 +175,7 @@ long kvmppc_do_h_enter(struct kvm *kvm,
 	unsigned long g_ptel;
 	struct kvm_memory_slot *memslot;
 	unsigned hpage_shift;
-	unsigned long is_io;
+	bool is_ci;
 	unsigned long *rmap;
 	pte_t *ptep;
 	unsigned int writing;
@@ -199,7 +199,7 @@ long kvmppc_do_h_enter(struct kvm *kvm,
 	gfn = gpa >> PAGE_SHIFT;
 	memslot = __gfn_to_memslot(kvm_memslots_raw(kvm), gfn);
 	pa = 0;
-	is_io = ~0ul;
+	is_ci = false;
 	rmap = NULL;
 	if (!(memslot && !(memslot->flags & KVM_MEMSLOT_INVALID))) {
 		/* Emulated MMIO - mark this with key=31 */
@@ -250,7 +250,7 @@ long kvmppc_do_h_enter(struct kvm *kvm,
 			if (writing && !pte_write(pte))
 				/* make the actual HPTE be read-only */
 				ptel = hpte_make_readonly(ptel);
-			is_io = hpte_cache_bits(pte_val(pte));
+			is_ci = pte_ci(pte);
 			pa = pte_pfn(pte) << PAGE_SHIFT;
 			pa |= hva & (host_pte_size - 1);
 			pa |= gpa & ~PAGE_MASK;
@@ -267,9 +267,9 @@ long kvmppc_do_h_enter(struct kvm *kvm,
 	else
 		pteh |= HPTE_V_ABSENT;
 
-	/* Check WIMG */
-	if (is_io != ~0ul && !hpte_cache_flags_ok(ptel, is_io)) {
-		if (is_io)
+	/*If we had host pte mapping then  Check WIMG */
+	if (ptep && !hpte_cache_flags_ok(ptel, is_ci)) {
+		if (is_ci)
 			return H_PARAMETER;
 		/*
 		 * Allow guest to map emulated device memory as
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kvm/book3s_pr.c linux-libre-4.7-gnu/arch/powerpc/kvm/book3s_pr.c
--- linux-libre-4.6-gnu/arch/powerpc/kvm/book3s_pr.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kvm/book3s_pr.c	2016-07-24 15:23:50.000000000 -0400
@@ -882,6 +882,24 @@ void kvmppc_set_fscr(struct kvm_vcpu *vc
 }
 #endif
 
+static void kvmppc_setup_debug(struct kvm_vcpu *vcpu)
+{
+	if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) {
+		u64 msr = kvmppc_get_msr(vcpu);
+
+		kvmppc_set_msr(vcpu, msr | MSR_SE);
+	}
+}
+
+static void kvmppc_clear_debug(struct kvm_vcpu *vcpu)
+{
+	if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) {
+		u64 msr = kvmppc_get_msr(vcpu);
+
+		kvmppc_set_msr(vcpu, msr & ~MSR_SE);
+	}
+}
+
 int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
 			  unsigned int exit_nr)
 {
@@ -1207,10 +1225,18 @@ program_interrupt:
 		break;
 #endif
 	case BOOK3S_INTERRUPT_MACHINE_CHECK:
-	case BOOK3S_INTERRUPT_TRACE:
 		kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
 		r = RESUME_GUEST;
 		break;
+	case BOOK3S_INTERRUPT_TRACE:
+		if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) {
+			run->exit_reason = KVM_EXIT_DEBUG;
+			r = RESUME_HOST;
+		} else {
+			kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
+			r = RESUME_GUEST;
+		}
+		break;
 	default:
 	{
 		ulong shadow_srr1 = vcpu->arch.shadow_srr1;
@@ -1479,6 +1505,8 @@ static int kvmppc_vcpu_run_pr(struct kvm
 		goto out;
 	}
 
+	kvmppc_setup_debug(vcpu);
+
 	/*
 	 * Interrupts could be timers for the guest which we have to inject
 	 * again, so let's postpone them until we're in the guest and if we
@@ -1501,6 +1529,8 @@ static int kvmppc_vcpu_run_pr(struct kvm
 
 	ret = __kvmppc_vcpu_run(kvm_run, vcpu);
 
+	kvmppc_clear_debug(vcpu);
+
 	/* No need for kvm_guest_exit. It's done in handle_exit.
 	   We also get here with interrupts enabled. */
 
@@ -1683,7 +1713,11 @@ static void kvmppc_core_destroy_vm_pr(st
 
 static int kvmppc_core_check_processor_compat_pr(void)
 {
-	/* we are always compatible */
+	/*
+	 * Disable KVM for Power9 untill the required bits merged.
+	 */
+	if (cpu_has_feature(CPU_FTR_ARCH_300))
+		return -EIO;
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kvm/book3s_xics.c linux-libre-4.7-gnu/arch/powerpc/kvm/book3s_xics.c
--- linux-libre-4.6-gnu/arch/powerpc/kvm/book3s_xics.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kvm/book3s_xics.c	2016-07-24 15:23:50.000000000 -0400
@@ -92,7 +92,7 @@ static int ics_deliver_irq(struct kvmppc
 	 * we are the only setter, thus concurrent access is undefined
 	 * to begin with.
 	 */
-	if (level == 1 || level == KVM_INTERRUPT_SET_LEVEL)
+	if ((level == 1 && state->lsi) || level == KVM_INTERRUPT_SET_LEVEL)
 		state->asserted = 1;
 	else if (level == 0 || level == KVM_INTERRUPT_UNSET) {
 		state->asserted = 0;
@@ -280,7 +280,7 @@ static inline bool icp_try_update(struct
 	if (!success)
 		goto bail;
 
-	XICS_DBG("UPD [%04x] - C:%02x M:%02x PP: %02x PI:%06x R:%d O:%d\n",
+	XICS_DBG("UPD [%04lx] - C:%02x M:%02x PP: %02x PI:%06x R:%d O:%d\n",
 		 icp->server_num,
 		 old.cppr, old.mfrr, old.pending_pri, old.xisr,
 		 old.need_resend, old.out_ee);
@@ -336,7 +336,7 @@ static bool icp_try_to_deliver(struct kv
 	union kvmppc_icp_state old_state, new_state;
 	bool success;
 
-	XICS_DBG("try deliver %#x(P:%#x) to server %#x\n", irq, priority,
+	XICS_DBG("try deliver %#x(P:%#x) to server %#lx\n", irq, priority,
 		 icp->server_num);
 
 	do {
@@ -1174,9 +1174,11 @@ static int xics_get_source(struct kvmppc
 			prio = irqp->saved_priority;
 		}
 		val |= prio << KVM_XICS_PRIORITY_SHIFT;
-		if (irqp->asserted)
-			val |= KVM_XICS_LEVEL_SENSITIVE | KVM_XICS_PENDING;
-		else if (irqp->masked_pending || irqp->resend)
+		if (irqp->lsi) {
+			val |= KVM_XICS_LEVEL_SENSITIVE;
+			if (irqp->asserted)
+				val |= KVM_XICS_PENDING;
+		} else if (irqp->masked_pending || irqp->resend)
 			val |= KVM_XICS_PENDING;
 		ret = 0;
 	}
@@ -1228,9 +1230,13 @@ static int xics_set_source(struct kvmppc
 	irqp->priority = prio;
 	irqp->resend = 0;
 	irqp->masked_pending = 0;
+	irqp->lsi = 0;
 	irqp->asserted = 0;
-	if ((val & KVM_XICS_PENDING) && (val & KVM_XICS_LEVEL_SENSITIVE))
-		irqp->asserted = 1;
+	if (val & KVM_XICS_LEVEL_SENSITIVE) {
+		irqp->lsi = 1;
+		if (val & KVM_XICS_PENDING)
+			irqp->asserted = 1;
+	}
 	irqp->exists = 1;
 	arch_spin_unlock(&ics->lock);
 	local_irq_restore(flags);
@@ -1249,11 +1255,10 @@ int kvm_set_irq(struct kvm *kvm, int irq
 	return ics_deliver_irq(xics, irq, level);
 }
 
-int kvm_set_msi(struct kvm_kernel_irq_routing_entry *irq_entry, struct kvm *kvm,
-		int irq_source_id, int level, bool line_status)
+int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *irq_entry,
+			      struct kvm *kvm, int irq_source_id,
+			      int level, bool line_status)
 {
-	if (!level)
-		return -1;
 	return kvm_set_irq(kvm, irq_source_id, irq_entry->gsi,
 			   level, line_status);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kvm/book3s_xics.h linux-libre-4.7-gnu/arch/powerpc/kvm/book3s_xics.h
--- linux-libre-4.6-gnu/arch/powerpc/kvm/book3s_xics.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kvm/book3s_xics.h	2016-07-24 15:23:50.000000000 -0400
@@ -39,6 +39,7 @@ struct ics_irq_state {
 	u8  saved_priority;
 	u8  resend;
 	u8  masked_pending;
+	u8  lsi;		/* level-sensitive interrupt */
 	u8  asserted; /* Only for LSI */
 	u8  exists;
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kvm/booke.c linux-libre-4.7-gnu/arch/powerpc/kvm/booke.c
--- linux-libre-4.6-gnu/arch/powerpc/kvm/booke.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kvm/booke.c	2016-07-24 15:23:50.000000000 -0400
@@ -64,6 +64,7 @@ struct kvm_stats_debugfs_item debugfs_en
 	{ "ext_intr",   VCPU_STAT(ext_intr_exits) },
 	{ "halt_successful_poll", VCPU_STAT(halt_successful_poll) },
 	{ "halt_attempted_poll", VCPU_STAT(halt_attempted_poll) },
+	{ "halt_poll_invalid", VCPU_STAT(halt_poll_invalid) },
 	{ "halt_wakeup", VCPU_STAT(halt_wakeup) },
 	{ "doorbell", VCPU_STAT(dbell_exits) },
 	{ "guest doorbell", VCPU_STAT(gdbell_exits) },
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/kvm/powerpc.c linux-libre-4.7-gnu/arch/powerpc/kvm/powerpc.c
--- linux-libre-4.6-gnu/arch/powerpc/kvm/powerpc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/kvm/powerpc.c	2016-07-24 15:23:50.000000000 -0400
@@ -800,9 +800,9 @@ static void kvmppc_complete_mmio_load(st
 	}
 }
 
-int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
-		       unsigned int rt, unsigned int bytes,
-		       int is_default_endian)
+static int __kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
+				unsigned int rt, unsigned int bytes,
+				int is_default_endian, int sign_extend)
 {
 	int idx, ret;
 	bool host_swabbed;
@@ -827,7 +827,7 @@ int kvmppc_handle_load(struct kvm_run *r
 	vcpu->arch.mmio_host_swabbed = host_swabbed;
 	vcpu->mmio_needed = 1;
 	vcpu->mmio_is_write = 0;
-	vcpu->arch.mmio_sign_extend = 0;
+	vcpu->arch.mmio_sign_extend = sign_extend;
 
 	idx = srcu_read_lock(&vcpu->kvm->srcu);
 
@@ -844,6 +844,13 @@ int kvmppc_handle_load(struct kvm_run *r
 
 	return EMULATE_DO_MMIO;
 }
+
+int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
+		       unsigned int rt, unsigned int bytes,
+		       int is_default_endian)
+{
+	return __kvmppc_handle_load(run, vcpu, rt, bytes, is_default_endian, 0);
+}
 EXPORT_SYMBOL_GPL(kvmppc_handle_load);
 
 /* Same as above, but sign extends */
@@ -851,12 +858,7 @@ int kvmppc_handle_loads(struct kvm_run *
 			unsigned int rt, unsigned int bytes,
 			int is_default_endian)
 {
-	int r;
-
-	vcpu->arch.mmio_sign_extend = 1;
-	r = kvmppc_handle_load(run, vcpu, rt, bytes, is_default_endian);
-
-	return r;
+	return __kvmppc_handle_load(run, vcpu, rt, bytes, is_default_endian, 1);
 }
 
 int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu,
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/lib/copy_32.S linux-libre-4.7-gnu/arch/powerpc/lib/copy_32.S
--- linux-libre-4.6-gnu/arch/powerpc/lib/copy_32.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/lib/copy_32.S	2016-07-24 15:23:50.000000000 -0400
@@ -217,7 +217,7 @@ _GLOBAL(memcpy)
 	bdnz	40b
 65:	blr
 
-_GLOBAL(generic_memcpy)
+generic_memcpy:
 	srwi.	r7,r5,3
 	addi	r6,r3,-4
 	addi	r4,r4,-4
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/lib/sstep.c linux-libre-4.7-gnu/arch/powerpc/lib/sstep.c
--- linux-libre-4.6-gnu/arch/powerpc/lib/sstep.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/lib/sstep.c	2016-07-24 15:23:50.000000000 -0400
@@ -925,6 +925,7 @@ int __kprobes analyse_instr(struct instr
 			}
 		}
 #endif
+	break; /* illegal instruction */
 
 	case 31:
 		switch ((instr >> 1) & 0x3ff) {
@@ -1818,9 +1819,11 @@ int __kprobes emulate_step(struct pt_reg
 		case 4:
 			__get_user_asmx(val, op.ea, err, "lwarx");
 			break;
+#ifdef __powerpc64__
 		case 8:
 			__get_user_asmx(val, op.ea, err, "ldarx");
 			break;
+#endif
 		default:
 			return 0;
 		}
@@ -1841,9 +1844,11 @@ int __kprobes emulate_step(struct pt_reg
 		case 4:
 			__put_user_asmx(op.val, op.ea, err, "stwcx.", cr);
 			break;
+#ifdef __powerpc64__
 		case 8:
 			__put_user_asmx(op.val, op.ea, err, "stdcx.", cr);
 			break;
+#endif
 		default:
 			return 0;
 		}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/lib/xor_vmx.c linux-libre-4.7-gnu/arch/powerpc/lib/xor_vmx.c
--- linux-libre-4.6-gnu/arch/powerpc/lib/xor_vmx.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/lib/xor_vmx.c	2016-07-24 15:23:50.000000000 -0400
@@ -17,7 +17,17 @@
  *
  * Author: Anton Blanchard <anton@au.ibm.com>
  */
+
+/*
+ * Sparse (as at v0.5.0) gets very, very confused by this file.
+ * Make it a bit simpler for it.
+ */
+#if !defined(__CHECKER__)
 #include <altivec.h>
+#else
+#define vec_xor(a, b) a ^ b
+#define vector __attribute__((vector_size(16)))
+#endif
 
 #include <linux/preempt.h>
 #include <linux/export.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/mm/fsl_booke_mmu.c linux-libre-4.7-gnu/arch/powerpc/mm/fsl_booke_mmu.c
--- linux-libre-4.6-gnu/arch/powerpc/mm/fsl_booke_mmu.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/mm/fsl_booke_mmu.c	2016-07-24 15:23:50.000000000 -0400
@@ -135,7 +135,7 @@ static void settlbcam(int index, unsigne
 		TLBCAM[index].MAS7 = (u64)phys >> 32;
 
 	/* Below is unlikely -- only for large user pages or similar */
-	if (pte_user(flags)) {
+	if (pte_user(__pte(flags))) {
 	   TLBCAM[index].MAS3 |= MAS3_UX | MAS3_UR;
 	   TLBCAM[index].MAS3 |= ((flags & _PAGE_RW) ? MAS3_UW : 0);
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/mm/hash64_4k.c linux-libre-4.7-gnu/arch/powerpc/mm/hash64_4k.c
--- linux-libre-4.6-gnu/arch/powerpc/mm/hash64_4k.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/mm/hash64_4k.c	2016-07-24 15:23:50.000000000 -0400
@@ -34,21 +34,21 @@ int __hash_page_4K(unsigned long ea, uns
 
 		old_pte = pte_val(pte);
 		/* If PTE busy, retry the access */
-		if (unlikely(old_pte & _PAGE_BUSY))
+		if (unlikely(old_pte & H_PAGE_BUSY))
 			return 0;
 		/* If PTE permissions don't match, take page fault */
-		if (unlikely(access & ~old_pte))
+		if (unlikely(!check_pte_access(access, old_pte)))
 			return 1;
 		/*
 		 * Try to lock the PTE, add ACCESSED and DIRTY if it was
 		 * a write access. Since this is 4K insert of 64K page size
-		 * also add _PAGE_COMBO
+		 * also add H_PAGE_COMBO
 		 */
-		new_pte = old_pte | _PAGE_BUSY | _PAGE_ACCESSED;
-		if (access & _PAGE_RW)
+		new_pte = old_pte | H_PAGE_BUSY | _PAGE_ACCESSED;
+		if (access & _PAGE_WRITE)
 			new_pte |= _PAGE_DIRTY;
-	} while (old_pte != __cmpxchg_u64((unsigned long *)ptep,
-					  old_pte, new_pte));
+	} while (!pte_xchg(ptep, __pte(old_pte), __pte(new_pte)));
+
 	/*
 	 * PP bits. _PAGE_USER is already PP bit 0x2, so we only
 	 * need to add in 0x1 if it's a read-only user page
@@ -60,22 +60,22 @@ int __hash_page_4K(unsigned long ea, uns
 		rflags = hash_page_do_lazy_icache(rflags, __pte(old_pte), trap);
 
 	vpn  = hpt_vpn(ea, vsid, ssize);
-	if (unlikely(old_pte & _PAGE_HASHPTE)) {
+	if (unlikely(old_pte & H_PAGE_HASHPTE)) {
 		/*
 		 * There MIGHT be an HPTE for this pte
 		 */
 		hash = hpt_hash(vpn, shift, ssize);
-		if (old_pte & _PAGE_F_SECOND)
+		if (old_pte & H_PAGE_F_SECOND)
 			hash = ~hash;
 		slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
-		slot += (old_pte & _PAGE_F_GIX) >> _PAGE_F_GIX_SHIFT;
+		slot += (old_pte & H_PAGE_F_GIX) >> H_PAGE_F_GIX_SHIFT;
 
 		if (ppc_md.hpte_updatepp(slot, rflags, vpn, MMU_PAGE_4K,
 					 MMU_PAGE_4K, ssize, flags) == -1)
 			old_pte &= ~_PAGE_HPTEFLAGS;
 	}
 
-	if (likely(!(old_pte & _PAGE_HASHPTE))) {
+	if (likely(!(old_pte & H_PAGE_HASHPTE))) {
 
 		pa = pte_pfn(__pte(old_pte)) << PAGE_SHIFT;
 		hash = hpt_hash(vpn, shift, ssize);
@@ -115,9 +115,10 @@ repeat:
 					   MMU_PAGE_4K, MMU_PAGE_4K, old_pte);
 			return -1;
 		}
-		new_pte = (new_pte & ~_PAGE_HPTEFLAGS) | _PAGE_HASHPTE;
-		new_pte |= (slot << _PAGE_F_GIX_SHIFT) & (_PAGE_F_SECOND | _PAGE_F_GIX);
+		new_pte = (new_pte & ~_PAGE_HPTEFLAGS) | H_PAGE_HASHPTE;
+		new_pte |= (slot << H_PAGE_F_GIX_SHIFT) &
+			(H_PAGE_F_SECOND | H_PAGE_F_GIX);
 	}
-	*ptep = __pte(new_pte & ~_PAGE_BUSY);
+	*ptep = __pte(new_pte & ~H_PAGE_BUSY);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/mm/hash64_64k.c linux-libre-4.7-gnu/arch/powerpc/mm/hash64_64k.c
--- linux-libre-4.6-gnu/arch/powerpc/mm/hash64_64k.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/mm/hash64_64k.c	2016-07-24 15:23:50.000000000 -0400
@@ -23,7 +23,7 @@ bool __rpte_sub_valid(real_pte_t rpte, u
 	unsigned long g_idx;
 	unsigned long ptev = pte_val(rpte.pte);
 
-	g_idx = (ptev & _PAGE_COMBO_VALID) >> _PAGE_F_GIX_SHIFT;
+	g_idx = (ptev & H_PAGE_COMBO_VALID) >> H_PAGE_F_GIX_SHIFT;
 	index = index >> 2;
 	if (g_idx & (0x1 << index))
 		return true;
@@ -37,12 +37,12 @@ static unsigned long mark_subptegroup_va
 {
 	unsigned long g_idx;
 
-	if (!(ptev & _PAGE_COMBO))
+	if (!(ptev & H_PAGE_COMBO))
 		return ptev;
 	index = index >> 2;
 	g_idx = 0x1 << index;
 
-	return ptev | (g_idx << _PAGE_F_GIX_SHIFT);
+	return ptev | (g_idx << H_PAGE_F_GIX_SHIFT);
 }
 
 int __hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid,
@@ -66,21 +66,21 @@ int __hash_page_4K(unsigned long ea, uns
 
 		old_pte = pte_val(pte);
 		/* If PTE busy, retry the access */
-		if (unlikely(old_pte & _PAGE_BUSY))
+		if (unlikely(old_pte & H_PAGE_BUSY))
 			return 0;
 		/* If PTE permissions don't match, take page fault */
-		if (unlikely(access & ~old_pte))
+		if (unlikely(!check_pte_access(access, old_pte)))
 			return 1;
 		/*
 		 * Try to lock the PTE, add ACCESSED and DIRTY if it was
 		 * a write access. Since this is 4K insert of 64K page size
-		 * also add _PAGE_COMBO
+		 * also add H_PAGE_COMBO
 		 */
-		new_pte = old_pte | _PAGE_BUSY | _PAGE_ACCESSED | _PAGE_COMBO;
-		if (access & _PAGE_RW)
+		new_pte = old_pte | H_PAGE_BUSY | _PAGE_ACCESSED | H_PAGE_COMBO;
+		if (access & _PAGE_WRITE)
 			new_pte |= _PAGE_DIRTY;
-	} while (old_pte != __cmpxchg_u64((unsigned long *)ptep,
-					  old_pte, new_pte));
+	} while (!pte_xchg(ptep, __pte(old_pte), __pte(new_pte)));
+
 	/*
 	 * Handle the subpage protection bits
 	 */
@@ -103,21 +103,21 @@ int __hash_page_4K(unsigned long ea, uns
 	/*
 	 *None of the sub 4k page is hashed
 	 */
-	if (!(old_pte & _PAGE_HASHPTE))
+	if (!(old_pte & H_PAGE_HASHPTE))
 		goto htab_insert_hpte;
 	/*
 	 * Check if the pte was already inserted into the hash table
 	 * as a 64k HW page, and invalidate the 64k HPTE if so.
 	 */
-	if (!(old_pte & _PAGE_COMBO)) {
+	if (!(old_pte & H_PAGE_COMBO)) {
 		flush_hash_page(vpn, rpte, MMU_PAGE_64K, ssize, flags);
 		/*
 		 * clear the old slot details from the old and new pte.
 		 * On hash insert failure we use old pte value and we don't
 		 * want slot information there if we have a insert failure.
 		 */
-		old_pte &= ~(_PAGE_HASHPTE | _PAGE_F_GIX | _PAGE_F_SECOND);
-		new_pte &= ~(_PAGE_HASHPTE | _PAGE_F_GIX | _PAGE_F_SECOND);
+		old_pte &= ~(H_PAGE_HASHPTE | H_PAGE_F_GIX | H_PAGE_F_SECOND);
+		new_pte &= ~(H_PAGE_HASHPTE | H_PAGE_F_GIX | H_PAGE_F_SECOND);
 		goto htab_insert_hpte;
 	}
 	/*
@@ -143,15 +143,15 @@ int __hash_page_4K(unsigned long ea, uns
 		if (ret == -1)
 			goto htab_insert_hpte;
 
-		*ptep = __pte(new_pte & ~_PAGE_BUSY);
+		*ptep = __pte(new_pte & ~H_PAGE_BUSY);
 		return 0;
 	}
 
 htab_insert_hpte:
 	/*
-	 * handle _PAGE_4K_PFN case
+	 * handle H_PAGE_4K_PFN case
 	 */
-	if (old_pte & _PAGE_4K_PFN) {
+	if (old_pte & H_PAGE_4K_PFN) {
 		/*
 		 * All the sub 4k page have the same
 		 * physical address.
@@ -199,20 +199,20 @@ repeat:
 	}
 	/*
 	 * Insert slot number & secondary bit in PTE second half,
-	 * clear _PAGE_BUSY and set appropriate HPTE slot bit
-	 * Since we have _PAGE_BUSY set on ptep, we can be sure
+	 * clear H_PAGE_BUSY and set appropriate HPTE slot bit
+	 * Since we have H_PAGE_BUSY set on ptep, we can be sure
 	 * nobody is undating hidx.
 	 */
 	hidxp = (unsigned long *)(ptep + PTRS_PER_PTE);
 	rpte.hidx &= ~(0xfUL << (subpg_index << 2));
 	*hidxp = rpte.hidx  | (slot << (subpg_index << 2));
 	new_pte = mark_subptegroup_valid(new_pte, subpg_index);
-	new_pte |=  _PAGE_HASHPTE;
+	new_pte |=  H_PAGE_HASHPTE;
 	/*
 	 * check __real_pte for details on matching smp_rmb()
 	 */
 	smp_wmb();
-	*ptep = __pte(new_pte & ~_PAGE_BUSY);
+	*ptep = __pte(new_pte & ~H_PAGE_BUSY);
 	return 0;
 }
 
@@ -220,7 +220,6 @@ int __hash_page_64K(unsigned long ea, un
 		    unsigned long vsid, pte_t *ptep, unsigned long trap,
 		    unsigned long flags, int ssize)
 {
-
 	unsigned long hpte_group;
 	unsigned long rflags, pa;
 	unsigned long old_pte, new_pte;
@@ -235,27 +234,26 @@ int __hash_page_64K(unsigned long ea, un
 
 		old_pte = pte_val(pte);
 		/* If PTE busy, retry the access */
-		if (unlikely(old_pte & _PAGE_BUSY))
+		if (unlikely(old_pte & H_PAGE_BUSY))
 			return 0;
 		/* If PTE permissions don't match, take page fault */
-		if (unlikely(access & ~old_pte))
+		if (unlikely(!check_pte_access(access, old_pte)))
 			return 1;
 		/*
 		 * Check if PTE has the cache-inhibit bit set
 		 * If so, bail out and refault as a 4k page
 		 */
 		if (!mmu_has_feature(MMU_FTR_CI_LARGE_PAGE) &&
-		    unlikely(old_pte & _PAGE_NO_CACHE))
+		    unlikely(pte_ci(pte)))
 			return 0;
 		/*
 		 * Try to lock the PTE, add ACCESSED and DIRTY if it was
 		 * a write access.
 		 */
-		new_pte = old_pte | _PAGE_BUSY | _PAGE_ACCESSED;
-		if (access & _PAGE_RW)
+		new_pte = old_pte | H_PAGE_BUSY | _PAGE_ACCESSED;
+		if (access & _PAGE_WRITE)
 			new_pte |= _PAGE_DIRTY;
-	} while (old_pte != __cmpxchg_u64((unsigned long *)ptep,
-					  old_pte, new_pte));
+	} while (!pte_xchg(ptep, __pte(old_pte), __pte(new_pte)));
 
 	rflags = htab_convert_pte_flags(new_pte);
 
@@ -264,22 +262,22 @@ int __hash_page_64K(unsigned long ea, un
 		rflags = hash_page_do_lazy_icache(rflags, __pte(old_pte), trap);
 
 	vpn  = hpt_vpn(ea, vsid, ssize);
-	if (unlikely(old_pte & _PAGE_HASHPTE)) {
+	if (unlikely(old_pte & H_PAGE_HASHPTE)) {
 		/*
 		 * There MIGHT be an HPTE for this pte
 		 */
 		hash = hpt_hash(vpn, shift, ssize);
-		if (old_pte & _PAGE_F_SECOND)
+		if (old_pte & H_PAGE_F_SECOND)
 			hash = ~hash;
 		slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
-		slot += (old_pte & _PAGE_F_GIX) >> _PAGE_F_GIX_SHIFT;
+		slot += (old_pte & H_PAGE_F_GIX) >> H_PAGE_F_GIX_SHIFT;
 
 		if (ppc_md.hpte_updatepp(slot, rflags, vpn, MMU_PAGE_64K,
 					 MMU_PAGE_64K, ssize, flags) == -1)
 			old_pte &= ~_PAGE_HPTEFLAGS;
 	}
 
-	if (likely(!(old_pte & _PAGE_HASHPTE))) {
+	if (likely(!(old_pte & H_PAGE_HASHPTE))) {
 
 		pa = pte_pfn(__pte(old_pte)) << PAGE_SHIFT;
 		hash = hpt_hash(vpn, shift, ssize);
@@ -319,9 +317,10 @@ repeat:
 					   MMU_PAGE_64K, MMU_PAGE_64K, old_pte);
 			return -1;
 		}
-		new_pte = (new_pte & ~_PAGE_HPTEFLAGS) | _PAGE_HASHPTE;
-		new_pte |= (slot << _PAGE_F_GIX_SHIFT) & (_PAGE_F_SECOND | _PAGE_F_GIX);
+		new_pte = (new_pte & ~_PAGE_HPTEFLAGS) | H_PAGE_HASHPTE;
+		new_pte |= (slot << H_PAGE_F_GIX_SHIFT) &
+			(H_PAGE_F_SECOND | H_PAGE_F_GIX);
 	}
-	*ptep = __pte(new_pte & ~_PAGE_BUSY);
+	*ptep = __pte(new_pte & ~H_PAGE_BUSY);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/mm/hash_native_64.c linux-libre-4.7-gnu/arch/powerpc/mm/hash_native_64.c
--- linux-libre-4.6-gnu/arch/powerpc/mm/hash_native_64.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/mm/hash_native_64.c	2016-07-24 15:23:50.000000000 -0400
@@ -221,7 +221,7 @@ static long native_hpte_insert(unsigned
 		return -1;
 
 	hpte_v = hpte_encode_v(vpn, psize, apsize, ssize) | vflags | HPTE_V_VALID;
-	hpte_r = hpte_encode_r(pa, psize, apsize) | rflags;
+	hpte_r = hpte_encode_r(pa, psize, apsize, ssize) | rflags;
 
 	if (!(vflags & HPTE_V_BOLTED)) {
 		DBG_LOW(" i=%x hpte_v=%016lx, hpte_r=%016lx\n",
@@ -316,8 +316,8 @@ static long native_hpte_updatepp(unsigne
 			DBG_LOW(" -> hit\n");
 			/* Update the HPTE */
 			hptep->r = cpu_to_be64((be64_to_cpu(hptep->r) &
-						~(HPTE_R_PP | HPTE_R_N)) |
-					       (newpp & (HPTE_R_PP | HPTE_R_N |
+						~(HPTE_R_PPP | HPTE_R_N)) |
+					       (newpp & (HPTE_R_PPP | HPTE_R_N |
 							 HPTE_R_C)));
 		}
 		native_unlock_hpte(hptep);
@@ -385,8 +385,8 @@ static void native_hpte_updateboltedpp(u
 
 	/* Update the HPTE */
 	hptep->r = cpu_to_be64((be64_to_cpu(hptep->r) &
-			~(HPTE_R_PP | HPTE_R_N)) |
-		(newpp & (HPTE_R_PP | HPTE_R_N)));
+				~(HPTE_R_PPP | HPTE_R_N)) |
+			       (newpp & (HPTE_R_PPP | HPTE_R_N)));
 	/*
 	 * Ensure it is out of the tlb too. Bolted entries base and
 	 * actual page size will be same.
@@ -550,7 +550,11 @@ static void hpte_decode(struct hash_pte
 		}
 	}
 	/* This works for all page sizes, and for 256M and 1T segments */
-	*ssize = hpte_v >> HPTE_V_SSIZE_SHIFT;
+	if (cpu_has_feature(CPU_FTR_ARCH_300))
+		*ssize = hpte_r >> HPTE_R_3_0_SSIZE_SHIFT;
+	else
+		*ssize = hpte_v >> HPTE_V_SSIZE_SHIFT;
+
 	shift = mmu_psize_defs[size].shift;
 
 	avpn = (HPTE_V_AVPN_VAL(hpte_v) & ~mmu_psize_defs[size].avpnm);
@@ -719,6 +723,12 @@ static void native_flush_hash_range(unsi
 	local_irq_restore(flags);
 }
 
+static int native_update_partition_table(u64 patb1)
+{
+	partition_tb->patb1 = cpu_to_be64(patb1);
+	return 0;
+}
+
 void __init hpte_init_native(void)
 {
 	ppc_md.hpte_invalidate	= native_hpte_invalidate;
@@ -729,4 +739,7 @@ void __init hpte_init_native(void)
 	ppc_md.hpte_clear_all	= native_hpte_clear;
 	ppc_md.flush_hash_range = native_flush_hash_range;
 	ppc_md.hugepage_invalidate   = native_hugepage_invalidate;
+
+	if (cpu_has_feature(CPU_FTR_ARCH_300))
+		ppc_md.update_partition_table = native_update_partition_table;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/mm/hash_utils_64.c linux-libre-4.7-gnu/arch/powerpc/mm/hash_utils_64.c
--- linux-libre-4.6-gnu/arch/powerpc/mm/hash_utils_64.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/mm/hash_utils_64.c	2016-07-24 15:23:50.000000000 -0400
@@ -159,6 +159,19 @@ static struct mmu_psize_def mmu_psize_de
 	},
 };
 
+/*
+ * 'R' and 'C' update notes:
+ *  - Under pHyp or KVM, the updatepp path will not set C, thus it *will*
+ *     create writeable HPTEs without C set, because the hcall H_PROTECT
+ *     that we use in that case will not update C
+ *  - The above is however not a problem, because we also don't do that
+ *     fancy "no flush" variant of eviction and we use H_REMOVE which will
+ *     do the right thing and thus we don't have the race I described earlier
+ *
+ *    - Under bare metal,  we do have the race, so we need R and C set
+ *    - We make sure R is always set and never lost
+ *    - C is _PAGE_DIRTY, and *should* always be set for a writeable mapping
+ */
 unsigned long htab_convert_pte_flags(unsigned long pteflags)
 {
 	unsigned long rflags = 0;
@@ -167,31 +180,47 @@ unsigned long htab_convert_pte_flags(uns
 	if ((pteflags & _PAGE_EXEC) == 0)
 		rflags |= HPTE_R_N;
 	/*
-	 * PP bits:
+	 * PPP bits:
 	 * Linux uses slb key 0 for kernel and 1 for user.
-	 * kernel areas are mapped with PP=00
-	 * and there is no kernel RO (_PAGE_KERNEL_RO).
-	 * User area is mapped with PP=0x2 for read/write
-	 * or PP=0x3 for read-only (including writeable but clean pages).
+	 * kernel RW areas are mapped with PPP=0b000
+	 * User area is mapped with PPP=0b010 for read/write
+	 * or PPP=0b011 for read-only (including writeable but clean pages).
 	 */
-	if (pteflags & _PAGE_USER) {
-		rflags |= 0x2;
-		if (!((pteflags & _PAGE_RW) && (pteflags & _PAGE_DIRTY)))
+	if (pteflags & _PAGE_PRIVILEGED) {
+		/*
+		 * Kernel read only mapped with ppp bits 0b110
+		 */
+		if (!(pteflags & _PAGE_WRITE))
+			rflags |= (HPTE_R_PP0 | 0x2);
+	} else {
+		if (pteflags & _PAGE_RWX)
+			rflags |= 0x2;
+		if (!((pteflags & _PAGE_WRITE) && (pteflags & _PAGE_DIRTY)))
 			rflags |= 0x1;
 	}
 	/*
-	 * Always add "C" bit for perf. Memory coherence is always enabled
+	 * We can't allow hardware to update hpte bits. Hence always
+	 * set 'R' bit and set 'C' if it is a write fault
 	 */
-	rflags |=  HPTE_R_C | HPTE_R_M;
+	rflags |=  HPTE_R_R;
+
+	if (pteflags & _PAGE_DIRTY)
+		rflags |= HPTE_R_C;
 	/*
 	 * Add in WIG bits
 	 */
-	if (pteflags & _PAGE_WRITETHRU)
-		rflags |= HPTE_R_W;
-	if (pteflags & _PAGE_NO_CACHE)
+
+	if ((pteflags & _PAGE_CACHE_CTL) == _PAGE_TOLERANT)
 		rflags |= HPTE_R_I;
-	if (pteflags & _PAGE_GUARDED)
-		rflags |= HPTE_R_G;
+	else if ((pteflags & _PAGE_CACHE_CTL) == _PAGE_NON_IDEMPOTENT)
+		rflags |= (HPTE_R_I | HPTE_R_G);
+	else if ((pteflags & _PAGE_CACHE_CTL) == _PAGE_SAO)
+		rflags |= (HPTE_R_W | HPTE_R_I | HPTE_R_M);
+	else
+		/*
+		 * Add memory coherence if cache inhibited is not set
+		 */
+		rflags |= HPTE_R_M;
 
 	return rflags;
 }
@@ -669,6 +698,41 @@ int remove_section_mapping(unsigned long
 }
 #endif /* CONFIG_MEMORY_HOTPLUG */
 
+static void __init hash_init_partition_table(phys_addr_t hash_table,
+					     unsigned long pteg_count)
+{
+	unsigned long ps_field;
+	unsigned long htab_size;
+	unsigned long patb_size = 1UL << PATB_SIZE_SHIFT;
+
+	/*
+	 * slb llp encoding for the page size used in VPM real mode.
+	 * We can ignore that for lpid 0
+	 */
+	ps_field = 0;
+	htab_size =  __ilog2(pteg_count) - 11;
+
+	BUILD_BUG_ON_MSG((PATB_SIZE_SHIFT > 24), "Partition table size too large.");
+	partition_tb = __va(memblock_alloc_base(patb_size, patb_size,
+						MEMBLOCK_ALLOC_ANYWHERE));
+
+	/* Initialize the Partition Table with no entries */
+	memset((void *)partition_tb, 0, patb_size);
+	partition_tb->patb0 = cpu_to_be64(ps_field | hash_table | htab_size);
+	/*
+	 * FIXME!! This should be done via update_partition table
+	 * For now UPRT is 0 for us.
+	 */
+	partition_tb->patb1 = 0;
+	DBG("Partition table %p\n", partition_tb);
+	/*
+	 * update partition table control register,
+	 * 64 K size.
+	 */
+	mtspr(SPRN_PTCR, __pa(partition_tb) | (PATB_SIZE_SHIFT - 12));
+
+}
+
 static void __init htab_initialize(void)
 {
 	unsigned long table;
@@ -737,8 +801,11 @@ static void __init htab_initialize(void)
 		/* Initialize the HPT with no entries */
 		memset((void *)table, 0, htab_size_bytes);
 
-		/* Set SDR1 */
-		mtspr(SPRN_SDR1, _SDR1);
+		if (!cpu_has_feature(CPU_FTR_ARCH_300))
+			/* Set SDR1 */
+			mtspr(SPRN_SDR1, _SDR1);
+		else
+			hash_init_partition_table(table, pteg_count);
 	}
 
 	prot = pgprot_val(PAGE_KERNEL);
@@ -823,8 +890,42 @@ static void __init htab_initialize(void)
 #undef KB
 #undef MB
 
-void __init early_init_mmu(void)
+void __init hash__early_init_mmu(void)
 {
+	/*
+	 * initialize page table size
+	 */
+	__pte_frag_nr = H_PTE_FRAG_NR;
+	__pte_frag_size_shift = H_PTE_FRAG_SIZE_SHIFT;
+
+	__pte_index_size = H_PTE_INDEX_SIZE;
+	__pmd_index_size = H_PMD_INDEX_SIZE;
+	__pud_index_size = H_PUD_INDEX_SIZE;
+	__pgd_index_size = H_PGD_INDEX_SIZE;
+	__pmd_cache_index = H_PMD_CACHE_INDEX;
+	__pte_table_size = H_PTE_TABLE_SIZE;
+	__pmd_table_size = H_PMD_TABLE_SIZE;
+	__pud_table_size = H_PUD_TABLE_SIZE;
+	__pgd_table_size = H_PGD_TABLE_SIZE;
+	/*
+	 * 4k use hugepd format, so for hash set then to
+	 * zero
+	 */
+	__pmd_val_bits = 0;
+	__pud_val_bits = 0;
+	__pgd_val_bits = 0;
+
+	__kernel_virt_start = H_KERN_VIRT_START;
+	__kernel_virt_size = H_KERN_VIRT_SIZE;
+	__vmalloc_start = H_VMALLOC_START;
+	__vmalloc_end = H_VMALLOC_END;
+	vmemmap = (struct page *)H_VMEMMAP_BASE;
+	ioremap_bot = IOREMAP_BASE;
+
+#ifdef CONFIG_PCI
+	pci_io_base = ISA_IO_BASE;
+#endif
+
 	/* Initialize the MMU Hash table and create the linear mapping
 	 * of memory. Has to be done before SLB initialization as this is
 	 * currently where the page size encoding is obtained.
@@ -836,12 +937,16 @@ void __init early_init_mmu(void)
 }
 
 #ifdef CONFIG_SMP
-void early_init_mmu_secondary(void)
+void hash__early_init_mmu_secondary(void)
 {
 	/* Initialize hash table for that CPU */
-	if (!firmware_has_feature(FW_FEATURE_LPAR))
-		mtspr(SPRN_SDR1, _SDR1);
-
+	if (!firmware_has_feature(FW_FEATURE_LPAR)) {
+		if (!cpu_has_feature(CPU_FTR_ARCH_300))
+			mtspr(SPRN_SDR1, _SDR1);
+		else
+			mtspr(SPRN_PTCR,
+			      __pa(partition_tb) | (PATB_SIZE_SHIFT - 12));
+	}
 	/* Initialize SLB */
 	slb_initialize();
 }
@@ -920,7 +1025,7 @@ void demote_segment_4k(struct mm_struct
  * Userspace sets the subpage permissions using the subpage_prot system call.
  *
  * Result is 0: full permissions, _PAGE_RW: read-only,
- * _PAGE_USER or _PAGE_USER|_PAGE_RW: no access.
+ * _PAGE_RWX: no access.
  */
 static int subpage_protection(struct mm_struct *mm, unsigned long ea)
 {
@@ -946,8 +1051,13 @@ static int subpage_protection(struct mm_
 	/* extract 2-bit bitfield for this 4k subpage */
 	spp >>= 30 - 2 * ((ea >> 12) & 0xf);
 
-	/* turn 0,1,2,3 into combination of _PAGE_USER and _PAGE_RW */
-	spp = ((spp & 2) ? _PAGE_USER : 0) | ((spp & 1) ? _PAGE_RW : 0);
+	/*
+	 * 0 -> full premission
+	 * 1 -> Read only
+	 * 2 -> no access.
+	 * We return the flag that need to be cleared.
+	 */
+	spp = ((spp & 2) ? _PAGE_RWX : 0) | ((spp & 1) ? _PAGE_WRITE : 0);
 	return spp;
 }
 
@@ -1084,7 +1194,7 @@ int hash_page_mm(struct mm_struct *mm, u
 	/* Pre-check access permissions (will be re-checked atomically
 	 * in __hash_page_XX but this pre-check is a fast path
 	 */
-	if (access & ~pte_val(*ptep)) {
+	if (!check_pte_access(access, pte_val(*ptep))) {
 		DBG_LOW(" no access !\n");
 		rc = 1;
 		goto bail;
@@ -1122,8 +1232,8 @@ int hash_page_mm(struct mm_struct *mm, u
 #endif
 	/* Do actual hashing */
 #ifdef CONFIG_PPC_64K_PAGES
-	/* If _PAGE_4K_PFN is set, make sure this is a 4k segment */
-	if ((pte_val(*ptep) & _PAGE_4K_PFN) && psize == MMU_PAGE_64K) {
+	/* If H_PAGE_4K_PFN is set, make sure this is a 4k segment */
+	if ((pte_val(*ptep) & H_PAGE_4K_PFN) && psize == MMU_PAGE_64K) {
 		demote_segment_4k(mm, ea);
 		psize = MMU_PAGE_4K;
 	}
@@ -1131,8 +1241,7 @@ int hash_page_mm(struct mm_struct *mm, u
 	/* If this PTE is non-cacheable and we have restrictions on
 	 * using non cacheable large pages, then we switch to 4k
 	 */
-	if (mmu_ci_restrictions && psize == MMU_PAGE_64K &&
-	    (pte_val(*ptep) & _PAGE_NO_CACHE)) {
+	if (mmu_ci_restrictions && psize == MMU_PAGE_64K && pte_ci(*ptep)) {
 		if (user_region) {
 			demote_segment_4k(mm, ea);
 			psize = MMU_PAGE_4K;
@@ -1209,7 +1318,7 @@ EXPORT_SYMBOL_GPL(hash_page);
 int __hash_page(unsigned long ea, unsigned long msr, unsigned long trap,
 		unsigned long dsisr)
 {
-	unsigned long access = _PAGE_PRESENT;
+	unsigned long access = _PAGE_PRESENT | _PAGE_READ;
 	unsigned long flags = 0;
 	struct mm_struct *mm = current->mm;
 
@@ -1220,14 +1329,18 @@ int __hash_page(unsigned long ea, unsign
 		flags |= HPTE_NOHPTE_UPDATE;
 
 	if (dsisr & DSISR_ISSTORE)
-		access |= _PAGE_RW;
+		access |= _PAGE_WRITE;
 	/*
-	 * We need to set the _PAGE_USER bit if MSR_PR is set or if we are
-	 * accessing a userspace segment (even from the kernel). We assume
-	 * kernel addresses always have the high bit set.
+	 * We set _PAGE_PRIVILEGED only when
+	 * kernel mode access kernel space.
+	 *
+	 * _PAGE_PRIVILEGED is NOT set
+	 * 1) when kernel mode access user space
+	 * 2) user space access kernel space.
 	 */
+	access |= _PAGE_PRIVILEGED;
 	if ((msr & MSR_PR) || (REGION_ID(ea) == USER_REGION_ID))
-		access |= _PAGE_USER;
+		access &= ~_PAGE_PRIVILEGED;
 
 	if (trap == 0x400)
 		access |= _PAGE_EXEC;
@@ -1235,6 +1348,30 @@ int __hash_page(unsigned long ea, unsign
 	return hash_page_mm(mm, ea, access, trap, flags);
 }
 
+#ifdef CONFIG_PPC_MM_SLICES
+static bool should_hash_preload(struct mm_struct *mm, unsigned long ea)
+{
+	int psize = get_slice_psize(mm, ea);
+
+	/* We only prefault standard pages for now */
+	if (unlikely(psize != mm->context.user_psize))
+		return false;
+
+	/*
+	 * Don't prefault if subpage protection is enabled for the EA.
+	 */
+	if (unlikely((psize == MMU_PAGE_4K) && subpage_protection(mm, ea)))
+		return false;
+
+	return true;
+}
+#else
+static bool should_hash_preload(struct mm_struct *mm, unsigned long ea)
+{
+	return true;
+}
+#endif
+
 void hash_preload(struct mm_struct *mm, unsigned long ea,
 		  unsigned long access, unsigned long trap)
 {
@@ -1247,11 +1384,8 @@ void hash_preload(struct mm_struct *mm,
 
 	BUG_ON(REGION_ID(ea) != USER_REGION_ID);
 
-#ifdef CONFIG_PPC_MM_SLICES
-	/* We only prefault standard pages for now */
-	if (unlikely(get_slice_psize(mm, ea) != mm->context.user_psize))
+	if (!should_hash_preload(mm, ea))
 		return;
-#endif
 
 	DBG_LOW("hash_preload(mm=%p, mm->pgdir=%p, ea=%016lx, access=%lx,"
 		" trap=%lx\n", mm, mm->pgd, ea, access, trap);
@@ -1282,13 +1416,13 @@ void hash_preload(struct mm_struct *mm,
 
 	WARN_ON(hugepage_shift);
 #ifdef CONFIG_PPC_64K_PAGES
-	/* If either _PAGE_4K_PFN or _PAGE_NO_CACHE is set (and we are on
+	/* If either H_PAGE_4K_PFN or cache inhibited is set (and we are on
 	 * a 64K kernel), then we don't preload, hash_page() will take
 	 * care of it once we actually try to access the page.
 	 * That way we don't have to duplicate all of the logic for segment
 	 * page size demotion here
 	 */
-	if (pte_val(*ptep) & (_PAGE_4K_PFN | _PAGE_NO_CACHE))
+	if ((pte_val(*ptep) & H_PAGE_4K_PFN) || pte_ci(*ptep))
 		goto out_exit;
 #endif /* CONFIG_PPC_64K_PAGES */
 
@@ -1570,7 +1704,7 @@ void __kernel_map_pages(struct page *pag
 }
 #endif /* CONFIG_DEBUG_PAGEALLOC */
 
-void setup_initial_memory_limit(phys_addr_t first_memblock_base,
+void hash__setup_initial_memory_limit(phys_addr_t first_memblock_base,
 				phys_addr_t first_memblock_size)
 {
 	/* We don't currently support the first MEMBLOCK not mapping 0
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/mm/hugepage-hash64.c linux-libre-4.7-gnu/arch/powerpc/mm/hugepage-hash64.c
--- linux-libre-4.6-gnu/arch/powerpc/mm/hugepage-hash64.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/mm/hugepage-hash64.c	2016-07-24 15:23:50.000000000 -0400
@@ -37,20 +37,20 @@ int __hash_page_thp(unsigned long ea, un
 
 		old_pmd = pmd_val(pmd);
 		/* If PMD busy, retry the access */
-		if (unlikely(old_pmd & _PAGE_BUSY))
+		if (unlikely(old_pmd & H_PAGE_BUSY))
 			return 0;
 		/* If PMD permissions don't match, take page fault */
-		if (unlikely(access & ~old_pmd))
+		if (unlikely(!check_pte_access(access, old_pmd)))
 			return 1;
 		/*
 		 * Try to lock the PTE, add ACCESSED and DIRTY if it was
 		 * a write access
 		 */
-		new_pmd = old_pmd | _PAGE_BUSY | _PAGE_ACCESSED;
-		if (access & _PAGE_RW)
+		new_pmd = old_pmd | H_PAGE_BUSY | _PAGE_ACCESSED;
+		if (access & _PAGE_WRITE)
 			new_pmd |= _PAGE_DIRTY;
-	} while (old_pmd != __cmpxchg_u64((unsigned long *)pmdp,
-					  old_pmd, new_pmd));
+	} while (!pmd_xchg(pmdp, __pmd(old_pmd), __pmd(new_pmd)));
+
 	rflags = htab_convert_pte_flags(new_pmd);
 
 #if 0
@@ -78,7 +78,7 @@ int __hash_page_thp(unsigned long ea, un
 		 * base page size. This is because demote_segment won't flush
 		 * hash page table entries.
 		 */
-		if ((old_pmd & _PAGE_HASHPTE) && !(old_pmd & _PAGE_COMBO)) {
+		if ((old_pmd & H_PAGE_HASHPTE) && !(old_pmd & H_PAGE_COMBO)) {
 			flush_hash_hugepage(vsid, ea, pmdp, MMU_PAGE_64K,
 					    ssize, flags);
 			/*
@@ -125,7 +125,7 @@ int __hash_page_thp(unsigned long ea, un
 		hash = hpt_hash(vpn, shift, ssize);
 		/* insert new entry */
 		pa = pmd_pfn(__pmd(old_pmd)) << PAGE_SHIFT;
-		new_pmd |= _PAGE_HASHPTE;
+		new_pmd |= H_PAGE_HASHPTE;
 
 repeat:
 		hpte_group = ((hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL;
@@ -169,17 +169,17 @@ repeat:
 		mark_hpte_slot_valid(hpte_slot_array, index, slot);
 	}
 	/*
-	 * Mark the pte with _PAGE_COMBO, if we are trying to hash it with
+	 * Mark the pte with H_PAGE_COMBO, if we are trying to hash it with
 	 * base page size 4k.
 	 */
 	if (psize == MMU_PAGE_4K)
-		new_pmd |= _PAGE_COMBO;
+		new_pmd |= H_PAGE_COMBO;
 	/*
 	 * The hpte valid is stored in the pgtable whose address is in the
 	 * second half of the PMD. Order this against clearing of the busy bit in
 	 * huge pmd.
 	 */
 	smp_wmb();
-	*pmdp = __pmd(new_pmd & ~_PAGE_BUSY);
+	*pmdp = __pmd(new_pmd & ~H_PAGE_BUSY);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/mm/hugetlbpage.c linux-libre-4.7-gnu/arch/powerpc/mm/hugetlbpage.c
--- linux-libre-4.6-gnu/arch/powerpc/mm/hugetlbpage.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/mm/hugetlbpage.c	2016-07-24 15:23:50.000000000 -0400
@@ -73,7 +73,7 @@ static int __hugepte_alloc(struct mm_str
 	cachep = PGT_CACHE(pdshift - pshift);
 #endif
 
-	new = kmem_cache_zalloc(cachep, GFP_KERNEL|__GFP_REPEAT);
+	new = kmem_cache_zalloc(cachep, GFP_KERNEL);
 
 	BUG_ON(pshift > HUGEPD_SHIFT_MASK);
 	BUG_ON((unsigned long)new & HUGEPD_SHIFT_MASK);
@@ -711,6 +711,9 @@ unsigned long hugetlb_get_unmapped_area(
 	struct hstate *hstate = hstate_file(file);
 	int mmu_psize = shift_to_mmu_psize(huge_page_shift(hstate));
 
+	if (radix_enabled())
+		return radix__hugetlb_get_unmapped_area(file, addr, len,
+						       pgoff, flags);
 	return slice_get_unmapped_area(addr, len, flags, mmu_psize, 1);
 }
 #endif
@@ -719,14 +722,14 @@ unsigned long vma_mmu_pagesize(struct vm
 {
 #ifdef CONFIG_PPC_MM_SLICES
 	unsigned int psize = get_slice_psize(vma->vm_mm, vma->vm_start);
-
-	return 1UL << mmu_psize_to_shift(psize);
-#else
+	/* With radix we don't use slice, so derive it from vma*/
+	if (!radix_enabled())
+		return 1UL << mmu_psize_to_shift(psize);
+#endif
 	if (!is_vm_hugetlb_page(vma))
 		return PAGE_SIZE;
 
 	return huge_page_size(hstate_vma(vma));
-#endif
 }
 
 static inline bool is_power_of_4(unsigned long x)
@@ -772,8 +775,10 @@ static int __init hugepage_setup_sz(char
 
 	size = memparse(str, &str);
 
-	if (add_huge_page_size(size) != 0)
-		printk(KERN_WARNING "Invalid huge page size specified(%llu)\n", size);
+	if (add_huge_page_size(size) != 0) {
+		hugetlb_bad_size();
+		pr_err("Invalid huge page size specified(%llu)\n", size);
+	}
 
 	return 1;
 }
@@ -823,7 +828,7 @@ static int __init hugetlbpage_init(void)
 {
 	int psize;
 
-	if (!mmu_has_feature(MMU_FTR_16M_PAGE))
+	if (!radix_enabled() && !mmu_has_feature(MMU_FTR_16M_PAGE))
 		return -ENODEV;
 
 	for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) {
@@ -863,6 +868,9 @@ static int __init hugetlbpage_init(void)
 		HPAGE_SHIFT = mmu_psize_defs[MMU_PAGE_16M].shift;
 	else if (mmu_psize_defs[MMU_PAGE_1M].shift)
 		HPAGE_SHIFT = mmu_psize_defs[MMU_PAGE_1M].shift;
+	else if (mmu_psize_defs[MMU_PAGE_2M].shift)
+		HPAGE_SHIFT = mmu_psize_defs[MMU_PAGE_2M].shift;
+
 
 	return 0;
 }
@@ -1003,9 +1011,9 @@ int gup_hugepte(pte_t *ptep, unsigned lo
 		end = pte_end;
 
 	pte = READ_ONCE(*ptep);
-	mask = _PAGE_PRESENT | _PAGE_USER;
+	mask = _PAGE_PRESENT | _PAGE_READ;
 	if (write)
-		mask |= _PAGE_RW;
+		mask |= _PAGE_WRITE;
 
 	if ((pte_val(pte) & mask) != mask)
 		return 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/mm/hugetlbpage-hash64.c linux-libre-4.7-gnu/arch/powerpc/mm/hugetlbpage-hash64.c
--- linux-libre-4.6-gnu/arch/powerpc/mm/hugetlbpage-hash64.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/mm/hugetlbpage-hash64.c	2016-07-24 15:23:50.000000000 -0400
@@ -47,18 +47,19 @@ int __hash_page_huge(unsigned long ea, u
 	do {
 		old_pte = pte_val(*ptep);
 		/* If PTE busy, retry the access */
-		if (unlikely(old_pte & _PAGE_BUSY))
+		if (unlikely(old_pte & H_PAGE_BUSY))
 			return 0;
 		/* If PTE permissions don't match, take page fault */
-		if (unlikely(access & ~old_pte))
+		if (unlikely(!check_pte_access(access, old_pte)))
 			return 1;
+
 		/* Try to lock the PTE, add ACCESSED and DIRTY if it was
 		 * a write access */
-		new_pte = old_pte | _PAGE_BUSY | _PAGE_ACCESSED;
-		if (access & _PAGE_RW)
+		new_pte = old_pte | H_PAGE_BUSY | _PAGE_ACCESSED;
+		if (access & _PAGE_WRITE)
 			new_pte |= _PAGE_DIRTY;
-	} while(old_pte != __cmpxchg_u64((unsigned long *)ptep,
-					 old_pte, new_pte));
+	} while(!pte_xchg(ptep, __pte(old_pte), __pte(new_pte)));
+
 	rflags = htab_convert_pte_flags(new_pte);
 
 	sz = ((1UL) << shift);
@@ -68,28 +69,28 @@ int __hash_page_huge(unsigned long ea, u
 		rflags = hash_page_do_lazy_icache(rflags, __pte(old_pte), trap);
 
 	/* Check if pte already has an hpte (case 2) */
-	if (unlikely(old_pte & _PAGE_HASHPTE)) {
+	if (unlikely(old_pte & H_PAGE_HASHPTE)) {
 		/* There MIGHT be an HPTE for this pte */
 		unsigned long hash, slot;
 
 		hash = hpt_hash(vpn, shift, ssize);
-		if (old_pte & _PAGE_F_SECOND)
+		if (old_pte & H_PAGE_F_SECOND)
 			hash = ~hash;
 		slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
-		slot += (old_pte & _PAGE_F_GIX) >> _PAGE_F_GIX_SHIFT;
+		slot += (old_pte & H_PAGE_F_GIX) >> H_PAGE_F_GIX_SHIFT;
 
 		if (ppc_md.hpte_updatepp(slot, rflags, vpn, mmu_psize,
 					 mmu_psize, ssize, flags) == -1)
 			old_pte &= ~_PAGE_HPTEFLAGS;
 	}
 
-	if (likely(!(old_pte & _PAGE_HASHPTE))) {
+	if (likely(!(old_pte & H_PAGE_HASHPTE))) {
 		unsigned long hash = hpt_hash(vpn, shift, ssize);
 
 		pa = pte_pfn(__pte(old_pte)) << PAGE_SHIFT;
 
 		/* clear HPTE slot informations in new PTE */
-		new_pte = (new_pte & ~_PAGE_HPTEFLAGS) | _PAGE_HASHPTE;
+		new_pte = (new_pte & ~_PAGE_HPTEFLAGS) | H_PAGE_HASHPTE;
 
 		slot = hpte_insert_repeating(hash, vpn, pa, rflags, 0,
 					     mmu_psize, ssize);
@@ -105,14 +106,14 @@ int __hash_page_huge(unsigned long ea, u
 			return -1;
 		}
 
-		new_pte |= (slot << _PAGE_F_GIX_SHIFT) &
-			(_PAGE_F_SECOND | _PAGE_F_GIX);
+		new_pte |= (slot << H_PAGE_F_GIX_SHIFT) &
+			(H_PAGE_F_SECOND | H_PAGE_F_GIX);
 	}
 
 	/*
 	 * No need to use ldarx/stdcx here
 	 */
-	*ptep = __pte(new_pte & ~_PAGE_BUSY);
+	*ptep = __pte(new_pte & ~H_PAGE_BUSY);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/mm/hugetlbpage-radix.c linux-libre-4.7-gnu/arch/powerpc/mm/hugetlbpage-radix.c
--- linux-libre-4.6-gnu/arch/powerpc/mm/hugetlbpage-radix.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/powerpc/mm/hugetlbpage-radix.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,87 @@
+#include <linux/mm.h>
+#include <linux/hugetlb.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/cacheflush.h>
+#include <asm/machdep.h>
+#include <asm/mman.h>
+
+void radix__flush_hugetlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
+{
+	unsigned long ap, shift;
+	struct hstate *hstate = hstate_file(vma->vm_file);
+
+	shift = huge_page_shift(hstate);
+	if (shift == mmu_psize_defs[MMU_PAGE_2M].shift)
+		ap = mmu_get_ap(MMU_PAGE_2M);
+	else if (shift == mmu_psize_defs[MMU_PAGE_1G].shift)
+		ap = mmu_get_ap(MMU_PAGE_1G);
+	else {
+		WARN(1, "Wrong huge page shift\n");
+		return ;
+	}
+	radix___flush_tlb_page(vma->vm_mm, vmaddr, ap, 0);
+}
+
+void radix__local_flush_hugetlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
+{
+	unsigned long ap, shift;
+	struct hstate *hstate = hstate_file(vma->vm_file);
+
+	shift = huge_page_shift(hstate);
+	if (shift == mmu_psize_defs[MMU_PAGE_2M].shift)
+		ap = mmu_get_ap(MMU_PAGE_2M);
+	else if (shift == mmu_psize_defs[MMU_PAGE_1G].shift)
+		ap = mmu_get_ap(MMU_PAGE_1G);
+	else {
+		WARN(1, "Wrong huge page shift\n");
+		return ;
+	}
+	radix___local_flush_tlb_page(vma->vm_mm, vmaddr, ap, 0);
+}
+
+/*
+ * A vairant of hugetlb_get_unmapped_area doing topdown search
+ * FIXME!! should we do as x86 does or non hugetlb area does ?
+ * ie, use topdown or not based on mmap_is_legacy check ?
+ */
+unsigned long
+radix__hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
+				unsigned long len, unsigned long pgoff,
+				unsigned long flags)
+{
+	struct mm_struct *mm = current->mm;
+	struct vm_area_struct *vma;
+	struct hstate *h = hstate_file(file);
+	struct vm_unmapped_area_info info;
+
+	if (len & ~huge_page_mask(h))
+		return -EINVAL;
+	if (len > TASK_SIZE)
+		return -ENOMEM;
+
+	if (flags & MAP_FIXED) {
+		if (prepare_hugepage_range(file, addr, len))
+			return -EINVAL;
+		return addr;
+	}
+
+	if (addr) {
+		addr = ALIGN(addr, huge_page_size(h));
+		vma = find_vma(mm, addr);
+		if (TASK_SIZE - len >= addr &&
+		    (!vma || addr + len <= vma->vm_start))
+			return addr;
+	}
+	/*
+	 * We are always doing an topdown search here. Slice code
+	 * does that too.
+	 */
+	info.flags = VM_UNMAPPED_AREA_TOPDOWN;
+	info.length = len;
+	info.low_limit = PAGE_SIZE;
+	info.high_limit = current->mm->mmap_base;
+	info.align_mask = PAGE_MASK & ~huge_page_mask(h);
+	info.align_offset = 0;
+	return vm_unmapped_area(&info);
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/mm/init_64.c linux-libre-4.7-gnu/arch/powerpc/mm/init_64.c
--- linux-libre-4.6-gnu/arch/powerpc/mm/init_64.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/mm/init_64.c	2016-07-24 15:23:50.000000000 -0400
@@ -66,11 +66,11 @@
 #include "mmu_decl.h"
 
 #ifdef CONFIG_PPC_STD_MMU_64
-#if PGTABLE_RANGE > USER_VSID_RANGE
+#if H_PGTABLE_RANGE > USER_VSID_RANGE
 #warning Limited user VSID range means pagetable space is wasted
 #endif
 
-#if (TASK_SIZE_USER64 < PGTABLE_RANGE) && (TASK_SIZE_USER64 < USER_VSID_RANGE)
+#if (TASK_SIZE_USER64 < H_PGTABLE_RANGE) && (TASK_SIZE_USER64 < USER_VSID_RANGE)
 #warning TASK_SIZE is smaller than it needs to be.
 #endif
 #endif /* CONFIG_PPC_STD_MMU_64 */
@@ -189,75 +189,6 @@ static int __meminit vmemmap_populated(u
 	return 0;
 }
 
-/* On hash-based CPUs, the vmemmap is bolted in the hash table.
- *
- * On Book3E CPUs, the vmemmap is currently mapped in the top half of
- * the vmalloc space using normal page tables, though the size of
- * pages encoded in the PTEs can be different
- */
-
-#ifdef CONFIG_PPC_BOOK3E
-static int __meminit vmemmap_create_mapping(unsigned long start,
-					    unsigned long page_size,
-					    unsigned long phys)
-{
-	/* Create a PTE encoding without page size */
-	unsigned long i, flags = _PAGE_PRESENT | _PAGE_ACCESSED |
-		_PAGE_KERNEL_RW;
-
-	/* PTEs only contain page size encodings up to 32M */
-	BUG_ON(mmu_psize_defs[mmu_vmemmap_psize].enc > 0xf);
-
-	/* Encode the size in the PTE */
-	flags |= mmu_psize_defs[mmu_vmemmap_psize].enc << 8;
-
-	/* For each PTE for that area, map things. Note that we don't
-	 * increment phys because all PTEs are of the large size and
-	 * thus must have the low bits clear
-	 */
-	for (i = 0; i < page_size; i += PAGE_SIZE)
-		BUG_ON(map_kernel_page(start + i, phys, flags));
-
-	return 0;
-}
-
-#ifdef CONFIG_MEMORY_HOTPLUG
-static void vmemmap_remove_mapping(unsigned long start,
-				   unsigned long page_size)
-{
-}
-#endif
-#else /* CONFIG_PPC_BOOK3E */
-static int __meminit vmemmap_create_mapping(unsigned long start,
-					    unsigned long page_size,
-					    unsigned long phys)
-{
-	int rc = htab_bolt_mapping(start, start + page_size, phys,
-				   pgprot_val(PAGE_KERNEL),
-				   mmu_vmemmap_psize, mmu_kernel_ssize);
-	if (rc < 0) {
-		int rc2 = htab_remove_mapping(start, start + page_size,
-					      mmu_vmemmap_psize,
-					      mmu_kernel_ssize);
-		BUG_ON(rc2 && (rc2 != -ENOENT));
-	}
-	return rc;
-}
-
-#ifdef CONFIG_MEMORY_HOTPLUG
-static void vmemmap_remove_mapping(unsigned long start,
-				   unsigned long page_size)
-{
-	int rc = htab_remove_mapping(start, start + page_size,
-				     mmu_vmemmap_psize,
-				     mmu_kernel_ssize);
-	BUG_ON((rc < 0) && (rc != -ENOENT));
-	WARN_ON(rc == -ENOENT);
-}
-#endif
-
-#endif /* CONFIG_PPC_BOOK3E */
-
 struct vmemmap_backing *vmemmap_list;
 static struct vmemmap_backing *next;
 static int num_left;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/mm/Makefile linux-libre-4.7-gnu/arch/powerpc/mm/Makefile
--- linux-libre-4.6-gnu/arch/powerpc/mm/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/mm/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -13,10 +13,11 @@ obj-$(CONFIG_PPC_MMU_NOHASH)	+= mmu_cont
 				   tlb_nohash_low.o
 obj-$(CONFIG_PPC_BOOK3E)	+= tlb_low_$(CONFIG_WORD_SIZE)e.o
 hash64-$(CONFIG_PPC_NATIVE)	:= hash_native_64.o
-obj-$(CONFIG_PPC_STD_MMU_64)	+= hash_utils_64.o slb_low.o slb.o $(hash64-y)
-obj-$(CONFIG_PPC_STD_MMU_32)	+= ppc_mmu_32.o hash_low_32.o
-obj-$(CONFIG_PPC_STD_MMU)	+= tlb_hash$(CONFIG_WORD_SIZE).o \
-				   mmu_context_hash$(CONFIG_WORD_SIZE).o
+obj-$(CONFIG_PPC_BOOK3E_64)   += pgtable-book3e.o
+obj-$(CONFIG_PPC_STD_MMU_64)	+= pgtable-hash64.o hash_utils_64.o slb_low.o slb.o $(hash64-y) mmu_context_book3s64.o pgtable-book3s64.o
+obj-$(CONFIG_PPC_RADIX_MMU)	+= pgtable-radix.o tlb-radix.o
+obj-$(CONFIG_PPC_STD_MMU_32)	+= ppc_mmu_32.o hash_low_32.o mmu_context_hash32.o
+obj-$(CONFIG_PPC_STD_MMU)	+= tlb_hash$(CONFIG_WORD_SIZE).o
 ifeq ($(CONFIG_PPC_STD_MMU_64),y)
 obj-$(CONFIG_PPC_4K_PAGES)	+= hash64_4k.o
 obj-$(CONFIG_PPC_64K_PAGES)	+= hash64_64k.o
@@ -33,6 +34,7 @@ obj-$(CONFIG_PPC_MM_SLICES)	+= slice.o
 obj-y				+= hugetlbpage.o
 ifeq ($(CONFIG_HUGETLB_PAGE),y)
 obj-$(CONFIG_PPC_STD_MMU_64)	+= hugetlbpage-hash64.o
+obj-$(CONFIG_PPC_RADIX_MMU)	+= hugetlbpage-radix.o
 obj-$(CONFIG_PPC_BOOK3E_MMU)	+= hugetlbpage-book3e.o
 endif
 obj-$(CONFIG_TRANSPARENT_HUGEPAGE) += hugepage-hash64.o
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/mm/mem.c linux-libre-4.7-gnu/arch/powerpc/mm/mem.c
--- linux-libre-4.6-gnu/arch/powerpc/mm/mem.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/mm/mem.c	2016-07-24 15:23:50.000000000 -0400
@@ -68,12 +68,15 @@ pte_t *kmap_pte;
 EXPORT_SYMBOL(kmap_pte);
 pgprot_t kmap_prot;
 EXPORT_SYMBOL(kmap_prot);
+#define TOP_ZONE ZONE_HIGHMEM
 
 static inline pte_t *virt_to_kpte(unsigned long vaddr)
 {
 	return pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr),
 			vaddr), vaddr), vaddr);
 }
+#else
+#define TOP_ZONE ZONE_NORMAL
 #endif
 
 int page_is_ram(unsigned long pfn)
@@ -267,14 +270,9 @@ void __init limit_zone_pfn(enum zone_typ
  */
 int dma_pfn_limit_to_zone(u64 pfn_limit)
 {
-	enum zone_type top_zone = ZONE_NORMAL;
 	int i;
 
-#ifdef CONFIG_HIGHMEM
-	top_zone = ZONE_HIGHMEM;
-#endif
-
-	for (i = top_zone; i >= 0; i--) {
+	for (i = TOP_ZONE; i >= 0; i--) {
 		if (max_zone_pfns[i] <= pfn_limit)
 			return i;
 	}
@@ -289,7 +287,6 @@ void __init paging_init(void)
 {
 	unsigned long long total_ram = memblock_phys_mem_size();
 	phys_addr_t top_of_ram = memblock_end_of_DRAM();
-	enum zone_type top_zone;
 
 #ifdef CONFIG_PPC32
 	unsigned long v = __fix_to_virt(__end_of_fixed_addresses - 1);
@@ -313,13 +310,9 @@ void __init paging_init(void)
 	       (long int)((top_of_ram - total_ram) >> 20));
 
 #ifdef CONFIG_HIGHMEM
-	top_zone = ZONE_HIGHMEM;
 	limit_zone_pfn(ZONE_NORMAL, lowmem_end_addr >> PAGE_SHIFT);
-#else
-	top_zone = ZONE_NORMAL;
 #endif
-
-	limit_zone_pfn(top_zone, top_of_ram >> PAGE_SHIFT);
+	limit_zone_pfn(TOP_ZONE, top_of_ram >> PAGE_SHIFT);
 	zone_limits_final = true;
 	free_area_init_nodes(max_zone_pfns);
 
@@ -498,7 +491,10 @@ void update_mmu_cache(struct vm_area_str
 	 * We don't need to worry about _PAGE_PRESENT here because we are
 	 * called with either mm->page_table_lock held or ptl lock held
 	 */
-	unsigned long access = 0, trap;
+	unsigned long access, trap;
+
+	if (radix_enabled())
+		return;
 
 	/* We only want HPTEs for linux PTEs that have _PAGE_ACCESSED set */
 	if (!pte_young(*ptep) || address >= TASK_SIZE)
@@ -511,13 +507,19 @@ void update_mmu_cache(struct vm_area_str
 	 *
 	 * We also avoid filling the hash if not coming from a fault
 	 */
-	if (current->thread.regs == NULL)
-		return;
-	trap = TRAP(current->thread.regs);
-	if (trap == 0x400)
-		access |= _PAGE_EXEC;
-	else if (trap != 0x300)
+
+	trap = current->thread.regs ? TRAP(current->thread.regs) : 0UL;
+	switch (trap) {
+	case 0x300:
+		access = 0UL;
+		break;
+	case 0x400:
+		access = _PAGE_EXEC;
+		break;
+	default:
 		return;
+	}
+
 	hash_preload(vma->vm_mm, address, access, trap);
 #endif /* CONFIG_PPC_STD_MMU */
 #if (defined(CONFIG_PPC_BOOK3E_64) || defined(CONFIG_PPC_FSL_BOOK3E)) \
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/mm/mmap.c linux-libre-4.7-gnu/arch/powerpc/mm/mmap.c
--- linux-libre-4.6-gnu/arch/powerpc/mm/mmap.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/mm/mmap.c	2016-07-24 15:23:50.000000000 -0400
@@ -26,6 +26,9 @@
 #include <linux/mm.h>
 #include <linux/random.h>
 #include <linux/sched.h>
+#include <linux/elf-randomize.h>
+#include <linux/security.h>
+#include <linux/mman.h>
 
 /*
  * Top of mmap area (just below the process stack).
@@ -78,6 +81,111 @@ static inline unsigned long mmap_base(un
 	return PAGE_ALIGN(TASK_SIZE - gap - rnd);
 }
 
+#ifdef CONFIG_PPC_RADIX_MMU
+/*
+ * Same function as generic code used only for radix, because we don't need to overload
+ * the generic one. But we will have to duplicate, because hash select
+ * HAVE_ARCH_UNMAPPED_AREA
+ */
+static unsigned long
+radix__arch_get_unmapped_area(struct file *filp, unsigned long addr,
+			     unsigned long len, unsigned long pgoff,
+			     unsigned long flags)
+{
+	struct mm_struct *mm = current->mm;
+	struct vm_area_struct *vma;
+	struct vm_unmapped_area_info info;
+
+	if (len > TASK_SIZE - mmap_min_addr)
+		return -ENOMEM;
+
+	if (flags & MAP_FIXED)
+		return addr;
+
+	if (addr) {
+		addr = PAGE_ALIGN(addr);
+		vma = find_vma(mm, addr);
+		if (TASK_SIZE - len >= addr && addr >= mmap_min_addr &&
+		    (!vma || addr + len <= vma->vm_start))
+			return addr;
+	}
+
+	info.flags = 0;
+	info.length = len;
+	info.low_limit = mm->mmap_base;
+	info.high_limit = TASK_SIZE;
+	info.align_mask = 0;
+	return vm_unmapped_area(&info);
+}
+
+static unsigned long
+radix__arch_get_unmapped_area_topdown(struct file *filp,
+				     const unsigned long addr0,
+				     const unsigned long len,
+				     const unsigned long pgoff,
+				     const unsigned long flags)
+{
+	struct vm_area_struct *vma;
+	struct mm_struct *mm = current->mm;
+	unsigned long addr = addr0;
+	struct vm_unmapped_area_info info;
+
+	/* requested length too big for entire address space */
+	if (len > TASK_SIZE - mmap_min_addr)
+		return -ENOMEM;
+
+	if (flags & MAP_FIXED)
+		return addr;
+
+	/* requesting a specific address */
+	if (addr) {
+		addr = PAGE_ALIGN(addr);
+		vma = find_vma(mm, addr);
+		if (TASK_SIZE - len >= addr && addr >= mmap_min_addr &&
+				(!vma || addr + len <= vma->vm_start))
+			return addr;
+	}
+
+	info.flags = VM_UNMAPPED_AREA_TOPDOWN;
+	info.length = len;
+	info.low_limit = max(PAGE_SIZE, mmap_min_addr);
+	info.high_limit = mm->mmap_base;
+	info.align_mask = 0;
+	addr = vm_unmapped_area(&info);
+
+	/*
+	 * A failed mmap() very likely causes application failure,
+	 * so fall back to the bottom-up function here. This scenario
+	 * can happen with large stack limits and large mmap()
+	 * allocations.
+	 */
+	if (addr & ~PAGE_MASK) {
+		VM_BUG_ON(addr != -ENOMEM);
+		info.flags = 0;
+		info.low_limit = TASK_UNMAPPED_BASE;
+		info.high_limit = TASK_SIZE;
+		addr = vm_unmapped_area(&info);
+	}
+
+	return addr;
+}
+
+static void radix__arch_pick_mmap_layout(struct mm_struct *mm,
+					unsigned long random_factor)
+{
+	if (mmap_is_legacy()) {
+		mm->mmap_base = TASK_UNMAPPED_BASE;
+		mm->get_unmapped_area = radix__arch_get_unmapped_area;
+	} else {
+		mm->mmap_base = mmap_base(random_factor);
+		mm->get_unmapped_area = radix__arch_get_unmapped_area_topdown;
+	}
+}
+#else
+/* dummy */
+extern void radix__arch_pick_mmap_layout(struct mm_struct *mm,
+					unsigned long random_factor);
+#endif
 /*
  * This function, called very early during the creation of a new
  * process VM image, sets up which VM layout function to use:
@@ -89,6 +197,8 @@ void arch_pick_mmap_layout(struct mm_str
 	if (current->flags & PF_RANDOMIZE)
 		random_factor = arch_mmap_rnd();
 
+	if (radix_enabled())
+		return radix__arch_pick_mmap_layout(mm, random_factor);
 	/*
 	 * Fall back to the standard layout if the personality
 	 * bit is set, or if the expected stack growth is unlimited:
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/mm/mmu_context_book3s64.c linux-libre-4.7-gnu/arch/powerpc/mm/mmu_context_book3s64.c
--- linux-libre-4.6-gnu/arch/powerpc/mm/mmu_context_book3s64.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/powerpc/mm/mmu_context_book3s64.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,187 @@
+/*
+ *  MMU context allocation for 64-bit kernels.
+ *
+ *  Copyright (C) 2004 Anton Blanchard, IBM Corp. <anton@samba.org>
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version
+ *  2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/spinlock.h>
+#include <linux/idr.h>
+#include <linux/export.h>
+#include <linux/gfp.h>
+#include <linux/slab.h>
+
+#include <asm/mmu_context.h>
+#include <asm/pgalloc.h>
+
+#include "icswx.h"
+
+static DEFINE_SPINLOCK(mmu_context_lock);
+static DEFINE_IDA(mmu_context_ida);
+
+int __init_new_context(void)
+{
+	int index;
+	int err;
+
+again:
+	if (!ida_pre_get(&mmu_context_ida, GFP_KERNEL))
+		return -ENOMEM;
+
+	spin_lock(&mmu_context_lock);
+	err = ida_get_new_above(&mmu_context_ida, 1, &index);
+	spin_unlock(&mmu_context_lock);
+
+	if (err == -EAGAIN)
+		goto again;
+	else if (err)
+		return err;
+
+	if (index > MAX_USER_CONTEXT) {
+		spin_lock(&mmu_context_lock);
+		ida_remove(&mmu_context_ida, index);
+		spin_unlock(&mmu_context_lock);
+		return -ENOMEM;
+	}
+
+	return index;
+}
+EXPORT_SYMBOL_GPL(__init_new_context);
+static int radix__init_new_context(struct mm_struct *mm, int index)
+{
+	unsigned long rts_field;
+
+	/*
+	 * set the process table entry,
+	 */
+	rts_field = radix__get_tree_size();
+	process_tb[index].prtb0 = cpu_to_be64(rts_field | __pa(mm->pgd) | RADIX_PGD_INDEX_SIZE);
+	return 0;
+}
+
+int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+{
+	int index;
+
+	index = __init_new_context();
+	if (index < 0)
+		return index;
+
+	if (radix_enabled()) {
+		radix__init_new_context(mm, index);
+	} else {
+
+		/* The old code would re-promote on fork, we don't do that
+		 * when using slices as it could cause problem promoting slices
+		 * that have been forced down to 4K
+		 *
+		 * For book3s we have MMU_NO_CONTEXT set to be ~0. Hence check
+		 * explicitly against context.id == 0. This ensures that we
+		 * properly initialize context slice details for newly allocated
+		 * mm's (which will have id == 0) and don't alter context slice
+		 * inherited via fork (which will have id != 0).
+		 *
+		 * We should not be calling init_new_context() on init_mm. Hence a
+		 * check against 0 is ok.
+		 */
+		if (mm->context.id == 0)
+			slice_set_user_psize(mm, mmu_virtual_psize);
+		subpage_prot_init_new_context(mm);
+	}
+	mm->context.id = index;
+#ifdef CONFIG_PPC_ICSWX
+	mm->context.cop_lockp = kmalloc(sizeof(spinlock_t), GFP_KERNEL);
+	if (!mm->context.cop_lockp) {
+		__destroy_context(index);
+		subpage_prot_free(mm);
+		mm->context.id = MMU_NO_CONTEXT;
+		return -ENOMEM;
+	}
+	spin_lock_init(mm->context.cop_lockp);
+#endif /* CONFIG_PPC_ICSWX */
+
+#ifdef CONFIG_PPC_64K_PAGES
+	mm->context.pte_frag = NULL;
+#endif
+#ifdef CONFIG_SPAPR_TCE_IOMMU
+	mm_iommu_init(&mm->context);
+#endif
+	return 0;
+}
+
+void __destroy_context(int context_id)
+{
+	spin_lock(&mmu_context_lock);
+	ida_remove(&mmu_context_ida, context_id);
+	spin_unlock(&mmu_context_lock);
+}
+EXPORT_SYMBOL_GPL(__destroy_context);
+
+#ifdef CONFIG_PPC_64K_PAGES
+static void destroy_pagetable_page(struct mm_struct *mm)
+{
+	int count;
+	void *pte_frag;
+	struct page *page;
+
+	pte_frag = mm->context.pte_frag;
+	if (!pte_frag)
+		return;
+
+	page = virt_to_page(pte_frag);
+	/* drop all the pending references */
+	count = ((unsigned long)pte_frag & ~PAGE_MASK) >> PTE_FRAG_SIZE_SHIFT;
+	/* We allow PTE_FRAG_NR fragments from a PTE page */
+	if (page_ref_sub_and_test(page, PTE_FRAG_NR - count)) {
+		pgtable_page_dtor(page);
+		free_hot_cold_page(page, 0);
+	}
+}
+
+#else
+static inline void destroy_pagetable_page(struct mm_struct *mm)
+{
+	return;
+}
+#endif
+
+
+void destroy_context(struct mm_struct *mm)
+{
+#ifdef CONFIG_SPAPR_TCE_IOMMU
+	mm_iommu_cleanup(&mm->context);
+#endif
+
+#ifdef CONFIG_PPC_ICSWX
+	drop_cop(mm->context.acop, mm);
+	kfree(mm->context.cop_lockp);
+	mm->context.cop_lockp = NULL;
+#endif /* CONFIG_PPC_ICSWX */
+
+	if (radix_enabled())
+		process_tb[mm->context.id].prtb1 = 0;
+	else
+		subpage_prot_free(mm);
+	destroy_pagetable_page(mm);
+	__destroy_context(mm->context.id);
+	mm->context.id = MMU_NO_CONTEXT;
+}
+
+#ifdef CONFIG_PPC_RADIX_MMU
+void radix__switch_mmu_context(struct mm_struct *prev, struct mm_struct *next)
+{
+	mtspr(SPRN_PID, next->context.id);
+	asm volatile("isync": : :"memory");
+}
+#endif
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/mm/mmu_context_hash64.c linux-libre-4.7-gnu/arch/powerpc/mm/mmu_context_hash64.c
--- linux-libre-4.6-gnu/arch/powerpc/mm/mmu_context_hash64.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/mm/mmu_context_hash64.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,151 +0,0 @@
-/*
- *  MMU context allocation for 64-bit kernels.
- *
- *  Copyright (C) 2004 Anton Blanchard, IBM Corp. <anton@samba.org>
- *
- *  This program is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU General Public License
- *  as published by the Free Software Foundation; either version
- *  2 of the License, or (at your option) any later version.
- *
- */
-
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/spinlock.h>
-#include <linux/idr.h>
-#include <linux/export.h>
-#include <linux/gfp.h>
-#include <linux/slab.h>
-
-#include <asm/mmu_context.h>
-#include <asm/pgalloc.h>
-
-#include "icswx.h"
-
-static DEFINE_SPINLOCK(mmu_context_lock);
-static DEFINE_IDA(mmu_context_ida);
-
-int __init_new_context(void)
-{
-	int index;
-	int err;
-
-again:
-	if (!ida_pre_get(&mmu_context_ida, GFP_KERNEL))
-		return -ENOMEM;
-
-	spin_lock(&mmu_context_lock);
-	err = ida_get_new_above(&mmu_context_ida, 1, &index);
-	spin_unlock(&mmu_context_lock);
-
-	if (err == -EAGAIN)
-		goto again;
-	else if (err)
-		return err;
-
-	if (index > MAX_USER_CONTEXT) {
-		spin_lock(&mmu_context_lock);
-		ida_remove(&mmu_context_ida, index);
-		spin_unlock(&mmu_context_lock);
-		return -ENOMEM;
-	}
-
-	return index;
-}
-EXPORT_SYMBOL_GPL(__init_new_context);
-
-int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
-{
-	int index;
-
-	index = __init_new_context();
-	if (index < 0)
-		return index;
-
-	/* The old code would re-promote on fork, we don't do that
-	 * when using slices as it could cause problem promoting slices
-	 * that have been forced down to 4K
-	 */
-	if (slice_mm_new_context(mm))
-		slice_set_user_psize(mm, mmu_virtual_psize);
-	subpage_prot_init_new_context(mm);
-	mm->context.id = index;
-#ifdef CONFIG_PPC_ICSWX
-	mm->context.cop_lockp = kmalloc(sizeof(spinlock_t), GFP_KERNEL);
-	if (!mm->context.cop_lockp) {
-		__destroy_context(index);
-		subpage_prot_free(mm);
-		mm->context.id = MMU_NO_CONTEXT;
-		return -ENOMEM;
-	}
-	spin_lock_init(mm->context.cop_lockp);
-#endif /* CONFIG_PPC_ICSWX */
-
-#ifdef CONFIG_PPC_64K_PAGES
-	mm->context.pte_frag = NULL;
-#endif
-#ifdef CONFIG_SPAPR_TCE_IOMMU
-	mm_iommu_init(&mm->context);
-#endif
-	return 0;
-}
-
-void __destroy_context(int context_id)
-{
-	spin_lock(&mmu_context_lock);
-	ida_remove(&mmu_context_ida, context_id);
-	spin_unlock(&mmu_context_lock);
-}
-EXPORT_SYMBOL_GPL(__destroy_context);
-
-#ifdef CONFIG_PPC_64K_PAGES
-static void destroy_pagetable_page(struct mm_struct *mm)
-{
-	int count;
-	void *pte_frag;
-	struct page *page;
-
-	pte_frag = mm->context.pte_frag;
-	if (!pte_frag)
-		return;
-
-	page = virt_to_page(pte_frag);
-	/* drop all the pending references */
-	count = ((unsigned long)pte_frag & ~PAGE_MASK) >> PTE_FRAG_SIZE_SHIFT;
-	/* We allow PTE_FRAG_NR fragments from a PTE page */
-	if (page_ref_sub_and_test(page, PTE_FRAG_NR - count)) {
-		pgtable_page_dtor(page);
-		free_hot_cold_page(page, 0);
-	}
-}
-
-#else
-static inline void destroy_pagetable_page(struct mm_struct *mm)
-{
-	return;
-}
-#endif
-
-
-void destroy_context(struct mm_struct *mm)
-{
-#ifdef CONFIG_SPAPR_TCE_IOMMU
-	mm_iommu_cleanup(&mm->context);
-#endif
-
-#ifdef CONFIG_PPC_ICSWX
-	drop_cop(mm->context.acop, mm);
-	kfree(mm->context.cop_lockp);
-	mm->context.cop_lockp = NULL;
-#endif /* CONFIG_PPC_ICSWX */
-
-	destroy_pagetable_page(mm);
-	__destroy_context(mm->context.id);
-	subpage_prot_free(mm);
-	mm->context.id = MMU_NO_CONTEXT;
-}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/mm/mmu_context_nohash.c linux-libre-4.7-gnu/arch/powerpc/mm/mmu_context_nohash.c
--- linux-libre-4.6-gnu/arch/powerpc/mm/mmu_context_nohash.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/mm/mmu_context_nohash.c	2016-07-24 15:23:50.000000000 -0400
@@ -226,7 +226,8 @@ static void context_check_map(void)
 static void context_check_map(void) { }
 #endif
 
-void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next)
+void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next,
+			struct task_struct *tsk)
 {
 	unsigned int i, id, cpu = smp_processor_id();
 	unsigned long *map;
@@ -334,8 +335,7 @@ int init_new_context(struct task_struct
 	mm->context.active = 0;
 
 #ifdef CONFIG_PPC_MM_SLICES
-	if (slice_mm_new_context(mm))
-		slice_set_user_psize(mm, mmu_virtual_psize);
+	slice_set_user_psize(mm, mmu_virtual_psize);
 #endif
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/mm/mmu_decl.h linux-libre-4.7-gnu/arch/powerpc/mm/mmu_decl.h
--- linux-libre-4.6-gnu/arch/powerpc/mm/mmu_decl.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/mm/mmu_decl.h	2016-07-24 15:23:50.000000000 -0400
@@ -108,11 +108,6 @@ extern unsigned long Hash_size, Hash_mas
 
 #endif /* CONFIG_PPC32 */
 
-#ifdef CONFIG_PPC64
-extern int map_kernel_page(unsigned long ea, unsigned long pa,
-			   unsigned long flags);
-#endif /* CONFIG_PPC64 */
-
 extern unsigned long ioremap_bot;
 extern unsigned long __max_low_memory;
 extern phys_addr_t __initial_memory_limit_addr;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/mm/pgtable_32.c linux-libre-4.7-gnu/arch/powerpc/mm/pgtable_32.c
--- linux-libre-4.6-gnu/arch/powerpc/mm/pgtable_32.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/mm/pgtable_32.c	2016-07-24 15:23:50.000000000 -0400
@@ -84,7 +84,7 @@ __init_refok pte_t *pte_alloc_one_kernel
 	pte_t *pte;
 
 	if (slab_is_available()) {
-		pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
+		pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_ZERO);
 	} else {
 		pte = __va(memblock_alloc(PAGE_SIZE, PAGE_SIZE));
 		if (pte)
@@ -97,7 +97,7 @@ pgtable_t pte_alloc_one(struct mm_struct
 {
 	struct page *ptepage;
 
-	gfp_t flags = GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO;
+	gfp_t flags = GFP_KERNEL | __GFP_ZERO;
 
 	ptepage = alloc_pages(flags, 0);
 	if (!ptepage)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/mm/pgtable_64.c linux-libre-4.7-gnu/arch/powerpc/mm/pgtable_64.c
--- linux-libre-4.6-gnu/arch/powerpc/mm/pgtable_64.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/mm/pgtable_64.c	2016-07-24 15:23:50.000000000 -0400
@@ -55,104 +55,63 @@
 
 #include "mmu_decl.h"
 
-#define CREATE_TRACE_POINTS
-#include <trace/events/thp.h>
-
-/* Some sanity checking */
-#if TASK_SIZE_USER64 > PGTABLE_RANGE
-#error TASK_SIZE_USER64 exceeds pagetable range
-#endif
-
 #ifdef CONFIG_PPC_STD_MMU_64
 #if TASK_SIZE_USER64 > (1UL << (ESID_BITS + SID_SHIFT))
 #error TASK_SIZE_USER64 exceeds user VSID range
 #endif
 #endif
 
-unsigned long ioremap_bot = IOREMAP_BASE;
-
-#ifdef CONFIG_PPC_MMU_NOHASH
-static __ref void *early_alloc_pgtable(unsigned long size)
-{
-	void *pt;
-
-	pt = __va(memblock_alloc_base(size, size, __pa(MAX_DMA_ADDRESS)));
-	memset(pt, 0, size);
-
-	return pt;
-}
-#endif /* CONFIG_PPC_MMU_NOHASH */
-
+#ifdef CONFIG_PPC_BOOK3S_64
 /*
- * map_kernel_page currently only called by __ioremap
- * map_kernel_page adds an entry to the ioremap page table
- * and adds an entry to the HPT, possibly bolting it
+ * partition table and process table for ISA 3.0
  */
-int map_kernel_page(unsigned long ea, unsigned long pa, unsigned long flags)
-{
-	pgd_t *pgdp;
-	pud_t *pudp;
-	pmd_t *pmdp;
-	pte_t *ptep;
-
-	if (slab_is_available()) {
-		pgdp = pgd_offset_k(ea);
-		pudp = pud_alloc(&init_mm, pgdp, ea);
-		if (!pudp)
-			return -ENOMEM;
-		pmdp = pmd_alloc(&init_mm, pudp, ea);
-		if (!pmdp)
-			return -ENOMEM;
-		ptep = pte_alloc_kernel(pmdp, ea);
-		if (!ptep)
-			return -ENOMEM;
-		set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT,
-							  __pgprot(flags)));
-	} else {
-#ifdef CONFIG_PPC_MMU_NOHASH
-		pgdp = pgd_offset_k(ea);
-#ifdef PUD_TABLE_SIZE
-		if (pgd_none(*pgdp)) {
-			pudp = early_alloc_pgtable(PUD_TABLE_SIZE);
-			BUG_ON(pudp == NULL);
-			pgd_populate(&init_mm, pgdp, pudp);
-		}
-#endif /* PUD_TABLE_SIZE */
-		pudp = pud_offset(pgdp, ea);
-		if (pud_none(*pudp)) {
-			pmdp = early_alloc_pgtable(PMD_TABLE_SIZE);
-			BUG_ON(pmdp == NULL);
-			pud_populate(&init_mm, pudp, pmdp);
-		}
-		pmdp = pmd_offset(pudp, ea);
-		if (!pmd_present(*pmdp)) {
-			ptep = early_alloc_pgtable(PAGE_SIZE);
-			BUG_ON(ptep == NULL);
-			pmd_populate_kernel(&init_mm, pmdp, ptep);
-		}
-		ptep = pte_offset_kernel(pmdp, ea);
-		set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT,
-							  __pgprot(flags)));
-#else /* CONFIG_PPC_MMU_NOHASH */
-		/*
-		 * If the mm subsystem is not fully up, we cannot create a
-		 * linux page table entry for this mapping.  Simply bolt an
-		 * entry in the hardware page table.
-		 *
-		 */
-		if (htab_bolt_mapping(ea, ea + PAGE_SIZE, pa, flags,
-				      mmu_io_psize, mmu_kernel_ssize)) {
-			printk(KERN_ERR "Failed to do bolted mapping IO "
-			       "memory at %016lx !\n", pa);
-			return -ENOMEM;
-		}
-#endif /* !CONFIG_PPC_MMU_NOHASH */
-	}
-
-	smp_wmb();
-	return 0;
-}
-
+struct prtb_entry *process_tb;
+struct patb_entry *partition_tb;
+/*
+ * page table size
+ */
+unsigned long __pte_index_size;
+EXPORT_SYMBOL(__pte_index_size);
+unsigned long __pmd_index_size;
+EXPORT_SYMBOL(__pmd_index_size);
+unsigned long __pud_index_size;
+EXPORT_SYMBOL(__pud_index_size);
+unsigned long __pgd_index_size;
+EXPORT_SYMBOL(__pgd_index_size);
+unsigned long __pmd_cache_index;
+EXPORT_SYMBOL(__pmd_cache_index);
+unsigned long __pte_table_size;
+EXPORT_SYMBOL(__pte_table_size);
+unsigned long __pmd_table_size;
+EXPORT_SYMBOL(__pmd_table_size);
+unsigned long __pud_table_size;
+EXPORT_SYMBOL(__pud_table_size);
+unsigned long __pgd_table_size;
+EXPORT_SYMBOL(__pgd_table_size);
+unsigned long __pmd_val_bits;
+EXPORT_SYMBOL(__pmd_val_bits);
+unsigned long __pud_val_bits;
+EXPORT_SYMBOL(__pud_val_bits);
+unsigned long __pgd_val_bits;
+EXPORT_SYMBOL(__pgd_val_bits);
+unsigned long __kernel_virt_start;
+EXPORT_SYMBOL(__kernel_virt_start);
+unsigned long __kernel_virt_size;
+EXPORT_SYMBOL(__kernel_virt_size);
+unsigned long __vmalloc_start;
+EXPORT_SYMBOL(__vmalloc_start);
+unsigned long __vmalloc_end;
+EXPORT_SYMBOL(__vmalloc_end);
+struct page *vmemmap;
+EXPORT_SYMBOL(vmemmap);
+unsigned long __pte_frag_nr;
+EXPORT_SYMBOL(__pte_frag_nr);
+unsigned long __pte_frag_size_shift;
+EXPORT_SYMBOL(__pte_frag_size_shift);
+unsigned long ioremap_bot;
+#else /* !CONFIG_PPC_BOOK3S_64 */
+unsigned long ioremap_bot = IOREMAP_BASE;
+#endif
 
 /**
  * __ioremap_at - Low level function to establish the page tables
@@ -167,12 +126,8 @@ void __iomem * __ioremap_at(phys_addr_t
 	if ((flags & _PAGE_PRESENT) == 0)
 		flags |= pgprot_val(PAGE_KERNEL);
 
-	/* Non-cacheable page cannot be coherent */
-	if (flags & _PAGE_NO_CACHE)
-		flags &= ~_PAGE_COHERENT;
-
 	/* We don't support the 4K PFN hack with ioremap */
-	if (flags & _PAGE_4K_PFN)
+	if (flags & H_PAGE_4K_PFN)
 		return NULL;
 
 	WARN_ON(pa & ~PAGE_MASK);
@@ -253,7 +208,7 @@ void __iomem * __ioremap(phys_addr_t add
 
 void __iomem * ioremap(phys_addr_t addr, unsigned long size)
 {
-	unsigned long flags = _PAGE_NO_CACHE | _PAGE_GUARDED;
+	unsigned long flags = pgprot_val(pgprot_noncached(__pgprot(0)));
 	void *caller = __builtin_return_address(0);
 
 	if (ppc_md.ioremap)
@@ -263,7 +218,7 @@ void __iomem * ioremap(phys_addr_t addr,
 
 void __iomem * ioremap_wc(phys_addr_t addr, unsigned long size)
 {
-	unsigned long flags = _PAGE_NO_CACHE;
+	unsigned long flags = pgprot_val(pgprot_noncached_wc(__pgprot(0)));
 	void *caller = __builtin_return_address(0);
 
 	if (ppc_md.ioremap)
@@ -277,11 +232,20 @@ void __iomem * ioremap_prot(phys_addr_t
 	void *caller = __builtin_return_address(0);
 
 	/* writeable implies dirty for kernel addresses */
-	if (flags & _PAGE_RW)
+	if (flags & _PAGE_WRITE)
 		flags |= _PAGE_DIRTY;
 
-	/* we don't want to let _PAGE_USER and _PAGE_EXEC leak out */
-	flags &= ~(_PAGE_USER | _PAGE_EXEC);
+	/* we don't want to let _PAGE_EXEC leak out */
+	flags &= ~_PAGE_EXEC;
+	/*
+	 * Force kernel mapping.
+	 */
+#if defined(CONFIG_PPC_BOOK3S_64)
+	flags |= _PAGE_PRIVILEGED;
+#else
+	flags &= ~_PAGE_USER;
+#endif
+
 
 #ifdef _PAGE_BAP_SR
 	/* _PAGE_USER contains _PAGE_BAP_SR on BookE using the new PTE format
@@ -386,8 +350,7 @@ static pte_t *get_from_cache(struct mm_s
 static pte_t *__alloc_for_cache(struct mm_struct *mm, int kernel)
 {
 	void *ret = NULL;
-	struct page *page = alloc_page(GFP_KERNEL | __GFP_NOTRACK |
-				       __GFP_REPEAT | __GFP_ZERO);
+	struct page *page = alloc_page(GFP_KERNEL | __GFP_NOTRACK | __GFP_ZERO);
 	if (!page)
 		return NULL;
 	if (!kernel && !pgtable_page_ctor(page)) {
@@ -411,7 +374,7 @@ static pte_t *__alloc_for_cache(struct m
 	return (pte_t *)ret;
 }
 
-pte_t *page_table_alloc(struct mm_struct *mm, unsigned long vmaddr, int kernel)
+pte_t *pte_fragment_alloc(struct mm_struct *mm, unsigned long vmaddr, int kernel)
 {
 	pte_t *pte;
 
@@ -421,8 +384,9 @@ pte_t *page_table_alloc(struct mm_struct
 
 	return __alloc_for_cache(mm, kernel);
 }
+#endif /* CONFIG_PPC_64K_PAGES */
 
-void page_table_free(struct mm_struct *mm, unsigned long *table, int kernel)
+void pte_fragment_free(unsigned long *table, int kernel)
 {
 	struct page *page = virt_to_page(table);
 	if (put_page_testzero(page)) {
@@ -433,15 +397,6 @@ void page_table_free(struct mm_struct *m
 }
 
 #ifdef CONFIG_SMP
-static void page_table_free_rcu(void *table)
-{
-	struct page *page = virt_to_page(table);
-	if (put_page_testzero(page)) {
-		pgtable_page_dtor(page);
-		free_hot_cold_page(page, 0);
-	}
-}
-
 void pgtable_free_tlb(struct mmu_gather *tlb, void *table, int shift)
 {
 	unsigned long pgf = (unsigned long)table;
@@ -458,7 +413,7 @@ void __tlb_remove_table(void *_table)
 
 	if (!shift)
 		/* PTE page needs special handling */
-		page_table_free_rcu(table);
+		pte_fragment_free(table, 0);
 	else {
 		BUG_ON(shift > MAX_PGTABLE_INDEX_SIZE);
 		kmem_cache_free(PGT_CACHE(shift), table);
@@ -469,385 +424,10 @@ void pgtable_free_tlb(struct mmu_gather
 {
 	if (!shift) {
 		/* PTE page needs special handling */
-		struct page *page = virt_to_page(table);
-		if (put_page_testzero(page)) {
-			pgtable_page_dtor(page);
-			free_hot_cold_page(page, 0);
-		}
+		pte_fragment_free(table, 0);
 	} else {
 		BUG_ON(shift > MAX_PGTABLE_INDEX_SIZE);
 		kmem_cache_free(PGT_CACHE(shift), table);
 	}
 }
 #endif
-#endif /* CONFIG_PPC_64K_PAGES */
-
-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
-
-/*
- * This is called when relaxing access to a hugepage. It's also called in the page
- * fault path when we don't hit any of the major fault cases, ie, a minor
- * update of _PAGE_ACCESSED, _PAGE_DIRTY, etc... The generic code will have
- * handled those two for us, we additionally deal with missing execute
- * permission here on some processors
- */
-int pmdp_set_access_flags(struct vm_area_struct *vma, unsigned long address,
-			  pmd_t *pmdp, pmd_t entry, int dirty)
-{
-	int changed;
-#ifdef CONFIG_DEBUG_VM
-	WARN_ON(!pmd_trans_huge(*pmdp));
-	assert_spin_locked(&vma->vm_mm->page_table_lock);
-#endif
-	changed = !pmd_same(*(pmdp), entry);
-	if (changed) {
-		__ptep_set_access_flags(pmdp_ptep(pmdp), pmd_pte(entry));
-		/*
-		 * Since we are not supporting SW TLB systems, we don't
-		 * have any thing similar to flush_tlb_page_nohash()
-		 */
-	}
-	return changed;
-}
-
-unsigned long pmd_hugepage_update(struct mm_struct *mm, unsigned long addr,
-				  pmd_t *pmdp, unsigned long clr,
-				  unsigned long set)
-{
-
-	unsigned long old, tmp;
-
-#ifdef CONFIG_DEBUG_VM
-	WARN_ON(!pmd_trans_huge(*pmdp));
-	assert_spin_locked(&mm->page_table_lock);
-#endif
-
-#ifdef PTE_ATOMIC_UPDATES
-	__asm__ __volatile__(
-	"1:	ldarx	%0,0,%3\n\
-		andi.	%1,%0,%6\n\
-		bne-	1b \n\
-		andc	%1,%0,%4 \n\
-		or	%1,%1,%7\n\
-		stdcx.	%1,0,%3 \n\
-		bne-	1b"
-	: "=&r" (old), "=&r" (tmp), "=m" (*pmdp)
-	: "r" (pmdp), "r" (clr), "m" (*pmdp), "i" (_PAGE_BUSY), "r" (set)
-	: "cc" );
-#else
-	old = pmd_val(*pmdp);
-	*pmdp = __pmd((old & ~clr) | set);
-#endif
-	trace_hugepage_update(addr, old, clr, set);
-	if (old & _PAGE_HASHPTE)
-		hpte_do_hugepage_flush(mm, addr, pmdp, old);
-	return old;
-}
-
-pmd_t pmdp_collapse_flush(struct vm_area_struct *vma, unsigned long address,
-			  pmd_t *pmdp)
-{
-	pmd_t pmd;
-
-	VM_BUG_ON(address & ~HPAGE_PMD_MASK);
-	VM_BUG_ON(pmd_trans_huge(*pmdp));
-
-	pmd = *pmdp;
-	pmd_clear(pmdp);
-	/*
-	 * Wait for all pending hash_page to finish. This is needed
-	 * in case of subpage collapse. When we collapse normal pages
-	 * to hugepage, we first clear the pmd, then invalidate all
-	 * the PTE entries. The assumption here is that any low level
-	 * page fault will see a none pmd and take the slow path that
-	 * will wait on mmap_sem. But we could very well be in a
-	 * hash_page with local ptep pointer value. Such a hash page
-	 * can result in adding new HPTE entries for normal subpages.
-	 * That means we could be modifying the page content as we
-	 * copy them to a huge page. So wait for parallel hash_page
-	 * to finish before invalidating HPTE entries. We can do this
-	 * by sending an IPI to all the cpus and executing a dummy
-	 * function there.
-	 */
-	kick_all_cpus_sync();
-	/*
-	 * Now invalidate the hpte entries in the range
-	 * covered by pmd. This make sure we take a
-	 * fault and will find the pmd as none, which will
-	 * result in a major fault which takes mmap_sem and
-	 * hence wait for collapse to complete. Without this
-	 * the __collapse_huge_page_copy can result in copying
-	 * the old content.
-	 */
-	flush_tlb_pmd_range(vma->vm_mm, &pmd, address);
-	return pmd;
-}
-
-int pmdp_test_and_clear_young(struct vm_area_struct *vma,
-			      unsigned long address, pmd_t *pmdp)
-{
-	return __pmdp_test_and_clear_young(vma->vm_mm, address, pmdp);
-}
-
-/*
- * We currently remove entries from the hashtable regardless of whether
- * the entry was young or dirty. The generic routines only flush if the
- * entry was young or dirty which is not good enough.
- *
- * We should be more intelligent about this but for the moment we override
- * these functions and force a tlb flush unconditionally
- */
-int pmdp_clear_flush_young(struct vm_area_struct *vma,
-				  unsigned long address, pmd_t *pmdp)
-{
-	return __pmdp_test_and_clear_young(vma->vm_mm, address, pmdp);
-}
-
-/*
- * We want to put the pgtable in pmd and use pgtable for tracking
- * the base page size hptes
- */
-void pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp,
-				pgtable_t pgtable)
-{
-	pgtable_t *pgtable_slot;
-	assert_spin_locked(&mm->page_table_lock);
-	/*
-	 * we store the pgtable in the second half of PMD
-	 */
-	pgtable_slot = (pgtable_t *)pmdp + PTRS_PER_PMD;
-	*pgtable_slot = pgtable;
-	/*
-	 * expose the deposited pgtable to other cpus.
-	 * before we set the hugepage PTE at pmd level
-	 * hash fault code looks at the deposted pgtable
-	 * to store hash index values.
-	 */
-	smp_wmb();
-}
-
-pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp)
-{
-	pgtable_t pgtable;
-	pgtable_t *pgtable_slot;
-
-	assert_spin_locked(&mm->page_table_lock);
-	pgtable_slot = (pgtable_t *)pmdp + PTRS_PER_PMD;
-	pgtable = *pgtable_slot;
-	/*
-	 * Once we withdraw, mark the entry NULL.
-	 */
-	*pgtable_slot = NULL;
-	/*
-	 * We store HPTE information in the deposited PTE fragment.
-	 * zero out the content on withdraw.
-	 */
-	memset(pgtable, 0, PTE_FRAG_SIZE);
-	return pgtable;
-}
-
-void pmdp_huge_split_prepare(struct vm_area_struct *vma,
-			     unsigned long address, pmd_t *pmdp)
-{
-	VM_BUG_ON(address & ~HPAGE_PMD_MASK);
-	VM_BUG_ON(REGION_ID(address) != USER_REGION_ID);
-
-	/*
-	 * We can't mark the pmd none here, because that will cause a race
-	 * against exit_mmap. We need to continue mark pmd TRANS HUGE, while
-	 * we spilt, but at the same time we wan't rest of the ppc64 code
-	 * not to insert hash pte on this, because we will be modifying
-	 * the deposited pgtable in the caller of this function. Hence
-	 * clear the _PAGE_USER so that we move the fault handling to
-	 * higher level function and that will serialize against ptl.
-	 * We need to flush existing hash pte entries here even though,
-	 * the translation is still valid, because we will withdraw
-	 * pgtable_t after this.
-	 */
-	pmd_hugepage_update(vma->vm_mm, address, pmdp, _PAGE_USER, 0);
-}
-
-
-/*
- * set a new huge pmd. We should not be called for updating
- * an existing pmd entry. That should go via pmd_hugepage_update.
- */
-void set_pmd_at(struct mm_struct *mm, unsigned long addr,
-		pmd_t *pmdp, pmd_t pmd)
-{
-#ifdef CONFIG_DEBUG_VM
-	WARN_ON((pmd_val(*pmdp) & (_PAGE_PRESENT | _PAGE_USER)) ==
-		(_PAGE_PRESENT | _PAGE_USER));
-	assert_spin_locked(&mm->page_table_lock);
-	WARN_ON(!pmd_trans_huge(pmd));
-#endif
-	trace_hugepage_set_pmd(addr, pmd_val(pmd));
-	return set_pte_at(mm, addr, pmdp_ptep(pmdp), pmd_pte(pmd));
-}
-
-/*
- * We use this to invalidate a pmdp entry before switching from a
- * hugepte to regular pmd entry.
- */
-void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
-		     pmd_t *pmdp)
-{
-	pmd_hugepage_update(vma->vm_mm, address, pmdp, _PAGE_PRESENT, 0);
-
-	/*
-	 * This ensures that generic code that rely on IRQ disabling
-	 * to prevent a parallel THP split work as expected.
-	 */
-	kick_all_cpus_sync();
-}
-
-/*
- * A linux hugepage PMD was changed and the corresponding hash table entries
- * neesd to be flushed.
- */
-void hpte_do_hugepage_flush(struct mm_struct *mm, unsigned long addr,
-			    pmd_t *pmdp, unsigned long old_pmd)
-{
-	int ssize;
-	unsigned int psize;
-	unsigned long vsid;
-	unsigned long flags = 0;
-	const struct cpumask *tmp;
-
-	/* get the base page size,vsid and segment size */
-#ifdef CONFIG_DEBUG_VM
-	psize = get_slice_psize(mm, addr);
-	BUG_ON(psize == MMU_PAGE_16M);
-#endif
-	if (old_pmd & _PAGE_COMBO)
-		psize = MMU_PAGE_4K;
-	else
-		psize = MMU_PAGE_64K;
-
-	if (!is_kernel_addr(addr)) {
-		ssize = user_segment_size(addr);
-		vsid = get_vsid(mm->context.id, addr, ssize);
-		WARN_ON(vsid == 0);
-	} else {
-		vsid = get_kernel_vsid(addr, mmu_kernel_ssize);
-		ssize = mmu_kernel_ssize;
-	}
-
-	tmp = cpumask_of(smp_processor_id());
-	if (cpumask_equal(mm_cpumask(mm), tmp))
-		flags |= HPTE_LOCAL_UPDATE;
-
-	return flush_hash_hugepage(vsid, addr, pmdp, psize, ssize, flags);
-}
-
-static pmd_t pmd_set_protbits(pmd_t pmd, pgprot_t pgprot)
-{
-	return __pmd(pmd_val(pmd) | pgprot_val(pgprot));
-}
-
-pmd_t pfn_pmd(unsigned long pfn, pgprot_t pgprot)
-{
-	unsigned long pmdv;
-
-	pmdv = (pfn << PTE_RPN_SHIFT) & PTE_RPN_MASK;
-	return pmd_set_protbits(__pmd(pmdv), pgprot);
-}
-
-pmd_t mk_pmd(struct page *page, pgprot_t pgprot)
-{
-	return pfn_pmd(page_to_pfn(page), pgprot);
-}
-
-pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
-{
-	unsigned long pmdv;
-
-	pmdv = pmd_val(pmd);
-	pmdv &= _HPAGE_CHG_MASK;
-	return pmd_set_protbits(__pmd(pmdv), newprot);
-}
-
-/*
- * This is called at the end of handling a user page fault, when the
- * fault has been handled by updating a HUGE PMD entry in the linux page tables.
- * We use it to preload an HPTE into the hash table corresponding to
- * the updated linux HUGE PMD entry.
- */
-void update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr,
-			  pmd_t *pmd)
-{
-	return;
-}
-
-pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
-			      unsigned long addr, pmd_t *pmdp)
-{
-	pmd_t old_pmd;
-	pgtable_t pgtable;
-	unsigned long old;
-	pgtable_t *pgtable_slot;
-
-	old = pmd_hugepage_update(mm, addr, pmdp, ~0UL, 0);
-	old_pmd = __pmd(old);
-	/*
-	 * We have pmd == none and we are holding page_table_lock.
-	 * So we can safely go and clear the pgtable hash
-	 * index info.
-	 */
-	pgtable_slot = (pgtable_t *)pmdp + PTRS_PER_PMD;
-	pgtable = *pgtable_slot;
-	/*
-	 * Let's zero out old valid and hash index details
-	 * hash fault look at them.
-	 */
-	memset(pgtable, 0, PTE_FRAG_SIZE);
-	/*
-	 * Serialize against find_linux_pte_or_hugepte which does lock-less
-	 * lookup in page tables with local interrupts disabled. For huge pages
-	 * it casts pmd_t to pte_t. Since format of pte_t is different from
-	 * pmd_t we want to prevent transit from pmd pointing to page table
-	 * to pmd pointing to huge page (and back) while interrupts are disabled.
-	 * We clear pmd to possibly replace it with page table pointer in
-	 * different code paths. So make sure we wait for the parallel
-	 * find_linux_pte_or_hugepage to finish.
-	 */
-	kick_all_cpus_sync();
-	return old_pmd;
-}
-
-int has_transparent_hugepage(void)
-{
-
-	BUILD_BUG_ON_MSG((PMD_SHIFT - PAGE_SHIFT) >= MAX_ORDER,
-		"hugepages can't be allocated by the buddy allocator");
-
-	BUILD_BUG_ON_MSG((PMD_SHIFT - PAGE_SHIFT) < 2,
-			 "We need more than 2 pages to do deferred thp split");
-
-	if (!mmu_has_feature(MMU_FTR_16M_PAGE))
-		return 0;
-	/*
-	 * We support THP only if PMD_SIZE is 16MB.
-	 */
-	if (mmu_psize_defs[MMU_PAGE_16M].shift != PMD_SHIFT)
-		return 0;
-	/*
-	 * We need to make sure that we support 16MB hugepage in a segement
-	 * with base page size 64K or 4K. We only enable THP with a PAGE_SIZE
-	 * of 64K.
-	 */
-	/*
-	 * If we have 64K HPTE, we will be using that by default
-	 */
-	if (mmu_psize_defs[MMU_PAGE_64K].shift &&
-	    (mmu_psize_defs[MMU_PAGE_64K].penc[MMU_PAGE_16M] == -1))
-		return 0;
-	/*
-	 * Ok we only have 4K HPTE
-	 */
-	if (mmu_psize_defs[MMU_PAGE_4K].penc[MMU_PAGE_16M] == -1)
-		return 0;
-
-	return 1;
-}
-#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/mm/pgtable-book3e.c linux-libre-4.7-gnu/arch/powerpc/mm/pgtable-book3e.c
--- linux-libre-4.6-gnu/arch/powerpc/mm/pgtable-book3e.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/powerpc/mm/pgtable-book3e.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2005, Paul Mackerras, IBM Corporation.
+ * Copyright 2009, Benjamin Herrenschmidt, IBM Corporation.
+ * Copyright 2015-2016, Aneesh Kumar K.V, IBM 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; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/sched.h>
+#include <linux/memblock.h>
+#include <asm/pgalloc.h>
+#include <asm/tlb.h>
+#include <asm/dma.h>
+
+#include "mmu_decl.h"
+
+#ifdef CONFIG_SPARSEMEM_VMEMMAP
+/*
+ * On Book3E CPUs, the vmemmap is currently mapped in the top half of
+ * the vmalloc space using normal page tables, though the size of
+ * pages encoded in the PTEs can be different
+ */
+int __meminit vmemmap_create_mapping(unsigned long start,
+				     unsigned long page_size,
+				     unsigned long phys)
+{
+	/* Create a PTE encoding without page size */
+	unsigned long i, flags = _PAGE_PRESENT | _PAGE_ACCESSED |
+		_PAGE_KERNEL_RW;
+
+	/* PTEs only contain page size encodings up to 32M */
+	BUG_ON(mmu_psize_defs[mmu_vmemmap_psize].enc > 0xf);
+
+	/* Encode the size in the PTE */
+	flags |= mmu_psize_defs[mmu_vmemmap_psize].enc << 8;
+
+	/* For each PTE for that area, map things. Note that we don't
+	 * increment phys because all PTEs are of the large size and
+	 * thus must have the low bits clear
+	 */
+	for (i = 0; i < page_size; i += PAGE_SIZE)
+		BUG_ON(map_kernel_page(start + i, phys, flags));
+
+	return 0;
+}
+
+#ifdef CONFIG_MEMORY_HOTPLUG
+void vmemmap_remove_mapping(unsigned long start,
+			    unsigned long page_size)
+{
+}
+#endif
+#endif /* CONFIG_SPARSEMEM_VMEMMAP */
+
+static __ref void *early_alloc_pgtable(unsigned long size)
+{
+	void *pt;
+
+	pt = __va(memblock_alloc_base(size, size, __pa(MAX_DMA_ADDRESS)));
+	memset(pt, 0, size);
+
+	return pt;
+}
+
+/*
+ * map_kernel_page currently only called by __ioremap
+ * map_kernel_page adds an entry to the ioremap page table
+ * and adds an entry to the HPT, possibly bolting it
+ */
+int map_kernel_page(unsigned long ea, unsigned long pa, unsigned long flags)
+{
+	pgd_t *pgdp;
+	pud_t *pudp;
+	pmd_t *pmdp;
+	pte_t *ptep;
+
+	BUILD_BUG_ON(TASK_SIZE_USER64 > PGTABLE_RANGE);
+	if (slab_is_available()) {
+		pgdp = pgd_offset_k(ea);
+		pudp = pud_alloc(&init_mm, pgdp, ea);
+		if (!pudp)
+			return -ENOMEM;
+		pmdp = pmd_alloc(&init_mm, pudp, ea);
+		if (!pmdp)
+			return -ENOMEM;
+		ptep = pte_alloc_kernel(pmdp, ea);
+		if (!ptep)
+			return -ENOMEM;
+		set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT,
+							  __pgprot(flags)));
+	} else {
+		pgdp = pgd_offset_k(ea);
+#ifndef __PAGETABLE_PUD_FOLDED
+		if (pgd_none(*pgdp)) {
+			pudp = early_alloc_pgtable(PUD_TABLE_SIZE);
+			BUG_ON(pudp == NULL);
+			pgd_populate(&init_mm, pgdp, pudp);
+		}
+#endif /* !__PAGETABLE_PUD_FOLDED */
+		pudp = pud_offset(pgdp, ea);
+		if (pud_none(*pudp)) {
+			pmdp = early_alloc_pgtable(PMD_TABLE_SIZE);
+			BUG_ON(pmdp == NULL);
+			pud_populate(&init_mm, pudp, pmdp);
+		}
+		pmdp = pmd_offset(pudp, ea);
+		if (!pmd_present(*pmdp)) {
+			ptep = early_alloc_pgtable(PAGE_SIZE);
+			BUG_ON(ptep == NULL);
+			pmd_populate_kernel(&init_mm, pmdp, ptep);
+		}
+		ptep = pte_offset_kernel(pmdp, ea);
+		set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT,
+							  __pgprot(flags)));
+	}
+
+	smp_wmb();
+	return 0;
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/mm/pgtable-book3s64.c linux-libre-4.7-gnu/arch/powerpc/mm/pgtable-book3s64.c
--- linux-libre-4.6-gnu/arch/powerpc/mm/pgtable-book3s64.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/powerpc/mm/pgtable-book3s64.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2015-2016, Aneesh Kumar K.V, IBM 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; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/sched.h>
+#include <asm/pgalloc.h>
+#include <asm/tlb.h>
+
+#include "mmu_decl.h"
+#include <trace/events/thp.h>
+
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+/*
+ * This is called when relaxing access to a hugepage. It's also called in the page
+ * fault path when we don't hit any of the major fault cases, ie, a minor
+ * update of _PAGE_ACCESSED, _PAGE_DIRTY, etc... The generic code will have
+ * handled those two for us, we additionally deal with missing execute
+ * permission here on some processors
+ */
+int pmdp_set_access_flags(struct vm_area_struct *vma, unsigned long address,
+			  pmd_t *pmdp, pmd_t entry, int dirty)
+{
+	int changed;
+#ifdef CONFIG_DEBUG_VM
+	WARN_ON(!pmd_trans_huge(*pmdp));
+	assert_spin_locked(&vma->vm_mm->page_table_lock);
+#endif
+	changed = !pmd_same(*(pmdp), entry);
+	if (changed) {
+		__ptep_set_access_flags(pmdp_ptep(pmdp), pmd_pte(entry));
+		flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
+	}
+	return changed;
+}
+
+int pmdp_test_and_clear_young(struct vm_area_struct *vma,
+			      unsigned long address, pmd_t *pmdp)
+{
+	return __pmdp_test_and_clear_young(vma->vm_mm, address, pmdp);
+}
+/*
+ * set a new huge pmd. We should not be called for updating
+ * an existing pmd entry. That should go via pmd_hugepage_update.
+ */
+void set_pmd_at(struct mm_struct *mm, unsigned long addr,
+		pmd_t *pmdp, pmd_t pmd)
+{
+#ifdef CONFIG_DEBUG_VM
+	WARN_ON(pte_present(pmd_pte(*pmdp)) && !pte_protnone(pmd_pte(*pmdp)));
+	assert_spin_locked(&mm->page_table_lock);
+	WARN_ON(!pmd_trans_huge(pmd));
+#endif
+	trace_hugepage_set_pmd(addr, pmd_val(pmd));
+	return set_pte_at(mm, addr, pmdp_ptep(pmdp), pmd_pte(pmd));
+}
+/*
+ * We use this to invalidate a pmdp entry before switching from a
+ * hugepte to regular pmd entry.
+ */
+void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
+		     pmd_t *pmdp)
+{
+	pmd_hugepage_update(vma->vm_mm, address, pmdp, _PAGE_PRESENT, 0);
+	flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
+	/*
+	 * This ensures that generic code that rely on IRQ disabling
+	 * to prevent a parallel THP split work as expected.
+	 */
+	kick_all_cpus_sync();
+}
+
+static pmd_t pmd_set_protbits(pmd_t pmd, pgprot_t pgprot)
+{
+	return __pmd(pmd_val(pmd) | pgprot_val(pgprot));
+}
+
+pmd_t pfn_pmd(unsigned long pfn, pgprot_t pgprot)
+{
+	unsigned long pmdv;
+
+	pmdv = (pfn << PAGE_SHIFT) & PTE_RPN_MASK;
+	return pmd_set_protbits(__pmd(pmdv), pgprot);
+}
+
+pmd_t mk_pmd(struct page *page, pgprot_t pgprot)
+{
+	return pfn_pmd(page_to_pfn(page), pgprot);
+}
+
+pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
+{
+	unsigned long pmdv;
+
+	pmdv = pmd_val(pmd);
+	pmdv &= _HPAGE_CHG_MASK;
+	return pmd_set_protbits(__pmd(pmdv), newprot);
+}
+
+/*
+ * This is called at the end of handling a user page fault, when the
+ * fault has been handled by updating a HUGE PMD entry in the linux page tables.
+ * We use it to preload an HPTE into the hash table corresponding to
+ * the updated linux HUGE PMD entry.
+ */
+void update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr,
+			  pmd_t *pmd)
+{
+	return;
+}
+#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/mm/pgtable.c linux-libre-4.7-gnu/arch/powerpc/mm/pgtable.c
--- linux-libre-4.6-gnu/arch/powerpc/mm/pgtable.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/mm/pgtable.c	2016-07-24 15:23:50.000000000 -0400
@@ -38,14 +38,25 @@ static inline int is_exec_fault(void)
 
 /* We only try to do i/d cache coherency on stuff that looks like
  * reasonably "normal" PTEs. We currently require a PTE to be present
- * and we avoid _PAGE_SPECIAL and _PAGE_NO_CACHE. We also only do that
+ * and we avoid _PAGE_SPECIAL and cache inhibited pte. We also only do that
  * on userspace PTEs
  */
 static inline int pte_looks_normal(pte_t pte)
 {
+
+#if defined(CONFIG_PPC_BOOK3S_64)
+	if ((pte_val(pte) & (_PAGE_PRESENT | _PAGE_SPECIAL)) == _PAGE_PRESENT) {
+		if (pte_ci(pte))
+			return 0;
+		if (pte_user(pte))
+			return 1;
+	}
+	return 0;
+#else
 	return (pte_val(pte) &
-	    (_PAGE_PRESENT | _PAGE_SPECIAL | _PAGE_NO_CACHE | _PAGE_USER)) ==
-	    (_PAGE_PRESENT | _PAGE_USER);
+		(_PAGE_PRESENT | _PAGE_SPECIAL | _PAGE_NO_CACHE | _PAGE_USER)) ==
+		(_PAGE_PRESENT | _PAGE_USER);
+#endif
 }
 
 static struct page *maybe_pte_to_page(pte_t pte)
@@ -71,6 +82,9 @@ static struct page *maybe_pte_to_page(pt
 
 static pte_t set_pte_filter(pte_t pte)
 {
+	if (radix_enabled())
+		return pte;
+
 	pte = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS);
 	if (pte_looks_normal(pte) && !(cpu_has_feature(CPU_FTR_COHERENT_ICACHE) ||
 				       cpu_has_feature(CPU_FTR_NOEXECUTE))) {
@@ -177,8 +191,8 @@ void set_pte_at(struct mm_struct *mm, un
 	 * _PAGE_PRESENT, but we can be sure that it is not in hpte.
 	 * Hence we can use set_pte_at for them.
 	 */
-	VM_WARN_ON((pte_val(*ptep) & (_PAGE_PRESENT | _PAGE_USER)) ==
-		(_PAGE_PRESENT | _PAGE_USER));
+	VM_WARN_ON(pte_present(*ptep) && !pte_protnone(*ptep));
+
 	/*
 	 * Add the pte bit when tryint set a pte
 	 */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/mm/pgtable-hash64.c linux-libre-4.7-gnu/arch/powerpc/mm/pgtable-hash64.c
--- linux-libre-4.6-gnu/arch/powerpc/mm/pgtable-hash64.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/powerpc/mm/pgtable-hash64.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,342 @@
+/*
+ * Copyright 2005, Paul Mackerras, IBM Corporation.
+ * Copyright 2009, Benjamin Herrenschmidt, IBM Corporation.
+ * Copyright 2015-2016, Aneesh Kumar K.V, IBM 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; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/sched.h>
+#include <asm/pgalloc.h>
+#include <asm/tlb.h>
+
+#include "mmu_decl.h"
+
+#define CREATE_TRACE_POINTS
+#include <trace/events/thp.h>
+
+#ifdef CONFIG_SPARSEMEM_VMEMMAP
+/*
+ * On hash-based CPUs, the vmemmap is bolted in the hash table.
+ *
+ */
+int __meminit hash__vmemmap_create_mapping(unsigned long start,
+				       unsigned long page_size,
+				       unsigned long phys)
+{
+	int rc = htab_bolt_mapping(start, start + page_size, phys,
+				   pgprot_val(PAGE_KERNEL),
+				   mmu_vmemmap_psize, mmu_kernel_ssize);
+	if (rc < 0) {
+		int rc2 = htab_remove_mapping(start, start + page_size,
+					      mmu_vmemmap_psize,
+					      mmu_kernel_ssize);
+		BUG_ON(rc2 && (rc2 != -ENOENT));
+	}
+	return rc;
+}
+
+#ifdef CONFIG_MEMORY_HOTPLUG
+void hash__vmemmap_remove_mapping(unsigned long start,
+			      unsigned long page_size)
+{
+	int rc = htab_remove_mapping(start, start + page_size,
+				     mmu_vmemmap_psize,
+				     mmu_kernel_ssize);
+	BUG_ON((rc < 0) && (rc != -ENOENT));
+	WARN_ON(rc == -ENOENT);
+}
+#endif
+#endif /* CONFIG_SPARSEMEM_VMEMMAP */
+
+/*
+ * map_kernel_page currently only called by __ioremap
+ * map_kernel_page adds an entry to the ioremap page table
+ * and adds an entry to the HPT, possibly bolting it
+ */
+int hash__map_kernel_page(unsigned long ea, unsigned long pa, unsigned long flags)
+{
+	pgd_t *pgdp;
+	pud_t *pudp;
+	pmd_t *pmdp;
+	pte_t *ptep;
+
+	BUILD_BUG_ON(TASK_SIZE_USER64 > H_PGTABLE_RANGE);
+	if (slab_is_available()) {
+		pgdp = pgd_offset_k(ea);
+		pudp = pud_alloc(&init_mm, pgdp, ea);
+		if (!pudp)
+			return -ENOMEM;
+		pmdp = pmd_alloc(&init_mm, pudp, ea);
+		if (!pmdp)
+			return -ENOMEM;
+		ptep = pte_alloc_kernel(pmdp, ea);
+		if (!ptep)
+			return -ENOMEM;
+		set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT,
+							  __pgprot(flags)));
+	} else {
+		/*
+		 * If the mm subsystem is not fully up, we cannot create a
+		 * linux page table entry for this mapping.  Simply bolt an
+		 * entry in the hardware page table.
+		 *
+		 */
+		if (htab_bolt_mapping(ea, ea + PAGE_SIZE, pa, flags,
+				      mmu_io_psize, mmu_kernel_ssize)) {
+			printk(KERN_ERR "Failed to do bolted mapping IO "
+			       "memory at %016lx !\n", pa);
+			return -ENOMEM;
+		}
+	}
+
+	smp_wmb();
+	return 0;
+}
+
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+
+unsigned long hash__pmd_hugepage_update(struct mm_struct *mm, unsigned long addr,
+				    pmd_t *pmdp, unsigned long clr,
+				    unsigned long set)
+{
+	__be64 old_be, tmp;
+	unsigned long old;
+
+#ifdef CONFIG_DEBUG_VM
+	WARN_ON(!pmd_trans_huge(*pmdp));
+	assert_spin_locked(&mm->page_table_lock);
+#endif
+
+	__asm__ __volatile__(
+	"1:	ldarx	%0,0,%3\n\
+		and.	%1,%0,%6\n\
+		bne-	1b \n\
+		andc	%1,%0,%4 \n\
+		or	%1,%1,%7\n\
+		stdcx.	%1,0,%3 \n\
+		bne-	1b"
+	: "=&r" (old_be), "=&r" (tmp), "=m" (*pmdp)
+	: "r" (pmdp), "r" (cpu_to_be64(clr)), "m" (*pmdp),
+	  "r" (cpu_to_be64(H_PAGE_BUSY)), "r" (cpu_to_be64(set))
+	: "cc" );
+
+	old = be64_to_cpu(old_be);
+
+	trace_hugepage_update(addr, old, clr, set);
+	if (old & H_PAGE_HASHPTE)
+		hpte_do_hugepage_flush(mm, addr, pmdp, old);
+	return old;
+}
+
+pmd_t hash__pmdp_collapse_flush(struct vm_area_struct *vma, unsigned long address,
+			    pmd_t *pmdp)
+{
+	pmd_t pmd;
+
+	VM_BUG_ON(address & ~HPAGE_PMD_MASK);
+	VM_BUG_ON(pmd_trans_huge(*pmdp));
+
+	pmd = *pmdp;
+	pmd_clear(pmdp);
+	/*
+	 * Wait for all pending hash_page to finish. This is needed
+	 * in case of subpage collapse. When we collapse normal pages
+	 * to hugepage, we first clear the pmd, then invalidate all
+	 * the PTE entries. The assumption here is that any low level
+	 * page fault will see a none pmd and take the slow path that
+	 * will wait on mmap_sem. But we could very well be in a
+	 * hash_page with local ptep pointer value. Such a hash page
+	 * can result in adding new HPTE entries for normal subpages.
+	 * That means we could be modifying the page content as we
+	 * copy them to a huge page. So wait for parallel hash_page
+	 * to finish before invalidating HPTE entries. We can do this
+	 * by sending an IPI to all the cpus and executing a dummy
+	 * function there.
+	 */
+	kick_all_cpus_sync();
+	/*
+	 * Now invalidate the hpte entries in the range
+	 * covered by pmd. This make sure we take a
+	 * fault and will find the pmd as none, which will
+	 * result in a major fault which takes mmap_sem and
+	 * hence wait for collapse to complete. Without this
+	 * the __collapse_huge_page_copy can result in copying
+	 * the old content.
+	 */
+	flush_tlb_pmd_range(vma->vm_mm, &pmd, address);
+	return pmd;
+}
+
+/*
+ * We want to put the pgtable in pmd and use pgtable for tracking
+ * the base page size hptes
+ */
+void hash__pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp,
+				  pgtable_t pgtable)
+{
+	pgtable_t *pgtable_slot;
+	assert_spin_locked(&mm->page_table_lock);
+	/*
+	 * we store the pgtable in the second half of PMD
+	 */
+	pgtable_slot = (pgtable_t *)pmdp + PTRS_PER_PMD;
+	*pgtable_slot = pgtable;
+	/*
+	 * expose the deposited pgtable to other cpus.
+	 * before we set the hugepage PTE at pmd level
+	 * hash fault code looks at the deposted pgtable
+	 * to store hash index values.
+	 */
+	smp_wmb();
+}
+
+pgtable_t hash__pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp)
+{
+	pgtable_t pgtable;
+	pgtable_t *pgtable_slot;
+
+	assert_spin_locked(&mm->page_table_lock);
+	pgtable_slot = (pgtable_t *)pmdp + PTRS_PER_PMD;
+	pgtable = *pgtable_slot;
+	/*
+	 * Once we withdraw, mark the entry NULL.
+	 */
+	*pgtable_slot = NULL;
+	/*
+	 * We store HPTE information in the deposited PTE fragment.
+	 * zero out the content on withdraw.
+	 */
+	memset(pgtable, 0, PTE_FRAG_SIZE);
+	return pgtable;
+}
+
+void hash__pmdp_huge_split_prepare(struct vm_area_struct *vma,
+			       unsigned long address, pmd_t *pmdp)
+{
+	VM_BUG_ON(address & ~HPAGE_PMD_MASK);
+	VM_BUG_ON(REGION_ID(address) != USER_REGION_ID);
+
+	/*
+	 * We can't mark the pmd none here, because that will cause a race
+	 * against exit_mmap. We need to continue mark pmd TRANS HUGE, while
+	 * we spilt, but at the same time we wan't rest of the ppc64 code
+	 * not to insert hash pte on this, because we will be modifying
+	 * the deposited pgtable in the caller of this function. Hence
+	 * clear the _PAGE_USER so that we move the fault handling to
+	 * higher level function and that will serialize against ptl.
+	 * We need to flush existing hash pte entries here even though,
+	 * the translation is still valid, because we will withdraw
+	 * pgtable_t after this.
+	 */
+	pmd_hugepage_update(vma->vm_mm, address, pmdp, 0, _PAGE_PRIVILEGED);
+}
+
+/*
+ * A linux hugepage PMD was changed and the corresponding hash table entries
+ * neesd to be flushed.
+ */
+void hpte_do_hugepage_flush(struct mm_struct *mm, unsigned long addr,
+			    pmd_t *pmdp, unsigned long old_pmd)
+{
+	int ssize;
+	unsigned int psize;
+	unsigned long vsid;
+	unsigned long flags = 0;
+	const struct cpumask *tmp;
+
+	/* get the base page size,vsid and segment size */
+#ifdef CONFIG_DEBUG_VM
+	psize = get_slice_psize(mm, addr);
+	BUG_ON(psize == MMU_PAGE_16M);
+#endif
+	if (old_pmd & H_PAGE_COMBO)
+		psize = MMU_PAGE_4K;
+	else
+		psize = MMU_PAGE_64K;
+
+	if (!is_kernel_addr(addr)) {
+		ssize = user_segment_size(addr);
+		vsid = get_vsid(mm->context.id, addr, ssize);
+		WARN_ON(vsid == 0);
+	} else {
+		vsid = get_kernel_vsid(addr, mmu_kernel_ssize);
+		ssize = mmu_kernel_ssize;
+	}
+
+	tmp = cpumask_of(smp_processor_id());
+	if (cpumask_equal(mm_cpumask(mm), tmp))
+		flags |= HPTE_LOCAL_UPDATE;
+
+	return flush_hash_hugepage(vsid, addr, pmdp, psize, ssize, flags);
+}
+
+pmd_t hash__pmdp_huge_get_and_clear(struct mm_struct *mm,
+				unsigned long addr, pmd_t *pmdp)
+{
+	pmd_t old_pmd;
+	pgtable_t pgtable;
+	unsigned long old;
+	pgtable_t *pgtable_slot;
+
+	old = pmd_hugepage_update(mm, addr, pmdp, ~0UL, 0);
+	old_pmd = __pmd(old);
+	/*
+	 * We have pmd == none and we are holding page_table_lock.
+	 * So we can safely go and clear the pgtable hash
+	 * index info.
+	 */
+	pgtable_slot = (pgtable_t *)pmdp + PTRS_PER_PMD;
+	pgtable = *pgtable_slot;
+	/*
+	 * Let's zero out old valid and hash index details
+	 * hash fault look at them.
+	 */
+	memset(pgtable, 0, PTE_FRAG_SIZE);
+	/*
+	 * Serialize against find_linux_pte_or_hugepte which does lock-less
+	 * lookup in page tables with local interrupts disabled. For huge pages
+	 * it casts pmd_t to pte_t. Since format of pte_t is different from
+	 * pmd_t we want to prevent transit from pmd pointing to page table
+	 * to pmd pointing to huge page (and back) while interrupts are disabled.
+	 * We clear pmd to possibly replace it with page table pointer in
+	 * different code paths. So make sure we wait for the parallel
+	 * find_linux_pte_or_hugepage to finish.
+	 */
+	kick_all_cpus_sync();
+	return old_pmd;
+}
+
+int hash__has_transparent_hugepage(void)
+{
+
+	if (!mmu_has_feature(MMU_FTR_16M_PAGE))
+		return 0;
+	/*
+	 * We support THP only if PMD_SIZE is 16MB.
+	 */
+	if (mmu_psize_defs[MMU_PAGE_16M].shift != PMD_SHIFT)
+		return 0;
+	/*
+	 * We need to make sure that we support 16MB hugepage in a segement
+	 * with base page size 64K or 4K. We only enable THP with a PAGE_SIZE
+	 * of 64K.
+	 */
+	/*
+	 * If we have 64K HPTE, we will be using that by default
+	 */
+	if (mmu_psize_defs[MMU_PAGE_64K].shift &&
+	    (mmu_psize_defs[MMU_PAGE_64K].penc[MMU_PAGE_16M] == -1))
+		return 0;
+	/*
+	 * Ok we only have 4K HPTE
+	 */
+	if (mmu_psize_defs[MMU_PAGE_4K].penc[MMU_PAGE_16M] == -1)
+		return 0;
+
+	return 1;
+}
+#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/mm/pgtable-radix.c linux-libre-4.7-gnu/arch/powerpc/mm/pgtable-radix.c
--- linux-libre-4.6-gnu/arch/powerpc/mm/pgtable-radix.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/powerpc/mm/pgtable-radix.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,525 @@
+/*
+ * Page table handling routines for radix page table.
+ *
+ * Copyright 2015-2016, Aneesh Kumar K.V, IBM 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; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <linux/sched.h>
+#include <linux/memblock.h>
+#include <linux/of_fdt.h>
+
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/dma.h>
+#include <asm/machdep.h>
+#include <asm/mmu.h>
+#include <asm/firmware.h>
+
+#include <trace/events/thp.h>
+
+static int native_update_partition_table(u64 patb1)
+{
+	partition_tb->patb1 = cpu_to_be64(patb1);
+	return 0;
+}
+
+static __ref void *early_alloc_pgtable(unsigned long size)
+{
+	void *pt;
+
+	pt = __va(memblock_alloc_base(size, size, MEMBLOCK_ALLOC_ANYWHERE));
+	memset(pt, 0, size);
+
+	return pt;
+}
+
+int radix__map_kernel_page(unsigned long ea, unsigned long pa,
+			  pgprot_t flags,
+			  unsigned int map_page_size)
+{
+	pgd_t *pgdp;
+	pud_t *pudp;
+	pmd_t *pmdp;
+	pte_t *ptep;
+	/*
+	 * Make sure task size is correct as per the max adddr
+	 */
+	BUILD_BUG_ON(TASK_SIZE_USER64 > RADIX_PGTABLE_RANGE);
+	if (slab_is_available()) {
+		pgdp = pgd_offset_k(ea);
+		pudp = pud_alloc(&init_mm, pgdp, ea);
+		if (!pudp)
+			return -ENOMEM;
+		if (map_page_size == PUD_SIZE) {
+			ptep = (pte_t *)pudp;
+			goto set_the_pte;
+		}
+		pmdp = pmd_alloc(&init_mm, pudp, ea);
+		if (!pmdp)
+			return -ENOMEM;
+		if (map_page_size == PMD_SIZE) {
+			ptep = (pte_t *)pudp;
+			goto set_the_pte;
+		}
+		ptep = pte_alloc_kernel(pmdp, ea);
+		if (!ptep)
+			return -ENOMEM;
+	} else {
+		pgdp = pgd_offset_k(ea);
+		if (pgd_none(*pgdp)) {
+			pudp = early_alloc_pgtable(PUD_TABLE_SIZE);
+			BUG_ON(pudp == NULL);
+			pgd_populate(&init_mm, pgdp, pudp);
+		}
+		pudp = pud_offset(pgdp, ea);
+		if (map_page_size == PUD_SIZE) {
+			ptep = (pte_t *)pudp;
+			goto set_the_pte;
+		}
+		if (pud_none(*pudp)) {
+			pmdp = early_alloc_pgtable(PMD_TABLE_SIZE);
+			BUG_ON(pmdp == NULL);
+			pud_populate(&init_mm, pudp, pmdp);
+		}
+		pmdp = pmd_offset(pudp, ea);
+		if (map_page_size == PMD_SIZE) {
+			ptep = (pte_t *)pudp;
+			goto set_the_pte;
+		}
+		if (!pmd_present(*pmdp)) {
+			ptep = early_alloc_pgtable(PAGE_SIZE);
+			BUG_ON(ptep == NULL);
+			pmd_populate_kernel(&init_mm, pmdp, ptep);
+		}
+		ptep = pte_offset_kernel(pmdp, ea);
+	}
+
+set_the_pte:
+	set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT, flags));
+	smp_wmb();
+	return 0;
+}
+
+static void __init radix_init_pgtable(void)
+{
+	int loop_count;
+	u64 base, end, start_addr;
+	unsigned long rts_field;
+	struct memblock_region *reg;
+	unsigned long linear_page_size;
+
+	/* We don't support slb for radix */
+	mmu_slb_size = 0;
+	/*
+	 * Create the linear mapping, using standard page size for now
+	 */
+	loop_count = 0;
+	for_each_memblock(memory, reg) {
+
+		start_addr = reg->base;
+
+redo:
+		if (loop_count < 1 && mmu_psize_defs[MMU_PAGE_1G].shift)
+			linear_page_size = PUD_SIZE;
+		else if (loop_count < 2 && mmu_psize_defs[MMU_PAGE_2M].shift)
+			linear_page_size = PMD_SIZE;
+		else
+			linear_page_size = PAGE_SIZE;
+
+		base = _ALIGN_UP(start_addr, linear_page_size);
+		end = _ALIGN_DOWN(reg->base + reg->size, linear_page_size);
+
+		pr_info("Mapping range 0x%lx - 0x%lx with 0x%lx\n",
+			(unsigned long)base, (unsigned long)end,
+			linear_page_size);
+
+		while (base < end) {
+			radix__map_kernel_page((unsigned long)__va(base),
+					      base, PAGE_KERNEL_X,
+					      linear_page_size);
+			base += linear_page_size;
+		}
+		/*
+		 * map the rest using lower page size
+		 */
+		if (end < reg->base + reg->size) {
+			start_addr = end;
+			loop_count++;
+			goto redo;
+		}
+	}
+	/*
+	 * Allocate Partition table and process table for the
+	 * host.
+	 */
+	BUILD_BUG_ON_MSG((PRTB_SIZE_SHIFT > 23), "Process table size too large.");
+	process_tb = early_alloc_pgtable(1UL << PRTB_SIZE_SHIFT);
+	/*
+	 * Fill in the process table.
+	 */
+	rts_field = radix__get_tree_size();
+	process_tb->prtb0 = cpu_to_be64(rts_field | __pa(init_mm.pgd) | RADIX_PGD_INDEX_SIZE);
+	/*
+	 * Fill in the partition table. We are suppose to use effective address
+	 * of process table here. But our linear mapping also enable us to use
+	 * physical address here.
+	 */
+	ppc_md.update_partition_table(__pa(process_tb) | (PRTB_SIZE_SHIFT - 12) | PATB_GR);
+	pr_info("Process table %p and radix root for kernel: %p\n", process_tb, init_mm.pgd);
+}
+
+static void __init radix_init_partition_table(void)
+{
+	unsigned long rts_field;
+
+	rts_field = radix__get_tree_size();
+
+	BUILD_BUG_ON_MSG((PATB_SIZE_SHIFT > 24), "Partition table size too large.");
+	partition_tb = early_alloc_pgtable(1UL << PATB_SIZE_SHIFT);
+	partition_tb->patb0 = cpu_to_be64(rts_field | __pa(init_mm.pgd) |
+					  RADIX_PGD_INDEX_SIZE | PATB_HR);
+	printk("Partition table %p\n", partition_tb);
+
+	memblock_set_current_limit(MEMBLOCK_ALLOC_ANYWHERE);
+	/*
+	 * update partition table control register,
+	 * 64 K size.
+	 */
+	mtspr(SPRN_PTCR, __pa(partition_tb) | (PATB_SIZE_SHIFT - 12));
+}
+
+void __init radix_init_native(void)
+{
+	ppc_md.update_partition_table = native_update_partition_table;
+}
+
+static int __init get_idx_from_shift(unsigned int shift)
+{
+	int idx = -1;
+
+	switch (shift) {
+	case 0xc:
+		idx = MMU_PAGE_4K;
+		break;
+	case 0x10:
+		idx = MMU_PAGE_64K;
+		break;
+	case 0x15:
+		idx = MMU_PAGE_2M;
+		break;
+	case 0x1e:
+		idx = MMU_PAGE_1G;
+		break;
+	}
+	return idx;
+}
+
+static int __init radix_dt_scan_page_sizes(unsigned long node,
+					   const char *uname, int depth,
+					   void *data)
+{
+	int size = 0;
+	int shift, idx;
+	unsigned int ap;
+	const __be32 *prop;
+	const char *type = of_get_flat_dt_prop(node, "device_type", NULL);
+
+	/* We are scanning "cpu" nodes only */
+	if (type == NULL || strcmp(type, "cpu") != 0)
+		return 0;
+
+	prop = of_get_flat_dt_prop(node, "ibm,processor-radix-AP-encodings", &size);
+	if (!prop)
+		return 0;
+
+	pr_info("Page sizes from device-tree:\n");
+	for (; size >= 4; size -= 4, ++prop) {
+
+		struct mmu_psize_def *def;
+
+		/* top 3 bit is AP encoding */
+		shift = be32_to_cpu(prop[0]) & ~(0xe << 28);
+		ap = be32_to_cpu(prop[0]) >> 29;
+		pr_info("Page size sift = %d AP=0x%x\n", shift, ap);
+
+		idx = get_idx_from_shift(shift);
+		if (idx < 0)
+			continue;
+
+		def = &mmu_psize_defs[idx];
+		def->shift = shift;
+		def->ap  = ap;
+	}
+
+	/* needed ? */
+	cur_cpu_spec->mmu_features &= ~MMU_FTR_NO_SLBIE_B;
+	return 1;
+}
+
+static void __init radix_init_page_sizes(void)
+{
+	int rc;
+
+	/*
+	 * Try to find the available page sizes in the device-tree
+	 */
+	rc = of_scan_flat_dt(radix_dt_scan_page_sizes, NULL);
+	if (rc != 0)  /* Found */
+		goto found;
+	/*
+	 * let's assume we have page 4k and 64k support
+	 */
+	mmu_psize_defs[MMU_PAGE_4K].shift = 12;
+	mmu_psize_defs[MMU_PAGE_4K].ap = 0x0;
+
+	mmu_psize_defs[MMU_PAGE_64K].shift = 16;
+	mmu_psize_defs[MMU_PAGE_64K].ap = 0x5;
+found:
+#ifdef CONFIG_SPARSEMEM_VMEMMAP
+	if (mmu_psize_defs[MMU_PAGE_2M].shift) {
+		/*
+		 * map vmemmap using 2M if available
+		 */
+		mmu_vmemmap_psize = MMU_PAGE_2M;
+	}
+#endif /* CONFIG_SPARSEMEM_VMEMMAP */
+	return;
+}
+
+void __init radix__early_init_mmu(void)
+{
+	unsigned long lpcr;
+
+#ifdef CONFIG_PPC_64K_PAGES
+	/* PAGE_SIZE mappings */
+	mmu_virtual_psize = MMU_PAGE_64K;
+#else
+	mmu_virtual_psize = MMU_PAGE_4K;
+#endif
+
+#ifdef CONFIG_SPARSEMEM_VMEMMAP
+	/* vmemmap mapping */
+	mmu_vmemmap_psize = mmu_virtual_psize;
+#endif
+	/*
+	 * initialize page table size
+	 */
+	__pte_index_size = RADIX_PTE_INDEX_SIZE;
+	__pmd_index_size = RADIX_PMD_INDEX_SIZE;
+	__pud_index_size = RADIX_PUD_INDEX_SIZE;
+	__pgd_index_size = RADIX_PGD_INDEX_SIZE;
+	__pmd_cache_index = RADIX_PMD_INDEX_SIZE;
+	__pte_table_size = RADIX_PTE_TABLE_SIZE;
+	__pmd_table_size = RADIX_PMD_TABLE_SIZE;
+	__pud_table_size = RADIX_PUD_TABLE_SIZE;
+	__pgd_table_size = RADIX_PGD_TABLE_SIZE;
+
+	__pmd_val_bits = RADIX_PMD_VAL_BITS;
+	__pud_val_bits = RADIX_PUD_VAL_BITS;
+	__pgd_val_bits = RADIX_PGD_VAL_BITS;
+
+	__kernel_virt_start = RADIX_KERN_VIRT_START;
+	__kernel_virt_size = RADIX_KERN_VIRT_SIZE;
+	__vmalloc_start = RADIX_VMALLOC_START;
+	__vmalloc_end = RADIX_VMALLOC_END;
+	vmemmap = (struct page *)RADIX_VMEMMAP_BASE;
+	ioremap_bot = IOREMAP_BASE;
+
+#ifdef CONFIG_PCI
+	pci_io_base = ISA_IO_BASE;
+#endif
+
+	/*
+	 * For now radix also use the same frag size
+	 */
+	__pte_frag_nr = H_PTE_FRAG_NR;
+	__pte_frag_size_shift = H_PTE_FRAG_SIZE_SHIFT;
+
+	radix_init_page_sizes();
+	if (!firmware_has_feature(FW_FEATURE_LPAR)) {
+		lpcr = mfspr(SPRN_LPCR);
+		mtspr(SPRN_LPCR, lpcr | LPCR_UPRT);
+		radix_init_partition_table();
+	}
+
+	radix_init_pgtable();
+}
+
+void radix__early_init_mmu_secondary(void)
+{
+	unsigned long lpcr;
+	/*
+	 * update partition table control register and UPRT
+	 */
+	if (!firmware_has_feature(FW_FEATURE_LPAR)) {
+		lpcr = mfspr(SPRN_LPCR);
+		mtspr(SPRN_LPCR, lpcr | LPCR_UPRT);
+
+		mtspr(SPRN_PTCR,
+		      __pa(partition_tb) | (PATB_SIZE_SHIFT - 12));
+	}
+}
+
+void radix__setup_initial_memory_limit(phys_addr_t first_memblock_base,
+				phys_addr_t first_memblock_size)
+{
+	/* We don't currently support the first MEMBLOCK not mapping 0
+	 * physical on those processors
+	 */
+	BUG_ON(first_memblock_base != 0);
+	/*
+	 * We limit the allocation that depend on ppc64_rma_size
+	 * to first_memblock_size. We also clamp it to 1GB to
+	 * avoid some funky things such as RTAS bugs.
+	 *
+	 * On radix config we really don't have a limitation
+	 * on real mode access. But keeping it as above works
+	 * well enough.
+	 */
+	ppc64_rma_size = min_t(u64, first_memblock_size, 0x40000000);
+	/*
+	 * Finally limit subsequent allocations. We really don't want
+	 * to limit the memblock allocations to rma_size. FIXME!! should
+	 * we even limit at all ?
+	 */
+	memblock_set_current_limit(first_memblock_base + first_memblock_size);
+}
+
+#ifdef CONFIG_SPARSEMEM_VMEMMAP
+int __meminit radix__vmemmap_create_mapping(unsigned long start,
+				      unsigned long page_size,
+				      unsigned long phys)
+{
+	/* Create a PTE encoding */
+	unsigned long flags = _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_KERNEL_RW;
+
+	BUG_ON(radix__map_kernel_page(start, phys, __pgprot(flags), page_size));
+	return 0;
+}
+
+#ifdef CONFIG_MEMORY_HOTPLUG
+void radix__vmemmap_remove_mapping(unsigned long start, unsigned long page_size)
+{
+	/* FIXME!! intel does more. We should free page tables mapping vmemmap ? */
+}
+#endif
+#endif
+
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+
+unsigned long radix__pmd_hugepage_update(struct mm_struct *mm, unsigned long addr,
+				  pmd_t *pmdp, unsigned long clr,
+				  unsigned long set)
+{
+	unsigned long old;
+
+#ifdef CONFIG_DEBUG_VM
+	WARN_ON(!radix__pmd_trans_huge(*pmdp));
+	assert_spin_locked(&mm->page_table_lock);
+#endif
+
+	old = radix__pte_update(mm, addr, (pte_t *)pmdp, clr, set, 1);
+	trace_hugepage_update(addr, old, clr, set);
+
+	return old;
+}
+
+pmd_t radix__pmdp_collapse_flush(struct vm_area_struct *vma, unsigned long address,
+			pmd_t *pmdp)
+
+{
+	pmd_t pmd;
+
+	VM_BUG_ON(address & ~HPAGE_PMD_MASK);
+	VM_BUG_ON(radix__pmd_trans_huge(*pmdp));
+	/*
+	 * khugepaged calls this for normal pmd
+	 */
+	pmd = *pmdp;
+	pmd_clear(pmdp);
+	/*FIXME!!  Verify whether we need this kick below */
+	kick_all_cpus_sync();
+	flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
+	return pmd;
+}
+
+/*
+ * For us pgtable_t is pte_t *. Inorder to save the deposisted
+ * page table, we consider the allocated page table as a list
+ * head. On withdraw we need to make sure we zero out the used
+ * list_head memory area.
+ */
+void radix__pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp,
+				 pgtable_t pgtable)
+{
+        struct list_head *lh = (struct list_head *) pgtable;
+
+        assert_spin_locked(pmd_lockptr(mm, pmdp));
+
+        /* FIFO */
+        if (!pmd_huge_pte(mm, pmdp))
+                INIT_LIST_HEAD(lh);
+        else
+                list_add(lh, (struct list_head *) pmd_huge_pte(mm, pmdp));
+        pmd_huge_pte(mm, pmdp) = pgtable;
+}
+
+pgtable_t radix__pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp)
+{
+        pte_t *ptep;
+        pgtable_t pgtable;
+        struct list_head *lh;
+
+        assert_spin_locked(pmd_lockptr(mm, pmdp));
+
+        /* FIFO */
+        pgtable = pmd_huge_pte(mm, pmdp);
+        lh = (struct list_head *) pgtable;
+        if (list_empty(lh))
+                pmd_huge_pte(mm, pmdp) = NULL;
+        else {
+                pmd_huge_pte(mm, pmdp) = (pgtable_t) lh->next;
+                list_del(lh);
+        }
+        ptep = (pte_t *) pgtable;
+        *ptep = __pte(0);
+        ptep++;
+        *ptep = __pte(0);
+        return pgtable;
+}
+
+
+pmd_t radix__pmdp_huge_get_and_clear(struct mm_struct *mm,
+			       unsigned long addr, pmd_t *pmdp)
+{
+	pmd_t old_pmd;
+	unsigned long old;
+
+	old = radix__pmd_hugepage_update(mm, addr, pmdp, ~0UL, 0);
+	old_pmd = __pmd(old);
+	/*
+	 * Serialize against find_linux_pte_or_hugepte which does lock-less
+	 * lookup in page tables with local interrupts disabled. For huge pages
+	 * it casts pmd_t to pte_t. Since format of pte_t is different from
+	 * pmd_t we want to prevent transit from pmd pointing to page table
+	 * to pmd pointing to huge page (and back) while interrupts are disabled.
+	 * We clear pmd to possibly replace it with page table pointer in
+	 * different code paths. So make sure we wait for the parallel
+	 * find_linux_pte_or_hugepage to finish.
+	 */
+	kick_all_cpus_sync();
+	return old_pmd;
+}
+
+int radix__has_transparent_hugepage(void)
+{
+	/* For radix 2M at PMD level means thp */
+	if (mmu_psize_defs[MMU_PAGE_2M].shift == PMD_SHIFT)
+		return 1;
+	return 0;
+}
+#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/mm/slb.c linux-libre-4.7-gnu/arch/powerpc/mm/slb.c
--- linux-libre-4.6-gnu/arch/powerpc/mm/slb.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/mm/slb.c	2016-07-24 15:23:50.000000000 -0400
@@ -32,7 +32,6 @@ enum slb_index {
 };
 
 extern void slb_allocate_realmode(unsigned long ea);
-extern void slb_allocate_user(unsigned long ea);
 
 static void slb_allocate(unsigned long ea)
 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/mm/slb_low.S linux-libre-4.7-gnu/arch/powerpc/mm/slb_low.S
--- linux-libre-4.6-gnu/arch/powerpc/mm/slb_low.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/mm/slb_low.S	2016-07-24 15:23:50.000000000 -0400
@@ -35,7 +35,7 @@ _GLOBAL(slb_allocate_realmode)
 	 * check for bad kernel/user address
 	 * (ea & ~REGION_MASK) >= PGTABLE_RANGE
 	 */
-	rldicr. r9,r3,4,(63 - PGTABLE_EADDR_SIZE - 4)
+	rldicr. r9,r3,4,(63 - H_PGTABLE_EADDR_SIZE - 4)
 	bne-	8f
 
 	srdi	r9,r3,60		/* get region */
@@ -91,7 +91,7 @@ slb_miss_kernel_load_vmemmap:
 	 * can be demoted from 64K -> 4K dynamically on some machines
 	 */
 	clrldi	r11,r10,48
-	cmpldi	r11,(VMALLOC_SIZE >> 28) - 1
+	cmpldi	r11,(H_VMALLOC_SIZE >> 28) - 1
 	bgt	5f
 	lhz	r11,PACAVMALLOCSLLP(r13)
 	b	6f
@@ -179,56 +179,6 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEG
 	li	r11,SLB_VSID_USER	/* flags don't much matter */
 	b	slb_finish_load
 
-#ifdef __DISABLED__
-
-/* void slb_allocate_user(unsigned long ea);
- *
- * Create an SLB entry for the given EA (user or kernel).
- * 	r3 = faulting address, r13 = PACA
- *	r9, r10, r11 are clobbered by this function
- * No other registers are examined or changed.
- *
- * It is called with translation enabled in order to be able to walk the
- * page tables. This is not currently used.
- */
-_GLOBAL(slb_allocate_user)
-	/* r3 = faulting address */
-	srdi	r10,r3,28		/* get esid */
-
-	crset	4*cr7+lt		/* set "user" flag for later */
-
-	/* check if we fit in the range covered by the pagetables*/
-	srdi.	r9,r3,PGTABLE_EADDR_SIZE
-	crnot	4*cr0+eq,4*cr0+eq
-	beqlr
-
-	/* now we need to get to the page tables in order to get the page
-	 * size encoding from the PMD. In the future, we'll be able to deal
-	 * with 1T segments too by getting the encoding from the PGD instead
-	 */
-	ld	r9,PACAPGDIR(r13)
-	cmpldi	cr0,r9,0
-	beqlr
-	rlwinm	r11,r10,8,25,28
-	ldx	r9,r9,r11		/* get pgd_t */
-	cmpldi	cr0,r9,0
-	beqlr
-	rlwinm	r11,r10,3,17,28
-	ldx	r9,r9,r11		/* get pmd_t */
-	cmpldi	cr0,r9,0
-	beqlr
-
-	/* build vsid flags */
-	andi.	r11,r9,SLB_VSID_LLP
-	ori	r11,r11,SLB_VSID_USER
-
-	/* get context to calculate proto-VSID */
-	ld	r9,PACACONTEXTID(r13)
-	/* fall through slb_finish_load */
-
-#endif /* __DISABLED__ */
-
-
 /*
  * Finish loading of an SLB entry and return
  *
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/mm/slice.c linux-libre-4.7-gnu/arch/powerpc/mm/slice.c
--- linux-libre-4.6-gnu/arch/powerpc/mm/slice.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/mm/slice.c	2016-07-24 15:23:50.000000000 -0400
@@ -37,8 +37,8 @@
 #include <asm/hugetlb.h>
 
 /* some sanity checks */
-#if (PGTABLE_RANGE >> 43) > SLICE_MASK_SIZE
-#error PGTABLE_RANGE exceeds slice_mask high_slices size
+#if (H_PGTABLE_RANGE >> 43) > SLICE_MASK_SIZE
+#error H_PGTABLE_RANGE exceeds slice_mask high_slices size
 #endif
 
 static DEFINE_SPINLOCK(slice_convert_lock);
@@ -395,6 +395,7 @@ unsigned long slice_get_unmapped_area(un
 
 	/* Sanity checks */
 	BUG_ON(mm->task_size == 0);
+	VM_BUG_ON(radix_enabled());
 
 	slice_dbg("slice_get_unmapped_area(mm=%p, psize=%d...\n", mm, psize);
 	slice_dbg(" addr=%lx, len=%lx, flags=%lx, topdown=%d\n",
@@ -568,6 +569,16 @@ unsigned int get_slice_psize(struct mm_s
 	unsigned char *hpsizes;
 	int index, mask_index;
 
+	/*
+	 * Radix doesn't use slice, but can get enabled along with MMU_SLICE
+	 */
+	if (radix_enabled()) {
+#ifdef CONFIG_PPC_64K_PAGES
+		return MMU_PAGE_64K;
+#else
+		return MMU_PAGE_4K;
+#endif
+	}
 	if (addr < SLICE_LOW_TOP) {
 		u64 lpsizes;
 		lpsizes = mm->context.low_slices_psize;
@@ -605,6 +616,7 @@ void slice_set_user_psize(struct mm_stru
 
 	slice_dbg("slice_set_user_psize(mm=%p, psize=%d)\n", mm, psize);
 
+	VM_BUG_ON(radix_enabled());
 	spin_lock_irqsave(&slice_convert_lock, flags);
 
 	old_psize = mm->context.user_psize;
@@ -649,6 +661,7 @@ void slice_set_range_psize(struct mm_str
 {
 	struct slice_mask mask = slice_range_to_mask(start, len);
 
+	VM_BUG_ON(radix_enabled());
 	slice_convert(mm, mask, psize);
 }
 
@@ -678,6 +691,9 @@ int is_hugepage_only_range(struct mm_str
 	struct slice_mask mask, available;
 	unsigned int psize = mm->context.user_psize;
 
+	if (radix_enabled())
+		return 0;
+
 	mask = slice_range_to_mask(addr, len);
 	available = slice_mask_for_size(mm, psize);
 #ifdef CONFIG_PPC_64K_PAGES
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/mm/tlb_hash64.c linux-libre-4.7-gnu/arch/powerpc/mm/tlb_hash64.c
--- linux-libre-4.6-gnu/arch/powerpc/mm/tlb_hash64.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/mm/tlb_hash64.c	2016-07-24 15:23:50.000000000 -0400
@@ -155,7 +155,7 @@ void __flush_tlb_pending(struct ppc64_tl
 	batch->index = 0;
 }
 
-void tlb_flush(struct mmu_gather *tlb)
+void hash__tlb_flush(struct mmu_gather *tlb)
 {
 	struct ppc64_tlb_batch *tlbbatch = &get_cpu_var(ppc64_tlb_batch);
 
@@ -218,7 +218,7 @@ void __flush_hash_table_range(struct mm_
 		pte = pte_val(*ptep);
 		if (is_thp)
 			trace_hugepage_invalidate(start, pte);
-		if (!(pte & _PAGE_HASHPTE))
+		if (!(pte & H_PAGE_HASHPTE))
 			continue;
 		if (unlikely(is_thp))
 			hpte_do_hugepage_flush(mm, start, (pmd_t *)ptep, pte);
@@ -248,7 +248,7 @@ void flush_tlb_pmd_range(struct mm_struc
 	start_pte = pte_offset_map(pmd, addr);
 	for (pte = start_pte; pte < start_pte + PTRS_PER_PTE; pte++) {
 		unsigned long pteval = pte_val(*pte);
-		if (pteval & _PAGE_HASHPTE)
+		if (pteval & H_PAGE_HASHPTE)
 			hpte_need_flush(mm, addr, pte, pteval, 0);
 		addr += PAGE_SIZE;
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/mm/tlb-radix.c linux-libre-4.7-gnu/arch/powerpc/mm/tlb-radix.c
--- linux-libre-4.6-gnu/arch/powerpc/mm/tlb-radix.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/powerpc/mm/tlb-radix.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,293 @@
+/*
+ * TLB flush routines for radix kernels.
+ *
+ * Copyright 2015-2016, Aneesh Kumar K.V, IBM 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; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/mm.h>
+#include <linux/hugetlb.h>
+#include <linux/memblock.h>
+
+#include <asm/tlb.h>
+#include <asm/tlbflush.h>
+
+static DEFINE_RAW_SPINLOCK(native_tlbie_lock);
+
+#define RIC_FLUSH_TLB 0
+#define RIC_FLUSH_PWC 1
+#define RIC_FLUSH_ALL 2
+
+static inline void __tlbiel_pid(unsigned long pid, int set,
+				unsigned long ric)
+{
+	unsigned long rb,rs,prs,r;
+
+	rb = PPC_BIT(53); /* IS = 1 */
+	rb |= set << PPC_BITLSHIFT(51);
+	rs = ((unsigned long)pid) << PPC_BITLSHIFT(31);
+	prs = 1; /* process scoped */
+	r = 1;   /* raidx format */
+
+	asm volatile("ptesync": : :"memory");
+	asm volatile(".long 0x7c000224 | (%0 << 11) | (%1 << 16) |"
+		     "(%2 << 17) | (%3 << 18) | (%4 << 21)"
+		     : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory");
+	asm volatile("ptesync": : :"memory");
+}
+
+/*
+ * We use 128 set in radix mode and 256 set in hpt mode.
+ */
+static inline void _tlbiel_pid(unsigned long pid, unsigned long ric)
+{
+	int set;
+
+	for (set = 0; set < POWER9_TLB_SETS_RADIX ; set++) {
+		__tlbiel_pid(pid, set, ric);
+	}
+	return;
+}
+
+static inline void _tlbie_pid(unsigned long pid, unsigned long ric)
+{
+	unsigned long rb,rs,prs,r;
+
+	rb = PPC_BIT(53); /* IS = 1 */
+	rs = pid << PPC_BITLSHIFT(31);
+	prs = 1; /* process scoped */
+	r = 1;   /* raidx format */
+
+	asm volatile("ptesync": : :"memory");
+	asm volatile(".long 0x7c000264 | (%0 << 11) | (%1 << 16) |"
+		     "(%2 << 17) | (%3 << 18) | (%4 << 21)"
+		     : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory");
+	asm volatile("eieio; tlbsync; ptesync": : :"memory");
+}
+
+static inline void _tlbiel_va(unsigned long va, unsigned long pid,
+			      unsigned long ap, unsigned long ric)
+{
+	unsigned long rb,rs,prs,r;
+
+	rb = va & ~(PPC_BITMASK(52, 63));
+	rb |= ap << PPC_BITLSHIFT(58);
+	rs = pid << PPC_BITLSHIFT(31);
+	prs = 1; /* process scoped */
+	r = 1;   /* raidx format */
+
+	asm volatile("ptesync": : :"memory");
+	asm volatile(".long 0x7c000224 | (%0 << 11) | (%1 << 16) |"
+		     "(%2 << 17) | (%3 << 18) | (%4 << 21)"
+		     : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory");
+	asm volatile("ptesync": : :"memory");
+}
+
+static inline void _tlbie_va(unsigned long va, unsigned long pid,
+			     unsigned long ap, unsigned long ric)
+{
+	unsigned long rb,rs,prs,r;
+
+	rb = va & ~(PPC_BITMASK(52, 63));
+	rb |= ap << PPC_BITLSHIFT(58);
+	rs = pid << PPC_BITLSHIFT(31);
+	prs = 1; /* process scoped */
+	r = 1;   /* raidx format */
+
+	asm volatile("ptesync": : :"memory");
+	asm volatile(".long 0x7c000264 | (%0 << 11) | (%1 << 16) |"
+		     "(%2 << 17) | (%3 << 18) | (%4 << 21)"
+		     : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory");
+	asm volatile("eieio; tlbsync; ptesync": : :"memory");
+}
+
+/*
+ * Base TLB flushing operations:
+ *
+ *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
+ *  - flush_tlb_page(vma, vmaddr) flushes one page
+ *  - flush_tlb_range(vma, start, end) flushes a range of pages
+ *  - flush_tlb_kernel_range(start, end) flushes kernel pages
+ *
+ *  - local_* variants of page and mm only apply to the current
+ *    processor
+ */
+void radix__local_flush_tlb_mm(struct mm_struct *mm)
+{
+	unsigned long pid;
+
+	preempt_disable();
+	pid = mm->context.id;
+	if (pid != MMU_NO_CONTEXT)
+		_tlbiel_pid(pid, RIC_FLUSH_ALL);
+	preempt_enable();
+}
+EXPORT_SYMBOL(radix__local_flush_tlb_mm);
+
+void radix__local_flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr)
+{
+	unsigned long pid;
+	struct mm_struct *mm = tlb->mm;
+
+	preempt_disable();
+
+	pid = mm->context.id;
+	if (pid != MMU_NO_CONTEXT)
+		_tlbiel_pid(pid, RIC_FLUSH_PWC);
+
+	preempt_enable();
+}
+EXPORT_SYMBOL(radix__local_flush_tlb_pwc);
+
+void radix___local_flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
+			    unsigned long ap, int nid)
+{
+	unsigned long pid;
+
+	preempt_disable();
+	pid = mm ? mm->context.id : 0;
+	if (pid != MMU_NO_CONTEXT)
+		_tlbiel_va(vmaddr, pid, ap, RIC_FLUSH_TLB);
+	preempt_enable();
+}
+
+void radix__local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
+{
+#ifdef CONFIG_HUGETLB_PAGE
+	/* need the return fix for nohash.c */
+	if (vma && is_vm_hugetlb_page(vma))
+		return __local_flush_hugetlb_page(vma, vmaddr);
+#endif
+	radix___local_flush_tlb_page(vma ? vma->vm_mm : NULL, vmaddr,
+			       mmu_get_ap(mmu_virtual_psize), 0);
+}
+EXPORT_SYMBOL(radix__local_flush_tlb_page);
+
+#ifdef CONFIG_SMP
+static int mm_is_core_local(struct mm_struct *mm)
+{
+	return cpumask_subset(mm_cpumask(mm),
+			      topology_sibling_cpumask(smp_processor_id()));
+}
+
+void radix__flush_tlb_mm(struct mm_struct *mm)
+{
+	unsigned long pid;
+
+	preempt_disable();
+	pid = mm->context.id;
+	if (unlikely(pid == MMU_NO_CONTEXT))
+		goto no_context;
+
+	if (!mm_is_core_local(mm)) {
+		int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE);
+
+		if (lock_tlbie)
+			raw_spin_lock(&native_tlbie_lock);
+		_tlbie_pid(pid, RIC_FLUSH_ALL);
+		if (lock_tlbie)
+			raw_spin_unlock(&native_tlbie_lock);
+	} else
+		_tlbiel_pid(pid, RIC_FLUSH_ALL);
+no_context:
+	preempt_enable();
+}
+EXPORT_SYMBOL(radix__flush_tlb_mm);
+
+void radix__flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr)
+{
+	unsigned long pid;
+	struct mm_struct *mm = tlb->mm;
+
+	preempt_disable();
+
+	pid = mm->context.id;
+	if (unlikely(pid == MMU_NO_CONTEXT))
+		goto no_context;
+
+	if (!mm_is_core_local(mm)) {
+		int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE);
+
+		if (lock_tlbie)
+			raw_spin_lock(&native_tlbie_lock);
+		_tlbie_pid(pid, RIC_FLUSH_PWC);
+		if (lock_tlbie)
+			raw_spin_unlock(&native_tlbie_lock);
+	} else
+		_tlbiel_pid(pid, RIC_FLUSH_PWC);
+no_context:
+	preempt_enable();
+}
+EXPORT_SYMBOL(radix__flush_tlb_pwc);
+
+void radix___flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
+		       unsigned long ap, int nid)
+{
+	unsigned long pid;
+
+	preempt_disable();
+	pid = mm ? mm->context.id : 0;
+	if (unlikely(pid == MMU_NO_CONTEXT))
+		goto bail;
+	if (!mm_is_core_local(mm)) {
+		int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE);
+
+		if (lock_tlbie)
+			raw_spin_lock(&native_tlbie_lock);
+		_tlbie_va(vmaddr, pid, ap, RIC_FLUSH_TLB);
+		if (lock_tlbie)
+			raw_spin_unlock(&native_tlbie_lock);
+	} else
+		_tlbiel_va(vmaddr, pid, ap, RIC_FLUSH_TLB);
+bail:
+	preempt_enable();
+}
+
+void radix__flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
+{
+#ifdef CONFIG_HUGETLB_PAGE
+	if (vma && is_vm_hugetlb_page(vma))
+		return flush_hugetlb_page(vma, vmaddr);
+#endif
+	radix___flush_tlb_page(vma ? vma->vm_mm : NULL, vmaddr,
+			 mmu_get_ap(mmu_virtual_psize), 0);
+}
+EXPORT_SYMBOL(radix__flush_tlb_page);
+
+#endif /* CONFIG_SMP */
+
+void radix__flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+	int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE);
+
+	if (lock_tlbie)
+		raw_spin_lock(&native_tlbie_lock);
+	_tlbie_pid(0, RIC_FLUSH_ALL);
+	if (lock_tlbie)
+		raw_spin_unlock(&native_tlbie_lock);
+}
+EXPORT_SYMBOL(radix__flush_tlb_kernel_range);
+
+/*
+ * Currently, for range flushing, we just do a full mm flush. Because
+ * we use this in code path where we don' track the page size.
+ */
+void radix__flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+		     unsigned long end)
+
+{
+	struct mm_struct *mm = vma->vm_mm;
+	radix__flush_tlb_mm(mm);
+}
+EXPORT_SYMBOL(radix__flush_tlb_range);
+
+
+void radix__tlb_flush(struct mmu_gather *tlb)
+{
+	struct mm_struct *mm = tlb->mm;
+	radix__flush_tlb_mm(mm);
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/perf/callchain.c linux-libre-4.7-gnu/arch/powerpc/perf/callchain.c
--- linux-libre-4.6-gnu/arch/powerpc/perf/callchain.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/perf/callchain.c	2016-07-24 15:23:50.000000000 -0400
@@ -47,7 +47,7 @@ static int valid_next_sp(unsigned long s
 }
 
 void
-perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs)
+perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs)
 {
 	unsigned long sp, next_sp;
 	unsigned long next_ip;
@@ -76,7 +76,7 @@ perf_callchain_kernel(struct perf_callch
 			next_ip = regs->nip;
 			lr = regs->link;
 			level = 0;
-			perf_callchain_store(entry, PERF_CONTEXT_KERNEL);
+			perf_callchain_store_context(entry, PERF_CONTEXT_KERNEL);
 
 		} else {
 			if (level == 0)
@@ -137,7 +137,7 @@ static int read_user_stack_slow(void __u
 	offset = addr & ((1UL << shift) - 1);
 
 	pte = READ_ONCE(*ptep);
-	if (!pte_present(pte) || !(pte_val(pte) & _PAGE_USER))
+	if (!pte_present(pte) || !pte_user(pte))
 		goto err_out;
 	pfn = pte_pfn(pte);
 	if (!page_is_ram(pfn))
@@ -232,7 +232,7 @@ static int sane_signal_64_frame(unsigned
 		puc == (unsigned long) &sf->uc;
 }
 
-static void perf_callchain_user_64(struct perf_callchain_entry *entry,
+static void perf_callchain_user_64(struct perf_callchain_entry_ctx *entry,
 				   struct pt_regs *regs)
 {
 	unsigned long sp, next_sp;
@@ -247,7 +247,7 @@ static void perf_callchain_user_64(struc
 	sp = regs->gpr[1];
 	perf_callchain_store(entry, next_ip);
 
-	while (entry->nr < PERF_MAX_STACK_DEPTH) {
+	while (entry->nr < entry->max_stack) {
 		fp = (unsigned long __user *) sp;
 		if (!valid_user_sp(sp, 1) || read_user_stack_64(fp, &next_sp))
 			return;
@@ -274,7 +274,7 @@ static void perf_callchain_user_64(struc
 			    read_user_stack_64(&uregs[PT_R1], &sp))
 				return;
 			level = 0;
-			perf_callchain_store(entry, PERF_CONTEXT_USER);
+			perf_callchain_store_context(entry, PERF_CONTEXT_USER);
 			perf_callchain_store(entry, next_ip);
 			continue;
 		}
@@ -319,7 +319,7 @@ static int read_user_stack_32(unsigned i
 	return rc;
 }
 
-static inline void perf_callchain_user_64(struct perf_callchain_entry *entry,
+static inline void perf_callchain_user_64(struct perf_callchain_entry_ctx *entry,
 					  struct pt_regs *regs)
 {
 }
@@ -439,7 +439,7 @@ static unsigned int __user *signal_frame
 	return mctx->mc_gregs;
 }
 
-static void perf_callchain_user_32(struct perf_callchain_entry *entry,
+static void perf_callchain_user_32(struct perf_callchain_entry_ctx *entry,
 				   struct pt_regs *regs)
 {
 	unsigned int sp, next_sp;
@@ -453,7 +453,7 @@ static void perf_callchain_user_32(struc
 	sp = regs->gpr[1];
 	perf_callchain_store(entry, next_ip);
 
-	while (entry->nr < PERF_MAX_STACK_DEPTH) {
+	while (entry->nr < entry->max_stack) {
 		fp = (unsigned int __user *) (unsigned long) sp;
 		if (!valid_user_sp(sp, 0) || read_user_stack_32(fp, &next_sp))
 			return;
@@ -473,7 +473,7 @@ static void perf_callchain_user_32(struc
 			    read_user_stack_32(&uregs[PT_R1], &sp))
 				return;
 			level = 0;
-			perf_callchain_store(entry, PERF_CONTEXT_USER);
+			perf_callchain_store_context(entry, PERF_CONTEXT_USER);
 			perf_callchain_store(entry, next_ip);
 			continue;
 		}
@@ -487,7 +487,7 @@ static void perf_callchain_user_32(struc
 }
 
 void
-perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
+perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs)
 {
 	if (current_is_64bit())
 		perf_callchain_user_64(entry, regs);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/perf/Makefile linux-libre-4.7-gnu/arch/powerpc/perf/Makefile
--- linux-libre-4.6-gnu/arch/powerpc/perf/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/perf/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -1,6 +1,6 @@
 subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
 
-obj-$(CONFIG_PERF_EVENTS)	+= callchain.o
+obj-$(CONFIG_PERF_EVENTS)	+= callchain.o perf_regs.o
 
 obj-$(CONFIG_PPC_PERF_CTRS)	+= core-book3s.o bhrb.o
 obj64-$(CONFIG_PPC_PERF_CTRS)	+= power4-pmu.o ppc970-pmu.o power5-pmu.o \
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/perf/perf_regs.c linux-libre-4.7-gnu/arch/powerpc/perf/perf_regs.c
--- linux-libre-4.6-gnu/arch/powerpc/perf/perf_regs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/powerpc/perf/perf_regs.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2016 Anju T, IBM 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; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/perf_event.h>
+#include <linux/bug.h>
+#include <linux/stddef.h>
+#include <asm/ptrace.h>
+#include <asm/perf_regs.h>
+
+#define PT_REGS_OFFSET(id, r) [id] = offsetof(struct pt_regs, r)
+
+#define REG_RESERVED (~((1ULL << PERF_REG_POWERPC_MAX) - 1))
+
+static unsigned int pt_regs_offset[PERF_REG_POWERPC_MAX] = {
+	PT_REGS_OFFSET(PERF_REG_POWERPC_R0,  gpr[0]),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_R1,  gpr[1]),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_R2,  gpr[2]),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_R3,  gpr[3]),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_R4,  gpr[4]),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_R5,  gpr[5]),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_R6,  gpr[6]),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_R7,  gpr[7]),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_R8,  gpr[8]),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_R9,  gpr[9]),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_R10, gpr[10]),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_R11, gpr[11]),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_R12, gpr[12]),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_R13, gpr[13]),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_R14, gpr[14]),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_R15, gpr[15]),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_R16, gpr[16]),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_R17, gpr[17]),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_R18, gpr[18]),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_R19, gpr[19]),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_R20, gpr[20]),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_R21, gpr[21]),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_R22, gpr[22]),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_R23, gpr[23]),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_R24, gpr[24]),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_R25, gpr[25]),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_R26, gpr[26]),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_R27, gpr[27]),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_R28, gpr[28]),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_R29, gpr[29]),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_R30, gpr[30]),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_R31, gpr[31]),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_NIP, nip),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_MSR, msr),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_ORIG_R3, orig_gpr3),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_CTR, ctr),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_LINK, link),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_XER, xer),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_CCR, ccr),
+#ifdef CONFIG_PPC64
+	PT_REGS_OFFSET(PERF_REG_POWERPC_SOFTE, softe),
+#else
+	PT_REGS_OFFSET(PERF_REG_POWERPC_SOFTE, mq),
+#endif
+	PT_REGS_OFFSET(PERF_REG_POWERPC_TRAP, trap),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_DAR, dar),
+	PT_REGS_OFFSET(PERF_REG_POWERPC_DSISR, dsisr),
+};
+
+u64 perf_reg_value(struct pt_regs *regs, int idx)
+{
+	if (WARN_ON_ONCE(idx >= PERF_REG_POWERPC_MAX))
+		return 0;
+
+	return regs_get_register(regs, pt_regs_offset[idx]);
+}
+
+int perf_reg_validate(u64 mask)
+{
+	if (!mask || mask & REG_RESERVED)
+		return -EINVAL;
+	return 0;
+}
+
+u64 perf_reg_abi(struct task_struct *task)
+{
+#ifdef CONFIG_PPC64
+	if (!test_tsk_thread_flag(task, TIF_32BIT))
+		return PERF_SAMPLE_REGS_ABI_64;
+	else
+#endif
+	return PERF_SAMPLE_REGS_ABI_32;
+}
+
+void perf_get_regs_user(struct perf_regs *regs_user,
+			struct pt_regs *regs,
+			struct pt_regs *regs_user_copy)
+{
+	regs_user->regs = task_pt_regs(current);
+	regs_user->abi  = perf_reg_abi(current);
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/perf/power8-events-list.h linux-libre-4.7-gnu/arch/powerpc/perf/power8-events-list.h
--- linux-libre-4.6-gnu/arch/powerpc/perf/power8-events-list.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/perf/power8-events-list.h	2016-07-24 15:23:50.000000000 -0400
@@ -49,3 +49,43 @@ EVENT(PM_L3_PREF_ALL,				0x4e052)
 EVENT(PM_DTLB_MISS,				0x300fc)
 /* ITLB Reloaded */
 EVENT(PM_ITLB_MISS,				0x400fc)
+/* Run_Instructions */
+EVENT(PM_RUN_INST_CMPL,				0x500fa)
+/* Alternate event code for PM_RUN_INST_CMPL */
+EVENT(PM_RUN_INST_CMPL_ALT,			0x400fa)
+/* Run_cycles */
+EVENT(PM_RUN_CYC,				0x600f4)
+/* Alternate event code for Run_cycles */
+EVENT(PM_RUN_CYC_ALT,				0x200f4)
+/* Marked store completed */
+EVENT(PM_MRK_ST_CMPL,				0x10134)
+/* Alternate event code for Marked store completed */
+EVENT(PM_MRK_ST_CMPL_ALT,			0x301e2)
+/* Marked two path branch */
+EVENT(PM_BR_MRK_2PATH,				0x10138)
+/* Alternate event code for PM_BR_MRK_2PATH */
+EVENT(PM_BR_MRK_2PATH_ALT,			0x40138)
+/* L3 castouts in Mepf state */
+EVENT(PM_L3_CO_MEPF,				0x18082)
+/* Alternate event code for PM_L3_CO_MEPF */
+EVENT(PM_L3_CO_MEPF_ALT,			0x3e05e)
+/* Data cache was reloaded from a location other than L2 due to a marked load */
+EVENT(PM_MRK_DATA_FROM_L2MISS,			0x1d14e)
+/* Alternate event code for PM_MRK_DATA_FROM_L2MISS */
+EVENT(PM_MRK_DATA_FROM_L2MISS_ALT,		0x401e8)
+/* Alternate event code for  PM_CMPLU_STALL */
+EVENT(PM_CMPLU_STALL_ALT,			0x1e054)
+/* Two path branch */
+EVENT(PM_BR_2PATH,				0x20036)
+/* Alternate event code for PM_BR_2PATH */
+EVENT(PM_BR_2PATH_ALT,				0x40036)
+/* # PPC Dispatched */
+EVENT(PM_INST_DISP,				0x200f2)
+/* Alternate event code for PM_INST_DISP */
+EVENT(PM_INST_DISP_ALT,				0x300f2)
+/* Marked filter Match */
+EVENT(PM_MRK_FILT_MATCH,			0x2013c)
+/* Alternate event code for PM_MRK_FILT_MATCH */
+EVENT(PM_MRK_FILT_MATCH_ALT,			0x3012e)
+/* Alternate event code for PM_LD_MISS_L1 */
+EVENT(PM_LD_MISS_L1_ALT,			0x400f0)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/perf/power8-pmu.c linux-libre-4.7-gnu/arch/powerpc/perf/power8-pmu.c
--- linux-libre-4.6-gnu/arch/powerpc/perf/power8-pmu.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/perf/power8-pmu.c	2016-07-24 15:23:50.000000000 -0400
@@ -274,7 +274,8 @@ static int power8_get_constraint(u64 eve
 		/* Ignore Linux defined bits when checking event below */
 		base_event = event & ~EVENT_LINUX_MASK;
 
-		if (pmc >= 5 && base_event != 0x500fa && base_event != 0x600f4)
+		if (pmc >= 5 && base_event != PM_RUN_INST_CMPL &&
+				base_event != PM_RUN_CYC)
 			return -1;
 
 		mask  |= CNST_PMC_MASK(pmc);
@@ -488,17 +489,17 @@ static int power8_compute_mmcr(u64 event
 
 /* Table of alternatives, sorted by column 0 */
 static const unsigned int event_alternatives[][MAX_ALT] = {
-	{ 0x10134, 0x301e2 },		/* PM_MRK_ST_CMPL */
-	{ 0x10138, 0x40138 },		/* PM_BR_MRK_2PATH */
-	{ 0x18082, 0x3e05e },		/* PM_L3_CO_MEPF */
-	{ 0x1d14e, 0x401e8 },		/* PM_MRK_DATA_FROM_L2MISS */
-	{ 0x1e054, 0x4000a },		/* PM_CMPLU_STALL */
-	{ 0x20036, 0x40036 },		/* PM_BR_2PATH */
-	{ 0x200f2, 0x300f2 },		/* PM_INST_DISP */
-	{ 0x200f4, 0x600f4 },		/* PM_RUN_CYC */
-	{ 0x2013c, 0x3012e },		/* PM_MRK_FILT_MATCH */
-	{ 0x3e054, 0x400f0 },		/* PM_LD_MISS_L1 */
-	{ 0x400fa, 0x500fa },		/* PM_RUN_INST_CMPL */
+	{ PM_MRK_ST_CMPL,		PM_MRK_ST_CMPL_ALT },
+	{ PM_BR_MRK_2PATH,		PM_BR_MRK_2PATH_ALT },
+	{ PM_L3_CO_MEPF,		PM_L3_CO_MEPF_ALT },
+	{ PM_MRK_DATA_FROM_L2MISS,	PM_MRK_DATA_FROM_L2MISS_ALT },
+	{ PM_CMPLU_STALL_ALT,		PM_CMPLU_STALL },
+	{ PM_BR_2PATH,			PM_BR_2PATH_ALT },
+	{ PM_INST_DISP,			PM_INST_DISP_ALT },
+	{ PM_RUN_CYC_ALT,		PM_RUN_CYC },
+	{ PM_MRK_FILT_MATCH,		PM_MRK_FILT_MATCH_ALT },
+	{ PM_LD_MISS_L1,		PM_LD_MISS_L1_ALT },
+	{ PM_RUN_INST_CMPL_ALT,		PM_RUN_INST_CMPL },
 };
 
 /*
@@ -546,17 +547,17 @@ static int power8_get_alternatives(u64 e
 		j = num_alt;
 		for (i = 0; i < num_alt; ++i) {
 			switch (alt[i]) {
-			case 0x1e:	/* PM_CYC */
-				alt[j++] = 0x600f4;	/* PM_RUN_CYC */
+			case PM_CYC:
+				alt[j++] = PM_RUN_CYC;
 				break;
-			case 0x600f4:	/* PM_RUN_CYC */
-				alt[j++] = 0x1e;
+			case PM_RUN_CYC:
+				alt[j++] = PM_CYC;
 				break;
-			case 0x2:	/* PM_PPC_CMPL */
-				alt[j++] = 0x500fa;	/* PM_RUN_INST_CMPL */
+			case PM_INST_CMPL:
+				alt[j++] = PM_RUN_INST_CMPL;
 				break;
-			case 0x500fa:	/* PM_RUN_INST_CMPL */
-				alt[j++] = 0x2;	/* PM_PPC_CMPL */
+			case PM_RUN_INST_CMPL:
+				alt[j++] = PM_INST_CMPL;
 				break;
 			}
 		}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/platforms/512x/clock-commonclk.c linux-libre-4.7-gnu/arch/powerpc/platforms/512x/clock-commonclk.c
--- linux-libre-4.6-gnu/arch/powerpc/platforms/512x/clock-commonclk.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/platforms/512x/clock-commonclk.c	2016-07-24 15:23:50.000000000 -0400
@@ -221,7 +221,7 @@ static bool soc_has_mclk_mux0_canin(void
 /* convenience wrappers around the common clk API */
 static inline struct clk *mpc512x_clk_fixed(const char *name, int rate)
 {
-	return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate);
+	return clk_register_fixed_rate(NULL, name, NULL, 0, rate);
 }
 
 static inline struct clk *mpc512x_clk_factor(
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/platforms/52xx/mpc52xx_gpt.c linux-libre-4.7-gnu/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
--- linux-libre-4.6-gnu/arch/powerpc/platforms/52xx/mpc52xx_gpt.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/platforms/52xx/mpc52xx_gpt.c	2016-07-24 15:23:50.000000000 -0400
@@ -278,14 +278,9 @@ mpc52xx_gpt_irq_setup(struct mpc52xx_gpt
  * GPIOLIB hooks
  */
 #if defined(CONFIG_GPIOLIB)
-static inline struct mpc52xx_gpt_priv *gc_to_mpc52xx_gpt(struct gpio_chip *gc)
-{
-	return container_of(gc, struct mpc52xx_gpt_priv, gc);
-}
-
 static int mpc52xx_gpt_gpio_get(struct gpio_chip *gc, unsigned int gpio)
 {
-	struct mpc52xx_gpt_priv *gpt = gc_to_mpc52xx_gpt(gc);
+	struct mpc52xx_gpt_priv *gpt = gpiochip_get_data(gc);
 
 	return (in_be32(&gpt->regs->status) >> 8) & 1;
 }
@@ -293,7 +288,7 @@ static int mpc52xx_gpt_gpio_get(struct g
 static void
 mpc52xx_gpt_gpio_set(struct gpio_chip *gc, unsigned int gpio, int v)
 {
-	struct mpc52xx_gpt_priv *gpt = gc_to_mpc52xx_gpt(gc);
+	struct mpc52xx_gpt_priv *gpt = gpiochip_get_data(gc);
 	unsigned long flags;
 	u32 r;
 
@@ -307,7 +302,7 @@ mpc52xx_gpt_gpio_set(struct gpio_chip *g
 
 static int mpc52xx_gpt_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
 {
-	struct mpc52xx_gpt_priv *gpt = gc_to_mpc52xx_gpt(gc);
+	struct mpc52xx_gpt_priv *gpt = gpiochip_get_data(gc);
 	unsigned long flags;
 
 	dev_dbg(gpt->dev, "%s: gpio:%d\n", __func__, gpio);
@@ -354,9 +349,9 @@ mpc52xx_gpt_gpio_setup(struct mpc52xx_gp
 	clrsetbits_be32(&gpt->regs->mode, MPC52xx_GPT_MODE_MS_MASK,
 			MPC52xx_GPT_MODE_MS_GPIO);
 
-	rc = gpiochip_add(&gpt->gc);
+	rc = gpiochip_add_data(&gpt->gc, gpt);
 	if (rc)
-		dev_err(gpt->dev, "gpiochip_add() failed; rc=%i\n", rc);
+		dev_err(gpt->dev, "gpiochip_add_data() failed; rc=%i\n", rc);
 
 	dev_dbg(gpt->dev, "%s() complete.\n", __func__);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c linux-libre-4.7-gnu/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c
--- linux-libre-4.6-gnu/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c	2016-07-24 15:23:50.000000000 -0400
@@ -16,7 +16,7 @@
 #include <linux/device.h>
 #include <linux/mutex.h>
 #include <linux/i2c.h>
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
 #include <linux/slab.h>
@@ -99,7 +99,7 @@ static void mcu_power_off(void)
 
 static void mcu_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
 {
-	struct mcu *mcu = container_of(gc, struct mcu, gc);
+	struct mcu *mcu = gpiochip_get_data(gc);
 	u8 bit = 1 << (4 + gpio);
 
 	mutex_lock(&mcu->lock);
@@ -136,7 +136,7 @@ static int mcu_gpiochip_add(struct mcu *
 	gc->direction_output = mcu_gpio_dir_out;
 	gc->of_node = np;
 
-	return gpiochip_add(gc);
+	return gpiochip_add_data(gc, mcu);
 }
 
 static int mcu_gpiochip_remove(struct mcu *mcu)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/platforms/cell/spu_base.c linux-libre-4.7-gnu/arch/powerpc/platforms/cell/spu_base.c
--- linux-libre-4.6-gnu/arch/powerpc/platforms/cell/spu_base.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/platforms/cell/spu_base.c	2016-07-24 15:23:50.000000000 -0400
@@ -24,7 +24,7 @@
 
 #include <linux/interrupt.h>
 #include <linux/list.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
 #include <linux/wait.h>
@@ -197,7 +197,7 @@ static int __spu_trap_data_map(struct sp
 	    (REGION_ID(ea) != USER_REGION_ID)) {
 
 		spin_unlock(&spu->register_lock);
-		ret = hash_page(ea, _PAGE_PRESENT, 0x300, dsisr);
+		ret = hash_page(ea, _PAGE_PRESENT | _PAGE_READ, 0x300, dsisr);
 		spin_lock(&spu->register_lock);
 
 		if (!ret) {
@@ -805,7 +805,4 @@ static int __init init_spu_base(void)
  out:
 	return ret;
 }
-module_init(init_spu_base);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Arnd Bergmann <arndb@de.ibm.com>");
+device_initcall(init_spu_base);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/platforms/cell/spufs/coredump.c linux-libre-4.7-gnu/arch/powerpc/platforms/cell/spufs/coredump.c
--- linux-libre-4.6-gnu/arch/powerpc/platforms/cell/spufs/coredump.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/platforms/cell/spufs/coredump.c	2016-07-24 15:23:50.000000000 -0400
@@ -137,6 +137,7 @@ static int spufs_arch_write_note(struct
 	char *name;
 	char fullname[80], *buf;
 	struct elf_note en;
+	size_t skip;
 
 	buf = (void *)get_zeroed_page(GFP_KERNEL);
 	if (!buf)
@@ -171,8 +172,8 @@ static int spufs_arch_write_note(struct
 	if (rc < 0)
 		goto out;
 
-	if (!dump_skip(cprm,
-		       roundup(cprm->written - total + sz, 4) - cprm->written))
+	skip = roundup(cprm->pos - total + sz, 4) - cprm->pos;
+	if (!dump_skip(cprm, skip))
 		goto Eio;
 out:
 	free_page((unsigned long)buf);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/platforms/cell/spufs/fault.c linux-libre-4.7-gnu/arch/powerpc/platforms/cell/spufs/fault.c
--- linux-libre-4.6-gnu/arch/powerpc/platforms/cell/spufs/fault.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/platforms/cell/spufs/fault.c	2016-07-24 15:23:50.000000000 -0400
@@ -141,8 +141,8 @@ int spufs_handle_class1(struct spu_conte
 	/* we must not hold the lock when entering copro_handle_mm_fault */
 	spu_release(ctx);
 
-	access = (_PAGE_PRESENT | _PAGE_USER);
-	access |= (dsisr & MFC_DSISR_ACCESS_PUT) ? _PAGE_RW : 0UL;
+	access = (_PAGE_PRESENT | _PAGE_READ);
+	access |= (dsisr & MFC_DSISR_ACCESS_PUT) ? _PAGE_WRITE : 0UL;
 	local_irq_save(flags);
 	ret = hash_page(ea, access, 0x300, dsisr);
 	local_irq_restore(flags);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/platforms/cell/spufs/inode.c linux-libre-4.7-gnu/arch/powerpc/platforms/cell/spufs/inode.c
--- linux-libre-4.6-gnu/arch/powerpc/platforms/cell/spufs/inode.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/platforms/cell/spufs/inode.c	2016-07-24 15:23:50.000000000 -0400
@@ -238,7 +238,7 @@ const struct file_operations spufs_conte
 	.release	= spufs_dir_close,
 	.llseek		= dcache_dir_lseek,
 	.read		= generic_read_dir,
-	.iterate	= dcache_readdir,
+	.iterate_shared	= dcache_readdir,
 	.fsync		= noop_fsync,
 };
 EXPORT_SYMBOL_GPL(spufs_context_fops);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/platforms/Kconfig.cputype linux-libre-4.7-gnu/arch/powerpc/platforms/Kconfig.cputype
--- linux-libre-4.6-gnu/arch/powerpc/platforms/Kconfig.cputype	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/platforms/Kconfig.cputype	2016-07-24 15:23:50.000000000 -0400
@@ -72,7 +72,7 @@ config PPC_BOOK3S_64
 	select PPC_FPU
 	select PPC_HAVE_PMU_SUPPORT
 	select SYS_SUPPORTS_HUGETLBFS
-	select HAVE_ARCH_TRANSPARENT_HUGEPAGE if PPC_64K_PAGES
+	select HAVE_ARCH_TRANSPARENT_HUGEPAGE
 	select ARCH_SUPPORTS_NUMA_BALANCING
 	select IRQ_WORK
 
@@ -331,6 +331,15 @@ config PPC_STD_MMU_64
 	def_bool y
 	depends on PPC_STD_MMU && PPC64
 
+config PPC_RADIX_MMU
+	bool "Radix MMU Support"
+	depends on PPC_BOOK3S_64
+	default y
+	help
+	  Enable support for the Power ISA 3.0 Radix style MMU. Currently this
+	  is only implemented by IBM Power9 CPUs, if you don't have one of them
+	  you can probably disable this.
+
 config PPC_MMU_NOHASH
 	def_bool y
 	depends on !PPC_STD_MMU
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/platforms/powernv/eeh-powernv.c linux-libre-4.7-gnu/arch/powerpc/platforms/powernv/eeh-powernv.c
--- linux-libre-4.6-gnu/arch/powerpc/platforms/powernv/eeh-powernv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/platforms/powernv/eeh-powernv.c	2016-07-24 15:23:50.000000000 -0400
@@ -75,7 +75,7 @@ static int pnv_eeh_init(void)
 		 * and P7IOC separately. So we should regard
 		 * PE#0 as valid for PHB3 and P7IOC.
 		 */
-		if (phb->ioda.reserved_pe != 0)
+		if (phb->ioda.reserved_pe_idx != 0)
 			eeh_add_flag(EEH_VALID_PE_ZERO);
 
 		break;
@@ -1009,8 +1009,9 @@ static int pnv_eeh_reset_vf_pe(struct ee
 static int pnv_eeh_reset(struct eeh_pe *pe, int option)
 {
 	struct pci_controller *hose = pe->phb;
+	struct pnv_phb *phb;
 	struct pci_bus *bus;
-	int ret;
+	int64_t rc;
 
 	/*
 	 * For PHB reset, we always have complete reset. For those PEs whose
@@ -1026,45 +1027,39 @@ static int pnv_eeh_reset(struct eeh_pe *
 	 * reset. The side effect is that EEH core has to clear the frozen
 	 * state explicitly after BAR restore.
 	 */
-	if (pe->type & EEH_PE_PHB) {
-		ret = pnv_eeh_phb_reset(hose, option);
-	} else {
-		struct pnv_phb *phb;
-		s64 rc;
+	if (pe->type & EEH_PE_PHB)
+		return pnv_eeh_phb_reset(hose, option);
 
-		/*
-		 * The frozen PE might be caused by PAPR error injection
-		 * registers, which are expected to be cleared after hitting
-		 * frozen PE as stated in the hardware spec. Unfortunately,
-		 * that's not true on P7IOC. So we have to clear it manually
-		 * to avoid recursive EEH errors during recovery.
-		 */
-		phb = hose->private_data;
-		if (phb->model == PNV_PHB_MODEL_P7IOC &&
-		    (option == EEH_RESET_HOT ||
-		    option == EEH_RESET_FUNDAMENTAL)) {
-			rc = opal_pci_reset(phb->opal_id,
-					    OPAL_RESET_PHB_ERROR,
-					    OPAL_ASSERT_RESET);
-			if (rc != OPAL_SUCCESS) {
-				pr_warn("%s: Failure %lld clearing "
-					"error injection registers\n",
-					__func__, rc);
-				return -EIO;
-			}
+	/*
+	 * The frozen PE might be caused by PAPR error injection
+	 * registers, which are expected to be cleared after hitting
+	 * frozen PE as stated in the hardware spec. Unfortunately,
+	 * that's not true on P7IOC. So we have to clear it manually
+	 * to avoid recursive EEH errors during recovery.
+	 */
+	phb = hose->private_data;
+	if (phb->model == PNV_PHB_MODEL_P7IOC &&
+	    (option == EEH_RESET_HOT ||
+	     option == EEH_RESET_FUNDAMENTAL)) {
+		rc = opal_pci_reset(phb->opal_id,
+				    OPAL_RESET_PHB_ERROR,
+				    OPAL_ASSERT_RESET);
+		if (rc != OPAL_SUCCESS) {
+			pr_warn("%s: Failure %lld clearing error injection registers\n",
+				__func__, rc);
+			return -EIO;
 		}
-
-		bus = eeh_pe_bus_get(pe);
-		if (pe->type & EEH_PE_VF)
-			ret = pnv_eeh_reset_vf_pe(pe, option);
-		else if (pci_is_root_bus(bus) ||
-			pci_is_root_bus(bus->parent))
-			ret = pnv_eeh_root_reset(hose, option);
-		else
-			ret = pnv_eeh_bridge_reset(bus->self, option);
 	}
 
-	return ret;
+	bus = eeh_pe_bus_get(pe);
+	if (pe->type & EEH_PE_VF)
+		return pnv_eeh_reset_vf_pe(pe, option);
+
+	if (pci_is_root_bus(bus) ||
+	    pci_is_root_bus(bus->parent))
+		return pnv_eeh_root_reset(hose, option);
+
+	return pnv_eeh_bridge_reset(bus->self, option);
 }
 
 /**
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/platforms/powernv/npu-dma.c linux-libre-4.7-gnu/arch/powerpc/platforms/powernv/npu-dma.c
--- linux-libre-4.6-gnu/arch/powerpc/platforms/powernv/npu-dma.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/platforms/powernv/npu-dma.c	2016-07-24 15:23:50.000000000 -0400
@@ -12,6 +12,7 @@
 #include <linux/export.h>
 #include <linux/pci.h>
 #include <linux/memblock.h>
+#include <linux/iommu.h>
 
 #include <asm/iommu.h>
 #include <asm/pnv-pci.h>
@@ -25,8 +26,6 @@
  * Other types of TCE cache invalidation are not functional in the
  * hardware.
  */
-#define TCE_KILL_INVAL_ALL PPC_BIT(0)
-
 static struct pci_dev *get_pci_dev(struct device_node *dn)
 {
 	return PCI_DN(dn)->pcidev;
@@ -138,22 +137,17 @@ static struct pnv_ioda_pe *get_gpu_pci_d
 	struct pnv_ioda_pe *pe;
 	struct pci_dn *pdn;
 
-	if (npe->flags & PNV_IODA_PE_PEER) {
-		pe = npe->peers[0];
-		pdev = pe->pdev;
-	} else {
-		pdev = pnv_pci_get_gpu_dev(npe->pdev);
-		if (!pdev)
-			return NULL;
+	pdev = pnv_pci_get_gpu_dev(npe->pdev);
+	if (!pdev)
+		return NULL;
 
-		pdn = pci_get_pdn(pdev);
-		if (WARN_ON(!pdn || pdn->pe_number == IODA_INVALID_PE))
-			return NULL;
+	pdn = pci_get_pdn(pdev);
+	if (WARN_ON(!pdn || pdn->pe_number == IODA_INVALID_PE))
+		return NULL;
 
-		hose = pci_bus_to_host(pdev->bus);
-		phb = hose->private_data;
-		pe = &phb->ioda.pe_array[pdn->pe_number];
-	}
+	hose = pci_bus_to_host(pdev->bus);
+	phb = hose->private_data;
+	pe = &phb->ioda.pe_array[pdn->pe_number];
 
 	if (gpdev)
 		*gpdev = pdev;
@@ -161,92 +155,70 @@ static struct pnv_ioda_pe *get_gpu_pci_d
 	return pe;
 }
 
-void pnv_npu_tce_invalidate_entire(struct pnv_ioda_pe *npe)
+long pnv_npu_set_window(struct pnv_ioda_pe *npe, int num,
+		struct iommu_table *tbl)
 {
 	struct pnv_phb *phb = npe->phb;
+	int64_t rc;
+	const unsigned long size = tbl->it_indirect_levels ?
+		tbl->it_level_size : tbl->it_size;
+	const __u64 start_addr = tbl->it_offset << tbl->it_page_shift;
+	const __u64 win_size = tbl->it_size << tbl->it_page_shift;
 
-	if (WARN_ON(phb->type != PNV_PHB_NPU ||
-		    !phb->ioda.tce_inval_reg ||
-		    !(npe->flags & PNV_IODA_PE_DEV)))
-		return;
-
-	mb(); /* Ensure previous TCE table stores are visible */
-	__raw_writeq(cpu_to_be64(TCE_KILL_INVAL_ALL),
-		phb->ioda.tce_inval_reg);
-}
-
-void pnv_npu_tce_invalidate(struct pnv_ioda_pe *npe,
-				struct iommu_table *tbl,
-				unsigned long index,
-				unsigned long npages,
-				bool rm)
-{
-	struct pnv_phb *phb = npe->phb;
+	pe_info(npe, "Setting up window %llx..%llx pg=%lx\n",
+			start_addr, start_addr + win_size - 1,
+			IOMMU_PAGE_SIZE(tbl));
 
-	/* We can only invalidate the whole cache on NPU */
-	unsigned long val = TCE_KILL_INVAL_ALL;
+	rc = opal_pci_map_pe_dma_window(phb->opal_id,
+			npe->pe_number,
+			npe->pe_number,
+			tbl->it_indirect_levels + 1,
+			__pa(tbl->it_base),
+			size << 3,
+			IOMMU_PAGE_SIZE(tbl));
+	if (rc) {
+		pe_err(npe, "Failed to configure TCE table, err %lld\n", rc);
+		return rc;
+	}
+	pnv_pci_ioda2_tce_invalidate_entire(phb, false);
 
-	if (WARN_ON(phb->type != PNV_PHB_NPU ||
-		    !phb->ioda.tce_inval_reg ||
-		    !(npe->flags & PNV_IODA_PE_DEV)))
-		return;
+	/* Add the table to the list so its TCE cache will get invalidated */
+	pnv_pci_link_table_and_group(phb->hose->node, num,
+			tbl, &npe->table_group);
 
-	mb(); /* Ensure previous TCE table stores are visible */
-	if (rm)
-		__raw_rm_writeq(cpu_to_be64(val),
-		  (__be64 __iomem *) phb->ioda.tce_inval_reg_phys);
-	else
-		__raw_writeq(cpu_to_be64(val),
-			phb->ioda.tce_inval_reg);
+	return 0;
 }
 
-void pnv_npu_init_dma_pe(struct pnv_ioda_pe *npe)
+long pnv_npu_unset_window(struct pnv_ioda_pe *npe, int num)
 {
-	struct pnv_ioda_pe *gpe;
-	struct pci_dev *gpdev;
-	int i, avail = -1;
-
-	if (!npe->pdev || !(npe->flags & PNV_IODA_PE_DEV))
-		return;
-
-	gpe = get_gpu_pci_dev_and_pe(npe, &gpdev);
-	if (!gpe)
-		return;
+	struct pnv_phb *phb = npe->phb;
+	int64_t rc;
 
-	for (i = 0; i < PNV_IODA_MAX_PEER_PES; i++) {
-		/* Nothing to do if the PE is already connected. */
-		if (gpe->peers[i] == npe)
-			return;
+	pe_info(npe, "Removing DMA window\n");
 
-		if (!gpe->peers[i])
-			avail = i;
+	rc = opal_pci_map_pe_dma_window(phb->opal_id, npe->pe_number,
+			npe->pe_number,
+			0/* levels */, 0/* table address */,
+			0/* table size */, 0/* page size */);
+	if (rc) {
+		pe_err(npe, "Unmapping failed, ret = %lld\n", rc);
+		return rc;
 	}
+	pnv_pci_ioda2_tce_invalidate_entire(phb, false);
 
-	if (WARN_ON(avail < 0))
-		return;
-
-	gpe->peers[avail] = npe;
-	gpe->flags |= PNV_IODA_PE_PEER;
+	pnv_pci_unlink_table_and_group(npe->table_group.tables[num],
+			&npe->table_group);
 
-	/*
-	 * We assume that the NPU devices only have a single peer PE
-	 * (the GPU PCIe device PE).
-	 */
-	npe->peers[0] = gpe;
-	npe->flags |= PNV_IODA_PE_PEER;
+	return 0;
 }
 
 /*
- * For the NPU we want to point the TCE table at the same table as the
- * real PCI device.
+ * Enables 32 bit DMA on NPU.
  */
-static void pnv_npu_disable_bypass(struct pnv_ioda_pe *npe)
+static void pnv_npu_dma_set_32(struct pnv_ioda_pe *npe)
 {
-	struct pnv_phb *phb = npe->phb;
 	struct pci_dev *gpdev;
 	struct pnv_ioda_pe *gpe;
-	void *addr;
-	unsigned int size;
 	int64_t rc;
 
 	/*
@@ -260,14 +232,7 @@ static void pnv_npu_disable_bypass(struc
 	if (!gpe)
 		return;
 
-	addr = (void *)gpe->table_group.tables[0]->it_base;
-	size = gpe->table_group.tables[0]->it_size << 3;
-	rc = opal_pci_map_pe_dma_window(phb->opal_id, npe->pe_number,
-					npe->pe_number, 1, __pa(addr),
-					size, 0x1000);
-	if (rc != OPAL_SUCCESS)
-		pr_warn("%s: Error %lld setting DMA window on PHB#%d-PE#%d\n",
-			__func__, rc, phb->hose->global_number, npe->pe_number);
+	rc = pnv_npu_set_window(npe, 0, gpe->table_group.tables[0]);
 
 	/*
 	 * We don't initialise npu_pe->tce32_table as we always use
@@ -277,72 +242,120 @@ static void pnv_npu_disable_bypass(struc
 }
 
 /*
- * Enable/disable bypass mode on the NPU. The NPU only supports one
+ * Enables bypass mode on the NPU. The NPU only supports one
  * window per link, so bypass needs to be explicitly enabled or
  * disabled. Unlike for a PHB3 bypass and non-bypass modes can't be
  * active at the same time.
  */
-int pnv_npu_dma_set_bypass(struct pnv_ioda_pe *npe, bool enable)
+static int pnv_npu_dma_set_bypass(struct pnv_ioda_pe *npe)
 {
 	struct pnv_phb *phb = npe->phb;
 	int64_t rc = 0;
+	phys_addr_t top = memblock_end_of_DRAM();
 
 	if (phb->type != PNV_PHB_NPU || !npe->pdev)
 		return -EINVAL;
 
-	if (enable) {
-		/* Enable the bypass window */
-		phys_addr_t top = memblock_end_of_DRAM();
+	rc = pnv_npu_unset_window(npe, 0);
+	if (rc != OPAL_SUCCESS)
+		return rc;
 
-		npe->tce_bypass_base = 0;
-		top = roundup_pow_of_two(top);
-		dev_info(&npe->pdev->dev, "Enabling bypass for PE %d\n",
-			 npe->pe_number);
-		rc = opal_pci_map_pe_dma_window_real(phb->opal_id,
-					npe->pe_number, npe->pe_number,
-					npe->tce_bypass_base, top);
-	} else {
-		/*
-		 * Disable the bypass window by replacing it with the
-		 * TCE32 window.
-		 */
-		pnv_npu_disable_bypass(npe);
-	}
+	/* Enable the bypass window */
+
+	top = roundup_pow_of_two(top);
+	dev_info(&npe->pdev->dev, "Enabling bypass for PE %d\n",
+			npe->pe_number);
+	rc = opal_pci_map_pe_dma_window_real(phb->opal_id,
+			npe->pe_number, npe->pe_number,
+			0 /* bypass base */, top);
+
+	if (rc == OPAL_SUCCESS)
+		pnv_pci_ioda2_tce_invalidate_entire(phb, false);
 
 	return rc;
 }
 
-int pnv_npu_dma_set_mask(struct pci_dev *npdev, u64 dma_mask)
+void pnv_npu_try_dma_set_bypass(struct pci_dev *gpdev, bool bypass)
 {
-	struct pci_controller *hose = pci_bus_to_host(npdev->bus);
-	struct pnv_phb *phb = hose->private_data;
-	struct pci_dn *pdn = pci_get_pdn(npdev);
-	struct pnv_ioda_pe *npe, *gpe;
-	struct pci_dev *gpdev;
-	uint64_t top;
-	bool bypass = false;
+	int i;
+	struct pnv_phb *phb;
+	struct pci_dn *pdn;
+	struct pnv_ioda_pe *npe;
+	struct pci_dev *npdev;
 
-	if (WARN_ON(!pdn || pdn->pe_number == IODA_INVALID_PE))
-		return -ENXIO;
+	for (i = 0; ; ++i) {
+		npdev = pnv_pci_get_npu_dev(gpdev, i);
 
-	/* We only do bypass if it's enabled on the linked device */
-	npe = &phb->ioda.pe_array[pdn->pe_number];
-	gpe = get_gpu_pci_dev_and_pe(npe, &gpdev);
-	if (!gpe)
-		return -ENODEV;
+		if (!npdev)
+			break;
 
-	if (gpe->tce_bypass_enabled) {
-		top = gpe->tce_bypass_base + memblock_end_of_DRAM() - 1;
-		bypass = (dma_mask >= top);
+		pdn = pci_get_pdn(npdev);
+		if (WARN_ON(!pdn || pdn->pe_number == IODA_INVALID_PE))
+			return;
+
+		phb = pci_bus_to_host(npdev->bus)->private_data;
+
+		/* We only do bypass if it's enabled on the linked device */
+		npe = &phb->ioda.pe_array[pdn->pe_number];
+
+		if (bypass) {
+			dev_info(&npdev->dev,
+					"Using 64-bit DMA iommu bypass\n");
+			pnv_npu_dma_set_bypass(npe);
+		} else {
+			dev_info(&npdev->dev, "Using 32-bit DMA via iommu\n");
+			pnv_npu_dma_set_32(npe);
+		}
 	}
+}
 
-	if (bypass)
-		dev_info(&npdev->dev, "Using 64-bit DMA iommu bypass\n");
-	else
-		dev_info(&npdev->dev, "Using 32-bit DMA via iommu\n");
+/* Switch ownership from platform code to external user (e.g. VFIO) */
+void pnv_npu_take_ownership(struct pnv_ioda_pe *npe)
+{
+	struct pnv_phb *phb = npe->phb;
+	int64_t rc;
 
-	pnv_npu_dma_set_bypass(npe, bypass);
-	*npdev->dev.dma_mask = dma_mask;
+	/*
+	 * Note: NPU has just a single TVE in the hardware which means that
+	 * while used by the kernel, it can have either 32bit window or
+	 * DMA bypass but never both. So we deconfigure 32bit window only
+	 * if it was enabled at the moment of ownership change.
+	 */
+	if (npe->table_group.tables[0]) {
+		pnv_npu_unset_window(npe, 0);
+		return;
+	}
 
-	return 0;
+	/* Disable bypass */
+	rc = opal_pci_map_pe_dma_window_real(phb->opal_id,
+			npe->pe_number, npe->pe_number,
+			0 /* bypass base */, 0);
+	if (rc) {
+		pe_err(npe, "Failed to disable bypass, err %lld\n", rc);
+		return;
+	}
+	pnv_pci_ioda2_tce_invalidate_entire(npe->phb, false);
+}
+
+struct pnv_ioda_pe *pnv_pci_npu_setup_iommu(struct pnv_ioda_pe *npe)
+{
+	struct pnv_phb *phb = npe->phb;
+	struct pci_bus *pbus = phb->hose->bus;
+	struct pci_dev *npdev, *gpdev = NULL, *gptmp;
+	struct pnv_ioda_pe *gpe = get_gpu_pci_dev_and_pe(npe, &gpdev);
+
+	if (!gpe || !gpdev)
+		return NULL;
+
+	list_for_each_entry(npdev, &pbus->devices, bus_list) {
+		gptmp = pnv_pci_get_gpu_dev(npdev);
+
+		if (gptmp != gpdev)
+			continue;
+
+		pe_info(gpe, "Attached NPU %s\n", dev_name(&npdev->dev));
+		iommu_group_add_device(gpe->table_group.group, &npdev->dev);
+	}
+
+	return gpe;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/platforms/powernv/opal-hmi.c linux-libre-4.7-gnu/arch/powerpc/platforms/powernv/opal-hmi.c
--- linux-libre-4.6-gnu/arch/powerpc/platforms/powernv/opal-hmi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/platforms/powernv/opal-hmi.c	2016-07-24 15:23:50.000000000 -0400
@@ -150,15 +150,17 @@ static void print_nx_checkstop_reason(co
 static void print_checkstop_reason(const char *level,
 					struct OpalHMIEvent *hmi_evt)
 {
-	switch (hmi_evt->u.xstop_error.xstop_type) {
+	uint8_t type = hmi_evt->u.xstop_error.xstop_type;
+	switch (type) {
 	case CHECKSTOP_TYPE_CORE:
 		print_core_checkstop_reason(level, hmi_evt);
 		break;
 	case CHECKSTOP_TYPE_NX:
 		print_nx_checkstop_reason(level, hmi_evt);
 		break;
-	case CHECKSTOP_TYPE_UNKNOWN:
-		printk("%s	Unknown Malfunction Alert.\n", level);
+	default:
+		printk("%s	Unknown Malfunction Alert of type %d\n",
+		       level, type);
 		break;
 	}
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/platforms/powernv/pci.c linux-libre-4.7-gnu/arch/powerpc/platforms/powernv/pci.c
--- linux-libre-4.6-gnu/arch/powerpc/platforms/powernv/pci.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/platforms/powernv/pci.c	2016-07-24 15:23:50.000000000 -0400
@@ -39,9 +39,6 @@
 /* Delay in usec */
 #define PCI_RESET_DELAY_US	3000000
 
-#define cfg_dbg(fmt...)	do { } while(0)
-//#define cfg_dbg(fmt...)	printk(fmt)
-
 #ifdef CONFIG_PCI_MSI
 int pnv_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
 {
@@ -370,7 +367,7 @@ static void pnv_pci_config_check_eeh(str
 	struct pnv_phb *phb = pdn->phb->private_data;
 	u8	fstate;
 	__be16	pcierr;
-	int	pe_no;
+	unsigned int pe_no;
 	s64	rc;
 
 	/*
@@ -380,7 +377,7 @@ static void pnv_pci_config_check_eeh(str
 	 */
 	pe_no = pdn->pe_number;
 	if (pe_no == IODA_INVALID_PE) {
-		pe_no = phb->ioda.reserved_pe;
+		pe_no = phb->ioda.reserved_pe_idx;
 	}
 
 	/*
@@ -402,8 +399,8 @@ static void pnv_pci_config_check_eeh(str
 		}
 	}
 
-	cfg_dbg(" -> EEH check, bdfn=%04x PE#%d fstate=%x\n",
-		(pdn->busno << 8) | (pdn->devfn), pe_no, fstate);
+	pr_devel(" -> EEH check, bdfn=%04x PE#%d fstate=%x\n",
+		 (pdn->busno << 8) | (pdn->devfn), pe_no, fstate);
 
 	/* Clear the frozen state if applicable */
 	if (fstate == OPAL_EEH_STOPPED_MMIO_FREEZE ||
@@ -451,8 +448,8 @@ int pnv_pci_cfg_read(struct pci_dn *pdn,
 		return PCIBIOS_FUNC_NOT_SUPPORTED;
 	}
 
-	cfg_dbg("%s: bus: %x devfn: %x +%x/%x -> %08x\n",
-		__func__, pdn->busno, pdn->devfn, where, size, *val);
+	pr_devel("%s: bus: %x devfn: %x +%x/%x -> %08x\n",
+		 __func__, pdn->busno, pdn->devfn, where, size, *val);
 	return PCIBIOS_SUCCESSFUL;
 }
 
@@ -462,8 +459,8 @@ int pnv_pci_cfg_write(struct pci_dn *pdn
 	struct pnv_phb *phb = pdn->phb->private_data;
 	u32 bdfn = (pdn->busno << 8) | pdn->devfn;
 
-	cfg_dbg("%s: bus: %x devfn: %x +%x/%x -> %08x\n",
-		pdn->busno, pdn->devfn, where, size, val);
+	pr_devel("%s: bus: %x devfn: %x +%x/%x -> %08x\n",
+		 __func__, pdn->busno, pdn->devfn, where, size, val);
 	switch (size) {
 	case 1:
 		opal_pci_config_write_byte(phb->opal_id, bdfn, where, val);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/platforms/powernv/pci.h linux-libre-4.7-gnu/arch/powerpc/platforms/powernv/pci.h
--- linux-libre-4.6-gnu/arch/powerpc/platforms/powernv/pci.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/platforms/powernv/pci.h	2016-07-24 15:23:50.000000000 -0400
@@ -24,7 +24,6 @@ enum pnv_phb_model {
 #define PNV_IODA_PE_MASTER	(1 << 3)	/* Master PE in compound case	*/
 #define PNV_IODA_PE_SLAVE	(1 << 4)	/* Slave PE in compound case	*/
 #define PNV_IODA_PE_VF		(1 << 5)	/* PE for one VF 		*/
-#define PNV_IODA_PE_PEER	(1 << 6)	/* PE has peers			*/
 
 /* Data associated with a PE, including IOMMU tracking etc.. */
 struct pnv_phb;
@@ -32,9 +31,6 @@ struct pnv_ioda_pe {
 	unsigned long		flags;
 	struct pnv_phb		*phb;
 
-#define PNV_IODA_MAX_PEER_PES	8
-	struct pnv_ioda_pe	*peers[PNV_IODA_MAX_PEER_PES];
-
 	/* A PE can be associated with a single device or an
 	 * entire bus (& children). In the former case, pdev
 	 * is populated, in the later case, pbus is.
@@ -53,14 +49,7 @@ struct pnv_ioda_pe {
 	/* PE number */
 	unsigned int		pe_number;
 
-	/* "Weight" assigned to the PE for the sake of DMA resource
-	 * allocations
-	 */
-	unsigned int		dma_weight;
-
 	/* "Base" iommu table, ie, 4K TCEs, 32-bit DMA */
-	int			tce32_seg;
-	int			tce32_segcount;
 	struct iommu_table_group table_group;
 
 	/* 64-bit TCE bypass region */
@@ -78,7 +67,6 @@ struct pnv_ioda_pe {
 	struct list_head	slaves;
 
 	/* Link in list of PE#s */
-	struct list_head	dma_link;
 	struct list_head	list;
 };
 
@@ -110,19 +98,18 @@ struct pnv_phb {
 			 unsigned int is_64, struct msi_msg *msg);
 	void (*dma_dev_setup)(struct pnv_phb *phb, struct pci_dev *pdev);
 	void (*fixup_phb)(struct pci_controller *hose);
-	u32 (*bdfn_to_pe)(struct pnv_phb *phb, struct pci_bus *bus, u32 devfn);
 	int (*init_m64)(struct pnv_phb *phb);
 	void (*reserve_m64_pe)(struct pci_bus *bus,
 			       unsigned long *pe_bitmap, bool all);
-	int (*pick_m64_pe)(struct pci_bus *bus, bool all);
+	struct pnv_ioda_pe *(*pick_m64_pe)(struct pci_bus *bus, bool all);
 	int (*get_pe_state)(struct pnv_phb *phb, int pe_no);
 	void (*freeze_pe)(struct pnv_phb *phb, int pe_no);
 	int (*unfreeze_pe)(struct pnv_phb *phb, int pe_no, int opt);
 
 	struct {
 		/* Global bridge info */
-		unsigned int		total_pe;
-		unsigned int		reserved_pe;
+		unsigned int		total_pe_num;
+		unsigned int		reserved_pe_idx;
 
 		/* 32-bit MMIO window */
 		unsigned int		m32_size;
@@ -141,15 +128,19 @@ struct pnv_phb {
 		unsigned int		io_segsize;
 		unsigned int		io_pci_base;
 
-		/* PE allocation bitmap */
-		unsigned long		*pe_alloc;
-		/* PE allocation mutex */
+		/* PE allocation */
 		struct mutex		pe_alloc_mutex;
+		unsigned long		*pe_alloc;
+		struct pnv_ioda_pe	*pe_array;
 
 		/* M32 & IO segment maps */
+		unsigned int		*m64_segmap;
 		unsigned int		*m32_segmap;
 		unsigned int		*io_segmap;
-		struct pnv_ioda_pe	*pe_array;
+
+		/* DMA32 segment maps - IODA1 only */
+		unsigned int		dma32_count;
+		unsigned int		*dma32_segmap;
 
 		/* IRQ chip */
 		int			irq_chip_init;
@@ -167,20 +158,6 @@ struct pnv_phb {
 		 */
 		unsigned char		pe_rmap[0x10000];
 
-		/* 32-bit TCE tables allocation */
-		unsigned long		tce32_count;
-
-		/* Total "weight" for the sake of DMA resources
-		 * allocation
-		 */
-		unsigned int		dma_weight;
-		unsigned int		dma_pe_count;
-
-		/* Sorted list of used PE's, sorted at
-		 * boot for resource allocation purposes
-		 */
-		struct list_head	pe_dma_list;
-
 		/* TCE cache invalidate registers (physical and
 		 * remapped)
 		 */
@@ -236,16 +213,23 @@ extern void pnv_pci_dma_bus_setup(struct
 extern int pnv_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type);
 extern void pnv_teardown_msi_irqs(struct pci_dev *pdev);
 
+extern void pe_level_printk(const struct pnv_ioda_pe *pe, const char *level,
+			    const char *fmt, ...);
+#define pe_err(pe, fmt, ...)					\
+	pe_level_printk(pe, KERN_ERR, fmt, ##__VA_ARGS__)
+#define pe_warn(pe, fmt, ...)					\
+	pe_level_printk(pe, KERN_WARNING, fmt, ##__VA_ARGS__)
+#define pe_info(pe, fmt, ...)					\
+	pe_level_printk(pe, KERN_INFO, fmt, ##__VA_ARGS__)
+
 /* Nvlink functions */
-extern void pnv_npu_tce_invalidate_entire(struct pnv_ioda_pe *npe);
-extern void pnv_npu_tce_invalidate(struct pnv_ioda_pe *npe,
-				       struct iommu_table *tbl,
-				       unsigned long index,
-				       unsigned long npages,
-				       bool rm);
-extern void pnv_npu_init_dma_pe(struct pnv_ioda_pe *npe);
-extern void pnv_npu_setup_dma_pe(struct pnv_ioda_pe *npe);
-extern int pnv_npu_dma_set_bypass(struct pnv_ioda_pe *npe, bool enabled);
-extern int pnv_npu_dma_set_mask(struct pci_dev *npdev, u64 dma_mask);
+extern void pnv_npu_try_dma_set_bypass(struct pci_dev *gpdev, bool bypass);
+extern void pnv_pci_ioda2_tce_invalidate_entire(struct pnv_phb *phb, bool rm);
+extern struct pnv_ioda_pe *pnv_pci_npu_setup_iommu(struct pnv_ioda_pe *npe);
+extern long pnv_npu_set_window(struct pnv_ioda_pe *npe, int num,
+		struct iommu_table *tbl);
+extern long pnv_npu_unset_window(struct pnv_ioda_pe *npe, int num);
+extern void pnv_npu_take_ownership(struct pnv_ioda_pe *npe);
+extern void pnv_npu_release_ownership(struct pnv_ioda_pe *npe);
 
 #endif /* __POWERNV_PCI_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/platforms/powernv/pci-ioda.c linux-libre-4.7-gnu/arch/powerpc/platforms/powernv/pci-ioda.c
--- linux-libre-4.6-gnu/arch/powerpc/platforms/powernv/pci-ioda.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/platforms/powernv/pci-ioda.c	2016-07-24 15:23:50.000000000 -0400
@@ -48,15 +48,16 @@
 #include "powernv.h"
 #include "pci.h"
 
-/* 256M DMA window, 4K TCE pages, 8 bytes TCE */
-#define TCE32_TABLE_SIZE	((0x10000000 / 0x1000) * 8)
+#define PNV_IODA1_M64_NUM	16	/* Number of M64 BARs	*/
+#define PNV_IODA1_M64_SEGS	8	/* Segments per M64 BAR	*/
+#define PNV_IODA1_DMA32_SEGSIZE	0x10000000
 
 #define POWERNV_IOMMU_DEFAULT_LEVELS	1
 #define POWERNV_IOMMU_MAX_LEVELS	5
 
 static void pnv_pci_ioda2_table_free_pages(struct iommu_table *tbl);
 
-static void pe_level_printk(const struct pnv_ioda_pe *pe, const char *level,
+void pe_level_printk(const struct pnv_ioda_pe *pe, const char *level,
 			    const char *fmt, ...)
 {
 	struct va_format vaf;
@@ -87,13 +88,6 @@ static void pe_level_printk(const struct
 	va_end(args);
 }
 
-#define pe_err(pe, fmt, ...)					\
-	pe_level_printk(pe, KERN_ERR, fmt, ##__VA_ARGS__)
-#define pe_warn(pe, fmt, ...)					\
-	pe_level_printk(pe, KERN_WARNING, fmt, ##__VA_ARGS__)
-#define pe_info(pe, fmt, ...)					\
-	pe_level_printk(pe, KERN_INFO, fmt, ##__VA_ARGS__)
-
 static bool pnv_iommu_bypass_disabled __read_mostly;
 
 static int __init iommu_setup(char *str)
@@ -122,9 +116,17 @@ static inline bool pnv_pci_is_mem_pref_6
 		(IORESOURCE_MEM_64 | IORESOURCE_PREFETCH));
 }
 
+static struct pnv_ioda_pe *pnv_ioda_init_pe(struct pnv_phb *phb, int pe_no)
+{
+	phb->ioda.pe_array[pe_no].phb = phb;
+	phb->ioda.pe_array[pe_no].pe_number = pe_no;
+
+	return &phb->ioda.pe_array[pe_no];
+}
+
 static void pnv_ioda_reserve_pe(struct pnv_phb *phb, int pe_no)
 {
-	if (!(pe_no >= 0 && pe_no < phb->ioda.total_pe)) {
+	if (!(pe_no >= 0 && pe_no < phb->ioda.total_pe_num)) {
 		pr_warn("%s: Invalid PE %d on PHB#%x\n",
 			__func__, pe_no, phb->hose->global_number);
 		return;
@@ -134,32 +136,31 @@ static void pnv_ioda_reserve_pe(struct p
 		pr_debug("%s: PE %d was reserved on PHB#%x\n",
 			 __func__, pe_no, phb->hose->global_number);
 
-	phb->ioda.pe_array[pe_no].phb = phb;
-	phb->ioda.pe_array[pe_no].pe_number = pe_no;
+	pnv_ioda_init_pe(phb, pe_no);
 }
 
-static int pnv_ioda_alloc_pe(struct pnv_phb *phb)
+static struct pnv_ioda_pe *pnv_ioda_alloc_pe(struct pnv_phb *phb)
 {
 	unsigned long pe;
 
 	do {
 		pe = find_next_zero_bit(phb->ioda.pe_alloc,
-					phb->ioda.total_pe, 0);
-		if (pe >= phb->ioda.total_pe)
-			return IODA_INVALID_PE;
+					phb->ioda.total_pe_num, 0);
+		if (pe >= phb->ioda.total_pe_num)
+			return NULL;
 	} while(test_and_set_bit(pe, phb->ioda.pe_alloc));
 
-	phb->ioda.pe_array[pe].phb = phb;
-	phb->ioda.pe_array[pe].pe_number = pe;
-	return pe;
+	return pnv_ioda_init_pe(phb, pe);
 }
 
-static void pnv_ioda_free_pe(struct pnv_phb *phb, int pe)
+static void pnv_ioda_free_pe(struct pnv_ioda_pe *pe)
 {
-	WARN_ON(phb->ioda.pe_array[pe].pdev);
+	struct pnv_phb *phb = pe->phb;
 
-	memset(&phb->ioda.pe_array[pe], 0, sizeof(struct pnv_ioda_pe));
-	clear_bit(pe, phb->ioda.pe_alloc);
+	WARN_ON(pe->pdev);
+
+	memset(pe, 0, sizeof(struct pnv_ioda_pe));
+	clear_bit(pe->pe_number, phb->ioda.pe_alloc);
 }
 
 /* The default M64 BAR is shared by all PEs */
@@ -199,13 +200,13 @@ static int pnv_ioda2_init_m64(struct pnv
 	 * expected to be 0 or last one of PE capabicity.
 	 */
 	r = &phb->hose->mem_resources[1];
-	if (phb->ioda.reserved_pe == 0)
+	if (phb->ioda.reserved_pe_idx == 0)
 		r->start += phb->ioda.m64_segsize;
-	else if (phb->ioda.reserved_pe == (phb->ioda.total_pe - 1))
+	else if (phb->ioda.reserved_pe_idx == (phb->ioda.total_pe_num - 1))
 		r->end -= phb->ioda.m64_segsize;
 	else
 		pr_warn("  Cannot strip M64 segment for reserved PE#%d\n",
-			phb->ioda.reserved_pe);
+			phb->ioda.reserved_pe_idx);
 
 	return 0;
 
@@ -219,7 +220,7 @@ fail:
 	return -EIO;
 }
 
-static void pnv_ioda2_reserve_dev_m64_pe(struct pci_dev *pdev,
+static void pnv_ioda_reserve_dev_m64_pe(struct pci_dev *pdev,
 					 unsigned long *pe_bitmap)
 {
 	struct pci_controller *hose = pci_bus_to_host(pdev->bus);
@@ -246,22 +247,80 @@ static void pnv_ioda2_reserve_dev_m64_pe
 	}
 }
 
-static void pnv_ioda2_reserve_m64_pe(struct pci_bus *bus,
-				     unsigned long *pe_bitmap,
-				     bool all)
+static int pnv_ioda1_init_m64(struct pnv_phb *phb)
+{
+	struct resource *r;
+	int index;
+
+	/*
+	 * There are 16 M64 BARs, each of which has 8 segments. So
+	 * there are as many M64 segments as the maximum number of
+	 * PEs, which is 128.
+	 */
+	for (index = 0; index < PNV_IODA1_M64_NUM; index++) {
+		unsigned long base, segsz = phb->ioda.m64_segsize;
+		int64_t rc;
+
+		base = phb->ioda.m64_base +
+		       index * PNV_IODA1_M64_SEGS * segsz;
+		rc = opal_pci_set_phb_mem_window(phb->opal_id,
+				OPAL_M64_WINDOW_TYPE, index, base, 0,
+				PNV_IODA1_M64_SEGS * segsz);
+		if (rc != OPAL_SUCCESS) {
+			pr_warn("  Error %lld setting M64 PHB#%d-BAR#%d\n",
+				rc, phb->hose->global_number, index);
+			goto fail;
+		}
+
+		rc = opal_pci_phb_mmio_enable(phb->opal_id,
+				OPAL_M64_WINDOW_TYPE, index,
+				OPAL_ENABLE_M64_SPLIT);
+		if (rc != OPAL_SUCCESS) {
+			pr_warn("  Error %lld enabling M64 PHB#%d-BAR#%d\n",
+				rc, phb->hose->global_number, index);
+			goto fail;
+		}
+	}
+
+	/*
+	 * Exclude the segment used by the reserved PE, which
+	 * is expected to be 0 or last supported PE#.
+	 */
+	r = &phb->hose->mem_resources[1];
+	if (phb->ioda.reserved_pe_idx == 0)
+		r->start += phb->ioda.m64_segsize;
+	else if (phb->ioda.reserved_pe_idx == (phb->ioda.total_pe_num - 1))
+		r->end -= phb->ioda.m64_segsize;
+	else
+		WARN(1, "Wrong reserved PE#%d on PHB#%d\n",
+		     phb->ioda.reserved_pe_idx, phb->hose->global_number);
+
+	return 0;
+
+fail:
+	for ( ; index >= 0; index--)
+		opal_pci_phb_mmio_enable(phb->opal_id,
+			OPAL_M64_WINDOW_TYPE, index, OPAL_DISABLE_M64);
+
+	return -EIO;
+}
+
+static void pnv_ioda_reserve_m64_pe(struct pci_bus *bus,
+				    unsigned long *pe_bitmap,
+				    bool all)
 {
 	struct pci_dev *pdev;
 
 	list_for_each_entry(pdev, &bus->devices, bus_list) {
-		pnv_ioda2_reserve_dev_m64_pe(pdev, pe_bitmap);
+		pnv_ioda_reserve_dev_m64_pe(pdev, pe_bitmap);
 
 		if (all && pdev->subordinate)
-			pnv_ioda2_reserve_m64_pe(pdev->subordinate,
-						 pe_bitmap, all);
+			pnv_ioda_reserve_m64_pe(pdev->subordinate,
+						pe_bitmap, all);
 	}
 }
 
-static int pnv_ioda2_pick_m64_pe(struct pci_bus *bus, bool all)
+static struct pnv_ioda_pe *pnv_ioda_pick_m64_pe(struct pci_bus *bus, bool all)
 {
 	struct pci_controller *hose = pci_bus_to_host(bus);
 	struct pnv_phb *phb = hose->private_data;
@@ -271,28 +330,28 @@ static int pnv_ioda2_pick_m64_pe(struct
 
 	/* Root bus shouldn't use M64 */
 	if (pci_is_root_bus(bus))
-		return IODA_INVALID_PE;
+		return NULL;
 
 	/* Allocate bitmap */
-	size = _ALIGN_UP(phb->ioda.total_pe / 8, sizeof(unsigned long));
+	size = _ALIGN_UP(phb->ioda.total_pe_num / 8, sizeof(unsigned long));
 	pe_alloc = kzalloc(size, GFP_KERNEL);
 	if (!pe_alloc) {
 		pr_warn("%s: Out of memory !\n",
 			__func__);
-		return IODA_INVALID_PE;
+		return NULL;
 	}
 
 	/* Figure out reserved PE numbers by the PE */
-	pnv_ioda2_reserve_m64_pe(bus, pe_alloc, all);
+	pnv_ioda_reserve_m64_pe(bus, pe_alloc, all);
 
 	/*
 	 * the current bus might not own M64 window and that's all
 	 * contributed by its child buses. For the case, we needn't
 	 * pick M64 dependent PE#.
 	 */
-	if (bitmap_empty(pe_alloc, phb->ioda.total_pe)) {
+	if (bitmap_empty(pe_alloc, phb->ioda.total_pe_num)) {
 		kfree(pe_alloc);
-		return IODA_INVALID_PE;
+		return NULL;
 	}
 
 	/*
@@ -301,10 +360,11 @@ static int pnv_ioda2_pick_m64_pe(struct
 	 */
 	master_pe = NULL;
 	i = -1;
-	while ((i = find_next_bit(pe_alloc, phb->ioda.total_pe, i + 1)) <
-		phb->ioda.total_pe) {
+	while ((i = find_next_bit(pe_alloc, phb->ioda.total_pe_num, i + 1)) <
+		phb->ioda.total_pe_num) {
 		pe = &phb->ioda.pe_array[i];
 
+		phb->ioda.m64_segmap[pe->pe_number] = pe->pe_number;
 		if (!master_pe) {
 			pe->flags |= PNV_IODA_PE_MASTER;
 			INIT_LIST_HEAD(&pe->slaves);
@@ -314,10 +374,30 @@ static int pnv_ioda2_pick_m64_pe(struct
 			pe->master = master_pe;
 			list_add_tail(&pe->list, &master_pe->slaves);
 		}
+
+		/*
+		 * P7IOC supports M64DT, which helps mapping M64 segment
+		 * to one particular PE#. However, PHB3 has fixed mapping
+		 * between M64 segment and PE#. In order to have same logic
+		 * for P7IOC and PHB3, we enforce fixed mapping between M64
+		 * segment and PE# on P7IOC.
+		 */
+		if (phb->type == PNV_PHB_IODA1) {
+			int64_t rc;
+
+			rc = opal_pci_map_pe_mmio_window(phb->opal_id,
+					pe->pe_number, OPAL_M64_WINDOW_TYPE,
+					pe->pe_number / PNV_IODA1_M64_SEGS,
+					pe->pe_number % PNV_IODA1_M64_SEGS);
+			if (rc != OPAL_SUCCESS)
+				pr_warn("%s: Error %lld mapping M64 for PHB#%d-PE#%d\n",
+					__func__, rc, phb->hose->global_number,
+					pe->pe_number);
+		}
 	}
 
 	kfree(pe_alloc);
-	return master_pe->pe_number;
+	return master_pe;
 }
 
 static void __init pnv_ioda_parse_m64_window(struct pnv_phb *phb)
@@ -328,8 +408,7 @@ static void __init pnv_ioda_parse_m64_wi
 	const u32 *r;
 	u64 pci_addr;
 
-	/* FIXME: Support M64 for P7IOC */
-	if (phb->type != PNV_PHB_IODA2) {
+	if (phb->type != PNV_PHB_IODA1 && phb->type != PNV_PHB_IODA2) {
 		pr_info("  Not support M64 window\n");
 		return;
 	}
@@ -355,7 +434,7 @@ static void __init pnv_ioda_parse_m64_wi
 	hose->mem_offset[1] = res->start - pci_addr;
 
 	phb->ioda.m64_size = resource_size(res);
-	phb->ioda.m64_segsize = phb->ioda.m64_size / phb->ioda.total_pe;
+	phb->ioda.m64_segsize = phb->ioda.m64_size / phb->ioda.total_pe_num;
 	phb->ioda.m64_base = pci_addr;
 
 	pr_info(" MEM64 0x%016llx..0x%016llx -> 0x%016llx\n",
@@ -363,9 +442,12 @@ static void __init pnv_ioda_parse_m64_wi
 
 	/* Use last M64 BAR to cover M64 window */
 	phb->ioda.m64_bar_idx = 15;
-	phb->init_m64 = pnv_ioda2_init_m64;
-	phb->reserve_m64_pe = pnv_ioda2_reserve_m64_pe;
-	phb->pick_m64_pe = pnv_ioda2_pick_m64_pe;
+	if (phb->type == PNV_PHB_IODA1)
+		phb->init_m64 = pnv_ioda1_init_m64;
+	else
+		phb->init_m64 = pnv_ioda2_init_m64;
+	phb->reserve_m64_pe = pnv_ioda_reserve_m64_pe;
+	phb->pick_m64_pe = pnv_ioda_pick_m64_pe;
 }
 
 static void pnv_ioda_freeze_pe(struct pnv_phb *phb, int pe_no)
@@ -456,7 +538,7 @@ static int pnv_ioda_get_pe_state(struct
 	s64 rc;
 
 	/* Sanity check on PE number */
-	if (pe_no < 0 || pe_no >= phb->ioda.total_pe)
+	if (pe_no < 0 || pe_no >= phb->ioda.total_pe_num)
 		return OPAL_EEH_STOPPED_PERM_UNAVAIL;
 
 	/*
@@ -808,44 +890,6 @@ out:
 	return 0;
 }
 
-static void pnv_ioda_link_pe_by_weight(struct pnv_phb *phb,
-				       struct pnv_ioda_pe *pe)
-{
-	struct pnv_ioda_pe *lpe;
-
-	list_for_each_entry(lpe, &phb->ioda.pe_dma_list, dma_link) {
-		if (lpe->dma_weight < pe->dma_weight) {
-			list_add_tail(&pe->dma_link, &lpe->dma_link);
-			return;
-		}
-	}
-	list_add_tail(&pe->dma_link, &phb->ioda.pe_dma_list);
-}
-
-static unsigned int pnv_ioda_dma_weight(struct pci_dev *dev)
-{
-	/* This is quite simplistic. The "base" weight of a device
-	 * is 10. 0 means no DMA is to be accounted for it.
-	 */
-
-	/* If it's a bridge, no DMA */
-	if (dev->hdr_type != PCI_HEADER_TYPE_NORMAL)
-		return 0;
-
-	/* Reduce the weight of slow USB controllers */
-	if (dev->class == PCI_CLASS_SERIAL_USB_UHCI ||
-	    dev->class == PCI_CLASS_SERIAL_USB_OHCI ||
-	    dev->class == PCI_CLASS_SERIAL_USB_EHCI)
-		return 3;
-
-	/* Increase the weight of RAID (includes Obsidian) */
-	if ((dev->class >> 8) == PCI_CLASS_STORAGE_RAID)
-		return 15;
-
-	/* Default */
-	return 10;
-}
-
 #ifdef CONFIG_PCI_IOV
 static int pnv_pci_vf_resource_shift(struct pci_dev *dev, int offset)
 {
@@ -919,7 +963,6 @@ static struct pnv_ioda_pe *pnv_ioda_setu
 	struct pnv_phb *phb = hose->private_data;
 	struct pci_dn *pdn = pci_get_pdn(dev);
 	struct pnv_ioda_pe *pe;
-	int pe_num;
 
 	if (!pdn) {
 		pr_err("%s: Device tree node not associated properly\n",
@@ -929,8 +972,8 @@ static struct pnv_ioda_pe *pnv_ioda_setu
 	if (pdn->pe_number != IODA_INVALID_PE)
 		return NULL;
 
-	pe_num = pnv_ioda_alloc_pe(phb);
-	if (pe_num == IODA_INVALID_PE) {
+	pe = pnv_ioda_alloc_pe(phb);
+	if (!pe) {
 		pr_warning("%s: Not enough PE# available, disabling device\n",
 			   pci_name(dev));
 		return NULL;
@@ -943,14 +986,12 @@ static struct pnv_ioda_pe *pnv_ioda_setu
 	 *
 	 * At some point we want to remove the PDN completely anyways
 	 */
-	pe = &phb->ioda.pe_array[pe_num];
 	pci_dev_get(dev);
 	pdn->pcidev = dev;
-	pdn->pe_number = pe_num;
+	pdn->pe_number = pe->pe_number;
 	pe->flags = PNV_IODA_PE_DEV;
 	pe->pdev = dev;
 	pe->pbus = NULL;
-	pe->tce32_seg = -1;
 	pe->mve_number = -1;
 	pe->rid = dev->bus->number << 8 | pdn->devfn;
 
@@ -958,23 +999,15 @@ static struct pnv_ioda_pe *pnv_ioda_setu
 
 	if (pnv_ioda_configure_pe(phb, pe)) {
 		/* XXX What do we do here ? */
-		if (pe_num)
-			pnv_ioda_free_pe(phb, pe_num);
+		pnv_ioda_free_pe(pe);
 		pdn->pe_number = IODA_INVALID_PE;
 		pe->pdev = NULL;
 		pci_dev_put(dev);
 		return NULL;
 	}
 
-	/* Assign a DMA weight to the device */
-	pe->dma_weight = pnv_ioda_dma_weight(dev);
-	if (pe->dma_weight != 0) {
-		phb->ioda.dma_weight += pe->dma_weight;
-		phb->ioda.dma_pe_count++;
-	}
-
-	/* Link the PE */
-	pnv_ioda_link_pe_by_weight(phb, pe);
+	/* Put PE to the list */
+	list_add_tail(&pe->list, &phb->ioda.pe_list);
 
 	return pe;
 }
@@ -993,7 +1026,6 @@ static void pnv_ioda_setup_same_PE(struc
 		}
 		pdn->pcidev = dev;
 		pdn->pe_number = pe->pe_number;
-		pe->dma_weight += pnv_ioda_dma_weight(dev);
 		if ((pe->flags & PNV_IODA_PE_BUS_ALL) && dev->subordinate)
 			pnv_ioda_setup_same_PE(dev->subordinate, pe);
 	}
@@ -1005,49 +1037,44 @@ static void pnv_ioda_setup_same_PE(struc
  * subordinate PCI devices and buses. The second type of PE is normally
  * orgiriated by PCIe-to-PCI bridge or PLX switch downstream ports.
  */
-static void pnv_ioda_setup_bus_PE(struct pci_bus *bus, bool all)
+static struct pnv_ioda_pe *pnv_ioda_setup_bus_PE(struct pci_bus *bus, bool all)
 {
 	struct pci_controller *hose = pci_bus_to_host(bus);
 	struct pnv_phb *phb = hose->private_data;
-	struct pnv_ioda_pe *pe;
-	int pe_num = IODA_INVALID_PE;
+	struct pnv_ioda_pe *pe = NULL;
 
 	/* Check if PE is determined by M64 */
 	if (phb->pick_m64_pe)
-		pe_num = phb->pick_m64_pe(bus, all);
+		pe = phb->pick_m64_pe(bus, all);
 
 	/* The PE number isn't pinned by M64 */
-	if (pe_num == IODA_INVALID_PE)
-		pe_num = pnv_ioda_alloc_pe(phb);
+	if (!pe)
+		pe = pnv_ioda_alloc_pe(phb);
 
-	if (pe_num == IODA_INVALID_PE) {
+	if (!pe) {
 		pr_warning("%s: Not enough PE# available for PCI bus %04x:%02x\n",
 			__func__, pci_domain_nr(bus), bus->number);
-		return;
+		return NULL;
 	}
 
-	pe = &phb->ioda.pe_array[pe_num];
 	pe->flags |= (all ? PNV_IODA_PE_BUS_ALL : PNV_IODA_PE_BUS);
 	pe->pbus = bus;
 	pe->pdev = NULL;
-	pe->tce32_seg = -1;
 	pe->mve_number = -1;
 	pe->rid = bus->busn_res.start << 8;
-	pe->dma_weight = 0;
 
 	if (all)
 		pe_info(pe, "Secondary bus %d..%d associated with PE#%d\n",
-			bus->busn_res.start, bus->busn_res.end, pe_num);
+			bus->busn_res.start, bus->busn_res.end, pe->pe_number);
 	else
 		pe_info(pe, "Secondary bus %d associated with PE#%d\n",
-			bus->busn_res.start, pe_num);
+			bus->busn_res.start, pe->pe_number);
 
 	if (pnv_ioda_configure_pe(phb, pe)) {
 		/* XXX What do we do here ? */
-		if (pe_num)
-			pnv_ioda_free_pe(phb, pe_num);
+		pnv_ioda_free_pe(pe);
 		pe->pbus = NULL;
-		return;
+		return NULL;
 	}
 
 	/* Associate it with all child devices */
@@ -1056,16 +1083,7 @@ static void pnv_ioda_setup_bus_PE(struct
 	/* Put PE to the list */
 	list_add_tail(&pe->list, &phb->ioda.pe_list);
 
-	/* Account for one DMA PE if at least one DMA capable device exist
-	 * below the bridge
-	 */
-	if (pe->dma_weight != 0) {
-		phb->ioda.dma_weight += pe->dma_weight;
-		phb->ioda.dma_pe_count++;
-	}
-
-	/* Link the PE */
-	pnv_ioda_link_pe_by_weight(phb, pe);
+	return pe;
 }
 
 static struct pnv_ioda_pe *pnv_ioda_setup_npu_PE(struct pci_dev *npu_pdev)
@@ -1088,7 +1106,7 @@ static struct pnv_ioda_pe *pnv_ioda_setu
 	 * same GPU get assigned the same PE.
 	 */
 	gpu_pdev = pnv_pci_get_gpu_dev(npu_pdev);
-	for (pe_num = 0; pe_num < phb->ioda.total_pe; pe_num++) {
+	for (pe_num = 0; pe_num < phb->ioda.total_pe_num; pe_num++) {
 		pe = &phb->ioda.pe_array[pe_num];
 		if (!pe->pdev)
 			continue;
@@ -1106,7 +1124,6 @@ static struct pnv_ioda_pe *pnv_ioda_setu
 			rid = npu_pdev->bus->number << 8 | npu_pdn->devfn;
 			npu_pdn->pcidev = npu_pdev;
 			npu_pdn->pe_number = pe_num;
-			pe->dma_weight += pnv_ioda_dma_weight(npu_pdev);
 			phb->ioda.pe_rmap[rid] = pe->pe_number;
 
 			/* Map the PE to this link */
@@ -1378,7 +1395,7 @@ static void pnv_ioda_release_vf_PE(struc
 
 		pnv_ioda_deconfigure_pe(phb, pe);
 
-		pnv_ioda_free_pe(phb, pe->pe_number);
+		pnv_ioda_free_pe(pe);
 	}
 }
 
@@ -1387,6 +1404,7 @@ void pnv_pci_sriov_disable(struct pci_de
 	struct pci_bus        *bus;
 	struct pci_controller *hose;
 	struct pnv_phb        *phb;
+	struct pnv_ioda_pe    *pe;
 	struct pci_dn         *pdn;
 	struct pci_sriov      *iov;
 	u16                    num_vfs, i;
@@ -1411,8 +1429,11 @@ void pnv_pci_sriov_disable(struct pci_de
 		/* Release PE numbers */
 		if (pdn->m64_single_mode) {
 			for (i = 0; i < num_vfs; i++) {
-				if (pdn->pe_num_map[i] != IODA_INVALID_PE)
-					pnv_ioda_free_pe(phb, pdn->pe_num_map[i]);
+				if (pdn->pe_num_map[i] == IODA_INVALID_PE)
+					continue;
+
+				pe = &phb->ioda.pe_array[pdn->pe_num_map[i]];
+				pnv_ioda_free_pe(pe);
 			}
 		} else
 			bitmap_clear(phb->ioda.pe_alloc, *pdn->pe_num_map, num_vfs);
@@ -1454,7 +1475,6 @@ static void pnv_ioda_setup_vf_PE(struct
 		pe->flags = PNV_IODA_PE_VF;
 		pe->pbus = NULL;
 		pe->parent_dev = pdev;
-		pe->tce32_seg = -1;
 		pe->mve_number = -1;
 		pe->rid = (pci_iov_virtfn_bus(pdev, vf_index) << 8) |
 			   pci_iov_virtfn_devfn(pdev, vf_index);
@@ -1466,8 +1486,7 @@ static void pnv_ioda_setup_vf_PE(struct
 
 		if (pnv_ioda_configure_pe(phb, pe)) {
 			/* XXX What do we do here ? */
-			if (pe_num)
-				pnv_ioda_free_pe(phb, pe_num);
+			pnv_ioda_free_pe(pe);
 			pe->pdev = NULL;
 			continue;
 		}
@@ -1486,6 +1505,7 @@ int pnv_pci_sriov_enable(struct pci_dev
 	struct pci_bus        *bus;
 	struct pci_controller *hose;
 	struct pnv_phb        *phb;
+	struct pnv_ioda_pe    *pe;
 	struct pci_dn         *pdn;
 	int                    ret;
 	u16                    i;
@@ -1528,18 +1548,20 @@ int pnv_pci_sriov_enable(struct pci_dev
 		/* Calculate available PE for required VFs */
 		if (pdn->m64_single_mode) {
 			for (i = 0; i < num_vfs; i++) {
-				pdn->pe_num_map[i] = pnv_ioda_alloc_pe(phb);
-				if (pdn->pe_num_map[i] == IODA_INVALID_PE) {
+				pe = pnv_ioda_alloc_pe(phb);
+				if (!pe) {
 					ret = -EBUSY;
 					goto m64_failed;
 				}
+
+				pdn->pe_num_map[i] = pe->pe_number;
 			}
 		} else {
 			mutex_lock(&phb->ioda.pe_alloc_mutex);
 			*pdn->pe_num_map = bitmap_find_next_zero_area(
-				phb->ioda.pe_alloc, phb->ioda.total_pe,
+				phb->ioda.pe_alloc, phb->ioda.total_pe_num,
 				0, num_vfs, 0);
-			if (*pdn->pe_num_map >= phb->ioda.total_pe) {
+			if (*pdn->pe_num_map >= phb->ioda.total_pe_num) {
 				mutex_unlock(&phb->ioda.pe_alloc_mutex);
 				dev_info(&pdev->dev, "Failed to enable VF%d\n", num_vfs);
 				kfree(pdn->pe_num_map);
@@ -1577,8 +1599,11 @@ int pnv_pci_sriov_enable(struct pci_dev
 m64_failed:
 	if (pdn->m64_single_mode) {
 		for (i = 0; i < num_vfs; i++) {
-			if (pdn->pe_num_map[i] != IODA_INVALID_PE)
-				pnv_ioda_free_pe(phb, pdn->pe_num_map[i]);
+			if (pdn->pe_num_map[i] == IODA_INVALID_PE)
+				continue;
+
+			pe = &phb->ioda.pe_array[pdn->pe_num_map[i]];
+			pnv_ioda_free_pe(pe);
 		}
 	} else
 		bitmap_clear(phb->ioda.pe_alloc, *pdn->pe_num_map, num_vfs);
@@ -1640,8 +1665,6 @@ static int pnv_pci_ioda_dma_set_mask(str
 	struct pnv_ioda_pe *pe;
 	uint64_t top;
 	bool bypass = false;
-	struct pci_dev *linked_npu_dev;
-	int i;
 
 	if (WARN_ON(!pdn || pdn->pe_number == IODA_INVALID_PE))
 		return -ENODEV;;
@@ -1662,15 +1685,7 @@ static int pnv_pci_ioda_dma_set_mask(str
 	*pdev->dev.dma_mask = dma_mask;
 
 	/* Update peer npu devices */
-	if (pe->flags & PNV_IODA_PE_PEER)
-		for (i = 0; i < PNV_IODA_MAX_PEER_PES; i++) {
-			if (!pe->peers[i])
-				continue;
-
-			linked_npu_dev = pe->peers[i]->pdev;
-			if (dma_get_mask(&linked_npu_dev->dev) != dma_mask)
-				dma_set_mask(&linked_npu_dev->dev, dma_mask);
-		}
+	pnv_npu_try_dma_set_bypass(pdev, bypass);
 
 	return 0;
 }
@@ -1811,28 +1826,34 @@ static struct iommu_table_ops pnv_ioda1_
 	.get = pnv_tce_get,
 };
 
-static inline void pnv_pci_ioda2_tce_invalidate_entire(struct pnv_ioda_pe *pe)
+#define TCE_KILL_INVAL_ALL  PPC_BIT(0)
+#define TCE_KILL_INVAL_PE   PPC_BIT(1)
+#define TCE_KILL_INVAL_TCE  PPC_BIT(2)
+
+void pnv_pci_ioda2_tce_invalidate_entire(struct pnv_phb *phb, bool rm)
+{
+	const unsigned long val = TCE_KILL_INVAL_ALL;
+
+	mb(); /* Ensure previous TCE table stores are visible */
+	if (rm)
+		__raw_rm_writeq(cpu_to_be64(val),
+				(__be64 __iomem *)
+				phb->ioda.tce_inval_reg_phys);
+	else
+		__raw_writeq(cpu_to_be64(val), phb->ioda.tce_inval_reg);
+}
+
+static inline void pnv_pci_ioda2_tce_invalidate_pe(struct pnv_ioda_pe *pe)
 {
 	/* 01xb - invalidate TCEs that match the specified PE# */
-	unsigned long val = (0x4ull << 60) | (pe->pe_number & 0xFF);
+	unsigned long val = TCE_KILL_INVAL_PE | (pe->pe_number & 0xFF);
 	struct pnv_phb *phb = pe->phb;
-	struct pnv_ioda_pe *npe;
-	int i;
 
 	if (!phb->ioda.tce_inval_reg)
 		return;
 
 	mb(); /* Ensure above stores are visible */
 	__raw_writeq(cpu_to_be64(val), phb->ioda.tce_inval_reg);
-
-	if (pe->flags & PNV_IODA_PE_PEER)
-		for (i = 0; i < PNV_IODA_MAX_PEER_PES; i++) {
-			npe = pe->peers[i];
-			if (!npe || npe->phb->type != PNV_PHB_NPU)
-				continue;
-
-			pnv_npu_tce_invalidate_entire(npe);
-		}
 }
 
 static void pnv_pci_ioda2_do_tce_invalidate(unsigned pe_number, bool rm,
@@ -1842,7 +1863,7 @@ static void pnv_pci_ioda2_do_tce_invalid
 	unsigned long start, end, inc;
 
 	/* We'll invalidate DMA address in PE scope */
-	start = 0x2ull << 60;
+	start = TCE_KILL_INVAL_TCE;
 	start |= (pe_number & 0xFF);
 	end = start;
 
@@ -1867,28 +1888,24 @@ static void pnv_pci_ioda2_tce_invalidate
 	struct iommu_table_group_link *tgl;
 
 	list_for_each_entry_rcu(tgl, &tbl->it_group_list, next) {
-		struct pnv_ioda_pe *npe;
 		struct pnv_ioda_pe *pe = container_of(tgl->table_group,
 				struct pnv_ioda_pe, table_group);
 		__be64 __iomem *invalidate = rm ?
 			(__be64 __iomem *)pe->phb->ioda.tce_inval_reg_phys :
 			pe->phb->ioda.tce_inval_reg;
-		int i;
 
+		if (pe->phb->type == PNV_PHB_NPU) {
+			/*
+			 * The NVLink hardware does not support TCE kill
+			 * per TCE entry so we have to invalidate
+			 * the entire cache for it.
+			 */
+			pnv_pci_ioda2_tce_invalidate_entire(pe->phb, rm);
+			continue;
+		}
 		pnv_pci_ioda2_do_tce_invalidate(pe->pe_number, rm,
 			invalidate, tbl->it_page_shift,
 			index, npages);
-
-		if (pe->flags & PNV_IODA_PE_PEER)
-			/* Invalidate PEs using the same TCE table */
-			for (i = 0; i < PNV_IODA_MAX_PEER_PES; i++) {
-				npe = pe->peers[i];
-				if (!npe || npe->phb->type != PNV_PHB_NPU)
-					continue;
-
-				pnv_npu_tce_invalidate(npe, tbl, index,
-							npages, rm);
-			}
 	}
 }
 
@@ -1945,56 +1962,140 @@ static struct iommu_table_ops pnv_ioda2_
 	.free = pnv_ioda2_table_free,
 };
 
-static void pnv_pci_ioda_setup_dma_pe(struct pnv_phb *phb,
-				      struct pnv_ioda_pe *pe, unsigned int base,
-				      unsigned int segs)
+static int pnv_pci_ioda_dev_dma_weight(struct pci_dev *dev, void *data)
+{
+	unsigned int *weight = (unsigned int *)data;
+
+	/* This is quite simplistic. The "base" weight of a device
+	 * is 10. 0 means no DMA is to be accounted for it.
+	 */
+	if (dev->hdr_type != PCI_HEADER_TYPE_NORMAL)
+		return 0;
+
+	if (dev->class == PCI_CLASS_SERIAL_USB_UHCI ||
+	    dev->class == PCI_CLASS_SERIAL_USB_OHCI ||
+	    dev->class == PCI_CLASS_SERIAL_USB_EHCI)
+		*weight += 3;
+	else if ((dev->class >> 8) == PCI_CLASS_STORAGE_RAID)
+		*weight += 15;
+	else
+		*weight += 10;
+
+	return 0;
+}
+
+static unsigned int pnv_pci_ioda_pe_dma_weight(struct pnv_ioda_pe *pe)
+{
+	unsigned int weight = 0;
+
+	/* SRIOV VF has same DMA32 weight as its PF */
+#ifdef CONFIG_PCI_IOV
+	if ((pe->flags & PNV_IODA_PE_VF) && pe->parent_dev) {
+		pnv_pci_ioda_dev_dma_weight(pe->parent_dev, &weight);
+		return weight;
+	}
+#endif
+
+	if ((pe->flags & PNV_IODA_PE_DEV) && pe->pdev) {
+		pnv_pci_ioda_dev_dma_weight(pe->pdev, &weight);
+	} else if ((pe->flags & PNV_IODA_PE_BUS) && pe->pbus) {
+		struct pci_dev *pdev;
+
+		list_for_each_entry(pdev, &pe->pbus->devices, bus_list)
+			pnv_pci_ioda_dev_dma_weight(pdev, &weight);
+	} else if ((pe->flags & PNV_IODA_PE_BUS_ALL) && pe->pbus) {
+		pci_walk_bus(pe->pbus, pnv_pci_ioda_dev_dma_weight, &weight);
+	}
+
+	return weight;
+}
+
+static void pnv_pci_ioda1_setup_dma_pe(struct pnv_phb *phb,
+				       struct pnv_ioda_pe *pe)
 {
 
 	struct page *tce_mem = NULL;
 	struct iommu_table *tbl;
-	unsigned int i;
+	unsigned int weight, total_weight = 0;
+	unsigned int tce32_segsz, base, segs, avail, i;
 	int64_t rc;
 	void *addr;
 
 	/* XXX FIXME: Handle 64-bit only DMA devices */
 	/* XXX FIXME: Provide 64-bit DMA facilities & non-4K TCE tables etc.. */
 	/* XXX FIXME: Allocate multi-level tables on PHB3 */
+	weight = pnv_pci_ioda_pe_dma_weight(pe);
+	if (!weight)
+		return;
 
-	/* We shouldn't already have a 32-bit DMA associated */
-	if (WARN_ON(pe->tce32_seg >= 0))
+	pci_walk_bus(phb->hose->bus, pnv_pci_ioda_dev_dma_weight,
+		     &total_weight);
+	segs = (weight * phb->ioda.dma32_count) / total_weight;
+	if (!segs)
+		segs = 1;
+
+	/*
+	 * Allocate contiguous DMA32 segments. We begin with the expected
+	 * number of segments. With one more attempt, the number of DMA32
+	 * segments to be allocated is decreased by one until one segment
+	 * is allocated successfully.
+	 */
+	do {
+		for (base = 0; base <= phb->ioda.dma32_count - segs; base++) {
+			for (avail = 0, i = base; i < base + segs; i++) {
+				if (phb->ioda.dma32_segmap[i] ==
+				    IODA_INVALID_PE)
+					avail++;
+			}
+
+			if (avail == segs)
+				goto found;
+		}
+	} while (--segs);
+
+	if (!segs) {
+		pe_warn(pe, "No available DMA32 segments\n");
 		return;
+	}
 
+found:
 	tbl = pnv_pci_table_alloc(phb->hose->node);
 	iommu_register_group(&pe->table_group, phb->hose->global_number,
 			pe->pe_number);
 	pnv_pci_link_table_and_group(phb->hose->node, 0, tbl, &pe->table_group);
 
 	/* Grab a 32-bit TCE table */
-	pe->tce32_seg = base;
+	pe_info(pe, "DMA weight %d (%d), assigned (%d) %d DMA32 segments\n",
+		weight, total_weight, base, segs);
 	pe_info(pe, " Setting up 32-bit TCE table at %08x..%08x\n",
-		(base << 28), ((base + segs) << 28) - 1);
+		base * PNV_IODA1_DMA32_SEGSIZE,
+		(base + segs) * PNV_IODA1_DMA32_SEGSIZE - 1);
 
 	/* XXX Currently, we allocate one big contiguous table for the
 	 * TCEs. We only really need one chunk per 256M of TCE space
 	 * (ie per segment) but that's an optimization for later, it
 	 * requires some added smarts with our get/put_tce implementation
+	 *
+	 * Each TCE page is 4KB in size and each TCE entry occupies 8
+	 * bytes
 	 */
+	tce32_segsz = PNV_IODA1_DMA32_SEGSIZE >> (IOMMU_PAGE_SHIFT_4K - 3);
 	tce_mem = alloc_pages_node(phb->hose->node, GFP_KERNEL,
-				   get_order(TCE32_TABLE_SIZE * segs));
+				   get_order(tce32_segsz * segs));
 	if (!tce_mem) {
 		pe_err(pe, " Failed to allocate a 32-bit TCE memory\n");
 		goto fail;
 	}
 	addr = page_address(tce_mem);
-	memset(addr, 0, TCE32_TABLE_SIZE * segs);
+	memset(addr, 0, tce32_segsz * segs);
 
 	/* Configure HW */
 	for (i = 0; i < segs; i++) {
 		rc = opal_pci_map_pe_dma_window(phb->opal_id,
 					      pe->pe_number,
 					      base + i, 1,
-					      __pa(addr) + TCE32_TABLE_SIZE * i,
-					      TCE32_TABLE_SIZE, 0x1000);
+					      __pa(addr) + tce32_segsz * i,
+					      tce32_segsz, IOMMU_PAGE_SIZE_4K);
 		if (rc) {
 			pe_err(pe, " Failed to configure 32-bit TCE table,"
 			       " err %ld\n", rc);
@@ -2002,9 +2103,14 @@ static void pnv_pci_ioda_setup_dma_pe(st
 		}
 	}
 
+	/* Setup DMA32 segment mapping */
+	for (i = base; i < base + segs; i++)
+		phb->ioda.dma32_segmap[i] = pe->pe_number;
+
 	/* Setup linux iommu table */
-	pnv_pci_setup_iommu_table(tbl, addr, TCE32_TABLE_SIZE * segs,
-				  base << 28, IOMMU_PAGE_SHIFT_4K);
+	pnv_pci_setup_iommu_table(tbl, addr, tce32_segsz * segs,
+				  base * PNV_IODA1_DMA32_SEGSIZE,
+				  IOMMU_PAGE_SHIFT_4K);
 
 	/* OPAL variant of P7IOC SW invalidated TCEs */
 	if (phb->ioda.tce_inval_reg)
@@ -2031,10 +2137,8 @@ static void pnv_pci_ioda_setup_dma_pe(st
 	return;
  fail:
 	/* XXX Failure: Try to fallback to 64-bit only ? */
-	if (pe->tce32_seg >= 0)
-		pe->tce32_seg = -1;
 	if (tce_mem)
-		__free_pages(tce_mem, get_order(TCE32_TABLE_SIZE * segs));
+		__free_pages(tce_mem, get_order(tce32_segsz * segs));
 	if (tbl) {
 		pnv_pci_unlink_table_and_group(tbl, &pe->table_group);
 		iommu_free_table(tbl, "pnv");
@@ -2075,7 +2179,7 @@ static long pnv_pci_ioda2_set_window(str
 
 	pnv_pci_link_table_and_group(phb->hose->node, num,
 			tbl, &pe->table_group);
-	pnv_pci_ioda2_tce_invalidate_entire(pe);
+	pnv_pci_ioda2_tce_invalidate_pe(pe);
 
 	return 0;
 }
@@ -2219,7 +2323,7 @@ static long pnv_pci_ioda2_unset_window(s
 	if (ret)
 		pe_warn(pe, "Unmapping failed, ret = %ld\n", ret);
 	else
-		pnv_pci_ioda2_tce_invalidate_entire(pe);
+		pnv_pci_ioda2_tce_invalidate_pe(pe);
 
 	pnv_pci_unlink_table_and_group(table_group->tables[num], table_group);
 
@@ -2288,6 +2392,116 @@ static struct iommu_table_group_ops pnv_
 	.take_ownership = pnv_ioda2_take_ownership,
 	.release_ownership = pnv_ioda2_release_ownership,
 };
+
+static int gpe_table_group_to_npe_cb(struct device *dev, void *opaque)
+{
+	struct pci_controller *hose;
+	struct pnv_phb *phb;
+	struct pnv_ioda_pe **ptmppe = opaque;
+	struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+	struct pci_dn *pdn = pci_get_pdn(pdev);
+
+	if (!pdn || pdn->pe_number == IODA_INVALID_PE)
+		return 0;
+
+	hose = pci_bus_to_host(pdev->bus);
+	phb = hose->private_data;
+	if (phb->type != PNV_PHB_NPU)
+		return 0;
+
+	*ptmppe = &phb->ioda.pe_array[pdn->pe_number];
+
+	return 1;
+}
+
+/*
+ * This returns PE of associated NPU.
+ * This assumes that NPU is in the same IOMMU group with GPU and there is
+ * no other PEs.
+ */
+static struct pnv_ioda_pe *gpe_table_group_to_npe(
+		struct iommu_table_group *table_group)
+{
+	struct pnv_ioda_pe *npe = NULL;
+	int ret = iommu_group_for_each_dev(table_group->group, &npe,
+			gpe_table_group_to_npe_cb);
+
+	BUG_ON(!ret || !npe);
+
+	return npe;
+}
+
+static long pnv_pci_ioda2_npu_set_window(struct iommu_table_group *table_group,
+		int num, struct iommu_table *tbl)
+{
+	long ret = pnv_pci_ioda2_set_window(table_group, num, tbl);
+
+	if (ret)
+		return ret;
+
+	ret = pnv_npu_set_window(gpe_table_group_to_npe(table_group), num, tbl);
+	if (ret)
+		pnv_pci_ioda2_unset_window(table_group, num);
+
+	return ret;
+}
+
+static long pnv_pci_ioda2_npu_unset_window(
+		struct iommu_table_group *table_group,
+		int num)
+{
+	long ret = pnv_pci_ioda2_unset_window(table_group, num);
+
+	if (ret)
+		return ret;
+
+	return pnv_npu_unset_window(gpe_table_group_to_npe(table_group), num);
+}
+
+static void pnv_ioda2_npu_take_ownership(struct iommu_table_group *table_group)
+{
+	/*
+	 * Detach NPU first as pnv_ioda2_take_ownership() will destroy
+	 * the iommu_table if 32bit DMA is enabled.
+	 */
+	pnv_npu_take_ownership(gpe_table_group_to_npe(table_group));
+	pnv_ioda2_take_ownership(table_group);
+}
+
+static struct iommu_table_group_ops pnv_pci_ioda2_npu_ops = {
+	.get_table_size = pnv_pci_ioda2_get_table_size,
+	.create_table = pnv_pci_ioda2_create_table,
+	.set_window = pnv_pci_ioda2_npu_set_window,
+	.unset_window = pnv_pci_ioda2_npu_unset_window,
+	.take_ownership = pnv_ioda2_npu_take_ownership,
+	.release_ownership = pnv_ioda2_release_ownership,
+};
+
+static void pnv_pci_ioda_setup_iommu_api(void)
+{
+	struct pci_controller *hose, *tmp;
+	struct pnv_phb *phb;
+	struct pnv_ioda_pe *pe, *gpe;
+
+	/*
+	 * Now we have all PHBs discovered, time to add NPU devices to
+	 * the corresponding IOMMU groups.
+	 */
+	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
+		phb = hose->private_data;
+
+		if (phb->type != PNV_PHB_NPU)
+			continue;
+
+		list_for_each_entry(pe, &phb->ioda.pe_list, list) {
+			gpe = pnv_pci_npu_setup_iommu(pe);
+			if (gpe)
+				gpe->table_group.ops = &pnv_pci_ioda2_npu_ops;
+		}
+	}
+}
+#else /* !CONFIG_IOMMU_API */
+static void pnv_pci_ioda_setup_iommu_api(void) { };
 #endif
 
 static void pnv_pci_ioda_setup_opal_tce_kill(struct pnv_phb *phb)
@@ -2443,10 +2657,6 @@ static void pnv_pci_ioda2_setup_dma_pe(s
 {
 	int64_t rc;
 
-	/* We shouldn't already have a 32-bit DMA associated */
-	if (WARN_ON(pe->tce32_seg >= 0))
-		return;
-
 	/* TVE #1 is selected by PCI address bit 59 */
 	pe->tce_bypass_base = 1ull << 59;
 
@@ -2454,7 +2664,6 @@ static void pnv_pci_ioda2_setup_dma_pe(s
 			pe->pe_number);
 
 	/* The PE will reserve all possible 32-bits space */
-	pe->tce32_seg = 0;
 	pe_info(pe, "Setting up 32-bit TCE table at 0..%08x\n",
 		phb->ioda.m32_pci_base);
 
@@ -2470,11 +2679,8 @@ static void pnv_pci_ioda2_setup_dma_pe(s
 #endif
 
 	rc = pnv_pci_ioda2_setup_default_config(pe);
-	if (rc) {
-		if (pe->tce32_seg >= 0)
-			pe->tce32_seg = -1;
+	if (rc)
 		return;
-	}
 
 	if (pe->flags & PNV_IODA_PE_DEV)
 		iommu_add_device(&pe->pdev->dev);
@@ -2485,47 +2691,24 @@ static void pnv_pci_ioda2_setup_dma_pe(s
 static void pnv_ioda_setup_dma(struct pnv_phb *phb)
 {
 	struct pci_controller *hose = phb->hose;
-	unsigned int residual, remaining, segs, tw, base;
 	struct pnv_ioda_pe *pe;
+	unsigned int weight;
 
 	/* If we have more PE# than segments available, hand out one
 	 * per PE until we run out and let the rest fail. If not,
 	 * then we assign at least one segment per PE, plus more based
 	 * on the amount of devices under that PE
 	 */
-	if (phb->ioda.dma_pe_count > phb->ioda.tce32_count)
-		residual = 0;
-	else
-		residual = phb->ioda.tce32_count -
-			phb->ioda.dma_pe_count;
-
-	pr_info("PCI: Domain %04x has %ld available 32-bit DMA segments\n",
-		hose->global_number, phb->ioda.tce32_count);
-	pr_info("PCI: %d PE# for a total weight of %d\n",
-		phb->ioda.dma_pe_count, phb->ioda.dma_weight);
+	pr_info("PCI: Domain %04x has %d available 32-bit DMA segments\n",
+		hose->global_number, phb->ioda.dma32_count);
 
 	pnv_pci_ioda_setup_opal_tce_kill(phb);
 
-	/* Walk our PE list and configure their DMA segments, hand them
-	 * out one base segment plus any residual segments based on
-	 * weight
-	 */
-	remaining = phb->ioda.tce32_count;
-	tw = phb->ioda.dma_weight;
-	base = 0;
-	list_for_each_entry(pe, &phb->ioda.pe_dma_list, dma_link) {
-		if (!pe->dma_weight)
-			continue;
-		if (!remaining) {
-			pe_warn(pe, "No DMA32 resources available\n");
+	/* Walk our PE list and configure their DMA segments */
+	list_for_each_entry(pe, &phb->ioda.pe_list, list) {
+		weight = pnv_pci_ioda_pe_dma_weight(pe);
+		if (!weight)
 			continue;
-		}
-		segs = 1;
-		if (residual) {
-			segs += ((pe->dma_weight * residual)  + (tw / 2)) / tw;
-			if (segs > remaining)
-				segs = remaining;
-		}
 
 		/*
 		 * For IODA2 compliant PHB3, we needn't care about the weight.
@@ -2533,12 +2716,9 @@ static void pnv_ioda_setup_dma(struct pn
 		 * the specific PE.
 		 */
 		if (phb->type == PNV_PHB_IODA1) {
-			pe_info(pe, "DMA weight %d, assigned %d DMA32 segments\n",
-				pe->dma_weight, segs);
-			pnv_pci_ioda_setup_dma_pe(phb, pe, base, segs);
+			pnv_pci_ioda1_setup_dma_pe(phb, pe);
 		} else if (phb->type == PNV_PHB_IODA2) {
 			pe_info(pe, "Assign DMA32 space\n");
-			segs = 0;
 			pnv_pci_ioda2_setup_dma_pe(phb, pe);
 		} else if (phb->type == PNV_PHB_NPU) {
 			/*
@@ -2548,9 +2728,6 @@ static void pnv_ioda_setup_dma(struct pn
 			 * as the PHB3 TVT.
 			 */
 		}
-
-		remaining -= segs;
-		base += segs;
 	}
 }
 
@@ -2858,7 +3035,7 @@ static void pnv_pci_ioda_fixup_iov_resou
 	pdn->m64_single_mode = false;
 
 	total_vfs = pci_sriov_get_totalvfs(pdev);
-	mul = phb->ioda.total_pe;
+	mul = phb->ioda.total_pe_num;
 	total_vf_bar_sz = 0;
 
 	for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
@@ -2929,19 +3106,72 @@ truncate_iov:
 }
 #endif /* CONFIG_PCI_IOV */
 
+static void pnv_ioda_setup_pe_res(struct pnv_ioda_pe *pe,
+				  struct resource *res)
+{
+	struct pnv_phb *phb = pe->phb;
+	struct pci_bus_region region;
+	int index;
+	int64_t rc;
+
+	if (!res || !res->flags || res->start > res->end)
+		return;
+
+	if (res->flags & IORESOURCE_IO) {
+		region.start = res->start - phb->ioda.io_pci_base;
+		region.end   = res->end - phb->ioda.io_pci_base;
+		index = region.start / phb->ioda.io_segsize;
+
+		while (index < phb->ioda.total_pe_num &&
+		       region.start <= region.end) {
+			phb->ioda.io_segmap[index] = pe->pe_number;
+			rc = opal_pci_map_pe_mmio_window(phb->opal_id,
+				pe->pe_number, OPAL_IO_WINDOW_TYPE, 0, index);
+			if (rc != OPAL_SUCCESS) {
+				pr_err("%s: Error %lld mapping IO segment#%d to PE#%d\n",
+				       __func__, rc, index, pe->pe_number);
+				break;
+			}
+
+			region.start += phb->ioda.io_segsize;
+			index++;
+		}
+	} else if ((res->flags & IORESOURCE_MEM) &&
+		   !pnv_pci_is_mem_pref_64(res->flags)) {
+		region.start = res->start -
+			       phb->hose->mem_offset[0] -
+			       phb->ioda.m32_pci_base;
+		region.end   = res->end -
+			       phb->hose->mem_offset[0] -
+			       phb->ioda.m32_pci_base;
+		index = region.start / phb->ioda.m32_segsize;
+
+		while (index < phb->ioda.total_pe_num &&
+		       region.start <= region.end) {
+			phb->ioda.m32_segmap[index] = pe->pe_number;
+			rc = opal_pci_map_pe_mmio_window(phb->opal_id,
+				pe->pe_number, OPAL_M32_WINDOW_TYPE, 0, index);
+			if (rc != OPAL_SUCCESS) {
+				pr_err("%s: Error %lld mapping M32 segment#%d to PE#%d",
+				       __func__, rc, index, pe->pe_number);
+				break;
+			}
+
+			region.start += phb->ioda.m32_segsize;
+			index++;
+		}
+	}
+}
+
 /*
  * This function is supposed to be called on basis of PE from top
  * to bottom style. So the the I/O or MMIO segment assigned to
  * parent PE could be overrided by its child PEs if necessary.
  */
-static void pnv_ioda_setup_pe_seg(struct pci_controller *hose,
-				  struct pnv_ioda_pe *pe)
+static void pnv_ioda_setup_pe_seg(struct pnv_ioda_pe *pe)
 {
-	struct pnv_phb *phb = hose->private_data;
-	struct pci_bus_region region;
-	struct resource *res;
-	int i, index;
-	int rc;
+	struct pci_dev *pdev;
+	int i;
 
 	/*
 	 * NOTE: We only care PCI bus based PE for now. For PCI
@@ -2950,57 +3180,20 @@ static void pnv_ioda_setup_pe_seg(struct
 	 */
 	BUG_ON(!(pe->flags & (PNV_IODA_PE_BUS | PNV_IODA_PE_BUS_ALL)));
 
-	pci_bus_for_each_resource(pe->pbus, res, i) {
-		if (!res || !res->flags ||
-		    res->start > res->end)
-			continue;
-
-		if (res->flags & IORESOURCE_IO) {
-			region.start = res->start - phb->ioda.io_pci_base;
-			region.end   = res->end - phb->ioda.io_pci_base;
-			index = region.start / phb->ioda.io_segsize;
-
-			while (index < phb->ioda.total_pe &&
-			       region.start <= region.end) {
-				phb->ioda.io_segmap[index] = pe->pe_number;
-				rc = opal_pci_map_pe_mmio_window(phb->opal_id,
-					pe->pe_number, OPAL_IO_WINDOW_TYPE, 0, index);
-				if (rc != OPAL_SUCCESS) {
-					pr_err("%s: OPAL error %d when mapping IO "
-					       "segment #%d to PE#%d\n",
-					       __func__, rc, index, pe->pe_number);
-					break;
-				}
-
-				region.start += phb->ioda.io_segsize;
-				index++;
-			}
-		} else if ((res->flags & IORESOURCE_MEM) &&
-			   !pnv_pci_is_mem_pref_64(res->flags)) {
-			region.start = res->start -
-				       hose->mem_offset[0] -
-				       phb->ioda.m32_pci_base;
-			region.end   = res->end -
-				       hose->mem_offset[0] -
-				       phb->ioda.m32_pci_base;
-			index = region.start / phb->ioda.m32_segsize;
-
-			while (index < phb->ioda.total_pe &&
-			       region.start <= region.end) {
-				phb->ioda.m32_segmap[index] = pe->pe_number;
-				rc = opal_pci_map_pe_mmio_window(phb->opal_id,
-					pe->pe_number, OPAL_M32_WINDOW_TYPE, 0, index);
-				if (rc != OPAL_SUCCESS) {
-					pr_err("%s: OPAL error %d when mapping M32 "
-					       "segment#%d to PE#%d",
-					       __func__, rc, index, pe->pe_number);
-					break;
-				}
+	list_for_each_entry(pdev, &pe->pbus->devices, bus_list) {
+		for (i = 0; i <= PCI_ROM_RESOURCE; i++)
+			pnv_ioda_setup_pe_res(pe, &pdev->resource[i]);
 
-				region.start += phb->ioda.m32_segsize;
-				index++;
-			}
-		}
+		/*
+		 * If the PE contains all subordinate PCI buses, the
+		 * windows of the child bridges should be mapped to
+		 * the PE as well.
+		 */
+		if (!(pe->flags & PNV_IODA_PE_BUS_ALL) || !pci_is_bridge(pdev))
+			continue;
+		for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++)
+			pnv_ioda_setup_pe_res(pe,
+				&pdev->resource[PCI_BRIDGE_RESOURCES + i]);
 	}
 }
 
@@ -3018,7 +3211,7 @@ static void pnv_pci_ioda_setup_seg(void)
 			continue;
 
 		list_for_each_entry(pe, &phb->ioda.pe_list, list) {
-			pnv_ioda_setup_pe_seg(hose, pe);
+			pnv_ioda_setup_pe_seg(pe);
 		}
 	}
 }
@@ -3035,6 +3228,8 @@ static void pnv_pci_ioda_setup_DMA(void)
 		phb = hose->private_data;
 		phb->initialized = 1;
 	}
+
+	pnv_pci_ioda_setup_iommu_api();
 }
 
 static void pnv_pci_ioda_create_dbgfs(void)
@@ -3056,27 +3251,6 @@ static void pnv_pci_ioda_create_dbgfs(vo
 #endif /* CONFIG_DEBUG_FS */
 }
 
-static void pnv_npu_ioda_fixup(void)
-{
-	bool enable_bypass;
-	struct pci_controller *hose, *tmp;
-	struct pnv_phb *phb;
-	struct pnv_ioda_pe *pe;
-
-	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
-		phb = hose->private_data;
-		if (phb->type != PNV_PHB_NPU)
-			continue;
-
-		list_for_each_entry(pe, &phb->ioda.pe_dma_list, dma_link) {
-			enable_bypass = dma_get_mask(&pe->pdev->dev) ==
-				DMA_BIT_MASK(64);
-			pnv_npu_init_dma_pe(pe);
-			pnv_npu_dma_set_bypass(pe, enable_bypass);
-		}
-	}
-}
-
 static void pnv_pci_ioda_fixup(void)
 {
 	pnv_pci_ioda_setup_PEs();
@@ -3089,9 +3263,6 @@ static void pnv_pci_ioda_fixup(void)
 	eeh_init();
 	eeh_addr_cache_build();
 #endif
-
-	/* Link NPU IODA tables to their PCI devices. */
-	pnv_npu_ioda_fixup();
 }
 
 /*
@@ -3195,12 +3366,6 @@ static bool pnv_pci_enable_device_hook(s
 	return true;
 }
 
-static u32 pnv_ioda_bdfn_to_pe(struct pnv_phb *phb, struct pci_bus *bus,
-			       u32 devfn)
-{
-	return phb->ioda.pe_rmap[(bus->number << 8) | devfn];
-}
-
 static void pnv_pci_ioda_shutdown(struct pci_controller *hose)
 {
 	struct pnv_phb *phb = hose->private_data;
@@ -3210,31 +3375,39 @@ static void pnv_pci_ioda_shutdown(struct
 }
 
 static const struct pci_controller_ops pnv_pci_ioda_controller_ops = {
-       .dma_dev_setup = pnv_pci_dma_dev_setup,
-       .dma_bus_setup = pnv_pci_dma_bus_setup,
+	.dma_dev_setup		= pnv_pci_dma_dev_setup,
+	.dma_bus_setup		= pnv_pci_dma_bus_setup,
 #ifdef CONFIG_PCI_MSI
-       .setup_msi_irqs = pnv_setup_msi_irqs,
-       .teardown_msi_irqs = pnv_teardown_msi_irqs,
+	.setup_msi_irqs		= pnv_setup_msi_irqs,
+	.teardown_msi_irqs	= pnv_teardown_msi_irqs,
 #endif
-       .enable_device_hook = pnv_pci_enable_device_hook,
-       .window_alignment = pnv_pci_window_alignment,
-       .reset_secondary_bus = pnv_pci_reset_secondary_bus,
-       .dma_set_mask = pnv_pci_ioda_dma_set_mask,
-       .dma_get_required_mask = pnv_pci_ioda_dma_get_required_mask,
-       .shutdown = pnv_pci_ioda_shutdown,
+	.enable_device_hook	= pnv_pci_enable_device_hook,
+	.window_alignment	= pnv_pci_window_alignment,
+	.reset_secondary_bus	= pnv_pci_reset_secondary_bus,
+	.dma_set_mask		= pnv_pci_ioda_dma_set_mask,
+	.dma_get_required_mask	= pnv_pci_ioda_dma_get_required_mask,
+	.shutdown		= pnv_pci_ioda_shutdown,
 };
 
+static int pnv_npu_dma_set_mask(struct pci_dev *npdev, u64 dma_mask)
+{
+	dev_err_once(&npdev->dev,
+			"%s operation unsupported for NVLink devices\n",
+			__func__);
+	return -EPERM;
+}
+
 static const struct pci_controller_ops pnv_npu_ioda_controller_ops = {
-	.dma_dev_setup = pnv_pci_dma_dev_setup,
+	.dma_dev_setup		= pnv_pci_dma_dev_setup,
 #ifdef CONFIG_PCI_MSI
-	.setup_msi_irqs = pnv_setup_msi_irqs,
-	.teardown_msi_irqs = pnv_teardown_msi_irqs,
+	.setup_msi_irqs		= pnv_setup_msi_irqs,
+	.teardown_msi_irqs	= pnv_teardown_msi_irqs,
 #endif
-	.enable_device_hook = pnv_pci_enable_device_hook,
-	.window_alignment = pnv_pci_window_alignment,
-	.reset_secondary_bus = pnv_pci_reset_secondary_bus,
-	.dma_set_mask = pnv_npu_dma_set_mask,
-	.shutdown = pnv_pci_ioda_shutdown,
+	.enable_device_hook	= pnv_pci_enable_device_hook,
+	.window_alignment	= pnv_pci_window_alignment,
+	.reset_secondary_bus	= pnv_pci_reset_secondary_bus,
+	.dma_set_mask		= pnv_npu_dma_set_mask,
+	.shutdown		= pnv_pci_ioda_shutdown,
 };
 
 static void __init pnv_pci_init_ioda_phb(struct device_node *np,
@@ -3242,10 +3415,12 @@ static void __init pnv_pci_init_ioda_phb
 {
 	struct pci_controller *hose;
 	struct pnv_phb *phb;
-	unsigned long size, m32map_off, pemap_off, iomap_off = 0;
+	unsigned long size, m64map_off, m32map_off, pemap_off;
+	unsigned long iomap_off = 0, dma32map_off = 0;
 	const __be64 *prop64;
 	const __be32 *prop32;
 	int len;
+	unsigned int segno;
 	u64 phb_id;
 	void *aux;
 	long rc;
@@ -3306,13 +3481,13 @@ static void __init pnv_pci_init_ioda_phb
 		pr_err("  Failed to map registers !\n");
 
 	/* Initialize more IODA stuff */
-	phb->ioda.total_pe = 1;
+	phb->ioda.total_pe_num = 1;
 	prop32 = of_get_property(np, "ibm,opal-num-pes", NULL);
 	if (prop32)
-		phb->ioda.total_pe = be32_to_cpup(prop32);
+		phb->ioda.total_pe_num = be32_to_cpup(prop32);
 	prop32 = of_get_property(np, "ibm,opal-reserved-pe", NULL);
 	if (prop32)
-		phb->ioda.reserved_pe = be32_to_cpup(prop32);
+		phb->ioda.reserved_pe_idx = be32_to_cpup(prop32);
 
 	/* Parse 64-bit MMIO range */
 	pnv_ioda_parse_m64_window(phb);
@@ -3321,36 +3496,58 @@ static void __init pnv_pci_init_ioda_phb
 	/* FW Has already off top 64k of M32 space (MSI space) */
 	phb->ioda.m32_size += 0x10000;
 
-	phb->ioda.m32_segsize = phb->ioda.m32_size / phb->ioda.total_pe;
+	phb->ioda.m32_segsize = phb->ioda.m32_size / phb->ioda.total_pe_num;
 	phb->ioda.m32_pci_base = hose->mem_resources[0].start - hose->mem_offset[0];
 	phb->ioda.io_size = hose->pci_io_size;
-	phb->ioda.io_segsize = phb->ioda.io_size / phb->ioda.total_pe;
+	phb->ioda.io_segsize = phb->ioda.io_size / phb->ioda.total_pe_num;
 	phb->ioda.io_pci_base = 0; /* XXX calculate this ? */
 
+	/* Calculate how many 32-bit TCE segments we have */
+	phb->ioda.dma32_count = phb->ioda.m32_pci_base /
+				PNV_IODA1_DMA32_SEGSIZE;
+
 	/* Allocate aux data & arrays. We don't have IO ports on PHB3 */
-	size = _ALIGN_UP(phb->ioda.total_pe / 8, sizeof(unsigned long));
+	size = _ALIGN_UP(max_t(unsigned, phb->ioda.total_pe_num, 8) / 8,
+			sizeof(unsigned long));
+	m64map_off = size;
+	size += phb->ioda.total_pe_num * sizeof(phb->ioda.m64_segmap[0]);
 	m32map_off = size;
-	size += phb->ioda.total_pe * sizeof(phb->ioda.m32_segmap[0]);
+	size += phb->ioda.total_pe_num * sizeof(phb->ioda.m32_segmap[0]);
 	if (phb->type == PNV_PHB_IODA1) {
 		iomap_off = size;
-		size += phb->ioda.total_pe * sizeof(phb->ioda.io_segmap[0]);
+		size += phb->ioda.total_pe_num * sizeof(phb->ioda.io_segmap[0]);
+		dma32map_off = size;
+		size += phb->ioda.dma32_count *
+			sizeof(phb->ioda.dma32_segmap[0]);
 	}
 	pemap_off = size;
-	size += phb->ioda.total_pe * sizeof(struct pnv_ioda_pe);
+	size += phb->ioda.total_pe_num * sizeof(struct pnv_ioda_pe);
 	aux = memblock_virt_alloc(size, 0);
 	phb->ioda.pe_alloc = aux;
+	phb->ioda.m64_segmap = aux + m64map_off;
 	phb->ioda.m32_segmap = aux + m32map_off;
-	if (phb->type == PNV_PHB_IODA1)
+	for (segno = 0; segno < phb->ioda.total_pe_num; segno++) {
+		phb->ioda.m64_segmap[segno] = IODA_INVALID_PE;
+		phb->ioda.m32_segmap[segno] = IODA_INVALID_PE;
+	}
+	if (phb->type == PNV_PHB_IODA1) {
 		phb->ioda.io_segmap = aux + iomap_off;
+		for (segno = 0; segno < phb->ioda.total_pe_num; segno++)
+			phb->ioda.io_segmap[segno] = IODA_INVALID_PE;
+
+		phb->ioda.dma32_segmap = aux + dma32map_off;
+		for (segno = 0; segno < phb->ioda.dma32_count; segno++)
+			phb->ioda.dma32_segmap[segno] = IODA_INVALID_PE;
+	}
 	phb->ioda.pe_array = aux + pemap_off;
-	set_bit(phb->ioda.reserved_pe, phb->ioda.pe_alloc);
+	set_bit(phb->ioda.reserved_pe_idx, phb->ioda.pe_alloc);
 
-	INIT_LIST_HEAD(&phb->ioda.pe_dma_list);
 	INIT_LIST_HEAD(&phb->ioda.pe_list);
 	mutex_init(&phb->ioda.pe_list_mutex);
 
 	/* Calculate how many 32-bit TCE segments we have */
-	phb->ioda.tce32_count = phb->ioda.m32_pci_base >> 28;
+	phb->ioda.dma32_count = phb->ioda.m32_pci_base /
+				PNV_IODA1_DMA32_SEGSIZE;
 
 #if 0 /* We should really do that ... */
 	rc = opal_pci_set_phb_mem_window(opal->phb_id,
@@ -3362,7 +3559,7 @@ static void __init pnv_pci_init_ioda_phb
 #endif
 
 	pr_info("  %03d (%03d) PE's M32: 0x%x [segment=0x%x]\n",
-		phb->ioda.total_pe, phb->ioda.reserved_pe,
+		phb->ioda.total_pe_num, phb->ioda.reserved_pe_idx,
 		phb->ioda.m32_size, phb->ioda.m32_segsize);
 	if (phb->ioda.m64_size)
 		pr_info("                 M64: 0x%lx [segment=0x%lx]\n",
@@ -3377,12 +3574,6 @@ static void __init pnv_pci_init_ioda_phb
 	phb->freeze_pe = pnv_ioda_freeze_pe;
 	phb->unfreeze_pe = pnv_ioda_unfreeze_pe;
 
-	/* Setup RID -> PE mapping function */
-	phb->bdfn_to_pe = pnv_ioda_bdfn_to_pe;
-
-	/* Setup TCEs */
-	phb->dma_dev_setup = pnv_pci_ioda_dma_dev_setup;
-
 	/* Setup MSI support */
 	pnv_pci_init_ioda_msis(phb);
 
@@ -3395,10 +3586,12 @@ static void __init pnv_pci_init_ioda_phb
 	 */
 	ppc_md.pcibios_fixup = pnv_pci_ioda_fixup;
 
-	if (phb->type == PNV_PHB_NPU)
+	if (phb->type == PNV_PHB_NPU) {
 		hose->controller_ops = pnv_npu_ioda_controller_ops;
-	else
+	} else {
+		phb->dma_dev_setup = pnv_pci_ioda_dma_dev_setup;
 		hose->controller_ops = pnv_pci_ioda_controller_ops;
+	}
 
 #ifdef CONFIG_PCI_IOV
 	ppc_md.pcibios_fixup_sriov = pnv_pci_ioda_fixup_iov_resources;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/platforms/powernv/setup.c linux-libre-4.7-gnu/arch/powerpc/platforms/powernv/setup.c
--- linux-libre-4.6-gnu/arch/powerpc/platforms/powernv/setup.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/platforms/powernv/setup.c	2016-07-24 15:23:50.000000000 -0400
@@ -273,7 +273,10 @@ static int __init pnv_probe(void)
 	if (!of_flat_dt_is_compatible(root, "ibm,powernv"))
 		return 0;
 
-	hpte_init_native();
+	if (IS_ENABLED(CONFIG_PPC_RADIX_MMU) && radix_enabled())
+		radix_init_native();
+	else if (IS_ENABLED(CONFIG_PPC_STD_MMU_64))
+		hpte_init_native();
 
 	if (firmware_has_feature(FW_FEATURE_OPAL))
 		pnv_setup_machdep_opal();
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/platforms/ps3/htab.c linux-libre-4.7-gnu/arch/powerpc/platforms/ps3/htab.c
--- linux-libre-4.6-gnu/arch/powerpc/platforms/ps3/htab.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/platforms/ps3/htab.c	2016-07-24 15:23:50.000000000 -0400
@@ -63,7 +63,7 @@ static long ps3_hpte_insert(unsigned lon
 	vflags &= ~HPTE_V_SECONDARY;
 
 	hpte_v = hpte_encode_v(vpn, psize, apsize, ssize) | vflags | HPTE_V_VALID;
-	hpte_r = hpte_encode_r(ps3_mm_phys_to_lpar(pa), psize, apsize) | rflags;
+	hpte_r = hpte_encode_r(ps3_mm_phys_to_lpar(pa), psize, apsize, ssize) | rflags;
 
 	spin_lock_irqsave(&ps3_htab_lock, flags);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/platforms/ps3/spu.c linux-libre-4.7-gnu/arch/powerpc/platforms/ps3/spu.c
--- linux-libre-4.6-gnu/arch/powerpc/platforms/ps3/spu.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/platforms/ps3/spu.c	2016-07-24 15:23:50.000000000 -0400
@@ -205,7 +205,7 @@ static void spu_unmap(struct spu *spu)
 static int __init setup_areas(struct spu *spu)
 {
 	struct table {char* name; unsigned long addr; unsigned long size;};
-	static const unsigned long shadow_flags = _PAGE_NO_CACHE | 3;
+	unsigned long shadow_flags = pgprot_val(pgprot_noncached_wc(PAGE_KERNEL_RO));
 
 	spu_pdata(spu)->shadow = __ioremap(spu_pdata(spu)->shadow_addr,
 					   sizeof(struct spe_shadow),
@@ -216,7 +216,7 @@ static int __init setup_areas(struct spu
 	}
 
 	spu->local_store = (__force void *)ioremap_prot(spu->local_store_phys,
-		LS_SIZE, _PAGE_NO_CACHE);
+		LS_SIZE, pgprot_val(pgprot_noncached_wc(__pgprot(0))));
 
 	if (!spu->local_store) {
 		pr_debug("%s:%d: ioremap local_store failed\n",
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/platforms/pseries/eeh_pseries.c linux-libre-4.7-gnu/arch/powerpc/platforms/pseries/eeh_pseries.c
--- linux-libre-4.6-gnu/arch/powerpc/platforms/pseries/eeh_pseries.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/platforms/pseries/eeh_pseries.c	2016-07-24 15:23:50.000000000 -0400
@@ -53,7 +53,6 @@ static int ibm_read_slot_reset_state2;
 static int ibm_slot_error_detail;
 static int ibm_get_config_addr_info;
 static int ibm_get_config_addr_info2;
-static int ibm_configure_bridge;
 static int ibm_configure_pe;
 
 /*
@@ -81,7 +80,14 @@ static int pseries_eeh_init(void)
 	ibm_get_config_addr_info2	= rtas_token("ibm,get-config-addr-info2");
 	ibm_get_config_addr_info	= rtas_token("ibm,get-config-addr-info");
 	ibm_configure_pe		= rtas_token("ibm,configure-pe");
-	ibm_configure_bridge		= rtas_token("ibm,configure-bridge");
+
+	/*
+	 * ibm,configure-pe and ibm,configure-bridge have the same semantics,
+	 * however ibm,configure-pe can be faster.  If we can't find
+	 * ibm,configure-pe then fall back to using ibm,configure-bridge.
+	 */
+	if (ibm_configure_pe == RTAS_UNKNOWN_SERVICE)
+		ibm_configure_pe 	= rtas_token("ibm,configure-bridge");
 
 	/*
 	 * Necessary sanity check. We needn't check "get-config-addr-info"
@@ -93,8 +99,7 @@ static int pseries_eeh_init(void)
 	    (ibm_read_slot_reset_state2 == RTAS_UNKNOWN_SERVICE &&
 	     ibm_read_slot_reset_state == RTAS_UNKNOWN_SERVICE)	||
 	    ibm_slot_error_detail == RTAS_UNKNOWN_SERVICE	||
-	    (ibm_configure_pe == RTAS_UNKNOWN_SERVICE		&&
-	     ibm_configure_bridge == RTAS_UNKNOWN_SERVICE)) {
+	    ibm_configure_pe == RTAS_UNKNOWN_SERVICE) {
 		pr_info("EEH functionality not supported\n");
 		return -EINVAL;
 	}
@@ -615,29 +620,41 @@ static int pseries_eeh_configure_bridge(
 {
 	int config_addr;
 	int ret;
+	/* Waiting 0.2s maximum before skipping configuration */
+	int max_wait = 200;
 
 	/* Figure out the PE address */
 	config_addr = pe->config_addr;
 	if (pe->addr)
 		config_addr = pe->addr;
 
-	/* Use new configure-pe function, if supported */
-	if (ibm_configure_pe != RTAS_UNKNOWN_SERVICE) {
+	while (max_wait > 0) {
 		ret = rtas_call(ibm_configure_pe, 3, 1, NULL,
 				config_addr, BUID_HI(pe->phb->buid),
 				BUID_LO(pe->phb->buid));
-	} else if (ibm_configure_bridge != RTAS_UNKNOWN_SERVICE) {
-		ret = rtas_call(ibm_configure_bridge, 3, 1, NULL,
-				config_addr, BUID_HI(pe->phb->buid),
-				BUID_LO(pe->phb->buid));
-	} else {
-		return -EFAULT;
-	}
 
-	if (ret)
-		pr_warn("%s: Unable to configure bridge PHB#%d-PE#%x (%d)\n",
-			__func__, pe->phb->global_number, pe->addr, ret);
+		if (!ret)
+			return ret;
+
+		/*
+		 * If RTAS returns a delay value that's above 100ms, cut it
+		 * down to 100ms in case firmware made a mistake.  For more
+		 * on how these delay values work see rtas_busy_delay_time
+		 */
+		if (ret > RTAS_EXTENDED_DELAY_MIN+2 &&
+		    ret <= RTAS_EXTENDED_DELAY_MAX)
+			ret = RTAS_EXTENDED_DELAY_MIN+2;
+
+		max_wait -= rtas_busy_delay_time(ret);
+
+		if (max_wait < 0)
+			break;
+
+		rtas_busy_delay(ret);
+	}
 
+	pr_warn("%s: Unable to configure bridge PHB#%d-PE#%x (%d)\n",
+		__func__, pe->phb->global_number, pe->addr, ret);
 	return ret;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/platforms/pseries/hotplug-memory.c linux-libre-4.7-gnu/arch/powerpc/platforms/pseries/hotplug-memory.c
--- linux-libre-4.6-gnu/arch/powerpc/platforms/pseries/hotplug-memory.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/platforms/pseries/hotplug-memory.c	2016-07-24 15:23:50.000000000 -0400
@@ -116,6 +116,155 @@ static struct property *dlpar_clone_drco
 	return new_prop;
 }
 
+static void dlpar_update_drconf_property(struct device_node *dn,
+					 struct property *prop)
+{
+	struct of_drconf_cell *lmbs;
+	u32 num_lmbs, *p;
+	int i;
+
+	/* Convert the property back to BE */
+	p = prop->value;
+	num_lmbs = *p;
+	*p = cpu_to_be32(*p);
+	p++;
+
+	lmbs = (struct of_drconf_cell *)p;
+	for (i = 0; i < num_lmbs; i++) {
+		lmbs[i].base_addr = cpu_to_be64(lmbs[i].base_addr);
+		lmbs[i].drc_index = cpu_to_be32(lmbs[i].drc_index);
+		lmbs[i].flags = cpu_to_be32(lmbs[i].flags);
+	}
+
+	rtas_hp_event = true;
+	of_update_property(dn, prop);
+	rtas_hp_event = false;
+}
+
+static int dlpar_update_device_tree_lmb(struct of_drconf_cell *lmb)
+{
+	struct device_node *dn;
+	struct property *prop;
+	struct of_drconf_cell *lmbs;
+	u32 *p, num_lmbs;
+	int i;
+
+	dn = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
+	if (!dn)
+		return -ENODEV;
+
+	prop = dlpar_clone_drconf_property(dn);
+	if (!prop) {
+		of_node_put(dn);
+		return -ENODEV;
+	}
+
+	p = prop->value;
+	num_lmbs = *p++;
+	lmbs = (struct of_drconf_cell *)p;
+
+	for (i = 0; i < num_lmbs; i++) {
+		if (lmbs[i].drc_index == lmb->drc_index) {
+			lmbs[i].flags = lmb->flags;
+			lmbs[i].aa_index = lmb->aa_index;
+
+			dlpar_update_drconf_property(dn, prop);
+			break;
+		}
+	}
+
+	of_node_put(dn);
+	return 0;
+}
+
+static u32 lookup_lmb_associativity_index(struct of_drconf_cell *lmb)
+{
+	struct device_node *parent, *lmb_node, *dr_node;
+	const u32 *lmb_assoc;
+	const u32 *assoc_arrays;
+	u32 aa_index;
+	int aa_arrays, aa_array_entries, aa_array_sz;
+	int i;
+
+	parent = of_find_node_by_path("/");
+	if (!parent)
+		return -ENODEV;
+
+	lmb_node = dlpar_configure_connector(cpu_to_be32(lmb->drc_index),
+					     parent);
+	of_node_put(parent);
+	if (!lmb_node)
+		return -EINVAL;
+
+	lmb_assoc = of_get_property(lmb_node, "ibm,associativity", NULL);
+	if (!lmb_assoc) {
+		dlpar_free_cc_nodes(lmb_node);
+		return -ENODEV;
+	}
+
+	dr_node = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
+	if (!dr_node) {
+		dlpar_free_cc_nodes(lmb_node);
+		return -ENODEV;
+	}
+
+	assoc_arrays = of_get_property(dr_node,
+				       "ibm,associativity-lookup-arrays",
+				       NULL);
+	of_node_put(dr_node);
+	if (!assoc_arrays) {
+		dlpar_free_cc_nodes(lmb_node);
+		return -ENODEV;
+	}
+
+	/* The ibm,associativity-lookup-arrays property is defined to be
+	 * a 32-bit value specifying the number of associativity arrays
+	 * followed by a 32-bitvalue specifying the number of entries per
+	 * array, followed by the associativity arrays.
+	 */
+	aa_arrays = be32_to_cpu(assoc_arrays[0]);
+	aa_array_entries = be32_to_cpu(assoc_arrays[1]);
+	aa_array_sz = aa_array_entries * sizeof(u32);
+
+	aa_index = -1;
+	for (i = 0; i < aa_arrays; i++) {
+		int indx = (i * aa_array_entries) + 2;
+
+		if (memcmp(&assoc_arrays[indx], &lmb_assoc[1], aa_array_sz))
+			continue;
+
+		aa_index = i;
+		break;
+	}
+
+	dlpar_free_cc_nodes(lmb_node);
+	return aa_index;
+}
+
+static int dlpar_add_device_tree_lmb(struct of_drconf_cell *lmb)
+{
+	int aa_index;
+
+	lmb->flags |= DRCONF_MEM_ASSIGNED;
+
+	aa_index = lookup_lmb_associativity_index(lmb);
+	if (aa_index < 0) {
+		pr_err("Couldn't find associativity index for drc index %x\n",
+		       lmb->drc_index);
+		return aa_index;
+	}
+
+	lmb->aa_index = aa_index;
+	return dlpar_update_device_tree_lmb(lmb);
+}
+
+static int dlpar_remove_device_tree_lmb(struct of_drconf_cell *lmb)
+{
+	lmb->flags &= ~DRCONF_MEM_ASSIGNED;
+	lmb->aa_index = 0xffffffff;
+	return dlpar_update_device_tree_lmb(lmb);
+}
+
 static struct memory_block *lmb_to_memblock(struct of_drconf_cell *lmb)
 {
 	unsigned long section_nr;
@@ -243,8 +392,8 @@ static int dlpar_remove_lmb(struct of_dr
 	memblock_remove(lmb->base_addr, block_sz);
 
 	dlpar_release_drc(lmb->drc_index);
+	dlpar_remove_device_tree_lmb(lmb);
 
-	lmb->flags &= ~DRCONF_MEM_ASSIGNED;
 	return 0;
 }
 
@@ -384,43 +533,32 @@ static int dlpar_memory_remove_by_index(
 
 #endif /* CONFIG_MEMORY_HOTREMOVE */
 
-static int dlpar_add_lmb(struct of_drconf_cell *lmb)
+static int dlpar_add_lmb_memory(struct of_drconf_cell *lmb)
 {
 	struct memory_block *mem_block;
 	unsigned long block_sz;
 	int nid, rc;
 
-	if (lmb->flags & DRCONF_MEM_ASSIGNED)
-		return -EINVAL;
-
 	block_sz = memory_block_size_bytes();
 
-	rc = dlpar_acquire_drc(lmb->drc_index);
-	if (rc)
-		return rc;
-
 	/* Find the node id for this address */
 	nid = memory_add_physaddr_to_nid(lmb->base_addr);
 
 	/* Add the memory */
 	rc = add_memory(nid, lmb->base_addr, block_sz);
-	if (rc) {
-		dlpar_release_drc(lmb->drc_index);
+	if (rc)
 		return rc;
-	}
 
 	/* Register this block of memory */
 	rc = memblock_add(lmb->base_addr, block_sz);
 	if (rc) {
 		remove_memory(nid, lmb->base_addr, block_sz);
-		dlpar_release_drc(lmb->drc_index);
 		return rc;
 	}
 
 	mem_block = lmb_to_memblock(lmb);
 	if (!mem_block) {
 		remove_memory(nid, lmb->base_addr, block_sz);
-		dlpar_release_drc(lmb->drc_index);
 		return -EINVAL;
 	}
 
@@ -428,7 +566,6 @@ static int dlpar_add_lmb(struct of_drcon
 	put_device(&mem_block->dev);
 	if (rc) {
 		remove_memory(nid, lmb->base_addr, block_sz);
-		dlpar_release_drc(lmb->drc_index);
 		return rc;
 	}
 
@@ -436,6 +573,34 @@ static int dlpar_add_lmb(struct of_drcon
 	return 0;
 }
 
+static int dlpar_add_lmb(struct of_drconf_cell *lmb)
+{
+	int rc;
+
+	if (lmb->flags & DRCONF_MEM_ASSIGNED)
+		return -EINVAL;
+
+	rc = dlpar_acquire_drc(lmb->drc_index);
+	if (rc)
+		return rc;
+
+	rc = dlpar_add_device_tree_lmb(lmb);
+	if (rc) {
+		pr_err("Couldn't update device tree for drc index %x\n",
+		       lmb->drc_index);
+		dlpar_release_drc(lmb->drc_index);
+		return rc;
+	}
+
+	rc = dlpar_add_lmb_memory(lmb);
+	if (rc) {
+		dlpar_remove_device_tree_lmb(lmb);
+		dlpar_release_drc(lmb->drc_index);
+	}
+
+	return rc;
+}
+
 static int dlpar_memory_add_by_count(u32 lmbs_to_add, struct property *prop)
 {
 	struct of_drconf_cell *lmbs;
@@ -536,31 +701,6 @@ static int dlpar_memory_add_by_index(u32
 	return rc;
 }
 
-static void dlpar_update_drconf_property(struct device_node *dn,
-					 struct property *prop)
-{
-	struct of_drconf_cell *lmbs;
-	u32 num_lmbs, *p;
-	int i;
-
-	/* Convert the property back to BE */
-	p = prop->value;
-	num_lmbs = *p;
-	*p = cpu_to_be32(*p);
-	p++;
-
-	lmbs = (struct of_drconf_cell *)p;
-	for (i = 0; i < num_lmbs; i++) {
-		lmbs[i].base_addr = cpu_to_be64(lmbs[i].base_addr);
-		lmbs[i].drc_index = cpu_to_be32(lmbs[i].drc_index);
-		lmbs[i].flags = cpu_to_be32(lmbs[i].flags);
-	}
-
-	rtas_hp_event = true;
-	of_update_property(dn, prop);
-	rtas_hp_event = false;
-}
-
 int dlpar_memory(struct pseries_hp_errorlog *hp_elog)
 {
 	struct device_node *dn;
@@ -608,10 +748,7 @@ int dlpar_memory(struct pseries_hp_error
 		break;
 	}
 
-	if (rc)
-		dlpar_free_drconf_property(prop);
-	else
-		dlpar_update_drconf_property(dn, prop);
+	dlpar_free_drconf_property(prop);
 
 dlpar_memory_out:
 	of_node_put(dn);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/platforms/pseries/iommu.c linux-libre-4.7-gnu/arch/powerpc/platforms/pseries/iommu.c
--- linux-libre-4.6-gnu/arch/powerpc/platforms/pseries/iommu.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/platforms/pseries/iommu.c	2016-07-24 15:23:50.000000000 -0400
@@ -912,7 +912,8 @@ machine_arch_initcall(pseries, find_exis
 static int query_ddw(struct pci_dev *dev, const u32 *ddw_avail,
 			struct ddw_query_response *query)
 {
-	struct eeh_dev *edev;
+	struct device_node *dn;
+	struct pci_dn *pdn;
 	u32 cfg_addr;
 	u64 buid;
 	int ret;
@@ -923,11 +924,10 @@ static int query_ddw(struct pci_dev *dev
 	 * Retrieve them from the pci device, not the node with the
 	 * dma-window property
 	 */
-	edev = pci_dev_to_eeh_dev(dev);
-	cfg_addr = edev->config_addr;
-	if (edev->pe_config_addr)
-		cfg_addr = edev->pe_config_addr;
-	buid = edev->phb->buid;
+	dn = pci_device_to_OF_node(dev);
+	pdn = PCI_DN(dn);
+	buid = pdn->phb->buid;
+	cfg_addr = ((pdn->busno << 16) | (pdn->devfn << 8));
 
 	ret = rtas_call(ddw_avail[0], 3, 5, (u32 *)query,
 		  cfg_addr, BUID_HI(buid), BUID_LO(buid));
@@ -941,7 +941,8 @@ static int create_ddw(struct pci_dev *de
 			struct ddw_create_response *create, int page_shift,
 			int window_shift)
 {
-	struct eeh_dev *edev;
+	struct device_node *dn;
+	struct pci_dn *pdn;
 	u32 cfg_addr;
 	u64 buid;
 	int ret;
@@ -952,11 +953,10 @@ static int create_ddw(struct pci_dev *de
 	 * Retrieve them from the pci device, not the node with the
 	 * dma-window property
 	 */
-	edev = pci_dev_to_eeh_dev(dev);
-	cfg_addr = edev->config_addr;
-	if (edev->pe_config_addr)
-		cfg_addr = edev->pe_config_addr;
-	buid = edev->phb->buid;
+	dn = pci_device_to_OF_node(dev);
+	pdn = PCI_DN(dn);
+	buid = pdn->phb->buid;
+	cfg_addr = ((pdn->busno << 16) | (pdn->devfn << 8));
 
 	do {
 		/* extra outputs are LIOBN and dma-addr (hi, lo) */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/platforms/pseries/lpar.c linux-libre-4.7-gnu/arch/powerpc/platforms/pseries/lpar.c
--- linux-libre-4.6-gnu/arch/powerpc/platforms/pseries/lpar.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/platforms/pseries/lpar.c	2016-07-24 15:23:50.000000000 -0400
@@ -89,18 +89,21 @@ void vpa_init(int cpu)
 		       "%lx failed with %ld\n", cpu, hwcpu, addr, ret);
 		return;
 	}
+
+#ifdef CONFIG_PPC_STD_MMU_64
 	/*
 	 * PAPR says this feature is SLB-Buffer but firmware never
 	 * reports that.  All SPLPAR support SLB shadow buffer.
 	 */
-	addr = __pa(paca[cpu].slb_shadow_ptr);
-	if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
+	if (!radix_enabled() && firmware_has_feature(FW_FEATURE_SPLPAR)) {
+		addr = __pa(paca[cpu].slb_shadow_ptr);
 		ret = register_slb_shadow(hwcpu, addr);
 		if (ret)
 			pr_err("WARNING: SLB shadow buffer registration for "
 			       "cpu %d (hw %d) of area %lx failed with %ld\n",
 			       cpu, hwcpu, addr, ret);
 	}
+#endif /* CONFIG_PPC_STD_MMU_64 */
 
 	/*
 	 * Register dispatch trace log, if one has been allocated.
@@ -123,6 +126,8 @@ void vpa_init(int cpu)
 	}
 }
 
+#ifdef CONFIG_PPC_STD_MMU_64
+
 static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
 				     unsigned long vpn, unsigned long pa,
 				     unsigned long rflags, unsigned long vflags,
@@ -139,7 +144,7 @@ static long pSeries_lpar_hpte_insert(uns
 			 hpte_group, vpn,  pa, rflags, vflags, psize);
 
 	hpte_v = hpte_encode_v(vpn, psize, apsize, ssize) | vflags | HPTE_V_VALID;
-	hpte_r = hpte_encode_r(pa, psize, apsize) | rflags;
+	hpte_r = hpte_encode_r(pa, psize, apsize, ssize) | rflags;
 
 	if (!(vflags & HPTE_V_BOLTED))
 		pr_devel(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r);
@@ -152,10 +157,6 @@ static long pSeries_lpar_hpte_insert(uns
 	/* Exact = 0                   */
 	flags = 0;
 
-	/* Make pHyp happy */
-	if ((rflags & _PAGE_NO_CACHE) && !(rflags & _PAGE_WRITETHRU))
-		hpte_r &= ~HPTE_R_M;
-
 	if (firmware_has_feature(FW_FEATURE_XCMO) && !(hpte_r & HPTE_R_N))
 		flags |= H_COALESCE_CAND;
 
@@ -659,6 +660,8 @@ static void pSeries_set_page_state(struc
 
 void arch_free_page(struct page *page, int order)
 {
+	if (radix_enabled())
+		return;
 	if (!cmo_free_hint_flag || !firmware_has_feature(FW_FEATURE_CMO))
 		return;
 
@@ -666,7 +669,8 @@ void arch_free_page(struct page *page, i
 }
 EXPORT_SYMBOL(arch_free_page);
 
-#endif
+#endif /* CONFIG_PPC_SMLPAR */
+#endif /* CONFIG_PPC_STD_MMU_64 */
 
 #ifdef CONFIG_TRACEPOINTS
 #ifdef HAVE_JUMP_LABEL
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/platforms/pseries/lparcfg.c linux-libre-4.7-gnu/arch/powerpc/platforms/pseries/lparcfg.c
--- linux-libre-4.6-gnu/arch/powerpc/platforms/pseries/lparcfg.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/platforms/pseries/lparcfg.c	2016-07-24 15:23:50.000000000 -0400
@@ -484,8 +484,9 @@ static int pseries_lparcfg_data(struct s
 	seq_printf(m, "shared_processor_mode=%d\n",
 		   lppaca_shared_proc(get_lppaca()));
 
+#ifdef CONFIG_PPC_STD_MMU_64
 	seq_printf(m, "slb_size=%d\n", mmu_slb_size);
-
+#endif
 	parse_em_data(m);
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/platforms/pseries/mobility.c linux-libre-4.7-gnu/arch/powerpc/platforms/pseries/mobility.c
--- linux-libre-4.6-gnu/arch/powerpc/platforms/pseries/mobility.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/platforms/pseries/mobility.c	2016-07-24 15:23:50.000000000 -0400
@@ -191,8 +191,8 @@ static int update_dt_node(__be32 phandle
 				break;
 
 			case 0x80000000:
-				prop = of_find_property(dn, prop_name, NULL);
-				of_remove_property(dn, prop);
+				of_remove_property(dn, of_find_property(dn,
+							prop_name, NULL));
 				prop = NULL;
 				break;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/platforms/pseries/msi.c linux-libre-4.7-gnu/arch/powerpc/platforms/pseries/msi.c
--- linux-libre-4.6-gnu/arch/powerpc/platforms/pseries/msi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/platforms/pseries/msi.c	2016-07-24 15:23:50.000000000 -0400
@@ -305,7 +305,7 @@ static int msi_quota_for_device(struct p
 	memset(&counts, 0, sizeof(struct msi_counts));
 
 	/* Work out how many devices we have below this PE */
-	traverse_pci_devices(pe_dn, count_non_bridge_devices, &counts);
+	pci_traverse_device_nodes(pe_dn, count_non_bridge_devices, &counts);
 
 	if (counts.num_devices == 0) {
 		pr_err("rtas_msi: found 0 devices under PE for %s\n",
@@ -320,7 +320,7 @@ static int msi_quota_for_device(struct p
 	/* else, we have some more calculating to do */
 	counts.requestor = pci_device_to_OF_node(dev);
 	counts.request = request;
-	traverse_pci_devices(pe_dn, count_spare_msis, &counts);
+	pci_traverse_device_nodes(pe_dn, count_spare_msis, &counts);
 
 	/* If the quota isn't an integer multiple of the total, we can
 	 * use the remainder as spare MSIs for anyone that wants them. */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/platforms/pseries/pci_dlpar.c linux-libre-4.7-gnu/arch/powerpc/platforms/pseries/pci_dlpar.c
--- linux-libre-4.6-gnu/arch/powerpc/platforms/pseries/pci_dlpar.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/platforms/pseries/pci_dlpar.c	2016-07-24 15:23:50.000000000 -0400
@@ -34,38 +34,6 @@
 
 #include "pseries.h"
 
-static struct pci_bus *
-find_bus_among_children(struct pci_bus *bus,
-                        struct device_node *dn)
-{
-	struct pci_bus *child = NULL;
-	struct pci_bus *tmp;
-	struct device_node *busdn;
-
-	busdn = pci_bus_to_OF_node(bus);
-	if (busdn == dn)
-		return bus;
-
-	list_for_each_entry(tmp, &bus->children, node) {
-		child = find_bus_among_children(tmp, dn);
-		if (child)
-			break;
-	};
-	return child;
-}
-
-struct pci_bus *
-pcibios_find_pci_bus(struct device_node *dn)
-{
-	struct pci_dn *pdn = dn->data;
-
-	if (!pdn  || !pdn->phb || !pdn->phb->bus)
-		return NULL;
-
-	return find_bus_among_children(pdn->phb->bus, dn);
-}
-EXPORT_SYMBOL_GPL(pcibios_find_pci_bus);
-
 struct pci_controller *init_phb_dynamic(struct device_node *dn)
 {
 	struct pci_controller *phb;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/platforms/pseries/reconfig.c linux-libre-4.7-gnu/arch/powerpc/platforms/pseries/reconfig.c
--- linux-libre-4.6-gnu/arch/powerpc/platforms/pseries/reconfig.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/platforms/pseries/reconfig.c	2016-07-24 15:23:50.000000000 -0400
@@ -303,7 +303,6 @@ static int do_remove_property(char *buf,
 {
 	struct device_node *np;
 	char *tmp;
-	struct property *prop;
 	buf = parse_node(buf, bufsize, &np);
 
 	if (!np)
@@ -316,9 +315,7 @@ static int do_remove_property(char *buf,
 	if (strlen(buf) == 0)
 		return -EINVAL;
 
-	prop = of_find_property(np, buf, NULL);
-
-	return of_remove_property(np, prop);
+	return of_remove_property(np, of_find_property(np, buf, NULL));
 }
 
 static int do_update_property(char *buf, size_t bufsize)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/platforms/pseries/setup.c linux-libre-4.7-gnu/arch/powerpc/platforms/pseries/setup.c
--- linux-libre-4.6-gnu/arch/powerpc/platforms/pseries/setup.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/platforms/pseries/setup.c	2016-07-24 15:23:50.000000000 -0400
@@ -235,6 +235,8 @@ static void __init pseries_discover_pic(
 
 	for_each_node_by_name(np, "interrupt-controller") {
 		typep = of_get_property(np, "compatible", NULL);
+		if (!typep)
+			continue;
 		if (strstr(typep, "open-pic")) {
 			pSeries_mpic_node = of_node_get(np);
 			ppc_md.init_IRQ       = pseries_mpic_init_IRQ;
@@ -265,7 +267,7 @@ static int pci_dn_reconfig_notifier(stru
 		pdn = parent ? PCI_DN(parent) : NULL;
 		if (pdn) {
 			/* Create pdn and EEH device */
-			update_dn_pci_info(np, pdn->phb);
+			pci_add_device_node_info(pdn->phb, np);
 			eeh_dev_init(PCI_DN(np), pdn->phb);
 		}
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/sysdev/axonram.c linux-libre-4.7-gnu/arch/powerpc/sysdev/axonram.c
--- linux-libre-4.6-gnu/arch/powerpc/sysdev/axonram.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/sysdev/axonram.c	2016-07-24 15:23:50.000000000 -0400
@@ -143,7 +143,7 @@ axon_ram_make_request(struct request_que
  */
 static long
 axon_ram_direct_access(struct block_device *device, sector_t sector,
-		       void __pmem **kaddr, pfn_t *pfn)
+		       void __pmem **kaddr, pfn_t *pfn, long size)
 {
 	struct axon_ram_bank *bank = device->bd_disk->private_data;
 	loff_t offset = (loff_t)sector << AXON_RAM_SECTOR_SHIFT;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/sysdev/cpm1.c linux-libre-4.7-gnu/arch/powerpc/sysdev/cpm1.c
--- linux-libre-4.6-gnu/arch/powerpc/sysdev/cpm1.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/sysdev/cpm1.c	2016-07-24 15:23:50.000000000 -0400
@@ -532,15 +532,9 @@ struct cpm1_gpio16_chip {
 	u16 cpdata;
 };
 
-static inline struct cpm1_gpio16_chip *
-to_cpm1_gpio16_chip(struct of_mm_gpio_chip *mm_gc)
-{
-	return container_of(mm_gc, struct cpm1_gpio16_chip, mm_gc);
-}
-
 static void cpm1_gpio16_save_regs(struct of_mm_gpio_chip *mm_gc)
 {
-	struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc);
+	struct cpm1_gpio16_chip *cpm1_gc = gpiochip_get_data(&mm_gc->gc);
 	struct cpm_ioport16 __iomem *iop = mm_gc->regs;
 
 	cpm1_gc->cpdata = in_be16(&iop->dat);
@@ -560,7 +554,7 @@ static int cpm1_gpio16_get(struct gpio_c
 static void __cpm1_gpio16_set(struct of_mm_gpio_chip *mm_gc, u16 pin_mask,
 	int value)
 {
-	struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc);
+	struct cpm1_gpio16_chip *cpm1_gc = gpiochip_get_data(&mm_gc->gc);
 	struct cpm_ioport16 __iomem *iop = mm_gc->regs;
 
 	if (value)
@@ -574,7 +568,7 @@ static void __cpm1_gpio16_set(struct of_
 static void cpm1_gpio16_set(struct gpio_chip *gc, unsigned int gpio, int value)
 {
 	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
-	struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc);
+	struct cpm1_gpio16_chip *cpm1_gc = gpiochip_get_data(&mm_gc->gc);
 	unsigned long flags;
 	u16 pin_mask = 1 << (15 - gpio);
 
@@ -588,7 +582,7 @@ static void cpm1_gpio16_set(struct gpio_
 static int cpm1_gpio16_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
 {
 	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
-	struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc);
+	struct cpm1_gpio16_chip *cpm1_gc = gpiochip_get_data(&mm_gc->gc);
 	struct cpm_ioport16 __iomem *iop = mm_gc->regs;
 	unsigned long flags;
 	u16 pin_mask = 1 << (15 - gpio);
@@ -606,7 +600,7 @@ static int cpm1_gpio16_dir_out(struct gp
 static int cpm1_gpio16_dir_in(struct gpio_chip *gc, unsigned int gpio)
 {
 	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
-	struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc);
+	struct cpm1_gpio16_chip *cpm1_gc = gpiochip_get_data(&mm_gc->gc);
 	struct cpm_ioport16 __iomem *iop = mm_gc->regs;
 	unsigned long flags;
 	u16 pin_mask = 1 << (15 - gpio);
@@ -642,7 +636,7 @@ int cpm1_gpiochip_add16(struct device_no
 	gc->get = cpm1_gpio16_get;
 	gc->set = cpm1_gpio16_set;
 
-	return of_mm_gpiochip_add(np, mm_gc);
+	return of_mm_gpiochip_add_data(np, mm_gc, cpm1_gc);
 }
 
 struct cpm1_gpio32_chip {
@@ -653,15 +647,9 @@ struct cpm1_gpio32_chip {
 	u32 cpdata;
 };
 
-static inline struct cpm1_gpio32_chip *
-to_cpm1_gpio32_chip(struct of_mm_gpio_chip *mm_gc)
-{
-	return container_of(mm_gc, struct cpm1_gpio32_chip, mm_gc);
-}
-
 static void cpm1_gpio32_save_regs(struct of_mm_gpio_chip *mm_gc)
 {
-	struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc);
+	struct cpm1_gpio32_chip *cpm1_gc = gpiochip_get_data(&mm_gc->gc);
 	struct cpm_ioport32b __iomem *iop = mm_gc->regs;
 
 	cpm1_gc->cpdata = in_be32(&iop->dat);
@@ -681,7 +669,7 @@ static int cpm1_gpio32_get(struct gpio_c
 static void __cpm1_gpio32_set(struct of_mm_gpio_chip *mm_gc, u32 pin_mask,
 	int value)
 {
-	struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc);
+	struct cpm1_gpio32_chip *cpm1_gc = gpiochip_get_data(&mm_gc->gc);
 	struct cpm_ioport32b __iomem *iop = mm_gc->regs;
 
 	if (value)
@@ -695,7 +683,7 @@ static void __cpm1_gpio32_set(struct of_
 static void cpm1_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value)
 {
 	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
-	struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc);
+	struct cpm1_gpio32_chip *cpm1_gc = gpiochip_get_data(&mm_gc->gc);
 	unsigned long flags;
 	u32 pin_mask = 1 << (31 - gpio);
 
@@ -709,7 +697,7 @@ static void cpm1_gpio32_set(struct gpio_
 static int cpm1_gpio32_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
 {
 	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
-	struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc);
+	struct cpm1_gpio32_chip *cpm1_gc = gpiochip_get_data(&mm_gc->gc);
 	struct cpm_ioport32b __iomem *iop = mm_gc->regs;
 	unsigned long flags;
 	u32 pin_mask = 1 << (31 - gpio);
@@ -727,7 +715,7 @@ static int cpm1_gpio32_dir_out(struct gp
 static int cpm1_gpio32_dir_in(struct gpio_chip *gc, unsigned int gpio)
 {
 	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
-	struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc);
+	struct cpm1_gpio32_chip *cpm1_gc = gpiochip_get_data(&mm_gc->gc);
 	struct cpm_ioport32b __iomem *iop = mm_gc->regs;
 	unsigned long flags;
 	u32 pin_mask = 1 << (31 - gpio);
@@ -763,7 +751,7 @@ int cpm1_gpiochip_add32(struct device_no
 	gc->get = cpm1_gpio32_get;
 	gc->set = cpm1_gpio32_set;
 
-	return of_mm_gpiochip_add(np, mm_gc);
+	return of_mm_gpiochip_add_data(np, mm_gc, cpm1_gc);
 }
 
 static int cpm_init_par_io(void)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/sysdev/cpm_common.c linux-libre-4.7-gnu/arch/powerpc/sysdev/cpm_common.c
--- linux-libre-4.6-gnu/arch/powerpc/sysdev/cpm_common.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/sysdev/cpm_common.c	2016-07-24 15:23:50.000000000 -0400
@@ -80,15 +80,9 @@ struct cpm2_gpio32_chip {
 	u32 cpdata;
 };
 
-static inline struct cpm2_gpio32_chip *
-to_cpm2_gpio32_chip(struct of_mm_gpio_chip *mm_gc)
-{
-	return container_of(mm_gc, struct cpm2_gpio32_chip, mm_gc);
-}
-
 static void cpm2_gpio32_save_regs(struct of_mm_gpio_chip *mm_gc)
 {
-	struct cpm2_gpio32_chip *cpm2_gc = to_cpm2_gpio32_chip(mm_gc);
+	struct cpm2_gpio32_chip *cpm2_gc = gpiochip_get_data(&mm_gc->gc);
 	struct cpm2_ioports __iomem *iop = mm_gc->regs;
 
 	cpm2_gc->cpdata = in_be32(&iop->dat);
@@ -108,7 +102,7 @@ static int cpm2_gpio32_get(struct gpio_c
 static void __cpm2_gpio32_set(struct of_mm_gpio_chip *mm_gc, u32 pin_mask,
 	int value)
 {
-	struct cpm2_gpio32_chip *cpm2_gc = to_cpm2_gpio32_chip(mm_gc);
+	struct cpm2_gpio32_chip *cpm2_gc = gpiochip_get_data(&mm_gc->gc);
 	struct cpm2_ioports __iomem *iop = mm_gc->regs;
 
 	if (value)
@@ -122,7 +116,7 @@ static void __cpm2_gpio32_set(struct of_
 static void cpm2_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value)
 {
 	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
-	struct cpm2_gpio32_chip *cpm2_gc = to_cpm2_gpio32_chip(mm_gc);
+	struct cpm2_gpio32_chip *cpm2_gc = gpiochip_get_data(gc);
 	unsigned long flags;
 	u32 pin_mask = 1 << (31 - gpio);
 
@@ -136,7 +130,7 @@ static void cpm2_gpio32_set(struct gpio_
 static int cpm2_gpio32_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
 {
 	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
-	struct cpm2_gpio32_chip *cpm2_gc = to_cpm2_gpio32_chip(mm_gc);
+	struct cpm2_gpio32_chip *cpm2_gc = gpiochip_get_data(gc);
 	struct cpm2_ioports __iomem *iop = mm_gc->regs;
 	unsigned long flags;
 	u32 pin_mask = 1 << (31 - gpio);
@@ -154,7 +148,7 @@ static int cpm2_gpio32_dir_out(struct gp
 static int cpm2_gpio32_dir_in(struct gpio_chip *gc, unsigned int gpio)
 {
 	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
-	struct cpm2_gpio32_chip *cpm2_gc = to_cpm2_gpio32_chip(mm_gc);
+	struct cpm2_gpio32_chip *cpm2_gc = gpiochip_get_data(gc);
 	struct cpm2_ioports __iomem *iop = mm_gc->regs;
 	unsigned long flags;
 	u32 pin_mask = 1 << (31 - gpio);
@@ -190,6 +184,6 @@ int cpm2_gpiochip_add32(struct device_no
 	gc->get = cpm2_gpio32_get;
 	gc->set = cpm2_gpio32_set;
 
-	return of_mm_gpiochip_add(np, mm_gc);
+	return of_mm_gpiochip_add_data(np, mm_gc, cpm2_gc);
 }
 #endif /* CONFIG_CPM2 || CONFIG_8xx_GPIO */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/sysdev/fsl_pci.c linux-libre-4.7-gnu/arch/powerpc/sysdev/fsl_pci.c
--- linux-libre-4.6-gnu/arch/powerpc/sysdev/fsl_pci.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/sysdev/fsl_pci.c	2016-07-24 15:23:50.000000000 -0400
@@ -37,6 +37,7 @@
 #include <asm/pci-bridge.h>
 #include <asm/ppc-pci.h>
 #include <asm/machdep.h>
+#include <asm/mpc85xx.h>
 #include <asm/disassemble.h>
 #include <asm/ppc-opcode.h>
 #include <sysdev/fsl_soc.h>
@@ -527,6 +528,8 @@ int fsl_add_bridge(struct platform_devic
 	u8 hdr_type, progif;
 	struct device_node *dev;
 	struct ccsr_pci __iomem *pci;
+	u16 temp;
+	u32 svr = mfspr(SPRN_SVR);
 
 	dev = pdev->dev.of_node;
 
@@ -596,6 +599,27 @@ int fsl_add_bridge(struct platform_devic
 			PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS;
 		if (fsl_pcie_check_link(hose))
 			hose->indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK;
+	} else {
+		/*
+		 * Set PBFR(PCI Bus Function Register)[10] = 1 to
+		 * disable the combining of crossing cacheline
+		 * boundary requests into one burst transaction.
+		 * PCI-X operation is not affected.
+		 * Fix erratum PCI 5 on MPC8548
+		 */
+#define PCI_BUS_FUNCTION 0x44
+#define PCI_BUS_FUNCTION_MDS 0x400	/* Master disable streaming */
+		if (((SVR_SOC_VER(svr) == SVR_8543) ||
+		     (SVR_SOC_VER(svr) == SVR_8545) ||
+		     (SVR_SOC_VER(svr) == SVR_8547) ||
+		     (SVR_SOC_VER(svr) == SVR_8548)) &&
+		    !early_find_capability(hose, 0, 0, PCI_CAP_ID_PCIX)) {
+			early_read_config_word(hose, 0, 0,
+					PCI_BUS_FUNCTION, &temp);
+			temp |= PCI_BUS_FUNCTION_MDS;
+			early_write_config_word(hose, 0, 0,
+					PCI_BUS_FUNCTION, temp);
+		}
 	}
 
 	printk(KERN_INFO "Found FSL PCI host bridge at 0x%016llx. "
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/sysdev/mpic.c linux-libre-4.7-gnu/arch/powerpc/sysdev/mpic.c
--- linux-libre-4.6-gnu/arch/powerpc/sysdev/mpic.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/sysdev/mpic.c	2016-07-24 15:23:50.000000000 -0400
@@ -2004,8 +2004,15 @@ static struct syscore_ops mpic_syscore_o
 
 static int mpic_init_sys(void)
 {
+	int rc;
+
 	register_syscore_ops(&mpic_syscore_ops);
-	subsys_system_register(&mpic_subsys, NULL);
+	rc = subsys_system_register(&mpic_subsys, NULL);
+	if (rc) {
+		unregister_syscore_ops(&mpic_syscore_ops);
+		pr_err("mpic: Failed to register subsystem!\n");
+		return rc;
+	}
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/sysdev/ppc4xx_gpio.c linux-libre-4.7-gnu/arch/powerpc/sysdev/ppc4xx_gpio.c
--- linux-libre-4.6-gnu/arch/powerpc/sysdev/ppc4xx_gpio.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/sysdev/ppc4xx_gpio.c	2016-07-24 15:23:50.000000000 -0400
@@ -27,7 +27,7 @@
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
 #include <linux/types.h>
 #include <linux/slab.h>
 
@@ -67,12 +67,6 @@ struct ppc4xx_gpio_chip {
  * There are a maximum of 32 gpios in each gpio controller.
  */
 
-static inline struct ppc4xx_gpio_chip *
-to_ppc4xx_gpiochip(struct of_mm_gpio_chip *mm_gc)
-{
-	return container_of(mm_gc, struct ppc4xx_gpio_chip, mm_gc);
-}
-
 static int ppc4xx_gpio_get(struct gpio_chip *gc, unsigned int gpio)
 {
 	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
@@ -96,8 +90,7 @@ __ppc4xx_gpio_set(struct gpio_chip *gc,
 static void
 ppc4xx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
 {
-	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
-	struct ppc4xx_gpio_chip *chip = to_ppc4xx_gpiochip(mm_gc);
+	struct ppc4xx_gpio_chip *chip = gpiochip_get_data(gc);
 	unsigned long flags;
 
 	spin_lock_irqsave(&chip->lock, flags);
@@ -112,7 +105,7 @@ ppc4xx_gpio_set(struct gpio_chip *gc, un
 static int ppc4xx_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
 {
 	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
-	struct ppc4xx_gpio_chip *chip = to_ppc4xx_gpiochip(mm_gc);
+	struct ppc4xx_gpio_chip *chip = gpiochip_get_data(gc);
 	struct ppc4xx_gpio __iomem *regs = mm_gc->regs;
 	unsigned long flags;
 
@@ -142,7 +135,7 @@ static int
 ppc4xx_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
 {
 	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
-	struct ppc4xx_gpio_chip *chip = to_ppc4xx_gpiochip(mm_gc);
+	struct ppc4xx_gpio_chip *chip = gpiochip_get_data(gc);
 	struct ppc4xx_gpio __iomem *regs = mm_gc->regs;
 	unsigned long flags;
 
@@ -200,7 +193,7 @@ static int __init ppc4xx_add_gpiochips(v
 		gc->get = ppc4xx_gpio_get;
 		gc->set = ppc4xx_gpio_set;
 
-		ret = of_mm_gpiochip_add(np, mm_gc);
+		ret = of_mm_gpiochip_add_data(np, mm_gc, ppc4xx_gc);
 		if (ret)
 			goto err;
 		continue;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/sysdev/simple_gpio.c linux-libre-4.7-gnu/arch/powerpc/sysdev/simple_gpio.c
--- linux-libre-4.6-gnu/arch/powerpc/sysdev/simple_gpio.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/sysdev/simple_gpio.c	2016-07-24 15:23:50.000000000 -0400
@@ -19,7 +19,7 @@
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
 #include <linux/slab.h>
 #include <asm/prom.h>
 #include "simple_gpio.h"
@@ -32,11 +32,6 @@ struct u8_gpio_chip {
 	u8 data;
 };
 
-static struct u8_gpio_chip *to_u8_gpio_chip(struct of_mm_gpio_chip *mm_gc)
-{
-	return container_of(mm_gc, struct u8_gpio_chip, mm_gc);
-}
-
 static u8 u8_pin2mask(unsigned int pin)
 {
 	return 1 << (8 - 1 - pin);
@@ -52,7 +47,7 @@ static int u8_gpio_get(struct gpio_chip
 static void u8_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
 {
 	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
-	struct u8_gpio_chip *u8_gc = to_u8_gpio_chip(mm_gc);
+	struct u8_gpio_chip *u8_gc = gpiochip_get_data(gc);
 	unsigned long flags;
 
 	spin_lock_irqsave(&u8_gc->lock, flags);
@@ -80,7 +75,7 @@ static int u8_gpio_dir_out(struct gpio_c
 
 static void u8_gpio_save_regs(struct of_mm_gpio_chip *mm_gc)
 {
-	struct u8_gpio_chip *u8_gc = to_u8_gpio_chip(mm_gc);
+	struct u8_gpio_chip *u8_gc = gpiochip_get_data(&mm_gc->gc);
 
 	u8_gc->data = in_8(mm_gc->regs);
 }
@@ -108,7 +103,7 @@ static int __init u8_simple_gpiochip_add
 	gc->get = u8_gpio_get;
 	gc->set = u8_gpio_set;
 
-	ret = of_mm_gpiochip_add(np, mm_gc);
+	ret = of_mm_gpiochip_add_data(np, mm_gc, u8_gc);
 	if (ret)
 		goto err;
 	return 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/xmon/Makefile linux-libre-4.7-gnu/arch/powerpc/xmon/Makefile
--- linux-libre-4.6-gnu/arch/powerpc/xmon/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/xmon/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -7,7 +7,7 @@ UBSAN_SANITIZE := n
 
 ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC)
 
-obj-y			+= xmon.o nonstdio.o
+obj-y			+= xmon.o nonstdio.o spr_access.o
 
 ifdef CONFIG_XMON_DISASSEMBLY
 obj-y			+= ppc-dis.o ppc-opc.o
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/xmon/spr_access.S linux-libre-4.7-gnu/arch/powerpc/xmon/spr_access.S
--- linux-libre-4.6-gnu/arch/powerpc/xmon/spr_access.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/powerpc/xmon/spr_access.S	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,45 @@
+#include <asm/ppc_asm.h>
+
+/* unsigned long xmon_mfspr(sprn, default_value) */
+_GLOBAL(xmon_mfspr)
+	ld	r5, .Lmfspr_table@got(r2)
+	b	xmon_mxspr
+
+/* void xmon_mtspr(sprn, new_value) */
+_GLOBAL(xmon_mtspr)
+	ld	r5, .Lmtspr_table@got(r2)
+	b	xmon_mxspr
+
+/*
+ * r3 = sprn
+ * r4 = default or new value
+ * r5 = table base
+ */
+xmon_mxspr:
+	/*
+	 * To index into the table of mxsprs we need:
+	 *  i = (sprn & 0x3ff) * 8
+	 * or using rwlinm:
+	 *  i = (sprn << 3) & (0x3ff << 3)
+	 */
+	rlwinm	r3, r3, 3, 0x3ff << 3
+	add	r5, r5, r3
+	mtctr	r5
+	mr	r3, r4 /* put default_value in r3 for mfspr */
+	bctr
+
+.Lmfspr_table:
+	spr = 0
+	.rept	1024
+	mfspr	r3, spr
+	blr
+	spr = spr + 1
+	.endr
+
+.Lmtspr_table:
+	spr = 0
+	.rept	1024
+	mtspr	spr, r4
+	blr
+	spr = spr + 1
+	.endr
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/powerpc/xmon/xmon.c linux-libre-4.7-gnu/arch/powerpc/xmon/xmon.c
--- linux-libre-4.6-gnu/arch/powerpc/xmon/xmon.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/powerpc/xmon/xmon.c	2016-07-24 15:23:50.000000000 -0400
@@ -86,6 +86,7 @@ static char tmpstr[128];
 
 static long bus_error_jmp[JMP_BUF_LEN];
 static int catch_memory_errors;
+static int catch_spr_faults;
 static long *xmon_fault_jmp[NR_CPUS];
 
 /* Breakpoint stuff */
@@ -147,7 +148,7 @@ void getstring(char *, int);
 static void flush_input(void);
 static int inchar(void);
 static void take_input(char *);
-static unsigned long read_spr(int);
+static int  read_spr(int, unsigned long *);
 static void write_spr(int, unsigned long);
 static void super_regs(void);
 static void remove_bpts(void);
@@ -250,6 +251,9 @@ Commands:\n\
   sdi #	disassemble spu local store for spu # (in hex)\n"
 #endif
 "  S	print special registers\n\
+  Sa    print all SPRs\n\
+  Sr #	read SPR #\n\
+  Sw #v write v to SPR #\n\
   t	print backtrace\n\
   x	exit monitor and recover\n\
   X	exit monitor and don't recover\n"
@@ -442,6 +446,12 @@ static int xmon_core(struct pt_regs *reg
 #ifdef CONFIG_SMP
 	cpu = smp_processor_id();
 	if (cpumask_test_cpu(cpu, &cpus_in_xmon)) {
+		/*
+		 * We catch SPR read/write faults here because the 0x700, 0xf60
+		 * etc. handlers don't call debugger_fault_handler().
+		 */
+		if (catch_spr_faults)
+			longjmp(bus_error_jmp, 1);
 		get_output_lock();
 		excprint(regs);
 		printf("cpu 0x%x: Exception %lx %s in xmon, "
@@ -1635,89 +1645,87 @@ static void cacheflush(void)
 	catch_memory_errors = 0;
 }
 
-static unsigned long
-read_spr(int n)
+extern unsigned long xmon_mfspr(int spr, unsigned long default_value);
+extern void xmon_mtspr(int spr, unsigned long value);
+
+static int
+read_spr(int n, unsigned long *vp)
 {
-	unsigned int instrs[2];
-	unsigned long (*code)(void);
 	unsigned long ret = -1UL;
-#ifdef CONFIG_PPC64
-	unsigned long opd[3];
-
-	opd[0] = (unsigned long)instrs;
-	opd[1] = 0;
-	opd[2] = 0;
-	code = (unsigned long (*)(void)) opd;
-#else
-	code = (unsigned long (*)(void)) instrs;
-#endif
-
-	/* mfspr r3,n; blr */
-	instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
-	instrs[1] = 0x4e800020;
-	store_inst(instrs);
-	store_inst(instrs+1);
+	int ok = 0;
 
 	if (setjmp(bus_error_jmp) == 0) {
-		catch_memory_errors = 1;
+		catch_spr_faults = 1;
 		sync();
 
-		ret = code();
+		ret = xmon_mfspr(n, *vp);
 
 		sync();
-		/* wait a little while to see if we get a machine check */
-		__delay(200);
-		n = size;
+		*vp = ret;
+		ok = 1;
 	}
+	catch_spr_faults = 0;
 
-	return ret;
+	return ok;
 }
 
 static void
 write_spr(int n, unsigned long val)
 {
-	unsigned int instrs[2];
-	unsigned long (*code)(unsigned long);
-#ifdef CONFIG_PPC64
-	unsigned long opd[3];
-
-	opd[0] = (unsigned long)instrs;
-	opd[1] = 0;
-	opd[2] = 0;
-	code = (unsigned long (*)(unsigned long)) opd;
-#else
-	code = (unsigned long (*)(unsigned long)) instrs;
-#endif
-
-	instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
-	instrs[1] = 0x4e800020;
-	store_inst(instrs);
-	store_inst(instrs+1);
-
 	if (setjmp(bus_error_jmp) == 0) {
-		catch_memory_errors = 1;
+		catch_spr_faults = 1;
 		sync();
 
-		code(val);
+		xmon_mtspr(n, val);
 
 		sync();
-		/* wait a little while to see if we get a machine check */
-		__delay(200);
-		n = size;
+	} else {
+		printf("SPR 0x%03x (%4d) Faulted during write\n", n, n);
 	}
+	catch_spr_faults = 0;
 }
 
 static unsigned long regno;
 extern char exc_prolog;
 extern char dec_exc;
 
+static void dump_one_spr(int spr, bool show_unimplemented)
+{
+	unsigned long val;
+
+	val = 0xdeadbeef;
+	if (!read_spr(spr, &val)) {
+		printf("SPR 0x%03x (%4d) Faulted during read\n", spr, spr);
+		return;
+	}
+
+	if (val == 0xdeadbeef) {
+		/* Looks like read was a nop, confirm */
+		val = 0x0badcafe;
+		if (!read_spr(spr, &val)) {
+			printf("SPR 0x%03x (%4d) Faulted during read\n", spr, spr);
+			return;
+		}
+
+		if (val == 0x0badcafe) {
+			if (show_unimplemented)
+				printf("SPR 0x%03x (%4d) Unimplemented\n", spr, spr);
+			return;
+		}
+	}
+
+	printf("SPR 0x%03x (%4d) = 0x%lx\n", spr, spr, val);
+}
+
 static void super_regs(void)
 {
 	int cmd;
-	unsigned long val;
+	int spr;
 
 	cmd = skipbl();
-	if (cmd == '\n') {
+
+	switch (cmd) {
+	case '\n': {
 		unsigned long sp, toc;
 		asm("mr %0,1" : "=r" (sp) :);
 		asm("mr %0,2" : "=r" (toc) :);
@@ -1730,21 +1738,29 @@ static void super_regs(void)
 		       mfspr(SPRN_DEC), mfspr(SPRN_SPRG2));
 		printf("sp   = "REG"  sprg3= "REG"\n", sp, mfspr(SPRN_SPRG3));
 		printf("toc  = "REG"  dar  = "REG"\n", toc, mfspr(SPRN_DAR));
-
 		return;
 	}
-
-	scanhex(&regno);
-	switch (cmd) {
-	case 'w':
-		val = read_spr(regno);
+	case 'w': {
+		unsigned long val;
+		scanhex(&regno);
+		val = 0;
+		read_spr(regno, &val);
 		scanhex(&val);
 		write_spr(regno, val);
-		/* fall through */
+		dump_one_spr(regno, true);
+		break;
+	}
 	case 'r':
-		printf("spr %lx = %lx\n", regno, read_spr(regno));
+		scanhex(&regno);
+		dump_one_spr(regno, true);
+		break;
+	case 'a':
+		/* dump ALL SPRs */
+		for (spr = 1; spr < 1024; ++spr)
+			dump_one_spr(spr, false);
 		break;
 	}
+
 	scannl();
 }
 
@@ -2913,7 +2929,7 @@ static void xmon_print_symbol(unsigned l
 	printf("%s", after);
 }
 
-#ifdef CONFIG_PPC_BOOK3S_64
+#ifdef CONFIG_PPC_STD_MMU_64
 void dump_segments(void)
 {
 	int i;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/boot/compressed/Makefile linux-libre-4.7-gnu/arch/s390/boot/compressed/Makefile
--- linux-libre-4.6-gnu/arch/s390/boot/compressed/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/boot/compressed/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -22,7 +22,6 @@ OBJECTS += $(obj)/head.o $(obj)/misc.o $
 LDFLAGS_vmlinux := --oformat $(LD_BFD) -e startup -T
 $(obj)/vmlinux: $(obj)/vmlinux.lds $(OBJECTS)
 	$(call if_changed,ld)
-	@:
 
 sed-sizes := -e 's/^\([0-9a-fA-F]*\) . \(__bss_start\|_end\)$$/\#define SZ\2 0x\1/p'
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/configs/default_defconfig linux-libre-4.7-gnu/arch/s390/configs/default_defconfig
--- linux-libre-4.6-gnu/arch/s390/configs/default_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/configs/default_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -1,8 +1,7 @@
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
-CONFIG_FHANDLE=y
 CONFIG_AUDIT=y
-CONFIG_NO_HZ=y
+CONFIG_NO_HZ_IDLE=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_BSD_PROCESS_ACCT_V3=y
@@ -13,19 +12,19 @@ CONFIG_TASK_IO_ACCOUNTING=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_NUMA_BALANCING=y
-CONFIG_CGROUP_FREEZER=y
-CONFIG_CGROUP_PIDS=y
-CONFIG_CGROUP_DEVICE=y
-CONFIG_CPUSETS=y
-CONFIG_CGROUP_CPUACCT=y
 CONFIG_MEMCG=y
 CONFIG_MEMCG_SWAP=y
-CONFIG_MEMCG_KMEM=y
-CONFIG_CGROUP_HUGETLB=y
-CONFIG_CGROUP_PERF=y
+CONFIG_BLK_CGROUP=y
 CONFIG_CFS_BANDWIDTH=y
 CONFIG_RT_GROUP_SCHED=y
-CONFIG_BLK_CGROUP=y
+CONFIG_CGROUP_PIDS=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_HUGETLB=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_PERF=y
+CONFIG_CHECKPOINT_RESTORE=y
 CONFIG_NAMESPACES=y
 CONFIG_USER_NS=y
 CONFIG_SCHED_AUTOGROUP=y
@@ -55,7 +54,6 @@ CONFIG_UNIXWARE_DISKLABEL=y
 CONFIG_CFQ_GROUP_IOSCHED=y
 CONFIG_DEFAULT_DEADLINE=y
 CONFIG_LIVEPATCH=y
-CONFIG_MARCH_Z196=y
 CONFIG_TUNE_ZEC12=y
 CONFIG_NR_CPUS=256
 CONFIG_NUMA=y
@@ -65,6 +63,15 @@ CONFIG_MEMORY_HOTPLUG=y
 CONFIG_MEMORY_HOTREMOVE=y
 CONFIG_KSM=y
 CONFIG_TRANSPARENT_HUGEPAGE=y
+CONFIG_CLEANCACHE=y
+CONFIG_FRONTSWAP=y
+CONFIG_CMA=y
+CONFIG_MEM_SOFT_DIRTY=y
+CONFIG_ZPOOL=m
+CONFIG_ZBUD=m
+CONFIG_ZSMALLOC=m
+CONFIG_ZSMALLOC_STAT=y
+CONFIG_IDLE_PAGE_TRACKING=y
 CONFIG_PCI=y
 CONFIG_PCI_DEBUG=y
 CONFIG_HOTPLUG_PCI=y
@@ -452,6 +459,7 @@ CONFIG_HW_RANDOM_VIRTIO=m
 CONFIG_RAW_DRIVER=m
 CONFIG_HANGCHECK_TIMER=m
 CONFIG_TN3270_FS=y
+# CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
 CONFIG_WATCHDOG_NOWAYOUT=y
 CONFIG_SOFT_WATCHDOG=m
@@ -537,6 +545,8 @@ CONFIG_DLM=m
 CONFIG_PRINTK_TIME=y
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_INFO_DWARF4=y
+CONFIG_GDB_SCRIPTS=y
 CONFIG_FRAME_WARN=1024
 CONFIG_READABLE_ASM=y
 CONFIG_UNUSED_SYMBOLS=y
@@ -555,13 +565,17 @@ CONFIG_SLUB_DEBUG_ON=y
 CONFIG_SLUB_STATS=y
 CONFIG_DEBUG_STACK_USAGE=y
 CONFIG_DEBUG_VM=y
+CONFIG_DEBUG_VM_VMACACHE=y
 CONFIG_DEBUG_VM_RB=y
+CONFIG_DEBUG_VM_PGFLAGS=y
 CONFIG_DEBUG_MEMORY_INIT=y
 CONFIG_MEMORY_NOTIFIER_ERROR_INJECT=m
 CONFIG_DEBUG_PER_CPU_MAPS=y
 CONFIG_DEBUG_SHIRQ=y
 CONFIG_DETECT_HUNG_TASK=y
+CONFIG_WQ_WATCHDOG=y
 CONFIG_PANIC_ON_OOPS=y
+CONFIG_DEBUG_TIMEKEEPING=y
 CONFIG_TIMER_STATS=y
 CONFIG_DEBUG_RT_MUTEXES=y
 CONFIG_DEBUG_WW_MUTEX_SLOWPATH=y
@@ -596,6 +610,8 @@ CONFIG_FTRACE_SYSCALLS=y
 CONFIG_STACK_TRACER=y
 CONFIG_BLK_DEV_IO_TRACE=y
 CONFIG_UPROBE_EVENT=y
+CONFIG_FUNCTION_PROFILER=y
+CONFIG_TRACE_ENUM_MAP_FILE=y
 CONFIG_LKDTM=m
 CONFIG_TEST_LIST_SORT=y
 CONFIG_KPROBES_SANITY_TEST=y
@@ -607,7 +623,6 @@ CONFIG_TEST_STRING_HELPERS=y
 CONFIG_TEST_KSTRTOX=y
 CONFIG_DMA_API_DEBUG=y
 CONFIG_TEST_BPF=m
-# CONFIG_STRICT_DEVMEM is not set
 CONFIG_S390_PTDUMP=y
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_SECURITY=y
@@ -651,7 +666,6 @@ CONFIG_CRYPTO_SEED=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_ZLIB=y
 CONFIG_CRYPTO_LZO=m
 CONFIG_CRYPTO_LZ4=m
 CONFIG_CRYPTO_LZ4HC=m
@@ -664,7 +678,7 @@ CONFIG_CRYPTO_SHA512_S390=m
 CONFIG_CRYPTO_DES_S390=m
 CONFIG_CRYPTO_AES_S390=m
 CONFIG_CRYPTO_GHASH_S390=m
-CONFIG_ASYMMETRIC_KEY_TYPE=m
+CONFIG_ASYMMETRIC_KEY_TYPE=y
 CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m
 CONFIG_X509_CERTIFICATE_PARSER=m
 CONFIG_CRC7=m
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/configs/gcov_defconfig linux-libre-4.7-gnu/arch/s390/configs/gcov_defconfig
--- linux-libre-4.6-gnu/arch/s390/configs/gcov_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/configs/gcov_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -1,8 +1,7 @@
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
-CONFIG_FHANDLE=y
 CONFIG_AUDIT=y
-CONFIG_NO_HZ=y
+CONFIG_NO_HZ_IDLE=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_BSD_PROCESS_ACCT_V3=y
@@ -13,17 +12,17 @@ CONFIG_TASK_IO_ACCOUNTING=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_NUMA_BALANCING=y
-CONFIG_CGROUP_FREEZER=y
-CONFIG_CGROUP_PIDS=y
-CONFIG_CGROUP_DEVICE=y
-CONFIG_CPUSETS=y
-CONFIG_CGROUP_CPUACCT=y
 CONFIG_MEMCG=y
 CONFIG_MEMCG_SWAP=y
-CONFIG_MEMCG_KMEM=y
+CONFIG_BLK_CGROUP=y
+CONFIG_CGROUP_PIDS=y
+CONFIG_CGROUP_FREEZER=y
 CONFIG_CGROUP_HUGETLB=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CGROUP_CPUACCT=y
 CONFIG_CGROUP_PERF=y
-CONFIG_BLK_CGROUP=y
+CONFIG_CHECKPOINT_RESTORE=y
 CONFIG_NAMESPACES=y
 CONFIG_USER_NS=y
 CONFIG_SCHED_AUTOGROUP=y
@@ -53,7 +52,6 @@ CONFIG_SOLARIS_X86_PARTITION=y
 CONFIG_UNIXWARE_DISKLABEL=y
 CONFIG_CFQ_GROUP_IOSCHED=y
 CONFIG_DEFAULT_DEADLINE=y
-CONFIG_MARCH_Z196=y
 CONFIG_TUNE_ZEC12=y
 CONFIG_NR_CPUS=256
 CONFIG_NUMA=y
@@ -62,6 +60,14 @@ CONFIG_MEMORY_HOTPLUG=y
 CONFIG_MEMORY_HOTREMOVE=y
 CONFIG_KSM=y
 CONFIG_TRANSPARENT_HUGEPAGE=y
+CONFIG_CLEANCACHE=y
+CONFIG_FRONTSWAP=y
+CONFIG_CMA=y
+CONFIG_ZSWAP=y
+CONFIG_ZBUD=m
+CONFIG_ZSMALLOC=m
+CONFIG_ZSMALLOC_STAT=y
+CONFIG_IDLE_PAGE_TRACKING=y
 CONFIG_PCI=y
 CONFIG_HOTPLUG_PCI=y
 CONFIG_HOTPLUG_PCI_S390=y
@@ -530,6 +536,8 @@ CONFIG_NLS_UTF8=m
 CONFIG_DLM=m
 CONFIG_PRINTK_TIME=y
 CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_INFO_DWARF4=y
+CONFIG_GDB_SCRIPTS=y
 # CONFIG_ENABLE_MUST_CHECK is not set
 CONFIG_FRAME_WARN=1024
 CONFIG_UNUSED_SYMBOLS=y
@@ -547,13 +555,13 @@ CONFIG_LATENCYTOP=y
 CONFIG_DEBUG_STRICT_USER_COPY_CHECKS=y
 CONFIG_BLK_DEV_IO_TRACE=y
 # CONFIG_KPROBE_EVENT is not set
+CONFIG_TRACE_ENUM_MAP_FILE=y
 CONFIG_LKDTM=m
 CONFIG_RBTREE_TEST=m
 CONFIG_INTERVAL_TREE_TEST=m
 CONFIG_PERCPU_TEST=m
 CONFIG_ATOMIC64_SELFTEST=y
 CONFIG_TEST_BPF=m
-# CONFIG_STRICT_DEVMEM is not set
 CONFIG_S390_PTDUMP=y
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_SECURITY=y
@@ -597,8 +605,6 @@ CONFIG_CRYPTO_SEED=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_ZLIB=y
-CONFIG_CRYPTO_LZO=m
 CONFIG_CRYPTO_LZ4=m
 CONFIG_CRYPTO_LZ4HC=m
 CONFIG_CRYPTO_USER_API_HASH=m
@@ -610,7 +616,7 @@ CONFIG_CRYPTO_SHA512_S390=m
 CONFIG_CRYPTO_DES_S390=m
 CONFIG_CRYPTO_AES_S390=m
 CONFIG_CRYPTO_GHASH_S390=m
-CONFIG_ASYMMETRIC_KEY_TYPE=m
+CONFIG_ASYMMETRIC_KEY_TYPE=y
 CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m
 CONFIG_X509_CERTIFICATE_PARSER=m
 CONFIG_CRC7=m
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/configs/performance_defconfig linux-libre-4.7-gnu/arch/s390/configs/performance_defconfig
--- linux-libre-4.6-gnu/arch/s390/configs/performance_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/configs/performance_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -1,8 +1,7 @@
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
-CONFIG_FHANDLE=y
 CONFIG_AUDIT=y
-CONFIG_NO_HZ=y
+CONFIG_NO_HZ_IDLE=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_BSD_PROCESS_ACCT_V3=y
@@ -14,17 +13,17 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_NUMA_BALANCING=y
 # CONFIG_NUMA_BALANCING_DEFAULT_ENABLED is not set
-CONFIG_CGROUP_FREEZER=y
-CONFIG_CGROUP_PIDS=y
-CONFIG_CGROUP_DEVICE=y
-CONFIG_CPUSETS=y
-CONFIG_CGROUP_CPUACCT=y
 CONFIG_MEMCG=y
 CONFIG_MEMCG_SWAP=y
-CONFIG_MEMCG_KMEM=y
+CONFIG_BLK_CGROUP=y
+CONFIG_CGROUP_PIDS=y
+CONFIG_CGROUP_FREEZER=y
 CONFIG_CGROUP_HUGETLB=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CGROUP_CPUACCT=y
 CONFIG_CGROUP_PERF=y
-CONFIG_BLK_CGROUP=y
+CONFIG_CHECKPOINT_RESTORE=y
 CONFIG_NAMESPACES=y
 CONFIG_USER_NS=y
 CONFIG_SCHED_AUTOGROUP=y
@@ -53,7 +52,6 @@ CONFIG_UNIXWARE_DISKLABEL=y
 CONFIG_CFQ_GROUP_IOSCHED=y
 CONFIG_DEFAULT_DEADLINE=y
 CONFIG_LIVEPATCH=y
-CONFIG_MARCH_Z196=y
 CONFIG_TUNE_ZEC12=y
 CONFIG_NR_CPUS=512
 CONFIG_NUMA=y
@@ -62,6 +60,14 @@ CONFIG_MEMORY_HOTPLUG=y
 CONFIG_MEMORY_HOTREMOVE=y
 CONFIG_KSM=y
 CONFIG_TRANSPARENT_HUGEPAGE=y
+CONFIG_CLEANCACHE=y
+CONFIG_FRONTSWAP=y
+CONFIG_CMA=y
+CONFIG_ZSWAP=y
+CONFIG_ZBUD=m
+CONFIG_ZSMALLOC=m
+CONFIG_ZSMALLOC_STAT=y
+CONFIG_IDLE_PAGE_TRACKING=y
 CONFIG_PCI=y
 CONFIG_HOTPLUG_PCI=y
 CONFIG_HOTPLUG_PCI_S390=y
@@ -447,6 +453,7 @@ CONFIG_HW_RANDOM_VIRTIO=m
 CONFIG_RAW_DRIVER=m
 CONFIG_HANGCHECK_TIMER=m
 CONFIG_TN3270_FS=y
+# CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
 CONFIG_WATCHDOG_NOWAYOUT=y
 CONFIG_SOFT_WATCHDOG=m
@@ -530,6 +537,8 @@ CONFIG_NLS_UTF8=m
 CONFIG_DLM=m
 CONFIG_PRINTK_TIME=y
 CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_INFO_DWARF4=y
+CONFIG_GDB_SCRIPTS=y
 # CONFIG_ENABLE_MUST_CHECK is not set
 CONFIG_FRAME_WARN=1024
 CONFIG_UNUSED_SYMBOLS=y
@@ -546,11 +555,12 @@ CONFIG_FTRACE_SYSCALLS=y
 CONFIG_STACK_TRACER=y
 CONFIG_BLK_DEV_IO_TRACE=y
 CONFIG_UPROBE_EVENT=y
+CONFIG_FUNCTION_PROFILER=y
+CONFIG_TRACE_ENUM_MAP_FILE=y
 CONFIG_LKDTM=m
 CONFIG_PERCPU_TEST=m
 CONFIG_ATOMIC64_SELFTEST=y
 CONFIG_TEST_BPF=m
-# CONFIG_STRICT_DEVMEM is not set
 CONFIG_S390_PTDUMP=y
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_SECURITY=y
@@ -594,8 +604,6 @@ CONFIG_CRYPTO_SEED=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_ZLIB=y
-CONFIG_CRYPTO_LZO=m
 CONFIG_CRYPTO_LZ4=m
 CONFIG_CRYPTO_LZ4HC=m
 CONFIG_CRYPTO_USER_API_HASH=m
@@ -607,7 +615,7 @@ CONFIG_CRYPTO_SHA512_S390=m
 CONFIG_CRYPTO_DES_S390=m
 CONFIG_CRYPTO_AES_S390=m
 CONFIG_CRYPTO_GHASH_S390=m
-CONFIG_ASYMMETRIC_KEY_TYPE=m
+CONFIG_ASYMMETRIC_KEY_TYPE=y
 CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m
 CONFIG_X509_CERTIFICATE_PARSER=m
 CONFIG_CRC7=m
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/configs/zfcpdump_defconfig linux-libre-4.7-gnu/arch/s390/configs/zfcpdump_defconfig
--- linux-libre-4.6-gnu/arch/s390/configs/zfcpdump_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/configs/zfcpdump_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -1,5 +1,5 @@
 # CONFIG_SWAP is not set
-CONFIG_NO_HZ=y
+CONFIG_NO_HZ_IDLE=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -7,7 +7,6 @@ CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_IBM_PARTITION=y
 CONFIG_DEFAULT_DEADLINE=y
-CONFIG_MARCH_Z196=y
 CONFIG_TUNE_ZEC12=y
 # CONFIG_COMPAT is not set
 CONFIG_NR_CPUS=2
@@ -64,7 +63,6 @@ CONFIG_PANIC_ON_OOPS=y
 # CONFIG_SCHED_DEBUG is not set
 CONFIG_RCU_CPU_STALL_TIMEOUT=60
 # CONFIG_FTRACE is not set
-# CONFIG_STRICT_DEVMEM is not set
 # CONFIG_PFAULT is not set
 # CONFIG_S390_HYPFS_FS is not set
 # CONFIG_VIRTUALIZATION is not set
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/crypto/aes_s390.c linux-libre-4.7-gnu/arch/s390/crypto/aes_s390.c
--- linux-libre-4.6-gnu/arch/s390/crypto/aes_s390.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/crypto/aes_s390.c	2016-07-24 15:23:50.000000000 -0400
@@ -28,7 +28,7 @@
 #include <linux/init.h>
 #include <linux/spinlock.h>
 #include <crypto/xts.h>
-#include "crypt_s390.h"
+#include <asm/cpacf.h>
 
 #define AES_KEYLEN_128		1
 #define AES_KEYLEN_192		2
@@ -145,16 +145,16 @@ static void aes_encrypt(struct crypto_tf
 
 	switch (sctx->key_len) {
 	case 16:
-		crypt_s390_km(KM_AES_128_ENCRYPT, &sctx->key, out, in,
-			      AES_BLOCK_SIZE);
+		cpacf_km(CPACF_KM_AES_128_ENC, &sctx->key, out, in,
+			 AES_BLOCK_SIZE);
 		break;
 	case 24:
-		crypt_s390_km(KM_AES_192_ENCRYPT, &sctx->key, out, in,
-			      AES_BLOCK_SIZE);
+		cpacf_km(CPACF_KM_AES_192_ENC, &sctx->key, out, in,
+			 AES_BLOCK_SIZE);
 		break;
 	case 32:
-		crypt_s390_km(KM_AES_256_ENCRYPT, &sctx->key, out, in,
-			      AES_BLOCK_SIZE);
+		cpacf_km(CPACF_KM_AES_256_ENC, &sctx->key, out, in,
+			 AES_BLOCK_SIZE);
 		break;
 	}
 }
@@ -170,16 +170,16 @@ static void aes_decrypt(struct crypto_tf
 
 	switch (sctx->key_len) {
 	case 16:
-		crypt_s390_km(KM_AES_128_DECRYPT, &sctx->key, out, in,
-			      AES_BLOCK_SIZE);
+		cpacf_km(CPACF_KM_AES_128_DEC, &sctx->key, out, in,
+			 AES_BLOCK_SIZE);
 		break;
 	case 24:
-		crypt_s390_km(KM_AES_192_DECRYPT, &sctx->key, out, in,
-			      AES_BLOCK_SIZE);
+		cpacf_km(CPACF_KM_AES_192_DEC, &sctx->key, out, in,
+			 AES_BLOCK_SIZE);
 		break;
 	case 32:
-		crypt_s390_km(KM_AES_256_DECRYPT, &sctx->key, out, in,
-			      AES_BLOCK_SIZE);
+		cpacf_km(CPACF_KM_AES_256_DEC, &sctx->key, out, in,
+			 AES_BLOCK_SIZE);
 		break;
 	}
 }
@@ -212,7 +212,7 @@ static void fallback_exit_cip(struct cry
 static struct crypto_alg aes_alg = {
 	.cra_name		=	"aes",
 	.cra_driver_name	=	"aes-s390",
-	.cra_priority		=	CRYPT_S390_PRIORITY,
+	.cra_priority		=	300,
 	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER |
 					CRYPTO_ALG_NEED_FALLBACK,
 	.cra_blocksize		=	AES_BLOCK_SIZE,
@@ -298,16 +298,16 @@ static int ecb_aes_set_key(struct crypto
 
 	switch (key_len) {
 	case 16:
-		sctx->enc = KM_AES_128_ENCRYPT;
-		sctx->dec = KM_AES_128_DECRYPT;
+		sctx->enc = CPACF_KM_AES_128_ENC;
+		sctx->dec = CPACF_KM_AES_128_DEC;
 		break;
 	case 24:
-		sctx->enc = KM_AES_192_ENCRYPT;
-		sctx->dec = KM_AES_192_DECRYPT;
+		sctx->enc = CPACF_KM_AES_192_ENC;
+		sctx->dec = CPACF_KM_AES_192_DEC;
 		break;
 	case 32:
-		sctx->enc = KM_AES_256_ENCRYPT;
-		sctx->dec = KM_AES_256_DECRYPT;
+		sctx->enc = CPACF_KM_AES_256_ENC;
+		sctx->dec = CPACF_KM_AES_256_DEC;
 		break;
 	}
 
@@ -326,7 +326,7 @@ static int ecb_aes_crypt(struct blkciphe
 		u8 *out = walk->dst.virt.addr;
 		u8 *in = walk->src.virt.addr;
 
-		ret = crypt_s390_km(func, param, out, in, n);
+		ret = cpacf_km(func, param, out, in, n);
 		if (ret < 0 || ret != n)
 			return -EIO;
 
@@ -393,7 +393,7 @@ static void fallback_exit_blk(struct cry
 static struct crypto_alg ecb_aes_alg = {
 	.cra_name		=	"ecb(aes)",
 	.cra_driver_name	=	"ecb-aes-s390",
-	.cra_priority		=	CRYPT_S390_COMPOSITE_PRIORITY,
+	.cra_priority		=	400,	/* combo: aes + ecb */
 	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER |
 					CRYPTO_ALG_NEED_FALLBACK,
 	.cra_blocksize		=	AES_BLOCK_SIZE,
@@ -427,16 +427,16 @@ static int cbc_aes_set_key(struct crypto
 
 	switch (key_len) {
 	case 16:
-		sctx->enc = KMC_AES_128_ENCRYPT;
-		sctx->dec = KMC_AES_128_DECRYPT;
+		sctx->enc = CPACF_KMC_AES_128_ENC;
+		sctx->dec = CPACF_KMC_AES_128_DEC;
 		break;
 	case 24:
-		sctx->enc = KMC_AES_192_ENCRYPT;
-		sctx->dec = KMC_AES_192_DECRYPT;
+		sctx->enc = CPACF_KMC_AES_192_ENC;
+		sctx->dec = CPACF_KMC_AES_192_DEC;
 		break;
 	case 32:
-		sctx->enc = KMC_AES_256_ENCRYPT;
-		sctx->dec = KMC_AES_256_DECRYPT;
+		sctx->enc = CPACF_KMC_AES_256_ENC;
+		sctx->dec = CPACF_KMC_AES_256_DEC;
 		break;
 	}
 
@@ -465,7 +465,7 @@ static int cbc_aes_crypt(struct blkciphe
 		u8 *out = walk->dst.virt.addr;
 		u8 *in = walk->src.virt.addr;
 
-		ret = crypt_s390_kmc(func, &param, out, in, n);
+		ret = cpacf_kmc(func, &param, out, in, n);
 		if (ret < 0 || ret != n)
 			return -EIO;
 
@@ -509,7 +509,7 @@ static int cbc_aes_decrypt(struct blkcip
 static struct crypto_alg cbc_aes_alg = {
 	.cra_name		=	"cbc(aes)",
 	.cra_driver_name	=	"cbc-aes-s390",
-	.cra_priority		=	CRYPT_S390_COMPOSITE_PRIORITY,
+	.cra_priority		=	400,	/* combo: aes + cbc */
 	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER |
 					CRYPTO_ALG_NEED_FALLBACK,
 	.cra_blocksize		=	AES_BLOCK_SIZE,
@@ -596,8 +596,8 @@ static int xts_aes_set_key(struct crypto
 
 	switch (key_len) {
 	case 32:
-		xts_ctx->enc = KM_XTS_128_ENCRYPT;
-		xts_ctx->dec = KM_XTS_128_DECRYPT;
+		xts_ctx->enc = CPACF_KM_XTS_128_ENC;
+		xts_ctx->dec = CPACF_KM_XTS_128_DEC;
 		memcpy(xts_ctx->key + 16, in_key, 16);
 		memcpy(xts_ctx->pcc_key + 16, in_key + 16, 16);
 		break;
@@ -607,8 +607,8 @@ static int xts_aes_set_key(struct crypto
 		xts_fallback_setkey(tfm, in_key, key_len);
 		break;
 	case 64:
-		xts_ctx->enc = KM_XTS_256_ENCRYPT;
-		xts_ctx->dec = KM_XTS_256_DECRYPT;
+		xts_ctx->enc = CPACF_KM_XTS_256_ENC;
+		xts_ctx->dec = CPACF_KM_XTS_256_DEC;
 		memcpy(xts_ctx->key, in_key, 32);
 		memcpy(xts_ctx->pcc_key, in_key + 32, 32);
 		break;
@@ -643,7 +643,8 @@ static int xts_aes_crypt(struct blkciphe
 	memset(pcc_param.xts, 0, sizeof(pcc_param.xts));
 	memcpy(pcc_param.tweak, walk->iv, sizeof(pcc_param.tweak));
 	memcpy(pcc_param.key, xts_ctx->pcc_key, 32);
-	ret = crypt_s390_pcc(func, &pcc_param.key[offset]);
+	/* remove decipher modifier bit from 'func' and call PCC */
+	ret = cpacf_pcc(func & 0x7f, &pcc_param.key[offset]);
 	if (ret < 0)
 		return -EIO;
 
@@ -655,7 +656,7 @@ static int xts_aes_crypt(struct blkciphe
 		out = walk->dst.virt.addr;
 		in = walk->src.virt.addr;
 
-		ret = crypt_s390_km(func, &xts_param.key[offset], out, in, n);
+		ret = cpacf_km(func, &xts_param.key[offset], out, in, n);
 		if (ret < 0 || ret != n)
 			return -EIO;
 
@@ -721,7 +722,7 @@ static void xts_fallback_exit(struct cry
 static struct crypto_alg xts_aes_alg = {
 	.cra_name		=	"xts(aes)",
 	.cra_driver_name	=	"xts-aes-s390",
-	.cra_priority		=	CRYPT_S390_COMPOSITE_PRIORITY,
+	.cra_priority		=	400,	/* combo: aes + xts */
 	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER |
 					CRYPTO_ALG_NEED_FALLBACK,
 	.cra_blocksize		=	AES_BLOCK_SIZE,
@@ -751,16 +752,16 @@ static int ctr_aes_set_key(struct crypto
 
 	switch (key_len) {
 	case 16:
-		sctx->enc = KMCTR_AES_128_ENCRYPT;
-		sctx->dec = KMCTR_AES_128_DECRYPT;
+		sctx->enc = CPACF_KMCTR_AES_128_ENC;
+		sctx->dec = CPACF_KMCTR_AES_128_DEC;
 		break;
 	case 24:
-		sctx->enc = KMCTR_AES_192_ENCRYPT;
-		sctx->dec = KMCTR_AES_192_DECRYPT;
+		sctx->enc = CPACF_KMCTR_AES_192_ENC;
+		sctx->dec = CPACF_KMCTR_AES_192_DEC;
 		break;
 	case 32:
-		sctx->enc = KMCTR_AES_256_ENCRYPT;
-		sctx->dec = KMCTR_AES_256_DECRYPT;
+		sctx->enc = CPACF_KMCTR_AES_256_ENC;
+		sctx->dec = CPACF_KMCTR_AES_256_DEC;
 		break;
 	}
 
@@ -804,8 +805,7 @@ static int ctr_aes_crypt(struct blkciphe
 				n = __ctrblk_init(ctrptr, nbytes);
 			else
 				n = AES_BLOCK_SIZE;
-			ret = crypt_s390_kmctr(func, sctx->key, out, in,
-					       n, ctrptr);
+			ret = cpacf_kmctr(func, sctx->key, out, in, n, ctrptr);
 			if (ret < 0 || ret != n) {
 				if (ctrptr == ctrblk)
 					spin_unlock(&ctrblk_lock);
@@ -837,8 +837,8 @@ static int ctr_aes_crypt(struct blkciphe
 	if (nbytes) {
 		out = walk->dst.virt.addr;
 		in = walk->src.virt.addr;
-		ret = crypt_s390_kmctr(func, sctx->key, buf, in,
-				       AES_BLOCK_SIZE, ctrbuf);
+		ret = cpacf_kmctr(func, sctx->key, buf, in,
+				  AES_BLOCK_SIZE, ctrbuf);
 		if (ret < 0 || ret != AES_BLOCK_SIZE)
 			return -EIO;
 		memcpy(out, buf, nbytes);
@@ -875,7 +875,7 @@ static int ctr_aes_decrypt(struct blkcip
 static struct crypto_alg ctr_aes_alg = {
 	.cra_name		=	"ctr(aes)",
 	.cra_driver_name	=	"ctr-aes-s390",
-	.cra_priority		=	CRYPT_S390_COMPOSITE_PRIORITY,
+	.cra_priority		=	400,	/* combo: aes + ctr */
 	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER,
 	.cra_blocksize		=	1,
 	.cra_ctxsize		=	sizeof(struct s390_aes_ctx),
@@ -899,11 +899,11 @@ static int __init aes_s390_init(void)
 {
 	int ret;
 
-	if (crypt_s390_func_available(KM_AES_128_ENCRYPT, CRYPT_S390_MSA))
+	if (cpacf_query(CPACF_KM, CPACF_KM_AES_128_ENC))
 		keylen_flag |= AES_KEYLEN_128;
-	if (crypt_s390_func_available(KM_AES_192_ENCRYPT, CRYPT_S390_MSA))
+	if (cpacf_query(CPACF_KM, CPACF_KM_AES_192_ENC))
 		keylen_flag |= AES_KEYLEN_192;
-	if (crypt_s390_func_available(KM_AES_256_ENCRYPT, CRYPT_S390_MSA))
+	if (cpacf_query(CPACF_KM, CPACF_KM_AES_256_ENC))
 		keylen_flag |= AES_KEYLEN_256;
 
 	if (!keylen_flag)
@@ -926,22 +926,17 @@ static int __init aes_s390_init(void)
 	if (ret)
 		goto cbc_aes_err;
 
-	if (crypt_s390_func_available(KM_XTS_128_ENCRYPT,
-			CRYPT_S390_MSA | CRYPT_S390_MSA4) &&
-	    crypt_s390_func_available(KM_XTS_256_ENCRYPT,
-			CRYPT_S390_MSA | CRYPT_S390_MSA4)) {
+	if (cpacf_query(CPACF_KM, CPACF_KM_XTS_128_ENC) &&
+	    cpacf_query(CPACF_KM, CPACF_KM_XTS_256_ENC)) {
 		ret = crypto_register_alg(&xts_aes_alg);
 		if (ret)
 			goto xts_aes_err;
 		xts_aes_alg_reg = 1;
 	}
 
-	if (crypt_s390_func_available(KMCTR_AES_128_ENCRYPT,
-				CRYPT_S390_MSA | CRYPT_S390_MSA4) &&
-	    crypt_s390_func_available(KMCTR_AES_192_ENCRYPT,
-				CRYPT_S390_MSA | CRYPT_S390_MSA4) &&
-	    crypt_s390_func_available(KMCTR_AES_256_ENCRYPT,
-				CRYPT_S390_MSA | CRYPT_S390_MSA4)) {
+	if (cpacf_query(CPACF_KMCTR, CPACF_KMCTR_AES_128_ENC) &&
+	    cpacf_query(CPACF_KMCTR, CPACF_KMCTR_AES_192_ENC) &&
+	    cpacf_query(CPACF_KMCTR, CPACF_KMCTR_AES_256_ENC)) {
 		ctrblk = (u8 *) __get_free_page(GFP_KERNEL);
 		if (!ctrblk) {
 			ret = -ENOMEM;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/crypto/crypt_s390.h linux-libre-4.7-gnu/arch/s390/crypto/crypt_s390.h
--- linux-libre-4.6-gnu/arch/s390/crypto/crypt_s390.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/crypto/crypt_s390.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,493 +0,0 @@
-/*
- * Cryptographic API.
- *
- * Support for s390 cryptographic instructions.
- *
- *   Copyright IBM Corp. 2003, 2015
- *   Author(s): Thomas Spatzier
- *		Jan Glauber (jan.glauber@de.ibm.com)
- *		Harald Freudenberger (freude@de.ibm.com)
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- */
-#ifndef _CRYPTO_ARCH_S390_CRYPT_S390_H
-#define _CRYPTO_ARCH_S390_CRYPT_S390_H
-
-#include <asm/errno.h>
-#include <asm/facility.h>
-
-#define CRYPT_S390_OP_MASK 0xFF00
-#define CRYPT_S390_FUNC_MASK 0x00FF
-
-#define CRYPT_S390_PRIORITY 300
-#define CRYPT_S390_COMPOSITE_PRIORITY 400
-
-#define CRYPT_S390_MSA	0x1
-#define CRYPT_S390_MSA3	0x2
-#define CRYPT_S390_MSA4	0x4
-#define CRYPT_S390_MSA5	0x8
-
-/* s390 cryptographic operations */
-enum crypt_s390_operations {
-	CRYPT_S390_KM	 = 0x0100,
-	CRYPT_S390_KMC	 = 0x0200,
-	CRYPT_S390_KIMD  = 0x0300,
-	CRYPT_S390_KLMD  = 0x0400,
-	CRYPT_S390_KMAC  = 0x0500,
-	CRYPT_S390_KMCTR = 0x0600,
-	CRYPT_S390_PPNO  = 0x0700
-};
-
-/*
- * function codes for KM (CIPHER MESSAGE) instruction
- * 0x80 is the decipher modifier bit
- */
-enum crypt_s390_km_func {
-	KM_QUERY	    = CRYPT_S390_KM | 0x0,
-	KM_DEA_ENCRYPT      = CRYPT_S390_KM | 0x1,
-	KM_DEA_DECRYPT      = CRYPT_S390_KM | 0x1 | 0x80,
-	KM_TDEA_128_ENCRYPT = CRYPT_S390_KM | 0x2,
-	KM_TDEA_128_DECRYPT = CRYPT_S390_KM | 0x2 | 0x80,
-	KM_TDEA_192_ENCRYPT = CRYPT_S390_KM | 0x3,
-	KM_TDEA_192_DECRYPT = CRYPT_S390_KM | 0x3 | 0x80,
-	KM_AES_128_ENCRYPT  = CRYPT_S390_KM | 0x12,
-	KM_AES_128_DECRYPT  = CRYPT_S390_KM | 0x12 | 0x80,
-	KM_AES_192_ENCRYPT  = CRYPT_S390_KM | 0x13,
-	KM_AES_192_DECRYPT  = CRYPT_S390_KM | 0x13 | 0x80,
-	KM_AES_256_ENCRYPT  = CRYPT_S390_KM | 0x14,
-	KM_AES_256_DECRYPT  = CRYPT_S390_KM | 0x14 | 0x80,
-	KM_XTS_128_ENCRYPT  = CRYPT_S390_KM | 0x32,
-	KM_XTS_128_DECRYPT  = CRYPT_S390_KM | 0x32 | 0x80,
-	KM_XTS_256_ENCRYPT  = CRYPT_S390_KM | 0x34,
-	KM_XTS_256_DECRYPT  = CRYPT_S390_KM | 0x34 | 0x80,
-};
-
-/*
- * function codes for KMC (CIPHER MESSAGE WITH CHAINING)
- * instruction
- */
-enum crypt_s390_kmc_func {
-	KMC_QUERY            = CRYPT_S390_KMC | 0x0,
-	KMC_DEA_ENCRYPT      = CRYPT_S390_KMC | 0x1,
-	KMC_DEA_DECRYPT      = CRYPT_S390_KMC | 0x1 | 0x80,
-	KMC_TDEA_128_ENCRYPT = CRYPT_S390_KMC | 0x2,
-	KMC_TDEA_128_DECRYPT = CRYPT_S390_KMC | 0x2 | 0x80,
-	KMC_TDEA_192_ENCRYPT = CRYPT_S390_KMC | 0x3,
-	KMC_TDEA_192_DECRYPT = CRYPT_S390_KMC | 0x3 | 0x80,
-	KMC_AES_128_ENCRYPT  = CRYPT_S390_KMC | 0x12,
-	KMC_AES_128_DECRYPT  = CRYPT_S390_KMC | 0x12 | 0x80,
-	KMC_AES_192_ENCRYPT  = CRYPT_S390_KMC | 0x13,
-	KMC_AES_192_DECRYPT  = CRYPT_S390_KMC | 0x13 | 0x80,
-	KMC_AES_256_ENCRYPT  = CRYPT_S390_KMC | 0x14,
-	KMC_AES_256_DECRYPT  = CRYPT_S390_KMC | 0x14 | 0x80,
-	KMC_PRNG	     = CRYPT_S390_KMC | 0x43,
-};
-
-/*
- * function codes for KMCTR (CIPHER MESSAGE WITH COUNTER)
- * instruction
- */
-enum crypt_s390_kmctr_func {
-	KMCTR_QUERY            = CRYPT_S390_KMCTR | 0x0,
-	KMCTR_DEA_ENCRYPT      = CRYPT_S390_KMCTR | 0x1,
-	KMCTR_DEA_DECRYPT      = CRYPT_S390_KMCTR | 0x1 | 0x80,
-	KMCTR_TDEA_128_ENCRYPT = CRYPT_S390_KMCTR | 0x2,
-	KMCTR_TDEA_128_DECRYPT = CRYPT_S390_KMCTR | 0x2 | 0x80,
-	KMCTR_TDEA_192_ENCRYPT = CRYPT_S390_KMCTR | 0x3,
-	KMCTR_TDEA_192_DECRYPT = CRYPT_S390_KMCTR | 0x3 | 0x80,
-	KMCTR_AES_128_ENCRYPT  = CRYPT_S390_KMCTR | 0x12,
-	KMCTR_AES_128_DECRYPT  = CRYPT_S390_KMCTR | 0x12 | 0x80,
-	KMCTR_AES_192_ENCRYPT  = CRYPT_S390_KMCTR | 0x13,
-	KMCTR_AES_192_DECRYPT  = CRYPT_S390_KMCTR | 0x13 | 0x80,
-	KMCTR_AES_256_ENCRYPT  = CRYPT_S390_KMCTR | 0x14,
-	KMCTR_AES_256_DECRYPT  = CRYPT_S390_KMCTR | 0x14 | 0x80,
-};
-
-/*
- * function codes for KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST)
- * instruction
- */
-enum crypt_s390_kimd_func {
-	KIMD_QUERY   = CRYPT_S390_KIMD | 0,
-	KIMD_SHA_1   = CRYPT_S390_KIMD | 1,
-	KIMD_SHA_256 = CRYPT_S390_KIMD | 2,
-	KIMD_SHA_512 = CRYPT_S390_KIMD | 3,
-	KIMD_GHASH   = CRYPT_S390_KIMD | 65,
-};
-
-/*
- * function codes for KLMD (COMPUTE LAST MESSAGE DIGEST)
- * instruction
- */
-enum crypt_s390_klmd_func {
-	KLMD_QUERY   = CRYPT_S390_KLMD | 0,
-	KLMD_SHA_1   = CRYPT_S390_KLMD | 1,
-	KLMD_SHA_256 = CRYPT_S390_KLMD | 2,
-	KLMD_SHA_512 = CRYPT_S390_KLMD | 3,
-};
-
-/*
- * function codes for KMAC (COMPUTE MESSAGE AUTHENTICATION CODE)
- * instruction
- */
-enum crypt_s390_kmac_func {
-	KMAC_QUERY    = CRYPT_S390_KMAC | 0,
-	KMAC_DEA      = CRYPT_S390_KMAC | 1,
-	KMAC_TDEA_128 = CRYPT_S390_KMAC | 2,
-	KMAC_TDEA_192 = CRYPT_S390_KMAC | 3
-};
-
-/*
- * function codes for PPNO (PERFORM PSEUDORANDOM NUMBER
- * OPERATION) instruction
- */
-enum crypt_s390_ppno_func {
-	PPNO_QUERY	      = CRYPT_S390_PPNO | 0,
-	PPNO_SHA512_DRNG_GEN  = CRYPT_S390_PPNO | 3,
-	PPNO_SHA512_DRNG_SEED = CRYPT_S390_PPNO | 0x83
-};
-
-/**
- * crypt_s390_km:
- * @func: the function code passed to KM; see crypt_s390_km_func
- * @param: address of parameter block; see POP for details on each func
- * @dest: address of destination memory area
- * @src: address of source memory area
- * @src_len: length of src operand in bytes
- *
- * Executes the KM (CIPHER MESSAGE) operation of the CPU.
- *
- * Returns -1 for failure, 0 for the query func, number of processed
- * bytes for encryption/decryption funcs
- */
-static inline int crypt_s390_km(long func, void *param,
-				u8 *dest, const u8 *src, long src_len)
-{
-	register long __func asm("0") = func & CRYPT_S390_FUNC_MASK;
-	register void *__param asm("1") = param;
-	register const u8 *__src asm("2") = src;
-	register long __src_len asm("3") = src_len;
-	register u8 *__dest asm("4") = dest;
-	int ret;
-
-	asm volatile(
-		"0:	.insn	rre,0xb92e0000,%3,%1\n" /* KM opcode */
-		"1:	brc	1,0b\n" /* handle partial completion */
-		"	la	%0,0\n"
-		"2:\n"
-		EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
-		: "=d" (ret), "+a" (__src), "+d" (__src_len), "+a" (__dest)
-		: "d" (__func), "a" (__param), "0" (-1) : "cc", "memory");
-	if (ret < 0)
-		return ret;
-	return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len;
-}
-
-/**
- * crypt_s390_kmc:
- * @func: the function code passed to KM; see crypt_s390_kmc_func
- * @param: address of parameter block; see POP for details on each func
- * @dest: address of destination memory area
- * @src: address of source memory area
- * @src_len: length of src operand in bytes
- *
- * Executes the KMC (CIPHER MESSAGE WITH CHAINING) operation of the CPU.
- *
- * Returns -1 for failure, 0 for the query func, number of processed
- * bytes for encryption/decryption funcs
- */
-static inline int crypt_s390_kmc(long func, void *param,
-				 u8 *dest, const u8 *src, long src_len)
-{
-	register long __func asm("0") = func & CRYPT_S390_FUNC_MASK;
-	register void *__param asm("1") = param;
-	register const u8 *__src asm("2") = src;
-	register long __src_len asm("3") = src_len;
-	register u8 *__dest asm("4") = dest;
-	int ret;
-
-	asm volatile(
-		"0:	.insn	rre,0xb92f0000,%3,%1\n" /* KMC opcode */
-		"1:	brc	1,0b\n" /* handle partial completion */
-		"	la	%0,0\n"
-		"2:\n"
-		EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
-		: "=d" (ret), "+a" (__src), "+d" (__src_len), "+a" (__dest)
-		: "d" (__func), "a" (__param), "0" (-1) : "cc", "memory");
-	if (ret < 0)
-		return ret;
-	return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len;
-}
-
-/**
- * crypt_s390_kimd:
- * @func: the function code passed to KM; see crypt_s390_kimd_func
- * @param: address of parameter block; see POP for details on each func
- * @src: address of source memory area
- * @src_len: length of src operand in bytes
- *
- * Executes the KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST) operation
- * of the CPU.
- *
- * Returns -1 for failure, 0 for the query func, number of processed
- * bytes for digest funcs
- */
-static inline int crypt_s390_kimd(long func, void *param,
-				  const u8 *src, long src_len)
-{
-	register long __func asm("0") = func & CRYPT_S390_FUNC_MASK;
-	register void *__param asm("1") = param;
-	register const u8 *__src asm("2") = src;
-	register long __src_len asm("3") = src_len;
-	int ret;
-
-	asm volatile(
-		"0:	.insn	rre,0xb93e0000,%1,%1\n" /* KIMD opcode */
-		"1:	brc	1,0b\n" /* handle partial completion */
-		"	la	%0,0\n"
-		"2:\n"
-		EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
-		: "=d" (ret), "+a" (__src), "+d" (__src_len)
-		: "d" (__func), "a" (__param), "0" (-1) : "cc", "memory");
-	if (ret < 0)
-		return ret;
-	return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len;
-}
-
-/**
- * crypt_s390_klmd:
- * @func: the function code passed to KM; see crypt_s390_klmd_func
- * @param: address of parameter block; see POP for details on each func
- * @src: address of source memory area
- * @src_len: length of src operand in bytes
- *
- * Executes the KLMD (COMPUTE LAST MESSAGE DIGEST) operation of the CPU.
- *
- * Returns -1 for failure, 0 for the query func, number of processed
- * bytes for digest funcs
- */
-static inline int crypt_s390_klmd(long func, void *param,
-				  const u8 *src, long src_len)
-{
-	register long __func asm("0") = func & CRYPT_S390_FUNC_MASK;
-	register void *__param asm("1") = param;
-	register const u8 *__src asm("2") = src;
-	register long __src_len asm("3") = src_len;
-	int ret;
-
-	asm volatile(
-		"0:	.insn	rre,0xb93f0000,%1,%1\n" /* KLMD opcode */
-		"1:	brc	1,0b\n" /* handle partial completion */
-		"	la	%0,0\n"
-		"2:\n"
-		EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
-		: "=d" (ret), "+a" (__src), "+d" (__src_len)
-		: "d" (__func), "a" (__param), "0" (-1) : "cc", "memory");
-	if (ret < 0)
-		return ret;
-	return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len;
-}
-
-/**
- * crypt_s390_kmac:
- * @func: the function code passed to KM; see crypt_s390_klmd_func
- * @param: address of parameter block; see POP for details on each func
- * @src: address of source memory area
- * @src_len: length of src operand in bytes
- *
- * Executes the KMAC (COMPUTE MESSAGE AUTHENTICATION CODE) operation
- * of the CPU.
- *
- * Returns -1 for failure, 0 for the query func, number of processed
- * bytes for digest funcs
- */
-static inline int crypt_s390_kmac(long func, void *param,
-				  const u8 *src, long src_len)
-{
-	register long __func asm("0") = func & CRYPT_S390_FUNC_MASK;
-	register void *__param asm("1") = param;
-	register const u8 *__src asm("2") = src;
-	register long __src_len asm("3") = src_len;
-	int ret;
-
-	asm volatile(
-		"0:	.insn	rre,0xb91e0000,%1,%1\n" /* KLAC opcode */
-		"1:	brc	1,0b\n" /* handle partial completion */
-		"	la	%0,0\n"
-		"2:\n"
-		EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
-		: "=d" (ret), "+a" (__src), "+d" (__src_len)
-		: "d" (__func), "a" (__param), "0" (-1) : "cc", "memory");
-	if (ret < 0)
-		return ret;
-	return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len;
-}
-
-/**
- * crypt_s390_kmctr:
- * @func: the function code passed to KMCTR; see crypt_s390_kmctr_func
- * @param: address of parameter block; see POP for details on each func
- * @dest: address of destination memory area
- * @src: address of source memory area
- * @src_len: length of src operand in bytes
- * @counter: address of counter value
- *
- * Executes the KMCTR (CIPHER MESSAGE WITH COUNTER) operation of the CPU.
- *
- * Returns -1 for failure, 0 for the query func, number of processed
- * bytes for encryption/decryption funcs
- */
-static inline int crypt_s390_kmctr(long func, void *param, u8 *dest,
-				 const u8 *src, long src_len, u8 *counter)
-{
-	register long __func asm("0") = func & CRYPT_S390_FUNC_MASK;
-	register void *__param asm("1") = param;
-	register const u8 *__src asm("2") = src;
-	register long __src_len asm("3") = src_len;
-	register u8 *__dest asm("4") = dest;
-	register u8 *__ctr asm("6") = counter;
-	int ret = -1;
-
-	asm volatile(
-		"0:	.insn	rrf,0xb92d0000,%3,%1,%4,0\n" /* KMCTR opcode */
-		"1:	brc	1,0b\n" /* handle partial completion */
-		"	la	%0,0\n"
-		"2:\n"
-		EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
-		: "+d" (ret), "+a" (__src), "+d" (__src_len), "+a" (__dest),
-		  "+a" (__ctr)
-		: "d" (__func), "a" (__param) : "cc", "memory");
-	if (ret < 0)
-		return ret;
-	return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len;
-}
-
-/**
- * crypt_s390_ppno:
- * @func: the function code passed to PPNO; see crypt_s390_ppno_func
- * @param: address of parameter block; see POP for details on each func
- * @dest: address of destination memory area
- * @dest_len: size of destination memory area in bytes
- * @seed: address of seed data
- * @seed_len: size of seed data in bytes
- *
- * Executes the PPNO (PERFORM PSEUDORANDOM NUMBER OPERATION)
- * operation of the CPU.
- *
- * Returns -1 for failure, 0 for the query func, number of random
- * bytes stored in dest buffer for generate function
- */
-static inline int crypt_s390_ppno(long func, void *param,
-				  u8 *dest, long dest_len,
-				  const u8 *seed, long seed_len)
-{
-	register long  __func	  asm("0") = func & CRYPT_S390_FUNC_MASK;
-	register void *__param	  asm("1") = param;    /* param block (240 bytes) */
-	register u8   *__dest	  asm("2") = dest;     /* buf for recv random bytes */
-	register long  __dest_len asm("3") = dest_len; /* requested random bytes */
-	register const u8 *__seed asm("4") = seed;     /* buf with seed data */
-	register long  __seed_len asm("5") = seed_len; /* bytes in seed buf */
-	int ret = -1;
-
-	asm volatile (
-		"0:	.insn	rre,0xb93c0000,%1,%5\n"	/* PPNO opcode */
-		"1:	brc	1,0b\n"	  /* handle partial completion */
-		"	la	%0,0\n"
-		"2:\n"
-		EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
-		: "+d" (ret), "+a"(__dest), "+d"(__dest_len)
-		: "d"(__func), "a"(__param), "a"(__seed), "d"(__seed_len)
-		: "cc", "memory");
-	if (ret < 0)
-		return ret;
-	return (func & CRYPT_S390_FUNC_MASK) ? dest_len - __dest_len : 0;
-}
-
-/**
- * crypt_s390_func_available:
- * @func: the function code of the specific function; 0 if op in general
- *
- * Tests if a specific crypto function is implemented on the machine.
- *
- * Returns 1 if func available; 0 if func or op in general not available
- */
-static inline int crypt_s390_func_available(int func,
-					    unsigned int facility_mask)
-{
-	unsigned char status[16];
-	int ret;
-
-	if (facility_mask & CRYPT_S390_MSA && !test_facility(17))
-		return 0;
-	if (facility_mask & CRYPT_S390_MSA3 && !test_facility(76))
-		return 0;
-	if (facility_mask & CRYPT_S390_MSA4 && !test_facility(77))
-		return 0;
-	if (facility_mask & CRYPT_S390_MSA5 && !test_facility(57))
-		return 0;
-
-	switch (func & CRYPT_S390_OP_MASK) {
-	case CRYPT_S390_KM:
-		ret = crypt_s390_km(KM_QUERY, &status, NULL, NULL, 0);
-		break;
-	case CRYPT_S390_KMC:
-		ret = crypt_s390_kmc(KMC_QUERY, &status, NULL, NULL, 0);
-		break;
-	case CRYPT_S390_KIMD:
-		ret = crypt_s390_kimd(KIMD_QUERY, &status, NULL, 0);
-		break;
-	case CRYPT_S390_KLMD:
-		ret = crypt_s390_klmd(KLMD_QUERY, &status, NULL, 0);
-		break;
-	case CRYPT_S390_KMAC:
-		ret = crypt_s390_kmac(KMAC_QUERY, &status, NULL, 0);
-		break;
-	case CRYPT_S390_KMCTR:
-		ret = crypt_s390_kmctr(KMCTR_QUERY, &status,
-				       NULL, NULL, 0, NULL);
-		break;
-	case CRYPT_S390_PPNO:
-		ret = crypt_s390_ppno(PPNO_QUERY, &status,
-				      NULL, 0, NULL, 0);
-		break;
-	default:
-		return 0;
-	}
-	if (ret < 0)
-		return 0;
-	func &= CRYPT_S390_FUNC_MASK;
-	func &= 0x7f;		/* mask modifier bit */
-	return (status[func >> 3] & (0x80 >> (func & 7))) != 0;
-}
-
-/**
- * crypt_s390_pcc:
- * @func: the function code passed to KM; see crypt_s390_km_func
- * @param: address of parameter block; see POP for details on each func
- *
- * Executes the PCC (PERFORM CRYPTOGRAPHIC COMPUTATION) operation of the CPU.
- *
- * Returns -1 for failure, 0 for success.
- */
-static inline int crypt_s390_pcc(long func, void *param)
-{
-	register long __func asm("0") = func & 0x7f; /* encrypt or decrypt */
-	register void *__param asm("1") = param;
-	int ret = -1;
-
-	asm volatile(
-		"0:	.insn	rre,0xb92c0000,0,0\n" /* PCC opcode */
-		"1:	brc	1,0b\n" /* handle partial completion */
-		"	la	%0,0\n"
-		"2:\n"
-		EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
-		: "+d" (ret)
-		: "d" (__func), "a" (__param) : "cc", "memory");
-	return ret;
-}
-
-#endif	/* _CRYPTO_ARCH_S390_CRYPT_S390_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/crypto/des_s390.c linux-libre-4.7-gnu/arch/s390/crypto/des_s390.c
--- linux-libre-4.6-gnu/arch/s390/crypto/des_s390.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/crypto/des_s390.c	2016-07-24 15:23:50.000000000 -0400
@@ -20,8 +20,7 @@
 #include <linux/crypto.h>
 #include <crypto/algapi.h>
 #include <crypto/des.h>
-
-#include "crypt_s390.h"
+#include <asm/cpacf.h>
 
 #define DES3_KEY_SIZE	(3 * DES_KEY_SIZE)
 
@@ -54,20 +53,20 @@ static void des_encrypt(struct crypto_tf
 {
 	struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm);
 
-	crypt_s390_km(KM_DEA_ENCRYPT, ctx->key, out, in, DES_BLOCK_SIZE);
+	cpacf_km(CPACF_KM_DEA_ENC, ctx->key, out, in, DES_BLOCK_SIZE);
 }
 
 static void des_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
 {
 	struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm);
 
-	crypt_s390_km(KM_DEA_DECRYPT, ctx->key, out, in, DES_BLOCK_SIZE);
+	cpacf_km(CPACF_KM_DEA_DEC, ctx->key, out, in, DES_BLOCK_SIZE);
 }
 
 static struct crypto_alg des_alg = {
 	.cra_name		=	"des",
 	.cra_driver_name	=	"des-s390",
-	.cra_priority		=	CRYPT_S390_PRIORITY,
+	.cra_priority		=	300,
 	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
 	.cra_blocksize		=	DES_BLOCK_SIZE,
 	.cra_ctxsize		=	sizeof(struct s390_des_ctx),
@@ -95,7 +94,7 @@ static int ecb_desall_crypt(struct blkci
 		u8 *out = walk->dst.virt.addr;
 		u8 *in = walk->src.virt.addr;
 
-		ret = crypt_s390_km(func, key, out, in, n);
+		ret = cpacf_km(func, key, out, in, n);
 		if (ret < 0 || ret != n)
 			return -EIO;
 
@@ -128,7 +127,7 @@ static int cbc_desall_crypt(struct blkci
 		u8 *out = walk->dst.virt.addr;
 		u8 *in = walk->src.virt.addr;
 
-		ret = crypt_s390_kmc(func, &param, out, in, n);
+		ret = cpacf_kmc(func, &param, out, in, n);
 		if (ret < 0 || ret != n)
 			return -EIO;
 
@@ -149,7 +148,7 @@ static int ecb_des_encrypt(struct blkcip
 	struct blkcipher_walk walk;
 
 	blkcipher_walk_init(&walk, dst, src, nbytes);
-	return ecb_desall_crypt(desc, KM_DEA_ENCRYPT, ctx->key, &walk);
+	return ecb_desall_crypt(desc, CPACF_KM_DEA_ENC, ctx->key, &walk);
 }
 
 static int ecb_des_decrypt(struct blkcipher_desc *desc,
@@ -160,13 +159,13 @@ static int ecb_des_decrypt(struct blkcip
 	struct blkcipher_walk walk;
 
 	blkcipher_walk_init(&walk, dst, src, nbytes);
-	return ecb_desall_crypt(desc, KM_DEA_DECRYPT, ctx->key, &walk);
+	return ecb_desall_crypt(desc, CPACF_KM_DEA_DEC, ctx->key, &walk);
 }
 
 static struct crypto_alg ecb_des_alg = {
 	.cra_name		=	"ecb(des)",
 	.cra_driver_name	=	"ecb-des-s390",
-	.cra_priority		=	CRYPT_S390_COMPOSITE_PRIORITY,
+	.cra_priority		=	400,	/* combo: des + ecb */
 	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER,
 	.cra_blocksize		=	DES_BLOCK_SIZE,
 	.cra_ctxsize		=	sizeof(struct s390_des_ctx),
@@ -190,7 +189,7 @@ static int cbc_des_encrypt(struct blkcip
 	struct blkcipher_walk walk;
 
 	blkcipher_walk_init(&walk, dst, src, nbytes);
-	return cbc_desall_crypt(desc, KMC_DEA_ENCRYPT, &walk);
+	return cbc_desall_crypt(desc, CPACF_KMC_DEA_ENC, &walk);
 }
 
 static int cbc_des_decrypt(struct blkcipher_desc *desc,
@@ -200,13 +199,13 @@ static int cbc_des_decrypt(struct blkcip
 	struct blkcipher_walk walk;
 
 	blkcipher_walk_init(&walk, dst, src, nbytes);
-	return cbc_desall_crypt(desc, KMC_DEA_DECRYPT, &walk);
+	return cbc_desall_crypt(desc, CPACF_KMC_DEA_DEC, &walk);
 }
 
 static struct crypto_alg cbc_des_alg = {
 	.cra_name		=	"cbc(des)",
 	.cra_driver_name	=	"cbc-des-s390",
-	.cra_priority		=	CRYPT_S390_COMPOSITE_PRIORITY,
+	.cra_priority		=	400,	/* combo: des + cbc */
 	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER,
 	.cra_blocksize		=	DES_BLOCK_SIZE,
 	.cra_ctxsize		=	sizeof(struct s390_des_ctx),
@@ -258,20 +257,20 @@ static void des3_encrypt(struct crypto_t
 {
 	struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm);
 
-	crypt_s390_km(KM_TDEA_192_ENCRYPT, ctx->key, dst, src, DES_BLOCK_SIZE);
+	cpacf_km(CPACF_KM_TDEA_192_ENC, ctx->key, dst, src, DES_BLOCK_SIZE);
 }
 
 static void des3_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 {
 	struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm);
 
-	crypt_s390_km(KM_TDEA_192_DECRYPT, ctx->key, dst, src, DES_BLOCK_SIZE);
+	cpacf_km(CPACF_KM_TDEA_192_DEC, ctx->key, dst, src, DES_BLOCK_SIZE);
 }
 
 static struct crypto_alg des3_alg = {
 	.cra_name		=	"des3_ede",
 	.cra_driver_name	=	"des3_ede-s390",
-	.cra_priority		=	CRYPT_S390_PRIORITY,
+	.cra_priority		=	300,
 	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
 	.cra_blocksize		=	DES_BLOCK_SIZE,
 	.cra_ctxsize		=	sizeof(struct s390_des_ctx),
@@ -295,7 +294,7 @@ static int ecb_des3_encrypt(struct blkci
 	struct blkcipher_walk walk;
 
 	blkcipher_walk_init(&walk, dst, src, nbytes);
-	return ecb_desall_crypt(desc, KM_TDEA_192_ENCRYPT, ctx->key, &walk);
+	return ecb_desall_crypt(desc, CPACF_KM_TDEA_192_ENC, ctx->key, &walk);
 }
 
 static int ecb_des3_decrypt(struct blkcipher_desc *desc,
@@ -306,13 +305,13 @@ static int ecb_des3_decrypt(struct blkci
 	struct blkcipher_walk walk;
 
 	blkcipher_walk_init(&walk, dst, src, nbytes);
-	return ecb_desall_crypt(desc, KM_TDEA_192_DECRYPT, ctx->key, &walk);
+	return ecb_desall_crypt(desc, CPACF_KM_TDEA_192_DEC, ctx->key, &walk);
 }
 
 static struct crypto_alg ecb_des3_alg = {
 	.cra_name		=	"ecb(des3_ede)",
 	.cra_driver_name	=	"ecb-des3_ede-s390",
-	.cra_priority		=	CRYPT_S390_COMPOSITE_PRIORITY,
+	.cra_priority		=	400,	/* combo: des3 + ecb */
 	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER,
 	.cra_blocksize		=	DES_BLOCK_SIZE,
 	.cra_ctxsize		=	sizeof(struct s390_des_ctx),
@@ -336,7 +335,7 @@ static int cbc_des3_encrypt(struct blkci
 	struct blkcipher_walk walk;
 
 	blkcipher_walk_init(&walk, dst, src, nbytes);
-	return cbc_desall_crypt(desc, KMC_TDEA_192_ENCRYPT, &walk);
+	return cbc_desall_crypt(desc, CPACF_KMC_TDEA_192_ENC, &walk);
 }
 
 static int cbc_des3_decrypt(struct blkcipher_desc *desc,
@@ -346,13 +345,13 @@ static int cbc_des3_decrypt(struct blkci
 	struct blkcipher_walk walk;
 
 	blkcipher_walk_init(&walk, dst, src, nbytes);
-	return cbc_desall_crypt(desc, KMC_TDEA_192_DECRYPT, &walk);
+	return cbc_desall_crypt(desc, CPACF_KMC_TDEA_192_DEC, &walk);
 }
 
 static struct crypto_alg cbc_des3_alg = {
 	.cra_name		=	"cbc(des3_ede)",
 	.cra_driver_name	=	"cbc-des3_ede-s390",
-	.cra_priority		=	CRYPT_S390_COMPOSITE_PRIORITY,
+	.cra_priority		=	400,	/* combo: des3 + cbc */
 	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER,
 	.cra_blocksize		=	DES_BLOCK_SIZE,
 	.cra_ctxsize		=	sizeof(struct s390_des_ctx),
@@ -407,8 +406,7 @@ static int ctr_desall_crypt(struct blkci
 				n = __ctrblk_init(ctrptr, nbytes);
 			else
 				n = DES_BLOCK_SIZE;
-			ret = crypt_s390_kmctr(func, ctx->key, out, in,
-					       n, ctrptr);
+			ret = cpacf_kmctr(func, ctx->key, out, in, n, ctrptr);
 			if (ret < 0 || ret != n) {
 				if (ctrptr == ctrblk)
 					spin_unlock(&ctrblk_lock);
@@ -438,8 +436,8 @@ static int ctr_desall_crypt(struct blkci
 	if (nbytes) {
 		out = walk->dst.virt.addr;
 		in = walk->src.virt.addr;
-		ret = crypt_s390_kmctr(func, ctx->key, buf, in,
-				       DES_BLOCK_SIZE, ctrbuf);
+		ret = cpacf_kmctr(func, ctx->key, buf, in,
+				  DES_BLOCK_SIZE, ctrbuf);
 		if (ret < 0 || ret != DES_BLOCK_SIZE)
 			return -EIO;
 		memcpy(out, buf, nbytes);
@@ -458,7 +456,7 @@ static int ctr_des_encrypt(struct blkcip
 	struct blkcipher_walk walk;
 
 	blkcipher_walk_init(&walk, dst, src, nbytes);
-	return ctr_desall_crypt(desc, KMCTR_DEA_ENCRYPT, ctx, &walk);
+	return ctr_desall_crypt(desc, CPACF_KMCTR_DEA_ENC, ctx, &walk);
 }
 
 static int ctr_des_decrypt(struct blkcipher_desc *desc,
@@ -469,13 +467,13 @@ static int ctr_des_decrypt(struct blkcip
 	struct blkcipher_walk walk;
 
 	blkcipher_walk_init(&walk, dst, src, nbytes);
-	return ctr_desall_crypt(desc, KMCTR_DEA_DECRYPT, ctx, &walk);
+	return ctr_desall_crypt(desc, CPACF_KMCTR_DEA_DEC, ctx, &walk);
 }
 
 static struct crypto_alg ctr_des_alg = {
 	.cra_name		=	"ctr(des)",
 	.cra_driver_name	=	"ctr-des-s390",
-	.cra_priority		=	CRYPT_S390_COMPOSITE_PRIORITY,
+	.cra_priority		=	400,	/* combo: des + ctr */
 	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER,
 	.cra_blocksize		=	1,
 	.cra_ctxsize		=	sizeof(struct s390_des_ctx),
@@ -501,7 +499,7 @@ static int ctr_des3_encrypt(struct blkci
 	struct blkcipher_walk walk;
 
 	blkcipher_walk_init(&walk, dst, src, nbytes);
-	return ctr_desall_crypt(desc, KMCTR_TDEA_192_ENCRYPT, ctx, &walk);
+	return ctr_desall_crypt(desc, CPACF_KMCTR_TDEA_192_ENC, ctx, &walk);
 }
 
 static int ctr_des3_decrypt(struct blkcipher_desc *desc,
@@ -512,13 +510,13 @@ static int ctr_des3_decrypt(struct blkci
 	struct blkcipher_walk walk;
 
 	blkcipher_walk_init(&walk, dst, src, nbytes);
-	return ctr_desall_crypt(desc, KMCTR_TDEA_192_DECRYPT, ctx, &walk);
+	return ctr_desall_crypt(desc, CPACF_KMCTR_TDEA_192_DEC, ctx, &walk);
 }
 
 static struct crypto_alg ctr_des3_alg = {
 	.cra_name		=	"ctr(des3_ede)",
 	.cra_driver_name	=	"ctr-des3_ede-s390",
-	.cra_priority		=	CRYPT_S390_COMPOSITE_PRIORITY,
+	.cra_priority		=	400,	/* combo: des3 + ede */
 	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER,
 	.cra_blocksize		=	1,
 	.cra_ctxsize		=	sizeof(struct s390_des_ctx),
@@ -540,8 +538,8 @@ static int __init des_s390_init(void)
 {
 	int ret;
 
-	if (!crypt_s390_func_available(KM_DEA_ENCRYPT, CRYPT_S390_MSA) ||
-	    !crypt_s390_func_available(KM_TDEA_192_ENCRYPT, CRYPT_S390_MSA))
+	if (!cpacf_query(CPACF_KM, CPACF_KM_DEA_ENC) ||
+	    !cpacf_query(CPACF_KM, CPACF_KM_TDEA_192_ENC))
 		return -EOPNOTSUPP;
 
 	ret = crypto_register_alg(&des_alg);
@@ -563,10 +561,8 @@ static int __init des_s390_init(void)
 	if (ret)
 		goto cbc_des3_err;
 
-	if (crypt_s390_func_available(KMCTR_DEA_ENCRYPT,
-			CRYPT_S390_MSA | CRYPT_S390_MSA4) &&
-	    crypt_s390_func_available(KMCTR_TDEA_192_ENCRYPT,
-			CRYPT_S390_MSA | CRYPT_S390_MSA4)) {
+	if (cpacf_query(CPACF_KMCTR, CPACF_KMCTR_DEA_ENC) &&
+	    cpacf_query(CPACF_KMCTR, CPACF_KMCTR_TDEA_192_ENC)) {
 		ret = crypto_register_alg(&ctr_des_alg);
 		if (ret)
 			goto ctr_des_err;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/crypto/ghash_s390.c linux-libre-4.7-gnu/arch/s390/crypto/ghash_s390.c
--- linux-libre-4.6-gnu/arch/s390/crypto/ghash_s390.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/crypto/ghash_s390.c	2016-07-24 15:23:50.000000000 -0400
@@ -10,8 +10,7 @@
 #include <crypto/internal/hash.h>
 #include <linux/module.h>
 #include <linux/cpufeature.h>
-
-#include "crypt_s390.h"
+#include <asm/cpacf.h>
 
 #define GHASH_BLOCK_SIZE	16
 #define GHASH_DIGEST_SIZE	16
@@ -72,8 +71,8 @@ static int ghash_update(struct shash_des
 		src += n;
 
 		if (!dctx->bytes) {
-			ret = crypt_s390_kimd(KIMD_GHASH, dctx, buf,
-					      GHASH_BLOCK_SIZE);
+			ret = cpacf_kimd(CPACF_KIMD_GHASH, dctx, buf,
+					 GHASH_BLOCK_SIZE);
 			if (ret != GHASH_BLOCK_SIZE)
 				return -EIO;
 		}
@@ -81,7 +80,7 @@ static int ghash_update(struct shash_des
 
 	n = srclen & ~(GHASH_BLOCK_SIZE - 1);
 	if (n) {
-		ret = crypt_s390_kimd(KIMD_GHASH, dctx, src, n);
+		ret = cpacf_kimd(CPACF_KIMD_GHASH, dctx, src, n);
 		if (ret != n)
 			return -EIO;
 		src += n;
@@ -106,7 +105,7 @@ static int ghash_flush(struct ghash_desc
 
 		memset(pos, 0, dctx->bytes);
 
-		ret = crypt_s390_kimd(KIMD_GHASH, dctx, buf, GHASH_BLOCK_SIZE);
+		ret = cpacf_kimd(CPACF_KIMD_GHASH, dctx, buf, GHASH_BLOCK_SIZE);
 		if (ret != GHASH_BLOCK_SIZE)
 			return -EIO;
 
@@ -137,7 +136,7 @@ static struct shash_alg ghash_alg = {
 	.base		= {
 		.cra_name		= "ghash",
 		.cra_driver_name	= "ghash-s390",
-		.cra_priority		= CRYPT_S390_PRIORITY,
+		.cra_priority		= 300,
 		.cra_flags		= CRYPTO_ALG_TYPE_SHASH,
 		.cra_blocksize		= GHASH_BLOCK_SIZE,
 		.cra_ctxsize		= sizeof(struct ghash_ctx),
@@ -147,8 +146,7 @@ static struct shash_alg ghash_alg = {
 
 static int __init ghash_mod_init(void)
 {
-	if (!crypt_s390_func_available(KIMD_GHASH,
-				       CRYPT_S390_MSA | CRYPT_S390_MSA4))
+	if (!cpacf_query(CPACF_KIMD, CPACF_KIMD_GHASH))
 		return -EOPNOTSUPP;
 
 	return crypto_register_shash(&ghash_alg);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/crypto/prng.c linux-libre-4.7-gnu/arch/s390/crypto/prng.c
--- linux-libre-4.6-gnu/arch/s390/crypto/prng.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/crypto/prng.c	2016-07-24 15:23:50.000000000 -0400
@@ -23,8 +23,7 @@
 #include <asm/debug.h>
 #include <asm/uaccess.h>
 #include <asm/timex.h>
-
-#include "crypt_s390.h"
+#include <asm/cpacf.h>
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("IBM Corporation");
@@ -136,8 +135,8 @@ static int generate_entropy(u8 *ebuf, si
 		else
 			h = ebuf;
 		/* generate sha256 from this page */
-		if (crypt_s390_kimd(KIMD_SHA_256, h,
-				    pg, PAGE_SIZE) != PAGE_SIZE) {
+		if (cpacf_kimd(CPACF_KIMD_SHA_256, h,
+			       pg, PAGE_SIZE) != PAGE_SIZE) {
 			prng_errorflag = PRNG_GEN_ENTROPY_FAILED;
 			ret = -EIO;
 			goto out;
@@ -164,9 +163,9 @@ static void prng_tdes_add_entropy(void)
 	int ret;
 
 	for (i = 0; i < 16; i++) {
-		ret = crypt_s390_kmc(KMC_PRNG, prng_data->prngws.parm_block,
-				     (char *)entropy, (char *)entropy,
-				     sizeof(entropy));
+		ret = cpacf_kmc(CPACF_KMC_PRNG, prng_data->prngws.parm_block,
+				(char *)entropy, (char *)entropy,
+				sizeof(entropy));
 		BUG_ON(ret < 0 || ret != sizeof(entropy));
 		memcpy(prng_data->prngws.parm_block, entropy, sizeof(entropy));
 	}
@@ -311,9 +310,8 @@ static int __init prng_sha512_selftest(v
 	memset(&ws, 0, sizeof(ws));
 
 	/* initial seed */
-	ret = crypt_s390_ppno(PPNO_SHA512_DRNG_SEED,
-			      &ws, NULL, 0,
-			      seed, sizeof(seed));
+	ret = cpacf_ppno(CPACF_PPNO_SHA512_DRNG_SEED, &ws, NULL, 0,
+			 seed, sizeof(seed));
 	if (ret < 0) {
 		pr_err("The prng self test seed operation for the "
 		       "SHA-512 mode failed with rc=%d\n", ret);
@@ -331,18 +329,16 @@ static int __init prng_sha512_selftest(v
 	}
 
 	/* generate random bytes */
-	ret = crypt_s390_ppno(PPNO_SHA512_DRNG_GEN,
-			      &ws, buf, sizeof(buf),
-			      NULL, 0);
+	ret = cpacf_ppno(CPACF_PPNO_SHA512_DRNG_GEN,
+			 &ws, buf, sizeof(buf), NULL, 0);
 	if (ret < 0) {
 		pr_err("The prng self test generate operation for "
 		       "the SHA-512 mode failed with rc=%d\n", ret);
 		prng_errorflag = PRNG_SELFTEST_FAILED;
 		return -EIO;
 	}
-	ret = crypt_s390_ppno(PPNO_SHA512_DRNG_GEN,
-			      &ws, buf, sizeof(buf),
-			      NULL, 0);
+	ret = cpacf_ppno(CPACF_PPNO_SHA512_DRNG_GEN,
+			 &ws, buf, sizeof(buf), NULL, 0);
 	if (ret < 0) {
 		pr_err("The prng self test generate operation for "
 		       "the SHA-512 mode failed with rc=%d\n", ret);
@@ -396,9 +392,8 @@ static int __init prng_sha512_instantiat
 	get_tod_clock_ext(seed + 48);
 
 	/* initial seed of the ppno drng */
-	ret = crypt_s390_ppno(PPNO_SHA512_DRNG_SEED,
-			      &prng_data->ppnows, NULL, 0,
-			      seed, sizeof(seed));
+	ret = cpacf_ppno(CPACF_PPNO_SHA512_DRNG_SEED,
+			 &prng_data->ppnows, NULL, 0, seed, sizeof(seed));
 	if (ret < 0) {
 		prng_errorflag = PRNG_SEED_FAILED;
 		ret = -EIO;
@@ -409,11 +404,9 @@ static int __init prng_sha512_instantiat
 	   bytes for the FIPS 140-2 Conditional Self Test */
 	if (fips_enabled) {
 		prng_data->prev = prng_data->buf + prng_chunk_size;
-		ret = crypt_s390_ppno(PPNO_SHA512_DRNG_GEN,
-				      &prng_data->ppnows,
-				      prng_data->prev,
-				      prng_chunk_size,
-				      NULL, 0);
+		ret = cpacf_ppno(CPACF_PPNO_SHA512_DRNG_GEN,
+				 &prng_data->ppnows,
+				 prng_data->prev, prng_chunk_size, NULL, 0);
 		if (ret < 0 || ret != prng_chunk_size) {
 			prng_errorflag = PRNG_GEN_FAILED;
 			ret = -EIO;
@@ -447,9 +440,8 @@ static int prng_sha512_reseed(void)
 		return ret;
 
 	/* do a reseed of the ppno drng with this bytestring */
-	ret = crypt_s390_ppno(PPNO_SHA512_DRNG_SEED,
-			      &prng_data->ppnows, NULL, 0,
-			      seed, sizeof(seed));
+	ret = cpacf_ppno(CPACF_PPNO_SHA512_DRNG_SEED,
+			 &prng_data->ppnows, NULL, 0, seed, sizeof(seed));
 	if (ret) {
 		prng_errorflag = PRNG_RESEED_FAILED;
 		return -EIO;
@@ -471,9 +463,8 @@ static int prng_sha512_generate(u8 *buf,
 	}
 
 	/* PPNO generate */
-	ret = crypt_s390_ppno(PPNO_SHA512_DRNG_GEN,
-			      &prng_data->ppnows, buf, nbytes,
-			      NULL, 0);
+	ret = cpacf_ppno(CPACF_PPNO_SHA512_DRNG_GEN,
+			 &prng_data->ppnows, buf, nbytes, NULL, 0);
 	if (ret < 0 || ret != nbytes) {
 		prng_errorflag = PRNG_GEN_FAILED;
 		return -EIO;
@@ -555,8 +546,8 @@ static ssize_t prng_tdes_read(struct fil
 		 * Note: you can still get strict X9.17 conformity by setting
 		 * prng_chunk_size to 8 bytes.
 		*/
-		tmp = crypt_s390_kmc(KMC_PRNG, prng_data->prngws.parm_block,
-				     prng_data->buf, prng_data->buf, n);
+		tmp = cpacf_kmc(CPACF_KMC_PRNG, prng_data->prngws.parm_block,
+				prng_data->buf, prng_data->buf, n);
 		if (tmp < 0 || tmp != n) {
 			ret = -EIO;
 			break;
@@ -815,14 +806,13 @@ static int __init prng_init(void)
 	int ret;
 
 	/* check if the CPU has a PRNG */
-	if (!crypt_s390_func_available(KMC_PRNG, CRYPT_S390_MSA))
+	if (!cpacf_query(CPACF_KMC, CPACF_KMC_PRNG))
 		return -EOPNOTSUPP;
 
 	/* choose prng mode */
 	if (prng_mode != PRNG_MODE_TDES) {
 		/* check for MSA5 support for PPNO operations */
-		if (!crypt_s390_func_available(PPNO_SHA512_DRNG_GEN,
-					       CRYPT_S390_MSA5)) {
+		if (!cpacf_query(CPACF_PPNO, CPACF_PPNO_SHA512_DRNG_GEN)) {
 			if (prng_mode == PRNG_MODE_SHA512) {
 				pr_err("The prng module cannot "
 				       "start in SHA-512 mode\n");
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/crypto/sha1_s390.c linux-libre-4.7-gnu/arch/s390/crypto/sha1_s390.c
--- linux-libre-4.6-gnu/arch/s390/crypto/sha1_s390.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/crypto/sha1_s390.c	2016-07-24 15:23:50.000000000 -0400
@@ -28,8 +28,8 @@
 #include <linux/module.h>
 #include <linux/cpufeature.h>
 #include <crypto/sha.h>
+#include <asm/cpacf.h>
 
-#include "crypt_s390.h"
 #include "sha.h"
 
 static int sha1_init(struct shash_desc *desc)
@@ -42,7 +42,7 @@ static int sha1_init(struct shash_desc *
 	sctx->state[3] = SHA1_H3;
 	sctx->state[4] = SHA1_H4;
 	sctx->count = 0;
-	sctx->func = KIMD_SHA_1;
+	sctx->func = CPACF_KIMD_SHA_1;
 
 	return 0;
 }
@@ -66,7 +66,7 @@ static int sha1_import(struct shash_desc
 	sctx->count = ictx->count;
 	memcpy(sctx->state, ictx->state, sizeof(ictx->state));
 	memcpy(sctx->buf, ictx->buffer, sizeof(ictx->buffer));
-	sctx->func = KIMD_SHA_1;
+	sctx->func = CPACF_KIMD_SHA_1;
 	return 0;
 }
 
@@ -82,7 +82,7 @@ static struct shash_alg alg = {
 	.base		=	{
 		.cra_name	=	"sha1",
 		.cra_driver_name=	"sha1-s390",
-		.cra_priority	=	CRYPT_S390_PRIORITY,
+		.cra_priority	=	300,
 		.cra_flags	=	CRYPTO_ALG_TYPE_SHASH,
 		.cra_blocksize	=	SHA1_BLOCK_SIZE,
 		.cra_module	=	THIS_MODULE,
@@ -91,7 +91,7 @@ static struct shash_alg alg = {
 
 static int __init sha1_s390_init(void)
 {
-	if (!crypt_s390_func_available(KIMD_SHA_1, CRYPT_S390_MSA))
+	if (!cpacf_query(CPACF_KIMD, CPACF_KIMD_SHA_1))
 		return -EOPNOTSUPP;
 	return crypto_register_shash(&alg);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/crypto/sha256_s390.c linux-libre-4.7-gnu/arch/s390/crypto/sha256_s390.c
--- linux-libre-4.6-gnu/arch/s390/crypto/sha256_s390.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/crypto/sha256_s390.c	2016-07-24 15:23:50.000000000 -0400
@@ -18,8 +18,8 @@
 #include <linux/module.h>
 #include <linux/cpufeature.h>
 #include <crypto/sha.h>
+#include <asm/cpacf.h>
 
-#include "crypt_s390.h"
 #include "sha.h"
 
 static int sha256_init(struct shash_desc *desc)
@@ -35,7 +35,7 @@ static int sha256_init(struct shash_desc
 	sctx->state[6] = SHA256_H6;
 	sctx->state[7] = SHA256_H7;
 	sctx->count = 0;
-	sctx->func = KIMD_SHA_256;
+	sctx->func = CPACF_KIMD_SHA_256;
 
 	return 0;
 }
@@ -59,7 +59,7 @@ static int sha256_import(struct shash_de
 	sctx->count = ictx->count;
 	memcpy(sctx->state, ictx->state, sizeof(ictx->state));
 	memcpy(sctx->buf, ictx->buf, sizeof(ictx->buf));
-	sctx->func = KIMD_SHA_256;
+	sctx->func = CPACF_KIMD_SHA_256;
 	return 0;
 }
 
@@ -75,7 +75,7 @@ static struct shash_alg sha256_alg = {
 	.base		=	{
 		.cra_name	=	"sha256",
 		.cra_driver_name=	"sha256-s390",
-		.cra_priority	=	CRYPT_S390_PRIORITY,
+		.cra_priority	=	300,
 		.cra_flags	=	CRYPTO_ALG_TYPE_SHASH,
 		.cra_blocksize	=	SHA256_BLOCK_SIZE,
 		.cra_module	=	THIS_MODULE,
@@ -95,7 +95,7 @@ static int sha224_init(struct shash_desc
 	sctx->state[6] = SHA224_H6;
 	sctx->state[7] = SHA224_H7;
 	sctx->count = 0;
-	sctx->func = KIMD_SHA_256;
+	sctx->func = CPACF_KIMD_SHA_256;
 
 	return 0;
 }
@@ -112,7 +112,7 @@ static struct shash_alg sha224_alg = {
 	.base		=	{
 		.cra_name	=	"sha224",
 		.cra_driver_name=	"sha224-s390",
-		.cra_priority	=	CRYPT_S390_PRIORITY,
+		.cra_priority	=	300,
 		.cra_flags	=	CRYPTO_ALG_TYPE_SHASH,
 		.cra_blocksize	=	SHA224_BLOCK_SIZE,
 		.cra_module	=	THIS_MODULE,
@@ -123,7 +123,7 @@ static int __init sha256_s390_init(void)
 {
 	int ret;
 
-	if (!crypt_s390_func_available(KIMD_SHA_256, CRYPT_S390_MSA))
+	if (!cpacf_query(CPACF_KIMD, CPACF_KIMD_SHA_256))
 		return -EOPNOTSUPP;
 	ret = crypto_register_shash(&sha256_alg);
 	if (ret < 0)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/crypto/sha512_s390.c linux-libre-4.7-gnu/arch/s390/crypto/sha512_s390.c
--- linux-libre-4.6-gnu/arch/s390/crypto/sha512_s390.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/crypto/sha512_s390.c	2016-07-24 15:23:50.000000000 -0400
@@ -19,9 +19,9 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/cpufeature.h>
+#include <asm/cpacf.h>
 
 #include "sha.h"
-#include "crypt_s390.h"
 
 static int sha512_init(struct shash_desc *desc)
 {
@@ -36,7 +36,7 @@ static int sha512_init(struct shash_desc
 	*(__u64 *)&ctx->state[12] = 0x1f83d9abfb41bd6bULL;
 	*(__u64 *)&ctx->state[14] = 0x5be0cd19137e2179ULL;
 	ctx->count = 0;
-	ctx->func = KIMD_SHA_512;
+	ctx->func = CPACF_KIMD_SHA_512;
 
 	return 0;
 }
@@ -64,7 +64,7 @@ static int sha512_import(struct shash_de
 
 	memcpy(sctx->state, ictx->state, sizeof(ictx->state));
 	memcpy(sctx->buf, ictx->buf, sizeof(ictx->buf));
-	sctx->func = KIMD_SHA_512;
+	sctx->func = CPACF_KIMD_SHA_512;
 	return 0;
 }
 
@@ -80,7 +80,7 @@ static struct shash_alg sha512_alg = {
 	.base		=	{
 		.cra_name	=	"sha512",
 		.cra_driver_name=	"sha512-s390",
-		.cra_priority	=	CRYPT_S390_PRIORITY,
+		.cra_priority	=	300,
 		.cra_flags	=	CRYPTO_ALG_TYPE_SHASH,
 		.cra_blocksize	=	SHA512_BLOCK_SIZE,
 		.cra_module	=	THIS_MODULE,
@@ -102,7 +102,7 @@ static int sha384_init(struct shash_desc
 	*(__u64 *)&ctx->state[12] = 0xdb0c2e0d64f98fa7ULL;
 	*(__u64 *)&ctx->state[14] = 0x47b5481dbefa4fa4ULL;
 	ctx->count = 0;
-	ctx->func = KIMD_SHA_512;
+	ctx->func = CPACF_KIMD_SHA_512;
 
 	return 0;
 }
@@ -119,7 +119,7 @@ static struct shash_alg sha384_alg = {
 	.base		=	{
 		.cra_name	=	"sha384",
 		.cra_driver_name=	"sha384-s390",
-		.cra_priority	=	CRYPT_S390_PRIORITY,
+		.cra_priority	=	300,
 		.cra_flags	=	CRYPTO_ALG_TYPE_SHASH,
 		.cra_blocksize	=	SHA384_BLOCK_SIZE,
 		.cra_ctxsize	=	sizeof(struct s390_sha_ctx),
@@ -133,7 +133,7 @@ static int __init init(void)
 {
 	int ret;
 
-	if (!crypt_s390_func_available(KIMD_SHA_512, CRYPT_S390_MSA))
+	if (!cpacf_query(CPACF_KIMD, CPACF_KIMD_SHA_512))
 		return -EOPNOTSUPP;
 	if ((ret = crypto_register_shash(&sha512_alg)) < 0)
 		goto out;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/crypto/sha_common.c linux-libre-4.7-gnu/arch/s390/crypto/sha_common.c
--- linux-libre-4.6-gnu/arch/s390/crypto/sha_common.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/crypto/sha_common.c	2016-07-24 15:23:50.000000000 -0400
@@ -15,8 +15,8 @@
 
 #include <crypto/internal/hash.h>
 #include <linux/module.h>
+#include <asm/cpacf.h>
 #include "sha.h"
-#include "crypt_s390.h"
 
 int s390_sha_update(struct shash_desc *desc, const u8 *data, unsigned int len)
 {
@@ -35,7 +35,7 @@ int s390_sha_update(struct shash_desc *d
 	/* process one stored block */
 	if (index) {
 		memcpy(ctx->buf + index, data, bsize - index);
-		ret = crypt_s390_kimd(ctx->func, ctx->state, ctx->buf, bsize);
+		ret = cpacf_kimd(ctx->func, ctx->state, ctx->buf, bsize);
 		if (ret != bsize)
 			return -EIO;
 		data += bsize - index;
@@ -45,8 +45,8 @@ int s390_sha_update(struct shash_desc *d
 
 	/* process as many blocks as possible */
 	if (len >= bsize) {
-		ret = crypt_s390_kimd(ctx->func, ctx->state, data,
-				      len & ~(bsize - 1));
+		ret = cpacf_kimd(ctx->func, ctx->state, data,
+				 len & ~(bsize - 1));
 		if (ret != (len & ~(bsize - 1)))
 			return -EIO;
 		data += ret;
@@ -89,7 +89,7 @@ int s390_sha_final(struct shash_desc *de
 	bits = ctx->count * 8;
 	memcpy(ctx->buf + end - 8, &bits, sizeof(bits));
 
-	ret = crypt_s390_kimd(ctx->func, ctx->state, ctx->buf, end);
+	ret = cpacf_kimd(ctx->func, ctx->state, ctx->buf, end);
 	if (ret != end)
 		return -EIO;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/defconfig linux-libre-4.7-gnu/arch/s390/defconfig
--- linux-libre-4.6-gnu/arch/s390/defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -1,8 +1,8 @@
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
-CONFIG_FHANDLE=y
+CONFIG_USELIB=y
 CONFIG_AUDIT=y
-CONFIG_NO_HZ=y
+CONFIG_NO_HZ_IDLE=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_TASKSTATS=y
 CONFIG_TASK_DELAY_ACCT=y
@@ -11,19 +11,19 @@ CONFIG_TASK_IO_ACCOUNTING=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_CGROUPS=y
-CONFIG_CGROUP_FREEZER=y
-CONFIG_CGROUP_PIDS=y
-CONFIG_CGROUP_DEVICE=y
-CONFIG_CPUSETS=y
-CONFIG_CGROUP_CPUACCT=y
 CONFIG_MEMCG=y
 CONFIG_MEMCG_SWAP=y
-CONFIG_MEMCG_KMEM=y
-CONFIG_CGROUP_HUGETLB=y
-CONFIG_CGROUP_PERF=y
+CONFIG_BLK_CGROUP=y
 CONFIG_CGROUP_SCHED=y
 CONFIG_RT_GROUP_SCHED=y
-CONFIG_BLK_CGROUP=y
+CONFIG_CGROUP_PIDS=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_HUGETLB=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_PERF=y
+CONFIG_CHECKPOINT_RESTORE=y
 CONFIG_NAMESPACES=y
 CONFIG_USER_NS=y
 CONFIG_BLK_DEV_INITRD=y
@@ -44,7 +44,6 @@ CONFIG_PARTITION_ADVANCED=y
 CONFIG_IBM_PARTITION=y
 CONFIG_DEFAULT_DEADLINE=y
 CONFIG_LIVEPATCH=y
-CONFIG_MARCH_Z196=y
 CONFIG_NR_CPUS=256
 CONFIG_NUMA=y
 CONFIG_HZ_100=y
@@ -52,6 +51,14 @@ CONFIG_MEMORY_HOTPLUG=y
 CONFIG_MEMORY_HOTREMOVE=y
 CONFIG_KSM=y
 CONFIG_TRANSPARENT_HUGEPAGE=y
+CONFIG_CLEANCACHE=y
+CONFIG_FRONTSWAP=y
+CONFIG_CMA=y
+CONFIG_ZSWAP=y
+CONFIG_ZBUD=m
+CONFIG_ZSMALLOC=m
+CONFIG_ZSMALLOC_STAT=y
+CONFIG_IDLE_PAGE_TRACKING=y
 CONFIG_CRASH_DUMP=y
 CONFIG_BINFMT_MISC=m
 CONFIG_HIBERNATION=y
@@ -61,7 +68,6 @@ CONFIG_UNIX=y
 CONFIG_NET_KEY=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
-# CONFIG_INET_LRO is not set
 CONFIG_L2TP=m
 CONFIG_L2TP_DEBUGFS=m
 CONFIG_VLAN_8021Q=y
@@ -144,6 +150,9 @@ CONFIG_TMPFS=y
 CONFIG_TMPFS_POSIX_ACL=y
 CONFIG_HUGETLBFS=y
 # CONFIG_NETWORK_FILESYSTEMS is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_INFO_DWARF4=y
+CONFIG_GDB_SCRIPTS=y
 CONFIG_UNUSED_SYMBOLS=y
 CONFIG_DEBUG_SECTION_MISMATCH=y
 CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y
@@ -158,20 +167,21 @@ CONFIG_LOCK_STAT=y
 CONFIG_DEBUG_LOCKDEP=y
 CONFIG_DEBUG_ATOMIC_SLEEP=y
 CONFIG_DEBUG_LIST=y
-CONFIG_DEBUG_PI_LIST=y
 CONFIG_DEBUG_SG=y
 CONFIG_DEBUG_NOTIFIERS=y
 CONFIG_RCU_CPU_STALL_TIMEOUT=60
 CONFIG_RCU_TRACE=y
 CONFIG_LATENCYTOP=y
 CONFIG_DEBUG_STRICT_USER_COPY_CHECKS=y
-CONFIG_TRACER_SNAPSHOT=y
+CONFIG_SCHED_TRACER=y
+CONFIG_FTRACE_SYSCALLS=y
 CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP=y
 CONFIG_STACK_TRACER=y
 CONFIG_BLK_DEV_IO_TRACE=y
 CONFIG_UPROBE_EVENT=y
+CONFIG_FUNCTION_PROFILER=y
+CONFIG_TRACE_ENUM_MAP_FILE=y
 CONFIG_KPROBES_SANITY_TEST=y
-# CONFIG_STRICT_DEVMEM is not set
 CONFIG_S390_PTDUMP=y
 CONFIG_CRYPTO_CRYPTD=m
 CONFIG_CRYPTO_AUTHENC=m
@@ -212,8 +222,6 @@ CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_ZLIB=m
-CONFIG_CRYPTO_LZO=m
 CONFIG_CRYPTO_LZ4=m
 CONFIG_CRYPTO_LZ4HC=m
 CONFIG_CRYPTO_ANSI_CPRNG=m
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/include/asm/cpacf.h linux-libre-4.7-gnu/arch/s390/include/asm/cpacf.h
--- linux-libre-4.6-gnu/arch/s390/include/asm/cpacf.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/s390/include/asm/cpacf.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,410 @@
+/*
+ * CP Assist for Cryptographic Functions (CPACF)
+ *
+ * Copyright IBM Corp. 2003, 2016
+ * Author(s): Thomas Spatzier
+ *	      Jan Glauber
+ *	      Harald Freudenberger (freude@de.ibm.com)
+ *	      Martin Schwidefsky <schwidefsky@de.ibm.com>
+ */
+#ifndef _ASM_S390_CPACF_H
+#define _ASM_S390_CPACF_H
+
+#include <asm/facility.h>
+
+/*
+ * Instruction opcodes for the CPACF instructions
+ */
+#define CPACF_KMAC		0xb91e		/* MSA	*/
+#define CPACF_KM		0xb92e		/* MSA	*/
+#define CPACF_KMC		0xb92f		/* MSA	*/
+#define CPACF_KIMD		0xb93e		/* MSA	*/
+#define CPACF_KLMD		0xb93f		/* MSA	*/
+#define CPACF_PCC		0xb92c		/* MSA4 */
+#define CPACF_KMCTR		0xb92d		/* MSA4 */
+#define CPACF_PPNO		0xb93c		/* MSA5 */
+
+/*
+ * Function codes for the KM (CIPHER MESSAGE)
+ * instruction (0x80 is the decipher modifier bit)
+ */
+#define CPACF_KM_QUERY		0x00
+#define CPACF_KM_DEA_ENC	0x01
+#define CPACF_KM_DEA_DEC	0x81
+#define CPACF_KM_TDEA_128_ENC	0x02
+#define CPACF_KM_TDEA_128_DEC	0x82
+#define CPACF_KM_TDEA_192_ENC	0x03
+#define CPACF_KM_TDEA_192_DEC	0x83
+#define CPACF_KM_AES_128_ENC	0x12
+#define CPACF_KM_AES_128_DEC	0x92
+#define CPACF_KM_AES_192_ENC	0x13
+#define CPACF_KM_AES_192_DEC	0x93
+#define CPACF_KM_AES_256_ENC	0x14
+#define CPACF_KM_AES_256_DEC	0x94
+#define CPACF_KM_XTS_128_ENC	0x32
+#define CPACF_KM_XTS_128_DEC	0xb2
+#define CPACF_KM_XTS_256_ENC	0x34
+#define CPACF_KM_XTS_256_DEC	0xb4
+
+/*
+ * Function codes for the KMC (CIPHER MESSAGE WITH CHAINING)
+ * instruction (0x80 is the decipher modifier bit)
+ */
+#define CPACF_KMC_QUERY		0x00
+#define CPACF_KMC_DEA_ENC	0x01
+#define CPACF_KMC_DEA_DEC	0x81
+#define CPACF_KMC_TDEA_128_ENC	0x02
+#define CPACF_KMC_TDEA_128_DEC	0x82
+#define CPACF_KMC_TDEA_192_ENC	0x03
+#define CPACF_KMC_TDEA_192_DEC	0x83
+#define CPACF_KMC_AES_128_ENC	0x12
+#define CPACF_KMC_AES_128_DEC	0x92
+#define CPACF_KMC_AES_192_ENC	0x13
+#define CPACF_KMC_AES_192_DEC	0x93
+#define CPACF_KMC_AES_256_ENC	0x14
+#define CPACF_KMC_AES_256_DEC	0x94
+#define CPACF_KMC_PRNG		0x43
+
+/*
+ * Function codes for the KMCTR (CIPHER MESSAGE WITH COUNTER)
+ * instruction (0x80 is the decipher modifier bit)
+ */
+#define CPACF_KMCTR_QUERY	 0x00
+#define CPACF_KMCTR_DEA_ENC	 0x01
+#define CPACF_KMCTR_DEA_DEC	 0x81
+#define CPACF_KMCTR_TDEA_128_ENC 0x02
+#define CPACF_KMCTR_TDEA_128_DEC 0x82
+#define CPACF_KMCTR_TDEA_192_ENC 0x03
+#define CPACF_KMCTR_TDEA_192_DEC 0x83
+#define CPACF_KMCTR_AES_128_ENC	 0x12
+#define CPACF_KMCTR_AES_128_DEC	 0x92
+#define CPACF_KMCTR_AES_192_ENC	 0x13
+#define CPACF_KMCTR_AES_192_DEC	 0x93
+#define CPACF_KMCTR_AES_256_ENC	 0x14
+#define CPACF_KMCTR_AES_256_DEC	 0x94
+
+/*
+ * Function codes for the KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST)
+ * instruction (0x80 is the decipher modifier bit)
+ */
+#define CPACF_KIMD_QUERY	0x00
+#define CPACF_KIMD_SHA_1	0x01
+#define CPACF_KIMD_SHA_256	0x02
+#define CPACF_KIMD_SHA_512	0x03
+#define CPACF_KIMD_GHASH	0x41
+
+/*
+ * Function codes for the KLMD (COMPUTE LAST MESSAGE DIGEST)
+ * instruction (0x80 is the decipher modifier bit)
+ */
+#define CPACF_KLMD_QUERY	0x00
+#define CPACF_KLMD_SHA_1	0x01
+#define CPACF_KLMD_SHA_256	0x02
+#define CPACF_KLMD_SHA_512	0x03
+
+/*
+ * function codes for the KMAC (COMPUTE MESSAGE AUTHENTICATION CODE)
+ * instruction (0x80 is the decipher modifier bit)
+ */
+#define CPACF_KMAC_QUERY	0x00
+#define CPACF_KMAC_DEA		0x01
+#define CPACF_KMAC_TDEA_128	0x02
+#define CPACF_KMAC_TDEA_192	0x03
+
+/*
+ * Function codes for the PPNO (PERFORM PSEUDORANDOM NUMBER OPERATION)
+ * instruction (0x80 is the decipher modifier bit)
+ */
+#define CPACF_PPNO_QUERY		0x00
+#define CPACF_PPNO_SHA512_DRNG_GEN	0x03
+#define CPACF_PPNO_SHA512_DRNG_SEED	0x83
+
+/**
+ * cpacf_query() - check if a specific CPACF function is available
+ * @opcode: the opcode of the crypto instruction
+ * @func: the function code to test for
+ *
+ * Executes the query function for the given crypto instruction @opcode
+ * and checks if @func is available
+ *
+ * Returns 1 if @func is available for @opcode, 0 otherwise
+ */
+static inline void __cpacf_query(unsigned int opcode, unsigned char *status)
+{
+	typedef struct { unsigned char _[16]; } status_type;
+	register unsigned long r0 asm("0") = 0;	/* query function */
+	register unsigned long r1 asm("1") = (unsigned long) status;
+
+	asm volatile(
+		/* Parameter registers are ignored, but may not be 0 */
+		"0:	.insn	rrf,%[opc] << 16,2,2,2,0\n"
+		"	brc	1,0b\n"	/* handle partial completion */
+		: "=m" (*(status_type *) status)
+		: [fc] "d" (r0), [pba] "a" (r1), [opc] "i" (opcode)
+		: "cc");
+}
+
+static inline int cpacf_query(unsigned int opcode, unsigned int func)
+{
+	unsigned char status[16];
+
+	switch (opcode) {
+	case CPACF_KMAC:
+	case CPACF_KM:
+	case CPACF_KMC:
+	case CPACF_KIMD:
+	case CPACF_KLMD:
+		if (!test_facility(17))	/* check for MSA */
+			return 0;
+		break;
+	case CPACF_PCC:
+	case CPACF_KMCTR:
+		if (!test_facility(77))	/* check for MSA4 */
+			return 0;
+		break;
+	case CPACF_PPNO:
+		if (!test_facility(57))	/* check for MSA5 */
+			return 0;
+		break;
+	default:
+		BUG();
+	}
+	__cpacf_query(opcode, status);
+	return (status[func >> 3] & (0x80 >> (func & 7))) != 0;
+}
+
+/**
+ * cpacf_km() - executes the KM (CIPHER MESSAGE) instruction
+ * @func: the function code passed to KM; see CPACF_KM_xxx defines
+ * @param: address of parameter block; see POP for details on each func
+ * @dest: address of destination memory area
+ * @src: address of source memory area
+ * @src_len: length of src operand in bytes
+ *
+ * Returns 0 for the query func, number of processed bytes for
+ * encryption/decryption funcs
+ */
+static inline int cpacf_km(long func, void *param,
+			   u8 *dest, const u8 *src, long src_len)
+{
+	register unsigned long r0 asm("0") = (unsigned long) func;
+	register unsigned long r1 asm("1") = (unsigned long) param;
+	register unsigned long r2 asm("2") = (unsigned long) src;
+	register unsigned long r3 asm("3") = (unsigned long) src_len;
+	register unsigned long r4 asm("4") = (unsigned long) dest;
+
+	asm volatile(
+		"0:	.insn	rre,%[opc] << 16,%[dst],%[src]\n"
+		"	brc	1,0b\n" /* handle partial completion */
+		: [src] "+a" (r2), [len] "+d" (r3), [dst] "+a" (r4)
+		: [fc] "d" (r0), [pba] "a" (r1), [opc] "i" (CPACF_KM)
+		: "cc", "memory");
+
+	return src_len - r3;
+}
+
+/**
+ * cpacf_kmc() - executes the KMC (CIPHER MESSAGE WITH CHAINING) instruction
+ * @func: the function code passed to KM; see CPACF_KMC_xxx defines
+ * @param: address of parameter block; see POP for details on each func
+ * @dest: address of destination memory area
+ * @src: address of source memory area
+ * @src_len: length of src operand in bytes
+ *
+ * Returns 0 for the query func, number of processed bytes for
+ * encryption/decryption funcs
+ */
+static inline int cpacf_kmc(long func, void *param,
+			    u8 *dest, const u8 *src, long src_len)
+{
+	register unsigned long r0 asm("0") = (unsigned long) func;
+	register unsigned long r1 asm("1") = (unsigned long) param;
+	register unsigned long r2 asm("2") = (unsigned long) src;
+	register unsigned long r3 asm("3") = (unsigned long) src_len;
+	register unsigned long r4 asm("4") = (unsigned long) dest;
+
+	asm volatile(
+		"0:	.insn	rre,%[opc] << 16,%[dst],%[src]\n"
+		"	brc	1,0b\n" /* handle partial completion */
+		: [src] "+a" (r2), [len] "+d" (r3), [dst] "+a" (r4)
+		: [fc] "d" (r0), [pba] "a" (r1), [opc] "i" (CPACF_KMC)
+		: "cc", "memory");
+
+	return src_len - r3;
+}
+
+/**
+ * cpacf_kimd() - executes the KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST)
+ *		  instruction
+ * @func: the function code passed to KM; see CPACF_KIMD_xxx defines
+ * @param: address of parameter block; see POP for details on each func
+ * @src: address of source memory area
+ * @src_len: length of src operand in bytes
+ *
+ * Returns 0 for the query func, number of processed bytes for digest funcs
+ */
+static inline int cpacf_kimd(long func, void *param,
+			     const u8 *src, long src_len)
+{
+	register unsigned long r0 asm("0") = (unsigned long) func;
+	register unsigned long r1 asm("1") = (unsigned long) param;
+	register unsigned long r2 asm("2") = (unsigned long) src;
+	register unsigned long r3 asm("3") = (unsigned long) src_len;
+
+	asm volatile(
+		"0:	.insn	rre,%[opc] << 16,0,%[src]\n"
+		"	brc	1,0b\n" /* handle partial completion */
+		: [src] "+a" (r2), [len] "+d" (r3)
+		: [fc] "d" (r0), [pba] "a" (r1), [opc] "i" (CPACF_KIMD)
+		: "cc", "memory");
+
+	return src_len - r3;
+}
+
+/**
+ * cpacf_klmd() - executes the KLMD (COMPUTE LAST MESSAGE DIGEST) instruction
+ * @func: the function code passed to KM; see CPACF_KLMD_xxx defines
+ * @param: address of parameter block; see POP for details on each func
+ * @src: address of source memory area
+ * @src_len: length of src operand in bytes
+ *
+ * Returns 0 for the query func, number of processed bytes for digest funcs
+ */
+static inline int cpacf_klmd(long func, void *param,
+			     const u8 *src, long src_len)
+{
+	register unsigned long r0 asm("0") = (unsigned long) func;
+	register unsigned long r1 asm("1") = (unsigned long) param;
+	register unsigned long r2 asm("2") = (unsigned long) src;
+	register unsigned long r3 asm("3") = (unsigned long) src_len;
+
+	asm volatile(
+		"0:	.insn	rre,%[opc] << 16,0,%[src]\n"
+		"	brc	1,0b\n" /* handle partial completion */
+		: [src] "+a" (r2), [len] "+d" (r3)
+		: [fc] "d" (r0), [pba] "a" (r1), [opc] "i" (CPACF_KLMD)
+		: "cc", "memory");
+
+	return src_len - r3;
+}
+
+/**
+ * cpacf_kmac() - executes the KMAC (COMPUTE MESSAGE AUTHENTICATION CODE)
+ *		  instruction
+ * @func: the function code passed to KM; see CPACF_KMAC_xxx defines
+ * @param: address of parameter block; see POP for details on each func
+ * @src: address of source memory area
+ * @src_len: length of src operand in bytes
+ *
+ * Returns 0 for the query func, number of processed bytes for digest funcs
+ */
+static inline int cpacf_kmac(long func, void *param,
+			     const u8 *src, long src_len)
+{
+	register unsigned long r0 asm("0") = (unsigned long) func;
+	register unsigned long r1 asm("1") = (unsigned long) param;
+	register unsigned long r2 asm("2") = (unsigned long) src;
+	register unsigned long r3 asm("3") = (unsigned long) src_len;
+
+	asm volatile(
+		"0:	.insn	rre,%[opc] << 16,0,%[src]\n"
+		"	brc	1,0b\n" /* handle partial completion */
+		: [src] "+a" (r2), [len] "+d" (r3)
+		: [fc] "d" (r0), [pba] "a" (r1), [opc] "i" (CPACF_KMAC)
+		: "cc", "memory");
+
+	return src_len - r3;
+}
+
+/**
+ * cpacf_kmctr() - executes the KMCTR (CIPHER MESSAGE WITH COUNTER) instruction
+ * @func: the function code passed to KMCTR; see CPACF_KMCTR_xxx defines
+ * @param: address of parameter block; see POP for details on each func
+ * @dest: address of destination memory area
+ * @src: address of source memory area
+ * @src_len: length of src operand in bytes
+ * @counter: address of counter value
+ *
+ * Returns 0 for the query func, number of processed bytes for
+ * encryption/decryption funcs
+ */
+static inline int cpacf_kmctr(long func, void *param, u8 *dest,
+			      const u8 *src, long src_len, u8 *counter)
+{
+	register unsigned long r0 asm("0") = (unsigned long) func;
+	register unsigned long r1 asm("1") = (unsigned long) param;
+	register unsigned long r2 asm("2") = (unsigned long) src;
+	register unsigned long r3 asm("3") = (unsigned long) src_len;
+	register unsigned long r4 asm("4") = (unsigned long) dest;
+	register unsigned long r6 asm("6") = (unsigned long) counter;
+
+	asm volatile(
+		"0:	.insn	rrf,%[opc] << 16,%[dst],%[src],%[ctr],0\n"
+		"	brc	1,0b\n" /* handle partial completion */
+		: [src] "+a" (r2), [len] "+d" (r3),
+		  [dst] "+a" (r4), [ctr] "+a" (r6)
+		: [fc] "d" (r0), [pba] "a" (r1), [opc] "i" (CPACF_KMCTR)
+		: "cc", "memory");
+
+	return src_len - r3;
+}
+
+/**
+ * cpacf_ppno() - executes the PPNO (PERFORM PSEUDORANDOM NUMBER OPERATION)
+ *		  instruction
+ * @func: the function code passed to PPNO; see CPACF_PPNO_xxx defines
+ * @param: address of parameter block; see POP for details on each func
+ * @dest: address of destination memory area
+ * @dest_len: size of destination memory area in bytes
+ * @seed: address of seed data
+ * @seed_len: size of seed data in bytes
+ *
+ * Returns 0 for the query func, number of random bytes stored in
+ * dest buffer for generate function
+ */
+static inline int cpacf_ppno(long func, void *param,
+			     u8 *dest, long dest_len,
+			     const u8 *seed, long seed_len)
+{
+	register unsigned long r0 asm("0") = (unsigned long) func;
+	register unsigned long r1 asm("1") = (unsigned long) param;
+	register unsigned long r2 asm("2") = (unsigned long) dest;
+	register unsigned long r3 asm("3") = (unsigned long) dest_len;
+	register unsigned long r4 asm("4") = (unsigned long) seed;
+	register unsigned long r5 asm("5") = (unsigned long) seed_len;
+
+	asm volatile (
+		"0:	.insn	rre,%[opc] << 16,%[dst],%[seed]\n"
+		"	brc	1,0b\n"	  /* handle partial completion */
+		: [dst] "+a" (r2), [dlen] "+d" (r3)
+		: [fc] "d" (r0), [pba] "a" (r1),
+		  [seed] "a" (r4), [slen] "d" (r5), [opc] "i" (CPACF_PPNO)
+		: "cc", "memory");
+
+	return dest_len - r3;
+}
+
+/**
+ * cpacf_pcc() - executes the PCC (PERFORM CRYPTOGRAPHIC COMPUTATION)
+ *		 instruction
+ * @func: the function code passed to PCC; see CPACF_KM_xxx defines
+ * @param: address of parameter block; see POP for details on each func
+ *
+ * Returns 0.
+ */
+static inline int cpacf_pcc(long func, void *param)
+{
+	register unsigned long r0 asm("0") = (unsigned long) func;
+	register unsigned long r1 asm("1") = (unsigned long) param;
+
+	asm volatile(
+		"0:	.insn	rre,%[opc] << 16,0,0\n" /* PCC opcode */
+		"	brc	1,0b\n" /* handle partial completion */
+		:
+		: [fc] "d" (r0), [pba] "a" (r1), [opc] "i" (CPACF_PCC)
+		: "cc", "memory");
+
+	return 0;
+}
+
+#endif	/* _ASM_S390_CPACF_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/include/asm/fpu/api.h linux-libre-4.7-gnu/arch/s390/include/asm/fpu/api.h
--- linux-libre-4.6-gnu/arch/s390/include/asm/fpu/api.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/include/asm/fpu/api.h	2016-07-24 15:23:50.000000000 -0400
@@ -22,7 +22,7 @@ static inline int test_fp_ctl(u32 fpc)
 		"	la	%0,0\n"
 		"1:\n"
 		EX_TABLE(0b,1b)
-		: "=d" (rc), "=d" (orig_fpc)
+		: "=d" (rc), "=&d" (orig_fpc)
 		: "d" (fpc), "0" (-EINVAL));
 	return rc;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/include/asm/fpu/types.h linux-libre-4.7-gnu/arch/s390/include/asm/fpu/types.h
--- linux-libre-4.6-gnu/arch/s390/include/asm/fpu/types.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/include/asm/fpu/types.h	2016-07-24 15:23:50.000000000 -0400
@@ -11,11 +11,13 @@
 #include <asm/sigcontext.h>
 
 struct fpu {
-	__u32 fpc;			/* Floating-point control */
+	__u32 fpc;		/* Floating-point control */
+	void *regs;		/* Pointer to the current save area */
 	union {
-		void *regs;
-		freg_t *fprs;		/* Floating-point register save area */
-		__vector128 *vxrs;	/* Vector register save area */
+		/* Floating-point register save area */
+		freg_t fprs[__NUM_FPRS];
+		/* Vector register save area */
+		__vector128 vxrs[__NUM_VXRS];
 	};
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/include/asm/ftrace.h linux-libre-4.7-gnu/arch/s390/include/asm/ftrace.h
--- linux-libre-4.6-gnu/arch/s390/include/asm/ftrace.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/include/asm/ftrace.h	2016-07-24 15:23:50.000000000 -0400
@@ -12,7 +12,9 @@
 
 #ifndef __ASSEMBLY__
 
-#define ftrace_return_address(n) __builtin_return_address(n)
+unsigned long return_address(int depth);
+
+#define ftrace_return_address(n) return_address(n)
 
 void _mcount(void);
 void ftrace_caller(void);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/include/asm/kvm_host.h linux-libre-4.7-gnu/arch/s390/include/asm/kvm_host.h
--- linux-libre-4.6-gnu/arch/s390/include/asm/kvm_host.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/include/asm/kvm_host.h	2016-07-24 15:23:50.000000000 -0400
@@ -38,7 +38,7 @@
  */
 #define KVM_NR_IRQCHIPS 1
 #define KVM_IRQCHIP_NUM_PINS 4096
-#define KVM_HALT_POLL_NS_DEFAULT 0
+#define KVM_HALT_POLL_NS_DEFAULT 80000
 
 /* s390-specific vcpu->requests bit members */
 #define KVM_REQ_ENABLE_IBS         8
@@ -245,8 +245,10 @@ struct kvm_vcpu_stat {
 	u32 exit_stop_request;
 	u32 exit_validity;
 	u32 exit_instruction;
+	u32 exit_pei;
 	u32 halt_successful_poll;
 	u32 halt_attempted_poll;
+	u32 halt_poll_invalid;
 	u32 halt_wakeup;
 	u32 instruction_lctl;
 	u32 instruction_lctlg;
@@ -544,10 +546,6 @@ struct kvm_vcpu_arch {
 	struct kvm_s390_local_interrupt local_int;
 	struct hrtimer    ckc_timer;
 	struct kvm_s390_pgm_info pgm;
-	union  {
-		struct cpuid	cpu_id;
-		u64		stidp_data;
-	};
 	struct gmap *gmap;
 	struct kvm_guestdbg_info_arch guestdbg;
 	unsigned long pfault_token;
@@ -605,7 +603,7 @@ struct kvm_s390_cpu_model {
 	__u64 fac_mask[S390_ARCH_FAC_LIST_SIZE_U64];
 	/* facility list requested by guest (in dma page) */
 	__u64 *fac_list;
-	struct cpuid cpu_id;
+	u64 cpuid;
 	unsigned short ibc;
 };
 
@@ -700,4 +698,6 @@ static inline void kvm_arch_flush_shadow
 static inline void kvm_arch_vcpu_blocking(struct kvm_vcpu *vcpu) {}
 static inline void kvm_arch_vcpu_unblocking(struct kvm_vcpu *vcpu) {}
 
+void kvm_arch_vcpu_block_finish(struct kvm_vcpu *vcpu);
+
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/include/asm/livepatch.h linux-libre-4.7-gnu/arch/s390/include/asm/livepatch.h
--- linux-libre-4.6-gnu/arch/s390/include/asm/livepatch.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/include/asm/livepatch.h	2016-07-24 15:23:50.000000000 -0400
@@ -24,13 +24,6 @@ static inline int klp_check_compiler_sup
 	return 0;
 }
 
-static inline int klp_write_module_reloc(struct module *mod, unsigned long
-		type, unsigned long loc, unsigned long value)
-{
-	/* not supported yet */
-	return -ENOSYS;
-}
-
 static inline void klp_arch_set_pc(struct pt_regs *regs, unsigned long ip)
 {
 	regs->psw.addr = ip;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/include/asm/pci.h linux-libre-4.7-gnu/arch/s390/include/asm/pci.h
--- linux-libre-4.6-gnu/arch/s390/include/asm/pci.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/include/asm/pci.h	2016-07-24 15:23:50.000000000 -0400
@@ -31,20 +31,41 @@ int pci_proc_domain(struct pci_bus *);
 #define ZPCI_FC_BLOCKED			0x20
 #define ZPCI_FC_DMA_ENABLED		0x10
 
+#define ZPCI_FMB_DMA_COUNTER_VALID	(1 << 23)
+
+struct zpci_fmb_fmt0 {
+	u64 dma_rbytes;
+	u64 dma_wbytes;
+};
+
+struct zpci_fmb_fmt1 {
+	u64 rx_bytes;
+	u64 rx_packets;
+	u64 tx_bytes;
+	u64 tx_packets;
+};
+
+struct zpci_fmb_fmt2 {
+	u64 consumed_work_units;
+	u64 max_work_units;
+};
+
 struct zpci_fmb {
-	u32 format	:  8;
-	u32 dma_valid	:  1;
-	u32		: 23;
+	u32 format	: 8;
+	u32 fmt_ind	: 24;
 	u32 samples;
 	u64 last_update;
-	/* hardware counters */
+	/* common counters */
 	u64 ld_ops;
 	u64 st_ops;
 	u64 stb_ops;
 	u64 rpcit_ops;
-	u64 dma_rbytes;
-	u64 dma_wbytes;
-	u64 pad[2];
+	/* format specific counters */
+	union {
+		struct zpci_fmb_fmt0 fmt0;
+		struct zpci_fmb_fmt1 fmt1;
+		struct zpci_fmb_fmt2 fmt2;
+	};
 } __packed __aligned(128);
 
 enum zpci_state {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/include/asm/pgtable.h linux-libre-4.7-gnu/arch/s390/include/asm/pgtable.h
--- linux-libre-4.6-gnu/arch/s390/include/asm/pgtable.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/include/asm/pgtable.h	2016-07-24 15:23:50.000000000 -0400
@@ -1223,6 +1223,7 @@ static inline int pmd_trans_huge(pmd_t p
 	return pmd_val(pmd) & _SEGMENT_ENTRY_LARGE;
 }
 
+#define has_transparent_hugepage has_transparent_hugepage
 static inline int has_transparent_hugepage(void)
 {
 	return MACHINE_HAS_HPAGE ? 1 : 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/include/asm/processor.h linux-libre-4.7-gnu/arch/s390/include/asm/processor.h
--- linux-libre-4.6-gnu/arch/s390/include/asm/processor.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/include/asm/processor.h	2016-07-24 15:23:50.000000000 -0400
@@ -105,7 +105,6 @@ typedef struct {
  * Thread structure
  */
 struct thread_struct {
-	struct fpu fpu;			/* FP and VX register save area */
 	unsigned int  acrs[NUM_ACRS];
         unsigned long ksp;              /* kernel stack pointer             */
 	mm_segment_t mm_segment;
@@ -120,6 +119,11 @@ struct thread_struct {
 	/* cpu runtime instrumentation */
 	struct runtime_instr_cb *ri_cb;
 	unsigned char trap_tdb[256];	/* Transaction abort diagnose block */
+	/*
+	 * Warning: 'fpu' is dynamically-sized. It *MUST* be at
+	 * the end.
+	 */
+	struct fpu fpu;			/* FP and VX register save area */
 };
 
 /* Flag to disable transactions. */
@@ -155,10 +159,9 @@ struct stack_frame {
 
 #define ARCH_MIN_TASKALIGN	8
 
-extern __vector128 init_task_fpu_regs[__NUM_VXRS];
 #define INIT_THREAD {							\
 	.ksp = sizeof(init_stack) + (unsigned long) &init_stack,	\
-	.fpu.regs = (void *)&init_task_fpu_regs,			\
+	.fpu.regs = (void *) init_task.thread.fpu.fprs,			\
 }
 
 /*
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/include/asm/rwsem.h linux-libre-4.7-gnu/arch/s390/include/asm/rwsem.h
--- linux-libre-4.6-gnu/arch/s390/include/asm/rwsem.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/include/asm/rwsem.h	2016-07-24 15:23:50.000000000 -0400
@@ -90,7 +90,7 @@ static inline int __down_read_trylock(st
 /*
  * lock for writing
  */
-static inline void __down_write_nested(struct rw_semaphore *sem, int subclass)
+static inline long ___down_write(struct rw_semaphore *sem)
 {
 	signed long old, new, tmp;
 
@@ -104,13 +104,23 @@ static inline void __down_write_nested(s
 		: "=&d" (old), "=&d" (new), "=Q" (sem->count)
 		: "Q" (sem->count), "m" (tmp)
 		: "cc", "memory");
-	if (old != 0)
-		rwsem_down_write_failed(sem);
+
+	return old;
 }
 
 static inline void __down_write(struct rw_semaphore *sem)
 {
-	__down_write_nested(sem, 0);
+	if (___down_write(sem))
+		rwsem_down_write_failed(sem);
+}
+
+static inline int __down_write_killable(struct rw_semaphore *sem)
+{
+	if (___down_write(sem))
+		if (IS_ERR(rwsem_down_write_failed_killable(sem)))
+			return -EINTR;
+
+	return 0;
 }
 
 /*
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/include/asm/sclp.h linux-libre-4.7-gnu/arch/s390/include/asm/sclp.h
--- linux-libre-4.6-gnu/arch/s390/include/asm/sclp.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/include/asm/sclp.h	2016-07-24 15:23:50.000000000 -0400
@@ -69,9 +69,22 @@ struct sclp_info {
 	unsigned int max_cores;
 	unsigned long hsa_size;
 	unsigned long facilities;
+	unsigned int hmfai;
 };
 extern struct sclp_info sclp;
 
+struct zpci_report_error_header {
+	u8 version;	/* Interface version byte */
+	u8 action;	/* Action qualifier byte
+			 * 1: Deconfigure and repair action requested
+			 *	(OpenCrypto Problem Call Home)
+			 * 2: Informational Report
+			 *	(OpenCrypto Successful Diagnostics Execution)
+			 */
+	u16 length;	/* Length of Subsequent Data (up to 4K – SCLP header */
+	u8 data[0];	/* Subsequent Data passed verbatim to SCLP ET 24 */
+} __packed;
+
 int sclp_get_core_info(struct sclp_core_info *info);
 int sclp_core_configure(u8 core);
 int sclp_core_deconfigure(u8 core);
@@ -83,6 +96,7 @@ int sclp_chp_read_info(struct sclp_chp_i
 void sclp_get_ipl_info(struct sclp_ipl_info *info);
 int sclp_pci_configure(u32 fid);
 int sclp_pci_deconfigure(u32 fid);
+int sclp_pci_report(struct zpci_report_error_header *report, u32 fh, u32 fid);
 int memcpy_hsa_kernel(void *dest, unsigned long src, size_t count);
 int memcpy_hsa_user(void __user *dest, unsigned long src, size_t count);
 void sclp_early_detect(void);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/include/asm/sigp.h linux-libre-4.7-gnu/arch/s390/include/asm/sigp.h
--- linux-libre-4.6-gnu/arch/s390/include/asm/sigp.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/include/asm/sigp.h	2016-07-24 15:23:50.000000000 -0400
@@ -27,6 +27,7 @@
 
 /* SIGP cpu status bits */
 
+#define SIGP_STATUS_INVALID_ORDER	0x00000002UL
 #define SIGP_STATUS_CHECK_STOP		0x00000010UL
 #define SIGP_STATUS_STOPPED		0x00000040UL
 #define SIGP_STATUS_EXT_CALL_PENDING	0x00000080UL
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/include/asm/thread_info.h linux-libre-4.7-gnu/arch/s390/include/asm/thread_info.h
--- linux-libre-4.6-gnu/arch/s390/include/asm/thread_info.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/include/asm/thread_info.h	2016-07-24 15:23:50.000000000 -0400
@@ -62,6 +62,7 @@ static inline struct thread_info *curren
 }
 
 void arch_release_task_struct(struct task_struct *tsk);
+int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src);
 
 #define THREAD_SIZE_ORDER THREAD_ORDER
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/include/uapi/asm/dasd.h linux-libre-4.7-gnu/arch/s390/include/uapi/asm/dasd.h
--- linux-libre-4.6-gnu/arch/s390/include/uapi/asm/dasd.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/include/uapi/asm/dasd.h	2016-07-24 15:23:50.000000000 -0400
@@ -187,6 +187,36 @@ typedef struct format_data_t {
 #define DASD_FMT_INT_INVAL  4 /* invalidate tracks */
 #define DASD_FMT_INT_COMPAT 8 /* use OS/390 compatible disk layout */
 
+/*
+ * struct format_check_t
+ * represents all data necessary to evaluate the format of
+ * different tracks of a dasd
+ */
+typedef struct format_check_t {
+	/* Input */
+	struct format_data_t expect;
+
+	/* Output */
+	unsigned int result;		/* Error indication (DASD_FMT_ERR_*) */
+	unsigned int unit;		/* Track that is in error */
+	unsigned int rec;		/* Record that is in error */
+	unsigned int num_records;	/* Records in the track in error */
+	unsigned int blksize;		/* Blocksize of first record in error */
+	unsigned int key_length;	/* Key length of first record in error */
+} format_check_t;
+
+/* Values returned in format_check_t when a format error is detected: */
+/* Too few records were found on a single track */
+#define DASD_FMT_ERR_TOO_FEW_RECORDS	1
+/* Too many records were found on a single track */
+#define DASD_FMT_ERR_TOO_MANY_RECORDS	2
+/* Blocksize/data-length of a record was wrong */
+#define DASD_FMT_ERR_BLKSIZE		3
+/* A record ID is defined by cylinder, head, and record number (CHR). */
+/* On mismatch, this error is set */
+#define DASD_FMT_ERR_RECORD_ID		4
+/* If key-length was != 0 */
+#define DASD_FMT_ERR_KEY_LENGTH		5
 
 /* 
  * struct attrib_data_t
@@ -288,6 +318,8 @@ struct dasd_snid_ioctl_data {
 
 /* Get Sense Path Group ID (SNID) data */
 #define BIODASDSNID    _IOWR(DASD_IOCTL_LETTER, 1, struct dasd_snid_ioctl_data)
+/* Check device format according to format_check_t */
+#define BIODASDCHECKFMT _IOWR(DASD_IOCTL_LETTER, 2, format_check_t)
 
 #define BIODASDSYMMIO  _IOWR(DASD_IOCTL_LETTER, 240, dasd_symmio_parms_t)
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/include/uapi/asm/kvm.h linux-libre-4.7-gnu/arch/s390/include/uapi/asm/kvm.h
--- linux-libre-4.6-gnu/arch/s390/include/uapi/asm/kvm.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/include/uapi/asm/kvm.h	2016-07-24 15:23:50.000000000 -0400
@@ -25,6 +25,7 @@
 #define KVM_DEV_FLIC_APF_DISABLE_WAIT	5
 #define KVM_DEV_FLIC_ADAPTER_REGISTER	6
 #define KVM_DEV_FLIC_ADAPTER_MODIFY	7
+#define KVM_DEV_FLIC_CLEAR_IO_IRQ	8
 /*
  * We can have up to 4*64k pending subchannels + 8 adapter interrupts,
  * as well as up  to ASYNC_PF_PER_VCPU*KVM_MAX_VCPUS pfault done interrupts.
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/include/uapi/asm/sie.h linux-libre-4.7-gnu/arch/s390/include/uapi/asm/sie.h
--- linux-libre-4.6-gnu/arch/s390/include/uapi/asm/sie.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/include/uapi/asm/sie.h	2016-07-24 15:23:50.000000000 -0400
@@ -16,14 +16,19 @@
 	{ 0x01, "SIGP sense" },					\
 	{ 0x02, "SIGP external call" },				\
 	{ 0x03, "SIGP emergency signal" },			\
+	{ 0x04, "SIGP start" },					\
 	{ 0x05, "SIGP stop" },					\
 	{ 0x06, "SIGP restart" },				\
 	{ 0x09, "SIGP stop and store status" },			\
 	{ 0x0b, "SIGP initial cpu reset" },			\
+	{ 0x0c, "SIGP cpu reset" },				\
 	{ 0x0d, "SIGP set prefix" },				\
 	{ 0x0e, "SIGP store status at address" },		\
 	{ 0x12, "SIGP set architecture" },			\
-	{ 0x15, "SIGP sense running" }
+	{ 0x13, "SIGP conditional emergency signal" },		\
+	{ 0x15, "SIGP sense running" },				\
+	{ 0x16, "SIGP set multithreading"},			\
+	{ 0x17, "SIGP store additional status ait address"}
 
 #define icpt_prog_codes						\
 	{ 0x0001, "Prog Operation" },				\
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/Kconfig linux-libre-4.7-gnu/arch/s390/Kconfig
--- linux-libre-4.6-gnu/arch/s390/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -107,6 +107,7 @@ config S390
 	select ARCH_SUPPORTS_NUMA_BALANCING
 	select ARCH_USE_BUILTIN_BSWAP
 	select ARCH_USE_CMPXCHG_LOCKREF
+	select ARCH_WANTS_DYNAMIC_TASK_STRUCT
 	select ARCH_WANTS_PROT_NUMA_PROT_NONE
 	select ARCH_WANT_IPC_PARSE_VERSION
 	select BUILDTIME_EXTABLE_SORT
@@ -122,17 +123,19 @@ config S390
 	select HAVE_ARCH_AUDITSYSCALL
 	select HAVE_ARCH_EARLY_PFN_TO_NID
 	select HAVE_ARCH_JUMP_LABEL
+	select CPU_NO_EFFICIENT_FFS if !HAVE_MARCH_Z9_109_FEATURES
 	select HAVE_ARCH_SECCOMP_FILTER
 	select HAVE_ARCH_SOFT_DIRTY
 	select HAVE_ARCH_TRACEHOOK
 	select HAVE_ARCH_TRANSPARENT_HUGEPAGE
-	select HAVE_BPF_JIT if PACK_STACK && HAVE_MARCH_Z196_FEATURES
+	select HAVE_EBPF_JIT if PACK_STACK && HAVE_MARCH_Z196_FEATURES
 	select HAVE_CMPXCHG_DOUBLE
 	select HAVE_CMPXCHG_LOCAL
 	select HAVE_DEBUG_KMEMLEAK
 	select HAVE_DMA_API_DEBUG
 	select HAVE_DYNAMIC_FTRACE
 	select HAVE_DYNAMIC_FTRACE_WITH_REGS
+	select HAVE_EXIT_THREAD
 	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_FUNCTION_TRACER
@@ -164,6 +167,7 @@ config S390
 	select TTY
 	select VIRT_CPU_ACCOUNTING
 	select VIRT_TO_BUS
+	select HAVE_NMI
 
 
 config SCHED_OMIT_FRAME_POINTER
@@ -210,7 +214,7 @@ config HAVE_MARCH_Z13_FEATURES
 
 choice
 	prompt "Processor type"
-	default MARCH_Z900
+	default MARCH_Z196
 
 config MARCH_Z900
 	bool "IBM zSeries model z800 and z900"
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/kernel/cache.c linux-libre-4.7-gnu/arch/s390/kernel/cache.c
--- linux-libre-4.6-gnu/arch/s390/kernel/cache.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/kernel/cache.c	2016-07-24 15:23:50.000000000 -0400
@@ -72,7 +72,6 @@ void show_cacheinfo(struct seq_file *m)
 
 	if (!test_facility(34))
 		return;
-	get_online_cpus();
 	this_cpu_ci = get_cpu_cacheinfo(cpumask_any(cpu_online_mask));
 	for (idx = 0; idx < this_cpu_ci->num_leaves; idx++) {
 		cache = this_cpu_ci->info_list + idx;
@@ -86,7 +85,6 @@ void show_cacheinfo(struct seq_file *m)
 		seq_printf(m, "associativity=%d", cache->ways_of_associativity);
 		seq_puts(m, "\n");
 	}
-	put_online_cpus();
 }
 
 static inline enum cache_type get_cache_type(struct cache_info *ci, int level)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/kernel/crash_dump.c linux-libre-4.7-gnu/arch/s390/kernel/crash_dump.c
--- linux-libre-4.6-gnu/arch/s390/kernel/crash_dump.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/kernel/crash_dump.c	2016-07-24 15:23:50.000000000 -0400
@@ -173,7 +173,7 @@ int copy_oldmem_kernel(void *dst, void *
 /*
  * Copy memory of the old, dumped system to a user space virtual address
  */
-int copy_oldmem_user(void __user *dst, void *src, size_t count)
+static int copy_oldmem_user(void __user *dst, void *src, size_t count)
 {
 	unsigned long from, len;
 	int rc;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/kernel/dumpstack.c linux-libre-4.7-gnu/arch/s390/kernel/dumpstack.c
--- linux-libre-4.6-gnu/arch/s390/kernel/dumpstack.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/kernel/dumpstack.c	2016-07-24 15:23:50.000000000 -0400
@@ -89,6 +89,30 @@ void dump_trace(dump_trace_func_t func,
 }
 EXPORT_SYMBOL_GPL(dump_trace);
 
+struct return_address_data {
+	unsigned long address;
+	int depth;
+};
+
+static int __return_address(void *data, unsigned long address)
+{
+	struct return_address_data *rd = data;
+
+	if (rd->depth--)
+		return 0;
+	rd->address = address;
+	return 1;
+}
+
+unsigned long return_address(int depth)
+{
+	struct return_address_data rd = { .depth = depth + 2 };
+
+	dump_trace(__return_address, &rd, NULL, current_stack_pointer());
+	return rd.address;
+}
+EXPORT_SYMBOL_GPL(return_address);
+
 static int show_address(void *data, unsigned long address)
 {
 	printk("([<%016lx>] %pSR)\n", address, (void *)address);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/kernel/entry.h linux-libre-4.7-gnu/arch/s390/kernel/entry.h
--- linux-libre-4.6-gnu/arch/s390/kernel/entry.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/kernel/entry.h	2016-07-24 15:23:50.000000000 -0400
@@ -1,6 +1,7 @@
 #ifndef _ENTRY_H
 #define _ENTRY_H
 
+#include <linux/percpu.h>
 #include <linux/types.h>
 #include <linux/signal.h>
 #include <asm/ptrace.h>
@@ -75,4 +76,7 @@ long sys_s390_personality(unsigned int p
 long sys_s390_runtime_instr(int command, int signum);
 long sys_s390_pci_mmio_write(unsigned long, const void __user *, size_t);
 long sys_s390_pci_mmio_read(unsigned long, void __user *, size_t);
+
+DECLARE_PER_CPU(u64, mt_cycles[8]);
+
 #endif /* _ENTRY_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/kernel/ipl.c linux-libre-4.7-gnu/arch/s390/kernel/ipl.c
--- linux-libre-4.6-gnu/arch/s390/kernel/ipl.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/kernel/ipl.c	2016-07-24 15:23:50.000000000 -0400
@@ -2064,12 +2064,5 @@ void s390_reset_system(void)
 	S390_lowcore.program_new_psw.addr =
 		(unsigned long) s390_base_pgm_handler;
 
-	/*
-	 * Clear subchannel ID and number to signal new kernel that no CCW or
-	 * SCSI IPL has been done (for kexec and kdump)
-	 */
-	S390_lowcore.subchannel_id = 0;
-	S390_lowcore.subchannel_nr = 0;
-
 	do_reset_calls();
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/kernel/machine_kexec.c linux-libre-4.7-gnu/arch/s390/kernel/machine_kexec.c
--- linux-libre-4.6-gnu/arch/s390/kernel/machine_kexec.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/kernel/machine_kexec.c	2016-07-24 15:23:50.000000000 -0400
@@ -43,13 +43,13 @@ static int machine_kdump_pm_cb(struct no
 	switch (action) {
 	case PM_SUSPEND_PREPARE:
 	case PM_HIBERNATION_PREPARE:
-		if (crashk_res.start)
-			crash_map_reserved_pages();
+		if (kexec_crash_image)
+			arch_kexec_unprotect_crashkres();
 		break;
 	case PM_POST_SUSPEND:
 	case PM_POST_HIBERNATION:
-		if (crashk_res.start)
-			crash_unmap_reserved_pages();
+		if (kexec_crash_image)
+			arch_kexec_protect_crashkres();
 		break;
 	default:
 		return NOTIFY_DONE;
@@ -60,6 +60,8 @@ static int machine_kdump_pm_cb(struct no
 static int __init machine_kdump_pm_init(void)
 {
 	pm_notifier(machine_kdump_pm_cb, 0);
+	/* Create initial mapping for crashkernel memory */
+	arch_kexec_unprotect_crashkres();
 	return 0;
 }
 arch_initcall(machine_kdump_pm_init);
@@ -146,6 +148,8 @@ static int kdump_csum_valid(struct kimag
 #endif
 }
 
+#ifdef CONFIG_CRASH_DUMP
+
 /*
  * Map or unmap crashkernel memory
  */
@@ -167,21 +171,25 @@ static void crash_map_pages(int enable)
 }
 
 /*
- * Map crashkernel memory
+ * Unmap crashkernel memory
  */
-void crash_map_reserved_pages(void)
+void arch_kexec_protect_crashkres(void)
 {
-	crash_map_pages(1);
+	if (crashk_res.end)
+		crash_map_pages(0);
 }
 
 /*
- * Unmap crashkernel memory
+ * Map crashkernel memory
  */
-void crash_unmap_reserved_pages(void)
+void arch_kexec_unprotect_crashkres(void)
 {
-	crash_map_pages(0);
+	if (crashk_res.end)
+		crash_map_pages(1);
 }
 
+#endif
+
 /*
  * Give back memory to hypervisor before new kdump is loaded
  */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/kernel/module.c linux-libre-4.7-gnu/arch/s390/kernel/module.c
--- linux-libre-4.6-gnu/arch/s390/kernel/module.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/kernel/module.c	2016-07-24 15:23:50.000000000 -0400
@@ -51,6 +51,10 @@ void *module_alloc(unsigned long size)
 
 void module_arch_freeing_init(struct module *mod)
 {
+	if (is_livepatch_module(mod) &&
+	    mod->state == MODULE_STATE_LIVE)
+		return;
+
 	vfree(mod->arch.syminfo);
 	mod->arch.syminfo = NULL;
 }
@@ -425,7 +429,5 @@ int module_finalize(const Elf_Ehdr *hdr,
 		    struct module *me)
 {
 	jump_label_apply_nops(me);
-	vfree(me->arch.syminfo);
-	me->arch.syminfo = NULL;
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/kernel/perf_cpum_cf.c linux-libre-4.7-gnu/arch/s390/kernel/perf_cpum_cf.c
--- linux-libre-4.6-gnu/arch/s390/kernel/perf_cpum_cf.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/kernel/perf_cpum_cf.c	2016-07-24 15:23:50.000000000 -0400
@@ -649,6 +649,8 @@ static int cpumf_pmu_commit_txn(struct p
 
 /* Performance monitoring unit for s390x */
 static struct pmu cpumf_pmu = {
+	.task_ctx_nr  = perf_sw_context,
+	.capabilities = PERF_PMU_CAP_NO_INTERRUPT,
 	.pmu_enable   = cpumf_pmu_enable,
 	.pmu_disable  = cpumf_pmu_disable,
 	.event_init   = cpumf_pmu_event_init,
@@ -665,18 +667,21 @@ static struct pmu cpumf_pmu = {
 static int cpumf_pmu_notifier(struct notifier_block *self, unsigned long action,
 			      void *hcpu)
 {
-	unsigned int cpu = (long) hcpu;
 	int flags;
 
 	switch (action & ~CPU_TASKS_FROZEN) {
 	case CPU_ONLINE:
 	case CPU_DOWN_FAILED:
 		flags = PMC_INIT;
-		smp_call_function_single(cpu, setup_pmc_cpu, &flags, 1);
+		local_irq_disable();
+		setup_pmc_cpu(&flags);
+		local_irq_enable();
 		break;
 	case CPU_DOWN_PREPARE:
 		flags = PMC_RELEASE;
-		smp_call_function_single(cpu, setup_pmc_cpu, &flags, 1);
+		local_irq_disable();
+		setup_pmc_cpu(&flags);
+		local_irq_enable();
 		break;
 	default:
 		break;
@@ -705,12 +710,6 @@ static int __init cpumf_pmu_init(void)
 		goto out;
 	}
 
-	/* The CPU measurement counter facility does not have overflow
-	 * interrupts to do sampling.  Sampling must be provided by
-	 * external means, for example, by timers.
-	 */
-	cpumf_pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
-
 	cpumf_pmu.attr_groups = cpumf_cf_event_group();
 	rc = perf_pmu_register(&cpumf_pmu, "cpum_cf", PERF_TYPE_RAW);
 	if (rc) {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/kernel/perf_cpum_sf.c linux-libre-4.7-gnu/arch/s390/kernel/perf_cpum_sf.c
--- linux-libre-4.6-gnu/arch/s390/kernel/perf_cpum_sf.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/kernel/perf_cpum_sf.c	2016-07-24 15:23:50.000000000 -0400
@@ -1510,7 +1510,6 @@ static void cpumf_measurement_alert(stru
 static int cpumf_pmu_notifier(struct notifier_block *self,
 			      unsigned long action, void *hcpu)
 {
-	unsigned int cpu = (long) hcpu;
 	int flags;
 
 	/* Ignore the notification if no events are scheduled on the PMU.
@@ -1523,11 +1522,15 @@ static int cpumf_pmu_notifier(struct not
 	case CPU_ONLINE:
 	case CPU_DOWN_FAILED:
 		flags = PMC_INIT;
-		smp_call_function_single(cpu, setup_pmc_cpu, &flags, 1);
+		local_irq_disable();
+		setup_pmc_cpu(&flags);
+		local_irq_enable();
 		break;
 	case CPU_DOWN_PREPARE:
 		flags = PMC_RELEASE;
-		smp_call_function_single(cpu, setup_pmc_cpu, &flags, 1);
+		local_irq_disable();
+		setup_pmc_cpu(&flags);
+		local_irq_enable();
 		break;
 	default:
 		break;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/kernel/perf_event.c linux-libre-4.7-gnu/arch/s390/kernel/perf_event.c
--- linux-libre-4.6-gnu/arch/s390/kernel/perf_event.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/kernel/perf_event.c	2016-07-24 15:23:50.000000000 -0400
@@ -224,13 +224,13 @@ arch_initcall(service_level_perf_registe
 
 static int __perf_callchain_kernel(void *data, unsigned long address)
 {
-	struct perf_callchain_entry *entry = data;
+	struct perf_callchain_entry_ctx *entry = data;
 
 	perf_callchain_store(entry, address);
 	return 0;
 }
 
-void perf_callchain_kernel(struct perf_callchain_entry *entry,
+void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
 			   struct pt_regs *regs)
 {
 	if (user_mode(regs))
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/kernel/process.c linux-libre-4.7-gnu/arch/s390/kernel/process.c
--- linux-libre-4.6-gnu/arch/s390/kernel/process.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/kernel/process.c	2016-07-24 15:23:50.000000000 -0400
@@ -7,6 +7,7 @@
  *		 Denis Joseph Barrow,
  */
 
+#include <linux/elf-randomize.h>
 #include <linux/compiler.h>
 #include <linux/cpu.h>
 #include <linux/sched.h>
@@ -37,9 +38,6 @@
 
 asmlinkage void ret_from_fork(void) asm ("ret_from_fork");
 
-/* FPU save area for the init task */
-__vector128 init_task_fpu_regs[__NUM_VXRS] __init_task_data;
-
 /*
  * Return saved PC of a blocked thread. used in kernel/sched.
  * resume in entry.S does not create a new stack frame, it
@@ -70,9 +68,10 @@ extern void kernel_thread_starter(void);
 /*
  * Free current thread data structures etc..
  */
-void exit_thread(void)
+void exit_thread(struct task_struct *tsk)
 {
-	exit_thread_runtime_instr();
+	if (tsk == current)
+		exit_thread_runtime_instr();
 }
 
 void flush_thread(void)
@@ -85,35 +84,19 @@ void release_thread(struct task_struct *
 
 void arch_release_task_struct(struct task_struct *tsk)
 {
-	/* Free either the floating-point or the vector register save area */
-	kfree(tsk->thread.fpu.regs);
 }
 
 int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
 {
-	size_t fpu_regs_size;
-
-	*dst = *src;
-
-	/*
-	 * If the vector extension is available, it is enabled for all tasks,
-	 * and, thus, the FPU register save area must be allocated accordingly.
-	 */
-	fpu_regs_size = MACHINE_HAS_VX ? sizeof(__vector128) * __NUM_VXRS
-				       : sizeof(freg_t) * __NUM_FPRS;
-	dst->thread.fpu.regs = kzalloc(fpu_regs_size, GFP_KERNEL|__GFP_REPEAT);
-	if (!dst->thread.fpu.regs)
-		return -ENOMEM;
-
 	/*
 	 * Save the floating-point or vector register state of the current
 	 * task and set the CIF_FPU flag to lazy restore the FPU register
 	 * state when returning to user space.
 	 */
 	save_fpu_regs();
-	dst->thread.fpu.fpc = current->thread.fpu.fpc;
-	memcpy(dst->thread.fpu.regs, current->thread.fpu.regs, fpu_regs_size);
 
+	memcpy(dst, src, arch_task_struct_size);
+	dst->thread.fpu.regs = dst->thread.fpu.fprs;
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/kernel/processor.c linux-libre-4.7-gnu/arch/s390/kernel/processor.c
--- linux-libre-4.6-gnu/arch/s390/kernel/processor.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/kernel/processor.c	2016-07-24 15:23:50.000000000 -0400
@@ -6,6 +6,7 @@
 #define KMSG_COMPONENT "cpu"
 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 
+#include <linux/cpufeature.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/seq_file.h>
@@ -84,7 +85,6 @@ static int show_cpuinfo(struct seq_file
 		seq_puts(m, "\n");
 		show_cacheinfo(m);
 	}
-	get_online_cpus();
 	if (cpu_online(n)) {
 		struct cpuid *id = &per_cpu(cpu_id, n);
 		seq_printf(m, "processor %li: "
@@ -93,23 +93,31 @@ static int show_cpuinfo(struct seq_file
 			   "machine = %04X\n",
 			   n, id->version, id->ident, id->machine);
 	}
-	put_online_cpus();
 	return 0;
 }
 
+static inline void *c_update(loff_t *pos)
+{
+	if (*pos)
+		*pos = cpumask_next(*pos - 1, cpu_online_mask);
+	return *pos < nr_cpu_ids ? (void *)*pos + 1 : NULL;
+}
+
 static void *c_start(struct seq_file *m, loff_t *pos)
 {
-	return *pos < nr_cpu_ids ? (void *)((unsigned long) *pos + 1) : NULL;
+	get_online_cpus();
+	return c_update(pos);
 }
 
 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
 {
 	++*pos;
-	return c_start(m, pos);
+	return c_update(pos);
 }
 
 static void c_stop(struct seq_file *m, void *v)
 {
+	put_online_cpus();
 }
 
 const struct seq_operations cpuinfo_op = {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/kernel/setup.c linux-libre-4.7-gnu/arch/s390/kernel/setup.c
--- linux-libre-4.6-gnu/arch/s390/kernel/setup.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/kernel/setup.c	2016-07-24 15:23:50.000000000 -0400
@@ -809,6 +809,22 @@ static void __init setup_randomness(void
 }
 
 /*
+ * Find the correct size for the task_struct. This depends on
+ * the size of the struct fpu at the end of the thread_struct
+ * which is embedded in the task_struct.
+ */
+static void __init setup_task_size(void)
+{
+	int task_size = sizeof(struct task_struct);
+
+	if (!MACHINE_HAS_VX) {
+		task_size -= sizeof(__vector128) * __NUM_VXRS;
+		task_size += sizeof(freg_t) * __NUM_FPRS;
+	}
+	arch_task_struct_size = task_size;
+}
+
+/*
  * Setup function called from init/main.c just after the banner
  * was printed.
  */
@@ -846,6 +862,7 @@ void __init setup_arch(char **cmdline_p)
 
 	os_info_init();
 	setup_ipl();
+	setup_task_size();
 
 	/* Do some memory reservations *before* memory is added to memblock */
 	reserve_memory_end();
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/kernel/smp.c linux-libre-4.7-gnu/arch/s390/kernel/smp.c
--- linux-libre-4.6-gnu/arch/s390/kernel/smp.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/kernel/smp.c	2016-07-24 15:23:50.000000000 -0400
@@ -832,7 +832,7 @@ int __cpu_up(unsigned int cpu, struct ta
 	pcpu_attach_task(pcpu, tidle);
 	pcpu_start_fn(pcpu, smp_start_secondary, NULL);
 	/* Wait until cpu puts itself in the online & active maps */
-	while (!cpu_online(cpu) || !cpu_active(cpu))
+	while (!cpu_online(cpu))
 		cpu_relax();
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/kernel/vdso.c linux-libre-4.7-gnu/arch/s390/kernel/vdso.c
--- linux-libre-4.6-gnu/arch/s390/kernel/vdso.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/kernel/vdso.c	2016-07-24 15:23:50.000000000 -0400
@@ -216,7 +216,8 @@ int arch_setup_additional_pages(struct l
 	 * it at vdso_base which is the "natural" base for it, but we might
 	 * fail and end up putting it elsewhere.
 	 */
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
 	vdso_base = get_unmapped_area(NULL, 0, vdso_pages << PAGE_SHIFT, 0, 0);
 	if (IS_ERR_VALUE(vdso_base)) {
 		rc = vdso_base;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/kernel/vtime.c linux-libre-4.7-gnu/arch/s390/kernel/vtime.c
--- linux-libre-4.6-gnu/arch/s390/kernel/vtime.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/kernel/vtime.c	2016-07-24 15:23:50.000000000 -0400
@@ -18,6 +18,8 @@
 #include <asm/cpu_mf.h>
 #include <asm/smp.h>
 
+#include "entry.h"
+
 static void virt_timer_expire(void);
 
 static LIST_HEAD(virt_timer_list);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/kvm/intercept.c linux-libre-4.7-gnu/arch/s390/kvm/intercept.c
--- linux-libre-4.6-gnu/arch/s390/kvm/intercept.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/kvm/intercept.c	2016-07-24 15:23:50.000000000 -0400
@@ -341,6 +341,8 @@ static int handle_mvpg_pei(struct kvm_vc
 
 static int handle_partial_execution(struct kvm_vcpu *vcpu)
 {
+	vcpu->stat.exit_pei++;
+
 	if (vcpu->arch.sie_block->ipa == 0xb254)	/* MVPG */
 		return handle_mvpg_pei(vcpu);
 	if (vcpu->arch.sie_block->ipa >> 8 == 0xae)	/* SIGP */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/kvm/interrupt.c linux-libre-4.7-gnu/arch/s390/kvm/interrupt.c
--- linux-libre-4.6-gnu/arch/s390/kvm/interrupt.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/kvm/interrupt.c	2016-07-24 15:23:50.000000000 -0400
@@ -977,6 +977,11 @@ no_timer:
 
 void kvm_s390_vcpu_wakeup(struct kvm_vcpu *vcpu)
 {
+	/*
+	 * We cannot move this into the if, as the CPU might be already
+	 * in kvm_vcpu_block without having the waitqueue set (polling)
+	 */
+	vcpu->valid_wakeup = true;
 	if (swait_active(&vcpu->wq)) {
 		/*
 		 * The vcpu gave up the cpu voluntarily, mark it as a good
@@ -2034,6 +2039,27 @@ static int modify_io_adapter(struct kvm_
 	return ret;
 }
 
+static int clear_io_irq(struct kvm *kvm, struct kvm_device_attr *attr)
+
+{
+	const u64 isc_mask = 0xffUL << 24; /* all iscs set */
+	u32 schid;
+
+	if (attr->flags)
+		return -EINVAL;
+	if (attr->attr != sizeof(schid))
+		return -EINVAL;
+	if (copy_from_user(&schid, (void __user *) attr->addr, sizeof(schid)))
+		return -EFAULT;
+	kfree(kvm_s390_get_io_int(kvm, isc_mask, schid));
+	/*
+	 * If userspace is conforming to the architecture, we can have at most
+	 * one pending I/O interrupt per subchannel, so this is effectively a
+	 * clear all.
+	 */
+	return 0;
+}
+
 static int flic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
 {
 	int r = 0;
@@ -2067,6 +2093,9 @@ static int flic_set_attr(struct kvm_devi
 	case KVM_DEV_FLIC_ADAPTER_MODIFY:
 		r = modify_io_adapter(dev, attr);
 		break;
+	case KVM_DEV_FLIC_CLEAR_IO_IRQ:
+		r = clear_io_irq(dev->kvm, attr);
+		break;
 	default:
 		r = -EINVAL;
 	}
@@ -2074,6 +2103,23 @@ static int flic_set_attr(struct kvm_devi
 	return r;
 }
 
+static int flic_has_attr(struct kvm_device *dev,
+			     struct kvm_device_attr *attr)
+{
+	switch (attr->group) {
+	case KVM_DEV_FLIC_GET_ALL_IRQS:
+	case KVM_DEV_FLIC_ENQUEUE:
+	case KVM_DEV_FLIC_CLEAR_IRQS:
+	case KVM_DEV_FLIC_APF_ENABLE:
+	case KVM_DEV_FLIC_APF_DISABLE_WAIT:
+	case KVM_DEV_FLIC_ADAPTER_REGISTER:
+	case KVM_DEV_FLIC_ADAPTER_MODIFY:
+	case KVM_DEV_FLIC_CLEAR_IO_IRQ:
+		return 0;
+	}
+	return -ENXIO;
+}
+
 static int flic_create(struct kvm_device *dev, u32 type)
 {
 	if (!dev)
@@ -2095,6 +2141,7 @@ struct kvm_device_ops kvm_flic_ops = {
 	.name = "kvm-flic",
 	.get_attr = flic_get_attr,
 	.set_attr = flic_set_attr,
+	.has_attr = flic_has_attr,
 	.create = flic_create,
 	.destroy = flic_destroy,
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/kvm/Kconfig linux-libre-4.7-gnu/arch/s390/kvm/Kconfig
--- linux-libre-4.6-gnu/arch/s390/kvm/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/kvm/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -28,6 +28,7 @@ config KVM
 	select HAVE_KVM_IRQCHIP
 	select HAVE_KVM_IRQFD
 	select HAVE_KVM_IRQ_ROUTING
+	select HAVE_KVM_INVALID_WAKEUPS
 	select SRCU
 	select KVM_VFIO
 	---help---
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/kvm/kvm-s390.c linux-libre-4.7-gnu/arch/s390/kvm/kvm-s390.c
--- linux-libre-4.6-gnu/arch/s390/kvm/kvm-s390.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/kvm/kvm-s390.c	2016-07-24 15:23:50.000000000 -0400
@@ -61,10 +61,12 @@ struct kvm_stats_debugfs_item debugfs_en
 	{ "exit_external_request", VCPU_STAT(exit_external_request) },
 	{ "exit_external_interrupt", VCPU_STAT(exit_external_interrupt) },
 	{ "exit_instruction", VCPU_STAT(exit_instruction) },
+	{ "exit_pei", VCPU_STAT(exit_pei) },
 	{ "exit_program_interruption", VCPU_STAT(exit_program_interruption) },
 	{ "exit_instr_and_program_int", VCPU_STAT(exit_instr_and_program) },
 	{ "halt_successful_poll", VCPU_STAT(halt_successful_poll) },
 	{ "halt_attempted_poll", VCPU_STAT(halt_attempted_poll) },
+	{ "halt_poll_invalid", VCPU_STAT(halt_poll_invalid) },
 	{ "halt_wakeup", VCPU_STAT(halt_wakeup) },
 	{ "instruction_lctlg", VCPU_STAT(instruction_lctlg) },
 	{ "instruction_lctl", VCPU_STAT(instruction_lctl) },
@@ -118,9 +120,9 @@ struct kvm_stats_debugfs_item debugfs_en
 };
 
 /* upper facilities limit for kvm */
-unsigned long kvm_s390_fac_list_mask[] = {
-	0xffe6fffbfcfdfc40UL,
-	0x005e800000000000UL,
+unsigned long kvm_s390_fac_list_mask[16] = {
+	0xffe6000000000000UL,
+	0x005e000000000000UL,
 };
 
 unsigned long kvm_s390_fac_list_mask_size(void)
@@ -638,6 +640,7 @@ static int kvm_s390_get_tod(struct kvm *
 static int kvm_s390_set_processor(struct kvm *kvm, struct kvm_device_attr *attr)
 {
 	struct kvm_s390_vm_cpu_processor *proc;
+	u16 lowest_ibc, unblocked_ibc;
 	int ret = 0;
 
 	mutex_lock(&kvm->lock);
@@ -652,9 +655,17 @@ static int kvm_s390_set_processor(struct
 	}
 	if (!copy_from_user(proc, (void __user *)attr->addr,
 			    sizeof(*proc))) {
-		memcpy(&kvm->arch.model.cpu_id, &proc->cpuid,
-		       sizeof(struct cpuid));
-		kvm->arch.model.ibc = proc->ibc;
+		kvm->arch.model.cpuid = proc->cpuid;
+		lowest_ibc = sclp.ibc >> 16 & 0xfff;
+		unblocked_ibc = sclp.ibc & 0xfff;
+		if (lowest_ibc && proc->ibc) {
+			if (proc->ibc > unblocked_ibc)
+				kvm->arch.model.ibc = unblocked_ibc;
+			else if (proc->ibc < lowest_ibc)
+				kvm->arch.model.ibc = lowest_ibc;
+			else
+				kvm->arch.model.ibc = proc->ibc;
+		}
 		memcpy(kvm->arch.model.fac_list, proc->fac_list,
 		       S390_ARCH_FAC_LIST_SIZE_BYTE);
 	} else
@@ -687,7 +698,7 @@ static int kvm_s390_get_processor(struct
 		ret = -ENOMEM;
 		goto out;
 	}
-	memcpy(&proc->cpuid, &kvm->arch.model.cpu_id, sizeof(struct cpuid));
+	proc->cpuid = kvm->arch.model.cpuid;
 	proc->ibc = kvm->arch.model.ibc;
 	memcpy(&proc->fac_list, kvm->arch.model.fac_list,
 	       S390_ARCH_FAC_LIST_SIZE_BYTE);
@@ -1081,10 +1092,13 @@ static void kvm_s390_set_crycb_format(st
 		kvm->arch.crypto.crycbd |= CRYCB_FORMAT1;
 }
 
-static void kvm_s390_get_cpu_id(struct cpuid *cpu_id)
+static u64 kvm_s390_get_initial_cpuid(void)
 {
-	get_cpu_id(cpu_id);
-	cpu_id->version = 0xff;
+	struct cpuid cpuid;
+
+	get_cpu_id(&cpuid);
+	cpuid.version = 0xff;
+	return *((u64 *) &cpuid);
 }
 
 static void kvm_s390_crypto_init(struct kvm *kvm)
@@ -1175,7 +1189,7 @@ int kvm_arch_init_vm(struct kvm *kvm, un
 	memcpy(kvm->arch.model.fac_list, kvm->arch.model.fac_mask,
 	       S390_ARCH_FAC_LIST_SIZE_BYTE);
 
-	kvm_s390_get_cpu_id(&kvm->arch.model.cpu_id);
+	kvm->arch.model.cpuid = kvm_s390_get_initial_cpuid();
 	kvm->arch.model.ibc = sclp.ibc & 0x0fff;
 
 	kvm_s390_crypto_init(kvm);
@@ -1624,7 +1638,6 @@ static void kvm_s390_vcpu_setup_model(st
 {
 	struct kvm_s390_cpu_model *model = &vcpu->kvm->arch.model;
 
-	vcpu->arch.cpu_id = model->cpu_id;
 	vcpu->arch.sie_block->ibc = model->ibc;
 	if (test_kvm_facility(vcpu->kvm, 7))
 		vcpu->arch.sie_block->fac = (u32)(u64) model->fac_list;
@@ -1645,11 +1658,14 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu
 
 	kvm_s390_vcpu_setup_model(vcpu);
 
-	vcpu->arch.sie_block->ecb   = 6;
+	vcpu->arch.sie_block->ecb = 0x02;
+	if (test_kvm_facility(vcpu->kvm, 9))
+		vcpu->arch.sie_block->ecb |= 0x04;
 	if (test_kvm_facility(vcpu->kvm, 50) && test_kvm_facility(vcpu->kvm, 73))
 		vcpu->arch.sie_block->ecb |= 0x10;
 
-	vcpu->arch.sie_block->ecb2  = 8;
+	if (test_kvm_facility(vcpu->kvm, 8))
+		vcpu->arch.sie_block->ecb2 |= 0x08;
 	vcpu->arch.sie_block->eca   = 0xC1002000U;
 	if (sclp.has_siif)
 		vcpu->arch.sie_block->eca |= 1;
@@ -2971,13 +2987,31 @@ void kvm_arch_commit_memory_region(struc
 	return;
 }
 
+static inline unsigned long nonhyp_mask(int i)
+{
+	unsigned int nonhyp_fai = (sclp.hmfai << i * 2) >> 30;
+
+	return 0x0000ffffffffffffUL >> (nonhyp_fai << 4);
+}
+
+void kvm_arch_vcpu_block_finish(struct kvm_vcpu *vcpu)
+{
+	vcpu->valid_wakeup = false;
+}
+
 static int __init kvm_s390_init(void)
 {
+	int i;
+
 	if (!sclp.has_sief2) {
 		pr_info("SIE not available\n");
 		return -ENODEV;
 	}
 
+	for (i = 0; i < 16; i++)
+		kvm_s390_fac_list_mask[i] |=
+			S390_lowcore.stfle_fac_list[i] & nonhyp_mask(i);
+
 	return kvm_init(NULL, sizeof(struct kvm_vcpu), 0, THIS_MODULE);
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/kvm/priv.c linux-libre-4.7-gnu/arch/s390/kvm/priv.c
--- linux-libre-4.6-gnu/arch/s390/kvm/priv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/kvm/priv.c	2016-07-24 15:23:50.000000000 -0400
@@ -439,7 +439,7 @@ static int handle_lpswe(struct kvm_vcpu
 
 static int handle_stidp(struct kvm_vcpu *vcpu)
 {
-	u64 stidp_data = vcpu->arch.stidp_data;
+	u64 stidp_data = vcpu->kvm->arch.model.cpuid;
 	u64 operand2;
 	int rc;
 	ar_t ar;
@@ -670,8 +670,9 @@ static int handle_pfmf(struct kvm_vcpu *
 	if (vcpu->run->s.regs.gprs[reg1] & PFMF_RESERVED)
 		return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
 
-	/* Only provide non-quiescing support if the host supports it */
-	if (vcpu->run->s.regs.gprs[reg1] & PFMF_NQ && !test_facility(14))
+	/* Only provide non-quiescing support if enabled for the guest */
+	if (vcpu->run->s.regs.gprs[reg1] & PFMF_NQ &&
+	    !test_kvm_facility(vcpu->kvm, 14))
 		return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
 
 	/* No support for conditional-SSKE */
@@ -744,7 +745,7 @@ static int handle_essa(struct kvm_vcpu *
 {
 	/* entries expected to be 1FF */
 	int entries = (vcpu->arch.sie_block->cbrlo & ~PAGE_MASK) >> 3;
-	unsigned long *cbrlo, cbrle;
+	unsigned long *cbrlo;
 	struct gmap *gmap;
 	int i;
 
@@ -765,17 +766,9 @@ static int handle_essa(struct kvm_vcpu *
 	vcpu->arch.sie_block->cbrlo &= PAGE_MASK;	/* reset nceo */
 	cbrlo = phys_to_virt(vcpu->arch.sie_block->cbrlo);
 	down_read(&gmap->mm->mmap_sem);
-	for (i = 0; i < entries; ++i) {
-		cbrle = cbrlo[i];
-		if (unlikely(cbrle & ~PAGE_MASK || cbrle < 2 * PAGE_SIZE))
-			/* invalid entry */
-			break;
-		/* try to free backing */
-		__gmap_zap(gmap, cbrle);
-	}
+	for (i = 0; i < entries; ++i)
+		__gmap_zap(gmap, cbrlo[i]);
 	up_read(&gmap->mm->mmap_sem);
-	if (i < entries)
-		return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/kvm/sigp.c linux-libre-4.7-gnu/arch/s390/kvm/sigp.c
--- linux-libre-4.6-gnu/arch/s390/kvm/sigp.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/kvm/sigp.c	2016-07-24 15:23:50.000000000 -0400
@@ -240,6 +240,12 @@ static int __sigp_sense_running(struct k
 	struct kvm_s390_local_interrupt *li;
 	int rc;
 
+	if (!test_kvm_facility(vcpu->kvm, 9)) {
+		*reg &= 0xffffffff00000000UL;
+		*reg |= SIGP_STATUS_INVALID_ORDER;
+		return SIGP_CC_STATUS_STORED;
+	}
+
 	li = &dst_vcpu->arch.local_int;
 	if (atomic_read(li->cpuflags) & CPUSTAT_RUNNING) {
 		/* running */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/mm/fault.c linux-libre-4.7-gnu/arch/s390/mm/fault.c
--- linux-libre-4.6-gnu/arch/s390/mm/fault.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/mm/fault.c	2016-07-24 15:23:50.000000000 -0400
@@ -250,6 +250,7 @@ static noinline void do_sigsegv(struct p
 
 	report_user_fault(regs, SIGSEGV, 1);
 	si.si_signo = SIGSEGV;
+	si.si_errno = 0;
 	si.si_code = si_code;
 	si.si_addr = (void __user *)(regs->int_parm_long & __FAIL_ADDR_MASK);
 	force_sig_info(SIGSEGV, &si, current);
@@ -631,6 +632,29 @@ void pfault_fini(void)
 static DEFINE_SPINLOCK(pfault_lock);
 static LIST_HEAD(pfault_list);
 
+#define PF_COMPLETE	0x0080
+
+/*
+ * The mechanism of our pfault code: if Linux is running as guest, runs a user
+ * space process and the user space process accesses a page that the host has
+ * paged out we get a pfault interrupt.
+ *
+ * This allows us, within the guest, to schedule a different process. Without
+ * this mechanism the host would have to suspend the whole virtual cpu until
+ * the page has been paged in.
+ *
+ * So when we get such an interrupt then we set the state of the current task
+ * to uninterruptible and also set the need_resched flag. Both happens within
+ * interrupt context(!). If we later on want to return to user space we
+ * recognize the need_resched flag and then call schedule().  It's not very
+ * obvious how this works...
+ *
+ * Of course we have a lot of additional fun with the completion interrupt (->
+ * host signals that a page of a process has been paged in and the process can
+ * continue to run). This interrupt can arrive on any cpu and, since we have
+ * virtual cpus, actually appear before the interrupt that signals that a page
+ * is missing.
+ */
 static void pfault_interrupt(struct ext_code ext_code,
 			     unsigned int param32, unsigned long param64)
 {
@@ -639,10 +663,9 @@ static void pfault_interrupt(struct ext_
 	pid_t pid;
 
 	/*
-	 * Get the external interruption subcode & pfault
-	 * initial/completion signal bit. VM stores this 
-	 * in the 'cpu address' field associated with the
-         * external interrupt. 
+	 * Get the external interruption subcode & pfault initial/completion
+	 * signal bit. VM stores this in the 'cpu address' field associated
+	 * with the external interrupt.
 	 */
 	subcode = ext_code.subcode;
 	if ((subcode & 0xff00) != __SUBCODE_MASK)
@@ -658,7 +681,7 @@ static void pfault_interrupt(struct ext_
 	if (!tsk)
 		return;
 	spin_lock(&pfault_lock);
-	if (subcode & 0x0080) {
+	if (subcode & PF_COMPLETE) {
 		/* signal bit is set -> a page has been swapped in by VM */
 		if (tsk->thread.pfault_wait == 1) {
 			/* Initial interrupt was faster than the completion
@@ -687,8 +710,7 @@ static void pfault_interrupt(struct ext_
 			goto out;
 		if (tsk->thread.pfault_wait == 1) {
 			/* Already on the list with a reference: put to sleep */
-			__set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-			set_tsk_need_resched(tsk);
+			goto block;
 		} else if (tsk->thread.pfault_wait == -1) {
 			/* Completion interrupt was faster than the initial
 			 * interrupt (pfault_wait == -1). Set pfault_wait
@@ -703,7 +725,11 @@ static void pfault_interrupt(struct ext_
 			get_task_struct(tsk);
 			tsk->thread.pfault_wait = 1;
 			list_add(&tsk->thread.list, &pfault_list);
-			__set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+block:
+			/* Since this must be a userspace fault, there
+			 * is no kernel task state to trample. Rely on the
+			 * return to userspace schedule() to block. */
+			__set_current_state(TASK_UNINTERRUPTIBLE);
 			set_tsk_need_resched(tsk);
 		}
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/mm/mmap.c linux-libre-4.7-gnu/arch/s390/mm/mmap.c
--- linux-libre-4.6-gnu/arch/s390/mm/mmap.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/mm/mmap.c	2016-07-24 15:23:50.000000000 -0400
@@ -22,6 +22,7 @@
  * Started by Ingo Molnar <mingo@elte.hu>
  */
 
+#include <linux/elf-randomize.h>
 #include <linux/personality.h>
 #include <linux/mm.h>
 #include <linux/mman.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/mm/pgalloc.c linux-libre-4.7-gnu/arch/s390/mm/pgalloc.c
--- linux-libre-4.6-gnu/arch/s390/mm/pgalloc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/mm/pgalloc.c	2016-07-24 15:23:50.000000000 -0400
@@ -169,7 +169,7 @@ unsigned long *page_table_alloc(struct m
 			return table;
 	}
 	/* Allocate a fresh page */
-	page = alloc_page(GFP_KERNEL|__GFP_REPEAT);
+	page = alloc_page(GFP_KERNEL);
 	if (!page)
 		return NULL;
 	if (!pgtable_page_ctor(page)) {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/mm/pgtable.c linux-libre-4.7-gnu/arch/s390/mm/pgtable.c
--- linux-libre-4.6-gnu/arch/s390/mm/pgtable.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/mm/pgtable.c	2016-07-24 15:23:50.000000000 -0400
@@ -437,7 +437,7 @@ void ptep_zap_unused(struct mm_struct *m
 	pgste = pgste_get_lock(ptep);
 	pgstev = pgste_val(pgste);
 	pte = *ptep;
-	if (pte_swap(pte) &&
+	if (!reset && pte_swap(pte) &&
 	    ((pgstev & _PGSTE_GPS_USAGE_MASK) == _PGSTE_GPS_USAGE_UNUSED ||
 	     (pgstev & _PGSTE_GPS_ZERO))) {
 		ptep_zap_swap_entry(mm, pte_to_swp_entry(pte));
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/mm/vmem.c linux-libre-4.7-gnu/arch/s390/mm/vmem.c
--- linux-libre-4.6-gnu/arch/s390/mm/vmem.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/mm/vmem.c	2016-07-24 15:23:50.000000000 -0400
@@ -56,7 +56,7 @@ static inline pmd_t *vmem_pmd_alloc(void
 	return pmd;
 }
 
-static pte_t __ref *vmem_pte_alloc(unsigned long address)
+static pte_t __ref *vmem_pte_alloc(void)
 {
 	pte_t *pte;
 
@@ -121,7 +121,7 @@ static int vmem_add_mem(unsigned long st
 			continue;
 		}
 		if (pmd_none(*pm_dir)) {
-			pt_dir = vmem_pte_alloc(address);
+			pt_dir = vmem_pte_alloc();
 			if (!pt_dir)
 				goto out;
 			pmd_populate(&init_mm, pm_dir, pt_dir);
@@ -233,7 +233,7 @@ int __meminit vmemmap_populate(unsigned
 				address = (address + PMD_SIZE) & PMD_MASK;
 				continue;
 			}
-			pt_dir = vmem_pte_alloc(address);
+			pt_dir = vmem_pte_alloc();
 			if (!pt_dir)
 				goto out;
 			pmd_populate(&init_mm, pm_dir, pt_dir);
@@ -370,7 +370,7 @@ void __init vmem_map_init(void)
 	ro_end = (unsigned long)&_eshared & PAGE_MASK;
 	for_each_memblock(memory, reg) {
 		start = reg->base;
-		end = reg->base + reg->size - 1;
+		end = reg->base + reg->size;
 		if (start >= ro_end || end <= ro_start)
 			vmem_add_mem(start, end - start, 0);
 		else if (start >= ro_start && end <= ro_end)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/net/bpf_jit_comp.c linux-libre-4.7-gnu/arch/s390/net/bpf_jit_comp.c
--- linux-libre-4.6-gnu/arch/s390/net/bpf_jit_comp.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/net/bpf_jit_comp.c	2016-07-24 15:23:50.000000000 -0400
@@ -45,7 +45,7 @@ struct bpf_jit {
 	int labels[1];		/* Labels for local jumps */
 };
 
-#define BPF_SIZE_MAX	0x7ffff	/* Max size for program (20 bit signed displ) */
+#define BPF_SIZE_MAX	0xffff	/* Max size for program (16 bit branches) */
 
 #define SEEN_SKB	1	/* skb access */
 #define SEEN_MEM	2	/* use mem[] for temporary storage */
@@ -54,16 +54,17 @@ struct bpf_jit {
 #define SEEN_FUNC	16	/* calls C functions */
 #define SEEN_TAIL_CALL	32	/* code uses tail calls */
 #define SEEN_SKB_CHANGE	64	/* code changes skb data */
+#define SEEN_REG_AX	128	/* code uses constant blinding */
 #define SEEN_STACK	(SEEN_FUNC | SEEN_MEM | SEEN_SKB)
 
 /*
  * s390 registers
  */
-#define REG_W0		(__MAX_BPF_REG+0)	/* Work register 1 (even) */
-#define REG_W1		(__MAX_BPF_REG+1)	/* Work register 2 (odd) */
-#define REG_SKB_DATA	(__MAX_BPF_REG+2)	/* SKB data register */
-#define REG_L		(__MAX_BPF_REG+3)	/* Literal pool register */
-#define REG_15		(__MAX_BPF_REG+4)	/* Register 15 */
+#define REG_W0		(MAX_BPF_JIT_REG + 0)	/* Work register 1 (even) */
+#define REG_W1		(MAX_BPF_JIT_REG + 1)	/* Work register 2 (odd) */
+#define REG_SKB_DATA	(MAX_BPF_JIT_REG + 2)	/* SKB data register */
+#define REG_L		(MAX_BPF_JIT_REG + 3)	/* Literal pool register */
+#define REG_15		(MAX_BPF_JIT_REG + 4)	/* Register 15 */
 #define REG_0		REG_W0			/* Register 0 */
 #define REG_1		REG_W1			/* Register 1 */
 #define REG_2		BPF_REG_1		/* Register 2 */
@@ -88,6 +89,8 @@ static const int reg2hex[] = {
 	[BPF_REG_9]	= 10,
 	/* BPF stack pointer */
 	[BPF_REG_FP]	= 13,
+	/* Register for blinding (shared with REG_SKB_DATA) */
+	[BPF_REG_AX]	= 12,
 	/* SKB data pointer */
 	[REG_SKB_DATA]	= 12,
 	/* Work registers for s390x backend */
@@ -385,7 +388,7 @@ static void save_restore_regs(struct bpf
 /*
  * For SKB access %b1 contains the SKB pointer. For "bpf_jit.S"
  * we store the SKB header length on the stack and the SKB data
- * pointer in REG_SKB_DATA.
+ * pointer in REG_SKB_DATA if BPF_REG_AX is not used.
  */
 static void emit_load_skb_data_hlen(struct bpf_jit *jit)
 {
@@ -397,9 +400,10 @@ static void emit_load_skb_data_hlen(stru
 		   offsetof(struct sk_buff, data_len));
 	/* stg %w1,ST_OFF_HLEN(%r0,%r15) */
 	EMIT6_DISP_LH(0xe3000000, 0x0024, REG_W1, REG_0, REG_15, STK_OFF_HLEN);
-	/* lg %skb_data,data_off(%b1) */
-	EMIT6_DISP_LH(0xe3000000, 0x0004, REG_SKB_DATA, REG_0,
-		      BPF_REG_1, offsetof(struct sk_buff, data));
+	if (!(jit->seen & SEEN_REG_AX))
+		/* lg %skb_data,data_off(%b1) */
+		EMIT6_DISP_LH(0xe3000000, 0x0004, REG_SKB_DATA, REG_0,
+			      BPF_REG_1, offsetof(struct sk_buff, data));
 }
 
 /*
@@ -446,7 +450,7 @@ static void bpf_jit_prologue(struct bpf_
 		emit_load_skb_data_hlen(jit);
 	if (jit->seen & SEEN_SKB_CHANGE)
 		/* stg %b1,ST_OFF_SKBP(%r0,%r15) */
-		EMIT6_DISP_LH(0xe3000000, 0x0024, REG_W1, REG_0, REG_15,
+		EMIT6_DISP_LH(0xe3000000, 0x0024, BPF_REG_1, REG_0, REG_15,
 			      STK_OFF_SKBP);
 }
 
@@ -487,6 +491,8 @@ static noinline int bpf_jit_insn(struct
 	s32 imm = insn->imm;
 	s16 off = insn->off;
 
+	if (dst_reg == BPF_REG_AX || src_reg == BPF_REG_AX)
+		jit->seen |= SEEN_REG_AX;
 	switch (insn->code) {
 	/*
 	 * BPF_MOV
@@ -1188,7 +1194,7 @@ call_fn:
 		/*
 		 * Implicit input:
 		 *  BPF_REG_6	 (R7) : skb pointer
-		 *  REG_SKB_DATA (R12): skb data pointer
+		 *  REG_SKB_DATA (R12): skb data pointer (if no BPF_REG_AX)
 		 *
 		 * Calculated input:
 		 *  BPF_REG_2	 (R3) : offset of byte(s) to fetch in skb
@@ -1209,6 +1215,11 @@ call_fn:
 			/* agfr %b2,%src (%src is s32 here) */
 			EMIT4(0xb9180000, BPF_REG_2, src_reg);
 
+		/* Reload REG_SKB_DATA if BPF_REG_AX is used */
+		if (jit->seen & SEEN_REG_AX)
+			/* lg %skb_data,data_off(%b6) */
+			EMIT6_DISP_LH(0xe3000000, 0x0004, REG_SKB_DATA, REG_0,
+				      BPF_REG_6, offsetof(struct sk_buff, data));
 		/* basr %b5,%w1 (%b5 is call saved) */
 		EMIT2(0x0d00, BPF_REG_5, REG_W1);
 
@@ -1262,37 +1273,62 @@ void bpf_jit_compile(struct bpf_prog *fp
 /*
  * Compile eBPF program "fp"
  */
-void bpf_int_jit_compile(struct bpf_prog *fp)
+struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
 {
+	struct bpf_prog *tmp, *orig_fp = fp;
 	struct bpf_binary_header *header;
+	bool tmp_blinded = false;
 	struct bpf_jit jit;
 	int pass;
 
 	if (!bpf_jit_enable)
-		return;
+		return orig_fp;
+
+	tmp = bpf_jit_blind_constants(fp);
+	/*
+	 * If blinding was requested and we failed during blinding,
+	 * we must fall back to the interpreter.
+	 */
+	if (IS_ERR(tmp))
+		return orig_fp;
+	if (tmp != fp) {
+		tmp_blinded = true;
+		fp = tmp;
+	}
+
 	memset(&jit, 0, sizeof(jit));
 	jit.addrs = kcalloc(fp->len + 1, sizeof(*jit.addrs), GFP_KERNEL);
-	if (jit.addrs == NULL)
-		return;
+	if (jit.addrs == NULL) {
+		fp = orig_fp;
+		goto out;
+	}
 	/*
 	 * Three initial passes:
 	 *   - 1/2: Determine clobbered registers
 	 *   - 3:   Calculate program size and addrs arrray
 	 */
 	for (pass = 1; pass <= 3; pass++) {
-		if (bpf_jit_prog(&jit, fp))
+		if (bpf_jit_prog(&jit, fp)) {
+			fp = orig_fp;
 			goto free_addrs;
+		}
 	}
 	/*
 	 * Final pass: Allocate and generate program
 	 */
-	if (jit.size >= BPF_SIZE_MAX)
+	if (jit.size >= BPF_SIZE_MAX) {
+		fp = orig_fp;
 		goto free_addrs;
+	}
 	header = bpf_jit_binary_alloc(jit.size, &jit.prg_buf, 2, jit_fill_hole);
-	if (!header)
+	if (!header) {
+		fp = orig_fp;
 		goto free_addrs;
-	if (bpf_jit_prog(&jit, fp))
+	}
+	if (bpf_jit_prog(&jit, fp)) {
+		fp = orig_fp;
 		goto free_addrs;
+	}
 	if (bpf_jit_enable > 1) {
 		bpf_jit_dump(fp->len, jit.size, pass, jit.prg_buf);
 		if (jit.prg_buf)
@@ -1305,6 +1341,11 @@ void bpf_int_jit_compile(struct bpf_prog
 	}
 free_addrs:
 	kfree(jit.addrs);
+out:
+	if (tmp_blinded)
+		bpf_jit_prog_release_other(fp, fp == orig_fp ?
+					   tmp : orig_fp);
+	return fp;
 }
 
 /*
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/net/bpf_jit.h linux-libre-4.7-gnu/arch/s390/net/bpf_jit.h
--- linux-libre-4.6-gnu/arch/s390/net/bpf_jit.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/net/bpf_jit.h	2016-07-24 15:23:50.000000000 -0400
@@ -37,7 +37,7 @@ extern u8 sk_load_word[], sk_load_half[]
  *	      |		      |     |
  *	      +---------------+     |
  *	      | 8 byte skbp   |     |
- * R15+170 -> +---------------+     |
+ * R15+176 -> +---------------+     |
  *	      | 8 byte hlen   |     |
  * R15+168 -> +---------------+     |
  *	      | 4 byte align  |     |
@@ -58,7 +58,7 @@ extern u8 sk_load_word[], sk_load_half[]
 #define STK_OFF		(STK_SPACE - STK_160_UNUSED)
 #define STK_OFF_TMP	160	/* Offset of tmp buffer on stack */
 #define STK_OFF_HLEN	168	/* Offset of SKB header length on stack */
-#define STK_OFF_SKBP	170	/* Offset of SKB pointer on stack */
+#define STK_OFF_SKBP	176	/* Offset of SKB pointer on stack */
 
 #define STK_OFF_R6	(160 - 11 * 8)	/* Offset of r6 on stack */
 #define STK_OFF_TCCNT	(160 - 12 * 8)	/* Offset of tail_call_cnt on stack */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/pci/pci_debug.c linux-libre-4.7-gnu/arch/s390/pci/pci_debug.c
--- linux-libre-4.6-gnu/arch/s390/pci/pci_debug.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/pci/pci_debug.c	2016-07-24 15:23:50.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- *  Copyright IBM Corp. 2012
+ *  Copyright IBM Corp. 2012,2015
  *
  *  Author(s):
  *    Jan Glauber <jang@linux.vnet.ibm.com>
@@ -23,22 +23,45 @@ EXPORT_SYMBOL_GPL(pci_debug_msg_id);
 debug_info_t *pci_debug_err_id;
 EXPORT_SYMBOL_GPL(pci_debug_err_id);
 
-static char *pci_perf_names[] = {
-	/* hardware counters */
+static char *pci_common_names[] = {
 	"Load operations",
 	"Store operations",
 	"Store block operations",
 	"Refresh operations",
+};
+
+static char *pci_fmt0_names[] = {
 	"DMA read bytes",
 	"DMA write bytes",
 };
 
+static char *pci_fmt1_names[] = {
+	"Received bytes",
+	"Received packets",
+	"Transmitted bytes",
+	"Transmitted packets",
+};
+
+static char *pci_fmt2_names[] = {
+	"Consumed work units",
+	"Maximum work units",
+};
+
 static char *pci_sw_names[] = {
 	"Allocated pages",
 	"Mapped pages",
 	"Unmapped pages",
 };
 
+static void pci_fmb_show(struct seq_file *m, char *name[], int length,
+			 u64 *data)
+{
+	int i;
+
+	for (i = 0; i < length; i++, data++)
+		seq_printf(m, "%26s:\t%llu\n", name[i], *data);
+}
+
 static void pci_sw_counter_show(struct seq_file *m)
 {
 	struct zpci_dev *zdev = m->private;
@@ -53,8 +76,6 @@ static void pci_sw_counter_show(struct s
 static int pci_perf_show(struct seq_file *m, void *v)
 {
 	struct zpci_dev *zdev = m->private;
-	u64 *stat;
-	int i;
 
 	if (!zdev)
 		return 0;
@@ -72,15 +93,27 @@ static int pci_perf_show(struct seq_file
 	seq_printf(m, "Samples: %u\n", zdev->fmb->samples);
 	seq_printf(m, "Last update TOD: %Lx\n", zdev->fmb->last_update);
 
-	/* hardware counters */
-	stat = (u64 *) &zdev->fmb->ld_ops;
-	for (i = 0; i < 4; i++)
-		seq_printf(m, "%26s:\t%llu\n",
-			   pci_perf_names[i], *(stat + i));
-	if (zdev->fmb->dma_valid)
-		for (i = 4; i < 6; i++)
-			seq_printf(m, "%26s:\t%llu\n",
-				   pci_perf_names[i], *(stat + i));
+	pci_fmb_show(m, pci_common_names, ARRAY_SIZE(pci_common_names),
+		     &zdev->fmb->ld_ops);
+
+	switch (zdev->fmb->format) {
+	case 0:
+		if (!(zdev->fmb->fmt_ind & ZPCI_FMB_DMA_COUNTER_VALID))
+			break;
+		pci_fmb_show(m, pci_fmt0_names, ARRAY_SIZE(pci_fmt0_names),
+			     &zdev->fmb->fmt0.dma_rbytes);
+		break;
+	case 1:
+		pci_fmb_show(m, pci_fmt1_names, ARRAY_SIZE(pci_fmt1_names),
+			     &zdev->fmb->fmt1.rx_bytes);
+		break;
+	case 2:
+		pci_fmb_show(m, pci_fmt2_names, ARRAY_SIZE(pci_fmt2_names),
+			     &zdev->fmb->fmt2.consumed_work_units);
+		break;
+	default:
+		seq_puts(m, "Unknown format\n");
+	}
 
 	pci_sw_counter_show(m);
 	mutex_unlock(&zdev->lock);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/s390/pci/pci_sysfs.c linux-libre-4.7-gnu/arch/s390/pci/pci_sysfs.c
--- linux-libre-4.6-gnu/arch/s390/pci/pci_sysfs.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/s390/pci/pci_sysfs.c	2016-07-24 15:23:50.000000000 -0400
@@ -12,6 +12,8 @@
 #include <linux/stat.h>
 #include <linux/pci.h>
 
+#include <asm/sclp.h>
+
 #define zpci_attr(name, fmt, member)					\
 static ssize_t name##_show(struct device *dev,				\
 			   struct device_attribute *attr, char *buf)	\
@@ -77,8 +79,29 @@ static ssize_t util_string_read(struct f
 				       sizeof(zdev->util_str));
 }
 static BIN_ATTR_RO(util_string, CLP_UTIL_STR_LEN);
+
+static ssize_t report_error_write(struct file *filp, struct kobject *kobj,
+				  struct bin_attribute *attr, char *buf,
+				  loff_t off, size_t count)
+{
+	struct zpci_report_error_header *report = (void *) buf;
+	struct device *dev = kobj_to_dev(kobj);
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct zpci_dev *zdev = to_zpci(pdev);
+	int ret;
+
+	if (off || (count < sizeof(*report)))
+		return -EINVAL;
+
+	ret = sclp_pci_report(report, zdev->fh, zdev->fid);
+
+	return ret ? ret : count;
+}
+static BIN_ATTR(report_error, S_IWUSR, NULL, report_error_write, PAGE_SIZE);
+
 static struct bin_attribute *zpci_bin_attrs[] = {
 	&bin_attr_util_string,
+	&bin_attr_report_error,
 	NULL,
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/score/include/asm/pgalloc.h linux-libre-4.7-gnu/arch/score/include/asm/pgalloc.h
--- linux-libre-4.6-gnu/arch/score/include/asm/pgalloc.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/score/include/asm/pgalloc.h	2016-07-24 15:23:50.000000000 -0400
@@ -42,8 +42,7 @@ static inline pte_t *pte_alloc_one_kerne
 {
 	pte_t *pte;
 
-	pte = (pte_t *) __get_free_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO,
-					PTE_ORDER);
+	pte = (pte_t *) __get_free_pages(GFP_KERNEL|__GFP_ZERO, PTE_ORDER);
 
 	return pte;
 }
@@ -53,7 +52,7 @@ static inline struct page *pte_alloc_one
 {
 	struct page *pte;
 
-	pte = alloc_pages(GFP_KERNEL | __GFP_REPEAT, PTE_ORDER);
+	pte = alloc_pages(GFP_KERNEL, PTE_ORDER);
 	if (!pte)
 		return NULL;
 	clear_highpage(pte);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/score/include/uapi/asm/unistd.h linux-libre-4.7-gnu/arch/score/include/uapi/asm/unistd.h
--- linux-libre-4.6-gnu/arch/score/include/uapi/asm/unistd.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/score/include/uapi/asm/unistd.h	2016-07-24 15:23:50.000000000 -0400
@@ -1,5 +1,6 @@
 #define __ARCH_HAVE_MMU
 
+#define __ARCH_WANT_RENAMEAT
 #define __ARCH_WANT_SYSCALL_NO_AT
 #define __ARCH_WANT_SYSCALL_NO_FLAGS
 #define __ARCH_WANT_SYSCALL_OFF_T
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/score/Kconfig linux-libre-4.7-gnu/arch/score/Kconfig
--- linux-libre-4.6-gnu/arch/score/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/score/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -14,6 +14,7 @@ config SCORE
 	select VIRT_TO_BUS
 	select MODULES_USE_ELF_REL
 	select CLONE_BACKWARDS
+	select CPU_NO_EFFICIENT_FFS
 
 choice
 	prompt "System type"
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/score/kernel/process.c linux-libre-4.7-gnu/arch/score/kernel/process.c
--- linux-libre-4.6-gnu/arch/score/kernel/process.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/score/kernel/process.c	2016-07-24 15:23:50.000000000 -0400
@@ -56,8 +56,6 @@ void start_thread(struct pt_regs *regs,
 	regs->regs[0] = sp;
 }
 
-void exit_thread(void) {}
-
 /*
  * When a process does an "exec", machine state like FPU and debug
  * registers need to be reset.  This is a hook function for that.
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sh/boards/board-sh7757lcr.c linux-libre-4.7-gnu/arch/sh/boards/board-sh7757lcr.c
--- linux-libre-4.6-gnu/arch/sh/boards/board-sh7757lcr.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sh/boards/board-sh7757lcr.c	2016-07-24 15:23:50.000000000 -0400
@@ -20,7 +20,6 @@
 #include <linux/mfd/tmio.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/sh_mmcif.h>
-#include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/sh_eth.h>
 #include <linux/sh_intc.h>
 #include <linux/usb/renesas_usbhs.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sh/boards/mach-ap325rxa/setup.c linux-libre-4.7-gnu/arch/sh/boards/mach-ap325rxa/setup.c
--- linux-libre-4.6-gnu/arch/sh/boards/mach-ap325rxa/setup.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sh/boards/mach-ap325rxa/setup.c	2016-07-24 15:23:50.000000000 -0400
@@ -15,7 +15,6 @@
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/mmc/host.h>
-#include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/sh_flctl.h>
 #include <linux/mfd/tmio.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sh/boards/mach-ecovec24/setup.c linux-libre-4.7-gnu/arch/sh/boards/mach-ecovec24/setup.c
--- linux-libre-4.6-gnu/arch/sh/boards/mach-ecovec24/setup.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sh/boards/mach-ecovec24/setup.c	2016-07-24 15:23:50.000000000 -0400
@@ -13,7 +13,6 @@
 #include <linux/platform_device.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/sh_mmcif.h>
-#include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/mtd/physmap.h>
 #include <linux/mfd/tmio.h>
 #include <linux/gpio.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sh/boards/mach-kfr2r09/setup.c linux-libre-4.7-gnu/arch/sh/boards/mach-kfr2r09/setup.c
--- linux-libre-4.6-gnu/arch/sh/boards/mach-kfr2r09/setup.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sh/boards/mach-kfr2r09/setup.c	2016-07-24 15:23:50.000000000 -0400
@@ -11,7 +11,6 @@
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/mmc/host.h>
-#include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/mfd/tmio.h>
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/onenand.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sh/boards/mach-migor/setup.c linux-libre-4.7-gnu/arch/sh/boards/mach-migor/setup.c
--- linux-libre-4.6-gnu/arch/sh/boards/mach-migor/setup.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sh/boards/mach-migor/setup.c	2016-07-24 15:23:50.000000000 -0400
@@ -13,7 +13,6 @@
 #include <linux/input.h>
 #include <linux/input/sh_keysc.h>
 #include <linux/mmc/host.h>
-#include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/mtd/physmap.h>
 #include <linux/mfd/tmio.h>
 #include <linux/mtd/nand.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sh/boards/mach-sdk7786/gpio.c linux-libre-4.7-gnu/arch/sh/boards/mach-sdk7786/gpio.c
--- linux-libre-4.6-gnu/arch/sh/boards/mach-sdk7786/gpio.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sh/boards/mach-sdk7786/gpio.c	2016-07-24 15:23:50.000000000 -0400
@@ -9,7 +9,7 @@
  */
 #include <linux/init.h>
 #include <linux/interrupt.h>
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
 #include <linux/irq.h>
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
@@ -44,6 +44,6 @@ static struct gpio_chip usrgpir_gpio_chi
 
 static int __init usrgpir_gpio_setup(void)
 {
-	return gpiochip_add(&usrgpir_gpio_chip);
+	return gpiochip_add_data(&usrgpir_gpio_chip, NULL);
 }
 device_initcall(usrgpir_gpio_setup);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sh/boards/mach-se/7724/setup.c linux-libre-4.7-gnu/arch/sh/boards/mach-se/7724/setup.c
--- linux-libre-4.6-gnu/arch/sh/boards/mach-se/7724/setup.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sh/boards/mach-se/7724/setup.c	2016-07-24 15:23:50.000000000 -0400
@@ -15,7 +15,6 @@
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/mmc/host.h>
-#include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/mfd/tmio.h>
 #include <linux/mtd/physmap.h>
 #include <linux/delay.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sh/boards/mach-x3proto/gpio.c linux-libre-4.7-gnu/arch/sh/boards/mach-x3proto/gpio.c
--- linux-libre-4.6-gnu/arch/sh/boards/mach-x3proto/gpio.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sh/boards/mach-x3proto/gpio.c	2016-07-24 15:23:50.000000000 -0400
@@ -13,7 +13,7 @@
 
 #include <linux/init.h>
 #include <linux/interrupt.h>
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
 #include <linux/irq.h>
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
@@ -107,7 +107,7 @@ int __init x3proto_gpio_setup(void)
 	if (unlikely(ilsel < 0))
 		return ilsel;
 
-	ret = gpiochip_add(&x3proto_gpio_chip);
+	ret = gpiochip_add_data(&x3proto_gpio_chip, NULL);
 	if (unlikely(ret))
 		goto err_gpio;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sh/boot/compressed/Makefile linux-libre-4.7-gnu/arch/sh/boot/compressed/Makefile
--- linux-libre-4.6-gnu/arch/sh/boot/compressed/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sh/boot/compressed/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -55,7 +55,6 @@ $(addprefix $(obj)/,$(lib1funcs-y)): $(o
 
 $(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o $(lib1funcs-obj) FORCE
 	$(call if_changed,ld)
-	@:
 
 $(obj)/vmlinux.bin: vmlinux FORCE
 	$(call if_changed,objcopy)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sh/boot/romimage/Makefile linux-libre-4.7-gnu/arch/sh/boot/romimage/Makefile
--- linux-libre-4.6-gnu/arch/sh/boot/romimage/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sh/boot/romimage/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -17,7 +17,6 @@ LDFLAGS_vmlinux := --oformat $(ld-bfd) -
 
 $(obj)/vmlinux: $(obj)/head.o $(obj-y) $(obj)/piggy.o FORCE
 	$(call if_changed,ld)
-	@:
 
 OBJCOPYFLAGS += -j .empty_zero_page
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sh/configs/apsh4ad0a_defconfig linux-libre-4.7-gnu/arch/sh/configs/apsh4ad0a_defconfig
--- linux-libre-4.6-gnu/arch/sh/configs/apsh4ad0a_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sh/configs/apsh4ad0a_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -10,7 +10,6 @@ CONFIG_CGROUPS=y
 CONFIG_CGROUP_FREEZER=y
 CONFIG_CGROUP_DEVICE=y
 CONFIG_CGROUP_CPUACCT=y
-CONFIG_RESOURCE_COUNTERS=y
 CONFIG_CGROUP_MEMCG=y
 CONFIG_BLK_CGROUP=y
 CONFIG_NAMESPACES=y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sh/configs/sdk7786_defconfig linux-libre-4.7-gnu/arch/sh/configs/sdk7786_defconfig
--- linux-libre-4.6-gnu/arch/sh/configs/sdk7786_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sh/configs/sdk7786_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -17,7 +17,6 @@ CONFIG_CGROUP_DEVICE=y
 CONFIG_CPUSETS=y
 # CONFIG_PROC_PID_CPUSET is not set
 CONFIG_CGROUP_CPUACCT=y
-CONFIG_RESOURCE_COUNTERS=y
 CONFIG_CGROUP_MEMCG=y
 CONFIG_CGROUP_MEMCG_SWAP=y
 CONFIG_CGROUP_SCHED=y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sh/configs/se7206_defconfig linux-libre-4.7-gnu/arch/sh/configs/se7206_defconfig
--- linux-libre-4.6-gnu/arch/sh/configs/se7206_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sh/configs/se7206_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -10,7 +10,6 @@ CONFIG_CGROUPS=y
 CONFIG_CGROUP_DEBUG=y
 CONFIG_CGROUP_DEVICE=y
 CONFIG_CGROUP_CPUACCT=y
-CONFIG_RESOURCE_COUNTERS=y
 CONFIG_CGROUP_MEMCG=y
 CONFIG_RELAY=y
 CONFIG_NAMESPACES=y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sh/configs/shx3_defconfig linux-libre-4.7-gnu/arch/sh/configs/shx3_defconfig
--- linux-libre-4.6-gnu/arch/sh/configs/shx3_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sh/configs/shx3_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -12,7 +12,6 @@ CONFIG_CGROUPS=y
 CONFIG_CGROUP_FREEZER=y
 CONFIG_CGROUP_DEVICE=y
 CONFIG_CGROUP_CPUACCT=y
-CONFIG_RESOURCE_COUNTERS=y
 CONFIG_CGROUP_MEMCG=y
 CONFIG_RELAY=y
 CONFIG_NAMESPACES=y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sh/configs/urquell_defconfig linux-libre-4.7-gnu/arch/sh/configs/urquell_defconfig
--- linux-libre-4.6-gnu/arch/sh/configs/urquell_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sh/configs/urquell_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -14,7 +14,6 @@ CONFIG_CGROUP_DEVICE=y
 CONFIG_CPUSETS=y
 # CONFIG_PROC_PID_CPUSET is not set
 CONFIG_CGROUP_CPUACCT=y
-CONFIG_RESOURCE_COUNTERS=y
 CONFIG_CGROUP_MEMCG=y
 CONFIG_CGROUP_MEMCG_SWAP=y
 CONFIG_CGROUP_SCHED=y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sh/include/asm/Kbuild linux-libre-4.7-gnu/arch/sh/include/asm/Kbuild
--- linux-libre-4.6-gnu/arch/sh/include/asm/Kbuild	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sh/include/asm/Kbuild	2016-07-24 15:23:50.000000000 -0400
@@ -26,6 +26,7 @@ generic-y += percpu.h
 generic-y += poll.h
 generic-y += preempt.h
 generic-y += resource.h
+generic-y += rwsem.h
 generic-y += sembuf.h
 generic-y += serial.h
 generic-y += shmbuf.h
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sh/include/asm/pgalloc.h linux-libre-4.7-gnu/arch/sh/include/asm/pgalloc.h
--- linux-libre-4.6-gnu/arch/sh/include/asm/pgalloc.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sh/include/asm/pgalloc.h	2016-07-24 15:23:50.000000000 -0400
@@ -34,7 +34,7 @@ static inline void pmd_populate(struct m
 static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
 					  unsigned long address)
 {
-	return quicklist_alloc(QUICK_PT, GFP_KERNEL | __GFP_REPEAT, NULL);
+	return quicklist_alloc(QUICK_PT, GFP_KERNEL, NULL);
 }
 
 static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
@@ -43,7 +43,7 @@ static inline pgtable_t pte_alloc_one(st
 	struct page *page;
 	void *pg;
 
-	pg = quicklist_alloc(QUICK_PT, GFP_KERNEL | __GFP_REPEAT, NULL);
+	pg = quicklist_alloc(QUICK_PT, GFP_KERNEL, NULL);
 	if (!pg)
 		return NULL;
 	page = virt_to_page(pg);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sh/include/asm/rwsem.h linux-libre-4.7-gnu/arch/sh/include/asm/rwsem.h
--- linux-libre-4.6-gnu/arch/sh/include/asm/rwsem.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sh/include/asm/rwsem.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,132 +0,0 @@
-/*
- * include/asm-sh/rwsem.h: R/W semaphores for SH using the stuff
- * in lib/rwsem.c.
- */
-
-#ifndef _ASM_SH_RWSEM_H
-#define _ASM_SH_RWSEM_H
-
-#ifndef _LINUX_RWSEM_H
-#error "please don't include asm/rwsem.h directly, use linux/rwsem.h instead"
-#endif
-
-#ifdef __KERNEL__
-
-#define RWSEM_UNLOCKED_VALUE		0x00000000
-#define RWSEM_ACTIVE_BIAS		0x00000001
-#define RWSEM_ACTIVE_MASK		0x0000ffff
-#define RWSEM_WAITING_BIAS		(-0x00010000)
-#define RWSEM_ACTIVE_READ_BIAS		RWSEM_ACTIVE_BIAS
-#define RWSEM_ACTIVE_WRITE_BIAS		(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
-
-/*
- * lock for reading
- */
-static inline void __down_read(struct rw_semaphore *sem)
-{
-	if (atomic_inc_return((atomic_t *)(&sem->count)) > 0)
-		smp_wmb();
-	else
-		rwsem_down_read_failed(sem);
-}
-
-static inline int __down_read_trylock(struct rw_semaphore *sem)
-{
-	int tmp;
-
-	while ((tmp = sem->count) >= 0) {
-		if (tmp == cmpxchg(&sem->count, tmp,
-				   tmp + RWSEM_ACTIVE_READ_BIAS)) {
-			smp_wmb();
-			return 1;
-		}
-	}
-	return 0;
-}
-
-/*
- * lock for writing
- */
-static inline void __down_write(struct rw_semaphore *sem)
-{
-	int tmp;
-
-	tmp = atomic_add_return(RWSEM_ACTIVE_WRITE_BIAS,
-				(atomic_t *)(&sem->count));
-	if (tmp == RWSEM_ACTIVE_WRITE_BIAS)
-		smp_wmb();
-	else
-		rwsem_down_write_failed(sem);
-}
-
-static inline int __down_write_trylock(struct rw_semaphore *sem)
-{
-	int tmp;
-
-	tmp = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE,
-		      RWSEM_ACTIVE_WRITE_BIAS);
-	smp_wmb();
-	return tmp == RWSEM_UNLOCKED_VALUE;
-}
-
-/*
- * unlock after reading
- */
-static inline void __up_read(struct rw_semaphore *sem)
-{
-	int tmp;
-
-	smp_wmb();
-	tmp = atomic_dec_return((atomic_t *)(&sem->count));
-	if (tmp < -1 && (tmp & RWSEM_ACTIVE_MASK) == 0)
-		rwsem_wake(sem);
-}
-
-/*
- * unlock after writing
- */
-static inline void __up_write(struct rw_semaphore *sem)
-{
-	smp_wmb();
-	if (atomic_sub_return(RWSEM_ACTIVE_WRITE_BIAS,
-			      (atomic_t *)(&sem->count)) < 0)
-		rwsem_wake(sem);
-}
-
-/*
- * implement atomic add functionality
- */
-static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem)
-{
-	atomic_add(delta, (atomic_t *)(&sem->count));
-}
-
-/*
- * downgrade write lock to read lock
- */
-static inline void __downgrade_write(struct rw_semaphore *sem)
-{
-	int tmp;
-
-	smp_wmb();
-	tmp = atomic_add_return(-RWSEM_WAITING_BIAS, (atomic_t *)(&sem->count));
-	if (tmp < 0)
-		rwsem_downgrade_wake(sem);
-}
-
-static inline void __down_write_nested(struct rw_semaphore *sem, int subclass)
-{
-	__down_write(sem);
-}
-
-/*
- * implement exchange and add functionality
- */
-static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem)
-{
-	smp_mb();
-	return atomic_add_return(delta, (atomic_t *)(&sem->count));
-}
-
-#endif /* __KERNEL__ */
-#endif /* _ASM_SH_RWSEM_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sh/Kconfig linux-libre-4.7-gnu/arch/sh/Kconfig
--- linux-libre-4.6-gnu/arch/sh/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sh/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -20,6 +20,7 @@ config SUPERH
 	select PERF_USE_VMALLOC
 	select HAVE_DEBUG_KMEMLEAK
 	select HAVE_KERNEL_GZIP
+	select CPU_NO_EFFICIENT_FFS
 	select HAVE_KERNEL_BZIP2
 	select HAVE_KERNEL_LZMA
 	select HAVE_KERNEL_XZ
@@ -44,6 +45,7 @@ config SUPERH
 	select OLD_SIGSUSPEND
 	select OLD_SIGACTION
 	select HAVE_ARCH_AUDITSYSCALL
+	select HAVE_NMI
 	help
 	  The SuperH is a RISC processor targeted for use in embedded systems
 	  and consumer electronics; it was also used in the Sega Dreamcast
@@ -71,6 +73,7 @@ config SUPERH32
 
 config SUPERH64
 	def_bool ARCH = "sh64"
+	select HAVE_EXIT_THREAD
 	select KALLSYMS
 
 config ARCH_DEFCONFIG
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sh/kernel/perf_callchain.c linux-libre-4.7-gnu/arch/sh/kernel/perf_callchain.c
--- linux-libre-4.6-gnu/arch/sh/kernel/perf_callchain.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sh/kernel/perf_callchain.c	2016-07-24 15:23:50.000000000 -0400
@@ -21,7 +21,7 @@ static int callchain_stack(void *data, c
 
 static void callchain_address(void *data, unsigned long addr, int reliable)
 {
-	struct perf_callchain_entry *entry = data;
+	struct perf_callchain_entry_ctx *entry = data;
 
 	if (reliable)
 		perf_callchain_store(entry, addr);
@@ -33,7 +33,7 @@ static const struct stacktrace_ops callc
 };
 
 void
-perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs)
+perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs)
 {
 	perf_callchain_store(entry, regs->pc);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sh/kernel/process_32.c linux-libre-4.7-gnu/arch/sh/kernel/process_32.c
--- linux-libre-4.6-gnu/arch/sh/kernel/process_32.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sh/kernel/process_32.c	2016-07-24 15:23:50.000000000 -0400
@@ -76,13 +76,6 @@ void start_thread(struct pt_regs *regs,
 }
 EXPORT_SYMBOL(start_thread);
 
-/*
- * Free current thread data structures etc..
- */
-void exit_thread(void)
-{
-}
-
 void flush_thread(void)
 {
 	struct task_struct *tsk = current;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sh/kernel/process_64.c linux-libre-4.7-gnu/arch/sh/kernel/process_64.c
--- linux-libre-4.6-gnu/arch/sh/kernel/process_64.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sh/kernel/process_64.c	2016-07-24 15:23:50.000000000 -0400
@@ -288,7 +288,7 @@ void show_regs(struct pt_regs *regs)
 /*
  * Free current thread data structures etc..
  */
-void exit_thread(void)
+void exit_thread(struct task_struct *tsk)
 {
 	/*
 	 * See arch/sparc/kernel/process.c for the precedent for doing
@@ -307,9 +307,8 @@ void exit_thread(void)
 	 * which it would get safely nulled.
 	 */
 #ifdef CONFIG_SH_FPU
-	if (last_task_used_math == current) {
+	if (last_task_used_math == tsk)
 		last_task_used_math = NULL;
-	}
 #endif
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sh/kernel/vsyscall/vsyscall.c linux-libre-4.7-gnu/arch/sh/kernel/vsyscall/vsyscall.c
--- linux-libre-4.6-gnu/arch/sh/kernel/vsyscall/vsyscall.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sh/kernel/vsyscall/vsyscall.c	2016-07-24 15:23:50.000000000 -0400
@@ -64,7 +64,9 @@ int arch_setup_additional_pages(struct l
 	unsigned long addr;
 	int ret;
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
+
 	addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, 0);
 	if (IS_ERR_VALUE(addr)) {
 		ret = addr;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sh/mm/pgtable.c linux-libre-4.7-gnu/arch/sh/mm/pgtable.c
--- linux-libre-4.6-gnu/arch/sh/mm/pgtable.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sh/mm/pgtable.c	2016-07-24 15:23:50.000000000 -0400
@@ -1,7 +1,7 @@
 #include <linux/mm.h>
 #include <linux/slab.h>
 
-#define PGALLOC_GFP GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO
+#define PGALLOC_GFP GFP_KERNEL | __GFP_ZERO
 
 static struct kmem_cache *pgd_cachep;
 #if PAGETABLE_LEVELS > 2
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sparc/include/asm/head_32.h linux-libre-4.7-gnu/arch/sparc/include/asm/head_32.h
--- linux-libre-4.6-gnu/arch/sparc/include/asm/head_32.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sparc/include/asm/head_32.h	2016-07-24 15:23:50.000000000 -0400
@@ -43,10 +43,10 @@
 	nop;
 
 #ifdef CONFIG_KGDB
-#define KGDB_TRAP(num) \
-	b kgdb_trap_low; \
-	rd %psr,%l0; \
-	nop; \
+#define KGDB_TRAP(num)                  \
+	mov num, %l7;                   \
+	b kgdb_trap_low;                \
+	rd %psr,%l0;                    \
 	nop;
 #else
 #define KGDB_TRAP(num) \
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sparc/include/asm/head_64.h linux-libre-4.7-gnu/arch/sparc/include/asm/head_64.h
--- linux-libre-4.6-gnu/arch/sparc/include/asm/head_64.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sparc/include/asm/head_64.h	2016-07-24 15:23:50.000000000 -0400
@@ -15,6 +15,10 @@
 
 #define	PTREGS_OFF	(STACK_BIAS + STACKFRAME_SZ)
 
+#define	RTRAP_PSTATE		(PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV|PSTATE_IE)
+#define	RTRAP_PSTATE_IRQOFF	(PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV)
+#define RTRAP_PSTATE_AG_IRQOFF	(PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV|PSTATE_AG)
+
 #define __CHEETAH_ID	0x003e0014
 #define __JALAPENO_ID	0x003e0016
 #define __SERRANO_ID	0x003e0022
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sparc/include/asm/Kbuild linux-libre-4.7-gnu/arch/sparc/include/asm/Kbuild
--- linux-libre-4.6-gnu/arch/sparc/include/asm/Kbuild	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sparc/include/asm/Kbuild	2016-07-24 15:23:50.000000000 -0400
@@ -16,6 +16,7 @@ generic-y += mm-arch-hooks.h
 generic-y += module.h
 generic-y += mutex.h
 generic-y += preempt.h
+generic-y += rwsem.h
 generic-y += serial.h
 generic-y += trace_clock.h
 generic-y += types.h
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sparc/include/asm/kgdb.h linux-libre-4.7-gnu/arch/sparc/include/asm/kgdb.h
--- linux-libre-4.6-gnu/arch/sparc/include/asm/kgdb.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sparc/include/asm/kgdb.h	2016-07-24 15:23:50.000000000 -0400
@@ -28,10 +28,10 @@ enum regnames {
 #define NUMREGBYTES		((GDB_CSR + 1) * 4)
 #else
 #define NUMREGBYTES		((GDB_Y + 1) * 8)
+#endif
 
 struct pt_regs;
 asmlinkage void kgdb_trap(unsigned long trap_level, struct pt_regs *regs);
-#endif
 
 void arch_kgdb_breakpoint(void);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sparc/include/asm/page_32.h linux-libre-4.7-gnu/arch/sparc/include/asm/page_32.h
--- linux-libre-4.6-gnu/arch/sparc/include/asm/page_32.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sparc/include/asm/page_32.h	2016-07-24 15:23:50.000000000 -0400
@@ -69,7 +69,6 @@ typedef struct { unsigned long iopgprot;
 
 #define __pte(x)	((pte_t) { (x) } )
 #define __iopte(x)	((iopte_t) { (x) } )
-/* #define __pmd(x)        ((pmd_t) { (x) } ) */ /* XXX procedure with loop */
 #define __pgd(x)	((pgd_t) { (x) } )
 #define __ctxd(x)	((ctxd_t) { (x) } )
 #define __pgprot(x)	((pgprot_t) { (x) } )
@@ -97,7 +96,6 @@ typedef unsigned long iopgprot_t;
 
 #define __pte(x)	(x)
 #define __iopte(x)	(x)
-/* #define __pmd(x)        (x) */ /* XXX later */
 #define __pgd(x)	(x)
 #define __ctxd(x)	(x)
 #define __pgprot(x)	(x)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sparc/include/asm/pgalloc_32.h linux-libre-4.7-gnu/arch/sparc/include/asm/pgalloc_32.h
--- linux-libre-4.6-gnu/arch/sparc/include/asm/pgalloc_32.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sparc/include/asm/pgalloc_32.h	2016-07-24 15:23:50.000000000 -0400
@@ -29,9 +29,9 @@ static inline void free_pgd_fast(pgd_t *
 
 static inline void pgd_set(pgd_t * pgdp, pmd_t * pmdp)
 {
-	unsigned long pa = __nocache_pa((unsigned long)pmdp);
+	unsigned long pa = __nocache_pa(pmdp);
 
-	set_pte((pte_t *)pgdp, (SRMMU_ET_PTD | (pa >> 4)));
+	set_pte((pte_t *)pgdp, __pte((SRMMU_ET_PTD | (pa >> 4))));
 }
 
 #define pgd_populate(MM, PGD, PMD)      pgd_set(PGD, PMD)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sparc/include/asm/pgalloc_64.h linux-libre-4.7-gnu/arch/sparc/include/asm/pgalloc_64.h
--- linux-libre-4.6-gnu/arch/sparc/include/asm/pgalloc_64.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sparc/include/asm/pgalloc_64.h	2016-07-24 15:23:50.000000000 -0400
@@ -41,8 +41,7 @@ static inline void __pud_populate(pud_t
 
 static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
 {
-	return kmem_cache_alloc(pgtable_cache,
-				GFP_KERNEL|__GFP_REPEAT);
+	return kmem_cache_alloc(pgtable_cache, GFP_KERNEL);
 }
 
 static inline void pud_free(struct mm_struct *mm, pud_t *pud)
@@ -52,8 +51,7 @@ static inline void pud_free(struct mm_st
 
 static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
 {
-	return kmem_cache_alloc(pgtable_cache,
-				GFP_KERNEL|__GFP_REPEAT);
+	return kmem_cache_alloc(pgtable_cache, GFP_KERNEL);
 }
 
 static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sparc/include/asm/pgtable_32.h linux-libre-4.7-gnu/arch/sparc/include/asm/pgtable_32.h
--- linux-libre-4.6-gnu/arch/sparc/include/asm/pgtable_32.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sparc/include/asm/pgtable_32.h	2016-07-24 15:23:50.000000000 -0400
@@ -298,7 +298,7 @@ static inline pte_t mk_pte_io(unsigned l
 #define pgprot_noncached pgprot_noncached
 static inline pgprot_t pgprot_noncached(pgprot_t prot)
 {
-	prot &= ~__pgprot(SRMMU_CACHE);
+	pgprot_val(prot) &= ~pgprot_val(__pgprot(SRMMU_CACHE));
 	return prot;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sparc/include/asm/pgtable_64.h linux-libre-4.7-gnu/arch/sparc/include/asm/pgtable_64.h
--- linux-libre-4.6-gnu/arch/sparc/include/asm/pgtable_64.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sparc/include/asm/pgtable_64.h	2016-07-24 15:23:50.000000000 -0400
@@ -375,7 +375,7 @@ static inline pgprot_t pgprot_noncached(
 #define pgprot_noncached pgprot_noncached
 
 #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
-static inline pte_t pte_mkhuge(pte_t pte)
+static inline unsigned long __pte_huge_mask(void)
 {
 	unsigned long mask;
 
@@ -390,8 +390,19 @@ static inline pte_t pte_mkhuge(pte_t pte
 	: "=r" (mask)
 	: "i" (_PAGE_SZHUGE_4U), "i" (_PAGE_SZHUGE_4V));
 
-	return __pte(pte_val(pte) | mask);
+	return mask;
+}
+
+static inline pte_t pte_mkhuge(pte_t pte)
+{
+	return __pte(pte_val(pte) | __pte_huge_mask());
 }
+
+static inline bool is_hugetlb_pte(pte_t pte)
+{
+	return !!(pte_val(pte) & __pte_huge_mask());
+}
+
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 static inline pmd_t pmd_mkhuge(pmd_t pmd)
 {
@@ -403,6 +414,11 @@ static inline pmd_t pmd_mkhuge(pmd_t pmd
 	return __pmd(pte_val(pte));
 }
 #endif
+#else
+static inline bool is_hugetlb_pte(pte_t pte)
+{
+	return false;
+}
 #endif
 
 static inline pte_t pte_mkdirty(pte_t pte)
@@ -681,8 +697,6 @@ static inline unsigned long pmd_trans_hu
 	return pte_val(pte) & _PAGE_PMD_HUGE;
 }
 
-#define has_transparent_hugepage() 1
-
 static inline pmd_t pmd_mkold(pmd_t pmd)
 {
 	pte_t pte = __pte(pmd_val(pmd));
@@ -858,6 +872,19 @@ static inline unsigned long pud_pfn(pud_
 void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr,
 		   pte_t *ptep, pte_t orig, int fullmm);
 
+static void maybe_tlb_batch_add(struct mm_struct *mm, unsigned long vaddr,
+				pte_t *ptep, pte_t orig, int fullmm)
+{
+	/* It is more efficient to let flush_tlb_kernel_range()
+	 * handle init_mm tlb flushes.
+	 *
+	 * SUN4V NOTE: _PAGE_VALID is the same value in both the SUN4U
+	 *             and SUN4V pte layout, so this inline test is fine.
+	 */
+	if (likely(mm != &init_mm) && pte_accessible(mm, orig))
+		tlb_batch_add(mm, vaddr, ptep, orig, fullmm);
+}
+
 #define __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR
 static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
 					    unsigned long addr,
@@ -874,15 +901,7 @@ static inline void __set_pte_at(struct m
 	pte_t orig = *ptep;
 
 	*ptep = pte;
-
-	/* It is more efficient to let flush_tlb_kernel_range()
-	 * handle init_mm tlb flushes.
-	 *
-	 * SUN4V NOTE: _PAGE_VALID is the same value in both the SUN4U
-	 *             and SUN4V pte layout, so this inline test is fine.
-	 */
-	if (likely(mm != &init_mm) && pte_accessible(mm, orig))
-		tlb_batch_add(mm, addr, ptep, orig, fullmm);
+	maybe_tlb_batch_add(mm, addr, ptep, orig, fullmm);
 }
 
 #define set_pte_at(mm,addr,ptep,pte)	\
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sparc/include/asm/rwsem.h linux-libre-4.7-gnu/arch/sparc/include/asm/rwsem.h
--- linux-libre-4.6-gnu/arch/sparc/include/asm/rwsem.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sparc/include/asm/rwsem.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,124 +0,0 @@
-/*
- * rwsem.h: R/W semaphores implemented using CAS
- *
- * Written by David S. Miller (davem@redhat.com), 2001.
- * Derived from asm-i386/rwsem.h
- */
-#ifndef _SPARC64_RWSEM_H
-#define _SPARC64_RWSEM_H
-
-#ifndef _LINUX_RWSEM_H
-#error "please don't include asm/rwsem.h directly, use linux/rwsem.h instead"
-#endif
-
-#ifdef __KERNEL__
-
-#define RWSEM_UNLOCKED_VALUE		0x00000000L
-#define RWSEM_ACTIVE_BIAS		0x00000001L
-#define RWSEM_ACTIVE_MASK		0xffffffffL
-#define RWSEM_WAITING_BIAS		(-RWSEM_ACTIVE_MASK-1)
-#define RWSEM_ACTIVE_READ_BIAS		RWSEM_ACTIVE_BIAS
-#define RWSEM_ACTIVE_WRITE_BIAS		(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
-
-/*
- * lock for reading
- */
-static inline void __down_read(struct rw_semaphore *sem)
-{
-	if (unlikely(atomic64_inc_return((atomic64_t *)(&sem->count)) <= 0L))
-		rwsem_down_read_failed(sem);
-}
-
-static inline int __down_read_trylock(struct rw_semaphore *sem)
-{
-	long tmp;
-
-	while ((tmp = sem->count) >= 0L) {
-		if (tmp == cmpxchg(&sem->count, tmp,
-				   tmp + RWSEM_ACTIVE_READ_BIAS)) {
-			return 1;
-		}
-	}
-	return 0;
-}
-
-/*
- * lock for writing
- */
-static inline void __down_write_nested(struct rw_semaphore *sem, int subclass)
-{
-	long tmp;
-
-	tmp = atomic64_add_return(RWSEM_ACTIVE_WRITE_BIAS,
-				  (atomic64_t *)(&sem->count));
-	if (unlikely(tmp != RWSEM_ACTIVE_WRITE_BIAS))
-		rwsem_down_write_failed(sem);
-}
-
-static inline void __down_write(struct rw_semaphore *sem)
-{
-	__down_write_nested(sem, 0);
-}
-
-static inline int __down_write_trylock(struct rw_semaphore *sem)
-{
-	long tmp;
-
-	tmp = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE,
-		      RWSEM_ACTIVE_WRITE_BIAS);
-	return tmp == RWSEM_UNLOCKED_VALUE;
-}
-
-/*
- * unlock after reading
- */
-static inline void __up_read(struct rw_semaphore *sem)
-{
-	long tmp;
-
-	tmp = atomic64_dec_return((atomic64_t *)(&sem->count));
-	if (unlikely(tmp < -1L && (tmp & RWSEM_ACTIVE_MASK) == 0L))
-		rwsem_wake(sem);
-}
-
-/*
- * unlock after writing
- */
-static inline void __up_write(struct rw_semaphore *sem)
-{
-	if (unlikely(atomic64_sub_return(RWSEM_ACTIVE_WRITE_BIAS,
-					 (atomic64_t *)(&sem->count)) < 0L))
-		rwsem_wake(sem);
-}
-
-/*
- * implement atomic add functionality
- */
-static inline void rwsem_atomic_add(long delta, struct rw_semaphore *sem)
-{
-	atomic64_add(delta, (atomic64_t *)(&sem->count));
-}
-
-/*
- * downgrade write lock to read lock
- */
-static inline void __downgrade_write(struct rw_semaphore *sem)
-{
-	long tmp;
-
-	tmp = atomic64_add_return(-RWSEM_WAITING_BIAS, (atomic64_t *)(&sem->count));
-	if (tmp < 0L)
-		rwsem_downgrade_wake(sem);
-}
-
-/*
- * implement exchange and add functionality
- */
-static inline long rwsem_atomic_update(long delta, struct rw_semaphore *sem)
-{
-	return atomic64_add_return(delta, (atomic64_t *)(&sem->count));
-}
-
-#endif /* __KERNEL__ */
-
-#endif /* _SPARC64_RWSEM_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sparc/include/asm/tlbflush_64.h linux-libre-4.7-gnu/arch/sparc/include/asm/tlbflush_64.h
--- linux-libre-4.6-gnu/arch/sparc/include/asm/tlbflush_64.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sparc/include/asm/tlbflush_64.h	2016-07-24 15:23:50.000000000 -0400
@@ -8,6 +8,7 @@
 #define TLB_BATCH_NR	192
 
 struct tlb_batch {
+	bool huge;
 	struct mm_struct *mm;
 	unsigned long tlb_nr;
 	unsigned long active;
@@ -16,7 +17,7 @@ struct tlb_batch {
 
 void flush_tsb_kernel_range(unsigned long start, unsigned long end);
 void flush_tsb_user(struct tlb_batch *tb);
-void flush_tsb_user_page(struct mm_struct *mm, unsigned long vaddr);
+void flush_tsb_user_page(struct mm_struct *mm, unsigned long vaddr, bool huge);
 
 /* TLB flush operations. */
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sparc/include/asm/ttable.h linux-libre-4.7-gnu/arch/sparc/include/asm/ttable.h
--- linux-libre-4.6-gnu/arch/sparc/include/asm/ttable.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sparc/include/asm/ttable.h	2016-07-24 15:23:50.000000000 -0400
@@ -589,8 +589,8 @@ user_rtt_fill_64bit:					\
 	 restored;					\
 	nop; nop; nop; nop; nop; nop;			\
 	nop; nop; nop; nop; nop;			\
-	ba,a,pt	%xcc, user_rtt_fill_fixup;		\
-	ba,a,pt	%xcc, user_rtt_fill_fixup;		\
+	ba,a,pt	%xcc, user_rtt_fill_fixup_dax;		\
+	ba,a,pt	%xcc, user_rtt_fill_fixup_mna;		\
 	ba,a,pt	%xcc, user_rtt_fill_fixup;
 
 
@@ -652,8 +652,8 @@ user_rtt_fill_32bit:					\
 	 restored;					\
 	nop; nop; nop; nop; nop;			\
 	nop; nop; nop;					\
-	ba,a,pt	%xcc, user_rtt_fill_fixup;		\
-	ba,a,pt	%xcc, user_rtt_fill_fixup;		\
+	ba,a,pt	%xcc, user_rtt_fill_fixup_dax;		\
+	ba,a,pt	%xcc, user_rtt_fill_fixup_mna;		\
 	ba,a,pt	%xcc, user_rtt_fill_fixup;
 
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sparc/Kconfig linux-libre-4.7-gnu/arch/sparc/Kconfig
--- linux-libre-4.6-gnu/arch/sparc/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sparc/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -20,8 +20,8 @@ config SPARC
 	select HAVE_OPROFILE
 	select HAVE_ARCH_KGDB if !SMP || SPARC64
 	select HAVE_ARCH_TRACEHOOK
+	select HAVE_EXIT_THREAD
 	select SYSCTL_EXCEPTION_TRACE
-	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
 	select RTC_CLASS
 	select RTC_DRV_M48T59
@@ -32,7 +32,7 @@ config SPARC
 	select ARCH_WANT_IPC_PARSE_VERSION
 	select GENERIC_PCI_IOMAP
 	select HAVE_NMI_WATCHDOG if SPARC64
-	select HAVE_BPF_JIT
+	select HAVE_CBPF_JIT
 	select HAVE_DEBUG_BUGVERBOSE
 	select GENERIC_SMP_IDLE_THREAD
 	select GENERIC_CLOCKEVENTS
@@ -42,6 +42,7 @@ config SPARC
 	select ODD_RT_SIGACTION
 	select OLD_SIGSUSPEND
 	select ARCH_HAS_SG_CHAIN
+	select CPU_NO_EFFICIENT_FFS
 
 config SPARC32
 	def_bool !64BIT
@@ -79,6 +80,7 @@ config SPARC64
 	select NO_BOOTMEM
 	select HAVE_ARCH_AUDITSYSCALL
 	select ARCH_SUPPORTS_ATOMIC_RMW
+	select HAVE_NMI
 
 config ARCH_DEFCONFIG
 	string
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sparc/kernel/entry.S linux-libre-4.7-gnu/arch/sparc/kernel/entry.S
--- linux-libre-4.6-gnu/arch/sparc/kernel/entry.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sparc/kernel/entry.S	2016-07-24 15:23:50.000000000 -0400
@@ -1225,20 +1225,18 @@ breakpoint_trap:
 	RESTORE_ALL
 
 #ifdef CONFIG_KGDB
-	.align	4
-	.globl	kgdb_trap_low
-	.type	kgdb_trap_low,#function
-kgdb_trap_low:
+	ENTRY(kgdb_trap_low)
 	rd	%wim,%l3
 	SAVE_ALL
 	wr 	%l0, PSR_ET, %psr
 	WRITE_PAUSE
 
+	mov	%l7, %o0		! trap_level
 	call	kgdb_trap
-	 add	%sp, STACKFRAME_SZ, %o0
+	 add	%sp, STACKFRAME_SZ, %o1	! struct pt_regs *regs
 
 	RESTORE_ALL
-	.size	kgdb_trap_low,.-kgdb_trap_low
+	ENDPROC(kgdb_trap_low)
 #endif
 
 	.align	4
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sparc/kernel/kernel.h linux-libre-4.7-gnu/arch/sparc/kernel/kernel.h
--- linux-libre-4.6-gnu/arch/sparc/kernel/kernel.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sparc/kernel/kernel.h	2016-07-24 15:23:50.000000000 -0400
@@ -127,6 +127,7 @@ extern unsigned int t_nmi[];
 extern unsigned int linux_trap_ipi15_sun4d[];
 extern unsigned int linux_trap_ipi15_sun4m[];
 
+extern struct tt_entry trapbase;
 extern struct tt_entry trapbase_cpu1;
 extern struct tt_entry trapbase_cpu2;
 extern struct tt_entry trapbase_cpu3;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sparc/kernel/kgdb_32.c linux-libre-4.7-gnu/arch/sparc/kernel/kgdb_32.c
--- linux-libre-4.6-gnu/arch/sparc/kernel/kgdb_32.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sparc/kernel/kgdb_32.c	2016-07-24 15:23:50.000000000 -0400
@@ -12,7 +12,8 @@
 #include <asm/irq.h>
 #include <asm/cacheflush.h>
 
-extern unsigned long trapbase;
+#include "kernel.h"
+#include "entry.h"
 
 void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
 {
@@ -133,21 +134,19 @@ int kgdb_arch_handle_exception(int e_vec
 	return -1;
 }
 
-extern void do_hw_interrupt(struct pt_regs *regs, unsigned long type);
-
-asmlinkage void kgdb_trap(struct pt_regs *regs)
+asmlinkage void kgdb_trap(unsigned long trap_level, struct pt_regs *regs)
 {
 	unsigned long flags;
 
 	if (user_mode(regs)) {
-		do_hw_interrupt(regs, 0xfd);
+		do_hw_interrupt(regs, trap_level);
 		return;
 	}
 
 	flushw_all();
 
 	local_irq_save(flags);
-	kgdb_handle_exception(0x172, SIGTRAP, 0, regs);
+	kgdb_handle_exception(trap_level, SIGTRAP, 0, regs);
 	local_irq_restore(flags);
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sparc/kernel/Makefile linux-libre-4.7-gnu/arch/sparc/kernel/Makefile
--- linux-libre-4.6-gnu/arch/sparc/kernel/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sparc/kernel/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -21,6 +21,7 @@ CFLAGS_REMOVE_perf_event.o := -pg
 CFLAGS_REMOVE_pcr.o := -pg
 endif
 
+obj-$(CONFIG_SPARC64)   += urtt_fill.o
 obj-$(CONFIG_SPARC32)   += entry.o wof.o wuf.o
 obj-$(CONFIG_SPARC32)   += etrap_32.o
 obj-$(CONFIG_SPARC32)   += rtrap_32.o
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sparc/kernel/perf_event.c linux-libre-4.7-gnu/arch/sparc/kernel/perf_event.c
--- linux-libre-4.6-gnu/arch/sparc/kernel/perf_event.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sparc/kernel/perf_event.c	2016-07-24 15:23:50.000000000 -0400
@@ -1711,7 +1711,7 @@ static int __init init_hw_perf_events(vo
 }
 pure_initcall(init_hw_perf_events);
 
-void perf_callchain_kernel(struct perf_callchain_entry *entry,
+void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
 			   struct pt_regs *regs)
 {
 	unsigned long ksp, fp;
@@ -1756,7 +1756,7 @@ void perf_callchain_kernel(struct perf_c
 			}
 		}
 #endif
-	} while (entry->nr < PERF_MAX_STACK_DEPTH);
+	} while (entry->nr < entry->max_stack);
 }
 
 static inline int
@@ -1769,7 +1769,7 @@ valid_user_frame(const void __user *fp,
 	return (__range_not_ok(fp, size, TASK_SIZE) == 0);
 }
 
-static void perf_callchain_user_64(struct perf_callchain_entry *entry,
+static void perf_callchain_user_64(struct perf_callchain_entry_ctx *entry,
 				   struct pt_regs *regs)
 {
 	unsigned long ufp;
@@ -1790,10 +1790,10 @@ static void perf_callchain_user_64(struc
 		pc = sf.callers_pc;
 		ufp = (unsigned long)sf.fp + STACK_BIAS;
 		perf_callchain_store(entry, pc);
-	} while (entry->nr < PERF_MAX_STACK_DEPTH);
+	} while (entry->nr < entry->max_stack);
 }
 
-static void perf_callchain_user_32(struct perf_callchain_entry *entry,
+static void perf_callchain_user_32(struct perf_callchain_entry_ctx *entry,
 				   struct pt_regs *regs)
 {
 	unsigned long ufp;
@@ -1822,11 +1822,11 @@ static void perf_callchain_user_32(struc
 			ufp = (unsigned long)sf.fp;
 		}
 		perf_callchain_store(entry, pc);
-	} while (entry->nr < PERF_MAX_STACK_DEPTH);
+	} while (entry->nr < entry->max_stack);
 }
 
 void
-perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
+perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs)
 {
 	u64 saved_fault_address = current_thread_info()->fault_address;
 	u8 saved_fault_code = get_thread_fault_code();
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sparc/kernel/process_32.c linux-libre-4.7-gnu/arch/sparc/kernel/process_32.c
--- linux-libre-4.6-gnu/arch/sparc/kernel/process_32.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sparc/kernel/process_32.c	2016-07-24 15:23:50.000000000 -0400
@@ -184,21 +184,21 @@ unsigned long thread_saved_pc(struct tas
 /*
  * Free current thread data structures etc..
  */
-void exit_thread(void)
+void exit_thread(struct task_struct *tsk)
 {
 #ifndef CONFIG_SMP
-	if(last_task_used_math == current) {
+	if (last_task_used_math == tsk) {
 #else
-	if (test_thread_flag(TIF_USEDFPU)) {
+	if (test_ti_thread_flag(task_thread_info(tsk), TIF_USEDFPU)) {
 #endif
 		/* Keep process from leaving FPU in a bogon state. */
 		put_psr(get_psr() | PSR_EF);
-		fpsave(&current->thread.float_regs[0], &current->thread.fsr,
-		       &current->thread.fpqueue[0], &current->thread.fpqdepth);
+		fpsave(&tsk->thread.float_regs[0], &tsk->thread.fsr,
+		       &tsk->thread.fpqueue[0], &tsk->thread.fpqdepth);
 #ifndef CONFIG_SMP
 		last_task_used_math = NULL;
 #else
-		clear_thread_flag(TIF_USEDFPU);
+		clear_ti_thread_flag(task_thread_info(tsk), TIF_USEDFPU);
 #endif
 	}
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sparc/kernel/process_64.c linux-libre-4.7-gnu/arch/sparc/kernel/process_64.c
--- linux-libre-4.6-gnu/arch/sparc/kernel/process_64.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sparc/kernel/process_64.c	2016-07-24 15:23:50.000000000 -0400
@@ -417,9 +417,9 @@ unsigned long thread_saved_pc(struct tas
 }
 
 /* Free current thread data structures etc.. */
-void exit_thread(void)
+void exit_thread(struct task_struct *tsk)
 {
-	struct thread_info *t = current_thread_info();
+	struct thread_info *t = task_thread_info(tsk);
 
 	if (t->utraps) {
 		if (t->utraps[0] < 2)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sparc/kernel/rtrap_64.S linux-libre-4.7-gnu/arch/sparc/kernel/rtrap_64.S
--- linux-libre-4.6-gnu/arch/sparc/kernel/rtrap_64.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sparc/kernel/rtrap_64.S	2016-07-24 15:23:50.000000000 -0400
@@ -14,10 +14,6 @@
 #include <asm/visasm.h>
 #include <asm/processor.h>
 
-#define		RTRAP_PSTATE		(PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV|PSTATE_IE)
-#define		RTRAP_PSTATE_IRQOFF	(PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV)
-#define		RTRAP_PSTATE_AG_IRQOFF	(PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV|PSTATE_AG)
-
 #ifdef CONFIG_CONTEXT_TRACKING
 # define SCHEDULE_USER schedule_user
 #else
@@ -242,52 +238,17 @@ rt_continue:	ldx			[%sp + PTREGS_OFF + P
 		 wrpr			%g1, %cwp
 		ba,a,pt			%xcc, user_rtt_fill_64bit
 
-user_rtt_fill_fixup:
-		rdpr	%cwp, %g1
-		add	%g1, 1, %g1
-		wrpr	%g1, 0x0, %cwp
-
-		rdpr	%wstate, %g2
-		sll	%g2, 3, %g2
-		wrpr	%g2, 0x0, %wstate
-
-		/* We know %canrestore and %otherwin are both zero.  */
-
-		sethi	%hi(sparc64_kern_pri_context), %g2
-		ldx	[%g2 + %lo(sparc64_kern_pri_context)], %g2
-		mov	PRIMARY_CONTEXT, %g1
-
-661:		stxa	%g2, [%g1] ASI_DMMU
-		.section .sun4v_1insn_patch, "ax"
-		.word	661b
-		stxa	%g2, [%g1] ASI_MMU
-		.previous
-
-		sethi	%hi(KERNBASE), %g1
-		flush	%g1
-
-		or	%g4, FAULT_CODE_WINFIXUP, %g4
-		stb	%g4, [%g6 + TI_FAULT_CODE]
-		stx	%g5, [%g6 + TI_FAULT_ADDR]
-
-		mov	%g6, %l1
-		wrpr	%g0, 0x0, %tl
-
-661:		nop
-		.section		.sun4v_1insn_patch, "ax"
-		.word			661b
-		SET_GL(0)
-		.previous
+user_rtt_fill_fixup_dax:
+		ba,pt	%xcc, user_rtt_fill_fixup_common
+		 mov	1, %g3
 
-		wrpr	%g0, RTRAP_PSTATE, %pstate
+user_rtt_fill_fixup_mna:
+		ba,pt	%xcc, user_rtt_fill_fixup_common
+		 mov	2, %g3
 
-		mov	%l1, %g6
-		ldx	[%g6 + TI_TASK], %g4
-		LOAD_PER_CPU_BASE(%g5, %g6, %g1, %g2, %g3)
-		call	do_sparc64_fault
-		 add	%sp, PTREGS_OFF, %o0
-		ba,pt	%xcc, rtrap
-		 nop
+user_rtt_fill_fixup:
+		ba,pt	%xcc, user_rtt_fill_fixup_common
+		 clr	%g3
 
 user_rtt_pre_restore:
 		add			%g1, 1, %g1
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sparc/kernel/setup_32.c linux-libre-4.7-gnu/arch/sparc/kernel/setup_32.c
--- linux-libre-4.6-gnu/arch/sparc/kernel/setup_32.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sparc/kernel/setup_32.c	2016-07-24 15:23:50.000000000 -0400
@@ -68,8 +68,6 @@ struct screen_info screen_info = {
  * prints out pretty messages and returns.
  */
 
-extern unsigned long trapbase;
-
 /* Pretty sick eh? */
 static void prom_sync_me(void)
 {
@@ -300,7 +298,7 @@ void __init setup_arch(char **cmdline_p)
 	int i;
 	unsigned long highest_paddr;
 
-	sparc_ttable = (struct tt_entry *) &trapbase;
+	sparc_ttable = &trapbase;
 
 	/* Initialize PROM console and command line. */
 	*cmdline_p = prom_getbootargs();
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sparc/kernel/signal_32.c linux-libre-4.7-gnu/arch/sparc/kernel/signal_32.c
--- linux-libre-4.6-gnu/arch/sparc/kernel/signal_32.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sparc/kernel/signal_32.c	2016-07-24 15:23:50.000000000 -0400
@@ -60,10 +60,22 @@ struct rt_signal_frame {
 #define SF_ALIGNEDSZ  (((sizeof(struct signal_frame) + 7) & (~7)))
 #define RT_ALIGNEDSZ  (((sizeof(struct rt_signal_frame) + 7) & (~7)))
 
+/* Checks if the fp is valid.  We always build signal frames which are
+ * 16-byte aligned, therefore we can always enforce that the restore
+ * frame has that property as well.
+ */
+static inline bool invalid_frame_pointer(void __user *fp, int fplen)
+{
+	if ((((unsigned long) fp) & 15) || !__access_ok((unsigned long)fp, fplen))
+		return true;
+
+	return false;
+}
+
 asmlinkage void do_sigreturn(struct pt_regs *regs)
 {
+	unsigned long up_psr, pc, npc, ufp;
 	struct signal_frame __user *sf;
-	unsigned long up_psr, pc, npc;
 	sigset_t set;
 	__siginfo_fpu_t __user *fpu_save;
 	__siginfo_rwin_t __user *rwin_save;
@@ -77,10 +89,13 @@ asmlinkage void do_sigreturn(struct pt_r
 	sf = (struct signal_frame __user *) regs->u_regs[UREG_FP];
 
 	/* 1. Make sure we are not getting garbage from the user */
-	if (!access_ok(VERIFY_READ, sf, sizeof(*sf)))
+	if (!invalid_frame_pointer(sf, sizeof(*sf)))
 		goto segv_and_exit;
 
-	if (((unsigned long) sf) & 3)
+	if (get_user(ufp, &sf->info.si_regs.u_regs[UREG_FP]))
+		goto segv_and_exit;
+
+	if (ufp & 0x7)
 		goto segv_and_exit;
 
 	err = __get_user(pc,  &sf->info.si_regs.pc);
@@ -127,7 +142,7 @@ segv_and_exit:
 asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
 {
 	struct rt_signal_frame __user *sf;
-	unsigned int psr, pc, npc;
+	unsigned int psr, pc, npc, ufp;
 	__siginfo_fpu_t __user *fpu_save;
 	__siginfo_rwin_t __user *rwin_save;
 	sigset_t set;
@@ -135,8 +150,13 @@ asmlinkage void do_rt_sigreturn(struct p
 
 	synchronize_user_stack();
 	sf = (struct rt_signal_frame __user *) regs->u_regs[UREG_FP];
-	if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) ||
-	    (((unsigned long) sf) & 0x03))
+	if (!invalid_frame_pointer(sf, sizeof(*sf)))
+		goto segv;
+
+	if (get_user(ufp, &sf->regs.u_regs[UREG_FP]))
+		goto segv;
+
+	if (ufp & 0x7)
 		goto segv;
 
 	err = __get_user(pc, &sf->regs.pc);
@@ -178,15 +198,6 @@ segv:
 	force_sig(SIGSEGV, current);
 }
 
-/* Checks if the fp is valid */
-static inline int invalid_frame_pointer(void __user *fp, int fplen)
-{
-	if ((((unsigned long) fp) & 7) || !__access_ok((unsigned long)fp, fplen))
-		return 1;
-
-	return 0;
-}
-
 static inline void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, unsigned long framesize)
 {
 	unsigned long sp = regs->u_regs[UREG_FP];
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sparc/kernel/signal32.c linux-libre-4.7-gnu/arch/sparc/kernel/signal32.c
--- linux-libre-4.6-gnu/arch/sparc/kernel/signal32.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sparc/kernel/signal32.c	2016-07-24 15:23:50.000000000 -0400
@@ -138,12 +138,24 @@ int copy_siginfo_from_user32(siginfo_t *
 	return 0;
 }
 
+/* Checks if the fp is valid.  We always build signal frames which are
+ * 16-byte aligned, therefore we can always enforce that the restore
+ * frame has that property as well.
+ */
+static bool invalid_frame_pointer(void __user *fp, int fplen)
+{
+	if ((((unsigned long) fp) & 15) ||
+	    ((unsigned long)fp) > 0x100000000ULL - fplen)
+		return true;
+	return false;
+}
+
 void do_sigreturn32(struct pt_regs *regs)
 {
 	struct signal_frame32 __user *sf;
 	compat_uptr_t fpu_save;
 	compat_uptr_t rwin_save;
-	unsigned int psr;
+	unsigned int psr, ufp;
 	unsigned int pc, npc;
 	sigset_t set;
 	compat_sigset_t seta;
@@ -158,11 +170,16 @@ void do_sigreturn32(struct pt_regs *regs
 	sf = (struct signal_frame32 __user *) regs->u_regs[UREG_FP];
 
 	/* 1. Make sure we are not getting garbage from the user */
-	if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) ||
-	    (((unsigned long) sf) & 3))
+	if (invalid_frame_pointer(sf, sizeof(*sf)))
 		goto segv;
 
-	if (get_user(pc, &sf->info.si_regs.pc) ||
+	if (get_user(ufp, &sf->info.si_regs.u_regs[UREG_FP]))
+		goto segv;
+
+	if (ufp & 0x7)
+		goto segv;
+
+	if (__get_user(pc, &sf->info.si_regs.pc) ||
 	    __get_user(npc, &sf->info.si_regs.npc))
 		goto segv;
 
@@ -227,7 +244,7 @@ segv:
 asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
 {
 	struct rt_signal_frame32 __user *sf;
-	unsigned int psr, pc, npc;
+	unsigned int psr, pc, npc, ufp;
 	compat_uptr_t fpu_save;
 	compat_uptr_t rwin_save;
 	sigset_t set;
@@ -242,11 +259,16 @@ asmlinkage void do_rt_sigreturn32(struct
 	sf = (struct rt_signal_frame32 __user *) regs->u_regs[UREG_FP];
 
 	/* 1. Make sure we are not getting garbage from the user */
-	if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) ||
-	    (((unsigned long) sf) & 3))
+	if (invalid_frame_pointer(sf, sizeof(*sf)))
 		goto segv;
 
-	if (get_user(pc, &sf->regs.pc) || 
+	if (get_user(ufp, &sf->regs.u_regs[UREG_FP]))
+		goto segv;
+
+	if (ufp & 0x7)
+		goto segv;
+
+	if (__get_user(pc, &sf->regs.pc) || 
 	    __get_user(npc, &sf->regs.npc))
 		goto segv;
 
@@ -307,14 +329,6 @@ segv:
 	force_sig(SIGSEGV, current);
 }
 
-/* Checks if the fp is valid */
-static int invalid_frame_pointer(void __user *fp, int fplen)
-{
-	if ((((unsigned long) fp) & 7) || ((unsigned long)fp) > 0x100000000ULL - fplen)
-		return 1;
-	return 0;
-}
-
 static void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, unsigned long framesize)
 {
 	unsigned long sp;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sparc/kernel/signal_64.c linux-libre-4.7-gnu/arch/sparc/kernel/signal_64.c
--- linux-libre-4.6-gnu/arch/sparc/kernel/signal_64.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sparc/kernel/signal_64.c	2016-07-24 15:23:50.000000000 -0400
@@ -234,6 +234,17 @@ do_sigsegv:
 	goto out;
 }
 
+/* Checks if the fp is valid.  We always build rt signal frames which
+ * are 16-byte aligned, therefore we can always enforce that the
+ * restore frame has that property as well.
+ */
+static bool invalid_frame_pointer(void __user *fp)
+{
+	if (((unsigned long) fp) & 15)
+		return true;
+	return false;
+}
+
 struct rt_signal_frame {
 	struct sparc_stackf	ss;
 	siginfo_t		info;
@@ -246,8 +257,8 @@ struct rt_signal_frame {
 
 void do_rt_sigreturn(struct pt_regs *regs)
 {
+	unsigned long tpc, tnpc, tstate, ufp;
 	struct rt_signal_frame __user *sf;
-	unsigned long tpc, tnpc, tstate;
 	__siginfo_fpu_t __user *fpu_save;
 	__siginfo_rwin_t __user *rwin_save;
 	sigset_t set;
@@ -261,10 +272,16 @@ void do_rt_sigreturn(struct pt_regs *reg
 		(regs->u_regs [UREG_FP] + STACK_BIAS);
 
 	/* 1. Make sure we are not getting garbage from the user */
-	if (((unsigned long) sf) & 3)
+	if (invalid_frame_pointer(sf))
 		goto segv;
 
-	err = get_user(tpc, &sf->regs.tpc);
+	if (get_user(ufp, &sf->regs.u_regs[UREG_FP]))
+		goto segv;
+
+	if ((ufp + STACK_BIAS) & 0x7)
+		goto segv;
+
+	err = __get_user(tpc, &sf->regs.tpc);
 	err |= __get_user(tnpc, &sf->regs.tnpc);
 	if (test_thread_flag(TIF_32BIT)) {
 		tpc &= 0xffffffff;
@@ -308,14 +325,6 @@ segv:
 	force_sig(SIGSEGV, current);
 }
 
-/* Checks if the fp is valid */
-static int invalid_frame_pointer(void __user *fp)
-{
-	if (((unsigned long) fp) & 15)
-		return 1;
-	return 0;
-}
-
 static inline void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, unsigned long framesize)
 {
 	unsigned long sp = regs->u_regs[UREG_FP] + STACK_BIAS;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sparc/kernel/sigutil_32.c linux-libre-4.7-gnu/arch/sparc/kernel/sigutil_32.c
--- linux-libre-4.6-gnu/arch/sparc/kernel/sigutil_32.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sparc/kernel/sigutil_32.c	2016-07-24 15:23:50.000000000 -0400
@@ -48,6 +48,10 @@ int save_fpu_state(struct pt_regs *regs,
 int restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
 {
 	int err;
+
+	if (((unsigned long) fpu) & 3)
+		return -EFAULT;
+
 #ifdef CONFIG_SMP
 	if (test_tsk_thread_flag(current, TIF_USEDFPU))
 		regs->psr &= ~PSR_EF;
@@ -97,7 +101,10 @@ int restore_rwin_state(__siginfo_rwin_t
 	struct thread_info *t = current_thread_info();
 	int i, wsaved, err;
 
-	__get_user(wsaved, &rp->wsaved);
+	if (((unsigned long) rp) & 3)
+		return -EFAULT;
+
+	get_user(wsaved, &rp->wsaved);
 	if (wsaved > NSWINS)
 		return -EFAULT;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sparc/kernel/sigutil_64.c linux-libre-4.7-gnu/arch/sparc/kernel/sigutil_64.c
--- linux-libre-4.6-gnu/arch/sparc/kernel/sigutil_64.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sparc/kernel/sigutil_64.c	2016-07-24 15:23:50.000000000 -0400
@@ -37,7 +37,10 @@ int restore_fpu_state(struct pt_regs *re
 	unsigned long fprs;
 	int err;
 
-	err = __get_user(fprs, &fpu->si_fprs);
+	if (((unsigned long) fpu) & 7)
+		return -EFAULT;
+
+	err = get_user(fprs, &fpu->si_fprs);
 	fprs_write(0);
 	regs->tstate &= ~TSTATE_PEF;
 	if (fprs & FPRS_DL)
@@ -72,7 +75,10 @@ int restore_rwin_state(__siginfo_rwin_t
 	struct thread_info *t = current_thread_info();
 	int i, wsaved, err;
 
-	__get_user(wsaved, &rp->wsaved);
+	if (((unsigned long) rp) & 7)
+		return -EFAULT;
+
+	get_user(wsaved, &rp->wsaved);
 	if (wsaved > NSWINS)
 		return -EFAULT;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sparc/kernel/urtt_fill.S linux-libre-4.7-gnu/arch/sparc/kernel/urtt_fill.S
--- linux-libre-4.6-gnu/arch/sparc/kernel/urtt_fill.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/sparc/kernel/urtt_fill.S	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,98 @@
+#include <asm/thread_info.h>
+#include <asm/trap_block.h>
+#include <asm/spitfire.h>
+#include <asm/ptrace.h>
+#include <asm/head.h>
+
+		.text
+		.align	8
+		.globl	user_rtt_fill_fixup_common
+user_rtt_fill_fixup_common:
+		rdpr	%cwp, %g1
+		add	%g1, 1, %g1
+		wrpr	%g1, 0x0, %cwp
+
+		rdpr	%wstate, %g2
+		sll	%g2, 3, %g2
+		wrpr	%g2, 0x0, %wstate
+
+		/* We know %canrestore and %otherwin are both zero.  */
+
+		sethi	%hi(sparc64_kern_pri_context), %g2
+		ldx	[%g2 + %lo(sparc64_kern_pri_context)], %g2
+		mov	PRIMARY_CONTEXT, %g1
+
+661:		stxa	%g2, [%g1] ASI_DMMU
+		.section .sun4v_1insn_patch, "ax"
+		.word	661b
+		stxa	%g2, [%g1] ASI_MMU
+		.previous
+
+		sethi	%hi(KERNBASE), %g1
+		flush	%g1
+
+		mov	%g4, %l4
+		mov	%g5, %l5
+		brnz,pn	%g3, 1f
+		 mov	%g3, %l3
+
+		or	%g4, FAULT_CODE_WINFIXUP, %g4
+		stb	%g4, [%g6 + TI_FAULT_CODE]
+		stx	%g5, [%g6 + TI_FAULT_ADDR]
+1:
+		mov	%g6, %l1
+		wrpr	%g0, 0x0, %tl
+
+661:		nop
+		.section		.sun4v_1insn_patch, "ax"
+		.word			661b
+		SET_GL(0)
+		.previous
+
+		wrpr	%g0, RTRAP_PSTATE, %pstate
+
+		mov	%l1, %g6
+		ldx	[%g6 + TI_TASK], %g4
+		LOAD_PER_CPU_BASE(%g5, %g6, %g1, %g2, %g3)
+
+		brnz,pn	%l3, 1f
+		 nop
+
+		call	do_sparc64_fault
+		 add	%sp, PTREGS_OFF, %o0
+		ba,pt	%xcc, rtrap
+		 nop
+
+1:		cmp	%g3, 2
+		bne,pn	%xcc, 2f
+		 nop
+
+		sethi	%hi(tlb_type), %g1
+		lduw	[%g1 + %lo(tlb_type)], %g1
+		cmp	%g1, 3
+		bne,pt	%icc, 1f
+		 add	%sp, PTREGS_OFF, %o0
+		mov	%l4, %o2
+		call	sun4v_do_mna
+		 mov	%l5, %o1
+		ba,a,pt	%xcc, rtrap
+1:		mov	%l4, %o1
+		mov	%l5, %o2
+		call	mem_address_unaligned
+		 nop
+		ba,a,pt	%xcc, rtrap
+
+2:		sethi	%hi(tlb_type), %g1
+		mov	%l4, %o1
+		lduw	[%g1 + %lo(tlb_type)], %g1
+		mov	%l5, %o2
+		cmp	%g1, 3
+		bne,pt	%icc, 1f
+		 add	%sp, PTREGS_OFF, %o0
+		call	sun4v_data_access_exception
+		 nop
+		ba,a,pt	%xcc, rtrap
+
+1:		call	spitfire_data_access_exception
+		 nop
+		ba,a,pt	%xcc, rtrap
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sparc/mm/hugetlbpage.c linux-libre-4.7-gnu/arch/sparc/mm/hugetlbpage.c
--- linux-libre-4.6-gnu/arch/sparc/mm/hugetlbpage.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sparc/mm/hugetlbpage.c	2016-07-24 15:23:50.000000000 -0400
@@ -176,17 +176,31 @@ void set_huge_pte_at(struct mm_struct *m
 		     pte_t *ptep, pte_t entry)
 {
 	int i;
+	pte_t orig[2];
+	unsigned long nptes;
 
 	if (!pte_present(*ptep) && pte_present(entry))
 		mm->context.huge_pte_count++;
 
 	addr &= HPAGE_MASK;
-	for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
-		set_pte_at(mm, addr, ptep, entry);
+
+	nptes = 1 << HUGETLB_PAGE_ORDER;
+	orig[0] = *ptep;
+	orig[1] = *(ptep + nptes / 2);
+	for (i = 0; i < nptes; i++) {
+		*ptep = entry;
 		ptep++;
 		addr += PAGE_SIZE;
 		pte_val(entry) += PAGE_SIZE;
 	}
+
+	/* Issue TLB flush at REAL_HPAGE_SIZE boundaries */
+	addr -= REAL_HPAGE_SIZE;
+	ptep -= nptes / 2;
+	maybe_tlb_batch_add(mm, addr, ptep, orig[1], 0);
+	addr -= REAL_HPAGE_SIZE;
+	ptep -= nptes / 2;
+	maybe_tlb_batch_add(mm, addr, ptep, orig[0], 0);
 }
 
 pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
@@ -194,19 +208,28 @@ pte_t huge_ptep_get_and_clear(struct mm_
 {
 	pte_t entry;
 	int i;
+	unsigned long nptes;
 
 	entry = *ptep;
 	if (pte_present(entry))
 		mm->context.huge_pte_count--;
 
 	addr &= HPAGE_MASK;
-
-	for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
-		pte_clear(mm, addr, ptep);
+	nptes = 1 << HUGETLB_PAGE_ORDER;
+	for (i = 0; i < nptes; i++) {
+		*ptep = __pte(0UL);
 		addr += PAGE_SIZE;
 		ptep++;
 	}
 
+	/* Issue TLB flush at REAL_HPAGE_SIZE boundaries */
+	addr -= REAL_HPAGE_SIZE;
+	ptep -= nptes / 2;
+	maybe_tlb_batch_add(mm, addr, ptep, entry, 0);
+	addr -= REAL_HPAGE_SIZE;
+	ptep -= nptes / 2;
+	maybe_tlb_batch_add(mm, addr, ptep, entry, 0);
+
 	return entry;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sparc/mm/init_64.c linux-libre-4.7-gnu/arch/sparc/mm/init_64.c
--- linux-libre-4.6-gnu/arch/sparc/mm/init_64.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sparc/mm/init_64.c	2016-07-24 15:23:50.000000000 -0400
@@ -324,18 +324,6 @@ static void __update_mmu_tsb_insert(stru
 	tsb_insert(tsb, tag, tte);
 }
 
-#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
-static inline bool is_hugetlb_pte(pte_t pte)
-{
-	if ((tlb_type == hypervisor &&
-	     (pte_val(pte) & _PAGE_SZALL_4V) == _PAGE_SZHUGE_4V) ||
-	    (tlb_type != hypervisor &&
-	     (pte_val(pte) & _PAGE_SZALL_4U) == _PAGE_SZHUGE_4U))
-		return true;
-	return false;
-}
-#endif
-
 void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
 {
 	struct mm_struct *mm;
@@ -2716,8 +2704,7 @@ void __flush_tlb_all(void)
 pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
 			    unsigned long address)
 {
-	struct page *page = alloc_page(GFP_KERNEL | __GFP_NOTRACK |
-				       __GFP_REPEAT | __GFP_ZERO);
+	struct page *page = alloc_page(GFP_KERNEL | __GFP_NOTRACK | __GFP_ZERO);
 	pte_t *pte = NULL;
 
 	if (page)
@@ -2729,8 +2716,7 @@ pte_t *pte_alloc_one_kernel(struct mm_st
 pgtable_t pte_alloc_one(struct mm_struct *mm,
 			unsigned long address)
 {
-	struct page *page = alloc_page(GFP_KERNEL | __GFP_NOTRACK |
-				       __GFP_REPEAT | __GFP_ZERO);
+	struct page *page = alloc_page(GFP_KERNEL | __GFP_NOTRACK | __GFP_ZERO);
 	if (!page)
 		return NULL;
 	if (!pgtable_page_ctor(page)) {
@@ -2836,9 +2822,10 @@ void hugetlb_setup(struct pt_regs *regs)
 	 * the Data-TLB for huge pages.
 	 */
 	if (tlb_type == cheetah_plus) {
+		bool need_context_reload = false;
 		unsigned long ctx;
 
-		spin_lock(&ctx_alloc_lock);
+		spin_lock_irq(&ctx_alloc_lock);
 		ctx = mm->context.sparc64_ctx_val;
 		ctx &= ~CTX_PGSZ_MASK;
 		ctx |= CTX_PGSZ_BASE << CTX_PGSZ0_SHIFT;
@@ -2857,9 +2844,12 @@ void hugetlb_setup(struct pt_regs *regs)
 			 * also executing in this address space.
 			 */
 			mm->context.sparc64_ctx_val = ctx;
-			on_each_cpu(context_reload, mm, 0);
+			need_context_reload = true;
 		}
-		spin_unlock(&ctx_alloc_lock);
+		spin_unlock_irq(&ctx_alloc_lock);
+
+		if (need_context_reload)
+			on_each_cpu(context_reload, mm, 0);
 	}
 }
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sparc/mm/io-unit.c linux-libre-4.7-gnu/arch/sparc/mm/io-unit.c
--- linux-libre-4.6-gnu/arch/sparc/mm/io-unit.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sparc/mm/io-unit.c	2016-07-24 15:23:50.000000000 -0400
@@ -133,7 +133,7 @@ nexti:	scan = find_next_zero_bit(iounit-
 	vaddr = IOUNIT_DMA_BASE + (scan << PAGE_SHIFT) + (vaddr & ~PAGE_MASK);
 	for (k = 0; k < npages; k++, iopte = __iopte(iopte_val(iopte) + 0x100), scan++) {
 		set_bit(scan, iounit->bmap);
-		sbus_writel(iopte, &iounit->page_table[scan]);
+		sbus_writel(iopte_val(iopte), &iounit->page_table[scan]);
 	}
 	IOD(("%08lx\n", vaddr));
 	return vaddr;
@@ -228,7 +228,7 @@ static int iounit_map_dma_area(struct de
 			i = ((addr - IOUNIT_DMA_BASE) >> PAGE_SHIFT);
 
 			iopte = iounit->page_table + i;
-			sbus_writel(MKIOPTE(__pa(page)), iopte);
+			sbus_writel(iopte_val(MKIOPTE(__pa(page))), iopte);
 		}
 		addr += PAGE_SIZE;
 		va += PAGE_SIZE;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sparc/mm/srmmu.c linux-libre-4.7-gnu/arch/sparc/mm/srmmu.c
--- linux-libre-4.6-gnu/arch/sparc/mm/srmmu.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sparc/mm/srmmu.c	2016-07-24 15:23:50.000000000 -0400
@@ -107,17 +107,22 @@ static inline int srmmu_pmd_none(pmd_t p
 
 /* XXX should we hyper_flush_whole_icache here - Anton */
 static inline void srmmu_ctxd_set(ctxd_t *ctxp, pgd_t *pgdp)
-{ set_pte((pte_t *)ctxp, (SRMMU_ET_PTD | (__nocache_pa((unsigned long) pgdp) >> 4))); }
+{
+	pte_t pte;
+
+	pte = __pte((SRMMU_ET_PTD | (__nocache_pa(pgdp) >> 4)));
+	set_pte((pte_t *)ctxp, pte);
+}
 
 void pmd_set(pmd_t *pmdp, pte_t *ptep)
 {
 	unsigned long ptp;	/* Physical address, shifted right by 4 */
 	int i;
 
-	ptp = __nocache_pa((unsigned long) ptep) >> 4;
+	ptp = __nocache_pa(ptep) >> 4;
 	for (i = 0; i < PTRS_PER_PTE/SRMMU_REAL_PTRS_PER_PTE; i++) {
-		set_pte((pte_t *)&pmdp->pmdv[i], SRMMU_ET_PTD | ptp);
-		ptp += (SRMMU_REAL_PTRS_PER_PTE*sizeof(pte_t) >> 4);
+		set_pte((pte_t *)&pmdp->pmdv[i], __pte(SRMMU_ET_PTD | ptp));
+		ptp += (SRMMU_REAL_PTRS_PER_PTE * sizeof(pte_t) >> 4);
 	}
 }
 
@@ -128,8 +133,8 @@ void pmd_populate(struct mm_struct *mm,
 
 	ptp = page_to_pfn(ptep) << (PAGE_SHIFT-4);	/* watch for overflow */
 	for (i = 0; i < PTRS_PER_PTE/SRMMU_REAL_PTRS_PER_PTE; i++) {
-		set_pte((pte_t *)&pmdp->pmdv[i], SRMMU_ET_PTD | ptp);
-		ptp += (SRMMU_REAL_PTRS_PER_PTE*sizeof(pte_t) >> 4);
+		set_pte((pte_t *)&pmdp->pmdv[i], __pte(SRMMU_ET_PTD | ptp));
+		ptp += (SRMMU_REAL_PTRS_PER_PTE * sizeof(pte_t) >> 4);
 	}
 }
 
@@ -911,7 +916,7 @@ void __init srmmu_paging_init(void)
 
 	/* ctx table has to be physically aligned to its size */
 	srmmu_context_table = __srmmu_get_nocache(num_contexts * sizeof(ctxd_t), num_contexts * sizeof(ctxd_t));
-	srmmu_ctx_table_phys = (ctxd_t *)__nocache_pa((unsigned long)srmmu_context_table);
+	srmmu_ctx_table_phys = (ctxd_t *)__nocache_pa(srmmu_context_table);
 
 	for (i = 0; i < num_contexts; i++)
 		srmmu_ctxd_set((ctxd_t *)__nocache_fix(&srmmu_context_table[i]), srmmu_swapper_pg_dir);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sparc/mm/tlb.c linux-libre-4.7-gnu/arch/sparc/mm/tlb.c
--- linux-libre-4.6-gnu/arch/sparc/mm/tlb.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sparc/mm/tlb.c	2016-07-24 15:23:50.000000000 -0400
@@ -67,7 +67,7 @@ void arch_leave_lazy_mmu_mode(void)
 }
 
 static void tlb_batch_add_one(struct mm_struct *mm, unsigned long vaddr,
-			      bool exec)
+			      bool exec, bool huge)
 {
 	struct tlb_batch *tb = &get_cpu_var(tlb_batch);
 	unsigned long nr;
@@ -84,13 +84,21 @@ static void tlb_batch_add_one(struct mm_
 	}
 
 	if (!tb->active) {
-		flush_tsb_user_page(mm, vaddr);
+		flush_tsb_user_page(mm, vaddr, huge);
 		global_flush_tlb_page(mm, vaddr);
 		goto out;
 	}
 
-	if (nr == 0)
+	if (nr == 0) {
 		tb->mm = mm;
+		tb->huge = huge;
+	}
+
+	if (tb->huge != huge) {
+		flush_tlb_pending();
+		tb->huge = huge;
+		nr = 0;
+	}
 
 	tb->vaddrs[nr] = vaddr;
 	tb->tlb_nr = ++nr;
@@ -104,6 +112,8 @@ out:
 void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr,
 		   pte_t *ptep, pte_t orig, int fullmm)
 {
+	bool huge = is_hugetlb_pte(orig);
+
 	if (tlb_type != hypervisor &&
 	    pte_dirty(orig)) {
 		unsigned long paddr, pfn = pte_pfn(orig);
@@ -129,7 +139,7 @@ void tlb_batch_add(struct mm_struct *mm,
 
 no_cache_flush:
 	if (!fullmm)
-		tlb_batch_add_one(mm, vaddr, pte_exec(orig));
+		tlb_batch_add_one(mm, vaddr, pte_exec(orig), huge);
 }
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
@@ -145,7 +155,7 @@ static void tlb_batch_pmd_scan(struct mm
 		if (pte_val(*pte) & _PAGE_VALID) {
 			bool exec = pte_exec(*pte);
 
-			tlb_batch_add_one(mm, vaddr, exec);
+			tlb_batch_add_one(mm, vaddr, exec, false);
 		}
 		pte++;
 		vaddr += PAGE_SIZE;
@@ -185,8 +195,9 @@ void set_pmd_at(struct mm_struct *mm, un
 			pte_t orig_pte = __pte(pmd_val(orig));
 			bool exec = pte_exec(orig_pte);
 
-			tlb_batch_add_one(mm, addr, exec);
-			tlb_batch_add_one(mm, addr + REAL_HPAGE_SIZE, exec);
+			tlb_batch_add_one(mm, addr, exec, true);
+			tlb_batch_add_one(mm, addr + REAL_HPAGE_SIZE, exec,
+					true);
 		} else {
 			tlb_batch_pmd_scan(mm, addr, orig);
 		}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/sparc/mm/tsb.c linux-libre-4.7-gnu/arch/sparc/mm/tsb.c
--- linux-libre-4.6-gnu/arch/sparc/mm/tsb.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/sparc/mm/tsb.c	2016-07-24 15:23:50.000000000 -0400
@@ -76,14 +76,15 @@ void flush_tsb_user(struct tlb_batch *tb
 
 	spin_lock_irqsave(&mm->context.lock, flags);
 
-	base = (unsigned long) mm->context.tsb_block[MM_TSB_BASE].tsb;
-	nentries = mm->context.tsb_block[MM_TSB_BASE].tsb_nentries;
-	if (tlb_type == cheetah_plus || tlb_type == hypervisor)
-		base = __pa(base);
-	__flush_tsb_one(tb, PAGE_SHIFT, base, nentries);
-
+	if (!tb->huge) {
+		base = (unsigned long) mm->context.tsb_block[MM_TSB_BASE].tsb;
+		nentries = mm->context.tsb_block[MM_TSB_BASE].tsb_nentries;
+		if (tlb_type == cheetah_plus || tlb_type == hypervisor)
+			base = __pa(base);
+		__flush_tsb_one(tb, PAGE_SHIFT, base, nentries);
+	}
 #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
-	if (mm->context.tsb_block[MM_TSB_HUGE].tsb) {
+	if (tb->huge && mm->context.tsb_block[MM_TSB_HUGE].tsb) {
 		base = (unsigned long) mm->context.tsb_block[MM_TSB_HUGE].tsb;
 		nentries = mm->context.tsb_block[MM_TSB_HUGE].tsb_nentries;
 		if (tlb_type == cheetah_plus || tlb_type == hypervisor)
@@ -94,20 +95,21 @@ void flush_tsb_user(struct tlb_batch *tb
 	spin_unlock_irqrestore(&mm->context.lock, flags);
 }
 
-void flush_tsb_user_page(struct mm_struct *mm, unsigned long vaddr)
+void flush_tsb_user_page(struct mm_struct *mm, unsigned long vaddr, bool huge)
 {
 	unsigned long nentries, base, flags;
 
 	spin_lock_irqsave(&mm->context.lock, flags);
 
-	base = (unsigned long) mm->context.tsb_block[MM_TSB_BASE].tsb;
-	nentries = mm->context.tsb_block[MM_TSB_BASE].tsb_nentries;
-	if (tlb_type == cheetah_plus || tlb_type == hypervisor)
-		base = __pa(base);
-	__flush_tsb_one_entry(base, vaddr, PAGE_SHIFT, nentries);
-
+	if (!huge) {
+		base = (unsigned long) mm->context.tsb_block[MM_TSB_BASE].tsb;
+		nentries = mm->context.tsb_block[MM_TSB_BASE].tsb_nentries;
+		if (tlb_type == cheetah_plus || tlb_type == hypervisor)
+			base = __pa(base);
+		__flush_tsb_one_entry(base, vaddr, PAGE_SHIFT, nentries);
+	}
 #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
-	if (mm->context.tsb_block[MM_TSB_HUGE].tsb) {
+	if (huge && mm->context.tsb_block[MM_TSB_HUGE].tsb) {
 		base = (unsigned long) mm->context.tsb_block[MM_TSB_HUGE].tsb;
 		nentries = mm->context.tsb_block[MM_TSB_HUGE].tsb_nentries;
 		if (tlb_type == cheetah_plus || tlb_type == hypervisor)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/tile/configs/tilegx_defconfig linux-libre-4.7-gnu/arch/tile/configs/tilegx_defconfig
--- linux-libre-4.6-gnu/arch/tile/configs/tilegx_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/tile/configs/tilegx_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -16,7 +16,6 @@ CONFIG_CGROUP_DEBUG=y
 CONFIG_CGROUP_DEVICE=y
 CONFIG_CPUSETS=y
 CONFIG_CGROUP_CPUACCT=y
-CONFIG_RESOURCE_COUNTERS=y
 CONFIG_CGROUP_SCHED=y
 CONFIG_RT_GROUP_SCHED=y
 CONFIG_BLK_CGROUP=y
@@ -89,7 +88,6 @@ CONFIG_TCP_CONG_YEAH=m
 CONFIG_TCP_CONG_ILLINOIS=m
 CONFIG_TCP_MD5SIG=y
 CONFIG_IPV6=y
-CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_IPV6_ROUTE_INFO=y
 CONFIG_IPV6_OPTIMISTIC_DAD=y
@@ -221,8 +219,7 @@ CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_TUN=y
 CONFIG_VETH=m
 CONFIG_NET_DSA_MV88E6060=y
-CONFIG_NET_DSA_MV88E6131=y
-CONFIG_NET_DSA_MV88E6123=y
+CONFIG_NET_DSA_MV88E6XXX=y
 CONFIG_SKY2=y
 CONFIG_PTP_1588_CLOCK_TILEGX=y
 # CONFIG_WLAN is not set
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/tile/configs/tilepro_defconfig linux-libre-4.7-gnu/arch/tile/configs/tilepro_defconfig
--- linux-libre-4.6-gnu/arch/tile/configs/tilepro_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/tile/configs/tilepro_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -15,7 +15,6 @@ CONFIG_CGROUP_DEBUG=y
 CONFIG_CGROUP_DEVICE=y
 CONFIG_CPUSETS=y
 CONFIG_CGROUP_CPUACCT=y
-CONFIG_RESOURCE_COUNTERS=y
 CONFIG_CGROUP_SCHED=y
 CONFIG_RT_GROUP_SCHED=y
 CONFIG_BLK_CGROUP=y
@@ -85,7 +84,6 @@ CONFIG_TCP_CONG_YEAH=m
 CONFIG_TCP_CONG_ILLINOIS=m
 CONFIG_TCP_MD5SIG=y
 CONFIG_IPV6=y
-CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_IPV6_ROUTE_INFO=y
 CONFIG_IPV6_OPTIMISTIC_DAD=y
@@ -340,8 +338,7 @@ CONFIG_NETCONSOLE_DYNAMIC=y
 CONFIG_TUN=y
 CONFIG_VETH=m
 CONFIG_NET_DSA_MV88E6060=y
-CONFIG_NET_DSA_MV88E6131=y
-CONFIG_NET_DSA_MV88E6123=y
+CONFIG_NET_DSA_MV88E6XXX=y
 # CONFIG_NET_VENDOR_3COM is not set
 CONFIG_E1000E=y
 # CONFIG_WLAN is not set
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/tile/gxio/mpipe.c linux-libre-4.7-gnu/arch/tile/gxio/mpipe.c
--- linux-libre-4.6-gnu/arch/tile/gxio/mpipe.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/tile/gxio/mpipe.c	2016-07-24 15:23:50.000000000 -0400
@@ -122,7 +122,7 @@ size_t gxio_mpipe_calc_buffer_stack_byte
 {
 	const int BUFFERS_PER_LINE = 12;
 
-	/* Count the number of cachlines. */
+	/* Count the number of cachelines. */
 	unsigned long lines =
 		(buffers + BUFFERS_PER_LINE - 1) / BUFFERS_PER_LINE;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/tile/include/asm/atomic_64.h linux-libre-4.7-gnu/arch/tile/include/asm/atomic_64.h
--- linux-libre-4.6-gnu/arch/tile/include/asm/atomic_64.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/tile/include/asm/atomic_64.h	2016-07-24 15:23:50.000000000 -0400
@@ -37,12 +37,25 @@ static inline void atomic_add(int i, ato
 	__insn_fetchadd4((void *)&v->counter, i);
 }
 
+/*
+ * Note a subtlety of the locking here.  We are required to provide a
+ * full memory barrier before and after the operation.  However, we
+ * only provide an explicit mb before the operation.  After the
+ * operation, we use barrier() to get a full mb for free, because:
+ *
+ * (1) The barrier directive to the compiler prohibits any instructions
+ * being statically hoisted before the barrier;
+ * (2) the microarchitecture will not issue any further instructions
+ * until the fetchadd result is available for the "+ i" add instruction;
+ * (3) the smb_mb before the fetchadd ensures that no other memory
+ * operations are in flight at this point.
+ */
 static inline int atomic_add_return(int i, atomic_t *v)
 {
 	int val;
 	smp_mb();  /* barrier for proper semantics */
 	val = __insn_fetchadd4((void *)&v->counter, i) + i;
-	barrier();  /* the "+ i" above will wait on memory */
+	barrier();  /* equivalent to smp_mb(); see block comment above */
 	return val;
 }
 
@@ -95,7 +108,7 @@ static inline long atomic64_add_return(l
 	int val;
 	smp_mb();  /* barrier for proper semantics */
 	val = __insn_fetchadd((void *)&v->counter, i) + i;
-	barrier();  /* the "+ i" above will wait on memory */
+	barrier();  /* equivalent to smp_mb; see atomic_add_return() */
 	return val;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/tile/include/asm/pgtable.h linux-libre-4.7-gnu/arch/tile/include/asm/pgtable.h
--- linux-libre-4.6-gnu/arch/tile/include/asm/pgtable.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/tile/include/asm/pgtable.h	2016-07-24 15:23:50.000000000 -0400
@@ -487,7 +487,6 @@ static inline pmd_t pmd_modify(pmd_t pmd
 }
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
-#define has_transparent_hugepage() 1
 #define pmd_trans_huge pmd_huge_page
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/tile/include/asm/thread_info.h linux-libre-4.7-gnu/arch/tile/include/asm/thread_info.h
--- linux-libre-4.6-gnu/arch/tile/include/asm/thread_info.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/tile/include/asm/thread_info.h	2016-07-24 15:23:50.000000000 -0400
@@ -78,7 +78,7 @@ struct thread_info {
 
 #ifndef __ASSEMBLY__
 
-void arch_release_thread_info(struct thread_info *info);
+void arch_release_thread_stack(unsigned long *stack);
 
 /* How to get the thread information struct from C. */
 register unsigned long stack_pointer __asm__("sp");
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/tile/include/uapi/asm/unistd.h linux-libre-4.7-gnu/arch/tile/include/uapi/asm/unistd.h
--- linux-libre-4.6-gnu/arch/tile/include/uapi/asm/unistd.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/tile/include/uapi/asm/unistd.h	2016-07-24 15:23:50.000000000 -0400
@@ -12,6 +12,7 @@
  *   more details.
  */
 
+#define __ARCH_WANT_RENAMEAT
 #if !defined(__LP64__) || defined(__SYSCALL_COMPAT)
 /* Use the flavor of this syscall that matches the 32-bit API better. */
 #define __ARCH_WANT_SYNC_FILE_RANGE2
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/tile/Kconfig linux-libre-4.7-gnu/arch/tile/Kconfig
--- linux-libre-4.6-gnu/arch/tile/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/tile/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -3,47 +3,38 @@
 
 config TILE
 	def_bool y
-	select HAVE_PERF_EVENTS
-	select USE_PMC if PERF_EVENTS
-	select HAVE_DMA_API_DEBUG
-	select HAVE_KVM if !TILEGX
-	select GENERIC_FIND_FIRST_BIT
-	select SYSCTL_EXCEPTION_TRACE
-	select CC_OPTIMIZE_FOR_SIZE
-	select HAVE_DEBUG_KMEMLEAK
-	select GENERIC_IRQ_PROBE
-	select GENERIC_PENDING_IRQ if SMP
-	select GENERIC_IRQ_SHOW
-	select HAVE_DEBUG_BUGVERBOSE
-	select VIRT_TO_BUS
-	select SYS_HYPERVISOR
+	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
 	select ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS
 	select ARCH_HAS_DEVMEM_IS_ALLOWED
 	select ARCH_HAVE_NMI_SAFE_CMPXCHG
-	select GENERIC_CLOCKEVENTS
-	select MODULES_USE_ELF_RELA
-	select HAVE_ARCH_TRACEHOOK
-	select HAVE_SYSCALL_TRACEPOINTS
-	select USER_STACKTRACE_SUPPORT
-	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
-	select HAVE_DEBUG_STACKOVERFLOW
 	select ARCH_WANT_FRAME_POINTERS
-	select HAVE_CONTEXT_TRACKING
+	select CC_OPTIMIZE_FOR_SIZE
 	select EDAC_SUPPORT
+	select GENERIC_CLOCKEVENTS
+	select GENERIC_FIND_FIRST_BIT
+	select GENERIC_IRQ_PROBE
+	select GENERIC_IRQ_SHOW
+	select GENERIC_PENDING_IRQ if SMP
 	select GENERIC_STRNCPY_FROM_USER
 	select GENERIC_STRNLEN_USER
 	select HAVE_ARCH_SECCOMP_FILTER
-
-# FIXME: investigate whether we need/want these options.
-#	select HAVE_IOREMAP_PROT
-#	select HAVE_OPTPROBES
-#	select HAVE_REGS_AND_STACK_ACCESS_API
-#	select HAVE_HW_BREAKPOINT
-#	select PERF_EVENTS
-#	select HAVE_USER_RETURN_NOTIFIER
-#	config NO_BOOTMEM
-#	config ARCH_SUPPORTS_DEBUG_PAGEALLOC
-#	config HUGETLB_PAGE_SIZE_VARIABLE
+	select HAVE_ARCH_TRACEHOOK
+	select HAVE_CONTEXT_TRACKING
+	select HAVE_DEBUG_BUGVERBOSE
+	select HAVE_DEBUG_KMEMLEAK
+	select HAVE_DEBUG_STACKOVERFLOW
+	select HAVE_DMA_API_DEBUG
+	select HAVE_EXIT_THREAD
+	select HAVE_KVM if !TILEGX
+	select HAVE_NMI if USE_PMC
+	select HAVE_PERF_EVENTS
+	select HAVE_SYSCALL_TRACEPOINTS
+	select MODULES_USE_ELF_RELA
+	select SYSCTL_EXCEPTION_TRACE
+	select SYS_HYPERVISOR
+	select USER_STACKTRACE_SUPPORT
+	select USE_PMC if PERF_EVENTS
+	select VIRT_TO_BUS
 
 config MMU
 	def_bool y
@@ -130,17 +121,17 @@ config HVC_TILE
 # 64-bit TILE-Gx toolchain, so force CONFIG_TILEGX on.
 config TILEGX
 	def_bool ARCH != "tilepro"
-	select SPARSE_IRQ
+	select ARCH_SUPPORTS_ATOMIC_RMW
 	select GENERIC_IRQ_LEGACY_ALLOC_HWIRQ
-	select HAVE_FUNCTION_TRACER
-	select HAVE_FUNCTION_GRAPH_TRACER
+	select HAVE_ARCH_JUMP_LABEL
+	select HAVE_ARCH_KGDB
 	select HAVE_DYNAMIC_FTRACE
 	select HAVE_FTRACE_MCOUNT_RECORD
+	select HAVE_FUNCTION_GRAPH_TRACER
+	select HAVE_FUNCTION_TRACER
 	select HAVE_KPROBES
 	select HAVE_KRETPROBES
-	select HAVE_ARCH_KGDB
-	select ARCH_SUPPORTS_ATOMIC_RMW
-	select HAVE_ARCH_JUMP_LABEL
+	select SPARSE_IRQ
 
 config TILEPRO
 	def_bool !TILEGX
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/tile/kernel/pci_gx.c linux-libre-4.7-gnu/arch/tile/kernel/pci_gx.c
--- linux-libre-4.6-gnu/arch/tile/kernel/pci_gx.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/tile/kernel/pci_gx.c	2016-07-24 15:23:50.000000000 -0400
@@ -40,7 +40,7 @@
 #include <arch/sim.h>
 
 /*
- * This file containes the routines to search for PCI buses,
+ * This file contains the routines to search for PCI buses,
  * enumerate the buses, and configure any attached devices.
  */
 
@@ -434,7 +434,7 @@ int __init tile_pci_init(void)
 
 	/*
 	 * Now determine which PCIe ports are configured to operate in RC
-	 * mode. There is a differece in the port configuration capability
+	 * mode. There is a difference in the port configuration capability
 	 * between the Gx36 and Gx72 devices.
 	 *
 	 * The Gx36 has configuration capability for each of the 3 PCIe
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/tile/kernel/perf_event.c linux-libre-4.7-gnu/arch/tile/kernel/perf_event.c
--- linux-libre-4.6-gnu/arch/tile/kernel/perf_event.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/tile/kernel/perf_event.c	2016-07-24 15:23:50.000000000 -0400
@@ -941,7 +941,7 @@ arch_initcall(init_hw_perf_events);
 /*
  * Tile specific backtracing code for perf_events.
  */
-static inline void perf_callchain(struct perf_callchain_entry *entry,
+static inline void perf_callchain(struct perf_callchain_entry_ctx *entry,
 		    struct pt_regs *regs)
 {
 	struct KBacktraceIterator kbt;
@@ -992,13 +992,13 @@ static inline void perf_callchain(struct
 	}
 }
 
-void perf_callchain_user(struct perf_callchain_entry *entry,
+void perf_callchain_user(struct perf_callchain_entry_ctx *entry,
 		    struct pt_regs *regs)
 {
 	perf_callchain(entry, regs);
 }
 
-void perf_callchain_kernel(struct perf_callchain_entry *entry,
+void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
 		      struct pt_regs *regs)
 {
 	perf_callchain(entry, regs);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/tile/kernel/process.c linux-libre-4.7-gnu/arch/tile/kernel/process.c
--- linux-libre-4.6-gnu/arch/tile/kernel/process.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/tile/kernel/process.c	2016-07-24 15:23:50.000000000 -0400
@@ -73,8 +73,9 @@ void arch_cpu_idle(void)
 /*
  * Release a thread_info structure
  */
-void arch_release_thread_info(struct thread_info *info)
+void arch_release_thread_stack(unsigned long *stack)
 {
+	struct thread_info *info = (void *)stack;
 	struct single_step_state *step_state = info->step_state;
 
 	if (step_state) {
@@ -541,7 +542,7 @@ void flush_thread(void)
 /*
  * Free current thread data structures etc..
  */
-void exit_thread(void)
+void exit_thread(struct task_struct *tsk)
 {
 #ifdef CONFIG_HARDWALL
 	/*
@@ -550,7 +551,7 @@ void exit_thread(void)
 	 * the last reference to a hardwall fd, it would already have
 	 * been released and deactivated at this point.)
 	 */
-	hardwall_deactivate_all(current);
+	hardwall_deactivate_all(tsk);
 #endif
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/tile/kernel/setup.c linux-libre-4.7-gnu/arch/tile/kernel/setup.c
--- linux-libre-4.6-gnu/arch/tile/kernel/setup.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/tile/kernel/setup.c	2016-07-24 15:23:50.000000000 -0400
@@ -962,9 +962,7 @@ static void __init setup_numa_mapping(vo
 		cpumask_set_cpu(best_cpu, &node_2_cpu_mask[node]);
 		cpu_2_node[best_cpu] = node;
 		cpumask_clear_cpu(best_cpu, &unbound_cpus);
-		node = next_node(node, default_nodes);
-		if (node == MAX_NUMNODES)
-			node = first_node(default_nodes);
+		node = next_node_in(node, default_nodes);
 	}
 
 	/* Print out node assignments and set defaults for disabled cpus */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/tile/kernel/unaligned.c linux-libre-4.7-gnu/arch/tile/kernel/unaligned.c
--- linux-libre-4.6-gnu/arch/tile/kernel/unaligned.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/tile/kernel/unaligned.c	2016-07-24 15:23:50.000000000 -0400
@@ -188,7 +188,7 @@ static void find_regs(tilegx_bundle_bits
 	 * Parse fault bundle, find potential used registers and mark
 	 * corresponding bits in reg_map and alias_map. These 2 bit maps
 	 * are used to find the scratch registers and determine if there
-	 * is register alais.
+	 * is register alias.
 	 */
 	if (bundle & TILEGX_BUNDLE_MODE_MASK) {  /* Y Mode Bundle. */
 
@@ -1529,7 +1529,7 @@ void do_unaligned(struct pt_regs *regs,
 	}
 
 
-	/* Read the bundle casued the exception! */
+	/* Read the bundle caused the exception! */
 	pc = (tilegx_bundle_bits __user *)(regs->pc);
 	if (get_user(bundle, pc) != 0) {
 		/* Probably never be here since pc is valid user address.*/
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/tile/mm/hugetlbpage.c linux-libre-4.7-gnu/arch/tile/mm/hugetlbpage.c
--- linux-libre-4.6-gnu/arch/tile/mm/hugetlbpage.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/tile/mm/hugetlbpage.c	2016-07-24 15:23:50.000000000 -0400
@@ -308,11 +308,16 @@ static bool saw_hugepagesz;
 
 static __init int setup_hugepagesz(char *opt)
 {
+	int rc;
+
 	if (!saw_hugepagesz) {
 		saw_hugepagesz = true;
 		memset(huge_shift, 0, sizeof(huge_shift));
 	}
-	return __setup_hugepagesz(memparse(opt, NULL));
+	rc = __setup_hugepagesz(memparse(opt, NULL));
+	if (rc)
+		hugetlb_bad_size();
+	return rc;
 }
 __setup("hugepagesz=", setup_hugepagesz);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/tile/mm/init.c linux-libre-4.7-gnu/arch/tile/mm/init.c
--- linux-libre-4.6-gnu/arch/tile/mm/init.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/tile/mm/init.c	2016-07-24 15:23:50.000000000 -0400
@@ -679,7 +679,7 @@ static void __init init_free_pfn_range(u
 			 * Hacky direct set to avoid unnecessary
 			 * lock take/release for EVERY page here.
 			 */
-			p->_count.counter = 0;
+			p->_refcount.counter = 0;
 			p->_mapcount.counter = -1;
 		}
 		init_page_count(page);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/tile/mm/pgtable.c linux-libre-4.7-gnu/arch/tile/mm/pgtable.c
--- linux-libre-4.6-gnu/arch/tile/mm/pgtable.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/tile/mm/pgtable.c	2016-07-24 15:23:50.000000000 -0400
@@ -231,7 +231,7 @@ void pgd_free(struct mm_struct *mm, pgd_
 struct page *pgtable_alloc_one(struct mm_struct *mm, unsigned long address,
 			       int order)
 {
-	gfp_t flags = GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO;
+	gfp_t flags = GFP_KERNEL|__GFP_ZERO;
 	struct page *p;
 	int i;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/um/configs/i386_defconfig linux-libre-4.7-gnu/arch/um/configs/i386_defconfig
--- linux-libre-4.6-gnu/arch/um/configs/i386_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/um/configs/i386_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -17,7 +17,6 @@ CONFIG_CGROUP_FREEZER=y
 CONFIG_CGROUP_DEVICE=y
 CONFIG_CPUSETS=y
 CONFIG_CGROUP_CPUACCT=y
-CONFIG_RESOURCE_COUNTERS=y
 CONFIG_CGROUP_SCHED=y
 CONFIG_BLK_CGROUP=y
 # CONFIG_PID_NS is not set
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/um/configs/x86_64_defconfig linux-libre-4.7-gnu/arch/um/configs/x86_64_defconfig
--- linux-libre-4.6-gnu/arch/um/configs/x86_64_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/um/configs/x86_64_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -15,7 +15,6 @@ CONFIG_CGROUP_FREEZER=y
 CONFIG_CGROUP_DEVICE=y
 CONFIG_CPUSETS=y
 CONFIG_CGROUP_CPUACCT=y
-CONFIG_RESOURCE_COUNTERS=y
 CONFIG_CGROUP_SCHED=y
 CONFIG_BLK_CGROUP=y
 # CONFIG_PID_NS is not set
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/um/drivers/net_kern.c linux-libre-4.7-gnu/arch/um/drivers/net_kern.c
--- linux-libre-4.6-gnu/arch/um/drivers/net_kern.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/um/drivers/net_kern.c	2016-07-24 15:23:50.000000000 -0400
@@ -223,7 +223,7 @@ static int uml_net_start_xmit(struct sk_
 	if (len == skb->len) {
 		dev->stats.tx_packets++;
 		dev->stats.tx_bytes += skb->len;
-		dev->trans_start = jiffies;
+		netif_trans_update(dev);
 		netif_start_queue(dev);
 
 		/* this is normally done in the interrupt when tx finishes */
@@ -252,7 +252,7 @@ static void uml_net_set_multicast_list(s
 
 static void uml_net_tx_timeout(struct net_device *dev)
 {
-	dev->trans_start = jiffies;
+	netif_trans_update(dev);
 	netif_wake_queue(dev);
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/um/drivers/ubd_kern.c linux-libre-4.7-gnu/arch/um/drivers/ubd_kern.c
--- linux-libre-4.6-gnu/arch/um/drivers/ubd_kern.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/um/drivers/ubd_kern.c	2016-07-24 15:23:50.000000000 -0400
@@ -862,7 +862,7 @@ static int ubd_add(int n, char **error_o
 		goto out;
 	}
 	ubd_dev->queue->queuedata = ubd_dev;
-	blk_queue_flush(ubd_dev->queue, REQ_FLUSH);
+	blk_queue_write_cache(ubd_dev->queue, true, false);
 
 	blk_queue_max_segments(ubd_dev->queue, MAX_SG);
 	err = ubd_disk_register(UBD_MAJOR, ubd_dev->size, n, &ubd_gendisk[n]);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/um/include/shared/registers.h linux-libre-4.7-gnu/arch/um/include/shared/registers.h
--- linux-libre-4.6-gnu/arch/um/include/shared/registers.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/um/include/shared/registers.h	2016-07-24 15:23:50.000000000 -0400
@@ -9,6 +9,8 @@
 #include <sysdep/ptrace.h>
 #include <sysdep/archsetjmp.h>
 
+extern int save_i387_registers(int pid, unsigned long *fp_regs);
+extern int restore_i387_registers(int pid, unsigned long *fp_regs);
 extern int save_fp_registers(int pid, unsigned long *fp_regs);
 extern int restore_fp_registers(int pid, unsigned long *fp_regs);
 extern int save_fpx_registers(int pid, unsigned long *fp_regs);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/um/kernel/mem.c linux-libre-4.7-gnu/arch/um/kernel/mem.c
--- linux-libre-4.6-gnu/arch/um/kernel/mem.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/um/kernel/mem.c	2016-07-24 15:23:50.000000000 -0400
@@ -204,7 +204,7 @@ pte_t *pte_alloc_one_kernel(struct mm_st
 {
 	pte_t *pte;
 
-	pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
+	pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_ZERO);
 	return pte;
 }
 
@@ -212,7 +212,7 @@ pgtable_t pte_alloc_one(struct mm_struct
 {
 	struct page *pte;
 
-	pte = alloc_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
+	pte = alloc_page(GFP_KERNEL|__GFP_ZERO);
 	if (!pte)
 		return NULL;
 	if (!pgtable_page_ctor(pte)) {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/um/kernel/process.c linux-libre-4.7-gnu/arch/um/kernel/process.c
--- linux-libre-4.6-gnu/arch/um/kernel/process.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/um/kernel/process.c	2016-07-24 15:23:50.000000000 -0400
@@ -103,10 +103,6 @@ void interrupt_end(void)
 		tracehook_notify_resume(regs);
 }
 
-void exit_thread(void)
-{
-}
-
 int get_current_pid(void)
 {
 	return task_pid_nr(current);
@@ -402,6 +398,6 @@ int elf_core_copy_fpregs(struct task_str
 {
 	int cpu = current_thread_info()->cpu;
 
-	return save_fp_registers(userspace_pid[cpu], (unsigned long *) fpu);
+	return save_i387_registers(userspace_pid[cpu], (unsigned long *) fpu);
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/um/os-Linux/signal.c linux-libre-4.7-gnu/arch/um/os-Linux/signal.c
--- linux-libre-4.6-gnu/arch/um/os-Linux/signal.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/um/os-Linux/signal.c	2016-07-24 15:23:50.000000000 -0400
@@ -29,23 +29,29 @@ void (*sig_info[NSIG])(int, struct sigin
 
 static void sig_handler_common(int sig, struct siginfo *si, mcontext_t *mc)
 {
-	struct uml_pt_regs r;
+	struct uml_pt_regs *r;
 	int save_errno = errno;
 
-	r.is_user = 0;
+	r = malloc(sizeof(struct uml_pt_regs));
+	if (!r)
+		panic("out of memory");
+
+	r->is_user = 0;
 	if (sig == SIGSEGV) {
 		/* For segfaults, we want the data from the sigcontext. */
-		get_regs_from_mc(&r, mc);
-		GET_FAULTINFO_FROM_MC(r.faultinfo, mc);
+		get_regs_from_mc(r, mc);
+		GET_FAULTINFO_FROM_MC(r->faultinfo, mc);
 	}
 
 	/* enable signals if sig isn't IRQ signal */
 	if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGALRM))
 		unblock_signals();
 
-	(*sig_info[sig])(sig, si, &r);
+	(*sig_info[sig])(sig, si, r);
 
 	errno = save_errno;
+
+	free(r);
 }
 
 /*
@@ -83,11 +89,17 @@ void sig_handler(int sig, struct siginfo
 
 static void timer_real_alarm_handler(mcontext_t *mc)
 {
-	struct uml_pt_regs regs;
+	struct uml_pt_regs *regs;
+
+	regs = malloc(sizeof(struct uml_pt_regs));
+	if (!regs)
+		panic("out of memory");
 
 	if (mc != NULL)
-		get_regs_from_mc(&regs, mc);
-	timer_handler(SIGALRM, NULL, &regs);
+		get_regs_from_mc(regs, mc);
+	timer_handler(SIGALRM, NULL, regs);
+
+	free(regs);
 }
 
 void timer_alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/unicore32/boot/compressed/Makefile linux-libre-4.7-gnu/arch/unicore32/boot/compressed/Makefile
--- linux-libre-4.6-gnu/arch/unicore32/boot/compressed/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/unicore32/boot/compressed/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -54,7 +54,6 @@ LDFLAGS_vmlinux += -T
 $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/head.o $(obj)/piggy.o \
 		$(obj)/misc.o FORCE
 	$(call if_changed,ld)
-	@:
 
 # We now have a PIC decompressor implementation.  Decompressors running
 # from RAM should not define ZTEXTADDR.  Decompressors running directly
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/unicore32/boot/Makefile linux-libre-4.7-gnu/arch/unicore32/boot/Makefile
--- linux-libre-4.6-gnu/arch/unicore32/boot/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/unicore32/boot/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -31,7 +31,7 @@ $(obj)/uImage: $(obj)/zImage FORCE
 	$(call if_changed,uimage)
 	@echo '  Image $@ is ready'
 
-PHONY += initrd FORCE
+PHONY += initrd
 initrd:
 	@test "$(INITRD)" != "" || \
 	(echo You must specify INITRD; exit -1)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/unicore32/include/asm/pgalloc.h linux-libre-4.7-gnu/arch/unicore32/include/asm/pgalloc.h
--- linux-libre-4.6-gnu/arch/unicore32/include/asm/pgalloc.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/unicore32/include/asm/pgalloc.h	2016-07-24 15:23:50.000000000 -0400
@@ -28,7 +28,7 @@ extern void free_pgd_slow(struct mm_stru
 #define pgd_alloc(mm)			get_pgd_slow(mm)
 #define pgd_free(mm, pgd)		free_pgd_slow(mm, pgd)
 
-#define PGALLOC_GFP	(GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO)
+#define PGALLOC_GFP	(GFP_KERNEL | __GFP_NOTRACK | __GFP_ZERO)
 
 /*
  * Allocate one PTE table.
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/unicore32/include/uapi/asm/unistd.h linux-libre-4.7-gnu/arch/unicore32/include/uapi/asm/unistd.h
--- linux-libre-4.6-gnu/arch/unicore32/include/uapi/asm/unistd.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/unicore32/include/uapi/asm/unistd.h	2016-07-24 15:23:50.000000000 -0400
@@ -10,6 +10,8 @@
  * published by the Free Software Foundation.
  */
 
+#define __ARCH_WANT_RENAMEAT
+
 /* Use the standard ABI for syscalls. */
 #include <asm-generic/unistd.h>
 #define __ARCH_WANT_SYS_CLONE
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/unicore32/kernel/gpio.c linux-libre-4.7-gnu/arch/unicore32/kernel/gpio.c
--- linux-libre-4.6-gnu/arch/unicore32/kernel/gpio.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/unicore32/kernel/gpio.c	2016-07-24 15:23:50.000000000 -0400
@@ -14,6 +14,8 @@
 
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/gpio/driver.h>
+/* FIXME: needed for gpio_set_value() - convert to use descriptors or hogs */
 #include <linux/gpio.h>
 #include <mach/hardware.h>
 
@@ -118,5 +120,5 @@ void __init puv3_init_gpio(void)
  *	gpio_set_value(GPO_SET_V2, 1);
  */
 #endif
-	gpiochip_add(&puv3_gpio_chip);
+	gpiochip_add_data(&puv3_gpio_chip, NULL);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/unicore32/kernel/process.c linux-libre-4.7-gnu/arch/unicore32/kernel/process.c
--- linux-libre-4.6-gnu/arch/unicore32/kernel/process.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/unicore32/kernel/process.c	2016-07-24 15:23:50.000000000 -0400
@@ -201,13 +201,6 @@ void show_regs(struct pt_regs *regs)
 	__backtrace();
 }
 
-/*
- * Free current thread data structures etc..
- */
-void exit_thread(void)
-{
-}
-
 void flush_thread(void)
 {
 	struct thread_info *thread = current_thread_info();
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/boot/compressed/aslr.c linux-libre-4.7-gnu/arch/x86/boot/compressed/aslr.c
--- linux-libre-4.6-gnu/arch/x86/boot/compressed/aslr.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/boot/compressed/aslr.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,339 +0,0 @@
-#include "misc.h"
-
-#include <asm/msr.h>
-#include <asm/archrandom.h>
-#include <asm/e820.h>
-
-#include <generated/compile.h>
-#include <linux/module.h>
-#include <linux/uts.h>
-#include <linux/utsname.h>
-#include <generated/utsrelease.h>
-
-/* Simplified build-specific string for starting entropy. */
-static const char build_str[] = UTS_RELEASE " (" LINUX_COMPILE_BY "@"
-		LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION;
-
-#define I8254_PORT_CONTROL	0x43
-#define I8254_PORT_COUNTER0	0x40
-#define I8254_CMD_READBACK	0xC0
-#define I8254_SELECT_COUNTER0	0x02
-#define I8254_STATUS_NOTREADY	0x40
-static inline u16 i8254(void)
-{
-	u16 status, timer;
-
-	do {
-		outb(I8254_PORT_CONTROL,
-		     I8254_CMD_READBACK | I8254_SELECT_COUNTER0);
-		status = inb(I8254_PORT_COUNTER0);
-		timer  = inb(I8254_PORT_COUNTER0);
-		timer |= inb(I8254_PORT_COUNTER0) << 8;
-	} while (status & I8254_STATUS_NOTREADY);
-
-	return timer;
-}
-
-static unsigned long rotate_xor(unsigned long hash, const void *area,
-				size_t size)
-{
-	size_t i;
-	unsigned long *ptr = (unsigned long *)area;
-
-	for (i = 0; i < size / sizeof(hash); i++) {
-		/* Rotate by odd number of bits and XOR. */
-		hash = (hash << ((sizeof(hash) * 8) - 7)) | (hash >> 7);
-		hash ^= ptr[i];
-	}
-
-	return hash;
-}
-
-/* Attempt to create a simple but unpredictable starting entropy. */
-static unsigned long get_random_boot(void)
-{
-	unsigned long hash = 0;
-
-	hash = rotate_xor(hash, build_str, sizeof(build_str));
-	hash = rotate_xor(hash, real_mode, sizeof(*real_mode));
-
-	return hash;
-}
-
-static unsigned long get_random_long(void)
-{
-#ifdef CONFIG_X86_64
-	const unsigned long mix_const = 0x5d6008cbf3848dd3UL;
-#else
-	const unsigned long mix_const = 0x3f39e593UL;
-#endif
-	unsigned long raw, random = get_random_boot();
-	bool use_i8254 = true;
-
-	debug_putstr("KASLR using");
-
-	if (has_cpuflag(X86_FEATURE_RDRAND)) {
-		debug_putstr(" RDRAND");
-		if (rdrand_long(&raw)) {
-			random ^= raw;
-			use_i8254 = false;
-		}
-	}
-
-	if (has_cpuflag(X86_FEATURE_TSC)) {
-		debug_putstr(" RDTSC");
-		raw = rdtsc();
-
-		random ^= raw;
-		use_i8254 = false;
-	}
-
-	if (use_i8254) {
-		debug_putstr(" i8254");
-		random ^= i8254();
-	}
-
-	/* Circular multiply for better bit diffusion */
-	asm("mul %3"
-	    : "=a" (random), "=d" (raw)
-	    : "a" (random), "rm" (mix_const));
-	random += raw;
-
-	debug_putstr("...\n");
-
-	return random;
-}
-
-struct mem_vector {
-	unsigned long start;
-	unsigned long size;
-};
-
-#define MEM_AVOID_MAX 5
-static struct mem_vector mem_avoid[MEM_AVOID_MAX];
-
-static bool mem_contains(struct mem_vector *region, struct mem_vector *item)
-{
-	/* Item at least partially before region. */
-	if (item->start < region->start)
-		return false;
-	/* Item at least partially after region. */
-	if (item->start + item->size > region->start + region->size)
-		return false;
-	return true;
-}
-
-static bool mem_overlaps(struct mem_vector *one, struct mem_vector *two)
-{
-	/* Item one is entirely before item two. */
-	if (one->start + one->size <= two->start)
-		return false;
-	/* Item one is entirely after item two. */
-	if (one->start >= two->start + two->size)
-		return false;
-	return true;
-}
-
-static void mem_avoid_init(unsigned long input, unsigned long input_size,
-			   unsigned long output, unsigned long output_size)
-{
-	u64 initrd_start, initrd_size;
-	u64 cmd_line, cmd_line_size;
-	unsigned long unsafe, unsafe_len;
-	char *ptr;
-
-	/*
-	 * Avoid the region that is unsafe to overlap during
-	 * decompression (see calculations at top of misc.c).
-	 */
-	unsafe_len = (output_size >> 12) + 32768 + 18;
-	unsafe = (unsigned long)input + input_size - unsafe_len;
-	mem_avoid[0].start = unsafe;
-	mem_avoid[0].size = unsafe_len;
-
-	/* Avoid initrd. */
-	initrd_start  = (u64)real_mode->ext_ramdisk_image << 32;
-	initrd_start |= real_mode->hdr.ramdisk_image;
-	initrd_size  = (u64)real_mode->ext_ramdisk_size << 32;
-	initrd_size |= real_mode->hdr.ramdisk_size;
-	mem_avoid[1].start = initrd_start;
-	mem_avoid[1].size = initrd_size;
-
-	/* Avoid kernel command line. */
-	cmd_line  = (u64)real_mode->ext_cmd_line_ptr << 32;
-	cmd_line |= real_mode->hdr.cmd_line_ptr;
-	/* Calculate size of cmd_line. */
-	ptr = (char *)(unsigned long)cmd_line;
-	for (cmd_line_size = 0; ptr[cmd_line_size++]; )
-		;
-	mem_avoid[2].start = cmd_line;
-	mem_avoid[2].size = cmd_line_size;
-
-	/* Avoid heap memory. */
-	mem_avoid[3].start = (unsigned long)free_mem_ptr;
-	mem_avoid[3].size = BOOT_HEAP_SIZE;
-
-	/* Avoid stack memory. */
-	mem_avoid[4].start = (unsigned long)free_mem_end_ptr;
-	mem_avoid[4].size = BOOT_STACK_SIZE;
-}
-
-/* Does this memory vector overlap a known avoided area? */
-static bool mem_avoid_overlap(struct mem_vector *img)
-{
-	int i;
-	struct setup_data *ptr;
-
-	for (i = 0; i < MEM_AVOID_MAX; i++) {
-		if (mem_overlaps(img, &mem_avoid[i]))
-			return true;
-	}
-
-	/* Avoid all entries in the setup_data linked list. */
-	ptr = (struct setup_data *)(unsigned long)real_mode->hdr.setup_data;
-	while (ptr) {
-		struct mem_vector avoid;
-
-		avoid.start = (unsigned long)ptr;
-		avoid.size = sizeof(*ptr) + ptr->len;
-
-		if (mem_overlaps(img, &avoid))
-			return true;
-
-		ptr = (struct setup_data *)(unsigned long)ptr->next;
-	}
-
-	return false;
-}
-
-static unsigned long slots[CONFIG_RANDOMIZE_BASE_MAX_OFFSET /
-			   CONFIG_PHYSICAL_ALIGN];
-static unsigned long slot_max;
-
-static void slots_append(unsigned long addr)
-{
-	/* Overflowing the slots list should be impossible. */
-	if (slot_max >= CONFIG_RANDOMIZE_BASE_MAX_OFFSET /
-			CONFIG_PHYSICAL_ALIGN)
-		return;
-
-	slots[slot_max++] = addr;
-}
-
-static unsigned long slots_fetch_random(void)
-{
-	/* Handle case of no slots stored. */
-	if (slot_max == 0)
-		return 0;
-
-	return slots[get_random_long() % slot_max];
-}
-
-static void process_e820_entry(struct e820entry *entry,
-			       unsigned long minimum,
-			       unsigned long image_size)
-{
-	struct mem_vector region, img;
-
-	/* Skip non-RAM entries. */
-	if (entry->type != E820_RAM)
-		return;
-
-	/* Ignore entries entirely above our maximum. */
-	if (entry->addr >= CONFIG_RANDOMIZE_BASE_MAX_OFFSET)
-		return;
-
-	/* Ignore entries entirely below our minimum. */
-	if (entry->addr + entry->size < minimum)
-		return;
-
-	region.start = entry->addr;
-	region.size = entry->size;
-
-	/* Potentially raise address to minimum location. */
-	if (region.start < minimum)
-		region.start = minimum;
-
-	/* Potentially raise address to meet alignment requirements. */
-	region.start = ALIGN(region.start, CONFIG_PHYSICAL_ALIGN);
-
-	/* Did we raise the address above the bounds of this e820 region? */
-	if (region.start > entry->addr + entry->size)
-		return;
-
-	/* Reduce size by any delta from the original address. */
-	region.size -= region.start - entry->addr;
-
-	/* Reduce maximum size to fit end of image within maximum limit. */
-	if (region.start + region.size > CONFIG_RANDOMIZE_BASE_MAX_OFFSET)
-		region.size = CONFIG_RANDOMIZE_BASE_MAX_OFFSET - region.start;
-
-	/* Walk each aligned slot and check for avoided areas. */
-	for (img.start = region.start, img.size = image_size ;
-	     mem_contains(&region, &img) ;
-	     img.start += CONFIG_PHYSICAL_ALIGN) {
-		if (mem_avoid_overlap(&img))
-			continue;
-		slots_append(img.start);
-	}
-}
-
-static unsigned long find_random_addr(unsigned long minimum,
-				      unsigned long size)
-{
-	int i;
-	unsigned long addr;
-
-	/* Make sure minimum is aligned. */
-	minimum = ALIGN(minimum, CONFIG_PHYSICAL_ALIGN);
-
-	/* Verify potential e820 positions, appending to slots list. */
-	for (i = 0; i < real_mode->e820_entries; i++) {
-		process_e820_entry(&real_mode->e820_map[i], minimum, size);
-	}
-
-	return slots_fetch_random();
-}
-
-unsigned char *choose_kernel_location(struct boot_params *boot_params,
-				      unsigned char *input,
-				      unsigned long input_size,
-				      unsigned char *output,
-				      unsigned long output_size)
-{
-	unsigned long choice = (unsigned long)output;
-	unsigned long random;
-
-#ifdef CONFIG_HIBERNATION
-	if (!cmdline_find_option_bool("kaslr")) {
-		debug_putstr("KASLR disabled by default...\n");
-		goto out;
-	}
-#else
-	if (cmdline_find_option_bool("nokaslr")) {
-		debug_putstr("KASLR disabled by cmdline...\n");
-		goto out;
-	}
-#endif
-
-	boot_params->hdr.loadflags |= KASLR_FLAG;
-
-	/* Record the various known unsafe memory ranges. */
-	mem_avoid_init((unsigned long)input, input_size,
-		       (unsigned long)output, output_size);
-
-	/* Walk e820 and find a random address. */
-	random = find_random_addr(choice, output_size);
-	if (!random) {
-		debug_putstr("KASLR could not find suitable E820 region...\n");
-		goto out;
-	}
-
-	/* Always enforce the minimum. */
-	if (random < choice)
-		goto out;
-
-	choice = random;
-out:
-	return (unsigned char *)choice;
-}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/boot/compressed/cmdline.c linux-libre-4.7-gnu/arch/x86/boot/compressed/cmdline.c
--- linux-libre-4.6-gnu/arch/x86/boot/compressed/cmdline.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/boot/compressed/cmdline.c	2016-07-24 15:23:50.000000000 -0400
@@ -15,9 +15,9 @@ static inline char rdfs8(addr_t addr)
 #include "../cmdline.c"
 static unsigned long get_cmd_line_ptr(void)
 {
-	unsigned long cmd_line_ptr = real_mode->hdr.cmd_line_ptr;
+	unsigned long cmd_line_ptr = boot_params->hdr.cmd_line_ptr;
 
-	cmd_line_ptr |= (u64)real_mode->ext_cmd_line_ptr << 32;
+	cmd_line_ptr |= (u64)boot_params->ext_cmd_line_ptr << 32;
 
 	return cmd_line_ptr;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/boot/compressed/eboot.c linux-libre-4.7-gnu/arch/x86/boot/compressed/eboot.c
--- linux-libre-4.6-gnu/arch/x86/boot/compressed/eboot.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/boot/compressed/eboot.c	2016-07-24 15:23:50.000000000 -0400
@@ -571,312 +571,6 @@ free_handle:
 	efi_call_early(free_pool, pci_handle);
 }
 
-static void
-setup_pixel_info(struct screen_info *si, u32 pixels_per_scan_line,
-		 struct efi_pixel_bitmask pixel_info, int pixel_format)
-{
-	if (pixel_format == PIXEL_RGB_RESERVED_8BIT_PER_COLOR) {
-		si->lfb_depth = 32;
-		si->lfb_linelength = pixels_per_scan_line * 4;
-		si->red_size = 8;
-		si->red_pos = 0;
-		si->green_size = 8;
-		si->green_pos = 8;
-		si->blue_size = 8;
-		si->blue_pos = 16;
-		si->rsvd_size = 8;
-		si->rsvd_pos = 24;
-	} else if (pixel_format == PIXEL_BGR_RESERVED_8BIT_PER_COLOR) {
-		si->lfb_depth = 32;
-		si->lfb_linelength = pixels_per_scan_line * 4;
-		si->red_size = 8;
-		si->red_pos = 16;
-		si->green_size = 8;
-		si->green_pos = 8;
-		si->blue_size = 8;
-		si->blue_pos = 0;
-		si->rsvd_size = 8;
-		si->rsvd_pos = 24;
-	} else if (pixel_format == PIXEL_BIT_MASK) {
-		find_bits(pixel_info.red_mask, &si->red_pos, &si->red_size);
-		find_bits(pixel_info.green_mask, &si->green_pos,
-			  &si->green_size);
-		find_bits(pixel_info.blue_mask, &si->blue_pos, &si->blue_size);
-		find_bits(pixel_info.reserved_mask, &si->rsvd_pos,
-			  &si->rsvd_size);
-		si->lfb_depth = si->red_size + si->green_size +
-			si->blue_size + si->rsvd_size;
-		si->lfb_linelength = (pixels_per_scan_line * si->lfb_depth) / 8;
-	} else {
-		si->lfb_depth = 4;
-		si->lfb_linelength = si->lfb_width / 2;
-		si->red_size = 0;
-		si->red_pos = 0;
-		si->green_size = 0;
-		si->green_pos = 0;
-		si->blue_size = 0;
-		si->blue_pos = 0;
-		si->rsvd_size = 0;
-		si->rsvd_pos = 0;
-	}
-}
-
-static efi_status_t
-__gop_query32(struct efi_graphics_output_protocol_32 *gop32,
-	      struct efi_graphics_output_mode_info **info,
-	      unsigned long *size, u64 *fb_base)
-{
-	struct efi_graphics_output_protocol_mode_32 *mode;
-	efi_status_t status;
-	unsigned long m;
-
-	m = gop32->mode;
-	mode = (struct efi_graphics_output_protocol_mode_32 *)m;
-
-	status = efi_early->call(gop32->query_mode, gop32,
-				 mode->mode, size, info);
-	if (status != EFI_SUCCESS)
-		return status;
-
-	*fb_base = mode->frame_buffer_base;
-	return status;
-}
-
-static efi_status_t
-setup_gop32(struct screen_info *si, efi_guid_t *proto,
-	    unsigned long size, void **gop_handle)
-{
-	struct efi_graphics_output_protocol_32 *gop32, *first_gop;
-	unsigned long nr_gops;
-	u16 width, height;
-	u32 pixels_per_scan_line;
-	u32 ext_lfb_base;
-	u64 fb_base;
-	struct efi_pixel_bitmask pixel_info;
-	int pixel_format;
-	efi_status_t status;
-	u32 *handles = (u32 *)(unsigned long)gop_handle;
-	int i;
-
-	first_gop = NULL;
-	gop32 = NULL;
-
-	nr_gops = size / sizeof(u32);
-	for (i = 0; i < nr_gops; i++) {
-		struct efi_graphics_output_mode_info *info = NULL;
-		efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
-		bool conout_found = false;
-		void *dummy = NULL;
-		u32 h = handles[i];
-		u64 current_fb_base;
-
-		status = efi_call_early(handle_protocol, h,
-					proto, (void **)&gop32);
-		if (status != EFI_SUCCESS)
-			continue;
-
-		status = efi_call_early(handle_protocol, h,
-					&conout_proto, &dummy);
-		if (status == EFI_SUCCESS)
-			conout_found = true;
-
-		status = __gop_query32(gop32, &info, &size, &current_fb_base);
-		if (status == EFI_SUCCESS && (!first_gop || conout_found)) {
-			/*
-			 * Systems that use the UEFI Console Splitter may
-			 * provide multiple GOP devices, not all of which are
-			 * backed by real hardware. The workaround is to search
-			 * for a GOP implementing the ConOut protocol, and if
-			 * one isn't found, to just fall back to the first GOP.
-			 */
-			width = info->horizontal_resolution;
-			height = info->vertical_resolution;
-			pixel_format = info->pixel_format;
-			pixel_info = info->pixel_information;
-			pixels_per_scan_line = info->pixels_per_scan_line;
-			fb_base = current_fb_base;
-
-			/*
-			 * Once we've found a GOP supporting ConOut,
-			 * don't bother looking any further.
-			 */
-			first_gop = gop32;
-			if (conout_found)
-				break;
-		}
-	}
-
-	/* Did we find any GOPs? */
-	if (!first_gop)
-		goto out;
-
-	/* EFI framebuffer */
-	si->orig_video_isVGA = VIDEO_TYPE_EFI;
-
-	si->lfb_width = width;
-	si->lfb_height = height;
-	si->lfb_base = fb_base;
-
-	ext_lfb_base = (u64)(unsigned long)fb_base >> 32;
-	if (ext_lfb_base) {
-		si->capabilities |= VIDEO_CAPABILITY_64BIT_BASE;
-		si->ext_lfb_base = ext_lfb_base;
-	}
-
-	si->pages = 1;
-
-	setup_pixel_info(si, pixels_per_scan_line, pixel_info, pixel_format);
-
-	si->lfb_size = si->lfb_linelength * si->lfb_height;
-
-	si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS;
-out:
-	return status;
-}
-
-static efi_status_t
-__gop_query64(struct efi_graphics_output_protocol_64 *gop64,
-	      struct efi_graphics_output_mode_info **info,
-	      unsigned long *size, u64 *fb_base)
-{
-	struct efi_graphics_output_protocol_mode_64 *mode;
-	efi_status_t status;
-	unsigned long m;
-
-	m = gop64->mode;
-	mode = (struct efi_graphics_output_protocol_mode_64 *)m;
-
-	status = efi_early->call(gop64->query_mode, gop64,
-				 mode->mode, size, info);
-	if (status != EFI_SUCCESS)
-		return status;
-
-	*fb_base = mode->frame_buffer_base;
-	return status;
-}
-
-static efi_status_t
-setup_gop64(struct screen_info *si, efi_guid_t *proto,
-	    unsigned long size, void **gop_handle)
-{
-	struct efi_graphics_output_protocol_64 *gop64, *first_gop;
-	unsigned long nr_gops;
-	u16 width, height;
-	u32 pixels_per_scan_line;
-	u32 ext_lfb_base;
-	u64 fb_base;
-	struct efi_pixel_bitmask pixel_info;
-	int pixel_format;
-	efi_status_t status;
-	u64 *handles = (u64 *)(unsigned long)gop_handle;
-	int i;
-
-	first_gop = NULL;
-	gop64 = NULL;
-
-	nr_gops = size / sizeof(u64);
-	for (i = 0; i < nr_gops; i++) {
-		struct efi_graphics_output_mode_info *info = NULL;
-		efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
-		bool conout_found = false;
-		void *dummy = NULL;
-		u64 h = handles[i];
-		u64 current_fb_base;
-
-		status = efi_call_early(handle_protocol, h,
-					proto, (void **)&gop64);
-		if (status != EFI_SUCCESS)
-			continue;
-
-		status = efi_call_early(handle_protocol, h,
-					&conout_proto, &dummy);
-		if (status == EFI_SUCCESS)
-			conout_found = true;
-
-		status = __gop_query64(gop64, &info, &size, &current_fb_base);
-		if (status == EFI_SUCCESS && (!first_gop || conout_found)) {
-			/*
-			 * Systems that use the UEFI Console Splitter may
-			 * provide multiple GOP devices, not all of which are
-			 * backed by real hardware. The workaround is to search
-			 * for a GOP implementing the ConOut protocol, and if
-			 * one isn't found, to just fall back to the first GOP.
-			 */
-			width = info->horizontal_resolution;
-			height = info->vertical_resolution;
-			pixel_format = info->pixel_format;
-			pixel_info = info->pixel_information;
-			pixels_per_scan_line = info->pixels_per_scan_line;
-			fb_base = current_fb_base;
-
-			/*
-			 * Once we've found a GOP supporting ConOut,
-			 * don't bother looking any further.
-			 */
-			first_gop = gop64;
-			if (conout_found)
-				break;
-		}
-	}
-
-	/* Did we find any GOPs? */
-	if (!first_gop)
-		goto out;
-
-	/* EFI framebuffer */
-	si->orig_video_isVGA = VIDEO_TYPE_EFI;
-
-	si->lfb_width = width;
-	si->lfb_height = height;
-	si->lfb_base = fb_base;
-
-	ext_lfb_base = (u64)(unsigned long)fb_base >> 32;
-	if (ext_lfb_base) {
-		si->capabilities |= VIDEO_CAPABILITY_64BIT_BASE;
-		si->ext_lfb_base = ext_lfb_base;
-	}
-
-	si->pages = 1;
-
-	setup_pixel_info(si, pixels_per_scan_line, pixel_info, pixel_format);
-
-	si->lfb_size = si->lfb_linelength * si->lfb_height;
-
-	si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS;
-out:
-	return status;
-}
-
-/*
- * See if we have Graphics Output Protocol
- */
-static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
-			      unsigned long size)
-{
-	efi_status_t status;
-	void **gop_handle = NULL;
-
-	status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
-				size, (void **)&gop_handle);
-	if (status != EFI_SUCCESS)
-		return status;
-
-	status = efi_call_early(locate_handle,
-				EFI_LOCATE_BY_PROTOCOL,
-				proto, NULL, &size, gop_handle);
-	if (status != EFI_SUCCESS)
-		goto free_handle;
-
-	if (efi_early->is64)
-		status = setup_gop64(si, proto, size, gop_handle);
-	else
-		status = setup_gop32(si, proto, size, gop_handle);
-
-free_handle:
-	efi_call_early(free_pool, gop_handle);
-	return status;
-}
-
 static efi_status_t
 setup_uga32(void **uga_handle, unsigned long size, u32 *width, u32 *height)
 {
@@ -1038,7 +732,7 @@ void setup_graphics(struct boot_params *
 				EFI_LOCATE_BY_PROTOCOL,
 				&graphics_proto, NULL, &size, gop_handle);
 	if (status == EFI_BUFFER_TOO_SMALL)
-		status = setup_gop(si, &graphics_proto, size);
+		status = efi_setup_gop(NULL, si, &graphics_proto, size);
 
 	if (status != EFI_SUCCESS) {
 		size = 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/boot/compressed/eboot.h linux-libre-4.7-gnu/arch/x86/boot/compressed/eboot.h
--- linux-libre-4.6-gnu/arch/x86/boot/compressed/eboot.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/boot/compressed/eboot.h	2016-07-24 15:23:50.000000000 -0400
@@ -11,80 +11,6 @@
 
 #define DESC_TYPE_CODE_DATA	(1 << 0)
 
-#define EFI_CONSOLE_OUT_DEVICE_GUID    \
-	EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4, 0x9a, 0x46, 0x0, 0x90, 0x27, \
-		  0x3f, 0xc1, 0x4d)
-
-#define PIXEL_RGB_RESERVED_8BIT_PER_COLOR		0
-#define PIXEL_BGR_RESERVED_8BIT_PER_COLOR		1
-#define PIXEL_BIT_MASK					2
-#define PIXEL_BLT_ONLY					3
-#define PIXEL_FORMAT_MAX				4
-
-struct efi_pixel_bitmask {
-	u32 red_mask;
-	u32 green_mask;
-	u32 blue_mask;
-	u32 reserved_mask;
-};
-
-struct efi_graphics_output_mode_info {
-	u32 version;
-	u32 horizontal_resolution;
-	u32 vertical_resolution;
-	int pixel_format;
-	struct efi_pixel_bitmask pixel_information;
-	u32 pixels_per_scan_line;
-} __packed;
-
-struct efi_graphics_output_protocol_mode_32 {
-	u32 max_mode;
-	u32 mode;
-	u32 info;
-	u32 size_of_info;
-	u64 frame_buffer_base;
-	u32 frame_buffer_size;
-} __packed;
-
-struct efi_graphics_output_protocol_mode_64 {
-	u32 max_mode;
-	u32 mode;
-	u64 info;
-	u64 size_of_info;
-	u64 frame_buffer_base;
-	u64 frame_buffer_size;
-} __packed;
-
-struct efi_graphics_output_protocol_mode {
-	u32 max_mode;
-	u32 mode;
-	unsigned long info;
-	unsigned long size_of_info;
-	u64 frame_buffer_base;
-	unsigned long frame_buffer_size;
-} __packed;
-
-struct efi_graphics_output_protocol_32 {
-	u32 query_mode;
-	u32 set_mode;
-	u32 blt;
-	u32 mode;
-};
-
-struct efi_graphics_output_protocol_64 {
-	u64 query_mode;
-	u64 set_mode;
-	u64 blt;
-	u64 mode;
-};
-
-struct efi_graphics_output_protocol {
-	void *query_mode;
-	unsigned long set_mode;
-	unsigned long blt;
-	struct efi_graphics_output_protocol_mode *mode;
-};
-
 struct efi_uga_draw_protocol_32 {
 	u32 get_mode;
 	u32 set_mode;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/boot/compressed/error.c linux-libre-4.7-gnu/arch/x86/boot/compressed/error.c
--- linux-libre-4.6-gnu/arch/x86/boot/compressed/error.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/x86/boot/compressed/error.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,22 @@
+/*
+ * Callers outside of misc.c need access to the error reporting routines,
+ * but the *_putstr() functions need to stay in misc.c because of how
+ * memcpy() and memmove() are defined for the compressed boot environment.
+ */
+#include "misc.h"
+
+void warn(char *m)
+{
+	error_putstr("\n\n");
+	error_putstr(m);
+	error_putstr("\n\n");
+}
+
+void error(char *m)
+{
+	warn(m);
+	error_putstr(" -- System halted");
+
+	while (1)
+		asm("hlt");
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/boot/compressed/error.h linux-libre-4.7-gnu/arch/x86/boot/compressed/error.h
--- linux-libre-4.6-gnu/arch/x86/boot/compressed/error.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/x86/boot/compressed/error.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,7 @@
+#ifndef BOOT_COMPRESSED_ERROR_H
+#define BOOT_COMPRESSED_ERROR_H
+
+void warn(char *m);
+void error(char *m);
+
+#endif /* BOOT_COMPRESSED_ERROR_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/boot/compressed/head_32.S linux-libre-4.7-gnu/arch/x86/boot/compressed/head_32.S
--- linux-libre-4.6-gnu/arch/x86/boot/compressed/head_32.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/boot/compressed/head_32.S	2016-07-24 15:23:50.000000000 -0400
@@ -176,7 +176,9 @@ preferred_addr:
 1:
 
 	/* Target address to relocate to for decompression */
-	addl	$z_extract_offset, %ebx
+	movl    BP_init_size(%esi), %eax
+	subl    $_end, %eax
+	addl    %eax, %ebx
 
 	/* Set up the stack */
 	leal	boot_stack_end(%ebx), %esp
@@ -233,24 +235,28 @@ relocated:
 2:
 
 /*
- * Do the decompression, and jump to the new kernel..
+ * Do the extraction, and jump to the new kernel..
  */
-				/* push arguments for decompress_kernel: */
-	pushl	$z_run_size	/* size of kernel with .bss and .brk */
+				/* push arguments for extract_kernel: */
 	pushl	$z_output_len	/* decompressed length, end of relocs */
-	leal	z_extract_offset_negative(%ebx), %ebp
+
+	movl    BP_init_size(%esi), %eax
+	subl    $_end, %eax
+	movl    %ebx, %ebp
+	subl    %eax, %ebp
 	pushl	%ebp		/* output address */
+
 	pushl	$z_input_len	/* input_len */
 	leal	input_data(%ebx), %eax
 	pushl	%eax		/* input_data */
 	leal	boot_heap(%ebx), %eax
 	pushl	%eax		/* heap area */
 	pushl	%esi		/* real mode pointer */
-	call	decompress_kernel /* returns kernel location in %eax */
-	addl	$28, %esp
+	call	extract_kernel	/* returns kernel location in %eax */
+	addl	$24, %esp
 
 /*
- * Jump to the decompressed kernel.
+ * Jump to the extracted kernel.
  */
 	xorl	%ebx, %ebx
 	jmp	*%eax
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/boot/compressed/head_64.S linux-libre-4.7-gnu/arch/x86/boot/compressed/head_64.S
--- linux-libre-4.6-gnu/arch/x86/boot/compressed/head_64.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/boot/compressed/head_64.S	2016-07-24 15:23:50.000000000 -0400
@@ -110,7 +110,9 @@ ENTRY(startup_32)
 1:
 
 	/* Target address to relocate to for decompression */
-	addl	$z_extract_offset, %ebx
+	movl	BP_init_size(%esi), %eax
+	subl	$_end, %eax
+	addl	%eax, %ebx
 
 /*
  * Prepare for entering 64 bit mode
@@ -132,7 +134,7 @@ ENTRY(startup_32)
 	/* Initialize Page tables to 0 */
 	leal	pgtable(%ebx), %edi
 	xorl	%eax, %eax
-	movl	$((4096*6)/4), %ecx
+	movl	$(BOOT_INIT_PGT_SIZE/4), %ecx
 	rep	stosl
 
 	/* Build Level 4 */
@@ -338,7 +340,9 @@ preferred_addr:
 1:
 
 	/* Target address to relocate to for decompression */
-	leaq	z_extract_offset(%rbp), %rbx
+	movl	BP_init_size(%rsi), %ebx
+	subl	$_end, %ebx
+	addq	%rbp, %rbx
 
 	/* Set up the stack */
 	leaq	boot_stack_end(%rbx), %rsp
@@ -408,19 +412,16 @@ relocated:
 2:
 	
 /*
- * Do the decompression, and jump to the new kernel..
+ * Do the extraction, and jump to the new kernel..
  */
 	pushq	%rsi			/* Save the real mode argument */
-	movq	$z_run_size, %r9	/* size of kernel with .bss and .brk */
-	pushq	%r9
 	movq	%rsi, %rdi		/* real mode address */
 	leaq	boot_heap(%rip), %rsi	/* malloc area for uncompression */
 	leaq	input_data(%rip), %rdx  /* input_data */
 	movl	$z_input_len, %ecx	/* input_len */
 	movq	%rbp, %r8		/* output target address */
 	movq	$z_output_len, %r9	/* decompressed length, end of relocs */
-	call	decompress_kernel	/* returns kernel location in %rax */
-	popq	%r9
+	call	extract_kernel		/* returns kernel location in %rax */
 	popq	%rsi
 
 /*
@@ -485,4 +486,4 @@ boot_stack_end:
 	.section ".pgtable","a",@nobits
 	.balign 4096
 pgtable:
-	.fill 6*4096, 1, 0
+	.fill BOOT_PGT_SIZE, 1, 0
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/boot/compressed/kaslr.c linux-libre-4.7-gnu/arch/x86/boot/compressed/kaslr.c
--- linux-libre-4.6-gnu/arch/x86/boot/compressed/kaslr.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/x86/boot/compressed/kaslr.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,510 @@
+/*
+ * kaslr.c
+ *
+ * This contains the routines needed to generate a reasonable level of
+ * entropy to choose a randomized kernel base address offset in support
+ * of Kernel Address Space Layout Randomization (KASLR). Additionally
+ * handles walking the physical memory maps (and tracking memory regions
+ * to avoid) in order to select a physical memory location that can
+ * contain the entire properly aligned running kernel image.
+ *
+ */
+#include "misc.h"
+#include "error.h"
+
+#include <asm/msr.h>
+#include <asm/archrandom.h>
+#include <asm/e820.h>
+
+#include <generated/compile.h>
+#include <linux/module.h>
+#include <linux/uts.h>
+#include <linux/utsname.h>
+#include <generated/utsrelease.h>
+
+/* Simplified build-specific string for starting entropy. */
+static const char build_str[] = UTS_RELEASE " (" LINUX_COMPILE_BY "@"
+		LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION;
+
+#define I8254_PORT_CONTROL	0x43
+#define I8254_PORT_COUNTER0	0x40
+#define I8254_CMD_READBACK	0xC0
+#define I8254_SELECT_COUNTER0	0x02
+#define I8254_STATUS_NOTREADY	0x40
+static inline u16 i8254(void)
+{
+	u16 status, timer;
+
+	do {
+		outb(I8254_PORT_CONTROL,
+		     I8254_CMD_READBACK | I8254_SELECT_COUNTER0);
+		status = inb(I8254_PORT_COUNTER0);
+		timer  = inb(I8254_PORT_COUNTER0);
+		timer |= inb(I8254_PORT_COUNTER0) << 8;
+	} while (status & I8254_STATUS_NOTREADY);
+
+	return timer;
+}
+
+static unsigned long rotate_xor(unsigned long hash, const void *area,
+				size_t size)
+{
+	size_t i;
+	unsigned long *ptr = (unsigned long *)area;
+
+	for (i = 0; i < size / sizeof(hash); i++) {
+		/* Rotate by odd number of bits and XOR. */
+		hash = (hash << ((sizeof(hash) * 8) - 7)) | (hash >> 7);
+		hash ^= ptr[i];
+	}
+
+	return hash;
+}
+
+/* Attempt to create a simple but unpredictable starting entropy. */
+static unsigned long get_random_boot(void)
+{
+	unsigned long hash = 0;
+
+	hash = rotate_xor(hash, build_str, sizeof(build_str));
+	hash = rotate_xor(hash, boot_params, sizeof(*boot_params));
+
+	return hash;
+}
+
+static unsigned long get_random_long(const char *purpose)
+{
+#ifdef CONFIG_X86_64
+	const unsigned long mix_const = 0x5d6008cbf3848dd3UL;
+#else
+	const unsigned long mix_const = 0x3f39e593UL;
+#endif
+	unsigned long raw, random = get_random_boot();
+	bool use_i8254 = true;
+
+	debug_putstr(purpose);
+	debug_putstr(" KASLR using");
+
+	if (has_cpuflag(X86_FEATURE_RDRAND)) {
+		debug_putstr(" RDRAND");
+		if (rdrand_long(&raw)) {
+			random ^= raw;
+			use_i8254 = false;
+		}
+	}
+
+	if (has_cpuflag(X86_FEATURE_TSC)) {
+		debug_putstr(" RDTSC");
+		raw = rdtsc();
+
+		random ^= raw;
+		use_i8254 = false;
+	}
+
+	if (use_i8254) {
+		debug_putstr(" i8254");
+		random ^= i8254();
+	}
+
+	/* Circular multiply for better bit diffusion */
+	asm("mul %3"
+	    : "=a" (random), "=d" (raw)
+	    : "a" (random), "rm" (mix_const));
+	random += raw;
+
+	debug_putstr("...\n");
+
+	return random;
+}
+
+struct mem_vector {
+	unsigned long start;
+	unsigned long size;
+};
+
+enum mem_avoid_index {
+	MEM_AVOID_ZO_RANGE = 0,
+	MEM_AVOID_INITRD,
+	MEM_AVOID_CMDLINE,
+	MEM_AVOID_BOOTPARAMS,
+	MEM_AVOID_MAX,
+};
+
+static struct mem_vector mem_avoid[MEM_AVOID_MAX];
+
+static bool mem_contains(struct mem_vector *region, struct mem_vector *item)
+{
+	/* Item at least partially before region. */
+	if (item->start < region->start)
+		return false;
+	/* Item at least partially after region. */
+	if (item->start + item->size > region->start + region->size)
+		return false;
+	return true;
+}
+
+static bool mem_overlaps(struct mem_vector *one, struct mem_vector *two)
+{
+	/* Item one is entirely before item two. */
+	if (one->start + one->size <= two->start)
+		return false;
+	/* Item one is entirely after item two. */
+	if (one->start >= two->start + two->size)
+		return false;
+	return true;
+}
+
+/*
+ * In theory, KASLR can put the kernel anywhere in the range of [16M, 64T).
+ * The mem_avoid array is used to store the ranges that need to be avoided
+ * when KASLR searches for an appropriate random address. We must avoid any
+ * regions that are unsafe to overlap with during decompression, and other
+ * things like the initrd, cmdline and boot_params. This comment seeks to
+ * explain mem_avoid as clearly as possible since incorrect mem_avoid
+ * memory ranges lead to really hard to debug boot failures.
+ *
+ * The initrd, cmdline, and boot_params are trivial to identify for
+ * avoiding. They are MEM_AVOID_INITRD, MEM_AVOID_CMDLINE, and
+ * MEM_AVOID_BOOTPARAMS respectively below.
+ *
+ * What is not obvious how to avoid is the range of memory that is used
+ * during decompression (MEM_AVOID_ZO_RANGE below). This range must cover
+ * the compressed kernel (ZO) and its run space, which is used to extract
+ * the uncompressed kernel (VO) and relocs.
+ *
+ * ZO's full run size sits against the end of the decompression buffer, so
+ * we can calculate where text, data, bss, etc of ZO are positioned more
+ * easily.
+ *
+ * For additional background, the decompression calculations can be found
+ * in header.S, and the memory diagram is based on the one found in misc.c.
+ *
+ * The following conditions are already enforced by the image layouts and
+ * associated code:
+ *  - input + input_size >= output + output_size
+ *  - kernel_total_size <= init_size
+ *  - kernel_total_size <= output_size (see Note below)
+ *  - output + init_size >= output + output_size
+ *
+ * (Note that kernel_total_size and output_size have no fundamental
+ * relationship, but output_size is passed to choose_random_location
+ * as a maximum of the two. The diagram is showing a case where
+ * kernel_total_size is larger than output_size, but this case is
+ * handled by bumping output_size.)
+ *
+ * The above conditions can be illustrated by a diagram:
+ *
+ * 0   output            input            input+input_size    output+init_size
+ * |     |                 |                             |             |
+ * |     |                 |                             |             |
+ * |-----|--------|--------|--------------|-----------|--|-------------|
+ *                |                       |           |
+ *                |                       |           |
+ * output+init_size-ZO_INIT_SIZE  output+output_size  output+kernel_total_size
+ *
+ * [output, output+init_size) is the entire memory range used for
+ * extracting the compressed image.
+ *
+ * [output, output+kernel_total_size) is the range needed for the
+ * uncompressed kernel (VO) and its run size (bss, brk, etc).
+ *
+ * [output, output+output_size) is VO plus relocs (i.e. the entire
+ * uncompressed payload contained by ZO). This is the area of the buffer
+ * written to during decompression.
+ *
+ * [output+init_size-ZO_INIT_SIZE, output+init_size) is the worst-case
+ * range of the copied ZO and decompression code. (i.e. the range
+ * covered backwards of size ZO_INIT_SIZE, starting from output+init_size.)
+ *
+ * [input, input+input_size) is the original copied compressed image (ZO)
+ * (i.e. it does not include its run size). This range must be avoided
+ * because it contains the data used for decompression.
+ *
+ * [input+input_size, output+init_size) is [_text, _end) for ZO. This
+ * range includes ZO's heap and stack, and must be avoided since it
+ * performs the decompression.
+ *
+ * Since the above two ranges need to be avoided and they are adjacent,
+ * they can be merged, resulting in: [input, output+init_size) which
+ * becomes the MEM_AVOID_ZO_RANGE below.
+ */
+static void mem_avoid_init(unsigned long input, unsigned long input_size,
+			   unsigned long output)
+{
+	unsigned long init_size = boot_params->hdr.init_size;
+	u64 initrd_start, initrd_size;
+	u64 cmd_line, cmd_line_size;
+	char *ptr;
+
+	/*
+	 * Avoid the region that is unsafe to overlap during
+	 * decompression.
+	 */
+	mem_avoid[MEM_AVOID_ZO_RANGE].start = input;
+	mem_avoid[MEM_AVOID_ZO_RANGE].size = (output + init_size) - input;
+	add_identity_map(mem_avoid[MEM_AVOID_ZO_RANGE].start,
+			 mem_avoid[MEM_AVOID_ZO_RANGE].size);
+
+	/* Avoid initrd. */
+	initrd_start  = (u64)boot_params->ext_ramdisk_image << 32;
+	initrd_start |= boot_params->hdr.ramdisk_image;
+	initrd_size  = (u64)boot_params->ext_ramdisk_size << 32;
+	initrd_size |= boot_params->hdr.ramdisk_size;
+	mem_avoid[MEM_AVOID_INITRD].start = initrd_start;
+	mem_avoid[MEM_AVOID_INITRD].size = initrd_size;
+	/* No need to set mapping for initrd, it will be handled in VO. */
+
+	/* Avoid kernel command line. */
+	cmd_line  = (u64)boot_params->ext_cmd_line_ptr << 32;
+	cmd_line |= boot_params->hdr.cmd_line_ptr;
+	/* Calculate size of cmd_line. */
+	ptr = (char *)(unsigned long)cmd_line;
+	for (cmd_line_size = 0; ptr[cmd_line_size++]; )
+		;
+	mem_avoid[MEM_AVOID_CMDLINE].start = cmd_line;
+	mem_avoid[MEM_AVOID_CMDLINE].size = cmd_line_size;
+	add_identity_map(mem_avoid[MEM_AVOID_CMDLINE].start,
+			 mem_avoid[MEM_AVOID_CMDLINE].size);
+
+	/* Avoid boot parameters. */
+	mem_avoid[MEM_AVOID_BOOTPARAMS].start = (unsigned long)boot_params;
+	mem_avoid[MEM_AVOID_BOOTPARAMS].size = sizeof(*boot_params);
+	add_identity_map(mem_avoid[MEM_AVOID_BOOTPARAMS].start,
+			 mem_avoid[MEM_AVOID_BOOTPARAMS].size);
+
+	/* We don't need to set a mapping for setup_data. */
+
+#ifdef CONFIG_X86_VERBOSE_BOOTUP
+	/* Make sure video RAM can be used. */
+	add_identity_map(0, PMD_SIZE);
+#endif
+}
+
+/*
+ * Does this memory vector overlap a known avoided area? If so, record the
+ * overlap region with the lowest address.
+ */
+static bool mem_avoid_overlap(struct mem_vector *img,
+			      struct mem_vector *overlap)
+{
+	int i;
+	struct setup_data *ptr;
+	unsigned long earliest = img->start + img->size;
+	bool is_overlapping = false;
+
+	for (i = 0; i < MEM_AVOID_MAX; i++) {
+		if (mem_overlaps(img, &mem_avoid[i]) &&
+		    mem_avoid[i].start < earliest) {
+			*overlap = mem_avoid[i];
+			is_overlapping = true;
+		}
+	}
+
+	/* Avoid all entries in the setup_data linked list. */
+	ptr = (struct setup_data *)(unsigned long)boot_params->hdr.setup_data;
+	while (ptr) {
+		struct mem_vector avoid;
+
+		avoid.start = (unsigned long)ptr;
+		avoid.size = sizeof(*ptr) + ptr->len;
+
+		if (mem_overlaps(img, &avoid) && (avoid.start < earliest)) {
+			*overlap = avoid;
+			is_overlapping = true;
+		}
+
+		ptr = (struct setup_data *)(unsigned long)ptr->next;
+	}
+
+	return is_overlapping;
+}
+
+static unsigned long slots[KERNEL_IMAGE_SIZE / CONFIG_PHYSICAL_ALIGN];
+
+struct slot_area {
+	unsigned long addr;
+	int num;
+};
+
+#define MAX_SLOT_AREA 100
+
+static struct slot_area slot_areas[MAX_SLOT_AREA];
+
+static unsigned long slot_max;
+
+static unsigned long slot_area_index;
+
+static void store_slot_info(struct mem_vector *region, unsigned long image_size)
+{
+	struct slot_area slot_area;
+
+	if (slot_area_index == MAX_SLOT_AREA)
+		return;
+
+	slot_area.addr = region->start;
+	slot_area.num = (region->size - image_size) /
+			CONFIG_PHYSICAL_ALIGN + 1;
+
+	if (slot_area.num > 0) {
+		slot_areas[slot_area_index++] = slot_area;
+		slot_max += slot_area.num;
+	}
+}
+
+static void slots_append(unsigned long addr)
+{
+	/* Overflowing the slots list should be impossible. */
+	if (slot_max >= KERNEL_IMAGE_SIZE / CONFIG_PHYSICAL_ALIGN)
+		return;
+
+	slots[slot_max++] = addr;
+}
+
+static unsigned long slots_fetch_random(void)
+{
+	/* Handle case of no slots stored. */
+	if (slot_max == 0)
+		return 0;
+
+	return slots[get_random_long("Physical") % slot_max];
+}
+
+static void process_e820_entry(struct e820entry *entry,
+			       unsigned long minimum,
+			       unsigned long image_size)
+{
+	struct mem_vector region, img, overlap;
+
+	/* Skip non-RAM entries. */
+	if (entry->type != E820_RAM)
+		return;
+
+	/* Ignore entries entirely above our maximum. */
+	if (entry->addr >= KERNEL_IMAGE_SIZE)
+		return;
+
+	/* Ignore entries entirely below our minimum. */
+	if (entry->addr + entry->size < minimum)
+		return;
+
+	region.start = entry->addr;
+	region.size = entry->size;
+
+	/* Potentially raise address to minimum location. */
+	if (region.start < minimum)
+		region.start = minimum;
+
+	/* Potentially raise address to meet alignment requirements. */
+	region.start = ALIGN(region.start, CONFIG_PHYSICAL_ALIGN);
+
+	/* Did we raise the address above the bounds of this e820 region? */
+	if (region.start > entry->addr + entry->size)
+		return;
+
+	/* Reduce size by any delta from the original address. */
+	region.size -= region.start - entry->addr;
+
+	/* Reduce maximum size to fit end of image within maximum limit. */
+	if (region.start + region.size > KERNEL_IMAGE_SIZE)
+		region.size = KERNEL_IMAGE_SIZE - region.start;
+
+	/* Walk each aligned slot and check for avoided areas. */
+	for (img.start = region.start, img.size = image_size ;
+	     mem_contains(&region, &img) ;
+	     img.start += CONFIG_PHYSICAL_ALIGN) {
+		if (mem_avoid_overlap(&img, &overlap))
+			continue;
+		slots_append(img.start);
+	}
+}
+
+static unsigned long find_random_phys_addr(unsigned long minimum,
+					   unsigned long image_size)
+{
+	int i;
+	unsigned long addr;
+
+	/* Make sure minimum is aligned. */
+	minimum = ALIGN(minimum, CONFIG_PHYSICAL_ALIGN);
+
+	/* Verify potential e820 positions, appending to slots list. */
+	for (i = 0; i < boot_params->e820_entries; i++) {
+		process_e820_entry(&boot_params->e820_map[i], minimum,
+				   image_size);
+	}
+
+	return slots_fetch_random();
+}
+
+static unsigned long find_random_virt_addr(unsigned long minimum,
+					   unsigned long image_size)
+{
+	unsigned long slots, random_addr;
+
+	/* Make sure minimum is aligned. */
+	minimum = ALIGN(minimum, CONFIG_PHYSICAL_ALIGN);
+	/* Align image_size for easy slot calculations. */
+	image_size = ALIGN(image_size, CONFIG_PHYSICAL_ALIGN);
+
+	/*
+	 * There are how many CONFIG_PHYSICAL_ALIGN-sized slots
+	 * that can hold image_size within the range of minimum to
+	 * KERNEL_IMAGE_SIZE?
+	 */
+	slots = (KERNEL_IMAGE_SIZE - minimum - image_size) /
+		 CONFIG_PHYSICAL_ALIGN + 1;
+
+	random_addr = get_random_long("Virtual") % slots;
+
+	return random_addr * CONFIG_PHYSICAL_ALIGN + minimum;
+}
+
+/*
+ * Since this function examines addresses much more numerically,
+ * it takes the input and output pointers as 'unsigned long'.
+ */
+unsigned char *choose_random_location(unsigned long input,
+				      unsigned long input_size,
+				      unsigned long output,
+				      unsigned long output_size)
+{
+	unsigned long choice = output;
+	unsigned long random_addr;
+
+#ifdef CONFIG_HIBERNATION
+	if (!cmdline_find_option_bool("kaslr")) {
+		warn("KASLR disabled: 'kaslr' not on cmdline (hibernation selected).");
+		goto out;
+	}
+#else
+	if (cmdline_find_option_bool("nokaslr")) {
+		warn("KASLR disabled: 'nokaslr' on cmdline.");
+		goto out;
+	}
+#endif
+
+	boot_params->hdr.loadflags |= KASLR_FLAG;
+
+	/* Record the various known unsafe memory ranges. */
+	mem_avoid_init(input, input_size, output);
+
+	/* Walk e820 and find a random address. */
+	random_addr = find_random_phys_addr(output, output_size);
+	if (!random_addr) {
+		warn("KASLR disabled: could not find suitable E820 region!");
+		goto out;
+	}
+
+	/* Always enforce the minimum. */
+	if (random_addr < choice)
+		goto out;
+
+	choice = random_addr;
+
+	add_identity_map(choice, output_size);
+
+	/* This actually loads the identity pagetable on x86_64. */
+	finalize_identity_maps();
+out:
+	return (unsigned char *)choice;
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/boot/compressed/Makefile linux-libre-4.7-gnu/arch/x86/boot/compressed/Makefile
--- linux-libre-4.6-gnu/arch/x86/boot/compressed/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/boot/compressed/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -57,12 +57,27 @@ LDFLAGS_vmlinux := -T
 hostprogs-y	:= mkpiggy
 HOST_EXTRACFLAGS += -I$(srctree)/tools/include
 
+sed-voffset := -e 's/^\([0-9a-fA-F]*\) [ABCDGRSTVW] \(_text\|__bss_start\|_end\)$$/\#define VO_\2 _AC(0x\1,UL)/p'
+
+quiet_cmd_voffset = VOFFSET $@
+      cmd_voffset = $(NM) $< | sed -n $(sed-voffset) > $@
+
+targets += ../voffset.h
+
+$(obj)/../voffset.h: vmlinux FORCE
+	$(call if_changed,voffset)
+
+$(obj)/misc.o: $(obj)/../voffset.h
+
 vmlinux-objs-y := $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o \
-	$(obj)/string.o $(obj)/cmdline.o \
+	$(obj)/string.o $(obj)/cmdline.o $(obj)/error.o \
 	$(obj)/piggy.o $(obj)/cpuflags.o
 
 vmlinux-objs-$(CONFIG_EARLY_PRINTK) += $(obj)/early_serial_console.o
-vmlinux-objs-$(CONFIG_RANDOMIZE_BASE) += $(obj)/aslr.o
+vmlinux-objs-$(CONFIG_RANDOMIZE_BASE) += $(obj)/kaslr.o
+ifdef CONFIG_X86_64
+	vmlinux-objs-$(CONFIG_RANDOMIZE_BASE) += $(obj)/pagetable.o
+endif
 
 $(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone
 
@@ -72,7 +87,6 @@ vmlinux-objs-$(CONFIG_EFI_MIXED) += $(ob
 
 $(obj)/vmlinux: $(vmlinux-objs-y) FORCE
 	$(call if_changed,ld)
-	@:
 
 OBJCOPYFLAGS_vmlinux.bin :=  -R .comment -S
 $(obj)/vmlinux.bin: vmlinux FORCE
@@ -109,10 +123,8 @@ suffix-$(CONFIG_KERNEL_XZ)	:= xz
 suffix-$(CONFIG_KERNEL_LZO) 	:= lzo
 suffix-$(CONFIG_KERNEL_LZ4) 	:= lz4
 
-RUN_SIZE = $(shell $(OBJDUMP) -h vmlinux | \
-	     $(CONFIG_SHELL) $(srctree)/arch/x86/tools/calc_run_size.sh)
 quiet_cmd_mkpiggy = MKPIGGY $@
-      cmd_mkpiggy = $(obj)/mkpiggy $< $(RUN_SIZE) > $@ || ( rm -f $@ ; false )
+      cmd_mkpiggy = $(obj)/mkpiggy $< > $@ || ( rm -f $@ ; false )
 
 targets += piggy.S
 $(obj)/piggy.S: $(obj)/vmlinux.bin.$(suffix-y) $(obj)/mkpiggy FORCE
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/boot/compressed/misc.c linux-libre-4.7-gnu/arch/x86/boot/compressed/misc.c
--- linux-libre-4.6-gnu/arch/x86/boot/compressed/misc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/boot/compressed/misc.c	2016-07-24 15:23:50.000000000 -0400
@@ -1,8 +1,10 @@
 /*
  * misc.c
  *
- * This is a collection of several routines from gzip-1.0.3
- * adapted for Linux.
+ * This is a collection of several routines used to extract the kernel
+ * which includes KASLR relocation, decompression, ELF parsing, and
+ * relocation processing. Additionally included are the screen and serial
+ * output functions and related debugging support functions.
  *
  * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
  * puts by Nick Holloway 1993, better puts by Martin Mares 1995
@@ -10,111 +12,37 @@
  */
 
 #include "misc.h"
+#include "error.h"
 #include "../string.h"
-
-/* WARNING!!
- * This code is compiled with -fPIC and it is relocated dynamically
- * at run time, but no relocation processing is performed.
- * This means that it is not safe to place pointers in static structures.
- */
+#include "../voffset.h"
 
 /*
- * Getting to provable safe in place decompression is hard.
- * Worst case behaviours need to be analyzed.
- * Background information:
- *
- * The file layout is:
- *    magic[2]
- *    method[1]
- *    flags[1]
- *    timestamp[4]
- *    extraflags[1]
- *    os[1]
- *    compressed data blocks[N]
- *    crc[4] orig_len[4]
- *
- * resulting in 18 bytes of non compressed data overhead.
- *
- * Files divided into blocks
- * 1 bit (last block flag)
- * 2 bits (block type)
- *
- * 1 block occurs every 32K -1 bytes or when there 50% compression
- * has been achieved. The smallest block type encoding is always used.
- *
- * stored:
- *    32 bits length in bytes.
- *
- * fixed:
- *    magic fixed tree.
- *    symbols.
- *
- * dynamic:
- *    dynamic tree encoding.
- *    symbols.
- *
- *
- * The buffer for decompression in place is the length of the
- * uncompressed data, plus a small amount extra to keep the algorithm safe.
- * The compressed data is placed at the end of the buffer.  The output
- * pointer is placed at the start of the buffer and the input pointer
- * is placed where the compressed data starts.  Problems will occur
- * when the output pointer overruns the input pointer.
- *
- * The output pointer can only overrun the input pointer if the input
- * pointer is moving faster than the output pointer.  A condition only
- * triggered by data whose compressed form is larger than the uncompressed
- * form.
- *
- * The worst case at the block level is a growth of the compressed data
- * of 5 bytes per 32767 bytes.
- *
- * The worst case internal to a compressed block is very hard to figure.
- * The worst case can at least be boundined by having one bit that represents
- * 32764 bytes and then all of the rest of the bytes representing the very
- * very last byte.
- *
- * All of which is enough to compute an amount of extra data that is required
- * to be safe.  To avoid problems at the block level allocating 5 extra bytes
- * per 32767 bytes of data is sufficient.  To avoind problems internal to a
- * block adding an extra 32767 bytes (the worst case uncompressed block size)
- * is sufficient, to ensure that in the worst case the decompressed data for
- * block will stop the byte before the compressed data for a block begins.
- * To avoid problems with the compressed data's meta information an extra 18
- * bytes are needed.  Leading to the formula:
- *
- * extra_bytes = (uncompressed_size >> 12) + 32768 + 18 + decompressor_size.
- *
- * Adding 8 bytes per 32K is a bit excessive but much easier to calculate.
- * Adding 32768 instead of 32767 just makes for round numbers.
- * Adding the decompressor_size is necessary as it musht live after all
- * of the data as well.  Last I measured the decompressor is about 14K.
- * 10K of actual data and 4K of bss.
- *
+ * WARNING!!
+ * This code is compiled with -fPIC and it is relocated dynamically at
+ * run time, but no relocation processing is performed. This means that
+ * it is not safe to place pointers in static structures.
  */
 
-/*
- * gzip declarations
- */
+/* Macros used by the included decompressor code below. */
 #define STATIC		static
 
-#undef memcpy
-
 /*
- * Use a normal definition of memset() from string.c. There are already
+ * Use normal definitions of mem*() from string.c. There are already
  * included header files which expect a definition of memset() and by
  * the time we define memset macro, it is too late.
  */
+#undef memcpy
 #undef memset
 #define memzero(s, n)	memset((s), 0, (n))
+#define memmove		memmove
 
-
-static void error(char *m);
+/* Functions used by the included decompressor code below. */
+void *memmove(void *dest, const void *src, size_t n);
 
 /*
  * This is set up by the setup-routine at boot-time
  */
-struct boot_params *real_mode;		/* Pointer to real-mode data */
+struct boot_params *boot_params;
 
 memptr free_mem_ptr;
 memptr free_mem_end_ptr;
@@ -146,12 +74,16 @@ static int lines, cols;
 #ifdef CONFIG_KERNEL_LZ4
 #include "../../../../lib/decompress_unlz4.c"
 #endif
+/*
+ * NOTE: When adding a new decompressor, please update the analysis in
+ * ../header.S.
+ */
 
 static void scroll(void)
 {
 	int i;
 
-	memcpy(vidmem, vidmem + cols * 2, (lines - 1) * cols * 2);
+	memmove(vidmem, vidmem + cols * 2, (lines - 1) * cols * 2);
 	for (i = (lines - 1) * cols * 2; i < lines * cols * 2; i += 2)
 		vidmem[i] = ' ';
 }
@@ -184,12 +116,12 @@ void __putstr(const char *s)
 		}
 	}
 
-	if (real_mode->screen_info.orig_video_mode == 0 &&
+	if (boot_params->screen_info.orig_video_mode == 0 &&
 	    lines == 0 && cols == 0)
 		return;
 
-	x = real_mode->screen_info.orig_x;
-	y = real_mode->screen_info.orig_y;
+	x = boot_params->screen_info.orig_x;
+	y = boot_params->screen_info.orig_y;
 
 	while ((c = *s++) != '\0') {
 		if (c == '\n') {
@@ -210,8 +142,8 @@ void __putstr(const char *s)
 		}
 	}
 
-	real_mode->screen_info.orig_x = x;
-	real_mode->screen_info.orig_y = y;
+	boot_params->screen_info.orig_x = x;
+	boot_params->screen_info.orig_y = y;
 
 	pos = (x + cols * y) * 2;	/* Update cursor position */
 	outb(14, vidport);
@@ -237,23 +169,13 @@ void __puthex(unsigned long value)
 	}
 }
 
-static void error(char *x)
-{
-	error_putstr("\n\n");
-	error_putstr(x);
-	error_putstr("\n\n -- System halted");
-
-	while (1)
-		asm("hlt");
-}
-
 #if CONFIG_X86_NEED_RELOCS
 static void handle_relocations(void *output, unsigned long output_len)
 {
 	int *reloc;
 	unsigned long delta, map, ptr;
 	unsigned long min_addr = (unsigned long)output;
-	unsigned long max_addr = min_addr + output_len;
+	unsigned long max_addr = min_addr + (VO___bss_start - VO__text);
 
 	/*
 	 * Calculate the delta between where vmlinux was linked to load
@@ -295,7 +217,7 @@ static void handle_relocations(void *out
 	 * So we work backwards from the end of the decompressed image.
 	 */
 	for (reloc = output + output_len - sizeof(*reloc); *reloc; reloc--) {
-		int extended = *reloc;
+		long extended = *reloc;
 		extended += map;
 
 		ptr = (unsigned long)extended;
@@ -372,9 +294,7 @@ static void parse_elf(void *output)
 #else
 			dest = (void *)(phdr->p_paddr);
 #endif
-			memcpy(dest,
-			       output + phdr->p_offset,
-			       phdr->p_filesz);
+			memmove(dest, output + phdr->p_offset, phdr->p_filesz);
 			break;
 		default: /* Ignore other PT_* */ break;
 		}
@@ -383,23 +303,41 @@ static void parse_elf(void *output)
 	free(phdrs);
 }
 
-asmlinkage __visible void *decompress_kernel(void *rmode, memptr heap,
+/*
+ * The compressed kernel image (ZO), has been moved so that its position
+ * is against the end of the buffer used to hold the uncompressed kernel
+ * image (VO) and the execution environment (.bss, .brk), which makes sure
+ * there is room to do the in-place decompression. (See header.S for the
+ * calculations.)
+ *
+ *                             |-----compressed kernel image------|
+ *                             V                                  V
+ * 0                       extract_offset                      +INIT_SIZE
+ * |-----------|---------------|-------------------------|--------|
+ *             |               |                         |        |
+ *           VO__text      startup_32 of ZO          VO__end    ZO__end
+ *             ^                                         ^
+ *             |-------uncompressed kernel image---------|
+ *
+ */
+asmlinkage __visible void *extract_kernel(void *rmode, memptr heap,
 				  unsigned char *input_data,
 				  unsigned long input_len,
 				  unsigned char *output,
-				  unsigned long output_len,
-				  unsigned long run_size)
+				  unsigned long output_len)
 {
+	const unsigned long kernel_total_size = VO__end - VO__text;
 	unsigned char *output_orig = output;
 
-	real_mode = rmode;
+	/* Retain x86 boot parameters pointer passed from startup_32/64. */
+	boot_params = rmode;
 
-	/* Clear it for solely in-kernel use */
-	real_mode->hdr.loadflags &= ~KASLR_FLAG;
+	/* Clear flags intended for solely in-kernel use. */
+	boot_params->hdr.loadflags &= ~KASLR_FLAG;
 
-	sanitize_boot_params(real_mode);
+	sanitize_boot_params(boot_params);
 
-	if (real_mode->screen_info.orig_video_mode == 7) {
+	if (boot_params->screen_info.orig_video_mode == 7) {
 		vidmem = (char *) 0xb0000;
 		vidport = 0x3b4;
 	} else {
@@ -407,11 +345,11 @@ asmlinkage __visible void *decompress_ke
 		vidport = 0x3d4;
 	}
 
-	lines = real_mode->screen_info.orig_video_lines;
-	cols = real_mode->screen_info.orig_video_cols;
+	lines = boot_params->screen_info.orig_video_lines;
+	cols = boot_params->screen_info.orig_video_cols;
 
 	console_init();
-	debug_putstr("early console in decompress_kernel\n");
+	debug_putstr("early console in extract_kernel\n");
 
 	free_mem_ptr     = heap;	/* Heap */
 	free_mem_end_ptr = heap + BOOT_HEAP_SIZE;
@@ -421,16 +359,16 @@ asmlinkage __visible void *decompress_ke
 	debug_putaddr(input_len);
 	debug_putaddr(output);
 	debug_putaddr(output_len);
-	debug_putaddr(run_size);
+	debug_putaddr(kernel_total_size);
 
 	/*
 	 * The memory hole needed for the kernel is the larger of either
 	 * the entire decompressed kernel plus relocation table, or the
 	 * entire decompressed kernel plus .bss and .brk sections.
 	 */
-	output = choose_kernel_location(real_mode, input_data, input_len, output,
-					output_len > run_size ? output_len
-							      : run_size);
+	output = choose_random_location((unsigned long)input_data, input_len,
+					(unsigned long)output,
+					max(output_len, kernel_total_size));
 
 	/* Validate memory location choices. */
 	if ((unsigned long)output & (MIN_KERNEL_ALIGN - 1))
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/boot/compressed/misc.h linux-libre-4.7-gnu/arch/x86/boot/compressed/misc.h
--- linux-libre-4.6-gnu/arch/x86/boot/compressed/misc.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/boot/compressed/misc.h	2016-07-24 15:23:50.000000000 -0400
@@ -32,7 +32,7 @@
 /* misc.c */
 extern memptr free_mem_ptr;
 extern memptr free_mem_end_ptr;
-extern struct boot_params *real_mode;		/* Pointer to real-mode data */
+extern struct boot_params *boot_params;
 void __putstr(const char *s);
 void __puthex(unsigned long value);
 #define error_putstr(__x)  __putstr(__x)
@@ -66,26 +66,35 @@ int cmdline_find_option_bool(const char
 
 
 #if CONFIG_RANDOMIZE_BASE
-/* aslr.c */
-unsigned char *choose_kernel_location(struct boot_params *boot_params,
-				      unsigned char *input,
+/* kaslr.c */
+unsigned char *choose_random_location(unsigned long input_ptr,
 				      unsigned long input_size,
-				      unsigned char *output,
+				      unsigned long output_ptr,
 				      unsigned long output_size);
 /* cpuflags.c */
 bool has_cpuflag(int flag);
 #else
 static inline
-unsigned char *choose_kernel_location(struct boot_params *boot_params,
-				      unsigned char *input,
+unsigned char *choose_random_location(unsigned long input_ptr,
 				      unsigned long input_size,
-				      unsigned char *output,
+				      unsigned long output_ptr,
 				      unsigned long output_size)
 {
-	return output;
+	return (unsigned char *)output_ptr;
 }
 #endif
 
+#ifdef CONFIG_X86_64
+void add_identity_map(unsigned long start, unsigned long size);
+void finalize_identity_maps(void);
+extern unsigned char _pgtable[];
+#else
+static inline void add_identity_map(unsigned long start, unsigned long size)
+{ }
+static inline void finalize_identity_maps(void)
+{ }
+#endif
+
 #ifdef CONFIG_EARLY_PRINTK
 /* early_serial_console.c */
 extern int early_serial_base;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/boot/compressed/mkpiggy.c linux-libre-4.7-gnu/arch/x86/boot/compressed/mkpiggy.c
--- linux-libre-4.6-gnu/arch/x86/boot/compressed/mkpiggy.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/boot/compressed/mkpiggy.c	2016-07-24 15:23:50.000000000 -0400
@@ -18,11 +18,10 @@
  *
  *  H. Peter Anvin <hpa@linux.intel.com>
  *
- * ----------------------------------------------------------------------- */
-
-/*
- * Compute the desired load offset from a compressed program; outputs
- * a small assembly wrapper with the appropriate symbols defined.
+ * -----------------------------------------------------------------------
+ *
+ * Outputs a small assembly wrapper with the appropriate symbols defined.
+ *
  */
 
 #include <stdlib.h>
@@ -35,14 +34,11 @@ int main(int argc, char *argv[])
 {
 	uint32_t olen;
 	long ilen;
-	unsigned long offs;
-	unsigned long run_size;
 	FILE *f = NULL;
 	int retval = 1;
 
-	if (argc < 3) {
-		fprintf(stderr, "Usage: %s compressed_file run_size\n",
-				argv[0]);
+	if (argc < 2) {
+		fprintf(stderr, "Usage: %s compressed_file\n", argv[0]);
 		goto bail;
 	}
 
@@ -67,29 +63,11 @@ int main(int argc, char *argv[])
 	ilen = ftell(f);
 	olen = get_unaligned_le32(&olen);
 
-	/*
-	 * Now we have the input (compressed) and output (uncompressed)
-	 * sizes, compute the necessary decompression offset...
-	 */
-
-	offs = (olen > ilen) ? olen - ilen : 0;
-	offs += olen >> 12;	/* Add 8 bytes for each 32K block */
-	offs += 64*1024 + 128;	/* Add 64K + 128 bytes slack */
-	offs = (offs+4095) & ~4095; /* Round to a 4K boundary */
-	run_size = atoi(argv[2]);
-
 	printf(".section \".rodata..compressed\",\"a\",@progbits\n");
 	printf(".globl z_input_len\n");
 	printf("z_input_len = %lu\n", ilen);
 	printf(".globl z_output_len\n");
 	printf("z_output_len = %lu\n", (unsigned long)olen);
-	printf(".globl z_extract_offset\n");
-	printf("z_extract_offset = 0x%lx\n", offs);
-	/* z_extract_offset_negative allows simplification of head_32.S */
-	printf(".globl z_extract_offset_negative\n");
-	printf("z_extract_offset_negative = -0x%lx\n", offs);
-	printf(".globl z_run_size\n");
-	printf("z_run_size = %lu\n", run_size);
 
 	printf(".globl input_data, input_data_end\n");
 	printf("input_data:\n");
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/boot/compressed/pagetable.c linux-libre-4.7-gnu/arch/x86/boot/compressed/pagetable.c
--- linux-libre-4.6-gnu/arch/x86/boot/compressed/pagetable.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/x86/boot/compressed/pagetable.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,129 @@
+/*
+ * This code is used on x86_64 to create page table identity mappings on
+ * demand by building up a new set of page tables (or appending to the
+ * existing ones), and then switching over to them when ready.
+ */
+
+/*
+ * Since we're dealing with identity mappings, physical and virtual
+ * addresses are the same, so override these defines which are ultimately
+ * used by the headers in misc.h.
+ */
+#define __pa(x)  ((unsigned long)(x))
+#define __va(x)  ((void *)((unsigned long)(x)))
+
+#include "misc.h"
+
+/* These actually do the work of building the kernel identity maps. */
+#include <asm/init.h>
+#include <asm/pgtable.h>
+#include "../../mm/ident_map.c"
+
+/* Used by pgtable.h asm code to force instruction serialization. */
+unsigned long __force_order;
+
+/* Used to track our page table allocation area. */
+struct alloc_pgt_data {
+	unsigned char *pgt_buf;
+	unsigned long pgt_buf_size;
+	unsigned long pgt_buf_offset;
+};
+
+/*
+ * Allocates space for a page table entry, using struct alloc_pgt_data
+ * above. Besides the local callers, this is used as the allocation
+ * callback in mapping_info below.
+ */
+static void *alloc_pgt_page(void *context)
+{
+	struct alloc_pgt_data *pages = (struct alloc_pgt_data *)context;
+	unsigned char *entry;
+
+	/* Validate there is space available for a new page. */
+	if (pages->pgt_buf_offset >= pages->pgt_buf_size) {
+		debug_putstr("out of pgt_buf in " __FILE__ "!?\n");
+		debug_putaddr(pages->pgt_buf_offset);
+		debug_putaddr(pages->pgt_buf_size);
+		return NULL;
+	}
+
+	entry = pages->pgt_buf + pages->pgt_buf_offset;
+	pages->pgt_buf_offset += PAGE_SIZE;
+
+	return entry;
+}
+
+/* Used to track our allocated page tables. */
+static struct alloc_pgt_data pgt_data;
+
+/* The top level page table entry pointer. */
+static unsigned long level4p;
+
+/* Locates and clears a region for a new top level page table. */
+static void prepare_level4(void)
+{
+	/*
+	 * It should be impossible for this not to already be true,
+	 * but since calling this a second time would rewind the other
+	 * counters, let's just make sure this is reset too.
+	 */
+	pgt_data.pgt_buf_offset = 0;
+
+	/*
+	 * If we came here via startup_32(), cr3 will be _pgtable already
+	 * and we must append to the existing area instead of entirely
+	 * overwriting it.
+	 */
+	level4p = read_cr3();
+	if (level4p == (unsigned long)_pgtable) {
+		debug_putstr("booted via startup_32()\n");
+		pgt_data.pgt_buf = _pgtable + BOOT_INIT_PGT_SIZE;
+		pgt_data.pgt_buf_size = BOOT_PGT_SIZE - BOOT_INIT_PGT_SIZE;
+		memset(pgt_data.pgt_buf, 0, pgt_data.pgt_buf_size);
+	} else {
+		debug_putstr("booted via startup_64()\n");
+		pgt_data.pgt_buf = _pgtable;
+		pgt_data.pgt_buf_size = BOOT_PGT_SIZE;
+		memset(pgt_data.pgt_buf, 0, pgt_data.pgt_buf_size);
+		level4p = (unsigned long)alloc_pgt_page(&pgt_data);
+	}
+}
+
+/*
+ * Adds the specified range to what will become the new identity mappings.
+ * Once all ranges have been added, the new mapping is activated by calling
+ * finalize_identity_maps() below.
+ */
+void add_identity_map(unsigned long start, unsigned long size)
+{
+	struct x86_mapping_info mapping_info = {
+		.alloc_pgt_page	= alloc_pgt_page,
+		.context	= &pgt_data,
+		.pmd_flag	= __PAGE_KERNEL_LARGE_EXEC,
+	};
+	unsigned long end = start + size;
+
+	/* Make sure we have a top level page table ready to use. */
+	if (!level4p)
+		prepare_level4();
+
+	/* Align boundary to 2M. */
+	start = round_down(start, PMD_SIZE);
+	end = round_up(end, PMD_SIZE);
+	if (start >= end)
+		return;
+
+	/* Build the mapping. */
+	kernel_ident_mapping_init(&mapping_info, (pgd_t *)level4p,
+				  start, end);
+}
+
+/*
+ * This switches the page tables to the new level4 that has been built
+ * via calls to add_identity_map() above. If booted via startup_32(),
+ * this is effectively a no-op.
+ */
+void finalize_identity_maps(void)
+{
+	write_cr3(level4p);
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/boot/compressed/string.c linux-libre-4.7-gnu/arch/x86/boot/compressed/string.c
--- linux-libre-4.6-gnu/arch/x86/boot/compressed/string.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/boot/compressed/string.c	2016-07-24 15:23:50.000000000 -0400
@@ -1,7 +1,16 @@
+/*
+ * This provides an optimized implementation of memcpy, and a simplified
+ * implementation of memset and memmove. These are used here because the
+ * standard kernel runtime versions are not yet available and we don't
+ * trust the gcc built-in implementations as they may do unexpected things
+ * (e.g. FPU ops) in the minimal decompression stub execution environment.
+ */
+#include "error.h"
+
 #include "../string.c"
 
 #ifdef CONFIG_X86_32
-void *memcpy(void *dest, const void *src, size_t n)
+static void *__memcpy(void *dest, const void *src, size_t n)
 {
 	int d0, d1, d2;
 	asm volatile(
@@ -15,7 +24,7 @@ void *memcpy(void *dest, const void *src
 	return dest;
 }
 #else
-void *memcpy(void *dest, const void *src, size_t n)
+static void *__memcpy(void *dest, const void *src, size_t n)
 {
 	long d0, d1, d2;
 	asm volatile(
@@ -39,3 +48,27 @@ void *memset(void *s, int c, size_t n)
 		ss[i] = c;
 	return s;
 }
+
+void *memmove(void *dest, const void *src, size_t n)
+{
+	unsigned char *d = dest;
+	const unsigned char *s = src;
+
+	if (d <= s || d - s >= n)
+		return __memcpy(dest, src, n);
+
+	while (n-- > 0)
+		d[n] = s[n];
+
+	return dest;
+}
+
+/* Detect and warn about potential overlaps, but handle them with memmove. */
+void *memcpy(void *dest, const void *src, size_t n)
+{
+	if (dest > src && dest - src < n) {
+		warn("Avoiding potentially unsafe overlapping memcpy()!");
+		return memmove(dest, src, n);
+	}
+	return __memcpy(dest, src, n);
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/boot/compressed/vmlinux.lds.S linux-libre-4.7-gnu/arch/x86/boot/compressed/vmlinux.lds.S
--- linux-libre-4.6-gnu/arch/x86/boot/compressed/vmlinux.lds.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/boot/compressed/vmlinux.lds.S	2016-07-24 15:23:50.000000000 -0400
@@ -70,5 +70,6 @@ SECTIONS
 		_epgtable = . ;
 	}
 #endif
+	. = ALIGN(PAGE_SIZE);	/* keep ZO size page aligned */
 	_end = .;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/boot/early_serial_console.c linux-libre-4.7-gnu/arch/x86/boot/early_serial_console.c
--- linux-libre-4.6-gnu/arch/x86/boot/early_serial_console.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/boot/early_serial_console.c	2016-07-24 15:23:50.000000000 -0400
@@ -1,3 +1,7 @@
+/*
+ * Serial port routines for use during early boot reporting. This code is
+ * included from both the compressed kernel and the regular kernel.
+ */
 #include "boot.h"
 
 #define DEFAULT_SERIAL_PORT 0x3f8 /* ttyS0 */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/boot/header.S linux-libre-4.7-gnu/arch/x86/boot/header.S
--- linux-libre-4.6-gnu/arch/x86/boot/header.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/boot/header.S	2016-07-24 15:23:50.000000000 -0400
@@ -440,13 +440,116 @@ setup_data:		.quad 0			# 64-bit physical
 
 pref_address:		.quad LOAD_PHYSICAL_ADDR	# preferred load addr
 
-#define ZO_INIT_SIZE	(ZO__end - ZO_startup_32 + ZO_z_extract_offset)
+#
+# Getting to provably safe in-place decompression is hard. Worst case
+# behaviours need to be analyzed. Here let's take the decompression of
+# a gzip-compressed kernel as example, to illustrate it:
+#
+# The file layout of gzip compressed kernel is:
+#
+#    magic[2]
+#    method[1]
+#    flags[1]
+#    timestamp[4]
+#    extraflags[1]
+#    os[1]
+#    compressed data blocks[N]
+#    crc[4] orig_len[4]
+#
+# ... resulting in +18 bytes overhead of uncompressed data.
+#
+# (For more information, please refer to RFC 1951 and RFC 1952.)
+#
+# Files divided into blocks
+# 1 bit (last block flag)
+# 2 bits (block type)
+#
+# 1 block occurs every 32K -1 bytes or when there 50% compression
+# has been achieved. The smallest block type encoding is always used.
+#
+# stored:
+#    32 bits length in bytes.
+#
+# fixed:
+#    magic fixed tree.
+#    symbols.
+#
+# dynamic:
+#    dynamic tree encoding.
+#    symbols.
+#
+#
+# The buffer for decompression in place is the length of the uncompressed
+# data, plus a small amount extra to keep the algorithm safe. The
+# compressed data is placed at the end of the buffer.  The output pointer
+# is placed at the start of the buffer and the input pointer is placed
+# where the compressed data starts. Problems will occur when the output
+# pointer overruns the input pointer.
+#
+# The output pointer can only overrun the input pointer if the input
+# pointer is moving faster than the output pointer.  A condition only
+# triggered by data whose compressed form is larger than the uncompressed
+# form.
+#
+# The worst case at the block level is a growth of the compressed data
+# of 5 bytes per 32767 bytes.
+#
+# The worst case internal to a compressed block is very hard to figure.
+# The worst case can at least be bounded by having one bit that represents
+# 32764 bytes and then all of the rest of the bytes representing the very
+# very last byte.
+#
+# All of which is enough to compute an amount of extra data that is required
+# to be safe.  To avoid problems at the block level allocating 5 extra bytes
+# per 32767 bytes of data is sufficient.  To avoid problems internal to a
+# block adding an extra 32767 bytes (the worst case uncompressed block size)
+# is sufficient, to ensure that in the worst case the decompressed data for
+# block will stop the byte before the compressed data for a block begins.
+# To avoid problems with the compressed data's meta information an extra 18
+# bytes are needed.  Leading to the formula:
+#
+# extra_bytes = (uncompressed_size >> 12) + 32768 + 18
+#
+# Adding 8 bytes per 32K is a bit excessive but much easier to calculate.
+# Adding 32768 instead of 32767 just makes for round numbers.
+#
+# Above analysis is for decompressing gzip compressed kernel only. Up to
+# now 6 different decompressor are supported all together. And among them
+# xz stores data in chunks and has maximum chunk of 64K. Hence safety
+# margin should be updated to cover all decompressors so that we don't
+# need to deal with each of them separately. Please check
+# the description in lib/decompressor_xxx.c for specific information.
+#
+# extra_bytes = (uncompressed_size >> 12) + 65536 + 128
+
+#define ZO_z_extra_bytes	((ZO_z_output_len >> 12) + 65536 + 128)
+#if ZO_z_output_len > ZO_z_input_len
+# define ZO_z_extract_offset	(ZO_z_output_len + ZO_z_extra_bytes - \
+				 ZO_z_input_len)
+#else
+# define ZO_z_extract_offset	ZO_z_extra_bytes
+#endif
+
+/*
+ * The extract_offset has to be bigger than ZO head section. Otherwise when
+ * the head code is running to move ZO to the end of the buffer, it will
+ * overwrite the head code itself.
+ */
+#if (ZO__ehead - ZO_startup_32) > ZO_z_extract_offset
+# define ZO_z_min_extract_offset ((ZO__ehead - ZO_startup_32 + 4095) & ~4095)
+#else
+# define ZO_z_min_extract_offset ((ZO_z_extract_offset + 4095) & ~4095)
+#endif
+
+#define ZO_INIT_SIZE	(ZO__end - ZO_startup_32 + ZO_z_min_extract_offset)
+
 #define VO_INIT_SIZE	(VO__end - VO__text)
 #if ZO_INIT_SIZE > VO_INIT_SIZE
-#define INIT_SIZE ZO_INIT_SIZE
+# define INIT_SIZE ZO_INIT_SIZE
 #else
-#define INIT_SIZE VO_INIT_SIZE
+# define INIT_SIZE VO_INIT_SIZE
 #endif
+
 init_size:		.long INIT_SIZE		# kernel initialization size
 handover_offset:	.long 0			# Filled in by build.c
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/boot/Makefile linux-libre-4.7-gnu/arch/x86/boot/Makefile
--- linux-libre-4.6-gnu/arch/x86/boot/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/boot/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -86,16 +86,7 @@ $(obj)/vmlinux.bin: $(obj)/compressed/vm
 
 SETUP_OBJS = $(addprefix $(obj)/,$(setup-y))
 
-sed-voffset := -e 's/^\([0-9a-fA-F]*\) [ABCDGRSTVW] \(_text\|_end\)$$/\#define VO_\2 0x\1/p'
-
-quiet_cmd_voffset = VOFFSET $@
-      cmd_voffset = $(NM) $< | sed -n $(sed-voffset) > $@
-
-targets += voffset.h
-$(obj)/voffset.h: vmlinux FORCE
-	$(call if_changed,voffset)
-
-sed-zoffset := -e 's/^\([0-9a-fA-F]*\) [ABCDGRSTVW] \(startup_32\|startup_64\|efi32_stub_entry\|efi64_stub_entry\|efi_pe_entry\|input_data\|_end\|z_.*\)$$/\#define ZO_\2 0x\1/p'
+sed-zoffset := -e 's/^\([0-9a-fA-F]*\) [ABCDGRSTVW] \(startup_32\|startup_64\|efi32_stub_entry\|efi64_stub_entry\|efi_pe_entry\|input_data\|_end\|_ehead\|_text\|z_.*\)$$/\#define ZO_\2 0x\1/p'
 
 quiet_cmd_zoffset = ZOFFSET $@
       cmd_zoffset = $(NM) $< | sed -n $(sed-zoffset) > $@
@@ -106,7 +97,7 @@ $(obj)/zoffset.h: $(obj)/compressed/vmli
 
 
 AFLAGS_header.o += -I$(obj)
-$(obj)/header.o: $(obj)/voffset.h $(obj)/zoffset.h
+$(obj)/header.o: $(obj)/zoffset.h
 
 LDFLAGS_setup.elf	:= -T
 $(obj)/setup.elf: $(src)/setup.ld $(SETUP_OBJS) FORCE
@@ -171,6 +162,9 @@ isoimage: $(obj)/bzImage
 	for i in lib lib64 share end ; do \
 		if [ -f /usr/$$i/syslinux/isolinux.bin ] ; then \
 			cp /usr/$$i/syslinux/isolinux.bin $(obj)/isoimage ; \
+			if [ -f /usr/$$i/syslinux/ldlinux.c32 ]; then \
+				cp /usr/$$i/syslinux/ldlinux.c32 $(obj)/isoimage ; \
+			fi ; \
 			break ; \
 		fi ; \
 		if [ $$i = end ] ; then exit 1 ; fi ; \
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/configs/i386_defconfig linux-libre-4.7-gnu/arch/x86/configs/i386_defconfig
--- linux-libre-4.6-gnu/arch/x86/configs/i386_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/configs/i386_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -17,7 +17,6 @@ CONFIG_CGROUPS=y
 CONFIG_CGROUP_FREEZER=y
 CONFIG_CPUSETS=y
 CONFIG_CGROUP_CPUACCT=y
-CONFIG_RESOURCE_COUNTERS=y
 CONFIG_CGROUP_SCHED=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_COMPAT_BRK is not set
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/configs/x86_64_defconfig linux-libre-4.7-gnu/arch/x86/configs/x86_64_defconfig
--- linux-libre-4.6-gnu/arch/x86/configs/x86_64_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/configs/x86_64_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -16,7 +16,6 @@ CONFIG_CGROUPS=y
 CONFIG_CGROUP_FREEZER=y
 CONFIG_CPUSETS=y
 CONFIG_CGROUP_CPUACCT=y
-CONFIG_RESOURCE_COUNTERS=y
 CONFIG_CGROUP_SCHED=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_COMPAT_BRK is not set
@@ -173,6 +172,7 @@ CONFIG_TIGON3=y
 CONFIG_NET_TULIP=y
 CONFIG_E100=y
 CONFIG_E1000=y
+CONFIG_E1000E=y
 CONFIG_SKY2=y
 CONFIG_FORCEDETH=y
 CONFIG_8139TOO=y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/crypto/aesni-intel_glue.c linux-libre-4.7-gnu/arch/x86/crypto/aesni-intel_glue.c
--- linux-libre-4.6-gnu/arch/x86/crypto/aesni-intel_glue.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/crypto/aesni-intel_glue.c	2016-07-24 15:23:50.000000000 -0400
@@ -1477,7 +1477,7 @@ static int __init aesni_init(void)
 	}
 	aesni_ctr_enc_tfm = aesni_ctr_enc;
 #ifdef CONFIG_AS_AVX
-	if (cpu_has_avx) {
+	if (boot_cpu_has(X86_FEATURE_AVX)) {
 		/* optimize performance of ctr mode encryption transform */
 		aesni_ctr_enc_tfm = aesni_ctr_enc_avx_tfm;
 		pr_info("AES CTR mode by8 optimization enabled\n");
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/crypto/camellia_aesni_avx2_glue.c linux-libre-4.7-gnu/arch/x86/crypto/camellia_aesni_avx2_glue.c
--- linux-libre-4.6-gnu/arch/x86/crypto/camellia_aesni_avx2_glue.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/crypto/camellia_aesni_avx2_glue.c	2016-07-24 15:23:50.000000000 -0400
@@ -562,7 +562,10 @@ static int __init camellia_aesni_init(vo
 {
 	const char *feature_name;
 
-	if (!cpu_has_avx2 || !cpu_has_avx || !cpu_has_aes || !cpu_has_osxsave) {
+	if (!boot_cpu_has(X86_FEATURE_AVX) ||
+	    !boot_cpu_has(X86_FEATURE_AVX2) ||
+	    !boot_cpu_has(X86_FEATURE_AES) ||
+	    !boot_cpu_has(X86_FEATURE_OSXSAVE)) {
 		pr_info("AVX2 or AES-NI instructions are not detected.\n");
 		return -ENODEV;
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/crypto/camellia_aesni_avx_glue.c linux-libre-4.7-gnu/arch/x86/crypto/camellia_aesni_avx_glue.c
--- linux-libre-4.6-gnu/arch/x86/crypto/camellia_aesni_avx_glue.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/crypto/camellia_aesni_avx_glue.c	2016-07-24 15:23:50.000000000 -0400
@@ -554,7 +554,9 @@ static int __init camellia_aesni_init(vo
 {
 	const char *feature_name;
 
-	if (!cpu_has_avx || !cpu_has_aes || !cpu_has_osxsave) {
+	if (!boot_cpu_has(X86_FEATURE_AVX) ||
+	    !boot_cpu_has(X86_FEATURE_AES) ||
+	    !boot_cpu_has(X86_FEATURE_OSXSAVE)) {
 		pr_info("AVX or AES-NI instructions are not detected.\n");
 		return -ENODEV;
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/crypto/chacha20_glue.c linux-libre-4.7-gnu/arch/x86/crypto/chacha20_glue.c
--- linux-libre-4.6-gnu/arch/x86/crypto/chacha20_glue.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/crypto/chacha20_glue.c	2016-07-24 15:23:50.000000000 -0400
@@ -129,7 +129,8 @@ static int __init chacha20_simd_mod_init
 		return -ENODEV;
 
 #ifdef CONFIG_AS_AVX2
-	chacha20_use_avx2 = cpu_has_avx && cpu_has_avx2 &&
+	chacha20_use_avx2 = boot_cpu_has(X86_FEATURE_AVX) &&
+			    boot_cpu_has(X86_FEATURE_AVX2) &&
 			    cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM, NULL);
 #endif
 	return crypto_register_alg(&alg);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/crypto/poly1305_glue.c linux-libre-4.7-gnu/arch/x86/crypto/poly1305_glue.c
--- linux-libre-4.6-gnu/arch/x86/crypto/poly1305_glue.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/crypto/poly1305_glue.c	2016-07-24 15:23:50.000000000 -0400
@@ -179,11 +179,12 @@ static struct shash_alg alg = {
 
 static int __init poly1305_simd_mod_init(void)
 {
-	if (!cpu_has_xmm2)
+	if (!boot_cpu_has(X86_FEATURE_XMM2))
 		return -ENODEV;
 
 #ifdef CONFIG_AS_AVX2
-	poly1305_use_avx2 = cpu_has_avx && cpu_has_avx2 &&
+	poly1305_use_avx2 = boot_cpu_has(X86_FEATURE_AVX) &&
+			    boot_cpu_has(X86_FEATURE_AVX2) &&
 			    cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM, NULL);
 	alg.descsize = sizeof(struct poly1305_simd_desc_ctx);
 	if (poly1305_use_avx2)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/crypto/serpent_avx2_glue.c linux-libre-4.7-gnu/arch/x86/crypto/serpent_avx2_glue.c
--- linux-libre-4.6-gnu/arch/x86/crypto/serpent_avx2_glue.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/crypto/serpent_avx2_glue.c	2016-07-24 15:23:50.000000000 -0400
@@ -538,7 +538,7 @@ static int __init init(void)
 {
 	const char *feature_name;
 
-	if (!cpu_has_avx2 || !cpu_has_osxsave) {
+	if (!boot_cpu_has(X86_FEATURE_AVX2) || !boot_cpu_has(X86_FEATURE_OSXSAVE)) {
 		pr_info("AVX2 instructions are not detected.\n");
 		return -ENODEV;
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/crypto/serpent_sse2_glue.c linux-libre-4.7-gnu/arch/x86/crypto/serpent_sse2_glue.c
--- linux-libre-4.6-gnu/arch/x86/crypto/serpent_sse2_glue.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/crypto/serpent_sse2_glue.c	2016-07-24 15:23:50.000000000 -0400
@@ -600,7 +600,7 @@ static struct crypto_alg serpent_algs[10
 
 static int __init serpent_sse2_init(void)
 {
-	if (!cpu_has_xmm2) {
+	if (!boot_cpu_has(X86_FEATURE_XMM2)) {
 		printk(KERN_INFO "SSE2 instructions are not detected.\n");
 		return -ENODEV;
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/crypto/sha1_ssse3_glue.c linux-libre-4.7-gnu/arch/x86/crypto/sha1_ssse3_glue.c
--- linux-libre-4.6-gnu/arch/x86/crypto/sha1_ssse3_glue.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/crypto/sha1_ssse3_glue.c	2016-07-24 15:23:50.000000000 -0400
@@ -166,7 +166,7 @@ static struct shash_alg sha1_avx_alg = {
 static bool avx_usable(void)
 {
 	if (!cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM, NULL)) {
-		if (cpu_has_avx)
+		if (boot_cpu_has(X86_FEATURE_AVX))
 			pr_info("AVX detected but unusable.\n");
 		return false;
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/crypto/sha256_ssse3_glue.c linux-libre-4.7-gnu/arch/x86/crypto/sha256_ssse3_glue.c
--- linux-libre-4.6-gnu/arch/x86/crypto/sha256_ssse3_glue.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/crypto/sha256_ssse3_glue.c	2016-07-24 15:23:50.000000000 -0400
@@ -201,7 +201,7 @@ static struct shash_alg sha256_avx_algs[
 static bool avx_usable(void)
 {
 	if (!cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM, NULL)) {
-		if (cpu_has_avx)
+		if (boot_cpu_has(X86_FEATURE_AVX))
 			pr_info("AVX detected but unusable.\n");
 		return false;
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/crypto/sha512_ssse3_glue.c linux-libre-4.7-gnu/arch/x86/crypto/sha512_ssse3_glue.c
--- linux-libre-4.6-gnu/arch/x86/crypto/sha512_ssse3_glue.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/crypto/sha512_ssse3_glue.c	2016-07-24 15:23:50.000000000 -0400
@@ -151,7 +151,7 @@ asmlinkage void sha512_transform_avx(u64
 static bool avx_usable(void)
 {
 	if (!cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM, NULL)) {
-		if (cpu_has_avx)
+		if (boot_cpu_has(X86_FEATURE_AVX))
 			pr_info("AVX detected but unusable.\n");
 		return false;
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/crypto/sha-mb/sha1_mb.c linux-libre-4.7-gnu/arch/x86/crypto/sha-mb/sha1_mb.c
--- linux-libre-4.6-gnu/arch/x86/crypto/sha-mb/sha1_mb.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/crypto/sha-mb/sha1_mb.c	2016-07-24 15:23:50.000000000 -0400
@@ -102,14 +102,14 @@ static asmlinkage struct job_sha1* (*sha
 static asmlinkage struct job_sha1* (*sha1_job_mgr_flush)(struct sha1_mb_mgr *state);
 static asmlinkage struct job_sha1* (*sha1_job_mgr_get_comp_job)(struct sha1_mb_mgr *state);
 
-inline void sha1_init_digest(uint32_t *digest)
+static inline void sha1_init_digest(uint32_t *digest)
 {
 	static const uint32_t initial_digest[SHA1_DIGEST_LENGTH] = {SHA1_H0,
 					SHA1_H1, SHA1_H2, SHA1_H3, SHA1_H4 };
 	memcpy(digest, initial_digest, sizeof(initial_digest));
 }
 
-inline uint32_t sha1_pad(uint8_t padblock[SHA1_BLOCK_SIZE * 2],
+static inline uint32_t sha1_pad(uint8_t padblock[SHA1_BLOCK_SIZE * 2],
 			 uint32_t total_len)
 {
 	uint32_t i = total_len & (SHA1_BLOCK_SIZE - 1);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/crypto/sha-mb/sha1_x8_avx2.S linux-libre-4.7-gnu/arch/x86/crypto/sha-mb/sha1_x8_avx2.S
--- linux-libre-4.6-gnu/arch/x86/crypto/sha-mb/sha1_x8_avx2.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/crypto/sha-mb/sha1_x8_avx2.S	2016-07-24 15:23:50.000000000 -0400
@@ -296,7 +296,11 @@ W14  = TMP_
 #
 ENTRY(sha1_x8_avx2)
 
-	push	RSP_SAVE
+	# save callee-saved clobbered registers to comply with C function ABI
+	push	%r12
+	push	%r13
+	push	%r14
+	push	%r15
 
 	#save rsp
 	mov	%rsp, RSP_SAVE
@@ -446,7 +450,12 @@ lloop:
 	## Postamble
 
 	mov     RSP_SAVE, %rsp
-	pop	RSP_SAVE
+
+	# restore callee-saved clobbered registers
+	pop	%r15
+	pop	%r14
+	pop	%r13
+	pop	%r12
 
 	ret
 ENDPROC(sha1_x8_avx2)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/entry/common.c linux-libre-4.7-gnu/arch/x86/entry/common.c
--- linux-libre-4.6-gnu/arch/x86/entry/common.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/entry/common.c	2016-07-24 15:23:50.000000000 -0400
@@ -191,7 +191,7 @@ long syscall_trace_enter_phase2(struct p
 
 long syscall_trace_enter(struct pt_regs *regs)
 {
-	u32 arch = is_ia32_task() ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64;
+	u32 arch = in_ia32_syscall() ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64;
 	unsigned long phase1_result = syscall_trace_enter_phase1(regs, arch);
 
 	if (phase1_result == 0)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/entry/entry_32.S linux-libre-4.7-gnu/arch/x86/entry/entry_32.S
--- linux-libre-4.6-gnu/arch/x86/entry/entry_32.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/entry/entry_32.S	2016-07-24 15:23:50.000000000 -0400
@@ -207,10 +207,7 @@
 ENTRY(ret_from_fork)
 	pushl	%eax
 	call	schedule_tail
-	GET_THREAD_INFO(%ebp)
 	popl	%eax
-	pushl	$0x0202				# Reset kernel eflags
-	popfl
 
 	/* When we fork, we trace the syscall return in the child, too. */
 	movl    %esp, %eax
@@ -221,10 +218,7 @@ END(ret_from_fork)
 ENTRY(ret_from_kernel_thread)
 	pushl	%eax
 	call	schedule_tail
-	GET_THREAD_INFO(%ebp)
 	popl	%eax
-	pushl	$0x0202				# Reset kernel eflags
-	popfl
 	movl	PT_EBP(%esp), %eax
 	call	*PT_EBX(%esp)
 	movl	$0, PT_EAX(%esp)
@@ -251,7 +245,6 @@ ENDPROC(ret_from_kernel_thread)
 ret_from_exception:
 	preempt_stop(CLBR_ANY)
 ret_from_intr:
-	GET_THREAD_INFO(%ebp)
 #ifdef CONFIG_VM86
 	movl	PT_EFLAGS(%esp), %eax		# mix EFLAGS and CS
 	movb	PT_CS(%esp), %al
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/entry/entry_64_compat.S linux-libre-4.7-gnu/arch/x86/entry/entry_64_compat.S
--- linux-libre-4.6-gnu/arch/x86/entry/entry_64_compat.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/entry/entry_64_compat.S	2016-07-24 15:23:50.000000000 -0400
@@ -72,24 +72,23 @@ ENTRY(entry_SYSENTER_compat)
 	pushfq				/* pt_regs->flags (except IF = 0) */
 	orl	$X86_EFLAGS_IF, (%rsp)	/* Fix saved flags */
 	pushq	$__USER32_CS		/* pt_regs->cs */
-	xorq    %r8,%r8
-	pushq	%r8			/* pt_regs->ip = 0 (placeholder) */
+	pushq	$0			/* pt_regs->ip = 0 (placeholder) */
 	pushq	%rax			/* pt_regs->orig_ax */
 	pushq	%rdi			/* pt_regs->di */
 	pushq	%rsi			/* pt_regs->si */
 	pushq	%rdx			/* pt_regs->dx */
 	pushq	%rcx			/* pt_regs->cx */
 	pushq	$-ENOSYS		/* pt_regs->ax */
-	pushq   %r8                     /* pt_regs->r8  = 0 */
-	pushq   %r8                     /* pt_regs->r9  = 0 */
-	pushq   %r8                     /* pt_regs->r10 = 0 */
-	pushq   %r8                     /* pt_regs->r11 = 0 */
+	pushq   $0			/* pt_regs->r8  = 0 */
+	pushq   $0			/* pt_regs->r9  = 0 */
+	pushq   $0			/* pt_regs->r10 = 0 */
+	pushq   $0			/* pt_regs->r11 = 0 */
 	pushq   %rbx                    /* pt_regs->rbx */
 	pushq   %rbp                    /* pt_regs->rbp (will be overwritten) */
-	pushq   %r8                     /* pt_regs->r12 = 0 */
-	pushq   %r8                     /* pt_regs->r13 = 0 */
-	pushq   %r8                     /* pt_regs->r14 = 0 */
-	pushq   %r8                     /* pt_regs->r15 = 0 */
+	pushq   $0			/* pt_regs->r12 = 0 */
+	pushq   $0			/* pt_regs->r13 = 0 */
+	pushq   $0			/* pt_regs->r14 = 0 */
+	pushq   $0			/* pt_regs->r15 = 0 */
 	cld
 
 	/*
@@ -205,17 +204,16 @@ ENTRY(entry_SYSCALL_compat)
 	pushq	%rdx			/* pt_regs->dx */
 	pushq	%rbp			/* pt_regs->cx (stashed in bp) */
 	pushq	$-ENOSYS		/* pt_regs->ax */
-	xorq    %r8,%r8
-	pushq   %r8                     /* pt_regs->r8  = 0 */
-	pushq   %r8                     /* pt_regs->r9  = 0 */
-	pushq   %r8                     /* pt_regs->r10 = 0 */
-	pushq   %r8                     /* pt_regs->r11 = 0 */
+	pushq   $0			/* pt_regs->r8  = 0 */
+	pushq   $0			/* pt_regs->r9  = 0 */
+	pushq   $0			/* pt_regs->r10 = 0 */
+	pushq   $0			/* pt_regs->r11 = 0 */
 	pushq   %rbx                    /* pt_regs->rbx */
 	pushq   %rbp                    /* pt_regs->rbp (will be overwritten) */
-	pushq   %r8                     /* pt_regs->r12 = 0 */
-	pushq   %r8                     /* pt_regs->r13 = 0 */
-	pushq   %r8                     /* pt_regs->r14 = 0 */
-	pushq   %r8                     /* pt_regs->r15 = 0 */
+	pushq   $0			/* pt_regs->r12 = 0 */
+	pushq   $0			/* pt_regs->r13 = 0 */
+	pushq   $0			/* pt_regs->r14 = 0 */
+	pushq   $0			/* pt_regs->r15 = 0 */
 
 	/*
 	 * User mode is traced as though IRQs are on, and SYSENTER
@@ -316,11 +314,10 @@ ENTRY(entry_INT80_compat)
 	pushq	%rdx			/* pt_regs->dx */
 	pushq	%rcx			/* pt_regs->cx */
 	pushq	$-ENOSYS		/* pt_regs->ax */
-	xorq    %r8,%r8
-	pushq   %r8                     /* pt_regs->r8  = 0 */
-	pushq   %r8                     /* pt_regs->r9  = 0 */
-	pushq   %r8                     /* pt_regs->r10 = 0 */
-	pushq   %r8                     /* pt_regs->r11 = 0 */
+	pushq   $0			/* pt_regs->r8  = 0 */
+	pushq   $0			/* pt_regs->r9  = 0 */
+	pushq   $0			/* pt_regs->r10 = 0 */
+	pushq   $0			/* pt_regs->r11 = 0 */
 	pushq   %rbx                    /* pt_regs->rbx */
 	pushq   %rbp                    /* pt_regs->rbp */
 	pushq   %r12                    /* pt_regs->r12 */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/entry/entry_64.S linux-libre-4.7-gnu/arch/x86/entry/entry_64.S
--- linux-libre-4.6-gnu/arch/x86/entry/entry_64.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/entry/entry_64.S	2016-07-24 15:23:50.000000000 -0400
@@ -372,9 +372,6 @@ END(ptregs_\func)
 ENTRY(ret_from_fork)
 	LOCK ; btr $TIF_FORK, TI_flags(%r8)
 
-	pushq	$0x0002
-	popfq					/* reset kernel eflags */
-
 	call	schedule_tail			/* rdi: 'prev' task parameter */
 
 	testb	$3, CS(%rsp)			/* from kernel_thread? */
@@ -781,19 +778,25 @@ ENTRY(native_load_gs_index)
 	pushfq
 	DISABLE_INTERRUPTS(CLBR_ANY & ~CLBR_RDI)
 	SWAPGS
-gs_change:
+.Lgs_change:
 	movl	%edi, %gs
-2:	mfence					/* workaround */
+2:	ALTERNATIVE "", "mfence", X86_BUG_SWAPGS_FENCE
 	SWAPGS
 	popfq
 	ret
 END(native_load_gs_index)
 
-	_ASM_EXTABLE(gs_change, bad_gs)
+	_ASM_EXTABLE(.Lgs_change, bad_gs)
 	.section .fixup, "ax"
 	/* running with kernelgs */
 bad_gs:
 	SWAPGS					/* switch back to user gs */
+.macro ZAP_GS
+	/* This can't be a string because the preprocessor needs to see it. */
+	movl $__USER_DS, %eax
+	movl %eax, %gs
+.endm
+	ALTERNATIVE "", "ZAP_GS", X86_BUG_NULL_SEG
 	xorl	%eax, %eax
 	movl	%eax, %gs
 	jmp	2b
@@ -1019,13 +1022,13 @@ ENTRY(error_entry)
 	movl	%ecx, %eax			/* zero extend */
 	cmpq	%rax, RIP+8(%rsp)
 	je	.Lbstep_iret
-	cmpq	$gs_change, RIP+8(%rsp)
+	cmpq	$.Lgs_change, RIP+8(%rsp)
 	jne	.Lerror_entry_done
 
 	/*
-	 * hack: gs_change can fail with user gsbase.  If this happens, fix up
+	 * hack: .Lgs_change can fail with user gsbase.  If this happens, fix up
 	 * gsbase and proceed.  We'll fix up the exception and land in
-	 * gs_change's error handler with kernel gsbase.
+	 * .Lgs_change's error handler with kernel gsbase.
 	 */
 	jmp	.Lerror_entry_from_usermode_swapgs
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/entry/syscalls/syscall_64.tbl linux-libre-4.7-gnu/arch/x86/entry/syscalls/syscall_64.tbl
--- linux-libre-4.6-gnu/arch/x86/entry/syscalls/syscall_64.tbl	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/entry/syscalls/syscall_64.tbl	2016-07-24 15:23:50.000000000 -0400
@@ -374,3 +374,5 @@
 543	x32	io_setup		compat_sys_io_setup
 544	x32	io_submit		compat_sys_io_submit
 545	x32	execveat		compat_sys_execveat/ptregs
+534	x32	preadv2			compat_sys_preadv2
+535	x32	pwritev2		compat_sys_pwritev2
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/entry/thunk_64.S linux-libre-4.7-gnu/arch/x86/entry/thunk_64.S
--- linux-libre-4.6-gnu/arch/x86/entry/thunk_64.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/entry/thunk_64.S	2016-07-24 15:23:50.000000000 -0400
@@ -8,16 +8,15 @@
 #include <linux/linkage.h>
 #include "calling.h"
 #include <asm/asm.h>
-#include <asm/frame.h>
 
 	/* rdi:	arg1 ... normal C conventions. rax is saved/restored. */
 	.macro THUNK name, func, put_ret_addr_in_rdi=0
 	.globl \name
 	.type \name, @function
 \name:
-	FRAME_BEGIN
+	pushq %rbp
+	movq %rsp, %rbp
 
-	/* this one pushes 9 elems, the next one would be %rIP */
 	pushq %rdi
 	pushq %rsi
 	pushq %rdx
@@ -29,8 +28,8 @@
 	pushq %r11
 
 	.if \put_ret_addr_in_rdi
-	/* 9*8(%rsp) is return addr on stack */
-	movq 9*8(%rsp), %rdi
+	/* 8(%rbp) is return addr on stack */
+	movq 8(%rbp), %rdi
 	.endif
 
 	call \func
@@ -65,7 +64,7 @@ restore:
 	popq %rdx
 	popq %rsi
 	popq %rdi
-	FRAME_END
+	popq %rbp
 	ret
 	_ASM_NOKPROBE(restore)
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/entry/vdso/Makefile linux-libre-4.7-gnu/arch/x86/entry/vdso/Makefile
--- linux-libre-4.6-gnu/arch/x86/entry/vdso/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/entry/vdso/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -193,10 +193,10 @@ vdso_img_insttargets := $(vdso_img_sodbg
 $(MODLIB)/vdso: FORCE
 	@mkdir -p $(MODLIB)/vdso
 
-$(vdso_img_insttargets): install_%: $(obj)/%.dbg $(MODLIB)/vdso FORCE
+$(vdso_img_insttargets): install_%: $(obj)/%.dbg $(MODLIB)/vdso
 	$(call cmd,vdso_install)
 
 PHONY += vdso_install $(vdso_img_insttargets)
-vdso_install: $(vdso_img_insttargets) FORCE
+vdso_install: $(vdso_img_insttargets)
 
 clean-files := vdso32.so vdso32.so.dbg vdso64* vdso-image-*.c vdsox32.so*
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/entry/vdso/vclock_gettime.c linux-libre-4.7-gnu/arch/x86/entry/vdso/vclock_gettime.c
--- linux-libre-4.6-gnu/arch/x86/entry/vdso/vclock_gettime.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/entry/vdso/vclock_gettime.c	2016-07-24 15:23:50.000000000 -0400
@@ -13,7 +13,6 @@
 
 #include <uapi/linux/time.h>
 #include <asm/vgtod.h>
-#include <asm/hpet.h>
 #include <asm/vvar.h>
 #include <asm/unistd.h>
 #include <asm/msr.h>
@@ -28,16 +27,6 @@ extern int __vdso_clock_gettime(clockid_
 extern int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz);
 extern time_t __vdso_time(time_t *t);
 
-#ifdef CONFIG_HPET_TIMER
-extern u8 hpet_page
-	__attribute__((visibility("hidden")));
-
-static notrace cycle_t vread_hpet(void)
-{
-	return *(const volatile u32 *)(&hpet_page + HPET_COUNTER);
-}
-#endif
-
 #ifdef CONFIG_PARAVIRT_CLOCK
 extern u8 pvclock_page
 	__attribute__((visibility("hidden")));
@@ -195,10 +184,6 @@ notrace static inline u64 vgetsns(int *m
 
 	if (gtod->vclock_mode == VCLOCK_TSC)
 		cycles = vread_tsc();
-#ifdef CONFIG_HPET_TIMER
-	else if (gtod->vclock_mode == VCLOCK_HPET)
-		cycles = vread_hpet();
-#endif
 #ifdef CONFIG_PARAVIRT_CLOCK
 	else if (gtod->vclock_mode == VCLOCK_PVCLOCK)
 		cycles = vread_pvclock(mode);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/entry/vdso/vdso-layout.lds.S linux-libre-4.7-gnu/arch/x86/entry/vdso/vdso-layout.lds.S
--- linux-libre-4.6-gnu/arch/x86/entry/vdso/vdso-layout.lds.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/entry/vdso/vdso-layout.lds.S	2016-07-24 15:23:50.000000000 -0400
@@ -25,7 +25,7 @@ SECTIONS
 	 * segment.
 	 */
 
-	vvar_start = . - 3 * PAGE_SIZE;
+	vvar_start = . - 2 * PAGE_SIZE;
 	vvar_page = vvar_start;
 
 	/* Place all vvars at the offsets in asm/vvar.h. */
@@ -35,8 +35,7 @@ SECTIONS
 #undef __VVAR_KERNEL_LDS
 #undef EMIT_VVAR
 
-	hpet_page = vvar_start + PAGE_SIZE;
-	pvclock_page = vvar_start + 2 * PAGE_SIZE;
+	pvclock_page = vvar_start + PAGE_SIZE;
 
 	. = SIZEOF_HEADERS;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/entry/vdso/vma.c linux-libre-4.7-gnu/arch/x86/entry/vdso/vma.c
--- linux-libre-4.6-gnu/arch/x86/entry/vdso/vma.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/entry/vdso/vma.c	2016-07-24 15:23:50.000000000 -0400
@@ -18,7 +18,6 @@
 #include <asm/vdso.h>
 #include <asm/vvar.h>
 #include <asm/page.h>
-#include <asm/hpet.h>
 #include <asm/desc.h>
 #include <asm/cpufeature.h>
 
@@ -129,16 +128,6 @@ static int vvar_fault(const struct vm_sp
 	if (sym_offset == image->sym_vvar_page) {
 		ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address,
 				    __pa_symbol(&__vvar_page) >> PAGE_SHIFT);
-	} else if (sym_offset == image->sym_hpet_page) {
-#ifdef CONFIG_HPET_TIMER
-		if (hpet_address && vclock_was_used(VCLOCK_HPET)) {
-			ret = vm_insert_pfn_prot(
-				vma,
-				(unsigned long)vmf->virtual_address,
-				hpet_address >> PAGE_SHIFT,
-				pgprot_noncached(PAGE_READONLY));
-		}
-#endif
 	} else if (sym_offset == image->sym_pvclock_page) {
 		struct pvclock_vsyscall_time_info *pvti =
 			pvclock_pvti_cpu0_va();
@@ -174,7 +163,8 @@ static int map_vdso(const struct vdso_im
 		addr = 0;
 	}
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
 
 	addr = get_unmapped_area(NULL, addr,
 				 image->size - image->sym_vvar_start, 0, 0);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/events/amd/uncore.c linux-libre-4.7-gnu/arch/x86/events/amd/uncore.c
--- linux-libre-4.6-gnu/arch/x86/events/amd/uncore.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/events/amd/uncore.c	2016-07-24 15:23:50.000000000 -0400
@@ -263,6 +263,7 @@ static const struct attribute_group *amd
 };
 
 static struct pmu amd_nb_pmu = {
+	.task_ctx_nr	= perf_invalid_context,
 	.attr_groups	= amd_uncore_attr_groups,
 	.name		= "amd_nb",
 	.event_init	= amd_uncore_event_init,
@@ -274,6 +275,7 @@ static struct pmu amd_nb_pmu = {
 };
 
 static struct pmu amd_l2_pmu = {
+	.task_ctx_nr	= perf_invalid_context,
 	.attr_groups	= amd_uncore_attr_groups,
 	.name		= "amd_l2",
 	.event_init	= amd_uncore_event_init,
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/events/core.c linux-libre-4.7-gnu/arch/x86/events/core.c
--- linux-libre-4.6-gnu/arch/x86/events/core.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/events/core.c	2016-07-24 15:23:50.000000000 -0400
@@ -263,7 +263,7 @@ static bool check_hw_exists(void)
 
 msr_fail:
 	pr_cont("Broken PMU hardware detected, using software events only.\n");
-	pr_info("%sFailed to access perfctr msr (MSR %x is %Lx)\n",
+	printk("%sFailed to access perfctr msr (MSR %x is %Lx)\n",
 		boot_cpu_has(X86_FEATURE_HYPERVISOR) ? KERN_INFO : KERN_ERR,
 		reg, val_new);
 
@@ -360,6 +360,9 @@ int x86_add_exclusive(unsigned int what)
 {
 	int i;
 
+	if (x86_pmu.lbr_pt_coexist)
+		return 0;
+
 	if (!atomic_inc_not_zero(&x86_pmu.lbr_exclusive[what])) {
 		mutex_lock(&pmc_reserve_mutex);
 		for (i = 0; i < ARRAY_SIZE(x86_pmu.lbr_exclusive); i++) {
@@ -380,6 +383,9 @@ fail_unlock:
 
 void x86_del_exclusive(unsigned int what)
 {
+	if (x86_pmu.lbr_pt_coexist)
+		return;
+
 	atomic_dec(&x86_pmu.lbr_exclusive[what]);
 	atomic_dec(&active_events);
 }
@@ -1518,7 +1524,7 @@ x86_pmu_notifier(struct notifier_block *
 
 static void __init pmu_check_apic(void)
 {
-	if (cpu_has_apic)
+	if (boot_cpu_has(X86_FEATURE_APIC))
 		return;
 
 	x86_pmu.apic = 0;
@@ -2177,7 +2183,7 @@ void arch_perf_update_userpage(struct pe
 	 * cap_user_time_zero doesn't make sense when we're using a different
 	 * time base for the records.
 	 */
-	if (event->clock == &local_clock) {
+	if (!event->attr.use_clockid) {
 		userpg->cap_user_time_zero = 1;
 		userpg->time_zero = data->cyc2ns_offset;
 	}
@@ -2196,7 +2202,7 @@ static int backtrace_stack(void *data, c
 
 static int backtrace_address(void *data, unsigned long addr, int reliable)
 {
-	struct perf_callchain_entry *entry = data;
+	struct perf_callchain_entry_ctx *entry = data;
 
 	return perf_callchain_store(entry, addr);
 }
@@ -2208,7 +2214,7 @@ static const struct stacktrace_ops backt
 };
 
 void
-perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs)
+perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs)
 {
 	if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
 		/* TODO: We don't support guest os callchain now */
@@ -2262,7 +2268,7 @@ static unsigned long get_segment_base(un
 #include <asm/compat.h>
 
 static inline int
-perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry)
+perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry_ctx *entry)
 {
 	/* 32-bit process in 64-bit kernel. */
 	unsigned long ss_base, cs_base;
@@ -2277,7 +2283,7 @@ perf_callchain_user32(struct pt_regs *re
 
 	fp = compat_ptr(ss_base + regs->bp);
 	pagefault_disable();
-	while (entry->nr < PERF_MAX_STACK_DEPTH) {
+	while (entry->nr < entry->max_stack) {
 		unsigned long bytes;
 		frame.next_frame     = 0;
 		frame.return_address = 0;
@@ -2303,17 +2309,17 @@ perf_callchain_user32(struct pt_regs *re
 }
 #else
 static inline int
-perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry)
+perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry_ctx *entry)
 {
     return 0;
 }
 #endif
 
 void
-perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
+perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs)
 {
 	struct stack_frame frame;
-	const void __user *fp;
+	const unsigned long __user *fp;
 
 	if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
 		/* TODO: We don't support guest os callchain now */
@@ -2326,7 +2332,7 @@ perf_callchain_user(struct perf_callchai
 	if (regs->flags & (X86_VM_MASK | PERF_EFLAGS_VM))
 		return;
 
-	fp = (void __user *)regs->bp;
+	fp = (unsigned long __user *)regs->bp;
 
 	perf_callchain_store(entry, regs->ip);
 
@@ -2337,18 +2343,19 @@ perf_callchain_user(struct perf_callchai
 		return;
 
 	pagefault_disable();
-	while (entry->nr < PERF_MAX_STACK_DEPTH) {
+	while (entry->nr < entry->max_stack) {
 		unsigned long bytes;
+
 		frame.next_frame	     = NULL;
 		frame.return_address = 0;
 
-		if (!access_ok(VERIFY_READ, fp, 16))
+		if (!access_ok(VERIFY_READ, fp, sizeof(*fp) * 2))
 			break;
 
-		bytes = __copy_from_user_nmi(&frame.next_frame, fp, 8);
+		bytes = __copy_from_user_nmi(&frame.next_frame, fp, sizeof(*fp));
 		if (bytes != 0)
 			break;
-		bytes = __copy_from_user_nmi(&frame.return_address, fp+8, 8);
+		bytes = __copy_from_user_nmi(&frame.return_address, fp + 1, sizeof(*fp));
 		if (bytes != 0)
 			break;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/events/intel/bts.c linux-libre-4.7-gnu/arch/x86/events/intel/bts.c
--- linux-libre-4.6-gnu/arch/x86/events/intel/bts.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/events/intel/bts.c	2016-07-24 15:23:50.000000000 -0400
@@ -171,18 +171,6 @@ static void bts_buffer_pad_out(struct bt
 	memset(page_address(phys->page) + index, 0, phys->size - index);
 }
 
-static bool bts_buffer_is_full(struct bts_buffer *buf, struct bts_ctx *bts)
-{
-	if (buf->snapshot)
-		return false;
-
-	if (local_read(&buf->data_size) >= bts->handle.size ||
-	    bts->handle.size - local_read(&buf->data_size) < BTS_RECORD_SIZE)
-		return true;
-
-	return false;
-}
-
 static void bts_update(struct bts_ctx *bts)
 {
 	int cpu = raw_smp_processor_id();
@@ -213,18 +201,15 @@ static void bts_update(struct bts_ctx *b
 	}
 }
 
+static int
+bts_buffer_reset(struct bts_buffer *buf, struct perf_output_handle *handle);
+
 static void __bts_event_start(struct perf_event *event)
 {
 	struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
 	struct bts_buffer *buf = perf_get_aux(&bts->handle);
 	u64 config = 0;
 
-	if (!buf || bts_buffer_is_full(buf, bts))
-		return;
-
-	event->hw.itrace_started = 1;
-	event->hw.state = 0;
-
 	if (!buf->snapshot)
 		config |= ARCH_PERFMON_EVENTSEL_INT;
 	if (!event->attr.exclude_kernel)
@@ -241,16 +226,41 @@ static void __bts_event_start(struct per
 	wmb();
 
 	intel_pmu_enable_bts(config);
+
 }
 
 static void bts_event_start(struct perf_event *event, int flags)
 {
+	struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
 	struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
+	struct bts_buffer *buf;
+
+	buf = perf_aux_output_begin(&bts->handle, event);
+	if (!buf)
+		goto fail_stop;
+
+	if (bts_buffer_reset(buf, &bts->handle))
+		goto fail_end_stop;
+
+	bts->ds_back.bts_buffer_base = cpuc->ds->bts_buffer_base;
+	bts->ds_back.bts_absolute_maximum = cpuc->ds->bts_absolute_maximum;
+	bts->ds_back.bts_interrupt_threshold = cpuc->ds->bts_interrupt_threshold;
+
+	event->hw.itrace_started = 1;
+	event->hw.state = 0;
 
 	__bts_event_start(event);
 
 	/* PMI handler: this counter is running and likely generating PMIs */
 	ACCESS_ONCE(bts->started) = 1;
+
+	return;
+
+fail_end_stop:
+	perf_aux_output_end(&bts->handle, 0, false);
+
+fail_stop:
+	event->hw.state = PERF_HES_STOPPED;
 }
 
 static void __bts_event_stop(struct perf_event *event)
@@ -269,15 +279,32 @@ static void __bts_event_stop(struct perf
 
 static void bts_event_stop(struct perf_event *event, int flags)
 {
+	struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
 	struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
+	struct bts_buffer *buf = perf_get_aux(&bts->handle);
 
 	/* PMI handler: don't restart this counter */
 	ACCESS_ONCE(bts->started) = 0;
 
 	__bts_event_stop(event);
 
-	if (flags & PERF_EF_UPDATE)
+	if (flags & PERF_EF_UPDATE) {
 		bts_update(bts);
+
+		if (buf) {
+			if (buf->snapshot)
+				bts->handle.head =
+					local_xchg(&buf->data_size,
+						   buf->nr_pages << PAGE_SHIFT);
+			perf_aux_output_end(&bts->handle, local_xchg(&buf->data_size, 0),
+					    !!local_xchg(&buf->lost, 0));
+		}
+
+		cpuc->ds->bts_index = bts->ds_back.bts_buffer_base;
+		cpuc->ds->bts_buffer_base = bts->ds_back.bts_buffer_base;
+		cpuc->ds->bts_absolute_maximum = bts->ds_back.bts_absolute_maximum;
+		cpuc->ds->bts_interrupt_threshold = bts->ds_back.bts_interrupt_threshold;
+	}
 }
 
 void intel_bts_enable_local(void)
@@ -417,34 +444,14 @@ int intel_bts_interrupt(void)
 
 static void bts_event_del(struct perf_event *event, int mode)
 {
-	struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
-	struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
-	struct bts_buffer *buf = perf_get_aux(&bts->handle);
-
 	bts_event_stop(event, PERF_EF_UPDATE);
-
-	if (buf) {
-		if (buf->snapshot)
-			bts->handle.head =
-				local_xchg(&buf->data_size,
-					   buf->nr_pages << PAGE_SHIFT);
-		perf_aux_output_end(&bts->handle, local_xchg(&buf->data_size, 0),
-				    !!local_xchg(&buf->lost, 0));
-	}
-
-	cpuc->ds->bts_index = bts->ds_back.bts_buffer_base;
-	cpuc->ds->bts_buffer_base = bts->ds_back.bts_buffer_base;
-	cpuc->ds->bts_absolute_maximum = bts->ds_back.bts_absolute_maximum;
-	cpuc->ds->bts_interrupt_threshold = bts->ds_back.bts_interrupt_threshold;
 }
 
 static int bts_event_add(struct perf_event *event, int mode)
 {
-	struct bts_buffer *buf;
 	struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
 	struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
 	struct hw_perf_event *hwc = &event->hw;
-	int ret = -EBUSY;
 
 	event->hw.state = PERF_HES_STOPPED;
 
@@ -454,26 +461,10 @@ static int bts_event_add(struct perf_eve
 	if (bts->handle.event)
 		return -EBUSY;
 
-	buf = perf_aux_output_begin(&bts->handle, event);
-	if (!buf)
-		return -EINVAL;
-
-	ret = bts_buffer_reset(buf, &bts->handle);
-	if (ret) {
-		perf_aux_output_end(&bts->handle, 0, false);
-		return ret;
-	}
-
-	bts->ds_back.bts_buffer_base = cpuc->ds->bts_buffer_base;
-	bts->ds_back.bts_absolute_maximum = cpuc->ds->bts_absolute_maximum;
-	bts->ds_back.bts_interrupt_threshold = cpuc->ds->bts_interrupt_threshold;
-
 	if (mode & PERF_EF_START) {
 		bts_event_start(event, 0);
-		if (hwc->state & PERF_HES_STOPPED) {
-			bts_event_del(event, 0);
-			return -EBUSY;
-		}
+		if (hwc->state & PERF_HES_STOPPED)
+			return -EINVAL;
 	}
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/events/intel/core.c linux-libre-4.7-gnu/arch/x86/events/intel/core.c
--- linux-libre-4.6-gnu/arch/x86/events/intel/core.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/events/intel/core.c	2016-07-24 15:23:50.000000000 -0400
@@ -115,6 +115,10 @@ static struct event_constraint intel_snb
 	INTEL_UEVENT_CONSTRAINT(0x04a3, 0xf), /* CYCLE_ACTIVITY.CYCLES_NO_DISPATCH */
 	INTEL_UEVENT_CONSTRAINT(0x02a3, 0x4), /* CYCLE_ACTIVITY.CYCLES_L1D_PENDING */
 
+	/*
+	 * When HT is off these events can only run on the bottom 4 counters
+	 * When HT is on, they are impacted by the HT bug and require EXCL access
+	 */
 	INTEL_EXCLEVT_CONSTRAINT(0xd0, 0xf), /* MEM_UOPS_RETIRED.* */
 	INTEL_EXCLEVT_CONSTRAINT(0xd1, 0xf), /* MEM_LOAD_UOPS_RETIRED.* */
 	INTEL_EXCLEVT_CONSTRAINT(0xd2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */
@@ -139,6 +143,10 @@ static struct event_constraint intel_ivb
 	INTEL_UEVENT_CONSTRAINT(0x0ca3, 0x4), /* CYCLE_ACTIVITY.STALLS_L1D_PENDING */
 	INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PREC_DIST */
 
+	/*
+	 * When HT is off these events can only run on the bottom 4 counters
+	 * When HT is on, they are impacted by the HT bug and require EXCL access
+	 */
 	INTEL_EXCLEVT_CONSTRAINT(0xd0, 0xf), /* MEM_UOPS_RETIRED.* */
 	INTEL_EXCLEVT_CONSTRAINT(0xd1, 0xf), /* MEM_LOAD_UOPS_RETIRED.* */
 	INTEL_EXCLEVT_CONSTRAINT(0xd2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */
@@ -182,6 +190,16 @@ struct event_constraint intel_skl_event_
 	FIXED_EVENT_CONSTRAINT(0x003c, 1),	/* CPU_CLK_UNHALTED.CORE */
 	FIXED_EVENT_CONSTRAINT(0x0300, 2),	/* CPU_CLK_UNHALTED.REF */
 	INTEL_UEVENT_CONSTRAINT(0x1c0, 0x2),	/* INST_RETIRED.PREC_DIST */
+
+	/*
+	 * when HT is off, these can only run on the bottom 4 counters
+	 */
+	INTEL_EVENT_CONSTRAINT(0xd0, 0xf),	/* MEM_INST_RETIRED.* */
+	INTEL_EVENT_CONSTRAINT(0xd1, 0xf),	/* MEM_LOAD_RETIRED.* */
+	INTEL_EVENT_CONSTRAINT(0xd2, 0xf),	/* MEM_LOAD_L3_HIT_RETIRED.* */
+	INTEL_EVENT_CONSTRAINT(0xcd, 0xf),	/* MEM_TRANS_RETIRED.* */
+	INTEL_EVENT_CONSTRAINT(0xc6, 0xf),	/* FRONTEND_RETIRED.* */
+
 	EVENT_CONSTRAINT_END
 };
 
@@ -250,6 +268,10 @@ static struct event_constraint intel_hsw
 	/* CYCLE_ACTIVITY.CYCLES_NO_EXECUTE */
 	INTEL_UEVENT_CONSTRAINT(0x04a3, 0xf),
 
+	/*
+	 * When HT is off these events can only run on the bottom 4 counters
+	 * When HT is on, they are impacted by the HT bug and require EXCL access
+	 */
 	INTEL_EXCLEVT_CONSTRAINT(0xd0, 0xf), /* MEM_UOPS_RETIRED.* */
 	INTEL_EXCLEVT_CONSTRAINT(0xd1, 0xf), /* MEM_LOAD_UOPS_RETIRED.* */
 	INTEL_EXCLEVT_CONSTRAINT(0xd2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */
@@ -264,6 +286,13 @@ struct event_constraint intel_bdw_event_
 	FIXED_EVENT_CONSTRAINT(0x0300, 2),	/* CPU_CLK_UNHALTED.REF */
 	INTEL_UEVENT_CONSTRAINT(0x148, 0x4),	/* L1D_PEND_MISS.PENDING */
 	INTEL_UBIT_EVENT_CONSTRAINT(0x8a3, 0x4),	/* CYCLE_ACTIVITY.CYCLES_L1D_MISS */
+	/*
+	 * when HT is off, these can only run on the bottom 4 counters
+	 */
+	INTEL_EVENT_CONSTRAINT(0xd0, 0xf),	/* MEM_INST_RETIRED.* */
+	INTEL_EVENT_CONSTRAINT(0xd1, 0xf),	/* MEM_LOAD_RETIRED.* */
+	INTEL_EVENT_CONSTRAINT(0xd2, 0xf),	/* MEM_LOAD_L3_HIT_RETIRED.* */
+	INTEL_EVENT_CONSTRAINT(0xcd, 0xf),	/* MEM_TRANS_RETIRED.* */
 	EVENT_CONSTRAINT_END
 };
 
@@ -1465,6 +1494,140 @@ static __initconst const u64 slm_hw_cach
  },
 };
 
+static struct extra_reg intel_glm_extra_regs[] __read_mostly = {
+	/* must define OFFCORE_RSP_X first, see intel_fixup_er() */
+	INTEL_UEVENT_EXTRA_REG(0x01b7, MSR_OFFCORE_RSP_0, 0x760005ffbfull, RSP_0),
+	INTEL_UEVENT_EXTRA_REG(0x02b7, MSR_OFFCORE_RSP_1, 0x360005ffbfull, RSP_1),
+	EVENT_EXTRA_END
+};
+
+#define GLM_DEMAND_DATA_RD		BIT_ULL(0)
+#define GLM_DEMAND_RFO			BIT_ULL(1)
+#define GLM_ANY_RESPONSE		BIT_ULL(16)
+#define GLM_SNP_NONE_OR_MISS		BIT_ULL(33)
+#define GLM_DEMAND_READ			GLM_DEMAND_DATA_RD
+#define GLM_DEMAND_WRITE		GLM_DEMAND_RFO
+#define GLM_DEMAND_PREFETCH		(SNB_PF_DATA_RD|SNB_PF_RFO)
+#define GLM_LLC_ACCESS			GLM_ANY_RESPONSE
+#define GLM_SNP_ANY			(GLM_SNP_NONE_OR_MISS|SNB_NO_FWD|SNB_HITM)
+#define GLM_LLC_MISS			(GLM_SNP_ANY|SNB_NON_DRAM)
+
+static __initconst const u64 glm_hw_cache_event_ids
+				[PERF_COUNT_HW_CACHE_MAX]
+				[PERF_COUNT_HW_CACHE_OP_MAX]
+				[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+	[C(L1D)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= 0x81d0,	/* MEM_UOPS_RETIRED.ALL_LOADS */
+			[C(RESULT_MISS)]	= 0x0,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= 0x82d0,	/* MEM_UOPS_RETIRED.ALL_STORES */
+			[C(RESULT_MISS)]	= 0x0,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= 0x0,
+			[C(RESULT_MISS)]	= 0x0,
+		},
+	},
+	[C(L1I)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= 0x0380,	/* ICACHE.ACCESSES */
+			[C(RESULT_MISS)]	= 0x0280,	/* ICACHE.MISSES */
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= -1,
+			[C(RESULT_MISS)]	= -1,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= 0x0,
+			[C(RESULT_MISS)]	= 0x0,
+		},
+	},
+	[C(LL)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= 0x1b7,	/* OFFCORE_RESPONSE */
+			[C(RESULT_MISS)]	= 0x1b7,	/* OFFCORE_RESPONSE */
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= 0x1b7,	/* OFFCORE_RESPONSE */
+			[C(RESULT_MISS)]	= 0x1b7,	/* OFFCORE_RESPONSE */
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= 0x1b7,	/* OFFCORE_RESPONSE */
+			[C(RESULT_MISS)]	= 0x1b7,	/* OFFCORE_RESPONSE */
+		},
+	},
+	[C(DTLB)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= 0x81d0,	/* MEM_UOPS_RETIRED.ALL_LOADS */
+			[C(RESULT_MISS)]	= 0x0,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= 0x82d0,	/* MEM_UOPS_RETIRED.ALL_STORES */
+			[C(RESULT_MISS)]	= 0x0,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= 0x0,
+			[C(RESULT_MISS)]	= 0x0,
+		},
+	},
+	[C(ITLB)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= 0x00c0,	/* INST_RETIRED.ANY_P */
+			[C(RESULT_MISS)]	= 0x0481,	/* ITLB.MISS */
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= -1,
+			[C(RESULT_MISS)]	= -1,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= -1,
+			[C(RESULT_MISS)]	= -1,
+		},
+	},
+	[C(BPU)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= 0x00c4,	/* BR_INST_RETIRED.ALL_BRANCHES */
+			[C(RESULT_MISS)]	= 0x00c5,	/* BR_MISP_RETIRED.ALL_BRANCHES */
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= -1,
+			[C(RESULT_MISS)]	= -1,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= -1,
+			[C(RESULT_MISS)]	= -1,
+		},
+	},
+};
+
+static __initconst const u64 glm_hw_cache_extra_regs
+				[PERF_COUNT_HW_CACHE_MAX]
+				[PERF_COUNT_HW_CACHE_OP_MAX]
+				[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+	[C(LL)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= GLM_DEMAND_READ|
+						  GLM_LLC_ACCESS,
+			[C(RESULT_MISS)]	= GLM_DEMAND_READ|
+						  GLM_LLC_MISS,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= GLM_DEMAND_WRITE|
+						  GLM_LLC_ACCESS,
+			[C(RESULT_MISS)]	= GLM_DEMAND_WRITE|
+						  GLM_LLC_MISS,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= GLM_DEMAND_PREFETCH|
+						  GLM_LLC_ACCESS,
+			[C(RESULT_MISS)]	= GLM_DEMAND_PREFETCH|
+						  GLM_LLC_MISS,
+		},
+	},
+};
+
 #define KNL_OT_L2_HITE		BIT_ULL(19) /* Other Tile L2 Hit */
 #define KNL_OT_L2_HITF		BIT_ULL(20) /* Other Tile L2 Hit */
 #define KNL_MCDRAM_LOCAL	BIT_ULL(21)
@@ -3447,7 +3610,7 @@ __init int intel_pmu_init(void)
 		memcpy(hw_cache_extra_regs, slm_hw_cache_extra_regs,
 		       sizeof(hw_cache_extra_regs));
 
-		intel_pmu_lbr_init_atom();
+		intel_pmu_lbr_init_slm();
 
 		x86_pmu.event_constraints = intel_slm_event_constraints;
 		x86_pmu.pebs_constraints = intel_slm_pebs_event_constraints;
@@ -3456,6 +3619,30 @@ __init int intel_pmu_init(void)
 		pr_cont("Silvermont events, ");
 		break;
 
+	case 92: /* 14nm Atom "Goldmont" */
+	case 95: /* 14nm Atom "Goldmont Denverton" */
+		memcpy(hw_cache_event_ids, glm_hw_cache_event_ids,
+		       sizeof(hw_cache_event_ids));
+		memcpy(hw_cache_extra_regs, glm_hw_cache_extra_regs,
+		       sizeof(hw_cache_extra_regs));
+
+		intel_pmu_lbr_init_skl();
+
+		x86_pmu.event_constraints = intel_slm_event_constraints;
+		x86_pmu.pebs_constraints = intel_glm_pebs_event_constraints;
+		x86_pmu.extra_regs = intel_glm_extra_regs;
+		/*
+		 * It's recommended to use CPU_CLK_UNHALTED.CORE_P + NPEBS
+		 * for precise cycles.
+		 * :pp is identical to :ppp
+		 */
+		x86_pmu.pebs_aliases = NULL;
+		x86_pmu.pebs_prec_dist = true;
+		x86_pmu.lbr_pt_coexist = true;
+		x86_pmu.flags |= PMU_FL_HAS_RSP_1;
+		pr_cont("Goldmont events, ");
+		break;
+
 	case 37: /* 32nm Westmere    */
 	case 44: /* 32nm Westmere-EP */
 	case 47: /* 32nm Westmere-EX */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/events/intel/cstate.c linux-libre-4.7-gnu/arch/x86/events/intel/cstate.c
--- linux-libre-4.6-gnu/arch/x86/events/intel/cstate.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/events/intel/cstate.c	2016-07-24 15:23:50.000000000 -0400
@@ -91,6 +91,8 @@
 #include <asm/cpu_device_id.h>
 #include "../perf_event.h"
 
+MODULE_LICENSE("GPL");
+
 #define DEFINE_CSTATE_FORMAT_ATTR(_var, _name, _format)		\
 static ssize_t __cstate_##_var##_show(struct kobject *kobj,	\
 				struct kobj_attribute *attr,	\
@@ -106,22 +108,27 @@ static ssize_t cstate_get_attr_cpumask(s
 				       struct device_attribute *attr,
 				       char *buf);
 
+/* Model -> events mapping */
+struct cstate_model {
+	unsigned long		core_events;
+	unsigned long		pkg_events;
+	unsigned long		quirks;
+};
+
+/* Quirk flags */
+#define SLM_PKG_C6_USE_C7_MSR	(1UL << 0)
+
 struct perf_cstate_msr {
 	u64	msr;
 	struct	perf_pmu_events_attr *attr;
-	bool	(*test)(int idx);
 };
 
 
 /* cstate_core PMU */
-
 static struct pmu cstate_core_pmu;
 static bool has_cstate_core;
 
-enum perf_cstate_core_id {
-	/*
-	 * cstate_core events
-	 */
+enum perf_cstate_core_events {
 	PERF_CSTATE_CORE_C1_RES = 0,
 	PERF_CSTATE_CORE_C3_RES,
 	PERF_CSTATE_CORE_C6_RES,
@@ -130,69 +137,16 @@ enum perf_cstate_core_id {
 	PERF_CSTATE_CORE_EVENT_MAX,
 };
 
-bool test_core(int idx)
-{
-	if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ||
-	    boot_cpu_data.x86 != 6)
-		return false;
-
-	switch (boot_cpu_data.x86_model) {
-	case 30: /* 45nm Nehalem    */
-	case 26: /* 45nm Nehalem-EP */
-	case 46: /* 45nm Nehalem-EX */
-
-	case 37: /* 32nm Westmere    */
-	case 44: /* 32nm Westmere-EP */
-	case 47: /* 32nm Westmere-EX */
-		if (idx == PERF_CSTATE_CORE_C3_RES ||
-		    idx == PERF_CSTATE_CORE_C6_RES)
-			return true;
-		break;
-	case 42: /* 32nm SandyBridge         */
-	case 45: /* 32nm SandyBridge-E/EN/EP */
-
-	case 58: /* 22nm IvyBridge       */
-	case 62: /* 22nm IvyBridge-EP/EX */
-
-	case 60: /* 22nm Haswell Core */
-	case 63: /* 22nm Haswell Server */
-	case 69: /* 22nm Haswell ULT */
-	case 70: /* 22nm Haswell + GT3e (Intel Iris Pro graphics) */
-
-	case 61: /* 14nm Broadwell Core-M */
-	case 86: /* 14nm Broadwell Xeon D */
-	case 71: /* 14nm Broadwell + GT3e (Intel Iris Pro graphics) */
-	case 79: /* 14nm Broadwell Server */
-
-	case 78: /* 14nm Skylake Mobile */
-	case 94: /* 14nm Skylake Desktop */
-		if (idx == PERF_CSTATE_CORE_C3_RES ||
-		    idx == PERF_CSTATE_CORE_C6_RES ||
-		    idx == PERF_CSTATE_CORE_C7_RES)
-			return true;
-		break;
-	case 55: /* 22nm Atom "Silvermont"                */
-	case 77: /* 22nm Atom "Silvermont Avoton/Rangely" */
-	case 76: /* 14nm Atom "Airmont"                   */
-		if (idx == PERF_CSTATE_CORE_C1_RES ||
-		    idx == PERF_CSTATE_CORE_C6_RES)
-			return true;
-		break;
-	}
-
-	return false;
-}
-
 PMU_EVENT_ATTR_STRING(c1-residency, evattr_cstate_core_c1, "event=0x00");
 PMU_EVENT_ATTR_STRING(c3-residency, evattr_cstate_core_c3, "event=0x01");
 PMU_EVENT_ATTR_STRING(c6-residency, evattr_cstate_core_c6, "event=0x02");
 PMU_EVENT_ATTR_STRING(c7-residency, evattr_cstate_core_c7, "event=0x03");
 
 static struct perf_cstate_msr core_msr[] = {
-	[PERF_CSTATE_CORE_C1_RES] = { MSR_CORE_C1_RES,		&evattr_cstate_core_c1,	test_core, },
-	[PERF_CSTATE_CORE_C3_RES] = { MSR_CORE_C3_RESIDENCY,	&evattr_cstate_core_c3, test_core, },
-	[PERF_CSTATE_CORE_C6_RES] = { MSR_CORE_C6_RESIDENCY,	&evattr_cstate_core_c6, test_core, },
-	[PERF_CSTATE_CORE_C7_RES] = { MSR_CORE_C7_RESIDENCY,	&evattr_cstate_core_c7,	test_core, },
+	[PERF_CSTATE_CORE_C1_RES] = { MSR_CORE_C1_RES,		&evattr_cstate_core_c1 },
+	[PERF_CSTATE_CORE_C3_RES] = { MSR_CORE_C3_RESIDENCY,	&evattr_cstate_core_c3 },
+	[PERF_CSTATE_CORE_C6_RES] = { MSR_CORE_C6_RESIDENCY,	&evattr_cstate_core_c6 },
+	[PERF_CSTATE_CORE_C7_RES] = { MSR_CORE_C7_RESIDENCY,	&evattr_cstate_core_c7 },
 };
 
 static struct attribute *core_events_attrs[PERF_CSTATE_CORE_EVENT_MAX + 1] = {
@@ -234,18 +188,11 @@ static const struct attribute_group *cor
 	NULL,
 };
 
-/* cstate_core PMU end */
-
-
 /* cstate_pkg PMU */
-
 static struct pmu cstate_pkg_pmu;
 static bool has_cstate_pkg;
 
-enum perf_cstate_pkg_id {
-	/*
-	 * cstate_pkg events
-	 */
+enum perf_cstate_pkg_events {
 	PERF_CSTATE_PKG_C2_RES = 0,
 	PERF_CSTATE_PKG_C3_RES,
 	PERF_CSTATE_PKG_C6_RES,
@@ -257,69 +204,6 @@ enum perf_cstate_pkg_id {
 	PERF_CSTATE_PKG_EVENT_MAX,
 };
 
-bool test_pkg(int idx)
-{
-	if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ||
-	    boot_cpu_data.x86 != 6)
-		return false;
-
-	switch (boot_cpu_data.x86_model) {
-	case 30: /* 45nm Nehalem    */
-	case 26: /* 45nm Nehalem-EP */
-	case 46: /* 45nm Nehalem-EX */
-
-	case 37: /* 32nm Westmere    */
-	case 44: /* 32nm Westmere-EP */
-	case 47: /* 32nm Westmere-EX */
-		if (idx == PERF_CSTATE_CORE_C3_RES ||
-		    idx == PERF_CSTATE_CORE_C6_RES ||
-		    idx == PERF_CSTATE_CORE_C7_RES)
-			return true;
-		break;
-	case 42: /* 32nm SandyBridge         */
-	case 45: /* 32nm SandyBridge-E/EN/EP */
-
-	case 58: /* 22nm IvyBridge       */
-	case 62: /* 22nm IvyBridge-EP/EX */
-
-	case 60: /* 22nm Haswell Core */
-	case 63: /* 22nm Haswell Server */
-	case 70: /* 22nm Haswell + GT3e (Intel Iris Pro graphics) */
-
-	case 61: /* 14nm Broadwell Core-M */
-	case 86: /* 14nm Broadwell Xeon D */
-	case 71: /* 14nm Broadwell + GT3e (Intel Iris Pro graphics) */
-	case 79: /* 14nm Broadwell Server */
-
-	case 78: /* 14nm Skylake Mobile */
-	case 94: /* 14nm Skylake Desktop */
-		if (idx == PERF_CSTATE_PKG_C2_RES ||
-		    idx == PERF_CSTATE_PKG_C3_RES ||
-		    idx == PERF_CSTATE_PKG_C6_RES ||
-		    idx == PERF_CSTATE_PKG_C7_RES)
-			return true;
-		break;
-	case 55: /* 22nm Atom "Silvermont"                */
-	case 77: /* 22nm Atom "Silvermont Avoton/Rangely" */
-	case 76: /* 14nm Atom "Airmont"                   */
-		if (idx == PERF_CSTATE_CORE_C6_RES)
-			return true;
-		break;
-	case 69: /* 22nm Haswell ULT */
-		if (idx == PERF_CSTATE_PKG_C2_RES ||
-		    idx == PERF_CSTATE_PKG_C3_RES ||
-		    idx == PERF_CSTATE_PKG_C6_RES ||
-		    idx == PERF_CSTATE_PKG_C7_RES ||
-		    idx == PERF_CSTATE_PKG_C8_RES ||
-		    idx == PERF_CSTATE_PKG_C9_RES ||
-		    idx == PERF_CSTATE_PKG_C10_RES)
-			return true;
-		break;
-	}
-
-	return false;
-}
-
 PMU_EVENT_ATTR_STRING(c2-residency, evattr_cstate_pkg_c2, "event=0x00");
 PMU_EVENT_ATTR_STRING(c3-residency, evattr_cstate_pkg_c3, "event=0x01");
 PMU_EVENT_ATTR_STRING(c6-residency, evattr_cstate_pkg_c6, "event=0x02");
@@ -329,13 +213,13 @@ PMU_EVENT_ATTR_STRING(c9-residency, evat
 PMU_EVENT_ATTR_STRING(c10-residency, evattr_cstate_pkg_c10, "event=0x06");
 
 static struct perf_cstate_msr pkg_msr[] = {
-	[PERF_CSTATE_PKG_C2_RES] = { MSR_PKG_C2_RESIDENCY,	&evattr_cstate_pkg_c2,	test_pkg, },
-	[PERF_CSTATE_PKG_C3_RES] = { MSR_PKG_C3_RESIDENCY,	&evattr_cstate_pkg_c3,	test_pkg, },
-	[PERF_CSTATE_PKG_C6_RES] = { MSR_PKG_C6_RESIDENCY,	&evattr_cstate_pkg_c6,	test_pkg, },
-	[PERF_CSTATE_PKG_C7_RES] = { MSR_PKG_C7_RESIDENCY,	&evattr_cstate_pkg_c7,	test_pkg, },
-	[PERF_CSTATE_PKG_C8_RES] = { MSR_PKG_C8_RESIDENCY,	&evattr_cstate_pkg_c8,	test_pkg, },
-	[PERF_CSTATE_PKG_C9_RES] = { MSR_PKG_C9_RESIDENCY,	&evattr_cstate_pkg_c9,	test_pkg, },
-	[PERF_CSTATE_PKG_C10_RES] = { MSR_PKG_C10_RESIDENCY,	&evattr_cstate_pkg_c10,	test_pkg, },
+	[PERF_CSTATE_PKG_C2_RES] = { MSR_PKG_C2_RESIDENCY,	&evattr_cstate_pkg_c2 },
+	[PERF_CSTATE_PKG_C3_RES] = { MSR_PKG_C3_RESIDENCY,	&evattr_cstate_pkg_c3 },
+	[PERF_CSTATE_PKG_C6_RES] = { MSR_PKG_C6_RESIDENCY,	&evattr_cstate_pkg_c6 },
+	[PERF_CSTATE_PKG_C7_RES] = { MSR_PKG_C7_RESIDENCY,	&evattr_cstate_pkg_c7 },
+	[PERF_CSTATE_PKG_C8_RES] = { MSR_PKG_C8_RESIDENCY,	&evattr_cstate_pkg_c8 },
+	[PERF_CSTATE_PKG_C9_RES] = { MSR_PKG_C9_RESIDENCY,	&evattr_cstate_pkg_c9 },
+	[PERF_CSTATE_PKG_C10_RES] = { MSR_PKG_C10_RESIDENCY,	&evattr_cstate_pkg_c10 },
 };
 
 static struct attribute *pkg_events_attrs[PERF_CSTATE_PKG_EVENT_MAX + 1] = {
@@ -366,8 +250,6 @@ static const struct attribute_group *pkg
 	NULL,
 };
 
-/* cstate_pkg PMU end*/
-
 static ssize_t cstate_get_attr_cpumask(struct device *dev,
 				       struct device_attribute *attr,
 				       char *buf)
@@ -385,7 +267,7 @@ static ssize_t cstate_get_attr_cpumask(s
 static int cstate_pmu_event_init(struct perf_event *event)
 {
 	u64 cfg = event->attr.config;
-	int ret = 0;
+	int cpu;
 
 	if (event->attr.type != event->pmu->type)
 		return -ENOENT;
@@ -400,26 +282,36 @@ static int cstate_pmu_event_init(struct
 	    event->attr.sample_period) /* no sampling */
 		return -EINVAL;
 
+	if (event->cpu < 0)
+		return -EINVAL;
+
 	if (event->pmu == &cstate_core_pmu) {
 		if (cfg >= PERF_CSTATE_CORE_EVENT_MAX)
 			return -EINVAL;
 		if (!core_msr[cfg].attr)
 			return -EINVAL;
 		event->hw.event_base = core_msr[cfg].msr;
+		cpu = cpumask_any_and(&cstate_core_cpu_mask,
+				      topology_sibling_cpumask(event->cpu));
 	} else if (event->pmu == &cstate_pkg_pmu) {
 		if (cfg >= PERF_CSTATE_PKG_EVENT_MAX)
 			return -EINVAL;
 		if (!pkg_msr[cfg].attr)
 			return -EINVAL;
 		event->hw.event_base = pkg_msr[cfg].msr;
-	} else
+		cpu = cpumask_any_and(&cstate_pkg_cpu_mask,
+				      topology_core_cpumask(event->cpu));
+	} else {
 		return -ENOENT;
+	}
 
-	/* must be done before validate_group */
+	if (cpu >= nr_cpu_ids)
+		return -ENODEV;
+
+	event->cpu = cpu;
 	event->hw.config = cfg;
 	event->hw.idx = -1;
-
-	return ret;
+	return 0;
 }
 
 static inline u64 cstate_pmu_read_counter(struct perf_event *event)
@@ -469,172 +361,91 @@ static int cstate_pmu_event_add(struct p
 	return 0;
 }
 
+/*
+ * Check if exiting cpu is the designated reader. If so migrate the
+ * events when there is a valid target available
+ */
 static void cstate_cpu_exit(int cpu)
 {
-	int i, id, target;
+	unsigned int target;
 
-	/* cpu exit for cstate core */
-	if (has_cstate_core) {
-		id = topology_core_id(cpu);
-		target = -1;
+	if (has_cstate_core &&
+	    cpumask_test_and_clear_cpu(cpu, &cstate_core_cpu_mask)) {
 
-		for_each_online_cpu(i) {
-			if (i == cpu)
-				continue;
-			if (id == topology_core_id(i)) {
-				target = i;
-				break;
-			}
-		}
-		if (cpumask_test_and_clear_cpu(cpu, &cstate_core_cpu_mask) && target >= 0)
+		target = cpumask_any_but(topology_sibling_cpumask(cpu), cpu);
+		/* Migrate events if there is a valid target */
+		if (target < nr_cpu_ids) {
 			cpumask_set_cpu(target, &cstate_core_cpu_mask);
-		WARN_ON(cpumask_empty(&cstate_core_cpu_mask));
-		if (target >= 0)
 			perf_pmu_migrate_context(&cstate_core_pmu, cpu, target);
+		}
 	}
 
-	/* cpu exit for cstate pkg */
-	if (has_cstate_pkg) {
-		id = topology_physical_package_id(cpu);
-		target = -1;
+	if (has_cstate_pkg &&
+	    cpumask_test_and_clear_cpu(cpu, &cstate_pkg_cpu_mask)) {
 
-		for_each_online_cpu(i) {
-			if (i == cpu)
-				continue;
-			if (id == topology_physical_package_id(i)) {
-				target = i;
-				break;
-			}
-		}
-		if (cpumask_test_and_clear_cpu(cpu, &cstate_pkg_cpu_mask) && target >= 0)
+		target = cpumask_any_but(topology_core_cpumask(cpu), cpu);
+		/* Migrate events if there is a valid target */
+		if (target < nr_cpu_ids) {
 			cpumask_set_cpu(target, &cstate_pkg_cpu_mask);
-		WARN_ON(cpumask_empty(&cstate_pkg_cpu_mask));
-		if (target >= 0)
 			perf_pmu_migrate_context(&cstate_pkg_pmu, cpu, target);
+		}
 	}
 }
 
 static void cstate_cpu_init(int cpu)
 {
-	int i, id;
+	unsigned int target;
 
-	/* cpu init for cstate core */
-	if (has_cstate_core) {
-		id = topology_core_id(cpu);
-		for_each_cpu(i, &cstate_core_cpu_mask) {
-			if (id == topology_core_id(i))
-				break;
-		}
-		if (i >= nr_cpu_ids)
-			cpumask_set_cpu(cpu, &cstate_core_cpu_mask);
-	}
+	/*
+	 * If this is the first online thread of that core, set it in
+	 * the core cpu mask as the designated reader.
+	 */
+	target = cpumask_any_and(&cstate_core_cpu_mask,
+				 topology_sibling_cpumask(cpu));
 
-	/* cpu init for cstate pkg */
-	if (has_cstate_pkg) {
-		id = topology_physical_package_id(cpu);
-		for_each_cpu(i, &cstate_pkg_cpu_mask) {
-			if (id == topology_physical_package_id(i))
-				break;
-		}
-		if (i >= nr_cpu_ids)
-			cpumask_set_cpu(cpu, &cstate_pkg_cpu_mask);
-	}
+	if (has_cstate_core && target >= nr_cpu_ids)
+		cpumask_set_cpu(cpu, &cstate_core_cpu_mask);
+
+	/*
+	 * If this is the first online thread of that package, set it
+	 * in the package cpu mask as the designated reader.
+	 */
+	target = cpumask_any_and(&cstate_pkg_cpu_mask,
+				 topology_core_cpumask(cpu));
+	if (has_cstate_pkg && target >= nr_cpu_ids)
+		cpumask_set_cpu(cpu, &cstate_pkg_cpu_mask);
 }
 
 static int cstate_cpu_notifier(struct notifier_block *self,
-				  unsigned long action, void *hcpu)
+			       unsigned long action, void *hcpu)
 {
 	unsigned int cpu = (long)hcpu;
 
 	switch (action & ~CPU_TASKS_FROZEN) {
-	case CPU_UP_PREPARE:
-		break;
 	case CPU_STARTING:
 		cstate_cpu_init(cpu);
 		break;
-	case CPU_UP_CANCELED:
-	case CPU_DYING:
-		break;
-	case CPU_ONLINE:
-	case CPU_DEAD:
-		break;
 	case CPU_DOWN_PREPARE:
 		cstate_cpu_exit(cpu);
 		break;
 	default:
 		break;
 	}
-
 	return NOTIFY_OK;
 }
 
-/*
- * Probe the cstate events and insert the available one into sysfs attrs
- * Return false if there is no available events.
- */
-static bool cstate_probe_msr(struct perf_cstate_msr *msr,
-			     struct attribute	**events_attrs,
-			     int max_event_nr)
-{
-	int i, j = 0;
-	u64 val;
-
-	/* Probe the cstate events. */
-	for (i = 0; i < max_event_nr; i++) {
-		if (!msr[i].test(i) || rdmsrl_safe(msr[i].msr, &val))
-			msr[i].attr = NULL;
-	}
-
-	/* List remaining events in the sysfs attrs. */
-	for (i = 0; i < max_event_nr; i++) {
-		if (msr[i].attr)
-			events_attrs[j++] = &msr[i].attr->attr.attr;
-	}
-	events_attrs[j] = NULL;
-
-	return (j > 0) ? true : false;
-}
-
-static int __init cstate_init(void)
-{
-	/* SLM has different MSR for PKG C6 */
-	switch (boot_cpu_data.x86_model) {
-	case 55:
-	case 76:
-	case 77:
-		pkg_msr[PERF_CSTATE_PKG_C6_RES].msr = MSR_PKG_C7_RESIDENCY;
-	}
-
-	if (cstate_probe_msr(core_msr, core_events_attrs, PERF_CSTATE_CORE_EVENT_MAX))
-		has_cstate_core = true;
-
-	if (cstate_probe_msr(pkg_msr, pkg_events_attrs, PERF_CSTATE_PKG_EVENT_MAX))
-		has_cstate_pkg = true;
-
-	return (has_cstate_core || has_cstate_pkg) ? 0 : -ENODEV;
-}
-
-static void __init cstate_cpumask_init(void)
-{
-	int cpu;
-
-	cpu_notifier_register_begin();
-
-	for_each_online_cpu(cpu)
-		cstate_cpu_init(cpu);
-
-	__perf_cpu_notifier(cstate_cpu_notifier);
-
-	cpu_notifier_register_done();
-}
+static struct notifier_block cstate_cpu_nb = {
+	.notifier_call	= cstate_cpu_notifier,
+	.priority       = CPU_PRI_PERF + 1,
+};
 
 static struct pmu cstate_core_pmu = {
 	.attr_groups	= core_attr_groups,
 	.name		= "cstate_core",
 	.task_ctx_nr	= perf_invalid_context,
 	.event_init	= cstate_pmu_event_init,
-	.add		= cstate_pmu_event_add, /* must have */
-	.del		= cstate_pmu_event_del, /* must have */
+	.add		= cstate_pmu_event_add,
+	.del		= cstate_pmu_event_del,
 	.start		= cstate_pmu_event_start,
 	.stop		= cstate_pmu_event_stop,
 	.read		= cstate_pmu_event_update,
@@ -646,49 +457,203 @@ static struct pmu cstate_pkg_pmu = {
 	.name		= "cstate_pkg",
 	.task_ctx_nr	= perf_invalid_context,
 	.event_init	= cstate_pmu_event_init,
-	.add		= cstate_pmu_event_add, /* must have */
-	.del		= cstate_pmu_event_del, /* must have */
+	.add		= cstate_pmu_event_add,
+	.del		= cstate_pmu_event_del,
 	.start		= cstate_pmu_event_start,
 	.stop		= cstate_pmu_event_stop,
 	.read		= cstate_pmu_event_update,
 	.capabilities	= PERF_PMU_CAP_NO_INTERRUPT,
 };
 
-static void __init cstate_pmus_register(void)
+static const struct cstate_model nhm_cstates __initconst = {
+	.core_events		= BIT(PERF_CSTATE_CORE_C3_RES) |
+				  BIT(PERF_CSTATE_CORE_C6_RES),
+
+	.pkg_events		= BIT(PERF_CSTATE_PKG_C3_RES) |
+				  BIT(PERF_CSTATE_PKG_C6_RES) |
+				  BIT(PERF_CSTATE_PKG_C7_RES),
+};
+
+static const struct cstate_model snb_cstates __initconst = {
+	.core_events		= BIT(PERF_CSTATE_CORE_C3_RES) |
+				  BIT(PERF_CSTATE_CORE_C6_RES) |
+				  BIT(PERF_CSTATE_CORE_C7_RES),
+
+	.pkg_events		= BIT(PERF_CSTATE_PKG_C2_RES) |
+				  BIT(PERF_CSTATE_PKG_C3_RES) |
+				  BIT(PERF_CSTATE_PKG_C6_RES) |
+				  BIT(PERF_CSTATE_PKG_C7_RES),
+};
+
+static const struct cstate_model hswult_cstates __initconst = {
+	.core_events		= BIT(PERF_CSTATE_CORE_C3_RES) |
+				  BIT(PERF_CSTATE_CORE_C6_RES) |
+				  BIT(PERF_CSTATE_CORE_C7_RES),
+
+	.pkg_events		= BIT(PERF_CSTATE_PKG_C2_RES) |
+				  BIT(PERF_CSTATE_PKG_C3_RES) |
+				  BIT(PERF_CSTATE_PKG_C6_RES) |
+				  BIT(PERF_CSTATE_PKG_C7_RES) |
+				  BIT(PERF_CSTATE_PKG_C8_RES) |
+				  BIT(PERF_CSTATE_PKG_C9_RES) |
+				  BIT(PERF_CSTATE_PKG_C10_RES),
+};
+
+static const struct cstate_model slm_cstates __initconst = {
+	.core_events		= BIT(PERF_CSTATE_CORE_C1_RES) |
+				  BIT(PERF_CSTATE_CORE_C6_RES),
+
+	.pkg_events		= BIT(PERF_CSTATE_PKG_C6_RES),
+	.quirks			= SLM_PKG_C6_USE_C7_MSR,
+};
+
+#define X86_CSTATES_MODEL(model, states)				\
+	{ X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long) &(states) }
+
+static const struct x86_cpu_id intel_cstates_match[] __initconst = {
+	X86_CSTATES_MODEL(30, nhm_cstates),    /* 45nm Nehalem              */
+	X86_CSTATES_MODEL(26, nhm_cstates),    /* 45nm Nehalem-EP           */
+	X86_CSTATES_MODEL(46, nhm_cstates),    /* 45nm Nehalem-EX           */
+
+	X86_CSTATES_MODEL(37, nhm_cstates),    /* 32nm Westmere             */
+	X86_CSTATES_MODEL(44, nhm_cstates),    /* 32nm Westmere-EP          */
+	X86_CSTATES_MODEL(47, nhm_cstates),    /* 32nm Westmere-EX          */
+
+	X86_CSTATES_MODEL(42, snb_cstates),    /* 32nm SandyBridge          */
+	X86_CSTATES_MODEL(45, snb_cstates),    /* 32nm SandyBridge-E/EN/EP  */
+
+	X86_CSTATES_MODEL(58, snb_cstates),    /* 22nm IvyBridge            */
+	X86_CSTATES_MODEL(62, snb_cstates),    /* 22nm IvyBridge-EP/EX      */
+
+	X86_CSTATES_MODEL(60, snb_cstates),    /* 22nm Haswell Core         */
+	X86_CSTATES_MODEL(63, snb_cstates),    /* 22nm Haswell Server       */
+	X86_CSTATES_MODEL(70, snb_cstates),    /* 22nm Haswell + GT3e       */
+
+	X86_CSTATES_MODEL(69, hswult_cstates), /* 22nm Haswell ULT          */
+
+	X86_CSTATES_MODEL(55, slm_cstates),    /* 22nm Atom Silvermont      */
+	X86_CSTATES_MODEL(77, slm_cstates),    /* 22nm Atom Avoton/Rangely  */
+	X86_CSTATES_MODEL(76, slm_cstates),    /* 22nm Atom Airmont         */
+
+	X86_CSTATES_MODEL(61, snb_cstates),    /* 14nm Broadwell Core-M     */
+	X86_CSTATES_MODEL(86, snb_cstates),    /* 14nm Broadwell Xeon D     */
+	X86_CSTATES_MODEL(71, snb_cstates),    /* 14nm Broadwell + GT3e     */
+	X86_CSTATES_MODEL(79, snb_cstates),    /* 14nm Broadwell Server     */
+
+	X86_CSTATES_MODEL(78, snb_cstates),    /* 14nm Skylake Mobile       */
+	X86_CSTATES_MODEL(94, snb_cstates),    /* 14nm Skylake Desktop      */
+	{ },
+};
+MODULE_DEVICE_TABLE(x86cpu, intel_cstates_match);
+
+/*
+ * Probe the cstate events and insert the available one into sysfs attrs
+ * Return false if there are no available events.
+ */
+static bool __init cstate_probe_msr(const unsigned long evmsk, int max,
+                                   struct perf_cstate_msr *msr,
+                                   struct attribute **attrs)
 {
-	int err;
+	bool found = false;
+	unsigned int bit;
+	u64 val;
+
+	for (bit = 0; bit < max; bit++) {
+		if (test_bit(bit, &evmsk) && !rdmsrl_safe(msr[bit].msr, &val)) {
+			*attrs++ = &msr[bit].attr->attr.attr;
+			found = true;
+		} else {
+			msr[bit].attr = NULL;
+		}
+	}
+	*attrs = NULL;
+
+	return found;
+}
+
+static int __init cstate_probe(const struct cstate_model *cm)
+{
+	/* SLM has different MSR for PKG C6 */
+	if (cm->quirks & SLM_PKG_C6_USE_C7_MSR)
+		pkg_msr[PERF_CSTATE_PKG_C6_RES].msr = MSR_PKG_C7_RESIDENCY;
+
+	has_cstate_core = cstate_probe_msr(cm->core_events,
+					   PERF_CSTATE_CORE_EVENT_MAX,
+					   core_msr, core_events_attrs);
+
+	has_cstate_pkg = cstate_probe_msr(cm->pkg_events,
+					  PERF_CSTATE_PKG_EVENT_MAX,
+					  pkg_msr, pkg_events_attrs);
+
+	return (has_cstate_core || has_cstate_pkg) ? 0 : -ENODEV;
+}
+
+static inline void cstate_cleanup(void)
+{
+	if (has_cstate_core)
+		perf_pmu_unregister(&cstate_core_pmu);
+
+	if (has_cstate_pkg)
+		perf_pmu_unregister(&cstate_pkg_pmu);
+}
+
+static int __init cstate_init(void)
+{
+	int cpu, err;
+
+	cpu_notifier_register_begin();
+	for_each_online_cpu(cpu)
+		cstate_cpu_init(cpu);
 
 	if (has_cstate_core) {
 		err = perf_pmu_register(&cstate_core_pmu, cstate_core_pmu.name, -1);
-		if (WARN_ON(err))
-			pr_info("Failed to register PMU %s error %d\n",
-				cstate_core_pmu.name, err);
+		if (err) {
+			has_cstate_core = false;
+			pr_info("Failed to register cstate core pmu\n");
+			goto out;
+		}
 	}
 
 	if (has_cstate_pkg) {
 		err = perf_pmu_register(&cstate_pkg_pmu, cstate_pkg_pmu.name, -1);
-		if (WARN_ON(err))
-			pr_info("Failed to register PMU %s error %d\n",
-				cstate_pkg_pmu.name, err);
+		if (err) {
+			has_cstate_pkg = false;
+			pr_info("Failed to register cstate pkg pmu\n");
+			cstate_cleanup();
+			goto out;
+		}
 	}
+	__register_cpu_notifier(&cstate_cpu_nb);
+out:
+	cpu_notifier_register_done();
+	return err;
 }
 
 static int __init cstate_pmu_init(void)
 {
+	const struct x86_cpu_id *id;
 	int err;
 
-	if (cpu_has_hypervisor)
+	if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
 		return -ENODEV;
 
-	err = cstate_init();
+	id = x86_match_cpu(intel_cstates_match);
+	if (!id)
+		return -ENODEV;
+
+	err = cstate_probe((const struct cstate_model *) id->driver_data);
 	if (err)
 		return err;
 
-	cstate_cpumask_init();
-
-	cstate_pmus_register();
-
-	return 0;
+	return cstate_init();
 }
+module_init(cstate_pmu_init);
 
-device_initcall(cstate_pmu_init);
+static void __exit cstate_pmu_exit(void)
+{
+	cpu_notifier_register_begin();
+	__unregister_cpu_notifier(&cstate_cpu_nb);
+	cstate_cleanup();
+	cpu_notifier_register_done();
+}
+module_exit(cstate_pmu_exit);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/events/intel/ds.c linux-libre-4.7-gnu/arch/x86/events/intel/ds.c
--- linux-libre-4.6-gnu/arch/x86/events/intel/ds.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/events/intel/ds.c	2016-07-24 15:23:50.000000000 -0400
@@ -645,6 +645,12 @@ struct event_constraint intel_slm_pebs_e
 	EVENT_CONSTRAINT_END
 };
 
+struct event_constraint intel_glm_pebs_event_constraints[] = {
+	/* Allow all events as PEBS with no flags */
+	INTEL_ALL_EVENT_CONSTRAINT(0, 0x1),
+	EVENT_CONSTRAINT_END
+};
+
 struct event_constraint intel_nehalem_pebs_event_constraints[] = {
 	INTEL_PLD_CONSTRAINT(0x100b, 0xf),      /* MEM_INST_RETIRED.* */
 	INTEL_FLAGS_EVENT_CONSTRAINT(0x0f, 0xf),    /* MEM_UNCORE_RETIRED.* */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/events/intel/lbr.c linux-libre-4.7-gnu/arch/x86/events/intel/lbr.c
--- linux-libre-4.6-gnu/arch/x86/events/intel/lbr.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/events/intel/lbr.c	2016-07-24 15:23:50.000000000 -0400
@@ -14,7 +14,8 @@ enum {
 	LBR_FORMAT_EIP_FLAGS	= 0x03,
 	LBR_FORMAT_EIP_FLAGS2	= 0x04,
 	LBR_FORMAT_INFO		= 0x05,
-	LBR_FORMAT_MAX_KNOWN    = LBR_FORMAT_INFO,
+	LBR_FORMAT_TIME		= 0x06,
+	LBR_FORMAT_MAX_KNOWN    = LBR_FORMAT_TIME,
 };
 
 static enum {
@@ -464,6 +465,16 @@ static void intel_pmu_lbr_read_64(struct
 			abort = !!(info & LBR_INFO_ABORT);
 			cycles = (info & LBR_INFO_CYCLES);
 		}
+
+		if (lbr_format == LBR_FORMAT_TIME) {
+			mis = !!(from & LBR_FROM_FLAG_MISPRED);
+			pred = !mis;
+			skip = 1;
+			cycles = ((to >> 48) & LBR_INFO_CYCLES);
+
+			to = (u64)((((s64)to) << 16) >> 16);
+		}
+
 		if (lbr_flags & LBR_EIP_FLAGS) {
 			mis = !!(from & LBR_FROM_FLAG_MISPRED);
 			pred = !mis;
@@ -1044,6 +1055,24 @@ void __init intel_pmu_lbr_init_atom(void
 
 	/*
 	 * SW branch filter usage:
+	 * - compensate for lack of HW filter
+	 */
+	pr_cont("8-deep LBR, ");
+}
+
+/* slm */
+void __init intel_pmu_lbr_init_slm(void)
+{
+	x86_pmu.lbr_nr	   = 8;
+	x86_pmu.lbr_tos    = MSR_LBR_TOS;
+	x86_pmu.lbr_from   = MSR_LBR_CORE_FROM;
+	x86_pmu.lbr_to     = MSR_LBR_CORE_TO;
+
+	x86_pmu.lbr_sel_mask = LBR_SEL_MASK;
+	x86_pmu.lbr_sel_map  = nhm_lbr_sel_map;
+
+	/*
+	 * SW branch filter usage:
 	 * - compensate for lack of HW filter
 	 */
 	pr_cont("8-deep LBR, ");
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/events/intel/Makefile linux-libre-4.7-gnu/arch/x86/events/intel/Makefile
--- linux-libre-4.6-gnu/arch/x86/events/intel/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/x86/events/intel/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,9 @@
+obj-$(CONFIG_CPU_SUP_INTEL)		+= core.o bts.o cqm.o
+obj-$(CONFIG_CPU_SUP_INTEL)		+= ds.o knc.o
+obj-$(CONFIG_CPU_SUP_INTEL)		+= lbr.o p4.o p6.o pt.o
+obj-$(CONFIG_PERF_EVENTS_INTEL_RAPL)	+= intel-rapl-perf.o
+intel-rapl-perf-objs			:= rapl.o
+obj-$(CONFIG_PERF_EVENTS_INTEL_UNCORE)	+= intel-uncore.o
+intel-uncore-objs			:= uncore.o uncore_nhmex.o uncore_snb.o uncore_snbep.o
+obj-$(CONFIG_PERF_EVENTS_INTEL_CSTATE)	+= intel-cstate.o
+intel-cstate-objs			:= cstate.o
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/events/intel/p4.c linux-libre-4.7-gnu/arch/x86/events/intel/p4.c
--- linux-libre-4.6-gnu/arch/x86/events/intel/p4.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/events/intel/p4.c	2016-07-24 15:23:50.000000000 -0400
@@ -826,7 +826,7 @@ static int p4_hw_config(struct perf_even
 		 * Clear bits we reserve to be managed by kernel itself
 		 * and never allowed from a user space
 		 */
-		 event->attr.config &= P4_CONFIG_MASK;
+		event->attr.config &= P4_CONFIG_MASK;
 
 		rc = p4_validate_raw_event(event);
 		if (rc)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/events/intel/pt.c linux-libre-4.7-gnu/arch/x86/events/intel/pt.c
--- linux-libre-4.6-gnu/arch/x86/events/intel/pt.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/events/intel/pt.c	2016-07-24 15:23:50.000000000 -0400
@@ -67,11 +67,13 @@ static struct pt_cap_desc {
 	PT_CAP(max_subleaf,		0, CR_EAX, 0xffffffff),
 	PT_CAP(cr3_filtering,		0, CR_EBX, BIT(0)),
 	PT_CAP(psb_cyc,			0, CR_EBX, BIT(1)),
+	PT_CAP(ip_filtering,		0, CR_EBX, BIT(2)),
 	PT_CAP(mtc,			0, CR_EBX, BIT(3)),
 	PT_CAP(topa_output,		0, CR_ECX, BIT(0)),
 	PT_CAP(topa_multiple_entries,	0, CR_ECX, BIT(1)),
 	PT_CAP(single_range_output,	0, CR_ECX, BIT(2)),
 	PT_CAP(payloads_lip,		0, CR_ECX, BIT(31)),
+	PT_CAP(num_address_ranges,	1, CR_EAX, 0x3),
 	PT_CAP(mtc_periods,		1, CR_EAX, 0xffff0000),
 	PT_CAP(cycle_thresholds,	1, CR_EBX, 0xffff),
 	PT_CAP(psb_periods,		1, CR_EBX, 0xffff0000),
@@ -125,9 +127,46 @@ static struct attribute_group pt_format_
 	.attrs	= pt_formats_attr,
 };
 
+static ssize_t
+pt_timing_attr_show(struct device *dev, struct device_attribute *attr,
+		    char *page)
+{
+	struct perf_pmu_events_attr *pmu_attr =
+		container_of(attr, struct perf_pmu_events_attr, attr);
+
+	switch (pmu_attr->id) {
+	case 0:
+		return sprintf(page, "%lu\n", pt_pmu.max_nonturbo_ratio);
+	case 1:
+		return sprintf(page, "%u:%u\n",
+			       pt_pmu.tsc_art_num,
+			       pt_pmu.tsc_art_den);
+	default:
+		break;
+	}
+
+	return -EINVAL;
+}
+
+PMU_EVENT_ATTR(max_nonturbo_ratio, timing_attr_max_nonturbo_ratio, 0,
+	       pt_timing_attr_show);
+PMU_EVENT_ATTR(tsc_art_ratio, timing_attr_tsc_art_ratio, 1,
+	       pt_timing_attr_show);
+
+static struct attribute *pt_timing_attr[] = {
+	&timing_attr_max_nonturbo_ratio.attr.attr,
+	&timing_attr_tsc_art_ratio.attr.attr,
+	NULL,
+};
+
+static struct attribute_group pt_timing_group = {
+	.attrs	= pt_timing_attr,
+};
+
 static const struct attribute_group *pt_attr_groups[] = {
 	&pt_cap_group,
 	&pt_format_group,
+	&pt_timing_group,
 	NULL,
 };
 
@@ -140,6 +179,23 @@ static int __init pt_pmu_hw_init(void)
 	int ret;
 	long i;
 
+	rdmsrl(MSR_PLATFORM_INFO, reg);
+	pt_pmu.max_nonturbo_ratio = (reg & 0xff00) >> 8;
+
+	/*
+	 * if available, read in TSC to core crystal clock ratio,
+	 * otherwise, zero for numerator stands for "not enumerated"
+	 * as per SDM
+	 */
+	if (boot_cpu_data.cpuid_level >= CPUID_TSC_LEAF) {
+		u32 eax, ebx, ecx, edx;
+
+		cpuid(CPUID_TSC_LEAF, &eax, &ebx, &ecx, &edx);
+
+		pt_pmu.tsc_art_num = ebx;
+		pt_pmu.tsc_art_den = eax;
+	}
+
 	if (boot_cpu_has(X86_FEATURE_VMX)) {
 		/*
 		 * Intel SDM, 36.5 "Tracing post-VMXON" says that
@@ -263,6 +319,75 @@ static bool pt_event_valid(struct perf_e
  * These all are cpu affine and operate on a local PT
  */
 
+/* Address ranges and their corresponding msr configuration registers */
+static const struct pt_address_range {
+	unsigned long	msr_a;
+	unsigned long	msr_b;
+	unsigned int	reg_off;
+} pt_address_ranges[] = {
+	{
+		.msr_a	 = MSR_IA32_RTIT_ADDR0_A,
+		.msr_b	 = MSR_IA32_RTIT_ADDR0_B,
+		.reg_off = RTIT_CTL_ADDR0_OFFSET,
+	},
+	{
+		.msr_a	 = MSR_IA32_RTIT_ADDR1_A,
+		.msr_b	 = MSR_IA32_RTIT_ADDR1_B,
+		.reg_off = RTIT_CTL_ADDR1_OFFSET,
+	},
+	{
+		.msr_a	 = MSR_IA32_RTIT_ADDR2_A,
+		.msr_b	 = MSR_IA32_RTIT_ADDR2_B,
+		.reg_off = RTIT_CTL_ADDR2_OFFSET,
+	},
+	{
+		.msr_a	 = MSR_IA32_RTIT_ADDR3_A,
+		.msr_b	 = MSR_IA32_RTIT_ADDR3_B,
+		.reg_off = RTIT_CTL_ADDR3_OFFSET,
+	}
+};
+
+static u64 pt_config_filters(struct perf_event *event)
+{
+	struct pt_filters *filters = event->hw.addr_filters;
+	struct pt *pt = this_cpu_ptr(&pt_ctx);
+	unsigned int range = 0;
+	u64 rtit_ctl = 0;
+
+	if (!filters)
+		return 0;
+
+	perf_event_addr_filters_sync(event);
+
+	for (range = 0; range < filters->nr_filters; range++) {
+		struct pt_filter *filter = &filters->filter[range];
+
+		/*
+		 * Note, if the range has zero start/end addresses due
+		 * to its dynamic object not being loaded yet, we just
+		 * go ahead and program zeroed range, which will simply
+		 * produce no data. Note^2: if executable code at 0x0
+		 * is a concern, we can set up an "invalid" configuration
+		 * such as msr_b < msr_a.
+		 */
+
+		/* avoid redundant msr writes */
+		if (pt->filters.filter[range].msr_a != filter->msr_a) {
+			wrmsrl(pt_address_ranges[range].msr_a, filter->msr_a);
+			pt->filters.filter[range].msr_a = filter->msr_a;
+		}
+
+		if (pt->filters.filter[range].msr_b != filter->msr_b) {
+			wrmsrl(pt_address_ranges[range].msr_b, filter->msr_b);
+			pt->filters.filter[range].msr_b = filter->msr_b;
+		}
+
+		rtit_ctl |= filter->config << pt_address_ranges[range].reg_off;
+	}
+
+	return rtit_ctl;
+}
+
 static void pt_config(struct perf_event *event)
 {
 	u64 reg;
@@ -272,7 +397,8 @@ static void pt_config(struct perf_event
 		wrmsrl(MSR_IA32_RTIT_STATUS, 0);
 	}
 
-	reg = RTIT_CTL_TOPA | RTIT_CTL_BRANCH_EN | RTIT_CTL_TRACEEN;
+	reg = pt_config_filters(event);
+	reg |= RTIT_CTL_TOPA | RTIT_CTL_BRANCH_EN | RTIT_CTL_TRACEEN;
 
 	if (!event->attr.exclude_kernel)
 		reg |= RTIT_CTL_OS;
@@ -921,24 +1047,80 @@ static void pt_buffer_free_aux(void *dat
 	kfree(buf);
 }
 
-/**
- * pt_buffer_is_full() - check if the buffer is full
- * @buf:	PT buffer.
- * @pt:		Per-cpu pt handle.
- *
- * If the user hasn't read data from the output region that aux_head
- * points to, the buffer is considered full: the user needs to read at
- * least this region and update aux_tail to point past it.
- */
-static bool pt_buffer_is_full(struct pt_buffer *buf, struct pt *pt)
+static int pt_addr_filters_init(struct perf_event *event)
 {
-	if (buf->snapshot)
-		return false;
+	struct pt_filters *filters;
+	int node = event->cpu == -1 ? -1 : cpu_to_node(event->cpu);
 
-	if (local_read(&buf->data_size) >= pt->handle.size)
-		return true;
+	if (!pt_cap_get(PT_CAP_num_address_ranges))
+		return 0;
 
-	return false;
+	filters = kzalloc_node(sizeof(struct pt_filters), GFP_KERNEL, node);
+	if (!filters)
+		return -ENOMEM;
+
+	if (event->parent)
+		memcpy(filters, event->parent->hw.addr_filters,
+		       sizeof(*filters));
+
+	event->hw.addr_filters = filters;
+
+	return 0;
+}
+
+static void pt_addr_filters_fini(struct perf_event *event)
+{
+	kfree(event->hw.addr_filters);
+	event->hw.addr_filters = NULL;
+}
+
+static int pt_event_addr_filters_validate(struct list_head *filters)
+{
+	struct perf_addr_filter *filter;
+	int range = 0;
+
+	list_for_each_entry(filter, filters, entry) {
+		/* PT doesn't support single address triggers */
+		if (!filter->range)
+			return -EOPNOTSUPP;
+
+		if (!filter->inode && !kernel_ip(filter->offset))
+			return -EINVAL;
+
+		if (++range > pt_cap_get(PT_CAP_num_address_ranges))
+			return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+static void pt_event_addr_filters_sync(struct perf_event *event)
+{
+	struct perf_addr_filters_head *head = perf_event_addr_filters(event);
+	unsigned long msr_a, msr_b, *offs = event->addr_filters_offs;
+	struct pt_filters *filters = event->hw.addr_filters;
+	struct perf_addr_filter *filter;
+	int range = 0;
+
+	if (!filters)
+		return;
+
+	list_for_each_entry(filter, &head->list, entry) {
+		if (filter->inode && !offs[range]) {
+			msr_a = msr_b = 0;
+		} else {
+			/* apply the offset */
+			msr_a = filter->offset + offs[range];
+			msr_b = filter->size + msr_a;
+		}
+
+		filters->filter[range].msr_a  = msr_a;
+		filters->filter[range].msr_b  = msr_b;
+		filters->filter[range].config = filter->filter ? 1 : 2;
+		range++;
+	}
+
+	filters->nr_filters = range;
 }
 
 /**
@@ -955,7 +1137,7 @@ void intel_pt_interrupt(void)
 	 * after PT has been disabled by pt_event_stop(). Make sure we don't
 	 * do anything (particularly, re-enable) for this event here.
 	 */
-	if (!ACCESS_ONCE(pt->handle_nmi))
+	if (!READ_ONCE(pt->handle_nmi))
 		return;
 
 	/*
@@ -1040,23 +1222,36 @@ EXPORT_SYMBOL_GPL(intel_pt_handle_vmx);
 
 static void pt_event_start(struct perf_event *event, int mode)
 {
+	struct hw_perf_event *hwc = &event->hw;
 	struct pt *pt = this_cpu_ptr(&pt_ctx);
-	struct pt_buffer *buf = perf_get_aux(&pt->handle);
+	struct pt_buffer *buf;
 
 	if (READ_ONCE(pt->vmx_on))
 		return;
 
-	if (!buf || pt_buffer_is_full(buf, pt)) {
-		event->hw.state = PERF_HES_STOPPED;
-		return;
+	buf = perf_aux_output_begin(&pt->handle, event);
+	if (!buf)
+		goto fail_stop;
+
+	pt_buffer_reset_offsets(buf, pt->handle.head);
+	if (!buf->snapshot) {
+		if (pt_buffer_reset_markers(buf, &pt->handle))
+			goto fail_end_stop;
 	}
 
-	ACCESS_ONCE(pt->handle_nmi) = 1;
-	event->hw.state = 0;
+	WRITE_ONCE(pt->handle_nmi, 1);
+	hwc->state = 0;
 
 	pt_config_buffer(buf->cur->table, buf->cur_idx,
 			 buf->output_off);
 	pt_config(event);
+
+	return;
+
+fail_end_stop:
+	perf_aux_output_end(&pt->handle, 0, true);
+fail_stop:
+	hwc->state = PERF_HES_STOPPED;
 }
 
 static void pt_event_stop(struct perf_event *event, int mode)
@@ -1067,7 +1262,7 @@ static void pt_event_stop(struct perf_ev
 	 * Protect against the PMI racing with disabling wrmsr,
 	 * see comment in intel_pt_interrupt().
 	 */
-	ACCESS_ONCE(pt->handle_nmi) = 0;
+	WRITE_ONCE(pt->handle_nmi, 0);
 
 	pt_config_stop(event);
 
@@ -1090,19 +1285,7 @@ static void pt_event_stop(struct perf_ev
 		pt_handle_status(pt);
 
 		pt_update_head(pt);
-	}
-}
-
-static void pt_event_del(struct perf_event *event, int mode)
-{
-	struct pt *pt = this_cpu_ptr(&pt_ctx);
-	struct pt_buffer *buf;
-
-	pt_event_stop(event, PERF_EF_UPDATE);
-
-	buf = perf_get_aux(&pt->handle);
 
-	if (buf) {
 		if (buf->snapshot)
 			pt->handle.head =
 				local_xchg(&buf->data_size,
@@ -1112,9 +1295,13 @@ static void pt_event_del(struct perf_eve
 	}
 }
 
+static void pt_event_del(struct perf_event *event, int mode)
+{
+	pt_event_stop(event, PERF_EF_UPDATE);
+}
+
 static int pt_event_add(struct perf_event *event, int mode)
 {
-	struct pt_buffer *buf;
 	struct pt *pt = this_cpu_ptr(&pt_ctx);
 	struct hw_perf_event *hwc = &event->hw;
 	int ret = -EBUSY;
@@ -1122,34 +1309,18 @@ static int pt_event_add(struct perf_even
 	if (pt->handle.event)
 		goto fail;
 
-	buf = perf_aux_output_begin(&pt->handle, event);
-	ret = -EINVAL;
-	if (!buf)
-		goto fail_stop;
-
-	pt_buffer_reset_offsets(buf, pt->handle.head);
-	if (!buf->snapshot) {
-		ret = pt_buffer_reset_markers(buf, &pt->handle);
-		if (ret)
-			goto fail_end_stop;
-	}
-
 	if (mode & PERF_EF_START) {
 		pt_event_start(event, 0);
-		ret = -EBUSY;
+		ret = -EINVAL;
 		if (hwc->state == PERF_HES_STOPPED)
-			goto fail_end_stop;
+			goto fail;
 	} else {
 		hwc->state = PERF_HES_STOPPED;
 	}
 
-	return 0;
-
-fail_end_stop:
-	perf_aux_output_end(&pt->handle, 0, true);
-fail_stop:
-	hwc->state = PERF_HES_STOPPED;
+	ret = 0;
 fail:
+
 	return ret;
 }
 
@@ -1159,6 +1330,7 @@ static void pt_event_read(struct perf_ev
 
 static void pt_event_destroy(struct perf_event *event)
 {
+	pt_addr_filters_fini(event);
 	x86_del_exclusive(x86_lbr_exclusive_pt);
 }
 
@@ -1173,6 +1345,11 @@ static int pt_event_init(struct perf_eve
 	if (x86_add_exclusive(x86_lbr_exclusive_pt))
 		return -EBUSY;
 
+	if (pt_addr_filters_init(event)) {
+		x86_del_exclusive(x86_lbr_exclusive_pt);
+		return -ENOMEM;
+	}
+
 	event->destroy = pt_event_destroy;
 
 	return 0;
@@ -1192,7 +1369,7 @@ static __init int pt_init(void)
 
 	BUILD_BUG_ON(sizeof(struct topa) > PAGE_SIZE);
 
-	if (!test_cpu_cap(&boot_cpu_data, X86_FEATURE_INTEL_PT))
+	if (!boot_cpu_has(X86_FEATURE_INTEL_PT))
 		return -ENODEV;
 
 	get_online_cpus();
@@ -1226,16 +1403,21 @@ static __init int pt_init(void)
 			PERF_PMU_CAP_AUX_NO_SG | PERF_PMU_CAP_AUX_SW_DOUBLEBUF;
 
 	pt_pmu.pmu.capabilities	|= PERF_PMU_CAP_EXCLUSIVE | PERF_PMU_CAP_ITRACE;
-	pt_pmu.pmu.attr_groups	= pt_attr_groups;
-	pt_pmu.pmu.task_ctx_nr	= perf_sw_context;
-	pt_pmu.pmu.event_init	= pt_event_init;
-	pt_pmu.pmu.add		= pt_event_add;
-	pt_pmu.pmu.del		= pt_event_del;
-	pt_pmu.pmu.start	= pt_event_start;
-	pt_pmu.pmu.stop		= pt_event_stop;
-	pt_pmu.pmu.read		= pt_event_read;
-	pt_pmu.pmu.setup_aux	= pt_buffer_setup_aux;
-	pt_pmu.pmu.free_aux	= pt_buffer_free_aux;
+	pt_pmu.pmu.attr_groups		 = pt_attr_groups;
+	pt_pmu.pmu.task_ctx_nr		 = perf_sw_context;
+	pt_pmu.pmu.event_init		 = pt_event_init;
+	pt_pmu.pmu.add			 = pt_event_add;
+	pt_pmu.pmu.del			 = pt_event_del;
+	pt_pmu.pmu.start		 = pt_event_start;
+	pt_pmu.pmu.stop			 = pt_event_stop;
+	pt_pmu.pmu.read			 = pt_event_read;
+	pt_pmu.pmu.setup_aux		 = pt_buffer_setup_aux;
+	pt_pmu.pmu.free_aux		 = pt_buffer_free_aux;
+	pt_pmu.pmu.addr_filters_sync     = pt_event_addr_filters_sync;
+	pt_pmu.pmu.addr_filters_validate = pt_event_addr_filters_validate;
+	pt_pmu.pmu.nr_addr_filters       =
+		pt_cap_get(PT_CAP_num_address_ranges);
+
 	ret = perf_pmu_register(&pt_pmu.pmu, "intel_pt", -1);
 
 	return ret;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/events/intel/pt.h linux-libre-4.7-gnu/arch/x86/events/intel/pt.h
--- linux-libre-4.6-gnu/arch/x86/events/intel/pt.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/events/intel/pt.h	2016-07-24 15:23:50.000000000 -0400
@@ -20,6 +20,40 @@
 #define __INTEL_PT_H__
 
 /*
+ * PT MSR bit definitions
+ */
+#define RTIT_CTL_TRACEEN		BIT(0)
+#define RTIT_CTL_CYCLEACC		BIT(1)
+#define RTIT_CTL_OS			BIT(2)
+#define RTIT_CTL_USR			BIT(3)
+#define RTIT_CTL_CR3EN			BIT(7)
+#define RTIT_CTL_TOPA			BIT(8)
+#define RTIT_CTL_MTC_EN			BIT(9)
+#define RTIT_CTL_TSC_EN			BIT(10)
+#define RTIT_CTL_DISRETC		BIT(11)
+#define RTIT_CTL_BRANCH_EN		BIT(13)
+#define RTIT_CTL_MTC_RANGE_OFFSET	14
+#define RTIT_CTL_MTC_RANGE		(0x0full << RTIT_CTL_MTC_RANGE_OFFSET)
+#define RTIT_CTL_CYC_THRESH_OFFSET	19
+#define RTIT_CTL_CYC_THRESH		(0x0full << RTIT_CTL_CYC_THRESH_OFFSET)
+#define RTIT_CTL_PSB_FREQ_OFFSET	24
+#define RTIT_CTL_PSB_FREQ      		(0x0full << RTIT_CTL_PSB_FREQ_OFFSET)
+#define RTIT_CTL_ADDR0_OFFSET		32
+#define RTIT_CTL_ADDR0      		(0x0full << RTIT_CTL_ADDR0_OFFSET)
+#define RTIT_CTL_ADDR1_OFFSET		36
+#define RTIT_CTL_ADDR1      		(0x0full << RTIT_CTL_ADDR1_OFFSET)
+#define RTIT_CTL_ADDR2_OFFSET		40
+#define RTIT_CTL_ADDR2      		(0x0full << RTIT_CTL_ADDR2_OFFSET)
+#define RTIT_CTL_ADDR3_OFFSET		44
+#define RTIT_CTL_ADDR3      		(0x0full << RTIT_CTL_ADDR3_OFFSET)
+#define RTIT_STATUS_FILTEREN		BIT(0)
+#define RTIT_STATUS_CONTEXTEN		BIT(1)
+#define RTIT_STATUS_TRIGGEREN		BIT(2)
+#define RTIT_STATUS_BUFFOVF		BIT(3)
+#define RTIT_STATUS_ERROR		BIT(4)
+#define RTIT_STATUS_STOPPED		BIT(5)
+
+/*
  * Single-entry ToPA: when this close to region boundary, switch
  * buffers to avoid losing data.
  */
@@ -48,15 +82,20 @@ struct topa_entry {
 #define PT_CPUID_LEAVES		2
 #define PT_CPUID_REGS_NUM	4 /* number of regsters (eax, ebx, ecx, edx) */
 
+/* TSC to Core Crystal Clock Ratio */
+#define CPUID_TSC_LEAF		0x15
+
 enum pt_capabilities {
 	PT_CAP_max_subleaf = 0,
 	PT_CAP_cr3_filtering,
 	PT_CAP_psb_cyc,
+	PT_CAP_ip_filtering,
 	PT_CAP_mtc,
 	PT_CAP_topa_output,
 	PT_CAP_topa_multiple_entries,
 	PT_CAP_single_range_output,
 	PT_CAP_payloads_lip,
+	PT_CAP_num_address_ranges,
 	PT_CAP_mtc_periods,
 	PT_CAP_cycle_thresholds,
 	PT_CAP_psb_periods,
@@ -66,6 +105,9 @@ struct pt_pmu {
 	struct pmu		pmu;
 	u32			caps[PT_CPUID_REGS_NUM * PT_CPUID_LEAVES];
 	bool			vmx;
+	unsigned long		max_nonturbo_ratio;
+	unsigned int		tsc_art_num;
+	unsigned int		tsc_art_den;
 };
 
 /**
@@ -104,14 +146,40 @@ struct pt_buffer {
 	struct topa_entry	*topa_index[0];
 };
 
+#define PT_FILTERS_NUM	4
+
+/**
+ * struct pt_filter - IP range filter configuration
+ * @msr_a:	range start, goes to RTIT_ADDRn_A
+ * @msr_b:	range end, goes to RTIT_ADDRn_B
+ * @config:	4-bit field in RTIT_CTL
+ */
+struct pt_filter {
+	unsigned long	msr_a;
+	unsigned long	msr_b;
+	unsigned long	config;
+};
+
+/**
+ * struct pt_filters - IP range filtering context
+ * @filter:	filters defined for this context
+ * @nr_filters:	number of defined filters in the @filter array
+ */
+struct pt_filters {
+	struct pt_filter	filter[PT_FILTERS_NUM];
+	unsigned int		nr_filters;
+};
+
 /**
  * struct pt - per-cpu pt context
  * @handle:	perf output handle
+ * @filters:		last configured filters
  * @handle_nmi:	do handle PT PMI on this cpu, there's an active event
  * @vmx_on:	1 if VMX is ON on this cpu
  */
 struct pt {
 	struct perf_output_handle handle;
+	struct pt_filters	filters;
 	int			handle_nmi;
 	int			vmx_on;
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/events/intel/rapl.c linux-libre-4.7-gnu/arch/x86/events/intel/rapl.c
--- linux-libre-4.6-gnu/arch/x86/events/intel/rapl.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/events/intel/rapl.c	2016-07-24 15:23:50.000000000 -0400
@@ -27,10 +27,14 @@
  *	  event: rapl_energy_dram
  *    perf code: 0x3
  *
- * dram counter: consumption of the builtin-gpu domain (client only)
+ * gpu counter: consumption of the builtin-gpu domain (client only)
  *	  event: rapl_energy_gpu
  *    perf code: 0x4
  *
+ *  psys counter: consumption of the builtin-psys domain (client only)
+ *	  event: rapl_energy_psys
+ *    perf code: 0x5
+ *
  * We manage those counters as free running (read-only). They may be
  * use simultaneously by other tools, such as turbostat.
  *
@@ -53,6 +57,8 @@
 #include <asm/cpu_device_id.h>
 #include "../perf_event.h"
 
+MODULE_LICENSE("GPL");
+
 /*
  * RAPL energy status counters
  */
@@ -64,13 +70,16 @@
 #define INTEL_RAPL_RAM		0x3	/* pseudo-encoding */
 #define RAPL_IDX_PP1_NRG_STAT	3	/* gpu */
 #define INTEL_RAPL_PP1		0x4	/* pseudo-encoding */
+#define RAPL_IDX_PSYS_NRG_STAT	4	/* psys */
+#define INTEL_RAPL_PSYS		0x5	/* pseudo-encoding */
 
-#define NR_RAPL_DOMAINS         0x4
+#define NR_RAPL_DOMAINS         0x5
 static const char *const rapl_domain_names[NR_RAPL_DOMAINS] __initconst = {
 	"pp0-core",
 	"package",
 	"dram",
 	"pp1-gpu",
+	"psys",
 };
 
 /* Clients have PP0, PKG */
@@ -89,6 +98,13 @@ static const char *const rapl_domain_nam
 			 1<<RAPL_IDX_RAM_NRG_STAT|\
 			 1<<RAPL_IDX_PP1_NRG_STAT)
 
+/* SKL clients have PP0, PKG, RAM, PP1, PSYS */
+#define RAPL_IDX_SKL_CLN (1<<RAPL_IDX_PP0_NRG_STAT|\
+			  1<<RAPL_IDX_PKG_NRG_STAT|\
+			  1<<RAPL_IDX_RAM_NRG_STAT|\
+			  1<<RAPL_IDX_PP1_NRG_STAT|\
+			  1<<RAPL_IDX_PSYS_NRG_STAT)
+
 /* Knights Landing has PKG, RAM */
 #define RAPL_IDX_KNL	(1<<RAPL_IDX_PKG_NRG_STAT|\
 			 1<<RAPL_IDX_RAM_NRG_STAT)
@@ -360,6 +376,10 @@ static int rapl_pmu_event_init(struct pe
 		bit = RAPL_IDX_PP1_NRG_STAT;
 		msr = MSR_PP1_ENERGY_STATUS;
 		break;
+	case INTEL_RAPL_PSYS:
+		bit = RAPL_IDX_PSYS_NRG_STAT;
+		msr = MSR_PLATFORM_ENERGY_STATUS;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -414,11 +434,13 @@ RAPL_EVENT_ATTR_STR(energy-cores, rapl_c
 RAPL_EVENT_ATTR_STR(energy-pkg  ,   rapl_pkg, "event=0x02");
 RAPL_EVENT_ATTR_STR(energy-ram  ,   rapl_ram, "event=0x03");
 RAPL_EVENT_ATTR_STR(energy-gpu  ,   rapl_gpu, "event=0x04");
+RAPL_EVENT_ATTR_STR(energy-psys,   rapl_psys, "event=0x05");
 
 RAPL_EVENT_ATTR_STR(energy-cores.unit, rapl_cores_unit, "Joules");
 RAPL_EVENT_ATTR_STR(energy-pkg.unit  ,   rapl_pkg_unit, "Joules");
 RAPL_EVENT_ATTR_STR(energy-ram.unit  ,   rapl_ram_unit, "Joules");
 RAPL_EVENT_ATTR_STR(energy-gpu.unit  ,   rapl_gpu_unit, "Joules");
+RAPL_EVENT_ATTR_STR(energy-psys.unit,   rapl_psys_unit, "Joules");
 
 /*
  * we compute in 0.23 nJ increments regardless of MSR
@@ -427,6 +449,7 @@ RAPL_EVENT_ATTR_STR(energy-cores.scale,
 RAPL_EVENT_ATTR_STR(energy-pkg.scale,     rapl_pkg_scale, "2.3283064365386962890625e-10");
 RAPL_EVENT_ATTR_STR(energy-ram.scale,     rapl_ram_scale, "2.3283064365386962890625e-10");
 RAPL_EVENT_ATTR_STR(energy-gpu.scale,     rapl_gpu_scale, "2.3283064365386962890625e-10");
+RAPL_EVENT_ATTR_STR(energy-psys.scale,   rapl_psys_scale, "2.3283064365386962890625e-10");
 
 static struct attribute *rapl_events_srv_attr[] = {
 	EVENT_PTR(rapl_cores),
@@ -476,6 +499,27 @@ static struct attribute *rapl_events_hsw
 	NULL,
 };
 
+static struct attribute *rapl_events_skl_attr[] = {
+	EVENT_PTR(rapl_cores),
+	EVENT_PTR(rapl_pkg),
+	EVENT_PTR(rapl_gpu),
+	EVENT_PTR(rapl_ram),
+	EVENT_PTR(rapl_psys),
+
+	EVENT_PTR(rapl_cores_unit),
+	EVENT_PTR(rapl_pkg_unit),
+	EVENT_PTR(rapl_gpu_unit),
+	EVENT_PTR(rapl_ram_unit),
+	EVENT_PTR(rapl_psys_unit),
+
+	EVENT_PTR(rapl_cores_scale),
+	EVENT_PTR(rapl_pkg_scale),
+	EVENT_PTR(rapl_gpu_scale),
+	EVENT_PTR(rapl_ram_scale),
+	EVENT_PTR(rapl_psys_scale),
+	NULL,
+};
+
 static struct attribute *rapl_events_knl_attr[] = {
 	EVENT_PTR(rapl_pkg),
 	EVENT_PTR(rapl_ram),
@@ -592,6 +636,11 @@ static int rapl_cpu_notifier(struct noti
 	return NOTIFY_OK;
 }
 
+static struct notifier_block rapl_cpu_nb = {
+	.notifier_call	= rapl_cpu_notifier,
+	.priority       = CPU_PRI_PERF + 1,
+};
+
 static int rapl_check_hw_unit(bool apply_quirk)
 {
 	u64 msr_rapl_power_unit_bits;
@@ -660,12 +709,12 @@ static int __init rapl_prepare_cpus(void
 	return 0;
 }
 
-static void __init cleanup_rapl_pmus(void)
+static void cleanup_rapl_pmus(void)
 {
 	int i;
 
 	for (i = 0; i < rapl_pmus->maxpkg; i++)
-		kfree(rapl_pmus->pmus + i);
+		kfree(rapl_pmus->pmus[i]);
 	kfree(rapl_pmus);
 }
 
@@ -691,52 +740,92 @@ static int __init init_rapl_pmus(void)
 	return 0;
 }
 
+#define X86_RAPL_MODEL_MATCH(model, init)	\
+	{ X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long)&init }
+
+struct intel_rapl_init_fun {
+	bool apply_quirk;
+	int cntr_mask;
+	struct attribute **attrs;
+};
+
+static const struct intel_rapl_init_fun snb_rapl_init __initconst = {
+	.apply_quirk = false,
+	.cntr_mask = RAPL_IDX_CLN,
+	.attrs = rapl_events_cln_attr,
+};
+
+static const struct intel_rapl_init_fun hsx_rapl_init __initconst = {
+	.apply_quirk = true,
+	.cntr_mask = RAPL_IDX_SRV,
+	.attrs = rapl_events_srv_attr,
+};
+
+static const struct intel_rapl_init_fun hsw_rapl_init __initconst = {
+	.apply_quirk = false,
+	.cntr_mask = RAPL_IDX_HSW,
+	.attrs = rapl_events_hsw_attr,
+};
+
+static const struct intel_rapl_init_fun snbep_rapl_init __initconst = {
+	.apply_quirk = false,
+	.cntr_mask = RAPL_IDX_SRV,
+	.attrs = rapl_events_srv_attr,
+};
+
+static const struct intel_rapl_init_fun knl_rapl_init __initconst = {
+	.apply_quirk = true,
+	.cntr_mask = RAPL_IDX_KNL,
+	.attrs = rapl_events_knl_attr,
+};
+
+static const struct intel_rapl_init_fun skl_rapl_init __initconst = {
+	.apply_quirk = false,
+	.cntr_mask = RAPL_IDX_SKL_CLN,
+	.attrs = rapl_events_skl_attr,
+};
+
 static const struct x86_cpu_id rapl_cpu_match[] __initconst = {
-	[0] = { .vendor = X86_VENDOR_INTEL, .family = 6 },
-	[1] = {},
+	X86_RAPL_MODEL_MATCH(42, snb_rapl_init),	/* Sandy Bridge */
+	X86_RAPL_MODEL_MATCH(45, snbep_rapl_init),	/* Sandy Bridge-EP */
+
+	X86_RAPL_MODEL_MATCH(58, snb_rapl_init),	/* Ivy Bridge */
+	X86_RAPL_MODEL_MATCH(62, snbep_rapl_init),	/* IvyTown */
+
+	X86_RAPL_MODEL_MATCH(60, hsw_rapl_init),	/* Haswell */
+	X86_RAPL_MODEL_MATCH(63, hsx_rapl_init),	/* Haswell-Server */
+	X86_RAPL_MODEL_MATCH(69, hsw_rapl_init),	/* Haswell-Celeron */
+	X86_RAPL_MODEL_MATCH(70, hsw_rapl_init),	/* Haswell GT3e */
+
+	X86_RAPL_MODEL_MATCH(61, hsw_rapl_init),	/* Broadwell */
+	X86_RAPL_MODEL_MATCH(71, hsw_rapl_init),	/* Broadwell-H */
+	X86_RAPL_MODEL_MATCH(79, hsx_rapl_init),	/* Broadwell-Server */
+	X86_RAPL_MODEL_MATCH(86, hsx_rapl_init),	/* Broadwell Xeon D */
+
+	X86_RAPL_MODEL_MATCH(87, knl_rapl_init),	/* Knights Landing */
+
+	X86_RAPL_MODEL_MATCH(78, skl_rapl_init),	/* Skylake */
+	X86_RAPL_MODEL_MATCH(94, skl_rapl_init),	/* Skylake H/S */
+	{},
 };
 
+MODULE_DEVICE_TABLE(x86cpu, rapl_cpu_match);
+
 static int __init rapl_pmu_init(void)
 {
-	bool apply_quirk = false;
+	const struct x86_cpu_id *id;
+	struct intel_rapl_init_fun *rapl_init;
+	bool apply_quirk;
 	int ret;
 
-	if (!x86_match_cpu(rapl_cpu_match))
+	id = x86_match_cpu(rapl_cpu_match);
+	if (!id)
 		return -ENODEV;
 
-	switch (boot_cpu_data.x86_model) {
-	case 42: /* Sandy Bridge */
-	case 58: /* Ivy Bridge */
-		rapl_cntr_mask = RAPL_IDX_CLN;
-		rapl_pmu_events_group.attrs = rapl_events_cln_attr;
-		break;
-	case 63: /* Haswell-Server */
-	case 79: /* Broadwell-Server */
-		apply_quirk = true;
-		rapl_cntr_mask = RAPL_IDX_SRV;
-		rapl_pmu_events_group.attrs = rapl_events_srv_attr;
-		break;
-	case 60: /* Haswell */
-	case 69: /* Haswell-Celeron */
-	case 70: /* Haswell GT3e */
-	case 61: /* Broadwell */
-	case 71: /* Broadwell-H */
-		rapl_cntr_mask = RAPL_IDX_HSW;
-		rapl_pmu_events_group.attrs = rapl_events_hsw_attr;
-		break;
-	case 45: /* Sandy Bridge-EP */
-	case 62: /* IvyTown */
-		rapl_cntr_mask = RAPL_IDX_SRV;
-		rapl_pmu_events_group.attrs = rapl_events_srv_attr;
-		break;
-	case 87: /* Knights Landing */
-		apply_quirk = true;
-		rapl_cntr_mask = RAPL_IDX_KNL;
-		rapl_pmu_events_group.attrs = rapl_events_knl_attr;
-		break;
-	default:
-		return -ENODEV;
-	}
+	rapl_init = (struct intel_rapl_init_fun *)id->driver_data;
+	apply_quirk = rapl_init->apply_quirk;
+	rapl_cntr_mask = rapl_init->cntr_mask;
+	rapl_pmu_events_group.attrs = rapl_init->attrs;
 
 	ret = rapl_check_hw_unit(apply_quirk);
 	if (ret)
@@ -756,7 +845,7 @@ static int __init rapl_pmu_init(void)
 	if (ret)
 		goto out;
 
-	__perf_cpu_notifier(rapl_cpu_notifier);
+	__register_cpu_notifier(&rapl_cpu_nb);
 	cpu_notifier_register_done();
 	rapl_advertise();
 	return 0;
@@ -767,4 +856,14 @@ out:
 	cpu_notifier_register_done();
 	return ret;
 }
-device_initcall(rapl_pmu_init);
+module_init(rapl_pmu_init);
+
+static void __exit intel_rapl_exit(void)
+{
+	cpu_notifier_register_begin();
+	__unregister_cpu_notifier(&rapl_cpu_nb);
+	perf_pmu_unregister(&rapl_pmus->pmu);
+	cleanup_rapl_pmus();
+	cpu_notifier_register_done();
+}
+module_exit(intel_rapl_exit);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/events/intel/uncore.c linux-libre-4.7-gnu/arch/x86/events/intel/uncore.c
--- linux-libre-4.6-gnu/arch/x86/events/intel/uncore.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/events/intel/uncore.c	2016-07-24 15:23:50.000000000 -0400
@@ -1,3 +1,4 @@
+#include <asm/cpu_device_id.h>
 #include "uncore.h"
 
 static struct intel_uncore_type *empty_uncore[] = { NULL, };
@@ -21,6 +22,8 @@ static struct event_constraint uncore_co
 struct event_constraint uncore_constraint_empty =
 	EVENT_CONSTRAINT(0, 0, 0);
 
+MODULE_LICENSE("GPL");
+
 static int uncore_pcibus_to_physid(struct pci_bus *bus)
 {
 	struct pci2phy_map *map;
@@ -754,7 +757,7 @@ static void uncore_pmu_unregister(struct
 	pmu->registered = false;
 }
 
-static void __init __uncore_exit_boxes(struct intel_uncore_type *type, int cpu)
+static void __uncore_exit_boxes(struct intel_uncore_type *type, int cpu)
 {
 	struct intel_uncore_pmu *pmu = type->pmus;
 	struct intel_uncore_box *box;
@@ -770,7 +773,7 @@ static void __init __uncore_exit_boxes(s
 	}
 }
 
-static void __init uncore_exit_boxes(void *dummy)
+static void uncore_exit_boxes(void *dummy)
 {
 	struct intel_uncore_type **types;
 
@@ -787,7 +790,7 @@ static void uncore_free_boxes(struct int
 	kfree(pmu->boxes);
 }
 
-static void __init uncore_type_exit(struct intel_uncore_type *type)
+static void uncore_type_exit(struct intel_uncore_type *type)
 {
 	struct intel_uncore_pmu *pmu = type->pmus;
 	int i;
@@ -804,7 +807,7 @@ static void __init uncore_type_exit(stru
 	type->events_group = NULL;
 }
 
-static void __init uncore_types_exit(struct intel_uncore_type **types)
+static void uncore_types_exit(struct intel_uncore_type **types)
 {
 	for (; *types; types++)
 		uncore_type_exit(*types);
@@ -888,7 +891,7 @@ static int uncore_pci_probe(struct pci_d
 		return -ENODEV;
 
 	pkg = topology_phys_to_logical_pkg(phys_id);
-	if (WARN_ON_ONCE(pkg < 0))
+	if (pkg < 0)
 		return -EINVAL;
 
 	if (UNCORE_PCI_DEV_TYPE(id->driver_data) == UNCORE_EXTRA_PCI_DEV) {
@@ -989,46 +992,6 @@ static int __init uncore_pci_init(void)
 	size_t size;
 	int ret;
 
-	switch (boot_cpu_data.x86_model) {
-	case 45: /* Sandy Bridge-EP */
-		ret = snbep_uncore_pci_init();
-		break;
-	case 62: /* Ivy Bridge-EP */
-		ret = ivbep_uncore_pci_init();
-		break;
-	case 63: /* Haswell-EP */
-		ret = hswep_uncore_pci_init();
-		break;
-	case 79: /* BDX-EP */
-	case 86: /* BDX-DE */
-		ret = bdx_uncore_pci_init();
-		break;
-	case 42: /* Sandy Bridge */
-		ret = snb_uncore_pci_init();
-		break;
-	case 58: /* Ivy Bridge */
-		ret = ivb_uncore_pci_init();
-		break;
-	case 60: /* Haswell */
-	case 69: /* Haswell Celeron */
-		ret = hsw_uncore_pci_init();
-		break;
-	case 61: /* Broadwell */
-		ret = bdw_uncore_pci_init();
-		break;
-	case 87: /* Knights Landing */
-		ret = knl_uncore_pci_init();
-		break;
-	case 94: /* SkyLake */
-		ret = skl_uncore_pci_init();
-		break;
-	default:
-		return -ENODEV;
-	}
-
-	if (ret)
-		return ret;
-
 	size = max_packages * sizeof(struct pci_extra_dev);
 	uncore_extra_pci_dev = kzalloc(size, GFP_KERNEL);
 	if (!uncore_extra_pci_dev) {
@@ -1060,7 +1023,7 @@ err:
 	return ret;
 }
 
-static void __init uncore_pci_exit(void)
+static void uncore_pci_exit(void)
 {
 	if (pcidrv_registered) {
 		pcidrv_registered = false;
@@ -1287,46 +1250,6 @@ static int __init uncore_cpu_init(void)
 {
 	int ret;
 
-	switch (boot_cpu_data.x86_model) {
-	case 26: /* Nehalem */
-	case 30:
-	case 37: /* Westmere */
-	case 44:
-		nhm_uncore_cpu_init();
-		break;
-	case 42: /* Sandy Bridge */
-	case 58: /* Ivy Bridge */
-	case 60: /* Haswell */
-	case 69: /* Haswell */
-	case 70: /* Haswell */
-	case 61: /* Broadwell */
-	case 71: /* Broadwell */
-		snb_uncore_cpu_init();
-		break;
-	case 45: /* Sandy Bridge-EP */
-		snbep_uncore_cpu_init();
-		break;
-	case 46: /* Nehalem-EX */
-	case 47: /* Westmere-EX aka. Xeon E7 */
-		nhmex_uncore_cpu_init();
-		break;
-	case 62: /* Ivy Bridge-EP */
-		ivbep_uncore_cpu_init();
-		break;
-	case 63: /* Haswell-EP */
-		hswep_uncore_cpu_init();
-		break;
-	case 79: /* BDX-EP */
-	case 86: /* BDX-DE */
-		bdx_uncore_cpu_init();
-		break;
-	case 87: /* Knights Landing */
-		knl_uncore_cpu_init();
-		break;
-	default:
-		return -ENODEV;
-	}
-
 	ret = uncore_types_init(uncore_msr_uncores, true);
 	if (ret)
 		goto err;
@@ -1376,20 +1299,123 @@ static int __init uncore_cpumask_init(bo
 	return 0;
 }
 
+#define X86_UNCORE_MODEL_MATCH(model, init)	\
+	{ X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long)&init }
+
+struct intel_uncore_init_fun {
+	void	(*cpu_init)(void);
+	int	(*pci_init)(void);
+};
+
+static const struct intel_uncore_init_fun nhm_uncore_init __initconst = {
+	.cpu_init = nhm_uncore_cpu_init,
+};
+
+static const struct intel_uncore_init_fun snb_uncore_init __initconst = {
+	.cpu_init = snb_uncore_cpu_init,
+	.pci_init = snb_uncore_pci_init,
+};
+
+static const struct intel_uncore_init_fun ivb_uncore_init __initconst = {
+	.cpu_init = snb_uncore_cpu_init,
+	.pci_init = ivb_uncore_pci_init,
+};
+
+static const struct intel_uncore_init_fun hsw_uncore_init __initconst = {
+	.cpu_init = snb_uncore_cpu_init,
+	.pci_init = hsw_uncore_pci_init,
+};
+
+static const struct intel_uncore_init_fun bdw_uncore_init __initconst = {
+	.cpu_init = snb_uncore_cpu_init,
+	.pci_init = bdw_uncore_pci_init,
+};
+
+static const struct intel_uncore_init_fun snbep_uncore_init __initconst = {
+	.cpu_init = snbep_uncore_cpu_init,
+	.pci_init = snbep_uncore_pci_init,
+};
+
+static const struct intel_uncore_init_fun nhmex_uncore_init __initconst = {
+	.cpu_init = nhmex_uncore_cpu_init,
+};
+
+static const struct intel_uncore_init_fun ivbep_uncore_init __initconst = {
+	.cpu_init = ivbep_uncore_cpu_init,
+	.pci_init = ivbep_uncore_pci_init,
+};
+
+static const struct intel_uncore_init_fun hswep_uncore_init __initconst = {
+	.cpu_init = hswep_uncore_cpu_init,
+	.pci_init = hswep_uncore_pci_init,
+};
+
+static const struct intel_uncore_init_fun bdx_uncore_init __initconst = {
+	.cpu_init = bdx_uncore_cpu_init,
+	.pci_init = bdx_uncore_pci_init,
+};
+
+static const struct intel_uncore_init_fun knl_uncore_init __initconst = {
+	.cpu_init = knl_uncore_cpu_init,
+	.pci_init = knl_uncore_pci_init,
+};
+
+static const struct intel_uncore_init_fun skl_uncore_init __initconst = {
+	.pci_init = skl_uncore_pci_init,
+};
+
+static const struct x86_cpu_id intel_uncore_match[] __initconst = {
+	X86_UNCORE_MODEL_MATCH(26, nhm_uncore_init),	/* Nehalem */
+	X86_UNCORE_MODEL_MATCH(30, nhm_uncore_init),
+	X86_UNCORE_MODEL_MATCH(37, nhm_uncore_init),	/* Westmere */
+	X86_UNCORE_MODEL_MATCH(44, nhm_uncore_init),
+	X86_UNCORE_MODEL_MATCH(42, snb_uncore_init),	/* Sandy Bridge */
+	X86_UNCORE_MODEL_MATCH(58, ivb_uncore_init),	/* Ivy Bridge */
+	X86_UNCORE_MODEL_MATCH(60, hsw_uncore_init),	/* Haswell */
+	X86_UNCORE_MODEL_MATCH(69, hsw_uncore_init),	/* Haswell Celeron */
+	X86_UNCORE_MODEL_MATCH(70, hsw_uncore_init),	/* Haswell */
+	X86_UNCORE_MODEL_MATCH(61, bdw_uncore_init),	/* Broadwell */
+	X86_UNCORE_MODEL_MATCH(71, bdw_uncore_init),	/* Broadwell */
+	X86_UNCORE_MODEL_MATCH(45, snbep_uncore_init),	/* Sandy Bridge-EP */
+	X86_UNCORE_MODEL_MATCH(46, nhmex_uncore_init),	/* Nehalem-EX */
+	X86_UNCORE_MODEL_MATCH(47, nhmex_uncore_init),	/* Westmere-EX aka. Xeon E7 */
+	X86_UNCORE_MODEL_MATCH(62, ivbep_uncore_init),	/* Ivy Bridge-EP */
+	X86_UNCORE_MODEL_MATCH(63, hswep_uncore_init),	/* Haswell-EP */
+	X86_UNCORE_MODEL_MATCH(79, bdx_uncore_init),	/* BDX-EP */
+	X86_UNCORE_MODEL_MATCH(86, bdx_uncore_init),	/* BDX-DE */
+	X86_UNCORE_MODEL_MATCH(87, knl_uncore_init),	/* Knights Landing */
+	X86_UNCORE_MODEL_MATCH(94, skl_uncore_init),	/* SkyLake */
+	{},
+};
+
+MODULE_DEVICE_TABLE(x86cpu, intel_uncore_match);
+
 static int __init intel_uncore_init(void)
 {
-	int pret, cret, ret;
+	const struct x86_cpu_id *id;
+	struct intel_uncore_init_fun *uncore_init;
+	int pret = 0, cret = 0, ret;
 
-	if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
+	id = x86_match_cpu(intel_uncore_match);
+	if (!id)
 		return -ENODEV;
 
-	if (cpu_has_hypervisor)
+	if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
 		return -ENODEV;
 
 	max_packages = topology_max_packages();
 
-	pret = uncore_pci_init();
-	cret = uncore_cpu_init();
+	uncore_init = (struct intel_uncore_init_fun *)id->driver_data;
+	if (uncore_init->pci_init) {
+		pret = uncore_init->pci_init();
+		if (!pret)
+			pret = uncore_pci_init();
+	}
+
+	if (uncore_init->cpu_init) {
+		uncore_init->cpu_init();
+		cret = uncore_cpu_init();
+	}
 
 	if (cret && pret)
 		return -ENODEV;
@@ -1409,4 +1435,14 @@ err:
 	cpu_notifier_register_done();
 	return ret;
 }
-device_initcall(intel_uncore_init);
+module_init(intel_uncore_init);
+
+static void __exit intel_uncore_exit(void)
+{
+	cpu_notifier_register_begin();
+	__unregister_cpu_notifier(&uncore_cpu_nb);
+	uncore_types_exit(uncore_msr_uncores);
+	uncore_pci_exit();
+	cpu_notifier_register_done();
+}
+module_exit(intel_uncore_exit);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/events/intel/uncore_snbep.c linux-libre-4.7-gnu/arch/x86/events/intel/uncore_snbep.c
--- linux-libre-4.6-gnu/arch/x86/events/intel/uncore_snbep.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/events/intel/uncore_snbep.c	2016-07-24 15:23:50.000000000 -0400
@@ -2868,27 +2868,10 @@ static struct intel_uncore_type bdx_unco
 	.format_group		= &hswep_uncore_cbox_format_group,
 };
 
-static struct intel_uncore_type bdx_uncore_sbox = {
-	.name			= "sbox",
-	.num_counters		= 4,
-	.num_boxes		= 4,
-	.perf_ctr_bits		= 48,
-	.event_ctl		= HSWEP_S0_MSR_PMON_CTL0,
-	.perf_ctr		= HSWEP_S0_MSR_PMON_CTR0,
-	.event_mask		= HSWEP_S_MSR_PMON_RAW_EVENT_MASK,
-	.box_ctl		= HSWEP_S0_MSR_PMON_BOX_CTL,
-	.msr_offset		= HSWEP_SBOX_MSR_OFFSET,
-	.ops			= &hswep_uncore_sbox_msr_ops,
-	.format_group		= &hswep_uncore_sbox_format_group,
-};
-
-#define BDX_MSR_UNCORE_SBOX	3
-
 static struct intel_uncore_type *bdx_msr_uncores[] = {
 	&bdx_uncore_ubox,
 	&bdx_uncore_cbox,
 	&hswep_uncore_pcu,
-	&bdx_uncore_sbox,
 	NULL,
 };
 
@@ -2897,10 +2880,6 @@ void bdx_uncore_cpu_init(void)
 	if (bdx_uncore_cbox.num_boxes > boot_cpu_data.x86_max_cores)
 		bdx_uncore_cbox.num_boxes = boot_cpu_data.x86_max_cores;
 	uncore_msr_uncores = bdx_msr_uncores;
-
-	/* BDX-DE doesn't have SBOX */
-	if (boot_cpu_data.x86_model == 86)
-		uncore_msr_uncores[BDX_MSR_UNCORE_SBOX] = NULL;
 }
 
 static struct intel_uncore_type bdx_uncore_ha = {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/events/Kconfig linux-libre-4.7-gnu/arch/x86/events/Kconfig
--- linux-libre-4.6-gnu/arch/x86/events/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/x86/events/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,36 @@
+menu "Performance monitoring"
+
+config PERF_EVENTS_INTEL_UNCORE
+	tristate "Intel uncore performance events"
+	depends on PERF_EVENTS && CPU_SUP_INTEL && PCI
+	default y
+	---help---
+	Include support for Intel uncore performance events. These are
+	available on NehalemEX and more modern processors.
+
+config PERF_EVENTS_INTEL_RAPL
+	tristate "Intel rapl performance events"
+	depends on PERF_EVENTS && CPU_SUP_INTEL && PCI
+	default y
+	---help---
+	Include support for Intel rapl performance events for power
+	monitoring on modern processors.
+
+config PERF_EVENTS_INTEL_CSTATE
+	tristate "Intel cstate performance events"
+	depends on PERF_EVENTS && CPU_SUP_INTEL && PCI
+	default y
+	---help---
+	Include support for Intel cstate performance events for power
+	monitoring on modern processors.
+
+config PERF_EVENTS_AMD_POWER
+	depends on PERF_EVENTS && CPU_SUP_AMD
+	tristate "AMD Processor Power Reporting Mechanism"
+	---help---
+	  Provide power reporting mechanism support for AMD processors.
+	  Currently, it leverages X86_FEATURE_ACC_POWER
+	  (CPUID Fn8000_0007_EDX[12]) interface to calculate the
+	  average power consumption on Family 15h processors.
+
+endmenu
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/events/Makefile linux-libre-4.7-gnu/arch/x86/events/Makefile
--- linux-libre-4.6-gnu/arch/x86/events/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/events/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -6,9 +6,6 @@ obj-$(CONFIG_X86_LOCAL_APIC)
 ifdef CONFIG_AMD_IOMMU
 obj-$(CONFIG_CPU_SUP_AMD)               += amd/iommu.o
 endif
-obj-$(CONFIG_CPU_SUP_INTEL)		+= intel/core.o intel/bts.o intel/cqm.o
-obj-$(CONFIG_CPU_SUP_INTEL)		+= intel/cstate.o intel/ds.o intel/knc.o 
-obj-$(CONFIG_CPU_SUP_INTEL)		+= intel/lbr.o intel/p4.o intel/p6.o intel/pt.o
-obj-$(CONFIG_CPU_SUP_INTEL)		+= intel/rapl.o msr.o
-obj-$(CONFIG_PERF_EVENTS_INTEL_UNCORE)	+= intel/uncore.o intel/uncore_nhmex.o
-obj-$(CONFIG_PERF_EVENTS_INTEL_UNCORE)	+= intel/uncore_snb.o intel/uncore_snbep.o
+
+obj-$(CONFIG_CPU_SUP_INTEL)		+= msr.o
+obj-$(CONFIG_CPU_SUP_INTEL)		+= intel/
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/events/msr.c linux-libre-4.7-gnu/arch/x86/events/msr.c
--- linux-libre-4.6-gnu/arch/x86/events/msr.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/events/msr.c	2016-07-24 15:23:50.000000000 -0400
@@ -6,6 +6,8 @@ enum perf_msr_id {
 	PERF_MSR_MPERF			= 2,
 	PERF_MSR_PPERF			= 3,
 	PERF_MSR_SMI			= 4,
+	PERF_MSR_PTSC			= 5,
+	PERF_MSR_IRPERF			= 6,
 
 	PERF_MSR_EVENT_MAX,
 };
@@ -15,6 +17,16 @@ static bool test_aperfmperf(int idx)
 	return boot_cpu_has(X86_FEATURE_APERFMPERF);
 }
 
+static bool test_ptsc(int idx)
+{
+	return boot_cpu_has(X86_FEATURE_PTSC);
+}
+
+static bool test_irperf(int idx)
+{
+	return boot_cpu_has(X86_FEATURE_IRPERF);
+}
+
 static bool test_intel(int idx)
 {
 	if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ||
@@ -69,18 +81,22 @@ struct perf_msr {
 	bool	(*test)(int idx);
 };
 
-PMU_EVENT_ATTR_STRING(tsc,   evattr_tsc,   "event=0x00");
-PMU_EVENT_ATTR_STRING(aperf, evattr_aperf, "event=0x01");
-PMU_EVENT_ATTR_STRING(mperf, evattr_mperf, "event=0x02");
-PMU_EVENT_ATTR_STRING(pperf, evattr_pperf, "event=0x03");
-PMU_EVENT_ATTR_STRING(smi,   evattr_smi,   "event=0x04");
+PMU_EVENT_ATTR_STRING(tsc,    evattr_tsc,    "event=0x00");
+PMU_EVENT_ATTR_STRING(aperf,  evattr_aperf,  "event=0x01");
+PMU_EVENT_ATTR_STRING(mperf,  evattr_mperf,  "event=0x02");
+PMU_EVENT_ATTR_STRING(pperf,  evattr_pperf,  "event=0x03");
+PMU_EVENT_ATTR_STRING(smi,    evattr_smi,    "event=0x04");
+PMU_EVENT_ATTR_STRING(ptsc,   evattr_ptsc,   "event=0x05");
+PMU_EVENT_ATTR_STRING(irperf, evattr_irperf, "event=0x06");
 
 static struct perf_msr msr[] = {
-	[PERF_MSR_TSC]   = { 0,			&evattr_tsc,	NULL,		 },
-	[PERF_MSR_APERF] = { MSR_IA32_APERF,	&evattr_aperf,	test_aperfmperf, },
-	[PERF_MSR_MPERF] = { MSR_IA32_MPERF,	&evattr_mperf,	test_aperfmperf, },
-	[PERF_MSR_PPERF] = { MSR_PPERF,		&evattr_pperf,	test_intel,	 },
-	[PERF_MSR_SMI]   = { MSR_SMI_COUNT,	&evattr_smi,	test_intel,	 },
+	[PERF_MSR_TSC]    = { 0,		&evattr_tsc,	NULL,		 },
+	[PERF_MSR_APERF]  = { MSR_IA32_APERF,	&evattr_aperf,	test_aperfmperf, },
+	[PERF_MSR_MPERF]  = { MSR_IA32_MPERF,	&evattr_mperf,	test_aperfmperf, },
+	[PERF_MSR_PPERF]  = { MSR_PPERF,	&evattr_pperf,	test_intel,	 },
+	[PERF_MSR_SMI]    = { MSR_SMI_COUNT,	&evattr_smi,	test_intel,	 },
+	[PERF_MSR_PTSC]   = { MSR_F15H_PTSC,	&evattr_ptsc,	test_ptsc,	 },
+	[PERF_MSR_IRPERF] = { MSR_F17H_IRPERF,	&evattr_irperf,	test_irperf,	 },
 };
 
 static struct attribute *events_attrs[PERF_MSR_EVENT_MAX + 1] = {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/events/perf_event.h linux-libre-4.7-gnu/arch/x86/events/perf_event.h
--- linux-libre-4.6-gnu/arch/x86/events/perf_event.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/events/perf_event.h	2016-07-24 15:23:50.000000000 -0400
@@ -601,6 +601,7 @@ struct x86_pmu {
 	u64		lbr_sel_mask;		   /* LBR_SELECT valid bits */
 	const int	*lbr_sel_map;		   /* lbr_select mappings */
 	bool		lbr_double_abort;	   /* duplicated lbr aborts */
+	bool		lbr_pt_coexist;		   /* LBR may coexist with PT */
 
 	/*
 	 * Intel PT/LBR/BTS are exclusive
@@ -859,6 +860,8 @@ extern struct event_constraint intel_ato
 
 extern struct event_constraint intel_slm_pebs_event_constraints[];
 
+extern struct event_constraint intel_glm_pebs_event_constraints[];
+
 extern struct event_constraint intel_nehalem_pebs_event_constraints[];
 
 extern struct event_constraint intel_westmere_pebs_event_constraints[];
@@ -907,6 +910,8 @@ void intel_pmu_lbr_init_nhm(void);
 
 void intel_pmu_lbr_init_atom(void);
 
+void intel_pmu_lbr_init_slm(void);
+
 void intel_pmu_lbr_init_snb(void);
 
 void intel_pmu_lbr_init_hsw(void);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/ia32/ia32_aout.c linux-libre-4.7-gnu/arch/x86/ia32/ia32_aout.c
--- linux-libre-4.6-gnu/arch/x86/ia32/ia32_aout.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/ia32/ia32_aout.c	2016-07-24 15:23:50.000000000 -0400
@@ -116,13 +116,13 @@ static struct linux_binfmt aout_format =
 	.min_coredump	= PAGE_SIZE
 };
 
-static void set_brk(unsigned long start, unsigned long end)
+static int set_brk(unsigned long start, unsigned long end)
 {
 	start = PAGE_ALIGN(start);
 	end = PAGE_ALIGN(end);
 	if (end <= start)
-		return;
-	vm_brk(start, end - start);
+		return 0;
+	return vm_brk(start, end - start);
 }
 
 #ifdef CONFIG_COREDUMP
@@ -321,7 +321,7 @@ static int load_aout_binary(struct linux
 
 		error = vm_brk(text_addr & PAGE_MASK, map_size);
 
-		if (error != (text_addr & PAGE_MASK))
+		if (error)
 			return error;
 
 		error = read_code(bprm->file, text_addr, 32,
@@ -349,7 +349,10 @@ static int load_aout_binary(struct linux
 #endif
 
 		if (!bprm->file->f_op->mmap || (fd_offset & ~PAGE_MASK) != 0) {
-			vm_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
+			error = vm_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
+			if (error)
+				return error;
+
 			read_code(bprm->file, N_TXTADDR(ex), fd_offset,
 					ex.a_text+ex.a_data);
 			goto beyond_if;
@@ -372,10 +375,13 @@ static int load_aout_binary(struct linux
 		if (error != N_DATADDR(ex))
 			return error;
 	}
+
 beyond_if:
-	set_binfmt(&aout_format);
+	error = set_brk(current->mm->start_brk, current->mm->brk);
+	if (error)
+		return error;
 
-	set_brk(current->mm->start_brk, current->mm->brk);
+	set_binfmt(&aout_format);
 
 	current->mm->start_stack =
 		(unsigned long)create_aout_tables((char __user *)bprm->p, bprm);
@@ -434,7 +440,9 @@ static int load_aout_library(struct file
 			error_time = jiffies;
 		}
 #endif
-		vm_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
+		retval = vm_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
+		if (retval)
+			goto out;
 
 		read_code(file, start_addr, N_TXTOFF(ex),
 			  ex.a_text + ex.a_data);
@@ -453,9 +461,8 @@ static int load_aout_library(struct file
 	len = PAGE_ALIGN(ex.a_text + ex.a_data);
 	bss = ex.a_text + ex.a_data + ex.a_bss;
 	if (bss > len) {
-		error = vm_brk(start_addr + len, bss - len);
-		retval = error;
-		if (error != start_addr + len)
+		retval = vm_brk(start_addr + len, bss - len);
+		if (retval)
 			goto out;
 	}
 	retval = 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/ia32/ia32_signal.c linux-libre-4.7-gnu/arch/x86/ia32/ia32_signal.c
--- linux-libre-4.6-gnu/arch/x86/ia32/ia32_signal.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/ia32/ia32_signal.c	2016-07-24 15:23:50.000000000 -0400
@@ -357,7 +357,7 @@ int ia32_setup_rt_frame(int sig, struct
 		put_user_ex(ptr_to_compat(&frame->uc), &frame->puc);
 
 		/* Create the ucontext.  */
-		if (cpu_has_xsave)
+		if (boot_cpu_has(X86_FEATURE_XSAVE))
 			put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);
 		else
 			put_user_ex(0, &frame->uc.uc_flags);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/alternative.h linux-libre-4.7-gnu/arch/x86/include/asm/alternative.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/alternative.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/alternative.h	2016-07-24 15:23:50.000000000 -0400
@@ -1,11 +1,12 @@
 #ifndef _ASM_X86_ALTERNATIVE_H
 #define _ASM_X86_ALTERNATIVE_H
 
+#ifndef __ASSEMBLY__
+
 #include <linux/types.h>
 #include <linux/stddef.h>
 #include <linux/stringify.h>
 #include <asm/asm.h>
-#include <asm/ptrace.h>
 
 /*
  * Alternative inline assembly for SMP.
@@ -233,36 +234,6 @@ static inline int alternatives_text_rese
  */
 #define ASM_NO_INPUT_CLOBBER(clbr...) "i" (0) : clbr
 
-struct paravirt_patch_site;
-#ifdef CONFIG_PARAVIRT
-void apply_paravirt(struct paravirt_patch_site *start,
-		    struct paravirt_patch_site *end);
-#else
-static inline void apply_paravirt(struct paravirt_patch_site *start,
-				  struct paravirt_patch_site *end)
-{}
-#define __parainstructions	NULL
-#define __parainstructions_end	NULL
-#endif
-
-extern void *text_poke_early(void *addr, const void *opcode, size_t len);
-
-/*
- * Clear and restore the kernel write-protection flag on the local CPU.
- * Allows the kernel to edit read-only pages.
- * Side-effect: any interrupt handler running between save and restore will have
- * the ability to write to read-only pages.
- *
- * Warning:
- * Code patching in the UP case is safe if NMIs and MCE handlers are stopped and
- * no thread can be preempted in the instructions being modified (no iret to an
- * invalid instruction possible) or if the instructions are changed from a
- * consistent state to another consistent state atomically.
- * On the local CPU you need to be protected again NMI or MCE handlers seeing an
- * inconsistent instruction while you patch.
- */
-extern void *text_poke(void *addr, const void *opcode, size_t len);
-extern int poke_int3_handler(struct pt_regs *regs);
-extern void *text_poke_bp(void *addr, const void *opcode, size_t len, void *handler);
+#endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_X86_ALTERNATIVE_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/apic.h linux-libre-4.7-gnu/arch/x86/include/asm/apic.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/apic.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/apic.h	2016-07-24 15:23:50.000000000 -0400
@@ -239,10 +239,10 @@ extern void __init check_x2apic(void);
 extern void x2apic_setup(void);
 static inline int x2apic_enabled(void)
 {
-	return cpu_has_x2apic && apic_is_x2apic_enabled();
+	return boot_cpu_has(X86_FEATURE_X2APIC) && apic_is_x2apic_enabled();
 }
 
-#define x2apic_supported()	(cpu_has_x2apic)
+#define x2apic_supported()	(boot_cpu_has(X86_FEATURE_X2APIC))
 #else /* !CONFIG_X86_X2APIC */
 static inline void check_x2apic(void) { }
 static inline void x2apic_setup(void) { }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/bios_ebda.h linux-libre-4.7-gnu/arch/x86/include/asm/bios_ebda.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/bios_ebda.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/bios_ebda.h	2016-07-24 15:23:50.000000000 -0400
@@ -17,27 +17,6 @@ static inline unsigned int get_bios_ebda
 	return address;	/* 0 means none */
 }
 
-/*
- * Return the sanitized length of the EBDA in bytes, if it exists.
- */
-static inline unsigned int get_bios_ebda_length(void)
-{
-	unsigned int address;
-	unsigned int length;
-
-	address = get_bios_ebda();
-	if (!address)
-		return 0;
-
-	/* EBDA length is byte 0 of the EBDA (stored in KiB) */
-	length = *(unsigned char *)phys_to_virt(address);
-	length <<= 10;
-
-	/* Trim the length if it extends beyond 640KiB */
-	length = min_t(unsigned int, (640 * 1024) - address, length);
-	return length;
-}
-
 void reserve_ebda_region(void);
 
 #ifdef CONFIG_X86_CHECK_BIOS_CORRUPTION
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/boot.h linux-libre-4.7-gnu/arch/x86/include/asm/boot.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/boot.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/boot.h	2016-07-24 15:23:50.000000000 -0400
@@ -12,29 +12,46 @@
 
 /* Minimum kernel alignment, as a power of two */
 #ifdef CONFIG_X86_64
-#define MIN_KERNEL_ALIGN_LG2	PMD_SHIFT
+# define MIN_KERNEL_ALIGN_LG2	PMD_SHIFT
 #else
-#define MIN_KERNEL_ALIGN_LG2	(PAGE_SHIFT + THREAD_SIZE_ORDER)
+# define MIN_KERNEL_ALIGN_LG2	(PAGE_SHIFT + THREAD_SIZE_ORDER)
 #endif
 #define MIN_KERNEL_ALIGN	(_AC(1, UL) << MIN_KERNEL_ALIGN_LG2)
 
 #if (CONFIG_PHYSICAL_ALIGN & (CONFIG_PHYSICAL_ALIGN-1)) || \
 	(CONFIG_PHYSICAL_ALIGN < MIN_KERNEL_ALIGN)
-#error "Invalid value for CONFIG_PHYSICAL_ALIGN"
+# error "Invalid value for CONFIG_PHYSICAL_ALIGN"
 #endif
 
 #ifdef CONFIG_KERNEL_BZIP2
-#define BOOT_HEAP_SIZE             0x400000
+# define BOOT_HEAP_SIZE		0x400000
 #else /* !CONFIG_KERNEL_BZIP2 */
+# define BOOT_HEAP_SIZE		 0x10000
+#endif
 
-#define BOOT_HEAP_SIZE	0x10000
+#ifdef CONFIG_X86_64
+# define BOOT_STACK_SIZE	0x4000
 
-#endif /* !CONFIG_KERNEL_BZIP2 */
+# define BOOT_INIT_PGT_SIZE	(6*4096)
+# ifdef CONFIG_RANDOMIZE_BASE
+/*
+ * Assuming all cross the 512GB boundary:
+ * 1 page for level4
+ * (2+2)*4 pages for kernel, param, cmd_line, and randomized kernel
+ * 2 pages for first 2M (video RAM: CONFIG_X86_VERBOSE_BOOTUP).
+ * Total is 19 pages.
+ */
+#  ifdef CONFIG_X86_VERBOSE_BOOTUP
+#   define BOOT_PGT_SIZE	(19*4096)
+#  else /* !CONFIG_X86_VERBOSE_BOOTUP */
+#   define BOOT_PGT_SIZE	(17*4096)
+#  endif
+# else /* !CONFIG_RANDOMIZE_BASE */
+#  define BOOT_PGT_SIZE		BOOT_INIT_PGT_SIZE
+# endif
 
-#ifdef CONFIG_X86_64
-#define BOOT_STACK_SIZE	0x4000
-#else
-#define BOOT_STACK_SIZE	0x1000
+#else /* !CONFIG_X86_64 */
+# define BOOT_STACK_SIZE	0x1000
 #endif
 
 #endif /* _ASM_X86_BOOT_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/bugs.h linux-libre-4.7-gnu/arch/x86/include/asm/bugs.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/bugs.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/bugs.h	2016-07-24 15:23:50.000000000 -0400
@@ -1,8 +1,16 @@
 #ifndef _ASM_X86_BUGS_H
 #define _ASM_X86_BUGS_H
 
+#include <asm/processor.h>
+
 extern void check_bugs(void);
 
+#if defined(CONFIG_CPU_SUP_INTEL)
+void check_mpx_erratum(struct cpuinfo_x86 *c);
+#else
+static inline void check_mpx_erratum(struct cpuinfo_x86 *c) {}
+#endif
+
 #if defined(CONFIG_CPU_SUP_INTEL) && defined(CONFIG_X86_32)
 int ppro_with_ram_bug(void);
 #else
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/clocksource.h linux-libre-4.7-gnu/arch/x86/include/asm/clocksource.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/clocksource.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/clocksource.h	2016-07-24 15:23:50.000000000 -0400
@@ -3,11 +3,10 @@
 #ifndef _ASM_X86_CLOCKSOURCE_H
 #define _ASM_X86_CLOCKSOURCE_H
 
-#define VCLOCK_NONE	0  /* No vDSO clock available.	*/
-#define VCLOCK_TSC	1  /* vDSO should use vread_tsc.	*/
-#define VCLOCK_HPET	2  /* vDSO should use vread_hpet.	*/
-#define VCLOCK_PVCLOCK	3 /* vDSO should use vread_pvclock. */
-#define VCLOCK_MAX	3
+#define VCLOCK_NONE	0	/* No vDSO clock available.		*/
+#define VCLOCK_TSC	1	/* vDSO should use vread_tsc.		*/
+#define VCLOCK_PVCLOCK	2	/* vDSO should use vread_pvclock.	*/
+#define VCLOCK_MAX	2
 
 struct arch_clocksource_data {
 	int vclock_mode;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/compat.h linux-libre-4.7-gnu/arch/x86/include/asm/compat.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/compat.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/compat.h	2016-07-24 15:23:50.000000000 -0400
@@ -307,7 +307,7 @@ static inline void __user *arch_compat_a
 	return (void __user *)round_down(sp - len, 16);
 }
 
-static inline bool is_x32_task(void)
+static inline bool in_x32_syscall(void)
 {
 #ifdef CONFIG_X86_X32_ABI
 	if (task_pt_regs(current)->orig_ax & __X32_SYSCALL_BIT)
@@ -318,7 +318,7 @@ static inline bool is_x32_task(void)
 
 static inline bool in_compat_syscall(void)
 {
-	return is_ia32_task() || is_x32_task();
+	return in_ia32_syscall() || in_x32_syscall();
 }
 #define in_compat_syscall in_compat_syscall	/* override the generic impl */
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/cpufeature.h linux-libre-4.7-gnu/arch/x86/include/asm/cpufeature.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/cpufeature.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/cpufeature.h	2016-07-24 15:23:50.000000000 -0400
@@ -27,6 +27,7 @@ enum cpuid_leafs
 	CPUID_6_EAX,
 	CPUID_8000_000A_EDX,
 	CPUID_7_ECX,
+	CPUID_8000_0007_EBX,
 };
 
 #ifdef CONFIG_X86_FEATURE_NAMES
@@ -63,9 +64,9 @@ extern const char * const x86_bug_flags[
 	   (((bit)>>5)==11 && (1UL<<((bit)&31) & REQUIRED_MASK11)) ||	\
 	   (((bit)>>5)==12 && (1UL<<((bit)&31) & REQUIRED_MASK12)) ||	\
 	   (((bit)>>5)==13 && (1UL<<((bit)&31) & REQUIRED_MASK13)) ||	\
-	   (((bit)>>5)==13 && (1UL<<((bit)&31) & REQUIRED_MASK14)) ||	\
-	   (((bit)>>5)==13 && (1UL<<((bit)&31) & REQUIRED_MASK15)) ||	\
-	   (((bit)>>5)==14 && (1UL<<((bit)&31) & REQUIRED_MASK16)) )
+	   (((bit)>>5)==14 && (1UL<<((bit)&31) & REQUIRED_MASK14)) ||	\
+	   (((bit)>>5)==15 && (1UL<<((bit)&31) & REQUIRED_MASK15)) ||	\
+	   (((bit)>>5)==16 && (1UL<<((bit)&31) & REQUIRED_MASK16)) )
 
 #define DISABLED_MASK_BIT_SET(bit)					\
 	 ( (((bit)>>5)==0  && (1UL<<((bit)&31) & DISABLED_MASK0 )) ||	\
@@ -82,9 +83,9 @@ extern const char * const x86_bug_flags[
 	   (((bit)>>5)==11 && (1UL<<((bit)&31) & DISABLED_MASK11)) ||	\
 	   (((bit)>>5)==12 && (1UL<<((bit)&31) & DISABLED_MASK12)) ||	\
 	   (((bit)>>5)==13 && (1UL<<((bit)&31) & DISABLED_MASK13)) ||	\
-	   (((bit)>>5)==13 && (1UL<<((bit)&31) & DISABLED_MASK14)) ||	\
-	   (((bit)>>5)==13 && (1UL<<((bit)&31) & DISABLED_MASK15)) ||	\
-	   (((bit)>>5)==14 && (1UL<<((bit)&31) & DISABLED_MASK16)) )
+	   (((bit)>>5)==14 && (1UL<<((bit)&31) & DISABLED_MASK14)) ||	\
+	   (((bit)>>5)==15 && (1UL<<((bit)&31) & DISABLED_MASK15)) ||	\
+	   (((bit)>>5)==16 && (1UL<<((bit)&31) & DISABLED_MASK16)) )
 
 #define cpu_has(c, bit)							\
 	(__builtin_constant_p(bit) && REQUIRED_MASK_BIT_SET(bit) ? 1 :	\
@@ -118,31 +119,6 @@ extern const char * const x86_bug_flags[
 	set_bit(bit, (unsigned long *)cpu_caps_set);	\
 } while (0)
 
-#define cpu_has_fpu		boot_cpu_has(X86_FEATURE_FPU)
-#define cpu_has_pse		boot_cpu_has(X86_FEATURE_PSE)
-#define cpu_has_tsc		boot_cpu_has(X86_FEATURE_TSC)
-#define cpu_has_pge		boot_cpu_has(X86_FEATURE_PGE)
-#define cpu_has_apic		boot_cpu_has(X86_FEATURE_APIC)
-#define cpu_has_fxsr		boot_cpu_has(X86_FEATURE_FXSR)
-#define cpu_has_xmm		boot_cpu_has(X86_FEATURE_XMM)
-#define cpu_has_xmm2		boot_cpu_has(X86_FEATURE_XMM2)
-#define cpu_has_aes		boot_cpu_has(X86_FEATURE_AES)
-#define cpu_has_avx		boot_cpu_has(X86_FEATURE_AVX)
-#define cpu_has_avx2		boot_cpu_has(X86_FEATURE_AVX2)
-#define cpu_has_clflush		boot_cpu_has(X86_FEATURE_CLFLUSH)
-#define cpu_has_gbpages		boot_cpu_has(X86_FEATURE_GBPAGES)
-#define cpu_has_arch_perfmon	boot_cpu_has(X86_FEATURE_ARCH_PERFMON)
-#define cpu_has_pat		boot_cpu_has(X86_FEATURE_PAT)
-#define cpu_has_x2apic		boot_cpu_has(X86_FEATURE_X2APIC)
-#define cpu_has_xsave		boot_cpu_has(X86_FEATURE_XSAVE)
-#define cpu_has_xsaves		boot_cpu_has(X86_FEATURE_XSAVES)
-#define cpu_has_osxsave		boot_cpu_has(X86_FEATURE_OSXSAVE)
-#define cpu_has_hypervisor	boot_cpu_has(X86_FEATURE_HYPERVISOR)
-/*
- * Do not add any more of those clumsy macros - use static_cpu_has() for
- * fast paths and boot_cpu_has() otherwise!
- */
-
 #if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_X86_FAST_FEATURE_TESTS)
 /*
  * Static testing of CPU features.  Used the same as boot_cpu_has().
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/cpufeatures.h linux-libre-4.7-gnu/arch/x86/include/asm/cpufeatures.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/cpufeatures.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/cpufeatures.h	2016-07-24 15:23:50.000000000 -0400
@@ -12,7 +12,7 @@
 /*
  * Defines x86 CPU feature bits
  */
-#define NCAPINTS	17	/* N 32-bit words worth of info */
+#define NCAPINTS	18	/* N 32-bit words worth of info */
 #define NBUGINTS	1	/* N 32-bit bug flags */
 
 /*
@@ -177,6 +177,7 @@
 #define X86_FEATURE_PERFCTR_CORE ( 6*32+23) /* core performance counter extensions */
 #define X86_FEATURE_PERFCTR_NB  ( 6*32+24) /* NB performance counter extensions */
 #define X86_FEATURE_BPEXT	(6*32+26) /* data breakpoint extension */
+#define X86_FEATURE_PTSC	( 6*32+27) /* performance time-stamp counter */
 #define X86_FEATURE_PERFCTR_L2	( 6*32+28) /* L2 performance counter extensions */
 #define X86_FEATURE_MWAITX	( 6*32+29) /* MWAIT extension (MONITORX/MWAITX) */
 
@@ -250,6 +251,7 @@
 
 /* AMD-defined CPU features, CPUID level 0x80000008 (ebx), word 13 */
 #define X86_FEATURE_CLZERO	(13*32+0) /* CLZERO instruction */
+#define X86_FEATURE_IRPERF	(13*32+1) /* Instructions Retired Count */
 
 /* Thermal and Power Management Leaf, CPUID level 0x00000006 (eax), word 14 */
 #define X86_FEATURE_DTHERM	(14*32+ 0) /* Digital Thermal Sensor */
@@ -280,6 +282,11 @@
 #define X86_FEATURE_PKU		(16*32+ 3) /* Protection Keys for Userspace */
 #define X86_FEATURE_OSPKE	(16*32+ 4) /* OS Protection Keys Enable */
 
+/* AMD-defined CPU features, CPUID level 0x80000007 (ebx), word 17 */
+#define X86_FEATURE_OVERFLOW_RECOV (17*32+0) /* MCA overflow recovery support */
+#define X86_FEATURE_SUCCOR	(17*32+1) /* Uncorrectable error containment and recovery */
+#define X86_FEATURE_SMCA	(17*32+3) /* Scalable MCA */
+
 /*
  * BUG word(s)
  */
@@ -294,7 +301,6 @@
 #define X86_BUG_FXSAVE_LEAK	X86_BUG(6) /* FXSAVE leaks FOP/FIP/FOP */
 #define X86_BUG_CLFLUSH_MONITOR	X86_BUG(7) /* AAI65, CLFLUSH required before MONITOR */
 #define X86_BUG_SYSRET_SS_ATTRS	X86_BUG(8) /* SYSRET doesn't fix up SS attrs */
-
 #ifdef CONFIG_X86_32
 /*
  * 64-bit kernels don't use X86_BUG_ESPFIX.  Make the define conditional
@@ -302,5 +308,7 @@
  */
 #define X86_BUG_ESPFIX		X86_BUG(9) /* "" IRET to 16-bit SS corrupts ESP/RSP high bits */
 #endif
+#define X86_BUG_NULL_SEG	X86_BUG(10) /* Nulling a selector preserves the base */
+#define X86_BUG_SWAPGS_FENCE	X86_BUG(11) /* SWAPGS without input dep on GS */
 
 #endif /* _ASM_X86_CPUFEATURES_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/disabled-features.h linux-libre-4.7-gnu/arch/x86/include/asm/disabled-features.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/disabled-features.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/disabled-features.h	2016-07-24 15:23:50.000000000 -0400
@@ -29,11 +29,11 @@
 #endif /* CONFIG_X86_64 */
 
 #ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
-# define DISABLE_PKU		(1<<(X86_FEATURE_PKU))
-# define DISABLE_OSPKE		(1<<(X86_FEATURE_OSPKE))
-#else
 # define DISABLE_PKU		0
 # define DISABLE_OSPKE		0
+#else
+# define DISABLE_PKU		(1<<(X86_FEATURE_PKU & 31))
+# define DISABLE_OSPKE		(1<<(X86_FEATURE_OSPKE & 31))
 #endif /* CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS */
 
 /*
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/efi.h linux-libre-4.7-gnu/arch/x86/include/asm/efi.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/efi.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/efi.h	2016-07-24 15:23:50.000000000 -0400
@@ -3,6 +3,7 @@
 
 #include <asm/fpu/api.h>
 #include <asm/pgtable.h>
+#include <asm/processor-flags.h>
 #include <asm/tlb.h>
 
 /*
@@ -28,33 +29,22 @@
 
 #define MAX_CMDLINE_ADDRESS	UINT_MAX
 
-#ifdef CONFIG_X86_32
+#define ARCH_EFI_IRQ_FLAGS_MASK	X86_EFLAGS_IF
 
+#ifdef CONFIG_X86_32
 
 extern unsigned long asmlinkage efi_call_phys(void *, ...);
 
+#define arch_efi_call_virt_setup()	kernel_fpu_begin()
+#define arch_efi_call_virt_teardown()	kernel_fpu_end()
+
 /*
  * Wrap all the virtual calls in a way that forces the parameters on the stack.
  */
-
-/* Use this macro if your virtual returns a non-void value */
-#define efi_call_virt(f, args...) \
-({									\
-	efi_status_t __s;						\
-	kernel_fpu_begin();						\
-	__s = ((efi_##f##_t __attribute__((regparm(0)))*)		\
-		efi.systab->runtime->f)(args);				\
-	kernel_fpu_end();						\
-	__s;								\
-})
-
-/* Use this macro if your virtual call does not return any value */
-#define __efi_call_virt(f, args...) \
+#define arch_efi_call_virt(f, args...)					\
 ({									\
-	kernel_fpu_begin();						\
 	((efi_##f##_t __attribute__((regparm(0)))*)			\
 		efi.systab->runtime->f)(args);				\
-	kernel_fpu_end();						\
 })
 
 #define efi_ioremap(addr, size, type, attr)	ioremap_cache(addr, size)
@@ -78,10 +68,8 @@ struct efi_scratch {
 	u64	phys_stack;
 } __packed;
 
-#define efi_call_virt(f, ...)						\
+#define arch_efi_call_virt_setup()					\
 ({									\
-	efi_status_t __s;						\
-									\
 	efi_sync_low_kernel_mappings();					\
 	preempt_disable();						\
 	__kernel_fpu_begin();						\
@@ -91,9 +79,13 @@ struct efi_scratch {
 		write_cr3((unsigned long)efi_scratch.efi_pgt);		\
 		__flush_tlb_all();					\
 	}								\
-									\
-	__s = efi_call((void *)efi.systab->runtime->f, __VA_ARGS__);	\
-									\
+})
+
+#define arch_efi_call_virt(f, args...)					\
+	efi_call((void *)efi.systab->runtime->f, args)			\
+
+#define arch_efi_call_virt_teardown()					\
+({									\
 	if (efi_scratch.use_pgd) {					\
 		write_cr3(efi_scratch.prev_cr3);			\
 		__flush_tlb_all();					\
@@ -101,15 +93,8 @@ struct efi_scratch {
 									\
 	__kernel_fpu_end();						\
 	preempt_enable();						\
-	__s;								\
 })
 
-/*
- * All X86_64 virt calls return non-void values. Thus, use non-void call for
- * virt calls that would be void on X86_32.
- */
-#define __efi_call_virt(f, args...) efi_call_virt(f, args)
-
 extern void __iomem *__init efi_ioremap(unsigned long addr, unsigned long size,
 					u32 type, u64 attribute);
 
@@ -180,6 +165,8 @@ static inline bool efi_runtime_supported
 extern struct console early_efi_console;
 extern void parse_efi_setup(u64 phys_addr, u32 data_len);
 
+extern void efifb_setup_from_dmi(struct screen_info *si, const char *opt);
+
 #ifdef CONFIG_EFI_MIXED
 extern void efi_thunk_runtime_setup(void);
 extern efi_status_t efi_thunk_set_virtual_address_map(
@@ -225,6 +212,11 @@ __pure const struct efi_config *__efi_ea
 #define efi_call_early(f, ...)						\
 	__efi_early()->call(__efi_early()->f, __VA_ARGS__);
 
+#define __efi_call_early(f, ...)					\
+	__efi_early()->call((unsigned long)f, __VA_ARGS__);
+
+#define efi_is_64bit()		__efi_early()->is64
+
 extern bool efi_reboot_required(void);
 
 #else
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/elf.h linux-libre-4.7-gnu/arch/x86/include/asm/elf.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/elf.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/elf.h	2016-07-24 15:23:50.000000000 -0400
@@ -176,7 +176,7 @@ static inline void elf_common_init(struc
 	regs->si = regs->di = regs->bp = 0;
 	regs->r8 = regs->r9 = regs->r10 = regs->r11 = 0;
 	regs->r12 = regs->r13 = regs->r14 = regs->r15 = 0;
-	t->fs = t->gs = 0;
+	t->fsbase = t->gsbase = 0;
 	t->fsindex = t->gsindex = 0;
 	t->ds = t->es = ds;
 }
@@ -226,8 +226,8 @@ do {								\
 	(pr_reg)[18] = (regs)->flags;				\
 	(pr_reg)[19] = (regs)->sp;				\
 	(pr_reg)[20] = (regs)->ss;				\
-	(pr_reg)[21] = current->thread.fs;			\
-	(pr_reg)[22] = current->thread.gs;			\
+	(pr_reg)[21] = current->thread.fsbase;			\
+	(pr_reg)[22] = current->thread.gsbase;			\
 	asm("movl %%ds,%0" : "=r" (v)); (pr_reg)[23] = v;	\
 	asm("movl %%es,%0" : "=r" (v)); (pr_reg)[24] = v;	\
 	asm("movl %%fs,%0" : "=r" (v)); (pr_reg)[25] = v;	\
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/hugetlb.h linux-libre-4.7-gnu/arch/x86/include/asm/hugetlb.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/hugetlb.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/hugetlb.h	2016-07-24 15:23:50.000000000 -0400
@@ -4,7 +4,7 @@
 #include <asm/page.h>
 #include <asm-generic/hugetlb.h>
 
-#define hugepages_supported() cpu_has_pse
+#define hugepages_supported() boot_cpu_has(X86_FEATURE_PSE)
 
 static inline int is_hugepage_only_range(struct mm_struct *mm,
 					 unsigned long addr,
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/intel-family.h linux-libre-4.7-gnu/arch/x86/include/asm/intel-family.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/intel-family.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/x86/include/asm/intel-family.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,68 @@
+#ifndef _ASM_X86_INTEL_FAMILY_H
+#define _ASM_X86_INTEL_FAMILY_H
+
+/*
+ * "Big Core" Processors (Branded as Core, Xeon, etc...)
+ *
+ * The "_X" parts are generally the EP and EX Xeons, or the
+ * "Extreme" ones, like Broadwell-E.
+ *
+ * Things ending in "2" are usually because we have no better
+ * name for them.  There's no processor called "WESTMERE2".
+ */
+
+#define INTEL_FAM6_CORE_YONAH		0x0E
+#define INTEL_FAM6_CORE2_MEROM		0x0F
+#define INTEL_FAM6_CORE2_MEROM_L	0x16
+#define INTEL_FAM6_CORE2_PENRYN		0x17
+#define INTEL_FAM6_CORE2_DUNNINGTON	0x1D
+
+#define INTEL_FAM6_NEHALEM		0x1E
+#define INTEL_FAM6_NEHALEM_EP		0x1A
+#define INTEL_FAM6_NEHALEM_EX		0x2E
+#define INTEL_FAM6_WESTMERE		0x25
+#define INTEL_FAM6_WESTMERE2		0x1F
+#define INTEL_FAM6_WESTMERE_EP		0x2C
+#define INTEL_FAM6_WESTMERE_EX		0x2F
+
+#define INTEL_FAM6_SANDYBRIDGE		0x2A
+#define INTEL_FAM6_SANDYBRIDGE_X	0x2D
+#define INTEL_FAM6_IVYBRIDGE		0x3A
+#define INTEL_FAM6_IVYBRIDGE_X		0x3E
+
+#define INTEL_FAM6_HASWELL_CORE		0x3C
+#define INTEL_FAM6_HASWELL_X		0x3F
+#define INTEL_FAM6_HASWELL_ULT		0x45
+#define INTEL_FAM6_HASWELL_GT3E		0x46
+
+#define INTEL_FAM6_BROADWELL_CORE	0x3D
+#define INTEL_FAM6_BROADWELL_XEON_D	0x56
+#define INTEL_FAM6_BROADWELL_GT3E	0x47
+#define INTEL_FAM6_BROADWELL_X		0x4F
+
+#define INTEL_FAM6_SKYLAKE_MOBILE	0x4E
+#define INTEL_FAM6_SKYLAKE_DESKTOP	0x5E
+#define INTEL_FAM6_SKYLAKE_X		0x55
+#define INTEL_FAM6_KABYLAKE_MOBILE	0x8E
+#define INTEL_FAM6_KABYLAKE_DESKTOP	0x9E
+
+/* "Small Core" Processors (Atom) */
+
+#define INTEL_FAM6_ATOM_PINEVIEW	0x1C
+#define INTEL_FAM6_ATOM_LINCROFT	0x26
+#define INTEL_FAM6_ATOM_PENWELL		0x27
+#define INTEL_FAM6_ATOM_CLOVERVIEW	0x35
+#define INTEL_FAM6_ATOM_CEDARVIEW	0x36
+#define INTEL_FAM6_ATOM_SILVERMONT1	0x37 /* BayTrail/BYT / Valleyview */
+#define INTEL_FAM6_ATOM_SILVERMONT2	0x4D /* Avaton/Rangely */
+#define INTEL_FAM6_ATOM_AIRMONT		0x4C /* CherryTrail / Braswell */
+#define INTEL_FAM6_ATOM_MERRIFIELD1	0x4A /* Tangier */
+#define INTEL_FAM6_ATOM_MERRIFIELD2	0x5A /* Annidale */
+#define INTEL_FAM6_ATOM_GOLDMONT	0x5C
+#define INTEL_FAM6_ATOM_DENVERTON	0x5F /* Goldmont Microserver */
+
+/* Xeon Phi */
+
+#define INTEL_FAM6_XEON_PHI_KNL		0x57 /* Knights Landing */
+
+#endif /* _ASM_X86_INTEL_FAMILY_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/intel_telemetry.h linux-libre-4.7-gnu/arch/x86/include/asm/intel_telemetry.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/intel_telemetry.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/intel_telemetry.h	2016-07-24 15:23:50.000000000 -0400
@@ -99,7 +99,7 @@ struct telemetry_core_ops {
 	int (*reset_events)(void);
 };
 
-int telemetry_set_pltdata(struct telemetry_core_ops *ops,
+int telemetry_set_pltdata(const struct telemetry_core_ops *ops,
 			  struct telemetry_plt_config *pltconfig);
 
 int telemetry_clear_pltdata(void);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/irq_work.h linux-libre-4.7-gnu/arch/x86/include/asm/irq_work.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/irq_work.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/irq_work.h	2016-07-24 15:23:50.000000000 -0400
@@ -5,7 +5,7 @@
 
 static inline bool arch_irq_work_has_interrupt(void)
 {
-	return cpu_has_apic;
+	return boot_cpu_has(X86_FEATURE_APIC);
 }
 
 #endif /* _ASM_IRQ_WORK_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/kgdb.h linux-libre-4.7-gnu/arch/x86/include/asm/kgdb.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/kgdb.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/kgdb.h	2016-07-24 15:23:50.000000000 -0400
@@ -6,6 +6,8 @@
  * Copyright (C) 2008 Wind River Systems, Inc.
  */
 
+#include <asm/ptrace.h>
+
 /*
  * BUFMAX defines the maximum number of characters in inbound/outbound
  * buffers at least NUMREGBYTES*2 are needed for register packets
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/kprobes.h linux-libre-4.7-gnu/arch/x86/include/asm/kprobes.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/kprobes.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/kprobes.h	2016-07-24 15:23:50.000000000 -0400
@@ -38,12 +38,11 @@ typedef u8 kprobe_opcode_t;
 #define RELATIVECALL_OPCODE 0xe8
 #define RELATIVE_ADDR_SIZE 4
 #define MAX_STACK_SIZE 64
-#define MIN_STACK_SIZE(ADDR)					       \
-	(((MAX_STACK_SIZE) < (((unsigned long)current_thread_info()) + \
-			      THREAD_SIZE - (unsigned long)(ADDR)))    \
-	 ? (MAX_STACK_SIZE)					       \
-	 : (((unsigned long)current_thread_info()) +		       \
-	    THREAD_SIZE - (unsigned long)(ADDR)))
+#define CUR_STACK_SIZE(ADDR) \
+	(current_top_of_stack() - (unsigned long)(ADDR))
+#define MIN_STACK_SIZE(ADDR)				\
+	(MAX_STACK_SIZE < CUR_STACK_SIZE(ADDR) ?	\
+	 MAX_STACK_SIZE : CUR_STACK_SIZE(ADDR))
 
 #define flush_insn_slot(p)	do { } while (0)
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/kvm_host.h linux-libre-4.7-gnu/arch/x86/include/asm/kvm_host.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/kvm_host.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/kvm_host.h	2016-07-24 15:23:50.000000000 -0400
@@ -27,6 +27,7 @@
 #include <linux/irqbypass.h>
 #include <linux/hyperv.h>
 
+#include <asm/apic.h>
 #include <asm/pvclock-abi.h>
 #include <asm/desc.h>
 #include <asm/mtrr.h>
@@ -562,7 +563,6 @@ struct kvm_vcpu_arch {
 	struct {
 		u64 msr_val;
 		u64 last_steal;
-		u64 accum_steal;
 		struct gfn_to_hva_cache stime;
 		struct kvm_steal_time steal;
 	} st;
@@ -774,6 +774,11 @@ struct kvm_arch {
 	u8 nr_reserved_ioapic_pins;
 
 	bool disabled_lapic_found;
+
+	/* Struct members for AVIC */
+	u32 ldr_mode;
+	struct page *avic_logical_id_table_page;
+	struct page *avic_physical_id_table_page;
 };
 
 struct kvm_vm_stat {
@@ -804,6 +809,7 @@ struct kvm_vcpu_stat {
 	u32 halt_exits;
 	u32 halt_successful_poll;
 	u32 halt_attempted_poll;
+	u32 halt_poll_invalid;
 	u32 halt_wakeup;
 	u32 request_irq_exits;
 	u32 irq_exits;
@@ -848,6 +854,9 @@ struct kvm_x86_ops {
 	bool (*cpu_has_high_real_mode_segbase)(void);
 	void (*cpuid_update)(struct kvm_vcpu *vcpu);
 
+	int (*vm_init)(struct kvm *kvm);
+	void (*vm_destroy)(struct kvm *kvm);
+
 	/* Create, but do not attach this VCPU */
 	struct kvm_vcpu *(*vcpu_create)(struct kvm *kvm, unsigned id);
 	void (*vcpu_free)(struct kvm_vcpu *vcpu);
@@ -914,7 +923,7 @@ struct kvm_x86_ops {
 	bool (*get_enable_apicv)(void);
 	void (*refresh_apicv_exec_ctrl)(struct kvm_vcpu *vcpu);
 	void (*hwapic_irr_update)(struct kvm_vcpu *vcpu, int max_irr);
-	void (*hwapic_isr_update)(struct kvm *kvm, int isr);
+	void (*hwapic_isr_update)(struct kvm_vcpu *vcpu, int isr);
 	void (*load_eoi_exitmap)(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap);
 	void (*set_virtual_x2apic_mode)(struct kvm_vcpu *vcpu, bool set);
 	void (*set_apic_access_page_addr)(struct kvm_vcpu *vcpu, hpa_t hpa);
@@ -990,8 +999,13 @@ struct kvm_x86_ops {
 	 */
 	int (*pre_block)(struct kvm_vcpu *vcpu);
 	void (*post_block)(struct kvm_vcpu *vcpu);
+
+	void (*vcpu_blocking)(struct kvm_vcpu *vcpu);
+	void (*vcpu_unblocking)(struct kvm_vcpu *vcpu);
+
 	int (*update_pi_irte)(struct kvm *kvm, unsigned int host_irq,
 			      uint32_t guest_irq, bool set);
+	void (*apicv_post_state_restore)(struct kvm_vcpu *vcpu);
 };
 
 struct kvm_arch_async_pf {
@@ -1341,7 +1355,28 @@ bool kvm_intr_is_single_vcpu(struct kvm
 void kvm_set_msi_irq(struct kvm_kernel_irq_routing_entry *e,
 		     struct kvm_lapic_irq *irq);
 
-static inline void kvm_arch_vcpu_blocking(struct kvm_vcpu *vcpu) {}
-static inline void kvm_arch_vcpu_unblocking(struct kvm_vcpu *vcpu) {}
+static inline void kvm_arch_vcpu_blocking(struct kvm_vcpu *vcpu)
+{
+	if (kvm_x86_ops->vcpu_blocking)
+		kvm_x86_ops->vcpu_blocking(vcpu);
+}
+
+static inline void kvm_arch_vcpu_unblocking(struct kvm_vcpu *vcpu)
+{
+	if (kvm_x86_ops->vcpu_unblocking)
+		kvm_x86_ops->vcpu_unblocking(vcpu);
+}
+
+static inline void kvm_arch_vcpu_block_finish(struct kvm_vcpu *vcpu) {}
+
+static inline int kvm_cpu_get_apicid(int mps_cpu)
+{
+#ifdef CONFIG_X86_LOCAL_APIC
+	return __default_cpu_present_to_apicid(mps_cpu);
+#else
+	WARN_ON_ONCE(1);
+	return BAD_APICID;
+#endif
+}
 
 #endif /* _ASM_X86_KVM_HOST_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/linkage.h linux-libre-4.7-gnu/arch/x86/include/asm/linkage.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/linkage.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/linkage.h	2016-07-24 15:23:50.000000000 -0400
@@ -8,40 +8,6 @@
 
 #ifdef CONFIG_X86_32
 #define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0)))
-
-/*
- * Make sure the compiler doesn't do anything stupid with the
- * arguments on the stack - they are owned by the *caller*, not
- * the callee. This just fools gcc into not spilling into them,
- * and keeps it from doing tailcall recursion and/or using the
- * stack slots for temporaries, since they are live and "used"
- * all the way to the end of the function.
- *
- * NOTE! On x86-64, all the arguments are in registers, so this
- * only matters on a 32-bit kernel.
- */
-#define asmlinkage_protect(n, ret, args...) \
-	__asmlinkage_protect##n(ret, ##args)
-#define __asmlinkage_protect_n(ret, args...) \
-	__asm__ __volatile__ ("" : "=r" (ret) : "0" (ret), ##args)
-#define __asmlinkage_protect0(ret) \
-	__asmlinkage_protect_n(ret)
-#define __asmlinkage_protect1(ret, arg1) \
-	__asmlinkage_protect_n(ret, "m" (arg1))
-#define __asmlinkage_protect2(ret, arg1, arg2) \
-	__asmlinkage_protect_n(ret, "m" (arg1), "m" (arg2))
-#define __asmlinkage_protect3(ret, arg1, arg2, arg3) \
-	__asmlinkage_protect_n(ret, "m" (arg1), "m" (arg2), "m" (arg3))
-#define __asmlinkage_protect4(ret, arg1, arg2, arg3, arg4) \
-	__asmlinkage_protect_n(ret, "m" (arg1), "m" (arg2), "m" (arg3), \
-			      "m" (arg4))
-#define __asmlinkage_protect5(ret, arg1, arg2, arg3, arg4, arg5) \
-	__asmlinkage_protect_n(ret, "m" (arg1), "m" (arg2), "m" (arg3), \
-			      "m" (arg4), "m" (arg5))
-#define __asmlinkage_protect6(ret, arg1, arg2, arg3, arg4, arg5, arg6) \
-	__asmlinkage_protect_n(ret, "m" (arg1), "m" (arg2), "m" (arg3), \
-			      "m" (arg4), "m" (arg5), "m" (arg6))
-
 #endif /* CONFIG_X86_32 */
 
 #ifdef __ASSEMBLY__
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/livepatch.h linux-libre-4.7-gnu/arch/x86/include/asm/livepatch.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/livepatch.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/livepatch.h	2016-07-24 15:23:50.000000000 -0400
@@ -32,8 +32,6 @@ static inline int klp_check_compiler_sup
 #endif
 	return 0;
 }
-int klp_write_module_reloc(struct module *mod, unsigned long type,
-			   unsigned long loc, unsigned long value);
 
 static inline void klp_arch_set_pc(struct pt_regs *regs, unsigned long ip)
 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/mce.h linux-libre-4.7-gnu/arch/x86/include/asm/mce.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/mce.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/mce.h	2016-07-24 15:23:50.000000000 -0400
@@ -104,13 +104,23 @@
 #define MCE_LOG_SIGNATURE	"MACHINECHECK"
 
 /* AMD Scalable MCA */
+#define MSR_AMD64_SMCA_MC0_CTL		0xc0002000
+#define MSR_AMD64_SMCA_MC0_STATUS	0xc0002001
+#define MSR_AMD64_SMCA_MC0_ADDR		0xc0002002
 #define MSR_AMD64_SMCA_MC0_MISC0	0xc0002003
 #define MSR_AMD64_SMCA_MC0_CONFIG	0xc0002004
 #define MSR_AMD64_SMCA_MC0_IPID		0xc0002005
+#define MSR_AMD64_SMCA_MC0_DESTAT	0xc0002008
+#define MSR_AMD64_SMCA_MC0_DEADDR	0xc0002009
 #define MSR_AMD64_SMCA_MC0_MISC1	0xc000200a
+#define MSR_AMD64_SMCA_MCx_CTL(x)	(MSR_AMD64_SMCA_MC0_CTL + 0x10*(x))
+#define MSR_AMD64_SMCA_MCx_STATUS(x)	(MSR_AMD64_SMCA_MC0_STATUS + 0x10*(x))
+#define MSR_AMD64_SMCA_MCx_ADDR(x)	(MSR_AMD64_SMCA_MC0_ADDR + 0x10*(x))
 #define MSR_AMD64_SMCA_MCx_MISC(x)	(MSR_AMD64_SMCA_MC0_MISC0 + 0x10*(x))
 #define MSR_AMD64_SMCA_MCx_CONFIG(x)	(MSR_AMD64_SMCA_MC0_CONFIG + 0x10*(x))
 #define MSR_AMD64_SMCA_MCx_IPID(x)	(MSR_AMD64_SMCA_MC0_IPID + 0x10*(x))
+#define MSR_AMD64_SMCA_MCx_DESTAT(x)	(MSR_AMD64_SMCA_MC0_DESTAT + 0x10*(x))
+#define MSR_AMD64_SMCA_MCx_DEADDR(x)	(MSR_AMD64_SMCA_MC0_DEADDR + 0x10*(x))
 #define MSR_AMD64_SMCA_MCx_MISCy(x, y)	((MSR_AMD64_SMCA_MC0_MISC1 + y) + (0x10*(x)))
 
 /*
@@ -168,9 +178,18 @@ struct mce_vendor_flags {
 
 	      __reserved_0	: 61;
 };
+
+struct mca_msr_regs {
+	u32 (*ctl)	(int bank);
+	u32 (*status)	(int bank);
+	u32 (*addr)	(int bank);
+	u32 (*misc)	(int bank);
+};
+
 extern struct mce_vendor_flags mce_flags;
 
 extern struct mca_config mca_cfg;
+extern struct mca_msr_regs msr_ops;
 extern void mce_register_decode_chain(struct notifier_block *nb);
 extern void mce_unregister_decode_chain(struct notifier_block *nb);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/mmu_context.h linux-libre-4.7-gnu/arch/x86/include/asm/mmu_context.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/mmu_context.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/mmu_context.h	2016-07-24 15:23:50.000000000 -0400
@@ -115,103 +115,12 @@ static inline void destroy_context(struc
 	destroy_context_ldt(mm);
 }
 
-static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
-			     struct task_struct *tsk)
-{
-	unsigned cpu = smp_processor_id();
-
-	if (likely(prev != next)) {
-#ifdef CONFIG_SMP
-		this_cpu_write(cpu_tlbstate.state, TLBSTATE_OK);
-		this_cpu_write(cpu_tlbstate.active_mm, next);
-#endif
-		cpumask_set_cpu(cpu, mm_cpumask(next));
-
-		/*
-		 * Re-load page tables.
-		 *
-		 * This logic has an ordering constraint:
-		 *
-		 *  CPU 0: Write to a PTE for 'next'
-		 *  CPU 0: load bit 1 in mm_cpumask.  if nonzero, send IPI.
-		 *  CPU 1: set bit 1 in next's mm_cpumask
-		 *  CPU 1: load from the PTE that CPU 0 writes (implicit)
-		 *
-		 * We need to prevent an outcome in which CPU 1 observes
-		 * the new PTE value and CPU 0 observes bit 1 clear in
-		 * mm_cpumask.  (If that occurs, then the IPI will never
-		 * be sent, and CPU 0's TLB will contain a stale entry.)
-		 *
-		 * The bad outcome can occur if either CPU's load is
-		 * reordered before that CPU's store, so both CPUs must
-		 * execute full barriers to prevent this from happening.
-		 *
-		 * Thus, switch_mm needs a full barrier between the
-		 * store to mm_cpumask and any operation that could load
-		 * from next->pgd.  TLB fills are special and can happen
-		 * due to instruction fetches or for no reason at all,
-		 * and neither LOCK nor MFENCE orders them.
-		 * Fortunately, load_cr3() is serializing and gives the
-		 * ordering guarantee we need.
-		 *
-		 */
-		load_cr3(next->pgd);
-
-		trace_tlb_flush(TLB_FLUSH_ON_TASK_SWITCH, TLB_FLUSH_ALL);
-
-		/* Stop flush ipis for the previous mm */
-		cpumask_clear_cpu(cpu, mm_cpumask(prev));
-
-		/* Load per-mm CR4 state */
-		load_mm_cr4(next);
-
-#ifdef CONFIG_MODIFY_LDT_SYSCALL
-		/*
-		 * Load the LDT, if the LDT is different.
-		 *
-		 * It's possible that prev->context.ldt doesn't match
-		 * the LDT register.  This can happen if leave_mm(prev)
-		 * was called and then modify_ldt changed
-		 * prev->context.ldt but suppressed an IPI to this CPU.
-		 * In this case, prev->context.ldt != NULL, because we
-		 * never set context.ldt to NULL while the mm still
-		 * exists.  That means that next->context.ldt !=
-		 * prev->context.ldt, because mms never share an LDT.
-		 */
-		if (unlikely(prev->context.ldt != next->context.ldt))
-			load_mm_ldt(next);
-#endif
-	}
-#ifdef CONFIG_SMP
-	  else {
-		this_cpu_write(cpu_tlbstate.state, TLBSTATE_OK);
-		BUG_ON(this_cpu_read(cpu_tlbstate.active_mm) != next);
-
-		if (!cpumask_test_cpu(cpu, mm_cpumask(next))) {
-			/*
-			 * On established mms, the mm_cpumask is only changed
-			 * from irq context, from ptep_clear_flush() while in
-			 * lazy tlb mode, and here. Irqs are blocked during
-			 * schedule, protecting us from simultaneous changes.
-			 */
-			cpumask_set_cpu(cpu, mm_cpumask(next));
+extern void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+		      struct task_struct *tsk);
 
-			/*
-			 * We were in lazy tlb mode and leave_mm disabled
-			 * tlb flush IPI delivery. We must reload CR3
-			 * to make sure to use no freed page tables.
-			 *
-			 * As above, load_cr3() is serializing and orders TLB
-			 * fills with respect to the mm_cpumask write.
-			 */
-			load_cr3(next->pgd);
-			trace_tlb_flush(TLB_FLUSH_ON_TASK_SWITCH, TLB_FLUSH_ALL);
-			load_mm_cr4(next);
-			load_mm_ldt(next);
-		}
-	}
-#endif
-}
+extern void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
+			       struct task_struct *tsk);
+#define switch_mm_irqs_off switch_mm_irqs_off
 
 #define activate_mm(prev, next)			\
 do {						\
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/msr.h linux-libre-4.7-gnu/arch/x86/include/asm/msr.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/msr.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/msr.h	2016-07-24 15:23:50.000000000 -0400
@@ -84,7 +84,10 @@ static inline unsigned long long native_
 {
 	DECLARE_ARGS(val, low, high);
 
-	asm volatile("rdmsr" : EAX_EDX_RET(val, low, high) : "c" (msr));
+	asm volatile("1: rdmsr\n"
+		     "2:\n"
+		     _ASM_EXTABLE_HANDLE(1b, 2b, ex_handler_rdmsr_unsafe)
+		     : EAX_EDX_RET(val, low, high) : "c" (msr));
 	if (msr_tracepoint_active(__tracepoint_read_msr))
 		do_trace_read_msr(msr, EAX_EDX_VAL(val, low, high), 0);
 	return EAX_EDX_VAL(val, low, high);
@@ -98,7 +101,10 @@ static inline unsigned long long native_
 	asm volatile("2: rdmsr ; xor %[err],%[err]\n"
 		     "1:\n\t"
 		     ".section .fixup,\"ax\"\n\t"
-		     "3:  mov %[fault],%[err] ; jmp 1b\n\t"
+		     "3: mov %[fault],%[err]\n\t"
+		     "xorl %%eax, %%eax\n\t"
+		     "xorl %%edx, %%edx\n\t"
+		     "jmp 1b\n\t"
 		     ".previous\n\t"
 		     _ASM_EXTABLE(2b, 3b)
 		     : [err] "=r" (*err), EAX_EDX_RET(val, low, high)
@@ -108,11 +114,15 @@ static inline unsigned long long native_
 	return EAX_EDX_VAL(val, low, high);
 }
 
-static inline void native_write_msr(unsigned int msr,
-				    unsigned low, unsigned high)
+/* Can be uninlined because referenced by paravirt */
+notrace static inline void native_write_msr(unsigned int msr,
+					    unsigned low, unsigned high)
 {
-	asm volatile("wrmsr" : : "c" (msr), "a"(low), "d" (high) : "memory");
-	if (msr_tracepoint_active(__tracepoint_read_msr))
+	asm volatile("1: wrmsr\n"
+		     "2:\n"
+		     _ASM_EXTABLE_HANDLE(1b, 2b, ex_handler_wrmsr_unsafe)
+		     : : "c" (msr), "a"(low), "d" (high) : "memory");
+	if (msr_tracepoint_active(__tracepoint_write_msr))
 		do_trace_write_msr(msr, ((u64)high << 32 | low), 0);
 }
 
@@ -131,7 +141,7 @@ notrace static inline int native_write_m
 		     : "c" (msr), "0" (low), "d" (high),
 		       [fault] "i" (-EIO)
 		     : "memory");
-	if (msr_tracepoint_active(__tracepoint_read_msr))
+	if (msr_tracepoint_active(__tracepoint_write_msr))
 		do_trace_write_msr(msr, ((u64)high << 32 | low), err);
 	return err;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/msr-index.h linux-libre-4.7-gnu/arch/x86/include/asm/msr-index.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/msr-index.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/msr-index.h	2016-07-24 15:23:50.000000000 -0400
@@ -89,27 +89,16 @@
 #define MSR_PEBS_LD_LAT_THRESHOLD	0x000003f6
 
 #define MSR_IA32_RTIT_CTL		0x00000570
-#define RTIT_CTL_TRACEEN		BIT(0)
-#define RTIT_CTL_CYCLEACC		BIT(1)
-#define RTIT_CTL_OS			BIT(2)
-#define RTIT_CTL_USR			BIT(3)
-#define RTIT_CTL_CR3EN			BIT(7)
-#define RTIT_CTL_TOPA			BIT(8)
-#define RTIT_CTL_MTC_EN			BIT(9)
-#define RTIT_CTL_TSC_EN			BIT(10)
-#define RTIT_CTL_DISRETC		BIT(11)
-#define RTIT_CTL_BRANCH_EN		BIT(13)
-#define RTIT_CTL_MTC_RANGE_OFFSET	14
-#define RTIT_CTL_MTC_RANGE		(0x0full << RTIT_CTL_MTC_RANGE_OFFSET)
-#define RTIT_CTL_CYC_THRESH_OFFSET	19
-#define RTIT_CTL_CYC_THRESH		(0x0full << RTIT_CTL_CYC_THRESH_OFFSET)
-#define RTIT_CTL_PSB_FREQ_OFFSET	24
-#define RTIT_CTL_PSB_FREQ      		(0x0full << RTIT_CTL_PSB_FREQ_OFFSET)
 #define MSR_IA32_RTIT_STATUS		0x00000571
-#define RTIT_STATUS_CONTEXTEN		BIT(1)
-#define RTIT_STATUS_TRIGGEREN		BIT(2)
-#define RTIT_STATUS_ERROR		BIT(4)
-#define RTIT_STATUS_STOPPED		BIT(5)
+#define MSR_IA32_RTIT_STATUS		0x00000571
+#define MSR_IA32_RTIT_ADDR0_A		0x00000580
+#define MSR_IA32_RTIT_ADDR0_B		0x00000581
+#define MSR_IA32_RTIT_ADDR1_A		0x00000582
+#define MSR_IA32_RTIT_ADDR1_B		0x00000583
+#define MSR_IA32_RTIT_ADDR2_A		0x00000584
+#define MSR_IA32_RTIT_ADDR2_B		0x00000585
+#define MSR_IA32_RTIT_ADDR3_A		0x00000586
+#define MSR_IA32_RTIT_ADDR3_B		0x00000587
 #define MSR_IA32_RTIT_CR3_MATCH		0x00000572
 #define MSR_IA32_RTIT_OUTPUT_BASE	0x00000560
 #define MSR_IA32_RTIT_OUTPUT_MASK	0x00000561
@@ -205,6 +194,8 @@
 #define MSR_CONFIG_TDP_CONTROL		0x0000064B
 #define MSR_TURBO_ACTIVATION_RATIO	0x0000064C
 
+#define MSR_PLATFORM_ENERGY_STATUS	0x0000064D
+
 #define MSR_PKG_WEIGHTED_CORE_C0_RES	0x00000658
 #define MSR_PKG_ANY_CORE_C0_RES		0x00000659
 #define MSR_PKG_ANY_GFXE_C0_RES		0x0000065A
@@ -315,6 +306,9 @@
 #define MSR_AMD64_IBSOPDATA4		0xc001103d
 #define MSR_AMD64_IBS_REG_COUNT_MAX	8 /* includes MSR_AMD64_IBSBRTARGET */
 
+/* Fam 17h MSRs */
+#define MSR_F17H_IRPERF			0xc00000e9
+
 /* Fam 16h MSRs */
 #define MSR_F16H_L2I_PERF_CTL		0xc0010230
 #define MSR_F16H_L2I_PERF_CTR		0xc0010231
@@ -328,6 +322,7 @@
 #define MSR_F15H_PERF_CTR		0xc0010201
 #define MSR_F15H_NB_PERF_CTL		0xc0010240
 #define MSR_F15H_NB_PERF_CTR		0xc0010241
+#define MSR_F15H_PTSC			0xc0010280
 #define MSR_F15H_IC_CFG			0xc0011021
 
 /* Fam 10h MSRs */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/mtrr.h linux-libre-4.7-gnu/arch/x86/include/asm/mtrr.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/mtrr.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/mtrr.h	2016-07-24 15:23:50.000000000 -0400
@@ -24,6 +24,7 @@
 #define _ASM_X86_MTRR_H
 
 #include <uapi/asm/mtrr.h>
+#include <asm/pat.h>
 
 
 /*
@@ -83,9 +84,12 @@ static inline int mtrr_trim_uncached_mem
 static inline void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi)
 {
 }
+static inline void mtrr_bp_init(void)
+{
+	pat_disable("MTRRs disabled, skipping PAT initialization too.");
+}
 
 #define mtrr_ap_init() do {} while (0)
-#define mtrr_bp_init() do {} while (0)
 #define set_mtrr_aps_delayed_init() do {} while (0)
 #define mtrr_aps_init() do {} while (0)
 #define mtrr_bp_restore() do {} while (0)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/page_64_types.h linux-libre-4.7-gnu/arch/x86/include/asm/page_64_types.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/page_64_types.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/page_64_types.h	2016-07-24 15:23:50.000000000 -0400
@@ -47,12 +47,10 @@
  * are fully set up. If kernel ASLR is configured, it can extend the
  * kernel page table mapping, reducing the size of the modules area.
  */
-#define KERNEL_IMAGE_SIZE_DEFAULT      (512 * 1024 * 1024)
-#if defined(CONFIG_RANDOMIZE_BASE) && \
-	CONFIG_RANDOMIZE_BASE_MAX_OFFSET > KERNEL_IMAGE_SIZE_DEFAULT
-#define KERNEL_IMAGE_SIZE   CONFIG_RANDOMIZE_BASE_MAX_OFFSET
+#if defined(CONFIG_RANDOMIZE_BASE)
+#define KERNEL_IMAGE_SIZE	(1024 * 1024 * 1024)
 #else
-#define KERNEL_IMAGE_SIZE      KERNEL_IMAGE_SIZE_DEFAULT
+#define KERNEL_IMAGE_SIZE	(512 * 1024 * 1024)
 #endif
 
 #endif /* _ASM_X86_PAGE_64_DEFS_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/page.h linux-libre-4.7-gnu/arch/x86/include/asm/page.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/page.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/page.h	2016-07-24 15:23:50.000000000 -0400
@@ -37,7 +37,10 @@ static inline void copy_user_page(void *
 	alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
 #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
 
+#ifndef __pa
 #define __pa(x)		__phys_addr((unsigned long)(x))
+#endif
+
 #define __pa_nodebug(x)	__phys_addr_nodebug((unsigned long)(x))
 /* __pa_symbol should be used for C visible symbols.
    This seems to be the official gcc blessed way to do such arithmetic. */
@@ -51,7 +54,9 @@ static inline void copy_user_page(void *
 #define __pa_symbol(x) \
 	__phys_addr_symbol(__phys_reloc_hide((unsigned long)(x)))
 
+#ifndef __va
 #define __va(x)			((void *)((unsigned long)(x)+PAGE_OFFSET))
+#endif
 
 #define __boot_va(x)		__va(x)
 #define __boot_pa(x)		__pa(x)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/paravirt.h linux-libre-4.7-gnu/arch/x86/include/asm/paravirt.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/paravirt.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/paravirt.h	2016-07-24 15:23:50.000000000 -0400
@@ -15,17 +15,6 @@
 #include <linux/cpumask.h>
 #include <asm/frame.h>
 
-static inline int paravirt_enabled(void)
-{
-	return pv_info.paravirt_enabled;
-}
-
-static inline int paravirt_has_feature(unsigned int feature)
-{
-	WARN_ON_ONCE(!pv_info.paravirt_enabled);
-	return (pv_info.features & feature);
-}
-
 static inline void load_sp0(struct tss_struct *tss,
 			     struct thread_struct *thread)
 {
@@ -130,21 +119,31 @@ static inline void wbinvd(void)
 
 #define get_kernel_rpl()  (pv_info.kernel_rpl)
 
-static inline u64 paravirt_read_msr(unsigned msr, int *err)
+static inline u64 paravirt_read_msr(unsigned msr)
 {
-	return PVOP_CALL2(u64, pv_cpu_ops.read_msr, msr, err);
+	return PVOP_CALL1(u64, pv_cpu_ops.read_msr, msr);
 }
 
-static inline int paravirt_write_msr(unsigned msr, unsigned low, unsigned high)
+static inline void paravirt_write_msr(unsigned msr,
+				      unsigned low, unsigned high)
 {
-	return PVOP_CALL3(int, pv_cpu_ops.write_msr, msr, low, high);
+	return PVOP_VCALL3(pv_cpu_ops.write_msr, msr, low, high);
+}
+
+static inline u64 paravirt_read_msr_safe(unsigned msr, int *err)
+{
+	return PVOP_CALL2(u64, pv_cpu_ops.read_msr_safe, msr, err);
+}
+
+static inline int paravirt_write_msr_safe(unsigned msr,
+					  unsigned low, unsigned high)
+{
+	return PVOP_CALL3(int, pv_cpu_ops.write_msr_safe, msr, low, high);
 }
 
-/* These should all do BUG_ON(_err), but our headers are too tangled. */
 #define rdmsr(msr, val1, val2)			\
 do {						\
-	int _err;				\
-	u64 _l = paravirt_read_msr(msr, &_err);	\
+	u64 _l = paravirt_read_msr(msr);	\
 	val1 = (u32)_l;				\
 	val2 = _l >> 32;			\
 } while (0)
@@ -156,8 +155,7 @@ do {						\
 
 #define rdmsrl(msr, val)			\
 do {						\
-	int _err;				\
-	val = paravirt_read_msr(msr, &_err);	\
+	val = paravirt_read_msr(msr);		\
 } while (0)
 
 static inline void wrmsrl(unsigned msr, u64 val)
@@ -165,23 +163,23 @@ static inline void wrmsrl(unsigned msr,
 	wrmsr(msr, (u32)val, (u32)(val>>32));
 }
 
-#define wrmsr_safe(msr, a, b)	paravirt_write_msr(msr, a, b)
+#define wrmsr_safe(msr, a, b)	paravirt_write_msr_safe(msr, a, b)
 
 /* rdmsr with exception handling */
-#define rdmsr_safe(msr, a, b)			\
-({						\
-	int _err;				\
-	u64 _l = paravirt_read_msr(msr, &_err);	\
-	(*a) = (u32)_l;				\
-	(*b) = _l >> 32;			\
-	_err;					\
+#define rdmsr_safe(msr, a, b)				\
+({							\
+	int _err;					\
+	u64 _l = paravirt_read_msr_safe(msr, &_err);	\
+	(*a) = (u32)_l;					\
+	(*b) = _l >> 32;				\
+	_err;						\
 })
 
 static inline int rdmsrl_safe(unsigned msr, unsigned long long *p)
 {
 	int err;
 
-	*p = paravirt_read_msr(msr, &err);
+	*p = paravirt_read_msr_safe(msr, &err);
 	return err;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/paravirt_types.h linux-libre-4.7-gnu/arch/x86/include/asm/paravirt_types.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/paravirt_types.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/paravirt_types.h	2016-07-24 15:23:50.000000000 -0400
@@ -69,15 +69,9 @@ struct pv_info {
 	u16 extra_user_64bit_cs;  /* __USER_CS if none */
 #endif
 
-	int paravirt_enabled;
-	unsigned int features;	  /* valid only if paravirt_enabled is set */
 	const char *name;
 };
 
-#define paravirt_has(x) paravirt_has_feature(PV_SUPPORTED_##x)
-/* Supported features */
-#define PV_SUPPORTED_RTC        (1<<0)
-
 struct pv_init_ops {
 	/*
 	 * Patch may replace one of the defined code sequences with
@@ -155,10 +149,16 @@ struct pv_cpu_ops {
 	void (*cpuid)(unsigned int *eax, unsigned int *ebx,
 		      unsigned int *ecx, unsigned int *edx);
 
-	/* MSR, PMC and TSR operations.
-	   err = 0/-EFAULT.  wrmsr returns 0/-EFAULT. */
-	u64 (*read_msr)(unsigned int msr, int *err);
-	int (*write_msr)(unsigned int msr, unsigned low, unsigned high);
+	/* Unsafe MSR operations.  These will warn or panic on failure. */
+	u64 (*read_msr)(unsigned int msr);
+	void (*write_msr)(unsigned int msr, unsigned low, unsigned high);
+
+	/*
+	 * Safe MSR operations.
+	 * read sets err to 0 or -EIO.  write returns 0 or -EIO.
+	 */
+	u64 (*read_msr_safe)(unsigned int msr, int *err);
+	int (*write_msr_safe)(unsigned int msr, unsigned low, unsigned high);
 
 	u64 (*read_pmc)(int counter);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/pat.h linux-libre-4.7-gnu/arch/x86/include/asm/pat.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/pat.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/pat.h	2016-07-24 15:23:50.000000000 -0400
@@ -5,8 +5,8 @@
 #include <asm/pgtable_types.h>
 
 bool pat_enabled(void);
+void pat_disable(const char *reason);
 extern void pat_init(void);
-void pat_init_cache_modes(u64);
 
 extern int reserve_memtype(u64 start, u64 end,
 		enum page_cache_mode req_pcm, enum page_cache_mode *ret_pcm);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/pgalloc.h linux-libre-4.7-gnu/arch/x86/include/asm/pgalloc.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/pgalloc.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/pgalloc.h	2016-07-24 15:23:50.000000000 -0400
@@ -81,7 +81,7 @@ static inline void pmd_populate(struct m
 static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
 {
 	struct page *page;
-	page = alloc_pages(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO, 0);
+	page = alloc_pages(GFP_KERNEL |  __GFP_ZERO, 0);
 	if (!page)
 		return NULL;
 	if (!pgtable_pmd_page_ctor(page)) {
@@ -125,7 +125,7 @@ static inline void pgd_populate(struct m
 
 static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
 {
-	return (pud_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
+	return (pud_t *)get_zeroed_page(GFP_KERNEL);
 }
 
 static inline void pud_free(struct mm_struct *mm, pud_t *pud)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/pgtable.h linux-libre-4.7-gnu/arch/x86/include/asm/pgtable.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/pgtable.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/pgtable.h	2016-07-24 15:23:50.000000000 -0400
@@ -181,9 +181,10 @@ static inline int pmd_trans_huge(pmd_t p
 	return (pmd_val(pmd) & (_PAGE_PSE|_PAGE_DEVMAP)) == _PAGE_PSE;
 }
 
+#define has_transparent_hugepage has_transparent_hugepage
 static inline int has_transparent_hugepage(void)
 {
-	return cpu_has_pse;
+	return boot_cpu_has(X86_FEATURE_PSE);
 }
 
 #ifdef __HAVE_ARCH_PTE_DEVMAP
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/pmc_core.h linux-libre-4.7-gnu/arch/x86/include/asm/pmc_core.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/pmc_core.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/x86/include/asm/pmc_core.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,27 @@
+/*
+ * Intel Core SoC Power Management Controller Header File
+ *
+ * Copyright (c) 2016, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * Authors: Rajneesh Bhardwaj <rajneesh.bhardwaj@intel.com>
+ *          Vishwanath Somayaji <vishwanath.somayaji@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ */
+
+#ifndef _ASM_PMC_CORE_H
+#define _ASM_PMC_CORE_H
+
+/* API to read SLP_S0_RESIDENCY counter */
+int intel_pmc_slp_s0_counter_read(u32 *data);
+
+#endif /* _ASM_PMC_CORE_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/processor.h linux-libre-4.7-gnu/arch/x86/include/asm/processor.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/processor.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/processor.h	2016-07-24 15:23:50.000000000 -0400
@@ -388,9 +388,16 @@ struct thread_struct {
 	unsigned long		ip;
 #endif
 #ifdef CONFIG_X86_64
-	unsigned long		fs;
+	unsigned long		fsbase;
+	unsigned long		gsbase;
+#else
+	/*
+	 * XXX: this could presumably be unsigned short.  Alternatively,
+	 * 32-bit kernels could be taught to use fsindex instead.
+	 */
+	unsigned long fs;
+	unsigned long gs;
 #endif
-	unsigned long		gs;
 
 	/* Save middle states of ptrace breakpoints */
 	struct perf_event	*ptrace_bps[HBP_NUM];
@@ -473,8 +480,6 @@ static inline unsigned long current_top_
 #include <asm/paravirt.h>
 #else
 #define __cpuid			native_cpuid
-#define paravirt_enabled()	0
-#define paravirt_has(x) 	0
 
 static inline void load_sp0(struct tss_struct *tss,
 			    struct thread_struct *thread)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/pvclock.h linux-libre-4.7-gnu/arch/x86/include/asm/pvclock.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/pvclock.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/pvclock.h	2016-07-24 15:23:50.000000000 -0400
@@ -69,29 +69,22 @@ static inline u64 pvclock_scale_delta(u6
 }
 
 static __always_inline
-u64 pvclock_get_nsec_offset(const struct pvclock_vcpu_time_info *src)
-{
-	u64 delta = rdtsc_ordered() - src->tsc_timestamp;
-	return pvclock_scale_delta(delta, src->tsc_to_system_mul,
-				   src->tsc_shift);
-}
-
-static __always_inline
 unsigned __pvclock_read_cycles(const struct pvclock_vcpu_time_info *src,
 			       cycle_t *cycles, u8 *flags)
 {
 	unsigned version;
-	cycle_t ret, offset;
-	u8 ret_flags;
+	cycle_t offset;
+	u64 delta;
 
 	version = src->version;
+	/* Make the latest version visible */
+	smp_rmb();
 
-	offset = pvclock_get_nsec_offset(src);
-	ret = src->system_time + offset;
-	ret_flags = src->flags;
-
-	*cycles = ret;
-	*flags = ret_flags;
+	delta = rdtsc_ordered() - src->tsc_timestamp;
+	offset = pvclock_scale_delta(delta, src->tsc_to_system_mul,
+				   src->tsc_shift);
+	*cycles = src->system_time + offset;
+	*flags = src->flags;
 	return version;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/rwsem.h linux-libre-4.7-gnu/arch/x86/include/asm/rwsem.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/rwsem.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/rwsem.h	2016-07-24 15:23:50.000000000 -0400
@@ -99,26 +99,36 @@ static inline int __down_read_trylock(st
 /*
  * lock for writing
  */
-static inline void __down_write_nested(struct rw_semaphore *sem, int subclass)
+#define ____down_write(sem, slow_path)			\
+({							\
+	long tmp;					\
+	struct rw_semaphore* ret;			\
+	asm volatile("# beginning down_write\n\t"	\
+		     LOCK_PREFIX "  xadd      %1,(%3)\n\t"	\
+		     /* adds 0xffff0001, returns the old value */ \
+		     "  test " __ASM_SEL(%w1,%k1) "," __ASM_SEL(%w1,%k1) "\n\t" \
+		     /* was the active mask 0 before? */\
+		     "  jz        1f\n"			\
+		     "  call " slow_path "\n"		\
+		     "1:\n"				\
+		     "# ending down_write"		\
+		     : "+m" (sem->count), "=d" (tmp), "=a" (ret)	\
+		     : "a" (sem), "1" (RWSEM_ACTIVE_WRITE_BIAS) \
+		     : "memory", "cc");			\
+	ret;						\
+})
+
+static inline void __down_write(struct rw_semaphore *sem)
 {
-	long tmp;
-	asm volatile("# beginning down_write\n\t"
-		     LOCK_PREFIX "  xadd      %1,(%2)\n\t"
-		     /* adds 0xffff0001, returns the old value */
-		     "  test " __ASM_SEL(%w1,%k1) "," __ASM_SEL(%w1,%k1) "\n\t"
-		     /* was the active mask 0 before? */
-		     "  jz        1f\n"
-		     "  call call_rwsem_down_write_failed\n"
-		     "1:\n"
-		     "# ending down_write"
-		     : "+m" (sem->count), "=d" (tmp)
-		     : "a" (sem), "1" (RWSEM_ACTIVE_WRITE_BIAS)
-		     : "memory", "cc");
+	____down_write(sem, "call_rwsem_down_write_failed");
 }
 
-static inline void __down_write(struct rw_semaphore *sem)
+static inline int __down_write_killable(struct rw_semaphore *sem)
 {
-	__down_write_nested(sem, 0);
+	if (IS_ERR(____down_write(sem, "call_rwsem_down_write_failed_killable")))
+		return -EINTR;
+
+	return 0;
 }
 
 /*
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/segment.h linux-libre-4.7-gnu/arch/x86/include/asm/segment.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/segment.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/segment.h	2016-07-24 15:23:50.000000000 -0400
@@ -2,6 +2,7 @@
 #define _ASM_X86_SEGMENT_H
 
 #include <linux/const.h>
+#include <asm/alternative.h>
 
 /*
  * Constructor for a conventional segment GDT (or LDT) entry.
@@ -207,13 +208,6 @@
 #define __USER_CS			(GDT_ENTRY_DEFAULT_USER_CS*8 + 3)
 #define __PER_CPU_SEG			(GDT_ENTRY_PER_CPU*8 + 3)
 
-/* TLS indexes for 64-bit - hardcoded in arch_prctl(): */
-#define FS_TLS				0
-#define GS_TLS				1
-
-#define GS_TLS_SEL			((GDT_ENTRY_TLS_MIN+GS_TLS)*8 + 3)
-#define FS_TLS_SEL			((GDT_ENTRY_TLS_MIN+FS_TLS)*8 + 3)
-
 #endif
 
 #ifndef CONFIG_PARAVIRT
@@ -249,10 +243,13 @@ extern const char early_idt_handler_arra
 #endif
 
 /*
- * Load a segment. Fall back on loading the zero
- * segment if something goes wrong..
+ * Load a segment. Fall back on loading the zero segment if something goes
+ * wrong.  This variant assumes that loading zero fully clears the segment.
+ * This is always the case on Intel CPUs and, even on 64-bit AMD CPUs, any
+ * failure to fully clear the cached descriptor is only observable for
+ * FS and GS.
  */
-#define loadsegment(seg, value)						\
+#define __loadsegment_simple(seg, value)				\
 do {									\
 	unsigned short __val = (value);					\
 									\
@@ -269,6 +266,38 @@ do {									\
 		     : "+r" (__val) : : "memory");			\
 } while (0)
 
+#define __loadsegment_ss(value) __loadsegment_simple(ss, (value))
+#define __loadsegment_ds(value) __loadsegment_simple(ds, (value))
+#define __loadsegment_es(value) __loadsegment_simple(es, (value))
+
+#ifdef CONFIG_X86_32
+
+/*
+ * On 32-bit systems, the hidden parts of FS and GS are unobservable if
+ * the selector is NULL, so there's no funny business here.
+ */
+#define __loadsegment_fs(value) __loadsegment_simple(fs, (value))
+#define __loadsegment_gs(value) __loadsegment_simple(gs, (value))
+
+#else
+
+static inline void __loadsegment_fs(unsigned short value)
+{
+	asm volatile("						\n"
+		     "1:	movw %0, %%fs			\n"
+		     "2:					\n"
+
+		     _ASM_EXTABLE_HANDLE(1b, 2b, ex_handler_clear_fs)
+
+		     : : "rm" (value) : "memory");
+}
+
+/* __loadsegment_gs is intentionally undefined.  Use load_gs_index instead. */
+
+#endif
+
+#define loadsegment(seg, value) __loadsegment_ ## seg (value)
+
 /*
  * Save a segment register away:
  */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/setup.h linux-libre-4.7-gnu/arch/x86/include/asm/setup.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/setup.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/setup.h	2016-07-24 15:23:50.000000000 -0400
@@ -6,6 +6,7 @@
 #define COMMAND_LINE_SIZE 2048
 
 #include <linux/linkage.h>
+#include <asm/page_types.h>
 
 #ifdef __i386__
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/stacktrace.h linux-libre-4.7-gnu/arch/x86/include/asm/stacktrace.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/stacktrace.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/stacktrace.h	2016-07-24 15:23:50.000000000 -0400
@@ -14,7 +14,7 @@ extern int kstack_depth_to_print;
 struct thread_info;
 struct stacktrace_ops;
 
-typedef unsigned long (*walk_stack_t)(struct thread_info *tinfo,
+typedef unsigned long (*walk_stack_t)(struct task_struct *task,
 				      unsigned long *stack,
 				      unsigned long bp,
 				      const struct stacktrace_ops *ops,
@@ -23,13 +23,13 @@ typedef unsigned long (*walk_stack_t)(st
 				      int *graph);
 
 extern unsigned long
-print_context_stack(struct thread_info *tinfo,
+print_context_stack(struct task_struct *task,
 		    unsigned long *stack, unsigned long bp,
 		    const struct stacktrace_ops *ops, void *data,
 		    unsigned long *end, int *graph);
 
 extern unsigned long
-print_context_stack_bp(struct thread_info *tinfo,
+print_context_stack_bp(struct task_struct *task,
 		       unsigned long *stack, unsigned long bp,
 		       const struct stacktrace_ops *ops, void *data,
 		       unsigned long *end, int *graph);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/svm.h linux-libre-4.7-gnu/arch/x86/include/asm/svm.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/svm.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/svm.h	2016-07-24 15:23:50.000000000 -0400
@@ -78,7 +78,8 @@ struct __attribute__ ((__packed__)) vmcb
 	u32 exit_int_info;
 	u32 exit_int_info_err;
 	u64 nested_ctl;
-	u8 reserved_4[16];
+	u64 avic_vapic_bar;
+	u8 reserved_4[8];
 	u32 event_inj;
 	u32 event_inj_err;
 	u64 nested_cr3;
@@ -88,7 +89,11 @@ struct __attribute__ ((__packed__)) vmcb
 	u64 next_rip;
 	u8 insn_len;
 	u8 insn_bytes[15];
-	u8 reserved_6[800];
+	u64 avic_backing_page;	/* Offset 0xe0 */
+	u8 reserved_6[8];	/* Offset 0xe8 */
+	u64 avic_logical_id;	/* Offset 0xf0 */
+	u64 avic_physical_id;	/* Offset 0xf8 */
+	u8 reserved_7[768];
 };
 
 
@@ -111,6 +116,9 @@ struct __attribute__ ((__packed__)) vmcb
 #define V_INTR_MASKING_SHIFT 24
 #define V_INTR_MASKING_MASK (1 << V_INTR_MASKING_SHIFT)
 
+#define AVIC_ENABLE_SHIFT 31
+#define AVIC_ENABLE_MASK (1 << AVIC_ENABLE_SHIFT)
+
 #define SVM_INTERRUPT_SHADOW_MASK 1
 
 #define SVM_IOIO_STR_SHIFT 2
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/switch_to.h linux-libre-4.7-gnu/arch/x86/include/asm/switch_to.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/switch_to.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/switch_to.h	2016-07-24 15:23:50.000000000 -0400
@@ -39,8 +39,7 @@ do {									\
 	 */								\
 	unsigned long ebx, ecx, edx, esi, edi;				\
 									\
-	asm volatile("pushfl\n\t"		/* save    flags */	\
-		     "pushl %%ebp\n\t"		/* save    EBP   */	\
+	asm volatile("pushl %%ebp\n\t"		/* save    EBP   */	\
 		     "movl %%esp,%[prev_sp]\n\t"	/* save    ESP   */ \
 		     "movl %[next_sp],%%esp\n\t"	/* restore ESP   */ \
 		     "movl $1f,%[prev_ip]\n\t"	/* save    EIP   */	\
@@ -49,7 +48,6 @@ do {									\
 		     "jmp __switch_to\n"	/* regparm call  */	\
 		     "1:\t"						\
 		     "popl %%ebp\n\t"		/* restore EBP   */	\
-		     "popfl\n"			/* restore flags */	\
 									\
 		     /* output parameters */				\
 		     : [prev_sp] "=m" (prev->thread.sp),		\
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/text-patching.h linux-libre-4.7-gnu/arch/x86/include/asm/text-patching.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/text-patching.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/x86/include/asm/text-patching.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,40 @@
+#ifndef _ASM_X86_TEXT_PATCHING_H
+#define _ASM_X86_TEXT_PATCHING_H
+
+#include <linux/types.h>
+#include <linux/stddef.h>
+#include <asm/ptrace.h>
+
+struct paravirt_patch_site;
+#ifdef CONFIG_PARAVIRT
+void apply_paravirt(struct paravirt_patch_site *start,
+		    struct paravirt_patch_site *end);
+#else
+static inline void apply_paravirt(struct paravirt_patch_site *start,
+				  struct paravirt_patch_site *end)
+{}
+#define __parainstructions	NULL
+#define __parainstructions_end	NULL
+#endif
+
+extern void *text_poke_early(void *addr, const void *opcode, size_t len);
+
+/*
+ * Clear and restore the kernel write-protection flag on the local CPU.
+ * Allows the kernel to edit read-only pages.
+ * Side-effect: any interrupt handler running between save and restore will have
+ * the ability to write to read-only pages.
+ *
+ * Warning:
+ * Code patching in the UP case is safe if NMIs and MCE handlers are stopped and
+ * no thread can be preempted in the instructions being modified (no iret to an
+ * invalid instruction possible) or if the instructions are changed from a
+ * consistent state to another consistent state atomically.
+ * On the local CPU you need to be protected again NMI or MCE handlers seeing an
+ * inconsistent instruction while you patch.
+ */
+extern void *text_poke(void *addr, const void *opcode, size_t len);
+extern int poke_int3_handler(struct pt_regs *regs);
+extern void *text_poke_bp(void *addr, const void *opcode, size_t len, void *handler);
+
+#endif /* _ASM_X86_TEXT_PATCHING_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/thread_info.h linux-libre-4.7-gnu/arch/x86/include/asm/thread_info.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/thread_info.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/thread_info.h	2016-07-24 15:23:50.000000000 -0400
@@ -255,7 +255,7 @@ static inline bool test_and_clear_restor
 	return true;
 }
 
-static inline bool is_ia32_task(void)
+static inline bool in_ia32_syscall(void)
 {
 #ifdef CONFIG_X86_32
 	return true;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/tlbflush.h linux-libre-4.7-gnu/arch/x86/include/asm/tlbflush.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/tlbflush.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/tlbflush.h	2016-07-24 15:23:50.000000000 -0400
@@ -181,7 +181,7 @@ static inline void __native_flush_tlb_si
 
 static inline void __flush_tlb_all(void)
 {
-	if (cpu_has_pge)
+	if (static_cpu_has(X86_FEATURE_PGE))
 		__flush_tlb_global();
 	else
 		__flush_tlb();
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/tsc.h linux-libre-4.7-gnu/arch/x86/include/asm/tsc.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/tsc.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/tsc.h	2016-07-24 15:23:50.000000000 -0400
@@ -22,7 +22,7 @@ extern void disable_TSC(void);
 static inline cycles_t get_cycles(void)
 {
 #ifndef CONFIG_X86_TSC
-	if (!cpu_has_tsc)
+	if (!boot_cpu_has(X86_FEATURE_TSC))
 		return 0;
 #endif
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/uaccess_32.h linux-libre-4.7-gnu/arch/x86/include/asm/uaccess_32.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/uaccess_32.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/uaccess_32.h	2016-07-24 15:23:50.000000000 -0400
@@ -33,46 +33,10 @@ unsigned long __must_check __copy_from_u
  * the specified block with access_ok() before calling this function.
  * The caller should also make sure he pins the user space address
  * so that we don't result in page fault and sleep.
- *
- * Here we special-case 1, 2 and 4-byte copy_*_user invocations.  On a fault
- * we return the initial request size (1, 2 or 4), as copy_*_user should do.
- * If a store crosses a page boundary and gets a fault, the x86 will not write
- * anything, so this is accurate.
  */
-
 static __always_inline unsigned long __must_check
 __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n)
 {
-	if (__builtin_constant_p(n)) {
-		unsigned long ret;
-
-		switch (n) {
-		case 1:
-			__uaccess_begin();
-			__put_user_size(*(u8 *)from, (u8 __user *)to,
-					1, ret, 1);
-			__uaccess_end();
-			return ret;
-		case 2:
-			__uaccess_begin();
-			__put_user_size(*(u16 *)from, (u16 __user *)to,
-					2, ret, 2);
-			__uaccess_end();
-			return ret;
-		case 4:
-			__uaccess_begin();
-			__put_user_size(*(u32 *)from, (u32 __user *)to,
-					4, ret, 4);
-			__uaccess_end();
-			return ret;
-		case 8:
-			__uaccess_begin();
-			__put_user_size(*(u64 *)from, (u64 __user *)to,
-					8, ret, 8);
-			__uaccess_end();
-			return ret;
-		}
-	}
 	return __copy_to_user_ll(to, from, n);
 }
 
@@ -101,32 +65,6 @@ __copy_to_user(void __user *to, const vo
 static __always_inline unsigned long
 __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n)
 {
-	/* Avoid zeroing the tail if the copy fails..
-	 * If 'n' is constant and 1, 2, or 4, we do still zero on a failure,
-	 * but as the zeroing behaviour is only significant when n is not
-	 * constant, that shouldn't be a problem.
-	 */
-	if (__builtin_constant_p(n)) {
-		unsigned long ret;
-
-		switch (n) {
-		case 1:
-			__uaccess_begin();
-			__get_user_size(*(u8 *)to, from, 1, ret, 1);
-			__uaccess_end();
-			return ret;
-		case 2:
-			__uaccess_begin();
-			__get_user_size(*(u16 *)to, from, 2, ret, 2);
-			__uaccess_end();
-			return ret;
-		case 4:
-			__uaccess_begin();
-			__get_user_size(*(u32 *)to, from, 4, ret, 4);
-			__uaccess_end();
-			return ret;
-		}
-	}
 	return __copy_from_user_ll_nozero(to, from, n);
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/uaccess_64.h linux-libre-4.7-gnu/arch/x86/include/asm/uaccess_64.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/uaccess_64.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/uaccess_64.h	2016-07-24 15:23:50.000000000 -0400
@@ -7,6 +7,7 @@
 #include <linux/compiler.h>
 #include <linux/errno.h>
 #include <linux/lockdep.h>
+#include <linux/kasan-checks.h>
 #include <asm/alternative.h>
 #include <asm/cpufeatures.h>
 #include <asm/page.h>
@@ -109,6 +110,7 @@ static __always_inline __must_check
 int __copy_from_user(void *dst, const void __user *src, unsigned size)
 {
 	might_fault();
+	kasan_check_write(dst, size);
 	return __copy_from_user_nocheck(dst, src, size);
 }
 
@@ -175,6 +177,7 @@ static __always_inline __must_check
 int __copy_to_user(void __user *dst, const void *src, unsigned size)
 {
 	might_fault();
+	kasan_check_read(src, size);
 	return __copy_to_user_nocheck(dst, src, size);
 }
 
@@ -242,12 +245,14 @@ int __copy_in_user(void __user *dst, con
 static __must_check __always_inline int
 __copy_from_user_inatomic(void *dst, const void __user *src, unsigned size)
 {
+	kasan_check_write(dst, size);
 	return __copy_from_user_nocheck(dst, src, size);
 }
 
 static __must_check __always_inline int
 __copy_to_user_inatomic(void __user *dst, const void *src, unsigned size)
 {
+	kasan_check_read(src, size);
 	return __copy_to_user_nocheck(dst, src, size);
 }
 
@@ -258,6 +263,7 @@ static inline int
 __copy_from_user_nocache(void *dst, const void __user *src, unsigned size)
 {
 	might_fault();
+	kasan_check_write(dst, size);
 	return __copy_user_nocache(dst, src, size, 1);
 }
 
@@ -265,6 +271,7 @@ static inline int
 __copy_from_user_inatomic_nocache(void *dst, const void __user *src,
 				  unsigned size)
 {
+	kasan_check_write(dst, size);
 	return __copy_user_nocache(dst, src, size, 0);
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/uaccess.h linux-libre-4.7-gnu/arch/x86/include/asm/uaccess.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/uaccess.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/uaccess.h	2016-07-24 15:23:50.000000000 -0400
@@ -5,6 +5,7 @@
  */
 #include <linux/errno.h>
 #include <linux/compiler.h>
+#include <linux/kasan-checks.h>
 #include <linux/thread_info.h>
 #include <linux/string.h>
 #include <asm/asm.h>
@@ -118,7 +119,7 @@ struct exception_table_entry {
 
 extern int fixup_exception(struct pt_regs *regs, int trapnr);
 extern bool ex_has_fault_handler(unsigned long ip);
-extern int early_fixup_exception(unsigned long *ip);
+extern void early_fixup_exception(struct pt_regs *regs, int trapnr);
 
 /*
  * These are the main single-value transfer routines.  They automatically
@@ -721,6 +722,8 @@ copy_from_user(void *to, const void __us
 
 	might_fault();
 
+	kasan_check_write(to, n);
+
 	/*
 	 * While we would like to have the compiler do the checking for us
 	 * even in the non-constant size case, any false positives there are
@@ -754,6 +757,8 @@ copy_to_user(void __user *to, const void
 {
 	int sz = __compiletime_object_size(from);
 
+	kasan_check_read(from, n);
+
 	might_fault();
 
 	/* See the comment in copy_from_user() above. */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/uv/bios.h linux-libre-4.7-gnu/arch/x86/include/asm/uv/bios.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/uv/bios.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/uv/bios.h	2016-07-24 15:23:50.000000000 -0400
@@ -51,15 +51,66 @@ enum {
 	BIOS_STATUS_UNAVAIL		= -EBUSY
 };
 
+/* Address map parameters */
+struct uv_gam_parameters {
+	u64	mmr_base;
+	u64	gru_base;
+	u8	mmr_shift;	/* Convert PNode to MMR space offset */
+	u8	gru_shift;	/* Convert PNode to GRU space offset */
+	u8	gpa_shift;	/* Size of offset field in GRU phys addr */
+	u8	unused1;
+};
+
+/* UV_TABLE_GAM_RANGE_ENTRY values */
+#define UV_GAM_RANGE_TYPE_UNUSED	0 /* End of table */
+#define UV_GAM_RANGE_TYPE_RAM		1 /* Normal RAM */
+#define UV_GAM_RANGE_TYPE_NVRAM		2 /* Non-volatile memory */
+#define UV_GAM_RANGE_TYPE_NV_WINDOW	3 /* NVMDIMM block window */
+#define UV_GAM_RANGE_TYPE_NV_MAILBOX	4 /* NVMDIMM mailbox */
+#define UV_GAM_RANGE_TYPE_HOLE		5 /* Unused address range */
+#define UV_GAM_RANGE_TYPE_MAX		6
+
+/* The structure stores PA bits 56:26, for 64MB granularity */
+#define UV_GAM_RANGE_SHFT		26		/* 64MB */
+
+struct uv_gam_range_entry {
+	char	type;		/* Entry type: GAM_RANGE_TYPE_UNUSED, etc. */
+	char	unused1;
+	u16	nasid;		/* HNasid */
+	u16	sockid;		/* Socket ID, high bits of APIC ID */
+	u16	pnode;		/* Index to MMR and GRU spaces */
+	u32	pxm;		/* ACPI proximity domain number */
+	u32	limit;		/* PA bits 56:26 (UV_GAM_RANGE_SHFT) */
+};
+
+#define	UV_SYSTAB_SIG			"UVST"
+#define	UV_SYSTAB_VERSION_1		1	/* UV1/2/3 BIOS version */
+#define	UV_SYSTAB_VERSION_UV4		0x400	/* UV4 BIOS base version */
+#define	UV_SYSTAB_VERSION_UV4_1		0x401	/* + gpa_shift */
+#define	UV_SYSTAB_VERSION_UV4_2		0x402	/* + TYPE_NVRAM/WINDOW/MBOX */
+#define	UV_SYSTAB_VERSION_UV4_LATEST	UV_SYSTAB_VERSION_UV4_2
+
+#define	UV_SYSTAB_TYPE_UNUSED		0	/* End of table (offset == 0) */
+#define	UV_SYSTAB_TYPE_GAM_PARAMS	1	/* GAM PARAM conversions */
+#define	UV_SYSTAB_TYPE_GAM_RNG_TBL	2	/* GAM entry table */
+#define	UV_SYSTAB_TYPE_MAX		3
+
 /*
  * The UV system table describes specific firmware
  * capabilities available to the Linux kernel at runtime.
  */
 struct uv_systab {
-	char signature[4];	/* must be "UVST" */
+	char signature[4];	/* must be UV_SYSTAB_SIG */
 	u32 revision;		/* distinguish different firmware revs */
 	u64 function;		/* BIOS runtime callback function ptr */
+	u32 size;		/* systab size (starting with _VERSION_UV4) */
+	struct {
+		u32 type:8;	/* type of entry */
+		u32 offset:24;	/* byte offset from struct start to entry */
+	} entry[1];		/* additional entries follow */
 };
+extern struct uv_systab *uv_systab;
+/* (... end of definitions from UV BIOS ...) */
 
 enum {
 	BIOS_FREQ_BASE_PLATFORM = 0,
@@ -99,7 +150,11 @@ extern s64 uv_bios_change_memprotect(u64
 extern s64 uv_bios_reserved_page_pa(u64, u64 *, u64 *, u64 *);
 extern int uv_bios_set_legacy_vga_target(bool decode, int domain, int bus);
 
+#ifdef CONFIG_EFI
 extern void uv_bios_init(void);
+#else
+void uv_bios_init(void) { }
+#endif
 
 extern unsigned long sn_rtc_cycles_per_second;
 extern int uv_type;
@@ -107,7 +162,7 @@ extern long sn_partition_id;
 extern long sn_coherency_id;
 extern long sn_region_size;
 extern long system_serial_number;
-#define partition_coherence_id()	(sn_coherency_id)
+#define uv_partition_coherence_id()	(sn_coherency_id)
 
 extern struct kobject *sgi_uv_kobj;	/* /sys/firmware/sgi_uv */
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/uv/uv_bau.h linux-libre-4.7-gnu/arch/x86/include/asm/uv/uv_bau.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/uv/uv_bau.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/uv/uv_bau.h	2016-07-24 15:23:50.000000000 -0400
@@ -598,7 +598,7 @@ struct bau_control {
 	int			timeout_tries;
 	int			ipi_attempts;
 	int			conseccompletes;
-	short			nobau;
+	bool			nobau;
 	short			baudisabled;
 	short			cpu;
 	short			osnode;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/uv/uv_hub.h linux-libre-4.7-gnu/arch/x86/include/asm/uv/uv_hub.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/uv/uv_hub.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/uv/uv_hub.h	2016-07-24 15:23:50.000000000 -0400
@@ -16,9 +16,11 @@
 #include <linux/percpu.h>
 #include <linux/timer.h>
 #include <linux/io.h>
+#include <linux/topology.h>
 #include <asm/types.h>
 #include <asm/percpu.h>
 #include <asm/uv/uv_mmrs.h>
+#include <asm/uv/bios.h>
 #include <asm/irq_vectors.h>
 #include <asm/io_apic.h>
 
@@ -103,7 +105,6 @@
  *	      processor APICID register.
  */
 
-
 /*
  * Maximum number of bricks in all partitions and in all coherency domains.
  * This is the total number of bricks accessible in the numalink fabric. It
@@ -127,6 +128,7 @@
  */
 #define UV_MAX_NASID_VALUE	(UV_MAX_NUMALINK_BLADES * 2)
 
+/* System Controller Interface Reg info */
 struct uv_scir_s {
 	struct timer_list timer;
 	unsigned long	offset;
@@ -137,71 +139,173 @@ struct uv_scir_s {
 	unsigned char	enabled;
 };
 
+/* GAM (globally addressed memory) range table */
+struct uv_gam_range_s {
+	u32	limit;		/* PA bits 56:26 (GAM_RANGE_SHFT) */
+	u16	nasid;		/* node's global physical address */
+	s8	base;		/* entry index of node's base addr */
+	u8	reserved;
+};
+
 /*
  * The following defines attributes of the HUB chip. These attributes are
- * frequently referenced and are kept in the per-cpu data areas of each cpu.
- * They are kept together in a struct to minimize cache misses.
+ * frequently referenced and are kept in a common per hub struct.
+ * After setup, the struct is read only, so it should be readily
+ * available in the L3 cache on the cpu socket for the node.
  */
 struct uv_hub_info_s {
 	unsigned long		global_mmr_base;
+	unsigned long		global_mmr_shift;
 	unsigned long		gpa_mask;
-	unsigned int		gnode_extra;
+	unsigned short		*socket_to_node;
+	unsigned short		*socket_to_pnode;
+	unsigned short		*pnode_to_socket;
+	struct uv_gam_range_s	*gr_table;
+	unsigned short		min_socket;
+	unsigned short		min_pnode;
+	unsigned char		m_val;
+	unsigned char		n_val;
+	unsigned char		gr_table_len;
 	unsigned char		hub_revision;
 	unsigned char		apic_pnode_shift;
+	unsigned char		gpa_shift;
 	unsigned char		m_shift;
 	unsigned char		n_lshift;
+	unsigned int		gnode_extra;
 	unsigned long		gnode_upper;
 	unsigned long		lowmem_remap_top;
 	unsigned long		lowmem_remap_base;
+	unsigned long		global_gru_base;
+	unsigned long		global_gru_shift;
 	unsigned short		pnode;
 	unsigned short		pnode_mask;
 	unsigned short		coherency_domain_number;
 	unsigned short		numa_blade_id;
-	unsigned char		blade_processor_id;
-	unsigned char		m_val;
-	unsigned char		n_val;
+	unsigned short		nr_possible_cpus;
+	unsigned short		nr_online_cpus;
+	short			memory_nid;
+};
+
+/* CPU specific info with a pointer to the hub common info struct */
+struct uv_cpu_info_s {
+	void			*p_uv_hub_info;
+	unsigned char		blade_cpu_id;
 	struct uv_scir_s	scir;
 };
+DECLARE_PER_CPU(struct uv_cpu_info_s, __uv_cpu_info);
 
-DECLARE_PER_CPU(struct uv_hub_info_s, __uv_hub_info);
-#define uv_hub_info		this_cpu_ptr(&__uv_hub_info)
-#define uv_cpu_hub_info(cpu)	(&per_cpu(__uv_hub_info, cpu))
+#define uv_cpu_info		this_cpu_ptr(&__uv_cpu_info)
+#define uv_cpu_info_per(cpu)	(&per_cpu(__uv_cpu_info, cpu))
+
+#define	uv_scir_info		(&uv_cpu_info->scir)
+#define	uv_cpu_scir_info(cpu)	(&uv_cpu_info_per(cpu)->scir)
+
+/* Node specific hub common info struct */
+extern void **__uv_hub_info_list;
+static inline struct uv_hub_info_s *uv_hub_info_list(int node)
+{
+	return (struct uv_hub_info_s *)__uv_hub_info_list[node];
+}
+
+static inline struct uv_hub_info_s *_uv_hub_info(void)
+{
+	return (struct uv_hub_info_s *)uv_cpu_info->p_uv_hub_info;
+}
+#define	uv_hub_info	_uv_hub_info()
+
+static inline struct uv_hub_info_s *uv_cpu_hub_info(int cpu)
+{
+	return (struct uv_hub_info_s *)uv_cpu_info_per(cpu)->p_uv_hub_info;
+}
+
+#define	UV_HUB_INFO_VERSION	0x7150
+extern int uv_hub_info_version(void);
+static inline int uv_hub_info_check(int version)
+{
+	if (uv_hub_info_version() == version)
+		return 0;
+
+	pr_crit("UV: uv_hub_info version(%x) mismatch, expecting(%x)\n",
+		uv_hub_info_version(), version);
+
+	BUG();	/* Catastrophic - cannot continue on unknown UV system */
+}
+#define	_uv_hub_info_check()	uv_hub_info_check(UV_HUB_INFO_VERSION)
 
 /*
- * Hub revisions less than UV2_HUB_REVISION_BASE are UV1 hubs. All UV2
- * hubs have revision numbers greater than or equal to UV2_HUB_REVISION_BASE.
+ * HUB revision ranges for each UV HUB architecture.
  * This is a software convention - NOT the hardware revision numbers in
  * the hub chip.
  */
 #define UV1_HUB_REVISION_BASE		1
 #define UV2_HUB_REVISION_BASE		3
 #define UV3_HUB_REVISION_BASE		5
+#define UV4_HUB_REVISION_BASE		7
 
+#ifdef	UV1_HUB_IS_SUPPORTED
 static inline int is_uv1_hub(void)
 {
 	return uv_hub_info->hub_revision < UV2_HUB_REVISION_BASE;
 }
+#else
+static inline int is_uv1_hub(void)
+{
+	return 0;
+}
+#endif
 
+#ifdef	UV2_HUB_IS_SUPPORTED
 static inline int is_uv2_hub(void)
 {
 	return ((uv_hub_info->hub_revision >= UV2_HUB_REVISION_BASE) &&
 		(uv_hub_info->hub_revision < UV3_HUB_REVISION_BASE));
 }
+#else
+static inline int is_uv2_hub(void)
+{
+	return 0;
+}
+#endif
 
+#ifdef	UV3_HUB_IS_SUPPORTED
 static inline int is_uv3_hub(void)
 {
-	return uv_hub_info->hub_revision >= UV3_HUB_REVISION_BASE;
+	return ((uv_hub_info->hub_revision >= UV3_HUB_REVISION_BASE) &&
+		(uv_hub_info->hub_revision < UV4_HUB_REVISION_BASE));
 }
+#else
+static inline int is_uv3_hub(void)
+{
+	return 0;
+}
+#endif
 
-static inline int is_uv_hub(void)
+#ifdef	UV4_HUB_IS_SUPPORTED
+static inline int is_uv4_hub(void)
 {
-	return uv_hub_info->hub_revision;
+	return uv_hub_info->hub_revision >= UV4_HUB_REVISION_BASE;
+}
+#else
+static inline int is_uv4_hub(void)
+{
+	return 0;
 }
+#endif
 
-/* code common to uv2 and uv3 only */
 static inline int is_uvx_hub(void)
 {
-	return uv_hub_info->hub_revision >= UV2_HUB_REVISION_BASE;
+	if (uv_hub_info->hub_revision >= UV2_HUB_REVISION_BASE)
+		return uv_hub_info->hub_revision;
+
+	return 0;
+}
+
+static inline int is_uv_hub(void)
+{
+#ifdef	UV1_HUB_IS_SUPPORTED
+	return uv_hub_info->hub_revision;
+#endif
+	return is_uvx_hub();
 }
 
 union uvh_apicid {
@@ -243,24 +347,42 @@ union uvh_apicid {
 #define UV3_LOCAL_MMR_SIZE		(32UL * 1024 * 1024)
 #define UV3_GLOBAL_MMR32_SIZE		(32UL * 1024 * 1024)
 
-#define UV_LOCAL_MMR_BASE		(is_uv1_hub() ? UV1_LOCAL_MMR_BASE : \
-					(is_uv2_hub() ? UV2_LOCAL_MMR_BASE : \
-							UV3_LOCAL_MMR_BASE))
-#define UV_GLOBAL_MMR32_BASE		(is_uv1_hub() ? UV1_GLOBAL_MMR32_BASE :\
-					(is_uv2_hub() ? UV2_GLOBAL_MMR32_BASE :\
-							UV3_GLOBAL_MMR32_BASE))
-#define UV_LOCAL_MMR_SIZE		(is_uv1_hub() ? UV1_LOCAL_MMR_SIZE : \
-					(is_uv2_hub() ? UV2_LOCAL_MMR_SIZE : \
-							UV3_LOCAL_MMR_SIZE))
-#define UV_GLOBAL_MMR32_SIZE		(is_uv1_hub() ? UV1_GLOBAL_MMR32_SIZE :\
-					(is_uv2_hub() ? UV2_GLOBAL_MMR32_SIZE :\
-							UV3_GLOBAL_MMR32_SIZE))
+#define UV4_LOCAL_MMR_BASE		0xfa000000UL
+#define UV4_GLOBAL_MMR32_BASE		0xfc000000UL
+#define UV4_LOCAL_MMR_SIZE		(32UL * 1024 * 1024)
+#define UV4_GLOBAL_MMR32_SIZE		(16UL * 1024 * 1024)
+
+#define UV_LOCAL_MMR_BASE		(				\
+					is_uv1_hub() ? UV1_LOCAL_MMR_BASE : \
+					is_uv2_hub() ? UV2_LOCAL_MMR_BASE : \
+					is_uv3_hub() ? UV3_LOCAL_MMR_BASE : \
+					/*is_uv4_hub*/ UV4_LOCAL_MMR_BASE)
+
+#define UV_GLOBAL_MMR32_BASE		(				\
+					is_uv1_hub() ? UV1_GLOBAL_MMR32_BASE : \
+					is_uv2_hub() ? UV2_GLOBAL_MMR32_BASE : \
+					is_uv3_hub() ? UV3_GLOBAL_MMR32_BASE : \
+					/*is_uv4_hub*/ UV4_GLOBAL_MMR32_BASE)
+
+#define UV_LOCAL_MMR_SIZE		(				\
+					is_uv1_hub() ? UV1_LOCAL_MMR_SIZE : \
+					is_uv2_hub() ? UV2_LOCAL_MMR_SIZE : \
+					is_uv3_hub() ? UV3_LOCAL_MMR_SIZE : \
+					/*is_uv4_hub*/ UV4_LOCAL_MMR_SIZE)
+
+#define UV_GLOBAL_MMR32_SIZE		(				\
+					is_uv1_hub() ? UV1_GLOBAL_MMR32_SIZE : \
+					is_uv2_hub() ? UV2_GLOBAL_MMR32_SIZE : \
+					is_uv3_hub() ? UV3_GLOBAL_MMR32_SIZE : \
+					/*is_uv4_hub*/ UV4_GLOBAL_MMR32_SIZE)
+
 #define UV_GLOBAL_MMR64_BASE		(uv_hub_info->global_mmr_base)
 
 #define UV_GLOBAL_GRU_MMR_BASE		0x4000000
 
 #define UV_GLOBAL_MMR32_PNODE_SHIFT	15
-#define UV_GLOBAL_MMR64_PNODE_SHIFT	26
+#define _UV_GLOBAL_MMR64_PNODE_SHIFT	26
+#define UV_GLOBAL_MMR64_PNODE_SHIFT	(uv_hub_info->global_mmr_shift)
 
 #define UV_GLOBAL_MMR32_PNODE_BITS(p)	((p) << (UV_GLOBAL_MMR32_PNODE_SHIFT))
 
@@ -307,18 +429,74 @@ union uvh_apicid {
  *	      between socket virtual and socket physical addresses.
  */
 
+/* global bits offset - number of local address bits in gpa for this UV arch */
+static inline unsigned int uv_gpa_shift(void)
+{
+	return uv_hub_info->gpa_shift;
+}
+#define	_uv_gpa_shift
+
+/* Find node that has the address range that contains global address  */
+static inline struct uv_gam_range_s *uv_gam_range(unsigned long pa)
+{
+	struct uv_gam_range_s *gr = uv_hub_info->gr_table;
+	unsigned long pal = (pa & uv_hub_info->gpa_mask) >> UV_GAM_RANGE_SHFT;
+	int i, num = uv_hub_info->gr_table_len;
+
+	if (gr) {
+		for (i = 0; i < num; i++, gr++) {
+			if (pal < gr->limit)
+				return gr;
+		}
+	}
+	pr_crit("UV: GAM Range for 0x%lx not found at %p!\n", pa, gr);
+	BUG();
+}
+
+/* Return base address of node that contains global address  */
+static inline unsigned long uv_gam_range_base(unsigned long pa)
+{
+	struct uv_gam_range_s *gr = uv_gam_range(pa);
+	int base = gr->base;
+
+	if (base < 0)
+		return 0UL;
+
+	return uv_hub_info->gr_table[base].limit;
+}
+
+/* socket phys RAM --> UV global NASID (UV4+) */
+static inline unsigned long uv_soc_phys_ram_to_nasid(unsigned long paddr)
+{
+	return uv_gam_range(paddr)->nasid;
+}
+#define	_uv_soc_phys_ram_to_nasid
+
+/* socket virtual --> UV global NASID (UV4+) */
+static inline unsigned long uv_gpa_nasid(void *v)
+{
+	return uv_soc_phys_ram_to_nasid(__pa(v));
+}
+
 /* socket phys RAM --> UV global physical address */
 static inline unsigned long uv_soc_phys_ram_to_gpa(unsigned long paddr)
 {
+	unsigned int m_val = uv_hub_info->m_val;
+
 	if (paddr < uv_hub_info->lowmem_remap_top)
 		paddr |= uv_hub_info->lowmem_remap_base;
 	paddr |= uv_hub_info->gnode_upper;
-	paddr = ((paddr << uv_hub_info->m_shift) >> uv_hub_info->m_shift) |
-		((paddr >> uv_hub_info->m_val) << uv_hub_info->n_lshift);
+	if (m_val)
+		paddr = ((paddr << uv_hub_info->m_shift)
+						>> uv_hub_info->m_shift) |
+			((paddr >> uv_hub_info->m_val)
+						<< uv_hub_info->n_lshift);
+	else
+		paddr |= uv_soc_phys_ram_to_nasid(paddr)
+						<< uv_hub_info->gpa_shift;
 	return paddr;
 }
 
-
 /* socket virtual --> UV global physical address */
 static inline unsigned long uv_gpa(void *v)
 {
@@ -338,54 +516,89 @@ static inline unsigned long uv_gpa_to_so
 	unsigned long paddr;
 	unsigned long remap_base = uv_hub_info->lowmem_remap_base;
 	unsigned long remap_top =  uv_hub_info->lowmem_remap_top;
+	unsigned int m_val = uv_hub_info->m_val;
+
+	if (m_val)
+		gpa = ((gpa << uv_hub_info->m_shift) >> uv_hub_info->m_shift) |
+			((gpa >> uv_hub_info->n_lshift) << uv_hub_info->m_val);
 
-	gpa = ((gpa << uv_hub_info->m_shift) >> uv_hub_info->m_shift) |
-		((gpa >> uv_hub_info->n_lshift) << uv_hub_info->m_val);
 	paddr = gpa & uv_hub_info->gpa_mask;
 	if (paddr >= remap_base && paddr < remap_base + remap_top)
 		paddr -= remap_base;
 	return paddr;
 }
 
-
-/* gpa -> pnode */
+/* gpa -> gnode */
 static inline unsigned long uv_gpa_to_gnode(unsigned long gpa)
 {
-	return gpa >> uv_hub_info->n_lshift;
+	unsigned int n_lshift = uv_hub_info->n_lshift;
+
+	if (n_lshift)
+		return gpa >> n_lshift;
+
+	return uv_gam_range(gpa)->nasid >> 1;
 }
 
 /* gpa -> pnode */
 static inline int uv_gpa_to_pnode(unsigned long gpa)
 {
-	unsigned long n_mask = (1UL << uv_hub_info->n_val) - 1;
-
-	return uv_gpa_to_gnode(gpa) & n_mask;
+	return uv_gpa_to_gnode(gpa) & uv_hub_info->pnode_mask;
 }
 
-/* gpa -> node offset*/
+/* gpa -> node offset */
 static inline unsigned long uv_gpa_to_offset(unsigned long gpa)
 {
-	return (gpa << uv_hub_info->m_shift) >> uv_hub_info->m_shift;
+	unsigned int m_shift = uv_hub_info->m_shift;
+
+	if (m_shift)
+		return (gpa << m_shift) >> m_shift;
+
+	return (gpa & uv_hub_info->gpa_mask) - uv_gam_range_base(gpa);
+}
+
+/* Convert socket to node */
+static inline int _uv_socket_to_node(int socket, unsigned short *s2nid)
+{
+	return s2nid ? s2nid[socket - uv_hub_info->min_socket] : socket;
+}
+
+static inline int uv_socket_to_node(int socket)
+{
+	return _uv_socket_to_node(socket, uv_hub_info->socket_to_node);
 }
 
 /* pnode, offset --> socket virtual */
 static inline void *uv_pnode_offset_to_vaddr(int pnode, unsigned long offset)
 {
-	return __va(((unsigned long)pnode << uv_hub_info->m_val) | offset);
-}
+	unsigned int m_val = uv_hub_info->m_val;
+	unsigned long base;
+	unsigned short sockid, node, *p2s;
 
+	if (m_val)
+		return __va(((unsigned long)pnode << m_val) | offset);
 
-/*
- * Extract a PNODE from an APICID (full apicid, not processor subset)
- */
+	p2s = uv_hub_info->pnode_to_socket;
+	sockid = p2s ? p2s[pnode - uv_hub_info->min_pnode] : pnode;
+	node = uv_socket_to_node(sockid);
+
+	/* limit address of previous socket is our base, except node 0 is 0 */
+	if (!node)
+		return __va((unsigned long)offset);
+
+	base = (unsigned long)(uv_hub_info->gr_table[node - 1].limit);
+	return __va(base << UV_GAM_RANGE_SHFT | offset);
+}
+
+/* Extract/Convert a PNODE from an APICID (full apicid, not processor subset) */
 static inline int uv_apicid_to_pnode(int apicid)
 {
-	return (apicid >> uv_hub_info->apic_pnode_shift);
+	int pnode = apicid >> uv_hub_info->apic_pnode_shift;
+	unsigned short *s2pn = uv_hub_info->socket_to_pnode;
+
+	return s2pn ? s2pn[pnode - uv_hub_info->min_socket] : pnode;
 }
 
-/*
- * Convert an apicid to the socket number on the blade
- */
+/* Convert an apicid to the socket number on the blade */
 static inline int uv_apicid_to_socket(int apicid)
 {
 	if (is_uv1_hub())
@@ -434,16 +647,6 @@ static inline unsigned long uv_read_glob
 	return readq(uv_global_mmr64_address(pnode, offset));
 }
 
-/*
- * Global MMR space addresses when referenced by the GRU. (GRU does
- * NOT use socket addressing).
- */
-static inline unsigned long uv_global_gru_mmr_address(int pnode, unsigned long offset)
-{
-	return UV_GLOBAL_GRU_MMR_BASE | offset |
-		((unsigned long)pnode << uv_hub_info->m_val);
-}
-
 static inline void uv_write_global_mmr8(int pnode, unsigned long offset, unsigned char val)
 {
 	writeb(val, uv_global_mmr64_address(pnode, offset));
@@ -483,27 +686,23 @@ static inline void uv_write_local_mmr8(u
 	writeb(val, uv_local_mmr_address(offset));
 }
 
-/*
- * Structures and definitions for converting between cpu, node, pnode, and blade
- * numbers.
- */
-struct uv_blade_info {
-	unsigned short	nr_possible_cpus;
-	unsigned short	nr_online_cpus;
-	unsigned short	pnode;
-	short		memory_nid;
-	spinlock_t	nmi_lock;	/* obsolete, see uv_hub_nmi */
-	unsigned long	nmi_count;	/* obsolete, see uv_hub_nmi */
-};
-extern struct uv_blade_info *uv_blade_info;
-extern short *uv_node_to_blade;
-extern short *uv_cpu_to_blade;
-extern short uv_possible_blades;
-
 /* Blade-local cpu number of current cpu. Numbered 0 .. <# cpus on the blade> */
 static inline int uv_blade_processor_id(void)
 {
-	return uv_hub_info->blade_processor_id;
+	return uv_cpu_info->blade_cpu_id;
+}
+
+/* Blade-local cpu number of cpu N. Numbered 0 .. <# cpus on the blade> */
+static inline int uv_cpu_blade_processor_id(int cpu)
+{
+	return uv_cpu_info_per(cpu)->blade_cpu_id;
+}
+#define _uv_cpu_blade_processor_id 1	/* indicate function available */
+
+/* Blade number to Node number (UV1..UV4 is 1:1) */
+static inline int uv_blade_to_node(int blade)
+{
+	return blade;
 }
 
 /* Blade number of current cpu. Numnbered 0 .. <#blades -1> */
@@ -512,55 +711,60 @@ static inline int uv_numa_blade_id(void)
 	return uv_hub_info->numa_blade_id;
 }
 
-/* Convert a cpu number to the the UV blade number */
-static inline int uv_cpu_to_blade_id(int cpu)
+/*
+ * Convert linux node number to the UV blade number.
+ * .. Currently for UV1 thru UV4 the node and the blade are identical.
+ * .. If this changes then you MUST check references to this function!
+ */
+static inline int uv_node_to_blade_id(int nid)
 {
-	return uv_cpu_to_blade[cpu];
+	return nid;
 }
 
-/* Convert linux node number to the UV blade number */
-static inline int uv_node_to_blade_id(int nid)
+/* Convert a cpu number to the the UV blade number */
+static inline int uv_cpu_to_blade_id(int cpu)
 {
-	return uv_node_to_blade[nid];
+	return uv_node_to_blade_id(cpu_to_node(cpu));
 }
 
 /* Convert a blade id to the PNODE of the blade */
 static inline int uv_blade_to_pnode(int bid)
 {
-	return uv_blade_info[bid].pnode;
+	return uv_hub_info_list(uv_blade_to_node(bid))->pnode;
 }
 
 /* Nid of memory node on blade. -1 if no blade-local memory */
 static inline int uv_blade_to_memory_nid(int bid)
 {
-	return uv_blade_info[bid].memory_nid;
+	return uv_hub_info_list(uv_blade_to_node(bid))->memory_nid;
 }
 
 /* Determine the number of possible cpus on a blade */
 static inline int uv_blade_nr_possible_cpus(int bid)
 {
-	return uv_blade_info[bid].nr_possible_cpus;
+	return uv_hub_info_list(uv_blade_to_node(bid))->nr_possible_cpus;
 }
 
 /* Determine the number of online cpus on a blade */
 static inline int uv_blade_nr_online_cpus(int bid)
 {
-	return uv_blade_info[bid].nr_online_cpus;
+	return uv_hub_info_list(uv_blade_to_node(bid))->nr_online_cpus;
 }
 
 /* Convert a cpu id to the PNODE of the blade containing the cpu */
 static inline int uv_cpu_to_pnode(int cpu)
 {
-	return uv_blade_info[uv_cpu_to_blade_id(cpu)].pnode;
+	return uv_cpu_hub_info(cpu)->pnode;
 }
 
 /* Convert a linux node number to the PNODE of the blade */
 static inline int uv_node_to_pnode(int nid)
 {
-	return uv_blade_info[uv_node_to_blade_id(nid)].pnode;
+	return uv_hub_info_list(nid)->pnode;
 }
 
 /* Maximum possible number of blades */
+extern short uv_possible_blades;
 static inline int uv_num_possible_blades(void)
 {
 	return uv_possible_blades;
@@ -578,9 +782,7 @@ extern void uv_nmi_setup(void);
 /* Newer SMM NMI handler, not present in all systems */
 #define UVH_NMI_MMRX		UVH_EVENT_OCCURRED0
 #define UVH_NMI_MMRX_CLEAR	UVH_EVENT_OCCURRED0_ALIAS
-#define UVH_NMI_MMRX_SHIFT	(is_uv1_hub() ? \
-					UV1H_EVENT_OCCURRED0_EXTIO_INT0_SHFT :\
-					UVXH_EVENT_OCCURRED0_EXTIO_INT0_SHFT)
+#define UVH_NMI_MMRX_SHIFT	UVH_EVENT_OCCURRED0_EXTIO_INT0_SHFT
 #define	UVH_NMI_MMRX_TYPE	"EXTIO_INT0"
 
 /* Non-zero indicates newer SMM NMI handler present */
@@ -622,9 +824,9 @@ DECLARE_PER_CPU(struct uv_cpu_nmi_s, uv_
 /* Update SCIR state */
 static inline void uv_set_scir_bits(unsigned char value)
 {
-	if (uv_hub_info->scir.state != value) {
-		uv_hub_info->scir.state = value;
-		uv_write_local_mmr8(uv_hub_info->scir.offset, value);
+	if (uv_scir_info->state != value) {
+		uv_scir_info->state = value;
+		uv_write_local_mmr8(uv_scir_info->offset, value);
 	}
 }
 
@@ -635,10 +837,10 @@ static inline unsigned long uv_scir_offs
 
 static inline void uv_set_cpu_scir_bits(int cpu, unsigned char value)
 {
-	if (uv_cpu_hub_info(cpu)->scir.state != value) {
+	if (uv_cpu_scir_info(cpu)->state != value) {
 		uv_write_global_mmr8(uv_cpu_to_pnode(cpu),
-				uv_cpu_hub_info(cpu)->scir.offset, value);
-		uv_cpu_hub_info(cpu)->scir.state = value;
+				uv_cpu_scir_info(cpu)->offset, value);
+		uv_cpu_scir_info(cpu)->state = value;
 	}
 }
 
@@ -666,10 +868,7 @@ static inline void uv_hub_send_ipi(int p
 
 /*
  * Get the minimum revision number of the hub chips within the partition.
- *     1 - UV1 rev 1.0 initial silicon
- *     2 - UV1 rev 2.0 production silicon
- *     3 - UV2 rev 1.0 initial silicon
- *     5 - UV3 rev 1.0 initial silicon
+ * (See UVx_HUB_REVISION_BASE above for specific values.)
  */
 static inline int uv_get_min_hub_revision_id(void)
 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/uv/uv_mmrs.h linux-libre-4.7-gnu/arch/x86/include/asm/uv/uv_mmrs.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/uv/uv_mmrs.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/uv/uv_mmrs.h	2016-07-24 15:23:50.000000000 -0400
@@ -5,7 +5,7 @@
  *
  * SGI UV MMR definitions
  *
- * Copyright (C) 2007-2014 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2007-2016 Silicon Graphics, Inc. All rights reserved.
  */
 
 #ifndef _ASM_X86_UV_UV_MMRS_H
@@ -18,10 +18,11 @@
  * grouped by architecture types.
  *
  * UVH  - definitions common to all UV hub types.
- * UVXH - definitions common to all UV eXtended hub types (currently 2 & 3).
+ * UVXH - definitions common to all UV eXtended hub types (currently 2, 3, 4).
  * UV1H - definitions specific to UV type 1 hub.
  * UV2H - definitions specific to UV type 2 hub.
  * UV3H - definitions specific to UV type 3 hub.
+ * UV4H - definitions specific to UV type 4 hub.
  *
  * So in general, MMR addresses and structures are identical on all hubs types.
  * These MMRs are identified as:
@@ -32,19 +33,25 @@
  *		} s;
  *	};
  *
- * If the MMR exists on all hub types but have different addresses:
+ * If the MMR exists on all hub types but have different addresses,
+ * use a conditional operator to define the value at runtime.
  *	#define UV1Hxxx	a
  *	#define UV2Hxxx	b
  *	#define UV3Hxxx	c
+ *	#define UV4Hxxx	d
  *	#define UVHxxx	(is_uv1_hub() ? UV1Hxxx :
  *			(is_uv2_hub() ? UV2Hxxx :
- *					UV3Hxxx))
+ *			(is_uv3_hub() ? UV3Hxxx :
+ *					UV4Hxxx))
  *
- * If the MMR exists on all hub types > 1 but have different addresses:
+ * If the MMR exists on all hub types > 1 but have different addresses, the
+ * variation using "UVX" as the prefix exists.
  *	#define UV2Hxxx	b
  *	#define UV3Hxxx	c
- *	#define UVXHxxx (is_uv2_hub() ? UV2Hxxx :
- *					UV3Hxxx))
+ *	#define UV4Hxxx	d
+ *	#define UVHxxx	(is_uv2_hub() ? UV2Hxxx :
+ *			(is_uv3_hub() ? UV3Hxxx :
+ *					UV4Hxxx))
  *
  *	union uvh_xxx {
  *		unsigned long       v;
@@ -56,6 +63,8 @@
  *		} s2;
  *		struct uv3h_xxx_s {	 # Full UV3 definition (*)
  *		} s3;
+ *		struct uv4h_xxx_s {	 # Full UV4 definition (*)
+ *		} s4;
  *	};
  *		(* - if present and different than the common struct)
  *
@@ -73,7 +82,7 @@
  *		} sn;
  *	};
  *
- * (GEN Flags: mflags_opt= undefs=0 UV23=UVXH)
+ * (GEN Flags: mflags_opt= undefs=function UV234=UVXH)
  */
 
 #define UV_MMR_ENABLE		(1UL << 63)
@@ -83,20 +92,36 @@
 #define UV2_HUB_PART_NUMBER_X	0x1111
 #define UV3_HUB_PART_NUMBER	0x9578
 #define UV3_HUB_PART_NUMBER_X	0x4321
+#define UV4_HUB_PART_NUMBER	0x99a1
 
 /* Compat: Indicate which UV Hubs are supported. */
+#define UV1_HUB_IS_SUPPORTED	1
 #define UV2_HUB_IS_SUPPORTED	1
 #define UV3_HUB_IS_SUPPORTED	1
+#define UV4_HUB_IS_SUPPORTED	1
+
+/* Error function to catch undefined references */
+extern unsigned long uv_undefined(char *str);
 
 /* ========================================================================= */
 /*                          UVH_BAU_DATA_BROADCAST                           */
 /* ========================================================================= */
 #define UVH_BAU_DATA_BROADCAST 0x61688UL
-#define UVH_BAU_DATA_BROADCAST_32 0x440
+
+#define UV1H_BAU_DATA_BROADCAST_32 0x440
+#define UV2H_BAU_DATA_BROADCAST_32 0x440
+#define UV3H_BAU_DATA_BROADCAST_32 0x440
+#define UV4H_BAU_DATA_BROADCAST_32 0x360
+#define UVH_BAU_DATA_BROADCAST_32 (					\
+	is_uv1_hub() ? UV1H_BAU_DATA_BROADCAST_32 :			\
+	is_uv2_hub() ? UV2H_BAU_DATA_BROADCAST_32 :			\
+	is_uv3_hub() ? UV3H_BAU_DATA_BROADCAST_32 :			\
+	/*is_uv4_hub*/ UV4H_BAU_DATA_BROADCAST_32)
 
 #define UVH_BAU_DATA_BROADCAST_ENABLE_SHFT		0
 #define UVH_BAU_DATA_BROADCAST_ENABLE_MASK		0x0000000000000001UL
 
+
 union uvh_bau_data_broadcast_u {
 	unsigned long	v;
 	struct uvh_bau_data_broadcast_s {
@@ -109,7 +134,16 @@ union uvh_bau_data_broadcast_u {
 /*                           UVH_BAU_DATA_CONFIG                             */
 /* ========================================================================= */
 #define UVH_BAU_DATA_CONFIG 0x61680UL
-#define UVH_BAU_DATA_CONFIG_32 0x438
+
+#define UV1H_BAU_DATA_CONFIG_32 0x438
+#define UV2H_BAU_DATA_CONFIG_32 0x438
+#define UV3H_BAU_DATA_CONFIG_32 0x438
+#define UV4H_BAU_DATA_CONFIG_32 0x358
+#define UVH_BAU_DATA_CONFIG_32 (					\
+	is_uv1_hub() ? UV1H_BAU_DATA_CONFIG_32 :			\
+	is_uv2_hub() ? UV2H_BAU_DATA_CONFIG_32 :			\
+	is_uv3_hub() ? UV3H_BAU_DATA_CONFIG_32 :			\
+	/*is_uv4_hub*/ UV4H_BAU_DATA_CONFIG_32)
 
 #define UVH_BAU_DATA_CONFIG_VECTOR_SHFT			0
 #define UVH_BAU_DATA_CONFIG_DM_SHFT			8
@@ -128,6 +162,7 @@ union uvh_bau_data_broadcast_u {
 #define UVH_BAU_DATA_CONFIG_M_MASK			0x0000000000010000UL
 #define UVH_BAU_DATA_CONFIG_APIC_ID_MASK		0xffffffff00000000UL
 
+
 union uvh_bau_data_config_u {
 	unsigned long	v;
 	struct uvh_bau_data_config_s {
@@ -266,7 +301,6 @@ union uvh_bau_data_config_u {
 #define UV1H_EVENT_OCCURRED0_BAU_DATA_MASK		0x0080000000000000UL
 #define UV1H_EVENT_OCCURRED0_POWER_MANAGEMENT_REQ_MASK	0x0100000000000000UL
 
-#define UVXH_EVENT_OCCURRED0_QP_HCERR_SHFT		1
 #define UVXH_EVENT_OCCURRED0_RH_HCERR_SHFT		2
 #define UVXH_EVENT_OCCURRED0_LH0_HCERR_SHFT		3
 #define UVXH_EVENT_OCCURRED0_LH1_HCERR_SHFT		4
@@ -275,55 +309,11 @@ union uvh_bau_data_config_u {
 #define UVXH_EVENT_OCCURRED0_NI0_HCERR_SHFT		7
 #define UVXH_EVENT_OCCURRED0_NI1_HCERR_SHFT		8
 #define UVXH_EVENT_OCCURRED0_LB_AOERR0_SHFT		9
-#define UVXH_EVENT_OCCURRED0_QP_AOERR0_SHFT		10
 #define UVXH_EVENT_OCCURRED0_LH0_AOERR0_SHFT		12
 #define UVXH_EVENT_OCCURRED0_LH1_AOERR0_SHFT		13
 #define UVXH_EVENT_OCCURRED0_GR0_AOERR0_SHFT		14
 #define UVXH_EVENT_OCCURRED0_GR1_AOERR0_SHFT		15
 #define UVXH_EVENT_OCCURRED0_XB_AOERR0_SHFT		16
-#define UVXH_EVENT_OCCURRED0_RT_AOERR0_SHFT		17
-#define UVXH_EVENT_OCCURRED0_NI0_AOERR0_SHFT		18
-#define UVXH_EVENT_OCCURRED0_NI1_AOERR0_SHFT		19
-#define UVXH_EVENT_OCCURRED0_LB_AOERR1_SHFT		20
-#define UVXH_EVENT_OCCURRED0_QP_AOERR1_SHFT		21
-#define UVXH_EVENT_OCCURRED0_RH_AOERR1_SHFT		22
-#define UVXH_EVENT_OCCURRED0_LH0_AOERR1_SHFT		23
-#define UVXH_EVENT_OCCURRED0_LH1_AOERR1_SHFT		24
-#define UVXH_EVENT_OCCURRED0_GR0_AOERR1_SHFT		25
-#define UVXH_EVENT_OCCURRED0_GR1_AOERR1_SHFT		26
-#define UVXH_EVENT_OCCURRED0_XB_AOERR1_SHFT		27
-#define UVXH_EVENT_OCCURRED0_RT_AOERR1_SHFT		28
-#define UVXH_EVENT_OCCURRED0_NI0_AOERR1_SHFT		29
-#define UVXH_EVENT_OCCURRED0_NI1_AOERR1_SHFT		30
-#define UVXH_EVENT_OCCURRED0_SYSTEM_SHUTDOWN_INT_SHFT	31
-#define UVXH_EVENT_OCCURRED0_LB_IRQ_INT_0_SHFT		32
-#define UVXH_EVENT_OCCURRED0_LB_IRQ_INT_1_SHFT		33
-#define UVXH_EVENT_OCCURRED0_LB_IRQ_INT_2_SHFT		34
-#define UVXH_EVENT_OCCURRED0_LB_IRQ_INT_3_SHFT		35
-#define UVXH_EVENT_OCCURRED0_LB_IRQ_INT_4_SHFT		36
-#define UVXH_EVENT_OCCURRED0_LB_IRQ_INT_5_SHFT		37
-#define UVXH_EVENT_OCCURRED0_LB_IRQ_INT_6_SHFT		38
-#define UVXH_EVENT_OCCURRED0_LB_IRQ_INT_7_SHFT		39
-#define UVXH_EVENT_OCCURRED0_LB_IRQ_INT_8_SHFT		40
-#define UVXH_EVENT_OCCURRED0_LB_IRQ_INT_9_SHFT		41
-#define UVXH_EVENT_OCCURRED0_LB_IRQ_INT_10_SHFT		42
-#define UVXH_EVENT_OCCURRED0_LB_IRQ_INT_11_SHFT		43
-#define UVXH_EVENT_OCCURRED0_LB_IRQ_INT_12_SHFT		44
-#define UVXH_EVENT_OCCURRED0_LB_IRQ_INT_13_SHFT		45
-#define UVXH_EVENT_OCCURRED0_LB_IRQ_INT_14_SHFT		46
-#define UVXH_EVENT_OCCURRED0_LB_IRQ_INT_15_SHFT		47
-#define UVXH_EVENT_OCCURRED0_L1_NMI_INT_SHFT		48
-#define UVXH_EVENT_OCCURRED0_STOP_CLOCK_SHFT		49
-#define UVXH_EVENT_OCCURRED0_ASIC_TO_L1_SHFT		50
-#define UVXH_EVENT_OCCURRED0_L1_TO_ASIC_SHFT		51
-#define UVXH_EVENT_OCCURRED0_LA_SEQ_TRIGGER_SHFT	52
-#define UVXH_EVENT_OCCURRED0_IPI_INT_SHFT		53
-#define UVXH_EVENT_OCCURRED0_EXTIO_INT0_SHFT		54
-#define UVXH_EVENT_OCCURRED0_EXTIO_INT1_SHFT		55
-#define UVXH_EVENT_OCCURRED0_EXTIO_INT2_SHFT		56
-#define UVXH_EVENT_OCCURRED0_EXTIO_INT3_SHFT		57
-#define UVXH_EVENT_OCCURRED0_PROFILE_INT_SHFT		58
-#define UVXH_EVENT_OCCURRED0_QP_HCERR_MASK		0x0000000000000002UL
 #define UVXH_EVENT_OCCURRED0_RH_HCERR_MASK		0x0000000000000004UL
 #define UVXH_EVENT_OCCURRED0_LH0_HCERR_MASK		0x0000000000000008UL
 #define UVXH_EVENT_OCCURRED0_LH1_HCERR_MASK		0x0000000000000010UL
@@ -332,54 +322,294 @@ union uvh_bau_data_config_u {
 #define UVXH_EVENT_OCCURRED0_NI0_HCERR_MASK		0x0000000000000080UL
 #define UVXH_EVENT_OCCURRED0_NI1_HCERR_MASK		0x0000000000000100UL
 #define UVXH_EVENT_OCCURRED0_LB_AOERR0_MASK		0x0000000000000200UL
-#define UVXH_EVENT_OCCURRED0_QP_AOERR0_MASK		0x0000000000000400UL
 #define UVXH_EVENT_OCCURRED0_LH0_AOERR0_MASK		0x0000000000001000UL
 #define UVXH_EVENT_OCCURRED0_LH1_AOERR0_MASK		0x0000000000002000UL
 #define UVXH_EVENT_OCCURRED0_GR0_AOERR0_MASK		0x0000000000004000UL
 #define UVXH_EVENT_OCCURRED0_GR1_AOERR0_MASK		0x0000000000008000UL
 #define UVXH_EVENT_OCCURRED0_XB_AOERR0_MASK		0x0000000000010000UL
-#define UVXH_EVENT_OCCURRED0_RT_AOERR0_MASK		0x0000000000020000UL
-#define UVXH_EVENT_OCCURRED0_NI0_AOERR0_MASK		0x0000000000040000UL
-#define UVXH_EVENT_OCCURRED0_NI1_AOERR0_MASK		0x0000000000080000UL
-#define UVXH_EVENT_OCCURRED0_LB_AOERR1_MASK		0x0000000000100000UL
-#define UVXH_EVENT_OCCURRED0_QP_AOERR1_MASK		0x0000000000200000UL
-#define UVXH_EVENT_OCCURRED0_RH_AOERR1_MASK		0x0000000000400000UL
-#define UVXH_EVENT_OCCURRED0_LH0_AOERR1_MASK		0x0000000000800000UL
-#define UVXH_EVENT_OCCURRED0_LH1_AOERR1_MASK		0x0000000001000000UL
-#define UVXH_EVENT_OCCURRED0_GR0_AOERR1_MASK		0x0000000002000000UL
-#define UVXH_EVENT_OCCURRED0_GR1_AOERR1_MASK		0x0000000004000000UL
-#define UVXH_EVENT_OCCURRED0_XB_AOERR1_MASK		0x0000000008000000UL
-#define UVXH_EVENT_OCCURRED0_RT_AOERR1_MASK		0x0000000010000000UL
-#define UVXH_EVENT_OCCURRED0_NI0_AOERR1_MASK		0x0000000020000000UL
-#define UVXH_EVENT_OCCURRED0_NI1_AOERR1_MASK		0x0000000040000000UL
-#define UVXH_EVENT_OCCURRED0_SYSTEM_SHUTDOWN_INT_MASK	0x0000000080000000UL
-#define UVXH_EVENT_OCCURRED0_LB_IRQ_INT_0_MASK		0x0000000100000000UL
-#define UVXH_EVENT_OCCURRED0_LB_IRQ_INT_1_MASK		0x0000000200000000UL
-#define UVXH_EVENT_OCCURRED0_LB_IRQ_INT_2_MASK		0x0000000400000000UL
-#define UVXH_EVENT_OCCURRED0_LB_IRQ_INT_3_MASK		0x0000000800000000UL
-#define UVXH_EVENT_OCCURRED0_LB_IRQ_INT_4_MASK		0x0000001000000000UL
-#define UVXH_EVENT_OCCURRED0_LB_IRQ_INT_5_MASK		0x0000002000000000UL
-#define UVXH_EVENT_OCCURRED0_LB_IRQ_INT_6_MASK		0x0000004000000000UL
-#define UVXH_EVENT_OCCURRED0_LB_IRQ_INT_7_MASK		0x0000008000000000UL
-#define UVXH_EVENT_OCCURRED0_LB_IRQ_INT_8_MASK		0x0000010000000000UL
-#define UVXH_EVENT_OCCURRED0_LB_IRQ_INT_9_MASK		0x0000020000000000UL
-#define UVXH_EVENT_OCCURRED0_LB_IRQ_INT_10_MASK		0x0000040000000000UL
-#define UVXH_EVENT_OCCURRED0_LB_IRQ_INT_11_MASK		0x0000080000000000UL
-#define UVXH_EVENT_OCCURRED0_LB_IRQ_INT_12_MASK		0x0000100000000000UL
-#define UVXH_EVENT_OCCURRED0_LB_IRQ_INT_13_MASK		0x0000200000000000UL
-#define UVXH_EVENT_OCCURRED0_LB_IRQ_INT_14_MASK		0x0000400000000000UL
-#define UVXH_EVENT_OCCURRED0_LB_IRQ_INT_15_MASK		0x0000800000000000UL
-#define UVXH_EVENT_OCCURRED0_L1_NMI_INT_MASK		0x0001000000000000UL
-#define UVXH_EVENT_OCCURRED0_STOP_CLOCK_MASK		0x0002000000000000UL
-#define UVXH_EVENT_OCCURRED0_ASIC_TO_L1_MASK		0x0004000000000000UL
-#define UVXH_EVENT_OCCURRED0_L1_TO_ASIC_MASK		0x0008000000000000UL
-#define UVXH_EVENT_OCCURRED0_LA_SEQ_TRIGGER_MASK	0x0010000000000000UL
-#define UVXH_EVENT_OCCURRED0_IPI_INT_MASK		0x0020000000000000UL
-#define UVXH_EVENT_OCCURRED0_EXTIO_INT0_MASK		0x0040000000000000UL
-#define UVXH_EVENT_OCCURRED0_EXTIO_INT1_MASK		0x0080000000000000UL
-#define UVXH_EVENT_OCCURRED0_EXTIO_INT2_MASK		0x0100000000000000UL
-#define UVXH_EVENT_OCCURRED0_EXTIO_INT3_MASK		0x0200000000000000UL
-#define UVXH_EVENT_OCCURRED0_PROFILE_INT_MASK		0x0400000000000000UL
+
+#define UV2H_EVENT_OCCURRED0_QP_HCERR_SHFT		1
+#define UV2H_EVENT_OCCURRED0_QP_AOERR0_SHFT		10
+#define UV2H_EVENT_OCCURRED0_RT_AOERR0_SHFT		17
+#define UV2H_EVENT_OCCURRED0_NI0_AOERR0_SHFT		18
+#define UV2H_EVENT_OCCURRED0_NI1_AOERR0_SHFT		19
+#define UV2H_EVENT_OCCURRED0_LB_AOERR1_SHFT		20
+#define UV2H_EVENT_OCCURRED0_QP_AOERR1_SHFT		21
+#define UV2H_EVENT_OCCURRED0_RH_AOERR1_SHFT		22
+#define UV2H_EVENT_OCCURRED0_LH0_AOERR1_SHFT		23
+#define UV2H_EVENT_OCCURRED0_LH1_AOERR1_SHFT		24
+#define UV2H_EVENT_OCCURRED0_GR0_AOERR1_SHFT		25
+#define UV2H_EVENT_OCCURRED0_GR1_AOERR1_SHFT		26
+#define UV2H_EVENT_OCCURRED0_XB_AOERR1_SHFT		27
+#define UV2H_EVENT_OCCURRED0_RT_AOERR1_SHFT		28
+#define UV2H_EVENT_OCCURRED0_NI0_AOERR1_SHFT		29
+#define UV2H_EVENT_OCCURRED0_NI1_AOERR1_SHFT		30
+#define UV2H_EVENT_OCCURRED0_SYSTEM_SHUTDOWN_INT_SHFT	31
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_0_SHFT		32
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_1_SHFT		33
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_2_SHFT		34
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_3_SHFT		35
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_4_SHFT		36
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_5_SHFT		37
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_6_SHFT		38
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_7_SHFT		39
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_8_SHFT		40
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_9_SHFT		41
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_10_SHFT		42
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_11_SHFT		43
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_12_SHFT		44
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_13_SHFT		45
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_14_SHFT		46
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_15_SHFT		47
+#define UV2H_EVENT_OCCURRED0_L1_NMI_INT_SHFT		48
+#define UV2H_EVENT_OCCURRED0_STOP_CLOCK_SHFT		49
+#define UV2H_EVENT_OCCURRED0_ASIC_TO_L1_SHFT		50
+#define UV2H_EVENT_OCCURRED0_L1_TO_ASIC_SHFT		51
+#define UV2H_EVENT_OCCURRED0_LA_SEQ_TRIGGER_SHFT	52
+#define UV2H_EVENT_OCCURRED0_IPI_INT_SHFT		53
+#define UV2H_EVENT_OCCURRED0_EXTIO_INT0_SHFT		54
+#define UV2H_EVENT_OCCURRED0_EXTIO_INT1_SHFT		55
+#define UV2H_EVENT_OCCURRED0_EXTIO_INT2_SHFT		56
+#define UV2H_EVENT_OCCURRED0_EXTIO_INT3_SHFT		57
+#define UV2H_EVENT_OCCURRED0_PROFILE_INT_SHFT		58
+#define UV2H_EVENT_OCCURRED0_QP_HCERR_MASK		0x0000000000000002UL
+#define UV2H_EVENT_OCCURRED0_QP_AOERR0_MASK		0x0000000000000400UL
+#define UV2H_EVENT_OCCURRED0_RT_AOERR0_MASK		0x0000000000020000UL
+#define UV2H_EVENT_OCCURRED0_NI0_AOERR0_MASK		0x0000000000040000UL
+#define UV2H_EVENT_OCCURRED0_NI1_AOERR0_MASK		0x0000000000080000UL
+#define UV2H_EVENT_OCCURRED0_LB_AOERR1_MASK		0x0000000000100000UL
+#define UV2H_EVENT_OCCURRED0_QP_AOERR1_MASK		0x0000000000200000UL
+#define UV2H_EVENT_OCCURRED0_RH_AOERR1_MASK		0x0000000000400000UL
+#define UV2H_EVENT_OCCURRED0_LH0_AOERR1_MASK		0x0000000000800000UL
+#define UV2H_EVENT_OCCURRED0_LH1_AOERR1_MASK		0x0000000001000000UL
+#define UV2H_EVENT_OCCURRED0_GR0_AOERR1_MASK		0x0000000002000000UL
+#define UV2H_EVENT_OCCURRED0_GR1_AOERR1_MASK		0x0000000004000000UL
+#define UV2H_EVENT_OCCURRED0_XB_AOERR1_MASK		0x0000000008000000UL
+#define UV2H_EVENT_OCCURRED0_RT_AOERR1_MASK		0x0000000010000000UL
+#define UV2H_EVENT_OCCURRED0_NI0_AOERR1_MASK		0x0000000020000000UL
+#define UV2H_EVENT_OCCURRED0_NI1_AOERR1_MASK		0x0000000040000000UL
+#define UV2H_EVENT_OCCURRED0_SYSTEM_SHUTDOWN_INT_MASK	0x0000000080000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_0_MASK		0x0000000100000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_1_MASK		0x0000000200000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_2_MASK		0x0000000400000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_3_MASK		0x0000000800000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_4_MASK		0x0000001000000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_5_MASK		0x0000002000000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_6_MASK		0x0000004000000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_7_MASK		0x0000008000000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_8_MASK		0x0000010000000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_9_MASK		0x0000020000000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_10_MASK		0x0000040000000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_11_MASK		0x0000080000000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_12_MASK		0x0000100000000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_13_MASK		0x0000200000000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_14_MASK		0x0000400000000000UL
+#define UV2H_EVENT_OCCURRED0_LB_IRQ_INT_15_MASK		0x0000800000000000UL
+#define UV2H_EVENT_OCCURRED0_L1_NMI_INT_MASK		0x0001000000000000UL
+#define UV2H_EVENT_OCCURRED0_STOP_CLOCK_MASK		0x0002000000000000UL
+#define UV2H_EVENT_OCCURRED0_ASIC_TO_L1_MASK		0x0004000000000000UL
+#define UV2H_EVENT_OCCURRED0_L1_TO_ASIC_MASK		0x0008000000000000UL
+#define UV2H_EVENT_OCCURRED0_LA_SEQ_TRIGGER_MASK	0x0010000000000000UL
+#define UV2H_EVENT_OCCURRED0_IPI_INT_MASK		0x0020000000000000UL
+#define UV2H_EVENT_OCCURRED0_EXTIO_INT0_MASK		0x0040000000000000UL
+#define UV2H_EVENT_OCCURRED0_EXTIO_INT1_MASK		0x0080000000000000UL
+#define UV2H_EVENT_OCCURRED0_EXTIO_INT2_MASK		0x0100000000000000UL
+#define UV2H_EVENT_OCCURRED0_EXTIO_INT3_MASK		0x0200000000000000UL
+#define UV2H_EVENT_OCCURRED0_PROFILE_INT_MASK		0x0400000000000000UL
+
+#define UV3H_EVENT_OCCURRED0_QP_HCERR_SHFT		1
+#define UV3H_EVENT_OCCURRED0_QP_AOERR0_SHFT		10
+#define UV3H_EVENT_OCCURRED0_RT_AOERR0_SHFT		17
+#define UV3H_EVENT_OCCURRED0_NI0_AOERR0_SHFT		18
+#define UV3H_EVENT_OCCURRED0_NI1_AOERR0_SHFT		19
+#define UV3H_EVENT_OCCURRED0_LB_AOERR1_SHFT		20
+#define UV3H_EVENT_OCCURRED0_QP_AOERR1_SHFT		21
+#define UV3H_EVENT_OCCURRED0_RH_AOERR1_SHFT		22
+#define UV3H_EVENT_OCCURRED0_LH0_AOERR1_SHFT		23
+#define UV3H_EVENT_OCCURRED0_LH1_AOERR1_SHFT		24
+#define UV3H_EVENT_OCCURRED0_GR0_AOERR1_SHFT		25
+#define UV3H_EVENT_OCCURRED0_GR1_AOERR1_SHFT		26
+#define UV3H_EVENT_OCCURRED0_XB_AOERR1_SHFT		27
+#define UV3H_EVENT_OCCURRED0_RT_AOERR1_SHFT		28
+#define UV3H_EVENT_OCCURRED0_NI0_AOERR1_SHFT		29
+#define UV3H_EVENT_OCCURRED0_NI1_AOERR1_SHFT		30
+#define UV3H_EVENT_OCCURRED0_SYSTEM_SHUTDOWN_INT_SHFT	31
+#define UV3H_EVENT_OCCURRED0_LB_IRQ_INT_0_SHFT		32
+#define UV3H_EVENT_OCCURRED0_LB_IRQ_INT_1_SHFT		33
+#define UV3H_EVENT_OCCURRED0_LB_IRQ_INT_2_SHFT		34
+#define UV3H_EVENT_OCCURRED0_LB_IRQ_INT_3_SHFT		35
+#define UV3H_EVENT_OCCURRED0_LB_IRQ_INT_4_SHFT		36
+#define UV3H_EVENT_OCCURRED0_LB_IRQ_INT_5_SHFT		37
+#define UV3H_EVENT_OCCURRED0_LB_IRQ_INT_6_SHFT		38
+#define UV3H_EVENT_OCCURRED0_LB_IRQ_INT_7_SHFT		39
+#define UV3H_EVENT_OCCURRED0_LB_IRQ_INT_8_SHFT		40
+#define UV3H_EVENT_OCCURRED0_LB_IRQ_INT_9_SHFT		41
+#define UV3H_EVENT_OCCURRED0_LB_IRQ_INT_10_SHFT		42
+#define UV3H_EVENT_OCCURRED0_LB_IRQ_INT_11_SHFT		43
+#define UV3H_EVENT_OCCURRED0_LB_IRQ_INT_12_SHFT		44
+#define UV3H_EVENT_OCCURRED0_LB_IRQ_INT_13_SHFT		45
+#define UV3H_EVENT_OCCURRED0_LB_IRQ_INT_14_SHFT		46
+#define UV3H_EVENT_OCCURRED0_LB_IRQ_INT_15_SHFT		47
+#define UV3H_EVENT_OCCURRED0_L1_NMI_INT_SHFT		48
+#define UV3H_EVENT_OCCURRED0_STOP_CLOCK_SHFT		49
+#define UV3H_EVENT_OCCURRED0_ASIC_TO_L1_SHFT		50
+#define UV3H_EVENT_OCCURRED0_L1_TO_ASIC_SHFT		51
+#define UV3H_EVENT_OCCURRED0_LA_SEQ_TRIGGER_SHFT	52
+#define UV3H_EVENT_OCCURRED0_IPI_INT_SHFT		53
+#define UV3H_EVENT_OCCURRED0_EXTIO_INT0_SHFT		54
+#define UV3H_EVENT_OCCURRED0_EXTIO_INT1_SHFT		55
+#define UV3H_EVENT_OCCURRED0_EXTIO_INT2_SHFT		56
+#define UV3H_EVENT_OCCURRED0_EXTIO_INT3_SHFT		57
+#define UV3H_EVENT_OCCURRED0_PROFILE_INT_SHFT		58
+#define UV3H_EVENT_OCCURRED0_QP_HCERR_MASK		0x0000000000000002UL
+#define UV3H_EVENT_OCCURRED0_QP_AOERR0_MASK		0x0000000000000400UL
+#define UV3H_EVENT_OCCURRED0_RT_AOERR0_MASK		0x0000000000020000UL
+#define UV3H_EVENT_OCCURRED0_NI0_AOERR0_MASK		0x0000000000040000UL
+#define UV3H_EVENT_OCCURRED0_NI1_AOERR0_MASK		0x0000000000080000UL
+#define UV3H_EVENT_OCCURRED0_LB_AOERR1_MASK		0x0000000000100000UL
+#define UV3H_EVENT_OCCURRED0_QP_AOERR1_MASK		0x0000000000200000UL
+#define UV3H_EVENT_OCCURRED0_RH_AOERR1_MASK		0x0000000000400000UL
+#define UV3H_EVENT_OCCURRED0_LH0_AOERR1_MASK		0x0000000000800000UL
+#define UV3H_EVENT_OCCURRED0_LH1_AOERR1_MASK		0x0000000001000000UL
+#define UV3H_EVENT_OCCURRED0_GR0_AOERR1_MASK		0x0000000002000000UL
+#define UV3H_EVENT_OCCURRED0_GR1_AOERR1_MASK		0x0000000004000000UL
+#define UV3H_EVENT_OCCURRED0_XB_AOERR1_MASK		0x0000000008000000UL
+#define UV3H_EVENT_OCCURRED0_RT_AOERR1_MASK		0x0000000010000000UL
+#define UV3H_EVENT_OCCURRED0_NI0_AOERR1_MASK		0x0000000020000000UL
+#define UV3H_EVENT_OCCURRED0_NI1_AOERR1_MASK		0x0000000040000000UL
+#define UV3H_EVENT_OCCURRED0_SYSTEM_SHUTDOWN_INT_MASK	0x0000000080000000UL
+#define UV3H_EVENT_OCCURRED0_LB_IRQ_INT_0_MASK		0x0000000100000000UL
+#define UV3H_EVENT_OCCURRED0_LB_IRQ_INT_1_MASK		0x0000000200000000UL
+#define UV3H_EVENT_OCCURRED0_LB_IRQ_INT_2_MASK		0x0000000400000000UL
+#define UV3H_EVENT_OCCURRED0_LB_IRQ_INT_3_MASK		0x0000000800000000UL
+#define UV3H_EVENT_OCCURRED0_LB_IRQ_INT_4_MASK		0x0000001000000000UL
+#define UV3H_EVENT_OCCURRED0_LB_IRQ_INT_5_MASK		0x0000002000000000UL
+#define UV3H_EVENT_OCCURRED0_LB_IRQ_INT_6_MASK		0x0000004000000000UL
+#define UV3H_EVENT_OCCURRED0_LB_IRQ_INT_7_MASK		0x0000008000000000UL
+#define UV3H_EVENT_OCCURRED0_LB_IRQ_INT_8_MASK		0x0000010000000000UL
+#define UV3H_EVENT_OCCURRED0_LB_IRQ_INT_9_MASK		0x0000020000000000UL
+#define UV3H_EVENT_OCCURRED0_LB_IRQ_INT_10_MASK		0x0000040000000000UL
+#define UV3H_EVENT_OCCURRED0_LB_IRQ_INT_11_MASK		0x0000080000000000UL
+#define UV3H_EVENT_OCCURRED0_LB_IRQ_INT_12_MASK		0x0000100000000000UL
+#define UV3H_EVENT_OCCURRED0_LB_IRQ_INT_13_MASK		0x0000200000000000UL
+#define UV3H_EVENT_OCCURRED0_LB_IRQ_INT_14_MASK		0x0000400000000000UL
+#define UV3H_EVENT_OCCURRED0_LB_IRQ_INT_15_MASK		0x0000800000000000UL
+#define UV3H_EVENT_OCCURRED0_L1_NMI_INT_MASK		0x0001000000000000UL
+#define UV3H_EVENT_OCCURRED0_STOP_CLOCK_MASK		0x0002000000000000UL
+#define UV3H_EVENT_OCCURRED0_ASIC_TO_L1_MASK		0x0004000000000000UL
+#define UV3H_EVENT_OCCURRED0_L1_TO_ASIC_MASK		0x0008000000000000UL
+#define UV3H_EVENT_OCCURRED0_LA_SEQ_TRIGGER_MASK	0x0010000000000000UL
+#define UV3H_EVENT_OCCURRED0_IPI_INT_MASK		0x0020000000000000UL
+#define UV3H_EVENT_OCCURRED0_EXTIO_INT0_MASK		0x0040000000000000UL
+#define UV3H_EVENT_OCCURRED0_EXTIO_INT1_MASK		0x0080000000000000UL
+#define UV3H_EVENT_OCCURRED0_EXTIO_INT2_MASK		0x0100000000000000UL
+#define UV3H_EVENT_OCCURRED0_EXTIO_INT3_MASK		0x0200000000000000UL
+#define UV3H_EVENT_OCCURRED0_PROFILE_INT_MASK		0x0400000000000000UL
+
+#define UV4H_EVENT_OCCURRED0_KT_HCERR_SHFT		1
+#define UV4H_EVENT_OCCURRED0_KT_AOERR0_SHFT		10
+#define UV4H_EVENT_OCCURRED0_RTQ0_AOERR0_SHFT		17
+#define UV4H_EVENT_OCCURRED0_RTQ1_AOERR0_SHFT		18
+#define UV4H_EVENT_OCCURRED0_RTQ2_AOERR0_SHFT		19
+#define UV4H_EVENT_OCCURRED0_RTQ3_AOERR0_SHFT		20
+#define UV4H_EVENT_OCCURRED0_NI0_AOERR0_SHFT		21
+#define UV4H_EVENT_OCCURRED0_NI1_AOERR0_SHFT		22
+#define UV4H_EVENT_OCCURRED0_LB_AOERR1_SHFT		23
+#define UV4H_EVENT_OCCURRED0_KT_AOERR1_SHFT		24
+#define UV4H_EVENT_OCCURRED0_RH_AOERR1_SHFT		25
+#define UV4H_EVENT_OCCURRED0_LH0_AOERR1_SHFT		26
+#define UV4H_EVENT_OCCURRED0_LH1_AOERR1_SHFT		27
+#define UV4H_EVENT_OCCURRED0_GR0_AOERR1_SHFT		28
+#define UV4H_EVENT_OCCURRED0_GR1_AOERR1_SHFT		29
+#define UV4H_EVENT_OCCURRED0_XB_AOERR1_SHFT		30
+#define UV4H_EVENT_OCCURRED0_RTQ0_AOERR1_SHFT		31
+#define UV4H_EVENT_OCCURRED0_RTQ1_AOERR1_SHFT		32
+#define UV4H_EVENT_OCCURRED0_RTQ2_AOERR1_SHFT		33
+#define UV4H_EVENT_OCCURRED0_RTQ3_AOERR1_SHFT		34
+#define UV4H_EVENT_OCCURRED0_NI0_AOERR1_SHFT		35
+#define UV4H_EVENT_OCCURRED0_NI1_AOERR1_SHFT		36
+#define UV4H_EVENT_OCCURRED0_SYSTEM_SHUTDOWN_INT_SHFT	37
+#define UV4H_EVENT_OCCURRED0_LB_IRQ_INT_0_SHFT		38
+#define UV4H_EVENT_OCCURRED0_LB_IRQ_INT_1_SHFT		39
+#define UV4H_EVENT_OCCURRED0_LB_IRQ_INT_2_SHFT		40
+#define UV4H_EVENT_OCCURRED0_LB_IRQ_INT_3_SHFT		41
+#define UV4H_EVENT_OCCURRED0_LB_IRQ_INT_4_SHFT		42
+#define UV4H_EVENT_OCCURRED0_LB_IRQ_INT_5_SHFT		43
+#define UV4H_EVENT_OCCURRED0_LB_IRQ_INT_6_SHFT		44
+#define UV4H_EVENT_OCCURRED0_LB_IRQ_INT_7_SHFT		45
+#define UV4H_EVENT_OCCURRED0_LB_IRQ_INT_8_SHFT		46
+#define UV4H_EVENT_OCCURRED0_LB_IRQ_INT_9_SHFT		47
+#define UV4H_EVENT_OCCURRED0_LB_IRQ_INT_10_SHFT		48
+#define UV4H_EVENT_OCCURRED0_LB_IRQ_INT_11_SHFT		49
+#define UV4H_EVENT_OCCURRED0_LB_IRQ_INT_12_SHFT		50
+#define UV4H_EVENT_OCCURRED0_LB_IRQ_INT_13_SHFT		51
+#define UV4H_EVENT_OCCURRED0_LB_IRQ_INT_14_SHFT		52
+#define UV4H_EVENT_OCCURRED0_LB_IRQ_INT_15_SHFT		53
+#define UV4H_EVENT_OCCURRED0_L1_NMI_INT_SHFT		54
+#define UV4H_EVENT_OCCURRED0_STOP_CLOCK_SHFT		55
+#define UV4H_EVENT_OCCURRED0_ASIC_TO_L1_SHFT		56
+#define UV4H_EVENT_OCCURRED0_L1_TO_ASIC_SHFT		57
+#define UV4H_EVENT_OCCURRED0_LA_SEQ_TRIGGER_SHFT	58
+#define UV4H_EVENT_OCCURRED0_IPI_INT_SHFT		59
+#define UV4H_EVENT_OCCURRED0_EXTIO_INT0_SHFT		60
+#define UV4H_EVENT_OCCURRED0_EXTIO_INT1_SHFT		61
+#define UV4H_EVENT_OCCURRED0_EXTIO_INT2_SHFT		62
+#define UV4H_EVENT_OCCURRED0_EXTIO_INT3_SHFT		63
+#define UV4H_EVENT_OCCURRED0_KT_HCERR_MASK		0x0000000000000002UL
+#define UV4H_EVENT_OCCURRED0_KT_AOERR0_MASK		0x0000000000000400UL
+#define UV4H_EVENT_OCCURRED0_RTQ0_AOERR0_MASK		0x0000000000020000UL
+#define UV4H_EVENT_OCCURRED0_RTQ1_AOERR0_MASK		0x0000000000040000UL
+#define UV4H_EVENT_OCCURRED0_RTQ2_AOERR0_MASK		0x0000000000080000UL
+#define UV4H_EVENT_OCCURRED0_RTQ3_AOERR0_MASK		0x0000000000100000UL
+#define UV4H_EVENT_OCCURRED0_NI0_AOERR0_MASK		0x0000000000200000UL
+#define UV4H_EVENT_OCCURRED0_NI1_AOERR0_MASK		0x0000000000400000UL
+#define UV4H_EVENT_OCCURRED0_LB_AOERR1_MASK		0x0000000000800000UL
+#define UV4H_EVENT_OCCURRED0_KT_AOERR1_MASK		0x0000000001000000UL
+#define UV4H_EVENT_OCCURRED0_RH_AOERR1_MASK		0x0000000002000000UL
+#define UV4H_EVENT_OCCURRED0_LH0_AOERR1_MASK		0x0000000004000000UL
+#define UV4H_EVENT_OCCURRED0_LH1_AOERR1_MASK		0x0000000008000000UL
+#define UV4H_EVENT_OCCURRED0_GR0_AOERR1_MASK		0x0000000010000000UL
+#define UV4H_EVENT_OCCURRED0_GR1_AOERR1_MASK		0x0000000020000000UL
+#define UV4H_EVENT_OCCURRED0_XB_AOERR1_MASK		0x0000000040000000UL
+#define UV4H_EVENT_OCCURRED0_RTQ0_AOERR1_MASK		0x0000000080000000UL
+#define UV4H_EVENT_OCCURRED0_RTQ1_AOERR1_MASK		0x0000000100000000UL
+#define UV4H_EVENT_OCCURRED0_RTQ2_AOERR1_MASK		0x0000000200000000UL
+#define UV4H_EVENT_OCCURRED0_RTQ3_AOERR1_MASK		0x0000000400000000UL
+#define UV4H_EVENT_OCCURRED0_NI0_AOERR1_MASK		0x0000000800000000UL
+#define UV4H_EVENT_OCCURRED0_NI1_AOERR1_MASK		0x0000001000000000UL
+#define UV4H_EVENT_OCCURRED0_SYSTEM_SHUTDOWN_INT_MASK	0x0000002000000000UL
+#define UV4H_EVENT_OCCURRED0_LB_IRQ_INT_0_MASK		0x0000004000000000UL
+#define UV4H_EVENT_OCCURRED0_LB_IRQ_INT_1_MASK		0x0000008000000000UL
+#define UV4H_EVENT_OCCURRED0_LB_IRQ_INT_2_MASK		0x0000010000000000UL
+#define UV4H_EVENT_OCCURRED0_LB_IRQ_INT_3_MASK		0x0000020000000000UL
+#define UV4H_EVENT_OCCURRED0_LB_IRQ_INT_4_MASK		0x0000040000000000UL
+#define UV4H_EVENT_OCCURRED0_LB_IRQ_INT_5_MASK		0x0000080000000000UL
+#define UV4H_EVENT_OCCURRED0_LB_IRQ_INT_6_MASK		0x0000100000000000UL
+#define UV4H_EVENT_OCCURRED0_LB_IRQ_INT_7_MASK		0x0000200000000000UL
+#define UV4H_EVENT_OCCURRED0_LB_IRQ_INT_8_MASK		0x0000400000000000UL
+#define UV4H_EVENT_OCCURRED0_LB_IRQ_INT_9_MASK		0x0000800000000000UL
+#define UV4H_EVENT_OCCURRED0_LB_IRQ_INT_10_MASK		0x0001000000000000UL
+#define UV4H_EVENT_OCCURRED0_LB_IRQ_INT_11_MASK		0x0002000000000000UL
+#define UV4H_EVENT_OCCURRED0_LB_IRQ_INT_12_MASK		0x0004000000000000UL
+#define UV4H_EVENT_OCCURRED0_LB_IRQ_INT_13_MASK		0x0008000000000000UL
+#define UV4H_EVENT_OCCURRED0_LB_IRQ_INT_14_MASK		0x0010000000000000UL
+#define UV4H_EVENT_OCCURRED0_LB_IRQ_INT_15_MASK		0x0020000000000000UL
+#define UV4H_EVENT_OCCURRED0_L1_NMI_INT_MASK		0x0040000000000000UL
+#define UV4H_EVENT_OCCURRED0_STOP_CLOCK_MASK		0x0080000000000000UL
+#define UV4H_EVENT_OCCURRED0_ASIC_TO_L1_MASK		0x0100000000000000UL
+#define UV4H_EVENT_OCCURRED0_L1_TO_ASIC_MASK		0x0200000000000000UL
+#define UV4H_EVENT_OCCURRED0_LA_SEQ_TRIGGER_MASK	0x0400000000000000UL
+#define UV4H_EVENT_OCCURRED0_IPI_INT_MASK		0x0800000000000000UL
+#define UV4H_EVENT_OCCURRED0_EXTIO_INT0_MASK		0x1000000000000000UL
+#define UV4H_EVENT_OCCURRED0_EXTIO_INT1_MASK		0x2000000000000000UL
+#define UV4H_EVENT_OCCURRED0_EXTIO_INT2_MASK		0x4000000000000000UL
+#define UV4H_EVENT_OCCURRED0_EXTIO_INT3_MASK		0x8000000000000000UL
+
+#define UVH_EVENT_OCCURRED0_EXTIO_INT0_SHFT (				\
+	is_uv1_hub() ? UV1H_EVENT_OCCURRED0_EXTIO_INT0_SHFT :		\
+	is_uv2_hub() ? UV2H_EVENT_OCCURRED0_EXTIO_INT0_SHFT :		\
+	is_uv3_hub() ? UV3H_EVENT_OCCURRED0_EXTIO_INT0_SHFT :		\
+	/*is_uv4_hub*/ UV4H_EVENT_OCCURRED0_EXTIO_INT0_SHFT)
 
 union uvh_event_occurred0_u {
 	unsigned long	v;
@@ -391,7 +621,7 @@ union uvh_event_occurred0_u {
 	} s;
 	struct uvxh_event_occurred0_s {
 		unsigned long	lb_hcerr:1;			/* RW */
-		unsigned long	qp_hcerr:1;			/* RW */
+		unsigned long	rsvd_1:1;
 		unsigned long	rh_hcerr:1;			/* RW */
 		unsigned long	lh0_hcerr:1;			/* RW */
 		unsigned long	lh1_hcerr:1;			/* RW */
@@ -400,25 +630,51 @@ union uvh_event_occurred0_u {
 		unsigned long	ni0_hcerr:1;			/* RW */
 		unsigned long	ni1_hcerr:1;			/* RW */
 		unsigned long	lb_aoerr0:1;			/* RW */
-		unsigned long	qp_aoerr0:1;			/* RW */
+		unsigned long	rsvd_10:1;
 		unsigned long	rh_aoerr0:1;			/* RW */
 		unsigned long	lh0_aoerr0:1;			/* RW */
 		unsigned long	lh1_aoerr0:1;			/* RW */
 		unsigned long	gr0_aoerr0:1;			/* RW */
 		unsigned long	gr1_aoerr0:1;			/* RW */
 		unsigned long	xb_aoerr0:1;			/* RW */
-		unsigned long	rt_aoerr0:1;			/* RW */
+		unsigned long	rsvd_17_63:47;
+	} sx;
+	struct uv4h_event_occurred0_s {
+		unsigned long	lb_hcerr:1;			/* RW */
+		unsigned long	kt_hcerr:1;			/* RW */
+		unsigned long	rh_hcerr:1;			/* RW */
+		unsigned long	lh0_hcerr:1;			/* RW */
+		unsigned long	lh1_hcerr:1;			/* RW */
+		unsigned long	gr0_hcerr:1;			/* RW */
+		unsigned long	gr1_hcerr:1;			/* RW */
+		unsigned long	ni0_hcerr:1;			/* RW */
+		unsigned long	ni1_hcerr:1;			/* RW */
+		unsigned long	lb_aoerr0:1;			/* RW */
+		unsigned long	kt_aoerr0:1;			/* RW */
+		unsigned long	rh_aoerr0:1;			/* RW */
+		unsigned long	lh0_aoerr0:1;			/* RW */
+		unsigned long	lh1_aoerr0:1;			/* RW */
+		unsigned long	gr0_aoerr0:1;			/* RW */
+		unsigned long	gr1_aoerr0:1;			/* RW */
+		unsigned long	xb_aoerr0:1;			/* RW */
+		unsigned long	rtq0_aoerr0:1;			/* RW */
+		unsigned long	rtq1_aoerr0:1;			/* RW */
+		unsigned long	rtq2_aoerr0:1;			/* RW */
+		unsigned long	rtq3_aoerr0:1;			/* RW */
 		unsigned long	ni0_aoerr0:1;			/* RW */
 		unsigned long	ni1_aoerr0:1;			/* RW */
 		unsigned long	lb_aoerr1:1;			/* RW */
-		unsigned long	qp_aoerr1:1;			/* RW */
+		unsigned long	kt_aoerr1:1;			/* RW */
 		unsigned long	rh_aoerr1:1;			/* RW */
 		unsigned long	lh0_aoerr1:1;			/* RW */
 		unsigned long	lh1_aoerr1:1;			/* RW */
 		unsigned long	gr0_aoerr1:1;			/* RW */
 		unsigned long	gr1_aoerr1:1;			/* RW */
 		unsigned long	xb_aoerr1:1;			/* RW */
-		unsigned long	rt_aoerr1:1;			/* RW */
+		unsigned long	rtq0_aoerr1:1;			/* RW */
+		unsigned long	rtq1_aoerr1:1;			/* RW */
+		unsigned long	rtq2_aoerr1:1;			/* RW */
+		unsigned long	rtq3_aoerr1:1;			/* RW */
 		unsigned long	ni0_aoerr1:1;			/* RW */
 		unsigned long	ni1_aoerr1:1;			/* RW */
 		unsigned long	system_shutdown_int:1;		/* RW */
@@ -448,9 +704,7 @@ union uvh_event_occurred0_u {
 		unsigned long	extio_int1:1;			/* RW */
 		unsigned long	extio_int2:1;			/* RW */
 		unsigned long	extio_int3:1;			/* RW */
-		unsigned long	profile_int:1;			/* RW */
-		unsigned long	rsvd_59_63:5;
-	} sx;
+	} s4;
 };
 
 /* ========================================================================= */
@@ -464,11 +718,21 @@ union uvh_event_occurred0_u {
 /*                         UVH_EXTIO_INT0_BROADCAST                          */
 /* ========================================================================= */
 #define UVH_EXTIO_INT0_BROADCAST 0x61448UL
-#define UVH_EXTIO_INT0_BROADCAST_32 0x3f0
+
+#define UV1H_EXTIO_INT0_BROADCAST_32 0x3f0
+#define UV2H_EXTIO_INT0_BROADCAST_32 0x3f0
+#define UV3H_EXTIO_INT0_BROADCAST_32 0x3f0
+#define UV4H_EXTIO_INT0_BROADCAST_32 0x310
+#define UVH_EXTIO_INT0_BROADCAST_32 (					\
+	is_uv1_hub() ? UV1H_EXTIO_INT0_BROADCAST_32 :			\
+	is_uv2_hub() ? UV2H_EXTIO_INT0_BROADCAST_32 :			\
+	is_uv3_hub() ? UV3H_EXTIO_INT0_BROADCAST_32 :			\
+	/*is_uv4_hub*/ UV4H_EXTIO_INT0_BROADCAST_32)
 
 #define UVH_EXTIO_INT0_BROADCAST_ENABLE_SHFT		0
 #define UVH_EXTIO_INT0_BROADCAST_ENABLE_MASK		0x0000000000000001UL
 
+
 union uvh_extio_int0_broadcast_u {
 	unsigned long	v;
 	struct uvh_extio_int0_broadcast_s {
@@ -499,6 +763,7 @@ union uvh_extio_int0_broadcast_u {
 #define UVH_GR0_TLB_INT0_CONFIG_M_MASK			0x0000000000010000UL
 #define UVH_GR0_TLB_INT0_CONFIG_APIC_ID_MASK		0xffffffff00000000UL
 
+
 union uvh_gr0_tlb_int0_config_u {
 	unsigned long	v;
 	struct uvh_gr0_tlb_int0_config_s {
@@ -537,6 +802,7 @@ union uvh_gr0_tlb_int0_config_u {
 #define UVH_GR0_TLB_INT1_CONFIG_M_MASK			0x0000000000010000UL
 #define UVH_GR0_TLB_INT1_CONFIG_APIC_ID_MASK		0xffffffff00000000UL
 
+
 union uvh_gr0_tlb_int1_config_u {
 	unsigned long	v;
 	struct uvh_gr0_tlb_int1_config_s {
@@ -559,19 +825,18 @@ union uvh_gr0_tlb_int1_config_u {
 #define UV1H_GR0_TLB_MMR_CONTROL 0x401080UL
 #define UV2H_GR0_TLB_MMR_CONTROL 0xc01080UL
 #define UV3H_GR0_TLB_MMR_CONTROL 0xc01080UL
-#define UVH_GR0_TLB_MMR_CONTROL						\
-		(is_uv1_hub() ? UV1H_GR0_TLB_MMR_CONTROL :		\
-		(is_uv2_hub() ? UV2H_GR0_TLB_MMR_CONTROL :		\
-				UV3H_GR0_TLB_MMR_CONTROL))
+#define UV4H_GR0_TLB_MMR_CONTROL 0x601080UL
+#define UVH_GR0_TLB_MMR_CONTROL (					\
+	is_uv1_hub() ? UV1H_GR0_TLB_MMR_CONTROL :			\
+	is_uv2_hub() ? UV2H_GR0_TLB_MMR_CONTROL :			\
+	is_uv3_hub() ? UV3H_GR0_TLB_MMR_CONTROL :			\
+	/*is_uv4_hub*/ UV4H_GR0_TLB_MMR_CONTROL)
 
 #define UVH_GR0_TLB_MMR_CONTROL_INDEX_SHFT		0
-#define UVH_GR0_TLB_MMR_CONTROL_MEM_SEL_SHFT		12
 #define UVH_GR0_TLB_MMR_CONTROL_AUTO_VALID_EN_SHFT	16
 #define UVH_GR0_TLB_MMR_CONTROL_MMR_HASH_INDEX_EN_SHFT	20
 #define UVH_GR0_TLB_MMR_CONTROL_MMR_WRITE_SHFT		30
 #define UVH_GR0_TLB_MMR_CONTROL_MMR_READ_SHFT		31
-#define UVH_GR0_TLB_MMR_CONTROL_INDEX_MASK		0x0000000000000fffUL
-#define UVH_GR0_TLB_MMR_CONTROL_MEM_SEL_MASK		0x0000000000003000UL
 #define UVH_GR0_TLB_MMR_CONTROL_AUTO_VALID_EN_MASK	0x0000000000010000UL
 #define UVH_GR0_TLB_MMR_CONTROL_MMR_HASH_INDEX_EN_MASK	0x0000000000100000UL
 #define UVH_GR0_TLB_MMR_CONTROL_MMR_WRITE_MASK		0x0000000040000000UL
@@ -601,14 +866,11 @@ union uvh_gr0_tlb_int1_config_u {
 #define UV1H_GR0_TLB_MMR_CONTROL_MMR_INJ_TLBLRUV_MASK	0x1000000000000000UL
 
 #define UVXH_GR0_TLB_MMR_CONTROL_INDEX_SHFT		0
-#define UVXH_GR0_TLB_MMR_CONTROL_MEM_SEL_SHFT		12
 #define UVXH_GR0_TLB_MMR_CONTROL_AUTO_VALID_EN_SHFT	16
 #define UVXH_GR0_TLB_MMR_CONTROL_MMR_HASH_INDEX_EN_SHFT	20
 #define UVXH_GR0_TLB_MMR_CONTROL_MMR_WRITE_SHFT		30
 #define UVXH_GR0_TLB_MMR_CONTROL_MMR_READ_SHFT		31
 #define UVXH_GR0_TLB_MMR_CONTROL_MMR_OP_DONE_SHFT	32
-#define UVXH_GR0_TLB_MMR_CONTROL_INDEX_MASK		0x0000000000000fffUL
-#define UVXH_GR0_TLB_MMR_CONTROL_MEM_SEL_MASK		0x0000000000003000UL
 #define UVXH_GR0_TLB_MMR_CONTROL_AUTO_VALID_EN_MASK	0x0000000000010000UL
 #define UVXH_GR0_TLB_MMR_CONTROL_MMR_HASH_INDEX_EN_MASK	0x0000000000100000UL
 #define UVXH_GR0_TLB_MMR_CONTROL_MMR_WRITE_MASK		0x0000000040000000UL
@@ -651,12 +913,45 @@ union uvh_gr0_tlb_int1_config_u {
 #define UV3H_GR0_TLB_MMR_CONTROL_MMR_READ_MASK		0x0000000080000000UL
 #define UV3H_GR0_TLB_MMR_CONTROL_MMR_OP_DONE_MASK	0x0000000100000000UL
 
+#define UV4H_GR0_TLB_MMR_CONTROL_INDEX_SHFT		0
+#define UV4H_GR0_TLB_MMR_CONTROL_MEM_SEL_SHFT		13
+#define UV4H_GR0_TLB_MMR_CONTROL_AUTO_VALID_EN_SHFT	16
+#define UV4H_GR0_TLB_MMR_CONTROL_MMR_HASH_INDEX_EN_SHFT	20
+#define UV4H_GR0_TLB_MMR_CONTROL_ECC_SEL_SHFT		21
+#define UV4H_GR0_TLB_MMR_CONTROL_MMR_WRITE_SHFT		30
+#define UV4H_GR0_TLB_MMR_CONTROL_MMR_READ_SHFT		31
+#define UV4H_GR0_TLB_MMR_CONTROL_MMR_OP_DONE_SHFT	32
+#define UV4H_GR0_TLB_MMR_CONTROL_PAGE_SIZE_SHFT		59
+#define UV4H_GR0_TLB_MMR_CONTROL_INDEX_MASK		0x0000000000001fffUL
+#define UV4H_GR0_TLB_MMR_CONTROL_MEM_SEL_MASK		0x0000000000006000UL
+#define UV4H_GR0_TLB_MMR_CONTROL_AUTO_VALID_EN_MASK	0x0000000000010000UL
+#define UV4H_GR0_TLB_MMR_CONTROL_MMR_HASH_INDEX_EN_MASK	0x0000000000100000UL
+#define UV4H_GR0_TLB_MMR_CONTROL_ECC_SEL_MASK		0x0000000000200000UL
+#define UV4H_GR0_TLB_MMR_CONTROL_MMR_WRITE_MASK		0x0000000040000000UL
+#define UV4H_GR0_TLB_MMR_CONTROL_MMR_READ_MASK		0x0000000080000000UL
+#define UV4H_GR0_TLB_MMR_CONTROL_MMR_OP_DONE_MASK	0x0000000100000000UL
+#define UV4H_GR0_TLB_MMR_CONTROL_PAGE_SIZE_MASK		0xf800000000000000UL
+
+#define UVH_GR0_TLB_MMR_CONTROL_INDEX_MASK (				\
+	is_uv1_hub() ? UV1H_GR0_TLB_MMR_CONTROL_INDEX_MASK :		\
+	is_uv2_hub() ? UV2H_GR0_TLB_MMR_CONTROL_INDEX_MASK :		\
+	is_uv3_hub() ? UV3H_GR0_TLB_MMR_CONTROL_INDEX_MASK :		\
+	/*is_uv4_hub*/ UV4H_GR0_TLB_MMR_CONTROL_INDEX_MASK)
+#define UVH_GR0_TLB_MMR_CONTROL_MEM_SEL_MASK (				\
+	is_uv1_hub() ? UV1H_GR0_TLB_MMR_CONTROL_MEM_SEL_MASK :		\
+	is_uv2_hub() ? UV2H_GR0_TLB_MMR_CONTROL_MEM_SEL_MASK :		\
+	is_uv3_hub() ? UV3H_GR0_TLB_MMR_CONTROL_MEM_SEL_MASK :		\
+	/*is_uv4_hub*/ UV4H_GR0_TLB_MMR_CONTROL_MEM_SEL_MASK)
+#define UVH_GR0_TLB_MMR_CONTROL_MEM_SEL_SHFT (				\
+	is_uv1_hub() ? UV1H_GR0_TLB_MMR_CONTROL_MEM_SEL_SHFT :		\
+	is_uv2_hub() ? UV2H_GR0_TLB_MMR_CONTROL_MEM_SEL_SHFT :		\
+	is_uv3_hub() ? UV3H_GR0_TLB_MMR_CONTROL_MEM_SEL_SHFT :		\
+	/*is_uv4_hub*/ UV4H_GR0_TLB_MMR_CONTROL_MEM_SEL_SHFT)
+
 union uvh_gr0_tlb_mmr_control_u {
 	unsigned long	v;
 	struct uvh_gr0_tlb_mmr_control_s {
-		unsigned long	index:12;			/* RW */
-		unsigned long	mem_sel:2;			/* RW */
-		unsigned long	rsvd_14_15:2;
+		unsigned long	rsvd_0_15:16;
 		unsigned long	auto_valid_en:1;		/* RW */
 		unsigned long	rsvd_17_19:3;
 		unsigned long	mmr_hash_index_en:1;		/* RW */
@@ -690,9 +985,7 @@ union uvh_gr0_tlb_mmr_control_u {
 		unsigned long	rsvd_61_63:3;
 	} s1;
 	struct uvxh_gr0_tlb_mmr_control_s {
-		unsigned long	index:12;			/* RW */
-		unsigned long	mem_sel:2;			/* RW */
-		unsigned long	rsvd_14_15:2;
+		unsigned long	rsvd_0_15:16;
 		unsigned long	auto_valid_en:1;		/* RW */
 		unsigned long	rsvd_17_19:3;
 		unsigned long	mmr_hash_index_en:1;		/* RW */
@@ -703,8 +996,7 @@ union uvh_gr0_tlb_mmr_control_u {
 		unsigned long	rsvd_33_47:15;
 		unsigned long	rsvd_48:1;
 		unsigned long	rsvd_49_51:3;
-		unsigned long	rsvd_52:1;
-		unsigned long	rsvd_53_63:11;
+		unsigned long	rsvd_52_63:12;
 	} sx;
 	struct uv2h_gr0_tlb_mmr_control_s {
 		unsigned long	index:12;			/* RW */
@@ -741,6 +1033,24 @@ union uvh_gr0_tlb_mmr_control_u {
 		unsigned long	undef_52:1;			/* Undefined */
 		unsigned long	rsvd_53_63:11;
 	} s3;
+	struct uv4h_gr0_tlb_mmr_control_s {
+		unsigned long	index:13;			/* RW */
+		unsigned long	mem_sel:2;			/* RW */
+		unsigned long	rsvd_15:1;
+		unsigned long	auto_valid_en:1;		/* RW */
+		unsigned long	rsvd_17_19:3;
+		unsigned long	mmr_hash_index_en:1;		/* RW */
+		unsigned long	ecc_sel:1;			/* RW */
+		unsigned long	rsvd_22_29:8;
+		unsigned long	mmr_write:1;			/* WP */
+		unsigned long	mmr_read:1;			/* WP */
+		unsigned long	mmr_op_done:1;			/* RW */
+		unsigned long	rsvd_33_47:15;
+		unsigned long	undef_48:1;			/* Undefined */
+		unsigned long	rsvd_49_51:3;
+		unsigned long	rsvd_52_58:7;
+		unsigned long	page_size:5;			/* RW */
+	} s4;
 };
 
 /* ========================================================================= */
@@ -749,19 +1059,14 @@ union uvh_gr0_tlb_mmr_control_u {
 #define UV1H_GR0_TLB_MMR_READ_DATA_HI 0x4010a0UL
 #define UV2H_GR0_TLB_MMR_READ_DATA_HI 0xc010a0UL
 #define UV3H_GR0_TLB_MMR_READ_DATA_HI 0xc010a0UL
-#define UVH_GR0_TLB_MMR_READ_DATA_HI					\
-		(is_uv1_hub() ? UV1H_GR0_TLB_MMR_READ_DATA_HI :		\
-		(is_uv2_hub() ? UV2H_GR0_TLB_MMR_READ_DATA_HI :		\
-				UV3H_GR0_TLB_MMR_READ_DATA_HI))
+#define UV4H_GR0_TLB_MMR_READ_DATA_HI 0x6010a0UL
+#define UVH_GR0_TLB_MMR_READ_DATA_HI (					\
+	is_uv1_hub() ? UV1H_GR0_TLB_MMR_READ_DATA_HI :			\
+	is_uv2_hub() ? UV2H_GR0_TLB_MMR_READ_DATA_HI :			\
+	is_uv3_hub() ? UV3H_GR0_TLB_MMR_READ_DATA_HI :			\
+	/*is_uv4_hub*/ UV4H_GR0_TLB_MMR_READ_DATA_HI)
 
 #define UVH_GR0_TLB_MMR_READ_DATA_HI_PFN_SHFT		0
-#define UVH_GR0_TLB_MMR_READ_DATA_HI_GAA_SHFT		41
-#define UVH_GR0_TLB_MMR_READ_DATA_HI_DIRTY_SHFT		43
-#define UVH_GR0_TLB_MMR_READ_DATA_HI_LARGER_SHFT	44
-#define UVH_GR0_TLB_MMR_READ_DATA_HI_PFN_MASK		0x000001ffffffffffUL
-#define UVH_GR0_TLB_MMR_READ_DATA_HI_GAA_MASK		0x0000060000000000UL
-#define UVH_GR0_TLB_MMR_READ_DATA_HI_DIRTY_MASK		0x0000080000000000UL
-#define UVH_GR0_TLB_MMR_READ_DATA_HI_LARGER_MASK	0x0000100000000000UL
 
 #define UV1H_GR0_TLB_MMR_READ_DATA_HI_PFN_SHFT		0
 #define UV1H_GR0_TLB_MMR_READ_DATA_HI_GAA_SHFT		41
@@ -773,13 +1078,6 @@ union uvh_gr0_tlb_mmr_control_u {
 #define UV1H_GR0_TLB_MMR_READ_DATA_HI_LARGER_MASK	0x0000100000000000UL
 
 #define UVXH_GR0_TLB_MMR_READ_DATA_HI_PFN_SHFT		0
-#define UVXH_GR0_TLB_MMR_READ_DATA_HI_GAA_SHFT		41
-#define UVXH_GR0_TLB_MMR_READ_DATA_HI_DIRTY_SHFT	43
-#define UVXH_GR0_TLB_MMR_READ_DATA_HI_LARGER_SHFT	44
-#define UVXH_GR0_TLB_MMR_READ_DATA_HI_PFN_MASK		0x000001ffffffffffUL
-#define UVXH_GR0_TLB_MMR_READ_DATA_HI_GAA_MASK		0x0000060000000000UL
-#define UVXH_GR0_TLB_MMR_READ_DATA_HI_DIRTY_MASK	0x0000080000000000UL
-#define UVXH_GR0_TLB_MMR_READ_DATA_HI_LARGER_MASK	0x0000100000000000UL
 
 #define UV2H_GR0_TLB_MMR_READ_DATA_HI_PFN_SHFT		0
 #define UV2H_GR0_TLB_MMR_READ_DATA_HI_GAA_SHFT		41
@@ -803,15 +1101,24 @@ union uvh_gr0_tlb_mmr_control_u {
 #define UV3H_GR0_TLB_MMR_READ_DATA_HI_AA_EXT_MASK	0x0000200000000000UL
 #define UV3H_GR0_TLB_MMR_READ_DATA_HI_WAY_ECC_MASK	0xff80000000000000UL
 
+#define UV4H_GR0_TLB_MMR_READ_DATA_HI_PFN_SHFT		0
+#define UV4H_GR0_TLB_MMR_READ_DATA_HI_PNID_SHFT		34
+#define UV4H_GR0_TLB_MMR_READ_DATA_HI_GAA_SHFT		49
+#define UV4H_GR0_TLB_MMR_READ_DATA_HI_DIRTY_SHFT	51
+#define UV4H_GR0_TLB_MMR_READ_DATA_HI_LARGER_SHFT	52
+#define UV4H_GR0_TLB_MMR_READ_DATA_HI_AA_EXT_SHFT	53
+#define UV4H_GR0_TLB_MMR_READ_DATA_HI_WAY_ECC_SHFT	55
+#define UV4H_GR0_TLB_MMR_READ_DATA_HI_PFN_MASK		0x00000003ffffffffUL
+#define UV4H_GR0_TLB_MMR_READ_DATA_HI_PNID_MASK		0x0001fffc00000000UL
+#define UV4H_GR0_TLB_MMR_READ_DATA_HI_GAA_MASK		0x0006000000000000UL
+#define UV4H_GR0_TLB_MMR_READ_DATA_HI_DIRTY_MASK	0x0008000000000000UL
+#define UV4H_GR0_TLB_MMR_READ_DATA_HI_LARGER_MASK	0x0010000000000000UL
+#define UV4H_GR0_TLB_MMR_READ_DATA_HI_AA_EXT_MASK	0x0020000000000000UL
+#define UV4H_GR0_TLB_MMR_READ_DATA_HI_WAY_ECC_MASK	0xff80000000000000UL
+
+
 union uvh_gr0_tlb_mmr_read_data_hi_u {
 	unsigned long	v;
-	struct uvh_gr0_tlb_mmr_read_data_hi_s {
-		unsigned long	pfn:41;				/* RO */
-		unsigned long	gaa:2;				/* RO */
-		unsigned long	dirty:1;			/* RO */
-		unsigned long	larger:1;			/* RO */
-		unsigned long	rsvd_45_63:19;
-	} s;
 	struct uv1h_gr0_tlb_mmr_read_data_hi_s {
 		unsigned long	pfn:41;				/* RO */
 		unsigned long	gaa:2;				/* RO */
@@ -819,13 +1126,6 @@ union uvh_gr0_tlb_mmr_read_data_hi_u {
 		unsigned long	larger:1;			/* RO */
 		unsigned long	rsvd_45_63:19;
 	} s1;
-	struct uvxh_gr0_tlb_mmr_read_data_hi_s {
-		unsigned long	pfn:41;				/* RO */
-		unsigned long	gaa:2;				/* RO */
-		unsigned long	dirty:1;			/* RO */
-		unsigned long	larger:1;			/* RO */
-		unsigned long	rsvd_45_63:19;
-	} sx;
 	struct uv2h_gr0_tlb_mmr_read_data_hi_s {
 		unsigned long	pfn:41;				/* RO */
 		unsigned long	gaa:2;				/* RO */
@@ -842,6 +1142,16 @@ union uvh_gr0_tlb_mmr_read_data_hi_u {
 		unsigned long	undef_46_54:9;			/* Undefined */
 		unsigned long	way_ecc:9;			/* RO */
 	} s3;
+	struct uv4h_gr0_tlb_mmr_read_data_hi_s {
+		unsigned long	pfn:34;				/* RO */
+		unsigned long	pnid:15;			/* RO */
+		unsigned long	gaa:2;				/* RO */
+		unsigned long	dirty:1;			/* RO */
+		unsigned long	larger:1;			/* RO */
+		unsigned long	aa_ext:1;			/* RO */
+		unsigned long	undef_54:1;			/* Undefined */
+		unsigned long	way_ecc:9;			/* RO */
+	} s4;
 };
 
 /* ========================================================================= */
@@ -850,10 +1160,12 @@ union uvh_gr0_tlb_mmr_read_data_hi_u {
 #define UV1H_GR0_TLB_MMR_READ_DATA_LO 0x4010a8UL
 #define UV2H_GR0_TLB_MMR_READ_DATA_LO 0xc010a8UL
 #define UV3H_GR0_TLB_MMR_READ_DATA_LO 0xc010a8UL
-#define UVH_GR0_TLB_MMR_READ_DATA_LO					\
-		(is_uv1_hub() ? UV1H_GR0_TLB_MMR_READ_DATA_LO :		\
-		(is_uv2_hub() ? UV2H_GR0_TLB_MMR_READ_DATA_LO :		\
-				UV3H_GR0_TLB_MMR_READ_DATA_LO))
+#define UV4H_GR0_TLB_MMR_READ_DATA_LO 0x6010a8UL
+#define UVH_GR0_TLB_MMR_READ_DATA_LO (					\
+	is_uv1_hub() ? UV1H_GR0_TLB_MMR_READ_DATA_LO :			\
+	is_uv2_hub() ? UV2H_GR0_TLB_MMR_READ_DATA_LO :			\
+	is_uv3_hub() ? UV3H_GR0_TLB_MMR_READ_DATA_LO :			\
+	/*is_uv4_hub*/ UV4H_GR0_TLB_MMR_READ_DATA_LO)
 
 #define UVH_GR0_TLB_MMR_READ_DATA_LO_VPN_SHFT		0
 #define UVH_GR0_TLB_MMR_READ_DATA_LO_ASID_SHFT		39
@@ -890,6 +1202,14 @@ union uvh_gr0_tlb_mmr_read_data_hi_u {
 #define UV3H_GR0_TLB_MMR_READ_DATA_LO_ASID_MASK		0x7fffff8000000000UL
 #define UV3H_GR0_TLB_MMR_READ_DATA_LO_VALID_MASK	0x8000000000000000UL
 
+#define UV4H_GR0_TLB_MMR_READ_DATA_LO_VPN_SHFT		0
+#define UV4H_GR0_TLB_MMR_READ_DATA_LO_ASID_SHFT		39
+#define UV4H_GR0_TLB_MMR_READ_DATA_LO_VALID_SHFT	63
+#define UV4H_GR0_TLB_MMR_READ_DATA_LO_VPN_MASK		0x0000007fffffffffUL
+#define UV4H_GR0_TLB_MMR_READ_DATA_LO_ASID_MASK		0x7fffff8000000000UL
+#define UV4H_GR0_TLB_MMR_READ_DATA_LO_VALID_MASK	0x8000000000000000UL
+
+
 union uvh_gr0_tlb_mmr_read_data_lo_u {
 	unsigned long	v;
 	struct uvh_gr0_tlb_mmr_read_data_lo_s {
@@ -917,12 +1237,25 @@ union uvh_gr0_tlb_mmr_read_data_lo_u {
 		unsigned long	asid:24;			/* RO */
 		unsigned long	valid:1;			/* RO */
 	} s3;
+	struct uv4h_gr0_tlb_mmr_read_data_lo_s {
+		unsigned long	vpn:39;				/* RO */
+		unsigned long	asid:24;			/* RO */
+		unsigned long	valid:1;			/* RO */
+	} s4;
 };
 
 /* ========================================================================= */
 /*                         UVH_GR1_TLB_INT0_CONFIG                           */
 /* ========================================================================= */
-#define UVH_GR1_TLB_INT0_CONFIG 0x61f00UL
+#define UV1H_GR1_TLB_INT0_CONFIG 0x61f00UL
+#define UV2H_GR1_TLB_INT0_CONFIG 0x61f00UL
+#define UV3H_GR1_TLB_INT0_CONFIG 0x61f00UL
+#define UV4H_GR1_TLB_INT0_CONFIG 0x62100UL
+#define UVH_GR1_TLB_INT0_CONFIG (					\
+	is_uv1_hub() ? UV1H_GR1_TLB_INT0_CONFIG :			\
+	is_uv2_hub() ? UV2H_GR1_TLB_INT0_CONFIG :			\
+	is_uv3_hub() ? UV3H_GR1_TLB_INT0_CONFIG :			\
+	/*is_uv4_hub*/ UV4H_GR1_TLB_INT0_CONFIG)
 
 #define UVH_GR1_TLB_INT0_CONFIG_VECTOR_SHFT		0
 #define UVH_GR1_TLB_INT0_CONFIG_DM_SHFT			8
@@ -941,6 +1274,7 @@ union uvh_gr0_tlb_mmr_read_data_lo_u {
 #define UVH_GR1_TLB_INT0_CONFIG_M_MASK			0x0000000000010000UL
 #define UVH_GR1_TLB_INT0_CONFIG_APIC_ID_MASK		0xffffffff00000000UL
 
+
 union uvh_gr1_tlb_int0_config_u {
 	unsigned long	v;
 	struct uvh_gr1_tlb_int0_config_s {
@@ -960,7 +1294,15 @@ union uvh_gr1_tlb_int0_config_u {
 /* ========================================================================= */
 /*                         UVH_GR1_TLB_INT1_CONFIG                           */
 /* ========================================================================= */
-#define UVH_GR1_TLB_INT1_CONFIG 0x61f40UL
+#define UV1H_GR1_TLB_INT1_CONFIG 0x61f40UL
+#define UV2H_GR1_TLB_INT1_CONFIG 0x61f40UL
+#define UV3H_GR1_TLB_INT1_CONFIG 0x61f40UL
+#define UV4H_GR1_TLB_INT1_CONFIG 0x62140UL
+#define UVH_GR1_TLB_INT1_CONFIG (					\
+	is_uv1_hub() ? UV1H_GR1_TLB_INT1_CONFIG :			\
+	is_uv2_hub() ? UV2H_GR1_TLB_INT1_CONFIG :			\
+	is_uv3_hub() ? UV3H_GR1_TLB_INT1_CONFIG :			\
+	/*is_uv4_hub*/ UV4H_GR1_TLB_INT1_CONFIG)
 
 #define UVH_GR1_TLB_INT1_CONFIG_VECTOR_SHFT		0
 #define UVH_GR1_TLB_INT1_CONFIG_DM_SHFT			8
@@ -979,6 +1321,7 @@ union uvh_gr1_tlb_int0_config_u {
 #define UVH_GR1_TLB_INT1_CONFIG_M_MASK			0x0000000000010000UL
 #define UVH_GR1_TLB_INT1_CONFIG_APIC_ID_MASK		0xffffffff00000000UL
 
+
 union uvh_gr1_tlb_int1_config_u {
 	unsigned long	v;
 	struct uvh_gr1_tlb_int1_config_s {
@@ -1001,19 +1344,18 @@ union uvh_gr1_tlb_int1_config_u {
 #define UV1H_GR1_TLB_MMR_CONTROL 0x801080UL
 #define UV2H_GR1_TLB_MMR_CONTROL 0x1001080UL
 #define UV3H_GR1_TLB_MMR_CONTROL 0x1001080UL
-#define UVH_GR1_TLB_MMR_CONTROL						\
-		(is_uv1_hub() ? UV1H_GR1_TLB_MMR_CONTROL :		\
-		(is_uv2_hub() ? UV2H_GR1_TLB_MMR_CONTROL :		\
-				UV3H_GR1_TLB_MMR_CONTROL))
+#define UV4H_GR1_TLB_MMR_CONTROL 0x701080UL
+#define UVH_GR1_TLB_MMR_CONTROL (					\
+	is_uv1_hub() ? UV1H_GR1_TLB_MMR_CONTROL :			\
+	is_uv2_hub() ? UV2H_GR1_TLB_MMR_CONTROL :			\
+	is_uv3_hub() ? UV3H_GR1_TLB_MMR_CONTROL :			\
+	/*is_uv4_hub*/ UV4H_GR1_TLB_MMR_CONTROL)
 
 #define UVH_GR1_TLB_MMR_CONTROL_INDEX_SHFT		0
-#define UVH_GR1_TLB_MMR_CONTROL_MEM_SEL_SHFT		12
 #define UVH_GR1_TLB_MMR_CONTROL_AUTO_VALID_EN_SHFT	16
 #define UVH_GR1_TLB_MMR_CONTROL_MMR_HASH_INDEX_EN_SHFT	20
 #define UVH_GR1_TLB_MMR_CONTROL_MMR_WRITE_SHFT		30
 #define UVH_GR1_TLB_MMR_CONTROL_MMR_READ_SHFT		31
-#define UVH_GR1_TLB_MMR_CONTROL_INDEX_MASK		0x0000000000000fffUL
-#define UVH_GR1_TLB_MMR_CONTROL_MEM_SEL_MASK		0x0000000000003000UL
 #define UVH_GR1_TLB_MMR_CONTROL_AUTO_VALID_EN_MASK	0x0000000000010000UL
 #define UVH_GR1_TLB_MMR_CONTROL_MMR_HASH_INDEX_EN_MASK	0x0000000000100000UL
 #define UVH_GR1_TLB_MMR_CONTROL_MMR_WRITE_MASK		0x0000000040000000UL
@@ -1043,14 +1385,11 @@ union uvh_gr1_tlb_int1_config_u {
 #define UV1H_GR1_TLB_MMR_CONTROL_MMR_INJ_TLBLRUV_MASK	0x1000000000000000UL
 
 #define UVXH_GR1_TLB_MMR_CONTROL_INDEX_SHFT		0
-#define UVXH_GR1_TLB_MMR_CONTROL_MEM_SEL_SHFT		12
 #define UVXH_GR1_TLB_MMR_CONTROL_AUTO_VALID_EN_SHFT	16
 #define UVXH_GR1_TLB_MMR_CONTROL_MMR_HASH_INDEX_EN_SHFT	20
 #define UVXH_GR1_TLB_MMR_CONTROL_MMR_WRITE_SHFT		30
 #define UVXH_GR1_TLB_MMR_CONTROL_MMR_READ_SHFT		31
 #define UVXH_GR1_TLB_MMR_CONTROL_MMR_OP_DONE_SHFT	32
-#define UVXH_GR1_TLB_MMR_CONTROL_INDEX_MASK		0x0000000000000fffUL
-#define UVXH_GR1_TLB_MMR_CONTROL_MEM_SEL_MASK		0x0000000000003000UL
 #define UVXH_GR1_TLB_MMR_CONTROL_AUTO_VALID_EN_MASK	0x0000000000010000UL
 #define UVXH_GR1_TLB_MMR_CONTROL_MMR_HASH_INDEX_EN_MASK	0x0000000000100000UL
 #define UVXH_GR1_TLB_MMR_CONTROL_MMR_WRITE_MASK		0x0000000040000000UL
@@ -1093,12 +1432,30 @@ union uvh_gr1_tlb_int1_config_u {
 #define UV3H_GR1_TLB_MMR_CONTROL_MMR_READ_MASK		0x0000000080000000UL
 #define UV3H_GR1_TLB_MMR_CONTROL_MMR_OP_DONE_MASK	0x0000000100000000UL
 
+#define UV4H_GR1_TLB_MMR_CONTROL_INDEX_SHFT		0
+#define UV4H_GR1_TLB_MMR_CONTROL_MEM_SEL_SHFT		13
+#define UV4H_GR1_TLB_MMR_CONTROL_AUTO_VALID_EN_SHFT	16
+#define UV4H_GR1_TLB_MMR_CONTROL_MMR_HASH_INDEX_EN_SHFT	20
+#define UV4H_GR1_TLB_MMR_CONTROL_ECC_SEL_SHFT		21
+#define UV4H_GR1_TLB_MMR_CONTROL_MMR_WRITE_SHFT		30
+#define UV4H_GR1_TLB_MMR_CONTROL_MMR_READ_SHFT		31
+#define UV4H_GR1_TLB_MMR_CONTROL_MMR_OP_DONE_SHFT	32
+#define UV4H_GR1_TLB_MMR_CONTROL_PAGE_SIZE_SHFT		59
+#define UV4H_GR1_TLB_MMR_CONTROL_INDEX_MASK		0x0000000000001fffUL
+#define UV4H_GR1_TLB_MMR_CONTROL_MEM_SEL_MASK		0x0000000000006000UL
+#define UV4H_GR1_TLB_MMR_CONTROL_AUTO_VALID_EN_MASK	0x0000000000010000UL
+#define UV4H_GR1_TLB_MMR_CONTROL_MMR_HASH_INDEX_EN_MASK	0x0000000000100000UL
+#define UV4H_GR1_TLB_MMR_CONTROL_ECC_SEL_MASK		0x0000000000200000UL
+#define UV4H_GR1_TLB_MMR_CONTROL_MMR_WRITE_MASK		0x0000000040000000UL
+#define UV4H_GR1_TLB_MMR_CONTROL_MMR_READ_MASK		0x0000000080000000UL
+#define UV4H_GR1_TLB_MMR_CONTROL_MMR_OP_DONE_MASK	0x0000000100000000UL
+#define UV4H_GR1_TLB_MMR_CONTROL_PAGE_SIZE_MASK		0xf800000000000000UL
+
+
 union uvh_gr1_tlb_mmr_control_u {
 	unsigned long	v;
 	struct uvh_gr1_tlb_mmr_control_s {
-		unsigned long	index:12;			/* RW */
-		unsigned long	mem_sel:2;			/* RW */
-		unsigned long	rsvd_14_15:2;
+		unsigned long	rsvd_0_15:16;
 		unsigned long	auto_valid_en:1;		/* RW */
 		unsigned long	rsvd_17_19:3;
 		unsigned long	mmr_hash_index_en:1;		/* RW */
@@ -1132,9 +1489,7 @@ union uvh_gr1_tlb_mmr_control_u {
 		unsigned long	rsvd_61_63:3;
 	} s1;
 	struct uvxh_gr1_tlb_mmr_control_s {
-		unsigned long	index:12;			/* RW */
-		unsigned long	mem_sel:2;			/* RW */
-		unsigned long	rsvd_14_15:2;
+		unsigned long	rsvd_0_15:16;
 		unsigned long	auto_valid_en:1;		/* RW */
 		unsigned long	rsvd_17_19:3;
 		unsigned long	mmr_hash_index_en:1;		/* RW */
@@ -1145,8 +1500,7 @@ union uvh_gr1_tlb_mmr_control_u {
 		unsigned long	rsvd_33_47:15;
 		unsigned long	rsvd_48:1;
 		unsigned long	rsvd_49_51:3;
-		unsigned long	rsvd_52:1;
-		unsigned long	rsvd_53_63:11;
+		unsigned long	rsvd_52_63:12;
 	} sx;
 	struct uv2h_gr1_tlb_mmr_control_s {
 		unsigned long	index:12;			/* RW */
@@ -1183,6 +1537,24 @@ union uvh_gr1_tlb_mmr_control_u {
 		unsigned long	undef_52:1;			/* Undefined */
 		unsigned long	rsvd_53_63:11;
 	} s3;
+	struct uv4h_gr1_tlb_mmr_control_s {
+		unsigned long	index:13;			/* RW */
+		unsigned long	mem_sel:2;			/* RW */
+		unsigned long	rsvd_15:1;
+		unsigned long	auto_valid_en:1;		/* RW */
+		unsigned long	rsvd_17_19:3;
+		unsigned long	mmr_hash_index_en:1;		/* RW */
+		unsigned long	ecc_sel:1;			/* RW */
+		unsigned long	rsvd_22_29:8;
+		unsigned long	mmr_write:1;			/* WP */
+		unsigned long	mmr_read:1;			/* WP */
+		unsigned long	mmr_op_done:1;			/* RW */
+		unsigned long	rsvd_33_47:15;
+		unsigned long	undef_48:1;			/* Undefined */
+		unsigned long	rsvd_49_51:3;
+		unsigned long	rsvd_52_58:7;
+		unsigned long	page_size:5;			/* RW */
+	} s4;
 };
 
 /* ========================================================================= */
@@ -1191,19 +1563,14 @@ union uvh_gr1_tlb_mmr_control_u {
 #define UV1H_GR1_TLB_MMR_READ_DATA_HI 0x8010a0UL
 #define UV2H_GR1_TLB_MMR_READ_DATA_HI 0x10010a0UL
 #define UV3H_GR1_TLB_MMR_READ_DATA_HI 0x10010a0UL
-#define UVH_GR1_TLB_MMR_READ_DATA_HI					\
-		(is_uv1_hub() ? UV1H_GR1_TLB_MMR_READ_DATA_HI :		\
-		(is_uv2_hub() ? UV2H_GR1_TLB_MMR_READ_DATA_HI :		\
-				UV3H_GR1_TLB_MMR_READ_DATA_HI))
+#define UV4H_GR1_TLB_MMR_READ_DATA_HI 0x7010a0UL
+#define UVH_GR1_TLB_MMR_READ_DATA_HI (					\
+	is_uv1_hub() ? UV1H_GR1_TLB_MMR_READ_DATA_HI :			\
+	is_uv2_hub() ? UV2H_GR1_TLB_MMR_READ_DATA_HI :			\
+	is_uv3_hub() ? UV3H_GR1_TLB_MMR_READ_DATA_HI :			\
+	/*is_uv4_hub*/ UV4H_GR1_TLB_MMR_READ_DATA_HI)
 
 #define UVH_GR1_TLB_MMR_READ_DATA_HI_PFN_SHFT		0
-#define UVH_GR1_TLB_MMR_READ_DATA_HI_GAA_SHFT		41
-#define UVH_GR1_TLB_MMR_READ_DATA_HI_DIRTY_SHFT		43
-#define UVH_GR1_TLB_MMR_READ_DATA_HI_LARGER_SHFT	44
-#define UVH_GR1_TLB_MMR_READ_DATA_HI_PFN_MASK		0x000001ffffffffffUL
-#define UVH_GR1_TLB_MMR_READ_DATA_HI_GAA_MASK		0x0000060000000000UL
-#define UVH_GR1_TLB_MMR_READ_DATA_HI_DIRTY_MASK		0x0000080000000000UL
-#define UVH_GR1_TLB_MMR_READ_DATA_HI_LARGER_MASK	0x0000100000000000UL
 
 #define UV1H_GR1_TLB_MMR_READ_DATA_HI_PFN_SHFT		0
 #define UV1H_GR1_TLB_MMR_READ_DATA_HI_GAA_SHFT		41
@@ -1215,13 +1582,6 @@ union uvh_gr1_tlb_mmr_control_u {
 #define UV1H_GR1_TLB_MMR_READ_DATA_HI_LARGER_MASK	0x0000100000000000UL
 
 #define UVXH_GR1_TLB_MMR_READ_DATA_HI_PFN_SHFT		0
-#define UVXH_GR1_TLB_MMR_READ_DATA_HI_GAA_SHFT		41
-#define UVXH_GR1_TLB_MMR_READ_DATA_HI_DIRTY_SHFT	43
-#define UVXH_GR1_TLB_MMR_READ_DATA_HI_LARGER_SHFT	44
-#define UVXH_GR1_TLB_MMR_READ_DATA_HI_PFN_MASK		0x000001ffffffffffUL
-#define UVXH_GR1_TLB_MMR_READ_DATA_HI_GAA_MASK		0x0000060000000000UL
-#define UVXH_GR1_TLB_MMR_READ_DATA_HI_DIRTY_MASK	0x0000080000000000UL
-#define UVXH_GR1_TLB_MMR_READ_DATA_HI_LARGER_MASK	0x0000100000000000UL
 
 #define UV2H_GR1_TLB_MMR_READ_DATA_HI_PFN_SHFT		0
 #define UV2H_GR1_TLB_MMR_READ_DATA_HI_GAA_SHFT		41
@@ -1245,15 +1605,24 @@ union uvh_gr1_tlb_mmr_control_u {
 #define UV3H_GR1_TLB_MMR_READ_DATA_HI_AA_EXT_MASK	0x0000200000000000UL
 #define UV3H_GR1_TLB_MMR_READ_DATA_HI_WAY_ECC_MASK	0xff80000000000000UL
 
+#define UV4H_GR1_TLB_MMR_READ_DATA_HI_PFN_SHFT		0
+#define UV4H_GR1_TLB_MMR_READ_DATA_HI_PNID_SHFT		34
+#define UV4H_GR1_TLB_MMR_READ_DATA_HI_GAA_SHFT		49
+#define UV4H_GR1_TLB_MMR_READ_DATA_HI_DIRTY_SHFT	51
+#define UV4H_GR1_TLB_MMR_READ_DATA_HI_LARGER_SHFT	52
+#define UV4H_GR1_TLB_MMR_READ_DATA_HI_AA_EXT_SHFT	53
+#define UV4H_GR1_TLB_MMR_READ_DATA_HI_WAY_ECC_SHFT	55
+#define UV4H_GR1_TLB_MMR_READ_DATA_HI_PFN_MASK		0x00000003ffffffffUL
+#define UV4H_GR1_TLB_MMR_READ_DATA_HI_PNID_MASK		0x0001fffc00000000UL
+#define UV4H_GR1_TLB_MMR_READ_DATA_HI_GAA_MASK		0x0006000000000000UL
+#define UV4H_GR1_TLB_MMR_READ_DATA_HI_DIRTY_MASK	0x0008000000000000UL
+#define UV4H_GR1_TLB_MMR_READ_DATA_HI_LARGER_MASK	0x0010000000000000UL
+#define UV4H_GR1_TLB_MMR_READ_DATA_HI_AA_EXT_MASK	0x0020000000000000UL
+#define UV4H_GR1_TLB_MMR_READ_DATA_HI_WAY_ECC_MASK	0xff80000000000000UL
+
+
 union uvh_gr1_tlb_mmr_read_data_hi_u {
 	unsigned long	v;
-	struct uvh_gr1_tlb_mmr_read_data_hi_s {
-		unsigned long	pfn:41;				/* RO */
-		unsigned long	gaa:2;				/* RO */
-		unsigned long	dirty:1;			/* RO */
-		unsigned long	larger:1;			/* RO */
-		unsigned long	rsvd_45_63:19;
-	} s;
 	struct uv1h_gr1_tlb_mmr_read_data_hi_s {
 		unsigned long	pfn:41;				/* RO */
 		unsigned long	gaa:2;				/* RO */
@@ -1261,13 +1630,6 @@ union uvh_gr1_tlb_mmr_read_data_hi_u {
 		unsigned long	larger:1;			/* RO */
 		unsigned long	rsvd_45_63:19;
 	} s1;
-	struct uvxh_gr1_tlb_mmr_read_data_hi_s {
-		unsigned long	pfn:41;				/* RO */
-		unsigned long	gaa:2;				/* RO */
-		unsigned long	dirty:1;			/* RO */
-		unsigned long	larger:1;			/* RO */
-		unsigned long	rsvd_45_63:19;
-	} sx;
 	struct uv2h_gr1_tlb_mmr_read_data_hi_s {
 		unsigned long	pfn:41;				/* RO */
 		unsigned long	gaa:2;				/* RO */
@@ -1284,6 +1646,16 @@ union uvh_gr1_tlb_mmr_read_data_hi_u {
 		unsigned long	undef_46_54:9;			/* Undefined */
 		unsigned long	way_ecc:9;			/* RO */
 	} s3;
+	struct uv4h_gr1_tlb_mmr_read_data_hi_s {
+		unsigned long	pfn:34;				/* RO */
+		unsigned long	pnid:15;			/* RO */
+		unsigned long	gaa:2;				/* RO */
+		unsigned long	dirty:1;			/* RO */
+		unsigned long	larger:1;			/* RO */
+		unsigned long	aa_ext:1;			/* RO */
+		unsigned long	undef_54:1;			/* Undefined */
+		unsigned long	way_ecc:9;			/* RO */
+	} s4;
 };
 
 /* ========================================================================= */
@@ -1292,10 +1664,12 @@ union uvh_gr1_tlb_mmr_read_data_hi_u {
 #define UV1H_GR1_TLB_MMR_READ_DATA_LO 0x8010a8UL
 #define UV2H_GR1_TLB_MMR_READ_DATA_LO 0x10010a8UL
 #define UV3H_GR1_TLB_MMR_READ_DATA_LO 0x10010a8UL
-#define UVH_GR1_TLB_MMR_READ_DATA_LO					\
-		(is_uv1_hub() ? UV1H_GR1_TLB_MMR_READ_DATA_LO :		\
-		(is_uv2_hub() ? UV2H_GR1_TLB_MMR_READ_DATA_LO :		\
-				UV3H_GR1_TLB_MMR_READ_DATA_LO))
+#define UV4H_GR1_TLB_MMR_READ_DATA_LO 0x7010a8UL
+#define UVH_GR1_TLB_MMR_READ_DATA_LO (					\
+	is_uv1_hub() ? UV1H_GR1_TLB_MMR_READ_DATA_LO :			\
+	is_uv2_hub() ? UV2H_GR1_TLB_MMR_READ_DATA_LO :			\
+	is_uv3_hub() ? UV3H_GR1_TLB_MMR_READ_DATA_LO :			\
+	/*is_uv4_hub*/ UV4H_GR1_TLB_MMR_READ_DATA_LO)
 
 #define UVH_GR1_TLB_MMR_READ_DATA_LO_VPN_SHFT		0
 #define UVH_GR1_TLB_MMR_READ_DATA_LO_ASID_SHFT		39
@@ -1332,6 +1706,14 @@ union uvh_gr1_tlb_mmr_read_data_hi_u {
 #define UV3H_GR1_TLB_MMR_READ_DATA_LO_ASID_MASK		0x7fffff8000000000UL
 #define UV3H_GR1_TLB_MMR_READ_DATA_LO_VALID_MASK	0x8000000000000000UL
 
+#define UV4H_GR1_TLB_MMR_READ_DATA_LO_VPN_SHFT		0
+#define UV4H_GR1_TLB_MMR_READ_DATA_LO_ASID_SHFT		39
+#define UV4H_GR1_TLB_MMR_READ_DATA_LO_VALID_SHFT	63
+#define UV4H_GR1_TLB_MMR_READ_DATA_LO_VPN_MASK		0x0000007fffffffffUL
+#define UV4H_GR1_TLB_MMR_READ_DATA_LO_ASID_MASK		0x7fffff8000000000UL
+#define UV4H_GR1_TLB_MMR_READ_DATA_LO_VALID_MASK	0x8000000000000000UL
+
+
 union uvh_gr1_tlb_mmr_read_data_lo_u {
 	unsigned long	v;
 	struct uvh_gr1_tlb_mmr_read_data_lo_s {
@@ -1359,6 +1741,11 @@ union uvh_gr1_tlb_mmr_read_data_lo_u {
 		unsigned long	asid:24;			/* RO */
 		unsigned long	valid:1;			/* RO */
 	} s3;
+	struct uv4h_gr1_tlb_mmr_read_data_lo_s {
+		unsigned long	vpn:39;				/* RO */
+		unsigned long	asid:24;			/* RO */
+		unsigned long	valid:1;			/* RO */
+	} s4;
 };
 
 /* ========================================================================= */
@@ -1369,6 +1756,7 @@ union uvh_gr1_tlb_mmr_read_data_lo_u {
 #define UVH_INT_CMPB_REAL_TIME_CMPB_SHFT		0
 #define UVH_INT_CMPB_REAL_TIME_CMPB_MASK		0x00ffffffffffffffUL
 
+
 union uvh_int_cmpb_u {
 	unsigned long	v;
 	struct uvh_int_cmpb_s {
@@ -1382,12 +1770,14 @@ union uvh_int_cmpb_u {
 /* ========================================================================= */
 #define UVH_INT_CMPC 0x22100UL
 
+
 #define UV1H_INT_CMPC_REAL_TIME_CMPC_SHFT		0
 #define UV1H_INT_CMPC_REAL_TIME_CMPC_MASK		0x00ffffffffffffffUL
 
 #define UVXH_INT_CMPC_REAL_TIME_CMP_2_SHFT		0
 #define UVXH_INT_CMPC_REAL_TIME_CMP_2_MASK		0x00ffffffffffffffUL
 
+
 union uvh_int_cmpc_u {
 	unsigned long	v;
 	struct uvh_int_cmpc_s {
@@ -1401,12 +1791,14 @@ union uvh_int_cmpc_u {
 /* ========================================================================= */
 #define UVH_INT_CMPD 0x22180UL
 
+
 #define UV1H_INT_CMPD_REAL_TIME_CMPD_SHFT		0
 #define UV1H_INT_CMPD_REAL_TIME_CMPD_MASK		0x00ffffffffffffffUL
 
 #define UVXH_INT_CMPD_REAL_TIME_CMP_3_SHFT		0
 #define UVXH_INT_CMPD_REAL_TIME_CMP_3_MASK		0x00ffffffffffffffUL
 
+
 union uvh_int_cmpd_u {
 	unsigned long	v;
 	struct uvh_int_cmpd_s {
@@ -1419,7 +1811,16 @@ union uvh_int_cmpd_u {
 /*                               UVH_IPI_INT                                 */
 /* ========================================================================= */
 #define UVH_IPI_INT 0x60500UL
-#define UVH_IPI_INT_32 0x348
+
+#define UV1H_IPI_INT_32 0x348
+#define UV2H_IPI_INT_32 0x348
+#define UV3H_IPI_INT_32 0x348
+#define UV4H_IPI_INT_32 0x268
+#define UVH_IPI_INT_32 (						\
+	is_uv1_hub() ? UV1H_IPI_INT_32 :				\
+	is_uv2_hub() ? UV2H_IPI_INT_32 :				\
+	is_uv3_hub() ? UV3H_IPI_INT_32 :				\
+	/*is_uv4_hub*/ UV4H_IPI_INT_32)
 
 #define UVH_IPI_INT_VECTOR_SHFT				0
 #define UVH_IPI_INT_DELIVERY_MODE_SHFT			8
@@ -1432,6 +1833,7 @@ union uvh_int_cmpd_u {
 #define UVH_IPI_INT_APIC_ID_MASK			0x0000ffffffff0000UL
 #define UVH_IPI_INT_SEND_MASK				0x8000000000000000UL
 
+
 union uvh_ipi_int_u {
 	unsigned long	v;
 	struct uvh_ipi_int_s {
@@ -1448,103 +1850,269 @@ union uvh_ipi_int_u {
 /* ========================================================================= */
 /*                   UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST                     */
 /* ========================================================================= */
-#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST 0x320050UL
+#define UV1H_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST 0x320050UL
+#define UV2H_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST 0x320050UL
+#define UV3H_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST 0x320050UL
+#define UV4H_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST uv_undefined("UV4H_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST")
+#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST (				\
+	is_uv1_hub() ? UV1H_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST :		\
+	is_uv2_hub() ? UV2H_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST :		\
+	is_uv3_hub() ? UV3H_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST :		\
+	/*is_uv4_hub*/ UV4H_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST)
 #define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_32 0x9c0
 
-#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_ADDRESS_SHFT 4
-#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_NODE_ID_SHFT 49
-#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_ADDRESS_MASK 0x000007fffffffff0UL
-#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_NODE_ID_MASK 0x7ffe000000000000UL
+
+#define UV1H_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_ADDRESS_SHFT 4
+#define UV1H_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_NODE_ID_SHFT 49
+#define UV1H_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_ADDRESS_MASK 0x000007fffffffff0UL
+#define UV1H_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_NODE_ID_MASK 0x7ffe000000000000UL
+
+
+#define UV2H_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_ADDRESS_SHFT 4
+#define UV2H_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_NODE_ID_SHFT 49
+#define UV2H_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_ADDRESS_MASK 0x000007fffffffff0UL
+#define UV2H_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_NODE_ID_MASK 0x7ffe000000000000UL
+
+#define UV3H_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_ADDRESS_SHFT 4
+#define UV3H_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_NODE_ID_SHFT 49
+#define UV3H_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_ADDRESS_MASK 0x000007fffffffff0UL
+#define UV3H_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST_NODE_ID_MASK 0x7ffe000000000000UL
+
 
 union uvh_lb_bau_intd_payload_queue_first_u {
 	unsigned long	v;
-	struct uvh_lb_bau_intd_payload_queue_first_s {
+	struct uv1h_lb_bau_intd_payload_queue_first_s {
 		unsigned long	rsvd_0_3:4;
 		unsigned long	address:39;			/* RW */
 		unsigned long	rsvd_43_48:6;
 		unsigned long	node_id:14;			/* RW */
 		unsigned long	rsvd_63:1;
-	} s;
+	} s1;
+	struct uv2h_lb_bau_intd_payload_queue_first_s {
+		unsigned long	rsvd_0_3:4;
+		unsigned long	address:39;			/* RW */
+		unsigned long	rsvd_43_48:6;
+		unsigned long	node_id:14;			/* RW */
+		unsigned long	rsvd_63:1;
+	} s2;
+	struct uv3h_lb_bau_intd_payload_queue_first_s {
+		unsigned long	rsvd_0_3:4;
+		unsigned long	address:39;			/* RW */
+		unsigned long	rsvd_43_48:6;
+		unsigned long	node_id:14;			/* RW */
+		unsigned long	rsvd_63:1;
+	} s3;
 };
 
 /* ========================================================================= */
 /*                    UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST                     */
 /* ========================================================================= */
-#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST 0x320060UL
+#define UV1H_LB_BAU_INTD_PAYLOAD_QUEUE_LAST 0x320060UL
+#define UV2H_LB_BAU_INTD_PAYLOAD_QUEUE_LAST 0x320060UL
+#define UV3H_LB_BAU_INTD_PAYLOAD_QUEUE_LAST 0x320060UL
+#define UV4H_LB_BAU_INTD_PAYLOAD_QUEUE_LAST uv_undefined("UV4H_LB_BAU_INTD_PAYLOAD_QUEUE_LAST")
+#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST (				\
+	is_uv1_hub() ? UV1H_LB_BAU_INTD_PAYLOAD_QUEUE_LAST :		\
+	is_uv2_hub() ? UV2H_LB_BAU_INTD_PAYLOAD_QUEUE_LAST :		\
+	is_uv3_hub() ? UV3H_LB_BAU_INTD_PAYLOAD_QUEUE_LAST :		\
+	/*is_uv4_hub*/ UV4H_LB_BAU_INTD_PAYLOAD_QUEUE_LAST)
 #define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST_32 0x9c8
 
-#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST_ADDRESS_SHFT	4
-#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST_ADDRESS_MASK	0x000007fffffffff0UL
+
+#define UV1H_LB_BAU_INTD_PAYLOAD_QUEUE_LAST_ADDRESS_SHFT 4
+#define UV1H_LB_BAU_INTD_PAYLOAD_QUEUE_LAST_ADDRESS_MASK 0x000007fffffffff0UL
+
+
+#define UV2H_LB_BAU_INTD_PAYLOAD_QUEUE_LAST_ADDRESS_SHFT 4
+#define UV2H_LB_BAU_INTD_PAYLOAD_QUEUE_LAST_ADDRESS_MASK 0x000007fffffffff0UL
+
+#define UV3H_LB_BAU_INTD_PAYLOAD_QUEUE_LAST_ADDRESS_SHFT 4
+#define UV3H_LB_BAU_INTD_PAYLOAD_QUEUE_LAST_ADDRESS_MASK 0x000007fffffffff0UL
+
 
 union uvh_lb_bau_intd_payload_queue_last_u {
 	unsigned long	v;
-	struct uvh_lb_bau_intd_payload_queue_last_s {
+	struct uv1h_lb_bau_intd_payload_queue_last_s {
 		unsigned long	rsvd_0_3:4;
 		unsigned long	address:39;			/* RW */
 		unsigned long	rsvd_43_63:21;
-	} s;
+	} s1;
+	struct uv2h_lb_bau_intd_payload_queue_last_s {
+		unsigned long	rsvd_0_3:4;
+		unsigned long	address:39;			/* RW */
+		unsigned long	rsvd_43_63:21;
+	} s2;
+	struct uv3h_lb_bau_intd_payload_queue_last_s {
+		unsigned long	rsvd_0_3:4;
+		unsigned long	address:39;			/* RW */
+		unsigned long	rsvd_43_63:21;
+	} s3;
 };
 
 /* ========================================================================= */
 /*                    UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL                     */
 /* ========================================================================= */
-#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL 0x320070UL
+#define UV1H_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL 0x320070UL
+#define UV2H_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL 0x320070UL
+#define UV3H_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL 0x320070UL
+#define UV4H_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL uv_undefined("UV4H_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL")
+#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL (				\
+	is_uv1_hub() ? UV1H_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL :		\
+	is_uv2_hub() ? UV2H_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL :		\
+	is_uv3_hub() ? UV3H_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL :		\
+	/*is_uv4_hub*/ UV4H_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL)
 #define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL_32 0x9d0
 
-#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL_ADDRESS_SHFT	4
-#define UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL_ADDRESS_MASK	0x000007fffffffff0UL
+
+#define UV1H_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL_ADDRESS_SHFT 4
+#define UV1H_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL_ADDRESS_MASK 0x000007fffffffff0UL
+
+
+#define UV2H_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL_ADDRESS_SHFT 4
+#define UV2H_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL_ADDRESS_MASK 0x000007fffffffff0UL
+
+#define UV3H_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL_ADDRESS_SHFT 4
+#define UV3H_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL_ADDRESS_MASK 0x000007fffffffff0UL
+
 
 union uvh_lb_bau_intd_payload_queue_tail_u {
 	unsigned long	v;
-	struct uvh_lb_bau_intd_payload_queue_tail_s {
+	struct uv1h_lb_bau_intd_payload_queue_tail_s {
 		unsigned long	rsvd_0_3:4;
 		unsigned long	address:39;			/* RW */
 		unsigned long	rsvd_43_63:21;
-	} s;
+	} s1;
+	struct uv2h_lb_bau_intd_payload_queue_tail_s {
+		unsigned long	rsvd_0_3:4;
+		unsigned long	address:39;			/* RW */
+		unsigned long	rsvd_43_63:21;
+	} s2;
+	struct uv3h_lb_bau_intd_payload_queue_tail_s {
+		unsigned long	rsvd_0_3:4;
+		unsigned long	address:39;			/* RW */
+		unsigned long	rsvd_43_63:21;
+	} s3;
 };
 
 /* ========================================================================= */
 /*                   UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE                    */
 /* ========================================================================= */
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE 0x320080UL
+#define UV1H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE 0x320080UL
+#define UV2H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE 0x320080UL
+#define UV3H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE 0x320080UL
+#define UV4H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE uv_undefined("UV4H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE")
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE (				\
+	is_uv1_hub() ? UV1H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE :		\
+	is_uv2_hub() ? UV2H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE :		\
+	is_uv3_hub() ? UV3H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE :		\
+	/*is_uv4_hub*/ UV4H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE)
 #define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_32 0xa68
 
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_0_SHFT 0
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_1_SHFT 1
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_2_SHFT 2
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_3_SHFT 3
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_4_SHFT 4
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_5_SHFT 5
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_6_SHFT 6
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_7_SHFT 7
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_0_SHFT 8
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_1_SHFT 9
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_2_SHFT 10
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_3_SHFT 11
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_4_SHFT 12
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_5_SHFT 13
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_6_SHFT 14
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_7_SHFT 15
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_0_MASK 0x0000000000000001UL
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_1_MASK 0x0000000000000002UL
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_2_MASK 0x0000000000000004UL
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_3_MASK 0x0000000000000008UL
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_4_MASK 0x0000000000000010UL
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_5_MASK 0x0000000000000020UL
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_6_MASK 0x0000000000000040UL
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_7_MASK 0x0000000000000080UL
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_0_MASK 0x0000000000000100UL
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_1_MASK 0x0000000000000200UL
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_2_MASK 0x0000000000000400UL
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_3_MASK 0x0000000000000800UL
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_4_MASK 0x0000000000001000UL
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_5_MASK 0x0000000000002000UL
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_6_MASK 0x0000000000004000UL
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_7_MASK 0x0000000000008000UL
+
+#define UV1H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_0_SHFT 0
+#define UV1H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_1_SHFT 1
+#define UV1H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_2_SHFT 2
+#define UV1H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_3_SHFT 3
+#define UV1H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_4_SHFT 4
+#define UV1H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_5_SHFT 5
+#define UV1H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_6_SHFT 6
+#define UV1H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_7_SHFT 7
+#define UV1H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_0_SHFT 8
+#define UV1H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_1_SHFT 9
+#define UV1H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_2_SHFT 10
+#define UV1H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_3_SHFT 11
+#define UV1H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_4_SHFT 12
+#define UV1H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_5_SHFT 13
+#define UV1H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_6_SHFT 14
+#define UV1H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_7_SHFT 15
+#define UV1H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_0_MASK 0x0000000000000001UL
+#define UV1H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_1_MASK 0x0000000000000002UL
+#define UV1H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_2_MASK 0x0000000000000004UL
+#define UV1H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_3_MASK 0x0000000000000008UL
+#define UV1H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_4_MASK 0x0000000000000010UL
+#define UV1H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_5_MASK 0x0000000000000020UL
+#define UV1H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_6_MASK 0x0000000000000040UL
+#define UV1H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_7_MASK 0x0000000000000080UL
+#define UV1H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_0_MASK 0x0000000000000100UL
+#define UV1H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_1_MASK 0x0000000000000200UL
+#define UV1H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_2_MASK 0x0000000000000400UL
+#define UV1H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_3_MASK 0x0000000000000800UL
+#define UV1H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_4_MASK 0x0000000000001000UL
+#define UV1H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_5_MASK 0x0000000000002000UL
+#define UV1H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_6_MASK 0x0000000000004000UL
+#define UV1H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_7_MASK 0x0000000000008000UL
+
+
+#define UV2H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_0_SHFT 0
+#define UV2H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_1_SHFT 1
+#define UV2H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_2_SHFT 2
+#define UV2H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_3_SHFT 3
+#define UV2H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_4_SHFT 4
+#define UV2H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_5_SHFT 5
+#define UV2H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_6_SHFT 6
+#define UV2H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_7_SHFT 7
+#define UV2H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_0_SHFT 8
+#define UV2H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_1_SHFT 9
+#define UV2H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_2_SHFT 10
+#define UV2H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_3_SHFT 11
+#define UV2H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_4_SHFT 12
+#define UV2H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_5_SHFT 13
+#define UV2H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_6_SHFT 14
+#define UV2H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_7_SHFT 15
+#define UV2H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_0_MASK 0x0000000000000001UL
+#define UV2H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_1_MASK 0x0000000000000002UL
+#define UV2H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_2_MASK 0x0000000000000004UL
+#define UV2H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_3_MASK 0x0000000000000008UL
+#define UV2H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_4_MASK 0x0000000000000010UL
+#define UV2H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_5_MASK 0x0000000000000020UL
+#define UV2H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_6_MASK 0x0000000000000040UL
+#define UV2H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_7_MASK 0x0000000000000080UL
+#define UV2H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_0_MASK 0x0000000000000100UL
+#define UV2H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_1_MASK 0x0000000000000200UL
+#define UV2H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_2_MASK 0x0000000000000400UL
+#define UV2H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_3_MASK 0x0000000000000800UL
+#define UV2H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_4_MASK 0x0000000000001000UL
+#define UV2H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_5_MASK 0x0000000000002000UL
+#define UV2H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_6_MASK 0x0000000000004000UL
+#define UV2H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_7_MASK 0x0000000000008000UL
+
+#define UV3H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_0_SHFT 0
+#define UV3H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_1_SHFT 1
+#define UV3H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_2_SHFT 2
+#define UV3H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_3_SHFT 3
+#define UV3H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_4_SHFT 4
+#define UV3H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_5_SHFT 5
+#define UV3H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_6_SHFT 6
+#define UV3H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_7_SHFT 7
+#define UV3H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_0_SHFT 8
+#define UV3H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_1_SHFT 9
+#define UV3H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_2_SHFT 10
+#define UV3H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_3_SHFT 11
+#define UV3H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_4_SHFT 12
+#define UV3H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_5_SHFT 13
+#define UV3H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_6_SHFT 14
+#define UV3H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_7_SHFT 15
+#define UV3H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_0_MASK 0x0000000000000001UL
+#define UV3H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_1_MASK 0x0000000000000002UL
+#define UV3H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_2_MASK 0x0000000000000004UL
+#define UV3H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_3_MASK 0x0000000000000008UL
+#define UV3H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_4_MASK 0x0000000000000010UL
+#define UV3H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_5_MASK 0x0000000000000020UL
+#define UV3H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_6_MASK 0x0000000000000040UL
+#define UV3H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_PENDING_7_MASK 0x0000000000000080UL
+#define UV3H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_0_MASK 0x0000000000000100UL
+#define UV3H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_1_MASK 0x0000000000000200UL
+#define UV3H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_2_MASK 0x0000000000000400UL
+#define UV3H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_3_MASK 0x0000000000000800UL
+#define UV3H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_4_MASK 0x0000000000001000UL
+#define UV3H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_5_MASK 0x0000000000002000UL
+#define UV3H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_6_MASK 0x0000000000004000UL
+#define UV3H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_TIMEOUT_7_MASK 0x0000000000008000UL
+
 
 union uvh_lb_bau_intd_software_acknowledge_u {
 	unsigned long	v;
-	struct uvh_lb_bau_intd_software_acknowledge_s {
+	struct uv1h_lb_bau_intd_software_acknowledge_s {
 		unsigned long	pending_0:1;			/* RW, W1C */
 		unsigned long	pending_1:1;			/* RW, W1C */
 		unsigned long	pending_2:1;			/* RW, W1C */
@@ -1562,27 +2130,84 @@ union uvh_lb_bau_intd_software_acknowled
 		unsigned long	timeout_6:1;			/* RW, W1C */
 		unsigned long	timeout_7:1;			/* RW, W1C */
 		unsigned long	rsvd_16_63:48;
-	} s;
+	} s1;
+	struct uv2h_lb_bau_intd_software_acknowledge_s {
+		unsigned long	pending_0:1;			/* RW */
+		unsigned long	pending_1:1;			/* RW */
+		unsigned long	pending_2:1;			/* RW */
+		unsigned long	pending_3:1;			/* RW */
+		unsigned long	pending_4:1;			/* RW */
+		unsigned long	pending_5:1;			/* RW */
+		unsigned long	pending_6:1;			/* RW */
+		unsigned long	pending_7:1;			/* RW */
+		unsigned long	timeout_0:1;			/* RW */
+		unsigned long	timeout_1:1;			/* RW */
+		unsigned long	timeout_2:1;			/* RW */
+		unsigned long	timeout_3:1;			/* RW */
+		unsigned long	timeout_4:1;			/* RW */
+		unsigned long	timeout_5:1;			/* RW */
+		unsigned long	timeout_6:1;			/* RW */
+		unsigned long	timeout_7:1;			/* RW */
+		unsigned long	rsvd_16_63:48;
+	} s2;
+	struct uv3h_lb_bau_intd_software_acknowledge_s {
+		unsigned long	pending_0:1;			/* RW */
+		unsigned long	pending_1:1;			/* RW */
+		unsigned long	pending_2:1;			/* RW */
+		unsigned long	pending_3:1;			/* RW */
+		unsigned long	pending_4:1;			/* RW */
+		unsigned long	pending_5:1;			/* RW */
+		unsigned long	pending_6:1;			/* RW */
+		unsigned long	pending_7:1;			/* RW */
+		unsigned long	timeout_0:1;			/* RW */
+		unsigned long	timeout_1:1;			/* RW */
+		unsigned long	timeout_2:1;			/* RW */
+		unsigned long	timeout_3:1;			/* RW */
+		unsigned long	timeout_4:1;			/* RW */
+		unsigned long	timeout_5:1;			/* RW */
+		unsigned long	timeout_6:1;			/* RW */
+		unsigned long	timeout_7:1;			/* RW */
+		unsigned long	rsvd_16_63:48;
+	} s3;
 };
 
 /* ========================================================================= */
 /*                UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS                 */
 /* ========================================================================= */
-#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS 0x320088UL
+#define UV1H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS 0x320088UL
+#define UV2H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS 0x320088UL
+#define UV3H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS 0x320088UL
+#define UV4H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS uv_undefined("UV4H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS")
+#define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS (			\
+	is_uv1_hub() ? UV1H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS :	\
+	is_uv2_hub() ? UV2H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS :	\
+	is_uv3_hub() ? UV3H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS :	\
+	/*is_uv4_hub*/ UV4H_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS)
 #define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS_32 0xa70
 
 
 /* ========================================================================= */
 /*                         UVH_LB_BAU_MISC_CONTROL                           */
 /* ========================================================================= */
-#define UVH_LB_BAU_MISC_CONTROL 0x320170UL
 #define UV1H_LB_BAU_MISC_CONTROL 0x320170UL
 #define UV2H_LB_BAU_MISC_CONTROL 0x320170UL
 #define UV3H_LB_BAU_MISC_CONTROL 0x320170UL
-#define UVH_LB_BAU_MISC_CONTROL_32 0xa10
-#define UV1H_LB_BAU_MISC_CONTROL_32 0x320170UL
-#define UV2H_LB_BAU_MISC_CONTROL_32 0x320170UL
-#define UV3H_LB_BAU_MISC_CONTROL_32 0x320170UL
+#define UV4H_LB_BAU_MISC_CONTROL 0xc8170UL
+#define UVH_LB_BAU_MISC_CONTROL (					\
+	is_uv1_hub() ? UV1H_LB_BAU_MISC_CONTROL :			\
+	is_uv2_hub() ? UV2H_LB_BAU_MISC_CONTROL :			\
+	is_uv3_hub() ? UV3H_LB_BAU_MISC_CONTROL :			\
+	/*is_uv4_hub*/ UV4H_LB_BAU_MISC_CONTROL)
+
+#define UV1H_LB_BAU_MISC_CONTROL_32 0xa10
+#define UV2H_LB_BAU_MISC_CONTROL_32 0xa10
+#define UV3H_LB_BAU_MISC_CONTROL_32 0xa10
+#define UV4H_LB_BAU_MISC_CONTROL_32 0xa18
+#define UVH_LB_BAU_MISC_CONTROL_32 (					\
+	is_uv1_hub() ? UV1H_LB_BAU_MISC_CONTROL_32 :			\
+	is_uv2_hub() ? UV2H_LB_BAU_MISC_CONTROL_32 :			\
+	is_uv3_hub() ? UV3H_LB_BAU_MISC_CONTROL_32 :			\
+	/*is_uv4_hub*/ UV4H_LB_BAU_MISC_CONTROL_32)
 
 #define UVH_LB_BAU_MISC_CONTROL_REJECTION_DELAY_SHFT	0
 #define UVH_LB_BAU_MISC_CONTROL_APIC_MODE_SHFT		8
@@ -1590,8 +2215,6 @@ union uvh_lb_bau_intd_software_acknowled
 #define UVH_LB_BAU_MISC_CONTROL_FORCE_LOCK_NOP_SHFT	10
 #define UVH_LB_BAU_MISC_CONTROL_QPI_AGENT_PRESENCE_VECTOR_SHFT 11
 #define UVH_LB_BAU_MISC_CONTROL_DESCRIPTOR_FETCH_MODE_SHFT 14
-#define UVH_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_SHFT 15
-#define UVH_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHFT 16
 #define UVH_LB_BAU_MISC_CONTROL_ENABLE_DUAL_MAPPING_MODE_SHFT 20
 #define UVH_LB_BAU_MISC_CONTROL_VGA_IO_PORT_DECODE_ENABLE_SHFT 21
 #define UVH_LB_BAU_MISC_CONTROL_VGA_IO_PORT_16_BIT_DECODE_SHFT 22
@@ -1606,8 +2229,6 @@ union uvh_lb_bau_intd_software_acknowled
 #define UVH_LB_BAU_MISC_CONTROL_FORCE_LOCK_NOP_MASK	0x0000000000000400UL
 #define UVH_LB_BAU_MISC_CONTROL_QPI_AGENT_PRESENCE_VECTOR_MASK 0x0000000000003800UL
 #define UVH_LB_BAU_MISC_CONTROL_DESCRIPTOR_FETCH_MODE_MASK 0x0000000000004000UL
-#define UVH_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_MASK 0x0000000000008000UL
-#define UVH_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_MASK 0x00000000000f0000UL
 #define UVH_LB_BAU_MISC_CONTROL_ENABLE_DUAL_MAPPING_MODE_MASK 0x0000000000100000UL
 #define UVH_LB_BAU_MISC_CONTROL_VGA_IO_PORT_DECODE_ENABLE_MASK 0x0000000000200000UL
 #define UVH_LB_BAU_MISC_CONTROL_VGA_IO_PORT_16_BIT_DECODE_MASK 0x0000000000400000UL
@@ -1656,8 +2277,6 @@ union uvh_lb_bau_intd_software_acknowled
 #define UVXH_LB_BAU_MISC_CONTROL_FORCE_LOCK_NOP_SHFT	10
 #define UVXH_LB_BAU_MISC_CONTROL_QPI_AGENT_PRESENCE_VECTOR_SHFT 11
 #define UVXH_LB_BAU_MISC_CONTROL_DESCRIPTOR_FETCH_MODE_SHFT 14
-#define UVXH_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_SHFT 15
-#define UVXH_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHFT 16
 #define UVXH_LB_BAU_MISC_CONTROL_ENABLE_DUAL_MAPPING_MODE_SHFT 20
 #define UVXH_LB_BAU_MISC_CONTROL_VGA_IO_PORT_DECODE_ENABLE_SHFT 21
 #define UVXH_LB_BAU_MISC_CONTROL_VGA_IO_PORT_16_BIT_DECODE_SHFT 22
@@ -1679,8 +2298,6 @@ union uvh_lb_bau_intd_software_acknowled
 #define UVXH_LB_BAU_MISC_CONTROL_FORCE_LOCK_NOP_MASK	0x0000000000000400UL
 #define UVXH_LB_BAU_MISC_CONTROL_QPI_AGENT_PRESENCE_VECTOR_MASK 0x0000000000003800UL
 #define UVXH_LB_BAU_MISC_CONTROL_DESCRIPTOR_FETCH_MODE_MASK 0x0000000000004000UL
-#define UVXH_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_MASK 0x0000000000008000UL
-#define UVXH_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_MASK 0x00000000000f0000UL
 #define UVXH_LB_BAU_MISC_CONTROL_ENABLE_DUAL_MAPPING_MODE_MASK 0x0000000000100000UL
 #define UVXH_LB_BAU_MISC_CONTROL_VGA_IO_PORT_DECODE_ENABLE_MASK 0x0000000000200000UL
 #define UVXH_LB_BAU_MISC_CONTROL_VGA_IO_PORT_16_BIT_DECODE_MASK 0x0000000000400000UL
@@ -1797,6 +2414,88 @@ union uvh_lb_bau_intd_software_acknowled
 #define UV3H_LB_BAU_MISC_CONTROL_THREAD_KILL_TIMEBASE_MASK 0x00003fc000000000UL
 #define UV3H_LB_BAU_MISC_CONTROL_FUN_MASK		0xffff000000000000UL
 
+#define UV4H_LB_BAU_MISC_CONTROL_REJECTION_DELAY_SHFT	0
+#define UV4H_LB_BAU_MISC_CONTROL_APIC_MODE_SHFT		8
+#define UV4H_LB_BAU_MISC_CONTROL_FORCE_BROADCAST_SHFT	9
+#define UV4H_LB_BAU_MISC_CONTROL_FORCE_LOCK_NOP_SHFT	10
+#define UV4H_LB_BAU_MISC_CONTROL_QPI_AGENT_PRESENCE_VECTOR_SHFT 11
+#define UV4H_LB_BAU_MISC_CONTROL_DESCRIPTOR_FETCH_MODE_SHFT 14
+#define UV4H_LB_BAU_MISC_CONTROL_RESERVED_15_19_SHFT	15
+#define UV4H_LB_BAU_MISC_CONTROL_ENABLE_DUAL_MAPPING_MODE_SHFT 20
+#define UV4H_LB_BAU_MISC_CONTROL_VGA_IO_PORT_DECODE_ENABLE_SHFT 21
+#define UV4H_LB_BAU_MISC_CONTROL_VGA_IO_PORT_16_BIT_DECODE_SHFT 22
+#define UV4H_LB_BAU_MISC_CONTROL_SUPPRESS_DEST_REGISTRATION_SHFT 23
+#define UV4H_LB_BAU_MISC_CONTROL_PROGRAMMED_INITIAL_PRIORITY_SHFT 24
+#define UV4H_LB_BAU_MISC_CONTROL_USE_INCOMING_PRIORITY_SHFT 27
+#define UV4H_LB_BAU_MISC_CONTROL_ENABLE_PROGRAMMED_INITIAL_PRIORITY_SHFT 28
+#define UV4H_LB_BAU_MISC_CONTROL_ENABLE_AUTOMATIC_APIC_MODE_SELECTION_SHFT 29
+#define UV4H_LB_BAU_MISC_CONTROL_APIC_MODE_STATUS_SHFT	30
+#define UV4H_LB_BAU_MISC_CONTROL_SUPPRESS_INTERRUPTS_TO_SELF_SHFT 31
+#define UV4H_LB_BAU_MISC_CONTROL_ENABLE_LOCK_BASED_SYSTEM_FLUSH_SHFT 32
+#define UV4H_LB_BAU_MISC_CONTROL_ENABLE_EXTENDED_SB_STATUS_SHFT 33
+#define UV4H_LB_BAU_MISC_CONTROL_SUPPRESS_INT_PRIO_UDT_TO_SELF_SHFT 34
+#define UV4H_LB_BAU_MISC_CONTROL_USE_LEGACY_DESCRIPTOR_FORMATS_SHFT 35
+#define UV4H_LB_BAU_MISC_CONTROL_SUPPRESS_QUIESCE_MSGS_TO_QPI_SHFT 36
+#define UV4H_LB_BAU_MISC_CONTROL_RESERVED_37_SHFT	37
+#define UV4H_LB_BAU_MISC_CONTROL_THREAD_KILL_TIMEBASE_SHFT 38
+#define UV4H_LB_BAU_MISC_CONTROL_ADDRESS_INTERLEAVE_SELECT_SHFT 46
+#define UV4H_LB_BAU_MISC_CONTROL_FUN_SHFT		48
+#define UV4H_LB_BAU_MISC_CONTROL_REJECTION_DELAY_MASK	0x00000000000000ffUL
+#define UV4H_LB_BAU_MISC_CONTROL_APIC_MODE_MASK		0x0000000000000100UL
+#define UV4H_LB_BAU_MISC_CONTROL_FORCE_BROADCAST_MASK	0x0000000000000200UL
+#define UV4H_LB_BAU_MISC_CONTROL_FORCE_LOCK_NOP_MASK	0x0000000000000400UL
+#define UV4H_LB_BAU_MISC_CONTROL_QPI_AGENT_PRESENCE_VECTOR_MASK 0x0000000000003800UL
+#define UV4H_LB_BAU_MISC_CONTROL_DESCRIPTOR_FETCH_MODE_MASK 0x0000000000004000UL
+#define UV4H_LB_BAU_MISC_CONTROL_RESERVED_15_19_MASK	0x00000000000f8000UL
+#define UV4H_LB_BAU_MISC_CONTROL_ENABLE_DUAL_MAPPING_MODE_MASK 0x0000000000100000UL
+#define UV4H_LB_BAU_MISC_CONTROL_VGA_IO_PORT_DECODE_ENABLE_MASK 0x0000000000200000UL
+#define UV4H_LB_BAU_MISC_CONTROL_VGA_IO_PORT_16_BIT_DECODE_MASK 0x0000000000400000UL
+#define UV4H_LB_BAU_MISC_CONTROL_SUPPRESS_DEST_REGISTRATION_MASK 0x0000000000800000UL
+#define UV4H_LB_BAU_MISC_CONTROL_PROGRAMMED_INITIAL_PRIORITY_MASK 0x0000000007000000UL
+#define UV4H_LB_BAU_MISC_CONTROL_USE_INCOMING_PRIORITY_MASK 0x0000000008000000UL
+#define UV4H_LB_BAU_MISC_CONTROL_ENABLE_PROGRAMMED_INITIAL_PRIORITY_MASK 0x0000000010000000UL
+#define UV4H_LB_BAU_MISC_CONTROL_ENABLE_AUTOMATIC_APIC_MODE_SELECTION_MASK 0x0000000020000000UL
+#define UV4H_LB_BAU_MISC_CONTROL_APIC_MODE_STATUS_MASK	0x0000000040000000UL
+#define UV4H_LB_BAU_MISC_CONTROL_SUPPRESS_INTERRUPTS_TO_SELF_MASK 0x0000000080000000UL
+#define UV4H_LB_BAU_MISC_CONTROL_ENABLE_LOCK_BASED_SYSTEM_FLUSH_MASK 0x0000000100000000UL
+#define UV4H_LB_BAU_MISC_CONTROL_ENABLE_EXTENDED_SB_STATUS_MASK 0x0000000200000000UL
+#define UV4H_LB_BAU_MISC_CONTROL_SUPPRESS_INT_PRIO_UDT_TO_SELF_MASK 0x0000000400000000UL
+#define UV4H_LB_BAU_MISC_CONTROL_USE_LEGACY_DESCRIPTOR_FORMATS_MASK 0x0000000800000000UL
+#define UV4H_LB_BAU_MISC_CONTROL_SUPPRESS_QUIESCE_MSGS_TO_QPI_MASK 0x0000001000000000UL
+#define UV4H_LB_BAU_MISC_CONTROL_RESERVED_37_MASK	0x0000002000000000UL
+#define UV4H_LB_BAU_MISC_CONTROL_THREAD_KILL_TIMEBASE_MASK 0x00003fc000000000UL
+#define UV4H_LB_BAU_MISC_CONTROL_ADDRESS_INTERLEAVE_SELECT_MASK 0x0000400000000000UL
+#define UV4H_LB_BAU_MISC_CONTROL_FUN_MASK		0xffff000000000000UL
+
+#define UV4H_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_MASK	\
+	uv_undefined("UV4H_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_MASK")
+#define UVH_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_MASK (	\
+	is_uv1_hub() ? UV1H_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_MASK : \
+	is_uv2_hub() ? UV2H_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_MASK : \
+	is_uv3_hub() ? UV3H_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_MASK : \
+	/*is_uv4_hub*/ UV4H_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_MASK)
+#define UV4H_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_SHFT	\
+	uv_undefined("UV4H_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_SHFT")
+#define UVH_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_SHFT (	\
+	is_uv1_hub() ? UV1H_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_SHFT : \
+	is_uv2_hub() ? UV2H_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_SHFT : \
+	is_uv3_hub() ? UV3H_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_SHFT : \
+	/*is_uv4_hub*/ UV4H_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_SHFT)
+#define UV4H_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_MASK	\
+	uv_undefined("UV4H_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_MASK")
+#define UVH_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_MASK (	\
+	is_uv1_hub() ? UV1H_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_MASK : \
+	is_uv2_hub() ? UV2H_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_MASK : \
+	is_uv3_hub() ? UV3H_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_MASK : \
+	/*is_uv4_hub*/ UV4H_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_MASK)
+#define UV4H_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHFT	\
+	uv_undefined("UV4H_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHFT")
+#define UVH_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHFT (	\
+	is_uv1_hub() ? UV1H_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHFT : \
+	is_uv2_hub() ? UV2H_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHFT : \
+	is_uv3_hub() ? UV3H_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHFT : \
+	/*is_uv4_hub*/ UV4H_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHFT)
+
 union uvh_lb_bau_misc_control_u {
 	unsigned long	v;
 	struct uvh_lb_bau_misc_control_s {
@@ -1806,8 +2505,7 @@ union uvh_lb_bau_misc_control_u {
 		unsigned long	force_lock_nop:1;		/* RW */
 		unsigned long	qpi_agent_presence_vector:3;	/* RW */
 		unsigned long	descriptor_fetch_mode:1;	/* RW */
-		unsigned long	enable_intd_soft_ack_mode:1;	/* RW */
-		unsigned long	intd_soft_ack_timeout_period:4;	/* RW */
+		unsigned long	rsvd_15_19:5;
 		unsigned long	enable_dual_mapping_mode:1;	/* RW */
 		unsigned long	vga_io_port_decode_enable:1;	/* RW */
 		unsigned long	vga_io_port_16_bit_decode:1;	/* RW */
@@ -1844,8 +2542,7 @@ union uvh_lb_bau_misc_control_u {
 		unsigned long	force_lock_nop:1;		/* RW */
 		unsigned long	qpi_agent_presence_vector:3;	/* RW */
 		unsigned long	descriptor_fetch_mode:1;	/* RW */
-		unsigned long	enable_intd_soft_ack_mode:1;	/* RW */
-		unsigned long	intd_soft_ack_timeout_period:4;	/* RW */
+		unsigned long	rsvd_15_19:5;
 		unsigned long	enable_dual_mapping_mode:1;	/* RW */
 		unsigned long	vga_io_port_decode_enable:1;	/* RW */
 		unsigned long	vga_io_port_16_bit_decode:1;	/* RW */
@@ -1918,13 +2615,59 @@ union uvh_lb_bau_misc_control_u {
 		unsigned long	rsvd_46_47:2;
 		unsigned long	fun:16;				/* RW */
 	} s3;
+	struct uv4h_lb_bau_misc_control_s {
+		unsigned long	rejection_delay:8;		/* RW */
+		unsigned long	apic_mode:1;			/* RW */
+		unsigned long	force_broadcast:1;		/* RW */
+		unsigned long	force_lock_nop:1;		/* RW */
+		unsigned long	qpi_agent_presence_vector:3;	/* RW */
+		unsigned long	descriptor_fetch_mode:1;	/* RW */
+		unsigned long	rsvd_15_19:5;
+		unsigned long	enable_dual_mapping_mode:1;	/* RW */
+		unsigned long	vga_io_port_decode_enable:1;	/* RW */
+		unsigned long	vga_io_port_16_bit_decode:1;	/* RW */
+		unsigned long	suppress_dest_registration:1;	/* RW */
+		unsigned long	programmed_initial_priority:3;	/* RW */
+		unsigned long	use_incoming_priority:1;	/* RW */
+		unsigned long	enable_programmed_initial_priority:1;/* RW */
+		unsigned long	enable_automatic_apic_mode_selection:1;/* RW */
+		unsigned long	apic_mode_status:1;		/* RO */
+		unsigned long	suppress_interrupts_to_self:1;	/* RW */
+		unsigned long	enable_lock_based_system_flush:1;/* RW */
+		unsigned long	enable_extended_sb_status:1;	/* RW */
+		unsigned long	suppress_int_prio_udt_to_self:1;/* RW */
+		unsigned long	use_legacy_descriptor_formats:1;/* RW */
+		unsigned long	suppress_quiesce_msgs_to_qpi:1;	/* RW */
+		unsigned long	rsvd_37:1;
+		unsigned long	thread_kill_timebase:8;		/* RW */
+		unsigned long	address_interleave_select:1;	/* RW */
+		unsigned long	rsvd_47:1;
+		unsigned long	fun:16;				/* RW */
+	} s4;
 };
 
 /* ========================================================================= */
 /*                     UVH_LB_BAU_SB_ACTIVATION_CONTROL                      */
 /* ========================================================================= */
-#define UVH_LB_BAU_SB_ACTIVATION_CONTROL 0x320020UL
-#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_32 0x9a8
+#define UV1H_LB_BAU_SB_ACTIVATION_CONTROL 0x320020UL
+#define UV2H_LB_BAU_SB_ACTIVATION_CONTROL 0x320020UL
+#define UV3H_LB_BAU_SB_ACTIVATION_CONTROL 0x320020UL
+#define UV4H_LB_BAU_SB_ACTIVATION_CONTROL 0xc8020UL
+#define UVH_LB_BAU_SB_ACTIVATION_CONTROL (				\
+	is_uv1_hub() ? UV1H_LB_BAU_SB_ACTIVATION_CONTROL :		\
+	is_uv2_hub() ? UV2H_LB_BAU_SB_ACTIVATION_CONTROL :		\
+	is_uv3_hub() ? UV3H_LB_BAU_SB_ACTIVATION_CONTROL :		\
+	/*is_uv4_hub*/ UV4H_LB_BAU_SB_ACTIVATION_CONTROL)
+
+#define UV1H_LB_BAU_SB_ACTIVATION_CONTROL_32 0x9a8
+#define UV2H_LB_BAU_SB_ACTIVATION_CONTROL_32 0x9a8
+#define UV3H_LB_BAU_SB_ACTIVATION_CONTROL_32 0x9a8
+#define UV4H_LB_BAU_SB_ACTIVATION_CONTROL_32 0x9c8
+#define UVH_LB_BAU_SB_ACTIVATION_CONTROL_32 (				\
+	is_uv1_hub() ? UV1H_LB_BAU_SB_ACTIVATION_CONTROL_32 :		\
+	is_uv2_hub() ? UV2H_LB_BAU_SB_ACTIVATION_CONTROL_32 :		\
+	is_uv3_hub() ? UV3H_LB_BAU_SB_ACTIVATION_CONTROL_32 :		\
+	/*is_uv4_hub*/ UV4H_LB_BAU_SB_ACTIVATION_CONTROL_32)
 
 #define UVH_LB_BAU_SB_ACTIVATION_CONTROL_INDEX_SHFT	0
 #define UVH_LB_BAU_SB_ACTIVATION_CONTROL_PUSH_SHFT	62
@@ -1933,6 +2676,7 @@ union uvh_lb_bau_misc_control_u {
 #define UVH_LB_BAU_SB_ACTIVATION_CONTROL_PUSH_MASK	0x4000000000000000UL
 #define UVH_LB_BAU_SB_ACTIVATION_CONTROL_INIT_MASK	0x8000000000000000UL
 
+
 union uvh_lb_bau_sb_activation_control_u {
 	unsigned long	v;
 	struct uvh_lb_bau_sb_activation_control_s {
@@ -1946,12 +2690,30 @@ union uvh_lb_bau_sb_activation_control_u
 /* ========================================================================= */
 /*                    UVH_LB_BAU_SB_ACTIVATION_STATUS_0                      */
 /* ========================================================================= */
-#define UVH_LB_BAU_SB_ACTIVATION_STATUS_0 0x320030UL
-#define UVH_LB_BAU_SB_ACTIVATION_STATUS_0_32 0x9b0
+#define UV1H_LB_BAU_SB_ACTIVATION_STATUS_0 0x320030UL
+#define UV2H_LB_BAU_SB_ACTIVATION_STATUS_0 0x320030UL
+#define UV3H_LB_BAU_SB_ACTIVATION_STATUS_0 0x320030UL
+#define UV4H_LB_BAU_SB_ACTIVATION_STATUS_0 0xc8030UL
+#define UVH_LB_BAU_SB_ACTIVATION_STATUS_0 (				\
+	is_uv1_hub() ? UV1H_LB_BAU_SB_ACTIVATION_STATUS_0 :		\
+	is_uv2_hub() ? UV2H_LB_BAU_SB_ACTIVATION_STATUS_0 :		\
+	is_uv3_hub() ? UV3H_LB_BAU_SB_ACTIVATION_STATUS_0 :		\
+	/*is_uv4_hub*/ UV4H_LB_BAU_SB_ACTIVATION_STATUS_0)
+
+#define UV1H_LB_BAU_SB_ACTIVATION_STATUS_0_32 0x9b0
+#define UV2H_LB_BAU_SB_ACTIVATION_STATUS_0_32 0x9b0
+#define UV3H_LB_BAU_SB_ACTIVATION_STATUS_0_32 0x9b0
+#define UV4H_LB_BAU_SB_ACTIVATION_STATUS_0_32 0x9d0
+#define UVH_LB_BAU_SB_ACTIVATION_STATUS_0_32 (				\
+	is_uv1_hub() ? UV1H_LB_BAU_SB_ACTIVATION_STATUS_0_32 :		\
+	is_uv2_hub() ? UV2H_LB_BAU_SB_ACTIVATION_STATUS_0_32 :		\
+	is_uv3_hub() ? UV3H_LB_BAU_SB_ACTIVATION_STATUS_0_32 :		\
+	/*is_uv4_hub*/ UV4H_LB_BAU_SB_ACTIVATION_STATUS_0_32)
 
 #define UVH_LB_BAU_SB_ACTIVATION_STATUS_0_STATUS_SHFT	0
 #define UVH_LB_BAU_SB_ACTIVATION_STATUS_0_STATUS_MASK	0xffffffffffffffffUL
 
+
 union uvh_lb_bau_sb_activation_status_0_u {
 	unsigned long	v;
 	struct uvh_lb_bau_sb_activation_status_0_s {
@@ -1962,12 +2724,30 @@ union uvh_lb_bau_sb_activation_status_0_
 /* ========================================================================= */
 /*                    UVH_LB_BAU_SB_ACTIVATION_STATUS_1                      */
 /* ========================================================================= */
-#define UVH_LB_BAU_SB_ACTIVATION_STATUS_1 0x320040UL
-#define UVH_LB_BAU_SB_ACTIVATION_STATUS_1_32 0x9b8
+#define UV1H_LB_BAU_SB_ACTIVATION_STATUS_1 0x320040UL
+#define UV2H_LB_BAU_SB_ACTIVATION_STATUS_1 0x320040UL
+#define UV3H_LB_BAU_SB_ACTIVATION_STATUS_1 0x320040UL
+#define UV4H_LB_BAU_SB_ACTIVATION_STATUS_1 0xc8040UL
+#define UVH_LB_BAU_SB_ACTIVATION_STATUS_1 (				\
+	is_uv1_hub() ? UV1H_LB_BAU_SB_ACTIVATION_STATUS_1 :		\
+	is_uv2_hub() ? UV2H_LB_BAU_SB_ACTIVATION_STATUS_1 :		\
+	is_uv3_hub() ? UV3H_LB_BAU_SB_ACTIVATION_STATUS_1 :		\
+	/*is_uv4_hub*/ UV4H_LB_BAU_SB_ACTIVATION_STATUS_1)
+
+#define UV1H_LB_BAU_SB_ACTIVATION_STATUS_1_32 0x9b8
+#define UV2H_LB_BAU_SB_ACTIVATION_STATUS_1_32 0x9b8
+#define UV3H_LB_BAU_SB_ACTIVATION_STATUS_1_32 0x9b8
+#define UV4H_LB_BAU_SB_ACTIVATION_STATUS_1_32 0x9d8
+#define UVH_LB_BAU_SB_ACTIVATION_STATUS_1_32 (				\
+	is_uv1_hub() ? UV1H_LB_BAU_SB_ACTIVATION_STATUS_1_32 :		\
+	is_uv2_hub() ? UV2H_LB_BAU_SB_ACTIVATION_STATUS_1_32 :		\
+	is_uv3_hub() ? UV3H_LB_BAU_SB_ACTIVATION_STATUS_1_32 :		\
+	/*is_uv4_hub*/ UV4H_LB_BAU_SB_ACTIVATION_STATUS_1_32)
 
 #define UVH_LB_BAU_SB_ACTIVATION_STATUS_1_STATUS_SHFT	0
 #define UVH_LB_BAU_SB_ACTIVATION_STATUS_1_STATUS_MASK	0xffffffffffffffffUL
 
+
 union uvh_lb_bau_sb_activation_status_1_u {
 	unsigned long	v;
 	struct uvh_lb_bau_sb_activation_status_1_s {
@@ -1978,23 +2758,55 @@ union uvh_lb_bau_sb_activation_status_1_
 /* ========================================================================= */
 /*                      UVH_LB_BAU_SB_DESCRIPTOR_BASE                        */
 /* ========================================================================= */
-#define UVH_LB_BAU_SB_DESCRIPTOR_BASE 0x320010UL
-#define UVH_LB_BAU_SB_DESCRIPTOR_BASE_32 0x9a0
+#define UV1H_LB_BAU_SB_DESCRIPTOR_BASE 0x320010UL
+#define UV2H_LB_BAU_SB_DESCRIPTOR_BASE 0x320010UL
+#define UV3H_LB_BAU_SB_DESCRIPTOR_BASE 0x320010UL
+#define UV4H_LB_BAU_SB_DESCRIPTOR_BASE 0xc8010UL
+#define UVH_LB_BAU_SB_DESCRIPTOR_BASE (					\
+	is_uv1_hub() ? UV1H_LB_BAU_SB_DESCRIPTOR_BASE :			\
+	is_uv2_hub() ? UV2H_LB_BAU_SB_DESCRIPTOR_BASE :			\
+	is_uv3_hub() ? UV3H_LB_BAU_SB_DESCRIPTOR_BASE :			\
+	/*is_uv4_hub*/ UV4H_LB_BAU_SB_DESCRIPTOR_BASE)
+
+#define UV1H_LB_BAU_SB_DESCRIPTOR_BASE_32 0x9a0
+#define UV2H_LB_BAU_SB_DESCRIPTOR_BASE_32 0x9a0
+#define UV3H_LB_BAU_SB_DESCRIPTOR_BASE_32 0x9a0
+#define UV4H_LB_BAU_SB_DESCRIPTOR_BASE_32 0x9c0
+#define UVH_LB_BAU_SB_DESCRIPTOR_BASE_32 (				\
+	is_uv1_hub() ? UV1H_LB_BAU_SB_DESCRIPTOR_BASE_32 :		\
+	is_uv2_hub() ? UV2H_LB_BAU_SB_DESCRIPTOR_BASE_32 :		\
+	is_uv3_hub() ? UV3H_LB_BAU_SB_DESCRIPTOR_BASE_32 :		\
+	/*is_uv4_hub*/ UV4H_LB_BAU_SB_DESCRIPTOR_BASE_32)
 
 #define UVH_LB_BAU_SB_DESCRIPTOR_BASE_PAGE_ADDRESS_SHFT	12
 #define UVH_LB_BAU_SB_DESCRIPTOR_BASE_NODE_ID_SHFT	49
-#define UVH_LB_BAU_SB_DESCRIPTOR_BASE_PAGE_ADDRESS_MASK	0x000007fffffff000UL
 #define UVH_LB_BAU_SB_DESCRIPTOR_BASE_NODE_ID_MASK	0x7ffe000000000000UL
 
+#define UV1H_LB_BAU_SB_DESCRIPTOR_BASE_PAGE_ADDRESS_MASK 0x000007fffffff000UL
+
+
+#define UV2H_LB_BAU_SB_DESCRIPTOR_BASE_PAGE_ADDRESS_MASK 0x000007fffffff000UL
+
+#define UV3H_LB_BAU_SB_DESCRIPTOR_BASE_PAGE_ADDRESS_MASK 0x000007fffffff000UL
+
+#define UV4H_LB_BAU_SB_DESCRIPTOR_BASE_PAGE_ADDRESS_MASK 0x00003ffffffff000UL
+
+
 union uvh_lb_bau_sb_descriptor_base_u {
 	unsigned long	v;
 	struct uvh_lb_bau_sb_descriptor_base_s {
 		unsigned long	rsvd_0_11:12;
-		unsigned long	page_address:31;		/* RW */
-		unsigned long	rsvd_43_48:6;
+		unsigned long	rsvd_12_48:37;
 		unsigned long	node_id:14;			/* RW */
 		unsigned long	rsvd_63:1;
 	} s;
+	struct uv4h_lb_bau_sb_descriptor_base_s {
+		unsigned long	rsvd_0_11:12;
+		unsigned long	page_address:34;		/* RW */
+		unsigned long	rsvd_46_48:3;
+		unsigned long	node_id:14;			/* RW */
+		unsigned long	rsvd_63:1;
+	} s4;
 };
 
 /* ========================================================================= */
@@ -2004,6 +2816,7 @@ union uvh_lb_bau_sb_descriptor_base_u {
 #define UV1H_NODE_ID 0x0UL
 #define UV2H_NODE_ID 0x0UL
 #define UV3H_NODE_ID 0x0UL
+#define UV4H_NODE_ID 0x0UL
 
 #define UVH_NODE_ID_FORCE1_SHFT				0
 #define UVH_NODE_ID_MANUFACTURER_SHFT			1
@@ -2080,6 +2893,26 @@ union uvh_lb_bau_sb_descriptor_base_u {
 #define UV3H_NODE_ID_NODES_PER_BIT_MASK			0x01fc000000000000UL
 #define UV3H_NODE_ID_NI_PORT_MASK			0x3e00000000000000UL
 
+#define UV4H_NODE_ID_FORCE1_SHFT			0
+#define UV4H_NODE_ID_MANUFACTURER_SHFT			1
+#define UV4H_NODE_ID_PART_NUMBER_SHFT			12
+#define UV4H_NODE_ID_REVISION_SHFT			28
+#define UV4H_NODE_ID_NODE_ID_SHFT			32
+#define UV4H_NODE_ID_ROUTER_SELECT_SHFT			48
+#define UV4H_NODE_ID_RESERVED_2_SHFT			49
+#define UV4H_NODE_ID_NODES_PER_BIT_SHFT			50
+#define UV4H_NODE_ID_NI_PORT_SHFT			57
+#define UV4H_NODE_ID_FORCE1_MASK			0x0000000000000001UL
+#define UV4H_NODE_ID_MANUFACTURER_MASK			0x0000000000000ffeUL
+#define UV4H_NODE_ID_PART_NUMBER_MASK			0x000000000ffff000UL
+#define UV4H_NODE_ID_REVISION_MASK			0x00000000f0000000UL
+#define UV4H_NODE_ID_NODE_ID_MASK			0x00007fff00000000UL
+#define UV4H_NODE_ID_ROUTER_SELECT_MASK			0x0001000000000000UL
+#define UV4H_NODE_ID_RESERVED_2_MASK			0x0002000000000000UL
+#define UV4H_NODE_ID_NODES_PER_BIT_MASK			0x01fc000000000000UL
+#define UV4H_NODE_ID_NI_PORT_MASK			0x3e00000000000000UL
+
+
 union uvh_node_id_u {
 	unsigned long	v;
 	struct uvh_node_id_s {
@@ -2137,17 +2970,40 @@ union uvh_node_id_u {
 		unsigned long	ni_port:5;			/* RO */
 		unsigned long	rsvd_62_63:2;
 	} s3;
+	struct uv4h_node_id_s {
+		unsigned long	force1:1;			/* RO */
+		unsigned long	manufacturer:11;		/* RO */
+		unsigned long	part_number:16;			/* RO */
+		unsigned long	revision:4;			/* RO */
+		unsigned long	node_id:15;			/* RW */
+		unsigned long	rsvd_47:1;
+		unsigned long	router_select:1;		/* RO */
+		unsigned long	rsvd_49:1;
+		unsigned long	nodes_per_bit:7;		/* RO */
+		unsigned long	ni_port:5;			/* RO */
+		unsigned long	rsvd_62_63:2;
+	} s4;
 };
 
 /* ========================================================================= */
 /*                          UVH_NODE_PRESENT_TABLE                           */
 /* ========================================================================= */
 #define UVH_NODE_PRESENT_TABLE 0x1400UL
-#define UVH_NODE_PRESENT_TABLE_DEPTH 16
+
+#define UV1H_NODE_PRESENT_TABLE_DEPTH 16
+#define UV2H_NODE_PRESENT_TABLE_DEPTH 16
+#define UV3H_NODE_PRESENT_TABLE_DEPTH 16
+#define UV4H_NODE_PRESENT_TABLE_DEPTH 4
+#define UVH_NODE_PRESENT_TABLE_DEPTH (					\
+	is_uv1_hub() ? UV1H_NODE_PRESENT_TABLE_DEPTH :			\
+	is_uv2_hub() ? UV2H_NODE_PRESENT_TABLE_DEPTH :			\
+	is_uv3_hub() ? UV3H_NODE_PRESENT_TABLE_DEPTH :			\
+	/*is_uv4_hub*/ UV4H_NODE_PRESENT_TABLE_DEPTH)
 
 #define UVH_NODE_PRESENT_TABLE_NODES_SHFT		0
 #define UVH_NODE_PRESENT_TABLE_NODES_MASK		0xffffffffffffffffUL
 
+
 union uvh_node_present_table_u {
 	unsigned long	v;
 	struct uvh_node_present_table_s {
@@ -2158,7 +3014,15 @@ union uvh_node_present_table_u {
 /* ========================================================================= */
 /*                 UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR                  */
 /* ========================================================================= */
-#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR 0x16000c8UL
+#define UV1H_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR 0x16000c8UL
+#define UV2H_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR 0x16000c8UL
+#define UV3H_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR 0x16000c8UL
+#define UV4H_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR 0x4800c8UL
+#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR (			\
+	is_uv1_hub() ? UV1H_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR :	\
+	is_uv2_hub() ? UV2H_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR :	\
+	is_uv3_hub() ? UV3H_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR :	\
+	/*is_uv4_hub*/ UV4H_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR)
 
 #define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR_BASE_SHFT 24
 #define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR_M_ALIAS_SHFT 48
@@ -2167,6 +3031,7 @@ union uvh_node_present_table_u {
 #define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR_M_ALIAS_MASK 0x001f000000000000UL
 #define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR_ENABLE_MASK 0x8000000000000000UL
 
+
 union uvh_rh_gam_alias210_overlay_config_0_mmr_u {
 	unsigned long	v;
 	struct uvh_rh_gam_alias210_overlay_config_0_mmr_s {
@@ -2182,7 +3047,15 @@ union uvh_rh_gam_alias210_overlay_config
 /* ========================================================================= */
 /*                 UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR                  */
 /* ========================================================================= */
-#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR 0x16000d8UL
+#define UV1H_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR 0x16000d8UL
+#define UV2H_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR 0x16000d8UL
+#define UV3H_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR 0x16000d8UL
+#define UV4H_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR 0x4800d8UL
+#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR (			\
+	is_uv1_hub() ? UV1H_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR :	\
+	is_uv2_hub() ? UV2H_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR :	\
+	is_uv3_hub() ? UV3H_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR :	\
+	/*is_uv4_hub*/ UV4H_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR)
 
 #define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR_BASE_SHFT 24
 #define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR_M_ALIAS_SHFT 48
@@ -2191,6 +3064,7 @@ union uvh_rh_gam_alias210_overlay_config
 #define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR_M_ALIAS_MASK 0x001f000000000000UL
 #define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR_ENABLE_MASK 0x8000000000000000UL
 
+
 union uvh_rh_gam_alias210_overlay_config_1_mmr_u {
 	unsigned long	v;
 	struct uvh_rh_gam_alias210_overlay_config_1_mmr_s {
@@ -2206,7 +3080,15 @@ union uvh_rh_gam_alias210_overlay_config
 /* ========================================================================= */
 /*                 UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR                  */
 /* ========================================================================= */
-#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR 0x16000e8UL
+#define UV1H_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR 0x16000e8UL
+#define UV2H_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR 0x16000e8UL
+#define UV3H_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR 0x16000e8UL
+#define UV4H_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR 0x4800e8UL
+#define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR (			\
+	is_uv1_hub() ? UV1H_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR :	\
+	is_uv2_hub() ? UV2H_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR :	\
+	is_uv3_hub() ? UV3H_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR :	\
+	/*is_uv4_hub*/ UV4H_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR)
 
 #define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR_BASE_SHFT 24
 #define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR_M_ALIAS_SHFT 48
@@ -2215,6 +3097,7 @@ union uvh_rh_gam_alias210_overlay_config
 #define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR_M_ALIAS_MASK 0x001f000000000000UL
 #define UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR_ENABLE_MASK 0x8000000000000000UL
 
+
 union uvh_rh_gam_alias210_overlay_config_2_mmr_u {
 	unsigned long	v;
 	struct uvh_rh_gam_alias210_overlay_config_2_mmr_s {
@@ -2230,11 +3113,20 @@ union uvh_rh_gam_alias210_overlay_config
 /* ========================================================================= */
 /*                UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR                  */
 /* ========================================================================= */
-#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR 0x16000d0UL
+#define UV1H_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR 0x16000d0UL
+#define UV2H_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR 0x16000d0UL
+#define UV3H_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR 0x16000d0UL
+#define UV4H_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR 0x4800d0UL
+#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR (			\
+	is_uv1_hub() ? UV1H_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR :	\
+	is_uv2_hub() ? UV2H_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR :	\
+	is_uv3_hub() ? UV3H_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR :	\
+	/*is_uv4_hub*/ UV4H_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR)
 
 #define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR_DEST_BASE_SHFT 24
 #define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR_DEST_BASE_MASK 0x00003fffff000000UL
 
+
 union uvh_rh_gam_alias210_redirect_config_0_mmr_u {
 	unsigned long	v;
 	struct uvh_rh_gam_alias210_redirect_config_0_mmr_s {
@@ -2247,11 +3139,20 @@ union uvh_rh_gam_alias210_redirect_confi
 /* ========================================================================= */
 /*                UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR                  */
 /* ========================================================================= */
-#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR 0x16000e0UL
+#define UV1H_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR 0x16000e0UL
+#define UV2H_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR 0x16000e0UL
+#define UV3H_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR 0x16000e0UL
+#define UV4H_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR 0x4800e0UL
+#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR (			\
+	is_uv1_hub() ? UV1H_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR :	\
+	is_uv2_hub() ? UV2H_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR :	\
+	is_uv3_hub() ? UV3H_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR :	\
+	/*is_uv4_hub*/ UV4H_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR)
 
 #define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR_DEST_BASE_SHFT 24
 #define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR_DEST_BASE_MASK 0x00003fffff000000UL
 
+
 union uvh_rh_gam_alias210_redirect_config_1_mmr_u {
 	unsigned long	v;
 	struct uvh_rh_gam_alias210_redirect_config_1_mmr_s {
@@ -2264,11 +3165,20 @@ union uvh_rh_gam_alias210_redirect_confi
 /* ========================================================================= */
 /*                UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR                  */
 /* ========================================================================= */
-#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR 0x16000f0UL
+#define UV1H_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR 0x16000f0UL
+#define UV2H_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR 0x16000f0UL
+#define UV3H_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR 0x16000f0UL
+#define UV4H_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR 0x4800f0UL
+#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR (			\
+	is_uv1_hub() ? UV1H_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR :	\
+	is_uv2_hub() ? UV2H_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR :	\
+	is_uv3_hub() ? UV3H_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR :	\
+	/*is_uv4_hub*/ UV4H_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR)
 
 #define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR_DEST_BASE_SHFT 24
 #define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR_DEST_BASE_MASK 0x00003fffff000000UL
 
+
 union uvh_rh_gam_alias210_redirect_config_2_mmr_u {
 	unsigned long	v;
 	struct uvh_rh_gam_alias210_redirect_config_2_mmr_s {
@@ -2281,14 +3191,17 @@ union uvh_rh_gam_alias210_redirect_confi
 /* ========================================================================= */
 /*                          UVH_RH_GAM_CONFIG_MMR                            */
 /* ========================================================================= */
-#define UVH_RH_GAM_CONFIG_MMR 0x1600000UL
 #define UV1H_RH_GAM_CONFIG_MMR 0x1600000UL
 #define UV2H_RH_GAM_CONFIG_MMR 0x1600000UL
 #define UV3H_RH_GAM_CONFIG_MMR 0x1600000UL
+#define UV4H_RH_GAM_CONFIG_MMR 0x480000UL
+#define UVH_RH_GAM_CONFIG_MMR (						\
+	is_uv1_hub() ? UV1H_RH_GAM_CONFIG_MMR :				\
+	is_uv2_hub() ? UV2H_RH_GAM_CONFIG_MMR :				\
+	is_uv3_hub() ? UV3H_RH_GAM_CONFIG_MMR :				\
+	/*is_uv4_hub*/ UV4H_RH_GAM_CONFIG_MMR)
 
-#define UVH_RH_GAM_CONFIG_MMR_M_SKT_SHFT		0
 #define UVH_RH_GAM_CONFIG_MMR_N_SKT_SHFT		6
-#define UVH_RH_GAM_CONFIG_MMR_M_SKT_MASK		0x000000000000003fUL
 #define UVH_RH_GAM_CONFIG_MMR_N_SKT_MASK		0x00000000000003c0UL
 
 #define UV1H_RH_GAM_CONFIG_MMR_M_SKT_SHFT		0
@@ -2298,9 +3211,7 @@ union uvh_rh_gam_alias210_redirect_confi
 #define UV1H_RH_GAM_CONFIG_MMR_N_SKT_MASK		0x00000000000003c0UL
 #define UV1H_RH_GAM_CONFIG_MMR_MMIOL_CFG_MASK		0x0000000000001000UL
 
-#define UVXH_RH_GAM_CONFIG_MMR_M_SKT_SHFT		0
 #define UVXH_RH_GAM_CONFIG_MMR_N_SKT_SHFT		6
-#define UVXH_RH_GAM_CONFIG_MMR_M_SKT_MASK		0x000000000000003fUL
 #define UVXH_RH_GAM_CONFIG_MMR_N_SKT_MASK		0x00000000000003c0UL
 
 #define UV2H_RH_GAM_CONFIG_MMR_M_SKT_SHFT		0
@@ -2313,10 +3224,14 @@ union uvh_rh_gam_alias210_redirect_confi
 #define UV3H_RH_GAM_CONFIG_MMR_M_SKT_MASK		0x000000000000003fUL
 #define UV3H_RH_GAM_CONFIG_MMR_N_SKT_MASK		0x00000000000003c0UL
 
+#define UV4H_RH_GAM_CONFIG_MMR_N_SKT_SHFT		6
+#define UV4H_RH_GAM_CONFIG_MMR_N_SKT_MASK		0x00000000000003c0UL
+
+
 union uvh_rh_gam_config_mmr_u {
 	unsigned long	v;
 	struct uvh_rh_gam_config_mmr_s {
-		unsigned long	m_skt:6;			/* RW */
+		unsigned long	rsvd_0_5:6;
 		unsigned long	n_skt:4;			/* RW */
 		unsigned long	rsvd_10_63:54;
 	} s;
@@ -2328,7 +3243,7 @@ union uvh_rh_gam_config_mmr_u {
 		unsigned long	rsvd_13_63:51;
 	} s1;
 	struct uvxh_rh_gam_config_mmr_s {
-		unsigned long	m_skt:6;			/* RW */
+		unsigned long	rsvd_0_5:6;
 		unsigned long	n_skt:4;			/* RW */
 		unsigned long	rsvd_10_63:54;
 	} sx;
@@ -2342,20 +3257,28 @@ union uvh_rh_gam_config_mmr_u {
 		unsigned long	n_skt:4;			/* RW */
 		unsigned long	rsvd_10_63:54;
 	} s3;
+	struct uv4h_rh_gam_config_mmr_s {
+		unsigned long	rsvd_0_5:6;
+		unsigned long	n_skt:4;			/* RW */
+		unsigned long	rsvd_10_63:54;
+	} s4;
 };
 
 /* ========================================================================= */
 /*                    UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR                      */
 /* ========================================================================= */
-#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR 0x1600010UL
 #define UV1H_RH_GAM_GRU_OVERLAY_CONFIG_MMR 0x1600010UL
 #define UV2H_RH_GAM_GRU_OVERLAY_CONFIG_MMR 0x1600010UL
 #define UV3H_RH_GAM_GRU_OVERLAY_CONFIG_MMR 0x1600010UL
+#define UV4H_RH_GAM_GRU_OVERLAY_CONFIG_MMR 0x480010UL
+#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR (				\
+	is_uv1_hub() ? UV1H_RH_GAM_GRU_OVERLAY_CONFIG_MMR :		\
+	is_uv2_hub() ? UV2H_RH_GAM_GRU_OVERLAY_CONFIG_MMR :		\
+	is_uv3_hub() ? UV3H_RH_GAM_GRU_OVERLAY_CONFIG_MMR :		\
+	/*is_uv4_hub*/ UV4H_RH_GAM_GRU_OVERLAY_CONFIG_MMR)
 
-#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_SHFT	28
 #define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_N_GRU_SHFT	52
 #define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_ENABLE_SHFT	63
-#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_MASK	0x00003ffff0000000UL
 #define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_N_GRU_MASK	0x00f0000000000000UL
 #define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_ENABLE_MASK	0x8000000000000000UL
 
@@ -2368,10 +3291,8 @@ union uvh_rh_gam_config_mmr_u {
 #define UV1H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_N_GRU_MASK	0x00f0000000000000UL
 #define UV1H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_ENABLE_MASK	0x8000000000000000UL
 
-#define UVXH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_SHFT	28
 #define UVXH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_N_GRU_SHFT	52
 #define UVXH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_ENABLE_SHFT	63
-#define UVXH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_MASK	0x00003ffff0000000UL
 #define UVXH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_N_GRU_MASK	0x00f0000000000000UL
 #define UVXH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_ENABLE_MASK	0x8000000000000000UL
 
@@ -2391,12 +3312,28 @@ union uvh_rh_gam_config_mmr_u {
 #define UV3H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_MODE_MASK	0x4000000000000000UL
 #define UV3H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_ENABLE_MASK	0x8000000000000000UL
 
+#define UV4H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_SHFT	26
+#define UV4H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_N_GRU_SHFT	52
+#define UV4H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_ENABLE_SHFT	63
+#define UV4H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_MASK	0x00003ffffc000000UL
+#define UV4H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_N_GRU_MASK	0x00f0000000000000UL
+#define UV4H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_ENABLE_MASK	0x8000000000000000UL
+
+#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_MASK (			\
+	is_uv1_hub() ? UV1H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_MASK :	\
+	is_uv2_hub() ? UV2H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_MASK :	\
+	is_uv3_hub() ? UV3H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_MASK :	\
+	/*is_uv4_hub*/ UV4H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_MASK)
+#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_SHFT (			\
+	is_uv1_hub() ? UV1H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_SHFT :	\
+	is_uv2_hub() ? UV2H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_SHFT :	\
+	is_uv3_hub() ? UV3H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_SHFT :	\
+	/*is_uv4_hub*/ UV4H_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_SHFT)
+
 union uvh_rh_gam_gru_overlay_config_mmr_u {
 	unsigned long	v;
 	struct uvh_rh_gam_gru_overlay_config_mmr_s {
-		unsigned long	rsvd_0_27:28;
-		unsigned long	base:18;			/* RW */
-		unsigned long	rsvd_46_51:6;
+		unsigned long	rsvd_0_51:52;
 		unsigned long	n_gru:4;			/* RW */
 		unsigned long	rsvd_56_62:7;
 		unsigned long	enable:1;			/* RW */
@@ -2412,8 +3349,7 @@ union uvh_rh_gam_gru_overlay_config_mmr_
 		unsigned long	enable:1;			/* RW */
 	} s1;
 	struct uvxh_rh_gam_gru_overlay_config_mmr_s {
-		unsigned long	rsvd_0_27:28;
-		unsigned long	base:18;			/* RW */
+		unsigned long	rsvd_0_45:46;
 		unsigned long	rsvd_46_51:6;
 		unsigned long	n_gru:4;			/* RW */
 		unsigned long	rsvd_56_62:7;
@@ -2436,6 +3372,15 @@ union uvh_rh_gam_gru_overlay_config_mmr_
 		unsigned long	mode:1;				/* RW */
 		unsigned long	enable:1;			/* RW */
 	} s3;
+	struct uv4h_rh_gam_gru_overlay_config_mmr_s {
+		unsigned long	rsvd_0_24:25;
+		unsigned long	undef_25:1;			/* Undefined */
+		unsigned long	base:20;			/* RW */
+		unsigned long	rsvd_46_51:6;
+		unsigned long	n_gru:4;			/* RW */
+		unsigned long	rsvd_56_62:7;
+		unsigned long	enable:1;			/* RW */
+	} s4;
 };
 
 /* ========================================================================= */
@@ -2443,6 +3388,14 @@ union uvh_rh_gam_gru_overlay_config_mmr_
 /* ========================================================================= */
 #define UV1H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR 0x1600030UL
 #define UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR 0x1600030UL
+#define UV3H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR uv_undefined("UV3H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR")
+#define UV4H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR uv_undefined("UV4H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR")
+#define UVH_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR (				\
+	is_uv1_hub() ? UV1H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR :		\
+	is_uv2_hub() ? UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR :		\
+	is_uv3_hub() ? UV3H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR :		\
+	/*is_uv4_hub*/ UV4H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR)
+
 
 #define UV1H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_BASE_SHFT	30
 #define UV1H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_M_IO_SHFT	46
@@ -2453,6 +3406,7 @@ union uvh_rh_gam_gru_overlay_config_mmr_
 #define UV1H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_N_IO_MASK	0x00f0000000000000UL
 #define UV1H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_ENABLE_MASK 0x8000000000000000UL
 
+
 #define UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_BASE_SHFT	27
 #define UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_M_IO_SHFT	46
 #define UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_N_IO_SHFT	52
@@ -2462,6 +3416,7 @@ union uvh_rh_gam_gru_overlay_config_mmr_
 #define UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_N_IO_MASK	0x00f0000000000000UL
 #define UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR_ENABLE_MASK 0x8000000000000000UL
 
+
 union uvh_rh_gam_mmioh_overlay_config_mmr_u {
 	unsigned long	v;
 	struct uv1h_rh_gam_mmioh_overlay_config_mmr_s {
@@ -2485,10 +3440,15 @@ union uvh_rh_gam_mmioh_overlay_config_mm
 /* ========================================================================= */
 /*                    UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR                      */
 /* ========================================================================= */
-#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR 0x1600028UL
 #define UV1H_RH_GAM_MMR_OVERLAY_CONFIG_MMR 0x1600028UL
 #define UV2H_RH_GAM_MMR_OVERLAY_CONFIG_MMR 0x1600028UL
 #define UV3H_RH_GAM_MMR_OVERLAY_CONFIG_MMR 0x1600028UL
+#define UV4H_RH_GAM_MMR_OVERLAY_CONFIG_MMR 0x480028UL
+#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR (				\
+	is_uv1_hub() ? UV1H_RH_GAM_MMR_OVERLAY_CONFIG_MMR :		\
+	is_uv2_hub() ? UV2H_RH_GAM_MMR_OVERLAY_CONFIG_MMR :		\
+	is_uv3_hub() ? UV3H_RH_GAM_MMR_OVERLAY_CONFIG_MMR :		\
+	/*is_uv4_hub*/ UV4H_RH_GAM_MMR_OVERLAY_CONFIG_MMR)
 
 #define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_SHFT	26
 #define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR_ENABLE_SHFT	63
@@ -2517,6 +3477,12 @@ union uvh_rh_gam_mmioh_overlay_config_mm
 #define UV3H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_MASK	0x00003ffffc000000UL
 #define UV3H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_ENABLE_MASK	0x8000000000000000UL
 
+#define UV4H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_SHFT	26
+#define UV4H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_ENABLE_SHFT	63
+#define UV4H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_MASK	0x00003ffffc000000UL
+#define UV4H_RH_GAM_MMR_OVERLAY_CONFIG_MMR_ENABLE_MASK	0x8000000000000000UL
+
+
 union uvh_rh_gam_mmr_overlay_config_mmr_u {
 	unsigned long	v;
 	struct uvh_rh_gam_mmr_overlay_config_mmr_s {
@@ -2550,16 +3516,31 @@ union uvh_rh_gam_mmr_overlay_config_mmr_
 		unsigned long	rsvd_46_62:17;
 		unsigned long	enable:1;			/* RW */
 	} s3;
+	struct uv4h_rh_gam_mmr_overlay_config_mmr_s {
+		unsigned long	rsvd_0_25:26;
+		unsigned long	base:20;			/* RW */
+		unsigned long	rsvd_46_62:17;
+		unsigned long	enable:1;			/* RW */
+	} s4;
 };
 
 /* ========================================================================= */
 /*                                 UVH_RTC                                   */
 /* ========================================================================= */
-#define UVH_RTC 0x340000UL
+#define UV1H_RTC 0x340000UL
+#define UV2H_RTC 0x340000UL
+#define UV3H_RTC 0x340000UL
+#define UV4H_RTC 0xe0000UL
+#define UVH_RTC (							\
+	is_uv1_hub() ? UV1H_RTC :					\
+	is_uv2_hub() ? UV2H_RTC :					\
+	is_uv3_hub() ? UV3H_RTC :					\
+	/*is_uv4_hub*/ UV4H_RTC)
 
 #define UVH_RTC_REAL_TIME_CLOCK_SHFT			0
 #define UVH_RTC_REAL_TIME_CLOCK_MASK			0x00ffffffffffffffUL
 
+
 union uvh_rtc_u {
 	unsigned long	v;
 	struct uvh_rtc_s {
@@ -2590,6 +3571,7 @@ union uvh_rtc_u {
 #define UVH_RTC1_INT_CONFIG_M_MASK			0x0000000000010000UL
 #define UVH_RTC1_INT_CONFIG_APIC_ID_MASK		0xffffffff00000000UL
 
+
 union uvh_rtc1_int_config_u {
 	unsigned long	v;
 	struct uvh_rtc1_int_config_s {
@@ -2609,12 +3591,30 @@ union uvh_rtc1_int_config_u {
 /* ========================================================================= */
 /*                               UVH_SCRATCH5                                */
 /* ========================================================================= */
-#define UVH_SCRATCH5 0x2d0200UL
-#define UVH_SCRATCH5_32 0x778
+#define UV1H_SCRATCH5 0x2d0200UL
+#define UV2H_SCRATCH5 0x2d0200UL
+#define UV3H_SCRATCH5 0x2d0200UL
+#define UV4H_SCRATCH5 0xb0200UL
+#define UVH_SCRATCH5 (							\
+	is_uv1_hub() ? UV1H_SCRATCH5 :					\
+	is_uv2_hub() ? UV2H_SCRATCH5 :					\
+	is_uv3_hub() ? UV3H_SCRATCH5 :					\
+	/*is_uv4_hub*/ UV4H_SCRATCH5)
+
+#define UV1H_SCRATCH5_32 0x778
+#define UV2H_SCRATCH5_32 0x778
+#define UV3H_SCRATCH5_32 0x778
+#define UV4H_SCRATCH5_32 0x798
+#define UVH_SCRATCH5_32 (						\
+	is_uv1_hub() ? UV1H_SCRATCH5_32 :				\
+	is_uv2_hub() ? UV2H_SCRATCH5_32 :				\
+	is_uv3_hub() ? UV3H_SCRATCH5_32 :				\
+	/*is_uv4_hub*/ UV4H_SCRATCH5_32)
 
 #define UVH_SCRATCH5_SCRATCH5_SHFT			0
 #define UVH_SCRATCH5_SCRATCH5_MASK			0xffffffffffffffffUL
 
+
 union uvh_scratch5_u {
 	unsigned long	v;
 	struct uvh_scratch5_s {
@@ -2625,14 +3625,39 @@ union uvh_scratch5_u {
 /* ========================================================================= */
 /*                            UVH_SCRATCH5_ALIAS                             */
 /* ========================================================================= */
-#define UVH_SCRATCH5_ALIAS 0x2d0208UL
-#define UVH_SCRATCH5_ALIAS_32 0x780
+#define UV1H_SCRATCH5_ALIAS 0x2d0208UL
+#define UV2H_SCRATCH5_ALIAS 0x2d0208UL
+#define UV3H_SCRATCH5_ALIAS 0x2d0208UL
+#define UV4H_SCRATCH5_ALIAS 0xb0208UL
+#define UVH_SCRATCH5_ALIAS (						\
+	is_uv1_hub() ? UV1H_SCRATCH5_ALIAS :				\
+	is_uv2_hub() ? UV2H_SCRATCH5_ALIAS :				\
+	is_uv3_hub() ? UV3H_SCRATCH5_ALIAS :				\
+	/*is_uv4_hub*/ UV4H_SCRATCH5_ALIAS)
+
+#define UV1H_SCRATCH5_ALIAS_32 0x780
+#define UV2H_SCRATCH5_ALIAS_32 0x780
+#define UV3H_SCRATCH5_ALIAS_32 0x780
+#define UV4H_SCRATCH5_ALIAS_32 0x7a0
+#define UVH_SCRATCH5_ALIAS_32 (						\
+	is_uv1_hub() ? UV1H_SCRATCH5_ALIAS_32 :				\
+	is_uv2_hub() ? UV2H_SCRATCH5_ALIAS_32 :				\
+	is_uv3_hub() ? UV3H_SCRATCH5_ALIAS_32 :				\
+	/*is_uv4_hub*/ UV4H_SCRATCH5_ALIAS_32)
 
 
 /* ========================================================================= */
 /*                           UVH_SCRATCH5_ALIAS_2                            */
 /* ========================================================================= */
-#define UVH_SCRATCH5_ALIAS_2 0x2d0210UL
+#define UV1H_SCRATCH5_ALIAS_2 0x2d0210UL
+#define UV2H_SCRATCH5_ALIAS_2 0x2d0210UL
+#define UV3H_SCRATCH5_ALIAS_2 0x2d0210UL
+#define UV4H_SCRATCH5_ALIAS_2 0xb0210UL
+#define UVH_SCRATCH5_ALIAS_2 (						\
+	is_uv1_hub() ? UV1H_SCRATCH5_ALIAS_2 :				\
+	is_uv2_hub() ? UV2H_SCRATCH5_ALIAS_2 :				\
+	is_uv3_hub() ? UV3H_SCRATCH5_ALIAS_2 :				\
+	/*is_uv4_hub*/ UV4H_SCRATCH5_ALIAS_2)
 #define UVH_SCRATCH5_ALIAS_2_32 0x788
 
 
@@ -2640,76 +3665,255 @@ union uvh_scratch5_u {
 /*                          UVXH_EVENT_OCCURRED2                             */
 /* ========================================================================= */
 #define UVXH_EVENT_OCCURRED2 0x70100UL
-#define UVXH_EVENT_OCCURRED2_32 0xb68
 
-#define UVXH_EVENT_OCCURRED2_RTC_0_SHFT			0
-#define UVXH_EVENT_OCCURRED2_RTC_1_SHFT			1
-#define UVXH_EVENT_OCCURRED2_RTC_2_SHFT			2
-#define UVXH_EVENT_OCCURRED2_RTC_3_SHFT			3
-#define UVXH_EVENT_OCCURRED2_RTC_4_SHFT			4
-#define UVXH_EVENT_OCCURRED2_RTC_5_SHFT			5
-#define UVXH_EVENT_OCCURRED2_RTC_6_SHFT			6
-#define UVXH_EVENT_OCCURRED2_RTC_7_SHFT			7
-#define UVXH_EVENT_OCCURRED2_RTC_8_SHFT			8
-#define UVXH_EVENT_OCCURRED2_RTC_9_SHFT			9
-#define UVXH_EVENT_OCCURRED2_RTC_10_SHFT		10
-#define UVXH_EVENT_OCCURRED2_RTC_11_SHFT		11
-#define UVXH_EVENT_OCCURRED2_RTC_12_SHFT		12
-#define UVXH_EVENT_OCCURRED2_RTC_13_SHFT		13
-#define UVXH_EVENT_OCCURRED2_RTC_14_SHFT		14
-#define UVXH_EVENT_OCCURRED2_RTC_15_SHFT		15
-#define UVXH_EVENT_OCCURRED2_RTC_16_SHFT		16
-#define UVXH_EVENT_OCCURRED2_RTC_17_SHFT		17
-#define UVXH_EVENT_OCCURRED2_RTC_18_SHFT		18
-#define UVXH_EVENT_OCCURRED2_RTC_19_SHFT		19
-#define UVXH_EVENT_OCCURRED2_RTC_20_SHFT		20
-#define UVXH_EVENT_OCCURRED2_RTC_21_SHFT		21
-#define UVXH_EVENT_OCCURRED2_RTC_22_SHFT		22
-#define UVXH_EVENT_OCCURRED2_RTC_23_SHFT		23
-#define UVXH_EVENT_OCCURRED2_RTC_24_SHFT		24
-#define UVXH_EVENT_OCCURRED2_RTC_25_SHFT		25
-#define UVXH_EVENT_OCCURRED2_RTC_26_SHFT		26
-#define UVXH_EVENT_OCCURRED2_RTC_27_SHFT		27
-#define UVXH_EVENT_OCCURRED2_RTC_28_SHFT		28
-#define UVXH_EVENT_OCCURRED2_RTC_29_SHFT		29
-#define UVXH_EVENT_OCCURRED2_RTC_30_SHFT		30
-#define UVXH_EVENT_OCCURRED2_RTC_31_SHFT		31
-#define UVXH_EVENT_OCCURRED2_RTC_0_MASK			0x0000000000000001UL
-#define UVXH_EVENT_OCCURRED2_RTC_1_MASK			0x0000000000000002UL
-#define UVXH_EVENT_OCCURRED2_RTC_2_MASK			0x0000000000000004UL
-#define UVXH_EVENT_OCCURRED2_RTC_3_MASK			0x0000000000000008UL
-#define UVXH_EVENT_OCCURRED2_RTC_4_MASK			0x0000000000000010UL
-#define UVXH_EVENT_OCCURRED2_RTC_5_MASK			0x0000000000000020UL
-#define UVXH_EVENT_OCCURRED2_RTC_6_MASK			0x0000000000000040UL
-#define UVXH_EVENT_OCCURRED2_RTC_7_MASK			0x0000000000000080UL
-#define UVXH_EVENT_OCCURRED2_RTC_8_MASK			0x0000000000000100UL
-#define UVXH_EVENT_OCCURRED2_RTC_9_MASK			0x0000000000000200UL
-#define UVXH_EVENT_OCCURRED2_RTC_10_MASK		0x0000000000000400UL
-#define UVXH_EVENT_OCCURRED2_RTC_11_MASK		0x0000000000000800UL
-#define UVXH_EVENT_OCCURRED2_RTC_12_MASK		0x0000000000001000UL
-#define UVXH_EVENT_OCCURRED2_RTC_13_MASK		0x0000000000002000UL
-#define UVXH_EVENT_OCCURRED2_RTC_14_MASK		0x0000000000004000UL
-#define UVXH_EVENT_OCCURRED2_RTC_15_MASK		0x0000000000008000UL
-#define UVXH_EVENT_OCCURRED2_RTC_16_MASK		0x0000000000010000UL
-#define UVXH_EVENT_OCCURRED2_RTC_17_MASK		0x0000000000020000UL
-#define UVXH_EVENT_OCCURRED2_RTC_18_MASK		0x0000000000040000UL
-#define UVXH_EVENT_OCCURRED2_RTC_19_MASK		0x0000000000080000UL
-#define UVXH_EVENT_OCCURRED2_RTC_20_MASK		0x0000000000100000UL
-#define UVXH_EVENT_OCCURRED2_RTC_21_MASK		0x0000000000200000UL
-#define UVXH_EVENT_OCCURRED2_RTC_22_MASK		0x0000000000400000UL
-#define UVXH_EVENT_OCCURRED2_RTC_23_MASK		0x0000000000800000UL
-#define UVXH_EVENT_OCCURRED2_RTC_24_MASK		0x0000000001000000UL
-#define UVXH_EVENT_OCCURRED2_RTC_25_MASK		0x0000000002000000UL
-#define UVXH_EVENT_OCCURRED2_RTC_26_MASK		0x0000000004000000UL
-#define UVXH_EVENT_OCCURRED2_RTC_27_MASK		0x0000000008000000UL
-#define UVXH_EVENT_OCCURRED2_RTC_28_MASK		0x0000000010000000UL
-#define UVXH_EVENT_OCCURRED2_RTC_29_MASK		0x0000000020000000UL
-#define UVXH_EVENT_OCCURRED2_RTC_30_MASK		0x0000000040000000UL
-#define UVXH_EVENT_OCCURRED2_RTC_31_MASK		0x0000000080000000UL
+#define UV2H_EVENT_OCCURRED2_32 0xb68
+#define UV3H_EVENT_OCCURRED2_32 0xb68
+#define UV4H_EVENT_OCCURRED2_32 0x608
+#define UVH_EVENT_OCCURRED2_32 (					\
+	is_uv2_hub() ? UV2H_EVENT_OCCURRED2_32 :			\
+	is_uv3_hub() ? UV3H_EVENT_OCCURRED2_32 :			\
+	/*is_uv4_hub*/ UV4H_EVENT_OCCURRED2_32)
 
-union uvxh_event_occurred2_u {
+
+#define UV2H_EVENT_OCCURRED2_RTC_0_SHFT			0
+#define UV2H_EVENT_OCCURRED2_RTC_1_SHFT			1
+#define UV2H_EVENT_OCCURRED2_RTC_2_SHFT			2
+#define UV2H_EVENT_OCCURRED2_RTC_3_SHFT			3
+#define UV2H_EVENT_OCCURRED2_RTC_4_SHFT			4
+#define UV2H_EVENT_OCCURRED2_RTC_5_SHFT			5
+#define UV2H_EVENT_OCCURRED2_RTC_6_SHFT			6
+#define UV2H_EVENT_OCCURRED2_RTC_7_SHFT			7
+#define UV2H_EVENT_OCCURRED2_RTC_8_SHFT			8
+#define UV2H_EVENT_OCCURRED2_RTC_9_SHFT			9
+#define UV2H_EVENT_OCCURRED2_RTC_10_SHFT		10
+#define UV2H_EVENT_OCCURRED2_RTC_11_SHFT		11
+#define UV2H_EVENT_OCCURRED2_RTC_12_SHFT		12
+#define UV2H_EVENT_OCCURRED2_RTC_13_SHFT		13
+#define UV2H_EVENT_OCCURRED2_RTC_14_SHFT		14
+#define UV2H_EVENT_OCCURRED2_RTC_15_SHFT		15
+#define UV2H_EVENT_OCCURRED2_RTC_16_SHFT		16
+#define UV2H_EVENT_OCCURRED2_RTC_17_SHFT		17
+#define UV2H_EVENT_OCCURRED2_RTC_18_SHFT		18
+#define UV2H_EVENT_OCCURRED2_RTC_19_SHFT		19
+#define UV2H_EVENT_OCCURRED2_RTC_20_SHFT		20
+#define UV2H_EVENT_OCCURRED2_RTC_21_SHFT		21
+#define UV2H_EVENT_OCCURRED2_RTC_22_SHFT		22
+#define UV2H_EVENT_OCCURRED2_RTC_23_SHFT		23
+#define UV2H_EVENT_OCCURRED2_RTC_24_SHFT		24
+#define UV2H_EVENT_OCCURRED2_RTC_25_SHFT		25
+#define UV2H_EVENT_OCCURRED2_RTC_26_SHFT		26
+#define UV2H_EVENT_OCCURRED2_RTC_27_SHFT		27
+#define UV2H_EVENT_OCCURRED2_RTC_28_SHFT		28
+#define UV2H_EVENT_OCCURRED2_RTC_29_SHFT		29
+#define UV2H_EVENT_OCCURRED2_RTC_30_SHFT		30
+#define UV2H_EVENT_OCCURRED2_RTC_31_SHFT		31
+#define UV2H_EVENT_OCCURRED2_RTC_0_MASK			0x0000000000000001UL
+#define UV2H_EVENT_OCCURRED2_RTC_1_MASK			0x0000000000000002UL
+#define UV2H_EVENT_OCCURRED2_RTC_2_MASK			0x0000000000000004UL
+#define UV2H_EVENT_OCCURRED2_RTC_3_MASK			0x0000000000000008UL
+#define UV2H_EVENT_OCCURRED2_RTC_4_MASK			0x0000000000000010UL
+#define UV2H_EVENT_OCCURRED2_RTC_5_MASK			0x0000000000000020UL
+#define UV2H_EVENT_OCCURRED2_RTC_6_MASK			0x0000000000000040UL
+#define UV2H_EVENT_OCCURRED2_RTC_7_MASK			0x0000000000000080UL
+#define UV2H_EVENT_OCCURRED2_RTC_8_MASK			0x0000000000000100UL
+#define UV2H_EVENT_OCCURRED2_RTC_9_MASK			0x0000000000000200UL
+#define UV2H_EVENT_OCCURRED2_RTC_10_MASK		0x0000000000000400UL
+#define UV2H_EVENT_OCCURRED2_RTC_11_MASK		0x0000000000000800UL
+#define UV2H_EVENT_OCCURRED2_RTC_12_MASK		0x0000000000001000UL
+#define UV2H_EVENT_OCCURRED2_RTC_13_MASK		0x0000000000002000UL
+#define UV2H_EVENT_OCCURRED2_RTC_14_MASK		0x0000000000004000UL
+#define UV2H_EVENT_OCCURRED2_RTC_15_MASK		0x0000000000008000UL
+#define UV2H_EVENT_OCCURRED2_RTC_16_MASK		0x0000000000010000UL
+#define UV2H_EVENT_OCCURRED2_RTC_17_MASK		0x0000000000020000UL
+#define UV2H_EVENT_OCCURRED2_RTC_18_MASK		0x0000000000040000UL
+#define UV2H_EVENT_OCCURRED2_RTC_19_MASK		0x0000000000080000UL
+#define UV2H_EVENT_OCCURRED2_RTC_20_MASK		0x0000000000100000UL
+#define UV2H_EVENT_OCCURRED2_RTC_21_MASK		0x0000000000200000UL
+#define UV2H_EVENT_OCCURRED2_RTC_22_MASK		0x0000000000400000UL
+#define UV2H_EVENT_OCCURRED2_RTC_23_MASK		0x0000000000800000UL
+#define UV2H_EVENT_OCCURRED2_RTC_24_MASK		0x0000000001000000UL
+#define UV2H_EVENT_OCCURRED2_RTC_25_MASK		0x0000000002000000UL
+#define UV2H_EVENT_OCCURRED2_RTC_26_MASK		0x0000000004000000UL
+#define UV2H_EVENT_OCCURRED2_RTC_27_MASK		0x0000000008000000UL
+#define UV2H_EVENT_OCCURRED2_RTC_28_MASK		0x0000000010000000UL
+#define UV2H_EVENT_OCCURRED2_RTC_29_MASK		0x0000000020000000UL
+#define UV2H_EVENT_OCCURRED2_RTC_30_MASK		0x0000000040000000UL
+#define UV2H_EVENT_OCCURRED2_RTC_31_MASK		0x0000000080000000UL
+
+#define UV3H_EVENT_OCCURRED2_RTC_0_SHFT			0
+#define UV3H_EVENT_OCCURRED2_RTC_1_SHFT			1
+#define UV3H_EVENT_OCCURRED2_RTC_2_SHFT			2
+#define UV3H_EVENT_OCCURRED2_RTC_3_SHFT			3
+#define UV3H_EVENT_OCCURRED2_RTC_4_SHFT			4
+#define UV3H_EVENT_OCCURRED2_RTC_5_SHFT			5
+#define UV3H_EVENT_OCCURRED2_RTC_6_SHFT			6
+#define UV3H_EVENT_OCCURRED2_RTC_7_SHFT			7
+#define UV3H_EVENT_OCCURRED2_RTC_8_SHFT			8
+#define UV3H_EVENT_OCCURRED2_RTC_9_SHFT			9
+#define UV3H_EVENT_OCCURRED2_RTC_10_SHFT		10
+#define UV3H_EVENT_OCCURRED2_RTC_11_SHFT		11
+#define UV3H_EVENT_OCCURRED2_RTC_12_SHFT		12
+#define UV3H_EVENT_OCCURRED2_RTC_13_SHFT		13
+#define UV3H_EVENT_OCCURRED2_RTC_14_SHFT		14
+#define UV3H_EVENT_OCCURRED2_RTC_15_SHFT		15
+#define UV3H_EVENT_OCCURRED2_RTC_16_SHFT		16
+#define UV3H_EVENT_OCCURRED2_RTC_17_SHFT		17
+#define UV3H_EVENT_OCCURRED2_RTC_18_SHFT		18
+#define UV3H_EVENT_OCCURRED2_RTC_19_SHFT		19
+#define UV3H_EVENT_OCCURRED2_RTC_20_SHFT		20
+#define UV3H_EVENT_OCCURRED2_RTC_21_SHFT		21
+#define UV3H_EVENT_OCCURRED2_RTC_22_SHFT		22
+#define UV3H_EVENT_OCCURRED2_RTC_23_SHFT		23
+#define UV3H_EVENT_OCCURRED2_RTC_24_SHFT		24
+#define UV3H_EVENT_OCCURRED2_RTC_25_SHFT		25
+#define UV3H_EVENT_OCCURRED2_RTC_26_SHFT		26
+#define UV3H_EVENT_OCCURRED2_RTC_27_SHFT		27
+#define UV3H_EVENT_OCCURRED2_RTC_28_SHFT		28
+#define UV3H_EVENT_OCCURRED2_RTC_29_SHFT		29
+#define UV3H_EVENT_OCCURRED2_RTC_30_SHFT		30
+#define UV3H_EVENT_OCCURRED2_RTC_31_SHFT		31
+#define UV3H_EVENT_OCCURRED2_RTC_0_MASK			0x0000000000000001UL
+#define UV3H_EVENT_OCCURRED2_RTC_1_MASK			0x0000000000000002UL
+#define UV3H_EVENT_OCCURRED2_RTC_2_MASK			0x0000000000000004UL
+#define UV3H_EVENT_OCCURRED2_RTC_3_MASK			0x0000000000000008UL
+#define UV3H_EVENT_OCCURRED2_RTC_4_MASK			0x0000000000000010UL
+#define UV3H_EVENT_OCCURRED2_RTC_5_MASK			0x0000000000000020UL
+#define UV3H_EVENT_OCCURRED2_RTC_6_MASK			0x0000000000000040UL
+#define UV3H_EVENT_OCCURRED2_RTC_7_MASK			0x0000000000000080UL
+#define UV3H_EVENT_OCCURRED2_RTC_8_MASK			0x0000000000000100UL
+#define UV3H_EVENT_OCCURRED2_RTC_9_MASK			0x0000000000000200UL
+#define UV3H_EVENT_OCCURRED2_RTC_10_MASK		0x0000000000000400UL
+#define UV3H_EVENT_OCCURRED2_RTC_11_MASK		0x0000000000000800UL
+#define UV3H_EVENT_OCCURRED2_RTC_12_MASK		0x0000000000001000UL
+#define UV3H_EVENT_OCCURRED2_RTC_13_MASK		0x0000000000002000UL
+#define UV3H_EVENT_OCCURRED2_RTC_14_MASK		0x0000000000004000UL
+#define UV3H_EVENT_OCCURRED2_RTC_15_MASK		0x0000000000008000UL
+#define UV3H_EVENT_OCCURRED2_RTC_16_MASK		0x0000000000010000UL
+#define UV3H_EVENT_OCCURRED2_RTC_17_MASK		0x0000000000020000UL
+#define UV3H_EVENT_OCCURRED2_RTC_18_MASK		0x0000000000040000UL
+#define UV3H_EVENT_OCCURRED2_RTC_19_MASK		0x0000000000080000UL
+#define UV3H_EVENT_OCCURRED2_RTC_20_MASK		0x0000000000100000UL
+#define UV3H_EVENT_OCCURRED2_RTC_21_MASK		0x0000000000200000UL
+#define UV3H_EVENT_OCCURRED2_RTC_22_MASK		0x0000000000400000UL
+#define UV3H_EVENT_OCCURRED2_RTC_23_MASK		0x0000000000800000UL
+#define UV3H_EVENT_OCCURRED2_RTC_24_MASK		0x0000000001000000UL
+#define UV3H_EVENT_OCCURRED2_RTC_25_MASK		0x0000000002000000UL
+#define UV3H_EVENT_OCCURRED2_RTC_26_MASK		0x0000000004000000UL
+#define UV3H_EVENT_OCCURRED2_RTC_27_MASK		0x0000000008000000UL
+#define UV3H_EVENT_OCCURRED2_RTC_28_MASK		0x0000000010000000UL
+#define UV3H_EVENT_OCCURRED2_RTC_29_MASK		0x0000000020000000UL
+#define UV3H_EVENT_OCCURRED2_RTC_30_MASK		0x0000000040000000UL
+#define UV3H_EVENT_OCCURRED2_RTC_31_MASK		0x0000000080000000UL
+
+#define UV4H_EVENT_OCCURRED2_MESSAGE_ACCELERATOR_INT0_SHFT 0
+#define UV4H_EVENT_OCCURRED2_MESSAGE_ACCELERATOR_INT1_SHFT 1
+#define UV4H_EVENT_OCCURRED2_MESSAGE_ACCELERATOR_INT2_SHFT 2
+#define UV4H_EVENT_OCCURRED2_MESSAGE_ACCELERATOR_INT3_SHFT 3
+#define UV4H_EVENT_OCCURRED2_MESSAGE_ACCELERATOR_INT4_SHFT 4
+#define UV4H_EVENT_OCCURRED2_MESSAGE_ACCELERATOR_INT5_SHFT 5
+#define UV4H_EVENT_OCCURRED2_MESSAGE_ACCELERATOR_INT6_SHFT 6
+#define UV4H_EVENT_OCCURRED2_MESSAGE_ACCELERATOR_INT7_SHFT 7
+#define UV4H_EVENT_OCCURRED2_MESSAGE_ACCELERATOR_INT8_SHFT 8
+#define UV4H_EVENT_OCCURRED2_MESSAGE_ACCELERATOR_INT9_SHFT 9
+#define UV4H_EVENT_OCCURRED2_MESSAGE_ACCELERATOR_INT10_SHFT 10
+#define UV4H_EVENT_OCCURRED2_MESSAGE_ACCELERATOR_INT11_SHFT 11
+#define UV4H_EVENT_OCCURRED2_MESSAGE_ACCELERATOR_INT12_SHFT 12
+#define UV4H_EVENT_OCCURRED2_MESSAGE_ACCELERATOR_INT13_SHFT 13
+#define UV4H_EVENT_OCCURRED2_MESSAGE_ACCELERATOR_INT14_SHFT 14
+#define UV4H_EVENT_OCCURRED2_MESSAGE_ACCELERATOR_INT15_SHFT 15
+#define UV4H_EVENT_OCCURRED2_RTC_INTERVAL_INT_SHFT	16
+#define UV4H_EVENT_OCCURRED2_BAU_DASHBOARD_INT_SHFT	17
+#define UV4H_EVENT_OCCURRED2_RTC_0_SHFT			18
+#define UV4H_EVENT_OCCURRED2_RTC_1_SHFT			19
+#define UV4H_EVENT_OCCURRED2_RTC_2_SHFT			20
+#define UV4H_EVENT_OCCURRED2_RTC_3_SHFT			21
+#define UV4H_EVENT_OCCURRED2_RTC_4_SHFT			22
+#define UV4H_EVENT_OCCURRED2_RTC_5_SHFT			23
+#define UV4H_EVENT_OCCURRED2_RTC_6_SHFT			24
+#define UV4H_EVENT_OCCURRED2_RTC_7_SHFT			25
+#define UV4H_EVENT_OCCURRED2_RTC_8_SHFT			26
+#define UV4H_EVENT_OCCURRED2_RTC_9_SHFT			27
+#define UV4H_EVENT_OCCURRED2_RTC_10_SHFT		28
+#define UV4H_EVENT_OCCURRED2_RTC_11_SHFT		29
+#define UV4H_EVENT_OCCURRED2_RTC_12_SHFT		30
+#define UV4H_EVENT_OCCURRED2_RTC_13_SHFT		31
+#define UV4H_EVENT_OCCURRED2_RTC_14_SHFT		32
+#define UV4H_EVENT_OCCURRED2_RTC_15_SHFT		33
+#define UV4H_EVENT_OCCURRED2_RTC_16_SHFT		34
+#define UV4H_EVENT_OCCURRED2_RTC_17_SHFT		35
+#define UV4H_EVENT_OCCURRED2_RTC_18_SHFT		36
+#define UV4H_EVENT_OCCURRED2_RTC_19_SHFT		37
+#define UV4H_EVENT_OCCURRED2_RTC_20_SHFT		38
+#define UV4H_EVENT_OCCURRED2_RTC_21_SHFT		39
+#define UV4H_EVENT_OCCURRED2_RTC_22_SHFT		40
+#define UV4H_EVENT_OCCURRED2_RTC_23_SHFT		41
+#define UV4H_EVENT_OCCURRED2_RTC_24_SHFT		42
+#define UV4H_EVENT_OCCURRED2_RTC_25_SHFT		43
+#define UV4H_EVENT_OCCURRED2_RTC_26_SHFT		44
+#define UV4H_EVENT_OCCURRED2_RTC_27_SHFT		45
+#define UV4H_EVENT_OCCURRED2_RTC_28_SHFT		46
+#define UV4H_EVENT_OCCURRED2_RTC_29_SHFT		47
+#define UV4H_EVENT_OCCURRED2_RTC_30_SHFT		48
+#define UV4H_EVENT_OCCURRED2_RTC_31_SHFT		49
+#define UV4H_EVENT_OCCURRED2_MESSAGE_ACCELERATOR_INT0_MASK 0x0000000000000001UL
+#define UV4H_EVENT_OCCURRED2_MESSAGE_ACCELERATOR_INT1_MASK 0x0000000000000002UL
+#define UV4H_EVENT_OCCURRED2_MESSAGE_ACCELERATOR_INT2_MASK 0x0000000000000004UL
+#define UV4H_EVENT_OCCURRED2_MESSAGE_ACCELERATOR_INT3_MASK 0x0000000000000008UL
+#define UV4H_EVENT_OCCURRED2_MESSAGE_ACCELERATOR_INT4_MASK 0x0000000000000010UL
+#define UV4H_EVENT_OCCURRED2_MESSAGE_ACCELERATOR_INT5_MASK 0x0000000000000020UL
+#define UV4H_EVENT_OCCURRED2_MESSAGE_ACCELERATOR_INT6_MASK 0x0000000000000040UL
+#define UV4H_EVENT_OCCURRED2_MESSAGE_ACCELERATOR_INT7_MASK 0x0000000000000080UL
+#define UV4H_EVENT_OCCURRED2_MESSAGE_ACCELERATOR_INT8_MASK 0x0000000000000100UL
+#define UV4H_EVENT_OCCURRED2_MESSAGE_ACCELERATOR_INT9_MASK 0x0000000000000200UL
+#define UV4H_EVENT_OCCURRED2_MESSAGE_ACCELERATOR_INT10_MASK 0x0000000000000400UL
+#define UV4H_EVENT_OCCURRED2_MESSAGE_ACCELERATOR_INT11_MASK 0x0000000000000800UL
+#define UV4H_EVENT_OCCURRED2_MESSAGE_ACCELERATOR_INT12_MASK 0x0000000000001000UL
+#define UV4H_EVENT_OCCURRED2_MESSAGE_ACCELERATOR_INT13_MASK 0x0000000000002000UL
+#define UV4H_EVENT_OCCURRED2_MESSAGE_ACCELERATOR_INT14_MASK 0x0000000000004000UL
+#define UV4H_EVENT_OCCURRED2_MESSAGE_ACCELERATOR_INT15_MASK 0x0000000000008000UL
+#define UV4H_EVENT_OCCURRED2_RTC_INTERVAL_INT_MASK	0x0000000000010000UL
+#define UV4H_EVENT_OCCURRED2_BAU_DASHBOARD_INT_MASK	0x0000000000020000UL
+#define UV4H_EVENT_OCCURRED2_RTC_0_MASK			0x0000000000040000UL
+#define UV4H_EVENT_OCCURRED2_RTC_1_MASK			0x0000000000080000UL
+#define UV4H_EVENT_OCCURRED2_RTC_2_MASK			0x0000000000100000UL
+#define UV4H_EVENT_OCCURRED2_RTC_3_MASK			0x0000000000200000UL
+#define UV4H_EVENT_OCCURRED2_RTC_4_MASK			0x0000000000400000UL
+#define UV4H_EVENT_OCCURRED2_RTC_5_MASK			0x0000000000800000UL
+#define UV4H_EVENT_OCCURRED2_RTC_6_MASK			0x0000000001000000UL
+#define UV4H_EVENT_OCCURRED2_RTC_7_MASK			0x0000000002000000UL
+#define UV4H_EVENT_OCCURRED2_RTC_8_MASK			0x0000000004000000UL
+#define UV4H_EVENT_OCCURRED2_RTC_9_MASK			0x0000000008000000UL
+#define UV4H_EVENT_OCCURRED2_RTC_10_MASK		0x0000000010000000UL
+#define UV4H_EVENT_OCCURRED2_RTC_11_MASK		0x0000000020000000UL
+#define UV4H_EVENT_OCCURRED2_RTC_12_MASK		0x0000000040000000UL
+#define UV4H_EVENT_OCCURRED2_RTC_13_MASK		0x0000000080000000UL
+#define UV4H_EVENT_OCCURRED2_RTC_14_MASK		0x0000000100000000UL
+#define UV4H_EVENT_OCCURRED2_RTC_15_MASK		0x0000000200000000UL
+#define UV4H_EVENT_OCCURRED2_RTC_16_MASK		0x0000000400000000UL
+#define UV4H_EVENT_OCCURRED2_RTC_17_MASK		0x0000000800000000UL
+#define UV4H_EVENT_OCCURRED2_RTC_18_MASK		0x0000001000000000UL
+#define UV4H_EVENT_OCCURRED2_RTC_19_MASK		0x0000002000000000UL
+#define UV4H_EVENT_OCCURRED2_RTC_20_MASK		0x0000004000000000UL
+#define UV4H_EVENT_OCCURRED2_RTC_21_MASK		0x0000008000000000UL
+#define UV4H_EVENT_OCCURRED2_RTC_22_MASK		0x0000010000000000UL
+#define UV4H_EVENT_OCCURRED2_RTC_23_MASK		0x0000020000000000UL
+#define UV4H_EVENT_OCCURRED2_RTC_24_MASK		0x0000040000000000UL
+#define UV4H_EVENT_OCCURRED2_RTC_25_MASK		0x0000080000000000UL
+#define UV4H_EVENT_OCCURRED2_RTC_26_MASK		0x0000100000000000UL
+#define UV4H_EVENT_OCCURRED2_RTC_27_MASK		0x0000200000000000UL
+#define UV4H_EVENT_OCCURRED2_RTC_28_MASK		0x0000400000000000UL
+#define UV4H_EVENT_OCCURRED2_RTC_29_MASK		0x0000800000000000UL
+#define UV4H_EVENT_OCCURRED2_RTC_30_MASK		0x0001000000000000UL
+#define UV4H_EVENT_OCCURRED2_RTC_31_MASK		0x0002000000000000UL
+
+#define UVXH_EVENT_OCCURRED2_RTC_1_MASK (				\
+	is_uv2_hub() ? UV2H_EVENT_OCCURRED2_RTC_1_MASK :		\
+	is_uv3_hub() ? UV3H_EVENT_OCCURRED2_RTC_1_MASK :		\
+	/*is_uv4_hub*/ UV4H_EVENT_OCCURRED2_RTC_1_MASK)
+
+union uvh_event_occurred2_u {
 	unsigned long	v;
-	struct uvxh_event_occurred2_s {
+	struct uv2h_event_occurred2_s {
 		unsigned long	rtc_0:1;			/* RW */
 		unsigned long	rtc_1:1;			/* RW */
 		unsigned long	rtc_2:1;			/* RW */
@@ -2743,25 +3947,129 @@ union uvxh_event_occurred2_u {
 		unsigned long	rtc_30:1;			/* RW */
 		unsigned long	rtc_31:1;			/* RW */
 		unsigned long	rsvd_32_63:32;
-	} sx;
+	} s2;
+	struct uv3h_event_occurred2_s {
+		unsigned long	rtc_0:1;			/* RW */
+		unsigned long	rtc_1:1;			/* RW */
+		unsigned long	rtc_2:1;			/* RW */
+		unsigned long	rtc_3:1;			/* RW */
+		unsigned long	rtc_4:1;			/* RW */
+		unsigned long	rtc_5:1;			/* RW */
+		unsigned long	rtc_6:1;			/* RW */
+		unsigned long	rtc_7:1;			/* RW */
+		unsigned long	rtc_8:1;			/* RW */
+		unsigned long	rtc_9:1;			/* RW */
+		unsigned long	rtc_10:1;			/* RW */
+		unsigned long	rtc_11:1;			/* RW */
+		unsigned long	rtc_12:1;			/* RW */
+		unsigned long	rtc_13:1;			/* RW */
+		unsigned long	rtc_14:1;			/* RW */
+		unsigned long	rtc_15:1;			/* RW */
+		unsigned long	rtc_16:1;			/* RW */
+		unsigned long	rtc_17:1;			/* RW */
+		unsigned long	rtc_18:1;			/* RW */
+		unsigned long	rtc_19:1;			/* RW */
+		unsigned long	rtc_20:1;			/* RW */
+		unsigned long	rtc_21:1;			/* RW */
+		unsigned long	rtc_22:1;			/* RW */
+		unsigned long	rtc_23:1;			/* RW */
+		unsigned long	rtc_24:1;			/* RW */
+		unsigned long	rtc_25:1;			/* RW */
+		unsigned long	rtc_26:1;			/* RW */
+		unsigned long	rtc_27:1;			/* RW */
+		unsigned long	rtc_28:1;			/* RW */
+		unsigned long	rtc_29:1;			/* RW */
+		unsigned long	rtc_30:1;			/* RW */
+		unsigned long	rtc_31:1;			/* RW */
+		unsigned long	rsvd_32_63:32;
+	} s3;
+	struct uv4h_event_occurred2_s {
+		unsigned long	message_accelerator_int0:1;	/* RW */
+		unsigned long	message_accelerator_int1:1;	/* RW */
+		unsigned long	message_accelerator_int2:1;	/* RW */
+		unsigned long	message_accelerator_int3:1;	/* RW */
+		unsigned long	message_accelerator_int4:1;	/* RW */
+		unsigned long	message_accelerator_int5:1;	/* RW */
+		unsigned long	message_accelerator_int6:1;	/* RW */
+		unsigned long	message_accelerator_int7:1;	/* RW */
+		unsigned long	message_accelerator_int8:1;	/* RW */
+		unsigned long	message_accelerator_int9:1;	/* RW */
+		unsigned long	message_accelerator_int10:1;	/* RW */
+		unsigned long	message_accelerator_int11:1;	/* RW */
+		unsigned long	message_accelerator_int12:1;	/* RW */
+		unsigned long	message_accelerator_int13:1;	/* RW */
+		unsigned long	message_accelerator_int14:1;	/* RW */
+		unsigned long	message_accelerator_int15:1;	/* RW */
+		unsigned long	rtc_interval_int:1;		/* RW */
+		unsigned long	bau_dashboard_int:1;		/* RW */
+		unsigned long	rtc_0:1;			/* RW */
+		unsigned long	rtc_1:1;			/* RW */
+		unsigned long	rtc_2:1;			/* RW */
+		unsigned long	rtc_3:1;			/* RW */
+		unsigned long	rtc_4:1;			/* RW */
+		unsigned long	rtc_5:1;			/* RW */
+		unsigned long	rtc_6:1;			/* RW */
+		unsigned long	rtc_7:1;			/* RW */
+		unsigned long	rtc_8:1;			/* RW */
+		unsigned long	rtc_9:1;			/* RW */
+		unsigned long	rtc_10:1;			/* RW */
+		unsigned long	rtc_11:1;			/* RW */
+		unsigned long	rtc_12:1;			/* RW */
+		unsigned long	rtc_13:1;			/* RW */
+		unsigned long	rtc_14:1;			/* RW */
+		unsigned long	rtc_15:1;			/* RW */
+		unsigned long	rtc_16:1;			/* RW */
+		unsigned long	rtc_17:1;			/* RW */
+		unsigned long	rtc_18:1;			/* RW */
+		unsigned long	rtc_19:1;			/* RW */
+		unsigned long	rtc_20:1;			/* RW */
+		unsigned long	rtc_21:1;			/* RW */
+		unsigned long	rtc_22:1;			/* RW */
+		unsigned long	rtc_23:1;			/* RW */
+		unsigned long	rtc_24:1;			/* RW */
+		unsigned long	rtc_25:1;			/* RW */
+		unsigned long	rtc_26:1;			/* RW */
+		unsigned long	rtc_27:1;			/* RW */
+		unsigned long	rtc_28:1;			/* RW */
+		unsigned long	rtc_29:1;			/* RW */
+		unsigned long	rtc_30:1;			/* RW */
+		unsigned long	rtc_31:1;			/* RW */
+		unsigned long	rsvd_50_63:14;
+	} s4;
 };
 
 /* ========================================================================= */
 /*                       UVXH_EVENT_OCCURRED2_ALIAS                          */
 /* ========================================================================= */
 #define UVXH_EVENT_OCCURRED2_ALIAS 0x70108UL
-#define UVXH_EVENT_OCCURRED2_ALIAS_32 0xb70
+
+#define UV2H_EVENT_OCCURRED2_ALIAS_32 0xb70
+#define UV3H_EVENT_OCCURRED2_ALIAS_32 0xb70
+#define UV4H_EVENT_OCCURRED2_ALIAS_32 0x610
+#define UVH_EVENT_OCCURRED2_ALIAS_32 (					\
+	is_uv2_hub() ? UV2H_EVENT_OCCURRED2_ALIAS_32 :			\
+	is_uv3_hub() ? UV3H_EVENT_OCCURRED2_ALIAS_32 :			\
+	/*is_uv4_hub*/ UV4H_EVENT_OCCURRED2_ALIAS_32)
 
 
 /* ========================================================================= */
 /*                   UVXH_LB_BAU_SB_ACTIVATION_STATUS_2                      */
 /* ========================================================================= */
-#define UVXH_LB_BAU_SB_ACTIVATION_STATUS_2 0x320130UL
 #define UV2H_LB_BAU_SB_ACTIVATION_STATUS_2 0x320130UL
 #define UV3H_LB_BAU_SB_ACTIVATION_STATUS_2 0x320130UL
-#define UVXH_LB_BAU_SB_ACTIVATION_STATUS_2_32 0x9f0
-#define UV2H_LB_BAU_SB_ACTIVATION_STATUS_2_32 0x320130UL
-#define UV3H_LB_BAU_SB_ACTIVATION_STATUS_2_32 0x320130UL
+#define UV4H_LB_BAU_SB_ACTIVATION_STATUS_2 0xc8130UL
+#define UVH_LB_BAU_SB_ACTIVATION_STATUS_2 (				\
+	is_uv2_hub() ? UV2H_LB_BAU_SB_ACTIVATION_STATUS_2 :		\
+	is_uv3_hub() ? UV3H_LB_BAU_SB_ACTIVATION_STATUS_2 :		\
+	/*is_uv4_hub*/ UV4H_LB_BAU_SB_ACTIVATION_STATUS_2)
+
+#define UV2H_LB_BAU_SB_ACTIVATION_STATUS_2_32 0x9f0
+#define UV3H_LB_BAU_SB_ACTIVATION_STATUS_2_32 0x9f0
+#define UV4H_LB_BAU_SB_ACTIVATION_STATUS_2_32 0xa10
+#define UVH_LB_BAU_SB_ACTIVATION_STATUS_2_32 (				\
+	is_uv2_hub() ? UV2H_LB_BAU_SB_ACTIVATION_STATUS_2_32 :		\
+	is_uv3_hub() ? UV3H_LB_BAU_SB_ACTIVATION_STATUS_2_32 :		\
+	/*is_uv4_hub*/ UV4H_LB_BAU_SB_ACTIVATION_STATUS_2_32)
 
 #define UVXH_LB_BAU_SB_ACTIVATION_STATUS_2_AUX_ERROR_SHFT 0
 #define UVXH_LB_BAU_SB_ACTIVATION_STATUS_2_AUX_ERROR_MASK 0xffffffffffffffffUL
@@ -2772,6 +4080,10 @@ union uvxh_event_occurred2_u {
 #define UV3H_LB_BAU_SB_ACTIVATION_STATUS_2_AUX_ERROR_SHFT 0
 #define UV3H_LB_BAU_SB_ACTIVATION_STATUS_2_AUX_ERROR_MASK 0xffffffffffffffffUL
 
+#define UV4H_LB_BAU_SB_ACTIVATION_STATUS_2_AUX_ERROR_SHFT 0
+#define UV4H_LB_BAU_SB_ACTIVATION_STATUS_2_AUX_ERROR_MASK 0xffffffffffffffffUL
+
+
 union uvxh_lb_bau_sb_activation_status_2_u {
 	unsigned long	v;
 	struct uvxh_lb_bau_sb_activation_status_2_s {
@@ -2783,6 +4095,9 @@ union uvxh_lb_bau_sb_activation_status_2
 	struct uv3h_lb_bau_sb_activation_status_2_s {
 		unsigned long	aux_error:64;			/* RW */
 	} s3;
+	struct uv4h_lb_bau_sb_activation_status_2_s {
+		unsigned long	aux_error:64;			/* RW */
+	} s4;
 };
 
 /* ========================================================================= */
@@ -2823,26 +4138,6 @@ union uv3h_gr0_gam_gr_config_u {
 };
 
 /* ========================================================================= */
-/*                          UV3H_GR1_GAM_GR_CONFIG                           */
-/* ========================================================================= */
-#define UV3H_GR1_GAM_GR_CONFIG				0x1000028UL
-
-#define UV3H_GR1_GAM_GR_CONFIG_M_SKT_SHFT		0
-#define UV3H_GR1_GAM_GR_CONFIG_SUBSPACE_SHFT		10
-#define UV3H_GR1_GAM_GR_CONFIG_M_SKT_MASK		0x000000000000003fUL
-#define UV3H_GR1_GAM_GR_CONFIG_SUBSPACE_MASK		0x0000000000000400UL
-
-union uv3h_gr1_gam_gr_config_u {
-	unsigned long	v;
-	struct uv3h_gr1_gam_gr_config_s {
-		unsigned long	m_skt:6;			/* RW */
-		unsigned long	undef_6_9:4;			/* Undefined */
-		unsigned long	subspace:1;			/* RW */
-		unsigned long	reserved:53;
-	} s3;
-};
-
-/* ========================================================================= */
 /*                   UV3H_RH_GAM_MMIOH_OVERLAY_CONFIG0_MMR                   */
 /* ========================================================================= */
 #define UV3H_RH_GAM_MMIOH_OVERLAY_CONFIG0_MMR		0x1603000UL
@@ -2924,5 +4219,67 @@ union uv3h_rh_gam_mmioh_redirect_config1
 	} s3;
 };
 
+/* ========================================================================= */
+/*                       UV4H_LB_PROC_INTD_QUEUE_FIRST                       */
+/* ========================================================================= */
+#define UV4H_LB_PROC_INTD_QUEUE_FIRST			0xa4100UL
+
+#define UV4H_LB_PROC_INTD_QUEUE_FIRST_FIRST_PAYLOAD_ADDRESS_SHFT 6
+#define UV4H_LB_PROC_INTD_QUEUE_FIRST_FIRST_PAYLOAD_ADDRESS_MASK 0x00003fffffffffc0UL
+
+union uv4h_lb_proc_intd_queue_first_u {
+	unsigned long	v;
+	struct uv4h_lb_proc_intd_queue_first_s {
+		unsigned long	undef_0_5:6;			/* Undefined */
+		unsigned long	first_payload_address:40;	/* RW */
+	} s4;
+};
+
+/* ========================================================================= */
+/*                       UV4H_LB_PROC_INTD_QUEUE_LAST                        */
+/* ========================================================================= */
+#define UV4H_LB_PROC_INTD_QUEUE_LAST			0xa4108UL
+
+#define UV4H_LB_PROC_INTD_QUEUE_LAST_LAST_PAYLOAD_ADDRESS_SHFT 5
+#define UV4H_LB_PROC_INTD_QUEUE_LAST_LAST_PAYLOAD_ADDRESS_MASK 0x00003fffffffffe0UL
+
+union uv4h_lb_proc_intd_queue_last_u {
+	unsigned long	v;
+	struct uv4h_lb_proc_intd_queue_last_s {
+		unsigned long	undef_0_4:5;			/* Undefined */
+		unsigned long	last_payload_address:41;	/* RW */
+	} s4;
+};
+
+/* ========================================================================= */
+/*                     UV4H_LB_PROC_INTD_SOFT_ACK_CLEAR                      */
+/* ========================================================================= */
+#define UV4H_LB_PROC_INTD_SOFT_ACK_CLEAR		0xa4118UL
+
+#define UV4H_LB_PROC_INTD_SOFT_ACK_CLEAR_SOFT_ACK_PENDING_FLAGS_SHFT 0
+#define UV4H_LB_PROC_INTD_SOFT_ACK_CLEAR_SOFT_ACK_PENDING_FLAGS_MASK 0x00000000000000ffUL
+
+union uv4h_lb_proc_intd_soft_ack_clear_u {
+	unsigned long	v;
+	struct uv4h_lb_proc_intd_soft_ack_clear_s {
+		unsigned long	soft_ack_pending_flags:8;	/* WP */
+	} s4;
+};
+
+/* ========================================================================= */
+/*                    UV4H_LB_PROC_INTD_SOFT_ACK_PENDING                     */
+/* ========================================================================= */
+#define UV4H_LB_PROC_INTD_SOFT_ACK_PENDING		0xa4110UL
+
+#define UV4H_LB_PROC_INTD_SOFT_ACK_PENDING_SOFT_ACK_FLAGS_SHFT 0
+#define UV4H_LB_PROC_INTD_SOFT_ACK_PENDING_SOFT_ACK_FLAGS_MASK 0x00000000000000ffUL
+
+union uv4h_lb_proc_intd_soft_ack_pending_u {
+	unsigned long	v;
+	struct uv4h_lb_proc_intd_soft_ack_pending_s {
+		unsigned long	soft_ack_flags:8;		/* RW */
+	} s4;
+};
+
 
 #endif /* _ASM_X86_UV_UV_MMRS_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/x86_init.h linux-libre-4.7-gnu/arch/x86/include/asm/x86_init.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/x86_init.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/x86_init.h	2016-07-24 15:23:50.000000000 -0400
@@ -142,6 +142,44 @@ struct x86_cpuinit_ops {
 struct timespec;
 
 /**
+ * struct x86_legacy_devices - legacy x86 devices
+ *
+ * @pnpbios: this platform can have a PNPBIOS. If this is disabled the platform
+ * 	is known to never have a PNPBIOS.
+ *
+ * These are devices known to require LPC or ISA bus. The definition of legacy
+ * devices adheres to the ACPI 5.2.9.3 IA-PC Boot Architecture flag
+ * ACPI_FADT_LEGACY_DEVICES. These devices consist of user visible devices on
+ * the LPC or ISA bus. User visible devices are devices that have end-user
+ * accessible connectors (for example, LPT parallel port). Legacy devices on
+ * the LPC bus consist for example of serial and parallel ports, PS/2 keyboard
+ * / mouse, and the floppy disk controller. A system that lacks all known
+ * legacy devices can assume all devices can be detected exclusively via
+ * standard device enumeration mechanisms including the ACPI namespace.
+ *
+ * A system which has does not have ACPI_FADT_LEGACY_DEVICES enabled must not
+ * have any of the legacy devices enumerated below present.
+ */
+struct x86_legacy_devices {
+	int pnpbios;
+};
+
+/**
+ * struct x86_legacy_features - legacy x86 features
+ *
+ * @rtc: this device has a CMOS real-time clock present
+ * @ebda_search: it's safe to search for the EBDA signature in the hardware's
+ * 	low RAM
+ * @devices: legacy x86 devices, refer to struct x86_legacy_devices
+ * 	documentation for further details.
+ */
+struct x86_legacy_features {
+	int rtc;
+	int ebda_search;
+	struct x86_legacy_devices devices;
+};
+
+/**
  * struct x86_platform_ops - platform specific runtime functions
  * @calibrate_tsc:		calibrate TSC
  * @get_wallclock:		get time from HW clock like RTC etc.
@@ -152,6 +190,14 @@ struct timespec;
  * @save_sched_clock_state:	save state for sched_clock() on suspend
  * @restore_sched_clock_state:	restore state for sched_clock() on resume
  * @apic_post_init:		adjust apic if neeeded
+ * @legacy:			legacy features
+ * @set_legacy_features:	override legacy features. Use of this callback
+ * 				is highly discouraged. You should only need
+ * 				this if your hardware platform requires further
+ * 				custom fine tuning far beyong what may be
+ * 				possible in x86_early_init_platform_quirks() by
+ * 				only using the current x86_hardware_subarch
+ * 				semantics.
  */
 struct x86_platform_ops {
 	unsigned long (*calibrate_tsc)(void);
@@ -165,6 +211,8 @@ struct x86_platform_ops {
 	void (*save_sched_clock_state)(void);
 	void (*restore_sched_clock_state)(void);
 	void (*apic_post_init)(void);
+	struct x86_legacy_features legacy;
+	void (*set_legacy_features)(void);
 };
 
 struct pci_dev;
@@ -186,6 +234,8 @@ extern struct x86_cpuinit_ops x86_cpuini
 extern struct x86_platform_ops x86_platform;
 extern struct x86_msi_ops x86_msi;
 extern struct x86_io_apic_ops x86_io_apic_ops;
+
+extern void x86_early_init_platform_quirks(void);
 extern void x86_init_noop(void);
 extern void x86_init_uint_noop(unsigned int unused);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/xor_32.h linux-libre-4.7-gnu/arch/x86/include/asm/xor_32.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/xor_32.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/xor_32.h	2016-07-24 15:23:50.000000000 -0400
@@ -550,7 +550,7 @@ static struct xor_block_template xor_blo
 #define XOR_TRY_TEMPLATES				\
 do {							\
 	AVX_XOR_SPEED;					\
-	if (cpu_has_xmm) {				\
+	if (boot_cpu_has(X86_FEATURE_XMM)) {				\
 		xor_speed(&xor_block_pIII_sse);		\
 		xor_speed(&xor_block_sse_pf64);		\
 	} else if (boot_cpu_has(X86_FEATURE_MMX)) {	\
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/asm/xor_avx.h linux-libre-4.7-gnu/arch/x86/include/asm/xor_avx.h
--- linux-libre-4.6-gnu/arch/x86/include/asm/xor_avx.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/asm/xor_avx.h	2016-07-24 15:23:50.000000000 -0400
@@ -167,12 +167,12 @@ static struct xor_block_template xor_blo
 
 #define AVX_XOR_SPEED \
 do { \
-	if (cpu_has_avx && cpu_has_osxsave) \
+	if (boot_cpu_has(X86_FEATURE_AVX) && boot_cpu_has(X86_FEATURE_OSXSAVE)) \
 		xor_speed(&xor_block_avx); \
 } while (0)
 
 #define AVX_SELECT(FASTEST) \
-	(cpu_has_avx && cpu_has_osxsave ? &xor_block_avx : FASTEST)
+	(boot_cpu_has(X86_FEATURE_AVX) && boot_cpu_has(X86_FEATURE_OSXSAVE) ? &xor_block_avx : FASTEST)
 
 #else
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/uapi/asm/bootparam.h linux-libre-4.7-gnu/arch/x86/include/uapi/asm/bootparam.h
--- linux-libre-4.6-gnu/arch/x86/include/uapi/asm/bootparam.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/uapi/asm/bootparam.h	2016-07-24 15:23:50.000000000 -0400
@@ -157,7 +157,46 @@ struct boot_params {
 	__u8  _pad9[276];				/* 0xeec */
 } __attribute__((packed));
 
-enum {
+/**
+ * enum x86_hardware_subarch - x86 hardware subarchitecture
+ *
+ * The x86 hardware_subarch and hardware_subarch_data were added as of the x86
+ * boot protocol 2.07 to help distinguish and support custom x86 boot
+ * sequences. This enum represents accepted values for the x86
+ * hardware_subarch.  Custom x86 boot sequences (not X86_SUBARCH_PC) do not
+ * have or simply *cannot* make use of natural stubs like BIOS or EFI, the
+ * hardware_subarch can be used on the Linux entry path to revector to a
+ * subarchitecture stub when needed. This subarchitecture stub can be used to
+ * set up Linux boot parameters or for special care to account for nonstandard
+ * handling of page tables.
+ *
+ * These enums should only ever be used by x86 code, and the code that uses
+ * it should be well contained and compartamentalized.
+ *
+ * KVM and Xen HVM do not have a subarch as these are expected to follow
+ * standard x86 boot entries. If there is a genuine need for "hypervisor" type
+ * that should be considered separately in the future. Future guest types
+ * should seriously consider working with standard x86 boot stubs such as
+ * the BIOS or EFI boot stubs.
+ *
+ * WARNING: this enum is only used for legacy hacks, for platform features that
+ *	    are not easily enumerated or discoverable. You should not ever use
+ *	    this for new features.
+ *
+ * @X86_SUBARCH_PC: Should be used if the hardware is enumerable using standard
+ *	PC mechanisms (PCI, ACPI) and doesn't need a special boot flow.
+ * @X86_SUBARCH_LGUEST: Used for x86 hypervisor demo, lguest
+ * @X86_SUBARCH_XEN: Used for Xen guest types which follow the PV boot path,
+ * 	which start at asm startup_xen() entry point and later jump to the C
+ * 	xen_start_kernel() entry point. Both domU and dom0 type of guests are
+ * 	currently supportd through this PV boot path.
+ * @X86_SUBARCH_INTEL_MID: Used for Intel MID (Mobile Internet Device) platform
+ *	systems which do not have the PCI legacy interfaces.
+ * @X86_SUBARCH_CE4100: Used for Intel CE media processor (CE4100) SoC for
+ * 	for settop boxes and media devices, the use of a subarch for CE4100
+ * 	is more of a hack...
+ */
+enum x86_hardware_subarch {
 	X86_SUBARCH_PC = 0,
 	X86_SUBARCH_LGUEST,
 	X86_SUBARCH_XEN,
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/uapi/asm/kvm.h linux-libre-4.7-gnu/arch/x86/include/uapi/asm/kvm.h
--- linux-libre-4.6-gnu/arch/x86/include/uapi/asm/kvm.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/uapi/asm/kvm.h	2016-07-24 15:23:50.000000000 -0400
@@ -216,9 +216,9 @@ struct kvm_cpuid_entry2 {
 	__u32 padding[3];
 };
 
-#define KVM_CPUID_FLAG_SIGNIFCANT_INDEX		BIT(0)
-#define KVM_CPUID_FLAG_STATEFUL_FUNC		BIT(1)
-#define KVM_CPUID_FLAG_STATE_READ_NEXT		BIT(2)
+#define KVM_CPUID_FLAG_SIGNIFCANT_INDEX		(1 << 0)
+#define KVM_CPUID_FLAG_STATEFUL_FUNC		(1 << 1)
+#define KVM_CPUID_FLAG_STATE_READ_NEXT		(1 << 2)
 
 /* for KVM_SET_CPUID2 */
 struct kvm_cpuid2 {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/include/uapi/asm/svm.h linux-libre-4.7-gnu/arch/x86/include/uapi/asm/svm.h
--- linux-libre-4.6-gnu/arch/x86/include/uapi/asm/svm.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/include/uapi/asm/svm.h	2016-07-24 15:23:50.000000000 -0400
@@ -2,10 +2,12 @@
 #define _UAPI__SVM_H
 
 #define SVM_EXIT_READ_CR0      0x000
+#define SVM_EXIT_READ_CR2      0x002
 #define SVM_EXIT_READ_CR3      0x003
 #define SVM_EXIT_READ_CR4      0x004
 #define SVM_EXIT_READ_CR8      0x008
 #define SVM_EXIT_WRITE_CR0     0x010
+#define SVM_EXIT_WRITE_CR2     0x012
 #define SVM_EXIT_WRITE_CR3     0x013
 #define SVM_EXIT_WRITE_CR4     0x014
 #define SVM_EXIT_WRITE_CR8     0x018
@@ -73,15 +75,19 @@
 #define SVM_EXIT_MWAIT_COND    0x08c
 #define SVM_EXIT_XSETBV        0x08d
 #define SVM_EXIT_NPF           0x400
+#define SVM_EXIT_AVIC_INCOMPLETE_IPI		0x401
+#define SVM_EXIT_AVIC_UNACCELERATED_ACCESS	0x402
 
 #define SVM_EXIT_ERR           -1
 
 #define SVM_EXIT_REASONS \
 	{ SVM_EXIT_READ_CR0,    "read_cr0" }, \
+	{ SVM_EXIT_READ_CR2,    "read_cr2" }, \
 	{ SVM_EXIT_READ_CR3,    "read_cr3" }, \
 	{ SVM_EXIT_READ_CR4,    "read_cr4" }, \
 	{ SVM_EXIT_READ_CR8,    "read_cr8" }, \
 	{ SVM_EXIT_WRITE_CR0,   "write_cr0" }, \
+	{ SVM_EXIT_WRITE_CR2,   "write_cr2" }, \
 	{ SVM_EXIT_WRITE_CR3,   "write_cr3" }, \
 	{ SVM_EXIT_WRITE_CR4,   "write_cr4" }, \
 	{ SVM_EXIT_WRITE_CR8,   "write_cr8" }, \
@@ -89,32 +95,66 @@
 	{ SVM_EXIT_READ_DR1,    "read_dr1" }, \
 	{ SVM_EXIT_READ_DR2,    "read_dr2" }, \
 	{ SVM_EXIT_READ_DR3,    "read_dr3" }, \
+	{ SVM_EXIT_READ_DR4,    "read_dr4" }, \
+	{ SVM_EXIT_READ_DR5,    "read_dr5" }, \
+	{ SVM_EXIT_READ_DR6,    "read_dr6" }, \
+	{ SVM_EXIT_READ_DR7,    "read_dr7" }, \
 	{ SVM_EXIT_WRITE_DR0,   "write_dr0" }, \
 	{ SVM_EXIT_WRITE_DR1,   "write_dr1" }, \
 	{ SVM_EXIT_WRITE_DR2,   "write_dr2" }, \
 	{ SVM_EXIT_WRITE_DR3,   "write_dr3" }, \
+	{ SVM_EXIT_WRITE_DR4,   "write_dr4" }, \
 	{ SVM_EXIT_WRITE_DR5,   "write_dr5" }, \
+	{ SVM_EXIT_WRITE_DR6,   "write_dr6" }, \
 	{ SVM_EXIT_WRITE_DR7,   "write_dr7" }, \
+	{ SVM_EXIT_EXCP_BASE + DE_VECTOR,       "DE excp" }, \
 	{ SVM_EXIT_EXCP_BASE + DB_VECTOR,       "DB excp" }, \
 	{ SVM_EXIT_EXCP_BASE + BP_VECTOR,       "BP excp" }, \
+	{ SVM_EXIT_EXCP_BASE + OF_VECTOR,       "OF excp" }, \
+	{ SVM_EXIT_EXCP_BASE + BR_VECTOR,       "BR excp" }, \
 	{ SVM_EXIT_EXCP_BASE + UD_VECTOR,       "UD excp" }, \
-	{ SVM_EXIT_EXCP_BASE + PF_VECTOR,       "PF excp" }, \
 	{ SVM_EXIT_EXCP_BASE + NM_VECTOR,       "NM excp" }, \
+	{ SVM_EXIT_EXCP_BASE + DF_VECTOR,       "DF excp" }, \
+	{ SVM_EXIT_EXCP_BASE + TS_VECTOR,       "TS excp" }, \
+	{ SVM_EXIT_EXCP_BASE + NP_VECTOR,       "NP excp" }, \
+	{ SVM_EXIT_EXCP_BASE + SS_VECTOR,       "SS excp" }, \
+	{ SVM_EXIT_EXCP_BASE + GP_VECTOR,       "GP excp" }, \
+	{ SVM_EXIT_EXCP_BASE + PF_VECTOR,       "PF excp" }, \
+	{ SVM_EXIT_EXCP_BASE + MF_VECTOR,       "MF excp" }, \
 	{ SVM_EXIT_EXCP_BASE + AC_VECTOR,       "AC excp" }, \
 	{ SVM_EXIT_EXCP_BASE + MC_VECTOR,       "MC excp" }, \
+	{ SVM_EXIT_EXCP_BASE + XM_VECTOR,       "XF excp" }, \
 	{ SVM_EXIT_INTR,        "interrupt" }, \
 	{ SVM_EXIT_NMI,         "nmi" }, \
 	{ SVM_EXIT_SMI,         "smi" }, \
 	{ SVM_EXIT_INIT,        "init" }, \
 	{ SVM_EXIT_VINTR,       "vintr" }, \
+	{ SVM_EXIT_CR0_SEL_WRITE, "cr0_sel_write" }, \
+	{ SVM_EXIT_IDTR_READ,   "read_idtr" }, \
+	{ SVM_EXIT_GDTR_READ,   "read_gdtr" }, \
+	{ SVM_EXIT_LDTR_READ,   "read_ldtr" }, \
+	{ SVM_EXIT_TR_READ,     "read_rt" }, \
+	{ SVM_EXIT_IDTR_WRITE,  "write_idtr" }, \
+	{ SVM_EXIT_GDTR_WRITE,  "write_gdtr" }, \
+	{ SVM_EXIT_LDTR_WRITE,  "write_ldtr" }, \
+	{ SVM_EXIT_TR_WRITE,    "write_rt" }, \
+	{ SVM_EXIT_RDTSC,       "rdtsc" }, \
+	{ SVM_EXIT_RDPMC,       "rdpmc" }, \
+	{ SVM_EXIT_PUSHF,       "pushf" }, \
+	{ SVM_EXIT_POPF,        "popf" }, \
 	{ SVM_EXIT_CPUID,       "cpuid" }, \
+	{ SVM_EXIT_RSM,         "rsm" }, \
+	{ SVM_EXIT_IRET,        "iret" }, \
+	{ SVM_EXIT_SWINT,       "swint" }, \
 	{ SVM_EXIT_INVD,        "invd" }, \
+	{ SVM_EXIT_PAUSE,       "pause" }, \
 	{ SVM_EXIT_HLT,         "hlt" }, \
 	{ SVM_EXIT_INVLPG,      "invlpg" }, \
 	{ SVM_EXIT_INVLPGA,     "invlpga" }, \
 	{ SVM_EXIT_IOIO,        "io" }, \
 	{ SVM_EXIT_MSR,         "msr" }, \
 	{ SVM_EXIT_TASK_SWITCH, "task_switch" }, \
+	{ SVM_EXIT_FERR_FREEZE, "ferr_freeze" }, \
 	{ SVM_EXIT_SHUTDOWN,    "shutdown" }, \
 	{ SVM_EXIT_VMRUN,       "vmrun" }, \
 	{ SVM_EXIT_VMMCALL,     "hypercall" }, \
@@ -123,11 +163,16 @@
 	{ SVM_EXIT_STGI,        "stgi" }, \
 	{ SVM_EXIT_CLGI,        "clgi" }, \
 	{ SVM_EXIT_SKINIT,      "skinit" }, \
+	{ SVM_EXIT_RDTSCP,      "rdtscp" }, \
+	{ SVM_EXIT_ICEBP,       "icebp" }, \
 	{ SVM_EXIT_WBINVD,      "wbinvd" }, \
 	{ SVM_EXIT_MONITOR,     "monitor" }, \
 	{ SVM_EXIT_MWAIT,       "mwait" }, \
 	{ SVM_EXIT_XSETBV,      "xsetbv" }, \
-	{ SVM_EXIT_NPF,         "npf" }
+	{ SVM_EXIT_NPF,         "npf" }, \
+	{ SVM_EXIT_AVIC_INCOMPLETE_IPI,		"avic_incomplete_ipi" }, \
+	{ SVM_EXIT_AVIC_UNACCELERATED_ACCESS,   "avic_unaccelerated_access" }, \
+	{ SVM_EXIT_ERR,         "invalid_guest_state" }
 
 
 #endif /* _UAPI__SVM_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/Kconfig linux-libre-4.7-gnu/arch/x86/Kconfig
--- linux-libre-4.6-gnu/arch/x86/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -91,7 +91,7 @@ config X86
 	select HAVE_ARCH_SOFT_DIRTY		if X86_64
 	select HAVE_ARCH_TRACEHOOK
 	select HAVE_ARCH_TRANSPARENT_HUGEPAGE
-	select HAVE_BPF_JIT			if X86_64
+	select HAVE_EBPF_JIT			if X86_64
 	select HAVE_CC_STACKPROTECTOR
 	select HAVE_CMPXCHG_DOUBLE
 	select HAVE_CMPXCHG_LOCAL
@@ -105,6 +105,7 @@ config X86
 	select HAVE_DYNAMIC_FTRACE
 	select HAVE_DYNAMIC_FTRACE_WITH_REGS
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
+	select HAVE_EXIT_THREAD
 	select HAVE_FENTRY			if X86_64
 	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_FUNCTION_GRAPH_FP_TEST
@@ -130,6 +131,7 @@ config X86
 	select HAVE_MEMBLOCK
 	select HAVE_MEMBLOCK_NODE_MAP
 	select HAVE_MIXED_BREAKPOINTS_REGS
+	select HAVE_NMI
 	select HAVE_OPROFILE
 	select HAVE_OPTPROBES
 	select HAVE_PCSPKR_PLATFORM
@@ -164,10 +166,6 @@ config INSTRUCTION_DECODER
 	def_bool y
 	depends on KPROBES || PERF_EVENTS || UPROBES
 
-config PERF_EVENTS_INTEL_UNCORE
-	def_bool y
-	depends on PERF_EVENTS && CPU_SUP_INTEL && PCI
-
 config OUTPUT_FORMAT
 	string
 	default "elf32-i386" if X86_32
@@ -1046,6 +1044,8 @@ config X86_THERMAL_VECTOR
 	def_bool y
 	depends on X86_MCE_INTEL
 
+source "arch/x86/events/Kconfig"
+
 config X86_LEGACY_VM86
 	bool "Legacy VM86 support"
 	default n
@@ -1210,15 +1210,6 @@ config MICROCODE_OLD_INTERFACE
 	def_bool y
 	depends on MICROCODE
 
-config PERF_EVENTS_AMD_POWER
-	depends on PERF_EVENTS && CPU_SUP_AMD
-	tristate "AMD Processor Power Reporting Mechanism"
-	---help---
-	  Provide power reporting mechanism support for AMD processors.
-	  Currently, it leverages X86_FEATURE_ACC_POWER
-	  (CPUID Fn8000_0007_EDX[12]) interface to calculate the
-	  average power consumption on Family 15h processors.
-
 config X86_MSR
 	tristate "/dev/cpu/*/msr - Model-specific register support"
 	---help---
@@ -1932,54 +1923,38 @@ config RELOCATABLE
 	  (CONFIG_PHYSICAL_START) is used as the minimum location.
 
 config RANDOMIZE_BASE
-	bool "Randomize the address of the kernel image"
+	bool "Randomize the address of the kernel image (KASLR)"
 	depends on RELOCATABLE
 	default n
 	---help---
-	   Randomizes the physical and virtual address at which the
-	   kernel image is decompressed, as a security feature that
-	   deters exploit attempts relying on knowledge of the location
-	   of kernel internals.
-
-	   Entropy is generated using the RDRAND instruction if it is
-	   supported. If RDTSC is supported, it is used as well. If
-	   neither RDRAND nor RDTSC are supported, then randomness is
-	   read from the i8254 timer.
-
-	   The kernel will be offset by up to RANDOMIZE_BASE_MAX_OFFSET,
-	   and aligned according to PHYSICAL_ALIGN. Since the kernel is
-	   built using 2GiB addressing, and PHYSICAL_ALGIN must be at a
-	   minimum of 2MiB, only 10 bits of entropy is theoretically
-	   possible. At best, due to page table layouts, 64-bit can use
-	   9 bits of entropy and 32-bit uses 8 bits.
+	  In support of Kernel Address Space Layout Randomization (KASLR),
+	  this randomizes the physical address at which the kernel image
+	  is decompressed and the virtual address where the kernel
+	  image is mapped, as a security feature that deters exploit
+	  attempts relying on knowledge of the location of kernel
+	  code internals.
 
-	   If unsure, say N.
+	  The kernel physical and virtual address can be randomized
+	  from 16MB up to 1GB on 64-bit and 512MB on 32-bit. (Note that
+	  using RANDOMIZE_BASE reduces the memory space available to
+	  kernel modules from 1.5GB to 1GB.)
 
-config RANDOMIZE_BASE_MAX_OFFSET
-	hex "Maximum kASLR offset allowed" if EXPERT
-	depends on RANDOMIZE_BASE
-	range 0x0 0x20000000 if X86_32
-	default "0x20000000" if X86_32
-	range 0x0 0x40000000 if X86_64
-	default "0x40000000" if X86_64
-	---help---
-	  The lesser of RANDOMIZE_BASE_MAX_OFFSET and available physical
-	  memory is used to determine the maximal offset in bytes that will
-	  be applied to the kernel when kernel Address Space Layout
-	  Randomization (kASLR) is active. This must be a multiple of
-	  PHYSICAL_ALIGN.
+	  Entropy is generated using the RDRAND instruction if it is
+	  supported. If RDTSC is supported, its value is mixed into
+	  the entropy pool as well. If neither RDRAND nor RDTSC are
+	  supported, then entropy is read from the i8254 timer.
 
-	  On 32-bit this is limited to 512MiB by page table layouts. The
-	  default is 512MiB.
+	  Since the kernel is built using 2GB addressing, and
+	  PHYSICAL_ALIGN must be at a minimum of 2MB, only 10 bits of
+	  entropy is theoretically possible. Currently, with the
+	  default value for PHYSICAL_ALIGN and due to page table
+	  layouts, 64-bit uses 9 bits of entropy and 32-bit uses 8 bits.
 
-	  On 64-bit this is limited by how the kernel fixmap page table is
-	  positioned, so this cannot be larger than 1GiB currently. Without
-	  RANDOMIZE_BASE, there is a 512MiB to 1.5GiB split between kernel
-	  and modules. When RANDOMIZE_BASE_MAX_OFFSET is above 512MiB, the
-	  modules area will shrink to compensate, up to the current maximum
-	  1GiB to 1GiB split. The default is 1GiB.
+	  If CONFIG_HIBERNATE is also enabled, KASLR is disabled at boot
+	  time. To enable it, boot with "kaslr" on the kernel command
+	  line (which will also disable hibernation).
 
-	  If unsure, leave at the default value.
+	  If unsure, say N.
 
 # Relocation on x86 needs some additional build support
 config X86_NEED_RELOCS
@@ -2464,6 +2439,15 @@ config PCI_CNB20LE_QUIRK
 
 source "drivers/pci/Kconfig"
 
+config ISA_BUS
+	bool "ISA-style bus support on modern systems" if EXPERT
+	select ISA_BUS_API
+	help
+	  Enables ISA-style drivers on modern systems. This is necessary to
+	  support PC/104 devices on X86_64 platforms.
+
+	  If unsure, say N.
+
 # x86_64 have no ISA slots, but can have ISA-style DMA.
 config ISA_DMA_API
 	bool "ISA-style DMA support" if (X86_64 && EXPERT)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/acpi/boot.c linux-libre-4.7-gnu/arch/x86/kernel/acpi/boot.c
--- linux-libre-4.6-gnu/arch/x86/kernel/acpi/boot.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/acpi/boot.c	2016-07-24 15:23:50.000000000 -0400
@@ -136,7 +136,7 @@ static int __init acpi_parse_madt(struct
 {
 	struct acpi_table_madt *madt = NULL;
 
-	if (!cpu_has_apic)
+	if (!boot_cpu_has(X86_FEATURE_APIC))
 		return -EINVAL;
 
 	madt = (struct acpi_table_madt *)table;
@@ -445,7 +445,6 @@ static void __init acpi_sci_ioapic_setup
 		polarity = acpi_sci_flags & ACPI_MADT_POLARITY_MASK;
 
 	mp_override_legacy_irq(bus_irq, polarity, trigger, gsi);
-	acpi_penalize_sci_irq(bus_irq, trigger, polarity);
 
 	/*
 	 * stash over-ride to indicate we've been here
@@ -913,6 +912,15 @@ late_initcall(hpet_insert_resource);
 
 static int __init acpi_parse_fadt(struct acpi_table_header *table)
 {
+	if (!(acpi_gbl_FADT.boot_flags & ACPI_FADT_LEGACY_DEVICES)) {
+		pr_debug("ACPI: no legacy devices present\n");
+		x86_platform.legacy.devices.pnpbios = 0;
+	}
+
+	if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_CMOS_RTC) {
+		pr_debug("ACPI: not registering RTC platform device\n");
+		x86_platform.legacy.rtc = 0;
+	}
 
 #ifdef CONFIG_X86_PM_TIMER
 	/* detect the location of the ACPI PM Timer */
@@ -951,7 +959,7 @@ static int __init early_acpi_parse_madt_
 {
 	int count;
 
-	if (!cpu_has_apic)
+	if (!boot_cpu_has(X86_FEATURE_APIC))
 		return -ENODEV;
 
 	/*
@@ -979,7 +987,7 @@ static int __init acpi_parse_madt_lapic_
 	int ret;
 	struct acpi_subtable_proc madt_proc[2];
 
-	if (!cpu_has_apic)
+	if (!boot_cpu_has(X86_FEATURE_APIC))
 		return -ENODEV;
 
 	/*
@@ -1125,7 +1133,7 @@ static int __init acpi_parse_madt_ioapic
 	if (acpi_disabled || acpi_noirq)
 		return -ENODEV;
 
-	if (!cpu_has_apic)
+	if (!boot_cpu_has(X86_FEATURE_APIC))
 		return -ENODEV;
 
 	/*
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/alternative.c linux-libre-4.7-gnu/arch/x86/kernel/alternative.c
--- linux-libre-4.6-gnu/arch/x86/kernel/alternative.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/alternative.c	2016-07-24 15:23:50.000000000 -0400
@@ -11,6 +11,7 @@
 #include <linux/stop_machine.h>
 #include <linux/slab.h>
 #include <linux/kdebug.h>
+#include <asm/text-patching.h>
 #include <asm/alternative.h>
 #include <asm/sections.h>
 #include <asm/pgtable.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/amd_nb.c linux-libre-4.7-gnu/arch/x86/kernel/amd_nb.c
--- linux-libre-4.6-gnu/arch/x86/kernel/amd_nb.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/amd_nb.c	2016-07-24 15:23:50.000000000 -0400
@@ -71,8 +71,8 @@ int amd_cache_northbridges(void)
 	while ((misc = next_northbridge(misc, amd_nb_misc_ids)) != NULL)
 		i++;
 
-	if (i == 0)
-		return 0;
+	if (!i)
+		return -ENODEV;
 
 	nb = kzalloc(i * sizeof(struct amd_northbridge), GFP_KERNEL);
 	if (!nb)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/apic/apic.c linux-libre-4.7-gnu/arch/x86/kernel/apic/apic.c
--- linux-libre-4.6-gnu/arch/x86/kernel/apic/apic.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/apic/apic.c	2016-07-24 15:23:50.000000000 -0400
@@ -607,7 +607,7 @@ static void __init lapic_cal_handler(str
 	long tapic = apic_read(APIC_TMCCT);
 	unsigned long pm = acpi_pm_read_early();
 
-	if (cpu_has_tsc)
+	if (boot_cpu_has(X86_FEATURE_TSC))
 		tsc = rdtsc();
 
 	switch (lapic_cal_loops++) {
@@ -668,7 +668,7 @@ calibrate_by_pmtimer(long deltapm, long
 	*delta = (long)res;
 
 	/* Correct the tsc counter value */
-	if (cpu_has_tsc) {
+	if (boot_cpu_has(X86_FEATURE_TSC)) {
 		res = (((u64)(*deltatsc)) * pm_100ms);
 		do_div(res, deltapm);
 		apic_printk(APIC_VERBOSE, "TSC delta adjusted to "
@@ -760,7 +760,7 @@ static int __init calibrate_APIC_clock(v
 	apic_printk(APIC_VERBOSE, "..... calibration result: %u\n",
 		    lapic_timer_frequency);
 
-	if (cpu_has_tsc) {
+	if (boot_cpu_has(X86_FEATURE_TSC)) {
 		apic_printk(APIC_VERBOSE, "..... CPU clock speed is "
 			    "%ld.%04ld MHz.\n",
 			    (deltatsc / LAPIC_CAL_LOOPS) / (1000000 / HZ),
@@ -1085,7 +1085,7 @@ void lapic_shutdown(void)
 {
 	unsigned long flags;
 
-	if (!cpu_has_apic && !apic_from_smp_config())
+	if (!boot_cpu_has(X86_FEATURE_APIC) && !apic_from_smp_config())
 		return;
 
 	local_irq_save(flags);
@@ -1134,7 +1134,7 @@ void __init init_bsp_APIC(void)
 	 * Don't do the setup now if we have a SMP BIOS as the
 	 * through-I/O-APIC virtual wire mode might be active.
 	 */
-	if (smp_found_config || !cpu_has_apic)
+	if (smp_found_config || !boot_cpu_has(X86_FEATURE_APIC))
 		return;
 
 	/*
@@ -1227,7 +1227,7 @@ void setup_local_APIC(void)
 	unsigned long long tsc = 0, ntsc;
 	long long max_loops = cpu_khz ? cpu_khz : 1000000;
 
-	if (cpu_has_tsc)
+	if (boot_cpu_has(X86_FEATURE_TSC))
 		tsc = rdtsc();
 
 	if (disable_apic) {
@@ -1311,7 +1311,7 @@ void setup_local_APIC(void)
 			break;
 		}
 		if (queued) {
-			if (cpu_has_tsc && cpu_khz) {
+			if (boot_cpu_has(X86_FEATURE_TSC) && cpu_khz) {
 				ntsc = rdtsc();
 				max_loops = (cpu_khz << 10) - (ntsc - tsc);
 			} else
@@ -1445,7 +1445,7 @@ static void __x2apic_disable(void)
 {
 	u64 msr;
 
-	if (!cpu_has_apic)
+	if (!boot_cpu_has(X86_FEATURE_APIC))
 		return;
 
 	rdmsrl(MSR_IA32_APICBASE, msr);
@@ -1561,7 +1561,7 @@ void __init check_x2apic(void)
 		pr_info("x2apic: enabled by BIOS, switching to x2apic ops\n");
 		x2apic_mode = 1;
 		x2apic_state = X2APIC_ON;
-	} else if (!cpu_has_x2apic) {
+	} else if (!boot_cpu_has(X86_FEATURE_X2APIC)) {
 		x2apic_state = X2APIC_DISABLED;
 	}
 }
@@ -1632,7 +1632,7 @@ void __init enable_IR_x2apic(void)
  */
 static int __init detect_init_APIC(void)
 {
-	if (!cpu_has_apic) {
+	if (!boot_cpu_has(X86_FEATURE_APIC)) {
 		pr_info("No local APIC present\n");
 		return -1;
 	}
@@ -1711,14 +1711,14 @@ static int __init detect_init_APIC(void)
 		goto no_apic;
 	case X86_VENDOR_INTEL:
 		if (boot_cpu_data.x86 == 6 || boot_cpu_data.x86 == 15 ||
-		    (boot_cpu_data.x86 == 5 && cpu_has_apic))
+		    (boot_cpu_data.x86 == 5 && boot_cpu_has(X86_FEATURE_APIC)))
 			break;
 		goto no_apic;
 	default:
 		goto no_apic;
 	}
 
-	if (!cpu_has_apic) {
+	if (!boot_cpu_has(X86_FEATURE_APIC)) {
 		/*
 		 * Over-ride BIOS and try to enable the local APIC only if
 		 * "lapic" specified.
@@ -2233,19 +2233,19 @@ int __init APIC_init_uniprocessor(void)
 		return -1;
 	}
 #ifdef CONFIG_X86_64
-	if (!cpu_has_apic) {
+	if (!boot_cpu_has(X86_FEATURE_APIC)) {
 		disable_apic = 1;
 		pr_info("Apic disabled by BIOS\n");
 		return -1;
 	}
 #else
-	if (!smp_found_config && !cpu_has_apic)
+	if (!smp_found_config && !boot_cpu_has(X86_FEATURE_APIC))
 		return -1;
 
 	/*
 	 * Complain if the BIOS pretends there is one.
 	 */
-	if (!cpu_has_apic &&
+	if (!boot_cpu_has(X86_FEATURE_APIC) &&
 	    APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) {
 		pr_err("BIOS bug, local APIC 0x%x not detected!...\n",
 			boot_cpu_physical_apicid);
@@ -2426,7 +2426,7 @@ static void apic_pm_activate(void)
 static int __init init_lapic_sysfs(void)
 {
 	/* XXX: remove suspend/resume procs if !apic_pm_state.active? */
-	if (cpu_has_apic)
+	if (boot_cpu_has(X86_FEATURE_APIC))
 		register_syscore_ops(&lapic_syscore_ops);
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/apic/apic_noop.c linux-libre-4.7-gnu/arch/x86/kernel/apic/apic_noop.c
--- linux-libre-4.6-gnu/arch/x86/kernel/apic/apic_noop.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/apic/apic_noop.c	2016-07-24 15:23:50.000000000 -0400
@@ -100,13 +100,13 @@ static void noop_vector_allocation_domai
 
 static u32 noop_apic_read(u32 reg)
 {
-	WARN_ON_ONCE((cpu_has_apic && !disable_apic));
+	WARN_ON_ONCE(boot_cpu_has(X86_FEATURE_APIC) && !disable_apic);
 	return 0;
 }
 
 static void noop_apic_write(u32 reg, u32 v)
 {
-	WARN_ON_ONCE(cpu_has_apic && !disable_apic);
+	WARN_ON_ONCE(boot_cpu_has(X86_FEATURE_APIC) && !disable_apic);
 }
 
 struct apic apic_noop = {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/apic/hw_nmi.c linux-libre-4.7-gnu/arch/x86/kernel/apic/hw_nmi.c
--- linux-libre-4.6-gnu/arch/x86/kernel/apic/hw_nmi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/apic/hw_nmi.c	2016-07-24 15:23:50.000000000 -0400
@@ -18,7 +18,6 @@
 #include <linux/nmi.h>
 #include <linux/module.h>
 #include <linux/delay.h>
-#include <linux/seq_buf.h>
 
 #ifdef CONFIG_HARDLOCKUP_DETECTOR
 u64 hw_nmi_get_sample_period(int watchdog_thresh)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/apic/io_apic.c linux-libre-4.7-gnu/arch/x86/kernel/apic/io_apic.c
--- linux-libre-4.6-gnu/arch/x86/kernel/apic/io_apic.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/apic/io_apic.c	2016-07-24 15:23:50.000000000 -0400
@@ -1454,7 +1454,7 @@ void native_disable_io_apic(void)
 		ioapic_write_entry(ioapic_i8259.apic, ioapic_i8259.pin, entry);
 	}
 
-	if (cpu_has_apic || apic_from_smp_config())
+	if (boot_cpu_has(X86_FEATURE_APIC) || apic_from_smp_config())
 		disconnect_bsp_APIC(ioapic_i8259.pin != -1);
 }
 
@@ -2588,8 +2588,8 @@ static struct resource * __init ioapic_s
 		res[num].flags = IORESOURCE_MEM | IORESOURCE_BUSY;
 		snprintf(mem, IOAPIC_RESOURCE_NAME_SIZE, "IOAPIC %u", i);
 		mem += IOAPIC_RESOURCE_NAME_SIZE;
+		ioapics[i].iomem_res = &res[num];
 		num++;
-		ioapics[i].iomem_res = res;
 	}
 
 	ioapic_resources = res;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/apic/ipi.c linux-libre-4.7-gnu/arch/x86/kernel/apic/ipi.c
--- linux-libre-4.6-gnu/arch/x86/kernel/apic/ipi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/apic/ipi.c	2016-07-24 15:23:50.000000000 -0400
@@ -230,7 +230,7 @@ int safe_smp_processor_id(void)
 {
 	int apicid, cpuid;
 
-	if (!cpu_has_apic)
+	if (!boot_cpu_has(X86_FEATURE_APIC))
 		return 0;
 
 	apicid = hard_smp_processor_id();
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/apic/vector.c linux-libre-4.7-gnu/arch/x86/kernel/apic/vector.c
--- linux-libre-4.6-gnu/arch/x86/kernel/apic/vector.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/apic/vector.c	2016-07-24 15:23:50.000000000 -0400
@@ -944,7 +944,7 @@ static int __init print_ICs(void)
 	print_PIC();
 
 	/* don't print out if apic is not there */
-	if (!cpu_has_apic && !apic_from_smp_config())
+	if (!boot_cpu_has(X86_FEATURE_APIC) && !apic_from_smp_config())
 		return 0;
 
 	print_local_APICs(show_lapic);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/apic/x2apic_uv_x.c linux-libre-4.7-gnu/arch/x86/kernel/apic/x2apic_uv_x.c
--- linux-libre-4.6-gnu/arch/x86/kernel/apic/x2apic_uv_x.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/apic/x2apic_uv_x.c	2016-07-24 15:23:50.000000000 -0400
@@ -48,12 +48,35 @@ static u64 gru_start_paddr, gru_end_padd
 static u64 gru_dist_base, gru_first_node_paddr = -1LL, gru_last_node_paddr;
 static u64 gru_dist_lmask, gru_dist_umask;
 static union uvh_apicid uvh_apicid;
+
+/* info derived from CPUID */
+static struct {
+	unsigned int apicid_shift;
+	unsigned int apicid_mask;
+	unsigned int socketid_shift;	/* aka pnode_shift for UV1/2/3 */
+	unsigned int pnode_mask;
+	unsigned int gpa_shift;
+} uv_cpuid;
+
 int uv_min_hub_revision_id;
 EXPORT_SYMBOL_GPL(uv_min_hub_revision_id);
 unsigned int uv_apicid_hibits;
 EXPORT_SYMBOL_GPL(uv_apicid_hibits);
 
 static struct apic apic_x2apic_uv_x;
+static struct uv_hub_info_s uv_hub_info_node0;
+
+/* Set this to use hardware error handler instead of kernel panic */
+static int disable_uv_undefined_panic = 1;
+unsigned long uv_undefined(char *str)
+{
+	if (likely(!disable_uv_undefined_panic))
+		panic("UV: error: undefined MMR: %s\n", str);
+	else
+		pr_crit("UV: error: undefined MMR: %s\n", str);
+	return ~0ul;	/* cause a machine fault  */
+}
+EXPORT_SYMBOL(uv_undefined);
 
 static unsigned long __init uv_early_read_mmr(unsigned long addr)
 {
@@ -108,21 +131,71 @@ static int __init early_get_pnodeid(void
 	case UV3_HUB_PART_NUMBER_X:
 		uv_min_hub_revision_id += UV3_HUB_REVISION_BASE;
 		break;
+	case UV4_HUB_PART_NUMBER:
+		uv_min_hub_revision_id += UV4_HUB_REVISION_BASE - 1;
+		break;
 	}
 
 	uv_hub_info->hub_revision = uv_min_hub_revision_id;
-	pnode = (node_id.s.node_id >> 1) & ((1 << m_n_config.s.n_skt) - 1);
+	uv_cpuid.pnode_mask = (1 << m_n_config.s.n_skt) - 1;
+	pnode = (node_id.s.node_id >> 1) & uv_cpuid.pnode_mask;
+	uv_cpuid.gpa_shift = 46;	/* default unless changed */
+
+	pr_info("UV: rev:%d part#:%x nodeid:%04x n_skt:%d pnmsk:%x pn:%x\n",
+		node_id.s.revision, node_id.s.part_number, node_id.s.node_id,
+		m_n_config.s.n_skt, uv_cpuid.pnode_mask, pnode);
 	return pnode;
 }
 
-static void __init early_get_apic_pnode_shift(void)
+/* [copied from arch/x86/kernel/cpu/topology.c:detect_extended_topology()] */
+#define SMT_LEVEL	0	/* leaf 0xb SMT level */
+#define INVALID_TYPE	0	/* leaf 0xb sub-leaf types */
+#define SMT_TYPE	1
+#define CORE_TYPE	2
+#define LEAFB_SUBTYPE(ecx)		(((ecx) >> 8) & 0xff)
+#define BITS_SHIFT_NEXT_LEVEL(eax)	((eax) & 0x1f)
+
+static void set_x2apic_bits(void)
 {
-	uvh_apicid.v = uv_early_read_mmr(UVH_APICID);
-	if (!uvh_apicid.v)
-		/*
-		 * Old bios, use default value
-		 */
-		uvh_apicid.s.pnode_shift = UV_APIC_PNODE_SHIFT;
+	unsigned int eax, ebx, ecx, edx, sub_index;
+	unsigned int sid_shift;
+
+	cpuid(0, &eax, &ebx, &ecx, &edx);
+	if (eax < 0xb) {
+		pr_info("UV: CPU does not have CPUID.11\n");
+		return;
+	}
+	cpuid_count(0xb, SMT_LEVEL, &eax, &ebx, &ecx, &edx);
+	if (ebx == 0 || (LEAFB_SUBTYPE(ecx) != SMT_TYPE)) {
+		pr_info("UV: CPUID.11 not implemented\n");
+		return;
+	}
+	sid_shift = BITS_SHIFT_NEXT_LEVEL(eax);
+	sub_index = 1;
+	do {
+		cpuid_count(0xb, sub_index, &eax, &ebx, &ecx, &edx);
+		if (LEAFB_SUBTYPE(ecx) == CORE_TYPE) {
+			sid_shift = BITS_SHIFT_NEXT_LEVEL(eax);
+			break;
+		}
+		sub_index++;
+	} while (LEAFB_SUBTYPE(ecx) != INVALID_TYPE);
+	uv_cpuid.apicid_shift = 0;
+	uv_cpuid.apicid_mask = (~(-1 << sid_shift));
+	uv_cpuid.socketid_shift = sid_shift;
+}
+
+static void __init early_get_apic_socketid_shift(void)
+{
+	if (is_uv2_hub() || is_uv3_hub())
+		uvh_apicid.v = uv_early_read_mmr(UVH_APICID);
+
+	set_x2apic_bits();
+
+	pr_info("UV: apicid_shift:%d apicid_mask:0x%x\n",
+		uv_cpuid.apicid_shift, uv_cpuid.apicid_mask);
+	pr_info("UV: socketid_shift:%d pnode_mask:0x%x\n",
+		uv_cpuid.socketid_shift, uv_cpuid.pnode_mask);
 }
 
 /*
@@ -150,13 +223,18 @@ static int __init uv_acpi_madt_oem_check
 	if (strncmp(oem_id, "SGI", 3) != 0)
 		return 0;
 
+	/* Setup early hub type field in uv_hub_info for Node 0 */
+	uv_cpu_info->p_uv_hub_info = &uv_hub_info_node0;
+
 	/*
 	 * Determine UV arch type.
 	 *   SGI: UV100/1000
 	 *   SGI2: UV2000/3000
 	 *   SGI3: UV300 (truncated to 4 chars because of different varieties)
+	 *   SGI4: UV400 (truncated to 4 chars because of different varieties)
 	 */
 	uv_hub_info->hub_revision =
+		!strncmp(oem_id, "SGI4", 4) ? UV4_HUB_REVISION_BASE :
 		!strncmp(oem_id, "SGI3", 4) ? UV3_HUB_REVISION_BASE :
 		!strcmp(oem_id, "SGI2") ? UV2_HUB_REVISION_BASE :
 		!strcmp(oem_id, "SGI") ? UV1_HUB_REVISION_BASE : 0;
@@ -165,7 +243,7 @@ static int __init uv_acpi_madt_oem_check
 		goto badbios;
 
 	pnodeid = early_get_pnodeid();
-	early_get_apic_pnode_shift();
+	early_get_apic_socketid_shift();
 	x86_platform.is_untracked_pat_range =  uv_is_untracked_pat_range;
 	x86_platform.nmi_init = uv_nmi_init;
 
@@ -211,17 +289,11 @@ int is_uv_system(void)
 }
 EXPORT_SYMBOL_GPL(is_uv_system);
 
-DEFINE_PER_CPU(struct uv_hub_info_s, __uv_hub_info);
-EXPORT_PER_CPU_SYMBOL_GPL(__uv_hub_info);
-
-struct uv_blade_info *uv_blade_info;
-EXPORT_SYMBOL_GPL(uv_blade_info);
-
-short *uv_node_to_blade;
-EXPORT_SYMBOL_GPL(uv_node_to_blade);
+void **__uv_hub_info_list;
+EXPORT_SYMBOL_GPL(__uv_hub_info_list);
 
-short *uv_cpu_to_blade;
-EXPORT_SYMBOL_GPL(uv_cpu_to_blade);
+DEFINE_PER_CPU(struct uv_cpu_info_s, __uv_cpu_info);
+EXPORT_PER_CPU_SYMBOL_GPL(__uv_cpu_info);
 
 short uv_possible_blades;
 EXPORT_SYMBOL_GPL(uv_possible_blades);
@@ -229,6 +301,115 @@ EXPORT_SYMBOL_GPL(uv_possible_blades);
 unsigned long sn_rtc_cycles_per_second;
 EXPORT_SYMBOL(sn_rtc_cycles_per_second);
 
+/* the following values are used for the per node hub info struct */
+static __initdata unsigned short *_node_to_pnode;
+static __initdata unsigned short _min_socket, _max_socket;
+static __initdata unsigned short _min_pnode, _max_pnode, _gr_table_len;
+static __initdata struct uv_gam_range_entry *uv_gre_table;
+static __initdata struct uv_gam_parameters *uv_gp_table;
+static __initdata unsigned short *_socket_to_node;
+static __initdata unsigned short *_socket_to_pnode;
+static __initdata unsigned short *_pnode_to_socket;
+static __initdata struct uv_gam_range_s *_gr_table;
+#define	SOCK_EMPTY	((unsigned short)~0)
+
+extern int uv_hub_info_version(void)
+{
+	return UV_HUB_INFO_VERSION;
+}
+EXPORT_SYMBOL(uv_hub_info_version);
+
+/* Build GAM range lookup table */
+static __init void build_uv_gr_table(void)
+{
+	struct uv_gam_range_entry *gre = uv_gre_table;
+	struct uv_gam_range_s *grt;
+	unsigned long last_limit = 0, ram_limit = 0;
+	int bytes, i, sid, lsid = -1;
+
+	if (!gre)
+		return;
+
+	bytes = _gr_table_len * sizeof(struct uv_gam_range_s);
+	grt = kzalloc(bytes, GFP_KERNEL);
+	BUG_ON(!grt);
+	_gr_table = grt;
+
+	for (; gre->type != UV_GAM_RANGE_TYPE_UNUSED; gre++) {
+		if (gre->type == UV_GAM_RANGE_TYPE_HOLE) {
+			if (!ram_limit) {   /* mark hole between ram/non-ram */
+				ram_limit = last_limit;
+				last_limit = gre->limit;
+				lsid++;
+				continue;
+			}
+			last_limit = gre->limit;
+			pr_info("UV: extra hole in GAM RE table @%d\n",
+				(int)(gre - uv_gre_table));
+			continue;
+		}
+		if (_max_socket < gre->sockid) {
+			pr_err("UV: GAM table sockid(%d) too large(>%d) @%d\n",
+				gre->sockid, _max_socket,
+				(int)(gre - uv_gre_table));
+			continue;
+		}
+		sid = gre->sockid - _min_socket;
+		if (lsid < sid) {		/* new range */
+			grt = &_gr_table[sid];
+			grt->base = lsid;
+			grt->nasid = gre->nasid;
+			grt->limit = last_limit = gre->limit;
+			lsid = sid;
+			continue;
+		}
+		if (lsid == sid && !ram_limit) {	/* update range */
+			if (grt->limit == last_limit) {	/* .. if contiguous */
+				grt->limit = last_limit = gre->limit;
+				continue;
+			}
+		}
+		if (!ram_limit) {		/* non-contiguous ram range */
+			grt++;
+			grt->base = sid - 1;
+			grt->nasid = gre->nasid;
+			grt->limit = last_limit = gre->limit;
+			continue;
+		}
+		grt++;				/* non-contiguous/non-ram */
+		grt->base = grt - _gr_table;	/* base is this entry */
+		grt->nasid = gre->nasid;
+		grt->limit = last_limit = gre->limit;
+		lsid++;
+	}
+
+	/* shorten table if possible */
+	grt++;
+	i = grt - _gr_table;
+	if (i < _gr_table_len) {
+		void *ret;
+
+		bytes = i * sizeof(struct uv_gam_range_s);
+		ret = krealloc(_gr_table, bytes, GFP_KERNEL);
+		if (ret) {
+			_gr_table = ret;
+			_gr_table_len = i;
+		}
+	}
+
+	/* display resultant gam range table */
+	for (i = 0, grt = _gr_table; i < _gr_table_len; i++, grt++) {
+		int gb = grt->base;
+		unsigned long start = gb < 0 ?  0 :
+			(unsigned long)_gr_table[gb].limit << UV_GAM_RANGE_SHFT;
+		unsigned long end =
+			(unsigned long)grt->limit << UV_GAM_RANGE_SHFT;
+
+		pr_info("UV: GAM Range %2d %04x 0x%013lx-0x%013lx (%d)\n",
+			i, grt->nasid, start, end, gb);
+	}
+}
+
 static int uv_wakeup_secondary(int phys_apicid, unsigned long start_rip)
 {
 	unsigned long val;
@@ -355,7 +536,6 @@ static unsigned long set_apic_id(unsigne
 
 static unsigned int uv_read_apic_id(void)
 {
-
 	return x2apic_get_apic_id(apic_read(APIC_ID));
 }
 
@@ -430,58 +610,38 @@ static void set_x2apic_extra_bits(int pn
 	__this_cpu_write(x2apic_extra_bits, pnode << uvh_apicid.s.pnode_shift);
 }
 
-/*
- * Called on boot cpu.
- */
-static __init int boot_pnode_to_blade(int pnode)
-{
-	int blade;
-
-	for (blade = 0; blade < uv_num_possible_blades(); blade++)
-		if (pnode == uv_blade_info[blade].pnode)
-			return blade;
-	BUG();
-}
-
-struct redir_addr {
-	unsigned long redirect;
-	unsigned long alias;
-};
-
+#define	UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_LENGTH	3
 #define DEST_SHIFT UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR_DEST_BASE_SHFT
 
-static __initdata struct redir_addr redir_addrs[] = {
-	{UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR, UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR},
-	{UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR, UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR},
-	{UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR, UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR},
-};
-
-static unsigned char get_n_lshift(int m_val)
-{
-	union uv3h_gr0_gam_gr_config_u m_gr_config;
-
-	if (is_uv1_hub())
-		return m_val;
-
-	if (is_uv2_hub())
-		return m_val == 40 ? 40 : 39;
-
-	m_gr_config.v = uv_read_local_mmr(UV3H_GR0_GAM_GR_CONFIG);
-	return m_gr_config.s3.m_skt;
-}
-
 static __init void get_lowmem_redirect(unsigned long *base, unsigned long *size)
 {
 	union uvh_rh_gam_alias210_overlay_config_2_mmr_u alias;
 	union uvh_rh_gam_alias210_redirect_config_2_mmr_u redirect;
+	unsigned long m_redirect;
+	unsigned long m_overlay;
 	int i;
 
-	for (i = 0; i < ARRAY_SIZE(redir_addrs); i++) {
-		alias.v = uv_read_local_mmr(redir_addrs[i].alias);
+	for (i = 0; i < UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_LENGTH; i++) {
+		switch (i) {
+		case 0:
+			m_redirect = UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR;
+			m_overlay = UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_0_MMR;
+			break;
+		case 1:
+			m_redirect = UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR;
+			m_overlay = UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_1_MMR;
+			break;
+		case 2:
+			m_redirect = UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR;
+			m_overlay = UVH_RH_GAM_ALIAS210_OVERLAY_CONFIG_2_MMR;
+			break;
+		}
+		alias.v = uv_read_local_mmr(m_overlay);
 		if (alias.s.enable && alias.s.base == 0) {
 			*size = (1UL << alias.s.m_alias);
-			redirect.v = uv_read_local_mmr(redir_addrs[i].redirect);
-			*base = (unsigned long)redirect.s.dest_base << DEST_SHIFT;
+			redirect.v = uv_read_local_mmr(m_redirect);
+			*base = (unsigned long)redirect.s.dest_base
+							<< DEST_SHIFT;
 			return;
 		}
 	}
@@ -544,6 +704,8 @@ static __init void map_gru_high(int max_
 {
 	union uvh_rh_gam_gru_overlay_config_mmr_u gru;
 	int shift = UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_SHFT;
+	unsigned long mask = UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_MASK;
+	unsigned long base;
 
 	gru.v = uv_read_local_mmr(UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR);
 	if (!gru.s.enable) {
@@ -555,8 +717,9 @@ static __init void map_gru_high(int max_
 		map_gru_distributed(gru.v);
 		return;
 	}
-	map_high("GRU", gru.s.base, shift, shift, max_pnode, map_wb);
-	gru_start_paddr = ((u64)gru.s.base << shift);
+	base = (gru.v & mask) >> shift;
+	map_high("GRU", base, shift, shift, max_pnode, map_wb);
+	gru_start_paddr = ((u64)base << shift);
 	gru_end_paddr = gru_start_paddr + (1UL << shift) * (max_pnode + 1);
 }
 
@@ -595,6 +758,7 @@ static __initdata struct mmioh_config mm
 	},
 };
 
+/* UV3 & UV4 have identical MMIOH overlay configs */
 static __init void map_mmioh_high_uv3(int index, int min_pnode, int max_pnode)
 {
 	union uv3h_rh_gam_mmioh_overlay_config0_mmr_u overlay;
@@ -674,7 +838,7 @@ static __init void map_mmioh_high(int mi
 	unsigned long mmr, base;
 	int shift, enable, m_io, n_io;
 
-	if (is_uv3_hub()) {
+	if (is_uv3_hub() || is_uv4_hub()) {
 		/* Map both MMIOH Regions */
 		map_mmioh_high_uv3(0, min_pnode, max_pnode);
 		map_mmioh_high_uv3(1, min_pnode, max_pnode);
@@ -739,8 +903,8 @@ static __init void uv_rtc_init(void)
  */
 static void uv_heartbeat(unsigned long ignored)
 {
-	struct timer_list *timer = &uv_hub_info->scir.timer;
-	unsigned char bits = uv_hub_info->scir.state;
+	struct timer_list *timer = &uv_scir_info->timer;
+	unsigned char bits = uv_scir_info->state;
 
 	/* flip heartbeat bit */
 	bits ^= SCIR_CPU_HEARTBEAT;
@@ -760,14 +924,14 @@ static void uv_heartbeat(unsigned long i
 
 static void uv_heartbeat_enable(int cpu)
 {
-	while (!uv_cpu_hub_info(cpu)->scir.enabled) {
-		struct timer_list *timer = &uv_cpu_hub_info(cpu)->scir.timer;
+	while (!uv_cpu_scir_info(cpu)->enabled) {
+		struct timer_list *timer = &uv_cpu_scir_info(cpu)->timer;
 
 		uv_set_cpu_scir_bits(cpu, SCIR_CPU_HEARTBEAT|SCIR_CPU_ACTIVITY);
 		setup_timer(timer, uv_heartbeat, cpu);
 		timer->expires = jiffies + SCIR_CPU_HB_INTERVAL;
 		add_timer_on(timer, cpu);
-		uv_cpu_hub_info(cpu)->scir.enabled = 1;
+		uv_cpu_scir_info(cpu)->enabled = 1;
 
 		/* also ensure that boot cpu is enabled */
 		cpu = 0;
@@ -777,9 +941,9 @@ static void uv_heartbeat_enable(int cpu)
 #ifdef CONFIG_HOTPLUG_CPU
 static void uv_heartbeat_disable(int cpu)
 {
-	if (uv_cpu_hub_info(cpu)->scir.enabled) {
-		uv_cpu_hub_info(cpu)->scir.enabled = 0;
-		del_timer(&uv_cpu_hub_info(cpu)->scir.timer);
+	if (uv_cpu_scir_info(cpu)->enabled) {
+		uv_cpu_scir_info(cpu)->enabled = 0;
+		del_timer(&uv_cpu_scir_info(cpu)->timer);
 	}
 	uv_set_cpu_scir_bits(cpu, 0xff);
 }
@@ -862,155 +1026,475 @@ int uv_set_vga_state(struct pci_dev *pde
 void uv_cpu_init(void)
 {
 	/* CPU 0 initialization will be done via uv_system_init. */
-	if (!uv_blade_info)
+	if (smp_processor_id() == 0)
 		return;
 
-	uv_blade_info[uv_numa_blade_id()].nr_online_cpus++;
+	uv_hub_info->nr_online_cpus++;
 
 	if (get_uv_system_type() == UV_NON_UNIQUE_APIC)
 		set_x2apic_extra_bits(uv_hub_info->pnode);
 }
 
-void __init uv_system_init(void)
+struct mn {
+	unsigned char	m_val;
+	unsigned char	n_val;
+	unsigned char	m_shift;
+	unsigned char	n_lshift;
+};
+
+static void get_mn(struct mn *mnp)
 {
-	union uvh_rh_gam_config_mmr_u  m_n_config;
-	union uvh_node_id_u node_id;
-	unsigned long gnode_upper, lowmem_redir_base, lowmem_redir_size;
-	int bytes, nid, cpu, lcpu, pnode, blade, i, j, m_val, n_val;
-	int gnode_extra, min_pnode = 999999, max_pnode = -1;
-	unsigned long mmr_base, present, paddr;
-	unsigned short pnode_mask;
-	unsigned char n_lshift;
-	char *hub = (is_uv1_hub() ? "UV100/1000" :
-		    (is_uv2_hub() ? "UV2000/3000" :
-		    (is_uv3_hub() ? "UV300" : NULL)));
+	union uvh_rh_gam_config_mmr_u m_n_config;
+	union uv3h_gr0_gam_gr_config_u m_gr_config;
 
-	if (!hub) {
-		pr_err("UV: Unknown/unsupported UV hub\n");
-		return;
+	m_n_config.v = uv_read_local_mmr(UVH_RH_GAM_CONFIG_MMR);
+	mnp->n_val = m_n_config.s.n_skt;
+	if (is_uv4_hub()) {
+		mnp->m_val = 0;
+		mnp->n_lshift = 0;
+	} else if (is_uv3_hub()) {
+		mnp->m_val = m_n_config.s3.m_skt;
+		m_gr_config.v = uv_read_local_mmr(UV3H_GR0_GAM_GR_CONFIG);
+		mnp->n_lshift = m_gr_config.s3.m_skt;
+	} else if (is_uv2_hub()) {
+		mnp->m_val = m_n_config.s2.m_skt;
+		mnp->n_lshift = mnp->m_val == 40 ? 40 : 39;
+	} else if (is_uv1_hub()) {
+		mnp->m_val = m_n_config.s1.m_skt;
+		mnp->n_lshift = mnp->m_val;
 	}
-	pr_info("UV: Found %s hub\n", hub);
+	mnp->m_shift = mnp->m_val ? 64 - mnp->m_val : 0;
+}
 
-	map_low_mmrs();
+void __init uv_init_hub_info(struct uv_hub_info_s *hub_info)
+{
+	struct mn mn = {0};	/* avoid unitialized warnings */
+	union uvh_node_id_u node_id;
 
-	m_n_config.v = uv_read_local_mmr(UVH_RH_GAM_CONFIG_MMR );
-	m_val = m_n_config.s.m_skt;
-	n_val = m_n_config.s.n_skt;
-	pnode_mask = (1 << n_val) - 1;
-	n_lshift = get_n_lshift(m_val);
-	mmr_base =
-	    uv_read_local_mmr(UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR) &
-	    ~UV_MMR_ENABLE;
+	get_mn(&mn);
+	hub_info->m_val = mn.m_val;
+	hub_info->n_val = mn.n_val;
+	hub_info->m_shift = mn.m_shift;
+	hub_info->n_lshift = mn.n_lshift ? mn.n_lshift : 0;
+
+	hub_info->hub_revision = uv_hub_info->hub_revision;
+	hub_info->pnode_mask = uv_cpuid.pnode_mask;
+	hub_info->min_pnode = _min_pnode;
+	hub_info->min_socket = _min_socket;
+	hub_info->pnode_to_socket = _pnode_to_socket;
+	hub_info->socket_to_node = _socket_to_node;
+	hub_info->socket_to_pnode = _socket_to_pnode;
+	hub_info->gr_table_len = _gr_table_len;
+	hub_info->gr_table = _gr_table;
+	hub_info->gpa_mask = mn.m_val ?
+		(1UL << (mn.m_val + mn.n_val)) - 1 :
+		(1UL << uv_cpuid.gpa_shift) - 1;
 
 	node_id.v = uv_read_local_mmr(UVH_NODE_ID);
-	gnode_extra = (node_id.s.node_id & ~((1 << n_val) - 1)) >> 1;
-	gnode_upper = ((unsigned long)gnode_extra  << m_val);
-	pr_info("UV: N:%d M:%d pnode_mask:0x%x gnode_upper/extra:0x%lx/0x%x n_lshift 0x%x\n",
-			n_val, m_val, pnode_mask, gnode_upper, gnode_extra,
-			n_lshift);
+	hub_info->gnode_extra =
+		(node_id.s.node_id & ~((1 << mn.n_val) - 1)) >> 1;
 
-	pr_info("UV: global MMR base 0x%lx\n", mmr_base);
+	hub_info->gnode_upper =
+		((unsigned long)hub_info->gnode_extra << mn.m_val);
 
-	for(i = 0; i < UVH_NODE_PRESENT_TABLE_DEPTH; i++)
-		uv_possible_blades +=
-		  hweight64(uv_read_local_mmr( UVH_NODE_PRESENT_TABLE + i * 8));
+	if (uv_gp_table) {
+		hub_info->global_mmr_base = uv_gp_table->mmr_base;
+		hub_info->global_mmr_shift = uv_gp_table->mmr_shift;
+		hub_info->global_gru_base = uv_gp_table->gru_base;
+		hub_info->global_gru_shift = uv_gp_table->gru_shift;
+		hub_info->gpa_shift = uv_gp_table->gpa_shift;
+		hub_info->gpa_mask = (1UL << hub_info->gpa_shift) - 1;
+	} else {
+		hub_info->global_mmr_base =
+			uv_read_local_mmr(UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR) &
+					~UV_MMR_ENABLE;
+		hub_info->global_mmr_shift = _UV_GLOBAL_MMR64_PNODE_SHIFT;
+	}
 
-	/* uv_num_possible_blades() is really the hub count */
-	pr_info("UV: Found %d blades, %d hubs\n",
-			is_uv1_hub() ? uv_num_possible_blades() :
-			(uv_num_possible_blades() + 1) / 2,
-			uv_num_possible_blades());
+	get_lowmem_redirect(
+		&hub_info->lowmem_remap_base, &hub_info->lowmem_remap_top);
 
-	bytes = sizeof(struct uv_blade_info) * uv_num_possible_blades();
-	uv_blade_info = kzalloc(bytes, GFP_KERNEL);
-	BUG_ON(!uv_blade_info);
+	hub_info->apic_pnode_shift = uv_cpuid.socketid_shift;
 
-	for (blade = 0; blade < uv_num_possible_blades(); blade++)
-		uv_blade_info[blade].memory_nid = -1;
+	/* show system specific info */
+	pr_info("UV: N:%d M:%d m_shift:%d n_lshift:%d\n",
+		hub_info->n_val, hub_info->m_val,
+		hub_info->m_shift, hub_info->n_lshift);
 
-	get_lowmem_redirect(&lowmem_redir_base, &lowmem_redir_size);
+	pr_info("UV: gpa_mask/shift:0x%lx/%d pnode_mask:0x%x apic_pns:%d\n",
+		hub_info->gpa_mask, hub_info->gpa_shift,
+		hub_info->pnode_mask, hub_info->apic_pnode_shift);
 
-	bytes = sizeof(uv_node_to_blade[0]) * num_possible_nodes();
-	uv_node_to_blade = kmalloc(bytes, GFP_KERNEL);
-	BUG_ON(!uv_node_to_blade);
-	memset(uv_node_to_blade, 255, bytes);
+	pr_info("UV: mmr_base/shift:0x%lx/%ld gru_base/shift:0x%lx/%ld\n",
+		hub_info->global_mmr_base, hub_info->global_mmr_shift,
+		hub_info->global_gru_base, hub_info->global_gru_shift);
 
-	bytes = sizeof(uv_cpu_to_blade[0]) * num_possible_cpus();
-	uv_cpu_to_blade = kmalloc(bytes, GFP_KERNEL);
-	BUG_ON(!uv_cpu_to_blade);
-	memset(uv_cpu_to_blade, 255, bytes);
+	pr_info("UV: gnode_upper:0x%lx gnode_extra:0x%x\n",
+		hub_info->gnode_upper, hub_info->gnode_extra);
+}
 
-	blade = 0;
+static void __init decode_gam_params(unsigned long ptr)
+{
+	uv_gp_table = (struct uv_gam_parameters *)ptr;
+
+	pr_info("UV: GAM Params...\n");
+	pr_info("UV: mmr_base/shift:0x%llx/%d gru_base/shift:0x%llx/%d gpa_shift:%d\n",
+		uv_gp_table->mmr_base, uv_gp_table->mmr_shift,
+		uv_gp_table->gru_base, uv_gp_table->gru_shift,
+		uv_gp_table->gpa_shift);
+}
+
+static void __init decode_gam_rng_tbl(unsigned long ptr)
+{
+	struct uv_gam_range_entry *gre = (struct uv_gam_range_entry *)ptr;
+	unsigned long lgre = 0;
+	int index = 0;
+	int sock_min = 999999, pnode_min = 99999;
+	int sock_max = -1, pnode_max = -1;
+
+	uv_gre_table = gre;
+	for (; gre->type != UV_GAM_RANGE_TYPE_UNUSED; gre++) {
+		if (!index) {
+			pr_info("UV: GAM Range Table...\n");
+			pr_info("UV:  # %20s %14s %5s %4s %5s %3s %2s %3s\n",
+				"Range", "", "Size", "Type", "NASID",
+				"SID", "PN", "PXM");
+		}
+		pr_info(
+		"UV: %2d: 0x%014lx-0x%014lx %5luG %3d   %04x  %02x %02x %3d\n",
+			index++,
+			(unsigned long)lgre << UV_GAM_RANGE_SHFT,
+			(unsigned long)gre->limit << UV_GAM_RANGE_SHFT,
+			((unsigned long)(gre->limit - lgre)) >>
+				(30 - UV_GAM_RANGE_SHFT), /* 64M -> 1G */
+			gre->type, gre->nasid, gre->sockid,
+			gre->pnode, gre->pxm);
+
+		lgre = gre->limit;
+		if (sock_min > gre->sockid)
+			sock_min = gre->sockid;
+		if (sock_max < gre->sockid)
+			sock_max = gre->sockid;
+		if (pnode_min > gre->pnode)
+			pnode_min = gre->pnode;
+		if (pnode_max < gre->pnode)
+			pnode_max = gre->pnode;
+	}
+	_min_socket = sock_min;
+	_max_socket = sock_max;
+	_min_pnode = pnode_min;
+	_max_pnode = pnode_max;
+	_gr_table_len = index;
+	pr_info(
+	"UV: GRT: %d entries, sockets(min:%x,max:%x) pnodes(min:%x,max:%x)\n",
+		index, _min_socket, _max_socket, _min_pnode, _max_pnode);
+}
+
+static void __init decode_uv_systab(void)
+{
+	struct uv_systab *st;
+	int i;
+
+	st = uv_systab;
+	if ((!st || st->revision < UV_SYSTAB_VERSION_UV4) && !is_uv4_hub())
+		return;
+	if (st->revision != UV_SYSTAB_VERSION_UV4_LATEST) {
+		pr_crit(
+		"UV: BIOS UVsystab version(%x) mismatch, expecting(%x)\n",
+			st->revision, UV_SYSTAB_VERSION_UV4_LATEST);
+		BUG();
+	}
+
+	for (i = 0; st->entry[i].type != UV_SYSTAB_TYPE_UNUSED; i++) {
+		unsigned long ptr = st->entry[i].offset;
+
+		if (!ptr)
+			continue;
+
+		ptr = ptr + (unsigned long)st;
+
+		switch (st->entry[i].type) {
+		case UV_SYSTAB_TYPE_GAM_PARAMS:
+			decode_gam_params(ptr);
+			break;
+
+		case UV_SYSTAB_TYPE_GAM_RNG_TBL:
+			decode_gam_rng_tbl(ptr);
+			break;
+		}
+	}
+}
+
+/*
+ * Setup physical blade translations from UVH_NODE_PRESENT_TABLE
+ * .. NB: UVH_NODE_PRESENT_TABLE is going away,
+ * .. being replaced by GAM Range Table
+ */
+static __init void boot_init_possible_blades(struct uv_hub_info_s *hub_info)
+{
+	int i, uv_pb = 0;
+
+	pr_info("UV: NODE_PRESENT_DEPTH = %d\n", UVH_NODE_PRESENT_TABLE_DEPTH);
 	for (i = 0; i < UVH_NODE_PRESENT_TABLE_DEPTH; i++) {
-		present = uv_read_local_mmr(UVH_NODE_PRESENT_TABLE + i * 8);
-		for (j = 0; j < 64; j++) {
-			if (!test_bit(j, &present))
-				continue;
-			pnode = (i * 64 + j) & pnode_mask;
-			uv_blade_info[blade].pnode = pnode;
-			uv_blade_info[blade].nr_possible_cpus = 0;
-			uv_blade_info[blade].nr_online_cpus = 0;
-			spin_lock_init(&uv_blade_info[blade].nmi_lock);
-			min_pnode = min(pnode, min_pnode);
-			max_pnode = max(pnode, max_pnode);
-			blade++;
+		unsigned long np;
+
+		np = uv_read_local_mmr(UVH_NODE_PRESENT_TABLE + i * 8);
+		if (np)
+			pr_info("UV: NODE_PRESENT(%d) = 0x%016lx\n", i, np);
+
+		uv_pb += hweight64(np);
+	}
+	if (uv_possible_blades != uv_pb)
+		uv_possible_blades = uv_pb;
+}
+
+static void __init build_socket_tables(void)
+{
+	struct uv_gam_range_entry *gre = uv_gre_table;
+	int num, nump;
+	int cpu, i, lnid;
+	int minsock = _min_socket;
+	int maxsock = _max_socket;
+	int minpnode = _min_pnode;
+	int maxpnode = _max_pnode;
+	size_t bytes;
+
+	if (!gre) {
+		if (is_uv1_hub() || is_uv2_hub() || is_uv3_hub()) {
+			pr_info("UV: No UVsystab socket table, ignoring\n");
+			return;		/* not required */
 		}
+		pr_crit(
+		"UV: Error: UVsystab address translations not available!\n");
+		BUG();
 	}
 
-	uv_bios_init();
+	/* build socket id -> node id, pnode */
+	num = maxsock - minsock + 1;
+	bytes = num * sizeof(_socket_to_node[0]);
+	_socket_to_node = kmalloc(bytes, GFP_KERNEL);
+	_socket_to_pnode = kmalloc(bytes, GFP_KERNEL);
+
+	nump = maxpnode - minpnode + 1;
+	bytes = nump * sizeof(_pnode_to_socket[0]);
+	_pnode_to_socket = kmalloc(bytes, GFP_KERNEL);
+	BUG_ON(!_socket_to_node || !_socket_to_pnode || !_pnode_to_socket);
+
+	for (i = 0; i < num; i++)
+		_socket_to_node[i] = _socket_to_pnode[i] = SOCK_EMPTY;
+
+	for (i = 0; i < nump; i++)
+		_pnode_to_socket[i] = SOCK_EMPTY;
+
+	/* fill in pnode/node/addr conversion list values */
+	pr_info("UV: GAM Building socket/pnode/pxm conversion tables\n");
+	for (; gre->type != UV_GAM_RANGE_TYPE_UNUSED; gre++) {
+		if (gre->type == UV_GAM_RANGE_TYPE_HOLE)
+			continue;
+		i = gre->sockid - minsock;
+		if (_socket_to_pnode[i] != SOCK_EMPTY)
+			continue;	/* duplicate */
+		_socket_to_pnode[i] = gre->pnode;
+		_socket_to_node[i] = gre->pxm;
+
+		i = gre->pnode - minpnode;
+		_pnode_to_socket[i] = gre->sockid;
+
+		pr_info(
+		"UV: sid:%02x type:%d nasid:%04x pn:%02x pxm:%2d pn2s:%2x\n",
+			gre->sockid, gre->type, gre->nasid,
+			_socket_to_pnode[gre->sockid - minsock],
+			_socket_to_node[gre->sockid - minsock],
+			_pnode_to_socket[gre->pnode - minpnode]);
+	}
+
+	/* check socket -> node values */
+	lnid = -1;
+	for_each_present_cpu(cpu) {
+		int nid = cpu_to_node(cpu);
+		int apicid, sockid;
+
+		if (lnid == nid)
+			continue;
+		lnid = nid;
+		apicid = per_cpu(x86_cpu_to_apicid, cpu);
+		sockid = apicid >> uv_cpuid.socketid_shift;
+		i = sockid - minsock;
+
+		if (nid != _socket_to_node[i]) {
+			pr_warn(
+			"UV: %02x: type:%d socket:%02x PXM:%02x != node:%2d\n",
+				i, sockid, gre->type, _socket_to_node[i], nid);
+			_socket_to_node[i] = nid;
+		}
+	}
+
+	/* Setup physical blade to pnode translation from GAM Range Table */
+	bytes = num_possible_nodes() * sizeof(_node_to_pnode[0]);
+	_node_to_pnode = kmalloc(bytes, GFP_KERNEL);
+	BUG_ON(!_node_to_pnode);
+
+	for (lnid = 0; lnid < num_possible_nodes(); lnid++) {
+		unsigned short sockid;
+
+		for (sockid = minsock; sockid <= maxsock; sockid++) {
+			if (lnid == _socket_to_node[sockid - minsock]) {
+				_node_to_pnode[lnid] =
+					_socket_to_pnode[sockid - minsock];
+				break;
+			}
+		}
+		if (sockid > maxsock) {
+			pr_err("UV: socket for node %d not found!\n", lnid);
+			BUG();
+		}
+	}
+
+	/*
+	 * If socket id == pnode or socket id == node for all nodes,
+	 *   system runs faster by removing corresponding conversion table.
+	 */
+	pr_info("UV: Checking socket->node/pnode for identity maps\n");
+	if (minsock == 0) {
+		for (i = 0; i < num; i++)
+			if (_socket_to_node[i] == SOCK_EMPTY ||
+				i != _socket_to_node[i])
+				break;
+		if (i >= num) {
+			kfree(_socket_to_node);
+			_socket_to_node = NULL;
+			pr_info("UV: 1:1 socket_to_node table removed\n");
+		}
+	}
+	if (minsock == minpnode) {
+		for (i = 0; i < num; i++)
+			if (_socket_to_pnode[i] != SOCK_EMPTY &&
+				_socket_to_pnode[i] != i + minpnode)
+				break;
+		if (i >= num) {
+			kfree(_socket_to_pnode);
+			_socket_to_pnode = NULL;
+			pr_info("UV: 1:1 socket_to_pnode table removed\n");
+		}
+	}
+}
+
+void __init uv_system_init(void)
+{
+	struct uv_hub_info_s hub_info = {0};
+	int bytes, cpu, nodeid;
+	unsigned short min_pnode = 9999, max_pnode = 0;
+	char *hub = is_uv4_hub() ? "UV400" :
+		    is_uv3_hub() ? "UV300" :
+		    is_uv2_hub() ? "UV2000/3000" :
+		    is_uv1_hub() ? "UV100/1000" : NULL;
+
+	if (!hub) {
+		pr_err("UV: Unknown/unsupported UV hub\n");
+		return;
+	}
+	pr_info("UV: Found %s hub\n", hub);
+
+	map_low_mmrs();
+
+	uv_bios_init();			/* get uv_systab for decoding */
+	decode_uv_systab();
+	build_socket_tables();
+	build_uv_gr_table();
+	uv_init_hub_info(&hub_info);
+	uv_possible_blades = num_possible_nodes();
+	if (!_node_to_pnode)
+		boot_init_possible_blades(&hub_info);
+
+	/* uv_num_possible_blades() is really the hub count */
+	pr_info("UV: Found %d hubs, %d nodes, %d cpus\n",
+			uv_num_possible_blades(),
+			num_possible_nodes(),
+			num_possible_cpus());
+
 	uv_bios_get_sn_info(0, &uv_type, &sn_partition_id, &sn_coherency_id,
 			    &sn_region_size, &system_serial_number);
+	hub_info.coherency_domain_number = sn_coherency_id;
 	uv_rtc_init();
 
-	for_each_present_cpu(cpu) {
-		int apicid = per_cpu(x86_cpu_to_apicid, cpu);
+	bytes = sizeof(void *) * uv_num_possible_blades();
+	__uv_hub_info_list = kzalloc(bytes, GFP_KERNEL);
+	BUG_ON(!__uv_hub_info_list);
 
-		nid = cpu_to_node(cpu);
-		/*
-		 * apic_pnode_shift must be set before calling uv_apicid_to_pnode();
-		 */
-		uv_cpu_hub_info(cpu)->pnode_mask = pnode_mask;
-		uv_cpu_hub_info(cpu)->apic_pnode_shift = uvh_apicid.s.pnode_shift;
-		uv_cpu_hub_info(cpu)->hub_revision = uv_hub_info->hub_revision;
+	bytes = sizeof(struct uv_hub_info_s);
+	for_each_node(nodeid) {
+		struct uv_hub_info_s *new_hub;
 
-		uv_cpu_hub_info(cpu)->m_shift = 64 - m_val;
-		uv_cpu_hub_info(cpu)->n_lshift = n_lshift;
+		if (__uv_hub_info_list[nodeid]) {
+			pr_err("UV: Node %d UV HUB already initialized!?\n",
+				nodeid);
+			BUG();
+		}
 
-		pnode = uv_apicid_to_pnode(apicid);
-		blade = boot_pnode_to_blade(pnode);
-		lcpu = uv_blade_info[blade].nr_possible_cpus;
-		uv_blade_info[blade].nr_possible_cpus++;
+		/* Allocate new per hub info list */
+		new_hub = (nodeid == 0) ?
+			&uv_hub_info_node0 :
+			kzalloc_node(bytes, GFP_KERNEL, nodeid);
+		BUG_ON(!new_hub);
+		__uv_hub_info_list[nodeid] = new_hub;
+		new_hub = uv_hub_info_list(nodeid);
+		BUG_ON(!new_hub);
+		*new_hub = hub_info;
 
-		/* Any node on the blade, else will contain -1. */
-		uv_blade_info[blade].memory_nid = nid;
+		/* Use information from GAM table if available */
+		if (_node_to_pnode)
+			new_hub->pnode = _node_to_pnode[nodeid];
+		else	/* Fill in during cpu loop */
+			new_hub->pnode = 0xffff;
+		new_hub->numa_blade_id = uv_node_to_blade_id(nodeid);
+		new_hub->memory_nid = -1;
+		new_hub->nr_possible_cpus = 0;
+		new_hub->nr_online_cpus = 0;
+	}
 
-		uv_cpu_hub_info(cpu)->lowmem_remap_base = lowmem_redir_base;
-		uv_cpu_hub_info(cpu)->lowmem_remap_top = lowmem_redir_size;
-		uv_cpu_hub_info(cpu)->m_val = m_val;
-		uv_cpu_hub_info(cpu)->n_val = n_val;
-		uv_cpu_hub_info(cpu)->numa_blade_id = blade;
-		uv_cpu_hub_info(cpu)->blade_processor_id = lcpu;
-		uv_cpu_hub_info(cpu)->pnode = pnode;
-		uv_cpu_hub_info(cpu)->gpa_mask = (1UL << (m_val + n_val)) - 1;
-		uv_cpu_hub_info(cpu)->gnode_upper = gnode_upper;
-		uv_cpu_hub_info(cpu)->gnode_extra = gnode_extra;
-		uv_cpu_hub_info(cpu)->global_mmr_base = mmr_base;
-		uv_cpu_hub_info(cpu)->coherency_domain_number = sn_coherency_id;
-		uv_cpu_hub_info(cpu)->scir.offset = uv_scir_offset(apicid);
-		uv_node_to_blade[nid] = blade;
-		uv_cpu_to_blade[cpu] = blade;
+	/* Initialize per cpu info */
+	for_each_possible_cpu(cpu) {
+		int apicid = per_cpu(x86_cpu_to_apicid, cpu);
+		int numa_node_id;
+		unsigned short pnode;
+
+		nodeid = cpu_to_node(cpu);
+		numa_node_id = numa_cpu_node(cpu);
+		pnode = uv_apicid_to_pnode(apicid);
+
+		uv_cpu_info_per(cpu)->p_uv_hub_info = uv_hub_info_list(nodeid);
+		uv_cpu_info_per(cpu)->blade_cpu_id =
+			uv_cpu_hub_info(cpu)->nr_possible_cpus++;
+		if (uv_cpu_hub_info(cpu)->memory_nid == -1)
+			uv_cpu_hub_info(cpu)->memory_nid = cpu_to_node(cpu);
+		if (nodeid != numa_node_id &&	/* init memoryless node */
+		    uv_hub_info_list(numa_node_id)->pnode == 0xffff)
+			uv_hub_info_list(numa_node_id)->pnode = pnode;
+		else if (uv_cpu_hub_info(cpu)->pnode == 0xffff)
+			uv_cpu_hub_info(cpu)->pnode = pnode;
+		uv_cpu_scir_info(cpu)->offset = uv_scir_offset(apicid);
 	}
 
-	/* Add blade/pnode info for nodes without cpus */
-	for_each_online_node(nid) {
-		if (uv_node_to_blade[nid] >= 0)
-			continue;
-		paddr = node_start_pfn(nid) << PAGE_SHIFT;
-		pnode = uv_gpa_to_pnode(uv_soc_phys_ram_to_gpa(paddr));
-		blade = boot_pnode_to_blade(pnode);
-		uv_node_to_blade[nid] = blade;
+	for_each_node(nodeid) {
+		unsigned short pnode = uv_hub_info_list(nodeid)->pnode;
+
+		/* Add pnode info for pre-GAM list nodes without cpus */
+		if (pnode == 0xffff) {
+			unsigned long paddr;
+
+			paddr = node_start_pfn(nodeid) << PAGE_SHIFT;
+			pnode = uv_gpa_to_pnode(uv_soc_phys_ram_to_gpa(paddr));
+			uv_hub_info_list(nodeid)->pnode = pnode;
+		}
+		min_pnode = min(pnode, min_pnode);
+		max_pnode = max(pnode, max_pnode);
+		pr_info("UV: UVHUB node:%2d pn:%02x nrcpus:%d\n",
+			nodeid,
+			uv_hub_info_list(nodeid)->pnode,
+			uv_hub_info_list(nodeid)->nr_possible_cpus);
 	}
 
+	pr_info("UV: min_pnode:%02x max_pnode:%02x\n", min_pnode, max_pnode);
 	map_gru_high(max_pnode);
 	map_mmr_high(max_pnode);
 	map_mmioh_high(min_pnode, max_pnode);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/apm_32.c linux-libre-4.7-gnu/arch/x86/kernel/apm_32.c
--- linux-libre-4.6-gnu/arch/x86/kernel/apm_32.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/apm_32.c	2016-07-24 15:23:50.000000000 -0400
@@ -2267,7 +2267,7 @@ static int __init apm_init(void)
 
 	dmi_check_system(apm_dmi_table);
 
-	if (apm_info.bios.version == 0 || paravirt_enabled() || machine_is_olpc()) {
+	if (apm_info.bios.version == 0 || machine_is_olpc()) {
 		printk(KERN_INFO "apm: BIOS not found.\n");
 		return -ENODEV;
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/asm-offsets.c linux-libre-4.7-gnu/arch/x86/kernel/asm-offsets.c
--- linux-libre-4.6-gnu/arch/x86/kernel/asm-offsets.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/asm-offsets.c	2016-07-24 15:23:50.000000000 -0400
@@ -80,6 +80,7 @@ void common(void) {
 	OFFSET(BP_hardware_subarch, boot_params, hdr.hardware_subarch);
 	OFFSET(BP_version, boot_params, hdr.version);
 	OFFSET(BP_kernel_alignment, boot_params, hdr.kernel_alignment);
+	OFFSET(BP_init_size, boot_params, hdr.init_size);
 	OFFSET(BP_pref_address, boot_params, hdr.pref_address);
 	OFFSET(BP_code32_start, boot_params, hdr.code32_start);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/cpu/amd.c linux-libre-4.7-gnu/arch/x86/kernel/cpu/amd.c
--- linux-libre-4.6-gnu/arch/x86/kernel/cpu/amd.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/cpu/amd.c	2016-07-24 15:23:50.000000000 -0400
@@ -565,14 +565,17 @@ static void early_init_amd(struct cpuinf
 	 * can safely set X86_FEATURE_EXTD_APICID unconditionally for families
 	 * after 16h.
 	 */
-	if (cpu_has_apic && c->x86 > 0x16) {
-		set_cpu_cap(c, X86_FEATURE_EXTD_APICID);
-	} else if (cpu_has_apic && c->x86 >= 0xf) {
-		/* check CPU config space for extended APIC ID */
-		unsigned int val;
-		val = read_pci_config(0, 24, 0, 0x68);
-		if ((val & ((1 << 17) | (1 << 18))) == ((1 << 17) | (1 << 18)))
+	if (boot_cpu_has(X86_FEATURE_APIC)) {
+		if (c->x86 > 0x16)
 			set_cpu_cap(c, X86_FEATURE_EXTD_APICID);
+		else if (c->x86 >= 0xf) {
+			/* check CPU config space for extended APIC ID */
+			unsigned int val;
+
+			val = read_pci_config(0, 24, 0, 0x68);
+			if ((val >> 17 & 0x3) == 0x3)
+				set_cpu_cap(c, X86_FEATURE_EXTD_APICID);
+		}
 	}
 #endif
 
@@ -628,6 +631,7 @@ static void init_amd_k8(struct cpuinfo_x
 	 */
 	msr_set_bit(MSR_K7_HWCR, 6);
 #endif
+	set_cpu_bug(c, X86_BUG_SWAPGS_FENCE);
 }
 
 static void init_amd_gh(struct cpuinfo_x86 *c)
@@ -670,14 +674,14 @@ static void init_amd_bd(struct cpuinfo_x
 	u64 value;
 
 	/* re-enable TopologyExtensions if switched off by BIOS */
-	if ((c->x86_model >= 0x10) && (c->x86_model <= 0x1f) &&
+	if ((c->x86_model >= 0x10) && (c->x86_model <= 0x6f) &&
 	    !cpu_has(c, X86_FEATURE_TOPOEXT)) {
 
 		if (msr_set_bit(0xc0011005, 54) > 0) {
 			rdmsrl(0xc0011005, value);
 			if (value & BIT_64(54)) {
 				set_cpu_cap(c, X86_FEATURE_TOPOEXT);
-				pr_info(FW_INFO "CPU: Re-enabling disabled Topology Extensions Support.\n");
+				pr_info_once(FW_INFO "CPU: Re-enabling disabled Topology Extensions Support.\n");
 			}
 		}
 	}
@@ -746,7 +750,7 @@ static void init_amd(struct cpuinfo_x86
 	if (c->x86 >= 0xf)
 		set_cpu_cap(c, X86_FEATURE_K8);
 
-	if (cpu_has_xmm2) {
+	if (cpu_has(c, X86_FEATURE_XMM2)) {
 		/* MFENCE stops RDTSC speculation */
 		set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC);
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/cpu/common.c linux-libre-4.7-gnu/arch/x86/kernel/cpu/common.c
--- linux-libre-4.6-gnu/arch/x86/kernel/cpu/common.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/cpu/common.c	2016-07-24 15:23:50.000000000 -0400
@@ -37,6 +37,7 @@
 #include <asm/mtrr.h>
 #include <linux/numa.h>
 #include <asm/asm.h>
+#include <asm/bugs.h>
 #include <asm/cpu.h>
 #include <asm/mce.h>
 #include <asm/msr.h>
@@ -270,6 +271,8 @@ static inline void squash_the_stupid_ser
 static __init int setup_disable_smep(char *arg)
 {
 	setup_clear_cpu_cap(X86_FEATURE_SMEP);
+	/* Check for things that depend on SMEP being enabled: */
+	check_mpx_erratum(&boot_cpu_data);
 	return 1;
 }
 __setup("nosmep", setup_disable_smep);
@@ -310,6 +313,10 @@ static bool pku_disabled;
 
 static __always_inline void setup_pku(struct cpuinfo_x86 *c)
 {
+	/* check the boot processor, plus compile options for PKU: */
+	if (!cpu_feature_enabled(X86_FEATURE_PKU))
+		return;
+	/* checks the actual processor's cpuid bits: */
 	if (!cpu_has(c, X86_FEATURE_PKU))
 		return;
 	if (pku_disabled)
@@ -430,7 +437,7 @@ void load_percpu_segment(int cpu)
 #ifdef CONFIG_X86_32
 	loadsegment(fs, __KERNEL_PERCPU);
 #else
-	loadsegment(gs, 0);
+	__loadsegment_simple(gs, 0);
 	wrmsrl(MSR_GS_BASE, (unsigned long)per_cpu(irq_stack_union.gs_base, cpu));
 #endif
 	load_stack_canary_segment();
@@ -717,6 +724,13 @@ void get_cpu_cap(struct cpuinfo_x86 *c)
 		}
 	}
 
+	if (c->extended_cpuid_level >= 0x80000007) {
+		cpuid(0x80000007, &eax, &ebx, &ecx, &edx);
+
+		c->x86_capability[CPUID_8000_0007_EBX] = ebx;
+		c->x86_power = edx;
+	}
+
 	if (c->extended_cpuid_level >= 0x80000008) {
 		cpuid(0x80000008, &eax, &ebx, &ecx, &edx);
 
@@ -729,9 +743,6 @@ void get_cpu_cap(struct cpuinfo_x86 *c)
 		c->x86_phys_bits = 36;
 #endif
 
-	if (c->extended_cpuid_level >= 0x80000007)
-		c->x86_power = cpuid_edx(0x80000007);
-
 	if (c->extended_cpuid_level >= 0x8000000a)
 		c->x86_capability[CPUID_8000_000A_EDX] = cpuid_edx(0x8000000a);
 
@@ -862,30 +873,34 @@ static void detect_nopl(struct cpuinfo_x
 #else
 	set_cpu_cap(c, X86_FEATURE_NOPL);
 #endif
+}
 
+static void detect_null_seg_behavior(struct cpuinfo_x86 *c)
+{
+#ifdef CONFIG_X86_64
 	/*
-	 * ESPFIX is a strange bug.  All real CPUs have it.  Paravirt
-	 * systems that run Linux at CPL > 0 may or may not have the
-	 * issue, but, even if they have the issue, there's absolutely
-	 * nothing we can do about it because we can't use the real IRET
-	 * instruction.
+	 * Empirically, writing zero to a segment selector on AMD does
+	 * not clear the base, whereas writing zero to a segment
+	 * selector on Intel does clear the base.  Intel's behavior
+	 * allows slightly faster context switches in the common case
+	 * where GS is unused by the prev and next threads.
 	 *
-	 * NB: For the time being, only 32-bit kernels support
-	 * X86_BUG_ESPFIX as such.  64-bit kernels directly choose
-	 * whether to apply espfix using paravirt hooks.  If any
-	 * non-paravirt system ever shows up that does *not* have the
-	 * ESPFIX issue, we can change this.
+	 * Since neither vendor documents this anywhere that I can see,
+	 * detect it directly instead of hardcoding the choice by
+	 * vendor.
+	 *
+	 * I've designated AMD's behavior as the "bug" because it's
+	 * counterintuitive and less friendly.
 	 */
-#ifdef CONFIG_X86_32
-#ifdef CONFIG_PARAVIRT
-	do {
-		extern void native_iret(void);
-		if (pv_cpu_ops.iret == native_iret)
-			set_cpu_bug(c, X86_BUG_ESPFIX);
-	} while (0);
-#else
-	set_cpu_bug(c, X86_BUG_ESPFIX);
-#endif
+
+	unsigned long old_base, tmp;
+	rdmsrl(MSR_FS_BASE, old_base);
+	wrmsrl(MSR_FS_BASE, 1);
+	loadsegment(fs, 0);
+	rdmsrl(MSR_FS_BASE, tmp);
+	if (tmp != 0)
+		set_cpu_bug(c, X86_BUG_NULL_SEG);
+	wrmsrl(MSR_FS_BASE, old_base);
 #endif
 }
 
@@ -921,6 +936,33 @@ static void generic_identify(struct cpui
 	get_model_name(c); /* Default name */
 
 	detect_nopl(c);
+
+	detect_null_seg_behavior(c);
+
+	/*
+	 * ESPFIX is a strange bug.  All real CPUs have it.  Paravirt
+	 * systems that run Linux at CPL > 0 may or may not have the
+	 * issue, but, even if they have the issue, there's absolutely
+	 * nothing we can do about it because we can't use the real IRET
+	 * instruction.
+	 *
+	 * NB: For the time being, only 32-bit kernels support
+	 * X86_BUG_ESPFIX as such.  64-bit kernels directly choose
+	 * whether to apply espfix using paravirt hooks.  If any
+	 * non-paravirt system ever shows up that does *not* have the
+	 * ESPFIX issue, we can change this.
+	 */
+#ifdef CONFIG_X86_32
+# ifdef CONFIG_PARAVIRT
+	do {
+		extern void native_iret(void);
+		if (pv_cpu_ops.iret == native_iret)
+			set_cpu_bug(c, X86_BUG_ESPFIX);
+	} while (0);
+# else
+	set_cpu_bug(c, X86_BUG_ESPFIX);
+# endif
+#endif
 }
 
 static void x86_init_cache_qos(struct cpuinfo_x86 *c)
@@ -1076,12 +1118,12 @@ void enable_sep_cpu(void)
 	struct tss_struct *tss;
 	int cpu;
 
+	if (!boot_cpu_has(X86_FEATURE_SEP))
+		return;
+
 	cpu = get_cpu();
 	tss = &per_cpu(cpu_tss, cpu);
 
-	if (!boot_cpu_has(X86_FEATURE_SEP))
-		goto out;
-
 	/*
 	 * We cache MSR_IA32_SYSENTER_CS's value in the TSS's ss1 field --
 	 * see the big comment in struct x86_hw_tss's definition.
@@ -1096,7 +1138,6 @@ void enable_sep_cpu(void)
 
 	wrmsr(MSR_IA32_SYSENTER_EIP, (unsigned long)entry_SYSENTER_32, 0);
 
-out:
 	put_cpu();
 }
 #endif
@@ -1528,7 +1569,7 @@ void cpu_init(void)
 	pr_info("Initializing CPU#%d\n", cpu);
 
 	if (cpu_feature_enabled(X86_FEATURE_VME) ||
-	    cpu_has_tsc ||
+	    boot_cpu_has(X86_FEATURE_TSC) ||
 	    boot_cpu_has(X86_FEATURE_DE))
 		cr4_clear_bits(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/cpu/cyrix.c linux-libre-4.7-gnu/arch/x86/kernel/cpu/cyrix.c
--- linux-libre-4.6-gnu/arch/x86/kernel/cpu/cyrix.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/cpu/cyrix.c	2016-07-24 15:23:50.000000000 -0400
@@ -333,7 +333,7 @@ static void init_cyrix(struct cpuinfo_x8
 		switch (dir0_lsn) {
 		case 0xd:  /* either a 486SLC or DLC w/o DEVID */
 			dir0_msn = 0;
-			p = Cx486_name[(cpu_has_fpu ? 1 : 0)];
+			p = Cx486_name[!!boot_cpu_has(X86_FEATURE_FPU)];
 			break;
 
 		case 0xe:  /* a 486S A step */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/cpu/intel.c linux-libre-4.7-gnu/arch/x86/kernel/cpu/intel.c
--- linux-libre-4.6-gnu/arch/x86/kernel/cpu/intel.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/cpu/intel.c	2016-07-24 15:23:50.000000000 -0400
@@ -25,6 +25,41 @@
 #include <asm/apic.h>
 #endif
 
+/*
+ * Just in case our CPU detection goes bad, or you have a weird system,
+ * allow a way to override the automatic disabling of MPX.
+ */
+static int forcempx;
+
+static int __init forcempx_setup(char *__unused)
+{
+	forcempx = 1;
+
+	return 1;
+}
+__setup("intel-skd-046-workaround=disable", forcempx_setup);
+
+void check_mpx_erratum(struct cpuinfo_x86 *c)
+{
+	if (forcempx)
+		return;
+	/*
+	 * Turn off the MPX feature on CPUs where SMEP is not
+	 * available or disabled.
+	 *
+	 * Works around Intel Erratum SKD046: "Branch Instructions
+	 * May Initialize MPX Bound Registers Incorrectly".
+	 *
+	 * This might falsely disable MPX on systems without
+	 * SMEP, like Atom processors without SMEP.  But there
+	 * is no such hardware known at the moment.
+	 */
+	if (cpu_has(c, X86_FEATURE_MPX) && !cpu_has(c, X86_FEATURE_SMEP)) {
+		setup_clear_cpu_cap(X86_FEATURE_MPX);
+		pr_warn("x86/mpx: Disabling MPX since SMEP not present\n");
+	}
+}
+
 static void early_init_intel(struct cpuinfo_x86 *c)
 {
 	u64 misc_enable;
@@ -152,9 +187,9 @@ static void early_init_intel(struct cpui
 	 *  the TLB when any changes are made to any of the page table entries.
 	 *  The operating system must reload CR3 to cause the TLB to be flushed"
 	 *
-	 * As a result cpu_has_pge() in arch/x86/include/asm/tlbflush.h should
-	 * be false so that __flush_tlb_all() causes CR3 insted of CR4.PGE
-	 * to be modified
+	 * As a result, boot_cpu_has(X86_FEATURE_PGE) in arch/x86/include/asm/tlbflush.h
+	 * should be false so that __flush_tlb_all() causes CR3 insted of CR4.PGE
+	 * to be modified.
 	 */
 	if (c->x86 == 5 && c->x86_model == 9) {
 		pr_info("Disabling PGE capability bit\n");
@@ -173,6 +208,8 @@ static void early_init_intel(struct cpui
 		if (edx & (1U << 28))
 			c->x86_coreid_bits = get_count_order((ebx >> 16) & 0xff);
 	}
+
+	check_mpx_erratum(c);
 }
 
 #ifdef CONFIG_X86_32
@@ -233,7 +270,7 @@ static void intel_workarounds(struct cpu
 	 * The Quark is also family 5, but does not have the same bug.
 	 */
 	clear_cpu_bug(c, X86_BUG_F00F);
-	if (!paravirt_enabled() && c->x86 == 5 && c->x86_model < 9) {
+	if (c->x86 == 5 && c->x86_model < 9) {
 		static int f00f_workaround_enabled;
 
 		set_cpu_bug(c, X86_BUG_F00F);
@@ -281,7 +318,7 @@ static void intel_workarounds(struct cpu
 	 * integrated APIC (see 11AP erratum in "Pentium Processor
 	 * Specification Update").
 	 */
-	if (cpu_has_apic && (c->x86<<8 | c->x86_model<<4) == 0x520 &&
+	if (boot_cpu_has(X86_FEATURE_APIC) && (c->x86<<8 | c->x86_model<<4) == 0x520 &&
 	    (c->x86_mask < 0x6 || c->x86_mask == 0xb))
 		set_cpu_bug(c, X86_BUG_11AP);
 
@@ -456,7 +493,7 @@ static void init_intel(struct cpuinfo_x8
 			set_cpu_cap(c, X86_FEATURE_ARCH_PERFMON);
 	}
 
-	if (cpu_has_xmm2)
+	if (cpu_has(c, X86_FEATURE_XMM2))
 		set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC);
 
 	if (boot_cpu_has(X86_FEATURE_DS)) {
@@ -468,7 +505,7 @@ static void init_intel(struct cpuinfo_x8
 			set_cpu_cap(c, X86_FEATURE_PEBS);
 	}
 
-	if (c->x86 == 6 && cpu_has_clflush &&
+	if (c->x86 == 6 && boot_cpu_has(X86_FEATURE_CLFLUSH) &&
 	    (c->x86_model == 29 || c->x86_model == 46 || c->x86_model == 47))
 		set_cpu_bug(c, X86_BUG_CLFLUSH_MONITOR);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/cpu/mcheck/mce_amd.c linux-libre-4.7-gnu/arch/x86/kernel/cpu/mcheck/mce_amd.c
--- linux-libre-4.6-gnu/arch/x86/kernel/cpu/mcheck/mce_amd.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/cpu/mcheck/mce_amd.c	2016-07-24 15:23:50.000000000 -0400
@@ -54,14 +54,6 @@
 /* Threshold LVT offset is at MSR0xC0000410[15:12] */
 #define SMCA_THR_LVT_OFF	0xF000
 
-/*
- * OS is required to set the MCAX bit to acknowledge that it is now using the
- * new MSR ranges and new registers under each bank. It also means that the OS
- * will configure deferred errors in the new MCx_CONFIG register. If the bit is
- * not set, uncorrectable errors will cause a system panic.
- */
-#define SMCA_MCAX_EN_OFF	0x1
-
 static const char * const th_names[] = {
 	"load_store",
 	"insn_fetch",
@@ -333,7 +325,7 @@ static u32 get_block_address(u32 current
 	/* Fall back to method we used for older processors: */
 	switch (block) {
 	case 0:
-		addr = MSR_IA32_MCx_MISC(bank);
+		addr = msr_ops.misc(bank);
 		break;
 	case 1:
 		offset = ((low & MASK_BLKPTR_LO) >> 21);
@@ -351,6 +343,7 @@ prepare_threshold_block(unsigned int ban
 			int offset, u32 misc_high)
 {
 	unsigned int cpu = smp_processor_id();
+	u32 smca_low, smca_high, smca_addr;
 	struct threshold_block b;
 	int new;
 
@@ -369,24 +362,49 @@ prepare_threshold_block(unsigned int ban
 
 	b.interrupt_enable = 1;
 
-	if (mce_flags.smca) {
-		u32 smca_low, smca_high;
-		u32 smca_addr = MSR_AMD64_SMCA_MCx_CONFIG(bank);
+	if (!mce_flags.smca) {
+		new = (misc_high & MASK_LVTOFF_HI) >> 20;
+		goto set_offset;
+	}
 
-		if (!rdmsr_safe(smca_addr, &smca_low, &smca_high)) {
-			smca_high |= SMCA_MCAX_EN_OFF;
-			wrmsr(smca_addr, smca_low, smca_high);
-		}
+	smca_addr = MSR_AMD64_SMCA_MCx_CONFIG(bank);
 
-		/* Gather LVT offset for thresholding: */
-		if (rdmsr_safe(MSR_CU_DEF_ERR, &smca_low, &smca_high))
-			goto out;
+	if (!rdmsr_safe(smca_addr, &smca_low, &smca_high)) {
+		/*
+		 * OS is required to set the MCAX bit to acknowledge that it is
+		 * now using the new MSR ranges and new registers under each
+		 * bank. It also means that the OS will configure deferred
+		 * errors in the new MCx_CONFIG register. If the bit is not set,
+		 * uncorrectable errors will cause a system panic.
+		 *
+		 * MCA_CONFIG[MCAX] is bit 32 (0 in the high portion of the MSR.)
+		 */
+		smca_high |= BIT(0);
 
-		new = (smca_low & SMCA_THR_LVT_OFF) >> 12;
-	} else {
-		new = (misc_high & MASK_LVTOFF_HI) >> 20;
+		/*
+		 * SMCA logs Deferred Error information in MCA_DE{STAT,ADDR}
+		 * registers with the option of additionally logging to
+		 * MCA_{STATUS,ADDR} if MCA_CONFIG[LogDeferredInMcaStat] is set.
+		 *
+		 * This bit is usually set by BIOS to retain the old behavior
+		 * for OSes that don't use the new registers. Linux supports the
+		 * new registers so let's disable that additional logging here.
+		 *
+		 * MCA_CONFIG[LogDeferredInMcaStat] is bit 34 (bit 2 in the high
+		 * portion of the MSR).
+		 */
+		smca_high &= ~BIT(2);
+
+		wrmsr(smca_addr, smca_low, smca_high);
 	}
 
+	/* Gather LVT offset for thresholding: */
+	if (rdmsr_safe(MSR_CU_DEF_ERR, &smca_low, &smca_high))
+		goto out;
+
+	new = (smca_low & SMCA_THR_LVT_OFF) >> 12;
+
+set_offset:
 	offset = setup_APIC_mce_threshold(offset, new);
 
 	if ((offset == new) && (mce_threshold_vector != amd_threshold_interrupt))
@@ -430,12 +448,23 @@ void mce_amd_feature_init(struct cpuinfo
 		deferred_error_interrupt_enable(c);
 }
 
-static void __log_error(unsigned int bank, bool threshold_err, u64 misc)
+static void
+__log_error(unsigned int bank, bool deferred_err, bool threshold_err, u64 misc)
 {
+	u32 msr_status = msr_ops.status(bank);
+	u32 msr_addr = msr_ops.addr(bank);
 	struct mce m;
 	u64 status;
 
-	rdmsrl(MSR_IA32_MCx_STATUS(bank), status);
+	WARN_ON_ONCE(deferred_err && threshold_err);
+
+	if (deferred_err && mce_flags.smca) {
+		msr_status = MSR_AMD64_SMCA_MCx_DESTAT(bank);
+		msr_addr = MSR_AMD64_SMCA_MCx_DEADDR(bank);
+	}
+
+	rdmsrl(msr_status, status);
+
 	if (!(status & MCI_STATUS_VAL))
 		return;
 
@@ -448,10 +477,11 @@ static void __log_error(unsigned int ban
 		m.misc = misc;
 
 	if (m.status & MCI_STATUS_ADDRV)
-		rdmsrl(MSR_IA32_MCx_ADDR(bank), m.addr);
+		rdmsrl(msr_addr, m.addr);
 
 	mce_log(&m);
-	wrmsrl(MSR_IA32_MCx_STATUS(bank), 0);
+
+	wrmsrl(msr_status, 0);
 }
 
 static inline void __smp_deferred_error_interrupt(void)
@@ -479,17 +509,21 @@ asmlinkage __visible void smp_trace_defe
 /* APIC interrupt handler for deferred errors */
 static void amd_deferred_error_interrupt(void)
 {
-	u64 status;
 	unsigned int bank;
+	u32 msr_status;
+	u64 status;
 
 	for (bank = 0; bank < mca_cfg.banks; ++bank) {
-		rdmsrl(MSR_IA32_MCx_STATUS(bank), status);
+		msr_status = (mce_flags.smca) ? MSR_AMD64_SMCA_MCx_DESTAT(bank)
+					      : msr_ops.status(bank);
+
+		rdmsrl(msr_status, status);
 
 		if (!(status & MCI_STATUS_VAL) ||
 		    !(status & MCI_STATUS_DEFERRED))
 			continue;
 
-		__log_error(bank, false, 0);
+		__log_error(bank, true, false, 0);
 		break;
 	}
 }
@@ -544,7 +578,7 @@ static void amd_threshold_interrupt(void
 	return;
 
 log:
-	__log_error(bank, true, ((u64)high << 32) | low);
+	__log_error(bank, false, true, ((u64)high << 32) | low);
 }
 
 /*
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/cpu/mcheck/mce.c linux-libre-4.7-gnu/arch/x86/kernel/cpu/mcheck/mce.c
--- linux-libre-4.6-gnu/arch/x86/kernel/cpu/mcheck/mce.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/cpu/mcheck/mce.c	2016-07-24 15:23:50.000000000 -0400
@@ -161,7 +161,6 @@ void mce_log(struct mce *mce)
 	if (!mce_gen_pool_add(mce))
 		irq_work_queue(&mce_irq_work);
 
-	mce->finished = 0;
 	wmb();
 	for (;;) {
 		entry = mce_log_get_idx_check(mcelog.next);
@@ -194,7 +193,6 @@ void mce_log(struct mce *mce)
 	mcelog.entry[entry].finished = 1;
 	wmb();
 
-	mce->finished = 1;
 	set_bit(0, &mce_need_notify);
 }
 
@@ -224,6 +222,53 @@ void mce_unregister_decode_chain(struct
 }
 EXPORT_SYMBOL_GPL(mce_unregister_decode_chain);
 
+static inline u32 ctl_reg(int bank)
+{
+	return MSR_IA32_MCx_CTL(bank);
+}
+
+static inline u32 status_reg(int bank)
+{
+	return MSR_IA32_MCx_STATUS(bank);
+}
+
+static inline u32 addr_reg(int bank)
+{
+	return MSR_IA32_MCx_ADDR(bank);
+}
+
+static inline u32 misc_reg(int bank)
+{
+	return MSR_IA32_MCx_MISC(bank);
+}
+
+static inline u32 smca_ctl_reg(int bank)
+{
+	return MSR_AMD64_SMCA_MCx_CTL(bank);
+}
+
+static inline u32 smca_status_reg(int bank)
+{
+	return MSR_AMD64_SMCA_MCx_STATUS(bank);
+}
+
+static inline u32 smca_addr_reg(int bank)
+{
+	return MSR_AMD64_SMCA_MCx_ADDR(bank);
+}
+
+static inline u32 smca_misc_reg(int bank)
+{
+	return MSR_AMD64_SMCA_MCx_MISC(bank);
+}
+
+struct mca_msr_regs msr_ops = {
+	.ctl	= ctl_reg,
+	.status	= status_reg,
+	.addr	= addr_reg,
+	.misc	= misc_reg
+};
+
 static void print_mce(struct mce *m)
 {
 	int ret = 0;
@@ -290,7 +335,9 @@ static void wait_for_panic(void)
 
 static void mce_panic(const char *msg, struct mce *final, char *exp)
 {
-	int i, apei_err = 0;
+	int apei_err = 0;
+	struct llist_node *pending;
+	struct mce_evt_llist *l;
 
 	if (!fake_panic) {
 		/*
@@ -307,11 +354,10 @@ static void mce_panic(const char *msg, s
 		if (atomic_inc_return(&mce_fake_panicked) > 1)
 			return;
 	}
+	pending = mce_gen_pool_prepare_records();
 	/* First print corrected ones that are still unlogged */
-	for (i = 0; i < MCE_LOG_LEN; i++) {
-		struct mce *m = &mcelog.entry[i];
-		if (!(m->status & MCI_STATUS_VAL))
-			continue;
+	llist_for_each_entry(l, pending, llnode) {
+		struct mce *m = &l->mce;
 		if (!(m->status & MCI_STATUS_UC)) {
 			print_mce(m);
 			if (!apei_err)
@@ -319,13 +365,11 @@ static void mce_panic(const char *msg, s
 		}
 	}
 	/* Now print uncorrected but with the final one last */
-	for (i = 0; i < MCE_LOG_LEN; i++) {
-		struct mce *m = &mcelog.entry[i];
-		if (!(m->status & MCI_STATUS_VAL))
-			continue;
+	llist_for_each_entry(l, pending, llnode) {
+		struct mce *m = &l->mce;
 		if (!(m->status & MCI_STATUS_UC))
 			continue;
-		if (!final || memcmp(m, final, sizeof(struct mce))) {
+		if (!final || mce_cmp(m, final)) {
 			print_mce(m);
 			if (!apei_err)
 				apei_err = apei_write_mce(m);
@@ -356,11 +400,11 @@ static int msr_to_offset(u32 msr)
 
 	if (msr == mca_cfg.rip_msr)
 		return offsetof(struct mce, ip);
-	if (msr == MSR_IA32_MCx_STATUS(bank))
+	if (msr == msr_ops.status(bank))
 		return offsetof(struct mce, status);
-	if (msr == MSR_IA32_MCx_ADDR(bank))
+	if (msr == msr_ops.addr(bank))
 		return offsetof(struct mce, addr);
-	if (msr == MSR_IA32_MCx_MISC(bank))
+	if (msr == msr_ops.misc(bank))
 		return offsetof(struct mce, misc);
 	if (msr == MSR_IA32_MCG_STATUS)
 		return offsetof(struct mce, mcgstatus);
@@ -523,9 +567,9 @@ static struct notifier_block mce_srao_nb
 static void mce_read_aux(struct mce *m, int i)
 {
 	if (m->status & MCI_STATUS_MISCV)
-		m->misc = mce_rdmsrl(MSR_IA32_MCx_MISC(i));
+		m->misc = mce_rdmsrl(msr_ops.misc(i));
 	if (m->status & MCI_STATUS_ADDRV) {
-		m->addr = mce_rdmsrl(MSR_IA32_MCx_ADDR(i));
+		m->addr = mce_rdmsrl(msr_ops.addr(i));
 
 		/*
 		 * Mask the reported address by the reported granularity.
@@ -607,7 +651,7 @@ bool machine_check_poll(enum mcp_flags f
 		m.tsc = 0;
 
 		barrier();
-		m.status = mce_rdmsrl(MSR_IA32_MCx_STATUS(i));
+		m.status = mce_rdmsrl(msr_ops.status(i));
 		if (!(m.status & MCI_STATUS_VAL))
 			continue;
 
@@ -654,7 +698,7 @@ bool machine_check_poll(enum mcp_flags f
 		/*
 		 * Clear state for this bank.
 		 */
-		mce_wrmsrl(MSR_IA32_MCx_STATUS(i), 0);
+		mce_wrmsrl(msr_ops.status(i), 0);
 	}
 
 	/*
@@ -679,7 +723,7 @@ static int mce_no_way_out(struct mce *m,
 	char *tmp;
 
 	for (i = 0; i < mca_cfg.banks; i++) {
-		m->status = mce_rdmsrl(MSR_IA32_MCx_STATUS(i));
+		m->status = mce_rdmsrl(msr_ops.status(i));
 		if (m->status & MCI_STATUS_VAL) {
 			__set_bit(i, validp);
 			if (quirk_no_way_out)
@@ -830,9 +874,9 @@ static int mce_start(int *no_way_out)
 
 	atomic_add(*no_way_out, &global_nwo);
 	/*
-	 * global_nwo should be updated before mce_callin
+	 * Rely on the implied barrier below, such that global_nwo
+	 * is updated before mce_callin.
 	 */
-	smp_wmb();
 	order = atomic_inc_return(&mce_callin);
 
 	/*
@@ -957,7 +1001,7 @@ static void mce_clear_state(unsigned lon
 
 	for (i = 0; i < mca_cfg.banks; i++) {
 		if (test_bit(i, toclear))
-			mce_wrmsrl(MSR_IA32_MCx_STATUS(i), 0);
+			mce_wrmsrl(msr_ops.status(i), 0);
 	}
 }
 
@@ -994,11 +1038,12 @@ void do_machine_check(struct pt_regs *re
 	int i;
 	int worst = 0;
 	int severity;
+
 	/*
 	 * Establish sequential order between the CPUs entering the machine
 	 * check handler.
 	 */
-	int order;
+	int order = -1;
 	/*
 	 * If no_way_out gets set, there is no safe way to recover from this
 	 * MCE.  If mca_cfg.tolerant is cranked up, we'll try anyway.
@@ -1012,7 +1057,12 @@ void do_machine_check(struct pt_regs *re
 	DECLARE_BITMAP(toclear, MAX_NR_BANKS);
 	DECLARE_BITMAP(valid_banks, MAX_NR_BANKS);
 	char *msg = "Unknown";
-	int lmce = 0;
+
+	/*
+	 * MCEs are always local on AMD. Same is determined by MCG_STATUS_LMCES
+	 * on Intel.
+	 */
+	int lmce = 1;
 
 	/* If this CPU is offline, just bail out. */
 	if (cpu_is_offline(smp_processor_id())) {
@@ -1051,19 +1101,20 @@ void do_machine_check(struct pt_regs *re
 		kill_it = 1;
 
 	/*
-	 * Check if this MCE is signaled to only this logical processor
+	 * Check if this MCE is signaled to only this logical processor,
+	 * on Intel only.
 	 */
-	if (m.mcgstatus & MCG_STATUS_LMCES)
-		lmce = 1;
-	else {
-		/*
-		 * Go through all the banks in exclusion of the other CPUs.
-		 * This way we don't report duplicated events on shared banks
-		 * because the first one to see it will clear it.
-		 * If this is a Local MCE, then no need to perform rendezvous.
-		 */
+	if (m.cpuvendor == X86_VENDOR_INTEL)
+		lmce = m.mcgstatus & MCG_STATUS_LMCES;
+
+	/*
+	 * Go through all banks in exclusion of the other CPUs. This way we
+	 * don't report duplicated events on shared banks because the first one
+	 * to see it will clear it. If this is a Local MCE, then no need to
+	 * perform rendezvous.
+	 */
+	if (!lmce)
 		order = mce_start(&no_way_out);
-	}
 
 	for (i = 0; i < cfg->banks; i++) {
 		__clear_bit(i, toclear);
@@ -1076,7 +1127,7 @@ void do_machine_check(struct pt_regs *re
 		m.addr = 0;
 		m.bank = i;
 
-		m.status = mce_rdmsrl(MSR_IA32_MCx_STATUS(i));
+		m.status = mce_rdmsrl(msr_ops.status(i));
 		if ((m.status & MCI_STATUS_VAL) == 0)
 			continue;
 
@@ -1420,7 +1471,6 @@ static void __mcheck_cpu_init_generic(vo
 	enum mcp_flags m_fl = 0;
 	mce_banks_t all_banks;
 	u64 cap;
-	int i;
 
 	if (!mca_cfg.bootlog)
 		m_fl = MCP_DONTLOG;
@@ -1436,14 +1486,19 @@ static void __mcheck_cpu_init_generic(vo
 	rdmsrl(MSR_IA32_MCG_CAP, cap);
 	if (cap & MCG_CTL_P)
 		wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff);
+}
+
+static void __mcheck_cpu_init_clear_banks(void)
+{
+	int i;
 
 	for (i = 0; i < mca_cfg.banks; i++) {
 		struct mce_bank *b = &mce_banks[i];
 
 		if (!b->init)
 			continue;
-		wrmsrl(MSR_IA32_MCx_CTL(i), b->ctl);
-		wrmsrl(MSR_IA32_MCx_STATUS(i), 0);
+		wrmsrl(msr_ops.ctl(i), b->ctl);
+		wrmsrl(msr_ops.status(i), 0);
 	}
 }
 
@@ -1495,7 +1550,7 @@ static int __mcheck_cpu_apply_quirks(str
 			 */
 			clear_bit(10, (unsigned long *)&mce_banks[4].ctl);
 		}
-		if (c->x86 <= 17 && cfg->bootlog < 0) {
+		if (c->x86 < 17 && cfg->bootlog < 0) {
 			/*
 			 * Lots of broken BIOS around that don't clear them
 			 * by default and leave crap in there. Don't log:
@@ -1628,11 +1683,19 @@ static void __mcheck_cpu_init_vendor(str
 		break;
 
 	case X86_VENDOR_AMD: {
-		u32 ebx = cpuid_ebx(0x80000007);
+		mce_flags.overflow_recov = !!cpu_has(c, X86_FEATURE_OVERFLOW_RECOV);
+		mce_flags.succor	 = !!cpu_has(c, X86_FEATURE_SUCCOR);
+		mce_flags.smca		 = !!cpu_has(c, X86_FEATURE_SMCA);
 
-		mce_flags.overflow_recov = !!(ebx & BIT(0));
-		mce_flags.succor	 = !!(ebx & BIT(1));
-		mce_flags.smca		 = !!(ebx & BIT(3));
+		/*
+		 * Install proper ops for Scalable MCA enabled processors
+		 */
+		if (mce_flags.smca) {
+			msr_ops.ctl	= smca_ctl_reg;
+			msr_ops.status	= smca_status_reg;
+			msr_ops.addr	= smca_addr_reg;
+			msr_ops.misc	= smca_misc_reg;
+		}
 		mce_amd_feature_init(c);
 
 		break;
@@ -1717,6 +1780,7 @@ void mcheck_cpu_init(struct cpuinfo_x86
 
 	__mcheck_cpu_init_generic();
 	__mcheck_cpu_init_vendor(c);
+	__mcheck_cpu_init_clear_banks();
 	__mcheck_cpu_init_timer();
 }
 
@@ -2082,7 +2146,7 @@ static void mce_disable_error_reporting(
 		struct mce_bank *b = &mce_banks[i];
 
 		if (b->init)
-			wrmsrl(MSR_IA32_MCx_CTL(i), 0);
+			wrmsrl(msr_ops.ctl(i), 0);
 	}
 	return;
 }
@@ -2121,6 +2185,7 @@ static void mce_syscore_resume(void)
 {
 	__mcheck_cpu_init_generic();
 	__mcheck_cpu_init_vendor(raw_cpu_ptr(&cpu_info));
+	__mcheck_cpu_init_clear_banks();
 }
 
 static struct syscore_ops mce_syscore_ops = {
@@ -2138,6 +2203,7 @@ static void mce_cpu_restart(void *data)
 	if (!mce_available(raw_cpu_ptr(&cpu_info)))
 		return;
 	__mcheck_cpu_init_generic();
+	__mcheck_cpu_init_clear_banks();
 	__mcheck_cpu_init_timer();
 }
 
@@ -2413,7 +2479,7 @@ static void mce_reenable_cpu(void *h)
 		struct mce_bank *b = &mce_banks[i];
 
 		if (b->init)
-			wrmsrl(MSR_IA32_MCx_CTL(i), b->ctl);
+			wrmsrl(msr_ops.ctl(i), b->ctl);
 	}
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/cpu/mcheck/mce-genpool.c linux-libre-4.7-gnu/arch/x86/kernel/cpu/mcheck/mce-genpool.c
--- linux-libre-4.6-gnu/arch/x86/kernel/cpu/mcheck/mce-genpool.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/cpu/mcheck/mce-genpool.c	2016-07-24 15:23:50.000000000 -0400
@@ -26,6 +26,52 @@ static struct gen_pool *mce_evt_pool;
 static LLIST_HEAD(mce_event_llist);
 static char gen_pool_buf[MCE_POOLSZ];
 
+/*
+ * Compare the record "t" with each of the records on list "l" to see if
+ * an equivalent one is present in the list.
+ */
+static bool is_duplicate_mce_record(struct mce_evt_llist *t, struct mce_evt_llist *l)
+{
+	struct mce_evt_llist *node;
+	struct mce *m1, *m2;
+
+	m1 = &t->mce;
+
+	llist_for_each_entry(node, &l->llnode, llnode) {
+		m2 = &node->mce;
+
+		if (!mce_cmp(m1, m2))
+			return true;
+	}
+	return false;
+}
+
+/*
+ * The system has panicked - we'd like to peruse the list of MCE records
+ * that have been queued, but not seen by anyone yet.  The list is in
+ * reverse time order, so we need to reverse it. While doing that we can
+ * also drop duplicate records (these were logged because some banks are
+ * shared between cores or by all threads on a socket).
+ */
+struct llist_node *mce_gen_pool_prepare_records(void)
+{
+	struct llist_node *head;
+	LLIST_HEAD(new_head);
+	struct mce_evt_llist *node, *t;
+
+	head = llist_del_all(&mce_event_llist);
+	if (!head)
+		return NULL;
+
+	/* squeeze out duplicates while reversing order */
+	llist_for_each_entry_safe(node, t, head, llnode) {
+		if (!is_duplicate_mce_record(node, t))
+			llist_add(&node->llnode, &new_head);
+	}
+
+	return new_head.first;
+}
+
 void mce_gen_pool_process(void)
 {
 	struct llist_node *head;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/cpu/mcheck/mce_intel.c linux-libre-4.7-gnu/arch/x86/kernel/cpu/mcheck/mce_intel.c
--- linux-libre-4.6-gnu/arch/x86/kernel/cpu/mcheck/mce_intel.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/cpu/mcheck/mce_intel.c	2016-07-24 15:23:50.000000000 -0400
@@ -84,7 +84,7 @@ static int cmci_supported(int *banks)
 	 */
 	if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
 		return 0;
-	if (!cpu_has_apic || lapic_get_maxlvt() < 6)
+	if (!boot_cpu_has(X86_FEATURE_APIC) || lapic_get_maxlvt() < 6)
 		return 0;
 	rdmsrl(MSR_IA32_MCG_CAP, cap);
 	*banks = min_t(unsigned, MAX_NR_BANKS, cap & 0xff);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/cpu/mcheck/mce-internal.h linux-libre-4.7-gnu/arch/x86/kernel/cpu/mcheck/mce-internal.h
--- linux-libre-4.6-gnu/arch/x86/kernel/cpu/mcheck/mce-internal.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/cpu/mcheck/mce-internal.h	2016-07-24 15:23:50.000000000 -0400
@@ -35,6 +35,7 @@ void mce_gen_pool_process(void);
 bool mce_gen_pool_empty(void);
 int mce_gen_pool_add(struct mce *mce);
 int mce_gen_pool_init(void);
+struct llist_node *mce_gen_pool_prepare_records(void);
 
 extern int (*mce_severity)(struct mce *a, int tolerant, char **msg, bool is_excp);
 struct dentry *mce_get_debugfs_dir(void);
@@ -81,3 +82,17 @@ static inline int apei_clear_mce(u64 rec
 #endif
 
 void mce_inject_log(struct mce *m);
+
+/*
+ * We consider records to be equivalent if bank+status+addr+misc all match.
+ * This is only used when the system is going down because of a fatal error
+ * to avoid cluttering the console log with essentially repeated information.
+ * In normal processing all errors seen are logged.
+ */
+static inline bool mce_cmp(struct mce *m1, struct mce *m2)
+{
+	return m1->bank != m2->bank ||
+		m1->status != m2->status ||
+		m1->addr != m2->addr ||
+		m1->misc != m2->misc;
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/cpu/mcheck/mce-severity.c linux-libre-4.7-gnu/arch/x86/kernel/cpu/mcheck/mce-severity.c
--- linux-libre-4.6-gnu/arch/x86/kernel/cpu/mcheck/mce-severity.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/cpu/mcheck/mce-severity.c	2016-07-24 15:23:50.000000000 -0400
@@ -204,6 +204,33 @@ static int error_context(struct mce *m)
 	return IN_KERNEL;
 }
 
+static int mce_severity_amd_smca(struct mce *m, int err_ctx)
+{
+	u32 addr = MSR_AMD64_SMCA_MCx_CONFIG(m->bank);
+	u32 low, high;
+
+	/*
+	 * We need to look at the following bits:
+	 * - "succor" bit (data poisoning support), and
+	 * - TCC bit (Task Context Corrupt)
+	 * in MCi_STATUS to determine error severity.
+	 */
+	if (!mce_flags.succor)
+		return MCE_PANIC_SEVERITY;
+
+	if (rdmsr_safe(addr, &low, &high))
+		return MCE_PANIC_SEVERITY;
+
+	/* TCC (Task context corrupt). If set and if IN_KERNEL, panic. */
+	if ((low & MCI_CONFIG_MCAX) &&
+	    (m->status & MCI_STATUS_TCC) &&
+	    (err_ctx == IN_KERNEL))
+		return MCE_PANIC_SEVERITY;
+
+	 /* ...otherwise invoke hwpoison handler. */
+	return MCE_AR_SEVERITY;
+}
+
 /*
  * See AMD Error Scope Hierarchy table in a newer BKDG. For example
  * 49125_15h_Models_30h-3Fh_BKDG.pdf, section "RAS Features"
@@ -225,6 +252,9 @@ static int mce_severity_amd(struct mce *
 		 * to at least kill process to prolong system operation.
 		 */
 		if (mce_flags.overflow_recov) {
+			if (mce_flags.smca)
+				return mce_severity_amd_smca(m, ctx);
+
 			/* software can try to contain */
 			if (!(m->mcgstatus & MCG_STATUS_RIPV) && (ctx == IN_KERNEL))
 				return MCE_PANIC_SEVERITY;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/cpu/mcheck/therm_throt.c linux-libre-4.7-gnu/arch/x86/kernel/cpu/mcheck/therm_throt.c
--- linux-libre-4.6-gnu/arch/x86/kernel/cpu/mcheck/therm_throt.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/cpu/mcheck/therm_throt.c	2016-07-24 15:23:50.000000000 -0400
@@ -450,7 +450,7 @@ asmlinkage __visible void smp_trace_ther
 /* Thermal monitoring depends on APIC, ACPI and clock modulation */
 static int intel_thermal_supported(struct cpuinfo_x86 *c)
 {
-	if (!cpu_has_apic)
+	if (!boot_cpu_has(X86_FEATURE_APIC))
 		return 0;
 	if (!cpu_has(c, X86_FEATURE_ACPI) || !cpu_has(c, X86_FEATURE_ACC))
 		return 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/cpu/microcode/intel.c linux-libre-4.7-gnu/arch/x86/kernel/cpu/microcode/intel.c
--- linux-libre-4.6-gnu/arch/x86/kernel/cpu/microcode/intel.c	2016-05-15 19:17:37.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/cpu/microcode/intel.c	2016-07-24 18:13:00.000000000 -0400
@@ -422,7 +422,7 @@ static void show_saved_mc(void)
 		data_size = get_datasize(mc_saved_header);
 		date = mc_saved_header->date;
 
-		pr_debug("mc_saved[%d]: sig=0x%x, pf=0x%x, rev=0x%x, toal size=0x%x, date = %04x-%02x-%02x\n",
+		pr_debug("mc_saved[%d]: sig=0x%x, pf=0x%x, rev=0x%x, total size=0x%x, date = %04x-%02x-%02x\n",
 			 i, sig, pf, rev, total_size,
 			 date & 0xffff,
 			 date >> 24,
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/cpu/mtrr/cyrix.c linux-libre-4.7-gnu/arch/x86/kernel/cpu/mtrr/cyrix.c
--- linux-libre-4.6-gnu/arch/x86/kernel/cpu/mtrr/cyrix.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/cpu/mtrr/cyrix.c	2016-07-24 15:23:50.000000000 -0400
@@ -137,7 +137,7 @@ static void prepare_set(void)
 	u32 cr0;
 
 	/*  Save value of CR4 and clear Page Global Enable (bit 7)  */
-	if (cpu_has_pge) {
+	if (boot_cpu_has(X86_FEATURE_PGE)) {
 		cr4 = __read_cr4();
 		__write_cr4(cr4 & ~X86_CR4_PGE);
 	}
@@ -170,7 +170,7 @@ static void post_set(void)
 	write_cr0(read_cr0() & ~X86_CR0_CD);
 
 	/* Restore value of CR4 */
-	if (cpu_has_pge)
+	if (boot_cpu_has(X86_FEATURE_PGE))
 		__write_cr4(cr4);
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/cpu/mtrr/generic.c linux-libre-4.7-gnu/arch/x86/kernel/cpu/mtrr/generic.c
--- linux-libre-4.6-gnu/arch/x86/kernel/cpu/mtrr/generic.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/cpu/mtrr/generic.c	2016-07-24 15:23:50.000000000 -0400
@@ -444,11 +444,24 @@ static void __init print_mtrr_state(void
 		pr_debug("TOM2: %016llx aka %lldM\n", mtrr_tom2, mtrr_tom2>>20);
 }
 
+/* PAT setup for BP. We need to go through sync steps here */
+void __init mtrr_bp_pat_init(void)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	prepare_set();
+
+	pat_init();
+
+	post_set();
+	local_irq_restore(flags);
+}
+
 /* Grab all of the MTRR state for this CPU into *state */
 bool __init get_mtrr_state(void)
 {
 	struct mtrr_var_range *vrs;
-	unsigned long flags;
 	unsigned lo, dummy;
 	unsigned int i;
 
@@ -481,15 +494,6 @@ bool __init get_mtrr_state(void)
 
 	mtrr_state_set = 1;
 
-	/* PAT setup for BP. We need to go through sync steps here */
-	local_irq_save(flags);
-	prepare_set();
-
-	pat_init();
-
-	post_set();
-	local_irq_restore(flags);
-
 	return !!(mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED);
 }
 
@@ -741,7 +745,7 @@ static void prepare_set(void) __acquires
 	wbinvd();
 
 	/* Save value of CR4 and clear Page Global Enable (bit 7) */
-	if (cpu_has_pge) {
+	if (boot_cpu_has(X86_FEATURE_PGE)) {
 		cr4 = __read_cr4();
 		__write_cr4(cr4 & ~X86_CR4_PGE);
 	}
@@ -771,7 +775,7 @@ static void post_set(void) __releases(se
 	write_cr0(read_cr0() & ~X86_CR0_CD);
 
 	/* Restore value of CR4 */
-	if (cpu_has_pge)
+	if (boot_cpu_has(X86_FEATURE_PGE))
 		__write_cr4(cr4);
 	raw_spin_unlock(&set_atomicity_lock);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/cpu/mtrr/main.c linux-libre-4.7-gnu/arch/x86/kernel/cpu/mtrr/main.c
--- linux-libre-4.6-gnu/arch/x86/kernel/cpu/mtrr/main.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/cpu/mtrr/main.c	2016-07-24 15:23:50.000000000 -0400
@@ -752,6 +752,9 @@ void __init mtrr_bp_init(void)
 			/* BIOS may override */
 			__mtrr_enabled = get_mtrr_state();
 
+			if (mtrr_enabled())
+				mtrr_bp_pat_init();
+
 			if (mtrr_cleanup(phys_addr)) {
 				changed_by_mtrr_cleanup = 1;
 				mtrr_if->set_all();
@@ -759,8 +762,16 @@ void __init mtrr_bp_init(void)
 		}
 	}
 
-	if (!mtrr_enabled())
+	if (!mtrr_enabled()) {
 		pr_info("MTRR: Disabled\n");
+
+		/*
+		 * PAT initialization relies on MTRR's rendezvous handler.
+		 * Skip PAT init until the handler can initialize both
+		 * features independently.
+		 */
+		pat_disable("MTRRs disabled, skipping PAT initialization too.");
+	}
 }
 
 void mtrr_ap_init(void)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/cpu/mtrr/mtrr.h linux-libre-4.7-gnu/arch/x86/kernel/cpu/mtrr/mtrr.h
--- linux-libre-4.6-gnu/arch/x86/kernel/cpu/mtrr/mtrr.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/cpu/mtrr/mtrr.h	2016-07-24 15:23:50.000000000 -0400
@@ -52,6 +52,7 @@ void set_mtrr_prepare_save(struct set_mt
 void fill_mtrr_var_range(unsigned int index,
 		u32 base_lo, u32 base_hi, u32 mask_lo, u32 mask_hi);
 bool get_mtrr_state(void);
+void mtrr_bp_pat_init(void);
 
 extern void set_mtrr_ops(const struct mtrr_ops *ops);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/cpu/vmware.c linux-libre-4.7-gnu/arch/x86/kernel/cpu/vmware.c
--- linux-libre-4.6-gnu/arch/x86/kernel/cpu/vmware.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/cpu/vmware.c	2016-07-24 15:23:50.000000000 -0400
@@ -94,7 +94,7 @@ static void __init vmware_platform_setup
  */
 static uint32_t __init vmware_platform(void)
 {
-	if (cpu_has_hypervisor) {
+	if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) {
 		unsigned int eax;
 		unsigned int hyper_vendor_id[3];
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/devicetree.c linux-libre-4.7-gnu/arch/x86/kernel/devicetree.c
--- linux-libre-4.6-gnu/arch/x86/kernel/devicetree.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/devicetree.c	2016-07-24 15:23:50.000000000 -0400
@@ -151,7 +151,7 @@ static void __init dtb_lapic_setup(void)
 		return;
 
 	/* Did the boot loader setup the local APIC ? */
-	if (!cpu_has_apic) {
+	if (!boot_cpu_has(X86_FEATURE_APIC)) {
 		if (apic_force_enable(r.start))
 			return;
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/dumpstack_32.c linux-libre-4.7-gnu/arch/x86/kernel/dumpstack_32.c
--- linux-libre-4.6-gnu/arch/x86/kernel/dumpstack_32.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/dumpstack_32.c	2016-07-24 15:23:50.000000000 -0400
@@ -61,15 +61,13 @@ void dump_trace(struct task_struct *task
 		bp = stack_frame(task, regs);
 
 	for (;;) {
-		struct thread_info *context;
 		void *end_stack;
 
 		end_stack = is_hardirq_stack(stack, cpu);
 		if (!end_stack)
 			end_stack = is_softirq_stack(stack, cpu);
 
-		context = task_thread_info(task);
-		bp = ops->walk_stack(context, stack, bp, ops, data,
+		bp = ops->walk_stack(task, stack, bp, ops, data,
 				     end_stack, &graph);
 
 		/* Stop if not on irq stack */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/dumpstack_64.c linux-libre-4.7-gnu/arch/x86/kernel/dumpstack_64.c
--- linux-libre-4.6-gnu/arch/x86/kernel/dumpstack_64.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/dumpstack_64.c	2016-07-24 15:23:50.000000000 -0400
@@ -153,7 +153,6 @@ void dump_trace(struct task_struct *task
 		const struct stacktrace_ops *ops, void *data)
 {
 	const unsigned cpu = get_cpu();
-	struct thread_info *tinfo;
 	unsigned long *irq_stack = (unsigned long *)per_cpu(irq_stack_ptr, cpu);
 	unsigned long dummy;
 	unsigned used = 0;
@@ -179,7 +178,6 @@ void dump_trace(struct task_struct *task
 	 * current stack address. If the stacks consist of nested
 	 * exceptions
 	 */
-	tinfo = task_thread_info(task);
 	while (!done) {
 		unsigned long *stack_end;
 		enum stack_type stype;
@@ -202,7 +200,7 @@ void dump_trace(struct task_struct *task
 			if (ops->stack(data, id) < 0)
 				break;
 
-			bp = ops->walk_stack(tinfo, stack, bp, ops,
+			bp = ops->walk_stack(task, stack, bp, ops,
 					     data, stack_end, &graph);
 			ops->stack(data, "<EOE>");
 			/*
@@ -218,7 +216,7 @@ void dump_trace(struct task_struct *task
 
 			if (ops->stack(data, "IRQ") < 0)
 				break;
-			bp = ops->walk_stack(tinfo, stack, bp,
+			bp = ops->walk_stack(task, stack, bp,
 				     ops, data, stack_end, &graph);
 			/*
 			 * We link to the next stack (which would be
@@ -240,7 +238,7 @@ void dump_trace(struct task_struct *task
 	/*
 	 * This handles the process stack:
 	 */
-	bp = ops->walk_stack(tinfo, stack, bp, ops, data, NULL, &graph);
+	bp = ops->walk_stack(task, stack, bp, ops, data, NULL, &graph);
 	put_cpu();
 }
 EXPORT_SYMBOL(dump_trace);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/dumpstack.c linux-libre-4.7-gnu/arch/x86/kernel/dumpstack.c
--- linux-libre-4.6-gnu/arch/x86/kernel/dumpstack.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/dumpstack.c	2016-07-24 15:23:50.000000000 -0400
@@ -42,16 +42,14 @@ void printk_address(unsigned long addres
 static void
 print_ftrace_graph_addr(unsigned long addr, void *data,
 			const struct stacktrace_ops *ops,
-			struct thread_info *tinfo, int *graph)
+			struct task_struct *task, int *graph)
 {
-	struct task_struct *task;
 	unsigned long ret_addr;
 	int index;
 
 	if (addr != (unsigned long)return_to_handler)
 		return;
 
-	task = tinfo->task;
 	index = task->curr_ret_stack;
 
 	if (!task->ret_stack || index < *graph)
@@ -68,7 +66,7 @@ print_ftrace_graph_addr(unsigned long ad
 static inline void
 print_ftrace_graph_addr(unsigned long addr, void *data,
 			const struct stacktrace_ops *ops,
-			struct thread_info *tinfo, int *graph)
+			struct task_struct *task, int *graph)
 { }
 #endif
 
@@ -79,10 +77,10 @@ print_ftrace_graph_addr(unsigned long ad
  * severe exception (double fault, nmi, stack fault, debug, mce) hardware stack
  */
 
-static inline int valid_stack_ptr(struct thread_info *tinfo,
+static inline int valid_stack_ptr(struct task_struct *task,
 			void *p, unsigned int size, void *end)
 {
-	void *t = tinfo;
+	void *t = task_stack_page(task);
 	if (end) {
 		if (p < end && p >= (end-THREAD_SIZE))
 			return 1;
@@ -93,14 +91,14 @@ static inline int valid_stack_ptr(struct
 }
 
 unsigned long
-print_context_stack(struct thread_info *tinfo,
+print_context_stack(struct task_struct *task,
 		unsigned long *stack, unsigned long bp,
 		const struct stacktrace_ops *ops, void *data,
 		unsigned long *end, int *graph)
 {
 	struct stack_frame *frame = (struct stack_frame *)bp;
 
-	while (valid_stack_ptr(tinfo, stack, sizeof(*stack), end)) {
+	while (valid_stack_ptr(task, stack, sizeof(*stack), end)) {
 		unsigned long addr;
 
 		addr = *stack;
@@ -112,7 +110,7 @@ print_context_stack(struct thread_info *
 			} else {
 				ops->address(data, addr, 0);
 			}
-			print_ftrace_graph_addr(addr, data, ops, tinfo, graph);
+			print_ftrace_graph_addr(addr, data, ops, task, graph);
 		}
 		stack++;
 	}
@@ -121,7 +119,7 @@ print_context_stack(struct thread_info *
 EXPORT_SYMBOL_GPL(print_context_stack);
 
 unsigned long
-print_context_stack_bp(struct thread_info *tinfo,
+print_context_stack_bp(struct task_struct *task,
 		       unsigned long *stack, unsigned long bp,
 		       const struct stacktrace_ops *ops, void *data,
 		       unsigned long *end, int *graph)
@@ -129,7 +127,7 @@ print_context_stack_bp(struct thread_inf
 	struct stack_frame *frame = (struct stack_frame *)bp;
 	unsigned long *ret_addr = &frame->return_address;
 
-	while (valid_stack_ptr(tinfo, ret_addr, sizeof(*ret_addr), end)) {
+	while (valid_stack_ptr(task, ret_addr, sizeof(*ret_addr), end)) {
 		unsigned long addr = *ret_addr;
 
 		if (!__kernel_text_address(addr))
@@ -139,7 +137,7 @@ print_context_stack_bp(struct thread_inf
 			break;
 		frame = frame->next_frame;
 		ret_addr = &frame->return_address;
-		print_ftrace_graph_addr(addr, data, ops, tinfo, graph);
+		print_ftrace_graph_addr(addr, data, ops, task, graph);
 	}
 
 	return (unsigned long)frame;
@@ -260,19 +258,12 @@ int __die(const char *str, struct pt_reg
 	unsigned long sp;
 #endif
 	printk(KERN_DEFAULT
-	       "%s: %04lx [#%d] ", str, err & 0xffff, ++die_counter);
-#ifdef CONFIG_PREEMPT
-	printk("PREEMPT ");
-#endif
-#ifdef CONFIG_SMP
-	printk("SMP ");
-#endif
-	if (debug_pagealloc_enabled())
-		printk("DEBUG_PAGEALLOC ");
-#ifdef CONFIG_KASAN
-	printk("KASAN");
-#endif
-	printk("\n");
+	       "%s: %04lx [#%d]%s%s%s%s\n", str, err & 0xffff, ++die_counter,
+	       IS_ENABLED(CONFIG_PREEMPT) ? " PREEMPT"         : "",
+	       IS_ENABLED(CONFIG_SMP)     ? " SMP"             : "",
+	       debug_pagealloc_enabled()  ? " DEBUG_PAGEALLOC" : "",
+	       IS_ENABLED(CONFIG_KASAN)   ? " KASAN"           : "");
+
 	if (notify_die(DIE_OOPS, str, regs, err,
 			current->thread.trap_nr, SIGSEGV) == NOTIFY_STOP)
 		return 1;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/early-quirks.c linux-libre-4.7-gnu/arch/x86/kernel/early-quirks.c
--- linux-libre-4.6-gnu/arch/x86/kernel/early-quirks.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/early-quirks.c	2016-07-24 15:23:50.000000000 -0400
@@ -11,7 +11,11 @@
 
 #include <linux/pci.h>
 #include <linux/acpi.h>
+#include <linux/delay.h>
+#include <linux/dmi.h>
 #include <linux/pci_ids.h>
+#include <linux/bcma/bcma.h>
+#include <linux/bcma/bcma_regs.h>
 #include <drm/i915_drm.h>
 #include <asm/pci-direct.h>
 #include <asm/dma.h>
@@ -21,6 +25,9 @@
 #include <asm/iommu.h>
 #include <asm/gart.h>
 #include <asm/irq_remapping.h>
+#include <asm/early_ioremap.h>
+
+#define dev_err(msg)  pr_err("pci 0000:%02x:%02x.%d: %s", bus, slot, func, msg)
 
 static void __init fix_hypertransport_config(int num, int slot, int func)
 {
@@ -76,6 +83,13 @@ static void __init nvidia_bugs(int num,
 #ifdef CONFIG_ACPI
 #ifdef CONFIG_X86_IO_APIC
 	/*
+	 * Only applies to Nvidia root ports (bus 0) and not to
+	 * Nvidia graphics cards with PCI ports on secondary buses.
+	 */
+	if (num)
+		return;
+
+	/*
 	 * All timer overrides on Nvidia are
 	 * wrong unless HPET is enabled.
 	 * Unfortunately that's not true on many Asus boards.
@@ -590,6 +604,61 @@ static void __init force_disable_hpet(in
 #endif
 }
 
+#define BCM4331_MMIO_SIZE	16384
+#define BCM4331_PM_CAP		0x40
+#define bcma_aread32(reg)	ioread32(mmio + 1 * BCMA_CORE_SIZE + reg)
+#define bcma_awrite32(reg, val)	iowrite32(val, mmio + 1 * BCMA_CORE_SIZE + reg)
+
+static void __init apple_airport_reset(int bus, int slot, int func)
+{
+	void __iomem *mmio;
+	u16 pmcsr;
+	u64 addr;
+	int i;
+
+	if (!dmi_match(DMI_SYS_VENDOR, "Apple Inc."))
+		return;
+
+	/* Card may have been put into PCI_D3hot by grub quirk */
+	pmcsr = read_pci_config_16(bus, slot, func, BCM4331_PM_CAP + PCI_PM_CTRL);
+
+	if ((pmcsr & PCI_PM_CTRL_STATE_MASK) != PCI_D0) {
+		pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
+		write_pci_config_16(bus, slot, func, BCM4331_PM_CAP + PCI_PM_CTRL, pmcsr);
+		mdelay(10);
+
+		pmcsr = read_pci_config_16(bus, slot, func, BCM4331_PM_CAP + PCI_PM_CTRL);
+		if ((pmcsr & PCI_PM_CTRL_STATE_MASK) != PCI_D0) {
+			dev_err("Cannot power up Apple AirPort card\n");
+			return;
+		}
+	}
+
+	addr  =      read_pci_config(bus, slot, func, PCI_BASE_ADDRESS_0);
+	addr |= (u64)read_pci_config(bus, slot, func, PCI_BASE_ADDRESS_1) << 32;
+	addr &= PCI_BASE_ADDRESS_MEM_MASK;
+
+	mmio = early_ioremap(addr, BCM4331_MMIO_SIZE);
+	if (!mmio) {
+		dev_err("Cannot iomap Apple AirPort card\n");
+		return;
+	}
+
+	pr_info("Resetting Apple AirPort card (left enabled by EFI)\n");
+
+	for (i = 0; bcma_aread32(BCMA_RESET_ST) && i < 30; i++)
+		udelay(10);
+
+	bcma_awrite32(BCMA_RESET_CTL, BCMA_RESET_CTL_RESET);
+	bcma_aread32(BCMA_RESET_CTL);
+	udelay(1);
+
+	bcma_awrite32(BCMA_RESET_CTL, 0);
+	bcma_aread32(BCMA_RESET_CTL);
+	udelay(10);
+
+	early_iounmap(mmio, BCM4331_MMIO_SIZE);
+}
 
 #define QFLAG_APPLY_ONCE 	0x1
 #define QFLAG_APPLIED		0x2
@@ -603,12 +672,6 @@ struct chipset {
 	void (*f)(int num, int slot, int func);
 };
 
-/*
- * Only works for devices on the root bus. If you add any devices
- * not on bus 0 readd another loop level in early_quirks(). But
- * be careful because at least the Nvidia quirk here relies on
- * only matching on bus 0.
- */
 static struct chipset early_qrk[] __initdata = {
 	{ PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
 	  PCI_CLASS_BRIDGE_PCI, PCI_ANY_ID, QFLAG_APPLY_ONCE, nvidia_bugs },
@@ -638,9 +701,13 @@ static struct chipset early_qrk[] __init
 	 */
 	{ PCI_VENDOR_ID_INTEL, 0x0f00,
 		PCI_CLASS_BRIDGE_HOST, PCI_ANY_ID, 0, force_disable_hpet},
+	{ PCI_VENDOR_ID_BROADCOM, 0x4331,
+	  PCI_CLASS_NETWORK_OTHER, PCI_ANY_ID, 0, apple_airport_reset},
 	{}
 };
 
+static void __init early_pci_scan_bus(int bus);
+
 /**
  * check_dev_quirk - apply early quirks to a given PCI device
  * @num: bus number
@@ -649,7 +716,7 @@ static struct chipset early_qrk[] __init
  *
  * Check the vendor & device ID against the early quirks table.
  *
- * If the device is single function, let early_quirks() know so we don't
+ * If the device is single function, let early_pci_scan_bus() know so we don't
  * poke at this device again.
  */
 static int __init check_dev_quirk(int num, int slot, int func)
@@ -658,6 +725,7 @@ static int __init check_dev_quirk(int nu
 	u16 vendor;
 	u16 device;
 	u8 type;
+	u8 sec;
 	int i;
 
 	class = read_pci_config_16(num, slot, func, PCI_CLASS_DEVICE);
@@ -685,25 +753,36 @@ static int __init check_dev_quirk(int nu
 
 	type = read_pci_config_byte(num, slot, func,
 				    PCI_HEADER_TYPE);
+
+	if ((type & 0x7f) == PCI_HEADER_TYPE_BRIDGE) {
+		sec = read_pci_config_byte(num, slot, func, PCI_SECONDARY_BUS);
+		if (sec > num)
+			early_pci_scan_bus(sec);
+	}
+
 	if (!(type & 0x80))
 		return -1;
 
 	return 0;
 }
 
-void __init early_quirks(void)
+static void __init early_pci_scan_bus(int bus)
 {
 	int slot, func;
 
-	if (!early_pci_allowed())
-		return;
-
 	/* Poor man's PCI discovery */
-	/* Only scan the root bus */
 	for (slot = 0; slot < 32; slot++)
 		for (func = 0; func < 8; func++) {
 			/* Only probe function 0 on single fn devices */
-			if (check_dev_quirk(0, slot, func))
+			if (check_dev_quirk(bus, slot, func))
 				break;
 		}
 }
+
+void __init early_quirks(void)
+{
+	if (!early_pci_allowed())
+		return;
+
+	early_pci_scan_bus(0);
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/ebda.c linux-libre-4.7-gnu/arch/x86/kernel/ebda.c
--- linux-libre-4.6-gnu/arch/x86/kernel/ebda.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/x86/kernel/ebda.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,71 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/memblock.h>
+
+#include <asm/setup.h>
+#include <asm/bios_ebda.h>
+
+/*
+ * The BIOS places the EBDA/XBDA at the top of conventional
+ * memory, and usually decreases the reported amount of
+ * conventional memory (int 0x12) too. This also contains a
+ * workaround for Dell systems that neglect to reserve EBDA.
+ * The same workaround also avoids a problem with the AMD768MPX
+ * chipset: reserve a page before VGA to prevent PCI prefetch
+ * into it (errata #56). Usually the page is reserved anyways,
+ * unless you have no PS/2 mouse plugged in.
+ *
+ * This functions is deliberately very conservative.  Losing
+ * memory in the bottom megabyte is rarely a problem, as long
+ * as we have enough memory to install the trampoline.  Using
+ * memory that is in use by the BIOS or by some DMA device
+ * the BIOS didn't shut down *is* a big problem.
+ */
+
+#define BIOS_LOWMEM_KILOBYTES	0x413
+#define LOWMEM_CAP		0x9f000U	/* Absolute maximum */
+#define INSANE_CUTOFF		0x20000U	/* Less than this = insane */
+
+void __init reserve_ebda_region(void)
+{
+	unsigned int lowmem, ebda_addr;
+
+	/*
+	 * To determine the position of the EBDA and the
+	 * end of conventional memory, we need to look at
+	 * the BIOS data area. In a paravirtual environment
+	 * that area is absent. We'll just have to assume
+	 * that the paravirt case can handle memory setup
+	 * correctly, without our help.
+	 */
+	if (!x86_platform.legacy.ebda_search)
+		return;
+
+	/* end of low (conventional) memory */
+	lowmem = *(unsigned short *)__va(BIOS_LOWMEM_KILOBYTES);
+	lowmem <<= 10;
+
+	/* start of EBDA area */
+	ebda_addr = get_bios_ebda();
+
+	/*
+	 * Note: some old Dells seem to need 4k EBDA without
+	 * reporting so, so just consider the memory above 0x9f000
+	 * to be off limits (bugzilla 2990).
+	 */
+
+	/* If the EBDA address is below 128K, assume it is bogus */
+	if (ebda_addr < INSANE_CUTOFF)
+		ebda_addr = LOWMEM_CAP;
+
+	/* If lowmem is less than 128K, assume it is bogus */
+	if (lowmem < INSANE_CUTOFF)
+		lowmem = LOWMEM_CAP;
+
+	/* Use the lower of the lowmem and EBDA markers as the cutoff */
+	lowmem = min(lowmem, ebda_addr);
+	lowmem = min(lowmem, LOWMEM_CAP); /* Absolute cap */
+
+	/* reserve all memory between lowmem and the 1MB mark */
+	memblock_reserve(lowmem, 0x100000 - lowmem);
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/espfix_64.c linux-libre-4.7-gnu/arch/x86/kernel/espfix_64.c
--- linux-libre-4.6-gnu/arch/x86/kernel/espfix_64.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/espfix_64.c	2016-07-24 15:23:50.000000000 -0400
@@ -57,7 +57,7 @@
 # error "Need more than one PGD for the ESPFIX hack"
 #endif
 
-#define PGALLOC_GFP (GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO)
+#define PGALLOC_GFP (GFP_KERNEL | __GFP_NOTRACK | __GFP_ZERO)
 
 /* This contains the *bottom* address of the espfix stack */
 DEFINE_PER_CPU_READ_MOSTLY(unsigned long, espfix_stack);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/fpu/bugs.c linux-libre-4.7-gnu/arch/x86/kernel/fpu/bugs.c
--- linux-libre-4.6-gnu/arch/x86/kernel/fpu/bugs.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/fpu/bugs.c	2016-07-24 15:23:50.000000000 -0400
@@ -21,11 +21,15 @@ static double __initdata y = 3145727.0;
  * We should really only care about bugs here
  * anyway. Not features.
  */
-static void __init check_fpu(void)
+void __init fpu__init_check_bugs(void)
 {
 	u32 cr0_saved;
 	s32 fdiv_bug;
 
+	/* kernel_fpu_begin/end() relies on patched alternative instructions. */
+	if (!boot_cpu_has(X86_FEATURE_FPU))
+		return;
+
 	/* We might have CR0::TS set already, clear it: */
 	cr0_saved = read_cr0();
 	write_cr0(cr0_saved & ~X86_CR0_TS);
@@ -59,13 +63,3 @@ static void __init check_fpu(void)
 		pr_warn("Hmm, FPU with FDIV bug\n");
 	}
 }
-
-void __init fpu__init_check_bugs(void)
-{
-	/*
-	 * kernel_fpu_begin/end() in check_fpu() relies on the patched
-	 * alternative instructions.
-	 */
-	if (cpu_has_fpu)
-		check_fpu();
-}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/fpu/core.c linux-libre-4.7-gnu/arch/x86/kernel/fpu/core.c
--- linux-libre-4.6-gnu/arch/x86/kernel/fpu/core.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/fpu/core.c	2016-07-24 15:23:50.000000000 -0400
@@ -217,14 +217,14 @@ static inline void fpstate_init_fstate(s
 
 void fpstate_init(union fpregs_state *state)
 {
-	if (!cpu_has_fpu) {
+	if (!static_cpu_has(X86_FEATURE_FPU)) {
 		fpstate_init_soft(&state->soft);
 		return;
 	}
 
 	memset(state, 0, xstate_size);
 
-	if (cpu_has_fxsr)
+	if (static_cpu_has(X86_FEATURE_FXSR))
 		fpstate_init_fxstate(&state->fxsave);
 	else
 		fpstate_init_fstate(&state->fsave);
@@ -237,7 +237,7 @@ int fpu__copy(struct fpu *dst_fpu, struc
 	dst_fpu->fpregs_active = 0;
 	dst_fpu->last_cpu = -1;
 
-	if (!src_fpu->fpstate_active || !cpu_has_fpu)
+	if (!src_fpu->fpstate_active || !static_cpu_has(X86_FEATURE_FPU))
 		return 0;
 
 	WARN_ON_FPU(src_fpu != &current->thread.fpu);
@@ -506,33 +506,6 @@ void fpu__clear(struct fpu *fpu)
  * x87 math exception handling:
  */
 
-static inline unsigned short get_fpu_cwd(struct fpu *fpu)
-{
-	if (cpu_has_fxsr) {
-		return fpu->state.fxsave.cwd;
-	} else {
-		return (unsigned short)fpu->state.fsave.cwd;
-	}
-}
-
-static inline unsigned short get_fpu_swd(struct fpu *fpu)
-{
-	if (cpu_has_fxsr) {
-		return fpu->state.fxsave.swd;
-	} else {
-		return (unsigned short)fpu->state.fsave.swd;
-	}
-}
-
-static inline unsigned short get_fpu_mxcsr(struct fpu *fpu)
-{
-	if (cpu_has_xmm) {
-		return fpu->state.fxsave.mxcsr;
-	} else {
-		return MXCSR_DEFAULT;
-	}
-}
-
 int fpu__exception_code(struct fpu *fpu, int trap_nr)
 {
 	int err;
@@ -547,10 +520,15 @@ int fpu__exception_code(struct fpu *fpu,
 		 * so if this combination doesn't produce any single exception,
 		 * then we have a bad program that isn't synchronizing its FPU usage
 		 * and it will suffer the consequences since we won't be able to
-		 * fully reproduce the context of the exception
+		 * fully reproduce the context of the exception.
 		 */
-		cwd = get_fpu_cwd(fpu);
-		swd = get_fpu_swd(fpu);
+		if (boot_cpu_has(X86_FEATURE_FXSR)) {
+			cwd = fpu->state.fxsave.cwd;
+			swd = fpu->state.fxsave.swd;
+		} else {
+			cwd = (unsigned short)fpu->state.fsave.cwd;
+			swd = (unsigned short)fpu->state.fsave.swd;
+		}
 
 		err = swd & ~cwd;
 	} else {
@@ -560,7 +538,11 @@ int fpu__exception_code(struct fpu *fpu,
 		 * unmasked exception was caught we must mask the exception mask bits
 		 * at 0x1f80, and then use these to mask the exception bits at 0x3f.
 		 */
-		unsigned short mxcsr = get_fpu_mxcsr(fpu);
+		unsigned short mxcsr = MXCSR_DEFAULT;
+
+		if (boot_cpu_has(X86_FEATURE_XMM))
+			mxcsr = fpu->state.fxsave.mxcsr;
+
 		err = ~(mxcsr >> 7) & mxcsr;
 	}
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/fpu/init.c linux-libre-4.7-gnu/arch/x86/kernel/fpu/init.c
--- linux-libre-4.6-gnu/arch/x86/kernel/fpu/init.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/fpu/init.c	2016-07-24 15:23:50.000000000 -0400
@@ -29,22 +29,22 @@ static void fpu__init_cpu_generic(void)
 	unsigned long cr0;
 	unsigned long cr4_mask = 0;
 
-	if (cpu_has_fxsr)
+	if (boot_cpu_has(X86_FEATURE_FXSR))
 		cr4_mask |= X86_CR4_OSFXSR;
-	if (cpu_has_xmm)
+	if (boot_cpu_has(X86_FEATURE_XMM))
 		cr4_mask |= X86_CR4_OSXMMEXCPT;
 	if (cr4_mask)
 		cr4_set_bits(cr4_mask);
 
 	cr0 = read_cr0();
 	cr0 &= ~(X86_CR0_TS|X86_CR0_EM); /* clear TS and EM */
-	if (!cpu_has_fpu)
+	if (!boot_cpu_has(X86_FEATURE_FPU))
 		cr0 |= X86_CR0_EM;
 	write_cr0(cr0);
 
 	/* Flush out any pending x87 state: */
 #ifdef CONFIG_MATH_EMULATION
-	if (!cpu_has_fpu)
+	if (!boot_cpu_has(X86_FEATURE_FPU))
 		fpstate_init_soft(&current->thread.fpu.state.soft);
 	else
 #endif
@@ -89,7 +89,7 @@ static void fpu__init_system_early_gener
 	}
 
 #ifndef CONFIG_MATH_EMULATION
-	if (!cpu_has_fpu) {
+	if (!boot_cpu_has(X86_FEATURE_FPU)) {
 		pr_emerg("x86/fpu: Giving up, no FPU found and no math emulation present\n");
 		for (;;)
 			asm volatile("hlt");
@@ -106,7 +106,7 @@ static void __init fpu__init_system_mxcs
 {
 	unsigned int mask = 0;
 
-	if (cpu_has_fxsr) {
+	if (boot_cpu_has(X86_FEATURE_FXSR)) {
 		/* Static because GCC does not get 16-byte stack alignment right: */
 		static struct fxregs_state fxregs __initdata;
 
@@ -212,7 +212,7 @@ static void __init fpu__init_system_xsta
 	 * fpu__init_system_xstate().
 	 */
 
-	if (!cpu_has_fpu) {
+	if (!boot_cpu_has(X86_FEATURE_FPU)) {
 		/*
 		 * Disable xsave as we do not support it if i387
 		 * emulation is enabled.
@@ -221,7 +221,7 @@ static void __init fpu__init_system_xsta
 		setup_clear_cpu_cap(X86_FEATURE_XSAVEOPT);
 		xstate_size = sizeof(struct swregs_state);
 	} else {
-		if (cpu_has_fxsr)
+		if (boot_cpu_has(X86_FEATURE_FXSR))
 			xstate_size = sizeof(struct fxregs_state);
 		else
 			xstate_size = sizeof(struct fregs_state);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/fpu/regset.c linux-libre-4.7-gnu/arch/x86/kernel/fpu/regset.c
--- linux-libre-4.6-gnu/arch/x86/kernel/fpu/regset.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/fpu/regset.c	2016-07-24 15:23:50.000000000 -0400
@@ -21,7 +21,10 @@ int regset_xregset_fpregs_active(struct
 {
 	struct fpu *target_fpu = &target->thread.fpu;
 
-	return (cpu_has_fxsr && target_fpu->fpstate_active) ? regset->n : 0;
+	if (boot_cpu_has(X86_FEATURE_FXSR) && target_fpu->fpstate_active)
+		return regset->n;
+	else
+		return 0;
 }
 
 int xfpregs_get(struct task_struct *target, const struct user_regset *regset,
@@ -30,7 +33,7 @@ int xfpregs_get(struct task_struct *targ
 {
 	struct fpu *fpu = &target->thread.fpu;
 
-	if (!cpu_has_fxsr)
+	if (!boot_cpu_has(X86_FEATURE_FXSR))
 		return -ENODEV;
 
 	fpu__activate_fpstate_read(fpu);
@@ -47,7 +50,7 @@ int xfpregs_set(struct task_struct *targ
 	struct fpu *fpu = &target->thread.fpu;
 	int ret;
 
-	if (!cpu_has_fxsr)
+	if (!boot_cpu_has(X86_FEATURE_FXSR))
 		return -ENODEV;
 
 	fpu__activate_fpstate_write(fpu);
@@ -65,7 +68,7 @@ int xfpregs_set(struct task_struct *targ
 	 * update the header bits in the xsave header, indicating the
 	 * presence of FP and SSE state.
 	 */
-	if (cpu_has_xsave)
+	if (boot_cpu_has(X86_FEATURE_XSAVE))
 		fpu->state.xsave.header.xfeatures |= XFEATURE_MASK_FPSSE;
 
 	return ret;
@@ -79,7 +82,7 @@ int xstateregs_get(struct task_struct *t
 	struct xregs_state *xsave;
 	int ret;
 
-	if (!cpu_has_xsave)
+	if (!boot_cpu_has(X86_FEATURE_XSAVE))
 		return -ENODEV;
 
 	fpu__activate_fpstate_read(fpu);
@@ -108,7 +111,7 @@ int xstateregs_set(struct task_struct *t
 	struct xregs_state *xsave;
 	int ret;
 
-	if (!cpu_has_xsave)
+	if (!boot_cpu_has(X86_FEATURE_XSAVE))
 		return -ENODEV;
 
 	fpu__activate_fpstate_write(fpu);
@@ -275,10 +278,10 @@ int fpregs_get(struct task_struct *targe
 
 	fpu__activate_fpstate_read(fpu);
 
-	if (!static_cpu_has(X86_FEATURE_FPU))
+	if (!boot_cpu_has(X86_FEATURE_FPU))
 		return fpregs_soft_get(target, regset, pos, count, kbuf, ubuf);
 
-	if (!cpu_has_fxsr)
+	if (!boot_cpu_has(X86_FEATURE_FXSR))
 		return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
 					   &fpu->state.fsave, 0,
 					   -1);
@@ -306,10 +309,10 @@ int fpregs_set(struct task_struct *targe
 	fpu__activate_fpstate_write(fpu);
 	fpstate_sanitize_xstate(fpu);
 
-	if (!static_cpu_has(X86_FEATURE_FPU))
+	if (!boot_cpu_has(X86_FEATURE_FPU))
 		return fpregs_soft_set(target, regset, pos, count, kbuf, ubuf);
 
-	if (!cpu_has_fxsr)
+	if (!boot_cpu_has(X86_FEATURE_FXSR))
 		return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 					  &fpu->state.fsave, 0,
 					  -1);
@@ -325,7 +328,7 @@ int fpregs_set(struct task_struct *targe
 	 * update the header bit in the xsave header, indicating the
 	 * presence of FP.
 	 */
-	if (cpu_has_xsave)
+	if (boot_cpu_has(X86_FEATURE_XSAVE))
 		fpu->state.xsave.header.xfeatures |= XFEATURE_MASK_FP;
 	return ret;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/fpu/xstate.c linux-libre-4.7-gnu/arch/x86/kernel/fpu/xstate.c
--- linux-libre-4.6-gnu/arch/x86/kernel/fpu/xstate.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/fpu/xstate.c	2016-07-24 15:23:50.000000000 -0400
@@ -190,7 +190,7 @@ void fpstate_sanitize_xstate(struct fpu
  */
 void fpu__init_cpu_xstate(void)
 {
-	if (!cpu_has_xsave || !xfeatures_mask)
+	if (!boot_cpu_has(X86_FEATURE_XSAVE) || !xfeatures_mask)
 		return;
 
 	cr4_set_bits(X86_CR4_OSXSAVE);
@@ -280,7 +280,7 @@ static void __init setup_xstate_comp(voi
 	xstate_comp_offsets[0] = 0;
 	xstate_comp_offsets[1] = offsetof(struct fxregs_state, xmm_space);
 
-	if (!cpu_has_xsaves) {
+	if (!boot_cpu_has(X86_FEATURE_XSAVES)) {
 		for (i = FIRST_EXTENDED_XFEATURE; i < XFEATURE_MAX; i++) {
 			if (xfeature_enabled(i)) {
 				xstate_comp_offsets[i] = xstate_offsets[i];
@@ -316,13 +316,13 @@ static void __init setup_init_fpu_buf(vo
 	WARN_ON_FPU(!on_boot_cpu);
 	on_boot_cpu = 0;
 
-	if (!cpu_has_xsave)
+	if (!boot_cpu_has(X86_FEATURE_XSAVE))
 		return;
 
 	setup_xstate_features();
 	print_xstate_features();
 
-	if (cpu_has_xsaves) {
+	if (boot_cpu_has(X86_FEATURE_XSAVES)) {
 		init_fpstate.xsave.header.xcomp_bv = (u64)1 << 63 | xfeatures_mask;
 		init_fpstate.xsave.header.xfeatures = xfeatures_mask;
 	}
@@ -417,7 +417,7 @@ static int xfeature_size(int xfeature_nr
  */
 static int using_compacted_format(void)
 {
-	return cpu_has_xsaves;
+	return boot_cpu_has(X86_FEATURE_XSAVES);
 }
 
 static void __xstate_dump_leaves(void)
@@ -549,7 +549,7 @@ static unsigned int __init calculate_xst
 	unsigned int eax, ebx, ecx, edx;
 	unsigned int calculated_xstate_size;
 
-	if (!cpu_has_xsaves) {
+	if (!boot_cpu_has(X86_FEATURE_XSAVES)) {
 		/*
 		 * - CPUID function 0DH, sub-function 0:
 		 *    EBX enumerates the size (in bytes) required by
@@ -630,7 +630,7 @@ void __init fpu__init_system_xstate(void
 	WARN_ON_FPU(!on_boot_cpu);
 	on_boot_cpu = 0;
 
-	if (!cpu_has_xsave) {
+	if (!boot_cpu_has(X86_FEATURE_XSAVE)) {
 		pr_info("x86/fpu: Legacy x87 FPU detected.\n");
 		return;
 	}
@@ -667,7 +667,7 @@ void __init fpu__init_system_xstate(void
 	pr_info("x86/fpu: Enabled xstate features 0x%llx, context size is %d bytes, using '%s' format.\n",
 		xfeatures_mask,
 		xstate_size,
-		cpu_has_xsaves ? "compacted" : "standard");
+		boot_cpu_has(X86_FEATURE_XSAVES) ? "compacted" : "standard");
 }
 
 /*
@@ -678,7 +678,7 @@ void fpu__resume_cpu(void)
 	/*
 	 * Restore XCR0 on xsave capable CPUs:
 	 */
-	if (cpu_has_xsave)
+	if (boot_cpu_has(X86_FEATURE_XSAVE))
 		xsetbv(XCR_XFEATURE_ENABLED_MASK, xfeatures_mask);
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/head32.c linux-libre-4.7-gnu/arch/x86/kernel/head32.c
--- linux-libre-4.6-gnu/arch/x86/kernel/head32.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/head32.c	2016-07-24 15:23:50.000000000 -0400
@@ -34,6 +34,8 @@ asmlinkage __visible void __init i386_st
 	cr4_init_shadow();
 	sanitize_boot_params(&boot_params);
 
+	x86_early_init_platform_quirks();
+
 	/* Call the subarch specific early setup function */
 	switch (boot_params.hdr.hardware_subarch) {
 	case X86_SUBARCH_INTEL_MID:
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/head_32.S linux-libre-4.7-gnu/arch/x86/kernel/head_32.S
--- linux-libre-4.6-gnu/arch/x86/kernel/head_32.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/head_32.S	2016-07-24 15:23:50.000000000 -0400
@@ -555,62 +555,53 @@ early_idt_handler_common:
 	 */
 	cld
 
-	cmpl $2,(%esp)		# X86_TRAP_NMI
-	je .Lis_nmi		# Ignore NMI
-
-	cmpl $2,%ss:early_recursion_flag
-	je hlt_loop
 	incl %ss:early_recursion_flag
 
-	push %eax		# 16(%esp)
-	push %ecx		# 12(%esp)
-	push %edx		#  8(%esp)
-	push %ds		#  4(%esp)
-	push %es		#  0(%esp)
-	movl $(__KERNEL_DS),%eax
-	movl %eax,%ds
-	movl %eax,%es
+	/* The vector number is in pt_regs->gs */
 
-	cmpl $(__KERNEL_CS),32(%esp)
-	jne 10f
+	cld
+	pushl	%fs		/* pt_regs->fs */
+	movw	$0, 2(%esp)	/* clear high bits (some CPUs leave garbage) */
+	pushl	%es		/* pt_regs->es */
+	movw	$0, 2(%esp)	/* clear high bits (some CPUs leave garbage) */
+	pushl	%ds		/* pt_regs->ds */
+	movw	$0, 2(%esp)	/* clear high bits (some CPUs leave garbage) */
+	pushl	%eax		/* pt_regs->ax */
+	pushl	%ebp		/* pt_regs->bp */
+	pushl	%edi		/* pt_regs->di */
+	pushl	%esi		/* pt_regs->si */
+	pushl	%edx		/* pt_regs->dx */
+	pushl	%ecx		/* pt_regs->cx */
+	pushl	%ebx		/* pt_regs->bx */
 
-	leal 28(%esp),%eax	# Pointer to %eip
-	call early_fixup_exception
-	andl %eax,%eax
-	jnz ex_entry		/* found an exception entry */
+	/* Fix up DS and ES */
+	movl	$(__KERNEL_DS), %ecx
+	movl	%ecx, %ds
+	movl	%ecx, %es
 
-10:
-#ifdef CONFIG_PRINTK
-	xorl %eax,%eax
-	movw %ax,2(%esp)	/* clean up the segment values on some cpus */
-	movw %ax,6(%esp)
-	movw %ax,34(%esp)
-	leal  40(%esp),%eax
-	pushl %eax		/* %esp before the exception */
-	pushl %ebx
-	pushl %ebp
-	pushl %esi
-	pushl %edi
-	movl %cr2,%eax
-	pushl %eax
-	pushl (20+6*4)(%esp)	/* trapno */
-	pushl $fault_msg
-	call printk
-#endif
-	call dump_stack
-hlt_loop:
-	hlt
-	jmp hlt_loop
+	/* Load the vector number into EDX */
+	movl	PT_GS(%esp), %edx
 
-ex_entry:
-	pop %es
-	pop %ds
-	pop %edx
-	pop %ecx
-	pop %eax
-	decl %ss:early_recursion_flag
-.Lis_nmi:
-	addl $8,%esp		/* drop vector number and error code */
+	/* Load GS into pt_regs->gs and clear high bits */
+	movw	%gs, PT_GS(%esp)
+	movw	$0, PT_GS+2(%esp)
+
+	movl	%esp, %eax	/* args are pt_regs (EAX), trapnr (EDX) */
+	call	early_fixup_exception
+
+	popl	%ebx		/* pt_regs->bx */
+	popl	%ecx		/* pt_regs->cx */
+	popl	%edx		/* pt_regs->dx */
+	popl	%esi		/* pt_regs->si */
+	popl	%edi		/* pt_regs->di */
+	popl	%ebp		/* pt_regs->bp */
+	popl	%eax		/* pt_regs->ax */
+	popl	%ds		/* pt_regs->ds */
+	popl	%es		/* pt_regs->es */
+	popl	%fs		/* pt_regs->fs */
+	popl	%gs		/* pt_regs->gs */
+	decl	%ss:early_recursion_flag
+	addl	$4, %esp	/* pop pt_regs->orig_ax */
 	iret
 ENDPROC(early_idt_handler_common)
 
@@ -647,10 +638,14 @@ ignore_int:
 	popl %eax
 #endif
 	iret
+
+hlt_loop:
+	hlt
+	jmp hlt_loop
 ENDPROC(ignore_int)
 __INITDATA
 	.align 4
-early_recursion_flag:
+GLOBAL(early_recursion_flag)
 	.long 0
 
 __REFDATA
@@ -715,19 +710,6 @@ __INITRODATA
 int_msg:
 	.asciz "Unknown interrupt or fault at: %p %p %p\n"
 
-fault_msg:
-/* fault info: */
-	.ascii "BUG: Int %d: CR2 %p\n"
-/* regs pushed in early_idt_handler: */
-	.ascii "     EDI %p  ESI %p  EBP %p  EBX %p\n"
-	.ascii "     ESP %p   ES %p   DS %p\n"
-	.ascii "     EDX %p  ECX %p  EAX %p\n"
-/* fault frame: */
-	.ascii "     vec %p  err %p  EIP %p   CS %p  flg %p\n"
-	.ascii "Stack: %p %p %p %p %p %p %p %p\n"
-	.ascii "       %p %p %p %p %p %p %p %p\n"
-	.asciz "       %p %p %p %p %p %p %p %p\n"
-
 #include "../../x86/xen/xen-head.S"
 
 /*
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/head64.c linux-libre-4.7-gnu/arch/x86/kernel/head64.c
--- linux-libre-4.6-gnu/arch/x86/kernel/head64.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/head64.c	2016-07-24 15:23:50.000000000 -0400
@@ -182,6 +182,7 @@ void __init x86_64_start_reservations(ch
 	if (!boot_params.hdr.version)
 		copy_bootdata(__va(real_mode_data));
 
+	x86_early_init_platform_quirks();
 	reserve_ebda_region();
 
 	switch (boot_params.hdr.hardware_subarch) {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/head_64.S linux-libre-4.7-gnu/arch/x86/kernel/head_64.S
--- linux-libre-4.6-gnu/arch/x86/kernel/head_64.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/head_64.S	2016-07-24 15:23:50.000000000 -0400
@@ -20,6 +20,7 @@
 #include <asm/processor-flags.h>
 #include <asm/percpu.h>
 #include <asm/nops.h>
+#include "../entry/calling.h"
 
 #ifdef CONFIG_PARAVIRT
 #include <asm/asm-offsets.h>
@@ -64,6 +65,14 @@ startup_64:
 	 * tables and then reload them.
 	 */
 
+	/*
+	 * Setup stack for verify_cpu(). "-8" because stack_start is defined
+	 * this way, see below. Our best guess is a NULL ptr for stack
+	 * termination heuristics and we don't want to break anything which
+	 * might depend on it (kgdb, ...).
+	 */
+	leaq	(__end_init_task - 8)(%rip), %rsp
+
 	/* Sanitize CPU configuration */
 	call verify_cpu
 
@@ -350,90 +359,48 @@ early_idt_handler_common:
 	 */
 	cld
 
-	cmpl $2,(%rsp)		# X86_TRAP_NMI
-	je .Lis_nmi		# Ignore NMI
-
-	cmpl $2,early_recursion_flag(%rip)
-	jz  1f
 	incl early_recursion_flag(%rip)
 
-	pushq %rax		# 64(%rsp)
-	pushq %rcx		# 56(%rsp)
-	pushq %rdx		# 48(%rsp)
-	pushq %rsi		# 40(%rsp)
-	pushq %rdi		# 32(%rsp)
-	pushq %r8		# 24(%rsp)
-	pushq %r9		# 16(%rsp)
-	pushq %r10		#  8(%rsp)
-	pushq %r11		#  0(%rsp)
-
-	cmpl $__KERNEL_CS,96(%rsp)
-	jne 11f
+	/* The vector number is currently in the pt_regs->di slot. */
+	pushq %rsi				/* pt_regs->si */
+	movq 8(%rsp), %rsi			/* RSI = vector number */
+	movq %rdi, 8(%rsp)			/* pt_regs->di = RDI */
+	pushq %rdx				/* pt_regs->dx */
+	pushq %rcx				/* pt_regs->cx */
+	pushq %rax				/* pt_regs->ax */
+	pushq %r8				/* pt_regs->r8 */
+	pushq %r9				/* pt_regs->r9 */
+	pushq %r10				/* pt_regs->r10 */
+	pushq %r11				/* pt_regs->r11 */
+	pushq %rbx				/* pt_regs->bx */
+	pushq %rbp				/* pt_regs->bp */
+	pushq %r12				/* pt_regs->r12 */
+	pushq %r13				/* pt_regs->r13 */
+	pushq %r14				/* pt_regs->r14 */
+	pushq %r15				/* pt_regs->r15 */
 
-	cmpl $14,72(%rsp)	# Page fault?
+	cmpq $14,%rsi		/* Page fault? */
 	jnz 10f
-	GET_CR2_INTO(%rdi)	# can clobber any volatile register if pv
+	GET_CR2_INTO(%rdi)	/* Can clobber any volatile register if pv */
 	call early_make_pgtable
 	andl %eax,%eax
-	jz 20f			# All good
+	jz 20f			/* All good */
 
 10:
-	leaq 88(%rsp),%rdi	# Pointer to %rip
+	movq %rsp,%rdi		/* RDI = pt_regs; RSI is already trapnr */
 	call early_fixup_exception
-	andl %eax,%eax
-	jnz 20f			# Found an exception entry
-
-11:
-#ifdef CONFIG_EARLY_PRINTK
-	GET_CR2_INTO(%r9)	# can clobber any volatile register if pv
-	movl 80(%rsp),%r8d	# error code
-	movl 72(%rsp),%esi	# vector number
-	movl 96(%rsp),%edx	# %cs
-	movq 88(%rsp),%rcx	# %rip
-	xorl %eax,%eax
-	leaq early_idt_msg(%rip),%rdi
-	call early_printk
-	cmpl $2,early_recursion_flag(%rip)
-	jz  1f
-	call dump_stack
-#ifdef CONFIG_KALLSYMS	
-	leaq early_idt_ripmsg(%rip),%rdi
-	movq 40(%rsp),%rsi	# %rip again
-	call __print_symbol
-#endif
-#endif /* EARLY_PRINTK */
-1:	hlt
-	jmp 1b
 
-20:	# Exception table entry found or page table generated
-	popq %r11
-	popq %r10
-	popq %r9
-	popq %r8
-	popq %rdi
-	popq %rsi
-	popq %rdx
-	popq %rcx
-	popq %rax
+20:
 	decl early_recursion_flag(%rip)
-.Lis_nmi:
-	addq $16,%rsp		# drop vector number and error code
-	INTERRUPT_RETURN
+	jmp restore_regs_and_iret
 ENDPROC(early_idt_handler_common)
 
 	__INITDATA
 
 	.balign 4
-early_recursion_flag:
+GLOBAL(early_recursion_flag)
 	.long 0
 
-#ifdef CONFIG_EARLY_PRINTK
-early_idt_msg:
-	.asciz "PANIC: early exception %02lx rip %lx:%lx error %lx cr2 %lx\n"
-early_idt_ripmsg:
-	.asciz "RIP %s\n"
-#endif /* CONFIG_EARLY_PRINTK */
-
 #define NEXT_PAGE(name) \
 	.balign	PAGE_SIZE; \
 GLOBAL(name)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/head.c linux-libre-4.7-gnu/arch/x86/kernel/head.c
--- linux-libre-4.6-gnu/arch/x86/kernel/head.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/head.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,71 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/memblock.h>
-
-#include <asm/setup.h>
-#include <asm/bios_ebda.h>
-
-/*
- * The BIOS places the EBDA/XBDA at the top of conventional
- * memory, and usually decreases the reported amount of
- * conventional memory (int 0x12) too. This also contains a
- * workaround for Dell systems that neglect to reserve EBDA.
- * The same workaround also avoids a problem with the AMD768MPX
- * chipset: reserve a page before VGA to prevent PCI prefetch
- * into it (errata #56). Usually the page is reserved anyways,
- * unless you have no PS/2 mouse plugged in.
- *
- * This functions is deliberately very conservative.  Losing
- * memory in the bottom megabyte is rarely a problem, as long
- * as we have enough memory to install the trampoline.  Using
- * memory that is in use by the BIOS or by some DMA device
- * the BIOS didn't shut down *is* a big problem.
- */
-
-#define BIOS_LOWMEM_KILOBYTES	0x413
-#define LOWMEM_CAP		0x9f000U	/* Absolute maximum */
-#define INSANE_CUTOFF		0x20000U	/* Less than this = insane */
-
-void __init reserve_ebda_region(void)
-{
-	unsigned int lowmem, ebda_addr;
-
-	/*
-	 * To determine the position of the EBDA and the
-	 * end of conventional memory, we need to look at
-	 * the BIOS data area. In a paravirtual environment
-	 * that area is absent. We'll just have to assume
-	 * that the paravirt case can handle memory setup
-	 * correctly, without our help.
-	 */
-	if (paravirt_enabled())
-		return;
-
-	/* end of low (conventional) memory */
-	lowmem = *(unsigned short *)__va(BIOS_LOWMEM_KILOBYTES);
-	lowmem <<= 10;
-
-	/* start of EBDA area */
-	ebda_addr = get_bios_ebda();
-
-	/*
-	 * Note: some old Dells seem to need 4k EBDA without
-	 * reporting so, so just consider the memory above 0x9f000
-	 * to be off limits (bugzilla 2990).
-	 */
-
-	/* If the EBDA address is below 128K, assume it is bogus */
-	if (ebda_addr < INSANE_CUTOFF)
-		ebda_addr = LOWMEM_CAP;
-
-	/* If lowmem is less than 128K, assume it is bogus */
-	if (lowmem < INSANE_CUTOFF)
-		lowmem = LOWMEM_CAP;
-
-	/* Use the lower of the lowmem and EBDA markers as the cutoff */
-	lowmem = min(lowmem, ebda_addr);
-	lowmem = min(lowmem, LOWMEM_CAP); /* Absolute cap */
-
-	/* reserve all memory between lowmem and the 1MB mark */
-	memblock_reserve(lowmem, 0x100000 - lowmem);
-}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/hpet.c linux-libre-4.7-gnu/arch/x86/kernel/hpet.c
--- linux-libre-4.6-gnu/arch/x86/kernel/hpet.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/hpet.c	2016-07-24 15:23:50.000000000 -0400
@@ -54,7 +54,7 @@ struct hpet_dev {
 	char				name[10];
 };
 
-inline struct hpet_dev *EVT_TO_HPET_DEV(struct clock_event_device *evtdev)
+static inline struct hpet_dev *EVT_TO_HPET_DEV(struct clock_event_device *evtdev)
 {
 	return container_of(evtdev, struct hpet_dev, evt);
 }
@@ -773,7 +773,6 @@ static struct clocksource clocksource_hp
 	.mask		= HPET_MASK,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 	.resume		= hpet_resume_counter,
-	.archdata	= { .vclock_mode = VCLOCK_HPET },
 };
 
 static int hpet_clocksource_register(void)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/irq_32.c linux-libre-4.7-gnu/arch/x86/kernel/irq_32.c
--- linux-libre-4.6-gnu/arch/x86/kernel/irq_32.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/irq_32.c	2016-07-24 15:23:50.000000000 -0400
@@ -130,11 +130,9 @@ void irq_ctx_init(int cpu)
 
 void do_softirq_own_stack(void)
 {
-	struct thread_info *curstk;
 	struct irq_stack *irqstk;
 	u32 *isp, *prev_esp;
 
-	curstk = current_stack();
 	irqstk = __this_cpu_read(softirq_stack);
 
 	/* build the stack frame on the softirq stack */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/jump_label.c linux-libre-4.7-gnu/arch/x86/kernel/jump_label.c
--- linux-libre-4.6-gnu/arch/x86/kernel/jump_label.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/jump_label.c	2016-07-24 15:23:50.000000000 -0400
@@ -13,6 +13,7 @@
 #include <linux/cpu.h>
 #include <asm/kprobes.h>
 #include <asm/alternative.h>
+#include <asm/text-patching.h>
 
 #ifdef HAVE_JUMP_LABEL
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/kexec-bzimage64.c linux-libre-4.7-gnu/arch/x86/kernel/kexec-bzimage64.c
--- linux-libre-4.6-gnu/arch/x86/kernel/kexec-bzimage64.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/kexec-bzimage64.c	2016-07-24 15:23:50.000000000 -0400
@@ -19,8 +19,7 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/efi.h>
-#include <linux/verify_pefile.h>
-#include <keys/system_keyring.h>
+#include <linux/verification.h>
 
 #include <asm/bootparam.h>
 #include <asm/setup.h>
@@ -529,18 +528,9 @@ static int bzImage64_cleanup(void *loade
 #ifdef CONFIG_KEXEC_BZIMAGE_VERIFY_SIG
 static int bzImage64_verify_sig(const char *kernel, unsigned long kernel_len)
 {
-	bool trusted;
-	int ret;
-
-	ret = verify_pefile_signature(kernel, kernel_len,
-				      system_trusted_keyring,
-				      VERIFYING_KEXEC_PE_SIGNATURE,
-				      &trusted);
-	if (ret < 0)
-		return ret;
-	if (!trusted)
-		return -EKEYREJECTED;
-	return 0;
+	return verify_pefile_signature(kernel, kernel_len,
+				       NULL,
+				       VERIFYING_KEXEC_PE_SIGNATURE);
 }
 #endif
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/kgdb.c linux-libre-4.7-gnu/arch/x86/kernel/kgdb.c
--- linux-libre-4.6-gnu/arch/x86/kernel/kgdb.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/kgdb.c	2016-07-24 15:23:50.000000000 -0400
@@ -45,6 +45,7 @@
 #include <linux/uaccess.h>
 #include <linux/memory.h>
 
+#include <asm/text-patching.h>
 #include <asm/debugreg.h>
 #include <asm/apicdef.h>
 #include <asm/apic.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/kprobes/core.c linux-libre-4.7-gnu/arch/x86/kernel/kprobes/core.c
--- linux-libre-4.6-gnu/arch/x86/kernel/kprobes/core.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/kprobes/core.c	2016-07-24 15:23:50.000000000 -0400
@@ -51,6 +51,7 @@
 #include <linux/ftrace.h>
 #include <linux/frame.h>
 
+#include <asm/text-patching.h>
 #include <asm/cacheflush.h>
 #include <asm/desc.h>
 #include <asm/pgtable.h>
@@ -960,7 +961,19 @@ int kprobe_fault_handler(struct pt_regs
 		 * normal page fault.
 		 */
 		regs->ip = (unsigned long)cur->addr;
+		/*
+		 * Trap flag (TF) has been set here because this fault
+		 * happened where the single stepping will be done.
+		 * So clear it by resetting the current kprobe:
+		 */
+		regs->flags &= ~X86_EFLAGS_TF;
+
+		/*
+		 * If the TF flag was set before the kprobe hit,
+		 * don't touch it:
+		 */
 		regs->flags |= kcb->kprobe_old_flags;
+
 		if (kcb->kprobe_status == KPROBE_REENTER)
 			restore_previous_kprobe(kcb);
 		else
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/kprobes/opt.c linux-libre-4.7-gnu/arch/x86/kernel/kprobes/opt.c
--- linux-libre-4.6-gnu/arch/x86/kernel/kprobes/opt.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/kprobes/opt.c	2016-07-24 15:23:50.000000000 -0400
@@ -29,6 +29,7 @@
 #include <linux/kallsyms.h>
 #include <linux/ftrace.h>
 
+#include <asm/text-patching.h>
 #include <asm/cacheflush.h>
 #include <asm/desc.h>
 #include <asm/pgtable.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/kvm.c linux-libre-4.7-gnu/arch/x86/kernel/kvm.c
--- linux-libre-4.6-gnu/arch/x86/kernel/kvm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/kvm.c	2016-07-24 15:23:50.000000000 -0400
@@ -285,14 +285,6 @@ static void __init paravirt_ops_setup(vo
 {
 	pv_info.name = "KVM";
 
-	/*
-	 * KVM isn't paravirt in the sense of paravirt_enabled.  A KVM
-	 * guest kernel works like a bare metal kernel with additional
-	 * features, and paravirt_enabled is about features that are
-	 * missing.
-	 */
-	pv_info.paravirt_enabled = 0;
-
 	if (kvm_para_has_feature(KVM_FEATURE_NOP_IO_DELAY))
 		pv_cpu_ops.io_delay = kvm_io_delay;
 
@@ -522,7 +514,7 @@ static noinline uint32_t __kvm_cpuid_bas
 	if (boot_cpu_data.cpuid_level < 0)
 		return 0;	/* So we don't blow up on old processors */
 
-	if (cpu_has_hypervisor)
+	if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
 		return hypervisor_cpuid_base("KVMKVMKVM\0\0\0", 0);
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/livepatch.c linux-libre-4.7-gnu/arch/x86/kernel/livepatch.c
--- linux-libre-4.6-gnu/arch/x86/kernel/livepatch.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/livepatch.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,70 +0,0 @@
-/*
- * livepatch.c - x86-specific Kernel Live Patching Core
- *
- * Copyright (C) 2014 Seth Jennings <sjenning@redhat.com>
- * Copyright (C) 2014 SUSE
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/module.h>
-#include <linux/uaccess.h>
-#include <asm/elf.h>
-#include <asm/livepatch.h>
-
-/**
- * klp_write_module_reloc() - write a relocation in a module
- * @mod:	module in which the section to be modified is found
- * @type:	ELF relocation type (see asm/elf.h)
- * @loc:	address that the relocation should be written to
- * @value:	relocation value (sym address + addend)
- *
- * This function writes a relocation to the specified location for
- * a particular module.
- */
-int klp_write_module_reloc(struct module *mod, unsigned long type,
-			   unsigned long loc, unsigned long value)
-{
-	size_t size = 4;
-	unsigned long val;
-	unsigned long core = (unsigned long)mod->core_layout.base;
-	unsigned long core_size = mod->core_layout.size;
-
-	switch (type) {
-	case R_X86_64_NONE:
-		return 0;
-	case R_X86_64_64:
-		val = value;
-		size = 8;
-		break;
-	case R_X86_64_32:
-		val = (u32)value;
-		break;
-	case R_X86_64_32S:
-		val = (s32)value;
-		break;
-	case R_X86_64_PC32:
-		val = (u32)(value - loc);
-		break;
-	default:
-		/* unsupported relocation type */
-		return -EINVAL;
-	}
-
-	if (loc < core || loc >= core + core_size)
-		/* loc does not point to any symbol inside the module */
-		return -EINVAL;
-
-	return probe_kernel_write((void *)loc, &val, size);
-}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/machine_kexec_64.c linux-libre-4.7-gnu/arch/x86/kernel/machine_kexec_64.c
--- linux-libre-4.6-gnu/arch/x86/kernel/machine_kexec_64.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/machine_kexec_64.c	2016-07-24 15:23:50.000000000 -0400
@@ -538,3 +538,48 @@ overflow:
 	return -ENOEXEC;
 }
 #endif /* CONFIG_KEXEC_FILE */
+
+static int
+kexec_mark_range(unsigned long start, unsigned long end, bool protect)
+{
+	struct page *page;
+	unsigned int nr_pages;
+
+	/*
+	 * For physical range: [start, end]. We must skip the unassigned
+	 * crashk resource with zero-valued "end" member.
+	 */
+	if (!end || start > end)
+		return 0;
+
+	page = pfn_to_page(start >> PAGE_SHIFT);
+	nr_pages = (end >> PAGE_SHIFT) - (start >> PAGE_SHIFT) + 1;
+	if (protect)
+		return set_pages_ro(page, nr_pages);
+	else
+		return set_pages_rw(page, nr_pages);
+}
+
+static void kexec_mark_crashkres(bool protect)
+{
+	unsigned long control;
+
+	kexec_mark_range(crashk_low_res.start, crashk_low_res.end, protect);
+
+	/* Don't touch the control code page used in crash_kexec().*/
+	control = PFN_PHYS(page_to_pfn(kexec_crash_image->control_code_page));
+	/* Control code page is located in the 2nd page. */
+	kexec_mark_range(crashk_res.start, control + PAGE_SIZE - 1, protect);
+	control += KEXEC_CONTROL_PAGE_SIZE;
+	kexec_mark_range(control, crashk_res.end, protect);
+}
+
+void arch_kexec_protect_crashkres(void)
+{
+	kexec_mark_crashkres(true);
+}
+
+void arch_kexec_unprotect_crashkres(void)
+{
+	kexec_mark_crashkres(false);
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/Makefile linux-libre-4.7-gnu/arch/x86/kernel/Makefile
--- linux-libre-4.6-gnu/arch/x86/kernel/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -2,7 +2,11 @@
 # Makefile for the linux kernel.
 #
 
-extra-y                := head_$(BITS).o head$(BITS).o head.o vmlinux.lds
+extra-y	:= head_$(BITS).o
+extra-y	+= head$(BITS).o
+extra-y	+= ebda.o
+extra-y	+= platform-quirks.o
+extra-y	+= vmlinux.lds
 
 CPPFLAGS_vmlinux.lds += -U$(UTS_MACHINE)
 
@@ -79,7 +83,6 @@ obj-$(CONFIG_X86_MPPARSE)	+= mpparse.o
 obj-y				+= apic/
 obj-$(CONFIG_X86_REBOOTFIXUPS)	+= reboot_fixups_32.o
 obj-$(CONFIG_DYNAMIC_FTRACE)	+= ftrace.o
-obj-$(CONFIG_LIVEPATCH)		+= livepatch.o
 obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
 obj-$(CONFIG_FTRACE_SYSCALLS)	+= ftrace.o
 obj-$(CONFIG_X86_TSC)		+= trace_clock.o
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/mcount_64.S linux-libre-4.7-gnu/arch/x86/kernel/mcount_64.S
--- linux-libre-4.6-gnu/arch/x86/kernel/mcount_64.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/mcount_64.S	2016-07-24 15:23:50.000000000 -0400
@@ -182,7 +182,8 @@ GLOBAL(ftrace_graph_call)
 	jmp ftrace_stub
 #endif
 
-GLOBAL(ftrace_stub)
+/* This is weak to keep gas from relaxing the jumps */
+WEAK(ftrace_stub)
 	retq
 END(ftrace_caller)
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/module.c linux-libre-4.7-gnu/arch/x86/kernel/module.c
--- linux-libre-4.6-gnu/arch/x86/kernel/module.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/module.c	2016-07-24 15:23:50.000000000 -0400
@@ -31,6 +31,7 @@
 #include <linux/jump_label.h>
 #include <linux/random.h>
 
+#include <asm/text-patching.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/setup.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/paravirt.c linux-libre-4.7-gnu/arch/x86/kernel/paravirt.c
--- linux-libre-4.6-gnu/arch/x86/kernel/paravirt.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/paravirt.c	2016-07-24 15:23:50.000000000 -0400
@@ -294,7 +294,6 @@ enum paravirt_lazy_mode paravirt_get_laz
 
 struct pv_info pv_info = {
 	.name = "bare hardware",
-	.paravirt_enabled = 0,
 	.kernel_rpl = 0,
 	.shared_kernel_pmd = 1,	/* Only used when CONFIG_X86_PAE is set */
 
@@ -339,8 +338,10 @@ __visible struct pv_cpu_ops pv_cpu_ops =
 	.write_cr8 = native_write_cr8,
 #endif
 	.wbinvd = native_wbinvd,
-	.read_msr = native_read_msr_safe,
-	.write_msr = native_write_msr_safe,
+	.read_msr = native_read_msr,
+	.write_msr = native_write_msr,
+	.read_msr_safe = native_read_msr_safe,
+	.write_msr_safe = native_write_msr_safe,
 	.read_pmc = native_read_pmc,
 	.load_tr_desc = native_load_tr_desc,
 	.set_ldt = native_set_ldt,
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/pci-iommu_table.c linux-libre-4.7-gnu/arch/x86/kernel/pci-iommu_table.c
--- linux-libre-4.6-gnu/arch/x86/kernel/pci-iommu_table.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/pci-iommu_table.c	2016-07-24 15:23:50.000000000 -0400
@@ -72,7 +72,7 @@ void __init check_iommu_entries(struct i
 	}
 }
 #else
-inline void check_iommu_entries(struct iommu_table_entry *start,
+void __init check_iommu_entries(struct iommu_table_entry *start,
 				       struct iommu_table_entry *finish)
 {
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/platform-quirks.c linux-libre-4.7-gnu/arch/x86/kernel/platform-quirks.c
--- linux-libre-4.6-gnu/arch/x86/kernel/platform-quirks.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/x86/kernel/platform-quirks.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,35 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/setup.h>
+#include <asm/bios_ebda.h>
+
+void __init x86_early_init_platform_quirks(void)
+{
+	x86_platform.legacy.rtc = 1;
+	x86_platform.legacy.ebda_search = 0;
+	x86_platform.legacy.devices.pnpbios = 1;
+
+	switch (boot_params.hdr.hardware_subarch) {
+	case X86_SUBARCH_PC:
+		x86_platform.legacy.ebda_search = 1;
+		break;
+	case X86_SUBARCH_XEN:
+	case X86_SUBARCH_LGUEST:
+	case X86_SUBARCH_INTEL_MID:
+	case X86_SUBARCH_CE4100:
+		x86_platform.legacy.devices.pnpbios = 0;
+		x86_platform.legacy.rtc = 0;
+		break;
+	}
+
+	if (x86_platform.set_legacy_features)
+		x86_platform.set_legacy_features();
+}
+
+#if defined(CONFIG_PNPBIOS)
+bool __init arch_pnpbios_disabled(void)
+{
+	return x86_platform.legacy.devices.pnpbios == 0;
+}
+#endif
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/process_64.c linux-libre-4.7-gnu/arch/x86/kernel/process_64.c
--- linux-libre-4.6-gnu/arch/x86/kernel/process_64.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/process_64.c	2016-07-24 15:23:50.000000000 -0400
@@ -136,25 +136,6 @@ void release_thread(struct task_struct *
 	}
 }
 
-static inline void set_32bit_tls(struct task_struct *t, int tls, u32 addr)
-{
-	struct user_desc ud = {
-		.base_addr = addr,
-		.limit = 0xfffff,
-		.seg_32bit = 1,
-		.limit_in_pages = 1,
-		.useable = 1,
-	};
-	struct desc_struct *desc = t->thread.tls_array;
-	desc += tls;
-	fill_ldt(desc, &ud);
-}
-
-static inline u32 read_32bit_tls(struct task_struct *t, int tls)
-{
-	return get_desc_base(&t->thread.tls_array[tls]);
-}
-
 int copy_thread_tls(unsigned long clone_flags, unsigned long sp,
 		unsigned long arg, struct task_struct *p, unsigned long tls)
 {
@@ -169,9 +150,9 @@ int copy_thread_tls(unsigned long clone_
 	p->thread.io_bitmap_ptr = NULL;
 
 	savesegment(gs, p->thread.gsindex);
-	p->thread.gs = p->thread.gsindex ? 0 : me->thread.gs;
+	p->thread.gsbase = p->thread.gsindex ? 0 : me->thread.gsbase;
 	savesegment(fs, p->thread.fsindex);
-	p->thread.fs = p->thread.fsindex ? 0 : me->thread.fs;
+	p->thread.fsbase = p->thread.fsindex ? 0 : me->thread.fsbase;
 	savesegment(es, p->thread.es);
 	savesegment(ds, p->thread.ds);
 	memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
@@ -210,7 +191,7 @@ int copy_thread_tls(unsigned long clone_
 	 */
 	if (clone_flags & CLONE_SETTLS) {
 #ifdef CONFIG_IA32_EMULATION
-		if (is_ia32_task())
+		if (in_ia32_syscall())
 			err = do_set_thread_area(p, -1,
 				(struct user_desc __user *)tls, 0);
 		else
@@ -282,7 +263,7 @@ __switch_to(struct task_struct *prev_p,
 	struct fpu *next_fpu = &next->fpu;
 	int cpu = smp_processor_id();
 	struct tss_struct *tss = &per_cpu(cpu_tss, cpu);
-	unsigned fsindex, gsindex;
+	unsigned prev_fsindex, prev_gsindex;
 	fpu_switch_t fpu_switch;
 
 	fpu_switch = switch_fpu_prepare(prev_fpu, next_fpu, cpu);
@@ -292,8 +273,8 @@ __switch_to(struct task_struct *prev_p,
 	 *
 	 * (e.g. xen_load_tls())
 	 */
-	savesegment(fs, fsindex);
-	savesegment(gs, gsindex);
+	savesegment(fs, prev_fsindex);
+	savesegment(gs, prev_gsindex);
 
 	/*
 	 * Load TLS before restoring any segments so that segment loads
@@ -336,66 +317,104 @@ __switch_to(struct task_struct *prev_p,
 	 * Switch FS and GS.
 	 *
 	 * These are even more complicated than DS and ES: they have
-	 * 64-bit bases are that controlled by arch_prctl.  Those bases
-	 * only differ from the values in the GDT or LDT if the selector
-	 * is 0.
-	 *
-	 * Loading the segment register resets the hidden base part of
-	 * the register to 0 or the value from the GDT / LDT.  If the
-	 * next base address zero, writing 0 to the segment register is
-	 * much faster than using wrmsr to explicitly zero the base.
-	 *
-	 * The thread_struct.fs and thread_struct.gs values are 0
-	 * if the fs and gs bases respectively are not overridden
-	 * from the values implied by fsindex and gsindex.  They
-	 * are nonzero, and store the nonzero base addresses, if
-	 * the bases are overridden.
-	 *
-	 * (fs != 0 && fsindex != 0) || (gs != 0 && gsindex != 0) should
-	 * be impossible.
-	 *
-	 * Therefore we need to reload the segment registers if either
-	 * the old or new selector is nonzero, and we need to override
-	 * the base address if next thread expects it to be overridden.
+	 * 64-bit bases are that controlled by arch_prctl.  The bases
+	 * don't necessarily match the selectors, as user code can do
+	 * any number of things to cause them to be inconsistent.
 	 *
-	 * This code is unnecessarily slow in the case where the old and
-	 * new indexes are zero and the new base is nonzero -- it will
-	 * unnecessarily write 0 to the selector before writing the new
-	 * base address.
+	 * We don't promise to preserve the bases if the selectors are
+	 * nonzero.  We also don't promise to preserve the base if the
+	 * selector is zero and the base doesn't match whatever was
+	 * most recently passed to ARCH_SET_FS/GS.  (If/when the
+	 * FSGSBASE instructions are enabled, we'll need to offer
+	 * stronger guarantees.)
 	 *
-	 * Note: This all depends on arch_prctl being the only way that
-	 * user code can override the segment base.  Once wrfsbase and
-	 * wrgsbase are enabled, most of this code will need to change.
+	 * As an invariant,
+	 * (fsbase != 0 && fsindex != 0) || (gsbase != 0 && gsindex != 0) is
+	 * impossible.
 	 */
-	if (unlikely(fsindex | next->fsindex | prev->fs)) {
+	if (next->fsindex) {
+		/* Loading a nonzero value into FS sets the index and base. */
 		loadsegment(fs, next->fsindex);
-
-		/*
-		 * If user code wrote a nonzero value to FS, then it also
-		 * cleared the overridden base address.
-		 *
-		 * XXX: if user code wrote 0 to FS and cleared the base
-		 * address itself, we won't notice and we'll incorrectly
-		 * restore the prior base address next time we reschdule
-		 * the process.
-		 */
-		if (fsindex)
-			prev->fs = 0;
+	} else {
+		if (next->fsbase) {
+			/* Next index is zero but next base is nonzero. */
+			if (prev_fsindex)
+				loadsegment(fs, 0);
+			wrmsrl(MSR_FS_BASE, next->fsbase);
+		} else {
+			/* Next base and index are both zero. */
+			if (static_cpu_has_bug(X86_BUG_NULL_SEG)) {
+				/*
+				 * We don't know the previous base and can't
+				 * find out without RDMSR.  Forcibly clear it.
+				 */
+				loadsegment(fs, __USER_DS);
+				loadsegment(fs, 0);
+			} else {
+				/*
+				 * If the previous index is zero and ARCH_SET_FS
+				 * didn't change the base, then the base is
+				 * also zero and we don't need to do anything.
+				 */
+				if (prev->fsbase || prev_fsindex)
+					loadsegment(fs, 0);
+			}
+		}
 	}
-	if (next->fs)
-		wrmsrl(MSR_FS_BASE, next->fs);
-	prev->fsindex = fsindex;
+	/*
+	 * Save the old state and preserve the invariant.
+	 * NB: if prev_fsindex == 0, then we can't reliably learn the base
+	 * without RDMSR because Intel user code can zero it without telling
+	 * us and AMD user code can program any 32-bit value without telling
+	 * us.
+	 */
+	if (prev_fsindex)
+		prev->fsbase = 0;
+	prev->fsindex = prev_fsindex;
 
-	if (unlikely(gsindex | next->gsindex | prev->gs)) {
+	if (next->gsindex) {
+		/* Loading a nonzero value into GS sets the index and base. */
 		load_gs_index(next->gsindex);
-
-		/* This works (and fails) the same way as fsindex above. */
-		if (gsindex)
-			prev->gs = 0;
+	} else {
+		if (next->gsbase) {
+			/* Next index is zero but next base is nonzero. */
+			if (prev_gsindex)
+				load_gs_index(0);
+			wrmsrl(MSR_KERNEL_GS_BASE, next->gsbase);
+		} else {
+			/* Next base and index are both zero. */
+			if (static_cpu_has_bug(X86_BUG_NULL_SEG)) {
+				/*
+				 * We don't know the previous base and can't
+				 * find out without RDMSR.  Forcibly clear it.
+				 *
+				 * This contains a pointless SWAPGS pair.
+				 * Fixing it would involve an explicit check
+				 * for Xen or a new pvop.
+				 */
+				load_gs_index(__USER_DS);
+				load_gs_index(0);
+			} else {
+				/*
+				 * If the previous index is zero and ARCH_SET_GS
+				 * didn't change the base, then the base is
+				 * also zero and we don't need to do anything.
+				 */
+				if (prev->gsbase || prev_gsindex)
+					load_gs_index(0);
+			}
+		}
 	}
-	if (next->gs)
-		wrmsrl(MSR_KERNEL_GS_BASE, next->gs);
-	prev->gsindex = gsindex;
+	/*
+	 * Save the old state and preserve the invariant.
+	 * NB: if prev_gsindex == 0, then we can't reliably learn the base
+	 * without RDMSR because Intel user code can zero it without telling
+	 * us and AMD user code can program any 32-bit value without telling
+	 * us.
+	 */
+	if (prev_gsindex)
+		prev->gsbase = 0;
+	prev->gsindex = prev_gsindex;
 
 	switch_fpu_finish(next_fpu, fpu_switch);
 
@@ -513,81 +532,47 @@ long do_arch_prctl(struct task_struct *t
 
 	switch (code) {
 	case ARCH_SET_GS:
-		if (addr >= TASK_SIZE_OF(task))
+		if (addr >= TASK_SIZE_MAX)
 			return -EPERM;
 		cpu = get_cpu();
-		/* handle small bases via the GDT because that's faster to
-		   switch. */
-		if (addr <= 0xffffffff) {
-			set_32bit_tls(task, GS_TLS, addr);
-			if (doit) {
-				load_TLS(&task->thread, cpu);
-				load_gs_index(GS_TLS_SEL);
-			}
-			task->thread.gsindex = GS_TLS_SEL;
-			task->thread.gs = 0;
-		} else {
-			task->thread.gsindex = 0;
-			task->thread.gs = addr;
-			if (doit) {
-				load_gs_index(0);
-				ret = wrmsrl_safe(MSR_KERNEL_GS_BASE, addr);
-			}
+		task->thread.gsindex = 0;
+		task->thread.gsbase = addr;
+		if (doit) {
+			load_gs_index(0);
+			ret = wrmsrl_safe(MSR_KERNEL_GS_BASE, addr);
 		}
 		put_cpu();
 		break;
 	case ARCH_SET_FS:
 		/* Not strictly needed for fs, but do it for symmetry
 		   with gs */
-		if (addr >= TASK_SIZE_OF(task))
+		if (addr >= TASK_SIZE_MAX)
 			return -EPERM;
 		cpu = get_cpu();
-		/* handle small bases via the GDT because that's faster to
-		   switch. */
-		if (addr <= 0xffffffff) {
-			set_32bit_tls(task, FS_TLS, addr);
-			if (doit) {
-				load_TLS(&task->thread, cpu);
-				loadsegment(fs, FS_TLS_SEL);
-			}
-			task->thread.fsindex = FS_TLS_SEL;
-			task->thread.fs = 0;
-		} else {
-			task->thread.fsindex = 0;
-			task->thread.fs = addr;
-			if (doit) {
-				/* set the selector to 0 to not confuse
-				   __switch_to */
-				loadsegment(fs, 0);
-				ret = wrmsrl_safe(MSR_FS_BASE, addr);
-			}
+		task->thread.fsindex = 0;
+		task->thread.fsbase = addr;
+		if (doit) {
+			/* set the selector to 0 to not confuse __switch_to */
+			loadsegment(fs, 0);
+			ret = wrmsrl_safe(MSR_FS_BASE, addr);
 		}
 		put_cpu();
 		break;
 	case ARCH_GET_FS: {
 		unsigned long base;
-		if (task->thread.fsindex == FS_TLS_SEL)
-			base = read_32bit_tls(task, FS_TLS);
-		else if (doit)
+		if (doit)
 			rdmsrl(MSR_FS_BASE, base);
 		else
-			base = task->thread.fs;
+			base = task->thread.fsbase;
 		ret = put_user(base, (unsigned long __user *)addr);
 		break;
 	}
 	case ARCH_GET_GS: {
 		unsigned long base;
-		unsigned gsindex;
-		if (task->thread.gsindex == GS_TLS_SEL)
-			base = read_32bit_tls(task, GS_TLS);
-		else if (doit) {
-			savesegment(gs, gsindex);
-			if (gsindex)
-				rdmsrl(MSR_KERNEL_GS_BASE, base);
-			else
-				base = task->thread.gs;
-		} else
-			base = task->thread.gs;
+		if (doit)
+			rdmsrl(MSR_KERNEL_GS_BASE, base);
+		else
+			base = task->thread.gsbase;
 		ret = put_user(base, (unsigned long __user *)addr);
 		break;
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/process.c linux-libre-4.7-gnu/arch/x86/kernel/process.c
--- linux-libre-4.6-gnu/arch/x86/kernel/process.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/process.c	2016-07-24 15:23:50.000000000 -0400
@@ -97,10 +97,9 @@ int arch_dup_task_struct(struct task_str
 /*
  * Free current thread data structures etc..
  */
-void exit_thread(void)
+void exit_thread(struct task_struct *tsk)
 {
-	struct task_struct *me = current;
-	struct thread_struct *t = &me->thread;
+	struct thread_struct *t = &tsk->thread;
 	unsigned long *bp = t->io_bitmap_ptr;
 	struct fpu *fpu = &t->fpu;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/ptrace.c linux-libre-4.7-gnu/arch/x86/kernel/ptrace.c
--- linux-libre-4.6-gnu/arch/x86/kernel/ptrace.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/ptrace.c	2016-07-24 15:23:50.000000000 -0400
@@ -303,29 +303,11 @@ static int set_segment_reg(struct task_s
 
 	switch (offset) {
 	case offsetof(struct user_regs_struct,fs):
-		/*
-		 * If this is setting fs as for normal 64-bit use but
-		 * setting fs_base has implicitly changed it, leave it.
-		 */
-		if ((value == FS_TLS_SEL && task->thread.fsindex == 0 &&
-		     task->thread.fs != 0) ||
-		    (value == 0 && task->thread.fsindex == FS_TLS_SEL &&
-		     task->thread.fs == 0))
-			break;
 		task->thread.fsindex = value;
 		if (task == current)
 			loadsegment(fs, task->thread.fsindex);
 		break;
 	case offsetof(struct user_regs_struct,gs):
-		/*
-		 * If this is setting gs as for normal 64-bit use but
-		 * setting gs_base has implicitly changed it, leave it.
-		 */
-		if ((value == GS_TLS_SEL && task->thread.gsindex == 0 &&
-		     task->thread.gs != 0) ||
-		    (value == 0 && task->thread.gsindex == GS_TLS_SEL &&
-		     task->thread.gs == 0))
-			break;
 		task->thread.gsindex = value;
 		if (task == current)
 			load_gs_index(task->thread.gsindex);
@@ -410,23 +392,23 @@ static int putreg(struct task_struct *ch
 
 #ifdef CONFIG_X86_64
 	case offsetof(struct user_regs_struct,fs_base):
-		if (value >= TASK_SIZE_OF(child))
+		if (value >= TASK_SIZE_MAX)
 			return -EIO;
 		/*
 		 * When changing the segment base, use do_arch_prctl
 		 * to set either thread.fs or thread.fsindex and the
 		 * corresponding GDT slot.
 		 */
-		if (child->thread.fs != value)
+		if (child->thread.fsbase != value)
 			return do_arch_prctl(child, ARCH_SET_FS, value);
 		return 0;
 	case offsetof(struct user_regs_struct,gs_base):
 		/*
 		 * Exactly the same here as the %fs handling above.
 		 */
-		if (value >= TASK_SIZE_OF(child))
+		if (value >= TASK_SIZE_MAX)
 			return -EIO;
-		if (child->thread.gs != value)
+		if (child->thread.gsbase != value)
 			return do_arch_prctl(child, ARCH_SET_GS, value);
 		return 0;
 #endif
@@ -453,31 +435,17 @@ static unsigned long getreg(struct task_
 #ifdef CONFIG_X86_64
 	case offsetof(struct user_regs_struct, fs_base): {
 		/*
-		 * do_arch_prctl may have used a GDT slot instead of
-		 * the MSR.  To userland, it appears the same either
-		 * way, except the %fs segment selector might not be 0.
+		 * XXX: This will not behave as expected if called on
+		 * current or if fsindex != 0.
 		 */
-		unsigned int seg = task->thread.fsindex;
-		if (task->thread.fs != 0)
-			return task->thread.fs;
-		if (task == current)
-			asm("movl %%fs,%0" : "=r" (seg));
-		if (seg != FS_TLS_SEL)
-			return 0;
-		return get_desc_base(&task->thread.tls_array[FS_TLS]);
+		return task->thread.fsbase;
 	}
 	case offsetof(struct user_regs_struct, gs_base): {
 		/*
-		 * Exactly the same here as the %fs handling above.
+		 * XXX: This will not behave as expected if called on
+		 * current or if fsindex != 0.
 		 */
-		unsigned int seg = task->thread.gsindex;
-		if (task->thread.gs != 0)
-			return task->thread.gs;
-		if (task == current)
-			asm("movl %%gs,%0" : "=r" (seg));
-		if (seg != GS_TLS_SEL)
-			return 0;
-		return get_desc_base(&task->thread.tls_array[GS_TLS]);
+		return task->thread.gsbase;
 	}
 #endif
 	}
@@ -1266,7 +1234,7 @@ long compat_arch_ptrace(struct task_stru
 			compat_ulong_t caddr, compat_ulong_t cdata)
 {
 #ifdef CONFIG_X86_X32_ABI
-	if (!is_ia32_task())
+	if (!in_ia32_syscall())
 		return x32_arch_ptrace(child, request, caddr, cdata);
 #endif
 #ifdef CONFIG_IA32_EMULATION
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/pvclock.c linux-libre-4.7-gnu/arch/x86/kernel/pvclock.c
--- linux-libre-4.6-gnu/arch/x86/kernel/pvclock.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/pvclock.c	2016-07-24 15:23:50.000000000 -0400
@@ -61,11 +61,16 @@ void pvclock_resume(void)
 u8 pvclock_read_flags(struct pvclock_vcpu_time_info *src)
 {
 	unsigned version;
-	cycle_t ret;
 	u8 flags;
 
 	do {
-		version = __pvclock_read_cycles(src, &ret, &flags);
+		version = src->version;
+		/* Make the latest version visible */
+		smp_rmb();
+
+		flags = src->flags;
+		/* Make sure that the version double-check is last. */
+		smp_rmb();
 	} while ((src->version & 1) || version != src->version);
 
 	return flags & valid_flags;
@@ -80,6 +85,8 @@ cycle_t pvclock_clocksource_read(struct
 
 	do {
 		version = __pvclock_read_cycles(src, &ret, &flags);
+		/* Make sure that the version double-check is last. */
+		smp_rmb();
 	} while ((src->version & 1) || version != src->version);
 
 	if (unlikely((flags & PVCLOCK_GUEST_STOPPED) != 0)) {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/reboot.c linux-libre-4.7-gnu/arch/x86/kernel/reboot.c
--- linux-libre-4.6-gnu/arch/x86/kernel/reboot.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/reboot.c	2016-07-24 15:23:50.000000000 -0400
@@ -535,6 +535,15 @@ static void native_machine_emergency_res
 	mode = reboot_mode == REBOOT_WARM ? 0x1234 : 0;
 	*((unsigned short *)__va(0x472)) = mode;
 
+	/*
+	 * If an EFI capsule has been registered with the firmware then
+	 * override the reboot= parameter.
+	 */
+	if (efi_capsule_pending(NULL)) {
+		pr_info("EFI capsule is pending, forcing EFI reboot.\n");
+		reboot_type = BOOT_EFI;
+	}
+
 	for (;;) {
 		/* Could also try the reset bit in the Hammer NB */
 		switch (reboot_type) {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/rtc.c linux-libre-4.7-gnu/arch/x86/kernel/rtc.c
--- linux-libre-4.6-gnu/arch/x86/kernel/rtc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/rtc.c	2016-07-24 15:23:50.000000000 -0400
@@ -14,6 +14,7 @@
 #include <asm/time.h>
 #include <asm/intel-mid.h>
 #include <asm/rtc.h>
+#include <asm/setup.h>
 
 #ifdef CONFIG_X86_32
 /*
@@ -185,22 +186,7 @@ static __init int add_rtc_cmos(void)
 		}
 	}
 #endif
-	if (of_have_populated_dt())
-		return 0;
-
-	/* Intel MID platforms don't have ioport rtc */
-	if (intel_mid_identify_cpu())
-		return -ENODEV;
-
-#ifdef CONFIG_ACPI
-	if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_CMOS_RTC) {
-		/* This warning can likely go away again in a year or two. */
-		pr_info("ACPI: not registering RTC platform device\n");
-		return -ENODEV;
-	}
-#endif
-
-	if (paravirt_enabled() && !paravirt_has(RTC))
+	if (!x86_platform.legacy.rtc)
 		return -ENODEV;
 
 	platform_device_register(&rtc_device);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/setup.c linux-libre-4.7-gnu/arch/x86/kernel/setup.c
--- linux-libre-4.6-gnu/arch/x86/kernel/setup.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/setup.c	2016-07-24 15:23:50.000000000 -0400
@@ -398,6 +398,11 @@ static void __init reserve_initrd(void)
 
 	memblock_free(ramdisk_image, ramdisk_end - ramdisk_image);
 }
+
+static void __init early_initrd_acpi_init(void)
+{
+	early_acpi_table_init((void *)initrd_start, initrd_end - initrd_start);
+}
 #else
 static void __init early_reserve_initrd(void)
 {
@@ -405,6 +410,9 @@ static void __init early_reserve_initrd(
 static void __init reserve_initrd(void)
 {
 }
+static void __init early_initrd_acpi_init(void)
+{
+}
 #endif /* CONFIG_BLK_DEV_INITRD */
 
 static void __init parse_setup_data(void)
@@ -1138,9 +1146,7 @@ void __init setup_arch(char **cmdline_p)
 
 	reserve_initrd();
 
-#if defined(CONFIG_ACPI) && defined(CONFIG_BLK_DEV_INITRD)
-	acpi_initrd_override((void *)initrd_start, initrd_end - initrd_start);
-#endif
+	early_initrd_acpi_init();
 
 	vsmp_init();
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/signal.c linux-libre-4.7-gnu/arch/x86/kernel/signal.c
--- linux-libre-4.6-gnu/arch/x86/kernel/signal.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/signal.c	2016-07-24 15:23:50.000000000 -0400
@@ -248,18 +248,17 @@ get_sigframe(struct k_sigaction *ka, str
 	if (config_enabled(CONFIG_X86_64))
 		sp -= 128;
 
-	if (!onsigstack) {
-		/* This is the X/Open sanctioned signal stack switching.  */
-		if (ka->sa.sa_flags & SA_ONSTACK) {
-			if (current->sas_ss_size)
-				sp = current->sas_ss_sp + current->sas_ss_size;
-		} else if (config_enabled(CONFIG_X86_32) &&
-			   (regs->ss & 0xffff) != __USER_DS &&
-			   !(ka->sa.sa_flags & SA_RESTORER) &&
-			   ka->sa.sa_restorer) {
-				/* This is the legacy signal stack switching. */
-				sp = (unsigned long) ka->sa.sa_restorer;
-		}
+	/* This is the X/Open sanctioned signal stack switching.  */
+	if (ka->sa.sa_flags & SA_ONSTACK) {
+		if (sas_ss_flags(sp) == 0)
+			sp = current->sas_ss_sp + current->sas_ss_size;
+	} else if (config_enabled(CONFIG_X86_32) &&
+		   !onsigstack &&
+		   (regs->ss & 0xffff) != __USER_DS &&
+		   !(ka->sa.sa_flags & SA_RESTORER) &&
+		   ka->sa.sa_restorer) {
+		/* This is the legacy signal stack switching. */
+		sp = (unsigned long) ka->sa.sa_restorer;
 	}
 
 	if (fpu->fpstate_active) {
@@ -391,7 +390,7 @@ static int __setup_rt_frame(int sig, str
 		put_user_ex(&frame->uc, &frame->puc);
 
 		/* Create the ucontext.  */
-		if (cpu_has_xsave)
+		if (boot_cpu_has(X86_FEATURE_XSAVE))
 			put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);
 		else
 			put_user_ex(0, &frame->uc.uc_flags);
@@ -442,7 +441,7 @@ static unsigned long frame_uc_flags(stru
 {
 	unsigned long flags;
 
-	if (cpu_has_xsave)
+	if (boot_cpu_has(X86_FEATURE_XSAVE))
 		flags = UC_FP_XSTATE | UC_SIGCONTEXT_SS;
 	else
 		flags = UC_SIGCONTEXT_SS;
@@ -762,7 +761,7 @@ handle_signal(struct ksignal *ksig, stru
 static inline unsigned long get_nr_restart_syscall(const struct pt_regs *regs)
 {
 #ifdef CONFIG_X86_64
-	if (is_ia32_task())
+	if (in_ia32_syscall())
 		return __NR_ia32_restart_syscall;
 #endif
 #ifdef CONFIG_X86_X32_ABI
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/smpboot.c linux-libre-4.7-gnu/arch/x86/kernel/smpboot.c
--- linux-libre-4.6-gnu/arch/x86/kernel/smpboot.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/smpboot.c	2016-07-24 15:23:50.000000000 -0400
@@ -1236,7 +1236,7 @@ static int __init smp_sanity_check(unsig
 	 * If we couldn't find a local APIC, then get out of here now!
 	 */
 	if (APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid]) &&
-	    !cpu_has_apic) {
+	    !boot_cpu_has(X86_FEATURE_APIC)) {
 		if (!disable_apic) {
 			pr_err("BIOS bug, local APIC #%d not detected!...\n",
 				boot_cpu_physical_apicid);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/sysfb_efi.c linux-libre-4.7-gnu/arch/x86/kernel/sysfb_efi.c
--- linux-libre-4.6-gnu/arch/x86/kernel/sysfb_efi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/sysfb_efi.c	2016-07-24 15:23:50.000000000 -0400
@@ -68,6 +68,21 @@ struct efifb_dmi_info efifb_dmi_list[] =
 	[M_UNKNOWN] = { NULL, 0, 0, 0, 0, OVERRIDE_NONE }
 };
 
+void efifb_setup_from_dmi(struct screen_info *si, const char *opt)
+{
+	int i;
+
+	for (i = 0; i < M_UNKNOWN; i++) {
+		if (efifb_dmi_list[i].base != 0 &&
+		    !strcmp(opt, efifb_dmi_list[i].optname)) {
+			si->lfb_base = efifb_dmi_list[i].base;
+			si->lfb_linelength = efifb_dmi_list[i].stride;
+			si->lfb_width = efifb_dmi_list[i].width;
+			si->lfb_height = efifb_dmi_list[i].height;
+		}
+	}
+}
+
 #define choose_value(dmivalue, fwvalue, field, flags) ({	\
 		typeof(fwvalue) _ret_ = fwvalue;		\
 		if ((flags) & (field))				\
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/tboot.c linux-libre-4.7-gnu/arch/x86/kernel/tboot.c
--- linux-libre-4.6-gnu/arch/x86/kernel/tboot.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/tboot.c	2016-07-24 15:23:50.000000000 -0400
@@ -74,12 +74,6 @@ void __init tboot_probe(void)
 		return;
 	}
 
-	/* only a natively booted kernel should be using TXT */
-	if (paravirt_enabled()) {
-		pr_warning("non-0 tboot_addr but pv_ops is enabled\n");
-		return;
-	}
-
 	/* Map and check for tboot UUID. */
 	set_fixmap(FIX_TBOOT_BASE, boot_params.tboot_addr);
 	tboot = (struct tboot *)fix_to_virt(FIX_TBOOT_BASE);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/tce_64.c linux-libre-4.7-gnu/arch/x86/kernel/tce_64.c
--- linux-libre-4.6-gnu/arch/x86/kernel/tce_64.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/tce_64.c	2016-07-24 15:23:50.000000000 -0400
@@ -40,7 +40,7 @@
 static inline void flush_tce(void* tceaddr)
 {
 	/* a single tce can't cross a cache line */
-	if (cpu_has_clflush)
+	if (boot_cpu_has(X86_FEATURE_CLFLUSH))
 		clflush(tceaddr);
 	else
 		wbinvd();
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/tls.c linux-libre-4.7-gnu/arch/x86/kernel/tls.c
--- linux-libre-4.6-gnu/arch/x86/kernel/tls.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/tls.c	2016-07-24 15:23:50.000000000 -0400
@@ -114,6 +114,7 @@ int do_set_thread_area(struct task_struc
 		       int can_allocate)
 {
 	struct user_desc info;
+	unsigned short __maybe_unused sel, modified_sel;
 
 	if (copy_from_user(&info, u_info, sizeof(info)))
 		return -EFAULT;
@@ -141,6 +142,47 @@ int do_set_thread_area(struct task_struc
 
 	set_tls_desc(p, idx, &info, 1);
 
+	/*
+	 * If DS, ES, FS, or GS points to the modified segment, forcibly
+	 * refresh it.  Only needed on x86_64 because x86_32 reloads them
+	 * on return to user mode.
+	 */
+	modified_sel = (idx << 3) | 3;
+
+	if (p == current) {
+#ifdef CONFIG_X86_64
+		savesegment(ds, sel);
+		if (sel == modified_sel)
+			loadsegment(ds, sel);
+
+		savesegment(es, sel);
+		if (sel == modified_sel)
+			loadsegment(es, sel);
+
+		savesegment(fs, sel);
+		if (sel == modified_sel)
+			loadsegment(fs, sel);
+
+		savesegment(gs, sel);
+		if (sel == modified_sel)
+			load_gs_index(sel);
+#endif
+
+#ifdef CONFIG_X86_32_LAZY_GS
+		savesegment(gs, sel);
+		if (sel == modified_sel)
+			loadsegment(gs, sel);
+#endif
+	} else {
+#ifdef CONFIG_X86_64
+		if (p->thread.fsindex == modified_sel)
+			p->thread.fsbase = info.base_addr;
+
+		if (p->thread.gsindex == modified_sel)
+			p->thread.gsbase = info.base_addr;
+#endif
+	}
+
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/traps.c linux-libre-4.7-gnu/arch/x86/kernel/traps.c
--- linux-libre-4.6-gnu/arch/x86/kernel/traps.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/traps.c	2016-07-24 15:23:50.000000000 -0400
@@ -51,6 +51,7 @@
 #include <asm/processor.h>
 #include <asm/debugreg.h>
 #include <linux/atomic.h>
+#include <asm/text-patching.h>
 #include <asm/ftrace.h>
 #include <asm/traps.h>
 #include <asm/desc.h>
@@ -95,6 +96,12 @@ static inline void cond_local_irq_disabl
 		local_irq_disable();
 }
 
+/*
+ * In IST context, we explicitly disable preemption.  This serves two
+ * purposes: it makes it much less likely that we would accidentally
+ * schedule in IST context and it will force a warning if we somehow
+ * manage to schedule by accident.
+ */
 void ist_enter(struct pt_regs *regs)
 {
 	if (user_mode(regs)) {
@@ -109,13 +116,7 @@ void ist_enter(struct pt_regs *regs)
 		rcu_nmi_enter();
 	}
 
-	/*
-	 * We are atomic because we're on the IST stack; or we're on
-	 * x86_32, in which case we still shouldn't schedule; or we're
-	 * on x86_64 and entered from user mode, in which case we're
-	 * still atomic unless ist_begin_non_atomic is called.
-	 */
-	preempt_count_add(HARDIRQ_OFFSET);
+	preempt_disable();
 
 	/* This code is a bit fragile.  Test it. */
 	RCU_LOCKDEP_WARN(!rcu_is_watching(), "ist_enter didn't work");
@@ -123,7 +124,7 @@ void ist_enter(struct pt_regs *regs)
 
 void ist_exit(struct pt_regs *regs)
 {
-	preempt_count_sub(HARDIRQ_OFFSET);
+	preempt_enable_no_resched();
 
 	if (!user_mode(regs))
 		rcu_nmi_exit();
@@ -154,7 +155,7 @@ void ist_begin_non_atomic(struct pt_regs
 	BUG_ON((unsigned long)(current_top_of_stack() -
 			       current_stack_pointer()) >= THREAD_SIZE);
 
-	preempt_count_sub(HARDIRQ_OFFSET);
+	preempt_enable_no_resched();
 }
 
 /**
@@ -164,7 +165,7 @@ void ist_begin_non_atomic(struct pt_regs
  */
 void ist_end_non_atomic(void)
 {
-	preempt_count_add(HARDIRQ_OFFSET);
+	preempt_disable();
 }
 
 static nokprobe_inline int
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/tsc.c linux-libre-4.7-gnu/arch/x86/kernel/tsc.c
--- linux-libre-4.6-gnu/arch/x86/kernel/tsc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/tsc.c	2016-07-24 15:23:50.000000000 -0400
@@ -36,7 +36,7 @@ static int __read_mostly tsc_unstable;
 
 /* native_sched_clock() is called before tsc_init(), so
    we must start with the TSC soft disabled to prevent
-   erroneous rdtsc usage on !cpu_has_tsc processors */
+   erroneous rdtsc usage on !boot_cpu_has(X86_FEATURE_TSC) processors */
 static int __read_mostly tsc_disabled = -1;
 
 static DEFINE_STATIC_KEY_FALSE(__use_tsc);
@@ -834,15 +834,15 @@ int recalibrate_cpu_khz(void)
 #ifndef CONFIG_SMP
 	unsigned long cpu_khz_old = cpu_khz;
 
-	if (cpu_has_tsc) {
-		tsc_khz = x86_platform.calibrate_tsc();
-		cpu_khz = tsc_khz;
-		cpu_data(0).loops_per_jiffy =
-			cpufreq_scale(cpu_data(0).loops_per_jiffy,
-					cpu_khz_old, cpu_khz);
-		return 0;
-	} else
+	if (!boot_cpu_has(X86_FEATURE_TSC))
 		return -ENODEV;
+
+	tsc_khz = x86_platform.calibrate_tsc();
+	cpu_khz = tsc_khz;
+	cpu_data(0).loops_per_jiffy = cpufreq_scale(cpu_data(0).loops_per_jiffy,
+						    cpu_khz_old, cpu_khz);
+
+	return 0;
 #else
 	return -ENODEV;
 #endif
@@ -922,9 +922,6 @@ static int time_cpufreq_notifier(struct
 	struct cpufreq_freqs *freq = data;
 	unsigned long *lpj;
 
-	if (cpu_has(&cpu_data(freq->cpu), X86_FEATURE_CONSTANT_TSC))
-		return 0;
-
 	lpj = &boot_cpu_data.loops_per_jiffy;
 #ifdef CONFIG_SMP
 	if (!(freq->flags & CPUFREQ_CONST_LOOPS))
@@ -954,9 +951,9 @@ static struct notifier_block time_cpufre
 	.notifier_call  = time_cpufreq_notifier
 };
 
-static int __init cpufreq_tsc(void)
+static int __init cpufreq_register_tsc_scaling(void)
 {
-	if (!cpu_has_tsc)
+	if (!boot_cpu_has(X86_FEATURE_TSC))
 		return 0;
 	if (boot_cpu_has(X86_FEATURE_CONSTANT_TSC))
 		return 0;
@@ -965,7 +962,7 @@ static int __init cpufreq_tsc(void)
 	return 0;
 }
 
-core_initcall(cpufreq_tsc);
+core_initcall(cpufreq_register_tsc_scaling);
 
 #endif /* CONFIG_CPU_FREQ */
 
@@ -1081,7 +1078,7 @@ static void __init check_system_tsc_reli
  */
 int unsynchronized_tsc(void)
 {
-	if (!cpu_has_tsc || tsc_unstable)
+	if (!boot_cpu_has(X86_FEATURE_TSC) || tsc_unstable)
 		return 1;
 
 #ifdef CONFIG_SMP
@@ -1205,7 +1202,7 @@ out:
 
 static int __init init_tsc_clocksource(void)
 {
-	if (!cpu_has_tsc || tsc_disabled > 0 || !tsc_khz)
+	if (!boot_cpu_has(X86_FEATURE_TSC) || tsc_disabled > 0 || !tsc_khz)
 		return 0;
 
 	if (tsc_clocksource_reliable)
@@ -1242,7 +1239,7 @@ void __init tsc_init(void)
 	u64 lpj;
 	int cpu;
 
-	if (!cpu_has_tsc) {
+	if (!boot_cpu_has(X86_FEATURE_TSC)) {
 		setup_clear_cpu_cap(X86_FEATURE_TSC_DEADLINE_TIMER);
 		return;
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/tsc_msr.c linux-libre-4.7-gnu/arch/x86/kernel/tsc_msr.c
--- linux-libre-4.6-gnu/arch/x86/kernel/tsc_msr.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/tsc_msr.c	2016-07-24 15:23:50.000000000 -0400
@@ -23,6 +23,7 @@
 #include <asm/param.h>
 
 /* CPU reference clock frequency: in KHz */
+#define FREQ_80		80000
 #define FREQ_83		83200
 #define FREQ_100	99840
 #define FREQ_133	133200
@@ -56,6 +57,8 @@ static struct freq_desc freq_desc_tables
 	{ 6, 0x37, 1, { FREQ_83, FREQ_100, FREQ_133, FREQ_166, 0, 0, 0, 0 } },
 	/* ANN */
 	{ 6, 0x5a, 1, { FREQ_83, FREQ_100, FREQ_133, FREQ_100, 0, 0, 0, 0 } },
+	/* AIRMONT */
+	{ 6, 0x4c, 1, { FREQ_83, FREQ_100, FREQ_133, FREQ_166, FREQ_80,	0, 0, 0 } },
 };
 
 static int match_cpu(u8 family, u8 model)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/uprobes.c linux-libre-4.7-gnu/arch/x86/kernel/uprobes.c
--- linux-libre-4.6-gnu/arch/x86/kernel/uprobes.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/uprobes.c	2016-07-24 15:23:50.000000000 -0400
@@ -516,7 +516,7 @@ struct uprobe_xol_ops {
 
 static inline int sizeof_long(void)
 {
-	return is_ia32_task() ? 4 : 8;
+	return in_ia32_syscall() ? 4 : 8;
 }
 
 static int default_pre_xol_op(struct arch_uprobe *auprobe, struct pt_regs *regs)
@@ -578,7 +578,7 @@ static void default_abort_op(struct arch
 	riprel_post_xol(auprobe, regs);
 }
 
-static struct uprobe_xol_ops default_xol_ops = {
+static const struct uprobe_xol_ops default_xol_ops = {
 	.pre_xol  = default_pre_xol_op,
 	.post_xol = default_post_xol_op,
 	.abort	  = default_abort_op,
@@ -695,7 +695,7 @@ static void branch_clear_offset(struct a
 		0, insn->immediate.nbytes);
 }
 
-static struct uprobe_xol_ops branch_xol_ops = {
+static const struct uprobe_xol_ops branch_xol_ops = {
 	.emulate  = branch_emulate_op,
 	.post_xol = branch_post_xol_op,
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kernel/vmlinux.lds.S linux-libre-4.7-gnu/arch/x86/kernel/vmlinux.lds.S
--- linux-libre-4.6-gnu/arch/x86/kernel/vmlinux.lds.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kernel/vmlinux.lds.S	2016-07-24 15:23:50.000000000 -0400
@@ -334,7 +334,7 @@ SECTIONS
 		__brk_limit = .;
 	}
 
-	. = ALIGN(PAGE_SIZE);
+	. = ALIGN(PAGE_SIZE);		/* keep VO_INIT_SIZE page aligned */
 	_end = .;
 
         STABS_DEBUG
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kvm/cpuid.c linux-libre-4.7-gnu/arch/x86/kvm/cpuid.c
--- linux-libre-4.6-gnu/arch/x86/kvm/cpuid.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kvm/cpuid.c	2016-07-24 15:23:50.000000000 -0400
@@ -75,7 +75,7 @@ int kvm_update_cpuid(struct kvm_vcpu *vc
 		return 0;
 
 	/* Update OSXSAVE bit */
-	if (cpu_has_xsave && best->function == 0x1) {
+	if (boot_cpu_has(X86_FEATURE_XSAVE) && best->function == 0x1) {
 		best->ecx &= ~F(OSXSAVE);
 		if (kvm_read_cr4_bits(vcpu, X86_CR4_OSXSAVE))
 			best->ecx |= F(OSXSAVE);
@@ -181,19 +181,22 @@ int kvm_vcpu_ioctl_set_cpuid(struct kvm_
 			     struct kvm_cpuid_entry __user *entries)
 {
 	int r, i;
-	struct kvm_cpuid_entry *cpuid_entries;
+	struct kvm_cpuid_entry *cpuid_entries = NULL;
 
 	r = -E2BIG;
 	if (cpuid->nent > KVM_MAX_CPUID_ENTRIES)
 		goto out;
 	r = -ENOMEM;
-	cpuid_entries = vmalloc(sizeof(struct kvm_cpuid_entry) * cpuid->nent);
-	if (!cpuid_entries)
-		goto out;
-	r = -EFAULT;
-	if (copy_from_user(cpuid_entries, entries,
-			   cpuid->nent * sizeof(struct kvm_cpuid_entry)))
-		goto out_free;
+	if (cpuid->nent) {
+		cpuid_entries = vmalloc(sizeof(struct kvm_cpuid_entry) *
+					cpuid->nent);
+		if (!cpuid_entries)
+			goto out;
+		r = -EFAULT;
+		if (copy_from_user(cpuid_entries, entries,
+				   cpuid->nent * sizeof(struct kvm_cpuid_entry)))
+			goto out;
+	}
 	for (i = 0; i < cpuid->nent; i++) {
 		vcpu->arch.cpuid_entries[i].function = cpuid_entries[i].function;
 		vcpu->arch.cpuid_entries[i].eax = cpuid_entries[i].eax;
@@ -212,9 +215,8 @@ int kvm_vcpu_ioctl_set_cpuid(struct kvm_
 	kvm_x86_ops->cpuid_update(vcpu);
 	r = kvm_update_cpuid(vcpu);
 
-out_free:
-	vfree(cpuid_entries);
 out:
+	vfree(cpuid_entries);
 	return r;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kvm/ioapic.c linux-libre-4.7-gnu/arch/x86/kvm/ioapic.c
--- linux-libre-4.6-gnu/arch/x86/kvm/ioapic.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kvm/ioapic.c	2016-07-24 15:23:50.000000000 -0400
@@ -443,7 +443,7 @@ static void __kvm_ioapic_update_eoi(stru
 		spin_lock(&ioapic->lock);
 
 		if (trigger_mode != IOAPIC_LEVEL_TRIG ||
-		    kvm_apic_get_reg(apic, APIC_SPIV) & APIC_SPIV_DIRECTED_EOI)
+		    kvm_lapic_get_reg(apic, APIC_SPIV) & APIC_SPIV_DIRECTED_EOI)
 			continue;
 
 		ASSERT(ent->fields.trig_mode == IOAPIC_LEVEL_TRIG);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kvm/iommu.c linux-libre-4.7-gnu/arch/x86/kvm/iommu.c
--- linux-libre-4.6-gnu/arch/x86/kvm/iommu.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kvm/iommu.c	2016-07-24 15:23:50.000000000 -0400
@@ -254,7 +254,7 @@ int kvm_iommu_map_guest(struct kvm *kvm)
 	    !iommu_capable(&pci_bus_type, IOMMU_CAP_INTR_REMAP)) {
 		printk(KERN_WARNING "%s: No interrupt remapping support,"
 		       " disallowing device assignment."
-		       " Re-enble with \"allow_unsafe_assigned_interrupts=1\""
+		       " Re-enable with \"allow_unsafe_assigned_interrupts=1\""
 		       " module option.\n", __func__);
 		iommu_domain_free(kvm->arch.iommu_domain);
 		kvm->arch.iommu_domain = NULL;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kvm/irq_comm.c linux-libre-4.7-gnu/arch/x86/kvm/irq_comm.c
--- linux-libre-4.6-gnu/arch/x86/kvm/irq_comm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kvm/irq_comm.c	2016-07-24 15:23:50.000000000 -0400
@@ -382,9 +382,6 @@ void kvm_scan_ioapic_routes(struct kvm_v
 	u32 i, nr_ioapic_pins;
 	int idx;
 
-	/* kvm->irq_routing must be read after clearing
-	 * KVM_SCAN_IOAPIC. */
-	smp_mb();
 	idx = srcu_read_lock(&kvm->irq_srcu);
 	table = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu);
 	nr_ioapic_pins = min_t(u32, table->nr_rt_entries,
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kvm/lapic.c linux-libre-4.7-gnu/arch/x86/kvm/lapic.c
--- linux-libre-4.6-gnu/arch/x86/kvm/lapic.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kvm/lapic.c	2016-07-24 15:23:50.000000000 -0400
@@ -59,9 +59,8 @@
 /* #define apic_debug(fmt,arg...) printk(KERN_WARNING fmt,##arg) */
 #define apic_debug(fmt, arg...)
 
-#define APIC_LVT_NUM			6
 /* 14 is the version for Xeon and Pentium 8.4.8*/
-#define APIC_VERSION			(0x14UL | ((APIC_LVT_NUM - 1) << 16))
+#define APIC_VERSION			(0x14UL | ((KVM_APIC_LVT_NUM - 1) << 16))
 #define LAPIC_MMIO_LENGTH		(1 << 12)
 /* followed define is not in apicdef.h */
 #define APIC_SHORT_MASK			0xc0000
@@ -73,14 +72,6 @@
 #define APIC_BROADCAST			0xFF
 #define X2APIC_BROADCAST		0xFFFFFFFFul
 
-#define VEC_POS(v) ((v) & (32 - 1))
-#define REG_POS(v) (((v) >> 5) << 4)
-
-static inline void apic_set_reg(struct kvm_lapic *apic, int reg_off, u32 val)
-{
-	*((u32 *) (apic->regs + reg_off)) = val;
-}
-
 static inline int apic_test_vector(int vec, void *bitmap)
 {
 	return test_bit(VEC_POS(vec), (bitmap) + REG_POS(vec));
@@ -94,11 +85,6 @@ bool kvm_apic_pending_eoi(struct kvm_vcp
 		apic_test_vector(vector, apic->regs + APIC_IRR);
 }
 
-static inline void apic_set_vector(int vec, void *bitmap)
-{
-	set_bit(VEC_POS(vec), (bitmap) + REG_POS(vec));
-}
-
 static inline void apic_clear_vector(int vec, void *bitmap)
 {
 	clear_bit(VEC_POS(vec), (bitmap) + REG_POS(vec));
@@ -173,7 +159,7 @@ static void recalculate_apic_map(struct
 			continue;
 
 		aid = kvm_apic_id(apic);
-		ldr = kvm_apic_get_reg(apic, APIC_LDR);
+		ldr = kvm_lapic_get_reg(apic, APIC_LDR);
 
 		if (aid < ARRAY_SIZE(new->phys_map))
 			new->phys_map[aid] = apic;
@@ -182,7 +168,7 @@ static void recalculate_apic_map(struct
 			new->mode |= KVM_APIC_MODE_X2APIC;
 		} else if (ldr) {
 			ldr = GET_APIC_LOGICAL_ID(ldr);
-			if (kvm_apic_get_reg(apic, APIC_DFR) == APIC_DFR_FLAT)
+			if (kvm_lapic_get_reg(apic, APIC_DFR) == APIC_DFR_FLAT)
 				new->mode |= KVM_APIC_MODE_XAPIC_FLAT;
 			else
 				new->mode |= KVM_APIC_MODE_XAPIC_CLUSTER;
@@ -212,7 +198,7 @@ static inline void apic_set_spiv(struct
 {
 	bool enabled = val & APIC_SPIV_APIC_ENABLED;
 
-	apic_set_reg(apic, APIC_SPIV, val);
+	kvm_lapic_set_reg(apic, APIC_SPIV, val);
 
 	if (enabled != apic->sw_enabled) {
 		apic->sw_enabled = enabled;
@@ -226,13 +212,13 @@ static inline void apic_set_spiv(struct
 
 static inline void kvm_apic_set_id(struct kvm_lapic *apic, u8 id)
 {
-	apic_set_reg(apic, APIC_ID, id << 24);
+	kvm_lapic_set_reg(apic, APIC_ID, id << 24);
 	recalculate_apic_map(apic->vcpu->kvm);
 }
 
 static inline void kvm_apic_set_ldr(struct kvm_lapic *apic, u32 id)
 {
-	apic_set_reg(apic, APIC_LDR, id);
+	kvm_lapic_set_reg(apic, APIC_LDR, id);
 	recalculate_apic_map(apic->vcpu->kvm);
 }
 
@@ -240,19 +226,19 @@ static inline void kvm_apic_set_x2apic_i
 {
 	u32 ldr = ((id >> 4) << 16) | (1 << (id & 0xf));
 
-	apic_set_reg(apic, APIC_ID, id << 24);
-	apic_set_reg(apic, APIC_LDR, ldr);
+	kvm_lapic_set_reg(apic, APIC_ID, id << 24);
+	kvm_lapic_set_reg(apic, APIC_LDR, ldr);
 	recalculate_apic_map(apic->vcpu->kvm);
 }
 
 static inline int apic_lvt_enabled(struct kvm_lapic *apic, int lvt_type)
 {
-	return !(kvm_apic_get_reg(apic, lvt_type) & APIC_LVT_MASKED);
+	return !(kvm_lapic_get_reg(apic, lvt_type) & APIC_LVT_MASKED);
 }
 
 static inline int apic_lvt_vector(struct kvm_lapic *apic, int lvt_type)
 {
-	return kvm_apic_get_reg(apic, lvt_type) & APIC_VECTOR_MASK;
+	return kvm_lapic_get_reg(apic, lvt_type) & APIC_VECTOR_MASK;
 }
 
 static inline int apic_lvtt_oneshot(struct kvm_lapic *apic)
@@ -287,10 +273,10 @@ void kvm_apic_set_version(struct kvm_vcp
 	feat = kvm_find_cpuid_entry(apic->vcpu, 0x1, 0);
 	if (feat && (feat->ecx & (1 << (X86_FEATURE_X2APIC & 31))))
 		v |= APIC_LVR_DIRECTED_EOI;
-	apic_set_reg(apic, APIC_LVR, v);
+	kvm_lapic_set_reg(apic, APIC_LVR, v);
 }
 
-static const unsigned int apic_lvt_mask[APIC_LVT_NUM] = {
+static const unsigned int apic_lvt_mask[KVM_APIC_LVT_NUM] = {
 	LVT_MASK ,      /* part LVTT mask, timer mode mask added at runtime */
 	LVT_MASK | APIC_MODE_MASK,	/* LVTTHMR */
 	LVT_MASK | APIC_MODE_MASK,	/* LVTPC */
@@ -349,16 +335,6 @@ void kvm_apic_update_irr(struct kvm_vcpu
 }
 EXPORT_SYMBOL_GPL(kvm_apic_update_irr);
 
-static inline void apic_set_irr(int vec, struct kvm_lapic *apic)
-{
-	apic_set_vector(vec, apic->regs + APIC_IRR);
-	/*
-	 * irr_pending must be true if any interrupt is pending; set it after
-	 * APIC_IRR to avoid race with apic_clear_irr
-	 */
-	apic->irr_pending = true;
-}
-
 static inline int apic_search_irr(struct kvm_lapic *apic)
 {
 	return find_highest_vector(apic->regs + APIC_IRR);
@@ -416,7 +392,7 @@ static inline void apic_set_isr(int vec,
 	 * just set SVI.
 	 */
 	if (unlikely(vcpu->arch.apicv_active))
-		kvm_x86_ops->hwapic_isr_update(vcpu->kvm, vec);
+		kvm_x86_ops->hwapic_isr_update(vcpu, vec);
 	else {
 		++apic->isr_count;
 		BUG_ON(apic->isr_count > MAX_APIC_VECTOR);
@@ -464,7 +440,7 @@ static inline void apic_clear_isr(int ve
 	 * and must be left alone.
 	 */
 	if (unlikely(vcpu->arch.apicv_active))
-		kvm_x86_ops->hwapic_isr_update(vcpu->kvm,
+		kvm_x86_ops->hwapic_isr_update(vcpu,
 					       apic_find_highest_isr(apic));
 	else {
 		--apic->isr_count;
@@ -549,8 +525,8 @@ static void apic_update_ppr(struct kvm_l
 	u32 tpr, isrv, ppr, old_ppr;
 	int isr;
 
-	old_ppr = kvm_apic_get_reg(apic, APIC_PROCPRI);
-	tpr = kvm_apic_get_reg(apic, APIC_TASKPRI);
+	old_ppr = kvm_lapic_get_reg(apic, APIC_PROCPRI);
+	tpr = kvm_lapic_get_reg(apic, APIC_TASKPRI);
 	isr = apic_find_highest_isr(apic);
 	isrv = (isr != -1) ? isr : 0;
 
@@ -563,7 +539,7 @@ static void apic_update_ppr(struct kvm_l
 		   apic, ppr, isr, isrv);
 
 	if (old_ppr != ppr) {
-		apic_set_reg(apic, APIC_PROCPRI, ppr);
+		kvm_lapic_set_reg(apic, APIC_PROCPRI, ppr);
 		if (ppr < old_ppr)
 			kvm_make_request(KVM_REQ_EVENT, apic->vcpu);
 	}
@@ -571,7 +547,7 @@ static void apic_update_ppr(struct kvm_l
 
 static void apic_set_tpr(struct kvm_lapic *apic, u32 tpr)
 {
-	apic_set_reg(apic, APIC_TASKPRI, tpr);
+	kvm_lapic_set_reg(apic, APIC_TASKPRI, tpr);
 	apic_update_ppr(apic);
 }
 
@@ -601,7 +577,7 @@ static bool kvm_apic_match_logical_addr(
 	if (kvm_apic_broadcast(apic, mda))
 		return true;
 
-	logical_id = kvm_apic_get_reg(apic, APIC_LDR);
+	logical_id = kvm_lapic_get_reg(apic, APIC_LDR);
 
 	if (apic_x2apic_mode(apic))
 		return ((logical_id >> 16) == (mda >> 16))
@@ -610,7 +586,7 @@ static bool kvm_apic_match_logical_addr(
 	logical_id = GET_APIC_LOGICAL_ID(logical_id);
 	mda = GET_APIC_DEST_FIELD(mda);
 
-	switch (kvm_apic_get_reg(apic, APIC_DFR)) {
+	switch (kvm_lapic_get_reg(apic, APIC_DFR)) {
 	case APIC_DFR_FLAT:
 		return (logical_id & mda) != 0;
 	case APIC_DFR_CLUSTER:
@@ -618,7 +594,7 @@ static bool kvm_apic_match_logical_addr(
 		       && (logical_id & mda & 0xf) != 0;
 	default:
 		apic_debug("Bad DFR vcpu %d: %08x\n",
-			   apic->vcpu->vcpu_id, kvm_apic_get_reg(apic, APIC_DFR));
+			   apic->vcpu->vcpu_id, kvm_lapic_get_reg(apic, APIC_DFR));
 		return false;
 	}
 }
@@ -668,6 +644,7 @@ bool kvm_apic_match_dest(struct kvm_vcpu
 		return false;
 	}
 }
+EXPORT_SYMBOL_GPL(kvm_apic_match_dest);
 
 int kvm_vector_to_index(u32 vector, u32 dest_vcpus,
 		       const unsigned long *bitmap, u32 bitmap_size)
@@ -921,7 +898,7 @@ static int __apic_accept_irq(struct kvm_
 
 		if (apic_test_vector(vector, apic->regs + APIC_TMR) != !!trig_mode) {
 			if (trig_mode)
-				apic_set_vector(vector, apic->regs + APIC_TMR);
+				kvm_lapic_set_vector(vector, apic->regs + APIC_TMR);
 			else
 				apic_clear_vector(vector, apic->regs + APIC_TMR);
 		}
@@ -929,7 +906,7 @@ static int __apic_accept_irq(struct kvm_
 		if (vcpu->arch.apicv_active)
 			kvm_x86_ops->deliver_posted_interrupt(vcpu, vector);
 		else {
-			apic_set_irr(vector, apic);
+			kvm_lapic_set_irr(vector, apic);
 
 			kvm_make_request(KVM_REQ_EVENT, vcpu);
 			kvm_vcpu_kick(vcpu);
@@ -1073,8 +1050,8 @@ EXPORT_SYMBOL_GPL(kvm_apic_set_eoi_accel
 
 static void apic_send_ipi(struct kvm_lapic *apic)
 {
-	u32 icr_low = kvm_apic_get_reg(apic, APIC_ICR);
-	u32 icr_high = kvm_apic_get_reg(apic, APIC_ICR2);
+	u32 icr_low = kvm_lapic_get_reg(apic, APIC_ICR);
+	u32 icr_high = kvm_lapic_get_reg(apic, APIC_ICR2);
 	struct kvm_lapic_irq irq;
 
 	irq.vector = icr_low & APIC_VECTOR_MASK;
@@ -1111,7 +1088,7 @@ static u32 apic_get_tmcct(struct kvm_lap
 	ASSERT(apic != NULL);
 
 	/* if initial count is 0, current count should also be 0 */
-	if (kvm_apic_get_reg(apic, APIC_TMICT) == 0 ||
+	if (kvm_lapic_get_reg(apic, APIC_TMICT) == 0 ||
 		apic->lapic_timer.period == 0)
 		return 0;
 
@@ -1168,13 +1145,13 @@ static u32 __apic_read(struct kvm_lapic
 		break;
 	case APIC_PROCPRI:
 		apic_update_ppr(apic);
-		val = kvm_apic_get_reg(apic, offset);
+		val = kvm_lapic_get_reg(apic, offset);
 		break;
 	case APIC_TASKPRI:
 		report_tpr_access(apic, false);
 		/* fall thru */
 	default:
-		val = kvm_apic_get_reg(apic, offset);
+		val = kvm_lapic_get_reg(apic, offset);
 		break;
 	}
 
@@ -1186,7 +1163,7 @@ static inline struct kvm_lapic *to_lapic
 	return container_of(dev, struct kvm_lapic, dev);
 }
 
-static int apic_reg_read(struct kvm_lapic *apic, u32 offset, int len,
+int kvm_lapic_reg_read(struct kvm_lapic *apic, u32 offset, int len,
 		void *data)
 {
 	unsigned char alignment = offset & 0xf;
@@ -1223,6 +1200,7 @@ static int apic_reg_read(struct kvm_lapi
 	}
 	return 0;
 }
+EXPORT_SYMBOL_GPL(kvm_lapic_reg_read);
 
 static int apic_mmio_in_range(struct kvm_lapic *apic, gpa_t addr)
 {
@@ -1240,7 +1218,7 @@ static int apic_mmio_read(struct kvm_vcp
 	if (!apic_mmio_in_range(apic, address))
 		return -EOPNOTSUPP;
 
-	apic_reg_read(apic, offset, len, data);
+	kvm_lapic_reg_read(apic, offset, len, data);
 
 	return 0;
 }
@@ -1249,7 +1227,7 @@ static void update_divide_count(struct k
 {
 	u32 tmp1, tmp2, tdcr;
 
-	tdcr = kvm_apic_get_reg(apic, APIC_TDCR);
+	tdcr = kvm_lapic_get_reg(apic, APIC_TDCR);
 	tmp1 = tdcr & 0xf;
 	tmp2 = ((tmp1 & 0x3) | ((tmp1 & 0x8) >> 1)) + 1;
 	apic->divide_count = 0x1 << (tmp2 & 0x7);
@@ -1260,7 +1238,7 @@ static void update_divide_count(struct k
 
 static void apic_update_lvtt(struct kvm_lapic *apic)
 {
-	u32 timer_mode = kvm_apic_get_reg(apic, APIC_LVTT) &
+	u32 timer_mode = kvm_lapic_get_reg(apic, APIC_LVTT) &
 			apic->lapic_timer.timer_mode_mask;
 
 	if (apic->lapic_timer.timer_mode != timer_mode) {
@@ -1296,7 +1274,7 @@ static void apic_timer_expired(struct kv
 static bool lapic_timer_int_injected(struct kvm_vcpu *vcpu)
 {
 	struct kvm_lapic *apic = vcpu->arch.apic;
-	u32 reg = kvm_apic_get_reg(apic, APIC_LVTT);
+	u32 reg = kvm_lapic_get_reg(apic, APIC_LVTT);
 
 	if (kvm_apic_hw_enabled(apic)) {
 		int vec = reg & APIC_VECTOR_MASK;
@@ -1332,7 +1310,8 @@ void wait_lapic_expire(struct kvm_vcpu *
 
 	/* __delay is delay_tsc whenever the hardware has TSC, thus always.  */
 	if (guest_tsc < tsc_deadline)
-		__delay(tsc_deadline - guest_tsc);
+		__delay(min(tsc_deadline - guest_tsc,
+			nsec_to_cycles(vcpu, lapic_timer_advance_ns)));
 }
 
 static void start_apic_timer(struct kvm_lapic *apic)
@@ -1344,7 +1323,7 @@ static void start_apic_timer(struct kvm_
 	if (apic_lvtt_period(apic) || apic_lvtt_oneshot(apic)) {
 		/* lapic timer in oneshot or periodic mode */
 		now = apic->lapic_timer.timer.base->get_time();
-		apic->lapic_timer.period = (u64)kvm_apic_get_reg(apic, APIC_TMICT)
+		apic->lapic_timer.period = (u64)kvm_lapic_get_reg(apic, APIC_TMICT)
 			    * APIC_BUS_CYCLE_NS * apic->divide_count;
 
 		if (!apic->lapic_timer.period)
@@ -1376,7 +1355,7 @@ static void start_apic_timer(struct kvm_
 			   "timer initial count 0x%x, period %lldns, "
 			   "expire @ 0x%016" PRIx64 ".\n", __func__,
 			   APIC_BUS_CYCLE_NS, ktime_to_ns(now),
-			   kvm_apic_get_reg(apic, APIC_TMICT),
+			   kvm_lapic_get_reg(apic, APIC_TMICT),
 			   apic->lapic_timer.period,
 			   ktime_to_ns(ktime_add_ns(now,
 					apic->lapic_timer.period)));
@@ -1425,7 +1404,7 @@ static void apic_manage_nmi_watchdog(str
 	}
 }
 
-static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
+int kvm_lapic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
 {
 	int ret = 0;
 
@@ -1457,7 +1436,7 @@ static int apic_reg_write(struct kvm_lap
 
 	case APIC_DFR:
 		if (!apic_x2apic_mode(apic)) {
-			apic_set_reg(apic, APIC_DFR, val | 0x0FFFFFFF);
+			kvm_lapic_set_reg(apic, APIC_DFR, val | 0x0FFFFFFF);
 			recalculate_apic_map(apic->vcpu->kvm);
 		} else
 			ret = 1;
@@ -1465,17 +1444,17 @@ static int apic_reg_write(struct kvm_lap
 
 	case APIC_SPIV: {
 		u32 mask = 0x3ff;
-		if (kvm_apic_get_reg(apic, APIC_LVR) & APIC_LVR_DIRECTED_EOI)
+		if (kvm_lapic_get_reg(apic, APIC_LVR) & APIC_LVR_DIRECTED_EOI)
 			mask |= APIC_SPIV_DIRECTED_EOI;
 		apic_set_spiv(apic, val & mask);
 		if (!(val & APIC_SPIV_APIC_ENABLED)) {
 			int i;
 			u32 lvt_val;
 
-			for (i = 0; i < APIC_LVT_NUM; i++) {
-				lvt_val = kvm_apic_get_reg(apic,
+			for (i = 0; i < KVM_APIC_LVT_NUM; i++) {
+				lvt_val = kvm_lapic_get_reg(apic,
 						       APIC_LVTT + 0x10 * i);
-				apic_set_reg(apic, APIC_LVTT + 0x10 * i,
+				kvm_lapic_set_reg(apic, APIC_LVTT + 0x10 * i,
 					     lvt_val | APIC_LVT_MASKED);
 			}
 			apic_update_lvtt(apic);
@@ -1486,14 +1465,14 @@ static int apic_reg_write(struct kvm_lap
 	}
 	case APIC_ICR:
 		/* No delay here, so we always clear the pending bit */
-		apic_set_reg(apic, APIC_ICR, val & ~(1 << 12));
+		kvm_lapic_set_reg(apic, APIC_ICR, val & ~(1 << 12));
 		apic_send_ipi(apic);
 		break;
 
 	case APIC_ICR2:
 		if (!apic_x2apic_mode(apic))
 			val &= 0xff000000;
-		apic_set_reg(apic, APIC_ICR2, val);
+		kvm_lapic_set_reg(apic, APIC_ICR2, val);
 		break;
 
 	case APIC_LVT0:
@@ -1507,7 +1486,7 @@ static int apic_reg_write(struct kvm_lap
 			val |= APIC_LVT_MASKED;
 
 		val &= apic_lvt_mask[(reg - APIC_LVTT) >> 4];
-		apic_set_reg(apic, reg, val);
+		kvm_lapic_set_reg(apic, reg, val);
 
 		break;
 
@@ -1515,7 +1494,7 @@ static int apic_reg_write(struct kvm_lap
 		if (!kvm_apic_sw_enabled(apic))
 			val |= APIC_LVT_MASKED;
 		val &= (apic_lvt_mask[0] | apic->lapic_timer.timer_mode_mask);
-		apic_set_reg(apic, APIC_LVTT, val);
+		kvm_lapic_set_reg(apic, APIC_LVTT, val);
 		apic_update_lvtt(apic);
 		break;
 
@@ -1524,14 +1503,14 @@ static int apic_reg_write(struct kvm_lap
 			break;
 
 		hrtimer_cancel(&apic->lapic_timer.timer);
-		apic_set_reg(apic, APIC_TMICT, val);
+		kvm_lapic_set_reg(apic, APIC_TMICT, val);
 		start_apic_timer(apic);
 		break;
 
 	case APIC_TDCR:
 		if (val & 4)
 			apic_debug("KVM_WRITE:TDCR %x\n", val);
-		apic_set_reg(apic, APIC_TDCR, val);
+		kvm_lapic_set_reg(apic, APIC_TDCR, val);
 		update_divide_count(apic);
 		break;
 
@@ -1544,7 +1523,7 @@ static int apic_reg_write(struct kvm_lap
 
 	case APIC_SELF_IPI:
 		if (apic_x2apic_mode(apic)) {
-			apic_reg_write(apic, APIC_ICR, 0x40000 | (val & 0xff));
+			kvm_lapic_reg_write(apic, APIC_ICR, 0x40000 | (val & 0xff));
 		} else
 			ret = 1;
 		break;
@@ -1556,6 +1535,7 @@ static int apic_reg_write(struct kvm_lap
 		apic_debug("Local APIC Write to read-only register %x\n", reg);
 	return ret;
 }
+EXPORT_SYMBOL_GPL(kvm_lapic_reg_write);
 
 static int apic_mmio_write(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
 			    gpa_t address, int len, const void *data)
@@ -1585,14 +1565,14 @@ static int apic_mmio_write(struct kvm_vc
 		apic_debug("%s: offset 0x%x with length 0x%x, and value is "
 			   "0x%x\n", __func__, offset, len, val);
 
-	apic_reg_write(apic, offset & 0xff0, val);
+	kvm_lapic_reg_write(apic, offset & 0xff0, val);
 
 	return 0;
 }
 
 void kvm_lapic_set_eoi(struct kvm_vcpu *vcpu)
 {
-	apic_reg_write(vcpu->arch.apic, APIC_EOI, 0);
+	kvm_lapic_reg_write(vcpu->arch.apic, APIC_EOI, 0);
 }
 EXPORT_SYMBOL_GPL(kvm_lapic_set_eoi);
 
@@ -1604,10 +1584,10 @@ void kvm_apic_write_nodecode(struct kvm_
 	/* hw has done the conditional check and inst decode */
 	offset &= 0xff0;
 
-	apic_reg_read(vcpu->arch.apic, offset, 4, &val);
+	kvm_lapic_reg_read(vcpu->arch.apic, offset, 4, &val);
 
 	/* TODO: optimize to just emulate side effect w/o one more write */
-	apic_reg_write(vcpu->arch.apic, offset, val);
+	kvm_lapic_reg_write(vcpu->arch.apic, offset, val);
 }
 EXPORT_SYMBOL_GPL(kvm_apic_write_nodecode);
 
@@ -1667,14 +1647,14 @@ void kvm_lapic_set_tpr(struct kvm_vcpu *
 	struct kvm_lapic *apic = vcpu->arch.apic;
 
 	apic_set_tpr(apic, ((cr8 & 0x0f) << 4)
-		     | (kvm_apic_get_reg(apic, APIC_TASKPRI) & 4));
+		     | (kvm_lapic_get_reg(apic, APIC_TASKPRI) & 4));
 }
 
 u64 kvm_lapic_get_cr8(struct kvm_vcpu *vcpu)
 {
 	u64 tpr;
 
-	tpr = (u64) kvm_apic_get_reg(vcpu->arch.apic, APIC_TASKPRI);
+	tpr = (u64) kvm_lapic_get_reg(vcpu->arch.apic, APIC_TASKPRI);
 
 	return (tpr & 0xf0) >> 4;
 }
@@ -1740,28 +1720,28 @@ void kvm_lapic_reset(struct kvm_vcpu *vc
 		kvm_apic_set_id(apic, vcpu->vcpu_id);
 	kvm_apic_set_version(apic->vcpu);
 
-	for (i = 0; i < APIC_LVT_NUM; i++)
-		apic_set_reg(apic, APIC_LVTT + 0x10 * i, APIC_LVT_MASKED);
+	for (i = 0; i < KVM_APIC_LVT_NUM; i++)
+		kvm_lapic_set_reg(apic, APIC_LVTT + 0x10 * i, APIC_LVT_MASKED);
 	apic_update_lvtt(apic);
 	if (kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_LINT0_REENABLED))
-		apic_set_reg(apic, APIC_LVT0,
+		kvm_lapic_set_reg(apic, APIC_LVT0,
 			     SET_APIC_DELIVERY_MODE(0, APIC_MODE_EXTINT));
-	apic_manage_nmi_watchdog(apic, kvm_apic_get_reg(apic, APIC_LVT0));
+	apic_manage_nmi_watchdog(apic, kvm_lapic_get_reg(apic, APIC_LVT0));
 
-	apic_set_reg(apic, APIC_DFR, 0xffffffffU);
+	kvm_lapic_set_reg(apic, APIC_DFR, 0xffffffffU);
 	apic_set_spiv(apic, 0xff);
-	apic_set_reg(apic, APIC_TASKPRI, 0);
+	kvm_lapic_set_reg(apic, APIC_TASKPRI, 0);
 	if (!apic_x2apic_mode(apic))
 		kvm_apic_set_ldr(apic, 0);
-	apic_set_reg(apic, APIC_ESR, 0);
-	apic_set_reg(apic, APIC_ICR, 0);
-	apic_set_reg(apic, APIC_ICR2, 0);
-	apic_set_reg(apic, APIC_TDCR, 0);
-	apic_set_reg(apic, APIC_TMICT, 0);
+	kvm_lapic_set_reg(apic, APIC_ESR, 0);
+	kvm_lapic_set_reg(apic, APIC_ICR, 0);
+	kvm_lapic_set_reg(apic, APIC_ICR2, 0);
+	kvm_lapic_set_reg(apic, APIC_TDCR, 0);
+	kvm_lapic_set_reg(apic, APIC_TMICT, 0);
 	for (i = 0; i < 8; i++) {
-		apic_set_reg(apic, APIC_IRR + 0x10 * i, 0);
-		apic_set_reg(apic, APIC_ISR + 0x10 * i, 0);
-		apic_set_reg(apic, APIC_TMR + 0x10 * i, 0);
+		kvm_lapic_set_reg(apic, APIC_IRR + 0x10 * i, 0);
+		kvm_lapic_set_reg(apic, APIC_ISR + 0x10 * i, 0);
+		kvm_lapic_set_reg(apic, APIC_TMR + 0x10 * i, 0);
 	}
 	apic->irr_pending = vcpu->arch.apicv_active;
 	apic->isr_count = vcpu->arch.apicv_active ? 1 : 0;
@@ -1806,7 +1786,7 @@ int apic_has_pending_timer(struct kvm_vc
 
 int kvm_apic_local_deliver(struct kvm_lapic *apic, int lvt_type)
 {
-	u32 reg = kvm_apic_get_reg(apic, lvt_type);
+	u32 reg = kvm_lapic_get_reg(apic, lvt_type);
 	int vector, mode, trig_mode;
 
 	if (kvm_apic_hw_enabled(apic) && !(reg & APIC_LVT_MASKED)) {
@@ -1901,14 +1881,14 @@ int kvm_apic_has_interrupt(struct kvm_vc
 	apic_update_ppr(apic);
 	highest_irr = apic_find_highest_irr(apic);
 	if ((highest_irr == -1) ||
-	    ((highest_irr & 0xF0) <= kvm_apic_get_reg(apic, APIC_PROCPRI)))
+	    ((highest_irr & 0xF0) <= kvm_lapic_get_reg(apic, APIC_PROCPRI)))
 		return -1;
 	return highest_irr;
 }
 
 int kvm_apic_accept_pic_intr(struct kvm_vcpu *vcpu)
 {
-	u32 lvt0 = kvm_apic_get_reg(vcpu->arch.apic, APIC_LVT0);
+	u32 lvt0 = kvm_lapic_get_reg(vcpu->arch.apic, APIC_LVT0);
 	int r = 0;
 
 	if (!kvm_apic_hw_enabled(vcpu->arch.apic))
@@ -1974,7 +1954,7 @@ void kvm_apic_post_state_restore(struct
 	apic_update_ppr(apic);
 	hrtimer_cancel(&apic->lapic_timer.timer);
 	apic_update_lvtt(apic);
-	apic_manage_nmi_watchdog(apic, kvm_apic_get_reg(apic, APIC_LVT0));
+	apic_manage_nmi_watchdog(apic, kvm_lapic_get_reg(apic, APIC_LVT0));
 	update_divide_count(apic);
 	start_apic_timer(apic);
 	apic->irr_pending = true;
@@ -1982,9 +1962,11 @@ void kvm_apic_post_state_restore(struct
 				1 : count_vectors(apic->regs + APIC_ISR);
 	apic->highest_isr_cache = -1;
 	if (vcpu->arch.apicv_active) {
+		if (kvm_x86_ops->apicv_post_state_restore)
+			kvm_x86_ops->apicv_post_state_restore(vcpu);
 		kvm_x86_ops->hwapic_irr_update(vcpu,
 				apic_find_highest_irr(apic));
-		kvm_x86_ops->hwapic_isr_update(vcpu->kvm,
+		kvm_x86_ops->hwapic_isr_update(vcpu,
 				apic_find_highest_isr(apic));
 	}
 	kvm_make_request(KVM_REQ_EVENT, vcpu);
@@ -2097,7 +2079,7 @@ void kvm_lapic_sync_to_vapic(struct kvm_
 	if (!test_bit(KVM_APIC_CHECK_VAPIC, &vcpu->arch.apic_attention))
 		return;
 
-	tpr = kvm_apic_get_reg(apic, APIC_TASKPRI) & 0xff;
+	tpr = kvm_lapic_get_reg(apic, APIC_TASKPRI) & 0xff;
 	max_irr = apic_find_highest_irr(apic);
 	if (max_irr < 0)
 		max_irr = 0;
@@ -2139,8 +2121,8 @@ int kvm_x2apic_msr_write(struct kvm_vcpu
 
 	/* if this is ICR write vector before command */
 	if (reg == APIC_ICR)
-		apic_reg_write(apic, APIC_ICR2, (u32)(data >> 32));
-	return apic_reg_write(apic, reg, (u32)data);
+		kvm_lapic_reg_write(apic, APIC_ICR2, (u32)(data >> 32));
+	return kvm_lapic_reg_write(apic, reg, (u32)data);
 }
 
 int kvm_x2apic_msr_read(struct kvm_vcpu *vcpu, u32 msr, u64 *data)
@@ -2157,10 +2139,10 @@ int kvm_x2apic_msr_read(struct kvm_vcpu
 		return 1;
 	}
 
-	if (apic_reg_read(apic, reg, 4, &low))
+	if (kvm_lapic_reg_read(apic, reg, 4, &low))
 		return 1;
 	if (reg == APIC_ICR)
-		apic_reg_read(apic, APIC_ICR2, 4, &high);
+		kvm_lapic_reg_read(apic, APIC_ICR2, 4, &high);
 
 	*data = (((u64)high) << 32) | low;
 
@@ -2176,8 +2158,8 @@ int kvm_hv_vapic_msr_write(struct kvm_vc
 
 	/* if this is ICR write vector before command */
 	if (reg == APIC_ICR)
-		apic_reg_write(apic, APIC_ICR2, (u32)(data >> 32));
-	return apic_reg_write(apic, reg, (u32)data);
+		kvm_lapic_reg_write(apic, APIC_ICR2, (u32)(data >> 32));
+	return kvm_lapic_reg_write(apic, reg, (u32)data);
 }
 
 int kvm_hv_vapic_msr_read(struct kvm_vcpu *vcpu, u32 reg, u64 *data)
@@ -2188,10 +2170,10 @@ int kvm_hv_vapic_msr_read(struct kvm_vcp
 	if (!lapic_in_kernel(vcpu))
 		return 1;
 
-	if (apic_reg_read(apic, reg, 4, &low))
+	if (kvm_lapic_reg_read(apic, reg, 4, &low))
 		return 1;
 	if (reg == APIC_ICR)
-		apic_reg_read(apic, APIC_ICR2, 4, &high);
+		kvm_lapic_reg_read(apic, APIC_ICR2, 4, &high);
 
 	*data = (((u64)high) << 32) | low;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kvm/lapic.h linux-libre-4.7-gnu/arch/x86/kvm/lapic.h
--- linux-libre-4.6-gnu/arch/x86/kvm/lapic.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kvm/lapic.h	2016-07-24 15:23:50.000000000 -0400
@@ -7,6 +7,10 @@
 
 #define KVM_APIC_INIT		0
 #define KVM_APIC_SIPI		1
+#define KVM_APIC_LVT_NUM	6
+
+#define KVM_APIC_SHORT_MASK	0xc0000
+#define KVM_APIC_DEST_MASK	0x800
 
 struct kvm_timer {
 	struct hrtimer timer;
@@ -59,6 +63,11 @@ void kvm_lapic_set_eoi(struct kvm_vcpu *
 void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value);
 u64 kvm_lapic_get_base(struct kvm_vcpu *vcpu);
 void kvm_apic_set_version(struct kvm_vcpu *vcpu);
+int kvm_lapic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val);
+int kvm_lapic_reg_read(struct kvm_lapic *apic, u32 offset, int len,
+		       void *data);
+bool kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
+			   int short_hand, unsigned int dest, int dest_mode);
 
 void __kvm_apic_update_irr(u32 *pir, void *regs);
 void kvm_apic_update_irr(struct kvm_vcpu *vcpu, u32 *pir);
@@ -99,9 +108,32 @@ static inline bool kvm_hv_vapic_assist_p
 int kvm_lapic_enable_pv_eoi(struct kvm_vcpu *vcpu, u64 data);
 void kvm_lapic_init(void);
 
-static inline u32 kvm_apic_get_reg(struct kvm_lapic *apic, int reg_off)
+#define VEC_POS(v) ((v) & (32 - 1))
+#define REG_POS(v) (((v) >> 5) << 4)
+
+static inline void kvm_lapic_set_vector(int vec, void *bitmap)
 {
-	        return *((u32 *) (apic->regs + reg_off));
+	set_bit(VEC_POS(vec), (bitmap) + REG_POS(vec));
+}
+
+static inline void kvm_lapic_set_irr(int vec, struct kvm_lapic *apic)
+{
+	kvm_lapic_set_vector(vec, apic->regs + APIC_IRR);
+	/*
+	 * irr_pending must be true if any interrupt is pending; set it after
+	 * APIC_IRR to avoid race with apic_clear_irr
+	 */
+	apic->irr_pending = true;
+}
+
+static inline u32 kvm_lapic_get_reg(struct kvm_lapic *apic, int reg_off)
+{
+	return *((u32 *) (apic->regs + reg_off));
+}
+
+static inline void kvm_lapic_set_reg(struct kvm_lapic *apic, int reg_off, u32 val)
+{
+	*((u32 *) (apic->regs + reg_off)) = val;
 }
 
 extern struct static_key kvm_no_apic_vcpu;
@@ -169,7 +201,7 @@ static inline int kvm_lapic_latched_init
 
 static inline int kvm_apic_id(struct kvm_lapic *apic)
 {
-	return (kvm_apic_get_reg(apic, APIC_ID) >> 24) & 0xff;
+	return (kvm_lapic_get_reg(apic, APIC_ID) >> 24) & 0xff;
 }
 
 bool kvm_apic_pending_eoi(struct kvm_vcpu *vcpu, int vector);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kvm/mmu.c linux-libre-4.7-gnu/arch/x86/kvm/mmu.c
--- linux-libre-4.6-gnu/arch/x86/kvm/mmu.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kvm/mmu.c	2016-07-24 15:23:50.000000000 -0400
@@ -336,12 +336,12 @@ static gfn_t pse36_gfn_delta(u32 gpte)
 #ifdef CONFIG_X86_64
 static void __set_spte(u64 *sptep, u64 spte)
 {
-	*sptep = spte;
+	WRITE_ONCE(*sptep, spte);
 }
 
 static void __update_clear_spte_fast(u64 *sptep, u64 spte)
 {
-	*sptep = spte;
+	WRITE_ONCE(*sptep, spte);
 }
 
 static u64 __update_clear_spte_slow(u64 *sptep, u64 spte)
@@ -390,7 +390,7 @@ static void __set_spte(u64 *sptep, u64 s
 	 */
 	smp_wmb();
 
-	ssptep->spte_low = sspte.spte_low;
+	WRITE_ONCE(ssptep->spte_low, sspte.spte_low);
 }
 
 static void __update_clear_spte_fast(u64 *sptep, u64 spte)
@@ -400,7 +400,7 @@ static void __update_clear_spte_fast(u64
 	ssptep = (union split_spte *)sptep;
 	sspte = (union split_spte)spte;
 
-	ssptep->spte_low = sspte.spte_low;
+	WRITE_ONCE(ssptep->spte_low, sspte.spte_low);
 
 	/*
 	 * If we map the spte from present to nonpresent, we should clear
@@ -1909,18 +1909,17 @@ static void kvm_mmu_commit_zap_page(stru
  * since it has been deleted from active_mmu_pages but still can be found
  * at hast list.
  *
- * for_each_gfn_indirect_valid_sp has skipped that kind of page and
- * kvm_mmu_get_page(), the only user of for_each_gfn_sp(), has skipped
- * all the obsolete pages.
+ * for_each_gfn_valid_sp() has skipped that kind of pages.
  */
-#define for_each_gfn_sp(_kvm, _sp, _gfn)				\
+#define for_each_gfn_valid_sp(_kvm, _sp, _gfn)				\
 	hlist_for_each_entry(_sp,					\
 	  &(_kvm)->arch.mmu_page_hash[kvm_page_table_hashfn(_gfn)], hash_link) \
-		if ((_sp)->gfn != (_gfn)) {} else
+		if ((_sp)->gfn != (_gfn) || is_obsolete_sp((_kvm), (_sp)) \
+			|| (_sp)->role.invalid) {} else
 
 #define for_each_gfn_indirect_valid_sp(_kvm, _sp, _gfn)			\
-	for_each_gfn_sp(_kvm, _sp, _gfn)				\
-		if ((_sp)->role.direct || (_sp)->role.invalid) {} else
+	for_each_gfn_valid_sp(_kvm, _sp, _gfn)				\
+		if ((_sp)->role.direct) {} else
 
 /* @sp->gfn should be write-protected at the call site */
 static bool __kvm_sync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
@@ -1961,6 +1960,11 @@ static void kvm_mmu_audit(struct kvm_vcp
 static void mmu_audit_disable(void) { }
 #endif
 
+static bool is_obsolete_sp(struct kvm *kvm, struct kvm_mmu_page *sp)
+{
+	return unlikely(sp->mmu_valid_gen != kvm->arch.mmu_valid_gen);
+}
+
 static bool kvm_sync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
 			 struct list_head *invalid_list)
 {
@@ -2105,11 +2109,6 @@ static void clear_sp_write_flooding_coun
 	__clear_sp_write_flooding_count(sp);
 }
 
-static bool is_obsolete_sp(struct kvm *kvm, struct kvm_mmu_page *sp)
-{
-	return unlikely(sp->mmu_valid_gen != kvm->arch.mmu_valid_gen);
-}
-
 static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
 					     gfn_t gfn,
 					     gva_t gaddr,
@@ -2136,10 +2135,7 @@ static struct kvm_mmu_page *kvm_mmu_get_
 		quadrant &= (1 << ((PT32_PT_BITS - PT64_PT_BITS) * level)) - 1;
 		role.quadrant = quadrant;
 	}
-	for_each_gfn_sp(vcpu->kvm, sp, gfn) {
-		if (is_obsolete_sp(vcpu->kvm, sp))
-			continue;
-
+	for_each_gfn_valid_sp(vcpu->kvm, sp, gfn) {
 		if (!need_sync && sp->unsync)
 			need_sync = true;
 
@@ -3844,7 +3840,8 @@ reset_tdp_shadow_zero_bits_mask(struct k
 		__reset_rsvds_bits_mask(vcpu, &context->shadow_zero_check,
 					boot_cpu_data.x86_phys_bits,
 					context->shadow_root_level, false,
-					cpu_has_gbpages, true, true);
+					boot_cpu_has(X86_FEATURE_GBPAGES),
+					true, true);
 	else
 		__reset_rsvds_bits_mask_ept(&context->shadow_zero_check,
 					    boot_cpu_data.x86_phys_bits,
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kvm/mtrr.c linux-libre-4.7-gnu/arch/x86/kvm/mtrr.c
--- linux-libre-4.6-gnu/arch/x86/kvm/mtrr.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kvm/mtrr.c	2016-07-24 15:23:50.000000000 -0400
@@ -44,8 +44,6 @@ static bool msr_mtrr_valid(unsigned msr)
 	case MSR_MTRRdefType:
 	case MSR_IA32_CR_PAT:
 		return true;
-	case 0x2f8:
-		return true;
 	}
 	return false;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kvm/svm.c linux-libre-4.7-gnu/arch/x86/kvm/svm.c
--- linux-libre-4.6-gnu/arch/x86/kvm/svm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kvm/svm.c	2016-07-24 15:23:50.000000000 -0400
@@ -14,6 +14,9 @@
  * the COPYING file in the top-level directory.
  *
  */
+
+#define pr_fmt(fmt) "SVM: " fmt
+
 #include <linux/kvm_host.h>
 
 #include "irq.h"
@@ -32,6 +35,7 @@
 #include <linux/trace_events.h>
 #include <linux/slab.h>
 
+#include <asm/apic.h>
 #include <asm/perf_event.h>
 #include <asm/tlbflush.h>
 #include <asm/desc.h>
@@ -68,6 +72,8 @@ MODULE_DEVICE_TABLE(x86cpu, svm_cpu_id);
 #define SVM_FEATURE_DECODE_ASSIST  (1 <<  7)
 #define SVM_FEATURE_PAUSE_FILTER   (1 << 10)
 
+#define SVM_AVIC_DOORBELL	0xc001011b
+
 #define NESTED_EXIT_HOST	0	/* Exit handled on host level */
 #define NESTED_EXIT_DONE	1	/* Exit caused nested vmexit  */
 #define NESTED_EXIT_CONTINUE	2	/* Further checks needed      */
@@ -78,6 +84,18 @@ MODULE_DEVICE_TABLE(x86cpu, svm_cpu_id);
 #define TSC_RATIO_MIN		0x0000000000000001ULL
 #define TSC_RATIO_MAX		0x000000ffffffffffULL
 
+#define AVIC_HPA_MASK	~((0xFFFULL << 52) | 0xFFF)
+
+/*
+ * 0xff is broadcast, so the max index allowed for physical APIC ID
+ * table is 0xfe.  APIC IDs above 0xff are reserved.
+ */
+#define AVIC_MAX_PHYSICAL_ID_COUNT	255
+
+#define AVIC_UNACCEL_ACCESS_WRITE_MASK		1
+#define AVIC_UNACCEL_ACCESS_OFFSET_MASK		0xFF0
+#define AVIC_UNACCEL_ACCESS_VECTOR_MASK		0xFFFFFFFF
+
 static bool erratum_383_found __read_mostly;
 
 static const u32 host_save_user_msrs[] = {
@@ -162,8 +180,21 @@ struct vcpu_svm {
 
 	/* cached guest cpuid flags for faster access */
 	bool nrips_enabled	: 1;
+
+	u32 ldr_reg;
+	struct page *avic_backing_page;
+	u64 *avic_physical_id_cache;
+	bool avic_is_running;
 };
 
+#define AVIC_LOGICAL_ID_ENTRY_GUEST_PHYSICAL_ID_MASK	(0xFF)
+#define AVIC_LOGICAL_ID_ENTRY_VALID_MASK		(1 << 31)
+
+#define AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK	(0xFFULL)
+#define AVIC_PHYSICAL_ID_ENTRY_BACKING_PAGE_MASK	(0xFFFFFFFFFFULL << 12)
+#define AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK		(1ULL << 62)
+#define AVIC_PHYSICAL_ID_ENTRY_VALID_MASK		(1ULL << 63)
+
 static DEFINE_PER_CPU(u64, current_tsc_ratio);
 #define TSC_RATIO_DEFAULT	0x0100000000ULL
 
@@ -205,6 +236,12 @@ module_param(npt, int, S_IRUGO);
 static int nested = true;
 module_param(nested, int, S_IRUGO);
 
+/* enable / disable AVIC */
+static int avic;
+#ifdef CONFIG_X86_LOCAL_APIC
+module_param(avic, int, S_IRUGO);
+#endif
+
 static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0);
 static void svm_flush_tlb(struct kvm_vcpu *vcpu);
 static void svm_complete_interrupts(struct vcpu_svm *svm);
@@ -228,12 +265,18 @@ enum {
 	VMCB_SEG,        /* CS, DS, SS, ES, CPL */
 	VMCB_CR2,        /* CR2 only */
 	VMCB_LBR,        /* DBGCTL, BR_FROM, BR_TO, LAST_EX_FROM, LAST_EX_TO */
+	VMCB_AVIC,       /* AVIC APIC_BAR, AVIC APIC_BACKING_PAGE,
+			  * AVIC PHYSICAL_TABLE pointer,
+			  * AVIC LOGICAL_TABLE pointer
+			  */
 	VMCB_DIRTY_MAX,
 };
 
 /* TPR and CR2 are always written before VMRUN */
 #define VMCB_ALWAYS_DIRTY_MASK	((1U << VMCB_INTR) | (1U << VMCB_CR2))
 
+#define VMCB_AVIC_APIC_BAR_MASK		0xFFFFFFFFFF000ULL
+
 static inline void mark_all_dirty(struct vmcb *vmcb)
 {
 	vmcb->control.clean = 0;
@@ -255,6 +298,23 @@ static inline struct vcpu_svm *to_svm(st
 	return container_of(vcpu, struct vcpu_svm, vcpu);
 }
 
+static inline void avic_update_vapic_bar(struct vcpu_svm *svm, u64 data)
+{
+	svm->vmcb->control.avic_vapic_bar = data & VMCB_AVIC_APIC_BAR_MASK;
+	mark_dirty(svm->vmcb, VMCB_AVIC);
+}
+
+static inline bool avic_vcpu_is_running(struct kvm_vcpu *vcpu)
+{
+	struct vcpu_svm *svm = to_svm(vcpu);
+	u64 *entry = svm->avic_physical_id_cache;
+
+	if (!entry)
+		return false;
+
+	return (READ_ONCE(*entry) & AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK);
+}
+
 static void recalc_intercepts(struct vcpu_svm *svm)
 {
 	struct vmcb_control_area *c, *h;
@@ -923,6 +983,15 @@ static __init int svm_hardware_setup(voi
 	} else
 		kvm_disable_tdp();
 
+	if (avic) {
+		if (!npt_enabled ||
+		    !boot_cpu_has(X86_FEATURE_AVIC) ||
+		    !IS_ENABLED(CONFIG_X86_LOCAL_APIC))
+			avic = false;
+		else
+			pr_info("AVIC enabled\n");
+	}
+
 	return 0;
 
 err:
@@ -1000,6 +1069,22 @@ static void svm_adjust_tsc_offset_guest(
 	mark_dirty(svm->vmcb, VMCB_INTERCEPTS);
 }
 
+static void avic_init_vmcb(struct vcpu_svm *svm)
+{
+	struct vmcb *vmcb = svm->vmcb;
+	struct kvm_arch *vm_data = &svm->vcpu.kvm->arch;
+	phys_addr_t bpa = page_to_phys(svm->avic_backing_page);
+	phys_addr_t lpa = page_to_phys(vm_data->avic_logical_id_table_page);
+	phys_addr_t ppa = page_to_phys(vm_data->avic_physical_id_table_page);
+
+	vmcb->control.avic_backing_page = bpa & AVIC_HPA_MASK;
+	vmcb->control.avic_logical_id = lpa & AVIC_HPA_MASK;
+	vmcb->control.avic_physical_id = ppa & AVIC_HPA_MASK;
+	vmcb->control.avic_physical_id |= AVIC_MAX_PHYSICAL_ID_COUNT;
+	vmcb->control.int_ctl |= AVIC_ENABLE_MASK;
+	svm->vcpu.arch.apicv_active = true;
+}
+
 static void init_vmcb(struct vcpu_svm *svm)
 {
 	struct vmcb_control_area *control = &svm->vmcb->control;
@@ -1014,7 +1099,8 @@ static void init_vmcb(struct vcpu_svm *s
 	set_cr_intercept(svm, INTERCEPT_CR0_WRITE);
 	set_cr_intercept(svm, INTERCEPT_CR3_WRITE);
 	set_cr_intercept(svm, INTERCEPT_CR4_WRITE);
-	set_cr_intercept(svm, INTERCEPT_CR8_WRITE);
+	if (!kvm_vcpu_apicv_active(&svm->vcpu))
+		set_cr_intercept(svm, INTERCEPT_CR8_WRITE);
 
 	set_dr_intercepts(svm);
 
@@ -1110,9 +1196,197 @@ static void init_vmcb(struct vcpu_svm *s
 		set_intercept(svm, INTERCEPT_PAUSE);
 	}
 
+	if (avic)
+		avic_init_vmcb(svm);
+
 	mark_all_dirty(svm->vmcb);
 
 	enable_gif(svm);
+
+}
+
+static u64 *avic_get_physical_id_entry(struct kvm_vcpu *vcpu, int index)
+{
+	u64 *avic_physical_id_table;
+	struct kvm_arch *vm_data = &vcpu->kvm->arch;
+
+	if (index >= AVIC_MAX_PHYSICAL_ID_COUNT)
+		return NULL;
+
+	avic_physical_id_table = page_address(vm_data->avic_physical_id_table_page);
+
+	return &avic_physical_id_table[index];
+}
+
+/**
+ * Note:
+ * AVIC hardware walks the nested page table to check permissions,
+ * but does not use the SPA address specified in the leaf page
+ * table entry since it uses  address in the AVIC_BACKING_PAGE pointer
+ * field of the VMCB. Therefore, we set up the
+ * APIC_ACCESS_PAGE_PRIVATE_MEMSLOT (4KB) here.
+ */
+static int avic_init_access_page(struct kvm_vcpu *vcpu)
+{
+	struct kvm *kvm = vcpu->kvm;
+	int ret;
+
+	if (kvm->arch.apic_access_page_done)
+		return 0;
+
+	ret = x86_set_memory_region(kvm,
+				    APIC_ACCESS_PAGE_PRIVATE_MEMSLOT,
+				    APIC_DEFAULT_PHYS_BASE,
+				    PAGE_SIZE);
+	if (ret)
+		return ret;
+
+	kvm->arch.apic_access_page_done = true;
+	return 0;
+}
+
+static int avic_init_backing_page(struct kvm_vcpu *vcpu)
+{
+	int ret;
+	u64 *entry, new_entry;
+	int id = vcpu->vcpu_id;
+	struct vcpu_svm *svm = to_svm(vcpu);
+
+	ret = avic_init_access_page(vcpu);
+	if (ret)
+		return ret;
+
+	if (id >= AVIC_MAX_PHYSICAL_ID_COUNT)
+		return -EINVAL;
+
+	if (!svm->vcpu.arch.apic->regs)
+		return -EINVAL;
+
+	svm->avic_backing_page = virt_to_page(svm->vcpu.arch.apic->regs);
+
+	/* Setting AVIC backing page address in the phy APIC ID table */
+	entry = avic_get_physical_id_entry(vcpu, id);
+	if (!entry)
+		return -EINVAL;
+
+	new_entry = READ_ONCE(*entry);
+	new_entry = (page_to_phys(svm->avic_backing_page) &
+		     AVIC_PHYSICAL_ID_ENTRY_BACKING_PAGE_MASK) |
+		     AVIC_PHYSICAL_ID_ENTRY_VALID_MASK;
+	WRITE_ONCE(*entry, new_entry);
+
+	svm->avic_physical_id_cache = entry;
+
+	return 0;
+}
+
+static void avic_vm_destroy(struct kvm *kvm)
+{
+	struct kvm_arch *vm_data = &kvm->arch;
+
+	if (vm_data->avic_logical_id_table_page)
+		__free_page(vm_data->avic_logical_id_table_page);
+	if (vm_data->avic_physical_id_table_page)
+		__free_page(vm_data->avic_physical_id_table_page);
+}
+
+static int avic_vm_init(struct kvm *kvm)
+{
+	int err = -ENOMEM;
+	struct kvm_arch *vm_data = &kvm->arch;
+	struct page *p_page;
+	struct page *l_page;
+
+	if (!avic)
+		return 0;
+
+	/* Allocating physical APIC ID table (4KB) */
+	p_page = alloc_page(GFP_KERNEL);
+	if (!p_page)
+		goto free_avic;
+
+	vm_data->avic_physical_id_table_page = p_page;
+	clear_page(page_address(p_page));
+
+	/* Allocating logical APIC ID table (4KB) */
+	l_page = alloc_page(GFP_KERNEL);
+	if (!l_page)
+		goto free_avic;
+
+	vm_data->avic_logical_id_table_page = l_page;
+	clear_page(page_address(l_page));
+
+	return 0;
+
+free_avic:
+	avic_vm_destroy(kvm);
+	return err;
+}
+
+/**
+ * This function is called during VCPU halt/unhalt.
+ */
+static void avic_set_running(struct kvm_vcpu *vcpu, bool is_run)
+{
+	u64 entry;
+	int h_physical_id = kvm_cpu_get_apicid(vcpu->cpu);
+	struct vcpu_svm *svm = to_svm(vcpu);
+
+	if (!kvm_vcpu_apicv_active(vcpu))
+		return;
+
+	svm->avic_is_running = is_run;
+
+	/* ID = 0xff (broadcast), ID > 0xff (reserved) */
+	if (WARN_ON(h_physical_id >= AVIC_MAX_PHYSICAL_ID_COUNT))
+		return;
+
+	entry = READ_ONCE(*(svm->avic_physical_id_cache));
+	WARN_ON(is_run == !!(entry & AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK));
+
+	entry &= ~AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK;
+	if (is_run)
+		entry |= AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK;
+	WRITE_ONCE(*(svm->avic_physical_id_cache), entry);
+}
+
+static void avic_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
+{
+	u64 entry;
+	/* ID = 0xff (broadcast), ID > 0xff (reserved) */
+	int h_physical_id = kvm_cpu_get_apicid(cpu);
+	struct vcpu_svm *svm = to_svm(vcpu);
+
+	if (!kvm_vcpu_apicv_active(vcpu))
+		return;
+
+	if (WARN_ON(h_physical_id >= AVIC_MAX_PHYSICAL_ID_COUNT))
+		return;
+
+	entry = READ_ONCE(*(svm->avic_physical_id_cache));
+	WARN_ON(entry & AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK);
+
+	entry &= ~AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK;
+	entry |= (h_physical_id & AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK);
+
+	entry &= ~AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK;
+	if (svm->avic_is_running)
+		entry |= AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK;
+
+	WRITE_ONCE(*(svm->avic_physical_id_cache), entry);
+}
+
+static void avic_vcpu_put(struct kvm_vcpu *vcpu)
+{
+	u64 entry;
+	struct vcpu_svm *svm = to_svm(vcpu);
+
+	if (!kvm_vcpu_apicv_active(vcpu))
+		return;
+
+	entry = READ_ONCE(*(svm->avic_physical_id_cache));
+	entry &= ~AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK;
+	WRITE_ONCE(*(svm->avic_physical_id_cache), entry);
 }
 
 static void svm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
@@ -1131,6 +1405,9 @@ static void svm_vcpu_reset(struct kvm_vc
 
 	kvm_cpuid(vcpu, &eax, &dummy, &dummy, &dummy);
 	kvm_register_write(vcpu, VCPU_REGS_RDX, eax);
+
+	if (kvm_vcpu_apicv_active(vcpu) && !init_event)
+		avic_update_vapic_bar(svm, APIC_DEFAULT_PHYS_BASE);
 }
 
 static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id)
@@ -1169,6 +1446,17 @@ static struct kvm_vcpu *svm_create_vcpu(
 	if (!hsave_page)
 		goto free_page3;
 
+	if (avic) {
+		err = avic_init_backing_page(&svm->vcpu);
+		if (err)
+			goto free_page4;
+	}
+
+	/* We initialize this flag to true to make sure that the is_running
+	 * bit would be set the first time the vcpu is loaded.
+	 */
+	svm->avic_is_running = true;
+
 	svm->nested.hsave = page_address(hsave_page);
 
 	svm->msrpm = page_address(msrpm_pages);
@@ -1187,6 +1475,8 @@ static struct kvm_vcpu *svm_create_vcpu(
 
 	return &svm->vcpu;
 
+free_page4:
+	__free_page(hsave_page);
 free_page3:
 	__free_pages(nested_msrpm_pages, MSRPM_ALLOC_ORDER);
 free_page2:
@@ -1243,6 +1533,8 @@ static void svm_vcpu_load(struct kvm_vcp
 	/* This assumes that the kernel never uses MSR_TSC_AUX */
 	if (static_cpu_has(X86_FEATURE_RDTSCP))
 		wrmsrl(MSR_TSC_AUX, svm->tsc_aux);
+
+	avic_vcpu_load(vcpu, cpu);
 }
 
 static void svm_vcpu_put(struct kvm_vcpu *vcpu)
@@ -1250,11 +1542,13 @@ static void svm_vcpu_put(struct kvm_vcpu
 	struct vcpu_svm *svm = to_svm(vcpu);
 	int i;
 
+	avic_vcpu_put(vcpu);
+
 	++vcpu->stat.host_state_reload;
 	kvm_load_ldt(svm->host.ldt);
 #ifdef CONFIG_X86_64
 	loadsegment(fs, svm->host.fs);
-	wrmsrl(MSR_KERNEL_GS_BASE, current->thread.gs);
+	wrmsrl(MSR_KERNEL_GS_BASE, current->thread.gsbase);
 	load_gs_index(svm->host.gs);
 #else
 #ifdef CONFIG_X86_32_LAZY_GS
@@ -1265,6 +1559,16 @@ static void svm_vcpu_put(struct kvm_vcpu
 		wrmsrl(host_save_user_msrs[i], svm->host_user_msrs[i]);
 }
 
+static void svm_vcpu_blocking(struct kvm_vcpu *vcpu)
+{
+	avic_set_running(vcpu, false);
+}
+
+static void svm_vcpu_unblocking(struct kvm_vcpu *vcpu)
+{
+	avic_set_running(vcpu, true);
+}
+
 static unsigned long svm_get_rflags(struct kvm_vcpu *vcpu)
 {
 	return to_svm(vcpu)->vmcb->save.rflags;
@@ -2673,10 +2977,11 @@ static int clgi_interception(struct vcpu
 	disable_gif(svm);
 
 	/* After a CLGI no interrupts should come */
-	svm_clear_vintr(svm);
-	svm->vmcb->control.int_ctl &= ~V_IRQ_MASK;
-
-	mark_dirty(svm->vmcb, VMCB_INTR);
+	if (!kvm_vcpu_apicv_active(&svm->vcpu)) {
+		svm_clear_vintr(svm);
+		svm->vmcb->control.int_ctl &= ~V_IRQ_MASK;
+		mark_dirty(svm->vmcb, VMCB_INTR);
+	}
 
 	return 1;
 }
@@ -3212,6 +3517,10 @@ static int svm_set_msr(struct kvm_vcpu *
 	case MSR_VM_IGNNE:
 		vcpu_unimpl(vcpu, "unimplemented wrmsr: 0x%x data 0x%llx\n", ecx, data);
 		break;
+	case MSR_IA32_APICBASE:
+		if (kvm_vcpu_apicv_active(vcpu))
+			avic_update_vapic_bar(to_svm(vcpu), data);
+		/* Follow through */
 	default:
 		return kvm_set_msr_common(vcpu, msr);
 	}
@@ -3281,6 +3590,278 @@ static int mwait_interception(struct vcp
 	return nop_interception(svm);
 }
 
+enum avic_ipi_failure_cause {
+	AVIC_IPI_FAILURE_INVALID_INT_TYPE,
+	AVIC_IPI_FAILURE_TARGET_NOT_RUNNING,
+	AVIC_IPI_FAILURE_INVALID_TARGET,
+	AVIC_IPI_FAILURE_INVALID_BACKING_PAGE,
+};
+
+static int avic_incomplete_ipi_interception(struct vcpu_svm *svm)
+{
+	u32 icrh = svm->vmcb->control.exit_info_1 >> 32;
+	u32 icrl = svm->vmcb->control.exit_info_1;
+	u32 id = svm->vmcb->control.exit_info_2 >> 32;
+	u32 index = svm->vmcb->control.exit_info_2 & 0xFF;
+	struct kvm_lapic *apic = svm->vcpu.arch.apic;
+
+	trace_kvm_avic_incomplete_ipi(svm->vcpu.vcpu_id, icrh, icrl, id, index);
+
+	switch (id) {
+	case AVIC_IPI_FAILURE_INVALID_INT_TYPE:
+		/*
+		 * AVIC hardware handles the generation of
+		 * IPIs when the specified Message Type is Fixed
+		 * (also known as fixed delivery mode) and
+		 * the Trigger Mode is edge-triggered. The hardware
+		 * also supports self and broadcast delivery modes
+		 * specified via the Destination Shorthand(DSH)
+		 * field of the ICRL. Logical and physical APIC ID
+		 * formats are supported. All other IPI types cause
+		 * a #VMEXIT, which needs to emulated.
+		 */
+		kvm_lapic_reg_write(apic, APIC_ICR2, icrh);
+		kvm_lapic_reg_write(apic, APIC_ICR, icrl);
+		break;
+	case AVIC_IPI_FAILURE_TARGET_NOT_RUNNING: {
+		int i;
+		struct kvm_vcpu *vcpu;
+		struct kvm *kvm = svm->vcpu.kvm;
+		struct kvm_lapic *apic = svm->vcpu.arch.apic;
+
+		/*
+		 * At this point, we expect that the AVIC HW has already
+		 * set the appropriate IRR bits on the valid target
+		 * vcpus. So, we just need to kick the appropriate vcpu.
+		 */
+		kvm_for_each_vcpu(i, vcpu, kvm) {
+			bool m = kvm_apic_match_dest(vcpu, apic,
+						     icrl & KVM_APIC_SHORT_MASK,
+						     GET_APIC_DEST_FIELD(icrh),
+						     icrl & KVM_APIC_DEST_MASK);
+
+			if (m && !avic_vcpu_is_running(vcpu))
+				kvm_vcpu_wake_up(vcpu);
+		}
+		break;
+	}
+	case AVIC_IPI_FAILURE_INVALID_TARGET:
+		break;
+	case AVIC_IPI_FAILURE_INVALID_BACKING_PAGE:
+		WARN_ONCE(1, "Invalid backing page\n");
+		break;
+	default:
+		pr_err("Unknown IPI interception\n");
+	}
+
+	return 1;
+}
+
+static u32 *avic_get_logical_id_entry(struct kvm_vcpu *vcpu, u32 ldr, bool flat)
+{
+	struct kvm_arch *vm_data = &vcpu->kvm->arch;
+	int index;
+	u32 *logical_apic_id_table;
+	int dlid = GET_APIC_LOGICAL_ID(ldr);
+
+	if (!dlid)
+		return NULL;
+
+	if (flat) { /* flat */
+		index = ffs(dlid) - 1;
+		if (index > 7)
+			return NULL;
+	} else { /* cluster */
+		int cluster = (dlid & 0xf0) >> 4;
+		int apic = ffs(dlid & 0x0f) - 1;
+
+		if ((apic < 0) || (apic > 7) ||
+		    (cluster >= 0xf))
+			return NULL;
+		index = (cluster << 2) + apic;
+	}
+
+	logical_apic_id_table = (u32 *) page_address(vm_data->avic_logical_id_table_page);
+
+	return &logical_apic_id_table[index];
+}
+
+static int avic_ldr_write(struct kvm_vcpu *vcpu, u8 g_physical_id, u32 ldr,
+			  bool valid)
+{
+	bool flat;
+	u32 *entry, new_entry;
+
+	flat = kvm_lapic_get_reg(vcpu->arch.apic, APIC_DFR) == APIC_DFR_FLAT;
+	entry = avic_get_logical_id_entry(vcpu, ldr, flat);
+	if (!entry)
+		return -EINVAL;
+
+	new_entry = READ_ONCE(*entry);
+	new_entry &= ~AVIC_LOGICAL_ID_ENTRY_GUEST_PHYSICAL_ID_MASK;
+	new_entry |= (g_physical_id & AVIC_LOGICAL_ID_ENTRY_GUEST_PHYSICAL_ID_MASK);
+	if (valid)
+		new_entry |= AVIC_LOGICAL_ID_ENTRY_VALID_MASK;
+	else
+		new_entry &= ~AVIC_LOGICAL_ID_ENTRY_VALID_MASK;
+	WRITE_ONCE(*entry, new_entry);
+
+	return 0;
+}
+
+static int avic_handle_ldr_update(struct kvm_vcpu *vcpu)
+{
+	int ret;
+	struct vcpu_svm *svm = to_svm(vcpu);
+	u32 ldr = kvm_lapic_get_reg(vcpu->arch.apic, APIC_LDR);
+
+	if (!ldr)
+		return 1;
+
+	ret = avic_ldr_write(vcpu, vcpu->vcpu_id, ldr, true);
+	if (ret && svm->ldr_reg) {
+		avic_ldr_write(vcpu, 0, svm->ldr_reg, false);
+		svm->ldr_reg = 0;
+	} else {
+		svm->ldr_reg = ldr;
+	}
+	return ret;
+}
+
+static int avic_handle_apic_id_update(struct kvm_vcpu *vcpu)
+{
+	u64 *old, *new;
+	struct vcpu_svm *svm = to_svm(vcpu);
+	u32 apic_id_reg = kvm_lapic_get_reg(vcpu->arch.apic, APIC_ID);
+	u32 id = (apic_id_reg >> 24) & 0xff;
+
+	if (vcpu->vcpu_id == id)
+		return 0;
+
+	old = avic_get_physical_id_entry(vcpu, vcpu->vcpu_id);
+	new = avic_get_physical_id_entry(vcpu, id);
+	if (!new || !old)
+		return 1;
+
+	/* We need to move physical_id_entry to new offset */
+	*new = *old;
+	*old = 0ULL;
+	to_svm(vcpu)->avic_physical_id_cache = new;
+
+	/*
+	 * Also update the guest physical APIC ID in the logical
+	 * APIC ID table entry if already setup the LDR.
+	 */
+	if (svm->ldr_reg)
+		avic_handle_ldr_update(vcpu);
+
+	return 0;
+}
+
+static int avic_handle_dfr_update(struct kvm_vcpu *vcpu)
+{
+	struct vcpu_svm *svm = to_svm(vcpu);
+	struct kvm_arch *vm_data = &vcpu->kvm->arch;
+	u32 dfr = kvm_lapic_get_reg(vcpu->arch.apic, APIC_DFR);
+	u32 mod = (dfr >> 28) & 0xf;
+
+	/*
+	 * We assume that all local APICs are using the same type.
+	 * If this changes, we need to flush the AVIC logical
+	 * APID id table.
+	 */
+	if (vm_data->ldr_mode == mod)
+		return 0;
+
+	clear_page(page_address(vm_data->avic_logical_id_table_page));
+	vm_data->ldr_mode = mod;
+
+	if (svm->ldr_reg)
+		avic_handle_ldr_update(vcpu);
+	return 0;
+}
+
+static int avic_unaccel_trap_write(struct vcpu_svm *svm)
+{
+	struct kvm_lapic *apic = svm->vcpu.arch.apic;
+	u32 offset = svm->vmcb->control.exit_info_1 &
+				AVIC_UNACCEL_ACCESS_OFFSET_MASK;
+
+	switch (offset) {
+	case APIC_ID:
+		if (avic_handle_apic_id_update(&svm->vcpu))
+			return 0;
+		break;
+	case APIC_LDR:
+		if (avic_handle_ldr_update(&svm->vcpu))
+			return 0;
+		break;
+	case APIC_DFR:
+		avic_handle_dfr_update(&svm->vcpu);
+		break;
+	default:
+		break;
+	}
+
+	kvm_lapic_reg_write(apic, offset, kvm_lapic_get_reg(apic, offset));
+
+	return 1;
+}
+
+static bool is_avic_unaccelerated_access_trap(u32 offset)
+{
+	bool ret = false;
+
+	switch (offset) {
+	case APIC_ID:
+	case APIC_EOI:
+	case APIC_RRR:
+	case APIC_LDR:
+	case APIC_DFR:
+	case APIC_SPIV:
+	case APIC_ESR:
+	case APIC_ICR:
+	case APIC_LVTT:
+	case APIC_LVTTHMR:
+	case APIC_LVTPC:
+	case APIC_LVT0:
+	case APIC_LVT1:
+	case APIC_LVTERR:
+	case APIC_TMICT:
+	case APIC_TDCR:
+		ret = true;
+		break;
+	default:
+		break;
+	}
+	return ret;
+}
+
+static int avic_unaccelerated_access_interception(struct vcpu_svm *svm)
+{
+	int ret = 0;
+	u32 offset = svm->vmcb->control.exit_info_1 &
+		     AVIC_UNACCEL_ACCESS_OFFSET_MASK;
+	u32 vector = svm->vmcb->control.exit_info_2 &
+		     AVIC_UNACCEL_ACCESS_VECTOR_MASK;
+	bool write = (svm->vmcb->control.exit_info_1 >> 32) &
+		     AVIC_UNACCEL_ACCESS_WRITE_MASK;
+	bool trap = is_avic_unaccelerated_access_trap(offset);
+
+	trace_kvm_avic_unaccelerated_access(svm->vcpu.vcpu_id, offset,
+					    trap, write, vector);
+	if (trap) {
+		/* Handling Trap */
+		WARN_ONCE(!write, "svm: Handling trap read.\n");
+		ret = avic_unaccel_trap_write(svm);
+	} else {
+		/* Handling Fault */
+		ret = (emulate_instruction(&svm->vcpu, 0) == EMULATE_DONE);
+	}
+
+	return ret;
+}
+
 static int (*const svm_exit_handlers[])(struct vcpu_svm *svm) = {
 	[SVM_EXIT_READ_CR0]			= cr_interception,
 	[SVM_EXIT_READ_CR3]			= cr_interception,
@@ -3344,6 +3925,8 @@ static int (*const svm_exit_handlers[])(
 	[SVM_EXIT_XSETBV]			= xsetbv_interception,
 	[SVM_EXIT_NPF]				= pf_interception,
 	[SVM_EXIT_RSM]                          = emulate_on_interception,
+	[SVM_EXIT_AVIC_INCOMPLETE_IPI]		= avic_incomplete_ipi_interception,
+	[SVM_EXIT_AVIC_UNACCELERATED_ACCESS]	= avic_unaccelerated_access_interception,
 };
 
 static void dump_vmcb(struct kvm_vcpu *vcpu)
@@ -3375,10 +3958,14 @@ static void dump_vmcb(struct kvm_vcpu *v
 	pr_err("%-20s%08x\n", "exit_int_info_err:", control->exit_int_info_err);
 	pr_err("%-20s%lld\n", "nested_ctl:", control->nested_ctl);
 	pr_err("%-20s%016llx\n", "nested_cr3:", control->nested_cr3);
+	pr_err("%-20s%016llx\n", "avic_vapic_bar:", control->avic_vapic_bar);
 	pr_err("%-20s%08x\n", "event_inj:", control->event_inj);
 	pr_err("%-20s%08x\n", "event_inj_err:", control->event_inj_err);
 	pr_err("%-20s%lld\n", "lbr_ctl:", control->lbr_ctl);
 	pr_err("%-20s%016llx\n", "next_rip:", control->next_rip);
+	pr_err("%-20s%016llx\n", "avic_backing_page:", control->avic_backing_page);
+	pr_err("%-20s%016llx\n", "avic_logical_id:", control->avic_logical_id);
+	pr_err("%-20s%016llx\n", "avic_physical_id:", control->avic_physical_id);
 	pr_err("VMCB State Save Area:\n");
 	pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n",
 	       "es:",
@@ -3562,6 +4149,7 @@ static inline void svm_inject_irq(struct
 {
 	struct vmcb_control_area *control;
 
+	/* The following fields are ignored when AVIC is enabled */
 	control = &svm->vmcb->control;
 	control->int_vector = irq;
 	control->int_ctl &= ~V_INTR_PRIO_MASK;
@@ -3583,11 +4171,17 @@ static void svm_set_irq(struct kvm_vcpu
 		SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_INTR;
 }
 
+static inline bool svm_nested_virtualize_tpr(struct kvm_vcpu *vcpu)
+{
+	return is_guest_mode(vcpu) && (vcpu->arch.hflags & HF_VINTR_MASK);
+}
+
 static void update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr)
 {
 	struct vcpu_svm *svm = to_svm(vcpu);
 
-	if (is_guest_mode(vcpu) && (vcpu->arch.hflags & HF_VINTR_MASK))
+	if (svm_nested_virtualize_tpr(vcpu) ||
+	    kvm_vcpu_apicv_active(vcpu))
 		return;
 
 	clr_cr_intercept(svm, INTERCEPT_CR8_WRITE);
@@ -3606,11 +4200,28 @@ static void svm_set_virtual_x2apic_mode(
 
 static bool svm_get_enable_apicv(void)
 {
-	return false;
+	return avic;
+}
+
+static void svm_hwapic_irr_update(struct kvm_vcpu *vcpu, int max_irr)
+{
 }
 
+static void svm_hwapic_isr_update(struct kvm_vcpu *vcpu, int max_isr)
+{
+}
+
+/* Note: Currently only used by Hyper-V. */
 static void svm_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu)
 {
+	struct vcpu_svm *svm = to_svm(vcpu);
+	struct vmcb *vmcb = svm->vmcb;
+
+	if (!avic)
+		return;
+
+	vmcb->control.int_ctl &= ~AVIC_ENABLE_MASK;
+	mark_dirty(vmcb, VMCB_INTR);
 }
 
 static void svm_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap)
@@ -3623,6 +4234,18 @@ static void svm_sync_pir_to_irr(struct k
 	return;
 }
 
+static void svm_deliver_avic_intr(struct kvm_vcpu *vcpu, int vec)
+{
+	kvm_lapic_set_irr(vec, vcpu->arch.apic);
+	smp_mb__after_atomic();
+
+	if (avic_vcpu_is_running(vcpu))
+		wrmsrl(SVM_AVIC_DOORBELL,
+		       kvm_cpu_get_apicid(vcpu->cpu));
+	else
+		kvm_vcpu_wake_up(vcpu);
+}
+
 static int svm_nmi_allowed(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_svm *svm = to_svm(vcpu);
@@ -3677,6 +4300,9 @@ static void enable_irq_window(struct kvm
 {
 	struct vcpu_svm *svm = to_svm(vcpu);
 
+	if (kvm_vcpu_apicv_active(vcpu))
+		return;
+
 	/*
 	 * In case GIF=0 we can't rely on the CPU to tell us when GIF becomes
 	 * 1, because that's a separate STGI/VMRUN intercept.  The next time we
@@ -3728,7 +4354,7 @@ static inline void sync_cr8_to_lapic(str
 {
 	struct vcpu_svm *svm = to_svm(vcpu);
 
-	if (is_guest_mode(vcpu) && (vcpu->arch.hflags & HF_VINTR_MASK))
+	if (svm_nested_virtualize_tpr(vcpu))
 		return;
 
 	if (!is_cr_intercept(svm, INTERCEPT_CR8_WRITE)) {
@@ -3742,7 +4368,8 @@ static inline void sync_lapic_to_cr8(str
 	struct vcpu_svm *svm = to_svm(vcpu);
 	u64 cr8;
 
-	if (is_guest_mode(vcpu) && (vcpu->arch.hflags & HF_VINTR_MASK))
+	if (svm_nested_virtualize_tpr(vcpu) ||
+	    kvm_vcpu_apicv_active(vcpu))
 		return;
 
 	cr8 = kvm_get_cr8(vcpu);
@@ -4045,14 +4672,26 @@ static u64 svm_get_mt_mask(struct kvm_vc
 static void svm_cpuid_update(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_svm *svm = to_svm(vcpu);
+	struct kvm_cpuid_entry2 *entry;
 
 	/* Update nrips enabled cache */
 	svm->nrips_enabled = !!guest_cpuid_has_nrips(&svm->vcpu);
+
+	if (!kvm_vcpu_apicv_active(vcpu))
+		return;
+
+	entry = kvm_find_cpuid_entry(vcpu, 1, 0);
+	if (entry)
+		entry->ecx &= ~bit(X86_FEATURE_X2APIC);
 }
 
 static void svm_set_supported_cpuid(u32 func, struct kvm_cpuid_entry2 *entry)
 {
 	switch (func) {
+	case 0x1:
+		if (avic)
+			entry->ecx &= ~bit(X86_FEATURE_X2APIC);
+		break;
 	case 0x80000001:
 		if (nested)
 			entry->ecx |= (1 << 2); /* Set SVM bit */
@@ -4307,6 +4946,15 @@ static void svm_sched_in(struct kvm_vcpu
 {
 }
 
+static inline void avic_post_state_restore(struct kvm_vcpu *vcpu)
+{
+	if (avic_handle_apic_id_update(vcpu) != 0)
+		return;
+	if (avic_handle_dfr_update(vcpu) != 0)
+		return;
+	avic_handle_ldr_update(vcpu);
+}
+
 static struct kvm_x86_ops svm_x86_ops = {
 	.cpu_has_kvm_support = has_svm,
 	.disabled_by_bios = is_disabled,
@@ -4322,9 +4970,14 @@ static struct kvm_x86_ops svm_x86_ops =
 	.vcpu_free = svm_free_vcpu,
 	.vcpu_reset = svm_vcpu_reset,
 
+	.vm_init = avic_vm_init,
+	.vm_destroy = avic_vm_destroy,
+
 	.prepare_guest_switch = svm_prepare_guest_switch,
 	.vcpu_load = svm_vcpu_load,
 	.vcpu_put = svm_vcpu_put,
+	.vcpu_blocking = svm_vcpu_blocking,
+	.vcpu_unblocking = svm_vcpu_unblocking,
 
 	.update_bp_intercept = update_bp_intercept,
 	.get_msr = svm_get_msr,
@@ -4382,6 +5035,9 @@ static struct kvm_x86_ops svm_x86_ops =
 	.refresh_apicv_exec_ctrl = svm_refresh_apicv_exec_ctrl,
 	.load_eoi_exitmap = svm_load_eoi_exitmap,
 	.sync_pir_to_irr = svm_sync_pir_to_irr,
+	.hwapic_irr_update = svm_hwapic_irr_update,
+	.hwapic_isr_update = svm_hwapic_isr_update,
+	.apicv_post_state_restore = avic_post_state_restore,
 
 	.set_tss_addr = svm_set_tss_addr,
 	.get_tdp_level = get_npt_level,
@@ -4415,6 +5071,7 @@ static struct kvm_x86_ops svm_x86_ops =
 	.sched_in = svm_sched_in,
 
 	.pmu_ops = &amd_pmu_ops,
+	.deliver_posted_interrupt = svm_deliver_avic_intr,
 };
 
 static int __init svm_init(void)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kvm/trace.h linux-libre-4.7-gnu/arch/x86/kvm/trace.h
--- linux-libre-4.6-gnu/arch/x86/kvm/trace.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kvm/trace.h	2016-07-24 15:23:50.000000000 -0400
@@ -809,8 +809,7 @@ TRACE_EVENT(kvm_write_tsc_offset,
 
 #define host_clocks					\
 	{VCLOCK_NONE, "none"},				\
-	{VCLOCK_TSC,  "tsc"},				\
-	{VCLOCK_HPET, "hpet"}				\
+	{VCLOCK_TSC,  "tsc"}				\
 
 TRACE_EVENT(kvm_update_master_clock,
 	TP_PROTO(bool use_master_clock, unsigned int host_clock, bool offset_matched),
@@ -1292,6 +1291,63 @@ TRACE_EVENT(kvm_hv_stimer_cleanup,
 		  __entry->vcpu_id, __entry->timer_index)
 );
 
+/*
+ * Tracepoint for AMD AVIC
+ */
+TRACE_EVENT(kvm_avic_incomplete_ipi,
+	    TP_PROTO(u32 vcpu, u32 icrh, u32 icrl, u32 id, u32 index),
+	    TP_ARGS(vcpu, icrh, icrl, id, index),
+
+	TP_STRUCT__entry(
+		__field(u32, vcpu)
+		__field(u32, icrh)
+		__field(u32, icrl)
+		__field(u32, id)
+		__field(u32, index)
+	),
+
+	TP_fast_assign(
+		__entry->vcpu = vcpu;
+		__entry->icrh = icrh;
+		__entry->icrl = icrl;
+		__entry->id = id;
+		__entry->index = index;
+	),
+
+	TP_printk("vcpu=%u, icrh:icrl=%#010x:%08x, id=%u, index=%u\n",
+		  __entry->vcpu, __entry->icrh, __entry->icrl,
+		  __entry->id, __entry->index)
+);
+
+TRACE_EVENT(kvm_avic_unaccelerated_access,
+	    TP_PROTO(u32 vcpu, u32 offset, bool ft, bool rw, u32 vec),
+	    TP_ARGS(vcpu, offset, ft, rw, vec),
+
+	TP_STRUCT__entry(
+		__field(u32, vcpu)
+		__field(u32, offset)
+		__field(bool, ft)
+		__field(bool, rw)
+		__field(u32, vec)
+	),
+
+	TP_fast_assign(
+		__entry->vcpu = vcpu;
+		__entry->offset = offset;
+		__entry->ft = ft;
+		__entry->rw = rw;
+		__entry->vec = vec;
+	),
+
+	TP_printk("vcpu=%u, offset=%#x(%s), %s, %s, vec=%#x\n",
+		  __entry->vcpu,
+		  __entry->offset,
+		  __print_symbolic(__entry->offset, kvm_trace_symbol_apic),
+		  __entry->ft ? "trap" : "fault",
+		  __entry->rw ? "write" : "read",
+		  __entry->vec)
+);
+
 #endif /* _TRACE_KVM_H */
 
 #undef TRACE_INCLUDE_PATH
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kvm/vmx.c linux-libre-4.7-gnu/arch/x86/kvm/vmx.c
--- linux-libre-4.6-gnu/arch/x86/kvm/vmx.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kvm/vmx.c	2016-07-24 15:23:50.000000000 -0400
@@ -2072,7 +2072,8 @@ static void vmx_vcpu_pi_load(struct kvm_
 	unsigned int dest;
 
 	if (!kvm_arch_has_assigned_device(vcpu->kvm) ||
-		!irq_remapping_cap(IRQ_POSTING_CAP))
+		!irq_remapping_cap(IRQ_POSTING_CAP)  ||
+		!kvm_vcpu_apicv_active(vcpu))
 		return;
 
 	do {
@@ -2180,7 +2181,8 @@ static void vmx_vcpu_pi_put(struct kvm_v
 	struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);
 
 	if (!kvm_arch_has_assigned_device(vcpu->kvm) ||
-		!irq_remapping_cap(IRQ_POSTING_CAP))
+		!irq_remapping_cap(IRQ_POSTING_CAP)  ||
+		!kvm_vcpu_apicv_active(vcpu))
 		return;
 
 	/* Set SN when the vCPU is preempted */
@@ -2418,7 +2420,9 @@ static void vmx_set_msr_bitmap(struct kv
 
 	if (is_guest_mode(vcpu))
 		msr_bitmap = vmx_msr_bitmap_nested;
-	else if (vcpu->arch.apic_base & X2APIC_ENABLE) {
+	else if (cpu_has_secondary_exec_ctrls() &&
+		 (vmcs_read32(SECONDARY_VM_EXEC_CONTROL) &
+		  SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE)) {
 		if (is_long_mode(vcpu))
 			msr_bitmap = vmx_msr_bitmap_longmode_x2apic;
 		else
@@ -3390,7 +3394,7 @@ static __init int setup_vmcs_config(stru
 		}
 	}
 
-	if (cpu_has_xsaves)
+	if (boot_cpu_has(X86_FEATURE_XSAVES))
 		rdmsrl(MSR_IA32_XSS, host_xss);
 
 	return 0;
@@ -4787,6 +4791,19 @@ static void vmx_refresh_apicv_exec_ctrl(
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
 
 	vmcs_write32(PIN_BASED_VM_EXEC_CONTROL, vmx_pin_based_exec_ctrl(vmx));
+	if (cpu_has_secondary_exec_ctrls()) {
+		if (kvm_vcpu_apicv_active(vcpu))
+			vmcs_set_bits(SECONDARY_VM_EXEC_CONTROL,
+				      SECONDARY_EXEC_APIC_REGISTER_VIRT |
+				      SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY);
+		else
+			vmcs_clear_bits(SECONDARY_VM_EXEC_CONTROL,
+					SECONDARY_EXEC_APIC_REGISTER_VIRT |
+					SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY);
+	}
+
+	if (cpu_has_vmx_msr_bitmap())
+		vmx_set_msr_bitmap(vcpu);
 }
 
 static u32 vmx_exec_control(struct vcpu_vmx *vmx)
@@ -5050,8 +5067,8 @@ static void vmx_vcpu_reset(struct kvm_vc
 		vmcs_write16(VIRTUAL_PROCESSOR_ID, vmx->vpid);
 
 	cr0 = X86_CR0_NW | X86_CR0_CD | X86_CR0_ET;
-	vmx_set_cr0(vcpu, cr0); /* enter rmode */
 	vmx->vcpu.arch.cr0 = cr0;
+	vmx_set_cr0(vcpu, cr0); /* enter rmode */
 	vmx_set_cr4(vcpu, 0);
 	vmx_set_efer(vcpu, 0);
 	vmx_fpu_activate(vcpu);
@@ -6333,23 +6350,20 @@ static __init int hardware_setup(void)
 
 	set_bit(0, vmx_vpid_bitmap); /* 0 is reserved for host */
 
-	if (enable_apicv) {
-		for (msr = 0x800; msr <= 0x8ff; msr++)
-			vmx_disable_intercept_msr_read_x2apic(msr);
+	for (msr = 0x800; msr <= 0x8ff; msr++)
+		vmx_disable_intercept_msr_read_x2apic(msr);
 
-		/* According SDM, in x2apic mode, the whole id reg is used.
-		 * But in KVM, it only use the highest eight bits. Need to
-		 * intercept it */
-		vmx_enable_intercept_msr_read_x2apic(0x802);
-		/* TMCCT */
-		vmx_enable_intercept_msr_read_x2apic(0x839);
-		/* TPR */
-		vmx_disable_intercept_msr_write_x2apic(0x808);
-		/* EOI */
-		vmx_disable_intercept_msr_write_x2apic(0x80b);
-		/* SELF-IPI */
-		vmx_disable_intercept_msr_write_x2apic(0x83f);
-	}
+	/* According SDM, in x2apic mode, the whole id reg is used.  But in
+	 * KVM, it only use the highest eight bits. Need to intercept it */
+	vmx_enable_intercept_msr_read_x2apic(0x802);
+	/* TMCCT */
+	vmx_enable_intercept_msr_read_x2apic(0x839);
+	/* TPR */
+	vmx_disable_intercept_msr_write_x2apic(0x808);
+	/* EOI */
+	vmx_disable_intercept_msr_write_x2apic(0x80b);
+	/* SELF-IPI */
+	vmx_disable_intercept_msr_write_x2apic(0x83f);
 
 	if (enable_ept) {
 		kvm_mmu_set_mask_ptes(0ull,
@@ -6657,7 +6671,13 @@ static int get_vmx_mem_address(struct kv
 
 	/* Checks for #GP/#SS exceptions. */
 	exn = false;
-	if (is_protmode(vcpu)) {
+	if (is_long_mode(vcpu)) {
+		/* Long mode: #GP(0)/#SS(0) if the memory address is in a
+		 * non-canonical form. This is the only check on the memory
+		 * destination for long mode!
+		 */
+		exn = is_noncanonical_address(*ret);
+	} else if (is_protmode(vcpu)) {
 		/* Protected mode: apply checks for segment validity in the
 		 * following order:
 		 * - segment type check (#GP(0) may be thrown)
@@ -6674,17 +6694,10 @@ static int get_vmx_mem_address(struct kv
 			 * execute-only code segment
 			 */
 			exn = ((s.type & 0xa) == 8);
-	}
-	if (exn) {
-		kvm_queue_exception_e(vcpu, GP_VECTOR, 0);
-		return 1;
-	}
-	if (is_long_mode(vcpu)) {
-		/* Long mode: #GP(0)/#SS(0) if the memory address is in a
-		 * non-canonical form. This is an only check for long mode.
-		 */
-		exn = is_noncanonical_address(*ret);
-	} else if (is_protmode(vcpu)) {
+		if (exn) {
+			kvm_queue_exception_e(vcpu, GP_VECTOR, 0);
+			return 1;
+		}
 		/* Protected mode: #GP(0)/#SS(0) if the segment is unusable.
 		 */
 		exn = (s.unusable != 0);
@@ -8318,19 +8331,19 @@ static void vmx_set_apic_access_page_add
 		vmcs_write64(APIC_ACCESS_ADDR, hpa);
 }
 
-static void vmx_hwapic_isr_update(struct kvm *kvm, int isr)
+static void vmx_hwapic_isr_update(struct kvm_vcpu *vcpu, int max_isr)
 {
 	u16 status;
 	u8 old;
 
-	if (isr == -1)
-		isr = 0;
+	if (max_isr == -1)
+		max_isr = 0;
 
 	status = vmcs_read16(GUEST_INTR_STATUS);
 	old = status >> 8;
-	if (isr != old) {
+	if (max_isr != old) {
 		status &= 0xff;
-		status |= isr << 8;
+		status |= max_isr << 8;
 		vmcs_write16(GUEST_INTR_STATUS, status);
 	}
 }
@@ -10702,7 +10715,8 @@ static int vmx_pre_block(struct kvm_vcpu
 	struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);
 
 	if (!kvm_arch_has_assigned_device(vcpu->kvm) ||
-		!irq_remapping_cap(IRQ_POSTING_CAP))
+		!irq_remapping_cap(IRQ_POSTING_CAP)  ||
+		!kvm_vcpu_apicv_active(vcpu))
 		return 0;
 
 	vcpu->pre_pcpu = vcpu->cpu;
@@ -10768,7 +10782,8 @@ static void vmx_post_block(struct kvm_vc
 	unsigned long flags;
 
 	if (!kvm_arch_has_assigned_device(vcpu->kvm) ||
-		!irq_remapping_cap(IRQ_POSTING_CAP))
+		!irq_remapping_cap(IRQ_POSTING_CAP)  ||
+		!kvm_vcpu_apicv_active(vcpu))
 		return;
 
 	do {
@@ -10821,7 +10836,8 @@ static int vmx_update_pi_irte(struct kvm
 	int idx, ret = -EINVAL;
 
 	if (!kvm_arch_has_assigned_device(kvm) ||
-		!irq_remapping_cap(IRQ_POSTING_CAP))
+		!irq_remapping_cap(IRQ_POSTING_CAP) ||
+		!kvm_vcpu_apicv_active(kvm->vcpus[0]))
 		return 0;
 
 	idx = srcu_read_lock(&kvm->irq_srcu);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kvm/x86.c linux-libre-4.7-gnu/arch/x86/kvm/x86.c
--- linux-libre-4.6-gnu/arch/x86/kvm/x86.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kvm/x86.c	2016-07-24 15:23:50.000000000 -0400
@@ -161,6 +161,7 @@ struct kvm_stats_debugfs_item debugfs_en
 	{ "halt_exits", VCPU_STAT(halt_exits) },
 	{ "halt_successful_poll", VCPU_STAT(halt_successful_poll) },
 	{ "halt_attempted_poll", VCPU_STAT(halt_attempted_poll) },
+	{ "halt_poll_invalid", VCPU_STAT(halt_poll_invalid) },
 	{ "halt_wakeup", VCPU_STAT(halt_wakeup) },
 	{ "hypercalls", VCPU_STAT(hypercalls) },
 	{ "request_irq", VCPU_STAT(request_irq_exits) },
@@ -1243,12 +1244,6 @@ static atomic_t kvm_guest_has_master_clo
 static DEFINE_PER_CPU(unsigned long, cpu_tsc_khz);
 static unsigned long max_tsc_khz;
 
-static inline u64 nsec_to_cycles(struct kvm_vcpu *vcpu, u64 nsec)
-{
-	return pvclock_scale_delta(nsec, vcpu->arch.virtual_tsc_mult,
-				   vcpu->arch.virtual_tsc_shift);
-}
-
 static u32 adjust_tsc_khz(u32 khz, s32 ppm)
 {
 	u64 v = (u64)khz * (1000000 + ppm);
@@ -2002,22 +1997,8 @@ static void kvmclock_reset(struct kvm_vc
 	vcpu->arch.pv_time_enabled = false;
 }
 
-static void accumulate_steal_time(struct kvm_vcpu *vcpu)
-{
-	u64 delta;
-
-	if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED))
-		return;
-
-	delta = current->sched_info.run_delay - vcpu->arch.st.last_steal;
-	vcpu->arch.st.last_steal = current->sched_info.run_delay;
-	vcpu->arch.st.accum_steal = delta;
-}
-
 static void record_steal_time(struct kvm_vcpu *vcpu)
 {
-	accumulate_steal_time(vcpu);
-
 	if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED))
 		return;
 
@@ -2025,9 +2006,26 @@ static void record_steal_time(struct kvm
 		&vcpu->arch.st.steal, sizeof(struct kvm_steal_time))))
 		return;
 
-	vcpu->arch.st.steal.steal += vcpu->arch.st.accum_steal;
-	vcpu->arch.st.steal.version += 2;
-	vcpu->arch.st.accum_steal = 0;
+	if (vcpu->arch.st.steal.version & 1)
+		vcpu->arch.st.steal.version += 1;  /* first time write, random junk */
+
+	vcpu->arch.st.steal.version += 1;
+
+	kvm_write_guest_cached(vcpu->kvm, &vcpu->arch.st.stime,
+		&vcpu->arch.st.steal, sizeof(struct kvm_steal_time));
+
+	smp_wmb();
+
+	vcpu->arch.st.steal.steal += current->sched_info.run_delay -
+		vcpu->arch.st.last_steal;
+	vcpu->arch.st.last_steal = current->sched_info.run_delay;
+
+	kvm_write_guest_cached(vcpu->kvm, &vcpu->arch.st.stime,
+		&vcpu->arch.st.steal, sizeof(struct kvm_steal_time));
+
+	smp_wmb();
+
+	vcpu->arch.st.steal.version += 1;
 
 	kvm_write_guest_cached(vcpu->kvm, &vcpu->arch.st.stime,
 		&vcpu->arch.st.steal, sizeof(struct kvm_steal_time));
@@ -2310,6 +2308,7 @@ int kvm_get_msr_common(struct kvm_vcpu *
 	case MSR_AMD64_NB_CFG:
 	case MSR_FAM10H_MMIO_CONF_BASE:
 	case MSR_AMD64_BU_CFG2:
+	case MSR_IA32_PERF_CTL:
 		msr_info->data = 0;
 		break;
 	case MSR_K7_EVNTSEL0 ... MSR_K7_EVNTSEL3:
@@ -2611,7 +2610,7 @@ int kvm_vm_ioctl_check_extension(struct
 		r = KVM_MAX_MCE_BANKS;
 		break;
 	case KVM_CAP_XCRS:
-		r = cpu_has_xsave;
+		r = boot_cpu_has(X86_FEATURE_XSAVE);
 		break;
 	case KVM_CAP_TSC_CONTROL:
 		r = kvm_has_tsc_control;
@@ -2968,6 +2967,10 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_e
 			      | KVM_VCPUEVENT_VALID_SMM))
 		return -EINVAL;
 
+	if (events->exception.injected &&
+	    (events->exception.nr > 31 || events->exception.nr == NMI_VECTOR))
+		return -EINVAL;
+
 	process_nmi(vcpu);
 	vcpu->arch.exception.pending = events->exception.injected;
 	vcpu->arch.exception.nr = events->exception.nr;
@@ -3032,6 +3035,11 @@ static int kvm_vcpu_ioctl_x86_set_debugr
 	if (dbgregs->flags)
 		return -EINVAL;
 
+	if (dbgregs->dr6 & ~0xffffffffull)
+		return -EINVAL;
+	if (dbgregs->dr7 & ~0xffffffffull)
+		return -EINVAL;
+
 	memcpy(vcpu->arch.db, dbgregs->db, sizeof(vcpu->arch.db));
 	kvm_update_dr0123(vcpu);
 	vcpu->arch.dr6 = dbgregs->dr6;
@@ -3094,7 +3102,7 @@ static void load_xsave(struct kvm_vcpu *
 
 	/* Set XSTATE_BV and possibly XCOMP_BV.  */
 	xsave->header.xfeatures = xstate_bv;
-	if (cpu_has_xsaves)
+	if (boot_cpu_has(X86_FEATURE_XSAVES))
 		xsave->header.xcomp_bv = host_xcr0 | XSTATE_COMPACTION_ENABLED;
 
 	/*
@@ -3121,7 +3129,7 @@ static void load_xsave(struct kvm_vcpu *
 static void kvm_vcpu_ioctl_x86_get_xsave(struct kvm_vcpu *vcpu,
 					 struct kvm_xsave *guest_xsave)
 {
-	if (cpu_has_xsave) {
+	if (boot_cpu_has(X86_FEATURE_XSAVE)) {
 		memset(guest_xsave, 0, sizeof(struct kvm_xsave));
 		fill_xsave((u8 *) guest_xsave->region, vcpu);
 	} else {
@@ -3139,7 +3147,7 @@ static int kvm_vcpu_ioctl_x86_set_xsave(
 	u64 xstate_bv =
 		*(u64 *)&guest_xsave->region[XSAVE_HDR_OFFSET / sizeof(u32)];
 
-	if (cpu_has_xsave) {
+	if (boot_cpu_has(X86_FEATURE_XSAVE)) {
 		/*
 		 * Here we allow setting states that are not present in
 		 * CPUID leaf 0xD, index 0, EDX:EAX.  This is for compatibility
@@ -3160,7 +3168,7 @@ static int kvm_vcpu_ioctl_x86_set_xsave(
 static void kvm_vcpu_ioctl_x86_get_xcrs(struct kvm_vcpu *vcpu,
 					struct kvm_xcrs *guest_xcrs)
 {
-	if (!cpu_has_xsave) {
+	if (!boot_cpu_has(X86_FEATURE_XSAVE)) {
 		guest_xcrs->nr_xcrs = 0;
 		return;
 	}
@@ -3176,7 +3184,7 @@ static int kvm_vcpu_ioctl_x86_set_xcrs(s
 {
 	int i, r = 0;
 
-	if (!cpu_has_xsave)
+	if (!boot_cpu_has(X86_FEATURE_XSAVE))
 		return -EINVAL;
 
 	if (guest_xcrs->nr_xcrs > KVM_MAX_XCRS || guest_xcrs->flags)
@@ -5865,7 +5873,7 @@ int kvm_arch_init(void *opaque)
 
 	perf_register_guest_info_callbacks(&kvm_guest_cbs);
 
-	if (cpu_has_xsave)
+	if (boot_cpu_has(X86_FEATURE_XSAVE))
 		host_xcr0 = xgetbv(XCR_XFEATURE_ENABLED_MASK);
 
 	kvm_lapic_init();
@@ -7293,7 +7301,7 @@ int kvm_arch_vcpu_ioctl_set_fpu(struct k
 static void fx_init(struct kvm_vcpu *vcpu)
 {
 	fpstate_init(&vcpu->arch.guest_fpu.state);
-	if (cpu_has_xsaves)
+	if (boot_cpu_has(X86_FEATURE_XSAVES))
 		vcpu->arch.guest_fpu.state.xsave.header.xcomp_bv =
 			host_xcr0 | XSTATE_COMPACTION_ENABLED;
 
@@ -7752,6 +7760,9 @@ int kvm_arch_init_vm(struct kvm *kvm, un
 	kvm_page_track_init(kvm);
 	kvm_mmu_init_vm(kvm);
 
+	if (kvm_x86_ops->vm_init)
+		return kvm_x86_ops->vm_init(kvm);
+
 	return 0;
 }
 
@@ -7808,7 +7819,7 @@ int __x86_set_memory_region(struct kvm *
 
 	slot = id_to_memslot(slots, id);
 	if (size) {
-		if (WARN_ON(slot->npages))
+		if (slot->npages)
 			return -EEXIST;
 
 		/*
@@ -7873,6 +7884,8 @@ void kvm_arch_destroy_vm(struct kvm *kvm
 		x86_set_memory_region(kvm, IDENTITY_PAGETABLE_PRIVATE_MEMSLOT, 0, 0);
 		x86_set_memory_region(kvm, TSS_PRIVATE_MEMSLOT, 0, 0);
 	}
+	if (kvm_x86_ops->vm_destroy)
+		kvm_x86_ops->vm_destroy(kvm);
 	kvm_iommu_unmap_guest(kvm);
 	kfree(kvm->arch.vpic);
 	kfree(kvm->arch.vioapic);
@@ -8355,19 +8368,21 @@ bool kvm_arch_has_noncoherent_dma(struct
 }
 EXPORT_SYMBOL_GPL(kvm_arch_has_noncoherent_dma);
 
+bool kvm_arch_has_irq_bypass(void)
+{
+	return kvm_x86_ops->update_pi_irte != NULL;
+}
+
 int kvm_arch_irq_bypass_add_producer(struct irq_bypass_consumer *cons,
 				      struct irq_bypass_producer *prod)
 {
 	struct kvm_kernel_irqfd *irqfd =
 		container_of(cons, struct kvm_kernel_irqfd, consumer);
 
-	if (kvm_x86_ops->update_pi_irte) {
-		irqfd->producer = prod;
-		return kvm_x86_ops->update_pi_irte(irqfd->kvm,
-				prod->irq, irqfd->gsi, 1);
-	}
+	irqfd->producer = prod;
 
-	return -EINVAL;
+	return kvm_x86_ops->update_pi_irte(irqfd->kvm,
+					   prod->irq, irqfd->gsi, 1);
 }
 
 void kvm_arch_irq_bypass_del_producer(struct irq_bypass_consumer *cons,
@@ -8377,11 +8392,6 @@ void kvm_arch_irq_bypass_del_producer(st
 	struct kvm_kernel_irqfd *irqfd =
 		container_of(cons, struct kvm_kernel_irqfd, consumer);
 
-	if (!kvm_x86_ops->update_pi_irte) {
-		WARN_ON(irqfd->producer != NULL);
-		return;
-	}
-
 	WARN_ON(irqfd->producer != prod);
 	irqfd->producer = NULL;
 
@@ -8429,3 +8439,5 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_write_t
 EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_ple_window);
 EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_pml_full);
 EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_pi_irte_update);
+EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_avic_unaccelerated_access);
+EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_avic_incomplete_ipi);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/kvm/x86.h linux-libre-4.7-gnu/arch/x86/kvm/x86.h
--- linux-libre-4.6-gnu/arch/x86/kvm/x86.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/kvm/x86.h	2016-07-24 15:23:50.000000000 -0400
@@ -2,6 +2,7 @@
 #define ARCH_X86_KVM_X86_H
 
 #include <linux/kvm_host.h>
+#include <asm/pvclock.h>
 #include "kvm_cache_regs.h"
 
 #define MSR_IA32_CR_PAT_DEFAULT  0x0007040600070406ULL
@@ -195,6 +196,12 @@ extern unsigned int lapic_timer_advance_
 
 extern struct static_key kvm_no_apic_vcpu;
 
+static inline u64 nsec_to_cycles(struct kvm_vcpu *vcpu, u64 nsec)
+{
+	return pvclock_scale_delta(nsec, vcpu->arch.virtual_tsc_mult,
+				   vcpu->arch.virtual_tsc_shift);
+}
+
 /* Same "calling convention" as do_div:
  * - divide (n << 32) by base
  * - put result in n
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/lguest/boot.c linux-libre-4.7-gnu/arch/x86/lguest/boot.c
--- linux-libre-4.6-gnu/arch/x86/lguest/boot.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/lguest/boot.c	2016-07-24 15:23:50.000000000 -0400
@@ -1408,13 +1408,10 @@ __init void lguest_init(void)
 {
 	/* We're under lguest. */
 	pv_info.name = "lguest";
-	/* Paravirt is enabled. */
-	pv_info.paravirt_enabled = 1;
 	/* We're running at privilege level 1, not 0 as normal. */
 	pv_info.kernel_rpl = 1;
 	/* Everyone except Xen runs with this set. */
 	pv_info.shared_kernel_pmd = 1;
-	pv_info.features = 0;
 
 	/*
 	 * We set up all the lguest overrides for sensitive operations.  These
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/lib/rwsem.S linux-libre-4.7-gnu/arch/x86/lib/rwsem.S
--- linux-libre-4.6-gnu/arch/x86/lib/rwsem.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/lib/rwsem.S	2016-07-24 15:23:50.000000000 -0400
@@ -29,8 +29,10 @@
  * there is contention on the semaphore.
  *
  * %eax contains the semaphore pointer on entry. Save the C-clobbered
- * registers (%eax, %edx and %ecx) except %eax whish is either a return
- * value or just clobbered..
+ * registers (%eax, %edx and %ecx) except %eax which is either a return
+ * value or just gets clobbered. Same is true for %edx so make sure GCC
+ * reloads it after the slow path, by making it hold a temporary, for
+ * example see ____down_write().
  */
 
 #define save_common_regs \
@@ -106,6 +108,16 @@ ENTRY(call_rwsem_down_write_failed)
 	ret
 ENDPROC(call_rwsem_down_write_failed)
 
+ENTRY(call_rwsem_down_write_failed_killable)
+	FRAME_BEGIN
+	save_common_regs
+	movq %rax,%rdi
+	call rwsem_down_write_failed_killable
+	restore_common_regs
+	FRAME_END
+	ret
+ENDPROC(call_rwsem_down_write_failed_killable)
+
 ENTRY(call_rwsem_wake)
 	FRAME_BEGIN
 	/* do nothing if still outstanding active readers */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/lib/usercopy_32.c linux-libre-4.7-gnu/arch/x86/lib/usercopy_32.c
--- linux-libre-4.6-gnu/arch/x86/lib/usercopy_32.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/lib/usercopy_32.c	2016-07-24 15:23:50.000000000 -0400
@@ -612,7 +612,7 @@ unsigned long __copy_from_user_ll_nocach
 {
 	stac();
 #ifdef CONFIG_X86_INTEL_USERCOPY
-	if (n > 64 && cpu_has_xmm2)
+	if (n > 64 && static_cpu_has(X86_FEATURE_XMM2))
 		n = __copy_user_zeroing_intel_nocache(to, from, n);
 	else
 		__copy_user_zeroing(to, from, n);
@@ -629,7 +629,7 @@ unsigned long __copy_from_user_ll_nocach
 {
 	stac();
 #ifdef CONFIG_X86_INTEL_USERCOPY
-	if (n > 64 && cpu_has_xmm2)
+	if (n > 64 && static_cpu_has(X86_FEATURE_XMM2))
 		n = __copy_user_intel_nocache(to, from, n);
 	else
 		__copy_user(to, from, n);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/Makefile linux-libre-4.7-gnu/arch/x86/Makefile
--- linux-libre-4.6-gnu/arch/x86/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -208,7 +208,8 @@ endif
 
 head-y := arch/x86/kernel/head_$(BITS).o
 head-y += arch/x86/kernel/head$(BITS).o
-head-y += arch/x86/kernel/head.o
+head-y += arch/x86/kernel/ebda.o
+head-y += arch/x86/kernel/platform-quirks.o
 
 libs-y  += arch/x86/lib/
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/mm/extable.c linux-libre-4.7-gnu/arch/x86/mm/extable.c
--- linux-libre-4.6-gnu/arch/x86/mm/extable.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/mm/extable.c	2016-07-24 15:23:50.000000000 -0400
@@ -1,5 +1,6 @@
 #include <linux/module.h>
 #include <asm/uaccess.h>
+#include <asm/traps.h>
 
 typedef bool (*ex_handler_t)(const struct exception_table_entry *,
 			    struct pt_regs *, int);
@@ -42,6 +43,43 @@ bool ex_handler_ext(const struct excepti
 }
 EXPORT_SYMBOL(ex_handler_ext);
 
+bool ex_handler_rdmsr_unsafe(const struct exception_table_entry *fixup,
+			     struct pt_regs *regs, int trapnr)
+{
+	WARN_ONCE(1, "unchecked MSR access error: RDMSR from 0x%x\n",
+		  (unsigned int)regs->cx);
+
+	/* Pretend that the read succeeded and returned 0. */
+	regs->ip = ex_fixup_addr(fixup);
+	regs->ax = 0;
+	regs->dx = 0;
+	return true;
+}
+EXPORT_SYMBOL(ex_handler_rdmsr_unsafe);
+
+bool ex_handler_wrmsr_unsafe(const struct exception_table_entry *fixup,
+			     struct pt_regs *regs, int trapnr)
+{
+	WARN_ONCE(1, "unchecked MSR access error: WRMSR to 0x%x (tried to write 0x%08x%08x)\n",
+		  (unsigned int)regs->cx,
+		  (unsigned int)regs->dx, (unsigned int)regs->ax);
+
+	/* Pretend that the write succeeded. */
+	regs->ip = ex_fixup_addr(fixup);
+	return true;
+}
+EXPORT_SYMBOL(ex_handler_wrmsr_unsafe);
+
+bool ex_handler_clear_fs(const struct exception_table_entry *fixup,
+			 struct pt_regs *regs, int trapnr)
+{
+	if (static_cpu_has(X86_BUG_NULL_SEG))
+		asm volatile ("mov %0, %%fs" : : "rm" (__USER_DS));
+	asm volatile ("mov %0, %%fs" : : "rm" (0));
+	return ex_handler_default(fixup, regs, trapnr);
+}
+EXPORT_SYMBOL(ex_handler_clear_fs);
+
 bool ex_has_fault_handler(unsigned long ip)
 {
 	const struct exception_table_entry *e;
@@ -82,24 +120,46 @@ int fixup_exception(struct pt_regs *regs
 	return handler(e, regs, trapnr);
 }
 
+extern unsigned int early_recursion_flag;
+
 /* Restricted version used during very early boot */
-int __init early_fixup_exception(unsigned long *ip)
+void __init early_fixup_exception(struct pt_regs *regs, int trapnr)
 {
-	const struct exception_table_entry *e;
-	unsigned long new_ip;
-	ex_handler_t handler;
+	/* Ignore early NMIs. */
+	if (trapnr == X86_TRAP_NMI)
+		return;
 
-	e = search_exception_tables(*ip);
-	if (!e)
-		return 0;
+	if (early_recursion_flag > 2)
+		goto halt_loop;
 
-	new_ip  = ex_fixup_addr(e);
-	handler = ex_fixup_handler(e);
+	if (regs->cs != __KERNEL_CS)
+		goto fail;
 
-	/* special handling not supported during early boot */
-	if (handler != ex_handler_default)
-		return 0;
+	/*
+	 * The full exception fixup machinery is available as soon as
+	 * the early IDT is loaded.  This means that it is the
+	 * responsibility of extable users to either function correctly
+	 * when handlers are invoked early or to simply avoid causing
+	 * exceptions before they're ready to handle them.
+	 *
+	 * This is better than filtering which handlers can be used,
+	 * because refusing to call a handler here is guaranteed to
+	 * result in a hard-to-debug panic.
+	 *
+	 * Keep in mind that not all vectors actually get here.  Early
+	 * fage faults, for example, are special.
+	 */
+	if (fixup_exception(regs, trapnr))
+		return;
 
-	*ip = new_ip;
-	return 1;
+fail:
+	early_printk("PANIC: early exception 0x%02x IP %lx:%lx error %lx cr2 0x%lx\n",
+		     (unsigned)trapnr, (unsigned long)regs->cs, regs->ip,
+		     regs->orig_ax, read_cr2());
+
+	show_regs(regs);
+
+halt_loop:
+	while (true)
+		halt();
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/mm/fault.c linux-libre-4.7-gnu/arch/x86/mm/fault.c
--- linux-libre-4.6-gnu/arch/x86/mm/fault.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/mm/fault.c	2016-07-24 15:23:50.000000000 -0400
@@ -292,7 +292,7 @@ void vmalloc_sync_all(void)
 		return;
 
 	for (address = VMALLOC_START & PMD_MASK;
-	     address >= TASK_SIZE && address < FIXADDR_TOP;
+	     address >= TASK_SIZE_MAX && address < FIXADDR_TOP;
 	     address += PMD_SIZE) {
 		struct page *page;
 
@@ -854,8 +854,13 @@ __bad_area_nosemaphore(struct pt_regs *r
 				return;
 		}
 #endif
-		/* Kernel addresses are always protection faults: */
-		if (address >= TASK_SIZE)
+
+		/*
+		 * To avoid leaking information about the kernel page table
+		 * layout, pretend that user-mode accesses to kernel addresses
+		 * are always protection faults.
+		 */
+		if (address >= TASK_SIZE_MAX)
 			error_code |= PF_PROT;
 
 		if (likely(show_unhandled_signals))
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/mm/hugetlbpage.c linux-libre-4.7-gnu/arch/x86/mm/hugetlbpage.c
--- linux-libre-4.6-gnu/arch/x86/mm/hugetlbpage.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/mm/hugetlbpage.c	2016-07-24 15:23:50.000000000 -0400
@@ -162,9 +162,10 @@ static __init int setup_hugepagesz(char
 	unsigned long ps = memparse(opt, &opt);
 	if (ps == PMD_SIZE) {
 		hugetlb_add_hstate(PMD_SHIFT - PAGE_SHIFT);
-	} else if (ps == PUD_SIZE && cpu_has_gbpages) {
+	} else if (ps == PUD_SIZE && boot_cpu_has(X86_FEATURE_GBPAGES)) {
 		hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT);
 	} else {
+		hugetlb_bad_size();
 		printk(KERN_ERR "hugepagesz: Unsupported page size %lu M\n",
 			ps >> 20);
 		return 0;
@@ -177,7 +178,7 @@ __setup("hugepagesz=", setup_hugepagesz)
 static __init int gigantic_pages_init(void)
 {
 	/* With compaction or CMA we can allocate gigantic pages at runtime */
-	if (cpu_has_gbpages && !size_to_hstate(1UL << PUD_SHIFT))
+	if (boot_cpu_has(X86_FEATURE_GBPAGES) && !size_to_hstate(1UL << PUD_SHIFT))
 		hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/mm/ident_map.c linux-libre-4.7-gnu/arch/x86/mm/ident_map.c
--- linux-libre-4.6-gnu/arch/x86/mm/ident_map.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/arch/x86/mm/ident_map.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,79 @@
+/*
+ * Helper routines for building identity mapping page tables. This is
+ * included by both the compressed kernel and the regular kernel.
+ */
+
+static void ident_pmd_init(unsigned long pmd_flag, pmd_t *pmd_page,
+			   unsigned long addr, unsigned long end)
+{
+	addr &= PMD_MASK;
+	for (; addr < end; addr += PMD_SIZE) {
+		pmd_t *pmd = pmd_page + pmd_index(addr);
+
+		if (!pmd_present(*pmd))
+			set_pmd(pmd, __pmd(addr | pmd_flag));
+	}
+}
+
+static int ident_pud_init(struct x86_mapping_info *info, pud_t *pud_page,
+			  unsigned long addr, unsigned long end)
+{
+	unsigned long next;
+
+	for (; addr < end; addr = next) {
+		pud_t *pud = pud_page + pud_index(addr);
+		pmd_t *pmd;
+
+		next = (addr & PUD_MASK) + PUD_SIZE;
+		if (next > end)
+			next = end;
+
+		if (pud_present(*pud)) {
+			pmd = pmd_offset(pud, 0);
+			ident_pmd_init(info->pmd_flag, pmd, addr, next);
+			continue;
+		}
+		pmd = (pmd_t *)info->alloc_pgt_page(info->context);
+		if (!pmd)
+			return -ENOMEM;
+		ident_pmd_init(info->pmd_flag, pmd, addr, next);
+		set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE));
+	}
+
+	return 0;
+}
+
+int kernel_ident_mapping_init(struct x86_mapping_info *info, pgd_t *pgd_page,
+			      unsigned long addr, unsigned long end)
+{
+	unsigned long next;
+	int result;
+	int off = info->kernel_mapping ? pgd_index(__PAGE_OFFSET) : 0;
+
+	for (; addr < end; addr = next) {
+		pgd_t *pgd = pgd_page + pgd_index(addr) + off;
+		pud_t *pud;
+
+		next = (addr & PGDIR_MASK) + PGDIR_SIZE;
+		if (next > end)
+			next = end;
+
+		if (pgd_present(*pgd)) {
+			pud = pud_offset(pgd, 0);
+			result = ident_pud_init(info, pud, addr, next);
+			if (result)
+				return result;
+			continue;
+		}
+
+		pud = (pud_t *)info->alloc_pgt_page(info->context);
+		if (!pud)
+			return -ENOMEM;
+		result = ident_pud_init(info, pud, addr, next);
+		if (result)
+			return result;
+		set_pgd(pgd, __pgd(__pa(pud) | _KERNPG_TABLE));
+	}
+
+	return 0;
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/mm/init_32.c linux-libre-4.7-gnu/arch/x86/mm/init_32.c
--- linux-libre-4.6-gnu/arch/x86/mm/init_32.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/mm/init_32.c	2016-07-24 15:23:50.000000000 -0400
@@ -284,7 +284,7 @@ kernel_physical_mapping_init(unsigned lo
 	 */
 	mapping_iter = 1;
 
-	if (!cpu_has_pse)
+	if (!boot_cpu_has(X86_FEATURE_PSE))
 		use_pse = 0;
 
 repeat:
@@ -804,9 +804,6 @@ void __init mem_init(void)
 	BUILD_BUG_ON(VMALLOC_START			>= VMALLOC_END);
 #undef high_memory
 #undef __FIXADDR_TOP
-#ifdef CONFIG_RANDOMIZE_BASE
-	BUILD_BUG_ON(CONFIG_RANDOMIZE_BASE_MAX_OFFSET > KERNEL_IMAGE_SIZE);
-#endif
 
 #ifdef CONFIG_HIGHMEM
 	BUG_ON(PKMAP_BASE + LAST_PKMAP*PAGE_SIZE	> FIXADDR_START);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/mm/init_64.c linux-libre-4.7-gnu/arch/x86/mm/init_64.c
--- linux-libre-4.6-gnu/arch/x86/mm/init_64.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/mm/init_64.c	2016-07-24 15:23:50.000000000 -0400
@@ -58,79 +58,7 @@
 
 #include "mm_internal.h"
 
-static void ident_pmd_init(unsigned long pmd_flag, pmd_t *pmd_page,
-			   unsigned long addr, unsigned long end)
-{
-	addr &= PMD_MASK;
-	for (; addr < end; addr += PMD_SIZE) {
-		pmd_t *pmd = pmd_page + pmd_index(addr);
-
-		if (!pmd_present(*pmd))
-			set_pmd(pmd, __pmd(addr | pmd_flag));
-	}
-}
-static int ident_pud_init(struct x86_mapping_info *info, pud_t *pud_page,
-			  unsigned long addr, unsigned long end)
-{
-	unsigned long next;
-
-	for (; addr < end; addr = next) {
-		pud_t *pud = pud_page + pud_index(addr);
-		pmd_t *pmd;
-
-		next = (addr & PUD_MASK) + PUD_SIZE;
-		if (next > end)
-			next = end;
-
-		if (pud_present(*pud)) {
-			pmd = pmd_offset(pud, 0);
-			ident_pmd_init(info->pmd_flag, pmd, addr, next);
-			continue;
-		}
-		pmd = (pmd_t *)info->alloc_pgt_page(info->context);
-		if (!pmd)
-			return -ENOMEM;
-		ident_pmd_init(info->pmd_flag, pmd, addr, next);
-		set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE));
-	}
-
-	return 0;
-}
-
-int kernel_ident_mapping_init(struct x86_mapping_info *info, pgd_t *pgd_page,
-			      unsigned long addr, unsigned long end)
-{
-	unsigned long next;
-	int result;
-	int off = info->kernel_mapping ? pgd_index(__PAGE_OFFSET) : 0;
-
-	for (; addr < end; addr = next) {
-		pgd_t *pgd = pgd_page + pgd_index(addr) + off;
-		pud_t *pud;
-
-		next = (addr & PGDIR_MASK) + PGDIR_SIZE;
-		if (next > end)
-			next = end;
-
-		if (pgd_present(*pgd)) {
-			pud = pud_offset(pgd, 0);
-			result = ident_pud_init(info, pud, addr, next);
-			if (result)
-				return result;
-			continue;
-		}
-
-		pud = (pud_t *)info->alloc_pgt_page(info->context);
-		if (!pud)
-			return -ENOMEM;
-		result = ident_pud_init(info, pud, addr, next);
-		if (result)
-			return result;
-		set_pgd(pgd, __pgd(__pa(pud) | _KERNPG_TABLE));
-	}
-
-	return 0;
-}
+#include "ident_map.c"
 
 /*
  * NOTE: pagetable_init alloc all the fixmap pagetables contiguous on the
@@ -1295,7 +1223,7 @@ int __meminit vmemmap_populate(unsigned
 	struct vmem_altmap *altmap = to_vmem_altmap(start);
 	int err;
 
-	if (cpu_has_pse)
+	if (boot_cpu_has(X86_FEATURE_PSE))
 		err = vmemmap_populate_hugepages(start, end, node, altmap);
 	else if (altmap) {
 		pr_err_once("%s: no cpu support for altmap allocations\n",
@@ -1338,7 +1266,7 @@ void register_page_bootmem_memmap(unsign
 		}
 		get_page_bootmem(section_nr, pud_page(*pud), MIX_SECTION_INFO);
 
-		if (!cpu_has_pse) {
+		if (!boot_cpu_has(X86_FEATURE_PSE)) {
 			next = (addr + PAGE_SIZE) & PAGE_MASK;
 			pmd = pmd_offset(pud, addr);
 			if (pmd_none(*pmd))
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/mm/init.c linux-libre-4.7-gnu/arch/x86/mm/init.c
--- linux-libre-4.6-gnu/arch/x86/mm/init.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/mm/init.c	2016-07-24 15:23:50.000000000 -0400
@@ -157,23 +157,23 @@ static void __init probe_page_size_mask(
 	 * This will simplify cpa(), which otherwise needs to support splitting
 	 * large pages into small in interrupt context, etc.
 	 */
-	if (cpu_has_pse && !debug_pagealloc_enabled())
+	if (boot_cpu_has(X86_FEATURE_PSE) && !debug_pagealloc_enabled())
 		page_size_mask |= 1 << PG_LEVEL_2M;
 #endif
 
 	/* Enable PSE if available */
-	if (cpu_has_pse)
+	if (boot_cpu_has(X86_FEATURE_PSE))
 		cr4_set_bits_and_update_boot(X86_CR4_PSE);
 
 	/* Enable PGE if available */
-	if (cpu_has_pge) {
+	if (boot_cpu_has(X86_FEATURE_PGE)) {
 		cr4_set_bits_and_update_boot(X86_CR4_PGE);
 		__supported_pte_mask |= _PAGE_GLOBAL;
 	} else
 		__supported_pte_mask &= ~_PAGE_GLOBAL;
 
 	/* Enable 1 GB linear kernel mappings if available: */
-	if (direct_gbpages && cpu_has_gbpages) {
+	if (direct_gbpages && boot_cpu_has(X86_FEATURE_GBPAGES)) {
 		printk(KERN_INFO "Using GB pages for direct mapping\n");
 		page_size_mask |= 1 << PG_LEVEL_1G;
 	} else {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/mm/ioremap.c linux-libre-4.7-gnu/arch/x86/mm/ioremap.c
--- linux-libre-4.6-gnu/arch/x86/mm/ioremap.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/mm/ioremap.c	2016-07-24 15:23:50.000000000 -0400
@@ -378,7 +378,7 @@ EXPORT_SYMBOL(iounmap);
 int __init arch_ioremap_pud_supported(void)
 {
 #ifdef CONFIG_X86_64
-	return cpu_has_gbpages;
+	return boot_cpu_has(X86_FEATURE_GBPAGES);
 #else
 	return 0;
 #endif
@@ -386,7 +386,7 @@ int __init arch_ioremap_pud_supported(vo
 
 int __init arch_ioremap_pmd_supported(void)
 {
-	return cpu_has_pse;
+	return boot_cpu_has(X86_FEATURE_PSE);
 }
 
 /*
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/mm/kasan_init_64.c linux-libre-4.7-gnu/arch/x86/mm/kasan_init_64.c
--- linux-libre-4.6-gnu/arch/x86/mm/kasan_init_64.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/mm/kasan_init_64.c	2016-07-24 15:23:50.000000000 -0400
@@ -54,8 +54,8 @@ static int kasan_die_handler(struct noti
 			     void *data)
 {
 	if (val == DIE_GPF) {
-		pr_emerg("CONFIG_KASAN_INLINE enabled");
-		pr_emerg("GPF could be caused by NULL-ptr deref or user memory access");
+		pr_emerg("CONFIG_KASAN_INLINE enabled\n");
+		pr_emerg("GPF could be caused by NULL-ptr deref or user memory access\n");
 	}
 	return NOTIFY_OK;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/mm/Makefile linux-libre-4.7-gnu/arch/x86/mm/Makefile
--- linux-libre-4.6-gnu/arch/x86/mm/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/mm/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -2,7 +2,7 @@
 KCOV_INSTRUMENT_tlb.o	:= n
 
 obj-y	:=  init.o init_$(BITS).o fault.o ioremap.o extable.o pageattr.o mmap.o \
-	    pat.o pgtable.o physaddr.o gup.o setup_nx.o
+	    pat.o pgtable.o physaddr.o gup.o setup_nx.o tlb.o
 
 # Make sure __phys_addr has no stackprotector
 nostackp := $(call cc-option, -fno-stack-protector)
@@ -12,7 +12,6 @@ CFLAGS_setup_nx.o		:= $(nostackp)
 CFLAGS_fault.o := -I$(src)/../include/asm/trace
 
 obj-$(CONFIG_X86_PAT)		+= pat_rbtree.o
-obj-$(CONFIG_SMP)		+= tlb.o
 
 obj-$(CONFIG_X86_32)		+= pgtable_32.o iomap_32.o
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/mm/numa.c linux-libre-4.7-gnu/arch/x86/mm/numa.c
--- linux-libre-4.6-gnu/arch/x86/mm/numa.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/mm/numa.c	2016-07-24 15:23:50.000000000 -0400
@@ -617,9 +617,7 @@ static void __init numa_init_array(void)
 		if (early_cpu_to_node(i) != NUMA_NO_NODE)
 			continue;
 		numa_set_node(i, rr);
-		rr = next_node(rr, node_online_map);
-		if (rr == MAX_NUMNODES)
-			rr = first_node(node_online_map);
+		rr = next_node_in(rr, node_online_map);
 	}
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/mm/pageattr.c linux-libre-4.7-gnu/arch/x86/mm/pageattr.c
--- linux-libre-4.6-gnu/arch/x86/mm/pageattr.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/mm/pageattr.c	2016-07-24 15:23:50.000000000 -0400
@@ -1055,7 +1055,7 @@ static int populate_pud(struct cpa_data
 	/*
 	 * Map everything starting from the Gb boundary, possibly with 1G pages
 	 */
-	while (cpu_has_gbpages && end - start >= PUD_SIZE) {
+	while (boot_cpu_has(X86_FEATURE_GBPAGES) && end - start >= PUD_SIZE) {
 		set_pud(pud, __pud(cpa->pfn << PAGE_SHIFT | _PAGE_PSE |
 				   massage_pgprot(pud_pgprot)));
 
@@ -1125,8 +1125,14 @@ static int populate_pgd(struct cpa_data
 static int __cpa_process_fault(struct cpa_data *cpa, unsigned long vaddr,
 			       int primary)
 {
-	if (cpa->pgd)
+	if (cpa->pgd) {
+		/*
+		 * Right now, we only execute this code path when mapping
+		 * the EFI virtual memory map regions, no other users
+		 * provide a ->pgd value. This may change in the future.
+		 */
 		return populate_pgd(cpa, vaddr);
+	}
 
 	/*
 	 * Ignore all non primary paths.
@@ -1460,7 +1466,7 @@ static int change_page_attr_set_clr(unsi
 	 * error case we fall back to cpa_flush_all (which uses
 	 * WBINVD):
 	 */
-	if (!ret && cpu_has_clflush) {
+	if (!ret && boot_cpu_has(X86_FEATURE_CLFLUSH)) {
 		if (cpa.flags & (CPA_PAGES_ARRAY | CPA_ARRAY)) {
 			cpa_flush_array(addr, numpages, cache,
 					cpa.flags, pages);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/mm/pat.c linux-libre-4.7-gnu/arch/x86/mm/pat.c
--- linux-libre-4.6-gnu/arch/x86/mm/pat.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/mm/pat.c	2016-07-24 15:23:50.000000000 -0400
@@ -40,11 +40,22 @@
 static bool boot_cpu_done;
 
 static int __read_mostly __pat_enabled = IS_ENABLED(CONFIG_X86_PAT);
+static void init_cache_modes(void);
 
-static inline void pat_disable(const char *reason)
+void pat_disable(const char *reason)
 {
+	if (!__pat_enabled)
+		return;
+
+	if (boot_cpu_done) {
+		WARN_ONCE(1, "x86/PAT: PAT cannot be disabled after initialization\n");
+		return;
+	}
+
 	__pat_enabled = 0;
 	pr_info("x86/PAT: %s\n", reason);
+
+	init_cache_modes();
 }
 
 static int __init nopat(char *str)
@@ -181,7 +192,7 @@ static enum page_cache_mode pat_get_cach
  * configuration.
  * Using lower indices is preferred, so we start with highest index.
  */
-void pat_init_cache_modes(u64 pat)
+static void __init_cache_modes(u64 pat)
 {
 	enum page_cache_mode cache;
 	char pat_msg[33];
@@ -202,14 +213,11 @@ static void pat_bsp_init(u64 pat)
 {
 	u64 tmp_pat;
 
-	if (!cpu_has_pat) {
+	if (!boot_cpu_has(X86_FEATURE_PAT)) {
 		pat_disable("PAT not supported by CPU.");
 		return;
 	}
 
-	if (!pat_enabled())
-		goto done;
-
 	rdmsrl(MSR_IA32_CR_PAT, tmp_pat);
 	if (!tmp_pat) {
 		pat_disable("PAT MSR is 0, disabled.");
@@ -218,16 +226,12 @@ static void pat_bsp_init(u64 pat)
 
 	wrmsrl(MSR_IA32_CR_PAT, pat);
 
-done:
-	pat_init_cache_modes(pat);
+	__init_cache_modes(pat);
 }
 
 static void pat_ap_init(u64 pat)
 {
-	if (!pat_enabled())
-		return;
-
-	if (!cpu_has_pat) {
+	if (!boot_cpu_has(X86_FEATURE_PAT)) {
 		/*
 		 * If this happens we are on a secondary CPU, but switched to
 		 * PAT on the boot CPU. We have no way to undo PAT.
@@ -238,18 +242,32 @@ static void pat_ap_init(u64 pat)
 	wrmsrl(MSR_IA32_CR_PAT, pat);
 }
 
-void pat_init(void)
+static void init_cache_modes(void)
 {
-	u64 pat;
-	struct cpuinfo_x86 *c = &boot_cpu_data;
+	u64 pat = 0;
+	static int init_cm_done;
 
-	if (!pat_enabled()) {
+	if (init_cm_done)
+		return;
+
+	if (boot_cpu_has(X86_FEATURE_PAT)) {
+		/*
+		 * CPU supports PAT. Set PAT table to be consistent with
+		 * PAT MSR. This case supports "nopat" boot option, and
+		 * virtual machine environments which support PAT without
+		 * MTRRs. In specific, Xen has unique setup to PAT MSR.
+		 *
+		 * If PAT MSR returns 0, it is considered invalid and emulates
+		 * as No PAT.
+		 */
+		rdmsrl(MSR_IA32_CR_PAT, pat);
+	}
+
+	if (!pat) {
 		/*
 		 * No PAT. Emulate the PAT table that corresponds to the two
-		 * cache bits, PWT (Write Through) and PCD (Cache Disable). This
-		 * setup is the same as the BIOS default setup when the system
-		 * has PAT but the "nopat" boot option has been specified. This
-		 * emulated PAT table is used when MSR_IA32_CR_PAT returns 0.
+		 * cache bits, PWT (Write Through) and PCD (Cache Disable).
+		 * This setup is also the same as the BIOS default setup.
 		 *
 		 * PTE encoding:
 		 *
@@ -266,10 +284,36 @@ void pat_init(void)
 		 */
 		pat = PAT(0, WB) | PAT(1, WT) | PAT(2, UC_MINUS) | PAT(3, UC) |
 		      PAT(4, WB) | PAT(5, WT) | PAT(6, UC_MINUS) | PAT(7, UC);
+	}
 
-	} else if ((c->x86_vendor == X86_VENDOR_INTEL) &&
-		   (((c->x86 == 0x6) && (c->x86_model <= 0xd)) ||
-		    ((c->x86 == 0xf) && (c->x86_model <= 0x6)))) {
+	__init_cache_modes(pat);
+
+	init_cm_done = 1;
+}
+
+/**
+ * pat_init - Initialize PAT MSR and PAT table
+ *
+ * This function initializes PAT MSR and PAT table with an OS-defined value
+ * to enable additional cache attributes, WC and WT.
+ *
+ * This function must be called on all CPUs using the specific sequence of
+ * operations defined in Intel SDM. mtrr_rendezvous_handler() provides this
+ * procedure for PAT.
+ */
+void pat_init(void)
+{
+	u64 pat;
+	struct cpuinfo_x86 *c = &boot_cpu_data;
+
+	if (!pat_enabled()) {
+		init_cache_modes();
+		return;
+	}
+
+	if ((c->x86_vendor == X86_VENDOR_INTEL) &&
+	    (((c->x86 == 0x6) && (c->x86_model <= 0xd)) ||
+	     ((c->x86 == 0xf) && (c->x86_model <= 0x6)))) {
 		/*
 		 * PAT support with the lower four entries. Intel Pentium 2,
 		 * 3, M, and 4 are affected by PAT errata, which makes the
@@ -734,25 +778,6 @@ int phys_mem_access_prot_allowed(struct
 	if (file->f_flags & O_DSYNC)
 		pcm = _PAGE_CACHE_MODE_UC_MINUS;
 
-#ifdef CONFIG_X86_32
-	/*
-	 * On the PPro and successors, the MTRRs are used to set
-	 * memory types for physical addresses outside main memory,
-	 * so blindly setting UC or PWT on those pages is wrong.
-	 * For Pentiums and earlier, the surround logic should disable
-	 * caching for the high addresses through the KEN pin, but
-	 * we maintain the tradition of paranoia in this code.
-	 */
-	if (!pat_enabled() &&
-	    !(boot_cpu_has(X86_FEATURE_MTRR) ||
-	      boot_cpu_has(X86_FEATURE_K6_MTRR) ||
-	      boot_cpu_has(X86_FEATURE_CYRIX_ARR) ||
-	      boot_cpu_has(X86_FEATURE_CENTAUR_MCR)) &&
-	    (pfn << PAGE_SHIFT) >= __pa(high_memory)) {
-		pcm = _PAGE_CACHE_MODE_UC;
-	}
-#endif
-
 	*vma_prot = __pgprot((pgprot_val(*vma_prot) & ~_PAGE_CACHE_MASK) |
 			     cachemode2protval(pcm));
 	return 1;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/mm/pgtable.c linux-libre-4.7-gnu/arch/x86/mm/pgtable.c
--- linux-libre-4.6-gnu/arch/x86/mm/pgtable.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/mm/pgtable.c	2016-07-24 15:23:50.000000000 -0400
@@ -6,7 +6,7 @@
 #include <asm/fixmap.h>
 #include <asm/mtrr.h>
 
-#define PGALLOC_GFP GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO
+#define PGALLOC_GFP GFP_KERNEL | __GFP_NOTRACK | __GFP_ZERO
 
 #ifdef CONFIG_HIGHPTE
 #define PGALLOC_USER_GFP __GFP_HIGHMEM
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/mm/tlb.c linux-libre-4.7-gnu/arch/x86/mm/tlb.c
--- linux-libre-4.6-gnu/arch/x86/mm/tlb.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/mm/tlb.c	2016-07-24 15:23:50.000000000 -0400
@@ -28,6 +28,8 @@
  *	Implement flush IPI by CALL_FUNCTION_VECTOR, Alex Shi
  */
 
+#ifdef CONFIG_SMP
+
 struct flush_tlb_info {
 	struct mm_struct *flush_mm;
 	unsigned long flush_start;
@@ -57,6 +59,118 @@ void leave_mm(int cpu)
 }
 EXPORT_SYMBOL_GPL(leave_mm);
 
+#endif /* CONFIG_SMP */
+
+void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+	       struct task_struct *tsk)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	switch_mm_irqs_off(prev, next, tsk);
+	local_irq_restore(flags);
+}
+
+void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
+			struct task_struct *tsk)
+{
+	unsigned cpu = smp_processor_id();
+
+	if (likely(prev != next)) {
+#ifdef CONFIG_SMP
+		this_cpu_write(cpu_tlbstate.state, TLBSTATE_OK);
+		this_cpu_write(cpu_tlbstate.active_mm, next);
+#endif
+		cpumask_set_cpu(cpu, mm_cpumask(next));
+
+		/*
+		 * Re-load page tables.
+		 *
+		 * This logic has an ordering constraint:
+		 *
+		 *  CPU 0: Write to a PTE for 'next'
+		 *  CPU 0: load bit 1 in mm_cpumask.  if nonzero, send IPI.
+		 *  CPU 1: set bit 1 in next's mm_cpumask
+		 *  CPU 1: load from the PTE that CPU 0 writes (implicit)
+		 *
+		 * We need to prevent an outcome in which CPU 1 observes
+		 * the new PTE value and CPU 0 observes bit 1 clear in
+		 * mm_cpumask.  (If that occurs, then the IPI will never
+		 * be sent, and CPU 0's TLB will contain a stale entry.)
+		 *
+		 * The bad outcome can occur if either CPU's load is
+		 * reordered before that CPU's store, so both CPUs must
+		 * execute full barriers to prevent this from happening.
+		 *
+		 * Thus, switch_mm needs a full barrier between the
+		 * store to mm_cpumask and any operation that could load
+		 * from next->pgd.  TLB fills are special and can happen
+		 * due to instruction fetches or for no reason at all,
+		 * and neither LOCK nor MFENCE orders them.
+		 * Fortunately, load_cr3() is serializing and gives the
+		 * ordering guarantee we need.
+		 *
+		 */
+		load_cr3(next->pgd);
+
+		trace_tlb_flush(TLB_FLUSH_ON_TASK_SWITCH, TLB_FLUSH_ALL);
+
+		/* Stop flush ipis for the previous mm */
+		cpumask_clear_cpu(cpu, mm_cpumask(prev));
+
+		/* Load per-mm CR4 state */
+		load_mm_cr4(next);
+
+#ifdef CONFIG_MODIFY_LDT_SYSCALL
+		/*
+		 * Load the LDT, if the LDT is different.
+		 *
+		 * It's possible that prev->context.ldt doesn't match
+		 * the LDT register.  This can happen if leave_mm(prev)
+		 * was called and then modify_ldt changed
+		 * prev->context.ldt but suppressed an IPI to this CPU.
+		 * In this case, prev->context.ldt != NULL, because we
+		 * never set context.ldt to NULL while the mm still
+		 * exists.  That means that next->context.ldt !=
+		 * prev->context.ldt, because mms never share an LDT.
+		 */
+		if (unlikely(prev->context.ldt != next->context.ldt))
+			load_mm_ldt(next);
+#endif
+	}
+#ifdef CONFIG_SMP
+	  else {
+		this_cpu_write(cpu_tlbstate.state, TLBSTATE_OK);
+		BUG_ON(this_cpu_read(cpu_tlbstate.active_mm) != next);
+
+		if (!cpumask_test_cpu(cpu, mm_cpumask(next))) {
+			/*
+			 * On established mms, the mm_cpumask is only changed
+			 * from irq context, from ptep_clear_flush() while in
+			 * lazy tlb mode, and here. Irqs are blocked during
+			 * schedule, protecting us from simultaneous changes.
+			 */
+			cpumask_set_cpu(cpu, mm_cpumask(next));
+
+			/*
+			 * We were in lazy tlb mode and leave_mm disabled
+			 * tlb flush IPI delivery. We must reload CR3
+			 * to make sure to use no freed page tables.
+			 *
+			 * As above, load_cr3() is serializing and orders TLB
+			 * fills with respect to the mm_cpumask write.
+			 */
+			load_cr3(next->pgd);
+			trace_tlb_flush(TLB_FLUSH_ON_TASK_SWITCH, TLB_FLUSH_ALL);
+			load_mm_cr4(next);
+			load_mm_ldt(next);
+		}
+	}
+#endif
+}
+
+#ifdef CONFIG_SMP
+
 /*
  * The flush IPI assumes that a thread switch happens in this order:
  * [cpu0: the cpu that switches]
@@ -353,3 +467,5 @@ static int __init create_tlb_single_page
 	return 0;
 }
 late_initcall(create_tlb_single_page_flush_ceiling);
+
+#endif /* CONFIG_SMP */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/net/bpf_jit_comp.c linux-libre-4.7-gnu/arch/x86/net/bpf_jit_comp.c
--- linux-libre-4.6-gnu/arch/x86/net/bpf_jit_comp.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/net/bpf_jit_comp.c	2016-07-24 15:23:50.000000000 -0400
@@ -110,11 +110,16 @@ static void bpf_flush_icache(void *start
 	((int)K < 0 ? ((int)K >= SKF_LL_OFF ? func##_negative_offset : func) : func##_positive_offset)
 
 /* pick a register outside of BPF range for JIT internal work */
-#define AUX_REG (MAX_BPF_REG + 1)
+#define AUX_REG (MAX_BPF_JIT_REG + 1)
 
-/* the following table maps BPF registers to x64 registers.
- * x64 register r12 is unused, since if used as base address register
- * in load/store instructions, it always needs an extra byte of encoding
+/* The following table maps BPF registers to x64 registers.
+ *
+ * x64 register r12 is unused, since if used as base address
+ * register in load/store instructions, it always needs an
+ * extra byte of encoding and is callee saved.
+ *
+ *  r9 caches skb->len - skb->data_len
+ * r10 caches skb->data, and used for blinding (if enabled)
  */
 static const int reg2hex[] = {
 	[BPF_REG_0] = 0,  /* rax */
@@ -128,6 +133,7 @@ static const int reg2hex[] = {
 	[BPF_REG_8] = 6,  /* r14 callee saved */
 	[BPF_REG_9] = 7,  /* r15 callee saved */
 	[BPF_REG_FP] = 5, /* rbp readonly */
+	[BPF_REG_AX] = 2, /* r10 temp register */
 	[AUX_REG] = 3,    /* r11 temp register */
 };
 
@@ -141,7 +147,8 @@ static bool is_ereg(u32 reg)
 			     BIT(AUX_REG) |
 			     BIT(BPF_REG_7) |
 			     BIT(BPF_REG_8) |
-			     BIT(BPF_REG_9));
+			     BIT(BPF_REG_9) |
+			     BIT(BPF_REG_AX));
 }
 
 /* add modifiers if 'reg' maps to x64 registers r8..r15 */
@@ -182,6 +189,7 @@ static void jit_fill_hole(void *area, un
 struct jit_context {
 	int cleanup_addr; /* epilogue code offset */
 	bool seen_ld_abs;
+	bool seen_ax_reg;
 };
 
 /* maximum number of bytes emitted while JITing one eBPF insn */
@@ -345,6 +353,7 @@ static int do_jit(struct bpf_prog *bpf_p
 	struct bpf_insn *insn = bpf_prog->insnsi;
 	int insn_cnt = bpf_prog->len;
 	bool seen_ld_abs = ctx->seen_ld_abs | (oldproglen == 0);
+	bool seen_ax_reg = ctx->seen_ax_reg | (oldproglen == 0);
 	bool seen_exit = false;
 	u8 temp[BPF_MAX_INSN_SIZE + BPF_INSN_SAFETY];
 	int i, cnt = 0;
@@ -367,6 +376,9 @@ static int do_jit(struct bpf_prog *bpf_p
 		int ilen;
 		u8 *func;
 
+		if (dst_reg == BPF_REG_AX || src_reg == BPF_REG_AX)
+			ctx->seen_ax_reg = seen_ax_reg = true;
+
 		switch (insn->code) {
 			/* ALU */
 		case BPF_ALU | BPF_ADD | BPF_X:
@@ -1002,6 +1014,10 @@ common_load:
 			 * sk_load_* helpers also use %r10 and %r9d.
 			 * See bpf_jit.S
 			 */
+			if (seen_ax_reg)
+				/* r10 = skb->data, mov %r10, off32(%rbx) */
+				EMIT3_off32(0x4c, 0x8b, 0x93,
+					    offsetof(struct sk_buff, data));
 			EMIT1_off32(0xE8, jmp_offset); /* call */
 			break;
 
@@ -1073,25 +1089,37 @@ void bpf_jit_compile(struct bpf_prog *pr
 {
 }
 
-void bpf_int_jit_compile(struct bpf_prog *prog)
+struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
 {
 	struct bpf_binary_header *header = NULL;
+	struct bpf_prog *tmp, *orig_prog = prog;
 	int proglen, oldproglen = 0;
 	struct jit_context ctx = {};
+	bool tmp_blinded = false;
 	u8 *image = NULL;
 	int *addrs;
 	int pass;
 	int i;
 
 	if (!bpf_jit_enable)
-		return;
+		return orig_prog;
 
-	if (!prog || !prog->len)
-		return;
+	tmp = bpf_jit_blind_constants(prog);
+	/* If blinding was requested and we failed during blinding,
+	 * we must fall back to the interpreter.
+	 */
+	if (IS_ERR(tmp))
+		return orig_prog;
+	if (tmp != prog) {
+		tmp_blinded = true;
+		prog = tmp;
+	}
 
 	addrs = kmalloc(prog->len * sizeof(*addrs), GFP_KERNEL);
-	if (!addrs)
-		return;
+	if (!addrs) {
+		prog = orig_prog;
+		goto out;
+	}
 
 	/* Before first pass, make a rough estimation of addrs[]
 	 * each bpf instruction is translated to less than 64 bytes
@@ -1113,21 +1141,25 @@ void bpf_int_jit_compile(struct bpf_prog
 			image = NULL;
 			if (header)
 				bpf_jit_binary_free(header);
-			goto out;
+			prog = orig_prog;
+			goto out_addrs;
 		}
 		if (image) {
 			if (proglen != oldproglen) {
 				pr_err("bpf_jit: proglen=%d != oldproglen=%d\n",
 				       proglen, oldproglen);
-				goto out;
+				prog = orig_prog;
+				goto out_addrs;
 			}
 			break;
 		}
 		if (proglen == oldproglen) {
 			header = bpf_jit_binary_alloc(proglen, &image,
 						      1, jit_fill_hole);
-			if (!header)
-				goto out;
+			if (!header) {
+				prog = orig_prog;
+				goto out_addrs;
+			}
 		}
 		oldproglen = proglen;
 	}
@@ -1141,8 +1173,14 @@ void bpf_int_jit_compile(struct bpf_prog
 		prog->bpf_func = (void *)image;
 		prog->jited = 1;
 	}
-out:
+
+out_addrs:
 	kfree(addrs);
+out:
+	if (tmp_blinded)
+		bpf_jit_prog_release_other(prog, prog == orig_prog ?
+					   tmp : orig_prog);
+	return prog;
 }
 
 void bpf_jit_free(struct bpf_prog *fp)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/oprofile/nmi_int.c linux-libre-4.7-gnu/arch/x86/oprofile/nmi_int.c
--- linux-libre-4.6-gnu/arch/x86/oprofile/nmi_int.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/oprofile/nmi_int.c	2016-07-24 15:23:50.000000000 -0400
@@ -636,7 +636,7 @@ static int __init ppro_init(char **cpu_t
 	__u8 cpu_model = boot_cpu_data.x86_model;
 	struct op_x86_model_spec *spec = &op_ppro_spec;	/* default */
 
-	if (force_cpu_type == arch_perfmon && cpu_has_arch_perfmon)
+	if (force_cpu_type == arch_perfmon && boot_cpu_has(X86_FEATURE_ARCH_PERFMON))
 		return 0;
 
 	/*
@@ -700,7 +700,7 @@ int __init op_nmi_init(struct oprofile_o
 	char *cpu_type = NULL;
 	int ret = 0;
 
-	if (!cpu_has_apic)
+	if (!boot_cpu_has(X86_FEATURE_APIC))
 		return -ENODEV;
 
 	if (force_cpu_type == timer)
@@ -761,7 +761,7 @@ int __init op_nmi_init(struct oprofile_o
 		if (cpu_type)
 			break;
 
-		if (!cpu_has_arch_perfmon)
+		if (!boot_cpu_has(X86_FEATURE_ARCH_PERFMON))
 			return -ENODEV;
 
 		/* use arch perfmon as fallback */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/oprofile/op_model_ppro.c linux-libre-4.7-gnu/arch/x86/oprofile/op_model_ppro.c
--- linux-libre-4.6-gnu/arch/x86/oprofile/op_model_ppro.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/oprofile/op_model_ppro.c	2016-07-24 15:23:50.000000000 -0400
@@ -75,7 +75,7 @@ static void ppro_setup_ctrs(struct op_x8
 	u64 val;
 	int i;
 
-	if (cpu_has_arch_perfmon) {
+	if (boot_cpu_has(X86_FEATURE_ARCH_PERFMON)) {
 		union cpuid10_eax eax;
 		eax.full = cpuid_eax(0xa);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/pci/common.c linux-libre-4.7-gnu/arch/x86/pci/common.c
--- linux-libre-4.6-gnu/arch/x86/pci/common.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/pci/common.c	2016-07-24 15:23:50.000000000 -0400
@@ -516,7 +516,7 @@ void __init pcibios_set_cache_line_size(
 
 int __init pcibios_init(void)
 {
-	if (!raw_pci_ops) {
+	if (!raw_pci_ops && !raw_pci_ext_ops) {
 		printk(KERN_WARNING "PCI: System does not support PCI\n");
 		return 0;
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/pci/fixup.c linux-libre-4.7-gnu/arch/x86/pci/fixup.c
--- linux-libre-4.6-gnu/arch/x86/pci/fixup.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/pci/fixup.c	2016-07-24 15:23:50.000000000 -0400
@@ -552,9 +552,16 @@ static void twinhead_reserve_killing_zon
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x27B9, twinhead_reserve_killing_zone);
 
+/*
+ * Broadwell EP Home Agent BARs erroneously return non-zero values when read.
+ *
+ * See http://www.intel.com/content/www/us/en/processors/xeon/xeon-e5-v4-spec-update.html
+ * entry BDF2.
+ */
 static void pci_bdwep_bar(struct pci_dev *dev)
 {
 	dev->non_compliant_bars = 1;
 }
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6f60, pci_bdwep_bar);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6fa0, pci_bdwep_bar);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6fc0, pci_bdwep_bar);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/pci/xen.c linux-libre-4.7-gnu/arch/x86/pci/xen.c
--- linux-libre-4.6-gnu/arch/x86/pci/xen.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/pci/xen.c	2016-07-24 15:23:50.000000000 -0400
@@ -445,7 +445,7 @@ void __init xen_msi_init(void)
 		uint32_t eax = cpuid_eax(xen_cpuid_base() + 4);
 
 		if (((eax & XEN_HVM_CPUID_X2APIC_VIRT) && x2apic_mode) ||
-		    ((eax & XEN_HVM_CPUID_APIC_ACCESS_VIRT) && cpu_has_apic))
+		    ((eax & XEN_HVM_CPUID_APIC_ACCESS_VIRT) && boot_cpu_has(X86_FEATURE_APIC)))
 			return;
 	}
 
@@ -491,8 +491,11 @@ int __init pci_xen_initial_domain(void)
 #endif
 	__acpi_register_gsi = acpi_register_gsi_xen;
 	__acpi_unregister_gsi = NULL;
-	/* Pre-allocate legacy irqs */
-	for (irq = 0; irq < nr_legacy_irqs(); irq++) {
+	/*
+	 * Pre-allocate the legacy IRQs.  Use NR_LEGACY_IRQS here
+	 * because we don't have a PIC and thus nr_legacy_irqs() is zero.
+	 */
+	for (irq = 0; irq < NR_IRQS_LEGACY; irq++) {
 		int trigger, polarity;
 
 		if (acpi_get_override_irq(irq, &trigger, &polarity) == -1)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/platform/efi/efi_64.c linux-libre-4.7-gnu/arch/x86/platform/efi/efi_64.c
--- linux-libre-4.6-gnu/arch/x86/platform/efi/efi_64.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/platform/efi/efi_64.c	2016-07-24 15:23:50.000000000 -0400
@@ -55,14 +55,12 @@ struct efi_scratch efi_scratch;
 static void __init early_code_mapping_set_exec(int executable)
 {
 	efi_memory_desc_t *md;
-	void *p;
 
 	if (!(__supported_pte_mask & _PAGE_NX))
 		return;
 
 	/* Make EFI service code area executable */
-	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
-		md = p;
+	for_each_efi_memory_desc(md) {
 		if (md->type == EFI_RUNTIME_SERVICES_CODE ||
 		    md->type == EFI_BOOT_SERVICES_CODE)
 			efi_set_executable(md, executable);
@@ -141,7 +139,7 @@ int __init efi_alloc_page_tables(void)
 	if (efi_enabled(EFI_OLD_MEMMAP))
 		return 0;
 
-	gfp_mask = GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO;
+	gfp_mask = GFP_KERNEL | __GFP_NOTRACK | __GFP_ZERO;
 	efi_pgd = (pgd_t *)__get_free_page(gfp_mask);
 	if (!efi_pgd)
 		return -ENOMEM;
@@ -253,7 +251,7 @@ int __init efi_setup_page_tables(unsigne
 	 * Map all of RAM so that we can access arguments in the 1:1
 	 * mapping when making EFI runtime calls.
 	 */
-	for_each_efi_memory_desc(&memmap, md) {
+	for_each_efi_memory_desc(md) {
 		if (md->type != EFI_CONVENTIONAL_MEMORY &&
 		    md->type != EFI_LOADER_DATA &&
 		    md->type != EFI_LOADER_CODE)
@@ -398,7 +396,6 @@ void __init efi_runtime_update_mappings(
 	unsigned long pfn;
 	pgd_t *pgd = efi_pgd;
 	efi_memory_desc_t *md;
-	void *p;
 
 	if (efi_enabled(EFI_OLD_MEMMAP)) {
 		if (__supported_pte_mask & _PAGE_NX)
@@ -409,9 +406,8 @@ void __init efi_runtime_update_mappings(
 	if (!efi_enabled(EFI_NX_PE_DATA))
 		return;
 
-	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
+	for_each_efi_memory_desc(md) {
 		unsigned long pf = 0;
-		md = p;
 
 		if (!(md->attribute & EFI_MEMORY_RUNTIME))
 			continue;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/platform/efi/efi.c linux-libre-4.7-gnu/arch/x86/platform/efi/efi.c
--- linux-libre-4.6-gnu/arch/x86/platform/efi/efi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/platform/efi/efi.c	2016-07-24 15:23:50.000000000 -0400
@@ -54,10 +54,6 @@
 #include <asm/rtc.h>
 #include <asm/uv/uv.h>
 
-#define EFI_DEBUG
-
-struct efi_memory_map memmap;
-
 static struct efi efi_phys __initdata;
 static efi_system_table_t efi_systab __initdata;
 
@@ -119,11 +115,10 @@ void efi_get_time(struct timespec *now)
 
 void __init efi_find_mirror(void)
 {
-	void *p;
+	efi_memory_desc_t *md;
 	u64 mirror_size = 0, total_size = 0;
 
-	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
-		efi_memory_desc_t *md = p;
+	for_each_efi_memory_desc(md) {
 		unsigned long long start = md->phys_addr;
 		unsigned long long size = md->num_pages << EFI_PAGE_SHIFT;
 
@@ -146,10 +141,9 @@ void __init efi_find_mirror(void)
 
 static void __init do_add_efi_memmap(void)
 {
-	void *p;
+	efi_memory_desc_t *md;
 
-	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
-		efi_memory_desc_t *md = p;
+	for_each_efi_memory_desc(md) {
 		unsigned long long start = md->phys_addr;
 		unsigned long long size = md->num_pages << EFI_PAGE_SHIFT;
 		int e820_type;
@@ -209,47 +203,47 @@ int __init efi_memblock_x86_reserve_rang
 #else
 	pmap = (e->efi_memmap |	((__u64)e->efi_memmap_hi << 32));
 #endif
-	memmap.phys_map		= pmap;
-	memmap.nr_map		= e->efi_memmap_size /
+	efi.memmap.phys_map	= pmap;
+	efi.memmap.nr_map	= e->efi_memmap_size /
 				  e->efi_memdesc_size;
-	memmap.desc_size	= e->efi_memdesc_size;
-	memmap.desc_version	= e->efi_memdesc_version;
+	efi.memmap.desc_size	= e->efi_memdesc_size;
+	efi.memmap.desc_version	= e->efi_memdesc_version;
 
-	memblock_reserve(pmap, memmap.nr_map * memmap.desc_size);
+	WARN(efi.memmap.desc_version != 1,
+	     "Unexpected EFI_MEMORY_DESCRIPTOR version %ld",
+	     efi.memmap.desc_version);
 
-	efi.memmap = &memmap;
+	memblock_reserve(pmap, efi.memmap.nr_map * efi.memmap.desc_size);
 
 	return 0;
 }
 
 void __init efi_print_memmap(void)
 {
-#ifdef EFI_DEBUG
 	efi_memory_desc_t *md;
-	void *p;
-	int i;
+	int i = 0;
 
-	for (p = memmap.map, i = 0;
-	     p < memmap.map_end;
-	     p += memmap.desc_size, i++) {
+	for_each_efi_memory_desc(md) {
 		char buf[64];
 
-		md = p;
 		pr_info("mem%02u: %s range=[0x%016llx-0x%016llx] (%lluMB)\n",
-			i, efi_md_typeattr_format(buf, sizeof(buf), md),
+			i++, efi_md_typeattr_format(buf, sizeof(buf), md),
 			md->phys_addr,
 			md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1,
 			(md->num_pages >> (20 - EFI_PAGE_SHIFT)));
 	}
-#endif  /*  EFI_DEBUG  */
 }
 
 void __init efi_unmap_memmap(void)
 {
+	unsigned long size;
+
 	clear_bit(EFI_MEMMAP, &efi.flags);
-	if (memmap.map) {
-		early_memunmap(memmap.map, memmap.nr_map * memmap.desc_size);
-		memmap.map = NULL;
+
+	size = efi.memmap.nr_map * efi.memmap.desc_size;
+	if (efi.memmap.map) {
+		early_memunmap(efi.memmap.map, size);
+		efi.memmap.map = NULL;
 	}
 }
 
@@ -352,8 +346,6 @@ static int __init efi_systab_init(void *
 		       efi.systab->hdr.revision >> 16,
 		       efi.systab->hdr.revision & 0xffff);
 
-	set_bit(EFI_SYSTEM_TABLES, &efi.flags);
-
 	return 0;
 }
 
@@ -440,17 +432,22 @@ static int __init efi_runtime_init(void)
 
 static int __init efi_memmap_init(void)
 {
+	unsigned long addr, size;
+
 	if (efi_enabled(EFI_PARAVIRT))
 		return 0;
 
 	/* Map the EFI memory map */
-	memmap.map = early_memremap((unsigned long)memmap.phys_map,
-				   memmap.nr_map * memmap.desc_size);
-	if (memmap.map == NULL) {
+	size = efi.memmap.nr_map * efi.memmap.desc_size;
+	addr = (unsigned long)efi.memmap.phys_map;
+
+	efi.memmap.map = early_memremap(addr, size);
+	if (efi.memmap.map == NULL) {
 		pr_err("Could not map the memory map!\n");
 		return -ENOMEM;
 	}
-	memmap.map_end = memmap.map + (memmap.nr_map * memmap.desc_size);
+
+	efi.memmap.map_end = efi.memmap.map + size;
 
 	if (add_efi_memmap)
 		do_add_efi_memmap();
@@ -552,12 +549,9 @@ void __init efi_set_executable(efi_memor
 void __init runtime_code_page_mkexec(void)
 {
 	efi_memory_desc_t *md;
-	void *p;
 
 	/* Make EFI runtime service code area executable */
-	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
-		md = p;
-
+	for_each_efi_memory_desc(md) {
 		if (md->type != EFI_RUNTIME_SERVICES_CODE)
 			continue;
 
@@ -604,12 +598,10 @@ void __init old_map_region(efi_memory_de
 /* Merge contiguous regions of the same type and attribute */
 static void __init efi_merge_regions(void)
 {
-	void *p;
 	efi_memory_desc_t *md, *prev_md = NULL;
 
-	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
+	for_each_efi_memory_desc(md) {
 		u64 prev_size;
-		md = p;
 
 		if (!prev_md) {
 			prev_md = md;
@@ -651,30 +643,31 @@ static void __init get_systab_virt_addr(
 static void __init save_runtime_map(void)
 {
 #ifdef CONFIG_KEXEC_CORE
+	unsigned long desc_size;
 	efi_memory_desc_t *md;
-	void *tmp, *p, *q = NULL;
+	void *tmp, *q = NULL;
 	int count = 0;
 
 	if (efi_enabled(EFI_OLD_MEMMAP))
 		return;
 
-	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
-		md = p;
+	desc_size = efi.memmap.desc_size;
 
+	for_each_efi_memory_desc(md) {
 		if (!(md->attribute & EFI_MEMORY_RUNTIME) ||
 		    (md->type == EFI_BOOT_SERVICES_CODE) ||
 		    (md->type == EFI_BOOT_SERVICES_DATA))
 			continue;
-		tmp = krealloc(q, (count + 1) * memmap.desc_size, GFP_KERNEL);
+		tmp = krealloc(q, (count + 1) * desc_size, GFP_KERNEL);
 		if (!tmp)
 			goto out;
 		q = tmp;
 
-		memcpy(q + count * memmap.desc_size, md, memmap.desc_size);
+		memcpy(q + count * desc_size, md, desc_size);
 		count++;
 	}
 
-	efi_runtime_map_setup(q, count, memmap.desc_size);
+	efi_runtime_map_setup(q, count, desc_size);
 	return;
 
 out:
@@ -714,10 +707,10 @@ static inline void *efi_map_next_entry_r
 {
 	/* Initial call */
 	if (!entry)
-		return memmap.map_end - memmap.desc_size;
+		return efi.memmap.map_end - efi.memmap.desc_size;
 
-	entry -= memmap.desc_size;
-	if (entry < memmap.map)
+	entry -= efi.memmap.desc_size;
+	if (entry < efi.memmap.map)
 		return NULL;
 
 	return entry;
@@ -759,10 +752,10 @@ static void *efi_map_next_entry(void *en
 
 	/* Initial call */
 	if (!entry)
-		return memmap.map;
+		return efi.memmap.map;
 
-	entry += memmap.desc_size;
-	if (entry >= memmap.map_end)
+	entry += efi.memmap.desc_size;
+	if (entry >= efi.memmap.map_end)
 		return NULL;
 
 	return entry;
@@ -776,8 +769,11 @@ static void * __init efi_map_regions(int
 {
 	void *p, *new_memmap = NULL;
 	unsigned long left = 0;
+	unsigned long desc_size;
 	efi_memory_desc_t *md;
 
+	desc_size = efi.memmap.desc_size;
+
 	p = NULL;
 	while ((p = efi_map_next_entry(p))) {
 		md = p;
@@ -792,7 +788,7 @@ static void * __init efi_map_regions(int
 		efi_map_region(md);
 		get_systab_virt_addr(md);
 
-		if (left < memmap.desc_size) {
+		if (left < desc_size) {
 			new_memmap = realloc_pages(new_memmap, *pg_shift);
 			if (!new_memmap)
 				return NULL;
@@ -801,10 +797,9 @@ static void * __init efi_map_regions(int
 			(*pg_shift)++;
 		}
 
-		memcpy(new_memmap + (*count * memmap.desc_size), md,
-		       memmap.desc_size);
+		memcpy(new_memmap + (*count * desc_size), md, desc_size);
 
-		left -= memmap.desc_size;
+		left -= desc_size;
 		(*count)++;
 	}
 
@@ -816,7 +811,6 @@ static void __init kexec_enter_virtual_m
 #ifdef CONFIG_KEXEC_CORE
 	efi_memory_desc_t *md;
 	unsigned int num_pages;
-	void *p;
 
 	efi.systab = NULL;
 
@@ -840,8 +834,7 @@ static void __init kexec_enter_virtual_m
 	* Map efi regions which were passed via setup_data. The virt_addr is a
 	* fixed addr which was used in first kernel of a kexec boot.
 	*/
-	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
-		md = p;
+	for_each_efi_memory_desc(md) {
 		efi_map_region_fixed(md); /* FIXME: add error handling */
 		get_systab_virt_addr(md);
 	}
@@ -850,10 +843,10 @@ static void __init kexec_enter_virtual_m
 
 	BUG_ON(!efi.systab);
 
-	num_pages = ALIGN(memmap.nr_map * memmap.desc_size, PAGE_SIZE);
+	num_pages = ALIGN(efi.memmap.nr_map * efi.memmap.desc_size, PAGE_SIZE);
 	num_pages >>= PAGE_SHIFT;
 
-	if (efi_setup_page_tables(memmap.phys_map, num_pages)) {
+	if (efi_setup_page_tables(efi.memmap.phys_map, num_pages)) {
 		clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
 		return;
 	}
@@ -937,16 +930,16 @@ static void __init __efi_enter_virtual_m
 
 	if (efi_is_native()) {
 		status = phys_efi_set_virtual_address_map(
-				memmap.desc_size * count,
-				memmap.desc_size,
-				memmap.desc_version,
+				efi.memmap.desc_size * count,
+				efi.memmap.desc_size,
+				efi.memmap.desc_version,
 				(efi_memory_desc_t *)__pa(new_memmap));
 	} else {
 		status = efi_thunk_set_virtual_address_map(
 				efi_phys.set_virtual_address_map,
-				memmap.desc_size * count,
-				memmap.desc_size,
-				memmap.desc_version,
+				efi.memmap.desc_size * count,
+				efi.memmap.desc_size,
+				efi.memmap.desc_version,
 				(efi_memory_desc_t *)__pa(new_memmap));
 	}
 
@@ -1011,13 +1004,11 @@ void __init efi_enter_virtual_mode(void)
 u32 efi_mem_type(unsigned long phys_addr)
 {
 	efi_memory_desc_t *md;
-	void *p;
 
 	if (!efi_enabled(EFI_MEMMAP))
 		return 0;
 
-	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
-		md = p;
+	for_each_efi_memory_desc(md) {
 		if ((md->phys_addr <= phys_addr) &&
 		    (phys_addr < (md->phys_addr +
 				  (md->num_pages << EFI_PAGE_SHIFT))))
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/platform/efi/efi_stub_64.S linux-libre-4.7-gnu/arch/x86/platform/efi/efi_stub_64.S
--- linux-libre-4.6-gnu/arch/x86/platform/efi/efi_stub_64.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/platform/efi/efi_stub_64.S	2016-07-24 15:23:50.000000000 -0400
@@ -11,7 +11,6 @@
 #include <asm/msr.h>
 #include <asm/processor-flags.h>
 #include <asm/page_types.h>
-#include <asm/frame.h>
 
 #define SAVE_XMM			\
 	mov %rsp, %rax;			\
@@ -40,10 +39,10 @@
 	mov (%rsp), %rsp
 
 ENTRY(efi_call)
-	FRAME_BEGIN
+	pushq %rbp
+	movq %rsp, %rbp
 	SAVE_XMM
-	mov (%rsp), %rax
-	mov 8(%rax), %rax
+	mov 16(%rbp), %rax
 	subq $48, %rsp
 	mov %r9, 32(%rsp)
 	mov %rax, 40(%rsp)
@@ -53,6 +52,6 @@ ENTRY(efi_call)
 	call *%rdi
 	addq $48, %rsp
 	RESTORE_XMM
-	FRAME_END
+	popq %rbp
 	ret
 ENDPROC(efi_call)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/platform/efi/quirks.c linux-libre-4.7-gnu/arch/x86/platform/efi/quirks.c
--- linux-libre-4.6-gnu/arch/x86/platform/efi/quirks.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/platform/efi/quirks.c	2016-07-24 15:23:50.000000000 -0400
@@ -195,10 +195,9 @@ static bool can_free_region(u64 start, u
 */
 void __init efi_reserve_boot_services(void)
 {
-	void *p;
+	efi_memory_desc_t *md;
 
-	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
-		efi_memory_desc_t *md = p;
+	for_each_efi_memory_desc(md) {
 		u64 start = md->phys_addr;
 		u64 size = md->num_pages << EFI_PAGE_SHIFT;
 		bool already_reserved;
@@ -250,10 +249,9 @@ void __init efi_reserve_boot_services(vo
 
 void __init efi_free_boot_services(void)
 {
-	void *p;
+	efi_memory_desc_t *md;
 
-	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
-		efi_memory_desc_t *md = p;
+	for_each_efi_memory_desc(md) {
 		unsigned long long start = md->phys_addr;
 		unsigned long long size = md->num_pages << EFI_PAGE_SHIFT;
 
@@ -373,5 +371,5 @@ bool efi_reboot_required(void)
 
 bool efi_poweroff_required(void)
 {
-	return !!acpi_gbl_reduced_hardware;
+	return acpi_gbl_reduced_hardware || acpi_no_s5;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/platform/uv/bios_uv.c linux-libre-4.7-gnu/arch/x86/platform/uv/bios_uv.c
--- linux-libre-4.6-gnu/arch/x86/platform/uv/bios_uv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/platform/uv/bios_uv.c	2016-07-24 15:23:50.000000000 -0400
@@ -21,19 +21,20 @@
 
 #include <linux/efi.h>
 #include <linux/export.h>
+#include <linux/slab.h>
 #include <asm/efi.h>
 #include <linux/io.h>
 #include <asm/uv/bios.h>
 #include <asm/uv/uv_hub.h>
 
-static struct uv_systab uv_systab;
+struct uv_systab *uv_systab;
 
 s64 uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5)
 {
-	struct uv_systab *tab = &uv_systab;
+	struct uv_systab *tab = uv_systab;
 	s64 ret;
 
-	if (!tab->function)
+	if (!tab || !tab->function)
 		/*
 		 * BIOS does not support UV systab
 		 */
@@ -183,34 +184,31 @@ int uv_bios_set_legacy_vga_target(bool d
 }
 EXPORT_SYMBOL_GPL(uv_bios_set_legacy_vga_target);
 
-
 #ifdef CONFIG_EFI
 void uv_bios_init(void)
 {
-	struct uv_systab *tab;
-
-	if ((efi.uv_systab == EFI_INVALID_TABLE_ADDR) ||
-	    (efi.uv_systab == (unsigned long)NULL)) {
-		printk(KERN_CRIT "No EFI UV System Table.\n");
-		uv_systab.function = (unsigned long)NULL;
+	uv_systab = NULL;
+	if ((efi.uv_systab == EFI_INVALID_TABLE_ADDR) || !efi.uv_systab) {
+		pr_crit("UV: UVsystab: missing\n");
 		return;
 	}
 
-	tab = (struct uv_systab *)ioremap(efi.uv_systab,
-					sizeof(struct uv_systab));
-	if (strncmp(tab->signature, "UVST", 4) != 0)
-		printk(KERN_ERR "bad signature in UV system table!");
-
-	/*
-	 * Copy table to permanent spot for later use.
-	 */
-	memcpy(&uv_systab, tab, sizeof(struct uv_systab));
-	iounmap(tab);
+	uv_systab = ioremap(efi.uv_systab, sizeof(struct uv_systab));
+	if (!uv_systab || strncmp(uv_systab->signature, UV_SYSTAB_SIG, 4)) {
+		pr_err("UV: UVsystab: bad signature!\n");
+		iounmap(uv_systab);
+		return;
+	}
 
-	printk(KERN_INFO "EFI UV System Table Revision %d\n",
-					uv_systab.revision);
+	if (uv_systab->revision >= UV_SYSTAB_VERSION_UV4) {
+		iounmap(uv_systab);
+		uv_systab = ioremap(efi.uv_systab, uv_systab->size);
+		if (!uv_systab) {
+			pr_err("UV: UVsystab: ioremap(%d) failed!\n",
+				uv_systab->size);
+			return;
+		}
+	}
+	pr_info("UV: UVsystab: Revision:%x\n", uv_systab->revision);
 }
-#else	/* !CONFIG_EFI */
-
-void uv_bios_init(void) { }
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/platform/uv/tlb_uv.c linux-libre-4.7-gnu/arch/x86/platform/uv/tlb_uv.c
--- linux-libre-4.6-gnu/arch/x86/platform/uv/tlb_uv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/platform/uv/tlb_uv.c	2016-07-24 15:23:50.000000000 -0400
@@ -37,7 +37,7 @@ static int timeout_base_ns[] = {
 };
 
 static int timeout_us;
-static int nobau;
+static bool nobau = true;
 static int nobau_perm;
 static cycles_t congested_cycles;
 
@@ -106,13 +106,28 @@ static char *stat_description[] = {
 	"enable:   number times use of the BAU was re-enabled"
 };
 
-static int __init
-setup_nobau(char *arg)
+static int __init setup_bau(char *arg)
 {
-	nobau = 1;
+	int result;
+
+	if (!arg)
+		return -EINVAL;
+
+	result = strtobool(arg, &nobau);
+	if (result)
+		return result;
+
+	/* we need to flip the logic here, so that bau=y sets nobau to false */
+	nobau = !nobau;
+
+	if (!nobau)
+		pr_info("UV BAU Enabled\n");
+	else
+		pr_info("UV BAU Disabled\n");
+
 	return 0;
 }
-early_param("nobau", setup_nobau);
+early_param("bau", setup_bau);
 
 /* base pnode in this partition */
 static int uv_base_pnode __read_mostly;
@@ -131,10 +146,10 @@ set_bau_on(void)
 		pr_info("BAU not initialized; cannot be turned on\n");
 		return;
 	}
-	nobau = 0;
+	nobau = false;
 	for_each_present_cpu(cpu) {
 		bcp = &per_cpu(bau_control, cpu);
-		bcp->nobau = 0;
+		bcp->nobau = false;
 	}
 	pr_info("BAU turned on\n");
 	return;
@@ -146,10 +161,10 @@ set_bau_off(void)
 	int cpu;
 	struct bau_control *bcp;
 
-	nobau = 1;
+	nobau = true;
 	for_each_present_cpu(cpu) {
 		bcp = &per_cpu(bau_control, cpu);
-		bcp->nobau = 1;
+		bcp->nobau = true;
 	}
 	pr_info("BAU turned off\n");
 	return;
@@ -1886,7 +1901,7 @@ static void __init init_per_cpu_tunables
 		bcp = &per_cpu(bau_control, cpu);
 		bcp->baudisabled		= 0;
 		if (nobau)
-			bcp->nobau		= 1;
+			bcp->nobau		= true;
 		bcp->statp			= &per_cpu(ptcstats, cpu);
 		/* time interval to catch a hardware stay-busy bug */
 		bcp->timeout_interval		= usec_2_cycles(2*timeout_us);
@@ -2025,7 +2040,8 @@ static int scan_sock(struct socket_desc
 			return 1;
 		}
 		bcp->uvhub_master = *hmasterp;
-		bcp->uvhub_cpu = uv_cpu_hub_info(cpu)->blade_processor_id;
+		bcp->uvhub_cpu = uv_cpu_blade_processor_id(cpu);
+
 		if (bcp->uvhub_cpu >= MAX_CPUS_PER_UVHUB) {
 			printk(KERN_EMERG "%d cpus per uvhub invalid\n",
 				bcp->uvhub_cpu);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/platform/uv/uv_sysfs.c linux-libre-4.7-gnu/arch/x86/platform/uv/uv_sysfs.c
--- linux-libre-4.6-gnu/arch/x86/platform/uv/uv_sysfs.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/platform/uv/uv_sysfs.c	2016-07-24 15:23:50.000000000 -0400
@@ -34,7 +34,7 @@ static ssize_t partition_id_show(struct
 static ssize_t coherence_id_show(struct kobject *kobj,
 			struct kobj_attribute *attr, char *buf)
 {
-	return snprintf(buf, PAGE_SIZE, "%ld\n", partition_coherence_id());
+	return snprintf(buf, PAGE_SIZE, "%ld\n", uv_partition_coherence_id());
 }
 
 static struct kobj_attribute partition_id_attr =
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/platform/uv/uv_time.c linux-libre-4.7-gnu/arch/x86/platform/uv/uv_time.c
--- linux-libre-4.6-gnu/arch/x86/platform/uv/uv_time.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/platform/uv/uv_time.c	2016-07-24 15:23:50.000000000 -0400
@@ -165,7 +165,7 @@ static __init int uv_rtc_allocate_timers
 	for_each_present_cpu(cpu) {
 		int nid = cpu_to_node(cpu);
 		int bid = uv_cpu_to_blade_id(cpu);
-		int bcpu = uv_cpu_hub_info(cpu)->blade_processor_id;
+		int bcpu = uv_cpu_blade_processor_id(cpu);
 		struct uv_rtc_timer_head *head = blade_info[bid];
 
 		if (!head) {
@@ -226,7 +226,7 @@ static int uv_rtc_set_timer(int cpu, u64
 	int pnode = uv_cpu_to_pnode(cpu);
 	int bid = uv_cpu_to_blade_id(cpu);
 	struct uv_rtc_timer_head *head = blade_info[bid];
-	int bcpu = uv_cpu_hub_info(cpu)->blade_processor_id;
+	int bcpu = uv_cpu_blade_processor_id(cpu);
 	u64 *t = &head->cpu[bcpu].expires;
 	unsigned long flags;
 	int next_cpu;
@@ -262,7 +262,7 @@ static int uv_rtc_unset_timer(int cpu, i
 	int pnode = uv_cpu_to_pnode(cpu);
 	int bid = uv_cpu_to_blade_id(cpu);
 	struct uv_rtc_timer_head *head = blade_info[bid];
-	int bcpu = uv_cpu_hub_info(cpu)->blade_processor_id;
+	int bcpu = uv_cpu_blade_processor_id(cpu);
 	u64 *t = &head->cpu[bcpu].expires;
 	unsigned long flags;
 	int rc = 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/power/hibernate_32.c linux-libre-4.7-gnu/arch/x86/power/hibernate_32.c
--- linux-libre-4.6-gnu/arch/x86/power/hibernate_32.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/power/hibernate_32.c	2016-07-24 15:23:50.000000000 -0400
@@ -106,7 +106,7 @@ static int resume_physical_mapping_init(
 			 * normal page tables.
 			 * NOTE: We can mark everything as executable here
 			 */
-			if (cpu_has_pse) {
+			if (boot_cpu_has(X86_FEATURE_PSE)) {
 				set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE_EXEC));
 				pfn += PTRS_PER_PTE;
 			} else {
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/power/hibernate_64.c linux-libre-4.7-gnu/arch/x86/power/hibernate_64.c
--- linux-libre-4.6-gnu/arch/x86/power/hibernate_64.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/power/hibernate_64.c	2016-07-24 15:23:50.000000000 -0400
@@ -19,6 +19,7 @@
 #include <asm/mtrr.h>
 #include <asm/sections.h>
 #include <asm/suspend.h>
+#include <asm/tlbflush.h>
 
 /* Defined in hibernate_asm_64.S */
 extern asmlinkage __visible int restore_image(void);
@@ -28,6 +29,7 @@ extern asmlinkage __visible int restore_
  * kernel's text (this value is passed in the image header).
  */
 unsigned long restore_jump_address __visible;
+unsigned long jump_address_phys;
 
 /*
  * Value of the cr3 register from before the hibernation (this value is passed
@@ -37,7 +39,43 @@ unsigned long restore_cr3 __visible;
 
 pgd_t *temp_level4_pgt __visible;
 
-void *relocated_restore_code __visible;
+unsigned long relocated_restore_code __visible;
+
+static int set_up_temporary_text_mapping(void)
+{
+	pmd_t *pmd;
+	pud_t *pud;
+
+	/*
+	 * The new mapping only has to cover the page containing the image
+	 * kernel's entry point (jump_address_phys), because the switch over to
+	 * it is carried out by relocated code running from a page allocated
+	 * specifically for this purpose and covered by the identity mapping, so
+	 * the temporary kernel text mapping is only needed for the final jump.
+	 * Moreover, in that mapping the virtual address of the image kernel's
+	 * entry point must be the same as its virtual address in the image
+	 * kernel (restore_jump_address), so the image kernel's
+	 * restore_registers() code doesn't find itself in a different area of
+	 * the virtual address space after switching over to the original page
+	 * tables used by the image kernel.
+	 */
+	pud = (pud_t *)get_safe_page(GFP_ATOMIC);
+	if (!pud)
+		return -ENOMEM;
+
+	pmd = (pmd_t *)get_safe_page(GFP_ATOMIC);
+	if (!pmd)
+		return -ENOMEM;
+
+	set_pmd(pmd + pmd_index(restore_jump_address),
+		__pmd((jump_address_phys & PMD_MASK) | __PAGE_KERNEL_LARGE_EXEC));
+	set_pud(pud + pud_index(restore_jump_address),
+		__pud(__pa(pmd) | _KERNPG_TABLE));
+	set_pgd(temp_level4_pgt + pgd_index(restore_jump_address),
+		__pgd(__pa(pud) | _KERNPG_TABLE));
+
+	return 0;
+}
 
 static void *alloc_pgt_page(void *context)
 {
@@ -59,9 +97,10 @@ static int set_up_temporary_mappings(voi
 	if (!temp_level4_pgt)
 		return -ENOMEM;
 
-	/* It is safe to reuse the original kernel mapping */
-	set_pgd(temp_level4_pgt + pgd_index(__START_KERNEL_map),
-		init_level4_pgt[pgd_index(__START_KERNEL_map)]);
+	/* Prepare a temporary mapping for the kernel text */
+	result = set_up_temporary_text_mapping();
+	if (result)
+		return result;
 
 	/* Set up the direct mapping from scratch */
 	for (i = 0; i < nr_pfn_mapped; i++) {
@@ -78,19 +117,50 @@ static int set_up_temporary_mappings(voi
 	return 0;
 }
 
+static int relocate_restore_code(void)
+{
+	pgd_t *pgd;
+	pud_t *pud;
+
+	relocated_restore_code = get_safe_page(GFP_ATOMIC);
+	if (!relocated_restore_code)
+		return -ENOMEM;
+
+	memcpy((void *)relocated_restore_code, &core_restore_code, PAGE_SIZE);
+
+	/* Make the page containing the relocated code executable */
+	pgd = (pgd_t *)__va(read_cr3()) + pgd_index(relocated_restore_code);
+	pud = pud_offset(pgd, relocated_restore_code);
+	if (pud_large(*pud)) {
+		set_pud(pud, __pud(pud_val(*pud) & ~_PAGE_NX));
+	} else {
+		pmd_t *pmd = pmd_offset(pud, relocated_restore_code);
+
+		if (pmd_large(*pmd)) {
+			set_pmd(pmd, __pmd(pmd_val(*pmd) & ~_PAGE_NX));
+		} else {
+			pte_t *pte = pte_offset_kernel(pmd, relocated_restore_code);
+
+			set_pte(pte, __pte(pte_val(*pte) & ~_PAGE_NX));
+		}
+	}
+	__flush_tlb_all();
+
+	return 0;
+}
+
 int swsusp_arch_resume(void)
 {
 	int error;
 
 	/* We have got enough memory and from now on we cannot recover */
-	if ((error = set_up_temporary_mappings()))
+	error = set_up_temporary_mappings();
+	if (error)
 		return error;
 
-	relocated_restore_code = (void *)get_safe_page(GFP_ATOMIC);
-	if (!relocated_restore_code)
-		return -ENOMEM;
-	memcpy(relocated_restore_code, &core_restore_code,
-	       &restore_registers - &core_restore_code);
+	error = relocate_restore_code();
+	if (error)
+		return error;
 
 	restore_image();
 	return 0;
@@ -109,11 +179,12 @@ int pfn_is_nosave(unsigned long pfn)
 
 struct restore_data_record {
 	unsigned long jump_address;
+	unsigned long jump_address_phys;
 	unsigned long cr3;
 	unsigned long magic;
 };
 
-#define RESTORE_MAGIC	0x0123456789ABCDEFUL
+#define RESTORE_MAGIC	0x123456789ABCDEF0UL
 
 /**
  *	arch_hibernation_header_save - populate the architecture specific part
@@ -126,7 +197,8 @@ int arch_hibernation_header_save(void *a
 
 	if (max_size < sizeof(struct restore_data_record))
 		return -EOVERFLOW;
-	rdr->jump_address = restore_jump_address;
+	rdr->jump_address = (unsigned long)&restore_registers;
+	rdr->jump_address_phys = __pa_symbol(&restore_registers);
 	rdr->cr3 = restore_cr3;
 	rdr->magic = RESTORE_MAGIC;
 	return 0;
@@ -142,6 +214,7 @@ int arch_hibernation_header_restore(void
 	struct restore_data_record *rdr = addr;
 
 	restore_jump_address = rdr->jump_address;
+	jump_address_phys = rdr->jump_address_phys;
 	restore_cr3 = rdr->cr3;
 	return (rdr->magic == RESTORE_MAGIC) ? 0 : -EINVAL;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/power/hibernate_asm_64.S linux-libre-4.7-gnu/arch/x86/power/hibernate_asm_64.S
--- linux-libre-4.6-gnu/arch/x86/power/hibernate_asm_64.S	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/power/hibernate_asm_64.S	2016-07-24 15:23:50.000000000 -0400
@@ -44,9 +44,6 @@ ENTRY(swsusp_arch_suspend)
 	pushfq
 	popq	pt_regs_flags(%rax)
 
-	/* save the address of restore_registers */
-	movq	$restore_registers, %rax
-	movq	%rax, restore_jump_address(%rip)
 	/* save cr3 */
 	movq	%cr3, %rax
 	movq	%rax, restore_cr3(%rip)
@@ -57,31 +54,34 @@ ENTRY(swsusp_arch_suspend)
 ENDPROC(swsusp_arch_suspend)
 
 ENTRY(restore_image)
-	/* switch to temporary page tables */
-	movq	$__PAGE_OFFSET, %rdx
-	movq	temp_level4_pgt(%rip), %rax
-	subq	%rdx, %rax
-	movq	%rax, %cr3
-	/* Flush TLB */
-	movq	mmu_cr4_features(%rip), %rax
-	movq	%rax, %rdx
-	andq	$~(X86_CR4_PGE), %rdx
-	movq	%rdx, %cr4;  # turn off PGE
-	movq	%cr3, %rcx;  # flush TLB
-	movq	%rcx, %cr3;
-	movq	%rax, %cr4;  # turn PGE back on
-
 	/* prepare to jump to the image kernel */
-	movq	restore_jump_address(%rip), %rax
-	movq	restore_cr3(%rip), %rbx
+	movq	restore_jump_address(%rip), %r8
+	movq	restore_cr3(%rip), %r9
+
+	/* prepare to switch to temporary page tables */
+	movq	temp_level4_pgt(%rip), %rax
+	movq	mmu_cr4_features(%rip), %rbx
 
 	/* prepare to copy image data to their original locations */
 	movq	restore_pblist(%rip), %rdx
+
+	/* jump to relocated restore code */
 	movq	relocated_restore_code(%rip), %rcx
 	jmpq	*%rcx
 
 	/* code below has been relocated to a safe page */
 ENTRY(core_restore_code)
+	/* switch to temporary page tables */
+	movq	$__PAGE_OFFSET, %rcx
+	subq	%rcx, %rax
+	movq	%rax, %cr3
+	/* flush TLB */
+	movq	%rbx, %rcx
+	andq	$~(X86_CR4_PGE), %rcx
+	movq	%rcx, %cr4;  # turn off PGE
+	movq	%cr3, %rcx;  # flush TLB
+	movq	%rcx, %cr3;
+	movq	%rbx, %cr4;  # turn PGE back on
 .Lloop:
 	testq	%rdx, %rdx
 	jz	.Ldone
@@ -96,24 +96,17 @@ ENTRY(core_restore_code)
 	/* progress to the next pbe */
 	movq	pbe_next(%rdx), %rdx
 	jmp	.Lloop
+
 .Ldone:
 	/* jump to the restore_registers address from the image header */
-	jmpq	*%rax
-	/*
-	 * NOTE: This assumes that the boot kernel's text mapping covers the
-	 * image kernel's page containing restore_registers and the address of
-	 * this page is the same as in the image kernel's text mapping (it
-	 * should always be true, because the text mapping is linear, starting
-	 * from 0, and is supposed to cover the entire kernel text for every
-	 * kernel).
-	 *
-	 * code below belongs to the image kernel
-	 */
+	jmpq	*%r8
 
+	 /* code below belongs to the image kernel */
+	.align PAGE_SIZE
 ENTRY(restore_registers)
 	FRAME_BEGIN
 	/* go back to the original page tables */
-	movq    %rbx, %cr3
+	movq    %r9, %cr3
 
 	/* Flush TLB, including "global" things (vmalloc) */
 	movq	mmu_cr4_features(%rip), %rax
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/purgatory/Makefile linux-libre-4.7-gnu/arch/x86/purgatory/Makefile
--- linux-libre-4.6-gnu/arch/x86/purgatory/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/purgatory/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -26,7 +26,5 @@ quiet_cmd_bin2c = BIN2C   $@
 
 $(obj)/kexec-purgatory.c: $(obj)/purgatory.ro FORCE
 	$(call if_changed,bin2c)
-	@:
-
 
 obj-$(CONFIG_KEXEC_FILE)	+= kexec-purgatory.o
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/ras/Kconfig linux-libre-4.7-gnu/arch/x86/ras/Kconfig
--- linux-libre-4.6-gnu/arch/x86/ras/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/ras/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -1,4 +1,4 @@
-config AMD_MCE_INJ
+config MCE_AMD_INJ
 	tristate "Simple MCE injection interface for AMD processors"
 	depends on RAS && EDAC_DECODE_MCE && DEBUG_FS && AMD_NB
 	default n
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/ras/Makefile linux-libre-4.7-gnu/arch/x86/ras/Makefile
--- linux-libre-4.6-gnu/arch/x86/ras/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/ras/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -1,2 +1,2 @@
-obj-$(CONFIG_AMD_MCE_INJ)		+= mce_amd_inj.o
+obj-$(CONFIG_MCE_AMD_INJ)		+= mce_amd_inj.o
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/ras/mce_amd_inj.c linux-libre-4.7-gnu/arch/x86/ras/mce_amd_inj.c
--- linux-libre-4.6-gnu/arch/x86/ras/mce_amd_inj.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/ras/mce_amd_inj.c	2016-07-24 15:23:50.000000000 -0400
@@ -290,14 +290,33 @@ static void do_inject(void)
 	wrmsr_on_cpu(cpu, MSR_IA32_MCG_STATUS,
 		     (u32)mcg_status, (u32)(mcg_status >> 32));
 
-	wrmsr_on_cpu(cpu, MSR_IA32_MCx_STATUS(b),
-		     (u32)i_mce.status, (u32)(i_mce.status >> 32));
+	if (boot_cpu_has(X86_FEATURE_SMCA)) {
+		if (inj_type == DFR_INT_INJ) {
+			wrmsr_on_cpu(cpu, MSR_AMD64_SMCA_MCx_DESTAT(b),
+				     (u32)i_mce.status, (u32)(i_mce.status >> 32));
 
-	wrmsr_on_cpu(cpu, MSR_IA32_MCx_ADDR(b),
-		     (u32)i_mce.addr, (u32)(i_mce.addr >> 32));
+			wrmsr_on_cpu(cpu, MSR_AMD64_SMCA_MCx_DEADDR(b),
+				     (u32)i_mce.addr, (u32)(i_mce.addr >> 32));
+		} else {
+			wrmsr_on_cpu(cpu, MSR_AMD64_SMCA_MCx_STATUS(b),
+				     (u32)i_mce.status, (u32)(i_mce.status >> 32));
 
-	wrmsr_on_cpu(cpu, MSR_IA32_MCx_MISC(b),
-		     (u32)i_mce.misc, (u32)(i_mce.misc >> 32));
+			wrmsr_on_cpu(cpu, MSR_AMD64_SMCA_MCx_ADDR(b),
+				     (u32)i_mce.addr, (u32)(i_mce.addr >> 32));
+		}
+
+		wrmsr_on_cpu(cpu, MSR_AMD64_SMCA_MCx_MISC(b),
+			     (u32)i_mce.misc, (u32)(i_mce.misc >> 32));
+	} else {
+		wrmsr_on_cpu(cpu, MSR_IA32_MCx_STATUS(b),
+			     (u32)i_mce.status, (u32)(i_mce.status >> 32));
+
+		wrmsr_on_cpu(cpu, MSR_IA32_MCx_ADDR(b),
+			     (u32)i_mce.addr, (u32)(i_mce.addr >> 32));
+
+		wrmsr_on_cpu(cpu, MSR_IA32_MCx_MISC(b),
+			     (u32)i_mce.misc, (u32)(i_mce.misc >> 32));
+	}
 
 	toggle_hw_mce_inject(cpu, false);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/realmode/rm/Makefile linux-libre-4.7-gnu/arch/x86/realmode/rm/Makefile
--- linux-libre-4.6-gnu/arch/x86/realmode/rm/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/realmode/rm/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -59,7 +59,6 @@ OBJCOPYFLAGS_realmode.bin := -O binary
 targets += realmode.bin
 $(obj)/realmode.bin: $(obj)/realmode.elf $(obj)/realmode.relocs FORCE
 	$(call if_changed,objcopy)
-	@:
 
 quiet_cmd_relocs = RELOCS  $@
       cmd_relocs = arch/x86/tools/relocs --realmode $< > $@
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/tools/calc_run_size.sh linux-libre-4.7-gnu/arch/x86/tools/calc_run_size.sh
--- linux-libre-4.6-gnu/arch/x86/tools/calc_run_size.sh	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/tools/calc_run_size.sh	1969-12-31 19:00:00.000000000 -0500
@@ -1,42 +0,0 @@
-#!/bin/sh
-#
-# Calculate the amount of space needed to run the kernel, including room for
-# the .bss and .brk sections.
-#
-# Usage:
-# objdump -h a.out | sh calc_run_size.sh
-
-NUM='\([0-9a-fA-F]*[ \t]*\)'
-OUT=$(sed -n 's/^[ \t0-9]*.b[sr][sk][ \t]*'"$NUM$NUM$NUM$NUM"'.*/\1\4/p')
-if [ -z "$OUT" ] ; then
-	echo "Never found .bss or .brk file offset" >&2
-	exit 1
-fi
-
-OUT=$(echo ${OUT# })
-sizeA=$(printf "%d" 0x${OUT%% *})
-OUT=${OUT#* }
-offsetA=$(printf "%d" 0x${OUT%% *})
-OUT=${OUT#* }
-sizeB=$(printf "%d" 0x${OUT%% *})
-OUT=${OUT#* }
-offsetB=$(printf "%d" 0x${OUT%% *})
-
-run_size=$(( $offsetA + $sizeA + $sizeB ))
-
-# BFD linker shows the same file offset in ELF.
-if [ "$offsetA" -ne "$offsetB" ] ; then
-	# Gold linker shows them as consecutive.
-	endB=$(( $offsetB + $sizeB ))
-	if [ "$endB" != "$run_size" ] ; then
-		printf "sizeA: 0x%x\n" $sizeA >&2
-		printf "offsetA: 0x%x\n" $offsetA >&2
-		printf "sizeB: 0x%x\n" $sizeB >&2
-		printf "offsetB: 0x%x\n" $offsetB >&2
-		echo ".bss and .brk are non-contiguous" >&2
-		exit 1
-	fi
-fi
-
-printf "%d\n" $run_size
-exit 0
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/um/os-Linux/registers.c linux-libre-4.7-gnu/arch/x86/um/os-Linux/registers.c
--- linux-libre-4.6-gnu/arch/x86/um/os-Linux/registers.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/um/os-Linux/registers.c	2016-07-24 15:23:50.000000000 -0400
@@ -11,21 +11,56 @@
 #endif
 #include <longjmp.h>
 #include <sysdep/ptrace_user.h>
+#include <sys/uio.h>
+#include <asm/sigcontext.h>
+#include <linux/elf.h>
 
-int save_fp_registers(int pid, unsigned long *fp_regs)
+int have_xstate_support;
+
+int save_i387_registers(int pid, unsigned long *fp_regs)
 {
 	if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0)
 		return -errno;
 	return 0;
 }
 
-int restore_fp_registers(int pid, unsigned long *fp_regs)
+int save_fp_registers(int pid, unsigned long *fp_regs)
+{
+	struct iovec iov;
+
+	if (have_xstate_support) {
+		iov.iov_base = fp_regs;
+		iov.iov_len = sizeof(struct _xstate);
+		if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) < 0)
+			return -errno;
+		return 0;
+	} else {
+		return save_i387_registers(pid, fp_regs);
+	}
+}
+
+int restore_i387_registers(int pid, unsigned long *fp_regs)
 {
 	if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0)
 		return -errno;
 	return 0;
 }
 
+int restore_fp_registers(int pid, unsigned long *fp_regs)
+{
+	struct iovec iov;
+
+	if (have_xstate_support) {
+		iov.iov_base = fp_regs;
+		iov.iov_len = sizeof(struct _xstate);
+		if (ptrace(PTRACE_SETREGSET, pid, NT_X86_XSTATE, &iov) < 0)
+			return -errno;
+		return 0;
+	} else {
+		return restore_i387_registers(pid, fp_regs);
+	}
+}
+
 #ifdef __i386__
 int have_fpx_regs = 1;
 int save_fpx_registers(int pid, unsigned long *fp_regs)
@@ -85,6 +120,16 @@ int put_fp_registers(int pid, unsigned l
 	return restore_fp_registers(pid, regs);
 }
 
+void arch_init_registers(int pid)
+{
+	struct _xstate fp_regs;
+	struct iovec iov;
+
+	iov.iov_base = &fp_regs;
+	iov.iov_len = sizeof(struct _xstate);
+	if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) == 0)
+		have_xstate_support = 1;
+}
 #endif
 
 unsigned long get_thread_reg(int reg, jmp_buf *buf)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/um/ptrace_32.c linux-libre-4.7-gnu/arch/x86/um/ptrace_32.c
--- linux-libre-4.6-gnu/arch/x86/um/ptrace_32.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/um/ptrace_32.c	2016-07-24 15:23:50.000000000 -0400
@@ -194,7 +194,8 @@ static int get_fpregs(struct user_i387_s
 	int err, n, cpu = ((struct thread_info *) child->stack)->cpu;
 	struct user_i387_struct fpregs;
 
-	err = save_fp_registers(userspace_pid[cpu], (unsigned long *) &fpregs);
+	err = save_i387_registers(userspace_pid[cpu],
+				  (unsigned long *) &fpregs);
 	if (err)
 		return err;
 
@@ -214,7 +215,7 @@ static int set_fpregs(struct user_i387_s
 	if (n > 0)
 		return -EFAULT;
 
-	return restore_fp_registers(userspace_pid[cpu],
+	return restore_i387_registers(userspace_pid[cpu],
 				    (unsigned long *) &fpregs);
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/um/ptrace_64.c linux-libre-4.7-gnu/arch/x86/um/ptrace_64.c
--- linux-libre-4.6-gnu/arch/x86/um/ptrace_64.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/um/ptrace_64.c	2016-07-24 15:23:50.000000000 -0400
@@ -222,14 +222,14 @@ int is_syscall(unsigned long addr)
 static int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
 {
 	int err, n, cpu = ((struct thread_info *) child->stack)->cpu;
-	long fpregs[HOST_FP_SIZE];
+	struct user_i387_struct fpregs;
 
-	BUG_ON(sizeof(*buf) != sizeof(fpregs));
-	err = save_fp_registers(userspace_pid[cpu], fpregs);
+	err = save_i387_registers(userspace_pid[cpu],
+				  (unsigned long *) &fpregs);
 	if (err)
 		return err;
 
-	n = copy_to_user(buf, fpregs, sizeof(fpregs));
+	n = copy_to_user(buf, &fpregs, sizeof(fpregs));
 	if (n > 0)
 		return -EFAULT;
 
@@ -239,14 +239,14 @@ static int get_fpregs(struct user_i387_s
 static int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
 {
 	int n, cpu = ((struct thread_info *) child->stack)->cpu;
-	long fpregs[HOST_FP_SIZE];
+	struct user_i387_struct fpregs;
 
-	BUG_ON(sizeof(*buf) != sizeof(fpregs));
-	n = copy_from_user(fpregs, buf, sizeof(fpregs));
+	n = copy_from_user(&fpregs, buf, sizeof(fpregs));
 	if (n > 0)
 		return -EFAULT;
 
-	return restore_fp_registers(userspace_pid[cpu], fpregs);
+	return restore_i387_registers(userspace_pid[cpu],
+				      (unsigned long *) &fpregs);
 }
 
 long subarch_ptrace(struct task_struct *child, long request,
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/um/shared/sysdep/ptrace_64.h linux-libre-4.7-gnu/arch/x86/um/shared/sysdep/ptrace_64.h
--- linux-libre-4.6-gnu/arch/x86/um/shared/sysdep/ptrace_64.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/um/shared/sysdep/ptrace_64.h	2016-07-24 15:23:50.000000000 -0400
@@ -57,8 +57,6 @@
 #define UPT_SYSCALL_ARG5(r) UPT_R8(r)
 #define UPT_SYSCALL_ARG6(r) UPT_R9(r)
 
-static inline void arch_init_registers(int pid)
-{
-}
+extern void arch_init_registers(int pid);
 
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/um/signal.c linux-libre-4.7-gnu/arch/x86/um/signal.c
--- linux-libre-4.6-gnu/arch/x86/um/signal.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/um/signal.c	2016-07-24 15:23:50.000000000 -0400
@@ -225,26 +225,16 @@ static int copy_sc_from_user(struct pt_r
 	} else
 #endif
 	{
-		struct user_i387_struct fp;
-
-		err = copy_from_user(&fp, (void *)sc.fpstate,
-				     sizeof(struct user_i387_struct));
+		err = copy_from_user(regs->regs.fp, (void *)sc.fpstate,
+				     sizeof(struct _xstate));
 		if (err)
 			return 1;
-
-		err = restore_fp_registers(pid, (unsigned long *) &fp);
-		if (err < 0) {
-			printk(KERN_ERR "copy_sc_from_user - "
-			       "restore_fp_registers failed, errno = %d\n",
-			       -err);
-			return 1;
-		}
 	}
 	return 0;
 }
 
 static int copy_sc_to_user(struct sigcontext __user *to,
-			   struct _fpstate __user *to_fp, struct pt_regs *regs,
+			   struct _xstate __user *to_fp, struct pt_regs *regs,
 			   unsigned long mask)
 {
 	struct sigcontext sc;
@@ -310,25 +300,22 @@ static int copy_sc_to_user(struct sigcon
 			return 1;
 		}
 
-		err = convert_fxsr_to_user(to_fp, &fpx);
+		err = convert_fxsr_to_user(&to_fp->fpstate, &fpx);
 		if (err)
 			return 1;
 
-		err |= __put_user(fpx.swd, &to_fp->status);
-		err |= __put_user(X86_FXSR_MAGIC, &to_fp->magic);
+		err |= __put_user(fpx.swd, &to_fp->fpstate.status);
+		err |= __put_user(X86_FXSR_MAGIC, &to_fp->fpstate.magic);
 		if (err)
 			return 1;
 
-		if (copy_to_user(&to_fp->_fxsr_env[0], &fpx,
+		if (copy_to_user(&to_fp->fpstate._fxsr_env[0], &fpx,
 				 sizeof(struct user_fxsr_struct)))
 			return 1;
 	} else
 #endif
 	{
-		struct user_i387_struct fp;
-
-		err = save_fp_registers(pid, (unsigned long *) &fp);
-		if (copy_to_user(to_fp, &fp, sizeof(struct user_i387_struct)))
+		if (copy_to_user(to_fp, regs->regs.fp, sizeof(struct _xstate)))
 			return 1;
 	}
 
@@ -337,7 +324,7 @@ static int copy_sc_to_user(struct sigcon
 
 #ifdef CONFIG_X86_32
 static int copy_ucontext_to_user(struct ucontext __user *uc,
-				 struct _fpstate __user *fp, sigset_t *set,
+				 struct _xstate __user *fp, sigset_t *set,
 				 unsigned long sp)
 {
 	int err = 0;
@@ -353,7 +340,7 @@ struct sigframe
 	char __user *pretcode;
 	int sig;
 	struct sigcontext sc;
-	struct _fpstate fpstate;
+	struct _xstate fpstate;
 	unsigned long extramask[_NSIG_WORDS-1];
 	char retcode[8];
 };
@@ -366,7 +353,7 @@ struct rt_sigframe
 	void __user *puc;
 	struct siginfo info;
 	struct ucontext uc;
-	struct _fpstate fpstate;
+	struct _xstate fpstate;
 	char retcode[8];
 };
 
@@ -495,7 +482,7 @@ struct rt_sigframe
 	char __user *pretcode;
 	struct ucontext uc;
 	struct siginfo info;
-	struct _fpstate fpstate;
+	struct _xstate fpstate;
 };
 
 int setup_signal_stack_si(unsigned long stack_top, struct ksignal *ksig,
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/um/user-offsets.c linux-libre-4.7-gnu/arch/x86/um/user-offsets.c
--- linux-libre-4.6-gnu/arch/x86/um/user-offsets.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/um/user-offsets.c	2016-07-24 15:23:50.000000000 -0400
@@ -50,7 +50,7 @@ void foo(void)
 	DEFINE(HOST_GS, GS);
 	DEFINE(HOST_ORIG_AX, ORIG_EAX);
 #else
-	DEFINE(HOST_FP_SIZE, sizeof(struct _fpstate) / sizeof(unsigned long));
+	DEFINE(HOST_FP_SIZE, sizeof(struct _xstate) / sizeof(unsigned long));
 	DEFINE_LONGS(HOST_BX, RBX);
 	DEFINE_LONGS(HOST_CX, RCX);
 	DEFINE_LONGS(HOST_DI, RDI);
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/um/vdso/vma.c linux-libre-4.7-gnu/arch/x86/um/vdso/vma.c
--- linux-libre-4.6-gnu/arch/x86/um/vdso/vma.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/um/vdso/vma.c	2016-07-24 15:23:50.000000000 -0400
@@ -61,7 +61,8 @@ int arch_setup_additional_pages(struct l
 	if (!vdso_enabled)
 		return 0;
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
 
 	err = install_special_mapping(mm, um_vdso_addr, PAGE_SIZE,
 		VM_READ|VM_EXEC|
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/xen/enlighten.c linux-libre-4.7-gnu/arch/x86/xen/enlighten.c
--- linux-libre-4.6-gnu/arch/x86/xen/enlighten.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/xen/enlighten.c	2016-07-24 15:23:50.000000000 -0400
@@ -75,7 +75,6 @@
 #include <asm/mach_traps.h>
 #include <asm/mwait.h>
 #include <asm/pci_x86.h>
-#include <asm/pat.h>
 #include <asm/cpu.h>
 
 #ifdef CONFIG_ACPI
@@ -1093,6 +1092,26 @@ static int xen_write_msr_safe(unsigned i
 	return ret;
 }
 
+static u64 xen_read_msr(unsigned int msr)
+{
+	/*
+	 * This will silently swallow a #GP from RDMSR.  It may be worth
+	 * changing that.
+	 */
+	int err;
+
+	return xen_read_msr_safe(msr, &err);
+}
+
+static void xen_write_msr(unsigned int msr, unsigned low, unsigned high)
+{
+	/*
+	 * This will silently swallow a #GP from WRMSR.  It may be worth
+	 * changing that.
+	 */
+	xen_write_msr_safe(msr, low, high);
+}
+
 void xen_setup_shared_info(void)
 {
 	if (!xen_feature(XENFEAT_auto_translated_physmap)) {
@@ -1187,13 +1206,11 @@ static unsigned xen_patch(u8 type, u16 c
 }
 
 static const struct pv_info xen_info __initconst = {
-	.paravirt_enabled = 1,
 	.shared_kernel_pmd = 0,
 
 #ifdef CONFIG_X86_64
 	.extra_user_64bit_cs = FLAT_USER_CS64,
 #endif
-	.features = 0,
 	.name = "Xen",
 };
 
@@ -1223,8 +1240,11 @@ static const struct pv_cpu_ops xen_cpu_o
 
 	.wbinvd = native_wbinvd,
 
-	.read_msr = xen_read_msr_safe,
-	.write_msr = xen_write_msr_safe,
+	.read_msr = xen_read_msr,
+	.write_msr = xen_write_msr,
+
+	.read_msr_safe = xen_read_msr_safe,
+	.write_msr_safe = xen_write_msr_safe,
 
 	.read_pmc = xen_read_pmc,
 
@@ -1469,10 +1489,10 @@ static void xen_pvh_set_cr_flags(int cpu
 	 * For BSP, PSE PGE are set in probe_page_size_mask(), for APs
 	 * set them here. For all, OSFXSR OSXMMEXCPT are set in fpu__init_cpu().
 	*/
-	if (cpu_has_pse)
+	if (boot_cpu_has(X86_FEATURE_PSE))
 		cr4_set_bits_and_update_boot(X86_CR4_PSE);
 
-	if (cpu_has_pge)
+	if (boot_cpu_has(X86_FEATURE_PGE))
 		cr4_set_bits_and_update_boot(X86_CR4_PGE);
 }
 
@@ -1506,12 +1526,16 @@ static void __init xen_pvh_early_guest_i
 }
 #endif    /* CONFIG_XEN_PVH */
 
+static void __init xen_dom0_set_legacy_features(void)
+{
+	x86_platform.legacy.rtc = 1;
+}
+
 /* First C function to be called on Xen boot */
 asmlinkage __visible void __init xen_start_kernel(void)
 {
 	struct physdev_set_iopl set_iopl;
 	unsigned long initrd_start = 0;
-	u64 pat;
 	int rc;
 
 	if (!xen_start_info)
@@ -1527,8 +1551,6 @@ asmlinkage __visible void __init xen_sta
 
 	/* Install Xen paravirt ops */
 	pv_info = xen_info;
-	if (xen_initial_domain())
-		pv_info.features |= PV_SUPPORTED_RTC;
 	pv_init_ops = xen_init_ops;
 	if (!xen_pvh_domain()) {
 		pv_cpu_ops = xen_cpu_ops;
@@ -1618,13 +1640,6 @@ asmlinkage __visible void __init xen_sta
 				   xen_start_info->nr_pages);
 	xen_reserve_special_pages();
 
-	/*
-	 * Modify the cache mode translation tables to match Xen's PAT
-	 * configuration.
-	 */
-	rdmsrl(MSR_IA32_CR_PAT, pat);
-	pat_init_cache_modes(pat);
-
 	/* keep using Xen gdt for now; no urgent need to change it */
 
 #ifdef CONFIG_X86_32
@@ -1670,6 +1685,7 @@ asmlinkage __visible void __init xen_sta
 	boot_params.hdr.ramdisk_image = initrd_start;
 	boot_params.hdr.ramdisk_size = xen_start_info->mod_len;
 	boot_params.hdr.cmd_line_ptr = __pa(xen_start_info->cmd_line);
+	boot_params.hdr.hardware_subarch = X86_SUBARCH_XEN;
 
 	if (!xen_initial_domain()) {
 		add_preferred_console("xenboot", 0, NULL);
@@ -1687,6 +1703,8 @@ asmlinkage __visible void __init xen_sta
 			.u.firmware_info.type = XEN_FW_KBD_SHIFT_FLAGS,
 		};
 
+		x86_platform.set_legacy_features =
+				xen_dom0_set_legacy_features;
 		xen_init_vga(info, xen_start_info->console.dom0.info_size);
 		xen_start_info->console.domU.mfn = 0;
 		xen_start_info->console.domU.evtchn = 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/xen/mmu.c linux-libre-4.7-gnu/arch/x86/xen/mmu.c
--- linux-libre-4.6-gnu/arch/x86/xen/mmu.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/xen/mmu.c	2016-07-24 15:23:50.000000000 -0400
@@ -1113,7 +1113,7 @@ static void __init xen_cleanhighmap(unsi
 
 	/* NOTE: The loop is more greedy than the cleanup_highmap variant.
 	 * We include the PMD passed in on _both_ boundaries. */
-	for (; vaddr <= vaddr_end && (pmd < (level2_kernel_pgt + PAGE_SIZE));
+	for (; vaddr <= vaddr_end && (pmd < (level2_kernel_pgt + PTRS_PER_PMD));
 			pmd++, vaddr += PMD_SIZE) {
 		if (pmd_none(*pmd))
 			continue;
@@ -1551,41 +1551,6 @@ static void xen_pgd_free(struct mm_struc
 #endif
 }
 
-#ifdef CONFIG_X86_32
-static pte_t __init mask_rw_pte(pte_t *ptep, pte_t pte)
-{
-	/* If there's an existing pte, then don't allow _PAGE_RW to be set */
-	if (pte_val_ma(*ptep) & _PAGE_PRESENT)
-		pte = __pte_ma(((pte_val_ma(*ptep) & _PAGE_RW) | ~_PAGE_RW) &
-			       pte_val_ma(pte));
-
-	return pte;
-}
-#else /* CONFIG_X86_64 */
-static pte_t __init mask_rw_pte(pte_t *ptep, pte_t pte)
-{
-	unsigned long pfn;
-
-	if (xen_feature(XENFEAT_writable_page_tables) ||
-	    xen_feature(XENFEAT_auto_translated_physmap) ||
-	    xen_start_info->mfn_list >= __START_KERNEL_map)
-		return pte;
-
-	/*
-	 * Pages belonging to the initial p2m list mapped outside the default
-	 * address range must be mapped read-only. This region contains the
-	 * page tables for mapping the p2m list, too, and page tables MUST be
-	 * mapped read-only.
-	 */
-	pfn = pte_pfn(pte);
-	if (pfn >= xen_start_info->first_p2m_pfn &&
-	    pfn < xen_start_info->first_p2m_pfn + xen_start_info->nr_p2m_frames)
-		pte = __pte_ma(pte_val_ma(pte) & ~_PAGE_RW);
-
-	return pte;
-}
-#endif /* CONFIG_X86_64 */
-
 /*
  * Init-time set_pte while constructing initial pagetables, which
  * doesn't allow RO page table pages to be remapped RW.
@@ -1600,13 +1565,37 @@ static pte_t __init mask_rw_pte(pte_t *p
  * so always write the PTE directly and rely on Xen trapping and
  * emulating any updates as necessary.
  */
-static void __init xen_set_pte_init(pte_t *ptep, pte_t pte)
+__visible pte_t xen_make_pte_init(pteval_t pte)
 {
-	if (pte_mfn(pte) != INVALID_P2M_ENTRY)
-		pte = mask_rw_pte(ptep, pte);
-	else
-		pte = __pte_ma(0);
+#ifdef CONFIG_X86_64
+	unsigned long pfn;
 
+	/*
+	 * Pages belonging to the initial p2m list mapped outside the default
+	 * address range must be mapped read-only. This region contains the
+	 * page tables for mapping the p2m list, too, and page tables MUST be
+	 * mapped read-only.
+	 */
+	pfn = (pte & PTE_PFN_MASK) >> PAGE_SHIFT;
+	if (xen_start_info->mfn_list < __START_KERNEL_map &&
+	    pfn >= xen_start_info->first_p2m_pfn &&
+	    pfn < xen_start_info->first_p2m_pfn + xen_start_info->nr_p2m_frames)
+		pte &= ~_PAGE_RW;
+#endif
+	pte = pte_pfn_to_mfn(pte);
+	return native_make_pte(pte);
+}
+PV_CALLEE_SAVE_REGS_THUNK(xen_make_pte_init);
+
+static void __init xen_set_pte_init(pte_t *ptep, pte_t pte)
+{
+#ifdef CONFIG_X86_32
+	/* If there's an existing pte, then don't allow _PAGE_RW to be set */
+	if (pte_mfn(pte) != INVALID_P2M_ENTRY
+	    && pte_val_ma(*ptep) & _PAGE_PRESENT)
+		pte = __pte_ma(((pte_val_ma(*ptep) & _PAGE_RW) | ~_PAGE_RW) &
+			       pte_val_ma(pte));
+#endif
 	native_set_pte(ptep, pte);
 }
 
@@ -2407,6 +2396,7 @@ static void __init xen_post_allocator_in
 	pv_mmu_ops.alloc_pud = xen_alloc_pud;
 	pv_mmu_ops.release_pud = xen_release_pud;
 #endif
+	pv_mmu_ops.make_pte = PV_CALLEE_SAVE(xen_make_pte);
 
 #ifdef CONFIG_X86_64
 	pv_mmu_ops.write_cr3 = &xen_write_cr3;
@@ -2455,7 +2445,7 @@ static const struct pv_mmu_ops xen_mmu_o
 	.pte_val = PV_CALLEE_SAVE(xen_pte_val),
 	.pgd_val = PV_CALLEE_SAVE(xen_pgd_val),
 
-	.make_pte = PV_CALLEE_SAVE(xen_make_pte),
+	.make_pte = PV_CALLEE_SAVE(xen_make_pte_init),
 	.make_pgd = PV_CALLEE_SAVE(xen_make_pgd),
 
 #ifdef CONFIG_X86_PAE
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/xen/p2m.c linux-libre-4.7-gnu/arch/x86/xen/p2m.c
--- linux-libre-4.6-gnu/arch/x86/xen/p2m.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/xen/p2m.c	2016-07-24 15:23:50.000000000 -0400
@@ -182,7 +182,7 @@ static void * __ref alloc_p2m_page(void)
 	if (unlikely(!slab_is_available()))
 		return alloc_bootmem_align(PAGE_SIZE, PAGE_SIZE);
 
-	return (void *)__get_free_page(GFP_KERNEL | __GFP_REPEAT);
+	return (void *)__get_free_page(GFP_KERNEL);
 }
 
 static void __ref free_p2m_page(void *p)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/xen/setup.c linux-libre-4.7-gnu/arch/x86/xen/setup.c
--- linux-libre-4.6-gnu/arch/x86/xen/setup.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/xen/setup.c	2016-07-24 15:23:50.000000000 -0400
@@ -393,6 +393,9 @@ static unsigned long __init xen_set_iden
 	unsigned long i = 0;
 	unsigned long n = end_pfn - start_pfn;
 
+	if (remap_pfn == 0)
+		remap_pfn = nr_pages;
+
 	while (i < n) {
 		unsigned long cur_pfn = start_pfn + i;
 		unsigned long left = n - i;
@@ -438,17 +441,29 @@ static unsigned long __init xen_set_iden
 	return remap_pfn;
 }
 
-static void __init xen_set_identity_and_remap(unsigned long nr_pages)
+static unsigned long __init xen_count_remap_pages(
+	unsigned long start_pfn, unsigned long end_pfn, unsigned long nr_pages,
+	unsigned long remap_pages)
+{
+	if (start_pfn >= nr_pages)
+		return remap_pages;
+
+	return remap_pages + min(end_pfn, nr_pages) - start_pfn;
+}
+
+static unsigned long __init xen_foreach_remap_area(unsigned long nr_pages,
+	unsigned long (*func)(unsigned long start_pfn, unsigned long end_pfn,
+			      unsigned long nr_pages, unsigned long last_val))
 {
 	phys_addr_t start = 0;
-	unsigned long last_pfn = nr_pages;
+	unsigned long ret_val = 0;
 	const struct e820entry *entry = xen_e820_map;
 	int i;
 
 	/*
 	 * Combine non-RAM regions and gaps until a RAM region (or the
-	 * end of the map) is reached, then set the 1:1 map and
-	 * remap the memory in those non-RAM regions.
+	 * end of the map) is reached, then call the provided function
+	 * to perform its duty on the non-RAM region.
 	 *
 	 * The combined non-RAM regions are rounded to a whole number
 	 * of pages so any partial pages are accessible via the 1:1
@@ -466,14 +481,13 @@ static void __init xen_set_identity_and_
 				end_pfn = PFN_UP(entry->addr);
 
 			if (start_pfn < end_pfn)
-				last_pfn = xen_set_identity_and_remap_chunk(
-						start_pfn, end_pfn, nr_pages,
-						last_pfn);
+				ret_val = func(start_pfn, end_pfn, nr_pages,
+					       ret_val);
 			start = end;
 		}
 	}
 
-	pr_info("Released %ld page(s)\n", xen_released_pages);
+	return ret_val;
 }
 
 /*
@@ -596,35 +610,6 @@ static void __init xen_ignore_unusable(v
 	}
 }
 
-static unsigned long __init xen_count_remap_pages(unsigned long max_pfn)
-{
-	unsigned long extra = 0;
-	unsigned long start_pfn, end_pfn;
-	const struct e820entry *entry = xen_e820_map;
-	int i;
-
-	end_pfn = 0;
-	for (i = 0; i < xen_e820_map_entries; i++, entry++) {
-		start_pfn = PFN_DOWN(entry->addr);
-		/* Adjacent regions on non-page boundaries handling! */
-		end_pfn = min(end_pfn, start_pfn);
-
-		if (start_pfn >= max_pfn)
-			return extra + max_pfn - end_pfn;
-
-		/* Add any holes in map to result. */
-		extra += start_pfn - end_pfn;
-
-		end_pfn = PFN_UP(entry->addr + entry->size);
-		end_pfn = min(end_pfn, max_pfn);
-
-		if (entry->type != E820_RAM)
-			extra += end_pfn - start_pfn;
-	}
-
-	return extra;
-}
-
 bool __init xen_is_e820_reserved(phys_addr_t start, phys_addr_t size)
 {
 	struct e820entry *entry;
@@ -804,7 +789,7 @@ char * __init xen_memory_setup(void)
 	max_pages = xen_get_max_pages();
 
 	/* How many extra pages do we need due to remapping? */
-	max_pages += xen_count_remap_pages(max_pfn);
+	max_pages += xen_foreach_remap_area(max_pfn, xen_count_remap_pages);
 
 	if (max_pages > max_pfn)
 		extra_pages += max_pages - max_pfn;
@@ -922,7 +907,9 @@ char * __init xen_memory_setup(void)
 	 * Set identity map on non-RAM pages and prepare remapping the
 	 * underlying RAM.
 	 */
-	xen_set_identity_and_remap(max_pfn);
+	xen_foreach_remap_area(max_pfn, xen_set_identity_and_remap_chunk);
+
+	pr_info("Released %ld page(s)\n", xen_released_pages);
 
 	return "Xen";
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/x86/xen/time.c linux-libre-4.7-gnu/arch/x86/xen/time.c
--- linux-libre-4.6-gnu/arch/x86/xen/time.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/x86/xen/time.c	2016-07-24 15:23:50.000000000 -0400
@@ -290,11 +290,11 @@ static int xen_vcpuop_set_next_event(uns
 	WARN_ON(!clockevent_state_oneshot(evt));
 
 	single.timeout_abs_ns = get_abs_timeout(delta);
-	single.flags = VCPU_SSHOTTMR_future;
+	/* Get an event anyway, even if the timeout is already expired */
+	single.flags = 0;
 
 	ret = HYPERVISOR_vcpu_op(VCPUOP_set_singleshot_timer, cpu, &single);
-
-	BUG_ON(ret != 0 && ret != -ETIME);
+	BUG_ON(ret != 0);
 
 	return ret;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/xtensa/configs/generic_kc705_defconfig linux-libre-4.7-gnu/arch/xtensa/configs/generic_kc705_defconfig
--- linux-libre-4.6-gnu/arch/xtensa/configs/generic_kc705_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/xtensa/configs/generic_kc705_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -11,7 +11,6 @@ CONFIG_CGROUP_FREEZER=y
 CONFIG_CGROUP_DEVICE=y
 CONFIG_CPUSETS=y
 CONFIG_CGROUP_CPUACCT=y
-CONFIG_RESOURCE_COUNTERS=y
 CONFIG_MEMCG=y
 CONFIG_NAMESPACES=y
 CONFIG_SCHED_AUTOGROUP=y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/xtensa/configs/smp_lx200_defconfig linux-libre-4.7-gnu/arch/xtensa/configs/smp_lx200_defconfig
--- linux-libre-4.6-gnu/arch/xtensa/configs/smp_lx200_defconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/xtensa/configs/smp_lx200_defconfig	2016-07-24 15:23:50.000000000 -0400
@@ -11,7 +11,6 @@ CONFIG_CGROUP_FREEZER=y
 CONFIG_CGROUP_DEVICE=y
 CONFIG_CPUSETS=y
 CONFIG_CGROUP_CPUACCT=y
-CONFIG_RESOURCE_COUNTERS=y
 CONFIG_MEMCG=y
 CONFIG_NAMESPACES=y
 CONFIG_SCHED_AUTOGROUP=y
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/xtensa/include/asm/Kbuild linux-libre-4.7-gnu/arch/xtensa/include/asm/Kbuild
--- linux-libre-4.6-gnu/arch/xtensa/include/asm/Kbuild	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/xtensa/include/asm/Kbuild	2016-07-24 15:23:50.000000000 -0400
@@ -22,6 +22,7 @@ generic-y += mm-arch-hooks.h
 generic-y += percpu.h
 generic-y += preempt.h
 generic-y += resource.h
+generic-y += rwsem.h
 generic-y += sections.h
 generic-y += siginfo.h
 generic-y += statfs.h
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/xtensa/include/asm/pgalloc.h linux-libre-4.7-gnu/arch/xtensa/include/asm/pgalloc.h
--- linux-libre-4.6-gnu/arch/xtensa/include/asm/pgalloc.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/xtensa/include/asm/pgalloc.h	2016-07-24 15:23:50.000000000 -0400
@@ -44,7 +44,7 @@ static inline pte_t *pte_alloc_one_kerne
 	pte_t *ptep;
 	int i;
 
-	ptep = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT);
+	ptep = (pte_t *)__get_free_page(GFP_KERNEL);
 	if (!ptep)
 		return NULL;
 	for (i = 0; i < 1024; i++)
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/xtensa/include/asm/rwsem.h linux-libre-4.7-gnu/arch/xtensa/include/asm/rwsem.h
--- linux-libre-4.6-gnu/arch/xtensa/include/asm/rwsem.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/xtensa/include/asm/rwsem.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,131 +0,0 @@
-/*
- * include/asm-xtensa/rwsem.h
- *
- * 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.
- *
- * Largely copied from include/asm-ppc/rwsem.h
- *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_RWSEM_H
-#define _XTENSA_RWSEM_H
-
-#ifndef _LINUX_RWSEM_H
-#error "Please don't include <asm/rwsem.h> directly, use <linux/rwsem.h> instead."
-#endif
-
-#define RWSEM_UNLOCKED_VALUE		0x00000000
-#define RWSEM_ACTIVE_BIAS		0x00000001
-#define RWSEM_ACTIVE_MASK		0x0000ffff
-#define RWSEM_WAITING_BIAS		(-0x00010000)
-#define RWSEM_ACTIVE_READ_BIAS		RWSEM_ACTIVE_BIAS
-#define RWSEM_ACTIVE_WRITE_BIAS		(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
-
-/*
- * lock for reading
- */
-static inline void __down_read(struct rw_semaphore *sem)
-{
-	if (atomic_add_return(1,(atomic_t *)(&sem->count)) > 0)
-		smp_wmb();
-	else
-		rwsem_down_read_failed(sem);
-}
-
-static inline int __down_read_trylock(struct rw_semaphore *sem)
-{
-	int tmp;
-
-	while ((tmp = sem->count) >= 0) {
-		if (tmp == cmpxchg(&sem->count, tmp,
-				   tmp + RWSEM_ACTIVE_READ_BIAS)) {
-			smp_wmb();
-			return 1;
-		}
-	}
-	return 0;
-}
-
-/*
- * lock for writing
- */
-static inline void __down_write(struct rw_semaphore *sem)
-{
-	int tmp;
-
-	tmp = atomic_add_return(RWSEM_ACTIVE_WRITE_BIAS,
-				(atomic_t *)(&sem->count));
-	if (tmp == RWSEM_ACTIVE_WRITE_BIAS)
-		smp_wmb();
-	else
-		rwsem_down_write_failed(sem);
-}
-
-static inline int __down_write_trylock(struct rw_semaphore *sem)
-{
-	int tmp;
-
-	tmp = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE,
-		      RWSEM_ACTIVE_WRITE_BIAS);
-	smp_wmb();
-	return tmp == RWSEM_UNLOCKED_VALUE;
-}
-
-/*
- * unlock after reading
- */
-static inline void __up_read(struct rw_semaphore *sem)
-{
-	int tmp;
-
-	smp_wmb();
-	tmp = atomic_sub_return(1,(atomic_t *)(&sem->count));
-	if (tmp < -1 && (tmp & RWSEM_ACTIVE_MASK) == 0)
-		rwsem_wake(sem);
-}
-
-/*
- * unlock after writing
- */
-static inline void __up_write(struct rw_semaphore *sem)
-{
-	smp_wmb();
-	if (atomic_sub_return(RWSEM_ACTIVE_WRITE_BIAS,
-			      (atomic_t *)(&sem->count)) < 0)
-		rwsem_wake(sem);
-}
-
-/*
- * implement atomic add functionality
- */
-static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem)
-{
-	atomic_add(delta, (atomic_t *)(&sem->count));
-}
-
-/*
- * downgrade write lock to read lock
- */
-static inline void __downgrade_write(struct rw_semaphore *sem)
-{
-	int tmp;
-
-	smp_wmb();
-	tmp = atomic_add_return(-RWSEM_WAITING_BIAS, (atomic_t *)(&sem->count));
-	if (tmp < 0)
-		rwsem_downgrade_wake(sem);
-}
-
-/*
- * implement exchange and add functionality
- */
-static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem)
-{
-	smp_mb();
-	return atomic_add_return(delta, (atomic_t *)(&sem->count));
-}
-
-#endif	/* _XTENSA_RWSEM_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/xtensa/Kconfig linux-libre-4.7-gnu/arch/xtensa/Kconfig
--- linux-libre-4.6-gnu/arch/xtensa/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/xtensa/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -5,7 +5,6 @@ config XTENSA
 	def_bool y
 	select ARCH_WANT_FRAME_POINTERS
 	select ARCH_WANT_IPC_PARSE_VERSION
-	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select BUILDTIME_EXTABLE_SORT
 	select CLONE_BACKWARDS
 	select COMMON_CLK
@@ -15,6 +14,7 @@ config XTENSA
 	select GENERIC_PCI_IOMAP
 	select GENERIC_SCHED_CLOCK
 	select HAVE_DMA_API_DEBUG
+	select HAVE_EXIT_THREAD
 	select HAVE_FUNCTION_TRACER
 	select HAVE_FUTEX_CMPXCHG if !MMU
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/xtensa/kernel/perf_event.c linux-libre-4.7-gnu/arch/xtensa/kernel/perf_event.c
--- linux-libre-4.6-gnu/arch/xtensa/kernel/perf_event.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/xtensa/kernel/perf_event.c	2016-07-24 15:23:50.000000000 -0400
@@ -323,23 +323,23 @@ static void xtensa_pmu_read(struct perf_
 
 static int callchain_trace(struct stackframe *frame, void *data)
 {
-	struct perf_callchain_entry *entry = data;
+	struct perf_callchain_entry_ctx *entry = data;
 
 	perf_callchain_store(entry, frame->pc);
 	return 0;
 }
 
-void perf_callchain_kernel(struct perf_callchain_entry *entry,
+void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
 			   struct pt_regs *regs)
 {
-	xtensa_backtrace_kernel(regs, PERF_MAX_STACK_DEPTH,
+	xtensa_backtrace_kernel(regs, entry->max_stack,
 				callchain_trace, NULL, entry);
 }
 
-void perf_callchain_user(struct perf_callchain_entry *entry,
+void perf_callchain_user(struct perf_callchain_entry_ctx *entry,
 			 struct pt_regs *regs)
 {
-	xtensa_backtrace_user(regs, PERF_MAX_STACK_DEPTH,
+	xtensa_backtrace_user(regs, entry->max_stack,
 			      callchain_trace, entry);
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/xtensa/kernel/process.c linux-libre-4.7-gnu/arch/xtensa/kernel/process.c
--- linux-libre-4.6-gnu/arch/xtensa/kernel/process.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/xtensa/kernel/process.c	2016-07-24 15:23:50.000000000 -0400
@@ -115,10 +115,10 @@ void arch_cpu_idle(void)
 /*
  * This is called when the thread calls exit().
  */
-void exit_thread(void)
+void exit_thread(struct task_struct *tsk)
 {
 #if XTENSA_HAVE_COPROCESSORS
-	coprocessor_release_all(current_thread_info());
+	coprocessor_release_all(task_thread_info(tsk));
 #endif
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/arch/xtensa/platforms/iss/network.c linux-libre-4.7-gnu/arch/xtensa/platforms/iss/network.c
--- linux-libre-4.6-gnu/arch/xtensa/platforms/iss/network.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/arch/xtensa/platforms/iss/network.c	2016-07-24 15:23:50.000000000 -0400
@@ -428,7 +428,7 @@ static int iss_net_start_xmit(struct sk_
 	if (len == skb->len) {
 		lp->stats.tx_packets++;
 		lp->stats.tx_bytes += skb->len;
-		dev->trans_start = jiffies;
+		netif_trans_update(dev);
 		netif_start_queue(dev);
 
 		/* this is normally done in the interrupt when tx finishes */
diff -druNp --no-dereference linux-libre-4.6-gnu/block/bio.c linux-libre-4.7-gnu/block/bio.c
--- linux-libre-4.6-gnu/block/bio.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/block/bio.c	2016-07-24 15:23:50.000000000 -0400
@@ -311,17 +311,6 @@ static void bio_chain_endio(struct bio *
 	bio_endio(__bio_chain_endio(bio));
 }
 
-/*
- * Increment chain count for the bio. Make sure the CHAIN flag update
- * is visible before the raised count.
- */
-static inline void bio_inc_remaining(struct bio *bio)
-{
-	bio_set_flag(bio, BIO_CHAIN);
-	smp_mb__before_atomic();
-	atomic_inc(&bio->__bi_remaining);
-}
-
 /**
  * bio_chain - chain bio completions
  * @bio: the target bio
diff -druNp --no-dereference linux-libre-4.6-gnu/block/blk-core.c linux-libre-4.7-gnu/block/blk-core.c
--- linux-libre-4.6-gnu/block/blk-core.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/block/blk-core.c	2016-07-24 15:23:50.000000000 -0400
@@ -1523,6 +1523,7 @@ EXPORT_SYMBOL(blk_put_request);
  * blk_add_request_payload - add a payload to a request
  * @rq: request to update
  * @page: page backing the payload
+ * @offset: offset in page
  * @len: length of the payload.
  *
  * This allows to later add a payload to an already submitted request by
@@ -1533,12 +1534,12 @@ EXPORT_SYMBOL(blk_put_request);
  * discard requests should ever use it.
  */
 void blk_add_request_payload(struct request *rq, struct page *page,
-		unsigned int len)
+		int offset, unsigned int len)
 {
 	struct bio *bio = rq->bio;
 
 	bio->bi_io_vec->bv_page = page;
-	bio->bi_io_vec->bv_offset = 0;
+	bio->bi_io_vec->bv_offset = offset;
 	bio->bi_io_vec->bv_len = len;
 
 	bio->bi_iter.bi_size = len;
@@ -1963,7 +1964,8 @@ generic_make_request_checks(struct bio *
 	 * drivers without flush support don't have to worry
 	 * about them.
 	 */
-	if ((bio->bi_rw & (REQ_FLUSH | REQ_FUA)) && !q->flush_flags) {
+	if ((bio->bi_rw & (REQ_FLUSH | REQ_FUA)) &&
+	    !test_bit(QUEUE_FLAG_WC, &q->queue_flags)) {
 		bio->bi_rw &= ~(REQ_FLUSH | REQ_FUA);
 		if (!nr_sectors) {
 			err = 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/block/blk-flush.c linux-libre-4.7-gnu/block/blk-flush.c
--- linux-libre-4.6-gnu/block/blk-flush.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/block/blk-flush.c	2016-07-24 15:23:50.000000000 -0400
@@ -95,17 +95,18 @@ enum {
 static bool blk_kick_flush(struct request_queue *q,
 			   struct blk_flush_queue *fq);
 
-static unsigned int blk_flush_policy(unsigned int fflags, struct request *rq)
+static unsigned int blk_flush_policy(unsigned long fflags, struct request *rq)
 {
 	unsigned int policy = 0;
 
 	if (blk_rq_sectors(rq))
 		policy |= REQ_FSEQ_DATA;
 
-	if (fflags & REQ_FLUSH) {
+	if (fflags & (1UL << QUEUE_FLAG_WC)) {
 		if (rq->cmd_flags & REQ_FLUSH)
 			policy |= REQ_FSEQ_PREFLUSH;
-		if (!(fflags & REQ_FUA) && (rq->cmd_flags & REQ_FUA))
+		if (!(fflags & (1UL << QUEUE_FLAG_FUA)) &&
+		    (rq->cmd_flags & REQ_FUA))
 			policy |= REQ_FSEQ_POSTFLUSH;
 	}
 	return policy;
@@ -384,7 +385,7 @@ static void mq_flush_data_end_io(struct
 void blk_insert_flush(struct request *rq)
 {
 	struct request_queue *q = rq->q;
-	unsigned int fflags = q->flush_flags;	/* may change, cache */
+	unsigned long fflags = q->queue_flags;	/* may change, cache */
 	unsigned int policy = blk_flush_policy(fflags, rq);
 	struct blk_flush_queue *fq = blk_get_flush_queue(q, rq->mq_ctx);
 
@@ -393,7 +394,7 @@ void blk_insert_flush(struct request *rq
 	 * REQ_FLUSH and FUA for the driver.
 	 */
 	rq->cmd_flags &= ~REQ_FLUSH;
-	if (!(fflags & REQ_FUA))
+	if (!(fflags & (1UL << QUEUE_FLAG_FUA)))
 		rq->cmd_flags &= ~REQ_FUA;
 
 	/*
diff -druNp --no-dereference linux-libre-4.6-gnu/block/blk-lib.c linux-libre-4.7-gnu/block/blk-lib.c
--- linux-libre-4.6-gnu/block/blk-lib.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/block/blk-lib.c	2016-07-24 15:23:50.000000000 -0400
@@ -9,82 +9,46 @@
 
 #include "blk.h"
 
-struct bio_batch {
-	atomic_t		done;
-	int			error;
-	struct completion	*wait;
-};
-
-static void bio_batch_end_io(struct bio *bio)
+static struct bio *next_bio(struct bio *bio, int rw, unsigned int nr_pages,
+		gfp_t gfp)
 {
-	struct bio_batch *bb = bio->bi_private;
+	struct bio *new = bio_alloc(gfp, nr_pages);
 
-	if (bio->bi_error && bio->bi_error != -EOPNOTSUPP)
-		bb->error = bio->bi_error;
-	if (atomic_dec_and_test(&bb->done))
-		complete(bb->wait);
-	bio_put(bio);
+	if (bio) {
+		bio_chain(bio, new);
+		submit_bio(rw, bio);
+	}
+
+	return new;
 }
 
-/**
- * blkdev_issue_discard - queue a discard
- * @bdev:	blockdev to issue discard for
- * @sector:	start sector
- * @nr_sects:	number of sectors to discard
- * @gfp_mask:	memory allocation flags (for bio_alloc)
- * @flags:	BLKDEV_IFL_* flags to control behaviour
- *
- * Description:
- *    Issue a discard request for the sectors in question.
- */
-int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
-		sector_t nr_sects, gfp_t gfp_mask, unsigned long flags)
+int __blkdev_issue_discard(struct block_device *bdev, sector_t sector,
+		sector_t nr_sects, gfp_t gfp_mask, int type, struct bio **biop)
 {
-	DECLARE_COMPLETION_ONSTACK(wait);
 	struct request_queue *q = bdev_get_queue(bdev);
-	int type = REQ_WRITE | REQ_DISCARD;
+	struct bio *bio = *biop;
 	unsigned int granularity;
 	int alignment;
-	struct bio_batch bb;
-	struct bio *bio;
-	int ret = 0;
-	struct blk_plug plug;
 
 	if (!q)
 		return -ENXIO;
-
 	if (!blk_queue_discard(q))
 		return -EOPNOTSUPP;
+	if ((type & REQ_SECURE) && !blk_queue_secdiscard(q))
+		return -EOPNOTSUPP;
 
 	/* Zero-sector (unknown) and one-sector granularities are the same.  */
 	granularity = max(q->limits.discard_granularity >> 9, 1U);
 	alignment = (bdev_discard_alignment(bdev) >> 9) % granularity;
 
-	if (flags & BLKDEV_DISCARD_SECURE) {
-		if (!blk_queue_secdiscard(q))
-			return -EOPNOTSUPP;
-		type |= REQ_SECURE;
-	}
-
-	atomic_set(&bb.done, 1);
-	bb.error = 0;
-	bb.wait = &wait;
-
-	blk_start_plug(&plug);
 	while (nr_sects) {
 		unsigned int req_sects;
 		sector_t end_sect, tmp;
 
-		bio = bio_alloc(gfp_mask, 1);
-		if (!bio) {
-			ret = -ENOMEM;
-			break;
-		}
-
 		/* Make sure bi_size doesn't overflow */
 		req_sects = min_t(sector_t, nr_sects, UINT_MAX >> 9);
 
-		/*
+		/**
 		 * If splitting a request, and the next starting sector would be
 		 * misaligned, stop the discard at the previous aligned sector.
 		 */
@@ -98,18 +62,14 @@ int blkdev_issue_discard(struct block_de
 			req_sects = end_sect - sector;
 		}
 
+		bio = next_bio(bio, type, 1, gfp_mask);
 		bio->bi_iter.bi_sector = sector;
-		bio->bi_end_io = bio_batch_end_io;
 		bio->bi_bdev = bdev;
-		bio->bi_private = &bb;
 
 		bio->bi_iter.bi_size = req_sects << 9;
 		nr_sects -= req_sects;
 		sector = end_sect;
 
-		atomic_inc(&bb.done);
-		submit_bio(type, bio);
-
 		/*
 		 * We can loop for a long time in here, if someone does
 		 * full device discards (like mkfs). Be nice and allow
@@ -118,14 +78,45 @@ int blkdev_issue_discard(struct block_de
 		 */
 		cond_resched();
 	}
-	blk_finish_plug(&plug);
 
-	/* Wait for bios in-flight */
-	if (!atomic_dec_and_test(&bb.done))
-		wait_for_completion_io(&wait);
+	*biop = bio;
+	return 0;
+}
+EXPORT_SYMBOL(__blkdev_issue_discard);
+
+/**
+ * blkdev_issue_discard - queue a discard
+ * @bdev:	blockdev to issue discard for
+ * @sector:	start sector
+ * @nr_sects:	number of sectors to discard
+ * @gfp_mask:	memory allocation flags (for bio_alloc)
+ * @flags:	BLKDEV_IFL_* flags to control behaviour
+ *
+ * Description:
+ *    Issue a discard request for the sectors in question.
+ */
+int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
+		sector_t nr_sects, gfp_t gfp_mask, unsigned long flags)
+{
+	int type = REQ_WRITE | REQ_DISCARD;
+	struct bio *bio = NULL;
+	struct blk_plug plug;
+	int ret;
+
+	if (flags & BLKDEV_DISCARD_SECURE)
+		type |= REQ_SECURE;
+
+	blk_start_plug(&plug);
+	ret = __blkdev_issue_discard(bdev, sector, nr_sects, gfp_mask, type,
+			&bio);
+	if (!ret && bio) {
+		ret = submit_bio_wait(type, bio);
+		if (ret == -EOPNOTSUPP)
+			ret = 0;
+		bio_put(bio);
+	}
+	blk_finish_plug(&plug);
 
-	if (bb.error)
-		return bb.error;
 	return ret;
 }
 EXPORT_SYMBOL(blkdev_issue_discard);
@@ -145,11 +136,9 @@ int blkdev_issue_write_same(struct block
 			    sector_t nr_sects, gfp_t gfp_mask,
 			    struct page *page)
 {
-	DECLARE_COMPLETION_ONSTACK(wait);
 	struct request_queue *q = bdev_get_queue(bdev);
 	unsigned int max_write_same_sectors;
-	struct bio_batch bb;
-	struct bio *bio;
+	struct bio *bio = NULL;
 	int ret = 0;
 
 	if (!q)
@@ -158,21 +147,10 @@ int blkdev_issue_write_same(struct block
 	/* Ensure that max_write_same_sectors doesn't overflow bi_size */
 	max_write_same_sectors = UINT_MAX >> 9;
 
-	atomic_set(&bb.done, 1);
-	bb.error = 0;
-	bb.wait = &wait;
-
 	while (nr_sects) {
-		bio = bio_alloc(gfp_mask, 1);
-		if (!bio) {
-			ret = -ENOMEM;
-			break;
-		}
-
+		bio = next_bio(bio, REQ_WRITE | REQ_WRITE_SAME, 1, gfp_mask);
 		bio->bi_iter.bi_sector = sector;
-		bio->bi_end_io = bio_batch_end_io;
 		bio->bi_bdev = bdev;
-		bio->bi_private = &bb;
 		bio->bi_vcnt = 1;
 		bio->bi_io_vec->bv_page = page;
 		bio->bi_io_vec->bv_offset = 0;
@@ -186,18 +164,13 @@ int blkdev_issue_write_same(struct block
 			bio->bi_iter.bi_size = nr_sects << 9;
 			nr_sects = 0;
 		}
-
-		atomic_inc(&bb.done);
-		submit_bio(REQ_WRITE | REQ_WRITE_SAME, bio);
 	}
 
-	/* Wait for bios in-flight */
-	if (!atomic_dec_and_test(&bb.done))
-		wait_for_completion_io(&wait);
-
-	if (bb.error)
-		return bb.error;
-	return ret;
+	if (bio) {
+		ret = submit_bio_wait(REQ_WRITE | REQ_WRITE_SAME, bio);
+		bio_put(bio);
+	}
+	return ret != -EOPNOTSUPP ? ret : 0;
 }
 EXPORT_SYMBOL(blkdev_issue_write_same);
 
@@ -216,28 +189,15 @@ static int __blkdev_issue_zeroout(struct
 				  sector_t nr_sects, gfp_t gfp_mask)
 {
 	int ret;
-	struct bio *bio;
-	struct bio_batch bb;
+	struct bio *bio = NULL;
 	unsigned int sz;
-	DECLARE_COMPLETION_ONSTACK(wait);
-
-	atomic_set(&bb.done, 1);
-	bb.error = 0;
-	bb.wait = &wait;
 
-	ret = 0;
 	while (nr_sects != 0) {
-		bio = bio_alloc(gfp_mask,
-				min(nr_sects, (sector_t)BIO_MAX_PAGES));
-		if (!bio) {
-			ret = -ENOMEM;
-			break;
-		}
-
+		bio = next_bio(bio, WRITE,
+				min(nr_sects, (sector_t)BIO_MAX_PAGES),
+				gfp_mask);
 		bio->bi_iter.bi_sector = sector;
 		bio->bi_bdev   = bdev;
-		bio->bi_end_io = bio_batch_end_io;
-		bio->bi_private = &bb;
 
 		while (nr_sects != 0) {
 			sz = min((sector_t) PAGE_SIZE >> 9 , nr_sects);
@@ -247,18 +207,14 @@ static int __blkdev_issue_zeroout(struct
 			if (ret < (sz << 9))
 				break;
 		}
-		ret = 0;
-		atomic_inc(&bb.done);
-		submit_bio(WRITE, bio);
 	}
 
-	/* Wait for bios in-flight */
-	if (!atomic_dec_and_test(&bb.done))
-		wait_for_completion_io(&wait);
-
-	if (bb.error)
-		return bb.error;
-	return ret;
+	if (bio) {
+		ret = submit_bio_wait(WRITE, bio);
+		bio_put(bio);
+		return ret;
+	}
+	return 0;
 }
 
 /**
diff -druNp --no-dereference linux-libre-4.6-gnu/block/blk-mq.c linux-libre-4.7-gnu/block/blk-mq.c
--- linux-libre-4.6-gnu/block/blk-mq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/block/blk-mq.c	2016-07-24 15:23:50.000000000 -0400
@@ -1122,8 +1122,7 @@ static void blk_mq_bio_to_request(struct
 {
 	init_request_from_bio(rq, bio);
 
-	if (blk_do_io_stat(rq))
-		blk_account_io_start(rq, 1);
+	blk_account_io_start(rq, 1);
 }
 
 static inline bool hctx_allow_merges(struct blk_mq_hw_ctx *hctx)
@@ -1263,12 +1262,9 @@ static blk_qc_t blk_mq_make_request(stru
 
 	blk_queue_split(q, &bio, q->bio_split);
 
-	if (!is_flush_fua && !blk_queue_nomerges(q)) {
-		if (blk_attempt_plug_merge(q, bio, &request_count,
-					   &same_queue_rq))
-			return BLK_QC_T_NONE;
-	} else
-		request_count = blk_plug_queued_count(q);
+	if (!is_flush_fua && !blk_queue_nomerges(q) &&
+	    blk_attempt_plug_merge(q, bio, &request_count, &same_queue_rq))
+		return BLK_QC_T_NONE;
 
 	rq = blk_mq_map_request(q, bio, &data);
 	if (unlikely(!rq))
@@ -1359,9 +1355,11 @@ static blk_qc_t blk_sq_make_request(stru
 
 	blk_queue_split(q, &bio, q->bio_split);
 
-	if (!is_flush_fua && !blk_queue_nomerges(q) &&
-	    blk_attempt_plug_merge(q, bio, &request_count, NULL))
-		return BLK_QC_T_NONE;
+	if (!is_flush_fua && !blk_queue_nomerges(q)) {
+		if (blk_attempt_plug_merge(q, bio, &request_count, NULL))
+			return BLK_QC_T_NONE;
+	} else
+		request_count = blk_plug_queued_count(q);
 
 	rq = blk_mq_map_request(q, bio, &data);
 	if (unlikely(!rq))
@@ -1496,7 +1494,7 @@ static struct blk_mq_tags *blk_mq_init_r
 		int to_do;
 		void *p;
 
-		while (left < order_to_size(this_order - 1) && this_order)
+		while (this_order && left < order_to_size(this_order - 1))
 			this_order--;
 
 		do {
@@ -2021,7 +2019,7 @@ struct request_queue *blk_mq_init_alloca
 
 	q->queue_ctx = alloc_percpu(struct blk_mq_ctx);
 	if (!q->queue_ctx)
-		return ERR_PTR(-ENOMEM);
+		goto err_exit;
 
 	q->queue_hw_ctx = kzalloc_node(nr_cpu_ids * sizeof(*(q->queue_hw_ctx)),
 						GFP_KERNEL, set->numa_node);
@@ -2085,6 +2083,8 @@ err_map:
 	kfree(q->queue_hw_ctx);
 err_percpu:
 	free_percpu(q->queue_ctx);
+err_exit:
+	q->mq_ops = NULL;
 	return ERR_PTR(-ENOMEM);
 }
 EXPORT_SYMBOL(blk_mq_init_allocated_queue);
diff -druNp --no-dereference linux-libre-4.6-gnu/block/blk-mq-tag.c linux-libre-4.7-gnu/block/blk-mq-tag.c
--- linux-libre-4.6-gnu/block/blk-mq-tag.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/block/blk-mq-tag.c	2016-07-24 15:23:50.000000000 -0400
@@ -464,15 +464,26 @@ static void bt_tags_for_each(struct blk_
 	}
 }
 
-void blk_mq_all_tag_busy_iter(struct blk_mq_tags *tags, busy_tag_iter_fn *fn,
-		void *priv)
+static void blk_mq_all_tag_busy_iter(struct blk_mq_tags *tags,
+		busy_tag_iter_fn *fn, void *priv)
 {
 	if (tags->nr_reserved_tags)
 		bt_tags_for_each(tags, &tags->breserved_tags, 0, fn, priv, true);
 	bt_tags_for_each(tags, &tags->bitmap_tags, tags->nr_reserved_tags, fn, priv,
 			false);
 }
-EXPORT_SYMBOL(blk_mq_all_tag_busy_iter);
+
+void blk_mq_tagset_busy_iter(struct blk_mq_tag_set *tagset,
+		busy_tag_iter_fn *fn, void *priv)
+{
+	int i;
+
+	for (i = 0; i < tagset->nr_hw_queues; i++) {
+		if (tagset->tags && tagset->tags[i])
+			blk_mq_all_tag_busy_iter(tagset->tags[i], fn, priv);
+	}
+}
+EXPORT_SYMBOL(blk_mq_tagset_busy_iter);
 
 void blk_mq_queue_tag_busy_iter(struct request_queue *q, busy_iter_fn *fn,
 		void *priv)
diff -druNp --no-dereference linux-libre-4.6-gnu/block/blk-settings.c linux-libre-4.7-gnu/block/blk-settings.c
--- linux-libre-4.6-gnu/block/blk-settings.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/block/blk-settings.c	2016-07-24 15:23:50.000000000 -0400
@@ -820,31 +820,39 @@ void blk_queue_update_dma_alignment(stru
 }
 EXPORT_SYMBOL(blk_queue_update_dma_alignment);
 
+void blk_queue_flush_queueable(struct request_queue *q, bool queueable)
+{
+	spin_lock_irq(q->queue_lock);
+	if (queueable)
+		clear_bit(QUEUE_FLAG_FLUSH_NQ, &q->queue_flags);
+	else
+		set_bit(QUEUE_FLAG_FLUSH_NQ, &q->queue_flags);
+	spin_unlock_irq(q->queue_lock);
+}
+EXPORT_SYMBOL_GPL(blk_queue_flush_queueable);
+
 /**
- * blk_queue_flush - configure queue's cache flush capability
+ * blk_queue_write_cache - configure queue's write cache
  * @q:		the request queue for the device
- * @flush:	0, REQ_FLUSH or REQ_FLUSH | REQ_FUA
+ * @wc:		write back cache on or off
+ * @fua:	device supports FUA writes, if true
  *
- * Tell block layer cache flush capability of @q.  If it supports
- * flushing, REQ_FLUSH should be set.  If it supports bypassing
- * write cache for individual writes, REQ_FUA should be set.
+ * Tell the block layer about the write cache of @q.
  */
-void blk_queue_flush(struct request_queue *q, unsigned int flush)
-{
-	WARN_ON_ONCE(flush & ~(REQ_FLUSH | REQ_FUA));
-
-	if (WARN_ON_ONCE(!(flush & REQ_FLUSH) && (flush & REQ_FUA)))
-		flush &= ~REQ_FUA;
-
-	q->flush_flags = flush & (REQ_FLUSH | REQ_FUA);
-}
-EXPORT_SYMBOL_GPL(blk_queue_flush);
-
-void blk_queue_flush_queueable(struct request_queue *q, bool queueable)
+void blk_queue_write_cache(struct request_queue *q, bool wc, bool fua)
 {
-	q->flush_not_queueable = !queueable;
+	spin_lock_irq(q->queue_lock);
+	if (wc)
+		queue_flag_set(QUEUE_FLAG_WC, q);
+	else
+		queue_flag_clear(QUEUE_FLAG_WC, q);
+	if (fua)
+		queue_flag_set(QUEUE_FLAG_FUA, q);
+	else
+		queue_flag_clear(QUEUE_FLAG_FUA, q);
+	spin_unlock_irq(q->queue_lock);
 }
-EXPORT_SYMBOL_GPL(blk_queue_flush_queueable);
+EXPORT_SYMBOL_GPL(blk_queue_write_cache);
 
 static int __init blk_settings_init(void)
 {
diff -druNp --no-dereference linux-libre-4.6-gnu/block/blk-sysfs.c linux-libre-4.7-gnu/block/blk-sysfs.c
--- linux-libre-4.6-gnu/block/blk-sysfs.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/block/blk-sysfs.c	2016-07-24 15:23:50.000000000 -0400
@@ -347,6 +347,38 @@ static ssize_t queue_poll_store(struct r
 	return ret;
 }
 
+static ssize_t queue_wc_show(struct request_queue *q, char *page)
+{
+	if (test_bit(QUEUE_FLAG_WC, &q->queue_flags))
+		return sprintf(page, "write back\n");
+
+	return sprintf(page, "write through\n");
+}
+
+static ssize_t queue_wc_store(struct request_queue *q, const char *page,
+			      size_t count)
+{
+	int set = -1;
+
+	if (!strncmp(page, "write back", 10))
+		set = 1;
+	else if (!strncmp(page, "write through", 13) ||
+		 !strncmp(page, "none", 4))
+		set = 0;
+
+	if (set == -1)
+		return -EINVAL;
+
+	spin_lock_irq(q->queue_lock);
+	if (set)
+		queue_flag_set(QUEUE_FLAG_WC, q);
+	else
+		queue_flag_clear(QUEUE_FLAG_WC, q);
+	spin_unlock_irq(q->queue_lock);
+
+	return count;
+}
+
 static struct queue_sysfs_entry queue_requests_entry = {
 	.attr = {.name = "nr_requests", .mode = S_IRUGO | S_IWUSR },
 	.show = queue_requests_show,
@@ -478,6 +510,12 @@ static struct queue_sysfs_entry queue_po
 	.store = queue_poll_store,
 };
 
+static struct queue_sysfs_entry queue_wc_entry = {
+	.attr = {.name = "write_cache", .mode = S_IRUGO | S_IWUSR },
+	.show = queue_wc_show,
+	.store = queue_wc_store,
+};
+
 static struct attribute *default_attrs[] = {
 	&queue_requests_entry.attr,
 	&queue_ra_entry.attr,
@@ -503,6 +541,7 @@ static struct attribute *default_attrs[]
 	&queue_iostats_entry.attr,
 	&queue_random_entry.attr,
 	&queue_poll_entry.attr,
+	&queue_wc_entry.attr,
 	NULL,
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/block/blk-throttle.c linux-libre-4.7-gnu/block/blk-throttle.c
--- linux-libre-4.6-gnu/block/blk-throttle.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/block/blk-throttle.c	2016-07-24 15:23:50.000000000 -0400
@@ -211,15 +211,14 @@ static struct throtl_data *sq_to_td(stru
  *
  * The messages are prefixed with "throtl BLKG_NAME" if @sq belongs to a
  * throtl_grp; otherwise, just "throtl".
- *
- * TODO: this should be made a function and name formatting should happen
- * after testing whether blktrace is enabled.
  */
 #define throtl_log(sq, fmt, args...)	do {				\
 	struct throtl_grp *__tg = sq_to_tg((sq));			\
 	struct throtl_data *__td = sq_to_td((sq));			\
 									\
 	(void)__td;							\
+	if (likely(!blk_trace_note_message_enabled(__td->queue)))	\
+		break;							\
 	if ((__tg)) {							\
 		char __pbuf[128];					\
 									\
diff -druNp --no-dereference linux-libre-4.6-gnu/block/ioctl.c linux-libre-4.7-gnu/block/ioctl.c
--- linux-libre-4.6-gnu/block/ioctl.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/block/ioctl.c	2016-07-24 15:23:50.000000000 -0400
@@ -4,7 +4,6 @@
 #include <linux/gfp.h>
 #include <linux/blkpg.h>
 #include <linux/hdreg.h>
-#include <linux/badblocks.h>
 #include <linux/backing-dev.h>
 #include <linux/fs.h>
 #include <linux/blktrace_api.h>
@@ -407,35 +406,6 @@ static inline int is_unrecognized_ioctl(
 		ret == -ENOIOCTLCMD;
 }
 
-#ifdef CONFIG_FS_DAX
-bool blkdev_dax_capable(struct block_device *bdev)
-{
-	struct gendisk *disk = bdev->bd_disk;
-
-	if (!disk->fops->direct_access)
-		return false;
-
-	/*
-	 * If the partition is not aligned on a page boundary, we can't
-	 * do dax I/O to it.
-	 */
-	if ((bdev->bd_part->start_sect % (PAGE_SIZE / 512))
-			|| (bdev->bd_part->nr_sects % (PAGE_SIZE / 512)))
-		return false;
-
-	/*
-	 * If the device has known bad blocks, force all I/O through the
-	 * driver / page cache.
-	 *
-	 * TODO: support finer grained dax error handling
-	 */
-	if (disk->bb && disk->bb->count)
-		return false;
-
-	return true;
-}
-#endif
-
 static int blkdev_flushbuf(struct block_device *bdev, fmode_t mode,
 		unsigned cmd, unsigned long arg)
 {
@@ -598,9 +568,6 @@ int blkdev_ioctl(struct block_device *bd
 	case BLKTRACESETUP:
 	case BLKTRACETEARDOWN:
 		return blk_trace_ioctl(bdev, cmd, argp);
-	case BLKDAXGET:
-		return put_int(arg, !!(bdev->bd_inode->i_flags & S_DAX));
-		break;
 	case IOC_PR_REGISTER:
 		return blkdev_pr_register(bdev, argp);
 	case IOC_PR_RESERVE:
diff -druNp --no-dereference linux-libre-4.6-gnu/block/ioprio.c linux-libre-4.7-gnu/block/ioprio.c
--- linux-libre-4.6-gnu/block/ioprio.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/block/ioprio.c	2016-07-24 15:23:50.000000000 -0400
@@ -150,8 +150,10 @@ static int get_task_ioprio(struct task_s
 	if (ret)
 		goto out;
 	ret = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_NONE, IOPRIO_NORM);
+	task_lock(p);
 	if (p->io_context)
 		ret = p->io_context->ioprio;
+	task_unlock(p);
 out:
 	return ret;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/block/partitions/efi.c linux-libre-4.7-gnu/block/partitions/efi.c
--- linux-libre-4.6-gnu/block/partitions/efi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/block/partitions/efi.c	2016-07-24 15:23:50.000000000 -0400
@@ -430,7 +430,7 @@ static int is_gpt_valid(struct parsed_pa
 	}
 	/* Check that sizeof_partition_entry has the correct value */
 	if (le32_to_cpu((*gpt)->sizeof_partition_entry) != sizeof(gpt_entry)) {
-		pr_debug("GUID Partitition Entry Size check failed.\n");
+		pr_debug("GUID Partition Entry Size check failed.\n");
 		goto fail;
 	}
 
@@ -443,7 +443,7 @@ static int is_gpt_valid(struct parsed_pa
 			le32_to_cpu((*gpt)->sizeof_partition_entry));
 
 	if (crc != le32_to_cpu((*gpt)->partition_entry_array_crc32)) {
-		pr_debug("GUID Partitition Entry Array CRC check failed.\n");
+		pr_debug("GUID Partition Entry Array CRC check failed.\n");
 		goto fail_ptes;
 	}
 
diff -druNp --no-dereference linux-libre-4.6-gnu/block/partitions/ldm.c linux-libre-4.7-gnu/block/partitions/ldm.c
--- linux-libre-4.6-gnu/block/partitions/ldm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/block/partitions/ldm.c	2016-07-24 15:23:50.000000000 -0400
@@ -27,6 +27,8 @@
 #include <linux/pagemap.h>
 #include <linux/stringify.h>
 #include <linux/kernel.h>
+#include <linux/uuid.h>
+
 #include "ldm.h"
 #include "check.h"
 #include "msdos.h"
@@ -66,60 +68,6 @@ void _ldm_printk(const char *level, cons
 }
 
 /**
- * ldm_parse_hexbyte - Convert a ASCII hex number to a byte
- * @src:  Pointer to at least 2 characters to convert.
- *
- * Convert a two character ASCII hex string to a number.
- *
- * Return:  0-255  Success, the byte was parsed correctly
- *          -1     Error, an invalid character was supplied
- */
-static int ldm_parse_hexbyte (const u8 *src)
-{
-	unsigned int x;		/* For correct wrapping */
-	int h;
-
-	/* high part */
-	x = h = hex_to_bin(src[0]);
-	if (h < 0)
-		return -1;
-
-	/* low part */
-	h = hex_to_bin(src[1]);
-	if (h < 0)
-		return -1;
-
-	return (x << 4) + h;
-}
-
-/**
- * ldm_parse_guid - Convert GUID from ASCII to binary
- * @src:   36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
- * @dest:  Memory block to hold binary GUID (16 bytes)
- *
- * N.B. The GUID need not be NULL terminated.
- *
- * Return:  'true'   @dest contains binary GUID
- *          'false'  @dest contents are undefined
- */
-static bool ldm_parse_guid (const u8 *src, u8 *dest)
-{
-	static const int size[] = { 4, 2, 2, 2, 6 };
-	int i, j, v;
-
-	if (src[8]  != '-' || src[13] != '-' ||
-	    src[18] != '-' || src[23] != '-')
-		return false;
-
-	for (j = 0; j < 5; j++, src++)
-		for (i = 0; i < size[j]; i++, src+=2, *dest++ = v)
-			if ((v = ldm_parse_hexbyte (src)) < 0)
-				return false;
-
-	return true;
-}
-
-/**
  * ldm_parse_privhead - Read the LDM Database PRIVHEAD structure
  * @data:  Raw database PRIVHEAD structure loaded from the device
  * @ph:    In-memory privhead structure in which to return parsed information
@@ -167,7 +115,7 @@ static bool ldm_parse_privhead(const u8
 		ldm_error("PRIVHEAD disk size doesn't match real disk size");
 		return false;
 	}
-	if (!ldm_parse_guid(data + 0x0030, ph->disk_id)) {
+	if (uuid_be_to_bin(data + 0x0030, (uuid_be *)ph->disk_id)) {
 		ldm_error("PRIVHEAD contains an invalid GUID.");
 		return false;
 	}
@@ -944,7 +892,7 @@ static bool ldm_parse_dsk3 (const u8 *bu
 	disk = &vb->vblk.disk;
 	ldm_get_vstr (buffer + 0x18 + r_diskid, disk->alt_name,
 		sizeof (disk->alt_name));
-	if (!ldm_parse_guid (buffer + 0x19 + r_name, disk->disk_id))
+	if (uuid_be_to_bin(buffer + 0x19 + r_name, (uuid_be *)disk->disk_id))
 		return false;
 
 	return true;
diff -druNp --no-dereference linux-libre-4.6-gnu/certs/Kconfig linux-libre-4.7-gnu/certs/Kconfig
--- linux-libre-4.6-gnu/certs/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/certs/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -17,6 +17,7 @@ config MODULE_SIG_KEY
 config SYSTEM_TRUSTED_KEYRING
 	bool "Provide system-wide ring of trusted keys"
 	depends on KEYS
+	depends on ASYMMETRIC_KEY_TYPE
 	help
 	  Provide a system keyring to which trusted keys can be added.  Keys in
 	  the keyring are considered to be trusted.  Keys may be added at will
@@ -55,4 +56,12 @@ config SYSTEM_EXTRA_CERTIFICATE_SIZE
 	  This is the number of bytes reserved in the kernel image for a
 	  certificate to be inserted.
 
+config SECONDARY_TRUSTED_KEYRING
+	bool "Provide a keyring to which extra trustable keys may be added"
+	depends on SYSTEM_TRUSTED_KEYRING
+	help
+	  If set, provide a keyring to which extra keys may be added, provided
+	  those keys are not blacklisted and are vouched for by a key built
+	  into the kernel or already in the secondary trusted keyring.
+
 endmenu
diff -druNp --no-dereference linux-libre-4.6-gnu/certs/system_keyring.c linux-libre-4.7-gnu/certs/system_keyring.c
--- linux-libre-4.6-gnu/certs/system_keyring.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/certs/system_keyring.c	2016-07-24 15:23:50.000000000 -0400
@@ -18,29 +18,88 @@
 #include <keys/system_keyring.h>
 #include <crypto/pkcs7.h>
 
-struct key *system_trusted_keyring;
-EXPORT_SYMBOL_GPL(system_trusted_keyring);
+static struct key *builtin_trusted_keys;
+#ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
+static struct key *secondary_trusted_keys;
+#endif
 
 extern __initconst const u8 system_certificate_list[];
 extern __initconst const unsigned long system_certificate_list_size;
 
+/**
+ * restrict_link_to_builtin_trusted - Restrict keyring addition by built in CA
+ *
+ * Restrict the addition of keys into a keyring based on the key-to-be-added
+ * being vouched for by a key in the built in system keyring.
+ */
+int restrict_link_by_builtin_trusted(struct key *keyring,
+				     const struct key_type *type,
+				     const union key_payload *payload)
+{
+	return restrict_link_by_signature(builtin_trusted_keys, type, payload);
+}
+
+#ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
+/**
+ * restrict_link_by_builtin_and_secondary_trusted - Restrict keyring
+ *   addition by both builtin and secondary keyrings
+ *
+ * Restrict the addition of keys into a keyring based on the key-to-be-added
+ * being vouched for by a key in either the built-in or the secondary system
+ * keyrings.
+ */
+int restrict_link_by_builtin_and_secondary_trusted(
+	struct key *keyring,
+	const struct key_type *type,
+	const union key_payload *payload)
+{
+	/* If we have a secondary trusted keyring, then that contains a link
+	 * through to the builtin keyring and the search will follow that link.
+	 */
+	if (type == &key_type_keyring &&
+	    keyring == secondary_trusted_keys &&
+	    payload == &builtin_trusted_keys->payload)
+		/* Allow the builtin keyring to be added to the secondary */
+		return 0;
+
+	return restrict_link_by_signature(secondary_trusted_keys, type, payload);
+}
+#endif
+
 /*
- * Load the compiled-in keys
+ * Create the trusted keyrings
  */
 static __init int system_trusted_keyring_init(void)
 {
-	pr_notice("Initialise system trusted keyring\n");
+	pr_notice("Initialise system trusted keyrings\n");
 
-	system_trusted_keyring =
-		keyring_alloc(".system_keyring",
+	builtin_trusted_keys =
+		keyring_alloc(".builtin_trusted_keys",
 			      KUIDT_INIT(0), KGIDT_INIT(0), current_cred(),
 			      ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
 			      KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH),
-			      KEY_ALLOC_NOT_IN_QUOTA, NULL);
-	if (IS_ERR(system_trusted_keyring))
-		panic("Can't allocate system trusted keyring\n");
+			      KEY_ALLOC_NOT_IN_QUOTA,
+			      NULL, NULL);
+	if (IS_ERR(builtin_trusted_keys))
+		panic("Can't allocate builtin trusted keyring\n");
+
+#ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
+	secondary_trusted_keys =
+		keyring_alloc(".secondary_trusted_keys",
+			      KUIDT_INIT(0), KGIDT_INIT(0), current_cred(),
+			      ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
+			       KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH |
+			       KEY_USR_WRITE),
+			      KEY_ALLOC_NOT_IN_QUOTA,
+			      restrict_link_by_builtin_and_secondary_trusted,
+			      NULL);
+	if (IS_ERR(secondary_trusted_keys))
+		panic("Can't allocate secondary trusted keyring\n");
+
+	if (key_link(secondary_trusted_keys, builtin_trusted_keys) < 0)
+		panic("Can't link trusted keyrings\n");
+#endif
 
-	set_bit(KEY_FLAG_TRUSTED_ONLY, &system_trusted_keyring->flags);
 	return 0;
 }
 
@@ -76,7 +135,7 @@ static __init int load_system_certificat
 		if (plen > end - p)
 			goto dodgy_cert;
 
-		key = key_create_or_update(make_key_ref(system_trusted_keyring, 1),
+		key = key_create_or_update(make_key_ref(builtin_trusted_keys, 1),
 					   "asymmetric",
 					   NULL,
 					   p,
@@ -84,8 +143,8 @@ static __init int load_system_certificat
 					   ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
 					   KEY_USR_VIEW | KEY_USR_READ),
 					   KEY_ALLOC_NOT_IN_QUOTA |
-					   KEY_ALLOC_TRUSTED |
-					   KEY_ALLOC_BUILT_IN);
+					   KEY_ALLOC_BUILT_IN |
+					   KEY_ALLOC_BYPASS_RESTRICTION);
 		if (IS_ERR(key)) {
 			pr_err("Problem loading in-kernel X.509 certificate (%ld)\n",
 			       PTR_ERR(key));
@@ -108,19 +167,27 @@ late_initcall(load_system_certificate_li
 #ifdef CONFIG_SYSTEM_DATA_VERIFICATION
 
 /**
- * Verify a PKCS#7-based signature on system data.
- * @data: The data to be verified.
+ * verify_pkcs7_signature - Verify a PKCS#7-based signature on system data.
+ * @data: The data to be verified (NULL if expecting internal data).
  * @len: Size of @data.
  * @raw_pkcs7: The PKCS#7 message that is the signature.
  * @pkcs7_len: The size of @raw_pkcs7.
+ * @trusted_keys: Trusted keys to use (NULL for builtin trusted keys only,
+ *					(void *)1UL for all trusted keys).
  * @usage: The use to which the key is being put.
+ * @view_content: Callback to gain access to content.
+ * @ctx: Context for callback.
  */
-int system_verify_data(const void *data, unsigned long len,
-		       const void *raw_pkcs7, size_t pkcs7_len,
-		       enum key_being_used_for usage)
+int verify_pkcs7_signature(const void *data, size_t len,
+			   const void *raw_pkcs7, size_t pkcs7_len,
+			   struct key *trusted_keys,
+			   enum key_being_used_for usage,
+			   int (*view_content)(void *ctx,
+					       const void *data, size_t len,
+					       size_t asn1hdrlen),
+			   void *ctx)
 {
 	struct pkcs7_message *pkcs7;
-	bool trusted;
 	int ret;
 
 	pkcs7 = pkcs7_parse_message(raw_pkcs7, pkcs7_len);
@@ -128,7 +195,7 @@ int system_verify_data(const void *data,
 		return PTR_ERR(pkcs7);
 
 	/* The data should be detached - so we need to supply it. */
-	if (pkcs7_supply_detached_data(pkcs7, data, len) < 0) {
+	if (data && pkcs7_supply_detached_data(pkcs7, data, len) < 0) {
 		pr_err("PKCS#7 signature with non-detached data\n");
 		ret = -EBADMSG;
 		goto error;
@@ -138,13 +205,33 @@ int system_verify_data(const void *data,
 	if (ret < 0)
 		goto error;
 
-	ret = pkcs7_validate_trust(pkcs7, system_trusted_keyring, &trusted);
-	if (ret < 0)
+	if (!trusted_keys) {
+		trusted_keys = builtin_trusted_keys;
+	} else if (trusted_keys == (void *)1UL) {
+#ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
+		trusted_keys = secondary_trusted_keys;
+#else
+		trusted_keys = builtin_trusted_keys;
+#endif
+	}
+	ret = pkcs7_validate_trust(pkcs7, trusted_keys);
+	if (ret < 0) {
+		if (ret == -ENOKEY)
+			pr_err("PKCS#7 signature not signed with a trusted key\n");
 		goto error;
+	}
 
-	if (!trusted) {
-		pr_err("PKCS#7 signature not signed with a trusted key\n");
-		ret = -ENOKEY;
+	if (view_content) {
+		size_t asn1hdrlen;
+
+		ret = pkcs7_get_content_data(pkcs7, &data, &len, &asn1hdrlen);
+		if (ret < 0) {
+			if (ret == -ENODATA)
+				pr_devel("PKCS#7 message does not contain data\n");
+			goto error;
+		}
+
+		ret = view_content(ctx, data, len, asn1hdrlen);
 	}
 
 error:
@@ -152,6 +239,6 @@ error:
 	pr_devel("<==%s() = %d\n", __func__, ret);
 	return ret;
 }
-EXPORT_SYMBOL_GPL(system_verify_data);
+EXPORT_SYMBOL_GPL(verify_pkcs7_signature);
 
 #endif /* CONFIG_SYSTEM_DATA_VERIFICATION */
diff -druNp --no-dereference linux-libre-4.6-gnu/CREDITS linux-libre-4.7-gnu/CREDITS
--- linux-libre-4.6-gnu/CREDITS	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/CREDITS	2016-07-24 15:23:50.000000000 -0400
@@ -649,6 +649,7 @@ D: Configure, Menuconfig, xconfig
 
 N: Mauro Carvalho Chehab
 E: m.chehab@samsung.org
+E: mchehab@osg.samsung.com
 E: mchehab@infradead.org
 D: Media subsystem (V4L/DVB) drivers and core
 D: EDAC drivers and EDAC 3.0 core rework
@@ -768,6 +769,7 @@ D: Z85230 driver
 D: Former security contact point (please use vendor-sec@lst.de)
 D: ex 2.2 maintainer
 D: 2.1.x modular sound
+D: Assigned major/minor numbers maintainer at lanana.org
 S: c/o Red Hat UK Ltd
 S: Alexandra House
 S: Alexandra Terrace
diff -druNp --no-dereference linux-libre-4.6-gnu/crypto/algif_aead.c linux-libre-4.7-gnu/crypto/algif_aead.c
--- linux-libre-4.6-gnu/crypto/algif_aead.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/crypto/algif_aead.c	2016-07-24 15:23:50.000000000 -0400
@@ -13,7 +13,7 @@
  * any later version.
  */
 
-#include <crypto/aead.h>
+#include <crypto/internal/aead.h>
 #include <crypto/scatterwalk.h>
 #include <crypto/if_alg.h>
 #include <linux/init.h>
@@ -29,15 +29,24 @@ struct aead_sg_list {
 	struct scatterlist sg[ALG_MAX_PAGES];
 };
 
+struct aead_async_rsgl {
+	struct af_alg_sgl sgl;
+	struct list_head list;
+};
+
+struct aead_async_req {
+	struct scatterlist *tsgl;
+	struct aead_async_rsgl first_rsgl;
+	struct list_head list;
+	struct kiocb *iocb;
+	unsigned int tsgls;
+	char iv[];
+};
+
 struct aead_ctx {
 	struct aead_sg_list tsgl;
-	/*
-	 * RSGL_MAX_ENTRIES is an artificial limit where user space at maximum
-	 * can cause the kernel to allocate RSGL_MAX_ENTRIES * ALG_MAX_PAGES
-	 * pages
-	 */
-#define RSGL_MAX_ENTRIES ALG_MAX_PAGES
-	struct af_alg_sgl rsgl[RSGL_MAX_ENTRIES];
+	struct aead_async_rsgl first_rsgl;
+	struct list_head list;
 
 	void *iv;
 
@@ -75,6 +84,17 @@ static inline bool aead_sufficient_data(
 	return ctx->used >= ctx->aead_assoclen + as;
 }
 
+static void aead_reset_ctx(struct aead_ctx *ctx)
+{
+	struct aead_sg_list *sgl = &ctx->tsgl;
+
+	sg_init_table(sgl->sg, ALG_MAX_PAGES);
+	sgl->cur = 0;
+	ctx->used = 0;
+	ctx->more = 0;
+	ctx->merge = 0;
+}
+
 static void aead_put_sgl(struct sock *sk)
 {
 	struct alg_sock *ask = alg_sk(sk);
@@ -90,11 +110,7 @@ static void aead_put_sgl(struct sock *sk
 		put_page(sg_page(sg + i));
 		sg_assign_page(sg + i, NULL);
 	}
-	sg_init_table(sg, ALG_MAX_PAGES);
-	sgl->cur = 0;
-	ctx->used = 0;
-	ctx->more = 0;
-	ctx->merge = 0;
+	aead_reset_ctx(ctx);
 }
 
 static void aead_wmem_wakeup(struct sock *sk)
@@ -349,23 +365,188 @@ unlock:
 	return err ?: size;
 }
 
-static int aead_recvmsg(struct socket *sock, struct msghdr *msg, size_t ignored, int flags)
+#define GET_ASYM_REQ(req, tfm) (struct aead_async_req *) \
+		((char *)req + sizeof(struct aead_request) + \
+		 crypto_aead_reqsize(tfm))
+
+ #define GET_REQ_SIZE(tfm) sizeof(struct aead_async_req) + \
+	crypto_aead_reqsize(tfm) + crypto_aead_ivsize(tfm) + \
+	sizeof(struct aead_request)
+
+static void aead_async_cb(struct crypto_async_request *_req, int err)
+{
+	struct sock *sk = _req->data;
+	struct alg_sock *ask = alg_sk(sk);
+	struct aead_ctx *ctx = ask->private;
+	struct crypto_aead *tfm = crypto_aead_reqtfm(&ctx->aead_req);
+	struct aead_request *req = aead_request_cast(_req);
+	struct aead_async_req *areq = GET_ASYM_REQ(req, tfm);
+	struct scatterlist *sg = areq->tsgl;
+	struct aead_async_rsgl *rsgl;
+	struct kiocb *iocb = areq->iocb;
+	unsigned int i, reqlen = GET_REQ_SIZE(tfm);
+
+	list_for_each_entry(rsgl, &areq->list, list) {
+		af_alg_free_sg(&rsgl->sgl);
+		if (rsgl != &areq->first_rsgl)
+			sock_kfree_s(sk, rsgl, sizeof(*rsgl));
+	}
+
+	for (i = 0; i < areq->tsgls; i++)
+		put_page(sg_page(sg + i));
+
+	sock_kfree_s(sk, areq->tsgl, sizeof(*areq->tsgl) * areq->tsgls);
+	sock_kfree_s(sk, req, reqlen);
+	__sock_put(sk);
+	iocb->ki_complete(iocb, err, err);
+}
+
+static int aead_recvmsg_async(struct socket *sock, struct msghdr *msg,
+			      int flags)
+{
+	struct sock *sk = sock->sk;
+	struct alg_sock *ask = alg_sk(sk);
+	struct aead_ctx *ctx = ask->private;
+	struct crypto_aead *tfm = crypto_aead_reqtfm(&ctx->aead_req);
+	struct aead_async_req *areq;
+	struct aead_request *req = NULL;
+	struct aead_sg_list *sgl = &ctx->tsgl;
+	struct aead_async_rsgl *last_rsgl = NULL, *rsgl;
+	unsigned int as = crypto_aead_authsize(tfm);
+	unsigned int i, reqlen = GET_REQ_SIZE(tfm);
+	int err = -ENOMEM;
+	unsigned long used;
+	size_t outlen;
+	size_t usedpages = 0;
+
+	lock_sock(sk);
+	if (ctx->more) {
+		err = aead_wait_for_data(sk, flags);
+		if (err)
+			goto unlock;
+	}
+
+	used = ctx->used;
+	outlen = used;
+
+	if (!aead_sufficient_data(ctx))
+		goto unlock;
+
+	req = sock_kmalloc(sk, reqlen, GFP_KERNEL);
+	if (unlikely(!req))
+		goto unlock;
+
+	areq = GET_ASYM_REQ(req, tfm);
+	memset(&areq->first_rsgl, '\0', sizeof(areq->first_rsgl));
+	INIT_LIST_HEAD(&areq->list);
+	areq->iocb = msg->msg_iocb;
+	memcpy(areq->iv, ctx->iv, crypto_aead_ivsize(tfm));
+	aead_request_set_tfm(req, tfm);
+	aead_request_set_ad(req, ctx->aead_assoclen);
+	aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+				  aead_async_cb, sk);
+	used -= ctx->aead_assoclen + (ctx->enc ? as : 0);
+
+	/* take over all tx sgls from ctx */
+	areq->tsgl = sock_kmalloc(sk, sizeof(*areq->tsgl) * sgl->cur,
+				  GFP_KERNEL);
+	if (unlikely(!areq->tsgl))
+		goto free;
+
+	sg_init_table(areq->tsgl, sgl->cur);
+	for (i = 0; i < sgl->cur; i++)
+		sg_set_page(&areq->tsgl[i], sg_page(&sgl->sg[i]),
+			    sgl->sg[i].length, sgl->sg[i].offset);
+
+	areq->tsgls = sgl->cur;
+
+	/* create rx sgls */
+	while (iov_iter_count(&msg->msg_iter)) {
+		size_t seglen = min_t(size_t, iov_iter_count(&msg->msg_iter),
+				      (outlen - usedpages));
+
+		if (list_empty(&areq->list)) {
+			rsgl = &areq->first_rsgl;
+
+		} else {
+			rsgl = sock_kmalloc(sk, sizeof(*rsgl), GFP_KERNEL);
+			if (unlikely(!rsgl)) {
+				err = -ENOMEM;
+				goto free;
+			}
+		}
+		rsgl->sgl.npages = 0;
+		list_add_tail(&rsgl->list, &areq->list);
+
+		/* make one iovec available as scatterlist */
+		err = af_alg_make_sg(&rsgl->sgl, &msg->msg_iter, seglen);
+		if (err < 0)
+			goto free;
+
+		usedpages += err;
+
+		/* chain the new scatterlist with previous one */
+		if (last_rsgl)
+			af_alg_link_sg(&last_rsgl->sgl, &rsgl->sgl);
+
+		last_rsgl = rsgl;
+
+		/* we do not need more iovecs as we have sufficient memory */
+		if (outlen <= usedpages)
+			break;
+
+		iov_iter_advance(&msg->msg_iter, err);
+	}
+	err = -EINVAL;
+	/* ensure output buffer is sufficiently large */
+	if (usedpages < outlen)
+		goto free;
+
+	aead_request_set_crypt(req, areq->tsgl, areq->first_rsgl.sgl.sg, used,
+			       areq->iv);
+	err = ctx->enc ? crypto_aead_encrypt(req) : crypto_aead_decrypt(req);
+	if (err) {
+		if (err == -EINPROGRESS) {
+			sock_hold(sk);
+			err = -EIOCBQUEUED;
+			aead_reset_ctx(ctx);
+			goto unlock;
+		} else if (err == -EBADMSG) {
+			aead_put_sgl(sk);
+		}
+		goto free;
+	}
+	aead_put_sgl(sk);
+
+free:
+	list_for_each_entry(rsgl, &areq->list, list) {
+		af_alg_free_sg(&rsgl->sgl);
+		if (rsgl != &areq->first_rsgl)
+			sock_kfree_s(sk, rsgl, sizeof(*rsgl));
+	}
+	if (areq->tsgl)
+		sock_kfree_s(sk, areq->tsgl, sizeof(*areq->tsgl) * areq->tsgls);
+	if (req)
+		sock_kfree_s(sk, req, reqlen);
+unlock:
+	aead_wmem_wakeup(sk);
+	release_sock(sk);
+	return err ? err : outlen;
+}
+
+static int aead_recvmsg_sync(struct socket *sock, struct msghdr *msg, int flags)
 {
 	struct sock *sk = sock->sk;
 	struct alg_sock *ask = alg_sk(sk);
 	struct aead_ctx *ctx = ask->private;
 	unsigned as = crypto_aead_authsize(crypto_aead_reqtfm(&ctx->aead_req));
 	struct aead_sg_list *sgl = &ctx->tsgl;
-	unsigned int i = 0;
+	struct aead_async_rsgl *last_rsgl = NULL;
+	struct aead_async_rsgl *rsgl, *tmp;
 	int err = -EINVAL;
 	unsigned long used = 0;
 	size_t outlen = 0;
 	size_t usedpages = 0;
-	unsigned int cnt = 0;
-
-	/* Limit number of IOV blocks to be accessed below */
-	if (msg->msg_iter.nr_segs > RSGL_MAX_ENTRIES)
-		return -ENOMSG;
 
 	lock_sock(sk);
 
@@ -417,21 +598,33 @@ static int aead_recvmsg(struct socket *s
 		size_t seglen = min_t(size_t, iov_iter_count(&msg->msg_iter),
 				      (outlen - usedpages));
 
+		if (list_empty(&ctx->list)) {
+			rsgl = &ctx->first_rsgl;
+		} else {
+			rsgl = sock_kmalloc(sk, sizeof(*rsgl), GFP_KERNEL);
+			if (unlikely(!rsgl)) {
+				err = -ENOMEM;
+				goto unlock;
+			}
+		}
+		rsgl->sgl.npages = 0;
+		list_add_tail(&rsgl->list, &ctx->list);
+
 		/* make one iovec available as scatterlist */
-		err = af_alg_make_sg(&ctx->rsgl[cnt], &msg->msg_iter,
-				     seglen);
+		err = af_alg_make_sg(&rsgl->sgl, &msg->msg_iter, seglen);
 		if (err < 0)
 			goto unlock;
 		usedpages += err;
 		/* chain the new scatterlist with previous one */
-		if (cnt)
-			af_alg_link_sg(&ctx->rsgl[cnt-1], &ctx->rsgl[cnt]);
+		if (last_rsgl)
+			af_alg_link_sg(&last_rsgl->sgl, &rsgl->sgl);
+
+		last_rsgl = rsgl;
 
 		/* we do not need more iovecs as we have sufficient memory */
 		if (outlen <= usedpages)
 			break;
 		iov_iter_advance(&msg->msg_iter, err);
-		cnt++;
 	}
 
 	err = -EINVAL;
@@ -440,8 +633,7 @@ static int aead_recvmsg(struct socket *s
 		goto unlock;
 
 	sg_mark_end(sgl->sg + sgl->cur - 1);
-
-	aead_request_set_crypt(&ctx->aead_req, sgl->sg, ctx->rsgl[0].sg,
+	aead_request_set_crypt(&ctx->aead_req, sgl->sg, ctx->first_rsgl.sgl.sg,
 			       used, ctx->iv);
 	aead_request_set_ad(&ctx->aead_req, ctx->aead_assoclen);
 
@@ -454,23 +646,35 @@ static int aead_recvmsg(struct socket *s
 		/* EBADMSG implies a valid cipher operation took place */
 		if (err == -EBADMSG)
 			aead_put_sgl(sk);
+
 		goto unlock;
 	}
 
 	aead_put_sgl(sk);
-
 	err = 0;
 
 unlock:
-	for (i = 0; i < cnt; i++)
-		af_alg_free_sg(&ctx->rsgl[i]);
-
+	list_for_each_entry_safe(rsgl, tmp, &ctx->list, list) {
+		af_alg_free_sg(&rsgl->sgl);
+		if (rsgl != &ctx->first_rsgl)
+			sock_kfree_s(sk, rsgl, sizeof(*rsgl));
+		list_del(&rsgl->list);
+	}
+	INIT_LIST_HEAD(&ctx->list);
 	aead_wmem_wakeup(sk);
 	release_sock(sk);
 
 	return err ? err : outlen;
 }
 
+static int aead_recvmsg(struct socket *sock, struct msghdr *msg, size_t ignored,
+			int flags)
+{
+	return (msg->msg_iocb && !is_sync_kiocb(msg->msg_iocb)) ?
+		aead_recvmsg_async(sock, msg, flags) :
+		aead_recvmsg_sync(sock, msg, flags);
+}
+
 static unsigned int aead_poll(struct file *file, struct socket *sock,
 			      poll_table *wait)
 {
@@ -540,6 +744,7 @@ static void aead_sock_destruct(struct so
 	unsigned int ivlen = crypto_aead_ivsize(
 				crypto_aead_reqtfm(&ctx->aead_req));
 
+	WARN_ON(atomic_read(&sk->sk_refcnt) != 0);
 	aead_put_sgl(sk);
 	sock_kzfree_s(sk, ctx->iv, ivlen);
 	sock_kfree_s(sk, ctx, ctx->len);
@@ -574,6 +779,7 @@ static int aead_accept_parent(void *priv
 	ctx->aead_assoclen = 0;
 	af_alg_init_completion(&ctx->completion);
 	sg_init_table(ctx->tsgl.sg, ALG_MAX_PAGES);
+	INIT_LIST_HEAD(&ctx->list);
 
 	ask->private = ctx;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/crypto/asymmetric_keys/asymmetric_keys.h linux-libre-4.7-gnu/crypto/asymmetric_keys/asymmetric_keys.h
--- linux-libre-4.6-gnu/crypto/asymmetric_keys/asymmetric_keys.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/crypto/asymmetric_keys/asymmetric_keys.h	2016-07-24 15:23:50.000000000 -0400
@@ -9,6 +9,8 @@
  * 2 of the Licence, or (at your option) any later version.
  */
 
+#include <keys/asymmetric-type.h>
+
 extern struct asymmetric_key_id *asymmetric_key_hex_to_key_id(const char *id);
 
 extern int __asymmetric_key_hex_to_key_id(const char *id,
diff -druNp --no-dereference linux-libre-4.6-gnu/crypto/asymmetric_keys/asymmetric_type.c linux-libre-4.7-gnu/crypto/asymmetric_keys/asymmetric_type.c
--- linux-libre-4.6-gnu/crypto/asymmetric_keys/asymmetric_type.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/crypto/asymmetric_keys/asymmetric_type.c	2016-07-24 15:23:50.000000000 -0400
@@ -35,6 +35,95 @@ static LIST_HEAD(asymmetric_key_parsers)
 static DECLARE_RWSEM(asymmetric_key_parsers_sem);
 
 /**
+ * find_asymmetric_key - Find a key by ID.
+ * @keyring: The keys to search.
+ * @id_0: The first ID to look for or NULL.
+ * @id_1: The second ID to look for or NULL.
+ * @partial: Use partial match if true, exact if false.
+ *
+ * Find a key in the given keyring by identifier.  The preferred identifier is
+ * the id_0 and the fallback identifier is the id_1.  If both are given, the
+ * lookup is by the former, but the latter must also match.
+ */
+struct key *find_asymmetric_key(struct key *keyring,
+				const struct asymmetric_key_id *id_0,
+				const struct asymmetric_key_id *id_1,
+				bool partial)
+{
+	struct key *key;
+	key_ref_t ref;
+	const char *lookup;
+	char *req, *p;
+	int len;
+
+	if (id_0) {
+		lookup = id_0->data;
+		len = id_0->len;
+	} else {
+		lookup = id_1->data;
+		len = id_1->len;
+	}
+
+	/* Construct an identifier "id:<keyid>". */
+	p = req = kmalloc(2 + 1 + len * 2 + 1, GFP_KERNEL);
+	if (!req)
+		return ERR_PTR(-ENOMEM);
+
+	if (partial) {
+		*p++ = 'i';
+		*p++ = 'd';
+	} else {
+		*p++ = 'e';
+		*p++ = 'x';
+	}
+	*p++ = ':';
+	p = bin2hex(p, lookup, len);
+	*p = 0;
+
+	pr_debug("Look up: \"%s\"\n", req);
+
+	ref = keyring_search(make_key_ref(keyring, 1),
+			     &key_type_asymmetric, req);
+	if (IS_ERR(ref))
+		pr_debug("Request for key '%s' err %ld\n", req, PTR_ERR(ref));
+	kfree(req);
+
+	if (IS_ERR(ref)) {
+		switch (PTR_ERR(ref)) {
+			/* Hide some search errors */
+		case -EACCES:
+		case -ENOTDIR:
+		case -EAGAIN:
+			return ERR_PTR(-ENOKEY);
+		default:
+			return ERR_CAST(ref);
+		}
+	}
+
+	key = key_ref_to_ptr(ref);
+	if (id_0 && id_1) {
+		const struct asymmetric_key_ids *kids = asymmetric_key_ids(key);
+
+		if (!kids->id[0]) {
+			pr_debug("First ID matches, but second is missing\n");
+			goto reject;
+		}
+		if (!asymmetric_key_id_same(id_1, kids->id[1])) {
+			pr_debug("First ID matches, but second does not\n");
+			goto reject;
+		}
+	}
+
+	pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key));
+	return key;
+
+reject:
+	key_put(key);
+	return ERR_PTR(-EKEYREJECTED);
+}
+EXPORT_SYMBOL_GPL(find_asymmetric_key);
+
+/**
  * asymmetric_key_generate_id: Construct an asymmetric key ID
  * @val_1: First binary blob
  * @len_1: Length of first binary blob
@@ -331,7 +420,8 @@ static void asymmetric_key_free_preparse
 	pr_devel("==>%s()\n", __func__);
 
 	if (subtype) {
-		subtype->destroy(prep->payload.data[asym_crypto]);
+		subtype->destroy(prep->payload.data[asym_crypto],
+				 prep->payload.data[asym_auth]);
 		module_put(subtype->owner);
 	}
 	asymmetric_key_free_kids(kids);
@@ -346,13 +436,15 @@ static void asymmetric_key_destroy(struc
 	struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key);
 	struct asymmetric_key_ids *kids = key->payload.data[asym_key_ids];
 	void *data = key->payload.data[asym_crypto];
+	void *auth = key->payload.data[asym_auth];
 
 	key->payload.data[asym_crypto] = NULL;
 	key->payload.data[asym_subtype] = NULL;
 	key->payload.data[asym_key_ids] = NULL;
+	key->payload.data[asym_auth] = NULL;
 
 	if (subtype) {
-		subtype->destroy(data);
+		subtype->destroy(data, auth);
 		module_put(subtype->owner);
 	}
 
diff -druNp --no-dereference linux-libre-4.6-gnu/crypto/asymmetric_keys/Kconfig linux-libre-4.7-gnu/crypto/asymmetric_keys/Kconfig
--- linux-libre-4.6-gnu/crypto/asymmetric_keys/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/crypto/asymmetric_keys/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -1,5 +1,5 @@
 menuconfig ASYMMETRIC_KEY_TYPE
-	tristate "Asymmetric (public-key cryptographic) key type"
+	bool "Asymmetric (public-key cryptographic) key type"
 	depends on KEYS
 	help
 	  This option provides support for a key type that holds the data for
@@ -13,6 +13,7 @@ config ASYMMETRIC_PUBLIC_KEY_SUBTYPE
 	tristate "Asymmetric public-key crypto algorithm subtype"
 	select MPILIB
 	select CRYPTO_HASH_INFO
+	select CRYPTO_AKCIPHER
 	help
 	  This option provides support for asymmetric public key type handling.
 	  If signature generation and/or verification are to be used,
@@ -40,8 +41,7 @@ config PKCS7_MESSAGE_PARSER
 
 config PKCS7_TEST_KEY
 	tristate "PKCS#7 testing key type"
-	depends on PKCS7_MESSAGE_PARSER
-	select SYSTEM_TRUSTED_KEYRING
+	depends on SYSTEM_DATA_VERIFICATION
 	help
 	  This option provides a type of key that can be loaded up from a
 	  PKCS#7 message - provided the message is signed by a trusted key.  If
@@ -54,6 +54,7 @@ config PKCS7_TEST_KEY
 config SIGNED_PE_FILE_VERIFICATION
 	bool "Support for PE file signature verification"
 	depends on PKCS7_MESSAGE_PARSER=y
+	depends on SYSTEM_DATA_VERIFICATION
 	select ASN1
 	select OID_REGISTRY
 	help
diff -druNp --no-dereference linux-libre-4.6-gnu/crypto/asymmetric_keys/Makefile linux-libre-4.7-gnu/crypto/asymmetric_keys/Makefile
--- linux-libre-4.6-gnu/crypto/asymmetric_keys/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/crypto/asymmetric_keys/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -4,7 +4,10 @@
 
 obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
 
-asymmetric_keys-y := asymmetric_type.o signature.o
+asymmetric_keys-y := \
+	asymmetric_type.o \
+	restrict.o \
+	signature.o
 
 obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o
 
diff -druNp --no-dereference linux-libre-4.6-gnu/crypto/asymmetric_keys/mscode_parser.c linux-libre-4.7-gnu/crypto/asymmetric_keys/mscode_parser.c
--- linux-libre-4.6-gnu/crypto/asymmetric_keys/mscode_parser.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/crypto/asymmetric_keys/mscode_parser.c	2016-07-24 15:23:50.000000000 -0400
@@ -21,19 +21,13 @@
 /*
  * Parse a Microsoft Individual Code Signing blob
  */
-int mscode_parse(struct pefile_context *ctx)
+int mscode_parse(void *_ctx, const void *content_data, size_t data_len,
+		 size_t asn1hdrlen)
 {
-	const void *content_data;
-	size_t data_len;
-	int ret;
-
-	ret = pkcs7_get_content_data(ctx->pkcs7, &content_data, &data_len, 1);
-
-	if (ret) {
-		pr_debug("PKCS#7 message does not contain data\n");
-		return ret;
-	}
+	struct pefile_context *ctx = _ctx;
 
+	content_data -= asn1hdrlen;
+	data_len += asn1hdrlen;
 	pr_devel("Data: %zu [%*ph]\n", data_len, (unsigned)(data_len),
 		 content_data);
 
@@ -129,7 +123,11 @@ int mscode_note_digest(void *context, si
 {
 	struct pefile_context *ctx = context;
 
-	ctx->digest = value;
+	ctx->digest = kmemdup(value, vlen, GFP_KERNEL);
+	if (!ctx->digest)
+		return -ENOMEM;
+
 	ctx->digest_len = vlen;
+
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/crypto/asymmetric_keys/pkcs7_key_type.c linux-libre-4.7-gnu/crypto/asymmetric_keys/pkcs7_key_type.c
--- linux-libre-4.6-gnu/crypto/asymmetric_keys/pkcs7_key_type.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/crypto/asymmetric_keys/pkcs7_key_type.c	2016-07-24 15:23:50.000000000 -0400
@@ -13,12 +13,9 @@
 #include <linux/key.h>
 #include <linux/err.h>
 #include <linux/module.h>
+#include <linux/verification.h>
 #include <linux/key-type.h>
-#include <keys/asymmetric-type.h>
-#include <crypto/pkcs7.h>
 #include <keys/user-type.h>
-#include <keys/system_keyring.h>
-#include "pkcs7_parser.h"
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("PKCS#7 testing key type");
@@ -29,60 +26,47 @@ MODULE_PARM_DESC(pkcs7_usage,
 		 "Usage to specify when verifying the PKCS#7 message");
 
 /*
- * Preparse a PKCS#7 wrapped and validated data blob.
+ * Retrieve the PKCS#7 message content.
  */
-static int pkcs7_preparse(struct key_preparsed_payload *prep)
+static int pkcs7_view_content(void *ctx, const void *data, size_t len,
+			      size_t asn1hdrlen)
 {
-	enum key_being_used_for usage = pkcs7_usage;
-	struct pkcs7_message *pkcs7;
-	const void *data, *saved_prep_data;
-	size_t datalen, saved_prep_datalen;
-	bool trusted;
+	struct key_preparsed_payload *prep = ctx;
+	const void *saved_prep_data;
+	size_t saved_prep_datalen;
 	int ret;
 
-	kenter("");
-
-	if (usage >= NR__KEY_BEING_USED_FOR) {
-		pr_err("Invalid usage type %d\n", usage);
-		return -EINVAL;
-	}
-
 	saved_prep_data = prep->data;
 	saved_prep_datalen = prep->datalen;
-	pkcs7 = pkcs7_parse_message(saved_prep_data, saved_prep_datalen);
-	if (IS_ERR(pkcs7)) {
-		ret = PTR_ERR(pkcs7);
-		goto error;
-	}
-
-	ret = pkcs7_verify(pkcs7, usage);
-	if (ret < 0)
-		goto error_free;
-
-	ret = pkcs7_validate_trust(pkcs7, system_trusted_keyring, &trusted);
-	if (ret < 0)
-		goto error_free;
-	if (!trusted)
-		pr_warn("PKCS#7 message doesn't chain back to a trusted key\n");
-
-	ret = pkcs7_get_content_data(pkcs7, &data, &datalen, false);
-	if (ret < 0)
-		goto error_free;
-
 	prep->data = data;
-	prep->datalen = datalen;
+	prep->datalen = len;
+
 	ret = user_preparse(prep);
+
 	prep->data = saved_prep_data;
 	prep->datalen = saved_prep_datalen;
-
-error_free:
-	pkcs7_free_message(pkcs7);
-error:
-	kleave(" = %d", ret);
 	return ret;
 }
 
 /*
+ * Preparse a PKCS#7 wrapped and validated data blob.
+ */
+static int pkcs7_preparse(struct key_preparsed_payload *prep)
+{
+	enum key_being_used_for usage = pkcs7_usage;
+
+	if (usage >= NR__KEY_BEING_USED_FOR) {
+		pr_err("Invalid usage type %d\n", usage);
+		return -EINVAL;
+	}
+
+	return verify_pkcs7_signature(NULL, 0,
+				      prep->data, prep->datalen,
+				      (void *)1UL, usage,
+				      pkcs7_view_content, prep);
+}
+
+/*
  * user defined keys take an arbitrary string as the description and an
  * arbitrary blob of data as the payload
  */
diff -druNp --no-dereference linux-libre-4.6-gnu/crypto/asymmetric_keys/pkcs7_parser.c linux-libre-4.7-gnu/crypto/asymmetric_keys/pkcs7_parser.c
--- linux-libre-4.6-gnu/crypto/asymmetric_keys/pkcs7_parser.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/crypto/asymmetric_keys/pkcs7_parser.c	2016-07-24 15:23:50.000000000 -0400
@@ -44,9 +44,7 @@ struct pkcs7_parse_context {
 static void pkcs7_free_signed_info(struct pkcs7_signed_info *sinfo)
 {
 	if (sinfo) {
-		kfree(sinfo->sig.s);
-		kfree(sinfo->sig.digest);
-		kfree(sinfo->signing_cert_id);
+		public_key_signature_free(sinfo->sig);
 		kfree(sinfo);
 	}
 }
@@ -125,6 +123,10 @@ struct pkcs7_message *pkcs7_parse_messag
 	ctx->sinfo = kzalloc(sizeof(struct pkcs7_signed_info), GFP_KERNEL);
 	if (!ctx->sinfo)
 		goto out_no_sinfo;
+	ctx->sinfo->sig = kzalloc(sizeof(struct public_key_signature),
+				  GFP_KERNEL);
+	if (!ctx->sinfo->sig)
+		goto out_no_sig;
 
 	ctx->data = (unsigned long)data;
 	ctx->ppcerts = &ctx->certs;
@@ -150,6 +152,7 @@ out:
 		ctx->certs = cert->next;
 		x509_free_certificate(cert);
 	}
+out_no_sig:
 	pkcs7_free_signed_info(ctx->sinfo);
 out_no_sinfo:
 	pkcs7_free_message(ctx->msg);
@@ -165,24 +168,25 @@ EXPORT_SYMBOL_GPL(pkcs7_parse_message);
  * @pkcs7: The preparsed PKCS#7 message to access
  * @_data: Place to return a pointer to the data
  * @_data_len: Place to return the data length
- * @want_wrapper: True if the ASN.1 object header should be included in the data
+ * @_headerlen: Size of ASN.1 header not included in _data
  *
- * Get access to the data content of the PKCS#7 message, including, optionally,
- * the header of the ASN.1 object that contains it.  Returns -ENODATA if the
- * data object was missing from the message.
+ * Get access to the data content of the PKCS#7 message.  The size of the
+ * header of the ASN.1 object that contains it is also provided and can be used
+ * to adjust *_data and *_data_len to get the entire object.
+ *
+ * Returns -ENODATA if the data object was missing from the message.
  */
 int pkcs7_get_content_data(const struct pkcs7_message *pkcs7,
 			   const void **_data, size_t *_data_len,
-			   bool want_wrapper)
+			   size_t *_headerlen)
 {
-	size_t wrapper;
-
 	if (!pkcs7->data)
 		return -ENODATA;
 
-	wrapper = want_wrapper ? pkcs7->data_hdrlen : 0;
-	*_data = pkcs7->data - wrapper;
-	*_data_len = pkcs7->data_len + wrapper;
+	*_data = pkcs7->data;
+	*_data_len = pkcs7->data_len;
+	if (_headerlen)
+		*_headerlen = pkcs7->data_hdrlen;
 	return 0;
 }
 EXPORT_SYMBOL_GPL(pkcs7_get_content_data);
@@ -218,25 +222,26 @@ int pkcs7_sig_note_digest_algo(void *con
 
 	switch (ctx->last_oid) {
 	case OID_md4:
-		ctx->sinfo->sig.hash_algo = "md4";
+		ctx->sinfo->sig->hash_algo = "md4";
 		break;
 	case OID_md5:
-		ctx->sinfo->sig.hash_algo = "md5";
+		ctx->sinfo->sig->hash_algo = "md5";
 		break;
 	case OID_sha1:
-		ctx->sinfo->sig.hash_algo = "sha1";
+		ctx->sinfo->sig->hash_algo = "sha1";
 		break;
 	case OID_sha256:
-		ctx->sinfo->sig.hash_algo = "sha256";
+		ctx->sinfo->sig->hash_algo = "sha256";
 		break;
 	case OID_sha384:
-		ctx->sinfo->sig.hash_algo = "sha384";
+		ctx->sinfo->sig->hash_algo = "sha384";
 		break;
 	case OID_sha512:
-		ctx->sinfo->sig.hash_algo = "sha512";
+		ctx->sinfo->sig->hash_algo = "sha512";
 		break;
 	case OID_sha224:
-		ctx->sinfo->sig.hash_algo = "sha224";
+		ctx->sinfo->sig->hash_algo = "sha224";
+		break;
 	default:
 		printk("Unsupported digest algo: %u\n", ctx->last_oid);
 		return -ENOPKG;
@@ -255,7 +260,7 @@ int pkcs7_sig_note_pkey_algo(void *conte
 
 	switch (ctx->last_oid) {
 	case OID_rsaEncryption:
-		ctx->sinfo->sig.pkey_algo = "rsa";
+		ctx->sinfo->sig->pkey_algo = "rsa";
 		break;
 	default:
 		printk("Unsupported pkey algo: %u\n", ctx->last_oid);
@@ -615,11 +620,11 @@ int pkcs7_sig_note_signature(void *conte
 {
 	struct pkcs7_parse_context *ctx = context;
 
-	ctx->sinfo->sig.s = kmemdup(value, vlen, GFP_KERNEL);
-	if (!ctx->sinfo->sig.s)
+	ctx->sinfo->sig->s = kmemdup(value, vlen, GFP_KERNEL);
+	if (!ctx->sinfo->sig->s)
 		return -ENOMEM;
 
-	ctx->sinfo->sig.s_size = vlen;
+	ctx->sinfo->sig->s_size = vlen;
 	return 0;
 }
 
@@ -655,12 +660,16 @@ int pkcs7_note_signed_info(void *context
 
 	pr_devel("SINFO KID: %u [%*phN]\n", kid->len, kid->len, kid->data);
 
-	sinfo->signing_cert_id = kid;
+	sinfo->sig->auth_ids[0] = kid;
 	sinfo->index = ++ctx->sinfo_index;
 	*ctx->ppsinfo = sinfo;
 	ctx->ppsinfo = &sinfo->next;
 	ctx->sinfo = kzalloc(sizeof(struct pkcs7_signed_info), GFP_KERNEL);
 	if (!ctx->sinfo)
 		return -ENOMEM;
+	ctx->sinfo->sig = kzalloc(sizeof(struct public_key_signature),
+				  GFP_KERNEL);
+	if (!ctx->sinfo->sig)
+		return -ENOMEM;
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/crypto/asymmetric_keys/pkcs7_parser.h linux-libre-4.7-gnu/crypto/asymmetric_keys/pkcs7_parser.h
--- linux-libre-4.6-gnu/crypto/asymmetric_keys/pkcs7_parser.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/crypto/asymmetric_keys/pkcs7_parser.h	2016-07-24 15:23:50.000000000 -0400
@@ -22,7 +22,6 @@ struct pkcs7_signed_info {
 	struct pkcs7_signed_info *next;
 	struct x509_certificate *signer; /* Signing certificate (in msg->certs) */
 	unsigned	index;
-	bool		trusted;
 	bool		unsupported_crypto;	/* T if not usable due to missing crypto */
 
 	/* Message digest - the digest of the Content Data (or NULL) */
@@ -41,19 +40,17 @@ struct pkcs7_signed_info {
 #define	sinfo_has_ms_statement_type	5
 	time64_t	signing_time;
 
-	/* Issuing cert serial number and issuer's name [PKCS#7 or CMS ver 1]
-	 * or issuing cert's SKID [CMS ver 3].
-	 */
-	struct asymmetric_key_id *signing_cert_id;
-
 	/* Message signature.
 	 *
 	 * This contains the generated digest of _either_ the Content Data or
 	 * the Authenticated Attributes [RFC2315 9.3].  If the latter, one of
 	 * the attributes contains the digest of the the Content Data within
 	 * it.
+	 *
+	 * THis also contains the issuing cert serial number and issuer's name
+	 * [PKCS#7 or CMS ver 1] or issuing cert's SKID [CMS ver 3].
 	 */
-	struct public_key_signature sig;
+	struct public_key_signature *sig;
 };
 
 struct pkcs7_message {
diff -druNp --no-dereference linux-libre-4.6-gnu/crypto/asymmetric_keys/pkcs7_trust.c linux-libre-4.7-gnu/crypto/asymmetric_keys/pkcs7_trust.c
--- linux-libre-4.6-gnu/crypto/asymmetric_keys/pkcs7_trust.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/crypto/asymmetric_keys/pkcs7_trust.c	2016-07-24 15:23:50.000000000 -0400
@@ -27,10 +27,9 @@ static int pkcs7_validate_trust_one(stru
 				    struct pkcs7_signed_info *sinfo,
 				    struct key *trust_keyring)
 {
-	struct public_key_signature *sig = &sinfo->sig;
+	struct public_key_signature *sig = sinfo->sig;
 	struct x509_certificate *x509, *last = NULL, *p;
 	struct key *key;
-	bool trusted;
 	int ret;
 
 	kenter(",%u,", sinfo->index);
@@ -42,10 +41,8 @@ static int pkcs7_validate_trust_one(stru
 
 	for (x509 = sinfo->signer; x509; x509 = x509->signer) {
 		if (x509->seen) {
-			if (x509->verified) {
-				trusted = x509->trusted;
+			if (x509->verified)
 				goto verified;
-			}
 			kleave(" = -ENOKEY [cached]");
 			return -ENOKEY;
 		}
@@ -54,9 +51,8 @@ static int pkcs7_validate_trust_one(stru
 		/* Look to see if this certificate is present in the trusted
 		 * keys.
 		 */
-		key = x509_request_asymmetric_key(trust_keyring,
-						  x509->id, x509->skid,
-						  false);
+		key = find_asymmetric_key(trust_keyring,
+					  x509->id, x509->skid, false);
 		if (!IS_ERR(key)) {
 			/* One of the X.509 certificates in the PKCS#7 message
 			 * is apparently the same as one we already trust.
@@ -80,17 +76,17 @@ static int pkcs7_validate_trust_one(stru
 
 		might_sleep();
 		last = x509;
-		sig = &last->sig;
+		sig = last->sig;
 	}
 
 	/* No match - see if the root certificate has a signer amongst the
 	 * trusted keys.
 	 */
-	if (last && (last->akid_id || last->akid_skid)) {
-		key = x509_request_asymmetric_key(trust_keyring,
-						  last->akid_id,
-						  last->akid_skid,
-						  false);
+	if (last && (last->sig->auth_ids[0] || last->sig->auth_ids[1])) {
+		key = find_asymmetric_key(trust_keyring,
+					  last->sig->auth_ids[0],
+					  last->sig->auth_ids[1],
+					  false);
 		if (!IS_ERR(key)) {
 			x509 = last;
 			pr_devel("sinfo %u: Root cert %u signer is key %x\n",
@@ -104,10 +100,8 @@ static int pkcs7_validate_trust_one(stru
 	/* As a last resort, see if we have a trusted public key that matches
 	 * the signed info directly.
 	 */
-	key = x509_request_asymmetric_key(trust_keyring,
-					  sinfo->signing_cert_id,
-					  NULL,
-					  false);
+	key = find_asymmetric_key(trust_keyring,
+				  sinfo->sig->auth_ids[0], NULL, false);
 	if (!IS_ERR(key)) {
 		pr_devel("sinfo %u: Direct signer is key %x\n",
 			 sinfo->index, key_serial(key));
@@ -122,7 +116,6 @@ static int pkcs7_validate_trust_one(stru
 
 matched:
 	ret = verify_signature(key, sig);
-	trusted = test_bit(KEY_FLAG_TRUSTED, &key->flags);
 	key_put(key);
 	if (ret < 0) {
 		if (ret == -ENOMEM)
@@ -134,12 +127,9 @@ matched:
 verified:
 	if (x509) {
 		x509->verified = true;
-		for (p = sinfo->signer; p != x509; p = p->signer) {
+		for (p = sinfo->signer; p != x509; p = p->signer)
 			p->verified = true;
-			p->trusted = trusted;
-		}
 	}
-	sinfo->trusted = trusted;
 	kleave(" = 0");
 	return 0;
 }
@@ -148,7 +138,6 @@ verified:
  * pkcs7_validate_trust - Validate PKCS#7 trust chain
  * @pkcs7: The PKCS#7 certificate to validate
  * @trust_keyring: Signing certificates to use as starting points
- * @_trusted: Set to true if trustworth, false otherwise
  *
  * Validate that the certificate chain inside the PKCS#7 message intersects
  * keys we already know and trust.
@@ -170,16 +159,13 @@ verified:
  * May also return -ENOMEM.
  */
 int pkcs7_validate_trust(struct pkcs7_message *pkcs7,
-			 struct key *trust_keyring,
-			 bool *_trusted)
+			 struct key *trust_keyring)
 {
 	struct pkcs7_signed_info *sinfo;
 	struct x509_certificate *p;
 	int cached_ret = -ENOKEY;
 	int ret;
 
-	*_trusted = false;
-
 	for (p = pkcs7->certs; p; p = p->next)
 		p->seen = false;
 
@@ -193,7 +179,6 @@ int pkcs7_validate_trust(struct pkcs7_me
 				cached_ret = -ENOPKG;
 			continue;
 		case 0:
-			*_trusted |= sinfo->trusted;
 			cached_ret = 0;
 			continue;
 		default:
diff -druNp --no-dereference linux-libre-4.6-gnu/crypto/asymmetric_keys/pkcs7_verify.c linux-libre-4.7-gnu/crypto/asymmetric_keys/pkcs7_verify.c
--- linux-libre-4.6-gnu/crypto/asymmetric_keys/pkcs7_verify.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/crypto/asymmetric_keys/pkcs7_verify.c	2016-07-24 15:23:50.000000000 -0400
@@ -25,34 +25,36 @@
 static int pkcs7_digest(struct pkcs7_message *pkcs7,
 			struct pkcs7_signed_info *sinfo)
 {
+	struct public_key_signature *sig = sinfo->sig;
 	struct crypto_shash *tfm;
 	struct shash_desc *desc;
-	size_t digest_size, desc_size;
-	void *digest;
+	size_t desc_size;
 	int ret;
 
-	kenter(",%u,%s", sinfo->index, sinfo->sig.hash_algo);
+	kenter(",%u,%s", sinfo->index, sinfo->sig->hash_algo);
 
-	if (!sinfo->sig.hash_algo)
+	if (!sinfo->sig->hash_algo)
 		return -ENOPKG;
 
 	/* Allocate the hashing algorithm we're going to need and find out how
 	 * big the hash operational data will be.
 	 */
-	tfm = crypto_alloc_shash(sinfo->sig.hash_algo, 0, 0);
+	tfm = crypto_alloc_shash(sinfo->sig->hash_algo, 0, 0);
 	if (IS_ERR(tfm))
 		return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm);
 
 	desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
-	sinfo->sig.digest_size = digest_size = crypto_shash_digestsize(tfm);
+	sig->digest_size = crypto_shash_digestsize(tfm);
 
 	ret = -ENOMEM;
-	digest = kzalloc(ALIGN(digest_size, __alignof__(*desc)) + desc_size,
-			 GFP_KERNEL);
-	if (!digest)
+	sig->digest = kmalloc(sig->digest_size, GFP_KERNEL);
+	if (!sig->digest)
+		goto error_no_desc;
+
+	desc = kzalloc(desc_size, GFP_KERNEL);
+	if (!desc)
 		goto error_no_desc;
 
-	desc = PTR_ALIGN(digest + digest_size, __alignof__(*desc));
 	desc->tfm   = tfm;
 	desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
 
@@ -60,10 +62,11 @@ static int pkcs7_digest(struct pkcs7_mes
 	ret = crypto_shash_init(desc);
 	if (ret < 0)
 		goto error;
-	ret = crypto_shash_finup(desc, pkcs7->data, pkcs7->data_len, digest);
+	ret = crypto_shash_finup(desc, pkcs7->data, pkcs7->data_len,
+				 sig->digest);
 	if (ret < 0)
 		goto error;
-	pr_devel("MsgDigest = [%*ph]\n", 8, digest);
+	pr_devel("MsgDigest = [%*ph]\n", 8, sig->digest);
 
 	/* However, if there are authenticated attributes, there must be a
 	 * message digest attribute amongst them which corresponds to the
@@ -78,14 +81,15 @@ static int pkcs7_digest(struct pkcs7_mes
 			goto error;
 		}
 
-		if (sinfo->msgdigest_len != sinfo->sig.digest_size) {
+		if (sinfo->msgdigest_len != sig->digest_size) {
 			pr_debug("Sig %u: Invalid digest size (%u)\n",
 				 sinfo->index, sinfo->msgdigest_len);
 			ret = -EBADMSG;
 			goto error;
 		}
 
-		if (memcmp(digest, sinfo->msgdigest, sinfo->msgdigest_len) != 0) {
+		if (memcmp(sig->digest, sinfo->msgdigest,
+			   sinfo->msgdigest_len) != 0) {
 			pr_debug("Sig %u: Message digest doesn't match\n",
 				 sinfo->index);
 			ret = -EKEYREJECTED;
@@ -97,7 +101,7 @@ static int pkcs7_digest(struct pkcs7_mes
 		 * convert the attributes from a CONT.0 into a SET before we
 		 * hash it.
 		 */
-		memset(digest, 0, sinfo->sig.digest_size);
+		memset(sig->digest, 0, sig->digest_size);
 
 		ret = crypto_shash_init(desc);
 		if (ret < 0)
@@ -107,17 +111,14 @@ static int pkcs7_digest(struct pkcs7_mes
 		if (ret < 0)
 			goto error;
 		ret = crypto_shash_finup(desc, sinfo->authattrs,
-					 sinfo->authattrs_len, digest);
+					 sinfo->authattrs_len, sig->digest);
 		if (ret < 0)
 			goto error;
-		pr_devel("AADigest = [%*ph]\n", 8, digest);
+		pr_devel("AADigest = [%*ph]\n", 8, sig->digest);
 	}
 
-	sinfo->sig.digest = digest;
-	digest = NULL;
-
 error:
-	kfree(digest);
+	kfree(desc);
 error_no_desc:
 	crypto_free_shash(tfm);
 	kleave(" = %d", ret);
@@ -144,12 +145,12 @@ static int pkcs7_find_key(struct pkcs7_m
 		 * PKCS#7 message - but I can't be 100% sure of that.  It's
 		 * possible this will need element-by-element comparison.
 		 */
-		if (!asymmetric_key_id_same(x509->id, sinfo->signing_cert_id))
+		if (!asymmetric_key_id_same(x509->id, sinfo->sig->auth_ids[0]))
 			continue;
 		pr_devel("Sig %u: Found cert serial match X.509[%u]\n",
 			 sinfo->index, certix);
 
-		if (x509->pub->pkey_algo != sinfo->sig.pkey_algo) {
+		if (x509->pub->pkey_algo != sinfo->sig->pkey_algo) {
 			pr_warn("Sig %u: X.509 algo and PKCS#7 sig algo don't match\n",
 				sinfo->index);
 			continue;
@@ -164,7 +165,7 @@ static int pkcs7_find_key(struct pkcs7_m
 	 */
 	pr_debug("Sig %u: Issuing X.509 cert not found (#%*phN)\n",
 		 sinfo->index,
-		 sinfo->signing_cert_id->len, sinfo->signing_cert_id->data);
+		 sinfo->sig->auth_ids[0]->len, sinfo->sig->auth_ids[0]->data);
 	return 0;
 }
 
@@ -174,6 +175,7 @@ static int pkcs7_find_key(struct pkcs7_m
 static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
 				  struct pkcs7_signed_info *sinfo)
 {
+	struct public_key_signature *sig;
 	struct x509_certificate *x509 = sinfo->signer, *p;
 	struct asymmetric_key_id *auth;
 	int ret;
@@ -188,34 +190,26 @@ static int pkcs7_verify_sig_chain(struct
 			 x509->subject,
 			 x509->raw_serial_size, x509->raw_serial);
 		x509->seen = true;
-		ret = x509_get_sig_params(x509);
-		if (ret < 0)
-			goto maybe_missing_crypto_in_x509;
+		if (x509->unsupported_key)
+			goto unsupported_crypto_in_x509;
 
 		pr_debug("- issuer %s\n", x509->issuer);
-		if (x509->akid_id)
+		sig = x509->sig;
+		if (sig->auth_ids[0])
 			pr_debug("- authkeyid.id %*phN\n",
-				 x509->akid_id->len, x509->akid_id->data);
-		if (x509->akid_skid)
+				 sig->auth_ids[0]->len, sig->auth_ids[0]->data);
+		if (sig->auth_ids[1])
 			pr_debug("- authkeyid.skid %*phN\n",
-				 x509->akid_skid->len, x509->akid_skid->data);
+				 sig->auth_ids[1]->len, sig->auth_ids[1]->data);
 
-		if ((!x509->akid_id && !x509->akid_skid) ||
-		    strcmp(x509->subject, x509->issuer) == 0) {
+		if (x509->self_signed) {
 			/* If there's no authority certificate specified, then
 			 * the certificate must be self-signed and is the root
 			 * of the chain.  Likewise if the cert is its own
 			 * authority.
 			 */
-			pr_debug("- no auth?\n");
-			if (x509->raw_subject_size != x509->raw_issuer_size ||
-			    memcmp(x509->raw_subject, x509->raw_issuer,
-				   x509->raw_issuer_size) != 0)
-				return 0;
-
-			ret = x509_check_signature(x509->pub, x509);
-			if (ret < 0)
-				goto maybe_missing_crypto_in_x509;
+			if (x509->unsupported_sig)
+				goto unsupported_crypto_in_x509;
 			x509->signer = x509;
 			pr_debug("- self-signed\n");
 			return 0;
@@ -224,7 +218,7 @@ static int pkcs7_verify_sig_chain(struct
 		/* Look through the X.509 certificates in the PKCS#7 message's
 		 * list to see if the next one is there.
 		 */
-		auth = x509->akid_id;
+		auth = sig->auth_ids[0];
 		if (auth) {
 			pr_debug("- want %*phN\n", auth->len, auth->data);
 			for (p = pkcs7->certs; p; p = p->next) {
@@ -233,8 +227,8 @@ static int pkcs7_verify_sig_chain(struct
 				if (asymmetric_key_id_same(p->id, auth))
 					goto found_issuer_check_skid;
 			}
-		} else {
-			auth = x509->akid_skid;
+		} else if (sig->auth_ids[1]) {
+			auth = sig->auth_ids[1];
 			pr_debug("- want %*phN\n", auth->len, auth->data);
 			for (p = pkcs7->certs; p; p = p->next) {
 				if (!p->skid)
@@ -254,8 +248,8 @@ static int pkcs7_verify_sig_chain(struct
 		/* We matched issuer + serialNumber, but if there's an
 		 * authKeyId.keyId, that must match the CA subjKeyId also.
 		 */
-		if (x509->akid_skid &&
-		    !asymmetric_key_id_same(p->skid, x509->akid_skid)) {
+		if (sig->auth_ids[1] &&
+		    !asymmetric_key_id_same(p->skid, sig->auth_ids[1])) {
 			pr_warn("Sig %u: X.509 chain contains auth-skid nonmatch (%u->%u)\n",
 				sinfo->index, x509->index, p->index);
 			return -EKEYREJECTED;
@@ -267,7 +261,7 @@ static int pkcs7_verify_sig_chain(struct
 				sinfo->index);
 			return 0;
 		}
-		ret = x509_check_signature(p->pub, x509);
+		ret = public_key_verify_signature(p->pub, p->sig);
 		if (ret < 0)
 			return ret;
 		x509->signer = p;
@@ -279,16 +273,14 @@ static int pkcs7_verify_sig_chain(struct
 		might_sleep();
 	}
 
-maybe_missing_crypto_in_x509:
+unsupported_crypto_in_x509:
 	/* Just prune the certificate chain at this point if we lack some
 	 * crypto module to go further.  Note, however, we don't want to set
-	 * sinfo->missing_crypto as the signed info block may still be
+	 * sinfo->unsupported_crypto as the signed info block may still be
 	 * validatable against an X.509 cert lower in the chain that we have a
 	 * trusted copy of.
 	 */
-	if (ret == -ENOPKG)
-		return 0;
-	return ret;
+	return 0;
 }
 
 /*
@@ -332,7 +324,7 @@ static int pkcs7_verify_one(struct pkcs7
 	}
 
 	/* Verify the PKCS#7 binary against the key */
-	ret = public_key_verify_signature(sinfo->signer->pub, &sinfo->sig);
+	ret = public_key_verify_signature(sinfo->signer->pub, sinfo->sig);
 	if (ret < 0)
 		return ret;
 
@@ -375,9 +367,8 @@ int pkcs7_verify(struct pkcs7_message *p
 		 enum key_being_used_for usage)
 {
 	struct pkcs7_signed_info *sinfo;
-	struct x509_certificate *x509;
 	int enopkg = -ENOPKG;
-	int ret, n;
+	int ret;
 
 	kenter("");
 
@@ -419,12 +410,6 @@ int pkcs7_verify(struct pkcs7_message *p
 		return -EINVAL;
 	}
 
-	for (n = 0, x509 = pkcs7->certs; x509; x509 = x509->next, n++) {
-		ret = x509_get_sig_params(x509);
-		if (ret < 0)
-			return ret;
-	}
-
 	for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) {
 		ret = pkcs7_verify_one(pkcs7, sinfo);
 		if (ret < 0) {
diff -druNp --no-dereference linux-libre-4.6-gnu/crypto/asymmetric_keys/public_key.c linux-libre-4.7-gnu/crypto/asymmetric_keys/public_key.c
--- linux-libre-4.6-gnu/crypto/asymmetric_keys/public_key.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/crypto/asymmetric_keys/public_key.c	2016-07-24 15:23:50.000000000 -0400
@@ -39,15 +39,23 @@ static void public_key_describe(const st
 /*
  * Destroy a public key algorithm key.
  */
-void public_key_destroy(void *payload)
+void public_key_free(struct public_key *key)
 {
-	struct public_key *key = payload;
-
-	if (key)
+	if (key) {
 		kfree(key->key);
-	kfree(key);
+		kfree(key);
+	}
+}
+EXPORT_SYMBOL_GPL(public_key_free);
+
+/*
+ * Destroy a public key algorithm key.
+ */
+static void public_key_destroy(void *payload0, void *payload3)
+{
+	public_key_free(payload0);
+	public_key_signature_free(payload3);
 }
-EXPORT_SYMBOL_GPL(public_key_destroy);
 
 struct public_key_completion {
 	struct completion completion;
diff -druNp --no-dereference linux-libre-4.6-gnu/crypto/asymmetric_keys/restrict.c linux-libre-4.7-gnu/crypto/asymmetric_keys/restrict.c
--- linux-libre-4.6-gnu/crypto/asymmetric_keys/restrict.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/crypto/asymmetric_keys/restrict.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,108 @@
+/* Instantiate a public key crypto key from an X.509 Certificate
+ *
+ * Copyright (C) 2012, 2016 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#define pr_fmt(fmt) "ASYM: "fmt
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <crypto/public_key.h>
+#include "asymmetric_keys.h"
+
+static bool use_builtin_keys;
+static struct asymmetric_key_id *ca_keyid;
+
+#ifndef MODULE
+static struct {
+	struct asymmetric_key_id id;
+	unsigned char data[10];
+} cakey;
+
+static int __init ca_keys_setup(char *str)
+{
+	if (!str)		/* default system keyring */
+		return 1;
+
+	if (strncmp(str, "id:", 3) == 0) {
+		struct asymmetric_key_id *p = &cakey.id;
+		size_t hexlen = (strlen(str) - 3) / 2;
+		int ret;
+
+		if (hexlen == 0 || hexlen > sizeof(cakey.data)) {
+			pr_err("Missing or invalid ca_keys id\n");
+			return 1;
+		}
+
+		ret = __asymmetric_key_hex_to_key_id(str + 3, p, hexlen);
+		if (ret < 0)
+			pr_err("Unparsable ca_keys id hex string\n");
+		else
+			ca_keyid = p;	/* owner key 'id:xxxxxx' */
+	} else if (strcmp(str, "builtin") == 0) {
+		use_builtin_keys = true;
+	}
+
+	return 1;
+}
+__setup("ca_keys=", ca_keys_setup);
+#endif
+
+/**
+ * restrict_link_by_signature - Restrict additions to a ring of public keys
+ * @trust_keyring: A ring of keys that can be used to vouch for the new cert.
+ * @type: The type of key being added.
+ * @payload: The payload of the new key.
+ *
+ * Check the new certificate against the ones in the trust keyring.  If one of
+ * those is the signing key and validates the new certificate, then mark the
+ * new certificate as being trusted.
+ *
+ * Returns 0 if the new certificate was accepted, -ENOKEY if we couldn't find a
+ * matching parent certificate in the trusted list, -EKEYREJECTED if the
+ * signature check fails or the key is blacklisted and some other error if
+ * there is a matching certificate but the signature check cannot be performed.
+ */
+int restrict_link_by_signature(struct key *trust_keyring,
+			       const struct key_type *type,
+			       const union key_payload *payload)
+{
+	const struct public_key_signature *sig;
+	struct key *key;
+	int ret;
+
+	pr_devel("==>%s()\n", __func__);
+
+	if (!trust_keyring)
+		return -ENOKEY;
+
+	if (type != &key_type_asymmetric)
+		return -EOPNOTSUPP;
+
+	sig = payload->data[asym_auth];
+	if (!sig->auth_ids[0] && !sig->auth_ids[1])
+		return -ENOKEY;
+
+	if (ca_keyid && !asymmetric_key_id_partial(sig->auth_ids[1], ca_keyid))
+		return -EPERM;
+
+	/* See if we have a key that signed this one. */
+	key = find_asymmetric_key(trust_keyring,
+				  sig->auth_ids[0], sig->auth_ids[1],
+				  false);
+	if (IS_ERR(key))
+		return -ENOKEY;
+
+	if (use_builtin_keys && !test_bit(KEY_FLAG_BUILTIN, &key->flags))
+		ret = -ENOKEY;
+	else
+		ret = verify_signature(key, sig);
+	key_put(key);
+	return ret;
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/crypto/asymmetric_keys/signature.c linux-libre-4.7-gnu/crypto/asymmetric_keys/signature.c
--- linux-libre-4.6-gnu/crypto/asymmetric_keys/signature.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/crypto/asymmetric_keys/signature.c	2016-07-24 15:23:50.000000000 -0400
@@ -15,9 +15,27 @@
 #include <keys/asymmetric-subtype.h>
 #include <linux/export.h>
 #include <linux/err.h>
+#include <linux/slab.h>
 #include <crypto/public_key.h>
 #include "asymmetric_keys.h"
 
+/*
+ * Destroy a public key signature.
+ */
+void public_key_signature_free(struct public_key_signature *sig)
+{
+	int i;
+
+	if (sig) {
+		for (i = 0; i < ARRAY_SIZE(sig->auth_ids); i++)
+			kfree(sig->auth_ids[i]);
+		kfree(sig->s);
+		kfree(sig->digest);
+		kfree(sig);
+	}
+}
+EXPORT_SYMBOL_GPL(public_key_signature_free);
+
 /**
  * verify_signature - Initiate the use of an asymmetric key to verify a signature
  * @key: The asymmetric key to verify against
diff -druNp --no-dereference linux-libre-4.6-gnu/crypto/asymmetric_keys/verify_pefile.c linux-libre-4.7-gnu/crypto/asymmetric_keys/verify_pefile.c
--- linux-libre-4.6-gnu/crypto/asymmetric_keys/verify_pefile.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/crypto/asymmetric_keys/verify_pefile.c	2016-07-24 15:23:50.000000000 -0400
@@ -16,7 +16,7 @@
 #include <linux/err.h>
 #include <linux/pe.h>
 #include <linux/asn1.h>
-#include <crypto/pkcs7.h>
+#include <linux/verification.h>
 #include <crypto/hash.h>
 #include "verify_pefile.h"
 
@@ -392,9 +392,8 @@ error_no_desc:
  * verify_pefile_signature - Verify the signature on a PE binary image
  * @pebuf: Buffer containing the PE binary image
  * @pelen: Length of the binary image
- * @trust_keyring: Signing certificates to use as starting points
+ * @trust_keys: Signing certificate(s) to use as starting points
  * @usage: The use to which the key is being put.
- * @_trusted: Set to true if trustworth, false otherwise
  *
  * Validate that the certificate chain inside the PKCS#7 message inside the PE
  * binary image intersects keys we already know and trust.
@@ -418,14 +417,10 @@ error_no_desc:
  * May also return -ENOMEM.
  */
 int verify_pefile_signature(const void *pebuf, unsigned pelen,
-			    struct key *trusted_keyring,
-			    enum key_being_used_for usage,
-			    bool *_trusted)
+			    struct key *trusted_keys,
+			    enum key_being_used_for usage)
 {
-	struct pkcs7_message *pkcs7;
 	struct pefile_context ctx;
-	const void *data;
-	size_t datalen;
 	int ret;
 
 	kenter("");
@@ -439,19 +434,10 @@ int verify_pefile_signature(const void *
 	if (ret < 0)
 		return ret;
 
-	pkcs7 = pkcs7_parse_message(pebuf + ctx.sig_offset, ctx.sig_len);
-	if (IS_ERR(pkcs7))
-		return PTR_ERR(pkcs7);
-	ctx.pkcs7 = pkcs7;
-
-	ret = pkcs7_get_content_data(ctx.pkcs7, &data, &datalen, false);
-	if (ret < 0 || datalen == 0) {
-		pr_devel("PKCS#7 message does not contain data\n");
-		ret = -EBADMSG;
-		goto error;
-	}
-
-	ret = mscode_parse(&ctx);
+	ret = verify_pkcs7_signature(NULL, 0,
+				     pebuf + ctx.sig_offset, ctx.sig_len,
+				     trusted_keys, usage,
+				     mscode_parse, &ctx);
 	if (ret < 0)
 		goto error;
 
@@ -462,16 +448,8 @@ int verify_pefile_signature(const void *
 	 * contents.
 	 */
 	ret = pefile_digest_pe(pebuf, pelen, &ctx);
-	if (ret < 0)
-		goto error;
-
-	ret = pkcs7_verify(pkcs7, usage);
-	if (ret < 0)
-		goto error;
-
-	ret = pkcs7_validate_trust(pkcs7, trusted_keyring, _trusted);
 
 error:
-	pkcs7_free_message(ctx.pkcs7);
+	kfree(ctx.digest);
 	return ret;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/crypto/asymmetric_keys/verify_pefile.h linux-libre-4.7-gnu/crypto/asymmetric_keys/verify_pefile.h
--- linux-libre-4.6-gnu/crypto/asymmetric_keys/verify_pefile.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/crypto/asymmetric_keys/verify_pefile.h	2016-07-24 15:23:50.000000000 -0400
@@ -9,7 +9,6 @@
  * 2 of the Licence, or (at your option) any later version.
  */
 
-#include <linux/verify_pefile.h>
 #include <crypto/pkcs7.h>
 #include <crypto/hash_info.h>
 
@@ -23,7 +22,6 @@ struct pefile_context {
 	unsigned	sig_offset;
 	unsigned	sig_len;
 	const struct section_header *secs;
-	struct pkcs7_message *pkcs7;
 
 	/* PKCS#7 MS Individual Code Signing content */
 	const void	*digest;		/* Digest */
@@ -39,4 +37,5 @@ struct pefile_context {
 /*
  * mscode_parser.c
  */
-extern int mscode_parse(struct pefile_context *ctx);
+extern int mscode_parse(void *_ctx, const void *content_data, size_t data_len,
+			size_t asn1hdrlen);
diff -druNp --no-dereference linux-libre-4.6-gnu/crypto/asymmetric_keys/x509_cert_parser.c linux-libre-4.7-gnu/crypto/asymmetric_keys/x509_cert_parser.c
--- linux-libre-4.6-gnu/crypto/asymmetric_keys/x509_cert_parser.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/crypto/asymmetric_keys/x509_cert_parser.c	2016-07-24 15:23:50.000000000 -0400
@@ -47,15 +47,12 @@ struct x509_parse_context {
 void x509_free_certificate(struct x509_certificate *cert)
 {
 	if (cert) {
-		public_key_destroy(cert->pub);
+		public_key_free(cert->pub);
+		public_key_signature_free(cert->sig);
 		kfree(cert->issuer);
 		kfree(cert->subject);
 		kfree(cert->id);
 		kfree(cert->skid);
-		kfree(cert->akid_id);
-		kfree(cert->akid_skid);
-		kfree(cert->sig.digest);
-		kfree(cert->sig.s);
 		kfree(cert);
 	}
 }
@@ -78,6 +75,9 @@ struct x509_certificate *x509_cert_parse
 	cert->pub = kzalloc(sizeof(struct public_key), GFP_KERNEL);
 	if (!cert->pub)
 		goto error_no_ctx;
+	cert->sig = kzalloc(sizeof(struct public_key_signature), GFP_KERNEL);
+	if (!cert->sig)
+		goto error_no_ctx;
 	ctx = kzalloc(sizeof(struct x509_parse_context), GFP_KERNEL);
 	if (!ctx)
 		goto error_no_ctx;
@@ -108,6 +108,11 @@ struct x509_certificate *x509_cert_parse
 
 	cert->pub->keylen = ctx->key_size;
 
+	/* Grab the signature bits */
+	ret = x509_get_sig_params(cert);
+	if (ret < 0)
+		goto error_decode;
+
 	/* Generate cert issuer + serial number key ID */
 	kid = asymmetric_key_generate_id(cert->raw_serial,
 					 cert->raw_serial_size,
@@ -119,6 +124,11 @@ struct x509_certificate *x509_cert_parse
 	}
 	cert->id = kid;
 
+	/* Detect self-signed certificates */
+	ret = x509_check_for_self_signed(cert);
+	if (ret < 0)
+		goto error_decode;
+
 	kfree(ctx);
 	return cert;
 
@@ -188,33 +198,33 @@ int x509_note_pkey_algo(void *context, s
 		return -ENOPKG; /* Unsupported combination */
 
 	case OID_md4WithRSAEncryption:
-		ctx->cert->sig.hash_algo = "md4";
-		ctx->cert->sig.pkey_algo = "rsa";
+		ctx->cert->sig->hash_algo = "md4";
+		ctx->cert->sig->pkey_algo = "rsa";
 		break;
 
 	case OID_sha1WithRSAEncryption:
-		ctx->cert->sig.hash_algo = "sha1";
-		ctx->cert->sig.pkey_algo = "rsa";
+		ctx->cert->sig->hash_algo = "sha1";
+		ctx->cert->sig->pkey_algo = "rsa";
 		break;
 
 	case OID_sha256WithRSAEncryption:
-		ctx->cert->sig.hash_algo = "sha256";
-		ctx->cert->sig.pkey_algo = "rsa";
+		ctx->cert->sig->hash_algo = "sha256";
+		ctx->cert->sig->pkey_algo = "rsa";
 		break;
 
 	case OID_sha384WithRSAEncryption:
-		ctx->cert->sig.hash_algo = "sha384";
-		ctx->cert->sig.pkey_algo = "rsa";
+		ctx->cert->sig->hash_algo = "sha384";
+		ctx->cert->sig->pkey_algo = "rsa";
 		break;
 
 	case OID_sha512WithRSAEncryption:
-		ctx->cert->sig.hash_algo = "sha512";
-		ctx->cert->sig.pkey_algo = "rsa";
+		ctx->cert->sig->hash_algo = "sha512";
+		ctx->cert->sig->pkey_algo = "rsa";
 		break;
 
 	case OID_sha224WithRSAEncryption:
-		ctx->cert->sig.hash_algo = "sha224";
-		ctx->cert->sig.pkey_algo = "rsa";
+		ctx->cert->sig->hash_algo = "sha224";
+		ctx->cert->sig->pkey_algo = "rsa";
 		break;
 	}
 
@@ -572,14 +582,14 @@ int x509_akid_note_kid(void *context, si
 
 	pr_debug("AKID: keyid: %*phN\n", (int)vlen, value);
 
-	if (ctx->cert->akid_skid)
+	if (ctx->cert->sig->auth_ids[1])
 		return 0;
 
 	kid = asymmetric_key_generate_id(value, vlen, "", 0);
 	if (IS_ERR(kid))
 		return PTR_ERR(kid);
 	pr_debug("authkeyid %*phN\n", kid->len, kid->data);
-	ctx->cert->akid_skid = kid;
+	ctx->cert->sig->auth_ids[1] = kid;
 	return 0;
 }
 
@@ -611,7 +621,7 @@ int x509_akid_note_serial(void *context,
 
 	pr_debug("AKID: serial: %*phN\n", (int)vlen, value);
 
-	if (!ctx->akid_raw_issuer || ctx->cert->akid_id)
+	if (!ctx->akid_raw_issuer || ctx->cert->sig->auth_ids[0])
 		return 0;
 
 	kid = asymmetric_key_generate_id(value,
@@ -622,6 +632,6 @@ int x509_akid_note_serial(void *context,
 		return PTR_ERR(kid);
 
 	pr_debug("authkeyid %*phN\n", kid->len, kid->data);
-	ctx->cert->akid_id = kid;
+	ctx->cert->sig->auth_ids[0] = kid;
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/crypto/asymmetric_keys/x509_parser.h linux-libre-4.7-gnu/crypto/asymmetric_keys/x509_parser.h
--- linux-libre-4.6-gnu/crypto/asymmetric_keys/x509_parser.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/crypto/asymmetric_keys/x509_parser.h	2016-07-24 15:23:50.000000000 -0400
@@ -17,13 +17,11 @@ struct x509_certificate {
 	struct x509_certificate *next;
 	struct x509_certificate *signer;	/* Certificate that signed this one */
 	struct public_key *pub;			/* Public key details */
-	struct public_key_signature sig;	/* Signature parameters */
+	struct public_key_signature *sig;	/* Signature parameters */
 	char		*issuer;		/* Name of certificate issuer */
 	char		*subject;		/* Name of certificate subject */
 	struct asymmetric_key_id *id;		/* Issuer + Serial number */
 	struct asymmetric_key_id *skid;		/* Subject + subjectKeyId (optional) */
-	struct asymmetric_key_id *akid_id;	/* CA AuthKeyId matching ->id (optional) */
-	struct asymmetric_key_id *akid_skid;	/* CA AuthKeyId matching ->skid (optional) */
 	time64_t	valid_from;
 	time64_t	valid_to;
 	const void	*tbs;			/* Signed data */
@@ -41,8 +39,9 @@ struct x509_certificate {
 	unsigned	index;
 	bool		seen;			/* Infinite recursion prevention */
 	bool		verified;
-	bool		trusted;
-	bool		unsupported_crypto;	/* T if can't be verified due to missing crypto */
+	bool		self_signed;		/* T if self-signed (check unsupported_sig too) */
+	bool		unsupported_key;	/* T if key uses unsupported crypto */
+	bool		unsupported_sig;	/* T if signature uses unsupported crypto */
 };
 
 /*
@@ -58,5 +57,4 @@ extern int x509_decode_time(time64_t *_t
  * x509_public_key.c
  */
 extern int x509_get_sig_params(struct x509_certificate *cert);
-extern int x509_check_signature(const struct public_key *pub,
-				struct x509_certificate *cert);
+extern int x509_check_for_self_signed(struct x509_certificate *cert);
diff -druNp --no-dereference linux-libre-4.6-gnu/crypto/asymmetric_keys/x509_public_key.c linux-libre-4.7-gnu/crypto/asymmetric_keys/x509_public_key.c
--- linux-libre-4.6-gnu/crypto/asymmetric_keys/x509_public_key.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/crypto/asymmetric_keys/x509_public_key.c	2016-07-24 15:23:50.000000000 -0400
@@ -20,256 +20,133 @@
 #include "asymmetric_keys.h"
 #include "x509_parser.h"
 
-static bool use_builtin_keys;
-static struct asymmetric_key_id *ca_keyid;
-
-#ifndef MODULE
-static struct {
-	struct asymmetric_key_id id;
-	unsigned char data[10];
-} cakey;
-
-static int __init ca_keys_setup(char *str)
-{
-	if (!str)		/* default system keyring */
-		return 1;
-
-	if (strncmp(str, "id:", 3) == 0) {
-		struct asymmetric_key_id *p = &cakey.id;
-		size_t hexlen = (strlen(str) - 3) / 2;
-		int ret;
-
-		if (hexlen == 0 || hexlen > sizeof(cakey.data)) {
-			pr_err("Missing or invalid ca_keys id\n");
-			return 1;
-		}
-
-		ret = __asymmetric_key_hex_to_key_id(str + 3, p, hexlen);
-		if (ret < 0)
-			pr_err("Unparsable ca_keys id hex string\n");
-		else
-			ca_keyid = p;	/* owner key 'id:xxxxxx' */
-	} else if (strcmp(str, "builtin") == 0) {
-		use_builtin_keys = true;
-	}
-
-	return 1;
-}
-__setup("ca_keys=", ca_keys_setup);
-#endif
-
-/**
- * x509_request_asymmetric_key - Request a key by X.509 certificate params.
- * @keyring: The keys to search.
- * @id: The issuer & serialNumber to look for or NULL.
- * @skid: The subjectKeyIdentifier to look for or NULL.
- * @partial: Use partial match if true, exact if false.
- *
- * Find a key in the given keyring by identifier.  The preferred identifier is
- * the issuer + serialNumber and the fallback identifier is the
- * subjectKeyIdentifier.  If both are given, the lookup is by the former, but
- * the latter must also match.
- */
-struct key *x509_request_asymmetric_key(struct key *keyring,
-					const struct asymmetric_key_id *id,
-					const struct asymmetric_key_id *skid,
-					bool partial)
-{
-	struct key *key;
-	key_ref_t ref;
-	const char *lookup;
-	char *req, *p;
-	int len;
-
-	if (id) {
-		lookup = id->data;
-		len = id->len;
-	} else {
-		lookup = skid->data;
-		len = skid->len;
-	}
-	
-	/* Construct an identifier "id:<keyid>". */
-	p = req = kmalloc(2 + 1 + len * 2 + 1, GFP_KERNEL);
-	if (!req)
-		return ERR_PTR(-ENOMEM);
-
-	if (partial) {
-		*p++ = 'i';
-		*p++ = 'd';
-	} else {
-		*p++ = 'e';
-		*p++ = 'x';
-	}
-	*p++ = ':';
-	p = bin2hex(p, lookup, len);
-	*p = 0;
-
-	pr_debug("Look up: \"%s\"\n", req);
-
-	ref = keyring_search(make_key_ref(keyring, 1),
-			     &key_type_asymmetric, req);
-	if (IS_ERR(ref))
-		pr_debug("Request for key '%s' err %ld\n", req, PTR_ERR(ref));
-	kfree(req);
-
-	if (IS_ERR(ref)) {
-		switch (PTR_ERR(ref)) {
-			/* Hide some search errors */
-		case -EACCES:
-		case -ENOTDIR:
-		case -EAGAIN:
-			return ERR_PTR(-ENOKEY);
-		default:
-			return ERR_CAST(ref);
-		}
-	}
-
-	key = key_ref_to_ptr(ref);
-	if (id && skid) {
-		const struct asymmetric_key_ids *kids = asymmetric_key_ids(key);
-		if (!kids->id[1]) {
-			pr_debug("issuer+serial match, but expected SKID missing\n");
-			goto reject;
-		}
-		if (!asymmetric_key_id_same(skid, kids->id[1])) {
-			pr_debug("issuer+serial match, but SKID does not\n");
-			goto reject;
-		}
-	}
-	
-	pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key));
-	return key;
-
-reject:
-	key_put(key);
-	return ERR_PTR(-EKEYREJECTED);
-}
-EXPORT_SYMBOL_GPL(x509_request_asymmetric_key);
-
 /*
  * Set up the signature parameters in an X.509 certificate.  This involves
  * digesting the signed data and extracting the signature.
  */
 int x509_get_sig_params(struct x509_certificate *cert)
 {
+	struct public_key_signature *sig = cert->sig;
 	struct crypto_shash *tfm;
 	struct shash_desc *desc;
-	size_t digest_size, desc_size;
-	void *digest;
+	size_t desc_size;
 	int ret;
 
 	pr_devel("==>%s()\n", __func__);
 
-	if (cert->unsupported_crypto)
-		return -ENOPKG;
-	if (cert->sig.s)
+	if (!cert->pub->pkey_algo)
+		cert->unsupported_key = true;
+
+	if (!sig->pkey_algo)
+		cert->unsupported_sig = true;
+
+	/* We check the hash if we can - even if we can't then verify it */
+	if (!sig->hash_algo) {
+		cert->unsupported_sig = true;
 		return 0;
+	}
 
-	cert->sig.s = kmemdup(cert->raw_sig, cert->raw_sig_size,
-			      GFP_KERNEL);
-	if (!cert->sig.s)
+	sig->s = kmemdup(cert->raw_sig, cert->raw_sig_size, GFP_KERNEL);
+	if (!sig->s)
 		return -ENOMEM;
 
-	cert->sig.s_size = cert->raw_sig_size;
+	sig->s_size = cert->raw_sig_size;
 
 	/* Allocate the hashing algorithm we're going to need and find out how
 	 * big the hash operational data will be.
 	 */
-	tfm = crypto_alloc_shash(cert->sig.hash_algo, 0, 0);
+	tfm = crypto_alloc_shash(sig->hash_algo, 0, 0);
 	if (IS_ERR(tfm)) {
 		if (PTR_ERR(tfm) == -ENOENT) {
-			cert->unsupported_crypto = true;
-			return -ENOPKG;
+			cert->unsupported_sig = true;
+			return 0;
 		}
 		return PTR_ERR(tfm);
 	}
 
 	desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
-	digest_size = crypto_shash_digestsize(tfm);
+	sig->digest_size = crypto_shash_digestsize(tfm);
 
-	/* We allocate the hash operational data storage on the end of the
-	 * digest storage space.
-	 */
 	ret = -ENOMEM;
-	digest = kzalloc(ALIGN(digest_size, __alignof__(*desc)) + desc_size,
-			 GFP_KERNEL);
-	if (!digest)
+	sig->digest = kmalloc(sig->digest_size, GFP_KERNEL);
+	if (!sig->digest)
 		goto error;
 
-	cert->sig.digest = digest;
-	cert->sig.digest_size = digest_size;
+	desc = kzalloc(desc_size, GFP_KERNEL);
+	if (!desc)
+		goto error;
 
-	desc = PTR_ALIGN(digest + digest_size, __alignof__(*desc));
 	desc->tfm = tfm;
 	desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
 
 	ret = crypto_shash_init(desc);
 	if (ret < 0)
-		goto error;
+		goto error_2;
 	might_sleep();
-	ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, digest);
+	ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, sig->digest);
+
+error_2:
+	kfree(desc);
 error:
 	crypto_free_shash(tfm);
 	pr_devel("<==%s() = %d\n", __func__, ret);
 	return ret;
 }
-EXPORT_SYMBOL_GPL(x509_get_sig_params);
 
 /*
- * Check the signature on a certificate using the provided public key
+ * Check for self-signedness in an X.509 cert and if found, check the signature
+ * immediately if we can.
  */
-int x509_check_signature(const struct public_key *pub,
-			 struct x509_certificate *cert)
+int x509_check_for_self_signed(struct x509_certificate *cert)
 {
-	int ret;
+	int ret = 0;
 
 	pr_devel("==>%s()\n", __func__);
 
-	ret = x509_get_sig_params(cert);
-	if (ret < 0)
-		return ret;
+	if (cert->raw_subject_size != cert->raw_issuer_size ||
+	    memcmp(cert->raw_subject, cert->raw_issuer,
+		   cert->raw_issuer_size) != 0)
+		goto not_self_signed;
 
-	ret = public_key_verify_signature(pub, &cert->sig);
-	if (ret == -ENOPKG)
-		cert->unsupported_crypto = true;
-	pr_debug("Cert Verification: %d\n", ret);
-	return ret;
-}
-EXPORT_SYMBOL_GPL(x509_check_signature);
+	if (cert->sig->auth_ids[0] || cert->sig->auth_ids[1]) {
+		/* If the AKID is present it may have one or two parts.  If
+		 * both are supplied, both must match.
+		 */
+		bool a = asymmetric_key_id_same(cert->skid, cert->sig->auth_ids[1]);
+		bool b = asymmetric_key_id_same(cert->id, cert->sig->auth_ids[0]);
 
-/*
- * Check the new certificate against the ones in the trust keyring.  If one of
- * those is the signing key and validates the new certificate, then mark the
- * new certificate as being trusted.
- *
- * Return 0 if the new certificate was successfully validated, 1 if we couldn't
- * find a matching parent certificate in the trusted list and an error if there
- * is a matching certificate but the signature check fails.
- */
-static int x509_validate_trust(struct x509_certificate *cert,
-			       struct key *trust_keyring)
-{
-	struct key *key;
-	int ret = 1;
+		if (!a && !b)
+			goto not_self_signed;
 
-	if (!trust_keyring)
-		return -EOPNOTSUPP;
+		ret = -EKEYREJECTED;
+		if (((a && !b) || (b && !a)) &&
+		    cert->sig->auth_ids[0] && cert->sig->auth_ids[1])
+			goto out;
+	}
 
-	if (ca_keyid && !asymmetric_key_id_partial(cert->akid_skid, ca_keyid))
-		return -EPERM;
+	ret = -EKEYREJECTED;
+	if (cert->pub->pkey_algo != cert->sig->pkey_algo)
+		goto out;
 
-	key = x509_request_asymmetric_key(trust_keyring,
-					  cert->akid_id, cert->akid_skid,
-					  false);
-	if (!IS_ERR(key))  {
-		if (!use_builtin_keys
-		    || test_bit(KEY_FLAG_BUILTIN, &key->flags))
-			ret = x509_check_signature(key->payload.data[asym_crypto],
-						   cert);
-		key_put(key);
+	ret = public_key_verify_signature(cert->pub, cert->sig);
+	if (ret < 0) {
+		if (ret == -ENOPKG) {
+			cert->unsupported_sig = true;
+			ret = 0;
+		}
+		goto out;
 	}
+
+	pr_devel("Cert Self-signature verified");
+	cert->self_signed = true;
+
+out:
+	pr_devel("<==%s() = %d\n", __func__, ret);
 	return ret;
+
+not_self_signed:
+	pr_devel("<==%s() = 0 [not]\n", __func__);
+	return 0;
 }
 
 /*
@@ -291,34 +168,22 @@ static int x509_key_preparse(struct key_
 	pr_devel("Cert Issuer: %s\n", cert->issuer);
 	pr_devel("Cert Subject: %s\n", cert->subject);
 
-	if (!cert->pub->pkey_algo ||
-	    !cert->sig.pkey_algo ||
-	    !cert->sig.hash_algo) {
+	if (cert->unsupported_key) {
 		ret = -ENOPKG;
 		goto error_free_cert;
 	}
 
 	pr_devel("Cert Key Algo: %s\n", cert->pub->pkey_algo);
 	pr_devel("Cert Valid period: %lld-%lld\n", cert->valid_from, cert->valid_to);
-	pr_devel("Cert Signature: %s + %s\n",
-		 cert->sig.pkey_algo,
-		 cert->sig.hash_algo);
 
 	cert->pub->id_type = "X509";
 
-	/* Check the signature on the key if it appears to be self-signed */
-	if ((!cert->akid_skid && !cert->akid_id) ||
-	    asymmetric_key_id_same(cert->skid, cert->akid_skid) ||
-	    asymmetric_key_id_same(cert->id, cert->akid_id)) {
-		ret = x509_check_signature(cert->pub, cert); /* self-signed */
-		if (ret < 0)
-			goto error_free_cert;
-	} else if (!prep->trusted) {
-		ret = x509_validate_trust(cert, get_system_trusted_keyring());
-		if (ret)
-			ret = x509_validate_trust(cert, get_ima_mok_keyring());
-		if (!ret)
-			prep->trusted = 1;
+	if (cert->unsupported_sig) {
+		public_key_signature_free(cert->sig);
+		cert->sig = NULL;
+	} else {
+		pr_devel("Cert Signature: %s + %s\n",
+			 cert->sig->pkey_algo, cert->sig->hash_algo);
 	}
 
 	/* Propose a description */
@@ -353,6 +218,7 @@ static int x509_key_preparse(struct key_
 	prep->payload.data[asym_subtype] = &public_key_subtype;
 	prep->payload.data[asym_key_ids] = kids;
 	prep->payload.data[asym_crypto] = cert->pub;
+	prep->payload.data[asym_auth] = cert->sig;
 	prep->description = desc;
 	prep->quotalen = 100;
 
@@ -360,6 +226,7 @@ static int x509_key_preparse(struct key_
 	cert->pub = NULL;
 	cert->id = NULL;
 	cert->skid = NULL;
+	cert->sig = NULL;
 	desc = NULL;
 	ret = 0;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/crypto/crypto_user.c linux-libre-4.7-gnu/crypto/crypto_user.c
--- linux-libre-4.6-gnu/crypto/crypto_user.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/crypto/crypto_user.c	2016-07-24 15:23:50.000000000 -0400
@@ -455,6 +455,7 @@ static const int crypto_msg_min[CRYPTO_N
 	[CRYPTO_MSG_NEWALG	- CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
 	[CRYPTO_MSG_DELALG	- CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
 	[CRYPTO_MSG_UPDATEALG	- CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
+	[CRYPTO_MSG_GETALG	- CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
 	[CRYPTO_MSG_DELRNG	- CRYPTO_MSG_BASE] = 0,
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/crypto/drbg.c linux-libre-4.7-gnu/crypto/drbg.c
--- linux-libre-4.6-gnu/crypto/drbg.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/crypto/drbg.c	2016-07-24 15:23:50.000000000 -0400
@@ -592,8 +592,10 @@ static const struct drbg_state_ops drbg_
  ******************************************************************/
 
 #if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC)
-static int drbg_kcapi_hash(struct drbg_state *drbg, const unsigned char *key,
-			   unsigned char *outval, const struct list_head *in);
+static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *outval,
+			   const struct list_head *in);
+static void drbg_kcapi_hmacsetkey(struct drbg_state *drbg,
+				  const unsigned char *key);
 static int drbg_init_hash_kernel(struct drbg_state *drbg);
 static int drbg_fini_hash_kernel(struct drbg_state *drbg);
 #endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */
@@ -619,9 +621,11 @@ static int drbg_hmac_update(struct drbg_
 	LIST_HEAD(seedlist);
 	LIST_HEAD(vdatalist);
 
-	if (!reseed)
+	if (!reseed) {
 		/* 10.1.2.3 step 2 -- memset(0) of C is implicit with kzalloc */
 		memset(drbg->V, 1, drbg_statelen(drbg));
+		drbg_kcapi_hmacsetkey(drbg, drbg->C);
+	}
 
 	drbg_string_fill(&seed1, drbg->V, drbg_statelen(drbg));
 	list_add_tail(&seed1.list, &seedlist);
@@ -641,12 +645,13 @@ static int drbg_hmac_update(struct drbg_
 			prefix = DRBG_PREFIX1;
 		/* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */
 		seed2.buf = &prefix;
-		ret = drbg_kcapi_hash(drbg, drbg->C, drbg->C, &seedlist);
+		ret = drbg_kcapi_hash(drbg, drbg->C, &seedlist);
 		if (ret)
 			return ret;
+		drbg_kcapi_hmacsetkey(drbg, drbg->C);
 
 		/* 10.1.2.2 step 2 and 5 -- HMAC for V */
-		ret = drbg_kcapi_hash(drbg, drbg->C, drbg->V, &vdatalist);
+		ret = drbg_kcapi_hash(drbg, drbg->V, &vdatalist);
 		if (ret)
 			return ret;
 
@@ -681,7 +686,7 @@ static int drbg_hmac_generate(struct drb
 	while (len < buflen) {
 		unsigned int outlen = 0;
 		/* 10.1.2.5 step 4.1 */
-		ret = drbg_kcapi_hash(drbg, drbg->C, drbg->V, &datalist);
+		ret = drbg_kcapi_hash(drbg, drbg->V, &datalist);
 		if (ret)
 			return ret;
 		outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
@@ -796,7 +801,7 @@ static int drbg_hash_df(struct drbg_stat
 	while (len < outlen) {
 		short blocklen = 0;
 		/* 10.4.1 step 4.1 */
-		ret = drbg_kcapi_hash(drbg, NULL, tmp, entropylist);
+		ret = drbg_kcapi_hash(drbg, tmp, entropylist);
 		if (ret)
 			goto out;
 		/* 10.4.1 step 4.2 */
@@ -874,7 +879,7 @@ static int drbg_hash_process_addtl(struc
 	list_add_tail(&data1.list, &datalist);
 	list_add_tail(&data2.list, &datalist);
 	list_splice_tail(addtl, &datalist);
-	ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &datalist);
+	ret = drbg_kcapi_hash(drbg, drbg->scratchpad, &datalist);
 	if (ret)
 		goto out;
 
@@ -907,7 +912,7 @@ static int drbg_hash_hashgen(struct drbg
 	while (len < buflen) {
 		unsigned int outlen = 0;
 		/* 10.1.1.4 step hashgen 4.1 */
-		ret = drbg_kcapi_hash(drbg, NULL, dst, &datalist);
+		ret = drbg_kcapi_hash(drbg, dst, &datalist);
 		if (ret) {
 			len = ret;
 			goto out;
@@ -956,7 +961,7 @@ static int drbg_hash_generate(struct drb
 	list_add_tail(&data1.list, &datalist);
 	drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
 	list_add_tail(&data2.list, &datalist);
-	ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &datalist);
+	ret = drbg_kcapi_hash(drbg, drbg->scratchpad, &datalist);
 	if (ret) {
 		len = ret;
 		goto out;
@@ -1600,14 +1605,20 @@ static int drbg_fini_hash_kernel(struct
 	return 0;
 }
 
-static int drbg_kcapi_hash(struct drbg_state *drbg, const unsigned char *key,
-			   unsigned char *outval, const struct list_head *in)
+static void drbg_kcapi_hmacsetkey(struct drbg_state *drbg,
+				  const unsigned char *key)
+{
+	struct sdesc *sdesc = (struct sdesc *)drbg->priv_data;
+
+	crypto_shash_setkey(sdesc->shash.tfm, key, drbg_statelen(drbg));
+}
+
+static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *outval,
+			   const struct list_head *in)
 {
 	struct sdesc *sdesc = (struct sdesc *)drbg->priv_data;
 	struct drbg_string *input = NULL;
 
-	if (key)
-		crypto_shash_setkey(sdesc->shash.tfm, key, drbg_statelen(drbg));
 	crypto_shash_init(&sdesc->shash);
 	list_for_each_entry(input, in, list)
 		crypto_shash_update(&sdesc->shash, input->buf, input->len);
diff -druNp --no-dereference linux-libre-4.6-gnu/crypto/lzo.c linux-libre-4.7-gnu/crypto/lzo.c
--- linux-libre-4.6-gnu/crypto/lzo.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/crypto/lzo.c	2016-07-24 15:23:50.000000000 -0400
@@ -32,7 +32,7 @@ static int lzo_init(struct crypto_tfm *t
 	struct lzo_ctx *ctx = crypto_tfm_ctx(tfm);
 
 	ctx->lzo_comp_mem = kmalloc(LZO1X_MEM_COMPRESS,
-				    GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT);
+				    GFP_KERNEL | __GFP_NOWARN);
 	if (!ctx->lzo_comp_mem)
 		ctx->lzo_comp_mem = vmalloc(LZO1X_MEM_COMPRESS);
 	if (!ctx->lzo_comp_mem)
diff -druNp --no-dereference linux-libre-4.6-gnu/crypto/rsa-pkcs1pad.c linux-libre-4.7-gnu/crypto/rsa-pkcs1pad.c
--- linux-libre-4.6-gnu/crypto/rsa-pkcs1pad.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/crypto/rsa-pkcs1pad.c	2016-07-24 15:23:50.000000000 -0400
@@ -102,10 +102,10 @@ struct pkcs1pad_inst_ctx {
 };
 
 struct pkcs1pad_request {
-	struct akcipher_request child_req;
-
 	struct scatterlist in_sg[3], out_sg[2];
 	uint8_t *in_buf, *out_buf;
+
+	struct akcipher_request child_req;
 };
 
 static int pkcs1pad_set_pub_key(struct crypto_akcipher *tfm, const void *key,
diff -druNp --no-dereference linux-libre-4.6-gnu/crypto/testmgr.c linux-libre-4.7-gnu/crypto/testmgr.c
--- linux-libre-4.6-gnu/crypto/testmgr.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/crypto/testmgr.c	2016-07-24 15:23:50.000000000 -0400
@@ -35,6 +35,10 @@
 
 #include "internal.h"
 
+static bool notests;
+module_param(notests, bool, 0644);
+MODULE_PARM_DESC(notests, "disable crypto self-tests");
+
 #ifdef CONFIG_CRYPTO_MANAGER_DISABLE_TESTS
 
 /* a perfect nop */
@@ -3885,6 +3889,11 @@ int alg_test(const char *driver, const c
 	int j;
 	int rc;
 
+	if (!fips_enabled && notests) {
+		printk_once(KERN_INFO "alg: self-tests disabled\n");
+		return 0;
+	}
+
 	alg_test_descs_check_order();
 
 	if ((type & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_CIPHER) {
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-savu linux-libre-4.7-gnu/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-savu
--- linux-libre-4.6-gnu/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-savu	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-savu	2016-07-24 15:23:50.000000000 -0400
@@ -3,9 +3,10 @@ Date:		Mai 2012
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:	The mouse can store 5 profiles which can be switched by the
 		press of a button. A profile is split into general settings and
-		button settings. buttons holds informations about button layout.
-		When written, this file lets one write the respective profile
-		buttons to the mouse. The data has to be 47 bytes long.
+		button settings. The buttons variable holds information about
+		button layout. When written, this file lets one write the
+		respective profile buttons to the mouse. The data has to be
+		47 bytes long.
 		The mouse will reject invalid data.
 		Which profile to write is determined by the profile number
 		contained in the data.
@@ -26,8 +27,8 @@ Date:		Mai 2012
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:	The mouse can store 5 profiles which can be switched by the
 		press of a button. A profile is split into general settings and
-		button settings. profile holds informations like resolution, sensitivity
-		and light effects.
+		button settings. A profile holds information like resolution,
+		sensitivity and light effects.
 		When written, this file lets one write the respective profile
 		settings back to the mouse. The data has to be 43 bytes long.
 		The mouse will reject invalid data.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/ABI/stable/sysfs-class-ubi linux-libre-4.7-gnu/Documentation/ABI/stable/sysfs-class-ubi
--- linux-libre-4.6-gnu/Documentation/ABI/stable/sysfs-class-ubi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/ABI/stable/sysfs-class-ubi	2016-07-24 15:23:50.000000000 -0400
@@ -107,6 +107,15 @@ Contact:	Artem Bityutskiy <dedekind@infr
 Description:
 		Number of physical eraseblocks reserved for bad block handling.
 
+What:		/sys/class/ubi/ubiX/ro_mode
+Date:		April 2016
+KernelVersion:	4.7
+Contact:	linux-mtd@lists.infradead.org
+Description:
+		Contains ASCII "1\n" if the read-only flag is set on this
+		device, and "0\n" if it is cleared. UBI devices mark themselves
+		as read-only when they detect an unrecoverable error.
+
 What:		/sys/class/ubi/ubiX/total_eraseblocks
 Date:		July 2006
 KernelVersion:	2.6.22
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/ABI/testing/configfs-usb-gadget-uvc linux-libre-4.7-gnu/Documentation/ABI/testing/configfs-usb-gadget-uvc
--- linux-libre-4.6-gnu/Documentation/ABI/testing/configfs-usb-gadget-uvc	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/ABI/testing/configfs-usb-gadget-uvc	2016-07-24 15:23:50.000000000 -0400
@@ -1,6 +1,6 @@
 What:		/config/usb-gadget/gadget/functions/uvc.name
 Date:		Dec 2014
-KernelVersion:	3.20
+KernelVersion:	4.0
 Description:	UVC function directory
 
 		streaming_maxburst	- 0..15 (ss only)
@@ -9,37 +9,37 @@ Description:	UVC function directory
 
 What:		/config/usb-gadget/gadget/functions/uvc.name/control
 Date:		Dec 2014
-KernelVersion:	3.20
+KernelVersion:	4.0
 Description:	Control descriptors
 
 What:		/config/usb-gadget/gadget/functions/uvc.name/control/class
 Date:		Dec 2014
-KernelVersion:	3.20
+KernelVersion:	4.0
 Description:	Class descriptors
 
 What:		/config/usb-gadget/gadget/functions/uvc.name/control/class/ss
 Date:		Dec 2014
-KernelVersion:	3.20
+KernelVersion:	4.0
 Description:	Super speed control class descriptors
 
 What:		/config/usb-gadget/gadget/functions/uvc.name/control/class/fs
 Date:		Dec 2014
-KernelVersion:	3.20
+KernelVersion:	4.0
 Description:	Full speed control class descriptors
 
 What:		/config/usb-gadget/gadget/functions/uvc.name/control/terminal
 Date:		Dec 2014
-KernelVersion:	3.20
+KernelVersion:	4.0
 Description:	Terminal descriptors
 
 What:		/config/usb-gadget/gadget/functions/uvc.name/control/terminal/output
 Date:		Dec 2014
-KernelVersion:	3.20
+KernelVersion:	4.0
 Description:	Output terminal descriptors
 
 What:		/config/usb-gadget/gadget/functions/uvc.name/control/terminal/output/default
 Date:		Dec 2014
-KernelVersion:	3.20
+KernelVersion:	4.0
 Description:	Default output terminal descriptors
 
 		All attributes read only:
@@ -53,12 +53,12 @@ Description:	Default output terminal des
 
 What:		/config/usb-gadget/gadget/functions/uvc.name/control/terminal/camera
 Date:		Dec 2014
-KernelVersion:	3.20
+KernelVersion:	4.0
 Description:	Camera terminal descriptors
 
 What:		/config/usb-gadget/gadget/functions/uvc.name/control/terminal/camera/default
 Date:		Dec 2014
-KernelVersion:	3.20
+KernelVersion:	4.0
 Description:	Default camera terminal descriptors
 
 		All attributes read only:
@@ -75,12 +75,12 @@ Description:	Default camera terminal des
 
 What:		/config/usb-gadget/gadget/functions/uvc.name/control/processing
 Date:		Dec 2014
-KernelVersion:	3.20
+KernelVersion:	4.0
 Description:	Processing unit descriptors
 
 What:		/config/usb-gadget/gadget/functions/uvc.name/control/processing/default
 Date:		Dec 2014
-KernelVersion:	3.20
+KernelVersion:	4.0
 Description:	Default processing unit descriptors
 
 		All attributes read only:
@@ -94,49 +94,49 @@ Description:	Default processing unit des
 
 What:		/config/usb-gadget/gadget/functions/uvc.name/control/header
 Date:		Dec 2014
-KernelVersion:	3.20
+KernelVersion:	4.0
 Description:	Control header descriptors
 
 What:		/config/usb-gadget/gadget/functions/uvc.name/control/header/name
 Date:		Dec 2014
-KernelVersion:	3.20
+KernelVersion:	4.0
 Description:	Specific control header descriptors
 
 dwClockFrequency
 bcdUVC
 What:		/config/usb-gadget/gadget/functions/uvc.name/streaming
 Date:		Dec 2014
-KernelVersion:	3.20
+KernelVersion:	4.0
 Description:	Streaming descriptors
 
 What:		/config/usb-gadget/gadget/functions/uvc.name/streaming/class
 Date:		Dec 2014
-KernelVersion:	3.20
+KernelVersion:	4.0
 Description:	Streaming class descriptors
 
 What:		/config/usb-gadget/gadget/functions/uvc.name/streaming/class/ss
 Date:		Dec 2014
-KernelVersion:	3.20
+KernelVersion:	4.0
 Description:	Super speed streaming class descriptors
 
 What:		/config/usb-gadget/gadget/functions/uvc.name/streaming/class/hs
 Date:		Dec 2014
-KernelVersion:	3.20
+KernelVersion:	4.0
 Description:	High speed streaming class descriptors
 
 What:		/config/usb-gadget/gadget/functions/uvc.name/streaming/class/fs
 Date:		Dec 2014
-KernelVersion:	3.20
+KernelVersion:	4.0
 Description:	Full speed streaming class descriptors
 
 What:		/config/usb-gadget/gadget/functions/uvc.name/streaming/color_matching
 Date:		Dec 2014
-KernelVersion:	3.20
+KernelVersion:	4.0
 Description:	Color matching descriptors
 
 What:		/config/usb-gadget/gadget/functions/uvc.name/streaming/color_matching/default
 Date:		Dec 2014
-KernelVersion:	3.20
+KernelVersion:	4.0
 Description:	Default color matching descriptors
 
 		All attributes read only:
@@ -150,12 +150,12 @@ Description:	Default color matching desc
 
 What:		/config/usb-gadget/gadget/functions/uvc.name/streaming/mjpeg
 Date:		Dec 2014
-KernelVersion:	3.20
+KernelVersion:	4.0
 Description:	MJPEG format descriptors
 
 What:		/config/usb-gadget/gadget/functions/uvc.name/streaming/mjpeg/name
 Date:		Dec 2014
-KernelVersion:	3.20
+KernelVersion:	4.0
 Description:	Specific MJPEG format descriptors
 
 		All attributes read only,
@@ -174,7 +174,7 @@ Description:	Specific MJPEG format descr
 
 What:		/config/usb-gadget/gadget/functions/uvc.name/streaming/mjpeg/name/name
 Date:		Dec 2014
-KernelVersion:	3.20
+KernelVersion:	4.0
 Description:	Specific MJPEG frame descriptors
 
 		dwFrameInterval		- indicates how frame interval can be
@@ -196,12 +196,12 @@ Description:	Specific MJPEG frame descri
 
 What:		/config/usb-gadget/gadget/functions/uvc.name/streaming/uncompressed
 Date:		Dec 2014
-KernelVersion:	3.20
+KernelVersion:	4.0
 Description:	Uncompressed format descriptors
 
 What:		/config/usb-gadget/gadget/functions/uvc.name/streaming/uncompressed/name
 Date:		Dec 2014
-KernelVersion:	3.20
+KernelVersion:	4.0
 Description:	Specific uncompressed format descriptors
 
 		bmaControls		- this format's data for bmaControls in
@@ -221,7 +221,7 @@ Description:	Specific uncompressed forma
 
 What:		/config/usb-gadget/gadget/functions/uvc.name/streaming/uncompressed/name/name
 Date:		Dec 2014
-KernelVersion:	3.20
+KernelVersion:	4.0
 Description:	Specific uncompressed frame descriptors
 
 		dwFrameInterval		- indicates how frame interval can be
@@ -243,12 +243,12 @@ Description:	Specific uncompressed frame
 
 What:		/config/usb-gadget/gadget/functions/uvc.name/streaming/header
 Date:		Dec 2014
-KernelVersion:	3.20
+KernelVersion:	4.0
 Description:	Streaming header descriptors
 
 What:		/config/usb-gadget/gadget/functions/uvc.name/streaming/header/name
 Date:		Dec 2014
-KernelVersion:	3.20
+KernelVersion:	4.0
 Description:	Specific streaming header descriptors
 
 		All attributes read only:
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/ABI/testing/sysfs-block-zram linux-libre-4.7-gnu/Documentation/ABI/testing/sysfs-block-zram
--- linux-libre-4.6-gnu/Documentation/ABI/testing/sysfs-block-zram	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/ABI/testing/sysfs-block-zram	2016-07-24 15:23:50.000000000 -0400
@@ -166,3 +166,12 @@ Description:
 		The mm_stat file is read-only and represents device's mm
 		statistics (orig_data_size, compr_data_size, etc.) in a format
 		similar to block layer statistics file format.
+
+What:		/sys/block/zram<id>/debug_stat
+Date:		July 2016
+Contact:	Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
+Description:
+		The debug_stat file is read-only and represents various
+		device's debugging info useful for kernel developers. Its
+		format is not documented intentionally and may change
+		anytime without any notice.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/ABI/testing/sysfs-bus-coresight-devices-etb10 linux-libre-4.7-gnu/Documentation/ABI/testing/sysfs-bus-coresight-devices-etb10
--- linux-libre-4.6-gnu/Documentation/ABI/testing/sysfs-bus-coresight-devices-etb10	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/ABI/testing/sysfs-bus-coresight-devices-etb10	2016-07-24 15:23:50.000000000 -0400
@@ -6,13 +6,6 @@ Description:	(RW) Add/remove a sink from
 		source for a single sink.
 		ex: echo 1 > /sys/bus/coresight/devices/20010000.etb/enable_sink
 
-What:		/sys/bus/coresight/devices/<memory_map>.etb/status
-Date:		November 2014
-KernelVersion:	3.19
-Contact:	Mathieu Poirier <mathieu.poirier@linaro.org>
-Description:	(R) List various control and status registers.  The specific
-		layout and content is driver specific.
-
 What:		/sys/bus/coresight/devices/<memory_map>.etb/trigger_cntr
 Date:		November 2014
 KernelVersion:	3.19
@@ -22,3 +15,65 @@ Description:	(RW) Disables write access
 		following the trigger event. The number of 32-bit words written
 		into the Trace RAM following the trigger event is equal to the
 		value stored in this register+1 (from ARM ETB-TRM).
+
+What:		/sys/bus/coresight/devices/<memory_map>.etb/mgmt/rdp
+Date:		March 2016
+KernelVersion:	4.7
+Contact:	Mathieu Poirier <mathieu.poirier@linaro.org>
+Description:	(R) Defines the depth, in words, of the trace RAM in powers of
+		2.  The value is read directly from HW register RDP, 0x004.
+
+What:		/sys/bus/coresight/devices/<memory_map>.etb/mgmt/sts
+Date:		March 2016
+KernelVersion:	4.7
+Contact:	Mathieu Poirier <mathieu.poirier@linaro.org>
+Description:	(R) Shows the value held by the ETB status register.  The value
+		is read directly from HW register STS, 0x00C.
+
+What:		/sys/bus/coresight/devices/<memory_map>.etb/mgmt/rrp
+Date:		March 2016
+KernelVersion:	4.7
+Contact:	Mathieu Poirier <mathieu.poirier@linaro.org>
+Description:	(R) Shows the value held by the ETB RAM Read Pointer register
+		that is used to read entries from the Trace RAM over the APB
+		interface.  The value is read directly from HW register RRP,
+		0x014.
+
+What:		/sys/bus/coresight/devices/<memory_map>.etb/mgmt/rwp
+Date:		March 2016
+KernelVersion:	4.7
+Contact:	Mathieu Poirier <mathieu.poirier@linaro.org>
+Description:	(R) Shows the value held by the ETB RAM Write Pointer register
+		that is used to sets the write pointer to write entries from
+		the CoreSight bus into the Trace RAM. The value is read directly
+		from HW register RWP, 0x018.
+
+What:		/sys/bus/coresight/devices/<memory_map>.etb/mgmt/trg
+Date:		March 2016
+KernelVersion:	4.7
+Contact:	Mathieu Poirier <mathieu.poirier@linaro.org>
+Description:	(R) Similar to "trigger_cntr" above except that this value is
+		read directly from HW register TRG, 0x01C.
+
+What:		/sys/bus/coresight/devices/<memory_map>.etb/mgmt/ctl
+Date:		March 2016
+KernelVersion:	4.7
+Contact:	Mathieu Poirier <mathieu.poirier@linaro.org>
+Description:	(R) Shows the value held by the ETB Control register. The value
+		is read directly from HW register CTL, 0x020.
+
+What:		/sys/bus/coresight/devices/<memory_map>.etb/mgmt/ffsr
+Date:		March 2016
+KernelVersion:	4.7
+Contact:	Mathieu Poirier <mathieu.poirier@linaro.org>
+Description:	(R) Shows the value held by the ETB Formatter and Flush Status
+		register.  The value is read directly from HW register FFSR,
+		0x300.
+
+What:		/sys/bus/coresight/devices/<memory_map>.etb/mgmt/ffcr
+Date:		March 2016
+KernelVersion:	4.7
+Contact:	Mathieu Poirier <mathieu.poirier@linaro.org>
+Description:	(R) Shows the value held by the ETB Formatter and Flush Control
+		register.  The value is read directly from HW register FFCR,
+		0x304.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/ABI/testing/sysfs-bus-coresight-devices-etm4x linux-libre-4.7-gnu/Documentation/ABI/testing/sysfs-bus-coresight-devices-etm4x
--- linux-libre-4.6-gnu/Documentation/ABI/testing/sysfs-bus-coresight-devices-etm4x	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/ABI/testing/sysfs-bus-coresight-devices-etm4x	2016-07-24 15:23:50.000000000 -0400
@@ -359,6 +359,19 @@ Contact:	Mathieu Poirier <mathieu.poirie
 Description:	(R) Print the content of the Peripheral ID3 Register
 		(0xFEC).  The value is taken directly from the HW.
 
+What:		/sys/bus/coresight/devices/<memory_map>.etm/mgmt/trcconfig
+Date:		February 2016
+KernelVersion:	4.07
+Contact:	Mathieu Poirier <mathieu.poirier@linaro.org>
+Description:	(R) Print the content of the trace configuration register
+		(0x010) as currently set by SW.
+
+What:		/sys/bus/coresight/devices/<memory_map>.etm/mgmt/trctraceid
+Date:		February 2016
+KernelVersion:	4.07
+Contact:	Mathieu Poirier <mathieu.poirier@linaro.org>
+Description:	(R) Print the content of the trace ID register (0x040).
+
 What:		/sys/bus/coresight/devices/<memory_map>.etm/trcidr/trcidr0
 Date:		April 2015
 KernelVersion:	4.01
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/ABI/testing/sysfs-bus-coresight-devices-stm linux-libre-4.7-gnu/Documentation/ABI/testing/sysfs-bus-coresight-devices-stm
--- linux-libre-4.6-gnu/Documentation/ABI/testing/sysfs-bus-coresight-devices-stm	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/ABI/testing/sysfs-bus-coresight-devices-stm	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,53 @@
+What:		/sys/bus/coresight/devices/<memory_map>.stm/enable_source
+Date:		April 2016
+KernelVersion:	4.7
+Contact:	Mathieu Poirier <mathieu.poirier@linaro.org>
+Description:	(RW) Enable/disable tracing on this specific trace macrocell.
+		Enabling the trace macrocell implies it has been configured
+		properly and a sink has been identified for it.  The path
+		of coresight components linking the source to the sink is
+		configured and managed automatically by the coresight framework.
+
+What:		/sys/bus/coresight/devices/<memory_map>.stm/hwevent_enable
+Date:		April 2016
+KernelVersion:	4.7
+Contact:	Mathieu Poirier <mathieu.poirier@linaro.org>
+Description:	(RW) Provides access to the HW event enable register, used in
+		conjunction with HW event bank select register.
+
+What:		/sys/bus/coresight/devices/<memory_map>.stm/hwevent_select
+Date:		April 2016
+KernelVersion:	4.7
+Contact:	Mathieu Poirier <mathieu.poirier@linaro.org>
+Description:	(RW) Gives access to the HW event block select register
+		(STMHEBSR) in order to configure up to 256 channels.  Used in
+		conjunction with "hwevent_enable" register as described above.
+
+What:		/sys/bus/coresight/devices/<memory_map>.stm/port_enable
+Date:		April 2016
+KernelVersion:	4.7
+Contact:	Mathieu Poirier <mathieu.poirier@linaro.org>
+Description:	(RW) Provides access to the stimulus port enable register
+		(STMSPER).  Used in conjunction with "port_select" described
+		below.
+
+What:		/sys/bus/coresight/devices/<memory_map>.stm/port_select
+Date:		April 2016
+KernelVersion:	4.7
+Contact:	Mathieu Poirier <mathieu.poirier@linaro.org>
+Description:	(RW) Used to determine which bank of stimulus port bit in
+		register STMSPER (see above) apply to.
+
+What:		/sys/bus/coresight/devices/<memory_map>.stm/status
+Date:		April 2016
+KernelVersion:	4.7
+Contact:	Mathieu Poirier <mathieu.poirier@linaro.org>
+Description:	(R) List various control and status registers.  The specific
+		layout and content is driver specific.
+
+What:		/sys/bus/coresight/devices/<memory_map>.stm/traceid
+Date:		April 2016
+KernelVersion:	4.7
+Contact:	Mathieu Poirier <mathieu.poirier@linaro.org>
+Description:	(RW) Holds the trace ID that will appear in the trace stream
+		coming from this trace entity.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/ABI/testing/sysfs-bus-coresight-devices-tmc linux-libre-4.7-gnu/Documentation/ABI/testing/sysfs-bus-coresight-devices-tmc
--- linux-libre-4.6-gnu/Documentation/ABI/testing/sysfs-bus-coresight-devices-tmc	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/ABI/testing/sysfs-bus-coresight-devices-tmc	2016-07-24 15:23:50.000000000 -0400
@@ -6,3 +6,80 @@ Description:	(RW) Disables write access
 		formatter after a defined number of words have been stored
 		following the trigger event. Additional interface for this
 		driver are expected to be added as it matures.
+
+What:           /sys/bus/coresight/devices/<memory_map>.tmc/mgmt/rsz
+Date:           March 2016
+KernelVersion:  4.7
+Contact:        Mathieu Poirier <mathieu.poirier@linaro.org>
+Description:    (R) Defines the size, in 32-bit words, of the local RAM buffer.
+                The value is read directly from HW register RSZ, 0x004.
+
+What:           /sys/bus/coresight/devices/<memory_map>.tmc/mgmt/sts
+Date:           March 2016
+KernelVersion:  4.7
+Contact:        Mathieu Poirier <mathieu.poirier@linaro.org>
+Description:	(R) Shows the value held by the TMC status register.  The value
+                is read directly from HW register STS, 0x00C.
+
+What:		/sys/bus/coresight/devices/<memory_map>.tmc/mgmt/rrp
+Date:		March 2016
+KernelVersion:	4.7
+Contact:	Mathieu Poirier <mathieu.poirier@linaro.org>
+Description:	(R) Shows the value held by the TMC RAM Read Pointer register
+		that is used to read entries from the Trace RAM over the APB
+		interface.  The value is read directly from HW register RRP,
+		0x014.
+
+What:		/sys/bus/coresight/devices/<memory_map>.tmc/mgmt/rwp
+Date:		March 2016
+KernelVersion:	4.7
+Contact:	Mathieu Poirier <mathieu.poirier@linaro.org>
+Description:	(R) Shows the value held by the TMC RAM Write Pointer register
+		that is used to sets the write pointer to write entries from
+		the CoreSight bus into the Trace RAM. The value is read directly
+		from HW register RWP, 0x018.
+
+What:		/sys/bus/coresight/devices/<memory_map>.tmc/mgmt/trg
+Date:		March 2016
+KernelVersion:	4.7
+Contact:	Mathieu Poirier <mathieu.poirier@linaro.org>
+Description:	(R) Similar to "trigger_cntr" above except that this value is
+		read directly from HW register TRG, 0x01C.
+
+What:		/sys/bus/coresight/devices/<memory_map>.tmc/mgmt/ctl
+Date:		March 2016
+KernelVersion:	4.7
+Contact:	Mathieu Poirier <mathieu.poirier@linaro.org>
+Description:	(R) Shows the value held by the TMC Control register. The value
+		is read directly from HW register CTL, 0x020.
+
+What:		/sys/bus/coresight/devices/<memory_map>.tmc/mgmt/ffsr
+Date:		March 2016
+KernelVersion:	4.7
+Contact:	Mathieu Poirier <mathieu.poirier@linaro.org>
+Description:	(R) Shows the value held by the TMC Formatter and Flush Status
+		register.  The value is read directly from HW register FFSR,
+		0x300.
+
+What:		/sys/bus/coresight/devices/<memory_map>.tmc/mgmt/ffcr
+Date:		March 2016
+KernelVersion:	4.7
+Contact:	Mathieu Poirier <mathieu.poirier@linaro.org>
+Description:	(R) Shows the value held by the TMC Formatter and Flush Control
+		register.  The value is read directly from HW register FFCR,
+		0x304.
+
+What:		/sys/bus/coresight/devices/<memory_map>.tmc/mgmt/mode
+Date:		March 2016
+KernelVersion:	4.7
+Contact:	Mathieu Poirier <mathieu.poirier@linaro.org>
+Description:	(R) Shows the value held by the TMC Mode register, which
+		indicate the mode the device has been configured to enact.  The
+		The value is read directly from the MODE register, 0x028.
+
+What:		/sys/bus/coresight/devices/<memory_map>.tmc/mgmt/devid
+Date:		March 2016
+KernelVersion:	4.7
+Contact:	Mathieu Poirier <mathieu.poirier@linaro.org>
+Description:	(R) Indicates the capabilities of the Coresight TMC.
+		The value is read directly from the DEVID register, 0xFC8,
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/ABI/testing/sysfs-bus-event_source-devices-hv_24x7 linux-libre-4.7-gnu/Documentation/ABI/testing/sysfs-bus-event_source-devices-hv_24x7
--- linux-libre-4.6-gnu/Documentation/ABI/testing/sysfs-bus-event_source-devices-hv_24x7	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/ABI/testing/sysfs-bus-event_source-devices-hv_24x7	2016-07-24 15:23:50.000000000 -0400
@@ -4,7 +4,7 @@ Contact:	Linux on PowerPC Developer List
 Description:
 		Provides access to the binary "24x7 catalog" provided by the
 		hypervisor on POWER7 and 8 systems. This catalog lists events
-		avaliable from the powerpc "hv_24x7" pmu. Its format is
+		available from the powerpc "hv_24x7" pmu. Its format is
 		documented here:
 		https://raw.githubusercontent.com/jmesmon/catalog-24x7/master/hv-24x7-catalog.h
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/ABI/testing/sysfs-bus-iio linux-libre-4.7-gnu/Documentation/ABI/testing/sysfs-bus-iio
--- linux-libre-4.6-gnu/Documentation/ABI/testing/sysfs-bus-iio	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/ABI/testing/sysfs-bus-iio	2016-07-24 15:23:50.000000000 -0400
@@ -1233,7 +1233,7 @@ KernelVersion:	3.4
 Contact:	linux-iio@vger.kernel.org
 Description:
 		Proximity measurement indicating that some
-		object is near the sensor, usually be observing
+		object is near the sensor, usually by observing
 		reflectivity of infrared or ultrasound emitted.
 		Often these sensors are unit less and as such conversion
 		to SI units is not possible. Higher proximity measurements
@@ -1255,12 +1255,23 @@ Description:
 What:		/sys/.../iio:deviceX/in_intensityY_raw
 What:		/sys/.../iio:deviceX/in_intensityY_ir_raw
 What:		/sys/.../iio:deviceX/in_intensityY_both_raw
+What:		/sys/.../iio:deviceX/in_intensityY_uv_raw
 KernelVersion:	3.4
 Contact:	linux-iio@vger.kernel.org
 Description:
 		Unit-less light intensity. Modifiers both and ir indicate
 		that measurements contains visible and infrared light
-		components or just infrared light, respectively.
+		components or just infrared light, respectively. Modifier uv indicates
+		that measurements contain ultraviolet light components.
+
+What:		/sys/.../iio:deviceX/in_uvindex_input
+KernelVersion:	4.6
+Contact:	linux-iio@vger.kernel.org
+Description:
+		UV light intensity index measuring the human skin's response to
+		different wavelength of sunlight weighted according to the
+		standardised CIE Erythemal Action Spectrum. UV index values range
+		from 0 (low) to >=11 (extreme).
 
 What:		/sys/.../iio:deviceX/in_intensity_red_integration_time
 What:		/sys/.../iio:deviceX/in_intensity_green_integration_time
@@ -1501,3 +1512,56 @@ Contact:	linux-iio@vger.kernel.org
 Description:
 		Raw (unscaled no offset etc.) pH reading of a substance as a negative
 		base-10 logarithm of hydrodium ions in a litre of water.
+
+What:           /sys/bus/iio/devices/iio:deviceX/mount_matrix
+What:           /sys/bus/iio/devices/iio:deviceX/in_mount_matrix
+What:           /sys/bus/iio/devices/iio:deviceX/out_mount_matrix
+What:           /sys/bus/iio/devices/iio:deviceX/in_anglvel_mount_matrix
+What:           /sys/bus/iio/devices/iio:deviceX/in_accel_mount_matrix
+KernelVersion:  4.6
+Contact:        linux-iio@vger.kernel.org
+Description:
+		Mounting matrix for IIO sensors. This is a rotation matrix which
+		informs userspace about sensor chip's placement relative to the
+		main hardware it is mounted on.
+		Main hardware placement is defined according to the local
+		reference frame related to the physical quantity the sensor
+		measures.
+		Given that the rotation matrix is defined in a board specific
+		way (platform data and / or device-tree), the main hardware
+		reference frame definition is left to the implementor's choice
+		(see below for a magnetometer example).
+		Applications should apply this rotation matrix to samples so
+		that when main hardware reference frame is aligned onto local
+		reference frame, then sensor chip reference frame is also
+		perfectly aligned with it.
+		Matrix is a 3x3 unitary matrix and typically looks like
+		[0, 1, 0; 1, 0, 0; 0, 0, -1]. Identity matrix
+		[1, 0, 0; 0, 1, 0; 0, 0, 1] means sensor chip and main hardware
+		are perfectly aligned with each other.
+
+		For example, a mounting matrix for a magnetometer sensor informs
+		userspace about sensor chip's ORIENTATION relative to the main
+		hardware.
+		More specifically, main hardware orientation is defined with
+		respect to the LOCAL EARTH GEOMAGNETIC REFERENCE FRAME where :
+		* Y is in the ground plane and positive towards magnetic North ;
+		* X is in the ground plane, perpendicular to the North axis and
+		  positive towards the East ;
+		* Z is perpendicular to the ground plane and positive upwards.
+
+		An implementor might consider that for a hand-held device, a
+		'natural' orientation would be 'front facing camera at the top'.
+		The main hardware reference frame could then be described as :
+		* Y is in the plane of the screen and is positive towards the
+		  top of the screen ;
+		* X is in the plane of the screen, perpendicular to Y axis, and
+		  positive towards the right hand side of the screen ;
+		* Z is perpendicular to the screen plane and positive out of the
+		  screen.
+		Another example for a quadrotor UAV might be :
+		* Y is in the plane of the propellers and positive towards the
+		  front-view camera;
+		* X is in the plane of the propellers, perpendicular to Y axis,
+		  and positive towards the starboard side of the UAV ;
+		* Z is perpendicular to propellers plane and positive upwards.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/ABI/testing/sysfs-bus-iio-proximity-as3935 linux-libre-4.7-gnu/Documentation/ABI/testing/sysfs-bus-iio-proximity-as3935
--- linux-libre-4.6-gnu/Documentation/ABI/testing/sysfs-bus-iio-proximity-as3935	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/ABI/testing/sysfs-bus-iio-proximity-as3935	2016-07-24 15:23:50.000000000 -0400
@@ -1,4 +1,4 @@
-What		/sys/bus/iio/devices/iio:deviceX/in_proximity_raw
+What		/sys/bus/iio/devices/iio:deviceX/in_proximity_input
 Date:		March 2014
 KernelVersion:	3.15
 Contact:	Matt Ranostay <mranostay@gmail.com>
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/ABI/testing/sysfs-bus-mcb linux-libre-4.7-gnu/Documentation/ABI/testing/sysfs-bus-mcb
--- linux-libre-4.6-gnu/Documentation/ABI/testing/sysfs-bus-mcb	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/ABI/testing/sysfs-bus-mcb	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,29 @@
+What:		/sys/bus/mcb/devices/mcb:X
+Date:		March 2016
+KernelVersion:	4.7
+Contact:	Johannes Thumshirn <jth@kernel.org>
+Description:	Hardware chip or device hosting the MEN chameleon bus
+
+What:		/sys/bus/mcb/devices/mcb:X/revision
+Date:		March 2016
+KernelVersion:	4.7
+Contact:	Johannes Thumshirn <jth@kernel.org>
+Description:	The FPGA's revision number
+
+What:		/sys/bus/mcb/devices/mcb:X/minor
+Date:		March 2016
+KernelVersion:	4.7
+Contact:	Johannes Thumshirn <jth@kernel.org>
+Description:	The FPGA's minor number
+
+What:		/sys/bus/mcb/devices/mcb:X/model
+Date:		March 2016
+KernelVersion:	4.7
+Contact:	Johannes Thumshirn <jth@kernel.org>
+Description:	The FPGA's model number
+
+What:		/sys/bus/mcb/devices/mcb:X/name
+Date:		March 2016
+KernelVersion:	4.7
+Contact:	Johannes Thumshirn <jth@kernel.org>
+Description:	The FPGA's name
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/ABI/testing/sysfs-class-cxl linux-libre-4.7-gnu/Documentation/ABI/testing/sysfs-class-cxl
--- linux-libre-4.6-gnu/Documentation/ABI/testing/sysfs-class-cxl	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/ABI/testing/sysfs-class-cxl	2016-07-24 15:23:50.000000000 -0400
@@ -233,3 +233,11 @@ Description:	read/write
 		0 = don't trust, the image may be different (default)
 		1 = trust that the image will not change.
 Users:		https://github.com/ibm-capi/libcxl
+
+What:           /sys/class/cxl/<card>/psl_timebase_synced
+Date:           March 2016
+Contact:        linuxppc-dev@lists.ozlabs.org
+Description:    read only
+                Returns 1 if the psl timebase register is synchronized
+                with the core timebase register, 0 otherwise.
+Users:          https://github.com/ibm-capi/libcxl
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/ABI/testing/sysfs-class-stm linux-libre-4.7-gnu/Documentation/ABI/testing/sysfs-class-stm
--- linux-libre-4.6-gnu/Documentation/ABI/testing/sysfs-class-stm	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/ABI/testing/sysfs-class-stm	2016-07-24 15:23:50.000000000 -0400
@@ -12,3 +12,13 @@ KernelVersion:	4.3
 Contact:	Alexander Shishkin <alexander.shishkin@linux.intel.com>
 Description:
 		Shows the number of channels per master on this STM device.
+
+What:		/sys/class/stm/<stm>/hw_override
+Date:		March 2016
+KernelVersion:	4.7
+Contact:	Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Description:
+		Reads as 0 if master numbers in the STP stream produced by
+		this stm device will match the master numbers assigned by
+		the software or 1 if the stm hardware overrides software
+		assigned masters.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/ABI/testing/sysfs-driver-hid-picolcd linux-libre-4.7-gnu/Documentation/ABI/testing/sysfs-driver-hid-picolcd
--- linux-libre-4.6-gnu/Documentation/ABI/testing/sysfs-driver-hid-picolcd	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/ABI/testing/sysfs-driver-hid-picolcd	2016-07-24 15:23:50.000000000 -0400
@@ -39,5 +39,5 @@ Description:	Make it possible to adjust
 		Note: As device can barely do 2 complete refreshes a second
 		it only makes sense to adjust this value if only one or two
 		tiles get changed and it's not appropriate to expect the application
-		to flush it's tiny changes explicitely at higher than default rate.
+		to flush its tiny changes explicitly at higher than default rate.
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/ABI/testing/sysfs-firmware-acpi linux-libre-4.7-gnu/Documentation/ABI/testing/sysfs-firmware-acpi
--- linux-libre-4.6-gnu/Documentation/ABI/testing/sysfs-firmware-acpi	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/ABI/testing/sysfs-firmware-acpi	2016-07-24 15:23:50.000000000 -0400
@@ -169,7 +169,7 @@ Description:
 		to enable/disable/clear ACPI interrupts in user space, which can be
 		used to debug some ACPI interrupt storm issues.
 
-		Note that only writting to VALID GPE/Fixed Event is allowed,
+		Note that only writing to VALID GPE/Fixed Event is allowed,
 		i.e. user can only change the status of runtime GPE and
 		Fixed Event with event handler installed.
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/ABI/testing/sysfs-ibft linux-libre-4.7-gnu/Documentation/ABI/testing/sysfs-ibft
--- linux-libre-4.6-gnu/Documentation/ABI/testing/sysfs-ibft	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/ABI/testing/sysfs-ibft	2016-07-24 15:23:50.000000000 -0400
@@ -21,3 +21,13 @@ Contact:	Konrad Rzeszutek <ketuzsezr@dar
 Description:	The /sys/firmware/ibft/ethernetX directory will contain
 		files that expose the iSCSI Boot Firmware Table NIC data.
 		Usually this contains the IP address, MAC, and gateway of the NIC.
+
+What:		/sys/firmware/ibft/acpi_header
+Date:		March 2016
+Contact:	David Bond <dbond@suse.com>
+Description:	The /sys/firmware/ibft/acpi_header directory will contain files
+		that expose the SIGNATURE, OEM_ID, and OEM_TABLE_ID fields of the
+		acpi table header of the iBFT structure.  This will allow for
+		identification of the creator of the table which is useful in
+		determining quirks associated with some adapters when used in
+		hardware vs software iscsi initiator mode.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/ABI/testing/sysfs-platform-hidma linux-libre-4.7-gnu/Documentation/ABI/testing/sysfs-platform-hidma
--- linux-libre-4.6-gnu/Documentation/ABI/testing/sysfs-platform-hidma	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/ABI/testing/sysfs-platform-hidma	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,9 @@
+What:		/sys/devices/platform/hidma-*/chid
+		/sys/devices/platform/QCOM8061:*/chid
+Date:		Dec 2015
+KernelVersion:	4.4
+Contact:	"Sinan Kaya <okaya@cudeaurora.org>"
+Description:
+		Contains the ID of the channel within the HIDMA instance.
+		It is used to associate a given HIDMA channel with the
+		priority and weight calls in the management interface.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/ABI/testing/sysfs-platform-usbip-vudc linux-libre-4.7-gnu/Documentation/ABI/testing/sysfs-platform-usbip-vudc
--- linux-libre-4.6-gnu/Documentation/ABI/testing/sysfs-platform-usbip-vudc	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/ABI/testing/sysfs-platform-usbip-vudc	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,35 @@
+What:		/sys/devices/platform/usbip-vudc.%d/dev_desc
+Date:		April 2016
+KernelVersion:	4.6
+Contact:	Krzysztof Opasiak <k.opasiak@samsung.com>
+Description:
+		This file allows to read device descriptor of
+		gadget driver which is currently bound to this
+		controller. It is possible to read this file
+		only if gadget driver is bound, otherwise error
+		is returned.
+
+What:		/sys/devices/platform/usbip-vudc.%d/usbip_status
+Date:		April 2016
+KernelVersion:	4.6
+Contact:	Krzysztof Opasiak <k.opasiak@samsung.com>
+Description:
+		Current status of the device.
+		Allowed values:
+		1 - Device is available and can be exported
+		2 - Device is currently exported
+		3 - Fatal error occurred during communication
+		  with peer
+
+What:		/sys/devices/platform/usbip-vudc.%d/usbip_sockfd
+Date:		April 2016
+KernelVersion:	4.6
+Contact:	Krzysztof Opasiak <k.opasiak@samsung.com>
+Description:
+		This file allows to export usb device to
+		connection peer. It is done by writing to this
+		file socket fd (as a string for example "8")
+		associated with a connection to remote peer who
+		would like to use this device. It is possible to
+		close the connection by writing -1 instead of
+		socked fd.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/accounting/getdelays.c linux-libre-4.7-gnu/Documentation/accounting/getdelays.c
--- linux-libre-4.6-gnu/Documentation/accounting/getdelays.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/accounting/getdelays.c	2016-07-24 15:23:50.000000000 -0400
@@ -505,6 +505,8 @@ int main(int argc, char *argv[])
 						if (!loop)
 							goto done;
 						break;
+					case TASKSTATS_TYPE_NULL:
+						break;
 					default:
 						fprintf(stderr, "Unknown nested"
 							" nla_type %d\n",
@@ -512,7 +514,8 @@ int main(int argc, char *argv[])
 						break;
 					}
 					len2 += NLA_ALIGN(na->nla_len);
-					na = (struct nlattr *) ((char *) na + len2);
+					na = (struct nlattr *)((char *)na +
+							       NLA_ALIGN(na->nla_len));
 				}
 				break;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/acpi/initrd_table_override.txt linux-libre-4.7-gnu/Documentation/acpi/initrd_table_override.txt
--- linux-libre-4.6-gnu/Documentation/acpi/initrd_table_override.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/acpi/initrd_table_override.txt	2016-07-24 15:23:50.000000000 -0400
@@ -1,5 +1,5 @@
-Overriding ACPI tables via initrd
-=================================
+Upgrading ACPI tables via initrd
+================================
 
 1) Introduction (What is this about)
 2) What is this for
@@ -9,12 +9,14 @@ Overriding ACPI tables via initrd
 1) What is this about
 ---------------------
 
-If the ACPI_INITRD_TABLE_OVERRIDE compile option is true, it is possible to
-override nearly any ACPI table provided by the BIOS with an instrumented,
-modified one.
+If the ACPI_TABLE_UPGRADE compile option is true, it is possible to
+upgrade the ACPI execution environment that is defined by the ACPI tables
+via upgrading the ACPI tables provided by the BIOS with an instrumented,
+modified, more recent version one, or installing brand new ACPI tables.
 
-For a full list of ACPI tables that can be overridden, take a look at
-the char *table_sigs[MAX_ACPI_SIGNATURE]; definition in drivers/acpi/osl.c
+For a full list of ACPI tables that can be upgraded/installed, take a look
+at the char *table_sigs[MAX_ACPI_SIGNATURE]; definition in
+drivers/acpi/tables.c.
 All ACPI tables iasl (Intel's ACPI compiler and disassembler) knows should
 be overridable, except:
    - ACPI_SIG_RSDP (has a signature of 6 bytes)
@@ -25,17 +27,20 @@ Both could get implemented as well.
 2) What is this for
 -------------------
 
-Please keep in mind that this is a debug option.
-ACPI tables should not get overridden for productive use.
-If BIOS ACPI tables are overridden the kernel will get tainted with the
-TAINT_OVERRIDDEN_ACPI_TABLE flag.
-Complain to your platform/BIOS vendor if you find a bug which is so sever
-that a workaround is not accepted in the Linux kernel.
+Complain to your platform/BIOS vendor if you find a bug which is so severe
+that a workaround is not accepted in the Linux kernel. And this facility
+allows you to upgrade the buggy tables before your platform/BIOS vendor
+releases an upgraded BIOS binary.
 
-Still, it can and should be enabled in any kernel, because:
-  - There is no functional change with not instrumented initrds
-  - It provides a powerful feature to easily debug and test ACPI BIOS table
-    compatibility with the Linux kernel.
+This facility can be used by platform/BIOS vendors to provide a Linux
+compatible environment without modifying the underlying platform firmware.
+
+This facility also provides a powerful feature to easily debug and test
+ACPI BIOS table compatibility with the Linux kernel by modifying old
+platform provided ACPI tables or inserting new ACPI tables.
+
+It can and should be enabled in any kernel because there is no functional
+change with not instrumented initrds.
 
 
 3) How does it work
@@ -50,23 +55,31 @@ iasl -d *.dat
 # For example add this statement into a _PRT (PCI Routing Table) function
 # of the DSDT:
 Store("HELLO WORLD", debug)
+# And increase the OEM Revision. For example, before modification:
+DefinitionBlock ("DSDT.aml", "DSDT", 2, "INTEL ", "TEMPLATE", 0x00000000)
+# After modification:
+DefinitionBlock ("DSDT.aml", "DSDT", 2, "INTEL ", "TEMPLATE", 0x00000001)
 iasl -sa dsdt.dsl
 # Add the raw ACPI tables to an uncompressed cpio archive.
-# They must be put into a /kernel/firmware/acpi directory inside the
-# cpio archive.
-# The uncompressed cpio archive must be the first.
-# Other, typically compressed cpio archives, must be
-# concatenated on top of the uncompressed one.
+# They must be put into a /kernel/firmware/acpi directory inside the cpio
+# archive. Note that if the table put here matches a platform table
+# (similar Table Signature, and similar OEMID, and similar OEM Table ID)
+# with a more recent OEM Revision, the platform table will be upgraded by
+# this table. If the table put here doesn't match a platform table
+# (dissimilar Table Signature, or dissimilar OEMID, or dissimilar OEM Table
+# ID), this table will be appended.
 mkdir -p kernel/firmware/acpi
 cp dsdt.aml kernel/firmware/acpi
-# A maximum of: #define ACPI_OVERRIDE_TABLES 10
-# tables are  currently allowed (see osl.c):
+# A maximum of "NR_ACPI_INITRD_TABLES (64)" tables are currently allowed
+# (see osl.c):
 iasl -sa facp.dsl
 iasl -sa ssdt1.dsl
 cp facp.aml kernel/firmware/acpi
 cp ssdt1.aml kernel/firmware/acpi
-# Create the uncompressed cpio archive and concatenate the original initrd
-# on top:
+# The uncompressed cpio archive must be the first. Other, typically
+# compressed cpio archives, must be concatenated on top of the uncompressed
+# one. Following command creates the uncompressed cpio archive and
+# concatenates the original initrd on top:
 find kernel | cpio -H newc --create > /boot/instrumented_initrd
 cat /boot/initrd >>/boot/instrumented_initrd
 # reboot with increased acpi debug level, e.g. boot params:
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/adding-syscalls.txt linux-libre-4.7-gnu/Documentation/adding-syscalls.txt
--- linux-libre-4.6-gnu/Documentation/adding-syscalls.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/adding-syscalls.txt	2016-07-24 15:23:50.000000000 -0400
@@ -136,7 +136,7 @@ an fxyzzy(3) operation for free:
  - xyzzyat(fd, "", ..., AT_EMPTY_PATH) is equivalent to fxyzzy(fd, ...)
 
 (For more details on the rationale of the *at() calls, see the openat(2) man
-page; for an example of AT_EMPTY_PATH, see the statat(2) man page.)
+page; for an example of AT_EMPTY_PATH, see the fstatat(2) man page.)
 
 If your new xyzzy(2) system call involves a parameter describing an offset
 within a file, make its type loff_t so that 64-bit offsets can be supported
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/arm/SA1100/Assabet linux-libre-4.7-gnu/Documentation/arm/SA1100/Assabet
--- linux-libre-4.6-gnu/Documentation/arm/SA1100/Assabet	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/arm/SA1100/Assabet	2016-07-24 15:23:50.000000000 -0400
@@ -214,7 +214,7 @@ RedBoot scripting
 -----------------
 
 All the commands above aren't so useful if they have to be typed in every
-time the Assabet is rebooted.  Therefore it's possible to automatize the boot
+time the Assabet is rebooted.  Therefore it's possible to automate the boot
 process using RedBoot's scripting capability.
 
 For example, I use this to boot Linux with both the kernel and the ramdisk
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/arm64/booting.txt linux-libre-4.7-gnu/Documentation/arm64/booting.txt
--- linux-libre-4.6-gnu/Documentation/arm64/booting.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/arm64/booting.txt	2016-07-24 15:23:50.000000000 -0400
@@ -132,6 +132,10 @@ NOTE: versions prior to v4.6 cannot make
 physical offset of the Image so it is recommended that the Image be
 placed as close as possible to the start of system RAM.
 
+If an initrd/initramfs is passed to the kernel at boot, it must reside
+entirely within a 1 GB aligned physical memory window of up to 32 GB in
+size that fully covers the kernel Image as well.
+
 Any memory described to the kernel (even that below the start of the
 image) which is not marked as reserved from the kernel (e.g., with a
 memreserve region in the device tree) will be considered as available to
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/arm64/silicon-errata.txt linux-libre-4.7-gnu/Documentation/arm64/silicon-errata.txt
--- linux-libre-4.6-gnu/Documentation/arm64/silicon-errata.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/arm64/silicon-errata.txt	2016-07-24 15:23:50.000000000 -0400
@@ -53,7 +53,10 @@ stable kernels.
 | ARM            | Cortex-A57      | #832075         | ARM64_ERRATUM_832075    |
 | ARM            | Cortex-A57      | #852523         | N/A                     |
 | ARM            | Cortex-A57      | #834220         | ARM64_ERRATUM_834220    |
+| ARM            | MMU-500         | #841119,#826419 | N/A                     |
 |                |                 |                 |                         |
 | Cavium         | ThunderX ITS    | #22375, #24313  | CAVIUM_ERRATUM_22375    |
+| Cavium         | ThunderX ITS    | #23144          | CAVIUM_ERRATUM_23144    |
 | Cavium         | ThunderX GICv3  | #23154          | CAVIUM_ERRATUM_23154    |
 | Cavium         | ThunderX Core   | #27456          | CAVIUM_ERRATUM_27456    |
+| Cavium         | ThunderX SMMUv2 | #27704          | N/A		       |
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/block/00-INDEX linux-libre-4.7-gnu/Documentation/block/00-INDEX
--- linux-libre-4.6-gnu/Documentation/block/00-INDEX	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/block/00-INDEX	2016-07-24 15:23:50.000000000 -0400
@@ -2,6 +2,8 @@
 	- This file
 biodoc.txt
 	- Notes on the Generic Block Layer Rewrite in Linux 2.5
+biovecs.txt
+	- Immutable biovecs and biovec iterators
 capability.txt
 	- Generic Block Device Capability (/sys/block/<device>/capability)
 cfq-iosched.txt
@@ -14,6 +16,8 @@ deadline-iosched.txt
 	- Deadline IO scheduler tunables
 ioprio.txt
 	- Block io priorities (in CFQ scheduler)
+pr.txt
+	- Block layer support for Persistent Reservations
 null_blk.txt
 	- Null block for block-layer benchmarking.
 queue-sysfs.txt
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/block/queue-sysfs.txt linux-libre-4.7-gnu/Documentation/block/queue-sysfs.txt
--- linux-libre-4.6-gnu/Documentation/block/queue-sysfs.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/block/queue-sysfs.txt	2016-07-24 15:23:50.000000000 -0400
@@ -141,6 +141,15 @@ control of this block device to that new
 an IO scheduler name to this file will attempt to load that IO scheduler
 module, if it isn't already present in the system.
 
+write_cache (RW)
+----------------
+When read, this file will display whether the device has write back
+caching enabled or not. It will return "write back" for the former
+case, and "write through" for the latter. Writing to this file can
+change the kernels view of the device, but it doesn't alter the
+device state. This means that it might not be safe to toggle the
+setting from "write back" to "write through", since that will also
+eliminate cache flushes issued by the kernel.
 
 
 Jens Axboe <jens.axboe@oracle.com>, February 2009
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/block/writeback_cache_control.txt linux-libre-4.7-gnu/Documentation/block/writeback_cache_control.txt
--- linux-libre-4.6-gnu/Documentation/block/writeback_cache_control.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/block/writeback_cache_control.txt	2016-07-24 15:23:50.000000000 -0400
@@ -71,7 +71,7 @@ requests that have a payload.  For devic
 driver needs to tell the block layer that it supports flushing caches by
 doing:
 
-	blk_queue_flush(sdkp->disk->queue, REQ_FLUSH);
+	blk_queue_write_cache(sdkp->disk->queue, true, false);
 
 and handle empty REQ_FLUSH requests in its prep_fn/request_fn.  Note that
 REQ_FLUSH requests with a payload are automatically turned into a sequence
@@ -79,7 +79,7 @@ of an empty REQ_FLUSH request followed b
 layer.  For devices that also support the FUA bit the block layer needs
 to be told to pass through the REQ_FUA bit using:
 
-	blk_queue_flush(sdkp->disk->queue, REQ_FLUSH | REQ_FUA);
+	blk_queue_write_cache(sdkp->disk->queue, true, true);
 
 and the driver must handle write requests that have the REQ_FUA bit set
 in prep_fn/request_fn.  If the FUA bit is not natively supported the block
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/blockdev/zram.txt linux-libre-4.7-gnu/Documentation/blockdev/zram.txt
--- linux-libre-4.6-gnu/Documentation/blockdev/zram.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/blockdev/zram.txt	2016-07-24 15:23:50.000000000 -0400
@@ -59,27 +59,16 @@ num_devices parameter is optional and te
 pre-created. Default: 1.
 
 2) Set max number of compression streams
-	Compression backend may use up to max_comp_streams compression streams,
-	thus allowing up to max_comp_streams concurrent compression operations.
-	By default, compression backend uses single compression stream.
+	Regardless the value passed to this attribute, ZRAM will always
+	allocate multiple compression streams - one per online CPUs - thus
+	allowing several concurrent compression operations. The number of
+	allocated compression streams goes down when some of the CPUs
+	become offline. There is no single-compression-stream mode anymore,
+	unless you are running a UP system or has only 1 CPU online.
 
-	Examples:
-	#show max compression streams number
+	To find out how many streams are currently available:
 	cat /sys/block/zram0/max_comp_streams
 
-	#set max compression streams number to 3
-	echo 3 > /sys/block/zram0/max_comp_streams
-
-Note:
-In order to enable compression backend's multi stream support max_comp_streams
-must be initially set to desired concurrency level before ZRAM device
-initialisation. Once the device initialised as a single stream compression
-backend (max_comp_streams equals to 1), you will see error if you try to change
-the value of max_comp_streams because single stream compression backend
-implemented as a special case by lock overhead issue and does not support
-dynamic max_comp_streams. Only multi stream backend supports dynamic
-max_comp_streams adjustment.
-
 3) Select compression algorithm
 	Using comp_algorithm device attribute one can see available and
 	currently selected (shown in square brackets) compression algorithms,
@@ -183,6 +172,7 @@ mem_limit         RW    the maximum amou
 pages_compacted   RO    the number of pages freed during compaction
                         (available only via zram<id>/mm_stat node)
 compact           WO    trigger memory compaction
+debug_stat        RO    this file is used for zram debugging purposes
 
 WARNING
 =======
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/cgroup-v1/memory.txt linux-libre-4.7-gnu/Documentation/cgroup-v1/memory.txt
--- linux-libre-4.6-gnu/Documentation/cgroup-v1/memory.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/cgroup-v1/memory.txt	2016-07-24 15:23:50.000000000 -0400
@@ -280,17 +280,9 @@ the amount of kernel memory used by the
 different than user memory, since it can't be swapped out, which makes it
 possible to DoS the system by consuming too much of this precious resource.
 
-Kernel memory won't be accounted at all until limit on a group is set. This
-allows for existing setups to continue working without disruption.  The limit
-cannot be set if the cgroup have children, or if there are already tasks in the
-cgroup. Attempting to set the limit under those conditions will return -EBUSY.
-When use_hierarchy == 1 and a group is accounted, its children will
-automatically be accounted regardless of their limit value.
-
-After a group is first limited, it will be kept being accounted until it
-is removed. The memory limitation itself, can of course be removed by writing
--1 to memory.kmem.limit_in_bytes. In this case, kmem will be accounted, but not
-limited.
+Kernel memory accounting is enabled for all memory cgroups by default. But
+it can be disabled system-wide by passing cgroup.memory=nokmem to the kernel
+at boot time. In this case, kernel memory will not be accounted at all.
 
 Kernel memory limits are not imposed for the root cgroup. Usage for the root
 cgroup may or may not be accounted. The memory used is accumulated into
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/connector/cn_test.c linux-libre-4.7-gnu/Documentation/connector/cn_test.c
--- linux-libre-4.6-gnu/Documentation/connector/cn_test.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/connector/cn_test.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,201 +0,0 @@
-/*
- * 	cn_test.c
- * 
- * 2004+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
- * All rights reserved.
- * 
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#define pr_fmt(fmt) "cn_test: " fmt
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/skbuff.h>
-#include <linux/slab.h>
-#include <linux/timer.h>
-
-#include <linux/connector.h>
-
-static struct cb_id cn_test_id = { CN_NETLINK_USERS + 3, 0x456 };
-static char cn_test_name[] = "cn_test";
-static struct sock *nls;
-static struct timer_list cn_test_timer;
-
-static void cn_test_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
-{
-	pr_info("%s: %lu: idx=%x, val=%x, seq=%u, ack=%u, len=%d: %s.\n",
-	        __func__, jiffies, msg->id.idx, msg->id.val,
-	        msg->seq, msg->ack, msg->len,
-	        msg->len ? (char *)msg->data : "");
-}
-
-/*
- * Do not remove this function even if no one is using it as
- * this is an example of how to get notifications about new
- * connector user registration
- */
-#if 0
-static int cn_test_want_notify(void)
-{
-	struct cn_ctl_msg *ctl;
-	struct cn_notify_req *req;
-	struct cn_msg *msg = NULL;
-	int size, size0;
-	struct sk_buff *skb;
-	struct nlmsghdr *nlh;
-	u32 group = 1;
-
-	size0 = sizeof(*msg) + sizeof(*ctl) + 3 * sizeof(*req);
-
-	size = NLMSG_SPACE(size0);
-
-	skb = alloc_skb(size, GFP_ATOMIC);
-	if (!skb) {
-		pr_err("failed to allocate new skb with size=%u\n", size);
-		return -ENOMEM;
-	}
-
-	nlh = nlmsg_put(skb, 0, 0x123, NLMSG_DONE, size - sizeof(*nlh), 0);
-	if (!nlh) {
-		kfree_skb(skb);
-		return -EMSGSIZE;
-	}
-
-	msg = nlmsg_data(nlh);
-
-	memset(msg, 0, size0);
-
-	msg->id.idx = -1;
-	msg->id.val = -1;
-	msg->seq = 0x123;
-	msg->ack = 0x345;
-	msg->len = size0 - sizeof(*msg);
-
-	ctl = (struct cn_ctl_msg *)(msg + 1);
-
-	ctl->idx_notify_num = 1;
-	ctl->val_notify_num = 2;
-	ctl->group = group;
-	ctl->len = msg->len - sizeof(*ctl);
-
-	req = (struct cn_notify_req *)(ctl + 1);
-
-	/*
-	 * Idx.
-	 */
-	req->first = cn_test_id.idx;
-	req->range = 10;
-
-	/*
-	 * Val 0.
-	 */
-	req++;
-	req->first = cn_test_id.val;
-	req->range = 10;
-
-	/*
-	 * Val 1.
-	 */
-	req++;
-	req->first = cn_test_id.val + 20;
-	req->range = 10;
-
-	NETLINK_CB(skb).dst_group = ctl->group;
-	//netlink_broadcast(nls, skb, 0, ctl->group, GFP_ATOMIC);
-	netlink_unicast(nls, skb, 0, 0);
-
-	pr_info("request was sent: group=0x%x\n", ctl->group);
-
-	return 0;
-}
-#endif
-
-static u32 cn_test_timer_counter;
-static void cn_test_timer_func(unsigned long __data)
-{
-	struct cn_msg *m;
-	char data[32];
-
-	pr_debug("%s: timer fired with data %lu\n", __func__, __data);
-
-	m = kzalloc(sizeof(*m) + sizeof(data), GFP_ATOMIC);
-	if (m) {
-
-		memcpy(&m->id, &cn_test_id, sizeof(m->id));
-		m->seq = cn_test_timer_counter;
-		m->len = sizeof(data);
-
-		m->len =
-		    scnprintf(data, sizeof(data), "counter = %u",
-			      cn_test_timer_counter) + 1;
-
-		memcpy(m + 1, data, m->len);
-
-		cn_netlink_send(m, 0, 0, GFP_ATOMIC);
-		kfree(m);
-	}
-
-	cn_test_timer_counter++;
-
-	mod_timer(&cn_test_timer, jiffies + msecs_to_jiffies(1000));
-}
-
-static int cn_test_init(void)
-{
-	int err;
-
-	err = cn_add_callback(&cn_test_id, cn_test_name, cn_test_callback);
-	if (err)
-		goto err_out;
-	cn_test_id.val++;
-	err = cn_add_callback(&cn_test_id, cn_test_name, cn_test_callback);
-	if (err) {
-		cn_del_callback(&cn_test_id);
-		goto err_out;
-	}
-
-	setup_timer(&cn_test_timer, cn_test_timer_func, 0);
-	mod_timer(&cn_test_timer, jiffies + msecs_to_jiffies(1000));
-
-	pr_info("initialized with id={%u.%u}\n",
-		cn_test_id.idx, cn_test_id.val);
-
-	return 0;
-
-      err_out:
-	if (nls && nls->sk_socket)
-		sock_release(nls->sk_socket);
-
-	return err;
-}
-
-static void cn_test_fini(void)
-{
-	del_timer_sync(&cn_test_timer);
-	cn_del_callback(&cn_test_id);
-	cn_test_id.val--;
-	cn_del_callback(&cn_test_id);
-	if (nls && nls->sk_socket)
-		sock_release(nls->sk_socket);
-}
-
-module_init(cn_test_init);
-module_exit(cn_test_fini);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
-MODULE_DESCRIPTION("Connector's test module");
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/connector/connector.txt linux-libre-4.7-gnu/Documentation/connector/connector.txt
--- linux-libre-4.6-gnu/Documentation/connector/connector.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/connector/connector.txt	2016-07-24 15:23:50.000000000 -0400
@@ -186,3 +186,11 @@ only cn_test.c test module used it.
 Some work in netlink area is still being done, so things can be changed in
 2.6.15 timeframe, if it will happen, documentation will be updated for that
 kernel.
+
+/*****************************************/
+Code samples
+/*****************************************/
+
+Sample code for a connector test module and user space can be found
+in samples/connector/. To build this code, enable CONFIG_CONNECTOR
+and CONFIG_SAMPLES.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/connector/.gitignore linux-libre-4.7-gnu/Documentation/connector/.gitignore
--- linux-libre-4.6-gnu/Documentation/connector/.gitignore	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/connector/.gitignore	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-ucon
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/connector/Makefile linux-libre-4.7-gnu/Documentation/connector/Makefile
--- linux-libre-4.6-gnu/Documentation/connector/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/connector/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,16 +0,0 @@
-ifneq ($(CONFIG_CONNECTOR),)
-obj-m += cn_test.o
-endif
-
-# List of programs to build
-hostprogs-y := ucon
-
-# Tell kbuild to always build the programs
-always := $(hostprogs-y)
-
-HOSTCFLAGS_ucon.o += -I$(objtree)/usr/include
-
-all: modules
-
-modules clean:
-	$(MAKE) -C ../.. SUBDIRS=$(PWD) $@
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/connector/ucon.c linux-libre-4.7-gnu/Documentation/connector/ucon.c
--- linux-libre-4.6-gnu/Documentation/connector/ucon.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/connector/ucon.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,250 +0,0 @@
-/*
- * 	ucon.c
- *
- * Copyright (c) 2004+ Evgeniy Polyakov <zbr@ioremap.net>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <asm/types.h>
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/poll.h>
-
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
-
-#include <arpa/inet.h>
-
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <time.h>
-#include <getopt.h>
-
-#include <linux/connector.h>
-
-#define DEBUG
-#define NETLINK_CONNECTOR 	11
-
-/* Hopefully your userspace connector.h matches this kernel */
-#define CN_TEST_IDX		CN_NETLINK_USERS + 3
-#define CN_TEST_VAL		0x456
-
-#ifdef DEBUG
-#define ulog(f, a...) fprintf(stdout, f, ##a)
-#else
-#define ulog(f, a...) do {} while (0)
-#endif
-
-static int need_exit;
-static __u32 seq;
-
-static int netlink_send(int s, struct cn_msg *msg)
-{
-	struct nlmsghdr *nlh;
-	unsigned int size;
-	int err;
-	char buf[128];
-	struct cn_msg *m;
-
-	size = NLMSG_SPACE(sizeof(struct cn_msg) + msg->len);
-
-	nlh = (struct nlmsghdr *)buf;
-	nlh->nlmsg_seq = seq++;
-	nlh->nlmsg_pid = getpid();
-	nlh->nlmsg_type = NLMSG_DONE;
-	nlh->nlmsg_len = size;
-	nlh->nlmsg_flags = 0;
-
-	m = NLMSG_DATA(nlh);
-#if 0
-	ulog("%s: [%08x.%08x] len=%u, seq=%u, ack=%u.\n",
-	       __func__, msg->id.idx, msg->id.val, msg->len, msg->seq, msg->ack);
-#endif
-	memcpy(m, msg, sizeof(*m) + msg->len);
-
-	err = send(s, nlh, size, 0);
-	if (err == -1)
-		ulog("Failed to send: %s [%d].\n",
-			strerror(errno), errno);
-
-	return err;
-}
-
-static void usage(void)
-{
-	printf(
-		"Usage: ucon [options] [output file]\n"
-		"\n"
-		"\t-h\tthis help screen\n"
-		"\t-s\tsend buffers to the test module\n"
-		"\n"
-		"The default behavior of ucon is to subscribe to the test module\n"
-		"and wait for state messages.  Any ones received are dumped to the\n"
-		"specified output file (or stdout).  The test module is assumed to\n"
-		"have an id of {%u.%u}\n"
-		"\n"
-		"If you get no output, then verify the cn_test module id matches\n"
-		"the expected id above.\n"
-		, CN_TEST_IDX, CN_TEST_VAL
-	);
-}
-
-int main(int argc, char *argv[])
-{
-	int s;
-	char buf[1024];
-	int len;
-	struct nlmsghdr *reply;
-	struct sockaddr_nl l_local;
-	struct cn_msg *data;
-	FILE *out;
-	time_t tm;
-	struct pollfd pfd;
-	bool send_msgs = false;
-
-	while ((s = getopt(argc, argv, "hs")) != -1) {
-		switch (s) {
-		case 's':
-			send_msgs = true;
-			break;
-
-		case 'h':
-			usage();
-			return 0;
-
-		default:
-			/* getopt() outputs an error for us */
-			usage();
-			return 1;
-		}
-	}
-
-	if (argc != optind) {
-		out = fopen(argv[optind], "a+");
-		if (!out) {
-			ulog("Unable to open %s for writing: %s\n",
-				argv[1], strerror(errno));
-			out = stdout;
-		}
-	} else
-		out = stdout;
-
-	memset(buf, 0, sizeof(buf));
-
-	s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
-	if (s == -1) {
-		perror("socket");
-		return -1;
-	}
-
-	l_local.nl_family = AF_NETLINK;
-	l_local.nl_groups = -1; /* bitmask of requested groups */
-	l_local.nl_pid = 0;
-
-	ulog("subscribing to %u.%u\n", CN_TEST_IDX, CN_TEST_VAL);
-
-	if (bind(s, (struct sockaddr *)&l_local, sizeof(struct sockaddr_nl)) == -1) {
-		perror("bind");
-		close(s);
-		return -1;
-	}
-
-#if 0
-	{
-		int on = 0x57; /* Additional group number */
-		setsockopt(s, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &on, sizeof(on));
-	}
-#endif
-	if (send_msgs) {
-		int i, j;
-
-		memset(buf, 0, sizeof(buf));
-
-		data = (struct cn_msg *)buf;
-
-		data->id.idx = CN_TEST_IDX;
-		data->id.val = CN_TEST_VAL;
-		data->seq = seq++;
-		data->ack = 0;
-		data->len = 0;
-
-		for (j=0; j<10; ++j) {
-			for (i=0; i<1000; ++i) {
-				len = netlink_send(s, data);
-			}
-
-			ulog("%d messages have been sent to %08x.%08x.\n", i, data->id.idx, data->id.val);
-		}
-
-		return 0;
-	}
-
-
-	pfd.fd = s;
-
-	while (!need_exit) {
-		pfd.events = POLLIN;
-		pfd.revents = 0;
-		switch (poll(&pfd, 1, -1)) {
-			case 0:
-				need_exit = 1;
-				break;
-			case -1:
-				if (errno != EINTR) {
-					need_exit = 1;
-					break;
-				}
-				continue;
-		}
-		if (need_exit)
-			break;
-
-		memset(buf, 0, sizeof(buf));
-		len = recv(s, buf, sizeof(buf), 0);
-		if (len == -1) {
-			perror("recv buf");
-			close(s);
-			return -1;
-		}
-		reply = (struct nlmsghdr *)buf;
-
-		switch (reply->nlmsg_type) {
-		case NLMSG_ERROR:
-			fprintf(out, "Error message received.\n");
-			fflush(out);
-			break;
-		case NLMSG_DONE:
-			data = (struct cn_msg *)NLMSG_DATA(reply);
-
-			time(&tm);
-			fprintf(out, "%.24s : [%x.%x] [%08u.%08u].\n",
-				ctime(&tm), data->id.idx, data->id.val, data->seq, data->ack);
-			fflush(out);
-			break;
-		default:
-			break;
-		}
-	}
-
-	close(s);
-	return 0;
-}
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/device-mapper/cache-policies.txt linux-libre-4.7-gnu/Documentation/device-mapper/cache-policies.txt
--- linux-libre-4.6-gnu/Documentation/device-mapper/cache-policies.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/device-mapper/cache-policies.txt	2016-07-24 15:23:50.000000000 -0400
@@ -11,7 +11,7 @@ Every bio that is mapped by the target i
 The policy can return a simple HIT or MISS or issue a migration.
 
 Currently there's no way for the policy to issue background work,
-e.g. to start writing back dirty blocks that are going to be evicte
+e.g. to start writing back dirty blocks that are going to be evicted
 soon.
 
 Because we map bios, rather than requests it's easy for the policy
@@ -48,7 +48,7 @@ with the multiqueue (mq) policy.
 
 The smq policy (vs mq) offers the promise of less memory utilization,
 improved performance and increased adaptability in the face of changing
-workloads.  SMQ also does not have any cumbersome tuning knobs.
+workloads.  smq also does not have any cumbersome tuning knobs.
 
 Users may switch from "mq" to "smq" simply by appropriately reloading a
 DM table that is using the cache target.  Doing so will cause all of the
@@ -57,47 +57,45 @@ degrade slightly until smq recalculates
 that should be cached.
 
 Memory usage:
-The mq policy uses a lot of memory; 88 bytes per cache block on a 64
+The mq policy used a lot of memory; 88 bytes per cache block on a 64
 bit machine.
 
-SMQ uses 28bit indexes to implement it's data structures rather than
+smq uses 28bit indexes to implement it's data structures rather than
 pointers.  It avoids storing an explicit hit count for each block.  It
-has a 'hotspot' queue rather than a pre cache which uses a quarter of
+has a 'hotspot' queue, rather than a pre-cache, which uses a quarter of
 the entries (each hotspot block covers a larger area than a single
 cache block).
 
-All these mean smq uses ~25bytes per cache block.  Still a lot of
+All this means smq uses ~25bytes per cache block.  Still a lot of
 memory, but a substantial improvement nontheless.
 
 Level balancing:
-MQ places entries in different levels of the multiqueue structures
-based on their hit count (~ln(hit count)).  This means the bottom
-levels generally have the most entries, and the top ones have very
-few.  Having unbalanced levels like this reduces the efficacy of the
+mq placed entries in different levels of the multiqueue structures
+based on their hit count (~ln(hit count)).  This meant the bottom
+levels generally had the most entries, and the top ones had very
+few.  Having unbalanced levels like this reduced the efficacy of the
 multiqueue.
 
-SMQ does not maintain a hit count, instead it swaps hit entries with
-the least recently used entry from the level above.  The over all
+smq does not maintain a hit count, instead it swaps hit entries with
+the least recently used entry from the level above.  The overall
 ordering being a side effect of this stochastic process.  With this
 scheme we can decide how many entries occupy each multiqueue level,
 resulting in better promotion/demotion decisions.
 
 Adaptability:
-The MQ policy maintains a hit count for each cache block.  For a
+The mq policy maintained a hit count for each cache block.  For a
 different block to get promoted to the cache it's hit count has to
-exceed the lowest currently in the cache.  This means it can take a
+exceed the lowest currently in the cache.  This meant it could take a
 long time for the cache to adapt between varying IO patterns.
-Periodically degrading the hit counts could help with this, but I
-haven't found a nice general solution.
 
-SMQ doesn't maintain hit counts, so a lot of this problem just goes
+smq doesn't maintain hit counts, so a lot of this problem just goes
 away.  In addition it tracks performance of the hotspot queue, which
 is used to decide which blocks to promote.  If the hotspot queue is
 performing badly then it starts moving entries more quickly between
 levels.  This lets it adapt to new IO patterns very quickly.
 
 Performance:
-Testing SMQ shows substantially better performance than MQ.
+Testing smq shows substantially better performance than mq.
 
 cleaner
 -------
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/device-mapper/statistics.txt linux-libre-4.7-gnu/Documentation/device-mapper/statistics.txt
--- linux-libre-4.6-gnu/Documentation/device-mapper/statistics.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/device-mapper/statistics.txt	2016-07-24 15:23:50.000000000 -0400
@@ -205,7 +205,7 @@ statistics on them:
 
   dmsetup message vol 0 @stats_create - /100
 
-Set the auxillary data string to "foo bar baz" (the escape for each
+Set the auxiliary data string to "foo bar baz" (the escape for each
 space must also be escaped, otherwise the shell will consume them):
 
   dmsetup message vol 0 @stats_set_aux 0 foo\\ bar\\ baz
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devices.txt linux-libre-4.7-gnu/Documentation/devices.txt
--- linux-libre-4.6-gnu/Documentation/devices.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devices.txt	2016-07-24 15:23:50.000000000 -0400
@@ -1,20 +1,17 @@
 
-		    LINUX ALLOCATED DEVICES (2.6+ version)
-
-	     Maintained by Alan Cox <device@lanana.org>
-
-		      Last revised: 6th April 2009
+		    LINUX ALLOCATED DEVICES (4.x+ version)
 
 This list is the Linux Device List, the official registry of allocated
 device numbers and /dev directory nodes for the Linux operating
 system.
 
-The latest version of this list is available from
-http://www.lanana.org/docs/device-list/ or
-ftp://ftp.kernel.org/pub/linux/docs/device-list/.  This version may be
-newer than the one distributed with the Linux kernel.
-
-The LaTeX version of this document is no longer maintained.
+The LaTeX version of this document is no longer maintained, nor is
+the document that used to reside at lanana.org.  This version in the
+mainline Linux kernel is the master document.  Updates shall be sent
+as patches to the kernel maintainers (see the SubmittingPatches document).
+Specifically explore the sections titled "CHAR and MISC DRIVERS", and
+"BLOCK LAYER" in the MAINTAINERS file to find the right maintainers
+to involve for character and block devices.
 
 This document is included by reference into the Filesystem Hierarchy
 Standard (FHS).	 The FHS is available from http://www.pathname.com/fhs/.
@@ -23,60 +20,33 @@ Allocations marked (68k/Amiga) apply to
 platform only.	Allocations marked (68k/Atari) apply to Linux/68k on
 the Atari platform only.
 
-The symbol {2.6} means the allocation is obsolete and scheduled for
-removal once kernel version 2.6 (or equivalent) is released. Some of these
-allocations have already been removed.
-
-This document is in the public domain.	The author requests, however,
+This document is in the public domain.	The authors requests, however,
 that semantically altered versions are not distributed without
-permission of the author, assuming the author can be contacted without
+permission of the authors, assuming the authors can be contacted without
 an unreasonable effort.
 
-In particular, please don't sent patches for this list to Linus, at
-least not without contacting me first.
-
-I do not have any information about these devices beyond what appears
-on this list.  Any such information requests will be deleted without
-reply.
-
 
 	  **** DEVICE DRIVERS AUTHORS PLEASE READ THIS ****
 
-To have a major number allocated, or a minor number in situations
-where that applies (e.g. busmice), please contact me with the
-appropriate device information.	 Also, if you have additional
-information regarding any of the devices listed below, or if I have
-made a mistake, I would greatly appreciate a note.
+Linux now has extensive support for dynamic allocation of device numbering
+and can use sysfs and udev (systemd) to handle the naming needs. There are
+still some exceptions in the serial and boot device area. Before asking
+for a device number make sure you actually need one.
 
-I do, however, make a few requests about the nature of your report.
-This is necessary for me to be able to keep this list up to date and
-correct in a timely manner.  First of all, *please* send it to the
-correct address... <device@lanana.org>.  I receive hundreds of email
-messages a day, so mail sent to other addresses may very well get lost
-in the avalanche.  Please put in a descriptive subject, so I can find
-your mail again should I need to.  Too many people send me email
-saying just "device number request" in the subject.
+To have a major number allocated, or a minor number in situations
+where that applies (e.g. busmice), please submit a patch and send to
+the authors as indicated above.
 
-Second, please include a description of the device *in the same format
-as this list*.	The reason for this is that it is the only way I have
-found to ensure I have all the requisite information to publish your
+Keep the description of the device *in the same format
+as this list*.	The reason for this is that it is the only way we have
+found to ensure we have all the requisite information to publish your
 device and avoid conflicts.
 
-Third, please don't assume that the distributed version of the list is
-up to date.  Due to the number of registrations I have to maintain it
-in "batch mode", so there is likely additional registrations that
-haven't been listed yet.
-
-Fourth, remember that Linux now has extensive support for dynamic allocation
-of device numbering and can use sysfs and udev to handle the naming needs.
-There are still some exceptions in the serial and boot device area. Before
-asking for a device number make sure you actually need one.
-
-Finally, sometimes I have to play "namespace police."  Please don't be
-offended.  I often get submissions for /dev names that would be bound
-to cause conflicts down the road.  I am trying to avoid getting in a
+Finally, sometimes we have to play "namespace police."  Please don't be
+offended.  We often get submissions for /dev names that would be bound
+to cause conflicts down the road.  We are trying to avoid getting in a
 situation where we would have to suffer an incompatible forward
-change.  Therefore, please consult with me *before* you make your
+change.  Therefore, please consult with us *before* you make your
 device names and numbers in any way public, at least to the point
 where it would be at all difficult to get them changed.
 
@@ -3099,9 +3069,9 @@ Your cooperation is appreciated.
 		129 = /dev/ipath_sma    Device used by Subnet Management Agent
 		130 = /dev/ipath_diag   Device used by diagnostics programs
 
-234-239		UNASSIGNED
-
-240-254 char	LOCAL/EXPERIMENTAL USE
+234-254	char	RESERVED FOR DYNAMIC ASSIGNMENT
+		Character devices that request a dynamic allocation of major number will
+		take numbers starting from 254 and downward.
 
 240-254 block	LOCAL/EXPERIMENTAL USE
 		Allocated for local/experimental use.  For devices not
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/arc/eznps.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/arc/eznps.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/arc/eznps.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/arc/eznps.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,7 @@
+EZchip NPS Network Processor Platforms Device Tree Bindings
+---------------------------------------------------------------------------
+
+Appliance main board with NPS400 ASIC.
+
+Required root node properties:
+    - compatible = "ezchip,arc-nps";
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/altera/socfpga-eccmgr.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/altera/socfpga-eccmgr.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/altera/socfpga-eccmgr.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/altera/socfpga-eccmgr.txt	2016-07-24 15:23:50.000000000 -0400
@@ -3,6 +3,7 @@ This driver uses the EDAC framework to i
 The ECC Manager counts and corrects single bit errors and counts/handles
 double bit errors which are uncorrectable.
 
+Cyclone5 and Arria5 ECC Manager
 Required Properties:
 - compatible : Should be "altr,socfpga-ecc-manager"
 - #address-cells: must be 1
@@ -47,3 +48,52 @@ Example:
 			interrupts = <0 178 1>, <0 179 1>;
 		};
 	};
+
+Arria10 SoCFPGA ECC Manager
+The Arria10 SoC ECC Manager handles the IRQs for each peripheral
+in a shared register instead of individual IRQs like the Cyclone5
+and Arria5. Therefore the device tree is different as well.
+
+Required Properties:
+- compatible : Should be "altr,socfpga-a10-ecc-manager"
+- altr,sysgr-syscon : phandle to Arria10 System Manager Block
+	containing the ECC manager registers.
+- #address-cells: must be 1
+- #size-cells: must be 1
+- interrupts : Should be single bit error interrupt, then double bit error
+	interrupt. Note the rising edge type.
+- ranges : standard definition, should translate from local addresses
+
+Subcomponents:
+
+L2 Cache ECC
+Required Properties:
+- compatible : Should be "altr,socfpga-a10-l2-ecc"
+- reg : Address and size for ECC error interrupt clear registers.
+
+On-Chip RAM ECC
+Required Properties:
+- compatible : Should be "altr,socfpga-a10-ocram-ecc"
+- reg        : Address and size for ECC block registers.
+
+Example:
+
+	eccmgr: eccmgr@ffd06000 {
+		compatible = "altr,socfpga-a10-ecc-manager";
+		altr,sysmgr-syscon = <&sysmgr>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		interrupts = <0 2 IRQ_TYPE_LEVEL_HIGH>,
+			     <0 0 IRQ_TYPE_LEVEL_HIGH>;
+		ranges;
+
+		l2-ecc@ffd06010 {
+			compatible = "altr,socfpga-a10-l2-ecc";
+			reg = <0xffd06010 0x4>;
+		};
+
+		ocram-ecc@ff8c3000 {
+			compatible = "altr,socfpga-a10-ocram-ecc";
+			reg = <0xff8c3000 0x90>;
+		};
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/amlogic.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/amlogic.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/amlogic.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/amlogic.txt	2016-07-24 15:23:50.000000000 -0400
@@ -25,3 +25,6 @@ Board compatible values:
   - "tronsmart,vega-s95-pro", "tronsmart,vega-s95" (Meson gxbb)
   - "tronsmart,vega-s95-meta", "tronsmart,vega-s95" (Meson gxbb)
   - "tronsmart,vega-s95-telos", "tronsmart,vega-s95" (Meson gxbb)
+  - "hardkernel,odroid-c2" (Meson gxbb)
+  - "amlogic,p200" (Meson gxbb)
+  - "amlogic,p201" (Meson gxbb)
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/arm-boards linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/arm-boards
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/arm-boards	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/arm-boards	2016-07-24 15:23:50.000000000 -0400
@@ -93,6 +93,14 @@ Required nodes:
   a core-module with regs and the compatible strings
   "arm,core-module-versatile", "syscon"
 
+Optional nodes:
+
+- arm,versatile-ib2-syscon : if the Versatile has an IB2 interface
+  board mounted, this has a separate system controller that is
+  defined in this node.
+  Required properties:
+  compatible = "arm,versatile-ib2-syscon", "syscon"
+
 ARM RealView Boards
 -------------------
 The RealView boards cover tailored evaluation boards that are used to explore
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/atmel-at91.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/atmel-at91.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/atmel-at91.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/atmel-at91.txt	2016-07-24 15:23:50.000000000 -0400
@@ -41,6 +41,10 @@ compatible: must be one of:
        - "atmel,sama5d43"
        - "atmel,sama5d44"
 
+Chipid required properties:
+- compatible: Should be "atmel,sama5d2-chipid"
+- reg : Should contain registers location and length
+
 PIT Timer required properties:
 - compatible: Should be "atmel,at91sam9260-pit"
 - reg: Should contain registers location and length
@@ -147,6 +151,65 @@ Example:
 		clocks = <&clk32k>;
 	};
 
+SHDWC SAMA5D2-Compatible Shutdown Controller
+
+1) shdwc node
+
+required properties:
+- compatible: should be "atmel,sama5d2-shdwc".
+- reg: should contain registers location and length
+- clocks: phandle to input clock.
+- #address-cells: should be one. The cell is the wake-up input index.
+- #size-cells: should be zero.
+
+optional properties:
+
+- debounce-delay-us: minimum wake-up inputs debouncer period in
+  microseconds. It's usually a board-related property.
+- atmel,wakeup-rtc-timer: boolean to enable Real-Time Clock wake-up.
+
+The node contains child nodes for each wake-up input that the platform uses.
+
+2) input nodes
+
+Wake-up input nodes are usually described in the "board" part of the Device
+Tree. Note also that input 0 is linked to the wake-up pin and is frequently
+used.
+
+Required properties:
+- reg: should contain the wake-up input index [0 - 15].
+
+Optional properties:
+- atmel,wakeup-active-high: boolean, the corresponding wake-up input described
+  by the child, forces the wake-up of the core power supply on a high level.
+  The default is to be active low.
+
+Example:
+
+On the SoC side:
+	shdwc@f8048010 {
+		compatible = "atmel,sama5d2-shdwc";
+		reg = <0xf8048010 0x10>;
+		clocks = <&clk32k>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		atmel,wakeup-rtc-timer;
+	};
+
+On the board side:
+	shdwc@f8048010 {
+		debounce-delay-us = <976>;
+
+		input@0 {
+			reg = <0>;
+		};
+
+		input@1 {
+			reg = <1>;
+			atmel,wakeup-active-high;
+		};
+	};
+
 Special Function Registers (SFR)
 
 Special Function Registers (SFR) manage specific aspects of the integrated
@@ -155,7 +218,7 @@ elsewhere.
 
 required properties:
 - compatible: Should be "atmel,<chip>-sfr", "syscon".
-  <chip> can be "sama5d3" or "sama5d4".
+  <chip> can be "sama5d3", "sama5d4" or "sama5d2".
 - reg: Should contain registers location and length
 
 	sfr@f0038000 {
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/cci.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/cci.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/cci.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/cci.txt	2016-07-24 15:23:50.000000000 -0400
@@ -100,7 +100,7 @@ specific to ARM.
 				 "arm,cci-400-pmu,r0"
 				 "arm,cci-400-pmu,r1"
 				 "arm,cci-400-pmu"  - DEPRECATED, permitted only where OS has
-						      secure acces to CCI registers
+						      secure access to CCI registers
 				 "arm,cci-500-pmu,r0"
 				 "arm,cci-550-pmu,r0"
 		- reg:
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/coresight.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/coresight.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/coresight.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/coresight.txt	2016-07-24 15:23:50.000000000 -0400
@@ -19,6 +19,7 @@ its hardware characteristcs.
 		- "arm,coresight-etm3x", "arm,primecell";
 		- "arm,coresight-etm4x", "arm,primecell";
 		- "qcom,coresight-replicator1x", "arm,primecell";
+		- "arm,coresight-stm", "arm,primecell"; [1]
 
 	* reg: physical base address and length of the register
 	  set(s) of the component.
@@ -36,6 +37,14 @@ its hardware characteristcs.
 	  layout using the generic DT graph presentation found in
 	  "bindings/graph.txt".
 
+* Additional required properties for System Trace Macrocells (STM):
+	* reg: along with the physical base address and length of the register
+	  set as described above, another entry is required to describe the
+	  mapping of the extended stimulus port area.
+
+	* reg-names: the only acceptable values are "stm-base" and
+	  "stm-stimulus-base", each corresponding to the areas defined in "reg".
+
 * Required properties for devices that don't show up on the AMBA bus, such as
   non-configurable replicators:
 
@@ -202,3 +211,22 @@ Example:
 			};
 		};
 	};
+
+4. STM
+	stm@20100000 {
+		compatible = "arm,coresight-stm", "arm,primecell";
+		reg = <0 0x20100000 0 0x1000>,
+		      <0 0x28000000 0 0x180000>;
+		reg-names = "stm-base", "stm-stimulus-base";
+
+		clocks = <&soc_smc50mhz>;
+		clock-names = "apb_pclk";
+		port {
+			stm_out_port: endpoint {
+				remote-endpoint = <&main_funnel_in_port2>;
+			};
+		};
+	};
+
+[1]. There is currently two version of STM: STM32 and STM500.  Both
+have the same HW interface and as such don't need an explicit binding name.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/fsl.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/fsl.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/fsl.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/fsl.txt	2016-07-24 15:23:50.000000000 -0400
@@ -135,6 +135,10 @@ LS1043A ARMv8 based RDB Board
 Required root node properties:
     - compatible = "fsl,ls1043a-rdb", "fsl,ls1043a";
 
+LS1043A ARMv8 based QDS Board
+Required root node properties:
+    - compatible = "fsl,ls1043a-qds", "fsl,ls1043a";
+
 LS2080A ARMv8 based Simulator model
 Required root node properties:
     - compatible = "fsl,ls2080a-simu", "fsl,ls2080a";
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt	2016-07-24 15:23:50.000000000 -0400
@@ -1,29 +1,33 @@
 Hisilicon Platforms Device Tree Bindings
 ----------------------------------------------------
-Hi6220 SoC
-Required root node properties:
-	- compatible = "hisilicon,hi6220";
-
 Hi4511 Board
 Required root node properties:
 	- compatible = "hisilicon,hi3620-hi4511";
 
-HiP04 D01 Board
+Hi6220 SoC
 Required root node properties:
-	- compatible = "hisilicon,hip04-d01";
+	- compatible = "hisilicon,hi6220";
+
+HiKey Board
+Required root node properties:
+	- compatible = "hisilicon,hi6220-hikey", "hisilicon,hi6220";
 
 HiP01 ca9x2 Board
 Required root node properties:
 	- compatible = "hisilicon,hip01-ca9x2";
 
-HiKey Board
+HiP04 D01 Board
 Required root node properties:
-	- compatible = "hisilicon,hi6220-hikey", "hisilicon,hi6220";
+	- compatible = "hisilicon,hip04-d01";
 
 HiP05 D02 Board
 Required root node properties:
 	- compatible = "hisilicon,hip05-d02";
 
+HiP06 D03 Board
+Required root node properties:
+	- compatible = "hisilicon,hip06-d03";
+
 Hisilicon system controller
 
 Required properties:
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/l2c2x0.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/l2c2x0.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/l2c2x0.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/l2c2x0.txt	2016-07-24 15:23:50.000000000 -0400
@@ -84,6 +84,12 @@ Optional properties:
 - prefetch-instr : Instruction prefetch. Value: <0> (forcibly disable),
   <1> (forcibly enable), property absent (retain settings set by
   firmware)
+- arm,dynamic-clock-gating : L2 dynamic clock gating. Value: <0> (forcibly
+  disable), <1> (forcibly enable), property absent (OS specific behavior,
+  preferrably retain firmware settings)
+- arm,standby-mode: L2 standby mode enable. Value <0> (forcibly disable),
+  <1> (forcibly enable), property absent (OS specific behavior,
+  preferrably retain firmware settings)
 
 Example:
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,35 @@
+Marvell Armada AP806 System Controller
+======================================
+
+The AP806 is one of the two core HW blocks of the Marvell Armada 7K/8K
+SoCs. It contains a system controller, which provides a number
+registers giving access to numerous features: clocks, pin-muxing and
+many other SoC configuration items. This DT binding allows to describe
+this system controller.
+
+The Device Tree node representing the AP806 system controller provides
+a number of clocks:
+
+ - 0: clock of CPU cluster 0
+ - 1: clock of CPU cluster 1
+ - 2: fixed PLL at 1200 Mhz
+ - 3: MSS clock, derived from the fixed PLL
+
+Required properties:
+
+ - compatible: must be:
+     "marvell,ap806-system-controller", "syscon"
+ - reg: register area of the AP806 system controller
+ - #clock-cells: must be set to 1
+ - clock-output-names: must be defined to:
+    "ap-cpu-cluster-0", "ap-cpu-cluster-1", "ap-fixed", "ap-mss"
+
+Example:
+
+	syscon: system-controller@6f4000 {
+		compatible = "marvell,ap806-system-controller", "syscon";
+		#clock-cells = <1>;
+		clock-output-names = "ap-cpu-cluster-0", "ap-cpu-cluster-1",
+				     "ap-fixed", "ap-mss";
+		reg = <0x6f4000 0x1000>;
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/marvell/cp110-system-controller0.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/marvell/cp110-system-controller0.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/marvell/cp110-system-controller0.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/marvell/cp110-system-controller0.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,83 @@
+Marvell Armada CP110 System Controller 0
+========================================
+
+The CP110 is one of the two core HW blocks of the Marvell Armada 7K/8K
+SoCs. It contains two sets of system control registers, System
+Controller 0 and System Controller 1. This Device Tree binding allows
+to describe the first system controller, which provides registers to
+configure various aspects of the SoC.
+
+The Device Tree node representing this System Controller 0 provides a
+number of clocks:
+
+ - a set of core clocks
+ - a set of gatable clocks
+
+Those clocks can be referenced by other Device Tree nodes using two
+cells:
+ - The first cell must be 0 or 1. 0 for the core clocks and 1 for the
+   gatable clocks.
+ - The second cell identifies the particular core clock or gatable
+   clocks.
+
+The following clocks are available:
+ - Core clocks
+   - 0 0	APLL
+   - 0 1	PPv2 core
+   - 0 2	EIP
+   - 0 3	Core
+   - 0 4	NAND core
+ - Gatable clocks
+   - 1 0	Audio
+   - 1 1	Comm Unit
+   - 1 2	NAND
+   - 1 3	PPv2
+   - 1 4	SDIO
+   - 1 5	MG Domain
+   - 1 6	MG Core
+   - 1 7	XOR1
+   - 1 8	XOR0
+   - 1 9	GOP DP
+   - 1 11	PCIe x1 0
+   - 1 12	PCIe x1 1
+   - 1 13	PCIe x4
+   - 1 14	PCIe / XOR
+   - 1 15	SATA
+   - 1 16	SATA USB
+   - 1 17	Main
+   - 1 18	SD/MMC
+   - 1 21	Slow IO (SPI, NOR, BootROM, I2C, UART)
+   - 1 22	USB3H0
+   - 1 23	USB3H1
+   - 1 24	USB3 Device
+   - 1 25	EIP150
+   - 1 26	EIP197
+
+Required properties:
+
+ - compatible: must be:
+     "marvell,cp110-system-controller0", "syscon";
+ - reg: register area of the CP110 system controller 0
+ - #clock-cells: must be set to 2
+ - core-clock-output-names must be set to:
+	"cpm-apll", "cpm-ppv2-core", "cpm-eip", "cpm-core", "cpm-nand-core"
+ - gate-clock-output-names must be set to:
+	"cpm-audio", "cpm-communit", "cpm-nand", "cpm-ppv2", "cpm-sdio",
+	"cpm-mg-domain", "cpm-mg-core", "cpm-xor1", "cpm-xor0", "cpm-gop-dp", "none",
+	"cpm-pcie_x10", "cpm-pcie_x11", "cpm-pcie_x4", "cpm-pcie-xor", "cpm-sata",
+	"cpm-sata-usb", "cpm-main", "cpm-sd-mmc", "none", "none", "cpm-slow-io",
+	"cpm-usb3h0", "cpm-usb3h1", "cpm-usb3dev", "cpm-eip150", "cpm-eip197";
+
+Example:
+
+	cpm_syscon0: system-controller@440000 {
+		compatible = "marvell,cp110-system-controller0", "syscon";
+		reg = <0x440000 0x1000>;
+		#clock-cells = <2>;
+		core-clock-output-names = "cpm-apll", "cpm-ppv2-core", "cpm-eip", "cpm-core", "cpm-nand-core";
+		gate-clock-output-names = "cpm-audio", "cpm-communit", "cpm-nand", "cpm-ppv2", "cpm-sdio",
+			"cpm-mg-domain", "cpm-mg-core", "cpm-xor1", "cpm-xor0", "cpm-gop-dp", "none",
+			"cpm-pcie_x10", "cpm-pcie_x11", "cpm-pcie_x4", "cpm-pcie-xor", "cpm-sata",
+			"cpm-sata-usb", "cpm-main", "cpm-sd-mmc", "none", "none", "cpm-slow-io",
+			"cpm-usb3h0", "cpm-usb3h1", "cpm-usb3dev", "cpm-eip150", "cpm-eip197";
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/omap/crossbar.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/omap/crossbar.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/omap/crossbar.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/omap/crossbar.txt	2016-07-24 15:23:50.000000000 -0400
@@ -42,7 +42,8 @@ Examples:
 Consumer:
 ========
 See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt and
-Documentation/devicetree/bindings/arm/gic.txt for further details.
+Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt for
+further details.
 
 An interrupt consumer on an SoC using crossbar will use:
 	interrupts = <GIC_SPI request_number interrupt_level>
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/omap/omap.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/omap/omap.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/omap/omap.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/omap/omap.txt	2016-07-24 15:23:50.000000000 -0400
@@ -133,6 +133,9 @@ Boards:
 - AM335X Bone : Low cost community board
   compatible = "ti,am335x-bone", "ti,am33xx", "ti,omap3"
 
+- AM3359 ICEv2 : Low cost Industrial Communication Engine EVM.
+  compatible = "ti,am3359-icev2", "ti,am33xx", "ti,omap3"
+
 - AM335X OrionLXm : Substation Automation Platform
   compatible = "novatech,am335x-lxm", "ti,am33xx"
 
@@ -169,6 +172,9 @@ Boards:
 - AM57XX SBC-AM57x
   compatible = "compulab,sbc-am57x", "compulab,cl-som-am57x", "ti,am5728", "ti,dra742", "ti,dra74", "ti,dra7"
 
+- AM5728 IDK
+  compatible = "ti,am5728-idk", "ti,am5728", "ti,dra742", "ti,dra74", "ti,dra7"
+
 - DRA742 EVM:  Software Development Board for DRA742
   compatible = "ti,dra7-evm", "ti,dra742", "ti,dra74", "ti,dra7"
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/oxnas.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/oxnas.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/oxnas.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/oxnas.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,9 @@
+Oxford Semiconductor OXNAS SoCs Family device tree bindings
+-------------------------------------------
+
+Boards with the OX810SE SoC shall have the following properties:
+  Required root node property:
+    compatible: "oxsemi,ox810se"
+
+Board compatible values:
+  - "wd,mbwe" (OX810SE)
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/pmu.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/pmu.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/pmu.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/pmu.txt	2016-07-24 15:23:50.000000000 -0400
@@ -22,10 +22,11 @@ Required properties:
 	"arm,arm11mpcore-pmu"
 	"arm,arm1176-pmu"
 	"arm,arm1136-pmu"
+	"brcm,vulcan-pmu"
+	"cavium,thunder-pmu"
 	"qcom,scorpion-pmu"
 	"qcom,scorpion-mp-pmu"
 	"qcom,krait-pmu"
-	"cavium,thunder-pmu"
 - interrupts : 1 combined interrupt or 1 per core. If the interrupt is a per-cpu
                interrupt (PPI) then 1 interrupt should be specified.
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/rockchip.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/rockchip.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/rockchip.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/rockchip.txt	2016-07-24 15:23:50.000000000 -0400
@@ -39,6 +39,10 @@ Rockchip platforms device tree bindings
     Required root node properties:
       - compatible = "netxeon,r89", "rockchip,rk3288";
 
+- GeekBuying GeekBox:
+    Required root node properties:
+      - compatible = "geekbuying,geekbox", "rockchip,rk3368";
+
 - Google Brain (dev-board):
     Required root node properties:
       - compatible = "google,veyron-brain-rev0", "google,veyron-brain",
@@ -87,6 +91,10 @@ Rockchip platforms device tree bindings
 		     "google,veyron-speedy-rev3", "google,veyron-speedy-rev2",
 		     "google,veyron-speedy", "google,veyron", "rockchip,rk3288";
 
+- mqmaker MiQi:
+    Required root node properties:
+      - compatible = "mqmaker,miqi", "rockchip,rk3288";
+
 - Rockchip RK3368 evb:
     Required root node properties:
       - compatible = "rockchip,rk3368-evb-act8846", "rockchip,rk3368";
@@ -97,4 +105,8 @@ Rockchip platforms device tree bindings
 
 - Rockchip RK3228 Evaluation board:
     Required root node properties:
-      - compatible = "rockchip,rk3228-evb", "rockchip,rk3228";
+     - compatible = "rockchip,rk3228-evb", "rockchip,rk3228";
+
+- Rockchip RK3399 evb:
+    Required root node properties:
+      - compatible = "rockchip,rk3399-evb", "rockchip,rk3399";
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt	2016-07-24 15:23:50.000000000 -0400
@@ -2,6 +2,8 @@
 
 Required root node properties:
     - compatible = should be one or more of the following.
+	- "samsung,artik5"	- for Exynos3250-based Samsung ARTIK5 module.
+	- "samsung,artik5-eval" - for Exynos3250-based Samsung ARTIK5 eval board.
 	- "samsung,monk"	- for Exynos3250-based Samsung Simband board.
 	- "samsung,rinato"	- for Exynos3250-based Samsung Gear2 board.
 	- "samsung,smdkv310"	- for Exynos4210-based Samsung SMDKV310 eval board.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/spear-misc.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/spear-misc.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/spear-misc.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/spear-misc.txt	2016-07-24 15:23:50.000000000 -0400
@@ -6,4 +6,4 @@ few properties of different peripheral c
 misc node required properties:
 
 - compatible Should be	"st,spear1340-misc", "syscon".
-- reg: Address range of misc space upto 8K
+- reg: Address range of misc space up to 8K
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt	2016-07-24 15:23:50.000000000 -0400
@@ -1,16 +1,20 @@
 NVIDIA Tegra Power Management Controller (PMC)
 
+== Power Management Controller Node ==
+
 The PMC block interacts with an external Power Management Unit. The PMC
 mostly controls the entry and exit of the system from different sleep
 modes. It provides power-gating controllers for SoC and CPU power-islands.
 
 Required properties:
 - name : Should be pmc
-- compatible : For Tegra20, must contain "nvidia,tegra20-pmc".  For Tegra30,
-  must contain "nvidia,tegra30-pmc".  For Tegra114, must contain
-  "nvidia,tegra114-pmc".  For Tegra124, must contain "nvidia,tegra124-pmc".
-  Otherwise, must contain "nvidia,<chip>-pmc", plus at least one of the
-  above, where <chip> is tegra132.
+- compatible : Should contain one of the following:
+	For Tegra20 must contain "nvidia,tegra20-pmc".
+	For Tegra30 must contain "nvidia,tegra30-pmc".
+	For Tegra114 must contain "nvidia,tegra114-pmc"
+	For Tegra124 must contain "nvidia,tegra124-pmc"
+	For Tegra132 must contain "nvidia,tegra124-pmc"
+	For Tegra210 must contain "nvidia,tegra210-pmc"
 - reg : Offset and length of the register set for the device
 - clocks : Must contain an entry for each entry in clock-names.
   See ../clocks/clock-bindings.txt for details.
@@ -68,6 +72,11 @@ Optional properties for hardware-trigger
                      Defaults to 0. Valid values are described in section 12.5.2
                      "Pinmux Support" of the Tegra4 Technical Reference Manual.
 
+Optional nodes:
+- powergates : This node contains a hierarchy of power domain nodes, which
+	       should match the powergates on the Tegra SoC. See "Powergate
+	       Nodes" below.
+
 Example:
 
 / SoC dts including file
@@ -113,3 +122,76 @@ pmc@7000f400 {
 	};
 	...
 };
+
+
+== Powergate Nodes ==
+
+Each of the powergate nodes represents a power-domain on the Tegra SoC
+that can be power-gated by the Tegra PMC. The name of the powergate node
+should be one of the below. Note that not every powergate is applicable
+to all Tegra devices and the following list shows which powergates are
+applicable to which devices. Please refer to the Tegra TRM for more
+details on the various powergates.
+
+ Name		Description			Devices Applicable
+ 3d		3D Graphics			Tegra20/114/124/210
+ 3d0		3D Graphics 0			Tegra30
+ 3d1		3D Graphics 1			Tegra30
+ aud		Audio				Tegra210
+ dfd		Debug				Tegra210
+ dis		Display A			Tegra114/124/210
+ disb		Display B			Tegra114/124/210
+ heg		2D Graphics			Tegra30/114/124/210
+ iram		Internal RAM			Tegra124/210
+ mpe		MPEG Encode			All
+ nvdec		NVIDIA Video Decode Engine	Tegra210
+ nvjpg		NVIDIA JPEG Engine		Tegra210
+ pcie		PCIE				Tegra20/30/124/210
+ sata		SATA				Tegra30/124/210
+ sor		Display interfaces		Tegra124/210
+ ve2		Video Encode Engine 2		Tegra210
+ venc		Video Encode Engine		All
+ vdec		Video Decode Engine		Tegra20/30/114/124
+ vic		Video Imaging Compositor	Tegra124/210
+ xusba		USB Partition A			Tegra114/124/210
+ xusbb		USB Partition B 		Tegra114/124/210
+ xusbc		USB Partition C			Tegra114/124/210
+
+Required properties:
+  - clocks: Must contain an entry for each clock required by the PMC for
+    controlling a power-gate. See ../clocks/clock-bindings.txt for details.
+  - resets: Must contain an entry for each reset required by the PMC for
+    controlling a power-gate. See ../reset/reset.txt for details.
+  - #power-domain-cells: Must be 0.
+
+Example:
+
+	pmc: pmc@7000e400 {
+		compatible = "nvidia,tegra210-pmc";
+		reg = <0x0 0x7000e400 0x0 0x400>;
+		clocks = <&tegra_car TEGRA210_CLK_PCLK>, <&clk32k_in>;
+		clock-names = "pclk", "clk32k_in";
+
+		powergates {
+			pd_audio: aud {
+				clocks = <&tegra_car TEGRA210_CLK_APE>,
+					 <&tegra_car TEGRA210_CLK_APB2APE>;
+				resets = <&tegra_car 198>;
+				#power-domain-cells = <0>;
+			};
+		};
+	};
+
+
+== Powergate Clients ==
+
+Hardware blocks belonging to a power domain should contain a "power-domains"
+property that is a phandle pointing to the corresponding powergate node.
+
+Example:
+
+	adma: adma@702e2000 {
+		...
+		power-domains = <&pd_audio>;
+		...
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/ux500/boards.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/ux500/boards.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/arm/ux500/boards.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/arm/ux500/boards.txt	2016-07-24 15:23:50.000000000 -0400
@@ -23,7 +23,7 @@ scu:
 	see binding for arm/scu.txt
 
 interrupt-controller:
-	see binding for arm/gic.txt
+	see binding for interrupt-controller/arm,gic.txt
 
 timer:
 	see binding for arm/twd.txt
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/ata/nvidia,tegra124-ahci.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/ata/nvidia,tegra124-ahci.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/ata/nvidia,tegra124-ahci.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/ata/nvidia,tegra124-ahci.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,32 @@
+Tegra124 SoC SATA AHCI controller
+
+Required properties :
+- compatible : For Tegra124, must contain "nvidia,tegra124-ahci".  Otherwise,
+  must contain '"nvidia,<chip>-ahci", "nvidia,tegra124-ahci"', where <chip>
+  is tegra132.
+- reg : Should contain 2 entries:
+  - AHCI register set (SATA BAR5)
+  - SATA register set
+- interrupts : Defines the interrupt used by SATA
+- clocks : Must contain an entry for each entry in clock-names.
+  See ../clocks/clock-bindings.txt for details.
+- clock-names : Must include the following entries:
+  - sata
+  - sata-oob
+  - cml1
+  - pll_e
+- resets : Must contain an entry for each entry in reset-names.
+  See ../reset/reset.txt for details.
+- reset-names : Must include the following entries:
+  - sata
+  - sata-oob
+  - sata-cold
+- phys : Must contain an entry for each entry in phy-names.
+  See ../phy/phy-bindings.txt for details.
+- phy-names : Must include the following entries:
+  - sata-phy : XUSB PADCTL SATA PHY
+- hvdd-supply : Defines the SATA HVDD regulator
+- vddio-supply : Defines the SATA VDDIO regulator
+- avdd-supply : Defines the SATA AVDD regulator
+- target-5v-supply : Defines the SATA 5V power regulator
+- target-12v-supply : Defines the SATA 12V power regulator
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/ata/tegra-sata.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/ata/tegra-sata.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/ata/tegra-sata.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/ata/tegra-sata.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,32 +0,0 @@
-Tegra124 SoC SATA AHCI controller
-
-Required properties :
-- compatible : For Tegra124, must contain "nvidia,tegra124-ahci".  Otherwise,
-  must contain '"nvidia,<chip>-ahci", "nvidia,tegra124-ahci"', where <chip>
-  is tegra132.
-- reg : Should contain 2 entries:
-  - AHCI register set (SATA BAR5)
-  - SATA register set
-- interrupts : Defines the interrupt used by SATA
-- clocks : Must contain an entry for each entry in clock-names.
-  See ../clocks/clock-bindings.txt for details.
-- clock-names : Must include the following entries:
-  - sata
-  - sata-oob
-  - cml1
-  - pll_e
-- resets : Must contain an entry for each entry in reset-names.
-  See ../reset/reset.txt for details.
-- reset-names : Must include the following entries:
-  - sata
-  - sata-oob
-  - sata-cold
-- phys : Must contain an entry for each entry in phy-names.
-  See ../phy/phy-bindings.txt for details.
-- phy-names : Must include the following entries:
-  - sata-phy : XUSB PADCTL SATA PHY
-- hvdd-supply : Defines the SATA HVDD regulator
-- vddio-supply : Defines the SATA VDDIO regulator
-- avdd-supply : Defines the SATA AVDD regulator
-- target-5v-supply : Defines the SATA 5V power regulator
-- target-12v-supply : Defines the SATA 12V power regulator
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/btmrvl.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/btmrvl.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/btmrvl.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/btmrvl.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,29 +0,0 @@
-btmrvl
-------
-
-Required properties:
-
-  - compatible : must be "btmrvl,cfgdata"
-
-Optional properties:
-
-  - btmrvl,cal-data : Calibration data downloaded to the device during
-		      initialization. This is an array of 28 values(u8).
-
-  - btmrvl,gpio-gap : gpio and gap (in msecs) combination to be
-		      configured.
-
-Example:
-
-GPIO pin 13 is configured as a wakeup source and GAP is set to 100 msecs
-in below example.
-
-btmrvl {
-	compatible = "btmrvl,cfgdata";
-
-	btmrvl,cal-data = /bits/ 8 <
-		0x37 0x01 0x1c 0x00 0xff 0xff 0xff 0xff 0x01 0x7f 0x04 0x02
-		0x00 0x00 0xba 0xce 0xc0 0xc6 0x2d 0x00 0x00 0x00 0x00 0x00
-		0x00 0x00 0xf0 0x00>;
-	btmrvl,gpio-gap = <0x0d64>;
-};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/bus/ti-gpmc.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/bus/ti-gpmc.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/bus/ti-gpmc.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/bus/ti-gpmc.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,135 +0,0 @@
-Device tree bindings for OMAP general purpose memory controllers (GPMC)
-
-The actual devices are instantiated from the child nodes of a GPMC node.
-
-Required properties:
-
- - compatible:		Should be set to one of the following:
-
-			ti,omap2420-gpmc (omap2420)
-			ti,omap2430-gpmc (omap2430)
-			ti,omap3430-gpmc (omap3430 & omap3630)
-			ti,omap4430-gpmc (omap4430 & omap4460 & omap543x)
-			ti,am3352-gpmc   (am335x devices)
-
- - reg:			A resource specifier for the register space
-			(see the example below)
- - ti,hwmods:		Should be set to "ti,gpmc" until the DT transition is
-			completed.
- - #address-cells:	Must be set to 2 to allow memory address translation
- - #size-cells:		Must be set to 1 to allow CS address passing
- - gpmc,num-cs:		The maximum number of chip-select lines that controller
-			can support.
- - gpmc,num-waitpins:	The maximum number of wait pins that controller can
-			support.
- - ranges:		Must be set up to reflect the memory layout with four
-			integer values for each chip-select line in use:
-
-			   <cs-number> 0 <physical address of mapping> <size>
-
-			Currently, calculated values derived from the contents
-			of the per-CS register GPMC_CONFIG7 (as set up by the
-			bootloader) are used for the physical address decoding.
-			As this will change in the future, filling correct
-			values here is a requirement.
-
-Timing properties for child nodes. All are optional and default to 0.
-
- - gpmc,sync-clk-ps:	Minimum clock period for synchronous mode, in picoseconds
-
- Chip-select signal timings (in nanoseconds) corresponding to GPMC_CONFIG2:
- - gpmc,cs-on-ns:	Assertion time
- - gpmc,cs-rd-off-ns:	Read deassertion time
- - gpmc,cs-wr-off-ns:	Write deassertion time
-
- ADV signal timings (in nanoseconds) corresponding to GPMC_CONFIG3:
- - gpmc,adv-on-ns:	Assertion time
- - gpmc,adv-rd-off-ns:	Read deassertion time
- - gpmc,adv-wr-off-ns:	Write deassertion time
- - gpmc,adv-aad-mux-on-ns:	Assertion time for AAD
- - gpmc,adv-aad-mux-rd-off-ns:	Read deassertion time for AAD
- - gpmc,adv-aad-mux-wr-off-ns:	Write deassertion time for AAD
-
- WE signals timings (in nanoseconds) corresponding to GPMC_CONFIG4:
- - gpmc,we-on-ns	Assertion time
- - gpmc,we-off-ns:	Deassertion time
-
- OE signals timings (in nanoseconds) corresponding to GPMC_CONFIG4:
- - gpmc,oe-on-ns:	Assertion time
- - gpmc,oe-off-ns:	Deassertion time
- - gpmc,oe-aad-mux-on-ns:	Assertion time for AAD
- - gpmc,oe-aad-mux-off-ns:	Deassertion time for AAD
-
- Access time and cycle time timings (in nanoseconds) corresponding to
- GPMC_CONFIG5:
- - gpmc,page-burst-access-ns: 	Multiple access word delay
- - gpmc,access-ns:		Start-cycle to first data valid delay
- - gpmc,rd-cycle-ns:		Total read cycle time
- - gpmc,wr-cycle-ns:		Total write cycle time
- - gpmc,bus-turnaround-ns:	Turn-around time between successive accesses
- - gpmc,cycle2cycle-delay-ns:	Delay between chip-select pulses
- - gpmc,clk-activation-ns: 	GPMC clock activation time
- - gpmc,wait-monitoring-ns:	Start of wait monitoring with regard to valid
-				data
-
-Boolean timing parameters. If property is present parameter enabled and
-disabled if omitted:
- - gpmc,adv-extra-delay:	ADV signal is delayed by half GPMC clock
- - gpmc,cs-extra-delay:		CS signal is delayed by half GPMC clock
- - gpmc,cycle2cycle-diffcsen:	Add "cycle2cycle-delay" between successive
-				accesses to a different CS
- - gpmc,cycle2cycle-samecsen:	Add "cycle2cycle-delay" between successive
-				accesses to the same CS
- - gpmc,oe-extra-delay:		OE signal is delayed by half GPMC clock
- - gpmc,we-extra-delay:		WE signal is delayed by half GPMC clock
- - gpmc,time-para-granularity:	Multiply all access times by 2
-
-The following are only applicable to OMAP3+ and AM335x:
- - gpmc,wr-access-ns:		In synchronous write mode, for single or
-				burst accesses, defines the number of
-				GPMC_FCLK cycles from start access time
-				to the GPMC_CLK rising edge used by the
-				memory device for the first data capture.
- - gpmc,wr-data-mux-bus-ns:	In address-data multiplex mode, specifies
-				the time when the first data is driven on
-				the address-data bus.
-
-GPMC chip-select settings properties for child nodes. All are optional.
-
-- gpmc,burst-length	Page/burst length. Must be 4, 8 or 16.
-- gpmc,burst-wrap	Enables wrap bursting
-- gpmc,burst-read	Enables read page/burst mode
-- gpmc,burst-write	Enables write page/burst mode
-- gpmc,device-width	Total width of device(s) connected to a GPMC
-			chip-select in bytes. The GPMC supports 8-bit
-			and 16-bit devices and so this property must be
-			1 or 2.
-- gpmc,mux-add-data	Address and data multiplexing configuration.
-			Valid values are 1 for address-address-data
-			multiplexing mode and 2 for address-data
-			multiplexing mode.
-- gpmc,sync-read	Enables synchronous read. Defaults to asynchronous
-			is this is not set.
-- gpmc,sync-write	Enables synchronous writes. Defaults to asynchronous
-			is this is not set.
-- gpmc,wait-pin		Wait-pin used by client. Must be less than
-			"gpmc,num-waitpins".
-- gpmc,wait-on-read	Enables wait monitoring on reads.
-- gpmc,wait-on-write	Enables wait monitoring on writes.
-
-Example for an AM33xx board:
-
-	gpmc: gpmc@50000000 {
-		compatible = "ti,am3352-gpmc";
-		ti,hwmods = "gpmc";
-		reg = <0x50000000 0x2000>;
-		interrupts = <100>;
-
-		gpmc,num-cs = <8>;
-		gpmc,num-waitpins = <2>;
-		#address-cells = <2>;
-		#size-cells = <1>;
-		ranges = <0 0 0x08000000 0x10000000>; /* CS0 @addr 0x8000000, size 0x10000000 */
-
-		/* child nodes go here */
-	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/clock/artpec6.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/clock/artpec6.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/clock/artpec6.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/clock/artpec6.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,41 @@
+* Clock bindings for Axis ARTPEC-6 chip
+
+The bindings are based on the clock provider binding in
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+External clocks:
+----------------
+
+There are two external inputs to the main clock controller which should be
+provided using the common clock bindings.
+- "sys_refclk": External 50 Mhz oscillator (required)
+- "i2s_refclk": Alternate audio reference clock (optional).
+
+Main clock controller
+---------------------
+
+Required properties:
+- #clock-cells: Should be <1>
+  See dt-bindings/clock/axis,artpec6-clkctrl.h for the list of valid identifiers.
+- compatible: Should be "axis,artpec6-clkctrl"
+- reg: Must contain the base address and length of the system controller
+- clocks:  Must contain a phandle entry for each clock in clock-names
+- clock-names: Must include the external oscillator ("sys_refclk"). Optional
+  ones are the audio reference clock ("i2s_refclk") and the audio fractional
+  dividers ("frac_clk0" and "frac_clk1").
+
+Examples:
+
+ext_clk: ext_clk {
+	#clock-cells = <0>;
+	compatible = "fixed-clock";
+	clock-frequency = <50000000>;
+};
+
+clkctrl: clkctrl@f8000000 {
+	#clock-cells = <1>;
+	compatible = "axis,artpec6-clkctrl";
+	reg = <0xf8000000 0x48>;
+	clocks = <&ext_clk>;
+	clock-names = "sys_refclk";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/clock/axs10x-i2s-pll-clock.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/clock/axs10x-i2s-pll-clock.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/clock/axs10x-i2s-pll-clock.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/clock/axs10x-i2s-pll-clock.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,25 @@
+Binding for the AXS10X I2S PLL clock
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible: shall be "snps,axs10x-i2s-pll-clock"
+- reg : address and length of the I2S PLL register set.
+- clocks: shall be the input parent clock phandle for the PLL.
+- #clock-cells: from common clock binding; Should always be set to 0.
+
+Example:
+	pll_clock: pll_clock {
+		compatible = "fixed-clock";
+		clock-frequency = <27000000>;
+		#clock-cells = <0>;
+	};
+
+	i2s_clock@100a0 {
+		compatible = "snps,axs10x-i2s-pll-clock";
+		reg = <0x100a0 0x10>;
+		clocks = <&pll_clock>;
+		#clock-cells = <0>;
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/clock/hi3519-crg.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/clock/hi3519-crg.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/clock/hi3519-crg.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/clock/hi3519-crg.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,46 @@
+* Hisilicon Hi3519 Clock and Reset Generator(CRG)
+
+The Hi3519 CRG module provides clock and reset signals to various
+controllers within the SoC.
+
+This binding uses the following bindings:
+    Documentation/devicetree/bindings/clock/clock-bindings.txt
+    Documentation/devicetree/bindings/reset/reset.txt
+
+Required Properties:
+
+- compatible: should be one of the following.
+  - "hisilicon,hi3519-crg" - controller compatible with Hi3519 SoC.
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- #clock-cells: should be 1.
+
+Each clock is assigned an identifier and client nodes use this identifier
+to specify the clock which they consume.
+
+All these identifier could be found in <dt-bindings/clock/hi3519-clock.h>.
+
+- #reset-cells: should be 2.
+
+A reset signal can be controlled by writing a bit register in the CRG module.
+The reset specifier consists of two cells. The first cell represents the
+register offset relative to the base address. The second cell represents the
+bit index in the register.
+
+Example: CRG nodes
+CRG: clock-reset-controller@12010000 {
+	compatible = "hisilicon,hi3519-crg";
+	reg = <0x12010000 0x10000>;
+	#clock-cells = <1>;
+	#reset-cells = <2>;
+};
+
+Example: consumer nodes
+i2c0: i2c@12110000 {
+	compatible = "hisilicon,hi3519-i2c";
+	reg = <0x12110000 0x1000>;
+	clocks = <&CRG HI3519_I2C0_RST>;
+	resets = <&CRG 0xe4 0>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/clock/imx35-clock.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/clock/imx35-clock.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/clock/imx35-clock.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/clock/imx35-clock.txt	2016-07-24 15:23:50.000000000 -0400
@@ -94,6 +94,7 @@ clocks and IDs.
 	csi_sel			79
 	iim_gate		80
 	gpu2d_gate		81
+	ckli_gate		82
 
 Examples:
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/clock/microchip,pic32.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/clock/microchip,pic32.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/clock/microchip,pic32.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/clock/microchip,pic32.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,39 @@
+Microchip PIC32 Clock Controller Binding
+----------------------------------------
+Microchip clock controller is consists of few oscillators, PLL, multiplexer
+and few divider modules.
+
+This binding uses common clock bindings.
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible: shall be "microchip,pic32mzda-clk".
+- reg: shall contain base address and length of clock registers.
+- #clock-cells: shall be 1.
+
+Optional properties:
+- microchip,pic32mzda-sosc: shall be added only if platform has
+  secondary oscillator connected.
+
+Example:
+	rootclk: clock-controller@1f801200 {
+		compatible = "microchip,pic32mzda-clk";
+		reg = <0x1f801200 0x200>;
+		#clock-cells = <1>;
+		/* optional */
+		microchip,pic32mzda-sosc;
+	};
+
+
+The clock consumer shall specify the desired clock-output of the clock
+controller (as defined in [2]) by specifying output-id in its "clock"
+phandle cell.
+[2] include/dt-bindings/clock/microchip,pic32-clock.h
+
+For example for UART2:
+uart2: serial@2 {
+	compatible = "microchip,pic32mzda-uart";
+	reg = <>;
+	interrupts = <>;
+	clocks = <&rootclk PB2CLK>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.txt	2016-07-24 15:23:50.000000000 -0400
@@ -50,7 +50,7 @@ Required properties for I2C mode:
 
 Example:
 
-clock@0,70110000 {
+clock@70110000 {
         compatible = "nvidia,tegra124-dfll";
         reg = <0 0x70110000 0 0x100>, /* DFLL control */
               <0 0x70110000 0 0x100>, /* I2C output control */
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/clock/oxnas,stdclk.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/clock/oxnas,stdclk.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/clock/oxnas,stdclk.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/clock/oxnas,stdclk.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,35 @@
+Oxford Semiconductor OXNAS SoC Family Standard Clocks
+================================================
+
+Please also refer to clock-bindings.txt in this directory for common clock
+bindings usage.
+
+Required properties:
+- compatible: Should be "oxsemi,ox810se-stdclk"
+- #clock-cells: 1, see below
+
+Parent node should have the following properties :
+- compatible: Should be "oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd"
+
+For OX810SE, the clock indices are :
+ - 0: LEON
+ - 1: DMA_SGDMA
+ - 2: CIPHER
+ - 3: SATA
+ - 4: AUDIO
+ - 5: USBMPH
+ - 6: ETHA
+ - 7: PCIA
+ - 8: NAND
+
+example:
+
+sys: sys-ctrl@000000 {
+	compatible = "oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd";
+	reg = <0x000000 0x100000>;
+
+	stdclk: stdclk {
+		compatible = "oxsemi,ox810se-stdclk";
+		#clock-cells = <1>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/clock/rockchip,rk3188-cru.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/clock/rockchip,rk3188-cru.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/clock/rockchip,rk3188-cru.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/clock/rockchip,rk3188-cru.txt	2016-07-24 15:23:50.000000000 -0400
@@ -16,7 +16,7 @@ Required Properties:
 Optional Properties:
 
 - rockchip,grf: phandle to the syscon managing the "general register files"
-  If missing pll rates are not changable, due to the missing pll lock status.
+  If missing pll rates are not changeable, due to the missing pll lock status.
 
 Each clock is assigned an identifier and client nodes can use this identifier
 to specify the clock which they consume. All available clocks are defined as
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/clock/rockchip,rk3288-cru.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/clock/rockchip,rk3288-cru.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/clock/rockchip,rk3288-cru.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/clock/rockchip,rk3288-cru.txt	2016-07-24 15:23:50.000000000 -0400
@@ -15,7 +15,7 @@ Required Properties:
 Optional Properties:
 
 - rockchip,grf: phandle to the syscon managing the "general register files"
-  If missing pll rates are not changable, due to the missing pll lock status.
+  If missing pll rates are not changeable, due to the missing pll lock status.
 
 Each clock is assigned an identifier and client nodes can use this identifier
 to specify the clock which they consume. All available clocks are defined as
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/clock/rockchip,rk3399-cru.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/clock/rockchip,rk3399-cru.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/clock/rockchip,rk3399-cru.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/clock/rockchip,rk3399-cru.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,62 @@
+* Rockchip RK3399 Clock and Reset Unit
+
+The RK3399 clock controller generates and supplies clock to various
+controllers within the SoC and also implements a reset controller for SoC
+peripherals.
+
+Required Properties:
+
+- compatible: PMU for CRU should be "rockchip,rk3399-pmucru"
+- compatible: CRU should be "rockchip,rk3399-cru"
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- #clock-cells: should be 1.
+- #reset-cells: should be 1.
+
+Each clock is assigned an identifier and client nodes can use this identifier
+to specify the clock which they consume. All available clocks are defined as
+preprocessor macros in the dt-bindings/clock/rk3399-cru.h headers and can be
+used in device tree sources. Similar macros exist for the reset sources in
+these files.
+
+External clocks:
+
+There are several clocks that are generated outside the SoC. It is expected
+that they are defined using standard clock bindings with following
+clock-output-names:
+ - "xin24m" - crystal input - required,
+ - "xin32k" - rtc clock - optional,
+ - "clkin_gmac" - external GMAC clock - optional,
+ - "clkin_i2s" - external I2S clock - optional,
+ - "pclkin_cif" - external ISP clock - optional,
+ - "clk_usbphy0_480m" - output clock of the pll in the usbphy0
+ - "clk_usbphy1_480m" - output clock of the pll in the usbphy1
+
+Example: Clock controller node:
+
+	pmucru: pmu-clock-controller@ff750000 {
+		compatible = "rockchip,rk3399-pmucru";
+		reg = <0x0 0xff750000 0x0 0x1000>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
+	cru: clock-controller@ff760000 {
+		compatible = "rockchip,rk3399-cru";
+		reg = <0x0 0xff760000 0x0 0x1000>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
+Example: UART controller node that consumes the clock generated by the clock
+  controller:
+
+	uart0: serial@ff1a0000 {
+		compatible = "rockchip,rk3399-uart", "snps,dw-apb-uart";
+		reg = <0x0 0xff180000 0x0 0x100>;
+		clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>;
+		clock-names = "baudclk", "apb_pclk";
+		interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/clock/st/st,clkgen.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/clock/st/st,clkgen.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/clock/st/st,clkgen.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/clock/st/st,clkgen.txt	2016-07-24 15:23:50.000000000 -0400
@@ -40,7 +40,7 @@ address is common of all subnode.
 	};
 
 This binding uses the common clock binding[1].
-Each subnode should use the binding discribe in [2]..[7]
+Each subnode should use the binding described in [2]..[7]
 
 [1] Documentation/devicetree/bindings/clock/clock-bindings.txt
 [2] Documentation/devicetree/bindings/clock/st,clkgen-divmux.txt
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/clock/sunxi.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/clock/sunxi.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/clock/sunxi.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/clock/sunxi.txt	2016-07-24 15:23:50.000000000 -0400
@@ -10,6 +10,7 @@ Required properties:
 	"allwinner,sun4i-a10-pll1-clk" - for the main PLL clock and PLL4
 	"allwinner,sun6i-a31-pll1-clk" - for the main PLL clock on A31
 	"allwinner,sun8i-a23-pll1-clk" - for the main PLL clock on A23
+	"allwinner,sun4i-a10-pll3-clk" - for the video PLL clock on A10
 	"allwinner,sun9i-a80-pll4-clk" - for the peripheral PLLs on A80
 	"allwinner,sun4i-a10-pll5-clk" - for the PLL5 clock
 	"allwinner,sun4i-a10-pll6-clk" - for the PLL6 clock
@@ -63,7 +64,9 @@ Required properties:
 	"allwinner,sun8i-a83t-bus-gates-clk" - for the bus gates on A83T
 	"allwinner,sun8i-h3-bus-gates-clk" - for the bus gates on H3
 	"allwinner,sun9i-a80-apbs-gates-clk" - for the APBS gates on A80
+	"allwinner,sun4i-a10-display-clk" - for the display clocks on the A10
 	"allwinner,sun4i-a10-dram-gates-clk" - for the DRAM gates on A10
+	"allwinner,sun5i-a13-dram-gates-clk" - for the DRAM gates on A13
 	"allwinner,sun5i-a13-mbus-clk" - for the MBUS clock on A13
 	"allwinner,sun4i-a10-mmc-clk" - for the MMC clock
 	"allwinner,sun9i-a80-mmc-clk" - for mmc module clocks on A80
@@ -73,6 +76,8 @@ Required properties:
 	"allwinner,sun8i-a23-mbus-clk" - for the MBUS clock on A23
 	"allwinner,sun7i-a20-out-clk" - for the external output clocks
 	"allwinner,sun7i-a20-gmac-clk" - for the GMAC clock module on A20/A31
+	"allwinner,sun4i-a10-tcon-ch0-clk" - for the TCON channel 0 clock on the A10
+	"allwinner,sun4i-a10-tcon-ch1-clk" - for the TCON channel 1 clock on the A10
 	"allwinner,sun4i-a10-usb-clk" - for usb gates + resets on A10 / A20
 	"allwinner,sun5i-a13-usb-clk" - for usb gates + resets on A13
 	"allwinner,sun6i-a31-usb-clk" - for usb gates + resets on A31
@@ -81,6 +86,7 @@ Required properties:
 	"allwinner,sun9i-a80-usb-mod-clk" - for usb gates + resets on A80
 	"allwinner,sun9i-a80-usb-phy-clk" - for usb phy gates + resets on A80
 	"allwinner,sun4i-a10-ve-clk" - for the Video Engine clock
+	"allwinner,sun6i-a31-display-clk" - for the display clocks
 
 Required properties for all clocks:
 - reg : shall be the control register address for the clock.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/cpufreq/nvidia,tegra124-cpufreq.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/cpufreq/nvidia,tegra124-cpufreq.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/cpufreq/nvidia,tegra124-cpufreq.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/cpufreq/nvidia,tegra124-cpufreq.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,44 @@
+Tegra124 CPU frequency scaling driver bindings
+----------------------------------------------
+
+Both required and optional properties listed below must be defined
+under node /cpus/cpu@0.
+
+Required properties:
+- clocks: Must contain an entry for each entry in clock-names.
+  See ../clocks/clock-bindings.txt for details.
+- clock-names: Must include the following entries:
+  - cpu_g: Clock mux for the fast CPU cluster.
+  - cpu_lp: Clock mux for the low-power CPU cluster.
+  - pll_x: Fast PLL clocksource.
+  - pll_p: Auxiliary PLL used during fast PLL rate changes.
+  - dfll: Fast DFLL clocksource that also automatically scales CPU voltage.
+- vdd-cpu-supply: Regulator for CPU voltage
+
+Optional properties:
+- clock-latency: Specify the possible maximum transition latency for clock,
+  in unit of nanoseconds.
+
+Example:
+--------
+cpus {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	cpu@0 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a15";
+		reg = <0>;
+
+		clocks = <&tegra_car TEGRA124_CLK_CCLK_G>,
+			 <&tegra_car TEGRA124_CLK_CCLK_LP>,
+			 <&tegra_car TEGRA124_CLK_PLL_X>,
+			 <&tegra_car TEGRA124_CLK_PLL_P>,
+			 <&dfll>;
+		clock-names = "cpu_g", "cpu_lp", "pll_x", "pll_p", "dfll";
+		clock-latency = <300000>;
+		vdd-cpu-supply: <&vdd_cpu>;
+	};
+
+	<...>
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/cpufreq/tegra124-cpufreq.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/cpufreq/tegra124-cpufreq.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/cpufreq/tegra124-cpufreq.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/cpufreq/tegra124-cpufreq.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,44 +0,0 @@
-Tegra124 CPU frequency scaling driver bindings
-----------------------------------------------
-
-Both required and optional properties listed below must be defined
-under node /cpus/cpu@0.
-
-Required properties:
-- clocks: Must contain an entry for each entry in clock-names.
-  See ../clocks/clock-bindings.txt for details.
-- clock-names: Must include the following entries:
-  - cpu_g: Clock mux for the fast CPU cluster.
-  - cpu_lp: Clock mux for the low-power CPU cluster.
-  - pll_x: Fast PLL clocksource.
-  - pll_p: Auxiliary PLL used during fast PLL rate changes.
-  - dfll: Fast DFLL clocksource that also automatically scales CPU voltage.
-- vdd-cpu-supply: Regulator for CPU voltage
-
-Optional properties:
-- clock-latency: Specify the possible maximum transition latency for clock,
-  in unit of nanoseconds.
-
-Example:
---------
-cpus {
-	#address-cells = <1>;
-	#size-cells = <0>;
-
-	cpu@0 {
-		device_type = "cpu";
-		compatible = "arm,cortex-a15";
-		reg = <0>;
-
-		clocks = <&tegra_car TEGRA124_CLK_CCLK_G>,
-			 <&tegra_car TEGRA124_CLK_CCLK_LP>,
-			 <&tegra_car TEGRA124_CLK_PLL_X>,
-			 <&tegra_car TEGRA124_CLK_PLL_P>,
-			 <&dfll>;
-		clock-names = "cpu_g", "cpu_lp", "pll_x", "pll_p", "dfll";
-		clock-latency = <300000>;
-		vdd-cpu-supply: <&vdd_cpu>;
-	};
-
-	<...>
-};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/crypto/fsl-imx-scc.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/crypto/fsl-imx-scc.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/crypto/fsl-imx-scc.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/crypto/fsl-imx-scc.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,21 @@
+Freescale Security Controller (SCC)
+
+Required properties:
+- compatible : Should be "fsl,imx25-scc".
+- reg : Should contain register location and length.
+- interrupts : Should contain interrupt numbers for SCM IRQ and SMN IRQ.
+- interrupt-names : Should specify the names "scm" and "smn" for the
+		    SCM IRQ and SMN IRQ.
+- clocks: Should contain the clock driving the SCC core.
+- clock-names: Should be set to "ipg".
+
+Example:
+
+	scc: crypto@53fac000 {
+		compatible = "fsl,imx25-scc";
+		reg = <0x53fac000 0x4000>;
+		clocks = <&clks 111>;
+		clock-names = "ipg";
+		interrupts = <49>, <50>;
+		interrupt-names = "scm", "smn";
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/crypto/samsung-sss.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/crypto/samsung-sss.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/crypto/samsung-sss.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/crypto/samsung-sss.txt	2016-07-24 15:23:50.000000000 -0400
@@ -23,10 +23,8 @@ Required properties:
   - "samsung,exynos4210-secss" for Exynos4210, Exynos4212, Exynos4412, Exynos5250,
 		Exynos5260 and Exynos5420 SoCs.
 - reg : Offset and length of the register set for the module
-- interrupts : interrupt specifiers of SSS module interrupts, should contain
-		following entries:
-		- first : feed control interrupt (required for all variants),
-		- second : hash interrupt (required only for samsung,s5pv210-secss).
+- interrupts : interrupt specifiers of SSS module interrupts (one feed
+		control interrupt).
 
 - clocks : list of clock phandle and specifier pairs for all clocks  listed in
 		clock-names property.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/devfreq/event/exynos-nocp.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/devfreq/event/exynos-nocp.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/devfreq/event/exynos-nocp.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/devfreq/event/exynos-nocp.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,26 @@
+
+* Samsung Exynos NoC (Network on Chip) Probe device
+
+The Samsung Exynos542x SoC has NoC (Network on Chip) Probe for NoC bus.
+NoC provides the primitive values to get the performance data. The packets
+that the Network on Chip (NoC) probes detects are transported over
+the network infrastructure to observer units. You can configure probes to
+capture packets with header or data on the data request response network,
+or as traffic debug or statistic collectors. Exynos542x bus has multiple
+NoC probes to provide bandwidth information about behavior of the SoC
+that you can use while analyzing system performance.
+
+Required properties:
+- compatible: Should be "samsung,exynos5420-nocp"
+- reg: physical base address of each NoC Probe and length of memory mapped region.
+
+Optional properties:
+- clock-names : the name of clock used by the NoC Probe, "nocp"
+- clocks : phandles for clock specified in "clock-names" property
+
+Example : NoC Probe nodes in Device Tree are listed below.
+
+	nocp_mem0_0: nocp@10CA1000 {
+		compatible = "samsung,exynos5420-nocp";
+		reg = <0x10CA1000 0x200>;
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/devfreq/exynos-bus.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/devfreq/exynos-bus.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/devfreq/exynos-bus.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/devfreq/exynos-bus.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,409 @@
+* Generic Exynos Bus frequency device
+
+The Samsung Exynos SoC has many buses for data transfer between DRAM
+and sub-blocks in SoC. Most Exynos SoCs share the common architecture
+for buses. Generally, each bus of Exynos SoC includes a source clock
+and a power line, which are able to change the clock frequency
+of the bus in runtime. To monitor the usage of each bus in runtime,
+the driver uses the PPMU (Platform Performance Monitoring Unit), which
+is able to measure the current load of sub-blocks.
+
+The Exynos SoC includes the various sub-blocks which have the each AXI bus.
+The each AXI bus has the owned source clock but, has not the only owned
+power line. The power line might be shared among one more sub-blocks.
+So, we can divide into two type of device as the role of each sub-block.
+There are two type of bus devices as following:
+- parent bus device
+- passive bus device
+
+Basically, parent and passive bus device share the same power line.
+The parent bus device can only change the voltage of shared power line
+and the rest bus devices (passive bus device) depend on the decision of
+the parent bus device. If there are three blocks which share the VDD_xxx
+power line, Only one block should be parent device and then the rest blocks
+should depend on the parent device as passive device.
+
+	VDD_xxx |--- A block (parent)
+		|--- B block (passive)
+		|--- C block (passive)
+
+There are a little different composition among Exynos SoC because each Exynos
+SoC has different sub-blocks. Therefore, such difference should be specified
+in devicetree file instead of each device driver. In result, this driver
+is able to support the bus frequency for all Exynos SoCs.
+
+Required properties for all bus devices:
+- compatible: Should be "samsung,exynos-bus".
+- clock-names : the name of clock used by the bus, "bus".
+- clocks : phandles for clock specified in "clock-names" property.
+- operating-points-v2: the OPP table including frequency/voltage information
+  to support DVFS (Dynamic Voltage/Frequency Scaling) feature.
+
+Required properties only for parent bus device:
+- vdd-supply: the regulator to provide the buses with the voltage.
+- devfreq-events: the devfreq-event device to monitor the current utilization
+  of buses.
+
+Required properties only for passive bus device:
+- devfreq: the parent bus device.
+
+Optional properties only for parent bus device:
+- exynos,saturation-ratio: the percentage value which is used to calibrate
+			the performance count against total cycle count.
+- exynos,voltage-tolerance: the percentage value for bus voltage tolerance
+			which is used to calculate the max voltage.
+
+Detailed correlation between sub-blocks and power line according to Exynos SoC:
+- In case of Exynos3250, there are two power line as following:
+	VDD_MIF |--- DMC
+
+	VDD_INT |--- LEFTBUS (parent device)
+		|--- PERIL
+		|--- MFC
+		|--- G3D
+		|--- RIGHTBUS
+		|--- PERIR
+		|--- FSYS
+		|--- LCD0
+		|--- PERIR
+		|--- ISP
+		|--- CAM
+
+- In case of Exynos4210, there is one power line as following:
+	VDD_INT |--- DMC (parent device)
+		|--- LEFTBUS
+		|--- PERIL
+		|--- MFC(L)
+		|--- G3D
+		|--- TV
+		|--- LCD0
+		|--- RIGHTBUS
+		|--- PERIR
+		|--- MFC(R)
+		|--- CAM
+		|--- FSYS
+		|--- GPS
+		|--- LCD0
+		|--- LCD1
+
+- In case of Exynos4x12, there are two power line as following:
+	VDD_MIF |--- DMC
+
+	VDD_INT |--- LEFTBUS (parent device)
+		|--- PERIL
+		|--- MFC(L)
+		|--- G3D
+		|--- TV
+		|--- IMAGE
+		|--- RIGHTBUS
+		|--- PERIR
+		|--- MFC(R)
+		|--- CAM
+		|--- FSYS
+		|--- GPS
+		|--- LCD0
+		|--- ISP
+
+- In case of Exynos5422, there are two power line as following:
+	VDD_MIF |--- DREX 0 (parent device, DRAM EXpress controller)
+	        |--- DREX 1
+
+	VDD_INT |--- NoC_Core (parent device)
+		|--- G2D
+		|--- G3D
+		|--- DISP1
+		|--- NoC_WCORE
+		|--- GSCL
+		|--- MSCL
+		|--- ISP
+		|--- MFC
+		|--- GEN
+		|--- PERIS
+		|--- PERIC
+		|--- FSYS
+		|--- FSYS2
+
+Example1:
+	Show the AXI buses of Exynos3250 SoC. Exynos3250 divides the buses to
+	power line (regulator). The MIF (Memory Interface) AXI bus is used to
+	transfer data between DRAM and CPU and uses the VDD_MIF regulator.
+
+	- MIF (Memory Interface) block
+	: VDD_MIF |--- DMC (Dynamic Memory Controller)
+
+	- INT (Internal) block
+	: VDD_INT |--- LEFTBUS (parent device)
+		  |--- PERIL
+		  |--- MFC
+		  |--- G3D
+		  |--- RIGHTBUS
+		  |--- FSYS
+		  |--- LCD0
+		  |--- PERIR
+		  |--- ISP
+		  |--- CAM
+
+	- MIF bus's frequency/voltage table
+	-----------------------
+	|Lv| Freq   | Voltage |
+	-----------------------
+	|L1| 50000  |800000   |
+	|L2| 100000 |800000   |
+	|L3| 134000 |800000   |
+	|L4| 200000 |825000   |
+	|L5| 400000 |875000   |
+	-----------------------
+
+	- INT bus's frequency/voltage table
+	----------------------------------------------------------
+	|Block|LEFTBUS|RIGHTBUS|MCUISP |ISP    |PERIL  ||VDD_INT |
+	| name|       |LCD0    |       |       |       ||        |
+	|     |       |FSYS    |       |       |       ||        |
+	|     |       |MFC     |       |       |       ||        |
+	----------------------------------------------------------
+	|Mode |*parent|passive |passive|passive|passive||        |
+	----------------------------------------------------------
+	|Lv   |Frequency                               ||Voltage |
+	----------------------------------------------------------
+	|L1   |50000  |50000   |50000  |50000  |50000  ||900000  |
+	|L2   |80000  |80000   |80000  |80000  |80000  ||900000  |
+	|L3   |100000 |100000  |100000 |100000 |100000 ||1000000 |
+	|L4   |134000 |134000  |200000 |200000 |       ||1000000 |
+	|L5   |200000 |200000  |400000 |300000 |       ||1000000 |
+	----------------------------------------------------------
+
+Example2 :
+	The bus of DMC (Dynamic Memory Controller) block in exynos3250.dtsi
+	is listed below:
+
+	bus_dmc: bus_dmc {
+		compatible = "samsung,exynos-bus";
+		clocks = <&cmu_dmc CLK_DIV_DMC>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_dmc_opp_table>;
+		status = "disabled";
+	};
+
+	bus_dmc_opp_table: opp_table1 {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp@50000000 {
+			opp-hz = /bits/ 64 <50000000>;
+			opp-microvolt = <800000>;
+		};
+		opp@100000000 {
+			opp-hz = /bits/ 64 <100000000>;
+			opp-microvolt = <800000>;
+		};
+		opp@134000000 {
+			opp-hz = /bits/ 64 <134000000>;
+			opp-microvolt = <800000>;
+		};
+		opp@200000000 {
+			opp-hz = /bits/ 64 <200000000>;
+			opp-microvolt = <825000>;
+		};
+		opp@400000000 {
+			opp-hz = /bits/ 64 <400000000>;
+			opp-microvolt = <875000>;
+		};
+	};
+
+	bus_leftbus: bus_leftbus {
+		compatible = "samsung,exynos-bus";
+		clocks = <&cmu CLK_DIV_GDL>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_leftbus_opp_table>;
+		status = "disabled";
+	};
+
+	bus_rightbus: bus_rightbus {
+		compatible = "samsung,exynos-bus";
+		clocks = <&cmu CLK_DIV_GDR>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_leftbus_opp_table>;
+		status = "disabled";
+	};
+
+	bus_lcd0: bus_lcd0 {
+		compatible = "samsung,exynos-bus";
+		clocks = <&cmu CLK_DIV_ACLK_160>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_leftbus_opp_table>;
+		status = "disabled";
+	};
+
+	bus_fsys: bus_fsys {
+		compatible = "samsung,exynos-bus";
+		clocks = <&cmu CLK_DIV_ACLK_200>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_leftbus_opp_table>;
+		status = "disabled";
+	};
+
+	bus_mcuisp: bus_mcuisp {
+		compatible = "samsung,exynos-bus";
+		clocks = <&cmu CLK_DIV_ACLK_400_MCUISP>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_mcuisp_opp_table>;
+		status = "disabled";
+	};
+
+	bus_isp: bus_isp {
+		compatible = "samsung,exynos-bus";
+		clocks = <&cmu CLK_DIV_ACLK_266>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_isp_opp_table>;
+		status = "disabled";
+	};
+
+	bus_peril: bus_peril {
+		compatible = "samsung,exynos-bus";
+		clocks = <&cmu CLK_DIV_ACLK_100>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_peril_opp_table>;
+		status = "disabled";
+	};
+
+	bus_mfc: bus_mfc {
+		compatible = "samsung,exynos-bus";
+		clocks = <&cmu CLK_SCLK_MFC>;
+		clock-names = "bus";
+		operating-points-v2 = <&bus_leftbus_opp_table>;
+		status = "disabled";
+	};
+
+	bus_leftbus_opp_table: opp_table1 {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp@50000000 {
+			opp-hz = /bits/ 64 <50000000>;
+			opp-microvolt = <900000>;
+		};
+		opp@80000000 {
+			opp-hz = /bits/ 64 <80000000>;
+			opp-microvolt = <900000>;
+		};
+		opp@100000000 {
+			opp-hz = /bits/ 64 <100000000>;
+			opp-microvolt = <1000000>;
+		};
+		opp@134000000 {
+			opp-hz = /bits/ 64 <134000000>;
+			opp-microvolt = <1000000>;
+		};
+		opp@200000000 {
+			opp-hz = /bits/ 64 <200000000>;
+			opp-microvolt = <1000000>;
+		};
+	};
+
+	bus_mcuisp_opp_table: opp_table2 {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp@50000000 {
+			opp-hz = /bits/ 64 <50000000>;
+		};
+		opp@80000000 {
+			opp-hz = /bits/ 64 <80000000>;
+		};
+		opp@100000000 {
+			opp-hz = /bits/ 64 <100000000>;
+		};
+		opp@200000000 {
+			opp-hz = /bits/ 64 <200000000>;
+		};
+		opp@400000000 {
+			opp-hz = /bits/ 64 <400000000>;
+		};
+	};
+
+	bus_isp_opp_table: opp_table3 {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp@50000000 {
+			opp-hz = /bits/ 64 <50000000>;
+		};
+		opp@80000000 {
+			opp-hz = /bits/ 64 <80000000>;
+		};
+		opp@100000000 {
+			opp-hz = /bits/ 64 <100000000>;
+		};
+		opp@200000000 {
+			opp-hz = /bits/ 64 <200000000>;
+		};
+		opp@300000000 {
+			opp-hz = /bits/ 64 <300000000>;
+		};
+	};
+
+	bus_peril_opp_table: opp_table4 {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp@50000000 {
+			opp-hz = /bits/ 64 <50000000>;
+		};
+		opp@80000000 {
+			opp-hz = /bits/ 64 <80000000>;
+		};
+		opp@100000000 {
+			opp-hz = /bits/ 64 <100000000>;
+		};
+	};
+
+
+	Usage case to handle the frequency and voltage of bus on runtime
+	in exynos3250-rinato.dts is listed below:
+
+	&bus_dmc {
+		devfreq-events = <&ppmu_dmc0_3>, <&ppmu_dmc1_3>;
+		vdd-supply = <&buck1_reg>;	/* VDD_MIF */
+		status = "okay";
+	};
+
+	&bus_leftbus {
+		devfreq-events = <&ppmu_leftbus_3>, <&ppmu_rightbus_3>;
+		vdd-supply = <&buck3_reg>;
+		status = "okay";
+	};
+
+	&bus_rightbus {
+		devfreq = <&bus_leftbus>;
+		status = "okay";
+	};
+
+	&bus_lcd0 {
+		devfreq = <&bus_leftbus>;
+		status = "okay";
+	};
+
+	&bus_fsys {
+		devfreq = <&bus_leftbus>;
+		status = "okay";
+	};
+
+	&bus_mcuisp {
+		devfreq = <&bus_leftbus>;
+		status = "okay";
+	};
+
+	&bus_isp {
+		devfreq = <&bus_leftbus>;
+		status = "okay";
+	};
+
+	&bus_peril {
+		devfreq = <&bus_leftbus>;
+		status = "okay";
+	};
+
+	&bus_mfc {
+		devfreq = <&bus_leftbus>;
+		status = "okay";
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/brcm,bcm-vc4.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/brcm,bcm-vc4.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/brcm,bcm-vc4.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/brcm,bcm-vc4.txt	2016-07-24 15:23:50.000000000 -0400
@@ -35,12 +35,22 @@ Optional properties for HDMI:
 		  as an interrupt/status bit in the HDMI controller
 		  itself).  See bindings/pinctrl/brcm,bcm2835-gpio.txt
 
+Required properties for DPI:
+- compatible:	Should be "brcm,bcm2835-dpi"
+- reg:		Physical base address and length of the registers
+- clocks:	a) core: The core clock the unit runs on
+		b) pixel: The pixel clock that feeds the pixelvalve
+- port:		Port node with a single endpoint connecting to the panel
+		  device, as defined in [1]
+
 Required properties for V3D:
 - compatible:	Should be "brcm,bcm2835-v3d"
 - reg:		Physical base address and length of the V3D's registers
 - interrupts:	The interrupt number
 		  See bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt
 
+[1] Documentation/devicetree/bindings/media/video-interfaces.txt
+
 Example:
 pixelvalve@7e807000 {
 	compatible = "brcm,bcm2835-pixelvalve2";
@@ -66,6 +76,22 @@ hdmi: hdmi@7e902000 {
 	clock-names = "pixel", "hdmi";
 };
 
+dpi: dpi@7e208000 {
+	compatible = "brcm,bcm2835-dpi";
+	reg = <0x7e208000 0x8c>;
+	clocks = <&clocks BCM2835_CLOCK_VPU>,
+	         <&clocks BCM2835_CLOCK_DPI>;
+	clock-names = "core", "pixel";
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	port {
+		dpi_out: endpoint@0 {
+			remote-endpoint = <&panel_in>;
+		};
+	};
+};
+
 v3d: v3d@7ec00000 {
 	compatible = "brcm,bcm2835-v3d";
 	reg = <0x7ec00000 0x1000>;
@@ -75,3 +101,13 @@ v3d: v3d@7ec00000 {
 vc4: gpu {
 	compatible = "brcm,bcm2835-vc4";
 };
+
+panel: panel {
+	compatible = "ontat,yx700wv03", "simple-panel";
+
+	port {
+		panel_in: endpoint {
+			remote-endpoint = <&dpi_out>;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/bridge/analogix_dp.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/bridge/analogix_dp.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/bridge/analogix_dp.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/bridge/analogix_dp.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,52 @@
+Analogix Display Port bridge bindings
+
+Required properties for dp-controller:
+	-compatible:
+		platform specific such as:
+		 * "samsung,exynos5-dp"
+		 * "rockchip,rk3288-dp"
+	-reg:
+		physical base address of the controller and length
+		of memory mapped region.
+	-interrupts:
+		interrupt combiner values.
+	-clocks:
+		from common clock binding: handle to dp clock.
+	-clock-names:
+		from common clock binding: Shall be "dp".
+	-interrupt-parent:
+		phandle to Interrupt combiner node.
+	-phys:
+		from general PHY binding: the phandle for the PHY device.
+	-phy-names:
+		from general PHY binding: Should be "dp".
+
+Optional properties for dp-controller:
+	-force-hpd:
+		Indicate driver need force hpd when hpd detect failed, this
+		is used for some eDP screen which don't have hpd signal.
+	-hpd-gpios:
+		Hotplug detect GPIO.
+		Indicates which GPIO should be used for hotplug detection
+	-port@[X]: SoC specific port nodes with endpoint definitions as defined
+		in Documentation/devicetree/bindings/media/video-interfaces.txt,
+		please refer to the SoC specific binding document:
+		* Documentation/devicetree/bindings/display/exynos/exynos_dp.txt
+		* Documentation/devicetree/bindings/video/analogix_dp-rockchip.txt
+
+[1]: Documentation/devicetree/bindings/media/video-interfaces.txt
+-------------------------------------------------------------------------------
+
+Example:
+
+	dp-controller {
+		compatible = "samsung,exynos5-dp";
+		reg = <0x145b0000 0x10000>;
+		interrupts = <10 3>;
+		interrupt-parent = <&combiner>;
+		clocks = <&clock 342>;
+		clock-names = "dp";
+
+		phys = <&dp_phy>;
+		phy-names = "dp";
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/exynos/exynos5433-decon.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/exynos/exynos5433-decon.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/exynos/exynos5433-decon.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/exynos/exynos5433-decon.txt	2016-07-24 15:23:50.000000000 -0400
@@ -5,7 +5,8 @@ Exynos series of SoCs which transfers th
 buffer to an external LCD interface.
 
 Required properties:
-- compatible: value should be "samsung,exynos5433-decon";
+- compatible: value should be one of:
+	"samsung,exynos5433-decon", "samsung,exynos5433-decon-tv";
 - reg: physical base address and length of the DECON registers set.
 - interrupts: should contain a list of all DECON IP block interrupts in the
 	      order: VSYNC, LCD_SYSTEM. The interrupt specifier format
@@ -16,7 +17,7 @@ Required properties:
 - clocks: must include clock specifiers corresponding to entries in the
 	  clock-names property.
 - clock-names: list of clock names sorted in the same order as the clocks
-	       property. Must contain "aclk_decon", "aclk_smmu_decon0x",
+	       property. Must contain "pclk", "aclk_decon", "aclk_smmu_decon0x",
 	       "aclk_xiu_decon0x", "pclk_smmu_decon0x", clk_decon_vclk",
 	       "sclk_decon_eclk"
 - ports: contains a port which is connected to mic node. address-cells and
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/exynos/exynos_dp.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/exynos/exynos_dp.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/exynos/exynos_dp.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/exynos/exynos_dp.txt	2016-07-24 15:23:50.000000000 -0400
@@ -1,20 +1,3 @@
-Device-Tree bindings for Samsung Exynos Embedded DisplayPort Transmitter(eDP)
-
-DisplayPort is industry standard to accommodate the growing board adoption
-of digital display technology within the PC and CE industries.
-It consolidates the internal and external connection methods to reduce device
-complexity and cost. It also supports necessary features for important cross
-industry applications and provides performance scalability to enable the next
-generation of displays that feature higher color depths, refresh rates, and
-display resolutions.
-
-eDP (embedded display port) device is compliant with Embedded DisplayPort
-standard as follows,
-- DisplayPort standard 1.1a for Exynos5250 and Exynos5260.
-- DisplayPort standard 1.3 for Exynos5422s and Exynos5800.
-
-eDP resides between FIMD and panel or FIMD and bridge such as LVDS.
-
 The Exynos display port interface should be configured based on
 the type of panel connected to it.
 
@@ -48,26 +31,6 @@ Required properties for dp-controller:
 		from general PHY binding: the phandle for the PHY device.
 	-phy-names:
 		from general PHY binding: Should be "dp".
-	-samsung,color-space:
-		input video data format.
-			COLOR_RGB = 0, COLOR_YCBCR422 = 1, COLOR_YCBCR444 = 2
-	-samsung,dynamic-range:
-		dynamic range for input video data.
-			VESA = 0, CEA = 1
-	-samsung,ycbcr-coeff:
-		YCbCr co-efficients for input video.
-			COLOR_YCBCR601 = 0, COLOR_YCBCR709 = 1
-	-samsung,color-depth:
-		number of bits per colour component.
-			COLOR_6 = 0, COLOR_8 = 1, COLOR_10 = 2, COLOR_12 = 3
-	-samsung,link-rate:
-		link rate supported by the panel.
-			LINK_RATE_1_62GBPS = 0x6, LINK_RATE_2_70GBPS = 0x0A
-	-samsung,lane-count:
-		number of lanes supported by the panel.
-			LANE_COUNT1 = 1, LANE_COUNT2 = 2, LANE_COUNT4 = 4
-	- display-timings: timings for the connected panel as described by
-		Documentation/devicetree/bindings/display/display-timing.txt
 
 Optional properties for dp-controller:
 	-interlaced:
@@ -83,17 +46,31 @@ Optional properties for dp-controller:
 		Hotplug detect GPIO.
 			Indicates which GPIO should be used for hotplug
 			detection
-Video interfaces:
-  Device node can contain video interface port nodes according to [1].
-  The following are properties specific to those nodes:
+	-video interfaces: Device node can contain video interface port
+			nodes according to [1].
+	- display-timings: timings for the connected panel as described by
+		Documentation/devicetree/bindings/display/panel/display-timing.txt
 
-  endpoint node connected to bridge or panel node:
-   - remote-endpoint: specifies the endpoint in panel or bridge node.
-		      This node is required in all kinds of exynos dp
-		      to represent the connection between dp and bridge
-		      or dp and panel.
+For the below properties, please refer to Analogix DP binding document:
+ * Documentation/devicetree/bindings/display/bridge/analogix_dp.txt
+	-phys (required)
+	-phy-names (required)
+	-hpd-gpios (optional)
+	 force-hpd (optional)
 
-[1]: Documentation/devicetree/bindings/media/video-interfaces.txt
+Deprecated properties for DisplayPort:
+-interlaced:            deprecated prop that can parsed from drm_display_mode.
+-vsync-active-high:     deprecated prop that can parsed from drm_display_mode.
+-hsync-active-high:     deprecated prop that can parsed from drm_display_mode.
+-samsung,ycbcr-coeff:   deprecated prop that can parsed from drm_display_mode.
+-samsung,dynamic-range: deprecated prop that can parsed from drm_display_mode.
+-samsung,color-space:   deprecated prop that can parsed from drm_display_info.
+-samsung,color-depth:   deprecated prop that can parsed from drm_display_info.
+-samsung,link-rate:     deprecated prop that can reading from monitor by dpcd method.
+-samsung,lane-count:    deprecated prop that can reading from monitor by dpcd method.
+-samsung,hpd-gpio:      deprecated name for hpd-gpios.
+
+-------------------------------------------------------------------------------
 
 Example:
 
@@ -112,13 +89,6 @@ SOC specific portion:
 
 Board Specific portion:
 	dp-controller {
-		samsung,color-space = <0>;
-		samsung,dynamic-range = <0>;
-		samsung,ycbcr-coeff = <0>;
-		samsung,color-depth = <1>;
-		samsung,link-rate = <0x0a>;
-		samsung,lane-count = <4>;
-
 		display-timings {
 			native-mode = <&lcd_timing>;
 			lcd_timing: 1366x768 {
@@ -135,18 +105,9 @@ Board Specific portion:
 		};
 
 		ports {
-			port {
+			port@0 {
 				dp_out: endpoint {
-					remote-endpoint = <&dp_in>;
-				};
-			};
-		};
-
-		panel {
-			...
-			port {
-				dp_in: endpoint {
-					remote-endpoint = <&dp_out>;
+					remote-endpoint = <&bridge_in>;
 				};
 			};
 		};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/exynos/exynos_dsim.txt	2016-07-24 15:23:50.000000000 -0400
@@ -41,7 +41,7 @@ Video interfaces:
   endpoint node connected from mic node (reg = 0):
     - remote-endpoint: specifies the endpoint in mic node. This node is required
 		       for Exynos5433 mipi dsi. So mic can access to panel node
-		       thoughout this dsi node.
+		       throughout this dsi node.
   endpoint node connected to panel node (reg = 1):
     - remote-endpoint: specifies the endpoint in panel node. This node is
 		       required in all kinds of exynos mipi dsi to represent
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/exynos/exynos_hdmi.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/exynos/exynos_hdmi.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/exynos/exynos_hdmi.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/exynos/exynos_hdmi.txt	2016-07-24 15:23:50.000000000 -0400
@@ -5,6 +5,7 @@ Required properties:
 	1) "samsung,exynos4210-hdmi"
 	2) "samsung,exynos4212-hdmi"
 	3) "samsung,exynos5420-hdmi"
+	4) "samsung,exynos5433-hdmi"
 - reg: physical base address of the hdmi and length of memory mapped
 	region.
 - interrupts: interrupt number to the cpu.
@@ -12,6 +13,11 @@ Required properties:
 	a) phandle of the gpio controller node.
 	b) pin number within the gpio controller.
 	c) optional flags and pull up/down.
+- ddc: phandle to the hdmi ddc node
+- phy: phandle to the hdmi phy node
+- samsung,syscon-phandle: phandle for system controller node for PMU.
+
+Required properties for Exynos 4210, 4212, 5420 and 5433:
 - clocks: list of clock IDs from SoC clock driver.
 	a) hdmi: Gate of HDMI IP bus clock.
 	b) sclk_hdmi: Gate of HDMI special clock.
@@ -25,9 +31,24 @@ Required properties:
 		sclk_pixel.
 - clock-names: aliases as per driver requirements for above clock IDs:
 	"hdmi", "sclk_hdmi", "sclk_pixel", "sclk_hdmiphy" and "mout_hdmi".
-- ddc: phandle to the hdmi ddc node
-- phy: phandle to the hdmi phy node
-- samsung,syscon-phandle: phandle for system controller node for PMU.
+
+Required properties for Exynos 5433:
+- clocks: list of clock specifiers according to common clock bindings.
+	a) hdmi_pclk: Gate of HDMI IP APB bus.
+	b) hdmi_i_pclk: Gate of HDMI-PHY IP APB bus.
+	d) i_tmds_clk: Gate of HDMI TMDS clock.
+	e) i_pixel_clk: Gate of HDMI pixel clock.
+	f) i_spdif_clk: Gate of HDMI SPDIF clock.
+	g) oscclk: Oscillator clock, used as parent of following *_user clocks
+		in case HDMI-PHY is not operational.
+	h) tmds_clko: TMDS clock generated by HDMI-PHY.
+	i) tmds_clko_user: MUX used to switch between oscclk and tmds_clko,
+		respectively if HDMI-PHY is off and operational.
+	j) pixel_clko: Pixel clock generated by HDMI-PHY.
+	k) pixel_clko_user: MUX used to switch between oscclk and pixel_clko,
+		respectively if HDMI-PHY is off and operational.
+- clock-names: aliases for above clock specfiers.
+- samsung,sysreg: handle to syscon used to control the system registers.
 
 Example:
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/fsl,dcu.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/fsl,dcu.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/fsl,dcu.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/fsl,dcu.txt	2016-07-24 15:23:50.000000000 -0400
@@ -6,17 +6,24 @@ Required properties:
 	* "fsl,vf610-dcu".
 
 - reg:			Address and length of the register set for dcu.
-- clocks:		From common clock binding: handle to dcu clock.
-- clock-names:		From common clock binding: Shall be "dcu".
+- clocks:		Handle to "dcu" and "pix" clock (in the order below)
+			This can be the same clock (e.g. LS1021a)
+			See ../clocks/clock-bindings.txt for details.
+- clock-names:		Should be "dcu" and "pix"
+			See ../clocks/clock-bindings.txt for details.
 - big-endian		Boolean property, LS1021A DCU registers are big-endian.
 - fsl,panel:		The phandle to panel node.
 
+Optional properties:
+- fsl,tcon:		The phandle to the timing controller node.
+
 Examples:
 dcu: dcu@2ce0000 {
 	compatible = "fsl,ls1021a-dcu";
 	reg = <0x0 0x2ce0000 0x0 0x10000>;
-	clocks = <&platform_clk 0>;
-	clock-names = "dcu";
+	clocks = <&platform_clk 0>, <&platform_clk 0>;
+	clock-names = "dcu", "pix";
 	big-endian;
 	fsl,panel = <&panel>;
+	fsl,tcon = <&tcon>;
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/fsl,tcon.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/fsl,tcon.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/fsl,tcon.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/fsl,tcon.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,18 @@
+Device Tree bindings for Freescale TCON Driver
+
+Required properties:
+- compatible:		Should be one of
+	* "fsl,vf610-tcon".
+
+- reg:			Address and length of the register set for tcon.
+- clocks:		From common clock binding: handle to tcon ipg clock.
+- clock-names:		From common clock binding: Shall be "ipg".
+
+Examples:
+timing-controller@4003d000 {
+	compatible = "fsl,vf610-tcon";
+	reg = <0x4003d000 0x1000>;
+	clocks = <&clks VF610_CLK_TCON0>;
+	clock-names = "ipg";
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/hisilicon/dw-dsi.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/hisilicon/dw-dsi.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/hisilicon/dw-dsi.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/hisilicon/dw-dsi.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,72 @@
+Device-Tree bindings for DesignWare DSI Host Controller v1.20a driver
+
+A DSI Host Controller resides in the middle of display controller and external
+HDMI converter or panel.
+
+Required properties:
+- compatible: value should be "hisilicon,hi6220-dsi".
+- reg: physical base address and length of dsi controller's registers.
+- clocks: contains APB clock phandle + clock-specifier pair.
+- clock-names: should be "pclk".
+- ports: contains DSI controller input and output sub port.
+  The input port connects to ADE output port with the reg value "0".
+  The output port with the reg value "1", it could connect to panel or
+  any other bridge endpoints.
+  See Documentation/devicetree/bindings/graph.txt for more device graph info.
+
+A example of HiKey board hi6220 SoC and board specific DT entry:
+Example:
+
+SoC specific:
+	dsi: dsi@f4107800 {
+		compatible = "hisilicon,hi6220-dsi";
+		reg = <0x0 0xf4107800 0x0 0x100>;
+		clocks = <&media_ctrl  HI6220_DSI_PCLK>;
+		clock-names = "pclk";
+		status = "disabled";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			/* 0 for input port */
+			port@0 {
+				reg = <0>;
+				dsi_in: endpoint {
+					remote-endpoint = <&ade_out>;
+				};
+			};
+		};
+	};
+
+
+Board specific:
+	&dsi {
+		status = "ok";
+
+		ports {
+			/* 1 for output port */
+			port@1 {
+				reg = <1>;
+
+				dsi_out0: endpoint@0 {
+					remote-endpoint = <&adv7533_in>;
+				};
+			};
+		};
+	};
+
+	&i2c2 {
+		...
+
+		adv7533: adv7533@39 {
+			...
+
+			port {
+				adv7533_in: endpoint {
+					remote-endpoint = <&dsi_out0>;
+				};
+			};
+		};
+	};
+
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/hisilicon/hisi-ade.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/hisilicon/hisi-ade.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/hisilicon/hisi-ade.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/hisilicon/hisi-ade.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,64 @@
+Device-Tree bindings for hisilicon ADE display controller driver
+
+ADE (Advanced Display Engine) is the display controller which grab image
+data from memory, do composition, do post image processing, generate RGB
+timing stream and transfer to DSI.
+
+Required properties:
+- compatible: value should be "hisilicon,hi6220-ade".
+- reg: physical base address and length of the ADE controller's registers.
+- hisilicon,noc-syscon: ADE NOC QoS syscon.
+- resets: The ADE reset controller node.
+- interrupt: the ldi vblank interrupt number used.
+- clocks: a list of phandle + clock-specifier pairs, one for each entry
+  in clock-names.
+- clock-names: should contain:
+  "clk_ade_core" for the ADE core clock.
+  "clk_codec_jpeg" for the media NOC QoS clock, which use the same clock with
+  jpeg codec.
+  "clk_ade_pix" for the ADE pixel clok.
+- assigned-clocks: Should contain "clk_ade_core" and "clk_codec_jpeg" clocks'
+  phandle + clock-specifier pairs.
+- assigned-clock-rates: clock rates, one for each entry in assigned-clocks.
+  The rate of "clk_ade_core" could be "360000000" or "180000000";
+  The rate of "clk_codec_jpeg" could be or less than "1440000000".
+  These rate values could be configured according to performance and power
+  consumption.
+- port: the output port. This contains one endpoint subnode, with its
+  remote-endpoint set to the phandle of the connected DSI input endpoint.
+  See Documentation/devicetree/bindings/graph.txt for more device graph info.
+
+Optional properties:
+- dma-coherent: Present if dma operations are coherent.
+
+
+A example of HiKey board hi6220 SoC specific DT entry:
+Example:
+
+	ade: ade@f4100000 {
+		compatible = "hisilicon,hi6220-ade";
+		reg = <0x0 0xf4100000 0x0 0x7800>;
+		reg-names = "ade_base";
+		hisilicon,noc-syscon = <&medianoc_ade>;
+		resets = <&media_ctrl MEDIA_ADE>;
+		interrupts = <0 115 4>; /* ldi interrupt */
+
+		clocks = <&media_ctrl HI6220_ADE_CORE>,
+			 <&media_ctrl HI6220_CODEC_JPEG>,
+			 <&media_ctrl HI6220_ADE_PIX_SRC>;
+		/*clock name*/
+		clock-names  = "clk_ade_core",
+			       "clk_codec_jpeg",
+			       "clk_ade_pix";
+
+		assigned-clocks = <&media_ctrl HI6220_ADE_CORE>,
+			<&media_ctrl HI6220_CODEC_JPEG>;
+		assigned-clock-rates = <360000000>, <288000000>;
+		dma-coherent;
+
+		port {
+			ade_out: endpoint {
+				remote-endpoint = <&dsi_in>;
+			};
+		};
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/imx/ldb.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/imx/ldb.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/imx/ldb.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/imx/ldb.txt	2016-07-24 15:23:50.000000000 -0400
@@ -62,6 +62,7 @@ Required properties:
    display-timings are used instead.
 
 Optional properties (required if display-timings are used):
+ - ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
  - display-timings : A node that describes the display timings as defined in
    Documentation/devicetree/bindings/display/display-timing.txt.
  - fsl,data-mapping : should be "spwg" or "jeida"
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,203 @@
+Mediatek display subsystem
+==========================
+
+The Mediatek display subsystem consists of various DISP function blocks in the
+MMSYS register space. The connections between them can be configured by output
+and input selectors in the MMSYS_CONFIG register space. Pixel clock and start
+of frame signal are distributed to the other function blocks by a DISP_MUTEX
+function block.
+
+All DISP device tree nodes must be siblings to the central MMSYS_CONFIG node.
+For a description of the MMSYS_CONFIG binding, see
+Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.txt.
+
+DISP function blocks
+====================
+
+A display stream starts at a source function block that reads pixel data from
+memory and ends with a sink function block that drives pixels on a display
+interface, or writes pixels back to memory. All DISP function blocks have
+their own register space, interrupt, and clock gate. The blocks that can
+access memory additionally have to list the IOMMU and local arbiter they are
+connected to.
+
+For a description of the display interface sink function blocks, see
+Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.txt and
+Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.txt.
+
+Required properties (all function blocks):
+- compatible: "mediatek,<chip>-disp-<function>", one of
+	"mediatek,<chip>-disp-ovl"   - overlay (4 layers, blending, csc)
+	"mediatek,<chip>-disp-rdma"  - read DMA / line buffer
+	"mediatek,<chip>-disp-wdma"  - write DMA
+	"mediatek,<chip>-disp-color" - color processor
+	"mediatek,<chip>-disp-aal"   - adaptive ambient light controller
+	"mediatek,<chip>-disp-gamma" - gamma correction
+	"mediatek,<chip>-disp-merge" - merge streams from two RDMA sources
+	"mediatek,<chip>-disp-split" - split stream to two encoders
+	"mediatek,<chip>-disp-ufoe"  - data compression engine
+	"mediatek,<chip>-dsi"        - DSI controller, see mediatek,dsi.txt
+	"mediatek,<chip>-dpi"        - DPI controller, see mediatek,dpi.txt
+	"mediatek,<chip>-disp-mutex" - display mutex
+	"mediatek,<chip>-disp-od"    - overdrive
+- reg: Physical base address and length of the function block register space
+- interrupts: The interrupt signal from the function block (required, except for
+  merge and split function blocks).
+- clocks: device clocks
+  See Documentation/devicetree/bindings/clock/clock-bindings.txt for details.
+  For most function blocks this is just a single clock input. Only the DSI and
+  DPI controller nodes have multiple clock inputs. These are documented in
+  mediatek,dsi.txt and mediatek,dpi.txt, respectively.
+
+Required properties (DMA function blocks):
+- compatible: Should be one of
+	"mediatek,<chip>-disp-ovl"
+	"mediatek,<chip>-disp-rdma"
+	"mediatek,<chip>-disp-wdma"
+- larb: Should contain a phandle pointing to the local arbiter device as defined
+  in Documentation/devicetree/bindings/soc/mediatek/mediatek,smi-larb.txt
+- iommus: Should point to the respective IOMMU block with master port as
+  argument, see Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
+  for details.
+
+Examples:
+
+mmsys: clock-controller@14000000 {
+	compatible = "mediatek,mt8173-mmsys", "syscon";
+	reg = <0 0x14000000 0 0x1000>;
+	power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+	#clock-cells = <1>;
+};
+
+ovl0: ovl@1400c000 {
+	compatible = "mediatek,mt8173-disp-ovl";
+	reg = <0 0x1400c000 0 0x1000>;
+	interrupts = <GIC_SPI 180 IRQ_TYPE_LEVEL_LOW>;
+	power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+	clocks = <&mmsys CLK_MM_DISP_OVL0>;
+	iommus = <&iommu M4U_PORT_DISP_OVL0>;
+	mediatek,larb = <&larb0>;
+};
+
+ovl1: ovl@1400d000 {
+	compatible = "mediatek,mt8173-disp-ovl";
+	reg = <0 0x1400d000 0 0x1000>;
+	interrupts = <GIC_SPI 181 IRQ_TYPE_LEVEL_LOW>;
+	power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+	clocks = <&mmsys CLK_MM_DISP_OVL1>;
+	iommus = <&iommu M4U_PORT_DISP_OVL1>;
+	mediatek,larb = <&larb4>;
+};
+
+rdma0: rdma@1400e000 {
+	compatible = "mediatek,mt8173-disp-rdma";
+	reg = <0 0x1400e000 0 0x1000>;
+	interrupts = <GIC_SPI 182 IRQ_TYPE_LEVEL_LOW>;
+	power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+	clocks = <&mmsys CLK_MM_DISP_RDMA0>;
+	iommus = <&iommu M4U_PORT_DISP_RDMA0>;
+	mediatek,larb = <&larb0>;
+};
+
+rdma1: rdma@1400f000 {
+	compatible = "mediatek,mt8173-disp-rdma";
+	reg = <0 0x1400f000 0 0x1000>;
+	interrupts = <GIC_SPI 183 IRQ_TYPE_LEVEL_LOW>;
+	power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+	clocks = <&mmsys CLK_MM_DISP_RDMA1>;
+	iommus = <&iommu M4U_PORT_DISP_RDMA1>;
+	mediatek,larb = <&larb4>;
+};
+
+rdma2: rdma@14010000 {
+	compatible = "mediatek,mt8173-disp-rdma";
+	reg = <0 0x14010000 0 0x1000>;
+	interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_LOW>;
+	power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+	clocks = <&mmsys CLK_MM_DISP_RDMA2>;
+	iommus = <&iommu M4U_PORT_DISP_RDMA2>;
+	mediatek,larb = <&larb4>;
+};
+
+wdma0: wdma@14011000 {
+	compatible = "mediatek,mt8173-disp-wdma";
+	reg = <0 0x14011000 0 0x1000>;
+	interrupts = <GIC_SPI 185 IRQ_TYPE_LEVEL_LOW>;
+	power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+	clocks = <&mmsys CLK_MM_DISP_WDMA0>;
+	iommus = <&iommu M4U_PORT_DISP_WDMA0>;
+	mediatek,larb = <&larb0>;
+};
+
+wdma1: wdma@14012000 {
+	compatible = "mediatek,mt8173-disp-wdma";
+	reg = <0 0x14012000 0 0x1000>;
+	interrupts = <GIC_SPI 186 IRQ_TYPE_LEVEL_LOW>;
+	power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+	clocks = <&mmsys CLK_MM_DISP_WDMA1>;
+	iommus = <&iommu M4U_PORT_DISP_WDMA1>;
+	mediatek,larb = <&larb4>;
+};
+
+color0: color@14013000 {
+	compatible = "mediatek,mt8173-disp-color";
+	reg = <0 0x14013000 0 0x1000>;
+	interrupts = <GIC_SPI 187 IRQ_TYPE_LEVEL_LOW>;
+	power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+	clocks = <&mmsys CLK_MM_DISP_COLOR0>;
+};
+
+color1: color@14014000 {
+	compatible = "mediatek,mt8173-disp-color";
+	reg = <0 0x14014000 0 0x1000>;
+	interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_LOW>;
+	power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+	clocks = <&mmsys CLK_MM_DISP_COLOR1>;
+};
+
+aal@14015000 {
+	compatible = "mediatek,mt8173-disp-aal";
+	reg = <0 0x14015000 0 0x1000>;
+	interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_LOW>;
+	power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+	clocks = <&mmsys CLK_MM_DISP_AAL>;
+};
+
+gamma@14016000 {
+	compatible = "mediatek,mt8173-disp-gamma";
+	reg = <0 0x14016000 0 0x1000>;
+	interrupts = <GIC_SPI 190 IRQ_TYPE_LEVEL_LOW>;
+	power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+	clocks = <&mmsys CLK_MM_DISP_GAMMA>;
+};
+
+ufoe@1401a000 {
+	compatible = "mediatek,mt8173-disp-ufoe";
+	reg = <0 0x1401a000 0 0x1000>;
+	interrupts = <GIC_SPI 191 IRQ_TYPE_LEVEL_LOW>;
+	power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+	clocks = <&mmsys CLK_MM_DISP_UFOE>;
+};
+
+dsi0: dsi@1401b000 {
+	/* See mediatek,dsi.txt for details */
+};
+
+dpi0: dpi@1401d000 {
+	/* See mediatek,dpi.txt for details */
+};
+
+mutex: mutex@14020000 {
+	compatible = "mediatek,mt8173-disp-mutex";
+	reg = <0 0x14020000 0 0x1000>;
+	interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_LOW>;
+	power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+	clocks = <&mmsys CLK_MM_MUTEX_32K>;
+};
+
+od@14023000 {
+	compatible = "mediatek,mt8173-disp-od";
+	reg = <0 0x14023000 0 0x1000>;
+	power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+	clocks = <&mmsys CLK_MM_DISP_OD>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,35 @@
+Mediatek DPI Device
+===================
+
+The Mediatek DPI function block is a sink of the display subsystem and
+provides 8-bit RGB/YUV444 or 8/10/10-bit YUV422 pixel data on a parallel
+output bus.
+
+Required properties:
+- compatible: "mediatek,<chip>-dpi"
+- reg: Physical base address and length of the controller's registers
+- interrupts: The interrupt signal from the function block.
+- clocks: device clocks
+  See Documentation/devicetree/bindings/clock/clock-bindings.txt for details.
+- clock-names: must contain "pixel", "engine", and "pll"
+- port: Output port node with endpoint definitions as described in
+  Documentation/devicetree/bindings/graph.txt. This port should be connected
+  to the input port of an attached HDMI or LVDS encoder chip.
+
+Example:
+
+dpi0: dpi@1401d000 {
+	compatible = "mediatek,mt8173-dpi";
+	reg = <0 0x1401d000 0 0x1000>;
+	interrupts = <GIC_SPI 194 IRQ_TYPE_LEVEL_LOW>;
+	clocks = <&mmsys CLK_MM_DPI_PIXEL>,
+		 <&mmsys CLK_MM_DPI_ENGINE>,
+		 <&apmixedsys CLK_APMIXED_TVDPLL>;
+	clock-names = "pixel", "engine", "pll";
+
+	port {
+		dpi0_out: endpoint {
+			remote-endpoint = <&hdmi0_in>;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,60 @@
+Mediatek DSI Device
+===================
+
+The Mediatek DSI function block is a sink of the display subsystem and can
+drive up to 4-lane MIPI DSI output. Two DSIs can be synchronized for dual-
+channel output.
+
+Required properties:
+- compatible: "mediatek,<chip>-dsi"
+- reg: Physical base address and length of the controller's registers
+- interrupts: The interrupt signal from the function block.
+- clocks: device clocks
+  See Documentation/devicetree/bindings/clock/clock-bindings.txt for details.
+- clock-names: must contain "engine", "digital", and "hs"
+- phys: phandle link to the MIPI D-PHY controller.
+- phy-names: must contain "dphy"
+- port: Output port node with endpoint definitions as described in
+  Documentation/devicetree/bindings/graph.txt. This port should be connected
+  to the input port of an attached DSI panel or DSI-to-eDP encoder chip.
+
+MIPI TX Configuration Module
+============================
+
+The MIPI TX configuration module controls the MIPI D-PHY.
+
+Required properties:
+- compatible: "mediatek,<chip>-mipi-tx"
+- reg: Physical base address and length of the controller's registers
+- clocks: PLL reference clock
+- clock-output-names: name of the output clock line to the DSI encoder
+- #clock-cells: must be <0>;
+- #phy-cells: must be <0>.
+
+Example:
+
+mipi_tx0: mipi-dphy@10215000 {
+	compatible = "mediatek,mt8173-mipi-tx";
+	reg = <0 0x10215000 0 0x1000>;
+	clocks = <&clk26m>;
+	clock-output-names = "mipi_tx0_pll";
+	#clock-cells = <0>;
+	#phy-cells = <0>;
+};
+
+dsi0: dsi@1401b000 {
+	compatible = "mediatek,mt8173-dsi";
+	reg = <0 0x1401b000 0 0x1000>;
+	interrupts = <GIC_SPI 192 IRQ_TYPE_LEVEL_LOW>;
+	clocks = <&mmsys MM_DSI0_ENGINE>, <&mmsys MM_DSI0_DIGITAL>,
+		 <&mipi_tx0>;
+	clock-names = "engine", "digital", "hs";
+	phys = <&mipi_tx0>;
+	phy-names = "dphy";
+
+	port {
+		dsi0_out: endpoint {
+			remote-endpoint = <&panel_in>;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/panel/innolux,at070tn92.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/panel/innolux,at070tn92.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/panel/innolux,at070tn92.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/panel/innolux,at070tn92.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,7 @@
+Innolux AT070TN92 7.0" WQVGA TFT LCD panel
+
+Required properties:
+- compatible: should be "innolux,at070tn92"
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/panel/olimex,lcd-olinuxino-43-ts.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/panel/olimex,lcd-olinuxino-43-ts.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/panel/olimex,lcd-olinuxino-43-ts.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/panel/olimex,lcd-olinuxino-43-ts.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,7 @@
+Olimex 4.3" TFT LCD panel
+
+Required properties:
+- compatible: should be "olimex,lcd-olinuxino-43-ts"
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/panel/ontat,yx700wv03.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/panel/ontat,yx700wv03.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/panel/ontat,yx700wv03.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/panel/ontat,yx700wv03.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,7 @@
+On Tat Industrial Company 7" DPI TFT panel.
+
+Required properties:
+- compatible: should be "ontat,yx700wv03"
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/panel/tpk,f07a-0102.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/panel/tpk,f07a-0102.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/panel/tpk,f07a-0102.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/panel/tpk,f07a-0102.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,8 @@
+TPK U.S.A. LLC Fusion 7" integrated projected capacitive touch display with,
+800 x 480 (WVGA) LCD panel.
+
+Required properties:
+- compatible: should be "tpk,f07a-0102"
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/panel/tpk,f10a-0102.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/panel/tpk,f10a-0102.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/panel/tpk,f10a-0102.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/panel/tpk,f10a-0102.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,8 @@
+TPK U.S.A. LLC Fusion 10.1" integrated projected capacitive touch display with,
+1024 x 600 (WSVGA) LCD panel.
+
+Required properties:
+- compatible: should be "tpk,f10a-0102"
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/rockchip/analogix_dp-rockchip.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/rockchip/analogix_dp-rockchip.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/rockchip/analogix_dp-rockchip.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/rockchip/analogix_dp-rockchip.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,92 @@
+Rockchip RK3288 specific extensions to the Analogix Display Port
+================================
+
+Required properties:
+- compatible: "rockchip,rk3288-edp";
+
+- reg: physical base address of the controller and length
+
+- clocks: from common clock binding: handle to dp clock.
+	  of memory mapped region.
+
+- clock-names: from common clock binding:
+	       Required elements: "dp" "pclk"
+
+- resets: Must contain an entry for each entry in reset-names.
+	  See ../reset/reset.txt for details.
+
+- pinctrl-names: Names corresponding to the chip hotplug pinctrl states.
+- pinctrl-0: pin-control mode. should be <&edp_hpd>
+
+- reset-names: Must include the name "dp"
+
+- rockchip,grf: this soc should set GRF regs, so need get grf here.
+
+- ports: there are 2 port nodes with endpoint definitions as defined in
+  Documentation/devicetree/bindings/media/video-interfaces.txt.
+    Port 0: contained 2 endpoints, connecting to the output of vop.
+    Port 1: contained 1 endpoint, connecting to the input of panel.
+
+For the below properties, please refer to Analogix DP binding document:
+ * Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt
+- phys (required)
+- phy-names (required)
+- hpd-gpios (optional)
+- force-hpd (optional)
+-------------------------------------------------------------------------------
+
+Example:
+	dp-controller: dp@ff970000 {
+		compatible = "rockchip,rk3288-dp";
+		reg = <0xff970000 0x4000>;
+		interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru SCLK_EDP>, <&cru PCLK_EDP_CTRL>;
+		clock-names = "dp", "pclk";
+		phys = <&dp_phy>;
+		phy-names = "dp";
+
+		rockchip,grf = <&grf>;
+		resets = <&cru 111>;
+		reset-names = "dp";
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&edp_hpd>;
+
+		status = "disabled";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			edp_in: port@0 {
+				reg = <0>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				edp_in_vopb: endpoint@0 {
+					reg = <0>;
+					remote-endpoint = <&vopb_out_edp>;
+				};
+				edp_in_vopl: endpoint@1 {
+					reg = <1>;
+					remote-endpoint = <&vopl_out_edp>;
+				};
+			};
+
+			edp_out: port@1 {
+				reg = <1>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				edp_out_panel: endpoint {
+					reg = <0>;
+					remote-endpoint = <&panel_in_edp>
+				};
+			};
+		};
+	};
+
+	pinctrl {
+		edp {
+			edp_hpd: edp-hpd {
+				rockchip,pins = <7 11 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/snps,arcpgu.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/snps,arcpgu.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/snps,arcpgu.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/snps,arcpgu.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,35 @@
+ARC PGU
+
+This is a display controller found on several development boards produced
+by Synopsys. The ARC PGU is an RGB streamer that reads the data from a
+framebuffer and sends it to a single digital encoder (usually HDMI).
+
+Required properties:
+  - compatible: "snps,arcpgu"
+  - reg: Physical base address and length of the controller's registers.
+  - clocks: A list of phandle + clock-specifier pairs, one for each
+    entry in 'clock-names'.
+  - clock-names: A list of clock names. For ARC PGU it should contain:
+      - "pxlclk" for the clock feeding the output PLL of the controller.
+
+Required sub-nodes:
+  - port: The PGU connection to an encoder chip.
+
+Example:
+
+/ {
+	...
+
+	pgu@XXXXXXXX {
+		compatible = "snps,arcpgu";
+		reg = <0xXXXXXXXX 0x400>;
+		clocks = <&clock_node>;
+		clock-names = "pxlclk";
+
+		port {
+			pgu_output: endpoint {
+				remote-endpoint = <&hdmi_enc_input>;
+			};
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,258 @@
+Allwinner A10 Display Pipeline
+==============================
+
+The Allwinner A10 Display pipeline is composed of several components
+that are going to be documented below:
+
+TV Encoder
+----------
+
+The TV Encoder supports the composite and VGA output. It is one end of
+the pipeline.
+
+Required properties:
+ - compatible: value should be "allwinner,sun4i-a10-tv-encoder".
+ - reg: base address and size of memory-mapped region
+ - clocks: the clocks driving the TV encoder
+ - resets: phandle to the reset controller driving the encoder
+
+- ports: A ports node with endpoint definitions as defined in
+  Documentation/devicetree/bindings/media/video-interfaces.txt. The
+  first port should be the input endpoint.
+
+TCON
+----
+
+The TCON acts as a timing controller for RGB, LVDS and TV interfaces.
+
+Required properties:
+ - compatible: value should be "allwinner,sun5i-a13-tcon".
+ - reg: base address and size of memory-mapped region
+ - interrupts: interrupt associated to this IP
+ - clocks: phandles to the clocks feeding the TCON. Three are needed:
+   - 'ahb': the interface clocks
+   - 'tcon-ch0': The clock driving the TCON channel 0
+   - 'tcon-ch1': The clock driving the TCON channel 1
+ - resets: phandles to the reset controllers driving the encoder
+   - "lcd": the reset line for the TCON channel 0
+
+ - clock-names: the clock names mentioned above
+ - reset-names: the reset names mentioned above
+ - clock-output-names: Name of the pixel clock created
+
+- ports: A ports node with endpoint definitions as defined in
+  Documentation/devicetree/bindings/media/video-interfaces.txt. The
+  first port should be the input endpoint, the second one the output
+
+  The output should have two endpoints. The first is the block
+  connected to the TCON channel 0 (usually a panel or a bridge), the
+  second the block connected to the TCON channel 1 (usually the TV
+  encoder)
+
+
+Display Engine Backend
+----------------------
+
+The display engine backend exposes layers and sprites to the
+system.
+
+Required properties:
+  - compatible: value must be one of:
+    * allwinner,sun5i-a13-display-backend
+  - reg: base address and size of the memory-mapped region.
+  - clocks: phandles to the clocks feeding the frontend and backend
+    * ahb: the backend interface clock
+    * mod: the backend module clock
+    * ram: the backend DRAM clock
+  - clock-names: the clock names mentioned above
+  - resets: phandles to the reset controllers driving the backend
+
+- ports: A ports node with endpoint definitions as defined in
+  Documentation/devicetree/bindings/media/video-interfaces.txt. The
+  first port should be the input endpoints, the second one the output
+
+Display Engine Frontend
+-----------------------
+
+The display engine frontend does formats conversion, scaling,
+deinterlacing and color space conversion.
+
+Required properties:
+  - compatible: value must be one of:
+    * allwinner,sun5i-a13-display-frontend
+  - reg: base address and size of the memory-mapped region.
+  - interrupts: interrupt associated to this IP
+  - clocks: phandles to the clocks feeding the frontend and backend
+    * ahb: the backend interface clock
+    * mod: the backend module clock
+    * ram: the backend DRAM clock
+  - clock-names: the clock names mentioned above
+  - resets: phandles to the reset controllers driving the backend
+
+- ports: A ports node with endpoint definitions as defined in
+  Documentation/devicetree/bindings/media/video-interfaces.txt. The
+  first port should be the input endpoints, the second one the outputs
+
+
+Display Engine Pipeline
+-----------------------
+
+The display engine pipeline (and its entry point, since it can be
+either directly the backend or the frontend) is represented as an
+extra node.
+
+Required properties:
+  - compatible: value must be one of:
+    * allwinner,sun5i-a13-display-engine
+
+  - allwinner,pipelines: list of phandle to the display engine
+    frontends available.
+
+Example:
+
+panel: panel {
+	compatible = "olimex,lcd-olinuxino-43-ts";
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	port {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		panel_input: endpoint {
+			remote-endpoint = <&tcon0_out_panel>;
+		};
+	};
+};
+
+tve0: tv-encoder@01c0a000 {
+	compatible = "allwinner,sun4i-a10-tv-encoder";
+	reg = <0x01c0a000 0x1000>;
+	clocks = <&ahb_gates 34>;
+	resets = <&tcon_ch0_clk 0>;
+
+	port {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		tve0_in_tcon0: endpoint@0 {
+			reg = <0>;
+			remote-endpoint = <&tcon0_out_tve0>;
+		};
+	};
+};
+
+tcon0: lcd-controller@1c0c000 {
+	compatible = "allwinner,sun5i-a13-tcon";
+	reg = <0x01c0c000 0x1000>;
+	interrupts = <44>;
+	resets = <&tcon_ch0_clk 1>;
+	reset-names = "lcd";
+	clocks = <&ahb_gates 36>,
+		 <&tcon_ch0_clk>,
+		 <&tcon_ch1_clk>;
+	clock-names = "ahb",
+		      "tcon-ch0",
+		      "tcon-ch1";
+	clock-output-names = "tcon-pixel-clock";
+
+	ports {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		tcon0_in: port@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+
+			tcon0_in_be0: endpoint@0 {
+				reg = <0>;
+				remote-endpoint = <&be0_out_tcon0>;
+			};
+		};
+
+		tcon0_out: port@1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+
+			tcon0_out_panel: endpoint@0 {
+				reg = <0>;
+				remote-endpoint = <&panel_input>;
+			};
+
+			tcon0_out_tve0: endpoint@1 {
+				reg = <1>;
+				remote-endpoint = <&tve0_in_tcon0>;
+			};
+		};
+	};
+};
+
+fe0: display-frontend@1e00000 {
+	compatible = "allwinner,sun5i-a13-display-frontend";
+	reg = <0x01e00000 0x20000>;
+	interrupts = <47>;
+	clocks = <&ahb_gates 46>, <&de_fe_clk>,
+		 <&dram_gates 25>;
+	clock-names = "ahb", "mod",
+		      "ram";
+	resets = <&de_fe_clk>;
+
+	ports {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		fe0_out: port@1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+
+			fe0_out_be0: endpoint {
+				remote-endpoint = <&be0_in_fe0>;
+			};
+		};
+	};
+};
+
+be0: display-backend@1e60000 {
+	compatible = "allwinner,sun5i-a13-display-backend";
+	reg = <0x01e60000 0x10000>;
+	clocks = <&ahb_gates 44>, <&de_be_clk>,
+		 <&dram_gates 26>;
+	clock-names = "ahb", "mod",
+		      "ram";
+	resets = <&de_be_clk>;
+
+	ports {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		be0_in: port@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+
+			be0_in_fe0: endpoint@0 {
+				reg = <0>;
+				remote-endpoint = <&fe0_out_be0>;
+			};
+		};
+
+		be0_out: port@1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+
+			be0_out_tcon0: endpoint@0 {
+				reg = <0>;
+				remote-endpoint = <&tcon0_in_be0>;
+			};
+		};
+	};
+};
+
+display-engine {
+	compatible = "allwinner,sun5i-a13-display-engine";
+	allwinner,pipelines = <&fe0>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/dma/brcm,bcm2835-dma.txt	2016-07-24 15:23:50.000000000 -0400
@@ -12,6 +12,10 @@ Required properties:
 - reg: Should contain DMA registers location and length.
 - interrupts: Should contain the DMA interrupts associated
 		to the DMA channels in ascending order.
+- interrupt-names: Should contain the names of the interrupt
+		   in the form "dmaXX".
+		   Use "dma-shared-all" for the common interrupt line
+		   that is shared by all dma channels.
 - #dma-cells: Must be <1>, the cell in the dmas property of the
 		client device represents the DREQ number.
 - brcm,dma-channel-mask: Bit mask representing the channels
@@ -34,13 +38,35 @@ dma: dma@7e007000 {
 		     <1 24>,
 		     <1 25>,
 		     <1 26>,
+		     /* dma channel 11-14 share one irq */
+		     <1 27>,
+		     <1 27>,
 		     <1 27>,
+		     <1 27>,
+		     /* unused shared irq for all channels */
 		     <1 28>;
+	interrupt-names = "dma0",
+			  "dma1",
+			  "dma2",
+			  "dma3",
+			  "dma4",
+			  "dma5",
+			  "dma6",
+			  "dma7",
+			  "dma8",
+			  "dma9",
+			  "dma10",
+			  "dma11",
+			  "dma12",
+			  "dma13",
+			  "dma14",
+			  "dma-shared-all";
 
 	#dma-cells = <1>;
 	brcm,dma-channel-mask = <0x7f35>;
 };
 
+
 DMA clients connected to the BCM2835 DMA controller must use the format
 described in the dma.txt file, using a two-cell specifier for each channel.
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt	2016-05-15 19:23:10.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/dma/fsl-imx-sdma.txt	2016-07-24 18:19:55.000000000 -0400
@@ -58,6 +58,15 @@ The third cell specifies the transfer pr
 	1	Medium
 	2	Low
 
+Optional properties:
+
+- gpr : The phandle to the General Purpose Register (GPR) node.
+- fsl,sdma-event-remap : Register bits of sdma event remap, the format is
+  <reg shift val>.
+    reg is the GPR register offset.
+    shift is the bit position inside the GPR register.
+    val is the value of the bit (0 or 1).
+
 Examples:
 
 sdma@83fb0000 {
@@ -83,3 +92,21 @@ ssi2: ssi@70014000 {
 	dma-names = "rx", "tx";
 	fsl,fifo-depth = <15>;
 };
+
+Using the fsl,sdma-event-remap property:
+
+If we want to use SDMA on the SAI1 port on a MX6SX:
+
+&sdma {
+	gpr = <&gpr>;
+	/* SDMA events remap for SAI1_RX and SAI1_TX */
+	fsl,sdma-event-remap = <0 15 1>, <0 16 1>;
+};
+
+The fsl,sdma-event-remap property in this case has two values:
+- <0 15 1> means that the offset is 0, so GPR0 is the register of the
+SDMA remap. Bit 15 of GPR0 selects between UART4_RX and SAI1_RX.
+Setting bit 15 to 1 selects SAI1_RX.
+- <0 16 1> means that the offset is 0, so GPR0 is the register of the
+SDMA remap. Bit 16 of GPR0 selects between UART4_TX and SAI1_TX.
+Setting bit 16 to 1 selects SAI1_TX.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/dma/mv-xor.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/dma/mv-xor.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/dma/mv-xor.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/dma/mv-xor.txt	2016-07-24 15:23:50.000000000 -0400
@@ -1,7 +1,10 @@
 * Marvell XOR engines
 
 Required properties:
-- compatible: Should be "marvell,orion-xor" or "marvell,armada-380-xor"
+- compatible: Should be one of the following:
+  - "marvell,orion-xor"
+  - "marvell,armada-380-xor"
+  - "marvell,armada-3700-xor".
 - reg: Should contain registers location and length (two sets)
     the first set is the low registers, the second set the high
     registers for the XOR engine.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/dma/nvidia,tegra20-apbdma.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/dma/nvidia,tegra20-apbdma.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/dma/nvidia,tegra20-apbdma.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/dma/nvidia,tegra20-apbdma.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,44 @@
+* NVIDIA Tegra APB DMA controller
+
+Required properties:
+- compatible: Should be "nvidia,<chip>-apbdma"
+- reg: Should contain DMA registers location and length. This shuld include
+  all of the per-channel registers.
+- interrupts: Should contain all of the per-channel DMA interrupts.
+- clocks: Must contain one entry, for the module clock.
+  See ../clocks/clock-bindings.txt for details.
+- resets : Must contain an entry for each entry in reset-names.
+  See ../reset/reset.txt for details.
+- reset-names : Must include the following entries:
+  - dma
+- #dma-cells : Must be <1>. This dictates the length of DMA specifiers in
+  client nodes' dmas properties. The specifier represents the DMA request
+  select value for the peripheral. For more details, consult the Tegra TRM's
+  documentation of the APB DMA channel control register REQ_SEL field.
+
+Examples:
+
+apbdma: dma@6000a000 {
+	compatible = "nvidia,tegra20-apbdma";
+	reg = <0x6000a000 0x1200>;
+	interrupts = < 0 136 0x04
+		       0 137 0x04
+		       0 138 0x04
+		       0 139 0x04
+		       0 140 0x04
+		       0 141 0x04
+		       0 142 0x04
+		       0 143 0x04
+		       0 144 0x04
+		       0 145 0x04
+		       0 146 0x04
+		       0 147 0x04
+		       0 148 0x04
+		       0 149 0x04
+		       0 150 0x04
+		       0 151 0x04 >;
+	clocks = <&tegra_car 34>;
+	resets = <&tegra_car 34>;
+	reset-names = "dma";
+	#dma-cells = <1>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/dma/nvidia,tegra210-adma.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/dma/nvidia,tegra210-adma.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/dma/nvidia,tegra210-adma.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/dma/nvidia,tegra210-adma.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,55 @@
+* NVIDIA Tegra Audio DMA (ADMA) controller
+
+The Tegra Audio DMA controller that is used for transferring data
+between system memory and the Audio Processing Engine (APE).
+
+Required properties:
+- compatible: Must be "nvidia,tegra210-adma".
+- reg: Should contain DMA registers location and length. This should be
+  a single entry that includes all of the per-channel registers in one
+  contiguous bank.
+- interrupt-parent: Phandle to the interrupt parent controller.
+- interrupts: Should contain all of the per-channel DMA interrupts in
+  ascending order with respect to the DMA channel index.
+- clocks: Must contain one entry for the ADMA module clock
+  (TEGRA210_CLK_D_AUDIO).
+- clock-names: Must contain the name "d_audio" for the corresponding
+  'clocks' entry.
+- #dma-cells : Must be 1. The first cell denotes the receive/transmit
+  request number and should be between 1 and the maximum number of
+  requests supported. This value corresponds to the RX/TX_REQUEST_SELECT
+  fields in the ADMA_CHn_CTRL register.
+
+
+Example:
+
+adma: dma@702e2000 {
+	compatible = "nvidia,tegra210-adma";
+	reg = <0x0 0x702e2000 0x0 0x2000>;
+	interrupt-parent = <&tegra_agic>;
+	interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+	clocks = <&tegra_car TEGRA210_CLK_D_AUDIO>;
+	clock-names = "d_audio";
+	#dma-cells = <1>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/dma/qcom_bam_dma.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/dma/qcom_bam_dma.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/dma/qcom_bam_dma.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/dma/qcom_bam_dma.txt	2016-07-24 15:23:50.000000000 -0400
@@ -13,6 +13,8 @@ Required properties:
 - clock-names: must contain "bam_clk" entry
 - qcom,ee : indicates the active Execution Environment identifier (0-7) used in
   the secure world.
+- qcom,controlled-remotely : optional, indicates that the bam is controlled by
+  remote proccessor i.e. execution environment.
 
 Example:
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/dma/snps-dma.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/dma/snps-dma.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/dma/snps-dma.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/dma/snps-dma.txt	2016-07-24 15:23:50.000000000 -0400
@@ -13,6 +13,11 @@ Required properties:
 - chan_priority: priority of channels. 0 (default): increase from chan 0->n, 1:
   increase from chan n->0
 - block_size: Maximum block size supported by the controller
+- data-width: Maximum data width supported by hardware per AHB master
+  (in bytes, power of 2)
+
+
+Deprecated properties:
 - data_width: Maximum data width supported by hardware per AHB master
   (0 - 8bits, 1 - 16bits, ..., 5 - 256bits)
 
@@ -38,7 +43,7 @@ Example:
 		chan_allocation_order = <1>;
 		chan_priority = <1>;
 		block_size = <0xfff>;
-		data_width = <3 3>;
+		data-width = <8 8>;
 	};
 
 DMA clients connected to the Designware DMA controller must use the format
@@ -47,8 +52,8 @@ The four cells in order are:
 
 1. A phandle pointing to the DMA controller
 2. The DMA request line number
-3. Source master for transfers on allocated channel
-4. Destination master for transfers on allocated channel
+3. Memory master for transfers on allocated channel
+4. Peripheral master for transfers on allocated channel
 
 Example:
 	
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/dma/tegra20-apbdma.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/dma/tegra20-apbdma.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/dma/tegra20-apbdma.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/dma/tegra20-apbdma.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,44 +0,0 @@
-* NVIDIA Tegra APB DMA controller
-
-Required properties:
-- compatible: Should be "nvidia,<chip>-apbdma"
-- reg: Should contain DMA registers location and length. This shuld include
-  all of the per-channel registers.
-- interrupts: Should contain all of the per-channel DMA interrupts.
-- clocks: Must contain one entry, for the module clock.
-  See ../clocks/clock-bindings.txt for details.
-- resets : Must contain an entry for each entry in reset-names.
-  See ../reset/reset.txt for details.
-- reset-names : Must include the following entries:
-  - dma
-- #dma-cells : Must be <1>. This dictates the length of DMA specifiers in
-  client nodes' dmas properties. The specifier represents the DMA request
-  select value for the peripheral. For more details, consult the Tegra TRM's
-  documentation of the APB DMA channel control register REQ_SEL field.
-
-Examples:
-
-apbdma: dma@6000a000 {
-	compatible = "nvidia,tegra20-apbdma";
-	reg = <0x6000a000 0x1200>;
-	interrupts = < 0 136 0x04
-		       0 137 0x04
-		       0 138 0x04
-		       0 139 0x04
-		       0 140 0x04
-		       0 141 0x04
-		       0 142 0x04
-		       0 143 0x04
-		       0 144 0x04
-		       0 145 0x04
-		       0 146 0x04
-		       0 147 0x04
-		       0 148 0x04
-		       0 149 0x04
-		       0 150 0x04
-		       0 151 0x04 >;
-	clocks = <&tegra_car 34>;
-	resets = <&tegra_car 34>;
-	reset-names = "dma";
-	#dma-cells = <1>;
-};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt	2016-07-24 15:23:50.000000000 -0400
@@ -7,7 +7,7 @@ Required properties:
 - compatible: Should be "xlnx,axi-dma-1.00.a"
 - #dma-cells: Should be <1>, see "dmas" property below
 - reg: Should contain DMA registers location and length.
-- dma-channel child node: Should have atleast one channel and can have upto
+- dma-channel child node: Should have at least one channel and can have up to
 	two channels per device. This node specifies the properties of each
 	DMA channel (see child node properties below).
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/dma/xilinx/xilinx_vdma.txt	2016-07-24 15:23:50.000000000 -0400
@@ -3,18 +3,44 @@ It can be configured to have one channel
 as two channels, one is to transmit to the video device and another is
 to receive from the video device.
 
+Xilinx AXI DMA engine, it does transfers between memory and AXI4 stream
+target devices. It can be configured to have one channel or two channels.
+If configured as two channels, one is to transmit to the device and another
+is to receive from the device.
+
+Xilinx AXI CDMA engine, it does transfers between memory-mapped source
+address and a memory-mapped destination address.
+
 Required properties:
-- compatible: Should be "xlnx,axi-vdma-1.00.a"
+- compatible: Should be "xlnx,axi-vdma-1.00.a" or "xlnx,axi-dma-1.00.a" or
+	      "xlnx,axi-cdma-1.00.a""
 - #dma-cells: Should be <1>, see "dmas" property below
 - reg: Should contain VDMA registers location and length.
-- xlnx,num-fstores: Should be the number of framebuffers as configured in h/w.
+- xlnx,addrwidth: Should be the vdma addressing size in bits(ex: 32 bits).
+- dma-ranges: Should be as the following <dma_addr cpu_addr max_len>.
 - dma-channel child node: Should have at least one channel and can have up to
 	two channels per device. This node specifies the properties of each
 	DMA channel (see child node properties below).
+- clocks: Input clock specifier. Refer to common clock bindings.
+- clock-names: List of input clocks
+	For VDMA:
+	Required elements: "s_axi_lite_aclk"
+	Optional elements: "m_axi_mm2s_aclk" "m_axi_s2mm_aclk",
+			   "m_axis_mm2s_aclk", "s_axis_s2mm_aclk"
+	For CDMA:
+	Required elements: "s_axi_lite_aclk", "m_axi_aclk"
+	FOR AXIDMA:
+	Required elements: "s_axi_lite_aclk"
+	Optional elements: "m_axi_mm2s_aclk", "m_axi_s2mm_aclk",
+			   "m_axi_sg_aclk"
+
+Required properties for VDMA:
+- xlnx,num-fstores: Should be the number of framebuffers as configured in h/w.
 
 Optional properties:
 - xlnx,include-sg: Tells configured for Scatter-mode in
 	the hardware.
+Optional properties for VDMA:
 - xlnx,flush-fsync: Tells which channel to Flush on Frame sync.
 	It takes following values:
 	{1}, flush both channels
@@ -31,6 +57,7 @@ Required child node properties:
 Optional child node properties:
 - xlnx,include-dre: Tells hardware is configured for Data
 	Realignment Engine.
+Optional child node properties for VDMA:
 - xlnx,genlock-mode: Tells Genlock synchronization is
 	enabled/disabled in hardware.
 
@@ -41,8 +68,13 @@ axi_vdma_0: axivdma@40030000 {
 	compatible = "xlnx,axi-vdma-1.00.a";
 	#dma_cells = <1>;
 	reg = < 0x40030000 0x10000 >;
+	dma-ranges = <0x00000000 0x00000000 0x40000000>;
 	xlnx,num-fstores = <0x8>;
 	xlnx,flush-fsync = <0x1>;
+	xlnx,addrwidth = <0x20>;
+	clocks = <&clk 0>, <&clk 1>, <&clk 2>, <&clk 3>, <&clk 4>;
+	clock-names = "s_axi_lite_aclk", "m_axi_mm2s_aclk", "m_axi_s2mm_aclk",
+		      "m_axis_mm2s_aclk", "s_axis_s2mm_aclk";
 	dma-channel@40030000 {
 		compatible = "xlnx,axi-vdma-mm2s-channel";
 		interrupts = < 0 54 4 >;
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/gpio/gpio-74x164.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/gpio/gpio-74x164.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/gpio/gpio-74x164.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/gpio/gpio-74x164.txt	2016-07-24 15:23:50.000000000 -0400
@@ -1,7 +1,9 @@
 * Generic 8-bits shift register GPIO driver
 
 Required properties:
-- compatible : Should be "fairchild,74hc595"
+- compatible: Should contain one of the following:
+    "fairchild,74hc595"
+    "nxp,74lvc594"
 - reg : chip select number
 - gpio-controller : Marks the device node as a gpio controller.
 - #gpio-cells : Should be two.  The first cell is the pin number and
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt	2016-07-24 15:23:50.000000000 -0400
@@ -1,9 +1,10 @@
-* Freescale MPC512x/MPC8xxx/Layerscape GPIO controller
+* Freescale MPC512x/MPC8xxx/QorIQ/Layerscape GPIO controller
 
 Required properties:
 - compatible : Should be "fsl,<soc>-gpio"
   The following <soc>s are known to be supported:
-    mpc5121, mpc5125, mpc8349, mpc8572, mpc8610, pq3, qoriq.
+	mpc5121, mpc5125, mpc8349, mpc8572, mpc8610, pq3, qoriq,
+	ls1021a, ls1043a, ls2080a.
 - reg : Address and length of the register set for the device
 - interrupts : Should be the port interrupt shared by all 32 pins.
 - #gpio-cells : Should be two.  The first cell is the pin number and
@@ -15,7 +16,7 @@ Optional properties:
 - little-endian : GPIO registers are used as little endian. If not
                   present registers are used as big endian by default.
 
-Example:
+Example of gpio-controller node for a mpc5125 SoC:
 
 gpio0: gpio@1100 {
 	compatible = "fsl,mpc5125-gpio";
@@ -24,3 +25,16 @@ gpio0: gpio@1100 {
 	interrupts = <78 0x8>;
 	status = "okay";
 };
+
+Example of gpio-controller node for a ls2080a SoC:
+
+gpio0: gpio@2300000 {
+	compatible = "fsl,ls2080a-gpio", "fsl,qoriq-gpio";
+	reg = <0x0 0x2300000 0x0 0x10000>;
+	interrupts = <0 36 0x4>; /* Level high type */
+	gpio-controller;
+	little-endian;
+	#gpio-cells = <2>;
+	interrupt-controller;
+	#interrupt-cells = <2>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/gpio/gpio-poweroff.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/gpio/gpio-poweroff.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/gpio/gpio-poweroff.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/gpio/gpio-poweroff.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,36 +0,0 @@
-Driver a GPIO line that can be used to turn the power off.
-
-The driver supports both level triggered and edge triggered power off.
-At driver load time, the driver will request the given gpio line and
-install a pm_power_off handler. If the optional properties 'input' is
-not found, the GPIO line will be driven in the inactive
-state. Otherwise its configured as an input.
-
-When the pm_power_off is called, the gpio is configured as an output,
-and drive active, so triggering a level triggered power off
-condition. This will also cause an inactive->active edge condition, so
-triggering positive edge triggered power off. After a delay of 100ms,
-the GPIO is set to inactive, thus causing an active->inactive edge,
-triggering negative edge triggered power off. After another 100ms
-delay the GPIO is driver active again. If the power is still on and
-the CPU still running after a 3000ms delay, a WARN_ON(1) is emitted.
-
-Required properties:
-- compatible : should be "gpio-poweroff".
-- gpios : The GPIO to set high/low, see "gpios property" in
-  Documentation/devicetree/bindings/gpio/gpio.txt. If the pin should be
-  low to power down the board set it to "Active Low", otherwise set
-  gpio to "Active High".
-
-Optional properties:
-- input : Initially configure the GPIO line as an input. Only reconfigure
-  it to an output when the pm_power_off function is called. If this optional
-  property is not specified, the GPIO is initialized as an output in its
-  inactive state.
-
-Examples:
-
-gpio-poweroff {
-	compatible = "gpio-poweroff";
-	gpios = <&gpio 4 0>;
-};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/gpio/gpio-restart.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/gpio/gpio-restart.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/gpio/gpio-restart.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/gpio/gpio-restart.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,54 +0,0 @@
-Drive a GPIO line that can be used to restart the system from a restart
-handler.
-
-This binding supports level and edge triggered reset.  At driver load
-time, the driver will request the given gpio line and install a restart
-handler. If the optional properties 'open-source' is not found, the GPIO line
-will be driven in the inactive state.  Otherwise its not driven until
-the restart is initiated.
-
-When the system is restarted, the restart handler will be invoked in
-priority order.  The gpio is configured as an output, and driven active,
-triggering a level triggered reset condition. This will also cause an
-inactive->active edge condition, triggering positive edge triggered
-reset. After a delay specified by active-delay, the GPIO is set to
-inactive, thus causing an active->inactive edge, triggering negative edge
-triggered reset. After a delay specified by inactive-delay, the GPIO
-is driven active again.  After a delay specified by wait-delay, the
-restart handler completes allowing other restart handlers to be attempted.
-
-Required properties:
-- compatible : should be "gpio-restart".
-- gpios : The GPIO to set high/low, see "gpios property" in
-  Documentation/devicetree/bindings/gpio/gpio.txt. If the pin should be
-  low to reset the board set it to "Active Low", otherwise set
-  gpio to "Active High".
-
-Optional properties:
-- open-source : Treat the GPIO as being open source and defer driving
-  it to when the restart is initiated.  If this optional property is not
-  specified, the GPIO is initialized as an output in its inactive state.
-- priority : A priority ranging from 0 to 255 (default 128) according to
-  the following guidelines:
-	0:	Restart handler of last resort, with limited restart
-		capabilities
-	128:	Default restart handler; use if no other restart handler is
-		expected to be available, and/or if restart functionality is
-		sufficient to restart the entire system
-	255:	Highest priority restart handler, will preempt all other
-		restart handlers
-- active-delay: Delay (default 100) to wait after driving gpio active [ms]
-- inactive-delay: Delay (default 100) to wait after driving gpio inactive [ms]
-- wait-delay: Delay (default 3000) to wait after completing restart
-  sequence [ms]
-
-Examples:
-
-gpio-restart {
-	compatible = "gpio-restart";
-	gpios = <&gpio 4 0>;
-	priority = <128>;
-	active-delay = <100>;
-	inactive-delay = <100>;
-	wait-delay = <3000>;
-};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/gpio/gpio.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/gpio/gpio.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/gpio/gpio.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/gpio/gpio.txt	2016-07-24 15:23:50.000000000 -0400
@@ -131,6 +131,13 @@ Every GPIO controller node must contain
 property, and a #gpio-cells integer property, which indicates the number of
 cells in a gpio-specifier.
 
+Some system-on-chips (SoCs) use the concept of GPIO banks. A GPIO bank is an
+instance of a hardware IP core on a silicon die, usually exposed to the
+programmer as a coherent range of I/O addresses. Usually each such bank is
+exposed in the device tree as an individual gpio-controller node, reflecting
+the fact that the hardware was synthesized by reusing the same IP block a
+few times over.
+
 Optionally, a GPIO controller may have a "ngpios" property. This property
 indicates the number of in-use slots of available slots for GPIOs. The
 typical example is something like this: the hardware register is 32 bits
@@ -145,6 +152,21 @@ additional bitmask is needed to specify
 and which are dummies. The bindings for this case has not yet been
 specified, but should be specified if/when such hardware appears.
 
+Optionally, a GPIO controller may have a "gpio-line-names" property. This is
+an array of strings defining the names of the GPIO lines going out of the
+GPIO controller. This name should be the most meaningful producer name
+for the system, such as a rail name indicating the usage. Package names
+such as pin name are discouraged: such lines have opaque names (since they
+are by definition generic purpose) and such names are usually not very
+helpful. For example "MMC-CD", "Red LED Vdd" and "ethernet reset" are
+reasonable line names as they describe what the line is used for. "GPIO0"
+is not a good name to give to a GPIO line. Placeholders are discouraged:
+rather use the "" (blank string) if the use of the GPIO line is undefined
+in your design. The names are assigned starting from line offset 0 from
+left to right from the passed array. An incomplete array (where the number
+of passed named are less than ngpios) will still be used up until the last
+provided valid line index.
+
 Example:
 
 gpio-controller@00000000 {
@@ -153,6 +175,10 @@ gpio-controller@00000000 {
 	gpio-controller;
 	#gpio-cells = <2>;
 	ngpios = <18>;
+	gpio-line-names = "MMC-CD", "MMC-WP", "VDD eth", "RST eth", "LED R",
+		"LED G", "LED B", "Col A", "Col B", "Col C", "Col D",
+		"Row A", "Row B", "Row C", "Row D", "NMI button",
+		"poweroff", "reset";
 }
 
 The GPIO chip may contain GPIO hog definitions. GPIO hogging is a mechanism
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/gpio/gpio-xlp.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/gpio/gpio-xlp.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/gpio/gpio-xlp.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/gpio/gpio-xlp.txt	2016-07-24 15:23:50.000000000 -0400
@@ -3,6 +3,8 @@ Netlogic XLP Family GPIO
 
 This GPIO driver is used for following Netlogic XLP SoCs:
 	XLP832, XLP316, XLP208, XLP980, XLP532
+This GPIO driver is also compatible with GPIO controller found on
+Broadcom Vulcan ARM64.
 
 Required properties:
 -------------------
@@ -13,6 +15,7 @@ Required properties:
   - "netlogic,xlp208-gpio": For Netlogic XLP208
   - "netlogic,xlp980-gpio": For Netlogic XLP980
   - "netlogic,xlp532-gpio": For Netlogic XLP532
+  - "brcm,vulcan-gpio": For Broadcom Vulcan ARM64
 - reg: Physical base address and length of the controller's registers.
 - #gpio-cells: Should be two. The first cell is the pin number and the second
   cell is used to specify optional parameters (currently unused).
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/gpio/ibm,ppc4xx-gpio.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/gpio/ibm,ppc4xx-gpio.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/gpio/ibm,ppc4xx-gpio.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/gpio/ibm,ppc4xx-gpio.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,24 @@
+* IBM/AMCC/APM GPIO Controller for PowerPC 4XX series and compatible SoCs
+
+All GPIOs are pin-shared with other functions. DCRs control whether a
+particular pin that has GPIO capabilities acts as a GPIO or is used for
+another purpose. GPIO outputs are separately programmable to emulate
+an open-drain driver.
+
+Required properties:
+	- compatible: must be "ibm,ppc4xx-gpio"
+	- reg: address and length of the register set for the device
+	- #gpio-cells: must be set to 2. The first cell is the pin number
+		and the second cell is used to specify the gpio polarity:
+		0 = active high
+		1 = active low
+	- gpio-controller: marks the device node as a gpio controller.
+
+Example:
+
+GPIO0: gpio@ef600b00 {
+	compatible = "ibm,ppc4xx-gpio";
+	reg = <0xef600b00 0x00000048>;
+	#gpio-cells = <2>;
+	gpio-controller;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/gpio/microchip,pic32-gpio.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/gpio/microchip,pic32-gpio.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/gpio/microchip,pic32-gpio.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/gpio/microchip,pic32-gpio.txt	2016-07-24 15:23:50.000000000 -0400
@@ -33,7 +33,7 @@ gpio0: gpio0@1f860000 {
 	gpio-controller;
 	interrupt-controller;
 	#interrupt-cells = <2>;
-	clocks = <&PBCLK4>;
+	clocks = <&rootclk PB4CLK>;
 	microchip,gpio-bank = <0>;
 	gpio-ranges = <&pic32_pinctrl 0 0 16>;
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/gpio/nvidia,tegra186-gpio.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/gpio/nvidia,tegra186-gpio.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/gpio/nvidia,tegra186-gpio.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/gpio/nvidia,tegra186-gpio.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,161 @@
+NVIDIA Tegra186 GPIO controllers
+
+Tegra186 contains two GPIO controllers; a main controller and an "AON"
+controller. This binding document applies to both controllers. The register
+layouts for the controllers share many similarities, but also some significant
+differences. Hence, this document describes closely related but different
+bindings and compatible values.
+
+The Tegra186 GPIO controller allows software to set the IO direction of, and
+read/write the value of, numerous GPIO signals. Routing of GPIO signals to
+package balls is under the control of a separate pin controller HW block. Two
+major sets of registers exist:
+
+a) Security registers, which allow configuration of allowed access to the GPIO
+register set. These registers exist in a single contiguous block of physical
+address space. The size of this block, and the security features available,
+varies between the different GPIO controllers.
+
+Access to this set of registers is not necessary in all circumstances. Code
+that wishes to configure access to the GPIO registers needs access to these
+registers to do so. Code which simply wishes to read or write GPIO data does not
+need access to these registers.
+
+b) GPIO registers, which allow manipulation of the GPIO signals. In some GPIO
+controllers, these registers are exposed via multiple "physical aliases" in
+address space, each of which access the same underlying state. See the hardware
+documentation for rationale. Any particular GPIO client is expected to access
+just one of these physical aliases.
+
+Tegra HW documentation describes a unified naming convention for all GPIOs
+implemented by the SoC. Each GPIO is assigned to a port, and a port may control
+a number of GPIOs. Thus, each GPIO is named according to an alphabetical port
+name and an integer GPIO name within the port. For example, GPIO_PA0, GPIO_PN6,
+or GPIO_PCC3.
+
+The number of ports implemented by each GPIO controller varies. The number of
+implemented GPIOs within each port varies. GPIO registers within a controller
+are grouped and laid out according to the port they affect.
+
+The mapping from port name to the GPIO controller that implements that port, and
+the mapping from port name to register offset within a controller, are both
+extremely non-linear. The header file <dt-bindings/gpio/tegra186-gpio.h>
+describes the port-level mapping. In that file, the naming convention for ports
+matches the HW documentation. The values chosen for the names are alphabetically
+sorted within a particular controller. Drivers need to map between the DT GPIO
+IDs and HW register offsets using a lookup table.
+
+Each GPIO controller can generate a number of interrupt signals. Each signal
+represents the aggregate status for all GPIOs within a set of ports. Thus, the
+number of interrupt signals generated by a controller varies as a rough function
+of the number of ports it implements. Note that the HW documentation refers to
+both the overall controller HW module and the sets-of-ports as "controllers".
+
+Each GPIO controller in fact generates multiple interrupts signals for each set
+of ports. Each GPIO may be configured to feed into a specific one of the
+interrupt signals generated by a set-of-ports. The intent is for each generated
+signal to be routed to a different CPU, thus allowing different CPUs to each
+handle subsets of the interrupts within a port. The status of each of these
+per-port-set signals is reported via a separate register. Thus, a driver needs
+to know which status register to observe. This binding currently defines no
+configuration mechanism for this. By default, drivers should use register
+GPIO_${port}_INTERRUPT_STATUS_G1_0. Future revisions to the binding could
+define a property to configure this.
+
+Required properties:
+- compatible
+    Array of strings.
+    One of:
+    - "nvidia,tegra186-gpio".
+    - "nvidia,tegra186-gpio-aon".
+- reg-names
+    Array of strings.
+    Contains a list of names for the register spaces described by the reg
+    property. May contain the following entries, in any order:
+    - "gpio": Mandatory. GPIO control registers. This may cover either:
+        a) The single physical alias that this OS should use.
+        b) All physical aliases that exist in the controller. This is
+           appropriate when the OS is responsible for managing assignment of
+           the physical aliases.
+    - "security": Optional. Security configuration registers.
+    Users of this binding MUST look up entries in the reg property by name,
+    using this reg-names property to do so.
+- reg
+    Array of (physical base address, length) tuples.
+    Must contain one entry per entry in the reg-names property, in a matching
+    order.
+- interrupts
+    Array of interrupt specifiers.
+    The interrupt outputs from the HW block, one per set of ports, in the
+    order the HW manual describes them. The number of entries required varies
+    depending on compatible value:
+    - "nvidia,tegra186-gpio": 6 entries.
+    - "nvidia,tegra186-gpio-aon": 1 entry.
+- gpio-controller
+    Boolean.
+    Marks the device node as a GPIO controller/provider.
+- #gpio-cells
+    Single-cell integer.
+    Must be <2>.
+    Indicates how many cells are used in a consumer's GPIO specifier.
+    In the specifier:
+    - The first cell is the pin number.
+        See <dt-bindings/gpio/tegra186-gpio.h>.
+    - The second cell contains flags:
+        - Bit 0 specifies polarity
+            - 0: Active-high (normal).
+            - 1: Active-low (inverted).
+- interrupt-controller
+    Boolean.
+    Marks the device node as an interrupt controller/provider.
+- #interrupt-cells
+    Single-cell integer.
+    Must be <2>.
+    Indicates how many cells are used in a consumer's interrupt specifier.
+    In the specifier:
+    - The first cell is the GPIO number.
+        See <dt-bindings/gpio/tegra186-gpio.h>.
+    - The second cell is contains flags:
+        - Bits [3:0] indicate trigger type and level:
+            - 1: Low-to-high edge triggered.
+            - 2: High-to-low edge triggered.
+            - 4: Active high level-sensitive.
+            - 8: Active low level-sensitive.
+            Valid combinations are 1, 2, 3, 4, 8.
+
+Example:
+
+#include <dt-bindings/interrupt-controller/irq.h>
+
+gpio@2200000 {
+	compatible = "nvidia,tegra186-gpio";
+	reg-names = "security", "gpio";
+	reg =
+		<0x0 0x2200000 0x0 0x10000>,
+		<0x0 0x2210000 0x0 0x10000>;
+	interrupts =
+		<0 47 IRQ_TYPE_LEVEL_HIGH>,
+		<0 50 IRQ_TYPE_LEVEL_HIGH>,
+		<0 53 IRQ_TYPE_LEVEL_HIGH>,
+		<0 56 IRQ_TYPE_LEVEL_HIGH>,
+		<0 59 IRQ_TYPE_LEVEL_HIGH>,
+		<0 180 IRQ_TYPE_LEVEL_HIGH>;
+	gpio-controller;
+	#gpio-cells = <2>;
+	interrupt-controller;
+	#interrupt-cells = <2>;
+};
+
+gpio@c2f0000 {
+	compatible = "nvidia,tegra186-gpio-aon";
+	reg-names = "security", "gpio";
+	reg =
+		<0x0 0xc2f0000 0x0 0x1000>,
+		<0x0 0xc2f1000 0x0 0x1000>;
+	interrupts =
+		<0 60 IRQ_TYPE_LEVEL_HIGH>;
+	gpio-controller;
+	#gpio-cells = <2>;
+	interrupt-controller;
+	#interrupt-cells = <2>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/gpio/wd,mbl-gpio.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/gpio/wd,mbl-gpio.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/gpio/wd,mbl-gpio.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/gpio/wd,mbl-gpio.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,38 @@
+Bindings for the Western Digital's MyBook Live memory-mapped GPIO controllers.
+
+The Western Digital MyBook Live has two memory-mapped GPIO controllers.
+Both GPIO controller only have a single 8-bit data register, where GPIO
+state can be read and/or written.
+
+Required properties:
+	- compatible: should be "wd,mbl-gpio"
+	- reg-names: must contain
+		"dat" - data register
+	- reg: address + size pairs describing the GPIO register sets;
+		order must correspond with the order of entries in reg-names
+	- #gpio-cells: must be set to 2. The first cell is the pin number and
+			the second cell is used to specify the gpio polarity:
+			0 = active high
+			1 = active low
+	- gpio-controller: Marks the device node as a gpio controller.
+
+Optional properties:
+	- no-output: GPIOs are read-only.
+
+Examples:
+	gpio0: gpio0@e0000000 {
+		compatible = "wd,mbl-gpio";
+		reg-names = "dat";
+		reg = <0xe0000000 0x1>;
+		#gpio-cells = <2>;
+		gpio-controller;
+	};
+
+	gpio1: gpio1@e0100000 {
+		compatible = "wd,mbl-gpio";
+		reg-names = "dat";
+		reg = <0xe0100000 0x1>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		no-output;
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/gpu/nvidia,gk20a.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/gpu/nvidia,gk20a.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/gpu/nvidia,gk20a.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/gpu/nvidia,gk20a.txt	2016-07-24 15:23:50.000000000 -0400
@@ -1,9 +1,10 @@
-NVIDIA GK20A Graphics Processing Unit
+NVIDIA Tegra Graphics Processing Units
 
 Required properties:
-- compatible: "nvidia,<chip>-<gpu>"
+- compatible: "nvidia,<gpu>"
   Currently recognized values:
-  - nvidia,tegra124-gk20a
+  - nvidia,gk20a
+  - nvidia,gm20b
 - reg: Physical base address and length of the controller's registers.
   Must contain two entries:
   - first entry for bar0
@@ -19,14 +20,20 @@ Required properties:
 - clock-names: Must include the following entries:
   - gpu
   - pwr
+If the compatible string is "nvidia,gm20b", then the following clock
+is also required:
+  - ref
 - resets: Must contain an entry for each entry in reset-names.
   See ../reset/reset.txt for details.
 - reset-names: Must include the following entries:
   - gpu
 
-Example:
+Optional properties:
+- iommus: A reference to the IOMMU. See ../iommu/iommu.txt for details.
 
-	gpu@0,57000000 {
+Example for GK20A:
+
+	gpu@57000000 {
 		compatible = "nvidia,gk20a";
 		reg = <0x0 0x57000000 0x0 0x01000000>,
 		      <0x0 0x58000000 0x0 0x01000000>;
@@ -39,5 +46,25 @@ Example:
 		clock-names = "gpu", "pwr";
 		resets = <&tegra_car 184>;
 		reset-names = "gpu";
+		iommus = <&mc TEGRA_SWGROUP_GPU>;
+		status = "disabled";
+	};
+
+Example for GM20B:
+
+	gpu@57000000 {
+		compatible = "nvidia,gm20b";
+		reg = <0x0 0x57000000 0x0 0x01000000>,
+		      <0x0 0x58000000 0x0 0x01000000>;
+		interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "stall", "nonstall";
+		clocks = <&tegra_car TEGRA210_CLK_GPU>,
+			 <&tegra_car TEGRA210_CLK_PLL_P_OUT5>,
+			 <&tegra_car TEGRA210_CLK_PLL_G_REF>;
+		clock-names = "gpu", "pwr", "ref";
+		resets = <&tegra_car 184>;
+		reset-names = "gpu";
+		iommus = <&mc TEGRA_SWGROUP_GPU>;
 		status = "disabled";
 	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/hwmon/ina2xx.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/hwmon/ina2xx.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/hwmon/ina2xx.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/hwmon/ina2xx.txt	2016-07-24 15:23:50.000000000 -0400
@@ -7,6 +7,7 @@ Required properties:
 	- "ti,ina220" for ina220
 	- "ti,ina226" for ina226
 	- "ti,ina230" for ina230
+	- "ti,ina231" for ina231
 - reg: I2C address
 
 Optional properties:
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/hwmon/ltc2978.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/hwmon/ltc2978.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/hwmon/ltc2978.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/hwmon/ltc2978.txt	2016-07-24 15:23:50.000000000 -0400
@@ -13,6 +13,7 @@ Required properties:
   * "lltc,ltc3886"
   * "lltc,ltc3887"
   * "lltc,ltm2987"
+  * "lltc,ltm4675"
   * "lltc,ltm4676"
 - reg: I2C slave address
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/i2c/i2c-arb-gpio-challenge.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/i2c/i2c-arb-gpio-challenge.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/i2c/i2c-arb-gpio-challenge.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/i2c/i2c-arb-gpio-challenge.txt	2016-07-24 15:23:50.000000000 -0400
@@ -44,8 +44,8 @@ Required properties:
 - our-claim-gpio: The GPIO that we use to claim the bus.
 - their-claim-gpios: The GPIOs that the other sides use to claim the bus.
   Note that some implementations may only support a single other master.
-- Standard I2C mux properties. See mux.txt in this directory.
-- Single I2C child bus node at reg 0. See mux.txt in this directory.
+- Standard I2C mux properties. See i2c-mux.txt in this directory.
+- Single I2C child bus node at reg 0. See i2c-mux.txt in this directory.
 
 Optional properties:
 - slew-delay-us: microseconds to wait for a GPIO to go high. Default is 10 us.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/i2c/i2c-demux-pinctrl.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/i2c/i2c-demux-pinctrl.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/i2c/i2c-demux-pinctrl.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/i2c/i2c-demux-pinctrl.txt	2016-07-24 15:23:50.000000000 -0400
@@ -27,7 +27,8 @@ Required properties:
 - i2c-bus-name: The name of this bus. Also needed as pinctrl-name for the I2C
 		parents.
 
-Furthermore, I2C mux properties and child nodes. See mux.txt in this directory.
+Furthermore, I2C mux properties and child nodes. See i2c-mux.txt in this
+directory.
 
 Example:
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/i2c/i2c-mux-gpio.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/i2c/i2c-mux-gpio.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/i2c/i2c-mux-gpio.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/i2c/i2c-mux-gpio.txt	2016-07-24 15:23:50.000000000 -0400
@@ -22,8 +22,8 @@ Required properties:
 - i2c-parent: The phandle of the I2C bus that this multiplexer's master-side
   port is connected to.
 - mux-gpios: list of gpios used to control the muxer
-* Standard I2C mux properties. See mux.txt in this directory.
-* I2C child bus nodes. See mux.txt in this directory.
+* Standard I2C mux properties. See i2c-mux.txt in this directory.
+* I2C child bus nodes. See i2c-mux.txt in this directory.
 
 Optional properties:
 - idle-state: value to set the muxer to when idle. When no value is
@@ -33,7 +33,7 @@ For each i2c child node, an I2C child bu
 be numbered based on their order in the device tree.
 
 Whenever an access is made to a device on a child bus, the value set
-in the revelant node's reg property will be output using the list of
+in the relevant node's reg property will be output using the list of
 GPIOs, the first in the list holding the least-significant value.
 
 If an idle state is defined, using the idle-state (optional) property,
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/i2c/i2c-mux-pinctrl.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/i2c/i2c-mux-pinctrl.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/i2c/i2c-mux-pinctrl.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/i2c/i2c-mux-pinctrl.txt	2016-07-24 15:23:50.000000000 -0400
@@ -28,9 +28,9 @@ Also required are:
 * Standard pinctrl properties that specify the pin mux state for each child
   bus. See ../pinctrl/pinctrl-bindings.txt.
 
-* Standard I2C mux properties. See mux.txt in this directory.
+* Standard I2C mux properties. See i2c-mux.txt in this directory.
 
-* I2C child bus nodes. See mux.txt in this directory.
+* I2C child bus nodes. See i2c-mux.txt in this directory.
 
 For each named state defined in the pinctrl-names property, an I2C child bus
 will be created. I2C child bus numbers are assigned based on the index into
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/i2c/i2c-mux-reg.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/i2c/i2c-mux-reg.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/i2c/i2c-mux-reg.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/i2c/i2c-mux-reg.txt	2016-07-24 15:23:50.000000000 -0400
@@ -7,8 +7,8 @@ Required properties:
 - compatible: i2c-mux-reg
 - i2c-parent: The phandle of the I2C bus that this multiplexer's master-side
   port is connected to.
-* Standard I2C mux properties. See mux.txt in this directory.
-* I2C child bus nodes. See mux.txt in this directory.
+* Standard I2C mux properties. See i2c-mux.txt in this directory.
+* I2C child bus nodes. See i2c-mux.txt in this directory.
 
 Optional properties:
 - reg: this pair of <offset size> specifies the register to control the mux.
@@ -24,7 +24,7 @@ Optional properties:
   given, it defaults to the last value used.
 
 Whenever an access is made to a device on a child bus, the value set
-in the revelant node's reg property will be output to the register.
+in the relevant node's reg property will be output to the register.
 
 If an idle state is defined, using the idle-state (optional) property,
 whenever an access is not being made to a device on a child bus, the
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/i2c/i2c-octeon.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/i2c/i2c-octeon.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/i2c/i2c-octeon.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/i2c/i2c-octeon.txt	2016-07-24 15:23:50.000000000 -0400
@@ -4,6 +4,12 @@
 
   Compatibility with all cn3XXX, cn5XXX and cn6XXX SOCs.
 
+  or
+
+  compatible: "cavium,octeon-7890-twsi"
+
+  Compatibility with cn78XX SOCs.
+
 - reg: The base address of the TWSI/I2C bus controller register bank.
 
 - #address-cells: Must be <1>.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/i2c/i2c-rcar.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/i2c/i2c-rcar.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/i2c/i2c-rcar.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/i2c/i2c-rcar.txt	2016-07-24 15:23:50.000000000 -0400
@@ -19,6 +19,9 @@ Optional properties:
 - clock-frequency: desired I2C bus clock frequency in Hz. The absence of this
   property indicates the default frequency 100 kHz.
 - clocks: clock specifier.
+- dmas: Must contain a list of two references to DMA specifiers, one for
+  transmission, and one for reception.
+- dma-names: Must contain a list of two DMA names, "tx" and "rx".
 
 - i2c-scl-falling-time-ns: see i2c.txt
 - i2c-scl-internal-delay-ns: see i2c.txt
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/iio/accel/mma8452.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/iio/accel/mma8452.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/iio/accel/mma8452.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/iio/accel/mma8452.txt	2016-07-24 15:23:50.000000000 -0400
@@ -1,4 +1,4 @@
-Freescale MMA8451Q, MMA8452Q, MMA8453Q, MMA8652FC or MMA8653FC
+Freescale MMA8451Q, MMA8452Q, MMA8453Q, MMA8652FC, MMA8653FC or FXLS8471Q
 triaxial accelerometer
 
 Required properties:
@@ -9,6 +9,7 @@ Required properties:
     * "fsl,mma8453"
     * "fsl,mma8652"
     * "fsl,mma8653"
+    * "fsl,fxls8471"
 
   - reg: the I2C address of the chip
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/iio/adc/lpc1850-adc.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/iio/adc/lpc1850-adc.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/iio/adc/lpc1850-adc.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/iio/adc/lpc1850-adc.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,21 @@
+NXP LPC1850 ADC bindings
+
+Required properties:
+- compatible: Should be "nxp,lpc1850-adc"
+- reg: Offset and length of the register set for the ADC device
+- interrupts: The interrupt number for the ADC device
+- clocks: The root clock of the ADC controller
+- vref-supply: The regulator supply ADC reference voltage
+- resets: phandle to reset controller and line specifier
+
+Example:
+
+adc0: adc@400e3000 {
+	compatible = "nxp,lpc1850-adc";
+	reg = <0x400e3000 0x1000>;
+	interrupts = <17>;
+	clocks = <&ccu1 CLK_APB3_ADC0>;
+	vref-supply = <&reg_vdda>;
+	resets = <&rgu 40>;
+	status = "disabled";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/iio/adc/mxs-lradc.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/iio/adc/mxs-lradc.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/iio/adc/mxs-lradc.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/iio/adc/mxs-lradc.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,47 @@
+* Freescale MXS LRADC device driver
+
+Required properties:
+- compatible: Should be "fsl,imx23-lradc" for i.MX23 SoC and "fsl,imx28-lradc"
+              for i.MX28 SoC
+- reg: Address and length of the register set for the device
+- interrupts: Should contain the LRADC interrupts
+
+Optional properties:
+- fsl,lradc-touchscreen-wires: Number of wires used to connect the touchscreen
+                               to LRADC. Valid value is either 4 or 5. If this
+                               property is not present, then the touchscreen is
+                               disabled. 5 wires is valid for i.MX28 SoC only.
+- fsl,ave-ctrl: number of samples per direction to calculate an average value.
+                Allowed value is 1 ... 32, default is 4
+- fsl,ave-delay: delay between consecutive samples. Allowed value is
+                 2 ... 2048. It is used if 'fsl,ave-ctrl' > 1, counts at
+                 2 kHz and its default is 2 (= 1 ms)
+- fsl,settling: delay between plate switch to next sample. Allowed value is
+                1 ... 2047. It counts at 2 kHz and its default is
+                10 (= 5 ms)
+
+Example for i.MX23 SoC:
+
+	lradc@80050000 {
+		compatible = "fsl,imx23-lradc";
+		reg = <0x80050000 0x2000>;
+		interrupts = <36 37 38 39 40 41 42 43 44>;
+		status = "okay";
+		fsl,lradc-touchscreen-wires = <4>;
+		fsl,ave-ctrl = <4>;
+		fsl,ave-delay = <2>;
+		fsl,settling = <10>;
+	};
+
+Example for i.MX28 SoC:
+
+	lradc@80050000 {
+		compatible = "fsl,imx28-lradc";
+		reg = <0x80050000 0x2000>;
+		interrupts = <10 14 15 16 17 18 19 20 21 22 23 24 25>;
+		status = "okay";
+		fsl,lradc-touchscreen-wires = <5>;
+		fsl,ave-ctrl = <4>;
+		fsl,ave-delay = <2>;
+		fsl,settling = <10>;
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/iio/adc/rockchip-saradc.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/iio/adc/rockchip-saradc.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/iio/adc/rockchip-saradc.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/iio/adc/rockchip-saradc.txt	2016-07-24 15:23:50.000000000 -0400
@@ -1,7 +1,11 @@
 Rockchip Successive Approximation Register (SAR) A/D Converter bindings
 
 Required properties:
-- compatible: Should be "rockchip,saradc" or "rockchip,rk3066-tsadc"
+- compatible: should be "rockchip,<name>-saradc" or "rockchip,rk3066-tsadc"
+   - "rockchip,saradc": for rk3188, rk3288
+   - "rockchip,rk3066-tsadc": for rk3036
+   - "rockchip,rk3399-saradc": for rk3399
+
 - reg: physical base address of the controller and length of memory mapped
        region.
 - interrupts: The interrupt number to the cpu. The interrupt specifier format
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/iio/dac/ad5592r.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/iio/dac/ad5592r.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/iio/dac/ad5592r.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/iio/dac/ad5592r.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,155 @@
+Analog Devices AD5592R/AD5593R DAC/ADC device driver
+
+Required properties for the AD5592R:
+	- compatible: Must be "adi,ad5592r"
+	- reg: SPI chip select number for the device
+	- spi-max-frequency: Max SPI frequency to use (< 30000000)
+	- spi-cpol: The AD5592R requires inverse clock polarity (CPOL) mode
+
+Required properties for the AD5593R:
+	- compatible: Must be "adi,ad5593r"
+	- reg: I2C address of the device
+
+Required properties for all supported chips:
+	- #address-cells: Should be 1.
+	- #size-cells: Should be 0.
+	- channel nodes:
+	  Each child node represents one channel and has the following
+	  Required properties:
+		* reg: Pin on which this channel is connected to.
+		* adi,mode: Mode or function of this channel.
+			    Macros specifying the valid values
+			    can be found in <dt-bindings/iio/adi,ad5592r.h>.
+
+			    The following values are currently supported:
+				* CH_MODE_UNUSED (the pin is unused)
+				* CH_MODE_ADC (the pin is ADC input)
+				* CH_MODE_DAC (the pin is DAC output)
+				* CH_MODE_DAC_AND_ADC (the pin is DAC output
+					but can be monitored by an ADC, since
+					there is no disadvantage this
+					this should be considered as the
+					preferred DAC mode)
+				* CH_MODE_GPIO (the pin is registered
+					with GPIOLIB)
+	 Optional properties:
+		* adi,off-state: State of this channel when unused or the
+				 device gets removed. Macros specifying the
+				 valid values can be found in
+				 <dt-bindings/iio/adi,ad5592r.h>.
+
+				* CH_OFFSTATE_PULLDOWN (the pin is pulled down)
+				* CH_OFFSTATE_OUT_LOW  (the pin is output low)
+				* CH_OFFSTATE_OUT_HIGH (the pin is output high)
+				* CH_OFFSTATE_OUT_TRISTATE (the pin is
+					tristated output)
+
+
+Optional properties:
+	- vref-supply: Phandle to the external reference voltage supply. This should
+	  only be set if there is an external reference voltage connected to the VREF
+	  pin. If the property is not set the internal 2.5V reference is used.
+	- reset-gpios : GPIO spec for the RESET pin. If specified, it will be
+	  asserted during driver probe.
+	- gpio-controller: Marks the device node as a GPIO controller.
+	- #gpio-cells: Should be 2. The first cell is the GPIO number and the second
+	  cell specifies GPIO flags, as defined in <dt-bindings/gpio/gpio.h>.
+
+AD5592R Example:
+
+	#include <dt-bindings/iio/adi,ad5592r.h>
+
+	vref: regulator-vref {
+		compatible = "regulator-fixed";
+		regulator-name = "vref-ad559x";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+	};
+
+	ad5592r@0 {
+		#size-cells = <0>;
+		#address-cells = <1>;
+		#gpio-cells = <2>;
+		compatible = "adi,ad5592r";
+		reg = <0>;
+
+		spi-max-frequency = <1000000>;
+		spi-cpol;
+
+		vref-supply = <&vref>; /* optional */
+		reset-gpios = <&gpio0 86 0>;  /* optional */
+		gpio-controller;
+
+		channel@0 {
+			reg = <0>;
+			adi,mode = <CH_MODE_DAC>;
+		};
+		channel@1 {
+			reg = <1>;
+			adi,mode = <CH_MODE_ADC>;
+		};
+		channel@2 {
+			reg = <2>;
+			adi,mode = <CH_MODE_DAC_AND_ADC>;
+		};
+		channel@3 {
+			reg = <3>;
+			adi,mode = <CH_MODE_DAC_AND_ADC>;
+			adi,off-state = <CH_OFFSTATE_PULLDOWN>;
+		};
+		channel@4 {
+			reg = <4>;
+			adi,mode = <CH_MODE_UNUSED>;
+			adi,off-state = <CH_OFFSTATE_PULLDOWN>;
+		};
+		channel@5 {
+			reg = <5>;
+			adi,mode = <CH_MODE_GPIO>;
+			adi,off-state = <CH_OFFSTATE_PULLDOWN>;
+		};
+		channel@6 {
+			reg = <6>;
+			adi,mode = <CH_MODE_GPIO>;
+			adi,off-state = <CH_OFFSTATE_PULLDOWN>;
+		};
+		channel@7 {
+			reg = <7>;
+			adi,mode = <CH_MODE_GPIO>;
+			adi,off-state = <CH_OFFSTATE_PULLDOWN>;
+		};
+	};
+
+AD5593R Example:
+
+	#include <dt-bindings/iio/adi,ad5592r.h>
+
+	ad5593r@10 {
+		#size-cells = <0>;
+		#address-cells = <1>;
+		#gpio-cells = <2>;
+		compatible = "adi,ad5593r";
+		reg = <0x10>;
+		gpio-controller;
+
+		channel@0 {
+			reg = <0>;
+			adi,mode = <CH_MODE_DAC>;
+			adi,off-state = <CH_OFFSTATE_PULLDOWN>;
+		};
+		channel@1 {
+			reg = <1>;
+			adi,mode = <CH_MODE_ADC>;
+			adi,off-state = <CH_OFFSTATE_PULLDOWN>;
+		};
+		channel@2 {
+			reg = <2>;
+			adi,mode = <CH_MODE_DAC_AND_ADC>;
+			adi,off-state = <CH_OFFSTATE_PULLDOWN>;
+		};
+		channel@6 {
+			reg = <6>;
+			adi,mode = <CH_MODE_GPIO>;
+			adi,off-state = <CH_OFFSTATE_PULLDOWN>;
+		};
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/iio/dac/lpc1850-dac.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/iio/dac/lpc1850-dac.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/iio/dac/lpc1850-dac.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/iio/dac/lpc1850-dac.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,20 @@
+NXP LPC1850 DAC bindings
+
+Required properties:
+- compatible: Should be "nxp,lpc1850-dac"
+- reg: Offset and length of the register set for the ADC device
+- interrupts: The interrupt number for the ADC device
+- clocks: The root clock of the ADC controller
+- vref-supply: The regulator supply ADC reference voltage
+- resets: phandle to reset controller and line specifier
+
+Example:
+dac: dac@400e1000 {
+	compatible = "nxp,lpc1850-dac";
+	reg = <0x400e1000 0x1000>;
+	interrupts = <0>;
+	clocks = <&ccu1 CLK_APB3_DAC>;
+	vref-supply = <&reg_vdda>;
+	resets = <&rgu 42>;
+	status = "disabled";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/iio/imu/inv_mpu6050.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/iio/imu/inv_mpu6050.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/iio/imu/inv_mpu6050.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/iio/imu/inv_mpu6050.txt	2016-07-24 15:23:50.000000000 -0400
@@ -8,10 +8,23 @@ Required properties:
  - interrupt-parent : should be the phandle for the interrupt controller
  - interrupts : interrupt mapping for GPIO IRQ
 
+Optional properties:
+ - mount-matrix: an optional 3x3 mounting rotation matrix
+
+
 Example:
 	mpu6050@68 {
 		compatible = "invensense,mpu6050";
 		reg = <0x68>;
 		interrupt-parent = <&gpio1>;
 		interrupts = <18 1>;
+		mount-matrix = "-0.984807753012208",  /* x0 */
+		               "0",                   /* y0 */
+		               "-0.173648177666930",  /* z0 */
+		               "0",                   /* x1 */
+		               "-1",                  /* y1 */
+		               "0",                   /* z1 */
+		               "-0.173648177666930",  /* x2 */
+		               "0",                   /* y2 */
+		               "0.984807753012208";   /* z2 */
 	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/iio/magnetometer/ak8975.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/iio/magnetometer/ak8975.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/iio/magnetometer/ak8975.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/iio/magnetometer/ak8975.txt	2016-07-24 15:23:50.000000000 -0400
@@ -8,6 +8,8 @@ Required properties:
 Optional properties:
 
   - gpios : should be device tree identifier of the magnetometer DRDY pin
+  - vdd-supply: an optional regulator that needs to be on to provide VDD
+  - mount-matrix: an optional 3x3 mounting rotation matrix
 
 Example:
 
@@ -15,4 +17,14 @@ ak8975@0c {
         compatible = "asahi-kasei,ak8975";
         reg = <0x0c>;
         gpios = <&gpj0 7 0>;
+        vdd-supply = <&ldo_3v3_gnss>;
+        mount-matrix = "-0.984807753012208",  /* x0 */
+                       "0",                   /* y0 */
+                       "-0.173648177666930",  /* z0 */
+                       "0",                   /* x1 */
+                       "-1",                  /* y1 */
+                       "0",                   /* z1 */
+                       "-0.173648177666930",  /* x2 */
+                       "0",                   /* y2 */
+                       "0.984807753012208";   /* z2 */
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/iio/potentiometer/ds1803.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/iio/potentiometer/ds1803.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/iio/potentiometer/ds1803.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/iio/potentiometer/ds1803.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,21 @@
+* Maxim Integrated DS1803 digital potentiometer driver
+
+The node for this driver must be a child node of a I2C controller, hence
+all mandatory properties for your controller must be specified. See directory:
+
+        Documentation/devicetree/bindings/i2c
+
+for more details.
+
+Required properties:
+	- compatible:  	Must be one of the following, depending on the
+			model:
+			"maxim,ds1803-010",
+			"maxim,ds1803-050",
+			"maxim,ds1803-100"
+
+Example:
+ds1803: ds1803@1 {
+	reg = <0x28>;
+	compatible = "maxim,ds1803-010";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/iio/potentiometer/mcp4131.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/iio/potentiometer/mcp4131.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/iio/potentiometer/mcp4131.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/iio/potentiometer/mcp4131.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,84 @@
+* Microchip MCP413X/414X/415X/416X/423X/424X/425X/426X Digital Potentiometer
+  driver
+
+The node for this driver must be a child node of a SPI controller, hence
+all mandatory properties described in
+
+        Documentation/devicetree/bindings/spi/spi-bus.txt
+
+must be specified.
+
+Required properties:
+	- compatible:  	Must be one of the following, depending on the
+			model:
+			"microchip,mcp4131-502"
+			"microchip,mcp4131-103"
+			"microchip,mcp4131-503"
+			"microchip,mcp4131-104"
+			"microchip,mcp4132-502"
+			"microchip,mcp4132-103"
+			"microchip,mcp4132-503"
+			"microchip,mcp4132-104"
+			"microchip,mcp4141-502"
+			"microchip,mcp4141-103"
+			"microchip,mcp4141-503"
+			"microchip,mcp4141-104"
+			"microchip,mcp4142-502"
+			"microchip,mcp4142-103"
+			"microchip,mcp4142-503"
+			"microchip,mcp4142-104"
+			"microchip,mcp4151-502"
+			"microchip,mcp4151-103"
+			"microchip,mcp4151-503"
+			"microchip,mcp4151-104"
+			"microchip,mcp4152-502"
+			"microchip,mcp4152-103"
+			"microchip,mcp4152-503"
+			"microchip,mcp4152-104"
+			"microchip,mcp4161-502"
+			"microchip,mcp4161-103"
+			"microchip,mcp4161-503"
+			"microchip,mcp4161-104"
+			"microchip,mcp4162-502"
+			"microchip,mcp4162-103"
+			"microchip,mcp4162-503"
+			"microchip,mcp4162-104"
+			"microchip,mcp4231-502"
+			"microchip,mcp4231-103"
+			"microchip,mcp4231-503"
+			"microchip,mcp4231-104"
+			"microchip,mcp4232-502"
+			"microchip,mcp4232-103"
+			"microchip,mcp4232-503"
+			"microchip,mcp4232-104"
+			"microchip,mcp4241-502"
+			"microchip,mcp4241-103"
+			"microchip,mcp4241-503"
+			"microchip,mcp4241-104"
+			"microchip,mcp4242-502"
+			"microchip,mcp4242-103"
+			"microchip,mcp4242-503"
+			"microchip,mcp4242-104"
+			"microchip,mcp4251-502"
+			"microchip,mcp4251-103"
+			"microchip,mcp4251-503"
+			"microchip,mcp4251-104"
+			"microchip,mcp4252-502"
+			"microchip,mcp4252-103"
+			"microchip,mcp4252-503"
+			"microchip,mcp4252-104"
+			"microchip,mcp4261-502"
+			"microchip,mcp4261-103"
+			"microchip,mcp4261-503"
+			"microchip,mcp4261-104"
+			"microchip,mcp4262-502"
+			"microchip,mcp4262-103"
+			"microchip,mcp4262-503"
+			"microchip,mcp4262-104"
+
+Example:
+mcp4131: mcp4131@0 {
+	compatible = "mcp4131-502";
+	reg = <0>;
+	spi-max-frequency = <500000>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/iio/pressure/hp03.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/iio/pressure/hp03.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/iio/pressure/hp03.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/iio/pressure/hp03.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,17 @@
+HopeRF HP03 digital pressure/temperature sensors
+
+Required properties:
+- compatible: must be "hoperf,hp03"
+- xclr-gpio: must be device tree identifier of the XCLR pin.
+             The XCLR pin is a reset of the ADC in the chip,
+             it must be pulled HI before the conversion and
+             readout of the value from the ADC registers and
+             pulled LO afterward.
+
+Example:
+
+hp03@0x77 {
+	compatible = "hoperf,hp03";
+	reg = <0x77>;
+	xclr-gpio = <&portc 0 0x0>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/iio/pressure/ms5611.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/iio/pressure/ms5611.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/iio/pressure/ms5611.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/iio/pressure/ms5611.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,19 @@
+MEAS ms5611 family pressure sensors
+
+Pressure sensors from MEAS Switzerland with SPI and I2C bus interfaces.
+
+Required properties:
+- compatible: "meas,ms5611" or "meas,ms5607"
+- reg: the I2C address or SPI chip select the device will respond to
+
+Optional properties:
+- vdd-supply: an optional regulator that needs to be on to provide VDD
+  power to the sensor.
+
+Example:
+
+ms5607@77 {
+	compatible = "meas,ms5607";
+	reg = <0x77>;
+	vdd-supply = <&ldo_3v3_gnss>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/iio/st-sensors.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/iio/st-sensors.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/iio/st-sensors.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/iio/st-sensors.txt	2016-07-24 15:23:50.000000000 -0400
@@ -16,6 +16,10 @@ Optional properties:
 - st,drdy-int-pin: the pin on the package that will be used to signal
   "data ready" (valid values: 1 or 2). This property is not configurable
   on all sensors.
+- drive-open-drain: the interrupt/data ready line will be configured
+  as open drain, which is useful if several sensors share the same
+  interrupt line. (This binding is taken from pinctrl/pinctrl-bindings.txt)
+  This is a boolean property.
 
 Sensors may also have applicable pin control settings, those use the
 standard bindings from pinctrl/pinctrl-bindings.txt.
@@ -37,6 +41,7 @@ Accelerometers:
 - st,lsm330-accel
 - st,lsm303agr-accel
 - st,lis2dh12-accel
+- st,h3lis331dl-accel
 
 Gyroscopes:
 - st,l3g4200d-gyro
@@ -46,6 +51,7 @@ Gyroscopes:
 - st,l3gd20-gyro
 - st,l3g4is-gyro
 - st,lsm330-gyro
+- st,lsm9ds0-gyro
 
 Magnetometers:
 - st,lsm303agr-magn
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/input/ads7846.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/input/ads7846.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/input/ads7846.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/input/ads7846.txt	2016-07-24 15:23:50.000000000 -0400
@@ -29,7 +29,7 @@ Optional properties:
 	ti,vref-delay-usecs		vref supply delay in usecs, 0 for
 					external vref (u16).
 	ti,vref-mv			The VREF voltage, in millivolts (u16).
-					Set to 0 to use internal refernce
+					Set to 0 to use internal references
 					(ADS7846).
 	ti,keep-vref-on			set to keep vref on for differential
 					measurements as well
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/input/gpio-keys.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/input/gpio-keys.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/input/gpio-keys.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/input/gpio-keys.txt	2016-07-24 15:23:50.000000000 -0400
@@ -32,17 +32,17 @@ Optional subnode-properties:
 
 Example nodes:
 
-	gpio_keys {
+	gpio-keys {
 			compatible = "gpio-keys";
-			#address-cells = <1>;
-			#size-cells = <0>;
 			autorepeat;
-			button@21 {
+
+			up {
 				label = "GPIO Key UP";
 				linux,code = <103>;
 				gpios = <&gpio1 0 1>;
 			};
-			button@22 {
+
+			down {
 				label = "GPIO Key DOWN";
 				linux,code = <108>;
 				interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/input/touchscreen/brcm,iproc-touchscreen.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/input/touchscreen/brcm,iproc-touchscreen.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/input/touchscreen/brcm,iproc-touchscreen.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/input/touchscreen/brcm,iproc-touchscreen.txt	2016-07-24 15:23:50.000000000 -0400
@@ -2,11 +2,17 @@
 
 Required properties:
 - compatible: must be "brcm,iproc-touchscreen"
-- reg: physical base address of the controller and length of memory mapped
-  region.
+- ts_syscon: handler of syscon node defining physical base
+  address of the controller and length of memory mapped region.
+  If this property is selected please make sure MFD_SYSCON config
+  is enabled in the defconfig file.
 - clocks:  The clock provided by the SOC to driver the tsc
-- clock-name:  name for the clock
+- clock-names:  name for the clock
 - interrupts: The touchscreen controller's interrupt
+- address-cells: Specify the number of u32 entries needed in child nodes.
+  Should set to 1.
+- size-cells: Specify number of u32 entries needed to specify child nodes size
+  in reg property. Should set to 1.
 
 Optional properties:
 - scanning_period: Time between scans. Each step is 1024 us.  Valid 1-256.
@@ -53,13 +59,18 @@ Optional properties:
 - touchscreen-inverted-x: X axis is inverted (boolean)
 - touchscreen-inverted-y: Y axis is inverted (boolean)
 
-Example:
+Example: An example of touchscreen node
 
-	touchscreen: tsc@0x180A6000 {
+	ts_adc_syscon: ts_adc_syscon@180a6000 {
+		compatible = "brcm,iproc-ts-adc-syscon","syscon";
+		reg = <0x180a6000 0xc30>;
+	};
+
+	touchscreen: touchscreen@180A6000 {
 		compatible = "brcm,iproc-touchscreen";
 		#address-cells = <1>;
 		#size-cells = <1>;
-		reg = <0x180A6000 0x40>;
+		ts_syscon = <&ts_adc_syscon>;
 		clocks = <&adc_clk>;
 		clock-names = "tsc_clk";
 		interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/input/touchscreen/fsl-mx25-tcq.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/input/touchscreen/fsl-mx25-tcq.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/input/touchscreen/fsl-mx25-tcq.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/input/touchscreen/fsl-mx25-tcq.txt	2016-07-24 15:23:50.000000000 -0400
@@ -15,7 +15,7 @@ Optional properties:
  - fsl,pen-debounce-ns: Pen debounce time in nanoseconds.
  - fsl,pen-threshold: Pen-down threshold for the touchscreen. This is a value
    between 1 and 4096. It is the ratio between the internal reference voltage
-   and the measured voltage after the plate was precharged. Resistence between
+   and the measured voltage after the plate was precharged. Resistance between
    plates and therefore the voltage decreases with pressure so that a smaller
    value is equivalent to a higher pressure.
  - fsl,settling-time-ns: Settling time in nanoseconds. The settling time is before
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt	2016-07-24 15:23:50.000000000 -0400
@@ -11,6 +11,8 @@ Main node required properties:
 - interrupt-controller : Identifies the node as an interrupt controller
 - #interrupt-cells : Specifies the number of cells needed to encode an
   interrupt source. Must be a single cell with a value of at least 3.
+  If the system requires describing PPI affinity, then the value must
+  be at least 4.
 
   The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI
   interrupts. Other values are reserved for future use.
@@ -24,7 +26,14 @@ Main node required properties:
 		1 = edge triggered
 		4 = level triggered
 
-  Cells 4 and beyond are reserved for future use and must have a value
+  The 4th cell is a phandle to a node describing a set of CPUs this
+  interrupt is affine to. The interrupt must be a PPI, and the node
+  pointed must be a subnode of the "ppi-partitions" subnode. For
+  interrupt types other than PPI or PPIs that are not partitionned,
+  this cell must be zero. See the "ppi-partitions" node description
+  below.
+
+  Cells 5 and beyond are reserved for future use and must have a value
   of 0 if present.
 
 - reg : Specifies base physical address(s) and size of the GIC
@@ -50,6 +59,11 @@ Optional
 
 Sub-nodes:
 
+PPI affinity can be expressed as a single "ppi-partitions" node,
+containing a set of sub-nodes, each with the following property:
+- affinity: Should be a list of phandles to CPU nodes (as described in
+Documentation/devicetree/bindings/arm/cpus.txt).
+
 GICv3 has one or more Interrupt Translation Services (ITS) that are
 used to route Message Signalled Interrupts (MSI) to the CPUs.
 
@@ -91,7 +105,7 @@ Examples:
 
 	gic: interrupt-controller@2c010000 {
 		compatible = "arm,gic-v3";
-		#interrupt-cells = <3>;
+		#interrupt-cells = <4>;
 		#address-cells = <2>;
 		#size-cells = <2>;
 		ranges;
@@ -119,4 +133,20 @@ Examples:
 			#msi-cells = <1>;
 			reg = <0x0 0x2c400000 0 0x200000>;
 		};
+
+		ppi-partitions {
+			part0: interrupt-partition-0 {
+				affinity = <&cpu0 &cpu2>;
+			};
+
+			part1: interrupt-partition-1 {
+				affinity = <&cpu1 &cpu3>;
+			};
+		};
+	};
+
+
+	device@0 {
+		reg = <0 0 0 4>;
+		interrupts = <1 1 4 &part0>;
 	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/interrupt-controller/arm,versatile-fpga-irq.txt	2016-07-24 15:23:50.000000000 -0400
@@ -6,7 +6,7 @@ controllers are OR:ed together and fed t
 instance can handle up to 32 interrupts.
 
 Required properties:
-- compatible: "arm,versatile-fpga-irq"
+- compatible: "arm,versatile-fpga-irq" or "oxsemi,ox810se-rps-irq"
 - interrupt-controller: Identifies the node as an interrupt controller
 - #interrupt-cells: The number of cells to define the interrupts.  Must be 1
   as the FPGA IRQ controller has no configuration options for interrupt
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt	2016-07-24 15:23:50.000000000 -0400
@@ -71,8 +71,8 @@ Bank 1:
 24: DMA8
 25: DMA9
 26: DMA10
-27: DMA11
-28: DMA12
+27: DMA11-14 - shared interrupt for DMA 11 to 14
+28: DMAALL - triggers on all dma interrupts (including chanel 15)
 29: AUX
 30: ARM
 31: VPUDMA
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-l1-intc.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-l1-intc.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-l1-intc.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-l1-intc.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,57 @@
+Broadcom BCM6345-style Level 1 interrupt controller
+
+This block is a first level interrupt controller that is typically connected
+directly to one of the HW INT lines on each CPU.
+
+Key elements of the hardware design include:
+
+- 32, 64 or 128 incoming level IRQ lines
+
+- Most onchip peripherals are wired directly to an L1 input
+
+- A separate instance of the register set for each CPU, allowing individual
+  peripheral IRQs to be routed to any CPU
+
+- Contains one or more enable/status word pairs per CPU
+
+- No atomic set/clear operations
+
+- No polarity/level/edge settings
+
+- No FIFO or priority encoder logic; software is expected to read all
+  2-4 status words to determine which IRQs are pending
+
+Required properties:
+
+- compatible: should be "brcm,bcm<soc>-l1-intc", "brcm,bcm6345-l1-intc"
+- reg: specifies the base physical address and size of the registers;
+  the number of supported IRQs is inferred from the size argument
+- interrupt-controller: identifies the node as an interrupt controller
+- #interrupt-cells: specifies the number of cells needed to encode an interrupt
+  source, should be 1.
+- interrupt-parent: specifies the phandle to the parent interrupt controller(s)
+  this one is cascaded from
+- interrupts: specifies the interrupt line(s) in the interrupt-parent controller
+  node; valid values depend on the type of parent interrupt controller
+
+If multiple reg ranges and interrupt-parent entries are present on an SMP
+system, the driver will allow IRQ SMP affinity to be set up through the
+/proc/irq/ interface.  In the simplest possible configuration, only one
+reg range and one interrupt-parent is needed.
+
+The driver operates in native CPU endian by default, there is no support for
+specifying an alternative endianness.
+
+Example:
+
+periph_intc: interrupt-controller@10000000 {
+        compatible = "brcm,bcm63168-l1-intc", "brcm,bcm6345-l1-intc";
+        reg = <0x10000020 0x20>,
+              <0x10000040 0x20>;
+
+        interrupt-controller;
+        #interrupt-cells = <1>;
+
+        interrupt-parent = <&cpu_intc>;
+        interrupts = <2>, <3>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/interrupt-controller/ezchip,nps400-ic.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/interrupt-controller/ezchip,nps400-ic.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/interrupt-controller/ezchip,nps400-ic.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/interrupt-controller/ezchip,nps400-ic.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,17 @@
+EZchip NPS Interrupt Controller
+
+Required properties:
+
+- compatible : should be "ezchip,nps400-ic"
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells : Specifies the number of cells needed to encode an
+  interrupt source. The value shall be 1.
+
+
+Example:
+
+intc: interrupt-controller {
+	compatible = "ezchip,nps400-ic";
+	interrupt-controller;
+	#interrupt-cells = <1>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,30 @@
+* Freescale Layerscape SCFG PCIe MSI controller
+
+Required properties:
+
+- compatible: should be "fsl,<soc-name>-msi" to identify
+	      Layerscape PCIe MSI controller block such as:
+              "fsl,1s1021a-msi"
+              "fsl,1s1043a-msi"
+- msi-controller: indicates that this is a PCIe MSI controller node
+- reg: physical base address of the controller and length of memory mapped.
+- interrupts: an interrupt to the parent interrupt controller.
+
+Optional properties:
+- interrupt-parent: the phandle to the parent interrupt controller.
+
+This interrupt controller hardware is a second level interrupt controller that
+is hooked to a parent interrupt controller: e.g: ARM GIC for ARM-based
+platforms. If interrupt-parent is not provided, the default parent interrupt
+controller will be used.
+Each PCIe node needs to have property msi-parent that points to
+MSI controller node
+
+Examples:
+
+	msi1: msi-controller@1571000 {
+		compatible = "fsl,1s1043a-msi";
+		reg = <0x0 0x1571000 0x0 0x8>,
+		msi-controller;
+		interrupts = <0 116 0x4>;
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/interrupt-controller/mediatek,sysirq.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/interrupt-controller/mediatek,sysirq.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/interrupt-controller/mediatek,sysirq.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/interrupt-controller/mediatek,sysirq.txt	2016-07-24 15:23:50.000000000 -0400
@@ -16,8 +16,7 @@ Required properties:
 	"mediatek,mt6577-sysirq"
 	"mediatek,mt2701-sysirq"
 - interrupt-controller : Identifies the node as an interrupt controller
-- #interrupt-cells : Use the same format as specified by GIC in
-  Documentation/devicetree/bindings/arm/gic.txt
+- #interrupt-cells : Use the same format as specified by GIC in arm,gic.txt.
 - interrupt-parent: phandle of irq parent for sysirq. The parent must
   use the same interrupt-cells format as GIC.
 - reg: Physical base address of the intpol registers and length of memory
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra20-ictlr.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra20-ictlr.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra20-ictlr.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra20-ictlr.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,43 @@
+NVIDIA Legacy Interrupt Controller
+
+All Tegra SoCs contain a legacy interrupt controller that routes
+interrupts to the GIC, and also serves as a wakeup source. It is also
+referred to as "ictlr", hence the name of the binding.
+
+The HW block exposes a number of interrupt controllers, each
+implementing a set of 32 interrupts.
+
+Required properties:
+
+- compatible : should be: "nvidia,tegra<chip>-ictlr". The LIC on
+  subsequent SoCs remained backwards-compatible with Tegra30, so on
+  Tegra generations later than Tegra30 the compatible value should
+  include "nvidia,tegra30-ictlr".	
+- reg : Specifies base physical address and size of the registers.
+  Each controller must be described separately (Tegra20 has 4 of them,
+  whereas Tegra30 and later have 5"  
+- interrupt-controller : Identifies the node as an interrupt controller.
+- #interrupt-cells : Specifies the number of cells needed to encode an
+  interrupt source. The value must be 3.
+- interrupt-parent : a phandle to the GIC these interrupts are routed
+  to.
+
+Notes:
+
+- Because this HW ultimately routes interrupts to the GIC, the
+  interrupt specifier must be that of the GIC.
+- Only SPIs can use the ictlr as an interrupt parent. SGIs and PPIs
+  are explicitly forbidden.
+
+Example:
+
+	ictlr: interrupt-controller@60004000 {
+		compatible = "nvidia,tegra20-ictlr", "nvidia,tegra-ictlr";
+		reg = <0x60004000 64>,
+		      <0x60004100 64>,
+		      <0x60004200 64>,
+		      <0x60004300 64>;
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		interrupt-parent = <&intc>;
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/interrupt-controller/nvidia,tegra-ictlr.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,43 +0,0 @@
-NVIDIA Legacy Interrupt Controller
-
-All Tegra SoCs contain a legacy interrupt controller that routes
-interrupts to the GIC, and also serves as a wakeup source. It is also
-referred to as "ictlr", hence the name of the binding.
-
-The HW block exposes a number of interrupt controllers, each
-implementing a set of 32 interrupts.
-
-Required properties:
-
-- compatible : should be: "nvidia,tegra<chip>-ictlr". The LIC on
-  subsequent SoCs remained backwards-compatible with Tegra30, so on
-  Tegra generations later than Tegra30 the compatible value should
-  include "nvidia,tegra30-ictlr".	
-- reg : Specifies base physical address and size of the registers.
-  Each controller must be described separately (Tegra20 has 4 of them,
-  whereas Tegra30 and later have 5"  
-- interrupt-controller : Identifies the node as an interrupt controller.
-- #interrupt-cells : Specifies the number of cells needed to encode an
-  interrupt source. The value must be 3.
-- interrupt-parent : a phandle to the GIC these interrupts are routed
-  to.
-
-Notes:
-
-- Because this HW ultimately routes interrupts to the GIC, the
-  interrupt specifier must be that of the GIC.
-- Only SPIs can use the ictlr as an interrupt parent. SGIs and PPIs
-  are explicitly forbidden.
-
-Example:
-
-	ictlr: interrupt-controller@60004000 {
-		compatible = "nvidia,tegra20-ictlr", "nvidia,tegra-ictlr";
-		reg = <0x60004000 64>,
-		      <0x60004100 64>,
-		      <0x60004200 64>,
-		      <0x60004300 64>;
-		interrupt-controller;
-		#interrupt-cells = <3>;
-		interrupt-parent = <&intc>;
-	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/interrupt-controller/nxp,lpc3220-mic.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/interrupt-controller/nxp,lpc3220-mic.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/interrupt-controller/nxp,lpc3220-mic.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/interrupt-controller/nxp,lpc3220-mic.txt	2016-07-24 15:23:50.000000000 -0400
@@ -1,38 +1,60 @@
-* NXP LPC32xx Main Interrupt Controller
-  (MIC, including SIC1 and SIC2 secondary controllers)
+* NXP LPC32xx MIC, SIC1 and SIC2 Interrupt Controllers
 
 Required properties:
-- compatible: Should be "nxp,lpc3220-mic"
-- interrupt-controller: Identifies the node as an interrupt controller.
-- interrupt-parent: Empty for the interrupt controller itself
-- #interrupt-cells: The number of cells to define the interrupts. Should be 2.
-  The first cell is the IRQ number
-  The second cell is used to specify mode:
-      1 = low-to-high edge triggered
-      2 = high-to-low edge triggered
-      4 = active high level-sensitive
-      8 = active low level-sensitive
-      Default for internal sources should be set to 4 (active high).
-- reg: Should contain MIC registers location and length
+- compatible: "nxp,lpc3220-mic" or "nxp,lpc3220-sic".
+- reg: should contain IC registers location and length.
+- interrupt-controller: identifies the node as an interrupt controller.
+- #interrupt-cells: the number of cells to define an interrupt, should be 2.
+  The first cell is the IRQ number, the second cell is used to specify
+  one of the supported IRQ types:
+      IRQ_TYPE_EDGE_RISING = low-to-high edge triggered,
+      IRQ_TYPE_EDGE_FALLING = high-to-low edge triggered,
+      IRQ_TYPE_LEVEL_HIGH = active high level-sensitive,
+      IRQ_TYPE_LEVEL_LOW = active low level-sensitive.
+  Reset value is IRQ_TYPE_LEVEL_LOW.
+
+Optional properties:
+- interrupt-parent: empty for MIC interrupt controller, link to parent
+  MIC interrupt controller for SIC1 and SIC2
+- interrupts: empty for MIC interrupt controller, cascaded MIC
+  hardware interrupts for SIC1 and SIC2
 
 Examples:
-	/*
-	 * MIC
-	 */
+
+	/* LPC32xx MIC, SIC1 and SIC2 interrupt controllers */
 	mic: interrupt-controller@40008000 {
 		compatible = "nxp,lpc3220-mic";
+		reg = <0x40008000 0x4000>;
 		interrupt-controller;
-		interrupt-parent;
 		#interrupt-cells = <2>;
-		reg = <0x40008000 0xC000>;
 	};
 
-	/*
-	 * ADC
-	 */
+	sic1: interrupt-controller@4000c000 {
+		compatible = "nxp,lpc3220-sic";
+		reg = <0x4000c000 0x4000>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+
+		interrupt-parent = <&mic>;
+		interrupts = <0 IRQ_TYPE_LEVEL_LOW>,
+			     <30 IRQ_TYPE_LEVEL_LOW>;
+	};
+
+	sic2: interrupt-controller@40010000 {
+		compatible = "nxp,lpc3220-sic";
+		reg = <0x40010000 0x4000>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+
+		interrupt-parent = <&mic>;
+		interrupts = <1 IRQ_TYPE_LEVEL_LOW>,
+			     <31 IRQ_TYPE_LEVEL_LOW>;
+	};
+
+	/* ADC */
 	adc@40048000 {
 		compatible = "nxp,lpc3220-adc";
 		reg = <0x40048000 0x1000>;
-		interrupt-parent = <&mic>;
-		interrupts = <39 4>;
+		interrupt-parent = <&sic1>;
+		interrupts = <7 IRQ_TYPE_LEVEL_HIGH>;
 	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu linux-libre-4.7-gnu/Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/interrupt-controller/ti,omap4-wugen-mpu	2016-07-24 15:23:50.000000000 -0400
@@ -4,7 +4,7 @@ All TI OMAP4/5 (and their derivatives) a
 routes interrupts to the GIC, and also serves as a wakeup source. It
 is also referred to as "WUGEN-MPU", hence the name of the binding.
 
-Reguired properties:
+Required properties:
 
 - compatible : should contain at least "ti,omap4-wugen-mpu" or
   "ti,omap5-wugen-mpu"
@@ -20,7 +20,7 @@ Notes:
 - Because this HW ultimately routes interrupts to the GIC, the
   interrupt specifier must be that of the GIC.
 - Only SPIs can use the WUGEN as an interrupt parent. SGIs and PPIs
-  are explicitly forbiden.
+  are explicitly forbidden.
 
 Example:
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/iommu/arm,smmu.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/iommu/arm,smmu.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/iommu/arm,smmu.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/iommu/arm,smmu.txt	2016-07-24 15:23:50.000000000 -0400
@@ -16,6 +16,7 @@ conditions.
                         "arm,mmu-400"
                         "arm,mmu-401"
                         "arm,mmu-500"
+                        "cavium,smmu-v2"
 
                   depending on the particular implementation and/or the
                   version of the architecture implemented.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/leds/common.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/leds/common.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/leds/common.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/leds/common.txt	2016-07-24 15:23:50.000000000 -0400
@@ -37,6 +37,9 @@ Optional properties for child nodes:
                      property is mandatory for the LEDs in the non-flash modes
                      (e.g. torch or indicator).
 
+- panic-indicator : This property specifies that the LED should be used,
+		    if at all possible, as a panic indicator.
+
 Required properties for flash LED child nodes:
 - flash-max-microamp : Maximum flash LED supply current in microamperes.
 - flash-max-timeout-us : Maximum timeout in microseconds after which the flash
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/leds/leds-gpio.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/leds/leds-gpio.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/leds/leds-gpio.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/leds/leds-gpio.txt	2016-07-24 15:23:50.000000000 -0400
@@ -23,6 +23,8 @@ LED sub-node properties:
   property is not present.
 - retain-state-suspended: (optional) The suspend state can be retained.Such
   as charge-led gpio.
+- panic-indicator : (optional)
+  see Documentation/devicetree/bindings/leds/common.txt
 
 Examples:
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/media/i2c/adv7180.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/media/i2c/adv7180.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/media/i2c/adv7180.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/media/i2c/adv7180.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,29 @@
+* Analog Devices ADV7180 analog video decoder family
+
+The adv7180 family devices are used to capture analog video to different
+digital interfaces like MIPI CSI-2 or parallel video.
+
+Required Properties :
+- compatible : value must be one of
+		"adi,adv7180"
+		"adi,adv7182"
+		"adi,adv7280"
+		"adi,adv7280-m"
+		"adi,adv7281"
+		"adi,adv7281-m"
+		"adi,adv7281-ma"
+		"adi,adv7282"
+		"adi,adv7282-m"
+
+Example:
+
+	i2c0@1c22000 {
+		...
+		...
+		adv7180@21 {
+			compatible = "adi,adv7180";
+			reg = <0x21>;
+		};
+		...
+	};
+
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/media/rcar_vin.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/media/rcar_vin.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/media/rcar_vin.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/media/rcar_vin.txt	2016-07-24 15:23:50.000000000 -0400
@@ -5,14 +5,22 @@ The rcar_vin device provides video input
 family of devices. The current blocks are always slaves and suppot one input
 channel which can be either RGB, YUYV or BT656.
 
- - compatible: Must be one of the following
+ - compatible: Must be one or more of the following
    - "renesas,vin-r8a7795" for the R8A7795 device
    - "renesas,vin-r8a7794" for the R8A7794 device
    - "renesas,vin-r8a7793" for the R8A7793 device
+   - "renesas,vin-r8a7792" for the R8A7792 device
    - "renesas,vin-r8a7791" for the R8A7791 device
    - "renesas,vin-r8a7790" for the R8A7790 device
    - "renesas,vin-r8a7779" for the R8A7779 device
    - "renesas,vin-r8a7778" for the R8A7778 device
+   - "renesas,rcar-gen2-vin" for a generic R-Car Gen2 compatible device.
+   - "renesas,rcar-gen3-vin" for a generic R-Car Gen3 compatible device.
+
+   When compatible with the generic version nodes must list the
+   SoC-specific version corresponding to the platform first
+   followed by the generic version.
+
  - reg: the register base and size for the device registers
  - interrupts: the interrupt for the device
  - clocks: Reference to the parent clock
@@ -37,7 +45,7 @@ Device node example
 	};
 
         vin0: vin@0xe6ef0000 {
-                compatible = "renesas,vin-r8a7790";
+                compatible = "renesas,vin-r8a7790", "renesas,rcar-gen2-vin";
                 clocks = <&mstp8_clks R8A7790_CLK_VIN0>;
                 reg = <0 0xe6ef0000 0 0x1000>;
                 interrupts = <0 188 IRQ_TYPE_LEVEL_HIGH>;
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/media/xilinx/video.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/media/xilinx/video.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/media/xilinx/video.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/media/xilinx/video.txt	2016-07-24 15:23:50.000000000 -0400
@@ -20,7 +20,7 @@ The following properties are common to a
 - xlnx,video-format: This property represents a video format transmitted on an
   AXI bus between video IP cores, using its VF code as defined in "AXI4-Stream
   Video IP and System Design Guide" [UG934]. How the format relates to the IP
-  core is decribed in the IP core bindings documentation.
+  core is described in the IP core bindings documentation.
 
 - xlnx,video-width: This property qualifies the video format with the sample
   width expressed as a number of bits per pixel component. All components must
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/memory-controllers/exynos-srom.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/memory-controllers/exynos-srom.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/memory-controllers/exynos-srom.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/memory-controllers/exynos-srom.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,79 @@
+SAMSUNG Exynos SoCs SROM Controller driver.
+
+Required properties:
+- compatible : Should contain "samsung,exynos4210-srom".
+
+- reg: offset and length of the register set
+
+Optional properties:
+The SROM controller can be used to attach external peripherals. In this case
+extra properties, describing the bus behind it, should be specified as below:
+
+- #address-cells: Must be set to 2 to allow device address translation.
+		  Address is specified as (bank#, offset).
+
+- #size-cells: Must be set to 1 to allow device size passing
+
+- ranges: Must be set up to reflect the memory layout with four integer values
+	  per bank:
+		<bank-number> 0 <parent address of bank> <size>
+
+Sub-nodes:
+The actual device nodes should be added as subnodes to the SROMc node. These
+subnodes, in addition to regular device specification, should contain the following
+properties, describing configuration of the relevant SROM bank:
+
+Required properties:
+- reg: bank number, base address (relative to start of the bank) and size of
+       the memory mapped for the device. Note that base address will be
+       typically 0 as this is the start of the bank.
+
+- samsung,srom-timing : array of 6 integers, specifying bank timings in the
+                        following order: Tacp, Tcah, Tcoh, Tacc, Tcos, Tacs.
+                        Each value is specified in cycles and has the following
+                        meaning and valid range:
+                        Tacp : Page mode access cycle at Page mode (0 - 15)
+                        Tcah : Address holding time after CSn (0 - 15)
+                        Tcoh : Chip selection hold on OEn (0 - 15)
+                        Tacc : Access cycle (0 - 31, the actual time is N + 1)
+                        Tcos : Chip selection set-up before OEn (0 - 15)
+                        Tacs : Address set-up before CSn (0 - 15)
+
+Optional properties:
+- reg-io-width : data width in bytes (1 or 2). If omitted, default of 1 is used.
+
+- samsung,srom-page-mode : if page mode is set, 4 data page mode will be configured,
+			   else normal (1 data) page mode will be set.
+
+Example: basic definition, no banks are configured
+	memory-controller@12570000 {
+		compatible = "samsung,exynos4210-srom";
+		reg = <0x12570000 0x14>;
+	};
+
+Example: SROMc with SMSC911x ethernet chip on bank 3
+	memory-controller@12570000 {
+		#address-cells = <2>;
+		#size-cells = <1>;
+		ranges = <0 0 0x04000000 0x20000   // Bank0
+			  1 0 0x05000000 0x20000   // Bank1
+			  2 0 0x06000000 0x20000   // Bank2
+			  3 0 0x07000000 0x20000>; // Bank3
+
+		compatible = "samsung,exynos4210-srom";
+		reg = <0x12570000 0x14>;
+
+		ethernet@3,0 {
+			compatible = "smsc,lan9115";
+			reg = <3 0 0x10000>;	   // Bank 3, offset = 0
+			phy-mode = "mii";
+			interrupt-parent = <&gpx0>;
+			interrupts = <5 8>;
+			reg-io-width = <2>;
+			smsc,irq-push-pull;
+			smsc,force-internal-phy;
+
+			samsung,srom-page-mode;
+			samsung,srom-timing = <9 12 1 9 1 1>;
+		};
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra124-emc.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra124-emc.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra124-emc.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra124-emc.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,374 @@
+NVIDIA Tegra124 SoC EMC (external memory controller)
+====================================================
+
+Required properties :
+- compatible : Should be "nvidia,tegra124-emc".
+- reg : physical base address and length of the controller's registers.
+- nvidia,memory-controller : phandle of the MC driver.
+
+The node should contain a "emc-timings" subnode for each supported RAM type
+(see field RAM_CODE in register PMC_STRAPPING_OPT_A), with its unit address
+being its RAM_CODE.
+
+Required properties for "emc-timings" nodes :
+- nvidia,ram-code : Should contain the value of RAM_CODE this timing set is
+used for.
+
+Each "emc-timings" node should contain a "timing" subnode for every supported
+EMC clock rate. The "timing" subnodes should have the clock rate in Hz as
+their unit address.
+
+Required properties for "timing" nodes :
+- clock-frequency : Should contain the memory clock rate in Hz.
+- The following properties contain EMC timing characterization values
+(specified in the board documentation) :
+  - nvidia,emc-auto-cal-config : EMC_AUTO_CAL_CONFIG
+  - nvidia,emc-auto-cal-config2 : EMC_AUTO_CAL_CONFIG2
+  - nvidia,emc-auto-cal-config3 : EMC_AUTO_CAL_CONFIG3
+  - nvidia,emc-auto-cal-interval : EMC_AUTO_CAL_INTERVAL
+  - nvidia,emc-bgbias-ctl0 : EMC_BGBIAS_CTL0
+  - nvidia,emc-cfg : EMC_CFG
+  - nvidia,emc-cfg-2 : EMC_CFG_2
+  - nvidia,emc-ctt-term-ctrl : EMC_CTT_TERM_CTRL
+  - nvidia,emc-mode-1 : Mode Register 1
+  - nvidia,emc-mode-2 : Mode Register 2
+  - nvidia,emc-mode-4 : Mode Register 4
+  - nvidia,emc-mode-reset : Mode Register 0
+  - nvidia,emc-mrs-wait-cnt : EMC_MRS_WAIT_CNT
+  - nvidia,emc-sel-dpd-ctrl : EMC_SEL_DPD_CTRL
+  - nvidia,emc-xm2dqspadctrl2 : EMC_XM2DQSPADCTRL2
+  - nvidia,emc-zcal-cnt-long : EMC_ZCAL_WAIT_CNT after clock change
+  - nvidia,emc-zcal-interval : EMC_ZCAL_INTERVAL
+- nvidia,emc-configuration : EMC timing characterization data. These are the
+registers (see section "15.6.2 EMC Registers" in the TRM) whose values need to
+be specified, according to the board documentation:
+
+	EMC_RC
+	EMC_RFC
+	EMC_RFC_SLR
+	EMC_RAS
+	EMC_RP
+	EMC_R2W
+	EMC_W2R
+	EMC_R2P
+	EMC_W2P
+	EMC_RD_RCD
+	EMC_WR_RCD
+	EMC_RRD
+	EMC_REXT
+	EMC_WEXT
+	EMC_WDV
+	EMC_WDV_MASK
+	EMC_QUSE
+	EMC_QUSE_WIDTH
+	EMC_IBDLY
+	EMC_EINPUT
+	EMC_EINPUT_DURATION
+	EMC_PUTERM_EXTRA
+	EMC_PUTERM_WIDTH
+	EMC_PUTERM_ADJ
+	EMC_CDB_CNTL_1
+	EMC_CDB_CNTL_2
+	EMC_CDB_CNTL_3
+	EMC_QRST
+	EMC_QSAFE
+	EMC_RDV
+	EMC_RDV_MASK
+	EMC_REFRESH
+	EMC_BURST_REFRESH_NUM
+	EMC_PRE_REFRESH_REQ_CNT
+	EMC_PDEX2WR
+	EMC_PDEX2RD
+	EMC_PCHG2PDEN
+	EMC_ACT2PDEN
+	EMC_AR2PDEN
+	EMC_RW2PDEN
+	EMC_TXSR
+	EMC_TXSRDLL
+	EMC_TCKE
+	EMC_TCKESR
+	EMC_TPD
+	EMC_TFAW
+	EMC_TRPAB
+	EMC_TCLKSTABLE
+	EMC_TCLKSTOP
+	EMC_TREFBW
+	EMC_FBIO_CFG6
+	EMC_ODT_WRITE
+	EMC_ODT_READ
+	EMC_FBIO_CFG5
+	EMC_CFG_DIG_DLL
+	EMC_CFG_DIG_DLL_PERIOD
+	EMC_DLL_XFORM_DQS0
+	EMC_DLL_XFORM_DQS1
+	EMC_DLL_XFORM_DQS2
+	EMC_DLL_XFORM_DQS3
+	EMC_DLL_XFORM_DQS4
+	EMC_DLL_XFORM_DQS5
+	EMC_DLL_XFORM_DQS6
+	EMC_DLL_XFORM_DQS7
+	EMC_DLL_XFORM_DQS8
+	EMC_DLL_XFORM_DQS9
+	EMC_DLL_XFORM_DQS10
+	EMC_DLL_XFORM_DQS11
+	EMC_DLL_XFORM_DQS12
+	EMC_DLL_XFORM_DQS13
+	EMC_DLL_XFORM_DQS14
+	EMC_DLL_XFORM_DQS15
+	EMC_DLL_XFORM_QUSE0
+	EMC_DLL_XFORM_QUSE1
+	EMC_DLL_XFORM_QUSE2
+	EMC_DLL_XFORM_QUSE3
+	EMC_DLL_XFORM_QUSE4
+	EMC_DLL_XFORM_QUSE5
+	EMC_DLL_XFORM_QUSE6
+	EMC_DLL_XFORM_QUSE7
+	EMC_DLL_XFORM_ADDR0
+	EMC_DLL_XFORM_ADDR1
+	EMC_DLL_XFORM_ADDR2
+	EMC_DLL_XFORM_ADDR3
+	EMC_DLL_XFORM_ADDR4
+	EMC_DLL_XFORM_ADDR5
+	EMC_DLL_XFORM_QUSE8
+	EMC_DLL_XFORM_QUSE9
+	EMC_DLL_XFORM_QUSE10
+	EMC_DLL_XFORM_QUSE11
+	EMC_DLL_XFORM_QUSE12
+	EMC_DLL_XFORM_QUSE13
+	EMC_DLL_XFORM_QUSE14
+	EMC_DLL_XFORM_QUSE15
+	EMC_DLI_TRIM_TXDQS0
+	EMC_DLI_TRIM_TXDQS1
+	EMC_DLI_TRIM_TXDQS2
+	EMC_DLI_TRIM_TXDQS3
+	EMC_DLI_TRIM_TXDQS4
+	EMC_DLI_TRIM_TXDQS5
+	EMC_DLI_TRIM_TXDQS6
+	EMC_DLI_TRIM_TXDQS7
+	EMC_DLI_TRIM_TXDQS8
+	EMC_DLI_TRIM_TXDQS9
+	EMC_DLI_TRIM_TXDQS10
+	EMC_DLI_TRIM_TXDQS11
+	EMC_DLI_TRIM_TXDQS12
+	EMC_DLI_TRIM_TXDQS13
+	EMC_DLI_TRIM_TXDQS14
+	EMC_DLI_TRIM_TXDQS15
+	EMC_DLL_XFORM_DQ0
+	EMC_DLL_XFORM_DQ1
+	EMC_DLL_XFORM_DQ2
+	EMC_DLL_XFORM_DQ3
+	EMC_DLL_XFORM_DQ4
+	EMC_DLL_XFORM_DQ5
+	EMC_DLL_XFORM_DQ6
+	EMC_DLL_XFORM_DQ7
+	EMC_XM2CMDPADCTRL
+	EMC_XM2CMDPADCTRL4
+	EMC_XM2CMDPADCTRL5
+	EMC_XM2DQPADCTRL2
+	EMC_XM2DQPADCTRL3
+	EMC_XM2CLKPADCTRL
+	EMC_XM2CLKPADCTRL2
+	EMC_XM2COMPPADCTRL
+	EMC_XM2VTTGENPADCTRL
+	EMC_XM2VTTGENPADCTRL2
+	EMC_XM2VTTGENPADCTRL3
+	EMC_XM2DQSPADCTRL3
+	EMC_XM2DQSPADCTRL4
+	EMC_XM2DQSPADCTRL5
+	EMC_XM2DQSPADCTRL6
+	EMC_DSR_VTTGEN_DRV
+	EMC_TXDSRVTTGEN
+	EMC_FBIO_SPARE
+	EMC_ZCAL_WAIT_CNT
+	EMC_MRS_WAIT_CNT2
+	EMC_CTT
+	EMC_CTT_DURATION
+	EMC_CFG_PIPE
+	EMC_DYN_SELF_REF_CONTROL
+	EMC_QPOP
+
+Example SoC include file:
+
+/ {
+	emc@7001b000 {
+		compatible = "nvidia,tegra124-emc";
+		reg = <0x0 0x7001b000 0x0 0x1000>;
+
+		nvidia,memory-controller = <&mc>;
+	};
+};
+
+Example board file:
+
+/ {
+	emc@7001b000 {
+		emc-timings-3 {
+			nvidia,ram-code = <3>;
+
+			timing-12750000 {
+				clock-frequency = <12750000>;
+
+				nvidia,emc-zcal-cnt-long = <0x00000042>;
+				nvidia,emc-auto-cal-interval = <0x001fffff>;
+				nvidia,emc-ctt-term-ctrl = <0x00000802>;
+				nvidia,emc-cfg = <0x73240000>;
+				nvidia,emc-cfg-2 = <0x000008c5>;
+				nvidia,emc-sel-dpd-ctrl = <0x00040128>;
+				nvidia,emc-bgbias-ctl0 = <0x00000008>;
+				nvidia,emc-auto-cal-config = <0xa1430000>;
+				nvidia,emc-auto-cal-config2 = <0x00000000>;
+				nvidia,emc-auto-cal-config3 = <0x00000000>;
+				nvidia,emc-mode-reset = <0x80001221>;
+				nvidia,emc-mode-1 = <0x80100003>;
+				nvidia,emc-mode-2 = <0x80200008>;
+				nvidia,emc-mode-4 = <0x00000000>;
+
+				nvidia,emc-configuration = <
+					0x00000000 /* EMC_RC */
+					0x00000003 /* EMC_RFC */
+					0x00000000 /* EMC_RFC_SLR */
+					0x00000000 /* EMC_RAS */
+					0x00000000 /* EMC_RP */
+					0x00000004 /* EMC_R2W */
+					0x0000000a /* EMC_W2R */
+					0x00000003 /* EMC_R2P */
+					0x0000000b /* EMC_W2P */
+					0x00000000 /* EMC_RD_RCD */
+					0x00000000 /* EMC_WR_RCD */
+					0x00000003 /* EMC_RRD */
+					0x00000003 /* EMC_REXT */
+					0x00000000 /* EMC_WEXT */
+					0x00000006 /* EMC_WDV */
+					0x00000006 /* EMC_WDV_MASK */
+					0x00000006 /* EMC_QUSE */
+					0x00000002 /* EMC_QUSE_WIDTH */
+					0x00000000 /* EMC_IBDLY */
+					0x00000005 /* EMC_EINPUT */
+					0x00000005 /* EMC_EINPUT_DURATION */
+					0x00010000 /* EMC_PUTERM_EXTRA */
+					0x00000003 /* EMC_PUTERM_WIDTH */
+					0x00000000 /* EMC_PUTERM_ADJ */
+					0x00000000 /* EMC_CDB_CNTL_1 */
+					0x00000000 /* EMC_CDB_CNTL_2 */
+					0x00000000 /* EMC_CDB_CNTL_3 */
+					0x00000004 /* EMC_QRST */
+					0x0000000c /* EMC_QSAFE */
+					0x0000000d /* EMC_RDV */
+					0x0000000f /* EMC_RDV_MASK */
+					0x00000060 /* EMC_REFRESH */
+					0x00000000 /* EMC_BURST_REFRESH_NUM */
+					0x00000018 /* EMC_PRE_REFRESH_REQ_CNT */
+					0x00000002 /* EMC_PDEX2WR */
+					0x00000002 /* EMC_PDEX2RD */
+					0x00000001 /* EMC_PCHG2PDEN */
+					0x00000000 /* EMC_ACT2PDEN */
+					0x00000007 /* EMC_AR2PDEN */
+					0x0000000f /* EMC_RW2PDEN */
+					0x00000005 /* EMC_TXSR */
+					0x00000005 /* EMC_TXSRDLL */
+					0x00000004 /* EMC_TCKE */
+					0x00000005 /* EMC_TCKESR */
+					0x00000004 /* EMC_TPD */
+					0x00000000 /* EMC_TFAW */
+					0x00000000 /* EMC_TRPAB */
+					0x00000005 /* EMC_TCLKSTABLE */
+					0x00000005 /* EMC_TCLKSTOP */
+					0x00000064 /* EMC_TREFBW */
+					0x00000000 /* EMC_FBIO_CFG6 */
+					0x00000000 /* EMC_ODT_WRITE */
+					0x00000000 /* EMC_ODT_READ */
+					0x106aa298 /* EMC_FBIO_CFG5 */
+					0x002c00a0 /* EMC_CFG_DIG_DLL */
+					0x00008000 /* EMC_CFG_DIG_DLL_PERIOD */
+					0x00064000 /* EMC_DLL_XFORM_DQS0 */
+					0x00064000 /* EMC_DLL_XFORM_DQS1 */
+					0x00064000 /* EMC_DLL_XFORM_DQS2 */
+					0x00064000 /* EMC_DLL_XFORM_DQS3 */
+					0x00064000 /* EMC_DLL_XFORM_DQS4 */
+					0x00064000 /* EMC_DLL_XFORM_DQS5 */
+					0x00064000 /* EMC_DLL_XFORM_DQS6 */
+					0x00064000 /* EMC_DLL_XFORM_DQS7 */
+					0x00064000 /* EMC_DLL_XFORM_DQS8 */
+					0x00064000 /* EMC_DLL_XFORM_DQS9 */
+					0x00064000 /* EMC_DLL_XFORM_DQS10 */
+					0x00064000 /* EMC_DLL_XFORM_DQS11 */
+					0x00064000 /* EMC_DLL_XFORM_DQS12 */
+					0x00064000 /* EMC_DLL_XFORM_DQS13 */
+					0x00064000 /* EMC_DLL_XFORM_DQS14 */
+					0x00064000 /* EMC_DLL_XFORM_DQS15 */
+					0x00000000 /* EMC_DLL_XFORM_QUSE0 */
+					0x00000000 /* EMC_DLL_XFORM_QUSE1 */
+					0x00000000 /* EMC_DLL_XFORM_QUSE2 */
+					0x00000000 /* EMC_DLL_XFORM_QUSE3 */
+					0x00000000 /* EMC_DLL_XFORM_QUSE4 */
+					0x00000000 /* EMC_DLL_XFORM_QUSE5 */
+					0x00000000 /* EMC_DLL_XFORM_QUSE6 */
+					0x00000000 /* EMC_DLL_XFORM_QUSE7 */
+					0x00000000 /* EMC_DLL_XFORM_ADDR0 */
+					0x00000000 /* EMC_DLL_XFORM_ADDR1 */
+					0x00000000 /* EMC_DLL_XFORM_ADDR2 */
+					0x00000000 /* EMC_DLL_XFORM_ADDR3 */
+					0x00000000 /* EMC_DLL_XFORM_ADDR4 */
+					0x00000000 /* EMC_DLL_XFORM_ADDR5 */
+					0x00000000 /* EMC_DLL_XFORM_QUSE8 */
+					0x00000000 /* EMC_DLL_XFORM_QUSE9 */
+					0x00000000 /* EMC_DLL_XFORM_QUSE10 */
+					0x00000000 /* EMC_DLL_XFORM_QUSE11 */
+					0x00000000 /* EMC_DLL_XFORM_QUSE12 */
+					0x00000000 /* EMC_DLL_XFORM_QUSE13 */
+					0x00000000 /* EMC_DLL_XFORM_QUSE14 */
+					0x00000000 /* EMC_DLL_XFORM_QUSE15 */
+					0x00000000 /* EMC_DLI_TRIM_TXDQS0 */
+					0x00000000 /* EMC_DLI_TRIM_TXDQS1 */
+					0x00000000 /* EMC_DLI_TRIM_TXDQS2 */
+					0x00000000 /* EMC_DLI_TRIM_TXDQS3 */
+					0x00000000 /* EMC_DLI_TRIM_TXDQS4 */
+					0x00000000 /* EMC_DLI_TRIM_TXDQS5 */
+					0x00000000 /* EMC_DLI_TRIM_TXDQS6 */
+					0x00000000 /* EMC_DLI_TRIM_TXDQS7 */
+					0x00000000 /* EMC_DLI_TRIM_TXDQS8 */
+					0x00000000 /* EMC_DLI_TRIM_TXDQS9 */
+					0x00000000 /* EMC_DLI_TRIM_TXDQS10 */
+					0x00000000 /* EMC_DLI_TRIM_TXDQS11 */
+					0x00000000 /* EMC_DLI_TRIM_TXDQS12 */
+					0x00000000 /* EMC_DLI_TRIM_TXDQS13 */
+					0x00000000 /* EMC_DLI_TRIM_TXDQS14 */
+					0x00000000 /* EMC_DLI_TRIM_TXDQS15 */
+					0x000fc000 /* EMC_DLL_XFORM_DQ0 */
+					0x000fc000 /* EMC_DLL_XFORM_DQ1 */
+					0x000fc000 /* EMC_DLL_XFORM_DQ2 */
+					0x000fc000 /* EMC_DLL_XFORM_DQ3 */
+					0x0000fc00 /* EMC_DLL_XFORM_DQ4 */
+					0x0000fc00 /* EMC_DLL_XFORM_DQ5 */
+					0x0000fc00 /* EMC_DLL_XFORM_DQ6 */
+					0x0000fc00 /* EMC_DLL_XFORM_DQ7 */
+					0x10000280 /* EMC_XM2CMDPADCTRL */
+					0x00000000 /* EMC_XM2CMDPADCTRL4 */
+					0x00111111 /* EMC_XM2CMDPADCTRL5 */
+					0x00000000 /* EMC_XM2DQPADCTRL2 */
+					0x00000000 /* EMC_XM2DQPADCTRL3 */
+					0x77ffc081 /* EMC_XM2CLKPADCTRL */
+					0x00000e0e /* EMC_XM2CLKPADCTRL2 */
+					0x81f1f108 /* EMC_XM2COMPPADCTRL */
+					0x07070004 /* EMC_XM2VTTGENPADCTRL */
+					0x0000003f /* EMC_XM2VTTGENPADCTRL2 */
+					0x016eeeee /* EMC_XM2VTTGENPADCTRL3 */
+					0x51451400 /* EMC_XM2DQSPADCTRL3 */
+					0x00514514 /* EMC_XM2DQSPADCTRL4 */
+					0x00514514 /* EMC_XM2DQSPADCTRL5 */
+					0x51451400 /* EMC_XM2DQSPADCTRL6 */
+					0x0000003f /* EMC_DSR_VTTGEN_DRV */
+					0x00000007 /* EMC_TXDSRVTTGEN */
+					0x00000000 /* EMC_FBIO_SPARE */
+					0x00000042 /* EMC_ZCAL_WAIT_CNT */
+					0x000e000e /* EMC_MRS_WAIT_CNT2 */
+					0x00000000 /* EMC_CTT */
+					0x00000003 /* EMC_CTT_DURATION */
+					0x0000f2f3 /* EMC_CFG_PIPE */
+					0x800001c5 /* EMC_DYN_SELF_REF_CONTROL */
+					0x0000000a /* EMC_QPOP */
+				>;
+			};
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra30-mc.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra30-mc.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra30-mc.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra30-mc.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,116 @@
+NVIDIA Tegra Memory Controller device tree bindings
+===================================================
+
+memory-controller node
+----------------------
+
+Required properties:
+- compatible: Should be "nvidia,tegra<chip>-mc"
+- reg: Physical base address and length of the controller's registers.
+- clocks: Must contain an entry for each entry in clock-names.
+  See ../clocks/clock-bindings.txt for details.
+- clock-names: Must include the following entries:
+  - mc: the module's clock input
+- interrupts: The interrupt outputs from the controller.
+- #iommu-cells: Should be 1. The single cell of the IOMMU specifier defines
+  the SWGROUP of the master.
+
+This device implements an IOMMU that complies with the generic IOMMU binding.
+See ../iommu/iommu.txt for details.
+
+emc-timings subnode
+-------------------
+
+The node should contain a "emc-timings" subnode for each supported RAM type (see field RAM_CODE in
+register PMC_STRAPPING_OPT_A).
+
+Required properties for "emc-timings" nodes :
+- nvidia,ram-code : Should contain the value of RAM_CODE this timing set is used for.
+
+timing subnode
+--------------
+
+Each "emc-timings" node should contain a subnode for every supported EMC clock rate.
+
+Required properties for timing nodes :
+- clock-frequency : Should contain the memory clock rate in Hz.
+- nvidia,emem-configuration : Values to be written to the EMEM register block. For the Tegra124 SoC
+(see section "15.6.1 MC Registers" in the TRM), these are the registers whose values need to be
+specified, according to the board documentation:
+
+	MC_EMEM_ARB_CFG
+	MC_EMEM_ARB_OUTSTANDING_REQ
+	MC_EMEM_ARB_TIMING_RCD
+	MC_EMEM_ARB_TIMING_RP
+	MC_EMEM_ARB_TIMING_RC
+	MC_EMEM_ARB_TIMING_RAS
+	MC_EMEM_ARB_TIMING_FAW
+	MC_EMEM_ARB_TIMING_RRD
+	MC_EMEM_ARB_TIMING_RAP2PRE
+	MC_EMEM_ARB_TIMING_WAP2PRE
+	MC_EMEM_ARB_TIMING_R2R
+	MC_EMEM_ARB_TIMING_W2W
+	MC_EMEM_ARB_TIMING_R2W
+	MC_EMEM_ARB_TIMING_W2R
+	MC_EMEM_ARB_DA_TURNS
+	MC_EMEM_ARB_DA_COVERS
+	MC_EMEM_ARB_MISC0
+	MC_EMEM_ARB_MISC1
+	MC_EMEM_ARB_RING1_THROTTLE
+
+Example SoC include file:
+
+/ {
+	mc: memory-controller@70019000 {
+		compatible = "nvidia,tegra124-mc";
+		reg = <0x0 0x70019000 0x0 0x1000>;
+		clocks = <&tegra_car TEGRA124_CLK_MC>;
+		clock-names = "mc";
+
+		interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
+
+		#iommu-cells = <1>;
+	};
+
+	sdhci@700b0000 {
+		compatible = "nvidia,tegra124-sdhci";
+		...
+		iommus = <&mc TEGRA_SWGROUP_SDMMC1A>;
+	};
+};
+
+Example board file:
+
+/ {
+	memory-controller@70019000 {
+		emc-timings-3 {
+			nvidia,ram-code = <3>;
+
+			timing-12750000 {
+				clock-frequency = <12750000>;
+
+				nvidia,emem-configuration = <
+					0x40040001 /* MC_EMEM_ARB_CFG */
+					0x8000000a /* MC_EMEM_ARB_OUTSTANDING_REQ */
+					0x00000001 /* MC_EMEM_ARB_TIMING_RCD */
+					0x00000001 /* MC_EMEM_ARB_TIMING_RP */
+					0x00000002 /* MC_EMEM_ARB_TIMING_RC */
+					0x00000000 /* MC_EMEM_ARB_TIMING_RAS */
+					0x00000002 /* MC_EMEM_ARB_TIMING_FAW */
+					0x00000001 /* MC_EMEM_ARB_TIMING_RRD */
+					0x00000002 /* MC_EMEM_ARB_TIMING_RAP2PRE */
+					0x00000008 /* MC_EMEM_ARB_TIMING_WAP2PRE */
+					0x00000003 /* MC_EMEM_ARB_TIMING_R2R */
+					0x00000002 /* MC_EMEM_ARB_TIMING_W2W */
+					0x00000003 /* MC_EMEM_ARB_TIMING_R2W */
+					0x00000006 /* MC_EMEM_ARB_TIMING_W2R */
+					0x06030203 /* MC_EMEM_ARB_DA_TURNS */
+					0x000a0402 /* MC_EMEM_ARB_DA_COVERS */
+					0x77e30303 /* MC_EMEM_ARB_MISC0 */
+					0x70000f03 /* MC_EMEM_ARB_MISC1 */
+					0x001f0000 /* MC_EMEM_ARB_RING1_THROTTLE */
+				>;
+			};
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra-mc.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra-mc.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra-mc.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra-mc.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,116 +0,0 @@
-NVIDIA Tegra Memory Controller device tree bindings
-===================================================
-
-memory-controller node
-----------------------
-
-Required properties:
-- compatible: Should be "nvidia,tegra<chip>-mc"
-- reg: Physical base address and length of the controller's registers.
-- clocks: Must contain an entry for each entry in clock-names.
-  See ../clocks/clock-bindings.txt for details.
-- clock-names: Must include the following entries:
-  - mc: the module's clock input
-- interrupts: The interrupt outputs from the controller.
-- #iommu-cells: Should be 1. The single cell of the IOMMU specifier defines
-  the SWGROUP of the master.
-
-This device implements an IOMMU that complies with the generic IOMMU binding.
-See ../iommu/iommu.txt for details.
-
-emc-timings subnode
--------------------
-
-The node should contain a "emc-timings" subnode for each supported RAM type (see field RAM_CODE in
-register PMC_STRAPPING_OPT_A).
-
-Required properties for "emc-timings" nodes :
-- nvidia,ram-code : Should contain the value of RAM_CODE this timing set is used for.
-
-timing subnode
---------------
-
-Each "emc-timings" node should contain a subnode for every supported EMC clock rate.
-
-Required properties for timing nodes :
-- clock-frequency : Should contain the memory clock rate in Hz.
-- nvidia,emem-configuration : Values to be written to the EMEM register block. For the Tegra124 SoC
-(see section "15.6.1 MC Registers" in the TRM), these are the registers whose values need to be
-specified, according to the board documentation:
-
-	MC_EMEM_ARB_CFG
-	MC_EMEM_ARB_OUTSTANDING_REQ
-	MC_EMEM_ARB_TIMING_RCD
-	MC_EMEM_ARB_TIMING_RP
-	MC_EMEM_ARB_TIMING_RC
-	MC_EMEM_ARB_TIMING_RAS
-	MC_EMEM_ARB_TIMING_FAW
-	MC_EMEM_ARB_TIMING_RRD
-	MC_EMEM_ARB_TIMING_RAP2PRE
-	MC_EMEM_ARB_TIMING_WAP2PRE
-	MC_EMEM_ARB_TIMING_R2R
-	MC_EMEM_ARB_TIMING_W2W
-	MC_EMEM_ARB_TIMING_R2W
-	MC_EMEM_ARB_TIMING_W2R
-	MC_EMEM_ARB_DA_TURNS
-	MC_EMEM_ARB_DA_COVERS
-	MC_EMEM_ARB_MISC0
-	MC_EMEM_ARB_MISC1
-	MC_EMEM_ARB_RING1_THROTTLE
-
-Example SoC include file:
-
-/ {
-	mc: memory-controller@0,70019000 {
-		compatible = "nvidia,tegra124-mc";
-		reg = <0x0 0x70019000 0x0 0x1000>;
-		clocks = <&tegra_car TEGRA124_CLK_MC>;
-		clock-names = "mc";
-
-		interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
-
-		#iommu-cells = <1>;
-	};
-
-	sdhci@0,700b0000 {
-		compatible = "nvidia,tegra124-sdhci";
-		...
-		iommus = <&mc TEGRA_SWGROUP_SDMMC1A>;
-	};
-};
-
-Example board file:
-
-/ {
-	memory-controller@0,70019000 {
-		emc-timings-3 {
-			nvidia,ram-code = <3>;
-
-			timing-12750000 {
-				clock-frequency = <12750000>;
-
-				nvidia,emem-configuration = <
-					0x40040001 /* MC_EMEM_ARB_CFG */
-					0x8000000a /* MC_EMEM_ARB_OUTSTANDING_REQ */
-					0x00000001 /* MC_EMEM_ARB_TIMING_RCD */
-					0x00000001 /* MC_EMEM_ARB_TIMING_RP */
-					0x00000002 /* MC_EMEM_ARB_TIMING_RC */
-					0x00000000 /* MC_EMEM_ARB_TIMING_RAS */
-					0x00000002 /* MC_EMEM_ARB_TIMING_FAW */
-					0x00000001 /* MC_EMEM_ARB_TIMING_RRD */
-					0x00000002 /* MC_EMEM_ARB_TIMING_RAP2PRE */
-					0x00000008 /* MC_EMEM_ARB_TIMING_WAP2PRE */
-					0x00000003 /* MC_EMEM_ARB_TIMING_R2R */
-					0x00000002 /* MC_EMEM_ARB_TIMING_W2W */
-					0x00000003 /* MC_EMEM_ARB_TIMING_R2W */
-					0x00000006 /* MC_EMEM_ARB_TIMING_W2R */
-					0x06030203 /* MC_EMEM_ARB_DA_TURNS */
-					0x000a0402 /* MC_EMEM_ARB_DA_COVERS */
-					0x77e30303 /* MC_EMEM_ARB_MISC0 */
-					0x70000f03 /* MC_EMEM_ARB_MISC1 */
-					0x001f0000 /* MC_EMEM_ARB_RING1_THROTTLE */
-				>;
-			};
-		};
-	};
-};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/memory-controllers/omap-gpmc.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/memory-controllers/omap-gpmc.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/memory-controllers/omap-gpmc.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/memory-controllers/omap-gpmc.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,152 @@
+Device tree bindings for OMAP general purpose memory controllers (GPMC)
+
+The actual devices are instantiated from the child nodes of a GPMC node.
+
+Required properties:
+
+ - compatible:		Should be set to one of the following:
+
+			ti,omap2420-gpmc (omap2420)
+			ti,omap2430-gpmc (omap2430)
+			ti,omap3430-gpmc (omap3430 & omap3630)
+			ti,omap4430-gpmc (omap4430 & omap4460 & omap543x)
+			ti,am3352-gpmc   (am335x devices)
+
+ - reg:			A resource specifier for the register space
+			(see the example below)
+ - ti,hwmods:		Should be set to "ti,gpmc" until the DT transition is
+			completed.
+ - #address-cells:	Must be set to 2 to allow memory address translation
+ - #size-cells:		Must be set to 1 to allow CS address passing
+ - gpmc,num-cs:		The maximum number of chip-select lines that controller
+			can support.
+ - gpmc,num-waitpins:	The maximum number of wait pins that controller can
+			support.
+ - ranges:		Must be set up to reflect the memory layout with four
+			integer values for each chip-select line in use:
+
+			   <cs-number> 0 <physical address of mapping> <size>
+
+			Currently, calculated values derived from the contents
+			of the per-CS register GPMC_CONFIG7 (as set up by the
+			bootloader) are used for the physical address decoding.
+			As this will change in the future, filling correct
+			values here is a requirement.
+ - interrupt-controller: The GPMC driver implements and interrupt controller for
+			the NAND events "fifoevent" and "termcount" plus the
+			rising/falling edges on the GPMC_WAIT pins.
+			The interrupt number mapping is as follows
+			0 - NAND_fifoevent
+			1 - NAND_termcount
+			2 - GPMC_WAIT0 pin edge
+			3 - GPMC_WAIT1 pin edge, and so on.
+ - interrupt-cells:	Must be set to 2
+ - gpio-controller:	The GPMC driver implements a GPIO controller for the
+			GPMC WAIT pins that can be used as general purpose inputs.
+			0 maps to GPMC_WAIT0 pin.
+ - gpio-cells:		Must be set to 2
+
+Timing properties for child nodes. All are optional and default to 0.
+
+ - gpmc,sync-clk-ps:	Minimum clock period for synchronous mode, in picoseconds
+
+ Chip-select signal timings (in nanoseconds) corresponding to GPMC_CONFIG2:
+ - gpmc,cs-on-ns:	Assertion time
+ - gpmc,cs-rd-off-ns:	Read deassertion time
+ - gpmc,cs-wr-off-ns:	Write deassertion time
+
+ ADV signal timings (in nanoseconds) corresponding to GPMC_CONFIG3:
+ - gpmc,adv-on-ns:	Assertion time
+ - gpmc,adv-rd-off-ns:	Read deassertion time
+ - gpmc,adv-wr-off-ns:	Write deassertion time
+ - gpmc,adv-aad-mux-on-ns:	Assertion time for AAD
+ - gpmc,adv-aad-mux-rd-off-ns:	Read deassertion time for AAD
+ - gpmc,adv-aad-mux-wr-off-ns:	Write deassertion time for AAD
+
+ WE signals timings (in nanoseconds) corresponding to GPMC_CONFIG4:
+ - gpmc,we-on-ns	Assertion time
+ - gpmc,we-off-ns:	Deassertion time
+
+ OE signals timings (in nanoseconds) corresponding to GPMC_CONFIG4:
+ - gpmc,oe-on-ns:	Assertion time
+ - gpmc,oe-off-ns:	Deassertion time
+ - gpmc,oe-aad-mux-on-ns:	Assertion time for AAD
+ - gpmc,oe-aad-mux-off-ns:	Deassertion time for AAD
+
+ Access time and cycle time timings (in nanoseconds) corresponding to
+ GPMC_CONFIG5:
+ - gpmc,page-burst-access-ns: 	Multiple access word delay
+ - gpmc,access-ns:		Start-cycle to first data valid delay
+ - gpmc,rd-cycle-ns:		Total read cycle time
+ - gpmc,wr-cycle-ns:		Total write cycle time
+ - gpmc,bus-turnaround-ns:	Turn-around time between successive accesses
+ - gpmc,cycle2cycle-delay-ns:	Delay between chip-select pulses
+ - gpmc,clk-activation-ns: 	GPMC clock activation time
+ - gpmc,wait-monitoring-ns:	Start of wait monitoring with regard to valid
+				data
+
+Boolean timing parameters. If property is present parameter enabled and
+disabled if omitted:
+ - gpmc,adv-extra-delay:	ADV signal is delayed by half GPMC clock
+ - gpmc,cs-extra-delay:		CS signal is delayed by half GPMC clock
+ - gpmc,cycle2cycle-diffcsen:	Add "cycle2cycle-delay" between successive
+				accesses to a different CS
+ - gpmc,cycle2cycle-samecsen:	Add "cycle2cycle-delay" between successive
+				accesses to the same CS
+ - gpmc,oe-extra-delay:		OE signal is delayed by half GPMC clock
+ - gpmc,we-extra-delay:		WE signal is delayed by half GPMC clock
+ - gpmc,time-para-granularity:	Multiply all access times by 2
+
+The following are only applicable to OMAP3+ and AM335x:
+ - gpmc,wr-access-ns:		In synchronous write mode, for single or
+				burst accesses, defines the number of
+				GPMC_FCLK cycles from start access time
+				to the GPMC_CLK rising edge used by the
+				memory device for the first data capture.
+ - gpmc,wr-data-mux-bus-ns:	In address-data multiplex mode, specifies
+				the time when the first data is driven on
+				the address-data bus.
+
+GPMC chip-select settings properties for child nodes. All are optional.
+
+- gpmc,burst-length	Page/burst length. Must be 4, 8 or 16.
+- gpmc,burst-wrap	Enables wrap bursting
+- gpmc,burst-read	Enables read page/burst mode
+- gpmc,burst-write	Enables write page/burst mode
+- gpmc,device-width	Total width of device(s) connected to a GPMC
+			chip-select in bytes. The GPMC supports 8-bit
+			and 16-bit devices and so this property must be
+			1 or 2.
+- gpmc,mux-add-data	Address and data multiplexing configuration.
+			Valid values are 1 for address-address-data
+			multiplexing mode and 2 for address-data
+			multiplexing mode.
+- gpmc,sync-read	Enables synchronous read. Defaults to asynchronous
+			is this is not set.
+- gpmc,sync-write	Enables synchronous writes. Defaults to asynchronous
+			is this is not set.
+- gpmc,wait-pin		Wait-pin used by client. Must be less than
+			"gpmc,num-waitpins".
+- gpmc,wait-on-read	Enables wait monitoring on reads.
+- gpmc,wait-on-write	Enables wait monitoring on writes.
+
+Example for an AM33xx board:
+
+	gpmc: gpmc@50000000 {
+		compatible = "ti,am3352-gpmc";
+		ti,hwmods = "gpmc";
+		reg = <0x50000000 0x2000>;
+		interrupts = <100>;
+
+		gpmc,num-cs = <8>;
+		gpmc,num-waitpins = <2>;
+		#address-cells = <2>;
+		#size-cells = <1>;
+		ranges = <0 0 0x08000000 0x10000000>; /* CS0 @addr 0x8000000, size 0x10000000 */
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		/* child nodes go here */
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/memory-controllers/tegra-emc.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/memory-controllers/tegra-emc.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/memory-controllers/tegra-emc.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/memory-controllers/tegra-emc.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,374 +0,0 @@
-NVIDIA Tegra124 SoC EMC (external memory controller)
-====================================================
-
-Required properties :
-- compatible : Should be "nvidia,tegra124-emc".
-- reg : physical base address and length of the controller's registers.
-- nvidia,memory-controller : phandle of the MC driver.
-
-The node should contain a "emc-timings" subnode for each supported RAM type
-(see field RAM_CODE in register PMC_STRAPPING_OPT_A), with its unit address
-being its RAM_CODE.
-
-Required properties for "emc-timings" nodes :
-- nvidia,ram-code : Should contain the value of RAM_CODE this timing set is
-used for.
-
-Each "emc-timings" node should contain a "timing" subnode for every supported
-EMC clock rate. The "timing" subnodes should have the clock rate in Hz as
-their unit address.
-
-Required properties for "timing" nodes :
-- clock-frequency : Should contain the memory clock rate in Hz.
-- The following properties contain EMC timing characterization values
-(specified in the board documentation) :
-  - nvidia,emc-auto-cal-config : EMC_AUTO_CAL_CONFIG
-  - nvidia,emc-auto-cal-config2 : EMC_AUTO_CAL_CONFIG2
-  - nvidia,emc-auto-cal-config3 : EMC_AUTO_CAL_CONFIG3
-  - nvidia,emc-auto-cal-interval : EMC_AUTO_CAL_INTERVAL
-  - nvidia,emc-bgbias-ctl0 : EMC_BGBIAS_CTL0
-  - nvidia,emc-cfg : EMC_CFG
-  - nvidia,emc-cfg-2 : EMC_CFG_2
-  - nvidia,emc-ctt-term-ctrl : EMC_CTT_TERM_CTRL
-  - nvidia,emc-mode-1 : Mode Register 1
-  - nvidia,emc-mode-2 : Mode Register 2
-  - nvidia,emc-mode-4 : Mode Register 4
-  - nvidia,emc-mode-reset : Mode Register 0
-  - nvidia,emc-mrs-wait-cnt : EMC_MRS_WAIT_CNT
-  - nvidia,emc-sel-dpd-ctrl : EMC_SEL_DPD_CTRL
-  - nvidia,emc-xm2dqspadctrl2 : EMC_XM2DQSPADCTRL2
-  - nvidia,emc-zcal-cnt-long : EMC_ZCAL_WAIT_CNT after clock change
-  - nvidia,emc-zcal-interval : EMC_ZCAL_INTERVAL
-- nvidia,emc-configuration : EMC timing characterization data. These are the
-registers (see section "15.6.2 EMC Registers" in the TRM) whose values need to
-be specified, according to the board documentation:
-
-	EMC_RC
-	EMC_RFC
-	EMC_RFC_SLR
-	EMC_RAS
-	EMC_RP
-	EMC_R2W
-	EMC_W2R
-	EMC_R2P
-	EMC_W2P
-	EMC_RD_RCD
-	EMC_WR_RCD
-	EMC_RRD
-	EMC_REXT
-	EMC_WEXT
-	EMC_WDV
-	EMC_WDV_MASK
-	EMC_QUSE
-	EMC_QUSE_WIDTH
-	EMC_IBDLY
-	EMC_EINPUT
-	EMC_EINPUT_DURATION
-	EMC_PUTERM_EXTRA
-	EMC_PUTERM_WIDTH
-	EMC_PUTERM_ADJ
-	EMC_CDB_CNTL_1
-	EMC_CDB_CNTL_2
-	EMC_CDB_CNTL_3
-	EMC_QRST
-	EMC_QSAFE
-	EMC_RDV
-	EMC_RDV_MASK
-	EMC_REFRESH
-	EMC_BURST_REFRESH_NUM
-	EMC_PRE_REFRESH_REQ_CNT
-	EMC_PDEX2WR
-	EMC_PDEX2RD
-	EMC_PCHG2PDEN
-	EMC_ACT2PDEN
-	EMC_AR2PDEN
-	EMC_RW2PDEN
-	EMC_TXSR
-	EMC_TXSRDLL
-	EMC_TCKE
-	EMC_TCKESR
-	EMC_TPD
-	EMC_TFAW
-	EMC_TRPAB
-	EMC_TCLKSTABLE
-	EMC_TCLKSTOP
-	EMC_TREFBW
-	EMC_FBIO_CFG6
-	EMC_ODT_WRITE
-	EMC_ODT_READ
-	EMC_FBIO_CFG5
-	EMC_CFG_DIG_DLL
-	EMC_CFG_DIG_DLL_PERIOD
-	EMC_DLL_XFORM_DQS0
-	EMC_DLL_XFORM_DQS1
-	EMC_DLL_XFORM_DQS2
-	EMC_DLL_XFORM_DQS3
-	EMC_DLL_XFORM_DQS4
-	EMC_DLL_XFORM_DQS5
-	EMC_DLL_XFORM_DQS6
-	EMC_DLL_XFORM_DQS7
-	EMC_DLL_XFORM_DQS8
-	EMC_DLL_XFORM_DQS9
-	EMC_DLL_XFORM_DQS10
-	EMC_DLL_XFORM_DQS11
-	EMC_DLL_XFORM_DQS12
-	EMC_DLL_XFORM_DQS13
-	EMC_DLL_XFORM_DQS14
-	EMC_DLL_XFORM_DQS15
-	EMC_DLL_XFORM_QUSE0
-	EMC_DLL_XFORM_QUSE1
-	EMC_DLL_XFORM_QUSE2
-	EMC_DLL_XFORM_QUSE3
-	EMC_DLL_XFORM_QUSE4
-	EMC_DLL_XFORM_QUSE5
-	EMC_DLL_XFORM_QUSE6
-	EMC_DLL_XFORM_QUSE7
-	EMC_DLL_XFORM_ADDR0
-	EMC_DLL_XFORM_ADDR1
-	EMC_DLL_XFORM_ADDR2
-	EMC_DLL_XFORM_ADDR3
-	EMC_DLL_XFORM_ADDR4
-	EMC_DLL_XFORM_ADDR5
-	EMC_DLL_XFORM_QUSE8
-	EMC_DLL_XFORM_QUSE9
-	EMC_DLL_XFORM_QUSE10
-	EMC_DLL_XFORM_QUSE11
-	EMC_DLL_XFORM_QUSE12
-	EMC_DLL_XFORM_QUSE13
-	EMC_DLL_XFORM_QUSE14
-	EMC_DLL_XFORM_QUSE15
-	EMC_DLI_TRIM_TXDQS0
-	EMC_DLI_TRIM_TXDQS1
-	EMC_DLI_TRIM_TXDQS2
-	EMC_DLI_TRIM_TXDQS3
-	EMC_DLI_TRIM_TXDQS4
-	EMC_DLI_TRIM_TXDQS5
-	EMC_DLI_TRIM_TXDQS6
-	EMC_DLI_TRIM_TXDQS7
-	EMC_DLI_TRIM_TXDQS8
-	EMC_DLI_TRIM_TXDQS9
-	EMC_DLI_TRIM_TXDQS10
-	EMC_DLI_TRIM_TXDQS11
-	EMC_DLI_TRIM_TXDQS12
-	EMC_DLI_TRIM_TXDQS13
-	EMC_DLI_TRIM_TXDQS14
-	EMC_DLI_TRIM_TXDQS15
-	EMC_DLL_XFORM_DQ0
-	EMC_DLL_XFORM_DQ1
-	EMC_DLL_XFORM_DQ2
-	EMC_DLL_XFORM_DQ3
-	EMC_DLL_XFORM_DQ4
-	EMC_DLL_XFORM_DQ5
-	EMC_DLL_XFORM_DQ6
-	EMC_DLL_XFORM_DQ7
-	EMC_XM2CMDPADCTRL
-	EMC_XM2CMDPADCTRL4
-	EMC_XM2CMDPADCTRL5
-	EMC_XM2DQPADCTRL2
-	EMC_XM2DQPADCTRL3
-	EMC_XM2CLKPADCTRL
-	EMC_XM2CLKPADCTRL2
-	EMC_XM2COMPPADCTRL
-	EMC_XM2VTTGENPADCTRL
-	EMC_XM2VTTGENPADCTRL2
-	EMC_XM2VTTGENPADCTRL3
-	EMC_XM2DQSPADCTRL3
-	EMC_XM2DQSPADCTRL4
-	EMC_XM2DQSPADCTRL5
-	EMC_XM2DQSPADCTRL6
-	EMC_DSR_VTTGEN_DRV
-	EMC_TXDSRVTTGEN
-	EMC_FBIO_SPARE
-	EMC_ZCAL_WAIT_CNT
-	EMC_MRS_WAIT_CNT2
-	EMC_CTT
-	EMC_CTT_DURATION
-	EMC_CFG_PIPE
-	EMC_DYN_SELF_REF_CONTROL
-	EMC_QPOP
-
-Example SoC include file:
-
-/ {
-	emc@0,7001b000 {
-		compatible = "nvidia,tegra124-emc";
-		reg = <0x0 0x7001b000 0x0 0x1000>;
-
-		nvidia,memory-controller = <&mc>;
-	};
-};
-
-Example board file:
-
-/ {
-	emc@0,7001b000 {
-		emc-timings-3 {
-			nvidia,ram-code = <3>;
-
-			timing-12750000 {
-				clock-frequency = <12750000>;
-
-				nvidia,emc-zcal-cnt-long = <0x00000042>;
-				nvidia,emc-auto-cal-interval = <0x001fffff>;
-				nvidia,emc-ctt-term-ctrl = <0x00000802>;
-				nvidia,emc-cfg = <0x73240000>;
-				nvidia,emc-cfg-2 = <0x000008c5>;
-				nvidia,emc-sel-dpd-ctrl = <0x00040128>;
-				nvidia,emc-bgbias-ctl0 = <0x00000008>;
-				nvidia,emc-auto-cal-config = <0xa1430000>;
-				nvidia,emc-auto-cal-config2 = <0x00000000>;
-				nvidia,emc-auto-cal-config3 = <0x00000000>;
-				nvidia,emc-mode-reset = <0x80001221>;
-				nvidia,emc-mode-1 = <0x80100003>;
-				nvidia,emc-mode-2 = <0x80200008>;
-				nvidia,emc-mode-4 = <0x00000000>;
-
-				nvidia,emc-configuration = <
-					0x00000000 /* EMC_RC */
-					0x00000003 /* EMC_RFC */
-					0x00000000 /* EMC_RFC_SLR */
-					0x00000000 /* EMC_RAS */
-					0x00000000 /* EMC_RP */
-					0x00000004 /* EMC_R2W */
-					0x0000000a /* EMC_W2R */
-					0x00000003 /* EMC_R2P */
-					0x0000000b /* EMC_W2P */
-					0x00000000 /* EMC_RD_RCD */
-					0x00000000 /* EMC_WR_RCD */
-					0x00000003 /* EMC_RRD */
-					0x00000003 /* EMC_REXT */
-					0x00000000 /* EMC_WEXT */
-					0x00000006 /* EMC_WDV */
-					0x00000006 /* EMC_WDV_MASK */
-					0x00000006 /* EMC_QUSE */
-					0x00000002 /* EMC_QUSE_WIDTH */
-					0x00000000 /* EMC_IBDLY */
-					0x00000005 /* EMC_EINPUT */
-					0x00000005 /* EMC_EINPUT_DURATION */
-					0x00010000 /* EMC_PUTERM_EXTRA */
-					0x00000003 /* EMC_PUTERM_WIDTH */
-					0x00000000 /* EMC_PUTERM_ADJ */
-					0x00000000 /* EMC_CDB_CNTL_1 */
-					0x00000000 /* EMC_CDB_CNTL_2 */
-					0x00000000 /* EMC_CDB_CNTL_3 */
-					0x00000004 /* EMC_QRST */
-					0x0000000c /* EMC_QSAFE */
-					0x0000000d /* EMC_RDV */
-					0x0000000f /* EMC_RDV_MASK */
-					0x00000060 /* EMC_REFRESH */
-					0x00000000 /* EMC_BURST_REFRESH_NUM */
-					0x00000018 /* EMC_PRE_REFRESH_REQ_CNT */
-					0x00000002 /* EMC_PDEX2WR */
-					0x00000002 /* EMC_PDEX2RD */
-					0x00000001 /* EMC_PCHG2PDEN */
-					0x00000000 /* EMC_ACT2PDEN */
-					0x00000007 /* EMC_AR2PDEN */
-					0x0000000f /* EMC_RW2PDEN */
-					0x00000005 /* EMC_TXSR */
-					0x00000005 /* EMC_TXSRDLL */
-					0x00000004 /* EMC_TCKE */
-					0x00000005 /* EMC_TCKESR */
-					0x00000004 /* EMC_TPD */
-					0x00000000 /* EMC_TFAW */
-					0x00000000 /* EMC_TRPAB */
-					0x00000005 /* EMC_TCLKSTABLE */
-					0x00000005 /* EMC_TCLKSTOP */
-					0x00000064 /* EMC_TREFBW */
-					0x00000000 /* EMC_FBIO_CFG6 */
-					0x00000000 /* EMC_ODT_WRITE */
-					0x00000000 /* EMC_ODT_READ */
-					0x106aa298 /* EMC_FBIO_CFG5 */
-					0x002c00a0 /* EMC_CFG_DIG_DLL */
-					0x00008000 /* EMC_CFG_DIG_DLL_PERIOD */
-					0x00064000 /* EMC_DLL_XFORM_DQS0 */
-					0x00064000 /* EMC_DLL_XFORM_DQS1 */
-					0x00064000 /* EMC_DLL_XFORM_DQS2 */
-					0x00064000 /* EMC_DLL_XFORM_DQS3 */
-					0x00064000 /* EMC_DLL_XFORM_DQS4 */
-					0x00064000 /* EMC_DLL_XFORM_DQS5 */
-					0x00064000 /* EMC_DLL_XFORM_DQS6 */
-					0x00064000 /* EMC_DLL_XFORM_DQS7 */
-					0x00064000 /* EMC_DLL_XFORM_DQS8 */
-					0x00064000 /* EMC_DLL_XFORM_DQS9 */
-					0x00064000 /* EMC_DLL_XFORM_DQS10 */
-					0x00064000 /* EMC_DLL_XFORM_DQS11 */
-					0x00064000 /* EMC_DLL_XFORM_DQS12 */
-					0x00064000 /* EMC_DLL_XFORM_DQS13 */
-					0x00064000 /* EMC_DLL_XFORM_DQS14 */
-					0x00064000 /* EMC_DLL_XFORM_DQS15 */
-					0x00000000 /* EMC_DLL_XFORM_QUSE0 */
-					0x00000000 /* EMC_DLL_XFORM_QUSE1 */
-					0x00000000 /* EMC_DLL_XFORM_QUSE2 */
-					0x00000000 /* EMC_DLL_XFORM_QUSE3 */
-					0x00000000 /* EMC_DLL_XFORM_QUSE4 */
-					0x00000000 /* EMC_DLL_XFORM_QUSE5 */
-					0x00000000 /* EMC_DLL_XFORM_QUSE6 */
-					0x00000000 /* EMC_DLL_XFORM_QUSE7 */
-					0x00000000 /* EMC_DLL_XFORM_ADDR0 */
-					0x00000000 /* EMC_DLL_XFORM_ADDR1 */
-					0x00000000 /* EMC_DLL_XFORM_ADDR2 */
-					0x00000000 /* EMC_DLL_XFORM_ADDR3 */
-					0x00000000 /* EMC_DLL_XFORM_ADDR4 */
-					0x00000000 /* EMC_DLL_XFORM_ADDR5 */
-					0x00000000 /* EMC_DLL_XFORM_QUSE8 */
-					0x00000000 /* EMC_DLL_XFORM_QUSE9 */
-					0x00000000 /* EMC_DLL_XFORM_QUSE10 */
-					0x00000000 /* EMC_DLL_XFORM_QUSE11 */
-					0x00000000 /* EMC_DLL_XFORM_QUSE12 */
-					0x00000000 /* EMC_DLL_XFORM_QUSE13 */
-					0x00000000 /* EMC_DLL_XFORM_QUSE14 */
-					0x00000000 /* EMC_DLL_XFORM_QUSE15 */
-					0x00000000 /* EMC_DLI_TRIM_TXDQS0 */
-					0x00000000 /* EMC_DLI_TRIM_TXDQS1 */
-					0x00000000 /* EMC_DLI_TRIM_TXDQS2 */
-					0x00000000 /* EMC_DLI_TRIM_TXDQS3 */
-					0x00000000 /* EMC_DLI_TRIM_TXDQS4 */
-					0x00000000 /* EMC_DLI_TRIM_TXDQS5 */
-					0x00000000 /* EMC_DLI_TRIM_TXDQS6 */
-					0x00000000 /* EMC_DLI_TRIM_TXDQS7 */
-					0x00000000 /* EMC_DLI_TRIM_TXDQS8 */
-					0x00000000 /* EMC_DLI_TRIM_TXDQS9 */
-					0x00000000 /* EMC_DLI_TRIM_TXDQS10 */
-					0x00000000 /* EMC_DLI_TRIM_TXDQS11 */
-					0x00000000 /* EMC_DLI_TRIM_TXDQS12 */
-					0x00000000 /* EMC_DLI_TRIM_TXDQS13 */
-					0x00000000 /* EMC_DLI_TRIM_TXDQS14 */
-					0x00000000 /* EMC_DLI_TRIM_TXDQS15 */
-					0x000fc000 /* EMC_DLL_XFORM_DQ0 */
-					0x000fc000 /* EMC_DLL_XFORM_DQ1 */
-					0x000fc000 /* EMC_DLL_XFORM_DQ2 */
-					0x000fc000 /* EMC_DLL_XFORM_DQ3 */
-					0x0000fc00 /* EMC_DLL_XFORM_DQ4 */
-					0x0000fc00 /* EMC_DLL_XFORM_DQ5 */
-					0x0000fc00 /* EMC_DLL_XFORM_DQ6 */
-					0x0000fc00 /* EMC_DLL_XFORM_DQ7 */
-					0x10000280 /* EMC_XM2CMDPADCTRL */
-					0x00000000 /* EMC_XM2CMDPADCTRL4 */
-					0x00111111 /* EMC_XM2CMDPADCTRL5 */
-					0x00000000 /* EMC_XM2DQPADCTRL2 */
-					0x00000000 /* EMC_XM2DQPADCTRL3 */
-					0x77ffc081 /* EMC_XM2CLKPADCTRL */
-					0x00000e0e /* EMC_XM2CLKPADCTRL2 */
-					0x81f1f108 /* EMC_XM2COMPPADCTRL */
-					0x07070004 /* EMC_XM2VTTGENPADCTRL */
-					0x0000003f /* EMC_XM2VTTGENPADCTRL2 */
-					0x016eeeee /* EMC_XM2VTTGENPADCTRL3 */
-					0x51451400 /* EMC_XM2DQSPADCTRL3 */
-					0x00514514 /* EMC_XM2DQSPADCTRL4 */
-					0x00514514 /* EMC_XM2DQSPADCTRL5 */
-					0x51451400 /* EMC_XM2DQSPADCTRL6 */
-					0x0000003f /* EMC_DSR_VTTGEN_DRV */
-					0x00000007 /* EMC_TXDSRVTTGEN */
-					0x00000000 /* EMC_FBIO_SPARE */
-					0x00000042 /* EMC_ZCAL_WAIT_CNT */
-					0x000e000e /* EMC_MRS_WAIT_CNT2 */
-					0x00000000 /* EMC_CTT */
-					0x00000003 /* EMC_CTT_DURATION */
-					0x0000f2f3 /* EMC_CFG_PIPE */
-					0x800001c5 /* EMC_DYN_SELF_REF_CONTROL */
-					0x0000000a /* EMC_QPOP */
-				>;
-			};
-		};
-	};
-};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/mfd/arizona.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/mfd/arizona.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/mfd/arizona.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/mfd/arizona.txt	2016-07-24 15:23:50.000000000 -0400
@@ -1,6 +1,6 @@
 Cirrus Logic/Wolfson Microelectronics Arizona class audio SoCs
 
-These devices are audio SoCs with extensive digital capabilites and a range
+These devices are audio SoCs with extensive digital capabilities and a range
 of analogue I/O.
 
 Required properties:
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/mfd/axp20x.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/mfd/axp20x.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/mfd/axp20x.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/mfd/axp20x.txt	2016-07-24 15:23:50.000000000 -0400
@@ -6,10 +6,11 @@ axp202 (X-Powers)
 axp209 (X-Powers)
 axp221 (X-Powers)
 axp223 (X-Powers)
+axp809 (X-Powers)
 
 Required properties:
 - compatible: "x-powers,axp152", "x-powers,axp202", "x-powers,axp209",
-	      "x-powers,axp221", "x-powers,axp223"
+	      "x-powers,axp221", "x-powers,axp223", "x-powers,axp809"
 - reg: The I2C slave address or RSB hardware address for the AXP chip
 - interrupt-parent: The parent interrupt controller
 - interrupts: SoC NMI / GPIO interrupt connected to the PMIC's IRQ pin
@@ -18,7 +19,9 @@ Required properties:
 
 Optional properties:
 - x-powers,dcdc-freq: defines the work frequency of DC-DC in KHz
-		      (range: 750-1875). Default: 1.5MHz
+		      AXP152/20X: range:  750-1875, Default: 1.5 MHz
+		      AXP22X/80X: range: 1800-4050, Default: 3   MHz
+
 - <input>-supply: a phandle to the regulator supply node. May be omitted if
 		  inputs are unregulated, such as using the IPSOUT output
 		  from the PMIC.
@@ -77,6 +80,30 @@ LDO_IO0		: LDO		: ips-supply		: GPIO 0
 LDO_IO1		: LDO		: ips-supply		: GPIO 1
 RTC_LDO		: LDO		: ips-supply		: always on
 
+AXP809 regulators, type, and corresponding input supply names:
+
+Regulator	  Type		  Supply Name		  Notes
+---------	  ----		  -----------		  -----
+DCDC1		: DC-DC buck	: vin1-supply
+DCDC2		: DC-DC buck	: vin2-supply
+DCDC3		: DC-DC	buck	: vin3-supply
+DCDC4		: DC-DC	buck	: vin4-supply
+DCDC5		: DC-DC	buck	: vin5-supply
+DC1SW		: On/Off Switch	:			: DCDC1 secondary output
+DC5LDO		: LDO		:			: input from DCDC5
+ALDO1		: LDO		: aldoin-supply		: shared supply
+ALDO2		: LDO		: aldoin-supply		: shared supply
+ALDO3		: LDO		: aldoin-supply		: shared supply
+DLDO1		: LDO		: dldoin-supply		: shared supply
+DLDO2		: LDO		: dldoin-supply		: shared supply
+ELDO1		: LDO		: eldoin-supply		: shared supply
+ELDO2		: LDO		: eldoin-supply		: shared supply
+ELDO3		: LDO		: eldoin-supply		: shared supply
+LDO_IO0		: LDO		: ips-supply		: GPIO 0
+LDO_IO1		: LDO		: ips-supply		: GPIO 1
+RTC_LDO		: LDO		: ips-supply		: always on
+SW		: On/Off Switch : swin-supply
+
 Example:
 
 axp209: pmic@34 {
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/mfd/hisilicon,hi655x.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/mfd/hisilicon,hi655x.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/mfd/hisilicon,hi655x.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/mfd/hisilicon,hi655x.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,27 @@
+Hisilicon Hi655x Power Management Integrated Circuit (PMIC)
+
+The hardware layout for access PMIC Hi655x from AP SoC Hi6220.
+Between PMIC Hi655x and Hi6220, the physical signal channel is SSI.
+We can use memory-mapped I/O to communicate.
+
++----------------+             +-------------+
+|                |             |             |
+|    Hi6220      |   SSI bus   |   Hi655x    |
+|                |-------------|             |
+|                |(REGMAP_MMIO)|             |
++----------------+             +-------------+
+
+Required properties:
+- compatible:           Should be "hisilicon,hi655x-pmic".
+- reg:                  Base address of PMIC on Hi6220 SoC.
+- interrupt-controller: Hi655x has internal IRQs (has own IRQ domain).
+- pmic-gpios:           The GPIO used by PMIC IRQ.
+
+Example:
+	pmic: pmic@f8000000 {
+		compatible = "hisilicon,hi655x-pmic";
+		reg = <0x0 0xf8000000 0x0 0x1000>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		pmic-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
+	}
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/mfd/max77620.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/mfd/max77620.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/mfd/max77620.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/mfd/max77620.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,143 @@
+MAX77620 Power management IC from Maxim Semiconductor.
+
+Required properties:
+-------------------
+- compatible: Must be one of
+		"maxim,max77620"
+		"maxim,max20024".
+- reg: I2C device address.
+
+Optional properties:
+-------------------
+- interrupts:		The interrupt on the parent the controller is
+			connected to.
+- interrupt-controller: Marks the device node as an interrupt controller.
+- #interrupt-cells:	is <2> and their usage is compliant to the 2 cells
+			variant of <../interrupt-controller/interrupts.txt>
+			IRQ numbers for different interrupt source of MAX77620
+			are defined at dt-bindings/mfd/max77620.h.
+
+Optional subnodes and their properties:
+=======================================
+
+Flexible power sequence configurations:
+--------------------------------------
+The Flexible Power Sequencer (FPS) allows each regulator to power up under
+hardware or software control. Additionally, each regulator can power on
+independently or among a group of other regulators with an adjustable power-up
+and power-down delays (sequencing). GPIO1, GPIO2, and GPIO3 can be programmed
+to be part of a sequence allowing external regulators to be sequenced along
+with internal regulators. 32KHz clock can be programmed to be part of a
+sequence.
+
+The flexible sequencing structure consists of two hardware enable inputs
+(EN0, EN1), and 3 master sequencing timers called FPS0, FPS1 and FPS2.
+Each master sequencing timer is programmable through its configuration
+register to have a hardware enable source (EN1 or EN2) or a software enable
+source (SW). When enabled/disabled, the master sequencing timer generates
+eight sequencing events on different time periods called slots. The time
+period between each event is programmable within the configuration register.
+Each regulator, GPIO1, GPIO2, GPIO3, and 32KHz clock has a flexible power
+sequence slave register which allows its enable source to be specified as
+a flexible power sequencer timer or a software bit. When a FPS source of
+regulators, GPIOs and clocks specifies the enable source to be a flexible
+power sequencer, the power up and power down delays can be specified in
+the regulators, GPIOs and clocks flexible power sequencer configuration
+registers.
+
+When FPS event cleared (set to LOW), regulators, GPIOs and 32KHz
+clock are set into following state at the sequencing event that
+corresponds to its flexible sequencer configuration register.
+	Sleep state: 			In this state, regulators, GPIOs
+					and 32KHz clock get disabled at
+					the sequencing event.
+	Global Low Power Mode (GLPM):	In this state, regulators are set in
+					low power mode at the sequencing event.
+
+The configuration parameters of FPS is provided through sub-node "fps"
+and their child for FPS specific. The child node name for FPS are "fps0",
+"fps1", and "fps2" for FPS0, FPS1 and FPS2 respectively.
+
+The FPS configurations like FPS source, power up and power down slots for
+regulators, GPIOs and 32kHz clocks are provided in their respective
+configuration nodes which is explained in respective sub-system DT
+binding document.
+
+There is need for different FPS configuration parameters based on system
+state like when system state changed from active to suspend or active to
+power off (shutdown).
+
+Optional properties:
+-------------------
+-maxim,fps-event-source:		u32, FPS event source like external
+					hardware input to PMIC i.e. EN0, EN1 or
+					software (SW).
+					The macros are defined on
+						dt-bindings/mfd/max77620.h
+					for different control source.
+					- MAX77620_FPS_EVENT_SRC_EN0
+						for hardware input pin EN0.
+					- MAX77620_FPS_EVENT_SRC_EN1
+						for hardware input pin EN1.
+					- MAX77620_FPS_EVENT_SRC_SW
+						for software control.
+
+-maxim,shutdown-fps-time-period-us:	u32, FPS time period in microseconds
+					when system enters in to shutdown
+					state.
+
+-maxim,suspend-fps-time-period-us:	u32, FPS time period in microseconds
+					when system enters in to suspend state.
+
+-maxim,device-state-on-disabled-event:	u32, describe the PMIC state when FPS
+					event cleared (set to LOW) whether it
+					should go to sleep state or low-power
+					state. Following are valid values:
+					- MAX77620_FPS_INACTIVE_STATE_SLEEP
+						to set the PMIC state to sleep.
+					- MAX77620_FPS_INACTIVE_STATE_LOW_POWER
+						to set the PMIC state to low
+						power.
+					Absence of this property or other value
+					will not change device state when FPS
+					event get cleared.
+
+Here supported time periods by device in microseconds are as follows:
+MAX77620 supports 40, 80, 160, 320, 640, 1280, 2560 and 5120 microseconds.
+MAX20024 supports 20, 40, 80, 160, 320, 640, 1280 and 2540 microseconds.
+
+For DT binding details of different sub modules like GPIO, pincontrol,
+regulator, power, please refer respective device-tree binding document
+under their respective sub-system directories.
+
+Example:
+--------
+#include <dt-bindings/mfd/max77620.h>
+
+max77620@3c {
+	compatible = "maxim,max77620";
+	reg = <0x3c>;
+
+	interrupt-parent = <&intc>;
+	interrupts = <0 86 IRQ_TYPE_NONE>;
+
+	interrupt-controller;
+	#interrupt-cells = <2>;
+
+	fps {
+		fps0 {
+			maxim,shutdown-fps-time-period-us = <1280>;
+			maxim,fps-event-source = <MAX77620_FPS_EVENT_SRC_EN1>;
+		};
+
+		fps1 {
+			maxim,shutdown-fps-time-period-us = <1280>;
+			maxim,fps-event-source = <MAX77620_FPS_EVENT_SRC_EN0>;
+		};
+
+		fps2 {
+			maxim,shutdown-fps-time-period-us = <1280>;
+			maxim,fps-event-source = <MAX77620_FPS_EVENT_SRC_SW>;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/mfd/qcom-rpm.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/mfd/qcom-rpm.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/mfd/qcom-rpm.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/mfd/qcom-rpm.txt	2016-07-24 15:23:50.000000000 -0400
@@ -178,7 +178,7 @@ see regulator.txt - with additional cust
 - qcom,force-mode:
 	Usage: optional (default if no other qcom,force-mode is specified)
 	Value type: <u32>
-	Defintion: indicates that the regulator should be forced to a
+	Definition: indicates that the regulator should be forced to a
 		   particular mode, valid values are:
 		   QCOM_RPM_FORCE_MODE_NONE - do not force any mode
 		   QCOM_RPM_FORCE_MODE_LPM - force into low power mode
@@ -204,7 +204,7 @@ see regulator.txt - with additional cust
 - qcom,force-mode:
 	Usage: optional
 	Value type: <u32>
-	Defintion: indicates that the regulator should not be forced to any
+	Definition: indicates that the regulator should not be forced to any
 		   particular mode, valid values are:
 		   QCOM_RPM_FORCE_MODE_NONE - do not force any mode
 		   QCOM_RPM_FORCE_MODE_LPM - force into low power mode
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/mips/brcm/soc.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/mips/brcm/soc.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/mips/brcm/soc.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/mips/brcm/soc.txt	2016-07-24 15:23:50.000000000 -0400
@@ -4,7 +4,8 @@ Required properties:
 
 - compatible: "brcm,bcm3384", "brcm,bcm33843"
               "brcm,bcm3384-viper", "brcm,bcm33843-viper"
-              "brcm,bcm6328", "brcm,bcm6368",
+              "brcm,bcm6328", "brcm,bcm6358", "brcm,bcm6368",
+              "brcm,bcm63168", "brcm,bcm63268",
               "brcm,bcm7125", "brcm,bcm7346", "brcm,bcm7358", "brcm,bcm7360",
               "brcm,bcm7362", "brcm,bcm7420", "brcm,bcm7425"
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/mips/cavium/ciu3.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/mips/cavium/ciu3.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/mips/cavium/ciu3.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/mips/cavium/ciu3.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,27 @@
+* Central Interrupt Unit v3
+
+Properties:
+- compatible: "cavium,octeon-7890-ciu3"
+
+  Compatibility with 78XX and 73XX SOCs.
+
+- interrupt-controller:  This is an interrupt controller.
+
+- reg: The base address of the CIU's register bank.
+
+- #interrupt-cells: Must be <2>.  The first cell is source number.
+  The second cell indicates the triggering semantics, and may have a
+  value of either 4 for level semantics, or 1 for edge semantics.
+
+Example:
+	interrupt-controller@1010000000000 {
+		compatible = "cavium,octeon-7890-ciu3";
+		interrupt-controller;
+		/* Interrupts are specified by two parts:
+		 * 1) Source number (20 significant bits)
+		 * 2) Trigger type: (4 == level, 1 == edge)
+		 */
+		#address-cells = <0>;
+		#interrupt-cells = <2>;
+		reg = <0x10100 0x00000000 0x0 0xb0000000>;
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/mips/cpu_irq.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/mips/cpu_irq.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/mips/cpu_irq.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/mips/cpu_irq.txt	2016-07-24 15:23:50.000000000 -0400
@@ -13,7 +13,7 @@ Required properties:
 - compatible : Should be "mti,cpu-interrupt-controller"
 
 Example devicetree:
-	cpu-irq: cpu-irq@0 {
+	cpu-irq: cpu-irq {
 		#address-cells = <0>;
 
 		interrupt-controller;
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt	2016-07-24 15:23:50.000000000 -0400
@@ -30,11 +30,90 @@ Required properties:
                         region may not be present in some scenarios, such
                         as in the device tree presented to a virtual machine.
 
+    - msi-parent
+        Value type: <phandle>
+        Definition: Must be present and point to the MSI controller node
+                    handling message interrupts for the MC.
+
+    - ranges
+        Value type: <prop-encoded-array>
+        Definition: A standard property.  Defines the mapping between the child
+                    MC address space and the parent system address space.
+
+                    The MC address space is defined by 3 components:
+                       <region type> <offset hi> <offset lo>
+
+                    Valid values for region type are
+                       0x0 - MC portals
+                       0x1 - QBMAN portals
+
+    - #address-cells
+        Value type: <u32>
+        Definition: Must be 3.  (see definition in 'ranges' property)
+
+    - #size-cells
+        Value type: <u32>
+        Definition: Must be 1.
+
+Sub-nodes:
+
+        The fsl-mc node may optionally have dpmac sub-nodes that describe
+        the relationship between the Ethernet MACs which belong to the MC
+        and the Ethernet PHYs on the system board.
+
+        The dpmac nodes must be under a node named "dpmacs" which contains
+        the following properties:
+
+            - #address-cells
+              Value type: <u32>
+              Definition: Must be present if dpmac sub-nodes are defined and must
+                          have a value of 1.
+
+            - #size-cells
+              Value type: <u32>
+              Definition: Must be present if dpmac sub-nodes are defined and must
+                          have a value of 0.
+
+        These nodes must have the following properties:
+
+            - compatible
+              Value type: <string>
+              Definition: Must be "fsl,qoriq-mc-dpmac".
+
+            - reg
+              Value type: <prop-encoded-array>
+              Definition: Specifies the id of the dpmac.
+
+            - phy-handle
+              Value type: <phandle>
+              Definition: Specifies the phandle to the PHY device node associated
+                          with the this dpmac.
+
 Example:
 
         fsl_mc: fsl-mc@80c000000 {
                 compatible = "fsl,qoriq-mc";
                 reg = <0x00000008 0x0c000000 0 0x40>,    /* MC portal base */
                       <0x00000000 0x08340000 0 0x40000>; /* MC control reg */
-        };
+                msi-parent = <&its>;
+                #address-cells = <3>;
+                #size-cells = <1>;
+
+                /*
+                 * Region type 0x0 - MC portals
+                 * Region type 0x1 - QBMAN portals
+                 */
+                ranges = <0x0 0x0 0x0 0x8 0x0c000000 0x4000000
+                          0x1 0x0 0x0 0x8 0x18000000 0x8000000>;
+
+                dpmacs {
+                    #address-cells = <1>;
+                    #size-cells = <0>;
 
+                    dpmac@1 {
+                        compatible = "fsl,qoriq-mc-dpmac";
+                        reg = <1>;
+                        phy-handle = <&mdio0_phy0>;
+                    }
+                }
+        };
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/mmc/microchip,sdhci-pic32.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/mmc/microchip,sdhci-pic32.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/mmc/microchip,sdhci-pic32.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/mmc/microchip,sdhci-pic32.txt	2016-07-24 15:23:50.000000000 -0400
@@ -20,7 +20,7 @@ Example:
 		compatible = "microchip,pic32mzda-sdhci";
 		reg = <0x1f8ec000 0x100>;
 		interrupts = <191 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&REFCLKO4>, <&PBCLK5>;
+		clocks = <&rootclk REF4CLK>, <&rootclk PB5CLK>;
 		clock-names = "base_clk", "sys_clk";
 		bus-width = <4>;
 		cap-sd-highspeed;
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/mmc/mmc-pwrseq-emmc.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/mmc/mmc-pwrseq-emmc.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/mmc/mmc-pwrseq-emmc.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/mmc/mmc-pwrseq-emmc.txt	2016-07-24 15:23:50.000000000 -0400
@@ -1,7 +1,7 @@
 * The simple eMMC hardware reset provider
 
 The purpose of this driver is to perform standard eMMC hw reset
-procedure, as descibed by Jedec 4.4 specification. This procedure is
+procedure, as described by Jedec 4.4 specification. This procedure is
 performed just after MMC core enabled power to the given mmc host (to
 fix possible issues if bootloader has left eMMC card in initialized or
 unknown state), and before performing complete system reboot (also in
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.txt	2016-07-24 15:23:50.000000000 -0400
@@ -15,6 +15,7 @@ Required Properties:
 	- "rockchip,rk3288-dw-mshc": for Rockchip RK3288
 	- "rockchip,rk3036-dw-mshc", "rockchip,rk3288-dw-mshc": for Rockchip RK3036
 	- "rockchip,rk3368-dw-mshc", "rockchip,rk3288-dw-mshc": for Rockchip RK3368
+	- "rockchip,rk3399-dw-mshc", "rockchip,rk3288-dw-mshc": for Rockchip RK3399
 
 Optional Properties:
 * clocks: from common clock binding: if ciu_drive and ciu_sample are
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/mmc/sdhci-st.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/mmc/sdhci-st.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/mmc/sdhci-st.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/mmc/sdhci-st.txt	2016-07-24 15:23:50.000000000 -0400
@@ -38,7 +38,7 @@ Optional properties:
 - bus-width:		Number of data lines.
 			See:  Documentation/devicetree/bindings/mmc/mmc.txt.
 
-- max-frequency: 	Can be 200MHz, 100Mz or 50MHz (default) and used for
+- max-frequency:	Can be 200MHz, 100Mz or 50MHz (default) and used for
 			configuring the CCONFIG3 in the mmcss.
 			See:  Documentation/devicetree/bindings/mmc/mmc.txt.
 
@@ -48,7 +48,7 @@ Optional properties:
 - vqmmc-supply:		Phandle to the regulator dt node, mentioned as the vcc/vdd
 			supply in eMMC/SD specs.
 
-- sd-uhs--sdr50:	To enable the SDR50 in the mmcss.
+- sd-uhs-sdr50:	To enable the SDR50 in the mmcss.
 			See:  Documentation/devicetree/bindings/mmc/mmc.txt.
 
 - sd-uhs-sdr104:	To enable the SDR104 in the mmcss.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/mmc/tmio_mmc.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/mmc/tmio_mmc.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/mmc/tmio_mmc.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/mmc/tmio_mmc.txt	2016-07-24 15:23:50.000000000 -0400
@@ -26,3 +26,6 @@ Required properties:
 
 Optional properties:
 - toshiba,mmc-wrprotect-disable: write-protect detection is unavailable
+- pinctrl-names: should be "default", "state_uhs"
+- pinctrl-0: should contain default/high speed pin ctrl
+- pinctrl-1: should contain uhs mode pin ctrl
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/mmc/usdhi6rol0.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/mmc/usdhi6rol0.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/mmc/usdhi6rol0.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/mmc/usdhi6rol0.txt	2016-07-24 15:23:50.000000000 -0400
@@ -12,6 +12,12 @@ Optional properties:
 
 - vmmc-supply:	a phandle of a regulator, supplying Vcc to the card
 - vqmmc-supply:	a phandle of a regulator, supplying VccQ to the card
+- pinctrl-names: Can contain a "default" entry and a "state_uhs"
+                 entry. The state_uhs entry is used together with the default
+                 entry when the board requires distinct settings for UHS speeds.
+
+- pinctrl-N: One property for each name listed in pinctrl-names, see
+             ../pinctrl/pinctrl-bindings.txt.
 
 Additionally any standard mmc bindings from mmc.txt can be used.
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/mtd/arm-versatile.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/mtd/arm-versatile.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/mtd/arm-versatile.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/mtd/arm-versatile.txt	2016-07-24 15:23:50.000000000 -0400
@@ -1,8 +1,26 @@
 Flash device on ARM Versatile board
 
+These flash chips are found in the ARM reference designs like Integrator,
+Versatile, RealView, Versatile Express etc.
+
+They are regular CFI compatible (Intel or AMD extended) flash chips with
+some special write protect/VPP bits that can be controlled by the machine's
+system controller.
+
 Required properties:
-- compatible : must be "arm,versatile-flash";
+- compatible : must be "arm,versatile-flash", "cfi-flash";
+- reg : memory address for the flash chip
 - bank-width : width in bytes of flash interface.
 
+For the rest of the properties, see mtd-physmap.txt.
+
 The device tree may optionally contain sub-nodes describing partitions of the
 address space. See partition.txt for more detail.
+
+Example:
+
+flash@34000000 {
+	compatible = "arm,versatile-flash", "cfi-flash";
+	reg = <0x34000000 0x4000000>;
+	bank-width = <4>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/mtd/atmel-nand.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/mtd/atmel-nand.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/mtd/atmel-nand.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/mtd/atmel-nand.txt	2016-07-24 15:23:50.000000000 -0400
@@ -39,7 +39,7 @@ Optional properties:
 
 Nand Flash Controller(NFC) is an optional sub-node
 Required properties:
-- compatible : "atmel,sama5d3-nfc" or "atmel,sama5d4-nfc".
+- compatible : "atmel,sama5d3-nfc".
 - reg : should specify the address and size used for NFC command registers,
         NFC registers and NFC SRAM. NFC SRAM address and size can be absent
         if don't want to use it.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt	2016-07-24 15:23:50.000000000 -0400
@@ -24,6 +24,7 @@ Required properties:
                          brcm,brcmnand-v5.0
                          brcm,brcmnand-v6.0
                          brcm,brcmnand-v6.1
+                         brcm,brcmnand-v6.2
                          brcm,brcmnand-v7.0
                          brcm,brcmnand-v7.1
                          brcm,brcmnand
@@ -52,7 +53,7 @@ Optional properties:
                               v7.0. Use this property to describe the rare
                               earlier versions of this core that include WP
 
- -- Additonal SoC-specific NAND controller properties --
+ -- Additional SoC-specific NAND controller properties --
 
 The NAND controller is integrated differently on the variety of SoCs on which it
 is found. Part of this integration involves providing status and enable bits
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/mtd/fsl-quadspi.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/mtd/fsl-quadspi.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/mtd/fsl-quadspi.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/mtd/fsl-quadspi.txt	2016-07-24 15:23:50.000000000 -0400
@@ -5,7 +5,8 @@ Required properties:
 		 "fsl,imx7d-qspi", "fsl,imx6ul-qspi",
 		 "fsl,ls1021a-qspi"
 		 or
-		 "fsl,ls2080a-qspi" followed by "fsl,ls1021a-qspi"
+		 "fsl,ls2080a-qspi" followed by "fsl,ls1021a-qspi",
+		 "fsl,ls1043a-qspi" followed by "fsl,ls1021a-qspi"
   - reg : the first contains the register location and length,
           the second contains the memory mapping address and length
   - reg-names: Should contain the reg names "QuadSPI" and "QuadSPI-memory"
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/mtd/gpmc-nand.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/mtd/gpmc-nand.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/mtd/gpmc-nand.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/mtd/gpmc-nand.txt	2016-07-24 15:23:50.000000000 -0400
@@ -13,7 +13,11 @@ Documentation/devicetree/bindings/mtd/na
 
 Required properties:
 
- - reg:		The CS line the peripheral is connected to
+ - compatible:	"ti,omap2-nand"
+ - reg:		range id (CS number), base offset and length of the
+		NAND I/O space
+ - interrupt-parent: must point to gpmc node
+ - interrupts:	Two interrupt specifiers, one for fifoevent, one for termcount.
 
 Optional properties:
 
@@ -44,6 +48,7 @@ Optional properties:
 		locating ECC errors for BCHx algorithms. SoC devices which have
 		ELM hardware engines should specify this device node in .dtsi
 		Using ELM for ECC error correction frees some CPU cycles.
+ - rb-gpios:	GPIO specifier for the ready/busy# pin.
 
 For inline partition table parsing (optional):
 
@@ -55,20 +60,26 @@ Example for an AM33xx board:
 	gpmc: gpmc@50000000 {
 		compatible = "ti,am3352-gpmc";
 		ti,hwmods = "gpmc";
-		reg = <0x50000000 0x1000000>;
+		reg = <0x50000000 0x36c>;
 		interrupts = <100>;
 		gpmc,num-cs = <8>;
 		gpmc,num-waitpins = <2>;
 		#address-cells = <2>;
 		#size-cells = <1>;
-		ranges = <0 0 0x08000000 0x2000>;	/* CS0: NAND */
+		ranges = <0 0 0x08000000 0x1000000>;	/* CS0 space, 16MB */
 		elm_id = <&elm>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
 
 		nand@0,0 {
-			reg = <0 0 0>; /* CS0, offset 0 */
+			compatible = "ti,omap2-nand";
+			reg = <0 0 4>;		/* CS0, offset 0, NAND I/O window 4 */
+			interrupt-parent = <&gpmc>;
+			interrupts = <0 IRQ_TYPE_NONE>, <1 IRQ_TYPE NONE>;
 			nand-bus-width = <16>;
 			ti,nand-ecc-opt = "bch8";
 			ti,nand-xfer-type = "polled";
+			rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */
 
 			gpmc,sync-clk-ps = <0>;
 			gpmc,cs-on-ns = <0>;
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/mtd/nand.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/mtd/nand.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/mtd/nand.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/mtd/nand.txt	2016-07-24 15:23:50.000000000 -0400
@@ -1,8 +1,31 @@
-* MTD generic binding
+* NAND chip and NAND controller generic binding
+
+NAND controller/NAND chip representation:
+
+The NAND controller should be represented with its own DT node, and all
+NAND chips attached to this controller should be defined as children nodes
+of the NAND controller. This representation should be enforced even for
+simple controllers supporting only one chip.
+
+Mandatory NAND controller properties:
+- #address-cells: depends on your controller. Should at least be 1 to
+		  encode the CS line id.
+- #size-cells: depends on your controller. Put zero unless you need a
+	       mapping between CS lines and dedicated memory regions
+
+Optional NAND controller properties
+- ranges: only needed if you need to define a mapping between CS lines and
+	  memory regions
+
+Optional NAND chip properties:
 
 - nand-ecc-mode : String, operation mode of the NAND ecc mode.
-  Supported values are: "none", "soft", "hw", "hw_syndrome", "hw_oob_first",
-  "soft_bch".
+		  Supported values are: "none", "soft", "hw", "hw_syndrome",
+		  "hw_oob_first".
+		  Deprecated values:
+		  "soft_bch": use "soft" and nand-ecc-algo instead
+- nand-ecc-algo: string, algorithm of NAND ECC.
+		 Supported values are: "hamming", "bch".
 - nand-bus-width : 8 or 16 bus width if not present 8
 - nand-on-flash-bbt: boolean to enable on flash bbt option if not present false
 
@@ -19,3 +42,20 @@ errors per {size} bytes".
 The interpretation of these parameters is implementation-defined, so not all
 implementations must support all possible combinations. However, implementations
 are encouraged to further specify the value(s) they support.
+
+Example:
+
+	nand-controller {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		/* controller specific properties */
+
+		nand@0 {
+			reg = <0>;
+			nand-ecc-mode = "soft";
+			nand-ecc-algo = "bch";
+
+			/* controller specific properties */
+		};
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/net/apm-xgene-enet.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/net/apm-xgene-enet.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/net/apm-xgene-enet.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/net/apm-xgene-enet.txt	2016-07-24 15:23:50.000000000 -0400
@@ -18,6 +18,8 @@ Required properties for all the ethernet
   - First is the Rx interrupt.  This irq is mandatory.
   - Second is the Tx completion interrupt.
     This is supported only on SGMII based 1GbE and 10GbE interfaces.
+- channel: Ethernet to CPU, start channel (prefetch buffer) number
+  - Must map to the first irq and irqs must be sequential
 - port-id: Port number (0 or 1)
 - clocks: Reference to the clock entry.
 - local-mac-address: MAC address assigned to this device
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/net/dsa/dsa.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/net/dsa/dsa.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/net/dsa/dsa.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/net/dsa/dsa.txt	2016-07-24 15:23:50.000000000 -0400
@@ -31,8 +31,6 @@ A switch child node has the following op
 			  switch. Must be set if the switch can not detect
 			  the presence and/or size of a connected EEPROM,
 			  otherwise optional.
-- reset-gpios		: phandle and specifier to a gpio line connected to
-			  reset pin of the switch chip.
 
 A switch may have multiple "port" children nodes
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/net/dsa/marvell.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/net/dsa/marvell.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/net/dsa/marvell.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/net/dsa/marvell.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,35 @@
+Marvell DSA Switch Device Tree Bindings
+---------------------------------------
+
+WARNING: This binding is currently unstable. Do not program it into a
+FLASH never to be changed again. Once this binding is stable, this
+warning will be removed.
+
+If you need a stable binding, use the old dsa.txt binding.
+
+Marvell Switches are MDIO devices. The following properties should be
+placed as a child node of an mdio device.
+
+The properties described here are those specific to Marvell devices.
+Additional required and optional properties can be found in dsa.txt.
+
+Required properties:
+- compatible           : Should be one of "marvell,mv88e6085",
+- reg                  : Address on the MII bus for the switch.
+
+Optional properties:
+
+- reset-gpios		: Should be a gpio specifier for a reset line
+
+Example:
+
+       mdio {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               switch0: switch@0 {
+                       compatible = "marvell,mv88e6085";
+                       reg = <0>;
+		       reset-gpios = <&gpio5 1 GPIO_ACTIVE_LOW>;
+               };
+       };
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/net/hisilicon-hns-dsaf.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/net/hisilicon-hns-dsaf.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/net/hisilicon-hns-dsaf.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/net/hisilicon-hns-dsaf.txt	2016-07-24 15:23:50.000000000 -0400
@@ -7,19 +7,45 @@ Required properties:
 - mode: dsa fabric mode string. only support one of dsaf modes like these:
 		"2port-64vf",
 		"6port-16rss",
-		"6port-16vf".
+		"6port-16vf",
+		"single-port".
 - interrupt-parent: the interrupt parent of this device.
 - interrupts: should contain the DSA Fabric and rcb interrupt.
 - reg: specifies base physical address(es) and size of the device registers.
-  The first region is external interface control register base and size.
-  The second region is SerDes base register and size.
+  The first region is external interface control register base and size(optional,
+  only used when subctrl-syscon does not exist). It is recommended using
+  subctrl-syscon rather than this address.
+  The second region is SerDes base register and size(optional, only used when
+  serdes-syscon in port node does not exist). It is recommended using
+  serdes-syscon rather than this address.
   The third region is the PPE register base and size.
-  The fourth region is dsa fabric base register and size.
-  The fifth region is cpld base register and size, it is not required if do not use cpld.
-- phy-handle: phy handle of physicl port, 0 if not any phy device. see ethernet.txt [1].
+  The fourth region is dsa fabric base register and size. It is not required for
+  single-port mode.
+- reg-names: may be ppe-base and(or) dsaf-base. It is used to find the
+  corresponding reg's index.
+
+- phy-handle: phy handle of physical port, 0 if not any phy device. It is optional
+  attribute. If port node exists, phy-handle in each port node will be used.
+  see ethernet.txt [1].
+- subctrl-syscon: is syscon handle for external interface control register.
+- reset-field-offset: is offset of reset field. Its value depends on the hardware
+  user manual.
 - buf-size: rx buffer size, should be 16-1024.
 - desc-num: number of description in TX and RX queue, should be 512, 1024, 2048 or 4096.
 
+- port: subnodes of dsaf. A dsaf node may contain several port nodes(Depending
+  on mode of dsaf). Port node contain some attributes listed below:
+- reg: is physical port index in one dsaf.
+- phy-handle: phy handle of physical port. It is not required if there isn't
+  phy device. see ethernet.txt [1].
+- serdes-syscon: is syscon handle for SerDes register.
+- cpld-syscon: is syscon handle + register offset pair for cpld register. It is
+  not required if there isn't cpld device.
+- port-rst-offset: is offset of reset field for each port in dsaf. Its value
+  depends on the hardware user manual.
+- port-mode-offset: is offset of port mode field for each port in dsaf. Its
+  value depends on the hardware user manual.
+
 [1] Documentation/devicetree/bindings/net/phy.txt
 
 Example:
@@ -28,11 +54,11 @@ dsaf0: dsa@c7000000 {
 	compatible = "hisilicon,hns-dsaf-v1";
 	mode = "6port-16rss";
 	interrupt-parent = <&mbigen_dsa>;
-	reg = <0x0 0xC0000000 0x0 0x420000
-	       0x0 0xC2000000 0x0 0x300000
-	       0x0 0xc5000000 0x0 0x890000
+	reg = <0x0 0xc5000000 0x0 0x890000
 	       0x0 0xc7000000 0x0 0x60000>;
-	phy-handle = <0 0 0 0 &soc0_phy4 &soc0_phy5 0 0>;
+	reg-names = "ppe-base", "dsaf-base";
+	subctrl-syscon = <&subctrl>;
+	reset-field-offset = 0;
 	interrupts = <131 4>,<132 4>, <133 4>,<134 4>,
 		     <135 4>,<136 4>, <137 4>,<138 4>,
 		     <139 4>,<140 4>, <141 4>,<142 4>,
@@ -43,4 +69,15 @@ dsaf0: dsa@c7000000 {
 	buf-size = <4096>;
 	desc-num = <1024>;
 	dma-coherent;
+
+	port@0 {
+		reg = 0;
+		phy-handle = <&phy0>;
+		serdes-syscon = <&serdes>;
+	};
+
+	port@1 {
+                reg = 1;
+                serdes-syscon = <&serdes>;
+        };
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/net/hisilicon-hns-nic.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/net/hisilicon-hns-nic.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/net/hisilicon-hns-nic.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/net/hisilicon-hns-nic.txt	2016-07-24 15:23:50.000000000 -0400
@@ -8,7 +8,7 @@ Required properties:
   specifies a reference to the associating hardware driver node.
   see Documentation/devicetree/bindings/net/hisilicon-hns-dsaf.txt
 - port-id: is the index of port provided by DSAF (the accelerator). DSAF can
-  connect to 8 PHYs. Port 0 to 1 are both used for adminstration purpose. They
+  connect to 8 PHYs. Port 0 to 1 are both used for administration purpose. They
   are called debug ports.
 
   The remaining 6 PHYs are taken according to the mode of DSAF.
@@ -36,6 +36,34 @@ Required properties:
                        | | | | | |
                       external port
 
+  This attribute is remained for compatible purpose. It is not recommended to
+  use it in new code.
+
+- port-idx-in-ae: is the index of port provided by AE.
+  In NIC mode of DSAF, all 6 PHYs of service DSAF are taken as ethernet ports
+  to the CPU. The port-idx-in-ae can be 0 to 5. Here is the diagram:
+            +-----+---------------+
+            |            CPU      |
+            +-+-+-+---+-+-+-+-+-+-+
+              |    |   | | | | | |
+           debug debug   service
+           port  port     port
+           (0)   (0)     (0-5)
+
+  In Switch mode of DSAF, all 6 PHYs of service DSAF are taken as physical
+  ports connected to a LAN Switch while the CPU side assume itself have one
+  single NIC connected to this switch. In this case, the port-idx-in-ae
+  will be 0 only.
+            +-----+-----+------+------+
+            |                CPU      |
+            +-+-+-+-+-+-+-+-+-+-+-+-+-+
+              |    |     service| port(0)
+            debug debug  +------------+
+            port  port   |   switch   |
+            (0)   (0)    +-+-+-+-+-+-++
+                          | | | | | |
+                         external port
+
 - local-mac-address: mac addr of the ethernet interface
 
 Example:
@@ -43,6 +71,6 @@ Example:
 	ethernet@0{
 		compatible = "hisilicon,hns-nic-v1";
 		ae-handle = <&dsaf0>;
-		port-id = <0>;
+		port-idx-in-ae = <0>;
 		local-mac-address = [a2 14 e4 4b 56 76];
 	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/net/marvell-bt-sd8xxx.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/net/marvell-bt-sd8xxx.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/net/marvell-bt-sd8xxx.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/net/marvell-bt-sd8xxx.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,56 @@
+Marvell 8897/8997 (sd8897/sd8997) bluetooth SDIO devices
+------
+
+Required properties:
+
+  - compatible : should be one of the following:
+	* "marvell,sd8897-bt"
+	* "marvell,sd8997-bt"
+
+Optional properties:
+
+  - marvell,cal-data: Calibration data downloaded to the device during
+		      initialization. This is an array of 28 values(u8).
+
+  - marvell,wakeup-pin: It represents wakeup pin number of the bluetooth chip.
+		        firmware will use the pin to wakeup host system (u16).
+  - marvell,wakeup-gap-ms: wakeup gap represents wakeup latency of the host
+		      platform. The value will be configured to firmware. This
+		      is needed to work chip's sleep feature as expected (u16).
+  - interrupt-parent: phandle of the parent interrupt controller
+  - interrupts : interrupt pin number to the cpu. Driver will request an irq based
+		 on this interrupt number. During system suspend, the irq will be
+		 enabled so that the bluetooth chip can wakeup host platform under
+		 certain condition. During system resume, the irq will be disabled
+		 to make sure unnecessary interrupt is not received.
+
+Example:
+
+IRQ pin 119 is used as system wakeup source interrupt.
+wakeup pin 13 and gap 100ms are configured so that firmware can wakeup host
+using this device side pin and wakeup latency.
+calibration data is also available in below example.
+
+&mmc3 {
+	status = "okay";
+	vmmc-supply = <&wlan_en_reg>;
+	bus-width = <4>;
+	cap-power-off-card;
+	keep-power-in-suspend;
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+	btmrvl: bluetooth@2 {
+		compatible = "marvell,sd8897-bt";
+		reg = <2>;
+		interrupt-parent = <&pio>;
+		interrupts = <119 IRQ_TYPE_LEVEL_LOW>;
+
+		marvell,cal-data = /bits/ 8 <
+			0x37 0x01 0x1c 0x00 0xff 0xff 0xff 0xff 0x01 0x7f 0x04 0x02
+			0x00 0x00 0xba 0xce 0xc0 0xc6 0x2d 0x00 0x00 0x00 0x00 0x00
+			0x00 0x00 0xf0 0x00>;
+		marvell,wakeup-pin = /bits/ 16 <0x0d>;
+		marvell,wakeup-gap-ms = /bits/ 16 <0x64>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/net/microchip,enc28j60.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/net/microchip,enc28j60.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/net/microchip,enc28j60.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/net/microchip,enc28j60.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,59 @@
+* Microchip ENC28J60
+
+This is a standalone 10 MBit ethernet controller with SPI interface.
+
+For each device connected to a SPI bus, define a child node within
+the SPI master node.
+
+Required properties:
+- compatible: Should be "microchip,enc28j60"
+- reg: Specify the SPI chip select the ENC28J60 is wired to
+- interrupt-parent: Specify the phandle of the source interrupt, see interrupt
+                    binding documentation for details. Usually this is the GPIO bank
+                    the interrupt line is wired to.
+- interrupts: Specify the interrupt index within the interrupt controller (referred
+              to above in interrupt-parent) and interrupt type. The ENC28J60 natively
+              generates falling edge interrupts, however, additional board logic
+              might invert the signal.
+- pinctrl-names: List of assigned state names, see pinctrl binding documentation.
+- pinctrl-0: List of phandles to configure the GPIO pin used as interrupt line,
+             see also generic and your platform specific pinctrl binding
+             documentation.
+
+Optional properties:
+- spi-max-frequency: Maximum frequency of the SPI bus when accessing the ENC28J60.
+  According to the ENC28J80 datasheet, the chip allows a maximum of 20 MHz, however,
+  board designs may need to limit this value.
+- local-mac-address: See ethernet.txt in the same directory.
+
+
+Example (for NXP i.MX28 with pin control stuff for GPIO irq):
+
+        ssp2: ssp@80014000 {
+                compatible = "fsl,imx28-spi";
+                pinctrl-names = "default";
+                pinctrl-0 = <&spi2_pins_b &spi2_sck_cfg>;
+                status = "okay";
+
+                enc28j60: ethernet@0 {
+                        compatible = "microchip,enc28j60";
+                        pinctrl-names = "default";
+                        pinctrl-0 = <&enc28j60_pins>;
+                        reg = <0>;
+                        interrupt-parent = <&gpio3>;
+                        interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+                        spi-max-frequency = <12000000>;
+                };
+        };
+
+        pinctrl@80018000 {
+                enc28j60_pins: enc28j60_pins@0 {
+                        reg = <0>;
+                        fsl,pinmux-ids = <
+                                MX28_PAD_AUART0_RTS__GPIO_3_3    /* Interrupt */
+                        >;
+                        fsl,drive-strength = <MXS_DRIVE_4mA>;
+                        fsl,voltage = <MXS_VOLTAGE_HIGH>;
+                        fsl,pull-up = <MXS_PULL_DISABLE>;
+                };
+        };
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/net/nfc/pn533-i2c.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/net/nfc/pn533-i2c.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/net/nfc/pn533-i2c.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/net/nfc/pn533-i2c.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,31 @@
+* NXP Semiconductors PN532 NFC Controller
+
+Required properties:
+- compatible: Should be "nxp,pn532-i2c" or "nxp,pn533-i2c".
+- clock-frequency: I²C work frequency.
+- reg: address on the bus
+- interrupt-parent: phandle for the interrupt gpio controller
+- interrupts: GPIO interrupt to which the chip is connected
+
+Optional SoC Specific Properties:
+- pinctrl-names: Contains only one value - "default".
+- pintctrl-0: Specifies the pin control groups used for this controller.
+
+Example (for ARM-based BeagleBone with PN532 on I2C2):
+
+&i2c2 {
+
+	status = "okay";
+
+	pn532: pn532@24 {
+
+		compatible = "nxp,pn532-i2c";
+
+		reg = <0x24>;
+		clock-frequency = <400000>;
+
+		interrupt-parent = <&gpio1>;
+		interrupts = <17 IRQ_TYPE_EDGE_FALLING>;
+
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/net/stmmac.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/net/stmmac.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/net/stmmac.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/net/stmmac.txt	2016-07-24 15:23:50.000000000 -0400
@@ -51,14 +51,16 @@ Optional properties:
 			   AXI register inside the DMA module:
 	- snps,lpi_en: enable Low Power Interface
 	- snps,xit_frm: unlock on WoL
-	- snps,wr_osr_lmt: max write oustanding req. limit
-	- snps,rd_osr_lmt: max read oustanding req. limit
+	- snps,wr_osr_lmt: max write outstanding req. limit
+	- snps,rd_osr_lmt: max read outstanding req. limit
 	- snps,kbbe: do not cross 1KiB boundary.
 	- snps,axi_all: align address
 	- snps,blen: this is a vector of supported burst length.
 	- snps,fb: fixed-burst
 	- snps,mb: mixed-burst
 	- snps,rb: rebuild INCRx Burst
+	- snps,tso: this enables the TSO feature otherwise it will be managed by
+	    MAC HW capability register.
 - mdio: with compatible = "snps,dwmac-mdio", create and register mdio bus.
 
 Examples:
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/net/ti,dp83867.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/net/ti,dp83867.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/net/ti,dp83867.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/net/ti,dp83867.txt	2016-07-24 15:23:50.000000000 -0400
@@ -2,7 +2,7 @@
 
 Required properties:
 	- reg - The ID number for the phy, usually a small integer
-	- ti,rx-internal-delay - RGMII Recieve Clock Delay - see dt-bindings/net/ti-dp83867.h
+	- ti,rx-internal-delay - RGMII Receive Clock Delay - see dt-bindings/net/ti-dp83867.h
 		for applicable values
 	- ti,tx-internal-delay - RGMII Transmit Clock Delay - see dt-bindings/net/ti-dp83867.h
 		for applicable values
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/net/wireless/marvell-sd8xxx.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/net/wireless/marvell-sd8xxx.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/net/wireless/marvell-sd8xxx.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/net/wireless/marvell-sd8xxx.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,63 @@
+Marvell 8897/8997 (sd8897/sd8997) SDIO devices
+------
+
+This node provides properties for controlling the marvell sdio wireless device.
+The node is expected to be specified as a child node to the SDIO controller that
+connects the device to the system.
+
+Required properties:
+
+  - compatible : should be one of the following:
+	* "marvell,sd8897"
+	* "marvell,sd8997"
+
+Optional properties:
+
+  - marvell,caldata* : A series of properties with marvell,caldata prefix,
+		      represent calibration data downloaded to the device during
+		      initialization. This is an array of unsigned 8-bit values.
+		      the properties should follow below property name and
+		      corresponding array length:
+	"marvell,caldata-txpwrlimit-2g" (length = 566).
+	"marvell,caldata-txpwrlimit-5g-sub0" (length = 502).
+	"marvell,caldata-txpwrlimit-5g-sub1" (length = 688).
+	"marvell,caldata-txpwrlimit-5g-sub2" (length = 750).
+	"marvell,caldata-txpwrlimit-5g-sub3" (length = 502).
+  - marvell,wakeup-pin : a wakeup pin number of wifi chip which will be configured
+		      to firmware. Firmware will wakeup the host using this pin
+		      during suspend/resume.
+  - interrupt-parent: phandle of the parent interrupt controller
+  - interrupts : interrupt pin number to the cpu. driver will request an irq based on
+		 this interrupt number. during system suspend, the irq will be enabled
+		 so that the wifi chip can wakeup host platform under certain condition.
+		 during system resume, the irq will be disabled to make sure
+		 unnecessary interrupt is not received.
+
+Example:
+
+Tx power limit calibration data is configured in below example.
+The calibration data is an array of unsigned values, the length
+can vary between hw versions.
+IRQ pin 38 is used as system wakeup source interrupt. wakeup pin 3 is configured
+so that firmware can wakeup host using this device side pin.
+
+&mmc3 {
+	status = "okay";
+	vmmc-supply = <&wlan_en_reg>;
+	bus-width = <4>;
+	cap-power-off-card;
+	keep-power-in-suspend;
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+	mwifiex: wifi@1 {
+		compatible = "marvell,sd8897";
+		reg = <1>;
+		interrupt-parent = <&pio>;
+		interrupts = <38 IRQ_TYPE_LEVEL_LOW>;
+
+		marvell,caldata_00_txpwrlimit_2g_cfg_set = /bits/ 8 <
+	0x01 0x00 0x06 0x00 0x08 0x02 0x89 0x01>;
+		marvell,wakeup-pin = <3>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt	2016-07-24 15:23:50.000000000 -0400
@@ -5,12 +5,18 @@ Required properties:
 	* "qcom,ath10k"
 	* "qcom,ipq4019-wifi"
 
-PCI based devices uses compatible string "qcom,ath10k" and takes only
-calibration data via "qcom,ath10k-calibration-data". Rest of the properties
-are not applicable for PCI based devices.
+PCI based devices uses compatible string "qcom,ath10k" and takes calibration
+data along with board specific data via "qcom,ath10k-calibration-data".
+Rest of the properties are not applicable for PCI based devices.
 
 AHB based devices (i.e. ipq4019) uses compatible string "qcom,ipq4019-wifi"
-and also uses most of the properties defined in this doc.
+and also uses most of the properties defined in this doc (except
+"qcom,ath10k-calibration-data"). It uses "qcom,ath10k-pre-calibration-data"
+to carry pre calibration data.
+
+In general, entry "qcom,ath10k-pre-calibration-data" and
+"qcom,ath10k-calibration-data" conflict with each other and only one
+can be provided per device.
 
 Optional properties:
 - reg: Address and length of the register set for the device.
@@ -35,8 +41,11 @@ Optional properties:
 - qcom,msi_addr: MSI interrupt address.
 - qcom,msi_base: Base value to add before writing MSI data into
 		MSI address register.
-- qcom,ath10k-calibration-data : calibration data as an array, the
-				 length can vary between hw versions
+- qcom,ath10k-calibration-data : calibration data + board specific data
+				 as an array, the length can vary between
+				 hw versions.
+- qcom,ath10k-pre-calibration-data : pre calibration data as an array,
+				     the length can vary between hw versions.
 
 Example (to supply the calibration data alone):
 
@@ -105,5 +114,5 @@ wifi0: wifi@a000000 {
 			  "legacy";
 	qcom,msi_addr = <0x0b006040>;
 	qcom,msi_base = <0x40>;
-	qcom,ath10k-calibration-data = [ 01 02 03 ... ];
+	qcom,ath10k-pre-calibration-data = [ 01 02 03 ... ];
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/numa.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/numa.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/numa.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/numa.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,275 @@
+==============================================================================
+NUMA binding description.
+==============================================================================
+
+==============================================================================
+1 - Introduction
+==============================================================================
+
+Systems employing a Non Uniform Memory Access (NUMA) architecture contain
+collections of hardware resources including processors, memory, and I/O buses,
+that comprise what is commonly known as a NUMA node.
+Processor accesses to memory within the local NUMA node is generally faster
+than processor accesses to memory outside of the local NUMA node.
+DT defines interfaces that allow the platform to convey NUMA node
+topology information to OS.
+
+==============================================================================
+2 - numa-node-id
+==============================================================================
+
+For the purpose of identification, each NUMA node is associated with a unique
+token known as a node id. For the purpose of this binding
+a node id is a 32-bit integer.
+
+A device node is associated with a NUMA node by the presence of a
+numa-node-id property which contains the node id of the device.
+
+Example:
+	/* numa node 0 */
+	numa-node-id = <0>;
+
+	/* numa node 1 */
+	numa-node-id = <1>;
+
+==============================================================================
+3 - distance-map
+==============================================================================
+
+The optional device tree node distance-map describes the relative
+distance (memory latency) between all numa nodes.
+
+- compatible : Should at least contain "numa-distance-map-v1".
+
+- distance-matrix
+  This property defines a matrix to describe the relative distances
+  between all numa nodes.
+  It is represented as a list of node pairs and their relative distance.
+
+  Note:
+	1. Each entry represents distance from first node to second node.
+	The distances are equal in either direction.
+	2. The distance from a node to self (local distance) is represented
+	with value 10 and all internode distance should be represented with
+	a value greater than 10.
+	3. distance-matrix should have entries in lexicographical ascending
+	order of nodes.
+	4. There must be only one device node distance-map which must
+	reside in the root node.
+	5. If the distance-map node is not present, a default
+	distance-matrix is used.
+
+Example:
+	4 nodes connected in mesh/ring topology as below,
+
+		0_______20______1
+		|               |
+		|               |
+		20             20
+		|               |
+		|               |
+		|_______________|
+		3       20      2
+
+	if relative distance for each hop is 20,
+	then internode distance would be,
+	      0 -> 1 = 20
+	      1 -> 2 = 20
+	      2 -> 3 = 20
+	      3 -> 0 = 20
+	      0 -> 2 = 40
+	      1 -> 3 = 40
+
+     and dt presentation for this distance matrix is,
+
+		distance-map {
+			 compatible = "numa-distance-map-v1";
+			 distance-matrix = <0 0  10>,
+					   <0 1  20>,
+					   <0 2  40>,
+					   <0 3  20>,
+					   <1 0  20>,
+					   <1 1  10>,
+					   <1 2  20>,
+					   <1 3  40>,
+					   <2 0  40>,
+					   <2 1  20>,
+					   <2 2  10>,
+					   <2 3  20>,
+					   <3 0  20>,
+					   <3 1  40>,
+					   <3 2  20>,
+					   <3 3  10>;
+		};
+
+==============================================================================
+4 - Example dts
+==============================================================================
+
+Dual socket system consists of 2 boards connected through ccn bus and
+each board having one socket/soc of 8 cpus, memory and pci bus.
+
+	memory@c00000 {
+		device_type = "memory";
+		reg = <0x0 0xc00000 0x0 0x80000000>;
+		/* node 0 */
+		numa-node-id = <0>;
+	};
+
+	memory@10000000000 {
+		device_type = "memory";
+		reg = <0x100 0x0 0x0 0x80000000>;
+		/* node 1 */
+		numa-node-id = <1>;
+	};
+
+	cpus {
+		#address-cells = <2>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible =  "arm,armv8";
+			reg = <0x0 0x0>;
+			enable-method = "psci";
+			/* node 0 */
+			numa-node-id = <0>;
+		};
+		cpu@1 {
+			device_type = "cpu";
+			compatible =  "arm,armv8";
+			reg = <0x0 0x1>;
+			enable-method = "psci";
+			numa-node-id = <0>;
+		};
+		cpu@2 {
+			device_type = "cpu";
+			compatible =  "arm,armv8";
+			reg = <0x0 0x2>;
+			enable-method = "psci";
+			numa-node-id = <0>;
+		};
+		cpu@3 {
+			device_type = "cpu";
+			compatible =  "arm,armv8";
+			reg = <0x0 0x3>;
+			enable-method = "psci";
+			numa-node-id = <0>;
+		};
+		cpu@4 {
+			device_type = "cpu";
+			compatible =  "arm,armv8";
+			reg = <0x0 0x4>;
+			enable-method = "psci";
+			numa-node-id = <0>;
+		};
+		cpu@5 {
+			device_type = "cpu";
+			compatible =  "arm,armv8";
+			reg = <0x0 0x5>;
+			enable-method = "psci";
+			numa-node-id = <0>;
+		};
+		cpu@6 {
+			device_type = "cpu";
+			compatible =  "arm,armv8";
+			reg = <0x0 0x6>;
+			enable-method = "psci";
+			numa-node-id = <0>;
+		};
+		cpu@7 {
+			device_type = "cpu";
+			compatible =  "arm,armv8";
+			reg = <0x0 0x7>;
+			enable-method = "psci";
+			numa-node-id = <0>;
+		};
+		cpu@8 {
+			device_type = "cpu";
+			compatible =  "arm,armv8";
+			reg = <0x0 0x8>;
+			enable-method = "psci";
+			/* node 1 */
+			numa-node-id = <1>;
+		};
+		cpu@9 {
+			device_type = "cpu";
+			compatible =  "arm,armv8";
+			reg = <0x0 0x9>;
+			enable-method = "psci";
+			numa-node-id = <1>;
+		};
+		cpu@a {
+			device_type = "cpu";
+			compatible =  "arm,armv8";
+			reg = <0x0 0xa>;
+			enable-method = "psci";
+			numa-node-id = <1>;
+		};
+		cpu@b {
+			device_type = "cpu";
+			compatible =  "arm,armv8";
+			reg = <0x0 0xb>;
+			enable-method = "psci";
+			numa-node-id = <1>;
+		};
+		cpu@c {
+			device_type = "cpu";
+			compatible =  "arm,armv8";
+			reg = <0x0 0xc>;
+			enable-method = "psci";
+			numa-node-id = <1>;
+		};
+		cpu@d {
+			device_type = "cpu";
+			compatible =  "arm,armv8";
+			reg = <0x0 0xd>;
+			enable-method = "psci";
+			numa-node-id = <1>;
+		};
+		cpu@e {
+			device_type = "cpu";
+			compatible =  "arm,armv8";
+			reg = <0x0 0xe>;
+			enable-method = "psci";
+			numa-node-id = <1>;
+		};
+		cpu@f {
+			device_type = "cpu";
+			compatible =  "arm,armv8";
+			reg = <0x0 0xf>;
+			enable-method = "psci";
+			numa-node-id = <1>;
+		};
+	};
+
+	pcie0: pcie0@848000000000 {
+		compatible = "arm,armv8";
+		device_type = "pci";
+		bus-range = <0 255>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0x8480 0x00000000 0 0x10000000>;  /* Configuration space */
+		ranges = <0x03000000 0x8010 0x00000000 0x8010 0x00000000 0x70 0x00000000>;
+		/* node 0 */
+		numa-node-id = <0>;
+        };
+
+	pcie1: pcie1@948000000000 {
+		compatible = "arm,armv8";
+		device_type = "pci";
+		bus-range = <0 255>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		reg = <0x9480 0x00000000 0 0x10000000>;  /* Configuration space */
+		ranges = <0x03000000 0x9010 0x00000000 0x9010 0x00000000 0x70 0x00000000>;
+		/* node 1 */
+		numa-node-id = <1>;
+        };
+
+	distance-map {
+		compatible = "numa-distance-map-v1";
+		distance-matrix = <0 0 10>,
+				  <0 1 20>,
+				  <1 1 10>;
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/opp/opp.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/opp/opp.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/opp/opp.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/opp/opp.txt	2016-07-24 15:23:50.000000000 -0400
@@ -45,7 +45,7 @@ Devices supporting OPPs must set their "
 phandle to a OPP table in their DT node. The OPP core will use this phandle to
 find the operating points for the device.
 
-If required, this can be extended for SoC vendor specfic bindings. Such bindings
+If required, this can be extended for SoC vendor specific bindings. Such bindings
 should be documented as Documentation/devicetree/bindings/power/<vendor>-opp.txt
 and should have a compatible description like: "operating-points-v2-<vendor>".
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/pci/designware-pcie.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/pci/designware-pcie.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/pci/designware-pcie.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/pci/designware-pcie.txt	2016-07-24 15:23:50.000000000 -0400
@@ -31,7 +31,7 @@ Optional properties:
 
 Example configuration:
 
-	pcie: pcie@0xdffff000 {
+	pcie: pcie@dffff000 {
 		compatible = "snps,dw-pcie";
 		reg = <0xdffff000 0x1000>, /* Controller registers */
 		      <0xd0000000 0x2000>; /* PCI config space */
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt	2016-07-24 15:23:50.000000000 -0400
@@ -4,8 +4,8 @@ This PCIe host controller is based on th
 and thus inherits all the common properties defined in designware-pcie.txt.
 
 Required properties:
-- compatible: "fsl,imx6q-pcie"
-- reg: base addresse and length of the pcie controller
+- compatible: "fsl,imx6q-pcie", "fsl,imx6sx-pcie", "fsl,imx6qp-pcie"
+- reg: base address and length of the PCIe controller
 - interrupts: A list of interrupt outputs of the controller. Must contain an
   entry for each entry in the interrupt-names property.
 - interrupt-names: Must include the following entries:
@@ -19,6 +19,20 @@ Optional properties:
 - fsl,tx-deemph-gen2-6db: Gen2 (6db) De-emphasis value. Default: 20
 - fsl,tx-swing-full: Gen2 TX SWING FULL value. Default: 127
 - fsl,tx-swing-low: TX launch amplitude swing_low value. Default: 127
+- fsl,max-link-speed: Specify PCI gen for link capability. Must be '2' for
+  gen2, otherwise will default to gen1. Note that the IMX6 LVDS clock outputs
+  do not meet gen2 jitter requirements and thus for gen2 capability a gen2
+  compliant clock generator should be used and configured.
+- reset-gpio: Should specify the GPIO for controlling the PCI bus device reset
+  signal. It's not polarity aware and defaults to active-low reset sequence
+  (L=reset state, H=operation state).
+- reset-gpio-active-high: If present then the reset sequence using the GPIO
+  specified in the "reset-gpio" property is reversed (H=reset state,
+  L=operation state).
+
+Additional required properties for imx6sx-pcie:
+- clock names: Must include the following additional entries:
+	- "pcie_inbound_axi"
 
 Example:
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt	2016-07-24 15:23:50.000000000 -0400
@@ -34,11 +34,11 @@ Hip05 Example (note that Hip06 is the sa
 		ranges = <0x82000000 0 0x00000000 0x220 0x00000000 0 0x10000000>;
 		num-lanes = <8>;
 		port-id = <1>;
-		#interrupts-cells = <1>;
-		interrupts-map-mask = <0xf800 0 0 7>;
-		interrupts-map = <0x0 0 0 1 &mbigen_pcie 1 10
-				  0x0 0 0 2 &mbigen_pcie 2 11
-				  0x0 0 0 3 &mbigen_pcie 3 12
-				  0x0 0 0 4 &mbigen_pcie 4 13>;
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0xf800 0 0 7>;
+		interrupt-map = <0x0 0 0 1 &mbigen_pcie 1 10
+				 0x0 0 0 2 &mbigen_pcie 2 11
+				 0x0 0 0 3 &mbigen_pcie 3 12
+				 0x0 0 0 4 &mbigen_pcie 4 13>;
 		status = "ok";
 	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt	2016-07-24 15:23:50.000000000 -0400
@@ -60,11 +60,14 @@ Required properties:
   - afi
   - pcie_x
 
-Required properties on Tegra124 and later:
+Required properties on Tegra124 and later (deprecated):
 - phys: Must contain an entry for each entry in phy-names.
 - phy-names: Must include the following entries:
   - pcie
 
+These properties are deprecated in favour of per-lane PHYs define in each of
+the root ports (see below).
+
 Power supplies for Tegra20:
 - avdd-pex-supply: Power supply for analog PCIe logic. Must supply 1.05 V.
 - vdd-pex-supply: Power supply for digital PCIe I/O. Must supply 1.05 V.
@@ -122,11 +125,22 @@ Required properties:
   - Root port 0 uses 4 lanes, root port 1 is unused.
   - Both root ports use 2 lanes.
 
-Example:
+Required properties for Tegra124 and later:
+- phys: Must contain an phandle to a PHY for each entry in phy-names.
+- phy-names: Must include an entry for each active lane. Note that the number
+  of entries does not have to (though usually will) be equal to the specified
+  number of lanes in the nvidia,num-lanes property. Entries are of the form
+  "pcie-N": where N ranges from 0 to the value specified in nvidia,num-lanes.
+
+Examples:
+=========
+
+Tegra20:
+--------
 
 SoC DTSI:
 
-	pcie-controller {
+	pcie-controller@80003000 {
 		compatible = "nvidia,tegra20-pcie";
 		device_type = "pci";
 		reg = <0x80003000 0x00000800   /* PADS registers */
@@ -186,10 +200,9 @@ SoC DTSI:
 		};
 	};
 
-
 Board DTS:
 
-	pcie-controller {
+	pcie-controller@80003000 {
 		status = "okay";
 
 		vdd-supply = <&pci_vdd_reg>;
@@ -222,3 +235,204 @@ if a device on the PCI bus provides a no
 device nodes need to be added in order to allow the bus' children to be
 instantiated at the proper location in the operating system's device tree (as
 illustrated by the optional nodes in the example above).
+
+Tegra30:
+--------
+
+SoC DTSI:
+
+	pcie-controller@00003000 {
+		compatible = "nvidia,tegra30-pcie";
+		device_type = "pci";
+		reg = <0x00003000 0x00000800   /* PADS registers */
+		       0x00003800 0x00000200   /* AFI registers */
+		       0x10000000 0x10000000>; /* configuration space */
+		reg-names = "pads", "afi", "cs";
+		interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH   /* controller interrupt */
+			      GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>; /* MSI interrupt */
+		interrupt-names = "intr", "msi";
+
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 0 0>;
+		interrupt-map = <0 0 0 0 &intc GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+
+		bus-range = <0x00 0xff>;
+		#address-cells = <3>;
+		#size-cells = <2>;
+
+		ranges = <0x82000000 0 0x00000000 0x00000000 0 0x00001000   /* port 0 configuration space */
+			  0x82000000 0 0x00001000 0x00001000 0 0x00001000   /* port 1 configuration space */
+			  0x82000000 0 0x00004000 0x00004000 0 0x00001000   /* port 2 configuration space */
+			  0x81000000 0 0          0x02000000 0 0x00010000   /* downstream I/O */
+			  0x82000000 0 0x20000000 0x20000000 0 0x08000000   /* non-prefetchable memory */
+			  0xc2000000 0 0x28000000 0x28000000 0 0x18000000>; /* prefetchable memory */
+
+		clocks = <&tegra_car TEGRA30_CLK_PCIE>,
+			 <&tegra_car TEGRA30_CLK_AFI>,
+			 <&tegra_car TEGRA30_CLK_PLL_E>,
+			 <&tegra_car TEGRA30_CLK_CML0>;
+		clock-names = "pex", "afi", "pll_e", "cml";
+		resets = <&tegra_car 70>,
+			 <&tegra_car 72>,
+			 <&tegra_car 74>;
+		reset-names = "pex", "afi", "pcie_x";
+		status = "disabled";
+
+		pci@1,0 {
+			device_type = "pci";
+			assigned-addresses = <0x82000800 0 0x00000000 0 0x1000>;
+			reg = <0x000800 0 0 0 0>;
+			status = "disabled";
+
+			#address-cells = <3>;
+			#size-cells = <2>;
+			ranges;
+
+			nvidia,num-lanes = <2>;
+		};
+
+		pci@2,0 {
+			device_type = "pci";
+			assigned-addresses = <0x82001000 0 0x00001000 0 0x1000>;
+			reg = <0x001000 0 0 0 0>;
+			status = "disabled";
+
+			#address-cells = <3>;
+			#size-cells = <2>;
+			ranges;
+
+			nvidia,num-lanes = <2>;
+		};
+
+		pci@3,0 {
+			device_type = "pci";
+			assigned-addresses = <0x82001800 0 0x00004000 0 0x1000>;
+			reg = <0x001800 0 0 0 0>;
+			status = "disabled";
+
+			#address-cells = <3>;
+			#size-cells = <2>;
+			ranges;
+
+			nvidia,num-lanes = <2>;
+		};
+	};
+
+Board DTS:
+
+	pcie-controller@00003000 {
+		status = "okay";
+
+		avdd-pexa-supply = <&ldo1_reg>;
+		vdd-pexa-supply = <&ldo1_reg>;
+		avdd-pexb-supply = <&ldo1_reg>;
+		vdd-pexb-supply = <&ldo1_reg>;
+		avdd-pex-pll-supply = <&ldo1_reg>;
+		avdd-plle-supply = <&ldo1_reg>;
+		vddio-pex-ctl-supply = <&sys_3v3_reg>;
+		hvdd-pex-supply = <&sys_3v3_pexs_reg>;
+
+		pci@1,0 {
+			status = "okay";
+		};
+
+		pci@3,0 {
+			status = "okay";
+		};
+	};
+
+Tegra124:
+---------
+
+SoC DTSI:
+
+	pcie-controller@01003000 {
+		compatible = "nvidia,tegra124-pcie";
+		device_type = "pci";
+		reg = <0x0 0x01003000 0x0 0x00000800   /* PADS registers */
+		       0x0 0x01003800 0x0 0x00000800   /* AFI registers */
+		       0x0 0x02000000 0x0 0x10000000>; /* configuration space */
+		reg-names = "pads", "afi", "cs";
+		interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>, /* controller interrupt */
+			     <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>; /* MSI interrupt */
+		interrupt-names = "intr", "msi";
+
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 0 0>;
+		interrupt-map = <0 0 0 0 &gic GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+
+		bus-range = <0x00 0xff>;
+		#address-cells = <3>;
+		#size-cells = <2>;
+
+		ranges = <0x82000000 0 0x01000000 0x0 0x01000000 0 0x00001000   /* port 0 configuration space */
+			  0x82000000 0 0x01001000 0x0 0x01001000 0 0x00001000   /* port 1 configuration space */
+			  0x81000000 0 0x0        0x0 0x12000000 0 0x00010000   /* downstream I/O (64 KiB) */
+			  0x82000000 0 0x13000000 0x0 0x13000000 0 0x0d000000   /* non-prefetchable memory (208 MiB) */
+			  0xc2000000 0 0x20000000 0x0 0x20000000 0 0x20000000>; /* prefetchable memory (512 MiB) */
+
+		clocks = <&tegra_car TEGRA124_CLK_PCIE>,
+			 <&tegra_car TEGRA124_CLK_AFI>,
+			 <&tegra_car TEGRA124_CLK_PLL_E>,
+			 <&tegra_car TEGRA124_CLK_CML0>;
+		clock-names = "pex", "afi", "pll_e", "cml";
+		resets = <&tegra_car 70>,
+			 <&tegra_car 72>,
+			 <&tegra_car 74>;
+		reset-names = "pex", "afi", "pcie_x";
+		status = "disabled";
+
+		pci@1,0 {
+			device_type = "pci";
+			assigned-addresses = <0x82000800 0 0x01000000 0 0x1000>;
+			reg = <0x000800 0 0 0 0>;
+			status = "disabled";
+
+			#address-cells = <3>;
+			#size-cells = <2>;
+			ranges;
+
+			nvidia,num-lanes = <2>;
+		};
+
+		pci@2,0 {
+			device_type = "pci";
+			assigned-addresses = <0x82001000 0 0x01001000 0 0x1000>;
+			reg = <0x001000 0 0 0 0>;
+			status = "disabled";
+
+			#address-cells = <3>;
+			#size-cells = <2>;
+			ranges;
+
+			nvidia,num-lanes = <1>;
+		};
+	};
+
+Board DTS:
+
+	pcie-controller@01003000 {
+		status = "okay";
+
+		avddio-pex-supply = <&vdd_1v05_run>;
+		dvddio-pex-supply = <&vdd_1v05_run>;
+		avdd-pex-pll-supply = <&vdd_1v05_run>;
+		hvdd-pex-supply = <&vdd_3v3_lp0>;
+		hvdd-pex-pll-e-supply = <&vdd_3v3_lp0>;
+		vddio-pex-ctl-supply = <&vdd_3v3_lp0>;
+		avdd-pll-erefe-supply = <&avdd_1v05_run>;
+
+		/* Mini PCIe */
+		pci@1,0 {
+			phys = <&{/padctl@7009f000/pads/pcie/lanes/pcie-4}>;
+			phy-names = "pcie-0";
+			status = "okay";
+		};
+
+		/* Gigabit Ethernet */
+		pci@2,0 {
+			phys = <&{/padctl@7009f000/pads/pcie/lanes/pcie-2}>;
+			phy-names = "pcie-0";
+			status = "okay";
+		};
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/pci/pci-armada8k.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/pci/pci-armada8k.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/pci/pci-armada8k.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/pci/pci-armada8k.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,38 @@
+* Marvell Armada 7K/8K PCIe interface
+
+This PCIe host controller is based on the Synopsis Designware PCIe IP
+and thus inherits all the common properties defined in designware-pcie.txt.
+
+Required properties:
+- compatible: "marvell,armada8k-pcie"
+- reg: must contain two register regions
+   - the control register region
+   - the config space region
+- reg-names:
+   - "ctrl" for the control register region
+   - "config" for the config space region
+- interrupts: Interrupt specifier for the PCIe controler
+- clocks: reference to the PCIe controller clock
+
+Example:
+
+	pcie@f2600000 {
+		compatible = "marvell,armada8k-pcie", "snps,dw-pcie";
+		reg = <0 0xf2600000 0 0x10000>, <0 0xf6f00000 0 0x80000>;
+		reg-names = "ctrl", "config";
+		#address-cells = <3>;
+		#size-cells = <2>;
+		#interrupt-cells = <1>;
+		device_type = "pci";
+		dma-coherent;
+
+		bus-range = <0 0xff>;
+		ranges = <0x81000000 0 0xf9000000 0  0xf9000000 0 0x10000	/* downstream I/O */
+			  0x82000000 0 0xf6000000 0  0xf6000000 0 0xf00000>;	/* non-prefetchable memory */
+		interrupt-map-mask = <0 0 0 0>;
+		interrupt-map = <0 0 0 0 &gic 0 GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+		num-lanes = <1>;
+		clocks = <&cpm_syscon0 1 13>;
+		status = "disabled";
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/pci/pci-keystone.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/pci/pci-keystone.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/pci/pci-keystone.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/pci/pci-keystone.txt	2016-07-24 15:23:50.000000000 -0400
@@ -56,6 +56,7 @@ Optional properties:-
 	phy-names: name of the Generic Keystine SerDes phy for PCI
 	  - If boot loader already does PCI link establishment, then phys and
 	    phy-names shouldn't be present.
+	interrupts: platform interrupt for error interrupts.
 
 Designware DT Properties not applicable for Keystone PCI
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/phy/bcm-ns-usb2-phy.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/phy/bcm-ns-usb2-phy.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/phy/bcm-ns-usb2-phy.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/phy/bcm-ns-usb2-phy.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,21 @@
+Driver for Broadcom Northstar USB 2.0 PHY
+
+Required properties:
+- compatible: brcm,ns-usb2-phy
+- reg: iomem address range of DMU (Device Management Unit)
+- reg-names: "dmu", the only needed & supported reg right now
+- clocks: USB PHY reference clock
+- clock-names: "phy-ref-clk", the only needed & supported clock right now
+
+To initialize USB 2.0 PHY driver needs to setup PLL correctly. To do this it
+requires passing phandle to the USB PHY reference clock.
+
+Example:
+	usb2-phy {
+		compatible = "brcm,ns-usb2-phy";
+		reg = <0x1800c000 0x1000>;
+		reg-names = "dmu";
+		#phy-cells = <0>;
+		clocks = <&genpll BCM_NSP_GENPLL_USB_PHY_REF_CLK>;
+		clock-names = "phy-ref-clk";
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/phy/brcm,brcmstb-sata-phy.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/phy/brcm,brcmstb-sata-phy.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/phy/brcm,brcmstb-sata-phy.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/phy/brcm,brcmstb-sata-phy.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,41 +0,0 @@
-* Broadcom SATA3 PHY for STB
-
-Required properties:
-- compatible: should be one or more of
-     "brcm,bcm7425-sata-phy"
-     "brcm,bcm7445-sata-phy"
-     "brcm,phy-sata3"
-- address-cells: should be 1
-- size-cells: should be 0
-- reg: register range for the PHY PCB interface
-- reg-names: should be "phy"
-
-Sub-nodes:
-  Each port's PHY should be represented as a sub-node.
-
-Sub-nodes required properties:
-- reg: the PHY number
-- phy-cells: generic PHY binding; must be 0
-Optional:
-- brcm,enable-ssc: use spread spectrum clocking (SSC) on this port
-
-
-Example:
-
-	sata-phy@f0458100 {
-		compatible = "brcm,bcm7445-sata-phy", "brcm,phy-sata3";
-		reg = <0xf0458100 0x1e00>, <0xf045804c 0x10>;
-		reg-names = "phy";
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		sata-phy@0 {
-			reg = <0>;
-			#phy-cells = <0>;
-		};
-
-		sata-phy@1 {
-			reg = <1>;
-			#phy-cells = <0>;
-		};
-	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/phy/brcm-sata-phy.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/phy/brcm-sata-phy.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/phy/brcm-sata-phy.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/phy/brcm-sata-phy.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,44 @@
+* Broadcom SATA3 PHY
+
+Required properties:
+- compatible: should be one or more of
+     "brcm,bcm7425-sata-phy"
+     "brcm,bcm7445-sata-phy"
+     "brcm,iproc-ns2-sata-phy"
+     "brcm,phy-sata3"
+- address-cells: should be 1
+- size-cells: should be 0
+- reg: register ranges for the PHY PCB interface
+- reg-names: should be "phy" and "phy-ctrl"
+     The "phy-ctrl" registers are only required for
+     "brcm,iproc-ns2-sata-phy".
+
+Sub-nodes:
+  Each port's PHY should be represented as a sub-node.
+
+Sub-nodes required properties:
+- reg: the PHY number
+- phy-cells: generic PHY binding; must be 0
+
+Sub-nodes optional properties:
+- brcm,enable-ssc: use spread spectrum clocking (SSC) on this port
+     This property is not applicable for "brcm,iproc-ns2-sata-phy".
+
+Example:
+	sata-phy@f0458100 {
+		compatible = "brcm,bcm7445-sata-phy", "brcm,phy-sata3";
+		reg = <0xf0458100 0x1e00>, <0xf045804c 0x10>;
+		reg-names = "phy";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		sata-phy@0 {
+			reg = <0>;
+			#phy-cells = <0>;
+		};
+
+		sata-phy@1 {
+			reg = <1>;
+			#phy-cells = <0>;
+		};
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/phy/nvidia,tegra124-xusb-padctl.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,733 @@
+Device tree binding for NVIDIA Tegra XUSB pad controller
+========================================================
+
+The Tegra XUSB pad controller manages a set of I/O lanes (with differential
+signals) which connect directly to pins/pads on the SoC package. Each lane
+is controlled by a HW block referred to as a "pad" in the Tegra hardware
+documentation. Each such "pad" may control either one or multiple lanes,
+and thus contains any logic common to all its lanes. Each lane can be
+separately configured and powered up.
+
+Some of the lanes are high-speed lanes, which can be used for PCIe, SATA or
+super-speed USB. Other lanes are for various types of low-speed, full-speed
+or high-speed USB (such as UTMI, ULPI and HSIC). The XUSB pad controller
+contains a software-configurable mux that sits between the I/O controller
+ports (e.g. PCIe) and the lanes.
+
+In addition to per-lane configuration, USB 3.0 ports may require additional
+settings on a per-board basis.
+
+Pads will be represented as children of the top-level XUSB pad controller
+device tree node. Each lane exposed by the pad will be represented by its
+own subnode and can be referenced by users of the lane using the standard
+PHY bindings, as described by the phy-bindings.txt file in this directory.
+
+The Tegra hardware documentation refers to the connection between the XUSB
+pad controller and the XUSB controller as "ports". This is confusing since
+"port" is typically used to denote the physical USB receptacle. The device
+tree binding in this document uses the term "port" to refer to the logical
+abstraction of the signals that are routed to a USB receptacle (i.e. a PHY
+for the USB signal, the VBUS power supply, the USB 2.0 companion port for
+USB 3.0 receptacles, ...).
+
+Required properties:
+--------------------
+- compatible: Must be:
+  - Tegra124: "nvidia,tegra124-xusb-padctl"
+  - Tegra132: "nvidia,tegra132-xusb-padctl", "nvidia,tegra124-xusb-padctl"
+  - Tegra210: "nvidia,tegra210-xusb-padctl"
+- reg: Physical base address and length of the controller's registers.
+- resets: Must contain an entry for each entry in reset-names.
+- reset-names: Must include the following entries:
+  - "padctl"
+
+
+Pad nodes:
+==========
+
+A required child node named "pads" contains a list of subnodes, one for each
+of the pads exposed by the XUSB pad controller. Each pad may need additional
+resources that can be referenced in its pad node.
+
+The "status" property is used to enable or disable the use of a pad. If set
+to "disabled", the pad will not be used on the given board. In order to use
+the pad and any of its lanes, this property must be set to "okay".
+
+For Tegra124 and Tegra132, the following pads exist: usb2, ulpi, hsic, pcie
+and sata. No extra resources are required for operation of these pads.
+
+For Tegra210, the following pads exist: usb2, hsic, pcie and sata. Below is
+a description of the properties of each pad.
+
+UTMI pad:
+---------
+
+Required properties:
+- clocks: Must contain an entry for each entry in clock-names.
+- clock-names: Must contain the following entries:
+  - "trk": phandle and specifier referring to the USB2 tracking clock
+
+HSIC pad:
+---------
+
+Required properties:
+- clocks: Must contain an entry for each entry in clock-names.
+- clock-names: Must contain the following entries:
+  - "trk": phandle and specifier referring to the HSIC tracking clock
+
+PCIe pad:
+---------
+
+Required properties:
+- clocks: Must contain an entry for each entry in clock-names.
+- clock-names: Must contain the following entries:
+  - "pll": phandle and specifier referring to the PLLE
+- resets: Must contain an entry for each entry in reset-names.
+- reset-names: Must contain the following entries:
+  - "phy": reset for the PCIe UPHY block
+
+SATA pad:
+---------
+
+Required properties:
+- resets: Must contain an entry for each entry in reset-names.
+- reset-names: Must contain the following entries:
+  - "phy": reset for the SATA UPHY block
+
+
+PHY nodes:
+==========
+
+Each pad node has a child named "lanes" that contains one or more children of
+its own, each representing one of the lanes controlled by the pad.
+
+Required properties:
+--------------------
+- status: Defines the operation status of the PHY. Valid values are:
+  - "disabled": the PHY is disabled
+  - "okay": the PHY is enabled
+- #phy-cells: Should be 0. Since each lane represents a single PHY, there is
+  no need for an additional specifier.
+- nvidia,function: The output function of the PHY. See below for a list of
+  valid functions per SoC generation.
+
+For Tegra124 and Tegra132, the list of valid PHY nodes is given below:
+- usb2: usb2-0, usb2-1, usb2-2
+  - functions: "snps", "xusb", "uart"
+- ulpi: ulpi-0
+  - functions: "snps", "xusb"
+- hsic: hsic-0, hsic-1
+  - functions: "snps", "xusb"
+- pcie: pcie-0, pcie-1, pcie-2, pcie-3, pcie-4
+  - functions: "pcie", "usb3-ss"
+- sata: sata-0
+  - functions: "usb3-ss", "sata"
+
+For Tegra210, the list of valid PHY nodes is given below:
+- utmi: utmi-0, utmi-1, utmi-2, utmi-3
+  - functions: "snps", "xusb", "uart"
+- hsic: hsic-0, hsic-1
+  - functions: "snps", "xusb"
+- pcie: pcie-0, pcie-1, pcie-2, pcie-3, pcie-4, pcie-5, pcie-6
+  - functions: "pcie-x1", "usb3-ss", "pcie-x4"
+- sata: sata-0
+  - functions: "usb3-ss", "sata"
+
+
+Port nodes:
+===========
+
+A required child node named "ports" contains a list of all the ports exposed
+by the XUSB pad controller. Per-port configuration is only required for USB.
+
+USB2 ports:
+-----------
+
+Required properties:
+- status: Defines the operation status of the port. Valid values are:
+  - "disabled": the port is disabled
+  - "okay": the port is enabled
+- mode: A string that determines the mode in which to run the port. Valid
+  values are:
+  - "host": for USB host mode
+  - "device": for USB device mode
+  - "otg": for USB OTG mode
+
+Optional properties:
+- nvidia,internal: A boolean property whose presence determines that a port
+  is internal. In the absence of this property the port is considered to be
+  external.
+- vbus-supply: phandle to a regulator supplying the VBUS voltage.
+
+ULPI ports:
+-----------
+
+Optional properties:
+- status: Defines the operation status of the port. Valid values are:
+  - "disabled": the port is disabled
+  - "okay": the port is enabled
+- nvidia,internal: A boolean property whose presence determines that a port
+  is internal. In the absence of this property the port is considered to be
+  external.
+- vbus-supply: phandle to a regulator supplying the VBUS voltage.
+
+HSIC ports:
+-----------
+
+Required properties:
+- status: Defines the operation status of the port. Valid values are:
+  - "disabled": the port is disabled
+  - "okay": the port is enabled
+
+Optional properties:
+- vbus-supply: phandle to a regulator supplying the VBUS voltage.
+
+Super-speed USB ports:
+----------------------
+
+Required properties:
+- status: Defines the operation status of the port. Valid values are:
+  - "disabled": the port is disabled
+  - "okay": the port is enabled
+- nvidia,usb2-companion: A single cell that specifies the physical port number
+  to map this super-speed USB port to. The range of valid port numbers varies
+  with the SoC generation:
+  - 0-2: for Tegra124 and Tegra132
+  - 0-3: for Tegra210
+
+Optional properties:
+- nvidia,internal: A boolean property whose presence determines that a port
+  is internal. In the absence of this property the port is considered to be
+  external.
+
+For Tegra124 and Tegra132, the XUSB pad controller exposes the following
+ports:
+- 3x USB2: usb2-0, usb2-1, usb2-2
+- 1x ULPI: ulpi-0
+- 2x HSIC: hsic-0, hsic-1
+- 2x super-speed USB: usb3-0, usb3-1
+
+For Tegra210, the XUSB pad controller exposes the following ports:
+- 4x USB2: usb2-0, usb2-1, usb2-2, usb2-3
+- 2x HSIC: hsic-0, hsic-1
+- 4x super-speed USB: usb3-0, usb3-1, usb3-2, usb3-3
+
+
+Examples:
+=========
+
+Tegra124 and Tegra132:
+----------------------
+
+SoC include:
+
+	padctl@7009f000 {
+		/* for Tegra124 */
+		compatible = "nvidia,tegra124-xusb-padctl";
+		/* for Tegra132 */
+		compatible = "nvidia,tegra132-xusb-padctl",
+			     "nvidia,tegra124-xusb-padctl";
+		reg = <0x0 0x7009f000 0x0 0x1000>;
+		resets = <&tegra_car 142>;
+		reset-names = "padctl";
+
+		pads {
+			usb2 {
+				status = "disabled";
+
+				lanes {
+					usb2-0 {
+						status = "disabled";
+						#phy-cells = <0>;
+					};
+
+					usb2-1 {
+						status = "disabled";
+						#phy-cells = <0>;
+					};
+
+					usb2-2 {
+						status = "disabled";
+						#phy-cells = <0>;
+					};
+				};
+			};
+
+			ulpi {
+				status = "disabled";
+
+				lanes {
+					ulpi-0 {
+						status = "disabled";
+						#phy-cells = <0>;
+					};
+				};
+			};
+
+			hsic {
+				status = "disabled";
+
+				lanes {
+					hsic-0 {
+						status = "disabled";
+						#phy-cells = <0>;
+					};
+
+					hsic-1 {
+						status = "disabled";
+						#phy-cells = <0>;
+					};
+				};
+			};
+
+			pcie {
+				status = "disabled";
+
+				lanes {
+					pcie-0 {
+						status = "disabled";
+						#phy-cells = <0>;
+					};
+
+					pcie-1 {
+						status = "disabled";
+						#phy-cells = <0>;
+					};
+
+					pcie-2 {
+						status = "disabled";
+						#phy-cells = <0>;
+					};
+
+					pcie-3 {
+						status = "disabled";
+						#phy-cells = <0>;
+					};
+
+					pcie-4 {
+						status = "disabled";
+						#phy-cells = <0>;
+					};
+				};
+			};
+
+			sata {
+				status = "disabled";
+
+				lanes {
+					sata-0 {
+						status = "disabled";
+						#phy-cells = <0>;
+					};
+				};
+			};
+		};
+
+		ports {
+			usb2-0 {
+				status = "disabled";
+			};
+
+			usb2-1 {
+				status = "disabled";
+			};
+
+			usb2-2 {
+				status = "disabled";
+			};
+
+			ulpi-0 {
+				status = "disabled";
+			};
+
+			hsic-0 {
+				status = "disabled";
+			};
+
+			hsic-1 {
+				status = "disabled";
+			};
+
+			usb3-0 {
+				status = "disabled";
+			};
+
+			usb3-1 {
+				status = "disabled";
+			};
+		};
+	};
+
+Board file:
+
+	padctl@7009f000 {
+		status = "okay";
+
+		pads {
+			usb2 {
+				status = "okay";
+
+				lanes {
+					usb2-0 {
+						nvidia,function = "xusb";
+						status = "okay";
+					};
+
+					usb2-1 {
+						nvidia,function = "xusb";
+						status = "okay";
+					};
+
+					usb2-2 {
+						nvidia,function = "xusb";
+						status = "okay";
+					};
+				};
+			};
+
+			pcie {
+				status = "okay";
+
+				lanes {
+					pcie-0 {
+						nvidia,function = "usb3-ss";
+						status = "okay";
+					};
+
+					pcie-2 {
+						nvidia,function = "pcie";
+						status = "okay";
+					};
+
+					pcie-4 {
+						nvidia,function = "pcie";
+						status = "okay";
+					};
+				};
+			};
+
+			sata {
+				status = "okay";
+
+				lanes {
+					sata-0 {
+						nvidia,function = "sata";
+						status = "okay";
+					};
+				};
+			};
+		};
+
+		ports {
+			/* Micro A/B */
+			usb2-0 {
+				status = "okay";
+				mode = "otg";
+			};
+
+			/* Mini PCIe */
+			usb2-1 {
+				status = "okay";
+				mode = "host";
+			};
+
+			/* USB3 */
+			usb2-2 {
+				status = "okay";
+				mode = "host";
+
+				vbus-supply = <&vdd_usb3_vbus>;
+			};
+
+			usb3-0 {
+				nvidia,port = <2>;
+				status = "okay";
+			};
+		};
+	};
+
+Tegra210:
+---------
+
+SoC include:
+
+	padctl@7009f000 {
+		compatible = "nvidia,tegra210-xusb-padctl";
+		reg = <0x0 0x7009f000 0x0 0x1000>;
+		resets = <&tegra_car 142>;
+		reset-names = "padctl";
+
+		status = "disabled";
+
+		pads {
+			usb2 {
+				clocks = <&tegra_car TEGRA210_CLK_USB2_TRK>;
+				clock-names = "trk";
+				status = "disabled";
+
+				lanes {
+					usb2-0 {
+						status = "disabled";
+						#phy-cells = <0>;
+					};
+
+					usb2-1 {
+						status = "disabled";
+						#phy-cells = <0>;
+					};
+
+					usb2-2 {
+						status = "disabled";
+						#phy-cells = <0>;
+					};
+
+					usb2-3 {
+						status = "disabled";
+						#phy-cells = <0>;
+					};
+				};
+			};
+
+			hsic {
+				clocks = <&tegra_car TEGRA210_CLK_HSIC_TRK>;
+				clock-names = "trk";
+				status = "disabled";
+
+				lanes {
+					hsic-0 {
+						status = "disabled";
+						#phy-cells = <0>;
+					};
+
+					hsic-1 {
+						status = "disabled";
+						#phy-cells = <0>;
+					};
+				};
+			};
+
+			pcie {
+				clocks = <&tegra_car TEGRA210_CLK_PLL_E>;
+				clock-names = "pll";
+				resets = <&tegra_car 205>;
+				reset-names = "phy";
+				status = "disabled";
+
+				lanes {
+					pcie-0 {
+						status = "disabled";
+						#phy-cells = <0>;
+					};
+
+					pcie-1 {
+						status = "disabled";
+						#phy-cells = <0>;
+					};
+
+					pcie-2 {
+						status = "disabled";
+						#phy-cells = <0>;
+					};
+
+					pcie-3 {
+						status = "disabled";
+						#phy-cells = <0>;
+					};
+
+					pcie-4 {
+						status = "disabled";
+						#phy-cells = <0>;
+					};
+
+					pcie-5 {
+						status = "disabled";
+						#phy-cells = <0>;
+					};
+
+					pcie-6 {
+						status = "disabled";
+						#phy-cells = <0>;
+					};
+				};
+			};
+
+			sata {
+				clocks = <&tegra_car TEGRA210_CLK_PLL_E>;
+				clock-names = "pll";
+				resets = <&tegra_car 204>;
+				reset-names = "phy";
+				status = "disabled";
+
+				lanes {
+					sata-0 {
+						status = "disabled";
+						#phy-cells = <0>;
+					};
+				};
+			};
+		};
+
+		ports {
+			usb2-0 {
+				status = "disabled";
+			};
+
+			usb2-1 {
+				status = "disabled";
+			};
+
+			usb2-2 {
+				status = "disabled";
+			};
+
+			usb2-3 {
+				status = "disabled";
+			};
+
+			hsic-0 {
+				status = "disabled";
+			};
+
+			hsic-1 {
+				status = "disabled";
+			};
+
+			usb3-0 {
+				status = "disabled";
+			};
+
+			usb3-1 {
+				status = "disabled";
+			};
+
+			usb3-2 {
+				status = "disabled";
+			};
+
+			usb3-3 {
+				status = "disabled";
+			};
+		};
+	};
+
+Board file:
+
+	padctl@7009f000 {
+		status = "okay";
+
+		pads {
+			usb2 {
+				status = "okay";
+
+				lanes {
+					usb2-0 {
+						nvidia,function = "xusb";
+						status = "okay";
+					};
+
+					usb2-1 {
+						nvidia,function = "xusb";
+						status = "okay";
+					};
+
+					usb2-2 {
+						nvidia,function = "xusb";
+						status = "okay";
+					};
+
+					usb2-3 {
+						nvidia,function = "xusb";
+						status = "okay";
+					};
+				};
+			};
+
+			pcie {
+				status = "okay";
+
+				lanes {
+					pcie-0 {
+						nvidia,function = "pcie-x1";
+						status = "okay";
+					};
+
+					pcie-1 {
+						nvidia,function = "pcie-x4";
+						status = "okay";
+					};
+
+					pcie-2 {
+						nvidia,function = "pcie-x4";
+						status = "okay";
+					};
+
+					pcie-3 {
+						nvidia,function = "pcie-x4";
+						status = "okay";
+					};
+
+					pcie-4 {
+						nvidia,function = "pcie-x4";
+						status = "okay";
+					};
+
+					pcie-5 {
+						nvidia,function = "usb3-ss";
+						status = "okay";
+					};
+
+					pcie-6 {
+						nvidia,function = "usb3-ss";
+						status = "okay";
+					};
+				};
+			};
+
+			sata {
+				status = "okay";
+
+				lanes {
+					sata-0 {
+						nvidia,function = "sata";
+						status = "okay";
+					};
+				};
+			};
+		};
+
+		ports {
+			usb2-0 {
+				status = "okay";
+				mode = "otg";
+			};
+
+			usb2-1 {
+				status = "okay";
+				vbus-supply = <&vdd_5v0_rtl>;
+				mode = "host";
+			};
+
+			usb2-2 {
+				status = "okay";
+				vbus-supply = <&vdd_usb_vbus>;
+				mode = "host";
+			};
+
+			usb2-3 {
+				status = "okay";
+				mode = "host";
+			};
+
+			usb3-0 {
+				status = "okay";
+				nvidia,lanes = "pcie-6";
+				nvidia,port = <1>;
+			};
+
+			usb3-1 {
+				status = "okay";
+				nvidia,lanes = "pcie-5";
+				nvidia,port = <2>;
+			};
+		};
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/phy/phy-lpc18xx-usb-otg.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/phy/phy-lpc18xx-usb-otg.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/phy/phy-lpc18xx-usb-otg.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/phy/phy-lpc18xx-usb-otg.txt	2016-07-24 15:23:50.000000000 -0400
@@ -18,7 +18,7 @@ creg: syscon@40043000 {
 	compatible = "nxp,lpc1850-creg", "syscon", "simple-mfd";
 	reg = <0x40043000 0x1000>;
 
-	usb0_otg_phy: phy@004 {
+	usb0_otg_phy: phy {
 		compatible = "nxp,lpc1850-usb-otg-phy";
 		clocks = <&ccu1 CLK_USB0>;
 		#phy-cells = <0>;
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/phy/phy-mt65xx-usb.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/phy/phy-mt65xx-usb.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/phy/phy-mt65xx-usb.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/phy/phy-mt65xx-usb.txt	2016-07-24 15:23:50.000000000 -0400
@@ -4,7 +4,9 @@ mt65xx USB3.0 PHY binding
 This binding describes a usb3.0 phy for mt65xx platforms of Medaitek SoC.
 
 Required properties (controller (parent) node):
- - compatible	: should be "mediatek,mt8173-u3phy"
+ - compatible	: should be one of
+		  "mediatek,mt2701-u3phy"
+		  "mediatek,mt8173-u3phy"
  - reg		: offset and length of register for phy, exclude port's
 		  register.
  - clocks	: a list of phandle + clock-specifier pairs, one for each
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/phy/phy-stih41x-usb.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/phy/phy-stih41x-usb.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/phy/phy-stih41x-usb.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/phy/phy-stih41x-usb.txt	2016-07-24 15:23:50.000000000 -0400
@@ -17,7 +17,7 @@ Example:
 
 usb2_phy: usb2phy@0 {
 	compatible	= "st,stih416-usb-phy";
-	#phy-cell	= <0>;
+	#phy-cells	= <0>;
 	st,syscfg	= <&syscfg_rear>;
 	clocks		= <&clk_sysin>;
 	clock-names	= "osc_phy";
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/phy/rcar-gen2-phy.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/phy/rcar-gen2-phy.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/phy/rcar-gen2-phy.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/phy/rcar-gen2-phy.txt	2016-07-24 15:23:50.000000000 -0400
@@ -7,6 +7,12 @@ Required properties:
 - compatible: "renesas,usb-phy-r8a7790" if the device is a part of R8A7790 SoC.
 	      "renesas,usb-phy-r8a7791" if the device is a part of R8A7791 SoC.
 	      "renesas,usb-phy-r8a7794" if the device is a part of R8A7794 SoC.
+	      "renesas,rcar-gen2-usb-phy" for a generic R-Car Gen2 compatible device.
+
+	      When compatible with the generic version, nodes must list the
+	      SoC-specific version corresponding to the platform first
+	      followed by the generic version.
+
 - reg: offset and length of the register block.
 - #address-cells: number of address cells for the USB channel subnodes, must
 		  be <1>.
@@ -34,7 +40,7 @@ the USB channel; see the selector meanin
 Example (Lager board):
 
 	usb-phy@e6590100 {
-		compatible = "renesas,usb-phy-r8a7790";
+		compatible = "renesas,usb-phy-r8a7790", "renesas,rcar-gen2-usb-phy";
 		reg = <0 0xe6590100 0 0x100>;
 		#address-cells = <1>;
 		#size-cells = <0>;
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/phy/rcar-gen3-phy-usb2.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/phy/rcar-gen3-phy-usb2.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/phy/rcar-gen3-phy-usb2.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/phy/rcar-gen3-phy-usb2.txt	2016-07-24 15:23:50.000000000 -0400
@@ -6,6 +6,12 @@ This file provides information on what t
 Required properties:
 - compatible: "renesas,usb2-phy-r8a7795" if the device is a part of an R8A7795
 	      SoC.
+	      "renesas,rcar-gen3-usb2-phy" for a generic R-Car Gen3 compatible device.
+
+	      When compatible with the generic version, nodes must list the
+	      SoC-specific version corresponding to the platform first
+	      followed by the generic version.
+
 - reg: offset and length of the partial USB 2.0 Host register block.
 - clocks: clock phandle and specifier pair(s).
 - #phy-cells: see phy-bindings.txt in the same directory, must be <0>.
@@ -15,18 +21,20 @@ To use a USB channel where USB 2.0 Host
 combined, the device tree node should set interrupt properties to use the
 channel as USB OTG:
 - interrupts: interrupt specifier for the PHY.
+- vbus-supply: Phandle to a regulator that provides power to the VBUS. This
+	       regulator will be managed during the PHY power on/off sequence.
 
 Example (R-Car H3):
 
 	usb-phy@ee080200 {
-		compatible = "renesas,usb2-phy-r8a7795";
+		compatible = "renesas,usb2-phy-r8a7795", "renesas,rcar-gen3-usb2-phy";
 		reg = <0 0xee080200 0 0x700>;
 		interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp7_clks R8A7795_CLK_EHCI0>;
 	};
 
 	usb-phy@ee0a0200 {
-		compatible = "renesas,usb2-phy-r8a7795";
+		compatible = "renesas,usb2-phy-r8a7795", "renesas,rcar-gen3-usb2-phy";
 		reg = <0 0xee0a0200 0 0x700>;
 		clocks = <&mstp7_clks R8A7795_CLK_EHCI0>;
 	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/phy/samsung-phy.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/phy/samsung-phy.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/phy/samsung-phy.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/phy/samsung-phy.txt	2016-07-24 15:23:50.000000000 -0400
@@ -2,9 +2,20 @@ Samsung S5P/EXYNOS SoC series MIPI CSIS/
 -------------------------------------------------
 
 Required properties:
-- compatible : should be "samsung,s5pv210-mipi-video-phy";
+- compatible : should be one of the listed compatibles:
+	- "samsung,s5pv210-mipi-video-phy"
+	- "samsung,exynos5420-mipi-video-phy"
+	- "samsung,exynos5433-mipi-video-phy"
 - #phy-cells : from the generic phy bindings, must be 1;
-- syscon - phandle to the PMU system controller;
+
+In case of s5pv210 and exynos5420 compatible PHYs:
+- syscon - phandle to the PMU system controller
+
+In case of exynos5433 compatible PHY:
+ - samsung,pmu-syscon - phandle to the PMU system controller
+ - samsung,disp-sysreg - phandle to the DISP system registers controller
+ - samsung,cam0-sysreg - phandle to the CAM0 system registers controller
+ - samsung,cam1-sysreg - phandle to the CAM1 system registers controller
 
 For "samsung,s5pv210-mipi-video-phy" compatible PHYs the second cell in
 the PHY specifier identifies the PHY and its meaning is as follows:
@@ -12,6 +23,9 @@ the PHY specifier identifies the PHY and
   1 - MIPI DSIM 0,
   2 - MIPI CSIS 1,
   3 - MIPI DSIM 1.
+"samsung,exynos5420-mipi-video-phy" and "samsung,exynos5433-mipi-video-phy"
+supports additional fifth PHY:
+  4 - MIPI CSIS 2.
 
 Samsung EXYNOS SoC series Display Port PHY
 -------------------------------------------------
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/pinctrl/microchip,pic32-pinctrl.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/pinctrl/microchip,pic32-pinctrl.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/pinctrl/microchip,pic32-pinctrl.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/pinctrl/microchip,pic32-pinctrl.txt	2016-07-24 15:23:50.000000000 -0400
@@ -34,7 +34,7 @@ pic32_pinctrl: pinctrl@1f801400{
 	#size-cells = <1>;
 	compatible = "microchip,pic32mzda-pinctrl";
 	reg = <0x1f801400 0x400>;
-	clocks = <&PBCLK1>;
+	clocks = <&rootclk PB1CLK>;
 
 	pinctrl_uart2: pinctrl_uart2 {
 		uart2-tx {
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt	2016-07-24 15:23:50.000000000 -0400
@@ -1,6 +1,12 @@
 Device tree binding for NVIDIA Tegra XUSB pad controller
 ========================================================
 
+NOTE: It turns out that this binding isn't an accurate description of the XUSB
+pad controller. While the description is good enough for the functional subset
+required for PCIe and SATA, it lacks the flexibility to represent the features
+needed for USB. For the new binding, see ../phy/nvidia,tegra-xusb-padctl.txt.
+The binding described in this file is deprecated and should not be used.
+
 The Tegra XUSB pad controller manages a set of lanes, each of which can be
 assigned to one out of a set of different pads. Some of these pads have an
 associated PHY that must be powered up before the pad can be used.
@@ -79,7 +85,7 @@ Example:
 SoC file extract:
 -----------------
 
-	padctl@0,7009f000 {
+	padctl@7009f000 {
 		compatible = "nvidia,tegra124-xusb-padctl";
 		reg = <0x0 0x7009f000 0x0 0x1000>;
 		resets = <&tegra_car 142>;
@@ -91,7 +97,7 @@ SoC file extract:
 Board file extract:
 -------------------
 
-	pcie-controller@0,01003000 {
+	pcie-controller@01003000 {
 		...
 
 		phys = <&padctl 0>;
@@ -102,7 +108,7 @@ Board file extract:
 
 	...
 
-	padctl: padctl@0,7009f000 {
+	padctl: padctl@7009f000 {
 		pinctrl-0 = <&padctl_default>;
 		pinctrl-names = "default";
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.txt	2016-07-24 15:23:50.000000000 -0400
@@ -122,7 +122,7 @@ to specify in a pin configuration subnod
 		    2: 1.5uA                    (PMIC_GPIO_PULL_UP_1P5)
 		    3: 31.5uA                   (PMIC_GPIO_PULL_UP_31P5)
 		    4: 1.5uA + 30uA boost       (PMIC_GPIO_PULL_UP_1P5_30)
-		    If this property is ommited 30uA strength will be used if
+		    If this property is omitted 30uA strength will be used if
 		    pull up is selected
 
 - bias-high-impedance:
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/pinctrl/renesas,pfc-pinctrl.txt	2016-07-24 15:23:50.000000000 -0400
@@ -72,8 +72,8 @@ Pin Configuration Node Properties:
 
 The pin configuration parameters use the generic pinconf bindings defined in
 pinctrl-bindings.txt in this directory. The supported parameters are
-bias-disable, bias-pull-up, bias-pull-down and power-source. For pins that
-have a configurable I/O voltage, the power-source value should be the
+bias-disable, bias-pull-up, bias-pull-down, drive strength and power-source. For
+pins that have a configurable I/O voltage, the power-source value should be the
 nominal I/O voltage in millivolts.
 
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/power/qcom,coincell-charger.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/power/qcom,coincell-charger.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/power/qcom,coincell-charger.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/power/qcom,coincell-charger.txt	2016-07-24 15:23:50.000000000 -0400
@@ -29,7 +29,7 @@ IC (PMIC)
 - qcom,charger-disable:
 	Usage: optional
 	Value type: <boolean>
-	Definition: definining this property disables charging
+	Definition: defining this property disables charging
 
 This charger is a sub-node of one of the 8941 PMIC blocks, and is specified
 as a child node in DTS of that node.  See ../mfd/qcom,spmi-pmic.txt and
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,48 @@
+DT bindings for the Renesas R-Car System Controller
+
+== System Controller Node ==
+
+The R-Car System Controller provides power management for the CPU cores and
+various coprocessors.
+
+Required properties:
+  - compatible: Must contain exactly one of the following:
+      - "renesas,r8a7779-sysc" (R-Car H1)
+      - "renesas,r8a7790-sysc" (R-Car H2)
+      - "renesas,r8a7791-sysc" (R-Car M2-W)
+      - "renesas,r8a7792-sysc" (R-Car V2H)
+      - "renesas,r8a7793-sysc" (R-Car M2-N)
+      - "renesas,r8a7794-sysc" (R-Car E2)
+      - "renesas,r8a7795-sysc" (R-Car H3)
+  - reg: Address start and address range for the device.
+  - #power-domain-cells: Must be 1.
+
+
+Example:
+
+	sysc: system-controller@e6180000 {
+		compatible = "renesas,r8a7791-sysc";
+		reg = <0 0xe6180000 0 0x0200>;
+		#power-domain-cells = <1>;
+	};
+
+
+== PM Domain Consumers ==
+
+Devices residing in a power area must refer to that power area, as documented
+by the generic PM domain bindings in
+Documentation/devicetree/bindings/power/power_domain.txt.
+
+Required properties:
+  - power-domains: A phandle and symbolic PM domain specifier, as defined in
+		   <dt-bindings/power/r8a77*-sysc.h>.
+
+
+Example:
+
+	L2_CA15: cache-controller@0 {
+		compatible = "cache";
+		power-domains = <&sysc R8A7791_PD_CA15_SCU>;
+		cache-unified;
+		cache-level = <2>;
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/power/reset/gpio-poweroff.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/power/reset/gpio-poweroff.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/power/reset/gpio-poweroff.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/power/reset/gpio-poweroff.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,36 @@
+Driver a GPIO line that can be used to turn the power off.
+
+The driver supports both level triggered and edge triggered power off.
+At driver load time, the driver will request the given gpio line and
+install a pm_power_off handler. If the optional properties 'input' is
+not found, the GPIO line will be driven in the inactive
+state. Otherwise its configured as an input.
+
+When the pm_power_off is called, the gpio is configured as an output,
+and drive active, so triggering a level triggered power off
+condition. This will also cause an inactive->active edge condition, so
+triggering positive edge triggered power off. After a delay of 100ms,
+the GPIO is set to inactive, thus causing an active->inactive edge,
+triggering negative edge triggered power off. After another 100ms
+delay the GPIO is driver active again. If the power is still on and
+the CPU still running after a 3000ms delay, a WARN_ON(1) is emitted.
+
+Required properties:
+- compatible : should be "gpio-poweroff".
+- gpios : The GPIO to set high/low, see "gpios property" in
+  Documentation/devicetree/bindings/gpio/gpio.txt. If the pin should be
+  low to power down the board set it to "Active Low", otherwise set
+  gpio to "Active High".
+
+Optional properties:
+- input : Initially configure the GPIO line as an input. Only reconfigure
+  it to an output when the pm_power_off function is called. If this optional
+  property is not specified, the GPIO is initialized as an output in its
+  inactive state.
+
+Examples:
+
+gpio-poweroff {
+	compatible = "gpio-poweroff";
+	gpios = <&gpio 4 0>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/power/reset/gpio-restart.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/power/reset/gpio-restart.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/power/reset/gpio-restart.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/power/reset/gpio-restart.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,54 @@
+Drive a GPIO line that can be used to restart the system from a restart
+handler.
+
+This binding supports level and edge triggered reset.  At driver load
+time, the driver will request the given gpio line and install a restart
+handler. If the optional properties 'open-source' is not found, the GPIO line
+will be driven in the inactive state.  Otherwise its not driven until
+the restart is initiated.
+
+When the system is restarted, the restart handler will be invoked in
+priority order.  The gpio is configured as an output, and driven active,
+triggering a level triggered reset condition. This will also cause an
+inactive->active edge condition, triggering positive edge triggered
+reset. After a delay specified by active-delay, the GPIO is set to
+inactive, thus causing an active->inactive edge, triggering negative edge
+triggered reset. After a delay specified by inactive-delay, the GPIO
+is driven active again.  After a delay specified by wait-delay, the
+restart handler completes allowing other restart handlers to be attempted.
+
+Required properties:
+- compatible : should be "gpio-restart".
+- gpios : The GPIO to set high/low, see "gpios property" in
+  Documentation/devicetree/bindings/gpio/gpio.txt. If the pin should be
+  low to reset the board set it to "Active Low", otherwise set
+  gpio to "Active High".
+
+Optional properties:
+- open-source : Treat the GPIO as being open source and defer driving
+  it to when the restart is initiated.  If this optional property is not
+  specified, the GPIO is initialized as an output in its inactive state.
+- priority : A priority ranging from 0 to 255 (default 128) according to
+  the following guidelines:
+	0:	Restart handler of last resort, with limited restart
+		capabilities
+	128:	Default restart handler; use if no other restart handler is
+		expected to be available, and/or if restart functionality is
+		sufficient to restart the entire system
+	255:	Highest priority restart handler, will preempt all other
+		restart handlers
+- active-delay: Delay (default 100) to wait after driving gpio active [ms]
+- inactive-delay: Delay (default 100) to wait after driving gpio inactive [ms]
+- wait-delay: Delay (default 3000) to wait after completing restart
+  sequence [ms]
+
+Examples:
+
+gpio-restart {
+	compatible = "gpio-restart";
+	gpios = <&gpio 4 0>;
+	priority = <128>;
+	active-delay = <100>;
+	inactive-delay = <100>;
+	wait-delay = <3000>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/power/rockchip-io-domain.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/power/rockchip-io-domain.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/power/rockchip-io-domain.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/power/rockchip-io-domain.txt	2016-07-24 15:23:50.000000000 -0400
@@ -37,8 +37,10 @@ Required properties:
   - "rockchip,rk3368-pmu-io-voltage-domain" for rk3368 pmu-domains
   - "rockchip,rk3399-io-voltage-domain" for rk3399
   - "rockchip,rk3399-pmu-io-voltage-domain" for rk3399 pmu-domains
-- rockchip,grf: phandle to the syscon managing the "general register files"
 
+Deprecated properties:
+- rockchip,grf: phandle to the syscon managing the "general register files"
+    Systems should move the io-domains to a sub-node of the grf simple-mfd.
 
 You specify supplies using the standard regulator bindings by including
 a phandle the relevant regulator.  All specified supplies must be able
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/regulator/max8973-regulator.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/regulator/max8973-regulator.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/regulator/max8973-regulator.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/regulator/max8973-regulator.txt	2016-07-24 15:23:50.000000000 -0400
@@ -32,6 +32,13 @@ Optional properties:
 
 Enhanced transient response (ETR) will affect the configuration of CKADV.
 
+-junction-warn-millicelsius: u32, junction warning temperature threshold
+		in millicelsius. If die temperature crosses this level then
+		device generates the warning interrupts.
+
+Please note that thermal functionality is only supported on MAX77621. The
+supported threshold warning temperature for MAX77621 are 120 degC and 140 degC.
+
 Example:
 
 	max8973@1b {
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/regulator/palmas-pmic.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/regulator/palmas-pmic.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/regulator/palmas-pmic.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/regulator/palmas-pmic.txt	2016-07-24 15:23:50.000000000 -0400
@@ -1,5 +1,12 @@
 * palmas regulator IP block devicetree bindings
 
+The tps659038 for the AM57x class have OTP spins that
+have different part numbers but the same functionality. There
+is not a need to add the OTP spins to the palmas driver. The
+spin devices should use the tps659038 as it's compatible value.
+This is the list of those devices:
+tps659037
+
 Required properties:
 - compatible : Should be from the list
   ti,twl6035-pmic
@@ -8,6 +15,7 @@ Required properties:
   ti,tps65913-pmic
   ti,tps65914-pmic
   ti,tps65917-pmic
+  ti,tps659038-pmic
 and also the generic series names
   ti,palmas-pmic
 - interrupt-parent : The parent interrupt controller which is palmas.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/regulator/pv88080.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/regulator/pv88080.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/regulator/pv88080.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/regulator/pv88080.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,49 @@
+* Powerventure Semiconductor PV88080 Voltage Regulator
+
+Required properties:
+- compatible: "pvs,pv88080".
+- reg: I2C slave address, usually 0x49.
+- interrupts: the interrupt outputs of the controller
+- regulators: A node that houses a sub-node for each regulator within the
+  device. Each sub-node is identified using the node's name, with valid
+  values listed below. The content of each sub-node is defined by the
+  standard binding for regulators; see regulator.txt.
+  BUCK1, BUCK2, and BUCK3.
+
+Optional properties:
+- Any optional property defined in regulator.txt
+
+Example
+
+	pmic: pv88080@49 {
+		compatible = "pvs,pv88080";
+		reg = <0x49>;
+		interrupt-parent = <&gpio>;
+		interrupts = <24 24>;
+
+		regulators {
+			BUCK1 {
+				regulator-name = "buck1";
+				regulator-min-microvolt = < 600000>;
+				regulator-max-microvolt = <1393750>;
+				regulator-min-microamp 	= < 220000>;
+				regulator-max-microamp 	= <7040000>;
+			};
+
+			BUCK2 {
+				regulator-name = "buck2";
+				regulator-min-microvolt = < 600000>;
+				regulator-max-microvolt = <1393750>;
+				regulator-min-microamp 	= <1496000>;
+				regulator-max-microamp 	= <4189000>;
+			};
+
+			BUCK3 {
+				regulator-name = "buck3";
+				regulator-min-microvolt = <1400000>;
+				regulator-max-microvolt = <2193750>;
+				regulator-min-microamp 	= <1496000>;
+				regulator-max-microamp 	= <4189000>;
+			};
+		};
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/regulator/qcom,spmi-regulator.txt	2016-07-24 15:23:50.000000000 -0400
@@ -7,6 +7,7 @@ Qualcomm SPMI Regulators
 			"qcom,pm8841-regulators"
 			"qcom,pm8916-regulators"
 			"qcom,pm8941-regulators"
+			"qcom,pm8994-regulators"
 
 - interrupts:
 	Usage: optional
@@ -68,6 +69,37 @@ Qualcomm SPMI Regulators
 	Definition: Reference to regulator supplying the input pin, as
 		    described in the data sheet.
 
+- vdd_s1-supply:
+- vdd_s2-supply:
+- vdd_s3-supply:
+- vdd_s4-supply:
+- vdd_s5-supply:
+- vdd_s6-supply:
+- vdd_s7-supply:
+- vdd_s8-supply:
+- vdd_s9-supply:
+- vdd_s10-supply:
+- vdd_s11-supply:
+- vdd_s12-supply:
+- vdd_l1-supply:
+- vdd_l2_l26_l28-supply:
+- vdd_l3_l11-supply:
+- vdd_l4_l27_l31-supply:
+- vdd_l5_l7-supply:
+- vdd_l6_l12_l32-supply:
+- vdd_l8_l16_l30-supply:
+- vdd_l9_l10_l18_l22-supply:
+- vdd_l13_l19_l23_l24-supply:
+- vdd_l14_l15-supply:
+- vdd_l17_l29-supply:
+- vdd_l20_l21-supply:
+- vdd_l25-supply:
+- vdd_lvs_1_2-supply:
+	Usage: optional (pm8994 only)
+	Value type: <phandle>
+	Definition: Reference to regulator supplying the input pin, as
+		    described in the data sheet.
+
 
 The regulator node houses sub-nodes for each regulator within the device. Each
 sub-node is identified using the node's name, with valid values listed for each
@@ -85,6 +117,11 @@ pm8941:
 	l15, l16, l17, l18, l19, l20, l21, l22, l23, l24, lvs1, lvs2, lvs3,
 	mvs1, mvs2
 
+pm8994:
+	s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, l1, l2, l3, l4, l5,
+	l6, l7, l8, l9, l10, l11, l12, l13, l14, l15, l16, l17, l18, l19, l20,
+	l21, l22, l23, l24, l25, l26, l27, l28, l29, l30, l31, l32, lvs1, lvs2
+
 The content of each sub-node is defined by the standard binding for regulators -
 see regulator.txt - with additional custom properties described below:
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/regulator/regulator-max77620.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/regulator/regulator-max77620.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/regulator/regulator-max77620.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/regulator/regulator-max77620.txt	2016-07-24 15:23:50.000000000 -0400
@@ -94,6 +94,28 @@ Following are additional properties:
 					This is applicable if suspend state
 					FPS source is selected as FPS0, FPS1 or
 					FPS2.
+- maxim,ramp-rate-setting:		integer, ramp rate(uV/us) setting to be
+					configured to the device.
+					The platform may have different ramp
+					rate than advertised ramp rate if it has
+					design variation from Maxim's
+					recommended. On this case, platform
+					specific ramp rate is used for ramp time
+					calculation and this property is used
+					for device register configurations.
+					The measured ramp rate of platform is
+					provided by the regulator-ramp-delay
+					as described in <devicetree/bindings/
+					regulator/regulator.txt>.
+					Maxim Max77620 supports following ramp
+					delay:
+					  SD: 13.75mV/us, 27.5mV/us, 55mV/us
+					  LDOs: 5mV/us, 100mV/us
+
+Note: If the measured ramp delay is same as advertised ramp delay then it is not
+required to provide the ramp delay with property "maxim,ramp-rate-setting". The
+ramp rate can be provided by the regulator-ramp-delay which will be used for
+ramp time calculation for voltage change as well as for device configuration.
 
 Example:
 --------
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/regulator/ti-abb-regulator.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/regulator/ti-abb-regulator.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/regulator/ti-abb-regulator.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/regulator/ti-abb-regulator.txt	2016-07-24 15:23:50.000000000 -0400
@@ -14,8 +14,8 @@ Required Properties:
   - "setup-address"	- contains setup register address of ABB module (ti,abb-v3)
   - "int-address"	- contains address of interrupt register for ABB module
   (also see Optional properties)
-- #address-cell: should be 0
-- #size-cell: should be 0
+- #address-cells: should be 0
+- #size-cells: should be 0
 - clocks: should point to the clock node used by ABB module
 - ti,settling-time: Settling time in uSecs from SoC documentation for ABB module
 	to settle down(target time for SR2_WTCNT_VALUE).
@@ -69,7 +69,7 @@ Example #1: Simplest configuration (no e
 abb_x: regulator-abb-x {
 	compatible = "ti,abb-v1";
 	regulator-name = "abb_x";
-	#address-cell = <0>;
+	#address-cells = <0>;
 	#size-cells = <0>;
 	reg = <0x483072f0 0x8>, <0x48306818 0x4>;
 	reg-names = "base-address", "int-address";
@@ -89,7 +89,7 @@ Example #2: Efuse bits contain ABB mode
 abb_y: regulator-abb-y {
 	compatible = "ti,abb-v2";
 	regulator-name = "abb_y";
-	#address-cell = <0>;
+	#address-cells = <0>;
 	#size-cells = <0>;
 	reg = <0x4a307bd0 0x8>, <0x4a306014 0x4>, <0x4A002268 0x8>;
 	reg-names = "base-address", "int-address", "efuse-address";
@@ -110,7 +110,7 @@ Example #3: Efuse bits contain ABB mode
 abb_z: regulator-abb-z {
 	compatible = "ti,abb-v2";
 	regulator-name = "abb_z";
-	#address-cell = <0>;
+	#address-cells = <0>;
 	#size-cells = <0>;
 	reg = <0x4ae07ce4 0x8>, <0x4ae06010 0x4>,
 	      <0x4a002194 0x8>, <0x4ae0C314 0x4>;
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/regulator/twl-regulator.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/regulator/twl-regulator.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/regulator/twl-regulator.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/regulator/twl-regulator.txt	2016-07-24 15:23:50.000000000 -0400
@@ -57,6 +57,12 @@ For twl4030 regulators/LDOs
 
 Optional properties:
 - Any optional property defined in bindings/regulator/regulator.txt
+For twl4030 regulators/LDOs:
+ - regulator-initial-mode:
+  - 0x08 - Sleep mode, the nominal output voltage is maintained with low power
+           consumption with low load current capability.
+  - 0x0e - Active mode, the regulator can deliver its nominal output voltage
+           with full-load current capability.
 
 Example:
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/reset/oxnas,reset.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/reset/oxnas,reset.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/reset/oxnas,reset.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/reset/oxnas,reset.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,58 @@
+Oxford Semiconductor OXNAS SoC Family RESET Controller
+================================================
+
+Please also refer to reset.txt in this directory for common reset
+controller binding usage.
+
+Required properties:
+- compatible: Should be "oxsemi,ox810se-reset"
+- #reset-cells: 1, see below
+
+Parent node should have the following properties :
+- compatible: Should be "oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd"
+
+For OX810SE, the indices are :
+ - 0 : ARM
+ - 1 : COPRO
+ - 2 : Reserved
+ - 3 : Reserved
+ - 4 : USBHS
+ - 5 : USBHSPHY
+ - 6 : MAC
+ - 7 : PCI
+ - 8 : DMA
+ - 9 : DPE
+ - 10 : DDR
+ - 11 : SATA
+ - 12 : SATA_LINK
+ - 13 : SATA_PHY
+ - 14 : Reserved
+ - 15 : NAND
+ - 16 : GPIO
+ - 17 : UART1
+ - 18 : UART2
+ - 19 : MISC
+ - 20 : I2S
+ - 21 : AHB_MON
+ - 22 : UART3
+ - 23 : UART4
+ - 24 : SGDMA
+ - 25 : Reserved
+ - 26 : Reserved
+ - 27 : Reserved
+ - 28 : Reserved
+ - 29 : Reserved
+ - 30 : Reserved
+ - 31 : BUS
+
+example:
+
+sys: sys-ctrl@000000 {
+	compatible = "oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd";
+	reg = <0x000000 0x100000>;
+
+	reset: reset-controller {
+		compatible = "oxsemi,ox810se-reset";
+		#reset-cells = <1>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/rng/hisi-rng.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/rng/hisi-rng.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/rng/hisi-rng.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/rng/hisi-rng.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,12 @@
+Hisilicon Random Number Generator
+
+Required properties:
+- compatible : Should be "hisilicon,hip04-rng" or "hisilicon,hip05-rng"
+- reg : Offset and length of the register set of this block
+
+Example:
+
+rng@d1010000 {
+	compatible = "hisilicon,hip05-rng";
+	reg = <0xd1010000 0x100>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/rtc/maxim-ds1302.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/rtc/maxim-ds1302.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/rtc/maxim-ds1302.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/rtc/maxim-ds1302.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,46 @@
+* Maxim/Dallas Semiconductor DS-1302 RTC
+
+Simple device which could be used to store date/time between reboots.
+
+The device uses the standard MicroWire half-duplex transfer timing.
+Master output is set on low clock and sensed by the RTC on the rising
+edge. Master input is set by the RTC on the trailing edge and is sensed
+by the master on low clock.
+
+Required properties:
+
+- compatible : Should be "maxim,ds1302"
+
+Required SPI properties:
+
+- reg : Should be address of the device chip select within
+  the controller.
+
+- spi-max-frequency : DS-1302 has 500 kHz if powered at 2.2V,
+  and 2MHz if powered at 5V.
+
+- spi-3wire : The device has a shared signal IN/OUT line.
+
+- spi-lsb-first : DS-1302 requires least significant bit first
+  transfers.
+
+- spi-cs-high: DS-1302 has active high chip select line. This is
+  required unless inverted in hardware.
+
+Example:
+
+spi@901c {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	compatible = "icpdas,lp8841-spi-rtc";
+	reg = <0x901c 0x1>;
+
+	rtc@0 {
+		compatible = "maxim,ds1302";
+		reg = <0>;
+		spi-max-frequency = <500000>;
+		spi-3wire;
+		spi-lsb-first;
+		spi-cs-high;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/rtc/rtc-palmas.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/rtc/rtc-palmas.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/rtc/rtc-palmas.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/rtc/rtc-palmas.txt	2016-07-24 15:23:50.000000000 -0400
@@ -15,9 +15,9 @@ Optional properties:
 	battery is chargeable or not. If charging battery then driver can
 	enable the charging.
 - ti,backup-battery-charge-high-current: Enable high current charging in
-	backup battery. Device supports the < 100mA and > 100mA charging.
-	The high current will be > 100mA. Absence of this property will
-	charge battery to lower current i.e. < 100mA.
+	backup battery. Device supports the < 100uA and > 100uA charging.
+	The high current will be > 100uA. Absence of this property will
+	charge battery to lower current i.e. < 100uA.
 
 Example:
 	palmas: tps65913@58 {
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/rtc/sa1100-rtc.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/rtc/sa1100-rtc.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/rtc/sa1100-rtc.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/rtc/sa1100-rtc.txt	2016-07-24 15:23:50.000000000 -0400
@@ -13,5 +13,5 @@ Example:
 		compatible = "mrvl,mmp-rtc";
 		reg = <0xd4010000 0x1000>;
 		interrupts = <5>, <6>;
-		interrupt-name = "rtc 1Hz", "rtc alarm";
+		interrupt-names = "rtc 1Hz", "rtc alarm";
 	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/serial/arm,mps2-uart.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/serial/arm,mps2-uart.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/serial/arm,mps2-uart.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/serial/arm,mps2-uart.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,19 @@
+ARM MPS2 UART
+
+Required properties:
+- compatible	: Should be "arm,mps2-uart"
+- reg		: Address and length of the register set
+- interrupts	: Reference to the UART RX, TX and overrun interrupts
+
+Required clocking property:
+- clocks	  : The input clock of the UART
+
+
+Examples:
+
+uart0: serial@40004000 {
+	compatible = "arm,mps2-uart";
+	reg = <0x40004000 0x1000>;
+	interrupts = <0 1 12>;
+	clocks = <&sysclk>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/serial/fsl-imx-uart.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/serial/fsl-imx-uart.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/serial/fsl-imx-uart.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/serial/fsl-imx-uart.txt	2016-07-24 15:23:50.000000000 -0400
@@ -6,7 +6,7 @@ Required properties:
 - interrupts : Should contain uart interrupt
 
 Optional properties:
-- fsl,uart-has-rtscts : Indicate the uart has rts and cts
+- uart-has-rtscts : Indicate the uart has rts and cts
 - fsl,irda-mode : Indicate the uart supports irda mode
 - fsl,dte-mode : Indicate the uart works in DTE mode. The uart works
                   in DCE mode by default.
@@ -24,6 +24,6 @@ uart1: serial@73fbc000 {
 	compatible = "fsl,imx51-uart", "fsl,imx21-uart";
 	reg = <0x73fbc000 0x4000>;
 	interrupts = <31>;
-	fsl,uart-has-rtscts;
+	uart-has-rtscts;
 	fsl,dte-mode;
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/serial/fsl-mxs-auart.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/serial/fsl-mxs-auart.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/serial/fsl-mxs-auart.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/serial/fsl-mxs-auart.txt	2016-07-24 15:23:50.000000000 -0400
@@ -1,8 +1,10 @@
 * Freescale MXS Application UART (AUART)
 
-Required properties:
-- compatible : Should be "fsl,<soc>-auart". The supported SoCs include
-  imx23 and imx28.
+Required properties for all SoCs:
+- compatible : Should be one of fallowing variants:
+	"fsl,imx23-auart" - Freescale i.MX23
+	"fsl,imx28-auart" - Freescale i.MX28
+	"alphascale,asm9260-auart" - Alphascale ASM9260
 - reg : Address and length of the register set for the device
 - interrupts : Should contain the auart interrupt numbers
 - dmas: DMA specifier, consisting of a phandle to DMA controller node
@@ -10,8 +12,14 @@ Required properties:
   Refer to dma.txt and fsl-mxs-dma.txt for details.
 - dma-names: "rx" for RX channel, "tx" for TX channel.
 
+Required properties for "alphascale,asm9260-auart":
+- clocks : the clocks feeding the watchdog timer. See clock-bindings.txt
+- clock-names : should be set to
+	"mod" - source for tick counter.
+	"ahb" - ahb gate.
+
 Optional properties:
-- fsl,uart-has-rtscts : Indicate the UART has RTS and CTS lines
+- uart-has-rtscts : Indicate the UART has RTS and CTS lines
   for hardware flow control,
 	it also means you enable the DMA support for this UART.
 - {rts,cts,dtr,dsr,rng,dcd}-gpios: specify a GPIO for RTS/CTS/DTR/DSR/RI/DCD
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/serial/microchip,pic32-uart.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/serial/microchip,pic32-uart.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/serial/microchip,pic32-uart.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/serial/microchip,pic32-uart.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,29 @@
+* Microchip Universal Asynchronous Receiver Transmitter (UART)
+
+Required properties:
+- compatible: Should be "microchip,pic32mzda-uart"
+- reg: Should contain registers location and length
+- interrupts: Should contain interrupt
+- clocks: Phandle to the clock.
+          See: Documentation/devicetree/bindings/clock/clock-bindings.txt
+- pinctrl-names: A pinctrl state names "default" must be defined.
+- pinctrl-0: Phandle referencing pin configuration of the UART peripheral.
+             See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt
+
+Optional properties:
+- cts-gpios: CTS pin for UART
+
+Example:
+	uart1: serial@1f822000 {
+		compatible = "microchip,pic32mzda-uart";
+		reg = <0x1f822000 0x50>;
+		interrupts = <112 IRQ_TYPE_LEVEL_HIGH>,
+			<113 IRQ_TYPE_LEVEL_HIGH>,
+			<114 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&rootclk PB2CLK>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_uart1
+				&pinctrl_uart1_cts
+				&pinctrl_uart1_rts>;
+		cts-gpios = <&gpio1 15 0>;
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/serial/mvebu-uart.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/serial/mvebu-uart.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/serial/mvebu-uart.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/serial/mvebu-uart.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,13 @@
+* Marvell UART : Non standard UART used in some of Marvell EBU SoCs (e.g., Armada-3700)
+
+Required properties:
+- compatible: "marvell,armada-3700-uart"
+- reg: offset and length of the register set for the device.
+- interrupts: device interrupt
+
+Example:
+	serial@12000 {
+		compatible = "marvell,armada-3700-uart";
+		reg = <0x12000 0x400>;
+		interrupts = <43>;
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/serial/serial.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/serial/serial.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/serial/serial.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/serial/serial.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,57 @@
+Generic Serial DT Bindings
+
+This document lists a set of generic properties for describing UARTs in a
+device tree.  Whether these properties apply to a particular device depends on
+the DT bindings for the actual device.
+
+Optional properties:
+  - cts-gpios: Must contain a GPIO specifier, referring to the GPIO pin to be
+    used as the UART's CTS line.
+  - dcd-gpios: Must contain a GPIO specifier, referring to the GPIO pin to be
+    used as the UART's DCD line.
+  - dsr-gpios: Must contain a GPIO specifier, referring to the GPIO pin to be
+    used as the UART's DSR line.
+  - dtr-gpios: Must contain a GPIO specifier, referring to the GPIO pin to be
+    used as the UART's DTR line.
+  - rng-gpios: Must contain a GPIO specifier, referring to the GPIO pin to be
+    used as the UART's RNG line.
+  - rts-gpios: Must contain a GPIO specifier, referring to the GPIO pin to be
+    used as the UART's RTS line.
+
+  - uart-has-rtscts: The presence of this property indicates that the
+    UART has dedicated lines for RTS/CTS hardware flow control, and that
+    they are available for use (wired and enabled by pinmux configuration).
+    This depends on both the UART hardware and the board wiring.
+    Note that this property is mutually-exclusive with "cts-gpios" and
+    "rts-gpios" above.
+
+
+Examples:
+
+	uart1: serial@48022000 {
+		compatible = "ti,am3352-uart", "ti,omap3-uart";
+		ti,hwmods = "uart2";
+		clock-frequency = <48000000>;
+		reg = <0x48022000 0x2000>;
+		interrupts = <73>;
+		dmas = <&edma 28 0>, <&edma 29 0>;
+		dma-names = "tx", "rx";
+		dtr-gpios = <&gpio2 22 GPIO_ACTIVE_LOW>;
+		dsr-gpios = <&gpio2 23 GPIO_ACTIVE_LOW>;
+		dcd-gpios = <&gpio2 24 GPIO_ACTIVE_LOW>;
+		rng-gpios = <&gpio2 25 GPIO_ACTIVE_LOW>;
+		cts-gpios = <&gpio0 12 GPIO_ACTIVE_LOW>;
+		rts-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
+		status = "okay";
+	};
+
+	scifa4: serial@e6c80000 {
+		compatible = "renesas,scifa-sh73a0", "renesas,scifa";
+		reg = <0xe6c80000 0x100>;
+		interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp2_clks SH73A0_CLK_SCIFA4>;
+		clock-names = "fck";
+		power-domains = <&pd_a3sp>;
+		uart-has-rtscts;
+		status = "okay";
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/serial/sirf-uart.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/serial/sirf-uart.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/serial/sirf-uart.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/serial/sirf-uart.txt	2016-07-24 15:23:50.000000000 -0400
@@ -9,9 +9,9 @@ Required properties:
 - clocks : Should contain uart clock number
 
 Optional properties:
-- sirf,uart-has-rtscts: we have hardware flow controller pins in hardware
-- rts-gpios: RTS pin for USP-based UART if sirf,uart-has-rtscts is true
-- cts-gpios: CTS pin for USP-based UART if sirf,uart-has-rtscts is true
+- uart-has-rtscts: we have hardware flow controller pins in hardware
+- rts-gpios: RTS pin for USP-based UART if uart-has-rtscts is true
+- cts-gpios: CTS pin for USP-based UART if uart-has-rtscts is true
 
 Example:
 
@@ -28,7 +28,7 @@ On the board-specific dts, we can put rt
 
 usp@b0090000 {
 	compatible = "sirf,prima2-usp-uart";
-	sirf,uart-has-rtscts;
+	uart-has-rtscts;
 	rts-gpios = <&gpio 15 0>;
 	cts-gpios = <&gpio 46 0>;
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/soc/mediatek/auxadc.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/soc/mediatek/auxadc.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/soc/mediatek/auxadc.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/soc/mediatek/auxadc.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,21 @@
+MediaTek AUXADC
+===============
+
+The Auxiliary Analog/Digital Converter (AUXADC) is an ADC found
+in some Mediatek SoCs which among other things measures the temperatures
+in the SoC. It can be used directly with register accesses, but it is also
+used by thermal controller which reads the temperatures from the AUXADC
+directly via its own bus interface. See
+Documentation/devicetree/bindings/thermal/mediatek-thermal.txt
+for the Thermal Controller which holds a phandle to the AUXADC.
+
+Required properties:
+- compatible: Must be "mediatek,mt8173-auxadc"
+- reg: Address range of the AUXADC unit
+
+Example:
+
+auxadc: auxadc@11001000 {
+	compatible = "mediatek,mt8173-auxadc";
+	reg = <0 0x11001000 0 0x1000>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/soc/mediatek/pwrap.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/soc/mediatek/pwrap.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/soc/mediatek/pwrap.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/soc/mediatek/pwrap.txt	2016-07-24 15:23:50.000000000 -0400
@@ -18,6 +18,7 @@ IP Pairing
 
 Required properties in pwrap device node.
 - compatible:
+	"mediatek,mt2701-pwrap" for MT2701/7623 SoCs
 	"mediatek,mt8135-pwrap" for MT8135 SoCs
 	"mediatek,mt8173-pwrap" for MT8173 SoCs
 - interrupts: IRQ for pwrap in SOC
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/soc/rockchip/grf.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/soc/rockchip/grf.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/soc/rockchip/grf.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/soc/rockchip/grf.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,35 @@
+* Rockchip General Register Files (GRF)
+
+The general register file will be used to do static set by software, which
+is composed of many registers for system control.
+
+From RK3368 SoCs, the GRF is divided into two sections,
+- GRF, used for general non-secure system,
+- PMUGRF, used for always on system
+
+Required Properties:
+
+- compatible: GRF should be one of the followings
+   - "rockchip,rk3066-grf", "syscon": for rk3066
+   - "rockchip,rk3188-grf", "syscon": for rk3188
+   - "rockchip,rk3228-grf", "syscon": for rk3228
+   - "rockchip,rk3288-grf", "syscon": for rk3288
+   - "rockchip,rk3368-grf", "syscon": for rk3368
+   - "rockchip,rk3399-grf", "syscon": for rk3399
+- compatible: PMUGRF should be one of the followings
+   - "rockchip,rk3368-pmugrf", "syscon": for rk3368
+   - "rockchip,rk3399-pmugrf", "syscon": for rk3399
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+Example: GRF and PMUGRF of RK3399 SoCs
+
+	pmugrf: syscon@ff320000 {
+		compatible = "rockchip,rk3399-pmugrf", "syscon";
+		reg = <0x0 0xff320000 0x0 0x1000>;
+	};
+
+	grf: syscon@ff770000 {
+		compatible = "rockchip,rk3399-grf", "syscon";
+		reg = <0x0 0xff770000 0x0 0x10000>;
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/soc/rockchip/power_domain.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/soc/rockchip/power_domain.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/soc/rockchip/power_domain.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/soc/rockchip/power_domain.txt	2016-07-24 15:23:50.000000000 -0400
@@ -7,6 +7,7 @@ Required properties for power domain con
 - compatible: Should be one of the following.
 	"rockchip,rk3288-power-controller" - for RK3288 SoCs.
 	"rockchip,rk3368-power-controller" - for RK3368 SoCs.
+	"rockchip,rk3399-power-controller" - for RK3399 SoCs.
 - #power-domain-cells: Number of cells in a power-domain specifier.
 	Should be 1 for multiple PM domains.
 - #address-cells: Should be 1.
@@ -16,8 +17,18 @@ Required properties for power domain sub
 - reg: index of the power domain, should use macros in:
 	"include/dt-bindings/power/rk3288-power.h" - for RK3288 type power domain.
 	"include/dt-bindings/power/rk3368-power.h" - for RK3368 type power domain.
+	"include/dt-bindings/power/rk3399-power.h" - for RK3399 type power domain.
 - clocks (optional): phandles to clocks which need to be enabled while power domain
 	switches state.
+- pm_qos (optional): phandles to qos blocks which need to be saved and restored
+	while power domain switches state.
+
+Qos Example:
+
+	qos_gpu: qos_gpu@ffaf0000 {
+		compatible ="syscon";
+		reg = <0x0 0xffaf0000 0x0 0x20>;
+	};
 
 Example:
 
@@ -30,6 +41,7 @@ Example:
 		pd_gpu {
 			reg = <RK3288_PD_GPU>;
 			clocks = <&cru ACLK_GPU>;
+			pm_qos = <&qos_gpu>;
 		};
 	};
 
@@ -45,12 +57,41 @@ Example:
                 };
         };
 
+Example 2:
+		power: power-controller {
+			compatible = "rockchip,rk3399-power-controller";
+			#power-domain-cells = <1>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			pd_vio {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <RK3399_PD_VIO>;
+
+				pd_vo {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <RK3399_PD_VO>;
+
+					pd_vopb {
+						reg = <RK3399_PD_VOPB>;
+					};
+
+					pd_vopl {
+						reg = <RK3399_PD_VOPL>;
+					};
+				};
+			};
+		};
+
 Node of a device using power domains must have a power-domains property,
 containing a phandle to the power device node and an index specifying which
 power domain to use.
 The index should use macros in:
 	"include/dt-bindings/power/rk3288-power.h" - for rk3288 type power domain.
 	"include/dt-bindings/power/rk3368-power.h" - for rk3368 type power domain.
+	"include/dt-bindings/power/rk3399-power.h" - for rk3399 type power domain.
 
 Example of the node using power domain:
 
@@ -65,3 +106,9 @@ Example of the node using power domain:
                 power-domains = <&power RK3368_PD_GPU_1>;
                 /* ... */
         };
+
+	node {
+		/* ... */
+		power-domains = <&power RK3399_PD_VOPB>;
+		/* ... */
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/soc/ti/keystone-navigator-qmss.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/soc/ti/keystone-navigator-qmss.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/soc/ti/keystone-navigator-qmss.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/soc/ti/keystone-navigator-qmss.txt	2016-07-24 15:23:50.000000000 -0400
@@ -42,7 +42,7 @@ Required properties:
 - queue-pools	: child node classifying the queue ranges into pools.
 		  Queue ranges are grouped into 3 type of pools:
 		  - qpend	    : pool of qpend(interruptible) queues
-		  - general-purpose : pool of general queues, primarly used
+		  - general-purpose : pool of general queues, primarily used
 				      as free descriptor queues or the
 				      transmit DMA queues.
 		  - accumulator	    : pool of queues on PDSP accumulator channel
@@ -50,7 +50,7 @@ Required properties:
   -- qrange		: number of queues to use per queue range, specified as
 			  <"base queue #" "# of queues">.
   -- interrupts		: Optional property to specify the interrupt mapping
-			  for interruptible queues. The driver additionaly sets
+			  for interruptible queues. The driver additionally sets
 			  the interrupt affinity hint based on the cpu mask.
   -- qalloc-by-id	: Optional property to specify that the queues in this
 			  range can only be allocated by queue id.
@@ -80,7 +80,7 @@ Required properties:
 			  latency     : time to delay the interrupt, specified
 					in microseconds.
   -- multi-queue	: Optional property to specify that the channel has to
-			  monitor upto 32 queues starting at the base queue #.
+			  monitor up to 32 queues starting at the base queue #.
 - descriptor-regions	: child node describing the memory regions for keystone
 			  navigator packet DMA descriptors. The memory for
 			  descriptors will be allocated by the driver.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/sound/davinci-mcbsp.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/sound/davinci-mcbsp.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/sound/davinci-mcbsp.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/sound/davinci-mcbsp.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,51 @@
+Texas Instruments DaVinci McBSP module
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This binding describes the "Multi-channel Buffered Serial Port" (McBSP)
+audio interface found in some TI DaVinci processors like the OMAP-L138 or AM180x.
+
+
+Required properties:
+~~~~~~~~~~~~~~~~~~~~
+- compatible :
+        "ti,da850-mcbsp" : for DA850, AM180x and OPAM-L138 platforms
+
+- reg : physical base address and length of the controller memory mapped
+        region(s).
+- reg-names : Should contain:
+        * "mpu" for the main registers (required).
+        * "dat" for the data FIFO (optional).
+
+- dmas: three element list of DMA controller phandles, DMA request line and
+	TC channel ordered triplets.
+- dma-names: identifier string for each DMA request line in the dmas property.
+	These strings correspond 1:1 with the ordered pairs in dmas. The dma
+	identifiers must be "rx" and "tx".
+
+Optional properties:
+~~~~~~~~~~~~~~~~~~~~
+- interrupts : Interrupt numbers for McBSP
+- interrupt-names : Known interrupt names are "rx" and "tx"
+
+- pinctrl-0: Should specify pin control group used for this controller.
+- pinctrl-names: Should contain only one value - "default", for more details
+        please refer to pinctrl-bindings.txt
+
+Example (AM1808):
+~~~~~~~~~~~~~~~~~
+
+mcbsp0: mcbsp@1d10000 {
+	compatible = "ti,da850-mcbsp";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcbsp0_pins>;
+
+	reg = 	<0x00110000 0x1000>,
+		<0x00310000 0x1000>;
+	reg-names = "mpu", "dat";
+	interrupts = <97 98>;
+	interrupts-names = "rx", "tx";
+	dmas = <&edma0 3 1
+		&edma0 2 1>;
+	dma-names = "tx", "rx";
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/sound/fsl-sai.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/sound/fsl-sai.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/sound/fsl-sai.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/sound/fsl-sai.txt	2016-07-24 15:23:50.000000000 -0400
@@ -7,8 +7,8 @@ codec/DSP interfaces.
 
 Required properties:
 
-  - compatible		: Compatible list, contains "fsl,vf610-sai" or
-			  "fsl,imx6sx-sai".
+  - compatible		: Compatible list, contains "fsl,vf610-sai",
+			  "fsl,imx6sx-sai" or "fsl,imx6ul-sai"
 
   - reg			: Offset and length of the register set for the device.
 
@@ -48,6 +48,11 @@ Required properties:
 			  receive data by following their own bit clocks and
 			  frame sync clocks separately.
 
+Optional properties (for mx6ul):
+
+  - fsl,sai-mclk-direction-output: This is a boolean property. If present,
+			 indicates that SAI will output the SAI MCLK clock.
+
 Note:
 - If both fsl,sai-asynchronous and fsl,sai-synchronous-rx are absent, the
   default synchronous mode (sync Rx with Tx) will be used, which means both
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/sound/max98371.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/sound/max98371.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/sound/max98371.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/sound/max98371.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,17 @@
+max98371 codec
+
+This device supports I2C mode only.
+
+Required properties:
+
+- compatible : "maxim,max98371"
+- reg : The chip select number on the I2C bus
+
+Example:
+
+&i2c {
+	max98371: max98371@0x31 {
+		compatible = "maxim,max98371";
+		reg = <0x31>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/sound/mt8173-rt5650-rt5676.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/sound/mt8173-rt5650-rt5676.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/sound/mt8173-rt5650-rt5676.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/sound/mt8173-rt5650-rt5676.txt	2016-07-24 15:23:50.000000000 -0400
@@ -1,15 +1,16 @@
-MT8173 with RT5650 RT5676 CODECS
+MT8173 with RT5650 RT5676 CODECS and HDMI via I2S
 
 Required properties:
 - compatible : "mediatek,mt8173-rt5650-rt5676"
 - mediatek,audio-codec: the phandles of rt5650 and rt5676 codecs
+			and of the hdmi encoder node
 - mediatek,platform: the phandle of MT8173 ASoC platform
 
 Example:
 
 	sound {
 		compatible = "mediatek,mt8173-rt5650-rt5676";
-		mediatek,audio-codec = <&rt5650 &rt5676>;
+		mediatek,audio-codec = <&rt5650 &rt5676 &hdmi0>;
 		mediatek,platform = <&afe>;
 	};
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/sound/mt8173-rt5650.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/sound/mt8173-rt5650.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/sound/mt8173-rt5650.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/sound/mt8173-rt5650.txt	2016-07-24 15:23:50.000000000 -0400
@@ -5,11 +5,21 @@ Required properties:
 - mediatek,audio-codec: the phandles of rt5650 codecs
 - mediatek,platform: the phandle of MT8173 ASoC platform
 
+Optional subnodes:
+- codec-capture : the subnode of rt5650 codec capture
+Required codec-capture subnode properties:
+- sound-dai: audio codec dai name on capture path
+  <&rt5650 0> : Default setting. Connect rt5650 I2S1 for capture. (dai_name = rt5645-aif1)
+  <&rt5650 1> : Connect rt5650 I2S2 for capture. (dai_name = rt5645-aif2)
+
 Example:
 
 	sound {
 		compatible = "mediatek,mt8173-rt5650";
 		mediatek,audio-codec = <&rt5650>;
 		mediatek,platform = <&afe>;
+		codec-capture {
+			sound-dai = <&rt5650 1>;
+		};
 	};
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/sound/nvidia,tegra30-hda.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/sound/nvidia,tegra30-hda.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/sound/nvidia,tegra30-hda.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/sound/nvidia,tegra30-hda.txt	2016-07-24 15:23:50.000000000 -0400
@@ -15,7 +15,7 @@ Required properties:
 
 Example:
 
-hda@0,70030000 {
+hda@70030000 {
 	compatible = "nvidia,tegra124-hda", "nvidia,tegra30-hda";
 	reg = <0x0 0x70030000 0x0 0x10000>;
 	interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/sound/pcm5102a.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/sound/pcm5102a.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/sound/pcm5102a.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/sound/pcm5102a.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,13 @@
+PCM5102a audio CODECs
+
+These devices does not use I2C or SPI.
+
+Required properties:
+
+  - compatible : set as "ti,pcm5102a"
+
+Examples:
+
+	pcm5102a: pcm5102a {
+		compatible = "ti,pcm5102a";
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/sound/st,sti-asoc-card.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/sound/st,sti-asoc-card.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/sound/st,sti-asoc-card.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/sound/st,sti-asoc-card.txt	2016-07-24 15:23:50.000000000 -0400
@@ -37,17 +37,18 @@ Required properties:
 
   - dai-name: DAI name that describes the IP.
 
+  - IP mode: IP working mode depending on associated codec.
+	"HDMI" connected to HDMI codec and support IEC HDMI formats (player only).
+	"SPDIF" connected to SPDIF codec and support SPDIF formats (player only).
+	"PCM" PCM standard mode for I2S or TDM bus.
+	"TDM" TDM mode for TDM bus.
+
 Required properties ("st,sti-uni-player" compatibility only):
   - clocks: CPU_DAI IP clock source, listed in the same order than the
 	    CPU_DAI properties.
 
   - uniperiph-id: internal SOC IP instance ID.
 
-  - IP mode: IP working mode depending on associated codec.
-	"HDMI" connected to HDMI codec IP and IEC HDMI formats.
-	"SPDIF"connected to SPDIF codec and support SPDIF formats.
-	"PCM"  PCM standard mode for I2S or TDM bus.
-
 Optional properties:
   - pinctrl-0: defined for CPU_DAI@1 and CPU_DAI@4 to describe I2S PIOs for
 	       external codecs connection.
@@ -56,6 +57,22 @@ Optional properties:
 
 Example:
 
+	sti_uni_player1: sti-uni-player@1 {
+		compatible = "st,sti-uni-player";
+		status = "okay";
+		#sound-dai-cells = <0>;
+		st,syscfg = <&syscfg_core>;
+		clocks = <&clk_s_d0_flexgen CLK_PCM_1>;
+		reg = <0x8D81000 0x158>;
+		interrupts = <GIC_SPI 85 IRQ_TYPE_NONE>;
+		dmas = <&fdma0 3 0 1>;
+		st,dai-name = "Uni Player #1 (I2S)";
+		dma-names = "tx";
+		st,uniperiph-id = <1>;
+		st,version = <5>;
+		st,mode = "TDM";
+	};
+
 	sti_uni_player2: sti-uni-player@2 {
 		compatible = "st,sti-uni-player";
 		status = "okay";
@@ -65,7 +82,7 @@ Example:
 		reg = <0x8D82000 0x158>;
 		interrupts = <GIC_SPI 86 IRQ_TYPE_NONE>;
 		dmas = <&fdma0 4 0 1>;
-		dai-name = "Uni Player #1 (DAC)";
+		dai-name = "Uni Player #2 (DAC)";
 		dma-names = "tx";
 		uniperiph-id = <2>;
 		version = <5>;
@@ -82,7 +99,7 @@ Example:
 		interrupts = <GIC_SPI 89 IRQ_TYPE_NONE>;
 		dmas = <&fdma0 7 0 1>;
 		dma-names = "tx";
-		dai-name = "Uni Player #1 (PIO)";
+		dai-name = "Uni Player #3 (SPDIF)";
 		uniperiph-id = <3>;
 		version = <5>;
 		mode = "SPDIF";
@@ -99,6 +116,7 @@ Example:
 		dma-names = "rx";
 		dai-name = "Uni Reader #1 (HDMI RX)";
 		version = <3>;
+		st,mode = "PCM";
 	};
 
 2) sti-sas-codec: internal audio codec IPs driver
@@ -152,4 +170,20 @@ Example of audio card declaration:
 				sound-dai = <&sti_sasg_codec 0>;
 			};
 		};
+		simple-audio-card,dai-link@2 {
+			/* TDM playback  */
+			format = "left_j";
+			frame-inversion = <1>;
+			cpu {
+				sound-dai = <&sti_uni_player1>;
+				dai-tdm-slot-num = <16>;
+				dai-tdm-slot-width = <16>;
+				dai-tdm-slot-tx-mask =
+					<1 1 1 1 0 0 0 0 0 0 1 1 0 0 1 1>;
+			};
+
+			codec {
+				sound-dai = <&sti_sasg_codec 3>;
+			};
+		};
 	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/sound/tas571x.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/sound/tas571x.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/sound/tas571x.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/sound/tas571x.txt	2016-07-24 15:23:50.000000000 -0400
@@ -1,4 +1,4 @@
-Texas Instruments TAS5711/TAS5717/TAS5719 stereo power amplifiers
+Texas Instruments TAS5711/TAS5717/TAS5719/TAS5721 stereo power amplifiers
 
 The codec is controlled through an I2C interface.  It also has two other
 signals that can be wired up to GPIOs: reset (strongly recommended), and
@@ -6,7 +6,11 @@ powerdown (optional).
 
 Required properties:
 
-- compatible: "ti,tas5711", "ti,tas5717", or "ti,tas5719"
+- compatible: should be one of the following:
+  - "ti,tas5711",
+  - "ti,tas5717",
+  - "ti,tas5719",
+  - "ti,tas5721"
 - reg: The I2C address of the device
 - #sound-dai-cells: must be equal to 0
 
@@ -25,6 +29,8 @@ Optional properties:
 - PVDD_B-supply: regulator phandle for the PVDD_B supply (5711)
 - PVDD_C-supply: regulator phandle for the PVDD_C supply (5711)
 - PVDD_D-supply: regulator phandle for the PVDD_D supply (5711)
+- DRVDD-supply: regulator phandle for the DRVDD supply (5721)
+- PVDD-supply: regulator phandle for the PVDD supply (5721)
 
 Example:
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/sound/tas5720.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/sound/tas5720.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/sound/tas5720.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/sound/tas5720.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,25 @@
+Texas Instruments TAS5720 Mono Audio amplifier
+
+The TAS5720 serial control bus communicates through the I2C protocol only. The
+serial bus is also used for periodic codec fault checking/reporting during
+audio playback. For more product information please see the links below:
+
+http://www.ti.com/product/TAS5720L
+http://www.ti.com/product/TAS5720M
+
+Required properties:
+
+- compatible : "ti,tas5720"
+- reg : I2C slave address
+- dvdd-supply : phandle to a 3.3-V supply for the digital circuitry
+- pvdd-supply : phandle to a supply used for the Class-D amp and the analog
+
+Example:
+
+tas5720: tas5720@6c {
+	status = "okay";
+	compatible = "ti,tas5720";
+	reg = <0x6c>;
+	dvdd-supply = <&vdd_3v3_reg>;
+	pvdd-supply = <&amp_supply_reg>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/spi/microchip,spi-pic32.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/spi/microchip,spi-pic32.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/spi/microchip,spi-pic32.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/spi/microchip,spi-pic32.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,34 @@
+Microchip PIC32 SPI Master controller
+
+Required properties:
+- compatible: Should be "microchip,pic32mzda-spi".
+- reg: Address and length of register space for the device.
+- interrupts: Should contain all three spi interrupts in sequence
+              of <fault-irq>, <receive-irq>, <transmit-irq>.
+- interrupt-names: Should be "fault", "rx", "tx" in order.
+- clocks: Phandle of the clock generating SPI clock on the bus.
+- clock-names: Should be "mck0".
+- cs-gpios: Specifies the gpio pins to be used for chipselects.
+            See: Documentation/devicetree/bindings/spi/spi-bus.txt
+
+Optional properties:
+- dmas: Two or more DMA channel specifiers following the convention outlined
+        in Documentation/devicetree/bindings/dma/dma.txt
+- dma-names: Names for the dma channels. There must be at least one channel
+             named "spi-tx" for transmit and named "spi-rx" for receive.
+
+Example:
+
+spi1: spi@1f821000 {
+        compatible = "microchip,pic32mzda-spi";
+        reg = <0x1f821000 0x200>;
+        interrupts = <109 IRQ_TYPE_LEVEL_HIGH>,
+                     <110 IRQ_TYPE_LEVEL_HIGH>,
+                     <111 IRQ_TYPE_LEVEL_HIGH>;
+        interrupt-names = "fault", "rx", "tx";
+        clocks = <&PBCLK2>;
+        clock-names = "mck0";
+        cs-gpios = <&gpio3 4 GPIO_ACTIVE_LOW>;
+        dmas = <&dma 134>, <&dma 135>;
+        dma-names = "spi-rx", "spi-tx";
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/spi/spi-fsl-dspi.txt	2016-07-24 15:23:50.000000000 -0400
@@ -1,7 +1,10 @@
 ARM Freescale DSPI controller
 
 Required properties:
-- compatible : "fsl,vf610-dspi", "fsl,ls1021a-v1.0-dspi", "fsl,ls2085a-dspi"
+- compatible : "fsl,vf610-dspi", "fsl,ls1021a-v1.0-dspi",
+		"fsl,ls2085a-dspi"
+		or
+		"fsl,ls2080a-dspi" followed by "fsl,ls2085a-dspi"
 - reg : Offset and length of the register set for the device
 - interrupts : Should contain SPI controller interrupt
 - clocks: from common clock binding: handle to dspi clock.
@@ -13,8 +16,7 @@ Required properties:
 
 Optional property:
 - big-endian: If present the dspi device's registers are implemented
-  in big endian mode, otherwise in native mode(same with CPU), for more
-  detail please see: Documentation/devicetree/bindings/regmap/regmap.txt.
+  in big endian mode.
 
 Optional SPI slave node properties:
 - fsl,spi-cs-sck-delay: a delay in nanoseconds between activating chip
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/spi/sqi-pic32.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/spi/sqi-pic32.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/spi/sqi-pic32.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/spi/sqi-pic32.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,18 @@
+Microchip PIC32 Quad SPI controller
+-----------------------------------
+Required properties:
+- compatible: Should be "microchip,pic32mzda-sqi".
+- reg: Address and length of SQI controller register space.
+- interrupts: Should contain SQI interrupt.
+- clocks: Should contain phandle of two clocks in sequence, one that drives
+          clock on SPI bus and other that drives SQI controller.
+- clock-names: Should be "spi_ck" and "reg_ck" in order.
+
+Example:
+	sqi1: spi@1f8e2000 {
+		compatible = "microchip,pic32mzda-sqi";
+		reg = <0x1f8e2000 0x200>;
+		clocks = <&rootclk REF2CLK>, <&rootclk PB5CLK>;
+		clock-names = "spi_ck", "reg_ck";
+		interrupts = <169 IRQ_TYPE_LEVEL_HIGH>;
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/spi/ti_qspi.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/spi/ti_qspi.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/spi/ti_qspi.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/spi/ti_qspi.txt	2016-07-24 15:23:50.000000000 -0400
@@ -19,6 +19,13 @@ Optional properties:
 - syscon-chipselects: Handle to system control region contains QSPI
 		      chipselect register and offset of that register.
 
+NOTE: TI QSPI controller requires different pinmux and IODelay
+paramaters for Mode-0 and Mode-3 operations, which needs to be set up by
+the bootloader (U-Boot). Default configuration only supports Mode-0
+operation. Hence, "spi-cpol" and "spi-cpha" DT properties cannot be
+specified in the slave nodes of TI QSPI controller without appropriate
+modification to bootloader.
+
 Example:
 
 For am4372:
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/sram/sram.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/sram/sram.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/sram/sram.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/sram/sram.txt	2016-07-24 15:23:50.000000000 -0400
@@ -51,7 +51,7 @@ sram: sram@5c000000 {
 	compatible = "mmio-sram";
 	reg = <0x5c000000 0x40000>; /* 256 KiB SRAM at address 0x5c000000 */
 
-	#adress-cells = <1>;
+	#address-cells = <1>;
 	#size-cells = <1>;
 	ranges = <0 0x5c000000 0x40000>;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,47 +0,0 @@
-* Freescale MXS LRADC device driver
-
-Required properties:
-- compatible: Should be "fsl,imx23-lradc" for i.MX23 SoC and "fsl,imx28-lradc"
-              for i.MX28 SoC
-- reg: Address and length of the register set for the device
-- interrupts: Should contain the LRADC interrupts
-
-Optional properties:
-- fsl,lradc-touchscreen-wires: Number of wires used to connect the touchscreen
-                               to LRADC. Valid value is either 4 or 5. If this
-                               property is not present, then the touchscreen is
-                               disabled. 5 wires is valid for i.MX28 SoC only.
-- fsl,ave-ctrl: number of samples per direction to calculate an average value.
-                Allowed value is 1 ... 32, default is 4
-- fsl,ave-delay: delay between consecutive samples. Allowed value is
-                 2 ... 2048. It is used if 'fsl,ave-ctrl' > 1, counts at
-                 2 kHz and its default is 2 (= 1 ms)
-- fsl,settling: delay between plate switch to next sample. Allowed value is
-                1 ... 2047. It counts at 2 kHz and its default is
-                10 (= 5 ms)
-
-Example for i.MX23 SoC:
-
-	lradc@80050000 {
-		compatible = "fsl,imx23-lradc";
-		reg = <0x80050000 0x2000>;
-		interrupts = <36 37 38 39 40 41 42 43 44>;
-		status = "okay";
-		fsl,lradc-touchscreen-wires = <4>;
-		fsl,ave-ctrl = <4>;
-		fsl,ave-delay = <2>;
-		fsl,settling = <10>;
-	};
-
-Example for i.MX28 SoC:
-
-	lradc@80050000 {
-		compatible = "fsl,imx28-lradc";
-		reg = <0x80050000 0x2000>;
-		interrupts = <10 14 15 16 17 18 19 20 21 22 23 24 25>;
-		status = "okay";
-		fsl,lradc-touchscreen-wires = <5>;
-		fsl,ave-ctrl = <4>;
-		fsl,ave-delay = <2>;
-		fsl,settling = <10>;
-	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/thermal/nvidia,tegra124-soctherm.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/thermal/nvidia,tegra124-soctherm.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/thermal/nvidia,tegra124-soctherm.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/thermal/nvidia,tegra124-soctherm.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,67 @@
+Tegra124 SOCTHERM thermal management system
+
+The SOCTHERM IP block contains thermal sensors, support for polled
+or interrupt-based thermal monitoring, CPU and GPU throttling based
+on temperature trip points, and handling external overcurrent
+notifications. It is also used to manage emergency shutdown in an
+overheating situation.
+
+Required properties :
+- compatible : For Tegra124, must contain "nvidia,tegra124-soctherm".
+  For Tegra132, must contain "nvidia,tegra132-soctherm".
+  For Tegra210, must contain "nvidia,tegra210-soctherm".
+- reg : Should contain 1 entry:
+  - SOCTHERM register set
+- interrupts : Defines the interrupt used by SOCTHERM
+- clocks : Must contain an entry for each entry in clock-names.
+  See ../clocks/clock-bindings.txt for details.
+- clock-names : Must include the following entries:
+  - tsensor
+  - soctherm
+- resets : Must contain an entry for each entry in reset-names.
+  See ../reset/reset.txt for details.
+- reset-names : Must include the following entries:
+  - soctherm
+- #thermal-sensor-cells : Should be 1. See ./thermal.txt for a description
+    of this property. See <dt-bindings/thermal/tegra124-soctherm.h> for a
+    list of valid values when referring to thermal sensors.
+
+Note:
+- the "critical" type trip points will be set to SOC_THERM hardware as the
+shut down temperature. Once the temperature of this thermal zone is higher
+than it, the system will be shutdown or reset by hardware.
+
+Example :
+
+	soctherm@700e2000 {
+		compatible = "nvidia,tegra124-soctherm";
+		reg = <0x0 0x700e2000 0x0 0x1000>;
+		interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&tegra_car TEGRA124_CLK_TSENSOR>,
+			<&tegra_car TEGRA124_CLK_SOC_THERM>;
+		clock-names = "tsensor", "soctherm";
+		resets = <&tegra_car 78>;
+		reset-names = "soctherm";
+
+		#thermal-sensor-cells = <1>;
+	};
+
+Example: referring to thermal sensors :
+
+       thermal-zones {
+                cpu {
+                        polling-delay-passive = <1000>;
+                        polling-delay = <1000>;
+
+                        thermal-sensors =
+                                <&soctherm TEGRA124_SOCTHERM_SENSOR_CPU>;
+
+			trips {
+				cpu_shutdown_trip: shutdown-trip {
+					temperature = <102500>;
+					hysteresis = <1000>;
+					type = "critical";
+				};
+			};
+                };
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/thermal/rcar-thermal.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/thermal/rcar-thermal.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/thermal/rcar-thermal.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/thermal/rcar-thermal.txt	2016-07-24 15:23:50.000000000 -0400
@@ -11,7 +11,6 @@ Required properties:
 			    - "renesas,thermal-r8a7791" (R-Car M2-W)
 			    - "renesas,thermal-r8a7792" (R-Car V2H)
 			    - "renesas,thermal-r8a7793" (R-Car M2-N)
-			    - "renesas,thermal-r8a7794" (R-Car E2)
 - reg			: Address range of the thermal registers.
 			  The 1st reg will be recognized as common register
 			  if it has "interrupts".
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/thermal/tango-thermal.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/thermal/tango-thermal.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/thermal/tango-thermal.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/thermal/tango-thermal.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,17 @@
+* Tango Thermal
+
+The SMP8758 SoC includes 3 instances of this temperature sensor
+(in the CPU, video decoder, and PCIe controller).
+
+Required properties:
+- #thermal-sensor-cells: Should be 0 (see thermal.txt)
+- compatible: "sigma,smp8758-thermal"
+- reg: Address range of the thermal registers
+
+Example:
+
+	cpu_temp: thermal@920100 {
+		#thermal-sensor-cells = <0>;
+		compatible = "sigma,smp8758-thermal";
+		reg = <0x920100 12>;
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/thermal/tegra-soctherm.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/thermal/tegra-soctherm.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/thermal/tegra-soctherm.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/thermal/tegra-soctherm.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,55 +0,0 @@
-Tegra124 SOCTHERM thermal management system
-
-The SOCTHERM IP block contains thermal sensors, support for polled
-or interrupt-based thermal monitoring, CPU and GPU throttling based
-on temperature trip points, and handling external overcurrent
-notifications. It is also used to manage emergency shutdown in an
-overheating situation.
-
-Required properties :
-- compatible : For Tegra124, must contain "nvidia,tegra124-soctherm".
-  For Tegra132, must contain "nvidia,tegra132-soctherm".
-  For Tegra210, must contain "nvidia,tegra210-soctherm".
-- reg : Should contain 1 entry:
-  - SOCTHERM register set
-- interrupts : Defines the interrupt used by SOCTHERM
-- clocks : Must contain an entry for each entry in clock-names.
-  See ../clocks/clock-bindings.txt for details.
-- clock-names : Must include the following entries:
-  - tsensor
-  - soctherm
-- resets : Must contain an entry for each entry in reset-names.
-  See ../reset/reset.txt for details.
-- reset-names : Must include the following entries:
-  - soctherm
-- #thermal-sensor-cells : Should be 1. See ./thermal.txt for a description
-    of this property. See <dt-bindings/thermal/tegra124-soctherm.h> for a
-    list of valid values when referring to thermal sensors.
-
-
-Example :
-
-	soctherm@0,700e2000 {
-		compatible = "nvidia,tegra124-soctherm";
-		reg = <0x0 0x700e2000 0x0 0x1000>;
-		interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&tegra_car TEGRA124_CLK_TSENSOR>,
-			<&tegra_car TEGRA124_CLK_SOC_THERM>;
-		clock-names = "tsensor", "soctherm";
-		resets = <&tegra_car 78>;
-		reset-names = "soctherm";
-
-		#thermal-sensor-cells = <1>;
-	};
-
-Example: referring to thermal sensors :
-
-       thermal-zones {
-                cpu {
-                        polling-delay-passive = <1000>;
-                        polling-delay = <1000>;
-
-                        thermal-sensors =
-                                <&soctherm TEGRA124_SOCTHERM_SENSOR_CPU>;
-                };
-	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/thermal/thermal-generic-adc.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/thermal/thermal-generic-adc.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/thermal/thermal-generic-adc.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/thermal/thermal-generic-adc.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,89 @@
+General Purpose Analog To Digital Converter (ADC) based thermal sensor.
+
+On some of platforms, thermal sensor like thermistors are connected to
+one of ADC channel and sensor resistance is read via voltage across the
+sensor resistor. The voltage read across the sensor is mapped to
+temperature using voltage-temperature lookup table.
+
+Required properties:
+===================
+- compatible:		     Must be "generic-adc-thermal".
+- temperature-lookup-table:  Two dimensional array of Integer; lookup table
+			     to map the relation between ADC value and
+			     temperature. When ADC is read, the value is
+			     looked up on the table to get the equivalent
+			     temperature.
+			     The first value of the each row of array is the
+			     temperature in milliCelsius and second value of
+			     the each row of array is the ADC read value.
+- #thermal-sensor-cells:     Should be 1. See ./thermal.txt for a description
+			     of this property.
+
+Example :
+#include <dt-bindings/thermal/thermal.h>
+
+i2c@7000c400 {
+	ads1015: ads1015@4a {
+		reg = <0x4a>;
+		compatible = "ads1015";
+		sampling-frequency = <3300>;
+		#io-channel-cells = <1>;
+	};
+};
+
+tboard_thermistor: thermal-sensor {
+	compatible = "generic-adc-thermal";
+	#thermal-sensor-cells = <0>;
+	io-channels = <&ads1015 1>;
+	io-channel-names = "sensor-channel";
+	temperature-lookup-table = <    (-40000) 2578
+					(-39000) 2577
+					(-38000) 2576
+					(-37000) 2575
+					(-36000) 2574
+					(-35000) 2573
+					(-34000) 2572
+					(-33000) 2571
+					(-32000) 2569
+					(-31000) 2568
+					(-30000) 2567
+					::::::::::
+					118000 254
+					119000 247
+					120000 240
+					121000 233
+					122000 226
+					123000 220
+					124000 214
+					125000 208>;
+};
+
+dummy_cool_dev: dummy-cool-dev {
+	compatible = "dummy-cooling-dev";
+	#cooling-cells = <2>; /* min followed by max */
+};
+
+thermal-zones {
+	Tboard {
+		polling-delay = <15000>; /* milliseconds */
+		polling-delay-passive = <0>; /* milliseconds */
+		thermal-sensors = <&tboard_thermistor>;
+
+		trips {
+			therm_est_trip: therm_est_trip {
+				temperature = <40000>;
+				type = "active";
+				hysteresis = <1000>;
+			};
+		};
+
+		cooling-maps {
+			map0 {
+				trip = <&therm_est_trip>;
+				cooling-device = <&dummy_cool_dev THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+				contribution = <100>;
+			};
+
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/timer/arm,mps2-timer.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/timer/arm,mps2-timer.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/timer/arm,mps2-timer.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/timer/arm,mps2-timer.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,28 @@
+ARM MPS2 timer
+
+The MPS2 platform has simple general-purpose 32 bits timers.
+
+Required properties:
+- compatible	: Should be "arm,mps2-timer"
+- reg		: Address and length of the register set
+- interrupts	: Reference to the timer interrupt
+
+Required clocking property, have to be one of:
+- clocks	  : The input clock of the timer
+- clock-frequency : The rate in HZ in input of the ARM MPS2 timer
+
+Examples:
+
+timer1: mps2-timer@40000000 {
+	compatible = "arm,mps2-timer";
+	reg = <0x40000000 0x1000>;
+	interrupts = <8>;
+	clocks = <&sysclk>;
+};
+
+timer2: mps2-timer@40001000 {
+	compatible = "arm,mps2-timer";
+	reg = <0x40001000 0x1000>;
+	interrupts = <9>;
+	clock-frequency = <25000000>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,15 @@
+NPS Network Processor
+
+Required properties:
+
+- compatible :	should be "ezchip,nps400-timer"
+
+Clocks required for compatible = "ezchip,nps400-timer":
+- clocks : Must contain a single entry describing the clock input
+
+Example:
+
+timer {
+	compatible = "ezchip,nps400-timer";
+	clocks = <&sysclk>;
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/timer/snps,archs-gfrc.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/timer/snps,archs-gfrc.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/timer/snps,archs-gfrc.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/timer/snps,archs-gfrc.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,14 @@
+Synopsys ARC Free Running 64-bit Global Timer for ARC HS CPUs
+- clocksource provider for SMP SoC
+
+Required properties:
+
+- compatible : should be "snps,archs-gfrc"
+- clocks     : phandle to the source clock
+
+Example:
+
+	gfrc {
+		compatible = "snps,archs-gfrc";
+		clocks = <&core_clk>;
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/timer/snps,archs-rtc.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/timer/snps,archs-rtc.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/timer/snps,archs-rtc.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/timer/snps,archs-rtc.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,14 @@
+Synopsys ARC Free Running 64-bit Local Timer for ARC HS CPUs
+- clocksource provider for UP SoC
+
+Required properties:
+
+- compatible : should be "snps,archs-rtc"
+- clocks     : phandle to the source clock
+
+Example:
+
+	rtc {
+		compatible = "snps,arc-rtc";
+		clocks = <&core_clk>;
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/timer/snps,arc-timer.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/timer/snps,arc-timer.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/timer/snps,arc-timer.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/timer/snps,arc-timer.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,31 @@
+Synopsys ARC Local Timer with Interrupt Capabilities
+- Found on all ARC CPUs (ARC700/ARCHS)
+- Can be optionally programmed to interrupt on Limit
+- Two idential copies TIMER0 and TIMER1 exist in ARC cores and historically
+  TIMER0 used as clockevent provider (true for all ARC cores)
+  TIMER1 used for clocksource (mandatory for ARC700, optional for ARC HS)
+
+Required properties:
+
+- compatible : should be "snps,arc-timer"
+- interrupts : single Interrupt going into parent intc
+	       (16 for ARCHS cores, 3 for ARC700 cores)
+- clocks     : phandle to the source clock
+
+Optional properties:
+
+- interrupt-parent : phandle to parent intc
+
+Example:
+
+	timer0 {
+		compatible = "snps,arc-timer";
+		interrupts = <3>;
+		interrupt-parent = <&core_intc>;
+		clocks = <&core_clk>;
+	};
+
+	timer1 {
+		compatible = "snps,arc-timer";
+		clocks = <&core_clk>;
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/tty/serial/mvebu-uart.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/tty/serial/mvebu-uart.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/tty/serial/mvebu-uart.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/tty/serial/mvebu-uart.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,13 +0,0 @@
-* Marvell UART : Non standard UART used in some of Marvell EBU SoCs (e.g., Armada-3700)
-
-Required properties:
-- compatible: "marvell,armada-3700-uart"
-- reg: offset and length of the register set for the device.
-- interrupts: device interrupt
-
-Example:
-	serial@12000 {
-		compatible = "marvell,armada-3700-uart";
-		reg = <0x12000 0x400>;
-		interrupts = <43>;
-	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/usb/dwc3.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/usb/dwc3.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/usb/dwc3.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/usb/dwc3.txt	2016-07-24 15:23:50.000000000 -0400
@@ -14,7 +14,6 @@ Optional properties:
    the second element is expected to be a handle to the USB3/SS PHY
  - phys: from the *Generic PHY* bindings
  - phy-names: from the *Generic PHY* bindings
- - tx-fifo-resize: determines if the FIFO *has* to be reallocated.
  - snps,usb3_lpm_capable: determines if platform is USB3 LPM capable
  - snps,disable_scramble_quirk: true when SW should disable data scrambling.
 	Only really useful for FPGA builds.
@@ -38,6 +37,8 @@ Optional properties:
  - snps,dis_u2_susphy_quirk: when set core will disable USB2 suspend phy.
  - snps,dis_enblslpm_quirk: when set clears the enblslpm in GUSB2PHYCFG,
 			disabling the suspend signal to the PHY.
+ - snps,dis_rxdet_inp3_quirk: when set core will disable receiver detection
+			in PHY P3 power state.
  - snps,is-utmi-l1-suspend: true when DWC3 asserts output signal
 			utmi_l1_suspend_n, false when asserts utmi_sleep_n
  - snps,hird-threshold: HIRD threshold
@@ -47,6 +48,8 @@ Optional properties:
 	register for post-silicon frame length adjustment when the
 	fladj_30mhz_sdbnd signal is invalid or incorrect.
 
+ - <DEPRECATED> tx-fifo-resize: determines if the FIFO *has* to be reallocated.
+
 This is usually a subnode to DWC3 glue to which it is connected.
 
 dwc3@4a030000 {
@@ -54,5 +57,4 @@ dwc3@4a030000 {
 	reg = <0x4a030000 0xcfff>;
 	interrupts = <0 92 4>
 	usb-phy = <&usb2_phy>, <&usb3,phy>;
-	tx-fifo-resize;
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/usb/nvidia,tegra124-xusb.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/usb/nvidia,tegra124-xusb.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/usb/nvidia,tegra124-xusb.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/usb/nvidia,tegra124-xusb.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,120 @@
+NVIDIA Tegra xHCI controller
+============================
+
+The Tegra xHCI controller supports both USB2 and USB3 interfaces exposed by
+the Tegra XUSB pad controller.
+
+Required properties:
+--------------------
+- compatible: Must be:
+  - Tegra124: "nvidia,tegra124-xusb"
+  - Tegra132: "nvidia,tegra132-xusb", "nvidia,tegra124-xusb"
+  - Tegra210: "nvidia,tegra210-xusb"
+- reg: Must contain the base and length of the xHCI host registers, XUSB FPCI
+  registers and XUSB IPFS registers.
+- reg-names: Must contain the following entries:
+  - "hcd"
+  - "fpci"
+  - "ipfs"
+- interrupts: Must contain the xHCI host interrupt and the mailbox interrupt.
+- clocks: Must contain an entry for each entry in clock-names.
+  See ../clock/clock-bindings.txt for details.
+- clock-names: Must include the following entries:
+   - xusb_host
+   - xusb_host_src
+   - xusb_falcon_src
+   - xusb_ss
+   - xusb_ss_src
+   - xusb_ss_div2
+   - xusb_hs_src
+   - xusb_fs_src
+   - pll_u_480m
+   - clk_m
+   - pll_e
+- resets: Must contain an entry for each entry in reset-names.
+  See ../reset/reset.txt for details.
+- reset-names: Must include the following entries:
+  - xusb_host
+  - xusb_ss
+  - xusb_src
+  Note that xusb_src is the shared reset for xusb_{ss,hs,fs,falcon,host}_src.
+- nvidia,xusb-padctl: phandle to the XUSB pad controller that is used to
+  configure the USB pads used by the XHCI controller
+
+For Tegra124 and Tegra132:
+- avddio-pex-supply: PCIe/USB3 analog logic power supply. Must supply 1.05 V.
+- dvddio-pex-supply: PCIe/USB3 digital logic power supply. Must supply 1.05 V.
+- avdd-usb-supply: USB controller power supply. Must supply 3.3 V.
+- avdd-pll-utmip-supply: UTMI PLL power supply. Must supply 1.8 V.
+- avdd-pll-erefe-supply: PLLE reference PLL power supply. Must supply 1.05 V.
+- avdd-usb-ss-pll-supply: PCIe/USB3 PLL power supply. Must supply 1.05 V.
+- hvdd-usb-ss-supply: High-voltage PCIe/USB3 power supply. Must supply 3.3 V.
+- hvdd-usb-ss-pll-e-supply: High-voltage PLLE power supply. Must supply 3.3 V.
+
+For Tegra210:
+- dvddio-pex-supply: PCIe/USB3 analog logic power supply. Must supply 1.05 V.
+- hvddio-pex-supply: High-voltage PCIe/USB3 power supply. Must supply 1.8 V.
+- avdd-usb-supply: USB controller power supply. Must supply 3.3 V.
+- avdd-pll-utmip-supply: UTMI PLL power supply. Must supply 1.8 V.
+- avdd-pll-uerefe-supply: PLLE reference PLL power supply. Must supply 1.05 V.
+- dvdd-pex-pll-supply: PCIe/USB3 PLL power supply. Must supply 1.05 V.
+- hvdd-pex-pll-e-supply: High-voltage PLLE power supply. Must supply 1.8 V.
+
+Optional properties:
+--------------------
+- phys: Must contain an entry for each entry in phy-names.
+  See ../phy/phy-bindings.txt for details.
+- phy-names: Should include an entry for each PHY used by the controller. The
+  following PHYs are available:
+  - Tegra124: usb2-0, usb2-1, usb2-2, hsic-0, hsic-1, usb3-0, usb3-1
+  - Tegra132: usb2-0, usb2-1, usb2-2, hsic-0, hsic-1, usb3-0, usb3-1
+  - Tegra210: usb2-0, usb2-1, usb2-2, usb2-3, hsic-0, usb3-0, usb3-1, usb3-2,
+              usb3-3
+
+Example:
+--------
+
+	usb@0,70090000 {
+		compatible = "nvidia,tegra124-xusb";
+		reg = <0x0 0x70090000 0x0 0x8000>,
+		      <0x0 0x70098000 0x0 0x1000>,
+		      <0x0 0x70099000 0x0 0x1000>;
+		reg-names = "hcd", "fpci", "ipfs";
+
+		interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+
+		clocks = <&tegra_car TEGRA124_CLK_XUSB_HOST>,
+			 <&tegra_car TEGRA124_CLK_XUSB_HOST_SRC>,
+			 <&tegra_car TEGRA124_CLK_XUSB_FALCON_SRC>,
+			 <&tegra_car TEGRA124_CLK_XUSB_SS>,
+			 <&tegra_car TEGRA124_CLK_XUSB_SS_DIV2>,
+			 <&tegra_car TEGRA124_CLK_XUSB_SS_SRC>,
+			 <&tegra_car TEGRA124_CLK_XUSB_HS_SRC>,
+			 <&tegra_car TEGRA124_CLK_XUSB_FS_SRC>,
+			 <&tegra_car TEGRA124_CLK_PLL_U_480M>,
+			 <&tegra_car TEGRA124_CLK_CLK_M>,
+			 <&tegra_car TEGRA124_CLK_PLL_E>;
+		clock-names = "xusb_host", "xusb_host_src", "xusb_falcon_src",
+			      "xusb_ss", "xusb_ss_div2", "xusb_ss_src",
+			      "xusb_hs_src", "xusb_fs_src", "pll_u_480m",
+			      "clk_m", "pll_e";
+		resets = <&tegra_car 89>, <&tegra_car 156>, <&tegra_car 143>;
+		reset-names = "xusb_host", "xusb_ss", "xusb_src";
+
+		nvidia,xusb-padctl = <&padctl>;
+
+		phys = <&{/padctl@0,7009f000/pads/usb2/usb2-1}>, /* mini-PCIe USB */
+		       <&{/padctl@0,7009f000/pads/usb2/usb2-2}>, /* USB A */
+		       <&{/padctl@0,7009f000/pads/pcie/pcie-0}>; /* USB A */
+		phy-names = "utmi-1", "utmi-2", "usb3-0";
+
+		avddio-pex-supply = <&vdd_1v05_run>;
+		dvddio-pex-supply = <&vdd_1v05_run>;
+		avdd-usb-supply = <&vdd_3v3_lp0>;
+		avdd-pll-utmip-supply = <&vddio_1v8>;
+		avdd-pll-erefe-supply = <&avdd_1v05_run>;
+		avdd-usb-ss-pll-supply = <&vdd_1v05_run>;
+		hvdd-usb-ss-supply = <&vdd_3v3_lp0>;
+		hvdd-usb-ss-pll-e-supply = <&vdd_3v3_lp0>;
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/usb/qcom,dwc3.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/usb/qcom,dwc3.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/usb/qcom,dwc3.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/usb/qcom,dwc3.txt	2016-07-24 15:23:50.000000000 -0400
@@ -59,7 +59,6 @@ Example device nodes:
 				interrupts = <0 205 0x4>;
 				phys = <&hs_phy>, <&ss_phy>;
 				phy-names = "usb2-phy", "usb3-phy";
-				tx-fifo-resize;
 				dr_mode = "host";
 			};
 		};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/usb/usb-xhci.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/usb/usb-xhci.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/usb/usb-xhci.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/usb/usb-xhci.txt	2016-07-24 15:23:50.000000000 -0400
@@ -4,6 +4,7 @@ Required properties:
   - compatible: should be one or more of
 
     - "generic-xhci" for generic XHCI device
+    - "marvell,armada3700-xhci" for Armada 37xx SoCs
     - "marvell,armada-375-xhci" for Armada 375 SoCs
     - "marvell,armada-380-xhci" for Armada 38x SoCs
     - "renesas,xhci-r8a7790" for r8a7790 SoC
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/vendor-prefixes.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/vendor-prefixes.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/vendor-prefixes.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/vendor-prefixes.txt	2016-07-24 15:23:50.000000000 -0400
@@ -16,19 +16,23 @@ al	Annapurna Labs
 allwinner	Allwinner Technology Co., Ltd.
 alphascale	AlphaScale Integrated Circuits Systems, Inc.
 altr	Altera Corp.
+amazon	Amazon.com, Inc.
 amcc	Applied Micro Circuits Corporation (APM, formally AMCC)
 amd	Advanced Micro Devices (AMD), Inc.
 amlogic	Amlogic, Inc.
 ampire	Ampire Co., Ltd.
 ams	AMS AG
 amstaos	AMS-Taos Inc.
+analogix	Analogix Semiconductor, Inc.
 apm	Applied Micro Circuits Corporation (APM)
 aptina	Aptina Imaging
 arasan	Arasan Chip Systems
 arm	ARM Ltd.
 armadeus	ARMadeus Systems SARL
+arrow	Arrow Electronics
 artesyn	Artesyn Embedded Technologies Inc.
 asahi-kasei	Asahi Kasei Corp.
+aspeed	ASPEED Technology Inc.
 atlas	Atlas Scientific LLC
 atmel	Atmel Corporation
 auo	AU Optronics Corporation
@@ -58,6 +62,7 @@ cnxt	Conexant Systems, Inc.
 compulab	CompuLab Ltd.
 cortina	Cortina Systems, Inc.
 cosmic	Cosmic Circuits
+creative	Creative Technology Ltd
 crystalfontz	Crystalfontz America, Inc.
 cubietech	Cubietech, Ltd.
 cypress	Cypress Semiconductor Corporation
@@ -70,11 +75,14 @@ digilent	Diglent, Inc.
 dlg	Dialog Semiconductor
 dlink	D-Link Corporation
 dmo	Data Modul AG
+dptechnics	DPTechnics
+dragino	Dragino Technology Co., Limited
 ea	Embedded Artists AB
 ebv	EBV Elektronik
 edt	Emerging Display Technologies
 eeti	eGalax_eMPIA Technology Inc
 elan	Elan Microelectronic Corp.
+embest	Shenzhen Embest Technology Co., Ltd.
 emmicro	EM Microelectronic
 energymicro	Silicon Laboratories (formerly Energy Micro AS)
 epcos	EPCOS AG
@@ -86,11 +94,13 @@ eukrea  Eukréa Electromatique
 everest	Everest Semiconductor Co. Ltd.
 everspin	Everspin Technologies, Inc.
 excito	Excito
+ezchip	EZchip Semiconductor
 fcs	Fairchild Semiconductor
 firefly	Firefly
 focaltech	FocalTech Systems Co.,Ltd
 fsl	Freescale Semiconductor
 ge	General Electric Company
+geekbuying	GeekBuying
 GEFanuc	GE Fanuc Intelligent Platforms Embedded Systems, Inc.
 gef	GE Fanuc Intelligent Platforms Embedded Systems, Inc.
 geniatech	Geniatech, Inc.
@@ -118,6 +128,7 @@ idt	Integrated Device Technologies, Inc.
 ifi	Ingenieurburo Fur Ic-Technologie (I/F/I)
 iom	Iomega Corporation
 img	Imagination Technologies Ltd.
+inforce	Inforce Computing
 ingenic	Ingenic Semiconductor
 innolux	Innolux Corporation
 intel	Intel Corporation
@@ -141,6 +152,7 @@ lsi	LSI Corp. (LSI Logic)
 lltc	Linear Technology Corporation
 marvell	Marvell Technology Group Ltd.
 maxim	Maxim Integrated Products
+meas	Measurement Specialties
 mediatek	MediaTek Inc.
 melexis	Melexis N.V.
 merrii	Merrii Technology Co., Ltd.
@@ -152,6 +164,7 @@ mitsubishi	Mitsubishi Electric Corporati
 mosaixtech	Mosaix Technologies, Inc.
 moxa	Moxa
 mpl	MPL AG
+mqmaker	mqmaker Inc.
 msi	Micro-Star International Co. Ltd.
 mti	Imagination Technologies Ltd. (formerly MIPS Technologies Inc.)
 mundoreader	Mundo Reader S.L.
@@ -171,12 +184,15 @@ nvidia	NVIDIA
 nxp	NXP Semiconductors
 okaya	Okaya Electric America, Inc.
 olimex	OLIMEX Ltd.
+onion	Onion Corporation
 onnn	ON Semiconductor Corp.
+ontat	On Tat Industrial Company
 opencores	OpenCores.org
 option	Option NV
 ortustech	Ortus Technology Co., Ltd.
 ovti	OmniVision Technologies
 ORCL	Oracle Corporation
+oxsemi	Oxford Semiconductor, Ltd.
 panasonic	Panasonic Corporation
 parade	Parade Technologies Inc.
 pericom	Pericom Technology Inc.
@@ -239,6 +255,7 @@ synology	Synology, Inc.
 SUNW	Sun Microsystems, Inc
 tbs	TBS Technologies
 tcl	Toby Churchill Ltd.
+technexion	TechNexion
 technologic	Technologic Systems
 thine	THine Electronics, Inc.
 ti	Texas Instruments
@@ -247,10 +264,13 @@ toradex	Toradex AG
 toshiba	Toshiba Corporation
 toumaz	Toumaz
 tplink	TP-LINK Technologies Co., Ltd.
+tpk	TPK U.S.A. LLC
 tronfy	Tronfy
 tronsmart	Tronsmart
 truly	Truly Semiconductors Limited
+tyan	Tyan Computer Corporation
 upisemi	uPI Semiconductor Corp.
+uniwest	United Western Technologies Corp (UniWest)
 urt	United Radiant Technology Corporation
 usi	Universal Scientific Industrial Co., Ltd.
 v3	V3 Semiconductor
@@ -259,6 +279,7 @@ via	VIA Technologies, Inc.
 virtio	Virtual I/O Device Specification, developed by the OASIS consortium
 vivante	Vivante Corporation
 voipac	Voipac Technologies s.r.o.
+wd	Western Digital Corp.
 wexler	Wexler
 winbond Winbond Electronics corp.
 wlf	Wolfson Microelectronics
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/video/bridge/anx7814.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/video/bridge/anx7814.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/video/bridge/anx7814.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/video/bridge/anx7814.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,40 @@
+Analogix ANX7814 SlimPort (Full-HD Transmitter)
+-----------------------------------------------
+
+The ANX7814 is an ultra-low power Full-HD (1080p60) SlimPort transmitter
+designed for portable devices.
+
+Required properties:
+
+ - compatible		: "analogix,anx7814"
+ - reg			: I2C address of the device
+ - interrupt-parent	: Should be the phandle of the interrupt controller
+			  that services interrupts for this device
+ - interrupts		: Should contain the INTP interrupt
+ - hpd-gpios		: Which GPIO to use for hpd
+ - pd-gpios		: Which GPIO to use for power down
+ - reset-gpios		: Which GPIO to use for reset
+
+Optional properties:
+
+ - dvdd10-supply	: Regulator for 1.0V digital core power.
+ - Video port for HDMI input, using the DT bindings defined in [1].
+
+[1]: Documentation/devicetree/bindings/media/video-interfaces.txt
+
+Example:
+
+	anx7814: anx7814@38 {
+		compatible = "analogix,anx7814";
+		reg = <0x38>;
+		interrupt-parent = <&gpio0>;
+		interrupts = <99 IRQ_TYPE_LEVEL_LOW>;   /* INTP */
+		hpd-gpios = <&pio 36 GPIO_ACTIVE_HIGH>;
+		pd-gpios = <&pio 33 GPIO_ACTIVE_HIGH>;
+		reset-gpios = <&pio 98 GPIO_ACTIVE_HIGH>;
+		port {
+			anx7814_in: endpoint {
+				remote-endpoint = <&hdmi0_out>;
+			};
+		};
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.txt	2016-07-24 15:23:50.000000000 -0400
@@ -5,10 +5,12 @@ Required properties:
 - reg : Should contain WDT registers location and length
 - interrupts : Should contain WDT interrupt
 
-Optional property:
+Optional properties:
 - big-endian: If present the watchdog device's registers are implemented
   in big endian mode, otherwise in native mode(same with CPU), for more
   detail please see: Documentation/devicetree/bindings/regmap/regmap.txt.
+- fsl,ext-reset-output: If present the watchdog device is configured to
+  assert its external reset (WDOG_B) instead of issuing a software reset.
 
 Examples:
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/watchdog/microchip,pic32-dmt.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/watchdog/microchip,pic32-dmt.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/watchdog/microchip,pic32-dmt.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/watchdog/microchip,pic32-dmt.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,19 @@
+* Microchip PIC32 Deadman Timer
+
+The deadman timer is used to reset the processor in the event of a software
+malfunction. It is a free-running instruction fetch timer, which is clocked
+whenever an instruction fetch occurs until a count match occurs.
+
+Required properties:
+- compatible: must be "microchip,pic32mzda-dmt".
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- clocks: phandle of source clk. Should be <&rootclk PB7CLK>.
+
+Example:
+
+	watchdog@1f800a00 {
+		compatible = "microchip,pic32mzda-dmt";
+		reg = <0x1f800a00 0x80>;
+		clocks = <&rootclk PB7CLK>;
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/watchdog/microchip,pic32-wdt.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/watchdog/microchip,pic32-wdt.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/watchdog/microchip,pic32-wdt.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/watchdog/microchip,pic32-wdt.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,18 @@
+* Microchip PIC32 Watchdog Timer
+
+When enabled, the watchdog peripheral can be used to reset the device if the
+WDT is not cleared periodically in software.
+
+Required properties:
+- compatible: must be "microchip,pic32mzda-wdt".
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- clocks: phandle of source clk. Should be <&rootclk LPRCCLK>.
+
+Example:
+
+	watchdog@1f800800 {
+		compatible = "microchip,pic32mzda-wdt";
+		reg = <0x1f800800 0x200>;
+		clocks = <&rootclk LPRCCLK>;
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/devicetree/bindings/watchdog/renesas-wdt.txt linux-libre-4.7-gnu/Documentation/devicetree/bindings/watchdog/renesas-wdt.txt
--- linux-libre-4.6-gnu/Documentation/devicetree/bindings/watchdog/renesas-wdt.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/devicetree/bindings/watchdog/renesas-wdt.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,25 @@
+Renesas Watchdog Timer (WDT) Controller
+
+Required properties:
+- compatible : Should be "renesas,r8a7795-wdt", or "renesas,rcar-gen3-wdt"
+
+  When compatible with the generic version, nodes must list the SoC-specific
+  version corresponding to the platform first, followed by the generic
+  version.
+
+- reg : Should contain WDT registers location and length
+- clocks : the clock feeding the watchdog timer.
+
+Optional properties:
+- timeout-sec : Contains the watchdog timeout in seconds
+- power-domains : the power domain the WDT belongs to
+
+Examples:
+
+	wdt0: watchdog@e6020000 {
+		compatible = "renesas,r8a7795-wdt", "renesas,rcar-gen3-wdt";
+		reg = <0 0xe6020000 0 0x0c>;
+		clocks = <&cpg CPG_MOD 402>;
+		power-domains = <&cpg>;
+		timeout-sec = <60>;
+	};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/DocBook/80211.tmpl linux-libre-4.7-gnu/Documentation/DocBook/80211.tmpl
--- linux-libre-4.6-gnu/Documentation/DocBook/80211.tmpl	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/DocBook/80211.tmpl	2016-07-24 15:23:50.000000000 -0400
@@ -75,7 +75,6 @@
       <chapter>
       <title>Device registration</title>
 !Pinclude/net/cfg80211.h Device registration
-!Finclude/net/cfg80211.h ieee80211_band
 !Finclude/net/cfg80211.h ieee80211_channel_flags
 !Finclude/net/cfg80211.h ieee80211_channel
 !Finclude/net/cfg80211.h ieee80211_rate_flags
@@ -136,6 +135,7 @@
 !Finclude/net/cfg80211.h cfg80211_tx_mlme_mgmt
 !Finclude/net/cfg80211.h cfg80211_ibss_joined
 !Finclude/net/cfg80211.h cfg80211_connect_result
+!Finclude/net/cfg80211.h cfg80211_connect_bss
 !Finclude/net/cfg80211.h cfg80211_roamed
 !Finclude/net/cfg80211.h cfg80211_disconnected
 !Finclude/net/cfg80211.h cfg80211_ready_on_channel
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/DocBook/crypto-API.tmpl linux-libre-4.7-gnu/Documentation/DocBook/crypto-API.tmpl
--- linux-libre-4.6-gnu/Documentation/DocBook/crypto-API.tmpl	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/DocBook/crypto-API.tmpl	2016-07-24 15:23:50.000000000 -0400
@@ -1936,9 +1936,9 @@ static int test_skcipher(void)
 	}
 
 	req = skcipher_request_alloc(skcipher, GFP_KERNEL);
-	if (IS_ERR(req)) {
-		pr_info("could not allocate request queue\n");
-		ret = PTR_ERR(req);
+	if (!req) {
+		pr_info("could not allocate skcipher request\n");
+		ret = -ENOMEM;
 		goto out;
 	}
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/DocBook/debugobjects.tmpl linux-libre-4.7-gnu/Documentation/DocBook/debugobjects.tmpl
--- linux-libre-4.6-gnu/Documentation/DocBook/debugobjects.tmpl	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/DocBook/debugobjects.tmpl	2016-07-24 15:23:50.000000000 -0400
@@ -316,8 +316,8 @@
 	</itemizedlist>
       </para>
       <para>
-	The function returns 1 when the fixup was successful,
-	otherwise 0. The return value is used to update the
+	The function returns true when the fixup was successful,
+	otherwise false. The return value is used to update the
 	statistics.
       </para>
       <para>
@@ -341,8 +341,8 @@
 	</itemizedlist>
       </para>
       <para>
-	The function returns 1 when the fixup was successful,
-	otherwise 0. The return value is used to update the
+	The function returns true when the fixup was successful,
+	otherwise false. The return value is used to update the
 	statistics.
       </para>
       <para>
@@ -359,7 +359,8 @@
 	statically initialized object or not. In case it is it calls
 	debug_object_init() and debug_object_activate() to make the
 	object known to the tracker and marked active. In this case
-	the function should return 0 because this is not a real fixup.
+	the function should return false because this is not a real
+	fixup.
       </para>
     </sect1>
 
@@ -376,8 +377,8 @@
 	</itemizedlist>
       </para>
       <para>
-	The function returns 1 when the fixup was successful,
-	otherwise 0. The return value is used to update the
+	The function returns true when the fixup was successful,
+	otherwise false. The return value is used to update the
 	statistics.
       </para>
     </sect1>
@@ -397,8 +398,8 @@
 	</itemizedlist>
       </para>
       <para>
-	The function returns 1 when the fixup was successful,
-	otherwise 0. The return value is used to update the
+	The function returns true when the fixup was successful,
+	otherwise false. The return value is used to update the
 	statistics.
       </para>
     </sect1>
@@ -414,8 +415,8 @@
 	debug bucket.
       </para>
       <para>
-	The function returns 1 when the fixup was successful,
-	otherwise 0. The return value is used to update the
+	The function returns true when the fixup was successful,
+	otherwise false. The return value is used to update the
 	statistics.
       </para>
       <para>
@@ -427,7 +428,8 @@
 	case. The fixup function should check if this is a legitimate
 	case of a statically initialized object or not. In this case only
 	debug_object_init() should be called to make the object known to
-	the tracker. Then the function should return 0 because this is not
+	the tracker. Then the function should return false because this
+	is not
 	a real fixup.
       </para>
     </sect1>
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/DocBook/device-drivers.tmpl linux-libre-4.7-gnu/Documentation/DocBook/device-drivers.tmpl
--- linux-libre-4.6-gnu/Documentation/DocBook/device-drivers.tmpl	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/DocBook/device-drivers.tmpl	2016-07-24 15:23:50.000000000 -0400
@@ -128,14 +128,44 @@ X!Edrivers/base/interface.c
 !Edrivers/base/platform.c
 !Edrivers/base/bus.c
      </sect1>
-     <sect1><title>Device Drivers DMA Management</title>
+     <sect1>
+       <title>Buffer Sharing and Synchronization</title>
+       <para>
+         The dma-buf subsystem provides the framework for sharing buffers
+         for hardware (DMA) access across multiple device drivers and
+         subsystems, and for synchronizing asynchronous hardware access.
+       </para>
+       <para>
+         This is used, for example, by drm "prime" multi-GPU support, but
+         is of course not limited to GPU use cases.
+       </para>
+       <para>
+         The three main components of this are: (1) dma-buf, representing
+         a sg_table and exposed to userspace as a file descriptor to allow
+         passing between devices, (2) fence, which provides a mechanism
+         to signal when one device as finished access, and (3) reservation,
+         which manages the shared or exclusive fence(s) associated with
+         the buffer.
+       </para>
+       <sect2><title>dma-buf</title>
 !Edrivers/dma-buf/dma-buf.c
+!Iinclude/linux/dma-buf.h
+       </sect2>
+       <sect2><title>reservation</title>
+!Pdrivers/dma-buf/reservation.c Reservation Object Overview
+!Edrivers/dma-buf/reservation.c
+!Iinclude/linux/reservation.h
+       </sect2>
+       <sect2><title>fence</title>
 !Edrivers/dma-buf/fence.c
-!Edrivers/dma-buf/seqno-fence.c
 !Iinclude/linux/fence.h
+!Edrivers/dma-buf/seqno-fence.c
 !Iinclude/linux/seqno-fence.h
-!Edrivers/dma-buf/reservation.c
-!Iinclude/linux/reservation.h
+!Edrivers/dma-buf/sync_file.c
+!Iinclude/linux/sync_file.h
+       </sect2>
+     </sect1>
+     <sect1><title>Device Drivers DMA Management</title>
 !Edrivers/base/dma-coherent.c
 !Edrivers/base/dma-mapping.c
      </sect1>
@@ -233,6 +263,7 @@ X!Isound/sound_firmware.c
 !Iinclude/media/v4l2-mediabus.h
 !Iinclude/media/v4l2-mem2mem.h
 !Iinclude/media/v4l2-of.h
+!Iinclude/media/v4l2-rect.h
 !Iinclude/media/v4l2-subdev.h
 !Iinclude/media/videobuf2-core.h
 !Iinclude/media/videobuf2-v4l2.h
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/DocBook/gpu.tmpl linux-libre-4.7-gnu/Documentation/DocBook/gpu.tmpl
--- linux-libre-4.6-gnu/Documentation/DocBook/gpu.tmpl	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/DocBook/gpu.tmpl	2016-07-24 15:23:50.000000000 -0400
@@ -1617,12 +1617,23 @@ void intel_crt_init(struct drm_device *d
 !Iinclude/drm/drm_fb_helper.h
     </sect2>
     <sect2>
+      <title>Framebuffer CMA Helper Functions Reference</title>
+!Pdrivers/gpu/drm/drm_fb_cma_helper.c framebuffer cma helper functions
+!Edrivers/gpu/drm/drm_fb_cma_helper.c
+    </sect2>
+    <sect2>
       <title>Display Port Helper Functions Reference</title>
 !Pdrivers/gpu/drm/drm_dp_helper.c dp helpers
 !Iinclude/drm/drm_dp_helper.h
 !Edrivers/gpu/drm/drm_dp_helper.c
     </sect2>
     <sect2>
+      <title>Display Port Dual Mode Adaptor Helper Functions Reference</title>
+!Pdrivers/gpu/drm/drm_dp_dual_mode_helper.c dp dual mode helpers
+!Iinclude/drm/drm_dp_dual_mode_helper.h
+!Edrivers/gpu/drm/drm_dp_dual_mode_helper.c
+    </sect2>
+    <sect2>
       <title>Display Port MST Helper Functions Reference</title>
 !Pdrivers/gpu/drm/drm_dp_mst_topology.c dp mst helper
 !Iinclude/drm/drm_dp_mst_helper.h
@@ -1671,17 +1682,23 @@ void intel_crt_init(struct drm_device *d
 !Pdrivers/gpu/drm/drm_crtc.c Tile group
     </sect2>
     <sect2>
-	<title>Bridges</title>
+      <title>Bridges</title>
       <sect3>
-	 <title>Overview</title>
+        <title>Overview</title>
 !Pdrivers/gpu/drm/drm_bridge.c overview
       </sect3>
       <sect3>
-	 <title>Default bridge callback sequence</title>
+        <title>Default bridge callback sequence</title>
 !Pdrivers/gpu/drm/drm_bridge.c bridge callbacks
       </sect3>
 !Edrivers/gpu/drm/drm_bridge.c
     </sect2>
+    <sect2>
+      <title>Panel Helper Reference</title>
+!Iinclude/drm/drm_panel.h
+!Edrivers/gpu/drm/drm_panel.c
+!Pdrivers/gpu/drm/drm_panel.c drm panel
+    </sect2>
   </sect1>
 
   <!-- Internals: kms properties -->
@@ -1817,7 +1834,7 @@ void intel_crt_init(struct drm_device *d
 	</tr>
 	<tr>
 	<td rowspan="42" valign="top" >DRM</td>
-	<td valign="top" >Generic</td>
+	<td rowspan="2" valign="top" >Generic</td>
 	<td valign="top" >“rotation”</td>
 	<td valign="top" >BITMASK</td>
 	<td valign="top" >{ 0, "rotate-0" },
@@ -1832,6 +1849,13 @@ void intel_crt_init(struct drm_device *d
 	image along the specified axis prior to rotation</td>
 	</tr>
 	<tr>
+	<td valign="top" >“scaling mode”</td>
+	<td valign="top" >ENUM</td>
+	<td valign="top" >{ "None", "Full", "Center", "Full aspect" }</td>
+	<td valign="top" >Connector</td>
+	<td valign="top" >Supported by: amdgpu, gma500, i915, nouveau and radeon.</td>
+	</tr>
+	<tr>
 	<td rowspan="5" valign="top" >Connector</td>
 	<td valign="top" >“EDID”</td>
 	<td valign="top" >BLOB | IMMUTABLE</td>
@@ -2068,21 +2092,12 @@ void intel_crt_init(struct drm_device *d
 	<td valign="top" >property to suggest an Y offset for a connector</td>
 	</tr>
 	<tr>
-	<td rowspan="8" valign="top" >Optional</td>
-	<td valign="top" >“scaling mode”</td>
-	<td valign="top" >ENUM</td>
-	<td valign="top" >{ "None", "Full", "Center", "Full aspect" }</td>
-	<td valign="top" >Connector</td>
-	<td valign="top" >TBD</td>
-	</tr>
-	<tr>
+	<td rowspan="7" valign="top" >Optional</td>
 	<td valign="top" >"aspect ratio"</td>
 	<td valign="top" >ENUM</td>
 	<td valign="top" >{ "None", "4:3", "16:9" }</td>
 	<td valign="top" >Connector</td>
-	<td valign="top" >DRM property to set aspect ratio from user space app.
-		This enum is made generic to allow addition of custom aspect
-		ratios.</td>
+	<td valign="top" >TDB</td>
 	</tr>
 	<tr>
 	<td valign="top" >“dirty”</td>
@@ -2153,7 +2168,11 @@ void intel_crt_init(struct drm_device *d
 	<td valign="top" >ENUM</td>
 	<td valign="top" >{ "Automatic", "Full", "Limited 16:235" }</td>
 	<td valign="top" >Connector</td>
-	<td valign="top" >TBD</td>
+	<td valign="top" >When this property is set to Limited 16:235
+		and CTM is set, the hardware will be programmed with the
+		result of the multiplication of CTM by the limited range
+		matrix to ensure the pixels normaly in the range 0..1.0 are
+		remapped to the range 16/255..235/255.</td>
 	</tr>
 	<tr>
 	<td valign="top" >“audio”</td>
@@ -3334,7 +3353,7 @@ int num_ioctls;</synopsis>
 	<title>Video BIOS Table (VBT)</title>
 !Pdrivers/gpu/drm/i915/intel_bios.c Video BIOS Table (VBT)
 !Idrivers/gpu/drm/i915/intel_bios.c
-!Idrivers/gpu/drm/i915/intel_bios.h
+!Idrivers/gpu/drm/i915/intel_vbt_defs.h
       </sect2>
     </sect1>
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/DocBook/media/dvb/net.xml linux-libre-4.7-gnu/Documentation/DocBook/media/dvb/net.xml
--- linux-libre-4.6-gnu/Documentation/DocBook/media/dvb/net.xml	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/DocBook/media/dvb/net.xml	2016-07-24 15:23:50.000000000 -0400
@@ -15,7 +15,7 @@
     that are present on the transport stream. This is done through
     <constant>/dev/dvb/adapter?/net?</constant> device node.
     The data will be available via virtual <constant>dvb?_?</constant>
-    network interfaces, and will be controled/routed via the standard
+    network interfaces, and will be controlled/routed via the standard
     ip tools (like ip, route, netstat, ifconfig, etc).</para>
 <para> Data types and and ioctl definitions are defined via
     <constant>linux/dvb/net.h</constant> header.</para>
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/compat.xml linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/compat.xml
--- linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/compat.xml	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/compat.xml	2016-07-24 15:23:50.000000000 -0400
@@ -2686,50 +2686,12 @@ and may change in the future.</para>
 
       <itemizedlist>
         <listitem>
-	  <para>Video Output Overlay (OSD) Interface, <xref
-	    linkend="osd" />.</para>
-        </listitem>
-        <listitem>
 	  <para>&VIDIOC-DBG-G-REGISTER; and &VIDIOC-DBG-S-REGISTER;
 ioctls.</para>
         </listitem>
         <listitem>
 	  <para>&VIDIOC-DBG-G-CHIP-INFO; ioctl.</para>
         </listitem>
-        <listitem>
-	  <para>&VIDIOC-ENUM-DV-TIMINGS;, &VIDIOC-QUERY-DV-TIMINGS; and
-	  &VIDIOC-DV-TIMINGS-CAP; ioctls.</para>
-        </listitem>
-        <listitem>
-	  <para>Flash API. <xref linkend="flash-controls" /></para>
-        </listitem>
-        <listitem>
-	  <para>&VIDIOC-CREATE-BUFS; and &VIDIOC-PREPARE-BUF; ioctls.</para>
-        </listitem>
-        <listitem>
-	  <para>Selection API. <xref linkend="selection-api" /></para>
-        </listitem>
-        <listitem>
-	  <para>Sub-device selection API: &VIDIOC-SUBDEV-G-SELECTION;
-	  and &VIDIOC-SUBDEV-S-SELECTION; ioctls.</para>
-        </listitem>
-        <listitem>
-	  <para>Support for frequency band enumeration: &VIDIOC-ENUM-FREQ-BANDS; ioctl.</para>
-        </listitem>
-        <listitem>
-	  <para>Vendor and device specific media bus pixel formats.
-	    <xref linkend="v4l2-mbus-vendor-spec-fmts" />.</para>
-        </listitem>
-        <listitem>
-	  <para>Importing DMABUF file descriptors as a new IO method described
-	  in <xref linkend="dmabuf" />.</para>
-        </listitem>
-        <listitem>
-	  <para>Exporting DMABUF files using &VIDIOC-EXPBUF; ioctl.</para>
-        </listitem>
-        <listitem>
-	  <para>Software Defined Radio (SDR) Interface, <xref linkend="sdr" />.</para>
-        </listitem>
       </itemizedlist>
     </section>
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/controls.xml linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/controls.xml
--- linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/controls.xml	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/controls.xml	2016-07-24 15:23:50.000000000 -0400
@@ -2841,7 +2841,7 @@ for a GOP and keep it below or equal the
 overall average bitrate for the stream and keeps it below or equal to the set bitrate. In the first case
 the average bitrate for the whole stream will be smaller then the set bitrate. This is caused because the
 average is calculated for smaller number of frames, on the other hand enabling this setting will ensure that
-the stream will meet tight bandwidth contraints. Applicable to encoders.
+the stream will meet tight bandwidth constraints. Applicable to encoders.
 </entry>
 	      </row>
 	      <row><entry></entry></row>
@@ -4272,13 +4272,6 @@ manually or automatically if set to zero
     <section id="flash-controls">
       <title>Flash Control Reference</title>
 
-      <note>
-	<title>Experimental</title>
-
-	<para>This is an <link linkend="experimental">experimental</link>
-interface and may change in the future.</para>
-      </note>
-
       <para>
 	The V4L2 flash controls are intended to provide generic access
 	to flash controller devices. Flash controller devices are
@@ -4743,14 +4736,6 @@ interface and may change in the future.<
     <section id="image-source-controls">
       <title>Image Source Control Reference</title>
 
-      <note>
-	<title>Experimental</title>
-
-	<para>This is an <link
-	linkend="experimental">experimental</link> interface and may
-	change in the future.</para>
-      </note>
-
       <para>
 	The Image Source control class is intended for low-level
 	control of image source devices such as image sensors. The
@@ -4862,14 +4847,6 @@ interface and may change in the future.<
     <section id="image-process-controls">
       <title>Image Process Control Reference</title>
 
-      <note>
-	<title>Experimental</title>
-
-	<para>This is an <link
-	linkend="experimental">experimental</link> interface and may
-	change in the future.</para>
-      </note>
-
       <para>
 	The Image Process control class is intended for low-level control of
 	image processing functions. Unlike
@@ -4955,14 +4932,6 @@ interface and may change in the future.<
     <section id="dv-controls">
       <title>Digital Video Control Reference</title>
 
-      <note>
-	<title>Experimental</title>
-
-	<para>This is an <link
-	linkend="experimental">experimental</link> interface and may
-	change in the future.</para>
-      </note>
-
       <para>
 	The Digital Video control class is intended to control receivers
 	and transmitters for <ulink url="http://en.wikipedia.org/wiki/Vga">VGA</ulink>,
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/dev-raw-vbi.xml linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/dev-raw-vbi.xml
--- linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/dev-raw-vbi.xml	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/dev-raw-vbi.xml	2016-07-24 15:23:50.000000000 -0400
@@ -85,7 +85,7 @@ initialize all fields of the &v4l2-vbi-f
 results of <constant>VIDIOC_G_FMT</constant>, and call the
 &VIDIOC-S-FMT; ioctl with a pointer to this structure. Drivers return
 an &EINVAL; only when the given parameters are ambiguous, otherwise
-they modify the parameters according to the hardware capabilites and
+they modify the parameters according to the hardware capabilities and
 return the actual parameters. When the driver allocates resources at
 this point, it may return an &EBUSY; to indicate the returned
 parameters are valid but the required resources are currently not
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/dev-sdr.xml linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/dev-sdr.xml
--- linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/dev-sdr.xml	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/dev-sdr.xml	2016-07-24 15:23:50.000000000 -0400
@@ -1,11 +1,5 @@
   <title>Software Defined Radio Interface (SDR)</title>
 
-  <note>
-    <title>Experimental</title>
-    <para>This is an <link linkend="experimental"> experimental </link>
-    interface and may change in the future.</para>
-  </note>
-
   <para>
 SDR is an abbreviation of Software Defined Radio, the radio device
 which uses application software for modulation or demodulation. This interface
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/dev-subdev.xml linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/dev-subdev.xml
--- linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/dev-subdev.xml	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/dev-subdev.xml	2016-07-24 15:23:50.000000000 -0400
@@ -1,11 +1,5 @@
   <title>Sub-device Interface</title>
 
-  <note>
-    <title>Experimental</title>
-    <para>This is an <link linkend="experimental">experimental</link>
-    interface and may change in the future.</para>
-  </note>
-
   <para>The complex nature of V4L2 devices, where hardware is often made of
   several integrated circuits that need to interact with each other in a
   controlled way, leads to complex V4L2 drivers. The drivers usually reflect
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/io.xml linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/io.xml
--- linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/io.xml	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/io.xml	2016-07-24 15:23:50.000000000 -0400
@@ -475,12 +475,6 @@ rest should be evident.</para>
   <section id="dmabuf">
     <title>Streaming I/O (DMA buffer importing)</title>
 
-    <note>
-      <title>Experimental</title>
-      <para>This is an <link linkend="experimental">experimental</link>
-      interface and may change in the future.</para>
-    </note>
-
 <para>The DMABUF framework provides a generic method for sharing buffers
 between multiple devices. Device drivers that support DMABUF can export a DMA
 buffer to userspace as a file descriptor (known as the exporter role), import a
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/selection-api.xml linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/selection-api.xml
--- linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/selection-api.xml	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/selection-api.xml	2016-07-24 15:23:50.000000000 -0400
@@ -1,13 +1,6 @@
 <section id="selection-api">
 
-  <title>Experimental API for cropping, composing and scaling</title>
-
-      <note>
-	<title>Experimental</title>
-
-	<para>This is an <link linkend="experimental">experimental</link>
-interface and may change in the future.</para>
-      </note>
+  <title>API for cropping, composing and scaling</title>
 
   <section>
     <title>Introduction</title>
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/subdev-formats.xml linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/subdev-formats.xml
--- linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/subdev-formats.xml	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/subdev-formats.xml	2016-07-24 15:23:50.000000000 -0400
@@ -4002,12 +4002,6 @@ see <xref linkend="colorspaces" />.</ent
     <section id="v4l2-mbus-vendor-spec-fmts">
       <title>Vendor and Device Specific Formats</title>
 
-      <note>
-	<title>Experimental</title>
-	<para>This is an <link linkend="experimental">experimental</link>
-interface and may change in the future.</para>
-      </note>
-
       <para>This section lists complex data formats that are either vendor or
 	device specific.
       </para>
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml
--- linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml	2016-07-24 15:23:50.000000000 -0400
@@ -49,12 +49,6 @@
   <refsect1>
     <title>Description</title>
 
-    <note>
-      <title>Experimental</title>
-      <para>This is an <link linkend="experimental"> experimental </link>
-      interface and may change in the future.</para>
-    </note>
-
     <para>This ioctl is used to create buffers for <link linkend="mmap">memory
 mapped</link> or <link linkend="userp">user pointer</link> or <link
 linkend="dmabuf">DMA buffer</link> I/O. It can be used as an alternative or in
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml
--- linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml	2016-07-24 15:23:50.000000000 -0400
@@ -49,14 +49,9 @@
   <refsect1>
     <title>Description</title>
 
-    <note>
-      <title>Experimental</title>
-      <para>This is an <link linkend="experimental"> experimental </link>
-      interface and may change in the future.</para>
-    </note>
-
-    <para>To query the capabilities of the DV receiver/transmitter applications
-can call the <constant>VIDIOC_DV_TIMINGS_CAP</constant> ioctl on a video node
+    <para>To query the capabilities of the DV receiver/transmitter applications initialize the
+<structfield>pad</structfield> field to 0, zero the reserved array of &v4l2-dv-timings-cap;
+and call the <constant>VIDIOC_DV_TIMINGS_CAP</constant> ioctl on a video node
 and the driver will fill in the structure. Note that drivers may return
 different values after switching the video input or output.</para>
 
@@ -65,8 +60,8 @@ queried by calling the <constant>VIDIOC_
 directly on a subdevice node. The capabilities are specific to inputs (for DV
 receivers) or outputs (for DV transmitters), applications must specify the
 desired pad number in the &v4l2-dv-timings-cap; <structfield>pad</structfield>
-field. Attempts to query capabilities on a pad that doesn't support them will
-return an &EINVAL;.</para>
+field and zero the <structfield>reserved</structfield> array. Attempts to query
+capabilities on a pad that doesn't support them will return an &EINVAL;.</para>
 
     <table pgwide="1" frame="none" id="v4l2-bt-timings-cap">
       <title>struct <structname>v4l2_bt_timings_cap</structname></title>
@@ -145,7 +140,8 @@ return an &EINVAL;.</para>
 	  <row>
 	    <entry>__u32</entry>
 	    <entry><structfield>reserved</structfield>[2]</entry>
-	    <entry>Reserved for future extensions. Drivers must set the array to zero.</entry>
+	    <entry>Reserved for future extensions. Drivers and applications must
+	    set the array to zero.</entry>
 	  </row>
 	  <row>
 	    <entry>union</entry>
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml
--- linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml	2016-07-24 15:23:50.000000000 -0400
@@ -49,20 +49,15 @@
   <refsect1>
     <title>Description</title>
 
-    <note>
-      <title>Experimental</title>
-      <para>This is an <link linkend="experimental"> experimental </link>
-      interface and may change in the future.</para>
-    </note>
-
     <para>While some DV receivers or transmitters support a wide range of timings, others
 support only a limited number of timings. With this ioctl applications can enumerate a list
 of known supported timings. Call &VIDIOC-DV-TIMINGS-CAP; to check if it also supports other
 standards or even custom timings that are not in this list.</para>
 
     <para>To query the available timings, applications initialize the
-<structfield>index</structfield> field and zero the reserved array of &v4l2-enum-dv-timings;
-and call the <constant>VIDIOC_ENUM_DV_TIMINGS</constant> ioctl on a video node with a
+<structfield>index</structfield> field, set the <structfield>pad</structfield> field to 0,
+zero the reserved array of &v4l2-enum-dv-timings; and call the
+<constant>VIDIOC_ENUM_DV_TIMINGS</constant> ioctl on a video node with a
 pointer to this structure. Drivers fill the rest of the structure or return an
 &EINVAL; when the index is out of bounds. To enumerate all supported DV timings,
 applications shall begin at index zero, incrementing by one until the
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/vidioc-enum-freq-bands.xml linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/vidioc-enum-freq-bands.xml
--- linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/vidioc-enum-freq-bands.xml	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/vidioc-enum-freq-bands.xml	2016-07-24 15:23:50.000000000 -0400
@@ -49,12 +49,6 @@
   <refsect1>
     <title>Description</title>
 
-    <note>
-      <title>Experimental</title>
-      <para>This is an <link linkend="experimental"> experimental </link>
-      interface and may change in the future.</para>
-    </note>
-
     <para>Enumerates the frequency bands that a tuner or modulator supports.
 To do this applications initialize the <structfield>tuner</structfield>,
 <structfield>type</structfield> and <structfield>index</structfield> fields,
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/vidioc-expbuf.xml linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/vidioc-expbuf.xml
--- linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/vidioc-expbuf.xml	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/vidioc-expbuf.xml	2016-07-24 15:23:50.000000000 -0400
@@ -49,12 +49,6 @@
   <refsect1>
     <title>Description</title>
 
-    <note>
-      <title>Experimental</title>
-      <para>This is an <link linkend="experimental"> experimental </link>
-      interface and may change in the future.</para>
-    </note>
-
 <para>This ioctl is an extension to the <link linkend="mmap">memory
 mapping</link> I/O method, therefore it is available only for
 <constant>V4L2_MEMORY_MMAP</constant> buffers.  It can be used to export a
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/vidioc-g-edid.xml linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/vidioc-g-edid.xml
--- linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/vidioc-g-edid.xml	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/vidioc-g-edid.xml	2016-07-24 15:23:50.000000000 -0400
@@ -1,6 +1,6 @@
 <refentry id="vidioc-g-edid">
   <refmeta>
-    <refentrytitle>ioctl VIDIOC_G_EDID, VIDIOC_S_EDID</refentrytitle>
+    <refentrytitle>ioctl VIDIOC_G_EDID, VIDIOC_S_EDID, VIDIOC_SUBDEV_G_EDID, VIDIOC_SUBDEV_S_EDID</refentrytitle>
     &manvol;
   </refmeta>
 
@@ -71,7 +71,8 @@
 
     <para>To get the EDID data the application has to fill in the <structfield>pad</structfield>,
     <structfield>start_block</structfield>, <structfield>blocks</structfield> and <structfield>edid</structfield>
-    fields and call <constant>VIDIOC_G_EDID</constant>. The current EDID from block
+    fields, zero the <structfield>reserved</structfield> array and call
+    <constant>VIDIOC_G_EDID</constant>. The current EDID from block
     <structfield>start_block</structfield> and of size <structfield>blocks</structfield>
     will be placed in the memory <structfield>edid</structfield> points to. The <structfield>edid</structfield>
     pointer must point to memory at least <structfield>blocks</structfield>&nbsp;*&nbsp;128 bytes
@@ -92,8 +93,9 @@
     the driver will set <structfield>blocks</structfield> to 0 and it returns 0.</para>
 
     <para>To set the EDID blocks of a receiver the application has to fill in the <structfield>pad</structfield>,
-    <structfield>blocks</structfield> and <structfield>edid</structfield> fields and set
-    <structfield>start_block</structfield> to 0. It is not possible to set part of an EDID,
+    <structfield>blocks</structfield> and <structfield>edid</structfield> fields, set
+    <structfield>start_block</structfield> to 0 and zero the <structfield>reserved</structfield> array.
+    It is not possible to set part of an EDID,
     it is always all or nothing. Setting the EDID data is only valid for receivers as it makes
     no sense for a transmitter.</para>
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/vidioc-g-selection.xml linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/vidioc-g-selection.xml
--- linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/vidioc-g-selection.xml	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/vidioc-g-selection.xml	2016-07-24 15:23:50.000000000 -0400
@@ -50,12 +50,6 @@
   <refsect1>
     <title>Description</title>
 
-    <note>
-      <title>Experimental</title>
-      <para>This is an <link linkend="experimental"> experimental </link>
-      interface and may change in the future.</para>
-    </note>
-
     <para>The ioctls are used to query and configure selection rectangles.</para>
 
 <para>To query the cropping (composing) rectangle set &v4l2-selection;
@@ -222,7 +216,7 @@ or the <structfield>flags</structfield>
 	<term><errorcode>ERANGE</errorcode></term>
 	<listitem>
 	  <para>It is not possible to adjust &v4l2-rect; <structfield>
-r</structfield> rectangle to satisfy all contraints given in the
+r</structfield> rectangle to satisfy all constraints given in the
 <structfield>flags</structfield> argument.</para>
 	</listitem>
       </varlistentry>
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml
--- linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml	2016-07-24 15:23:50.000000000 -0400
@@ -48,12 +48,6 @@
   <refsect1>
     <title>Description</title>
 
-    <note>
-      <title>Experimental</title>
-      <para>This is an <link linkend="experimental"> experimental </link>
-      interface and may change in the future.</para>
-    </note>
-
     <para>Applications can optionally call the
 <constant>VIDIOC_PREPARE_BUF</constant> ioctl to pass ownership of the buffer
 to the driver before actually enqueuing it, using the
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/vidioc-query-dv-timings.xml linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/vidioc-query-dv-timings.xml
--- linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/vidioc-query-dv-timings.xml	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/vidioc-query-dv-timings.xml	2016-07-24 15:23:50.000000000 -0400
@@ -50,12 +50,6 @@ input</refpurpose>
   <refsect1>
     <title>Description</title>
 
-    <note>
-      <title>Experimental</title>
-      <para>This is an <link linkend="experimental"> experimental </link>
-      interface and may change in the future.</para>
-    </note>
-
     <para>The hardware may be able to detect the current DV timings
 automatically, similar to sensing the video standard. To do so, applications
 call <constant>VIDIOC_QUERY_DV_TIMINGS</constant> with a pointer to a
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/vidioc-streamon.xml linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/vidioc-streamon.xml
--- linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/vidioc-streamon.xml	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/vidioc-streamon.xml	2016-07-24 15:23:50.000000000 -0400
@@ -123,6 +123,14 @@ synchronize with other events.</para>
 	  </para>
 	</listitem>
       </varlistentry>
+      <varlistentry>
+	<term><errorcode>ENOLINK</errorcode></term>
+	<listitem>
+	  <para>The driver implements Media Controller interface and
+	  the pipeline link configuration is invalid.
+	  </para>
+	</listitem>
+      </varlistentry>
     </variablelist>
   </refsect1>
 </refentry>
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-interval.xml linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-interval.xml
--- linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-interval.xml	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-interval.xml	2016-07-24 15:23:50.000000000 -0400
@@ -49,12 +49,6 @@
   <refsect1>
     <title>Description</title>
 
-    <note>
-      <title>Experimental</title>
-      <para>This is an <link linkend="experimental">experimental</link>
-      interface and may change in the future.</para>
-    </note>
-
     <para>This ioctl lets applications enumerate available frame intervals on a
     given sub-device pad. Frame intervals only makes sense for sub-devices that
     can control the frame period on their own. This includes, for instance,
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-size.xml linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-size.xml
--- linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-size.xml	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-size.xml	2016-07-24 15:23:50.000000000 -0400
@@ -49,12 +49,6 @@
   <refsect1>
     <title>Description</title>
 
-    <note>
-      <title>Experimental</title>
-      <para>This is an <link linkend="experimental">experimental</link>
-      interface and may change in the future.</para>
-    </note>
-
     <para>This ioctl allows applications to enumerate all frame sizes
     supported by a sub-device on the given pad for the given media bus format.
     Supported formats can be retrieved with the &VIDIOC-SUBDEV-ENUM-MBUS-CODE;
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/vidioc-subdev-enum-mbus-code.xml linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/vidioc-subdev-enum-mbus-code.xml
--- linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/vidioc-subdev-enum-mbus-code.xml	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/vidioc-subdev-enum-mbus-code.xml	2016-07-24 15:23:50.000000000 -0400
@@ -49,12 +49,6 @@
   <refsect1>
     <title>Description</title>
 
-    <note>
-      <title>Experimental</title>
-      <para>This is an <link linkend="experimental">experimental</link>
-      interface and may change in the future.</para>
-    </note>
-
     <para>To enumerate media bus formats available at a given sub-device pad
     applications initialize the <structfield>pad</structfield>, <structfield>which</structfield>
     and <structfield>index</structfield> fields of &v4l2-subdev-mbus-code-enum; and
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/vidioc-subdev-g-fmt.xml linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/vidioc-subdev-g-fmt.xml
--- linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/vidioc-subdev-g-fmt.xml	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/vidioc-subdev-g-fmt.xml	2016-07-24 15:23:50.000000000 -0400
@@ -50,12 +50,6 @@
   <refsect1>
     <title>Description</title>
 
-    <note>
-      <title>Experimental</title>
-      <para>This is an <link linkend="experimental">experimental</link>
-      interface and may change in the future.</para>
-    </note>
-
     <para>These ioctls are used to negotiate the frame format at specific
     subdev pads in the image pipeline.</para>
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/vidioc-subdev-g-frame-interval.xml linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/vidioc-subdev-g-frame-interval.xml
--- linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/vidioc-subdev-g-frame-interval.xml	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/vidioc-subdev-g-frame-interval.xml	2016-07-24 15:23:50.000000000 -0400
@@ -50,12 +50,6 @@
   <refsect1>
     <title>Description</title>
 
-    <note>
-      <title>Experimental</title>
-      <para>This is an <link linkend="experimental">experimental</link>
-      interface and may change in the future.</para>
-    </note>
-
     <para>These ioctls are used to get and set the frame interval at specific
     subdev pads in the image pipeline. The frame interval only makes sense for
     sub-devices that can control the frame period on their own. This includes,
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml
--- linux-libre-4.6-gnu/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml	2016-07-24 15:23:50.000000000 -0400
@@ -49,12 +49,6 @@
   <refsect1>
     <title>Description</title>
 
-    <note>
-      <title>Experimental</title>
-      <para>This is an <link linkend="experimental">experimental</link>
-      interface and may change in the future.</para>
-    </note>
-
     <para>The selections are used to configure various image
     processing functionality performed by the subdevs which affect the
     image size. This currently includes cropping, scaling and
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/driver-model/devres.txt linux-libre-4.7-gnu/Documentation/driver-model/devres.txt
--- linux-libre-4.6-gnu/Documentation/driver-model/devres.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/driver-model/devres.txt	2016-07-24 15:23:50.000000000 -0400
@@ -236,6 +236,7 @@ certainly invest a bit more effort into
 CLOCK
   devm_clk_get()
   devm_clk_put()
+  devm_clk_hw_register()
 
 DMA
   dmam_alloc_coherent()
@@ -267,6 +268,13 @@ IIO
   devm_iio_kfifo_free()
   devm_iio_trigger_alloc()
   devm_iio_trigger_free()
+  devm_iio_channel_get()
+  devm_iio_channel_release()
+  devm_iio_channel_get_all()
+  devm_iio_channel_release_all()
+
+INPUT
+  devm_input_allocate_device()
 
 IO region
   devm_release_mem_region()
@@ -317,6 +325,9 @@ MEM
   devm_kvasprintf()
   devm_kzalloc()
 
+MFD
+ devm_mfd_add_devices()
+
 PCI
   pcim_enable_device()	: after success, all PCI ops become managed
   pcim_pin_device()	: keep PCI device enabled after release
@@ -328,6 +339,8 @@ PHY
 PINCTRL
   devm_pinctrl_get()
   devm_pinctrl_put()
+  devm_pinctrl_register()
+  devm_pinctrl_unregister()
 
 PWM
   devm_pwm_get()
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/fb/udlfb.txt linux-libre-4.7-gnu/Documentation/fb/udlfb.txt
--- linux-libre-4.6-gnu/Documentation/fb/udlfb.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/fb/udlfb.txt	2016-07-24 15:23:50.000000000 -0400
@@ -9,7 +9,7 @@ pairing that with a hardware framebuffer
 USB wire.  That hardware framebuffer is able to drive the VGA, DVI, or HDMI
 monitor with no CPU involvement until a pixel has to change.
 
-The CPU or other local resource does all the rendering; optinally compares the
+The CPU or other local resource does all the rendering; optionally compares the
 result with a local shadow of the remote hardware framebuffer to identify
 the minimal set of pixels that have changed; and compresses and sends those
 pixels line-by-line via USB bulk transfers.
@@ -66,10 +66,10 @@ means that from a hardware and fbdev sof
 At that point, a /dev/fb? interface will be present for user-mode applications
 to open and begin writing to the framebuffer of the DisplayLink device using
 standard fbdev calls.  Note that if mmap() is used, by default the user mode
-application must send down damage notifcations to trigger repaints of the
+application must send down damage notifications to trigger repaints of the
 changed regions.  Alternatively, udlfb can be recompiled with experimental
 defio support enabled, to support a page-fault based detection mechanism
-that can work without explicit notifcation.
+that can work without explicit notification.
 
 The most common client of udlfb is xf86-video-displaylink or a modified
 xf86-video-fbdev X server. These servers have no real DisplayLink specific
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/features/perf/perf-regs/arch-support.txt linux-libre-4.7-gnu/Documentation/features/perf/perf-regs/arch-support.txt
--- linux-libre-4.6-gnu/Documentation/features/perf/perf-regs/arch-support.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/features/perf/perf-regs/arch-support.txt	2016-07-24 15:23:50.000000000 -0400
@@ -27,7 +27,7 @@
     |       nios2: | TODO |
     |    openrisc: | TODO |
     |      parisc: | TODO |
-    |     powerpc: | TODO |
+    |     powerpc: |  ok  |
     |        s390: | TODO |
     |       score: | TODO |
     |          sh: | TODO |
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/features/perf/perf-stackdump/arch-support.txt linux-libre-4.7-gnu/Documentation/features/perf/perf-stackdump/arch-support.txt
--- linux-libre-4.6-gnu/Documentation/features/perf/perf-stackdump/arch-support.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/features/perf/perf-stackdump/arch-support.txt	2016-07-24 15:23:50.000000000 -0400
@@ -27,7 +27,7 @@
     |       nios2: | TODO |
     |    openrisc: | TODO |
     |      parisc: | TODO |
-    |     powerpc: | TODO |
+    |     powerpc: |  ok  |
     |        s390: | TODO |
     |       score: | TODO |
     |          sh: | TODO |
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/filesystems/cifs/README linux-libre-4.7-gnu/Documentation/filesystems/cifs/README
--- linux-libre-4.6-gnu/Documentation/filesystems/cifs/README	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/filesystems/cifs/README	2016-07-24 15:23:50.000000000 -0400
@@ -272,7 +272,7 @@ A partial list of the supported mount op
 		same domain (e.g. running winbind or nss_ldap) and
 		the server supports the Unix Extensions then the uid
 		and gid can be retrieved from the server (and uid
-		and gid would not have to be specifed on the mount. 
+		and gid would not have to be specified on the mount.
 		For servers which do not support the CIFS Unix
 		extensions, the default uid (and gid) returned on lookup
 		of existing files will be the uid (gid) of the person
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/filesystems/dax.txt linux-libre-4.7-gnu/Documentation/filesystems/dax.txt
--- linux-libre-4.6-gnu/Documentation/filesystems/dax.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/filesystems/dax.txt	2016-07-24 15:23:50.000000000 -0400
@@ -79,6 +79,38 @@ These filesystems may be used for inspir
 - ext4: the fourth extended filesystem, see Documentation/filesystems/ext4.txt
 
 
+Handling Media Errors
+---------------------
+
+The libnvdimm subsystem stores a record of known media error locations for
+each pmem block device (in gendisk->badblocks). If we fault at such location,
+or one with a latent error not yet discovered, the application can expect
+to receive a SIGBUS. Libnvdimm also allows clearing of these errors by simply
+writing the affected sectors (through the pmem driver, and if the underlying
+NVDIMM supports the clear_poison DSM defined by ACPI).
+
+Since DAX IO normally doesn't go through the driver/bio path, applications or
+sysadmins have an option to restore the lost data from a prior backup/inbuilt
+redundancy in the following ways:
+
+1. Delete the affected file, and restore from a backup (sysadmin route):
+   This will free the file system blocks that were being used by the file,
+   and the next time they're allocated, they will be zeroed first, which
+   happens through the driver, and will clear bad sectors.
+
+2. Truncate or hole-punch the part of the file that has a bad-block (at least
+   an entire aligned sector has to be hole-punched, but not necessarily an
+   entire filesystem block).
+
+These are the two basic paths that allow DAX filesystems to continue operating
+in the presence of media errors. More robust error recovery mechanisms can be
+built on top of this in the future, for example, involving redundancy/mirroring
+provided at the block layer through DM, or additionally, at the filesystem
+level. These would have to rely on the above two tenets, that error clearing
+can happen either by sending an IO through the driver, or zeroing (also through
+the driver).
+
+
 Shortcomings
 ------------
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/filesystems/devpts.txt linux-libre-4.7-gnu/Documentation/filesystems/devpts.txt
--- linux-libre-4.6-gnu/Documentation/filesystems/devpts.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/filesystems/devpts.txt	2016-07-24 15:23:50.000000000 -0400
@@ -1,141 +1,26 @@
+Each mount of the devpts filesystem is now distinct such that ptys
+and their indicies allocated in one mount are independent from ptys
+and their indicies in all other mounts.
 
-To support containers, we now allow multiple instances of devpts filesystem,
-such that indices of ptys allocated in one instance are independent of indices
-allocated in other instances of devpts.
-
-To preserve backward compatibility, this support for multiple instances is
-enabled only if:
-
-	- CONFIG_DEVPTS_MULTIPLE_INSTANCES=y, and
-	- '-o newinstance' mount option is specified while mounting devpts
-
-IOW, devpts now supports both single-instance and multi-instance semantics.
-
-If CONFIG_DEVPTS_MULTIPLE_INSTANCES=n, there is no change in behavior and
-this referred to as the "legacy" mode. In this mode, the new mount options
-(-o newinstance and -o ptmxmode) will be ignored with a 'bogus option' message
-on console.
-
-If CONFIG_DEVPTS_MULTIPLE_INSTANCES=y and devpts is mounted without the
-'newinstance' option (as in current start-up scripts) the new mount binds
-to the initial kernel mount of devpts. This mode is referred to as the
-'single-instance' mode and the current, single-instance semantics are
-preserved, i.e PTYs are common across the system.
-
-The only difference between this single-instance mode and the legacy mode
-is the presence of new, '/dev/pts/ptmx' node with permissions 0000, which
-can safely be ignored.
-
-If CONFIG_DEVPTS_MULTIPLE_INSTANCES=y and 'newinstance' option is specified,
-the mount is considered to be in the multi-instance mode and a new instance
-of the devpts fs is created. Any ptys created in this instance are independent
-of ptys in other instances of devpts. Like in the single-instance mode, the
-/dev/pts/ptmx node is present. To effectively use the multi-instance mode,
-open of /dev/ptmx must be a redirected to '/dev/pts/ptmx' using a symlink or
-bind-mount.
-
-Eg: A container startup script could do the following:
-
-	$ chmod 0666 /dev/pts/ptmx
-	$ rm /dev/ptmx
-	$ ln -s pts/ptmx /dev/ptmx
-	$ ns_exec -cm /bin/bash
-
-	# We are now in new container
+All mounts of the devpts filesystem now create a /dev/pts/ptmx node
+with permissions 0000.
 
-	$ umount /dev/pts
-	$ mount -t devpts -o newinstance lxcpts /dev/pts
-	$ sshd -p 1234
+To retain backwards compatibility the a ptmx device node (aka any node
+created with "mknod name c 5 2") when opened will look for an instance
+of devpts under the name "pts" in the same directory as the ptmx device
+node.
 
-where 'ns_exec -cm /bin/bash' calls clone() with CLONE_NEWNS flag and execs
-/bin/bash in the child process.  A pty created by the sshd is not visible in
-the original mount of /dev/pts.
+As an option instead of placing a /dev/ptmx device node at /dev/ptmx
+it is possible to place a symlink to /dev/pts/ptmx at /dev/ptmx or
+to bind mount /dev/ptx/ptmx to /dev/ptmx.  If you opt for using
+the devpts filesystem in this manner devpts should be mounted with
+the ptmxmode=0666, or chmod 0666 /dev/pts/ptmx should be called.
 
 Total count of pty pairs in all instances is limited by sysctls:
 kernel.pty.max = 4096		- global limit
-kernel.pty.reserve = 1024	- reserve for initial instance
+kernel.pty.reserve = 1024	- reserved for filesystems mounted from the initial mount namespace
 kernel.pty.nr			- current count of ptys
 
 Per-instance limit could be set by adding mount option "max=<count>".
 This feature was added in kernel 3.4 together with sysctl kernel.pty.reserve.
 In kernels older than 3.4 sysctl kernel.pty.max works as per-instance limit.
-
-User-space changes
-------------------
-
-In multi-instance mode (i.e '-o newinstance' mount option is specified at least
-once), following user-space issues should be noted.
-
-1. If -o newinstance mount option is never used, /dev/pts/ptmx can be ignored
-   and no change is needed to system-startup scripts.
-
-2. To effectively use multi-instance mode (i.e -o newinstance is specified)
-   administrators or startup scripts should "redirect" open of /dev/ptmx to
-   /dev/pts/ptmx using either a bind mount or symlink.
-
-	$ mount -t devpts -o newinstance devpts /dev/pts
-
-   followed by either
-
-	$ rm /dev/ptmx
-	$ ln -s pts/ptmx /dev/ptmx
-	$ chmod 666 /dev/pts/ptmx
-   or
-	$ mount -o bind /dev/pts/ptmx /dev/ptmx
-
-3. The '/dev/ptmx -> pts/ptmx' symlink is the preferred method since it
-   enables better error-reporting and treats both single-instance and
-   multi-instance mounts similarly.
-
-   But this method requires that system-startup scripts set the mode of
-   /dev/pts/ptmx correctly (default mode is 0000). The scripts can set the
-   mode by, either
-
-   	- adding ptmxmode mount option to devpts entry in /etc/fstab, or
-	- using 'chmod 0666 /dev/pts/ptmx'
-
-4. If multi-instance mode mount is needed for containers, but the system
-   startup scripts have not yet been updated, container-startup scripts
-   should bind mount /dev/ptmx to /dev/pts/ptmx to avoid breaking single-
-   instance mounts.
-
-   Or, in general, container-startup scripts should use:
-
-	mount -t devpts -o newinstance -o ptmxmode=0666 devpts /dev/pts
-	if [ ! -L /dev/ptmx ]; then
-		mount -o bind /dev/pts/ptmx /dev/ptmx
-	fi
-
-   When all devpts mounts are multi-instance, /dev/ptmx can permanently be
-   a symlink to pts/ptmx and the bind mount can be ignored.
-
-5. A multi-instance mount that is not accompanied by the /dev/ptmx to
-   /dev/pts/ptmx redirection would result in an unusable/unreachable pty.
-
-	mount -t devpts -o newinstance lxcpts /dev/pts
-
-   immediately followed by:
-
-	open("/dev/ptmx")
-
-    would create a pty, say /dev/pts/7, in the initial kernel mount.
-    But /dev/pts/7 would be invisible in the new mount.
-
-6. The permissions for /dev/pts/ptmx node should be specified when mounting
-   /dev/pts, using the '-o ptmxmode=%o' mount option (default is 0000).
-
-	mount -t devpts -o newinstance -o ptmxmode=0644 devpts /dev/pts
-
-   The permissions can be later be changed as usual with 'chmod'.
-
-	chmod 666 /dev/pts/ptmx
-
-7. A mount of devpts without the 'newinstance' option results in binding to
-   initial kernel mount.  This behavior while preserving legacy semantics,
-   does not provide strict isolation in a container environment. i.e by
-   mounting devpts without the 'newinstance' option, a container could
-   get visibility into the 'host' or root container's devpts.
-   
-   To workaround this and have strict isolation, all mounts of devpts,
-   including the mount in the root container, should use the newinstance
-   option.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/filesystems/directory-locking linux-libre-4.7-gnu/Documentation/filesystems/directory-locking
--- linux-libre-4.6-gnu/Documentation/filesystems/directory-locking	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/filesystems/directory-locking	2016-07-24 15:23:50.000000000 -0400
@@ -1,30 +1,37 @@
 	Locking scheme used for directory operations is based on two
-kinds of locks - per-inode (->i_mutex) and per-filesystem
+kinds of locks - per-inode (->i_rwsem) and per-filesystem
 (->s_vfs_rename_mutex).
 
-	When taking the i_mutex on multiple non-directory objects, we
+	When taking the i_rwsem on multiple non-directory objects, we
 always acquire the locks in order by increasing address.  We'll call
 that "inode pointer" order in the following.
 
 	For our purposes all operations fall in 5 classes:
 
 1) read access.  Locking rules: caller locks directory we are accessing.
+The lock is taken shared.
 
-2) object creation.  Locking rules: same as above.
+2) object creation.  Locking rules: same as above, but the lock is taken
+exclusive.
 
 3) object removal.  Locking rules: caller locks parent, finds victim,
-locks victim and calls the method.
+locks victim and calls the method.  Locks are exclusive.
 
 4) rename() that is _not_ cross-directory.  Locking rules: caller locks
-the parent and finds source and target.  If target already exists, lock
-it.  If source is a non-directory, lock it.  If that means we need to
-lock both, lock them in inode pointer order.
+the parent and finds source and target.  In case of exchange (with
+RENAME_EXCHANGE in rename2() flags argument) lock both.  In any case,
+if the target already exists, lock it.  If the source is a non-directory,
+lock it.  If we need to lock both, lock them in inode pointer order.
+Then call the method.  All locks are exclusive.
+NB: we might get away with locking the the source (and target in exchange
+case) shared.
 
 5) link creation.  Locking rules:
 	* lock parent
 	* check that source is not a directory
 	* lock source
 	* call the method.
+All locks are exclusive.
 
 6) cross-directory rename.  The trickiest in the whole bunch.  Locking
 rules:
@@ -35,11 +42,12 @@ rules:
 		fail with -ENOTEMPTY
 	* if new parent is equal to or is a descendent of source
 		fail with -ELOOP
-	* If target exists, lock it.  If source is a non-directory, lock
-	  it.  In case that means we need to lock both source and target,
-	  do so in inode pointer order.
+	* If it's an exchange, lock both the source and the target.
+	* If the target exists, lock it.  If the source is a non-directory,
+	  lock it.  If we need to lock both, do so in inode pointer order.
 	* call the method.
-
+All ->i_rwsem are taken exclusive.  Again, we might get away with locking
+the the source (and target in exchange case) shared.
 
 The rules above obviously guarantee that all directories that are going to be
 read, modified or removed by method will be locked by caller.
@@ -73,7 +81,7 @@ objects - A < B iff A is an ancestor of
 attempt to acquire some lock and already holds at least one lock.  Let's
 consider the set of contended locks.  First of all, filesystem lock is
 not contended, since any process blocked on it is not holding any locks.
-Thus all processes are blocked on ->i_mutex.
+Thus all processes are blocked on ->i_rwsem.
 
 	By (3), any process holding a non-directory lock can only be
 waiting on another non-directory lock with a larger address.  Therefore
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/filesystems/Locking linux-libre-4.7-gnu/Documentation/filesystems/Locking
--- linux-libre-4.6-gnu/Documentation/filesystems/Locking	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/filesystems/Locking	2016-07-24 15:23:50.000000000 -0400
@@ -194,7 +194,7 @@ prototypes:
 	void (*invalidatepage) (struct page *, unsigned int, unsigned int);
 	int (*releasepage) (struct page *, int);
 	void (*freepage)(struct page *);
-	int (*direct_IO)(struct kiocb *, struct iov_iter *iter, loff_t offset);
+	int (*direct_IO)(struct kiocb *, struct iov_iter *iter);
 	int (*migratepage)(struct address_space *, struct page *, struct page *);
 	int (*launder_page)(struct page *);
 	int (*is_partially_uptodate)(struct page *, unsigned long, unsigned long);
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/filesystems/nilfs2.txt linux-libre-4.7-gnu/Documentation/filesystems/nilfs2.txt
--- linux-libre-4.6-gnu/Documentation/filesystems/nilfs2.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/filesystems/nilfs2.txt	2016-07-24 15:23:50.000000000 -0400
@@ -268,3 +268,8 @@ among NILFS2 files can be depicted as fo
                                     ( regular file, directory, or symlink )
 
 For detail on the format of each file, please see include/linux/nilfs2_fs.h.
+
+There are no patents or other intellectual property that we protect
+with regard to the design of NILFS2.  It is allowed to replicate the
+design in hopes that other operating systems could share (mount, read,
+write, etc.) data stored in this format.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/filesystems/overlayfs.txt linux-libre-4.7-gnu/Documentation/filesystems/overlayfs.txt
--- linux-libre-4.6-gnu/Documentation/filesystems/overlayfs.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/filesystems/overlayfs.txt	2016-07-24 15:23:50.000000000 -0400
@@ -194,15 +194,6 @@ If a file with multiple hard links is co
 "break" the link.  Changes will not be propagated to other names
 referring to the same inode.
 
-Symlinks in /proc/PID/ and /proc/PID/fd which point to a non-directory
-object in overlayfs will not contain valid absolute paths, only
-relative paths leading up to the filesystem's root.  This will be
-fixed in the future.
-
-Some operations are not atomic, for example a crash during copy_up or
-rename will leave the filesystem in an inconsistent state.  This will
-be addressed in the future.
-
 Changes to underlying filesystems
 ---------------------------------
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/filesystems/pohmelfs/design_notes.txt linux-libre-4.7-gnu/Documentation/filesystems/pohmelfs/design_notes.txt
--- linux-libre-4.6-gnu/Documentation/filesystems/pohmelfs/design_notes.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/filesystems/pohmelfs/design_notes.txt	2016-07-24 15:23:50.000000000 -0400
@@ -29,7 +29,7 @@ Main features of this FS include:
  * Read request (data read, directory listing, lookup requests) balancing between multiple servers.
  * Write requests are replicated to multiple servers and completed only when all of them are acked.
  * Ability to add and/or remove servers from the working set at run-time.
- * Strong authentification and possible data encryption in network channel.
+ * Strong authentication and possible data encryption in network channel.
  * Extended attributes support.
 
 POHMELFS is based on transactions, which are potentially long-standing objects that live
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/filesystems/porting linux-libre-4.7-gnu/Documentation/filesystems/porting
--- linux-libre-4.6-gnu/Documentation/filesystems/porting	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/filesystems/porting	2016-07-24 15:23:50.000000000 -0400
@@ -525,3 +525,63 @@ in your dentry operations instead.
 	set_delayed_call() where it used to set *cookie.
 	->put_link() is gone - just give the destructor to set_delayed_call()
 	in ->get_link().
+--
+[mandatory]
+	->getxattr() and xattr_handler.get() get dentry and inode passed separately.
+	dentry might be yet to be attached to inode, so do _not_ use its ->d_inode
+	in the instances.  Rationale: !@#!@# security_d_instantiate() needs to be
+	called before we attach dentry to inode.
+--
+[mandatory]
+	symlinks are no longer the only inodes that do *not* have i_bdev/i_cdev/
+	i_pipe/i_link union zeroed out at inode eviction.  As the result, you can't
+	assume that non-NULL value in ->i_nlink at ->destroy_inode() implies that
+	it's a symlink.  Checking ->i_mode is really needed now.  In-tree we had
+	to fix shmem_destroy_callback() that used to take that kind of shortcut;
+	watch out, since that shortcut is no longer valid.
+--
+[mandatory]
+	->i_mutex is replaced with ->i_rwsem now.  inode_lock() et.al. work as
+	they used to - they just take it exclusive.  However, ->lookup() may be
+	called with parent locked shared.  Its instances must not
+		* use d_instantiate) and d_rehash() separately - use d_add() or
+		  d_splice_alias() instead.
+		* use d_rehash() alone - call d_add(new_dentry, NULL) instead.
+		* in the unlikely case when (read-only) access to filesystem
+		  data structures needs exclusion for some reason, arrange it
+		  yourself.  None of the in-tree filesystems needed that.
+		* rely on ->d_parent and ->d_name not changing after dentry has
+		  been fed to d_add() or d_splice_alias().  Again, none of the
+		  in-tree instances relied upon that.
+	We are guaranteed that lookups of the same name in the same directory
+	will not happen in parallel ("same" in the sense of your ->d_compare()).
+	Lookups on different names in the same directory can and do happen in
+	parallel now.
+--
+[recommended]
+	->iterate_shared() is added; it's a parallel variant of ->iterate().
+	Exclusion on struct file level is still provided (as well as that
+	between it and lseek on the same struct file), but if your directory
+	has been opened several times, you can get these called in parallel.
+	Exclusion between that method and all directory-modifying ones is
+	still provided, of course.
+
+	Often enough ->iterate() can serve as ->iterate_shared() without any
+	changes - it is a read-only operation, after all.  If you have any
+	per-inode or per-dentry in-core data structures modified by ->iterate(),
+	you might need something to serialize the access to them.  If you
+	do dcache pre-seeding, you'll need to switch to d_alloc_parallel() for
+	that; look for in-tree examples.
+
+	Old method is only used if the new one is absent; eventually it will
+	be removed.  Switch while you still can; the old one won't stay.
+--
+[mandatory]
+	->atomic_open() calls without O_CREAT may happen in parallel.
+--
+[mandatory]
+	->setxattr() and xattr_handler.set() get dentry and inode passed separately.
+	dentry might be yet to be attached to inode, so do _not_ use its ->d_inode
+	in the instances.  Rationale: !@#!@# security_d_instantiate() needs to be
+	called before we attach dentry to inode and !@#!@##!@$!$#!@#$!@$!@$ smack
+	->d_instantiate() uses not just ->getxattr() but ->setxattr() as well.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/filesystems/proc.txt linux-libre-4.7-gnu/Documentation/filesystems/proc.txt
--- linux-libre-4.6-gnu/Documentation/filesystems/proc.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/filesystems/proc.txt	2016-07-24 15:23:50.000000000 -0400
@@ -225,6 +225,7 @@ Table 1-2: Contents of the status files
  TracerPid                   PID of process tracing this process (0 if not)
  Uid                         Real, effective, saved set, and  file system UIDs
  Gid                         Real, effective, saved set, and  file system GIDs
+ Umask                       file mode creation mask
  FDSize                      number of file descriptor slots currently allocated
  Groups                      supplementary group list
  NStgid                      descendant namespace thread group ID hierarchy
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/filesystems/qnx6.txt linux-libre-4.7-gnu/Documentation/filesystems/qnx6.txt
--- linux-libre-4.6-gnu/Documentation/filesystems/qnx6.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/filesystems/qnx6.txt	2016-07-24 15:23:50.000000000 -0400
@@ -16,7 +16,7 @@ qnx6fs shares many properties with tradi
 concepts of blocks, inodes and directories.
 On QNX it is possible to create little endian and big endian qnx6 filesystems.
 This feature makes it possible to create and use a different endianness fs
-for the target (QNX is used on quite a range of embedded systems) plattform
+for the target (QNX is used on quite a range of embedded systems) platform
 running on a different endianness.
 The Linux driver handles endianness transparently. (LE and BE)
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/filesystems/vfs.txt linux-libre-4.7-gnu/Documentation/filesystems/vfs.txt
--- linux-libre-4.6-gnu/Documentation/filesystems/vfs.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/filesystems/vfs.txt	2016-07-24 15:23:50.000000000 -0400
@@ -591,7 +591,7 @@ struct address_space_operations {
 	void (*invalidatepage) (struct page *, unsigned int, unsigned int);
 	int (*releasepage) (struct page *, int);
 	void (*freepage)(struct page *);
-	ssize_t (*direct_IO)(struct kiocb *, struct iov_iter *iter, loff_t offset);
+	ssize_t (*direct_IO)(struct kiocb *, struct iov_iter *iter);
 	/* migrate the contents of a page to the specified target */
 	int (*migratepage) (struct page *, struct page *);
 	int (*launder_page) (struct page *);
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/firmware_class/README linux-libre-4.7-gnu/Documentation/firmware_class/README
--- linux-libre-4.6-gnu/Documentation/firmware_class/README	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/firmware_class/README	2016-07-24 15:23:50.000000000 -0400
@@ -20,7 +20,7 @@
 
  1), kernel(driver):
 	- calls request_firmware(&fw_entry, $FIRMWARE, device)
-	- kernel searchs the fimware image with name $FIRMWARE directly
+	- kernel searches the firmware image with name $FIRMWARE directly
 	in the below search path of root filesystem:
 		User customized search path by module parameter 'path'[1]
 		"/lib/firmware/updates/" UTS_RELEASE,
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/gpio/driver.txt linux-libre-4.7-gnu/Documentation/gpio/driver.txt
--- linux-libre-4.6-gnu/Documentation/gpio/driver.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/gpio/driver.txt	2016-07-24 15:23:50.000000000 -0400
@@ -68,6 +68,103 @@ control callbacks) if it is expected to
 on -RT (inside hard IRQ handlers and similar contexts). Normally this should
 not be required.
 
+
+GPIOs with open drain/source support
+------------------------------------
+
+Open drain (CMOS) or open collector (TTL) means the line is not actively driven
+high: instead you provide the drain/collector as output, so when the transistor
+is not open, it will present a high-impedance (tristate) to the external rail.
+
+
+   CMOS CONFIGURATION      TTL CONFIGURATION
+
+            ||--- out              +--- out
+     in ----||                   |/
+            ||--+         in ----|
+                |                |\
+               GND	           GND
+
+This configuration is normally used as a way to achieve one of two things:
+
+- Level-shifting: to reach a logical level higher than that of the silicon
+  where the output resides.
+
+- inverse wire-OR on an I/O line, for example a GPIO line, making it possible
+  for any driving stage on the line to drive it low even if any other output
+  to the same line is simultaneously driving it high. A special case of this
+  is driving the SCL and SCA lines of an I2C bus, which is by definition a
+  wire-OR bus.
+
+Both usecases require that the line be equipped with a pull-up resistor. This
+resistor will make the line tend to high level unless one of the transistors on
+the rail actively pulls it down.
+
+The level on the line will go as high as the VDD on the pull-up resistor, which
+may be higher than the level supported by the transistor, achieveing a
+level-shift to the higher VDD.
+
+Integrated electronics often have an output driver stage in the form of a CMOS
+"totem-pole" with one N-MOS and one P-MOS transistor where one of them drives
+the line high and one of them drives the line low. This is called a push-pull
+output. The "totem-pole" looks like so:
+
+                 VDD
+                  |
+        OD    ||--+
+     +--/ ---o||     P-MOS-FET
+     |        ||--+
+IN --+            +----- out
+     |        ||--+
+     +--/ ----||     N-MOS-FET
+        OS    ||--+
+                  |
+                 GND
+
+The desired output signal (e.g. coming directly from some GPIO output register)
+arrives at IN. The switches named "OD" and "OS" are normally closed, creating
+a push-pull circuit.
+
+Consider the little "switches" named "OD" and "OS" that enable/disable the
+P-MOS or N-MOS transistor right after the split of the input. As you can see,
+either transistor will go totally numb if this switch is open. The totem-pole
+is then halved and give high impedance instead of actively driving the line
+high or low respectively. That is usually how software-controlled open
+drain/source works.
+
+Some GPIO hardware come in open drain / open source configuration. Some are
+hard-wired lines that will only support open drain or open source no matter
+what: there is only one transistor there. Some are software-configurable:
+by flipping a bit in a register the output can be configured as open drain
+or open source, in practice by flicking open the switches labeled "OD" and "OS"
+in the drawing above.
+
+By disabling the P-MOS transistor, the output can be driven between GND and
+high impedance (open drain), and by disabling the N-MOS transistor, the output
+can be driven between VDD and high impedance (open source). In the first case,
+a pull-up resistor is needed on the outgoing rail to complete the circuit, and
+in the second case, a pull-down resistor is needed on the rail.
+
+Hardware that supports open drain or open source or both, can implement a
+special callback in the gpio_chip: .set_single_ended() that takes an enum flag
+telling whether to configure the line as open drain, open source or push-pull.
+This will happen in response to the GPIO_OPEN_DRAIN or GPIO_OPEN_SOURCE flag
+set in the machine file, or coming from other hardware descriptions.
+
+If this state can not be configured in hardware, i.e. if the GPIO hardware does
+not support open drain/open source in hardware, the GPIO library will instead
+use a trick: when a line is set as output, if the line is flagged as open
+drain, and the IN output value is low, it will be driven low as usual. But
+if the IN output value is set to high, it will instead *NOT* be driven high,
+instead it will be switched to input, as input mode is high impedance, thus
+achieveing an "open drain emulation" of sorts: electrically the behaviour will
+be identical, with the exception of possible hardware glitches when switching
+the mode of the line.
+
+For open source configuration the same principle is used, just that instead
+of actively driving the line low, it is set to input.
+
+
 GPIO drivers providing IRQs
 ---------------------------
 It is custom that GPIO drivers (GPIO chips) are also providing interrupts,
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/hwmon/abituguru linux-libre-4.7-gnu/Documentation/hwmon/abituguru
--- linux-libre-4.6-gnu/Documentation/hwmon/abituguru	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/hwmon/abituguru	2016-07-24 15:23:50.000000000 -0400
@@ -25,7 +25,7 @@ Supported chips:
 	1) For revisions 2 and 3 uGuru's the driver can autodetect the
 	   sensortype (Volt or Temp) for bank1 sensors, for revision 1 uGuru's
 	   this doesnot always work. For these uGuru's the autodection can
-	   be overriden with the bank1_types module param. For all 3 known
+	   be overridden with the bank1_types module param. For all 3 known
 	   revison 1 motherboards the correct use of this param is:
 	   bank1_types=1,1,0,0,0,0,0,2,0,0,0,0,2,0,0,1
 	   You may also need to specify the fan_sensors option for these boards
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/hwmon/fam15h_power linux-libre-4.7-gnu/Documentation/hwmon/fam15h_power
--- linux-libre-4.6-gnu/Documentation/hwmon/fam15h_power	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/hwmon/fam15h_power	2016-07-24 15:23:50.000000000 -0400
@@ -10,14 +10,22 @@ Supported chips:
   Datasheets:
   BIOS and Kernel Developer's Guide (BKDG) For AMD Family 15h Processors
   BIOS and Kernel Developer's Guide (BKDG) For AMD Family 16h Processors
+  AMD64 Architecture Programmer's Manual Volume 2: System Programming
 
 Author: Andreas Herrmann <herrmann.der.user@googlemail.com>
 
 Description
 -----------
 
+1) Processor TDP (Thermal design power)
+
+Given a fixed frequency and voltage, the power consumption of a
+processor varies based on the workload being executed. Derated power
+is the power consumed when running a specific application. Thermal
+design power (TDP) is an example of derated power.
+
 This driver permits reading of registers providing power information
-of AMD Family 15h and 16h processors.
+of AMD Family 15h and 16h processors via TDP algorithm.
 
 For AMD Family 15h and 16h processors the following power values can
 be calculated using different processor northbridge function
@@ -37,3 +45,58 @@ This driver provides ProcessorPwrWatts a
 On multi-node processors the calculated value is for the entire
 package and not for a single node. Thus the driver creates sysfs
 attributes only for internal node0 of a multi-node processor.
+
+2) Accumulated Power Mechanism
+
+This driver also introduces an algorithm that should be used to
+calculate the average power consumed by a processor during a
+measurement interval Tm. The feature of accumulated power mechanism is
+indicated by CPUID Fn8000_0007_EDX[12].
+
+* Tsample: compute unit power accumulator sample period
+* Tref: the PTSC counter period
+* PTSC: performance timestamp counter
+* N: the ratio of compute unit power accumulator sample period to the
+  PTSC period
+* Jmax: max compute unit accumulated power which is indicated by
+  MaxCpuSwPwrAcc MSR C001007b
+* Jx/Jy: compute unit accumulated power which is indicated by
+  CpuSwPwrAcc MSR C001007a
+* Tx/Ty: the value of performance timestamp counter which is indicated
+  by CU_PTSC MSR C0010280
+* PwrCPUave: CPU average power
+
+i. Determine the ratio of Tsample to Tref by executing CPUID Fn8000_0007.
+	N = value of CPUID Fn8000_0007_ECX[CpuPwrSampleTimeRatio[15:0]].
+
+ii. Read the full range of the cumulative energy value from the new
+MSR MaxCpuSwPwrAcc.
+	Jmax = value returned.
+iii. At time x, SW reads CpuSwPwrAcc MSR and samples the PTSC.
+	Jx = value read from CpuSwPwrAcc and Tx = value read from
+PTSC.
+
+iv. At time y, SW reads CpuSwPwrAcc MSR and samples the PTSC.
+	Jy = value read from CpuSwPwrAcc and Ty = value read from
+PTSC.
+
+v. Calculate the average power consumption for a compute unit over
+time period (y-x). Unit of result is uWatt.
+	if (Jy < Jx) // Rollover has occurred
+		Jdelta = (Jy + Jmax) - Jx
+	else
+		Jdelta = Jy - Jx
+	PwrCPUave = N * Jdelta * 1000 / (Ty - Tx)
+
+This driver provides PwrCPUave and interval(default is 10 millisecond
+and maximum is 1 second):
+* power1_average (PwrCPUave)
+* power1_average_interval (Interval)
+
+The power1_average_interval can be updated at /etc/sensors3.conf file
+as below:
+
+chip "fam15h_power-*"
+	set power1_average_interval 0.01
+
+Then save it with "sensors -s".
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/hwmon/it87 linux-libre-4.7-gnu/Documentation/hwmon/it87
--- linux-libre-4.6-gnu/Documentation/hwmon/it87	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/hwmon/it87	2016-07-24 15:23:50.000000000 -0400
@@ -9,6 +9,9 @@ Supported chips:
   * IT8620E
     Prefix: 'it8620'
     Addresses scanned: from Super I/O config space (8 I/O ports)
+  * IT8628E
+    Prefix: 'it8628'
+    Addresses scanned: from Super I/O config space (8 I/O ports)
     Datasheet: Not publicly available
   * IT8705F
     Prefix: 'it87'
@@ -114,8 +117,8 @@ motherboard models.
 Description
 -----------
 
-This driver implements support for the IT8603E, IT8620E, IT8623E, IT8705F,
-IT8712F, IT8716F, IT8718F, IT8720F, IT8721F, IT8726F, IT8728F, IT8732F,
+This driver implements support for the IT8603E, IT8620E, IT8623E, IT8628E,
+IT8705F, IT8712F, IT8716F, IT8718F, IT8720F, IT8721F, IT8726F, IT8728F, IT8732F,
 IT8758E, IT8771E, IT8772E, IT8781F, IT8782F, IT8783E/F, IT8786E, IT8790E, and
 SiS950 chips.
 
@@ -158,8 +161,8 @@ The IT8603E/IT8623E is a custom design,
 IT8728F. It only supports 3 fans, 16-bit fan mode, and the full speed mode
 of the fan is not supported (value 0 of pwmX_enable).
 
-The IT8620E is another custom design, hardware monitoring part is similar to
-IT8728F. It only supports 16-bit fan mode.
+The IT8620E and IT8628E are custom designs, hardware monitoring part is similar
+to IT8728F. It only supports 16-bit fan mode. Both chips support up to 6 fans.
 
 The IT8790E supports up to 3 fans. 16-bit fan mode is always enabled.
 
@@ -187,8 +190,8 @@ of 0.016 volt.  IT8603E, IT8721F/IT8758E
 2.8 volts with a resolution of 0.0109 volt.  The battery voltage in8 does not
 have limit registers.
 
-On the IT8603E, IT8721F/IT8758E, IT8732F, IT8781F, IT8782F, and IT8783E/F, some
-voltage inputs are internal and scaled inside the chip:
+On the IT8603E, IT8620E, IT8628E, IT8721F/IT8758E, IT8732F, IT8781F, IT8782F,
+and IT8783E/F, some voltage inputs are internal and scaled inside the chip:
 * in3 (optional)
 * in7 (optional for IT8781F, IT8782F, and IT8783E/F)
 * in8 (always)
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/hwmon/max31722 linux-libre-4.7-gnu/Documentation/hwmon/max31722
--- linux-libre-4.6-gnu/Documentation/hwmon/max31722	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/hwmon/max31722	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,34 @@
+Kernel driver max31722
+======================
+
+Supported chips:
+  * Maxim Integrated MAX31722
+    Prefix: 'max31722'
+    ACPI ID: MAX31722
+    Addresses scanned: -
+    Datasheet: https://datasheets.maximintegrated.com/en/ds/MAX31722-MAX31723.pdf
+  * Maxim Integrated MAX31723
+    Prefix: 'max31723'
+    ACPI ID: MAX31723
+    Addresses scanned: -
+    Datasheet: https://datasheets.maximintegrated.com/en/ds/MAX31722-MAX31723.pdf
+
+Author: Tiberiu Breana <tiberiu.a.breana@intel.com>
+
+Description
+-----------
+
+This driver adds support for the Maxim Integrated MAX31722/MAX31723 thermometers
+and thermostats running over an SPI interface.
+
+Usage Notes
+-----------
+
+This driver uses ACPI to auto-detect devices. See ACPI IDs in the above section.
+
+Sysfs entries
+-------------
+
+The following attribute is supported:
+
+temp1_input		Measured temperature. Read-only.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/hwmon/max34440 linux-libre-4.7-gnu/Documentation/hwmon/max34440
--- linux-libre-4.6-gnu/Documentation/hwmon/max34440	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/hwmon/max34440	2016-07-24 15:23:50.000000000 -0400
@@ -5,17 +5,17 @@ Supported chips:
   * Maxim MAX34440
     Prefixes: 'max34440'
     Addresses scanned: -
-    Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX34440.pdf
+    Datasheet: http://datasheets.maximintegrated.com/en/ds/MAX34440.pdf
   * Maxim MAX34441
     PMBus 5-Channel Power-Supply Manager and Intelligent Fan Controller
     Prefixes: 'max34441'
     Addresses scanned: -
-    Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX34441.pdf
+    Datasheet: http://datasheets.maximintegrated.com/en/ds/MAX34441.pdf
   * Maxim MAX34446
     PMBus Power-Supply Data Logger
     Prefixes: 'max34446'
     Addresses scanned: -
-    Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX34446.pdf
+    Datasheet: http://datasheets.maximintegrated.com/en/ds/MAX34446.pdf
   * Maxim MAX34460
     PMBus 12-Channel Voltage Monitor & Sequencer
     Prefix: 'max34460'
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/i2c/i2c-topology linux-libre-4.7-gnu/Documentation/i2c/i2c-topology
--- linux-libre-4.6-gnu/Documentation/i2c/i2c-topology	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/i2c/i2c-topology	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,370 @@
+I2C topology
+============
+
+There are a couple of reasons for building more complex i2c topologies
+than a straight-forward i2c bus with one adapter and one or more devices.
+
+1. A mux may be needed on the bus to prevent address collisions.
+
+2. The bus may be accessible from some external bus master, and arbitration
+   may be needed to determine if it is ok to access the bus.
+
+3. A device (particularly RF tuners) may want to avoid the digital noise
+   from the i2c bus, at least most of the time, and sits behind a gate
+   that has to be operated before the device can be accessed.
+
+Etc
+
+These constructs are represented as i2c adapter trees by Linux, where
+each adapter has a parent adapter (except the root adapter) and zero or
+more child adapters. The root adapter is the actual adapter that issues
+i2c transfers, and all adapters with a parent are part of an "i2c-mux"
+object (quoted, since it can also be an arbitrator or a gate).
+
+Depending of the particular mux driver, something happens when there is
+an i2c transfer on one of its child adapters. The mux driver can
+obviously operate a mux, but it can also do arbitration with an external
+bus master or open a gate. The mux driver has two operations for this,
+select and deselect. select is called before the transfer and (the
+optional) deselect is called after the transfer.
+
+
+Locking
+=======
+
+There are two variants of locking available to i2c muxes, they can be
+mux-locked or parent-locked muxes. As is evident from below, it can be
+useful to know if a mux is mux-locked or if it is parent-locked. The
+following list was correct at the time of writing:
+
+In drivers/i2c/muxes/
+i2c-arb-gpio-challenge    Parent-locked
+i2c-mux-gpio              Normally parent-locked, mux-locked iff
+                          all involved gpio pins are controlled by the
+                          same i2c root adapter that they mux.
+i2c-mux-pca9541           Parent-locked
+i2c-mux-pca954x           Parent-locked
+i2c-mux-pinctrl           Normally parent-locked, mux-locked iff
+                          all involved pinctrl devices are controlled
+                          by the same i2c root adapter that they mux.
+i2c-mux-reg               Parent-locked
+
+In drivers/iio/
+imu/inv_mpu6050/          Mux-locked
+
+In drivers/media/
+dvb-frontends/m88ds3103   Parent-locked
+dvb-frontends/rtl2830     Parent-locked
+dvb-frontends/rtl2832     Mux-locked
+dvb-frontends/si2168      Mux-locked
+usb/cx231xx/              Parent-locked
+
+
+Mux-locked muxes
+----------------
+
+Mux-locked muxes does not lock the entire parent adapter during the
+full select-transfer-deselect transaction, only the muxes on the parent
+adapter are locked. Mux-locked muxes are mostly interesting if the
+select and/or deselect operations must use i2c transfers to complete
+their tasks. Since the parent adapter is not fully locked during the
+full transaction, unrelated i2c transfers may interleave the different
+stages of the transaction. This has the benefit that the mux driver
+may be easier and cleaner to implement, but it has some caveats.
+
+ML1. If you build a topology with a mux-locked mux being the parent
+     of a parent-locked mux, this might break the expectation from the
+     parent-locked mux that the root adapter is locked during the
+     transaction.
+
+ML2. It is not safe to build arbitrary topologies with two (or more)
+     mux-locked muxes that are not siblings, when there are address
+     collisions between the devices on the child adapters of these
+     non-sibling muxes.
+
+     I.e. the select-transfer-deselect transaction targeting e.g. device
+     address 0x42 behind mux-one may be interleaved with a similar
+     operation targeting device address 0x42 behind mux-two. The
+     intension with such a topology would in this hypothetical example
+     be that mux-one and mux-two should not be selected simultaneously,
+     but mux-locked muxes do not guarantee that in all topologies.
+
+ML3. A mux-locked mux cannot be used by a driver for auto-closing
+     gates/muxes, i.e. something that closes automatically after a given
+     number (one, in most cases) of i2c transfers. Unrelated i2c transfers
+     may creep in and close prematurely.
+
+ML4. If any non-i2c operation in the mux driver changes the i2c mux state,
+     the driver has to lock the root adapter during that operation.
+     Otherwise garbage may appear on the bus as seen from devices
+     behind the mux, when an unrelated i2c transfer is in flight during
+     the non-i2c mux-changing operation.
+
+
+Mux-locked Example
+------------------
+
+                   .----------.     .--------.
+    .--------.     |   mux-   |-----| dev D1 |
+    |  root  |--+--|  locked  |     '--------'
+    '--------'  |  |  mux M1  |--.  .--------.
+                |  '----------'  '--| dev D2 |
+                |  .--------.       '--------'
+                '--| dev D3 |
+                   '--------'
+
+When there is an access to D1, this happens:
+
+ 1. Someone issues an i2c-transfer to D1.
+ 2. M1 locks muxes on its parent (the root adapter in this case).
+ 3. M1 calls ->select to ready the mux.
+ 4. M1 (presumably) does some i2c-transfers as part of its select.
+    These transfers are normal i2c-transfers that locks the parent
+    adapter.
+ 5. M1 feeds the i2c-transfer from step 1 to its parent adapter as a
+    normal i2c-transfer that locks the parent adapter.
+ 6. M1 calls ->deselect, if it has one.
+ 7. Same rules as in step 4, but for ->deselect.
+ 8. M1 unlocks muxes on its parent.
+
+This means that accesses to D2 are lockout out for the full duration
+of the entire operation. But accesses to D3 are possibly interleaved
+at any point.
+
+
+Parent-locked muxes
+-------------------
+
+Parent-locked muxes lock the parent adapter during the full select-
+transfer-deselect transaction. The implication is that the mux driver
+has to ensure that any and all i2c transfers through that parent
+adapter during the transaction are unlocked i2c transfers (using e.g.
+__i2c_transfer), or a deadlock will follow. There are a couple of
+caveats.
+
+PL1. If you build a topology with a parent-locked mux being the child
+     of another mux, this might break a possible assumption from the
+     child mux that the root adapter is unused between its select op
+     and the actual transfer (e.g. if the child mux is auto-closing
+     and the parent mux issus i2c-transfers as part of its select).
+     This is especially the case if the parent mux is mux-locked, but
+     it may also happen if the parent mux is parent-locked.
+
+PL2. If select/deselect calls out to other subsystems such as gpio,
+     pinctrl, regmap or iio, it is essential that any i2c transfers
+     caused by these subsystems are unlocked. This can be convoluted to
+     accomplish, maybe even impossible if an acceptably clean solution
+     is sought.
+
+
+Parent-locked Example
+---------------------
+
+                   .----------.     .--------.
+    .--------.     |  parent- |-----| dev D1 |
+    |  root  |--+--|  locked  |     '--------'
+    '--------'  |  |  mux M1  |--.  .--------.
+                |  '----------'  '--| dev D2 |
+                |  .--------.       '--------'
+                '--| dev D3 |
+                   '--------'
+
+When there is an access to D1, this happens:
+
+ 1. Someone issues an i2c-transfer to D1.
+ 2. M1 locks muxes on its parent (the root adapter in this case).
+ 3. M1 locks its parent adapter.
+ 4. M1 calls ->select to ready the mux.
+ 5. If M1 does any i2c-transfers (on this root adapter) as part of
+    its select, those transfers must be unlocked i2c-transfers so
+    that they do not deadlock the root adapter.
+ 6. M1 feeds the i2c-transfer from step 1 to the root adapter as an
+    unlocked i2c-transfer, so that it does not deadlock the parent
+    adapter.
+ 7. M1 calls ->deselect, if it has one.
+ 8. Same rules as in step 5, but for ->deselect.
+ 9. M1 unlocks its parent adapter.
+10. M1 unlocks muxes on its parent.
+
+
+This means that accesses to both D2 and D3 are locked out for the full
+duration of the entire operation.
+
+
+Complex Examples
+================
+
+Parent-locked mux as parent of parent-locked mux
+------------------------------------------------
+
+This is a useful topology, but it can be bad.
+
+                   .----------.     .----------.     .--------.
+    .--------.     |  parent- |-----|  parent- |-----| dev D1 |
+    |  root  |--+--|  locked  |     |  locked  |     '--------'
+    '--------'  |  |  mux M1  |--.  |  mux M2  |--.  .--------.
+                |  '----------'  |  '----------'  '--| dev D2 |
+                |  .--------.    |  .--------.       '--------'
+                '--| dev D4 |    '--| dev D3 |
+                   '--------'       '--------'
+
+When any device is accessed, all other devices are locked out for
+the full duration of the operation (both muxes lock their parent,
+and specifically when M2 requests its parent to lock, M1 passes
+the buck to the root adapter).
+
+This topology is bad if M2 is an auto-closing mux and M1->select
+issues any unlocked i2c transfers on the root adapter that may leak
+through and be seen by the M2 adapter, thus closing M2 prematurely.
+
+
+Mux-locked mux as parent of mux-locked mux
+------------------------------------------
+
+This is a good topology.
+
+                   .----------.     .----------.     .--------.
+    .--------.     |   mux-   |-----|   mux-   |-----| dev D1 |
+    |  root  |--+--|  locked  |     |  locked  |     '--------'
+    '--------'  |  |  mux M1  |--.  |  mux M2  |--.  .--------.
+                |  '----------'  |  '----------'  '--| dev D2 |
+                |  .--------.    |  .--------.       '--------'
+                '--| dev D4 |    '--| dev D3 |
+                   '--------'       '--------'
+
+When device D1 is accessed, accesses to D2 are locked out for the
+full duration of the operation (muxes on the top child adapter of M1
+are locked). But accesses to D3 and D4 are possibly interleaved at
+any point. Accesses to D3 locks out D1 and D2, but accesses to D4
+are still possibly interleaved.
+
+
+Mux-locked mux as parent of parent-locked mux
+---------------------------------------------
+
+This is probably a bad topology.
+
+                   .----------.     .----------.     .--------.
+    .--------.     |   mux-   |-----|  parent- |-----| dev D1 |
+    |  root  |--+--|  locked  |     |  locked  |     '--------'
+    '--------'  |  |  mux M1  |--.  |  mux M2  |--.  .--------.
+                |  '----------'  |  '----------'  '--| dev D2 |
+                |  .--------.    |  .--------.       '--------'
+                '--| dev D4 |    '--| dev D3 |
+                   '--------'       '--------'
+
+When device D1 is accessed, accesses to D2 and D3 are locked out
+for the full duration of the operation (M1 locks child muxes on the
+root adapter). But accesses to D4 are possibly interleaved at any
+point.
+
+This kind of topology is generally not suitable and should probably
+be avoided. The reason is that M2 probably assumes that there will
+be no i2c transfers during its calls to ->select and ->deselect, and
+if there are, any such transfers might appear on the slave side of M2
+as partial i2c transfers, i.e. garbage or worse. This might cause
+device lockups and/or other problems.
+
+The topology is especially troublesome if M2 is an auto-closing
+mux. In that case, any interleaved accesses to D4 might close M2
+prematurely, as might any i2c-transfers part of M1->select.
+
+But if M2 is not making the above stated assumption, and if M2 is not
+auto-closing, the topology is fine.
+
+
+Parent-locked mux as parent of mux-locked mux
+---------------------------------------------
+
+This is a good topology.
+
+                   .----------.     .----------.     .--------.
+    .--------.     |  parent- |-----|   mux-   |-----| dev D1 |
+    |  root  |--+--|  locked  |     |  locked  |     '--------'
+    '--------'  |  |  mux M1  |--.  |  mux M2  |--.  .--------.
+                |  '----------'  |  '----------'  '--| dev D2 |
+                |  .--------.    |  .--------.       '--------'
+                '--| dev D4 |    '--| dev D3 |
+                   '--------'       '--------'
+
+When D1 is accessed, accesses to D2 are locked out for the full
+duration of the operation (muxes on the top child adapter of M1
+are locked). Accesses to D3 and D4 are possibly interleaved at
+any point, just as is expected for mux-locked muxes.
+
+When D3 or D4 are accessed, everything else is locked out. For D3
+accesses, M1 locks the root adapter. For D4 accesses, the root
+adapter is locked directly.
+
+
+Two mux-locked sibling muxes
+----------------------------
+
+This is a good topology.
+
+                                    .--------.
+                   .----------.  .--| dev D1 |
+                   |   mux-   |--'  '--------'
+                .--|  locked  |     .--------.
+                |  |  mux M1  |-----| dev D2 |
+                |  '----------'     '--------'
+                |  .----------.     .--------.
+    .--------.  |  |   mux-   |-----| dev D3 |
+    |  root  |--+--|  locked  |     '--------'
+    '--------'  |  |  mux M2  |--.  .--------.
+                |  '----------'  '--| dev D4 |
+                |  .--------.       '--------'
+                '--| dev D5 |
+                   '--------'
+
+When D1 is accessed, accesses to D2, D3 and D4 are locked out. But
+accesses to D5 may be interleaved at any time.
+
+
+Two parent-locked sibling muxes
+-------------------------------
+
+This is a good topology.
+
+                                   .--------.
+                   .----------.  .--| dev D1 |
+                   |  parent- |--'  '--------'
+                .--|  locked  |     .--------.
+                |  |  mux M1  |-----| dev D2 |
+                |  '----------'     '--------'
+                |  .----------.     .--------.
+    .--------.  |  |  parent- |-----| dev D3 |
+    |  root  |--+--|  locked  |     '--------'
+    '--------'  |  |  mux M2  |--.  .--------.
+                |  '----------'  '--| dev D4 |
+                |  .--------.       '--------'
+                '--| dev D5 |
+                   '--------'
+
+When any device is accessed, accesses to all other devices are locked
+out.
+
+
+Mux-locked and parent-locked sibling muxes
+------------------------------------------
+
+This is a good topology.
+
+                                   .--------.
+                   .----------.  .--| dev D1 |
+                   |   mux-   |--'  '--------'
+                .--|  locked  |     .--------.
+                |  |  mux M1  |-----| dev D2 |
+                |  '----------'     '--------'
+                |  .----------.     .--------.
+    .--------.  |  |  parent- |-----| dev D3 |
+    |  root  |--+--|  locked  |     '--------'
+    '--------'  |  |  mux M2  |--.  .--------.
+                |  '----------'  '--| dev D4 |
+                |  .--------.       '--------'
+                '--| dev D5 |
+                   '--------'
+
+When D1 or D2 are accessed, accesses to D3 and D4 are locked out while
+accesses to D5 may interleave. When D3 or D4 are accessed, accesses to
+all other devices are locked out.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/infiniband/ipoib.txt linux-libre-4.7-gnu/Documentation/infiniband/ipoib.txt
--- linux-libre-4.6-gnu/Documentation/infiniband/ipoib.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/infiniband/ipoib.txt	2016-07-24 15:23:50.000000000 -0400
@@ -25,7 +25,7 @@ Partitions and P_Keys
   main interface for a subinterface is in "parent."
 
   Child interface create/delete can also be done using IPoIB's
-  rtnl_link_ops, where childs created using either way behave the same.
+  rtnl_link_ops, where children created using either way behave the same.
 
 Datagram vs Connected modes
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/infiniband/sysfs.txt linux-libre-4.7-gnu/Documentation/infiniband/sysfs.txt
--- linux-libre-4.6-gnu/Documentation/infiniband/sysfs.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/infiniband/sysfs.txt	2016-07-24 15:23:50.000000000 -0400
@@ -56,6 +56,18 @@ SYSFS FILES
   ports/1/pkeys/10 contains the value at index 10 in port 1's P_Key
   table.
 
+  There is an optional "hw_counters" subdirectory that may be under either
+  the parent device or the port subdirectories or both.  If present,
+  there are a list of counters provided by the hardware.  They may match
+  some of the counters in the counters directory, but they often include
+  many other counters.  In addition to the various counters, there will
+  be a file named "lifespan" that configures how frequently the core
+  should update the counters when they are being accessed (counters are
+  not updated if they are not being accessed).  The lifespan is in milli-
+  seconds and defaults to 10 unless set to something else by the driver.
+  Users may echo a value between 0 - 10000 to the lifespan file to set
+  the length of time between updates in milliseconds.
+
 MTHCA
 
   The Mellanox HCA driver also creates the files:
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/IRQ-domain.txt linux-libre-4.7-gnu/Documentation/IRQ-domain.txt
--- linux-libre-4.6-gnu/Documentation/IRQ-domain.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/IRQ-domain.txt	2016-07-24 15:23:50.000000000 -0400
@@ -70,6 +70,7 @@ of the reverse map types are described b
 
 ==== Linear ====
 irq_domain_add_linear()
+irq_domain_create_linear()
 
 The linear reverse map maintains a fixed size table indexed by the
 hwirq number.  When a hwirq is mapped, an irq_desc is allocated for
@@ -81,10 +82,16 @@ map are fixed time lookup for IRQ number
 allocated for in-use IRQs.  The disadvantage is that the table must be
 as large as the largest possible hwirq number.
 
+irq_domain_add_linear() and irq_domain_create_linear() are functionally
+equivalent, except for the first argument is different - the former
+accepts an Open Firmware specific 'struct device_node', while the latter
+accepts a more general abstraction 'struct fwnode_handle'.
+
 The majority of drivers should use the linear map.
 
 ==== Tree ====
 irq_domain_add_tree()
+irq_domain_create_tree()
 
 The irq_domain maintains a radix tree map from hwirq numbers to Linux
 IRQs.  When an hwirq is mapped, an irq_desc is allocated and the
@@ -95,6 +102,11 @@ since it doesn't need to allocate a tabl
 hwirq number.  The disadvantage is that hwirq to IRQ number lookup is
 dependent on how many entries are in the table.
 
+irq_domain_add_tree() and irq_domain_create_tree() are functionally
+equivalent, except for the first argument is different - the former
+accepts an Open Firmware specific 'struct device_node', while the latter
+accepts a more general abstraction 'struct fwnode_handle'.
+
 Very few drivers should need this mapping.
 
 ==== No Map ===-
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/isa.txt linux-libre-4.7-gnu/Documentation/isa.txt
--- linux-libre-4.6-gnu/Documentation/isa.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/isa.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,121 @@
+ISA Drivers
+-----------
+
+The following text is adapted from the commit message of the initial
+commit of the ISA bus driver authored by Rene Herman.
+
+During the recent "isa drivers using platform devices" discussion it was
+pointed out that (ALSA) ISA drivers ran into the problem of not having
+the option to fail driver load (device registration rather) upon not
+finding their hardware due to a probe() error not being passed up
+through the driver model. In the course of that, I suggested a separate
+ISA bus might be best; Russell King agreed and suggested this bus could
+use the .match() method for the actual device discovery.
+
+The attached does this. For this old non (generically) discoverable ISA
+hardware only the driver itself can do discovery so as a difference with
+the platform_bus, this isa_bus also distributes match() up to the
+driver.
+
+As another difference: these devices only exist in the driver model due
+to the driver creating them because it might want to drive them, meaning
+that all device creation has been made internal as well.
+
+The usage model this provides is nice, and has been acked from the ALSA
+side by Takashi Iwai and Jaroslav Kysela. The ALSA driver module_init's
+now (for oldisa-only drivers) become:
+
+static int __init alsa_card_foo_init(void)
+{
+	return isa_register_driver(&snd_foo_isa_driver, SNDRV_CARDS);
+}
+
+static void __exit alsa_card_foo_exit(void)
+{
+	isa_unregister_driver(&snd_foo_isa_driver);
+}
+
+Quite like the other bus models therefore. This removes a lot of
+duplicated init code from the ALSA ISA drivers.
+
+The passed in isa_driver struct is the regular driver struct embedding a
+struct device_driver, the normal probe/remove/shutdown/suspend/resume
+callbacks, and as indicated that .match callback.
+
+The "SNDRV_CARDS" you see being passed in is a "unsigned int ndev"
+parameter, indicating how many devices to create and call our methods
+with.
+
+The platform_driver callbacks are called with a platform_device param;
+the isa_driver callbacks are being called with a "struct device *dev,
+unsigned int id" pair directly -- with the device creation completely
+internal to the bus it's much cleaner to not leak isa_dev's by passing
+them in at all. The id is the only thing we ever want other then the
+struct device * anyways, and it makes for nicer code in the callbacks as
+well.
+
+With this additional .match() callback ISA drivers have all options. If
+ALSA would want to keep the old non-load behaviour, it could stick all
+of the old .probe in .match, which would only keep them registered after
+everything was found to be present and accounted for. If it wanted the
+behaviour of always loading as it inadvertently did for a bit after the
+changeover to platform devices, it could just not provide a .match() and
+do everything in .probe() as before.
+
+If it, as Takashi Iwai already suggested earlier as a way of following
+the model from saner buses more closely, wants to load when a later bind
+could conceivably succeed, it could use .match() for the prerequisites
+(such as checking the user wants the card enabled and that port/irq/dma
+values have been passed in) and .probe() for everything else. This is
+the nicest model.
+
+To the code...
+
+This exports only two functions; isa_{,un}register_driver().
+
+isa_register_driver() register's the struct device_driver, and then
+loops over the passed in ndev creating devices and registering them.
+This causes the bus match method to be called for them, which is:
+
+int isa_bus_match(struct device *dev, struct device_driver *driver)
+{
+          struct isa_driver *isa_driver = to_isa_driver(driver);
+
+          if (dev->platform_data == isa_driver) {
+                  if (!isa_driver->match ||
+                          isa_driver->match(dev, to_isa_dev(dev)->id))
+                          return 1;
+                  dev->platform_data = NULL;
+          }
+          return 0;
+}
+
+The first thing this does is check if this device is in fact one of this
+driver's devices by seeing if the device's platform_data pointer is set
+to this driver. Platform devices compare strings, but we don't need to
+do that with everything being internal, so isa_register_driver() abuses
+dev->platform_data as a isa_driver pointer which we can then check here.
+I believe platform_data is available for this, but if rather not, moving
+the isa_driver pointer to the private struct isa_dev is ofcourse fine as
+well.
+
+Then, if the the driver did not provide a .match, it matches. If it did,
+the driver match() method is called to determine a match.
+
+If it did _not_ match, dev->platform_data is reset to indicate this to
+isa_register_driver which can then unregister the device again.
+
+If during all this, there's any error, or no devices matched at all
+everything is backed out again and the error, or -ENODEV, is returned.
+
+isa_unregister_driver() just unregisters the matched devices and the
+driver itself.
+
+module_isa_driver is a helper macro for ISA drivers which do not do
+anything special in module init/exit. This eliminates a lot of
+boilerplate code. Each module may only use this macro once, and calling
+it replaces module_init and module_exit.
+
+max_num_isa_dev is a macro to determine the maximum possible number of
+ISA devices which may be registered in the I/O port address space given
+the address extent of the ISA devices.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/ja_JP/HOWTO linux-libre-4.7-gnu/Documentation/ja_JP/HOWTO
--- linux-libre-4.6-gnu/Documentation/ja_JP/HOWTO	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/ja_JP/HOWTO	2016-07-24 15:23:50.000000000 -0400
@@ -290,12 +290,6 @@ 以下のとおり-
   - このプロセスはカーネルが 「準備ができた」と考えられるまで継続しま
     す。このプロセスはだいたい 6週間継続します。
 
-  - 各リリースでの既知の後戻り問題(regression: このリリースの中で新規
-    に作り込まれた問題を指す) はその都度 Linux-kernel メーリングリスト
-    に投稿されます。ゴールとしては、カーネルが 「準備ができた」と宣言
-    する前にこのリストの長さをゼロに減らすことですが、現実には、数個の
-    後戻り問題がリリース時にたびたび残ってしまいます。
-
 Andrew Morton が Linux-kernel メーリングリストにカーネルリリースについ
 て書いたことをここで言っておくことは価値があります-
   「カーネルがいつリリースされるかは誰も知りません。なぜなら、これは現
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/kbuild/kconfig-language.txt linux-libre-4.7-gnu/Documentation/kbuild/kconfig-language.txt
--- linux-libre-4.6-gnu/Documentation/kbuild/kconfig-language.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/kbuild/kconfig-language.txt	2016-07-24 15:23:50.000000000 -0400
@@ -241,9 +241,8 @@ comment "module support disabled"
 	depends on !MODULES
 
 MODVERSIONS directly depends on MODULES, this means it's only visible if
-MODULES is different from 'n'. The comment on the other hand is always
-visible when MODULES is visible (the (empty) dependency of MODULES is
-also part of the comment dependencies).
+MODULES is different from 'n'. The comment on the other hand is only
+visible when MODULES is set to 'n'.
 
 
 Kconfig syntax
@@ -285,12 +284,17 @@ choices:
 	"endchoice"
 
 This defines a choice group and accepts any of the above attributes as
-options. A choice can only be of type bool or tristate, while a boolean
-choice only allows a single config entry to be selected, a tristate
-choice also allows any number of config entries to be set to 'm'. This
-can be used if multiple drivers for a single hardware exists and only a
-single driver can be compiled/loaded into the kernel, but all drivers
-can be compiled as modules.
+options. A choice can only be of type bool or tristate.  If no type is
+specified for a choice, it's type will be determined by the type of
+the first choice element in the group or remain unknown if none of the
+choice elements have a type specified, as well.
+
+While a boolean choice only allows a single config entry to be
+selected, a tristate choice also allows any number of config entries
+to be set to 'm'. This can be used if multiple drivers for a single
+hardware exists and only a single driver can be compiled/loaded into
+the kernel, but all drivers can be compiled as modules.
+
 A choice accepts another option "optional", which allows to set the
 choice to 'n' and no entry needs to be selected.
 If no [symbol] is associated with a choice, then you can not have multiple
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/kdump/gdbmacros.txt linux-libre-4.7-gnu/Documentation/kdump/gdbmacros.txt
--- linux-libre-4.6-gnu/Documentation/kdump/gdbmacros.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/kdump/gdbmacros.txt	2016-07-24 15:23:50.000000000 -0400
@@ -15,15 +15,16 @@
 
 define bttnobp
 	set $tasks_off=((size_t)&((struct task_struct *)0)->tasks)
-	set $pid_off=((size_t)&((struct task_struct *)0)->pids[1].pid_list.next)
+	set $pid_off=((size_t)&((struct task_struct *)0)->thread_group.next)
 	set $init_t=&init_task
 	set $next_t=(((char *)($init_t->tasks).next) - $tasks_off)
+	set var $stacksize = sizeof(union thread_union)
 	while ($next_t != $init_t)
 		set $next_t=(struct task_struct *)$next_t
 		printf "\npid %d; comm %s:\n", $next_t.pid, $next_t.comm
 		printf "===================\n"
-		set var $stackp = $next_t.thread.esp
-		set var $stack_top = ($stackp & ~4095) + 4096
+		set var $stackp = $next_t.thread.sp
+		set var $stack_top = ($stackp & ~($stacksize - 1)) + $stacksize
 
 		while ($stackp < $stack_top)
 			if (*($stackp) > _stext && *($stackp) < _sinittext)
@@ -31,13 +32,13 @@ define bttnobp
 			end
 			set $stackp += 4
 		end
-		set $next_th=(((char *)$next_t->pids[1].pid_list.next) - $pid_off)
+		set $next_th=(((char *)$next_t->thread_group.next) - $pid_off)
 		while ($next_th != $next_t)
 			set $next_th=(struct task_struct *)$next_th
 			printf "\npid %d; comm %s:\n", $next_t.pid, $next_t.comm
 			printf "===================\n"
-			set var $stackp = $next_t.thread.esp
-			set var $stack_top = ($stackp & ~4095) + 4096
+			set var $stackp = $next_t.thread.sp
+			set var $stack_top = ($stackp & ~($stacksize - 1)) + stacksize
 
 			while ($stackp < $stack_top)
 				if (*($stackp) > _stext && *($stackp) < _sinittext)
@@ -45,7 +46,7 @@ define bttnobp
 				end
 				set $stackp += 4
 			end
-			set $next_th=(((char *)$next_th->pids[1].pid_list.next) - $pid_off)
+			set $next_th=(((char *)$next_th->thread_group.next) - $pid_off)
 		end
 		set $next_t=(char *)($next_t->tasks.next) - $tasks_off
 	end
@@ -54,42 +55,44 @@ document bttnobp
 	dump all thread stack traces on a kernel compiled with !CONFIG_FRAME_POINTER
 end
 
+define btthreadstack
+	set var $pid_task = $arg0
+
+	printf "\npid %d; comm %s:\n", $pid_task.pid, $pid_task.comm
+	printf "task struct: "
+	print $pid_task
+	printf "===================\n"
+	set var $stackp = $pid_task.thread.sp
+	set var $stacksize = sizeof(union thread_union)
+	set var $stack_top = ($stackp & ~($stacksize - 1)) + $stacksize
+	set var $stack_bot = ($stackp & ~($stacksize - 1))
+
+	set $stackp = *((unsigned long *) $stackp)
+	while (($stackp < $stack_top) && ($stackp > $stack_bot))
+		set var $addr = *(((unsigned long *) $stackp) + 1)
+		info symbol $addr
+		set $stackp = *((unsigned long *) $stackp)
+	end
+end
+document btthreadstack
+	 dump a thread stack using the given task structure pointer
+end
+
+
 define btt
 	set $tasks_off=((size_t)&((struct task_struct *)0)->tasks)
-	set $pid_off=((size_t)&((struct task_struct *)0)->pids[1].pid_list.next)
+	set $pid_off=((size_t)&((struct task_struct *)0)->thread_group.next)
 	set $init_t=&init_task
 	set $next_t=(((char *)($init_t->tasks).next) - $tasks_off)
 	while ($next_t != $init_t)
 		set $next_t=(struct task_struct *)$next_t
-		printf "\npid %d; comm %s:\n", $next_t.pid, $next_t.comm
-		printf "===================\n"
-		set var $stackp = $next_t.thread.esp
-		set var $stack_top = ($stackp & ~4095) + 4096
-		set var $stack_bot = ($stackp & ~4095)
-
-		set $stackp = *($stackp)
-		while (($stackp < $stack_top) && ($stackp > $stack_bot))
-			set var $addr = *($stackp + 4)
-			info symbol $addr
-			set $stackp = *($stackp)
-		end
+		btthreadstack $next_t
 
-		set $next_th=(((char *)$next_t->pids[1].pid_list.next) - $pid_off)
+		set $next_th=(((char *)$next_t->thread_group.next) - $pid_off)
 		while ($next_th != $next_t)
 			set $next_th=(struct task_struct *)$next_th
-			printf "\npid %d; comm %s:\n", $next_t.pid, $next_t.comm
-			printf "===================\n"
-			set var $stackp = $next_t.thread.esp
-			set var $stack_top = ($stackp & ~4095) + 4096
-			set var $stack_bot = ($stackp & ~4095)
-
-			set $stackp = *($stackp)
-			while (($stackp < $stack_top) && ($stackp > $stack_bot))
-				set var $addr = *($stackp + 4)
-				info symbol $addr
-				set $stackp = *($stackp)
-			end
-			set $next_th=(((char *)$next_th->pids[1].pid_list.next) - $pid_off)
+			btthreadstack $next_th
+			set $next_th=(((char *)$next_th->thread_group.next) - $pid_off)
 		end
 		set $next_t=(char *)($next_t->tasks.next) - $tasks_off
 	end
@@ -101,7 +104,7 @@ end
 define btpid
 	set var $pid = $arg0
 	set $tasks_off=((size_t)&((struct task_struct *)0)->tasks)
-	set $pid_off=((size_t)&((struct task_struct *)0)->pids[1].pid_list.next)
+	set $pid_off=((size_t)&((struct task_struct *)0)->thread_group.next)
 	set $init_t=&init_task
 	set $next_t=(((char *)($init_t->tasks).next) - $tasks_off)
 	set var $pid_task = 0
@@ -113,29 +116,18 @@ define btpid
 			set $pid_task = $next_t
 		end
 
-		set $next_th=(((char *)$next_t->pids[1].pid_list.next) - $pid_off)
+		set $next_th=(((char *)$next_t->thread_group.next) - $pid_off)
 		while ($next_th != $next_t)
 			set $next_th=(struct task_struct *)$next_th
 			if ($next_th.pid == $pid)
 				set $pid_task = $next_th
 			end
-			set $next_th=(((char *)$next_th->pids[1].pid_list.next) - $pid_off)
+			set $next_th=(((char *)$next_th->thread_group.next) - $pid_off)
 		end
 		set $next_t=(char *)($next_t->tasks.next) - $tasks_off
 	end
 
-	printf "\npid %d; comm %s:\n", $pid_task.pid, $pid_task.comm
-	printf "===================\n"
-	set var $stackp = $pid_task.thread.esp
-	set var $stack_top = ($stackp & ~4095) + 4096
-	set var $stack_bot = ($stackp & ~4095)
-
-	set $stackp = *($stackp)
-	while (($stackp < $stack_top) && ($stackp > $stack_bot))
-		set var $addr = *($stackp + 4)
-		info symbol $addr
-		set $stackp = *($stackp)
-	end
+	btthreadstack $pid_task
 end
 document btpid
 	backtrace of pid
@@ -145,7 +137,7 @@ end
 define trapinfo
 	set var $pid = $arg0
 	set $tasks_off=((size_t)&((struct task_struct *)0)->tasks)
-	set $pid_off=((size_t)&((struct task_struct *)0)->pids[1].pid_list.next)
+	set $pid_off=((size_t)&((struct task_struct *)0)->thread_group.next)
 	set $init_t=&init_task
 	set $next_t=(((char *)($init_t->tasks).next) - $tasks_off)
 	set var $pid_task = 0
@@ -157,13 +149,13 @@ define trapinfo
 			set $pid_task = $next_t
 		end
 
-		set $next_th=(((char *)$next_t->pids[1].pid_list.next) - $pid_off)
+		set $next_th=(((char *)$next_t->thread_group.next) - $pid_off)
 		while ($next_th != $next_t)
 			set $next_th=(struct task_struct *)$next_th
 			if ($next_th.pid == $pid)
 				set $pid_task = $next_th
 			end
-			set $next_th=(((char *)$next_th->pids[1].pid_list.next) - $pid_off)
+			set $next_th=(((char *)$next_th->thread_group.next) - $pid_off)
 		end
 		set $next_t=(char *)($next_t->tasks.next) - $tasks_off
 	end
@@ -178,21 +170,92 @@ document trapinfo
 	address the kernel panicked.
 end
 
+define dump_log_idx
+	set $idx = $arg0
+	if ($argc > 1)
+		set $prev_flags = $arg1
+	else
+		set $prev_flags = 0
+	end
+	set $msg = ((struct printk_log *) (log_buf + $idx))
+	set $prefix = 1
+	set $newline = 1
+	set $log = log_buf + $idx + sizeof(*$msg)
 
-define dmesg
-	set $i = 0
-	set $end_idx = (log_end - 1) & (log_buf_len - 1)
+	# prev & LOG_CONT && !(msg->flags & LOG_PREIX)
+	if (($prev_flags & 8) && !($msg->flags & 4))
+		set $prefix = 0
+	end
 
-	while ($i < logged_chars)
-		set $idx = (log_end - 1 - logged_chars + $i) & (log_buf_len - 1)
+	# msg->flags & LOG_CONT
+	if ($msg->flags & 8)
+		# (prev & LOG_CONT && !(prev & LOG_NEWLINE))
+		if (($prev_flags & 8) && !($prev_flags & 2))
+			set $prefix = 0
+		end
+		# (!(msg->flags & LOG_NEWLINE))
+		if (!($msg->flags & 2))
+			set $newline = 0
+		end
+	end
 
-		if ($idx + 100 <= $end_idx) || \
-		   ($end_idx <= $idx && $idx + 100 < log_buf_len)
-			printf "%.100s", &log_buf[$idx]
-			set $i = $i + 100
+	if ($prefix)
+		printf "[%5lu.%06lu] ", $msg->ts_nsec / 1000000000, $msg->ts_nsec % 1000000000
+	end
+	if ($msg->text_len != 0)
+		eval "printf \"%%%d.%ds\", $log", $msg->text_len, $msg->text_len
+	end
+	if ($newline)
+		printf "\n"
+	end
+	if ($msg->dict_len > 0)
+		set $dict = $log + $msg->text_len
+		set $idx = 0
+		set $line = 1
+		while ($idx < $msg->dict_len)
+			if ($line)
+				printf " "
+				set $line = 0
+			end
+			set $c = $dict[$idx]
+			if ($c == '\0')
+				printf "\n"
+				set $line = 1
+			else
+				if ($c < ' ' || $c >= 127 || $c == '\\')
+					printf "\\x%02x", $c
+				else
+					printf "%c", $c
+				end
+			end
+			set $idx = $idx + 1
+		end
+		printf "\n"
+	end
+end
+document dump_log_idx
+	Dump a single log given its index in the log buffer.  The first
+	parameter is the index into log_buf, the second is optional and
+	specified the previous log buffer's flags, used for properly
+	formatting continued lines.
+end
+
+define dmesg
+	set $i = log_first_idx
+	set $end_idx = log_first_idx
+	set $prev_flags = 0
+
+	while (1)
+		set $msg = ((struct printk_log *) (log_buf + $i))
+		if ($msg->len == 0)
+			set $i = 0
 		else
-			printf "%c", log_buf[$idx]
-			set $i = $i + 1
+			dump_log_idx $i $prev_flags
+			set $i = $i + $msg->len
+			set $prev_flags = $msg->flags
+		end
+		if ($i == $end_idx)
+			loop_break
 		end
 	end
 end
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/kdump/kdump.txt linux-libre-4.7-gnu/Documentation/kdump/kdump.txt
--- linux-libre-4.6-gnu/Documentation/kdump/kdump.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/kdump/kdump.txt	2016-07-24 15:23:50.000000000 -0400
@@ -263,12 +263,6 @@ The syntax is:
     crashkernel=<range1>:<size1>[,<range2>:<size2>,...][@offset]
     range=start-[end]
 
-Please note, on arm, the offset is required.
-    crashkernel=<range1>:<size1>[,<range2>:<size2>,...]@offset
-    range=start-[end]
-
-    'start' is inclusive and 'end' is exclusive.
-
 For example:
 
     crashkernel=512M-2G:64M,2G-:128M
@@ -307,10 +301,9 @@ Boot into System Kernel
    on the memory consumption of the kdump system. In general this is not
    dependent on the memory size of the production system.
 
-   On arm, use "crashkernel=Y@X". Note that the start address of the kernel
-   will be aligned to 128MiB (0x08000000), so if the start address is not then
-   any space below the alignment point may be overwritten by the dump-capture kernel,
-   which means it is possible that the vmcore is not that precise as expected.
+   On arm, the use of "crashkernel=Y@X" is no longer necessary; the
+   kernel will automatically locate the crash kernel image within the
+   first 512MB of RAM if X is not given.
 
 
 Load the Dump-capture Kernel
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/kernel-docs.txt linux-libre-4.7-gnu/Documentation/kernel-docs.txt
--- linux-libre-4.6-gnu/Documentation/kernel-docs.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/kernel-docs.txt	2016-07-24 15:23:50.000000000 -0400
@@ -194,15 +194,15 @@
        simple---most of the complexity (other than talking to the
        hardware) involves managing network packets in memory".
        
-     * Title: "Writing Linux Device Drivers"
+     * Title: "Linux Kernel Hackers' Guide"
        Author: Michael K. Johnson.
-       URL: http://users.evitech.fi/~tk/rtos/writing_linux_device_d.html
-       Keywords: files, VFS, file operations, kernel interface, character
-       vs block devices, I/O access, hardware interrupts, DMA, access to
-       user memory, memory allocation, timers.
-       Description: Introductory 50-minutes (sic) tutorial on writing
-       device drivers. 12 pages written by the same author of the "Kernel
-       Hackers' Guide" which give a very good overview of the topic.
+       URL: http://www.tldp.org/LDP/khg/HyperNews/get/khg.html
+       Keywords: device drivers, files, VFS, kernel interface, character vs
+       block devices, hardware interrupts, scsi, DMA, access to user memory,
+       memory allocation, timers.
+       Description: A guide designed to help you get up to speed on the
+       concepts that are not intuitevly obvious, and to document the internal
+       structures of Linux.
        
      * Title: "The Venus kernel interface"
        Author: Peter J. Braam.
@@ -250,7 +250,7 @@
 
      * Title: "Analysis of the Ext2fs structure"
        Author: Louis-Dominique Dubeau.
-       URL: http://www.nondot.org/sabre/os/files/FileSystems/ext2fs/
+       URL: http://teaching.csse.uwa.edu.au/units/CITS2002/fs-ext2/
        Keywords: ext2, filesystem, ext2fs.
        Description: Description of ext2's blocks, directories, inodes,
        bitmaps, invariants...
@@ -266,14 +266,14 @@
 
      * Title: "Kernel API changes from 2.0 to 2.2"
        Author: Richard Gooch.
-       URL:
-       http://www.linuxhq.com/guides/LKMPG/node28.html 
+       URL: http://www.safe-mbox.com/~rgooch/linux/docs/porting-to-2.2.html
        Keywords: 2.2, changes.
        Description: Kernel functions/structures/variables which changed
        from 2.0.x to 2.2.x.
 
      * Title: "Kernel API changes from 2.2 to 2.4"
        Author: Richard Gooch.
+       URL: http://www.safe-mbox.com/~rgooch/linux/docs/porting-to-2.4.html
        Keywords: 2.4, changes.
        Description: Kernel functions/structures/variables which changed
        from 2.2.x to 2.4.x.
@@ -609,6 +609,13 @@
        Pages: 432.
        ISBN: 0-201-63338-8
 
+     * Title: "Linux Kernel Development, 3rd Edition"
+       Author: Robert Love
+       Publisher: Addison-Wesley.
+       Date: July, 2010
+       Pages: 440
+       ISBN: 978-0672329463
+
      MISCELLANEOUS:
 
      * Name: linux/Documentation
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/kernel-parameters.txt linux-libre-4.7-gnu/Documentation/kernel-parameters.txt
--- linux-libre-4.6-gnu/Documentation/kernel-parameters.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/kernel-parameters.txt	2016-07-24 15:23:50.000000000 -0400
@@ -131,6 +131,7 @@ parameter is applicable:
 			More X86-64 boot options can be found in
 			Documentation/x86/x86_64/boot-options.txt .
 	X86	Either 32-bit or 64-bit x86 (same as X86-32+X86-64)
+	X86_UV	SGI UV support is enabled.
 	XEN	Xen support is enabled
 
 In addition, the following text indicates that the option:
@@ -167,16 +168,18 @@ bytes respectively. Such letter suffixes
 
 	acpi=		[HW,ACPI,X86,ARM64]
 			Advanced Configuration and Power Interface
-			Format: { force | off | strict | noirq | rsdt |
+			Format: { force | on | off | strict | noirq | rsdt |
 				  copy_dsdt }
 			force -- enable ACPI if default was off
+			on -- enable ACPI but allow fallback to DT [arm64]
 			off -- disable ACPI if default was on
 			noirq -- do not use ACPI for IRQ routing
 			strict -- Be less tolerant of platforms that are not
 				strictly ACPI specification compliant.
 			rsdt -- prefer RSDT over (default) XSDT
 			copy_dsdt -- copy DSDT to memory
-			For ARM64, ONLY "acpi=off" or "acpi=force" are available
+			For ARM64, ONLY "acpi=off", "acpi=on" or "acpi=force"
+			are available
 
 			See also Documentation/power/runtime_pm.txt, pci=noacpi
 
@@ -312,6 +315,8 @@ bytes respectively. Such letter suffixes
 			acpi_osi=!*		# remove all strings
 			acpi_osi=!		# disable all built-in OS vendor
 						  strings
+			acpi_osi=!!		# enable all built-in OS vendor
+						  strings
 			acpi_osi=		# disable all strings
 
 			'acpi_osi=!' can be used in combination with single or
@@ -542,6 +547,13 @@ bytes respectively. Such letter suffixes
 			Format: <int> (must be >=0)
 			Default: 64
 
+	bau=		[X86_UV] Enable the BAU on SGI UV.  The default
+			behavior is to disable the BAU (i.e. bau=0).
+			Format: { "0" | "1" }
+			0 - Disable the BAU.
+			1 - Enable the BAU.
+			unset - Disable the BAU.
+
 	baycom_epp=	[HW,AX25]
 			Format: <io>,<mode>
 
@@ -826,6 +838,9 @@ bytes respectively. Such letter suffixes
 			It will be ignored when crashkernel=X,high is not used
 			or memory reserved is below 4G.
 
+	cryptomgr.notests
+                        [KNL] Disable crypto self-tests
+
 	cs89x0_dma=	[HW,NET]
 			Format: <dma>
 
@@ -1039,6 +1054,12 @@ bytes respectively. Such letter suffixes
 			the driver will use only 32-bit accessors to read/write
 			the device registers.
 
+		meson,<addr>
+			Start an early, polled-mode console on a meson serial
+			port at the specified address. The serial port must
+			already be setup and configured. Options are not yet
+			supported.
+
 		msm_serial,<addr>
 			Start an early, polled-mode console on an msm serial
 			port at the specified address. The serial port
@@ -1661,6 +1682,11 @@ bytes respectively. Such letter suffixes
 		hwp_only
 			Only load intel_pstate on systems which support
 			hardware P state control (HWP) if available.
+		support_acpi_ppc
+			Enforce ACPI _PPC performance limits. If the Fixed ACPI
+			Description Table, specifies preferred power management
+			profile as "Enterprise Server" or "Performance Server",
+			then this feature is turned on by default.
 
 	intremap=	[X86-64, Intel-IOMMU]
 			on	enable Interrupt Remapping (default)
@@ -1767,6 +1793,13 @@ bytes respectively. Such letter suffixes
 			PCI device 00:14.0 write the parameter as:
 				ivrs_hpet[0]=00:14.0
 
+	ivrs_acpihid	[HW,X86_64]
+			Provide an override to the ACPI-HID:UID<->DEVICE-ID
+			mapping provided in the IVRS ACPI table. For
+			example, to map UART-HID:UID AMD0020:0 to
+			PCI device 00:14.5 write the parameter as:
+				ivrs_acpihid[00:14.5]=AMD0020:0
+
 	js=		[HW,JOY] Analog joystick
 			See Documentation/input/joystick.txt.
 
@@ -2141,6 +2174,14 @@ bytes respectively. Such letter suffixes
 			[KNL,SH] Allow user to override the default size for
 			per-device physically contiguous DMA buffers.
 
+        memhp_default_state=online/offline
+			[KNL] Set the initial state for the memory hotplug
+			onlining policy. If not specified, the default value is
+			set according to the
+			CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE kernel config
+			option.
+			See Documentation/memory-hotplug.txt.
+
 	memmap=exactmap	[KNL,X86] Enable setting of an exact
 			E820 memory map, as specified by the user.
 			Such memmap=exactmap lines can be constructed based on
@@ -2538,6 +2579,9 @@ bytes respectively. Such letter suffixes
 
 	nohugeiomap	[KNL,x86] Disable kernel huge I/O mappings.
 
+	nosmt		[KNL,S390] Disable symmetric multithreading (SMT).
+			Equivalent to smt=1.
+
 	noxsave		[BUGS=X86] Disables x86 extended register state save
 			and restore using xsave. The kernel will fallback to
 			enabling legacy floating-point and sse state.
@@ -2921,11 +2965,6 @@ bytes respectively. Such letter suffixes
 				for broken drivers that don't call it.
 		skip_isa_align	[X86] do not align io start addr, so can
 				handle more pci cards
-		firmware	[ARM] Do not re-enumerate the bus but instead
-				just use the configuration from the
-				bootloader. This is currently used on
-				IXP2000 systems where the bus has to be
-				configured a certain way for adjunct CPUs.
 		noearly		[X86] Don't do any early type 1 scanning.
 				This might help on some broken boards which
 				machine check when some devices' config space
@@ -3284,6 +3323,44 @@ bytes respectively. Such letter suffixes
 			Lazy RCU callbacks are those which RCU can
 			prove do nothing more than free memory.
 
+	rcuperf.gp_exp= [KNL]
+			Measure performance of expedited synchronous
+			grace-period primitives.
+
+	rcuperf.holdoff= [KNL]
+			Set test-start holdoff period.  The purpose of
+			this parameter is to delay the start of the
+			test until boot completes in order to avoid
+			interference.
+
+	rcuperf.nreaders= [KNL]
+			Set number of RCU readers.  The value -1 selects
+			N, where N is the number of CPUs.  A value
+			"n" less than -1 selects N-n+1, where N is again
+			the number of CPUs.  For example, -2 selects N
+			(the number of CPUs), -3 selects N+1, and so on.
+			A value of "n" less than or equal to -N selects
+			a single reader.
+
+	rcuperf.nwriters= [KNL]
+			Set number of RCU writers.  The values operate
+			the same as for rcuperf.nreaders.
+			N, where N is the number of CPUs
+
+	rcuperf.perf_runnable= [BOOT]
+			Start rcuperf running at boot time.
+
+	rcuperf.shutdown= [KNL]
+			Shut the system down after performance tests
+			complete.  This is useful for hands-off automated
+			testing.
+
+	rcuperf.perf_type= [KNL]
+			Specify the RCU implementation to test.
+
+	rcuperf.verbose= [KNL]
+			Enable additional printk() statements.
+
 	rcutorture.cbflood_inter_holdoff= [KNL]
 			Set holdoff time (jiffies) between successive
 			callback-flood tests.
@@ -3695,6 +3772,13 @@ bytes respectively. Such letter suffixes
 				1: Fast pin select (default)
 				2: ATC IRMode
 
+	smt		[KNL,S390] Set the maximum number of threads (logical
+			CPUs) to use per physical CPU on systems capable of
+			symmetric multithreading (SMT). Will be capped to the
+			actual hardware limit.
+			Format: <integer>
+			Default: -1 (no limit)
+
 	softlockup_panic=
 			[KNL] Should the soft-lockup detector generate panics.
 			Format: <integer>
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/ko_KR/HOWTO linux-libre-4.7-gnu/Documentation/ko_KR/HOWTO
--- linux-libre-4.6-gnu/Documentation/ko_KR/HOWTO	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/ko_KR/HOWTO	2016-07-24 15:23:50.000000000 -0400
@@ -236,9 +236,9 @@ 디렉토리에서 참조될 수 있다.
   - 새로운 커널이 배포되자마자 2주의 시간이 주어진다. 이 기간동은
     메인테이너들은 큰 diff들을 Linus에게 제출할 수 있다. 대개 이 패치들은
     몇 주 동안 -next 커널내에 이미 있었던 것들이다. 큰 변경들을 제출하는 데
-    선호되는 방법은  git(커널의 소스 관리 툴, 더 많은 정보들은 http://git.or.cz/
-    에서 참조할 수 있다)를 사용하는 것이지만 순수한 패치파일의 형식으로 보내는
-    것도 무관하다.
+    선호되는 방법은  git(커널의 소스 관리 툴, 더 많은 정보들은
+    http://git-scm.com/ 에서 참조할 수 있다)를 사용하는 것이지만 순수한
+    패치파일의 형식으로 보내는 것도 무관하다.
   - 2주 후에 -rc1 커널이 배포되며 지금부터는 전체 커널의 안정성에 영향을
     미칠수 있는 새로운 기능들을 포함하지 않는 패치들만이 추가될 수 있다.
     완전히 새로운 드라이버(혹은 파일시스템)는 -rc1 이후에만 받아들여진다는
@@ -253,8 +253,6 @@ 디렉토리에서 참조될 수 있다.
     것이다.
   - 이러한 프로세스는 커널이 "준비(ready)"되었다고 여겨질때까지 계속된다.
     프로세스는 대체로 6주간 지속된다.
-  - 각 -rc 배포에 있는 알려진 회귀의 목록들은 다음 URI에 남겨진다.
-    http://kernelnewbies.org/known_regressions
 
 커널 배포에 있어서 언급할만한 가치가 있는 리눅스 커널 메일링 리스트의
 Andrew Morton의 글이 있다.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/laptops/toshiba_haps.txt linux-libre-4.7-gnu/Documentation/laptops/toshiba_haps.txt
--- linux-libre-4.6-gnu/Documentation/laptops/toshiba_haps.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/laptops/toshiba_haps.txt	2016-07-24 15:23:50.000000000 -0400
@@ -19,7 +19,7 @@ Author: Azael Avalos <coproscefalo@gmail
 --------------
 
 This driver provides support for the accelerometer found in various Toshiba
-laptops, being called "Toshiba HDD Protection - Shock Sensor" officialy,
+laptops, being called "Toshiba HDD Protection - Shock Sensor" officially,
 and detects laptops automatically with this device.
 On Windows, Toshiba provided software monitors this device and provides
 automatic HDD protection (head unload) on sudden moves or harsh vibrations,
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/leds/leds-class.txt linux-libre-4.7-gnu/Documentation/leds/leds-class.txt
--- linux-libre-4.6-gnu/Documentation/leds/leds-class.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/leds/leds-class.txt	2016-07-24 15:23:50.000000000 -0400
@@ -74,8 +74,8 @@ blink_set() function (see <linux/leds.h>
 however, it is better to use the API function led_blink_set(), as it
 will check and implement software fallback if necessary.
 
-To turn off blinking again, use the API function led_brightness_set()
-as that will not just set the LED brightness but also stop any software
+To turn off blinking, use the API function led_brightness_set()
+with brightness value LED_OFF, which should stop any software
 timers that may have been required for blinking.
 
 The blink_set() function should choose a user friendly blinking value
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/livepatch/livepatch.txt linux-libre-4.7-gnu/Documentation/livepatch/livepatch.txt
--- linux-libre-4.6-gnu/Documentation/livepatch/livepatch.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/livepatch/livepatch.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,394 @@
+=========
+Livepatch
+=========
+
+This document outlines basic information about kernel livepatching.
+
+Table of Contents:
+
+1. Motivation
+2. Kprobes, Ftrace, Livepatching
+3. Consistency model
+4. Livepatch module
+   4.1. New functions
+   4.2. Metadata
+   4.3. Livepatch module handling
+5. Livepatch life-cycle
+   5.1. Registration
+   5.2. Enabling
+   5.3. Disabling
+   5.4. Unregistration
+6. Sysfs
+7. Limitations
+
+
+1. Motivation
+=============
+
+There are many situations where users are reluctant to reboot a system. It may
+be because their system is performing complex scientific computations or under
+heavy load during peak usage. In addition to keeping systems up and running,
+users want to also have a stable and secure system. Livepatching gives users
+both by allowing for function calls to be redirected; thus, fixing critical
+functions without a system reboot.
+
+
+2. Kprobes, Ftrace, Livepatching
+================================
+
+There are multiple mechanisms in the Linux kernel that are directly related
+to redirection of code execution; namely: kernel probes, function tracing,
+and livepatching:
+
+  + The kernel probes are the most generic. The code can be redirected by
+    putting a breakpoint instruction instead of any instruction.
+
+  + The function tracer calls the code from a predefined location that is
+    close to the function entry point. This location is generated by the
+    compiler using the '-pg' gcc option.
+
+  + Livepatching typically needs to redirect the code at the very beginning
+    of the function entry before the function parameters or the stack
+    are in any way modified.
+
+All three approaches need to modify the existing code at runtime. Therefore
+they need to be aware of each other and not step over each other's toes.
+Most of these problems are solved by using the dynamic ftrace framework as
+a base. A Kprobe is registered as a ftrace handler when the function entry
+is probed, see CONFIG_KPROBES_ON_FTRACE. Also an alternative function from
+a live patch is called with the help of a custom ftrace handler. But there are
+some limitations, see below.
+
+
+3. Consistency model
+====================
+
+Functions are there for a reason. They take some input parameters, get or
+release locks, read, process, and even write some data in a defined way,
+have return values. In other words, each function has a defined semantic.
+
+Many fixes do not change the semantic of the modified functions. For
+example, they add a NULL pointer or a boundary check, fix a race by adding
+a missing memory barrier, or add some locking around a critical section.
+Most of these changes are self contained and the function presents itself
+the same way to the rest of the system. In this case, the functions might
+be updated independently one by one.
+
+But there are more complex fixes. For example, a patch might change
+ordering of locking in multiple functions at the same time. Or a patch
+might exchange meaning of some temporary structures and update
+all the relevant functions. In this case, the affected unit
+(thread, whole kernel) need to start using all new versions of
+the functions at the same time. Also the switch must happen only
+when it is safe to do so, e.g. when the affected locks are released
+or no data are stored in the modified structures at the moment.
+
+The theory about how to apply functions a safe way is rather complex.
+The aim is to define a so-called consistency model. It attempts to define
+conditions when the new implementation could be used so that the system
+stays consistent. The theory is not yet finished. See the discussion at
+http://thread.gmane.org/gmane.linux.kernel/1823033/focus=1828189
+
+The current consistency model is very simple. It guarantees that either
+the old or the new function is called. But various functions get redirected
+one by one without any synchronization.
+
+In other words, the current implementation _never_ modifies the behavior
+in the middle of the call. It is because it does _not_ rewrite the entire
+function in the memory. Instead, the function gets redirected at the
+very beginning. But this redirection is used immediately even when
+some other functions from the same patch have not been redirected yet.
+
+See also the section "Limitations" below.
+
+
+4. Livepatch module
+===================
+
+Livepatches are distributed using kernel modules, see
+samples/livepatch/livepatch-sample.c.
+
+The module includes a new implementation of functions that we want
+to replace. In addition, it defines some structures describing the
+relation between the original and the new implementation. Then there
+is code that makes the kernel start using the new code when the livepatch
+module is loaded. Also there is code that cleans up before the
+livepatch module is removed. All this is explained in more details in
+the next sections.
+
+
+4.1. New functions
+------------------
+
+New versions of functions are typically just copied from the original
+sources. A good practice is to add a prefix to the names so that they
+can be distinguished from the original ones, e.g. in a backtrace. Also
+they can be declared as static because they are not called directly
+and do not need the global visibility.
+
+The patch contains only functions that are really modified. But they
+might want to access functions or data from the original source file
+that may only be locally accessible. This can be solved by a special
+relocation section in the generated livepatch module, see
+Documentation/livepatch/module-elf-format.txt for more details.
+
+
+4.2. Metadata
+------------
+
+The patch is described by several structures that split the information
+into three levels:
+
+  + struct klp_func is defined for each patched function. It describes
+    the relation between the original and the new implementation of a
+    particular function.
+
+    The structure includes the name, as a string, of the original function.
+    The function address is found via kallsyms at runtime.
+
+    Then it includes the address of the new function. It is defined
+    directly by assigning the function pointer. Note that the new
+    function is typically defined in the same source file.
+
+    As an optional parameter, the symbol position in the kallsyms database can
+    be used to disambiguate functions of the same name. This is not the
+    absolute position in the database, but rather the order it has been found
+    only for a particular object ( vmlinux or a kernel module ). Note that
+    kallsyms allows for searching symbols according to the object name.
+
+  + struct klp_object defines an array of patched functions (struct
+    klp_func) in the same object. Where the object is either vmlinux
+    (NULL) or a module name.
+
+    The structure helps to group and handle functions for each object
+    together. Note that patched modules might be loaded later than
+    the patch itself and the relevant functions might be patched
+    only when they are available.
+
+
+  + struct klp_patch defines an array of patched objects (struct
+    klp_object).
+
+    This structure handles all patched functions consistently and eventually,
+    synchronously. The whole patch is applied only when all patched
+    symbols are found. The only exception are symbols from objects
+    (kernel modules) that have not been loaded yet. Also if a more complex
+    consistency model is supported then a selected unit (thread,
+    kernel as a whole) will see the new code from the entire patch
+    only when it is in a safe state.
+
+
+4.3. Livepatch module handling
+------------------------------
+
+The usual behavior is that the new functions will get used when
+the livepatch module is loaded. For this, the module init() function
+has to register the patch (struct klp_patch) and enable it. See the
+section "Livepatch life-cycle" below for more details about these
+two operations.
+
+Module removal is only safe when there are no users of the underlying
+functions.  The immediate consistency model is not able to detect this;
+therefore livepatch modules cannot be removed. See "Limitations" below.
+
+5. Livepatch life-cycle
+=======================
+
+Livepatching defines four basic operations that define the life cycle of each
+live patch: registration, enabling, disabling and unregistration.  There are
+several reasons why it is done this way.
+
+First, the patch is applied only when all patched symbols for already
+loaded objects are found. The error handling is much easier if this
+check is done before particular functions get redirected.
+
+Second, the immediate consistency model does not guarantee that anyone is not
+sleeping in the new code after the patch is reverted. This means that the new
+code needs to stay around "forever". If the code is there, one could apply it
+again. Therefore it makes sense to separate the operations that might be done
+once and those that need to be repeated when the patch is enabled (applied)
+again.
+
+Third, it might take some time until the entire system is migrated
+when a more complex consistency model is used. The patch revert might
+block the livepatch module removal for too long. Therefore it is useful
+to revert the patch using a separate operation that might be called
+explicitly. But it does not make sense to remove all information
+until the livepatch module is really removed.
+
+
+5.1. Registration
+-----------------
+
+Each patch first has to be registered using klp_register_patch(). This makes
+the patch known to the livepatch framework. Also it does some preliminary
+computing and checks.
+
+In particular, the patch is added into the list of known patches. The
+addresses of the patched functions are found according to their names.
+The special relocations, mentioned in the section "New functions", are
+applied. The relevant entries are created under
+/sys/kernel/livepatch/<name>. The patch is rejected when any operation
+fails.
+
+
+5.2. Enabling
+-------------
+
+Registered patches might be enabled either by calling klp_enable_patch() or
+by writing '1' to /sys/kernel/livepatch/<name>/enabled. The system will
+start using the new implementation of the patched functions at this stage.
+
+In particular, if an original function is patched for the first time, a
+function specific struct klp_ops is created and an universal ftrace handler
+is registered.
+
+Functions might be patched multiple times. The ftrace handler is registered
+only once for the given function. Further patches just add an entry to the
+list (see field `func_stack`) of the struct klp_ops. The last added
+entry is chosen by the ftrace handler and becomes the active function
+replacement.
+
+Note that the patches might be enabled in a different order than they were
+registered.
+
+
+5.3. Disabling
+--------------
+
+Enabled patches might get disabled either by calling klp_disable_patch() or
+by writing '0' to /sys/kernel/livepatch/<name>/enabled. At this stage
+either the code from the previously enabled patch or even the original
+code gets used.
+
+Here all the functions (struct klp_func) associated with the to-be-disabled
+patch are removed from the corresponding struct klp_ops. The ftrace handler
+is unregistered and the struct klp_ops is freed when the func_stack list
+becomes empty.
+
+Patches must be disabled in exactly the reverse order in which they were
+enabled. It makes the problem and the implementation much easier.
+
+
+5.4. Unregistration
+-------------------
+
+Disabled patches might be unregistered by calling klp_unregister_patch().
+This can be done only when the patch is disabled and the code is no longer
+used. It must be called before the livepatch module gets unloaded.
+
+At this stage, all the relevant sys-fs entries are removed and the patch
+is removed from the list of known patches.
+
+
+6. Sysfs
+========
+
+Information about the registered patches can be found under
+/sys/kernel/livepatch. The patches could be enabled and disabled
+by writing there.
+
+See Documentation/ABI/testing/sysfs-kernel-livepatch for more details.
+
+
+7. Limitations
+==============
+
+The current Livepatch implementation has several limitations:
+
+
+  + The patch must not change the semantic of the patched functions.
+
+    The current implementation guarantees only that either the old
+    or the new function is called. The functions are patched one
+    by one. It means that the patch must _not_ change the semantic
+    of the function.
+
+
+  + Data structures can not be patched.
+
+    There is no support to version data structures or anyhow migrate
+    one structure into another. Also the simple consistency model does
+    not allow to switch more functions atomically.
+
+    Once there is more complex consistency mode, it will be possible to
+    use some workarounds. For example, it will be possible to use a hole
+    for a new member because the data structure is aligned. Or it will
+    be possible to use an existing member for something else.
+
+    There are no plans to add more generic support for modified structures
+    at the moment.
+
+
+  + Only functions that can be traced could be patched.
+
+    Livepatch is based on the dynamic ftrace. In particular, functions
+    implementing ftrace or the livepatch ftrace handler could not be
+    patched. Otherwise, the code would end up in an infinite loop. A
+    potential mistake is prevented by marking the problematic functions
+    by "notrace".
+
+
+  + Anything inlined into __schedule() can not be patched.
+
+    The switch_to macro is inlined into __schedule(). It switches the
+    context between two processes in the middle of the macro. It does
+    not save RIP in x86_64 version (contrary to 32-bit version). Instead,
+    the currently used __schedule()/switch_to() handles both processes.
+
+    Now, let's have two different tasks. One calls the original
+    __schedule(), its registers are stored in a defined order and it
+    goes to sleep in the switch_to macro and some other task is restored
+    using the original __schedule(). Then there is the second task which
+    calls patched__schedule(), it goes to sleep there and the first task
+    is picked by the patched__schedule(). Its RSP is restored and now
+    the registers should be restored as well. But the order is different
+    in the new patched__schedule(), so...
+
+    There is work in progress to remove this limitation.
+
+
+  + Livepatch modules can not be removed.
+
+    The current implementation just redirects the functions at the very
+    beginning. It does not check if the functions are in use. In other
+    words, it knows when the functions get called but it does not
+    know when the functions return. Therefore it can not decide when
+    the livepatch module can be safely removed.
+
+    This will get most likely solved once a more complex consistency model
+    is supported. The idea is that a safe state for patching should also
+    mean a safe state for removing the patch.
+
+    Note that the patch itself might get disabled by writing zero
+    to /sys/kernel/livepatch/<patch>/enabled. It causes that the new
+    code will not longer get called. But it does not guarantee
+    that anyone is not sleeping anywhere in the new code.
+
+
+  + Livepatch works reliably only when the dynamic ftrace is located at
+    the very beginning of the function.
+
+    The function need to be redirected before the stack or the function
+    parameters are modified in any way. For example, livepatch requires
+    using -fentry gcc compiler option on x86_64.
+
+    One exception is the PPC port. It uses relative addressing and TOC.
+    Each function has to handle TOC and save LR before it could call
+    the ftrace handler. This operation has to be reverted on return.
+    Fortunately, the generic ftrace code has the same problem and all
+    this is is handled on the ftrace level.
+
+
+  + Kretprobes using the ftrace framework conflict with the patched
+    functions.
+
+    Both kretprobes and livepatches use a ftrace handler that modifies
+    the return address. The first user wins. Either the probe or the patch
+    is rejected when the handler is already in use by the other.
+
+
+  + Kprobes in the original function are ignored when the code is
+    redirected to the new implementation.
+
+    There is a work in progress to add warnings about this situation.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/livepatch/module-elf-format.txt linux-libre-4.7-gnu/Documentation/livepatch/module-elf-format.txt
--- linux-libre-4.6-gnu/Documentation/livepatch/module-elf-format.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/livepatch/module-elf-format.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,311 @@
+===========================
+Livepatch module Elf format
+===========================
+
+This document outlines the Elf format requirements that livepatch modules must follow.
+
+-----------------
+Table of Contents
+-----------------
+0. Background and motivation
+1. Livepatch modinfo field
+2. Livepatch relocation sections
+   2.1 What are livepatch relocation sections?
+   2.2 Livepatch relocation section format
+       2.2.1 Required flags
+       2.2.2 Required name format
+       2.2.3 Example livepatch relocation section names
+       2.2.4 Example `readelf --sections` output
+       2.2.5 Example `readelf --relocs` output
+3. Livepatch symbols
+   3.1 What are livepatch symbols?
+   3.2 A livepatch module's symbol table
+   3.3 Livepatch symbol format
+       3.3.1 Required flags
+       3.3.2 Required name format
+       3.3.3 Example livepatch symbol names
+       3.3.4 Example `readelf --symbols` output
+4. Symbol table and Elf section access
+
+----------------------------
+0. Background and motivation
+----------------------------
+
+Formerly, livepatch required separate architecture-specific code to write
+relocations. However, arch-specific code to write relocations already
+exists in the module loader, so this former approach produced redundant
+code. So, instead of duplicating code and re-implementing what the module
+loader can already do, livepatch leverages existing code in the module
+loader to perform the all the arch-specific relocation work. Specifically,
+livepatch reuses the apply_relocate_add() function in the module loader to
+write relocations. The patch module Elf format described in this document
+enables livepatch to be able to do this. The hope is that this will make
+livepatch more easily portable to other architectures and reduce the amount
+of arch-specific code required to port livepatch to a particular
+architecture.
+
+Since apply_relocate_add() requires access to a module's section header
+table, symbol table, and relocation section indices, Elf information is
+preserved for livepatch modules (see section 4). Livepatch manages its own
+relocation sections and symbols, which are described in this document. The
+Elf constants used to mark livepatch symbols and relocation sections were
+selected from OS-specific ranges according to the definitions from glibc.
+
+0.1 Why does livepatch need to write its own relocations?
+---------------------------------------------------------
+A typical livepatch module contains patched versions of functions that can
+reference non-exported global symbols and non-included local symbols.
+Relocations referencing these types of symbols cannot be left in as-is
+since the kernel module loader cannot resolve them and will therefore
+reject the livepatch module. Furthermore, we cannot apply relocations that
+affect modules not yet loaded at patch module load time (e.g. a patch to a
+driver that is not loaded). Formerly, livepatch solved this problem by
+embedding special "dynrela" (dynamic rela) sections in the resulting patch
+module Elf output. Using these dynrela sections, livepatch could resolve
+symbols while taking into account its scope and what module the symbol
+belongs to, and then manually apply the dynamic relocations. However this
+approach required livepatch to supply arch-specific code in order to write
+these relocations. In the new format, livepatch manages its own SHT_RELA
+relocation sections in place of dynrela sections, and the symbols that the
+relas reference are special livepatch symbols (see section 2 and 3). The
+arch-specific livepatch relocation code is replaced by a call to
+apply_relocate_add().
+
+================================
+PATCH MODULE FORMAT REQUIREMENTS
+================================
+
+--------------------------
+1. Livepatch modinfo field
+--------------------------
+
+Livepatch modules are required to have the "livepatch" modinfo attribute.
+See the sample livepatch module in samples/livepatch/ for how this is done.
+
+Livepatch modules can be identified by users by using the 'modinfo' command
+and looking for the presence of the "livepatch" field. This field is also
+used by the kernel module loader to identify livepatch modules.
+
+Example modinfo output:
+-----------------------
+% modinfo livepatch-meminfo.ko
+filename:		livepatch-meminfo.ko
+livepatch:		Y
+license:		GPL
+depends:
+vermagic:		4.3.0+ SMP mod_unload
+
+--------------------------------
+2. Livepatch relocation sections
+--------------------------------
+
+-------------------------------------------
+2.1 What are livepatch relocation sections?
+-------------------------------------------
+A livepatch module manages its own Elf relocation sections to apply
+relocations to modules as well as to the kernel (vmlinux) at the
+appropriate time. For example, if a patch module patches a driver that is
+not currently loaded, livepatch will apply the corresponding livepatch
+relocation section(s) to the driver once it loads.
+
+Each "object" (e.g. vmlinux, or a module) within a patch module may have
+multiple livepatch relocation sections associated with it (e.g. patches to
+multiple functions within the same object). There is a 1-1 correspondence
+between a livepatch relocation section and the target section (usually the
+text section of a function) to which the relocation(s) apply. It is
+also possible for a livepatch module to have no livepatch relocation
+sections, as in the case of the sample livepatch module (see
+samples/livepatch).
+
+Since Elf information is preserved for livepatch modules (see Section 4), a
+livepatch relocation section can be applied simply by passing in the
+appropriate section index to apply_relocate_add(), which then uses it to
+access the relocation section and apply the relocations.
+
+Every symbol referenced by a rela in a livepatch relocation section is a
+livepatch symbol. These must be resolved before livepatch can call
+apply_relocate_add(). See Section 3 for more information.
+
+---------------------------------------
+2.2 Livepatch relocation section format
+---------------------------------------
+
+2.2.1 Required flags
+--------------------
+Livepatch relocation sections must be marked with the SHF_RELA_LIVEPATCH
+section flag. See include/uapi/linux/elf.h for the definition. The module
+loader recognizes this flag and will avoid applying those relocation sections
+at patch module load time. These sections must also be marked with SHF_ALLOC,
+so that the module loader doesn't discard them on module load (i.e. they will
+be copied into memory along with the other SHF_ALLOC sections).
+
+2.2.2 Required name format
+--------------------------
+The name of a livepatch relocation section must conform to the following format:
+
+.klp.rela.objname.section_name
+^        ^^     ^ ^          ^
+|________||_____| |__________|
+   [A]      [B]        [C]
+
+[A] The relocation section name is prefixed with the string ".klp.rela."
+[B] The name of the object (i.e. "vmlinux" or name of module) to
+    which the relocation section belongs follows immediately after the prefix.
+[C] The actual name of the section to which this relocation section applies.
+
+2.2.3 Example livepatch relocation section names:
+-------------------------------------------------
+.klp.rela.ext4.text.ext4_attr_store
+.klp.rela.vmlinux.text.cmdline_proc_show
+
+2.2.4 Example `readelf --sections` output for a patch
+module that patches vmlinux and modules 9p, btrfs, ext4:
+--------------------------------------------------------
+  Section Headers:
+  [Nr] Name                          Type                    Address          Off    Size   ES Flg Lk Inf Al
+  [ snip ]
+  [29] .klp.rela.9p.text.caches.show RELA                    0000000000000000 002d58 0000c0 18 AIo 64   9  8
+  [30] .klp.rela.btrfs.text.btrfs.feature.attr.show RELA     0000000000000000 002e18 000060 18 AIo 64  11  8
+  [ snip ]
+  [34] .klp.rela.ext4.text.ext4.attr.store RELA              0000000000000000 002fd8 0000d8 18 AIo 64  13  8
+  [35] .klp.rela.ext4.text.ext4.attr.show RELA               0000000000000000 0030b0 000150 18 AIo 64  15  8
+  [36] .klp.rela.vmlinux.text.cmdline.proc.show RELA         0000000000000000 003200 000018 18 AIo 64  17  8
+  [37] .klp.rela.vmlinux.text.meminfo.proc.show RELA         0000000000000000 003218 0000f0 18 AIo 64  19  8
+  [ snip ]                                       ^                                             ^
+                                                 |                                             |
+                                                [*]                                           [*]
+[*] Livepatch relocation sections are SHT_RELA sections but with a few special
+characteristics. Notice that they are marked SHF_ALLOC ("A") so that they will
+not be discarded when the module is loaded into memory, as well as with the
+SHF_RELA_LIVEPATCH flag ("o" - for OS-specific).
+
+2.2.5 Example `readelf --relocs` output for a patch module:
+-----------------------------------------------------------
+Relocation section '.klp.rela.btrfs.text.btrfs_feature_attr_show' at offset 0x2ba0 contains 4 entries:
+    Offset             Info             Type               Symbol's Value  Symbol's Name + Addend
+000000000000001f  0000005e00000002 R_X86_64_PC32          0000000000000000 .klp.sym.vmlinux.printk,0 - 4
+0000000000000028  0000003d0000000b R_X86_64_32S           0000000000000000 .klp.sym.btrfs.btrfs_ktype,0 + 0
+0000000000000036  0000003b00000002 R_X86_64_PC32          0000000000000000 .klp.sym.btrfs.can_modify_feature.isra.3,0 - 4
+000000000000004c  0000004900000002 R_X86_64_PC32          0000000000000000 .klp.sym.vmlinux.snprintf,0 - 4
+[ snip ]                                                                   ^
+                                                                           |
+                                                                          [*]
+[*] Every symbol referenced by a relocation is a livepatch symbol.
+
+--------------------
+3. Livepatch symbols
+--------------------
+
+-------------------------------
+3.1 What are livepatch symbols?
+-------------------------------
+Livepatch symbols are symbols referred to by livepatch relocation sections.
+These are symbols accessed from new versions of functions for patched
+objects, whose addresses cannot be resolved by the module loader (because
+they are local or unexported global syms). Since the module loader only
+resolves exported syms, and not every symbol referenced by the new patched
+functions is exported, livepatch symbols were introduced. They are used
+also in cases where we cannot immediately know the address of a symbol when
+a patch module loads. For example, this is the case when livepatch patches
+a module that is not loaded yet. In this case, the relevant livepatch
+symbols are resolved simply when the target module loads. In any case, for
+any livepatch relocation section, all livepatch symbols referenced by that
+section must be resolved before livepatch can call apply_relocate_add() for
+that reloc section.
+
+Livepatch symbols must be marked with SHN_LIVEPATCH so that the module
+loader can identify and ignore them. Livepatch modules keep these symbols
+in their symbol tables, and the symbol table is made accessible through
+module->symtab.
+
+-------------------------------------
+3.2 A livepatch module's symbol table
+-------------------------------------
+Normally, a stripped down copy of a module's symbol table (containing only
+"core" symbols) is made available through module->symtab (See layout_symtab()
+in kernel/module.c). For livepatch modules, the symbol table copied into memory
+on module load must be exactly the same as the symbol table produced when the
+patch module was compiled. This is because the relocations in each livepatch
+relocation section refer to their respective symbols with their symbol indices,
+and the original symbol indices (and thus the symtab ordering) must be
+preserved in order for apply_relocate_add() to find the right symbol.
+
+For example, take this particular rela from a livepatch module:
+Relocation section '.klp.rela.btrfs.text.btrfs_feature_attr_show' at offset 0x2ba0 contains 4 entries:
+    Offset             Info             Type               Symbol's Value  Symbol's Name + Addend
+000000000000001f  0000005e00000002 R_X86_64_PC32          0000000000000000 .klp.sym.vmlinux.printk,0 - 4
+
+This rela refers to the symbol '.klp.sym.vmlinux.printk,0', and the symbol index is encoded
+in 'Info'. Here its symbol index is 0x5e, which is 94 in decimal, which refers to the
+symbol index 94.
+And in this patch module's corresponding symbol table, symbol index 94 refers to that very symbol:
+[ snip ]
+94: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT OS [0xff20] .klp.sym.vmlinux.printk,0
+[ snip ]
+
+---------------------------
+3.3 Livepatch symbol format
+---------------------------
+
+3.3.1 Required flags
+--------------------
+Livepatch symbols must have their section index marked as SHN_LIVEPATCH, so
+that the module loader can identify them and not attempt to resolve them.
+See include/uapi/linux/elf.h for the actual definitions.
+
+3.3.2 Required name format
+--------------------------
+Livepatch symbol names must conform to the following format:
+
+.klp.sym.objname.symbol_name,sympos
+^       ^^     ^ ^         ^ ^
+|_______||_____| |_________| |
+   [A]     [B]       [C]    [D]
+
+[A] The symbol name is prefixed with the string ".klp.sym."
+[B] The name of the object (i.e. "vmlinux" or name of module) to
+    which the symbol belongs follows immediately after the prefix.
+[C] The actual name of the symbol.
+[D] The position of the symbol in the object (as according to kallsyms)
+    This is used to differentiate duplicate symbols within the same
+    object. The symbol position is expressed numerically (0, 1, 2...).
+    The symbol position of a unique symbol is 0.
+
+3.3.3 Example livepatch symbol names:
+-------------------------------------
+.klp.sym.vmlinux.snprintf,0
+.klp.sym.vmlinux.printk,0
+.klp.sym.btrfs.btrfs_ktype,0
+
+3.3.4 Example `readelf --symbols` output for a patch module:
+------------------------------------------------------------
+Symbol table '.symtab' contains 127 entries:
+   Num:    Value          Size Type    Bind   Vis     Ndx         Name
+   [ snip ]
+    73: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT OS [0xff20] .klp.sym.vmlinux.snprintf,0
+    74: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT OS [0xff20] .klp.sym.vmlinux.capable,0
+    75: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT OS [0xff20] .klp.sym.vmlinux.find_next_bit,0
+    76: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT OS [0xff20] .klp.sym.vmlinux.si_swapinfo,0
+  [ snip ]                                               ^
+                                                         |
+                                                        [*]
+[*] Note that the 'Ndx' (Section index) for these symbols is SHN_LIVEPATCH (0xff20).
+    "OS" means OS-specific.
+
+--------------------------------------
+4. Symbol table and Elf section access
+--------------------------------------
+A livepatch module's symbol table is accessible through module->symtab.
+
+Since apply_relocate_add() requires access to a module's section headers,
+symbol table, and relocation section indices, Elf information is preserved for
+livepatch modules and is made accessible by the module loader through
+module->klp_info, which is a klp_modinfo struct. When a livepatch module loads,
+this struct is filled in by the module loader. Its fields are documented below:
+
+struct klp_modinfo {
+	Elf_Ehdr hdr; /* Elf header */
+	Elf_Shdr *sechdrs; /* Section header table */
+	char *secstrings; /* String table for the section headers */
+	unsigned int symndx; /* The symbol table section index */
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/locking/lockdep-design.txt linux-libre-4.7-gnu/Documentation/locking/lockdep-design.txt
--- linux-libre-4.6-gnu/Documentation/locking/lockdep-design.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/locking/lockdep-design.txt	2016-07-24 15:23:50.000000000 -0400
@@ -97,7 +97,7 @@ between any two lock-classes:
    <hardirq-safe>   ->  <hardirq-unsafe>
    <softirq-safe>   ->  <softirq-unsafe>
 
-The first rule comes from the fact the a hardirq-safe lock could be
+The first rule comes from the fact that a hardirq-safe lock could be
 taken by a hardirq context, interrupting a hardirq-unsafe lock - and
 thus could result in a lock inversion deadlock. Likewise, a softirq-safe
 lock could be taken by an softirq context, interrupting a softirq-unsafe
@@ -220,7 +220,7 @@ calculated, which hash is unique for eve
 when the chain is validated for the first time, is then put into a hash
 table, which hash-table can be checked in a lockfree manner. If the
 locking chain occurs again later on, the hash table tells us that we
-dont have to validate the chain again.
+don't have to validate the chain again.
 
 Troubleshooting:
 ----------------
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/lzo.txt linux-libre-4.7-gnu/Documentation/lzo.txt
--- linux-libre-4.6-gnu/Documentation/lzo.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/lzo.txt	2016-07-24 15:23:50.000000000 -0400
@@ -69,9 +69,9 @@ Description
 
   IMPORTANT NOTE : in the code some length checks are missing because certain
   instructions are called under the assumption that a certain number of bytes
-  follow because it has already been garanteed before parsing the instructions.
+  follow because it has already been guaranteed before parsing the instructions.
   They just have to "refill" this credit if they consume extra bytes. This is
-  an implementation design choice independant on the algorithm or encoding.
+  an implementation design choice independent on the algorithm or encoding.
 
 Byte sequences
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/Makefile linux-libre-4.7-gnu/Documentation/Makefile
--- linux-libre-4.6-gnu/Documentation/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -1,4 +1,3 @@
-subdir-y := accounting auxdisplay blackfin connector \
+subdir-y := accounting auxdisplay blackfin \
 	filesystems filesystems ia64 laptops mic misc-devices \
-	networking pcmcia prctl ptp timers vDSO video4linux \
-	watchdog
+	networking pcmcia prctl ptp timers vDSO watchdog
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/md-cluster.txt linux-libre-4.7-gnu/Documentation/md-cluster.txt
--- linux-libre-4.6-gnu/Documentation/md-cluster.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/md-cluster.txt	2016-07-24 15:23:50.000000000 -0400
@@ -316,3 +316,9 @@ The algorithm is:
  nodes are using the raid which is achieved by lock all bitmap
  locks within the cluster, and also those locks are unlocked
  accordingly.
+
+7. Unsupported features
+
+There are somethings which are not supported by cluster MD yet.
+
+- update size and change array_sectors.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/memory-barriers.txt linux-libre-4.7-gnu/Documentation/memory-barriers.txt
--- linux-libre-4.6-gnu/Documentation/memory-barriers.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/memory-barriers.txt	2016-07-24 15:23:50.000000000 -0400
@@ -4,8 +4,40 @@
 
 By: David Howells <dhowells@redhat.com>
     Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+    Will Deacon <will.deacon@arm.com>
+    Peter Zijlstra <peterz@infradead.org>
+
+==========
+DISCLAIMER
+==========
+
+This document is not a specification; it is intentionally (for the sake of
+brevity) and unintentionally (due to being human) incomplete. This document is
+meant as a guide to using the various memory barriers provided by Linux, but
+in case of any doubt (and there are many) please ask.
+
+To repeat, this document is not a specification of what Linux expects from
+hardware.
+
+The purpose of this document is twofold:
+
+ (1) to specify the minimum functionality that one can rely on for any
+     particular barrier, and
+
+ (2) to provide a guide as to how to use the barriers that are available.
+
+Note that an architecture can provide more than the minimum requirement
+for any particular barrier, but if the architecure provides less than
+that, that architecture is incorrect.
+
+Note also that it is possible that a barrier may be a no-op for an
+architecture because the way that arch works renders an explicit barrier
+unnecessary in that case.
 
-Contents:
+
+========
+CONTENTS
+========
 
  (*) Abstract memory access model.
 
@@ -31,15 +63,15 @@ Contents:
 
  (*) Implicit kernel memory barriers.
 
-     - Locking functions.
+     - Lock acquisition functions.
      - Interrupt disabling functions.
      - Sleep and wake-up functions.
      - Miscellaneous functions.
 
- (*) Inter-CPU locking barrier effects.
+ (*) Inter-CPU acquiring barrier effects.
 
-     - Locks vs memory accesses.
-     - Locks vs I/O accesses.
+     - Acquires vs memory accesses.
+     - Acquires vs I/O accesses.
 
  (*) Where are memory barriers needed?
 
@@ -61,6 +93,7 @@ Contents:
  (*) The things CPUs get up to.
 
      - And then there's the Alpha.
+     - Virtual Machine Guests.
 
  (*) Example uses.
 
@@ -148,7 +181,7 @@ As a further example, consider this sequ
 
 	CPU 1		CPU 2
 	===============	===============
-	{ A == 1, B == 2, C = 3, P == &A, Q == &C }
+	{ A == 1, B == 2, C == 3, P == &A, Q == &C }
 	B = 4;		Q = P;
 	P = &B		D = *Q;
 
@@ -430,8 +463,9 @@ And a couple of implicit varieties:
      This acts as a one-way permeable barrier.  It guarantees that all memory
      operations after the ACQUIRE operation will appear to happen after the
      ACQUIRE operation with respect to the other components of the system.
-     ACQUIRE operations include LOCK operations and smp_load_acquire()
-     operations.
+     ACQUIRE operations include LOCK operations and both smp_load_acquire()
+     and smp_cond_acquire() operations. The later builds the necessary ACQUIRE
+     semantics from relying on a control dependency and smp_rmb().
 
      Memory operations that occur before an ACQUIRE operation may appear to
      happen after it completes.
@@ -464,6 +498,11 @@ And a couple of implicit varieties:
      This means that ACQUIRE acts as a minimal "acquire" operation and
      RELEASE acts as a minimal "release" operation.
 
+A subset of the atomic operations described in atomic_ops.txt have ACQUIRE
+and RELEASE variants in addition to fully-ordered and relaxed (no barrier
+semantics) definitions.  For compound atomics performing both a load and a
+store, ACQUIRE semantics apply only to the load and RELEASE semantics apply
+only to the store portion of the operation.
 
 Memory barriers are only required where there's a possibility of interaction
 between two CPUs or between a CPU and a device.  If it can be guaranteed that
@@ -517,7 +556,7 @@ following sequence of events:
 
 	CPU 1		      CPU 2
 	===============	      ===============
-	{ A == 1, B == 2, C = 3, P == &A, Q == &C }
+	{ A == 1, B == 2, C == 3, P == &A, Q == &C }
 	B = 4;
 	<write barrier>
 	WRITE_ONCE(P, &B)
@@ -544,7 +583,7 @@ between the address load and the data lo
 
 	CPU 1		      CPU 2
 	===============	      ===============
-	{ A == 1, B == 2, C = 3, P == &A, Q == &C }
+	{ A == 1, B == 2, C == 3, P == &A, Q == &C }
 	B = 4;
 	<write barrier>
 	WRITE_ONCE(P, &B);
@@ -813,9 +852,10 @@ In summary:
       the same variable, then those stores must be ordered, either by
       preceding both of them with smp_mb() or by using smp_store_release()
       to carry out the stores.  Please note that it is -not- sufficient
-      to use barrier() at beginning of each leg of the "if" statement,
-      as optimizing compilers do not necessarily respect barrier()
-      in this case.
+      to use barrier() at beginning of each leg of the "if" statement
+      because, as shown by the example above, optimizing compilers can
+      destroy the control dependency while respecting the letter of the
+      barrier() law.
 
   (*) Control dependencies require at least one run-time conditional
       between the prior load and the subsequent store, and this
@@ -1731,15 +1771,15 @@ The Linux kernel has eight basic CPU mem
 
 
 All memory barriers except the data dependency barriers imply a compiler
-barrier. Data dependencies do not impose any additional compiler ordering.
+barrier.  Data dependencies do not impose any additional compiler ordering.
 
 Aside: In the case of data dependencies, the compiler would be expected
 to issue the loads in the correct order (eg. `a[b]` would have to load
 the value of b before loading a[b]), however there is no guarantee in
 the C specification that the compiler may not speculate the value of b
 (eg. is equal to 1) and load a before b (eg. tmp = a[1]; if (b != 1)
-tmp = a[b]; ). There is also the problem of a compiler reloading b after
-having loaded a[b], thus having a newer copy of b than a[b]. A consensus
+tmp = a[b]; ).  There is also the problem of a compiler reloading b after
+having loaded a[b], thus having a newer copy of b than a[b].  A consensus
 has not yet been reached about these problems, however the READ_ONCE()
 macro is a good place to start looking.
 
@@ -1794,6 +1834,7 @@ There are some more advanced barrier fun
 
 
  (*) lockless_dereference();
+
      This can be thought of as a pointer-fetch wrapper around the
      smp_read_barrier_depends() data-dependency barrier.
 
@@ -1858,7 +1899,7 @@ This is a variation on the mandatory wri
 ordered I/O regions to be partially ordered.  Its effects may go beyond the
 CPU->Hardware interface and actually affect the hardware at some level.
 
-See the subsection "Locks vs I/O accesses" for more information.
+See the subsection "Acquires vs I/O accesses" for more information.
 
 
 ===============================
@@ -1873,8 +1914,8 @@ provide more substantial guarantees, but
 of arch specific code.
 
 
-ACQUIRING FUNCTIONS
--------------------
+LOCK ACQUISITION FUNCTIONS
+--------------------------
 
 The Linux kernel has a number of locking constructs:
 
@@ -1895,7 +1936,7 @@ for each construct.  These operations al
      Memory operations issued before the ACQUIRE may be completed after
      the ACQUIRE operation has completed.  An smp_mb__before_spinlock(),
      combined with a following ACQUIRE, orders prior stores against
-     subsequent loads and stores. Note that this is weaker than smp_mb()!
+     subsequent loads and stores.  Note that this is weaker than smp_mb()!
      The smp_mb__before_spinlock() primitive is free on many architectures.
 
  (2) RELEASE operation implication:
@@ -2090,9 +2131,9 @@ or:
 	event_indicated = 1;
 	wake_up_process(event_daemon);
 
-A write memory barrier is implied by wake_up() and co. if and only if they wake
-something up.  The barrier occurs before the task state is cleared, and so sits
-between the STORE to indicate the event and the STORE to set TASK_RUNNING:
+A write memory barrier is implied by wake_up() and co.  if and only if they
+wake something up.  The barrier occurs before the task state is cleared, and so
+sits between the STORE to indicate the event and the STORE to set TASK_RUNNING:
 
 	CPU 1				CPU 2
 	===============================	===============================
@@ -2206,7 +2247,7 @@ three CPUs; then should the following se
 
 Then there is no guarantee as to what order CPU 3 will see the accesses to *A
 through *H occur in, other than the constraints imposed by the separate locks
-on the separate CPUs. It might, for example, see:
+on the separate CPUs.  It might, for example, see:
 
 	*E, ACQUIRE M, ACQUIRE Q, *G, *C, *F, *A, *B, RELEASE Q, *D, *H, RELEASE M
 
@@ -2486,9 +2527,9 @@ The following operations are special loc
 	clear_bit_unlock();
 	__clear_bit_unlock();
 
-These implement ACQUIRE-class and RELEASE-class operations. These should be used in
-preference to other operations when implementing locking primitives, because
-their implementations can be optimised on many architectures.
+These implement ACQUIRE-class and RELEASE-class operations.  These should be
+used in preference to other operations when implementing locking primitives,
+because their implementations can be optimised on many architectures.
 
 [!] Note that special memory barrier primitives are available for these
 situations because on some CPUs the atomic instructions used imply full memory
@@ -2568,12 +2609,12 @@ explicit barriers are used.
 
 Normally this won't be a problem because the I/O accesses done inside such
 sections will include synchronous load operations on strictly ordered I/O
-registers that form implicit I/O barriers. If this isn't sufficient then an
+registers that form implicit I/O barriers.  If this isn't sufficient then an
 mmiowb() may need to be used explicitly.
 
 
 A similar situation may occur between an interrupt routine and two routines
-running on separate CPUs that communicate with each other. If such a case is
+running on separate CPUs that communicate with each other.  If such a case is
 likely, then interrupt-disabling locks should be used to guarantee ordering.
 
 
@@ -2587,8 +2628,8 @@ functions:
  (*) inX(), outX():
 
      These are intended to talk to I/O space rather than memory space, but
-     that's primarily a CPU-specific concept. The i386 and x86_64 processors do
-     indeed have special I/O space access cycles and instructions, but many
+     that's primarily a CPU-specific concept.  The i386 and x86_64 processors
+     do indeed have special I/O space access cycles and instructions, but many
      CPUs don't have such a concept.
 
      The PCI bus, amongst others, defines an I/O space concept which - on such
@@ -2610,7 +2651,7 @@ functions:
 
      Whether these are guaranteed to be fully ordered and uncombined with
      respect to each other on the issuing CPU depends on the characteristics
-     defined for the memory window through which they're accessing. On later
+     defined for the memory window through which they're accessing.  On later
      i386 architecture machines, for example, this is controlled by way of the
      MTRR registers.
 
@@ -2635,10 +2676,10 @@ functions:
  (*) readX_relaxed(), writeX_relaxed()
 
      These are similar to readX() and writeX(), but provide weaker memory
-     ordering guarantees. Specifically, they do not guarantee ordering with
+     ordering guarantees.  Specifically, they do not guarantee ordering with
      respect to normal memory accesses (e.g. DMA buffers) nor do they guarantee
-     ordering with respect to LOCK or UNLOCK operations. If the latter is
-     required, an mmiowb() barrier can be used. Note that relaxed accesses to
+     ordering with respect to LOCK or UNLOCK operations.  If the latter is
+     required, an mmiowb() barrier can be used.  Note that relaxed accesses to
      the same peripheral are guaranteed to be ordered with respect to each
      other.
 
@@ -3040,8 +3081,9 @@ The Alpha defines the Linux kernel's mem
 
 See the subsection on "Cache Coherency" above.
 
+
 VIRTUAL MACHINE GUESTS
--------------------
+----------------------
 
 Guests running within virtual machines might be affected by SMP effects even if
 the guest itself is compiled without SMP support.  This is an artifact of
@@ -3050,7 +3092,7 @@ barriers for this use-case would be poss
 
 To handle this case optimally, low-level virt_mb() etc macros are available.
 These have the same effect as smp_mb() etc when SMP is enabled, but generate
-identical code for SMP and non-SMP systems. For example, virtual machine guests
+identical code for SMP and non-SMP systems.  For example, virtual machine guests
 should use virt_mb() rather than smp_mb() when synchronizing against a
 (possibly SMP) host.
 
@@ -3058,6 +3100,7 @@ These are equivalent to smp_mb() etc cou
 in particular, they do not control MMIO effects: to control
 MMIO effects, use mandatory barriers.
 
+
 ============
 EXAMPLE USES
 ============
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/memory-hotplug.txt linux-libre-4.7-gnu/Documentation/memory-hotplug.txt
--- linux-libre-4.6-gnu/Documentation/memory-hotplug.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/memory-hotplug.txt	2016-07-24 15:23:50.000000000 -0400
@@ -261,10 +261,11 @@ it according to the policy which can be
 
 % cat /sys/devices/system/memory/auto_online_blocks
 
-The default is "offline" which means the newly added memory is not in a
-ready-to-use state and you have to "online" the newly added memory blocks
-manually. Automatic onlining can be requested by writing "online" to
-"auto_online_blocks" file:
+The default depends on the CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE kernel config
+option. If it is disabled the default is "offline" which means the newly added
+memory is not in a ready-to-use state and you have to "online" the newly added
+memory blocks manually. Automatic onlining can be requested by writing "online"
+to "auto_online_blocks" file:
 
 % echo online > /sys/devices/system/memory/auto_online_blocks
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/mmc/00-INDEX linux-libre-4.7-gnu/Documentation/mmc/00-INDEX
--- linux-libre-4.6-gnu/Documentation/mmc/00-INDEX	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/mmc/00-INDEX	2016-07-24 15:23:50.000000000 -0400
@@ -6,3 +6,5 @@ mmc-dev-parts.txt
         - info on SD and MMC device partitions
 mmc-async-req.txt
         - info on mmc asynchronous requests
+mmc-tools.txt
+	- info on mmc-utils tools
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/mmc/mmc-tools.txt linux-libre-4.7-gnu/Documentation/mmc/mmc-tools.txt
--- linux-libre-4.6-gnu/Documentation/mmc/mmc-tools.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/mmc/mmc-tools.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,34 @@
+MMC tools introduction
+======================
+
+There is one MMC test tools called mmc-utils, which is maintained by Chris Ball,
+you can find it at the below public git repository:
+http://git.kernel.org/cgit/linux/kernel/git/cjb/mmc-utils.git/
+
+Functions
+=========
+
+The mmc-utils tools can do the following:
+ - Print and parse extcsd data.
+ - Determine the eMMC writeprotect status.
+ - Set the eMMC writeprotect status.
+ - Set the eMMC data sector size to 4KB by disabling emulation.
+ - Create general purpose partition.
+ - Enable the enhanced user area.
+ - Enable write reliability per partition.
+ - Print the response to STATUS_SEND (CMD13).
+ - Enable the boot partition.
+ - Set Boot Bus Conditions.
+ - Enable the eMMC BKOPS feature.
+ - Permanently enable the eMMC H/W Reset feature.
+ - Permanently disable the eMMC H/W Reset feature.
+ - Send Sanitize command.
+ - Program authentication key for the device.
+ - Counter value for the rpmb device will be read to stdout.
+ - Read from rpmb device to output.
+ - Write to rpmb device from data file.
+ - Enable the eMMC cache feature.
+ - Disable the eMMC cache feature.
+ - Print and parse CID data.
+ - Print and parse CSD data.
+ - Print and parse SCR data.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/networking/bonding.txt linux-libre-4.7-gnu/Documentation/networking/bonding.txt
--- linux-libre-4.6-gnu/Documentation/networking/bonding.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/networking/bonding.txt	2016-07-24 15:23:50.000000000 -0400
@@ -1880,8 +1880,8 @@ or more peers on the local network.
 
 	The ARP monitor relies on the device driver itself to verify
 that traffic is flowing.  In particular, the driver must keep up to
-date the last receive time, dev->last_rx, and transmit start time,
-dev->trans_start.  If these are not updated by the driver, then the
+date the last receive time, dev->last_rx.  Drivers that use NETIF_F_LLTX
+flag must also update netdev_queue->trans_start.  If they do not, then the
 ARP monitor will immediately fail any slaves using that driver, and
 those slaves will stay down.  If networking monitoring (tcpdump, etc)
 shows the ARP requests and replies on the network, then it may be that
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/networking/can.txt linux-libre-4.7-gnu/Documentation/networking/can.txt
--- linux-libre-4.6-gnu/Documentation/networking/can.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/networking/can.txt	2016-07-24 15:23:50.000000000 -0400
@@ -1256,7 +1256,7 @@ solution for a couple of reasons:
 7. SocketCAN resources
 -----------------------
 
-  The Linux CAN / SocketCAN project ressources (project site / mailing list)
+  The Linux CAN / SocketCAN project resources (project site / mailing list)
   are referenced in the MAINTAINERS file in the Linux source tree.
   Search for CAN NETWORK [LAYERS|DRIVERS].
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/networking/dsa/bcm_sf2.txt linux-libre-4.7-gnu/Documentation/networking/dsa/bcm_sf2.txt
--- linux-libre-4.6-gnu/Documentation/networking/dsa/bcm_sf2.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/networking/dsa/bcm_sf2.txt	2016-07-24 15:23:50.000000000 -0400
@@ -38,7 +38,7 @@ Implementation details
 ======================
 
 The driver is located in drivers/net/dsa/bcm_sf2.c and is implemented as a DSA
-driver; see Documentation/networking/dsa/dsa.txt for details on the subsytem
+driver; see Documentation/networking/dsa/dsa.txt for details on the subsystem
 and what it provides.
 
 The SF2 switch is configured to enable a Broadcom specific 4-bytes switch tag
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/networking/dsa/dsa.txt linux-libre-4.7-gnu/Documentation/networking/dsa/dsa.txt
--- linux-libre-4.6-gnu/Documentation/networking/dsa/dsa.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/networking/dsa/dsa.txt	2016-07-24 15:23:50.000000000 -0400
@@ -334,7 +334,7 @@ more specifically with its VLAN filterin
 of per-port slave network devices. Since DSA primarily deals with
 MDIO-connected switches, although not exclusively, SWITCHDEV's
 prepare/abort/commit phases are often simplified into a prepare phase which
-checks whether the operation is supporte by the DSA switch driver, and a commit
+checks whether the operation is supported by the DSA switch driver, and a commit
 phase which applies the changes.
 
 As of today, the only SWITCHDEV objects supported by DSA are the FDB and VLAN
@@ -369,8 +369,6 @@ does not allocate any driver private con
 Switch configuration
 --------------------
 
-- priv_size: additional size needed by the switch driver for its private context
-
 - tag_protocol: this is to indicate what kind of tagging protocol is supported,
   should be a valid value from the dsa_tag_protocol enum
 
@@ -416,11 +414,6 @@ PHY devices and link management
   to the switch port MDIO registers. If unavailable return a negative error
   code.
 
-- poll_link: Function invoked by DSA to query the link state of the switch
-  builtin Ethernet PHYs, per port. This function is responsible for calling
-  netif_carrier_{on,off} when appropriate, and can be used to poll all ports in a
-  single call. Executes from workqueue context.
-
 - adjust_link: Function invoked by the PHY library when a slave network device
   is attached to a PHY device. This function is responsible for appropriately
   configuring the switch port link parameters: speed, duplex, pause based on
@@ -533,7 +526,7 @@ Bridge layer
   out at the switch hardware for the switch to (re) learn MAC addresses behind
   this port.
 
-- port_stp_update: bridge layer function invoked when a given switch port STP
+- port_stp_state_set: bridge layer function invoked when a given switch port STP
   state is computed by the bridge layer and should be propagated to switch
   hardware to forward/block/learn traffic. The switch driver is responsible for
   computing a STP state change based on current and asked parameters and perform
@@ -542,6 +535,22 @@ Bridge layer
 Bridge VLAN filtering
 ---------------------
 
+- port_vlan_filtering: bridge layer function invoked when the bridge gets
+  configured for turning on or off VLAN filtering. If nothing specific needs to
+  be done at the hardware level, this callback does not need to be implemented.
+  When VLAN filtering is turned on, the hardware must be programmed with
+  rejecting 802.1Q frames which have VLAN IDs outside of the programmed allowed
+  VLAN ID map/rules.  If there is no PVID programmed into the switch port,
+  untagged frames must be rejected as well. When turned off the switch must
+  accept any 802.1Q frames irrespective of their VLAN ID, and untagged frames are
+  allowed.
+
+- port_vlan_prepare: bridge layer function invoked when the bridge prepares the
+  configuration of a VLAN on the given port. If the operation is not supported
+  by the hardware, this function should return -EOPNOTSUPP to inform the bridge
+  code to fallback to a software implementation. No hardware setup must be done
+  in this function. See port_vlan_add for this and details.
+
 - port_vlan_add: bridge layer function invoked when a VLAN is configured
   (tagged or untagged) for the given switch port
 
@@ -552,6 +561,12 @@ Bridge VLAN filtering
   function that the driver has to call for each VLAN the given port is a member
   of. A switchdev object is used to carry the VID and bridge flags.
 
+- port_fdb_prepare: bridge layer function invoked when the bridge prepares the
+  installation of a Forwarding Database entry. If the operation is not
+  supported, this function should return -EOPNOTSUPP to inform the bridge code
+  to fallback to a software implementation. No hardware setup must be done in
+  this function. See port_fdb_add for this and details.
+
 - port_fdb_add: bridge layer function invoked when the bridge wants to install a
   Forwarding Database entry, the switch hardware should be programmed with the
   specified address in the specified VLAN Id in the forwarding database
@@ -565,6 +580,10 @@ of DSA, would be the its port-based VLAN
   the specified MAC address from the specified VLAN ID if it was mapped into
   this port forwarding database
 
+- port_fdb_dump: bridge layer function invoked with a switchdev callback
+  function that the driver has to call for each MAC address known to be behind
+  the given port. A switchdev object is used to carry the VID and FDB info.
+
 TODO
 ====
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/networking/filter.txt linux-libre-4.7-gnu/Documentation/networking/filter.txt
--- linux-libre-4.6-gnu/Documentation/networking/filter.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/networking/filter.txt	2016-07-24 15:23:50.000000000 -0400
@@ -216,21 +216,21 @@ opcodes as defined in linux/filter.h sta
 
   jmp              6                    Jump to label
   ja               6                    Jump to label
-  jeq              7, 8                 Jump on k == A
-  jneq             8                    Jump on k != A
-  jne              8                    Jump on k != A
-  jlt              8                    Jump on k < A
-  jle              8                    Jump on k <= A
-  jgt              7, 8                 Jump on k > A
-  jge              7, 8                 Jump on k >= A
-  jset             7, 8                 Jump on k & A
+  jeq              7, 8                 Jump on A == k
+  jneq             8                    Jump on A != k
+  jne              8                    Jump on A != k
+  jlt              8                    Jump on A <  k
+  jle              8                    Jump on A <= k
+  jgt              7, 8                 Jump on A >  k
+  jge              7, 8                 Jump on A >= k
+  jset             7, 8                 Jump on A &  k
 
   add              0, 4                 A + <x>
   sub              0, 4                 A - <x>
   mul              0, 4                 A * <x>
   div              0, 4                 A / <x>
   mod              0, 4                 A % <x>
-  neg              0, 4                 !A
+  neg                                   !A
   and              0, 4                 A & <x>
   or               0, 4                 A | <x>
   xor              0, 4                 A ^ <x>
@@ -1095,6 +1095,87 @@ all use cases.
 
 See details of eBPF verifier in kernel/bpf/verifier.c
 
+Direct packet access
+--------------------
+In cls_bpf and act_bpf programs the verifier allows direct access to the packet
+data via skb->data and skb->data_end pointers.
+Ex:
+1:  r4 = *(u32 *)(r1 +80)  /* load skb->data_end */
+2:  r3 = *(u32 *)(r1 +76)  /* load skb->data */
+3:  r5 = r3
+4:  r5 += 14
+5:  if r5 > r4 goto pc+16
+R1=ctx R3=pkt(id=0,off=0,r=14) R4=pkt_end R5=pkt(id=0,off=14,r=14) R10=fp
+6:  r0 = *(u16 *)(r3 +12) /* access 12 and 13 bytes of the packet */
+
+this 2byte load from the packet is safe to do, since the program author
+did check 'if (skb->data + 14 > skb->data_end) goto err' at insn #5 which
+means that in the fall-through case the register R3 (which points to skb->data)
+has at least 14 directly accessible bytes. The verifier marks it
+as R3=pkt(id=0,off=0,r=14).
+id=0 means that no additional variables were added to the register.
+off=0 means that no additional constants were added.
+r=14 is the range of safe access which means that bytes [R3, R3 + 14) are ok.
+Note that R5 is marked as R5=pkt(id=0,off=14,r=14). It also points
+to the packet data, but constant 14 was added to the register, so
+it now points to 'skb->data + 14' and accessible range is [R5, R5 + 14 - 14)
+which is zero bytes.
+
+More complex packet access may look like:
+ R0=imm1 R1=ctx R3=pkt(id=0,off=0,r=14) R4=pkt_end R5=pkt(id=0,off=14,r=14) R10=fp
+ 6:  r0 = *(u8 *)(r3 +7) /* load 7th byte from the packet */
+ 7:  r4 = *(u8 *)(r3 +12)
+ 8:  r4 *= 14
+ 9:  r3 = *(u32 *)(r1 +76) /* load skb->data */
+10:  r3 += r4
+11:  r2 = r1
+12:  r2 <<= 48
+13:  r2 >>= 48
+14:  r3 += r2
+15:  r2 = r3
+16:  r2 += 8
+17:  r1 = *(u32 *)(r1 +80) /* load skb->data_end */
+18:  if r2 > r1 goto pc+2
+ R0=inv56 R1=pkt_end R2=pkt(id=2,off=8,r=8) R3=pkt(id=2,off=0,r=8) R4=inv52 R5=pkt(id=0,off=14,r=14) R10=fp
+19:  r1 = *(u8 *)(r3 +4)
+The state of the register R3 is R3=pkt(id=2,off=0,r=8)
+id=2 means that two 'r3 += rX' instructions were seen, so r3 points to some
+offset within a packet and since the program author did
+'if (r3 + 8 > r1) goto err' at insn #18, the safe range is [R3, R3 + 8).
+The verifier only allows 'add' operation on packet registers. Any other
+operation will set the register state to 'unknown_value' and it won't be
+available for direct packet access.
+Operation 'r3 += rX' may overflow and become less than original skb->data,
+therefore the verifier has to prevent that. So it tracks the number of
+upper zero bits in all 'uknown_value' registers, so when it sees
+'r3 += rX' instruction and rX is more than 16-bit value, it will error as:
+"cannot add integer value with N upper zero bits to ptr_to_packet"
+Ex. after insn 'r4 = *(u8 *)(r3 +12)' (insn #7 above) the state of r4 is
+R4=inv56 which means that upper 56 bits on the register are guaranteed
+to be zero. After insn 'r4 *= 14' the state becomes R4=inv52, since
+multiplying 8-bit value by constant 14 will keep upper 52 bits as zero.
+Similarly 'r2 >>= 48' will make R2=inv48, since the shift is not sign
+extending. This logic is implemented in evaluate_reg_alu() function.
+
+The end result is that bpf program author can access packet directly
+using normal C code as:
+  void *data = (void *)(long)skb->data;
+  void *data_end = (void *)(long)skb->data_end;
+  struct eth_hdr *eth = data;
+  struct iphdr *iph = data + sizeof(*eth);
+  struct udphdr *udp = data + sizeof(*eth) + sizeof(*iph);
+
+  if (data + sizeof(*eth) + sizeof(*iph) + sizeof(*udp) > data_end)
+          return 0;
+  if (eth->h_proto != htons(ETH_P_IP))
+          return 0;
+  if (iph->protocol != IPPROTO_UDP || iph->ihl != 5)
+          return 0;
+  if (udp->dest == 53 || udp->source == 9)
+          ...;
+which makes such programs easier to write comparing to LD_ABS insn
+and significantly faster.
+
 eBPF maps
 ---------
 'maps' is a generic storage of different types for sharing data between kernel
@@ -1293,5 +1374,5 @@ to give potential BPF hackers or securit
 the underlying architecture.
 
 Jay Schulist <jschlst@samba.org>
-Daniel Borkmann <dborkman@redhat.com>
-Alexei Starovoitov <ast@plumgrid.com>
+Daniel Borkmann <daniel@iogearbox.net>
+Alexei Starovoitov <ast@kernel.org>
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/networking/gen_stats.txt linux-libre-4.7-gnu/Documentation/networking/gen_stats.txt
--- linux-libre-4.6-gnu/Documentation/networking/gen_stats.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/networking/gen_stats.txt	2016-07-24 15:23:50.000000000 -0400
@@ -33,7 +33,8 @@ my_dumping_routine(struct sk_buff *skb,
 {
 	struct gnet_dump dump;
 
-	if (gnet_stats_start_copy(skb, TCA_STATS2, &mystruct->lock, &dump) < 0)
+	if (gnet_stats_start_copy(skb, TCA_STATS2, &mystruct->lock, &dump,
+				  TCA_PAD) < 0)
 		goto rtattr_failure;
 
 	if (gnet_stats_copy_basic(&dump, &mystruct->bstats) < 0 ||
@@ -56,7 +57,8 @@ existing TLV types.
 my_dumping_routine(struct sk_buff *skb, ...)
 {
     if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS,
-		TCA_XSTATS, &mystruct->lock, &dump) < 0)
+				     TCA_XSTATS, &mystruct->lock, &dump,
+				     TCA_PAD) < 0)
 		goto rtattr_failure;
 	...
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/networking/ip-sysctl.txt linux-libre-4.7-gnu/Documentation/networking/ip-sysctl.txt
--- linux-libre-4.6-gnu/Documentation/networking/ip-sysctl.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/networking/ip-sysctl.txt	2016-07-24 15:23:50.000000000 -0400
@@ -63,6 +63,16 @@ fwmark_reflect - BOOLEAN
 	fwmark of the packet they are replying to.
 	Default: 0
 
+fib_multipath_use_neigh - BOOLEAN
+	Use status of existing neighbor entry when determining nexthop for
+	multipath routes. If disabled, neighbor information is not used and
+	packets could be directed to a failed nexthop. Only valid for kernels
+	built with CONFIG_IP_ROUTE_MULTIPATH enabled.
+	Default: 0 (disabled)
+	Possible values:
+	0 - disabled
+	1 - enabled
+
 route/max_size - INTEGER
 	Maximum number of routes allowed in the kernel.  Increase
 	this when using large numbers of interfaces and/or routes.
@@ -1026,15 +1036,17 @@ proxy_arp_pvlan - BOOLEAN
 
 shared_media - BOOLEAN
 	Send(router) or accept(host) RFC1620 shared media redirects.
-	Overrides ip_secure_redirects.
+	Overrides secure_redirects.
 	shared_media for the interface will be enabled if at least one of
 	conf/{all,interface}/shared_media is set to TRUE,
 	it will be disabled otherwise
 	default TRUE
 
 secure_redirects - BOOLEAN
-	Accept ICMP redirect messages only for gateways,
-	listed in default gateway list.
+	Accept ICMP redirect messages only to gateways listed in the
+	interface's current gateway list. Even if disabled, RFC1122 redirect
+	rules still apply.
+	Overridden by shared_media.
 	secure_redirects for the interface will be enabled if at least one of
 	conf/{all,interface}/secure_redirects is set to TRUE,
 	it will be disabled otherwise
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/networking/mac80211-injection.txt linux-libre-4.7-gnu/Documentation/networking/mac80211-injection.txt
--- linux-libre-4.6-gnu/Documentation/networking/mac80211-injection.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/networking/mac80211-injection.txt	2016-07-24 15:23:50.000000000 -0400
@@ -37,14 +37,27 @@ radiotap headers and used to control inj
    HT rate for the transmission (only for devices without own rate control).
    Also some flags are parsed
 
-   IEEE80211_TX_RC_SHORT_GI: use short guard interval
-   IEEE80211_TX_RC_40_MHZ_WIDTH: send in HT40 mode
+   IEEE80211_RADIOTAP_MCS_SGI: use short guard interval
+   IEEE80211_RADIOTAP_MCS_BW_40: send in HT40 mode
 
  * IEEE80211_RADIOTAP_DATA_RETRIES
 
    number of retries when either IEEE80211_RADIOTAP_RATE or
    IEEE80211_RADIOTAP_MCS was used
 
+ * IEEE80211_RADIOTAP_VHT
+
+   VHT mcs and number of streams used in the transmission (only for devices
+   without own rate control). Also other fields are parsed
+
+   flags field
+   IEEE80211_RADIOTAP_VHT_FLAG_SGI: use short guard interval
+
+   bandwidth field
+   1: send using 40MHz channel width
+   4: send using 80MHz channel width
+   11: send using 160MHz channel width
+
 The injection code can also skip all other currently defined radiotap fields
 facilitating replay of captured radiotap headers directly.
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/networking/netdev-features.txt linux-libre-4.7-gnu/Documentation/networking/netdev-features.txt
--- linux-libre-4.6-gnu/Documentation/networking/netdev-features.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/networking/netdev-features.txt	2016-07-24 15:23:50.000000000 -0400
@@ -131,13 +131,11 @@ stack. Driver should not change behaviou
 
  * LLTX driver (deprecated for hardware drivers)
 
-NETIF_F_LLTX should be set in drivers that implement their own locking in
-transmit path or don't need locking at all (e.g. software tunnels).
-In ndo_start_xmit, it is recommended to use a try_lock and return
-NETDEV_TX_LOCKED when the spin lock fails.  The locking should also properly
-protect against other callbacks (the rules you need to find out).
+NETIF_F_LLTX is meant to be used by drivers that don't need locking at all,
+e.g. software tunnels.
 
-Don't use it for new drivers.
+This is also used in a few legacy drivers that implement their
+own locking, don't use it for new (hardware) drivers.
 
  * netns-local device
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/networking/netdevices.txt linux-libre-4.7-gnu/Documentation/networking/netdevices.txt
--- linux-libre-4.6-gnu/Documentation/networking/netdevices.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/networking/netdevices.txt	2016-07-24 15:23:50.000000000 -0400
@@ -69,10 +69,9 @@ ndo_start_xmit:
 
 	When the driver sets NETIF_F_LLTX in dev->features this will be
 	called without holding netif_tx_lock. In this case the driver
-	has to lock by itself when needed. It is recommended to use a try lock
-	for this and return NETDEV_TX_LOCKED when the spin lock fails.
-	The locking there should also properly protect against 
-	set_rx_mode. Note that the use of NETIF_F_LLTX is deprecated.
+	has to lock by itself when needed.
+	The locking there should also properly protect against
+	set_rx_mode. WARNING: use of NETIF_F_LLTX is deprecated.
 	Don't use it for new drivers.
 
 	Context: Process with BHs disabled or BH (timer),
@@ -83,8 +82,6 @@ ndo_start_xmit:
 	o NETDEV_TX_BUSY Cannot transmit packet, try later 
 	  Usually a bug, means queue start/stop flow control is broken in
 	  the driver. Note: the driver must NOT put the skb in its DMA ring.
-	o NETDEV_TX_LOCKED Locking failed, please retry quickly.
-	  Only valid when NETIF_F_LLTX is set.
 
 ndo_tx_timeout:
 	Synchronization: netif_tx_lock spinlock; all TX queues frozen.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/networking/segmentation-offloads.txt linux-libre-4.7-gnu/Documentation/networking/segmentation-offloads.txt
--- linux-libre-4.6-gnu/Documentation/networking/segmentation-offloads.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/networking/segmentation-offloads.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,130 @@
+Segmentation Offloads in the Linux Networking Stack
+
+Introduction
+============
+
+This document describes a set of techniques in the Linux networking stack
+to take advantage of segmentation offload capabilities of various NICs.
+
+The following technologies are described:
+ * TCP Segmentation Offload - TSO
+ * UDP Fragmentation Offload - UFO
+ * IPIP, SIT, GRE, and UDP Tunnel Offloads
+ * Generic Segmentation Offload - GSO
+ * Generic Receive Offload - GRO
+ * Partial Generic Segmentation Offload - GSO_PARTIAL
+
+TCP Segmentation Offload
+========================
+
+TCP segmentation allows a device to segment a single frame into multiple
+frames with a data payload size specified in skb_shinfo()->gso_size.
+When TCP segmentation requested the bit for either SKB_GSO_TCP or
+SKB_GSO_TCP6 should be set in skb_shinfo()->gso_type and
+skb_shinfo()->gso_size should be set to a non-zero value.
+
+TCP segmentation is dependent on support for the use of partial checksum
+offload.  For this reason TSO is normally disabled if the Tx checksum
+offload for a given device is disabled.
+
+In order to support TCP segmentation offload it is necessary to populate
+the network and transport header offsets of the skbuff so that the device
+drivers will be able determine the offsets of the IP or IPv6 header and the
+TCP header.  In addition as CHECKSUM_PARTIAL is required csum_start should
+also point to the TCP header of the packet.
+
+For IPv4 segmentation we support one of two types in terms of the IP ID.
+The default behavior is to increment the IP ID with every segment.  If the
+GSO type SKB_GSO_TCP_FIXEDID is specified then we will not increment the IP
+ID and all segments will use the same IP ID.  If a device has
+NETIF_F_TSO_MANGLEID set then the IP ID can be ignored when performing TSO
+and we will either increment the IP ID for all frames, or leave it at a
+static value based on driver preference.
+
+UDP Fragmentation Offload
+=========================
+
+UDP fragmentation offload allows a device to fragment an oversized UDP
+datagram into multiple IPv4 fragments.  Many of the requirements for UDP
+fragmentation offload are the same as TSO.  However the IPv4 ID for
+fragments should not increment as a single IPv4 datagram is fragmented.
+
+IPIP, SIT, GRE, UDP Tunnel, and Remote Checksum Offloads
+========================================================
+
+In addition to the offloads described above it is possible for a frame to
+contain additional headers such as an outer tunnel.  In order to account
+for such instances an additional set of segmentation offload types were
+introduced including SKB_GSO_IPIP, SKB_GSO_SIT, SKB_GSO_GRE, and
+SKB_GSO_UDP_TUNNEL.  These extra segmentation types are used to identify
+cases where there are more than just 1 set of headers.  For example in the
+case of IPIP and SIT we should have the network and transport headers moved
+from the standard list of headers to "inner" header offsets.
+
+Currently only two levels of headers are supported.  The convention is to
+refer to the tunnel headers as the outer headers, while the encapsulated
+data is normally referred to as the inner headers.  Below is the list of
+calls to access the given headers:
+
+IPIP/SIT Tunnel:
+		Outer			Inner
+MAC		skb_mac_header
+Network		skb_network_header	skb_inner_network_header
+Transport	skb_transport_header
+
+UDP/GRE Tunnel:
+		Outer			Inner
+MAC		skb_mac_header		skb_inner_mac_header
+Network		skb_network_header	skb_inner_network_header
+Transport	skb_transport_header	skb_inner_transport_header
+
+In addition to the above tunnel types there are also SKB_GSO_GRE_CSUM and
+SKB_GSO_UDP_TUNNEL_CSUM.  These two additional tunnel types reflect the
+fact that the outer header also requests to have a non-zero checksum
+included in the outer header.
+
+Finally there is SKB_GSO_REMCSUM which indicates that a given tunnel header
+has requested a remote checksum offload.  In this case the inner headers
+will be left with a partial checksum and only the outer header checksum
+will be computed.
+
+Generic Segmentation Offload
+============================
+
+Generic segmentation offload is a pure software offload that is meant to
+deal with cases where device drivers cannot perform the offloads described
+above.  What occurs in GSO is that a given skbuff will have its data broken
+out over multiple skbuffs that have been resized to match the MSS provided
+via skb_shinfo()->gso_size.
+
+Before enabling any hardware segmentation offload a corresponding software
+offload is required in GSO.  Otherwise it becomes possible for a frame to
+be re-routed between devices and end up being unable to be transmitted.
+
+Generic Receive Offload
+=======================
+
+Generic receive offload is the complement to GSO.  Ideally any frame
+assembled by GRO should be segmented to create an identical sequence of
+frames using GSO, and any sequence of frames segmented by GSO should be
+able to be reassembled back to the original by GRO.  The only exception to
+this is IPv4 ID in the case that the DF bit is set for a given IP header.
+If the value of the IPv4 ID is not sequentially incrementing it will be
+altered so that it is when a frame assembled via GRO is segmented via GSO.
+
+Partial Generic Segmentation Offload
+====================================
+
+Partial generic segmentation offload is a hybrid between TSO and GSO.  What
+it effectively does is take advantage of certain traits of TCP and tunnels
+so that instead of having to rewrite the packet headers for each segment
+only the inner-most transport header and possibly the outer-most network
+header need to be updated.  This allows devices that do not support tunnel
+offloads or tunnel offloads with checksum to still make use of segmentation.
+
+With the partial offload what occurs is that all headers excluding the
+inner transport header are updated such that they will contain the correct
+values for if the header was simply duplicated.  The one exception to this
+is the outer IPv4 ID field.  It is up to the device drivers to guarantee
+that the IPv4 ID field is incremented in the case that a given header does
+not have the DF bit set.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/networking/stmmac.txt linux-libre-4.7-gnu/Documentation/networking/stmmac.txt
--- linux-libre-4.6-gnu/Documentation/networking/stmmac.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/networking/stmmac.txt	2016-07-24 15:23:50.000000000 -0400
@@ -1,6 +1,6 @@
        STMicroelectronics 10/100/1000 Synopsys Ethernet driver
 
-Copyright (C) 2007-2014  STMicroelectronics Ltd
+Copyright (C) 2007-2015  STMicroelectronics Ltd
 Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
 
 This is the driver for the MAC 10/100/1000 on-chip Ethernet controllers
@@ -138,6 +138,8 @@ struct plat_stmmacenet_data {
 	int (*init)(struct platform_device *pdev, void *priv);
 	void (*exit)(struct platform_device *pdev, void *priv);
 	void *bsp_priv;
+	int has_gmac4;
+	bool tso_en;
 };
 
 Where:
@@ -181,6 +183,8 @@ Where:
 	     registers.  init/exit callbacks should not use or modify
 	     platform data.
  o bsp_priv: another private pointer.
+ o has_gmac4: uses GMAC4 core.
+ o tso_en: Enables TSO (TCP Segmentation Offload) feature.
 
 For MDIO bus The we have:
 
@@ -278,6 +282,13 @@ Please see the following document:
  o stmmac_ethtool.c: to implement the ethtool support;
  o stmmac.h: private driver structure;
  o common.h: common definitions and VFTs;
+ o mmc_core.c/mmc.h: Management MAC Counters;
+ o stmmac_hwtstamp.c: HW timestamp support for PTP;
+ o stmmac_ptp.c: PTP 1588 clock;
+ o dwmac-<XXX>.c: these are for the platform glue-logic file; e.g. dwmac-sti.c
+   for STMicroelectronics SoCs.
+
+- GMAC 3.x
  o descs.h: descriptor structure definitions;
  o dwmac1000_core.c: dwmac GiGa core functions;
  o dwmac1000_dma.c: dma functions for the GMAC chip;
@@ -289,11 +300,32 @@ Please see the following document:
  o enh_desc.c: functions for handling enhanced descriptors;
  o norm_desc.c: functions for handling normal descriptors;
  o chain_mode.c/ring_mode.c:: functions to manage RING/CHAINED modes;
- o mmc_core.c/mmc.h: Management MAC Counters;
- o stmmac_hwtstamp.c: HW timestamp support for PTP;
- o stmmac_ptp.c: PTP 1588 clock;
- o dwmac-<XXX>.c: these are for the platform glue-logic file; e.g. dwmac-sti.c
-   for STMicroelectronics SoCs.
+
+- GMAC4.x generation
+ o dwmac4_core.c: dwmac GMAC4.x core functions;
+ o dwmac4_desc.c: functions for handling GMAC4.x descriptors;
+ o dwmac4_descs.h: descriptor definitions;
+ o dwmac4_dma.c: dma functions for the GMAC4.x chip;
+ o dwmac4_dma.h: dma definitions for the GMAC4.x chip;
+ o dwmac4.h: core definitions for the GMAC4.x chip;
+ o dwmac4_lib.c: generic GMAC4.x functions;
+
+4.12) TSO support (GMAC4.x)
+
+TSO (Tcp Segmentation Offload) feature is supported by GMAC 4.x chip family.
+When a packet is sent through TCP protocol, the TCP stack ensures that
+the SKB provided to the low level driver (stmmac in our case) matches with
+the maximum frame len (IP header + TCP header + payload <= 1500 bytes (for
+MTU set to 1500)). It means that if an application using TCP want to send a
+packet which will have a length (after adding headers) > 1514 the packet
+will be split in several TCP packets: The data payload is split and headers
+(TCP/IP ..) are added. It is done by software.
+
+When TSO is enabled, the TCP stack doesn't care about the maximum frame
+length and provide SKB packet to stmmac as it is. The GMAC IP will have to
+perform the segmentation by it self to match with maximum frame length.
+
+This feature can be enabled in device tree through "snps,tso" entry.
 
 5) Debug Information
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/networking/switchdev.txt linux-libre-4.7-gnu/Documentation/networking/switchdev.txt
--- linux-libre-4.6-gnu/Documentation/networking/switchdev.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/networking/switchdev.txt	2016-07-24 15:23:50.000000000 -0400
@@ -89,6 +89,18 @@ Typically, the management port is not pa
 is loaded with a different driver, such as a NIC driver, on the management port
 device.
 
+Switch ID
+^^^^^^^^^
+
+The switchdev driver must implement the switchdev op switchdev_port_attr_get
+for SWITCHDEV_ATTR_ID_PORT_PARENT_ID for each port netdev, returning the same
+physical ID for each port of a switch.  The ID must be unique between switches
+on the same system.  The ID does not need to be unique between switches on
+different systems.
+
+The switch ID is used to locate ports on a switch and to know if aggregated
+ports belong to the same switch.
+
 Port Netdev Naming
 ^^^^^^^^^^^^^^^^^^
 
@@ -104,25 +116,13 @@ external configuration.  For example, if
 into 4 10G ports, resulting in 4 port netdevs, the device can give a unique
 name for each port using port PHYS name.  The udev rule would be:
 
-SUBSYSTEM=="net", ACTION=="add", DRIVER="<driver>", ATTR{phys_port_name}!="", \
-	NAME="$attr{phys_port_name}"
+SUBSYSTEM=="net", ACTION=="add", ATTR{phys_switch_id}=="<phys_switch_id>", \
+	ATTR{phys_port_name}!="", NAME="swX$attr{phys_port_name}"
 
 Suggested naming convention is "swXpYsZ", where X is the switch name or ID, Y
 is the port name or ID, and Z is the sub-port name or ID.  For example, sw1p1s0
 would be sub-port 0 on port 1 on switch 1.
 
-Switch ID
-^^^^^^^^^
-
-The switchdev driver must implement the switchdev op switchdev_port_attr_get
-for SWITCHDEV_ATTR_ID_PORT_PARENT_ID for each port netdev, returning the same
-physical ID for each port of a switch.  The ID must be unique between switches
-on the same system.  The ID does not need to be unique between switches on
-different systems.
-
-The switch ID is used to locate ports on a switch and to know if aggregated
-ports belong to the same switch.
-
 Port Features
 ^^^^^^^^^^^^^
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/networking/timestamping.txt linux-libre-4.7-gnu/Documentation/networking/timestamping.txt
--- linux-libre-4.6-gnu/Documentation/networking/timestamping.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/networking/timestamping.txt	2016-07-24 15:23:50.000000000 -0400
@@ -44,11 +44,17 @@ timeval of SO_TIMESTAMP (ms).
 Supports multiple types of timestamp requests. As a result, this
 socket option takes a bitmap of flags, not a boolean. In
 
-  err = setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING, (void *) val, &val);
+  err = setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING, (void *) val,
+                   sizeof(val));
 
 val is an integer with any of the following bits set. Setting other
 bit returns EINVAL and does not change the current state.
 
+The socket option configures timestamp generation for individual
+sk_buffs (1.3.1), timestamp reporting to the socket's error
+queue (1.3.2) and options (1.3.3). Timestamp generation can also
+be enabled for individual sendmsg calls using cmsg (1.3.4).
+
 
 1.3.1 Timestamp Generation
 
@@ -71,13 +77,16 @@ SOF_TIMESTAMPING_RX_SOFTWARE:
   kernel receive stack.
 
 SOF_TIMESTAMPING_TX_HARDWARE:
-  Request tx timestamps generated by the network adapter.
+  Request tx timestamps generated by the network adapter. This flag
+  can be enabled via both socket options and control messages.
 
 SOF_TIMESTAMPING_TX_SOFTWARE:
   Request tx timestamps when data leaves the kernel. These timestamps
   are generated in the device driver as close as possible, but always
   prior to, passing the packet to the network interface. Hence, they
   require driver support and may not be available for all devices.
+  This flag can be enabled via both socket options and control messages.
+
 
 SOF_TIMESTAMPING_TX_SCHED:
   Request tx timestamps prior to entering the packet scheduler. Kernel
@@ -90,7 +99,8 @@ SOF_TIMESTAMPING_TX_SCHED:
   machines with virtual devices where a transmitted packet travels
   through multiple devices and, hence, multiple packet schedulers,
   a timestamp is generated at each layer. This allows for fine
-  grained measurement of queuing delay.
+  grained measurement of queuing delay. This flag can be enabled
+  via both socket options and control messages.
 
 SOF_TIMESTAMPING_TX_ACK:
   Request tx timestamps when all data in the send buffer has been
@@ -99,6 +109,7 @@ SOF_TIMESTAMPING_TX_ACK:
   over-report measurement, because the timestamp is generated when all
   data up to and including the buffer at send() was acknowledged: the
   cumulative acknowledgment. The mechanism ignores SACK and FACK.
+  This flag can be enabled via both socket options and control messages.
 
 
 1.3.2 Timestamp Reporting
@@ -183,6 +194,37 @@ having access to the contents of the ori
 combined with SOF_TIMESTAMPING_OPT_TSONLY.
 
 
+1.3.4. Enabling timestamps via control messages
+
+In addition to socket options, timestamp generation can be requested
+per write via cmsg, only for SOF_TIMESTAMPING_TX_* (see Section 1.3.1).
+Using this feature, applications can sample timestamps per sendmsg()
+without paying the overhead of enabling and disabling timestamps via
+setsockopt:
+
+  struct msghdr *msg;
+  ...
+  cmsg			       = CMSG_FIRSTHDR(msg);
+  cmsg->cmsg_level	       = SOL_SOCKET;
+  cmsg->cmsg_type	       = SO_TIMESTAMPING;
+  cmsg->cmsg_len	       = CMSG_LEN(sizeof(__u32));
+  *((__u32 *) CMSG_DATA(cmsg)) = SOF_TIMESTAMPING_TX_SCHED |
+				 SOF_TIMESTAMPING_TX_SOFTWARE |
+				 SOF_TIMESTAMPING_TX_ACK;
+  err = sendmsg(fd, msg, 0);
+
+The SOF_TIMESTAMPING_TX_* flags set via cmsg will override
+the SOF_TIMESTAMPING_TX_* flags set via setsockopt.
+
+Moreover, applications must still enable timestamp reporting via
+setsockopt to receive timestamps:
+
+  __u32 val = SOF_TIMESTAMPING_SOFTWARE |
+	      SOF_TIMESTAMPING_OPT_ID /* or any other flag */;
+  err = setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING, (void *) val,
+                   sizeof(val));
+
+
 1.4 Bytestream Timestamps
 
 The SO_TIMESTAMPING interface supports timestamping of bytes in a
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/phy.txt linux-libre-4.7-gnu/Documentation/phy.txt
--- linux-libre-4.6-gnu/Documentation/phy.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/phy.txt	2016-07-24 15:23:50.000000000 -0400
@@ -31,16 +31,28 @@ should provide its own implementation of
 dt boot case.
 
 #define of_phy_provider_register(dev, xlate)    \
-        __of_phy_provider_register((dev), THIS_MODULE, (xlate))
+        __of_phy_provider_register((dev), NULL, THIS_MODULE, (xlate))
 
 #define devm_of_phy_provider_register(dev, xlate)       \
-        __devm_of_phy_provider_register((dev), THIS_MODULE, (xlate))
+        __devm_of_phy_provider_register((dev), NULL, THIS_MODULE, (xlate))
 
 of_phy_provider_register and devm_of_phy_provider_register macros can be used to
 register the phy_provider and it takes device and of_xlate as
 arguments. For the dt boot case, all PHY providers should use one of the above
 2 macros to register the PHY provider.
 
+Often the device tree nodes associated with a PHY provider will contain a set
+of children that each represent a single PHY. Some bindings may nest the child
+nodes within extra levels for context and extensibility, in which case the low
+level of_phy_provider_register_full() and devm_of_phy_provider_register_full()
+macros can be used to override the node containing the children.
+
+#define of_phy_provider_register_full(dev, children, xlate) \
+	__of_phy_provider_register(dev, children, THIS_MODULE, xlate)
+
+#define devm_of_phy_provider_register_full(dev, children, xlate) \
+	__devm_of_phy_provider_register_full(dev, children, THIS_MODULE, xlate)
+
 void devm_of_phy_provider_unregister(struct device *dev,
 	struct phy_provider *phy_provider);
 void of_phy_provider_unregister(struct phy_provider *phy_provider);
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/powerpc/eeh-pci-error-recovery.txt linux-libre-4.7-gnu/Documentation/powerpc/eeh-pci-error-recovery.txt
--- linux-libre-4.6-gnu/Documentation/powerpc/eeh-pci-error-recovery.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/powerpc/eeh-pci-error-recovery.txt	2016-07-24 15:23:50.000000000 -0400
@@ -12,7 +12,7 @@ Overview:
 The IBM POWER-based pSeries and iSeries computers include PCI bus
 controller chips that have extended capabilities for detecting and
 reporting a large variety of PCI bus error conditions.  These features
-go under the name of "EEH", for "Extended Error Handling".  The EEH
+go under the name of "EEH", for "Enhanced Error Handling".  The EEH
 hardware features allow PCI bus errors to be cleared and a PCI
 card to be "rebooted", without also having to reboot the operating
 system.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/pps/pps.txt linux-libre-4.7-gnu/Documentation/pps/pps.txt
--- linux-libre-4.6-gnu/Documentation/pps/pps.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/pps/pps.txt	2016-07-24 15:23:50.000000000 -0400
@@ -98,7 +98,7 @@ pps_source_info_s as follows:
     };
 
 and then calling the function pps_register_source() in your
-intialization routine as follows:
+initialization routine as follows:
 
     source = pps_register_source(&pps_ktimer_info,
 			PPS_CAPTUREASSERT | PPS_OFFSETASSERT);
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/pwm.txt linux-libre-4.7-gnu/Documentation/pwm.txt
--- linux-libre-4.6-gnu/Documentation/pwm.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/pwm.txt	2016-07-24 15:23:50.000000000 -0400
@@ -42,9 +42,26 @@ variants of these functions, devm_pwm_ge
 
 After being requested, a PWM has to be configured using:
 
-int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns);
+int pwm_apply_state(struct pwm_device *pwm, struct pwm_state *state);
 
-To start/stop toggling the PWM output use pwm_enable()/pwm_disable().
+This API controls both the PWM period/duty_cycle config and the
+enable/disable state.
+
+The pwm_config(), pwm_enable() and pwm_disable() functions are just wrappers
+around pwm_apply_state() and should not be used if the user wants to change
+several parameter at once. For example, if you see pwm_config() and
+pwm_{enable,disable}() calls in the same function, this probably means you
+should switch to pwm_apply_state().
+
+The PWM user API also allows one to query the PWM state with pwm_get_state().
+
+In addition to the PWM state, the PWM API also exposes PWM arguments, which
+are the reference PWM config one should use on this PWM.
+PWM arguments are usually platform-specific and allows the PWM user to only
+care about dutycycle relatively to the full period (like, duty = 50% of the
+period). struct pwm_args contains 2 fields (period and polarity) and should
+be used to set the initial PWM config (usually done in the probe function
+of the PWM user). PWM arguments are retrieved with pwm_get_args().
 
 Using PWMs with the sysfs interface
 -----------------------------------
@@ -105,6 +122,15 @@ goes low for the remainder of the period
 polarity starts low for the duration of the duty cycle and goes high for the
 remainder of the period.
 
+Drivers are encouraged to implement ->apply() instead of the legacy
+->enable(), ->disable() and ->config() methods. Doing that should provide
+atomicity in the PWM config workflow, which is required when the PWM controls
+a critical device (like a regulator).
+
+The implementation of ->get_state() (a method used to retrieve initial PWM
+state) is also encouraged for the same reason: letting the PWM user know
+about the current PWM state would allow him to avoid glitches.
+
 Locking
 -------
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/RCU/Design/Data-Structures/BigTreeClassicRCUBHdyntick.svg linux-libre-4.7-gnu/Documentation/RCU/Design/Data-Structures/BigTreeClassicRCUBHdyntick.svg
--- linux-libre-4.6-gnu/Documentation/RCU/Design/Data-Structures/BigTreeClassicRCUBHdyntick.svg	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/RCU/Design/Data-Structures/BigTreeClassicRCUBHdyntick.svg	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,695 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Creator: fig2dev Version 3.2 Patchlevel 5e -->
+
+<!-- CreationDate: Wed Dec  9 17:20:02 2015 -->
+
+<!-- Magnification: 2.000 -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="5.7in"
+   height="8.6in"
+   viewBox="-44 -44 6838 10288"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="BigTreeClassicRCUBHdyntick.fig">
+  <metadata
+     id="metadata166">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs164">
+    <marker
+       inkscape:stockid="Arrow1Mend"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Mend"
+       style="overflow:visible;">
+      <path
+         id="path3924"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
+         transform="scale(0.4) rotate(180) translate(10,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow2Lend"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow2Lend"
+       style="overflow:visible;">
+      <path
+         id="path3936"
+         style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+         d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+         transform="scale(1.1) rotate(180) translate(1,0)" />
+    </marker>
+  </defs>
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="845"
+     inkscape:window-height="988"
+     id="namedview162"
+     showgrid="false"
+     inkscape:zoom="1.0452196"
+     inkscape:cx="256.5"
+     inkscape:cy="387.00003"
+     inkscape:window-x="356"
+     inkscape:window-y="61"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="g4" />
+  <g
+     style="stroke-width:.025in; fill:none"
+     id="g4">
+    <!-- Line: box -->
+    <rect
+       x="450"
+       y="0"
+       width="6300"
+       height="7350"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffffff; "
+       id="rect6" />
+    <!-- Line: box -->
+    <rect
+       x="4950"
+       y="4950"
+       width="1500"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#87cfff; "
+       id="rect8" />
+    <!-- Line: box -->
+    <rect
+       x="750"
+       y="600"
+       width="5700"
+       height="3750"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffff00; "
+       id="rect10" />
+    <!-- Line -->
+    <polyline
+       points="5250,8100 5688,5912 "
+       style="stroke:#00ff00;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="polyline12" />
+    <!-- Arrowhead on XXXpoint 5250 8100 - 5710 5790-->
+    <polyline
+       points="5714 6068 5704 5822 5598 6044 "
+       style="stroke:#00ff00;stroke-width:14;stroke-miterlimit:8; "
+       id="polyline14" />
+    <!-- Line -->
+    <polyline
+       points="4050,9300 4486,7262 "
+       style="stroke:#00ff00;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="polyline16" />
+    <!-- Arrowhead on XXXpoint 4050 9300 - 4512 7140-->
+    <polyline
+       points="4514 7418 4506 7172 4396 7394 "
+       style="stroke:#00ff00;stroke-width:14;stroke-miterlimit:8; "
+       id="polyline18" />
+    <!-- Line -->
+    <polyline
+       points="1040,9300 1476,7262 "
+       style="stroke:#00ff00;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="polyline20" />
+    <!-- Arrowhead on XXXpoint 1040 9300 - 1502 7140-->
+    <polyline
+       points="1504 7418 1496 7172 1386 7394 "
+       style="stroke:#00ff00;stroke-width:14;stroke-miterlimit:8; "
+       id="polyline22" />
+    <!-- Line -->
+    <polyline
+       points="2240,8100 2676,6062 "
+       style="stroke:#00ff00;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="polyline24" />
+    <!-- Arrowhead on XXXpoint 2240 8100 - 2702 5940-->
+    <polyline
+       points="2704 6218 2696 5972 2586 6194 "
+       style="stroke:#00ff00;stroke-width:14;stroke-miterlimit:8; "
+       id="polyline26" />
+    <!-- Line: box -->
+    <rect
+       x="0"
+       y="450"
+       width="6300"
+       height="7350"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffffff; "
+       id="rect28" />
+    <!-- Line: box -->
+    <rect
+       x="300"
+       y="1050"
+       width="5700"
+       height="3750"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffff00; "
+       id="rect30" />
+    <!-- Line -->
+    <polyline
+       points="1350,3450 2350,2590 "
+       style="stroke:#00d1d1;stroke-width:30.0045575;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline32" />
+    <!-- Arrowhead on XXXpoint 1350 3450 - 2444 2510-->
+    <!-- Line -->
+    <polyline
+       points="4950,3450 3948,2590 "
+       style="stroke:#00d1d1;stroke-width:30.0045575;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline36" />
+    <!-- Arrowhead on XXXpoint 4950 3450 - 3854 2510-->
+    <!-- Line -->
+    <polyline
+       points="4050,6600 4050,4414 "
+       style="stroke:#00d1d1;stroke-width:30.00455750000000066;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline40" />
+    <!-- Arrowhead on XXXpoint 4050 6600 - 4050 4290-->
+    <!-- Line -->
+    <polyline
+       points="1050,6600 1050,4414 "
+       style="stroke:#00d1d1;stroke-width:30.00455750000000066;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline44" />
+    <!-- Arrowhead on XXXpoint 1050 6600 - 1050 4290-->
+    <!-- Line -->
+    <polyline
+       points="2250,5400 2250,4414 "
+       style="stroke:#00d1d1;stroke-width:30.00455750000000066;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline48" />
+    <!-- Arrowhead on XXXpoint 2250 5400 - 2250 4290-->
+    <!-- Line -->
+    <polyline
+       points="2250,8100 2250,6364 "
+       style="stroke:#00ff00;stroke-width:30;stroke-linejoin:miter;stroke-linecap:butt;marker-end:url(#Arrow1Mend)"
+       id="polyline52" />
+    <!-- Arrowhead on XXXpoint 2250 8100 - 2250 6240-->
+    <!-- Line -->
+    <polyline
+       points="1050,9300 1050,7564 "
+       style="stroke:#00ff00;stroke-width:30;stroke-linejoin:miter;stroke-linecap:butt;marker-end:url(#Arrow1Mend)"
+       id="polyline56" />
+    <!-- Arrowhead on XXXpoint 1050 9300 - 1050 7440-->
+    <!-- Line -->
+    <polyline
+       points="4050,9300 4050,7564 "
+       style="stroke:#00ff00;stroke-width:30;stroke-linejoin:miter;stroke-linecap:butt;marker-end:url(#Arrow1Mend)"
+       id="polyline60" />
+    <!-- Arrowhead on XXXpoint 4050 9300 - 4050 7440-->
+    <!-- Line -->
+    <polyline
+       points="5250,8100 5250,6364 "
+       style="stroke:#00ff00;stroke-width:30;stroke-linejoin:miter;stroke-linecap:butt;marker-end:url(#Arrow1Mend)"
+       id="polyline64" />
+    <!-- Arrowhead on XXXpoint 5250 8100 - 5250 6240-->
+    <!-- Circle -->
+    <circle
+       cx="2850"
+       cy="3900"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle68" />
+    <!-- Circle -->
+    <circle
+       cx="3150"
+       cy="3900"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle70" />
+    <!-- Circle -->
+    <circle
+       cx="3450"
+       cy="3900"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle72" />
+    <!-- Circle -->
+    <circle
+       cx="1350"
+       cy="5100"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle74" />
+    <!-- Circle -->
+    <circle
+       cx="1650"
+       cy="5100"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle76" />
+    <!-- Circle -->
+    <circle
+       cx="1950"
+       cy="5100"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle78" />
+    <!-- Circle -->
+    <circle
+       cx="4350"
+       cy="5100"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle80" />
+    <!-- Circle -->
+    <circle
+       cx="4650"
+       cy="5100"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle82" />
+    <!-- Circle -->
+    <circle
+       cx="4950"
+       cy="5100"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle84" />
+    <!-- Line: box -->
+    <rect
+       x="750"
+       y="3450"
+       width="1800"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect86" />
+    <!-- Line: box -->
+    <rect
+       x="300"
+       y="6600"
+       width="1500"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#87cfff; "
+       id="rect88" />
+    <!-- Line: box -->
+    <rect
+       x="3750"
+       y="3450"
+       width="1800"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect90" />
+    <!-- Line: box -->
+    <rect
+       x="4500"
+       y="5400"
+       width="1500"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#87cfff; "
+       id="rect92" />
+    <!-- Line: box -->
+    <rect
+       x="3300"
+       y="6600"
+       width="1500"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#87cfff; "
+       id="rect94" />
+    <!-- Line: box -->
+    <rect
+       x="2250"
+       y="1650"
+       width="1800"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect96" />
+    <!-- Line: box -->
+    <rect
+       x="0"
+       y="9300"
+       width="2100"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#00ff00; "
+       id="rect98" />
+    <!-- Line: box -->
+    <rect
+       x="1350"
+       y="8100"
+       width="2100"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#00ff00; "
+       id="rect100" />
+    <!-- Line: box -->
+    <rect
+       x="3000"
+       y="9300"
+       width="2100"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#00ff00; "
+       id="rect102" />
+    <!-- Line: box -->
+    <rect
+       x="4350"
+       y="8100"
+       width="2100"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#00ff00; "
+       id="rect104" />
+    <!-- Line: box -->
+    <rect
+       x="1500"
+       y="5400"
+       width="1500"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#87cfff; "
+       id="rect106" />
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="6450"
+       y="300"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="192"
+       text-anchor="end"
+       id="text108">rcu_bh</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="3150"
+       y="1950"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text110">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="3150"
+       y="2250"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text112">rcu_node</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="1650"
+       y="3750"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text114">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="1650"
+       y="4050"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text116">rcu_node</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="4650"
+       y="4050"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text118">rcu_node</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="4650"
+       y="3750"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text120">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="2250"
+       y="5700"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text122">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="2250"
+       y="6000"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text124">rcu_data</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="1050"
+       y="6900"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text126">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="1050"
+       y="7200"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text128">rcu_data</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="5250"
+       y="5700"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text130">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="5250"
+       y="6000"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text132">rcu_data</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="4050"
+       y="6900"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text134">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="4050"
+       y="7200"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text136">rcu_data</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="450"
+       y="1350"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="start"
+       id="text138">struct rcu_state</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="1050"
+       y="9600"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text140">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="1050"
+       y="9900"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text142">rcu_dynticks</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="4050"
+       y="9600"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text144">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="4050"
+       y="9900"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text146">rcu_dynticks</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="2400"
+       y="8400"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text148">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="2400"
+       y="8700"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text150">rcu_dynticks</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="5400"
+       y="8400"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text152">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="5400"
+       y="8700"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text154">rcu_dynticks</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="6000"
+       y="750"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="192"
+       text-anchor="end"
+       id="text156">rcu_sched</text>
+    <!-- Line -->
+    <polyline
+       points="5250,5400 5250,4414 "
+       style="stroke:#00d1d1;stroke-width:30.00455750000000066;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline158" />
+    <!-- Arrowhead on XXXpoint 5250 5400 - 5250 4290-->
+  </g>
+</svg>
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/RCU/Design/Data-Structures/BigTreeClassicRCUBH.svg linux-libre-4.7-gnu/Documentation/RCU/Design/Data-Structures/BigTreeClassicRCUBH.svg
--- linux-libre-4.6-gnu/Documentation/RCU/Design/Data-Structures/BigTreeClassicRCUBH.svg	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/RCU/Design/Data-Structures/BigTreeClassicRCUBH.svg	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,499 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Creator: fig2dev Version 3.2 Patchlevel 5e -->
+
+<!-- CreationDate: Wed Dec  9 17:26:09 2015 -->
+
+<!-- Magnification: 2.000 -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="5.7in"
+   height="6.6in"
+   viewBox="-44 -44 6838 7888"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="BigTreeClassicRCUBH.fig">
+  <metadata
+     id="metadata110">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs108">
+    <marker
+       inkscape:stockid="Arrow1Mend"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Mend"
+       style="overflow:visible;">
+      <path
+         id="path3868"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
+         transform="scale(0.4) rotate(180) translate(10,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow2Mend"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow2Mend"
+       style="overflow:visible;">
+      <path
+         id="path3886"
+         style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+         d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+         transform="scale(0.6) rotate(180) translate(0,0)" />
+    </marker>
+  </defs>
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="878"
+     inkscape:window-height="1148"
+     id="namedview106"
+     showgrid="false"
+     inkscape:zoom="1.3547758"
+     inkscape:cx="256.5"
+     inkscape:cy="297"
+     inkscape:window-x="45"
+     inkscape:window-y="24"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="g4" />
+  <g
+     style="stroke-width:.025in; fill:none"
+     id="g4">
+    <!-- Line: box -->
+    <rect
+       x="450"
+       y="0"
+       width="6300"
+       height="7350"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffffff; "
+       id="rect6" />
+    <!-- Line: box -->
+    <rect
+       x="4950"
+       y="4950"
+       width="1500"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#87cfff; "
+       id="rect8" />
+    <!-- Line: box -->
+    <rect
+       x="750"
+       y="600"
+       width="5700"
+       height="3750"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffff00; "
+       id="rect10" />
+    <!-- Line: box -->
+    <rect
+       x="0"
+       y="450"
+       width="6300"
+       height="7350"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffffff; "
+       id="rect12" />
+    <!-- Line: box -->
+    <rect
+       x="300"
+       y="1050"
+       width="5700"
+       height="3750"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffff00; "
+       id="rect14" />
+    <!-- Circle -->
+    <circle
+       cx="2850"
+       cy="3900"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle16" />
+    <!-- Circle -->
+    <circle
+       cx="3150"
+       cy="3900"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle18" />
+    <!-- Circle -->
+    <circle
+       cx="3450"
+       cy="3900"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle20" />
+    <!-- Circle -->
+    <circle
+       cx="1350"
+       cy="5100"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle22" />
+    <!-- Circle -->
+    <circle
+       cx="1650"
+       cy="5100"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle24" />
+    <!-- Circle -->
+    <circle
+       cx="1950"
+       cy="5100"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle26" />
+    <!-- Circle -->
+    <circle
+       cx="4350"
+       cy="5100"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle28" />
+    <!-- Circle -->
+    <circle
+       cx="4650"
+       cy="5100"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle30" />
+    <!-- Circle -->
+    <circle
+       cx="4950"
+       cy="5100"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle32" />
+    <!-- Line -->
+    <polyline
+       points="1350,3450 2350,2590 "
+       style="stroke:#00d1d1;stroke-width:30.0045575;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline34" />
+    <!-- Arrowhead on XXXpoint 1350 3450 - 2444 2510-->
+    <!-- Line -->
+    <polyline
+       points="4950,3450 3948,2590 "
+       style="stroke:#00d1d1;stroke-width:30.0045575;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline38" />
+    <!-- Arrowhead on XXXpoint 4950 3450 - 3854 2510-->
+    <!-- Line: box -->
+    <rect
+       x="750"
+       y="3450"
+       width="1800"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect42" />
+    <!-- Line -->
+    <polyline
+       points="2250,5400 2250,4414 "
+       style="stroke:#00d1d1;stroke-width:30.0045575;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline44" />
+    <!-- Arrowhead on XXXpoint 2250 5400 - 2250 4290-->
+    <!-- Line: box -->
+    <rect
+       x="1500"
+       y="5400"
+       width="1500"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#87cfff; "
+       id="rect48" />
+    <!-- Line: box -->
+    <rect
+       x="300"
+       y="6600"
+       width="1500"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#87cfff; "
+       id="rect50" />
+    <!-- Line: box -->
+    <rect
+       x="3750"
+       y="3450"
+       width="1800"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect52" />
+    <!-- Line: box -->
+    <rect
+       x="4500"
+       y="5400"
+       width="1500"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#87cfff; "
+       id="rect54" />
+    <!-- Line: box -->
+    <rect
+       x="3300"
+       y="6600"
+       width="1500"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#87cfff; "
+       id="rect56" />
+    <!-- Line: box -->
+    <rect
+       x="2250"
+       y="1650"
+       width="1800"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect58" />
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="6450"
+       y="300"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="192"
+       text-anchor="end"
+       id="text60">rcu_bh</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="3150"
+       y="1950"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text62">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="3150"
+       y="2250"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text64">rcu_node</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="1650"
+       y="3750"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text66">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="1650"
+       y="4050"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text68">rcu_node</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="4650"
+       y="4050"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text70">rcu_node</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="4650"
+       y="3750"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text72">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="2250"
+       y="5700"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text74">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="2250"
+       y="6000"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text76">rcu_data</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="1050"
+       y="6900"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text78">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="1050"
+       y="7200"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text80">rcu_data</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="5250"
+       y="5700"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text82">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="5250"
+       y="6000"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text84">rcu_data</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="4050"
+       y="6900"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text86">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="4050"
+       y="7200"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text88">rcu_data</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="450"
+       y="1350"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="start"
+       id="text90">struct rcu_state</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="6000"
+       y="750"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="192"
+       text-anchor="end"
+       id="text92">rcu_sched</text>
+    <!-- Line -->
+    <polyline
+       points="5250,5400 5250,4414 "
+       style="stroke:#00d1d1;stroke-width:30.0045575;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline94" />
+    <!-- Arrowhead on XXXpoint 5250 5400 - 5250 4290-->
+    <!-- Line -->
+    <polyline
+       points="4050,6600 4050,4414 "
+       style="stroke:#00d1d1;stroke-width:30.0045575;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline98" />
+    <!-- Arrowhead on XXXpoint 4050 6600 - 4050 4290-->
+    <!-- Line -->
+    <polyline
+       points="1050,6600 1050,4414 "
+       style="stroke:#00d1d1;stroke-width:30.0045575;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline102" />
+    <!-- Arrowhead on XXXpoint 1050 6600 - 1050 4290-->
+  </g>
+</svg>
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/RCU/Design/Data-Structures/BigTreeClassicRCU.svg linux-libre-4.7-gnu/Documentation/RCU/Design/Data-Structures/BigTreeClassicRCU.svg
--- linux-libre-4.6-gnu/Documentation/RCU/Design/Data-Structures/BigTreeClassicRCU.svg	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/RCU/Design/Data-Structures/BigTreeClassicRCU.svg	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,474 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Creator: fig2dev Version 3.2 Patchlevel 5e -->
+
+<!-- CreationDate: Wed Dec  9 17:28:20 2015 -->
+
+<!-- Magnification: 3.000 -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="9.1in"
+   height="8.9in"
+   viewBox="-66 -66 10932 10707"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="BigTreeClassicRCU.fig">
+  <metadata
+     id="metadata106">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs104">
+    <marker
+       inkscape:stockid="Arrow1Mend"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Mend"
+       style="overflow:visible;">
+      <path
+         id="path3864"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
+         transform="scale(0.4) rotate(180) translate(10,0)" />
+    </marker>
+  </defs>
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="973"
+     inkscape:window-height="1137"
+     id="namedview102"
+     showgrid="false"
+     inkscape:zoom="0.9743589"
+     inkscape:cx="409.50003"
+     inkscape:cy="400.49997"
+     inkscape:window-x="915"
+     inkscape:window-y="24"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="g4" />
+  <g
+     style="stroke-width:.025in; fill:none"
+     id="g4">
+    <!-- Line: box -->
+    <rect
+       x="0"
+       y="0"
+       width="10800"
+       height="5625"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffff00; "
+       id="rect6" />
+    <!-- Line: box -->
+    <rect
+       x="1125"
+       y="3600"
+       width="2700"
+       height="1350"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect8" />
+    <!-- Line: box -->
+    <rect
+       x="3825"
+       y="900"
+       width="2700"
+       height="1350"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect10" />
+    <!-- Line: box -->
+    <rect
+       x="6525"
+       y="3600"
+       width="2700"
+       height="1350"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect12" />
+    <!-- Line -->
+    <polyline
+       points="3375,6525 3375,5046 "
+       style="stroke:#00d1d1;stroke-width:44.9934641;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline14" />
+    <!-- Arrowhead on XXXpoint 3375 6525 - 3375 4860-->
+    <!-- Circle -->
+    <circle
+       cx="7425"
+       cy="6075"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle18" />
+    <!-- Circle -->
+    <circle
+       cx="7875"
+       cy="6075"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle20" />
+    <!-- Circle -->
+    <circle
+       cx="8325"
+       cy="6075"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle22" />
+    <!-- Circle -->
+    <circle
+       cx="2025"
+       cy="6075"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle24" />
+    <!-- Circle -->
+    <circle
+       cx="2475"
+       cy="6075"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle26" />
+    <!-- Circle -->
+    <circle
+       cx="2925"
+       cy="6075"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle28" />
+    <!-- Circle -->
+    <circle
+       cx="4725"
+       cy="4275"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle30" />
+    <!-- Circle -->
+    <circle
+       cx="5175"
+       cy="4275"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle32" />
+    <!-- Circle -->
+    <circle
+       cx="5625"
+       cy="4275"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle34" />
+    <!-- Line: box -->
+    <rect
+       x="2025"
+       y="6525"
+       width="2700"
+       height="1800"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="rect36" />
+    <!-- Line -->
+    <polyline
+       points="2475,3600 3975,2310 "
+       style="stroke:#00d1d1;stroke-width:44.9934641;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline38" />
+    <!-- Arrowhead on XXXpoint 2475 3600 - 4116 2190-->
+    <!-- Line -->
+    <polyline
+       points="7875,3600 6372,2310 "
+       style="stroke:#00d1d1;stroke-width:44.9934641;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline42" />
+    <!-- Arrowhead on XXXpoint 7875 3600 - 6231 2190-->
+    <!-- Line -->
+    <polyline
+       points="6975,8775 6975,5046 "
+       style="stroke:#00d1d1;stroke-width:44.9934641;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline46" />
+    <!-- Arrowhead on XXXpoint 6975 8775 - 6975 4860-->
+    <!-- Line -->
+    <polyline
+       points="1575,8775 1575,5046 "
+       style="stroke:#00d1d1;stroke-width:44.9934641;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline50" />
+    <!-- Arrowhead on XXXpoint 1575 8775 - 1575 4860-->
+    <!-- Line -->
+    <polyline
+       points="8775,6525 8775,5046 "
+       style="stroke:#00d1d1;stroke-width:44.9934641;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline54" />
+    <!-- Arrowhead on XXXpoint 8775 6525 - 8775 4860-->
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="1575"
+       y="9225"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text58">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="1575"
+       y="9675"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text60">rcu_data</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="1575"
+       y="10350"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="324"
+       text-anchor="middle"
+       id="text62">CPU 0</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="3375"
+       y="6975"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text64">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="3375"
+       y="7425"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text66">rcu_data</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="3375"
+       y="8100"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="324"
+       text-anchor="middle"
+       id="text68">CPU 15</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="6975"
+       y="9225"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text70">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="6975"
+       y="9675"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text72">rcu_data</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="6975"
+       y="10350"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="324"
+       text-anchor="middle"
+       id="text74">CPU 1007</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="8730"
+       y="6930"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text76">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="8730"
+       y="7380"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text78">rcu_data</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="8730"
+       y="8055"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="324"
+       text-anchor="middle"
+       id="text80">CPU 1023</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="225"
+       y="450"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="start"
+       id="text82">struct rcu_state</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="2475"
+       y="4050"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text84">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="2475"
+       y="4500"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text86">rcu_node</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="7875"
+       y="4500"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text88">rcu_node</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="7875"
+       y="4050"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text90">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="5175"
+       y="1350"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text92">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="5175"
+       y="1800"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text94">rcu_node</text>
+    <!-- Line: box -->
+    <rect
+       x="225"
+       y="8775"
+       width="2700"
+       height="1800"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="rect96" />
+    <!-- Line: box -->
+    <rect
+       x="5625"
+       y="8775"
+       width="2700"
+       height="1800"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="rect98" />
+    <!-- Line: box -->
+    <rect
+       x="7380"
+       y="6480"
+       width="2700"
+       height="1800"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="rect100" />
+  </g>
+</svg>
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/RCU/Design/Data-Structures/BigTreePreemptRCUBHdyntickCB.svg linux-libre-4.7-gnu/Documentation/RCU/Design/Data-Structures/BigTreePreemptRCUBHdyntickCB.svg
--- linux-libre-4.6-gnu/Documentation/RCU/Design/Data-Structures/BigTreePreemptRCUBHdyntickCB.svg	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/RCU/Design/Data-Structures/BigTreePreemptRCUBHdyntickCB.svg	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,858 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Creator: fig2dev Version 3.2 Patchlevel 5e -->
+
+<!-- CreationDate: Wed Dec  9 17:29:48 2015 -->
+
+<!-- Magnification: 2.000 -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="7.4in"
+   height="9.9in"
+   viewBox="-44 -44 8938 11938"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="BigTreePreemptRCUBHdyntickCB.svg">
+  <metadata
+     id="metadata212">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs210">
+    <marker
+       inkscape:stockid="Arrow1Mend"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Mend"
+       style="overflow:visible;">
+      <path
+         id="path3970"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
+         transform="scale(0.4) rotate(180) translate(10,0)" />
+    </marker>
+  </defs>
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="881"
+     inkscape:window-height="1128"
+     id="namedview208"
+     showgrid="false"
+     inkscape:zoom="1.0195195"
+     inkscape:cx="333"
+     inkscape:cy="445.49997"
+     inkscape:window-x="936"
+     inkscape:window-y="24"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="g4" />
+  <g
+     style="stroke-width:.025in; fill:none"
+     id="g4">
+    <!-- Line: box -->
+    <rect
+       x="900"
+       y="0"
+       width="6300"
+       height="7350"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffffff; "
+       id="rect6" />
+    <!-- Line: box -->
+    <rect
+       x="1200"
+       y="600"
+       width="5700"
+       height="3750"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffff00; "
+       id="rect8" />
+    <!-- Line: box -->
+    <rect
+       x="5400"
+       y="4950"
+       width="1500"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#87cfff; "
+       id="rect10" />
+    <!-- Line: box -->
+    <rect
+       x="450"
+       y="450"
+       width="6300"
+       height="7350"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffffff; "
+       id="rect12" />
+    <!-- Line: box -->
+    <rect
+       x="750"
+       y="1050"
+       width="5700"
+       height="3750"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffff00; "
+       id="rect14" />
+    <!-- Line: box -->
+    <rect
+       x="4950"
+       y="5400"
+       width="1500"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#87cfff; "
+       id="rect16" />
+    <!-- Line -->
+    <polyline
+       points="5250,8550 5688,6362 "
+       style="stroke:#00ff00;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="polyline18" />
+    <!-- Arrowhead on XXXpoint 5250 8550 - 5710 6240-->
+    <polyline
+       points="5714 6518 5704 6272 5598 6494 "
+       style="stroke:#00ff00;stroke-width:14;stroke-miterlimit:8; "
+       id="polyline20" />
+    <!-- Line -->
+    <polyline
+       points="4050,9750 4486,7712 "
+       style="stroke:#00ff00;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="polyline22" />
+    <!-- Arrowhead on XXXpoint 4050 9750 - 4512 7590-->
+    <polyline
+       points="4514 7868 4506 7622 4396 7844 "
+       style="stroke:#00ff00;stroke-width:14;stroke-miterlimit:8; "
+       id="polyline24" />
+    <!-- Line -->
+    <polyline
+       points="1040,9750 1476,7712 "
+       style="stroke:#00ff00;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="polyline26" />
+    <!-- Arrowhead on XXXpoint 1040 9750 - 1502 7590-->
+    <polyline
+       points="1504 7868 1496 7622 1386 7844 "
+       style="stroke:#00ff00;stroke-width:14;stroke-miterlimit:8; "
+       id="polyline28" />
+    <!-- Line -->
+    <polyline
+       points="2240,8550 2676,6512 "
+       style="stroke:#00ff00;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="polyline30" />
+    <!-- Arrowhead on XXXpoint 2240 8550 - 2702 6390-->
+    <polyline
+       points="2704 6668 2696 6422 2586 6644 "
+       style="stroke:#00ff00;stroke-width:14;stroke-miterlimit:8; "
+       id="polyline32" />
+    <!-- Line -->
+    <polyline
+       points="4050,9600 5692,6062 "
+       style="stroke:#00ff00;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="polyline34" />
+    <!-- Arrowhead on XXXpoint 4050 9600 - 5744 5948-->
+    <polyline
+       points="5682 6220 5730 5978 5574 6170 "
+       style="stroke:#00ff00;stroke-width:14;stroke-miterlimit:8; "
+       id="polyline36" />
+    <!-- Line -->
+    <polyline
+       points="1086,9600 2728,6062 "
+       style="stroke:#00ff00;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="polyline38" />
+    <!-- Arrowhead on XXXpoint 1086 9600 - 2780 5948-->
+    <polyline
+       points="2718 6220 2766 5978 2610 6170 "
+       style="stroke:#00ff00;stroke-width:14;stroke-miterlimit:8; "
+       id="polyline40" />
+    <!-- Line: box -->
+    <rect
+       x="0"
+       y="900"
+       width="6300"
+       height="7350"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffffff; "
+       id="rect42" />
+    <!-- Line: box -->
+    <rect
+       x="300"
+       y="1500"
+       width="5700"
+       height="3750"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffff00; "
+       id="rect44" />
+    <!-- Line -->
+    <polyline
+       points="1350,3900 2350,3040 "
+       style="stroke:#00d1d1;stroke-width:29.99463964;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline46" />
+    <!-- Arrowhead on XXXpoint 1350 3900 - 2444 2960-->
+    <!-- Line -->
+    <polyline
+       points="4950,3900 3948,3040 "
+       style="stroke:#00d1d1;stroke-width:29.99463964;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline50" />
+    <!-- Arrowhead on XXXpoint 4950 3900 - 3854 2960-->
+    <!-- Line -->
+    <polyline
+       points="4050,7050 4050,4864 "
+       style="stroke:#00d1d1;stroke-width:29.99463964;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline54" />
+    <!-- Arrowhead on XXXpoint 4050 7050 - 4050 4740-->
+    <!-- Line -->
+    <polyline
+       points="1050,7050 1050,4864 "
+       style="stroke:#00d1d1;stroke-width:29.99463964;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline58" />
+    <!-- Arrowhead on XXXpoint 1050 7050 - 1050 4740-->
+    <!-- Line -->
+    <polyline
+       points="2250,5850 2250,4864 "
+       style="stroke:#00d1d1;stroke-width:29.99463964;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline62" />
+    <!-- Arrowhead on XXXpoint 2250 5850 - 2250 4740-->
+    <!-- Line -->
+    <polyline
+       points="2250,8550 2250,6814 "
+       style="stroke:#00ff00;stroke-width:29.99463964;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline66" />
+    <!-- Arrowhead on XXXpoint 2250 8550 - 2250 6690-->
+    <!-- Line -->
+    <polyline
+       points="1050,9750 1050,8014 "
+       style="stroke:#00ff00;stroke-width:29.99463964;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline70" />
+    <!-- Arrowhead on XXXpoint 1050 9750 - 1050 7890-->
+    <!-- Line -->
+    <polyline
+       points="4050,9750 4050,8014 "
+       style="stroke:#00ff00;stroke-width:29.99463964;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline74" />
+    <!-- Arrowhead on XXXpoint 4050 9750 - 4050 7890-->
+    <!-- Line -->
+    <polyline
+       points="5250,8550 5250,6814 "
+       style="stroke:#00ff00;stroke-width:29.99463964;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline78" />
+    <!-- Arrowhead on XXXpoint 5250 8550 - 5250 6690-->
+    <!-- Line -->
+    <polyline
+       points="6000,6300 8048,7910 "
+       style="stroke:#87cfff;stroke-width:30;stroke-linejoin:miter;stroke-linecap:butt;marker-end:url(#Arrow1Mend)"
+       id="polyline82" />
+    <!-- Arrowhead on XXXpoint 6000 6300 - 8146 7986-->
+    <!-- Circle -->
+    <circle
+       cx="2850"
+       cy="4350"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle86" />
+    <!-- Circle -->
+    <circle
+       cx="3150"
+       cy="4350"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle88" />
+    <!-- Circle -->
+    <circle
+       cx="3450"
+       cy="4350"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle90" />
+    <!-- Circle -->
+    <circle
+       cx="1350"
+       cy="5550"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle92" />
+    <!-- Circle -->
+    <circle
+       cx="1650"
+       cy="5550"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle94" />
+    <!-- Circle -->
+    <circle
+       cx="1950"
+       cy="5550"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle96" />
+    <!-- Circle -->
+    <circle
+       cx="4350"
+       cy="5550"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle98" />
+    <!-- Circle -->
+    <circle
+       cx="4650"
+       cy="5550"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle100" />
+    <!-- Circle -->
+    <circle
+       cx="4950"
+       cy="5550"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle102" />
+    <!-- Line: box -->
+    <rect
+       x="7350"
+       y="7950"
+       width="1500"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="rect104" />
+    <!-- Line: box -->
+    <rect
+       x="7350"
+       y="9450"
+       width="1500"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="rect106" />
+    <!-- Line -->
+    <polyline
+       points="8100,8850 8100,9384 "
+       style="stroke:#000000;stroke-width:30;stroke-linejoin:miter;stroke-linecap:butt;marker-end:url(#Arrow1Mend)"
+       id="polyline108" />
+    <!-- Arrowhead on XXXpoint 8100 8850 - 8100 9510-->
+    <!-- Line: box -->
+    <rect
+       x="7350"
+       y="10950"
+       width="1500"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="rect112" />
+    <!-- Line -->
+    <polyline
+       points="8100,10350 8100,10884 "
+       style="stroke:#000000;stroke-width:30;stroke-linejoin:miter;stroke-linecap:butt;marker-end:url(#Arrow1Mend)"
+       id="polyline114" />
+    <!-- Arrowhead on XXXpoint 8100 10350 - 8100 11010-->
+    <!-- Line: box -->
+    <rect
+       x="750"
+       y="3900"
+       width="1800"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect118" />
+    <!-- Line: box -->
+    <rect
+       x="300"
+       y="7050"
+       width="1500"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#87cfff; "
+       id="rect120" />
+    <!-- Line: box -->
+    <rect
+       x="3750"
+       y="3900"
+       width="1800"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect122" />
+    <!-- Line: box -->
+    <rect
+       x="4500"
+       y="5850"
+       width="1500"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#87cfff; "
+       id="rect124" />
+    <!-- Line: box -->
+    <rect
+       x="3300"
+       y="7050"
+       width="1500"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#87cfff; "
+       id="rect126" />
+    <!-- Line: box -->
+    <rect
+       x="2250"
+       y="2100"
+       width="1800"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect128" />
+    <!-- Line: box -->
+    <rect
+       x="0"
+       y="9750"
+       width="2100"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#00ff00; "
+       id="rect130" />
+    <!-- Line: box -->
+    <rect
+       x="1350"
+       y="8550"
+       width="2100"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#00ff00; "
+       id="rect132" />
+    <!-- Line: box -->
+    <rect
+       x="3000"
+       y="9750"
+       width="2100"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#00ff00; "
+       id="rect134" />
+    <!-- Line: box -->
+    <rect
+       x="4350"
+       y="8550"
+       width="2100"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#00ff00; "
+       id="rect136" />
+    <!-- Line: box -->
+    <rect
+       x="1500"
+       y="5850"
+       width="1500"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#87cfff; "
+       id="rect138" />
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="8100"
+       y="8250"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text140">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="8100"
+       y="8550"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text142">rcu_head</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="8100"
+       y="9750"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text144">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="8100"
+       y="10050"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text146">rcu_head</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="8100"
+       y="11250"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text148">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="8100"
+       y="11550"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text150">rcu_head</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="6000"
+       y="1200"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="192"
+       text-anchor="end"
+       id="text152">rcu_sched</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="6450"
+       y="750"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="192"
+       text-anchor="end"
+       id="text154">rcu_bh</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="3150"
+       y="2400"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text156">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="3150"
+       y="2700"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text158">rcu_node</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="1650"
+       y="4200"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text160">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="1650"
+       y="4500"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text162">rcu_node</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="4650"
+       y="4500"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text164">rcu_node</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="4650"
+       y="4200"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text166">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="2250"
+       y="6150"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text168">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="2250"
+       y="6450"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text170">rcu_data</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="1050"
+       y="7350"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text172">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="1050"
+       y="7650"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text174">rcu_data</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="5250"
+       y="6150"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text176">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="5250"
+       y="6450"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text178">rcu_data</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="4050"
+       y="7350"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text180">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="4050"
+       y="7650"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text182">rcu_data</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="450"
+       y="1800"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="start"
+       id="text184">struct rcu_state</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="1050"
+       y="10050"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text186">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="1050"
+       y="10350"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text188">rcu_dynticks</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="4050"
+       y="10050"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text190">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="4050"
+       y="10350"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text192">rcu_dynticks</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="2400"
+       y="8850"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text194">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="2400"
+       y="9150"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text196">rcu_dynticks</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="5400"
+       y="8850"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text198">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="5400"
+       y="9150"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text200">rcu_dynticks</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="6900"
+       y="300"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="192"
+       text-anchor="end"
+       id="text202">rcu_preempt</text>
+    <!-- Line -->
+    <polyline
+       points="5250,5850 5250,4864 "
+       style="stroke:#00d1d1;stroke-width:29.99463964;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline204" />
+    <!-- Arrowhead on XXXpoint 5250 5850 - 5250 4740-->
+  </g>
+</svg>
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/RCU/Design/Data-Structures/BigTreePreemptRCUBHdyntick.svg linux-libre-4.7-gnu/Documentation/RCU/Design/Data-Structures/BigTreePreemptRCUBHdyntick.svg
--- linux-libre-4.6-gnu/Documentation/RCU/Design/Data-Structures/BigTreePreemptRCUBHdyntick.svg	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/RCU/Design/Data-Structures/BigTreePreemptRCUBHdyntick.svg	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,741 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Creator: fig2dev Version 3.2 Patchlevel 5e -->
+
+<!-- CreationDate: Wed Dec  9 17:32:59 2015 -->
+
+<!-- Magnification: 2.000 -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="6.1in"
+   height="8.9in"
+   viewBox="-44 -44 7288 10738"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="BigTreePreemptRCUBHdyntick.fig">
+  <metadata
+     id="metadata182">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs180">
+    <marker
+       inkscape:stockid="Arrow1Mend"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Mend"
+       style="overflow:visible;">
+      <path
+         id="path3940"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
+         transform="scale(0.4) rotate(180) translate(10,0)" />
+    </marker>
+  </defs>
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="874"
+     inkscape:window-height="1148"
+     id="namedview178"
+     showgrid="false"
+     inkscape:zoom="1.2097379"
+     inkscape:cx="274.5"
+     inkscape:cy="400.49997"
+     inkscape:window-x="946"
+     inkscape:window-y="24"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="g4" />
+  <g
+     style="stroke-width:.025in; fill:none"
+     id="g4">
+    <!-- Line: box -->
+    <rect
+       x="900"
+       y="0"
+       width="6300"
+       height="7350"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffffff; "
+       id="rect6" />
+    <!-- Line: box -->
+    <rect
+       x="1200"
+       y="600"
+       width="5700"
+       height="3750"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffff00; "
+       id="rect8" />
+    <!-- Line: box -->
+    <rect
+       x="5400"
+       y="4950"
+       width="1500"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#87cfff; "
+       id="rect10" />
+    <!-- Line: box -->
+    <rect
+       x="450"
+       y="450"
+       width="6300"
+       height="7350"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffffff; "
+       id="rect12" />
+    <!-- Line: box -->
+    <rect
+       x="750"
+       y="1050"
+       width="5700"
+       height="3750"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffff00; "
+       id="rect14" />
+    <!-- Line: box -->
+    <rect
+       x="4950"
+       y="5400"
+       width="1500"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#87cfff; "
+       id="rect16" />
+    <!-- Line -->
+    <polyline
+       points="5250,8550 5688,6362 "
+       style="stroke:#00ff00;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="polyline18" />
+    <!-- Arrowhead on XXXpoint 5250 8550 - 5710 6240-->
+    <polyline
+       points="5714 6518 5704 6272 5598 6494 "
+       style="stroke:#00ff00;stroke-width:14;stroke-miterlimit:8; "
+       id="polyline20" />
+    <!-- Line -->
+    <polyline
+       points="4050,9750 4486,7712 "
+       style="stroke:#00ff00;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="polyline22" />
+    <!-- Arrowhead on XXXpoint 4050 9750 - 4512 7590-->
+    <polyline
+       points="4514 7868 4506 7622 4396 7844 "
+       style="stroke:#00ff00;stroke-width:14;stroke-miterlimit:8; "
+       id="polyline24" />
+    <!-- Line -->
+    <polyline
+       points="1040,9750 1476,7712 "
+       style="stroke:#00ff00;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="polyline26" />
+    <!-- Arrowhead on XXXpoint 1040 9750 - 1502 7590-->
+    <polyline
+       points="1504 7868 1496 7622 1386 7844 "
+       style="stroke:#00ff00;stroke-width:14;stroke-miterlimit:8; "
+       id="polyline28" />
+    <!-- Line -->
+    <polyline
+       points="2240,8550 2676,6512 "
+       style="stroke:#00ff00;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="polyline30" />
+    <!-- Arrowhead on XXXpoint 2240 8550 - 2702 6390-->
+    <polyline
+       points="2704 6668 2696 6422 2586 6644 "
+       style="stroke:#00ff00;stroke-width:14;stroke-miterlimit:8; "
+       id="polyline32" />
+    <!-- Line -->
+    <polyline
+       points="4050,9750 5682,6360 "
+       style="stroke:#00ff00;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="polyline34" />
+    <!-- Arrowhead on XXXpoint 4050 9750 - 5736 6246-->
+    <polyline
+       points="5672 6518 5722 6276 5562 6466 "
+       style="stroke:#00ff00;stroke-width:14;stroke-miterlimit:8; "
+       id="polyline36" />
+    <!-- Line -->
+    <polyline
+       points="1010,9750 2642,6360 "
+       style="stroke:#00ff00;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="polyline38" />
+    <!-- Arrowhead on XXXpoint 1010 9750 - 2696 6246-->
+    <polyline
+       points="2632 6518 2682 6276 2522 6466 "
+       style="stroke:#00ff00;stroke-width:14;stroke-miterlimit:8; "
+       id="polyline40" />
+    <!-- Line: box -->
+    <rect
+       x="0"
+       y="900"
+       width="6300"
+       height="7350"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffffff; "
+       id="rect42" />
+    <!-- Line: box -->
+    <rect
+       x="300"
+       y="1500"
+       width="5700"
+       height="3750"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffff00; "
+       id="rect44" />
+    <!-- Line -->
+    <polyline
+       points="1350,3900 2350,3040 "
+       style="stroke:#00d1d1;stroke-width:30.00205472;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline46" />
+    <!-- Arrowhead on XXXpoint 1350 3900 - 2444 2960-->
+    <!-- Line -->
+    <polyline
+       points="4950,3900 3948,3040 "
+       style="stroke:#00d1d1;stroke-width:30.00205472;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline50" />
+    <!-- Arrowhead on XXXpoint 4950 3900 - 3854 2960-->
+    <!-- Line -->
+    <polyline
+       points="4050,7050 4050,4864 "
+       style="stroke:#00d1d1;stroke-width:30.00205472;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline54" />
+    <!-- Arrowhead on XXXpoint 4050 7050 - 4050 4740-->
+    <!-- Line -->
+    <polyline
+       points="1050,7050 1050,4864 "
+       style="stroke:#00d1d1;stroke-width:30.00205472;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline58" />
+    <!-- Arrowhead on XXXpoint 1050 7050 - 1050 4740-->
+    <!-- Line -->
+    <polyline
+       points="2250,5850 2250,4864 "
+       style="stroke:#00d1d1;stroke-width:30.00205472;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline62" />
+    <!-- Arrowhead on XXXpoint 2250 5850 - 2250 4740-->
+    <!-- Line -->
+    <polyline
+       points="2250,8550 2250,6814 "
+       style="stroke:#00ff00;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="polyline66" />
+    <!-- Arrowhead on XXXpoint 2250 8550 - 2250 6690-->
+    <!-- Line -->
+    <polyline
+       points="1050,9750 1050,8014 "
+       style="stroke:#00ff00;stroke-width:30.00205472;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline70" />
+    <!-- Arrowhead on XXXpoint 1050 9750 - 1050 7890-->
+    <!-- Line -->
+    <polyline
+       points="4050,9750 4050,8014 "
+       style="stroke:#00ff00;stroke-width:30.00205472;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline74" />
+    <!-- Arrowhead on XXXpoint 4050 9750 - 4050 7890-->
+    <!-- Line -->
+    <polyline
+       points="5250,8550 5250,6814 "
+       style="stroke:#00ff00;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="polyline78" />
+    <!-- Arrowhead on XXXpoint 5250 8550 - 5250 6690-->
+    <!-- Circle -->
+    <circle
+       cx="2850"
+       cy="4350"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle82" />
+    <!-- Circle -->
+    <circle
+       cx="3150"
+       cy="4350"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle84" />
+    <!-- Circle -->
+    <circle
+       cx="3450"
+       cy="4350"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle86" />
+    <!-- Circle -->
+    <circle
+       cx="1350"
+       cy="5550"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle88" />
+    <!-- Circle -->
+    <circle
+       cx="1650"
+       cy="5550"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle90" />
+    <!-- Circle -->
+    <circle
+       cx="1950"
+       cy="5550"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle92" />
+    <!-- Circle -->
+    <circle
+       cx="4350"
+       cy="5550"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle94" />
+    <!-- Circle -->
+    <circle
+       cx="4650"
+       cy="5550"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle96" />
+    <!-- Circle -->
+    <circle
+       cx="4950"
+       cy="5550"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle98" />
+    <!-- Line: box -->
+    <rect
+       x="750"
+       y="3900"
+       width="1800"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect100" />
+    <!-- Line: box -->
+    <rect
+       x="300"
+       y="7050"
+       width="1500"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#87cfff; "
+       id="rect102" />
+    <!-- Line: box -->
+    <rect
+       x="3750"
+       y="3900"
+       width="1800"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect104" />
+    <!-- Line: box -->
+    <rect
+       x="4500"
+       y="5850"
+       width="1500"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#87cfff; "
+       id="rect106" />
+    <!-- Line: box -->
+    <rect
+       x="3300"
+       y="7050"
+       width="1500"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#87cfff; "
+       id="rect108" />
+    <!-- Line: box -->
+    <rect
+       x="2250"
+       y="2100"
+       width="1800"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect110" />
+    <!-- Line: box -->
+    <rect
+       x="0"
+       y="9750"
+       width="2100"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#00ff00; "
+       id="rect112" />
+    <!-- Line: box -->
+    <rect
+       x="1350"
+       y="8550"
+       width="2100"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#00ff00; "
+       id="rect114" />
+    <!-- Line: box -->
+    <rect
+       x="3000"
+       y="9750"
+       width="2100"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#00ff00; "
+       id="rect116" />
+    <!-- Line: box -->
+    <rect
+       x="4350"
+       y="8550"
+       width="2100"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#00ff00; "
+       id="rect118" />
+    <!-- Line: box -->
+    <rect
+       x="1500"
+       y="5850"
+       width="1500"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#87cfff; "
+       id="rect120" />
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="6450"
+       y="750"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="192"
+       text-anchor="end"
+       id="text122">rcu_bh</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="3150"
+       y="2400"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text124">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="3150"
+       y="2700"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text126">rcu_node</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="1650"
+       y="4200"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text128">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="1650"
+       y="4500"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text130">rcu_node</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="4650"
+       y="4500"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text132">rcu_node</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="4650"
+       y="4200"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text134">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="2250"
+       y="6150"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text136">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="2250"
+       y="6450"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text138">rcu_data</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="1050"
+       y="7350"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text140">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="1050"
+       y="7650"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text142">rcu_data</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="5250"
+       y="6150"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text144">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="5250"
+       y="6450"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text146">rcu_data</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="4050"
+       y="7350"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text148">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="4050"
+       y="7650"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text150">rcu_data</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="450"
+       y="1800"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="start"
+       id="text152">struct rcu_state</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="1050"
+       y="10050"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text154">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="1050"
+       y="10350"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text156">rcu_dynticks</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="4050"
+       y="10050"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text158">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="4050"
+       y="10350"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text160">rcu_dynticks</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="2400"
+       y="8850"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text162">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="2400"
+       y="9150"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text164">rcu_dynticks</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="5400"
+       y="8850"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text166">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="5400"
+       y="9150"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text168">rcu_dynticks</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="6900"
+       y="300"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="192"
+       text-anchor="end"
+       id="text170">rcu_preempt</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="6000"
+       y="1200"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="192"
+       text-anchor="end"
+       id="text172">rcu_sched</text>
+    <!-- Line -->
+    <polyline
+       points="5250,5850 5250,4864 "
+       style="stroke:#00d1d1;stroke-width:30.00205472;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline174" />
+    <!-- Arrowhead on XXXpoint 5250 5850 - 5250 4740-->
+  </g>
+</svg>
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/RCU/Design/Data-Structures/blkd_task.svg linux-libre-4.7-gnu/Documentation/RCU/Design/Data-Structures/blkd_task.svg
--- linux-libre-4.6-gnu/Documentation/RCU/Design/Data-Structures/blkd_task.svg	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/RCU/Design/Data-Structures/blkd_task.svg	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,843 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Creator: fig2dev Version 3.2 Patchlevel 5e -->
+
+<!-- CreationDate: Wed Dec  9 17:35:03 2015 -->
+
+<!-- Magnification: 2.000 -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="10.1in"
+   height="8.6in"
+   viewBox="-44 -44 12088 10288"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="blkd_task.fig">
+  <metadata
+     id="metadata212">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs210">
+    <marker
+       inkscape:stockid="Arrow1Mend"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Mend"
+       style="overflow:visible;">
+      <path
+         id="path3970"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
+         transform="scale(0.4) rotate(180) translate(10,0)" />
+    </marker>
+  </defs>
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1087"
+     inkscape:window-height="1144"
+     id="namedview208"
+     showgrid="false"
+     inkscape:zoom="1.0495049"
+     inkscape:cx="454.50003"
+     inkscape:cy="387.00003"
+     inkscape:window-x="833"
+     inkscape:window-y="28"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="g4" />
+  <g
+     style="stroke-width:.025in; fill:none"
+     id="g4">
+    <!-- Line: box -->
+    <rect
+       x="450"
+       y="0"
+       width="6300"
+       height="7350"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffffff; "
+       id="rect6" />
+    <!-- Line: box -->
+    <rect
+       x="4950"
+       y="4950"
+       width="1500"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#87cfff; "
+       id="rect8" />
+    <!-- Line: box -->
+    <rect
+       x="750"
+       y="600"
+       width="5700"
+       height="3750"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffff00; "
+       id="rect10" />
+    <!-- Line -->
+    <polyline
+       points="5250,8100 5688,5912 "
+       style="stroke:#00ff00;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="polyline12" />
+    <!-- Arrowhead on XXXpoint 5250 8100 - 5710 5790-->
+    <polyline
+       points="5714 6068 5704 5822 5598 6044 "
+       style="stroke:#00ff00;stroke-width:14;stroke-miterlimit:8; "
+       id="polyline14" />
+    <!-- Line -->
+    <polyline
+       points="4050,9300 4486,7262 "
+       style="stroke:#00ff00;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="polyline16" />
+    <!-- Arrowhead on XXXpoint 4050 9300 - 4512 7140-->
+    <polyline
+       points="4514 7418 4506 7172 4396 7394 "
+       style="stroke:#00ff00;stroke-width:14;stroke-miterlimit:8; "
+       id="polyline18" />
+    <!-- Line -->
+    <polyline
+       points="1040,9300 1476,7262 "
+       style="stroke:#00ff00;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="polyline20" />
+    <!-- Arrowhead on XXXpoint 1040 9300 - 1502 7140-->
+    <polyline
+       points="1504 7418 1496 7172 1386 7394 "
+       style="stroke:#00ff00;stroke-width:14;stroke-miterlimit:8; "
+       id="polyline22" />
+    <!-- Line -->
+    <polyline
+       points="2240,8100 2676,6062 "
+       style="stroke:#00ff00;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="polyline24" />
+    <!-- Arrowhead on XXXpoint 2240 8100 - 2702 5940-->
+    <polyline
+       points="2704 6218 2696 5972 2586 6194 "
+       style="stroke:#00ff00;stroke-width:14;stroke-miterlimit:8; "
+       id="polyline26" />
+    <!-- Line: box -->
+    <rect
+       x="0"
+       y="450"
+       width="6300"
+       height="7350"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffffff; "
+       id="rect28" />
+    <!-- Line: box -->
+    <rect
+       x="300"
+       y="1050"
+       width="5700"
+       height="3750"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffff00; "
+       id="rect30" />
+    <!-- Line -->
+    <polyline
+       points="1350,3450 2350,2590 "
+       style="stroke:#00d1d1;stroke-width:30.00057884;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline32" />
+    <!-- Arrowhead on XXXpoint 1350 3450 - 2444 2510-->
+    <!-- Line -->
+    <polyline
+       points="4950,3450 3948,2590 "
+       style="stroke:#00d1d1;stroke-width:30.00057884;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline36" />
+    <!-- Arrowhead on XXXpoint 4950 3450 - 3854 2510-->
+    <!-- Line -->
+    <polyline
+       points="4050,6600 4050,4414 "
+       style="stroke:#00d1d1;stroke-width:30.00057884;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline40" />
+    <!-- Arrowhead on XXXpoint 4050 6600 - 4050 4290-->
+    <!-- Line -->
+    <polyline
+       points="1050,6600 1050,4414 "
+       style="stroke:#00d1d1;stroke-width:30.00057884;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline44" />
+    <!-- Arrowhead on XXXpoint 1050 6600 - 1050 4290-->
+    <!-- Line -->
+    <polyline
+       points="2250,5400 2250,4414 "
+       style="stroke:#00d1d1;stroke-width:30.00057884;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline48" />
+    <!-- Arrowhead on XXXpoint 2250 5400 - 2250 4290-->
+    <!-- Line -->
+    <polyline
+       points="2250,8100 2250,6364 "
+       style="stroke:#00ff00;stroke-width:30.00057884;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline52" />
+    <!-- Arrowhead on XXXpoint 2250 8100 - 2250 6240-->
+    <!-- Line -->
+    <polyline
+       points="1050,9300 1050,7564 "
+       style="stroke:#00ff00;stroke-width:30.00057884;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline56" />
+    <!-- Arrowhead on XXXpoint 1050 9300 - 1050 7440-->
+    <!-- Line -->
+    <polyline
+       points="4050,9300 4050,7564 "
+       style="stroke:#00ff00;stroke-width:30.00057884;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline60" />
+    <!-- Arrowhead on XXXpoint 4050 9300 - 4050 7440-->
+    <!-- Line -->
+    <polyline
+       points="5250,8100 5250,6364 "
+       style="stroke:#00ff00;stroke-width:30.00057884;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline64" />
+    <!-- Arrowhead on XXXpoint 5250 8100 - 5250 6240-->
+    <!-- Circle -->
+    <circle
+       cx="2850"
+       cy="3900"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle68" />
+    <!-- Circle -->
+    <circle
+       cx="3150"
+       cy="3900"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle70" />
+    <!-- Circle -->
+    <circle
+       cx="3450"
+       cy="3900"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle72" />
+    <!-- Circle -->
+    <circle
+       cx="1350"
+       cy="5100"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle74" />
+    <!-- Circle -->
+    <circle
+       cx="1650"
+       cy="5100"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle76" />
+    <!-- Circle -->
+    <circle
+       cx="1950"
+       cy="5100"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle78" />
+    <!-- Circle -->
+    <circle
+       cx="4350"
+       cy="5100"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle80" />
+    <!-- Circle -->
+    <circle
+       cx="4650"
+       cy="5100"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle82" />
+    <!-- Circle -->
+    <circle
+       cx="4950"
+       cy="5100"
+       r="76"
+       style="fill:#000000;stroke:#000000;stroke-width:14;"
+       id="circle84" />
+    <!-- Line: box -->
+    <rect
+       x="750"
+       y="3450"
+       width="1800"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect86" />
+    <!-- Line: box -->
+    <rect
+       x="300"
+       y="6600"
+       width="1500"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#87cfff; "
+       id="rect88" />
+    <!-- Line: box -->
+    <rect
+       x="4500"
+       y="5400"
+       width="1500"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#87cfff; "
+       id="rect90" />
+    <!-- Line: box -->
+    <rect
+       x="3300"
+       y="6600"
+       width="1500"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#87cfff; "
+       id="rect92" />
+    <!-- Line: box -->
+    <rect
+       x="2250"
+       y="1650"
+       width="1800"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect94" />
+    <!-- Line: box -->
+    <rect
+       x="0"
+       y="9300"
+       width="2100"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#00ff00; "
+       id="rect96" />
+    <!-- Line: box -->
+    <rect
+       x="1350"
+       y="8100"
+       width="2100"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#00ff00; "
+       id="rect98" />
+    <!-- Line: box -->
+    <rect
+       x="3000"
+       y="9300"
+       width="2100"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#00ff00; "
+       id="rect100" />
+    <!-- Line: box -->
+    <rect
+       x="4350"
+       y="8100"
+       width="2100"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#00ff00; "
+       id="rect102" />
+    <!-- Line: box -->
+    <rect
+       x="1500"
+       y="5400"
+       width="1500"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#87cfff; "
+       id="rect104" />
+    <!-- Line -->
+    <polygon
+       points="5550,3450 7350,2850 7350,5100 5550,4350 5550,3450 "
+       style="stroke:#000000;stroke-width:14; stroke-linejoin:miter; stroke-linecap:butt; stroke-dasharray:120 120;fill:#ffbfbf; "
+       id="polygon106" />
+    <!-- Line -->
+    <polyline
+       points="9300,3150 10734,3150 "
+       style="stroke:#000000;stroke-width:30.00057884;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline108" />
+    <!-- Arrowhead on XXXpoint 9300 3150 - 10860 3150-->
+    <!-- Line: box -->
+    <rect
+       x="10800"
+       y="2850"
+       width="1200"
+       height="750"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="rect112" />
+    <!-- Line -->
+    <polyline
+       points="11400,3600 11400,4284 "
+       style="stroke:#000000;stroke-width:30.00057884;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline114" />
+    <!-- Arrowhead on XXXpoint 11400 3600 - 11400 4410-->
+    <!-- Line: box -->
+    <rect
+       x="10800"
+       y="4350"
+       width="1200"
+       height="750"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="rect118" />
+    <!-- Line -->
+    <polyline
+       points="11400,5100 11400,5784 "
+       style="stroke:#000000;stroke-width:30.00057884;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline120" />
+    <!-- Arrowhead on XXXpoint 11400 5100 - 11400 5910-->
+    <!-- Line: box -->
+    <rect
+       x="10800"
+       y="5850"
+       width="1200"
+       height="750"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="rect124" />
+    <!-- Line -->
+    <polyline
+       points="9300,3900 9900,3900 9900,4650 10734,4650 "
+       style="stroke:#000000;stroke-width:30.00057884;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline126" />
+    <!-- Arrowhead on XXXpoint 9900 4650 - 10860 4650-->
+    <!-- Line -->
+    <polyline
+       points="9300,4650 9600,4650 9600,6150 10734,6150 "
+       style="stroke:#000000;stroke-width:30.00057884;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline130" />
+    <!-- Arrowhead on XXXpoint 9600 6150 - 10860 6150-->
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="6450"
+       y="300"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="192"
+       text-anchor="end"
+       id="text134">rcu_bh</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="3150"
+       y="1950"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text136">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="3150"
+       y="2250"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text138">rcu_node</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="1650"
+       y="3750"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text140">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="1650"
+       y="4050"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text142">rcu_node</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="2250"
+       y="5700"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text144">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="2250"
+       y="6000"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text146">rcu_data</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="1050"
+       y="6900"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text148">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="1050"
+       y="7200"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text150">rcu_data</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="5250"
+       y="5700"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text152">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="5250"
+       y="6000"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text154">rcu_data</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="4050"
+       y="6900"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text156">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="4050"
+       y="7200"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text158">rcu_data</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="450"
+       y="1350"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="start"
+       id="text160">struct rcu_state</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="1050"
+       y="9600"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text162">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="1050"
+       y="9900"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text164">rcu_dynticks</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="4050"
+       y="9600"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text166">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="4050"
+       y="9900"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text168">rcu_dynticks</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="2400"
+       y="8400"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text170">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="2400"
+       y="8700"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text172">rcu_dynticks</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="5400"
+       y="8400"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text174">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="5400"
+       y="8700"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text176">rcu_dynticks</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="6000"
+       y="750"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="192"
+       text-anchor="end"
+       id="text178">rcu_sched</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="11400"
+       y="3300"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="216"
+       text-anchor="middle"
+       id="text180">T3</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="11400"
+       y="4800"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="216"
+       text-anchor="middle"
+       id="text182">T2</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="11400"
+       y="6300"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="216"
+       text-anchor="middle"
+       id="text184">T1</text>
+    <!-- Line -->
+    <polyline
+       points="5250,5400 5250,4414 "
+       style="stroke:#00d1d1;stroke-width:30.00057884;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline186" />
+    <!-- Arrowhead on XXXpoint 5250 5400 - 5250 4290-->
+    <!-- Line: box -->
+    <rect
+       x="3750"
+       y="3450"
+       width="1800"
+       height="900"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect190" />
+    <!-- Line: box -->
+    <rect
+       x="7350"
+       y="2850"
+       width="1950"
+       height="750"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect192" />
+    <!-- Line: box -->
+    <rect
+       x="7350"
+       y="3600"
+       width="1950"
+       height="750"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect194" />
+    <!-- Line: box -->
+    <rect
+       x="7350"
+       y="4350"
+       width="1950"
+       height="750"
+       rx="0"
+       style="stroke:#000000;stroke-width:30; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect196" />
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="4650"
+       y="4050"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text198">rcu_node</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="4650"
+       y="3750"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="middle"
+       id="text200">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="7500"
+       y="3300"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="start"
+       id="text202">blkd_tasks</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="7500"
+       y="4050"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="start"
+       id="text204">gp_tasks</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="7500"
+       y="4800"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="192"
+       text-anchor="start"
+       id="text206">exp_tasks</text>
+  </g>
+</svg>
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/RCU/Design/Data-Structures/Data-Structures.html linux-libre-4.7-gnu/Documentation/RCU/Design/Data-Structures/Data-Structures.html
--- linux-libre-4.6-gnu/Documentation/RCU/Design/Data-Structures/Data-Structures.html	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/RCU/Design/Data-Structures/Data-Structures.html	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,1333 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+        "http://www.w3.org/TR/html4/loose.dtd">
+        <html>
+        <head><title>A Tour Through TREE_RCU's Data Structures [LWN.net]</title>
+        <meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
+
+           <p>January 27, 2016</p>
+           <p>This article was contributed by Paul E.&nbsp;McKenney</p>
+
+<h3>Introduction</h3>
+
+This document describes RCU's major data structures and their relationship
+to each other.
+
+<ol>
+<li>	<a href="#Data-Structure Relationships">
+	Data-Structure Relationships</a>
+<li>	<a href="#The rcu_state Structure">
+	The <tt>rcu_state</tt> Structure</a>
+<li>	<a href="#The rcu_node Structure">
+	The <tt>rcu_node</tt> Structure</a>
+<li>	<a href="#The rcu_data Structure">
+	The <tt>rcu_data</tt> Structure</a>
+<li>	<a href="#The rcu_dynticks Structure">
+	The <tt>rcu_dynticks</tt> Structure</a>
+<li>	<a href="#The rcu_head Structure">
+	The <tt>rcu_head</tt> Structure</a>
+<li>	<a href="#RCU-Specific Fields in the task_struct Structure">
+	RCU-Specific Fields in the <tt>task_struct</tt> Structure</a>
+<li>	<a href="#Accessor Functions">
+	Accessor Functions</a>
+</ol>
+
+At the end we have the
+<a href="#Answers to Quick Quizzes">answers to the quick quizzes</a>.
+
+<h3><a name="Data-Structure Relationships">Data-Structure Relationships</a></h3>
+
+<p>RCU is for all intents and purposes a large state machine, and its
+data structures maintain the state in such a way as to allow RCU readers
+to execute extremely quickly, while also processing the RCU grace periods
+requested by updaters in an efficient and extremely scalable fashion.
+The efficiency and scalability of RCU updaters is provided primarily
+by a combining tree, as shown below:
+
+</p><p><img src="BigTreeClassicRCU.svg" alt="BigTreeClassicRCU.svg" width="30%">
+
+</p><p>This diagram shows an enclosing <tt>rcu_state</tt> structure
+containing a tree of <tt>rcu_node</tt> structures.
+Each leaf node of the <tt>rcu_node</tt> tree has up to 16
+<tt>rcu_data</tt> structures associated with it, so that there
+are <tt>NR_CPUS</tt> number of <tt>rcu_data</tt> structures,
+one for each possible CPU.
+This structure is adjusted at boot time, if needed, to handle the
+common case where <tt>nr_cpu_ids</tt> is much less than
+<tt>NR_CPUs</tt>.
+For example, a number of Linux distributions set <tt>NR_CPUs=4096</tt>,
+which results in a three-level <tt>rcu_node</tt> tree.
+If the actual hardware has only 16 CPUs, RCU will adjust itself
+at boot time, resulting in an <tt>rcu_node</tt> tree with only a single node.
+
+</p><p>The purpose of this combining tree is to allow per-CPU events
+such as quiescent states, dyntick-idle transitions,
+and CPU hotplug operations to be processed efficiently
+and scalably.
+Quiescent states are recorded by the per-CPU <tt>rcu_data</tt> structures,
+and other events are recorded by the leaf-level <tt>rcu_node</tt>
+structures.
+All of these events are combined at each level of the tree until finally
+grace periods are completed at the tree's root <tt>rcu_node</tt>
+structure.
+A grace period can be completed at the root once every CPU
+(or, in the case of <tt>CONFIG_PREEMPT_RCU</tt>, task)
+has passed through a quiescent state.
+Once a grace period has completed, record of that fact is propagated
+back down the tree.
+
+</p><p>As can be seen from the diagram, on a 64-bit system
+a two-level tree with 64 leaves can accommodate 1,024 CPUs, with a fanout
+of 64 at the root and a fanout of 16 at the leaves.
+
+<table>
+<tr><th>&nbsp;</th></tr>
+<tr><th align="left">Quick Quiz:</th></tr>
+<tr><td>
+	Why isn't the fanout at the leaves also 64?
+</td></tr>
+<tr><th align="left">Answer:</th></tr>
+<tr><td bgcolor="#ffffff"><font color="ffffff">
+	Because there are more types of events that affect the leaf-level
+	<tt>rcu_node</tt> structures than further up the tree.
+	Therefore, if the leaf <tt>rcu_node</tt> structures have fanout of
+	64, the contention on these structures' <tt>-&gt;structures</tt>
+	becomes excessive.
+	Experimentation on a wide variety of systems has shown that a fanout
+	of 16 works well for the leaves of the <tt>rcu_node</tt> tree.
+	</font>
+
+	<p><font color="ffffff">Of course, further experience with
+	systems having hundreds or thousands of CPUs may demonstrate
+	that the fanout for the non-leaf <tt>rcu_node</tt> structures
+	must also be reduced.
+	Such reduction can be easily carried out when and if it proves
+	necessary.
+	In the meantime, if you are using such a system and running into
+	contention problems on the non-leaf <tt>rcu_node</tt> structures,
+	you may use the <tt>CONFIG_RCU_FANOUT</tt> kernel configuration
+	parameter to reduce the non-leaf fanout as needed.
+	</font>
+
+	<p><font color="ffffff">Kernels built for systems with
+	strong NUMA characteristics might also need to adjust
+	<tt>CONFIG_RCU_FANOUT</tt> so that the domains of the
+	<tt>rcu_node</tt> structures align with hardware boundaries.
+	However, there has thus far been no need for this.
+</font></td></tr>
+<tr><td>&nbsp;</td></tr>
+</table>
+
+<p>If your system has more than 1,024 CPUs (or more than 512 CPUs on
+a 32-bit system), then RCU will automatically add more levels to the
+tree.
+For example, if you are crazy enough to build a 64-bit system with 65,536
+CPUs, RCU would configure the <tt>rcu_node</tt> tree as follows:
+
+</p><p><img src="HugeTreeClassicRCU.svg" alt="HugeTreeClassicRCU.svg" width="50%">
+
+</p><p>RCU currently permits up to a four-level tree, which on a 64-bit system
+accommodates up to 4,194,304 CPUs, though only a mere 524,288 CPUs for
+32-bit systems.
+On the other hand, you can set <tt>CONFIG_RCU_FANOUT</tt> to be
+as small as 2 if you wish, which would permit only 16 CPUs, which
+is useful for testing.
+
+</p><p>This multi-level combining tree allows us to get most of the
+performance and scalability
+benefits of partitioning, even though RCU grace-period detection is
+inherently a global operation.
+The trick here is that only the last CPU to report a quiescent state
+into a given <tt>rcu_node</tt> structure need advance to the <tt>rcu_node</tt>
+structure at the next level up the tree.
+This means that at the leaf-level <tt>rcu_node</tt> structure, only
+one access out of sixteen will progress up the tree.
+For the internal <tt>rcu_node</tt> structures, the situation is even
+more extreme:  Only one access out of sixty-four will progress up
+the tree.
+Because the vast majority of the CPUs do not progress up the tree,
+the lock contention remains roughly constant up the tree.
+No matter how many CPUs there are in the system, at most 64 quiescent-state
+reports per grace period will progress all the way to the root
+<tt>rcu_node</tt> structure, thus ensuring that the lock contention
+on that root <tt>rcu_node</tt> structure remains acceptably low.
+
+</p><p>In effect, the combining tree acts like a big shock absorber,
+keeping lock contention under control at all tree levels regardless
+of the level of loading on the system.
+
+</p><p>The Linux kernel actually supports multiple flavors of RCU
+running concurrently, so RCU builds separate data structures for each
+flavor.
+For example, for <tt>CONFIG_TREE_RCU=y</tt> kernels, RCU provides
+rcu_sched and rcu_bh, as shown below:
+
+</p><p><img src="BigTreeClassicRCUBH.svg" alt="BigTreeClassicRCUBH.svg" width="33%">
+
+</p><p>Energy efficiency is increasingly important, and for that
+reason the Linux kernel provides <tt>CONFIG_NO_HZ_IDLE</tt>, which
+turns off the scheduling-clock interrupts on idle CPUs, which in
+turn allows those CPUs to attain deeper sleep states and to consume
+less energy.
+CPUs whose scheduling-clock interrupts have been turned off are
+said to be in <i>dyntick-idle mode</i>.
+RCU must handle dyntick-idle CPUs specially
+because RCU would otherwise wake up each CPU on every grace period,
+which would defeat the whole purpose of <tt>CONFIG_NO_HZ_IDLE</tt>.
+RCU uses the <tt>rcu_dynticks</tt> structure to track
+which CPUs are in dyntick idle mode, as shown below:
+
+</p><p><img src="BigTreeClassicRCUBHdyntick.svg" alt="BigTreeClassicRCUBHdyntick.svg" width="33%">
+
+</p><p>However, if a CPU is in dyntick-idle mode, it is in that mode
+for all flavors of RCU.
+Therefore, a single <tt>rcu_dynticks</tt> structure is allocated per
+CPU, and all of a given CPU's <tt>rcu_data</tt> structures share
+that <tt>rcu_dynticks</tt>, as shown in the figure.
+
+</p><p>Kernels built with <tt>CONFIG_PREEMPT_RCU</tt> support
+rcu_preempt in addition to rcu_sched and rcu_bh, as shown below:
+
+</p><p><img src="BigTreePreemptRCUBHdyntick.svg" alt="BigTreePreemptRCUBHdyntick.svg" width="35%">
+
+</p><p>RCU updaters wait for normal grace periods by registering
+RCU callbacks, either directly via <tt>call_rcu()</tt> and
+friends (namely <tt>call_rcu_bh()</tt> and <tt>call_rcu_sched()</tt>),
+there being a separate interface per flavor of RCU)
+or indirectly via <tt>synchronize_rcu()</tt> and friends.
+RCU callbacks are represented by <tt>rcu_head</tt> structures,
+which are queued on <tt>rcu_data</tt> structures while they are
+waiting for a grace period to elapse, as shown in the following figure:
+
+</p><p><img src="BigTreePreemptRCUBHdyntickCB.svg" alt="BigTreePreemptRCUBHdyntickCB.svg" width="40%">
+
+</p><p>This figure shows how <tt>TREE_RCU</tt>'s and
+<tt>PREEMPT_RCU</tt>'s major data structures are related.
+Lesser data structures will be introduced with the algorithms that
+make use of them.
+
+</p><p>Note that each of the data structures in the above figure has
+its own synchronization:
+
+<p><ol>
+<li>	Each <tt>rcu_state</tt> structures has a lock and a mutex,
+	and some fields are protected by the corresponding root
+	<tt>rcu_node</tt> structure's lock.
+<li>	Each <tt>rcu_node</tt> structure has a spinlock.
+<li>	The fields in <tt>rcu_data</tt> are private to the corresponding
+	CPU, although a few can be read and written by other CPUs.
+<li>	Similarly, the fields in <tt>rcu_dynticks</tt> are private
+	to the corresponding CPU, although a few can be read by
+	other CPUs.
+</ol>
+
+<p>It is important to note that different data structures can have
+very different ideas about the state of RCU at any given time.
+For but one example, awareness of the start or end of a given RCU
+grace period propagates slowly through the data structures.
+This slow propagation is absolutely necessary for RCU to have good
+read-side performance.
+If this balkanized implementation seems foreign to you, one useful
+trick is to consider each instance of these data structures to be
+a different person, each having the usual slightly different
+view of reality.
+
+</p><p>The general role of each of these data structures is as
+follows:
+
+</p><ol>
+<li>	<tt>rcu_state</tt>:
+	This structure forms the interconnection between the
+	<tt>rcu_node</tt> and <tt>rcu_data</tt> structures,
+	tracks grace periods, serves as short-term repository
+	for callbacks orphaned by CPU-hotplug events,
+	maintains <tt>rcu_barrier()</tt> state,
+	tracks expedited grace-period state,
+	and maintains state used to force quiescent states when
+	grace periods extend too long,
+<li>	<tt>rcu_node</tt>: This structure forms the combining
+	tree that propagates quiescent-state
+	information from the leaves to the root, and also propagates
+	grace-period information from the root to the leaves.
+	It provides local copies of the grace-period state in order
+	to allow this information to be accessed in a synchronized
+	manner without suffering the scalability limitations that
+	would otherwise be imposed by global locking.
+	In <tt>CONFIG_PREEMPT_RCU</tt> kernels, it manages the lists
+	of tasks that have blocked while in their current
+	RCU read-side critical section.
+	In <tt>CONFIG_PREEMPT_RCU</tt> with
+	<tt>CONFIG_RCU_BOOST</tt>, it manages the
+	per-<tt>rcu_node</tt> priority-boosting
+	kernel threads (kthreads) and state.
+	Finally, it records CPU-hotplug state in order to determine
+	which CPUs should be ignored during a given grace period.
+<li>	<tt>rcu_data</tt>: This per-CPU structure is the
+	focus of quiescent-state detection and RCU callback queuing.
+	It also tracks its relationship to the corresponding leaf
+	<tt>rcu_node</tt> structure to allow more-efficient
+	propagation of quiescent states up the <tt>rcu_node</tt>
+	combining tree.
+	Like the <tt>rcu_node</tt> structure, it provides a local
+	copy of the grace-period information to allow for-free
+	synchronized
+	access to this information from the corresponding CPU.
+	Finally, this structure records past dyntick-idle state
+	for the corresponding CPU and also tracks statistics.
+<li>	<tt>rcu_dynticks</tt>:
+	This per-CPU structure tracks the current dyntick-idle
+	state for the corresponding CPU.
+	Unlike the other three structures, the <tt>rcu_dynticks</tt>
+	structure is not replicated per RCU flavor.
+<li>	<tt>rcu_head</tt>:
+	This structure represents RCU callbacks, and is the
+	only structure allocated and managed by RCU users.
+	The <tt>rcu_head</tt> structure is normally embedded
+	within the RCU-protected data structure.
+</ol>
+
+<p>If all you wanted from this article was a general notion of how
+RCU's data structures are related, you are done.
+Otherwise, each of the following sections give more details on
+the <tt>rcu_state</tt>, <tt>rcu_node</tt>, <tt>rcu_data</tt>,
+and <tt>rcu_dynticks</tt> data structures.
+
+<h3><a name="The rcu_state Structure">
+The <tt>rcu_state</tt> Structure</a></h3>
+
+<p>The <tt>rcu_state</tt> structure is the base structure that
+represents a flavor of RCU.
+This structure forms the interconnection between the
+<tt>rcu_node</tt> and <tt>rcu_data</tt> structures,
+tracks grace periods, contains the lock used to
+synchronize with CPU-hotplug events,
+and maintains state used to force quiescent states when
+grace periods extend too long,
+
+</p><p>A few of the <tt>rcu_state</tt> structure's fields are discussed,
+singly and in groups, in the following sections.
+The more specialized fields are covered in the discussion of their
+use.
+
+<h5>Relationship to rcu_node and rcu_data Structures</h5>
+
+This portion of the <tt>rcu_state</tt> structure is declared
+as follows:
+
+<pre>
+  1   struct rcu_node node[NUM_RCU_NODES];
+  2   struct rcu_node *level[NUM_RCU_LVLS + 1];
+  3   struct rcu_data __percpu *rda;
+</pre>
+
+<table>
+<tr><th>&nbsp;</th></tr>
+<tr><th align="left">Quick Quiz:</th></tr>
+<tr><td>
+	Wait a minute!
+	You said that the <tt>rcu_node</tt> structures formed a tree,
+	but they are declared as a flat array!
+	What gives?
+</td></tr>
+<tr><th align="left">Answer:</th></tr>
+<tr><td bgcolor="#ffffff"><font color="ffffff">
+	The tree is laid out in the array.
+	The first node In the array is the head, the next set of nodes in the
+	array are children of the head node, and so on until the last set of
+	nodes in the array are the leaves.
+	</font>
+
+	<p><font color="ffffff">See the following diagrams to see how
+	this works.
+</font></td></tr>
+<tr><td>&nbsp;</td></tr>
+</table>
+
+<p>The <tt>rcu_node</tt> tree is embedded into the
+<tt>-&gt;node[]</tt> array as shown in the following figure:
+
+</p><p><img src="TreeMapping.svg" alt="TreeMapping.svg" width="40%">
+
+</p><p>One interesting consequence of this mapping is that a
+breadth-first traversal of the tree is implemented as a simple
+linear scan of the array, which is in fact what the
+<tt>rcu_for_each_node_breadth_first()</tt> macro does.
+This macro is used at the beginning and ends of grace periods.
+
+</p><p>Each entry of the <tt>-&gt;level</tt> array references
+the first <tt>rcu_node</tt> structure on the corresponding level
+of the tree, for example, as shown below:
+
+</p><p><img src="TreeMappingLevel.svg" alt="TreeMappingLevel.svg" width="40%">
+
+</p><p>The zero<sup>th</sup> element of the array references the root
+<tt>rcu_node</tt> structure, the first element references the
+first child of the root <tt>rcu_node</tt>, and finally the second
+element references the first leaf <tt>rcu_node</tt> structure.
+
+</p><p>For whatever it is worth, if you draw the tree to be tree-shaped
+rather than array-shaped, it is easy to draw a planar representation:
+
+</p><p><img src="TreeLevel.svg" alt="TreeLevel.svg" width="60%">
+
+</p><p>Finally, the <tt>-&gt;rda</tt> field references a per-CPU
+pointer to the corresponding CPU's <tt>rcu_data</tt> structure.
+
+</p><p>All of these fields are constant once initialization is complete,
+and therefore need no protection.
+
+<h5>Grace-Period Tracking</h5>
+
+<p>This portion of the <tt>rcu_state</tt> structure is declared
+as follows:
+
+<pre>
+  1   unsigned long gpnum;
+  2   unsigned long completed;
+</pre>
+
+<p>RCU grace periods are numbered, and
+the <tt>-&gt;gpnum</tt> field contains the number of the grace
+period that started most recently.
+The <tt>-&gt;completed</tt> field contains the number of the
+grace period that completed most recently.
+If the two fields are equal, the RCU grace period that most recently
+started has already completed, and therefore the corresponding
+flavor of RCU is idle.
+If <tt>-&gt;gpnum</tt> is one greater than <tt>-&gt;completed</tt>,
+then <tt>-&gt;gpnum</tt> gives the number of the current RCU
+grace period, which has not yet completed.
+Any other combination of values indicates that something is broken.
+These two fields are protected by the root <tt>rcu_node</tt>'s
+<tt>-&gt;lock</tt> field.
+
+</p><p>There are <tt>-&gt;gpnum</tt> and <tt>-&gt;completed</tt> fields
+in the <tt>rcu_node</tt> and <tt>rcu_data</tt> structures
+as well.
+The fields in the <tt>rcu_state</tt> structure represent the
+most current values, and those of the other structures are compared
+in order to detect the start of a new grace period in a distributed
+fashion.
+The values flow from <tt>rcu_state</tt> to <tt>rcu_node</tt>
+(down the tree from the root to the leaves) to <tt>rcu_data</tt>.
+
+<h5>Miscellaneous</h5>
+
+<p>This portion of the <tt>rcu_state</tt> structure is declared
+as follows:
+
+<pre>
+  1   unsigned long gp_max;
+  2   char abbr;
+  3   char *name;
+</pre>
+
+<p>The <tt>-&gt;gp_max</tt> field tracks the duration of the longest
+grace period in jiffies.
+It is protected by the root <tt>rcu_node</tt>'s <tt>-&gt;lock</tt>.
+
+<p>The <tt>-&gt;name</tt> field points to the name of the RCU flavor
+(for example, &ldquo;rcu_sched&rdquo;), and is constant.
+The <tt>-&gt;abbr</tt> field contains a one-character abbreviation,
+for example, &ldquo;s&rdquo; for RCU-sched.
+
+<h3><a name="The rcu_node Structure">
+The <tt>rcu_node</tt> Structure</a></h3>
+
+<p>The <tt>rcu_node</tt> structures form the combining
+tree that propagates quiescent-state
+information from the leaves to the root and also that propagates
+grace-period information from the root down to the leaves.
+They provides local copies of the grace-period state in order
+to allow this information to be accessed in a synchronized
+manner without suffering the scalability limitations that
+would otherwise be imposed by global locking.
+In <tt>CONFIG_PREEMPT_RCU</tt> kernels, they manage the lists
+of tasks that have blocked while in their current
+RCU read-side critical section.
+In <tt>CONFIG_PREEMPT_RCU</tt> with
+<tt>CONFIG_RCU_BOOST</tt>, they manage the
+per-<tt>rcu_node</tt> priority-boosting
+kernel threads (kthreads) and state.
+Finally, they record CPU-hotplug state in order to determine
+which CPUs should be ignored during a given grace period.
+
+</p><p>The <tt>rcu_node</tt> structure's fields are discussed,
+singly and in groups, in the following sections.
+
+<h5>Connection to Combining Tree</h5>
+
+<p>This portion of the <tt>rcu_node</tt> structure is declared
+as follows:
+
+<pre>
+  1   struct rcu_node *parent;
+  2   u8 level;
+  3   u8 grpnum;
+  4   unsigned long grpmask;
+  5   int grplo;
+  6   int grphi;
+</pre>
+
+<p>The <tt>-&gt;parent</tt> pointer references the <tt>rcu_node</tt>
+one level up in the tree, and is <tt>NULL</tt> for the root
+<tt>rcu_node</tt>.
+The RCU implementation makes heavy use of this field to push quiescent
+states up the tree.
+The <tt>-&gt;level</tt> field gives the level in the tree, with
+the root being at level zero, its children at level one, and so on.
+The <tt>-&gt;grpnum</tt> field gives this node's position within
+the children of its parent, so this number can range between 0 and 31
+on 32-bit systems and between 0 and 63 on 64-bit systems.
+The <tt>-&gt;level</tt> and <tt>-&gt;grpnum</tt> fields are
+used only during initialization and for tracing.
+The <tt>-&gt;grpmask</tt> field is the bitmask counterpart of
+<tt>-&gt;grpnum</tt>, and therefore always has exactly one bit set.
+This mask is used to clear the bit corresponding to this <tt>rcu_node</tt>
+structure in its parent's bitmasks, which are described later.
+Finally, the <tt>-&gt;grplo</tt> and <tt>-&gt;grphi</tt> fields
+contain the lowest and highest numbered CPU served by this
+<tt>rcu_node</tt> structure, respectively.
+
+</p><p>All of these fields are constant, and thus do not require any
+synchronization.
+
+<h5>Synchronization</h5>
+
+<p>This field of the <tt>rcu_node</tt> structure is declared
+as follows:
+
+<pre>
+  1   raw_spinlock_t lock;
+</pre>
+
+<p>This field is used to protect the remaining fields in this structure,
+unless otherwise stated.
+That said, all of the fields in this structure can be accessed without
+locking for tracing purposes.
+Yes, this can result in confusing traces, but better some tracing confusion
+than to be heisenbugged out of existence.
+
+<h5>Grace-Period Tracking</h5>
+
+<p>This portion of the <tt>rcu_node</tt> structure is declared
+as follows:
+
+<pre>
+  1   unsigned long gpnum;
+  2   unsigned long completed;
+</pre>
+
+<p>These fields are the counterparts of the fields of the same name in
+the <tt>rcu_state</tt> structure.
+They each may lag up to one behind their <tt>rcu_state</tt>
+counterparts.
+If a given <tt>rcu_node</tt> structure's <tt>-&gt;gpnum</tt> and
+<tt>-&gt;complete</tt> fields are equal, then this <tt>rcu_node</tt>
+structure believes that RCU is idle.
+Otherwise, as with the <tt>rcu_state</tt> structure,
+the <tt>-&gt;gpnum</tt> field will be one greater than the
+<tt>-&gt;complete</tt> fields, with <tt>-&gt;gpnum</tt>
+indicating which grace period this <tt>rcu_node</tt> believes
+is still being waited for.
+
+</p><p>The <tt>&gt;gpnum</tt> field of each <tt>rcu_node</tt>
+structure is updated at the beginning
+of each grace period, and the <tt>-&gt;completed</tt> fields are
+updated at the end of each grace period.
+
+<h5>Quiescent-State Tracking</h5>
+
+<p>These fields manage the propagation of quiescent states up the
+combining tree.
+
+</p><p>This portion of the <tt>rcu_node</tt> structure has fields
+as follows:
+
+<pre>
+  1   unsigned long qsmask;
+  2   unsigned long expmask;
+  3   unsigned long qsmaskinit;
+  4   unsigned long expmaskinit;
+</pre>
+
+<p>The <tt>-&gt;qsmask</tt> field tracks which of this
+<tt>rcu_node</tt> structure's children still need to report
+quiescent states for the current normal grace period.
+Such children will have a value of 1 in their corresponding bit.
+Note that the leaf <tt>rcu_node</tt> structures should be
+thought of as having <tt>rcu_data</tt> structures as their
+children.
+Similarly, the <tt>-&gt;expmask</tt> field tracks which
+of this <tt>rcu_node</tt> structure's children still need to report
+quiescent states for the current expedited grace period.
+An expedited grace period has
+the same conceptual properties as a normal grace period, but the
+expedited implementation accepts extreme CPU overhead to obtain
+much lower grace-period latency, for example, consuming a few
+tens of microseconds worth of CPU time to reduce grace-period
+duration from milliseconds to tens of microseconds.
+The <tt>-&gt;qsmaskinit</tt> field tracks which of this
+<tt>rcu_node</tt> structure's children cover for at least
+one online CPU.
+This mask is used to initialize <tt>-&gt;qsmask</tt>,
+and <tt>-&gt;expmaskinit</tt> is used to initialize
+<tt>-&gt;expmask</tt> and the beginning of the
+normal and expedited grace periods, respectively.
+
+<table>
+<tr><th>&nbsp;</th></tr>
+<tr><th align="left">Quick Quiz:</th></tr>
+<tr><td>
+	Why are these bitmasks protected by locking?
+	Come on, haven't you heard of atomic instructions???
+</td></tr>
+<tr><th align="left">Answer:</th></tr>
+<tr><td bgcolor="#ffffff"><font color="ffffff">
+	Lockless grace-period computation!  Such a tantalizing possibility!
+	</font>
+
+	<p><font color="ffffff">But consider the following sequence of events:
+	</font>
+
+	<ol>
+	<li>	<font color="ffffff">CPU&nbsp;0 has been in dyntick-idle
+		mode for quite some time.
+		When it wakes up, it notices that the current RCU
+		grace period needs it to report in, so it sets a
+		flag where the scheduling clock interrupt will find it.
+		</font><p>
+	<li>	<font color="ffffff">Meanwhile, CPU&nbsp;1 is running
+		<tt>force_quiescent_state()</tt>,
+		and notices that CPU&nbsp;0 has been in dyntick idle mode,
+		which qualifies as an extended quiescent state.
+		</font><p>
+	<li>	<font color="ffffff">CPU&nbsp;0's scheduling clock
+		interrupt fires in the
+		middle of an RCU read-side critical section, and notices
+		that the RCU core needs something, so commences RCU softirq
+		processing.
+		</font>
+		<p>
+	<li>	<font color="ffffff">CPU&nbsp;0's softirq handler
+		executes and is just about ready
+		to report its quiescent state up the <tt>rcu_node</tt>
+		tree.
+		</font><p>
+	<li>	<font color="ffffff">But CPU&nbsp;1 beats it to the punch,
+		completing the current
+		grace period and starting a new one.
+		</font><p>
+	<li>	<font color="ffffff">CPU&nbsp;0 now reports its quiescent
+		state for the wrong
+		grace period.
+		That grace period might now end before the RCU read-side
+		critical section.
+		If that happens, disaster will ensue.
+		</font>
+	</ol>
+
+	<p><font color="ffffff">So the locking is absolutely required in
+	order to coordinate
+	clearing of the bits with the grace-period numbers in
+	<tt>-&gt;gpnum</tt> and <tt>-&gt;completed</tt>.
+</font></td></tr>
+<tr><td>&nbsp;</td></tr>
+</table>
+
+<h5>Blocked-Task Management</h5>
+
+<p><tt>PREEMPT_RCU</tt> allows tasks to be preempted in the
+midst of their RCU read-side critical sections, and these tasks
+must be tracked explicitly.
+The details of exactly why and how they are tracked will be covered
+in a separate article on RCU read-side processing.
+For now, it is enough to know that the <tt>rcu_node</tt>
+structure tracks them.
+
+<pre>
+  1   struct list_head blkd_tasks;
+  2   struct list_head *gp_tasks;
+  3   struct list_head *exp_tasks;
+  4   bool wait_blkd_tasks;
+</pre>
+
+<p>The <tt>-&gt;blkd_tasks</tt> field is a list header for
+the list of blocked and preempted tasks.
+As tasks undergo context switches within RCU read-side critical
+sections, their <tt>task_struct</tt> structures are enqueued
+(via the <tt>task_struct</tt>'s <tt>-&gt;rcu_node_entry</tt>
+field) onto the head of the <tt>-&gt;blkd_tasks</tt> list for the
+leaf <tt>rcu_node</tt> structure corresponding to the CPU
+on which the outgoing context switch executed.
+As these tasks later exit their RCU read-side critical sections,
+they remove themselves from the list.
+This list is therefore in reverse time order, so that if one of the tasks
+is blocking the current grace period, all subsequent tasks must
+also be blocking that same grace period.
+Therefore, a single pointer into this list suffices to track
+all tasks blocking a given grace period.
+That pointer is stored in <tt>-&gt;gp_tasks</tt> for normal
+grace periods and in <tt>-&gt;exp_tasks</tt> for expedited
+grace periods.
+These last two fields are <tt>NULL</tt> if either there is
+no grace period in flight or if there are no blocked tasks
+preventing that grace period from completing.
+If either of these two pointers is referencing a task that
+removes itself from the <tt>-&gt;blkd_tasks</tt> list,
+then that task must advance the pointer to the next task on
+the list, or set the pointer to <tt>NULL</tt> if there
+are no subsequent tasks on the list.
+
+</p><p>For example, suppose that tasks&nbsp;T1, T2, and&nbsp;T3 are
+all hard-affinitied to the largest-numbered CPU in the system.
+Then if task&nbsp;T1 blocked in an RCU read-side
+critical section, then an expedited grace period started,
+then task&nbsp;T2 blocked in an RCU read-side critical section,
+then a normal grace period started, and finally task&nbsp;3 blocked
+in an RCU read-side critical section, then the state of the
+last leaf <tt>rcu_node</tt> structure's blocked-task list
+would be as shown below:
+
+</p><p><img src="blkd_task.svg" alt="blkd_task.svg" width="60%">
+
+</p><p>Task&nbsp;T1 is blocking both grace periods, task&nbsp;T2 is
+blocking only the normal grace period, and task&nbsp;T3 is blocking
+neither grace period.
+Note that these tasks will not remove themselves from this list
+immediately upon resuming execution.
+They will instead remain on the list until they execute the outermost
+<tt>rcu_read_unlock()</tt> that ends their RCU read-side critical
+section.
+
+<p>
+The <tt>-&gt;wait_blkd_tasks</tt> field indicates whether or not
+the current grace period is waiting on a blocked task.
+
+<h5>Sizing the <tt>rcu_node</tt> Array</h5>
+
+<p>The <tt>rcu_node</tt> array is sized via a series of
+C-preprocessor expressions as follows:
+
+<pre>
+ 1 #ifdef CONFIG_RCU_FANOUT
+ 2 #define RCU_FANOUT CONFIG_RCU_FANOUT
+ 3 #else
+ 4 # ifdef CONFIG_64BIT
+ 5 # define RCU_FANOUT 64
+ 6 # else
+ 7 # define RCU_FANOUT 32
+ 8 # endif
+ 9 #endif
+10
+11 #ifdef CONFIG_RCU_FANOUT_LEAF
+12 #define RCU_FANOUT_LEAF CONFIG_RCU_FANOUT_LEAF
+13 #else
+14 # ifdef CONFIG_64BIT
+15 # define RCU_FANOUT_LEAF 64
+16 # else
+17 # define RCU_FANOUT_LEAF 32
+18 # endif
+19 #endif
+20
+21 #define RCU_FANOUT_1        (RCU_FANOUT_LEAF)
+22 #define RCU_FANOUT_2        (RCU_FANOUT_1 * RCU_FANOUT)
+23 #define RCU_FANOUT_3        (RCU_FANOUT_2 * RCU_FANOUT)
+24 #define RCU_FANOUT_4        (RCU_FANOUT_3 * RCU_FANOUT)
+25
+26 #if NR_CPUS &lt;= RCU_FANOUT_1
+27 #  define RCU_NUM_LVLS        1
+28 #  define NUM_RCU_LVL_0        1
+29 #  define NUM_RCU_NODES        NUM_RCU_LVL_0
+30 #  define NUM_RCU_LVL_INIT    { NUM_RCU_LVL_0 }
+31 #  define RCU_NODE_NAME_INIT  { "rcu_node_0" }
+32 #  define RCU_FQS_NAME_INIT   { "rcu_node_fqs_0" }
+33 #  define RCU_EXP_NAME_INIT   { "rcu_node_exp_0" }
+34 #elif NR_CPUS &lt;= RCU_FANOUT_2
+35 #  define RCU_NUM_LVLS        2
+36 #  define NUM_RCU_LVL_0        1
+37 #  define NUM_RCU_LVL_1        DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_1)
+38 #  define NUM_RCU_NODES        (NUM_RCU_LVL_0 + NUM_RCU_LVL_1)
+39 #  define NUM_RCU_LVL_INIT    { NUM_RCU_LVL_0, NUM_RCU_LVL_1 }
+40 #  define RCU_NODE_NAME_INIT  { "rcu_node_0", "rcu_node_1" }
+41 #  define RCU_FQS_NAME_INIT   { "rcu_node_fqs_0", "rcu_node_fqs_1" }
+42 #  define RCU_EXP_NAME_INIT   { "rcu_node_exp_0", "rcu_node_exp_1" }
+43 #elif NR_CPUS &lt;= RCU_FANOUT_3
+44 #  define RCU_NUM_LVLS        3
+45 #  define NUM_RCU_LVL_0        1
+46 #  define NUM_RCU_LVL_1        DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_2)
+47 #  define NUM_RCU_LVL_2        DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_1)
+48 #  define NUM_RCU_NODES        (NUM_RCU_LVL_0 + NUM_RCU_LVL_1 + NUM_RCU_LVL_2)
+49 #  define NUM_RCU_LVL_INIT    { NUM_RCU_LVL_0, NUM_RCU_LVL_1, NUM_RCU_LVL_2 }
+50 #  define RCU_NODE_NAME_INIT  { "rcu_node_0", "rcu_node_1", "rcu_node_2" }
+51 #  define RCU_FQS_NAME_INIT   { "rcu_node_fqs_0", "rcu_node_fqs_1", "rcu_node_fqs_2" }
+52 #  define RCU_EXP_NAME_INIT   { "rcu_node_exp_0", "rcu_node_exp_1", "rcu_node_exp_2" }
+53 #elif NR_CPUS &lt;= RCU_FANOUT_4
+54 #  define RCU_NUM_LVLS        4
+55 #  define NUM_RCU_LVL_0        1
+56 #  define NUM_RCU_LVL_1        DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_3)
+57 #  define NUM_RCU_LVL_2        DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_2)
+58 #  define NUM_RCU_LVL_3        DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_1)
+59 #  define NUM_RCU_NODES        (NUM_RCU_LVL_0 + NUM_RCU_LVL_1 + NUM_RCU_LVL_2 + NUM_RCU_LVL_3)
+60 #  define NUM_RCU_LVL_INIT    { NUM_RCU_LVL_0, NUM_RCU_LVL_1, NUM_RCU_LVL_2, NUM_RCU_LVL_3 }
+61 #  define RCU_NODE_NAME_INIT  { "rcu_node_0", "rcu_node_1", "rcu_node_2", "rcu_node_3" }
+62 #  define RCU_FQS_NAME_INIT   { "rcu_node_fqs_0", "rcu_node_fqs_1", "rcu_node_fqs_2", "rcu_node_fqs_3" }
+63 #  define RCU_EXP_NAME_INIT   { "rcu_node_exp_0", "rcu_node_exp_1", "rcu_node_exp_2", "rcu_node_exp_3" }
+64 #else
+65 # error "CONFIG_RCU_FANOUT insufficient for NR_CPUS"
+66 #endif
+</pre>
+
+<p>The maximum number of levels in the <tt>rcu_node</tt> structure
+is currently limited to four, as specified by lines&nbsp;21-24
+and the structure of the subsequent &ldquo;if&rdquo; statement.
+For 32-bit systems, this allows 16*32*32*32=524,288 CPUs, which
+should be sufficient for the next few years at least.
+For 64-bit systems, 16*64*64*64=4,194,304 CPUs is allowed, which
+should see us through the next decade or so.
+This four-level tree also allows kernels built with
+<tt>CONFIG_RCU_FANOUT=8</tt> to support up to 4096 CPUs,
+which might be useful in very large systems having eight CPUs per
+socket (but please note that no one has yet shown any measurable
+performance degradation due to misaligned socket and <tt>rcu_node</tt>
+boundaries).
+In addition, building kernels with a full four levels of <tt>rcu_node</tt>
+tree permits better testing of RCU's combining-tree code.
+
+</p><p>The <tt>RCU_FANOUT</tt> symbol controls how many children
+are permitted at each non-leaf level of the <tt>rcu_node</tt> tree.
+If the <tt>CONFIG_RCU_FANOUT</tt> Kconfig option is not specified,
+it is set based on the word size of the system, which is also
+the Kconfig default.
+
+</p><p>The <tt>RCU_FANOUT_LEAF</tt> symbol controls how many CPUs are
+handled by each leaf <tt>rcu_node</tt> structure.
+Experience has shown that allowing a given leaf <tt>rcu_node</tt>
+structure to handle 64 CPUs, as permitted by the number of bits in
+the <tt>-&gt;qsmask</tt> field on a 64-bit system, results in
+excessive contention for the leaf <tt>rcu_node</tt> structures'
+<tt>-&gt;lock</tt> fields.
+The number of CPUs per leaf <tt>rcu_node</tt> structure is therefore
+limited to 16 given the default value of <tt>CONFIG_RCU_FANOUT_LEAF</tt>.
+If <tt>CONFIG_RCU_FANOUT_LEAF</tt> is unspecified, the value
+selected is based on the word size of the system, just as for
+<tt>CONFIG_RCU_FANOUT</tt>.
+Lines&nbsp;11-19 perform this computation.
+
+</p><p>Lines&nbsp;21-24 compute the maximum number of CPUs supported by
+a single-level (which contains a single <tt>rcu_node</tt> structure),
+two-level, three-level, and four-level <tt>rcu_node</tt> tree,
+respectively, given the fanout specified by <tt>RCU_FANOUT</tt>
+and <tt>RCU_FANOUT_LEAF</tt>.
+These numbers of CPUs are retained in the
+<tt>RCU_FANOUT_1</tt>,
+<tt>RCU_FANOUT_2</tt>,
+<tt>RCU_FANOUT_3</tt>, and
+<tt>RCU_FANOUT_4</tt>
+C-preprocessor variables, respectively.
+
+</p><p>These variables are used to control the C-preprocessor <tt>#if</tt>
+statement spanning lines&nbsp;26-66 that computes the number of
+<tt>rcu_node</tt> structures required for each level of the tree,
+as well as the number of levels required.
+The number of levels is placed in the <tt>NUM_RCU_LVLS</tt>
+C-preprocessor variable by lines&nbsp;27, 35, 44, and&nbsp;54.
+The number of <tt>rcu_node</tt> structures for the topmost level
+of the tree is always exactly one, and this value is unconditionally
+placed into <tt>NUM_RCU_LVL_0</tt> by lines&nbsp;28, 36, 45, and&nbsp;55.
+The rest of the levels (if any) of the <tt>rcu_node</tt> tree
+are computed by dividing the maximum number of CPUs by the
+fanout supported by the number of levels from the current level down,
+rounding up.  This computation is performed by lines&nbsp;37,
+46-47, and&nbsp;56-58.
+Lines&nbsp;31-33, 40-42, 50-52, and&nbsp;62-63 create initializers
+for lockdep lock-class names.
+Finally, lines&nbsp;64-66 produce an error if the maximum number of
+CPUs is too large for the specified fanout.
+
+<h3><a name="The rcu_data Structure">
+The <tt>rcu_data</tt> Structure</a></h3>
+
+<p>The <tt>rcu_data</tt> maintains the per-CPU state for the
+corresponding flavor of RCU.
+The fields in this structure may be accessed only from the corresponding
+CPU (and from tracing) unless otherwise stated.
+This structure is the
+focus of quiescent-state detection and RCU callback queuing.
+It also tracks its relationship to the corresponding leaf
+<tt>rcu_node</tt> structure to allow more-efficient
+propagation of quiescent states up the <tt>rcu_node</tt>
+combining tree.
+Like the <tt>rcu_node</tt> structure, it provides a local
+copy of the grace-period information to allow for-free
+synchronized
+access to this information from the corresponding CPU.
+Finally, this structure records past dyntick-idle state
+for the corresponding CPU and also tracks statistics.
+
+</p><p>The <tt>rcu_data</tt> structure's fields are discussed,
+singly and in groups, in the following sections.
+
+<h5>Connection to Other Data Structures</h5>
+
+<p>This portion of the <tt>rcu_data</tt> structure is declared
+as follows:
+
+<pre>
+  1   int cpu;
+  2   struct rcu_state *rsp;
+  3   struct rcu_node *mynode;
+  4   struct rcu_dynticks *dynticks;
+  5   unsigned long grpmask;
+  6   bool beenonline;
+</pre>
+
+<p>The <tt>-&gt;cpu</tt> field contains the number of the
+corresponding CPU, the <tt>-&gt;rsp</tt> pointer references
+the corresponding <tt>rcu_state</tt> structure (and is most frequently
+used to locate the name of the corresponding flavor of RCU for tracing),
+and the <tt>-&gt;mynode</tt> field references the corresponding
+<tt>rcu_node</tt> structure.
+The <tt>-&gt;mynode</tt> is used to propagate quiescent states
+up the combining tree.
+<p>The <tt>-&gt;dynticks</tt> pointer references the
+<tt>rcu_dynticks</tt> structure corresponding to this
+CPU.
+Recall that a single per-CPU instance of the <tt>rcu_dynticks</tt>
+structure is shared among all flavors of RCU.
+These first four fields are constant and therefore require not
+synchronization.
+
+</p><p>The <tt>-&gt;grpmask</tt> field indicates the bit in
+the <tt>-&gt;mynode-&gt;qsmask</tt> corresponding to this
+<tt>rcu_data</tt> structure, and is also used when propagating
+quiescent states.
+The <tt>-&gt;beenonline</tt> flag is set whenever the corresponding
+CPU comes online, which means that the debugfs tracing need not dump
+out any <tt>rcu_data</tt> structure for which this flag is not set.
+
+<h5>Quiescent-State and Grace-Period Tracking</h5>
+
+<p>This portion of the <tt>rcu_data</tt> structure is declared
+as follows:
+
+<pre>
+  1   unsigned long completed;
+  2   unsigned long gpnum;
+  3   bool cpu_no_qs;
+  4   bool core_needs_qs;
+  5   bool gpwrap;
+  6   unsigned long rcu_qs_ctr_snap;
+</pre>
+
+<p>The <tt>completed</tt> and <tt>gpnum</tt>
+fields are the counterparts of the fields of the same name
+in the <tt>rcu_state</tt> and <tt>rcu_node</tt> structures.
+They may each lag up to one behind their <tt>rcu_node</tt>
+counterparts, but in <tt>CONFIG_NO_HZ_IDLE</tt> and
+<tt>CONFIG_NO_HZ_FULL</tt> kernels can lag
+arbitrarily far behind for CPUs in dyntick-idle mode (but these counters
+will catch up upon exit from dyntick-idle mode).
+If a given <tt>rcu_data</tt> structure's <tt>-&gt;gpnum</tt> and
+<tt>-&gt;complete</tt> fields are equal, then this <tt>rcu_data</tt>
+structure believes that RCU is idle.
+Otherwise, as with the <tt>rcu_state</tt> and <tt>rcu_node</tt>
+structure,
+the <tt>-&gt;gpnum</tt> field will be one greater than the
+<tt>-&gt;complete</tt> fields, with <tt>-&gt;gpnum</tt>
+indicating which grace period this <tt>rcu_data</tt> believes
+is still being waited for.
+
+<table>
+<tr><th>&nbsp;</th></tr>
+<tr><th align="left">Quick Quiz:</th></tr>
+<tr><td>
+	All this replication of the grace period numbers can only cause
+	massive confusion.
+	Why not just keep a global pair of counters and be done with it???
+</td></tr>
+<tr><th align="left">Answer:</th></tr>
+<tr><td bgcolor="#ffffff"><font color="ffffff">
+	Because if there was only a single global pair of grace-period
+	numbers, there would need to be a single global lock to allow
+	safely accessing and updating them.
+	And if we are not going to have a single global lock, we need
+	to carefully manage the numbers on a per-node basis.
+	Recall from the answer to a previous Quick Quiz that the consequences
+	of applying a previously sampled quiescent state to the wrong
+	grace period are quite severe.
+</font></td></tr>
+<tr><td>&nbsp;</td></tr>
+</table>
+
+<p>The <tt>-&gt;cpu_no_qs</tt> flag indicates that the
+CPU has not yet passed through a quiescent state,
+while the <tt>-&gt;core_needs_qs</tt> flag indicates that the
+RCU core needs a quiescent state from the corresponding CPU.
+The <tt>-&gt;gpwrap</tt> field indicates that the corresponding
+CPU has remained idle for so long that the <tt>completed</tt>
+and <tt>gpnum</tt> counters are in danger of overflow, which
+will cause the CPU to disregard the values of its counters on
+its next exit from idle.
+Finally, the <tt>rcu_qs_ctr_snap</tt> field is used to detect
+cases where a given operation has resulted in a quiescent state
+for all flavors of RCU, for example, <tt>cond_resched_rcu_qs()</tt>.
+
+<h5>RCU Callback Handling</h5>
+
+<p>In the absence of CPU-hotplug events, RCU callbacks are invoked by
+the same CPU that registered them.
+This is strictly a cache-locality optimization: callbacks can and
+do get invoked on CPUs other than the one that registered them.
+After all, if the CPU that registered a given callback has gone
+offline before the callback can be invoked, there really is no other
+choice.
+
+</p><p>This portion of the <tt>rcu_data</tt> structure is declared
+as follows:
+
+<pre>
+ 1 struct rcu_head *nxtlist;
+ 2 struct rcu_head **nxttail[RCU_NEXT_SIZE];
+ 3 unsigned long nxtcompleted[RCU_NEXT_SIZE];
+ 4 long qlen_lazy;
+ 5 long qlen;
+ 6 long qlen_last_fqs_check;
+ 7 unsigned long n_force_qs_snap;
+ 8 unsigned long n_cbs_invoked;
+ 9 unsigned long n_cbs_orphaned;
+10 unsigned long n_cbs_adopted;
+11 long blimit;
+</pre>
+
+<p>The <tt>-&gt;nxtlist</tt> pointer and the
+<tt>-&gt;nxttail[]</tt> array form a four-segment list with
+older callbacks near the head and newer ones near the tail.
+Each segment contains callbacks with the corresponding relationship
+to the current grace period.
+The pointer out of the end of each of the four segments is referenced
+by the element of the <tt>-&gt;nxttail[]</tt> array indexed by
+<tt>RCU_DONE_TAIL</tt> (for callbacks handled by a prior grace period),
+<tt>RCU_WAIT_TAIL</tt> (for callbacks waiting on the current grace period),
+<tt>RCU_NEXT_READY_TAIL</tt> (for callbacks that will wait on the next
+grace period), and
+<tt>RCU_NEXT_TAIL</tt> (for callbacks that are not yet associated
+with a specific grace period)
+respectively, as shown in the following figure.
+
+</p><p><img src="nxtlist.svg" alt="nxtlist.svg" width="40%">
+
+</p><p>In this figure, the <tt>-&gt;nxtlist</tt> pointer references the
+first
+RCU callback in the list.
+The <tt>-&gt;nxttail[RCU_DONE_TAIL]</tt> array element references
+the <tt>-&gt;nxtlist</tt> pointer itself, indicating that none
+of the callbacks is ready to invoke.
+The <tt>-&gt;nxttail[RCU_WAIT_TAIL]</tt> array element references callback
+CB&nbsp;2's <tt>-&gt;next</tt> pointer, which indicates that
+CB&nbsp;1 and CB&nbsp;2 are both waiting on the current grace period.
+The <tt>-&gt;nxttail[RCU_NEXT_READY_TAIL]</tt> array element
+references the same RCU callback that <tt>-&gt;nxttail[RCU_WAIT_TAIL]</tt>
+does, which indicates that there are no callbacks waiting on the next
+RCU grace period.
+The <tt>-&gt;nxttail[RCU_NEXT_TAIL]</tt> array element references
+CB&nbsp;4's <tt>-&gt;next</tt> pointer, indicating that all the
+remaining RCU callbacks have not yet been assigned to an RCU grace
+period.
+Note that the <tt>-&gt;nxttail[RCU_NEXT_TAIL]</tt> array element
+always references the last RCU callback's <tt>-&gt;next</tt> pointer
+unless the callback list is empty, in which case it references
+the <tt>-&gt;nxtlist</tt> pointer.
+
+</p><p>CPUs advance their callbacks from the
+<tt>RCU_NEXT_TAIL</tt> to the <tt>RCU_NEXT_READY_TAIL</tt> to the
+<tt>RCU_WAIT_TAIL</tt> to the <tt>RCU_DONE_TAIL</tt> list segments
+as grace periods advance.
+The CPU advances the callbacks in its <tt>rcu_data</tt> structure
+whenever it notices that another RCU grace period has completed.
+The CPU detects the completion of an RCU grace period by noticing
+that the value of its <tt>rcu_data</tt> structure's
+<tt>-&gt;completed</tt> field differs from that of its leaf
+<tt>rcu_node</tt> structure.
+Recall that each <tt>rcu_node</tt> structure's
+<tt>-&gt;completed</tt> field is updated at the end of each
+grace period.
+
+</p><p>The <tt>-&gt;nxtcompleted[]</tt> array records grace-period
+numbers corresponding to the list segments.
+This allows CPUs that go idle for extended periods to determine
+which of their callbacks are ready to be invoked after reawakening.
+
+</p><p>The <tt>-&gt;qlen</tt> counter contains the number of
+callbacks in <tt>-&gt;nxtlist</tt>, and the
+<tt>-&gt;qlen_lazy</tt> contains the number of those callbacks that
+are known to only free memory, and whose invocation can therefore
+be safely deferred.
+The <tt>-&gt;qlen_last_fqs_check</tt> and
+<tt>-&gt;n_force_qs_snap</tt> coordinate the forcing of quiescent
+states from <tt>call_rcu()</tt> and friends when callback
+lists grow excessively long.
+
+</p><p>The <tt>-&gt;n_cbs_invoked</tt>,
+<tt>-&gt;n_cbs_orphaned</tt>, and <tt>-&gt;n_cbs_adopted</tt>
+fields count the number of callbacks invoked,
+sent to other CPUs when this CPU goes offline,
+and received from other CPUs when those other CPUs go offline.
+Finally, the <tt>-&gt;blimit</tt> counter is the maximum number of
+RCU callbacks that may be invoked at a given time.
+
+<h5>Dyntick-Idle Handling</h5>
+
+<p>This portion of the <tt>rcu_data</tt> structure is declared
+as follows:
+
+<pre>
+  1   int dynticks_snap;
+  2   unsigned long dynticks_fqs;
+</pre>
+
+The <tt>-&gt;dynticks_snap</tt> field is used to take a snapshot
+of the corresponding CPU's dyntick-idle state when forcing
+quiescent states, and is therefore accessed from other CPUs.
+Finally, the <tt>-&gt;dynticks_fqs</tt> field is used to
+count the number of times this CPU is determined to be in
+dyntick-idle state, and is used for tracing and debugging purposes.
+
+<h3><a name="The rcu_dynticks Structure">
+The <tt>rcu_dynticks</tt> Structure</a></h3>
+
+<p>The <tt>rcu_dynticks</tt> maintains the per-CPU dyntick-idle state
+for the corresponding CPU.
+Unlike the other structures, <tt>rcu_dynticks</tt> is not
+replicated over the different flavors of RCU.
+The fields in this structure may be accessed only from the corresponding
+CPU (and from tracing) unless otherwise stated.
+Its fields are as follows:
+
+<pre>
+  1   int dynticks_nesting;
+  2   int dynticks_nmi_nesting;
+  3   atomic_t dynticks;
+</pre>
+
+<p>The <tt>-&gt;dynticks_nesting</tt> field counts the
+nesting depth of normal interrupts.
+In addition, this counter is incremented when exiting dyntick-idle
+mode and decremented when entering it.
+This counter can therefore be thought of as counting the number
+of reasons why this CPU cannot be permitted to enter dyntick-idle
+mode, aside from non-maskable interrupts (NMIs).
+NMIs are counted by the <tt>-&gt;dynticks_nmi_nesting</tt>
+field, except that NMIs that interrupt non-dyntick-idle execution
+are not counted.
+
+</p><p>Finally, the <tt>-&gt;dynticks</tt> field counts the corresponding
+CPU's transitions to and from dyntick-idle mode, so that this counter
+has an even value when the CPU is in dyntick-idle mode and an odd
+value otherwise.
+
+<table>
+<tr><th>&nbsp;</th></tr>
+<tr><th align="left">Quick Quiz:</th></tr>
+<tr><td>
+	Why not just count all NMIs?
+	Wouldn't that be simpler and less error prone?
+</td></tr>
+<tr><th align="left">Answer:</th></tr>
+<tr><td bgcolor="#ffffff"><font color="ffffff">
+	It seems simpler only until you think hard about how to go about
+	updating the <tt>rcu_dynticks</tt> structure's
+	<tt>-&gt;dynticks</tt> field.
+</font></td></tr>
+<tr><td>&nbsp;</td></tr>
+</table>
+
+<p>Additional fields are present for some special-purpose
+builds, and are discussed separately.
+
+<h3><a name="The rcu_head Structure">
+The <tt>rcu_head</tt> Structure</a></h3>
+
+<p>Each <tt>rcu_head</tt> structure represents an RCU callback.
+These structures are normally embedded within RCU-protected data
+structures whose algorithms use asynchronous grace periods.
+In contrast, when using algorithms that block waiting for RCU grace periods,
+RCU users need not provide <tt>rcu_head</tt> structures.
+
+</p><p>The <tt>rcu_head</tt> structure has fields as follows:
+
+<pre>
+  1   struct rcu_head *next;
+  2   void (*func)(struct rcu_head *head);
+</pre>
+
+<p>The <tt>-&gt;next</tt> field is used
+to link the <tt>rcu_head</tt> structures together in the
+lists within the <tt>rcu_data</tt> structures.
+The <tt>-&gt;func</tt> field is a pointer to the function
+to be called when the callback is ready to be invoked, and
+this function is passed a pointer to the <tt>rcu_head</tt>
+structure.
+However, <tt>kfree_rcu()</tt> uses the <tt>-&gt;func</tt>
+field to record the offset of the <tt>rcu_head</tt>
+structure within the enclosing RCU-protected data structure.
+
+</p><p>Both of these fields are used internally by RCU.
+From the viewpoint of RCU users, this structure is an
+opaque &ldquo;cookie&rdquo;.
+
+<table>
+<tr><th>&nbsp;</th></tr>
+<tr><th align="left">Quick Quiz:</th></tr>
+<tr><td>
+	Given that the callback function <tt>-&gt;func</tt>
+	is passed a pointer to the <tt>rcu_head</tt> structure,
+	how is that function supposed to find the beginning of the
+	enclosing RCU-protected data structure?
+</td></tr>
+<tr><th align="left">Answer:</th></tr>
+<tr><td bgcolor="#ffffff"><font color="ffffff">
+	In actual practice, there is a separate callback function per
+	type of RCU-protected data structure.
+	The callback function can therefore use the <tt>container_of()</tt>
+	macro in the Linux kernel (or other pointer-manipulation facilities
+	in other software environments) to find the beginning of the
+	enclosing structure.
+</font></td></tr>
+<tr><td>&nbsp;</td></tr>
+</table>
+
+<h3><a name="RCU-Specific Fields in the task_struct Structure">
+RCU-Specific Fields in the <tt>task_struct</tt> Structure</a></h3>
+
+<p>The <tt>CONFIG_PREEMPT_RCU</tt> implementation uses some
+additional fields in the <tt>task_struct</tt> structure:
+
+<pre>
+ 1 #ifdef CONFIG_PREEMPT_RCU
+ 2   int rcu_read_lock_nesting;
+ 3   union rcu_special rcu_read_unlock_special;
+ 4   struct list_head rcu_node_entry;
+ 5   struct rcu_node *rcu_blocked_node;
+ 6 #endif /* #ifdef CONFIG_PREEMPT_RCU */
+ 7 #ifdef CONFIG_TASKS_RCU
+ 8   unsigned long rcu_tasks_nvcsw;
+ 9   bool rcu_tasks_holdout;
+10   struct list_head rcu_tasks_holdout_list;
+11   int rcu_tasks_idle_cpu;
+12 #endif /* #ifdef CONFIG_TASKS_RCU */
+</pre>
+
+<p>The <tt>-&gt;rcu_read_lock_nesting</tt> field records the
+nesting level for RCU read-side critical sections, and
+the <tt>-&gt;rcu_read_unlock_special</tt> field is a bitmask
+that records special conditions that require <tt>rcu_read_unlock()</tt>
+to do additional work.
+The <tt>-&gt;rcu_node_entry</tt> field is used to form lists of
+tasks that have blocked within preemptible-RCU read-side critical
+sections and the <tt>-&gt;rcu_blocked_node</tt> field references
+the <tt>rcu_node</tt> structure whose list this task is a member of,
+or <tt>NULL</tt> if it is not blocked within a preemptible-RCU
+read-side critical section.
+
+<p>The <tt>-&gt;rcu_tasks_nvcsw</tt> field tracks the number of
+voluntary context switches that this task had undergone at the
+beginning of the current tasks-RCU grace period,
+<tt>-&gt;rcu_tasks_holdout</tt> is set if the current tasks-RCU
+grace period is waiting on this task, <tt>-&gt;rcu_tasks_holdout_list</tt>
+is a list element enqueuing this task on the holdout list,
+and <tt>-&gt;rcu_tasks_idle_cpu</tt> tracks which CPU this
+idle task is running, but only if the task is currently running,
+that is, if the CPU is currently idle.
+
+<h3><a name="Accessor Functions">
+Accessor Functions</a></h3>
+
+<p>The following listing shows the
+<tt>rcu_get_root()</tt>, <tt>rcu_for_each_node_breadth_first</tt>,
+<tt>rcu_for_each_nonleaf_node_breadth_first()</tt>, and
+<tt>rcu_for_each_leaf_node()</tt> function and macros:
+
+<pre>
+  1 static struct rcu_node *rcu_get_root(struct rcu_state *rsp)
+  2 {
+  3   return &amp;rsp-&gt;node[0];
+  4 }
+  5
+  6 #define rcu_for_each_node_breadth_first(rsp, rnp) \
+  7   for ((rnp) = &amp;(rsp)-&gt;node[0]; \
+  8        (rnp) &lt; &amp;(rsp)-&gt;node[NUM_RCU_NODES]; (rnp)++)
+  9
+ 10 #define rcu_for_each_nonleaf_node_breadth_first(rsp, rnp) \
+ 11   for ((rnp) = &amp;(rsp)-&gt;node[0]; \
+ 12        (rnp) &lt; (rsp)-&gt;level[NUM_RCU_LVLS - 1]; (rnp)++)
+ 13
+ 14 #define rcu_for_each_leaf_node(rsp, rnp) \
+ 15   for ((rnp) = (rsp)-&gt;level[NUM_RCU_LVLS - 1]; \
+ 16        (rnp) &lt; &amp;(rsp)-&gt;node[NUM_RCU_NODES]; (rnp)++)
+</pre>
+
+<p>The <tt>rcu_get_root()</tt> simply returns a pointer to the
+first element of the specified <tt>rcu_state</tt> structure's
+<tt>-&gt;node[]</tt> array, which is the root <tt>rcu_node</tt>
+structure.
+
+</p><p>As noted earlier, the <tt>rcu_for_each_node_breadth_first()</tt>
+macro takes advantage of the layout of the <tt>rcu_node</tt>
+structures in the <tt>rcu_state</tt> structure's
+<tt>-&gt;node[]</tt> array, performing a breadth-first traversal by
+simply traversing the array in order.
+The <tt>rcu_for_each_nonleaf_node_breadth_first()</tt> macro operates
+similarly, but traverses only the first part of the array, thus excluding
+the leaf <tt>rcu_node</tt> structures.
+Finally, the <tt>rcu_for_each_leaf_node()</tt> macro traverses only
+the last part of the array, thus traversing only the leaf
+<tt>rcu_node</tt> structures.
+
+<table>
+<tr><th>&nbsp;</th></tr>
+<tr><th align="left">Quick Quiz:</th></tr>
+<tr><td>
+	What do <tt>rcu_for_each_nonleaf_node_breadth_first()</tt> and
+	<tt>rcu_for_each_leaf_node()</tt> do if the <tt>rcu_node</tt> tree
+	contains only a single node?
+</td></tr>
+<tr><th align="left">Answer:</th></tr>
+<tr><td bgcolor="#ffffff"><font color="ffffff">
+	In the single-node case,
+	<tt>rcu_for_each_nonleaf_node_breadth_first()</tt> is a no-op
+	and <tt>rcu_for_each_leaf_node()</tt> traverses the single node.
+</font></td></tr>
+<tr><td>&nbsp;</td></tr>
+</table>
+
+<h3><a name="Summary">
+Summary</a></h3>
+
+So each flavor of RCU is represented by an <tt>rcu_state</tt> structure,
+which contains a combining tree of <tt>rcu_node</tt> and
+<tt>rcu_data</tt> structures.
+Finally, in <tt>CONFIG_NO_HZ_IDLE</tt> kernels, each CPU's dyntick-idle
+state is tracked by an <tt>rcu_dynticks</tt> structure.
+
+If you made it this far, you are well prepared to read the code
+walkthroughs in the other articles in this series.
+
+<h3><a name="Acknowledgments">
+Acknowledgments</a></h3>
+
+I owe thanks to Cyrill Gorcunov, Mathieu Desnoyers, Dhaval Giani, Paul
+Turner, Abhishek Srivastava, Matt Kowalczyk, and Serge Hallyn
+for helping me get this document into a more human-readable state.
+
+<h3><a name="Legal Statement">
+Legal Statement</a></h3>
+
+<p>This work represents the view of the author and does not necessarily
+represent the view of IBM.
+
+</p><p>Linux is a registered trademark of Linus Torvalds.
+
+</p><p>Other company, product, and service names may be trademarks or
+service marks of others.
+
+</body></html>
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/RCU/Design/Data-Structures/HugeTreeClassicRCU.svg linux-libre-4.7-gnu/Documentation/RCU/Design/Data-Structures/HugeTreeClassicRCU.svg
--- linux-libre-4.6-gnu/Documentation/RCU/Design/Data-Structures/HugeTreeClassicRCU.svg	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/RCU/Design/Data-Structures/HugeTreeClassicRCU.svg	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,939 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Creator: fig2dev Version 3.2 Patchlevel 5e -->
+
+<!-- CreationDate: Wed Dec  9 17:37:22 2015 -->
+
+<!-- Magnification: 3.000 -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="15.1in"
+   height="11.2in"
+   viewBox="-66 -66 18087 13407"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="HugeTreeClassicRCU.fig">
+  <metadata
+     id="metadata224">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs222">
+    <marker
+       inkscape:stockid="Arrow1Mend"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Mend"
+       style="overflow:visible;">
+      <path
+         id="path3982"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
+         transform="scale(0.4) rotate(180) translate(10,0)" />
+    </marker>
+  </defs>
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1134"
+     inkscape:window-height="789"
+     id="namedview220"
+     showgrid="false"
+     inkscape:zoom="0.60515873"
+     inkscape:cx="679.5"
+     inkscape:cy="504"
+     inkscape:window-x="786"
+     inkscape:window-y="24"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="g4" />
+  <g
+     style="stroke-width:.025in; fill:none"
+     id="g4">
+    <!-- Line: box -->
+    <rect
+       x="450"
+       y="0"
+       width="17100"
+       height="8325"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffff00; "
+       id="rect6" />
+    <!-- Line: box -->
+    <rect
+       x="11025"
+       y="3600"
+       width="2700"
+       height="1350"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect8" />
+    <!-- Line: box -->
+    <rect
+       x="4275"
+       y="3600"
+       width="2700"
+       height="1350"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect10" />
+    <!-- Line: box -->
+    <rect
+       x="5400"
+       y="6300"
+       width="2700"
+       height="1350"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect12" />
+    <!-- Line: box -->
+    <rect
+       x="9900"
+       y="6300"
+       width="2700"
+       height="1350"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect14" />
+    <!-- Line: box -->
+    <rect
+       x="14400"
+       y="6300"
+       width="2700"
+       height="1350"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect16" />
+    <!-- Line: box -->
+    <rect
+       x="900"
+       y="6300"
+       width="2700"
+       height="1350"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect18" />
+    <!-- Line: box -->
+    <rect
+       x="7650"
+       y="900"
+       width="2700"
+       height="1350"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect20" />
+    <!-- Line -->
+    <polyline
+       points="3150,9225 3150,7746 "
+       style="stroke:#00d1d1;stroke-width:44.99790066;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline22" />
+    <!-- Arrowhead on XXXpoint 3150 9225 - 3150 7560-->
+    <!-- Circle -->
+    <circle
+       cx="8550"
+       cy="4275"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle26" />
+    <!-- Circle -->
+    <circle
+       cx="9000"
+       cy="4275"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle28" />
+    <!-- Circle -->
+    <circle
+       cx="9450"
+       cy="4275"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle30" />
+    <!-- Line -->
+    <polyline
+       points="6750,6300 8250,5010 "
+       style="stroke:#00d1d1;stroke-width:44.99790066;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline32" />
+    <!-- Arrowhead on XXXpoint 6750 6300 - 8391 4890-->
+    <!-- Line -->
+    <polyline
+       points="11250,6300 9747,5010 "
+       style="stroke:#00d1d1;stroke-width:44.99790066;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline36" />
+    <!-- Arrowhead on XXXpoint 11250 6300 - 9606 4890-->
+    <!-- Circle -->
+    <circle
+       cx="13950"
+       cy="6975"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle40" />
+    <!-- Circle -->
+    <circle
+       cx="13500"
+       cy="6975"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle42" />
+    <!-- Circle -->
+    <circle
+       cx="13050"
+       cy="6975"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle44" />
+    <!-- Circle -->
+    <circle
+       cx="9450"
+       cy="6975"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle46" />
+    <!-- Circle -->
+    <circle
+       cx="9000"
+       cy="6975"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle48" />
+    <!-- Circle -->
+    <circle
+       cx="8550"
+       cy="6975"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle50" />
+    <!-- Circle -->
+    <circle
+       cx="4950"
+       cy="6975"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle52" />
+    <!-- Circle -->
+    <circle
+       cx="4500"
+       cy="6975"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle54" />
+    <!-- Circle -->
+    <circle
+       cx="4050"
+       cy="6975"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle56" />
+    <!-- Circle -->
+    <circle
+       cx="1800"
+       cy="8775"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle58" />
+    <!-- Circle -->
+    <circle
+       cx="2250"
+       cy="8775"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle60" />
+    <!-- Circle -->
+    <circle
+       cx="2700"
+       cy="8775"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle62" />
+    <!-- Circle -->
+    <circle
+       cx="15300"
+       cy="8775"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle64" />
+    <!-- Circle -->
+    <circle
+       cx="15750"
+       cy="8775"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle66" />
+    <!-- Circle -->
+    <circle
+       cx="16200"
+       cy="8775"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle68" />
+    <!-- Circle -->
+    <circle
+       cx="10800"
+       cy="8775"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle70" />
+    <!-- Circle -->
+    <circle
+       cx="11250"
+       cy="8775"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle72" />
+    <!-- Circle -->
+    <circle
+       cx="11700"
+       cy="8775"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle74" />
+    <!-- Circle -->
+    <circle
+       cx="6300"
+       cy="8775"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle76" />
+    <!-- Circle -->
+    <circle
+       cx="6750"
+       cy="8775"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle78" />
+    <!-- Circle -->
+    <circle
+       cx="7200"
+       cy="8775"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle80" />
+    <!-- Line: box -->
+    <rect
+       x="0"
+       y="11475"
+       width="2700"
+       height="1800"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="rect82" />
+    <!-- Line: box -->
+    <rect
+       x="1800"
+       y="9225"
+       width="2700"
+       height="1800"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="rect84" />
+    <!-- Line: box -->
+    <rect
+       x="4500"
+       y="11475"
+       width="2700"
+       height="1800"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="rect86" />
+    <!-- Line: box -->
+    <rect
+       x="6300"
+       y="9270"
+       width="2700"
+       height="1800"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="rect88" />
+    <!-- Line: box -->
+    <rect
+       x="8955"
+       y="11475"
+       width="2700"
+       height="1800"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="rect90" />
+    <!-- Line: box -->
+    <rect
+       x="10755"
+       y="9270"
+       width="2700"
+       height="1800"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="rect92" />
+    <!-- Line: box -->
+    <rect
+       x="13455"
+       y="11475"
+       width="2700"
+       height="1800"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="rect94" />
+    <!-- Line: box -->
+    <rect
+       x="15255"
+       y="9270"
+       width="2700"
+       height="1800"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="rect96" />
+    <!-- Line -->
+    <polyline
+       points="11700,3600 10197,2310 "
+       style="stroke:#00d1d1;stroke-width:44.99790066;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline98" />
+    <!-- Arrowhead on XXXpoint 11700 3600 - 10056 2190-->
+    <!-- Line -->
+    <polyline
+       points="6300,3600 7800,2310 "
+       style="stroke:#00d1d1;stroke-width:44.99790066;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline102" />
+    <!-- Arrowhead on XXXpoint 6300 3600 - 7941 2190-->
+    <!-- Line -->
+    <polyline
+       points="3150,6300 4650,5010 "
+       style="stroke:#00d1d1;stroke-width:44.99790066;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline106" />
+    <!-- Arrowhead on XXXpoint 3150 6300 - 4791 4890-->
+    <!-- Line -->
+    <polyline
+       points="14850,6300 13347,5010 "
+       style="stroke:#00d1d1;stroke-width:44.99790066;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline110" />
+    <!-- Arrowhead on XXXpoint 14850 6300 - 13206 4890-->
+    <!-- Line -->
+    <polyline
+       points="1350,11475 1350,7746 "
+       style="stroke:#00d1d1;stroke-width:44.99790066;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline114" />
+    <!-- Arrowhead on XXXpoint 1350 11475 - 1350 7560-->
+    <!-- Line -->
+    <polyline
+       points="16650,9225 16650,7746 "
+       style="stroke:#00d1d1;stroke-width:44.99790066;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline118" />
+    <!-- Arrowhead on XXXpoint 16650 9225 - 16650 7560-->
+    <!-- Line -->
+    <polyline
+       points="14850,11475 14850,7746 "
+       style="stroke:#00d1d1;stroke-width:44.99790066;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline122" />
+    <!-- Arrowhead on XXXpoint 14850 11475 - 14850 7560-->
+    <!-- Line -->
+    <polyline
+       points="12150,9225 12150,7746 "
+       style="stroke:#00d1d1;stroke-width:44.99790066;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline126" />
+    <!-- Arrowhead on XXXpoint 12150 9225 - 12150 7560-->
+    <!-- Line -->
+    <polyline
+       points="10350,11475 10350,7746 "
+       style="stroke:#00d1d1;stroke-width:44.99790066;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline130" />
+    <!-- Arrowhead on XXXpoint 10350 11475 - 10350 7560-->
+    <!-- Line -->
+    <polyline
+       points="7650,9225 7650,7746 "
+       style="stroke:#00d1d1;stroke-width:44.99790066;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline134" />
+    <!-- Arrowhead on XXXpoint 7650 9225 - 7650 7560-->
+    <!-- Line -->
+    <polyline
+       points="5850,11475 5850,7746 "
+       style="stroke:#00d1d1;stroke-width:44.99790066;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline138" />
+    <!-- Arrowhead on XXXpoint 5850 11475 - 5850 7560-->
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="12375"
+       y="4500"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text142">rcu_node</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="12375"
+       y="4050"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text144">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="5625"
+       y="4050"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text146">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="5625"
+       y="4500"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text148">rcu_node</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="6750"
+       y="6750"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text150">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="6750"
+       y="7200"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text152">rcu_node</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="11250"
+       y="7200"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text154">rcu_node</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="11250"
+       y="6750"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text156">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="15750"
+       y="7200"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text158">rcu_node</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="15750"
+       y="6750"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text160">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="2250"
+       y="6750"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text162">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="2250"
+       y="7200"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text164">rcu_node</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="1350"
+       y="13050"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="324"
+       text-anchor="middle"
+       id="text166">CPU 0</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="1350"
+       y="11925"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text168">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="1350"
+       y="12375"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text170">rcu_data</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="3150"
+       y="10800"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="324"
+       text-anchor="middle"
+       id="text172">CPU 15</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="3150"
+       y="9675"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text174">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="3150"
+       y="10125"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text176">rcu_data</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="5850"
+       y="11925"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text178">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="5850"
+       y="12375"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text180">rcu_data</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="5850"
+       y="13050"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="324"
+       text-anchor="middle"
+       id="text182">CPU 21823</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="7650"
+       y="10845"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="324"
+       text-anchor="middle"
+       id="text184">CPU 21839</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="7650"
+       y="10170"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text186">rcu_data</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="7650"
+       y="9720"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text188">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="10305"
+       y="11925"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text190">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="10305"
+       y="12375"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text192">rcu_data</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="10305"
+       y="13050"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="324"
+       text-anchor="middle"
+       id="text194">CPU 43679</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="12105"
+       y="10845"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="324"
+       text-anchor="middle"
+       id="text196">CPU 43695</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="12105"
+       y="10170"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text198">rcu_data</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="12105"
+       y="9720"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text200">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="14805"
+       y="11925"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text202">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="14805"
+       y="12375"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text204">rcu_data</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="14805"
+       y="13050"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="324"
+       text-anchor="middle"
+       id="text206">CPU 65519</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="16605"
+       y="10845"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="324"
+       text-anchor="middle"
+       id="text208">CPU 65535</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="16605"
+       y="10170"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text210">rcu_data</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="16605"
+       y="9720"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text212">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="675"
+       y="450"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="start"
+       id="text214">struct rcu_state</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="9000"
+       y="1350"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text216">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="9000"
+       y="1800"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text218">rcu_node</text>
+  </g>
+</svg>
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/RCU/Design/Data-Structures/nxtlist.svg linux-libre-4.7-gnu/Documentation/RCU/Design/Data-Structures/nxtlist.svg
--- linux-libre-4.6-gnu/Documentation/RCU/Design/Data-Structures/nxtlist.svg	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/RCU/Design/Data-Structures/nxtlist.svg	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,396 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Creator: fig2dev Version 3.2 Patchlevel 5e -->
+
+<!-- CreationDate: Wed Dec  9 17:39:46 2015 -->
+
+<!-- Magnification: 3.000 -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="10.4in"
+   height="10.4in"
+   viewBox="-66 -66 12507 12507"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="nxtlist.fig">
+  <metadata
+     id="metadata94">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs92">
+    <marker
+       inkscape:stockid="Arrow1Mend"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Mend"
+       style="overflow:visible;">
+      <path
+         id="path3852"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
+         transform="scale(0.4) rotate(180) translate(10,0)" />
+    </marker>
+  </defs>
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="925"
+     inkscape:window-height="928"
+     id="namedview90"
+     showgrid="false"
+     inkscape:zoom="0.80021373"
+     inkscape:cx="467.99997"
+     inkscape:cy="467.99997"
+     inkscape:window-x="948"
+     inkscape:window-y="73"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="g4" />
+  <g
+     style="stroke-width:.025in; fill:none"
+     id="g4">
+    <!-- Line: box -->
+    <rect
+       x="0"
+       y="0"
+       width="7875"
+       height="1125"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#87cfff; "
+       id="rect6" />
+    <!-- Line: box -->
+    <rect
+       x="0"
+       y="1125"
+       width="7875"
+       height="1125"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#87cfff; "
+       id="rect8" />
+    <!-- Line: box -->
+    <rect
+       x="0"
+       y="2250"
+       width="7875"
+       height="1125"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#87cfff; "
+       id="rect10" />
+    <!-- Line: box -->
+    <rect
+       x="0"
+       y="3375"
+       width="7875"
+       height="1125"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#87cfff; "
+       id="rect12" />
+    <!-- Line: box -->
+    <rect
+       x="0"
+       y="4500"
+       width="7875"
+       height="1125"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#87cfff; "
+       id="rect14" />
+    <!-- Line: box -->
+    <rect
+       x="10575"
+       y="0"
+       width="1800"
+       height="1125"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="rect16" />
+    <!-- Line: box -->
+    <rect
+       x="10575"
+       y="1125"
+       width="1800"
+       height="1125"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="rect18" />
+    <!-- Line -->
+    <polyline
+       points="11475,2250 11475,3276 "
+       style="stroke:#000000;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline20" />
+    <!-- Arrowhead on XXXpoint 11475 2250 - 11475 3465-->
+    <!-- Line: box -->
+    <rect
+       x="10575"
+       y="6750"
+       width="1800"
+       height="1125"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="rect24" />
+    <!-- Line: box -->
+    <rect
+       x="10575"
+       y="7875"
+       width="1800"
+       height="1125"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="rect26" />
+    <!-- Line: box -->
+    <rect
+       x="10575"
+       y="10125"
+       width="1800"
+       height="1125"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="rect28" />
+    <!-- Line: box -->
+    <rect
+       x="10575"
+       y="11250"
+       width="1800"
+       height="1125"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="rect30" />
+    <!-- Line: box -->
+    <rect
+       x="10575"
+       y="3375"
+       width="1800"
+       height="1125"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="rect32" />
+    <!-- Line -->
+    <polyline
+       points="11475,5625 11475,6651 "
+       style="stroke:#000000;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline34" />
+    <!-- Arrowhead on XXXpoint 11475 5625 - 11475 6840-->
+    <!-- Line -->
+    <polyline
+       points="7875,225 10476,225 "
+       style="stroke:#000000;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline38" />
+    <!-- Arrowhead on XXXpoint 7875 225 - 10665 225-->
+    <!-- Line -->
+    <polyline
+       points="7875,1350 9675,1350 9675,675 7971,675 "
+       style="stroke:#000000;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline42" />
+    <!-- Arrowhead on XXXpoint 9675 675 - 7785 675-->
+    <!-- Line -->
+    <polyline
+       points="7875,2475 9675,2475 9675,4725 10476,4725 "
+       style="stroke:#000000;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline46" />
+    <!-- Arrowhead on XXXpoint 9675 4725 - 10665 4725-->
+    <!-- Line -->
+    <polyline
+       points="7875,3600 9225,3600 9225,5175 10476,5175 "
+       style="stroke:#000000;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline50" />
+    <!-- Arrowhead on XXXpoint 9225 5175 - 10665 5175-->
+    <!-- Line -->
+    <polyline
+       points="7875,4725 8775,4725 8775,11475 10476,11475 "
+       style="stroke:#000000;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline54" />
+    <!-- Arrowhead on XXXpoint 8775 11475 - 10665 11475-->
+    <!-- Line: box -->
+    <rect
+       x="10575"
+       y="4500"
+       width="1800"
+       height="1125"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="rect58" />
+    <!-- Line -->
+    <polyline
+       points="11475,9000 11475,10026 "
+       style="stroke:#000000;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline60" />
+    <!-- Arrowhead on XXXpoint 11475 9000 - 11475 10215-->
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="225"
+       y="675"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="324"
+       text-anchor="start"
+       id="text64">nxtlist</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="225"
+       y="1800"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="324"
+       text-anchor="start"
+       id="text66">nxttail[RCU_DONE_TAIL]</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="225"
+       y="2925"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="324"
+       text-anchor="start"
+       id="text68">nxttail[RCU_WAIT_TAIL]</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="225"
+       y="4050"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="324"
+       text-anchor="start"
+       id="text70">nxttail[RCU_NEXT_READY_TAIL]</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="225"
+       y="5175"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="324"
+       text-anchor="start"
+       id="text72">nxttail[RCU_NEXT_TAIL]</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="11475"
+       y="675"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="324"
+       text-anchor="middle"
+       id="text74">CB 1</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="11475"
+       y="1800"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="324"
+       text-anchor="middle"
+       id="text76">next</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="11475"
+       y="7425"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="324"
+       text-anchor="middle"
+       id="text78">CB 3</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="11475"
+       y="8550"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="324"
+       text-anchor="middle"
+       id="text80">next</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="11475"
+       y="10800"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="324"
+       text-anchor="middle"
+       id="text82">CB 4</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="11475"
+       y="11925"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="324"
+       text-anchor="middle"
+       id="text84">next</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="11475"
+       y="4050"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="324"
+       text-anchor="middle"
+       id="text86">CB 2</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="11475"
+       y="5175"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="324"
+       text-anchor="middle"
+       id="text88">next</text>
+  </g>
+</svg>
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/RCU/Design/Data-Structures/TreeLevel.svg linux-libre-4.7-gnu/Documentation/RCU/Design/Data-Structures/TreeLevel.svg
--- linux-libre-4.6-gnu/Documentation/RCU/Design/Data-Structures/TreeLevel.svg	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/RCU/Design/Data-Structures/TreeLevel.svg	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,828 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Creator: fig2dev Version 3.2 Patchlevel 5e -->
+
+<!-- CreationDate: Wed Dec  9 17:41:29 2015 -->
+
+<!-- Magnification: 3.000 -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="17.7in"
+   height="10.4in"
+   viewBox="-66 -66 21237 12507"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="TreeLevel.fig">
+  <metadata
+     id="metadata216">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs214">
+    <marker
+       inkscape:stockid="Arrow1Mend"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Mend"
+       style="overflow:visible;">
+      <path
+         id="path3974"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
+         transform="scale(0.4) rotate(180) translate(10,0)" />
+    </marker>
+  </defs>
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1023"
+     inkscape:window-height="1148"
+     id="namedview212"
+     showgrid="false"
+     inkscape:zoom="0.55869424"
+     inkscape:cx="796.50006"
+     inkscape:cy="467.99997"
+     inkscape:window-x="897"
+     inkscape:window-y="24"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="g4" />
+  <g
+     style="stroke-width:.025in; fill:none"
+     id="g4">
+    <!-- Line: box -->
+    <rect
+       x="0"
+       y="0"
+       width="20655"
+       height="8325"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffff00; "
+       id="rect6" />
+    <!-- Line: box -->
+    <rect
+       x="14130"
+       y="3600"
+       width="2700"
+       height="1350"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect8" />
+    <!-- Line: box -->
+    <rect
+       x="7380"
+       y="3600"
+       width="2700"
+       height="1350"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect10" />
+    <!-- Line: box -->
+    <rect
+       x="8505"
+       y="6300"
+       width="2700"
+       height="1350"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect12" />
+    <!-- Line: box -->
+    <rect
+       x="13005"
+       y="6300"
+       width="2700"
+       height="1350"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect14" />
+    <!-- Line: box -->
+    <rect
+       x="17505"
+       y="6300"
+       width="2700"
+       height="1350"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect16" />
+    <!-- Line: box -->
+    <rect
+       x="4005"
+       y="6300"
+       width="2700"
+       height="1350"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect18" />
+    <!-- Line: box -->
+    <rect
+       x="10755"
+       y="900"
+       width="2700"
+       height="1350"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect20" />
+    <!-- Line -->
+    <polyline
+       points="6255,9225 6255,7746 "
+       style="stroke:#00d1d1;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline22" />
+    <!-- Arrowhead on XXXpoint 6255 9225 - 6255 7560-->
+    <!-- Circle -->
+    <circle
+       cx="11655"
+       cy="4275"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle26" />
+    <!-- Circle -->
+    <circle
+       cx="12105"
+       cy="4275"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle28" />
+    <!-- Circle -->
+    <circle
+       cx="12555"
+       cy="4275"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle30" />
+    <!-- Line -->
+    <polyline
+       points="9855,6300 11355,5010 "
+       style="stroke:#00d1d1;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline32" />
+    <!-- Arrowhead on XXXpoint 9855 6300 - 11496 4890-->
+    <!-- Line -->
+    <polyline
+       points="14355,6300 12852,5010 "
+       style="stroke:#00d1d1;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline36" />
+    <!-- Arrowhead on XXXpoint 14355 6300 - 12711 4890-->
+    <!-- Circle -->
+    <circle
+       cx="17055"
+       cy="6975"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle40" />
+    <!-- Circle -->
+    <circle
+       cx="16605"
+       cy="6975"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle42" />
+    <!-- Circle -->
+    <circle
+       cx="16155"
+       cy="6975"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle44" />
+    <!-- Circle -->
+    <circle
+       cx="12555"
+       cy="6975"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle46" />
+    <!-- Circle -->
+    <circle
+       cx="12105"
+       cy="6975"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle48" />
+    <!-- Circle -->
+    <circle
+       cx="11655"
+       cy="6975"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle50" />
+    <!-- Circle -->
+    <circle
+       cx="8055"
+       cy="6975"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle52" />
+    <!-- Circle -->
+    <circle
+       cx="7605"
+       cy="6975"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle54" />
+    <!-- Circle -->
+    <circle
+       cx="7155"
+       cy="6975"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle56" />
+    <!-- Circle -->
+    <circle
+       cx="4905"
+       cy="8775"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle58" />
+    <!-- Circle -->
+    <circle
+       cx="5355"
+       cy="8775"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle60" />
+    <!-- Circle -->
+    <circle
+       cx="5805"
+       cy="8775"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle62" />
+    <!-- Circle -->
+    <circle
+       cx="18405"
+       cy="8775"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle64" />
+    <!-- Circle -->
+    <circle
+       cx="18855"
+       cy="8775"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle66" />
+    <!-- Circle -->
+    <circle
+       cx="19305"
+       cy="8775"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle68" />
+    <!-- Circle -->
+    <circle
+       cx="13905"
+       cy="8775"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle70" />
+    <!-- Circle -->
+    <circle
+       cx="14355"
+       cy="8775"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle72" />
+    <!-- Circle -->
+    <circle
+       cx="14805"
+       cy="8775"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle74" />
+    <!-- Circle -->
+    <circle
+       cx="9405"
+       cy="8775"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle76" />
+    <!-- Circle -->
+    <circle
+       cx="9855"
+       cy="8775"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle78" />
+    <!-- Circle -->
+    <circle
+       cx="10305"
+       cy="8775"
+       r="114"
+       style="fill:#000000;stroke:#000000;stroke-width:21;"
+       id="circle80" />
+    <!-- Line: box -->
+    <rect
+       x="225"
+       y="1125"
+       width="3150"
+       height="1125"
+       rx="0"
+       style="stroke:#000000;stroke-width:21; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffffff; "
+       id="rect82" />
+    <!-- Line: box -->
+    <rect
+       x="225"
+       y="2250"
+       width="3150"
+       height="1125"
+       rx="0"
+       style="stroke:#000000;stroke-width:21; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffffff; "
+       id="rect84" />
+    <!-- Line: box -->
+    <rect
+       x="225"
+       y="3375"
+       width="3150"
+       height="1125"
+       rx="0"
+       style="stroke:#000000;stroke-width:21; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffffff; "
+       id="rect86" />
+    <!-- Line -->
+    <polyline
+       points="14805,3600 13302,2310 "
+       style="stroke:#00d1d1;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline88" />
+    <!-- Arrowhead on XXXpoint 14805 3600 - 13161 2190-->
+    <!-- Line -->
+    <polyline
+       points="9405,3600 10905,2310 "
+       style="stroke:#00d1d1;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline92" />
+    <!-- Arrowhead on XXXpoint 9405 3600 - 11046 2190-->
+    <!-- Line -->
+    <polyline
+       points="6255,6300 7755,5010 "
+       style="stroke:#00d1d1;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline96" />
+    <!-- Arrowhead on XXXpoint 6255 6300 - 7896 4890-->
+    <!-- Line -->
+    <polyline
+       points="17955,6300 16452,5010 "
+       style="stroke:#00d1d1;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline100" />
+    <!-- Arrowhead on XXXpoint 17955 6300 - 16311 4890-->
+    <!-- Line -->
+    <polyline
+       points="4455,11025 4455,7746 "
+       style="stroke:#00d1d1;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline104" />
+    <!-- Arrowhead on XXXpoint 4455 11025 - 4455 7560-->
+    <!-- Line -->
+    <polyline
+       points="19755,9225 19755,7746 "
+       style="stroke:#00d1d1;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline108" />
+    <!-- Arrowhead on XXXpoint 19755 9225 - 19755 7560-->
+    <!-- Line -->
+    <polyline
+       points="17955,11025 17955,7746 "
+       style="stroke:#00d1d1;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline112" />
+    <!-- Arrowhead on XXXpoint 17955 11025 - 17955 7560-->
+    <!-- Line -->
+    <polyline
+       points="15255,9225 15255,7746 "
+       style="stroke:#00d1d1;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline116" />
+    <!-- Arrowhead on XXXpoint 15255 9225 - 15255 7560-->
+    <!-- Line -->
+    <polyline
+       points="13455,11025 13455,7746 "
+       style="stroke:#00d1d1;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline120" />
+    <!-- Arrowhead on XXXpoint 13455 11025 - 13455 7560-->
+    <!-- Line -->
+    <polyline
+       points="10755,9225 10755,7746 "
+       style="stroke:#00d1d1;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline124" />
+    <!-- Arrowhead on XXXpoint 10755 9225 - 10755 7560-->
+    <!-- Line -->
+    <polyline
+       points="8955,11025 8955,7746 "
+       style="stroke:#00d1d1;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline128" />
+    <!-- Arrowhead on XXXpoint 8955 11025 - 8955 7560-->
+    <!-- Line: box -->
+    <rect
+       x="12105"
+       y="11025"
+       width="2700"
+       height="1350"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="rect132" />
+    <!-- Line: box -->
+    <rect
+       x="13905"
+       y="9225"
+       width="2700"
+       height="1350"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="rect134" />
+    <!-- Line: box -->
+    <rect
+       x="16605"
+       y="11025"
+       width="2700"
+       height="1350"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="rect136" />
+    <!-- Line: box -->
+    <rect
+       x="18405"
+       y="9225"
+       width="2700"
+       height="1350"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="rect138" />
+    <!-- Line: box -->
+    <rect
+       x="9405"
+       y="9225"
+       width="2700"
+       height="1350"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="rect140" />
+    <!-- Line: box -->
+    <rect
+       x="7605"
+       y="11025"
+       width="2700"
+       height="1350"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="rect142" />
+    <!-- Line: box -->
+    <rect
+       x="4905"
+       y="9225"
+       width="2700"
+       height="1350"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="rect144" />
+    <!-- Line: box -->
+    <rect
+       x="3105"
+       y="11025"
+       width="2700"
+       height="1350"
+       rx="0"
+       style="stroke:#000000;stroke-width:45; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="rect146" />
+    <!-- Line -->
+    <polyline
+       points="3375,1575 10701,1575 "
+       style="stroke:#000000;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline148" />
+    <!-- Arrowhead on XXXpoint 3375 1575 - 10890 1575-->
+    <!-- Line -->
+    <polyline
+       points="3375,3825 4050,3825 4050,5400 2700,5400 2700,6975 3951,6975 "
+       style="stroke:#000000;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline152" />
+    <!-- Arrowhead on XXXpoint 2700 6975 - 4140 6975-->
+    <!-- Line -->
+    <polyline
+       points="3375,2700 5175,2700 5175,4275 7326,4275 "
+       style="stroke:#000000;stroke-width:45.00382345;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
+       id="polyline156" />
+    <!-- Arrowhead on XXXpoint 5175 4275 - 7515 4275-->
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="15480"
+       y="4500"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text160">rcu_node</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="15480"
+       y="4050"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text162">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="8730"
+       y="4050"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text164">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="8730"
+       y="4500"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text166">rcu_node</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="9855"
+       y="6750"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text168">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="9855"
+       y="7200"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text170">rcu_node</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="14355"
+       y="7200"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text172">rcu_node</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="14355"
+       y="6750"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text174">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="18855"
+       y="7200"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text176">rcu_node</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="18855"
+       y="6750"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text178">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="5355"
+       y="6750"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text180">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="5355"
+       y="7200"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text182">rcu_node</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="450"
+       y="1800"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="324"
+       text-anchor="start"
+       id="text184">-&gt;level[0]</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="450"
+       y="2925"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="324"
+       text-anchor="start"
+       id="text186">-&gt;level[1]</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="450"
+       y="4050"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="324"
+       text-anchor="start"
+       id="text188">-&gt;level[2]</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="12105"
+       y="1350"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text190">struct</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="12105"
+       y="1800"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="middle"
+       id="text192">rcu_node</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="6255"
+       y="10125"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="324"
+       text-anchor="middle"
+       id="text194">CPU 15</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="4455"
+       y="11925"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="324"
+       text-anchor="middle"
+       id="text196">CPU 0</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="19755"
+       y="10125"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="324"
+       text-anchor="middle"
+       id="text198">CPU 65535</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="17955"
+       y="11925"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="324"
+       text-anchor="middle"
+       id="text200">CPU 65519</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="15255"
+       y="10125"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="324"
+       text-anchor="middle"
+       id="text202">CPU 43695</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="13455"
+       y="11925"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="324"
+       text-anchor="middle"
+       id="text204">CPU 43679</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="10755"
+       y="10125"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="324"
+       text-anchor="middle"
+       id="text206">CPU 21839</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="8955"
+       y="11925"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="324"
+       text-anchor="middle"
+       id="text208">CPU 21823</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="225"
+       y="450"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="bold"
+       font-size="288"
+       text-anchor="start"
+       id="text210">struct rcu_state</text>
+  </g>
+</svg>
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/RCU/Design/Data-Structures/TreeMappingLevel.svg linux-libre-4.7-gnu/Documentation/RCU/Design/Data-Structures/TreeMappingLevel.svg
--- linux-libre-4.6-gnu/Documentation/RCU/Design/Data-Structures/TreeMappingLevel.svg	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/RCU/Design/Data-Structures/TreeMappingLevel.svg	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,380 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Creator: fig2dev Version 3.2 Patchlevel 5e -->
+
+<!-- CreationDate: Wed Dec  9 17:45:19 2015 -->
+
+<!-- Magnification: 1.000 -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="3.1in"
+   height="1.8in"
+   viewBox="-12 -12 3699 2124"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="TreeMappingLevel.svg">
+  <metadata
+     id="metadata98">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs96">
+    <marker
+       inkscape:stockid="Arrow2Lend"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow2Lend"
+       style="overflow:visible;">
+      <path
+         id="path3868"
+         style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+         d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+         transform="scale(1.1) rotate(180) translate(1,0)" />
+    </marker>
+  </defs>
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1598"
+     inkscape:window-height="1211"
+     id="namedview94"
+     showgrid="false"
+     inkscape:zoom="5.2508961"
+     inkscape:cx="139.5"
+     inkscape:cy="81"
+     inkscape:window-x="840"
+     inkscape:window-y="122"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="g4" />
+  <g
+     style="stroke-width:.025in; fill:none"
+     id="g4">
+    <!-- Line: box -->
+    <rect
+       x="0"
+       y="0"
+       width="3675"
+       height="2100"
+       rx="0"
+       style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffff00; "
+       id="rect6" />
+    <!-- Line: box -->
+    <rect
+       x="75"
+       y="1350"
+       width="750"
+       height="225"
+       rx="0"
+       style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect8" />
+    <!-- Line: box -->
+    <rect
+       x="75"
+       y="1575"
+       width="750"
+       height="225"
+       rx="0"
+       style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect10" />
+    <!-- Line: box -->
+    <rect
+       x="75"
+       y="1800"
+       width="750"
+       height="225"
+       rx="0"
+       style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect12" />
+    <!-- Arc -->
+    <path
+       style="stroke:#000000;stroke-width:7;stroke-linecap:butt;"
+       d="M 1800,900 A 118 118  0  0  0  1800  1125 "
+       id="path14" />
+    <!-- Arc -->
+    <path
+       style="stroke:#000000;stroke-width:7;stroke-linecap:butt;"
+       d="M 750,900 A 75 75  0  0  0  750  1050 "
+       id="path16" />
+    <!-- Line -->
+    <polyline
+       points="750,900 750,691 "
+       style="stroke:#000000;stroke-width:7.00025806;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
+       id="polyline18" />
+    <!-- Arrowhead on XXXpoint 750 900 - 750 660-->
+    <!-- Line: box -->
+    <rect
+       x="75"
+       y="375"
+       width="375"
+       height="300"
+       rx="0"
+       style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect22" />
+    <!-- Line: box -->
+    <rect
+       x="600"
+       y="375"
+       width="375"
+       height="300"
+       rx="0"
+       style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect24" />
+    <!-- Line: box -->
+    <rect
+       x="1650"
+       y="375"
+       width="375"
+       height="300"
+       rx="0"
+       style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect26" />
+    <!-- Line: box -->
+    <rect
+       x="2175"
+       y="375"
+       width="375"
+       height="300"
+       rx="0"
+       style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect28" />
+    <!-- Line: box -->
+    <rect
+       x="3225"
+       y="375"
+       width="375"
+       height="300"
+       rx="0"
+       style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect30" />
+    <!-- Line -->
+    <polyline
+       points="675,375 675,150 300,150 300,358 "
+       style="stroke:#000000;stroke-width:7.00025806;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
+       id="polyline32" />
+    <!-- Arrowhead on XXXpoint 300 150 - 300 390-->
+    <!-- Line -->
+    <polyline
+       points="1725,375 1725,150 900,150 900,358 "
+       style="stroke:#000000;stroke-width:7.00025806;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
+       id="polyline36" />
+    <!-- Arrowhead on XXXpoint 900 150 - 900 390-->
+    <!-- Line -->
+    <polyline
+       points="2250,375 2250,75 825,75 825,358 "
+       style="stroke:#000000;stroke-width:7.00025806;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
+       id="polyline40" />
+    <!-- Arrowhead on XXXpoint 825 75 - 825 390-->
+    <!-- Line -->
+    <polyline
+       points="2775,675 2775,975 1425,975 1425,691 "
+       style="stroke:#000000;stroke-width:7.00025806;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
+       id="polyline44" />
+    <!-- Arrowhead on XXXpoint 1425 975 - 1425 660-->
+    <!-- Line: box -->
+    <rect
+       x="2700"
+       y="375"
+       width="375"
+       height="300"
+       rx="0"
+       style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect48" />
+    <!-- Line: box -->
+    <rect
+       x="1125"
+       y="375"
+       width="375"
+       height="300"
+       rx="0"
+       style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect50" />
+    <!-- Line -->
+    <polyline
+       points="3300,675 3300,1050 1350,1050 1350,691 "
+       style="stroke:#000000;stroke-width:7.00025806;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
+       id="polyline52" />
+    <!-- Arrowhead on XXXpoint 1350 1050 - 1350 660-->
+    <!-- Line -->
+    <polyline
+       points="825,1425 975,1425 975,1200 225,1200 225,691 "
+       style="stroke:#000000;stroke-width:7.00025806;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
+       id="polyline56" />
+    <!-- Arrowhead on XXXpoint 225 1200 - 225 660-->
+    <!-- Line -->
+    <polyline
+       points="1200,675 1200,975 300,975 300,691 "
+       style="stroke:#000000;stroke-width:7.00025806;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
+       id="polyline60" />
+    <!-- Arrowhead on XXXpoint 300 975 - 300 660-->
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="150"
+       y="1500"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="108"
+       text-anchor="start"
+       id="text64">-&gt;level[0]</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="150"
+       y="1725"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="108"
+       text-anchor="start"
+       id="text66">-&gt;level[1]</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="150"
+       y="1950"
+       fill="#000000"
+       font-family="Helvetica"
+       font-style="normal"
+       font-weight="normal"
+       font-size="108"
+       text-anchor="start"
+       id="text68">-&gt;level[2]</text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="300"
+       y="525"
+       fill="#000000"
+       font-family="Times"
+       font-style="normal"
+       font-weight="normal"
+       font-size="96"
+       text-anchor="middle"
+       id="text70">0:7  </text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="1350"
+       y="525"
+       fill="#000000"
+       font-family="Times"
+       font-style="normal"
+       font-weight="normal"
+       font-size="96"
+       text-anchor="middle"
+       id="text72">4:7  </text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="1875"
+       y="525"
+       fill="#000000"
+       font-family="Times"
+       font-style="normal"
+       font-weight="normal"
+       font-size="96"
+       text-anchor="middle"
+       id="text74">0:1  </text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="2400"
+       y="525"
+       fill="#000000"
+       font-family="Times"
+       font-style="normal"
+       font-weight="normal"
+       font-size="96"
+       text-anchor="middle"
+       id="text76">2:3  </text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="2925"
+       y="525"
+       fill="#000000"
+       font-family="Times"
+       font-style="normal"
+       font-weight="normal"
+       font-size="96"
+       text-anchor="middle"
+       id="text78">4:5  </text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="3450"
+       y="525"
+       fill="#000000"
+       font-family="Times"
+       font-style="normal"
+       font-weight="normal"
+       font-size="96"
+       text-anchor="middle"
+       id="text80">6:7  </text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="825"
+       y="525"
+       fill="#000000"
+       font-family="Times"
+       font-style="normal"
+       font-weight="normal"
+       font-size="96"
+       text-anchor="middle"
+       id="text82">0:3  </text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="3600"
+       y="150"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="normal"
+       font-size="96"
+       text-anchor="end"
+       id="text84">struct rcu_state</text>
+    <!-- Line -->
+    <polyline
+       points="825,1875 1800,1875 1800,1125 "
+       style="stroke:#000000;stroke-width:7.00025806;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:none"
+       id="polyline86" />
+    <!-- Line -->
+    <polyline
+       points="1800,900 1800,691 "
+       style="stroke:#000000;stroke-width:7.00025806;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
+       id="polyline88" />
+    <!-- Arrowhead on XXXpoint 1800 900 - 1800 660-->
+    <!-- Line -->
+    <polyline
+       points="825,1650 1200,1650 1200,1125 750,1125 750,1050 "
+       style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; "
+       id="polyline92" />
+  </g>
+</svg>
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/RCU/Design/Data-Structures/TreeMapping.svg linux-libre-4.7-gnu/Documentation/RCU/Design/Data-Structures/TreeMapping.svg
--- linux-libre-4.6-gnu/Documentation/RCU/Design/Data-Structures/TreeMapping.svg	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/RCU/Design/Data-Structures/TreeMapping.svg	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,305 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Creator: fig2dev Version 3.2 Patchlevel 5e -->
+
+<!-- CreationDate: Wed Dec  9 17:43:22 2015 -->
+
+<!-- Magnification: 1.000 -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="3.1in"
+   height="0.9in"
+   viewBox="-12 -12 3699 1074"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="TreeMapping.fig">
+  <metadata
+     id="metadata66">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs64">
+    <marker
+       inkscape:stockid="Arrow2Lend"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow2Lend"
+       style="overflow:visible;">
+      <path
+         id="path3836"
+         style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+         d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+         transform="scale(1.1) rotate(180) translate(1,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow2Mend"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow2Mend"
+       style="overflow:visible;">
+      <path
+         id="path3842"
+         style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
+         d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
+         transform="scale(0.6) rotate(180) translate(0,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Mend"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Mend"
+       style="overflow:visible;">
+      <path
+         id="path3824"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
+         transform="scale(0.4) rotate(180) translate(10,0)" />
+    </marker>
+  </defs>
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="991"
+     inkscape:window-height="606"
+     id="namedview62"
+     showgrid="false"
+     inkscape:zoom="3.0752688"
+     inkscape:cx="139.5"
+     inkscape:cy="40.5"
+     inkscape:window-x="891"
+     inkscape:window-y="177"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="g4" />
+  <g
+     style="stroke-width:.025in; fill:none"
+     id="g4">
+    <!-- Line: box -->
+    <rect
+       x="0"
+       y="0"
+       width="3675"
+       height="1050"
+       rx="0"
+       style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffff00; "
+       id="rect6" />
+    <!-- Line: box -->
+    <rect
+       x="75"
+       y="375"
+       width="375"
+       height="300"
+       rx="0"
+       style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect8" />
+    <!-- Line: box -->
+    <rect
+       x="600"
+       y="375"
+       width="375"
+       height="300"
+       rx="0"
+       style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect10" />
+    <!-- Line: box -->
+    <rect
+       x="1125"
+       y="375"
+       width="375"
+       height="300"
+       rx="0"
+       style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect12" />
+    <!-- Line: box -->
+    <rect
+       x="1650"
+       y="375"
+       width="375"
+       height="300"
+       rx="0"
+       style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect14" />
+    <!-- Line: box -->
+    <rect
+       x="2175"
+       y="375"
+       width="375"
+       height="300"
+       rx="0"
+       style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect16" />
+    <!-- Line: box -->
+    <rect
+       x="3225"
+       y="375"
+       width="375"
+       height="300"
+       rx="0"
+       style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect18" />
+    <!-- Line -->
+    <polyline
+       points="675,375 675,150 300,150 300,358 "
+       style="stroke:#000000;stroke-width:7.00088889;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
+       id="polyline20" />
+    <!-- Arrowhead on XXXpoint 300 150 - 300 390-->
+    <!-- Line -->
+    <polyline
+       points="1200,675 1200,900 300,900 300,691 "
+       style="stroke:#000000;stroke-width:7.00088889;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
+       id="polyline24" />
+    <!-- Arrowhead on XXXpoint 300 900 - 300 660-->
+    <!-- Line -->
+    <polyline
+       points="1725,375 1725,150 900,150 900,358 "
+       style="stroke:#000000;stroke-width:7.00088889;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
+       id="polyline28" />
+    <!-- Arrowhead on XXXpoint 900 150 - 900 390-->
+    <!-- Line -->
+    <polyline
+       points="2250,375 2250,75 825,75 825,358 "
+       style="stroke:#000000;stroke-width:7.00088889;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
+       id="polyline32" />
+    <!-- Arrowhead on XXXpoint 825 75 - 825 390-->
+    <!-- Line -->
+    <polyline
+       points="2775,675 2775,900 1425,900 1425,691 "
+       style="stroke:#000000;stroke-width:7.00088889;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
+       id="polyline36" />
+    <!-- Arrowhead on XXXpoint 1425 900 - 1425 660-->
+    <!-- Line -->
+    <polyline
+       points="3300,675 3300,975 1350,975 1350,691 "
+       style="stroke:#000000;stroke-width:7.00088889;stroke-linejoin:miter;stroke-linecap:butt;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Lend)"
+       id="polyline40" />
+    <!-- Arrowhead on XXXpoint 1350 975 - 1350 660-->
+    <!-- Line: box -->
+    <rect
+       x="2700"
+       y="375"
+       width="375"
+       height="300"
+       rx="0"
+       style="stroke:#000000;stroke-width:7; stroke-linejoin:miter; stroke-linecap:butt; fill:#ffbfbf; "
+       id="rect44" />
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="300"
+       y="525"
+       fill="#000000"
+       font-family="Times"
+       font-style="normal"
+       font-weight="normal"
+       font-size="96"
+       text-anchor="middle"
+       id="text46">0:7  </text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="1350"
+       y="525"
+       fill="#000000"
+       font-family="Times"
+       font-style="normal"
+       font-weight="normal"
+       font-size="96"
+       text-anchor="middle"
+       id="text48">4:7  </text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="1875"
+       y="525"
+       fill="#000000"
+       font-family="Times"
+       font-style="normal"
+       font-weight="normal"
+       font-size="96"
+       text-anchor="middle"
+       id="text50">0:1  </text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="2400"
+       y="525"
+       fill="#000000"
+       font-family="Times"
+       font-style="normal"
+       font-weight="normal"
+       font-size="96"
+       text-anchor="middle"
+       id="text52">2:3  </text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="2925"
+       y="525"
+       fill="#000000"
+       font-family="Times"
+       font-style="normal"
+       font-weight="normal"
+       font-size="96"
+       text-anchor="middle"
+       id="text54">4:5  </text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="3450"
+       y="525"
+       fill="#000000"
+       font-family="Times"
+       font-style="normal"
+       font-weight="normal"
+       font-size="96"
+       text-anchor="middle"
+       id="text56">6:7  </text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="825"
+       y="525"
+       fill="#000000"
+       font-family="Times"
+       font-style="normal"
+       font-weight="normal"
+       font-size="96"
+       text-anchor="middle"
+       id="text58">0:3  </text>
+    <!-- Text -->
+    <text
+       xml:space="preserve"
+       x="3600"
+       y="150"
+       fill="#000000"
+       font-family="Courier"
+       font-style="normal"
+       font-weight="normal"
+       font-size="96"
+       text-anchor="end"
+       id="text60">struct rcu_state</text>
+  </g>
+</svg>
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/RCU/Design/htmlqqz.sh linux-libre-4.7-gnu/Documentation/RCU/Design/htmlqqz.sh
--- linux-libre-4.6-gnu/Documentation/RCU/Design/htmlqqz.sh	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/RCU/Design/htmlqqz.sh	1969-12-31 19:00:00.000000000 -0500
@@ -1,108 +0,0 @@
-#!/bin/sh
-#
-# Usage: sh htmlqqz.sh file
-#
-# Extracts and converts quick quizzes in a proto-HTML document file.htmlx.
-# Commands, all of which must be on a line by themselves:
-#
-#	"<p>@@QQ@@": Start of a quick quiz.
-#	"<p>@@QQA@@": Start of a quick-quiz answer.
-#	"<p>@@QQE@@": End of a quick-quiz answer, and thus of the quick quiz.
-#	"<p>@@QQAL@@": Place to put quick-quiz answer list.
-#
-# Places the result in file.html.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, you can access it online at
-# http://www.gnu.org/licenses/gpl-2.0.html.
-#
-# Copyright (c) 2013 Paul E. McKenney, IBM Corporation.
-
-fn=$1
-if test ! -r $fn.htmlx
-then
-	echo "Error: $fn.htmlx unreadable."
-	exit 1
-fi
-
-echo "<!-- DO NOT HAND EDIT. -->" > $fn.html
-echo "<!-- Instead, edit $fn.htmlx and run 'sh htmlqqz.sh $fn' -->" >> $fn.html
-awk < $fn.htmlx >> $fn.html '
-
-state == "" && $1 != "<p>@@QQ@@" && $1 != "<p>@@QQAL@@" {
-	print $0;
-	if ($0 ~ /^<p>@@QQ/)
-		print "Bad Quick Quiz command: " NR " (expected <p>@@QQ@@ or <p>@@QQAL@@)." > "/dev/stderr"
-	next;
-}
-
-state == "" && $1 == "<p>@@QQ@@" {
-	qqn++;
-	qqlineno = NR;
-	haveqq = 1;
-	state = "qq";
-	print "<p><a name=\"Quick Quiz " qqn "\"><b>Quick Quiz " qqn "</b>:</a>"
-	next;
-}
-
-state == "qq" && $1 != "<p>@@QQA@@" {
-	qq[qqn] = qq[qqn] $0 "\n";
-	print $0
-	if ($0 ~ /^<p>@@QQ/)
-		print "Bad Quick Quiz command: " NR ". (expected <p>@@QQA@@)" > "/dev/stderr"
-	next;
-}
-
-state == "qq" && $1 == "<p>@@QQA@@" {
-	state = "qqa";
-	print "<br><a href=\"#qq" qqn "answer\">Answer</a>"
-	next;
-}
-
-state == "qqa" && $1 != "<p>@@QQE@@" {
-	qqa[qqn] = qqa[qqn] $0 "\n";
-	if ($0 ~ /^<p>@@QQ/)
-		print "Bad Quick Quiz command: " NR " (expected <p>@@QQE@@)." > "/dev/stderr"
-	next;
-}
-
-state == "qqa" && $1 == "<p>@@QQE@@" {
-	state = "";
-	next;
-}
-
-state == "" && $1 == "<p>@@QQAL@@" {
-	haveqq = "";
-	print "<h3><a name=\"Answers to Quick Quizzes\">"
-	print "Answers to Quick Quizzes</a></h3>"
-	print "";
-	for (i = 1; i <= qqn; i++) {
-		print "<a name=\"qq" i "answer\"></a>"
-		print "<p><b>Quick Quiz " i "</b>:"
-		print qq[i];
-		print "";
-		print "</p><p><b>Answer</b>:"
-		print qqa[i];
-		print "";
-		print "</p><p><a href=\"#Quick%20Quiz%20" i "\"><b>Back to Quick Quiz " i "</b>.</a>"
-		print "";
-	}
-	next;
-}
-
-END {
-	if (state != "")
-		print "Unterminated Quick Quiz: " qqlineno "." > "/dev/stderr"
-	else if (haveqq)
-		print "Missing \"<p>@@QQAL@@\", no Quick Quiz." > "/dev/stderr"
-}'
Binary files linux-libre-4.6-gnu/Documentation/RCU/Design/Requirements/2013-08-is-it-dead.png and linux-libre-4.7-gnu/Documentation/RCU/Design/Requirements/2013-08-is-it-dead.png differ
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/RCU/Design/Requirements/RCUApplicability.svg linux-libre-4.7-gnu/Documentation/RCU/Design/Requirements/RCUApplicability.svg
--- linux-libre-4.6-gnu/Documentation/RCU/Design/Requirements/RCUApplicability.svg	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/RCU/Design/Requirements/RCUApplicability.svg	1969-12-31 19:00:00.000000000 -0500
@@ -1,237 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Creator: fig2dev Version 3.2 Patchlevel 5d -->
-
-<!-- CreationDate: Tue Mar  4 18:34:25 2014 -->
-
-<!-- Magnification: 3.000 -->
-
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="1089.1382"
-   height="668.21368"
-   viewBox="-2121 -36 14554.634 8876.4061"
-   id="svg2"
-   version="1.1"
-   inkscape:version="0.48.3.1 r9886"
-   sodipodi:docname="RCUApplicability.svg">
-  <metadata
-     id="metadata40">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title />
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <defs
-     id="defs38" />
-  <sodipodi:namedview
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1"
-     objecttolerance="10"
-     gridtolerance="10"
-     guidetolerance="10"
-     inkscape:pageopacity="0"
-     inkscape:pageshadow="2"
-     inkscape:window-width="849"
-     inkscape:window-height="639"
-     id="namedview36"
-     showgrid="false"
-     inkscape:zoom="0.51326165"
-     inkscape:cx="544.56912"
-     inkscape:cy="334.10686"
-     inkscape:window-x="149"
-     inkscape:window-y="448"
-     inkscape:window-maximized="0"
-     inkscape:current-layer="g4"
-     fit-margin-top="5"
-     fit-margin-left="5"
-     fit-margin-right="5"
-     fit-margin-bottom="5" />
-  <g
-     style="fill:none;stroke-width:0.025in"
-     id="g4"
-     transform="translate(-2043.6828,14.791398)">
-    <!-- Line: box -->
-    <rect
-       x="0"
-       y="0"
-       width="14400"
-       height="8775"
-       rx="0"
-       style="fill:#ffa1a1;stroke:#000000;stroke-width:21;stroke-linecap:butt;stroke-linejoin:miter"
-       id="rect6" />
-    <!-- Line: box -->
-    <rect
-       x="1350"
-       y="0"
-       width="11700"
-       height="6075"
-       rx="0"
-       style="fill:#ffff00;stroke:#000000;stroke-width:21;stroke-linecap:butt;stroke-linejoin:miter"
-       id="rect8" />
-    <!-- Line: box -->
-    <rect
-       x="2700"
-       y="0"
-       width="9000"
-       height="4275"
-       rx="0"
-       style="fill:#00ff00;stroke:#000000;stroke-width:21;stroke-linecap:butt;stroke-linejoin:miter"
-       id="rect10" />
-    <!-- Line: box -->
-    <rect
-       x="4050"
-       y="0"
-       width="6300"
-       height="2475"
-       rx="0"
-       style="fill:#87cfff;stroke:#000000;stroke-width:21;stroke-linecap:butt;stroke-linejoin:miter"
-       id="rect12" />
-    <!-- Text -->
-    <text
-       xml:space="preserve"
-       x="7200"
-       y="900"
-       font-style="normal"
-       font-weight="normal"
-       font-size="324"
-       id="text14"
-       sodipodi:linespacing="125%"
-       style="font-size:427.63009644px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L"><tspan
-         style="font-size:427.63009644px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L"
-         id="tspan3017">Read-Mostly, Stale &amp;</tspan></text>
-    <!-- Text -->
-    <text
-       xml:space="preserve"
-       x="7200"
-       y="1350"
-       font-style="normal"
-       font-weight="normal"
-       font-size="324"
-       id="text16"
-       sodipodi:linespacing="125%"
-       style="font-size:427.63009644px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L"><tspan
-         style="font-size:427.63009644px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L"
-         id="tspan3019">Inconsistent Data OK</tspan></text>
-    <!-- Text -->
-    <text
-       xml:space="preserve"
-       x="7200"
-       y="1800"
-       font-style="normal"
-       font-weight="normal"
-       font-size="324"
-       id="text18"
-       sodipodi:linespacing="125%"
-       style="font-size:427.63009644px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L"><tspan
-         style="font-size:427.63009644px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L"
-         id="tspan3021">(RCU Works Great!!!)</tspan></text>
-    <!-- Text -->
-    <text
-       xml:space="preserve"
-       x="7200"
-       y="3825"
-       font-style="normal"
-       font-weight="normal"
-       font-size="324"
-       id="text20"
-       sodipodi:linespacing="125%"
-       style="font-size:427.63009644px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L"><tspan
-         style="font-size:427.63009644px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L"
-         id="tspan3023">(RCU Works Well)</tspan></text>
-    <!-- Text -->
-    <text
-       xml:space="preserve"
-       x="7200"
-       y="3375"
-       font-style="normal"
-       font-weight="normal"
-       font-size="324"
-       id="text22"
-       sodipodi:linespacing="125%"
-       style="font-size:427.63009644px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L"><tspan
-         style="font-size:427.63009644px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L"
-         id="tspan3025">Read-Mostly, Need Consistent Data</tspan></text>
-    <!-- Text -->
-    <text
-       xml:space="preserve"
-       x="7200"
-       y="5175"
-       font-style="normal"
-       font-weight="normal"
-       font-size="324"
-       id="text24"
-       sodipodi:linespacing="125%"
-       style="font-size:427.63009644px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L"><tspan
-         style="font-size:427.63009644px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L"
-         id="tspan3027">Read-Write, Need Consistent Data</tspan></text>
-    <!-- Text -->
-    <text
-       xml:space="preserve"
-       x="7200"
-       y="6975"
-       font-style="normal"
-       font-weight="normal"
-       font-size="324"
-       id="text26"
-       style="font-size:427.63009644px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L"
-       sodipodi:linespacing="125%">Update-Mostly, Need Consistent Data</text>
-    <!-- Text -->
-    <text
-       xml:space="preserve"
-       x="7200"
-       y="5625"
-       font-style="normal"
-       font-weight="normal"
-       font-size="324"
-       id="text28"
-       sodipodi:linespacing="125%"
-       style="font-size:427.63009644px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L"><tspan
-         style="font-size:427.63009644px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L"
-         id="tspan3029">(RCU Might Be OK...)</tspan></text>
-    <!-- Text -->
-    <text
-       xml:space="preserve"
-       x="7200"
-       y="7875"
-       font-style="normal"
-       font-weight="normal"
-       font-size="324"
-       id="text30"
-       style="font-size:427.63009644px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L"
-       sodipodi:linespacing="125%">(1) Provide Existence Guarantees For Update-Friendly Mechanisms</text>
-    <!-- Text -->
-    <text
-       xml:space="preserve"
-       x="7200"
-       y="8325"
-       font-style="normal"
-       font-weight="normal"
-       font-size="324"
-       id="text32"
-       style="font-size:427.63009644px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L"
-       sodipodi:linespacing="125%">(2) Provide Wait-Free Read-Side Primitives for Real-Time Use)</text>
-    <!-- Text -->
-    <text
-       xml:space="preserve"
-       x="7200"
-       y="7425"
-       font-style="normal"
-       font-weight="normal"
-       font-size="324"
-       id="text34"
-       style="font-size:427.63009644px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L"
-       sodipodi:linespacing="125%">(RCU is Very Unlikely to be the Right Tool For The Job, But it Can:</text>
-  </g>
-</svg>
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/RCU/Design/Requirements/Requirements.html linux-libre-4.7-gnu/Documentation/RCU/Design/Requirements/Requirements.html
--- linux-libre-4.6-gnu/Documentation/RCU/Design/Requirements/Requirements.html	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/RCU/Design/Requirements/Requirements.html	2016-07-24 15:23:50.000000000 -0400
@@ -1,5 +1,3 @@
-<!-- DO NOT HAND EDIT. -->
-<!-- Instead, edit Documentation/RCU/Design/Requirements/Requirements.htmlx and run 'sh htmlqqz.sh Documentation/RCU/Design/Requirements/Requirements' -->
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
         "http://www.w3.org/TR/html4/loose.dtd">
         <html>
@@ -65,8 +63,8 @@ All that aside, here are the categories
 
 <p>
 This is followed by a <a href="#Summary">summary</a>,
-which is in turn followed by the inevitable
-<a href="#Answers to Quick Quizzes">answers to the quick quizzes</a>.
+however, the answers to each quick quiz immediately follows the quiz.
+Select the big white space with your mouse to see the answer.
 
 <h2><a name="Fundamental Requirements">Fundamental Requirements</a></h2>
 
@@ -153,13 +151,27 @@ Therefore, the outcome:
 </blockquote>
 cannot happen.
 
-<p><a name="Quick Quiz 1"><b>Quick Quiz 1</b>:</a>
-Wait a minute!
-You said that updaters can make useful forward progress concurrently
-with readers, but pre-existing readers will block
-<tt>synchronize_rcu()</tt>!!!
-Just who are you trying to fool???
-<br><a href="#qq1answer">Answer</a>
+<table>
+<tr><th>&nbsp;</th></tr>
+<tr><th align="left">Quick Quiz:</th></tr>
+<tr><td>
+	Wait a minute!
+	You said that updaters can make useful forward progress concurrently
+	with readers, but pre-existing readers will block
+	<tt>synchronize_rcu()</tt>!!!
+	Just who are you trying to fool???
+</td></tr>
+<tr><th align="left">Answer:</th></tr>
+<tr><td bgcolor="#ffffff"><font color="ffffff">
+	First, if updaters do not wish to be blocked by readers, they can use
+	<tt>call_rcu()</tt> or <tt>kfree_rcu()</tt>, which will
+	be discussed later.
+	Second, even when using <tt>synchronize_rcu()</tt>, the other
+	update-side code does run concurrently with readers, whether
+	pre-existing or not.
+</font></td></tr>
+<tr><td>&nbsp;</td></tr>
+</table>
 
 <p>
 This scenario resembles one of the first uses of RCU in
@@ -210,9 +222,20 @@ to guarantee that <tt>do_something()</tt
 with <tt>recovery()</tt>, but with little or no synchronization
 overhead in <tt>do_something_dlm()</tt>.
 
-<p><a name="Quick Quiz 2"><b>Quick Quiz 2</b>:</a>
-Why is the <tt>synchronize_rcu()</tt> on line&nbsp;28 needed?
-<br><a href="#qq2answer">Answer</a>
+<table>
+<tr><th>&nbsp;</th></tr>
+<tr><th align="left">Quick Quiz:</th></tr>
+<tr><td>
+	Why is the <tt>synchronize_rcu()</tt> on line&nbsp;28 needed?
+</td></tr>
+<tr><th align="left">Answer:</th></tr>
+<tr><td bgcolor="#ffffff"><font color="ffffff">
+	Without that extra grace period, memory reordering could result in
+	<tt>do_something_dlm()</tt> executing <tt>do_something()</tt>
+	concurrently with the last bits of <tt>recovery()</tt>.
+</font></td></tr>
+<tr><td>&nbsp;</td></tr>
+</table>
 
 <p>
 In order to avoid fatal problems such as deadlocks,
@@ -332,12 +355,27 @@ It also prevents any number of &ldquo;in
 optimizations, for example, the use of <tt>gp</tt> as a scratch
 location immediately preceding the assignment.
 
-<p><a name="Quick Quiz 3"><b>Quick Quiz 3</b>:</a>
-But <tt>rcu_assign_pointer()</tt> does nothing to prevent the
-two assignments to <tt>p-&gt;a</tt> and <tt>p-&gt;b</tt>
-from being reordered.
-Can't that also cause problems?
-<br><a href="#qq3answer">Answer</a>
+<table>
+<tr><th>&nbsp;</th></tr>
+<tr><th align="left">Quick Quiz:</th></tr>
+<tr><td>
+	But <tt>rcu_assign_pointer()</tt> does nothing to prevent the
+	two assignments to <tt>p-&gt;a</tt> and <tt>p-&gt;b</tt>
+	from being reordered.
+	Can't that also cause problems?
+</td></tr>
+<tr><th align="left">Answer:</th></tr>
+<tr><td bgcolor="#ffffff"><font color="ffffff">
+	No, it cannot.
+	The readers cannot see either of these two fields until
+	the assignment to <tt>gp</tt>, by which time both fields are
+	fully initialized.
+	So reordering the assignments
+	to <tt>p-&gt;a</tt> and <tt>p-&gt;b</tt> cannot possibly
+	cause any problems.
+</font></td></tr>
+<tr><td>&nbsp;</td></tr>
+</table>
 
 <p>
 It is tempting to assume that the reader need not do anything special
@@ -494,11 +532,42 @@ The <tt>rcu_access_pointer()</tt> on lin
 	code protected by the corresponding update-side lock.
 </ol>
 
-<p><a name="Quick Quiz 4"><b>Quick Quiz 4</b>:</a>
-Without the <tt>rcu_dereference()</tt> or the
-<tt>rcu_access_pointer()</tt>, what destructive optimizations
-might the compiler make use of?
-<br><a href="#qq4answer">Answer</a>
+<table>
+<tr><th>&nbsp;</th></tr>
+<tr><th align="left">Quick Quiz:</th></tr>
+<tr><td>
+	Without the <tt>rcu_dereference()</tt> or the
+	<tt>rcu_access_pointer()</tt>, what destructive optimizations
+	might the compiler make use of?
+</td></tr>
+<tr><th align="left">Answer:</th></tr>
+<tr><td bgcolor="#ffffff"><font color="ffffff">
+	Let's start with what happens to <tt>do_something_gp()</tt>
+	if it fails to use <tt>rcu_dereference()</tt>.
+	It could reuse a value formerly fetched from this same pointer.
+	It could also fetch the pointer from <tt>gp</tt> in a byte-at-a-time
+	manner, resulting in <i>load tearing</i>, in turn resulting a bytewise
+	mash-up of two distince pointer values.
+	It might even use value-speculation optimizations, where it makes
+	a wrong guess, but by the time it gets around to checking the
+	value, an update has changed the pointer to match the wrong guess.
+	Too bad about any dereferences that returned pre-initialization garbage
+	in the meantime!
+	</font>
+
+	<p><font color="ffffff">
+	For <tt>remove_gp_synchronous()</tt>, as long as all modifications
+	to <tt>gp</tt> are carried out while holding <tt>gp_lock</tt>,
+	the above optimizations are harmless.
+	However,
+	with <tt>CONFIG_SPARSE_RCU_POINTER=y</tt>,
+	<tt>sparse</tt> will complain if you
+	define <tt>gp</tt> with <tt>__rcu</tt> and then
+	access it without using
+	either <tt>rcu_access_pointer()</tt> or <tt>rcu_dereference()</tt>.
+</font></td></tr>
+<tr><td>&nbsp;</td></tr>
+</table>
 
 <p>
 In short, RCU's publish-subscribe guarantee is provided by the combination
@@ -571,17 +640,156 @@ systems with more than one CPU:
 	<tt>synchronize_rcu()</tt> migrates in the meantime.
 </ol>
 
-<p><a name="Quick Quiz 5"><b>Quick Quiz 5</b>:</a>
-Given that multiple CPUs can start RCU read-side critical sections
-at any time without any ordering whatsoever, how can RCU possibly tell whether
-or not a given RCU read-side critical section starts before a
-given instance of <tt>synchronize_rcu()</tt>?
-<br><a href="#qq5answer">Answer</a>
+<table>
+<tr><th>&nbsp;</th></tr>
+<tr><th align="left">Quick Quiz:</th></tr>
+<tr><td>
+	Given that multiple CPUs can start RCU read-side critical sections
+	at any time without any ordering whatsoever, how can RCU possibly
+	tell whether or not a given RCU read-side critical section starts
+	before a given instance of <tt>synchronize_rcu()</tt>?
+</td></tr>
+<tr><th align="left">Answer:</th></tr>
+<tr><td bgcolor="#ffffff"><font color="ffffff">
+	If RCU cannot tell whether or not a given
+	RCU read-side critical section starts before a
+	given instance of <tt>synchronize_rcu()</tt>,
+	then it must assume that the RCU read-side critical section
+	started first.
+	In other words, a given instance of <tt>synchronize_rcu()</tt>
+	can avoid waiting on a given RCU read-side critical section only
+	if it can prove that <tt>synchronize_rcu()</tt> started first.
+</font></td></tr>
+<tr><td>&nbsp;</td></tr>
+</table>
 
-<p><a name="Quick Quiz 6"><b>Quick Quiz 6</b>:</a>
-The first and second guarantees require unbelievably strict ordering!
-Are all these memory barriers <i> really</i> required?
-<br><a href="#qq6answer">Answer</a>
+<table>
+<tr><th>&nbsp;</th></tr>
+<tr><th align="left">Quick Quiz:</th></tr>
+<tr><td>
+	The first and second guarantees require unbelievably strict ordering!
+	Are all these memory barriers <i> really</i> required?
+</td></tr>
+<tr><th align="left">Answer:</th></tr>
+<tr><td bgcolor="#ffffff"><font color="ffffff">
+	Yes, they really are required.
+	To see why the first guarantee is required, consider the following
+	sequence of events:
+	</font>
+
+	<ol>
+	<li>	<font color="ffffff">
+		CPU 1: <tt>rcu_read_lock()</tt>
+		</font>
+	<li>	<font color="ffffff">
+		CPU 1: <tt>q = rcu_dereference(gp);
+		/* Very likely to return p. */</tt>
+		</font>
+	<li>	<font color="ffffff">
+		CPU 0: <tt>list_del_rcu(p);</tt>
+		</font>
+	<li>	<font color="ffffff">
+		CPU 0: <tt>synchronize_rcu()</tt> starts.
+		</font>
+	<li>	<font color="ffffff">
+		CPU 1: <tt>do_something_with(q-&gt;a);
+		/* No smp_mb(), so might happen after kfree(). */</tt>
+		</font>
+	<li>	<font color="ffffff">
+		CPU 1: <tt>rcu_read_unlock()</tt>
+		</font>
+	<li>	<font color="ffffff">
+		CPU 0: <tt>synchronize_rcu()</tt> returns.
+		</font>
+	<li>	<font color="ffffff">
+		CPU 0: <tt>kfree(p);</tt>
+		</font>
+	</ol>
+
+	<p><font color="ffffff">
+	Therefore, there absolutely must be a full memory barrier between the
+	end of the RCU read-side critical section and the end of the
+	grace period.
+	</font>
+
+	<p><font color="ffffff">
+	The sequence of events demonstrating the necessity of the second rule
+	is roughly similar:
+	</font>
+
+	<ol>
+	<li>	<font color="ffffff">CPU 0: <tt>list_del_rcu(p);</tt>
+		</font>
+	<li>	<font color="ffffff">CPU 0: <tt>synchronize_rcu()</tt> starts.
+		</font>
+	<li>	<font color="ffffff">CPU 1: <tt>rcu_read_lock()</tt>
+		</font>
+	<li>	<font color="ffffff">CPU 1: <tt>q = rcu_dereference(gp);
+		/* Might return p if no memory barrier. */</tt>
+		</font>
+	<li>	<font color="ffffff">CPU 0: <tt>synchronize_rcu()</tt> returns.
+		</font>
+	<li>	<font color="ffffff">CPU 0: <tt>kfree(p);</tt>
+		</font>
+	<li>	<font color="ffffff">
+		CPU 1: <tt>do_something_with(q-&gt;a); /* Boom!!! */</tt>
+		</font>
+	<li>	<font color="ffffff">CPU 1: <tt>rcu_read_unlock()</tt>
+		</font>
+	</ol>
+
+	<p><font color="ffffff">
+	And similarly, without a memory barrier between the beginning of the
+	grace period and the beginning of the RCU read-side critical section,
+	CPU&nbsp;1 might end up accessing the freelist.
+	</font>
+
+	<p><font color="ffffff">
+	The &ldquo;as if&rdquo; rule of course applies, so that any
+	implementation that acts as if the appropriate memory barriers
+	were in place is a correct implementation.
+	That said, it is much easier to fool yourself into believing
+	that you have adhered to the as-if rule than it is to actually
+	adhere to it!
+</font></td></tr>
+<tr><td>&nbsp;</td></tr>
+</table>
+
+<table>
+<tr><th>&nbsp;</th></tr>
+<tr><th align="left">Quick Quiz:</th></tr>
+<tr><td>
+	You claim that <tt>rcu_read_lock()</tt> and <tt>rcu_read_unlock()</tt>
+	generate absolutely no code in some kernel builds.
+	This means that the compiler might arbitrarily rearrange consecutive
+	RCU read-side critical sections.
+	Given such rearrangement, if a given RCU read-side critical section
+	is done, how can you be sure that all prior RCU read-side critical
+	sections are done?
+	Won't the compiler rearrangements make that impossible to determine?
+</td></tr>
+<tr><th align="left">Answer:</th></tr>
+<tr><td bgcolor="#ffffff"><font color="ffffff">
+	In cases where <tt>rcu_read_lock()</tt> and <tt>rcu_read_unlock()</tt>
+	generate absolutely no code, RCU infers quiescent states only at
+	special locations, for example, within the scheduler.
+	Because calls to <tt>schedule()</tt> had better prevent calling-code
+	accesses to shared variables from being rearranged across the call to
+	<tt>schedule()</tt>, if RCU detects the end of a given RCU read-side
+	critical section, it will necessarily detect the end of all prior
+	RCU read-side critical sections, no matter how aggressively the
+	compiler scrambles the code.
+	</font>
+
+	<p><font color="ffffff">
+	Again, this all assumes that the compiler cannot scramble code across
+	calls to the scheduler, out of interrupt handlers, into the idle loop,
+	into user-mode code, and so on.
+	But if your kernel build allows that sort of scrambling, you have broken
+	far more than just RCU!
+</font></td></tr>
+<tr><td>&nbsp;</td></tr>
+</table>
 
 <p>
 Note that these memory-barrier requirements do not replace the fundamental
@@ -626,9 +834,19 @@ inconvenience can be avoided through use
 <tt>call_rcu()</tt> and <tt>kfree_rcu()</tt> API members
 described later in this document.
 
-<p><a name="Quick Quiz 7"><b>Quick Quiz 7</b>:</a>
-But how does the upgrade-to-write operation exclude other readers?
-<br><a href="#qq7answer">Answer</a>
+<table>
+<tr><th>&nbsp;</th></tr>
+<tr><th align="left">Quick Quiz:</th></tr>
+<tr><td>
+	But how does the upgrade-to-write operation exclude other readers?
+</td></tr>
+<tr><th align="left">Answer:</th></tr>
+<tr><td bgcolor="#ffffff"><font color="ffffff">
+	It doesn't, just like normal RCU updates, which also do not exclude
+	RCU readers.
+</font></td></tr>
+<tr><td>&nbsp;</td></tr>
+</table>
 
 <p>
 This guarantee allows lookup code to be shared between read-side
@@ -714,9 +932,20 @@ to do significant reordering.
 This is by design:  Any significant ordering constraints would slow down
 these fast-path APIs.
 
-<p><a name="Quick Quiz 8"><b>Quick Quiz 8</b>:</a>
-Can't the compiler also reorder this code?
-<br><a href="#qq8answer">Answer</a>
+<table>
+<tr><th>&nbsp;</th></tr>
+<tr><th align="left">Quick Quiz:</th></tr>
+<tr><td>
+	Can't the compiler also reorder this code?
+</td></tr>
+<tr><th align="left">Answer:</th></tr>
+<tr><td bgcolor="#ffffff"><font color="ffffff">
+	No, the volatile casts in <tt>READ_ONCE()</tt> and
+	<tt>WRITE_ONCE()</tt> prevent the compiler from reordering in
+	this particular case.
+</font></td></tr>
+<tr><td>&nbsp;</td></tr>
+</table>
 
 <h3><a name="Readers Do Not Exclude Updaters">Readers Do Not Exclude Updaters</a></h3>
 
@@ -769,10 +998,28 @@ new readers can start immediately after
 starts, and <tt>synchronize_rcu()</tt> is under no
 obligation to wait for these new readers.
 
-<p><a name="Quick Quiz 9"><b>Quick Quiz 9</b>:</a>
-Suppose that synchronize_rcu() did wait until all readers had completed.
-Would the updater be able to rely on this?
-<br><a href="#qq9answer">Answer</a>
+<table>
+<tr><th>&nbsp;</th></tr>
+<tr><th align="left">Quick Quiz:</th></tr>
+<tr><td>
+	Suppose that synchronize_rcu() did wait until <i>all</i>
+	readers had completed instead of waiting only on
+	pre-existing readers.
+	For how long would the updater be able to rely on there
+	being no readers?
+</td></tr>
+<tr><th align="left">Answer:</th></tr>
+<tr><td bgcolor="#ffffff"><font color="ffffff">
+	For no time at all.
+	Even if <tt>synchronize_rcu()</tt> were to wait until
+	all readers had completed, a new reader might start immediately after
+	<tt>synchronize_rcu()</tt> completed.
+	Therefore, the code following
+	<tt>synchronize_rcu()</tt> can <i>never</i> rely on there being
+	no readers.
+</font></td></tr>
+<tr><td>&nbsp;</td></tr>
+</table>
 
 <h3><a name="Grace Periods Don't Partition Read-Side Critical Sections">
 Grace Periods Don't Partition Read-Side Critical Sections</a></h3>
@@ -969,11 +1216,24 @@ grace period.
 As a result, an RCU read-side critical section cannot partition a pair
 of RCU grace periods.
 
-<p><a name="Quick Quiz 10"><b>Quick Quiz 10</b>:</a>
-How long a sequence of grace periods, each separated by an RCU read-side
-critical section, would be required to partition the RCU read-side
-critical sections at the beginning and end of the chain?
-<br><a href="#qq10answer">Answer</a>
+<table>
+<tr><th>&nbsp;</th></tr>
+<tr><th align="left">Quick Quiz:</th></tr>
+<tr><td>
+	How long a sequence of grace periods, each separated by an RCU
+	read-side critical section, would be required to partition the RCU
+	read-side critical sections at the beginning and end of the chain?
+</td></tr>
+<tr><th align="left">Answer:</th></tr>
+<tr><td bgcolor="#ffffff"><font color="ffffff">
+	In theory, an infinite number.
+	In practice, an unknown number that is sensitive to both implementation
+	details and timing considerations.
+	Therefore, even in practice, RCU users must abide by the
+	theoretical rather than the practical answer.
+</font></td></tr>
+<tr><td>&nbsp;</td></tr>
+</table>
 
 <h3><a name="Disabling Preemption Does Not Block Grace Periods">
 Disabling Preemption Does Not Block Grace Periods</a></h3>
@@ -1109,12 +1369,27 @@ These classes is covered in the followin
 <h3><a name="Specialization">Specialization</a></h3>
 
 <p>
-RCU is and always has been intended primarily for read-mostly situations, as
-illustrated by the following figure.
-This means that RCU's read-side primitives are optimized, often at the
+RCU is and always has been intended primarily for read-mostly situations,
+which means that RCU's read-side primitives are optimized, often at the
 expense of its update-side primitives.
+Experience thus far is captured by the following list of situations:
 
-<p><img src="RCUApplicability.svg" alt="RCUApplicability.svg" width="70%"></p>
+<ol>
+<li>	Read-mostly data, where stale and inconsistent data is not
+	a problem:   RCU works great!
+<li>	Read-mostly data, where data must be consistent:
+	RCU works well.
+<li>	Read-write data, where data must be consistent:
+	RCU <i>might</i> work OK.
+	Or not.
+<li>	Write-mostly data, where data must be consistent:
+	RCU is very unlikely to be the right tool for the job,
+	with the following exceptions, where RCU can provide:
+	<ol type=a>
+	<li>	Existence guarantees for update-friendly mechanisms.
+	<li>	Wait-free read-side primitives for real-time use.
+	</ol>
+</ol>
 
 <p>
 This focus on read-mostly situations means that RCU must interoperate
@@ -1127,9 +1402,43 @@ synchronization primitives be legal with
 including spinlocks, sequence locks, atomic operations, reference
 counters, and memory barriers.
 
-<p><a name="Quick Quiz 11"><b>Quick Quiz 11</b>:</a>
-What about sleeping locks?
-<br><a href="#qq11answer">Answer</a>
+<table>
+<tr><th>&nbsp;</th></tr>
+<tr><th align="left">Quick Quiz:</th></tr>
+<tr><td>
+	What about sleeping locks?
+</td></tr>
+<tr><th align="left">Answer:</th></tr>
+<tr><td bgcolor="#ffffff"><font color="ffffff">
+	These are forbidden within Linux-kernel RCU read-side critical
+	sections because it is not legal to place a quiescent state
+	(in this case, voluntary context switch) within an RCU read-side
+	critical section.
+	However, sleeping locks may be used within userspace RCU read-side
+	critical sections, and also within Linux-kernel sleepable RCU
+	<a href="#Sleepable RCU"><font color="ffffff">(SRCU)</font></a>
+	read-side critical sections.
+	In addition, the -rt patchset turns spinlocks into a
+	sleeping locks so that the corresponding critical sections
+	can be preempted, which also means that these sleeplockified
+	spinlocks (but not other sleeping locks!)  may be acquire within
+	-rt-Linux-kernel RCU read-side critical sections.
+	</font>
+
+	<p><font color="ffffff">
+	Note that it <i>is</i> legal for a normal RCU read-side
+	critical section to conditionally acquire a sleeping locks
+	(as in <tt>mutex_trylock()</tt>), but only as long as it does
+	not loop indefinitely attempting to conditionally acquire that
+	sleeping locks.
+	The key point is that things like <tt>mutex_trylock()</tt>
+	either return with the mutex held, or return an error indication if
+	the mutex was not immediately available.
+	Either way, <tt>mutex_trylock()</tt> returns immediately without
+	sleeping.
+</font></td></tr>
+<tr><td>&nbsp;</td></tr>
+</table>
 
 <p>
 It often comes as a surprise that many algorithms do not require a
@@ -1160,10 +1469,7 @@ some period of time, so the exact wait p
 One of our pair of veternarians might wait 30 seconds before pronouncing
 the cat dead, while the other might insist on waiting a full minute.
 The two veternarians would then disagree on the state of the cat during
-the final 30 seconds of the minute following the last heartbeat, as
-fancifully illustrated below:
-
-<p><img src="2013-08-is-it-dead.png" alt="2013-08-is-it-dead.png" width="431"></p>
+the final 30 seconds of the minute following the last heartbeat.
 
 <p>
 Interestingly enough, this same situation applies to hardware.
@@ -1343,7 +1649,8 @@ situations where neither <tt>synchronize
 <tt>synchronize_rcu_expedited()</tt> would be legal,
 including within preempt-disable code, <tt>local_bh_disable()</tt> code,
 interrupt-disable code, and interrupt handlers.
-However, even <tt>call_rcu()</tt> is illegal within NMI handlers.
+However, even <tt>call_rcu()</tt> is illegal within NMI handlers
+and from idle and offline CPUs.
 The callback function (<tt>remove_gp_cb()</tt> in this case) will be
 executed within softirq (software interrupt) environment within the
 Linux kernel,
@@ -1354,12 +1661,27 @@ write an RCU callback function that take
 Long-running operations should be relegated to separate threads or
 (in the Linux kernel) workqueues.
 
-<p><a name="Quick Quiz 12"><b>Quick Quiz 12</b>:</a>
-Why does line&nbsp;19 use <tt>rcu_access_pointer()</tt>?
-After all, <tt>call_rcu()</tt> on line&nbsp;25 stores into the
-structure, which would interact badly with concurrent insertions.
-Doesn't this mean that <tt>rcu_dereference()</tt> is required?
-<br><a href="#qq12answer">Answer</a>
+<table>
+<tr><th>&nbsp;</th></tr>
+<tr><th align="left">Quick Quiz:</th></tr>
+<tr><td>
+	Why does line&nbsp;19 use <tt>rcu_access_pointer()</tt>?
+	After all, <tt>call_rcu()</tt> on line&nbsp;25 stores into the
+	structure, which would interact badly with concurrent insertions.
+	Doesn't this mean that <tt>rcu_dereference()</tt> is required?
+</td></tr>
+<tr><th align="left">Answer:</th></tr>
+<tr><td bgcolor="#ffffff"><font color="ffffff">
+	Presumably the <tt>-&gt;gp_lock</tt> acquired on line&nbsp;18 excludes
+	any changes, including any insertions that <tt>rcu_dereference()</tt>
+	would protect against.
+	Therefore, any insertions will be delayed until after
+	<tt>-&gt;gp_lock</tt>
+	is released on line&nbsp;25, which in turn means that
+	<tt>rcu_access_pointer()</tt> suffices.
+</font></td></tr>
+<tr><td>&nbsp;</td></tr>
+</table>
 
 <p>
 However, all that <tt>remove_gp_cb()</tt> is doing is
@@ -1406,14 +1728,31 @@ This was due to the fact that RCU was no
 so the very few places that needed something like
 <tt>synchronize_rcu()</tt> simply open-coded it.
 
-<p><a name="Quick Quiz 13"><b>Quick Quiz 13</b>:</a>
-Earlier it was claimed that <tt>call_rcu()</tt> and
-<tt>kfree_rcu()</tt> allowed updaters to avoid being blocked
-by readers.
-But how can that be correct, given that the invocation of the callback
-and the freeing of the memory (respectively) must still wait for
-a grace period to elapse?
-<br><a href="#qq13answer">Answer</a>
+<table>
+<tr><th>&nbsp;</th></tr>
+<tr><th align="left">Quick Quiz:</th></tr>
+<tr><td>
+	Earlier it was claimed that <tt>call_rcu()</tt> and
+	<tt>kfree_rcu()</tt> allowed updaters to avoid being blocked
+	by readers.
+	But how can that be correct, given that the invocation of the callback
+	and the freeing of the memory (respectively) must still wait for
+	a grace period to elapse?
+</td></tr>
+<tr><th align="left">Answer:</th></tr>
+<tr><td bgcolor="#ffffff"><font color="ffffff">
+	We could define things this way, but keep in mind that this sort of
+	definition would say that updates in garbage-collected languages
+	cannot complete until the next time the garbage collector runs,
+	which does not seem at all reasonable.
+	The key point is that in most cases, an updater using either
+	<tt>call_rcu()</tt> or <tt>kfree_rcu()</tt> can proceed to the
+	next update as soon as it has invoked <tt>call_rcu()</tt> or
+	<tt>kfree_rcu()</tt>, without having to wait for a subsequent
+	grace period.
+</font></td></tr>
+<tr><td>&nbsp;</td></tr>
+</table>
 
 <p>
 But what if the updater must wait for the completion of code to be
@@ -1838,11 +2177,26 @@ kthreads to be spawned.
 Therefore, invoking <tt>synchronize_rcu()</tt> during scheduler
 initialization can result in deadlock.
 
-<p><a name="Quick Quiz 14"><b>Quick Quiz 14</b>:</a>
-So what happens with <tt>synchronize_rcu()</tt> during
-scheduler initialization for <tt>CONFIG_PREEMPT=n</tt>
-kernels?
-<br><a href="#qq14answer">Answer</a>
+<table>
+<tr><th>&nbsp;</th></tr>
+<tr><th align="left">Quick Quiz:</th></tr>
+<tr><td>
+	So what happens with <tt>synchronize_rcu()</tt> during
+	scheduler initialization for <tt>CONFIG_PREEMPT=n</tt>
+	kernels?
+</td></tr>
+<tr><th align="left">Answer:</th></tr>
+<tr><td bgcolor="#ffffff"><font color="ffffff">
+	In <tt>CONFIG_PREEMPT=n</tt> kernel, <tt>synchronize_rcu()</tt>
+	maps directly to <tt>synchronize_sched()</tt>.
+	Therefore, <tt>synchronize_rcu()</tt> works normally throughout
+	boot in <tt>CONFIG_PREEMPT=n</tt> kernels.
+	However, your code must also work in <tt>CONFIG_PREEMPT=y</tt> kernels,
+	so it is still necessary to avoid invoking <tt>synchronize_rcu()</tt>
+	during scheduler initialization.
+</font></td></tr>
+<tr><td>&nbsp;</td></tr>
+</table>
 
 <p>
 I learned of these boot-time requirements as a result of a series of
@@ -2171,6 +2525,14 @@ This real-time requirement motivated the
 also simplified handling of a number of race conditions.
 
 <p>
+RCU must avoid degrading real-time response for CPU-bound threads, whether
+executing in usermode (which is one use case for
+<tt>CONFIG_NO_HZ_FULL=y</tt>) or in the kernel.
+That said, CPU-bound loops in the kernel must execute
+<tt>cond_resched_rcu_qs()</tt> at least once per few tens of milliseconds
+in order to avoid receiving an IPI from RCU.
+
+<p>
 Finally, RCU's status as a synchronization primitive means that
 any RCU failure can result in arbitrary memory corruption that can be
 extremely difficult to debug.
@@ -2223,6 +2585,8 @@ described in a separate section.
 <li>	<a href="#Sched Flavor">Sched Flavor</a>
 <li>	<a href="#Sleepable RCU">Sleepable RCU</a>
 <li>	<a href="#Tasks RCU">Tasks RCU</a>
+<li>	<a href="#Waiting for Multiple Grace Periods">
+	Waiting for Multiple Grace Periods</a>
 </ol>
 
 <h3><a name="Bottom-Half Flavor">Bottom-Half Flavor</a></h3>
@@ -2472,6 +2836,94 @@ The tasks-RCU API is quite compact, cons
 <tt>synchronize_rcu_tasks()</tt>, and
 <tt>rcu_barrier_tasks()</tt>.
 
+<h3><a name="Waiting for Multiple Grace Periods">
+Waiting for Multiple Grace Periods</a></h3>
+
+<p>
+Perhaps you have an RCU protected data structure that is accessed from
+RCU read-side critical sections, from softirq handlers, and from
+hardware interrupt handlers.
+That is three flavors of RCU, the normal flavor, the bottom-half flavor,
+and the sched flavor.
+How to wait for a compound grace period?
+
+<p>
+The best approach is usually to &ldquo;just say no!&rdquo; and
+insert <tt>rcu_read_lock()</tt> and <tt>rcu_read_unlock()</tt>
+around each RCU read-side critical section, regardless of what
+environment it happens to be in.
+But suppose that some of the RCU read-side critical sections are
+on extremely hot code paths, and that use of <tt>CONFIG_PREEMPT=n</tt>
+is not a viable option, so that <tt>rcu_read_lock()</tt> and
+<tt>rcu_read_unlock()</tt> are not free.
+What then?
+
+<p>
+You <i>could</i> wait on all three grace periods in succession, as follows:
+
+<blockquote>
+<pre>
+ 1 synchronize_rcu();
+ 2 synchronize_rcu_bh();
+ 3 synchronize_sched();
+</pre>
+</blockquote>
+
+<p>
+This works, but triples the update-side latency penalty.
+In cases where this is not acceptable, <tt>synchronize_rcu_mult()</tt>
+may be used to wait on all three flavors of grace period concurrently:
+
+<blockquote>
+<pre>
+ 1 synchronize_rcu_mult(call_rcu, call_rcu_bh, call_rcu_sched);
+</pre>
+</blockquote>
+
+<p>
+But what if it is necessary to also wait on SRCU?
+This can be done as follows:
+
+<blockquote>
+<pre>
+ 1 static void call_my_srcu(struct rcu_head *head,
+ 2        void (*func)(struct rcu_head *head))
+ 3 {
+ 4   call_srcu(&amp;my_srcu, head, func);
+ 5 }
+ 6
+ 7 synchronize_rcu_mult(call_rcu, call_rcu_bh, call_rcu_sched, call_my_srcu);
+</pre>
+</blockquote>
+
+<p>
+If you needed to wait on multiple different flavors of SRCU
+(but why???), you would need to create a wrapper function resembling
+<tt>call_my_srcu()</tt> for each SRCU flavor.
+
+<table>
+<tr><th>&nbsp;</th></tr>
+<tr><th align="left">Quick Quiz:</th></tr>
+<tr><td>
+	But what if I need to wait for multiple RCU flavors, but I also need
+	the grace periods to be expedited?
+</td></tr>
+<tr><th align="left">Answer:</th></tr>
+<tr><td bgcolor="#ffffff"><font color="ffffff">
+	If you are using expedited grace periods, there should be less penalty
+	for waiting on them in succession.
+	But if that is nevertheless a problem, you can use workqueues
+	or multiple kthreads to wait on the various expedited grace
+	periods concurrently.
+</font></td></tr>
+<tr><td>&nbsp;</td></tr>
+</table>
+
+<p>
+Again, it is usually better to adjust the RCU read-side critical sections
+to use a single flavor of RCU, but when this is not feasible, you can use
+<tt>synchronize_rcu_mult()</tt>.
+
 <h2><a name="Possible Future Changes">Possible Future Changes</a></h2>
 
 <p>
@@ -2569,329 +3021,4 @@ and is provided
 under the terms of the Creative Commons Attribution-Share Alike 3.0
 United States license.
 
-<h3><a name="Answers to Quick Quizzes">
-Answers to Quick Quizzes</a></h3>
-
-<a name="qq1answer"></a>
-<p><b>Quick Quiz 1</b>:
-Wait a minute!
-You said that updaters can make useful forward progress concurrently
-with readers, but pre-existing readers will block
-<tt>synchronize_rcu()</tt>!!!
-Just who are you trying to fool???
-
-
-</p><p><b>Answer</b>:
-First, if updaters do not wish to be blocked by readers, they can use
-<tt>call_rcu()</tt> or <tt>kfree_rcu()</tt>, which will
-be discussed later.
-Second, even when using <tt>synchronize_rcu()</tt>, the other
-update-side code does run concurrently with readers, whether pre-existing
-or not.
-
-
-</p><p><a href="#Quick%20Quiz%201"><b>Back to Quick Quiz 1</b>.</a>
-
-<a name="qq2answer"></a>
-<p><b>Quick Quiz 2</b>:
-Why is the <tt>synchronize_rcu()</tt> on line&nbsp;28 needed?
-
-
-</p><p><b>Answer</b>:
-Without that extra grace period, memory reordering could result in
-<tt>do_something_dlm()</tt> executing <tt>do_something()</tt>
-concurrently with the last bits of <tt>recovery()</tt>.
-
-
-</p><p><a href="#Quick%20Quiz%202"><b>Back to Quick Quiz 2</b>.</a>
-
-<a name="qq3answer"></a>
-<p><b>Quick Quiz 3</b>:
-But <tt>rcu_assign_pointer()</tt> does nothing to prevent the
-two assignments to <tt>p-&gt;a</tt> and <tt>p-&gt;b</tt>
-from being reordered.
-Can't that also cause problems?
-
-
-</p><p><b>Answer</b>:
-No, it cannot.
-The readers cannot see either of these two fields until
-the assignment to <tt>gp</tt>, by which time both fields are
-fully initialized.
-So reordering the assignments
-to <tt>p-&gt;a</tt> and <tt>p-&gt;b</tt> cannot possibly
-cause any problems.
-
-
-</p><p><a href="#Quick%20Quiz%203"><b>Back to Quick Quiz 3</b>.</a>
-
-<a name="qq4answer"></a>
-<p><b>Quick Quiz 4</b>:
-Without the <tt>rcu_dereference()</tt> or the
-<tt>rcu_access_pointer()</tt>, what destructive optimizations
-might the compiler make use of?
-
-
-</p><p><b>Answer</b>:
-Let's start with what happens to <tt>do_something_gp()</tt>
-if it fails to use <tt>rcu_dereference()</tt>.
-It could reuse a value formerly fetched from this same pointer.
-It could also fetch the pointer from <tt>gp</tt> in a byte-at-a-time
-manner, resulting in <i>load tearing</i>, in turn resulting a bytewise
-mash-up of two distince pointer values.
-It might even use value-speculation optimizations, where it makes a wrong
-guess, but by the time it gets around to checking the value, an update
-has changed the pointer to match the wrong guess.
-Too bad about any dereferences that returned pre-initialization garbage
-in the meantime!
-
-<p>
-For <tt>remove_gp_synchronous()</tt>, as long as all modifications
-to <tt>gp</tt> are carried out while holding <tt>gp_lock</tt>,
-the above optimizations are harmless.
-However,
-with <tt>CONFIG_SPARSE_RCU_POINTER=y</tt>,
-<tt>sparse</tt> will complain if you
-define <tt>gp</tt> with <tt>__rcu</tt> and then
-access it without using
-either <tt>rcu_access_pointer()</tt> or <tt>rcu_dereference()</tt>.
-
-
-</p><p><a href="#Quick%20Quiz%204"><b>Back to Quick Quiz 4</b>.</a>
-
-<a name="qq5answer"></a>
-<p><b>Quick Quiz 5</b>:
-Given that multiple CPUs can start RCU read-side critical sections
-at any time without any ordering whatsoever, how can RCU possibly tell whether
-or not a given RCU read-side critical section starts before a
-given instance of <tt>synchronize_rcu()</tt>?
-
-
-</p><p><b>Answer</b>:
-If RCU cannot tell whether or not a given
-RCU read-side critical section starts before a
-given instance of <tt>synchronize_rcu()</tt>,
-then it must assume that the RCU read-side critical section
-started first.
-In other words, a given instance of <tt>synchronize_rcu()</tt>
-can avoid waiting on a given RCU read-side critical section only
-if it can prove that <tt>synchronize_rcu()</tt> started first.
-
-
-</p><p><a href="#Quick%20Quiz%205"><b>Back to Quick Quiz 5</b>.</a>
-
-<a name="qq6answer"></a>
-<p><b>Quick Quiz 6</b>:
-The first and second guarantees require unbelievably strict ordering!
-Are all these memory barriers <i> really</i> required?
-
-
-</p><p><b>Answer</b>:
-Yes, they really are required.
-To see why the first guarantee is required, consider the following
-sequence of events:
-
-<ol>
-<li>	CPU 1: <tt>rcu_read_lock()</tt>
-<li>	CPU 1: <tt>q = rcu_dereference(gp);
-	/* Very likely to return p. */</tt>
-<li>	CPU 0: <tt>list_del_rcu(p);</tt>
-<li>	CPU 0: <tt>synchronize_rcu()</tt> starts.
-<li>	CPU 1: <tt>do_something_with(q-&gt;a);
-	/* No smp_mb(), so might happen after kfree(). */</tt>
-<li>	CPU 1: <tt>rcu_read_unlock()</tt>
-<li>	CPU 0: <tt>synchronize_rcu()</tt> returns.
-<li>	CPU 0: <tt>kfree(p);</tt>
-</ol>
-
-<p>
-Therefore, there absolutely must be a full memory barrier between the
-end of the RCU read-side critical section and the end of the
-grace period.
-
-<p>
-The sequence of events demonstrating the necessity of the second rule
-is roughly similar:
-
-<ol>
-<li>	CPU 0: <tt>list_del_rcu(p);</tt>
-<li>	CPU 0: <tt>synchronize_rcu()</tt> starts.
-<li>	CPU 1: <tt>rcu_read_lock()</tt>
-<li>	CPU 1: <tt>q = rcu_dereference(gp);
-	/* Might return p if no memory barrier. */</tt>
-<li>	CPU 0: <tt>synchronize_rcu()</tt> returns.
-<li>	CPU 0: <tt>kfree(p);</tt>
-<li>	CPU 1: <tt>do_something_with(q-&gt;a); /* Boom!!! */</tt>
-<li>	CPU 1: <tt>rcu_read_unlock()</tt>
-</ol>
-
-<p>
-And similarly, without a memory barrier between the beginning of the
-grace period and the beginning of the RCU read-side critical section,
-CPU&nbsp;1 might end up accessing the freelist.
-
-<p>
-The &ldquo;as if&rdquo; rule of course applies, so that any implementation
-that acts as if the appropriate memory barriers were in place is a
-correct implementation.
-That said, it is much easier to fool yourself into believing that you have
-adhered to the as-if rule than it is to actually adhere to it!
-
-
-</p><p><a href="#Quick%20Quiz%206"><b>Back to Quick Quiz 6</b>.</a>
-
-<a name="qq7answer"></a>
-<p><b>Quick Quiz 7</b>:
-But how does the upgrade-to-write operation exclude other readers?
-
-
-</p><p><b>Answer</b>:
-It doesn't, just like normal RCU updates, which also do not exclude
-RCU readers.
-
-
-</p><p><a href="#Quick%20Quiz%207"><b>Back to Quick Quiz 7</b>.</a>
-
-<a name="qq8answer"></a>
-<p><b>Quick Quiz 8</b>:
-Can't the compiler also reorder this code?
-
-
-</p><p><b>Answer</b>:
-No, the volatile casts in <tt>READ_ONCE()</tt> and
-<tt>WRITE_ONCE()</tt> prevent the compiler from reordering in
-this particular case.
-
-
-</p><p><a href="#Quick%20Quiz%208"><b>Back to Quick Quiz 8</b>.</a>
-
-<a name="qq9answer"></a>
-<p><b>Quick Quiz 9</b>:
-Suppose that synchronize_rcu() did wait until all readers had completed.
-Would the updater be able to rely on this?
-
-
-</p><p><b>Answer</b>:
-No.
-Even if <tt>synchronize_rcu()</tt> were to wait until
-all readers had completed, a new reader might start immediately after
-<tt>synchronize_rcu()</tt> completed.
-Therefore, the code following
-<tt>synchronize_rcu()</tt> cannot rely on there being no readers
-in any case.
-
-
-</p><p><a href="#Quick%20Quiz%209"><b>Back to Quick Quiz 9</b>.</a>
-
-<a name="qq10answer"></a>
-<p><b>Quick Quiz 10</b>:
-How long a sequence of grace periods, each separated by an RCU read-side
-critical section, would be required to partition the RCU read-side
-critical sections at the beginning and end of the chain?
-
-
-</p><p><b>Answer</b>:
-In theory, an infinite number.
-In practice, an unknown number that is sensitive to both implementation
-details and timing considerations.
-Therefore, even in practice, RCU users must abide by the theoretical rather
-than the practical answer.
-
-
-</p><p><a href="#Quick%20Quiz%2010"><b>Back to Quick Quiz 10</b>.</a>
-
-<a name="qq11answer"></a>
-<p><b>Quick Quiz 11</b>:
-What about sleeping locks?
-
-
-</p><p><b>Answer</b>:
-These are forbidden within Linux-kernel RCU read-side critical sections
-because it is not legal to place a quiescent state (in this case,
-voluntary context switch) within an RCU read-side critical section.
-However, sleeping locks may be used within userspace RCU read-side critical
-sections, and also within Linux-kernel sleepable RCU
-<a href="#Sleepable RCU">(SRCU)</a>
-read-side critical sections.
-In addition, the -rt patchset turns spinlocks into a sleeping locks so
-that the corresponding critical sections can be preempted, which
-also means that these sleeplockified spinlocks (but not other sleeping locks!)
-may be acquire within -rt-Linux-kernel RCU read-side critical sections.
-
-<p>
-Note that it <i>is</i> legal for a normal RCU read-side critical section
-to conditionally acquire a sleeping locks (as in <tt>mutex_trylock()</tt>),
-but only as long as it does not loop indefinitely attempting to
-conditionally acquire that sleeping locks.
-The key point is that things like <tt>mutex_trylock()</tt>
-either return with the mutex held, or return an error indication if
-the mutex was not immediately available.
-Either way, <tt>mutex_trylock()</tt> returns immediately without sleeping.
-
-
-</p><p><a href="#Quick%20Quiz%2011"><b>Back to Quick Quiz 11</b>.</a>
-
-<a name="qq12answer"></a>
-<p><b>Quick Quiz 12</b>:
-Why does line&nbsp;19 use <tt>rcu_access_pointer()</tt>?
-After all, <tt>call_rcu()</tt> on line&nbsp;25 stores into the
-structure, which would interact badly with concurrent insertions.
-Doesn't this mean that <tt>rcu_dereference()</tt> is required?
-
-
-</p><p><b>Answer</b>:
-Presumably the <tt>-&gt;gp_lock</tt> acquired on line&nbsp;18 excludes
-any changes, including any insertions that <tt>rcu_dereference()</tt>
-would protect against.
-Therefore, any insertions will be delayed until after <tt>-&gt;gp_lock</tt>
-is released on line&nbsp;25, which in turn means that
-<tt>rcu_access_pointer()</tt> suffices.
-
-
-</p><p><a href="#Quick%20Quiz%2012"><b>Back to Quick Quiz 12</b>.</a>
-
-<a name="qq13answer"></a>
-<p><b>Quick Quiz 13</b>:
-Earlier it was claimed that <tt>call_rcu()</tt> and
-<tt>kfree_rcu()</tt> allowed updaters to avoid being blocked
-by readers.
-But how can that be correct, given that the invocation of the callback
-and the freeing of the memory (respectively) must still wait for
-a grace period to elapse?
-
-
-</p><p><b>Answer</b>:
-We could define things this way, but keep in mind that this sort of
-definition would say that updates in garbage-collected languages
-cannot complete until the next time the garbage collector runs,
-which does not seem at all reasonable.
-The key point is that in most cases, an updater using either
-<tt>call_rcu()</tt> or <tt>kfree_rcu()</tt> can proceed to the
-next update as soon as it has invoked <tt>call_rcu()</tt> or
-<tt>kfree_rcu()</tt>, without having to wait for a subsequent
-grace period.
-
-
-</p><p><a href="#Quick%20Quiz%2013"><b>Back to Quick Quiz 13</b>.</a>
-
-<a name="qq14answer"></a>
-<p><b>Quick Quiz 14</b>:
-So what happens with <tt>synchronize_rcu()</tt> during
-scheduler initialization for <tt>CONFIG_PREEMPT=n</tt>
-kernels?
-
-
-</p><p><b>Answer</b>:
-In <tt>CONFIG_PREEMPT=n</tt> kernel, <tt>synchronize_rcu()</tt>
-maps directly to <tt>synchronize_sched()</tt>.
-Therefore, <tt>synchronize_rcu()</tt> works normally throughout
-boot in <tt>CONFIG_PREEMPT=n</tt> kernels.
-However, your code must also work in <tt>CONFIG_PREEMPT=y</tt> kernels,
-so it is still necessary to avoid invoking <tt>synchronize_rcu()</tt>
-during scheduler initialization.
-
-
-</p><p><a href="#Quick%20Quiz%2014"><b>Back to Quick Quiz 14</b>.</a>
-
-
 </body></html>
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/RCU/Design/Requirements/Requirements.htmlx linux-libre-4.7-gnu/Documentation/RCU/Design/Requirements/Requirements.htmlx
--- linux-libre-4.6-gnu/Documentation/RCU/Design/Requirements/Requirements.htmlx	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/RCU/Design/Requirements/Requirements.htmlx	1969-12-31 19:00:00.000000000 -0500
@@ -1,2741 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
-        "http://www.w3.org/TR/html4/loose.dtd">
-        <html>
-        <head><title>A Tour Through RCU's Requirements [LWN.net]</title>
-        <meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
-
-<h1>A Tour Through RCU's Requirements</h1>
-
-<p>Copyright IBM Corporation, 2015</p>
-<p>Author: Paul E.&nbsp;McKenney</p>
-<p><i>The initial version of this document appeared in the
-<a href="https://lwn.net/">LWN</a> articles
-<a href="https://lwn.net/Articles/652156/">here</a>,
-<a href="https://lwn.net/Articles/652677/">here</a>, and
-<a href="https://lwn.net/Articles/653326/">here</a>.</i></p>
-
-<h2>Introduction</h2>
-
-<p>
-Read-copy update (RCU) is a synchronization mechanism that is often
-used as a replacement for reader-writer locking.
-RCU is unusual in that updaters do not block readers,
-which means that RCU's read-side primitives can be exceedingly fast
-and scalable.
-In addition, updaters can make useful forward progress concurrently
-with readers.
-However, all this concurrency between RCU readers and updaters does raise
-the question of exactly what RCU readers are doing, which in turn
-raises the question of exactly what RCU's requirements are.
-
-<p>
-This document therefore summarizes RCU's requirements, and can be thought
-of as an informal, high-level specification for RCU.
-It is important to understand that RCU's specification is primarily
-empirical in nature;
-in fact, I learned about many of these requirements the hard way.
-This situation might cause some consternation, however, not only
-has this learning process been a lot of fun, but it has also been
-a great privilege to work with so many people willing to apply
-technologies in interesting new ways.
-
-<p>
-All that aside, here are the categories of currently known RCU requirements:
-</p>
-
-<ol>
-<li>	<a href="#Fundamental Requirements">
-	Fundamental Requirements</a>
-<li>	<a href="#Fundamental Non-Requirements">Fundamental Non-Requirements</a>
-<li>	<a href="#Parallelism Facts of Life">
-	Parallelism Facts of Life</a>
-<li>	<a href="#Quality-of-Implementation Requirements">
-	Quality-of-Implementation Requirements</a>
-<li>	<a href="#Linux Kernel Complications">
-	Linux Kernel Complications</a>
-<li>	<a href="#Software-Engineering Requirements">
-	Software-Engineering Requirements</a>
-<li>	<a href="#Other RCU Flavors">
-	Other RCU Flavors</a>
-<li>	<a href="#Possible Future Changes">
-	Possible Future Changes</a>
-</ol>
-
-<p>
-This is followed by a <a href="#Summary">summary</a>,
-which is in turn followed by the inevitable
-<a href="#Answers to Quick Quizzes">answers to the quick quizzes</a>.
-
-<h2><a name="Fundamental Requirements">Fundamental Requirements</a></h2>
-
-<p>
-RCU's fundamental requirements are the closest thing RCU has to hard
-mathematical requirements.
-These are:
-
-<ol>
-<li>	<a href="#Grace-Period Guarantee">
-	Grace-Period Guarantee</a>
-<li>	<a href="#Publish-Subscribe Guarantee">
-	Publish-Subscribe Guarantee</a>
-<li>	<a href="#Memory-Barrier Guarantees">
-	Memory-Barrier Guarantees</a>
-<li>	<a href="#RCU Primitives Guaranteed to Execute Unconditionally">
-	RCU Primitives Guaranteed to Execute Unconditionally</a>
-<li>	<a href="#Guaranteed Read-to-Write Upgrade">
-	Guaranteed Read-to-Write Upgrade</a>
-</ol>
-
-<h3><a name="Grace-Period Guarantee">Grace-Period Guarantee</a></h3>
-
-<p>
-RCU's grace-period guarantee is unusual in being premeditated:
-Jack Slingwine and I had this guarantee firmly in mind when we started
-work on RCU (then called &ldquo;rclock&rdquo;) in the early 1990s.
-That said, the past two decades of experience with RCU have produced
-a much more detailed understanding of this guarantee.
-
-<p>
-RCU's grace-period guarantee allows updaters to wait for the completion
-of all pre-existing RCU read-side critical sections.
-An RCU read-side critical section
-begins with the marker <tt>rcu_read_lock()</tt> and ends with
-the marker <tt>rcu_read_unlock()</tt>.
-These markers may be nested, and RCU treats a nested set as one
-big RCU read-side critical section.
-Production-quality implementations of <tt>rcu_read_lock()</tt> and
-<tt>rcu_read_unlock()</tt> are extremely lightweight, and in
-fact have exactly zero overhead in Linux kernels built for production
-use with <tt>CONFIG_PREEMPT=n</tt>.
-
-<p>
-This guarantee allows ordering to be enforced with extremely low
-overhead to readers, for example:
-
-<blockquote>
-<pre>
- 1 int x, y;
- 2
- 3 void thread0(void)
- 4 {
- 5   rcu_read_lock();
- 6   r1 = READ_ONCE(x);
- 7   r2 = READ_ONCE(y);
- 8   rcu_read_unlock();
- 9 }
-10
-11 void thread1(void)
-12 {
-13   WRITE_ONCE(x, 1);
-14   synchronize_rcu();
-15   WRITE_ONCE(y, 1);
-16 }
-</pre>
-</blockquote>
-
-<p>
-Because the <tt>synchronize_rcu()</tt> on line&nbsp;14 waits for
-all pre-existing readers, any instance of <tt>thread0()</tt> that
-loads a value of zero from <tt>x</tt> must complete before
-<tt>thread1()</tt> stores to <tt>y</tt>, so that instance must
-also load a value of zero from <tt>y</tt>.
-Similarly, any instance of <tt>thread0()</tt> that loads a value of
-one from <tt>y</tt> must have started after the
-<tt>synchronize_rcu()</tt> started, and must therefore also load
-a value of one from <tt>x</tt>.
-Therefore, the outcome:
-<blockquote>
-<pre>
-(r1 == 0 &amp;&amp; r2 == 1)
-</pre>
-</blockquote>
-cannot happen.
-
-<p>@@QQ@@
-Wait a minute!
-You said that updaters can make useful forward progress concurrently
-with readers, but pre-existing readers will block
-<tt>synchronize_rcu()</tt>!!!
-Just who are you trying to fool???
-<p>@@QQA@@
-First, if updaters do not wish to be blocked by readers, they can use
-<tt>call_rcu()</tt> or <tt>kfree_rcu()</tt>, which will
-be discussed later.
-Second, even when using <tt>synchronize_rcu()</tt>, the other
-update-side code does run concurrently with readers, whether pre-existing
-or not.
-<p>@@QQE@@
-
-<p>
-This scenario resembles one of the first uses of RCU in
-<a href="https://en.wikipedia.org/wiki/DYNIX">DYNIX/ptx</a>,
-which managed a distributed lock manager's transition into
-a state suitable for handling recovery from node failure,
-more or less as follows:
-
-<blockquote>
-<pre>
- 1 #define STATE_NORMAL        0
- 2 #define STATE_WANT_RECOVERY 1
- 3 #define STATE_RECOVERING    2
- 4 #define STATE_WANT_NORMAL   3
- 5
- 6 int state = STATE_NORMAL;
- 7
- 8 void do_something_dlm(void)
- 9 {
-10   int state_snap;
-11
-12   rcu_read_lock();
-13   state_snap = READ_ONCE(state);
-14   if (state_snap == STATE_NORMAL)
-15     do_something();
-16   else
-17     do_something_carefully();
-18   rcu_read_unlock();
-19 }
-20
-21 void start_recovery(void)
-22 {
-23   WRITE_ONCE(state, STATE_WANT_RECOVERY);
-24   synchronize_rcu();
-25   WRITE_ONCE(state, STATE_RECOVERING);
-26   recovery();
-27   WRITE_ONCE(state, STATE_WANT_NORMAL);
-28   synchronize_rcu();
-29   WRITE_ONCE(state, STATE_NORMAL);
-30 }
-</pre>
-</blockquote>
-
-<p>
-The RCU read-side critical section in <tt>do_something_dlm()</tt>
-works with the <tt>synchronize_rcu()</tt> in <tt>start_recovery()</tt>
-to guarantee that <tt>do_something()</tt> never runs concurrently
-with <tt>recovery()</tt>, but with little or no synchronization
-overhead in <tt>do_something_dlm()</tt>.
-
-<p>@@QQ@@
-Why is the <tt>synchronize_rcu()</tt> on line&nbsp;28 needed?
-<p>@@QQA@@
-Without that extra grace period, memory reordering could result in
-<tt>do_something_dlm()</tt> executing <tt>do_something()</tt>
-concurrently with the last bits of <tt>recovery()</tt>.
-<p>@@QQE@@
-
-<p>
-In order to avoid fatal problems such as deadlocks,
-an RCU read-side critical section must not contain calls to
-<tt>synchronize_rcu()</tt>.
-Similarly, an RCU read-side critical section must not
-contain anything that waits, directly or indirectly, on completion of
-an invocation of <tt>synchronize_rcu()</tt>.
-
-<p>
-Although RCU's grace-period guarantee is useful in and of itself, with
-<a href="https://lwn.net/Articles/573497/">quite a few use cases</a>,
-it would be good to be able to use RCU to coordinate read-side
-access to linked data structures.
-For this, the grace-period guarantee is not sufficient, as can
-be seen in function <tt>add_gp_buggy()</tt> below.
-We will look at the reader's code later, but in the meantime, just think of
-the reader as locklessly picking up the <tt>gp</tt> pointer,
-and, if the value loaded is non-<tt>NULL</tt>, locklessly accessing the
-<tt>-&gt;a</tt> and <tt>-&gt;b</tt> fields.
-
-<blockquote>
-<pre>
- 1 bool add_gp_buggy(int a, int b)
- 2 {
- 3   p = kmalloc(sizeof(*p), GFP_KERNEL);
- 4   if (!p)
- 5     return -ENOMEM;
- 6   spin_lock(&amp;gp_lock);
- 7   if (rcu_access_pointer(gp)) {
- 8     spin_unlock(&amp;gp_lock);
- 9     return false;
-10   }
-11   p-&gt;a = a;
-12   p-&gt;b = a;
-13   gp = p; /* ORDERING BUG */
-14   spin_unlock(&amp;gp_lock);
-15   return true;
-16 }
-</pre>
-</blockquote>
-
-<p>
-The problem is that both the compiler and weakly ordered CPUs are within
-their rights to reorder this code as follows:
-
-<blockquote>
-<pre>
- 1 bool add_gp_buggy_optimized(int a, int b)
- 2 {
- 3   p = kmalloc(sizeof(*p), GFP_KERNEL);
- 4   if (!p)
- 5     return -ENOMEM;
- 6   spin_lock(&amp;gp_lock);
- 7   if (rcu_access_pointer(gp)) {
- 8     spin_unlock(&amp;gp_lock);
- 9     return false;
-10   }
-<b>11   gp = p; /* ORDERING BUG */
-12   p-&gt;a = a;
-13   p-&gt;b = a;</b>
-14   spin_unlock(&amp;gp_lock);
-15   return true;
-16 }
-</pre>
-</blockquote>
-
-<p>
-If an RCU reader fetches <tt>gp</tt> just after
-<tt>add_gp_buggy_optimized</tt> executes line&nbsp;11,
-it will see garbage in the <tt>-&gt;a</tt> and <tt>-&gt;b</tt>
-fields.
-And this is but one of many ways in which compiler and hardware optimizations
-could cause trouble.
-Therefore, we clearly need some way to prevent the compiler and the CPU from
-reordering in this manner, which brings us to the publish-subscribe
-guarantee discussed in the next section.
-
-<h3><a name="Publish-Subscribe Guarantee">Publish/Subscribe Guarantee</a></h3>
-
-<p>
-RCU's publish-subscribe guarantee allows data to be inserted
-into a linked data structure without disrupting RCU readers.
-The updater uses <tt>rcu_assign_pointer()</tt> to insert the
-new data, and readers use <tt>rcu_dereference()</tt> to
-access data, whether new or old.
-The following shows an example of insertion:
-
-<blockquote>
-<pre>
- 1 bool add_gp(int a, int b)
- 2 {
- 3   p = kmalloc(sizeof(*p), GFP_KERNEL);
- 4   if (!p)
- 5     return -ENOMEM;
- 6   spin_lock(&amp;gp_lock);
- 7   if (rcu_access_pointer(gp)) {
- 8     spin_unlock(&amp;gp_lock);
- 9     return false;
-10   }
-11   p-&gt;a = a;
-12   p-&gt;b = a;
-13   rcu_assign_pointer(gp, p);
-14   spin_unlock(&amp;gp_lock);
-15   return true;
-16 }
-</pre>
-</blockquote>
-
-<p>
-The <tt>rcu_assign_pointer()</tt> on line&nbsp;13 is conceptually
-equivalent to a simple assignment statement, but also guarantees
-that its assignment will
-happen after the two assignments in lines&nbsp;11 and&nbsp;12,
-similar to the C11 <tt>memory_order_release</tt> store operation.
-It also prevents any number of &ldquo;interesting&rdquo; compiler
-optimizations, for example, the use of <tt>gp</tt> as a scratch
-location immediately preceding the assignment.
-
-<p>@@QQ@@
-But <tt>rcu_assign_pointer()</tt> does nothing to prevent the
-two assignments to <tt>p-&gt;a</tt> and <tt>p-&gt;b</tt>
-from being reordered.
-Can't that also cause problems?
-<p>@@QQA@@
-No, it cannot.
-The readers cannot see either of these two fields until
-the assignment to <tt>gp</tt>, by which time both fields are
-fully initialized.
-So reordering the assignments
-to <tt>p-&gt;a</tt> and <tt>p-&gt;b</tt> cannot possibly
-cause any problems.
-<p>@@QQE@@
-
-<p>
-It is tempting to assume that the reader need not do anything special
-to control its accesses to the RCU-protected data,
-as shown in <tt>do_something_gp_buggy()</tt> below:
-
-<blockquote>
-<pre>
- 1 bool do_something_gp_buggy(void)
- 2 {
- 3   rcu_read_lock();
- 4   p = gp;  /* OPTIMIZATIONS GALORE!!! */
- 5   if (p) {
- 6     do_something(p-&gt;a, p-&gt;b);
- 7     rcu_read_unlock();
- 8     return true;
- 9   }
-10   rcu_read_unlock();
-11   return false;
-12 }
-</pre>
-</blockquote>
-
-<p>
-However, this temptation must be resisted because there are a
-surprisingly large number of ways that the compiler
-(to say nothing of
-<a href="https://h71000.www7.hp.com/wizard/wiz_2637.html">DEC Alpha CPUs</a>)
-can trip this code up.
-For but one example, if the compiler were short of registers, it
-might choose to refetch from <tt>gp</tt> rather than keeping
-a separate copy in <tt>p</tt> as follows:
-
-<blockquote>
-<pre>
- 1 bool do_something_gp_buggy_optimized(void)
- 2 {
- 3   rcu_read_lock();
- 4   if (gp) { /* OPTIMIZATIONS GALORE!!! */
-<b> 5     do_something(gp-&gt;a, gp-&gt;b);</b>
- 6     rcu_read_unlock();
- 7     return true;
- 8   }
- 9   rcu_read_unlock();
-10   return false;
-11 }
-</pre>
-</blockquote>
-
-<p>
-If this function ran concurrently with a series of updates that
-replaced the current structure with a new one,
-the fetches of <tt>gp-&gt;a</tt>
-and <tt>gp-&gt;b</tt> might well come from two different structures,
-which could cause serious confusion.
-To prevent this (and much else besides), <tt>do_something_gp()</tt> uses
-<tt>rcu_dereference()</tt> to fetch from <tt>gp</tt>:
-
-<blockquote>
-<pre>
- 1 bool do_something_gp(void)
- 2 {
- 3   rcu_read_lock();
- 4   p = rcu_dereference(gp);
- 5   if (p) {
- 6     do_something(p-&gt;a, p-&gt;b);
- 7     rcu_read_unlock();
- 8     return true;
- 9   }
-10   rcu_read_unlock();
-11   return false;
-12 }
-</pre>
-</blockquote>
-
-<p>
-The <tt>rcu_dereference()</tt> uses volatile casts and (for DEC Alpha)
-memory barriers in the Linux kernel.
-Should a
-<a href="http://www.rdrop.com/users/paulmck/RCU/consume.2015.07.13a.pdf">high-quality implementation of C11 <tt>memory_order_consume</tt> [PDF]</a>
-ever appear, then <tt>rcu_dereference()</tt> could be implemented
-as a <tt>memory_order_consume</tt> load.
-Regardless of the exact implementation, a pointer fetched by
-<tt>rcu_dereference()</tt> may not be used outside of the
-outermost RCU read-side critical section containing that
-<tt>rcu_dereference()</tt>, unless protection of
-the corresponding data element has been passed from RCU to some
-other synchronization mechanism, most commonly locking or
-<a href="https://www.kernel.org/doc/Documentation/RCU/rcuref.txt">reference counting</a>.
-
-<p>
-In short, updaters use <tt>rcu_assign_pointer()</tt> and readers
-use <tt>rcu_dereference()</tt>, and these two RCU API elements
-work together to ensure that readers have a consistent view of
-newly added data elements.
-
-<p>
-Of course, it is also necessary to remove elements from RCU-protected
-data structures, for example, using the following process:
-
-<ol>
-<li>	Remove the data element from the enclosing structure.
-<li>	Wait for all pre-existing RCU read-side critical sections
-	to complete (because only pre-existing readers can possibly have
-	a reference to the newly removed data element).
-<li>	At this point, only the updater has a reference to the
-	newly removed data element, so it can safely reclaim
-	the data element, for example, by passing it to <tt>kfree()</tt>.
-</ol>
-
-This process is implemented by <tt>remove_gp_synchronous()</tt>:
-
-<blockquote>
-<pre>
- 1 bool remove_gp_synchronous(void)
- 2 {
- 3   struct foo *p;
- 4
- 5   spin_lock(&amp;gp_lock);
- 6   p = rcu_access_pointer(gp);
- 7   if (!p) {
- 8     spin_unlock(&amp;gp_lock);
- 9     return false;
-10   }
-11   rcu_assign_pointer(gp, NULL);
-12   spin_unlock(&amp;gp_lock);
-13   synchronize_rcu();
-14   kfree(p);
-15   return true;
-16 }
-</pre>
-</blockquote>
-
-<p>
-This function is straightforward, with line&nbsp;13 waiting for a grace
-period before line&nbsp;14 frees the old data element.
-This waiting ensures that readers will reach line&nbsp;7 of
-<tt>do_something_gp()</tt> before the data element referenced by
-<tt>p</tt> is freed.
-The <tt>rcu_access_pointer()</tt> on line&nbsp;6 is similar to
-<tt>rcu_dereference()</tt>, except that:
-
-<ol>
-<li>	The value returned by <tt>rcu_access_pointer()</tt>
-	cannot be dereferenced.
-	If you want to access the value pointed to as well as
-	the pointer itself, use <tt>rcu_dereference()</tt>
-	instead of <tt>rcu_access_pointer()</tt>.
-<li>	The call to <tt>rcu_access_pointer()</tt> need not be
-	protected.
-	In contrast, <tt>rcu_dereference()</tt> must either be
-	within an RCU read-side critical section or in a code
-	segment where the pointer cannot change, for example, in
-	code protected by the corresponding update-side lock.
-</ol>
-
-<p>@@QQ@@
-Without the <tt>rcu_dereference()</tt> or the
-<tt>rcu_access_pointer()</tt>, what destructive optimizations
-might the compiler make use of?
-<p>@@QQA@@
-Let's start with what happens to <tt>do_something_gp()</tt>
-if it fails to use <tt>rcu_dereference()</tt>.
-It could reuse a value formerly fetched from this same pointer.
-It could also fetch the pointer from <tt>gp</tt> in a byte-at-a-time
-manner, resulting in <i>load tearing</i>, in turn resulting a bytewise
-mash-up of two distince pointer values.
-It might even use value-speculation optimizations, where it makes a wrong
-guess, but by the time it gets around to checking the value, an update
-has changed the pointer to match the wrong guess.
-Too bad about any dereferences that returned pre-initialization garbage
-in the meantime!
-
-<p>
-For <tt>remove_gp_synchronous()</tt>, as long as all modifications
-to <tt>gp</tt> are carried out while holding <tt>gp_lock</tt>,
-the above optimizations are harmless.
-However,
-with <tt>CONFIG_SPARSE_RCU_POINTER=y</tt>,
-<tt>sparse</tt> will complain if you
-define <tt>gp</tt> with <tt>__rcu</tt> and then
-access it without using
-either <tt>rcu_access_pointer()</tt> or <tt>rcu_dereference()</tt>.
-<p>@@QQE@@
-
-<p>
-In short, RCU's publish-subscribe guarantee is provided by the combination
-of <tt>rcu_assign_pointer()</tt> and <tt>rcu_dereference()</tt>.
-This guarantee allows data elements to be safely added to RCU-protected
-linked data structures without disrupting RCU readers.
-This guarantee can be used in combination with the grace-period
-guarantee to also allow data elements to be removed from RCU-protected
-linked data structures, again without disrupting RCU readers.
-
-<p>
-This guarantee was only partially premeditated.
-DYNIX/ptx used an explicit memory barrier for publication, but had nothing
-resembling <tt>rcu_dereference()</tt> for subscription, nor did it
-have anything resembling the <tt>smp_read_barrier_depends()</tt>
-that was later subsumed into <tt>rcu_dereference()</tt>.
-The need for these operations made itself known quite suddenly at a
-late-1990s meeting with the DEC Alpha architects, back in the days when
-DEC was still a free-standing company.
-It took the Alpha architects a good hour to convince me that any sort
-of barrier would ever be needed, and it then took me a good <i>two</i> hours
-to convince them that their documentation did not make this point clear.
-More recent work with the C and C++ standards committees have provided
-much education on tricks and traps from the compiler.
-In short, compilers were much less tricky in the early 1990s, but in
-2015, don't even think about omitting <tt>rcu_dereference()</tt>!
-
-<h3><a name="Memory-Barrier Guarantees">Memory-Barrier Guarantees</a></h3>
-
-<p>
-The previous section's simple linked-data-structure scenario clearly
-demonstrates the need for RCU's stringent memory-ordering guarantees on
-systems with more than one CPU:
-
-<ol>
-<li>	Each CPU that has an RCU read-side critical section that
-	begins before <tt>synchronize_rcu()</tt> starts is
-	guaranteed to execute a full memory barrier between the time
-	that the RCU read-side critical section ends and the time that
-	<tt>synchronize_rcu()</tt> returns.
-	Without this guarantee, a pre-existing RCU read-side critical section
-	might hold a reference to the newly removed <tt>struct foo</tt>
-	after the <tt>kfree()</tt> on line&nbsp;14 of
-	<tt>remove_gp_synchronous()</tt>.
-<li>	Each CPU that has an RCU read-side critical section that ends
-	after <tt>synchronize_rcu()</tt> returns is guaranteed
-	to execute a full memory barrier between the time that
-	<tt>synchronize_rcu()</tt> begins and the time that the RCU
-	read-side critical section begins.
-	Without this guarantee, a later RCU read-side critical section
-	running after the <tt>kfree()</tt> on line&nbsp;14 of
-	<tt>remove_gp_synchronous()</tt> might
-	later run <tt>do_something_gp()</tt> and find the
-	newly deleted <tt>struct foo</tt>.
-<li>	If the task invoking <tt>synchronize_rcu()</tt> remains
-	on a given CPU, then that CPU is guaranteed to execute a full
-	memory barrier sometime during the execution of
-	<tt>synchronize_rcu()</tt>.
-	This guarantee ensures that the <tt>kfree()</tt> on
-	line&nbsp;14 of <tt>remove_gp_synchronous()</tt> really does
-	execute after the removal on line&nbsp;11.
-<li>	If the task invoking <tt>synchronize_rcu()</tt> migrates
-	among a group of CPUs during that invocation, then each of the
-	CPUs in that group is guaranteed to execute a full memory barrier
-	sometime during the execution of <tt>synchronize_rcu()</tt>.
-	This guarantee also ensures that the <tt>kfree()</tt> on
-	line&nbsp;14 of <tt>remove_gp_synchronous()</tt> really does
-	execute after the removal on
-	line&nbsp;11, but also in the case where the thread executing the
-	<tt>synchronize_rcu()</tt> migrates in the meantime.
-</ol>
-
-<p>@@QQ@@
-Given that multiple CPUs can start RCU read-side critical sections
-at any time without any ordering whatsoever, how can RCU possibly tell whether
-or not a given RCU read-side critical section starts before a
-given instance of <tt>synchronize_rcu()</tt>?
-<p>@@QQA@@
-If RCU cannot tell whether or not a given
-RCU read-side critical section starts before a
-given instance of <tt>synchronize_rcu()</tt>,
-then it must assume that the RCU read-side critical section
-started first.
-In other words, a given instance of <tt>synchronize_rcu()</tt>
-can avoid waiting on a given RCU read-side critical section only
-if it can prove that <tt>synchronize_rcu()</tt> started first.
-<p>@@QQE@@
-
-<p>@@QQ@@
-The first and second guarantees require unbelievably strict ordering!
-Are all these memory barriers <i> really</i> required?
-<p>@@QQA@@
-Yes, they really are required.
-To see why the first guarantee is required, consider the following
-sequence of events:
-
-<ol>
-<li>	CPU 1: <tt>rcu_read_lock()</tt>
-<li>	CPU 1: <tt>q = rcu_dereference(gp);
-	/* Very likely to return p. */</tt>
-<li>	CPU 0: <tt>list_del_rcu(p);</tt>
-<li>	CPU 0: <tt>synchronize_rcu()</tt> starts.
-<li>	CPU 1: <tt>do_something_with(q-&gt;a);
-	/* No smp_mb(), so might happen after kfree(). */</tt>
-<li>	CPU 1: <tt>rcu_read_unlock()</tt>
-<li>	CPU 0: <tt>synchronize_rcu()</tt> returns.
-<li>	CPU 0: <tt>kfree(p);</tt>
-</ol>
-
-<p>
-Therefore, there absolutely must be a full memory barrier between the
-end of the RCU read-side critical section and the end of the
-grace period.
-
-<p>
-The sequence of events demonstrating the necessity of the second rule
-is roughly similar:
-
-<ol>
-<li>	CPU 0: <tt>list_del_rcu(p);</tt>
-<li>	CPU 0: <tt>synchronize_rcu()</tt> starts.
-<li>	CPU 1: <tt>rcu_read_lock()</tt>
-<li>	CPU 1: <tt>q = rcu_dereference(gp);
-	/* Might return p if no memory barrier. */</tt>
-<li>	CPU 0: <tt>synchronize_rcu()</tt> returns.
-<li>	CPU 0: <tt>kfree(p);</tt>
-<li>	CPU 1: <tt>do_something_with(q-&gt;a); /* Boom!!! */</tt>
-<li>	CPU 1: <tt>rcu_read_unlock()</tt>
-</ol>
-
-<p>
-And similarly, without a memory barrier between the beginning of the
-grace period and the beginning of the RCU read-side critical section,
-CPU&nbsp;1 might end up accessing the freelist.
-
-<p>
-The &ldquo;as if&rdquo; rule of course applies, so that any implementation
-that acts as if the appropriate memory barriers were in place is a
-correct implementation.
-That said, it is much easier to fool yourself into believing that you have
-adhered to the as-if rule than it is to actually adhere to it!
-<p>@@QQE@@
-
-<p>
-Note that these memory-barrier requirements do not replace the fundamental
-RCU requirement that a grace period wait for all pre-existing readers.
-On the contrary, the memory barriers called out in this section must operate in
-such a way as to <i>enforce</i> this fundamental requirement.
-Of course, different implementations enforce this requirement in different
-ways, but enforce it they must.
-
-<h3><a name="RCU Primitives Guaranteed to Execute Unconditionally">RCU Primitives Guaranteed to Execute Unconditionally</a></h3>
-
-<p>
-The common-case RCU primitives are unconditional.
-They are invoked, they do their job, and they return, with no possibility
-of error, and no need to retry.
-This is a key RCU design philosophy.
-
-<p>
-However, this philosophy is pragmatic rather than pigheaded.
-If someone comes up with a good justification for a particular conditional
-RCU primitive, it might well be implemented and added.
-After all, this guarantee was reverse-engineered, not premeditated.
-The unconditional nature of the RCU primitives was initially an
-accident of implementation, and later experience with synchronization
-primitives with conditional primitives caused me to elevate this
-accident to a guarantee.
-Therefore, the justification for adding a conditional primitive to
-RCU would need to be based on detailed and compelling use cases.
-
-<h3><a name="Guaranteed Read-to-Write Upgrade">Guaranteed Read-to-Write Upgrade</a></h3>
-
-<p>
-As far as RCU is concerned, it is always possible to carry out an
-update within an RCU read-side critical section.
-For example, that RCU read-side critical section might search for
-a given data element, and then might acquire the update-side
-spinlock in order to update that element, all while remaining
-in that RCU read-side critical section.
-Of course, it is necessary to exit the RCU read-side critical section
-before invoking <tt>synchronize_rcu()</tt>, however, this
-inconvenience can be avoided through use of the
-<tt>call_rcu()</tt> and <tt>kfree_rcu()</tt> API members
-described later in this document.
-
-<p>@@QQ@@
-But how does the upgrade-to-write operation exclude other readers?
-<p>@@QQA@@
-It doesn't, just like normal RCU updates, which also do not exclude
-RCU readers.
-<p>@@QQE@@
-
-<p>
-This guarantee allows lookup code to be shared between read-side
-and update-side code, and was premeditated, appearing in the earliest
-DYNIX/ptx RCU documentation.
-
-<h2><a name="Fundamental Non-Requirements">Fundamental Non-Requirements</a></h2>
-
-<p>
-RCU provides extremely lightweight readers, and its read-side guarantees,
-though quite useful, are correspondingly lightweight.
-It is therefore all too easy to assume that RCU is guaranteeing more
-than it really is.
-Of course, the list of things that RCU does not guarantee is infinitely
-long, however, the following sections list a few non-guarantees that
-have caused confusion.
-Except where otherwise noted, these non-guarantees were premeditated.
-
-<ol>
-<li>	<a href="#Readers Impose Minimal Ordering">
-	Readers Impose Minimal Ordering</a>
-<li>	<a href="#Readers Do Not Exclude Updaters">
-	Readers Do Not Exclude Updaters</a>
-<li>	<a href="#Updaters Only Wait For Old Readers">
-	Updaters Only Wait For Old Readers</a>
-<li>	<a href="#Grace Periods Don't Partition Read-Side Critical Sections">
-	Grace Periods Don't Partition Read-Side Critical Sections</a>
-<li>	<a href="#Read-Side Critical Sections Don't Partition Grace Periods">
-	Read-Side Critical Sections Don't Partition Grace Periods</a>
-<li>	<a href="#Disabling Preemption Does Not Block Grace Periods">
-	Disabling Preemption Does Not Block Grace Periods</a>
-</ol>
-
-<h3><a name="Readers Impose Minimal Ordering">Readers Impose Minimal Ordering</a></h3>
-
-<p>
-Reader-side markers such as <tt>rcu_read_lock()</tt> and
-<tt>rcu_read_unlock()</tt> provide absolutely no ordering guarantees
-except through their interaction with the grace-period APIs such as
-<tt>synchronize_rcu()</tt>.
-To see this, consider the following pair of threads:
-
-<blockquote>
-<pre>
- 1 void thread0(void)
- 2 {
- 3   rcu_read_lock();
- 4   WRITE_ONCE(x, 1);
- 5   rcu_read_unlock();
- 6   rcu_read_lock();
- 7   WRITE_ONCE(y, 1);
- 8   rcu_read_unlock();
- 9 }
-10
-11 void thread1(void)
-12 {
-13   rcu_read_lock();
-14   r1 = READ_ONCE(y);
-15   rcu_read_unlock();
-16   rcu_read_lock();
-17   r2 = READ_ONCE(x);
-18   rcu_read_unlock();
-19 }
-</pre>
-</blockquote>
-
-<p>
-After <tt>thread0()</tt> and <tt>thread1()</tt> execute
-concurrently, it is quite possible to have
-
-<blockquote>
-<pre>
-(r1 == 1 &amp;&amp; r2 == 0)
-</pre>
-</blockquote>
-
-(that is, <tt>y</tt> appears to have been assigned before <tt>x</tt>),
-which would not be possible if <tt>rcu_read_lock()</tt> and
-<tt>rcu_read_unlock()</tt> had much in the way of ordering
-properties.
-But they do not, so the CPU is within its rights
-to do significant reordering.
-This is by design:  Any significant ordering constraints would slow down
-these fast-path APIs.
-
-<p>@@QQ@@
-Can't the compiler also reorder this code?
-<p>@@QQA@@
-No, the volatile casts in <tt>READ_ONCE()</tt> and
-<tt>WRITE_ONCE()</tt> prevent the compiler from reordering in
-this particular case.
-<p>@@QQE@@
-
-<h3><a name="Readers Do Not Exclude Updaters">Readers Do Not Exclude Updaters</a></h3>
-
-<p>
-Neither <tt>rcu_read_lock()</tt> nor <tt>rcu_read_unlock()</tt>
-exclude updates.
-All they do is to prevent grace periods from ending.
-The following example illustrates this:
-
-<blockquote>
-<pre>
- 1 void thread0(void)
- 2 {
- 3   rcu_read_lock();
- 4   r1 = READ_ONCE(y);
- 5   if (r1) {
- 6     do_something_with_nonzero_x();
- 7     r2 = READ_ONCE(x);
- 8     WARN_ON(!r2); /* BUG!!! */
- 9   }
-10   rcu_read_unlock();
-11 }
-12
-13 void thread1(void)
-14 {
-15   spin_lock(&amp;my_lock);
-16   WRITE_ONCE(x, 1);
-17   WRITE_ONCE(y, 1);
-18   spin_unlock(&amp;my_lock);
-19 }
-</pre>
-</blockquote>
-
-<p>
-If the <tt>thread0()</tt> function's <tt>rcu_read_lock()</tt>
-excluded the <tt>thread1()</tt> function's update,
-the <tt>WARN_ON()</tt> could never fire.
-But the fact is that <tt>rcu_read_lock()</tt> does not exclude
-much of anything aside from subsequent grace periods, of which
-<tt>thread1()</tt> has none, so the
-<tt>WARN_ON()</tt> can and does fire.
-
-<h3><a name="Updaters Only Wait For Old Readers">Updaters Only Wait For Old Readers</a></h3>
-
-<p>
-It might be tempting to assume that after <tt>synchronize_rcu()</tt>
-completes, there are no readers executing.
-This temptation must be avoided because
-new readers can start immediately after <tt>synchronize_rcu()</tt>
-starts, and <tt>synchronize_rcu()</tt> is under no
-obligation to wait for these new readers.
-
-<p>@@QQ@@
-Suppose that synchronize_rcu() did wait until all readers had completed.
-Would the updater be able to rely on this?
-<p>@@QQA@@
-No.
-Even if <tt>synchronize_rcu()</tt> were to wait until
-all readers had completed, a new reader might start immediately after
-<tt>synchronize_rcu()</tt> completed.
-Therefore, the code following
-<tt>synchronize_rcu()</tt> cannot rely on there being no readers
-in any case.
-<p>@@QQE@@
-
-<h3><a name="Grace Periods Don't Partition Read-Side Critical Sections">
-Grace Periods Don't Partition Read-Side Critical Sections</a></h3>
-
-<p>
-It is tempting to assume that if any part of one RCU read-side critical
-section precedes a given grace period, and if any part of another RCU
-read-side critical section follows that same grace period, then all of
-the first RCU read-side critical section must precede all of the second.
-However, this just isn't the case: A single grace period does not
-partition the set of RCU read-side critical sections.
-An example of this situation can be illustrated as follows, where
-<tt>x</tt>, <tt>y</tt>, and <tt>z</tt> are initially all zero:
-
-<blockquote>
-<pre>
- 1 void thread0(void)
- 2 {
- 3   rcu_read_lock();
- 4   WRITE_ONCE(a, 1);
- 5   WRITE_ONCE(b, 1);
- 6   rcu_read_unlock();
- 7 }
- 8
- 9 void thread1(void)
-10 {
-11   r1 = READ_ONCE(a);
-12   synchronize_rcu();
-13   WRITE_ONCE(c, 1);
-14 }
-15
-16 void thread2(void)
-17 {
-18   rcu_read_lock();
-19   r2 = READ_ONCE(b);
-20   r3 = READ_ONCE(c);
-21   rcu_read_unlock();
-22 }
-</pre>
-</blockquote>
-
-<p>
-It turns out that the outcome:
-
-<blockquote>
-<pre>
-(r1 == 1 &amp;&amp; r2 == 0 &amp;&amp; r3 == 1)
-</pre>
-</blockquote>
-
-is entirely possible.
-The following figure show how this can happen, with each circled
-<tt>QS</tt> indicating the point at which RCU recorded a
-<i>quiescent state</i> for each thread, that is, a state in which
-RCU knows that the thread cannot be in the midst of an RCU read-side
-critical section that started before the current grace period:
-
-<p><img src="GPpartitionReaders1.svg" alt="GPpartitionReaders1.svg" width="60%"></p>
-
-<p>
-If it is necessary to partition RCU read-side critical sections in this
-manner, it is necessary to use two grace periods, where the first
-grace period is known to end before the second grace period starts:
-
-<blockquote>
-<pre>
- 1 void thread0(void)
- 2 {
- 3   rcu_read_lock();
- 4   WRITE_ONCE(a, 1);
- 5   WRITE_ONCE(b, 1);
- 6   rcu_read_unlock();
- 7 }
- 8
- 9 void thread1(void)
-10 {
-11   r1 = READ_ONCE(a);
-12   synchronize_rcu();
-13   WRITE_ONCE(c, 1);
-14 }
-15
-16 void thread2(void)
-17 {
-18   r2 = READ_ONCE(c);
-19   synchronize_rcu();
-20   WRITE_ONCE(d, 1);
-21 }
-22
-23 void thread3(void)
-24 {
-25   rcu_read_lock();
-26   r3 = READ_ONCE(b);
-27   r4 = READ_ONCE(d);
-28   rcu_read_unlock();
-29 }
-</pre>
-</blockquote>
-
-<p>
-Here, if <tt>(r1 == 1)</tt>, then
-<tt>thread0()</tt>'s write to <tt>b</tt> must happen
-before the end of <tt>thread1()</tt>'s grace period.
-If in addition <tt>(r4 == 1)</tt>, then
-<tt>thread3()</tt>'s read from <tt>b</tt> must happen
-after the beginning of <tt>thread2()</tt>'s grace period.
-If it is also the case that <tt>(r2 == 1)</tt>, then the
-end of <tt>thread1()</tt>'s grace period must precede the
-beginning of <tt>thread2()</tt>'s grace period.
-This mean that the two RCU read-side critical sections cannot overlap,
-guaranteeing that <tt>(r3 == 1)</tt>.
-As a result, the outcome:
-
-<blockquote>
-<pre>
-(r1 == 1 &amp;&amp; r2 == 1 &amp;&amp; r3 == 0 &amp;&amp; r4 == 1)
-</pre>
-</blockquote>
-
-cannot happen.
-
-<p>
-This non-requirement was also non-premeditated, but became apparent
-when studying RCU's interaction with memory ordering.
-
-<h3><a name="Read-Side Critical Sections Don't Partition Grace Periods">
-Read-Side Critical Sections Don't Partition Grace Periods</a></h3>
-
-<p>
-It is also tempting to assume that if an RCU read-side critical section
-happens between a pair of grace periods, then those grace periods cannot
-overlap.
-However, this temptation leads nowhere good, as can be illustrated by
-the following, with all variables initially zero:
-
-<blockquote>
-<pre>
- 1 void thread0(void)
- 2 {
- 3   rcu_read_lock();
- 4   WRITE_ONCE(a, 1);
- 5   WRITE_ONCE(b, 1);
- 6   rcu_read_unlock();
- 7 }
- 8
- 9 void thread1(void)
-10 {
-11   r1 = READ_ONCE(a);
-12   synchronize_rcu();
-13   WRITE_ONCE(c, 1);
-14 }
-15
-16 void thread2(void)
-17 {
-18   rcu_read_lock();
-19   WRITE_ONCE(d, 1);
-20   r2 = READ_ONCE(c);
-21   rcu_read_unlock();
-22 }
-23
-24 void thread3(void)
-25 {
-26   r3 = READ_ONCE(d);
-27   synchronize_rcu();
-28   WRITE_ONCE(e, 1);
-29 }
-30
-31 void thread4(void)
-32 {
-33   rcu_read_lock();
-34   r4 = READ_ONCE(b);
-35   r5 = READ_ONCE(e);
-36   rcu_read_unlock();
-37 }
-</pre>
-</blockquote>
-
-<p>
-In this case, the outcome:
-
-<blockquote>
-<pre>
-(r1 == 1 &amp;&amp; r2 == 1 &amp;&amp; r3 == 1 &amp;&amp; r4 == 0 &amp&amp; r5 == 1)
-</pre>
-</blockquote>
-
-is entirely possible, as illustrated below:
-
-<p><img src="ReadersPartitionGP1.svg" alt="ReadersPartitionGP1.svg" width="100%"></p>
-
-<p>
-Again, an RCU read-side critical section can overlap almost all of a
-given grace period, just so long as it does not overlap the entire
-grace period.
-As a result, an RCU read-side critical section cannot partition a pair
-of RCU grace periods.
-
-<p>@@QQ@@
-How long a sequence of grace periods, each separated by an RCU read-side
-critical section, would be required to partition the RCU read-side
-critical sections at the beginning and end of the chain?
-<p>@@QQA@@
-In theory, an infinite number.
-In practice, an unknown number that is sensitive to both implementation
-details and timing considerations.
-Therefore, even in practice, RCU users must abide by the theoretical rather
-than the practical answer.
-<p>@@QQE@@
-
-<h3><a name="Disabling Preemption Does Not Block Grace Periods">
-Disabling Preemption Does Not Block Grace Periods</a></h3>
-
-<p>
-There was a time when disabling preemption on any given CPU would block
-subsequent grace periods.
-However, this was an accident of implementation and is not a requirement.
-And in the current Linux-kernel implementation, disabling preemption
-on a given CPU in fact does not block grace periods, as Oleg Nesterov
-<a href="https://lkml.kernel.org/g/20150614193825.GA19582@redhat.com">demonstrated</a>.
-
-<p>
-If you need a preempt-disable region to block grace periods, you need to add
-<tt>rcu_read_lock()</tt> and <tt>rcu_read_unlock()</tt>, for example
-as follows:
-
-<blockquote>
-<pre>
- 1 preempt_disable();
- 2 rcu_read_lock();
- 3 do_something();
- 4 rcu_read_unlock();
- 5 preempt_enable();
- 6
- 7 /* Spinlocks implicitly disable preemption. */
- 8 spin_lock(&amp;mylock);
- 9 rcu_read_lock();
-10 do_something();
-11 rcu_read_unlock();
-12 spin_unlock(&amp;mylock);
-</pre>
-</blockquote>
-
-<p>
-In theory, you could enter the RCU read-side critical section first,
-but it is more efficient to keep the entire RCU read-side critical
-section contained in the preempt-disable region as shown above.
-Of course, RCU read-side critical sections that extend outside of
-preempt-disable regions will work correctly, but such critical sections
-can be preempted, which forces <tt>rcu_read_unlock()</tt> to do
-more work.
-And no, this is <i>not</i> an invitation to enclose all of your RCU
-read-side critical sections within preempt-disable regions, because
-doing so would degrade real-time response.
-
-<p>
-This non-requirement appeared with preemptible RCU.
-If you need a grace period that waits on non-preemptible code regions, use
-<a href="#Sched Flavor">RCU-sched</a>.
-
-<h2><a name="Parallelism Facts of Life">Parallelism Facts of Life</a></h2>
-
-<p>
-These parallelism facts of life are by no means specific to RCU, but
-the RCU implementation must abide by them.
-They therefore bear repeating:
-
-<ol>
-<li>	Any CPU or task may be delayed at any time,
-	and any attempts to avoid these delays by disabling
-	preemption, interrupts, or whatever are completely futile.
-	This is most obvious in preemptible user-level
-	environments and in virtualized environments (where
-	a given guest OS's VCPUs can be preempted at any time by
-	the underlying hypervisor), but can also happen in bare-metal
-	environments due to ECC errors, NMIs, and other hardware
-	events.
-	Although a delay of more than about 20 seconds can result
-	in splats, the RCU implementation is obligated to use
-	algorithms that can tolerate extremely long delays, but where
-	&ldquo;extremely long&rdquo; is not long enough to allow
-	wrap-around when incrementing a 64-bit counter.
-<li>	Both the compiler and the CPU can reorder memory accesses.
-	Where it matters, RCU must use compiler directives and
-	memory-barrier instructions to preserve ordering.
-<li>	Conflicting writes to memory locations in any given cache line
-	will result in expensive cache misses.
-	Greater numbers of concurrent writes and more-frequent
-	concurrent writes will result in more dramatic slowdowns.
-	RCU is therefore obligated to use algorithms that have
-	sufficient locality to avoid significant performance and
-	scalability problems.
-<li>	As a rough rule of thumb, only one CPU's worth of processing
-	may be carried out under the protection of any given exclusive
-	lock.
-	RCU must therefore use scalable locking designs.
-<li>	Counters are finite, especially on 32-bit systems.
-	RCU's use of counters must therefore tolerate counter wrap,
-	or be designed such that counter wrap would take way more
-	time than a single system is likely to run.
-	An uptime of ten years is quite possible, a runtime
-	of a century much less so.
-	As an example of the latter, RCU's dyntick-idle nesting counter
-	allows 54 bits for interrupt nesting level (this counter
-	is 64 bits even on a 32-bit system).
-	Overflowing this counter requires 2<sup>54</sup>
-	half-interrupts on a given CPU without that CPU ever going idle.
-	If a half-interrupt happened every microsecond, it would take
-	570 years of runtime to overflow this counter, which is currently
-	believed to be an acceptably long time.
-<li>	Linux systems can have thousands of CPUs running a single
-	Linux kernel in a single shared-memory environment.
-	RCU must therefore pay close attention to high-end scalability.
-</ol>
-
-<p>
-This last parallelism fact of life means that RCU must pay special
-attention to the preceding facts of life.
-The idea that Linux might scale to systems with thousands of CPUs would
-have been met with some skepticism in the 1990s, but these requirements
-would have otherwise have been unsurprising, even in the early 1990s.
-
-<h2><a name="Quality-of-Implementation Requirements">Quality-of-Implementation Requirements</a></h2>
-
-<p>
-These sections list quality-of-implementation requirements.
-Although an RCU implementation that ignores these requirements could
-still be used, it would likely be subject to limitations that would
-make it inappropriate for industrial-strength production use.
-Classes of quality-of-implementation requirements are as follows:
-
-<ol>
-<li>	<a href="#Specialization">Specialization</a>
-<li>	<a href="#Performance and Scalability">Performance and Scalability</a>
-<li>	<a href="#Composability">Composability</a>
-<li>	<a href="#Corner Cases">Corner Cases</a>
-</ol>
-
-<p>
-These classes is covered in the following sections.
-
-<h3><a name="Specialization">Specialization</a></h3>
-
-<p>
-RCU is and always has been intended primarily for read-mostly situations, as
-illustrated by the following figure.
-This means that RCU's read-side primitives are optimized, often at the
-expense of its update-side primitives.
-
-<p><img src="RCUApplicability.svg" alt="RCUApplicability.svg" width="70%"></p>
-
-<p>
-This focus on read-mostly situations means that RCU must interoperate
-with other synchronization primitives.
-For example, the <tt>add_gp()</tt> and <tt>remove_gp_synchronous()</tt>
-examples discussed earlier use RCU to protect readers and locking to
-coordinate updaters.
-However, the need extends much farther, requiring that a variety of
-synchronization primitives be legal within RCU read-side critical sections,
-including spinlocks, sequence locks, atomic operations, reference
-counters, and memory barriers.
-
-<p>@@QQ@@
-What about sleeping locks?
-<p>@@QQA@@
-These are forbidden within Linux-kernel RCU read-side critical sections
-because it is not legal to place a quiescent state (in this case,
-voluntary context switch) within an RCU read-side critical section.
-However, sleeping locks may be used within userspace RCU read-side critical
-sections, and also within Linux-kernel sleepable RCU
-<a href="#Sleepable RCU">(SRCU)</a>
-read-side critical sections.
-In addition, the -rt patchset turns spinlocks into a sleeping locks so
-that the corresponding critical sections can be preempted, which
-also means that these sleeplockified spinlocks (but not other sleeping locks!)
-may be acquire within -rt-Linux-kernel RCU read-side critical sections.
-
-<p>
-Note that it <i>is</i> legal for a normal RCU read-side critical section
-to conditionally acquire a sleeping locks (as in <tt>mutex_trylock()</tt>),
-but only as long as it does not loop indefinitely attempting to
-conditionally acquire that sleeping locks.
-The key point is that things like <tt>mutex_trylock()</tt>
-either return with the mutex held, or return an error indication if
-the mutex was not immediately available.
-Either way, <tt>mutex_trylock()</tt> returns immediately without sleeping.
-<p>@@QQE@@
-
-<p>
-It often comes as a surprise that many algorithms do not require a
-consistent view of data, but many can function in that mode,
-with network routing being the poster child.
-Internet routing algorithms take significant time to propagate
-updates, so that by the time an update arrives at a given system,
-that system has been sending network traffic the wrong way for
-a considerable length of time.
-Having a few threads continue to send traffic the wrong way for a
-few more milliseconds is clearly not a problem:  In the worst case,
-TCP retransmissions will eventually get the data where it needs to go.
-In general, when tracking the state of the universe outside of the
-computer, some level of inconsistency must be tolerated due to
-speed-of-light delays if nothing else.
-
-<p>
-Furthermore, uncertainty about external state is inherent in many cases.
-For example, a pair of veternarians might use heartbeat to determine
-whether or not a given cat was alive.
-But how long should they wait after the last heartbeat to decide that
-the cat is in fact dead?
-Waiting less than 400 milliseconds makes no sense because this would
-mean that a relaxed cat would be considered to cycle between death
-and life more than 100 times per minute.
-Moreover, just as with human beings, a cat's heart might stop for
-some period of time, so the exact wait period is a judgment call.
-One of our pair of veternarians might wait 30 seconds before pronouncing
-the cat dead, while the other might insist on waiting a full minute.
-The two veternarians would then disagree on the state of the cat during
-the final 30 seconds of the minute following the last heartbeat, as
-fancifully illustrated below:
-
-<p><img src="2013-08-is-it-dead.png" alt="2013-08-is-it-dead.png" width="431"></p>
-
-<p>
-Interestingly enough, this same situation applies to hardware.
-When push comes to shove, how do we tell whether or not some
-external server has failed?
-We send messages to it periodically, and declare it failed if we
-don't receive a response within a given period of time.
-Policy decisions can usually tolerate short
-periods of inconsistency.
-The policy was decided some time ago, and is only now being put into
-effect, so a few milliseconds of delay is normally inconsequential.
-
-<p>
-However, there are algorithms that absolutely must see consistent data.
-For example, the translation between a user-level SystemV semaphore
-ID to the corresponding in-kernel data structure is protected by RCU,
-but it is absolutely forbidden to update a semaphore that has just been
-removed.
-In the Linux kernel, this need for consistency is accommodated by acquiring
-spinlocks located in the in-kernel data structure from within
-the RCU read-side critical section, and this is indicated by the
-green box in the figure above.
-Many other techniques may be used, and are in fact used within the
-Linux kernel.
-
-<p>
-In short, RCU is not required to maintain consistency, and other
-mechanisms may be used in concert with RCU when consistency is required.
-RCU's specialization allows it to do its job extremely well, and its
-ability to interoperate with other synchronization mechanisms allows
-the right mix of synchronization tools to be used for a given job.
-
-<h3><a name="Performance and Scalability">Performance and Scalability</a></h3>
-
-<p>
-Energy efficiency is a critical component of performance today,
-and Linux-kernel RCU implementations must therefore avoid unnecessarily
-awakening idle CPUs.
-I cannot claim that this requirement was premeditated.
-In fact, I learned of it during a telephone conversation in which I
-was given &ldquo;frank and open&rdquo; feedback on the importance
-of energy efficiency in battery-powered systems and on specific
-energy-efficiency shortcomings of the Linux-kernel RCU implementation.
-In my experience, the battery-powered embedded community will consider
-any unnecessary wakeups to be extremely unfriendly acts.
-So much so that mere Linux-kernel-mailing-list posts are
-insufficient to vent their ire.
-
-<p>
-Memory consumption is not particularly important for in most
-situations, and has become decreasingly
-so as memory sizes have expanded and memory
-costs have plummeted.
-However, as I learned from Matt Mackall's
-<a href="http://elinux.org/Linux_Tiny-FAQ">bloatwatch</a>
-efforts, memory footprint is critically important on single-CPU systems with
-non-preemptible (<tt>CONFIG_PREEMPT=n</tt>) kernels, and thus
-<a href="https://lkml.kernel.org/g/20090113221724.GA15307@linux.vnet.ibm.com">tiny RCU</a>
-was born.
-Josh Triplett has since taken over the small-memory banner with his
-<a href="https://tiny.wiki.kernel.org/">Linux kernel tinification</a>
-project, which resulted in
-<a href="#Sleepable RCU">SRCU</a>
-becoming optional for those kernels not needing it.
-
-<p>
-The remaining performance requirements are, for the most part,
-unsurprising.
-For example, in keeping with RCU's read-side specialization,
-<tt>rcu_dereference()</tt> should have negligible overhead (for
-example, suppression of a few minor compiler optimizations).
-Similarly, in non-preemptible environments, <tt>rcu_read_lock()</tt> and
-<tt>rcu_read_unlock()</tt> should have exactly zero overhead.
-
-<p>
-In preemptible environments, in the case where the RCU read-side
-critical section was not preempted (as will be the case for the
-highest-priority real-time process), <tt>rcu_read_lock()</tt> and
-<tt>rcu_read_unlock()</tt> should have minimal overhead.
-In particular, they should not contain atomic read-modify-write
-operations, memory-barrier instructions, preemption disabling,
-interrupt disabling, or backwards branches.
-However, in the case where the RCU read-side critical section was preempted,
-<tt>rcu_read_unlock()</tt> may acquire spinlocks and disable interrupts.
-This is why it is better to nest an RCU read-side critical section
-within a preempt-disable region than vice versa, at least in cases
-where that critical section is short enough to avoid unduly degrading
-real-time latencies.
-
-<p>
-The <tt>synchronize_rcu()</tt> grace-period-wait primitive is
-optimized for throughput.
-It may therefore incur several milliseconds of latency in addition to
-the duration of the longest RCU read-side critical section.
-On the other hand, multiple concurrent invocations of
-<tt>synchronize_rcu()</tt> are required to use batching optimizations
-so that they can be satisfied by a single underlying grace-period-wait
-operation.
-For example, in the Linux kernel, it is not unusual for a single
-grace-period-wait operation to serve more than
-<a href="https://www.usenix.org/conference/2004-usenix-annual-technical-conference/making-rcu-safe-deep-sub-millisecond-response">1,000 separate invocations</a>
-of <tt>synchronize_rcu()</tt>, thus amortizing the per-invocation
-overhead down to nearly zero.
-However, the grace-period optimization is also required to avoid
-measurable degradation of real-time scheduling and interrupt latencies.
-
-<p>
-In some cases, the multi-millisecond <tt>synchronize_rcu()</tt>
-latencies are unacceptable.
-In these cases, <tt>synchronize_rcu_expedited()</tt> may be used
-instead, reducing the grace-period latency down to a few tens of
-microseconds on small systems, at least in cases where the RCU read-side
-critical sections are short.
-There are currently no special latency requirements for
-<tt>synchronize_rcu_expedited()</tt> on large systems, but,
-consistent with the empirical nature of the RCU specification,
-that is subject to change.
-However, there most definitely are scalability requirements:
-A storm of <tt>synchronize_rcu_expedited()</tt> invocations on 4096
-CPUs should at least make reasonable forward progress.
-In return for its shorter latencies, <tt>synchronize_rcu_expedited()</tt>
-is permitted to impose modest degradation of real-time latency
-on non-idle online CPUs.
-That said, it will likely be necessary to take further steps to reduce this
-degradation, hopefully to roughly that of a scheduling-clock interrupt.
-
-<p>
-There are a number of situations where even
-<tt>synchronize_rcu_expedited()</tt>'s reduced grace-period
-latency is unacceptable.
-In these situations, the asynchronous <tt>call_rcu()</tt> can be
-used in place of <tt>synchronize_rcu()</tt> as follows:
-
-<blockquote>
-<pre>
- 1 struct foo {
- 2   int a;
- 3   int b;
- 4   struct rcu_head rh;
- 5 };
- 6
- 7 static void remove_gp_cb(struct rcu_head *rhp)
- 8 {
- 9   struct foo *p = container_of(rhp, struct foo, rh);
-10
-11   kfree(p);
-12 }
-13
-14 bool remove_gp_asynchronous(void)
-15 {
-16   struct foo *p;
-17
-18   spin_lock(&amp;gp_lock);
-19   p = rcu_dereference(gp);
-20   if (!p) {
-21     spin_unlock(&amp;gp_lock);
-22     return false;
-23   }
-24   rcu_assign_pointer(gp, NULL);
-25   call_rcu(&amp;p-&gt;rh, remove_gp_cb);
-26   spin_unlock(&amp;gp_lock);
-27   return true;
-28 }
-</pre>
-</blockquote>
-
-<p>
-A definition of <tt>struct foo</tt> is finally needed, and appears
-on lines&nbsp;1-5.
-The function <tt>remove_gp_cb()</tt> is passed to <tt>call_rcu()</tt>
-on line&nbsp;25, and will be invoked after the end of a subsequent
-grace period.
-This gets the same effect as <tt>remove_gp_synchronous()</tt>,
-but without forcing the updater to wait for a grace period to elapse.
-The <tt>call_rcu()</tt> function may be used in a number of
-situations where neither <tt>synchronize_rcu()</tt> nor
-<tt>synchronize_rcu_expedited()</tt> would be legal,
-including within preempt-disable code, <tt>local_bh_disable()</tt> code,
-interrupt-disable code, and interrupt handlers.
-However, even <tt>call_rcu()</tt> is illegal within NMI handlers.
-The callback function (<tt>remove_gp_cb()</tt> in this case) will be
-executed within softirq (software interrupt) environment within the
-Linux kernel,
-either within a real softirq handler or under the protection
-of <tt>local_bh_disable()</tt>.
-In both the Linux kernel and in userspace, it is bad practice to
-write an RCU callback function that takes too long.
-Long-running operations should be relegated to separate threads or
-(in the Linux kernel) workqueues.
-
-<p>@@QQ@@
-Why does line&nbsp;19 use <tt>rcu_access_pointer()</tt>?
-After all, <tt>call_rcu()</tt> on line&nbsp;25 stores into the
-structure, which would interact badly with concurrent insertions.
-Doesn't this mean that <tt>rcu_dereference()</tt> is required?
-<p>@@QQA@@
-Presumably the <tt>-&gt;gp_lock</tt> acquired on line&nbsp;18 excludes
-any changes, including any insertions that <tt>rcu_dereference()</tt>
-would protect against.
-Therefore, any insertions will be delayed until after <tt>-&gt;gp_lock</tt>
-is released on line&nbsp;25, which in turn means that
-<tt>rcu_access_pointer()</tt> suffices.
-<p>@@QQE@@
-
-<p>
-However, all that <tt>remove_gp_cb()</tt> is doing is
-invoking <tt>kfree()</tt> on the data element.
-This is a common idiom, and is supported by <tt>kfree_rcu()</tt>,
-which allows &ldquo;fire and forget&rdquo; operation as shown below:
-
-<blockquote>
-<pre>
- 1 struct foo {
- 2   int a;
- 3   int b;
- 4   struct rcu_head rh;
- 5 };
- 6
- 7 bool remove_gp_faf(void)
- 8 {
- 9   struct foo *p;
-10
-11   spin_lock(&amp;gp_lock);
-12   p = rcu_dereference(gp);
-13   if (!p) {
-14     spin_unlock(&amp;gp_lock);
-15     return false;
-16   }
-17   rcu_assign_pointer(gp, NULL);
-18   kfree_rcu(p, rh);
-19   spin_unlock(&amp;gp_lock);
-20   return true;
-21 }
-</pre>
-</blockquote>
-
-<p>
-Note that <tt>remove_gp_faf()</tt> simply invokes
-<tt>kfree_rcu()</tt> and proceeds, without any need to pay any
-further attention to the subsequent grace period and <tt>kfree()</tt>.
-It is permissible to invoke <tt>kfree_rcu()</tt> from the same
-environments as for <tt>call_rcu()</tt>.
-Interestingly enough, DYNIX/ptx had the equivalents of
-<tt>call_rcu()</tt> and <tt>kfree_rcu()</tt>, but not
-<tt>synchronize_rcu()</tt>.
-This was due to the fact that RCU was not heavily used within DYNIX/ptx,
-so the very few places that needed something like
-<tt>synchronize_rcu()</tt> simply open-coded it.
-
-<p>@@QQ@@
-Earlier it was claimed that <tt>call_rcu()</tt> and
-<tt>kfree_rcu()</tt> allowed updaters to avoid being blocked
-by readers.
-But how can that be correct, given that the invocation of the callback
-and the freeing of the memory (respectively) must still wait for
-a grace period to elapse?
-<p>@@QQA@@
-We could define things this way, but keep in mind that this sort of
-definition would say that updates in garbage-collected languages
-cannot complete until the next time the garbage collector runs,
-which does not seem at all reasonable.
-The key point is that in most cases, an updater using either
-<tt>call_rcu()</tt> or <tt>kfree_rcu()</tt> can proceed to the
-next update as soon as it has invoked <tt>call_rcu()</tt> or
-<tt>kfree_rcu()</tt>, without having to wait for a subsequent
-grace period.
-<p>@@QQE@@
-
-<p>
-But what if the updater must wait for the completion of code to be
-executed after the end of the grace period, but has other tasks
-that can be carried out in the meantime?
-The polling-style <tt>get_state_synchronize_rcu()</tt> and
-<tt>cond_synchronize_rcu()</tt> functions may be used for this
-purpose, as shown below:
-
-<blockquote>
-<pre>
- 1 bool remove_gp_poll(void)
- 2 {
- 3   struct foo *p;
- 4   unsigned long s;
- 5
- 6   spin_lock(&amp;gp_lock);
- 7   p = rcu_access_pointer(gp);
- 8   if (!p) {
- 9     spin_unlock(&amp;gp_lock);
-10     return false;
-11   }
-12   rcu_assign_pointer(gp, NULL);
-13   spin_unlock(&amp;gp_lock);
-14   s = get_state_synchronize_rcu();
-15   do_something_while_waiting();
-16   cond_synchronize_rcu(s);
-17   kfree(p);
-18   return true;
-19 }
-</pre>
-</blockquote>
-
-<p>
-On line&nbsp;14, <tt>get_state_synchronize_rcu()</tt> obtains a
-&ldquo;cookie&rdquo; from RCU,
-then line&nbsp;15 carries out other tasks,
-and finally, line&nbsp;16 returns immediately if a grace period has
-elapsed in the meantime, but otherwise waits as required.
-The need for <tt>get_state_synchronize_rcu</tt> and
-<tt>cond_synchronize_rcu()</tt> has appeared quite recently,
-so it is too early to tell whether they will stand the test of time.
-
-<p>
-RCU thus provides a range of tools to allow updaters to strike the
-required tradeoff between latency, flexibility and CPU overhead.
-
-<h3><a name="Composability">Composability</a></h3>
-
-<p>
-Composability has received much attention in recent years, perhaps in part
-due to the collision of multicore hardware with object-oriented techniques
-designed in single-threaded environments for single-threaded use.
-And in theory, RCU read-side critical sections may be composed, and in
-fact may be nested arbitrarily deeply.
-In practice, as with all real-world implementations of composable
-constructs, there are limitations.
-
-<p>
-Implementations of RCU for which <tt>rcu_read_lock()</tt>
-and <tt>rcu_read_unlock()</tt> generate no code, such as
-Linux-kernel RCU when <tt>CONFIG_PREEMPT=n</tt>, can be
-nested arbitrarily deeply.
-After all, there is no overhead.
-Except that if all these instances of <tt>rcu_read_lock()</tt>
-and <tt>rcu_read_unlock()</tt> are visible to the compiler,
-compilation will eventually fail due to exhausting memory,
-mass storage, or user patience, whichever comes first.
-If the nesting is not visible to the compiler, as is the case with
-mutually recursive functions each in its own translation unit,
-stack overflow will result.
-If the nesting takes the form of loops, either the control variable
-will overflow or (in the Linux kernel) you will get an RCU CPU stall warning.
-Nevertheless, this class of RCU implementations is one
-of the most composable constructs in existence.
-
-<p>
-RCU implementations that explicitly track nesting depth
-are limited by the nesting-depth counter.
-For example, the Linux kernel's preemptible RCU limits nesting to
-<tt>INT_MAX</tt>.
-This should suffice for almost all practical purposes.
-That said, a consecutive pair of RCU read-side critical sections
-between which there is an operation that waits for a grace period
-cannot be enclosed in another RCU read-side critical section.
-This is because it is not legal to wait for a grace period within
-an RCU read-side critical section:  To do so would result either
-in deadlock or
-in RCU implicitly splitting the enclosing RCU read-side critical
-section, neither of which is conducive to a long-lived and prosperous
-kernel.
-
-<p>
-It is worth noting that RCU is not alone in limiting composability.
-For example, many transactional-memory implementations prohibit
-composing a pair of transactions separated by an irrevocable
-operation (for example, a network receive operation).
-For another example, lock-based critical sections can be composed
-surprisingly freely, but only if deadlock is avoided.
-
-<p>
-In short, although RCU read-side critical sections are highly composable,
-care is required in some situations, just as is the case for any other
-composable synchronization mechanism.
-
-<h3><a name="Corner Cases">Corner Cases</a></h3>
-
-<p>
-A given RCU workload might have an endless and intense stream of
-RCU read-side critical sections, perhaps even so intense that there
-was never a point in time during which there was not at least one
-RCU read-side critical section in flight.
-RCU cannot allow this situation to block grace periods:  As long as
-all the RCU read-side critical sections are finite, grace periods
-must also be finite.
-
-<p>
-That said, preemptible RCU implementations could potentially result
-in RCU read-side critical sections being preempted for long durations,
-which has the effect of creating a long-duration RCU read-side
-critical section.
-This situation can arise only in heavily loaded systems, but systems using
-real-time priorities are of course more vulnerable.
-Therefore, RCU priority boosting is provided to help deal with this
-case.
-That said, the exact requirements on RCU priority boosting will likely
-evolve as more experience accumulates.
-
-<p>
-Other workloads might have very high update rates.
-Although one can argue that such workloads should instead use
-something other than RCU, the fact remains that RCU must
-handle such workloads gracefully.
-This requirement is another factor driving batching of grace periods,
-but it is also the driving force behind the checks for large numbers
-of queued RCU callbacks in the <tt>call_rcu()</tt> code path.
-Finally, high update rates should not delay RCU read-side critical
-sections, although some read-side delays can occur when using
-<tt>synchronize_rcu_expedited()</tt>, courtesy of this function's use
-of <tt>try_stop_cpus()</tt>.
-(In the future, <tt>synchronize_rcu_expedited()</tt> will be
-converted to use lighter-weight inter-processor interrupts (IPIs),
-but this will still disturb readers, though to a much smaller degree.)
-
-<p>
-Although all three of these corner cases were understood in the early
-1990s, a simple user-level test consisting of <tt>close(open(path))</tt>
-in a tight loop
-in the early 2000s suddenly provided a much deeper appreciation of the
-high-update-rate corner case.
-This test also motivated addition of some RCU code to react to high update
-rates, for example, if a given CPU finds itself with more than 10,000
-RCU callbacks queued, it will cause RCU to take evasive action by
-more aggressively starting grace periods and more aggressively forcing
-completion of grace-period processing.
-This evasive action causes the grace period to complete more quickly,
-but at the cost of restricting RCU's batching optimizations, thus
-increasing the CPU overhead incurred by that grace period.
-
-<h2><a name="Software-Engineering Requirements">
-Software-Engineering Requirements</a></h2>
-
-<p>
-Between Murphy's Law and &ldquo;To err is human&rdquo;, it is necessary to
-guard against mishaps and misuse:
-
-<ol>
-<li>	It is all too easy to forget to use <tt>rcu_read_lock()</tt>
-	everywhere that it is needed, so kernels built with
-	<tt>CONFIG_PROVE_RCU=y</tt> will spat if
-	<tt>rcu_dereference()</tt> is used outside of an
-	RCU read-side critical section.
-	Update-side code can use <tt>rcu_dereference_protected()</tt>,
-	which takes a
-	<a href="https://lwn.net/Articles/371986/">lockdep expression</a>
-	to indicate what is providing the protection.
-	If the indicated protection is not provided, a lockdep splat
-	is emitted.
-
-	<p>
-	Code shared between readers and updaters can use
-	<tt>rcu_dereference_check()</tt>, which also takes a
-	lockdep expression, and emits a lockdep splat if neither
-	<tt>rcu_read_lock()</tt> nor the indicated protection
-	is in place.
-	In addition, <tt>rcu_dereference_raw()</tt> is used in those
-	(hopefully rare) cases where the required protection cannot
-	be easily described.
-	Finally, <tt>rcu_read_lock_held()</tt> is provided to
-	allow a function to verify that it has been invoked within
-	an RCU read-side critical section.
-	I was made aware of this set of requirements shortly after Thomas
-	Gleixner audited a number of RCU uses.
-<li>	A given function might wish to check for RCU-related preconditions
-	upon entry, before using any other RCU API.
-	The <tt>rcu_lockdep_assert()</tt> does this job,
-	asserting the expression in kernels having lockdep enabled
-	and doing nothing otherwise.
-<li>	It is also easy to forget to use <tt>rcu_assign_pointer()</tt>
-	and <tt>rcu_dereference()</tt>, perhaps (incorrectly)
-	substituting a simple assignment.
-	To catch this sort of error, a given RCU-protected pointer may be
-	tagged with <tt>__rcu</tt>, after which running sparse
-	with <tt>CONFIG_SPARSE_RCU_POINTER=y</tt> will complain
-	about simple-assignment accesses to that pointer.
-	Arnd Bergmann made me aware of this requirement, and also
-	supplied the needed
-	<a href="https://lwn.net/Articles/376011/">patch series</a>.
-<li>	Kernels built with <tt>CONFIG_DEBUG_OBJECTS_RCU_HEAD=y</tt>
-	will splat if a data element is passed to <tt>call_rcu()</tt>
-	twice in a row, without a grace period in between.
-	(This error is similar to a double free.)
-	The corresponding <tt>rcu_head</tt> structures that are
-	dynamically allocated are automatically tracked, but
-	<tt>rcu_head</tt> structures allocated on the stack
-	must be initialized with <tt>init_rcu_head_on_stack()</tt>
-	and cleaned up with <tt>destroy_rcu_head_on_stack()</tt>.
-	Similarly, statically allocated non-stack <tt>rcu_head</tt>
-	structures must be initialized with <tt>init_rcu_head()</tt>
-	and cleaned up with <tt>destroy_rcu_head()</tt>.
-	Mathieu Desnoyers made me aware of this requirement, and also
-	supplied the needed
-	<a href="https://lkml.kernel.org/g/20100319013024.GA28456@Krystal">patch</a>.
-<li>	An infinite loop in an RCU read-side critical section will
-	eventually trigger an RCU CPU stall warning splat, with
-	the duration of &ldquo;eventually&rdquo; being controlled by the
-	<tt>RCU_CPU_STALL_TIMEOUT</tt> <tt>Kconfig</tt> option, or,
-	alternatively, by the
-	<tt>rcupdate.rcu_cpu_stall_timeout</tt> boot/sysfs
-	parameter.
-	However, RCU is not obligated to produce this splat
-	unless there is a grace period waiting on that particular
-	RCU read-side critical section.
-	<p>
-	Some extreme workloads might intentionally delay
-	RCU grace periods, and systems running those workloads can
-	be booted with <tt>rcupdate.rcu_cpu_stall_suppress</tt>
-	to suppress the splats.
-	This kernel parameter may also be set via <tt>sysfs</tt>.
-	Furthermore, RCU CPU stall warnings are counter-productive
-	during sysrq dumps and during panics.
-	RCU therefore supplies the <tt>rcu_sysrq_start()</tt> and
-	<tt>rcu_sysrq_end()</tt> API members to be called before
-	and after long sysrq dumps.
-	RCU also supplies the <tt>rcu_panic()</tt> notifier that is
-	automatically invoked at the beginning of a panic to suppress
-	further RCU CPU stall warnings.
-
-	<p>
-	This requirement made itself known in the early 1990s, pretty
-	much the first time that it was necessary to debug a CPU stall.
-	That said, the initial implementation in DYNIX/ptx was quite
-	generic in comparison with that of Linux.
-<li>	Although it would be very good to detect pointers leaking out
-	of RCU read-side critical sections, there is currently no
-	good way of doing this.
-	One complication is the need to distinguish between pointers
-	leaking and pointers that have been handed off from RCU to
-	some other synchronization mechanism, for example, reference
-	counting.
-<li>	In kernels built with <tt>CONFIG_RCU_TRACE=y</tt>, RCU-related
-	information is provided via both debugfs and event tracing.
-<li>	Open-coded use of <tt>rcu_assign_pointer()</tt> and
-	<tt>rcu_dereference()</tt> to create typical linked
-	data structures can be surprisingly error-prone.
-	Therefore, RCU-protected
-	<a href="https://lwn.net/Articles/609973/#RCU List APIs">linked lists</a>
-	and, more recently, RCU-protected
-	<a href="https://lwn.net/Articles/612100/">hash tables</a>
-	are available.
-	Many other special-purpose RCU-protected data structures are
-	available in the Linux kernel and the userspace RCU library.
-<li>	Some linked structures are created at compile time, but still
-	require <tt>__rcu</tt> checking.
-	The <tt>RCU_POINTER_INITIALIZER()</tt> macro serves this
-	purpose.
-<li>	It is not necessary to use <tt>rcu_assign_pointer()</tt>
-	when creating linked structures that are to be published via
-	a single external pointer.
-	The <tt>RCU_INIT_POINTER()</tt> macro is provided for
-	this task and also for assigning <tt>NULL</tt> pointers
-	at runtime.
-</ol>
-
-<p>
-This not a hard-and-fast list:  RCU's diagnostic capabilities will
-continue to be guided by the number and type of usage bugs found
-in real-world RCU usage.
-
-<h2><a name="Linux Kernel Complications">Linux Kernel Complications</a></h2>
-
-<p>
-The Linux kernel provides an interesting environment for all kinds of
-software, including RCU.
-Some of the relevant points of interest are as follows:
-
-<ol>
-<li>	<a href="#Configuration">Configuration</a>.
-<li>	<a href="#Firmware Interface">Firmware Interface</a>.
-<li>	<a href="#Early Boot">Early Boot</a>.
-<li>	<a href="#Interrupts and NMIs">
-	Interrupts and non-maskable interrupts (NMIs)</a>.
-<li>	<a href="#Loadable Modules">Loadable Modules</a>.
-<li>	<a href="#Hotplug CPU">Hotplug CPU</a>.
-<li>	<a href="#Scheduler and RCU">Scheduler and RCU</a>.
-<li>	<a href="#Tracing and RCU">Tracing and RCU</a>.
-<li>	<a href="#Energy Efficiency">Energy Efficiency</a>.
-<li>	<a href="#Memory Efficiency">Memory Efficiency</a>.
-<li>	<a href="#Performance, Scalability, Response Time, and Reliability">
-	Performance, Scalability, Response Time, and Reliability</a>.
-</ol>
-
-<p>
-This list is probably incomplete, but it does give a feel for the
-most notable Linux-kernel complications.
-Each of the following sections covers one of the above topics.
-
-<h3><a name="Configuration">Configuration</a></h3>
-
-<p>
-RCU's goal is automatic configuration, so that almost nobody
-needs to worry about RCU's <tt>Kconfig</tt> options.
-And for almost all users, RCU does in fact work well
-&ldquo;out of the box.&rdquo;
-
-<p>
-However, there are specialized use cases that are handled by
-kernel boot parameters and <tt>Kconfig</tt> options.
-Unfortunately, the <tt>Kconfig</tt> system will explicitly ask users
-about new <tt>Kconfig</tt> options, which requires almost all of them
-be hidden behind a <tt>CONFIG_RCU_EXPERT</tt> <tt>Kconfig</tt> option.
-
-<p>
-This all should be quite obvious, but the fact remains that
-Linus Torvalds recently had to
-<a href="https://lkml.kernel.org/g/CA+55aFy4wcCwaL4okTs8wXhGZ5h-ibecy_Meg9C4MNQrUnwMcg@mail.gmail.com">remind</a>
-me of this requirement.
-
-<h3><a name="Firmware Interface">Firmware Interface</a></h3>
-
-<p>
-In many cases, kernel obtains information about the system from the
-firmware, and sometimes things are lost in translation.
-Or the translation is accurate, but the original message is bogus.
-
-<p>
-For example, some systems' firmware overreports the number of CPUs,
-sometimes by a large factor.
-If RCU naively believed the firmware, as it used to do,
-it would create too many per-CPU kthreads.
-Although the resulting system will still run correctly, the extra
-kthreads needlessly consume memory and can cause confusion
-when they show up in <tt>ps</tt> listings.
-
-<p>
-RCU must therefore wait for a given CPU to actually come online before
-it can allow itself to believe that the CPU actually exists.
-The resulting &ldquo;ghost CPUs&rdquo; (which are never going to
-come online) cause a number of
-<a href="https://paulmck.livejournal.com/37494.html">interesting complications</a>.
-
-<h3><a name="Early Boot">Early Boot</a></h3>
-
-<p>
-The Linux kernel's boot sequence is an interesting process,
-and RCU is used early, even before <tt>rcu_init()</tt>
-is invoked.
-In fact, a number of RCU's primitives can be used as soon as the
-initial task's <tt>task_struct</tt> is available and the
-boot CPU's per-CPU variables are set up.
-The read-side primitives (<tt>rcu_read_lock()</tt>,
-<tt>rcu_read_unlock()</tt>, <tt>rcu_dereference()</tt>,
-and <tt>rcu_access_pointer()</tt>) will operate normally very early on,
-as will <tt>rcu_assign_pointer()</tt>.
-
-<p>
-Although <tt>call_rcu()</tt> may be invoked at any
-time during boot, callbacks are not guaranteed to be invoked until after
-the scheduler is fully up and running.
-This delay in callback invocation is due to the fact that RCU does not
-invoke callbacks until it is fully initialized, and this full initialization
-cannot occur until after the scheduler has initialized itself to the
-point where RCU can spawn and run its kthreads.
-In theory, it would be possible to invoke callbacks earlier,
-however, this is not a panacea because there would be severe restrictions
-on what operations those callbacks could invoke.
-
-<p>
-Perhaps surprisingly, <tt>synchronize_rcu()</tt>,
-<a href="#Bottom-Half Flavor"><tt>synchronize_rcu_bh()</tt></a>
-(<a href="#Bottom-Half Flavor">discussed below</a>),
-and
-<a href="#Sched Flavor"><tt>synchronize_sched()</tt></a>
-will all operate normally
-during very early boot, the reason being that there is only one CPU
-and preemption is disabled.
-This means that the call <tt>synchronize_rcu()</tt> (or friends)
-itself is a quiescent
-state and thus a grace period, so the early-boot implementation can
-be a no-op.
-
-<p>
-Both <tt>synchronize_rcu_bh()</tt> and <tt>synchronize_sched()</tt>
-continue to operate normally through the remainder of boot, courtesy
-of the fact that preemption is disabled across their RCU read-side
-critical sections and also courtesy of the fact that there is still
-only one CPU.
-However, once the scheduler starts initializing, preemption is enabled.
-There is still only a single CPU, but the fact that preemption is enabled
-means that the no-op implementation of <tt>synchronize_rcu()</tt> no
-longer works in <tt>CONFIG_PREEMPT=y</tt> kernels.
-Therefore, as soon as the scheduler starts initializing, the early-boot
-fastpath is disabled.
-This means that <tt>synchronize_rcu()</tt> switches to its runtime
-mode of operation where it posts callbacks, which in turn means that
-any call to <tt>synchronize_rcu()</tt> will block until the corresponding
-callback is invoked.
-Unfortunately, the callback cannot be invoked until RCU's runtime
-grace-period machinery is up and running, which cannot happen until
-the scheduler has initialized itself sufficiently to allow RCU's
-kthreads to be spawned.
-Therefore, invoking <tt>synchronize_rcu()</tt> during scheduler
-initialization can result in deadlock.
-
-<p>@@QQ@@
-So what happens with <tt>synchronize_rcu()</tt> during
-scheduler initialization for <tt>CONFIG_PREEMPT=n</tt>
-kernels?
-<p>@@QQA@@
-In <tt>CONFIG_PREEMPT=n</tt> kernel, <tt>synchronize_rcu()</tt>
-maps directly to <tt>synchronize_sched()</tt>.
-Therefore, <tt>synchronize_rcu()</tt> works normally throughout
-boot in <tt>CONFIG_PREEMPT=n</tt> kernels.
-However, your code must also work in <tt>CONFIG_PREEMPT=y</tt> kernels,
-so it is still necessary to avoid invoking <tt>synchronize_rcu()</tt>
-during scheduler initialization.
-<p>@@QQE@@
-
-<p>
-I learned of these boot-time requirements as a result of a series of
-system hangs.
-
-<h3><a name="Interrupts and NMIs">Interrupts and NMIs</a></h3>
-
-<p>
-The Linux kernel has interrupts, and RCU read-side critical sections are
-legal within interrupt handlers and within interrupt-disabled regions
-of code, as are invocations of <tt>call_rcu()</tt>.
-
-<p>
-Some Linux-kernel architectures can enter an interrupt handler from
-non-idle process context, and then just never leave it, instead stealthily
-transitioning back to process context.
-This trick is sometimes used to invoke system calls from inside the kernel.
-These &ldquo;half-interrupts&rdquo; mean that RCU has to be very careful
-about how it counts interrupt nesting levels.
-I learned of this requirement the hard way during a rewrite
-of RCU's dyntick-idle code.
-
-<p>
-The Linux kernel has non-maskable interrupts (NMIs), and
-RCU read-side critical sections are legal within NMI handlers.
-Thankfully, RCU update-side primitives, including
-<tt>call_rcu()</tt>, are prohibited within NMI handlers.
-
-<p>
-The name notwithstanding, some Linux-kernel architectures
-can have nested NMIs, which RCU must handle correctly.
-Andy Lutomirski
-<a href="https://lkml.kernel.org/g/CALCETrXLq1y7e_dKFPgou-FKHB6Pu-r8+t-6Ds+8=va7anBWDA@mail.gmail.com">surprised me</a>
-with this requirement;
-he also kindly surprised me with
-<a href="https://lkml.kernel.org/g/CALCETrXSY9JpW3uE6H8WYk81sg56qasA2aqmjMPsq5dOtzso=g@mail.gmail.com">an algorithm</a>
-that meets this requirement.
-
-<h3><a name="Loadable Modules">Loadable Modules</a></h3>
-
-<p>
-The Linux kernel has loadable modules, and these modules can
-also be unloaded.
-After a given module has been unloaded, any attempt to call
-one of its functions results in a segmentation fault.
-The module-unload functions must therefore cancel any
-delayed calls to loadable-module functions, for example,
-any outstanding <tt>mod_timer()</tt> must be dealt with
-via <tt>del_timer_sync()</tt> or similar.
-
-<p>
-Unfortunately, there is no way to cancel an RCU callback;
-once you invoke <tt>call_rcu()</tt>, the callback function is
-going to eventually be invoked, unless the system goes down first.
-Because it is normally considered socially irresponsible to crash the system
-in response to a module unload request, we need some other way
-to deal with in-flight RCU callbacks.
-
-<p>
-RCU therefore provides
-<tt><a href="https://lwn.net/Articles/217484/">rcu_barrier()</a></tt>,
-which waits until all in-flight RCU callbacks have been invoked.
-If a module uses <tt>call_rcu()</tt>, its exit function should therefore
-prevent any future invocation of <tt>call_rcu()</tt>, then invoke
-<tt>rcu_barrier()</tt>.
-In theory, the underlying module-unload code could invoke
-<tt>rcu_barrier()</tt> unconditionally, but in practice this would
-incur unacceptable latencies.
-
-<p>
-Nikita Danilov noted this requirement for an analogous filesystem-unmount
-situation, and Dipankar Sarma incorporated <tt>rcu_barrier()</tt> into RCU.
-The need for <tt>rcu_barrier()</tt> for module unloading became
-apparent later.
-
-<h3><a name="Hotplug CPU">Hotplug CPU</a></h3>
-
-<p>
-The Linux kernel supports CPU hotplug, which means that CPUs
-can come and go.
-It is of course illegal to use any RCU API member from an offline CPU.
-This requirement was present from day one in DYNIX/ptx, but
-on the other hand, the Linux kernel's CPU-hotplug implementation
-is &ldquo;interesting.&rdquo;
-
-<p>
-The Linux-kernel CPU-hotplug implementation has notifiers that
-are used to allow the various kernel subsystems (including RCU)
-to respond appropriately to a given CPU-hotplug operation.
-Most RCU operations may be invoked from CPU-hotplug notifiers,
-including even normal synchronous grace-period operations
-such as <tt>synchronize_rcu()</tt>.
-However, expedited grace-period operations such as
-<tt>synchronize_rcu_expedited()</tt> are not supported,
-due to the fact that current implementations block CPU-hotplug
-operations, which could result in deadlock.
-
-<p>
-In addition, all-callback-wait operations such as
-<tt>rcu_barrier()</tt> are also not supported, due to the
-fact that there are phases of CPU-hotplug operations where
-the outgoing CPU's callbacks will not be invoked until after
-the CPU-hotplug operation ends, which could also result in deadlock.
-
-<h3><a name="Scheduler and RCU">Scheduler and RCU</a></h3>
-
-<p>
-RCU depends on the scheduler, and the scheduler uses RCU to
-protect some of its data structures.
-This means the scheduler is forbidden from acquiring
-the runqueue locks and the priority-inheritance locks
-in the middle of an outermost RCU read-side critical section unless either
-(1)&nbsp;it releases them before exiting that same
-RCU read-side critical section, or
-(2)&nbsp;interrupts are disabled across
-that entire RCU read-side critical section.
-This same prohibition also applies (recursively!) to any lock that is acquired
-while holding any lock to which this prohibition applies.
-Adhering to this rule prevents preemptible RCU from invoking
-<tt>rcu_read_unlock_special()</tt> while either runqueue or
-priority-inheritance locks are held, thus avoiding deadlock.
-
-<p>
-Prior to v4.4, it was only necessary to disable preemption across
-RCU read-side critical sections that acquired scheduler locks.
-In v4.4, expedited grace periods started using IPIs, and these
-IPIs could force a <tt>rcu_read_unlock()</tt> to take the slowpath.
-Therefore, this expedited-grace-period change required disabling of
-interrupts, not just preemption.
-
-<p>
-For RCU's part, the preemptible-RCU <tt>rcu_read_unlock()</tt>
-implementation must be written carefully to avoid similar deadlocks.
-In particular, <tt>rcu_read_unlock()</tt> must tolerate an
-interrupt where the interrupt handler invokes both
-<tt>rcu_read_lock()</tt> and <tt>rcu_read_unlock()</tt>.
-This possibility requires <tt>rcu_read_unlock()</tt> to use
-negative nesting levels to avoid destructive recursion via
-interrupt handler's use of RCU.
-
-<p>
-This pair of mutual scheduler-RCU requirements came as a
-<a href="https://lwn.net/Articles/453002/">complete surprise</a>.
-
-<p>
-As noted above, RCU makes use of kthreads, and it is necessary to
-avoid excessive CPU-time accumulation by these kthreads.
-This requirement was no surprise, but RCU's violation of it
-when running context-switch-heavy workloads when built with
-<tt>CONFIG_NO_HZ_FULL=y</tt>
-<a href="http://www.rdrop.com/users/paulmck/scalability/paper/BareMetal.2015.01.15b.pdf">did come as a surprise [PDF]</a>.
-RCU has made good progress towards meeting this requirement, even
-for context-switch-have <tt>CONFIG_NO_HZ_FULL=y</tt> workloads,
-but there is room for further improvement.
-
-<h3><a name="Tracing and RCU">Tracing and RCU</a></h3>
-
-<p>
-It is possible to use tracing on RCU code, but tracing itself
-uses RCU.
-For this reason, <tt>rcu_dereference_raw_notrace()</tt>
-is provided for use by tracing, which avoids the destructive
-recursion that could otherwise ensue.
-This API is also used by virtualization in some architectures,
-where RCU readers execute in environments in which tracing
-cannot be used.
-The tracing folks both located the requirement and provided the
-needed fix, so this surprise requirement was relatively painless.
-
-<h3><a name="Energy Efficiency">Energy Efficiency</a></h3>
-
-<p>
-Interrupting idle CPUs is considered socially unacceptable,
-especially by people with battery-powered embedded systems.
-RCU therefore conserves energy by detecting which CPUs are
-idle, including tracking CPUs that have been interrupted from idle.
-This is a large part of the energy-efficiency requirement,
-so I learned of this via an irate phone call.
-
-<p>
-Because RCU avoids interrupting idle CPUs, it is illegal to
-execute an RCU read-side critical section on an idle CPU.
-(Kernels built with <tt>CONFIG_PROVE_RCU=y</tt> will splat
-if you try it.)
-The <tt>RCU_NONIDLE()</tt> macro and <tt>_rcuidle</tt>
-event tracing is provided to work around this restriction.
-In addition, <tt>rcu_is_watching()</tt> may be used to
-test whether or not it is currently legal to run RCU read-side
-critical sections on this CPU.
-I learned of the need for diagnostics on the one hand
-and <tt>RCU_NONIDLE()</tt> on the other while inspecting
-idle-loop code.
-Steven Rostedt supplied <tt>_rcuidle</tt> event tracing,
-which is used quite heavily in the idle loop.
-
-<p>
-It is similarly socially unacceptable to interrupt an
-<tt>nohz_full</tt> CPU running in userspace.
-RCU must therefore track <tt>nohz_full</tt> userspace
-execution.
-And in
-<a href="https://lwn.net/Articles/558284/"><tt>CONFIG_NO_HZ_FULL_SYSIDLE=y</tt></a>
-kernels, RCU must separately track idle CPUs on the one hand and
-CPUs that are either idle or executing in userspace on the other.
-In both cases, RCU must be able to sample state at two points in
-time, and be able to determine whether or not some other CPU spent
-any time idle and/or executing in userspace.
-
-<p>
-These energy-efficiency requirements have proven quite difficult to
-understand and to meet, for example, there have been more than five
-clean-sheet rewrites of RCU's energy-efficiency code, the last of
-which was finally able to demonstrate
-<a href="http://www.rdrop.com/users/paulmck/realtime/paper/AMPenergy.2013.04.19a.pdf">real energy savings running on real hardware [PDF]</a>.
-As noted earlier,
-I learned of many of these requirements via angry phone calls:
-Flaming me on the Linux-kernel mailing list was apparently not
-sufficient to fully vent their ire at RCU's energy-efficiency bugs!
-
-<h3><a name="Memory Efficiency">Memory Efficiency</a></h3>
-
-<p>
-Although small-memory non-realtime systems can simply use Tiny RCU,
-code size is only one aspect of memory efficiency.
-Another aspect is the size of the <tt>rcu_head</tt> structure
-used by <tt>call_rcu()</tt> and <tt>kfree_rcu()</tt>.
-Although this structure contains nothing more than a pair of pointers,
-it does appear in many RCU-protected data structures, including
-some that are size critical.
-The <tt>page</tt> structure is a case in point, as evidenced by
-the many occurrences of the <tt>union</tt> keyword within that structure.
-
-<p>
-This need for memory efficiency is one reason that RCU uses hand-crafted
-singly linked lists to track the <tt>rcu_head</tt> structures that
-are waiting for a grace period to elapse.
-It is also the reason why <tt>rcu_head</tt> structures do not contain
-debug information, such as fields tracking the file and line of the
-<tt>call_rcu()</tt> or <tt>kfree_rcu()</tt> that posted them.
-Although this information might appear in debug-only kernel builds at some
-point, in the meantime, the <tt>-&gt;func</tt> field will often provide
-the needed debug information.
-
-<p>
-However, in some cases, the need for memory efficiency leads to even
-more extreme measures.
-Returning to the <tt>page</tt> structure, the <tt>rcu_head</tt> field
-shares storage with a great many other structures that are used at
-various points in the corresponding page's lifetime.
-In order to correctly resolve certain
-<a href="https://lkml.kernel.org/g/1439976106-137226-1-git-send-email-kirill.shutemov@linux.intel.com">race conditions</a>,
-the Linux kernel's memory-management subsystem needs a particular bit
-to remain zero during all phases of grace-period processing,
-and that bit happens to map to the bottom bit of the
-<tt>rcu_head</tt> structure's <tt>-&gt;next</tt> field.
-RCU makes this guarantee as long as <tt>call_rcu()</tt>
-is used to post the callback, as opposed to <tt>kfree_rcu()</tt>
-or some future &ldquo;lazy&rdquo;
-variant of <tt>call_rcu()</tt> that might one day be created for
-energy-efficiency purposes.
-
-<h3><a name="Performance, Scalability, Response Time, and Reliability">
-Performance, Scalability, Response Time, and Reliability</a></h3>
-
-<p>
-Expanding on the
-<a href="#Performance and Scalability">earlier discussion</a>,
-RCU is used heavily by hot code paths in performance-critical
-portions of the Linux kernel's networking, security, virtualization,
-and scheduling code paths.
-RCU must therefore use efficient implementations, especially in its
-read-side primitives.
-To that end, it would be good if preemptible RCU's implementation
-of <tt>rcu_read_lock()</tt> could be inlined, however, doing
-this requires resolving <tt>#include</tt> issues with the
-<tt>task_struct</tt> structure.
-
-<p>
-The Linux kernel supports hardware configurations with up to
-4096 CPUs, which means that RCU must be extremely scalable.
-Algorithms that involve frequent acquisitions of global locks or
-frequent atomic operations on global variables simply cannot be
-tolerated within the RCU implementation.
-RCU therefore makes heavy use of a combining tree based on the
-<tt>rcu_node</tt> structure.
-RCU is required to tolerate all CPUs continuously invoking any
-combination of RCU's runtime primitives with minimal per-operation
-overhead.
-In fact, in many cases, increasing load must <i>decrease</i> the
-per-operation overhead, witness the batching optimizations for
-<tt>synchronize_rcu()</tt>, <tt>call_rcu()</tt>,
-<tt>synchronize_rcu_expedited()</tt>, and <tt>rcu_barrier()</tt>.
-As a general rule, RCU must cheerfully accept whatever the
-rest of the Linux kernel decides to throw at it.
-
-<p>
-The Linux kernel is used for real-time workloads, especially
-in conjunction with the
-<a href="https://rt.wiki.kernel.org/index.php/Main_Page">-rt patchset</a>.
-The real-time-latency response requirements are such that the
-traditional approach of disabling preemption across RCU
-read-side critical sections is inappropriate.
-Kernels built with <tt>CONFIG_PREEMPT=y</tt> therefore
-use an RCU implementation that allows RCU read-side critical
-sections to be preempted.
-This requirement made its presence known after users made it
-clear that an earlier
-<a href="https://lwn.net/Articles/107930/">real-time patch</a>
-did not meet their needs, in conjunction with some
-<a href="https://lkml.kernel.org/g/20050318002026.GA2693@us.ibm.com">RCU issues</a>
-encountered by a very early version of the -rt patchset.
-
-<p>
-In addition, RCU must make do with a sub-100-microsecond real-time latency
-budget.
-In fact, on smaller systems with the -rt patchset, the Linux kernel
-provides sub-20-microsecond real-time latencies for the whole kernel,
-including RCU.
-RCU's scalability and latency must therefore be sufficient for
-these sorts of configurations.
-To my surprise, the sub-100-microsecond real-time latency budget
-<a href="http://www.rdrop.com/users/paulmck/realtime/paper/bigrt.2013.01.31a.LCA.pdf">
-applies to even the largest systems [PDF]</a>,
-up to and including systems with 4096 CPUs.
-This real-time requirement motivated the grace-period kthread, which
-also simplified handling of a number of race conditions.
-
-<p>
-Finally, RCU's status as a synchronization primitive means that
-any RCU failure can result in arbitrary memory corruption that can be
-extremely difficult to debug.
-This means that RCU must be extremely reliable, which in
-practice also means that RCU must have an aggressive stress-test
-suite.
-This stress-test suite is called <tt>rcutorture</tt>.
-
-<p>
-Although the need for <tt>rcutorture</tt> was no surprise,
-the current immense popularity of the Linux kernel is posing
-interesting&mdash;and perhaps unprecedented&mdash;validation
-challenges.
-To see this, keep in mind that there are well over one billion
-instances of the Linux kernel running today, given Android
-smartphones, Linux-powered televisions, and servers.
-This number can be expected to increase sharply with the advent of
-the celebrated Internet of Things.
-
-<p>
-Suppose that RCU contains a race condition that manifests on average
-once per million years of runtime.
-This bug will be occurring about three times per <i>day</i> across
-the installed base.
-RCU could simply hide behind hardware error rates, given that no one
-should really expect their smartphone to last for a million years.
-However, anyone taking too much comfort from this thought should
-consider the fact that in most jurisdictions, a successful multi-year
-test of a given mechanism, which might include a Linux kernel,
-suffices for a number of types of safety-critical certifications.
-In fact, rumor has it that the Linux kernel is already being used
-in production for safety-critical applications.
-I don't know about you, but I would feel quite bad if a bug in RCU
-killed someone.
-Which might explain my recent focus on validation and verification.
-
-<h2><a name="Other RCU Flavors">Other RCU Flavors</a></h2>
-
-<p>
-One of the more surprising things about RCU is that there are now
-no fewer than five <i>flavors</i>, or API families.
-In addition, the primary flavor that has been the sole focus up to
-this point has two different implementations, non-preemptible and
-preemptible.
-The other four flavors are listed below, with requirements for each
-described in a separate section.
-
-<ol>
-<li>	<a href="#Bottom-Half Flavor">Bottom-Half Flavor</a>
-<li>	<a href="#Sched Flavor">Sched Flavor</a>
-<li>	<a href="#Sleepable RCU">Sleepable RCU</a>
-<li>	<a href="#Tasks RCU">Tasks RCU</a>
-</ol>
-
-<h3><a name="Bottom-Half Flavor">Bottom-Half Flavor</a></h3>
-
-<p>
-The softirq-disable (AKA &ldquo;bottom-half&rdquo;,
-hence the &ldquo;_bh&rdquo; abbreviations)
-flavor of RCU, or <i>RCU-bh</i>, was developed by
-Dipankar Sarma to provide a flavor of RCU that could withstand the
-network-based denial-of-service attacks researched by Robert
-Olsson.
-These attacks placed so much networking load on the system
-that some of the CPUs never exited softirq execution,
-which in turn prevented those CPUs from ever executing a context switch,
-which, in the RCU implementation of that time, prevented grace periods
-from ever ending.
-The result was an out-of-memory condition and a system hang.
-
-<p>
-The solution was the creation of RCU-bh, which does
-<tt>local_bh_disable()</tt>
-across its read-side critical sections, and which uses the transition
-from one type of softirq processing to another as a quiescent state
-in addition to context switch, idle, user mode, and offline.
-This means that RCU-bh grace periods can complete even when some of
-the CPUs execute in softirq indefinitely, thus allowing algorithms
-based on RCU-bh to withstand network-based denial-of-service attacks.
-
-<p>
-Because
-<tt>rcu_read_lock_bh()</tt> and <tt>rcu_read_unlock_bh()</tt>
-disable and re-enable softirq handlers, any attempt to start a softirq
-handlers during the
-RCU-bh read-side critical section will be deferred.
-In this case, <tt>rcu_read_unlock_bh()</tt>
-will invoke softirq processing, which can take considerable time.
-One can of course argue that this softirq overhead should be associated
-with the code following the RCU-bh read-side critical section rather
-than <tt>rcu_read_unlock_bh()</tt>, but the fact
-is that most profiling tools cannot be expected to make this sort
-of fine distinction.
-For example, suppose that a three-millisecond-long RCU-bh read-side
-critical section executes during a time of heavy networking load.
-There will very likely be an attempt to invoke at least one softirq
-handler during that three milliseconds, but any such invocation will
-be delayed until the time of the <tt>rcu_read_unlock_bh()</tt>.
-This can of course make it appear at first glance as if
-<tt>rcu_read_unlock_bh()</tt> was executing very slowly.
-
-<p>
-The
-<a href="https://lwn.net/Articles/609973/#RCU Per-Flavor API Table">RCU-bh API</a>
-includes
-<tt>rcu_read_lock_bh()</tt>,
-<tt>rcu_read_unlock_bh()</tt>,
-<tt>rcu_dereference_bh()</tt>,
-<tt>rcu_dereference_bh_check()</tt>,
-<tt>synchronize_rcu_bh()</tt>,
-<tt>synchronize_rcu_bh_expedited()</tt>,
-<tt>call_rcu_bh()</tt>,
-<tt>rcu_barrier_bh()</tt>, and
-<tt>rcu_read_lock_bh_held()</tt>.
-
-<h3><a name="Sched Flavor">Sched Flavor</a></h3>
-
-<p>
-Before preemptible RCU, waiting for an RCU grace period had the
-side effect of also waiting for all pre-existing interrupt
-and NMI handlers.
-However, there are legitimate preemptible-RCU implementations that
-do not have this property, given that any point in the code outside
-of an RCU read-side critical section can be a quiescent state.
-Therefore, <i>RCU-sched</i> was created, which follows &ldquo;classic&rdquo;
-RCU in that an RCU-sched grace period waits for for pre-existing
-interrupt and NMI handlers.
-In kernels built with <tt>CONFIG_PREEMPT=n</tt>, the RCU and RCU-sched
-APIs have identical implementations, while kernels built with
-<tt>CONFIG_PREEMPT=y</tt> provide a separate implementation for each.
-
-<p>
-Note well that in <tt>CONFIG_PREEMPT=y</tt> kernels,
-<tt>rcu_read_lock_sched()</tt> and <tt>rcu_read_unlock_sched()</tt>
-disable and re-enable preemption, respectively.
-This means that if there was a preemption attempt during the
-RCU-sched read-side critical section, <tt>rcu_read_unlock_sched()</tt>
-will enter the scheduler, with all the latency and overhead entailed.
-Just as with <tt>rcu_read_unlock_bh()</tt>, this can make it look
-as if <tt>rcu_read_unlock_sched()</tt> was executing very slowly.
-However, the highest-priority task won't be preempted, so that task
-will enjoy low-overhead <tt>rcu_read_unlock_sched()</tt> invocations.
-
-<p>
-The
-<a href="https://lwn.net/Articles/609973/#RCU Per-Flavor API Table">RCU-sched API</a>
-includes
-<tt>rcu_read_lock_sched()</tt>,
-<tt>rcu_read_unlock_sched()</tt>,
-<tt>rcu_read_lock_sched_notrace()</tt>,
-<tt>rcu_read_unlock_sched_notrace()</tt>,
-<tt>rcu_dereference_sched()</tt>,
-<tt>rcu_dereference_sched_check()</tt>,
-<tt>synchronize_sched()</tt>,
-<tt>synchronize_rcu_sched_expedited()</tt>,
-<tt>call_rcu_sched()</tt>,
-<tt>rcu_barrier_sched()</tt>, and
-<tt>rcu_read_lock_sched_held()</tt>.
-However, anything that disables preemption also marks an RCU-sched
-read-side critical section, including
-<tt>preempt_disable()</tt> and <tt>preempt_enable()</tt>,
-<tt>local_irq_save()</tt> and <tt>local_irq_restore()</tt>,
-and so on.
-
-<h3><a name="Sleepable RCU">Sleepable RCU</a></h3>
-
-<p>
-For well over a decade, someone saying &ldquo;I need to block within
-an RCU read-side critical section&rdquo; was a reliable indication
-that this someone did not understand RCU.
-After all, if you are always blocking in an RCU read-side critical
-section, you can probably afford to use a higher-overhead synchronization
-mechanism.
-However, that changed with the advent of the Linux kernel's notifiers,
-whose RCU read-side critical
-sections almost never sleep, but sometimes need to.
-This resulted in the introduction of
-<a href="https://lwn.net/Articles/202847/">sleepable RCU</a>,
-or <i>SRCU</i>.
-
-<p>
-SRCU allows different domains to be defined, with each such domain
-defined by an instance of an <tt>srcu_struct</tt> structure.
-A pointer to this structure must be passed in to each SRCU function,
-for example, <tt>synchronize_srcu(&amp;ss)</tt>, where
-<tt>ss</tt> is the <tt>srcu_struct</tt> structure.
-The key benefit of these domains is that a slow SRCU reader in one
-domain does not delay an SRCU grace period in some other domain.
-That said, one consequence of these domains is that read-side code
-must pass a &ldquo;cookie&rdquo; from <tt>srcu_read_lock()</tt>
-to <tt>srcu_read_unlock()</tt>, for example, as follows:
-
-<blockquote>
-<pre>
- 1 int idx;
- 2
- 3 idx = srcu_read_lock(&amp;ss);
- 4 do_something();
- 5 srcu_read_unlock(&amp;ss, idx);
-</pre>
-</blockquote>
-
-<p>
-As noted above, it is legal to block within SRCU read-side critical sections,
-however, with great power comes great responsibility.
-If you block forever in one of a given domain's SRCU read-side critical
-sections, then that domain's grace periods will also be blocked forever.
-Of course, one good way to block forever is to deadlock, which can
-happen if any operation in a given domain's SRCU read-side critical
-section can block waiting, either directly or indirectly, for that domain's
-grace period to elapse.
-For example, this results in a self-deadlock:
-
-<blockquote>
-<pre>
- 1 int idx;
- 2
- 3 idx = srcu_read_lock(&amp;ss);
- 4 do_something();
- 5 synchronize_srcu(&amp;ss);
- 6 srcu_read_unlock(&amp;ss, idx);
-</pre>
-</blockquote>
-
-<p>
-However, if line&nbsp;5 acquired a mutex that was held across
-a <tt>synchronize_srcu()</tt> for domain <tt>ss</tt>,
-deadlock would still be possible.
-Furthermore, if line&nbsp;5 acquired a mutex that was held across
-a <tt>synchronize_srcu()</tt> for some other domain <tt>ss1</tt>,
-and if an <tt>ss1</tt>-domain SRCU read-side critical section
-acquired another mutex that was held across as <tt>ss</tt>-domain
-<tt>synchronize_srcu()</tt>,
-deadlock would again be possible.
-Such a deadlock cycle could extend across an arbitrarily large number
-of different SRCU domains.
-Again, with great power comes great responsibility.
-
-<p>
-Unlike the other RCU flavors, SRCU read-side critical sections can
-run on idle and even offline CPUs.
-This ability requires that <tt>srcu_read_lock()</tt> and
-<tt>srcu_read_unlock()</tt> contain memory barriers, which means
-that SRCU readers will run a bit slower than would RCU readers.
-It also motivates the <tt>smp_mb__after_srcu_read_unlock()</tt>
-API, which, in combination with <tt>srcu_read_unlock()</tt>,
-guarantees a full memory barrier.
-
-<p>
-The
-<a href="https://lwn.net/Articles/609973/#RCU Per-Flavor API Table">SRCU API</a>
-includes
-<tt>srcu_read_lock()</tt>,
-<tt>srcu_read_unlock()</tt>,
-<tt>srcu_dereference()</tt>,
-<tt>srcu_dereference_check()</tt>,
-<tt>synchronize_srcu()</tt>,
-<tt>synchronize_srcu_expedited()</tt>,
-<tt>call_srcu()</tt>,
-<tt>srcu_barrier()</tt>, and
-<tt>srcu_read_lock_held()</tt>.
-It also includes
-<tt>DEFINE_SRCU()</tt>,
-<tt>DEFINE_STATIC_SRCU()</tt>, and
-<tt>init_srcu_struct()</tt>
-APIs for defining and initializing <tt>srcu_struct</tt> structures.
-
-<h3><a name="Tasks RCU">Tasks RCU</a></h3>
-
-<p>
-Some forms of tracing use &ldquo;tramopolines&rdquo; to handle the
-binary rewriting required to install different types of probes.
-It would be good to be able to free old trampolines, which sounds
-like a job for some form of RCU.
-However, because it is necessary to be able to install a trace
-anywhere in the code, it is not possible to use read-side markers
-such as <tt>rcu_read_lock()</tt> and <tt>rcu_read_unlock()</tt>.
-In addition, it does not work to have these markers in the trampoline
-itself, because there would need to be instructions following
-<tt>rcu_read_unlock()</tt>.
-Although <tt>synchronize_rcu()</tt> would guarantee that execution
-reached the <tt>rcu_read_unlock()</tt>, it would not be able to
-guarantee that execution had completely left the trampoline.
-
-<p>
-The solution, in the form of
-<a href="https://lwn.net/Articles/607117/"><i>Tasks RCU</i></a>,
-is to have implicit
-read-side critical sections that are delimited by voluntary context
-switches, that is, calls to <tt>schedule()</tt>,
-<tt>cond_resched_rcu_qs()</tt>, and
-<tt>synchronize_rcu_tasks()</tt>.
-In addition, transitions to and from userspace execution also delimit
-tasks-RCU read-side critical sections.
-
-<p>
-The tasks-RCU API is quite compact, consisting only of
-<tt>call_rcu_tasks()</tt>,
-<tt>synchronize_rcu_tasks()</tt>, and
-<tt>rcu_barrier_tasks()</tt>.
-
-<h2><a name="Possible Future Changes">Possible Future Changes</a></h2>
-
-<p>
-One of the tricks that RCU uses to attain update-side scalability is
-to increase grace-period latency with increasing numbers of CPUs.
-If this becomes a serious problem, it will be necessary to rework the
-grace-period state machine so as to avoid the need for the additional
-latency.
-
-<p>
-Expedited grace periods scan the CPUs, so their latency and overhead
-increases with increasing numbers of CPUs.
-If this becomes a serious problem on large systems, it will be necessary
-to do some redesign to avoid this scalability problem.
-
-<p>
-RCU disables CPU hotplug in a few places, perhaps most notably in the
-expedited grace-period and <tt>rcu_barrier()</tt> operations.
-If there is a strong reason to use expedited grace periods in CPU-hotplug
-notifiers, it will be necessary to avoid disabling CPU hotplug.
-This would introduce some complexity, so there had better be a <i>very</i>
-good reason.
-
-<p>
-The tradeoff between grace-period latency on the one hand and interruptions
-of other CPUs on the other hand may need to be re-examined.
-The desire is of course for zero grace-period latency as well as zero
-interprocessor interrupts undertaken during an expedited grace period
-operation.
-While this ideal is unlikely to be achievable, it is quite possible that
-further improvements can be made.
-
-<p>
-The multiprocessor implementations of RCU use a combining tree that
-groups CPUs so as to reduce lock contention and increase cache locality.
-However, this combining tree does not spread its memory across NUMA
-nodes nor does it align the CPU groups with hardware features such
-as sockets or cores.
-Such spreading and alignment is currently believed to be unnecessary
-because the hotpath read-side primitives do not access the combining
-tree, nor does <tt>call_rcu()</tt> in the common case.
-If you believe that your architecture needs such spreading and alignment,
-then your architecture should also benefit from the
-<tt>rcutree.rcu_fanout_leaf</tt> boot parameter, which can be set
-to the number of CPUs in a socket, NUMA node, or whatever.
-If the number of CPUs is too large, use a fraction of the number of
-CPUs.
-If the number of CPUs is a large prime number, well, that certainly
-is an &ldquo;interesting&rdquo; architectural choice!
-More flexible arrangements might be considered, but only if
-<tt>rcutree.rcu_fanout_leaf</tt> has proven inadequate, and only
-if the inadequacy has been demonstrated by a carefully run and
-realistic system-level workload.
-
-<p>
-Please note that arrangements that require RCU to remap CPU numbers will
-require extremely good demonstration of need and full exploration of
-alternatives.
-
-<p>
-There is an embarrassingly large number of flavors of RCU, and this
-number has been increasing over time.
-Perhaps it will be possible to combine some at some future date.
-
-<p>
-RCU's various kthreads are reasonably recent additions.
-It is quite likely that adjustments will be required to more gracefully
-handle extreme loads.
-It might also be necessary to be able to relate CPU utilization by
-RCU's kthreads and softirq handlers to the code that instigated this
-CPU utilization.
-For example, RCU callback overhead might be charged back to the
-originating <tt>call_rcu()</tt> instance, though probably not
-in production kernels.
-
-<h2><a name="Summary">Summary</a></h2>
-
-<p>
-This document has presented more than two decade's worth of RCU
-requirements.
-Given that the requirements keep changing, this will not be the last
-word on this subject, but at least it serves to get an important
-subset of the requirements set forth.
-
-<h2><a name="Acknowledgments">Acknowledgments</a></h2>
-
-I am grateful to Steven Rostedt, Lai Jiangshan, Ingo Molnar,
-Oleg Nesterov, Borislav Petkov, Peter Zijlstra, Boqun Feng, and
-Andy Lutomirski for their help in rendering
-this article human readable, and to Michelle Rankin for her support
-of this effort.
-Other contributions are acknowledged in the Linux kernel's git archive.
-The cartoon is copyright (c) 2013 by Melissa Broussard,
-and is provided
-under the terms of the Creative Commons Attribution-Share Alike 3.0
-United States license.
-
-<p>@@QQAL@@
-
-</body></html>
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/RCU/RTFP.txt linux-libre-4.7-gnu/Documentation/RCU/RTFP.txt
--- linux-libre-4.6-gnu/Documentation/RCU/RTFP.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/RCU/RTFP.txt	2016-07-24 15:23:50.000000000 -0400
@@ -176,13 +176,13 @@ a history of how Linux changed RCU more
 which Mathieu Desnoyers is now maintaining [MathieuDesnoyers2009URCU]
 [MathieuDesnoyersPhD].  TINY_RCU [PaulEMcKenney2009BloatWatchRCU] made
 its appearance, as did expedited RCU [PaulEMcKenney2009expeditedRCU].
-The problem of resizeable RCU-protected hash tables may now be on a path
+The problem of resizable RCU-protected hash tables may now be on a path
 to a solution [JoshTriplett2009RPHash].  A few academic researchers are now
 using RCU to solve their parallel problems [HariKannan2009DynamicAnalysisRCU].
 
 2010 produced a simpler preemptible-RCU implementation
 based on TREE_RCU [PaulEMcKenney2010SimpleOptRCU], lockdep-RCU
-[PaulEMcKenney2010LockdepRCU], another resizeable RCU-protected hash
+[PaulEMcKenney2010LockdepRCU], another resizable RCU-protected hash
 table [HerbertXu2010RCUResizeHash] (this one consuming more memory,
 but allowing arbitrary changes in hash function, as required for DoS
 avoidance in the networking code), realization of the 2009 RCU-protected
@@ -193,7 +193,7 @@ the RCU API [PaulEMcKenney2010RCUAPI].
 [LinusTorvalds2011Linux2:6:38:rc1:NPigginVFS], an RCU-protected red-black
 tree using software transactional memory to protect concurrent updates
 (strange, but true!) [PhilHoward2011RCUTMRBTree], yet another variant of
-RCU-protected resizeable hash tables [Triplett:2011:RPHash], the 3.0 RCU
+RCU-protected resizable hash tables [Triplett:2011:RPHash], the 3.0 RCU
 trainwreck [PaulEMcKenney2011RCU3.0trainwreck], and Neil Brown's "Meet the
 Lockers" LWN article [NeilBrown2011MeetTheLockers].  Some academic
 work looked at debugging uses of RCU [Seyster:2011:RFA:2075416.2075425].
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/RCU/trace.txt linux-libre-4.7-gnu/Documentation/RCU/trace.txt
--- linux-libre-4.6-gnu/Documentation/RCU/trace.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/RCU/trace.txt	2016-07-24 15:23:50.000000000 -0400
@@ -237,17 +237,17 @@ o	"ktl" is the low-order 16 bits (in hex
 
 The output of "cat rcu/rcu_preempt/rcuexp" looks as follows:
 
-s=21872 wd0=0 wd1=0 wd2=0 wd3=5 n=0 enq=0 sc=21872
+s=21872 wd1=0 wd2=0 wd3=5 n=0 enq=0 sc=21872
 
 These fields are as follows:
 
 o	"s" is the sequence number, with an odd number indicating that
 	an expedited grace period is in progress.
 
-o	"wd0", "wd1", "wd2", and "wd3" are the number of times that an
-	attempt to start an expedited grace period found that someone
-	else had completed an expedited grace period that satisfies the
-	attempted request.  "Our work is done."
+o	"wd1", "wd2", and "wd3" are the number of times that an attempt
+	to start an expedited grace period found that someone else had
+	completed an expedited grace period that satisfies the attempted
+	request.  "Our work is done."
 
 o	"n" is number of times that a concurrent CPU-hotplug operation
 	forced a fallback to a normal grace period.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/RCU/whatisRCU.txt linux-libre-4.7-gnu/Documentation/RCU/whatisRCU.txt
--- linux-libre-4.6-gnu/Documentation/RCU/whatisRCU.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/RCU/whatisRCU.txt	2016-07-24 15:23:50.000000000 -0400
@@ -681,22 +681,30 @@ Although RCU can be used in many differe
 RCU is analogous to reader-writer locking.  The following unified
 diff shows how closely related RCU and reader-writer locking can be.
 
+	@@ -5,5 +5,5 @@ struct el {
+	 	int data;
+	 	/* Other data fields */
+	 };
+	-rwlock_t listmutex;
+	+spinlock_t listmutex;
+	 struct el head;
+
 	@@ -13,15 +14,15 @@
 		struct list_head *lp;
 		struct el *p;
 
-	-	read_lock();
+	-	read_lock(&listmutex);
 	-	list_for_each_entry(p, head, lp) {
 	+	rcu_read_lock();
 	+	list_for_each_entry_rcu(p, head, lp) {
 			if (p->key == key) {
 				*result = p->data;
-	-			read_unlock();
+	-			read_unlock(&listmutex);
 	+			rcu_read_unlock();
 				return 1;
 			}
 		}
-	-	read_unlock();
+	-	read_unlock(&listmutex);
 	+	rcu_read_unlock();
 		return 0;
 	 }
@@ -732,7 +740,7 @@ Or, for those who prefer a side-by-side
  5   int data;                          5   int data;
  6   /* Other data fields */            6   /* Other data fields */
  7 };                                   7 };
- 8 spinlock_t listmutex;                8 spinlock_t listmutex;
+ 8 rwlock_t listmutex;                  8 spinlock_t listmutex;
  9 struct el head;                      9 struct el head;
 
  1 int search(long key, int *result)    1 int search(long key, int *result)
@@ -740,15 +748,15 @@ Or, for those who prefer a side-by-side
  3   struct list_head *lp;              3   struct list_head *lp;
  4   struct el *p;                      4   struct el *p;
  5                                      5
- 6   read_lock();                       6   rcu_read_lock();
+ 6   read_lock(&listmutex);             6   rcu_read_lock();
  7   list_for_each_entry(p, head, lp) { 7   list_for_each_entry_rcu(p, head, lp) {
  8     if (p->key == key) {             8     if (p->key == key) {
  9       *result = p->data;             9       *result = p->data;
-10       read_unlock();                10       rcu_read_unlock();
+10       read_unlock(&listmutex);      10       rcu_read_unlock();
 11       return 1;                     11       return 1;
 12     }                               12     }
 13   }                                 13   }
-14   read_unlock();                    14   rcu_read_unlock();
+14   read_unlock(&listmutex);          14   rcu_read_unlock();
 15   return 0;                         15   return 0;
 16 }                                   16 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/robust-futexes.txt linux-libre-4.7-gnu/Documentation/robust-futexes.txt
--- linux-libre-4.6-gnu/Documentation/robust-futexes.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/robust-futexes.txt	2016-07-24 15:23:50.000000000 -0400
@@ -126,9 +126,9 @@ vma based method:
 
  - no VM changes are needed - 'struct address_space' is left alone.
 
- - no registration of individual locks is needed: robust mutexes dont
+ - no registration of individual locks is needed: robust mutexes don't
    need any extra per-lock syscalls. Robust mutexes thus become a very
-   lightweight primitive - so they dont force the application designer
+   lightweight primitive - so they don't force the application designer
    to do a hard choice between performance and robustness - robust
    mutexes are just as fast.
 
@@ -202,7 +202,7 @@ and the remaining bits are for the TID.
 Testing, architecture support
 -----------------------------
 
-i've tested the new syscalls on x86 and x86_64, and have made sure the
+I've tested the new syscalls on x86 and x86_64, and have made sure the
 parsing of the userspace list is robust [ ;-) ] even if the list is
 deliberately corrupted.
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/rpmsg.txt linux-libre-4.7-gnu/Documentation/rpmsg.txt
--- linux-libre-4.6-gnu/Documentation/rpmsg.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/rpmsg.txt	2016-07-24 15:23:50.000000000 -0400
@@ -249,24 +249,12 @@ MODULE_DEVICE_TABLE(rpmsg, rpmsg_driver_
 
 static struct rpmsg_driver rpmsg_sample_client = {
 	.drv.name	= KBUILD_MODNAME,
-	.drv.owner	= THIS_MODULE,
 	.id_table	= rpmsg_driver_sample_id_table,
 	.probe		= rpmsg_sample_probe,
 	.callback	= rpmsg_sample_cb,
 	.remove		= rpmsg_sample_remove,
 };
-
-static int __init init(void)
-{
-	return register_rpmsg_driver(&rpmsg_sample_client);
-}
-module_init(init);
-
-static void __exit fini(void)
-{
-	unregister_rpmsg_driver(&rpmsg_sample_client);
-}
-module_exit(fini);
+module_rpmsg_driver(rpmsg_sample_client);
 
 Note: a similar sample which can be built and loaded can be found
 in samples/rpmsg/.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/scsi/bfa.txt linux-libre-4.7-gnu/Documentation/scsi/bfa.txt
--- linux-libre-4.6-gnu/Documentation/scsi/bfa.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/scsi/bfa.txt	2016-07-24 15:23:50.000000000 -0400
@@ -50,7 +50,7 @@ be found at:
 
 http://www.brocade.com/services-support/drivers-downloads/adapters/Linux.page
 
-and then click following respective util pacakge link
+and then click following respective util package link
 
 	Version			Link
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/scsi/ChangeLog.megaraid_sas linux-libre-4.7-gnu/Documentation/scsi/ChangeLog.megaraid_sas
--- linux-libre-4.6-gnu/Documentation/scsi/ChangeLog.megaraid_sas	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/scsi/ChangeLog.megaraid_sas	2016-07-24 15:23:50.000000000 -0400
@@ -63,7 +63,7 @@ Release Date    : Sat. Feb 9, 2013 17:00
 Current Version : 06.506.00.00-rc1
 Old Version     : 06.504.01.00-rc1
     1. Add 4k FastPath DIF support.
-    2. Dont load DevHandle unless FastPath enabled.
+    2. Don't load DevHandle unless FastPath enabled.
     3. Version and Changelog update.
 -------------------------------------------------------------------------------
 Release Date    : Mon. Oct 1, 2012 17:00:00 PST 2012 -
@@ -105,7 +105,7 @@ Old Version     : 00.00.06.12-rc1
     1. Fix reglockFlags for degraded raid5/6 for MR 9360/9380.
     2. Mask off flags in ioctl path to prevent memory scribble with older
        MegaCLI versions.
-    3. Remove poll_mode_io module paramater, sysfs node, and associated code.
+    3. Remove poll_mode_io module parameter, sysfs node, and associated code.
 -------------------------------------------------------------------------------
 Release Date    : Wed. Oct 5, 2011 17:00:00 PST 2010 -
 			(emaild-id:megaraidlinux@lsi.com)
@@ -199,7 +199,7 @@ Old Version     : 00.00.04.31-rc1
 1.	Add the Online Controller Reset (OCR) to the Driver.
 	OCR is the new feature for megaraid_sas driver which
 	will allow the fw to do the chip reset which will not
-	affact the OS behavious.
+	affect the OS behavior.
 
 	To add the OCR support, driver need to do:
 		a). reset the controller chips -- Xscale and Gen2 which
@@ -233,7 +233,7 @@ Old Version     : 00.00.04.31-rc1
 	failed state.  Driver will kill adapter if can't bring back FW after the
 	this three times reset.
 4.	Add the input parameter max_sectors to 1MB support to our GEN2 controller.
-	customer can use the input paramenter max_sectors to add 1MB support to GEN2
+	customer can use the input parameter max_sectors to add 1MB support to GEN2
 	controller.
 
 1 Release Date    : Thur.  Oct 29, 2009 09:12:45 PST 2009 -
@@ -582,11 +582,11 @@ ii.	Bug fix : Disable controller interru
 
 1 Release Date    : Wed Feb 03 14:31:44 PST 2006 - Sumant Patro <Sumant.Patro@lsil.com>
 2 Current Version : 00.00.02.04
-3 Older Version   : 00.00.02.04 
+3 Older Version   : 00.00.02.04
 
-i.	Remove superflous instance_lock
+i.	Remove superfluous instance_lock
 
-	gets rid of the otherwise superflous instance_lock and avoids an unsave 
+	gets rid of the otherwise superfluous instance_lock and avoids an unsafe
 	unsynchronized access in the error handler.
 
 		- Christoph Hellwig <hch@lst.de>
@@ -594,43 +594,43 @@ i.	Remove superflous instance_lock
 
 1 Release Date    : Wed Feb 03 14:31:44 PST 2006 - Sumant Patro <Sumant.Patro@lsil.com>
 2 Current Version : 00.00.02.04
-3 Older Version   : 00.00.02.04 
+3 Older Version   : 00.00.02.04
 
 i.	Support for 1078 type (ppc IOP) controller, device id : 0x60 added.
-	During initialization, depending on the device id, the template members 
-	are initialized with function pointers specific to the ppc or 
-	xscale controllers.  
+	During initialization, depending on the device id, the template members
+	are initialized with function pointers specific to the ppc or
+	xscale controllers.
 
 		-Sumant Patro <Sumant.Patro@lsil.com>
 		
-1 Release Date    : Fri Feb 03 14:16:25 PST 2006 - Sumant Patro 
+1 Release Date    : Fri Feb 03 14:16:25 PST 2006 - Sumant Patro
 							<Sumant.Patro@lsil.com>
 2 Current Version : 00.00.02.04
-3 Older Version   : 00.00.02.02 
-i.	Register 16 byte CDB capability with scsi midlayer 
+3 Older Version   : 00.00.02.02
+i.	Register 16 byte CDB capability with scsi midlayer
 
-	"This patch properly registers the 16 byte command length capability of the 
-	megaraid_sas controlled hardware with the scsi midlayer. All megaraid_sas 
+	"This patch properly registers the 16 byte command length capability of the
+	megaraid_sas controlled hardware with the scsi midlayer. All megaraid_sas
 	hardware supports 16 byte CDB's."
 
-		-Joshua Giles <joshua_giles@dell.com> 
+		-Joshua Giles <joshua_giles@dell.com>
 
 1 Release Date    : Mon Jan 23 14:09:01 PST 2006 - Sumant Patro <Sumant.Patro@lsil.com>
 2 Current Version : 00.00.02.02
-3 Older Version   : 00.00.02.01 
+3 Older Version   : 00.00.02.01
 
-i.	New template defined to represent each family of controllers (identified by processor used). 
-	The template will have defintions that will be initialised to appropritae values for a specific family of controllers. The template definition has four function pointers. During driver initialisation the function pointers will be set based on the controller family type. This change is done to support new controllers that has different processors and thus different register set.
+i.	New template defined to represent each family of controllers (identified by processor used).
+	The template will have definitions that will be initialised to appropriate values for a specific family of controllers. The template definition has four function pointers. During driver initialisation the function pointers will be set based on the controller family type. This change is done to support new controllers that has different processors and thus different register set.
 
 		-Sumant Patro <Sumant.Patro@lsil.com>
 
 1 Release Date    : Mon Dec 19 14:36:26 PST 2005 - Sumant Patro <Sumant.Patro@lsil.com>
-2 Current Version : 00.00.02.00-rc4 
-3 Older Version   : 00.00.02.01 
+2 Current Version : 00.00.02.00-rc4
+3 Older Version   : 00.00.02.01
 
-i.	Code reorganized to remove code duplication in megasas_build_cmd. 
+i.	Code reorganized to remove code duplication in megasas_build_cmd.
 
-	"There's a lot of duplicate code megasas_build_cmd.  Move that out of the different codepathes and merge the reminder of megasas_build_cmd into megasas_queue_command"
+	"There's a lot of duplicate code megasas_build_cmd.  Move that out of the different codepaths and merge the reminder of megasas_build_cmd into megasas_queue_command"
 
 		- Christoph Hellwig <hch@lst.de>
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/scsi/g_NCR5380.txt linux-libre-4.7-gnu/Documentation/scsi/g_NCR5380.txt
--- linux-libre-4.6-gnu/Documentation/scsi/g_NCR5380.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/scsi/g_NCR5380.txt	2016-07-24 15:23:50.000000000 -0400
@@ -23,11 +23,10 @@ supported by the driver.
 
 If the default configuration does not work for you, you can use the kernel
 command lines (eg using the lilo append command):
-	ncr5380=port,irq,dma
-	ncr53c400=port,irq
-or
-	ncr5380=base,irq,dma
-	ncr53c400=base,irq
+	ncr5380=addr,irq
+	ncr53c400=addr,irq
+	ncr53c400a=addr,irq
+	dtc3181e=addr,irq
 
 The driver does not probe for any addresses or ports other than those in
 the OVERRIDE or given to the kernel as above.
@@ -36,19 +35,17 @@ This driver provides some information on
 /proc/scsi/g_NCR5380/x where x is the scsi card number as detected at boot
 time. More info to come in the future.
 
-When NCR53c400 support is compiled in, BIOS parameters will be returned by
-the driver (the raw 5380 driver does not and I don't plan to fiddle with
-it!).
-
 This driver works as a module.
 When included as a module, parameters can be passed on the insmod/modprobe
 command line:
   ncr_irq=xx   the interrupt
   ncr_addr=xx  the port or base address (for port or memory
                mapped, resp.)
-  ncr_dma=xx   the DMA
   ncr_5380=1   to set up for a NCR5380 board
   ncr_53c400=1 to set up for a NCR53C400 board
+  ncr_53c400a=1 to set up for a NCR53C400A board
+  dtc_3181e=1  to set up for a Domex Technology Corp 3181E board
+  hp_c2502=1   to set up for a Hewlett Packard C2502 board
 e.g.
 modprobe g_NCR5380 ncr_irq=5 ncr_addr=0x350 ncr_5380=1
   for a port mapped NCR5380 board or
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/scsi/scsi_eh.txt linux-libre-4.7-gnu/Documentation/scsi/scsi_eh.txt
--- linux-libre-4.6-gnu/Documentation/scsi/scsi_eh.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/scsi/scsi_eh.txt	2016-07-24 15:23:50.000000000 -0400
@@ -263,19 +263,23 @@ scmd->allowed.
 
  3. scmd recovered
     ACTION: scsi_eh_finish_cmd() is invoked to EH-finish scmd
-	- shost->host_failed--
 	- clear scmd->eh_eflags
 	- scsi_setup_cmd_retry()
 	- move from local eh_work_q to local eh_done_q
     LOCKING: none
+    CONCURRENCY: at most one thread per separate eh_work_q to
+		 keep queue manipulation lockless
 
  4. EH completes
     ACTION: scsi_eh_flush_done_q() retries scmds or notifies upper
-	    layer of failure.
+	    layer of failure. May be called concurrently but must have
+	    a no more than one thread per separate eh_work_q to
+	    manipulate the queue locklessly
 	- scmd is removed from eh_done_q and scmd->eh_entry is cleared
 	- if retry is necessary, scmd is requeued using
           scsi_queue_insert()
 	- otherwise, scsi_finish_command() is invoked for scmd
+	- zero shost->host_failed
     LOCKING: queue or finish function performs appropriate locking
 
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/scsi/scsi-parameters.txt linux-libre-4.7-gnu/Documentation/scsi/scsi-parameters.txt
--- linux-libre-4.6-gnu/Documentation/scsi/scsi-parameters.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/scsi/scsi-parameters.txt	2016-07-24 15:23:50.000000000 -0400
@@ -27,13 +27,15 @@ parameters may be changed at runtime by
 	aic79xx=	[HW,SCSI]
 			See Documentation/scsi/aic79xx.txt.
 
-	atascsi=	[HW,SCSI] Atari SCSI
+	atascsi=	[HW,SCSI]
+			See drivers/scsi/atari_scsi.c.
 
 	BusLogic=	[HW,SCSI]
 			See drivers/scsi/BusLogic.c, comment before function
 			BusLogic_ParseDriverOptions().
 
 	dtc3181e=	[HW,SCSI]
+			See Documentation/scsi/g_NCR5380.txt.
 
 	eata=		[HW,SCSI]
 
@@ -51,8 +53,8 @@ parameters may be changed at runtime by
 	ips=		[HW,SCSI] Adaptec / IBM ServeRAID controller
 			See header of drivers/scsi/ips.c.
 
-	mac5380=	[HW,SCSI] Format:
-			<can_queue>,<cmd_per_lun>,<sg_tablesize>,<hostid>,<use_tags>
+	mac5380=	[HW,SCSI]
+			See drivers/scsi/mac_scsi.c.
 
 	max_luns=	[SCSI] Maximum number of LUNs to probe.
 			Should be between 1 and 2^32-1.
@@ -65,10 +67,13 @@ parameters may be changed at runtime by
 			See header of drivers/scsi/NCR_D700.c.
 
 	ncr5380=	[HW,SCSI]
+			See Documentation/scsi/g_NCR5380.txt.
 
 	ncr53c400=	[HW,SCSI]
+			See Documentation/scsi/g_NCR5380.txt.
 
 	ncr53c400a=	[HW,SCSI]
+			See Documentation/scsi/g_NCR5380.txt.
 
 	ncr53c406a=	[HW,SCSI]
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/scsi/tcm_qla2xxx.txt linux-libre-4.7-gnu/Documentation/scsi/tcm_qla2xxx.txt
--- linux-libre-4.6-gnu/Documentation/scsi/tcm_qla2xxx.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/scsi/tcm_qla2xxx.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,22 @@
+tcm_qla2xxx jam_host attribute
+------------------------------
+There is now a new module endpoint atribute called jam_host
+attribute: jam_host: boolean=0/1
+This attribute and accompanying code is only included if the
+Kconfig parameter TCM_QLA2XXX_DEBUG is set to Y
+By default this jammer code and functionality is disabled
+
+Use this attribute to control the discarding of SCSI commands to a
+selected host.
+This may be useful for testing error handling and simulating slow drain
+and other fabric issues.
+
+Setting a boolean of 1 for the jam_host attribute for a particular host
+ will discard the commands for that host.
+Reset back to 0 to stop the jamming.
+
+Enable host 4 to be jammed
+echo 1 > /sys/kernel/config/target/qla2xxx/21:00:00:24:ff:27:8f:ae/tpgt_1/attrib/jam_host
+
+Disable jamming on host 4
+echo 0 > /sys/kernel/config/target/qla2xxx/21:00:00:24:ff:27:8f:ae/tpgt_1/attrib/jam_host
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/security/keys.txt linux-libre-4.7-gnu/Documentation/security/keys.txt
--- linux-libre-4.6-gnu/Documentation/security/keys.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/security/keys.txt	2016-07-24 15:23:50.000000000 -0400
@@ -823,6 +823,39 @@ The keyctl syscall functions are:
      A process must have search permission on the key for this function to be
      successful.
 
+ (*) Compute a Diffie-Hellman shared secret or public key
+
+       long keyctl(KEYCTL_DH_COMPUTE, struct keyctl_dh_params *params,
+		   char *buffer, size_t buflen,
+		   void *reserved);
+
+     The params struct contains serial numbers for three keys:
+
+	 - The prime, p, known to both parties
+	 - The local private key
+	 - The base integer, which is either a shared generator or the
+	   remote public key
+
+     The value computed is:
+
+	result = base ^ private (mod prime)
+
+     If the base is the shared generator, the result is the local
+     public key.  If the base is the remote public key, the result is
+     the shared secret.
+
+     The reserved argument must be set to NULL.
+
+     The buffer length must be at least the length of the prime, or zero.
+
+     If the buffer length is nonzero, the length of the result is
+     returned when it is successfully calculated and copied in to the
+     buffer. When the buffer length is zero, the minimum required
+     buffer length is returned.
+
+     This function will return error EOPNOTSUPP if the key type is not
+     supported, error ENOKEY if the key could not be found, or error
+     EACCES if the key is not readable by the caller.
 
 ===============
 KERNEL SERVICES
@@ -999,6 +1032,10 @@ payload contents" for more information.
 	struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
 				  const struct cred *cred,
 				  key_perm_t perm,
+				  int (*restrict_link)(struct key *,
+						       const struct key_type *,
+						       unsigned long,
+						       const union key_payload *),
 				  unsigned long flags,
 				  struct key *dest);
 
@@ -1010,6 +1047,24 @@ payload contents" for more information.
     KEY_ALLOC_NOT_IN_QUOTA in flags if the keyring shouldn't be accounted
     towards the user's quota).  Error ENOMEM can also be returned.
 
+    If restrict_link not NULL, it should point to a function that will be
+    called each time an attempt is made to link a key into the new keyring.
+    This function is called to check whether a key may be added into the keying
+    or not.  Callers of key_create_or_update() within the kernel can pass
+    KEY_ALLOC_BYPASS_RESTRICTION to suppress the check.  An example of using
+    this is to manage rings of cryptographic keys that are set up when the
+    kernel boots where userspace is also permitted to add keys - provided they
+    can be verified by a key the kernel already has.
+
+    When called, the restriction function will be passed the keyring being
+    added to, the key flags value and the type and payload of the key being
+    added.  Note that when a new key is being created, this is called between
+    payload preparsing and actual key creation.  The function should return 0
+    to allow the link or an error to reject it.
+
+    A convenience function, restrict_link_reject, exists to always return
+    -EPERM to in this case.
+
 
 (*) To check the validity of a key, this function can be called:
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/security/LoadPin.txt linux-libre-4.7-gnu/Documentation/security/LoadPin.txt
--- linux-libre-4.6-gnu/Documentation/security/LoadPin.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/security/LoadPin.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,17 @@
+LoadPin is a Linux Security Module that ensures all kernel-loaded files
+(modules, firmware, etc) all originate from the same filesystem, with
+the expectation that such a filesystem is backed by a read-only device
+such as dm-verity or CDROM. This allows systems that have a verified
+and/or unchangeable filesystem to enforce module and firmware loading
+restrictions without needing to sign the files individually.
+
+The LSM is selectable at build-time with CONFIG_SECURITY_LOADPIN, and
+can be controlled at boot-time with the kernel command line option
+"loadpin.enabled". By default, it is enabled, but can be disabled at
+boot ("loadpin.enabled=0").
+
+LoadPin starts pinning when it sees the first file loaded. If the
+block device backing the filesystem is not read-only, a sysctl is
+created to toggle pinning: /proc/sys/kernel/loadpin/enabled. (Having
+a mutable filesystem means pinning is mutable too, but having the
+sysctl allows for easy testing on systems with a mutable filesystem.)
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/security/self-protection.txt linux-libre-4.7-gnu/Documentation/security/self-protection.txt
--- linux-libre-4.6-gnu/Documentation/security/self-protection.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/security/self-protection.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,261 @@
+# Kernel Self-Protection
+
+Kernel self-protection is the design and implementation of systems and
+structures within the Linux kernel to protect against security flaws in
+the kernel itself. This covers a wide range of issues, including removing
+entire classes of bugs, blocking security flaw exploitation methods,
+and actively detecting attack attempts. Not all topics are explored in
+this document, but it should serve as a reasonable starting point and
+answer any frequently asked questions. (Patches welcome, of course!)
+
+In the worst-case scenario, we assume an unprivileged local attacker
+has arbitrary read and write access to the kernel's memory. In many
+cases, bugs being exploited will not provide this level of access,
+but with systems in place that defend against the worst case we'll
+cover the more limited cases as well. A higher bar, and one that should
+still be kept in mind, is protecting the kernel against a _privileged_
+local attacker, since the root user has access to a vastly increased
+attack surface. (Especially when they have the ability to load arbitrary
+kernel modules.)
+
+The goals for successful self-protection systems would be that they
+are effective, on by default, require no opt-in by developers, have no
+performance impact, do not impede kernel debugging, and have tests. It
+is uncommon that all these goals can be met, but it is worth explicitly
+mentioning them, since these aspects need to be explored, dealt with,
+and/or accepted.
+
+
+## Attack Surface Reduction
+
+The most fundamental defense against security exploits is to reduce the
+areas of the kernel that can be used to redirect execution. This ranges
+from limiting the exposed APIs available to userspace, making in-kernel
+APIs hard to use incorrectly, minimizing the areas of writable kernel
+memory, etc.
+
+### Strict kernel memory permissions
+
+When all of kernel memory is writable, it becomes trivial for attacks
+to redirect execution flow. To reduce the availability of these targets
+the kernel needs to protect its memory with a tight set of permissions.
+
+#### Executable code and read-only data must not be writable
+
+Any areas of the kernel with executable memory must not be writable.
+While this obviously includes the kernel text itself, we must consider
+all additional places too: kernel modules, JIT memory, etc. (There are
+temporary exceptions to this rule to support things like instruction
+alternatives, breakpoints, kprobes, etc. If these must exist in a
+kernel, they are implemented in a way where the memory is temporarily
+made writable during the update, and then returned to the original
+permissions.)
+
+In support of this are (the poorly named) CONFIG_DEBUG_RODATA and
+CONFIG_DEBUG_SET_MODULE_RONX, which seek to make sure that code is not
+writable, data is not executable, and read-only data is neither writable
+nor executable.
+
+#### Function pointers and sensitive variables must not be writable
+
+Vast areas of kernel memory contain function pointers that are looked
+up by the kernel and used to continue execution (e.g. descriptor/vector
+tables, file/network/etc operation structures, etc). The number of these
+variables must be reduced to an absolute minimum.
+
+Many such variables can be made read-only by setting them "const"
+so that they live in the .rodata section instead of the .data section
+of the kernel, gaining the protection of the kernel's strict memory
+permissions as described above.
+
+For variables that are initialized once at __init time, these can
+be marked with the (new and under development) __ro_after_init
+attribute.
+
+What remains are variables that are updated rarely (e.g. GDT). These
+will need another infrastructure (similar to the temporary exceptions
+made to kernel code mentioned above) that allow them to spend the rest
+of their lifetime read-only. (For example, when being updated, only the
+CPU thread performing the update would be given uninterruptible write
+access to the memory.)
+
+#### Segregation of kernel memory from userspace memory
+
+The kernel must never execute userspace memory. The kernel must also never
+access userspace memory without explicit expectation to do so. These
+rules can be enforced either by support of hardware-based restrictions
+(x86's SMEP/SMAP, ARM's PXN/PAN) or via emulation (ARM's Memory Domains).
+By blocking userspace memory in this way, execution and data parsing
+cannot be passed to trivially-controlled userspace memory, forcing
+attacks to operate entirely in kernel memory.
+
+### Reduced access to syscalls
+
+One trivial way to eliminate many syscalls for 64-bit systems is building
+without CONFIG_COMPAT. However, this is rarely a feasible scenario.
+
+The "seccomp" system provides an opt-in feature made available to
+userspace, which provides a way to reduce the number of kernel entry
+points available to a running process. This limits the breadth of kernel
+code that can be reached, possibly reducing the availability of a given
+bug to an attack.
+
+An area of improvement would be creating viable ways to keep access to
+things like compat, user namespaces, BPF creation, and perf limited only
+to trusted processes. This would keep the scope of kernel entry points
+restricted to the more regular set of normally available to unprivileged
+userspace.
+
+### Restricting access to kernel modules
+
+The kernel should never allow an unprivileged user the ability to
+load specific kernel modules, since that would provide a facility to
+unexpectedly extend the available attack surface. (The on-demand loading
+of modules via their predefined subsystems, e.g. MODULE_ALIAS_*, is
+considered "expected" here, though additional consideration should be
+given even to these.) For example, loading a filesystem module via an
+unprivileged socket API is nonsense: only the root or physically local
+user should trigger filesystem module loading. (And even this can be up
+for debate in some scenarios.)
+
+To protect against even privileged users, systems may need to either
+disable module loading entirely (e.g. monolithic kernel builds or
+modules_disabled sysctl), or provide signed modules (e.g.
+CONFIG_MODULE_SIG_FORCE, or dm-crypt with LoadPin), to keep from having
+root load arbitrary kernel code via the module loader interface.
+
+
+## Memory integrity
+
+There are many memory structures in the kernel that are regularly abused
+to gain execution control during an attack, By far the most commonly
+understood is that of the stack buffer overflow in which the return
+address stored on the stack is overwritten. Many other examples of this
+kind of attack exist, and protections exist to defend against them.
+
+### Stack buffer overflow
+
+The classic stack buffer overflow involves writing past the expected end
+of a variable stored on the stack, ultimately writing a controlled value
+to the stack frame's stored return address. The most widely used defense
+is the presence of a stack canary between the stack variables and the
+return address (CONFIG_CC_STACKPROTECTOR), which is verified just before
+the function returns. Other defenses include things like shadow stacks.
+
+### Stack depth overflow
+
+A less well understood attack is using a bug that triggers the
+kernel to consume stack memory with deep function calls or large stack
+allocations. With this attack it is possible to write beyond the end of
+the kernel's preallocated stack space and into sensitive structures. Two
+important changes need to be made for better protections: moving the
+sensitive thread_info structure elsewhere, and adding a faulting memory
+hole at the bottom of the stack to catch these overflows.
+
+### Heap memory integrity
+
+The structures used to track heap free lists can be sanity-checked during
+allocation and freeing to make sure they aren't being used to manipulate
+other memory areas.
+
+### Counter integrity
+
+Many places in the kernel use atomic counters to track object references
+or perform similar lifetime management. When these counters can be made
+to wrap (over or under) this traditionally exposes a use-after-free
+flaw. By trapping atomic wrapping, this class of bug vanishes.
+
+### Size calculation overflow detection
+
+Similar to counter overflow, integer overflows (usually size calculations)
+need to be detected at runtime to kill this class of bug, which
+traditionally leads to being able to write past the end of kernel buffers.
+
+
+## Statistical defenses
+
+While many protections can be considered deterministic (e.g. read-only
+memory cannot be written to), some protections provide only statistical
+defense, in that an attack must gather enough information about a
+running system to overcome the defense. While not perfect, these do
+provide meaningful defenses.
+
+### Canaries, blinding, and other secrets
+
+It should be noted that things like the stack canary discussed earlier
+are technically statistical defenses, since they rely on a (leakable)
+secret value.
+
+Blinding literal values for things like JITs, where the executable
+contents may be partially under the control of userspace, need a similar
+secret value.
+
+It is critical that the secret values used must be separate (e.g.
+different canary per stack) and high entropy (e.g. is the RNG actually
+working?) in order to maximize their success.
+
+### Kernel Address Space Layout Randomization (KASLR)
+
+Since the location of kernel memory is almost always instrumental in
+mounting a successful attack, making the location non-deterministic
+raises the difficulty of an exploit. (Note that this in turn makes
+the value of leaks higher, since they may be used to discover desired
+memory locations.)
+
+#### Text and module base
+
+By relocating the physical and virtual base address of the kernel at
+boot-time (CONFIG_RANDOMIZE_BASE), attacks needing kernel code will be
+frustrated. Additionally, offsetting the module loading base address
+means that even systems that load the same set of modules in the same
+order every boot will not share a common base address with the rest of
+the kernel text.
+
+#### Stack base
+
+If the base address of the kernel stack is not the same between processes,
+or even not the same between syscalls, targets on or beyond the stack
+become more difficult to locate.
+
+#### Dynamic memory base
+
+Much of the kernel's dynamic memory (e.g. kmalloc, vmalloc, etc) ends up
+being relatively deterministic in layout due to the order of early-boot
+initializations. If the base address of these areas is not the same
+between boots, targeting them is frustrated, requiring a leak specific
+to the region.
+
+
+## Preventing Leaks
+
+Since the locations of sensitive structures are the primary target for
+attacks, it is important to defend against leaks of both kernel memory
+addresses and kernel memory contents (since they may contain kernel
+addresses or other sensitive things like canary values).
+
+### Unique identifiers
+
+Kernel memory addresses must never be used as identifiers exposed to
+userspace. Instead, use an atomic counter, an idr, or similar unique
+identifier.
+
+### Memory initialization
+
+Memory copied to userspace must always be fully initialized. If not
+explicitly memset(), this will require changes to the compiler to make
+sure structure holes are cleared.
+
+### Memory poisoning
+
+When releasing memory, it is best to poison the contents (clear stack on
+syscall return, wipe heap memory on a free), to avoid reuse attacks that
+rely on the old contents of memory. This frustrates many uninitialized
+variable attacks, stack info leaks, heap info leaks, and use-after-free
+attacks.
+
+### Destination tracking
+
+To help kill classes of bugs that result in kernel addresses being
+written to userspace, the destination of writes needs to be tracked. If
+the buffer is destined for userspace (e.g. seq_file backed /proc files),
+it should automatically censor sensitive values.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/serial/driver linux-libre-4.7-gnu/Documentation/serial/driver
--- linux-libre-4.6-gnu/Documentation/serial/driver	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/serial/driver	2016-07-24 15:23:50.000000000 -0400
@@ -28,7 +28,7 @@ The serial core provides a few helper fu
 the correct port structure (via uart_get_console) and decoding command line
 arguments (uart_parse_options).
 
-There is also a helper function (uart_write_console) which performs a
+There is also a helper function (uart_console_write) which performs a
 character by character write, translating newlines to CRLF sequences.
 Driver writers are recommended to use this function rather than implementing
 their own version.
@@ -41,27 +41,23 @@ It is the responsibility of the low leve
 necessary locking using port->lock.  There are some exceptions (which
 are described in the uart_ops listing below.)
 
-There are three locks.  A per-port spinlock, a per-port tmpbuf semaphore,
-and an overall semaphore.
+There are two locks.  A per-port spinlock, and an overall semaphore.
 
 From the core driver perspective, the port->lock locks the following
 data:
 
 	port->mctrl
 	port->icount
-	info->xmit.head (circ->head)
-	info->xmit.tail (circ->tail)
+	port->state->xmit.head (circ_buf->head)
+	port->state->xmit.tail (circ_buf->tail)
 
 The low level driver is free to use this lock to provide any additional
 locking.
 
-The core driver uses the info->tmpbuf_sem lock to prevent multi-threaded
-access to the info->tmpbuf bouncebuffer used for port writes.
-
 The port_sem semaphore is used to protect against ports being added/
 removed or reconfigured at inappropriate times. Since v2.6.27, this
 semaphore has been the 'mutex' member of the tty_port struct, and
-commonly referred to as the port mutex (or port->mutex).
+commonly referred to as the port mutex.
 
 
 uart_ops
@@ -135,6 +131,24 @@ hardware.
 	Interrupts: locally disabled.
 	This call must not sleep
 
+  throttle(port)
+	Notify the serial driver that input buffers for the line discipline are
+	close to full, and it should somehow signal that no more characters
+	should be sent to the serial port.
+	This will be called only if hardware assisted flow control is enabled.
+
+	Locking: serialized with .unthrottle() and termios modification by the
+		 tty layer.
+
+  unthrottle(port)
+	Notify the serial driver that characters can now be sent to the serial
+	port without fear of overrunning the input buffers of the line
+	disciplines.
+	This will be called only if hardware assisted flow control is enabled.
+
+	Locking: serialized with .throttle() and termios modification by the
+		 tty layer.
+
   send_xchar(port,ch)
 	Transmit a high priority character, even if the port is stopped.
 	This is used to implement XON/XOFF flow control and tcflow().  If
@@ -172,9 +186,7 @@ hardware.
 	should be terminated when another call is made with a zero
 	ctl.
 
-	Locking: none.
-	Interrupts: caller dependent.
-	This call must not sleep
+	Locking: caller holds tty_port->mutex
 
   startup(port)
 	Grab any interrupt resources and initialise any low level driver
@@ -192,7 +204,7 @@ hardware.
 	RTS nor DTR; this will have already been done via a separate
 	call to set_mctrl.
 
-	Drivers must not access port->info once this call has completed.
+	Drivers must not access port->state once this call has completed.
 
 	This method will only be called when there are no more users of
 	this port.
@@ -204,7 +216,7 @@ hardware.
 	Flush any write buffers, reset any DMA state and stop any
 	ongoing DMA transfers.
 
-	This will be called whenever the port->info->xmit circular
+	This will be called whenever the port->state->xmit circular
 	buffer is cleared.
 
 	Locking: port->lock taken.
@@ -250,10 +262,15 @@ hardware.
 	Other flags may be used (eg, xon/xoff characters) if your
 	hardware supports hardware "soft" flow control.
 
-	Locking: caller holds port->mutex
+	Locking: caller holds tty_port->mutex
 	Interrupts: caller dependent.
 	This call must not sleep
 
+  set_ldisc(port,termios)
+	Notifier for discipline change. See Documentation/serial/tty.txt.
+
+	Locking: caller holds tty_port->mutex
+
   pm(port,state,oldstate)
 	Perform any power management related activities on the specified
 	port.  State indicates the new state (defined by
@@ -371,7 +388,7 @@ uart_get_baud_rate(port,termios,old,min,
 	Interrupts: n/a
 
 uart_get_divisor(port,baud)
-	Return the divsor (baud_base / baud) for the specified baud
+	Return the divisor (baud_base / baud) for the specified baud
 	rate, appropriately rounded.
 
 	If 38400 baud and custom divisor is selected, return the
@@ -449,11 +466,12 @@ mctrl_gpio_init(port, idx):
 
 mctrl_gpio_free(dev, gpios):
 	This will free the requested gpios in mctrl_gpio_init().
-	As devm_* function are used, there's generally no need to call
+	As devm_* functions are used, there's generally no need to call
 	this function.
 
 mctrl_gpio_to_gpiod(gpios, gidx)
-	This returns the gpio structure associated to the modem line index.
+	This returns the gpio_desc structure associated to the modem line
+	index.
 
 mctrl_gpio_set(gpios, mctrl):
 	This will sets the gpios according to the mctrl state.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/serial/tty.txt linux-libre-4.7-gnu/Documentation/serial/tty.txt
--- linux-libre-4.6-gnu/Documentation/serial/tty.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/serial/tty.txt	2016-07-24 15:23:50.000000000 -0400
@@ -210,9 +210,6 @@ TTY_IO_ERROR		If set, causes all subsequ
 
 TTY_OTHER_CLOSED	Device is a pty and the other side has closed.
 
-TTY_OTHER_DONE		Device is a pty and the other side has closed and
-			all pending input processing has been completed.
-
 TTY_NO_WRITE_SPLIT	Prevent driver from splitting up writes into
 			smaller chunks.
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/sound/alsa/compress_offload.txt linux-libre-4.7-gnu/Documentation/sound/alsa/compress_offload.txt
--- linux-libre-4.6-gnu/Documentation/sound/alsa/compress_offload.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/sound/alsa/compress_offload.txt	2016-07-24 15:23:50.000000000 -0400
@@ -149,7 +149,7 @@ Gapless Playback
 ================
 When playing thru an album, the decoders have the ability to skip the encoder
 delay and padding and directly move from one track content to another. The end
-user can perceive this as gapless playback as we dont have silence while
+user can perceive this as gapless playback as we don't have silence while
 switching from one track to another
 
 Also, there might be low-intensity noises due to encoding. Perfect gapless is
@@ -184,7 +184,7 @@ Sequence flow for gapless would be:
 - Fill data of the first track
 - Trigger start
 - User-space finished sending all,
-- Indicaite next track data by sending set_next_track
+- Indicate next track data by sending set_next_track
 - Set metadata of the next track
 - then call partial_drain to flush most of buffer in DSP
 - Fill data of the next track
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/sound/alsa/HD-Audio.txt linux-libre-4.7-gnu/Documentation/sound/alsa/HD-Audio.txt
--- linux-libre-4.6-gnu/Documentation/sound/alsa/HD-Audio.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/sound/alsa/HD-Audio.txt	2016-07-24 15:23:50.000000000 -0400
@@ -655,17 +655,6 @@ development branches in general while th
 and next kernels are found in for-linus and for-next branches,
 respectively.
 
-If you are using the latest Linus tree, it'd be better to pull the
-above GIT tree onto it.  If you are using the older kernels, an easy
-way to try the latest ALSA code is to build from the snapshot
-tarball.  There are daily tarballs and the latest snapshot tarball.
-All can be built just like normal alsa-driver release packages, that
-is, installed via the usual spells: configure, make and make
-install(-modules).  See INSTALL in the package.  The snapshot tarballs
-are found at:
-
-- ftp://ftp.suse.com/pub/people/tiwai/snapshot/
-
 
 Sending a Bug Report
 ~~~~~~~~~~~~~~~~~~~~
@@ -699,7 +688,12 @@ problems.
 alsa-info
 ~~~~~~~~~
 The script `alsa-info.sh` is a very useful tool to gather the audio
-device information.  You can fetch the latest version from:
+device information.  It's included in alsa-utils package.  The latest
+version can be found on git repository:
+
+- git://git.alsa-project.org/alsa-utils.git
+
+The script can be fetched directly from the following URL, too:
 
 - http://www.alsa-project.org/alsa-info.sh
 
@@ -836,15 +830,11 @@ can get a proc-file dump at the current
 (mixer) elements, set/get the control element value, simulate the PCM
 operation, the jack plugging simulation, etc.
 
-The package is found in:
-
-- ftp://ftp.suse.com/pub/people/tiwai/misc/
-
-A git repository is available:
+The program is found in the git repository below:
 
 - git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/hda-emu.git
 
-See README file in the tarball for more details about hda-emu
+See README file in the repository for more details about hda-emu
 program.
 
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/sound/alsa/soc/dapm.txt linux-libre-4.7-gnu/Documentation/sound/alsa/soc/dapm.txt
--- linux-libre-4.6-gnu/Documentation/sound/alsa/soc/dapm.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/sound/alsa/soc/dapm.txt	2016-07-24 15:23:50.000000000 -0400
@@ -132,7 +132,7 @@ SOC_DAPM_SINGLE("HiFi Playback Switch",
 SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1, wm8731_output_mixer_controls,
 	ARRAY_SIZE(wm8731_output_mixer_controls)),
 
-If you dont want the mixer elements prefixed with the name of the mixer widget,
+If you don't want the mixer elements prefixed with the name of the mixer widget,
 you can use SND_SOC_DAPM_MIXER_NAMED_CTL instead. the parameters are the same
 as for SND_SOC_DAPM_MIXER.
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/sound/alsa/soc/overview.txt linux-libre-4.7-gnu/Documentation/sound/alsa/soc/overview.txt
--- linux-libre-4.6-gnu/Documentation/sound/alsa/soc/overview.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/sound/alsa/soc/overview.txt	2016-07-24 15:23:50.000000000 -0400
@@ -63,7 +63,7 @@ multiple re-usable component drivers :-
     and any audio DSP drivers for that platform.
 
   * Machine class driver: The machine driver class acts as the glue that
-    decribes and binds the other component drivers together to form an ALSA
+    describes and binds the other component drivers together to form an ALSA
     "sound card device". It handles any machine specific controls and
     machine level audio events (e.g. turning on an amp at start of playback).
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/sound/alsa/timestamping.txt linux-libre-4.7-gnu/Documentation/sound/alsa/timestamping.txt
--- linux-libre-4.6-gnu/Documentation/sound/alsa/timestamping.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/sound/alsa/timestamping.txt	2016-07-24 15:23:50.000000000 -0400
@@ -129,7 +129,7 @@ will be required to issue multiple queri
 interpolation of the results
 
 In some hardware-specific configuration, the system timestamp is
-latched by a low-level audio subsytem, and the information provided
+latched by a low-level audio subsystem, and the information provided
 back to the driver. Due to potential delays in the communication with
 the hardware, there is a risk of misalignment with the avail and delay
 information. To make sure applications are not confused, a
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/sync_file.txt linux-libre-4.7-gnu/Documentation/sync_file.txt
--- linux-libre-4.6-gnu/Documentation/sync_file.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/sync_file.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,69 @@
+			      Sync File API Guide
+			      ~~~~~~~~~~~~~~~~~~~
+
+				Gustavo Padovan
+			  <gustavo at padovan dot org>
+
+This document serves as a guide for device drivers writers on what the
+sync_file API is, and how drivers can support it. Sync file is the carrier of
+the fences(struct fence) that needs to synchronized between drivers or across
+process boundaries.
+
+The sync_file API is meant to be used to send and receive fence information
+to/from userspace. It enables userspace to do explicit fencing, where instead
+of attaching a fence to the buffer a producer driver (such as a GPU or V4L
+driver) sends the fence related to the buffer to userspace via a sync_file.
+
+The sync_file then can be sent to the consumer (DRM driver for example), that
+will not use the buffer for anything before the fence(s) signals, i.e., the
+driver that issued the fence is not using/processing the buffer anymore, so it
+signals that the buffer is ready to use. And vice-versa for the consumer ->
+producer part of the cycle.
+
+Sync files allows userspace awareness on buffer sharing synchronization between
+drivers.
+
+Sync file was originally added in the Android kernel but current Linux Desktop
+can benefit a lot from it.
+
+in-fences and out-fences
+------------------------
+
+Sync files can go either to or from userspace. When a sync_file is sent from
+the driver to userspace we call the fences it contains 'out-fences'. They are
+related to a buffer that the driver is processing or is going to process, so
+the driver an create out-fence to be able to notify, through fence_signal(),
+when it has finished using (or processing) that buffer. Out-fences are fences
+that the driver creates.
+
+On the other hand if the driver receives fence(s) through a sync_file from
+userspace we call these fence(s) 'in-fences'. Receiveing in-fences means that
+we need to wait for the fence(s) to signal before using any buffer related to
+the in-fences.
+
+Creating Sync Files
+-------------------
+
+When a driver needs to send an out-fence userspace it creates a sync_file.
+
+Interface:
+	struct sync_file *sync_file_create(struct fence *fence);
+
+The caller pass the out-fence and gets back the sync_file. That is just the
+first step, next it needs to install an fd on sync_file->file. So it gets an
+fd:
+
+	fd = get_unused_fd_flags(O_CLOEXEC);
+
+and installs it on sync_file->file:
+
+	fd_install(fd, sync_file->file);
+
+The sync_file fd now can be sent to userspace.
+
+If the creation process fail, or the sync_file needs to be released by any
+other reason fput(sync_file->file) should be used.
+
+References:
+[1] struct sync_file in include/linux/sync_file.h
+[2] All interfaces mentioned above defined in include/linux/sync_file.h
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/sysctl/kernel.txt linux-libre-4.7-gnu/Documentation/sysctl/kernel.txt
--- linux-libre-4.6-gnu/Documentation/sysctl/kernel.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/sysctl/kernel.txt	2016-07-24 15:23:50.000000000 -0400
@@ -60,6 +60,8 @@ show up in /proc/sys/kernel:
 - panic_on_warn
 - perf_cpu_time_max_percent
 - perf_event_paranoid
+- perf_event_max_stack
+- perf_event_max_contexts_per_stack
 - pid_max
 - powersave-nap               [ PPC only ]
 - printk
@@ -654,6 +656,32 @@ users (without CAP_SYS_ADMIN).  The defa
 
 ==============================================================
 
+perf_event_max_stack:
+
+Controls maximum number of stack frames to copy for (attr.sample_type &
+PERF_SAMPLE_CALLCHAIN) configured events, for instance, when using
+'perf record -g' or 'perf trace --call-graph fp'.
+
+This can only be done when no events are in use that have callchains
+enabled, otherwise writing to this file will return -EBUSY.
+
+The default value is 127.
+
+==============================================================
+
+perf_event_max_contexts_per_stack:
+
+Controls maximum number of stack frame context entries for
+(attr.sample_type & PERF_SAMPLE_CALLCHAIN) configured events, for
+instance, when using 'perf record -g' or 'perf trace --call-graph fp'.
+
+This can only be done when no events are in use that have callchains
+enabled, otherwise writing to this file will return -EBUSY.
+
+The default value is 8.
+
+==============================================================
+
 pid_max:
 
 PID allocation wrap value.  When the kernel's next PID value
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/sysctl/net.txt linux-libre-4.7-gnu/Documentation/sysctl/net.txt
--- linux-libre-4.6-gnu/Documentation/sysctl/net.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/sysctl/net.txt	2016-07-24 15:23:50.000000000 -0400
@@ -43,6 +43,17 @@ Values :
 	1 - enable the JIT
 	2 - enable the JIT and ask the compiler to emit traces on kernel log.
 
+bpf_jit_harden
+--------------
+
+This enables hardening for the Berkeley Packet Filter Just in Time compiler.
+Supported are eBPF JIT backends. Enabling hardening trades off performance,
+but can mitigate JIT spraying.
+Values :
+	0 - disable JIT hardening (default value)
+	1 - enable JIT hardening for unprivileged users only
+	2 - enable JIT hardening for all users
+
 dev_weight
 --------------
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/sysctl/vm.txt linux-libre-4.7-gnu/Documentation/sysctl/vm.txt
--- linux-libre-4.6-gnu/Documentation/sysctl/vm.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/sysctl/vm.txt	2016-07-24 15:23:50.000000000 -0400
@@ -57,6 +57,7 @@ Currently, these files are in /proc/sys/
 - panic_on_oom
 - percpu_pagelist_fraction
 - stat_interval
+- stat_refresh
 - swappiness
 - user_reserve_kbytes
 - vfs_cache_pressure
@@ -755,6 +756,19 @@ is 1 second.
 
 ==============================================================
 
+stat_refresh
+
+Any read or write (by root only) flushes all the per-cpu vm statistics
+into their global totals, for more accurate reports when testing
+e.g. cat /proc/sys/vm/stat_refresh /proc/meminfo
+
+As a side-effect, it also checks for negative totals (elsewhere reported
+as 0) and "fails" with EINVAL if any are found, with a warning in dmesg.
+(At time of writing, a few stats are known sometimes to be found negative,
+with no ill effects: errors and warnings on these stats are suppressed.)
+
+==============================================================
+
 swappiness
 
 This control is used to define how aggressive the kernel will swap
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/sysrq.txt linux-libre-4.7-gnu/Documentation/sysrq.txt
--- linux-libre-4.6-gnu/Documentation/sysrq.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/sysrq.txt	2016-07-24 15:23:50.000000000 -0400
@@ -212,7 +212,7 @@ it is currently registered in that slot.
 overwritten since you registered it.
 
 The Magic SysRQ system works by registering key operations against a key op
-lookup table, which is defined in 'drivers/char/sysrq.c'. This key table has
+lookup table, which is defined in 'drivers/tty/sysrq.c'. This key table has
 a number of operations registered into it at compile time, but is mutable,
 and 2 functions are exported for interface to it:
 	register_sysrq_key and unregister_sysrq_key.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/target/tcm_mod_builder.py linux-libre-4.7-gnu/Documentation/target/tcm_mod_builder.py
--- linux-libre-4.6-gnu/Documentation/target/tcm_mod_builder.py	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/target/tcm_mod_builder.py	2016-07-24 15:23:50.000000000 -0400
@@ -294,8 +294,6 @@ def tcm_mod_build_configfs(proto_ident,
 	buf += "	.tpg_check_prod_mode_write_protect = " + fabric_mod_name + "_check_false,\n"
 	buf += "	.tpg_get_inst_index		= " + fabric_mod_name + "_tpg_get_inst_index,\n"
 	buf += "	.release_cmd			= " + fabric_mod_name + "_release_cmd,\n"
-	buf += "	.shutdown_session		= " + fabric_mod_name + "_shutdown_session,\n"
-	buf += "	.close_session			= " + fabric_mod_name + "_close_session,\n"
 	buf += "	.sess_get_index			= " + fabric_mod_name + "_sess_get_index,\n"
 	buf += "	.sess_get_initiator_sid		= NULL,\n"
 	buf += "	.write_pending			= " + fabric_mod_name + "_write_pending,\n"
@@ -467,20 +465,6 @@ def tcm_mod_dump_fabric_ops(proto_ident,
 			buf += "}\n\n"
 			bufi += "void " + fabric_mod_name + "_release_cmd(struct se_cmd *);\n"
 
-		if re.search('shutdown_session\)\(', fo):
-			buf += "int " + fabric_mod_name + "_shutdown_session(struct se_session *se_sess)\n"
-			buf += "{\n"
-			buf += "	return 0;\n"
-			buf += "}\n\n"
-			bufi += "int " + fabric_mod_name + "_shutdown_session(struct se_session *);\n"
-
-		if re.search('close_session\)\(', fo):
-			buf += "void " + fabric_mod_name + "_close_session(struct se_session *se_sess)\n"
-			buf += "{\n"
-			buf += "	return;\n"
-			buf += "}\n\n"
-			bufi += "void " + fabric_mod_name + "_close_session(struct se_session *);\n"
-
 		if re.search('sess_get_index\)\(', fo):
 			buf += "u32 " + fabric_mod_name + "_sess_get_index(struct se_session *se_sess)\n"
 			buf += "{\n"
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/thermal/sysfs-api.txt linux-libre-4.7-gnu/Documentation/thermal/sysfs-api.txt
--- linux-libre-4.6-gnu/Documentation/thermal/sysfs-api.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/thermal/sysfs-api.txt	2016-07-24 15:23:50.000000000 -0400
@@ -69,8 +69,8 @@ temperature) and throttle appropriate de
 1.1.2 void thermal_zone_device_unregister(struct thermal_zone_device *tz)
 
     This interface function removes the thermal zone device.
-    It deletes the corresponding entry form /sys/class/thermal folder and
-    unbind all the thermal cooling devices it uses.
+    It deletes the corresponding entry from /sys/class/thermal folder and
+    unbinds all the thermal cooling devices it uses.
 
 1.1.3 struct thermal_zone_device *thermal_zone_of_sensor_register(
 		struct device *dev, int sensor_id, void *data,
@@ -146,32 +146,32 @@ temperature) and throttle appropriate de
 
     This interface function adds a new thermal cooling device (fan/processor/...)
     to /sys/class/thermal/ folder as cooling_device[0-*]. It tries to bind itself
-    to all the thermal zone devices register at the same time.
+    to all the thermal zone devices registered at the same time.
     name: the cooling device name.
     devdata: device private data.
     ops: thermal cooling devices call-backs.
 	.get_max_state: get the Maximum throttle state of the cooling device.
-	.get_cur_state: get the Current throttle state of the cooling device.
+	.get_cur_state: get the Currently requested throttle state of the cooling device.
 	.set_cur_state: set the Current throttle state of the cooling device.
 
 1.2.2 void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev)
 
-    This interface function remove the thermal cooling device.
-    It deletes the corresponding entry form /sys/class/thermal folder and
-    unbind itself from all the thermal zone devices using it.
+    This interface function removes the thermal cooling device.
+    It deletes the corresponding entry from /sys/class/thermal folder and
+    unbinds itself from all the thermal zone devices using it.
 
 1.3 interface for binding a thermal zone device with a thermal cooling device
 1.3.1 int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
 	int trip, struct thermal_cooling_device *cdev,
 	unsigned long upper, unsigned long lower, unsigned int weight);
 
-    This interface function bind a thermal cooling device to the certain trip
+    This interface function binds a thermal cooling device to a particular trip
     point of a thermal zone device.
     This function is usually called in the thermal zone device .bind callback.
     tz: the thermal zone device
     cdev: thermal cooling device
-    trip: indicates which trip point the cooling devices is associated with
-	  in this thermal zone.
+    trip: indicates which trip point in this thermal zone the cooling device
+          is associated with.
     upper:the Maximum cooling state for this trip point.
           THERMAL_NO_LIMIT means no upper limit,
 	  and the cooling device can be in max_state.
@@ -184,13 +184,13 @@ temperature) and throttle appropriate de
 1.3.2 int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz,
 		int trip, struct thermal_cooling_device *cdev);
 
-    This interface function unbind a thermal cooling device from the certain
+    This interface function unbinds a thermal cooling device from a particular
     trip point of a thermal zone device. This function is usually called in
     the thermal zone device .unbind callback.
     tz: the thermal zone device
     cdev: thermal cooling device
-    trip: indicates which trip point the cooling devices is associated with
-	  in this thermal zone.
+    trip: indicates which trip point in this thermal zone the cooling device
+          is associated with.
 
 1.4 Thermal Zone Parameters
 1.4.1 struct thermal_bind_params
@@ -210,13 +210,13 @@ temperature) and throttle appropriate de
                this thermal zone and cdev, for a particular trip point.
                If nth bit is set, then the cdev and thermal zone are bound
                for trip point n.
-    .limits: This is an array of cooling state limits. Must have exactly
-         2 * thermal_zone.number_of_trip_points. It is an array consisting
-         of tuples <lower-state upper-state> of state limits. Each trip
-         will be associated with one state limit tuple when binding.
-         A NULL pointer means <THERMAL_NO_LIMITS THERMAL_NO_LIMITS>
-         on all trips. These limits are used when binding a cdev to a
-         trip point.
+    .binding_limits: This is an array of cooling state limits. Must have
+                     exactly 2 * thermal_zone.number_of_trip_points. It is an
+                     array consisting of tuples <lower-state upper-state> of
+                     state limits. Each trip will be associated with one state
+                     limit tuple when binding. A NULL pointer means
+                     <THERMAL_NO_LIMITS THERMAL_NO_LIMITS> on all trips.
+                     These limits are used when binding a cdev to a trip point.
     .match: This call back returns success(0) if the 'tz and cdev' need to
 	    be bound, as per platform data.
 1.4.2 struct thermal_zone_params
@@ -351,8 +351,8 @@ cdev[0-*]
 	RO, Optional
 
 cdev[0-*]_trip_point
-	The trip point with which cdev[0-*] is associated in this thermal
-	zone; -1 means the cooling device is not associated with any trip
+	The trip point in this thermal zone which cdev[0-*] is associated
+	with; -1 means the cooling device is not associated with any trip
 	point.
 	RO, Optional
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/timers/hrtimers.txt linux-libre-4.7-gnu/Documentation/timers/hrtimers.txt
--- linux-libre-4.6-gnu/Documentation/timers/hrtimers.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/timers/hrtimers.txt	2016-07-24 15:23:50.000000000 -0400
@@ -28,9 +28,9 @@ several reasons why such integration is
 
 - the unpredictable [O(N)] overhead of cascading leads to delays which
   necessitate a more complex handling of high resolution timers, which
-  in turn decreases robustness. Such a design still led to rather large
+  in turn decreases robustness. Such a design still leads to rather large
   timing inaccuracies. Cascading is a fundamental property of the timer
-  wheel concept, it cannot be 'designed out' without unevitably
+  wheel concept, it cannot be 'designed out' without inevitably
   degrading other portions of the timers.c code in an unacceptable way.
 
 - the implementation of the current posix-timer subsystem on top of
@@ -119,7 +119,7 @@ was not really a win, due to the differe
 hrtimer functions now have clearer behavior and clearer names - such as
 hrtimer_try_to_cancel() and hrtimer_cancel() [which are roughly
 equivalent to del_timer() and del_timer_sync()] - so there's no direct
-1:1 mapping between them on the algorithmical level, and thus no real
+1:1 mapping between them on the algorithmic level, and thus no real
 potential for code sharing either.
 
 Basic data types: every time value, absolute or relative, is in a
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/trace/coresight.txt linux-libre-4.7-gnu/Documentation/trace/coresight.txt
--- linux-libre-4.6-gnu/Documentation/trace/coresight.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/trace/coresight.txt	2016-07-24 15:23:50.000000000 -0400
@@ -190,8 +190,8 @@ expected to be accessed and controlled u
 Last but not least, "struct module *owner" is expected to be set to reflect
 the information carried in "THIS_MODULE".
 
-How to use
-----------
+How to use the tracer modules
+-----------------------------
 
 Before trace collection can start, a coresight sink needs to be identify.
 There is no limit on the amount of sinks (nor sources) that can be enabled at
@@ -297,3 +297,36 @@ Info
 Instruction     13570831        0x8026B584      E28DD00C        false   ADD      sp,sp,#0xc
 Instruction     0       0x8026B588      E8BD8000        true    LDM      sp!,{pc}
 Timestamp                                       Timestamp: 17107041535
+
+How to use the STM module
+-------------------------
+
+Using the System Trace Macrocell module is the same as the tracers - the only
+difference is that clients are driving the trace capture rather
+than the program flow through the code.
+
+As with any other CoreSight component, specifics about the STM tracer can be
+found in sysfs with more information on each entry being found in [1]:
+
+root@genericarmv8:~# ls /sys/bus/coresight/devices/20100000.stm
+enable_source   hwevent_select  port_enable     subsystem       uevent
+hwevent_enable  mgmt            port_select     traceid
+root@genericarmv8:~#
+
+Like any other source a sink needs to be identified and the STM enabled before
+being used:
+
+root@genericarmv8:~# echo 1 > /sys/bus/coresight/devices/20010000.etf/enable_sink
+root@genericarmv8:~# echo 1 > /sys/bus/coresight/devices/20100000.stm/enable_source
+
+From there user space applications can request and use channels using the devfs
+interface provided for that purpose by the generic STM API:
+
+root@genericarmv8:~# ls -l /dev/20100000.stm
+crw-------    1 root     root       10,  61 Jan  3 18:11 /dev/20100000.stm
+root@genericarmv8:~#
+
+Details on how to use the generic STM API can be found here [2].
+
+[1]. Documentation/ABI/testing/sysfs-bus-coresight-devices-stm
+[2]. Documentation/trace/stm.txt
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/trace/events.txt linux-libre-4.7-gnu/Documentation/trace/events.txt
--- linux-libre-4.6-gnu/Documentation/trace/events.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/trace/events.txt	2016-07-24 15:23:50.000000000 -0400
@@ -512,3 +512,1558 @@ The following commands are supported:
 
   Note that there can be only one traceon or traceoff trigger per
   triggering event.
+
+- hist
+
+  This command aggregates event hits into a hash table keyed on one or
+  more trace event format fields (or stacktrace) and a set of running
+  totals derived from one or more trace event format fields and/or
+  event counts (hitcount).
+
+  The format of a hist trigger is as follows:
+
+        hist:keys=<field1[,field2,...]>[:values=<field1[,field2,...]>]
+          [:sort=<field1[,field2,...]>][:size=#entries][:pause][:continue]
+          [:clear][:name=histname1] [if <filter>]
+
+  When a matching event is hit, an entry is added to a hash table
+  using the key(s) and value(s) named.  Keys and values correspond to
+  fields in the event's format description.  Values must correspond to
+  numeric fields - on an event hit, the value(s) will be added to a
+  sum kept for that field.  The special string 'hitcount' can be used
+  in place of an explicit value field - this is simply a count of
+  event hits.  If 'values' isn't specified, an implicit 'hitcount'
+  value will be automatically created and used as the only value.
+  Keys can be any field, or the special string 'stacktrace', which
+  will use the event's kernel stacktrace as the key.  The keywords
+  'keys' or 'key' can be used to specify keys, and the keywords
+  'values', 'vals', or 'val' can be used to specify values.  Compound
+  keys consisting of up to two fields can be specified by the 'keys'
+  keyword.  Hashing a compound key produces a unique entry in the
+  table for each unique combination of component keys, and can be
+  useful for providing more fine-grained summaries of event data.
+  Additionally, sort keys consisting of up to two fields can be
+  specified by the 'sort' keyword.  If more than one field is
+  specified, the result will be a 'sort within a sort': the first key
+  is taken to be the primary sort key and the second the secondary
+  key.  If a hist trigger is given a name using the 'name' parameter,
+  its histogram data will be shared with other triggers of the same
+  name, and trigger hits will update this common data.  Only triggers
+  with 'compatible' fields can be combined in this way; triggers are
+  'compatible' if the fields named in the trigger share the same
+  number and type of fields and those fields also have the same names.
+  Note that any two events always share the compatible 'hitcount' and
+  'stacktrace' fields and can therefore be combined using those
+  fields, however pointless that may be.
+
+  'hist' triggers add a 'hist' file to each event's subdirectory.
+  Reading the 'hist' file for the event will dump the hash table in
+  its entirety to stdout.  If there are multiple hist triggers
+  attached to an event, there will be a table for each trigger in the
+  output.  The table displayed for a named trigger will be the same as
+  any other instance having the same name. Each printed hash table
+  entry is a simple list of the keys and values comprising the entry;
+  keys are printed first and are delineated by curly braces, and are
+  followed by the set of value fields for the entry.  By default,
+  numeric fields are displayed as base-10 integers.  This can be
+  modified by appending any of the following modifiers to the field
+  name:
+
+        .hex        display a number as a hex value
+	.sym        display an address as a symbol
+	.sym-offset display an address as a symbol and offset
+	.syscall    display a syscall id as a system call name
+	.execname   display a common_pid as a program name
+
+  Note that in general the semantics of a given field aren't
+  interpreted when applying a modifier to it, but there are some
+  restrictions to be aware of in this regard:
+
+    - only the 'hex' modifier can be used for values (because values
+      are essentially sums, and the other modifiers don't make sense
+      in that context).
+    - the 'execname' modifier can only be used on a 'common_pid'.  The
+      reason for this is that the execname is simply the 'comm' value
+      saved for the 'current' process when an event was triggered,
+      which is the same as the common_pid value saved by the event
+      tracing code.  Trying to apply that comm value to other pid
+      values wouldn't be correct, and typically events that care save
+      pid-specific comm fields in the event itself.
+
+  A typical usage scenario would be the following to enable a hist
+  trigger, read its current contents, and then turn it off:
+
+  # echo 'hist:keys=skbaddr.hex:vals=len' > \
+    /sys/kernel/debug/tracing/events/net/netif_rx/trigger
+
+  # cat /sys/kernel/debug/tracing/events/net/netif_rx/hist
+
+  # echo '!hist:keys=skbaddr.hex:vals=len' > \
+    /sys/kernel/debug/tracing/events/net/netif_rx/trigger
+
+  The trigger file itself can be read to show the details of the
+  currently attached hist trigger.  This information is also displayed
+  at the top of the 'hist' file when read.
+
+  By default, the size of the hash table is 2048 entries.  The 'size'
+  parameter can be used to specify more or fewer than that.  The units
+  are in terms of hashtable entries - if a run uses more entries than
+  specified, the results will show the number of 'drops', the number
+  of hits that were ignored.  The size should be a power of 2 between
+  128 and 131072 (any non- power-of-2 number specified will be rounded
+  up).
+
+  The 'sort' parameter can be used to specify a value field to sort
+  on.  The default if unspecified is 'hitcount' and the default sort
+  order is 'ascending'.  To sort in the opposite direction, append
+  .descending' to the sort key.
+
+  The 'pause' parameter can be used to pause an existing hist trigger
+  or to start a hist trigger but not log any events until told to do
+  so.  'continue' or 'cont' can be used to start or restart a paused
+  hist trigger.
+
+  The 'clear' parameter will clear the contents of a running hist
+  trigger and leave its current paused/active state.
+
+  Note that the 'pause', 'cont', and 'clear' parameters should be
+  applied using 'append' shell operator ('>>') if applied to an
+  existing trigger, rather than via the '>' operator, which will cause
+  the trigger to be removed through truncation.
+
+- enable_hist/disable_hist
+
+  The enable_hist and disable_hist triggers can be used to have one
+  event conditionally start and stop another event's already-attached
+  hist trigger.  Any number of enable_hist and disable_hist triggers
+  can be attached to a given event, allowing that event to kick off
+  and stop aggregations on a host of other events.
+
+  The format is very similar to the enable/disable_event triggers:
+
+      enable_hist:<system>:<event>[:count]
+      disable_hist:<system>:<event>[:count]
+
+  Instead of enabling or disabling the tracing of the target event
+  into the trace buffer as the enable/disable_event triggers do, the
+  enable/disable_hist triggers enable or disable the aggregation of
+  the target event into a hash table.
+
+  A typical usage scenario for the enable_hist/disable_hist triggers
+  would be to first set up a paused hist trigger on some event,
+  followed by an enable_hist/disable_hist pair that turns the hist
+  aggregation on and off when conditions of interest are hit:
+
+  # echo 'hist:keys=skbaddr.hex:vals=len:pause' > \
+    /sys/kernel/debug/tracing/events/net/netif_receive_skb/trigger
+
+  # echo 'enable_hist:net:netif_receive_skb if filename==/usr/bin/wget' > \
+    /sys/kernel/debug/tracing/events/sched/sched_process_exec/trigger
+
+  # echo 'disable_hist:net:netif_receive_skb if comm==wget' > \
+    /sys/kernel/debug/tracing/events/sched/sched_process_exit/trigger
+
+  The above sets up an initially paused hist trigger which is unpaused
+  and starts aggregating events when a given program is executed, and
+  which stops aggregating when the process exits and the hist trigger
+  is paused again.
+
+  The examples below provide a more concrete illustration of the
+  concepts and typical usage patterns discussed above.
+
+
+6.2 'hist' trigger examples
+---------------------------
+
+  The first set of examples creates aggregations using the kmalloc
+  event.  The fields that can be used for the hist trigger are listed
+  in the kmalloc event's format file:
+
+    # cat /sys/kernel/debug/tracing/events/kmem/kmalloc/format
+    name: kmalloc
+    ID: 374
+    format:
+	field:unsigned short common_type;	offset:0;	size:2;	signed:0;
+	field:unsigned char common_flags;	offset:2;	size:1;	signed:0;
+	field:unsigned char common_preempt_count;		offset:3;	size:1;	signed:0;
+	field:int common_pid;					offset:4;	size:4;	signed:1;
+
+	field:unsigned long call_site;				offset:8;	size:8;	signed:0;
+	field:const void * ptr;					offset:16;	size:8;	signed:0;
+	field:size_t bytes_req;					offset:24;	size:8;	signed:0;
+	field:size_t bytes_alloc;				offset:32;	size:8;	signed:0;
+	field:gfp_t gfp_flags;					offset:40;	size:4;	signed:0;
+
+  We'll start by creating a hist trigger that generates a simple table
+  that lists the total number of bytes requested for each function in
+  the kernel that made one or more calls to kmalloc:
+
+    # echo 'hist:key=call_site:val=bytes_req' > \
+            /sys/kernel/debug/tracing/events/kmem/kmalloc/trigger
+
+  This tells the tracing system to create a 'hist' trigger using the
+  call_site field of the kmalloc event as the key for the table, which
+  just means that each unique call_site address will have an entry
+  created for it in the table.  The 'val=bytes_req' parameter tells
+  the hist trigger that for each unique entry (call_site) in the
+  table, it should keep a running total of the number of bytes
+  requested by that call_site.
+
+  We'll let it run for awhile and then dump the contents of the 'hist'
+  file in the kmalloc event's subdirectory (for readability, a number
+  of entries have been omitted):
+
+    # cat /sys/kernel/debug/tracing/events/kmem/kmalloc/hist
+    # trigger info: hist:keys=call_site:vals=bytes_req:sort=hitcount:size=2048 [active]
+
+    { call_site: 18446744072106379007 } hitcount:          1  bytes_req:        176
+    { call_site: 18446744071579557049 } hitcount:          1  bytes_req:       1024
+    { call_site: 18446744071580608289 } hitcount:          1  bytes_req:      16384
+    { call_site: 18446744071581827654 } hitcount:          1  bytes_req:         24
+    { call_site: 18446744071580700980 } hitcount:          1  bytes_req:          8
+    { call_site: 18446744071579359876 } hitcount:          1  bytes_req:        152
+    { call_site: 18446744071580795365 } hitcount:          3  bytes_req:        144
+    { call_site: 18446744071581303129 } hitcount:          3  bytes_req:        144
+    { call_site: 18446744071580713234 } hitcount:          4  bytes_req:       2560
+    { call_site: 18446744071580933750 } hitcount:          4  bytes_req:        736
+    .
+    .
+    .
+    { call_site: 18446744072106047046 } hitcount:         69  bytes_req:       5576
+    { call_site: 18446744071582116407 } hitcount:         73  bytes_req:       2336
+    { call_site: 18446744072106054684 } hitcount:        136  bytes_req:     140504
+    { call_site: 18446744072106224230 } hitcount:        136  bytes_req:      19584
+    { call_site: 18446744072106078074 } hitcount:        153  bytes_req:       2448
+    { call_site: 18446744072106062406 } hitcount:        153  bytes_req:      36720
+    { call_site: 18446744071582507929 } hitcount:        153  bytes_req:      37088
+    { call_site: 18446744072102520590 } hitcount:        273  bytes_req:      10920
+    { call_site: 18446744071582143559 } hitcount:        358  bytes_req:        716
+    { call_site: 18446744072106465852 } hitcount:        417  bytes_req:      56712
+    { call_site: 18446744072102523378 } hitcount:        485  bytes_req:      27160
+    { call_site: 18446744072099568646 } hitcount:       1676  bytes_req:      33520
+
+    Totals:
+        Hits: 4610
+        Entries: 45
+        Dropped: 0
+
+  The output displays a line for each entry, beginning with the key
+  specified in the trigger, followed by the value(s) also specified in
+  the trigger.  At the beginning of the output is a line that displays
+  the trigger info, which can also be displayed by reading the
+  'trigger' file:
+
+    # cat /sys/kernel/debug/tracing/events/kmem/kmalloc/trigger
+    hist:keys=call_site:vals=bytes_req:sort=hitcount:size=2048 [active]
+
+  At the end of the output are a few lines that display the overall
+  totals for the run.  The 'Hits' field shows the total number of
+  times the event trigger was hit, the 'Entries' field shows the total
+  number of used entries in the hash table, and the 'Dropped' field
+  shows the number of hits that were dropped because the number of
+  used entries for the run exceeded the maximum number of entries
+  allowed for the table (normally 0, but if not a hint that you may
+  want to increase the size of the table using the 'size' parameter).
+
+  Notice in the above output that there's an extra field, 'hitcount',
+  which wasn't specified in the trigger.  Also notice that in the
+  trigger info output, there's a parameter, 'sort=hitcount', which
+  wasn't specified in the trigger either.  The reason for that is that
+  every trigger implicitly keeps a count of the total number of hits
+  attributed to a given entry, called the 'hitcount'.  That hitcount
+  information is explicitly displayed in the output, and in the
+  absence of a user-specified sort parameter, is used as the default
+  sort field.
+
+  The value 'hitcount' can be used in place of an explicit value in
+  the 'values' parameter if you don't really need to have any
+  particular field summed and are mainly interested in hit
+  frequencies.
+
+  To turn the hist trigger off, simply call up the trigger in the
+  command history and re-execute it with a '!' prepended:
+
+    # echo '!hist:key=call_site:val=bytes_req' > \
+           /sys/kernel/debug/tracing/events/kmem/kmalloc/trigger
+
+  Finally, notice that the call_site as displayed in the output above
+  isn't really very useful.  It's an address, but normally addresses
+  are displayed in hex.  To have a numeric field displayed as a hex
+  value, simply append '.hex' to the field name in the trigger:
+
+    # echo 'hist:key=call_site.hex:val=bytes_req' > \
+           /sys/kernel/debug/tracing/events/kmem/kmalloc/trigger
+
+    # cat /sys/kernel/debug/tracing/events/kmem/kmalloc/hist
+    # trigger info: hist:keys=call_site.hex:vals=bytes_req:sort=hitcount:size=2048 [active]
+
+    { call_site: ffffffffa026b291 } hitcount:          1  bytes_req:        433
+    { call_site: ffffffffa07186ff } hitcount:          1  bytes_req:        176
+    { call_site: ffffffff811ae721 } hitcount:          1  bytes_req:      16384
+    { call_site: ffffffff811c5134 } hitcount:          1  bytes_req:          8
+    { call_site: ffffffffa04a9ebb } hitcount:          1  bytes_req:        511
+    { call_site: ffffffff8122e0a6 } hitcount:          1  bytes_req:         12
+    { call_site: ffffffff8107da84 } hitcount:          1  bytes_req:        152
+    { call_site: ffffffff812d8246 } hitcount:          1  bytes_req:         24
+    { call_site: ffffffff811dc1e5 } hitcount:          3  bytes_req:        144
+    { call_site: ffffffffa02515e8 } hitcount:          3  bytes_req:        648
+    { call_site: ffffffff81258159 } hitcount:          3  bytes_req:        144
+    { call_site: ffffffff811c80f4 } hitcount:          4  bytes_req:        544
+    .
+    .
+    .
+    { call_site: ffffffffa06c7646 } hitcount:        106  bytes_req:       8024
+    { call_site: ffffffffa06cb246 } hitcount:        132  bytes_req:      31680
+    { call_site: ffffffffa06cef7a } hitcount:        132  bytes_req:       2112
+    { call_site: ffffffff8137e399 } hitcount:        132  bytes_req:      23232
+    { call_site: ffffffffa06c941c } hitcount:        185  bytes_req:     171360
+    { call_site: ffffffffa06f2a66 } hitcount:        185  bytes_req:      26640
+    { call_site: ffffffffa036a70e } hitcount:        265  bytes_req:      10600
+    { call_site: ffffffff81325447 } hitcount:        292  bytes_req:        584
+    { call_site: ffffffffa072da3c } hitcount:        446  bytes_req:      60656
+    { call_site: ffffffffa036b1f2 } hitcount:        526  bytes_req:      29456
+    { call_site: ffffffffa0099c06 } hitcount:       1780  bytes_req:      35600
+
+    Totals:
+        Hits: 4775
+        Entries: 46
+        Dropped: 0
+
+  Even that's only marginally more useful - while hex values do look
+  more like addresses, what users are typically more interested in
+  when looking at text addresses are the corresponding symbols
+  instead.  To have an address displayed as symbolic value instead,
+  simply append '.sym' or '.sym-offset' to the field name in the
+  trigger:
+
+    # echo 'hist:key=call_site.sym:val=bytes_req' > \
+           /sys/kernel/debug/tracing/events/kmem/kmalloc/trigger
+
+    # cat /sys/kernel/debug/tracing/events/kmem/kmalloc/hist
+    # trigger info: hist:keys=call_site.sym:vals=bytes_req:sort=hitcount:size=2048 [active]
+
+    { call_site: [ffffffff810adcb9] syslog_print_all                              } hitcount:          1  bytes_req:       1024
+    { call_site: [ffffffff8154bc62] usb_control_msg                               } hitcount:          1  bytes_req:          8
+    { call_site: [ffffffffa00bf6fe] hidraw_send_report [hid]                      } hitcount:          1  bytes_req:          7
+    { call_site: [ffffffff8154acbe] usb_alloc_urb                                 } hitcount:          1  bytes_req:        192
+    { call_site: [ffffffffa00bf1ca] hidraw_report_event [hid]                     } hitcount:          1  bytes_req:          7
+    { call_site: [ffffffff811e3a25] __seq_open_private                            } hitcount:          1  bytes_req:         40
+    { call_site: [ffffffff8109524a] alloc_fair_sched_group                        } hitcount:          2  bytes_req:        128
+    { call_site: [ffffffff811febd5] fsnotify_alloc_group                          } hitcount:          2  bytes_req:        528
+    { call_site: [ffffffff81440f58] __tty_buffer_request_room                     } hitcount:          2  bytes_req:       2624
+    { call_site: [ffffffff81200ba6] inotify_new_group                             } hitcount:          2  bytes_req:         96
+    { call_site: [ffffffffa05e19af] ieee80211_start_tx_ba_session [mac80211]      } hitcount:          2  bytes_req:        464
+    { call_site: [ffffffff81672406] tcp_get_metrics                               } hitcount:          2  bytes_req:        304
+    { call_site: [ffffffff81097ec2] alloc_rt_sched_group                          } hitcount:          2  bytes_req:        128
+    { call_site: [ffffffff81089b05] sched_create_group                            } hitcount:          2  bytes_req:       1424
+    .
+    .
+    .
+    { call_site: [ffffffffa04a580c] intel_crtc_page_flip [i915]                   } hitcount:       1185  bytes_req:     123240
+    { call_site: [ffffffffa0287592] drm_mode_page_flip_ioctl [drm]                } hitcount:       1185  bytes_req:     104280
+    { call_site: [ffffffffa04c4a3c] intel_plane_duplicate_state [i915]            } hitcount:       1402  bytes_req:     190672
+    { call_site: [ffffffff812891ca] ext4_find_extent                              } hitcount:       1518  bytes_req:     146208
+    { call_site: [ffffffffa029070e] drm_vma_node_allow [drm]                      } hitcount:       1746  bytes_req:      69840
+    { call_site: [ffffffffa045e7c4] i915_gem_do_execbuffer.isra.23 [i915]         } hitcount:       2021  bytes_req:     792312
+    { call_site: [ffffffffa02911f2] drm_modeset_lock_crtc [drm]                   } hitcount:       2592  bytes_req:     145152
+    { call_site: [ffffffffa0489a66] intel_ring_begin [i915]                       } hitcount:       2629  bytes_req:     378576
+    { call_site: [ffffffffa046041c] i915_gem_execbuffer2 [i915]                   } hitcount:       2629  bytes_req:    3783248
+    { call_site: [ffffffff81325607] apparmor_file_alloc_security                  } hitcount:       5192  bytes_req:      10384
+    { call_site: [ffffffffa00b7c06] hid_report_raw_event [hid]                    } hitcount:       5529  bytes_req:     110584
+    { call_site: [ffffffff8131ebf7] aa_alloc_task_context                         } hitcount:      21943  bytes_req:     702176
+    { call_site: [ffffffff8125847d] ext4_htree_store_dirent                       } hitcount:      55759  bytes_req:    5074265
+
+    Totals:
+        Hits: 109928
+        Entries: 71
+        Dropped: 0
+
+  Because the default sort key above is 'hitcount', the above shows a
+  the list of call_sites by increasing hitcount, so that at the bottom
+  we see the functions that made the most kmalloc calls during the
+  run.  If instead we we wanted to see the top kmalloc callers in
+  terms of the number of bytes requested rather than the number of
+  calls, and we wanted the top caller to appear at the top, we can use
+  the 'sort' parameter, along with the 'descending' modifier:
+
+    # echo 'hist:key=call_site.sym:val=bytes_req:sort=bytes_req.descending' > \
+           /sys/kernel/debug/tracing/events/kmem/kmalloc/trigger
+
+    # cat /sys/kernel/debug/tracing/events/kmem/kmalloc/hist
+    # trigger info: hist:keys=call_site.sym:vals=bytes_req:sort=bytes_req.descending:size=2048 [active]
+
+    { call_site: [ffffffffa046041c] i915_gem_execbuffer2 [i915]                   } hitcount:       2186  bytes_req:    3397464
+    { call_site: [ffffffffa045e7c4] i915_gem_do_execbuffer.isra.23 [i915]         } hitcount:       1790  bytes_req:     712176
+    { call_site: [ffffffff8125847d] ext4_htree_store_dirent                       } hitcount:       8132  bytes_req:     513135
+    { call_site: [ffffffff811e2a1b] seq_buf_alloc                                 } hitcount:        106  bytes_req:     440128
+    { call_site: [ffffffffa0489a66] intel_ring_begin [i915]                       } hitcount:       2186  bytes_req:     314784
+    { call_site: [ffffffff812891ca] ext4_find_extent                              } hitcount:       2174  bytes_req:     208992
+    { call_site: [ffffffff811ae8e1] __kmalloc                                     } hitcount:          8  bytes_req:     131072
+    { call_site: [ffffffffa04c4a3c] intel_plane_duplicate_state [i915]            } hitcount:        859  bytes_req:     116824
+    { call_site: [ffffffffa02911f2] drm_modeset_lock_crtc [drm]                   } hitcount:       1834  bytes_req:     102704
+    { call_site: [ffffffffa04a580c] intel_crtc_page_flip [i915]                   } hitcount:        972  bytes_req:     101088
+    { call_site: [ffffffffa0287592] drm_mode_page_flip_ioctl [drm]                } hitcount:        972  bytes_req:      85536
+    { call_site: [ffffffffa00b7c06] hid_report_raw_event [hid]                    } hitcount:       3333  bytes_req:      66664
+    { call_site: [ffffffff8137e559] sg_kmalloc                                    } hitcount:        209  bytes_req:      61632
+    .
+    .
+    .
+    { call_site: [ffffffff81095225] alloc_fair_sched_group                        } hitcount:          2  bytes_req:        128
+    { call_site: [ffffffff81097ec2] alloc_rt_sched_group                          } hitcount:          2  bytes_req:        128
+    { call_site: [ffffffff812d8406] copy_semundo                                  } hitcount:          2  bytes_req:         48
+    { call_site: [ffffffff81200ba6] inotify_new_group                             } hitcount:          1  bytes_req:         48
+    { call_site: [ffffffffa027121a] drm_getmagic [drm]                            } hitcount:          1  bytes_req:         48
+    { call_site: [ffffffff811e3a25] __seq_open_private                            } hitcount:          1  bytes_req:         40
+    { call_site: [ffffffff811c52f4] bprm_change_interp                            } hitcount:          2  bytes_req:         16
+    { call_site: [ffffffff8154bc62] usb_control_msg                               } hitcount:          1  bytes_req:          8
+    { call_site: [ffffffffa00bf1ca] hidraw_report_event [hid]                     } hitcount:          1  bytes_req:          7
+    { call_site: [ffffffffa00bf6fe] hidraw_send_report [hid]                      } hitcount:          1  bytes_req:          7
+
+    Totals:
+        Hits: 32133
+        Entries: 81
+        Dropped: 0
+
+  To display the offset and size information in addition to the symbol
+  name, just use 'sym-offset' instead:
+
+    # echo 'hist:key=call_site.sym-offset:val=bytes_req:sort=bytes_req.descending' > \
+           /sys/kernel/debug/tracing/events/kmem/kmalloc/trigger
+
+    # cat /sys/kernel/debug/tracing/events/kmem/kmalloc/hist
+    # trigger info: hist:keys=call_site.sym-offset:vals=bytes_req:sort=bytes_req.descending:size=2048 [active]
+
+    { call_site: [ffffffffa046041c] i915_gem_execbuffer2+0x6c/0x2c0 [i915]                  } hitcount:       4569  bytes_req:    3163720
+    { call_site: [ffffffffa0489a66] intel_ring_begin+0xc6/0x1f0 [i915]                      } hitcount:       4569  bytes_req:     657936
+    { call_site: [ffffffffa045e7c4] i915_gem_do_execbuffer.isra.23+0x694/0x1020 [i915]      } hitcount:       1519  bytes_req:     472936
+    { call_site: [ffffffffa045e646] i915_gem_do_execbuffer.isra.23+0x516/0x1020 [i915]      } hitcount:       3050  bytes_req:     211832
+    { call_site: [ffffffff811e2a1b] seq_buf_alloc+0x1b/0x50                                 } hitcount:         34  bytes_req:     148384
+    { call_site: [ffffffffa04a580c] intel_crtc_page_flip+0xbc/0x870 [i915]                  } hitcount:       1385  bytes_req:     144040
+    { call_site: [ffffffff811ae8e1] __kmalloc+0x191/0x1b0                                   } hitcount:          8  bytes_req:     131072
+    { call_site: [ffffffffa0287592] drm_mode_page_flip_ioctl+0x282/0x360 [drm]              } hitcount:       1385  bytes_req:     121880
+    { call_site: [ffffffffa02911f2] drm_modeset_lock_crtc+0x32/0x100 [drm]                  } hitcount:       1848  bytes_req:     103488
+    { call_site: [ffffffffa04c4a3c] intel_plane_duplicate_state+0x2c/0xa0 [i915]            } hitcount:        461  bytes_req:      62696
+    { call_site: [ffffffffa029070e] drm_vma_node_allow+0x2e/0xd0 [drm]                      } hitcount:       1541  bytes_req:      61640
+    { call_site: [ffffffff815f8d7b] sk_prot_alloc+0xcb/0x1b0                                } hitcount:         57  bytes_req:      57456
+    .
+    .
+    .
+    { call_site: [ffffffff8109524a] alloc_fair_sched_group+0x5a/0x1a0                       } hitcount:          2  bytes_req:        128
+    { call_site: [ffffffffa027b921] drm_vm_open_locked+0x31/0xa0 [drm]                      } hitcount:          3  bytes_req:         96
+    { call_site: [ffffffff8122e266] proc_self_follow_link+0x76/0xb0                         } hitcount:          8  bytes_req:         96
+    { call_site: [ffffffff81213e80] load_elf_binary+0x240/0x1650                            } hitcount:          3  bytes_req:         84
+    { call_site: [ffffffff8154bc62] usb_control_msg+0x42/0x110                              } hitcount:          1  bytes_req:          8
+    { call_site: [ffffffffa00bf6fe] hidraw_send_report+0x7e/0x1a0 [hid]                     } hitcount:          1  bytes_req:          7
+    { call_site: [ffffffffa00bf1ca] hidraw_report_event+0x8a/0x120 [hid]                    } hitcount:          1  bytes_req:          7
+
+    Totals:
+        Hits: 26098
+        Entries: 64
+        Dropped: 0
+
+  We can also add multiple fields to the 'values' parameter.  For
+  example, we might want to see the total number of bytes allocated
+  alongside bytes requested, and display the result sorted by bytes
+  allocated in a descending order:
+
+    # echo 'hist:keys=call_site.sym:values=bytes_req,bytes_alloc:sort=bytes_alloc.descending' > \
+           /sys/kernel/debug/tracing/events/kmem/kmalloc/trigger
+
+    # cat /sys/kernel/debug/tracing/events/kmem/kmalloc/hist
+    # trigger info: hist:keys=call_site.sym:vals=bytes_req,bytes_alloc:sort=bytes_alloc.descending:size=2048 [active]
+
+    { call_site: [ffffffffa046041c] i915_gem_execbuffer2 [i915]                   } hitcount:       7403  bytes_req:    4084360  bytes_alloc:    5958016
+    { call_site: [ffffffff811e2a1b] seq_buf_alloc                                 } hitcount:        541  bytes_req:    2213968  bytes_alloc:    2228224
+    { call_site: [ffffffffa0489a66] intel_ring_begin [i915]                       } hitcount:       7404  bytes_req:    1066176  bytes_alloc:    1421568
+    { call_site: [ffffffffa045e7c4] i915_gem_do_execbuffer.isra.23 [i915]         } hitcount:       1565  bytes_req:     557368  bytes_alloc:    1037760
+    { call_site: [ffffffff8125847d] ext4_htree_store_dirent                       } hitcount:       9557  bytes_req:     595778  bytes_alloc:     695744
+    { call_site: [ffffffffa045e646] i915_gem_do_execbuffer.isra.23 [i915]         } hitcount:       5839  bytes_req:     430680  bytes_alloc:     470400
+    { call_site: [ffffffffa04c4a3c] intel_plane_duplicate_state [i915]            } hitcount:       2388  bytes_req:     324768  bytes_alloc:     458496
+    { call_site: [ffffffffa02911f2] drm_modeset_lock_crtc [drm]                   } hitcount:       3911  bytes_req:     219016  bytes_alloc:     250304
+    { call_site: [ffffffff815f8d7b] sk_prot_alloc                                 } hitcount:        235  bytes_req:     236880  bytes_alloc:     240640
+    { call_site: [ffffffff8137e559] sg_kmalloc                                    } hitcount:        557  bytes_req:     169024  bytes_alloc:     221760
+    { call_site: [ffffffffa00b7c06] hid_report_raw_event [hid]                    } hitcount:       9378  bytes_req:     187548  bytes_alloc:     206312
+    { call_site: [ffffffffa04a580c] intel_crtc_page_flip [i915]                   } hitcount:       1519  bytes_req:     157976  bytes_alloc:     194432
+    .
+    .
+    .
+    { call_site: [ffffffff8109bd3b] sched_autogroup_create_attach                 } hitcount:          2  bytes_req:        144  bytes_alloc:        192
+    { call_site: [ffffffff81097ee8] alloc_rt_sched_group                          } hitcount:          2  bytes_req:        128  bytes_alloc:        128
+    { call_site: [ffffffff8109524a] alloc_fair_sched_group                        } hitcount:          2  bytes_req:        128  bytes_alloc:        128
+    { call_site: [ffffffff81095225] alloc_fair_sched_group                        } hitcount:          2  bytes_req:        128  bytes_alloc:        128
+    { call_site: [ffffffff81097ec2] alloc_rt_sched_group                          } hitcount:          2  bytes_req:        128  bytes_alloc:        128
+    { call_site: [ffffffff81213e80] load_elf_binary                               } hitcount:          3  bytes_req:         84  bytes_alloc:         96
+    { call_site: [ffffffff81079a2e] kthread_create_on_node                        } hitcount:          1  bytes_req:         56  bytes_alloc:         64
+    { call_site: [ffffffffa00bf6fe] hidraw_send_report [hid]                      } hitcount:          1  bytes_req:          7  bytes_alloc:          8
+    { call_site: [ffffffff8154bc62] usb_control_msg                               } hitcount:          1  bytes_req:          8  bytes_alloc:          8
+    { call_site: [ffffffffa00bf1ca] hidraw_report_event [hid]                     } hitcount:          1  bytes_req:          7  bytes_alloc:          8
+
+    Totals:
+        Hits: 66598
+        Entries: 65
+        Dropped: 0
+
+  Finally, to finish off our kmalloc example, instead of simply having
+  the hist trigger display symbolic call_sites, we can have the hist
+  trigger additionally display the complete set of kernel stack traces
+  that led to each call_site.  To do that, we simply use the special
+  value 'stacktrace' for the key parameter:
+
+    # echo 'hist:keys=stacktrace:values=bytes_req,bytes_alloc:sort=bytes_alloc' > \
+           /sys/kernel/debug/tracing/events/kmem/kmalloc/trigger
+
+  The above trigger will use the kernel stack trace in effect when an
+  event is triggered as the key for the hash table.  This allows the
+  enumeration of every kernel callpath that led up to a particular
+  event, along with a running total of any of the event fields for
+  that event.  Here we tally bytes requested and bytes allocated for
+  every callpath in the system that led up to a kmalloc (in this case
+  every callpath to a kmalloc for a kernel compile):
+
+    # cat /sys/kernel/debug/tracing/events/kmem/kmalloc/hist
+    # trigger info: hist:keys=stacktrace:vals=bytes_req,bytes_alloc:sort=bytes_alloc:size=2048 [active]
+
+    { stacktrace:
+         __kmalloc_track_caller+0x10b/0x1a0
+         kmemdup+0x20/0x50
+         hidraw_report_event+0x8a/0x120 [hid]
+         hid_report_raw_event+0x3ea/0x440 [hid]
+         hid_input_report+0x112/0x190 [hid]
+         hid_irq_in+0xc2/0x260 [usbhid]
+         __usb_hcd_giveback_urb+0x72/0x120
+         usb_giveback_urb_bh+0x9e/0xe0
+         tasklet_hi_action+0xf8/0x100
+         __do_softirq+0x114/0x2c0
+         irq_exit+0xa5/0xb0
+         do_IRQ+0x5a/0xf0
+         ret_from_intr+0x0/0x30
+         cpuidle_enter+0x17/0x20
+         cpu_startup_entry+0x315/0x3e0
+         rest_init+0x7c/0x80
+    } hitcount:          3  bytes_req:         21  bytes_alloc:         24
+    { stacktrace:
+         __kmalloc_track_caller+0x10b/0x1a0
+         kmemdup+0x20/0x50
+         hidraw_report_event+0x8a/0x120 [hid]
+         hid_report_raw_event+0x3ea/0x440 [hid]
+         hid_input_report+0x112/0x190 [hid]
+         hid_irq_in+0xc2/0x260 [usbhid]
+         __usb_hcd_giveback_urb+0x72/0x120
+         usb_giveback_urb_bh+0x9e/0xe0
+         tasklet_hi_action+0xf8/0x100
+         __do_softirq+0x114/0x2c0
+         irq_exit+0xa5/0xb0
+         do_IRQ+0x5a/0xf0
+         ret_from_intr+0x0/0x30
+    } hitcount:          3  bytes_req:         21  bytes_alloc:         24
+    { stacktrace:
+         kmem_cache_alloc_trace+0xeb/0x150
+         aa_alloc_task_context+0x27/0x40
+         apparmor_cred_prepare+0x1f/0x50
+         security_prepare_creds+0x16/0x20
+         prepare_creds+0xdf/0x1a0
+         SyS_capset+0xb5/0x200
+         system_call_fastpath+0x12/0x6a
+    } hitcount:          1  bytes_req:         32  bytes_alloc:         32
+    .
+    .
+    .
+    { stacktrace:
+         __kmalloc+0x11b/0x1b0
+         i915_gem_execbuffer2+0x6c/0x2c0 [i915]
+         drm_ioctl+0x349/0x670 [drm]
+         do_vfs_ioctl+0x2f0/0x4f0
+         SyS_ioctl+0x81/0xa0
+         system_call_fastpath+0x12/0x6a
+    } hitcount:      17726  bytes_req:   13944120  bytes_alloc:   19593808
+    { stacktrace:
+         __kmalloc+0x11b/0x1b0
+         load_elf_phdrs+0x76/0xa0
+         load_elf_binary+0x102/0x1650
+         search_binary_handler+0x97/0x1d0
+         do_execveat_common.isra.34+0x551/0x6e0
+         SyS_execve+0x3a/0x50
+         return_from_execve+0x0/0x23
+    } hitcount:      33348  bytes_req:   17152128  bytes_alloc:   20226048
+    { stacktrace:
+         kmem_cache_alloc_trace+0xeb/0x150
+         apparmor_file_alloc_security+0x27/0x40
+         security_file_alloc+0x16/0x20
+         get_empty_filp+0x93/0x1c0
+         path_openat+0x31/0x5f0
+         do_filp_open+0x3a/0x90
+         do_sys_open+0x128/0x220
+         SyS_open+0x1e/0x20
+         system_call_fastpath+0x12/0x6a
+    } hitcount:    4766422  bytes_req:    9532844  bytes_alloc:   38131376
+    { stacktrace:
+         __kmalloc+0x11b/0x1b0
+         seq_buf_alloc+0x1b/0x50
+         seq_read+0x2cc/0x370
+         proc_reg_read+0x3d/0x80
+         __vfs_read+0x28/0xe0
+         vfs_read+0x86/0x140
+         SyS_read+0x46/0xb0
+         system_call_fastpath+0x12/0x6a
+    } hitcount:      19133  bytes_req:   78368768  bytes_alloc:   78368768
+
+    Totals:
+        Hits: 6085872
+        Entries: 253
+        Dropped: 0
+
+  If you key a hist trigger on common_pid, in order for example to
+  gather and display sorted totals for each process, you can use the
+  special .execname modifier to display the executable names for the
+  processes in the table rather than raw pids.  The example below
+  keeps a per-process sum of total bytes read:
+
+    # echo 'hist:key=common_pid.execname:val=count:sort=count.descending' > \
+           /sys/kernel/debug/tracing/events/syscalls/sys_enter_read/trigger
+
+    # cat /sys/kernel/debug/tracing/events/syscalls/sys_enter_read/hist
+    # trigger info: hist:keys=common_pid.execname:vals=count:sort=count.descending:size=2048 [active]
+
+    { common_pid: gnome-terminal  [      3196] } hitcount:        280  count:    1093512
+    { common_pid: Xorg            [      1309] } hitcount:        525  count:     256640
+    { common_pid: compiz          [      2889] } hitcount:         59  count:     254400
+    { common_pid: bash            [      8710] } hitcount:          3  count:      66369
+    { common_pid: dbus-daemon-lau [      8703] } hitcount:         49  count:      47739
+    { common_pid: irqbalance      [      1252] } hitcount:         27  count:      27648
+    { common_pid: 01ifupdown      [      8705] } hitcount:          3  count:      17216
+    { common_pid: dbus-daemon     [       772] } hitcount:         10  count:      12396
+    { common_pid: Socket Thread   [      8342] } hitcount:         11  count:      11264
+    { common_pid: nm-dhcp-client. [      8701] } hitcount:          6  count:       7424
+    { common_pid: gmain           [      1315] } hitcount:         18  count:       6336
+    .
+    .
+    .
+    { common_pid: postgres        [      1892] } hitcount:          2  count:         32
+    { common_pid: postgres        [      1891] } hitcount:          2  count:         32
+    { common_pid: gmain           [      8704] } hitcount:          2  count:         32
+    { common_pid: upstart-dbus-br [      2740] } hitcount:         21  count:         21
+    { common_pid: nm-dispatcher.a [      8696] } hitcount:          1  count:         16
+    { common_pid: indicator-datet [      2904] } hitcount:          1  count:         16
+    { common_pid: gdbus           [      2998] } hitcount:          1  count:         16
+    { common_pid: rtkit-daemon    [      2052] } hitcount:          1  count:          8
+    { common_pid: init            [         1] } hitcount:          2  count:          2
+
+    Totals:
+        Hits: 2116
+        Entries: 51
+        Dropped: 0
+
+  Similarly, if you key a hist trigger on syscall id, for example to
+  gather and display a list of systemwide syscall hits, you can use
+  the special .syscall modifier to display the syscall names rather
+  than raw ids.  The example below keeps a running total of syscall
+  counts for the system during the run:
+
+    # echo 'hist:key=id.syscall:val=hitcount' > \
+           /sys/kernel/debug/tracing/events/raw_syscalls/sys_enter/trigger
+
+    # cat /sys/kernel/debug/tracing/events/raw_syscalls/sys_enter/hist
+    # trigger info: hist:keys=id.syscall:vals=hitcount:sort=hitcount:size=2048 [active]
+
+    { id: sys_fsync                     [ 74] } hitcount:          1
+    { id: sys_newuname                  [ 63] } hitcount:          1
+    { id: sys_prctl                     [157] } hitcount:          1
+    { id: sys_statfs                    [137] } hitcount:          1
+    { id: sys_symlink                   [ 88] } hitcount:          1
+    { id: sys_sendmmsg                  [307] } hitcount:          1
+    { id: sys_semctl                    [ 66] } hitcount:          1
+    { id: sys_readlink                  [ 89] } hitcount:          3
+    { id: sys_bind                      [ 49] } hitcount:          3
+    { id: sys_getsockname               [ 51] } hitcount:          3
+    { id: sys_unlink                    [ 87] } hitcount:          3
+    { id: sys_rename                    [ 82] } hitcount:          4
+    { id: unknown_syscall               [ 58] } hitcount:          4
+    { id: sys_connect                   [ 42] } hitcount:          4
+    { id: sys_getpid                    [ 39] } hitcount:          4
+    .
+    .
+    .
+    { id: sys_rt_sigprocmask            [ 14] } hitcount:        952
+    { id: sys_futex                     [202] } hitcount:       1534
+    { id: sys_write                     [  1] } hitcount:       2689
+    { id: sys_setitimer                 [ 38] } hitcount:       2797
+    { id: sys_read                      [  0] } hitcount:       3202
+    { id: sys_select                    [ 23] } hitcount:       3773
+    { id: sys_writev                    [ 20] } hitcount:       4531
+    { id: sys_poll                      [  7] } hitcount:       8314
+    { id: sys_recvmsg                   [ 47] } hitcount:      13738
+    { id: sys_ioctl                     [ 16] } hitcount:      21843
+
+    Totals:
+        Hits: 67612
+        Entries: 72
+        Dropped: 0
+
+    The syscall counts above provide a rough overall picture of system
+    call activity on the system; we can see for example that the most
+    popular system call on this system was the 'sys_ioctl' system call.
+
+    We can use 'compound' keys to refine that number and provide some
+    further insight as to which processes exactly contribute to the
+    overall ioctl count.
+
+    The command below keeps a hitcount for every unique combination of
+    system call id and pid - the end result is essentially a table
+    that keeps a per-pid sum of system call hits.  The results are
+    sorted using the system call id as the primary key, and the
+    hitcount sum as the secondary key:
+
+    # echo 'hist:key=id.syscall,common_pid.execname:val=hitcount:sort=id,hitcount' > \
+           /sys/kernel/debug/tracing/events/raw_syscalls/sys_enter/trigger
+
+    # cat /sys/kernel/debug/tracing/events/raw_syscalls/sys_enter/hist
+    # trigger info: hist:keys=id.syscall,common_pid.execname:vals=hitcount:sort=id.syscall,hitcount:size=2048 [active]
+
+    { id: sys_read                      [  0], common_pid: rtkit-daemon    [      1877] } hitcount:          1
+    { id: sys_read                      [  0], common_pid: gdbus           [      2976] } hitcount:          1
+    { id: sys_read                      [  0], common_pid: console-kit-dae [      3400] } hitcount:          1
+    { id: sys_read                      [  0], common_pid: postgres        [      1865] } hitcount:          1
+    { id: sys_read                      [  0], common_pid: deja-dup-monito [      3543] } hitcount:          2
+    { id: sys_read                      [  0], common_pid: NetworkManager  [       890] } hitcount:          2
+    { id: sys_read                      [  0], common_pid: evolution-calen [      3048] } hitcount:          2
+    { id: sys_read                      [  0], common_pid: postgres        [      1864] } hitcount:          2
+    { id: sys_read                      [  0], common_pid: nm-applet       [      3022] } hitcount:          2
+    { id: sys_read                      [  0], common_pid: whoopsie        [      1212] } hitcount:          2
+    .
+    .
+    .
+    { id: sys_ioctl                     [ 16], common_pid: bash            [      8479] } hitcount:          1
+    { id: sys_ioctl                     [ 16], common_pid: bash            [      3472] } hitcount:         12
+    { id: sys_ioctl                     [ 16], common_pid: gnome-terminal  [      3199] } hitcount:         16
+    { id: sys_ioctl                     [ 16], common_pid: Xorg            [      1267] } hitcount:       1808
+    { id: sys_ioctl                     [ 16], common_pid: compiz          [      2994] } hitcount:       5580
+    .
+    .
+    .
+    { id: sys_waitid                    [247], common_pid: upstart-dbus-br [      2690] } hitcount:          3
+    { id: sys_waitid                    [247], common_pid: upstart-dbus-br [      2688] } hitcount:         16
+    { id: sys_inotify_add_watch         [254], common_pid: gmain           [       975] } hitcount:          2
+    { id: sys_inotify_add_watch         [254], common_pid: gmain           [      3204] } hitcount:          4
+    { id: sys_inotify_add_watch         [254], common_pid: gmain           [      2888] } hitcount:          4
+    { id: sys_inotify_add_watch         [254], common_pid: gmain           [      3003] } hitcount:          4
+    { id: sys_inotify_add_watch         [254], common_pid: gmain           [      2873] } hitcount:          4
+    { id: sys_inotify_add_watch         [254], common_pid: gmain           [      3196] } hitcount:          6
+    { id: sys_openat                    [257], common_pid: java            [      2623] } hitcount:          2
+    { id: sys_eventfd2                  [290], common_pid: ibus-ui-gtk3    [      2760] } hitcount:          4
+    { id: sys_eventfd2                  [290], common_pid: compiz          [      2994] } hitcount:          6
+
+    Totals:
+        Hits: 31536
+        Entries: 323
+        Dropped: 0
+
+    The above list does give us a breakdown of the ioctl syscall by
+    pid, but it also gives us quite a bit more than that, which we
+    don't really care about at the moment.  Since we know the syscall
+    id for sys_ioctl (16, displayed next to the sys_ioctl name), we
+    can use that to filter out all the other syscalls:
+
+    # echo 'hist:key=id.syscall,common_pid.execname:val=hitcount:sort=id,hitcount if id == 16' > \
+           /sys/kernel/debug/tracing/events/raw_syscalls/sys_enter/trigger
+
+    # cat /sys/kernel/debug/tracing/events/raw_syscalls/sys_enter/hist
+    # trigger info: hist:keys=id.syscall,common_pid.execname:vals=hitcount:sort=id.syscall,hitcount:size=2048 if id == 16 [active]
+
+    { id: sys_ioctl                     [ 16], common_pid: gmain           [      2769] } hitcount:          1
+    { id: sys_ioctl                     [ 16], common_pid: evolution-addre [      8571] } hitcount:          1
+    { id: sys_ioctl                     [ 16], common_pid: gmain           [      3003] } hitcount:          1
+    { id: sys_ioctl                     [ 16], common_pid: gmain           [      2781] } hitcount:          1
+    { id: sys_ioctl                     [ 16], common_pid: gmain           [      2829] } hitcount:          1
+    { id: sys_ioctl                     [ 16], common_pid: bash            [      8726] } hitcount:          1
+    { id: sys_ioctl                     [ 16], common_pid: bash            [      8508] } hitcount:          1
+    { id: sys_ioctl                     [ 16], common_pid: gmain           [      2970] } hitcount:          1
+    { id: sys_ioctl                     [ 16], common_pid: gmain           [      2768] } hitcount:          1
+    .
+    .
+    .
+    { id: sys_ioctl                     [ 16], common_pid: pool            [      8559] } hitcount:         45
+    { id: sys_ioctl                     [ 16], common_pid: pool            [      8555] } hitcount:         48
+    { id: sys_ioctl                     [ 16], common_pid: pool            [      8551] } hitcount:         48
+    { id: sys_ioctl                     [ 16], common_pid: avahi-daemon    [       896] } hitcount:         66
+    { id: sys_ioctl                     [ 16], common_pid: Xorg            [      1267] } hitcount:      26674
+    { id: sys_ioctl                     [ 16], common_pid: compiz          [      2994] } hitcount:      73443
+
+    Totals:
+        Hits: 101162
+        Entries: 103
+        Dropped: 0
+
+    The above output shows that 'compiz' and 'Xorg' are far and away
+    the heaviest ioctl callers (which might lead to questions about
+    whether they really need to be making all those calls and to
+    possible avenues for further investigation.)
+
+    The compound key examples used a key and a sum value (hitcount) to
+    sort the output, but we can just as easily use two keys instead.
+    Here's an example where we use a compound key composed of the the
+    common_pid and size event fields.  Sorting with pid as the primary
+    key and 'size' as the secondary key allows us to display an
+    ordered summary of the recvfrom sizes, with counts, received by
+    each process:
+
+    # echo 'hist:key=common_pid.execname,size:val=hitcount:sort=common_pid,size' > \
+           /sys/kernel/debug/tracing/events/syscalls/sys_enter_recvfrom/trigger
+
+    # cat /sys/kernel/debug/tracing/events/syscalls/sys_enter_recvfrom/hist
+    # trigger info: hist:keys=common_pid.execname,size:vals=hitcount:sort=common_pid.execname,size:size=2048 [active]
+
+    { common_pid: smbd            [       784], size:          4 } hitcount:          1
+    { common_pid: dnsmasq         [      1412], size:       4096 } hitcount:        672
+    { common_pid: postgres        [      1796], size:       1000 } hitcount:          6
+    { common_pid: postgres        [      1867], size:       1000 } hitcount:         10
+    { common_pid: bamfdaemon      [      2787], size:         28 } hitcount:          2
+    { common_pid: bamfdaemon      [      2787], size:      14360 } hitcount:          1
+    { common_pid: compiz          [      2994], size:          8 } hitcount:          1
+    { common_pid: compiz          [      2994], size:         20 } hitcount:         11
+    { common_pid: gnome-terminal  [      3199], size:          4 } hitcount:          2
+    { common_pid: firefox         [      8817], size:          4 } hitcount:          1
+    { common_pid: firefox         [      8817], size:          8 } hitcount:          5
+    { common_pid: firefox         [      8817], size:        588 } hitcount:          2
+    { common_pid: firefox         [      8817], size:        628 } hitcount:          1
+    { common_pid: firefox         [      8817], size:       6944 } hitcount:          1
+    { common_pid: firefox         [      8817], size:     408880 } hitcount:          2
+    { common_pid: firefox         [      8822], size:          8 } hitcount:          2
+    { common_pid: firefox         [      8822], size:        160 } hitcount:          2
+    { common_pid: firefox         [      8822], size:        320 } hitcount:          2
+    { common_pid: firefox         [      8822], size:        352 } hitcount:          1
+    .
+    .
+    .
+    { common_pid: pool            [      8923], size:       1960 } hitcount:         10
+    { common_pid: pool            [      8923], size:       2048 } hitcount:         10
+    { common_pid: pool            [      8924], size:       1960 } hitcount:         10
+    { common_pid: pool            [      8924], size:       2048 } hitcount:         10
+    { common_pid: pool            [      8928], size:       1964 } hitcount:          4
+    { common_pid: pool            [      8928], size:       1965 } hitcount:          2
+    { common_pid: pool            [      8928], size:       2048 } hitcount:          6
+    { common_pid: pool            [      8929], size:       1982 } hitcount:          1
+    { common_pid: pool            [      8929], size:       2048 } hitcount:          1
+
+    Totals:
+        Hits: 2016
+        Entries: 224
+        Dropped: 0
+
+  The above example also illustrates the fact that although a compound
+  key is treated as a single entity for hashing purposes, the sub-keys
+  it's composed of can be accessed independently.
+
+  The next example uses a string field as the hash key and
+  demonstrates how you can manually pause and continue a hist trigger.
+  In this example, we'll aggregate fork counts and don't expect a
+  large number of entries in the hash table, so we'll drop it to a
+  much smaller number, say 256:
+
+    # echo 'hist:key=child_comm:val=hitcount:size=256' > \
+           /sys/kernel/debug/tracing/events/sched/sched_process_fork/trigger
+
+    # cat /sys/kernel/debug/tracing/events/sched/sched_process_fork/hist
+    # trigger info: hist:keys=child_comm:vals=hitcount:sort=hitcount:size=256 [active]
+
+    { child_comm: dconf worker                        } hitcount:          1
+    { child_comm: ibus-daemon                         } hitcount:          1
+    { child_comm: whoopsie                            } hitcount:          1
+    { child_comm: smbd                                } hitcount:          1
+    { child_comm: gdbus                               } hitcount:          1
+    { child_comm: kthreadd                            } hitcount:          1
+    { child_comm: dconf worker                        } hitcount:          1
+    { child_comm: evolution-alarm                     } hitcount:          2
+    { child_comm: Socket Thread                       } hitcount:          2
+    { child_comm: postgres                            } hitcount:          2
+    { child_comm: bash                                } hitcount:          3
+    { child_comm: compiz                              } hitcount:          3
+    { child_comm: evolution-sourc                     } hitcount:          4
+    { child_comm: dhclient                            } hitcount:          4
+    { child_comm: pool                                } hitcount:          5
+    { child_comm: nm-dispatcher.a                     } hitcount:          8
+    { child_comm: firefox                             } hitcount:          8
+    { child_comm: dbus-daemon                         } hitcount:          8
+    { child_comm: glib-pacrunner                      } hitcount:         10
+    { child_comm: evolution                           } hitcount:         23
+
+    Totals:
+        Hits: 89
+        Entries: 20
+        Dropped: 0
+
+  If we want to pause the hist trigger, we can simply append :pause to
+  the command that started the trigger.  Notice that the trigger info
+  displays as [paused]:
+
+    # echo 'hist:key=child_comm:val=hitcount:size=256:pause' >> \
+           /sys/kernel/debug/tracing/events/sched/sched_process_fork/trigger
+
+    # cat /sys/kernel/debug/tracing/events/sched/sched_process_fork/hist
+    # trigger info: hist:keys=child_comm:vals=hitcount:sort=hitcount:size=256 [paused]
+
+    { child_comm: dconf worker                        } hitcount:          1
+    { child_comm: kthreadd                            } hitcount:          1
+    { child_comm: dconf worker                        } hitcount:          1
+    { child_comm: gdbus                               } hitcount:          1
+    { child_comm: ibus-daemon                         } hitcount:          1
+    { child_comm: Socket Thread                       } hitcount:          2
+    { child_comm: evolution-alarm                     } hitcount:          2
+    { child_comm: smbd                                } hitcount:          2
+    { child_comm: bash                                } hitcount:          3
+    { child_comm: whoopsie                            } hitcount:          3
+    { child_comm: compiz                              } hitcount:          3
+    { child_comm: evolution-sourc                     } hitcount:          4
+    { child_comm: pool                                } hitcount:          5
+    { child_comm: postgres                            } hitcount:          6
+    { child_comm: firefox                             } hitcount:          8
+    { child_comm: dhclient                            } hitcount:         10
+    { child_comm: emacs                               } hitcount:         12
+    { child_comm: dbus-daemon                         } hitcount:         20
+    { child_comm: nm-dispatcher.a                     } hitcount:         20
+    { child_comm: evolution                           } hitcount:         35
+    { child_comm: glib-pacrunner                      } hitcount:         59
+
+    Totals:
+        Hits: 199
+        Entries: 21
+        Dropped: 0
+
+  To manually continue having the trigger aggregate events, append
+  :cont instead.  Notice that the trigger info displays as [active]
+  again, and the data has changed:
+
+    # echo 'hist:key=child_comm:val=hitcount:size=256:cont' >> \
+           /sys/kernel/debug/tracing/events/sched/sched_process_fork/trigger
+
+    # cat /sys/kernel/debug/tracing/events/sched/sched_process_fork/hist
+    # trigger info: hist:keys=child_comm:vals=hitcount:sort=hitcount:size=256 [active]
+
+    { child_comm: dconf worker                        } hitcount:          1
+    { child_comm: dconf worker                        } hitcount:          1
+    { child_comm: kthreadd                            } hitcount:          1
+    { child_comm: gdbus                               } hitcount:          1
+    { child_comm: ibus-daemon                         } hitcount:          1
+    { child_comm: Socket Thread                       } hitcount:          2
+    { child_comm: evolution-alarm                     } hitcount:          2
+    { child_comm: smbd                                } hitcount:          2
+    { child_comm: whoopsie                            } hitcount:          3
+    { child_comm: compiz                              } hitcount:          3
+    { child_comm: evolution-sourc                     } hitcount:          4
+    { child_comm: bash                                } hitcount:          5
+    { child_comm: pool                                } hitcount:          5
+    { child_comm: postgres                            } hitcount:          6
+    { child_comm: firefox                             } hitcount:          8
+    { child_comm: dhclient                            } hitcount:         11
+    { child_comm: emacs                               } hitcount:         12
+    { child_comm: dbus-daemon                         } hitcount:         22
+    { child_comm: nm-dispatcher.a                     } hitcount:         22
+    { child_comm: evolution                           } hitcount:         35
+    { child_comm: glib-pacrunner                      } hitcount:         59
+
+    Totals:
+        Hits: 206
+        Entries: 21
+        Dropped: 0
+
+  The previous example showed how to start and stop a hist trigger by
+  appending 'pause' and 'continue' to the hist trigger command.  A
+  hist trigger can also be started in a paused state by initially
+  starting the trigger with ':pause' appended.  This allows you to
+  start the trigger only when you're ready to start collecting data
+  and not before.  For example, you could start the trigger in a
+  paused state, then unpause it and do something you want to measure,
+  then pause the trigger again when done.
+
+  Of course, doing this manually can be difficult and error-prone, but
+  it is possible to automatically start and stop a hist trigger based
+  on some condition, via the enable_hist and disable_hist triggers.
+
+  For example, suppose we wanted to take a look at the relative
+  weights in terms of skb length for each callpath that leads to a
+  netif_receieve_skb event when downloading a decent-sized file using
+  wget.
+
+  First we set up an initially paused stacktrace trigger on the
+  netif_receive_skb event:
+
+    # echo 'hist:key=stacktrace:vals=len:pause' > \
+           /sys/kernel/debug/tracing/events/net/netif_receive_skb/trigger
+
+  Next, we set up an 'enable_hist' trigger on the sched_process_exec
+  event, with an 'if filename==/usr/bin/wget' filter.  The effect of
+  this new trigger is that it will 'unpause' the hist trigger we just
+  set up on netif_receive_skb if and only if it sees a
+  sched_process_exec event with a filename of '/usr/bin/wget'.  When
+  that happens, all netif_receive_skb events are aggregated into a
+  hash table keyed on stacktrace:
+
+    # echo 'enable_hist:net:netif_receive_skb if filename==/usr/bin/wget' > \
+           /sys/kernel/debug/tracing/events/sched/sched_process_exec/trigger
+
+  The aggregation continues until the netif_receive_skb is paused
+  again, which is what the following disable_hist event does by
+  creating a similar setup on the sched_process_exit event, using the
+  filter 'comm==wget':
+
+    # echo 'disable_hist:net:netif_receive_skb if comm==wget' > \
+           /sys/kernel/debug/tracing/events/sched/sched_process_exit/trigger
+
+  Whenever a process exits and the comm field of the disable_hist
+  trigger filter matches 'comm==wget', the netif_receive_skb hist
+  trigger is disabled.
+
+  The overall effect is that netif_receive_skb events are aggregated
+  into the hash table for only the duration of the wget.  Executing a
+  wget command and then listing the 'hist' file will display the
+  output generated by the wget command:
+
+    $ wget https://www.kernel.org/pub/linux/kernel/v3.x/patch-3.19.xz
+
+    # cat /sys/kernel/debug/tracing/events/net/netif_receive_skb/hist
+    # trigger info: hist:keys=stacktrace:vals=len:sort=hitcount:size=2048 [paused]
+
+    { stacktrace:
+         __netif_receive_skb_core+0x46d/0x990
+         __netif_receive_skb+0x18/0x60
+         netif_receive_skb_internal+0x23/0x90
+         napi_gro_receive+0xc8/0x100
+         ieee80211_deliver_skb+0xd6/0x270 [mac80211]
+         ieee80211_rx_handlers+0xccf/0x22f0 [mac80211]
+         ieee80211_prepare_and_rx_handle+0x4e7/0xc40 [mac80211]
+         ieee80211_rx+0x31d/0x900 [mac80211]
+         iwlagn_rx_reply_rx+0x3db/0x6f0 [iwldvm]
+         iwl_rx_dispatch+0x8e/0xf0 [iwldvm]
+         iwl_pcie_irq_handler+0xe3c/0x12f0 [iwlwifi]
+         irq_thread_fn+0x20/0x50
+         irq_thread+0x11f/0x150
+         kthread+0xd2/0xf0
+         ret_from_fork+0x42/0x70
+    } hitcount:         85  len:      28884
+    { stacktrace:
+         __netif_receive_skb_core+0x46d/0x990
+         __netif_receive_skb+0x18/0x60
+         netif_receive_skb_internal+0x23/0x90
+         napi_gro_complete+0xa4/0xe0
+         dev_gro_receive+0x23a/0x360
+         napi_gro_receive+0x30/0x100
+         ieee80211_deliver_skb+0xd6/0x270 [mac80211]
+         ieee80211_rx_handlers+0xccf/0x22f0 [mac80211]
+         ieee80211_prepare_and_rx_handle+0x4e7/0xc40 [mac80211]
+         ieee80211_rx+0x31d/0x900 [mac80211]
+         iwlagn_rx_reply_rx+0x3db/0x6f0 [iwldvm]
+         iwl_rx_dispatch+0x8e/0xf0 [iwldvm]
+         iwl_pcie_irq_handler+0xe3c/0x12f0 [iwlwifi]
+         irq_thread_fn+0x20/0x50
+         irq_thread+0x11f/0x150
+         kthread+0xd2/0xf0
+    } hitcount:         98  len:     664329
+    { stacktrace:
+         __netif_receive_skb_core+0x46d/0x990
+         __netif_receive_skb+0x18/0x60
+         process_backlog+0xa8/0x150
+         net_rx_action+0x15d/0x340
+         __do_softirq+0x114/0x2c0
+         do_softirq_own_stack+0x1c/0x30
+         do_softirq+0x65/0x70
+         __local_bh_enable_ip+0xb5/0xc0
+         ip_finish_output+0x1f4/0x840
+         ip_output+0x6b/0xc0
+         ip_local_out_sk+0x31/0x40
+         ip_send_skb+0x1a/0x50
+         udp_send_skb+0x173/0x2a0
+         udp_sendmsg+0x2bf/0x9f0
+         inet_sendmsg+0x64/0xa0
+         sock_sendmsg+0x3d/0x50
+    } hitcount:        115  len:      13030
+    { stacktrace:
+         __netif_receive_skb_core+0x46d/0x990
+         __netif_receive_skb+0x18/0x60
+         netif_receive_skb_internal+0x23/0x90
+         napi_gro_complete+0xa4/0xe0
+         napi_gro_flush+0x6d/0x90
+         iwl_pcie_irq_handler+0x92a/0x12f0 [iwlwifi]
+         irq_thread_fn+0x20/0x50
+         irq_thread+0x11f/0x150
+         kthread+0xd2/0xf0
+         ret_from_fork+0x42/0x70
+    } hitcount:        934  len:    5512212
+
+    Totals:
+        Hits: 1232
+        Entries: 4
+        Dropped: 0
+
+  The above shows all the netif_receive_skb callpaths and their total
+  lengths for the duration of the wget command.
+
+  The 'clear' hist trigger param can be used to clear the hash table.
+  Suppose we wanted to try another run of the previous example but
+  this time also wanted to see the complete list of events that went
+  into the histogram.  In order to avoid having to set everything up
+  again, we can just clear the histogram first:
+
+    # echo 'hist:key=stacktrace:vals=len:clear' >> \
+           /sys/kernel/debug/tracing/events/net/netif_receive_skb/trigger
+
+  Just to verify that it is in fact cleared, here's what we now see in
+  the hist file:
+
+    # cat /sys/kernel/debug/tracing/events/net/netif_receive_skb/hist
+    # trigger info: hist:keys=stacktrace:vals=len:sort=hitcount:size=2048 [paused]
+
+    Totals:
+        Hits: 0
+        Entries: 0
+        Dropped: 0
+
+  Since we want to see the detailed list of every netif_receive_skb
+  event occurring during the new run, which are in fact the same
+  events being aggregated into the hash table, we add some additional
+  'enable_event' events to the triggering sched_process_exec and
+  sched_process_exit events as such:
+
+    # echo 'enable_event:net:netif_receive_skb if filename==/usr/bin/wget' > \
+           /sys/kernel/debug/tracing/events/sched/sched_process_exec/trigger
+
+    # echo 'disable_event:net:netif_receive_skb if comm==wget' > \
+           /sys/kernel/debug/tracing/events/sched/sched_process_exit/trigger
+
+  If you read the trigger files for the sched_process_exec and
+  sched_process_exit triggers, you should see two triggers for each:
+  one enabling/disabling the hist aggregation and the other
+  enabling/disabling the logging of events:
+
+    # cat /sys/kernel/debug/tracing/events/sched/sched_process_exec/trigger
+    enable_event:net:netif_receive_skb:unlimited if filename==/usr/bin/wget
+    enable_hist:net:netif_receive_skb:unlimited if filename==/usr/bin/wget
+
+    # cat /sys/kernel/debug/tracing/events/sched/sched_process_exit/trigger
+    enable_event:net:netif_receive_skb:unlimited if comm==wget
+    disable_hist:net:netif_receive_skb:unlimited if comm==wget
+
+  In other words, whenever either of the sched_process_exec or
+  sched_process_exit events is hit and matches 'wget', it enables or
+  disables both the histogram and the event log, and what you end up
+  with is a hash table and set of events just covering the specified
+  duration.  Run the wget command again:
+
+    $ wget https://www.kernel.org/pub/linux/kernel/v3.x/patch-3.19.xz
+
+  Displaying the 'hist' file should show something similar to what you
+  saw in the last run, but this time you should also see the
+  individual events in the trace file:
+
+    # cat /sys/kernel/debug/tracing/trace
+
+    # tracer: nop
+    #
+    # entries-in-buffer/entries-written: 183/1426   #P:4
+    #
+    #                              _-----=> irqs-off
+    #                             / _----=> need-resched
+    #                            | / _---=> hardirq/softirq
+    #                            || / _--=> preempt-depth
+    #                            ||| /     delay
+    #           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION
+    #              | |       |   ||||       |         |
+                wget-15108 [000] ..s1 31769.606929: netif_receive_skb: dev=lo skbaddr=ffff88009c353100 len=60
+                wget-15108 [000] ..s1 31769.606999: netif_receive_skb: dev=lo skbaddr=ffff88009c353200 len=60
+             dnsmasq-1382  [000] ..s1 31769.677652: netif_receive_skb: dev=lo skbaddr=ffff88009c352b00 len=130
+             dnsmasq-1382  [000] ..s1 31769.685917: netif_receive_skb: dev=lo skbaddr=ffff88009c352200 len=138
+    ##### CPU 2 buffer started ####
+      irq/29-iwlwifi-559   [002] ..s. 31772.031529: netif_receive_skb: dev=wlan0 skbaddr=ffff88009d433d00 len=2948
+      irq/29-iwlwifi-559   [002] ..s. 31772.031572: netif_receive_skb: dev=wlan0 skbaddr=ffff88009d432200 len=1500
+      irq/29-iwlwifi-559   [002] ..s. 31772.032196: netif_receive_skb: dev=wlan0 skbaddr=ffff88009d433100 len=2948
+      irq/29-iwlwifi-559   [002] ..s. 31772.032761: netif_receive_skb: dev=wlan0 skbaddr=ffff88009d433000 len=2948
+      irq/29-iwlwifi-559   [002] ..s. 31772.033220: netif_receive_skb: dev=wlan0 skbaddr=ffff88009d432e00 len=1500
+    .
+    .
+    .
+
+  The following example demonstrates how multiple hist triggers can be
+  attached to a given event.  This capability can be useful for
+  creating a set of different summaries derived from the same set of
+  events, or for comparing the effects of different filters, among
+  other things.
+
+    # echo 'hist:keys=skbaddr.hex:vals=len if len < 0' >> \
+           /sys/kernel/debug/tracing/events/net/netif_receive_skb/trigger
+    # echo 'hist:keys=skbaddr.hex:vals=len if len > 4096' >> \
+           /sys/kernel/debug/tracing/events/net/netif_receive_skb/trigger
+    # echo 'hist:keys=skbaddr.hex:vals=len if len == 256' >> \
+           /sys/kernel/debug/tracing/events/net/netif_receive_skb/trigger
+    # echo 'hist:keys=skbaddr.hex:vals=len' >> \
+           /sys/kernel/debug/tracing/events/net/netif_receive_skb/trigger
+    # echo 'hist:keys=len:vals=common_preempt_count' >> \
+           /sys/kernel/debug/tracing/events/net/netif_receive_skb/trigger
+
+  The above set of commands create four triggers differing only in
+  their filters, along with a completely different though fairly
+  nonsensical trigger.  Note that in order to append multiple hist
+  triggers to the same file, you should use the '>>' operator to
+  append them ('>' will also add the new hist trigger, but will remove
+  any existing hist triggers beforehand).
+
+  Displaying the contents of the 'hist' file for the event shows the
+  contents of all five histograms:
+
+    # cat /sys/kernel/debug/tracing/events/net/netif_receive_skb/hist
+
+    # event histogram
+    #
+    # trigger info: hist:keys=len:vals=hitcount,common_preempt_count:sort=hitcount:size=2048 [active]
+    #
+
+    { len:        176 } hitcount:          1  common_preempt_count:          0
+    { len:        223 } hitcount:          1  common_preempt_count:          0
+    { len:       4854 } hitcount:          1  common_preempt_count:          0
+    { len:        395 } hitcount:          1  common_preempt_count:          0
+    { len:        177 } hitcount:          1  common_preempt_count:          0
+    { len:        446 } hitcount:          1  common_preempt_count:          0
+    { len:       1601 } hitcount:          1  common_preempt_count:          0
+    .
+    .
+    .
+    { len:       1280 } hitcount:         66  common_preempt_count:          0
+    { len:        116 } hitcount:         81  common_preempt_count:         40
+    { len:        708 } hitcount:        112  common_preempt_count:          0
+    { len:         46 } hitcount:        221  common_preempt_count:          0
+    { len:       1264 } hitcount:        458  common_preempt_count:          0
+
+    Totals:
+        Hits: 1428
+        Entries: 147
+        Dropped: 0
+
+
+    # event histogram
+    #
+    # trigger info: hist:keys=skbaddr.hex:vals=hitcount,len:sort=hitcount:size=2048 [active]
+    #
+
+    { skbaddr: ffff8800baee5e00 } hitcount:          1  len:        130
+    { skbaddr: ffff88005f3d5600 } hitcount:          1  len:       1280
+    { skbaddr: ffff88005f3d4900 } hitcount:          1  len:       1280
+    { skbaddr: ffff88009fed6300 } hitcount:          1  len:        115
+    { skbaddr: ffff88009fe0ad00 } hitcount:          1  len:        115
+    { skbaddr: ffff88008cdb1900 } hitcount:          1  len:         46
+    { skbaddr: ffff880064b5ef00 } hitcount:          1  len:        118
+    { skbaddr: ffff880044e3c700 } hitcount:          1  len:         60
+    { skbaddr: ffff880100065900 } hitcount:          1  len:         46
+    { skbaddr: ffff8800d46bd500 } hitcount:          1  len:        116
+    { skbaddr: ffff88005f3d5f00 } hitcount:          1  len:       1280
+    { skbaddr: ffff880100064700 } hitcount:          1  len:        365
+    { skbaddr: ffff8800badb6f00 } hitcount:          1  len:         60
+    .
+    .
+    .
+    { skbaddr: ffff88009fe0be00 } hitcount:         27  len:      24677
+    { skbaddr: ffff88009fe0a400 } hitcount:         27  len:      23052
+    { skbaddr: ffff88009fe0b700 } hitcount:         31  len:      25589
+    { skbaddr: ffff88009fe0b600 } hitcount:         32  len:      27326
+    { skbaddr: ffff88006a462800 } hitcount:         68  len:      71678
+    { skbaddr: ffff88006a463700 } hitcount:         70  len:      72678
+    { skbaddr: ffff88006a462b00 } hitcount:         71  len:      77589
+    { skbaddr: ffff88006a463600 } hitcount:         73  len:      71307
+    { skbaddr: ffff88006a462200 } hitcount:         81  len:      81032
+
+    Totals:
+        Hits: 1451
+        Entries: 318
+        Dropped: 0
+
+
+    # event histogram
+    #
+    # trigger info: hist:keys=skbaddr.hex:vals=hitcount,len:sort=hitcount:size=2048 if len == 256 [active]
+    #
+
+
+    Totals:
+        Hits: 0
+        Entries: 0
+        Dropped: 0
+
+
+    # event histogram
+    #
+    # trigger info: hist:keys=skbaddr.hex:vals=hitcount,len:sort=hitcount:size=2048 if len > 4096 [active]
+    #
+
+    { skbaddr: ffff88009fd2c300 } hitcount:          1  len:       7212
+    { skbaddr: ffff8800d2bcce00 } hitcount:          1  len:       7212
+    { skbaddr: ffff8800d2bcd700 } hitcount:          1  len:       7212
+    { skbaddr: ffff8800d2bcda00 } hitcount:          1  len:      21492
+    { skbaddr: ffff8800ae2e2d00 } hitcount:          1  len:       7212
+    { skbaddr: ffff8800d2bcdb00 } hitcount:          1  len:       7212
+    { skbaddr: ffff88006a4df500 } hitcount:          1  len:       4854
+    { skbaddr: ffff88008ce47b00 } hitcount:          1  len:      18636
+    { skbaddr: ffff8800ae2e2200 } hitcount:          1  len:      12924
+    { skbaddr: ffff88005f3e1000 } hitcount:          1  len:       4356
+    { skbaddr: ffff8800d2bcdc00 } hitcount:          2  len:      24420
+    { skbaddr: ffff8800d2bcc200 } hitcount:          2  len:      12996
+
+    Totals:
+        Hits: 14
+        Entries: 12
+        Dropped: 0
+
+
+    # event histogram
+    #
+    # trigger info: hist:keys=skbaddr.hex:vals=hitcount,len:sort=hitcount:size=2048 if len < 0 [active]
+    #
+
+
+    Totals:
+        Hits: 0
+        Entries: 0
+        Dropped: 0
+
+  Named triggers can be used to have triggers share a common set of
+  histogram data.  This capability is mostly useful for combining the
+  output of events generated by tracepoints contained inside inline
+  functions, but names can be used in a hist trigger on any event.
+  For example, these two triggers when hit will update the same 'len'
+  field in the shared 'foo' histogram data:
+
+    # echo 'hist:name=foo:keys=skbaddr.hex:vals=len' > \
+           /sys/kernel/debug/tracing/events/net/netif_receive_skb/trigger
+    # echo 'hist:name=foo:keys=skbaddr.hex:vals=len' > \
+           /sys/kernel/debug/tracing/events/net/netif_rx/trigger
+
+  You can see that they're updating common histogram data by reading
+  each event's hist files at the same time:
+
+    # cat /sys/kernel/debug/tracing/events/net/netif_receive_skb/hist;
+      cat /sys/kernel/debug/tracing/events/net/netif_rx/hist
+
+    # event histogram
+    #
+    # trigger info: hist:name=foo:keys=skbaddr.hex:vals=hitcount,len:sort=hitcount:size=2048 [active]
+    #
+
+    { skbaddr: ffff88000ad53500 } hitcount:          1  len:         46
+    { skbaddr: ffff8800af5a1500 } hitcount:          1  len:         76
+    { skbaddr: ffff8800d62a1900 } hitcount:          1  len:         46
+    { skbaddr: ffff8800d2bccb00 } hitcount:          1  len:        468
+    { skbaddr: ffff8800d3c69900 } hitcount:          1  len:         46
+    { skbaddr: ffff88009ff09100 } hitcount:          1  len:         52
+    { skbaddr: ffff88010f13ab00 } hitcount:          1  len:        168
+    { skbaddr: ffff88006a54f400 } hitcount:          1  len:         46
+    { skbaddr: ffff8800d2bcc500 } hitcount:          1  len:        260
+    { skbaddr: ffff880064505000 } hitcount:          1  len:         46
+    { skbaddr: ffff8800baf24e00 } hitcount:          1  len:         32
+    { skbaddr: ffff88009fe0ad00 } hitcount:          1  len:         46
+    { skbaddr: ffff8800d3edff00 } hitcount:          1  len:         44
+    { skbaddr: ffff88009fe0b400 } hitcount:          1  len:        168
+    { skbaddr: ffff8800a1c55a00 } hitcount:          1  len:         40
+    { skbaddr: ffff8800d2bcd100 } hitcount:          1  len:         40
+    { skbaddr: ffff880064505f00 } hitcount:          1  len:        174
+    { skbaddr: ffff8800a8bff200 } hitcount:          1  len:        160
+    { skbaddr: ffff880044e3cc00 } hitcount:          1  len:         76
+    { skbaddr: ffff8800a8bfe700 } hitcount:          1  len:         46
+    { skbaddr: ffff8800d2bcdc00 } hitcount:          1  len:         32
+    { skbaddr: ffff8800a1f64800 } hitcount:          1  len:         46
+    { skbaddr: ffff8800d2bcde00 } hitcount:          1  len:        988
+    { skbaddr: ffff88006a5dea00 } hitcount:          1  len:         46
+    { skbaddr: ffff88002e37a200 } hitcount:          1  len:         44
+    { skbaddr: ffff8800a1f32c00 } hitcount:          2  len:        676
+    { skbaddr: ffff88000ad52600 } hitcount:          2  len:        107
+    { skbaddr: ffff8800a1f91e00 } hitcount:          2  len:         92
+    { skbaddr: ffff8800af5a0200 } hitcount:          2  len:        142
+    { skbaddr: ffff8800d2bcc600 } hitcount:          2  len:        220
+    { skbaddr: ffff8800ba36f500 } hitcount:          2  len:         92
+    { skbaddr: ffff8800d021f800 } hitcount:          2  len:         92
+    { skbaddr: ffff8800a1f33600 } hitcount:          2  len:        675
+    { skbaddr: ffff8800a8bfff00 } hitcount:          3  len:        138
+    { skbaddr: ffff8800d62a1300 } hitcount:          3  len:        138
+    { skbaddr: ffff88002e37a100 } hitcount:          4  len:        184
+    { skbaddr: ffff880064504400 } hitcount:          4  len:        184
+    { skbaddr: ffff8800a8bfec00 } hitcount:          4  len:        184
+    { skbaddr: ffff88000ad53700 } hitcount:          5  len:        230
+    { skbaddr: ffff8800d2bcdb00 } hitcount:          5  len:        196
+    { skbaddr: ffff8800a1f90000 } hitcount:          6  len:        276
+    { skbaddr: ffff88006a54f900 } hitcount:          6  len:        276
+
+    Totals:
+        Hits: 81
+        Entries: 42
+        Dropped: 0
+    # event histogram
+    #
+    # trigger info: hist:name=foo:keys=skbaddr.hex:vals=hitcount,len:sort=hitcount:size=2048 [active]
+    #
+
+    { skbaddr: ffff88000ad53500 } hitcount:          1  len:         46
+    { skbaddr: ffff8800af5a1500 } hitcount:          1  len:         76
+    { skbaddr: ffff8800d62a1900 } hitcount:          1  len:         46
+    { skbaddr: ffff8800d2bccb00 } hitcount:          1  len:        468
+    { skbaddr: ffff8800d3c69900 } hitcount:          1  len:         46
+    { skbaddr: ffff88009ff09100 } hitcount:          1  len:         52
+    { skbaddr: ffff88010f13ab00 } hitcount:          1  len:        168
+    { skbaddr: ffff88006a54f400 } hitcount:          1  len:         46
+    { skbaddr: ffff8800d2bcc500 } hitcount:          1  len:        260
+    { skbaddr: ffff880064505000 } hitcount:          1  len:         46
+    { skbaddr: ffff8800baf24e00 } hitcount:          1  len:         32
+    { skbaddr: ffff88009fe0ad00 } hitcount:          1  len:         46
+    { skbaddr: ffff8800d3edff00 } hitcount:          1  len:         44
+    { skbaddr: ffff88009fe0b400 } hitcount:          1  len:        168
+    { skbaddr: ffff8800a1c55a00 } hitcount:          1  len:         40
+    { skbaddr: ffff8800d2bcd100 } hitcount:          1  len:         40
+    { skbaddr: ffff880064505f00 } hitcount:          1  len:        174
+    { skbaddr: ffff8800a8bff200 } hitcount:          1  len:        160
+    { skbaddr: ffff880044e3cc00 } hitcount:          1  len:         76
+    { skbaddr: ffff8800a8bfe700 } hitcount:          1  len:         46
+    { skbaddr: ffff8800d2bcdc00 } hitcount:          1  len:         32
+    { skbaddr: ffff8800a1f64800 } hitcount:          1  len:         46
+    { skbaddr: ffff8800d2bcde00 } hitcount:          1  len:        988
+    { skbaddr: ffff88006a5dea00 } hitcount:          1  len:         46
+    { skbaddr: ffff88002e37a200 } hitcount:          1  len:         44
+    { skbaddr: ffff8800a1f32c00 } hitcount:          2  len:        676
+    { skbaddr: ffff88000ad52600 } hitcount:          2  len:        107
+    { skbaddr: ffff8800a1f91e00 } hitcount:          2  len:         92
+    { skbaddr: ffff8800af5a0200 } hitcount:          2  len:        142
+    { skbaddr: ffff8800d2bcc600 } hitcount:          2  len:        220
+    { skbaddr: ffff8800ba36f500 } hitcount:          2  len:         92
+    { skbaddr: ffff8800d021f800 } hitcount:          2  len:         92
+    { skbaddr: ffff8800a1f33600 } hitcount:          2  len:        675
+    { skbaddr: ffff8800a8bfff00 } hitcount:          3  len:        138
+    { skbaddr: ffff8800d62a1300 } hitcount:          3  len:        138
+    { skbaddr: ffff88002e37a100 } hitcount:          4  len:        184
+    { skbaddr: ffff880064504400 } hitcount:          4  len:        184
+    { skbaddr: ffff8800a8bfec00 } hitcount:          4  len:        184
+    { skbaddr: ffff88000ad53700 } hitcount:          5  len:        230
+    { skbaddr: ffff8800d2bcdb00 } hitcount:          5  len:        196
+    { skbaddr: ffff8800a1f90000 } hitcount:          6  len:        276
+    { skbaddr: ffff88006a54f900 } hitcount:          6  len:        276
+
+    Totals:
+        Hits: 81
+        Entries: 42
+        Dropped: 0
+
+  And here's an example that shows how to combine histogram data from
+  any two events even if they don't share any 'compatible' fields
+  other than 'hitcount' and 'stacktrace'.  These commands create a
+  couple of triggers named 'bar' using those fields:
+
+    # echo 'hist:name=bar:key=stacktrace:val=hitcount' > \
+           /sys/kernel/debug/tracing/events/sched/sched_process_fork/trigger
+    # echo 'hist:name=bar:key=stacktrace:val=hitcount' > \
+          /sys/kernel/debug/tracing/events/net/netif_rx/trigger
+
+  And displaying the output of either shows some interesting if
+  somewhat confusing output:
+
+    # cat /sys/kernel/debug/tracing/events/sched/sched_process_fork/hist
+    # cat /sys/kernel/debug/tracing/events/net/netif_rx/hist
+
+    # event histogram
+    #
+    # trigger info: hist:name=bar:keys=stacktrace:vals=hitcount:sort=hitcount:size=2048 [active]
+    #
+
+    { stacktrace:
+             _do_fork+0x18e/0x330
+             kernel_thread+0x29/0x30
+             kthreadd+0x154/0x1b0
+             ret_from_fork+0x3f/0x70
+    } hitcount:          1
+    { stacktrace:
+             netif_rx_internal+0xb2/0xd0
+             netif_rx_ni+0x20/0x70
+             dev_loopback_xmit+0xaa/0xd0
+             ip_mc_output+0x126/0x240
+             ip_local_out_sk+0x31/0x40
+             igmp_send_report+0x1e9/0x230
+             igmp_timer_expire+0xe9/0x120
+             call_timer_fn+0x39/0xf0
+             run_timer_softirq+0x1e1/0x290
+             __do_softirq+0xfd/0x290
+             irq_exit+0x98/0xb0
+             smp_apic_timer_interrupt+0x4a/0x60
+             apic_timer_interrupt+0x6d/0x80
+             cpuidle_enter+0x17/0x20
+             call_cpuidle+0x3b/0x60
+             cpu_startup_entry+0x22d/0x310
+    } hitcount:          1
+    { stacktrace:
+             netif_rx_internal+0xb2/0xd0
+             netif_rx_ni+0x20/0x70
+             dev_loopback_xmit+0xaa/0xd0
+             ip_mc_output+0x17f/0x240
+             ip_local_out_sk+0x31/0x40
+             ip_send_skb+0x1a/0x50
+             udp_send_skb+0x13e/0x270
+             udp_sendmsg+0x2bf/0x980
+             inet_sendmsg+0x67/0xa0
+             sock_sendmsg+0x38/0x50
+             SYSC_sendto+0xef/0x170
+             SyS_sendto+0xe/0x10
+             entry_SYSCALL_64_fastpath+0x12/0x6a
+    } hitcount:          2
+    { stacktrace:
+             netif_rx_internal+0xb2/0xd0
+             netif_rx+0x1c/0x60
+             loopback_xmit+0x6c/0xb0
+             dev_hard_start_xmit+0x219/0x3a0
+             __dev_queue_xmit+0x415/0x4f0
+             dev_queue_xmit_sk+0x13/0x20
+             ip_finish_output2+0x237/0x340
+             ip_finish_output+0x113/0x1d0
+             ip_output+0x66/0xc0
+             ip_local_out_sk+0x31/0x40
+             ip_send_skb+0x1a/0x50
+             udp_send_skb+0x16d/0x270
+             udp_sendmsg+0x2bf/0x980
+             inet_sendmsg+0x67/0xa0
+             sock_sendmsg+0x38/0x50
+             ___sys_sendmsg+0x14e/0x270
+    } hitcount:         76
+    { stacktrace:
+             netif_rx_internal+0xb2/0xd0
+             netif_rx+0x1c/0x60
+             loopback_xmit+0x6c/0xb0
+             dev_hard_start_xmit+0x219/0x3a0
+             __dev_queue_xmit+0x415/0x4f0
+             dev_queue_xmit_sk+0x13/0x20
+             ip_finish_output2+0x237/0x340
+             ip_finish_output+0x113/0x1d0
+             ip_output+0x66/0xc0
+             ip_local_out_sk+0x31/0x40
+             ip_send_skb+0x1a/0x50
+             udp_send_skb+0x16d/0x270
+             udp_sendmsg+0x2bf/0x980
+             inet_sendmsg+0x67/0xa0
+             sock_sendmsg+0x38/0x50
+             ___sys_sendmsg+0x269/0x270
+    } hitcount:         77
+    { stacktrace:
+             netif_rx_internal+0xb2/0xd0
+             netif_rx+0x1c/0x60
+             loopback_xmit+0x6c/0xb0
+             dev_hard_start_xmit+0x219/0x3a0
+             __dev_queue_xmit+0x415/0x4f0
+             dev_queue_xmit_sk+0x13/0x20
+             ip_finish_output2+0x237/0x340
+             ip_finish_output+0x113/0x1d0
+             ip_output+0x66/0xc0
+             ip_local_out_sk+0x31/0x40
+             ip_send_skb+0x1a/0x50
+             udp_send_skb+0x16d/0x270
+             udp_sendmsg+0x2bf/0x980
+             inet_sendmsg+0x67/0xa0
+             sock_sendmsg+0x38/0x50
+             SYSC_sendto+0xef/0x170
+    } hitcount:         88
+    { stacktrace:
+             _do_fork+0x18e/0x330
+             SyS_clone+0x19/0x20
+             entry_SYSCALL_64_fastpath+0x12/0x6a
+    } hitcount:        244
+
+    Totals:
+        Hits: 489
+        Entries: 7
+        Dropped: 0
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/trace/ftrace.txt linux-libre-4.7-gnu/Documentation/trace/ftrace.txt
--- linux-libre-4.6-gnu/Documentation/trace/ftrace.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/trace/ftrace.txt	2016-07-24 15:23:50.000000000 -0400
@@ -210,6 +210,11 @@ of ftrace. Here is a list of some of the
 	Note, sched_switch and sched_wake_up will also trace events
 	listed in this file.
 
+	To have the PIDs of children of tasks with their PID in this file
+	added on fork, enable the "event-fork" option. That option will also
+	cause the PIDs of tasks to be removed from this file when the task
+	exits.
+
   set_graph_function:
 
 	Set a "trigger" function where tracing should start
@@ -725,16 +730,14 @@ noraw
 nohex
 nobin
 noblock
-nostacktrace
 trace_printk
-noftrace_preempt
 nobranch
 annotate
 nouserstacktrace
 nosym-userobj
 noprintk-msg-only
 context-info
-latency-format
+nolatency-format
 sleep-time
 graph-time
 record-cmd
@@ -742,7 +745,10 @@ overwrite
 nodisable_on_free
 irq-info
 markers
+noevent-fork
 function-trace
+nodisplay-graph
+nostacktrace
 
 To disable one of the options, echo in the option prepended with
 "no".
@@ -796,11 +802,6 @@ Here are the available options:
 
   block - When set, reading trace_pipe will not block when polled.
 
-  stacktrace - This is one of the options that changes the trace
-	       itself. When a trace is recorded, so is the stack
-	       of functions. This allows for back traces of
-	       trace sites.
-
   trace_printk - Can disable trace_printk() from writing into the buffer.
 
   branch - Enable branch tracing with the tracer.
@@ -897,6 +898,10 @@ x494] <- /root/a.out[+0x4a8] <- /lib/lib
   	    When disabled, the trace_marker will error with EINVAL
 	    on write.
 
+  event-fork - When set, tasks with PIDs listed in set_event_pid will have
+	       the PIDs of their children added to set_event_pid when those
+	       tasks fork. Also, when tasks with PIDs in set_event_pid exit,
+	       their PIDs will be removed from the file.
 
   function-trace - The latency tracers will enable function tracing
   	    if this option is enabled (default it is). When
@@ -904,8 +909,17 @@ x494] <- /root/a.out[+0x4a8] <- /lib/lib
 	    functions. This keeps the overhead of the tracer down
 	    when performing latency tests.
 
- Note: Some tracers have their own options. They only appear
-       when the tracer is active.
+  display-graph - When set, the latency tracers (irqsoff, wakeup, etc) will
+	          use function graph tracing instead of function tracing.
+
+  stacktrace - This is one of the options that changes the trace
+	       itself. When a trace is recorded, so is the stack
+	       of functions. This allows for back traces of
+	       trace sites.
+
+ Note: Some tracers have their own options. They only appear in this
+       file when the tracer is active. They always appear in the
+       options directory.
 
 
 
@@ -1562,12 +1576,12 @@ Doing the same with chrt -r 5 and functi
   <idle>-0       3dN.1   12us : menu_hrtimer_cancel <-tick_nohz_idle_exit
   <idle>-0       3dN.1   12us : ktime_get <-tick_nohz_idle_exit
   <idle>-0       3dN.1   12us : tick_do_update_jiffies64 <-tick_nohz_idle_exit
-  <idle>-0       3dN.1   13us : update_cpu_load_nohz <-tick_nohz_idle_exit
-  <idle>-0       3dN.1   13us : _raw_spin_lock <-update_cpu_load_nohz
+  <idle>-0       3dN.1   13us : cpu_load_update_nohz <-tick_nohz_idle_exit
+  <idle>-0       3dN.1   13us : _raw_spin_lock <-cpu_load_update_nohz
   <idle>-0       3dN.1   13us : add_preempt_count <-_raw_spin_lock
-  <idle>-0       3dN.2   13us : __update_cpu_load <-update_cpu_load_nohz
-  <idle>-0       3dN.2   14us : sched_avg_update <-__update_cpu_load
-  <idle>-0       3dN.2   14us : _raw_spin_unlock <-update_cpu_load_nohz
+  <idle>-0       3dN.2   13us : __cpu_load_update <-cpu_load_update_nohz
+  <idle>-0       3dN.2   14us : sched_avg_update <-__cpu_load_update
+  <idle>-0       3dN.2   14us : _raw_spin_unlock <-cpu_load_update_nohz
   <idle>-0       3dN.2   14us : sub_preempt_count <-_raw_spin_unlock
   <idle>-0       3dN.1   15us : calc_load_exit_idle <-tick_nohz_idle_exit
   <idle>-0       3dN.1   15us : touch_softlockup_watchdog <-tick_nohz_idle_exit
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/usb/chipidea.txt linux-libre-4.7-gnu/Documentation/usb/chipidea.txt
--- linux-libre-4.6-gnu/Documentation/usb/chipidea.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/usb/chipidea.txt	2016-07-24 15:23:50.000000000 -0400
@@ -3,14 +3,17 @@
 To show how to demo OTG HNP and SRP functions via sys input files
 with 2 Freescale i.MX6Q sabre SD boards.
 
-1.1 How to enable OTG FSM in menuconfig
+1.1 How to enable OTG FSM
 ---------------------------------------
-Select CONFIG_USB_OTG_FSM, rebuild kernel Image and modules.
-If you want to check some internal variables for otg fsm,
-mount debugfs, there are 2 files which can show otg fsm
-variables and some controller registers value:
+1.1.1 Select CONFIG_USB_OTG_FSM in menuconfig, rebuild kernel
+Image and modules. If you want to check some internal
+variables for otg fsm, mount debugfs, there are 2 files
+which can show otg fsm variables and some controller registers value:
 cat /sys/kernel/debug/ci_hdrc.0/otg
 cat /sys/kernel/debug/ci_hdrc.0/registers
+1.1.2 Add below entries in your dts file for your controller node
+	otg-rev = <0x0200>;
+	adp-disable;
 
 1.2 Test operations
 -------------------
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/video4linux/bttv/Sound-FAQ linux-libre-4.7-gnu/Documentation/video4linux/bttv/Sound-FAQ
--- linux-libre-4.6-gnu/Documentation/video4linux/bttv/Sound-FAQ	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/video4linux/bttv/Sound-FAQ	2016-07-24 15:23:50.000000000 -0400
@@ -55,7 +55,7 @@ receiver chips.  Some boards use the i2c
 to connect the mux chip.
 
 As mentioned above, there is a array which holds the required
-informations for each known board.  You basically have to create a new
+information for each known board.  You basically have to create a new
 line for your board.  The important fields are these two:
 
 struct tvcard
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/video4linux/CARDLIST.cx23885 linux-libre-4.7-gnu/Documentation/video4linux/CARDLIST.cx23885
--- linux-libre-4.6-gnu/Documentation/video4linux/CARDLIST.cx23885	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/video4linux/CARDLIST.cx23885	2016-07-24 15:23:50.000000000 -0400
@@ -52,3 +52,5 @@
  51 -> DVBSky T982                                         [4254:0982]
  52 -> Hauppauge WinTV-HVR5525                             [0070:f038]
  53 -> Hauppauge WinTV Starburst                           [0070:c12a]
+ 54 -> ViewCast 260e                                       [1576:0260]
+ 55 -> ViewCast 460e                                       [1576:0460]
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/video4linux/CARDLIST.em28xx linux-libre-4.7-gnu/Documentation/video4linux/CARDLIST.em28xx
--- linux-libre-4.6-gnu/Documentation/video4linux/CARDLIST.em28xx	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/video4linux/CARDLIST.em28xx	2016-07-24 15:23:50.000000000 -0400
@@ -76,9 +76,9 @@
  75 -> Dikom DK300                              (em2882)
  76 -> KWorld PlusTV 340U or UB435-Q (ATSC)     (em2870)        [1b80:a340]
  77 -> EM2874 Leadership ISDBT                  (em2874)
- 78 -> PCTV nanoStick T2 290e                   (em28174)
+ 78 -> PCTV nanoStick T2 290e                   (em28174)       [2013:024f]
  79 -> Terratec Cinergy H5                      (em2884)        [eb1a:2885,0ccd:10a2,0ccd:10ad,0ccd:10b6]
- 80 -> PCTV DVB-S2 Stick (460e)                 (em28174)
+ 80 -> PCTV DVB-S2 Stick (460e)                 (em28174)       [2013:024c]
  81 -> Hauppauge WinTV HVR 930C                 (em2884)        [2040:1605]
  82 -> Terratec Cinergy HTC Stick               (em2884)        [0ccd:00b2]
  83 -> Honestech Vidbox NW03                    (em2860)        [eb1a:5006]
@@ -90,9 +90,11 @@
  89 -> Delock 61959                             (em2874)        [1b80:e1cc]
  90 -> KWorld USB ATSC TV Stick UB435-Q V2      (em2874)        [1b80:e346]
  91 -> SpeedLink Vicious And Devine Laplace webcam (em2765)        [1ae7:9003,1ae7:9004]
- 92 -> PCTV DVB-S2 Stick (461e)                 (em28178)
+ 92 -> PCTV DVB-S2 Stick (461e)                 (em28178)       [2013:0258]
  93 -> KWorld USB ATSC TV Stick UB435-Q V3      (em2874)        [1b80:e34c]
- 94 -> PCTV tripleStick (292e)                  (em28178)
+ 94 -> PCTV tripleStick (292e)                  (em28178)       [2013:025f,2040:0264]
  95 -> Leadtek VC100                            (em2861)        [0413:6f07]
- 96 -> Terratec Cinergy T2 Stick HD             (em28178)
+ 96 -> Terratec Cinergy T2 Stick HD             (em28178)       [eb1a:8179]
  97 -> Elgato EyeTV Hybrid 2008 INT             (em2884)        [0fd9:0018]
+ 98 -> PLEX PX-BCUD                             (em28178)       [3275:0085]
+ 99 -> Hauppauge WinTV-dualHD DVB               (em28174)       [2040:0265]
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/video4linux/Makefile linux-libre-4.7-gnu/Documentation/video4linux/Makefile
--- linux-libre-4.6-gnu/Documentation/video4linux/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/video4linux/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-obj-$(CONFIG_VIDEO_PCI_SKELETON) := v4l2-pci-skeleton.o
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/video4linux/README.cx88 linux-libre-4.7-gnu/Documentation/video4linux/README.cx88
--- linux-libre-4.6-gnu/Documentation/video4linux/README.cx88	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/video4linux/README.cx88	2016-07-24 15:23:50.000000000 -0400
@@ -50,7 +50,7 @@ the driver.  What to do then?
      cx88-cards.c.  If that worked, mail me your changes as unified
      diff ("diff -u").
  (3) Or you can mail me the config information.  I need at least the
-     following informations to add the card:
+     following information to add the card:
 
      * the PCI Subsystem ID ("0070:3400" from the line above,
        "lspci -v" output is fine too).
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/video4linux/v4l2-framework.txt linux-libre-4.7-gnu/Documentation/video4linux/v4l2-framework.txt
--- linux-libre-4.6-gnu/Documentation/video4linux/v4l2-framework.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/video4linux/v4l2-framework.txt	2016-07-24 15:23:50.000000000 -0400
@@ -35,7 +35,7 @@ need and this same framework should make
 common code into utility functions shared by all drivers.
 
 A good example to look at as a reference is the v4l2-pci-skeleton.c
-source that is available in this directory. It is a skeleton driver for
+source that is available in samples/v4l/. It is a skeleton driver for
 a PCI capture card, and demonstrates how to use the V4L2 driver
 framework. It can be used as a template for real PCI video capture driver.
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/video4linux/v4l2-pci-skeleton.c linux-libre-4.7-gnu/Documentation/video4linux/v4l2-pci-skeleton.c
--- linux-libre-4.6-gnu/Documentation/video4linux/v4l2-pci-skeleton.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/video4linux/v4l2-pci-skeleton.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,923 +0,0 @@
-/*
- * This is a V4L2 PCI Skeleton Driver. It gives an initial skeleton source
- * for use with other PCI drivers.
- *
- * This skeleton PCI driver assumes that the card has an S-Video connector as
- * input 0 and an HDMI connector as input 1.
- *
- * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
- *
- * This program is free software; you may 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.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/kmod.h>
-#include <linux/mutex.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/videodev2.h>
-#include <linux/v4l2-dv-timings.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-dev.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-dv-timings.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-event.h>
-#include <media/videobuf2-v4l2.h>
-#include <media/videobuf2-dma-contig.h>
-
-MODULE_DESCRIPTION("V4L2 PCI Skeleton Driver");
-MODULE_AUTHOR("Hans Verkuil");
-MODULE_LICENSE("GPL v2");
-
-/**
- * struct skeleton - All internal data for one instance of device
- * @pdev: PCI device
- * @v4l2_dev: top-level v4l2 device struct
- * @vdev: video node structure
- * @ctrl_handler: control handler structure
- * @lock: ioctl serialization mutex
- * @std: current SDTV standard
- * @timings: current HDTV timings
- * @format: current pix format
- * @input: current video input (0 = SDTV, 1 = HDTV)
- * @queue: vb2 video capture queue
- * @alloc_ctx: vb2 contiguous DMA context
- * @qlock: spinlock controlling access to buf_list and sequence
- * @buf_list: list of buffers queued for DMA
- * @sequence: frame sequence counter
- */
-struct skeleton {
-	struct pci_dev *pdev;
-	struct v4l2_device v4l2_dev;
-	struct video_device vdev;
-	struct v4l2_ctrl_handler ctrl_handler;
-	struct mutex lock;
-	v4l2_std_id std;
-	struct v4l2_dv_timings timings;
-	struct v4l2_pix_format format;
-	unsigned input;
-
-	struct vb2_queue queue;
-	struct vb2_alloc_ctx *alloc_ctx;
-
-	spinlock_t qlock;
-	struct list_head buf_list;
-	unsigned field;
-	unsigned sequence;
-};
-
-struct skel_buffer {
-	struct vb2_buffer vb;
-	struct list_head list;
-};
-
-static inline struct skel_buffer *to_skel_buffer(struct vb2_buffer *vb2)
-{
-	return container_of(vb2, struct skel_buffer, vb);
-}
-
-static const struct pci_device_id skeleton_pci_tbl[] = {
-	/* { PCI_DEVICE(PCI_VENDOR_ID_, PCI_DEVICE_ID_) }, */
-	{ 0, }
-};
-MODULE_DEVICE_TABLE(pci, skeleton_pci_tbl);
-
-/*
- * HDTV: this structure has the capabilities of the HDTV receiver.
- * It is used to constrain the huge list of possible formats based
- * upon the hardware capabilities.
- */
-static const struct v4l2_dv_timings_cap skel_timings_cap = {
-	.type = V4L2_DV_BT_656_1120,
-	/* keep this initialization for compatibility with GCC < 4.4.6 */
-	.reserved = { 0 },
-	V4L2_INIT_BT_TIMINGS(
-		720, 1920,		/* min/max width */
-		480, 1080,		/* min/max height */
-		27000000, 74250000,	/* min/max pixelclock*/
-		V4L2_DV_BT_STD_CEA861,	/* Supported standards */
-		/* capabilities */
-		V4L2_DV_BT_CAP_INTERLACED | V4L2_DV_BT_CAP_PROGRESSIVE
-	)
-};
-
-/*
- * Supported SDTV standards. This does the same job as skel_timings_cap, but
- * for standard TV formats.
- */
-#define SKEL_TVNORMS V4L2_STD_ALL
-
-/*
- * Interrupt handler: typically interrupts happen after a new frame has been
- * captured. It is the job of the handler to remove the new frame from the
- * internal list and give it back to the vb2 framework, updating the sequence
- * counter, field and timestamp at the same time.
- */
-static irqreturn_t skeleton_irq(int irq, void *dev_id)
-{
-#ifdef TODO
-	struct skeleton *skel = dev_id;
-
-	/* handle interrupt */
-
-	/* Once a new frame has been captured, mark it as done like this: */
-	if (captured_new_frame) {
-		...
-		spin_lock(&skel->qlock);
-		list_del(&new_buf->list);
-		spin_unlock(&skel->qlock);
-		v4l2_get_timestamp(&new_buf->vb.v4l2_buf.timestamp);
-		new_buf->vb.v4l2_buf.sequence = skel->sequence++;
-		new_buf->vb.v4l2_buf.field = skel->field;
-		if (skel->format.field == V4L2_FIELD_ALTERNATE) {
-			if (skel->field == V4L2_FIELD_BOTTOM)
-				skel->field = V4L2_FIELD_TOP;
-			else if (skel->field == V4L2_FIELD_TOP)
-				skel->field = V4L2_FIELD_BOTTOM;
-		}
-		vb2_buffer_done(&new_buf->vb, VB2_BUF_STATE_DONE);
-	}
-#endif
-	return IRQ_HANDLED;
-}
-
-/*
- * Setup the constraints of the queue: besides setting the number of planes
- * per buffer and the size and allocation context of each plane, it also
- * checks if sufficient buffers have been allocated. Usually 3 is a good
- * minimum number: many DMA engines need a minimum of 2 buffers in the
- * queue and you need to have another available for userspace processing.
- */
-static int queue_setup(struct vb2_queue *vq,
-		       unsigned int *nbuffers, unsigned int *nplanes,
-		       unsigned int sizes[], void *alloc_ctxs[])
-{
-	struct skeleton *skel = vb2_get_drv_priv(vq);
-
-	skel->field = skel->format.field;
-	if (skel->field == V4L2_FIELD_ALTERNATE) {
-		/*
-		 * You cannot use read() with FIELD_ALTERNATE since the field
-		 * information (TOP/BOTTOM) cannot be passed back to the user.
-		 */
-		if (vb2_fileio_is_active(vq))
-			return -EINVAL;
-		skel->field = V4L2_FIELD_TOP;
-	}
-
-	if (vq->num_buffers + *nbuffers < 3)
-		*nbuffers = 3 - vq->num_buffers;
-	alloc_ctxs[0] = skel->alloc_ctx;
-
-	if (*nplanes)
-		return sizes[0] < skel->format.sizeimage ? -EINVAL : 0;
-	*nplanes = 1;
-	sizes[0] = skel->format.sizeimage;
-	return 0;
-}
-
-/*
- * Prepare the buffer for queueing to the DMA engine: check and set the
- * payload size.
- */
-static int buffer_prepare(struct vb2_buffer *vb)
-{
-	struct skeleton *skel = vb2_get_drv_priv(vb->vb2_queue);
-	unsigned long size = skel->format.sizeimage;
-
-	if (vb2_plane_size(vb, 0) < size) {
-		dev_err(&skel->pdev->dev, "buffer too small (%lu < %lu)\n",
-			 vb2_plane_size(vb, 0), size);
-		return -EINVAL;
-	}
-
-	vb2_set_plane_payload(vb, 0, size);
-	return 0;
-}
-
-/*
- * Queue this buffer to the DMA engine.
- */
-static void buffer_queue(struct vb2_buffer *vb)
-{
-	struct skeleton *skel = vb2_get_drv_priv(vb->vb2_queue);
-	struct skel_buffer *buf = to_skel_buffer(vb);
-	unsigned long flags;
-
-	spin_lock_irqsave(&skel->qlock, flags);
-	list_add_tail(&buf->list, &skel->buf_list);
-
-	/* TODO: Update any DMA pointers if necessary */
-
-	spin_unlock_irqrestore(&skel->qlock, flags);
-}
-
-static void return_all_buffers(struct skeleton *skel,
-			       enum vb2_buffer_state state)
-{
-	struct skel_buffer *buf, *node;
-	unsigned long flags;
-
-	spin_lock_irqsave(&skel->qlock, flags);
-	list_for_each_entry_safe(buf, node, &skel->buf_list, list) {
-		vb2_buffer_done(&buf->vb, state);
-		list_del(&buf->list);
-	}
-	spin_unlock_irqrestore(&skel->qlock, flags);
-}
-
-/*
- * Start streaming. First check if the minimum number of buffers have been
- * queued. If not, then return -ENOBUFS and the vb2 framework will call
- * this function again the next time a buffer has been queued until enough
- * buffers are available to actually start the DMA engine.
- */
-static int start_streaming(struct vb2_queue *vq, unsigned int count)
-{
-	struct skeleton *skel = vb2_get_drv_priv(vq);
-	int ret = 0;
-
-	skel->sequence = 0;
-
-	/* TODO: start DMA */
-
-	if (ret) {
-		/*
-		 * In case of an error, return all active buffers to the
-		 * QUEUED state
-		 */
-		return_all_buffers(skel, VB2_BUF_STATE_QUEUED);
-	}
-	return ret;
-}
-
-/*
- * Stop the DMA engine. Any remaining buffers in the DMA queue are dequeued
- * and passed on to the vb2 framework marked as STATE_ERROR.
- */
-static void stop_streaming(struct vb2_queue *vq)
-{
-	struct skeleton *skel = vb2_get_drv_priv(vq);
-
-	/* TODO: stop DMA */
-
-	/* Release all active buffers */
-	return_all_buffers(skel, VB2_BUF_STATE_ERROR);
-}
-
-/*
- * The vb2 queue ops. Note that since q->lock is set we can use the standard
- * vb2_ops_wait_prepare/finish helper functions. If q->lock would be NULL,
- * then this driver would have to provide these ops.
- */
-static struct vb2_ops skel_qops = {
-	.queue_setup		= queue_setup,
-	.buf_prepare		= buffer_prepare,
-	.buf_queue		= buffer_queue,
-	.start_streaming	= start_streaming,
-	.stop_streaming		= stop_streaming,
-	.wait_prepare		= vb2_ops_wait_prepare,
-	.wait_finish		= vb2_ops_wait_finish,
-};
-
-/*
- * Required ioctl querycap. Note that the version field is prefilled with
- * the version of the kernel.
- */
-static int skeleton_querycap(struct file *file, void *priv,
-			     struct v4l2_capability *cap)
-{
-	struct skeleton *skel = video_drvdata(file);
-
-	strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
-	strlcpy(cap->card, "V4L2 PCI Skeleton", sizeof(cap->card));
-	snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
-		 pci_name(skel->pdev));
-	cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
-			   V4L2_CAP_STREAMING;
-	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
-	return 0;
-}
-
-/*
- * Helper function to check and correct struct v4l2_pix_format. It's used
- * not only in VIDIOC_TRY/S_FMT, but also elsewhere if changes to the SDTV
- * standard, HDTV timings or the video input would require updating the
- * current format.
- */
-static void skeleton_fill_pix_format(struct skeleton *skel,
-				     struct v4l2_pix_format *pix)
-{
-	pix->pixelformat = V4L2_PIX_FMT_YUYV;
-	if (skel->input == 0) {
-		/* S-Video input */
-		pix->width = 720;
-		pix->height = (skel->std & V4L2_STD_525_60) ? 480 : 576;
-		pix->field = V4L2_FIELD_INTERLACED;
-		pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
-	} else {
-		/* HDMI input */
-		pix->width = skel->timings.bt.width;
-		pix->height = skel->timings.bt.height;
-		if (skel->timings.bt.interlaced) {
-			pix->field = V4L2_FIELD_ALTERNATE;
-			pix->height /= 2;
-		} else {
-			pix->field = V4L2_FIELD_NONE;
-		}
-		pix->colorspace = V4L2_COLORSPACE_REC709;
-	}
-
-	/*
-	 * The YUYV format is four bytes for every two pixels, so bytesperline
-	 * is width * 2.
-	 */
-	pix->bytesperline = pix->width * 2;
-	pix->sizeimage = pix->bytesperline * pix->height;
-	pix->priv = 0;
-}
-
-static int skeleton_try_fmt_vid_cap(struct file *file, void *priv,
-				    struct v4l2_format *f)
-{
-	struct skeleton *skel = video_drvdata(file);
-	struct v4l2_pix_format *pix = &f->fmt.pix;
-
-	/*
-	 * Due to historical reasons providing try_fmt with an unsupported
-	 * pixelformat will return -EINVAL for video receivers. Webcam drivers,
-	 * however, will silently correct the pixelformat. Some video capture
-	 * applications rely on this behavior...
-	 */
-	if (pix->pixelformat != V4L2_PIX_FMT_YUYV)
-		return -EINVAL;
-	skeleton_fill_pix_format(skel, pix);
-	return 0;
-}
-
-static int skeleton_s_fmt_vid_cap(struct file *file, void *priv,
-				  struct v4l2_format *f)
-{
-	struct skeleton *skel = video_drvdata(file);
-	int ret;
-
-	ret = skeleton_try_fmt_vid_cap(file, priv, f);
-	if (ret)
-		return ret;
-
-	/*
-	 * It is not allowed to change the format while buffers for use with
-	 * streaming have already been allocated.
-	 */
-	if (vb2_is_busy(&skel->queue))
-		return -EBUSY;
-
-	/* TODO: change format */
-	skel->format = f->fmt.pix;
-	return 0;
-}
-
-static int skeleton_g_fmt_vid_cap(struct file *file, void *priv,
-				  struct v4l2_format *f)
-{
-	struct skeleton *skel = video_drvdata(file);
-
-	f->fmt.pix = skel->format;
-	return 0;
-}
-
-static int skeleton_enum_fmt_vid_cap(struct file *file, void *priv,
-				     struct v4l2_fmtdesc *f)
-{
-	if (f->index != 0)
-		return -EINVAL;
-
-	f->pixelformat = V4L2_PIX_FMT_YUYV;
-	return 0;
-}
-
-static int skeleton_s_std(struct file *file, void *priv, v4l2_std_id std)
-{
-	struct skeleton *skel = video_drvdata(file);
-
-	/* S_STD is not supported on the HDMI input */
-	if (skel->input)
-		return -ENODATA;
-
-	/*
-	 * No change, so just return. Some applications call S_STD again after
-	 * the buffers for streaming have been set up, so we have to allow for
-	 * this behavior.
-	 */
-	if (std == skel->std)
-		return 0;
-
-	/*
-	 * Changing the standard implies a format change, which is not allowed
-	 * while buffers for use with streaming have already been allocated.
-	 */
-	if (vb2_is_busy(&skel->queue))
-		return -EBUSY;
-
-	/* TODO: handle changing std */
-
-	skel->std = std;
-
-	/* Update the internal format */
-	skeleton_fill_pix_format(skel, &skel->format);
-	return 0;
-}
-
-static int skeleton_g_std(struct file *file, void *priv, v4l2_std_id *std)
-{
-	struct skeleton *skel = video_drvdata(file);
-
-	/* G_STD is not supported on the HDMI input */
-	if (skel->input)
-		return -ENODATA;
-
-	*std = skel->std;
-	return 0;
-}
-
-/*
- * Query the current standard as seen by the hardware. This function shall
- * never actually change the standard, it just detects and reports.
- * The framework will initially set *std to tvnorms (i.e. the set of
- * supported standards by this input), and this function should just AND
- * this value. If there is no signal, then *std should be set to 0.
- */
-static int skeleton_querystd(struct file *file, void *priv, v4l2_std_id *std)
-{
-	struct skeleton *skel = video_drvdata(file);
-
-	/* QUERY_STD is not supported on the HDMI input */
-	if (skel->input)
-		return -ENODATA;
-
-#ifdef TODO
-	/*
-	 * Query currently seen standard. Initial value of *std is
-	 * V4L2_STD_ALL. This function should look something like this:
-	 */
-	get_signal_info();
-	if (no_signal) {
-		*std = 0;
-		return 0;
-	}
-	/* Use signal information to reduce the number of possible standards */
-	if (signal_has_525_lines)
-		*std &= V4L2_STD_525_60;
-	else
-		*std &= V4L2_STD_625_50;
-#endif
-	return 0;
-}
-
-static int skeleton_s_dv_timings(struct file *file, void *_fh,
-				 struct v4l2_dv_timings *timings)
-{
-	struct skeleton *skel = video_drvdata(file);
-
-	/* S_DV_TIMINGS is not supported on the S-Video input */
-	if (skel->input == 0)
-		return -ENODATA;
-
-	/* Quick sanity check */
-	if (!v4l2_valid_dv_timings(timings, &skel_timings_cap, NULL, NULL))
-		return -EINVAL;
-
-	/* Check if the timings are part of the CEA-861 timings. */
-	if (!v4l2_find_dv_timings_cap(timings, &skel_timings_cap,
-				      0, NULL, NULL))
-		return -EINVAL;
-
-	/* Return 0 if the new timings are the same as the current timings. */
-	if (v4l2_match_dv_timings(timings, &skel->timings, 0, false))
-		return 0;
-
-	/*
-	 * Changing the timings implies a format change, which is not allowed
-	 * while buffers for use with streaming have already been allocated.
-	 */
-	if (vb2_is_busy(&skel->queue))
-		return -EBUSY;
-
-	/* TODO: Configure new timings */
-
-	/* Save timings */
-	skel->timings = *timings;
-
-	/* Update the internal format */
-	skeleton_fill_pix_format(skel, &skel->format);
-	return 0;
-}
-
-static int skeleton_g_dv_timings(struct file *file, void *_fh,
-				 struct v4l2_dv_timings *timings)
-{
-	struct skeleton *skel = video_drvdata(file);
-
-	/* G_DV_TIMINGS is not supported on the S-Video input */
-	if (skel->input == 0)
-		return -ENODATA;
-
-	*timings = skel->timings;
-	return 0;
-}
-
-static int skeleton_enum_dv_timings(struct file *file, void *_fh,
-				    struct v4l2_enum_dv_timings *timings)
-{
-	struct skeleton *skel = video_drvdata(file);
-
-	/* ENUM_DV_TIMINGS is not supported on the S-Video input */
-	if (skel->input == 0)
-		return -ENODATA;
-
-	return v4l2_enum_dv_timings_cap(timings, &skel_timings_cap,
-					NULL, NULL);
-}
-
-/*
- * Query the current timings as seen by the hardware. This function shall
- * never actually change the timings, it just detects and reports.
- * If no signal is detected, then return -ENOLINK. If the hardware cannot
- * lock to the signal, then return -ENOLCK. If the signal is out of range
- * of the capabilities of the system (e.g., it is possible that the receiver
- * can lock but that the DMA engine it is connected to cannot handle
- * pixelclocks above a certain frequency), then -ERANGE is returned.
- */
-static int skeleton_query_dv_timings(struct file *file, void *_fh,
-				     struct v4l2_dv_timings *timings)
-{
-	struct skeleton *skel = video_drvdata(file);
-
-	/* QUERY_DV_TIMINGS is not supported on the S-Video input */
-	if (skel->input == 0)
-		return -ENODATA;
-
-#ifdef TODO
-	/*
-	 * Query currently seen timings. This function should look
-	 * something like this:
-	 */
-	detect_timings();
-	if (no_signal)
-		return -ENOLINK;
-	if (cannot_lock_to_signal)
-		return -ENOLCK;
-	if (signal_out_of_range_of_capabilities)
-		return -ERANGE;
-
-	/* Useful for debugging */
-	v4l2_print_dv_timings(skel->v4l2_dev.name, "query_dv_timings:",
-			timings, true);
-#endif
-	return 0;
-}
-
-static int skeleton_dv_timings_cap(struct file *file, void *fh,
-				   struct v4l2_dv_timings_cap *cap)
-{
-	struct skeleton *skel = video_drvdata(file);
-
-	/* DV_TIMINGS_CAP is not supported on the S-Video input */
-	if (skel->input == 0)
-		return -ENODATA;
-	*cap = skel_timings_cap;
-	return 0;
-}
-
-static int skeleton_enum_input(struct file *file, void *priv,
-			       struct v4l2_input *i)
-{
-	if (i->index > 1)
-		return -EINVAL;
-
-	i->type = V4L2_INPUT_TYPE_CAMERA;
-	if (i->index == 0) {
-		i->std = SKEL_TVNORMS;
-		strlcpy(i->name, "S-Video", sizeof(i->name));
-		i->capabilities = V4L2_IN_CAP_STD;
-	} else {
-		i->std = 0;
-		strlcpy(i->name, "HDMI", sizeof(i->name));
-		i->capabilities = V4L2_IN_CAP_DV_TIMINGS;
-	}
-	return 0;
-}
-
-static int skeleton_s_input(struct file *file, void *priv, unsigned int i)
-{
-	struct skeleton *skel = video_drvdata(file);
-
-	if (i > 1)
-		return -EINVAL;
-
-	/*
-	 * Changing the input implies a format change, which is not allowed
-	 * while buffers for use with streaming have already been allocated.
-	 */
-	if (vb2_is_busy(&skel->queue))
-		return -EBUSY;
-
-	skel->input = i;
-	/*
-	 * Update tvnorms. The tvnorms value is used by the core to implement
-	 * VIDIOC_ENUMSTD so it has to be correct. If tvnorms == 0, then
-	 * ENUMSTD will return -ENODATA.
-	 */
-	skel->vdev.tvnorms = i ? 0 : SKEL_TVNORMS;
-
-	/* Update the internal format */
-	skeleton_fill_pix_format(skel, &skel->format);
-	return 0;
-}
-
-static int skeleton_g_input(struct file *file, void *priv, unsigned int *i)
-{
-	struct skeleton *skel = video_drvdata(file);
-
-	*i = skel->input;
-	return 0;
-}
-
-/* The control handler. */
-static int skeleton_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-	/*struct skeleton *skel =
-		container_of(ctrl->handler, struct skeleton, ctrl_handler);*/
-
-	switch (ctrl->id) {
-	case V4L2_CID_BRIGHTNESS:
-		/* TODO: set brightness to ctrl->val */
-		break;
-	case V4L2_CID_CONTRAST:
-		/* TODO: set contrast to ctrl->val */
-		break;
-	case V4L2_CID_SATURATION:
-		/* TODO: set saturation to ctrl->val */
-		break;
-	case V4L2_CID_HUE:
-		/* TODO: set hue to ctrl->val */
-		break;
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-/* ------------------------------------------------------------------
-	File operations for the device
-   ------------------------------------------------------------------*/
-
-static const struct v4l2_ctrl_ops skel_ctrl_ops = {
-	.s_ctrl = skeleton_s_ctrl,
-};
-
-/*
- * The set of all supported ioctls. Note that all the streaming ioctls
- * use the vb2 helper functions that take care of all the locking and
- * that also do ownership tracking (i.e. only the filehandle that requested
- * the buffers can call the streaming ioctls, all other filehandles will
- * receive -EBUSY if they attempt to call the same streaming ioctls).
- *
- * The last three ioctls also use standard helper functions: these implement
- * standard behavior for drivers with controls.
- */
-static const struct v4l2_ioctl_ops skel_ioctl_ops = {
-	.vidioc_querycap = skeleton_querycap,
-	.vidioc_try_fmt_vid_cap = skeleton_try_fmt_vid_cap,
-	.vidioc_s_fmt_vid_cap = skeleton_s_fmt_vid_cap,
-	.vidioc_g_fmt_vid_cap = skeleton_g_fmt_vid_cap,
-	.vidioc_enum_fmt_vid_cap = skeleton_enum_fmt_vid_cap,
-
-	.vidioc_g_std = skeleton_g_std,
-	.vidioc_s_std = skeleton_s_std,
-	.vidioc_querystd = skeleton_querystd,
-
-	.vidioc_s_dv_timings = skeleton_s_dv_timings,
-	.vidioc_g_dv_timings = skeleton_g_dv_timings,
-	.vidioc_enum_dv_timings = skeleton_enum_dv_timings,
-	.vidioc_query_dv_timings = skeleton_query_dv_timings,
-	.vidioc_dv_timings_cap = skeleton_dv_timings_cap,
-
-	.vidioc_enum_input = skeleton_enum_input,
-	.vidioc_g_input = skeleton_g_input,
-	.vidioc_s_input = skeleton_s_input,
-
-	.vidioc_reqbufs = vb2_ioctl_reqbufs,
-	.vidioc_create_bufs = vb2_ioctl_create_bufs,
-	.vidioc_querybuf = vb2_ioctl_querybuf,
-	.vidioc_qbuf = vb2_ioctl_qbuf,
-	.vidioc_dqbuf = vb2_ioctl_dqbuf,
-	.vidioc_expbuf = vb2_ioctl_expbuf,
-	.vidioc_streamon = vb2_ioctl_streamon,
-	.vidioc_streamoff = vb2_ioctl_streamoff,
-
-	.vidioc_log_status = v4l2_ctrl_log_status,
-	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
-	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
-};
-
-/*
- * The set of file operations. Note that all these ops are standard core
- * helper functions.
- */
-static const struct v4l2_file_operations skel_fops = {
-	.owner = THIS_MODULE,
-	.open = v4l2_fh_open,
-	.release = vb2_fop_release,
-	.unlocked_ioctl = video_ioctl2,
-	.read = vb2_fop_read,
-	.mmap = vb2_fop_mmap,
-	.poll = vb2_fop_poll,
-};
-
-/*
- * The initial setup of this device instance. Note that the initial state of
- * the driver should be complete. So the initial format, standard, timings
- * and video input should all be initialized to some reasonable value.
- */
-static int skeleton_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-	/* The initial timings are chosen to be 720p60. */
-	static const struct v4l2_dv_timings timings_def =
-		V4L2_DV_BT_CEA_1280X720P60;
-	struct skeleton *skel;
-	struct video_device *vdev;
-	struct v4l2_ctrl_handler *hdl;
-	struct vb2_queue *q;
-	int ret;
-
-	/* Enable PCI */
-	ret = pci_enable_device(pdev);
-	if (ret)
-		return ret;
-	ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
-	if (ret) {
-		dev_err(&pdev->dev, "no suitable DMA available.\n");
-		goto disable_pci;
-	}
-
-	/* Allocate a new instance */
-	skel = devm_kzalloc(&pdev->dev, sizeof(struct skeleton), GFP_KERNEL);
-	if (!skel)
-		return -ENOMEM;
-
-	/* Allocate the interrupt */
-	ret = devm_request_irq(&pdev->dev, pdev->irq,
-			       skeleton_irq, 0, KBUILD_MODNAME, skel);
-	if (ret) {
-		dev_err(&pdev->dev, "request_irq failed\n");
-		goto disable_pci;
-	}
-	skel->pdev = pdev;
-
-	/* Fill in the initial format-related settings */
-	skel->timings = timings_def;
-	skel->std = V4L2_STD_625_50;
-	skeleton_fill_pix_format(skel, &skel->format);
-
-	/* Initialize the top-level structure */
-	ret = v4l2_device_register(&pdev->dev, &skel->v4l2_dev);
-	if (ret)
-		goto disable_pci;
-
-	mutex_init(&skel->lock);
-
-	/* Add the controls */
-	hdl = &skel->ctrl_handler;
-	v4l2_ctrl_handler_init(hdl, 4);
-	v4l2_ctrl_new_std(hdl, &skel_ctrl_ops,
-			  V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
-	v4l2_ctrl_new_std(hdl, &skel_ctrl_ops,
-			  V4L2_CID_CONTRAST, 0, 255, 1, 16);
-	v4l2_ctrl_new_std(hdl, &skel_ctrl_ops,
-			  V4L2_CID_SATURATION, 0, 255, 1, 127);
-	v4l2_ctrl_new_std(hdl, &skel_ctrl_ops,
-			  V4L2_CID_HUE, -128, 127, 1, 0);
-	if (hdl->error) {
-		ret = hdl->error;
-		goto free_hdl;
-	}
-	skel->v4l2_dev.ctrl_handler = hdl;
-
-	/* Initialize the vb2 queue */
-	q = &skel->queue;
-	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ;
-	q->drv_priv = skel;
-	q->buf_struct_size = sizeof(struct skel_buffer);
-	q->ops = &skel_qops;
-	q->mem_ops = &vb2_dma_contig_memops;
-	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
-	/*
-	 * Assume that this DMA engine needs to have at least two buffers
-	 * available before it can be started. The start_streaming() op
-	 * won't be called until at least this many buffers are queued up.
-	 */
-	q->min_buffers_needed = 2;
-	/*
-	 * The serialization lock for the streaming ioctls. This is the same
-	 * as the main serialization lock, but if some of the non-streaming
-	 * ioctls could take a long time to execute, then you might want to
-	 * have a different lock here to prevent VIDIOC_DQBUF from being
-	 * blocked while waiting for another action to finish. This is
-	 * generally not needed for PCI devices, but USB devices usually do
-	 * want a separate lock here.
-	 */
-	q->lock = &skel->lock;
-	/*
-	 * Since this driver can only do 32-bit DMA we must make sure that
-	 * the vb2 core will allocate the buffers in 32-bit DMA memory.
-	 */
-	q->gfp_flags = GFP_DMA32;
-	ret = vb2_queue_init(q);
-	if (ret)
-		goto free_hdl;
-
-	skel->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
-	if (IS_ERR(skel->alloc_ctx)) {
-		dev_err(&pdev->dev, "Can't allocate buffer context");
-		ret = PTR_ERR(skel->alloc_ctx);
-		goto free_hdl;
-	}
-	INIT_LIST_HEAD(&skel->buf_list);
-	spin_lock_init(&skel->qlock);
-
-	/* Initialize the video_device structure */
-	vdev = &skel->vdev;
-	strlcpy(vdev->name, KBUILD_MODNAME, sizeof(vdev->name));
-	/*
-	 * There is nothing to clean up, so release is set to an empty release
-	 * function. The release callback must be non-NULL.
-	 */
-	vdev->release = video_device_release_empty;
-	vdev->fops = &skel_fops,
-	vdev->ioctl_ops = &skel_ioctl_ops,
-	/*
-	 * The main serialization lock. All ioctls are serialized by this
-	 * lock. Exception: if q->lock is set, then the streaming ioctls
-	 * are serialized by that separate lock.
-	 */
-	vdev->lock = &skel->lock;
-	vdev->queue = q;
-	vdev->v4l2_dev = &skel->v4l2_dev;
-	/* Supported SDTV standards, if any */
-	vdev->tvnorms = SKEL_TVNORMS;
-	video_set_drvdata(vdev, skel);
-
-	ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
-	if (ret)
-		goto free_ctx;
-
-	dev_info(&pdev->dev, "V4L2 PCI Skeleton Driver loaded\n");
-	return 0;
-
-free_ctx:
-	vb2_dma_contig_cleanup_ctx(skel->alloc_ctx);
-free_hdl:
-	v4l2_ctrl_handler_free(&skel->ctrl_handler);
-	v4l2_device_unregister(&skel->v4l2_dev);
-disable_pci:
-	pci_disable_device(pdev);
-	return ret;
-}
-
-static void skeleton_remove(struct pci_dev *pdev)
-{
-	struct v4l2_device *v4l2_dev = pci_get_drvdata(pdev);
-	struct skeleton *skel = container_of(v4l2_dev, struct skeleton, v4l2_dev);
-
-	video_unregister_device(&skel->vdev);
-	v4l2_ctrl_handler_free(&skel->ctrl_handler);
-	vb2_dma_contig_cleanup_ctx(skel->alloc_ctx);
-	v4l2_device_unregister(&skel->v4l2_dev);
-	pci_disable_device(skel->pdev);
-}
-
-static struct pci_driver skeleton_driver = {
-	.name = KBUILD_MODNAME,
-	.probe = skeleton_probe,
-	.remove = skeleton_remove,
-	.id_table = skeleton_pci_tbl,
-};
-
-module_pci_driver(skeleton_driver);
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/video4linux/vivid.txt linux-libre-4.7-gnu/Documentation/video4linux/vivid.txt
--- linux-libre-4.6-gnu/Documentation/video4linux/vivid.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/video4linux/vivid.txt	2016-07-24 15:23:50.000000000 -0400
@@ -294,7 +294,7 @@ the result will be.
 
 These inputs support all combinations of the field setting. Special care has
 been taken to faithfully reproduce how fields are handled for the different
-TV standards. This is particularly noticable when generating a horizontally
+TV standards. This is particularly noticeable when generating a horizontally
 moving image so the temporal effect of using interlaced formats becomes clearly
 visible. For 50 Hz standards the top field is the oldest and the bottom field
 is the newest in time. For 60 Hz standards that is reversed: the bottom field
@@ -313,7 +313,7 @@ will be SMPTE-170M.
 The pixel aspect ratio will depend on the TV standard. The video aspect ratio
 can be selected through the 'Standard Aspect Ratio' Vivid control.
 Choices are '4x3', '16x9' which will give letterboxed widescreen video and
-'16x9 Anomorphic' which will give full screen squashed anamorphic widescreen
+'16x9 Anamorphic' which will give full screen squashed anamorphic widescreen
 video that will need to be scaled accordingly.
 
 The TV 'tuner' supports a frequency range of 44-958 MHz. Channels are available
@@ -862,7 +862,7 @@ RDS Radio Text:
 RDS Stereo:
 RDS Artificial Head:
 RDS Compressed:
-RDS Dymanic PTY:
+RDS Dynamic PTY:
 RDS Traffic Announcement:
 RDS Traffic Program:
 RDS Music: these are all controls that set the RDS data that is transmitted by
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/virtual/kvm/api.txt linux-libre-4.7-gnu/Documentation/virtual/kvm/api.txt
--- linux-libre-4.6-gnu/Documentation/virtual/kvm/api.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/virtual/kvm/api.txt	2016-07-24 15:23:50.000000000 -0400
@@ -199,8 +199,8 @@ Type: vm ioctl
 Parameters: vcpu id (apic id on x86)
 Returns: vcpu fd on success, -1 on error
 
-This API adds a vcpu to a virtual machine.  The vcpu id is a small integer
-in the range [0, max_vcpus).
+This API adds a vcpu to a virtual machine. No more than max_vcpus may be added.
+The vcpu id is an integer in the range [0, max_vcpu_id).
 
 The recommended max_vcpus value can be retrieved using the KVM_CAP_NR_VCPUS of
 the KVM_CHECK_EXTENSION ioctl() at run-time.
@@ -212,6 +212,12 @@ cpus max.
 If the KVM_CAP_MAX_VCPUS does not exist, you should assume that max_vcpus is
 same as the value returned from KVM_CAP_NR_VCPUS.
 
+The maximum possible value for max_vcpu_id can be retrieved using the
+KVM_CAP_MAX_VCPU_ID of the KVM_CHECK_EXTENSION ioctl() at run-time.
+
+If the KVM_CAP_MAX_VCPU_ID does not exist, you should assume that max_vcpu_id
+is the same as the value returned from KVM_CAP_MAX_VCPUS.
+
 On powerpc using book3s_hv mode, the vcpus are mapped onto virtual
 threads in one or more virtual CPU cores.  (This is because the
 hardware requires all the hardware threads in a CPU core to be in the
@@ -3788,6 +3794,14 @@ a KVM_EXIT_IOAPIC_EOI vmexit will be rep
 Fails if VCPU has already been created, or if the irqchip is already in the
 kernel (i.e. KVM_CREATE_IRQCHIP has already been called).
 
+7.6 KVM_CAP_S390_RI
+
+Architectures: s390
+Parameters: none
+
+Allows use of runtime-instrumentation introduced with zEC12 processor.
+Will return -EINVAL if the machine does not support runtime-instrumentation.
+Will return -EBUSY if a VCPU has already been created.
 
 8. Other capabilities.
 ----------------------
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/virtual/kvm/devices/s390_flic.txt linux-libre-4.7-gnu/Documentation/virtual/kvm/devices/s390_flic.txt
--- linux-libre-4.6-gnu/Documentation/virtual/kvm/devices/s390_flic.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/virtual/kvm/devices/s390_flic.txt	2016-07-24 15:23:50.000000000 -0400
@@ -11,6 +11,7 @@ FLIC provides support to
 - add interrupts (KVM_DEV_FLIC_ENQUEUE)
 - inspect currently pending interrupts (KVM_FLIC_GET_ALL_IRQS)
 - purge all pending floating interrupts (KVM_DEV_FLIC_CLEAR_IRQS)
+- purge one pending floating I/O interrupt (KVM_DEV_FLIC_CLEAR_IO_IRQ)
 - enable/disable for the guest transparent async page faults
 - register and modify adapter interrupt sources (KVM_DEV_FLIC_ADAPTER_*)
 
@@ -40,6 +41,11 @@ Groups:
     Simply deletes all elements from the list of currently pending floating
     interrupts.  No interrupts are injected into the guest.
 
+  KVM_DEV_FLIC_CLEAR_IO_IRQ
+    Deletes one (if any) I/O interrupt for a subchannel identified by the
+    subsystem identification word passed via the buffer specified by
+    attr->addr (address) and attr->attr (length).
+
   KVM_DEV_FLIC_APF_ENABLE
     Enables async page faults for the guest. So in case of a major page fault
     the host is allowed to handle this async and continues the guest.
@@ -68,7 +74,7 @@ struct kvm_s390_io_adapter {
 
   KVM_DEV_FLIC_ADAPTER_MODIFY
     Modifies attributes of an existing I/O adapter interrupt source. Takes
-    a kvm_s390_io_adapter_req specifiying the adapter and the operation:
+    a kvm_s390_io_adapter_req specifying the adapter and the operation:
 
 struct kvm_s390_io_adapter_req {
 	__u32 id;
@@ -94,3 +100,9 @@ struct kvm_s390_io_adapter_req {
     KVM_S390_IO_ADAPTER_UNMAP
       release a userspace page for the translated address specified in addr
       from the list of mappings
+
+Note: The KVM_SET_DEVICE_ATTR/KVM_GET_DEVICE_ATTR device ioctls executed on
+FLIC with an unknown group or attribute gives the error code EINVAL (instead of
+ENXIO, as specified in the API documentation). It is not possible to conclude
+that a FLIC operation is unavailable based on the error code resulting from a
+usage attempt.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/vm/hugetlbpage.txt linux-libre-4.7-gnu/Documentation/vm/hugetlbpage.txt
--- linux-libre-4.6-gnu/Documentation/vm/hugetlbpage.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/vm/hugetlbpage.txt	2016-07-24 15:23:50.000000000 -0400
@@ -220,7 +220,7 @@ resulting effect on persistent huge page
    node list of "all" with numactl --interleave or --membind [-m] to achieve
    interleaving over all nodes in the system or cpuset.
 
-4) Any task mempolicy specifed--e.g., using numactl--will be constrained by
+4) Any task mempolicy specified--e.g., using numactl--will be constrained by
    the resource limits of any cpuset in which the task runs.  Thus, there will
    be no way for a task with non-default policy running in a cpuset with a
    subset of the system nodes to allocate huge pages outside the cpuset
@@ -275,10 +275,10 @@ This command mounts a (pseudo) filesyste
 options sets the owner and group of the root of the file system.  By default
 the uid and gid of the current process are taken.  The mode option sets the
 mode of root of file system to value & 01777.  This value is given in octal.
-By default the value 0755 is picked. If the paltform supports multiple huge
+By default the value 0755 is picked. If the platform supports multiple huge
 page sizes, the pagesize option can be used to specify the huge page size and
 associated pool.  pagesize is specified in bytes.  If pagesize is not specified
-the paltform's default huge page size and associated pool will be used. The
+the platform's default huge page size and associated pool will be used. The
 size option sets the maximum value of memory (huge pages) allowed for that
 filesystem (/mnt/huge).  The size option can be specified in bytes, or as a
 percentage of the specified huge page pool (nr_hugepages).  The size is
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/vm/pagemap.txt linux-libre-4.7-gnu/Documentation/vm/pagemap.txt
--- linux-libre-4.6-gnu/Documentation/vm/pagemap.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/vm/pagemap.txt	2016-07-24 15:23:50.000000000 -0400
@@ -62,7 +62,7 @@ There are four components to pagemap:
     14. SWAPBACKED
     15. COMPOUND_HEAD
     16. COMPOUND_TAIL
-    16. HUGE
+    17. HUGE
     18. UNEVICTABLE
     19. HWPOISON
     20. NOPAGE
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/vm/transhuge.txt linux-libre-4.7-gnu/Documentation/vm/transhuge.txt
--- linux-libre-4.6-gnu/Documentation/vm/transhuge.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/vm/transhuge.txt	2016-07-24 15:23:50.000000000 -0400
@@ -340,7 +340,7 @@ unaffected. libhugetlbfs will also work
 
 == Graceful fallback ==
 
-Code walking pagetables but unware about huge pmds can simply call
+Code walking pagetables but unaware about huge pmds can simply call
 split_huge_pmd(vma, pmd, addr) where the pmd is the one returned by
 pmd_offset. It's trivial to make the code transparent hugepage aware
 by just grepping for "pmd_offset" and adding split_huge_pmd where
@@ -394,9 +394,9 @@ hugepage natively. Once finished you can
 Refcounting on THP is mostly consistent with refcounting on other compound
 pages:
 
-  - get_page()/put_page() and GUP operate in head page's ->_count.
+  - get_page()/put_page() and GUP operate in head page's ->_refcount.
 
-  - ->_count in tail pages is always zero: get_page_unless_zero() never
+  - ->_refcount in tail pages is always zero: get_page_unless_zero() never
     succeed on tail pages.
 
   - map/unmap of the pages with PTE entry increment/decrement ->_mapcount
@@ -414,7 +414,7 @@ tracking. The alternative is alter ->_ma
 map/unmap of the whole compound page.
 
 We set PG_double_map when a PMD of the page got split for the first time,
-but still have PMD mapping. The addtional references go away with last
+but still have PMD mapping. The additional references go away with last
 compound_mapcount.
 
 split_huge_page internally has to distribute the refcounts in the head
@@ -426,16 +426,16 @@ requests to split pinned huge page: it e
 sum of mapcount of all sub-pages plus one (split_huge_page caller must
 have reference for head page).
 
-split_huge_page uses migration entries to stabilize page->_count and
+split_huge_page uses migration entries to stabilize page->_refcount and
 page->_mapcount.
 
 We safe against physical memory scanners too: the only legitimate way
 scanner can get reference to a page is get_page_unless_zero().
 
-All tail pages has zero ->_count until atomic_add(). It prevent scanner
-from geting reference to tail page up to the point. After the atomic_add()
-we don't care about ->_count value.  We already known how many references
-with should uncharge from head page.
+All tail pages have zero ->_refcount until atomic_add(). This prevents the
+scanner from getting a reference to the tail page up to that point. After the
+atomic_add() we don't care about the ->_refcount value.  We already known how
+many references should be uncharged from the head page.
 
 For head page get_page_unless_zero() will succeed and we don't mind. It's
 clear where reference should go after split: it will stay on head page.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/vm/z3fold.txt linux-libre-4.7-gnu/Documentation/vm/z3fold.txt
--- linux-libre-4.6-gnu/Documentation/vm/z3fold.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/Documentation/vm/z3fold.txt	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,26 @@
+z3fold
+------
+
+z3fold is a special purpose allocator for storing compressed pages.
+It is designed to store up to three compressed pages per physical page.
+It is a zbud derivative which allows for higher compression
+ratio keeping the simplicity and determinism of its predecessor.
+
+The main differences between z3fold and zbud are:
+* unlike zbud, z3fold allows for up to PAGE_SIZE allocations
+* z3fold can hold up to 3 compressed pages in its page
+* z3fold doesn't export any API itself and is thus intended to be used
+  via the zpool API.
+
+To keep the determinism and simplicity, z3fold, just like zbud, always
+stores an integral number of compressed pages per page, but it can store
+up to 3 pages unlike zbud which can store at most 2. Therefore the
+compression ratio goes to around 2.7x while zbud's one is around 1.7x.
+
+Unlike zbud (but like zsmalloc for that matter) z3fold_alloc() does not
+return a dereferenceable pointer. Instead, it returns an unsigned long
+handle which encodes actual location of the allocated object.
+
+Keeping effective compression ratio close to zsmalloc's, z3fold doesn't
+depend on MMU enabled and provides more predictable reclaim behavior
+which makes it a better fit for small and response-critical systems.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/w1/slaves/w1_therm linux-libre-4.7-gnu/Documentation/w1/slaves/w1_therm
--- linux-libre-4.6-gnu/Documentation/w1/slaves/w1_therm	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/w1/slaves/w1_therm	2016-07-24 15:23:50.000000000 -0400
@@ -33,7 +33,15 @@ temperature conversion at a time.  If no
 powered it would be possible to convert all the devices at the same
 time and then go back to read individual sensors.  That isn't
 currently supported.  The driver also doesn't support reduced
-precision (which would also reduce the conversion time).
+precision (which would also reduce the conversion time) when reading values.
+
+Writing a value between 9 and 12 to the sysfs w1_slave file will change the
+precision of the sensor for the next readings. This value is in (volatile)
+SRAM, so it is reset when the sensor gets power-cycled.
+
+To store the current precision configuration into EEPROM, the value 0
+has to be written to the sysfs w1_slave file. Since the EEPROM has a limited
+amount of writes (>50k), this command should be used wisely.
 
 The module parameter strong_pullup can be set to 0 to disable the
 strong pullup, 1 to enable autodetection or 2 to force strong pullup.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/watchdog/hpwdt.txt linux-libre-4.7-gnu/Documentation/watchdog/hpwdt.txt
--- linux-libre-4.6-gnu/Documentation/watchdog/hpwdt.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/watchdog/hpwdt.txt	2016-07-24 15:23:50.000000000 -0400
@@ -1,64 +1,67 @@
-Last reviewed: 06/02/2009
+Last reviewed: 04/04/2016
 
-                     HP iLO2 NMI Watchdog Driver
-              NMI sourcing for iLO2 based ProLiant Servers
+                     HPE iLO NMI Watchdog Driver
+              NMI sourcing for iLO based ProLiant Servers
                      Documentation and Driver by
-              Thomas Mingarelli <thomas.mingarelli@hp.com>
+              Thomas Mingarelli <thomas.mingarelli@hpe.com>
 
- The HP iLO2 NMI Watchdog driver is a kernel module that provides basic
+ The HPE iLO NMI Watchdog driver is a kernel module that provides basic
  watchdog functionality and the added benefit of NMI sourcing. Both the
  watchdog functionality and the NMI sourcing capability need to be enabled
  by the user. Remember that the two modes are not dependent on one another.
  A user can have the NMI sourcing without the watchdog timer and vice-versa.
+ All references to iLO in this document imply it also works on iLO2 and all
+ subsequent generations.
 
  Watchdog functionality is enabled like any other common watchdog driver. That
  is, an application needs to be started that kicks off the watchdog timer. A
  basic application exists in the Documentation/watchdog/src directory called
  watchdog-test.c. Simply compile the C file and kick it off. If the system
- gets into a bad state and hangs, the HP ProLiant iLO 2 timer register will
+ gets into a bad state and hangs, the HPE ProLiant iLO timer register will
  not be updated in a timely fashion and a hardware system reset (also known as
  an Automatic Server Recovery (ASR)) event will occur.
 
- The hpwdt driver also has four (4) module parameters. They are the following:
+ The hpwdt driver also has three (3) module parameters. They are the following:
 
- soft_margin - allows the user to set the watchdog timer value
- allow_kdump - allows the user to save off a kernel dump image after an NMI
+ soft_margin - allows the user to set the watchdog timer value.
+               Default value is 30 seconds.
+ allow_kdump - allows the user to save off a kernel dump image after an NMI.
+               Default value is 1/ON
  nowayout    - basic watchdog parameter that does not allow the timer to
                be restarted or an impending ASR to be escaped.
- priority    - determines whether or not the hpwdt driver is first on the
-               die_notify list to handle NMIs or last. The default value
-               for this module parameter is 0 or LAST. If the user wants to
-               enable NMI sourcing then reload the hpwdt driver with
-               priority=1 (and boot with nmi_watchdog=0).
+               Default value is set when compiling the kernel. If it is set
+               to "Y", then there is no way of disabling the watchdog once
+               it has been started.
 
  NOTE: More information about watchdog drivers in general, including the ioctl
        interface to /dev/watchdog can be found in
        Documentation/watchdog/watchdog-api.txt and Documentation/IPMI.txt.
 
- The priority parameter was introduced due to other kernel software that relied
- on handling NMIs (like oprofile). Keeping hpwdt's priority at 0 (or LAST)
- enables the users of NMIs for non critical events to be work as expected.
-
  The NMI sourcing capability is disabled by default due to the inability to
  distinguish between "NMI Watchdog Ticks" and "HW generated NMI events" in the
  Linux kernel. What this means is that the hpwdt nmi handler code is called
  each time the NMI signal fires off. This could amount to several thousands of
  NMIs in a matter of seconds. If a user sees the Linux kernel's "dazed and
  confused" message in the logs or if the system gets into a hung state, then
- the hpwdt driver can be reloaded with the "priority" module parameter set
- (priority=1).
+ the hpwdt driver can be reloaded.
 
  1. If the kernel has not been booted with nmi_watchdog turned off then
-    edit /boot/grub/menu.lst and place the nmi_watchdog=0 at the end of the
-    currently booting kernel line.
+    edit and place the nmi_watchdog=0 at the end of the currently booting
+    kernel line. Depending on your Linux distribution and platform setup:
+    For non-UEFI systems
+       /boot/grub/grub.conf   or
+       /boot/grub/menu.lst
+    For UEFI systems
+      /boot/efi/EFI/distroname/grub.conf   or
+      /boot/efi/efi/distroname/elilo.conf
  2. reboot the sever
- 3. Once the system comes up perform a rmmod hpwdt
- 4. insmod /lib/modules/`uname -r`/kernel/drivers/char/watchdog/hpwdt.ko priority=1
+ 3. Once the system comes up perform a modprobe -r hpwdt
+ 4. modprobe /lib/modules/`uname -r`/kernel/drivers/watchdog/hpwdt.ko
 
  Now, the hpwdt can successfully receive and source the NMI and provide a log
- message that details the reason for the NMI (as determined by the HP BIOS).
+ message that details the reason for the NMI (as determined by the HPE BIOS).
 
- Below is a list of NMIs the HP BIOS understands along with the associated
+ Below is a list of NMIs the HPE BIOS understands along with the associated
  code (reason):
 
 	No source found                00h
@@ -92,4 +95,4 @@ Last reviewed: 06/02/2009
 
 
  -- Tom Mingarelli
-    (thomas.mingarelli@hp.com)
+    (thomas.mingarelli@hpe.com)
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/watchdog/watchdog-parameters.txt linux-libre-4.7-gnu/Documentation/watchdog/watchdog-parameters.txt
--- linux-libre-4.6-gnu/Documentation/watchdog/watchdog-parameters.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/watchdog/watchdog-parameters.txt	2016-07-24 15:23:50.000000000 -0400
@@ -86,6 +86,10 @@ nowayout: Watchdog cannot be stopped onc
 davinci_wdt:
 heartbeat: Watchdog heartbeat period in seconds from 1 to 600, default 60
 -------------------------------------------------
+ebc-c384_wdt:
+timeout: Watchdog timeout in seconds. (1<=timeout<=15300, default=60)
+nowayout: Watchdog cannot be stopped once started
+-------------------------------------------------
 ep93xx_wdt:
 nowayout: Watchdog cannot be stopped once started
 timeout: Watchdog timeout in seconds. (1<=timeout<=3600, default=TBD)
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/x86/intel_mpx.txt linux-libre-4.7-gnu/Documentation/x86/intel_mpx.txt
--- linux-libre-4.6-gnu/Documentation/x86/intel_mpx.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/x86/intel_mpx.txt	2016-07-24 15:23:50.000000000 -0400
@@ -45,7 +45,7 @@ is how we expect the compiler, applicati
    MPX-instrumented.
 3) The kernel detects that the CPU has MPX, allows the new prctl() to
    succeed, and notes the location of the bounds directory. Userspace is
-   expected to keep the bounds directory at that locationWe note it
+   expected to keep the bounds directory at that location. We note it
    instead of reading it each time because the 'xsave' operation needed
    to access the bounds directory register is an expensive operation.
 4) If the application needs to spill bounds out of the 4 registers, it
@@ -136,7 +136,7 @@ A: MPX-enabled application will possibly
    If we were to preallocate them for the 128TB of user virtual address
    space, we would need to reserve 512TB+2GB, which is larger than the
    entire virtual address space today. This means they can not be reserved
-   ahead of time. Also, a single process's pre-popualated bounds directory
+   ahead of time. Also, a single process's pre-populated bounds directory
    consumes 2GB of virtual *AND* physical memory. IOW, it's completely
    infeasible to prepopulate bounds directories.
 
@@ -151,7 +151,7 @@ A: This would work if we could hook the
    these calls.
 
 Q: Could a bounds fault be handed to userspace and the tables allocated
-   there in a signal handler intead of in the kernel?
+   there in a signal handler instead of in the kernel?
 A: mmap() is not on the list of safe async handler functions and even
    if mmap() would work it still requires locking or nasty tricks to
    keep track of the allocation state there.
@@ -167,7 +167,7 @@ If a #BR is generated due to a bounds vi
 We need to decode MPX instructions to get violation address and
 set this address into extended struct siginfo.
 
-The _sigfault feild of struct siginfo is extended as follow:
+The _sigfault field of struct siginfo is extended as follow:
 
 87		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
 88		struct {
@@ -240,5 +240,5 @@ them at the same bounds table.
 This is allowed architecturally.  See more information "Intel(R) Architecture
 Instruction Set Extensions Programming Reference" (9.3.4).
 
-However, if users did this, the kernel might be fooled in to unmaping an
+However, if users did this, the kernel might be fooled in to unmapping an
 in-use bounds table since it does not recognize sharing.
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/x86/pat.txt linux-libre-4.7-gnu/Documentation/x86/pat.txt
--- linux-libre-4.6-gnu/Documentation/x86/pat.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/x86/pat.txt	2016-07-24 15:23:50.000000000 -0400
@@ -196,3 +196,35 @@ Another, more verbose way of getting PAT
 "debugpat" boot parameter. With this parameter, various debug messages are
 printed to dmesg log.
 
+PAT Initialization
+------------------
+
+The following table describes how PAT is initialized under various
+configurations. The PAT MSR must be updated by Linux in order to support WC
+and WT attributes. Otherwise, the PAT MSR has the value programmed in it
+by the firmware. Note, Xen enables WC attribute in the PAT MSR for guests.
+
+ MTRR PAT   Call Sequence               PAT State  PAT MSR
+ =========================================================
+ E    E     MTRR -> PAT init            Enabled    OS
+ E    D     MTRR -> PAT init            Disabled    -
+ D    E     MTRR -> PAT disable         Disabled   BIOS
+ D    D     MTRR -> PAT disable         Disabled    -
+ -    np/E  PAT  -> PAT disable         Disabled   BIOS
+ -    np/D  PAT  -> PAT disable         Disabled    -
+ E    !P/E  MTRR -> PAT init            Disabled   BIOS
+ D    !P/E  MTRR -> PAT disable         Disabled   BIOS
+ !M   !P/E  MTRR stub -> PAT disable    Disabled   BIOS
+
+ Legend
+ ------------------------------------------------
+ E         Feature enabled in CPU
+ D	   Feature disabled/unsupported in CPU
+ np	   "nopat" boot option specified
+ !P	   CONFIG_X86_PAT option unset
+ !M	   CONFIG_MTRR option unset
+ Enabled   PAT state set to enabled
+ Disabled  PAT state set to disabled
+ OS        PAT initializes PAT MSR with OS setting
+ BIOS      PAT keeps PAT MSR with BIOS setting
+
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/x86/tlb.txt linux-libre-4.7-gnu/Documentation/x86/tlb.txt
--- linux-libre-4.6-gnu/Documentation/x86/tlb.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/x86/tlb.txt	2016-07-24 15:23:50.000000000 -0400
@@ -5,7 +5,7 @@ memory, it has two choices:
     from areas other than the one we are trying to flush will be
     destroyed and must be refilled later, at some cost.
  2. Use the invlpg instruction to invalidate a single page at a
-    time.  This could potentialy cost many more instructions, but
+    time.  This could potentially cost many more instructions, but
     it is a much more precise operation, causing no collateral
     damage to other TLB entries.
 
@@ -19,7 +19,7 @@ Which method to do depends on a few thin
     work.
  3. The size of the TLB.  The larger the TLB, the more collateral
     damage we do with a full flush.  So, the larger the TLB, the
-    more attrative an individual flush looks.  Data and
+    more attractive an individual flush looks.  Data and
     instructions have separate TLBs, as do different page sizes.
  4. The microarchitecture.  The TLB has become a multi-level
     cache on modern CPUs, and the global flushes have become more
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/x86/x86_64/machinecheck linux-libre-4.7-gnu/Documentation/x86/x86_64/machinecheck
--- linux-libre-4.6-gnu/Documentation/x86/x86_64/machinecheck	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/x86/x86_64/machinecheck	2016-07-24 15:23:50.000000000 -0400
@@ -36,7 +36,7 @@ between all CPUs.
 
 check_interval
 	How often to poll for corrected machine check errors, in seconds
-	(Note output is hexademical). Default 5 minutes.  When the poller
+	(Note output is hexadecimal). Default 5 minutes.  When the poller
 	finds MCEs it triggers an exponential speedup (poll more often) on
 	the polling interval.  When the poller stops finding MCEs, it
 	triggers an exponential backoff (poll less often) on the polling
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/xillybus.txt linux-libre-4.7-gnu/Documentation/xillybus.txt
--- linux-libre-4.6-gnu/Documentation/xillybus.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/xillybus.txt	2016-07-24 15:23:50.000000000 -0400
@@ -215,7 +215,7 @@ in xillybus_core.c as follows:
   choice is a non-zero value, to match standard UNIX behavior.
 
 * synchronous: A non-zero value means that the pipe is synchronous. See
-  Syncronization above.
+  Synchronization above.
 
 * bufsize: Each DMA buffer's size. Always a power of two.
 
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/zh_CN/arm64/booting.txt linux-libre-4.7-gnu/Documentation/zh_CN/arm64/booting.txt
--- linux-libre-4.6-gnu/Documentation/zh_CN/arm64/booting.txt	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/zh_CN/arm64/booting.txt	2016-07-24 15:23:50.000000000 -0400
@@ -8,7 +8,7 @@ or if there is a problem with the transl
 
 M:	Will Deacon <will.deacon@arm.com>
 zh_CN:	Fu Wei <wefu@redhat.com>
-C:	1926e54f115725a9248d0c4c65c22acaf94de4c4
+C:	55f058e7574c3615dea4615573a19bdb258696c6
 ---------------------------------------------------------------------
 Documentation/arm64/booting.txt 的中文翻译
 
@@ -20,7 +20,7 @@ 英文版维护者： Will Deacon <will.
 中文版维护者： 傅炜  Fu Wei <wefu@redhat.com>
 中文版翻译者： 傅炜  Fu Wei <wefu@redhat.com>
 中文版校译者： 傅炜  Fu Wei <wefu@redhat.com>
-本文翻译提交时的 Git 检出点为： 1926e54f115725a9248d0c4c65c22acaf94de4c4
+本文翻译提交时的 Git 检出点为： 55f058e7574c3615dea4615573a19bdb258696c6
 
 以下为正文
 ---------------------------------------------------------------------
@@ -125,18 +125,22 @@ 映像头注释：
 			1 - 4K
 			2 - 16K
 			3 - 64K
-  位 3-63:	保留。
+  位 3:		内核物理位置
+			0 - 2MB 对齐基址应尽量靠近内存起始处，因为
+			    其基址以下的内存无法通过线性映射访问
+			1 - 2MB 对齐基址可以在物理内存的任意位置
+  位 4-63:	保留。
 
 - 当 image_size 为零时，引导装载程序应试图在内核映像末尾之后尽可能
   多地保留空闲内存供内核直接使用。对内存空间的需求量因所选定的内核
   特性而异, 并无实际限制。
 
-内核映像必须被放置在靠近可用系统内存起始的 2MB 对齐为基址的
-text_offset 字节处，并从该处被调用。当前，对 Linux 来说在此基址以下的
-内存是无法使用的，因此强烈建议将系统内存的起始作为这个基址。2MB 对齐
-基址和内核映像起始地址之间的区域对于内核来说没有特殊意义，且可能被
-用于其他目的。
+内核映像必须被放置在任意一个可用系统内存 2MB 对齐基址的 text_offset
+字节处，并从该处被调用。2MB 对齐基址和内核映像起始地址之间的区域对于
+内核来说没有特殊意义，且可能被用于其他目的。
 从映像起始地址算起，最少必须准备 image_size 字节的空闲内存供内核使用。
+注： v4.6 之前的版本无法使用内核映像物理偏移以下的内存，所以当时建议
+将映像尽量放置在靠近系统内存起始的地方。
 
 任何提供给内核的内存（甚至在映像起始地址之前），若未从内核中标记为保留
 (如在设备树（dtb）的 memreserve 区域），都将被认为对内核是可用。
diff -druNp --no-dereference linux-libre-4.6-gnu/Documentation/zh_CN/HOWTO linux-libre-4.7-gnu/Documentation/zh_CN/HOWTO
--- linux-libre-4.6-gnu/Documentation/zh_CN/HOWTO	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/Documentation/zh_CN/HOWTO	2016-07-24 15:23:50.000000000 -0400
@@ -207,7 +207,7 @@ 骤：
   - 每当一个新版本的内核被发布，为期两周的集成窗口将被打开。在这段时间里
     维护者可以向Linus提交大段的修改，通常这些修改已经被放到-mm内核中几个
     星期了。提交大量修改的首选方式是使用git工具（内核的代码版本管理工具
-    ，更多的信息可以在http://git.or.cz/获取），不过使用普通补丁也是可以
+    ，更多的信息可以在http://git-scm.com/获取），不过使用普通补丁也是可以
     的。
   - 两个星期以后-rc1版本内核发布。之后只有不包含可能影响整个内核稳定性的
     新功能的补丁才可能被接受。请注意一个全新的驱动程序（或者文件系统）有
@@ -218,8 +218,6 @@ 骤：
     时，一个新的-rc版本就会被发布。计划是每周都发布新的-rc版本。
   - 这个过程一直持续下去直到内核被认为达到足够稳定的状态，持续时间大概是
     6个星期。
-  - 以下地址跟踪了在每个-rc发布中发现的退步列表：
-    http://kernelnewbies.org/known_regressions
 
 关于内核发布，值得一提的是Andrew Morton在linux-kernel邮件列表中如是说：
 	“没有人知道新内核何时会被发布，因为发布是根据已知bug的情况来决定
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpi_amba.c linux-libre-4.7-gnu/drivers/acpi/acpi_amba.c
--- linux-libre-4.6-gnu/drivers/acpi/acpi_amba.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpi_amba.c	2016-07-24 15:23:50.000000000 -0400
@@ -35,8 +35,7 @@ static void amba_register_dummy_clk(void
 	if (amba_dummy_clk)
 		return;
 
-	amba_dummy_clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL,
-						CLK_IS_ROOT, 0);
+	amba_dummy_clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, 0, 0);
 	clk_register_clkdev(amba_dummy_clk, "apb_pclk", NULL);
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpi_apd.c linux-libre-4.7-gnu/drivers/acpi/acpi_apd.c
--- linux-libre-4.6-gnu/drivers/acpi/acpi_apd.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpi_apd.c	2016-07-24 15:23:50.000000000 -0400
@@ -62,8 +62,7 @@ static int acpi_apd_setup(struct apd_pri
 	if (dev_desc->fixed_clk_rate) {
 		clk = clk_register_fixed_rate(&pdata->adev->dev,
 					dev_name(&pdata->adev->dev),
-					NULL, CLK_IS_ROOT,
-					dev_desc->fixed_clk_rate);
+					NULL, 0, dev_desc->fixed_clk_rate);
 		clk_register_clkdev(clk, NULL, dev_name(&pdata->adev->dev));
 		pdata->clk = clk;
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/acdebug.h linux-libre-4.7-gnu/drivers/acpi/acpica/acdebug.h
--- linux-libre-4.6-gnu/drivers/acpi/acpica/acdebug.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/acdebug.h	2016-07-24 15:23:50.000000000 -0400
@@ -53,7 +53,7 @@
 #define ACPI_DEBUG_BUFFER_SIZE  0x4000	/* 16K buffer for return objects */
 
 struct acpi_db_command_info {
-	char *name;		/* Command Name */
+	const char *name;	/* Command Name */
 	u8 min_args;		/* Minimum arguments required */
 };
 
@@ -64,7 +64,7 @@ struct acpi_db_command_help {
 };
 
 struct acpi_db_argument_info {
-	char *name;		/* Argument Name */
+	const char *name;	/* Argument Name */
 };
 
 struct acpi_db_execute_walk {
@@ -196,7 +196,7 @@ ACPI_DBR_DEPENDENT_RETURN_VOID(void
 							     acpi_walk_state
 							     *walk_state))
 
- acpi_status acpi_db_display_all_methods(char *display_count_arg);
+acpi_status acpi_db_display_all_methods(char *display_count_arg);
 
 void acpi_db_display_arguments(void);
 
@@ -220,7 +220,7 @@ ACPI_DBR_DEPENDENT_RETURN_VOID(void
  * dbexec - debugger control method execution
  */
 void
-acpi_db_execute(char *name, char **args, acpi_object_type * types, u32 flags);
+acpi_db_execute(char *name, char **args, acpi_object_type *types, u32 flags);
 
 void
 acpi_db_create_execution_threads(char *num_threads_arg,
@@ -271,7 +271,7 @@ void ACPI_SYSTEM_XFACE acpi_db_execute_t
 acpi_status acpi_db_user_commands(void);
 
 char *acpi_db_get_next_token(char *string,
-			     char **next, acpi_object_type * return_type);
+			     char **next, acpi_object_type *return_type);
 
 /*
  * dbobject
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/acevents.h linux-libre-4.7-gnu/drivers/acpi/acpica/acevents.h
--- linux-libre-4.6-gnu/drivers/acpi/acpica/acevents.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/acevents.h	2016-07-24 15:23:50.000000000 -0400
@@ -72,6 +72,7 @@ acpi_status acpi_ev_init_global_lock_han
 ACPI_HW_DEPENDENT_RETURN_OK(acpi_status
 			    acpi_ev_acquire_global_lock(u16 timeout))
 ACPI_HW_DEPENDENT_RETURN_OK(acpi_status acpi_ev_release_global_lock(void))
+
 acpi_status acpi_ev_remove_global_lock_handler(void);
 
 /*
@@ -198,8 +199,6 @@ void
 acpi_ev_detach_region(union acpi_operand_object *region_obj,
 		      u8 acpi_ns_is_locked);
 
-void acpi_ev_associate_reg_method(union acpi_operand_object *region_obj);
-
 void
 acpi_ev_execute_reg_methods(struct acpi_namespace_node *node,
 			    acpi_adr_space_type space_id, u32 function);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/acglobal.h linux-libre-4.7-gnu/drivers/acpi/acpica/acglobal.h
--- linux-libre-4.6-gnu/drivers/acpi/acpica/acglobal.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/acglobal.h	2016-07-24 15:23:50.000000000 -0400
@@ -187,6 +187,8 @@ extern const char *acpi_gbl_sleep_state_
 extern const char *acpi_gbl_lowest_dstate_names[ACPI_NUM_sx_w_METHODS];
 extern const char *acpi_gbl_highest_dstate_names[ACPI_NUM_sx_d_METHODS];
 extern const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS];
+extern const char acpi_gbl_lower_hex_digits[];
+extern const char acpi_gbl_upper_hex_digits[];
 extern const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES];
 
 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
@@ -361,6 +363,15 @@ ACPI_GLOBAL(u32, acpi_gbl_num_objects);
 
 #endif				/* ACPI_DEBUGGER */
 
+#if defined (ACPI_DISASSEMBLER) || defined (ACPI_ASL_COMPILER)
+
+ACPI_GLOBAL(const char, *acpi_gbl_pld_panel_list[]);
+ACPI_GLOBAL(const char, *acpi_gbl_pld_vertical_position_list[]);
+ACPI_GLOBAL(const char, *acpi_gbl_pld_horizontal_position_list[]);
+ACPI_GLOBAL(const char, *acpi_gbl_pld_shape_list[]);
+
+#endif
+
 /*****************************************************************************
  *
  * Application globals
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/acinterp.h linux-libre-4.7-gnu/drivers/acpi/acpica/acinterp.h
--- linux-libre-4.6-gnu/drivers/acpi/acpica/acinterp.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/acinterp.h	2016-07-24 15:23:50.000000000 -0400
@@ -67,7 +67,7 @@
 typedef const struct acpi_exdump_info {
 	u8 opcode;
 	u8 offset;
-	char *name;
+	const char *name;
 
 } acpi_exdump_info;
 
@@ -370,7 +370,7 @@ acpi_ex_resolve_to_value(union acpi_oper
 acpi_status
 acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
 			 union acpi_operand_object *operand,
-			 acpi_object_type * return_type,
+			 acpi_object_type *return_type,
 			 union acpi_operand_object **return_desc);
 
 /*
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/aclocal.h linux-libre-4.7-gnu/drivers/acpi/acpica/aclocal.h
--- linux-libre-4.6-gnu/drivers/acpi/acpica/aclocal.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/aclocal.h	2016-07-24 15:23:50.000000000 -0400
@@ -278,7 +278,7 @@ struct acpi_create_field_info {
 };
 
 typedef
-acpi_status(*acpi_internal_method) (struct acpi_walk_state * walk_state);
+acpi_status (*acpi_internal_method) (struct acpi_walk_state * walk_state);
 
 /*
  * Bitmapped ACPI types. Used internally only
@@ -395,11 +395,12 @@ union acpi_predefined_info {
 
 /* Return object auto-repair info */
 
-typedef acpi_status(*acpi_object_converter) (struct acpi_namespace_node * scope,
-					     union acpi_operand_object
-					     *original_object,
-					     union acpi_operand_object
-					     **converted_object);
+typedef acpi_status (*acpi_object_converter) (struct acpi_namespace_node *
+					      scope,
+					      union acpi_operand_object *
+					      original_object,
+					      union acpi_operand_object **
+					      converted_object);
 
 struct acpi_simple_repair_info {
 	char name[ACPI_NAME_SIZE];
@@ -539,10 +540,10 @@ struct acpi_gpe_device_info {
 	struct acpi_namespace_node *gpe_device;
 };
 
-typedef acpi_status(*acpi_gpe_callback) (struct acpi_gpe_xrupt_info *
-					 gpe_xrupt_info,
-					 struct acpi_gpe_block_info *gpe_block,
-					 void *context);
+typedef acpi_status (*acpi_gpe_callback) (struct acpi_gpe_xrupt_info *
+					  gpe_xrupt_info,
+					  struct acpi_gpe_block_info *
+					  gpe_block, void *context);
 
 /* Information about each particular fixed event */
 
@@ -657,10 +658,11 @@ struct acpi_result_values {
 };
 
 typedef
-acpi_status(*acpi_parse_downwards) (struct acpi_walk_state * walk_state,
-				    union acpi_parse_object ** out_op);
+acpi_status (*acpi_parse_downwards) (struct acpi_walk_state * walk_state,
+				     union acpi_parse_object ** out_op);
 
-typedef acpi_status(*acpi_parse_upwards) (struct acpi_walk_state * walk_state);
+typedef
+acpi_status (*acpi_parse_upwards) (struct acpi_walk_state * walk_state);
 
 /* Global handlers for AML Notifies */
 
@@ -700,7 +702,8 @@ union acpi_generic_state {
  *
  ****************************************************************************/
 
-typedef acpi_status(*acpi_execute_op) (struct acpi_walk_state * walk_state);
+typedef
+acpi_status (*acpi_execute_op) (struct acpi_walk_state * walk_state);
 
 /* Address Range info block */
 
@@ -853,24 +856,24 @@ struct acpi_parse_state {
 
 /* Parse object flags */
 
-#define ACPI_PARSEOP_GENERIC            0x01
-#define ACPI_PARSEOP_NAMED              0x02
-#define ACPI_PARSEOP_DEFERRED           0x04
-#define ACPI_PARSEOP_BYTELIST           0x08
-#define ACPI_PARSEOP_IN_STACK           0x10
-#define ACPI_PARSEOP_TARGET             0x20
-#define ACPI_PARSEOP_IN_CACHE           0x80
+#define ACPI_PARSEOP_GENERIC                0x01
+#define ACPI_PARSEOP_NAMED_OBJECT           0x02
+#define ACPI_PARSEOP_DEFERRED               0x04
+#define ACPI_PARSEOP_BYTELIST               0x08
+#define ACPI_PARSEOP_IN_STACK               0x10
+#define ACPI_PARSEOP_TARGET                 0x20
+#define ACPI_PARSEOP_IN_CACHE               0x80
 
 /* Parse object disasm_flags */
 
-#define ACPI_PARSEOP_IGNORE             0x01
-#define ACPI_PARSEOP_PARAMLIST          0x02
-#define ACPI_PARSEOP_EMPTY_TERMLIST     0x04
-#define ACPI_PARSEOP_PREDEF_CHECKED     0x08
-#define ACPI_PARSEOP_CLOSING_PAREN      0x10
-#define ACPI_PARSEOP_COMPOUND           0x20
-#define ACPI_PARSEOP_ASSIGNMENT         0x40
-#define ACPI_PARSEOP_ELSEIF             0x80
+#define ACPI_PARSEOP_IGNORE                 0x01
+#define ACPI_PARSEOP_PARAMETER_LIST         0x02
+#define ACPI_PARSEOP_EMPTY_TERMLIST         0x04
+#define ACPI_PARSEOP_PREDEFINED_CHECKED     0x08
+#define ACPI_PARSEOP_CLOSING_PAREN          0x10
+#define ACPI_PARSEOP_COMPOUND_ASSIGNMENT    0x20
+#define ACPI_PARSEOP_ASSIGNMENT             0x40
+#define ACPI_PARSEOP_ELSEIF                 0x80
 
 /*****************************************************************************
  *
@@ -1096,6 +1099,7 @@ struct acpi_external_list {
 #define ACPI_EXT_ORIGIN_FROM_FILE           0x02	/* External came from a file */
 #define ACPI_EXT_INTERNAL_PATH_ALLOCATED    0x04	/* Deallocate internal path on completion */
 #define ACPI_EXT_EXTERNAL_EMITTED           0x08	/* External() statement has been emitted */
+#define ACPI_EXT_ORIGIN_FROM_OPCODE         0x10	/* External came from a External() opcode */
 
 struct acpi_external_file {
 	char *path;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/acmacros.h linux-libre-4.7-gnu/drivers/acpi/acpica/acmacros.h
--- linux-libre-4.6-gnu/drivers/acpi/acpica/acmacros.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/acmacros.h	2016-07-24 15:23:50.000000000 -0400
@@ -260,14 +260,31 @@
 
 #define ACPI_IS_MISALIGNED(value)           (((acpi_size) value) & (sizeof(acpi_size)-1))
 
+/* Generic (power-of-two) rounding */
+
+#define ACPI_IS_ALIGNED(a, s)               (((a) & ((s) - 1)) == 0)
+#define ACPI_IS_POWER_OF_TWO(a)             ACPI_IS_ALIGNED(a, a)
+
 /*
  * Bitmask creation
  * Bit positions start at zero.
  * MASK_BITS_ABOVE creates a mask starting AT the position and above
  * MASK_BITS_BELOW creates a mask starting one bit BELOW the position
+ * MASK_BITS_ABOVE/BELOW accpets a bit offset to create a mask
+ * MASK_BITS_ABOVE/BELOW_32/64 accpets a bit width to create a mask
+ * Note: The ACPI_INTEGER_BIT_SIZE check is used to bypass compiler
+ * differences with the shift operator
  */
 #define ACPI_MASK_BITS_ABOVE(position)      (~((ACPI_UINT64_MAX) << ((u32) (position))))
 #define ACPI_MASK_BITS_BELOW(position)      ((ACPI_UINT64_MAX) << ((u32) (position)))
+#define ACPI_MASK_BITS_ABOVE_32(width)      ((u32) ACPI_MASK_BITS_ABOVE(width))
+#define ACPI_MASK_BITS_BELOW_32(width)      ((u32) ACPI_MASK_BITS_BELOW(width))
+#define ACPI_MASK_BITS_ABOVE_64(width)      ((width) == ACPI_INTEGER_BIT_SIZE ? \
+												ACPI_UINT64_MAX : \
+												ACPI_MASK_BITS_ABOVE(width))
+#define ACPI_MASK_BITS_BELOW_64(width)      ((width) == ACPI_INTEGER_BIT_SIZE ? \
+												(u64) 0 : \
+												ACPI_MASK_BITS_BELOW(width))
 
 /* Bitfields within ACPI registers */
 
@@ -283,10 +300,10 @@
 /* Generic bitfield macros and masks */
 
 #define ACPI_GET_BITS(source_ptr, position, mask) \
-	((*source_ptr >> position) & mask)
+	((*(source_ptr) >> (position)) & (mask))
 
 #define ACPI_SET_BITS(target_ptr, position, mask, value) \
-	(*target_ptr |= ((value & mask) << position))
+	(*(target_ptr) |= (((value) & (mask)) << (position)))
 
 #define ACPI_1BIT_MASK      0x00000001
 #define ACPI_2BIT_MASK      0x00000003
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/acnamesp.h linux-libre-4.7-gnu/drivers/acpi/acpica/acnamesp.h
--- linux-libre-4.6-gnu/drivers/acpi/acpica/acnamesp.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/acnamesp.h	2016-07-24 15:23:50.000000000 -0400
@@ -206,9 +206,10 @@ void acpi_ns_dump_tables(acpi_handle sea
 void acpi_ns_dump_entry(acpi_handle handle, u32 debug_level);
 
 void
-acpi_ns_dump_pathname(acpi_handle handle, char *msg, u32 level, u32 component);
+acpi_ns_dump_pathname(acpi_handle handle,
+		      const char *msg, u32 level, u32 component);
 
-void acpi_ns_print_pathname(u32 num_segments, char *pathname);
+void acpi_ns_print_pathname(u32 num_segments, const char *pathname);
 
 acpi_status
 acpi_ns_dump_one_object(acpi_handle obj_handle,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/acparser.h linux-libre-4.7-gnu/drivers/acpi/acpica/acparser.h
--- linux-libre-4.6-gnu/drivers/acpi/acpica/acparser.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/acparser.h	2016-07-24 15:23:50.000000000 -0400
@@ -139,7 +139,7 @@ acpi_ps_complete_final_op(struct acpi_wa
  */
 const struct acpi_opcode_info *acpi_ps_get_opcode_info(u16 opcode);
 
-char *acpi_ps_get_opcode_name(u16 opcode);
+const char *acpi_ps_get_opcode_name(u16 opcode);
 
 u8 acpi_ps_get_argument_count(u32 op_type);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/acpredef.h linux-libre-4.7-gnu/drivers/acpi/acpica/acpredef.h
--- linux-libre-4.6-gnu/drivers/acpi/acpica/acpredef.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/acpredef.h	2016-07-24 15:23:50.000000000 -0400
@@ -129,7 +129,8 @@ enum acpi_return_package_types {
 	ACPI_PTYPE2_REV_FIXED = 9,
 	ACPI_PTYPE2_FIX_VAR = 10,
 	ACPI_PTYPE2_VAR_VAR = 11,
-	ACPI_PTYPE2_UUID_PAIR = 12
+	ACPI_PTYPE2_UUID_PAIR = 12,
+	ACPI_PTYPE_CUSTOM = 13
 };
 
 /* Support macros for users of the predefined info table */
@@ -340,7 +341,7 @@ const union acpi_predefined_info acpi_gb
 
 	{{"_BIX", METHOD_0ARGS,
 	  METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}},	/* Fixed-length (16 Int),(4 Str) */
-	PACKAGE_INFO(ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 16,
+	PACKAGE_INFO(ACPI_PTYPE_CUSTOM, ACPI_RTYPE_INTEGER, 16,
 		     ACPI_RTYPE_STRING, 4, 0),
 
 	{{"_BLT",
@@ -523,6 +524,9 @@ const union acpi_predefined_info acpi_gb
 	  METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}},	/* Fixed-length (4 Int) */
 	PACKAGE_INFO(ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4, 0, 0, 0),
 
+	{{"_FIT", METHOD_0ARGS,
+	  METHOD_RETURNS(ACPI_RTYPE_BUFFER)}},	/* ACPI 6.0 */
+
 	{{"_FIX", METHOD_0ARGS,
 	  METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}},	/* Variable-length (Ints) */
 	PACKAGE_INFO(ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 0, 0, 0, 0),
@@ -1053,6 +1057,12 @@ const union acpi_predefined_info acpi_gb
 	  METHOD_RETURNS(ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING |
 			 ACPI_RTYPE_BUFFER)}},
 
+	{{"_WPC", METHOD_0ARGS,
+	  METHOD_RETURNS(ACPI_RTYPE_INTEGER)}},	/* ACPI 6.1 */
+
+	{{"_WPP", METHOD_0ARGS,
+	  METHOD_RETURNS(ACPI_RTYPE_INTEGER)}},	/* ACPI 6.1 */
+
 	PACKAGE_INFO(0, 0, 0, 0, 0, 0)	/* Table terminator */
 };
 #else
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/acresrc.h linux-libre-4.7-gnu/drivers/acpi/acpica/acresrc.h
--- linux-libre-4.6-gnu/drivers/acpi/acpica/acresrc.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/acresrc.h	2016-07-24 15:23:50.000000000 -0400
@@ -124,7 +124,7 @@ typedef enum {
 typedef const struct acpi_rsdump_info {
 	u8 opcode;
 	u8 offset;
-	char *name;
+	const char *name;
 	const char **pointer;
 
 } acpi_rsdump_info;
@@ -209,7 +209,7 @@ acpi_rs_get_prs_method_data(struct acpi_
 
 acpi_status
 acpi_rs_get_method_data(acpi_handle handle,
-			char *path, struct acpi_buffer *ret_buffer);
+			const char *path, struct acpi_buffer *ret_buffer);
 
 acpi_status
 acpi_rs_set_srs_method_data(struct acpi_namespace_node *node,
@@ -223,16 +223,16 @@ acpi_rs_get_aei_method_data(struct acpi_
  * rscalc
  */
 acpi_status
-acpi_rs_get_list_length(u8 * aml_buffer,
-			u32 aml_buffer_length, acpi_size * size_needed);
+acpi_rs_get_list_length(u8 *aml_buffer,
+			u32 aml_buffer_length, acpi_size *size_needed);
 
 acpi_status
 acpi_rs_get_aml_length(struct acpi_resource *resource_list,
-		       acpi_size resource_list_size, acpi_size * size_needed);
+		       acpi_size resource_list_size, acpi_size *size_needed);
 
 acpi_status
 acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object,
-				     acpi_size * buffer_size_needed);
+				     acpi_size *buffer_size_needed);
 
 acpi_status
 acpi_rs_convert_aml_to_resources(u8 * aml,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/acstruct.h linux-libre-4.7-gnu/drivers/acpi/acpica/acstruct.h
--- linux-libre-4.6-gnu/drivers/acpi/acpica/acstruct.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/acstruct.h	2016-07-24 15:23:50.000000000 -0400
@@ -184,7 +184,7 @@ struct acpi_evaluate_info {
 	/* The first 3 elements are passed by the caller to acpi_ns_evaluate */
 
 	struct acpi_namespace_node *prefix_node;	/* Input: starting node */
-	char *relative_pathname;	/* Input: path relative to prefix_node */
+	const char *relative_pathname;	/* Input: path relative to prefix_node */
 	union acpi_operand_object **parameters;	/* Input: argument list */
 
 	struct acpi_namespace_node *node;	/* Resolved node (prefix_node:relative_pathname) */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/actables.h linux-libre-4.7-gnu/drivers/acpi/acpica/actables.h
--- linux-libre-4.6-gnu/drivers/acpi/acpica/actables.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/actables.h	2016-07-24 15:23:50.000000000 -0400
@@ -161,8 +161,6 @@ acpi_tb_install_fixed_table(acpi_physica
 
 acpi_status acpi_tb_parse_root_table(acpi_physical_address rsdp_address);
 
-u8 acpi_is_valid_signature(char *signature);
-
 /*
  * tbxfload
  */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/acutils.h linux-libre-4.7-gnu/drivers/acpi/acpica/acutils.h
--- linux-libre-4.6-gnu/drivers/acpi/acpica/acutils.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/acutils.h	2016-07-24 15:23:50.000000000 -0400
@@ -136,16 +136,16 @@ extern const char *acpi_gbl_pt_decode[];
 #define ACPI_SMALL_VARIABLE_LENGTH      3
 
 typedef
-acpi_status(*acpi_walk_aml_callback) (u8 *aml,
-				      u32 length,
-				      u32 offset,
-				      u8 resource_index, void **context);
+acpi_status (*acpi_walk_aml_callback) (u8 *aml,
+				       u32 length,
+				       u32 offset,
+				       u8 resource_index, void **context);
 
 typedef
-acpi_status(*acpi_pkg_callback) (u8 object_type,
-				 union acpi_operand_object *source_object,
-				 union acpi_generic_state * state,
-				 void *context);
+acpi_status (*acpi_pkg_callback) (u8 object_type,
+				  union acpi_operand_object * source_object,
+				  union acpi_generic_state * state,
+				  void *context);
 
 struct acpi_pkg_info {
 	u8 *free_space;
@@ -167,6 +167,15 @@ struct acpi_pkg_info {
 #define DB_QWORD_DISPLAY    8
 
 /*
+ * utascii - ASCII utilities
+ */
+u8 acpi_ut_valid_nameseg(char *signature);
+
+u8 acpi_ut_valid_name_char(char character, u32 position);
+
+void acpi_ut_check_and_repair_ascii(u8 *name, char *repaired_name, u32 count);
+
+/*
  * utnonansi - Non-ANSI C library functions
  */
 void acpi_ut_strupr(char *src_string);
@@ -175,7 +184,14 @@ void acpi_ut_strlwr(char *src_string);
 
 int acpi_ut_stricmp(char *string1, char *string2);
 
-acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer);
+acpi_status
+acpi_ut_strtoul64(char *string,
+		  u32 base, u32 max_integer_byte_width, u64 *ret_integer);
+
+/* Values for max_integer_byte_width above */
+
+#define ACPI_MAX32_BYTE_WIDTH       4
+#define ACPI_MAX64_BYTE_WIDTH       8
 
 /*
  * utglobal - Global data structures and procedures
@@ -266,7 +282,8 @@ acpi_ut_trace(u32 line_number,
 void
 acpi_ut_trace_ptr(u32 line_number,
 		  const char *function_name,
-		  const char *module_name, u32 component_id, void *pointer);
+		  const char *module_name,
+		  u32 component_id, const void *pointer);
 
 void
 acpi_ut_trace_u32(u32 line_number,
@@ -276,7 +293,8 @@ acpi_ut_trace_u32(u32 line_number,
 void
 acpi_ut_trace_str(u32 line_number,
 		  const char *function_name,
-		  const char *module_name, u32 component_id, char *string);
+		  const char *module_name,
+		  u32 component_id, const char *string);
 
 void
 acpi_ut_exit(u32 line_number,
@@ -335,12 +353,12 @@ void acpi_ut_delete_internal_object_list
  */
 acpi_status
 acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node,
-			char *path,
+			const char *path,
 			u32 expected_return_btypes,
 			union acpi_operand_object **return_desc);
 
 acpi_status
-acpi_ut_evaluate_numeric_object(char *object_name,
+acpi_ut_evaluate_numeric_object(const char *object_name,
 				struct acpi_namespace_node *device_node,
 				u64 *value);
 
@@ -415,7 +433,7 @@ union acpi_operand_object *acpi_ut_creat
 union acpi_operand_object *acpi_ut_create_string_object(acpi_size string_size);
 
 acpi_status
-acpi_ut_get_object_size(union acpi_operand_object *obj, acpi_size * obj_length);
+acpi_ut_get_object_size(union acpi_operand_object *obj, acpi_size *obj_length);
 
 /*
  * utosi - Support for the _OSI predefined control method
@@ -526,15 +544,15 @@ void acpi_ut_set_integer_width(u8 revisi
 void
 acpi_ut_display_init_pathname(u8 type,
 			      struct acpi_namespace_node *obj_handle,
-			      char *path);
+			      const char *path);
 #endif
 
 /*
  * utownerid - Support for Table/Method Owner IDs
  */
-acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id);
+acpi_status acpi_ut_allocate_owner_id(acpi_owner_id *owner_id);
 
-void acpi_ut_release_owner_id(acpi_owner_id * owner_id);
+void acpi_ut_release_owner_id(acpi_owner_id *owner_id);
 
 /*
  * utresrc
@@ -570,10 +588,6 @@ void acpi_ut_print_string(char *string,
 void ut_convert_backslashes(char *pathname);
 #endif
 
-u8 acpi_ut_valid_acpi_name(char *name);
-
-u8 acpi_ut_valid_acpi_char(char character, u32 position);
-
 void acpi_ut_repair_name(char *name);
 
 #if defined (ACPI_DEBUGGER) || defined (ACPI_APPLICATION)
@@ -628,7 +642,7 @@ void acpi_ut_dump_allocation_info(void);
 void acpi_ut_dump_allocations(u32 component, const char *module);
 
 acpi_status
-acpi_ut_create_list(char *list_name,
+acpi_ut_create_list(const char *list_name,
 		    u16 object_size, struct acpi_memory_list **return_cache);
 
 #endif				/* ACPI_DBG_TRACK_ALLOCATIONS */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/dbcmds.c linux-libre-4.7-gnu/drivers/acpi/acpica/dbcmds.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/dbcmds.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/dbcmds.c	2016-07-24 15:23:50.000000000 -0400
@@ -738,9 +738,9 @@ acpi_dm_test_resource_conversion(struct
 	original_aml = return_buffer.pointer;
 
 	acpi_dm_compare_aml_resources(original_aml->buffer.pointer,
-				      (acpi_rsdesc_size) original_aml->buffer.
+				      (acpi_rsdesc_size)original_aml->buffer.
 				      length, new_aml.pointer,
-				      (acpi_rsdesc_size) new_aml.length);
+				      (acpi_rsdesc_size)new_aml.length);
 
 	/* Cleanup and exit */
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/dbconvert.c linux-libre-4.7-gnu/drivers/acpi/acpica/dbconvert.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/dbconvert.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/dbconvert.c	2016-07-24 15:23:50.000000000 -0400
@@ -194,7 +194,7 @@ acpi_db_convert_to_buffer(char *string,
  *
  ******************************************************************************/
 
-acpi_status acpi_db_convert_to_package(char *string, union acpi_object * object)
+acpi_status acpi_db_convert_to_package(char *string, union acpi_object *object)
 {
 	char *this;
 	char *next;
@@ -252,7 +252,7 @@ acpi_status acpi_db_convert_to_package(c
 
 acpi_status
 acpi_db_convert_to_object(acpi_object_type type,
-			  char *string, union acpi_object * object)
+			  char *string, union acpi_object *object)
 {
 	acpi_status status = AE_OK;
 
@@ -277,7 +277,9 @@ acpi_db_convert_to_object(acpi_object_ty
 	default:
 
 		object->type = ACPI_TYPE_INTEGER;
-		status = acpi_ut_strtoul64(string, 16, &object->integer.value);
+		status =
+		    acpi_ut_strtoul64(string, 16, acpi_gbl_integer_byte_width,
+				      &object->integer.value);
 		break;
 	}
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/dbexec.c linux-libre-4.7-gnu/drivers/acpi/acpica/dbexec.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/dbexec.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/dbexec.c	2016-07-24 15:23:50.000000000 -0400
@@ -361,7 +361,7 @@ acpi_db_execution_walk(acpi_handle obj_h
  ******************************************************************************/
 
 void
-acpi_db_execute(char *name, char **args, acpi_object_type * types, u32 flags)
+acpi_db_execute(char *name, char **args, acpi_object_type *types, u32 flags)
 {
 	acpi_status status;
 	struct acpi_buffer return_obj;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/dbinput.c linux-libre-4.7-gnu/drivers/acpi/acpica/dbinput.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/dbinput.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/dbinput.c	2016-07-24 15:23:50.000000000 -0400
@@ -57,12 +57,12 @@ static u32 acpi_db_get_line(char *input_
 
 static u32 acpi_db_match_command(char *user_command);
 
-static void acpi_db_display_command_info(char *command, u8 display_all);
+static void acpi_db_display_command_info(const char *command, u8 display_all);
 
 static void acpi_db_display_help(char *command);
 
 static u8
-acpi_db_match_command_help(char *command,
+acpi_db_match_command_help(const char *command,
 			   const struct acpi_db_command_help *help);
 
 /*
@@ -348,7 +348,7 @@ static const struct acpi_db_command_help
  ******************************************************************************/
 
 static u8
-acpi_db_match_command_help(char *command,
+acpi_db_match_command_help(const char *command,
 			   const struct acpi_db_command_help *help)
 {
 	char *invocation = help->invocation;
@@ -402,7 +402,7 @@ acpi_db_match_command_help(char *command
  *
  ******************************************************************************/
 
-static void acpi_db_display_command_info(char *command, u8 display_all)
+static void acpi_db_display_command_info(const char *command, u8 display_all)
 {
 	const struct acpi_db_command_help *next;
 	u8 matched;
@@ -466,7 +466,7 @@ static void acpi_db_display_help(char *c
  ******************************************************************************/
 
 char *acpi_db_get_next_token(char *string,
-			     char **next, acpi_object_type * return_type)
+			     char **next, acpi_object_type *return_type)
 {
 	char *start;
 	u32 depth;
@@ -656,8 +656,9 @@ static u32 acpi_db_match_command(char *u
 	}
 
 	for (i = CMD_FIRST_VALID; acpi_gbl_db_commands[i].name; i++) {
-		if (strstr(acpi_gbl_db_commands[i].name, user_command) ==
-		    acpi_gbl_db_commands[i].name) {
+		if (strstr
+		    (ACPI_CAST_PTR(char, acpi_gbl_db_commands[i].name),
+		     user_command) == acpi_gbl_db_commands[i].name) {
 			return (i);
 		}
 	}
@@ -683,8 +684,8 @@ static u32 acpi_db_match_command(char *u
 
 acpi_status
 acpi_db_command_dispatch(char *input_buffer,
-			 struct acpi_walk_state * walk_state,
-			 union acpi_parse_object * op)
+			 struct acpi_walk_state *walk_state,
+			 union acpi_parse_object *op)
 {
 	u32 temp;
 	u32 command_index;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/dbnames.c linux-libre-4.7-gnu/drivers/acpi/acpica/dbnames.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/dbnames.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/dbnames.c	2016-07-24 15:23:50.000000000 -0400
@@ -285,7 +285,7 @@ void acpi_db_dump_namespace_by_owner(cha
 	u32 max_depth = ACPI_UINT32_MAX;
 	acpi_owner_id owner_id;
 
-	owner_id = (acpi_owner_id) strtoul(owner_arg, NULL, 0);
+	owner_id = (acpi_owner_id)strtoul(owner_arg, NULL, 0);
 
 	/* Now we can check for the depth argument */
 
@@ -709,7 +709,7 @@ acpi_db_integrity_walk(acpi_handle obj_h
 		return (AE_OK);
 	}
 
-	if (!acpi_ut_valid_acpi_name(node->name.ascii)) {
+	if (!acpi_ut_valid_nameseg(node->name.ascii)) {
 		acpi_os_printf("Invalid AcpiName for Node %p\n", node);
 		return (AE_OK);
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/dbutils.c linux-libre-4.7-gnu/drivers/acpi/acpica/dbutils.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/dbutils.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/dbutils.c	2016-07-24 15:23:50.000000000 -0400
@@ -56,8 +56,6 @@ acpi_status acpi_db_second_pass_parse(un
 void acpi_db_dump_buffer(u32 address);
 #endif
 
-static char *gbl_hex_to_ascii = "0123456789ABCDEF";
-
 /*******************************************************************************
  *
  * FUNCTION:    acpi_db_match_argument
@@ -82,8 +80,9 @@ acpi_db_match_argument(char *user_argume
 	}
 
 	for (i = 0; arguments[i].name; i++) {
-		if (strstr(arguments[i].name, user_argument) ==
-		    arguments[i].name) {
+		if (strstr(ACPI_CAST_PTR(char, arguments[i].name),
+			   ACPI_CAST_PTR(char,
+					 user_argument)) == arguments[i].name) {
 			return (i);
 		}
 	}
@@ -339,7 +338,7 @@ void acpi_db_uint32_to_hex_string(u32 va
 	buffer[8] = '\0';
 
 	for (i = 7; i >= 0; i--) {
-		buffer[i] = gbl_hex_to_ascii[value & 0x0F];
+		buffer[i] = acpi_gbl_upper_hex_digits[value & 0x0F];
 		value = value >> 4;
 	}
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/dbxface.c linux-libre-4.7-gnu/drivers/acpi/acpica/dbxface.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/dbxface.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/dbxface.c	2016-07-24 15:23:50.000000000 -0400
@@ -162,8 +162,8 @@ void acpi_db_signal_break_point(struct a
  ******************************************************************************/
 
 acpi_status
-acpi_db_single_step(struct acpi_walk_state * walk_state,
-		    union acpi_parse_object * op, u32 opcode_class)
+acpi_db_single_step(struct acpi_walk_state *walk_state,
+		    union acpi_parse_object *op, u32 opcode_class)
 {
 	union acpi_parse_object *next;
 	acpi_status status = AE_OK;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/dscontrol.c linux-libre-4.7-gnu/drivers/acpi/acpica/dscontrol.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/dscontrol.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/dscontrol.c	2016-07-24 15:23:50.000000000 -0400
@@ -163,8 +163,8 @@ acpi_ds_exec_begin_control_op(struct acp
  ******************************************************************************/
 
 acpi_status
-acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state,
-			    union acpi_parse_object * op)
+acpi_ds_exec_end_control_op(struct acpi_walk_state *walk_state,
+			    union acpi_parse_object *op)
 {
 	acpi_status status = AE_OK;
 	union acpi_generic_state *control_state;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/dsinit.c linux-libre-4.7-gnu/drivers/acpi/acpica/dsinit.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/dsinit.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/dsinit.c	2016-07-24 15:23:50.000000000 -0400
@@ -188,7 +188,7 @@ acpi_ds_init_one_object(acpi_handle obj_
 
 acpi_status
 acpi_ds_initialize_objects(u32 table_index,
-			   struct acpi_namespace_node * start_node)
+			   struct acpi_namespace_node *start_node)
 {
 	acpi_status status;
 	struct acpi_init_walk_info info;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/dsmethod.c linux-libre-4.7-gnu/drivers/acpi/acpica/dsmethod.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/dsmethod.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/dsmethod.c	2016-07-24 15:23:50.000000000 -0400
@@ -209,7 +209,7 @@ acpi_ds_detect_named_opcodes(struct acpi
  ******************************************************************************/
 
 acpi_status
-acpi_ds_method_error(acpi_status status, struct acpi_walk_state * walk_state)
+acpi_ds_method_error(acpi_status status, struct acpi_walk_state *walk_state)
 {
 	u32 aml_offset;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/dsutils.c linux-libre-4.7-gnu/drivers/acpi/acpica/dsutils.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/dsutils.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/dsutils.c	2016-07-24 15:23:50.000000000 -0400
@@ -569,7 +569,7 @@ acpi_ds_create_operand(struct acpi_walk_
 					/* TBD: May only be temporary */
 
 					obj_desc =
-					    acpi_ut_create_string_object((acpi_size) name_length);
+					    acpi_ut_create_string_object((acpi_size)name_length);
 
 					strncpy(obj_desc->string.pointer,
 						name_string, name_length);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/dswload2.c linux-libre-4.7-gnu/drivers/acpi/acpica/dswload2.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/dswload2.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/dswload2.c	2016-07-24 15:23:50.000000000 -0400
@@ -490,8 +490,8 @@ acpi_status acpi_ds_load2_end_op(struct
 
 			status =
 			    acpi_ds_create_index_field(op,
-						       (acpi_handle) arg->
-						       common.node, walk_state);
+						       (acpi_handle)arg->common.
+						       node, walk_state);
 			break;
 
 		case AML_BANK_FIELD_OP:
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/dswload.c linux-libre-4.7-gnu/drivers/acpi/acpica/dswload.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/dswload.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/dswload.c	2016-07-24 15:23:50.000000000 -0400
@@ -137,8 +137,8 @@ acpi_ds_init_callbacks(struct acpi_walk_
  ******************************************************************************/
 
 acpi_status
-acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state,
-		       union acpi_parse_object ** out_op)
+acpi_ds_load1_begin_op(struct acpi_walk_state *walk_state,
+		       union acpi_parse_object **out_op)
 {
 	union acpi_parse_object *op;
 	struct acpi_namespace_node *node;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/dswstate.c linux-libre-4.7-gnu/drivers/acpi/acpica/dswstate.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/dswstate.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/dswstate.c	2016-07-24 15:23:50.000000000 -0400
@@ -143,8 +143,8 @@ acpi_ds_result_pop(union acpi_operand_ob
  ******************************************************************************/
 
 acpi_status
-acpi_ds_result_push(union acpi_operand_object * object,
-		    struct acpi_walk_state * walk_state)
+acpi_ds_result_push(union acpi_operand_object *object,
+		    struct acpi_walk_state *walk_state)
 {
 	union acpi_generic_state *state;
 	acpi_status status;
@@ -307,7 +307,7 @@ static acpi_status acpi_ds_result_stack_
  ******************************************************************************/
 
 acpi_status
-acpi_ds_obj_stack_push(void *object, struct acpi_walk_state * walk_state)
+acpi_ds_obj_stack_push(void *object, struct acpi_walk_state *walk_state)
 {
 	ACPI_FUNCTION_NAME(ds_obj_stack_push);
 
@@ -354,7 +354,7 @@ acpi_ds_obj_stack_push(void *object, str
  ******************************************************************************/
 
 acpi_status
-acpi_ds_obj_stack_pop(u32 pop_count, struct acpi_walk_state * walk_state)
+acpi_ds_obj_stack_pop(u32 pop_count, struct acpi_walk_state *walk_state)
 {
 	u32 i;
 
@@ -411,7 +411,7 @@ acpi_ds_obj_stack_pop_and_delete(u32 pop
 		return;
 	}
 
-	for (i = (s32) pop_count - 1; i >= 0; i--) {
+	for (i = (s32)pop_count - 1; i >= 0; i--) {
 		if (walk_state->num_operands == 0) {
 			return;
 		}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/evgpeblk.c linux-libre-4.7-gnu/drivers/acpi/acpica/evgpeblk.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/evgpeblk.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/evgpeblk.c	2016-07-24 15:23:50.000000000 -0400
@@ -211,7 +211,7 @@ acpi_ev_create_gpe_info_blocks(struct ac
 
 	/* Allocate the GPE register information block */
 
-	gpe_register_info = ACPI_ALLOCATE_ZEROED((acpi_size) gpe_block->
+	gpe_register_info = ACPI_ALLOCATE_ZEROED((acpi_size)gpe_block->
 						 register_count *
 						 sizeof(struct
 							acpi_gpe_register_info));
@@ -225,7 +225,7 @@ acpi_ev_create_gpe_info_blocks(struct ac
 	 * Allocate the GPE event_info block. There are eight distinct GPEs
 	 * per register. Initialization to zeros is sufficient.
 	 */
-	gpe_event_info = ACPI_ALLOCATE_ZEROED((acpi_size) gpe_block->gpe_count *
+	gpe_event_info = ACPI_ALLOCATE_ZEROED((acpi_size)gpe_block->gpe_count *
 					      sizeof(struct
 						     acpi_gpe_event_info));
 	if (!gpe_event_info) {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/evgpe.c linux-libre-4.7-gnu/drivers/acpi/acpica/evgpe.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/evgpe.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/evgpe.c	2016-07-24 15:23:50.000000000 -0400
@@ -440,7 +440,7 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_x
 
 				gpe_event_info =
 				    &gpe_block->
-				    event_info[((acpi_size) i *
+				    event_info[((acpi_size)i *
 						ACPI_GPE_REGISTER_WIDTH) + j];
 				gpe_number =
 				    j + gpe_register_info->base_gpe_number;
@@ -652,7 +652,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_as
  *
  ******************************************************************************/
 
-acpi_status acpi_ev_finish_gpe(struct acpi_gpe_event_info * gpe_event_info)
+acpi_status acpi_ev_finish_gpe(struct acpi_gpe_event_info *gpe_event_info)
 {
 	acpi_status status;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/evgpeutil.c linux-libre-4.7-gnu/drivers/acpi/acpica/evgpeutil.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/evgpeutil.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/evgpeutil.c	2016-07-24 15:23:50.000000000 -0400
@@ -163,7 +163,7 @@ acpi_ev_get_gpe_device(struct acpi_gpe_x
 
 acpi_status
 acpi_ev_get_gpe_xrupt_block(u32 interrupt_number,
-			    struct acpi_gpe_xrupt_info ** gpe_xrupt_block)
+			    struct acpi_gpe_xrupt_info **gpe_xrupt_block)
 {
 	struct acpi_gpe_xrupt_info *next_gpe_xrupt;
 	struct acpi_gpe_xrupt_info *gpe_xrupt;
@@ -320,7 +320,7 @@ acpi_ev_delete_gpe_handlers(struct acpi_
 		/* Now look at the individual GPEs in this byte register */
 
 		for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
-			gpe_event_info = &gpe_block->event_info[((acpi_size) i *
+			gpe_event_info = &gpe_block->event_info[((acpi_size)i *
 								 ACPI_GPE_REGISTER_WIDTH)
 								+ j];
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/evhandler.c linux-libre-4.7-gnu/drivers/acpi/acpica/evhandler.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/evhandler.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/evhandler.c	2016-07-24 15:23:50.000000000 -0400
@@ -359,7 +359,7 @@ union acpi_operand_object *acpi_ev_find_
  ******************************************************************************/
 
 acpi_status
-acpi_ev_install_space_handler(struct acpi_namespace_node * node,
+acpi_ev_install_space_handler(struct acpi_namespace_node *node,
 			      acpi_adr_space_type space_id,
 			      acpi_adr_space_handler handler,
 			      acpi_adr_space_setup setup, void *context)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/evmisc.c linux-libre-4.7-gnu/drivers/acpi/acpica/evmisc.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/evmisc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/evmisc.c	2016-07-24 15:23:50.000000000 -0400
@@ -99,8 +99,7 @@ u8 acpi_ev_is_notify_object(struct acpi_
  ******************************************************************************/
 
 acpi_status
-acpi_ev_queue_notify_request(struct acpi_namespace_node * node,
-			     u32 notify_value)
+acpi_ev_queue_notify_request(struct acpi_namespace_node *node, u32 notify_value)
 {
 	union acpi_operand_object *obj_desc;
 	union acpi_operand_object *handler_list_head = NULL;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/evregion.c linux-libre-4.7-gnu/drivers/acpi/acpica/evregion.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/evregion.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/evregion.c	2016-07-24 15:23:50.000000000 -0400
@@ -526,81 +526,59 @@ acpi_ev_attach_region(union acpi_operand
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ev_associate_reg_method
+ * FUNCTION:    acpi_ev_execute_reg_method
  *
  * PARAMETERS:  region_obj          - Region object
+ *              function            - Passed to _REG: On (1) or Off (0)
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Find and associate _REG method to a region
+ * DESCRIPTION: Execute _REG method for a region
  *
  ******************************************************************************/
 
-void acpi_ev_associate_reg_method(union acpi_operand_object *region_obj)
+acpi_status
+acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function)
 {
-	acpi_name *reg_name_ptr = (acpi_name *) METHOD_NAME__REG;
+	struct acpi_evaluate_info *info;
+	union acpi_operand_object *args[3];
+	union acpi_operand_object *region_obj2;
+	const acpi_name *reg_name_ptr =
+	    ACPI_CAST_PTR(acpi_name, METHOD_NAME__REG);
 	struct acpi_namespace_node *method_node;
 	struct acpi_namespace_node *node;
-	union acpi_operand_object *region_obj2;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE(ev_associate_reg_method);
+	ACPI_FUNCTION_TRACE(ev_execute_reg_method);
+
+	if (!acpi_gbl_namespace_initialized ||
+	    region_obj->region.handler == NULL) {
+		return_ACPI_STATUS(AE_OK);
+	}
 
 	region_obj2 = acpi_ns_get_secondary_object(region_obj);
 	if (!region_obj2) {
-		return_VOID;
+		return_ACPI_STATUS(AE_NOT_EXIST);
 	}
 
+	/*
+	 * Find any "_REG" method associated with this region definition.
+	 * The method should always be updated as this function may be
+	 * invoked after a namespace change.
+	 */
 	node = region_obj->region.node->parent;
-
-	/* Find any "_REG" method associated with this region definition */
-
 	status =
 	    acpi_ns_search_one_scope(*reg_name_ptr, node, ACPI_TYPE_METHOD,
 				     &method_node);
 	if (ACPI_SUCCESS(status)) {
 		/*
-		 * The _REG method is optional and there can be only one per region
-		 * definition. This will be executed when the handler is attached
-		 * or removed
+		 * The _REG method is optional and there can be only one per
+		 * region definition. This will be executed when the handler is
+		 * attached or removed.
 		 */
 		region_obj2->extra.method_REG = method_node;
 	}
-
-	return_VOID;
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ev_execute_reg_method
- *
- * PARAMETERS:  region_obj          - Region object
- *              function            - Passed to _REG: On (1) or Off (0)
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Execute _REG method for a region
- *
- ******************************************************************************/
-
-acpi_status
-acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function)
-{
-	struct acpi_evaluate_info *info;
-	union acpi_operand_object *args[3];
-	union acpi_operand_object *region_obj2;
-	acpi_status status;
-
-	ACPI_FUNCTION_TRACE(ev_execute_reg_method);
-
-	region_obj2 = acpi_ns_get_secondary_object(region_obj);
-	if (!region_obj2) {
-		return_ACPI_STATUS(AE_NOT_EXIST);
-	}
-
-	if (region_obj2->extra.method_REG == NULL ||
-	    region_obj->region.handler == NULL ||
-	    !acpi_gbl_namespace_initialized) {
+	if (region_obj2->extra.method_REG == NULL) {
 		return_ACPI_STATUS(AE_OK);
 	}
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/evrgnini.c linux-libre-4.7-gnu/drivers/acpi/acpica/evrgnini.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/evrgnini.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/evrgnini.c	2016-07-24 15:23:50.000000000 -0400
@@ -227,7 +227,7 @@ acpi_ev_pci_config_region_setup(acpi_han
 
 				/* Install a handler for this PCI root bridge */
 
-				status = acpi_install_address_space_handler((acpi_handle) pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL);
+				status = acpi_install_address_space_handler((acpi_handle)pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL);
 				if (ACPI_FAILURE(status)) {
 					if (status == AE_SAME_HANDLER) {
 						/*
@@ -518,7 +518,6 @@ acpi_ev_initialize_region(union acpi_ope
 		return_ACPI_STATUS(AE_OK);
 	}
 
-	acpi_ev_associate_reg_method(region_obj);
 	region_obj->common.flags |= AOPOBJ_OBJECT_INITIALIZED;
 
 	node = region_obj->region.node->parent;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/evxfgpe.c linux-libre-4.7-gnu/drivers/acpi/acpica/evxfgpe.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/evxfgpe.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/evxfgpe.c	2016-07-24 15:23:50.000000000 -0400
@@ -917,7 +917,7 @@ ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block
  *              the FADT-defined gpe blocks. Otherwise, the GPE block device.
  *
  ******************************************************************************/
-acpi_status acpi_get_gpe_device(u32 index, acpi_handle * gpe_device)
+acpi_status acpi_get_gpe_device(u32 index, acpi_handle *gpe_device)
 {
 	struct acpi_gpe_device_info info;
 	acpi_status status;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/exconcat.c linux-libre-4.7-gnu/drivers/acpi/acpica/exconcat.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/exconcat.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/exconcat.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,439 @@
+/******************************************************************************
+ *
+ * Module Name: exconcat - Concatenate-type AML operators
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2016, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    substantially similar to the "NO WARRANTY" disclaimer below
+ *    ("Disclaimer") and any redistribution must be conditioned upon
+ *    including a substantially similar Disclaimer requirement for further
+ *    binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+#include "acinterp.h"
+#include "amlresrc.h"
+
+#define _COMPONENT          ACPI_EXECUTER
+ACPI_MODULE_NAME("exconcat")
+
+/* Local Prototypes */
+static acpi_status
+acpi_ex_convert_to_object_type_string(union acpi_operand_object *obj_desc,
+				      union acpi_operand_object **result_desc);
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ex_do_concatenate
+ *
+ * PARAMETERS:  operand0            - First source object
+ *              operand1            - Second source object
+ *              actual_return_desc  - Where to place the return object
+ *              walk_state          - Current walk state
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Concatenate two objects with the ACPI-defined conversion
+ *              rules as necessary.
+ * NOTE:
+ * Per the ACPI spec (up to 6.1), Concatenate only supports Integer,
+ * String, and Buffer objects. However, we support all objects here
+ * as an extension. This improves the usefulness of both Concatenate
+ * and the Printf/Fprintf macros. The extension returns a string
+ * describing the object type for the other objects.
+ * 02/2016.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ex_do_concatenate(union acpi_operand_object *operand0,
+		       union acpi_operand_object *operand1,
+		       union acpi_operand_object **actual_return_desc,
+		       struct acpi_walk_state *walk_state)
+{
+	union acpi_operand_object *local_operand0 = operand0;
+	union acpi_operand_object *local_operand1 = operand1;
+	union acpi_operand_object *temp_operand1 = NULL;
+	union acpi_operand_object *return_desc;
+	char *buffer;
+	acpi_object_type operand0_type;
+	acpi_object_type operand1_type;
+	acpi_status status;
+
+	ACPI_FUNCTION_TRACE(ex_do_concatenate);
+
+	/* Operand 0 preprocessing */
+
+	switch (operand0->common.type) {
+	case ACPI_TYPE_INTEGER:
+	case ACPI_TYPE_STRING:
+	case ACPI_TYPE_BUFFER:
+
+		operand0_type = operand0->common.type;
+		break;
+
+	default:
+
+		/* For all other types, get the "object type" string */
+
+		status =
+		    acpi_ex_convert_to_object_type_string(operand0,
+							  &local_operand0);
+		if (ACPI_FAILURE(status)) {
+			goto cleanup;
+		}
+
+		operand0_type = ACPI_TYPE_STRING;
+		break;
+	}
+
+	/* Operand 1 preprocessing */
+
+	switch (operand1->common.type) {
+	case ACPI_TYPE_INTEGER:
+	case ACPI_TYPE_STRING:
+	case ACPI_TYPE_BUFFER:
+
+		operand1_type = operand1->common.type;
+		break;
+
+	default:
+
+		/* For all other types, get the "object type" string */
+
+		status =
+		    acpi_ex_convert_to_object_type_string(operand1,
+							  &local_operand1);
+		if (ACPI_FAILURE(status)) {
+			goto cleanup;
+		}
+
+		operand1_type = ACPI_TYPE_STRING;
+		break;
+	}
+
+	/*
+	 * Convert the second operand if necessary. The first operand (0)
+	 * determines the type of the second operand (1) (See the Data Types
+	 * section of the ACPI specification). Both object types are
+	 * guaranteed to be either Integer/String/Buffer by the operand
+	 * resolution mechanism.
+	 */
+	switch (operand0_type) {
+	case ACPI_TYPE_INTEGER:
+
+		status =
+		    acpi_ex_convert_to_integer(local_operand1, &temp_operand1,
+					       16);
+		break;
+
+	case ACPI_TYPE_BUFFER:
+
+		status =
+		    acpi_ex_convert_to_buffer(local_operand1, &temp_operand1);
+		break;
+
+	case ACPI_TYPE_STRING:
+
+		switch (operand1_type) {
+		case ACPI_TYPE_INTEGER:
+		case ACPI_TYPE_STRING:
+		case ACPI_TYPE_BUFFER:
+
+			/* Other types have already been converted to string */
+
+			status =
+			    acpi_ex_convert_to_string(local_operand1,
+						      &temp_operand1,
+						      ACPI_IMPLICIT_CONVERT_HEX);
+			break;
+
+		default:
+
+			status = AE_OK;
+			break;
+		}
+		break;
+
+	default:
+
+		ACPI_ERROR((AE_INFO, "Invalid object type: 0x%X",
+			    operand0->common.type));
+		status = AE_AML_INTERNAL;
+	}
+
+	if (ACPI_FAILURE(status)) {
+		goto cleanup;
+	}
+
+	/* Take care with any newly created operand objects */
+
+	if ((local_operand1 != operand1) && (local_operand1 != temp_operand1)) {
+		acpi_ut_remove_reference(local_operand1);
+	}
+
+	local_operand1 = temp_operand1;
+
+	/*
+	 * Both operands are now known to be the same object type
+	 * (Both are Integer, String, or Buffer), and we can now perform
+	 * the concatenation.
+	 *
+	 * There are three cases to handle, as per the ACPI spec:
+	 *
+	 * 1) Two Integers concatenated to produce a new Buffer
+	 * 2) Two Strings concatenated to produce a new String
+	 * 3) Two Buffers concatenated to produce a new Buffer
+	 */
+	switch (operand0_type) {
+	case ACPI_TYPE_INTEGER:
+
+		/* Result of two Integers is a Buffer */
+		/* Need enough buffer space for two integers */
+
+		return_desc = acpi_ut_create_buffer_object((acpi_size)
+							   ACPI_MUL_2
+							   (acpi_gbl_integer_byte_width));
+		if (!return_desc) {
+			status = AE_NO_MEMORY;
+			goto cleanup;
+		}
+
+		buffer = (char *)return_desc->buffer.pointer;
+
+		/* Copy the first integer, LSB first */
+
+		memcpy(buffer, &operand0->integer.value,
+		       acpi_gbl_integer_byte_width);
+
+		/* Copy the second integer (LSB first) after the first */
+
+		memcpy(buffer + acpi_gbl_integer_byte_width,
+		       &local_operand1->integer.value,
+		       acpi_gbl_integer_byte_width);
+		break;
+
+	case ACPI_TYPE_STRING:
+
+		/* Result of two Strings is a String */
+
+		return_desc = acpi_ut_create_string_object(((acpi_size)
+							    local_operand0->
+							    string.length +
+							    local_operand1->
+							    string.length));
+		if (!return_desc) {
+			status = AE_NO_MEMORY;
+			goto cleanup;
+		}
+
+		buffer = return_desc->string.pointer;
+
+		/* Concatenate the strings */
+
+		strcpy(buffer, local_operand0->string.pointer);
+		strcat(buffer, local_operand1->string.pointer);
+		break;
+
+	case ACPI_TYPE_BUFFER:
+
+		/* Result of two Buffers is a Buffer */
+
+		return_desc = acpi_ut_create_buffer_object(((acpi_size)
+							    operand0->buffer.
+							    length +
+							    local_operand1->
+							    buffer.length));
+		if (!return_desc) {
+			status = AE_NO_MEMORY;
+			goto cleanup;
+		}
+
+		buffer = (char *)return_desc->buffer.pointer;
+
+		/* Concatenate the buffers */
+
+		memcpy(buffer, operand0->buffer.pointer,
+		       operand0->buffer.length);
+		memcpy(buffer + operand0->buffer.length,
+		       local_operand1->buffer.pointer,
+		       local_operand1->buffer.length);
+		break;
+
+	default:
+
+		/* Invalid object type, should not happen here */
+
+		ACPI_ERROR((AE_INFO, "Invalid object type: 0x%X",
+			    operand0->common.type));
+		status = AE_AML_INTERNAL;
+		goto cleanup;
+	}
+
+	*actual_return_desc = return_desc;
+
+cleanup:
+	if (local_operand0 != operand0) {
+		acpi_ut_remove_reference(local_operand0);
+	}
+
+	if (local_operand1 != operand1) {
+		acpi_ut_remove_reference(local_operand1);
+	}
+
+	return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ex_convert_to_object_type_string
+ *
+ * PARAMETERS:  obj_desc            - Object to be converted
+ *              return_desc         - Where to place the return object
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Convert an object of arbitrary type to a string object that
+ *              contains the namestring for the object. Used for the
+ *              concatenate operator.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_ex_convert_to_object_type_string(union acpi_operand_object *obj_desc,
+				      union acpi_operand_object **result_desc)
+{
+	union acpi_operand_object *return_desc;
+	const char *type_string;
+
+	type_string = acpi_ut_get_type_name(obj_desc->common.type);
+
+	return_desc = acpi_ut_create_string_object(((acpi_size)strlen(type_string) + 9));	/* 9 For "[ Object]" */
+	if (!return_desc) {
+		return (AE_NO_MEMORY);
+	}
+
+	strcpy(return_desc->string.pointer, "[");
+	strcat(return_desc->string.pointer, type_string);
+	strcat(return_desc->string.pointer, " Object]");
+
+	*result_desc = return_desc;
+	return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ex_concat_template
+ *
+ * PARAMETERS:  operand0            - First source object
+ *              operand1            - Second source object
+ *              actual_return_desc  - Where to place the return object
+ *              walk_state          - Current walk state
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Concatenate two resource templates
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ex_concat_template(union acpi_operand_object *operand0,
+			union acpi_operand_object *operand1,
+			union acpi_operand_object **actual_return_desc,
+			struct acpi_walk_state *walk_state)
+{
+	acpi_status status;
+	union acpi_operand_object *return_desc;
+	u8 *new_buf;
+	u8 *end_tag;
+	acpi_size length0;
+	acpi_size length1;
+	acpi_size new_length;
+
+	ACPI_FUNCTION_TRACE(ex_concat_template);
+
+	/*
+	 * Find the end_tag descriptor in each resource template.
+	 * Note1: returned pointers point TO the end_tag, not past it.
+	 * Note2: zero-length buffers are allowed; treated like one end_tag
+	 */
+
+	/* Get the length of the first resource template */
+
+	status = acpi_ut_get_resource_end_tag(operand0, &end_tag);
+	if (ACPI_FAILURE(status)) {
+		return_ACPI_STATUS(status);
+	}
+
+	length0 = ACPI_PTR_DIFF(end_tag, operand0->buffer.pointer);
+
+	/* Get the length of the second resource template */
+
+	status = acpi_ut_get_resource_end_tag(operand1, &end_tag);
+	if (ACPI_FAILURE(status)) {
+		return_ACPI_STATUS(status);
+	}
+
+	length1 = ACPI_PTR_DIFF(end_tag, operand1->buffer.pointer);
+
+	/* Combine both lengths, minimum size will be 2 for end_tag */
+
+	new_length = length0 + length1 + sizeof(struct aml_resource_end_tag);
+
+	/* Create a new buffer object for the result (with one end_tag) */
+
+	return_desc = acpi_ut_create_buffer_object(new_length);
+	if (!return_desc) {
+		return_ACPI_STATUS(AE_NO_MEMORY);
+	}
+
+	/*
+	 * Copy the templates to the new buffer, 0 first, then 1 follows. One
+	 * end_tag descriptor is copied from Operand1.
+	 */
+	new_buf = return_desc->buffer.pointer;
+	memcpy(new_buf, operand0->buffer.pointer, length0);
+	memcpy(new_buf + length0, operand1->buffer.pointer, length1);
+
+	/* Insert end_tag and set the checksum to zero, means "ignore checksum" */
+
+	new_buf[new_length - 1] = 0;
+	new_buf[new_length - 2] = ACPI_RESOURCE_NAME_END_TAG | 1;
+
+	/* Return the completed resource template */
+
+	*actual_return_desc = return_desc;
+	return_ACPI_STATUS(AE_OK);
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/exconfig.c linux-libre-4.7-gnu/drivers/acpi/acpica/exconfig.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/exconfig.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/exconfig.c	2016-07-24 15:23:50.000000000 -0400
@@ -118,7 +118,9 @@ acpi_ex_add_table(u32 table_index,
 	/* Execute any module-level code that was found in the table */
 
 	acpi_ex_exit_interpreter();
-	acpi_ns_exec_module_code_list();
+	if (acpi_gbl_group_module_level_code) {
+		acpi_ns_exec_module_code_list();
+	}
 	acpi_ex_enter_interpreter();
 
 	/*
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/exconvrt.c linux-libre-4.7-gnu/drivers/acpi/acpica/exconvrt.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/exconvrt.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/exconvrt.c	2016-07-24 15:23:50.000000000 -0400
@@ -124,7 +124,9 @@ acpi_ex_convert_to_integer(union acpi_op
 		 * of ACPI 3.0) is that the to_integer() operator allows both decimal
 		 * and hexadecimal strings (hex prefixed with "0x").
 		 */
-		status = acpi_ut_strtoul64((char *)pointer, flags, &result);
+		status = acpi_ut_strtoul64((char *)pointer, flags,
+					   acpi_gbl_integer_byte_width,
+					   &result);
 		if (ACPI_FAILURE(status)) {
 			return_ACPI_STATUS(status);
 		}
@@ -439,7 +441,7 @@ acpi_ex_convert_to_string(union acpi_ope
 		 * Need enough space for one ASCII integer (plus null terminator)
 		 */
 		return_desc =
-		    acpi_ut_create_string_object((acpi_size) string_length);
+		    acpi_ut_create_string_object((acpi_size)string_length);
 		if (!return_desc) {
 			return_ACPI_STATUS(AE_NO_MEMORY);
 		}
@@ -518,7 +520,7 @@ acpi_ex_convert_to_string(union acpi_ope
 		}
 
 		return_desc =
-		    acpi_ut_create_string_object((acpi_size) string_length);
+		    acpi_ut_create_string_object((acpi_size)string_length);
 		if (!return_desc) {
 			return_ACPI_STATUS(AE_NO_MEMORY);
 		}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/excreate.c linux-libre-4.7-gnu/drivers/acpi/acpica/excreate.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/excreate.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/excreate.c	2016-07-24 15:23:50.000000000 -0400
@@ -394,7 +394,7 @@ acpi_status acpi_ex_create_processor(str
 	obj_desc->processor.proc_id = (u8) operand[1]->integer.value;
 	obj_desc->processor.length = (u8) operand[3]->integer.value;
 	obj_desc->processor.address =
-	    (acpi_io_address) operand[2]->integer.value;
+	    (acpi_io_address)operand[2]->integer.value;
 
 	/* Install the processor object in the parent Node */
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/exdump.c linux-libre-4.7-gnu/drivers/acpi/acpica/exdump.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/exdump.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/exdump.c	2016-07-24 15:23:50.000000000 -0400
@@ -55,9 +55,9 @@ ACPI_MODULE_NAME("exdump")
  */
 #if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
 /* Local prototypes */
-static void acpi_ex_out_string(char *title, char *value);
+static void acpi_ex_out_string(const char *title, const char *value);
 
-static void acpi_ex_out_pointer(char *title, void *value);
+static void acpi_ex_out_pointer(const char *title, const void *value);
 
 static void
 acpi_ex_dump_object(union acpi_operand_object *obj_desc,
@@ -365,8 +365,7 @@ acpi_ex_dump_object(union acpi_operand_o
 		    struct acpi_exdump_info *info)
 {
 	u8 *target;
-	char *name;
-	const char *reference_name;
+	const char *name;
 	u8 count;
 	union acpi_operand_object *start;
 	union acpi_operand_object *data = NULL;
@@ -459,9 +458,9 @@ acpi_ex_dump_object(union acpi_operand_o
 
 		case ACPI_EXD_REFERENCE:
 
-			reference_name = acpi_ut_get_reference_name(obj_desc);
 			acpi_ex_out_string("Class Name",
-					   ACPI_CAST_PTR(char, reference_name));
+					   acpi_ut_get_reference_name
+					   (obj_desc));
 			acpi_ex_dump_reference_obj(obj_desc);
 			break;
 
@@ -934,12 +933,12 @@ acpi_ex_dump_operands(union acpi_operand
  *
  ******************************************************************************/
 
-static void acpi_ex_out_string(char *title, char *value)
+static void acpi_ex_out_string(const char *title, const char *value)
 {
 	acpi_os_printf("%20s : %s\n", title, value);
 }
 
-static void acpi_ex_out_pointer(char *title, void *value)
+static void acpi_ex_out_pointer(const char *title, const void *value)
 {
 	acpi_os_printf("%20s : %p\n", title, value);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/exfield.c linux-libre-4.7-gnu/drivers/acpi/acpica/exfield.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/exfield.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/exfield.c	2016-07-24 15:23:50.000000000 -0400
@@ -126,7 +126,7 @@ acpi_ex_get_serial_access_length(u32 acc
  ******************************************************************************/
 
 acpi_status
-acpi_ex_read_data_from_field(struct acpi_walk_state * walk_state,
+acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
 			     union acpi_operand_object *obj_desc,
 			     union acpi_operand_object **ret_buffer_desc)
 {
@@ -233,7 +233,7 @@ acpi_ex_read_data_from_field(struct acpi
 	 * Note: Field.length is in bits.
 	 */
 	length =
-	    (acpi_size) ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->field.bit_length);
+	    (acpi_size)ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->field.bit_length);
 
 	if (length > acpi_gbl_integer_byte_width) {
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/exfldio.c linux-libre-4.7-gnu/drivers/acpi/acpica/exfldio.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/exfldio.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/exfldio.c	2016-07-24 15:23:50.000000000 -0400
@@ -164,7 +164,7 @@ acpi_ex_setup_region(union acpi_operand_
 			if (ACPI_ROUND_UP(rgn_desc->region.length,
 					  obj_desc->common_field.
 					  access_byte_width) >=
-			    ((acpi_size) obj_desc->common_field.
+			    ((acpi_size)obj_desc->common_field.
 			     base_byte_offset +
 			     obj_desc->common_field.access_byte_width +
 			     field_datum_byte_offset)) {
@@ -897,17 +897,9 @@ acpi_ex_insert_into_field(union acpi_ope
 
 	access_bit_width = ACPI_MUL_8(obj_desc->common_field.access_byte_width);
 
-	/*
-	 * Create the bitmasks used for bit insertion.
-	 * Note: This if/else is used to bypass compiler differences with the
-	 * shift operator
-	 */
-	if (access_bit_width == ACPI_INTEGER_BIT_SIZE) {
-		width_mask = ACPI_UINT64_MAX;
-	} else {
-		width_mask = ACPI_MASK_BITS_ABOVE(access_bit_width);
-	}
+	/* Create the bitmasks used for bit insertion */
 
+	width_mask = ACPI_MASK_BITS_ABOVE_64(access_bit_width);
 	mask = width_mask &
 	    ACPI_MASK_BITS_BELOW(obj_desc->common_field.start_field_bit_offset);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/exmisc.c linux-libre-4.7-gnu/drivers/acpi/acpica/exmisc.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/exmisc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/exmisc.c	2016-07-24 15:23:50.000000000 -0400
@@ -45,7 +45,6 @@
 #include "accommon.h"
 #include "acinterp.h"
 #include "amlcode.h"
-#include "amlresrc.h"
 
 #define _COMPONENT          ACPI_EXECUTER
 ACPI_MODULE_NAME("exmisc")
@@ -139,295 +138,6 @@ acpi_ex_get_object_reference(union acpi_
 }
 
 /*******************************************************************************
- *
- * FUNCTION:    acpi_ex_concat_template
- *
- * PARAMETERS:  operand0            - First source object
- *              operand1            - Second source object
- *              actual_return_desc  - Where to place the return object
- *              walk_state          - Current walk state
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Concatenate two resource templates
- *
- ******************************************************************************/
-
-acpi_status
-acpi_ex_concat_template(union acpi_operand_object *operand0,
-			union acpi_operand_object *operand1,
-			union acpi_operand_object **actual_return_desc,
-			struct acpi_walk_state *walk_state)
-{
-	acpi_status status;
-	union acpi_operand_object *return_desc;
-	u8 *new_buf;
-	u8 *end_tag;
-	acpi_size length0;
-	acpi_size length1;
-	acpi_size new_length;
-
-	ACPI_FUNCTION_TRACE(ex_concat_template);
-
-	/*
-	 * Find the end_tag descriptor in each resource template.
-	 * Note1: returned pointers point TO the end_tag, not past it.
-	 * Note2: zero-length buffers are allowed; treated like one end_tag
-	 */
-
-	/* Get the length of the first resource template */
-
-	status = acpi_ut_get_resource_end_tag(operand0, &end_tag);
-	if (ACPI_FAILURE(status)) {
-		return_ACPI_STATUS(status);
-	}
-
-	length0 = ACPI_PTR_DIFF(end_tag, operand0->buffer.pointer);
-
-	/* Get the length of the second resource template */
-
-	status = acpi_ut_get_resource_end_tag(operand1, &end_tag);
-	if (ACPI_FAILURE(status)) {
-		return_ACPI_STATUS(status);
-	}
-
-	length1 = ACPI_PTR_DIFF(end_tag, operand1->buffer.pointer);
-
-	/* Combine both lengths, minimum size will be 2 for end_tag */
-
-	new_length = length0 + length1 + sizeof(struct aml_resource_end_tag);
-
-	/* Create a new buffer object for the result (with one end_tag) */
-
-	return_desc = acpi_ut_create_buffer_object(new_length);
-	if (!return_desc) {
-		return_ACPI_STATUS(AE_NO_MEMORY);
-	}
-
-	/*
-	 * Copy the templates to the new buffer, 0 first, then 1 follows. One
-	 * end_tag descriptor is copied from Operand1.
-	 */
-	new_buf = return_desc->buffer.pointer;
-	memcpy(new_buf, operand0->buffer.pointer, length0);
-	memcpy(new_buf + length0, operand1->buffer.pointer, length1);
-
-	/* Insert end_tag and set the checksum to zero, means "ignore checksum" */
-
-	new_buf[new_length - 1] = 0;
-	new_buf[new_length - 2] = ACPI_RESOURCE_NAME_END_TAG | 1;
-
-	/* Return the completed resource template */
-
-	*actual_return_desc = return_desc;
-	return_ACPI_STATUS(AE_OK);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ex_do_concatenate
- *
- * PARAMETERS:  operand0            - First source object
- *              operand1            - Second source object
- *              actual_return_desc  - Where to place the return object
- *              walk_state          - Current walk state
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Concatenate two objects OF THE SAME TYPE.
- *
- ******************************************************************************/
-
-acpi_status
-acpi_ex_do_concatenate(union acpi_operand_object *operand0,
-		       union acpi_operand_object *operand1,
-		       union acpi_operand_object **actual_return_desc,
-		       struct acpi_walk_state *walk_state)
-{
-	union acpi_operand_object *local_operand1 = operand1;
-	union acpi_operand_object *return_desc;
-	char *new_buf;
-	const char *type_string;
-	acpi_status status;
-
-	ACPI_FUNCTION_TRACE(ex_do_concatenate);
-
-	/*
-	 * Convert the second operand if necessary. The first operand
-	 * determines the type of the second operand, (See the Data Types
-	 * section of the ACPI specification.)  Both object types are
-	 * guaranteed to be either Integer/String/Buffer by the operand
-	 * resolution mechanism.
-	 */
-	switch (operand0->common.type) {
-	case ACPI_TYPE_INTEGER:
-
-		status =
-		    acpi_ex_convert_to_integer(operand1, &local_operand1, 16);
-		break;
-
-	case ACPI_TYPE_STRING:
-		/*
-		 * Per the ACPI spec, Concatenate only supports int/str/buf.
-		 * However, we support all objects here as an extension.
-		 * This improves the usefulness of the Printf() macro.
-		 * 12/2015.
-		 */
-		switch (operand1->common.type) {
-		case ACPI_TYPE_INTEGER:
-		case ACPI_TYPE_STRING:
-		case ACPI_TYPE_BUFFER:
-
-			status =
-			    acpi_ex_convert_to_string(operand1, &local_operand1,
-						      ACPI_IMPLICIT_CONVERT_HEX);
-			break;
-
-		default:
-			/*
-			 * Just emit a string containing the object type.
-			 */
-			type_string =
-			    acpi_ut_get_type_name(operand1->common.type);
-
-			local_operand1 = acpi_ut_create_string_object(((acpi_size) strlen(type_string) + 9));	/* 9 For "[Object]" */
-			if (!local_operand1) {
-				status = AE_NO_MEMORY;
-				goto cleanup;
-			}
-
-			strcpy(local_operand1->string.pointer, "[");
-			strcat(local_operand1->string.pointer, type_string);
-			strcat(local_operand1->string.pointer, " Object]");
-			status = AE_OK;
-			break;
-		}
-		break;
-
-	case ACPI_TYPE_BUFFER:
-
-		status = acpi_ex_convert_to_buffer(operand1, &local_operand1);
-		break;
-
-	default:
-
-		ACPI_ERROR((AE_INFO, "Invalid object type: 0x%X",
-			    operand0->common.type));
-		status = AE_AML_INTERNAL;
-	}
-
-	if (ACPI_FAILURE(status)) {
-		goto cleanup;
-	}
-
-	/*
-	 * Both operands are now known to be the same object type
-	 * (Both are Integer, String, or Buffer), and we can now perform the
-	 * concatenation.
-	 */
-
-	/*
-	 * There are three cases to handle:
-	 *
-	 * 1) Two Integers concatenated to produce a new Buffer
-	 * 2) Two Strings concatenated to produce a new String
-	 * 3) Two Buffers concatenated to produce a new Buffer
-	 */
-	switch (operand0->common.type) {
-	case ACPI_TYPE_INTEGER:
-
-		/* Result of two Integers is a Buffer */
-		/* Need enough buffer space for two integers */
-
-		return_desc = acpi_ut_create_buffer_object((acpi_size)
-							   ACPI_MUL_2
-							   (acpi_gbl_integer_byte_width));
-		if (!return_desc) {
-			status = AE_NO_MEMORY;
-			goto cleanup;
-		}
-
-		new_buf = (char *)return_desc->buffer.pointer;
-
-		/* Copy the first integer, LSB first */
-
-		memcpy(new_buf, &operand0->integer.value,
-		       acpi_gbl_integer_byte_width);
-
-		/* Copy the second integer (LSB first) after the first */
-
-		memcpy(new_buf + acpi_gbl_integer_byte_width,
-		       &local_operand1->integer.value,
-		       acpi_gbl_integer_byte_width);
-		break;
-
-	case ACPI_TYPE_STRING:
-
-		/* Result of two Strings is a String */
-
-		return_desc = acpi_ut_create_string_object(((acpi_size)
-							    operand0->string.
-							    length +
-							    local_operand1->
-							    string.length));
-		if (!return_desc) {
-			status = AE_NO_MEMORY;
-			goto cleanup;
-		}
-
-		new_buf = return_desc->string.pointer;
-
-		/* Concatenate the strings */
-
-		strcpy(new_buf, operand0->string.pointer);
-		strcat(new_buf, local_operand1->string.pointer);
-		break;
-
-	case ACPI_TYPE_BUFFER:
-
-		/* Result of two Buffers is a Buffer */
-
-		return_desc = acpi_ut_create_buffer_object(((acpi_size)
-							    operand0->buffer.
-							    length +
-							    local_operand1->
-							    buffer.length));
-		if (!return_desc) {
-			status = AE_NO_MEMORY;
-			goto cleanup;
-		}
-
-		new_buf = (char *)return_desc->buffer.pointer;
-
-		/* Concatenate the buffers */
-
-		memcpy(new_buf, operand0->buffer.pointer,
-		       operand0->buffer.length);
-		memcpy(new_buf + operand0->buffer.length,
-		       local_operand1->buffer.pointer,
-		       local_operand1->buffer.length);
-		break;
-
-	default:
-
-		/* Invalid object type, should not happen here */
-
-		ACPI_ERROR((AE_INFO, "Invalid object type: 0x%X",
-			    operand0->common.type));
-		status = AE_AML_INTERNAL;
-		goto cleanup;
-	}
-
-	*actual_return_desc = return_desc;
-
-cleanup:
-	if (local_operand1 != operand1) {
-		acpi_ut_remove_reference(local_operand1);
-	}
-	return_ACPI_STATUS(status);
-}
-
-/*******************************************************************************
  *
  * FUNCTION:    acpi_ex_do_math_op
  *
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/exnames.c linux-libre-4.7-gnu/drivers/acpi/acpica/exnames.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/exnames.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/exnames.c	2016-07-24 15:23:50.000000000 -0400
@@ -178,7 +178,7 @@ static acpi_status acpi_ex_name_segment(
 
 	for (index = 0;
 	     (index < ACPI_NAME_SIZE)
-	     && (acpi_ut_valid_acpi_char(*aml_address, 0)); index++) {
+	     && (acpi_ut_valid_name_char(*aml_address, 0)); index++) {
 		char_buf[index] = *aml_address++;
 		ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "%c\n", char_buf[index]));
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/exoparg3.c linux-libre-4.7-gnu/drivers/acpi/acpica/exoparg3.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/exoparg3.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/exoparg3.c	2016-07-24 15:23:50.000000000 -0400
@@ -184,7 +184,7 @@ acpi_status acpi_ex_opcode_3A_1T_1R(stru
 		/* Get the Integer values from the objects */
 
 		index = operand[1]->integer.value;
-		length = (acpi_size) operand[2]->integer.value;
+		length = (acpi_size)operand[2]->integer.value;
 
 		/*
 		 * If the index is beyond the length of the String/Buffer, or if the
@@ -198,8 +198,8 @@ acpi_status acpi_ex_opcode_3A_1T_1R(stru
 
 		else if ((index + length) > operand[0]->string.length) {
 			length =
-			    (acpi_size) operand[0]->string.length -
-			    (acpi_size) index;
+			    (acpi_size)operand[0]->string.length -
+			    (acpi_size)index;
 		}
 
 		/* Strings always have a sub-pointer, not so for buffers */
@@ -209,7 +209,7 @@ acpi_status acpi_ex_opcode_3A_1T_1R(stru
 
 			/* Always allocate a new buffer for the String */
 
-			buffer = ACPI_ALLOCATE_ZEROED((acpi_size) length + 1);
+			buffer = ACPI_ALLOCATE_ZEROED((acpi_size)length + 1);
 			if (!buffer) {
 				status = AE_NO_MEMORY;
 				goto cleanup;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/exoparg6.c linux-libre-4.7-gnu/drivers/acpi/acpica/exoparg6.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/exoparg6.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/exoparg6.c	2016-07-24 15:23:50.000000000 -0400
@@ -207,7 +207,7 @@ acpi_ex_do_match(u32 match_op,
  *
  ******************************************************************************/
 
-acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state)
+acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state *walk_state)
 {
 	union acpi_operand_object **operand = &walk_state->operands[0];
 	union acpi_operand_object *return_desc = NULL;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/exregion.c linux-libre-4.7-gnu/drivers/acpi/acpica/exregion.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/exregion.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/exregion.c	2016-07-24 15:23:50.000000000 -0400
@@ -325,15 +325,15 @@ acpi_ex_system_io_space_handler(u32 func
 	switch (function) {
 	case ACPI_READ:
 
-		status = acpi_hw_read_port((acpi_io_address) address,
+		status = acpi_hw_read_port((acpi_io_address)address,
 					   &value32, bit_width);
 		*value = value32;
 		break;
 
 	case ACPI_WRITE:
 
-		status = acpi_hw_write_port((acpi_io_address) address,
-					    (u32) * value, bit_width);
+		status = acpi_hw_write_port((acpi_io_address)address,
+					    (u32)*value, bit_width);
 		break;
 
 	default:
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/exresnte.c linux-libre-4.7-gnu/drivers/acpi/acpica/exresnte.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/exresnte.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/exresnte.c	2016-07-24 15:23:50.000000000 -0400
@@ -93,7 +93,7 @@ acpi_ex_resolve_node_to_value(struct acp
 	 */
 	node = *object_ptr;
 	source_desc = acpi_ns_get_attached_object(node);
-	entry_type = acpi_ns_get_type((acpi_handle) node);
+	entry_type = acpi_ns_get_type((acpi_handle)node);
 
 	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Entry=%p SourceDesc=%p [%s]\n",
 			  node, source_desc,
@@ -106,7 +106,7 @@ acpi_ex_resolve_node_to_value(struct acp
 
 		node = ACPI_CAST_PTR(struct acpi_namespace_node, node->object);
 		source_desc = acpi_ns_get_attached_object(node);
-		entry_type = acpi_ns_get_type((acpi_handle) node);
+		entry_type = acpi_ns_get_type((acpi_handle)node);
 		*object_ptr = node;
 	}
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/exresolv.c linux-libre-4.7-gnu/drivers/acpi/acpica/exresolv.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/exresolv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/exresolv.c	2016-07-24 15:23:50.000000000 -0400
@@ -334,7 +334,7 @@ acpi_ex_resolve_object_to_value(union ac
 acpi_status
 acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
 			 union acpi_operand_object *operand,
-			 acpi_object_type * return_type,
+			 acpi_object_type *return_type,
 			 union acpi_operand_object **return_desc)
 {
 	union acpi_operand_object *obj_desc = ACPI_CAST_PTR(void, operand);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/exresop.c linux-libre-4.7-gnu/drivers/acpi/acpica/exresop.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/exresop.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/exresop.c	2016-07-24 15:23:50.000000000 -0400
@@ -131,8 +131,8 @@ acpi_ex_check_object_type(acpi_object_ty
 
 acpi_status
 acpi_ex_resolve_operands(u16 opcode,
-			 union acpi_operand_object ** stack_ptr,
-			 struct acpi_walk_state * walk_state)
+			 union acpi_operand_object **stack_ptr,
+			 struct acpi_walk_state *walk_state)
 {
 	union acpi_operand_object *obj_desc;
 	acpi_status status = AE_OK;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/exstorob.c linux-libre-4.7-gnu/drivers/acpi/acpica/exstorob.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/exstorob.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/exstorob.c	2016-07-24 15:23:50.000000000 -0400
@@ -188,7 +188,7 @@ acpi_ex_store_string_to_string(union acp
 		 * Clear old string and copy in the new one
 		 */
 		memset(target_desc->string.pointer, 0,
-		       (acpi_size) target_desc->string.length + 1);
+		       (acpi_size)target_desc->string.length + 1);
 		memcpy(target_desc->string.pointer, buffer, length);
 	} else {
 		/*
@@ -204,7 +204,7 @@ acpi_ex_store_string_to_string(union acp
 		}
 
 		target_desc->string.pointer =
-		    ACPI_ALLOCATE_ZEROED((acpi_size) length + 1);
+		    ACPI_ALLOCATE_ZEROED((acpi_size)length + 1);
 
 		if (!target_desc->string.pointer) {
 			return_ACPI_STATUS(AE_NO_MEMORY);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/exutils.c linux-libre-4.7-gnu/drivers/acpi/acpica/exutils.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/exutils.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/exutils.c	2016-07-24 15:23:50.000000000 -0400
@@ -301,8 +301,8 @@ static u32 acpi_ex_digits_needed(u64 val
  *
  * FUNCTION:    acpi_ex_eisa_id_to_string
  *
- * PARAMETERS:  compressed_id   - EISAID to be converted
- *              out_string      - Where to put the converted string (8 bytes)
+ * PARAMETERS:  out_string      - Where to put the converted string (8 bytes)
+ *              compressed_id   - EISAID to be converted
  *
  * RETURN:      None
  *
@@ -354,7 +354,7 @@ void acpi_ex_eisa_id_to_string(char *out
  *                                possible 64-bit integer.
  *              value           - Value to be converted
  *
- * RETURN:      None, string
+ * RETURN:      Converted string in out_string
  *
  * DESCRIPTION: Convert a 64-bit integer to decimal string representation.
  *              Assumes string buffer is large enough to hold the string. The
@@ -384,9 +384,9 @@ void acpi_ex_integer_to_string(char *out
  * FUNCTION:    acpi_ex_pci_cls_to_string
  *
  * PARAMETERS:  out_string      - Where to put the converted string (7 bytes)
- * PARAMETERS:  class_code      - PCI class code to be converted (3 bytes)
+ *              class_code      - PCI class code to be converted (3 bytes)
  *
- * RETURN:      None
+ * RETURN:      Converted string in out_string
  *
  * DESCRIPTION: Convert 3-bytes PCI class code to string representation.
  *              Return buffer must be large enough to hold the string. The
@@ -417,7 +417,7 @@ void acpi_ex_pci_cls_to_string(char *out
  *
  * PARAMETERS:  space_id            - ID to be validated
  *
- * RETURN:      TRUE if valid/supported ID.
+ * RETURN:      TRUE if space_id is a valid/supported ID.
  *
  * DESCRIPTION: Validate an operation region space_ID.
  *
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/hwgpe.c linux-libre-4.7-gnu/drivers/acpi/acpica/hwgpe.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/hwgpe.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/hwgpe.c	2016-07-24 15:23:50.000000000 -0400
@@ -166,7 +166,7 @@ acpi_hw_low_set_gpe(struct acpi_gpe_even
  *
  ******************************************************************************/
 
-acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info)
+acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info *gpe_event_info)
 {
 	struct acpi_gpe_register_info *gpe_register_info;
 	acpi_status status;
@@ -206,7 +206,7 @@ acpi_status acpi_hw_clear_gpe(struct acp
  ******************************************************************************/
 
 acpi_status
-acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,
+acpi_hw_get_gpe_status(struct acpi_gpe_event_info *gpe_event_info,
 		       acpi_event_status *event_status)
 {
 	u32 in_byte;
@@ -391,7 +391,7 @@ acpi_hw_clear_gpe_block(struct acpi_gpe_
 
 acpi_status
 acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
-				 struct acpi_gpe_block_info * gpe_block,
+				 struct acpi_gpe_block_info *gpe_block,
 				 void *context)
 {
 	u32 i;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/hwregs.c linux-libre-4.7-gnu/drivers/acpi/acpica/hwregs.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/hwregs.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/hwregs.c	2016-07-24 15:23:50.000000000 -0400
@@ -51,6 +51,10 @@ ACPI_MODULE_NAME("hwregs")
 
 #if (!ACPI_REDUCED_HARDWARE)
 /* Local Prototypes */
+static u8
+acpi_hw_get_access_bit_width(struct acpi_generic_address *reg,
+			     u8 max_bit_width);
+
 static acpi_status
 acpi_hw_read_multiple(u32 *value,
 		      struct acpi_generic_address *register_a,
@@ -65,6 +69,43 @@ acpi_hw_write_multiple(u32 value,
 
 /******************************************************************************
  *
+ * FUNCTION:    acpi_hw_get_access_bit_width
+ *
+ * PARAMETERS:  reg                 - GAS register structure
+ *              max_bit_width       - Max bit_width supported (32 or 64)
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Obtain optimal access bit width
+ *
+ ******************************************************************************/
+
+static u8
+acpi_hw_get_access_bit_width(struct acpi_generic_address *reg, u8 max_bit_width)
+{
+	if (!reg->access_width) {
+		if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
+			max_bit_width = 32;
+		}
+
+		/*
+		 * Detect old register descriptors where only the bit_width field
+		 * makes senses.
+		 */
+		if (reg->bit_width < max_bit_width &&
+		    !reg->bit_offset && reg->bit_width &&
+		    ACPI_IS_POWER_OF_TWO(reg->bit_width) &&
+		    ACPI_IS_ALIGNED(reg->bit_width, 8)) {
+			return (reg->bit_width);
+		}
+		return (max_bit_width);
+	} else {
+		return (1 << (reg->access_width + 2));
+	}
+}
+
+/******************************************************************************
+ *
  * FUNCTION:    acpi_hw_validate_register
  *
  * PARAMETERS:  reg                 - GAS register structure
@@ -83,6 +124,8 @@ acpi_status
 acpi_hw_validate_register(struct acpi_generic_address *reg,
 			  u8 max_bit_width, u64 *address)
 {
+	u8 bit_width;
+	u8 access_width;
 
 	/* Must have a valid pointer to a GAS structure */
 
@@ -109,23 +152,25 @@ acpi_hw_validate_register(struct acpi_ge
 		return (AE_SUPPORT);
 	}
 
-	/* Validate the bit_width */
+	/* Validate the access_width */
 
-	if ((reg->bit_width != 8) &&
-	    (reg->bit_width != 16) &&
-	    (reg->bit_width != 32) && (reg->bit_width != max_bit_width)) {
+	if (reg->access_width > 4) {
 		ACPI_ERROR((AE_INFO,
-			    "Unsupported register bit width: 0x%X",
-			    reg->bit_width));
+			    "Unsupported register access width: 0x%X",
+			    reg->access_width));
 		return (AE_SUPPORT);
 	}
 
-	/* Validate the bit_offset. Just a warning for now. */
+	/* Validate the bit_width, convert access_width into number of bits */
 
-	if (reg->bit_offset != 0) {
+	access_width = acpi_hw_get_access_bit_width(reg, max_bit_width);
+	bit_width =
+	    ACPI_ROUND_UP(reg->bit_offset + reg->bit_width, access_width);
+	if (max_bit_width < bit_width) {
 		ACPI_WARNING((AE_INFO,
-			      "Unsupported register bit offset: 0x%X",
-			      reg->bit_offset));
+			      "Requested bit width 0x%X is smaller than register bit width 0x%X",
+			      max_bit_width, bit_width));
+		return (AE_SUPPORT);
 	}
 
 	return (AE_OK);
@@ -145,17 +190,19 @@ acpi_hw_validate_register(struct acpi_ge
  *              64-bit values is not needed.
  *
  * LIMITATIONS: <These limitations also apply to acpi_hw_write>
- *      bit_width must be exactly 8, 16, or 32.
  *      space_ID must be system_memory or system_IO.
- *      bit_offset and access_width are currently ignored, as there has
- *          not been a need to implement these.
  *
  ******************************************************************************/
 
 acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg)
 {
 	u64 address;
+	u8 access_width;
+	u32 bit_width;
+	u8 bit_offset;
 	u64 value64;
+	u32 value32;
+	u8 index;
 	acpi_status status;
 
 	ACPI_FUNCTION_NAME(hw_read);
@@ -167,28 +214,75 @@ acpi_status acpi_hw_read(u32 *value, str
 		return (status);
 	}
 
-	/* Initialize entire 32-bit return value to zero */
-
+	/*
+	 * Initialize entire 32-bit return value to zero, convert access_width
+	 * into number of bits based
+	 */
 	*value = 0;
+	access_width = acpi_hw_get_access_bit_width(reg, 32);
+	bit_width = reg->bit_offset + reg->bit_width;
+	bit_offset = reg->bit_offset;
 
 	/*
 	 * Two address spaces supported: Memory or IO. PCI_Config is
 	 * not supported here because the GAS structure is insufficient
 	 */
-	if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
-		status = acpi_os_read_memory((acpi_physical_address)
-					     address, &value64, reg->bit_width);
+	index = 0;
+	while (bit_width) {
+		if (bit_offset >= access_width) {
+			value32 = 0;
+			bit_offset -= access_width;
+		} else {
+			if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
+				status =
+				    acpi_os_read_memory((acpi_physical_address)
+							address +
+							index *
+							ACPI_DIV_8
+							(access_width),
+							&value64, access_width);
+				value32 = (u32)value64;
+			} else {	/* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
 
-		*value = (u32)value64;
-	} else {		/* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
+				status = acpi_hw_read_port((acpi_io_address)
+							   address +
+							   index *
+							   ACPI_DIV_8
+							   (access_width),
+							   &value32,
+							   access_width);
+			}
 
-		status = acpi_hw_read_port((acpi_io_address)
-					   address, value, reg->bit_width);
+			/*
+			 * Use offset style bit masks because:
+			 * bit_offset < access_width/bit_width < access_width, and
+			 * access_width is ensured to be less than 32-bits by
+			 * acpi_hw_validate_register().
+			 */
+			if (bit_offset) {
+				value32 &= ACPI_MASK_BITS_BELOW(bit_offset);
+				bit_offset = 0;
+			}
+			if (bit_width < access_width) {
+				value32 &= ACPI_MASK_BITS_ABOVE(bit_width);
+			}
+		}
+
+		/*
+		 * Use offset style bit writes because "Index * AccessWidth" is
+		 * ensured to be less than 32-bits by acpi_hw_validate_register().
+		 */
+		ACPI_SET_BITS(value, index * access_width,
+			      ACPI_MASK_BITS_ABOVE_32(access_width), value32);
+
+		bit_width -=
+		    bit_width > access_width ? access_width : bit_width;
+		index++;
 	}
 
 	ACPI_DEBUG_PRINT((ACPI_DB_IO,
 			  "Read:  %8.8X width %2d from %8.8X%8.8X (%s)\n",
-			  *value, reg->bit_width, ACPI_FORMAT_UINT64(address),
+			  *value, access_width, ACPI_FORMAT_UINT64(address),
 			  acpi_ut_get_region_name(reg->space_id)));
 
 	return (status);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/hwxface.c linux-libre-4.7-gnu/drivers/acpi/acpica/hwxface.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/hwxface.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/hwxface.c	2016-07-24 15:23:50.000000000 -0400
@@ -91,10 +91,9 @@ acpi_status acpi_reset(void)
 		 * compatibility with other ACPI implementations that have allowed
 		 * BIOS code with bad register width values to go unnoticed.
 		 */
-		status =
-		    acpi_os_write_port((acpi_io_address) reset_reg->address,
-				       acpi_gbl_FADT.reset_value,
-				       ACPI_RESET_REGISTER_WIDTH);
+		status = acpi_os_write_port((acpi_io_address)reset_reg->address,
+					    acpi_gbl_FADT.reset_value,
+					    ACPI_RESET_REGISTER_WIDTH);
 	} else {
 		/* Write the reset value to the reset register */
 
@@ -504,9 +503,7 @@ acpi_get_sleep_type_data(u8 sleep_state,
 	 * Evaluate the \_Sx namespace object containing the register values
 	 * for this state
 	 */
-	info->relative_pathname = ACPI_CAST_PTR(char,
-						acpi_gbl_sleep_state_names
-						[sleep_state]);
+	info->relative_pathname = acpi_gbl_sleep_state_names[sleep_state];
 
 	status = acpi_ns_evaluate(info);
 	if (ACPI_FAILURE(status)) {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/Makefile linux-libre-4.7-gnu/drivers/acpi/acpica/Makefile
--- linux-libre-4.6-gnu/drivers/acpi/acpica/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -43,6 +43,7 @@ acpi-y +=		\
 	evxfregn.o
 
 acpi-y +=		\
+	exconcat.o	\
 	exconfig.o	\
 	exconvrt.o	\
 	excreate.o	\
@@ -149,6 +150,7 @@ acpi-y +=		\
 acpi-y +=		\
 	utaddress.o	\
 	utalloc.o	\
+	utascii.o	\
 	utbuffer.o	\
 	utcopy.o	\
 	utexcep.o	\
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/nsaccess.c linux-libre-4.7-gnu/drivers/acpi/acpica/nsaccess.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/nsaccess.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/nsaccess.c	2016-07-24 15:23:50.000000000 -0400
@@ -107,9 +107,10 @@ acpi_status acpi_ns_root_initialize(void
 			continue;
 		}
 
-		status = acpi_ns_lookup(NULL, init_val->name, init_val->type,
-					ACPI_IMODE_LOAD_PASS2,
-					ACPI_NS_NO_UPSEARCH, NULL, &new_node);
+		status =
+		    acpi_ns_lookup(NULL, (char *)init_val->name, init_val->type,
+				   ACPI_IMODE_LOAD_PASS2, ACPI_NS_NO_UPSEARCH,
+				   NULL, &new_node);
 		if (ACPI_FAILURE(status)) {
 			ACPI_EXCEPTION((AE_INFO, status,
 					"Could not create predefined name %s",
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/nsconvert.c linux-libre-4.7-gnu/drivers/acpi/acpica/nsconvert.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/nsconvert.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/nsconvert.c	2016-07-24 15:23:50.000000000 -0400
@@ -79,7 +79,8 @@ acpi_ns_convert_to_integer(union acpi_op
 		/* String-to-Integer conversion */
 
 		status = acpi_ut_strtoul64(original_object->string.pointer,
-					   ACPI_ANY_BASE, &value);
+					   ACPI_ANY_BASE,
+					   acpi_gbl_integer_byte_width, &value);
 		if (ACPI_FAILURE(status)) {
 			return (status);
 		}
@@ -317,7 +318,7 @@ acpi_ns_convert_to_buffer(union acpi_ope
  ******************************************************************************/
 
 acpi_status
-acpi_ns_convert_to_unicode(struct acpi_namespace_node * scope,
+acpi_ns_convert_to_unicode(struct acpi_namespace_node *scope,
 			   union acpi_operand_object *original_object,
 			   union acpi_operand_object **return_object)
 {
@@ -384,7 +385,7 @@ acpi_ns_convert_to_unicode(struct acpi_n
  ******************************************************************************/
 
 acpi_status
-acpi_ns_convert_to_resource(struct acpi_namespace_node * scope,
+acpi_ns_convert_to_resource(struct acpi_namespace_node *scope,
 			    union acpi_operand_object *original_object,
 			    union acpi_operand_object **return_object)
 {
@@ -463,7 +464,7 @@ acpi_ns_convert_to_resource(struct acpi_
  ******************************************************************************/
 
 acpi_status
-acpi_ns_convert_to_reference(struct acpi_namespace_node * scope,
+acpi_ns_convert_to_reference(struct acpi_namespace_node *scope,
 			     union acpi_operand_object *original_object,
 			     union acpi_operand_object **return_object)
 {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/nsdump.c linux-libre-4.7-gnu/drivers/acpi/acpica/nsdump.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/nsdump.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/nsdump.c	2016-07-24 15:23:50.000000000 -0400
@@ -81,7 +81,7 @@ acpi_ns_get_max_depth(acpi_handle obj_ha
  *
  ******************************************************************************/
 
-void acpi_ns_print_pathname(u32 num_segments, char *pathname)
+void acpi_ns_print_pathname(u32 num_segments, const char *pathname)
 {
 	u32 i;
 
@@ -114,6 +114,9 @@ void acpi_ns_print_pathname(u32 num_segm
 	acpi_os_printf("]\n");
 }
 
+#ifdef ACPI_OBSOLETE_FUNCTIONS
+/* Not used at this time, perhaps later */
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ns_dump_pathname
@@ -131,7 +134,8 @@ void acpi_ns_print_pathname(u32 num_segm
  ******************************************************************************/
 
 void
-acpi_ns_dump_pathname(acpi_handle handle, char *msg, u32 level, u32 component)
+acpi_ns_dump_pathname(acpi_handle handle,
+		      const char *msg, u32 level, u32 component)
 {
 
 	ACPI_FUNCTION_TRACE(ns_dump_pathname);
@@ -148,6 +152,7 @@ acpi_ns_dump_pathname(acpi_handle handle
 	acpi_os_printf("\n");
 	return_VOID;
 }
+#endif
 
 /*******************************************************************************
  *
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/nsinit.c linux-libre-4.7-gnu/drivers/acpi/acpica/nsinit.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/nsinit.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/nsinit.c	2016-07-24 15:23:50.000000000 -0400
@@ -140,6 +140,7 @@ acpi_status acpi_ns_initialize_devices(u
 {
 	acpi_status status = AE_OK;
 	struct acpi_device_walk_info info;
+	acpi_handle handle;
 
 	ACPI_FUNCTION_TRACE(ns_initialize_devices);
 
@@ -190,6 +191,27 @@ acpi_status acpi_ns_initialize_devices(u
 		if (ACPI_SUCCESS(status)) {
 			info.num_INI++;
 		}
+
+		/*
+		 * Execute \_SB._INI.
+		 * There appears to be a strict order requirement for \_SB._INI,
+		 * which should be evaluated before any _REG evaluations.
+		 */
+		status = acpi_get_handle(NULL, "\\_SB", &handle);
+		if (ACPI_SUCCESS(status)) {
+			memset(info.evaluate_info, 0,
+			       sizeof(struct acpi_evaluate_info));
+			info.evaluate_info->prefix_node = handle;
+			info.evaluate_info->relative_pathname =
+			    METHOD_NAME__INI;
+			info.evaluate_info->parameters = NULL;
+			info.evaluate_info->flags = ACPI_IGNORE_RETURN_VALUE;
+
+			status = acpi_ns_evaluate(info.evaluate_info);
+			if (ACPI_SUCCESS(status)) {
+				info.num_INI++;
+			}
+		}
 	}
 
 	/*
@@ -198,6 +220,12 @@ acpi_status acpi_ns_initialize_devices(u
 	 * Note: Any objects accessed by the _REG methods will be automatically
 	 * initialized, even if they contain executable AML (see the call to
 	 * acpi_ns_initialize_objects below).
+	 *
+	 * Note: According to the ACPI specification, we actually needn't execute
+	 * _REG for system_memory/system_io operation regions, but for PCI_Config
+	 * operation regions, it is required to evaluate _REG for those on a PCI
+	 * root bus that doesn't contain _BBN object. So this code is kept here
+	 * in order not to break things.
 	 */
 	if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
 		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
@@ -592,33 +620,37 @@ acpi_ns_init_one_device(acpi_handle obj_
 	 * Note: We know there is an _INI within this subtree, but it may not be
 	 * under this particular device, it may be lower in the branch.
 	 */
-	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
-			(ACPI_TYPE_METHOD, device_node, METHOD_NAME__INI));
-
-	memset(info, 0, sizeof(struct acpi_evaluate_info));
-	info->prefix_node = device_node;
-	info->relative_pathname = METHOD_NAME__INI;
-	info->parameters = NULL;
-	info->flags = ACPI_IGNORE_RETURN_VALUE;
+	if (!ACPI_COMPARE_NAME(device_node->name.ascii, "_SB_") ||
+	    device_node->parent != acpi_gbl_root_node) {
+		ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
+				(ACPI_TYPE_METHOD, device_node,
+				 METHOD_NAME__INI));
 
-	status = acpi_ns_evaluate(info);
+		memset(info, 0, sizeof(struct acpi_evaluate_info));
+		info->prefix_node = device_node;
+		info->relative_pathname = METHOD_NAME__INI;
+		info->parameters = NULL;
+		info->flags = ACPI_IGNORE_RETURN_VALUE;
 
-	if (ACPI_SUCCESS(status)) {
-		walk_info->num_INI++;
-	}
+		status = acpi_ns_evaluate(info);
+		if (ACPI_SUCCESS(status)) {
+			walk_info->num_INI++;
+		}
 #ifdef ACPI_DEBUG_OUTPUT
-	else if (status != AE_NOT_FOUND) {
+		else if (status != AE_NOT_FOUND) {
 
-		/* Ignore error and move on to next device */
+			/* Ignore error and move on to next device */
 
-		char *scope_name =
-		    acpi_ns_get_normalized_pathname(device_node, TRUE);
+			char *scope_name =
+			    acpi_ns_get_normalized_pathname(device_node, TRUE);
 
-		ACPI_EXCEPTION((AE_INFO, status, "during %s._INI execution",
-				scope_name));
-		ACPI_FREE(scope_name);
-	}
+			ACPI_EXCEPTION((AE_INFO, status,
+					"during %s._INI execution",
+					scope_name));
+			ACPI_FREE(scope_name);
+		}
 #endif
+	}
 
 	/* Ignore errors from above */
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/nsload.c linux-libre-4.7-gnu/drivers/acpi/acpica/nsload.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/nsload.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/nsload.c	2016-07-24 15:23:50.000000000 -0400
@@ -123,8 +123,8 @@ acpi_ns_load_table(u32 table_index, stru
 		(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 		acpi_ns_delete_namespace_by_owner(acpi_gbl_root_table_list.
 						  tables[table_index].owner_id);
-		acpi_tb_release_owner_id(table_index);
 
+		acpi_tb_release_owner_id(table_index);
 		return_ACPI_STATUS(status);
 	}
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/nsnames.c linux-libre-4.7-gnu/drivers/acpi/acpica/nsnames.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/nsnames.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/nsnames.c	2016-07-24 15:23:50.000000000 -0400
@@ -113,7 +113,7 @@ acpi_size acpi_ns_get_pathname_length(st
 
 acpi_status
 acpi_ns_handle_to_pathname(acpi_handle target_handle,
-			   struct acpi_buffer * buffer, u8 no_trailing)
+			   struct acpi_buffer *buffer, u8 no_trailing)
 {
 	acpi_status status;
 	struct acpi_namespace_node *node;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/nsobject.c linux-libre-4.7-gnu/drivers/acpi/acpica/nsobject.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/nsobject.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/nsobject.c	2016-07-24 15:23:50.000000000 -0400
@@ -399,7 +399,7 @@ acpi_ns_attach_data(struct acpi_namespac
  ******************************************************************************/
 
 acpi_status
-acpi_ns_detach_data(struct acpi_namespace_node * node,
+acpi_ns_detach_data(struct acpi_namespace_node *node,
 		    acpi_object_handler handler)
 {
 	union acpi_operand_object *obj_desc;
@@ -444,7 +444,7 @@ acpi_ns_detach_data(struct acpi_namespac
  ******************************************************************************/
 
 acpi_status
-acpi_ns_get_attached_data(struct acpi_namespace_node * node,
+acpi_ns_get_attached_data(struct acpi_namespace_node *node,
 			  acpi_object_handler handler, void **data)
 {
 	union acpi_operand_object *obj_desc;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/nsprepkg.c linux-libre-4.7-gnu/drivers/acpi/acpica/nsprepkg.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/nsprepkg.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/nsprepkg.c	2016-07-24 15:23:50.000000000 -0400
@@ -62,6 +62,10 @@ acpi_ns_check_package_elements(struct ac
 			       u32 count1,
 			       u8 type2, u32 count2, u32 start_index);
 
+static acpi_status
+acpi_ns_custom_package(struct acpi_evaluate_info *info,
+		       union acpi_operand_object **elements, u32 count);
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ns_check_package
@@ -135,6 +139,11 @@ acpi_ns_check_package(struct acpi_evalua
 	 * PTYPE2 packages contain subpackages
 	 */
 	switch (package->ret_info.type) {
+	case ACPI_PTYPE_CUSTOM:
+
+		status = acpi_ns_custom_package(info, elements, count);
+		break;
+
 	case ACPI_PTYPE1_FIXED:
 		/*
 		 * The package count is fixed and there are no subpackages
@@ -179,6 +188,7 @@ acpi_ns_check_package(struct acpi_evalua
 			if (ACPI_FAILURE(status)) {
 				return (status);
 			}
+
 			elements++;
 		}
 		break;
@@ -225,6 +235,7 @@ acpi_ns_check_package(struct acpi_evalua
 					return (status);
 				}
 			}
+
 			elements++;
 		}
 		break;
@@ -569,11 +580,13 @@ acpi_ns_check_package_list(struct acpi_e
 			if (sub_package->package.count < expected_count) {
 				goto package_too_small;
 			}
+
 			if (sub_package->package.count <
 			    package->ret_info.count1) {
 				expected_count = package->ret_info.count1;
 				goto package_too_small;
 			}
+
 			if (expected_count == 0) {
 				/*
 				 * Either the num_entries element was originally zero or it was
@@ -622,6 +635,83 @@ package_too_small:
 
 /*******************************************************************************
  *
+ * FUNCTION:    acpi_ns_custom_package
+ *
+ * PARAMETERS:  info                - Method execution information block
+ *              elements            - Pointer to the package elements array
+ *              count               - Element count for the package
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Check a returned package object for the correct count and
+ *              correct type of all sub-objects.
+ *
+ * NOTE: Currently used for the _BIX method only. When needed for two or more
+ * methods, probably a detect/dispatch mechanism will be required.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_ns_custom_package(struct acpi_evaluate_info *info,
+		       union acpi_operand_object **elements, u32 count)
+{
+	u32 expected_count;
+	u32 version;
+	acpi_status status = AE_OK;
+
+	ACPI_FUNCTION_NAME(ns_custom_package);
+
+	/* Get version number, must be Integer */
+
+	if ((*elements)->common.type != ACPI_TYPE_INTEGER) {
+		ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
+				      info->node_flags,
+				      "Return Package has invalid object type for version number"));
+		return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
+	}
+
+	version = (u32)(*elements)->integer.value;
+	expected_count = 21;	/* Version 1 */
+
+	if (version == 0) {
+		expected_count = 20;	/* Version 0 */
+	}
+
+	if (count < expected_count) {
+		ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
+				      info->node_flags,
+				      "Return Package is too small - found %u elements, expected %u",
+				      count, expected_count));
+		return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
+	} else if (count > expected_count) {
+		ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
+				  "%s: Return Package is larger than needed - "
+				  "found %u, expected %u\n",
+				  info->full_pathname, count, expected_count));
+	}
+
+	/* Validate all elements of the returned package */
+
+	status = acpi_ns_check_package_elements(info, elements,
+						ACPI_RTYPE_INTEGER, 16,
+						ACPI_RTYPE_STRING, 4, 0);
+	if (ACPI_FAILURE(status)) {
+		return_ACPI_STATUS(status);
+	}
+
+	/* Version 1 has a single trailing integer */
+
+	if (version > 0) {
+		status = acpi_ns_check_package_elements(info, elements + 20,
+							ACPI_RTYPE_INTEGER, 1,
+							0, 0, 20);
+	}
+
+	return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
  * FUNCTION:    acpi_ns_check_package_elements
  *
  * PARAMETERS:  info            - Method execution information block
@@ -661,6 +751,7 @@ acpi_ns_check_package_elements(struct ac
 		if (ACPI_FAILURE(status)) {
 			return (status);
 		}
+
 		this_element++;
 	}
 
@@ -671,6 +762,7 @@ acpi_ns_check_package_elements(struct ac
 		if (ACPI_FAILURE(status)) {
 			return (status);
 		}
+
 		this_element++;
 	}
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/nsrepair2.c linux-libre-4.7-gnu/drivers/acpi/acpica/nsrepair2.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/nsrepair2.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/nsrepair2.c	2016-07-24 15:23:50.000000000 -0400
@@ -54,9 +54,9 @@ ACPI_MODULE_NAME("nsrepair2")
  * be repaired on a per-name basis.
  */
 typedef
-acpi_status(*acpi_repair_function) (struct acpi_evaluate_info * info,
-				    union acpi_operand_object
-				    **return_object_ptr);
+acpi_status (*acpi_repair_function) (struct acpi_evaluate_info * info,
+				     union acpi_operand_object **
+				     return_object_ptr);
 
 typedef struct acpi_repair_info {
 	char name[ACPI_NAME_SIZE];
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/nsrepair.c linux-libre-4.7-gnu/drivers/acpi/acpica/nsrepair.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/nsrepair.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/nsrepair.c	2016-07-24 15:23:50.000000000 -0400
@@ -399,7 +399,7 @@ static const struct acpi_simple_repair_i
  ******************************************************************************/
 
 acpi_status
-acpi_ns_repair_null_element(struct acpi_evaluate_info * info,
+acpi_ns_repair_null_element(struct acpi_evaluate_info *info,
 			    u32 expected_btypes,
 			    u32 package_index,
 			    union acpi_operand_object **return_object_ptr)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/nsutils.c linux-libre-4.7-gnu/drivers/acpi/acpica/nsutils.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/nsutils.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/nsutils.c	2016-07-24 15:23:50.000000000 -0400
@@ -272,11 +272,11 @@ acpi_status acpi_ns_build_internal_name(
 			result = &internal_name[i];
 		} else if (num_segments == 2) {
 			internal_name[i] = AML_DUAL_NAME_PREFIX;
-			result = &internal_name[(acpi_size) i + 1];
+			result = &internal_name[(acpi_size)i + 1];
 		} else {
 			internal_name[i] = AML_MULTI_NAME_PREFIX_OP;
-			internal_name[(acpi_size) i + 1] = (char)num_segments;
-			result = &internal_name[(acpi_size) i + 2];
+			internal_name[(acpi_size)i + 1] = (char)num_segments;
+			result = &internal_name[(acpi_size)i + 2];
 		}
 	}
 
@@ -456,7 +456,7 @@ acpi_ns_externalize_name(u32 internal_na
 
 			names_index = prefix_length + 2;
 			num_segments = (u8)
-			    internal_name[(acpi_size) prefix_length + 1];
+			    internal_name[(acpi_size)prefix_length + 1];
 			break;
 
 		case AML_DUAL_NAME_PREFIX:
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/nsxfeval.c linux-libre-4.7-gnu/drivers/acpi/acpica/nsxfeval.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/nsxfeval.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/nsxfeval.c	2016-07-24 15:23:50.000000000 -0400
@@ -256,7 +256,7 @@ acpi_evaluate_object(acpi_handle handle,
 		 * Allocate a new parameter block for the internal objects
 		 * Add 1 to count to allow for null terminated internal list
 		 */
-		info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size) info->
+		info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size)info->
 							 param_count +
 							 1) * sizeof(void *));
 		if (!info->parameters) {
@@ -280,13 +280,12 @@ acpi_evaluate_object(acpi_handle handle,
 		info->parameters[info->param_count] = NULL;
 	}
 
-#if 0
+#ifdef _FUTURE_FEATURE
 
 	/*
 	 * Begin incoming argument count analysis. Check for too few args
 	 * and too many args.
 	 */
-
 	switch (acpi_ns_get_type(info->node)) {
 	case ACPI_TYPE_METHOD:
 
@@ -370,68 +369,68 @@ acpi_evaluate_object(acpi_handle handle,
 	 * If we are expecting a return value, and all went well above,
 	 * copy the return value to an external object.
 	 */
-	if (return_buffer) {
-		if (!info->return_object) {
-			return_buffer->length = 0;
-		} else {
-			if (ACPI_GET_DESCRIPTOR_TYPE(info->return_object) ==
-			    ACPI_DESC_TYPE_NAMED) {
-				/*
-				 * If we received a NS Node as a return object, this means that
-				 * the object we are evaluating has nothing interesting to
-				 * return (such as a mutex, etc.)  We return an error because
-				 * these types are essentially unsupported by this interface.
-				 * We don't check up front because this makes it easier to add
-				 * support for various types at a later date if necessary.
-				 */
-				status = AE_TYPE;
-				info->return_object = NULL;	/* No need to delete a NS Node */
-				return_buffer->length = 0;
-			}
+	if (!return_buffer) {
+		goto cleanup_return_object;
+	}
 
-			if (ACPI_SUCCESS(status)) {
+	if (!info->return_object) {
+		return_buffer->length = 0;
+		goto cleanup;
+	}
 
-				/* Dereference Index and ref_of references */
+	if (ACPI_GET_DESCRIPTOR_TYPE(info->return_object) ==
+	    ACPI_DESC_TYPE_NAMED) {
+		/*
+		 * If we received a NS Node as a return object, this means that
+		 * the object we are evaluating has nothing interesting to
+		 * return (such as a mutex, etc.)  We return an error because
+		 * these types are essentially unsupported by this interface.
+		 * We don't check up front because this makes it easier to add
+		 * support for various types at a later date if necessary.
+		 */
+		status = AE_TYPE;
+		info->return_object = NULL;	/* No need to delete a NS Node */
+		return_buffer->length = 0;
+	}
 
-				acpi_ns_resolve_references(info);
+	if (ACPI_FAILURE(status)) {
+		goto cleanup_return_object;
+	}
 
-				/* Get the size of the returned object */
+	/* Dereference Index and ref_of references */
 
-				status =
-				    acpi_ut_get_object_size(info->return_object,
-							    &buffer_space_needed);
-				if (ACPI_SUCCESS(status)) {
+	acpi_ns_resolve_references(info);
 
-					/* Validate/Allocate/Clear caller buffer */
+	/* Get the size of the returned object */
 
-					status =
-					    acpi_ut_initialize_buffer
-					    (return_buffer,
-					     buffer_space_needed);
-					if (ACPI_FAILURE(status)) {
-						/*
-						 * Caller's buffer is too small or a new one can't
-						 * be allocated
-						 */
-						ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-								  "Needed buffer size %X, %s\n",
-								  (u32)
-								  buffer_space_needed,
-								  acpi_format_exception
-								  (status)));
-					} else {
-						/* We have enough space for the object, build it */
+	status = acpi_ut_get_object_size(info->return_object,
+					 &buffer_space_needed);
+	if (ACPI_SUCCESS(status)) {
 
-						status =
-						    acpi_ut_copy_iobject_to_eobject
-						    (info->return_object,
-						     return_buffer);
-					}
-				}
-			}
+		/* Validate/Allocate/Clear caller buffer */
+
+		status = acpi_ut_initialize_buffer(return_buffer,
+						   buffer_space_needed);
+		if (ACPI_FAILURE(status)) {
+			/*
+			 * Caller's buffer is too small or a new one can't
+			 * be allocated
+			 */
+			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+					  "Needed buffer size %X, %s\n",
+					  (u32)buffer_space_needed,
+					  acpi_format_exception(status)));
+		} else {
+			/* We have enough space for the object, build it */
+
+			status =
+			    acpi_ut_copy_iobject_to_eobject(info->return_object,
+							    return_buffer);
 		}
 	}
 
+cleanup_return_object:
+
 	if (info->return_object) {
 		/*
 		 * Delete the internal return object. NOTE: Interpreter must be
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/nsxfname.c linux-libre-4.7-gnu/drivers/acpi/acpica/nsxfname.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/nsxfname.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/nsxfname.c	2016-07-24 15:23:50.000000000 -0400
@@ -78,7 +78,7 @@ static char *acpi_ns_copy_device_id(stru
 
 acpi_status
 acpi_get_handle(acpi_handle parent,
-		acpi_string pathname, acpi_handle * ret_handle)
+		acpi_string pathname, acpi_handle *ret_handle)
 {
 	acpi_status status;
 	struct acpi_namespace_node *node = NULL;
@@ -155,7 +155,7 @@ ACPI_EXPORT_SYMBOL(acpi_get_handle)
  *
  ******************************************************************************/
 acpi_status
-acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer)
+acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer *buffer)
 {
 	acpi_status status;
 	struct acpi_namespace_node *node;
@@ -448,7 +448,7 @@ acpi_get_object_info(acpi_handle handle,
 		/* Point past the CID PNP_DEVICE_ID array */
 
 		next_id_string +=
-		    ((acpi_size) cid_list->count *
+		    ((acpi_size)cid_list->count *
 		     sizeof(struct acpi_pnp_device_id));
 	}
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/nsxfobj.c linux-libre-4.7-gnu/drivers/acpi/acpica/nsxfobj.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/nsxfobj.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/nsxfobj.c	2016-07-24 15:23:50.000000000 -0400
@@ -63,7 +63,7 @@ ACPI_MODULE_NAME("nsxfobj")
  * DESCRIPTION: This routine returns the type associatd with a particular handle
  *
  ******************************************************************************/
-acpi_status acpi_get_type(acpi_handle handle, acpi_object_type * ret_type)
+acpi_status acpi_get_type(acpi_handle handle, acpi_object_type *ret_type)
 {
 	struct acpi_namespace_node *node;
 	acpi_status status;
@@ -115,7 +115,7 @@ ACPI_EXPORT_SYMBOL(acpi_get_type)
  *              Handle.
  *
  ******************************************************************************/
-acpi_status acpi_get_parent(acpi_handle handle, acpi_handle * ret_handle)
+acpi_status acpi_get_parent(acpi_handle handle, acpi_handle *ret_handle)
 {
 	struct acpi_namespace_node *node;
 	struct acpi_namespace_node *parent_node;
@@ -183,7 +183,7 @@ ACPI_EXPORT_SYMBOL(acpi_get_parent)
 acpi_status
 acpi_get_next_object(acpi_object_type type,
 		     acpi_handle parent,
-		     acpi_handle child, acpi_handle * ret_handle)
+		     acpi_handle child, acpi_handle *ret_handle)
 {
 	acpi_status status;
 	struct acpi_namespace_node *node;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/psargs.c linux-libre-4.7-gnu/drivers/acpi/acpica/psargs.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/psargs.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/psargs.c	2016-07-24 15:23:50.000000000 -0400
@@ -87,7 +87,7 @@ acpi_ps_get_next_package_length(struct a
 	 * used to encode the package length, either 0,1,2, or 3
 	 */
 	byte_count = (aml[0] >> 6);
-	parser_state->aml += ((acpi_size) byte_count + 1);
+	parser_state->aml += ((acpi_size)byte_count + 1);
 
 	/* Get bytes 3, 2, 1 as needed */
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/psopinfo.c linux-libre-4.7-gnu/drivers/acpi/acpica/psopinfo.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/psopinfo.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/psopinfo.c	2016-07-24 15:23:50.000000000 -0400
@@ -158,7 +158,7 @@ const struct acpi_opcode_info *acpi_ps_g
  *
  ******************************************************************************/
 
-char *acpi_ps_get_opcode_name(u16 opcode)
+const char *acpi_ps_get_opcode_name(u16 opcode)
 {
 #if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUG_OUTPUT)
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/psparse.c linux-libre-4.7-gnu/drivers/acpi/acpica/psparse.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/psparse.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/psparse.c	2016-07-24 15:23:50.000000000 -0400
@@ -130,8 +130,8 @@ u16 acpi_ps_peek_opcode(struct acpi_pars
  ******************************************************************************/
 
 acpi_status
-acpi_ps_complete_this_op(struct acpi_walk_state * walk_state,
-			 union acpi_parse_object * op)
+acpi_ps_complete_this_op(struct acpi_walk_state *walk_state,
+			 union acpi_parse_object *op)
 {
 	union acpi_parse_object *prev;
 	union acpi_parse_object *next;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/psutils.c linux-libre-4.7-gnu/drivers/acpi/acpica/psutils.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/psutils.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/psutils.c	2016-07-24 15:23:50.000000000 -0400
@@ -128,7 +128,7 @@ union acpi_parse_object *acpi_ps_alloc_o
 	if (op_info->flags & AML_DEFER) {
 		flags = ACPI_PARSEOP_DEFERRED;
 	} else if (op_info->flags & AML_NAMED) {
-		flags = ACPI_PARSEOP_NAMED;
+		flags = ACPI_PARSEOP_NAMED_OBJECT;
 	} else if (opcode == AML_INT_BYTELIST_OP) {
 		flags = ACPI_PARSEOP_BYTELIST;
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/psxface.c linux-libre-4.7-gnu/drivers/acpi/acpica/psxface.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/psxface.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/psxface.c	2016-07-24 15:23:50.000000000 -0400
@@ -115,7 +115,7 @@ acpi_debug_trace(const char *name, u32 d
  *
  ******************************************************************************/
 
-acpi_status acpi_ps_execute_method(struct acpi_evaluate_info * info)
+acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info)
 {
 	acpi_status status;
 	union acpi_parse_object *op;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/rscalc.c linux-libre-4.7-gnu/drivers/acpi/acpica/rscalc.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/rscalc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/rscalc.c	2016-07-24 15:23:50.000000000 -0400
@@ -112,7 +112,7 @@ acpi_rs_struct_option_length(struct acpi
 	 * resource_source_index (1).
 	 */
 	if (resource_source->string_ptr) {
-		return ((acpi_rs_length) (resource_source->string_length + 1));
+		return ((acpi_rs_length)(resource_source->string_length + 1));
 	}
 
 	return (0);
@@ -188,7 +188,7 @@ acpi_rs_stream_option_length(u32 resourc
 
 acpi_status
 acpi_rs_get_aml_length(struct acpi_resource *resource,
-		       acpi_size resource_list_size, acpi_size * size_needed)
+		       acpi_size resource_list_size, acpi_size *size_needed)
 {
 	acpi_size aml_size_needed = 0;
 	struct acpi_resource *resource_end;
@@ -278,11 +278,11 @@ acpi_rs_get_aml_length(struct acpi_resou
 			 * 16-Bit Address Resource:
 			 * Add the size of the optional resource_source info
 			 */
-			total_size = (acpi_rs_length) (total_size +
-						       acpi_rs_struct_option_length
-						       (&resource->data.
-							address16.
-							resource_source));
+			total_size = (acpi_rs_length)(total_size +
+						      acpi_rs_struct_option_length
+						      (&resource->data.
+						       address16.
+						       resource_source));
 			break;
 
 		case ACPI_RESOURCE_TYPE_ADDRESS32:
@@ -290,11 +290,11 @@ acpi_rs_get_aml_length(struct acpi_resou
 			 * 32-Bit Address Resource:
 			 * Add the size of the optional resource_source info
 			 */
-			total_size = (acpi_rs_length) (total_size +
-						       acpi_rs_struct_option_length
-						       (&resource->data.
-							address32.
-							resource_source));
+			total_size = (acpi_rs_length)(total_size +
+						      acpi_rs_struct_option_length
+						      (&resource->data.
+						       address32.
+						       resource_source));
 			break;
 
 		case ACPI_RESOURCE_TYPE_ADDRESS64:
@@ -302,11 +302,11 @@ acpi_rs_get_aml_length(struct acpi_resou
 			 * 64-Bit Address Resource:
 			 * Add the size of the optional resource_source info
 			 */
-			total_size = (acpi_rs_length) (total_size +
-						       acpi_rs_struct_option_length
-						       (&resource->data.
-							address64.
-							resource_source));
+			total_size = (acpi_rs_length)(total_size +
+						      acpi_rs_struct_option_length
+						      (&resource->data.
+						       address64.
+						       resource_source));
 			break;
 
 		case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
@@ -315,28 +315,28 @@ acpi_rs_get_aml_length(struct acpi_resou
 			 * Add the size of each additional optional interrupt beyond the
 			 * required 1 (4 bytes for each u32 interrupt number)
 			 */
-			total_size = (acpi_rs_length) (total_size +
-						       ((resource->data.
-							 extended_irq.
-							 interrupt_count -
-							 1) * 4) +
-						       /* Add the size of the optional resource_source info */
-						       acpi_rs_struct_option_length
-						       (&resource->data.
+			total_size = (acpi_rs_length)(total_size +
+						      ((resource->data.
 							extended_irq.
-							resource_source));
+							interrupt_count -
+							1) * 4) +
+						      /* Add the size of the optional resource_source info */
+						      acpi_rs_struct_option_length
+						      (&resource->data.
+						       extended_irq.
+						       resource_source));
 			break;
 
 		case ACPI_RESOURCE_TYPE_GPIO:
 
-			total_size = (acpi_rs_length) (total_size +
-						       (resource->data.gpio.
-							pin_table_length * 2) +
-						       resource->data.gpio.
-						       resource_source.
-						       string_length +
-						       resource->data.gpio.
-						       vendor_length);
+			total_size = (acpi_rs_length)(total_size +
+						      (resource->data.gpio.
+						       pin_table_length * 2) +
+						      resource->data.gpio.
+						      resource_source.
+						      string_length +
+						      resource->data.gpio.
+						      vendor_length);
 
 			break;
 
@@ -348,14 +348,14 @@ acpi_rs_get_aml_length(struct acpi_resou
 								   common_serial_bus.
 								   type];
 
-			total_size = (acpi_rs_length) (total_size +
-						       resource->data.
-						       i2c_serial_bus.
-						       resource_source.
-						       string_length +
-						       resource->data.
-						       i2c_serial_bus.
-						       vendor_length);
+			total_size = (acpi_rs_length)(total_size +
+						      resource->data.
+						      i2c_serial_bus.
+						      resource_source.
+						      string_length +
+						      resource->data.
+						      i2c_serial_bus.
+						      vendor_length);
 
 			break;
 
@@ -397,8 +397,8 @@ acpi_rs_get_aml_length(struct acpi_resou
  ******************************************************************************/
 
 acpi_status
-acpi_rs_get_list_length(u8 * aml_buffer,
-			u32 aml_buffer_length, acpi_size * size_needed)
+acpi_rs_get_list_length(u8 *aml_buffer,
+			u32 aml_buffer_length, acpi_size *size_needed)
 {
 	acpi_status status;
 	u8 *end_aml;
@@ -610,7 +610,7 @@ acpi_rs_get_list_length(u8 * aml_buffer,
 
 acpi_status
 acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object,
-				     acpi_size * buffer_size_needed)
+				     acpi_size *buffer_size_needed)
 {
 	u32 number_of_elements;
 	acpi_size temp_size_needed = 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/rscreate.c linux-libre-4.7-gnu/drivers/acpi/acpica/rscreate.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/rscreate.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/rscreate.c	2016-07-24 15:23:50.000000000 -0400
@@ -347,7 +347,7 @@ acpi_rs_create_pci_routing_table(union a
 					   (u8 *) output_buffer->pointer);
 				path_buffer.pointer = user_prt->source;
 
-				status = acpi_ns_handle_to_pathname((acpi_handle) node, &path_buffer, FALSE);
+				status = acpi_ns_handle_to_pathname((acpi_handle)node, &path_buffer, FALSE);
 
 				/* +1 to include null terminator */
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/rsdump.c linux-libre-4.7-gnu/drivers/acpi/acpica/rsdump.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/rsdump.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/rsdump.c	2016-07-24 15:23:50.000000000 -0400
@@ -52,17 +52,17 @@ ACPI_MODULE_NAME("rsdump")
  * All functions in this module are used by the AML Debugger only
  */
 /* Local prototypes */
-static void acpi_rs_out_string(char *title, char *value);
+static void acpi_rs_out_string(const char *title, const char *value);
 
-static void acpi_rs_out_integer8(char *title, u8 value);
+static void acpi_rs_out_integer8(const char *title, u8 value);
 
-static void acpi_rs_out_integer16(char *title, u16 value);
+static void acpi_rs_out_integer16(const char *title, u16 value);
 
-static void acpi_rs_out_integer32(char *title, u32 value);
+static void acpi_rs_out_integer32(const char *title, u32 value);
 
-static void acpi_rs_out_integer64(char *title, u64 value);
+static void acpi_rs_out_integer64(const char *title, u64 value);
 
-static void acpi_rs_out_title(char *title);
+static void acpi_rs_out_title(const char *title);
 
 static void acpi_rs_dump_byte_list(u16 length, u8 *data);
 
@@ -208,7 +208,7 @@ acpi_rs_dump_descriptor(void *resource,
 {
 	u8 *target = NULL;
 	u8 *previous_target;
-	char *name;
+	const char *name;
 	u8 count;
 
 	/* First table entry must contain the table length (# of table entries) */
@@ -248,10 +248,8 @@ acpi_rs_dump_descriptor(void *resource,
 		case ACPI_RSD_UINT8:
 
 			if (table->pointer) {
-				acpi_rs_out_string(name, ACPI_CAST_PTR(char,
-								       table->
-								       pointer
-								       [*target]));
+				acpi_rs_out_string(name,
+						   table->pointer[*target]);
 			} else {
 				acpi_rs_out_integer8(name, ACPI_GET8(target));
 			}
@@ -276,26 +274,20 @@ acpi_rs_dump_descriptor(void *resource,
 
 		case ACPI_RSD_1BITFLAG:
 
-			acpi_rs_out_string(name, ACPI_CAST_PTR(char,
-							       table->
-							       pointer[*target &
-								       0x01]));
+			acpi_rs_out_string(name,
+					   table->pointer[*target & 0x01]);
 			break;
 
 		case ACPI_RSD_2BITFLAG:
 
-			acpi_rs_out_string(name, ACPI_CAST_PTR(char,
-							       table->
-							       pointer[*target &
-								       0x03]));
+			acpi_rs_out_string(name,
+					   table->pointer[*target & 0x03]);
 			break;
 
 		case ACPI_RSD_3BITFLAG:
 
-			acpi_rs_out_string(name, ACPI_CAST_PTR(char,
-							       table->
-							       pointer[*target &
-								       0x07]));
+			acpi_rs_out_string(name,
+					   table->pointer[*target & 0x07]);
 			break;
 
 		case ACPI_RSD_SHORTLIST:
@@ -481,7 +473,7 @@ static void acpi_rs_dump_address_common(
  *
  ******************************************************************************/
 
-static void acpi_rs_out_string(char *title, char *value)
+static void acpi_rs_out_string(const char *title, const char *value)
 {
 
 	acpi_os_printf("%27s : %s", title, value);
@@ -491,30 +483,30 @@ static void acpi_rs_out_string(char *tit
 	acpi_os_printf("\n");
 }
 
-static void acpi_rs_out_integer8(char *title, u8 value)
+static void acpi_rs_out_integer8(const char *title, u8 value)
 {
 	acpi_os_printf("%27s : %2.2X\n", title, value);
 }
 
-static void acpi_rs_out_integer16(char *title, u16 value)
+static void acpi_rs_out_integer16(const char *title, u16 value)
 {
 
 	acpi_os_printf("%27s : %4.4X\n", title, value);
 }
 
-static void acpi_rs_out_integer32(char *title, u32 value)
+static void acpi_rs_out_integer32(const char *title, u32 value)
 {
 
 	acpi_os_printf("%27s : %8.8X\n", title, value);
 }
 
-static void acpi_rs_out_integer64(char *title, u64 value)
+static void acpi_rs_out_integer64(const char *title, u64 value)
 {
 
 	acpi_os_printf("%27s : %8.8X%8.8X\n", title, ACPI_FORMAT_UINT64(value));
 }
 
-static void acpi_rs_out_title(char *title)
+static void acpi_rs_out_title(const char *title)
 {
 
 	acpi_os_printf("%27s : ", title);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/rsdumpinfo.c linux-libre-4.7-gnu/drivers/acpi/acpica/rsdumpinfo.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/rsdumpinfo.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/rsdumpinfo.c	2016-07-24 15:23:50.000000000 -0400
@@ -330,19 +330,20 @@ struct acpi_rsdump_info acpi_rs_dump_fix
 	{ACPI_RSD_UINT8,    ACPI_RSD_OFFSET (common_serial_bus.type),           "Type",                     acpi_gbl_sbt_decode}, \
 	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (common_serial_bus.producer_consumer), "ProducerConsumer",      acpi_gbl_consume_decode}, \
 	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (common_serial_bus.slave_mode),     "SlaveMode",                acpi_gbl_sm_decode}, \
+	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (common_serial_bus.connection_sharing),"ConnectionSharing",     acpi_gbl_shr_decode}, \
 	{ACPI_RSD_UINT8,    ACPI_RSD_OFFSET (common_serial_bus.type_revision_id), "TypeRevisionId",         NULL}, \
 	{ACPI_RSD_UINT16,   ACPI_RSD_OFFSET (common_serial_bus.type_data_length), "TypeDataLength",         NULL}, \
 	{ACPI_RSD_SOURCE,   ACPI_RSD_OFFSET (common_serial_bus.resource_source), "ResourceSource",          NULL}, \
 	{ACPI_RSD_UINT16,   ACPI_RSD_OFFSET (common_serial_bus.vendor_length),  "VendorLength",             NULL}, \
 	{ACPI_RSD_SHORTLISTX,ACPI_RSD_OFFSET (common_serial_bus.vendor_data),   "VendorData",               NULL},
 
-struct acpi_rsdump_info acpi_rs_dump_common_serial_bus[10] = {
+struct acpi_rsdump_info acpi_rs_dump_common_serial_bus[11] = {
 	{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_common_serial_bus),
 	 "Common Serial Bus", NULL},
 	ACPI_RS_DUMP_COMMON_SERIAL_BUS
 };
 
-struct acpi_rsdump_info acpi_rs_dump_i2c_serial_bus[13] = {
+struct acpi_rsdump_info acpi_rs_dump_i2c_serial_bus[14] = {
 	{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_i2c_serial_bus),
 	 "I2C Serial Bus", NULL},
 	ACPI_RS_DUMP_COMMON_SERIAL_BUS {ACPI_RSD_1BITFLAG,
@@ -355,7 +356,7 @@ struct acpi_rsdump_info acpi_rs_dump_i2c
 	 "SlaveAddress", NULL},
 };
 
-struct acpi_rsdump_info acpi_rs_dump_spi_serial_bus[17] = {
+struct acpi_rsdump_info acpi_rs_dump_spi_serial_bus[18] = {
 	{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_spi_serial_bus),
 	 "Spi Serial Bus", NULL},
 	ACPI_RS_DUMP_COMMON_SERIAL_BUS {ACPI_RSD_1BITFLAG,
@@ -376,7 +377,7 @@ struct acpi_rsdump_info acpi_rs_dump_spi
 	 "ConnectionSpeed", NULL},
 };
 
-struct acpi_rsdump_info acpi_rs_dump_uart_serial_bus[19] = {
+struct acpi_rsdump_info acpi_rs_dump_uart_serial_bus[20] = {
 	{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_uart_serial_bus),
 	 "Uart Serial Bus", NULL},
 	ACPI_RS_DUMP_COMMON_SERIAL_BUS {ACPI_RSD_2BITFLAG,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/rsmisc.c linux-libre-4.7-gnu/drivers/acpi/acpica/rsmisc.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/rsmisc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/rsmisc.c	2016-07-24 15:23:50.000000000 -0400
@@ -87,7 +87,7 @@ acpi_rs_convert_aml_to_resource(struct a
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
 	}
 
-	if (((acpi_size) resource) & 0x3) {
+	if (((acpi_size)resource) & 0x3) {
 
 		/* Each internal resource struct is expected to be 32-bit aligned */
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/rsserial.c linux-libre-4.7-gnu/drivers/acpi/acpica/rsserial.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/rsserial.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/rsserial.c	2016-07-24 15:23:50.000000000 -0400
@@ -151,7 +151,7 @@ struct acpi_rsconvert_info acpi_rs_conve
  *
  ******************************************************************************/
 
-struct acpi_rsconvert_info acpi_rs_convert_i2c_serial_bus[16] = {
+struct acpi_rsconvert_info acpi_rs_convert_i2c_serial_bus[17] = {
 	{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_SERIAL_BUS,
 	 ACPI_RS_SIZE(struct acpi_resource_i2c_serialbus),
 	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_i2c_serial_bus)},
@@ -177,6 +177,11 @@ struct acpi_rsconvert_info acpi_rs_conve
 	 AML_OFFSET(common_serial_bus.flags),
 	 1},
 
+	{ACPI_RSC_1BITFLAG,
+	 ACPI_RS_OFFSET(data.common_serial_bus.connection_sharing),
+	 AML_OFFSET(common_serial_bus.flags),
+	 2},
+
 	{ACPI_RSC_MOVE8,
 	 ACPI_RS_OFFSET(data.common_serial_bus.type_revision_id),
 	 AML_OFFSET(common_serial_bus.type_revision_id),
@@ -237,7 +242,7 @@ struct acpi_rsconvert_info acpi_rs_conve
  *
  ******************************************************************************/
 
-struct acpi_rsconvert_info acpi_rs_convert_spi_serial_bus[20] = {
+struct acpi_rsconvert_info acpi_rs_convert_spi_serial_bus[21] = {
 	{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_SERIAL_BUS,
 	 ACPI_RS_SIZE(struct acpi_resource_spi_serialbus),
 	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_spi_serial_bus)},
@@ -263,6 +268,11 @@ struct acpi_rsconvert_info acpi_rs_conve
 	 AML_OFFSET(common_serial_bus.flags),
 	 1},
 
+	{ACPI_RSC_1BITFLAG,
+	 ACPI_RS_OFFSET(data.common_serial_bus.connection_sharing),
+	 AML_OFFSET(common_serial_bus.flags),
+	 2},
+
 	{ACPI_RSC_MOVE8,
 	 ACPI_RS_OFFSET(data.common_serial_bus.type_revision_id),
 	 AML_OFFSET(common_serial_bus.type_revision_id),
@@ -339,7 +349,7 @@ struct acpi_rsconvert_info acpi_rs_conve
  *
  ******************************************************************************/
 
-struct acpi_rsconvert_info acpi_rs_convert_uart_serial_bus[22] = {
+struct acpi_rsconvert_info acpi_rs_convert_uart_serial_bus[23] = {
 	{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_SERIAL_BUS,
 	 ACPI_RS_SIZE(struct acpi_resource_uart_serialbus),
 	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_uart_serial_bus)},
@@ -365,6 +375,11 @@ struct acpi_rsconvert_info acpi_rs_conve
 	 AML_OFFSET(common_serial_bus.flags),
 	 1},
 
+	{ACPI_RSC_1BITFLAG,
+	 ACPI_RS_OFFSET(data.common_serial_bus.connection_sharing),
+	 AML_OFFSET(common_serial_bus.flags),
+	 2},
+
 	{ACPI_RSC_MOVE8,
 	 ACPI_RS_OFFSET(data.common_serial_bus.type_revision_id),
 	 AML_OFFSET(common_serial_bus.type_revision_id),
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/rsutils.c linux-libre-4.7-gnu/drivers/acpi/acpica/rsutils.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/rsutils.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/rsutils.c	2016-07-24 15:23:50.000000000 -0400
@@ -338,7 +338,7 @@ acpi_rs_get_resource_source(acpi_rs_leng
 	 * Note: Some resource descriptors will have an additional null, so
 	 * we add 1 to the minimum length.
 	 */
-	if (total_length > (acpi_rsdesc_size) (minimum_length + 1)) {
+	if (total_length > (acpi_rsdesc_size)(minimum_length + 1)) {
 
 		/* Get the resource_source_index */
 
@@ -377,7 +377,7 @@ acpi_rs_get_resource_source(acpi_rs_leng
 				   ACPI_CAST_PTR(char,
 						 &aml_resource_source[1]));
 
-		return ((acpi_rs_length) total_length);
+		return ((acpi_rs_length)total_length);
 	}
 
 	/* resource_source is not present */
@@ -406,9 +406,9 @@ acpi_rs_get_resource_source(acpi_rs_leng
  ******************************************************************************/
 
 acpi_rsdesc_size
-acpi_rs_set_resource_source(union aml_resource * aml,
+acpi_rs_set_resource_source(union aml_resource *aml,
 			    acpi_rs_length minimum_length,
-			    struct acpi_resource_source * resource_source)
+			    struct acpi_resource_source *resource_source)
 {
 	u8 *aml_resource_source;
 	acpi_rsdesc_size descriptor_length;
@@ -466,8 +466,8 @@ acpi_rs_set_resource_source(union aml_re
  ******************************************************************************/
 
 acpi_status
-acpi_rs_get_prt_method_data(struct acpi_namespace_node * node,
-			    struct acpi_buffer * ret_buffer)
+acpi_rs_get_prt_method_data(struct acpi_namespace_node *node,
+			    struct acpi_buffer *ret_buffer)
 {
 	union acpi_operand_object *obj_desc;
 	acpi_status status;
@@ -671,7 +671,7 @@ acpi_rs_get_aei_method_data(struct acpi_
 
 acpi_status
 acpi_rs_get_method_data(acpi_handle handle,
-			char *path, struct acpi_buffer *ret_buffer)
+			const char *path, struct acpi_buffer *ret_buffer)
 {
 	union acpi_operand_object *obj_desc;
 	acpi_status status;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/rsxface.c linux-libre-4.7-gnu/drivers/acpi/acpica/rsxface.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/rsxface.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/rsxface.c	2016-07-24 15:23:50.000000000 -0400
@@ -433,8 +433,8 @@ ACPI_EXPORT_SYMBOL(acpi_resource_to_addr
 acpi_status
 acpi_get_vendor_resource(acpi_handle device_handle,
 			 char *name,
-			 struct acpi_vendor_uuid * uuid,
-			 struct acpi_buffer * ret_buffer)
+			 struct acpi_vendor_uuid *uuid,
+			 struct acpi_buffer *ret_buffer)
 {
 	struct acpi_vendor_walk_info info;
 	acpi_status status;
@@ -539,7 +539,7 @@ acpi_rs_match_vendor_resource(struct acp
  ******************************************************************************/
 
 acpi_status
-acpi_walk_resource_buffer(struct acpi_buffer * buffer,
+acpi_walk_resource_buffer(struct acpi_buffer *buffer,
 			  acpi_walk_resource_callback user_function,
 			  void *context)
 {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/tbdata.c linux-libre-4.7-gnu/drivers/acpi/acpica/tbdata.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/tbdata.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/tbdata.c	2016-07-24 15:23:50.000000000 -0400
@@ -368,7 +368,7 @@ acpi_status acpi_tb_validate_temp_table(
  *****************************************************************************/
 
 acpi_status
-acpi_tb_verify_temp_table(struct acpi_table_desc * table_desc, char *signature)
+acpi_tb_verify_temp_table(struct acpi_table_desc *table_desc, char *signature)
 {
 	acpi_status status = AE_OK;
 
@@ -401,9 +401,9 @@ acpi_tb_verify_temp_table(struct acpi_ta
 			ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY,
 					"%4.4s 0x%8.8X%8.8X"
 					" Attempted table install failed",
-					acpi_ut_valid_acpi_name(table_desc->
-								signature.
-								ascii) ?
+					acpi_ut_valid_nameseg(table_desc->
+							      signature.
+							      ascii) ?
 					table_desc->signature.ascii : "????",
 					ACPI_FORMAT_UINT64(table_desc->
 							   address)));
@@ -454,7 +454,7 @@ acpi_status acpi_tb_resize_root_table_li
 		table_count = acpi_gbl_root_table_list.current_table_count;
 	}
 
-	tables = ACPI_ALLOCATE_ZEROED(((acpi_size) table_count +
+	tables = ACPI_ALLOCATE_ZEROED(((acpi_size)table_count +
 				       ACPI_ROOT_TABLE_SIZE_INCREMENT) *
 				      sizeof(struct acpi_table_desc));
 	if (!tables) {
@@ -467,8 +467,7 @@ acpi_status acpi_tb_resize_root_table_li
 
 	if (acpi_gbl_root_table_list.tables) {
 		memcpy(tables, acpi_gbl_root_table_list.tables,
-		       (acpi_size) table_count *
-		       sizeof(struct acpi_table_desc));
+		       (acpi_size)table_count * sizeof(struct acpi_table_desc));
 
 		if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
 			ACPI_FREE(acpi_gbl_root_table_list.tables);
@@ -701,7 +700,7 @@ acpi_status acpi_tb_release_owner_id(u32
  *
  ******************************************************************************/
 
-acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id * owner_id)
+acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id *owner_id)
 {
 	acpi_status status = AE_BAD_PARAMETER;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/tbfadt.c linux-libre-4.7-gnu/drivers/acpi/acpica/tbfadt.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/tbfadt.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/tbfadt.c	2016-07-24 15:23:50.000000000 -0400
@@ -53,7 +53,7 @@ static void
 acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
 			     u8 space_id,
 			     u8 byte_width,
-			     u64 address, char *register_name, u8 flags);
+			     u64 address, const char *register_name, u8 flags);
 
 static void acpi_tb_convert_fadt(void);
 
@@ -65,7 +65,7 @@ acpi_tb_select_address(char *register_na
 /* Table for conversion of FADT to common internal format and FADT validation */
 
 typedef struct acpi_fadt_info {
-	char *name;
+	const char *name;
 	u16 address64;
 	u16 address32;
 	u16 length;
@@ -192,7 +192,7 @@ static void
 acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
 			     u8 space_id,
 			     u8 byte_width,
-			     u64 address, char *register_name, u8 flags)
+			     u64 address, const char *register_name, u8 flags)
 {
 	u8 bit_width;
 
@@ -344,7 +344,7 @@ void acpi_tb_parse_fadt(void)
 
 	/* Obtain the DSDT and FACS tables via their addresses within the FADT */
 
-	acpi_tb_install_fixed_table((acpi_physical_address) acpi_gbl_FADT.Xdsdt,
+	acpi_tb_install_fixed_table((acpi_physical_address)acpi_gbl_FADT.Xdsdt,
 				    ACPI_SIG_DSDT, &acpi_gbl_dsdt_index);
 
 	/* If Hardware Reduced flag is set, there is no FACS */
@@ -385,14 +385,15 @@ void acpi_tb_create_local_fadt(struct ac
 {
 	/*
 	 * Check if the FADT is larger than the largest table that we expect
-	 * (the ACPI 5.0 version). If so, truncate the table, and issue
-	 * a warning.
+	 * (typically the current ACPI specification version). If so, truncate
+	 * the table, and issue a warning.
 	 */
 	if (length > sizeof(struct acpi_table_fadt)) {
 		ACPI_BIOS_WARNING((AE_INFO,
-				   "FADT (revision %u) is longer than ACPI 5.0 version, "
+				   "FADT (revision %u) is longer than %s length, "
 				   "truncating length %u to %u",
-				   table->revision, length,
+				   table->revision, ACPI_FADT_CONFORMANCE,
+				   length,
 				   (u32)sizeof(struct acpi_table_fadt)));
 	}
 
@@ -467,7 +468,7 @@ void acpi_tb_create_local_fadt(struct ac
 
 static void acpi_tb_convert_fadt(void)
 {
-	char *name;
+	const char *name;
 	struct acpi_generic_address *address64;
 	u32 address32;
 	u8 length;
@@ -646,9 +647,12 @@ static void acpi_tb_convert_fadt(void)
 			if ((address64->address && !length) ||
 			    (!address64->address && length)) {
 				ACPI_BIOS_WARNING((AE_INFO,
-						   "Optional FADT field %s has zero address or length: "
-						   "0x%8.8X%8.8X/0x%X",
-						   name,
+						   "Optional FADT field %s has valid %s but zero %s: "
+						   "0x%8.8X%8.8X/0x%X", name,
+						   (length ? "Length" :
+						    "Address"),
+						   (length ? "Address" :
+						    "Length"),
 						   ACPI_FORMAT_UINT64
 						   (address64->address),
 						   length));
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/tbfind.c linux-libre-4.7-gnu/drivers/acpi/acpica/tbfind.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/tbfind.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/tbfind.c	2016-07-24 15:23:50.000000000 -0400
@@ -76,7 +76,7 @@ acpi_tb_find_table(char *signature,
 
 	/* Validate the input table signature */
 
-	if (!acpi_is_valid_signature(signature)) {
+	if (!acpi_ut_valid_nameseg(signature)) {
 		return_ACPI_STATUS(AE_BAD_SIGNATURE);
 	}
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/tbinstal.c linux-libre-4.7-gnu/drivers/acpi/acpica/tbinstal.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/tbinstal.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/tbinstal.c	2016-07-24 15:23:50.000000000 -0400
@@ -299,9 +299,9 @@ acpi_tb_install_standard_table(acpi_phys
 			ACPI_BIOS_ERROR((AE_INFO,
 					 "Table has invalid signature [%4.4s] (0x%8.8X), "
 					 "must be SSDT or OEMx",
-					 acpi_ut_valid_acpi_name(new_table_desc.
-								 signature.
-								 ascii) ?
+					 acpi_ut_valid_nameseg(new_table_desc.
+							       signature.
+							       ascii) ?
 					 new_table_desc.signature.
 					 ascii : "????",
 					 new_table_desc.signature.integer));
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/tbutils.c linux-libre-4.7-gnu/drivers/acpi/acpica/tbutils.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/tbutils.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/tbutils.c	2016-07-24 15:23:50.000000000 -0400
@@ -231,7 +231,7 @@ acpi_tb_get_root_table_entry(u8 *table_e
 					   ACPI_FORMAT_UINT64(address64)));
 		}
 #endif
-		return ((acpi_physical_address) (address64));
+		return ((acpi_physical_address)(address64));
 	}
 }
 
@@ -287,12 +287,12 @@ acpi_status __init acpi_tb_parse_root_ta
 		 * the XSDT if the revision is > 1 and the XSDT pointer is present,
 		 * as per the ACPI specification.
 		 */
-		address = (acpi_physical_address) rsdp->xsdt_physical_address;
+		address = (acpi_physical_address)rsdp->xsdt_physical_address;
 		table_entry_size = ACPI_XSDT_ENTRY_SIZE;
 	} else {
 		/* Root table is an RSDT (32-bit physical addresses) */
 
-		address = (acpi_physical_address) rsdp->rsdt_physical_address;
+		address = (acpi_physical_address)rsdp->rsdt_physical_address;
 		table_entry_size = ACPI_RSDT_ENTRY_SIZE;
 	}
 
@@ -380,30 +380,3 @@ next_table:
 	acpi_os_unmap_memory(table, length);
 	return_ACPI_STATUS(AE_OK);
 }
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_is_valid_signature
- *
- * PARAMETERS:  signature           - Sig string to be validated
- *
- * RETURN:      TRUE if signature is has 4 valid ACPI characters
- *
- * DESCRIPTION: Validate an ACPI table signature.
- *
- ******************************************************************************/
-
-u8 acpi_is_valid_signature(char *signature)
-{
-	u32 i;
-
-	/* Validate each character in the signature */
-
-	for (i = 0; i < ACPI_NAME_SIZE; i++) {
-		if (!acpi_ut_valid_acpi_char(signature[i], i)) {
-			return (FALSE);
-		}
-	}
-
-	return (TRUE);
-}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/tbxface.c linux-libre-4.7-gnu/drivers/acpi/acpica/tbxface.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/tbxface.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/tbxface.c	2016-07-24 15:23:50.000000000 -0400
@@ -99,7 +99,7 @@ acpi_status acpi_allocate_root_table(u32
  ******************************************************************************/
 
 acpi_status __init
-acpi_initialize_tables(struct acpi_table_desc * initial_table_array,
+acpi_initialize_tables(struct acpi_table_desc *initial_table_array,
 		       u32 initial_table_count, u8 allow_resize)
 {
 	acpi_physical_address rsdp_address;
@@ -120,7 +120,7 @@ acpi_initialize_tables(struct acpi_table
 		/* Root Table Array has been statically allocated by the host */
 
 		memset(initial_table_array, 0,
-		       (acpi_size) initial_table_count *
+		       (acpi_size)initial_table_count *
 		       sizeof(struct acpi_table_desc));
 
 		acpi_gbl_root_table_list.tables = initial_table_array;
@@ -352,7 +352,7 @@ ACPI_EXPORT_SYMBOL(acpi_get_table)
  *
  ******************************************************************************/
 acpi_status
-acpi_get_table_by_index(u32 table_index, struct acpi_table_header ** table)
+acpi_get_table_by_index(u32 table_index, struct acpi_table_header **table)
 {
 	acpi_status status;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/tbxfload.c linux-libre-4.7-gnu/drivers/acpi/acpica/tbxfload.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/tbxfload.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/tbxfload.c	2016-07-24 15:23:50.000000000 -0400
@@ -82,7 +82,7 @@ acpi_status __init acpi_load_tables(void
 	 * their customized default region handlers.
 	 */
 	status = acpi_ev_install_region_handlers();
-	if (ACPI_FAILURE(status) && status != AE_ALREADY_EXISTS) {
+	if (ACPI_FAILURE(status)) {
 		ACPI_EXCEPTION((AE_INFO, status,
 				"During Region initialization"));
 		return_ACPI_STATUS(status);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/tbxfroot.c linux-libre-4.7-gnu/drivers/acpi/acpica/tbxfroot.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/tbxfroot.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/tbxfroot.c	2016-07-24 15:23:50.000000000 -0400
@@ -90,7 +90,7 @@ u32 acpi_tb_get_rsdp_length(struct acpi_
  *
  ******************************************************************************/
 
-acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp * rsdp)
+acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp)
 {
 
 	/*
@@ -142,7 +142,7 @@ acpi_status acpi_tb_validate_rsdp(struct
  *
  ******************************************************************************/
 
-acpi_status __init acpi_find_root_pointer(acpi_physical_address * table_address)
+acpi_status __init acpi_find_root_pointer(acpi_physical_address *table_address)
 {
 	u8 *table_ptr;
 	u8 *mem_rover;
@@ -201,7 +201,7 @@ acpi_status __init acpi_find_root_pointe
 			    (u32) ACPI_PTR_DIFF(mem_rover, table_ptr);
 
 			*table_address =
-			    (acpi_physical_address) physical_address;
+			    (acpi_physical_address)physical_address;
 			return_ACPI_STATUS(AE_OK);
 		}
 	}
@@ -234,7 +234,7 @@ acpi_status __init acpi_find_root_pointe
 		    (ACPI_HI_RSDP_WINDOW_BASE +
 		     ACPI_PTR_DIFF(mem_rover, table_ptr));
 
-		*table_address = (acpi_physical_address) physical_address;
+		*table_address = (acpi_physical_address)physical_address;
 		return_ACPI_STATUS(AE_OK);
 	}
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/utalloc.c linux-libre-4.7-gnu/drivers/acpi/acpica/utalloc.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/utalloc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/utalloc.c	2016-07-24 15:23:50.000000000 -0400
@@ -231,7 +231,7 @@ acpi_status acpi_ut_delete_caches(void)
  *
  ******************************************************************************/
 
-acpi_status acpi_ut_validate_buffer(struct acpi_buffer * buffer)
+acpi_status acpi_ut_validate_buffer(struct acpi_buffer *buffer)
 {
 
 	/* Obviously, the structure pointer must be valid */
@@ -272,8 +272,7 @@ acpi_status acpi_ut_validate_buffer(stru
  ******************************************************************************/
 
 acpi_status
-acpi_ut_initialize_buffer(struct acpi_buffer * buffer,
-			  acpi_size required_length)
+acpi_ut_initialize_buffer(struct acpi_buffer *buffer, acpi_size required_length)
 {
 	acpi_size input_buffer_length;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/utascii.c linux-libre-4.7-gnu/drivers/acpi/acpica/utascii.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/utascii.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/utascii.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,140 @@
+/******************************************************************************
+ *
+ * Module Name: utascii - Utility ascii functions
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2016, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    substantially similar to the "NO WARRANTY" disclaimer below
+ *    ("Disclaimer") and any redistribution must be conditioned upon
+ *    including a substantially similar Disclaimer requirement for further
+ *    binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_valid_nameseg
+ *
+ * PARAMETERS:  name            - The name or table signature to be examined.
+ *                                Four characters, does not have to be a
+ *                                NULL terminated string.
+ *
+ * RETURN:      TRUE if signature is has 4 valid ACPI characters
+ *
+ * DESCRIPTION: Validate an ACPI table signature.
+ *
+ ******************************************************************************/
+
+u8 acpi_ut_valid_nameseg(char *name)
+{
+	u32 i;
+
+	/* Validate each character in the signature */
+
+	for (i = 0; i < ACPI_NAME_SIZE; i++) {
+		if (!acpi_ut_valid_name_char(name[i], i)) {
+			return (FALSE);
+		}
+	}
+
+	return (TRUE);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_valid_name_char
+ *
+ * PARAMETERS:  char            - The character to be examined
+ *              position        - Byte position (0-3)
+ *
+ * RETURN:      TRUE if the character is valid, FALSE otherwise
+ *
+ * DESCRIPTION: Check for a valid ACPI character. Must be one of:
+ *              1) Upper case alpha
+ *              2) numeric
+ *              3) underscore
+ *
+ *              We allow a '!' as the last character because of the ASF! table
+ *
+ ******************************************************************************/
+
+u8 acpi_ut_valid_name_char(char character, u32 position)
+{
+
+	if (!((character >= 'A' && character <= 'Z') ||
+	      (character >= '0' && character <= '9') || (character == '_'))) {
+
+		/* Allow a '!' in the last position */
+
+		if (character == '!' && position == 3) {
+			return (TRUE);
+		}
+
+		return (FALSE);
+	}
+
+	return (TRUE);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_check_and_repair_ascii
+ *
+ * PARAMETERS:  name                - Ascii string
+ *              count               - Number of characters to check
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Ensure that the requested number of characters are printable
+ *              Ascii characters. Sets non-printable and null chars to <space>.
+ *
+ ******************************************************************************/
+
+void acpi_ut_check_and_repair_ascii(u8 *name, char *repaired_name, u32 count)
+{
+	u32 i;
+
+	for (i = 0; i < count; i++) {
+		repaired_name[i] = (char)name[i];
+
+		if (!name[i]) {
+			return;
+		}
+		if (!isprint(name[i])) {
+			repaired_name[i] = ' ';
+		}
+	}
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/utbuffer.c linux-libre-4.7-gnu/drivers/acpi/acpica/utbuffer.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/utbuffer.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/utbuffer.c	2016-07-24 15:23:50.000000000 -0400
@@ -106,31 +106,31 @@ void acpi_ut_dump_buffer(u8 *buffer, u32
 			default:	/* Default is BYTE display */
 
 				acpi_os_printf("%02X ",
-					       buffer[(acpi_size) i + j]);
+					       buffer[(acpi_size)i + j]);
 				break;
 
 			case DB_WORD_DISPLAY:
 
 				ACPI_MOVE_16_TO_32(&temp32,
-						   &buffer[(acpi_size) i + j]);
+						   &buffer[(acpi_size)i + j]);
 				acpi_os_printf("%04X ", temp32);
 				break;
 
 			case DB_DWORD_DISPLAY:
 
 				ACPI_MOVE_32_TO_32(&temp32,
-						   &buffer[(acpi_size) i + j]);
+						   &buffer[(acpi_size)i + j]);
 				acpi_os_printf("%08X ", temp32);
 				break;
 
 			case DB_QWORD_DISPLAY:
 
 				ACPI_MOVE_32_TO_32(&temp32,
-						   &buffer[(acpi_size) i + j]);
+						   &buffer[(acpi_size)i + j]);
 				acpi_os_printf("%08X", temp32);
 
 				ACPI_MOVE_32_TO_32(&temp32,
-						   &buffer[(acpi_size) i + j +
+						   &buffer[(acpi_size)i + j +
 							   4]);
 				acpi_os_printf("%08X ", temp32);
 				break;
@@ -158,7 +158,7 @@ void acpi_ut_dump_buffer(u8 *buffer, u32
 				acpi_os_printf("// ");
 			}
 
-			buf_char = buffer[(acpi_size) i + j];
+			buf_char = buffer[(acpi_size)i + j];
 			if (isprint(buf_char)) {
 				acpi_os_printf("%c", buf_char);
 			} else {
@@ -274,31 +274,31 @@ acpi_ut_dump_buffer_to_file(ACPI_FILE fi
 			default:	/* Default is BYTE display */
 
 				acpi_ut_file_printf(file, "%02X ",
-						    buffer[(acpi_size) i + j]);
+						    buffer[(acpi_size)i + j]);
 				break;
 
 			case DB_WORD_DISPLAY:
 
 				ACPI_MOVE_16_TO_32(&temp32,
-						   &buffer[(acpi_size) i + j]);
+						   &buffer[(acpi_size)i + j]);
 				acpi_ut_file_printf(file, "%04X ", temp32);
 				break;
 
 			case DB_DWORD_DISPLAY:
 
 				ACPI_MOVE_32_TO_32(&temp32,
-						   &buffer[(acpi_size) i + j]);
+						   &buffer[(acpi_size)i + j]);
 				acpi_ut_file_printf(file, "%08X ", temp32);
 				break;
 
 			case DB_QWORD_DISPLAY:
 
 				ACPI_MOVE_32_TO_32(&temp32,
-						   &buffer[(acpi_size) i + j]);
+						   &buffer[(acpi_size)i + j]);
 				acpi_ut_file_printf(file, "%08X", temp32);
 
 				ACPI_MOVE_32_TO_32(&temp32,
-						   &buffer[(acpi_size) i + j +
+						   &buffer[(acpi_size)i + j +
 							   4]);
 				acpi_ut_file_printf(file, "%08X ", temp32);
 				break;
@@ -318,7 +318,7 @@ acpi_ut_dump_buffer_to_file(ACPI_FILE fi
 				return;
 			}
 
-			buf_char = buffer[(acpi_size) i + j];
+			buf_char = buffer[(acpi_size)i + j];
 			if (isprint(buf_char)) {
 				acpi_ut_file_printf(file, "%c", buf_char);
 			} else {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/utcache.c linux-libre-4.7-gnu/drivers/acpi/acpica/utcache.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/utcache.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/utcache.c	2016-07-24 15:23:50.000000000 -0400
@@ -105,7 +105,7 @@ acpi_os_create_cache(char *cache_name,
  *
  ******************************************************************************/
 
-acpi_status acpi_os_purge_cache(struct acpi_memory_list * cache)
+acpi_status acpi_os_purge_cache(struct acpi_memory_list *cache)
 {
 	void *next;
 	acpi_status status;
@@ -151,7 +151,7 @@ acpi_status acpi_os_purge_cache(struct a
  *
  ******************************************************************************/
 
-acpi_status acpi_os_delete_cache(struct acpi_memory_list * cache)
+acpi_status acpi_os_delete_cache(struct acpi_memory_list *cache)
 {
 	acpi_status status;
 
@@ -184,8 +184,7 @@ acpi_status acpi_os_delete_cache(struct
  *
  ******************************************************************************/
 
-acpi_status
-acpi_os_release_object(struct acpi_memory_list * cache, void *object)
+acpi_status acpi_os_release_object(struct acpi_memory_list *cache, void *object)
 {
 	acpi_status status;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/utcopy.c linux-libre-4.7-gnu/drivers/acpi/acpica/utcopy.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/utcopy.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/utcopy.c	2016-07-24 15:23:50.000000000 -0400
@@ -53,7 +53,7 @@ ACPI_MODULE_NAME("utcopy")
 static acpi_status
 acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object,
 				union acpi_object *external_object,
-				u8 * data_space, acpi_size * buffer_space_used);
+				u8 *data_space, acpi_size *buffer_space_used);
 
 static acpi_status
 acpi_ut_copy_ielement_to_ielement(u8 object_type,
@@ -63,7 +63,7 @@ acpi_ut_copy_ielement_to_ielement(u8 obj
 
 static acpi_status
 acpi_ut_copy_ipackage_to_epackage(union acpi_operand_object *internal_object,
-				  u8 * buffer, acpi_size * space_used);
+				  u8 *buffer, acpi_size *space_used);
 
 static acpi_status
 acpi_ut_copy_esimple_to_isimple(union acpi_object *user_obj,
@@ -111,7 +111,7 @@ acpi_ut_copy_ipackage_to_ipackage(union
 static acpi_status
 acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object,
 				union acpi_object *external_object,
-				u8 * data_space, acpi_size * buffer_space_used)
+				u8 *data_space, acpi_size *buffer_space_used)
 {
 	acpi_status status = AE_OK;
 
@@ -151,7 +151,7 @@ acpi_ut_copy_isimple_to_esimple(union ac
 
 		memcpy((void *)data_space,
 		       (void *)internal_object->string.pointer,
-		       (acpi_size) internal_object->string.length + 1);
+		       (acpi_size)internal_object->string.length + 1);
 		break;
 
 	case ACPI_TYPE_BUFFER:
@@ -331,7 +331,7 @@ acpi_ut_copy_ielement_to_eelement(u8 obj
 
 static acpi_status
 acpi_ut_copy_ipackage_to_epackage(union acpi_operand_object *internal_object,
-				  u8 * buffer, acpi_size * space_used)
+				  u8 *buffer, acpi_size *space_used)
 {
 	union acpi_object *external_object;
 	acpi_status status;
@@ -362,7 +362,7 @@ acpi_ut_copy_ipackage_to_epackage(union
 	 * Leave room for an array of ACPI_OBJECTS in the buffer
 	 * and move the free space past it
 	 */
-	info.length += (acpi_size) external_object->package.count *
+	info.length += (acpi_size)external_object->package.count *
 	    ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object));
 	info.free_space += external_object->package.count *
 	    ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object));
@@ -738,7 +738,7 @@ acpi_ut_copy_simple_object(union acpi_op
 		 */
 		if (source_desc->string.pointer) {
 			dest_desc->string.pointer =
-			    ACPI_ALLOCATE((acpi_size) source_desc->string.
+			    ACPI_ALLOCATE((acpi_size)source_desc->string.
 					  length + 1);
 			if (!dest_desc->string.pointer) {
 				return (AE_NO_MEMORY);
@@ -748,7 +748,7 @@ acpi_ut_copy_simple_object(union acpi_op
 
 			memcpy(dest_desc->string.pointer,
 			       source_desc->string.pointer,
-			       (acpi_size) source_desc->string.length + 1);
+			       (acpi_size)source_desc->string.length + 1);
 		}
 		break;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/utdebug.c linux-libre-4.7-gnu/drivers/acpi/acpica/utdebug.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/utdebug.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/utdebug.c	2016-07-24 15:23:50.000000000 -0400
@@ -51,13 +51,9 @@
 ACPI_MODULE_NAME("utdebug")
 
 #ifdef ACPI_DEBUG_OUTPUT
-static acpi_thread_id acpi_gbl_prev_thread_id = (acpi_thread_id) 0xFFFFFFFF;
-static char *acpi_gbl_fn_entry_str = "----Entry";
-static char *acpi_gbl_fn_exit_str = "----Exit-";
-
-/* Local prototypes */
-
-static const char *acpi_ut_trim_function_name(const char *function_name);
+static acpi_thread_id acpi_gbl_previous_thread_id = (acpi_thread_id) 0xFFFFFFFF;
+static const char *acpi_gbl_function_entry_prefix = "----Entry";
+static const char *acpi_gbl_function_exit_prefix = "----Exit-";
 
 /*******************************************************************************
  *
@@ -178,14 +174,14 @@ acpi_debug_print(u32 requested_debug_lev
 	 * Thread tracking and context switch notification
 	 */
 	thread_id = acpi_os_get_thread_id();
-	if (thread_id != acpi_gbl_prev_thread_id) {
+	if (thread_id != acpi_gbl_previous_thread_id) {
 		if (ACPI_LV_THREADS & acpi_dbg_level) {
 			acpi_os_printf
 			    ("\n**** Context Switch from TID %u to TID %u ****\n\n",
-			     (u32)acpi_gbl_prev_thread_id, (u32)thread_id);
+			     (u32)acpi_gbl_previous_thread_id, (u32)thread_id);
 		}
 
-		acpi_gbl_prev_thread_id = thread_id;
+		acpi_gbl_previous_thread_id = thread_id;
 		acpi_gbl_nesting_level = 0;
 	}
 
@@ -287,7 +283,8 @@ acpi_ut_trace(u32 line_number,
 	if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) {
 		acpi_debug_print(ACPI_LV_FUNCTIONS,
 				 line_number, function_name, module_name,
-				 component_id, "%s\n", acpi_gbl_fn_entry_str);
+				 component_id, "%s\n",
+				 acpi_gbl_function_entry_prefix);
 	}
 }
 
@@ -312,7 +309,8 @@ ACPI_EXPORT_SYMBOL(acpi_ut_trace)
 void
 acpi_ut_trace_ptr(u32 line_number,
 		  const char *function_name,
-		  const char *module_name, u32 component_id, void *pointer)
+		  const char *module_name,
+		  u32 component_id, const void *pointer)
 {
 
 	acpi_gbl_nesting_level++;
@@ -323,8 +321,8 @@ acpi_ut_trace_ptr(u32 line_number,
 	if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) {
 		acpi_debug_print(ACPI_LV_FUNCTIONS,
 				 line_number, function_name, module_name,
-				 component_id, "%s %p\n", acpi_gbl_fn_entry_str,
-				 pointer);
+				 component_id, "%s %p\n",
+				 acpi_gbl_function_entry_prefix, pointer);
 	}
 }
 
@@ -348,7 +346,7 @@ acpi_ut_trace_ptr(u32 line_number,
 void
 acpi_ut_trace_str(u32 line_number,
 		  const char *function_name,
-		  const char *module_name, u32 component_id, char *string)
+		  const char *module_name, u32 component_id, const char *string)
 {
 
 	acpi_gbl_nesting_level++;
@@ -359,8 +357,8 @@ acpi_ut_trace_str(u32 line_number,
 	if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) {
 		acpi_debug_print(ACPI_LV_FUNCTIONS,
 				 line_number, function_name, module_name,
-				 component_id, "%s %s\n", acpi_gbl_fn_entry_str,
-				 string);
+				 component_id, "%s %s\n",
+				 acpi_gbl_function_entry_prefix, string);
 	}
 }
 
@@ -396,7 +394,7 @@ acpi_ut_trace_u32(u32 line_number,
 		acpi_debug_print(ACPI_LV_FUNCTIONS,
 				 line_number, function_name, module_name,
 				 component_id, "%s %08X\n",
-				 acpi_gbl_fn_entry_str, integer);
+				 acpi_gbl_function_entry_prefix, integer);
 	}
 }
 
@@ -427,7 +425,8 @@ acpi_ut_exit(u32 line_number,
 	if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) {
 		acpi_debug_print(ACPI_LV_FUNCTIONS,
 				 line_number, function_name, module_name,
-				 component_id, "%s\n", acpi_gbl_fn_exit_str);
+				 component_id, "%s\n",
+				 acpi_gbl_function_exit_prefix);
 	}
 
 	if (acpi_gbl_nesting_level) {
@@ -467,14 +466,14 @@ acpi_ut_status_exit(u32 line_number,
 			acpi_debug_print(ACPI_LV_FUNCTIONS,
 					 line_number, function_name,
 					 module_name, component_id, "%s %s\n",
-					 acpi_gbl_fn_exit_str,
+					 acpi_gbl_function_exit_prefix,
 					 acpi_format_exception(status));
 		} else {
 			acpi_debug_print(ACPI_LV_FUNCTIONS,
 					 line_number, function_name,
 					 module_name, component_id,
 					 "%s ****Exception****: %s\n",
-					 acpi_gbl_fn_exit_str,
+					 acpi_gbl_function_exit_prefix,
 					 acpi_format_exception(status));
 		}
 	}
@@ -514,7 +513,7 @@ acpi_ut_value_exit(u32 line_number,
 		acpi_debug_print(ACPI_LV_FUNCTIONS,
 				 line_number, function_name, module_name,
 				 component_id, "%s %8.8X%8.8X\n",
-				 acpi_gbl_fn_exit_str,
+				 acpi_gbl_function_exit_prefix,
 				 ACPI_FORMAT_UINT64(value));
 	}
 
@@ -552,8 +551,8 @@ acpi_ut_ptr_exit(u32 line_number,
 	if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_FUNCTIONS, component_id)) {
 		acpi_debug_print(ACPI_LV_FUNCTIONS,
 				 line_number, function_name, module_name,
-				 component_id, "%s %p\n", acpi_gbl_fn_exit_str,
-				 ptr);
+				 component_id, "%s %p\n",
+				 acpi_gbl_function_exit_prefix, ptr);
 	}
 
 	if (acpi_gbl_nesting_level) {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/utdecode.c linux-libre-4.7-gnu/drivers/acpi/acpica/utdecode.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/utdecode.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/utdecode.c	2016-07-24 15:23:50.000000000 -0400
@@ -446,7 +446,7 @@ const char *acpi_ut_get_mutex_name(u32 m
 
 /* Names for Notify() values, used for debug output */
 
-static const char *acpi_gbl_generic_notify[ACPI_NOTIFY_MAX + 1] = {
+static const char *acpi_gbl_generic_notify[ACPI_GENERIC_NOTIFY_MAX + 1] = {
 	/* 00 */ "Bus Check",
 	/* 01 */ "Device Check",
 	/* 02 */ "Device Wake",
@@ -459,49 +459,53 @@ static const char *acpi_gbl_generic_noti
 	/* 09 */ "Device PLD Check",
 	/* 0A */ "Reserved",
 	/* 0B */ "System Locality Update",
-	/* 0C */ "Shutdown Request",
+					/* 0C */ "Shutdown Request",
+					/* Reserved in ACPI 6.0 */
 	/* 0D */ "System Resource Affinity Update"
 };
 
-static const char *acpi_gbl_device_notify[4] = {
+static const char *acpi_gbl_device_notify[5] = {
 	/* 80 */ "Status Change",
 	/* 81 */ "Information Change",
 	/* 82 */ "Device-Specific Change",
-	/* 83 */ "Device-Specific Change"
+	/* 83 */ "Device-Specific Change",
+	/* 84 */ "Reserved"
 };
 
-static const char *acpi_gbl_processor_notify[4] = {
+static const char *acpi_gbl_processor_notify[5] = {
 	/* 80 */ "Performance Capability Change",
 	/* 81 */ "C-State Change",
 	/* 82 */ "Throttling Capability Change",
-	/* 83 */ "Device-Specific Change"
+	/* 83 */ "Guaranteed Change",
+	/* 84 */ "Minimum Excursion"
 };
 
-static const char *acpi_gbl_thermal_notify[4] = {
+static const char *acpi_gbl_thermal_notify[5] = {
 	/* 80 */ "Thermal Status Change",
 	/* 81 */ "Thermal Trip Point Change",
 	/* 82 */ "Thermal Device List Change",
-	/* 83 */ "Thermal Relationship Change"
+	/* 83 */ "Thermal Relationship Change",
+	/* 84 */ "Reserved"
 };
 
 const char *acpi_ut_get_notify_name(u32 notify_value, acpi_object_type type)
 {
 
-	/* 00 - 0D are common to all object types */
+	/* 00 - 0D are "common to all object types" (from ACPI Spec) */
 
-	if (notify_value <= ACPI_NOTIFY_MAX) {
+	if (notify_value <= ACPI_GENERIC_NOTIFY_MAX) {
 		return (acpi_gbl_generic_notify[notify_value]);
 	}
 
-	/* 0D - 7F are reserved */
+	/* 0E - 7F are reserved */
 
 	if (notify_value <= ACPI_MAX_SYS_NOTIFY) {
 		return ("Reserved");
 	}
 
-	/* 80 - 83 are per-object-type */
+	/* 80 - 84 are per-object-type */
 
-	if (notify_value <= 0x83) {
+	if (notify_value <= ACPI_SPECIFIC_NOTIFY_MAX) {
 		switch (type) {
 		case ACPI_TYPE_ANY:
 		case ACPI_TYPE_DEVICE:
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/uteval.c linux-libre-4.7-gnu/drivers/acpi/acpica/uteval.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/uteval.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/uteval.c	2016-07-24 15:23:50.000000000 -0400
@@ -69,7 +69,7 @@ ACPI_MODULE_NAME("uteval")
 
 acpi_status
 acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node,
-			char *path,
+			const char *path,
 			u32 expected_return_btypes,
 			union acpi_operand_object **return_desc)
 {
@@ -204,7 +204,7 @@ cleanup:
  ******************************************************************************/
 
 acpi_status
-acpi_ut_evaluate_numeric_object(char *object_name,
+acpi_ut_evaluate_numeric_object(const char *object_name,
 				struct acpi_namespace_node *device_node,
 				u64 *value)
 {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/utglobal.c linux-libre-4.7-gnu/drivers/acpi/acpica/utglobal.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/utglobal.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/utglobal.c	2016-07-24 15:23:50.000000000 -0400
@@ -80,6 +80,11 @@ const char *acpi_gbl_highest_dstate_name
 	"_S4D"
 };
 
+/* Hex-to-ascii */
+
+const char acpi_gbl_lower_hex_digits[] = "0123456789abcdef";
+const char acpi_gbl_upper_hex_digits[] = "0123456789ABCDEF";
+
 /*******************************************************************************
  *
  * Namespace globals
@@ -221,6 +226,49 @@ struct acpi_fixed_event_info acpi_gbl_fi
 };
 #endif				/* !ACPI_REDUCED_HARDWARE */
 
+#if defined (ACPI_DISASSEMBLER) || defined (ACPI_ASL_COMPILER)
+
+/* to_pld macro: compile/disassemble strings */
+
+const char *acpi_gbl_pld_panel_list[] = {
+	"TOP",
+	"BOTTOM",
+	"LEFT",
+	"RIGHT",
+	"FRONT",
+	"BACK",
+	"UNKNOWN",
+	NULL
+};
+
+const char *acpi_gbl_pld_vertical_position_list[] = {
+	"UPPER",
+	"CENTER",
+	"LOWER",
+	NULL
+};
+
+const char *acpi_gbl_pld_horizontal_position_list[] = {
+	"LEFT",
+	"CENTER",
+	"RIGHT",
+	NULL
+};
+
+const char *acpi_gbl_pld_shape_list[] = {
+	"ROUND",
+	"OVAL",
+	"SQUARE",
+	"VERTICALRECTANGLE",
+	"HORIZONTALRECTANGLE",
+	"VERTICALTRAPEZOID",
+	"HORIZONTALTRAPEZOID",
+	"UNKNOWN",
+	"CHAMFERED",
+	NULL
+};
+#endif
+
 /* Public globals */
 
 ACPI_EXPORT_SYMBOL(acpi_gbl_FADT)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/utids.c linux-libre-4.7-gnu/drivers/acpi/acpica/utids.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/utids.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/utids.c	2016-07-24 15:23:50.000000000 -0400
@@ -95,7 +95,7 @@ acpi_ut_execute_HID(struct acpi_namespac
 
 	hid =
 	    ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) +
-				 (acpi_size) length);
+				 (acpi_size)length);
 	if (!hid) {
 		status = AE_NO_MEMORY;
 		goto cleanup;
@@ -173,7 +173,7 @@ acpi_ut_execute_UID(struct acpi_namespac
 
 	uid =
 	    ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) +
-				 (acpi_size) length);
+				 (acpi_size)length);
 	if (!uid) {
 		status = AE_NO_MEMORY;
 		goto cleanup;
@@ -309,7 +309,7 @@ acpi_ut_execute_CID(struct acpi_namespac
 	/* Area for CID strings starts after the CID PNP_DEVICE_ID array */
 
 	next_id_string = ACPI_CAST_PTR(char, cid_list->ids) +
-	    ((acpi_size) count * sizeof(struct acpi_pnp_device_id));
+	    ((acpi_size)count * sizeof(struct acpi_pnp_device_id));
 
 	/* Copy/convert the CIDs to the return buffer */
 
@@ -413,7 +413,7 @@ acpi_ut_execute_CLS(struct acpi_namespac
 
 	cls =
 	    ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) +
-				 (acpi_size) length);
+				 (acpi_size)length);
 	if (!cls) {
 		status = AE_NO_MEMORY;
 		goto cleanup;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/utmath.c linux-libre-4.7-gnu/drivers/acpi/acpica/utmath.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/utmath.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/utmath.c	2016-07-24 15:23:50.000000000 -0400
@@ -236,8 +236,8 @@ acpi_ut_divide(u64 in_dividend,
 			}
 
 			remainder.full = remainder.full - dividend.full;
-			remainder.part.hi = (u32) - ((s32) remainder.part.hi);
-			remainder.part.lo = (u32) - ((s32) remainder.part.lo);
+			remainder.part.hi = (u32)-((s32)remainder.part.hi);
+			remainder.part.lo = (u32)-((s32)remainder.part.lo);
 
 			if (remainder.part.lo) {
 				remainder.part.hi--;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/utmisc.c linux-libre-4.7-gnu/drivers/acpi/acpica/utmisc.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/utmisc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/utmisc.c	2016-07-24 15:23:50.000000000 -0400
@@ -361,7 +361,7 @@ acpi_ut_walk_package_tree(union acpi_ope
 void
 acpi_ut_display_init_pathname(u8 type,
 			      struct acpi_namespace_node *obj_handle,
-			      char *path)
+			      const char *path)
 {
 	acpi_status status;
 	struct acpi_buffer buffer;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/utnonansi.c linux-libre-4.7-gnu/drivers/acpi/acpica/utnonansi.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/utnonansi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/utnonansi.c	2016-07-24 15:23:50.000000000 -0400
@@ -205,37 +205,41 @@ acpi_ut_safe_strncat(char *dest,
  *
  * FUNCTION:    acpi_ut_strtoul64
  *
- * PARAMETERS:  string          - Null terminated string
- *              base            - Radix of the string: 16 or ACPI_ANY_BASE;
- *                                ACPI_ANY_BASE means 'in behalf of to_integer'
- *              ret_integer     - Where the converted integer is returned
+ * PARAMETERS:  string                  - Null terminated string
+ *              base                    - Radix of the string: 16 or 10 or
+ *                                        ACPI_ANY_BASE
+ *              max_integer_byte_width  - Maximum allowable integer,in bytes:
+ *                                        4 or 8 (32 or 64 bits)
+ *              ret_integer             - Where the converted integer is
+ *                                        returned
  *
  * RETURN:      Status and Converted value
  *
  * DESCRIPTION: Convert a string into an unsigned value. Performs either a
- *              32-bit or 64-bit conversion, depending on the current mode
- *              of the interpreter.
+ *              32-bit or 64-bit conversion, depending on the input integer
+ *              size (often the current mode of the interpreter).
  *
- * NOTES:       acpi_gbl_integer_byte_width should be set to the proper width.
+ * NOTES:       Negative numbers are not supported, as they are not supported
+ *              by ACPI.
+ *
+ *              acpi_gbl_integer_byte_width should be set to the proper width.
  *              For the core ACPICA code, this width depends on the DSDT
- *              version. For iASL, the default byte width is always 8.
+ *              version. For iASL, the default byte width is always 8 for the
+ *              parser, but error checking is performed later to flag cases
+ *              where a 64-bit constant is defined in a 32-bit DSDT/SSDT.
  *
  *              Does not support Octal strings, not needed at this time.
  *
- *              There is an earlier version of the function after this one,
- *              below. It is slightly different than this one, and the two
- *              may eventually may need to be merged. (01/2016).
- *
  ******************************************************************************/
 
-acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer)
+acpi_status
+acpi_ut_strtoul64(char *string,
+		  u32 base, u32 max_integer_byte_width, u64 *ret_integer)
 {
 	u32 this_digit = 0;
 	u64 return_value = 0;
 	u64 quotient;
 	u64 dividend;
-	u32 to_integer_op = (base == ACPI_ANY_BASE);
-	u32 mode32 = (acpi_gbl_integer_byte_width == 4);
 	u8 valid_digits = 0;
 	u8 sign_of0x = 0;
 	u8 term = 0;
@@ -244,6 +248,7 @@ acpi_status acpi_ut_strtoul64(char *stri
 
 	switch (base) {
 	case ACPI_ANY_BASE:
+	case 10:
 	case 16:
 
 		break;
@@ -265,9 +270,9 @@ acpi_status acpi_ut_strtoul64(char *stri
 		string++;
 	}
 
-	if (to_integer_op) {
+	if (base == ACPI_ANY_BASE) {
 		/*
-		 * Base equal to ACPI_ANY_BASE means 'ToInteger operation case'.
+		 * Base equal to ACPI_ANY_BASE means 'Either decimal or hex'.
 		 * We need to determine if it is decimal or hexadecimal.
 		 */
 		if ((*string == '0') && (tolower((int)*(string + 1)) == 'x')) {
@@ -284,7 +289,7 @@ acpi_status acpi_ut_strtoul64(char *stri
 	/* Any string left? Check that '0x' is not followed by white space. */
 
 	if (!(*string) || isspace((int)*string) || *string == '\t') {
-		if (to_integer_op) {
+		if (base == ACPI_ANY_BASE) {
 			goto error_exit;
 		} else {
 			goto all_done;
@@ -292,10 +297,11 @@ acpi_status acpi_ut_strtoul64(char *stri
 	}
 
 	/*
-	 * Perform a 32-bit or 64-bit conversion, depending upon the current
-	 * execution mode of the interpreter
+	 * Perform a 32-bit or 64-bit conversion, depending upon the input
+	 * byte width
 	 */
-	dividend = (mode32) ? ACPI_UINT32_MAX : ACPI_UINT64_MAX;
+	dividend = (max_integer_byte_width <= ACPI_MAX32_BYTE_WIDTH) ?
+	    ACPI_UINT32_MAX : ACPI_UINT64_MAX;
 
 	/* Main loop: convert the string to a 32- or 64-bit integer */
 
@@ -323,7 +329,7 @@ acpi_status acpi_ut_strtoul64(char *stri
 		}
 
 		if (term) {
-			if (to_integer_op) {
+			if (base == ACPI_ANY_BASE) {
 				goto error_exit;
 			} else {
 				break;
@@ -338,12 +344,13 @@ acpi_status acpi_ut_strtoul64(char *stri
 
 		valid_digits++;
 
-		if (sign_of0x
-		    && ((valid_digits > 16)
-			|| ((valid_digits > 8) && mode32))) {
+		if (sign_of0x && ((valid_digits > 16) ||
+				  ((valid_digits > 8)
+				   && (max_integer_byte_width <=
+				       ACPI_MAX32_BYTE_WIDTH)))) {
 			/*
 			 * This is to_integer operation case.
-			 * No any restrictions for string-to-integer conversion,
+			 * No restrictions for string-to-integer conversion,
 			 * see ACPI spec.
 			 */
 			goto error_exit;
@@ -355,7 +362,7 @@ acpi_status acpi_ut_strtoul64(char *stri
 					   &quotient, NULL);
 
 		if (return_value > quotient) {
-			if (to_integer_op) {
+			if (base == ACPI_ANY_BASE) {
 				goto error_exit;
 			} else {
 				break;
@@ -378,7 +385,8 @@ all_done:
 	return_ACPI_STATUS(AE_OK);
 
 error_exit:
-	/* Base was set/validated above */
+
+	/* Base was set/validated above (10 or 16) */
 
 	if (base == 10) {
 		return_ACPI_STATUS(AE_BAD_DECIMAL_CONSTANT);
@@ -388,8 +396,7 @@ error_exit:
 }
 
 #ifdef _OBSOLETE_FUNCTIONS
-/* TBD: use version in ACPICA main code base? */
-/* DONE: 01/2016 */
+/* Removed: 01/2016 */
 
 /*******************************************************************************
  *
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/utobject.c linux-libre-4.7-gnu/drivers/acpi/acpica/utobject.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/utobject.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/utobject.c	2016-07-24 15:23:50.000000000 -0400
@@ -51,11 +51,11 @@ ACPI_MODULE_NAME("utobject")
 /* Local prototypes */
 static acpi_status
 acpi_ut_get_simple_object_size(union acpi_operand_object *obj,
-			       acpi_size * obj_length);
+			       acpi_size *obj_length);
 
 static acpi_status
 acpi_ut_get_package_object_size(union acpi_operand_object *obj,
-				acpi_size * obj_length);
+				acpi_size *obj_length);
 
 static acpi_status
 acpi_ut_get_element_length(u8 object_type,
@@ -177,7 +177,7 @@ union acpi_operand_object *acpi_ut_creat
 	 * Create the element array. Count+1 allows the array to be null
 	 * terminated.
 	 */
-	package_elements = ACPI_ALLOCATE_ZEROED(((acpi_size) count +
+	package_elements = ACPI_ALLOCATE_ZEROED(((acpi_size)count +
 						 1) * sizeof(void *));
 	if (!package_elements) {
 		ACPI_FREE(package_desc);
@@ -454,7 +454,7 @@ void acpi_ut_delete_object_desc(union ac
 
 static acpi_status
 acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object,
-			       acpi_size * obj_length)
+			       acpi_size *obj_length)
 {
 	acpi_size length;
 	acpi_size size;
@@ -495,12 +495,12 @@ acpi_ut_get_simple_object_size(union acp
 	switch (internal_object->common.type) {
 	case ACPI_TYPE_STRING:
 
-		length += (acpi_size) internal_object->string.length + 1;
+		length += (acpi_size)internal_object->string.length + 1;
 		break;
 
 	case ACPI_TYPE_BUFFER:
 
-		length += (acpi_size) internal_object->buffer.length;
+		length += (acpi_size)internal_object->buffer.length;
 		break;
 
 	case ACPI_TYPE_INTEGER:
@@ -640,7 +640,7 @@ acpi_ut_get_element_length(u8 object_typ
 
 static acpi_status
 acpi_ut_get_package_object_size(union acpi_operand_object *internal_object,
-				acpi_size * obj_length)
+				acpi_size *obj_length)
 {
 	acpi_status status;
 	struct acpi_pkg_info info;
@@ -665,7 +665,7 @@ acpi_ut_get_package_object_size(union ac
 	 */
 	info.length +=
 	    ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object)) *
-	    (acpi_size) info.num_packages;
+	    (acpi_size)info.num_packages;
 
 	/* Return the total package length */
 
@@ -689,7 +689,7 @@ acpi_ut_get_package_object_size(union ac
 
 acpi_status
 acpi_ut_get_object_size(union acpi_operand_object *internal_object,
-			acpi_size * obj_length)
+			acpi_size *obj_length)
 {
 	acpi_status status;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/utosi.c linux-libre-4.7-gnu/drivers/acpi/acpica/utosi.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/utosi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/utosi.c	2016-07-24 15:23:50.000000000 -0400
@@ -150,7 +150,7 @@ acpi_status acpi_ut_initialize_interface
 	     i < (ACPI_ARRAY_LENGTH(acpi_default_supported_interfaces) - 1);
 	     i++) {
 		acpi_default_supported_interfaces[i].next =
-		    &acpi_default_supported_interfaces[(acpi_size) i + 1];
+		    &acpi_default_supported_interfaces[(acpi_size)i + 1];
 	}
 
 	acpi_os_release_mutex(acpi_gbl_osi_mutex);
@@ -397,7 +397,7 @@ struct acpi_interface_info *acpi_ut_get_
  *
  ******************************************************************************/
 
-acpi_status acpi_ut_osi_implementation(struct acpi_walk_state * walk_state)
+acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state)
 {
 	union acpi_operand_object *string_desc;
 	union acpi_operand_object *return_desc;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/utownerid.c linux-libre-4.7-gnu/drivers/acpi/acpica/utownerid.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/utownerid.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/utownerid.c	2016-07-24 15:23:50.000000000 -0400
@@ -61,7 +61,7 @@ ACPI_MODULE_NAME("utownerid")
  *              when the method exits or the table is unloaded.
  *
  ******************************************************************************/
-acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id)
+acpi_status acpi_ut_allocate_owner_id(acpi_owner_id *owner_id)
 {
 	u32 i;
 	u32 j;
@@ -122,7 +122,7 @@ acpi_status acpi_ut_allocate_owner_id(ac
 				 * permanently allocated (prevents +1 overflow)
 				 */
 				*owner_id =
-				    (acpi_owner_id) ((k + 1) + ACPI_MUL_32(j));
+				    (acpi_owner_id)((k + 1) + ACPI_MUL_32(j));
 
 				ACPI_DEBUG_PRINT((ACPI_DB_VALUES,
 						  "Allocated OwnerId: %2.2X\n",
@@ -167,7 +167,7 @@ exit:
  *
  ******************************************************************************/
 
-void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr)
+void acpi_ut_release_owner_id(acpi_owner_id *owner_id_ptr)
 {
 	acpi_owner_id owner_id = *owner_id_ptr;
 	acpi_status status;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/utprint.c linux-libre-4.7-gnu/drivers/acpi/acpica/utprint.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/utprint.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/utprint.c	2016-07-24 15:23:50.000000000 -0400
@@ -67,11 +67,6 @@ static char *acpi_ut_format_number(char
 
 static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper);
 
-/* Module globals */
-
-static const char acpi_gbl_lower_hex_digits[] = "0123456789abcdef";
-static const char acpi_gbl_upper_hex_digits[] = "0123456789ABCDEF";
-
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ut_bound_string_length
@@ -269,9 +264,9 @@ static char *acpi_ut_format_number(char
 
 	sign = '\0';
 	if (type & ACPI_FORMAT_SIGN) {
-		if ((s64) number < 0) {
+		if ((s64)number < 0) {
 			sign = '-';
-			number = -(s64) number;
+			number = -(s64)number;
 			width--;
 		} else if (type & ACPI_FORMAT_SIGN_PLUS) {
 			sign = '+';
@@ -409,7 +404,7 @@ acpi_ut_vsnprintf(char *string,
 		width = -1;
 		if (isdigit((int)*format)) {
 			format = acpi_ut_scan_number(format, &number);
-			width = (s32) number;
+			width = (s32)number;
 		} else if (*format == '*') {
 			++format;
 			width = va_arg(args, int);
@@ -426,7 +421,7 @@ acpi_ut_vsnprintf(char *string,
 			++format;
 			if (isdigit((int)*format)) {
 				format = acpi_ut_scan_number(format, &number);
-				precision = (s32) number;
+				precision = (s32)number;
 			} else if (*format == '*') {
 				++format;
 				precision = va_arg(args, int);
@@ -555,17 +550,17 @@ acpi_ut_vsnprintf(char *string,
 		if (qualifier == 'L') {
 			number = va_arg(args, u64);
 			if (type & ACPI_FORMAT_SIGN) {
-				number = (s64) number;
+				number = (s64)number;
 			}
 		} else if (qualifier == 'l') {
 			number = va_arg(args, unsigned long);
 			if (type & ACPI_FORMAT_SIGN) {
-				number = (s32) number;
+				number = (s32)number;
 			}
 		} else if (qualifier == 'h') {
 			number = (u16)va_arg(args, int);
 			if (type & ACPI_FORMAT_SIGN) {
-				number = (s16) number;
+				number = (s16)number;
 			}
 		} else {
 			number = va_arg(args, unsigned int);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/utstring.c linux-libre-4.7-gnu/drivers/acpi/acpica/utstring.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/utstring.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/utstring.c	2016-07-24 15:23:50.000000000 -0400
@@ -130,7 +130,7 @@ void acpi_ut_print_string(char *string,
 			} else {
 				/* All others will be Hex escapes */
 
-				acpi_os_printf("\\x%2.2X", (s32) string[i]);
+				acpi_os_printf("\\x%2.2X", (s32)string[i]);
 			}
 			break;
 		}
@@ -145,73 +145,6 @@ void acpi_ut_print_string(char *string,
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ut_valid_acpi_char
- *
- * PARAMETERS:  char            - The character to be examined
- *              position        - Byte position (0-3)
- *
- * RETURN:      TRUE if the character is valid, FALSE otherwise
- *
- * DESCRIPTION: Check for a valid ACPI character. Must be one of:
- *              1) Upper case alpha
- *              2) numeric
- *              3) underscore
- *
- *              We allow a '!' as the last character because of the ASF! table
- *
- ******************************************************************************/
-
-u8 acpi_ut_valid_acpi_char(char character, u32 position)
-{
-
-	if (!((character >= 'A' && character <= 'Z') ||
-	      (character >= '0' && character <= '9') || (character == '_'))) {
-
-		/* Allow a '!' in the last position */
-
-		if (character == '!' && position == 3) {
-			return (TRUE);
-		}
-
-		return (FALSE);
-	}
-
-	return (TRUE);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ut_valid_acpi_name
- *
- * PARAMETERS:  name            - The name to be examined. Does not have to
- *                                be NULL terminated string.
- *
- * RETURN:      TRUE if the name is valid, FALSE otherwise
- *
- * DESCRIPTION: Check for a valid ACPI name. Each character must be one of:
- *              1) Upper case alpha
- *              2) numeric
- *              3) underscore
- *
- ******************************************************************************/
-
-u8 acpi_ut_valid_acpi_name(char *name)
-{
-	u32 i;
-
-	ACPI_FUNCTION_ENTRY();
-
-	for (i = 0; i < ACPI_NAME_SIZE; i++) {
-		if (!acpi_ut_valid_acpi_char(name[i], i)) {
-			return (FALSE);
-		}
-	}
-
-	return (TRUE);
-}
-
-/*******************************************************************************
- *
  * FUNCTION:    acpi_ut_repair_name
  *
  * PARAMETERS:  name            - The ACPI name to be repaired
@@ -253,7 +186,7 @@ void acpi_ut_repair_name(char *name)
 	/* Check each character in the name */
 
 	for (i = 0; i < ACPI_NAME_SIZE; i++) {
-		if (acpi_ut_valid_acpi_char(name[i], i)) {
+		if (acpi_ut_valid_name_char(name[i], i)) {
 			continue;
 		}
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/uttrack.c linux-libre-4.7-gnu/drivers/acpi/acpica/uttrack.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/uttrack.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/uttrack.c	2016-07-24 15:23:50.000000000 -0400
@@ -90,7 +90,7 @@ acpi_ut_remove_allocation(struct acpi_de
  ******************************************************************************/
 
 acpi_status
-acpi_ut_create_list(char *list_name,
+acpi_ut_create_list(const char *list_name,
 		    u16 object_size, struct acpi_memory_list **return_cache)
 {
 	struct acpi_memory_list *cache;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpica/utxface.c linux-libre-4.7-gnu/drivers/acpi/acpica/utxface.c
--- linux-libre-4.6-gnu/drivers/acpi/acpica/utxface.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpica/utxface.c	2016-07-24 15:23:50.000000000 -0400
@@ -127,7 +127,7 @@ ACPI_EXPORT_SYMBOL(acpi_subsystem_status
  *              and the value of out_buffer is undefined.
  *
  ******************************************************************************/
-acpi_status acpi_get_system_info(struct acpi_buffer * out_buffer)
+acpi_status acpi_get_system_info(struct acpi_buffer *out_buffer)
 {
 	struct acpi_system_info *info_ptr;
 	acpi_status status;
@@ -483,7 +483,7 @@ ACPI_EXPORT_SYMBOL(acpi_check_address_ra
  ******************************************************************************/
 acpi_status
 acpi_decode_pld_buffer(u8 *in_buffer,
-		       acpi_size length, struct acpi_pld_info ** return_buffer)
+		       acpi_size length, struct acpi_pld_info **return_buffer)
 {
 	struct acpi_pld_info *pld_info;
 	u32 *buffer = ACPI_CAST_PTR(u32, in_buffer);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpi_dbg.c linux-libre-4.7-gnu/drivers/acpi/acpi_dbg.c
--- linux-libre-4.6-gnu/drivers/acpi/acpi_dbg.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpi_dbg.c	2016-07-24 15:23:50.000000000 -0400
@@ -265,7 +265,7 @@ static int acpi_aml_write_kern(const cha
 	char *p;
 
 	ret = acpi_aml_lock_write(crc, ACPI_AML_OUT_KERN);
-	if (IS_ERR_VALUE(ret))
+	if (ret < 0)
 		return ret;
 	/* sync tail before inserting logs */
 	smp_mb();
@@ -286,7 +286,7 @@ static int acpi_aml_readb_kern(void)
 	char *p;
 
 	ret = acpi_aml_lock_read(crc, ACPI_AML_IN_KERN);
-	if (IS_ERR_VALUE(ret))
+	if (ret < 0)
 		return ret;
 	/* sync head before removing cmds */
 	smp_rmb();
@@ -330,7 +330,7 @@ again:
 				goto again;
 			break;
 		}
-		if (IS_ERR_VALUE(ret))
+		if (ret < 0)
 			break;
 		size += ret;
 		count -= ret;
@@ -373,7 +373,7 @@ again:
 			if (ret == 0)
 				goto again;
 		}
-		if (IS_ERR_VALUE(ret))
+		if (ret < 0)
 			break;
 		*(msg + size) = (char)ret;
 		size++;
@@ -526,7 +526,7 @@ static int acpi_aml_open(struct inode *i
 	}
 	acpi_aml_io.users++;
 err_lock:
-	if (IS_ERR_VALUE(ret)) {
+	if (ret < 0) {
 		if (acpi_aml_active_reader == file)
 			acpi_aml_active_reader = NULL;
 	}
@@ -587,7 +587,7 @@ static int acpi_aml_read_user(char __use
 	char *p;
 
 	ret = acpi_aml_lock_read(crc, ACPI_AML_OUT_USER);
-	if (IS_ERR_VALUE(ret))
+	if (ret < 0)
 		return ret;
 	/* sync head before removing logs */
 	smp_rmb();
@@ -602,7 +602,7 @@ static int acpi_aml_read_user(char __use
 	crc->tail = (crc->tail + n) & (ACPI_AML_BUF_SIZE - 1);
 	ret = n;
 out:
-	acpi_aml_unlock_fifo(ACPI_AML_OUT_USER, !IS_ERR_VALUE(ret));
+	acpi_aml_unlock_fifo(ACPI_AML_OUT_USER, ret >= 0);
 	return ret;
 }
 
@@ -634,7 +634,7 @@ again:
 					goto again;
 			}
 		}
-		if (IS_ERR_VALUE(ret)) {
+		if (ret < 0) {
 			if (!acpi_aml_running())
 				ret = 0;
 			break;
@@ -657,7 +657,7 @@ static int acpi_aml_write_user(const cha
 	char *p;
 
 	ret = acpi_aml_lock_write(crc, ACPI_AML_IN_USER);
-	if (IS_ERR_VALUE(ret))
+	if (ret < 0)
 		return ret;
 	/* sync tail before inserting cmds */
 	smp_mb();
@@ -672,7 +672,7 @@ static int acpi_aml_write_user(const cha
 	crc->head = (crc->head + n) & (ACPI_AML_BUF_SIZE - 1);
 	ret = n;
 out:
-	acpi_aml_unlock_fifo(ACPI_AML_IN_USER, !IS_ERR_VALUE(ret));
+	acpi_aml_unlock_fifo(ACPI_AML_IN_USER, ret >= 0);
 	return n;
 }
 
@@ -704,7 +704,7 @@ again:
 					goto again;
 			}
 		}
-		if (IS_ERR_VALUE(ret)) {
+		if (ret < 0) {
 			if (!acpi_aml_running())
 				ret = 0;
 			break;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpi_processor.c linux-libre-4.7-gnu/drivers/acpi/acpi_processor.c
--- linux-libre-4.6-gnu/drivers/acpi/acpi_processor.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpi_processor.c	2016-07-24 15:23:50.000000000 -0400
@@ -331,15 +331,6 @@ static int acpi_processor_get_info(struc
 		pr->throttling.duty_width = acpi_gbl_FADT.duty_width;
 
 		pr->pblk = object.processor.pblk_address;
-
-		/*
-		 * We don't care about error returns - we just try to mark
-		 * these reserved so that nobody else is confused into thinking
-		 * that this region might be unused..
-		 *
-		 * (In particular, allocating the IO range for Cardbus)
-		 */
-		request_region(pr->throttling.address, 6, "ACPI CPU throttle");
 	}
 
 	/*
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/acpi_video.c linux-libre-4.7-gnu/drivers/acpi/acpi_video.c
--- linux-libre-4.6-gnu/drivers/acpi/acpi_video.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/acpi_video.c	2016-07-24 15:23:50.000000000 -0400
@@ -191,19 +191,6 @@ struct acpi_video_device_cap {
 	u8 _DDC:1;		/* Return the EDID for this device */
 };
 
-struct acpi_video_brightness_flags {
-	u8 _BCL_no_ac_battery_levels:1;	/* no AC/Battery levels in _BCL */
-	u8 _BCL_reversed:1;		/* _BCL package is in a reversed order */
-	u8 _BQC_use_index:1;		/* _BQC returns an index value */
-};
-
-struct acpi_video_device_brightness {
-	int curr;
-	int count;
-	int *levels;
-	struct acpi_video_brightness_flags flags;
-};
-
 struct acpi_video_device {
 	unsigned long device_id;
 	struct acpi_video_device_flags flags;
@@ -325,7 +312,7 @@ static const struct thermal_cooling_devi
  */
 
 static int
-acpi_video_device_lcd_query_levels(struct acpi_video_device *device,
+acpi_video_device_lcd_query_levels(acpi_handle handle,
 				   union acpi_object **levels)
 {
 	int status;
@@ -335,7 +322,7 @@ acpi_video_device_lcd_query_levels(struc
 
 	*levels = NULL;
 
-	status = acpi_evaluate_object(device->dev->handle, "_BCL", NULL, &buffer);
+	status = acpi_evaluate_object(handle, "_BCL", NULL, &buffer);
 	if (!ACPI_SUCCESS(status))
 		return status;
 	obj = (union acpi_object *)buffer.pointer;
@@ -766,36 +753,29 @@ static int acpi_video_bqc_quirk(struct a
 	return 0;
 }
 
-
-/*
- *  Arg:
- *	device	: video output device (LCD, CRT, ..)
- *
- *  Return Value:
- *	Maximum brightness level
- *
- *  Allocate and initialize device->brightness.
- */
-
-static int
-acpi_video_init_brightness(struct acpi_video_device *device)
+int acpi_video_get_levels(struct acpi_device *device,
+			  struct acpi_video_device_brightness **dev_br,
+			  int *pmax_level)
 {
 	union acpi_object *obj = NULL;
 	int i, max_level = 0, count = 0, level_ac_battery = 0;
-	unsigned long long level, level_old;
 	union acpi_object *o;
 	struct acpi_video_device_brightness *br = NULL;
-	int result = -EINVAL;
+	int result = 0;
 	u32 value;
 
-	if (!ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device, &obj))) {
+	if (!ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device->handle,
+								&obj))) {
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Could not query available "
 						"LCD brightness level\n"));
+		result = -ENODEV;
 		goto out;
 	}
 
-	if (obj->package.count < 2)
+	if (obj->package.count < 2) {
+		result = -EINVAL;
 		goto out;
+	}
 
 	br = kzalloc(sizeof(*br), GFP_KERNEL);
 	if (!br) {
@@ -861,6 +841,40 @@ acpi_video_init_brightness(struct acpi_v
 			    "Found unordered _BCL package"));
 
 	br->count = count;
+	*dev_br = br;
+	if (pmax_level)
+		*pmax_level = max_level;
+
+out:
+	kfree(obj);
+	return result;
+out_free:
+	kfree(br);
+	goto out;
+}
+EXPORT_SYMBOL(acpi_video_get_levels);
+
+/*
+ *  Arg:
+ *	device	: video output device (LCD, CRT, ..)
+ *
+ *  Return Value:
+ *	Maximum brightness level
+ *
+ *  Allocate and initialize device->brightness.
+ */
+
+static int
+acpi_video_init_brightness(struct acpi_video_device *device)
+{
+	int i, max_level = 0;
+	unsigned long long level, level_old;
+	struct acpi_video_device_brightness *br = NULL;
+	int result = -EINVAL;
+
+	result = acpi_video_get_levels(device->dev, &br, &max_level);
+	if (result)
+		return result;
 	device->brightness = br;
 
 	/* _BQC uses INDEX while _BCL uses VALUE in some laptops */
@@ -903,17 +917,13 @@ set_level:
 		goto out_free_levels;
 
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-			  "found %d brightness levels\n", count - 2));
-	kfree(obj);
-	return result;
+			  "found %d brightness levels\n", br->count - 2));
+	return 0;
 
 out_free_levels:
 	kfree(br->levels);
-out_free:
 	kfree(br);
-out:
 	device->brightness = NULL;
-	kfree(obj);
 	return result;
 }
 
@@ -1730,7 +1740,7 @@ static void acpi_video_run_bcl_for_osi(s
 
 	mutex_lock(&video->device_list_lock);
 	list_for_each_entry(dev, &video->video_device_list, entry) {
-		if (!acpi_video_device_lcd_query_levels(dev, &levels))
+		if (!acpi_video_device_lcd_query_levels(dev->dev->handle, &levels))
 			kfree(levels);
 	}
 	mutex_unlock(&video->device_list_lock);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/battery.c linux-libre-4.7-gnu/drivers/acpi/battery.c
--- linux-libre-4.6-gnu/drivers/acpi/battery.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/battery.c	2016-07-24 15:23:50.000000000 -0400
@@ -1316,7 +1316,7 @@ static int __init acpi_battery_init(void
 
 static void __exit acpi_battery_exit(void)
 {
-	async_synchronize_cookie(async_cookie);
+	async_synchronize_cookie(async_cookie + 1);
 	acpi_bus_unregister_driver(&acpi_battery_driver);
 #ifdef CONFIG_ACPI_PROCFS_POWER
 	acpi_unlock_battery_dir(acpi_battery_dir);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/blacklist.c linux-libre-4.7-gnu/drivers/acpi/blacklist.c
--- linux-libre-4.6-gnu/drivers/acpi/blacklist.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/blacklist.c	2016-07-24 15:23:50.000000000 -0400
@@ -3,7 +3,7 @@
  *
  *  Check to see if the given machine has a known bad ACPI BIOS
  *  or if the BIOS is too old.
- *  Check given machine against acpi_osi_dmi_table[].
+ *  Check given machine against acpi_rev_dmi_table[].
  *
  *  Copyright (C) 2004 Len Brown <len.brown@intel.com>
  *  Copyright (C) 2002 Andy Grover <andrew.grover@intel.com>
@@ -47,7 +47,7 @@ struct acpi_blacklist_item {
 	u32 is_critical_error;
 };
 
-static struct dmi_system_id acpi_osi_dmi_table[] __initdata;
+static struct dmi_system_id acpi_rev_dmi_table[] __initdata;
 
 /*
  * POLICY: If *anything* doesn't work, put it on the blacklist.
@@ -128,36 +128,12 @@ int __init acpi_blacklisted(void)
 		}
 	}
 
-	dmi_check_system(acpi_osi_dmi_table);
+	(void)early_acpi_osi_init();
+	dmi_check_system(acpi_rev_dmi_table);
 
 	return blacklisted;
 }
 #ifdef CONFIG_DMI
-static int __init dmi_enable_osi_linux(const struct dmi_system_id *d)
-{
-	acpi_dmi_osi_linux(1, d);	/* enable */
-	return 0;
-}
-static int __init dmi_disable_osi_vista(const struct dmi_system_id *d)
-{
-	printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident);
-	acpi_osi_setup("!Windows 2006");
-	acpi_osi_setup("!Windows 2006 SP1");
-	acpi_osi_setup("!Windows 2006 SP2");
-	return 0;
-}
-static int __init dmi_disable_osi_win7(const struct dmi_system_id *d)
-{
-	printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident);
-	acpi_osi_setup("!Windows 2009");
-	return 0;
-}
-static int __init dmi_disable_osi_win8(const struct dmi_system_id *d)
-{
-	printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident);
-	acpi_osi_setup("!Windows 2012");
-	return 0;
-}
 #ifdef CONFIG_ACPI_REV_OVERRIDE_POSSIBLE
 static int __init dmi_enable_rev_override(const struct dmi_system_id *d)
 {
@@ -168,169 +144,7 @@ static int __init dmi_enable_rev_overrid
 }
 #endif
 
-static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
-	{
-	.callback = dmi_disable_osi_vista,
-	.ident = "Fujitsu Siemens",
-	.matches = {
-		     DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
-		     DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile V5505"),
-		},
-	},
-	{
-	/*
-	 * There have a NVIF method in MSI GX723 DSDT need call by Nvidia
-	 * driver (e.g. nouveau) when user press brightness hotkey.
-	 * Currently, nouveau driver didn't do the job and it causes there
-	 * have a infinite while loop in DSDT when user press hotkey.
-	 * We add MSI GX723's dmi information to this table for workaround
-	 * this issue.
-	 * Will remove MSI GX723 from the table after nouveau grows support.
-	 */
-	.callback = dmi_disable_osi_vista,
-	.ident = "MSI GX723",
-	.matches = {
-		     DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
-		     DMI_MATCH(DMI_PRODUCT_NAME, "GX723"),
-		},
-	},
-	{
-	.callback = dmi_disable_osi_vista,
-	.ident = "Sony VGN-NS10J_S",
-	.matches = {
-		     DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
-		     DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS10J_S"),
-		},
-	},
-	{
-	.callback = dmi_disable_osi_vista,
-	.ident = "Sony VGN-SR290J",
-	.matches = {
-		     DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
-		     DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR290J"),
-		},
-	},
-	{
-	.callback = dmi_disable_osi_vista,
-	.ident = "VGN-NS50B_L",
-	.matches = {
-		     DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
-		     DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS50B_L"),
-		},
-	},
-	{
-	.callback = dmi_disable_osi_vista,
-	.ident = "VGN-SR19XN",
-	.matches = {
-		     DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
-		     DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR19XN"),
-		},
-	},
-	{
-	.callback = dmi_disable_osi_vista,
-	.ident = "Toshiba Satellite L355",
-	.matches = {
-		     DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
-		     DMI_MATCH(DMI_PRODUCT_VERSION, "Satellite L355"),
-		},
-	},
-	{
-	.callback = dmi_disable_osi_win7,
-	.ident = "ASUS K50IJ",
-	.matches = {
-		     DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
-		     DMI_MATCH(DMI_PRODUCT_NAME, "K50IJ"),
-		},
-	},
-	{
-	.callback = dmi_disable_osi_vista,
-	.ident = "Toshiba P305D",
-	.matches = {
-		     DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
-		     DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P305D"),
-		},
-	},
-	{
-	.callback = dmi_disable_osi_vista,
-	.ident = "Toshiba NB100",
-	.matches = {
-		     DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
-		     DMI_MATCH(DMI_PRODUCT_NAME, "NB100"),
-		},
-	},
-
-	/*
-	 * The wireless hotkey does not work on those machines when
-	 * returning true for _OSI("Windows 2012")
-	 */
-	{
-	.callback = dmi_disable_osi_win8,
-	.ident = "Dell Inspiron 7737",
-	.matches = {
-		    DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-		    DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7737"),
-		},
-	},
-	{
-	.callback = dmi_disable_osi_win8,
-	.ident = "Dell Inspiron 7537",
-	.matches = {
-		    DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-		    DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7537"),
-		},
-	},
-	{
-	.callback = dmi_disable_osi_win8,
-	.ident = "Dell Inspiron 5437",
-	.matches = {
-		    DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-		    DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5437"),
-		},
-	},
-	{
-	.callback = dmi_disable_osi_win8,
-	.ident = "Dell Inspiron 3437",
-	.matches = {
-		    DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-		    DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 3437"),
-		},
-	},
-	{
-	.callback = dmi_disable_osi_win8,
-	.ident = "Dell Vostro 3446",
-	.matches = {
-		    DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-		    DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3446"),
-		},
-	},
-	{
-	.callback = dmi_disable_osi_win8,
-	.ident = "Dell Vostro 3546",
-	.matches = {
-		    DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-		    DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3546"),
-		},
-	},
-
-	/*
-	 * BIOS invocation of _OSI(Linux) is almost always a BIOS bug.
-	 * Linux ignores it, except for the machines enumerated below.
-	 */
-
-	/*
-	 * Without this this EEEpc exports a non working WMI interface, with
-	 * this it exports a working "good old" eeepc_laptop interface, fixing
-	 * both brightness control, and rfkill not working.
-	 */
-	{
-	.callback = dmi_enable_osi_linux,
-	.ident = "Asus EEE PC 1015PX",
-	.matches = {
-		     DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer INC."),
-		     DMI_MATCH(DMI_PRODUCT_NAME, "1015PX"),
-		},
-	},
-
+static struct dmi_system_id acpi_rev_dmi_table[] __initdata = {
 #ifdef CONFIG_ACPI_REV_OVERRIDE_POSSIBLE
 	/*
 	 * DELL XPS 13 (2015) switches sound between HDA and I2S
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/bus.c linux-libre-4.7-gnu/drivers/acpi/bus.c
--- linux-libre-4.6-gnu/drivers/acpi/bus.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/bus.c	2016-07-24 15:23:50.000000000 -0400
@@ -925,11 +925,13 @@ void __init acpi_early_init(void)
 		goto error0;
 	}
 
-	status = acpi_load_tables();
-	if (ACPI_FAILURE(status)) {
-		printk(KERN_ERR PREFIX
-		       "Unable to load the System Description Tables\n");
-		goto error0;
+	if (acpi_gbl_group_module_level_code) {
+		status = acpi_load_tables();
+		if (ACPI_FAILURE(status)) {
+			printk(KERN_ERR PREFIX
+			       "Unable to load the System Description Tables\n");
+			goto error0;
+		}
 	}
 
 #ifdef CONFIG_X86
@@ -995,17 +997,10 @@ static int __init acpi_bus_init(void)
 
 	acpi_os_initialize1();
 
-	status = acpi_enable_subsystem(ACPI_NO_ACPI_ENABLE);
-	if (ACPI_FAILURE(status)) {
-		printk(KERN_ERR PREFIX
-		       "Unable to start the ACPI Interpreter\n");
-		goto error1;
-	}
-
 	/*
 	 * ACPI 2.0 requires the EC driver to be loaded and work before
-	 * the EC device is found in the namespace (i.e. before acpi_initialize_objects()
-	 * is called).
+	 * the EC device is found in the namespace (i.e. before
+	 * acpi_load_tables() is called).
 	 *
 	 * This is accomplished by looking for the ECDT table, and getting
 	 * the EC parameters out of that.
@@ -1013,6 +1008,22 @@ static int __init acpi_bus_init(void)
 	status = acpi_ec_ecdt_probe();
 	/* Ignore result. Not having an ECDT is not fatal. */
 
+	if (!acpi_gbl_group_module_level_code) {
+		status = acpi_load_tables();
+		if (ACPI_FAILURE(status)) {
+			printk(KERN_ERR PREFIX
+			       "Unable to load the System Description Tables\n");
+			goto error1;
+		}
+	}
+
+	status = acpi_enable_subsystem(ACPI_NO_ACPI_ENABLE);
+	if (ACPI_FAILURE(status)) {
+		printk(KERN_ERR PREFIX
+		       "Unable to start the ACPI Interpreter\n");
+		goto error1;
+	}
+
 	status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION);
 	if (ACPI_FAILURE(status)) {
 		printk(KERN_ERR PREFIX "Unable to initialize ACPI objects\n");
@@ -1040,7 +1051,7 @@ static int __init acpi_bus_init(void)
 	 * Maybe EC region is required at bus_scan/acpi_get_devices. So it
 	 * is necessary to enable it as early as possible.
 	 */
-	acpi_boot_ec_enable();
+	acpi_ec_dsdt_probe();
 
 	printk(KERN_INFO PREFIX "Interpreter enabled\n");
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/device_pm.c linux-libre-4.7-gnu/drivers/acpi/device_pm.c
--- linux-libre-4.6-gnu/drivers/acpi/device_pm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/device_pm.c	2016-07-24 15:23:50.000000000 -0400
@@ -319,6 +319,7 @@ int acpi_device_fix_up_power(struct acpi
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(acpi_device_fix_up_power);
 
 int acpi_device_update_power(struct acpi_device *device, int *state_p)
 {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/device_sysfs.c linux-libre-4.7-gnu/drivers/acpi/device_sysfs.c
--- linux-libre-4.6-gnu/drivers/acpi/device_sysfs.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/device_sysfs.c	2016-07-24 15:23:50.000000000 -0400
@@ -35,7 +35,7 @@ static ssize_t acpi_object_path(acpi_han
 	if (result)
 		return result;
 
-	result = sprintf(buf, "%s\n", (char*)path.pointer);
+	result = sprintf(buf, "%s\n", (char *)path.pointer);
 	kfree(path.pointer);
 	return result;
 }
@@ -333,7 +333,8 @@ int acpi_device_modalias(struct device *
 EXPORT_SYMBOL_GPL(acpi_device_modalias);
 
 static ssize_t
-acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, char *buf) {
+acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
 	return __acpi_device_modalias(to_acpi_device(dev), buf, 1024);
 }
 static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL);
@@ -397,7 +398,8 @@ acpi_eject_store(struct device *d, struc
 static DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store);
 
 static ssize_t
-acpi_device_hid_show(struct device *dev, struct device_attribute *attr, char *buf) {
+acpi_device_hid_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
 	struct acpi_device *acpi_dev = to_acpi_device(dev);
 
 	return sprintf(buf, "%s\n", acpi_device_hid(acpi_dev));
@@ -467,12 +469,27 @@ acpi_device_sun_show(struct device *dev,
 
 	status = acpi_evaluate_integer(acpi_dev->handle, "_SUN", NULL, &sun);
 	if (ACPI_FAILURE(status))
-		return -ENODEV;
+		return -EIO;
 
 	return sprintf(buf, "%llu\n", sun);
 }
 static DEVICE_ATTR(sun, 0444, acpi_device_sun_show, NULL);
 
+static ssize_t
+acpi_device_hrv_show(struct device *dev, struct device_attribute *attr,
+		     char *buf) {
+	struct acpi_device *acpi_dev = to_acpi_device(dev);
+	acpi_status status;
+	unsigned long long hrv;
+
+	status = acpi_evaluate_integer(acpi_dev->handle, "_HRV", NULL, &hrv);
+	if (ACPI_FAILURE(status))
+		return -EIO;
+
+	return sprintf(buf, "%llu\n", hrv);
+}
+static DEVICE_ATTR(hrv, 0444, acpi_device_hrv_show, NULL);
+
 static ssize_t status_show(struct device *dev, struct device_attribute *attr,
 				char *buf) {
 	struct acpi_device *acpi_dev = to_acpi_device(dev);
@@ -481,7 +498,7 @@ static ssize_t status_show(struct device
 
 	status = acpi_evaluate_integer(acpi_dev->handle, "_STA", NULL, &sta);
 	if (ACPI_FAILURE(status))
-		return -ENODEV;
+		return -EIO;
 
 	return sprintf(buf, "%llu\n", sta);
 }
@@ -541,16 +558,22 @@ int acpi_device_setup_files(struct acpi_
 			goto end;
 	}
 
+	if (acpi_has_method(dev->handle, "_HRV")) {
+		result = device_create_file(&dev->dev, &dev_attr_hrv);
+		if (result)
+			goto end;
+	}
+
 	if (acpi_has_method(dev->handle, "_STA")) {
 		result = device_create_file(&dev->dev, &dev_attr_status);
 		if (result)
 			goto end;
 	}
 
-        /*
-         * If device has _EJ0, 'eject' file is created that is used to trigger
-         * hot-removal function from userland.
-         */
+	/*
+	 * If device has _EJ0, 'eject' file is created that is used to trigger
+	 * hot-removal function from userland.
+	 */
 	if (acpi_has_method(dev->handle, "_EJ0")) {
 		result = device_create_file(&dev->dev, &dev_attr_eject);
 		if (result)
@@ -604,6 +627,9 @@ void acpi_device_remove_files(struct acp
 	if (acpi_has_method(dev->handle, "_SUN"))
 		device_remove_file(&dev->dev, &dev_attr_sun);
 
+	if (acpi_has_method(dev->handle, "_HRV"))
+		device_remove_file(&dev->dev, &dev_attr_hrv);
+
 	if (dev->pnp.unique_id)
 		device_remove_file(&dev->dev, &dev_attr_uid);
 	if (dev->pnp.type.bus_address)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/ec.c linux-libre-4.7-gnu/drivers/acpi/ec.c
--- linux-libre-4.6-gnu/drivers/acpi/ec.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/ec.c	2016-07-24 15:23:50.000000000 -0400
@@ -105,8 +105,8 @@ enum ec_command {
 enum {
 	EC_FLAGS_QUERY_PENDING,		/* Query is pending */
 	EC_FLAGS_QUERY_GUARDING,	/* Guard for SCI_EVT check */
-	EC_FLAGS_HANDLERS_INSTALLED,	/* Handlers for GPE and
-					 * OpReg are installed */
+	EC_FLAGS_GPE_HANDLER_INSTALLED,	/* GPE handler installed */
+	EC_FLAGS_EC_HANDLER_INSTALLED,	/* OpReg handler installed */
 	EC_FLAGS_STARTED,		/* Driver is started */
 	EC_FLAGS_STOPPED,		/* Driver is stopped */
 	EC_FLAGS_COMMAND_STORM,		/* GPE storms occurred to the
@@ -175,10 +175,9 @@ static void acpi_ec_event_processor(stru
 struct acpi_ec *boot_ec, *first_ec;
 EXPORT_SYMBOL(first_ec);
 
-static int EC_FLAGS_VALIDATE_ECDT; /* ASUStec ECDTs need to be validated */
-static int EC_FLAGS_SKIP_DSDT_SCAN; /* Not all BIOS survive early DSDT scan */
 static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */
 static int EC_FLAGS_QUERY_HANDSHAKE; /* Needs QR_EC issued when SCI_EVT set */
+static int EC_FLAGS_CORRECT_ECDT; /* Needs ECDT port address correction */
 
 /* --------------------------------------------------------------------------
  *                           Logging/Debugging
@@ -367,7 +366,8 @@ static inline void acpi_ec_clear_gpe(str
 static void acpi_ec_submit_request(struct acpi_ec *ec)
 {
 	ec->reference_count++;
-	if (ec->reference_count == 1)
+	if (test_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags) &&
+	    ec->reference_count == 1)
 		acpi_ec_enable_gpe(ec, true);
 }
 
@@ -376,7 +376,8 @@ static void acpi_ec_complete_request(str
 	bool flushed = false;
 
 	ec->reference_count--;
-	if (ec->reference_count == 0)
+	if (test_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags) &&
+	    ec->reference_count == 0)
 		acpi_ec_disable_gpe(ec, true);
 	flushed = acpi_ec_flushed(ec);
 	if (flushed)
@@ -1287,52 +1288,75 @@ static int ec_install_handlers(struct ac
 {
 	acpi_status status;
 
-	if (test_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags))
-		return 0;
-	status = acpi_install_gpe_raw_handler(NULL, ec->gpe,
-				  ACPI_GPE_EDGE_TRIGGERED,
-				  &acpi_ec_gpe_handler, ec);
-	if (ACPI_FAILURE(status))
-		return -ENODEV;
-
 	acpi_ec_start(ec, false);
-	status = acpi_install_address_space_handler(ec->handle,
-						    ACPI_ADR_SPACE_EC,
-						    &acpi_ec_space_handler,
-						    NULL, ec);
-	if (ACPI_FAILURE(status)) {
-		if (status == AE_NOT_FOUND) {
-			/*
-			 * Maybe OS fails in evaluating the _REG object.
-			 * The AE_NOT_FOUND error will be ignored and OS
-			 * continue to initialize EC.
-			 */
-			pr_err("Fail in evaluating the _REG object"
-				" of EC device. Broken bios is suspected.\n");
-		} else {
-			acpi_ec_stop(ec, false);
-			acpi_remove_gpe_handler(NULL, ec->gpe,
-				&acpi_ec_gpe_handler);
-			return -ENODEV;
+
+	if (!test_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags)) {
+		status = acpi_install_address_space_handler(ec->handle,
+							    ACPI_ADR_SPACE_EC,
+							    &acpi_ec_space_handler,
+							    NULL, ec);
+		if (ACPI_FAILURE(status)) {
+			if (status == AE_NOT_FOUND) {
+				/*
+				 * Maybe OS fails in evaluating the _REG
+				 * object. The AE_NOT_FOUND error will be
+				 * ignored and OS * continue to initialize
+				 * EC.
+				 */
+				pr_err("Fail in evaluating the _REG object"
+					" of EC device. Broken bios is suspected.\n");
+			} else {
+				acpi_ec_stop(ec, false);
+				return -ENODEV;
+			}
+		}
+		set_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags);
+	}
+
+	if (!test_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags)) {
+		status = acpi_install_gpe_raw_handler(NULL, ec->gpe,
+					  ACPI_GPE_EDGE_TRIGGERED,
+					  &acpi_ec_gpe_handler, ec);
+		/* This is not fatal as we can poll EC events */
+		if (ACPI_SUCCESS(status)) {
+			set_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags);
+			if (test_bit(EC_FLAGS_STARTED, &ec->flags) &&
+			    ec->reference_count >= 1)
+				acpi_ec_enable_gpe(ec, true);
 		}
 	}
 
-	set_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags);
 	return 0;
 }
 
 static void ec_remove_handlers(struct acpi_ec *ec)
 {
-	if (!test_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags))
-		return;
+	if (test_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags)) {
+		if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle,
+					ACPI_ADR_SPACE_EC, &acpi_ec_space_handler)))
+			pr_err("failed to remove space handler\n");
+		clear_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags);
+	}
+
+	/*
+	 * Stops handling the EC transactions after removing the operation
+	 * region handler. This is required because _REG(DISCONNECT)
+	 * invoked during the removal can result in new EC transactions.
+	 *
+	 * Flushes the EC requests and thus disables the GPE before
+	 * removing the GPE handler. This is required by the current ACPICA
+	 * GPE core. ACPICA GPE core will automatically disable a GPE when
+	 * it is indicated but there is no way to handle it. So the drivers
+	 * must disable the GPEs prior to removing the GPE handlers.
+	 */
 	acpi_ec_stop(ec, false);
-	if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle,
-				ACPI_ADR_SPACE_EC, &acpi_ec_space_handler)))
-		pr_err("failed to remove space handler\n");
-	if (ACPI_FAILURE(acpi_remove_gpe_handler(NULL, ec->gpe,
-				&acpi_ec_gpe_handler)))
-		pr_err("failed to remove gpe handler\n");
-	clear_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags);
+
+	if (test_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags)) {
+		if (ACPI_FAILURE(acpi_remove_gpe_handler(NULL, ec->gpe,
+					&acpi_ec_gpe_handler)))
+			pr_err("failed to remove gpe handler\n");
+		clear_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags);
+	}
 }
 
 static int acpi_ec_add(struct acpi_device *device)
@@ -1344,11 +1368,12 @@ static int acpi_ec_add(struct acpi_devic
 	strcpy(acpi_device_class(device), ACPI_EC_CLASS);
 
 	/* Check for boot EC */
-	if (boot_ec &&
-	    (boot_ec->handle == device->handle ||
-	     boot_ec->handle == ACPI_ROOT_OBJECT)) {
+	if (boot_ec) {
 		ec = boot_ec;
 		boot_ec = NULL;
+		ec_remove_handlers(ec);
+		if (first_ec == ec)
+			first_ec = NULL;
 	} else {
 		ec = make_acpi_ec();
 		if (!ec)
@@ -1432,34 +1457,35 @@ ec_parse_io_ports(struct acpi_resource *
 	return AE_OK;
 }
 
-int __init acpi_boot_ec_enable(void)
-{
-	if (!boot_ec || test_bit(EC_FLAGS_HANDLERS_INSTALLED, &boot_ec->flags))
-		return 0;
-	if (!ec_install_handlers(boot_ec)) {
-		first_ec = boot_ec;
-		return 0;
-	}
-	return -EFAULT;
-}
-
 static const struct acpi_device_id ec_device_ids[] = {
 	{"PNP0C09", 0},
 	{"", 0},
 };
 
-/* Some BIOS do not survive early DSDT scan, skip it */
-static int ec_skip_dsdt_scan(const struct dmi_system_id *id)
+int __init acpi_ec_dsdt_probe(void)
 {
-	EC_FLAGS_SKIP_DSDT_SCAN = 1;
-	return 0;
-}
+	acpi_status status;
 
-/* ASUStek often supplies us with broken ECDT, validate it */
-static int ec_validate_ecdt(const struct dmi_system_id *id)
-{
-	EC_FLAGS_VALIDATE_ECDT = 1;
-	return 0;
+	if (boot_ec)
+		return 0;
+
+	/*
+	 * Finding EC from DSDT if there is no ECDT EC available. When this
+	 * function is invoked, ACPI tables have been fully loaded, we can
+	 * walk namespace now.
+	 */
+	boot_ec = make_acpi_ec();
+	if (!boot_ec)
+		return -ENOMEM;
+	status = acpi_get_devices(ec_device_ids[0].id,
+				  ec_parse_device, boot_ec, NULL);
+	if (ACPI_FAILURE(status) || !boot_ec->handle)
+		return -ENODEV;
+	if (!ec_install_handlers(boot_ec)) {
+		first_ec = boot_ec;
+		return 0;
+	}
+	return -EFAULT;
 }
 
 #if 0
@@ -1503,30 +1529,29 @@ static int ec_clear_on_resume(const stru
 	return 0;
 }
 
+static int ec_correct_ecdt(const struct dmi_system_id *id)
+{
+	pr_debug("Detected system needing ECDT address correction.\n");
+	EC_FLAGS_CORRECT_ECDT = 1;
+	return 0;
+}
+
 static struct dmi_system_id ec_dmi_table[] __initdata = {
 	{
-	ec_skip_dsdt_scan, "Compal JFL92", {
-	DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"),
-	DMI_MATCH(DMI_BOARD_NAME, "JFL92") }, NULL},
+	ec_correct_ecdt, "Asus L4R", {
+	DMI_MATCH(DMI_BIOS_VERSION, "1008.006"),
+	DMI_MATCH(DMI_PRODUCT_NAME, "L4R"),
+	DMI_MATCH(DMI_BOARD_NAME, "L4R") }, NULL},
 	{
-	ec_validate_ecdt, "MSI MS-171F", {
+	ec_correct_ecdt, "Asus M6R", {
+	DMI_MATCH(DMI_BIOS_VERSION, "0207"),
+	DMI_MATCH(DMI_PRODUCT_NAME, "M6R"),
+	DMI_MATCH(DMI_BOARD_NAME, "M6R") }, NULL},
+	{
+	ec_correct_ecdt, "MSI MS-171F", {
 	DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star"),
 	DMI_MATCH(DMI_PRODUCT_NAME, "MS-171F"),}, NULL},
 	{
-	ec_validate_ecdt, "ASUS hardware", {
-	DMI_MATCH(DMI_BIOS_VENDOR, "ASUS") }, NULL},
-	{
-	ec_validate_ecdt, "ASUS hardware", {
-	DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc.") }, NULL},
-	{
-	ec_skip_dsdt_scan, "HP Folio 13", {
-	DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-	DMI_MATCH(DMI_PRODUCT_NAME, "HP Folio 13"),}, NULL},
-	{
-	ec_validate_ecdt, "ASUS hardware", {
-	DMI_MATCH(DMI_SYS_VENDOR, "ASUSTek Computer Inc."),
-	DMI_MATCH(DMI_PRODUCT_NAME, "L4R"),}, NULL},
-	{
 	ec_clear_on_resume, "Samsung hardware", {
 	DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD.")}, NULL},
 	{},
@@ -1534,8 +1559,8 @@ static struct dmi_system_id ec_dmi_table
 
 int __init acpi_ec_ecdt_probe(void)
 {
+	int ret = 0;
 	acpi_status status;
-	struct acpi_ec *saved_ec = NULL;
 	struct acpi_table_ecdt *ecdt_ptr;
 
 	boot_ec = make_acpi_ec();
@@ -1547,67 +1572,45 @@ int __init acpi_ec_ecdt_probe(void)
 	dmi_check_system(ec_dmi_table);
 	status = acpi_get_table(ACPI_SIG_ECDT, 1,
 				(struct acpi_table_header **)&ecdt_ptr);
-	if (ACPI_SUCCESS(status)) {
-		pr_info("EC description table is found, configuring boot EC\n");
-		boot_ec->command_addr = ecdt_ptr->control.address;
-		boot_ec->data_addr = ecdt_ptr->data.address;
-		boot_ec->gpe = ecdt_ptr->gpe;
-		boot_ec->handle = ACPI_ROOT_OBJECT;
-		acpi_get_handle(ACPI_ROOT_OBJECT, ecdt_ptr->id,
-				&boot_ec->handle);
-		/* Don't trust ECDT, which comes from ASUSTek */
-		if (!EC_FLAGS_VALIDATE_ECDT)
-			goto install;
-		saved_ec = kmemdup(boot_ec, sizeof(struct acpi_ec), GFP_KERNEL);
-		if (!saved_ec)
-			return -ENOMEM;
-	/* fall through */
+	if (ACPI_FAILURE(status)) {
+		ret = -ENODEV;
+		goto error;
 	}
 
-	if (EC_FLAGS_SKIP_DSDT_SCAN) {
-		kfree(saved_ec);
-		return -ENODEV;
+	if (!ecdt_ptr->control.address || !ecdt_ptr->data.address) {
+		/*
+		 * Asus X50GL:
+		 * https://bugzilla.kernel.org/show_bug.cgi?id=11880
+		 */
+		ret = -ENODEV;
+		goto error;
 	}
 
-	/* This workaround is needed only on some broken machines,
-	 * which require early EC, but fail to provide ECDT */
-	pr_debug("Look up EC in DSDT\n");
-	status = acpi_get_devices(ec_device_ids[0].id, ec_parse_device,
-					boot_ec, NULL);
-	/* Check that acpi_get_devices actually find something */
-	if (ACPI_FAILURE(status) || !boot_ec->handle)
-		goto error;
-	if (saved_ec) {
-		/* try to find good ECDT from ASUSTek */
-		if (saved_ec->command_addr != boot_ec->command_addr ||
-		    saved_ec->data_addr != boot_ec->data_addr ||
-		    saved_ec->gpe != boot_ec->gpe ||
-		    saved_ec->handle != boot_ec->handle)
-			pr_info("ASUSTek keeps feeding us with broken "
-			"ECDT tables, which are very hard to workaround. "
-			"Trying to use DSDT EC info instead. Please send "
-			"output of acpidump to linux-acpi@vger.kernel.org\n");
-		kfree(saved_ec);
-		saved_ec = NULL;
+	pr_info("EC description table is found, configuring boot EC\n");
+	if (EC_FLAGS_CORRECT_ECDT) {
+		/*
+		 * Asus L4R, Asus M6R
+		 * https://bugzilla.kernel.org/show_bug.cgi?id=9399
+		 * MSI MS-171F
+		 * https://bugzilla.kernel.org/show_bug.cgi?id=12461
+		 */
+		boot_ec->command_addr = ecdt_ptr->data.address;
+		boot_ec->data_addr = ecdt_ptr->control.address;
 	} else {
-		/* We really need to limit this workaround, the only ASUS,
-		* which needs it, has fake EC._INI method, so use it as flag.
-		* Keep boot_ec struct as it will be needed soon.
-		*/
-		if (!dmi_name_in_vendors("ASUS") ||
-		    !acpi_has_method(boot_ec->handle, "_INI"))
-			return -ENODEV;
+		boot_ec->command_addr = ecdt_ptr->control.address;
+		boot_ec->data_addr = ecdt_ptr->data.address;
 	}
-install:
-	if (!ec_install_handlers(boot_ec)) {
+	boot_ec->gpe = ecdt_ptr->gpe;
+	boot_ec->handle = ACPI_ROOT_OBJECT;
+	ret = ec_install_handlers(boot_ec);
+	if (!ret)
 		first_ec = boot_ec;
-		return 0;
-	}
 error:
-	kfree(boot_ec);
-	kfree(saved_ec);
-	boot_ec = NULL;
-	return -ENODEV;
+	if (ret) {
+		kfree(boot_ec);
+		boot_ec = NULL;
+	}
+	return ret;
 }
 
 static int param_set_event_clearing(const char *val, struct kernel_param *kp)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/evged.c linux-libre-4.7-gnu/drivers/acpi/evged.c
--- linux-libre-4.6-gnu/drivers/acpi/evged.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/acpi/evged.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,154 @@
+/*
+ * Generic Event Device for ACPI.
+ *
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 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.
+ *
+ * Generic Event Device allows platforms to handle interrupts in ACPI
+ * ASL statements. It follows very similar to  _EVT method approach
+ * from GPIO events. All interrupts are listed in _CRS and the handler
+ * is written in _EVT method. Here is an example.
+ *
+ * Device (GED0)
+ * {
+ *
+ *     Name (_HID, "ACPI0013")
+ *     Name (_UID, 0)
+ *     Method (_CRS, 0x0, Serialized)
+ *     {
+ *		Name (RBUF, ResourceTemplate ()
+ *		{
+ *		Interrupt(ResourceConsumer, Edge, ActiveHigh, Shared, , , )
+ *		{123}
+ *		}
+ *     })
+ *
+ *     Method (_EVT, 1) {
+ *             if (Lequal(123, Arg0))
+ *             {
+ *             }
+ *     }
+ * }
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/platform_device.h>
+#include <linux/acpi.h>
+
+#define MODULE_NAME	"acpi-ged"
+
+struct acpi_ged_event {
+	struct list_head node;
+	struct device *dev;
+	unsigned int gsi;
+	unsigned int irq;
+	acpi_handle handle;
+};
+
+static irqreturn_t acpi_ged_irq_handler(int irq, void *data)
+{
+	struct acpi_ged_event *event = data;
+	acpi_status acpi_ret;
+
+	acpi_ret = acpi_execute_simple_method(event->handle, NULL, event->gsi);
+	if (ACPI_FAILURE(acpi_ret))
+		dev_err_once(event->dev, "IRQ method execution failed\n");
+
+	return IRQ_HANDLED;
+}
+
+static acpi_status acpi_ged_request_interrupt(struct acpi_resource *ares,
+					      void *context)
+{
+	struct acpi_ged_event *event;
+	unsigned int irq;
+	unsigned int gsi;
+	unsigned int irqflags = IRQF_ONESHOT;
+	struct device *dev = context;
+	acpi_handle handle = ACPI_HANDLE(dev);
+	acpi_handle evt_handle;
+	struct resource r;
+	struct acpi_resource_irq *p = &ares->data.irq;
+	struct acpi_resource_extended_irq *pext = &ares->data.extended_irq;
+
+	if (ares->type == ACPI_RESOURCE_TYPE_END_TAG)
+		return AE_OK;
+
+	if (!acpi_dev_resource_interrupt(ares, 0, &r)) {
+		dev_err(dev, "unable to parse IRQ resource\n");
+		return AE_ERROR;
+	}
+	if (ares->type == ACPI_RESOURCE_TYPE_IRQ)
+		gsi = p->interrupts[0];
+	else
+		gsi = pext->interrupts[0];
+
+	irq = r.start;
+
+	if (ACPI_FAILURE(acpi_get_handle(handle, "_EVT", &evt_handle))) {
+		dev_err(dev, "cannot locate _EVT method\n");
+		return AE_ERROR;
+	}
+
+	dev_info(dev, "GED listening GSI %u @ IRQ %u\n", gsi, irq);
+
+	event = devm_kzalloc(dev, sizeof(*event), GFP_KERNEL);
+	if (!event)
+		return AE_ERROR;
+
+	event->gsi = gsi;
+	event->dev = dev;
+	event->irq = irq;
+	event->handle = evt_handle;
+
+	if (r.flags & IORESOURCE_IRQ_SHAREABLE)
+		irqflags |= IRQF_SHARED;
+
+	if (devm_request_threaded_irq(dev, irq, NULL, acpi_ged_irq_handler,
+				      irqflags, "ACPI:Ged", event)) {
+		dev_err(dev, "failed to setup event handler for irq %u\n", irq);
+		return AE_ERROR;
+	}
+
+	return AE_OK;
+}
+
+static int ged_probe(struct platform_device *pdev)
+{
+	acpi_status acpi_ret;
+
+	acpi_ret = acpi_walk_resources(ACPI_HANDLE(&pdev->dev), "_CRS",
+				       acpi_ged_request_interrupt, &pdev->dev);
+	if (ACPI_FAILURE(acpi_ret)) {
+		dev_err(&pdev->dev, "unable to parse the _CRS record\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct acpi_device_id ged_acpi_ids[] = {
+	{"ACPI0013"},
+	{},
+};
+
+static struct platform_driver ged_driver = {
+	.probe = ged_probe,
+	.driver = {
+		.name = MODULE_NAME,
+		.acpi_match_table = ACPI_PTR(ged_acpi_ids),
+	},
+};
+builtin_platform_driver(ged_driver);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/internal.h linux-libre-4.7-gnu/drivers/acpi/internal.h
--- linux-libre-4.6-gnu/drivers/acpi/internal.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/internal.h	2016-07-24 15:23:50.000000000 -0400
@@ -20,7 +20,8 @@
 
 #define PREFIX "ACPI: "
 
-void acpi_initrd_initialize_tables(void);
+int early_acpi_osi_init(void);
+int acpi_osi_init(void);
 acpi_status acpi_os_initialize1(void);
 void init_acpi_device_notify(void);
 int acpi_scan_init(void);
@@ -180,7 +181,7 @@ typedef int (*acpi_ec_query_func) (void
 
 int acpi_ec_init(void);
 int acpi_ec_ecdt_probe(void);
-int acpi_boot_ec_enable(void);
+int acpi_ec_dsdt_probe(void);
 void acpi_ec_block_transactions(void);
 void acpi_ec_unblock_transactions(void);
 void acpi_ec_unblock_transactions_early(void);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/Kconfig linux-libre-4.7-gnu/drivers/acpi/Kconfig
--- linux-libre-4.6-gnu/drivers/acpi/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -5,10 +5,10 @@
 menuconfig ACPI
 	bool "ACPI (Advanced Configuration and Power Interface) Support"
 	depends on !IA64_HP_SIM
-	depends on IA64 || X86 || (ARM64 && EXPERT)
+	depends on IA64 || X86 || ARM64
 	depends on PCI
 	select PNP
-	default y
+	default y if (IA64 || X86)
 	help
 	  Advanced Configuration and Power Interface (ACPI) support for 
 	  Linux requires an ACPI-compliant platform (hardware/firmware),
@@ -311,12 +311,12 @@ config ACPI_CUSTOM_DSDT
 	bool
 	default ACPI_CUSTOM_DSDT_FILE != ""
 
-config ACPI_INITRD_TABLE_OVERRIDE
-	bool "ACPI tables override via initrd"
+config ACPI_TABLE_UPGRADE
+	bool "Allow upgrading ACPI tables via initrd"
 	depends on BLK_DEV_INITRD && X86
-	default n
+	default y
 	help
-	  This option provides functionality to override arbitrary ACPI tables
+	  This option provides functionality to upgrade arbitrary ACPI tables
 	  via initrd. No functional change if no ACPI tables are passed via
 	  initrd, therefore it's safe to say Y.
 	  See Documentation/acpi/initrd_table_override.txt for details
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/Makefile linux-libre-4.7-gnu/drivers/acpi/Makefile
--- linux-libre-4.6-gnu/drivers/acpi/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -18,7 +18,7 @@ obj-$(CONFIG_ACPI)		+= acpi.o \
 					acpica/
 
 # All the builtin files are in the "acpi." module_param namespace.
-acpi-y				+= osl.o utils.o reboot.o
+acpi-y				+= osi.o osl.o utils.o reboot.o
 acpi-y				+= nvs.o
 
 # Power management related files
@@ -47,6 +47,7 @@ acpi-$(CONFIG_ARM_AMBA)	+= acpi_amba.o
 acpi-y				+= int340x_thermal.o
 acpi-y				+= power.o
 acpi-y				+= event.o
+acpi-$(CONFIG_ACPI_REDUCED_HARDWARE_ONLY) += evged.o
 acpi-y				+= sysfs.o
 acpi-y				+= property.o
 acpi-$(CONFIG_X86)		+= acpi_cmos_rtc.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/nfit.c linux-libre-4.7-gnu/drivers/acpi/nfit.c
--- linux-libre-4.6-gnu/drivers/acpi/nfit.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/nfit.c	2016-07-24 15:23:50.000000000 -0400
@@ -45,6 +45,11 @@ module_param(scrub_overflow_abort, uint,
 MODULE_PARM_DESC(scrub_overflow_abort,
 		"Number of times we overflow ARS results before abort");
 
+static bool disable_vendor_specific;
+module_param(disable_vendor_specific, bool, S_IRUGO);
+MODULE_PARM_DESC(disable_vendor_specific,
+		"Limit commands to the publicly specified set\n");
+
 static struct workqueue_struct *nfit_wq;
 
 struct nfit_table_prev {
@@ -171,33 +176,46 @@ static int acpi_nfit_ctl(struct nvdimm_b
 		unsigned int buf_len, int *cmd_rc)
 {
 	struct acpi_nfit_desc *acpi_desc = to_acpi_nfit_desc(nd_desc);
-	const struct nd_cmd_desc *desc = NULL;
 	union acpi_object in_obj, in_buf, *out_obj;
+	const struct nd_cmd_desc *desc = NULL;
 	struct device *dev = acpi_desc->dev;
+	struct nd_cmd_pkg *call_pkg = NULL;
 	const char *cmd_name, *dimm_name;
-	unsigned long dsm_mask;
+	unsigned long cmd_mask, dsm_mask;
 	acpi_handle handle;
+	unsigned int func;
 	const u8 *uuid;
 	u32 offset;
 	int rc, i;
 
+	func = cmd;
+	if (cmd == ND_CMD_CALL) {
+		call_pkg = buf;
+		func = call_pkg->nd_command;
+	}
+
 	if (nvdimm) {
 		struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
 		struct acpi_device *adev = nfit_mem->adev;
 
 		if (!adev)
 			return -ENOTTY;
+		if (call_pkg && nfit_mem->family != call_pkg->nd_family)
+			return -ENOTTY;
+
 		dimm_name = nvdimm_name(nvdimm);
 		cmd_name = nvdimm_cmd_name(cmd);
+		cmd_mask = nvdimm_cmd_mask(nvdimm);
 		dsm_mask = nfit_mem->dsm_mask;
 		desc = nd_cmd_dimm_desc(cmd);
-		uuid = to_nfit_uuid(NFIT_DEV_DIMM);
+		uuid = to_nfit_uuid(nfit_mem->family);
 		handle = adev->handle;
 	} else {
 		struct acpi_device *adev = to_acpi_dev(acpi_desc);
 
 		cmd_name = nvdimm_bus_cmd_name(cmd);
-		dsm_mask = nd_desc->dsm_mask;
+		cmd_mask = nd_desc->cmd_mask;
+		dsm_mask = cmd_mask;
 		desc = nd_cmd_bus_desc(cmd);
 		uuid = to_nfit_uuid(NFIT_DEV_BUS);
 		handle = adev->handle;
@@ -207,7 +225,7 @@ static int acpi_nfit_ctl(struct nvdimm_b
 	if (!desc || (cmd && (desc->out_num + desc->in_num == 0)))
 		return -ENOTTY;
 
-	if (!test_bit(cmd, &dsm_mask))
+	if (!test_bit(cmd, &cmd_mask) || !test_bit(func, &dsm_mask))
 		return -ENOTTY;
 
 	in_obj.type = ACPI_TYPE_PACKAGE;
@@ -222,21 +240,44 @@ static int acpi_nfit_ctl(struct nvdimm_b
 		in_buf.buffer.length += nd_cmd_in_size(nvdimm, cmd, desc,
 				i, buf);
 
+	if (call_pkg) {
+		/* skip over package wrapper */
+		in_buf.buffer.pointer = (void *) &call_pkg->nd_payload;
+		in_buf.buffer.length = call_pkg->nd_size_in;
+	}
+
 	if (IS_ENABLED(CONFIG_ACPI_NFIT_DEBUG)) {
-		dev_dbg(dev, "%s:%s cmd: %s input length: %d\n", __func__,
-				dimm_name, cmd_name, in_buf.buffer.length);
-		print_hex_dump_debug(cmd_name, DUMP_PREFIX_OFFSET, 4,
-				4, in_buf.buffer.pointer, min_t(u32, 128,
-					in_buf.buffer.length), true);
+		dev_dbg(dev, "%s:%s cmd: %d: func: %d input length: %d\n",
+				__func__, dimm_name, cmd, func,
+				in_buf.buffer.length);
+		print_hex_dump_debug("nvdimm in  ", DUMP_PREFIX_OFFSET, 4, 4,
+			in_buf.buffer.pointer,
+			min_t(u32, 256, in_buf.buffer.length), true);
 	}
 
-	out_obj = acpi_evaluate_dsm(handle, uuid, 1, cmd, &in_obj);
+	out_obj = acpi_evaluate_dsm(handle, uuid, 1, func, &in_obj);
 	if (!out_obj) {
 		dev_dbg(dev, "%s:%s _DSM failed cmd: %s\n", __func__, dimm_name,
 				cmd_name);
 		return -EINVAL;
 	}
 
+	if (call_pkg) {
+		call_pkg->nd_fw_size = out_obj->buffer.length;
+		memcpy(call_pkg->nd_payload + call_pkg->nd_size_in,
+			out_obj->buffer.pointer,
+			min(call_pkg->nd_fw_size, call_pkg->nd_size_out));
+
+		ACPI_FREE(out_obj);
+		/*
+		 * Need to support FW function w/o known size in advance.
+		 * Caller can determine required size based upon nd_fw_size.
+		 * If we return an error (like elsewhere) then caller wouldn't
+		 * be able to rely upon data returned to make calculation.
+		 */
+		return 0;
+	}
+
 	if (out_obj->package.type != ACPI_TYPE_BUFFER) {
 		dev_dbg(dev, "%s:%s unexpected output object type cmd: %s type: %d\n",
 				__func__, dimm_name, cmd_name, out_obj->type);
@@ -658,6 +699,7 @@ static int nfit_mem_dcr_init(struct acpi
 			if (!nfit_mem)
 				return -ENOMEM;
 			INIT_LIST_HEAD(&nfit_mem->list);
+			nfit_mem->acpi_desc = acpi_desc;
 			list_add(&nfit_mem->list, &acpi_desc->dimms);
 		}
 
@@ -819,7 +861,7 @@ static ssize_t vendor_show(struct device
 {
 	struct acpi_nfit_control_region *dcr = to_nfit_dcr(dev);
 
-	return sprintf(buf, "%#x\n", dcr->vendor_id);
+	return sprintf(buf, "0x%04x\n", be16_to_cpu(dcr->vendor_id));
 }
 static DEVICE_ATTR_RO(vendor);
 
@@ -828,7 +870,7 @@ static ssize_t rev_id_show(struct device
 {
 	struct acpi_nfit_control_region *dcr = to_nfit_dcr(dev);
 
-	return sprintf(buf, "%#x\n", dcr->revision_id);
+	return sprintf(buf, "0x%04x\n", be16_to_cpu(dcr->revision_id));
 }
 static DEVICE_ATTR_RO(rev_id);
 
@@ -837,28 +879,142 @@ static ssize_t device_show(struct device
 {
 	struct acpi_nfit_control_region *dcr = to_nfit_dcr(dev);
 
-	return sprintf(buf, "%#x\n", dcr->device_id);
+	return sprintf(buf, "0x%04x\n", be16_to_cpu(dcr->device_id));
 }
 static DEVICE_ATTR_RO(device);
 
+static ssize_t subsystem_vendor_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct acpi_nfit_control_region *dcr = to_nfit_dcr(dev);
+
+	return sprintf(buf, "0x%04x\n", be16_to_cpu(dcr->subsystem_vendor_id));
+}
+static DEVICE_ATTR_RO(subsystem_vendor);
+
+static ssize_t subsystem_rev_id_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct acpi_nfit_control_region *dcr = to_nfit_dcr(dev);
+
+	return sprintf(buf, "0x%04x\n",
+			be16_to_cpu(dcr->subsystem_revision_id));
+}
+static DEVICE_ATTR_RO(subsystem_rev_id);
+
+static ssize_t subsystem_device_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct acpi_nfit_control_region *dcr = to_nfit_dcr(dev);
+
+	return sprintf(buf, "0x%04x\n", be16_to_cpu(dcr->subsystem_device_id));
+}
+static DEVICE_ATTR_RO(subsystem_device);
+
+static int num_nvdimm_formats(struct nvdimm *nvdimm)
+{
+	struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
+	int formats = 0;
+
+	if (nfit_mem->memdev_pmem)
+		formats++;
+	if (nfit_mem->memdev_bdw)
+		formats++;
+	return formats;
+}
+
 static ssize_t format_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
 	struct acpi_nfit_control_region *dcr = to_nfit_dcr(dev);
 
-	return sprintf(buf, "%#x\n", dcr->code);
+	return sprintf(buf, "0x%04x\n", le16_to_cpu(dcr->code));
 }
 static DEVICE_ATTR_RO(format);
 
+static ssize_t format1_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	u32 handle;
+	ssize_t rc = -ENXIO;
+	struct nfit_mem *nfit_mem;
+	struct nfit_memdev *nfit_memdev;
+	struct acpi_nfit_desc *acpi_desc;
+	struct nvdimm *nvdimm = to_nvdimm(dev);
+	struct acpi_nfit_control_region *dcr = to_nfit_dcr(dev);
+
+	nfit_mem = nvdimm_provider_data(nvdimm);
+	acpi_desc = nfit_mem->acpi_desc;
+	handle = to_nfit_memdev(dev)->device_handle;
+
+	/* assumes DIMMs have at most 2 published interface codes */
+	mutex_lock(&acpi_desc->init_mutex);
+	list_for_each_entry(nfit_memdev, &acpi_desc->memdevs, list) {
+		struct acpi_nfit_memory_map *memdev = nfit_memdev->memdev;
+		struct nfit_dcr *nfit_dcr;
+
+		if (memdev->device_handle != handle)
+			continue;
+
+		list_for_each_entry(nfit_dcr, &acpi_desc->dcrs, list) {
+			if (nfit_dcr->dcr->region_index != memdev->region_index)
+				continue;
+			if (nfit_dcr->dcr->code == dcr->code)
+				continue;
+			rc = sprintf(buf, "0x%04x\n",
+					le16_to_cpu(nfit_dcr->dcr->code));
+			break;
+		}
+		if (rc != ENXIO)
+			break;
+	}
+	mutex_unlock(&acpi_desc->init_mutex);
+	return rc;
+}
+static DEVICE_ATTR_RO(format1);
+
+static ssize_t formats_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct nvdimm *nvdimm = to_nvdimm(dev);
+
+	return sprintf(buf, "%d\n", num_nvdimm_formats(nvdimm));
+}
+static DEVICE_ATTR_RO(formats);
+
 static ssize_t serial_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
 	struct acpi_nfit_control_region *dcr = to_nfit_dcr(dev);
 
-	return sprintf(buf, "%#x\n", dcr->serial_number);
+	return sprintf(buf, "0x%08x\n", be32_to_cpu(dcr->serial_number));
 }
 static DEVICE_ATTR_RO(serial);
 
+static ssize_t family_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct nvdimm *nvdimm = to_nvdimm(dev);
+	struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
+
+	if (nfit_mem->family < 0)
+		return -ENXIO;
+	return sprintf(buf, "%d\n", nfit_mem->family);
+}
+static DEVICE_ATTR_RO(family);
+
+static ssize_t dsm_mask_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct nvdimm *nvdimm = to_nvdimm(dev);
+	struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
+
+	if (nfit_mem->family < 0)
+		return -ENXIO;
+	return sprintf(buf, "%#lx\n", nfit_mem->dsm_mask);
+}
+static DEVICE_ATTR_RO(dsm_mask);
+
 static ssize_t flags_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -873,15 +1029,41 @@ static ssize_t flags_show(struct device
 }
 static DEVICE_ATTR_RO(flags);
 
+static ssize_t id_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct acpi_nfit_control_region *dcr = to_nfit_dcr(dev);
+
+	if (dcr->valid_fields & ACPI_NFIT_CONTROL_MFG_INFO_VALID)
+		return sprintf(buf, "%04x-%02x-%04x-%08x\n",
+				be16_to_cpu(dcr->vendor_id),
+				dcr->manufacturing_location,
+				be16_to_cpu(dcr->manufacturing_date),
+				be32_to_cpu(dcr->serial_number));
+	else
+		return sprintf(buf, "%04x-%08x\n",
+				be16_to_cpu(dcr->vendor_id),
+				be32_to_cpu(dcr->serial_number));
+}
+static DEVICE_ATTR_RO(id);
+
 static struct attribute *acpi_nfit_dimm_attributes[] = {
 	&dev_attr_handle.attr,
 	&dev_attr_phys_id.attr,
 	&dev_attr_vendor.attr,
 	&dev_attr_device.attr,
+	&dev_attr_rev_id.attr,
+	&dev_attr_subsystem_vendor.attr,
+	&dev_attr_subsystem_device.attr,
+	&dev_attr_subsystem_rev_id.attr,
 	&dev_attr_format.attr,
+	&dev_attr_formats.attr,
+	&dev_attr_format1.attr,
 	&dev_attr_serial.attr,
-	&dev_attr_rev_id.attr,
 	&dev_attr_flags.attr,
+	&dev_attr_id.attr,
+	&dev_attr_family.attr,
+	&dev_attr_dsm_mask.attr,
 	NULL,
 };
 
@@ -889,11 +1071,13 @@ static umode_t acpi_nfit_dimm_attr_visib
 		struct attribute *a, int n)
 {
 	struct device *dev = container_of(kobj, struct device, kobj);
+	struct nvdimm *nvdimm = to_nvdimm(dev);
 
-	if (to_nfit_dcr(dev))
-		return a->mode;
-	else
+	if (!to_nfit_dcr(dev))
+		return 0;
+	if (a == &dev_attr_format1.attr && num_nvdimm_formats(nvdimm) <= 1)
 		return 0;
+	return a->mode;
 }
 
 static struct attribute_group acpi_nfit_dimm_attribute_group = {
@@ -926,10 +1110,13 @@ static int acpi_nfit_add_dimm(struct acp
 {
 	struct acpi_device *adev, *adev_dimm;
 	struct device *dev = acpi_desc->dev;
-	const u8 *uuid = to_nfit_uuid(NFIT_DEV_DIMM);
+	unsigned long dsm_mask;
+	const u8 *uuid;
 	int i;
 
-	nfit_mem->dsm_mask = acpi_desc->dimm_dsm_force_en;
+	/* nfit test assumes 1:1 relationship between commands and dsms */
+	nfit_mem->dsm_mask = acpi_desc->dimm_cmd_force_en;
+	nfit_mem->family = NVDIMM_FAMILY_INTEL;
 	adev = to_acpi_dev(acpi_desc);
 	if (!adev)
 		return 0;
@@ -942,7 +1129,36 @@ static int acpi_nfit_add_dimm(struct acp
 		return force_enable_dimms ? 0 : -ENODEV;
 	}
 
-	for (i = ND_CMD_SMART; i <= ND_CMD_VENDOR; i++)
+	/*
+	 * Until standardization materializes we need to consider up to 3
+	 * different command sets.  Note, that checking for function0 (bit0)
+	 * tells us if any commands are reachable through this uuid.
+	 */
+	for (i = NVDIMM_FAMILY_INTEL; i <= NVDIMM_FAMILY_HPE2; i++)
+		if (acpi_check_dsm(adev_dimm->handle, to_nfit_uuid(i), 1, 1))
+			break;
+
+	/* limit the supported commands to those that are publicly documented */
+	nfit_mem->family = i;
+	if (nfit_mem->family == NVDIMM_FAMILY_INTEL) {
+		dsm_mask = 0x3fe;
+		if (disable_vendor_specific)
+			dsm_mask &= ~(1 << ND_CMD_VENDOR);
+	} else if (nfit_mem->family == NVDIMM_FAMILY_HPE1)
+		dsm_mask = 0x1c3c76;
+	else if (nfit_mem->family == NVDIMM_FAMILY_HPE2) {
+		dsm_mask = 0x1fe;
+		if (disable_vendor_specific)
+			dsm_mask &= ~(1 << 8);
+	} else {
+		dev_dbg(dev, "unknown dimm command family\n");
+		nfit_mem->family = -1;
+		/* DSMs are optional, continue loading the driver... */
+		return 0;
+	}
+
+	uuid = to_nfit_uuid(nfit_mem->family);
+	for_each_set_bit(i, &dsm_mask, BITS_PER_LONG)
 		if (acpi_check_dsm(adev_dimm->handle, uuid, 1, 1ULL << i))
 			set_bit(i, &nfit_mem->dsm_mask);
 
@@ -955,8 +1171,8 @@ static int acpi_nfit_register_dimms(stru
 	int dimm_count = 0;
 
 	list_for_each_entry(nfit_mem, &acpi_desc->dimms, list) {
+		unsigned long flags = 0, cmd_mask;
 		struct nvdimm *nvdimm;
-		unsigned long flags = 0;
 		u32 device_handle;
 		u16 mem_flags;
 		int rc;
@@ -979,9 +1195,18 @@ static int acpi_nfit_register_dimms(stru
 		if (rc)
 			continue;
 
+		/*
+		 * TODO: provide translation for non-NVDIMM_FAMILY_INTEL
+		 * devices (i.e. from nd_cmd to acpi_dsm) to standardize the
+		 * userspace interface.
+		 */
+		cmd_mask = 1UL << ND_CMD_CALL;
+		if (nfit_mem->family == NVDIMM_FAMILY_INTEL)
+			cmd_mask |= nfit_mem->dsm_mask;
+
 		nvdimm = nvdimm_create(acpi_desc->nvdimm_bus, nfit_mem,
 				acpi_nfit_dimm_attribute_groups,
-				flags, &nfit_mem->dsm_mask);
+				flags, cmd_mask);
 		if (!nvdimm)
 			return -ENOMEM;
 
@@ -1010,14 +1235,14 @@ static void acpi_nfit_init_dsms(struct a
 	struct acpi_device *adev;
 	int i;
 
-	nd_desc->dsm_mask = acpi_desc->bus_dsm_force_en;
+	nd_desc->cmd_mask = acpi_desc->bus_cmd_force_en;
 	adev = to_acpi_dev(acpi_desc);
 	if (!adev)
 		return;
 
 	for (i = ND_CMD_ARS_CAP; i <= ND_CMD_CLEAR_ERROR; i++)
 		if (acpi_check_dsm(adev->handle, uuid, 1, 1ULL << i))
-			set_bit(i, &nd_desc->dsm_mask);
+			set_bit(i, &nd_desc->cmd_mask);
 }
 
 static ssize_t range_index_show(struct device *dev,
@@ -2309,7 +2534,7 @@ static int acpi_nfit_add(struct acpi_dev
 	acpi_size sz;
 	int rc;
 
-	status = acpi_get_table_with_size("NFIT", 0, &tbl, &sz);
+	status = acpi_get_table_with_size(ACPI_SIG_NFIT, 0, &tbl, &sz);
 	if (ACPI_FAILURE(status)) {
 		/* This is ok, we could have an nvdimm hotplugged later */
 		dev_dbg(dev, "failed to find NFIT at startup\n");
@@ -2466,6 +2691,8 @@ static __init int nfit_init(void)
 	acpi_str_to_uuid(UUID_PERSISTENT_VIRTUAL_CD, nfit_uuid[NFIT_SPA_PCD]);
 	acpi_str_to_uuid(UUID_NFIT_BUS, nfit_uuid[NFIT_DEV_BUS]);
 	acpi_str_to_uuid(UUID_NFIT_DIMM, nfit_uuid[NFIT_DEV_DIMM]);
+	acpi_str_to_uuid(UUID_NFIT_DIMM_N_HPE1, nfit_uuid[NFIT_DEV_DIMM_N_HPE1]);
+	acpi_str_to_uuid(UUID_NFIT_DIMM_N_HPE2, nfit_uuid[NFIT_DEV_DIMM_N_HPE2]);
 
 	nfit_wq = create_singlethread_workqueue("nfit");
 	if (!nfit_wq)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/nfit.h linux-libre-4.7-gnu/drivers/acpi/nfit.h
--- linux-libre-4.6-gnu/drivers/acpi/nfit.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/nfit.h	2016-07-24 15:23:50.000000000 -0400
@@ -21,13 +21,25 @@
 #include <linux/acpi.h>
 #include <acpi/acuuid.h>
 
+/* ACPI 6.1 */
 #define UUID_NFIT_BUS "2f10e7a4-9e91-11e4-89d3-123b93f75cba"
+
+/* http://pmem.io/documents/NVDIMM_DSM_Interface_Example.pdf */
 #define UUID_NFIT_DIMM "4309ac30-0d11-11e4-9191-0800200c9a66"
+
+/* https://github.com/HewlettPackard/hpe-nvm/blob/master/Documentation/ */
+#define UUID_NFIT_DIMM_N_HPE1 "9002c334-acf3-4c0e-9642-a235f0d53bc6"
+#define UUID_NFIT_DIMM_N_HPE2 "5008664b-b758-41a0-a03c-27c2f2d04f7e"
+
 #define ACPI_NFIT_MEM_FAILED_MASK (ACPI_NFIT_MEM_SAVE_FAILED \
 		| ACPI_NFIT_MEM_RESTORE_FAILED | ACPI_NFIT_MEM_FLUSH_FAILED \
 		| ACPI_NFIT_MEM_NOT_ARMED)
 
 enum nfit_uuids {
+	/* for simplicity alias the uuid index with the family id */
+	NFIT_DEV_DIMM = NVDIMM_FAMILY_INTEL,
+	NFIT_DEV_DIMM_N_HPE1 = NVDIMM_FAMILY_HPE1,
+	NFIT_DEV_DIMM_N_HPE2 = NVDIMM_FAMILY_HPE2,
 	NFIT_SPA_VOLATILE,
 	NFIT_SPA_PM,
 	NFIT_SPA_DCR,
@@ -37,15 +49,16 @@ enum nfit_uuids {
 	NFIT_SPA_PDISK,
 	NFIT_SPA_PCD,
 	NFIT_DEV_BUS,
-	NFIT_DEV_DIMM,
 	NFIT_UUID_MAX,
 };
 
-enum nfit_fic {
-	NFIT_FIC_BYTE = 0x101, /* byte-addressable energy backed */
-	NFIT_FIC_BLK = 0x201, /* block-addressable non-energy backed */
-	NFIT_FIC_BYTEN = 0x301, /* byte-addressable non-energy backed */
-};
+/*
+ * Region format interface codes are stored with the interface as the
+ * LSB and the function as the MSB.
+ */
+#define NFIT_FIC_BYTE cpu_to_le16(0x101) /* byte-addressable energy backed */
+#define NFIT_FIC_BLK cpu_to_le16(0x201) /* block-addressable non-energy backed */
+#define NFIT_FIC_BYTEN cpu_to_le16(0x301) /* byte-addressable non-energy backed */
 
 enum {
 	NFIT_BLK_READ_FLUSH = 1,
@@ -109,7 +122,9 @@ struct nfit_mem {
 	struct nfit_flush *nfit_flush;
 	struct list_head list;
 	struct acpi_device *adev;
+	struct acpi_nfit_desc *acpi_desc;
 	unsigned long dsm_mask;
+	int family;
 };
 
 struct acpi_nfit_desc {
@@ -132,8 +147,8 @@ struct acpi_nfit_desc {
 	size_t ars_status_size;
 	struct work_struct work;
 	unsigned int cancel:1;
-	unsigned long dimm_dsm_force_en;
-	unsigned long bus_dsm_force_en;
+	unsigned long dimm_cmd_force_en;
+	unsigned long bus_cmd_force_en;
 	int (*blk_do_io)(struct nd_blk_region *ndbr, resource_size_t dpa,
 			void *iobuf, u64 len, int rw);
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/numa.c linux-libre-4.7-gnu/drivers/acpi/numa.c
--- linux-libre-4.6-gnu/drivers/acpi/numa.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/numa.c	2016-07-24 15:23:50.000000000 -0400
@@ -327,10 +327,18 @@ int __init acpi_numa_init(void)
 
 	/* SRAT: Static Resource Affinity Table */
 	if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) {
-		acpi_table_parse_srat(ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY,
-				     acpi_parse_x2apic_affinity, 0);
-		acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY,
-				     acpi_parse_processor_affinity, 0);
+		struct acpi_subtable_proc srat_proc[2];
+
+		memset(srat_proc, 0, sizeof(srat_proc));
+		srat_proc[0].id = ACPI_SRAT_TYPE_CPU_AFFINITY;
+		srat_proc[0].handler = acpi_parse_processor_affinity;
+		srat_proc[1].id = ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY;
+		srat_proc[1].handler = acpi_parse_x2apic_affinity;
+
+		acpi_table_parse_entries_array(ACPI_SIG_SRAT,
+					sizeof(struct acpi_table_srat),
+					srat_proc, ARRAY_SIZE(srat_proc), 0);
+
 		cnt = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY,
 					    acpi_parse_memory_affinity,
 					    NR_NODE_MEMBLKS);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/osi.c linux-libre-4.7-gnu/drivers/acpi/osi.c
--- linux-libre-4.6-gnu/drivers/acpi/osi.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/acpi/osi.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,522 @@
+/*
+ *  osi.c - _OSI implementation
+ *
+ *  Copyright (C) 2016 Intel Corporation
+ *    Author: Lv Zheng <lv.zheng@intel.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or (at
+ *  your option) any later version.
+ *
+ *  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.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+/* Uncomment next line to get verbose printout */
+/* #define DEBUG */
+#define pr_fmt(fmt) "ACPI: " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/acpi.h>
+#include <linux/dmi.h>
+
+#include "internal.h"
+
+
+#define OSI_STRING_LENGTH_MAX	64
+#define OSI_STRING_ENTRIES_MAX	16
+
+struct acpi_osi_entry {
+	char string[OSI_STRING_LENGTH_MAX];
+	bool enable;
+};
+
+static struct acpi_osi_config {
+	u8		default_disabling;
+	unsigned int	linux_enable:1;
+	unsigned int	linux_dmi:1;
+	unsigned int	linux_cmdline:1;
+	unsigned int	darwin_enable:1;
+	unsigned int	darwin_dmi:1;
+	unsigned int	darwin_cmdline:1;
+} osi_config;
+
+static struct acpi_osi_config osi_config;
+static struct acpi_osi_entry
+osi_setup_entries[OSI_STRING_ENTRIES_MAX] __initdata = {
+	{"Module Device", true},
+	{"Processor Device", true},
+	{"3.0 _SCP Extensions", true},
+	{"Processor Aggregator Device", true},
+};
+
+static u32 acpi_osi_handler(acpi_string interface, u32 supported)
+{
+	if (!strcmp("Linux", interface)) {
+		pr_notice_once(FW_BUG
+			"BIOS _OSI(Linux) query %s%s\n",
+			osi_config.linux_enable ? "honored" : "ignored",
+			osi_config.linux_cmdline ? " via cmdline" :
+			osi_config.linux_dmi ? " via DMI" : "");
+	}
+	if (!strcmp("Darwin", interface)) {
+		pr_notice_once(
+			"BIOS _OSI(Darwin) query %s%s\n",
+			osi_config.darwin_enable ? "honored" : "ignored",
+			osi_config.darwin_cmdline ? " via cmdline" :
+			osi_config.darwin_dmi ? " via DMI" : "");
+	}
+
+	return supported;
+}
+
+void __init acpi_osi_setup(char *str)
+{
+	struct acpi_osi_entry *osi;
+	bool enable = true;
+	int i;
+
+	if (!acpi_gbl_create_osi_method)
+		return;
+
+	if (str == NULL || *str == '\0') {
+		pr_info("_OSI method disabled\n");
+		acpi_gbl_create_osi_method = FALSE;
+		return;
+	}
+
+	if (*str == '!') {
+		str++;
+		if (*str == '\0') {
+			/* Do not override acpi_osi=!* */
+			if (!osi_config.default_disabling)
+				osi_config.default_disabling =
+					ACPI_DISABLE_ALL_VENDOR_STRINGS;
+			return;
+		} else if (*str == '*') {
+			osi_config.default_disabling = ACPI_DISABLE_ALL_STRINGS;
+			for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) {
+				osi = &osi_setup_entries[i];
+				osi->enable = false;
+			}
+			return;
+		} else if (*str == '!') {
+			osi_config.default_disabling = 0;
+			return;
+		}
+		enable = false;
+	}
+
+	for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) {
+		osi = &osi_setup_entries[i];
+		if (!strcmp(osi->string, str)) {
+			osi->enable = enable;
+			break;
+		} else if (osi->string[0] == '\0') {
+			osi->enable = enable;
+			strncpy(osi->string, str, OSI_STRING_LENGTH_MAX);
+			break;
+		}
+	}
+}
+
+static void __init __acpi_osi_setup_darwin(bool enable)
+{
+	osi_config.darwin_enable = !!enable;
+	if (enable) {
+		acpi_osi_setup("!");
+		acpi_osi_setup("Darwin");
+	} else {
+		acpi_osi_setup("!!");
+		acpi_osi_setup("!Darwin");
+	}
+}
+
+static void __init acpi_osi_setup_darwin(bool enable)
+{
+	/* Override acpi_osi_dmi_blacklisted() */
+	osi_config.darwin_dmi = 0;
+	osi_config.darwin_cmdline = 1;
+	__acpi_osi_setup_darwin(enable);
+}
+
+/*
+ * The story of _OSI(Linux)
+ *
+ * From pre-history through Linux-2.6.22, Linux responded TRUE upon a BIOS
+ * OSI(Linux) query.
+ *
+ * Unfortunately, reference BIOS writers got wind of this and put
+ * OSI(Linux) in their example code, quickly exposing this string as
+ * ill-conceived and opening the door to an un-bounded number of BIOS
+ * incompatibilities.
+ *
+ * For example, OSI(Linux) was used on resume to re-POST a video card on
+ * one system, because Linux at that time could not do a speedy restore in
+ * its native driver. But then upon gaining quick native restore
+ * capability, Linux has no way to tell the BIOS to skip the time-consuming
+ * POST -- putting Linux at a permanent performance disadvantage. On
+ * another system, the BIOS writer used OSI(Linux) to infer native OS
+ * support for IPMI!  On other systems, OSI(Linux) simply got in the way of
+ * Linux claiming to be compatible with other operating systems, exposing
+ * BIOS issues such as skipped device initialization.
+ *
+ * So "Linux" turned out to be a really poor chose of OSI string, and from
+ * Linux-2.6.23 onward we respond FALSE.
+ *
+ * BIOS writers should NOT query _OSI(Linux) on future systems. Linux will
+ * complain on the console when it sees it, and return FALSE. To get Linux
+ * to return TRUE for your system  will require a kernel source update to
+ * add a DMI entry, or boot with "acpi_osi=Linux"
+ */
+static void __init __acpi_osi_setup_linux(bool enable)
+{
+	osi_config.linux_enable = !!enable;
+	if (enable)
+		acpi_osi_setup("Linux");
+	else
+		acpi_osi_setup("!Linux");
+}
+
+static void __init acpi_osi_setup_linux(bool enable)
+{
+	/* Override acpi_osi_dmi_blacklisted() */
+	osi_config.linux_dmi = 0;
+	osi_config.linux_cmdline = 1;
+	__acpi_osi_setup_linux(enable);
+}
+
+/*
+ * Modify the list of "OS Interfaces" reported to BIOS via _OSI
+ *
+ * empty string disables _OSI
+ * string starting with '!' disables that string
+ * otherwise string is added to list, augmenting built-in strings
+ */
+static void __init acpi_osi_setup_late(void)
+{
+	struct acpi_osi_entry *osi;
+	char *str;
+	int i;
+	acpi_status status;
+
+	if (osi_config.default_disabling) {
+		status = acpi_update_interfaces(osi_config.default_disabling);
+		if (ACPI_SUCCESS(status))
+			pr_info("Disabled all _OSI OS vendors%s\n",
+				osi_config.default_disabling ==
+				ACPI_DISABLE_ALL_STRINGS ?
+				" and feature groups" : "");
+	}
+
+	for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) {
+		osi = &osi_setup_entries[i];
+		str = osi->string;
+		if (*str == '\0')
+			break;
+		if (osi->enable) {
+			status = acpi_install_interface(str);
+			if (ACPI_SUCCESS(status))
+				pr_info("Added _OSI(%s)\n", str);
+		} else {
+			status = acpi_remove_interface(str);
+			if (ACPI_SUCCESS(status))
+				pr_info("Deleted _OSI(%s)\n", str);
+		}
+	}
+}
+
+static int __init osi_setup(char *str)
+{
+	if (str && !strcmp("Linux", str))
+		acpi_osi_setup_linux(true);
+	else if (str && !strcmp("!Linux", str))
+		acpi_osi_setup_linux(false);
+	else if (str && !strcmp("Darwin", str))
+		acpi_osi_setup_darwin(true);
+	else if (str && !strcmp("!Darwin", str))
+		acpi_osi_setup_darwin(false);
+	else
+		acpi_osi_setup(str);
+
+	return 1;
+}
+__setup("acpi_osi=", osi_setup);
+
+bool acpi_osi_is_win8(void)
+{
+	return acpi_gbl_osi_data >= ACPI_OSI_WIN_8;
+}
+EXPORT_SYMBOL(acpi_osi_is_win8);
+
+static void __init acpi_osi_dmi_darwin(bool enable,
+				       const struct dmi_system_id *d)
+{
+	pr_notice("DMI detected to setup _OSI(\"Darwin\"): %s\n", d->ident);
+	osi_config.darwin_dmi = 1;
+	__acpi_osi_setup_darwin(enable);
+}
+
+void __init acpi_osi_dmi_linux(bool enable, const struct dmi_system_id *d)
+{
+	pr_notice("DMI detected to setup _OSI(\"Linux\"): %s\n", d->ident);
+	osi_config.linux_dmi = 1;
+	__acpi_osi_setup_linux(enable);
+}
+
+static int __init dmi_enable_osi_darwin(const struct dmi_system_id *d)
+{
+	acpi_osi_dmi_darwin(true, d);
+
+	return 0;
+}
+
+static int __init dmi_enable_osi_linux(const struct dmi_system_id *d)
+{
+	acpi_osi_dmi_linux(true, d);
+
+	return 0;
+}
+
+static int __init dmi_disable_osi_vista(const struct dmi_system_id *d)
+{
+	pr_notice("DMI detected: %s\n", d->ident);
+	acpi_osi_setup("!Windows 2006");
+	acpi_osi_setup("!Windows 2006 SP1");
+	acpi_osi_setup("!Windows 2006 SP2");
+
+	return 0;
+}
+
+static int __init dmi_disable_osi_win7(const struct dmi_system_id *d)
+{
+	pr_notice("DMI detected: %s\n", d->ident);
+	acpi_osi_setup("!Windows 2009");
+
+	return 0;
+}
+
+static int __init dmi_disable_osi_win8(const struct dmi_system_id *d)
+{
+	pr_notice("DMI detected: %s\n", d->ident);
+	acpi_osi_setup("!Windows 2012");
+
+	return 0;
+}
+
+/*
+ * Linux default _OSI response behavior is determined by this DMI table.
+ *
+ * Note that _OSI("Linux")/_OSI("Darwin") determined here can be overridden
+ * by acpi_osi=!Linux/acpi_osi=!Darwin command line options.
+ */
+static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
+	{
+	.callback = dmi_disable_osi_vista,
+	.ident = "Fujitsu Siemens",
+	.matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+		     DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile V5505"),
+		},
+	},
+	{
+	/*
+	 * There have a NVIF method in MSI GX723 DSDT need call by Nvidia
+	 * driver (e.g. nouveau) when user press brightness hotkey.
+	 * Currently, nouveau driver didn't do the job and it causes there
+	 * have a infinite while loop in DSDT when user press hotkey.
+	 * We add MSI GX723's dmi information to this table for workaround
+	 * this issue.
+	 * Will remove MSI GX723 from the table after nouveau grows support.
+	 */
+	.callback = dmi_disable_osi_vista,
+	.ident = "MSI GX723",
+	.matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
+		     DMI_MATCH(DMI_PRODUCT_NAME, "GX723"),
+		},
+	},
+	{
+	.callback = dmi_disable_osi_vista,
+	.ident = "Sony VGN-NS10J_S",
+	.matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+		     DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS10J_S"),
+		},
+	},
+	{
+	.callback = dmi_disable_osi_vista,
+	.ident = "Sony VGN-SR290J",
+	.matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+		     DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR290J"),
+		},
+	},
+	{
+	.callback = dmi_disable_osi_vista,
+	.ident = "VGN-NS50B_L",
+	.matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+		     DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NS50B_L"),
+		},
+	},
+	{
+	.callback = dmi_disable_osi_vista,
+	.ident = "VGN-SR19XN",
+	.matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+		     DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR19XN"),
+		},
+	},
+	{
+	.callback = dmi_disable_osi_vista,
+	.ident = "Toshiba Satellite L355",
+	.matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+		     DMI_MATCH(DMI_PRODUCT_VERSION, "Satellite L355"),
+		},
+	},
+	{
+	.callback = dmi_disable_osi_win7,
+	.ident = "ASUS K50IJ",
+	.matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+		     DMI_MATCH(DMI_PRODUCT_NAME, "K50IJ"),
+		},
+	},
+	{
+	.callback = dmi_disable_osi_vista,
+	.ident = "Toshiba P305D",
+	.matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+		     DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P305D"),
+		},
+	},
+	{
+	.callback = dmi_disable_osi_vista,
+	.ident = "Toshiba NB100",
+	.matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+		     DMI_MATCH(DMI_PRODUCT_NAME, "NB100"),
+		},
+	},
+
+	/*
+	 * The wireless hotkey does not work on those machines when
+	 * returning true for _OSI("Windows 2012")
+	 */
+	{
+	.callback = dmi_disable_osi_win8,
+	.ident = "Dell Inspiron 7737",
+	.matches = {
+		    DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+		    DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7737"),
+		},
+	},
+	{
+	.callback = dmi_disable_osi_win8,
+	.ident = "Dell Inspiron 7537",
+	.matches = {
+		    DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+		    DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7537"),
+		},
+	},
+	{
+	.callback = dmi_disable_osi_win8,
+	.ident = "Dell Inspiron 5437",
+	.matches = {
+		    DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+		    DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5437"),
+		},
+	},
+	{
+	.callback = dmi_disable_osi_win8,
+	.ident = "Dell Inspiron 3437",
+	.matches = {
+		    DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+		    DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 3437"),
+		},
+	},
+	{
+	.callback = dmi_disable_osi_win8,
+	.ident = "Dell Vostro 3446",
+	.matches = {
+		    DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+		    DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3446"),
+		},
+	},
+	{
+	.callback = dmi_disable_osi_win8,
+	.ident = "Dell Vostro 3546",
+	.matches = {
+		    DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+		    DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3546"),
+		},
+	},
+
+	/*
+	 * BIOS invocation of _OSI(Linux) is almost always a BIOS bug.
+	 * Linux ignores it, except for the machines enumerated below.
+	 */
+
+	/*
+	 * Without this this EEEpc exports a non working WMI interface, with
+	 * this it exports a working "good old" eeepc_laptop interface, fixing
+	 * both brightness control, and rfkill not working.
+	 */
+	{
+	.callback = dmi_enable_osi_linux,
+	.ident = "Asus EEE PC 1015PX",
+	.matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer INC."),
+		     DMI_MATCH(DMI_PRODUCT_NAME, "1015PX"),
+		},
+	},
+
+	/*
+	 * Enable _OSI("Darwin") for all apple platforms.
+	 */
+	{
+	.callback = dmi_enable_osi_darwin,
+	.ident = "Apple hardware",
+	.matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+		},
+	},
+	{
+	.callback = dmi_enable_osi_darwin,
+	.ident = "Apple hardware",
+	.matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."),
+		},
+	},
+	{}
+};
+
+static __init void acpi_osi_dmi_blacklisted(void)
+{
+	dmi_check_system(acpi_osi_dmi_table);
+}
+
+int __init early_acpi_osi_init(void)
+{
+	acpi_osi_dmi_blacklisted();
+
+	return 0;
+}
+
+int __init acpi_osi_init(void)
+{
+	acpi_install_interface_handler(acpi_osi_handler);
+	acpi_osi_setup_late();
+
+	return 0;
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/osl.c linux-libre-4.7-gnu/drivers/acpi/osl.c
--- linux-libre-4.6-gnu/drivers/acpi/osl.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/osl.c	2016-07-24 15:23:50.000000000 -0400
@@ -56,10 +56,6 @@ struct acpi_os_dpc {
 	struct work_struct work;
 };
 
-#ifdef CONFIG_ACPI_CUSTOM_DSDT
-#include CONFIG_ACPI_CUSTOM_DSDT_FILE
-#endif
-
 #ifdef ENABLE_DEBUGGER
 #include <linux/kdb.h>
 
@@ -96,72 +92,6 @@ struct acpi_ioremap {
 static LIST_HEAD(acpi_ioremaps);
 static DEFINE_MUTEX(acpi_ioremap_lock);
 
-static void __init acpi_osi_setup_late(void);
-
-/*
- * The story of _OSI(Linux)
- *
- * From pre-history through Linux-2.6.22,
- * Linux responded TRUE upon a BIOS OSI(Linux) query.
- *
- * Unfortunately, reference BIOS writers got wind of this
- * and put OSI(Linux) in their example code, quickly exposing
- * this string as ill-conceived and opening the door to
- * an un-bounded number of BIOS incompatibilities.
- *
- * For example, OSI(Linux) was used on resume to re-POST a
- * video card on one system, because Linux at that time
- * could not do a speedy restore in its native driver.
- * But then upon gaining quick native restore capability,
- * Linux has no way to tell the BIOS to skip the time-consuming
- * POST -- putting Linux at a permanent performance disadvantage.
- * On another system, the BIOS writer used OSI(Linux)
- * to infer native OS support for IPMI!  On other systems,
- * OSI(Linux) simply got in the way of Linux claiming to
- * be compatible with other operating systems, exposing
- * BIOS issues such as skipped device initialization.
- *
- * So "Linux" turned out to be a really poor chose of
- * OSI string, and from Linux-2.6.23 onward we respond FALSE.
- *
- * BIOS writers should NOT query _OSI(Linux) on future systems.
- * Linux will complain on the console when it sees it, and return FALSE.
- * To get Linux to return TRUE for your system  will require
- * a kernel source update to add a DMI entry,
- * or boot with "acpi_osi=Linux"
- */
-
-static struct osi_linux {
-	unsigned int	enable:1;
-	unsigned int	dmi:1;
-	unsigned int	cmdline:1;
-	unsigned int	default_disabling:1;
-} osi_linux = {0, 0, 0, 0};
-
-static u32 acpi_osi_handler(acpi_string interface, u32 supported)
-{
-	if (!strcmp("Linux", interface)) {
-
-		printk_once(KERN_NOTICE FW_BUG PREFIX
-			"BIOS _OSI(Linux) query %s%s\n",
-			osi_linux.enable ? "honored" : "ignored",
-			osi_linux.cmdline ? " via cmdline" :
-			osi_linux.dmi ? " via DMI" : "");
-	}
-
-	if (!strcmp("Darwin", interface)) {
-		/*
-		 * Apple firmware will behave poorly if it receives positive
-		 * answers to "Darwin" and any other OS. Respond positively
-		 * to Darwin and then disable all other vendor strings.
-		 */
-		acpi_update_interfaces(ACPI_DISABLE_ALL_VENDOR_STRINGS);
-		supported = ACPI_UINT32_MAX;
-	}
-
-	return supported;
-}
-
 static void __init acpi_request_region (struct acpi_generic_address *gas,
 	unsigned int length, char *desc)
 {
@@ -582,7 +512,7 @@ static char acpi_os_name[ACPI_MAX_OVERRI
 
 acpi_status
 acpi_os_predefined_override(const struct acpi_predefined_names *init_val,
-			    char **new_val)
+			    acpi_string *new_val)
 {
 	if (!init_val || !new_val)
 		return AE_BAD_PARAMETER;
@@ -602,280 +532,6 @@ acpi_os_predefined_override(const struct
 	return AE_OK;
 }
 
-static void acpi_table_taint(struct acpi_table_header *table)
-{
-	pr_warn(PREFIX
-		"Override [%4.4s-%8.8s], this is unsafe: tainting kernel\n",
-		table->signature, table->oem_table_id);
-	add_taint(TAINT_OVERRIDDEN_ACPI_TABLE, LOCKDEP_NOW_UNRELIABLE);
-}
-
-#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
-#include <linux/earlycpio.h>
-#include <linux/memblock.h>
-
-static u64 acpi_tables_addr;
-static int all_tables_size;
-
-/* Copied from acpica/tbutils.c:acpi_tb_checksum() */
-static u8 __init acpi_table_checksum(u8 *buffer, u32 length)
-{
-	u8 sum = 0;
-	u8 *end = buffer + length;
-
-	while (buffer < end)
-		sum = (u8) (sum + *(buffer++));
-	return sum;
-}
-
-/* All but ACPI_SIG_RSDP and ACPI_SIG_FACS: */
-static const char * const table_sigs[] = {
-	ACPI_SIG_BERT, ACPI_SIG_CPEP, ACPI_SIG_ECDT, ACPI_SIG_EINJ,
-	ACPI_SIG_ERST, ACPI_SIG_HEST, ACPI_SIG_MADT, ACPI_SIG_MSCT,
-	ACPI_SIG_SBST, ACPI_SIG_SLIT, ACPI_SIG_SRAT, ACPI_SIG_ASF,
-	ACPI_SIG_BOOT, ACPI_SIG_DBGP, ACPI_SIG_DMAR, ACPI_SIG_HPET,
-	ACPI_SIG_IBFT, ACPI_SIG_IVRS, ACPI_SIG_MCFG, ACPI_SIG_MCHI,
-	ACPI_SIG_SLIC, ACPI_SIG_SPCR, ACPI_SIG_SPMI, ACPI_SIG_TCPA,
-	ACPI_SIG_UEFI, ACPI_SIG_WAET, ACPI_SIG_WDAT, ACPI_SIG_WDDT,
-	ACPI_SIG_WDRT, ACPI_SIG_DSDT, ACPI_SIG_FADT, ACPI_SIG_PSDT,
-	ACPI_SIG_RSDT, ACPI_SIG_XSDT, ACPI_SIG_SSDT, NULL };
-
-#define ACPI_HEADER_SIZE sizeof(struct acpi_table_header)
-
-#define ACPI_OVERRIDE_TABLES 64
-static struct cpio_data __initdata acpi_initrd_files[ACPI_OVERRIDE_TABLES];
-static DECLARE_BITMAP(acpi_initrd_installed, ACPI_OVERRIDE_TABLES);
-
-#define MAP_CHUNK_SIZE   (NR_FIX_BTMAPS << PAGE_SHIFT)
-
-void __init acpi_initrd_override(void *data, size_t size)
-{
-	int sig, no, table_nr = 0, total_offset = 0;
-	long offset = 0;
-	struct acpi_table_header *table;
-	char cpio_path[32] = "kernel/firmware/acpi/";
-	struct cpio_data file;
-
-	if (data == NULL || size == 0)
-		return;
-
-	for (no = 0; no < ACPI_OVERRIDE_TABLES; no++) {
-		file = find_cpio_data(cpio_path, data, size, &offset);
-		if (!file.data)
-			break;
-
-		data += offset;
-		size -= offset;
-
-		if (file.size < sizeof(struct acpi_table_header)) {
-			pr_err("ACPI OVERRIDE: Table smaller than ACPI header [%s%s]\n",
-				cpio_path, file.name);
-			continue;
-		}
-
-		table = file.data;
-
-		for (sig = 0; table_sigs[sig]; sig++)
-			if (!memcmp(table->signature, table_sigs[sig], 4))
-				break;
-
-		if (!table_sigs[sig]) {
-			pr_err("ACPI OVERRIDE: Unknown signature [%s%s]\n",
-				cpio_path, file.name);
-			continue;
-		}
-		if (file.size != table->length) {
-			pr_err("ACPI OVERRIDE: File length does not match table length [%s%s]\n",
-				cpio_path, file.name);
-			continue;
-		}
-		if (acpi_table_checksum(file.data, table->length)) {
-			pr_err("ACPI OVERRIDE: Bad table checksum [%s%s]\n",
-				cpio_path, file.name);
-			continue;
-		}
-
-		pr_info("%4.4s ACPI table found in initrd [%s%s][0x%x]\n",
-			table->signature, cpio_path, file.name, table->length);
-
-		all_tables_size += table->length;
-		acpi_initrd_files[table_nr].data = file.data;
-		acpi_initrd_files[table_nr].size = file.size;
-		table_nr++;
-	}
-	if (table_nr == 0)
-		return;
-
-	acpi_tables_addr =
-		memblock_find_in_range(0, max_low_pfn_mapped << PAGE_SHIFT,
-				       all_tables_size, PAGE_SIZE);
-	if (!acpi_tables_addr) {
-		WARN_ON(1);
-		return;
-	}
-	/*
-	 * Only calling e820_add_reserve does not work and the
-	 * tables are invalid (memory got used) later.
-	 * memblock_reserve works as expected and the tables won't get modified.
-	 * But it's not enough on X86 because ioremap will
-	 * complain later (used by acpi_os_map_memory) that the pages
-	 * that should get mapped are not marked "reserved".
-	 * Both memblock_reserve and e820_add_region (via arch_reserve_mem_area)
-	 * works fine.
-	 */
-	memblock_reserve(acpi_tables_addr, all_tables_size);
-	arch_reserve_mem_area(acpi_tables_addr, all_tables_size);
-
-	/*
-	 * early_ioremap only can remap 256k one time. If we map all
-	 * tables one time, we will hit the limit. Need to map chunks
-	 * one by one during copying the same as that in relocate_initrd().
-	 */
-	for (no = 0; no < table_nr; no++) {
-		unsigned char *src_p = acpi_initrd_files[no].data;
-		phys_addr_t size = acpi_initrd_files[no].size;
-		phys_addr_t dest_addr = acpi_tables_addr + total_offset;
-		phys_addr_t slop, clen;
-		char *dest_p;
-
-		total_offset += size;
-
-		while (size) {
-			slop = dest_addr & ~PAGE_MASK;
-			clen = size;
-			if (clen > MAP_CHUNK_SIZE - slop)
-				clen = MAP_CHUNK_SIZE - slop;
-			dest_p = early_ioremap(dest_addr & PAGE_MASK,
-						 clen + slop);
-			memcpy(dest_p + slop, src_p, clen);
-			early_iounmap(dest_p, clen + slop);
-			src_p += clen;
-			dest_addr += clen;
-			size -= clen;
-		}
-	}
-}
-
-acpi_status
-acpi_os_physical_table_override(struct acpi_table_header *existing_table,
-				acpi_physical_address *address, u32 *length)
-{
-	int table_offset = 0;
-	int table_index = 0;
-	struct acpi_table_header *table;
-	u32 table_length;
-
-	*length = 0;
-	*address = 0;
-	if (!acpi_tables_addr)
-		return AE_OK;
-
-	while (table_offset + ACPI_HEADER_SIZE <= all_tables_size) {
-		table = acpi_os_map_memory(acpi_tables_addr + table_offset,
-					   ACPI_HEADER_SIZE);
-		if (table_offset + table->length > all_tables_size) {
-			acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
-			WARN_ON(1);
-			return AE_OK;
-		}
-
-		table_length = table->length;
-
-		/* Only override tables matched */
-		if (test_bit(table_index, acpi_initrd_installed) ||
-		    memcmp(existing_table->signature, table->signature, 4) ||
-		    memcmp(table->oem_table_id, existing_table->oem_table_id,
-			   ACPI_OEM_TABLE_ID_SIZE)) {
-			acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
-			goto next_table;
-		}
-
-		*length = table_length;
-		*address = acpi_tables_addr + table_offset;
-		acpi_table_taint(existing_table);
-		acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
-		set_bit(table_index, acpi_initrd_installed);
-		break;
-
-next_table:
-		table_offset += table_length;
-		table_index++;
-	}
-	return AE_OK;
-}
-
-void __init acpi_initrd_initialize_tables(void)
-{
-	int table_offset = 0;
-	int table_index = 0;
-	u32 table_length;
-	struct acpi_table_header *table;
-
-	if (!acpi_tables_addr)
-		return;
-
-	while (table_offset + ACPI_HEADER_SIZE <= all_tables_size) {
-		table = acpi_os_map_memory(acpi_tables_addr + table_offset,
-					   ACPI_HEADER_SIZE);
-		if (table_offset + table->length > all_tables_size) {
-			acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
-			WARN_ON(1);
-			return;
-		}
-
-		table_length = table->length;
-
-		/* Skip RSDT/XSDT which should only be used for override */
-		if (test_bit(table_index, acpi_initrd_installed) ||
-		    ACPI_COMPARE_NAME(table->signature, ACPI_SIG_RSDT) ||
-		    ACPI_COMPARE_NAME(table->signature, ACPI_SIG_XSDT)) {
-			acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
-			goto next_table;
-		}
-
-		acpi_table_taint(table);
-		acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
-		acpi_install_table(acpi_tables_addr + table_offset, TRUE);
-		set_bit(table_index, acpi_initrd_installed);
-next_table:
-		table_offset += table_length;
-		table_index++;
-	}
-}
-#else
-acpi_status
-acpi_os_physical_table_override(struct acpi_table_header *existing_table,
-				acpi_physical_address *address,
-				u32 *table_length)
-{
-	*table_length = 0;
-	*address = 0;
-	return AE_OK;
-}
-
-void __init acpi_initrd_initialize_tables(void)
-{
-}
-#endif /* CONFIG_ACPI_INITRD_TABLE_OVERRIDE */
-
-acpi_status
-acpi_os_table_override(struct acpi_table_header *existing_table,
-		       struct acpi_table_header **new_table)
-{
-	if (!existing_table || !new_table)
-		return AE_BAD_PARAMETER;
-
-	*new_table = NULL;
-
-#ifdef CONFIG_ACPI_CUSTOM_DSDT
-	if (strncmp(existing_table->signature, "DSDT", 4) == 0)
-		*new_table = (struct acpi_table_header *)AmlCode;
-#endif
-	if (*new_table != NULL)
-		acpi_table_taint(existing_table);
-	return AE_OK;
-}
-
 static irqreturn_t acpi_irq(int irq, void *dev_id)
 {
 	u32 handled;
@@ -1717,156 +1373,6 @@ static int __init acpi_os_name_setup(cha
 
 __setup("acpi_os_name=", acpi_os_name_setup);
 
-#define	OSI_STRING_LENGTH_MAX 64	/* arbitrary */
-#define	OSI_STRING_ENTRIES_MAX 16	/* arbitrary */
-
-struct osi_setup_entry {
-	char string[OSI_STRING_LENGTH_MAX];
-	bool enable;
-};
-
-static struct osi_setup_entry
-		osi_setup_entries[OSI_STRING_ENTRIES_MAX] __initdata = {
-	{"Module Device", true},
-	{"Processor Device", true},
-	{"3.0 _SCP Extensions", true},
-	{"Processor Aggregator Device", true},
-};
-
-void __init acpi_osi_setup(char *str)
-{
-	struct osi_setup_entry *osi;
-	bool enable = true;
-	int i;
-
-	if (!acpi_gbl_create_osi_method)
-		return;
-
-	if (str == NULL || *str == '\0') {
-		printk(KERN_INFO PREFIX "_OSI method disabled\n");
-		acpi_gbl_create_osi_method = FALSE;
-		return;
-	}
-
-	if (*str == '!') {
-		str++;
-		if (*str == '\0') {
-			osi_linux.default_disabling = 1;
-			return;
-		} else if (*str == '*') {
-			acpi_update_interfaces(ACPI_DISABLE_ALL_STRINGS);
-			for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) {
-				osi = &osi_setup_entries[i];
-				osi->enable = false;
-			}
-			return;
-		}
-		enable = false;
-	}
-
-	for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) {
-		osi = &osi_setup_entries[i];
-		if (!strcmp(osi->string, str)) {
-			osi->enable = enable;
-			break;
-		} else if (osi->string[0] == '\0') {
-			osi->enable = enable;
-			strncpy(osi->string, str, OSI_STRING_LENGTH_MAX);
-			break;
-		}
-	}
-}
-
-static void __init set_osi_linux(unsigned int enable)
-{
-	if (osi_linux.enable != enable)
-		osi_linux.enable = enable;
-
-	if (osi_linux.enable)
-		acpi_osi_setup("Linux");
-	else
-		acpi_osi_setup("!Linux");
-
-	return;
-}
-
-static void __init acpi_cmdline_osi_linux(unsigned int enable)
-{
-	osi_linux.cmdline = 1;	/* cmdline set the default and override DMI */
-	osi_linux.dmi = 0;
-	set_osi_linux(enable);
-
-	return;
-}
-
-void __init acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d)
-{
-	printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident);
-
-	if (enable == -1)
-		return;
-
-	osi_linux.dmi = 1;	/* DMI knows that this box asks OSI(Linux) */
-	set_osi_linux(enable);
-
-	return;
-}
-
-/*
- * Modify the list of "OS Interfaces" reported to BIOS via _OSI
- *
- * empty string disables _OSI
- * string starting with '!' disables that string
- * otherwise string is added to list, augmenting built-in strings
- */
-static void __init acpi_osi_setup_late(void)
-{
-	struct osi_setup_entry *osi;
-	char *str;
-	int i;
-	acpi_status status;
-
-	if (osi_linux.default_disabling) {
-		status = acpi_update_interfaces(ACPI_DISABLE_ALL_VENDOR_STRINGS);
-
-		if (ACPI_SUCCESS(status))
-			printk(KERN_INFO PREFIX "Disabled all _OSI OS vendors\n");
-	}
-
-	for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) {
-		osi = &osi_setup_entries[i];
-		str = osi->string;
-
-		if (*str == '\0')
-			break;
-		if (osi->enable) {
-			status = acpi_install_interface(str);
-
-			if (ACPI_SUCCESS(status))
-				printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str);
-		} else {
-			status = acpi_remove_interface(str);
-
-			if (ACPI_SUCCESS(status))
-				printk(KERN_INFO PREFIX "Deleted _OSI(%s)\n", str);
-		}
-	}
-}
-
-static int __init osi_setup(char *str)
-{
-	if (str && !strcmp("Linux", str))
-		acpi_cmdline_osi_linux(1);
-	else if (str && !strcmp("!Linux", str))
-		acpi_cmdline_osi_linux(0);
-	else
-		acpi_osi_setup(str);
-
-	return 1;
-}
-
-__setup("acpi_osi=", osi_setup);
-
 /*
  * Disable the auto-serialization of named objects creation methods.
  *
@@ -1986,12 +1492,6 @@ int acpi_resources_are_enforced(void)
 }
 EXPORT_SYMBOL(acpi_resources_are_enforced);
 
-bool acpi_osi_is_win8(void)
-{
-	return acpi_gbl_osi_data >= ACPI_OSI_WIN_8;
-}
-EXPORT_SYMBOL(acpi_osi_is_win8);
-
 /*
  * Deallocate the memory for a spinlock.
  */
@@ -2157,8 +1657,7 @@ acpi_status __init acpi_os_initialize1(v
 	BUG_ON(!kacpid_wq);
 	BUG_ON(!kacpi_notify_wq);
 	BUG_ON(!kacpi_hotplug_wq);
-	acpi_install_interface_handler(acpi_osi_handler);
-	acpi_osi_setup_late();
+	acpi_osi_init();
 	return AE_OK;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/pci_link.c linux-libre-4.7-gnu/drivers/acpi/pci_link.c
--- linux-libre-4.6-gnu/drivers/acpi/pci_link.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/pci_link.c	2016-07-24 15:23:50.000000000 -0400
@@ -36,6 +36,7 @@
 #include <linux/mutex.h>
 #include <linux/slab.h>
 #include <linux/acpi.h>
+#include <linux/irq.h>
 
 #include "internal.h"
 
@@ -437,17 +438,15 @@ static int acpi_pci_link_set(struct acpi
  * enabled system.
  */
 
-#define ACPI_MAX_IRQS		256
-#define ACPI_MAX_ISA_IRQ	16
+#define ACPI_MAX_ISA_IRQS	16
 
-#define PIRQ_PENALTY_PCI_AVAILABLE	(0)
 #define PIRQ_PENALTY_PCI_POSSIBLE	(16*16)
 #define PIRQ_PENALTY_PCI_USING		(16*16*16)
 #define PIRQ_PENALTY_ISA_TYPICAL	(16*16*16*16)
 #define PIRQ_PENALTY_ISA_USED		(16*16*16*16*16)
 #define PIRQ_PENALTY_ISA_ALWAYS		(16*16*16*16*16*16)
 
-static int acpi_irq_penalty[ACPI_MAX_IRQS] = {
+static int acpi_isa_irq_penalty[ACPI_MAX_ISA_IRQS] = {
 	PIRQ_PENALTY_ISA_ALWAYS,	/* IRQ0 timer */
 	PIRQ_PENALTY_ISA_ALWAYS,	/* IRQ1 keyboard */
 	PIRQ_PENALTY_ISA_ALWAYS,	/* IRQ2 cascade */
@@ -457,9 +456,9 @@ static int acpi_irq_penalty[ACPI_MAX_IRQ
 	PIRQ_PENALTY_ISA_TYPICAL,	/* IRQ6 */
 	PIRQ_PENALTY_ISA_TYPICAL,	/* IRQ7 parallel, spurious */
 	PIRQ_PENALTY_ISA_TYPICAL,	/* IRQ8 rtc, sometimes */
-	PIRQ_PENALTY_PCI_AVAILABLE,	/* IRQ9  PCI, often acpi */
-	PIRQ_PENALTY_PCI_AVAILABLE,	/* IRQ10 PCI */
-	PIRQ_PENALTY_PCI_AVAILABLE,	/* IRQ11 PCI */
+	0,				/* IRQ9  PCI, often acpi */
+	0,				/* IRQ10 PCI */
+	0,				/* IRQ11 PCI */
 	PIRQ_PENALTY_ISA_USED,		/* IRQ12 mouse */
 	PIRQ_PENALTY_ISA_USED,		/* IRQ13 fpe, sometimes */
 	PIRQ_PENALTY_ISA_USED,		/* IRQ14 ide0 */
@@ -467,6 +466,57 @@ static int acpi_irq_penalty[ACPI_MAX_IRQ
 	/* >IRQ15 */
 };
 
+static int acpi_irq_pci_sharing_penalty(int irq)
+{
+	struct acpi_pci_link *link;
+	int penalty = 0;
+	int i;
+
+	list_for_each_entry(link, &acpi_link_list, list) {
+		/*
+		 * If a link is active, penalize its IRQ heavily
+		 * so we try to choose a different IRQ.
+		 */
+		if (link->irq.active && link->irq.active == irq)
+			penalty += PIRQ_PENALTY_PCI_USING;
+
+		/*
+		 * penalize the IRQs PCI might use, but not as severely.
+		 */
+		for (i = 0; i < link->irq.possible_count; i++)
+			if (link->irq.possible[i] == irq)
+				penalty += PIRQ_PENALTY_PCI_POSSIBLE /
+					link->irq.possible_count;
+	}
+
+	return penalty;
+}
+
+static int acpi_irq_get_penalty(int irq)
+{
+	int penalty = 0;
+
+	/*
+	* Penalize IRQ used by ACPI SCI. If ACPI SCI pin attributes conflict
+	* with PCI IRQ attributes, mark ACPI SCI as ISA_ALWAYS so it won't be
+	* use for PCI IRQs.
+	*/
+	if (irq == acpi_gbl_FADT.sci_interrupt) {
+		u32 type = irq_get_trigger_type(irq) & IRQ_TYPE_SENSE_MASK;
+
+		if (type != IRQ_TYPE_LEVEL_LOW)
+			penalty += PIRQ_PENALTY_ISA_ALWAYS;
+		else
+			penalty += PIRQ_PENALTY_PCI_USING;
+	}
+
+	if (irq < ACPI_MAX_ISA_IRQS)
+		return penalty + acpi_isa_irq_penalty[irq];
+
+	penalty += acpi_irq_pci_sharing_penalty(irq);
+	return penalty;
+}
+
 int __init acpi_irq_penalty_init(void)
 {
 	struct acpi_pci_link *link;
@@ -487,14 +537,15 @@ int __init acpi_irq_penalty_init(void)
 			    link->irq.possible_count;
 
 			for (i = 0; i < link->irq.possible_count; i++) {
-				if (link->irq.possible[i] < ACPI_MAX_ISA_IRQ)
-					acpi_irq_penalty[link->irq.
+				if (link->irq.possible[i] < ACPI_MAX_ISA_IRQS)
+					acpi_isa_irq_penalty[link->irq.
 							 possible[i]] +=
 					    penalty;
 			}
 
-		} else if (link->irq.active) {
-			acpi_irq_penalty[link->irq.active] +=
+		} else if (link->irq.active &&
+				(link->irq.active < ACPI_MAX_ISA_IRQS)) {
+			acpi_isa_irq_penalty[link->irq.active] +=
 			    PIRQ_PENALTY_PCI_POSSIBLE;
 		}
 	}
@@ -547,12 +598,12 @@ static int acpi_pci_link_allocate(struct
 		 * the use of IRQs 9, 10, 11, and >15.
 		 */
 		for (i = (link->irq.possible_count - 1); i >= 0; i--) {
-			if (acpi_irq_penalty[irq] >
-			    acpi_irq_penalty[link->irq.possible[i]])
+			if (acpi_irq_get_penalty(irq) >
+			    acpi_irq_get_penalty(link->irq.possible[i]))
 				irq = link->irq.possible[i];
 		}
 	}
-	if (acpi_irq_penalty[irq] >= PIRQ_PENALTY_ISA_ALWAYS) {
+	if (acpi_irq_get_penalty(irq) >= PIRQ_PENALTY_ISA_ALWAYS) {
 		printk(KERN_ERR PREFIX "No IRQ available for %s [%s]. "
 			    "Try pci=noacpi or acpi=off\n",
 			    acpi_device_name(link->device),
@@ -568,7 +619,6 @@ static int acpi_pci_link_allocate(struct
 			    acpi_device_bid(link->device));
 		return -ENODEV;
 	} else {
-		acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_USING;
 		printk(KERN_WARNING PREFIX "%s [%s] enabled at IRQ %d\n",
 		       acpi_device_name(link->device),
 		       acpi_device_bid(link->device), link->irq.active);
@@ -778,7 +828,7 @@ static void acpi_pci_link_remove(struct
 }
 
 /*
- * modify acpi_irq_penalty[] from cmdline
+ * modify acpi_isa_irq_penalty[] from cmdline
  */
 static int __init acpi_irq_penalty_update(char *str, int used)
 {
@@ -787,23 +837,24 @@ static int __init acpi_irq_penalty_updat
 	for (i = 0; i < 16; i++) {
 		int retval;
 		int irq;
+		int new_penalty;
 
 		retval = get_option(&str, &irq);
 
 		if (!retval)
 			break;	/* no number found */
 
-		if (irq < 0)
-			continue;
-
-		if (irq >= ARRAY_SIZE(acpi_irq_penalty))
+		/* see if this is a ISA IRQ */
+		if ((irq < 0) || (irq >= ACPI_MAX_ISA_IRQS))
 			continue;
 
 		if (used)
-			acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED;
+			new_penalty = acpi_irq_get_penalty(irq) +
+					PIRQ_PENALTY_ISA_USED;
 		else
-			acpi_irq_penalty[irq] = PIRQ_PENALTY_PCI_AVAILABLE;
+			new_penalty = 0;
 
+		acpi_isa_irq_penalty[irq] = new_penalty;
 		if (retval != 2)	/* no next number */
 			break;
 	}
@@ -819,34 +870,15 @@ static int __init acpi_irq_penalty_updat
  */
 void acpi_penalize_isa_irq(int irq, int active)
 {
-	if (irq >= 0 && irq < ARRAY_SIZE(acpi_irq_penalty)) {
-		if (active)
-			acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED;
-		else
-			acpi_irq_penalty[irq] += PIRQ_PENALTY_PCI_USING;
-	}
+	if ((irq >= 0) && (irq < ARRAY_SIZE(acpi_isa_irq_penalty)))
+		acpi_isa_irq_penalty[irq] = acpi_irq_get_penalty(irq) +
+		  (active ? PIRQ_PENALTY_ISA_USED : PIRQ_PENALTY_PCI_USING);
 }
 
 bool acpi_isa_irq_available(int irq)
 {
-	return irq >= 0 && (irq >= ARRAY_SIZE(acpi_irq_penalty) ||
-			    acpi_irq_penalty[irq] < PIRQ_PENALTY_ISA_ALWAYS);
-}
-
-/*
- * Penalize IRQ used by ACPI SCI. If ACPI SCI pin attributes conflict with
- * PCI IRQ attributes, mark ACPI SCI as ISA_ALWAYS so it won't be use for
- * PCI IRQs.
- */
-void acpi_penalize_sci_irq(int irq, int trigger, int polarity)
-{
-	if (irq >= 0 && irq < ARRAY_SIZE(acpi_irq_penalty)) {
-		if (trigger != ACPI_MADT_TRIGGER_LEVEL ||
-		    polarity != ACPI_MADT_POLARITY_ACTIVE_LOW)
-			acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_ALWAYS;
-		else
-			acpi_irq_penalty[irq] += PIRQ_PENALTY_PCI_USING;
-	}
+	return irq >= 0 && (irq >= ARRAY_SIZE(acpi_isa_irq_penalty) ||
+		    acpi_irq_get_penalty(irq) < PIRQ_PENALTY_ISA_ALWAYS);
 }
 
 /*
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/processor_throttling.c linux-libre-4.7-gnu/drivers/acpi/processor_throttling.c
--- linux-libre-4.6-gnu/drivers/acpi/processor_throttling.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/processor_throttling.c	2016-07-24 15:23:50.000000000 -0400
@@ -676,6 +676,15 @@ static int acpi_processor_get_throttling
 	if (!pr->flags.throttling)
 		return -ENODEV;
 
+	/*
+	 * We don't care about error returns - we just try to mark
+	 * these reserved so that nobody else is confused into thinking
+	 * that this region might be unused..
+	 *
+	 * (In particular, allocating the IO range for Cardbus)
+	 */
+	request_region(pr->throttling.address, 6, "ACPI CPU throttle");
+
 	pr->throttling.state = 0;
 
 	duty_mask = pr->throttling.state_count - 1;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/sleep.c linux-libre-4.7-gnu/drivers/acpi/sleep.c
--- linux-libre-4.6-gnu/drivers/acpi/sleep.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/sleep.c	2016-07-24 15:23:50.000000000 -0400
@@ -26,6 +26,11 @@
 #include "internal.h"
 #include "sleep.h"
 
+/*
+ * Some HW-full platforms do not have _S5, so they may need
+ * to leverage efi power off for a shutdown.
+ */
+bool acpi_no_s5;
 static u8 sleep_states[ACPI_S_STATE_COUNT];
 
 static void acpi_sleep_tts_switch(u32 acpi_state)
@@ -882,6 +887,8 @@ int __init acpi_sleep_init(void)
 		sleep_states[ACPI_STATE_S5] = 1;
 		pm_power_off_prepare = acpi_power_off_prepare;
 		pm_power_off = acpi_power_off;
+	} else {
+		acpi_no_s5 = true;
 	}
 
 	supported[0] = 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/sysfs.c linux-libre-4.7-gnu/drivers/acpi/sysfs.c
--- linux-libre-4.6-gnu/drivers/acpi/sysfs.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/sysfs.c	2016-07-24 15:23:50.000000000 -0400
@@ -555,23 +555,22 @@ static void acpi_global_event_handler(u3
 static int get_status(u32 index, acpi_event_status *status,
 		      acpi_handle *handle)
 {
-	int result = 0;
+	int result;
 
 	if (index >= num_gpes + ACPI_NUM_FIXED_EVENTS)
-		goto end;
+		return -EINVAL;
 
 	if (index < num_gpes) {
 		result = acpi_get_gpe_device(index, handle);
 		if (result) {
 			ACPI_EXCEPTION((AE_INFO, AE_NOT_FOUND,
 					"Invalid GPE 0x%x", index));
-			goto end;
+			return result;
 		}
 		result = acpi_get_gpe_status(*handle, index, status);
 	} else if (index < (num_gpes + ACPI_NUM_FIXED_EVENTS))
 		result = acpi_get_event_status(index - num_gpes, status);
 
-end:
 	return result;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/tables.c linux-libre-4.7-gnu/drivers/acpi/tables.c
--- linux-libre-4.6-gnu/drivers/acpi/tables.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/tables.c	2016-07-24 15:23:50.000000000 -0400
@@ -32,8 +32,14 @@
 #include <linux/errno.h>
 #include <linux/acpi.h>
 #include <linux/bootmem.h>
+#include <linux/earlycpio.h>
+#include <linux/memblock.h>
 #include "internal.h"
 
+#ifdef CONFIG_ACPI_CUSTOM_DSDT
+#include CONFIG_ACPI_CUSTOM_DSDT_FILE
+#endif
+
 #define ACPI_MAX_TABLES		128
 
 static char *mps_inti_flags_polarity[] = { "dfl", "high", "res", "low" };
@@ -433,6 +439,314 @@ static void __init check_multiple_madt(v
 	return;
 }
 
+static void acpi_table_taint(struct acpi_table_header *table)
+{
+	pr_warn("Override [%4.4s-%8.8s], this is unsafe: tainting kernel\n",
+		table->signature, table->oem_table_id);
+	add_taint(TAINT_OVERRIDDEN_ACPI_TABLE, LOCKDEP_NOW_UNRELIABLE);
+}
+
+#ifdef CONFIG_ACPI_TABLE_UPGRADE
+static u64 acpi_tables_addr;
+static int all_tables_size;
+
+/* Copied from acpica/tbutils.c:acpi_tb_checksum() */
+static u8 __init acpi_table_checksum(u8 *buffer, u32 length)
+{
+	u8 sum = 0;
+	u8 *end = buffer + length;
+
+	while (buffer < end)
+		sum = (u8) (sum + *(buffer++));
+	return sum;
+}
+
+/* All but ACPI_SIG_RSDP and ACPI_SIG_FACS: */
+static const char * const table_sigs[] = {
+	ACPI_SIG_BERT, ACPI_SIG_CPEP, ACPI_SIG_ECDT, ACPI_SIG_EINJ,
+	ACPI_SIG_ERST, ACPI_SIG_HEST, ACPI_SIG_MADT, ACPI_SIG_MSCT,
+	ACPI_SIG_SBST, ACPI_SIG_SLIT, ACPI_SIG_SRAT, ACPI_SIG_ASF,
+	ACPI_SIG_BOOT, ACPI_SIG_DBGP, ACPI_SIG_DMAR, ACPI_SIG_HPET,
+	ACPI_SIG_IBFT, ACPI_SIG_IVRS, ACPI_SIG_MCFG, ACPI_SIG_MCHI,
+	ACPI_SIG_SLIC, ACPI_SIG_SPCR, ACPI_SIG_SPMI, ACPI_SIG_TCPA,
+	ACPI_SIG_UEFI, ACPI_SIG_WAET, ACPI_SIG_WDAT, ACPI_SIG_WDDT,
+	ACPI_SIG_WDRT, ACPI_SIG_DSDT, ACPI_SIG_FADT, ACPI_SIG_PSDT,
+	ACPI_SIG_RSDT, ACPI_SIG_XSDT, ACPI_SIG_SSDT, NULL };
+
+#define ACPI_HEADER_SIZE sizeof(struct acpi_table_header)
+
+#define NR_ACPI_INITRD_TABLES 64
+static struct cpio_data __initdata acpi_initrd_files[NR_ACPI_INITRD_TABLES];
+static DECLARE_BITMAP(acpi_initrd_installed, NR_ACPI_INITRD_TABLES);
+
+#define MAP_CHUNK_SIZE   (NR_FIX_BTMAPS << PAGE_SHIFT)
+
+static void __init acpi_table_initrd_init(void *data, size_t size)
+{
+	int sig, no, table_nr = 0, total_offset = 0;
+	long offset = 0;
+	struct acpi_table_header *table;
+	char cpio_path[32] = "kernel/firmware/acpi/";
+	struct cpio_data file;
+
+	if (data == NULL || size == 0)
+		return;
+
+	for (no = 0; no < NR_ACPI_INITRD_TABLES; no++) {
+		file = find_cpio_data(cpio_path, data, size, &offset);
+		if (!file.data)
+			break;
+
+		data += offset;
+		size -= offset;
+
+		if (file.size < sizeof(struct acpi_table_header)) {
+			pr_err("ACPI OVERRIDE: Table smaller than ACPI header [%s%s]\n",
+				cpio_path, file.name);
+			continue;
+		}
+
+		table = file.data;
+
+		for (sig = 0; table_sigs[sig]; sig++)
+			if (!memcmp(table->signature, table_sigs[sig], 4))
+				break;
+
+		if (!table_sigs[sig]) {
+			pr_err("ACPI OVERRIDE: Unknown signature [%s%s]\n",
+				cpio_path, file.name);
+			continue;
+		}
+		if (file.size != table->length) {
+			pr_err("ACPI OVERRIDE: File length does not match table length [%s%s]\n",
+				cpio_path, file.name);
+			continue;
+		}
+		if (acpi_table_checksum(file.data, table->length)) {
+			pr_err("ACPI OVERRIDE: Bad table checksum [%s%s]\n",
+				cpio_path, file.name);
+			continue;
+		}
+
+		pr_info("%4.4s ACPI table found in initrd [%s%s][0x%x]\n",
+			table->signature, cpio_path, file.name, table->length);
+
+		all_tables_size += table->length;
+		acpi_initrd_files[table_nr].data = file.data;
+		acpi_initrd_files[table_nr].size = file.size;
+		table_nr++;
+	}
+	if (table_nr == 0)
+		return;
+
+	acpi_tables_addr =
+		memblock_find_in_range(0, max_low_pfn_mapped << PAGE_SHIFT,
+				       all_tables_size, PAGE_SIZE);
+	if (!acpi_tables_addr) {
+		WARN_ON(1);
+		return;
+	}
+	/*
+	 * Only calling e820_add_reserve does not work and the
+	 * tables are invalid (memory got used) later.
+	 * memblock_reserve works as expected and the tables won't get modified.
+	 * But it's not enough on X86 because ioremap will
+	 * complain later (used by acpi_os_map_memory) that the pages
+	 * that should get mapped are not marked "reserved".
+	 * Both memblock_reserve and e820_add_region (via arch_reserve_mem_area)
+	 * works fine.
+	 */
+	memblock_reserve(acpi_tables_addr, all_tables_size);
+	arch_reserve_mem_area(acpi_tables_addr, all_tables_size);
+
+	/*
+	 * early_ioremap only can remap 256k one time. If we map all
+	 * tables one time, we will hit the limit. Need to map chunks
+	 * one by one during copying the same as that in relocate_initrd().
+	 */
+	for (no = 0; no < table_nr; no++) {
+		unsigned char *src_p = acpi_initrd_files[no].data;
+		phys_addr_t size = acpi_initrd_files[no].size;
+		phys_addr_t dest_addr = acpi_tables_addr + total_offset;
+		phys_addr_t slop, clen;
+		char *dest_p;
+
+		total_offset += size;
+
+		while (size) {
+			slop = dest_addr & ~PAGE_MASK;
+			clen = size;
+			if (clen > MAP_CHUNK_SIZE - slop)
+				clen = MAP_CHUNK_SIZE - slop;
+			dest_p = early_ioremap(dest_addr & PAGE_MASK,
+						 clen + slop);
+			memcpy(dest_p + slop, src_p, clen);
+			early_iounmap(dest_p, clen + slop);
+			src_p += clen;
+			dest_addr += clen;
+			size -= clen;
+		}
+	}
+}
+
+static acpi_status
+acpi_table_initrd_override(struct acpi_table_header *existing_table,
+			   acpi_physical_address *address, u32 *length)
+{
+	int table_offset = 0;
+	int table_index = 0;
+	struct acpi_table_header *table;
+	u32 table_length;
+
+	*length = 0;
+	*address = 0;
+	if (!acpi_tables_addr)
+		return AE_OK;
+
+	while (table_offset + ACPI_HEADER_SIZE <= all_tables_size) {
+		table = acpi_os_map_memory(acpi_tables_addr + table_offset,
+					   ACPI_HEADER_SIZE);
+		if (table_offset + table->length > all_tables_size) {
+			acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
+			WARN_ON(1);
+			return AE_OK;
+		}
+
+		table_length = table->length;
+
+		/* Only override tables matched */
+		if (memcmp(existing_table->signature, table->signature, 4) ||
+		    memcmp(table->oem_id, existing_table->oem_id,
+			   ACPI_OEM_ID_SIZE) ||
+		    memcmp(table->oem_table_id, existing_table->oem_table_id,
+			   ACPI_OEM_TABLE_ID_SIZE)) {
+			acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
+			goto next_table;
+		}
+		/*
+		 * Mark the table to avoid being used in
+		 * acpi_table_initrd_scan() and check the revision.
+		 */
+		if (test_and_set_bit(table_index, acpi_initrd_installed) ||
+		    existing_table->oem_revision >= table->oem_revision) {
+			acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
+			goto next_table;
+		}
+
+		*length = table_length;
+		*address = acpi_tables_addr + table_offset;
+		pr_info("Table Upgrade: override [%4.4s-%6.6s-%8.8s]\n",
+			table->signature, table->oem_id,
+			table->oem_table_id);
+		acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
+		break;
+
+next_table:
+		table_offset += table_length;
+		table_index++;
+	}
+	return AE_OK;
+}
+
+static void __init acpi_table_initrd_scan(void)
+{
+	int table_offset = 0;
+	int table_index = 0;
+	u32 table_length;
+	struct acpi_table_header *table;
+
+	if (!acpi_tables_addr)
+		return;
+
+	while (table_offset + ACPI_HEADER_SIZE <= all_tables_size) {
+		table = acpi_os_map_memory(acpi_tables_addr + table_offset,
+					   ACPI_HEADER_SIZE);
+		if (table_offset + table->length > all_tables_size) {
+			acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
+			WARN_ON(1);
+			return;
+		}
+
+		table_length = table->length;
+
+		/* Skip RSDT/XSDT which should only be used for override */
+		if (ACPI_COMPARE_NAME(table->signature, ACPI_SIG_RSDT) ||
+		    ACPI_COMPARE_NAME(table->signature, ACPI_SIG_XSDT)) {
+			acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
+			goto next_table;
+		}
+		/*
+		 * Mark the table to avoid being used in
+		 * acpi_table_initrd_override(). Though this is not possible
+		 * because override is disabled in acpi_install_table().
+		 */
+		if (test_and_set_bit(table_index, acpi_initrd_installed)) {
+			acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
+			goto next_table;
+		}
+
+		pr_info("Table Upgrade: install [%4.4s-%6.6s-%8.8s]\n",
+			table->signature, table->oem_id,
+			table->oem_table_id);
+		acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
+		acpi_install_table(acpi_tables_addr + table_offset, TRUE);
+next_table:
+		table_offset += table_length;
+		table_index++;
+	}
+}
+#else
+static void __init acpi_table_initrd_init(void *data, size_t size)
+{
+}
+
+static acpi_status
+acpi_table_initrd_override(struct acpi_table_header *existing_table,
+			   acpi_physical_address *address,
+			   u32 *table_length)
+{
+	*table_length = 0;
+	*address = 0;
+	return AE_OK;
+}
+
+static void __init acpi_table_initrd_scan(void)
+{
+}
+#endif /* CONFIG_ACPI_TABLE_UPGRADE */
+
+acpi_status
+acpi_os_physical_table_override(struct acpi_table_header *existing_table,
+				acpi_physical_address *address,
+				u32 *table_length)
+{
+	return acpi_table_initrd_override(existing_table, address,
+					  table_length);
+}
+
+acpi_status
+acpi_os_table_override(struct acpi_table_header *existing_table,
+		       struct acpi_table_header **new_table)
+{
+	if (!existing_table || !new_table)
+		return AE_BAD_PARAMETER;
+
+	*new_table = NULL;
+
+#ifdef CONFIG_ACPI_CUSTOM_DSDT
+	if (strncmp(existing_table->signature, "DSDT", 4) == 0)
+		*new_table = (struct acpi_table_header *)AmlCode;
+#endif
+	if (*new_table != NULL)
+		acpi_table_taint(existing_table);
+	return AE_OK;
+}
+
+void __init early_acpi_table_init(void *data, size_t size)
+{
+	acpi_table_initrd_init(data, size);
+}
+
 /*
  * acpi_table_init()
  *
@@ -457,7 +771,7 @@ int __init acpi_table_init(void)
 	status = acpi_initialize_tables(initial_tables, ACPI_MAX_TABLES, 0);
 	if (ACPI_FAILURE(status))
 		return -EINVAL;
-	acpi_initrd_initialize_tables();
+	acpi_table_initrd_scan();
 
 	check_multiple_madt();
 	return 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/utils.c linux-libre-4.7-gnu/drivers/acpi/utils.c
--- linux-libre-4.6-gnu/drivers/acpi/utils.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/utils.c	2016-07-24 15:23:50.000000000 -0400
@@ -625,7 +625,7 @@ acpi_status acpi_evaluate_lck(acpi_handl
  * some old BIOSes do expect a buffer or an integer etc.
  */
 union acpi_object *
-acpi_evaluate_dsm(acpi_handle handle, const u8 *uuid, int rev, int func,
+acpi_evaluate_dsm(acpi_handle handle, const u8 *uuid, u64 rev, u64 func,
 		  union acpi_object *argv4)
 {
 	acpi_status ret;
@@ -674,7 +674,7 @@ EXPORT_SYMBOL(acpi_evaluate_dsm);
  * functions. Currently only support 64 functions at maximum, should be
  * enough for now.
  */
-bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs)
+bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, u64 rev, u64 funcs)
 {
 	int i;
 	u64 mask = 0;
@@ -707,7 +707,7 @@ bool acpi_check_dsm(acpi_handle handle,
 EXPORT_SYMBOL(acpi_check_dsm);
 
 /**
- * acpi_dev_present - Detect presence of a given ACPI device in the system.
+ * acpi_dev_found - Detect presence of a given ACPI device in the namespace.
  * @hid: Hardware ID of the device.
  *
  * Return %true if the device was present at the moment of invocation.
@@ -719,7 +719,7 @@ EXPORT_SYMBOL(acpi_check_dsm);
  * instead). Calling from module_init() is fine (which is synonymous
  * with device_initcall()).
  */
-bool acpi_dev_present(const char *hid)
+bool acpi_dev_found(const char *hid)
 {
 	struct acpi_device_bus_id *acpi_device_bus_id;
 	bool found = false;
@@ -734,7 +734,7 @@ bool acpi_dev_present(const char *hid)
 
 	return found;
 }
-EXPORT_SYMBOL(acpi_dev_present);
+EXPORT_SYMBOL(acpi_dev_found);
 
 /*
  * acpi_backlight= handling, this is done here rather then in video_detect.c
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/acpi/video_detect.c linux-libre-4.7-gnu/drivers/acpi/video_detect.c
--- linux-libre-4.6-gnu/drivers/acpi/video_detect.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/acpi/video_detect.c	2016-07-24 15:23:50.000000000 -0400
@@ -358,7 +358,7 @@ enum acpi_backlight_type acpi_video_get_
 	if (!(video_caps & ACPI_VIDEO_BACKLIGHT))
 		return acpi_backlight_vendor;
 
-	if (acpi_osi_is_win8() && backlight_device_registered(BACKLIGHT_RAW))
+	if (acpi_osi_is_win8() && backlight_device_get_by_type(BACKLIGHT_RAW))
 		return acpi_backlight_native;
 
 	return acpi_backlight_video;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/amba/bus.c linux-libre-4.7-gnu/drivers/amba/bus.c
--- linux-libre-4.6-gnu/drivers/amba/bus.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/amba/bus.c	2016-07-24 15:23:50.000000000 -0400
@@ -336,16 +336,7 @@ static void amba_device_release(struct d
 	kfree(d);
 }
 
-/**
- *	amba_device_add - add a previously allocated AMBA device structure
- *	@dev: AMBA device allocated by amba_device_alloc
- *	@parent: resource parent for this devices resources
- *
- *	Claim the resource, and read the device cell ID if not already
- *	initialized.  Register the AMBA device with the Linux device
- *	manager.
- */
-int amba_device_add(struct amba_device *dev, struct resource *parent)
+static int amba_device_try_add(struct amba_device *dev, struct resource *parent)
 {
 	u32 size;
 	void __iomem *tmp;
@@ -373,6 +364,12 @@ int amba_device_add(struct amba_device *
 		goto err_release;
 	}
 
+	ret = dev_pm_domain_attach(&dev->dev, true);
+	if (ret == -EPROBE_DEFER) {
+		iounmap(tmp);
+		goto err_release;
+	}
+
 	ret = amba_get_enable_pclk(dev);
 	if (ret == 0) {
 		u32 pid, cid;
@@ -398,6 +395,7 @@ int amba_device_add(struct amba_device *
 	}
 
 	iounmap(tmp);
+	dev_pm_domain_detach(&dev->dev, true);
 
 	if (ret)
 		goto err_release;
@@ -421,6 +419,88 @@ int amba_device_add(struct amba_device *
  err_out:
 	return ret;
 }
+
+/*
+ * Registration of AMBA device require reading its pid and cid registers.
+ * To do this, the device must be turned on (if it is a part of power domain)
+ * and have clocks enabled. However in some cases those resources might not be
+ * yet available. Returning EPROBE_DEFER is not a solution in such case,
+ * because callers don't handle this special error code. Instead such devices
+ * are added to the special list and their registration is retried from
+ * periodic worker, until all resources are available and registration succeeds.
+ */
+struct deferred_device {
+	struct amba_device *dev;
+	struct resource *parent;
+	struct list_head node;
+};
+
+static LIST_HEAD(deferred_devices);
+static DEFINE_MUTEX(deferred_devices_lock);
+
+static void amba_deferred_retry_func(struct work_struct *dummy);
+static DECLARE_DELAYED_WORK(deferred_retry_work, amba_deferred_retry_func);
+
+#define DEFERRED_DEVICE_TIMEOUT (msecs_to_jiffies(5 * 1000))
+
+static void amba_deferred_retry_func(struct work_struct *dummy)
+{
+	struct deferred_device *ddev, *tmp;
+
+	mutex_lock(&deferred_devices_lock);
+
+	list_for_each_entry_safe(ddev, tmp, &deferred_devices, node) {
+		int ret = amba_device_try_add(ddev->dev, ddev->parent);
+
+		if (ret == -EPROBE_DEFER)
+			continue;
+
+		list_del_init(&ddev->node);
+		kfree(ddev);
+	}
+
+	if (!list_empty(&deferred_devices))
+		schedule_delayed_work(&deferred_retry_work,
+				      DEFERRED_DEVICE_TIMEOUT);
+
+	mutex_unlock(&deferred_devices_lock);
+}
+
+/**
+ *	amba_device_add - add a previously allocated AMBA device structure
+ *	@dev: AMBA device allocated by amba_device_alloc
+ *	@parent: resource parent for this devices resources
+ *
+ *	Claim the resource, and read the device cell ID if not already
+ *	initialized.  Register the AMBA device with the Linux device
+ *	manager.
+ */
+int amba_device_add(struct amba_device *dev, struct resource *parent)
+{
+	int ret = amba_device_try_add(dev, parent);
+
+	if (ret == -EPROBE_DEFER) {
+		struct deferred_device *ddev;
+
+		ddev = kmalloc(sizeof(*ddev), GFP_KERNEL);
+		if (!ddev)
+			return -ENOMEM;
+
+		ddev->dev = dev;
+		ddev->parent = parent;
+		ret = 0;
+
+		mutex_lock(&deferred_devices_lock);
+
+		if (list_empty(&deferred_devices))
+			schedule_delayed_work(&deferred_retry_work,
+					      DEFERRED_DEVICE_TIMEOUT);
+		list_add_tail(&ddev->node, &deferred_devices);
+
+		mutex_unlock(&deferred_devices_lock);
+	}
+	return ret;
+}
 EXPORT_SYMBOL_GPL(amba_device_add);
 
 static struct amba_device *
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/ata/ahci_seattle.c linux-libre-4.7-gnu/drivers/ata/ahci_seattle.c
--- linux-libre-4.6-gnu/drivers/ata/ahci_seattle.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/ata/ahci_seattle.c	2016-07-24 15:23:50.000000000 -0400
@@ -137,7 +137,7 @@ static const struct ata_port_info *ahci_
 	u32 val;
 
 	plat_data = devm_kzalloc(dev, sizeof(*plat_data), GFP_KERNEL);
-	if (IS_ERR(plat_data))
+	if (!plat_data)
 		return &ahci_port_info;
 
 	plat_data->sgpio_ctrl = devm_ioremap_resource(dev,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/ata/Kconfig linux-libre-4.7-gnu/drivers/ata/Kconfig
--- linux-libre-4.6-gnu/drivers/ata/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/ata/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -313,14 +313,23 @@ config ATA_PIIX
 
 config SATA_DWC
 	tristate "DesignWare Cores SATA support"
-	depends on 460EX
-	select DW_DMAC
+	depends on DMADEVICES
+	select GENERIC_PHY
 	help
 	  This option enables support for the on-chip SATA controller of the
 	  AppliedMicro processor 460EX.
 
 	  If unsure, say N.
 
+config SATA_DWC_OLD_DMA
+	bool "Support old device trees"
+	depends on SATA_DWC
+	select DW_DMAC_CORE
+	default y if 460EX
+	help
+	  This option enables support for old device trees without the
+	  "dmas" property.
+
 config SATA_DWC_DEBUG
 	bool "Debugging driver version"
 	depends on SATA_DWC
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/ata/libahci.c linux-libre-4.7-gnu/drivers/ata/libahci.c
--- linux-libre-4.6-gnu/drivers/ata/libahci.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/ata/libahci.c	2016-07-24 15:23:50.000000000 -0400
@@ -2550,8 +2550,8 @@ int ahci_host_activate(struct ata_host *
 
 	if (hpriv->flags & (AHCI_HFLAG_MULTI_MSI | AHCI_HFLAG_MULTI_MSIX)) {
 		if (hpriv->irq_handler)
-			dev_warn(host->dev, "both AHCI_HFLAG_MULTI_MSI flag set \
-				 and custom irq handler implemented\n");
+			dev_warn(host->dev,
+			         "both AHCI_HFLAG_MULTI_MSI flag set and custom irq handler implemented\n");
 
 		rc = ahci_host_activate_multi_irqs(host, sht);
 	} else {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/ata/libata-core.c linux-libre-4.7-gnu/drivers/ata/libata-core.c
--- linux-libre-4.6-gnu/drivers/ata/libata-core.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/ata/libata-core.c	2016-07-24 15:23:50.000000000 -0400
@@ -66,6 +66,7 @@
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
 #include <asm/byteorder.h>
+#include <asm/unaligned.h>
 #include <linux/cdrom.h>
 #include <linux/ratelimit.h>
 #include <linux/pm_runtime.h>
@@ -695,7 +696,7 @@ static int ata_rwcmd_protocol(struct ata
  *	RETURNS:
  *	Block address read from @tf.
  */
-u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev)
+u64 ata_tf_read_block(const struct ata_taskfile *tf, struct ata_device *dev)
 {
 	u64 block = 0;
 
@@ -720,7 +721,7 @@ u64 ata_tf_read_block(struct ata_taskfil
 		if (!sect) {
 			ata_dev_warn(dev,
 				     "device reported invalid CHS sector 0\n");
-			sect = 1; /* oh well */
+			return U64_MAX;
 		}
 
 		block = (cyl * dev->heads + head) * dev->sectors + sect - 1;
@@ -884,7 +885,7 @@ unsigned long ata_pack_xfermask(unsigned
  *	@udma_mask: resulting udma_mask
  *
  *	Unpack @xfer_mask into @pio_mask, @mwdma_mask and @udma_mask.
- *	Any NULL distination masks will be ignored.
+ *	Any NULL destination masks will be ignored.
  */
 void ata_unpack_xfermask(unsigned long xfer_mask, unsigned long *pio_mask,
 			 unsigned long *mwdma_mask, unsigned long *udma_mask)
@@ -2079,6 +2080,81 @@ static inline u8 ata_dev_knobble(struct
 	return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id)));
 }
 
+static void ata_dev_config_ncq_send_recv(struct ata_device *dev)
+{
+	struct ata_port *ap = dev->link->ap;
+	unsigned int err_mask;
+	int log_index = ATA_LOG_NCQ_SEND_RECV * 2;
+	u16 log_pages;
+
+	err_mask = ata_read_log_page(dev, ATA_LOG_DIRECTORY,
+				     0, ap->sector_buf, 1);
+	if (err_mask) {
+		ata_dev_dbg(dev,
+			    "failed to get Log Directory Emask 0x%x\n",
+			    err_mask);
+		return;
+	}
+	log_pages = get_unaligned_le16(&ap->sector_buf[log_index]);
+	if (!log_pages) {
+		ata_dev_warn(dev,
+			     "NCQ Send/Recv Log not supported\n");
+		return;
+	}
+	err_mask = ata_read_log_page(dev, ATA_LOG_NCQ_SEND_RECV,
+				     0, ap->sector_buf, 1);
+	if (err_mask) {
+		ata_dev_dbg(dev,
+			    "failed to get NCQ Send/Recv Log Emask 0x%x\n",
+			    err_mask);
+	} else {
+		u8 *cmds = dev->ncq_send_recv_cmds;
+
+		dev->flags |= ATA_DFLAG_NCQ_SEND_RECV;
+		memcpy(cmds, ap->sector_buf, ATA_LOG_NCQ_SEND_RECV_SIZE);
+
+		if (dev->horkage & ATA_HORKAGE_NO_NCQ_TRIM) {
+			ata_dev_dbg(dev, "disabling queued TRIM support\n");
+			cmds[ATA_LOG_NCQ_SEND_RECV_DSM_OFFSET] &=
+				~ATA_LOG_NCQ_SEND_RECV_DSM_TRIM;
+		}
+	}
+}
+
+static void ata_dev_config_ncq_non_data(struct ata_device *dev)
+{
+	struct ata_port *ap = dev->link->ap;
+	unsigned int err_mask;
+	int log_index = ATA_LOG_NCQ_NON_DATA * 2;
+	u16 log_pages;
+
+	err_mask = ata_read_log_page(dev, ATA_LOG_DIRECTORY,
+				     0, ap->sector_buf, 1);
+	if (err_mask) {
+		ata_dev_dbg(dev,
+			    "failed to get Log Directory Emask 0x%x\n",
+			    err_mask);
+		return;
+	}
+	log_pages = get_unaligned_le16(&ap->sector_buf[log_index]);
+	if (!log_pages) {
+		ata_dev_warn(dev,
+			     "NCQ Send/Recv Log not supported\n");
+		return;
+	}
+	err_mask = ata_read_log_page(dev, ATA_LOG_NCQ_NON_DATA,
+				     0, ap->sector_buf, 1);
+	if (err_mask) {
+		ata_dev_dbg(dev,
+			    "failed to get NCQ Non-Data Log Emask 0x%x\n",
+			    err_mask);
+	} else {
+		u8 *cmds = dev->ncq_non_data_cmds;
+
+		memcpy(cmds, ap->sector_buf, ATA_LOG_NCQ_NON_DATA_SIZE);
+	}
+}
+
 static int ata_dev_config_ncq(struct ata_device *dev,
 			       char *desc, size_t desc_sz)
 {
@@ -2123,29 +2199,125 @@ static int ata_dev_config_ncq(struct ata
 		snprintf(desc, desc_sz, "NCQ (depth %d/%d)%s", hdepth,
 			ddepth, aa_desc);
 
-	if ((ap->flags & ATA_FLAG_FPDMA_AUX) &&
-	    ata_id_has_ncq_send_and_recv(dev->id)) {
-		err_mask = ata_read_log_page(dev, ATA_LOG_NCQ_SEND_RECV,
-					     0, ap->sector_buf, 1);
-		if (err_mask) {
-			ata_dev_dbg(dev,
-				    "failed to get NCQ Send/Recv Log Emask 0x%x\n",
-				    err_mask);
-		} else {
-			u8 *cmds = dev->ncq_send_recv_cmds;
+	if ((ap->flags & ATA_FLAG_FPDMA_AUX)) {
+		if (ata_id_has_ncq_send_and_recv(dev->id))
+			ata_dev_config_ncq_send_recv(dev);
+		if (ata_id_has_ncq_non_data(dev->id))
+			ata_dev_config_ncq_non_data(dev);
+	}
 
-			dev->flags |= ATA_DFLAG_NCQ_SEND_RECV;
-			memcpy(cmds, ap->sector_buf, ATA_LOG_NCQ_SEND_RECV_SIZE);
+	return 0;
+}
 
-			if (dev->horkage & ATA_HORKAGE_NO_NCQ_TRIM) {
-				ata_dev_dbg(dev, "disabling queued TRIM support\n");
-				cmds[ATA_LOG_NCQ_SEND_RECV_DSM_OFFSET] &=
-					~ATA_LOG_NCQ_SEND_RECV_DSM_TRIM;
-			}
+static void ata_dev_config_sense_reporting(struct ata_device *dev)
+{
+	unsigned int err_mask;
+
+	if (!ata_id_has_sense_reporting(dev->id))
+		return;
+
+	if (ata_id_sense_reporting_enabled(dev->id))
+		return;
+
+	err_mask = ata_dev_set_feature(dev, SETFEATURE_SENSE_DATA, 0x1);
+	if (err_mask) {
+		ata_dev_dbg(dev,
+			    "failed to enable Sense Data Reporting, Emask 0x%x\n",
+			    err_mask);
+	}
+}
+
+static void ata_dev_config_zac(struct ata_device *dev)
+{
+	struct ata_port *ap = dev->link->ap;
+	unsigned int err_mask;
+	u8 *identify_buf = ap->sector_buf;
+	int log_index = ATA_LOG_SATA_ID_DEV_DATA * 2, i, found = 0;
+	u16 log_pages;
+
+	dev->zac_zones_optimal_open = U32_MAX;
+	dev->zac_zones_optimal_nonseq = U32_MAX;
+	dev->zac_zones_max_open = U32_MAX;
+
+	/*
+	 * Always set the 'ZAC' flag for Host-managed devices.
+	 */
+	if (dev->class == ATA_DEV_ZAC)
+		dev->flags |= ATA_DFLAG_ZAC;
+	else if (ata_id_zoned_cap(dev->id) == 0x01)
+		/*
+		 * Check for host-aware devices.
+		 */
+		dev->flags |= ATA_DFLAG_ZAC;
+
+	if (!(dev->flags & ATA_DFLAG_ZAC))
+		return;
+
+	/*
+	 * Read Log Directory to figure out if IDENTIFY DEVICE log
+	 * is supported.
+	 */
+	err_mask = ata_read_log_page(dev, ATA_LOG_DIRECTORY,
+				     0, ap->sector_buf, 1);
+	if (err_mask) {
+		ata_dev_info(dev,
+			     "failed to get Log Directory Emask 0x%x\n",
+			     err_mask);
+		return;
+	}
+	log_pages = get_unaligned_le16(&ap->sector_buf[log_index]);
+	if (log_pages == 0) {
+		ata_dev_warn(dev,
+			     "ATA Identify Device Log not supported\n");
+		return;
+	}
+	/*
+	 * Read IDENTIFY DEVICE data log, page 0, to figure out
+	 * if page 9 is supported.
+	 */
+	err_mask = ata_read_log_page(dev, ATA_LOG_SATA_ID_DEV_DATA, 0,
+				     identify_buf, 1);
+	if (err_mask) {
+		ata_dev_info(dev,
+			     "failed to get Device Identify Log Emask 0x%x\n",
+			     err_mask);
+		return;
+	}
+	log_pages = identify_buf[8];
+	for (i = 0; i < log_pages; i++) {
+		if (identify_buf[9 + i] == ATA_LOG_ZONED_INFORMATION) {
+			found++;
+			break;
 		}
 	}
+	if (!found) {
+		ata_dev_warn(dev,
+			     "ATA Zoned Information Log not supported\n");
+		return;
+	}
 
-	return 0;
+	/*
+	 * Read IDENTIFY DEVICE data log, page 9 (Zoned-device information)
+	 */
+	err_mask = ata_read_log_page(dev, ATA_LOG_SATA_ID_DEV_DATA,
+				     ATA_LOG_ZONED_INFORMATION,
+				     identify_buf, 1);
+	if (!err_mask) {
+		u64 zoned_cap, opt_open, opt_nonseq, max_open;
+
+		zoned_cap = get_unaligned_le64(&identify_buf[8]);
+		if ((zoned_cap >> 63))
+			dev->zac_zoned_cap = (zoned_cap & 1);
+		opt_open = get_unaligned_le64(&identify_buf[24]);
+		if ((opt_open >> 63))
+			dev->zac_zones_optimal_open = (u32)opt_open;
+		opt_nonseq = get_unaligned_le64(&identify_buf[32]);
+		if ((opt_nonseq >> 63))
+			dev->zac_zones_optimal_nonseq = (u32)opt_nonseq;
+		max_open = get_unaligned_le64(&identify_buf[40]);
+		if ((max_open >> 63))
+			dev->zac_zones_max_open = (u32)max_open;
+	}
 }
 
 /**
@@ -2370,7 +2542,8 @@ int ata_dev_configure(struct ata_device
 					dev->devslp_timing[i] = sata_setting[j];
 				}
 		}
-
+		ata_dev_config_sense_reporting(dev);
+		ata_dev_config_zac(dev);
 		dev->cdb_len = 16;
 	}
 
@@ -3399,7 +3572,7 @@ int ata_do_set_mode(struct ata_link *lin
  *	EH context.
  *
  *	RETURNS:
- *	0 if @linke is ready before @deadline; otherwise, -errno.
+ *	0 if @link is ready before @deadline; otherwise, -errno.
  */
 int ata_wait_ready(struct ata_link *link, unsigned long deadline,
 		   int (*check_ready)(struct ata_link *link))
@@ -3480,7 +3653,7 @@ int ata_wait_ready(struct ata_link *link
  *	EH context.
  *
  *	RETURNS:
- *	0 if @linke is ready before @deadline; otherwise, -errno.
+ *	0 if @link is ready before @deadline; otherwise, -errno.
  */
 int ata_wait_after_reset(struct ata_link *link, unsigned long deadline,
 				int (*check_ready)(struct ata_link *link))
@@ -3493,7 +3666,7 @@ int ata_wait_after_reset(struct ata_link
 /**
  *	sata_link_debounce - debounce SATA phy status
  *	@link: ATA link to debounce SATA phy status for
- *	@params: timing parameters { interval, duratinon, timeout } in msec
+ *	@params: timing parameters { interval, duration, timeout } in msec
  *	@deadline: deadline jiffies for the operation
  *
  *	Make sure SStatus of @link reaches stable state, determined by
@@ -3563,7 +3736,7 @@ int sata_link_debounce(struct ata_link *
 /**
  *	sata_link_resume - resume SATA link
  *	@link: ATA link to resume SATA
- *	@params: timing parameters { interval, duratinon, timeout } in msec
+ *	@params: timing parameters { interval, duration, timeout } in msec
  *	@deadline: deadline jiffies for the operation
  *
  *	Resume SATA phy @link and debounce it.
@@ -3746,7 +3919,7 @@ int ata_std_prereset(struct ata_link *li
 /**
  *	sata_link_hardreset - reset link via SATA phy reset
  *	@link: link to reset
- *	@timing: timing parameters { interval, duratinon, timeout } in msec
+ *	@timing: timing parameters { interval, duration, timeout } in msec
  *	@deadline: deadline jiffies for the operation
  *	@online: optional out parameter indicating link onlineness
  *	@check_ready: optional callback to check link readiness
@@ -4141,6 +4314,12 @@ static const struct ata_blacklist_entry
 	 */
 	{ "ST380013AS",		"3.20",		ATA_HORKAGE_MAX_SEC_1024 },
 
+	/*
+	 * Device times out with higher max sects.
+	 * https://bugzilla.kernel.org/show_bug.cgi?id=121671
+	 */
+	{ "LITEON CX1-JB256-HP", NULL,		ATA_HORKAGE_MAX_SEC_1024 },
+
 	/* Devices we expect to fail diagnostics */
 
 	/* Devices where NCQ should be avoided */
@@ -4528,6 +4707,7 @@ unsigned int ata_dev_set_feature(struct
 {
 	struct ata_taskfile tf;
 	unsigned int err_mask;
+	unsigned long timeout = 0;
 
 	/* set up set-features taskfile */
 	DPRINTK("set features - SATA features\n");
@@ -4539,7 +4719,10 @@ unsigned int ata_dev_set_feature(struct
 	tf.protocol = ATA_PROT_NODATA;
 	tf.nsect = feature;
 
-	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);
+	if (enable == SETFEATURES_SPINUP)
+		timeout = ata_probe_timeout ?
+			  ata_probe_timeout * 1000 : SETFEATURES_SPINUP_TIMEOUT;
+	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, timeout);
 
 	DPRINTK("EXIT, err_mask=%x\n", err_mask);
 	return err_mask;
@@ -6208,7 +6391,7 @@ int ata_host_register(struct ata_host *h
  *
  *	After allocating an ATA host and initializing it, most libata
  *	LLDs perform three steps to activate the host - start host,
- *	request IRQ and register it.  This helper takes necessasry
+ *	request IRQ and register it.  This helper takes necessary
  *	arguments and performs the three steps in one go.
  *
  *	An invalid IRQ skips the IRQ registration and expects the host to
@@ -6261,7 +6444,7 @@ int ata_host_activate(struct ata_host *h
 }
 
 /**
- *	ata_port_detach - Detach ATA port in prepration of device removal
+ *	ata_port_detach - Detach ATA port in preparation of device removal
  *	@ap: ATA port to be detached
  *
  *	Detach all ATA devices and the associated SCSI devices of @ap;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/ata/libata-eh.c linux-libre-4.7-gnu/drivers/ata/libata-eh.c
--- linux-libre-4.6-gnu/drivers/ata/libata-eh.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/ata/libata-eh.c	2016-07-24 15:23:50.000000000 -0400
@@ -606,7 +606,7 @@ void ata_scsi_error(struct Scsi_Host *ho
 	ata_scsi_port_error_handler(host, ap);
 
 	/* finish or retry handled scmd's and clean up */
-	WARN_ON(host->host_failed || !list_empty(&eh_work_q));
+	WARN_ON(!list_empty(&eh_work_q));
 
 	DPRINTK("EXIT\n");
 }
@@ -1600,6 +1600,8 @@ static int ata_eh_read_log_10h(struct at
 	tf->hob_lbah = buf[10];
 	tf->nsect = buf[12];
 	tf->hob_nsect = buf[13];
+	if (ata_id_has_ncq_autosense(dev->id))
+		tf->auxiliary = buf[14] << 16 | buf[15] << 8 | buf[16];
 
 	return 0;
 }
@@ -1636,6 +1638,56 @@ unsigned int atapi_eh_tur(struct ata_dev
 }
 
 /**
+ *	ata_eh_request_sense - perform REQUEST_SENSE_DATA_EXT
+ *	@dev: device to perform REQUEST_SENSE_SENSE_DATA_EXT to
+ *	@cmd: scsi command for which the sense code should be set
+ *
+ *	Perform REQUEST_SENSE_DATA_EXT after the device reported CHECK
+ *	SENSE.  This function is an EH helper.
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep).
+ */
+static void ata_eh_request_sense(struct ata_queued_cmd *qc,
+				 struct scsi_cmnd *cmd)
+{
+	struct ata_device *dev = qc->dev;
+	struct ata_taskfile tf;
+	unsigned int err_mask;
+
+	if (qc->ap->pflags & ATA_PFLAG_FROZEN) {
+		ata_dev_warn(dev, "sense data available but port frozen\n");
+		return;
+	}
+
+	if (!cmd || qc->flags & ATA_QCFLAG_SENSE_VALID)
+		return;
+
+	if (!ata_id_sense_reporting_enabled(dev->id)) {
+		ata_dev_warn(qc->dev, "sense data reporting disabled\n");
+		return;
+	}
+
+	DPRINTK("ATA request sense\n");
+
+	ata_tf_init(dev, &tf);
+	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	tf.flags |= ATA_TFLAG_LBA | ATA_TFLAG_LBA48;
+	tf.command = ATA_CMD_REQ_SENSE_DATA;
+	tf.protocol = ATA_PROT_NODATA;
+
+	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);
+	/* Ignore err_mask; ATA_ERR might be set */
+	if (tf.command & ATA_SENSE) {
+		ata_scsi_set_sense(dev, cmd, tf.lbah, tf.lbam, tf.lbal);
+		qc->flags |= ATA_QCFLAG_SENSE_VALID;
+	} else {
+		ata_dev_warn(dev, "request sense failed stat %02x emask %x\n",
+			     tf.command, err_mask);
+	}
+}
+
+/**
  *	atapi_eh_request_sense - perform ATAPI REQUEST_SENSE
  *	@dev: device to perform REQUEST_SENSE to
  *	@sense_buf: result sense data buffer (SCSI_SENSE_BUFFERSIZE bytes long)
@@ -1797,6 +1849,18 @@ void ata_eh_analyze_ncq_error(struct ata
 	memcpy(&qc->result_tf, &tf, sizeof(tf));
 	qc->result_tf.flags = ATA_TFLAG_ISADDR | ATA_TFLAG_LBA | ATA_TFLAG_LBA48;
 	qc->err_mask |= AC_ERR_DEV | AC_ERR_NCQ;
+	if ((qc->result_tf.command & ATA_SENSE) || qc->result_tf.auxiliary) {
+		char sense_key, asc, ascq;
+
+		sense_key = (qc->result_tf.auxiliary >> 16) & 0xff;
+		asc = (qc->result_tf.auxiliary >> 8) & 0xff;
+		ascq = qc->result_tf.auxiliary & 0xff;
+		ata_scsi_set_sense(dev, qc->scsicmd, sense_key, asc, ascq);
+		ata_scsi_set_sense_information(dev, qc->scsicmd,
+					       &qc->result_tf);
+		qc->flags |= ATA_QCFLAG_SENSE_VALID;
+	}
+
 	ehc->i.err_mask &= ~AC_ERR_DEV;
 }
 
@@ -1826,14 +1890,23 @@ static unsigned int ata_eh_analyze_tf(st
 		return ATA_EH_RESET;
 	}
 
-	if (stat & (ATA_ERR | ATA_DF))
+	if (stat & (ATA_ERR | ATA_DF)) {
 		qc->err_mask |= AC_ERR_DEV;
-	else
+		/*
+		 * Sense data reporting does not work if the
+		 * device fault bit is set.
+		 */
+		if (stat & ATA_DF)
+			stat &= ~ATA_SENSE;
+	} else {
 		return 0;
+	}
 
 	switch (qc->dev->class) {
 	case ATA_DEV_ATA:
 	case ATA_DEV_ZAC:
+		if (stat & ATA_SENSE)
+			ata_eh_request_sense(qc, qc->scsicmd);
 		if (err & ATA_ICRC)
 			qc->err_mask |= AC_ERR_ATA_BUS;
 		if (err & (ATA_UNC | ATA_AMNF))
@@ -1847,20 +1920,31 @@ static unsigned int ata_eh_analyze_tf(st
 			tmp = atapi_eh_request_sense(qc->dev,
 						qc->scsicmd->sense_buffer,
 						qc->result_tf.feature >> 4);
-			if (!tmp) {
-				/* ATA_QCFLAG_SENSE_VALID is used to
-				 * tell atapi_qc_complete() that sense
-				 * data is already valid.
-				 *
-				 * TODO: interpret sense data and set
-				 * appropriate err_mask.
-				 */
+			if (!tmp)
 				qc->flags |= ATA_QCFLAG_SENSE_VALID;
-			} else
+			else
 				qc->err_mask |= tmp;
 		}
 	}
 
+	if (qc->flags & ATA_QCFLAG_SENSE_VALID) {
+		int ret = scsi_check_sense(qc->scsicmd);
+		/*
+		 * SUCCESS here means that the sense code could
+		 * evaluated and should be passed to the upper layers
+		 * for correct evaluation.
+		 * FAILED means the sense code could not interpreted
+		 * and the device would need to be reset.
+		 * NEEDS_RETRY and ADD_TO_MLQUEUE means that the
+		 * command would need to be retried.
+		 */
+		if (ret == NEEDS_RETRY || ret == ADD_TO_MLQUEUE) {
+			qc->flags |= ATA_QCFLAG_RETRY;
+			qc->err_mask |= AC_ERR_OTHER;
+		} else if (ret != SUCCESS) {
+			qc->err_mask |= AC_ERR_HSM;
+		}
+	}
 	if (qc->err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT | AC_ERR_ATA_BUS))
 		action |= ATA_EH_RESET;
 
@@ -2398,6 +2482,8 @@ const char *ata_get_cmd_descript(u8 comm
 		{ ATA_CMD_CFA_WRITE_MULT_NE,	"CFA WRITE MULTIPLE WITHOUT ERASE" },
 		{ ATA_CMD_REQ_SENSE_DATA,	"REQUEST SENSE DATA EXT" },
 		{ ATA_CMD_SANITIZE_DEVICE,	"SANITIZE DEVICE" },
+		{ ATA_CMD_ZAC_MGMT_IN,		"ZAC MANAGEMENT IN" },
+		{ ATA_CMD_ZAC_MGMT_OUT,		"ZAC MANAGEMENT OUT" },
 		{ ATA_CMD_READ_LONG,		"READ LONG (with retries)" },
 		{ ATA_CMD_READ_LONG_ONCE,	"READ LONG (without retries)" },
 		{ ATA_CMD_WRITE_LONG,		"WRITE LONG (with retries)" },
@@ -2569,14 +2655,15 @@ static void ata_eh_link_report(struct at
 
 #ifdef CONFIG_ATA_VERBOSE_ERROR
 		if (res->command & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ |
-				    ATA_ERR)) {
+				    ATA_SENSE | ATA_ERR)) {
 			if (res->command & ATA_BUSY)
 				ata_dev_err(qc->dev, "status: { Busy }\n");
 			else
-				ata_dev_err(qc->dev, "status: { %s%s%s%s}\n",
+				ata_dev_err(qc->dev, "status: { %s%s%s%s%s}\n",
 				  res->command & ATA_DRDY ? "DRDY " : "",
 				  res->command & ATA_DF ? "DF " : "",
 				  res->command & ATA_DRQ ? "DRQ " : "",
+				  res->command & ATA_SENSE ? "SENSE " : "",
 				  res->command & ATA_ERR ? "ERR " : "");
 		}
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/ata/libata.h linux-libre-4.7-gnu/drivers/ata/libata.h
--- linux-libre-4.6-gnu/drivers/ata/libata.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/ata/libata.h	2016-07-24 15:23:50.000000000 -0400
@@ -67,7 +67,8 @@ extern struct ata_queued_cmd *ata_qc_new
 extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
 			   u64 block, u32 n_block, unsigned int tf_flags,
 			   unsigned int tag);
-extern u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev);
+extern u64 ata_tf_read_block(const struct ata_taskfile *tf,
+			     struct ata_device *dev);
 extern unsigned ata_exec_internal(struct ata_device *dev,
 				  struct ata_taskfile *tf, const u8 *cdb,
 				  int dma_dir, void *buf, unsigned int buflen,
@@ -137,6 +138,11 @@ extern int ata_scsi_add_hosts(struct ata
 			      struct scsi_host_template *sht);
 extern void ata_scsi_scan_host(struct ata_port *ap, int sync);
 extern int ata_scsi_offline_dev(struct ata_device *dev);
+extern void ata_scsi_set_sense(struct ata_device *dev,
+			       struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq);
+extern void ata_scsi_set_sense_information(struct ata_device *dev,
+					   struct scsi_cmnd *cmd,
+					   const struct ata_taskfile *tf);
 extern void ata_scsi_media_change_notify(struct ata_device *dev);
 extern void ata_scsi_hotplug(struct work_struct *work);
 extern void ata_schedule_scsi_eh(struct Scsi_Host *shost);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/ata/libata-scsi.c linux-libre-4.7-gnu/drivers/ata/libata-scsi.c
--- linux-libre-4.6-gnu/drivers/ata/libata-scsi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/ata/libata-scsi.c	2016-07-24 15:23:50.000000000 -0400
@@ -270,11 +270,52 @@ DEVICE_ATTR(unload_heads, S_IRUGO | S_IW
 	    ata_scsi_park_show, ata_scsi_park_store);
 EXPORT_SYMBOL_GPL(dev_attr_unload_heads);
 
-static void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq)
+void ata_scsi_set_sense(struct ata_device *dev, struct scsi_cmnd *cmd,
+			u8 sk, u8 asc, u8 ascq)
 {
+	bool d_sense = (dev->flags & ATA_DFLAG_D_SENSE);
+
+	if (!cmd)
+		return;
+
 	cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
 
-	scsi_build_sense_buffer(0, cmd->sense_buffer, sk, asc, ascq);
+	scsi_build_sense_buffer(d_sense, cmd->sense_buffer, sk, asc, ascq);
+}
+
+void ata_scsi_set_sense_information(struct ata_device *dev,
+				    struct scsi_cmnd *cmd,
+				    const struct ata_taskfile *tf)
+{
+	u64 information;
+
+	if (!cmd)
+		return;
+
+	information = ata_tf_read_block(tf, dev);
+	if (information == U64_MAX)
+		return;
+
+	scsi_set_sense_information(cmd->sense_buffer,
+				   SCSI_SENSE_BUFFERSIZE, information);
+}
+
+static void ata_scsi_set_invalid_field(struct ata_device *dev,
+				       struct scsi_cmnd *cmd, u16 field, u8 bit)
+{
+	ata_scsi_set_sense(dev, cmd, ILLEGAL_REQUEST, 0x24, 0x0);
+	/* "Invalid field in cbd" */
+	scsi_set_sense_field_pointer(cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE,
+				     field, bit, 1);
+}
+
+static void ata_scsi_set_invalid_parameter(struct ata_device *dev,
+					   struct scsi_cmnd *cmd, u16 field)
+{
+	/* "Invalid field in parameter list" */
+	ata_scsi_set_sense(dev, cmd, ILLEGAL_REQUEST, 0x26, 0x0);
+	scsi_set_sense_field_pointer(cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE,
+				     field, 0xff, 0);
 }
 
 static ssize_t
@@ -364,10 +405,10 @@ struct device_attribute *ata_common_sdev
 };
 EXPORT_SYMBOL_GPL(ata_common_sdev_attrs);
 
-static void ata_scsi_invalid_field(struct scsi_cmnd *cmd)
+static void ata_scsi_invalid_field(struct ata_device *dev,
+				   struct scsi_cmnd *cmd, u16 field)
 {
-	ata_scsi_set_sense(cmd, ILLEGAL_REQUEST, 0x24, 0x0);
-	/* "Invalid field in cbd" */
+	ata_scsi_set_invalid_field(dev, cmd, field, 0xff);
 	cmd->scsi_done(cmd);
 }
 
@@ -980,6 +1021,7 @@ static void ata_gen_passthru_sense(struc
 	unsigned char *sb = cmd->sense_buffer;
 	unsigned char *desc = sb + 8;
 	int verbose = qc->ap->ops->error_handler == NULL;
+	u8 sense_key, asc, ascq;
 
 	memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
 
@@ -992,47 +1034,71 @@ static void ata_gen_passthru_sense(struc
 	if (qc->err_mask ||
 	    tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) {
 		ata_to_sense_error(qc->ap->print_id, tf->command, tf->feature,
-				   &sb[1], &sb[2], &sb[3], verbose);
-		sb[1] &= 0x0f;
+				   &sense_key, &asc, &ascq, verbose);
+		ata_scsi_set_sense(qc->dev, cmd, sense_key, asc, ascq);
 	} else {
-		sb[1] = RECOVERED_ERROR;
-		sb[2] = 0;
-		sb[3] = 0x1D;
+		/*
+		 * ATA PASS-THROUGH INFORMATION AVAILABLE
+		 * Always in descriptor format sense.
+		 */
+		scsi_build_sense_buffer(1, cmd->sense_buffer,
+					RECOVERED_ERROR, 0, 0x1D);
 	}
 
-	/*
-	 * Sense data is current and format is descriptor.
-	 */
-	sb[0] = 0x72;
-
-	desc[0] = 0x09;
-
-	/* set length of additional sense data */
-	sb[7] = 14;
-	desc[1] = 12;
+	if ((cmd->sense_buffer[0] & 0x7f) >= 0x72) {
+		u8 len;
 
-	/*
-	 * Copy registers into sense buffer.
-	 */
-	desc[2] = 0x00;
-	desc[3] = tf->feature;	/* == error reg */
-	desc[5] = tf->nsect;
-	desc[7] = tf->lbal;
-	desc[9] = tf->lbam;
-	desc[11] = tf->lbah;
-	desc[12] = tf->device;
-	desc[13] = tf->command; /* == status reg */
+		/* descriptor format */
+		len = sb[7];
+		desc = (char *)scsi_sense_desc_find(sb, len + 8, 9);
+		if (!desc) {
+			if (SCSI_SENSE_BUFFERSIZE < len + 14)
+				return;
+			sb[7] = len + 14;
+			desc = sb + 8 + len;
+		}
+		desc[0] = 9;
+		desc[1] = 12;
+		/*
+		 * Copy registers into sense buffer.
+		 */
+		desc[2] = 0x00;
+		desc[3] = tf->feature;	/* == error reg */
+		desc[5] = tf->nsect;
+		desc[7] = tf->lbal;
+		desc[9] = tf->lbam;
+		desc[11] = tf->lbah;
+		desc[12] = tf->device;
+		desc[13] = tf->command; /* == status reg */
 
-	/*
-	 * Fill in Extend bit, and the high order bytes
-	 * if applicable.
-	 */
-	if (tf->flags & ATA_TFLAG_LBA48) {
-		desc[2] |= 0x01;
-		desc[4] = tf->hob_nsect;
-		desc[6] = tf->hob_lbal;
-		desc[8] = tf->hob_lbam;
-		desc[10] = tf->hob_lbah;
+		/*
+		 * Fill in Extend bit, and the high order bytes
+		 * if applicable.
+		 */
+		if (tf->flags & ATA_TFLAG_LBA48) {
+			desc[2] |= 0x01;
+			desc[4] = tf->hob_nsect;
+			desc[6] = tf->hob_lbal;
+			desc[8] = tf->hob_lbam;
+			desc[10] = tf->hob_lbah;
+		}
+	} else {
+		/* Fixed sense format */
+		desc[0] = tf->feature;
+		desc[1] = tf->command; /* status */
+		desc[2] = tf->device;
+		desc[3] = tf->nsect;
+		desc[0] = 0;
+		if (tf->flags & ATA_TFLAG_LBA48)  {
+			desc[8] |= 0x80;
+			if (tf->hob_nsect)
+				desc[8] |= 0x40;
+			if (tf->hob_lbal || tf->hob_lbam || tf->hob_lbah)
+				desc[8] |= 0x20;
+		}
+		desc[9] = tf->lbal;
+		desc[10] = tf->lbam;
+		desc[11] = tf->lbah;
 	}
 }
 
@@ -1052,41 +1118,41 @@ static void ata_gen_ata_sense(struct ata
 	struct scsi_cmnd *cmd = qc->scsicmd;
 	struct ata_taskfile *tf = &qc->result_tf;
 	unsigned char *sb = cmd->sense_buffer;
-	unsigned char *desc = sb + 8;
 	int verbose = qc->ap->ops->error_handler == NULL;
 	u64 block;
+	u8 sense_key, asc, ascq;
 
 	memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
 
 	cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
 
-	/* sense data is current and format is descriptor */
-	sb[0] = 0x72;
-
+	if (ata_dev_disabled(dev)) {
+		/* Device disabled after error recovery */
+		/* LOGICAL UNIT NOT READY, HARD RESET REQUIRED */
+		ata_scsi_set_sense(dev, cmd, NOT_READY, 0x04, 0x21);
+		return;
+	}
 	/* Use ata_to_sense_error() to map status register bits
 	 * onto sense key, asc & ascq.
 	 */
 	if (qc->err_mask ||
 	    tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) {
 		ata_to_sense_error(qc->ap->print_id, tf->command, tf->feature,
-				   &sb[1], &sb[2], &sb[3], verbose);
-		sb[1] &= 0x0f;
+				   &sense_key, &asc, &ascq, verbose);
+		ata_scsi_set_sense(dev, cmd, sense_key, asc, ascq);
+	} else {
+		/* Could not decode error */
+		ata_dev_warn(dev, "could not decode error status 0x%x err_mask 0x%x\n",
+			     tf->command, qc->err_mask);
+		ata_scsi_set_sense(dev, cmd, ABORTED_COMMAND, 0, 0);
+		return;
 	}
 
 	block = ata_tf_read_block(&qc->result_tf, dev);
+	if (block == U64_MAX)
+		return;
 
-	/* information sense data descriptor */
-	sb[7] = 12;
-	desc[0] = 0x00;
-	desc[1] = 10;
-
-	desc[2] |= 0x80;	/* valid */
-	desc[6] = block >> 40;
-	desc[7] = block >> 32;
-	desc[8] = block >> 24;
-	desc[9] = block >> 16;
-	desc[10] = block >> 8;
-	desc[11] = block;
+	scsi_set_sense_information(sb, SCSI_SENSE_BUFFERSIZE, block);
 }
 
 static void ata_scsi_sdev_config(struct scsi_device *sdev)
@@ -1109,7 +1175,7 @@ static void ata_scsi_sdev_config(struct
  *	@rq: request to be checked
  *
  *	ATAPI commands which transfer variable length data to host
- *	might overflow due to application error or hardare bug.  This
+ *	might overflow due to application error or hardware bug.  This
  *	function checks whether overflow should be drained and ignored
  *	for @request.
  *
@@ -1343,19 +1409,29 @@ static unsigned int ata_scsi_start_stop_
 	struct scsi_cmnd *scmd = qc->scsicmd;
 	struct ata_taskfile *tf = &qc->tf;
 	const u8 *cdb = scmd->cmnd;
+	u16 fp;
+	u8 bp = 0xff;
 
-	if (scmd->cmd_len < 5)
+	if (scmd->cmd_len < 5) {
+		fp = 4;
 		goto invalid_fld;
+	}
 
 	tf->flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;
 	tf->protocol = ATA_PROT_NODATA;
 	if (cdb[1] & 0x1) {
 		;	/* ignore IMMED bit, violates sat-r05 */
 	}
-	if (cdb[4] & 0x2)
+	if (cdb[4] & 0x2) {
+		fp = 4;
+		bp = 1;
 		goto invalid_fld;       /* LOEJ bit set not supported */
-	if (((cdb[4] >> 4) & 0xf) != 0)
+	}
+	if (((cdb[4] >> 4) & 0xf) != 0) {
+		fp = 4;
+		bp = 3;
 		goto invalid_fld;       /* power conditions not supported */
+	}
 
 	if (cdb[4] & 0x1) {
 		tf->nsect = 1;	/* 1 sector, lba=0 */
@@ -1401,8 +1477,7 @@ static unsigned int ata_scsi_start_stop_
 	return 0;
 
  invalid_fld:
-	ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x24, 0x0);
-	/* "Invalid field in cbd" */
+	ata_scsi_set_invalid_field(qc->dev, scmd, fp, bp);
 	return 1;
  skip:
 	scmd->result = SAM_STAT_GOOD;
@@ -1553,20 +1628,27 @@ static unsigned int ata_scsi_verify_xlat
 	const u8 *cdb = scmd->cmnd;
 	u64 block;
 	u32 n_block;
+	u16 fp;
 
 	tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
 	tf->protocol = ATA_PROT_NODATA;
 
 	if (cdb[0] == VERIFY) {
-		if (scmd->cmd_len < 10)
+		if (scmd->cmd_len < 10) {
+			fp = 9;
 			goto invalid_fld;
+		}
 		scsi_10_lba_len(cdb, &block, &n_block);
 	} else if (cdb[0] == VERIFY_16) {
-		if (scmd->cmd_len < 16)
+		if (scmd->cmd_len < 16) {
+			fp = 15;
 			goto invalid_fld;
+		}
 		scsi_16_lba_len(cdb, &block, &n_block);
-	} else
+	} else {
+		fp = 0;
 		goto invalid_fld;
+	}
 
 	if (!n_block)
 		goto nothing_to_do;
@@ -1640,12 +1722,11 @@ static unsigned int ata_scsi_verify_xlat
 	return 0;
 
 invalid_fld:
-	ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x24, 0x0);
-	/* "Invalid field in cbd" */
+	ata_scsi_set_invalid_field(qc->dev, scmd, fp, 0xff);
 	return 1;
 
 out_of_range:
-	ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x21, 0x0);
+	ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x21, 0x0);
 	/* "Logical Block Address out of range" */
 	return 1;
 
@@ -1680,6 +1761,7 @@ static unsigned int ata_scsi_rw_xlat(str
 	u64 block;
 	u32 n_block;
 	int rc;
+	u16 fp = 0;
 
 	if (cdb[0] == WRITE_10 || cdb[0] == WRITE_6 || cdb[0] == WRITE_16)
 		tf_flags |= ATA_TFLAG_WRITE;
@@ -1688,16 +1770,20 @@ static unsigned int ata_scsi_rw_xlat(str
 	switch (cdb[0]) {
 	case READ_10:
 	case WRITE_10:
-		if (unlikely(scmd->cmd_len < 10))
+		if (unlikely(scmd->cmd_len < 10)) {
+			fp = 9;
 			goto invalid_fld;
+		}
 		scsi_10_lba_len(cdb, &block, &n_block);
 		if (cdb[1] & (1 << 3))
 			tf_flags |= ATA_TFLAG_FUA;
 		break;
 	case READ_6:
 	case WRITE_6:
-		if (unlikely(scmd->cmd_len < 6))
+		if (unlikely(scmd->cmd_len < 6)) {
+			fp = 5;
 			goto invalid_fld;
+		}
 		scsi_6_lba_len(cdb, &block, &n_block);
 
 		/* for 6-byte r/w commands, transfer length 0
@@ -1708,14 +1794,17 @@ static unsigned int ata_scsi_rw_xlat(str
 		break;
 	case READ_16:
 	case WRITE_16:
-		if (unlikely(scmd->cmd_len < 16))
+		if (unlikely(scmd->cmd_len < 16)) {
+			fp = 15;
 			goto invalid_fld;
+		}
 		scsi_16_lba_len(cdb, &block, &n_block);
 		if (cdb[1] & (1 << 3))
 			tf_flags |= ATA_TFLAG_FUA;
 		break;
 	default:
 		DPRINTK("no-byte command\n");
+		fp = 0;
 		goto invalid_fld;
 	}
 
@@ -1742,12 +1831,11 @@ static unsigned int ata_scsi_rw_xlat(str
 		goto out_of_range;
 	/* treat all other errors as -EINVAL, fall through */
 invalid_fld:
-	ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x24, 0x0);
-	/* "Invalid field in cbd" */
+	ata_scsi_set_invalid_field(qc->dev, scmd, fp, 0xff);
 	return 1;
 
 out_of_range:
-	ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x21, 0x0);
+	ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x21, 0x0);
 	/* "Logical Block Address out of range" */
 	return 1;
 
@@ -1784,6 +1872,8 @@ static void ata_scsi_qc_complete(struct
 	if (((cdb[0] == ATA_16) || (cdb[0] == ATA_12)) &&
 	    ((cdb[2] & 0x20) || need_sense))
 		ata_gen_passthru_sense(qc);
+	else if (qc->flags & ATA_QCFLAG_SENSE_VALID)
+		cmd->result = SAM_STAT_CHECK_CONDITION;
 	else if (need_sense)
 		ata_gen_ata_sense(qc);
 	else
@@ -1992,14 +2082,14 @@ static unsigned int ata_scsiop_inq_std(s
 		0x00,
 		0xA0,	/* SAM-5 (no version claimed) */
 
-		0x04,
-		0xC0,	/* SBC-3 (no version claimed) */
+		0x06,
+		0x00,	/* SBC-4 (no version claimed) */
 
-		0x04,
-		0x60,	/* SPC-4 (no version claimed) */
+		0x05,
+		0xC0,	/* SPC-5 (no version claimed) */
 
 		0x60,
-		0x20,   /* ZBC (no version claimed) */
+		0x24,   /* ZBC r05 */
 	};
 
 	u8 hdr[] = {
@@ -2019,10 +2109,8 @@ static unsigned int ata_scsiop_inq_std(s
 	    (args->dev->link->ap->pflags & ATA_PFLAG_EXTERNAL))
 		hdr[1] |= (1 << 7);
 
-	if (args->dev->class == ATA_DEV_ZAC) {
+	if (args->dev->class == ATA_DEV_ZAC)
 		hdr[0] = TYPE_ZBC;
-		hdr[2] = 0x6; /* ZBC is defined in SPC-4 */
-	}
 
 	memcpy(rbuf, hdr, sizeof(hdr));
 	memcpy(&rbuf[8], "ATA     ", 8);
@@ -2036,7 +2124,7 @@ static unsigned int ata_scsiop_inq_std(s
 	if (rbuf[32] == 0 || rbuf[32] == ' ')
 		memcpy(&rbuf[32], "n/a ", 4);
 
-	if (args->dev->class == ATA_DEV_ZAC)
+	if (ata_id_zoned_cap(args->id) || args->dev->class == ATA_DEV_ZAC)
 		memcpy(rbuf + 58, versions_zbc, sizeof(versions_zbc));
 	else
 		memcpy(rbuf + 58, versions, sizeof(versions));
@@ -2056,6 +2144,7 @@ static unsigned int ata_scsiop_inq_std(s
  */
 static unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf)
 {
+	int num_pages;
 	const u8 pages[] = {
 		0x00,	/* page 0x00, this page */
 		0x80,	/* page 0x80, unit serial no page */
@@ -2064,10 +2153,14 @@ static unsigned int ata_scsiop_inq_00(st
 		0xb0,	/* page 0xb0, block limits page */
 		0xb1,	/* page 0xb1, block device characteristics page */
 		0xb2,	/* page 0xb2, thin provisioning page */
+		0xb6,	/* page 0xb6, zoned block device characteristics */
 	};
 
-	rbuf[3] = sizeof(pages);	/* number of supported VPD pages */
-	memcpy(rbuf + 4, pages, sizeof(pages));
+	num_pages = sizeof(pages);
+	if (!(args->dev->flags & ATA_DFLAG_ZAC))
+		num_pages--;
+	rbuf[3] = num_pages;	/* number of supported VPD pages */
+	memcpy(rbuf + 4, pages, num_pages);
 	return 0;
 }
 
@@ -2232,12 +2325,15 @@ static unsigned int ata_scsiop_inq_b1(st
 {
 	int form_factor = ata_id_form_factor(args->id);
 	int media_rotation_rate = ata_id_rotation_rate(args->id);
+	u8 zoned = ata_id_zoned_cap(args->id);
 
 	rbuf[1] = 0xb1;
 	rbuf[3] = 0x3c;
 	rbuf[4] = media_rotation_rate >> 8;
 	rbuf[5] = media_rotation_rate;
 	rbuf[7] = form_factor;
+	if (zoned)
+		rbuf[8] = (zoned << 4);
 
 	return 0;
 }
@@ -2252,6 +2348,26 @@ static unsigned int ata_scsiop_inq_b2(st
 	return 0;
 }
 
+static unsigned int ata_scsiop_inq_b6(struct ata_scsi_args *args, u8 *rbuf)
+{
+	/*
+	 * zbc-r05 SCSI Zoned Block device characteristics VPD page
+	 */
+	rbuf[1] = 0xb6;
+	rbuf[3] = 0x3C;
+
+	/*
+	 * URSWRZ bit is only meaningful for host-managed ZAC drives
+	 */
+	if (args->dev->zac_zoned_cap & 1)
+		rbuf[4] |= 1;
+	put_unaligned_be32(args->dev->zac_zones_optimal_open, &rbuf[8]);
+	put_unaligned_be32(args->dev->zac_zones_optimal_nonseq, &rbuf[12]);
+	put_unaligned_be32(args->dev->zac_zones_max_open, &rbuf[16]);
+
+	return 0;
+}
+
 /**
  *	ata_scsiop_noop - Command handler that simply returns success.
  *	@args: device IDENTIFY data / SCSI command of interest.
@@ -2317,6 +2433,7 @@ static unsigned int ata_msense_caching(u
 
 /**
  *	ata_msense_ctl_mode - Simulate MODE SENSE control mode page
+ *	@dev: ATA device of interest
  *	@buf: output buffer
  *	@changeable: whether changeable parameters are requested
  *
@@ -2325,9 +2442,12 @@ static unsigned int ata_msense_caching(u
  *	LOCKING:
  *	None.
  */
-static unsigned int ata_msense_ctl_mode(u8 *buf, bool changeable)
+static unsigned int ata_msense_ctl_mode(struct ata_device *dev, u8 *buf,
+					bool changeable)
 {
 	modecpy(buf, def_control_mpage, sizeof(def_control_mpage), changeable);
+	if (changeable && (dev->flags & ATA_DFLAG_D_SENSE))
+		buf[2] |= (1 << 2);	/* Descriptor sense requested */
 	return sizeof(def_control_mpage);
 }
 
@@ -2395,7 +2515,8 @@ static unsigned int ata_scsiop_mode_sens
 	};
 	u8 pg, spg;
 	unsigned int ebd, page_control, six_byte;
-	u8 dpofua;
+	u8 dpofua, bp = 0xff;
+	u16 fp;
 
 	VPRINTK("ENTER\n");
 
@@ -2414,6 +2535,8 @@ static unsigned int ata_scsiop_mode_sens
 	case 3: /* saved */
 		goto saving_not_supp;
 	default:
+		fp = 2;
+		bp = 6;
 		goto invalid_fld;
 	}
 
@@ -2428,8 +2551,10 @@ static unsigned int ata_scsiop_mode_sens
 	 * No mode subpages supported (yet) but asking for _all_
 	 * subpages may be valid
 	 */
-	if (spg && (spg != ALL_SUB_MPAGES))
+	if (spg && (spg != ALL_SUB_MPAGES)) {
+		fp = 3;
 		goto invalid_fld;
+	}
 
 	switch(pg) {
 	case RW_RECOVERY_MPAGE:
@@ -2441,16 +2566,17 @@ static unsigned int ata_scsiop_mode_sens
 		break;
 
 	case CONTROL_MPAGE:
-		p += ata_msense_ctl_mode(p, page_control == 1);
+		p += ata_msense_ctl_mode(args->dev, p, page_control == 1);
 		break;
 
 	case ALL_MPAGES:
 		p += ata_msense_rw_recovery(p, page_control == 1);
 		p += ata_msense_caching(args->id, p, page_control == 1);
-		p += ata_msense_ctl_mode(p, page_control == 1);
+		p += ata_msense_ctl_mode(args->dev, p, page_control == 1);
 		break;
 
 	default:		/* invalid page code */
+		fp = 2;
 		goto invalid_fld;
 	}
 
@@ -2480,12 +2606,11 @@ static unsigned int ata_scsiop_mode_sens
 	return 0;
 
 invalid_fld:
-	ata_scsi_set_sense(args->cmd, ILLEGAL_REQUEST, 0x24, 0x0);
-	/* "Invalid field in cbd" */
+	ata_scsi_set_invalid_field(dev, args->cmd, fp, bp);
 	return 1;
 
 saving_not_supp:
-	ata_scsi_set_sense(args->cmd, ILLEGAL_REQUEST, 0x39, 0x0);
+	ata_scsi_set_sense(dev, args->cmd, ILLEGAL_REQUEST, 0x39, 0x0);
 	 /* "Saving parameters not supported" */
 	return 1;
 }
@@ -2561,6 +2686,9 @@ static unsigned int ata_scsiop_read_cap(
 				rbuf[14] |= 0x40; /* LBPRZ */
 			}
 		}
+		if (ata_id_zoned_cap(args->id) ||
+		    args->dev->class == ATA_DEV_ZAC)
+			rbuf[12] = (1 << 4); /* RC_BASIS */
 	}
 	return 0;
 }
@@ -2942,9 +3070,12 @@ static unsigned int ata_scsi_pass_thru(s
 	struct scsi_cmnd *scmd = qc->scsicmd;
 	struct ata_device *dev = qc->dev;
 	const u8 *cdb = scmd->cmnd;
+	u16 fp;
 
-	if ((tf->protocol = ata_scsi_map_proto(cdb[1])) == ATA_PROT_UNKNOWN)
+	if ((tf->protocol = ata_scsi_map_proto(cdb[1])) == ATA_PROT_UNKNOWN) {
+		fp = 1;
 		goto invalid_fld;
+	}
 
 	/* enable LBA */
 	tf->flags |= ATA_TFLAG_LBA;
@@ -3008,8 +3139,10 @@ static unsigned int ata_scsi_pass_thru(s
 	case ATA_CMD_READ_LONG_ONCE:
 	case ATA_CMD_WRITE_LONG:
 	case ATA_CMD_WRITE_LONG_ONCE:
-		if (tf->protocol != ATA_PROT_PIO || tf->nsect != 1)
+		if (tf->protocol != ATA_PROT_PIO || tf->nsect != 1) {
+			fp = 1;
 			goto invalid_fld;
+		}
 		qc->sect_size = scsi_bufflen(scmd);
 		break;
 
@@ -3072,12 +3205,16 @@ static unsigned int ata_scsi_pass_thru(s
 	ata_qc_set_pc_nbytes(qc);
 
 	/* We may not issue DMA commands if no DMA mode is set */
-	if (tf->protocol == ATA_PROT_DMA && dev->dma_mode == 0)
+	if (tf->protocol == ATA_PROT_DMA && dev->dma_mode == 0) {
+		fp = 1;
 		goto invalid_fld;
+	}
 
 	/* sanity check for pio multi commands */
-	if ((cdb[1] & 0xe0) && !is_multi_taskfile(tf))
+	if ((cdb[1] & 0xe0) && !is_multi_taskfile(tf)) {
+		fp = 1;
 		goto invalid_fld;
+	}
 
 	if (is_multi_taskfile(tf)) {
 		unsigned int multi_count = 1 << (cdb[1] >> 5);
@@ -3098,8 +3235,10 @@ static unsigned int ata_scsi_pass_thru(s
 	 * ->set_dmamode(), and ->post_set_mode() hooks).
 	 */
 	if (tf->command == ATA_CMD_SET_FEATURES &&
-	    tf->feature == SETFEATURES_XFER)
+	    tf->feature == SETFEATURES_XFER) {
+		fp = (cdb[0] == ATA_16) ? 4 : 3;
 		goto invalid_fld;
+	}
 
 	/*
 	 * Filter TPM commands by default. These provide an
@@ -3116,14 +3255,15 @@ static unsigned int ata_scsi_pass_thru(s
 	 * so that we comply with the TC consortium stated goal that the user
 	 * can turn off TC features of their system.
 	 */
-	if (tf->command >= 0x5C && tf->command <= 0x5F && !libata_allow_tpm)
+	if (tf->command >= 0x5C && tf->command <= 0x5F && !libata_allow_tpm) {
+		fp = (cdb[0] == ATA_16) ? 14 : 9;
 		goto invalid_fld;
+	}
 
 	return 0;
 
  invalid_fld:
-	ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x24, 0x00);
-	/* "Invalid field in cdb" */
+	ata_scsi_set_invalid_field(dev, scmd, fp, 0xff);
 	return 1;
 }
 
@@ -3137,25 +3277,32 @@ static unsigned int ata_scsi_write_same_
 	u32 n_block;
 	u32 size;
 	void *buf;
+	u16 fp;
+	u8 bp = 0xff;
 
 	/* we may not issue DMA commands if no DMA mode is set */
 	if (unlikely(!dev->dma_mode))
-		goto invalid_fld;
+		goto invalid_opcode;
 
-	if (unlikely(scmd->cmd_len < 16))
+	if (unlikely(scmd->cmd_len < 16)) {
+		fp = 15;
 		goto invalid_fld;
+	}
 	scsi_16_lba_len(cdb, &block, &n_block);
 
 	/* for now we only support WRITE SAME with the unmap bit set */
-	if (unlikely(!(cdb[1] & 0x8)))
+	if (unlikely(!(cdb[1] & 0x8))) {
+		fp = 1;
+		bp = 3;
 		goto invalid_fld;
+	}
 
 	/*
 	 * WRITE SAME always has a sector sized buffer as payload, this
 	 * should never be a multiple entry S/G list.
 	 */
 	if (!scsi_sg_count(scmd))
-		goto invalid_fld;
+		goto invalid_param_len;
 
 	buf = page_address(sg_page(scsi_sglist(scmd)));
 	size = ata_set_lba_range_entries(buf, 512, block, n_block);
@@ -3186,9 +3333,242 @@ static unsigned int ata_scsi_write_same_
 
 	return 0;
 
+invalid_fld:
+	ata_scsi_set_invalid_field(dev, scmd, fp, bp);
+	return 1;
+invalid_param_len:
+	/* "Parameter list length error" */
+	ata_scsi_set_sense(dev, scmd, ILLEGAL_REQUEST, 0x1a, 0x0);
+	return 1;
+invalid_opcode:
+	/* "Invalid command operation code" */
+	ata_scsi_set_sense(dev, scmd, ILLEGAL_REQUEST, 0x20, 0x0);
+	return 1;
+}
+
+/**
+ *	ata_scsi_report_zones_complete - convert ATA output
+ *	@qc: command structure returning the data
+ *
+ *	Convert T-13 little-endian field representation into
+ *	T-10 big-endian field representation.
+ *	What a mess.
+ */
+static void ata_scsi_report_zones_complete(struct ata_queued_cmd *qc)
+{
+	struct scsi_cmnd *scmd = qc->scsicmd;
+	struct sg_mapping_iter miter;
+	unsigned long flags;
+	unsigned int bytes = 0;
+
+	sg_miter_start(&miter, scsi_sglist(scmd), scsi_sg_count(scmd),
+		       SG_MITER_TO_SG | SG_MITER_ATOMIC);
+
+	local_irq_save(flags);
+	while (sg_miter_next(&miter)) {
+		unsigned int offset = 0;
+
+		if (bytes == 0) {
+			char *hdr;
+			u32 list_length;
+			u64 max_lba, opt_lba;
+			u16 same;
+
+			/* Swizzle header */
+			hdr = miter.addr;
+			list_length = get_unaligned_le32(&hdr[0]);
+			same = get_unaligned_le16(&hdr[4]);
+			max_lba = get_unaligned_le64(&hdr[8]);
+			opt_lba = get_unaligned_le64(&hdr[16]);
+			put_unaligned_be32(list_length, &hdr[0]);
+			hdr[4] = same & 0xf;
+			put_unaligned_be64(max_lba, &hdr[8]);
+			put_unaligned_be64(opt_lba, &hdr[16]);
+			offset += 64;
+			bytes += 64;
+		}
+		while (offset < miter.length) {
+			char *rec;
+			u8 cond, type, non_seq, reset;
+			u64 size, start, wp;
+
+			/* Swizzle zone descriptor */
+			rec = miter.addr + offset;
+			type = rec[0] & 0xf;
+			cond = (rec[1] >> 4) & 0xf;
+			non_seq = (rec[1] & 2);
+			reset = (rec[1] & 1);
+			size = get_unaligned_le64(&rec[8]);
+			start = get_unaligned_le64(&rec[16]);
+			wp = get_unaligned_le64(&rec[24]);
+			rec[0] = type;
+			rec[1] = (cond << 4) | non_seq | reset;
+			put_unaligned_be64(size, &rec[8]);
+			put_unaligned_be64(start, &rec[16]);
+			put_unaligned_be64(wp, &rec[24]);
+			WARN_ON(offset + 64 > miter.length);
+			offset += 64;
+			bytes += 64;
+		}
+	}
+	sg_miter_stop(&miter);
+	local_irq_restore(flags);
+
+	ata_scsi_qc_complete(qc);
+}
+
+static unsigned int ata_scsi_zbc_in_xlat(struct ata_queued_cmd *qc)
+{
+	struct ata_taskfile *tf = &qc->tf;
+	struct scsi_cmnd *scmd = qc->scsicmd;
+	const u8 *cdb = scmd->cmnd;
+	u16 sect, fp = (u16)-1;
+	u8 sa, options, bp = 0xff;
+	u64 block;
+	u32 n_block;
+
+	if (unlikely(scmd->cmd_len < 16)) {
+		ata_dev_warn(qc->dev, "invalid cdb length %d\n",
+			     scmd->cmd_len);
+		fp = 15;
+		goto invalid_fld;
+	}
+	scsi_16_lba_len(cdb, &block, &n_block);
+	if (n_block != scsi_bufflen(scmd)) {
+		ata_dev_warn(qc->dev, "non-matching transfer count (%d/%d)\n",
+			     n_block, scsi_bufflen(scmd));
+		goto invalid_param_len;
+	}
+	sa = cdb[1] & 0x1f;
+	if (sa != ZI_REPORT_ZONES) {
+		ata_dev_warn(qc->dev, "invalid service action %d\n", sa);
+		fp = 1;
+		goto invalid_fld;
+	}
+	/*
+	 * ZAC allows only for transfers in 512 byte blocks,
+	 * and uses a 16 bit value for the transfer count.
+	 */
+	if ((n_block / 512) > 0xffff || n_block < 512 || (n_block % 512)) {
+		ata_dev_warn(qc->dev, "invalid transfer count %d\n", n_block);
+		goto invalid_param_len;
+	}
+	sect = n_block / 512;
+	options = cdb[14];
+
+	if (ata_ncq_enabled(qc->dev) &&
+	    ata_fpdma_zac_mgmt_in_supported(qc->dev)) {
+		tf->protocol = ATA_PROT_NCQ;
+		tf->command = ATA_CMD_FPDMA_RECV;
+		tf->hob_nsect = ATA_SUBCMD_FPDMA_RECV_ZAC_MGMT_IN & 0x1f;
+		tf->nsect = qc->tag << 3;
+		tf->feature = sect & 0xff;
+		tf->hob_feature = (sect >> 8) & 0xff;
+		tf->auxiliary = ATA_SUBCMD_ZAC_MGMT_IN_REPORT_ZONES;
+	} else {
+		tf->command = ATA_CMD_ZAC_MGMT_IN;
+		tf->feature = ATA_SUBCMD_ZAC_MGMT_IN_REPORT_ZONES;
+		tf->protocol = ATA_PROT_DMA;
+		tf->hob_feature = options;
+		tf->hob_nsect = (sect >> 8) & 0xff;
+		tf->nsect = sect & 0xff;
+	}
+	tf->device = ATA_LBA;
+	tf->lbah = (block >> 16) & 0xff;
+	tf->lbam = (block >> 8) & 0xff;
+	tf->lbal = block & 0xff;
+	tf->hob_lbah = (block >> 40) & 0xff;
+	tf->hob_lbam = (block >> 32) & 0xff;
+	tf->hob_lbal = (block >> 24) & 0xff;
+
+	tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE | ATA_TFLAG_LBA48;
+	qc->flags |= ATA_QCFLAG_RESULT_TF;
+
+	ata_qc_set_pc_nbytes(qc);
+
+	qc->complete_fn = ata_scsi_report_zones_complete;
+
+	return 0;
+
+invalid_fld:
+	ata_scsi_set_invalid_field(qc->dev, scmd, fp, bp);
+	return 1;
+
+invalid_param_len:
+	/* "Parameter list length error" */
+	ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x1a, 0x0);
+	return 1;
+}
+
+static unsigned int ata_scsi_zbc_out_xlat(struct ata_queued_cmd *qc)
+{
+	struct ata_taskfile *tf = &qc->tf;
+	struct scsi_cmnd *scmd = qc->scsicmd;
+	struct ata_device *dev = qc->dev;
+	const u8 *cdb = scmd->cmnd;
+	u8 reset_all, sa;
+	u64 block;
+	u32 n_block;
+	u16 fp = (u16)-1;
+
+	if (unlikely(scmd->cmd_len < 16)) {
+		fp = 15;
+		goto invalid_fld;
+	}
+
+	sa = cdb[1] & 0x1f;
+	if ((sa != ZO_CLOSE_ZONE) && (sa != ZO_FINISH_ZONE) &&
+	    (sa != ZO_OPEN_ZONE) && (sa != ZO_RESET_WRITE_POINTER)) {
+		fp = 1;
+		goto invalid_fld;
+	}
+
+	scsi_16_lba_len(cdb, &block, &n_block);
+	if (n_block) {
+		/*
+		 * ZAC MANAGEMENT OUT doesn't define any length
+		 */
+		goto invalid_param_len;
+	}
+	if (block > dev->n_sectors)
+		goto out_of_range;
+
+	reset_all = cdb[14] & 0x1;
+
+	if (ata_ncq_enabled(qc->dev) &&
+	    ata_fpdma_zac_mgmt_out_supported(qc->dev)) {
+		tf->protocol = ATA_PROT_NCQ;
+		tf->command = ATA_CMD_NCQ_NON_DATA;
+		tf->hob_nsect = ATA_SUBCMD_NCQ_NON_DATA_ZAC_MGMT_OUT;
+		tf->nsect = qc->tag << 3;
+		tf->auxiliary = sa | (reset_all & 0x1) << 8;
+	} else {
+		tf->protocol = ATA_PROT_NODATA;
+		tf->command = ATA_CMD_ZAC_MGMT_OUT;
+		tf->feature = sa;
+		tf->hob_feature = reset_all & 0x1;
+	}
+	tf->lbah = (block >> 16) & 0xff;
+	tf->lbam = (block >> 8) & 0xff;
+	tf->lbal = block & 0xff;
+	tf->hob_lbah = (block >> 40) & 0xff;
+	tf->hob_lbam = (block >> 32) & 0xff;
+	tf->hob_lbal = (block >> 24) & 0xff;
+	tf->device = ATA_LBA;
+	tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE | ATA_TFLAG_LBA48;
+
+	return 0;
+
  invalid_fld:
-	ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x24, 0x00);
-	/* "Invalid field in cdb" */
+	ata_scsi_set_invalid_field(qc->dev, scmd, fp, 0xff);
+	return 1;
+ out_of_range:
+	/* "Logical Block Address out of range" */
+	ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x21, 0x00);
+	return 1;
+invalid_param_len:
+	/* "Parameter list length error" */
+	ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x1a, 0x0);
 	return 1;
 }
 
@@ -3197,6 +3577,7 @@ static unsigned int ata_scsi_write_same_
  *	@qc: Storage for translated ATA taskfile
  *	@buf: input buffer
  *	@len: number of valid bytes in the input buffer
+ *	@fp: out parameter for the failed field on error
  *
  *	Prepare a taskfile to modify caching information for the device.
  *
@@ -3204,20 +3585,26 @@ static unsigned int ata_scsi_write_same_
  *	None.
  */
 static int ata_mselect_caching(struct ata_queued_cmd *qc,
-			       const u8 *buf, int len)
+			       const u8 *buf, int len, u16 *fp)
 {
 	struct ata_taskfile *tf = &qc->tf;
 	struct ata_device *dev = qc->dev;
 	char mpage[CACHE_MPAGE_LEN];
 	u8 wce;
+	int i;
 
 	/*
 	 * The first two bytes of def_cache_mpage are a header, so offsets
 	 * in mpage are off by 2 compared to buf.  Same for len.
 	 */
 
-	if (len != CACHE_MPAGE_LEN - 2)
+	if (len != CACHE_MPAGE_LEN - 2) {
+		if (len < CACHE_MPAGE_LEN - 2)
+			*fp = len;
+		else
+			*fp = CACHE_MPAGE_LEN - 2;
 		return -EINVAL;
+	}
 
 	wce = buf[0] & (1 << 2);
 
@@ -3225,10 +3612,14 @@ static int ata_mselect_caching(struct at
 	 * Check that read-only bits are not modified.
 	 */
 	ata_msense_caching(dev->id, mpage, false);
-	mpage[2] &= ~(1 << 2);
-	mpage[2] |= wce;
-	if (memcmp(mpage + 2, buf, CACHE_MPAGE_LEN - 2) != 0)
-		return -EINVAL;
+	for (i = 0; i < CACHE_MPAGE_LEN - 2; i++) {
+		if (i == 0)
+			continue;
+		if (mpage[i + 2] != buf[i]) {
+			*fp = i;
+			return -EINVAL;
+		}
+	}
 
 	tf->flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;
 	tf->protocol = ATA_PROT_NODATA;
@@ -3239,6 +3630,62 @@ static int ata_mselect_caching(struct at
 }
 
 /**
+ *	ata_mselect_control - Simulate MODE SELECT for control page
+ *	@qc: Storage for translated ATA taskfile
+ *	@buf: input buffer
+ *	@len: number of valid bytes in the input buffer
+ *	@fp: out parameter for the failed field on error
+ *
+ *	Prepare a taskfile to modify caching information for the device.
+ *
+ *	LOCKING:
+ *	None.
+ */
+static int ata_mselect_control(struct ata_queued_cmd *qc,
+			       const u8 *buf, int len, u16 *fp)
+{
+	struct ata_device *dev = qc->dev;
+	char mpage[CONTROL_MPAGE_LEN];
+	u8 d_sense;
+	int i;
+
+	/*
+	 * The first two bytes of def_control_mpage are a header, so offsets
+	 * in mpage are off by 2 compared to buf.  Same for len.
+	 */
+
+	if (len != CONTROL_MPAGE_LEN - 2) {
+		if (len < CONTROL_MPAGE_LEN - 2)
+			*fp = len;
+		else
+			*fp = CONTROL_MPAGE_LEN - 2;
+		return -EINVAL;
+	}
+
+	d_sense = buf[0] & (1 << 2);
+
+	/*
+	 * Check that read-only bits are not modified.
+	 */
+	ata_msense_ctl_mode(dev, mpage, false);
+	for (i = 0; i < CONTROL_MPAGE_LEN - 2; i++) {
+		if (i == 0)
+			continue;
+		if (mpage[2 + i] != buf[i]) {
+			*fp = i;
+			return -EINVAL;
+		}
+	}
+	if (d_sense & (1 << 2))
+		dev->flags |= ATA_DFLAG_D_SENSE;
+	else
+		dev->flags &= ~ATA_DFLAG_D_SENSE;
+	qc->scsicmd->result = SAM_STAT_GOOD;
+	qc->scsicmd->scsi_done(qc->scsicmd);
+	return 0;
+}
+
+/**
  *	ata_scsiop_mode_select - Simulate MODE SELECT 6, 10 commands
  *	@qc: Storage for translated ATA taskfile
  *
@@ -3257,27 +3704,36 @@ static unsigned int ata_scsi_mode_select
 	u8 pg, spg;
 	unsigned six_byte, pg_len, hdr_len, bd_len;
 	int len;
+	u16 fp = (u16)-1;
+	u8 bp = 0xff;
 
 	VPRINTK("ENTER\n");
 
 	six_byte = (cdb[0] == MODE_SELECT);
 	if (six_byte) {
-		if (scmd->cmd_len < 5)
+		if (scmd->cmd_len < 5) {
+			fp = 4;
 			goto invalid_fld;
+		}
 
 		len = cdb[4];
 		hdr_len = 4;
 	} else {
-		if (scmd->cmd_len < 9)
+		if (scmd->cmd_len < 9) {
+			fp = 8;
 			goto invalid_fld;
+		}
 
 		len = (cdb[7] << 8) + cdb[8];
 		hdr_len = 8;
 	}
 
 	/* We only support PF=1, SP=0.  */
-	if ((cdb[1] & 0x11) != 0x10)
+	if ((cdb[1] & 0x11) != 0x10) {
+		fp = 1;
+		bp = (cdb[1] & 0x01) ? 1 : 5;
 		goto invalid_fld;
+	}
 
 	/* Test early for possible overrun.  */
 	if (!scsi_sg_count(scmd) || scsi_sglist(scmd)->length < len)
@@ -3298,8 +3754,11 @@ static unsigned int ata_scsi_mode_select
 	p += hdr_len;
 	if (len < bd_len)
 		goto invalid_param_len;
-	if (bd_len != 0 && bd_len != 8)
+	if (bd_len != 0 && bd_len != 8) {
+		fp = (six_byte) ? 3 : 6;
+		fp += bd_len + hdr_len;
 		goto invalid_param;
+	}
 
 	len -= bd_len;
 	p += bd_len;
@@ -3330,18 +3789,29 @@ static unsigned int ata_scsi_mode_select
 	 * No mode subpages supported (yet) but asking for _all_
 	 * subpages may be valid
 	 */
-	if (spg && (spg != ALL_SUB_MPAGES))
+	if (spg && (spg != ALL_SUB_MPAGES)) {
+		fp = (p[0] & 0x40) ? 1 : 0;
+		fp += hdr_len + bd_len;
 		goto invalid_param;
+	}
 	if (pg_len > len)
 		goto invalid_param_len;
 
 	switch (pg) {
 	case CACHE_MPAGE:
-		if (ata_mselect_caching(qc, p, pg_len) < 0)
+		if (ata_mselect_caching(qc, p, pg_len, &fp) < 0) {
+			fp += hdr_len + bd_len;
 			goto invalid_param;
+		}
+		break;
+	case CONTROL_MPAGE:
+		if (ata_mselect_control(qc, p, pg_len, &fp) < 0) {
+			fp += hdr_len + bd_len;
+			goto invalid_param;
+		}
 		break;
-
 	default:		/* invalid page code */
+		fp = bd_len + hdr_len;
 		goto invalid_param;
 	}
 
@@ -3355,18 +3825,16 @@ static unsigned int ata_scsi_mode_select
 	return 0;
 
  invalid_fld:
-	/* "Invalid field in CDB" */
-	ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x24, 0x0);
+	ata_scsi_set_invalid_field(qc->dev, scmd, fp, bp);
 	return 1;
 
  invalid_param:
-	/* "Invalid field in parameter list" */
-	ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x26, 0x0);
+	ata_scsi_set_invalid_parameter(qc->dev, scmd, fp);
 	return 1;
 
  invalid_param_len:
 	/* "Parameter list length error" */
-	ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x1a, 0x0);
+	ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x1a, 0x0);
 	return 1;
 
  skip:
@@ -3419,6 +3887,12 @@ static inline ata_xlat_func_t ata_get_xl
 		return ata_scsi_mode_select_xlat;
 		break;
 
+	case ZBC_IN:
+		return ata_scsi_zbc_in_xlat;
+
+	case ZBC_OUT:
+		return ata_scsi_zbc_out_xlat;
+
 	case START_STOP:
 		return ata_scsi_start_stop_xlat;
 	}
@@ -3439,14 +3913,11 @@ static inline void ata_scsi_dump_cdb(str
 {
 #ifdef ATA_DEBUG
 	struct scsi_device *scsidev = cmd->device;
-	u8 *scsicmd = cmd->cmnd;
 
-	DPRINTK("CDB (%u:%d,%d,%d) %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+	DPRINTK("CDB (%u:%d,%d,%d) %9ph\n",
 		ap->print_id,
 		scsidev->channel, scsidev->id, scsidev->lun,
-		scsicmd[0], scsicmd[1], scsicmd[2], scsicmd[3],
-		scsicmd[4], scsicmd[5], scsicmd[6], scsicmd[7],
-		scsicmd[8]);
+		cmd->cmnd);
 #endif
 }
 
@@ -3570,12 +4041,12 @@ void ata_scsi_simulate(struct ata_device
 	switch(scsicmd[0]) {
 	/* TODO: worth improving? */
 	case FORMAT_UNIT:
-		ata_scsi_invalid_field(cmd);
+		ata_scsi_invalid_field(dev, cmd, 0);
 		break;
 
 	case INQUIRY:
-		if (scsicmd[1] & 2)	           /* is CmdDt set?  */
-			ata_scsi_invalid_field(cmd);
+		if (scsicmd[1] & 2)		   /* is CmdDt set?  */
+		    ata_scsi_invalid_field(dev, cmd, 1);
 		else if ((scsicmd[1] & 1) == 0)    /* is EVPD clear? */
 			ata_scsi_rbuf_fill(&args, ata_scsiop_inq_std);
 		else switch (scsicmd[2]) {
@@ -3600,8 +4071,14 @@ void ata_scsi_simulate(struct ata_device
 		case 0xb2:
 			ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b2);
 			break;
+		case 0xb6:
+			if (dev->flags & ATA_DFLAG_ZAC) {
+				ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b6);
+				break;
+			}
+			/* Fallthrough */
 		default:
-			ata_scsi_invalid_field(cmd);
+			ata_scsi_invalid_field(dev, cmd, 2);
 			break;
 		}
 		break;
@@ -3619,7 +4096,7 @@ void ata_scsi_simulate(struct ata_device
 		if ((scsicmd[1] & 0x1f) == SAI_READ_CAPACITY_16)
 			ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap);
 		else
-			ata_scsi_invalid_field(cmd);
+			ata_scsi_invalid_field(dev, cmd, 1);
 		break;
 
 	case REPORT_LUNS:
@@ -3627,7 +4104,7 @@ void ata_scsi_simulate(struct ata_device
 		break;
 
 	case REQUEST_SENSE:
-		ata_scsi_set_sense(cmd, 0, 0, 0);
+		ata_scsi_set_sense(dev, cmd, 0, 0, 0);
 		cmd->result = (DRIVER_SENSE << 24);
 		cmd->scsi_done(cmd);
 		break;
@@ -3651,12 +4128,12 @@ void ata_scsi_simulate(struct ata_device
 		if ((tmp8 == 0x4) && (!scsicmd[3]) && (!scsicmd[4]))
 			ata_scsi_rbuf_fill(&args, ata_scsiop_noop);
 		else
-			ata_scsi_invalid_field(cmd);
+			ata_scsi_invalid_field(dev, cmd, 1);
 		break;
 
 	/* all other commands */
 	default:
-		ata_scsi_set_sense(cmd, ILLEGAL_REQUEST, 0x20, 0x0);
+		ata_scsi_set_sense(dev, cmd, ILLEGAL_REQUEST, 0x20, 0x0);
 		/* "Invalid command operation code" */
 		cmd->scsi_done(cmd);
 		break;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/ata/libata-trace.c linux-libre-4.7-gnu/drivers/ata/libata-trace.c
--- linux-libre-4.6-gnu/drivers/ata/libata-trace.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/ata/libata-trace.c	2016-07-24 15:23:50.000000000 -0400
@@ -149,3 +149,75 @@ libata_trace_parse_qc_flags(struct trace
 
 	return ret;
 }
+
+const char *
+libata_trace_parse_subcmd(struct trace_seq *p, unsigned char cmd,
+			  unsigned char feature, unsigned char hob_nsect)
+{
+	const char *ret = trace_seq_buffer_ptr(p);
+
+	switch (cmd) {
+	case ATA_CMD_FPDMA_RECV:
+		switch (hob_nsect & 0x5f) {
+		case ATA_SUBCMD_FPDMA_RECV_RD_LOG_DMA_EXT:
+			trace_seq_printf(p, " READ_LOG_DMA_EXT");
+			break;
+		case ATA_SUBCMD_FPDMA_RECV_ZAC_MGMT_IN:
+			trace_seq_printf(p, " ZAC_MGMT_IN");
+			break;
+		}
+		break;
+	case ATA_CMD_FPDMA_SEND:
+		switch (hob_nsect & 0x5f) {
+		case ATA_SUBCMD_FPDMA_SEND_WR_LOG_DMA_EXT:
+			trace_seq_printf(p, " WRITE_LOG_DMA_EXT");
+			break;
+		case ATA_SUBCMD_FPDMA_SEND_DSM:
+			trace_seq_printf(p, " DATASET_MANAGEMENT");
+			break;
+		}
+		break;
+	case ATA_CMD_NCQ_NON_DATA:
+		switch (feature) {
+		case ATA_SUBCMD_NCQ_NON_DATA_ABORT_QUEUE:
+			trace_seq_printf(p, " ABORT_QUEUE");
+			break;
+		case ATA_SUBCMD_NCQ_NON_DATA_SET_FEATURES:
+			trace_seq_printf(p, " SET_FEATURES");
+			break;
+		case ATA_SUBCMD_NCQ_NON_DATA_ZERO_EXT:
+			trace_seq_printf(p, " ZERO_EXT");
+			break;
+		case ATA_SUBCMD_NCQ_NON_DATA_ZAC_MGMT_OUT:
+			trace_seq_printf(p, " ZAC_MGMT_OUT");
+			break;
+		}
+		break;
+	case ATA_CMD_ZAC_MGMT_IN:
+		switch (feature) {
+		case ATA_SUBCMD_ZAC_MGMT_IN_REPORT_ZONES:
+			trace_seq_printf(p, " REPORT_ZONES");
+			break;
+		}
+		break;
+	case ATA_CMD_ZAC_MGMT_OUT:
+		switch (feature) {
+		case ATA_SUBCMD_ZAC_MGMT_OUT_CLOSE_ZONE:
+			trace_seq_printf(p, " CLOSE_ZONE");
+			break;
+		case ATA_SUBCMD_ZAC_MGMT_OUT_FINISH_ZONE:
+			trace_seq_printf(p, " FINISH_ZONE");
+			break;
+		case ATA_SUBCMD_ZAC_MGMT_OUT_OPEN_ZONE:
+			trace_seq_printf(p, " OPEN_ZONE");
+			break;
+		case ATA_SUBCMD_ZAC_MGMT_OUT_RESET_WRITE_POINTER:
+			trace_seq_printf(p, " RESET_WRITE_POINTER");
+			break;
+		}
+		break;
+	}
+	trace_seq_putc(p, 0);
+
+	return ret;
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/ata/pata_icside.c linux-libre-4.7-gnu/drivers/ata/pata_icside.c
--- linux-libre-4.6-gnu/drivers/ata/pata_icside.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/ata/pata_icside.c	2016-07-24 15:23:50.000000000 -0400
@@ -294,7 +294,7 @@ static int icside_dma_init(struct pata_i
 
 static struct scsi_host_template pata_icside_sht = {
 	ATA_BASE_SHT(DRV_NAME),
-	.sg_tablesize		= SCSI_MAX_SG_CHAIN_SEGMENTS,
+	.sg_tablesize		= SG_MAX_SEGMENTS,
 	.dma_boundary		= IOMD_DMA_BOUNDARY,
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/ata/sata_dwc_460ex.c linux-libre-4.7-gnu/drivers/ata/sata_dwc_460ex.c
--- linux-libre-4.6-gnu/drivers/ata/sata_dwc_460ex.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/ata/sata_dwc_460ex.c	2016-07-24 15:23:50.000000000 -0400
@@ -30,10 +30,12 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/device.h>
+#include <linux/dmaengine.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
+#include <linux/phy/phy.h>
 #include <linux/libata.h>
 #include <linux/slab.h>
 
@@ -42,10 +44,6 @@
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_cmnd.h>
 
-/* Supported DMA engine drivers */
-#include <linux/platform_data/dma-dw.h>
-#include <linux/dma/dw.h>
-
 /* These two are defined in "libata.h" */
 #undef	DRV_NAME
 #undef	DRV_VERSION
@@ -53,19 +51,14 @@
 #define DRV_NAME        "sata-dwc"
 #define DRV_VERSION     "1.3"
 
-#ifndef out_le32
-#define out_le32(a, v)	__raw_writel(__cpu_to_le32(v), (void __iomem *)(a))
-#endif
-
-#ifndef in_le32
-#define in_le32(a)	__le32_to_cpu(__raw_readl((void __iomem *)(a)))
-#endif
+#define sata_dwc_writel(a, v)	writel_relaxed(v, a)
+#define sata_dwc_readl(a)	readl_relaxed(a)
 
 #ifndef NO_IRQ
 #define NO_IRQ		0
 #endif
 
-#define AHB_DMA_BRST_DFLT	64	/* 16 data items burst length*/
+#define AHB_DMA_BRST_DFLT	64	/* 16 data items burst length */
 
 enum {
 	SATA_DWC_MAX_PORTS = 1,
@@ -102,7 +95,7 @@ struct sata_dwc_regs {
 	u32 versionr;		/* Version Register */
 	u32 idr;		/* ID Register */
 	u32 unimpl[192];	/* Unimplemented */
-	u32 dmadr[256];	/* FIFO Locations in DMA Mode */
+	u32 dmadr[256];		/* FIFO Locations in DMA Mode */
 };
 
 enum {
@@ -146,9 +139,14 @@ struct sata_dwc_device {
 	struct device		*dev;		/* generic device struct */
 	struct ata_probe_ent	*pe;		/* ptr to probe-ent */
 	struct ata_host		*host;
-	u8 __iomem		*reg_base;
-	struct sata_dwc_regs	*sata_dwc_regs;	/* DW Synopsys SATA specific */
+	struct sata_dwc_regs __iomem *sata_dwc_regs;	/* DW SATA specific */
+	u32			sactive_issued;
+	u32			sactive_queued;
+	struct phy		*phy;
+	phys_addr_t		dmadr;
+#ifdef CONFIG_SATA_DWC_OLD_DMA
 	struct dw_dma_chip	*dma;
+#endif
 };
 
 #define SATA_DWC_QCMD_MAX	32
@@ -159,25 +157,19 @@ struct sata_dwc_device_port {
 	int			dma_pending[SATA_DWC_QCMD_MAX];
 
 	/* DMA info */
-	struct dw_dma_slave		*dws;
 	struct dma_chan			*chan;
 	struct dma_async_tx_descriptor	*desc[SATA_DWC_QCMD_MAX];
 	u32				dma_interrupt_count;
 };
 
 /*
- * Commonly used DWC SATA driver Macros
+ * Commonly used DWC SATA driver macros
  */
-#define HSDEV_FROM_HOST(host)  ((struct sata_dwc_device *)\
-					(host)->private_data)
-#define HSDEV_FROM_AP(ap)  ((struct sata_dwc_device *)\
-					(ap)->host->private_data)
-#define HSDEVP_FROM_AP(ap)   ((struct sata_dwc_device_port *)\
-					(ap)->private_data)
-#define HSDEV_FROM_QC(qc)	((struct sata_dwc_device *)\
-					(qc)->ap->host->private_data)
-#define HSDEV_FROM_HSDEVP(p)	((struct sata_dwc_device *)\
-						(hsdevp)->hsdev)
+#define HSDEV_FROM_HOST(host)	((struct sata_dwc_device *)(host)->private_data)
+#define HSDEV_FROM_AP(ap)	((struct sata_dwc_device *)(ap)->host->private_data)
+#define HSDEVP_FROM_AP(ap)	((struct sata_dwc_device_port *)(ap)->private_data)
+#define HSDEV_FROM_QC(qc)	((struct sata_dwc_device *)(qc)->ap->host->private_data)
+#define HSDEV_FROM_HSDEVP(p)	((struct sata_dwc_device *)(p)->hsdev)
 
 enum {
 	SATA_DWC_CMD_ISSUED_NOT		= 0,
@@ -190,21 +182,6 @@ enum {
 	SATA_DWC_DMA_PENDING_RX		= 2,
 };
 
-struct sata_dwc_host_priv {
-	void	__iomem	 *scr_addr_sstatus;
-	u32	sata_dwc_sactive_issued ;
-	u32	sata_dwc_sactive_queued ;
-};
-
-static struct sata_dwc_host_priv host_pvt;
-
-static struct dw_dma_slave sata_dwc_dma_dws = {
-	.src_id = 0,
-	.dst_id = 0,
-	.src_master = 0,
-	.dst_master = 1,
-};
-
 /*
  * Prototypes
  */
@@ -215,6 +192,93 @@ static void sata_dwc_dma_xfer_complete(s
 static void sata_dwc_port_stop(struct ata_port *ap);
 static void sata_dwc_clear_dmacr(struct sata_dwc_device_port *hsdevp, u8 tag);
 
+#ifdef CONFIG_SATA_DWC_OLD_DMA
+
+#include <linux/platform_data/dma-dw.h>
+#include <linux/dma/dw.h>
+
+static struct dw_dma_slave sata_dwc_dma_dws = {
+	.src_id = 0,
+	.dst_id = 0,
+	.m_master = 1,
+	.p_master = 0,
+};
+
+static bool sata_dwc_dma_filter(struct dma_chan *chan, void *param)
+{
+	struct dw_dma_slave *dws = &sata_dwc_dma_dws;
+
+	if (dws->dma_dev != chan->device->dev)
+		return false;
+
+	chan->private = dws;
+	return true;
+}
+
+static int sata_dwc_dma_get_channel_old(struct sata_dwc_device_port *hsdevp)
+{
+	struct sata_dwc_device *hsdev = hsdevp->hsdev;
+	struct dw_dma_slave *dws = &sata_dwc_dma_dws;
+	dma_cap_mask_t mask;
+
+	dws->dma_dev = hsdev->dev;
+
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+
+	/* Acquire DMA channel */
+	hsdevp->chan = dma_request_channel(mask, sata_dwc_dma_filter, hsdevp);
+	if (!hsdevp->chan) {
+		dev_err(hsdev->dev, "%s: dma channel unavailable\n",
+			 __func__);
+		return -EAGAIN;
+	}
+
+	return 0;
+}
+
+static int sata_dwc_dma_init_old(struct platform_device *pdev,
+				 struct sata_dwc_device *hsdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct resource *res;
+
+	hsdev->dma = devm_kzalloc(&pdev->dev, sizeof(*hsdev->dma), GFP_KERNEL);
+	if (!hsdev->dma)
+		return -ENOMEM;
+
+	hsdev->dma->dev = &pdev->dev;
+
+	/* Get SATA DMA interrupt number */
+	hsdev->dma->irq = irq_of_parse_and_map(np, 1);
+	if (hsdev->dma->irq == NO_IRQ) {
+		dev_err(&pdev->dev, "no SATA DMA irq\n");
+		return -ENODEV;
+	}
+
+	/* Get physical SATA DMA register base address */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	hsdev->dma->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(hsdev->dma->regs)) {
+		dev_err(&pdev->dev,
+			"ioremap failed for AHBDMA register address\n");
+		return PTR_ERR(hsdev->dma->regs);
+	}
+
+	/* Initialize AHB DMAC */
+	return dw_dma_probe(hsdev->dma);
+}
+
+static void sata_dwc_dma_exit_old(struct sata_dwc_device *hsdev)
+{
+	if (!hsdev->dma)
+		return;
+
+	dw_dma_remove(hsdev->dma);
+}
+
+#endif
+
 static const char *get_prot_descript(u8 protocol)
 {
 	switch ((enum ata_tf_protocols)protocol) {
@@ -305,21 +369,20 @@ static struct dma_async_tx_descriptor *d
 	struct ata_port *ap = qc->ap;
 	struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap);
 	struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap);
-	dma_addr_t addr = (dma_addr_t)&hsdev->sata_dwc_regs->dmadr;
 	struct dma_slave_config sconf;
 	struct dma_async_tx_descriptor *desc;
 
 	if (qc->dma_dir == DMA_DEV_TO_MEM) {
-		sconf.src_addr = addr;
-		sconf.device_fc = true;
+		sconf.src_addr = hsdev->dmadr;
+		sconf.device_fc = false;
 	} else {	/* DMA_MEM_TO_DEV */
-		sconf.dst_addr = addr;
+		sconf.dst_addr = hsdev->dmadr;
 		sconf.device_fc = false;
 	}
 
 	sconf.direction = qc->dma_dir;
-	sconf.src_maxburst = AHB_DMA_BRST_DFLT;
-	sconf.dst_maxburst = AHB_DMA_BRST_DFLT;
+	sconf.src_maxburst = AHB_DMA_BRST_DFLT / 4;	/* in items */
+	sconf.dst_maxburst = AHB_DMA_BRST_DFLT / 4;	/* in items */
 	sconf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
 	sconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
 
@@ -336,8 +399,8 @@ static struct dma_async_tx_descriptor *d
 	desc->callback = dma_dwc_xfer_done;
 	desc->callback_param = hsdev;
 
-	dev_dbg(hsdev->dev, "%s sg: 0x%p, count: %d addr: %pad\n",
-		__func__, qc->sg, qc->n_elem, &addr);
+	dev_dbg(hsdev->dev, "%s sg: 0x%p, count: %d addr: %pa\n", __func__,
+		qc->sg, qc->n_elem, &hsdev->dmadr);
 
 	return desc;
 }
@@ -350,48 +413,38 @@ static int sata_dwc_scr_read(struct ata_
 		return -EINVAL;
 	}
 
-	*val = in_le32(link->ap->ioaddr.scr_addr + (scr * 4));
-	dev_dbg(link->ap->dev, "%s: id=%d reg=%d val=val=0x%08x\n",
-		__func__, link->ap->print_id, scr, *val);
+	*val = sata_dwc_readl(link->ap->ioaddr.scr_addr + (scr * 4));
+	dev_dbg(link->ap->dev, "%s: id=%d reg=%d val=0x%08x\n", __func__,
+		link->ap->print_id, scr, *val);
 
 	return 0;
 }
 
 static int sata_dwc_scr_write(struct ata_link *link, unsigned int scr, u32 val)
 {
-	dev_dbg(link->ap->dev, "%s: id=%d reg=%d val=val=0x%08x\n",
-		__func__, link->ap->print_id, scr, val);
+	dev_dbg(link->ap->dev, "%s: id=%d reg=%d val=0x%08x\n", __func__,
+		link->ap->print_id, scr, val);
 	if (scr > SCR_NOTIFICATION) {
 		dev_err(link->ap->dev, "%s: Incorrect SCR offset 0x%02x\n",
 			 __func__, scr);
 		return -EINVAL;
 	}
-	out_le32(link->ap->ioaddr.scr_addr + (scr * 4), val);
+	sata_dwc_writel(link->ap->ioaddr.scr_addr + (scr * 4), val);
 
 	return 0;
 }
 
-static u32 core_scr_read(unsigned int scr)
-{
-	return in_le32(host_pvt.scr_addr_sstatus + (scr * 4));
-}
-
-static void core_scr_write(unsigned int scr, u32 val)
-{
-	out_le32(host_pvt.scr_addr_sstatus + (scr * 4), val);
-}
-
-static void clear_serror(void)
+static void clear_serror(struct ata_port *ap)
 {
 	u32 val;
-	val = core_scr_read(SCR_ERROR);
-	core_scr_write(SCR_ERROR, val);
+	sata_dwc_scr_read(&ap->link, SCR_ERROR, &val);
+	sata_dwc_scr_write(&ap->link, SCR_ERROR, val);
 }
 
 static void clear_interrupt_bit(struct sata_dwc_device *hsdev, u32 bit)
 {
-	out_le32(&hsdev->sata_dwc_regs->intpr,
-		 in_le32(&hsdev->sata_dwc_regs->intpr));
+	sata_dwc_writel(&hsdev->sata_dwc_regs->intpr,
+			sata_dwc_readl(&hsdev->sata_dwc_regs->intpr));
 }
 
 static u32 qcmd_tag_to_mask(u8 tag)
@@ -412,7 +465,7 @@ static void sata_dwc_error_intr(struct a
 
 	ata_ehi_clear_desc(ehi);
 
-	serror = core_scr_read(SCR_ERROR);
+	sata_dwc_scr_read(&ap->link, SCR_ERROR, &serror);
 	status = ap->ops->sff_check_status(ap);
 
 	tag = ap->link.active_tag;
@@ -423,7 +476,7 @@ static void sata_dwc_error_intr(struct a
 		hsdevp->dma_pending[tag], hsdevp->cmd_issued[tag]);
 
 	/* Clear error register and interrupt bit */
-	clear_serror();
+	clear_serror(ap);
 	clear_interrupt_bit(hsdev, SATA_DWC_INTPR_ERR);
 
 	/* This is the only error happening now.  TODO check for exact error */
@@ -462,12 +515,12 @@ static irqreturn_t sata_dwc_isr(int irq,
 	int handled, num_processed, port = 0;
 	uint intpr, sactive, sactive2, tag_mask;
 	struct sata_dwc_device_port *hsdevp;
-	host_pvt.sata_dwc_sactive_issued = 0;
+	hsdev->sactive_issued = 0;
 
 	spin_lock_irqsave(&host->lock, flags);
 
 	/* Read the interrupt register */
-	intpr = in_le32(&hsdev->sata_dwc_regs->intpr);
+	intpr = sata_dwc_readl(&hsdev->sata_dwc_regs->intpr);
 
 	ap = host->ports[port];
 	hsdevp = HSDEVP_FROM_AP(ap);
@@ -486,12 +539,12 @@ static irqreturn_t sata_dwc_isr(int irq,
 	if (intpr & SATA_DWC_INTPR_NEWFP) {
 		clear_interrupt_bit(hsdev, SATA_DWC_INTPR_NEWFP);
 
-		tag = (u8)(in_le32(&hsdev->sata_dwc_regs->fptagr));
+		tag = (u8)(sata_dwc_readl(&hsdev->sata_dwc_regs->fptagr));
 		dev_dbg(ap->dev, "%s: NEWFP tag=%d\n", __func__, tag);
 		if (hsdevp->cmd_issued[tag] != SATA_DWC_CMD_ISSUED_PEND)
 			dev_warn(ap->dev, "CMD tag=%d not pending?\n", tag);
 
-		host_pvt.sata_dwc_sactive_issued |= qcmd_tag_to_mask(tag);
+		hsdev->sactive_issued |= qcmd_tag_to_mask(tag);
 
 		qc = ata_qc_from_tag(ap, tag);
 		/*
@@ -505,11 +558,11 @@ static irqreturn_t sata_dwc_isr(int irq,
 		handled = 1;
 		goto DONE;
 	}
-	sactive = core_scr_read(SCR_ACTIVE);
-	tag_mask = (host_pvt.sata_dwc_sactive_issued | sactive) ^ sactive;
+	sata_dwc_scr_read(&ap->link, SCR_ACTIVE, &sactive);
+	tag_mask = (hsdev->sactive_issued | sactive) ^ sactive;
 
 	/* If no sactive issued and tag_mask is zero then this is not NCQ */
-	if (host_pvt.sata_dwc_sactive_issued == 0 && tag_mask == 0) {
+	if (hsdev->sactive_issued == 0 && tag_mask == 0) {
 		if (ap->link.active_tag == ATA_TAG_POISON)
 			tag = 0;
 		else
@@ -579,22 +632,19 @@ DRVSTILLBUSY:
 	 */
 
 	 /* process completed commands */
-	sactive = core_scr_read(SCR_ACTIVE);
-	tag_mask = (host_pvt.sata_dwc_sactive_issued | sactive) ^ sactive;
+	sata_dwc_scr_read(&ap->link, SCR_ACTIVE, &sactive);
+	tag_mask = (hsdev->sactive_issued | sactive) ^ sactive;
 
-	if (sactive != 0 || (host_pvt.sata_dwc_sactive_issued) > 1 || \
-							tag_mask > 1) {
+	if (sactive != 0 || hsdev->sactive_issued > 1 || tag_mask > 1) {
 		dev_dbg(ap->dev,
 			"%s NCQ:sactive=0x%08x  sactive_issued=0x%08x tag_mask=0x%08x\n",
-			__func__, sactive, host_pvt.sata_dwc_sactive_issued,
-			tag_mask);
+			__func__, sactive, hsdev->sactive_issued, tag_mask);
 	}
 
-	if ((tag_mask | (host_pvt.sata_dwc_sactive_issued)) != \
-					(host_pvt.sata_dwc_sactive_issued)) {
+	if ((tag_mask | hsdev->sactive_issued) != hsdev->sactive_issued) {
 		dev_warn(ap->dev,
-			 "Bad tag mask?  sactive=0x%08x (host_pvt.sata_dwc_sactive_issued)=0x%08x  tag_mask=0x%08x\n",
-			 sactive, host_pvt.sata_dwc_sactive_issued, tag_mask);
+			 "Bad tag mask?  sactive=0x%08x sactive_issued=0x%08x  tag_mask=0x%08x\n",
+			 sactive, hsdev->sactive_issued, tag_mask);
 	}
 
 	/* read just to clear ... not bad if currently still busy */
@@ -656,7 +706,7 @@ STILLBUSY:
 	 * we were processing --we read status as part of processing a completed
 	 * command).
 	 */
-	sactive2 = core_scr_read(SCR_ACTIVE);
+	sata_dwc_scr_read(&ap->link, SCR_ACTIVE, &sactive2);
 	if (sactive2 != sactive) {
 		dev_dbg(ap->dev,
 			"More completed - sactive=0x%x sactive2=0x%x\n",
@@ -672,15 +722,14 @@ DONE:
 static void sata_dwc_clear_dmacr(struct sata_dwc_device_port *hsdevp, u8 tag)
 {
 	struct sata_dwc_device *hsdev = HSDEV_FROM_HSDEVP(hsdevp);
+	u32 dmacr = sata_dwc_readl(&hsdev->sata_dwc_regs->dmacr);
 
 	if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_RX) {
-		out_le32(&(hsdev->sata_dwc_regs->dmacr),
-			 SATA_DWC_DMACR_RX_CLEAR(
-				 in_le32(&(hsdev->sata_dwc_regs->dmacr))));
+		dmacr = SATA_DWC_DMACR_RX_CLEAR(dmacr);
+		sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr, dmacr);
 	} else if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_TX) {
-		out_le32(&(hsdev->sata_dwc_regs->dmacr),
-			 SATA_DWC_DMACR_TX_CLEAR(
-				 in_le32(&(hsdev->sata_dwc_regs->dmacr))));
+		dmacr = SATA_DWC_DMACR_TX_CLEAR(dmacr);
+		sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr, dmacr);
 	} else {
 		/*
 		 * This should not happen, it indicates the driver is out of
@@ -688,10 +737,9 @@ static void sata_dwc_clear_dmacr(struct
 		 */
 		dev_err(hsdev->dev,
 			"%s DMA protocol RX and TX DMA not pending tag=0x%02x pending=%d dmacr: 0x%08x\n",
-			__func__, tag, hsdevp->dma_pending[tag],
-			in_le32(&hsdev->sata_dwc_regs->dmacr));
-		out_le32(&(hsdev->sata_dwc_regs->dmacr),
-			SATA_DWC_DMACR_TXRXCH_CLEAR);
+			__func__, tag, hsdevp->dma_pending[tag], dmacr);
+		sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr,
+				SATA_DWC_DMACR_TXRXCH_CLEAR);
 	}
 }
 
@@ -716,7 +764,7 @@ static void sata_dwc_dma_xfer_complete(s
 			 __func__, qc->tag, qc->tf.command,
 			 get_dma_dir_descript(qc->dma_dir),
 			 get_prot_descript(qc->tf.protocol),
-			 in_le32(&(hsdev->sata_dwc_regs->dmacr)));
+			 sata_dwc_readl(&hsdev->sata_dwc_regs->dmacr));
 	}
 #endif
 
@@ -725,7 +773,7 @@ static void sata_dwc_dma_xfer_complete(s
 			dev_err(ap->dev,
 				"%s DMA protocol RX and TX DMA not pending dmacr: 0x%08x\n",
 				__func__,
-				in_le32(&(hsdev->sata_dwc_regs->dmacr)));
+				sata_dwc_readl(&hsdev->sata_dwc_regs->dmacr));
 		}
 
 		hsdevp->dma_pending[tag] = SATA_DWC_DMA_PENDING_NONE;
@@ -742,8 +790,9 @@ static int sata_dwc_qc_complete(struct a
 	u8 status = 0;
 	u32 mask = 0x0;
 	u8 tag = qc->tag;
+	struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap);
 	struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap);
-	host_pvt.sata_dwc_sactive_queued = 0;
+	hsdev->sactive_queued = 0;
 	dev_dbg(ap->dev, "%s checkstatus? %x\n", __func__, check_status);
 
 	if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_TX)
@@ -756,10 +805,8 @@ static int sata_dwc_qc_complete(struct a
 
 	/* clear active bit */
 	mask = (~(qcmd_tag_to_mask(tag)));
-	host_pvt.sata_dwc_sactive_queued = (host_pvt.sata_dwc_sactive_queued) \
-						& mask;
-	host_pvt.sata_dwc_sactive_issued = (host_pvt.sata_dwc_sactive_issued) \
-						& mask;
+	hsdev->sactive_queued = hsdev->sactive_queued & mask;
+	hsdev->sactive_issued = hsdev->sactive_issued & mask;
 	ata_qc_complete(qc);
 	return 0;
 }
@@ -767,54 +814,62 @@ static int sata_dwc_qc_complete(struct a
 static void sata_dwc_enable_interrupts(struct sata_dwc_device *hsdev)
 {
 	/* Enable selective interrupts by setting the interrupt maskregister*/
-	out_le32(&hsdev->sata_dwc_regs->intmr,
-		 SATA_DWC_INTMR_ERRM |
-		 SATA_DWC_INTMR_NEWFPM |
-		 SATA_DWC_INTMR_PMABRTM |
-		 SATA_DWC_INTMR_DMATM);
+	sata_dwc_writel(&hsdev->sata_dwc_regs->intmr,
+			SATA_DWC_INTMR_ERRM |
+			SATA_DWC_INTMR_NEWFPM |
+			SATA_DWC_INTMR_PMABRTM |
+			SATA_DWC_INTMR_DMATM);
 	/*
 	 * Unmask the error bits that should trigger an error interrupt by
 	 * setting the error mask register.
 	 */
-	out_le32(&hsdev->sata_dwc_regs->errmr, SATA_DWC_SERROR_ERR_BITS);
+	sata_dwc_writel(&hsdev->sata_dwc_regs->errmr, SATA_DWC_SERROR_ERR_BITS);
 
 	dev_dbg(hsdev->dev, "%s: INTMR = 0x%08x, ERRMR = 0x%08x\n",
-		 __func__, in_le32(&hsdev->sata_dwc_regs->intmr),
-		in_le32(&hsdev->sata_dwc_regs->errmr));
+		 __func__, sata_dwc_readl(&hsdev->sata_dwc_regs->intmr),
+		sata_dwc_readl(&hsdev->sata_dwc_regs->errmr));
 }
 
-static bool sata_dwc_dma_filter(struct dma_chan *chan, void *param)
+static void sata_dwc_setup_port(struct ata_ioports *port, void __iomem *base)
 {
-	struct sata_dwc_device_port *hsdevp = param;
-	struct dw_dma_slave *dws = hsdevp->dws;
+	port->cmd_addr		= base + 0x00;
+	port->data_addr		= base + 0x00;
 
-	if (dws->dma_dev != chan->device->dev)
-		return false;
+	port->error_addr	= base + 0x04;
+	port->feature_addr	= base + 0x04;
 
-	chan->private = dws;
-	return true;
-}
+	port->nsect_addr	= base + 0x08;
 
-static void sata_dwc_setup_port(struct ata_ioports *port, unsigned long base)
-{
-	port->cmd_addr = (void __iomem *)base + 0x00;
-	port->data_addr = (void __iomem *)base + 0x00;
+	port->lbal_addr		= base + 0x0c;
+	port->lbam_addr		= base + 0x10;
+	port->lbah_addr		= base + 0x14;
 
-	port->error_addr = (void __iomem *)base + 0x04;
-	port->feature_addr = (void __iomem *)base + 0x04;
+	port->device_addr	= base + 0x18;
+	port->command_addr	= base + 0x1c;
+	port->status_addr	= base + 0x1c;
 
-	port->nsect_addr = (void __iomem *)base + 0x08;
+	port->altstatus_addr	= base + 0x20;
+	port->ctl_addr		= base + 0x20;
+}
 
-	port->lbal_addr = (void __iomem *)base + 0x0c;
-	port->lbam_addr = (void __iomem *)base + 0x10;
-	port->lbah_addr = (void __iomem *)base + 0x14;
+static int sata_dwc_dma_get_channel(struct sata_dwc_device_port *hsdevp)
+{
+	struct sata_dwc_device *hsdev = hsdevp->hsdev;
+	struct device *dev = hsdev->dev;
 
-	port->device_addr = (void __iomem *)base + 0x18;
-	port->command_addr = (void __iomem *)base + 0x1c;
-	port->status_addr = (void __iomem *)base + 0x1c;
+#ifdef CONFIG_SATA_DWC_OLD_DMA
+	if (!of_find_property(dev->of_node, "dmas", NULL))
+		return sata_dwc_dma_get_channel_old(hsdevp);
+#endif
 
-	port->altstatus_addr = (void __iomem *)base + 0x20;
-	port->ctl_addr = (void __iomem *)base + 0x20;
+	hsdevp->chan = dma_request_chan(dev, "sata-dma");
+	if (IS_ERR(hsdevp->chan)) {
+		dev_err(dev, "failed to allocate dma channel: %ld\n",
+			PTR_ERR(hsdevp->chan));
+		return PTR_ERR(hsdevp->chan);
+	}
+
+	return 0;
 }
 
 /*
@@ -829,7 +884,6 @@ static int sata_dwc_port_start(struct at
 	struct sata_dwc_device *hsdev;
 	struct sata_dwc_device_port *hsdevp = NULL;
 	struct device *pdev;
-	dma_cap_mask_t mask;
 	int i;
 
 	hsdev = HSDEV_FROM_AP(ap);
@@ -853,20 +907,13 @@ static int sata_dwc_port_start(struct at
 	}
 	hsdevp->hsdev = hsdev;
 
-	hsdevp->dws = &sata_dwc_dma_dws;
-	hsdevp->dws->dma_dev = hsdev->dev;
-
-	dma_cap_zero(mask);
-	dma_cap_set(DMA_SLAVE, mask);
+	err = sata_dwc_dma_get_channel(hsdevp);
+	if (err)
+		goto CLEANUP_ALLOC;
 
-	/* Acquire DMA channel */
-	hsdevp->chan = dma_request_channel(mask, sata_dwc_dma_filter, hsdevp);
-	if (!hsdevp->chan) {
-		dev_err(hsdev->dev, "%s: dma channel unavailable\n",
-			 __func__);
-		err = -EAGAIN;
+	err = phy_power_on(hsdev->phy);
+	if (err)
 		goto CLEANUP_ALLOC;
-	}
 
 	for (i = 0; i < SATA_DWC_QCMD_MAX; i++)
 		hsdevp->cmd_issued[i] = SATA_DWC_CMD_ISSUED_NOT;
@@ -877,18 +924,18 @@ static int sata_dwc_port_start(struct at
 	if (ap->port_no == 0)  {
 		dev_dbg(ap->dev, "%s: clearing TXCHEN, RXCHEN in DMAC\n",
 			__func__);
-		out_le32(&hsdev->sata_dwc_regs->dmacr,
-			 SATA_DWC_DMACR_TXRXCH_CLEAR);
+		sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr,
+				SATA_DWC_DMACR_TXRXCH_CLEAR);
 
 		dev_dbg(ap->dev, "%s: setting burst size in DBTSR\n",
 			 __func__);
-		out_le32(&hsdev->sata_dwc_regs->dbtsr,
-			 (SATA_DWC_DBTSR_MWR(AHB_DMA_BRST_DFLT) |
-			  SATA_DWC_DBTSR_MRD(AHB_DMA_BRST_DFLT)));
+		sata_dwc_writel(&hsdev->sata_dwc_regs->dbtsr,
+				(SATA_DWC_DBTSR_MWR(AHB_DMA_BRST_DFLT) |
+				 SATA_DWC_DBTSR_MRD(AHB_DMA_BRST_DFLT)));
 	}
 
 	/* Clear any error bits before libata starts issuing commands */
-	clear_serror();
+	clear_serror(ap);
 	ap->private_data = hsdevp;
 	dev_dbg(ap->dev, "%s: done\n", __func__);
 	return 0;
@@ -903,11 +950,13 @@ CLEANUP:
 static void sata_dwc_port_stop(struct ata_port *ap)
 {
 	struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap);
+	struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap);
 
 	dev_dbg(ap->dev, "%s: ap->id = %d\n", __func__, ap->print_id);
 
-	dmaengine_terminate_all(hsdevp->chan);
+	dmaengine_terminate_sync(hsdevp->chan);
 	dma_release_channel(hsdevp->chan);
+	phy_power_off(hsdev->phy);
 
 	kfree(hsdevp);
 	ap->private_data = NULL;
@@ -924,22 +973,20 @@ static void sata_dwc_exec_command_by_tag
 					 struct ata_taskfile *tf,
 					 u8 tag, u32 cmd_issued)
 {
-	unsigned long flags;
 	struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap);
 
 	dev_dbg(ap->dev, "%s cmd(0x%02x): %s tag=%d\n", __func__, tf->command,
 		ata_get_cmd_descript(tf->command), tag);
 
-	spin_lock_irqsave(&ap->host->lock, flags);
 	hsdevp->cmd_issued[tag] = cmd_issued;
-	spin_unlock_irqrestore(&ap->host->lock, flags);
+
 	/*
 	 * Clear SError before executing a new command.
 	 * sata_dwc_scr_write and read can not be used here. Clearing the PM
 	 * managed SError register for the disk needs to be done before the
 	 * task file is loaded.
 	 */
-	clear_serror();
+	clear_serror(ap);
 	ata_sff_exec_command(ap, tf);
 }
 
@@ -992,18 +1039,18 @@ static void sata_dwc_bmdma_start_by_tag(
 	sata_dwc_tf_dump(ap, &qc->tf);
 
 	if (start_dma) {
-		reg = core_scr_read(SCR_ERROR);
+		sata_dwc_scr_read(&ap->link, SCR_ERROR, &reg);
 		if (reg & SATA_DWC_SERROR_ERR_BITS) {
 			dev_err(ap->dev, "%s: ****** SError=0x%08x ******\n",
 				__func__, reg);
 		}
 
 		if (dir == DMA_TO_DEVICE)
-			out_le32(&hsdev->sata_dwc_regs->dmacr,
-				SATA_DWC_DMACR_TXCHEN);
+			sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr,
+					SATA_DWC_DMACR_TXCHEN);
 		else
-			out_le32(&hsdev->sata_dwc_regs->dmacr,
-				SATA_DWC_DMACR_RXCHEN);
+			sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr,
+					SATA_DWC_DMACR_RXCHEN);
 
 		/* Enable AHB DMA transfer on the specified channel */
 		dmaengine_submit(desc);
@@ -1025,36 +1072,12 @@ static void sata_dwc_bmdma_start(struct
 	sata_dwc_bmdma_start_by_tag(qc, tag);
 }
 
-/*
- * Function : sata_dwc_qc_prep_by_tag
- * arguments : ata_queued_cmd *qc, u8 tag
- * Return value : None
- * qc_prep for a particular queued command based on tag
- */
-static void sata_dwc_qc_prep_by_tag(struct ata_queued_cmd *qc, u8 tag)
-{
-	struct dma_async_tx_descriptor *desc;
-	struct ata_port *ap = qc->ap;
-	struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap);
-
-	dev_dbg(ap->dev, "%s: port=%d dma dir=%s n_elem=%d\n",
-		__func__, ap->port_no, get_dma_dir_descript(qc->dma_dir),
-		 qc->n_elem);
-
-	desc = dma_dwc_xfer_setup(qc);
-	if (!desc) {
-		dev_err(ap->dev, "%s: dma_dwc_xfer_setup returns NULL\n",
-			__func__);
-		return;
-	}
-	hsdevp->desc[tag] = desc;
-}
-
 static unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc)
 {
 	u32 sactive;
 	u8 tag = qc->tag;
 	struct ata_port *ap = qc->ap;
+	struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap);
 
 #ifdef DEBUG_NCQ
 	if (qc->tag > 0 || ap->link.sactive > 1)
@@ -1068,47 +1091,33 @@ static unsigned int sata_dwc_qc_issue(st
 
 	if (!ata_is_ncq(qc->tf.protocol))
 		tag = 0;
-	sata_dwc_qc_prep_by_tag(qc, tag);
+
+	if (ata_is_dma(qc->tf.protocol)) {
+		hsdevp->desc[tag] = dma_dwc_xfer_setup(qc);
+		if (!hsdevp->desc[tag])
+			return AC_ERR_SYSTEM;
+	} else {
+		hsdevp->desc[tag] = NULL;
+	}
 
 	if (ata_is_ncq(qc->tf.protocol)) {
-		sactive = core_scr_read(SCR_ACTIVE);
+		sata_dwc_scr_read(&ap->link, SCR_ACTIVE, &sactive);
 		sactive |= (0x00000001 << tag);
-		core_scr_write(SCR_ACTIVE, sactive);
+		sata_dwc_scr_write(&ap->link, SCR_ACTIVE, sactive);
 
 		dev_dbg(qc->ap->dev,
 			"%s: tag=%d ap->link.sactive = 0x%08x sactive=0x%08x\n",
 			__func__, tag, qc->ap->link.sactive, sactive);
 
 		ap->ops->sff_tf_load(ap, &qc->tf);
-		sata_dwc_exec_command_by_tag(ap, &qc->tf, qc->tag,
+		sata_dwc_exec_command_by_tag(ap, &qc->tf, tag,
 					     SATA_DWC_CMD_ISSUED_PEND);
 	} else {
-		ata_sff_qc_issue(qc);
+		return ata_bmdma_qc_issue(qc);
 	}
 	return 0;
 }
 
-/*
- * Function : sata_dwc_qc_prep
- * arguments : ata_queued_cmd *qc
- * Return value : None
- * qc_prep for a particular queued command
- */
-
-static void sata_dwc_qc_prep(struct ata_queued_cmd *qc)
-{
-	if ((qc->dma_dir == DMA_NONE) || (qc->tf.protocol == ATA_PROT_PIO))
-		return;
-
-#ifdef DEBUG_NCQ
-	if (qc->tag > 0)
-		dev_info(qc->ap->dev, "%s: qc->tag=%d ap->active_tag=0x%08x\n",
-			 __func__, qc->tag, qc->ap->link.active_tag);
-
-	return ;
-#endif
-}
-
 static void sata_dwc_error_handler(struct ata_port *ap)
 {
 	ata_sff_error_handler(ap);
@@ -1125,17 +1134,22 @@ static int sata_dwc_hardreset(struct ata
 	sata_dwc_enable_interrupts(hsdev);
 
 	/* Reconfigure the DMA control register */
-	out_le32(&hsdev->sata_dwc_regs->dmacr,
-		 SATA_DWC_DMACR_TXRXCH_CLEAR);
+	sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr,
+			SATA_DWC_DMACR_TXRXCH_CLEAR);
 
 	/* Reconfigure the DMA Burst Transaction Size register */
-	out_le32(&hsdev->sata_dwc_regs->dbtsr,
-		 SATA_DWC_DBTSR_MWR(AHB_DMA_BRST_DFLT) |
-		 SATA_DWC_DBTSR_MRD(AHB_DMA_BRST_DFLT));
+	sata_dwc_writel(&hsdev->sata_dwc_regs->dbtsr,
+			SATA_DWC_DBTSR_MWR(AHB_DMA_BRST_DFLT) |
+			SATA_DWC_DBTSR_MRD(AHB_DMA_BRST_DFLT));
 
 	return ret;
 }
 
+static void sata_dwc_dev_select(struct ata_port *ap, unsigned int device)
+{
+	/* SATA DWC is master only */
+}
+
 /*
  * scsi mid-layer and libata interface structures
  */
@@ -1148,7 +1162,13 @@ static struct scsi_host_template sata_dw
 	 */
 	.sg_tablesize		= LIBATA_MAX_PRD,
 	/* .can_queue		= ATA_MAX_QUEUE, */
-	.dma_boundary		= ATA_DMA_BOUNDARY,
+	/*
+	 * Make sure a LLI block is not created that will span 8K max FIS
+	 * boundary. If the block spans such a FIS boundary, there is a chance
+	 * that a DMA burst will cross that boundary -- this results in an
+	 * error in the host controller.
+	 */
+	.dma_boundary		= 0x1fff /* ATA_DMA_BOUNDARY */,
 };
 
 static struct ata_port_operations sata_dwc_ops = {
@@ -1157,7 +1177,6 @@ static struct ata_port_operations sata_d
 	.error_handler		= sata_dwc_error_handler,
 	.hardreset		= sata_dwc_hardreset,
 
-	.qc_prep		= sata_dwc_qc_prep,
 	.qc_issue		= sata_dwc_qc_issue,
 
 	.scr_read		= sata_dwc_scr_read,
@@ -1166,6 +1185,8 @@ static struct ata_port_operations sata_d
 	.port_start		= sata_dwc_port_start,
 	.port_stop		= sata_dwc_port_stop,
 
+	.sff_dev_select		= sata_dwc_dev_select,
+
 	.bmdma_setup		= sata_dwc_bmdma_setup,
 	.bmdma_start		= sata_dwc_bmdma_start,
 };
@@ -1184,13 +1205,14 @@ static int sata_dwc_probe(struct platfor
 	struct sata_dwc_device *hsdev;
 	u32 idr, versionr;
 	char *ver = (char *)&versionr;
-	u8 __iomem *base;
+	void __iomem *base;
 	int err = 0;
 	int irq;
 	struct ata_host *host;
 	struct ata_port_info pi = sata_dwc_port_info[0];
 	const struct ata_port_info *ppi[] = { &pi, NULL };
 	struct device_node *np = ofdev->dev.of_node;
+	struct resource *res;
 
 	/* Allocate DWC SATA device */
 	host = ata_host_alloc_pinfo(&ofdev->dev, ppi, SATA_DWC_MAX_PORTS);
@@ -1201,57 +1223,33 @@ static int sata_dwc_probe(struct platfor
 	host->private_data = hsdev;
 
 	/* Ioremap SATA registers */
-	base = of_iomap(np, 0);
-	if (!base) {
+	res = platform_get_resource(ofdev, IORESOURCE_MEM, 0);
+	base = devm_ioremap_resource(&ofdev->dev, res);
+	if (IS_ERR(base)) {
 		dev_err(&ofdev->dev,
 			"ioremap failed for SATA register address\n");
-		return -ENODEV;
+		return PTR_ERR(base);
 	}
-	hsdev->reg_base = base;
 	dev_dbg(&ofdev->dev, "ioremap done for SATA register address\n");
 
 	/* Synopsys DWC SATA specific Registers */
-	hsdev->sata_dwc_regs = (void *__iomem)(base + SATA_DWC_REG_OFFSET);
+	hsdev->sata_dwc_regs = base + SATA_DWC_REG_OFFSET;
+	hsdev->dmadr = res->start + SATA_DWC_REG_OFFSET + offsetof(struct sata_dwc_regs, dmadr);
 
 	/* Setup port */
 	host->ports[0]->ioaddr.cmd_addr = base;
 	host->ports[0]->ioaddr.scr_addr = base + SATA_DWC_SCR_OFFSET;
-	host_pvt.scr_addr_sstatus = base + SATA_DWC_SCR_OFFSET;
-	sata_dwc_setup_port(&host->ports[0]->ioaddr, (unsigned long)base);
+	sata_dwc_setup_port(&host->ports[0]->ioaddr, base);
 
 	/* Read the ID and Version Registers */
-	idr = in_le32(&hsdev->sata_dwc_regs->idr);
-	versionr = in_le32(&hsdev->sata_dwc_regs->versionr);
+	idr = sata_dwc_readl(&hsdev->sata_dwc_regs->idr);
+	versionr = sata_dwc_readl(&hsdev->sata_dwc_regs->versionr);
 	dev_notice(&ofdev->dev, "id %d, controller version %c.%c%c\n",
 		   idr, ver[0], ver[1], ver[2]);
 
-	/* Get SATA DMA interrupt number */
-	hsdev->dma->irq = irq_of_parse_and_map(np, 1);
-	if (hsdev->dma->irq == NO_IRQ) {
-		dev_err(&ofdev->dev, "no SATA DMA irq\n");
-		err = -ENODEV;
-		goto error_iomap;
-	}
-
-	/* Get physical SATA DMA register base address */
-	hsdev->dma->regs = of_iomap(np, 1);
-	if (!hsdev->dma->regs) {
-		dev_err(&ofdev->dev,
-			"ioremap failed for AHBDMA register address\n");
-		err = -ENODEV;
-		goto error_iomap;
-	}
-
 	/* Save dev for later use in dev_xxx() routines */
 	hsdev->dev = &ofdev->dev;
 
-	hsdev->dma->dev = &ofdev->dev;
-
-	/* Initialize AHB DMAC */
-	err = dw_dma_probe(hsdev->dma, NULL);
-	if (err)
-		goto error_dma_iomap;
-
 	/* Enable SATA Interrupts */
 	sata_dwc_enable_interrupts(hsdev);
 
@@ -1263,6 +1261,25 @@ static int sata_dwc_probe(struct platfor
 		goto error_out;
 	}
 
+#ifdef CONFIG_SATA_DWC_OLD_DMA
+	if (!of_find_property(np, "dmas", NULL)) {
+		err = sata_dwc_dma_init_old(ofdev, hsdev);
+		if (err)
+			goto error_out;
+	}
+#endif
+
+	hsdev->phy = devm_phy_optional_get(hsdev->dev, "sata-phy");
+	if (IS_ERR(hsdev->phy)) {
+		err = PTR_ERR(hsdev->phy);
+		hsdev->phy = NULL;
+		goto error_out;
+	}
+
+	err = phy_init(hsdev->phy);
+	if (err)
+		goto error_out;
+
 	/*
 	 * Now, register with libATA core, this will also initiate the
 	 * device discovery process, invoking our port_start() handler &
@@ -1276,12 +1293,7 @@ static int sata_dwc_probe(struct platfor
 	return 0;
 
 error_out:
-	/* Free SATA DMA resources */
-	dw_dma_remove(hsdev->dma);
-error_dma_iomap:
-	iounmap(hsdev->dma->regs);
-error_iomap:
-	iounmap(base);
+	phy_exit(hsdev->phy);
 	return err;
 }
 
@@ -1293,11 +1305,13 @@ static int sata_dwc_remove(struct platfo
 
 	ata_host_detach(host);
 
+	phy_exit(hsdev->phy);
+
+#ifdef CONFIG_SATA_DWC_OLD_DMA
 	/* Free SATA DMA resources */
-	dw_dma_remove(hsdev->dma);
+	sata_dwc_dma_exit_old(hsdev);
+#endif
 
-	iounmap(hsdev->dma->regs);
-	iounmap(hsdev->reg_base);
 	dev_dbg(&ofdev->dev, "done\n");
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/ata/sata_highbank.c linux-libre-4.7-gnu/drivers/ata/sata_highbank.c
--- linux-libre-4.6-gnu/drivers/ata/sata_highbank.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/ata/sata_highbank.c	2016-07-24 15:23:50.000000000 -0400
@@ -197,7 +197,7 @@ static void highbank_set_em_messages(str
 
 	for (i = 0; i < SGPIO_PINS; i++) {
 		err = of_get_named_gpio(np, "calxeda,sgpio-gpio", i);
-		if (IS_ERR_VALUE(err))
+		if (err < 0)
 			return;
 
 		pdata->sgpio_gpio[i] = err;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/ata/sata_mv.c linux-libre-4.7-gnu/drivers/ata/sata_mv.c
--- linux-libre-4.6-gnu/drivers/ata/sata_mv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/ata/sata_mv.c	2016-07-24 15:23:50.000000000 -0400
@@ -986,7 +986,7 @@ static inline void mv_write_cached_reg(v
 		 * Looks like a lot of fuss, but it avoids an unnecessary
 		 * +1 usec read-after-write delay for unaffected registers.
 		 */
-		laddr = (long)addr & 0xffff;
+		laddr = (unsigned long)addr & 0xffff;
 		if (laddr >= 0x300 && laddr <= 0x33c) {
 			laddr &= 0x000f;
 			if (laddr == 0x4 || laddr == 0xc) {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/atm/firestream.c linux-libre-4.7-gnu/drivers/atm/firestream.c
--- linux-libre-4.6-gnu/drivers/atm/firestream.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/atm/firestream.c	2016-07-24 15:23:50.000000000 -0400
@@ -181,13 +181,17 @@ static char *res_strings[] = {
 	"reserved 27", 
 	"reserved 28", 
 	"reserved 29", 
-	"reserved 30", 
+	"reserved 30", /* FIXME: The strings between 30-40 might be wrong. */
 	"reassembly abort: no buffers", 
 	"receive buffer overflow", 
 	"change in GFC", 
 	"receive buffer full", 
 	"low priority discard - no receive descriptor", 
 	"low priority discard - missing end of packet", 
+	"reserved 37",
+	"reserved 38",
+	"reserved 39",
+	"reseverd 40",
 	"reserved 41", 
 	"reserved 42", 
 	"reserved 43", 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/atm/iphase.c linux-libre-4.7-gnu/drivers/atm/iphase.c
--- linux-libre-4.6-gnu/drivers/atm/iphase.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/atm/iphase.c	2016-07-24 15:23:50.000000000 -0400
@@ -1128,7 +1128,7 @@ static int rx_pkt(struct atm_dev *dev)
 	/* make the ptr point to the corresponding buffer desc entry */  
 	buf_desc_ptr += desc;	  
         if (!desc || (desc > iadev->num_rx_desc) || 
-                      ((buf_desc_ptr->vc_index & 0xffff) > iadev->num_vc)) { 
+                      ((buf_desc_ptr->vc_index & 0xffff) >= iadev->num_vc)) {
             free_desc(dev, desc);
             IF_ERR(printk("IA: bad descriptor desc = %d \n", desc);)
             return -1;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/base/devcoredump.c linux-libre-4.7-gnu/drivers/base/devcoredump.c
--- linux-libre-4.6-gnu/drivers/base/devcoredump.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/base/devcoredump.c	2016-07-24 15:23:50.000000000 -0400
@@ -4,6 +4,7 @@
  * GPL LICENSE SUMMARY
  *
  * Copyright(c) 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2015 Intel Deutschland GmbH
  *
  * 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
@@ -41,12 +42,12 @@ static bool devcd_disabled;
 
 struct devcd_entry {
 	struct device devcd_dev;
-	const void *data;
+	void *data;
 	size_t datalen;
 	struct module *owner;
 	ssize_t (*read)(char *buffer, loff_t offset, size_t count,
-			const void *data, size_t datalen);
-	void (*free)(const void *data);
+			void *data, size_t datalen);
+	void (*free)(void *data);
 	struct delayed_work del_wk;
 	struct device *failing_dev;
 };
@@ -174,7 +175,7 @@ static struct class devcd_class = {
 };
 
 static ssize_t devcd_readv(char *buffer, loff_t offset, size_t count,
-			   const void *data, size_t datalen)
+			   void *data, size_t datalen)
 {
 	if (offset > datalen)
 		return -EINVAL;
@@ -188,6 +189,11 @@ static ssize_t devcd_readv(char *buffer,
 	return count;
 }
 
+static void devcd_freev(void *data)
+{
+	vfree(data);
+}
+
 /**
  * dev_coredumpv - create device coredump with vmalloc data
  * @dev: the struct device for the crashed device
@@ -198,10 +204,10 @@ static ssize_t devcd_readv(char *buffer,
  * This function takes ownership of the vmalloc'ed data and will free
  * it when it is no longer used. See dev_coredumpm() for more information.
  */
-void dev_coredumpv(struct device *dev, const void *data, size_t datalen,
+void dev_coredumpv(struct device *dev, void *data, size_t datalen,
 		   gfp_t gfp)
 {
-	dev_coredumpm(dev, NULL, data, datalen, gfp, devcd_readv, vfree);
+	dev_coredumpm(dev, NULL, data, datalen, gfp, devcd_readv, devcd_freev);
 }
 EXPORT_SYMBOL_GPL(dev_coredumpv);
 
@@ -213,6 +219,44 @@ static int devcd_match_failing(struct de
 }
 
 /**
+ * devcd_free_sgtable - free all the memory of the given scatterlist table
+ * (i.e. both pages and scatterlist instances)
+ * NOTE: if two tables allocated with devcd_alloc_sgtable and then chained
+ * using the sg_chain function then that function should be called only once
+ * on the chained table
+ * @table: pointer to sg_table to free
+ */
+static void devcd_free_sgtable(void *data)
+{
+	_devcd_free_sgtable(data);
+}
+
+/**
+ * devcd_read_from_table - copy data from sg_table to a given buffer
+ * and return the number of bytes read
+ * @buffer: the buffer to copy the data to it
+ * @buf_len: the length of the buffer
+ * @data: the scatterlist table to copy from
+ * @offset: start copy from @offset@ bytes from the head of the data
+ *	in the given scatterlist
+ * @data_len: the length of the data in the sg_table
+ */
+static ssize_t devcd_read_from_sgtable(char *buffer, loff_t offset,
+				       size_t buf_len, void *data,
+				       size_t data_len)
+{
+	struct scatterlist *table = data;
+
+	if (offset > data_len)
+		return -EINVAL;
+
+	if (offset + buf_len > data_len)
+		buf_len = data_len - offset;
+	return sg_pcopy_to_buffer(table, sg_nents(table), buffer, buf_len,
+				  offset);
+}
+
+/**
  * dev_coredumpm - create device coredump with read/free methods
  * @dev: the struct device for the crashed device
  * @owner: the module that contains the read/free functions, use %THIS_MODULE
@@ -228,10 +272,10 @@ static int devcd_match_failing(struct de
  * function will be called to free the data.
  */
 void dev_coredumpm(struct device *dev, struct module *owner,
-		   const void *data, size_t datalen, gfp_t gfp,
+		   void *data, size_t datalen, gfp_t gfp,
 		   ssize_t (*read)(char *buffer, loff_t offset, size_t count,
-				   const void *data, size_t datalen),
-		   void (*free)(const void *data))
+				   void *data, size_t datalen),
+		   void (*free)(void *data))
 {
 	static atomic_t devcd_count = ATOMIC_INIT(0);
 	struct devcd_entry *devcd;
@@ -291,6 +335,27 @@ void dev_coredumpm(struct device *dev, s
 }
 EXPORT_SYMBOL_GPL(dev_coredumpm);
 
+/**
+ * dev_coredumpmsg - create device coredump that uses scatterlist as data
+ * parameter
+ * @dev: the struct device for the crashed device
+ * @table: the dump data
+ * @datalen: length of the data
+ * @gfp: allocation flags
+ *
+ * Creates a new device coredump for the given device. If a previous one hasn't
+ * been read yet, the new coredump is discarded. The data lifetime is determined
+ * by the device coredump framework and when it is no longer needed
+ * it will free the data.
+ */
+void dev_coredumpsg(struct device *dev, struct scatterlist *table,
+		    size_t datalen, gfp_t gfp)
+{
+	dev_coredumpm(dev, NULL, table, datalen, gfp, devcd_read_from_sgtable,
+		      devcd_free_sgtable);
+}
+EXPORT_SYMBOL_GPL(dev_coredumpsg);
+
 static int __init devcoredump_init(void)
 {
 	return class_register(&devcd_class);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/base/isa.c linux-libre-4.7-gnu/drivers/base/isa.c
--- linux-libre-4.6-gnu/drivers/base/isa.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/base/isa.c	2016-07-24 15:23:50.000000000 -0400
@@ -180,4 +180,4 @@ static int __init isa_bus_init(void)
 	return error;
 }
 
-device_initcall(isa_bus_init);
+postcore_initcall(isa_bus_init);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/base/Makefile linux-libre-4.7-gnu/drivers/base/Makefile
--- linux-libre-4.6-gnu/drivers/base/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/base/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -10,7 +10,7 @@ obj-$(CONFIG_DMA_CMA) += dma-contiguous.
 obj-y			+= power/
 obj-$(CONFIG_HAS_DMA)	+= dma-mapping.o
 obj-$(CONFIG_HAVE_GENERIC_DMA_COHERENT) += dma-coherent.o
-obj-$(CONFIG_ISA)	+= isa.o
+obj-$(CONFIG_ISA_BUS_API)	+= isa.o
 obj-$(CONFIG_FW_LOADER)	+= firmware_class.o
 obj-$(CONFIG_NUMA)	+= node.o
 obj-$(CONFIG_MEMORY_HOTPLUG_SPARSE) += memory.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/base/module.c linux-libre-4.7-gnu/drivers/base/module.c
--- linux-libre-4.6-gnu/drivers/base/module.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/base/module.c	2016-07-24 15:23:50.000000000 -0400
@@ -24,10 +24,12 @@ static char *make_driver_name(struct dev
 
 static void module_create_drivers_dir(struct module_kobject *mk)
 {
-	if (!mk || mk->drivers_dir)
-		return;
+	static DEFINE_MUTEX(drivers_dir_mutex);
 
-	mk->drivers_dir = kobject_create_and_add("drivers", &mk->kobj);
+	mutex_lock(&drivers_dir_mutex);
+	if (mk && !mk->drivers_dir)
+		mk->drivers_dir = kobject_create_and_add("drivers", &mk->kobj);
+	mutex_unlock(&drivers_dir_mutex);
 }
 
 void module_add_driver(struct module *mod, struct device_driver *drv)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/base/platform.c linux-libre-4.7-gnu/drivers/base/platform.c
--- linux-libre-4.6-gnu/drivers/base/platform.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/base/platform.c	2016-07-24 15:23:50.000000000 -0400
@@ -322,16 +322,16 @@ EXPORT_SYMBOL_GPL(platform_device_add_da
 /**
  * platform_device_add_properties - add built-in properties to a platform device
  * @pdev: platform device to add properties to
- * @pset: properties to add
+ * @properties: null terminated array of properties to add
  *
- * The function will take deep copy of the properties in @pset and attach
- * the copy to the platform device. The memory associated with properties
- * will be freed when the platform device is released.
+ * The function will take deep copy of @properties and attach the copy to the
+ * platform device. The memory associated with properties will be freed when the
+ * platform device is released.
  */
 int platform_device_add_properties(struct platform_device *pdev,
-				   const struct property_set *pset)
+				   struct property_entry *properties)
 {
-	return device_add_property_set(&pdev->dev, pset);
+	return device_add_properties(&pdev->dev, properties);
 }
 EXPORT_SYMBOL_GPL(platform_device_add_properties);
 
@@ -447,7 +447,7 @@ void platform_device_del(struct platform
 				release_resource(r);
 		}
 
-		device_remove_property_set(&pdev->dev);
+		device_remove_properties(&pdev->dev);
 	}
 }
 EXPORT_SYMBOL_GPL(platform_device_del);
@@ -526,8 +526,9 @@ struct platform_device *platform_device_
 	if (ret)
 		goto err;
 
-	if (pdevinfo->pset) {
-		ret = platform_device_add_properties(pdev, pdevinfo->pset);
+	if (pdevinfo->properties) {
+		ret = platform_device_add_properties(pdev,
+						     pdevinfo->properties);
 		if (ret)
 			goto err;
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/base/power/clock_ops.c linux-libre-4.7-gnu/drivers/base/power/clock_ops.c
--- linux-libre-4.6-gnu/drivers/base/power/clock_ops.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/base/power/clock_ops.c	2016-07-24 15:23:50.000000000 -0400
@@ -159,7 +159,7 @@ int of_pm_clk_add_clks(struct device *de
 
 	count = of_count_phandle_with_args(dev->of_node, "clocks",
 					   "#clock-cells");
-	if (count == 0)
+	if (count <= 0)
 		return -ENODEV;
 
 	clks = kcalloc(count, sizeof(*clks), GFP_KERNEL);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/base/power/domain.c linux-libre-4.7-gnu/drivers/base/power/domain.c
--- linux-libre-4.6-gnu/drivers/base/power/domain.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/base/power/domain.c	2016-07-24 15:23:50.000000000 -0400
@@ -229,17 +229,6 @@ static int genpd_poweron(struct generic_
 	return ret;
 }
 
-static int genpd_save_dev(struct generic_pm_domain *genpd, struct device *dev)
-{
-	return GENPD_DEV_CALLBACK(genpd, int, save_state, dev);
-}
-
-static int genpd_restore_dev(struct generic_pm_domain *genpd,
-			struct device *dev)
-{
-	return GENPD_DEV_CALLBACK(genpd, int, restore_state, dev);
-}
-
 static int genpd_dev_pm_qos_notifier(struct notifier_block *nb,
 				     unsigned long val, void *ptr)
 {
@@ -372,17 +361,63 @@ static void genpd_power_off_work_fn(stru
 }
 
 /**
- * pm_genpd_runtime_suspend - Suspend a device belonging to I/O PM domain.
+ * __genpd_runtime_suspend - walk the hierarchy of ->runtime_suspend() callbacks
+ * @dev: Device to handle.
+ */
+static int __genpd_runtime_suspend(struct device *dev)
+{
+	int (*cb)(struct device *__dev);
+
+	if (dev->type && dev->type->pm)
+		cb = dev->type->pm->runtime_suspend;
+	else if (dev->class && dev->class->pm)
+		cb = dev->class->pm->runtime_suspend;
+	else if (dev->bus && dev->bus->pm)
+		cb = dev->bus->pm->runtime_suspend;
+	else
+		cb = NULL;
+
+	if (!cb && dev->driver && dev->driver->pm)
+		cb = dev->driver->pm->runtime_suspend;
+
+	return cb ? cb(dev) : 0;
+}
+
+/**
+ * __genpd_runtime_resume - walk the hierarchy of ->runtime_resume() callbacks
+ * @dev: Device to handle.
+ */
+static int __genpd_runtime_resume(struct device *dev)
+{
+	int (*cb)(struct device *__dev);
+
+	if (dev->type && dev->type->pm)
+		cb = dev->type->pm->runtime_resume;
+	else if (dev->class && dev->class->pm)
+		cb = dev->class->pm->runtime_resume;
+	else if (dev->bus && dev->bus->pm)
+		cb = dev->bus->pm->runtime_resume;
+	else
+		cb = NULL;
+
+	if (!cb && dev->driver && dev->driver->pm)
+		cb = dev->driver->pm->runtime_resume;
+
+	return cb ? cb(dev) : 0;
+}
+
+/**
+ * genpd_runtime_suspend - Suspend a device belonging to I/O PM domain.
  * @dev: Device to suspend.
  *
  * Carry out a runtime suspend of a device under the assumption that its
  * pm_domain field points to the domain member of an object of type
  * struct generic_pm_domain representing a PM domain consisting of I/O devices.
  */
-static int pm_genpd_runtime_suspend(struct device *dev)
+static int genpd_runtime_suspend(struct device *dev)
 {
 	struct generic_pm_domain *genpd;
-	bool (*stop_ok)(struct device *__dev);
+	bool (*suspend_ok)(struct device *__dev);
 	struct gpd_timing_data *td = &dev_gpd_data(dev)->td;
 	bool runtime_pm = pm_runtime_enabled(dev);
 	ktime_t time_start;
@@ -401,21 +436,21 @@ static int pm_genpd_runtime_suspend(stru
 	 * runtime PM is disabled. Under these circumstances, we shall skip
 	 * validating/measuring the PM QoS latency.
 	 */
-	stop_ok = genpd->gov ? genpd->gov->stop_ok : NULL;
-	if (runtime_pm && stop_ok && !stop_ok(dev))
+	suspend_ok = genpd->gov ? genpd->gov->suspend_ok : NULL;
+	if (runtime_pm && suspend_ok && !suspend_ok(dev))
 		return -EBUSY;
 
 	/* Measure suspend latency. */
 	if (runtime_pm)
 		time_start = ktime_get();
 
-	ret = genpd_save_dev(genpd, dev);
+	ret = __genpd_runtime_suspend(dev);
 	if (ret)
 		return ret;
 
 	ret = genpd_stop_dev(genpd, dev);
 	if (ret) {
-		genpd_restore_dev(genpd, dev);
+		__genpd_runtime_resume(dev);
 		return ret;
 	}
 
@@ -446,14 +481,14 @@ static int pm_genpd_runtime_suspend(stru
 }
 
 /**
- * pm_genpd_runtime_resume - Resume a device belonging to I/O PM domain.
+ * genpd_runtime_resume - Resume a device belonging to I/O PM domain.
  * @dev: Device to resume.
  *
  * Carry out a runtime resume of a device under the assumption that its
  * pm_domain field points to the domain member of an object of type
  * struct generic_pm_domain representing a PM domain consisting of I/O devices.
  */
-static int pm_genpd_runtime_resume(struct device *dev)
+static int genpd_runtime_resume(struct device *dev)
 {
 	struct generic_pm_domain *genpd;
 	struct gpd_timing_data *td = &dev_gpd_data(dev)->td;
@@ -491,7 +526,7 @@ static int pm_genpd_runtime_resume(struc
 	if (ret)
 		goto err_poweroff;
 
-	ret = genpd_restore_dev(genpd, dev);
+	ret = __genpd_runtime_resume(dev);
 	if (ret)
 		goto err_stop;
 
@@ -695,15 +730,6 @@ static int pm_genpd_prepare(struct devic
 	 * at this point and a system wakeup event should be reported if it's
 	 * set up to wake up the system from sleep states.
 	 */
-	pm_runtime_get_noresume(dev);
-	if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
-		pm_wakeup_event(dev, 0);
-
-	if (pm_wakeup_pending()) {
-		pm_runtime_put(dev);
-		return -EBUSY;
-	}
-
 	if (resume_needed(dev, genpd))
 		pm_runtime_resume(dev);
 
@@ -716,10 +742,8 @@ static int pm_genpd_prepare(struct devic
 
 	mutex_unlock(&genpd->lock);
 
-	if (genpd->suspend_power_off) {
-		pm_runtime_put_noidle(dev);
+	if (genpd->suspend_power_off)
 		return 0;
-	}
 
 	/*
 	 * The PM domain must be in the GPD_STATE_ACTIVE state at this point,
@@ -741,7 +765,6 @@ static int pm_genpd_prepare(struct devic
 		pm_runtime_enable(dev);
 	}
 
-	pm_runtime_put(dev);
 	return ret;
 }
 
@@ -1427,54 +1450,6 @@ out:
 }
 EXPORT_SYMBOL_GPL(pm_genpd_remove_subdomain);
 
-/* Default device callbacks for generic PM domains. */
-
-/**
- * pm_genpd_default_save_state - Default "save device state" for PM domains.
- * @dev: Device to handle.
- */
-static int pm_genpd_default_save_state(struct device *dev)
-{
-	int (*cb)(struct device *__dev);
-
-	if (dev->type && dev->type->pm)
-		cb = dev->type->pm->runtime_suspend;
-	else if (dev->class && dev->class->pm)
-		cb = dev->class->pm->runtime_suspend;
-	else if (dev->bus && dev->bus->pm)
-		cb = dev->bus->pm->runtime_suspend;
-	else
-		cb = NULL;
-
-	if (!cb && dev->driver && dev->driver->pm)
-		cb = dev->driver->pm->runtime_suspend;
-
-	return cb ? cb(dev) : 0;
-}
-
-/**
- * pm_genpd_default_restore_state - Default PM domains "restore device state".
- * @dev: Device to handle.
- */
-static int pm_genpd_default_restore_state(struct device *dev)
-{
-	int (*cb)(struct device *__dev);
-
-	if (dev->type && dev->type->pm)
-		cb = dev->type->pm->runtime_resume;
-	else if (dev->class && dev->class->pm)
-		cb = dev->class->pm->runtime_resume;
-	else if (dev->bus && dev->bus->pm)
-		cb = dev->bus->pm->runtime_resume;
-	else
-		cb = NULL;
-
-	if (!cb && dev->driver && dev->driver->pm)
-		cb = dev->driver->pm->runtime_resume;
-
-	return cb ? cb(dev) : 0;
-}
-
 /**
  * pm_genpd_init - Initialize a generic I/O PM domain object.
  * @genpd: PM domain object to initialize.
@@ -1498,8 +1473,8 @@ void pm_genpd_init(struct generic_pm_dom
 	genpd->device_count = 0;
 	genpd->max_off_time_ns = -1;
 	genpd->max_off_time_changed = true;
-	genpd->domain.ops.runtime_suspend = pm_genpd_runtime_suspend;
-	genpd->domain.ops.runtime_resume = pm_genpd_runtime_resume;
+	genpd->domain.ops.runtime_suspend = genpd_runtime_suspend;
+	genpd->domain.ops.runtime_resume = genpd_runtime_resume;
 	genpd->domain.ops.prepare = pm_genpd_prepare;
 	genpd->domain.ops.suspend = pm_genpd_suspend;
 	genpd->domain.ops.suspend_late = pm_genpd_suspend_late;
@@ -1520,8 +1495,6 @@ void pm_genpd_init(struct generic_pm_dom
 	genpd->domain.ops.restore_early = pm_genpd_resume_early;
 	genpd->domain.ops.restore = pm_genpd_resume;
 	genpd->domain.ops.complete = pm_genpd_complete;
-	genpd->dev_ops.save_state = pm_genpd_default_save_state;
-	genpd->dev_ops.restore_state = pm_genpd_default_restore_state;
 
 	if (genpd->flags & GENPD_FLAG_PM_CLK) {
 		genpd->dev_ops.stop = pm_clk_suspend;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/base/power/domain_governor.c linux-libre-4.7-gnu/drivers/base/power/domain_governor.c
--- linux-libre-4.6-gnu/drivers/base/power/domain_governor.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/base/power/domain_governor.c	2016-07-24 15:23:50.000000000 -0400
@@ -37,10 +37,10 @@ static int dev_update_qos_constraint(str
 }
 
 /**
- * default_stop_ok - Default PM domain governor routine for stopping devices.
+ * default_suspend_ok - Default PM domain governor routine to suspend devices.
  * @dev: Device to check.
  */
-static bool default_stop_ok(struct device *dev)
+static bool default_suspend_ok(struct device *dev)
 {
 	struct gpd_timing_data *td = &dev_gpd_data(dev)->td;
 	unsigned long flags;
@@ -51,13 +51,13 @@ static bool default_stop_ok(struct devic
 	spin_lock_irqsave(&dev->power.lock, flags);
 
 	if (!td->constraint_changed) {
-		bool ret = td->cached_stop_ok;
+		bool ret = td->cached_suspend_ok;
 
 		spin_unlock_irqrestore(&dev->power.lock, flags);
 		return ret;
 	}
 	td->constraint_changed = false;
-	td->cached_stop_ok = false;
+	td->cached_suspend_ok = false;
 	td->effective_constraint_ns = -1;
 	constraint_ns = __dev_pm_qos_read_value(dev);
 
@@ -83,13 +83,13 @@ static bool default_stop_ok(struct devic
 			return false;
 	}
 	td->effective_constraint_ns = constraint_ns;
-	td->cached_stop_ok = constraint_ns >= 0;
+	td->cached_suspend_ok = constraint_ns >= 0;
 
 	/*
 	 * The children have been suspended already, so we don't need to take
-	 * their stop latencies into account here.
+	 * their suspend latencies into account here.
 	 */
-	return td->cached_stop_ok;
+	return td->cached_suspend_ok;
 }
 
 /**
@@ -150,7 +150,7 @@ static bool __default_power_down_ok(stru
 		 */
 		td = &to_gpd_data(pdd)->td;
 		constraint_ns = td->effective_constraint_ns;
-		/* default_stop_ok() need not be called before us. */
+		/* default_suspend_ok() need not be called before us. */
 		if (constraint_ns < 0) {
 			constraint_ns = dev_pm_qos_read_value(pdd->dev);
 			constraint_ns *= NSEC_PER_USEC;
@@ -227,7 +227,7 @@ static bool always_on_power_down_ok(stru
 }
 
 struct dev_power_governor simple_qos_governor = {
-	.stop_ok = default_stop_ok,
+	.suspend_ok = default_suspend_ok,
 	.power_down_ok = default_power_down_ok,
 };
 
@@ -236,5 +236,5 @@ struct dev_power_governor simple_qos_gov
  */
 struct dev_power_governor pm_domain_always_on_gov = {
 	.power_down_ok = always_on_power_down_ok,
-	.stop_ok = default_stop_ok,
+	.suspend_ok = default_suspend_ok,
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/base/power/main.c linux-libre-4.7-gnu/drivers/base/power/main.c
--- linux-libre-4.6-gnu/drivers/base/power/main.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/base/power/main.c	2016-07-24 15:23:50.000000000 -0400
@@ -1267,14 +1267,15 @@ int dpm_suspend_late(pm_message_t state)
 		error = device_suspend_late(dev);
 
 		mutex_lock(&dpm_list_mtx);
+		if (!list_empty(&dev->power.entry))
+			list_move(&dev->power.entry, &dpm_late_early_list);
+
 		if (error) {
 			pm_dev_err(dev, state, " late", error);
 			dpm_save_failed_dev(dev_name(dev));
 			put_device(dev);
 			break;
 		}
-		if (!list_empty(&dev->power.entry))
-			list_move(&dev->power.entry, &dpm_late_early_list);
 		put_device(dev);
 
 		if (async_error)
@@ -1556,7 +1557,6 @@ int dpm_suspend(pm_message_t state)
 static int device_prepare(struct device *dev, pm_message_t state)
 {
 	int (*callback)(struct device *) = NULL;
-	char *info = NULL;
 	int ret = 0;
 
 	if (dev->power.syscore)
@@ -1579,24 +1579,17 @@ static int device_prepare(struct device
 		goto unlock;
 	}
 
-	if (dev->pm_domain) {
-		info = "preparing power domain ";
+	if (dev->pm_domain)
 		callback = dev->pm_domain->ops.prepare;
-	} else if (dev->type && dev->type->pm) {
-		info = "preparing type ";
+	else if (dev->type && dev->type->pm)
 		callback = dev->type->pm->prepare;
-	} else if (dev->class && dev->class->pm) {
-		info = "preparing class ";
+	else if (dev->class && dev->class->pm)
 		callback = dev->class->pm->prepare;
-	} else if (dev->bus && dev->bus->pm) {
-		info = "preparing bus ";
+	else if (dev->bus && dev->bus->pm)
 		callback = dev->bus->pm->prepare;
-	}
 
-	if (!callback && dev->driver && dev->driver->pm) {
-		info = "preparing driver ";
+	if (!callback && dev->driver && dev->driver->pm)
 		callback = dev->driver->pm->prepare;
-	}
 
 	if (callback)
 		ret = callback(dev);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/base/power/opp/core.c linux-libre-4.7-gnu/drivers/base/power/opp/core.c
--- linux-libre-4.6-gnu/drivers/base/power/opp/core.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/base/power/opp/core.c	2016-07-24 15:23:50.000000000 -0400
@@ -18,7 +18,6 @@
 #include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/device.h>
-#include <linux/of.h>
 #include <linux/export.h>
 #include <linux/regulator/consumer.h>
 
@@ -29,7 +28,7 @@
  * from here, with each opp_table containing the list of opps it supports in
  * various states of availability.
  */
-static LIST_HEAD(opp_tables);
+LIST_HEAD(opp_tables);
 /* Lock to allow exclusive modification to the device and opp lists */
 DEFINE_MUTEX(opp_table_lock);
 
@@ -53,26 +52,6 @@ static struct opp_device *_find_opp_dev(
 	return NULL;
 }
 
-static struct opp_table *_managed_opp(const struct device_node *np)
-{
-	struct opp_table *opp_table;
-
-	list_for_each_entry_rcu(opp_table, &opp_tables, node) {
-		if (opp_table->np == np) {
-			/*
-			 * Multiple devices can point to the same OPP table and
-			 * so will have same node-pointer, np.
-			 *
-			 * But the OPPs will be considered as shared only if the
-			 * OPP table contains a "opp-shared" property.
-			 */
-			return opp_table->shared_opp ? opp_table : NULL;
-		}
-	}
-
-	return NULL;
-}
-
 /**
  * _find_opp_table() - find opp_table struct using device pointer
  * @dev:	device pointer used to lookup OPP table
@@ -757,7 +736,6 @@ static struct opp_table *_add_opp_table(
 {
 	struct opp_table *opp_table;
 	struct opp_device *opp_dev;
-	struct device_node *np;
 	int ret;
 
 	/* Check for existing table for 'dev' first */
@@ -781,20 +759,7 @@ static struct opp_table *_add_opp_table(
 		return NULL;
 	}
 
-	/*
-	 * Only required for backward compatibility with v1 bindings, but isn't
-	 * harmful for other cases. And so we do it unconditionally.
-	 */
-	np = of_node_get(dev->of_node);
-	if (np) {
-		u32 val;
-
-		if (!of_property_read_u32(np, "clock-latency", &val))
-			opp_table->clock_latency_ns_max = val;
-		of_property_read_u32(np, "voltage-tolerance",
-				     &opp_table->voltage_tolerance_v1);
-		of_node_put(np);
-	}
+	_of_init_opp_table(opp_table, dev);
 
 	/* Set regulator to a non-NULL error value */
 	opp_table->regulator = ERR_PTR(-ENXIO);
@@ -890,8 +855,8 @@ static void _kfree_opp_rcu(struct rcu_he
  * It is assumed that the caller holds required mutex for an RCU updater
  * strategy.
  */
-static void _opp_remove(struct opp_table *opp_table,
-			struct dev_pm_opp *opp, bool notify)
+void _opp_remove(struct opp_table *opp_table, struct dev_pm_opp *opp,
+		 bool notify)
 {
 	/*
 	 * Notify the changes in the availability of the operable
@@ -952,8 +917,8 @@ unlock:
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_remove);
 
-static struct dev_pm_opp *_allocate_opp(struct device *dev,
-					struct opp_table **opp_table)
+struct dev_pm_opp *_allocate_opp(struct device *dev,
+				 struct opp_table **opp_table)
 {
 	struct dev_pm_opp *opp;
 
@@ -989,8 +954,8 @@ static bool _opp_supported_by_regulators
 	return true;
 }
 
-static int _opp_add(struct device *dev, struct dev_pm_opp *new_opp,
-		    struct opp_table *opp_table)
+int _opp_add(struct device *dev, struct dev_pm_opp *new_opp,
+	     struct opp_table *opp_table)
 {
 	struct dev_pm_opp *opp;
 	struct list_head *head = &opp_table->opp_list;
@@ -1066,8 +1031,8 @@ static int _opp_add(struct device *dev,
  *		Duplicate OPPs (both freq and volt are same) and !opp->available
  * -ENOMEM	Memory allocation failure
  */
-static int _opp_add_v1(struct device *dev, unsigned long freq, long u_volt,
-		       bool dynamic)
+int _opp_add_v1(struct device *dev, unsigned long freq, long u_volt,
+		bool dynamic)
 {
 	struct opp_table *opp_table;
 	struct dev_pm_opp *new_opp;
@@ -1112,83 +1077,6 @@ unlock:
 	return ret;
 }
 
-/* TODO: Support multiple regulators */
-static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev,
-			      struct opp_table *opp_table)
-{
-	u32 microvolt[3] = {0};
-	u32 val;
-	int count, ret;
-	struct property *prop = NULL;
-	char name[NAME_MAX];
-
-	/* Search for "opp-microvolt-<name>" */
-	if (opp_table->prop_name) {
-		snprintf(name, sizeof(name), "opp-microvolt-%s",
-			 opp_table->prop_name);
-		prop = of_find_property(opp->np, name, NULL);
-	}
-
-	if (!prop) {
-		/* Search for "opp-microvolt" */
-		sprintf(name, "opp-microvolt");
-		prop = of_find_property(opp->np, name, NULL);
-
-		/* Missing property isn't a problem, but an invalid entry is */
-		if (!prop)
-			return 0;
-	}
-
-	count = of_property_count_u32_elems(opp->np, name);
-	if (count < 0) {
-		dev_err(dev, "%s: Invalid %s property (%d)\n",
-			__func__, name, count);
-		return count;
-	}
-
-	/* There can be one or three elements here */
-	if (count != 1 && count != 3) {
-		dev_err(dev, "%s: Invalid number of elements in %s property (%d)\n",
-			__func__, name, count);
-		return -EINVAL;
-	}
-
-	ret = of_property_read_u32_array(opp->np, name, microvolt, count);
-	if (ret) {
-		dev_err(dev, "%s: error parsing %s: %d\n", __func__, name, ret);
-		return -EINVAL;
-	}
-
-	opp->u_volt = microvolt[0];
-
-	if (count == 1) {
-		opp->u_volt_min = opp->u_volt;
-		opp->u_volt_max = opp->u_volt;
-	} else {
-		opp->u_volt_min = microvolt[1];
-		opp->u_volt_max = microvolt[2];
-	}
-
-	/* Search for "opp-microamp-<name>" */
-	prop = NULL;
-	if (opp_table->prop_name) {
-		snprintf(name, sizeof(name), "opp-microamp-%s",
-			 opp_table->prop_name);
-		prop = of_find_property(opp->np, name, NULL);
-	}
-
-	if (!prop) {
-		/* Search for "opp-microamp" */
-		sprintf(name, "opp-microamp");
-		prop = of_find_property(opp->np, name, NULL);
-	}
-
-	if (prop && !of_property_read_u32(opp->np, name, &val))
-		opp->u_amp = val;
-
-	return 0;
-}
-
 /**
  * dev_pm_opp_set_supported_hw() - Set supported platforms
  * @dev: Device for which supported-hw has to be set.
@@ -1517,144 +1405,6 @@ unlock:
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_put_regulator);
 
-static bool _opp_is_supported(struct device *dev, struct opp_table *opp_table,
-			      struct device_node *np)
-{
-	unsigned int count = opp_table->supported_hw_count;
-	u32 version;
-	int ret;
-
-	if (!opp_table->supported_hw)
-		return true;
-
-	while (count--) {
-		ret = of_property_read_u32_index(np, "opp-supported-hw", count,
-						 &version);
-		if (ret) {
-			dev_warn(dev, "%s: failed to read opp-supported-hw property at index %d: %d\n",
-				 __func__, count, ret);
-			return false;
-		}
-
-		/* Both of these are bitwise masks of the versions */
-		if (!(version & opp_table->supported_hw[count]))
-			return false;
-	}
-
-	return true;
-}
-
-/**
- * _opp_add_static_v2() - Allocate static OPPs (As per 'v2' DT bindings)
- * @dev:	device for which we do this operation
- * @np:		device node
- *
- * This function adds an opp definition to the opp table and returns status. The
- * opp can be controlled using dev_pm_opp_enable/disable functions and may be
- * removed by dev_pm_opp_remove.
- *
- * Locking: The internal opp_table and opp structures are RCU protected.
- * Hence this function internally uses RCU updater strategy with mutex locks
- * to keep the integrity of the internal data structures. Callers should ensure
- * that this function is *NOT* called under RCU protection or in contexts where
- * mutex cannot be locked.
- *
- * Return:
- * 0		On success OR
- *		Duplicate OPPs (both freq and volt are same) and opp->available
- * -EEXIST	Freq are same and volt are different OR
- *		Duplicate OPPs (both freq and volt are same) and !opp->available
- * -ENOMEM	Memory allocation failure
- * -EINVAL	Failed parsing the OPP node
- */
-static int _opp_add_static_v2(struct device *dev, struct device_node *np)
-{
-	struct opp_table *opp_table;
-	struct dev_pm_opp *new_opp;
-	u64 rate;
-	u32 val;
-	int ret;
-
-	/* Hold our table modification lock here */
-	mutex_lock(&opp_table_lock);
-
-	new_opp = _allocate_opp(dev, &opp_table);
-	if (!new_opp) {
-		ret = -ENOMEM;
-		goto unlock;
-	}
-
-	ret = of_property_read_u64(np, "opp-hz", &rate);
-	if (ret < 0) {
-		dev_err(dev, "%s: opp-hz not found\n", __func__);
-		goto free_opp;
-	}
-
-	/* Check if the OPP supports hardware's hierarchy of versions or not */
-	if (!_opp_is_supported(dev, opp_table, np)) {
-		dev_dbg(dev, "OPP not supported by hardware: %llu\n", rate);
-		goto free_opp;
-	}
-
-	/*
-	 * Rate is defined as an unsigned long in clk API, and so casting
-	 * explicitly to its type. Must be fixed once rate is 64 bit
-	 * guaranteed in clk API.
-	 */
-	new_opp->rate = (unsigned long)rate;
-	new_opp->turbo = of_property_read_bool(np, "turbo-mode");
-
-	new_opp->np = np;
-	new_opp->dynamic = false;
-	new_opp->available = true;
-
-	if (!of_property_read_u32(np, "clock-latency-ns", &val))
-		new_opp->clock_latency_ns = val;
-
-	ret = opp_parse_supplies(new_opp, dev, opp_table);
-	if (ret)
-		goto free_opp;
-
-	ret = _opp_add(dev, new_opp, opp_table);
-	if (ret)
-		goto free_opp;
-
-	/* OPP to select on device suspend */
-	if (of_property_read_bool(np, "opp-suspend")) {
-		if (opp_table->suspend_opp) {
-			dev_warn(dev, "%s: Multiple suspend OPPs found (%lu %lu)\n",
-				 __func__, opp_table->suspend_opp->rate,
-				 new_opp->rate);
-		} else {
-			new_opp->suspend = true;
-			opp_table->suspend_opp = new_opp;
-		}
-	}
-
-	if (new_opp->clock_latency_ns > opp_table->clock_latency_ns_max)
-		opp_table->clock_latency_ns_max = new_opp->clock_latency_ns;
-
-	mutex_unlock(&opp_table_lock);
-
-	pr_debug("%s: turbo:%d rate:%lu uv:%lu uvmin:%lu uvmax:%lu latency:%lu\n",
-		 __func__, new_opp->turbo, new_opp->rate, new_opp->u_volt,
-		 new_opp->u_volt_min, new_opp->u_volt_max,
-		 new_opp->clock_latency_ns);
-
-	/*
-	 * Notify the changes in the availability of the operable
-	 * frequency/voltage list.
-	 */
-	srcu_notifier_call_chain(&opp_table->srcu_head, OPP_EVENT_ADD, new_opp);
-	return 0;
-
-free_opp:
-	_opp_remove(opp_table, new_opp, false);
-unlock:
-	mutex_unlock(&opp_table_lock);
-	return ret;
-}
-
 /**
  * dev_pm_opp_add()  - Add an OPP table from a table definitions
  * @dev:	device for which we do this operation
@@ -1842,21 +1592,11 @@ struct srcu_notifier_head *dev_pm_opp_ge
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_get_notifier);
 
-#ifdef CONFIG_OF
-/**
- * dev_pm_opp_of_remove_table() - Free OPP table entries created from static DT
- *				  entries
- * @dev:	device pointer used to lookup OPP table.
- *
- * Free OPPs created using static entries present in DT.
- *
- * Locking: The internal opp_table and opp structures are RCU protected.
- * Hence this function indirectly uses RCU updater strategy with mutex locks
- * to keep the integrity of the internal data structures. Callers should ensure
- * that this function is *NOT* called under RCU protection or in contexts where
- * mutex cannot be locked.
+/*
+ * Free OPPs either created using static entries present in DT or even the
+ * dynamically added entries based on remove_all param.
  */
-void dev_pm_opp_of_remove_table(struct device *dev)
+void _dev_pm_opp_remove_table(struct device *dev, bool remove_all)
 {
 	struct opp_table *opp_table;
 	struct dev_pm_opp *opp, *tmp;
@@ -1881,7 +1621,7 @@ void dev_pm_opp_of_remove_table(struct d
 	if (list_is_singular(&opp_table->dev_list)) {
 		/* Free static OPPs */
 		list_for_each_entry_safe(opp, tmp, &opp_table->opp_list, node) {
-			if (!opp->dynamic)
+			if (remove_all || !opp->dynamic)
 				_opp_remove(opp_table, opp, true);
 		}
 	} else {
@@ -1891,160 +1631,22 @@ void dev_pm_opp_of_remove_table(struct d
 unlock:
 	mutex_unlock(&opp_table_lock);
 }
-EXPORT_SYMBOL_GPL(dev_pm_opp_of_remove_table);
-
-/* Returns opp descriptor node for a device, caller must do of_node_put() */
-struct device_node *_of_get_opp_desc_node(struct device *dev)
-{
-	/*
-	 * TODO: Support for multiple OPP tables.
-	 *
-	 * There should be only ONE phandle present in "operating-points-v2"
-	 * property.
-	 */
-
-	return of_parse_phandle(dev->of_node, "operating-points-v2", 0);
-}
-
-/* Initializes OPP tables based on new bindings */
-static int _of_add_opp_table_v2(struct device *dev, struct device_node *opp_np)
-{
-	struct device_node *np;
-	struct opp_table *opp_table;
-	int ret = 0, count = 0;
-
-	mutex_lock(&opp_table_lock);
-
-	opp_table = _managed_opp(opp_np);
-	if (opp_table) {
-		/* OPPs are already managed */
-		if (!_add_opp_dev(dev, opp_table))
-			ret = -ENOMEM;
-		mutex_unlock(&opp_table_lock);
-		return ret;
-	}
-	mutex_unlock(&opp_table_lock);
-
-	/* We have opp-table node now, iterate over it and add OPPs */
-	for_each_available_child_of_node(opp_np, np) {
-		count++;
-
-		ret = _opp_add_static_v2(dev, np);
-		if (ret) {
-			dev_err(dev, "%s: Failed to add OPP, %d\n", __func__,
-				ret);
-			goto free_table;
-		}
-	}
-
-	/* There should be one of more OPP defined */
-	if (WARN_ON(!count))
-		return -ENOENT;
-
-	mutex_lock(&opp_table_lock);
-
-	opp_table = _find_opp_table(dev);
-	if (WARN_ON(IS_ERR(opp_table))) {
-		ret = PTR_ERR(opp_table);
-		mutex_unlock(&opp_table_lock);
-		goto free_table;
-	}
-
-	opp_table->np = opp_np;
-	opp_table->shared_opp = of_property_read_bool(opp_np, "opp-shared");
-
-	mutex_unlock(&opp_table_lock);
-
-	return 0;
-
-free_table:
-	dev_pm_opp_of_remove_table(dev);
-
-	return ret;
-}
-
-/* Initializes OPP tables based on old-deprecated bindings */
-static int _of_add_opp_table_v1(struct device *dev)
-{
-	const struct property *prop;
-	const __be32 *val;
-	int nr;
-
-	prop = of_find_property(dev->of_node, "operating-points", NULL);
-	if (!prop)
-		return -ENODEV;
-	if (!prop->value)
-		return -ENODATA;
-
-	/*
-	 * Each OPP is a set of tuples consisting of frequency and
-	 * voltage like <freq-kHz vol-uV>.
-	 */
-	nr = prop->length / sizeof(u32);
-	if (nr % 2) {
-		dev_err(dev, "%s: Invalid OPP table\n", __func__);
-		return -EINVAL;
-	}
-
-	val = prop->value;
-	while (nr) {
-		unsigned long freq = be32_to_cpup(val++) * 1000;
-		unsigned long volt = be32_to_cpup(val++);
-
-		if (_opp_add_v1(dev, freq, volt, false))
-			dev_warn(dev, "%s: Failed to add OPP %ld\n",
-				 __func__, freq);
-		nr -= 2;
-	}
-
-	return 0;
-}
 
 /**
- * dev_pm_opp_of_add_table() - Initialize opp table from device tree
+ * dev_pm_opp_remove_table() - Free all OPPs associated with the device
  * @dev:	device pointer used to lookup OPP table.
  *
- * Register the initial OPP table with the OPP library for given device.
+ * Free both OPPs created using static entries present in DT and the
+ * dynamically added entries.
  *
  * Locking: The internal opp_table and opp structures are RCU protected.
  * Hence this function indirectly uses RCU updater strategy with mutex locks
  * to keep the integrity of the internal data structures. Callers should ensure
  * that this function is *NOT* called under RCU protection or in contexts where
  * mutex cannot be locked.
- *
- * Return:
- * 0		On success OR
- *		Duplicate OPPs (both freq and volt are same) and opp->available
- * -EEXIST	Freq are same and volt are different OR
- *		Duplicate OPPs (both freq and volt are same) and !opp->available
- * -ENOMEM	Memory allocation failure
- * -ENODEV	when 'operating-points' property is not found or is invalid data
- *		in device node.
- * -ENODATA	when empty 'operating-points' property is found
- * -EINVAL	when invalid entries are found in opp-v2 table
  */
-int dev_pm_opp_of_add_table(struct device *dev)
+void dev_pm_opp_remove_table(struct device *dev)
 {
-	struct device_node *opp_np;
-	int ret;
-
-	/*
-	 * OPPs have two version of bindings now. The older one is deprecated,
-	 * try for the new binding first.
-	 */
-	opp_np = _of_get_opp_desc_node(dev);
-	if (!opp_np) {
-		/*
-		 * Try old-deprecated bindings for backward compatibility with
-		 * older dtbs.
-		 */
-		return _of_add_opp_table_v1(dev);
-	}
-
-	ret = _of_add_opp_table_v2(dev, opp_np);
-	of_node_put(opp_np);
-
-	return ret;
+	_dev_pm_opp_remove_table(dev, true);
 }
-EXPORT_SYMBOL_GPL(dev_pm_opp_of_add_table);
-#endif
+EXPORT_SYMBOL_GPL(dev_pm_opp_remove_table);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/base/power/opp/cpu.c linux-libre-4.7-gnu/drivers/base/power/opp/cpu.c
--- linux-libre-4.6-gnu/drivers/base/power/opp/cpu.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/base/power/opp/cpu.c	2016-07-24 15:23:50.000000000 -0400
@@ -18,7 +18,6 @@
 #include <linux/err.h>
 #include <linux/errno.h>
 #include <linux/export.h>
-#include <linux/of.h>
 #include <linux/slab.h>
 
 #include "opp.h"
@@ -119,8 +118,66 @@ void dev_pm_opp_free_cpufreq_table(struc
 EXPORT_SYMBOL_GPL(dev_pm_opp_free_cpufreq_table);
 #endif	/* CONFIG_CPU_FREQ */
 
-/* Required only for V1 bindings, as v2 can manage it from DT itself */
-int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, cpumask_var_t cpumask)
+void _dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask, bool of)
+{
+	struct device *cpu_dev;
+	int cpu;
+
+	WARN_ON(cpumask_empty(cpumask));
+
+	for_each_cpu(cpu, cpumask) {
+		cpu_dev = get_cpu_device(cpu);
+		if (!cpu_dev) {
+			pr_err("%s: failed to get cpu%d device\n", __func__,
+			       cpu);
+			continue;
+		}
+
+		if (of)
+			dev_pm_opp_of_remove_table(cpu_dev);
+		else
+			dev_pm_opp_remove_table(cpu_dev);
+	}
+}
+
+/**
+ * dev_pm_opp_cpumask_remove_table() - Removes OPP table for @cpumask
+ * @cpumask:	cpumask for which OPP table needs to be removed
+ *
+ * This removes the OPP tables for CPUs present in the @cpumask.
+ * This should be used to remove all the OPPs entries associated with
+ * the cpus in @cpumask.
+ *
+ * Locking: The internal opp_table and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ */
+void dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask)
+{
+	_dev_pm_opp_cpumask_remove_table(cpumask, false);
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_cpumask_remove_table);
+
+/**
+ * dev_pm_opp_set_sharing_cpus() - Mark OPP table as shared by few CPUs
+ * @cpu_dev:	CPU device for which we do this operation
+ * @cpumask:	cpumask of the CPUs which share the OPP table with @cpu_dev
+ *
+ * This marks OPP table of the @cpu_dev as shared by the CPUs present in
+ * @cpumask.
+ *
+ * Returns -ENODEV if OPP table isn't already present.
+ *
+ * Locking: The internal opp_table and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ */
+int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev,
+				const struct cpumask *cpumask)
 {
 	struct opp_device *opp_dev;
 	struct opp_table *opp_table;
@@ -131,7 +188,7 @@ int dev_pm_opp_set_sharing_cpus(struct d
 
 	opp_table = _find_opp_table(cpu_dev);
 	if (IS_ERR(opp_table)) {
-		ret = -EINVAL;
+		ret = PTR_ERR(opp_table);
 		goto unlock;
 	}
 
@@ -152,6 +209,9 @@ int dev_pm_opp_set_sharing_cpus(struct d
 				__func__, cpu);
 			continue;
 		}
+
+		/* Mark opp-table as multiple CPUs are sharing it now */
+		opp_table->shared_opp = OPP_TABLE_ACCESS_SHARED;
 	}
 unlock:
 	mutex_unlock(&opp_table_lock);
@@ -160,112 +220,53 @@ unlock:
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_set_sharing_cpus);
 
-#ifdef CONFIG_OF
-void dev_pm_opp_of_cpumask_remove_table(cpumask_var_t cpumask)
+/**
+ * dev_pm_opp_get_sharing_cpus() - Get cpumask of CPUs sharing OPPs with @cpu_dev
+ * @cpu_dev:	CPU device for which we do this operation
+ * @cpumask:	cpumask to update with information of sharing CPUs
+ *
+ * This updates the @cpumask with CPUs that are sharing OPPs with @cpu_dev.
+ *
+ * Returns -ENODEV if OPP table isn't already present and -EINVAL if the OPP
+ * table's status is access-unknown.
+ *
+ * Locking: The internal opp_table and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ */
+int dev_pm_opp_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask)
 {
-	struct device *cpu_dev;
-	int cpu;
-
-	WARN_ON(cpumask_empty(cpumask));
+	struct opp_device *opp_dev;
+	struct opp_table *opp_table;
+	int ret = 0;
 
-	for_each_cpu(cpu, cpumask) {
-		cpu_dev = get_cpu_device(cpu);
-		if (!cpu_dev) {
-			pr_err("%s: failed to get cpu%d device\n", __func__,
-			       cpu);
-			continue;
-		}
+	mutex_lock(&opp_table_lock);
 
-		dev_pm_opp_of_remove_table(cpu_dev);
+	opp_table = _find_opp_table(cpu_dev);
+	if (IS_ERR(opp_table)) {
+		ret = PTR_ERR(opp_table);
+		goto unlock;
 	}
-}
-EXPORT_SYMBOL_GPL(dev_pm_opp_of_cpumask_remove_table);
-
-int dev_pm_opp_of_cpumask_add_table(cpumask_var_t cpumask)
-{
-	struct device *cpu_dev;
-	int cpu, ret = 0;
-
-	WARN_ON(cpumask_empty(cpumask));
-
-	for_each_cpu(cpu, cpumask) {
-		cpu_dev = get_cpu_device(cpu);
-		if (!cpu_dev) {
-			pr_err("%s: failed to get cpu%d device\n", __func__,
-			       cpu);
-			continue;
-		}
-
-		ret = dev_pm_opp_of_add_table(cpu_dev);
-		if (ret) {
-			pr_err("%s: couldn't find opp table for cpu:%d, %d\n",
-			       __func__, cpu, ret);
 
-			/* Free all other OPPs */
-			dev_pm_opp_of_cpumask_remove_table(cpumask);
-			break;
-		}
+	if (opp_table->shared_opp == OPP_TABLE_ACCESS_UNKNOWN) {
+		ret = -EINVAL;
+		goto unlock;
 	}
 
-	return ret;
-}
-EXPORT_SYMBOL_GPL(dev_pm_opp_of_cpumask_add_table);
-
-/*
- * Works only for OPP v2 bindings.
- *
- * Returns -ENOENT if operating-points-v2 bindings aren't supported.
- */
-int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev, cpumask_var_t cpumask)
-{
-	struct device_node *np, *tmp_np;
-	struct device *tcpu_dev;
-	int cpu, ret = 0;
+	cpumask_clear(cpumask);
 
-	/* Get OPP descriptor node */
-	np = _of_get_opp_desc_node(cpu_dev);
-	if (!np) {
-		dev_dbg(cpu_dev, "%s: Couldn't find cpu_dev node.\n", __func__);
-		return -ENOENT;
+	if (opp_table->shared_opp == OPP_TABLE_ACCESS_SHARED) {
+		list_for_each_entry(opp_dev, &opp_table->dev_list, node)
+			cpumask_set_cpu(opp_dev->dev->id, cpumask);
+	} else {
+		cpumask_set_cpu(cpu_dev->id, cpumask);
 	}
 
-	cpumask_set_cpu(cpu_dev->id, cpumask);
-
-	/* OPPs are shared ? */
-	if (!of_property_read_bool(np, "opp-shared"))
-		goto put_cpu_node;
-
-	for_each_possible_cpu(cpu) {
-		if (cpu == cpu_dev->id)
-			continue;
-
-		tcpu_dev = get_cpu_device(cpu);
-		if (!tcpu_dev) {
-			dev_err(cpu_dev, "%s: failed to get cpu%d device\n",
-				__func__, cpu);
-			ret = -ENODEV;
-			goto put_cpu_node;
-		}
-
-		/* Get OPP descriptor node */
-		tmp_np = _of_get_opp_desc_node(tcpu_dev);
-		if (!tmp_np) {
-			dev_err(tcpu_dev, "%s: Couldn't find tcpu_dev node.\n",
-				__func__);
-			ret = -ENOENT;
-			goto put_cpu_node;
-		}
-
-		/* CPUs are sharing opp node */
-		if (np == tmp_np)
-			cpumask_set_cpu(cpu, cpumask);
-
-		of_node_put(tmp_np);
-	}
+unlock:
+	mutex_unlock(&opp_table_lock);
 
-put_cpu_node:
-	of_node_put(np);
 	return ret;
 }
-EXPORT_SYMBOL_GPL(dev_pm_opp_of_get_sharing_cpus);
-#endif
+EXPORT_SYMBOL_GPL(dev_pm_opp_get_sharing_cpus);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/base/power/opp/Makefile linux-libre-4.7-gnu/drivers/base/power/opp/Makefile
--- linux-libre-4.6-gnu/drivers/base/power/opp/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/base/power/opp/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -1,3 +1,4 @@
 ccflags-$(CONFIG_DEBUG_DRIVER)	:= -DDEBUG
 obj-y				+= core.o cpu.o
+obj-$(CONFIG_OF)		+= of.o
 obj-$(CONFIG_DEBUG_FS)		+= debugfs.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/base/power/opp/of.c linux-libre-4.7-gnu/drivers/base/power/opp/of.c
--- linux-libre-4.6-gnu/drivers/base/power/opp/of.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/base/power/opp/of.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,597 @@
+/*
+ * Generic OPP OF helpers
+ *
+ * Copyright (C) 2009-2010 Texas Instruments Incorporated.
+ *	Nishanth Menon
+ *	Romit Dasgupta
+ *	Kevin Hilman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/cpu.h>
+#include <linux/errno.h>
+#include <linux/device.h>
+#include <linux/of.h>
+#include <linux/export.h>
+
+#include "opp.h"
+
+static struct opp_table *_managed_opp(const struct device_node *np)
+{
+	struct opp_table *opp_table;
+
+	list_for_each_entry_rcu(opp_table, &opp_tables, node) {
+		if (opp_table->np == np) {
+			/*
+			 * Multiple devices can point to the same OPP table and
+			 * so will have same node-pointer, np.
+			 *
+			 * But the OPPs will be considered as shared only if the
+			 * OPP table contains a "opp-shared" property.
+			 */
+			if (opp_table->shared_opp == OPP_TABLE_ACCESS_SHARED)
+				return opp_table;
+
+			return NULL;
+		}
+	}
+
+	return NULL;
+}
+
+void _of_init_opp_table(struct opp_table *opp_table, struct device *dev)
+{
+	struct device_node *np;
+
+	/*
+	 * Only required for backward compatibility with v1 bindings, but isn't
+	 * harmful for other cases. And so we do it unconditionally.
+	 */
+	np = of_node_get(dev->of_node);
+	if (np) {
+		u32 val;
+
+		if (!of_property_read_u32(np, "clock-latency", &val))
+			opp_table->clock_latency_ns_max = val;
+		of_property_read_u32(np, "voltage-tolerance",
+				     &opp_table->voltage_tolerance_v1);
+		of_node_put(np);
+	}
+}
+
+static bool _opp_is_supported(struct device *dev, struct opp_table *opp_table,
+			      struct device_node *np)
+{
+	unsigned int count = opp_table->supported_hw_count;
+	u32 version;
+	int ret;
+
+	if (!opp_table->supported_hw)
+		return true;
+
+	while (count--) {
+		ret = of_property_read_u32_index(np, "opp-supported-hw", count,
+						 &version);
+		if (ret) {
+			dev_warn(dev, "%s: failed to read opp-supported-hw property at index %d: %d\n",
+				 __func__, count, ret);
+			return false;
+		}
+
+		/* Both of these are bitwise masks of the versions */
+		if (!(version & opp_table->supported_hw[count]))
+			return false;
+	}
+
+	return true;
+}
+
+/* TODO: Support multiple regulators */
+static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev,
+			      struct opp_table *opp_table)
+{
+	u32 microvolt[3] = {0};
+	u32 val;
+	int count, ret;
+	struct property *prop = NULL;
+	char name[NAME_MAX];
+
+	/* Search for "opp-microvolt-<name>" */
+	if (opp_table->prop_name) {
+		snprintf(name, sizeof(name), "opp-microvolt-%s",
+			 opp_table->prop_name);
+		prop = of_find_property(opp->np, name, NULL);
+	}
+
+	if (!prop) {
+		/* Search for "opp-microvolt" */
+		sprintf(name, "opp-microvolt");
+		prop = of_find_property(opp->np, name, NULL);
+
+		/* Missing property isn't a problem, but an invalid entry is */
+		if (!prop)
+			return 0;
+	}
+
+	count = of_property_count_u32_elems(opp->np, name);
+	if (count < 0) {
+		dev_err(dev, "%s: Invalid %s property (%d)\n",
+			__func__, name, count);
+		return count;
+	}
+
+	/* There can be one or three elements here */
+	if (count != 1 && count != 3) {
+		dev_err(dev, "%s: Invalid number of elements in %s property (%d)\n",
+			__func__, name, count);
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32_array(opp->np, name, microvolt, count);
+	if (ret) {
+		dev_err(dev, "%s: error parsing %s: %d\n", __func__, name, ret);
+		return -EINVAL;
+	}
+
+	opp->u_volt = microvolt[0];
+
+	if (count == 1) {
+		opp->u_volt_min = opp->u_volt;
+		opp->u_volt_max = opp->u_volt;
+	} else {
+		opp->u_volt_min = microvolt[1];
+		opp->u_volt_max = microvolt[2];
+	}
+
+	/* Search for "opp-microamp-<name>" */
+	prop = NULL;
+	if (opp_table->prop_name) {
+		snprintf(name, sizeof(name), "opp-microamp-%s",
+			 opp_table->prop_name);
+		prop = of_find_property(opp->np, name, NULL);
+	}
+
+	if (!prop) {
+		/* Search for "opp-microamp" */
+		sprintf(name, "opp-microamp");
+		prop = of_find_property(opp->np, name, NULL);
+	}
+
+	if (prop && !of_property_read_u32(opp->np, name, &val))
+		opp->u_amp = val;
+
+	return 0;
+}
+
+/**
+ * dev_pm_opp_of_remove_table() - Free OPP table entries created from static DT
+ *				  entries
+ * @dev:	device pointer used to lookup OPP table.
+ *
+ * Free OPPs created using static entries present in DT.
+ *
+ * Locking: The internal opp_table and opp structures are RCU protected.
+ * Hence this function indirectly uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ */
+void dev_pm_opp_of_remove_table(struct device *dev)
+{
+	_dev_pm_opp_remove_table(dev, false);
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_of_remove_table);
+
+/* Returns opp descriptor node for a device, caller must do of_node_put() */
+struct device_node *_of_get_opp_desc_node(struct device *dev)
+{
+	/*
+	 * TODO: Support for multiple OPP tables.
+	 *
+	 * There should be only ONE phandle present in "operating-points-v2"
+	 * property.
+	 */
+
+	return of_parse_phandle(dev->of_node, "operating-points-v2", 0);
+}
+
+/**
+ * _opp_add_static_v2() - Allocate static OPPs (As per 'v2' DT bindings)
+ * @dev:	device for which we do this operation
+ * @np:		device node
+ *
+ * This function adds an opp definition to the opp table and returns status. The
+ * opp can be controlled using dev_pm_opp_enable/disable functions and may be
+ * removed by dev_pm_opp_remove.
+ *
+ * Locking: The internal opp_table and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ *
+ * Return:
+ * 0		On success OR
+ *		Duplicate OPPs (both freq and volt are same) and opp->available
+ * -EEXIST	Freq are same and volt are different OR
+ *		Duplicate OPPs (both freq and volt are same) and !opp->available
+ * -ENOMEM	Memory allocation failure
+ * -EINVAL	Failed parsing the OPP node
+ */
+static int _opp_add_static_v2(struct device *dev, struct device_node *np)
+{
+	struct opp_table *opp_table;
+	struct dev_pm_opp *new_opp;
+	u64 rate;
+	u32 val;
+	int ret;
+
+	/* Hold our table modification lock here */
+	mutex_lock(&opp_table_lock);
+
+	new_opp = _allocate_opp(dev, &opp_table);
+	if (!new_opp) {
+		ret = -ENOMEM;
+		goto unlock;
+	}
+
+	ret = of_property_read_u64(np, "opp-hz", &rate);
+	if (ret < 0) {
+		dev_err(dev, "%s: opp-hz not found\n", __func__);
+		goto free_opp;
+	}
+
+	/* Check if the OPP supports hardware's hierarchy of versions or not */
+	if (!_opp_is_supported(dev, opp_table, np)) {
+		dev_dbg(dev, "OPP not supported by hardware: %llu\n", rate);
+		goto free_opp;
+	}
+
+	/*
+	 * Rate is defined as an unsigned long in clk API, and so casting
+	 * explicitly to its type. Must be fixed once rate is 64 bit
+	 * guaranteed in clk API.
+	 */
+	new_opp->rate = (unsigned long)rate;
+	new_opp->turbo = of_property_read_bool(np, "turbo-mode");
+
+	new_opp->np = np;
+	new_opp->dynamic = false;
+	new_opp->available = true;
+
+	if (!of_property_read_u32(np, "clock-latency-ns", &val))
+		new_opp->clock_latency_ns = val;
+
+	ret = opp_parse_supplies(new_opp, dev, opp_table);
+	if (ret)
+		goto free_opp;
+
+	ret = _opp_add(dev, new_opp, opp_table);
+	if (ret)
+		goto free_opp;
+
+	/* OPP to select on device suspend */
+	if (of_property_read_bool(np, "opp-suspend")) {
+		if (opp_table->suspend_opp) {
+			dev_warn(dev, "%s: Multiple suspend OPPs found (%lu %lu)\n",
+				 __func__, opp_table->suspend_opp->rate,
+				 new_opp->rate);
+		} else {
+			new_opp->suspend = true;
+			opp_table->suspend_opp = new_opp;
+		}
+	}
+
+	if (new_opp->clock_latency_ns > opp_table->clock_latency_ns_max)
+		opp_table->clock_latency_ns_max = new_opp->clock_latency_ns;
+
+	mutex_unlock(&opp_table_lock);
+
+	pr_debug("%s: turbo:%d rate:%lu uv:%lu uvmin:%lu uvmax:%lu latency:%lu\n",
+		 __func__, new_opp->turbo, new_opp->rate, new_opp->u_volt,
+		 new_opp->u_volt_min, new_opp->u_volt_max,
+		 new_opp->clock_latency_ns);
+
+	/*
+	 * Notify the changes in the availability of the operable
+	 * frequency/voltage list.
+	 */
+	srcu_notifier_call_chain(&opp_table->srcu_head, OPP_EVENT_ADD, new_opp);
+	return 0;
+
+free_opp:
+	_opp_remove(opp_table, new_opp, false);
+unlock:
+	mutex_unlock(&opp_table_lock);
+	return ret;
+}
+
+/* Initializes OPP tables based on new bindings */
+static int _of_add_opp_table_v2(struct device *dev, struct device_node *opp_np)
+{
+	struct device_node *np;
+	struct opp_table *opp_table;
+	int ret = 0, count = 0;
+
+	mutex_lock(&opp_table_lock);
+
+	opp_table = _managed_opp(opp_np);
+	if (opp_table) {
+		/* OPPs are already managed */
+		if (!_add_opp_dev(dev, opp_table))
+			ret = -ENOMEM;
+		mutex_unlock(&opp_table_lock);
+		return ret;
+	}
+	mutex_unlock(&opp_table_lock);
+
+	/* We have opp-table node now, iterate over it and add OPPs */
+	for_each_available_child_of_node(opp_np, np) {
+		count++;
+
+		ret = _opp_add_static_v2(dev, np);
+		if (ret) {
+			dev_err(dev, "%s: Failed to add OPP, %d\n", __func__,
+				ret);
+			goto free_table;
+		}
+	}
+
+	/* There should be one of more OPP defined */
+	if (WARN_ON(!count))
+		return -ENOENT;
+
+	mutex_lock(&opp_table_lock);
+
+	opp_table = _find_opp_table(dev);
+	if (WARN_ON(IS_ERR(opp_table))) {
+		ret = PTR_ERR(opp_table);
+		mutex_unlock(&opp_table_lock);
+		goto free_table;
+	}
+
+	opp_table->np = opp_np;
+	if (of_property_read_bool(opp_np, "opp-shared"))
+		opp_table->shared_opp = OPP_TABLE_ACCESS_SHARED;
+	else
+		opp_table->shared_opp = OPP_TABLE_ACCESS_EXCLUSIVE;
+
+	mutex_unlock(&opp_table_lock);
+
+	return 0;
+
+free_table:
+	dev_pm_opp_of_remove_table(dev);
+
+	return ret;
+}
+
+/* Initializes OPP tables based on old-deprecated bindings */
+static int _of_add_opp_table_v1(struct device *dev)
+{
+	const struct property *prop;
+	const __be32 *val;
+	int nr;
+
+	prop = of_find_property(dev->of_node, "operating-points", NULL);
+	if (!prop)
+		return -ENODEV;
+	if (!prop->value)
+		return -ENODATA;
+
+	/*
+	 * Each OPP is a set of tuples consisting of frequency and
+	 * voltage like <freq-kHz vol-uV>.
+	 */
+	nr = prop->length / sizeof(u32);
+	if (nr % 2) {
+		dev_err(dev, "%s: Invalid OPP table\n", __func__);
+		return -EINVAL;
+	}
+
+	val = prop->value;
+	while (nr) {
+		unsigned long freq = be32_to_cpup(val++) * 1000;
+		unsigned long volt = be32_to_cpup(val++);
+
+		if (_opp_add_v1(dev, freq, volt, false))
+			dev_warn(dev, "%s: Failed to add OPP %ld\n",
+				 __func__, freq);
+		nr -= 2;
+	}
+
+	return 0;
+}
+
+/**
+ * dev_pm_opp_of_add_table() - Initialize opp table from device tree
+ * @dev:	device pointer used to lookup OPP table.
+ *
+ * Register the initial OPP table with the OPP library for given device.
+ *
+ * Locking: The internal opp_table and opp structures are RCU protected.
+ * Hence this function indirectly uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ *
+ * Return:
+ * 0		On success OR
+ *		Duplicate OPPs (both freq and volt are same) and opp->available
+ * -EEXIST	Freq are same and volt are different OR
+ *		Duplicate OPPs (both freq and volt are same) and !opp->available
+ * -ENOMEM	Memory allocation failure
+ * -ENODEV	when 'operating-points' property is not found or is invalid data
+ *		in device node.
+ * -ENODATA	when empty 'operating-points' property is found
+ * -EINVAL	when invalid entries are found in opp-v2 table
+ */
+int dev_pm_opp_of_add_table(struct device *dev)
+{
+	struct device_node *opp_np;
+	int ret;
+
+	/*
+	 * OPPs have two version of bindings now. The older one is deprecated,
+	 * try for the new binding first.
+	 */
+	opp_np = _of_get_opp_desc_node(dev);
+	if (!opp_np) {
+		/*
+		 * Try old-deprecated bindings for backward compatibility with
+		 * older dtbs.
+		 */
+		return _of_add_opp_table_v1(dev);
+	}
+
+	ret = _of_add_opp_table_v2(dev, opp_np);
+	of_node_put(opp_np);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_of_add_table);
+
+/* CPU device specific helpers */
+
+/**
+ * dev_pm_opp_of_cpumask_remove_table() - Removes OPP table for @cpumask
+ * @cpumask:	cpumask for which OPP table needs to be removed
+ *
+ * This removes the OPP tables for CPUs present in the @cpumask.
+ * This should be used only to remove static entries created from DT.
+ *
+ * Locking: The internal opp_table and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ */
+void dev_pm_opp_of_cpumask_remove_table(const struct cpumask *cpumask)
+{
+	_dev_pm_opp_cpumask_remove_table(cpumask, true);
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_of_cpumask_remove_table);
+
+/**
+ * dev_pm_opp_of_cpumask_add_table() - Adds OPP table for @cpumask
+ * @cpumask:	cpumask for which OPP table needs to be added.
+ *
+ * This adds the OPP tables for CPUs present in the @cpumask.
+ *
+ * Locking: The internal opp_table and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ */
+int dev_pm_opp_of_cpumask_add_table(const struct cpumask *cpumask)
+{
+	struct device *cpu_dev;
+	int cpu, ret = 0;
+
+	WARN_ON(cpumask_empty(cpumask));
+
+	for_each_cpu(cpu, cpumask) {
+		cpu_dev = get_cpu_device(cpu);
+		if (!cpu_dev) {
+			pr_err("%s: failed to get cpu%d device\n", __func__,
+			       cpu);
+			continue;
+		}
+
+		ret = dev_pm_opp_of_add_table(cpu_dev);
+		if (ret) {
+			pr_err("%s: couldn't find opp table for cpu:%d, %d\n",
+			       __func__, cpu, ret);
+
+			/* Free all other OPPs */
+			dev_pm_opp_of_cpumask_remove_table(cpumask);
+			break;
+		}
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_of_cpumask_add_table);
+
+/*
+ * Works only for OPP v2 bindings.
+ *
+ * Returns -ENOENT if operating-points-v2 bindings aren't supported.
+ */
+/**
+ * dev_pm_opp_of_get_sharing_cpus() - Get cpumask of CPUs sharing OPPs with
+ *				      @cpu_dev using operating-points-v2
+ *				      bindings.
+ *
+ * @cpu_dev:	CPU device for which we do this operation
+ * @cpumask:	cpumask to update with information of sharing CPUs
+ *
+ * This updates the @cpumask with CPUs that are sharing OPPs with @cpu_dev.
+ *
+ * Returns -ENOENT if operating-points-v2 isn't present for @cpu_dev.
+ *
+ * Locking: The internal opp_table and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ */
+int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev,
+				   struct cpumask *cpumask)
+{
+	struct device_node *np, *tmp_np;
+	struct device *tcpu_dev;
+	int cpu, ret = 0;
+
+	/* Get OPP descriptor node */
+	np = _of_get_opp_desc_node(cpu_dev);
+	if (!np) {
+		dev_dbg(cpu_dev, "%s: Couldn't find cpu_dev node.\n", __func__);
+		return -ENOENT;
+	}
+
+	cpumask_set_cpu(cpu_dev->id, cpumask);
+
+	/* OPPs are shared ? */
+	if (!of_property_read_bool(np, "opp-shared"))
+		goto put_cpu_node;
+
+	for_each_possible_cpu(cpu) {
+		if (cpu == cpu_dev->id)
+			continue;
+
+		tcpu_dev = get_cpu_device(cpu);
+		if (!tcpu_dev) {
+			dev_err(cpu_dev, "%s: failed to get cpu%d device\n",
+				__func__, cpu);
+			ret = -ENODEV;
+			goto put_cpu_node;
+		}
+
+		/* Get OPP descriptor node */
+		tmp_np = _of_get_opp_desc_node(tcpu_dev);
+		if (!tmp_np) {
+			dev_err(tcpu_dev, "%s: Couldn't find tcpu_dev node.\n",
+				__func__);
+			ret = -ENOENT;
+			goto put_cpu_node;
+		}
+
+		/* CPUs are sharing opp node */
+		if (np == tmp_np)
+			cpumask_set_cpu(cpu, cpumask);
+
+		of_node_put(tmp_np);
+	}
+
+put_cpu_node:
+	of_node_put(np);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_of_get_sharing_cpus);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/base/power/opp/opp.h linux-libre-4.7-gnu/drivers/base/power/opp/opp.h
--- linux-libre-4.6-gnu/drivers/base/power/opp/opp.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/base/power/opp/opp.h	2016-07-24 15:23:50.000000000 -0400
@@ -28,6 +28,8 @@ struct regulator;
 /* Lock to allow exclusive modification to the device and opp lists */
 extern struct mutex opp_table_lock;
 
+extern struct list_head opp_tables;
+
 /*
  * Internal data structure organization with the OPP layer library is as
  * follows:
@@ -117,6 +119,12 @@ struct opp_device {
 #endif
 };
 
+enum opp_table_access {
+	OPP_TABLE_ACCESS_UNKNOWN = 0,
+	OPP_TABLE_ACCESS_EXCLUSIVE = 1,
+	OPP_TABLE_ACCESS_SHARED = 2,
+};
+
 /**
  * struct opp_table - Device opp structure
  * @node:	table node - contains the devices with OPPs that
@@ -164,7 +172,7 @@ struct opp_table {
 	/* For backward compatibility with v1 bindings */
 	unsigned int voltage_tolerance_v1;
 
-	bool shared_opp;
+	enum opp_table_access shared_opp;
 	struct dev_pm_opp *suspend_opp;
 
 	unsigned int *supported_hw;
@@ -183,6 +191,18 @@ struct opp_table {
 struct opp_table *_find_opp_table(struct device *dev);
 struct opp_device *_add_opp_dev(const struct device *dev, struct opp_table *opp_table);
 struct device_node *_of_get_opp_desc_node(struct device *dev);
+void _dev_pm_opp_remove_table(struct device *dev, bool remove_all);
+struct dev_pm_opp *_allocate_opp(struct device *dev, struct opp_table **opp_table);
+int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, struct opp_table *opp_table);
+void _opp_remove(struct opp_table *opp_table, struct dev_pm_opp *opp, bool notify);
+int _opp_add_v1(struct device *dev, unsigned long freq, long u_volt, bool dynamic);
+void _dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask, bool of);
+
+#ifdef CONFIG_OF
+void _of_init_opp_table(struct opp_table *opp_table, struct device *dev);
+#else
+static inline void _of_init_opp_table(struct opp_table *opp_table, struct device *dev) {}
+#endif
 
 #ifdef CONFIG_DEBUG_FS
 void opp_debug_remove_one(struct dev_pm_opp *opp);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/base/power/runtime.c linux-libre-4.7-gnu/drivers/base/power/runtime.c
--- linux-libre-4.6-gnu/drivers/base/power/runtime.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/base/power/runtime.c	2016-07-24 15:23:50.000000000 -0400
@@ -1506,11 +1506,16 @@ int pm_runtime_force_resume(struct devic
 		goto out;
 	}
 
-	ret = callback(dev);
+	ret = pm_runtime_set_active(dev);
 	if (ret)
 		goto out;
 
-	pm_runtime_set_active(dev);
+	ret = callback(dev);
+	if (ret) {
+		pm_runtime_set_suspended(dev);
+		goto out;
+	}
+
 	pm_runtime_mark_last_busy(dev);
 out:
 	pm_runtime_enable(dev);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/base/property.c linux-libre-4.7-gnu/drivers/base/property.c
--- linux-libre-4.6-gnu/drivers/base/property.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/base/property.c	2016-07-24 15:23:50.000000000 -0400
@@ -19,6 +19,11 @@
 #include <linux/etherdevice.h>
 #include <linux/phy.h>
 
+struct property_set {
+	struct fwnode_handle fwnode;
+	struct property_entry *properties;
+};
+
 static inline bool is_pset_node(struct fwnode_handle *fwnode)
 {
 	return !IS_ERR_OR_NULL(fwnode) && fwnode->type == FWNODE_PDATA;
@@ -801,14 +806,14 @@ static struct property_set *pset_copy_se
 }
 
 /**
- * device_remove_property_set - Remove properties from a device object.
+ * device_remove_properties - Remove properties from a device object.
  * @dev: Device whose properties to remove.
  *
  * The function removes properties previously associated to the device
- * secondary firmware node with device_add_property_set(). Memory allocated
+ * secondary firmware node with device_add_properties(). Memory allocated
  * to the properties will also be released.
  */
-void device_remove_property_set(struct device *dev)
+void device_remove_properties(struct device *dev)
 {
 	struct fwnode_handle *fwnode;
 
@@ -831,24 +836,27 @@ void device_remove_property_set(struct d
 		}
 	}
 }
-EXPORT_SYMBOL_GPL(device_remove_property_set);
+EXPORT_SYMBOL_GPL(device_remove_properties);
 
 /**
- * device_add_property_set - Add a collection of properties to a device object.
+ * device_add_properties - Add a collection of properties to a device object.
  * @dev: Device to add properties to.
- * @pset: Collection of properties to add.
+ * @properties: Collection of properties to add.
  *
- * Associate a collection of device properties represented by @pset with @dev
- * as its secondary firmware node. The function takes a copy of @pset.
+ * Associate a collection of device properties represented by @properties with
+ * @dev as its secondary firmware node. The function takes a copy of
+ * @properties.
  */
-int device_add_property_set(struct device *dev, const struct property_set *pset)
+int device_add_properties(struct device *dev, struct property_entry *properties)
 {
-	struct property_set *p;
+	struct property_set *p, pset;
 
-	if (!pset)
+	if (!properties)
 		return -EINVAL;
 
-	p = pset_copy_set(pset);
+	pset.properties = properties;
+
+	p = pset_copy_set(&pset);
 	if (IS_ERR(p))
 		return PTR_ERR(p);
 
@@ -856,7 +864,7 @@ int device_add_property_set(struct devic
 	set_secondary_fwnode(dev, &p->fwnode);
 	return 0;
 }
-EXPORT_SYMBOL_GPL(device_add_property_set);
+EXPORT_SYMBOL_GPL(device_add_properties);
 
 /**
  * device_get_next_child_node - Return the next child node handle for a device
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/base/regmap/regcache.c linux-libre-4.7-gnu/drivers/base/regmap/regcache.c
--- linux-libre-4.6-gnu/drivers/base/regmap/regcache.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/base/regmap/regcache.c	2016-07-24 15:23:50.000000000 -0400
@@ -529,7 +529,7 @@ EXPORT_SYMBOL_GPL(regcache_mark_dirty);
  * regcache_cache_bypass: Put a register map into cache bypass mode
  *
  * @map: map to configure
- * @cache_bypass: flag if changes should not be written to the hardware
+ * @cache_bypass: flag if changes should not be written to the cache
  *
  * When a register map is marked with the cache bypass option, writes
  * to the register map API will only update the hardware and not the
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/base/regmap/regcache-flat.c linux-libre-4.7-gnu/drivers/base/regmap/regcache-flat.c
--- linux-libre-4.6-gnu/drivers/base/regmap/regcache-flat.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/base/regmap/regcache-flat.c	2016-07-24 15:23:50.000000000 -0400
@@ -27,7 +27,7 @@ static int regcache_flat_init(struct reg
 	int i;
 	unsigned int *cache;
 
-	if (!map || map->reg_stride_order < 0)
+	if (!map || map->reg_stride_order < 0 || !map->max_register)
 		return -EINVAL;
 
 	map->cache = kcalloc(regcache_flat_get_index(map, map->max_register)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/bcma/bcma_private.h linux-libre-4.7-gnu/drivers/bcma/bcma_private.h
--- linux-libre-4.6-gnu/drivers/bcma/bcma_private.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/bcma/bcma_private.h	2016-07-24 15:23:50.000000000 -0400
@@ -8,8 +8,6 @@
 #include <linux/bcma/bcma.h>
 #include <linux/delay.h>
 
-#define BCMA_CORE_SIZE		0x1000
-
 #define bcma_err(bus, fmt, ...) \
 	pr_err("bus%d: " fmt, (bus)->num, ##__VA_ARGS__)
 #define bcma_warn(bus, fmt, ...) \
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/bcma/driver_chipcommon_sflash.c linux-libre-4.7-gnu/drivers/bcma/driver_chipcommon_sflash.c
--- linux-libre-4.6-gnu/drivers/bcma/driver_chipcommon_sflash.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/bcma/driver_chipcommon_sflash.c	2016-07-24 15:23:50.000000000 -0400
@@ -146,7 +146,6 @@ int bcma_sflash_init(struct bcma_drv_cc
 		return -ENOTSUPP;
 	}
 
-	sflash->window = BCMA_SOC_FLASH2;
 	sflash->blocksize = e->blocksize;
 	sflash->numblocks = e->numblocks;
 	sflash->size = sflash->blocksize * sflash->numblocks;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/block/aoe/aoecmd.c linux-libre-4.7-gnu/drivers/block/aoe/aoecmd.c
--- linux-libre-4.6-gnu/drivers/block/aoe/aoecmd.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/block/aoe/aoecmd.c	2016-07-24 15:23:50.000000000 -0400
@@ -861,7 +861,7 @@ rqbiocnt(struct request *r)
  * discussion.
  *
  * We cannot use get_page in the workaround, because it insists on a
- * positive page count as a precondition.  So we use _count directly.
+ * positive page count as a precondition.  So we use _refcount directly.
  */
 static void
 bio_pageinc(struct bio *bio)
@@ -1750,7 +1750,7 @@ aoecmd_init(void)
 	int ret;
 
 	/* get_zeroed_page returns page with ref count 1 */
-	p = (void *) get_zeroed_page(GFP_KERNEL | __GFP_REPEAT);
+	p = (void *) get_zeroed_page(GFP_KERNEL);
 	if (!p)
 		return -ENOMEM;
 	empty_page = virt_to_page(p);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/block/brd.c linux-libre-4.7-gnu/drivers/block/brd.c
--- linux-libre-4.6-gnu/drivers/block/brd.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/block/brd.c	2016-07-24 15:23:50.000000000 -0400
@@ -381,7 +381,7 @@ static int brd_rw_page(struct block_devi
 
 #ifdef CONFIG_BLK_DEV_RAM_DAX
 static long brd_direct_access(struct block_device *bdev, sector_t sector,
-			void __pmem **kaddr, pfn_t *pfn)
+			void __pmem **kaddr, pfn_t *pfn, long size)
 {
 	struct brd_device *brd = bdev->bd_disk->private_data;
 	struct page *page;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/block/drbd/drbd_main.c linux-libre-4.7-gnu/drivers/block/drbd/drbd_main.c
--- linux-libre-4.6-gnu/drivers/block/drbd/drbd_main.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/block/drbd/drbd_main.c	2016-07-24 15:23:50.000000000 -0400
@@ -2761,7 +2761,7 @@ enum drbd_ret_code drbd_create_device(st
 	q->backing_dev_info.congested_data = device;
 
 	blk_queue_make_request(q, drbd_make_request);
-	blk_queue_flush(q, REQ_FLUSH | REQ_FUA);
+	blk_queue_write_cache(q, true, true);
 	/* Setting the max_hw_sectors to an odd value of 8kibyte here
 	   This triggers a max_bio_size message upon first attach or connect */
 	blk_queue_max_hw_sectors(q, DRBD_MAX_BIO_SIZE_SAFE >> 8);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/block/drbd/drbd_nl.c linux-libre-4.7-gnu/drivers/block/drbd/drbd_nl.c
--- linux-libre-4.6-gnu/drivers/block/drbd/drbd_nl.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/block/drbd/drbd_nl.c	2016-07-24 15:23:50.000000000 -0400
@@ -3633,14 +3633,15 @@ static int nla_put_status_info(struct sk
 		goto nla_put_failure;
 	if (nla_put_u32(skb, T_sib_reason, sib ? sib->sib_reason : SIB_GET_STATUS_REPLY) ||
 	    nla_put_u32(skb, T_current_state, device->state.i) ||
-	    nla_put_u64(skb, T_ed_uuid, device->ed_uuid) ||
-	    nla_put_u64(skb, T_capacity, drbd_get_capacity(device->this_bdev)) ||
-	    nla_put_u64(skb, T_send_cnt, device->send_cnt) ||
-	    nla_put_u64(skb, T_recv_cnt, device->recv_cnt) ||
-	    nla_put_u64(skb, T_read_cnt, device->read_cnt) ||
-	    nla_put_u64(skb, T_writ_cnt, device->writ_cnt) ||
-	    nla_put_u64(skb, T_al_writ_cnt, device->al_writ_cnt) ||
-	    nla_put_u64(skb, T_bm_writ_cnt, device->bm_writ_cnt) ||
+	    nla_put_u64_0pad(skb, T_ed_uuid, device->ed_uuid) ||
+	    nla_put_u64_0pad(skb, T_capacity,
+			     drbd_get_capacity(device->this_bdev)) ||
+	    nla_put_u64_0pad(skb, T_send_cnt, device->send_cnt) ||
+	    nla_put_u64_0pad(skb, T_recv_cnt, device->recv_cnt) ||
+	    nla_put_u64_0pad(skb, T_read_cnt, device->read_cnt) ||
+	    nla_put_u64_0pad(skb, T_writ_cnt, device->writ_cnt) ||
+	    nla_put_u64_0pad(skb, T_al_writ_cnt, device->al_writ_cnt) ||
+	    nla_put_u64_0pad(skb, T_bm_writ_cnt, device->bm_writ_cnt) ||
 	    nla_put_u32(skb, T_ap_bio_cnt, atomic_read(&device->ap_bio_cnt)) ||
 	    nla_put_u32(skb, T_ap_pending_cnt, atomic_read(&device->ap_pending_cnt)) ||
 	    nla_put_u32(skb, T_rs_pending_cnt, atomic_read(&device->rs_pending_cnt)))
@@ -3657,13 +3658,16 @@ static int nla_put_status_info(struct sk
 			goto nla_put_failure;
 
 		if (nla_put_u32(skb, T_disk_flags, device->ldev->md.flags) ||
-		    nla_put_u64(skb, T_bits_total, drbd_bm_bits(device)) ||
-		    nla_put_u64(skb, T_bits_oos, drbd_bm_total_weight(device)))
+		    nla_put_u64_0pad(skb, T_bits_total, drbd_bm_bits(device)) ||
+		    nla_put_u64_0pad(skb, T_bits_oos,
+				     drbd_bm_total_weight(device)))
 			goto nla_put_failure;
 		if (C_SYNC_SOURCE <= device->state.conn &&
 		    C_PAUSED_SYNC_T >= device->state.conn) {
-			if (nla_put_u64(skb, T_bits_rs_total, device->rs_total) ||
-			    nla_put_u64(skb, T_bits_rs_failed, device->rs_failed))
+			if (nla_put_u64_0pad(skb, T_bits_rs_total,
+					     device->rs_total) ||
+			    nla_put_u64_0pad(skb, T_bits_rs_failed,
+					     device->rs_failed))
 				goto nla_put_failure;
 		}
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/block/loop.c linux-libre-4.7-gnu/drivers/block/loop.c
--- linux-libre-4.6-gnu/drivers/block/loop.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/block/loop.c	2016-07-24 15:23:50.000000000 -0400
@@ -943,7 +943,7 @@ static int loop_set_fd(struct loop_devic
 	mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));
 
 	if (!(lo_flags & LO_FLAGS_READ_ONLY) && file->f_op->fsync)
-		blk_queue_flush(lo->lo_queue, REQ_FLUSH);
+		blk_queue_write_cache(lo->lo_queue, true, false);
 
 	loop_update_dio(lo);
 	set_capacity(lo->lo_disk, size);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/block/mtip32xx/mtip32xx.c linux-libre-4.7-gnu/drivers/block/mtip32xx/mtip32xx.c
--- linux-libre-4.6-gnu/drivers/block/mtip32xx/mtip32xx.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/block/mtip32xx/mtip32xx.c	2016-07-24 15:23:50.000000000 -0400
@@ -3000,14 +3000,14 @@ restart_eh:
 					"Completion workers still active!");
 
 			spin_lock(dd->queue->queue_lock);
-			blk_mq_all_tag_busy_iter(*dd->tags.tags,
+			blk_mq_tagset_busy_iter(&dd->tags,
 							mtip_queue_cmd, dd);
 			spin_unlock(dd->queue->queue_lock);
 
 			set_bit(MTIP_PF_ISSUE_CMDS_BIT, &dd->port->flags);
 
 			if (mtip_device_reset(dd))
-				blk_mq_all_tag_busy_iter(*dd->tags.tags,
+				blk_mq_tagset_busy_iter(&dd->tags,
 							mtip_abort_cmd, dd);
 
 			clear_bit(MTIP_PF_TO_ACTIVE_BIT, &dd->port->flags);
@@ -4023,12 +4023,6 @@ skip_create_disk:
 	blk_queue_io_min(dd->queue, 4096);
 	blk_queue_bounce_limit(dd->queue, dd->pdev->dma_mask);
 
-	/*
-	 * write back cache is not supported in the device. FUA depends on
-	 * write back cache support, hence setting flush support to zero.
-	 */
-	blk_queue_flush(dd->queue, 0);
-
 	/* Signal trim support */
 	if (dd->trim_supp == true) {
 		set_bit(QUEUE_FLAG_DISCARD, &dd->queue->queue_flags);
@@ -4174,7 +4168,7 @@ static int mtip_block_remove(struct driv
 
 	blk_mq_freeze_queue_start(dd->queue);
 	blk_mq_stop_hw_queues(dd->queue);
-	blk_mq_all_tag_busy_iter(dd->tags.tags[0], mtip_no_dev_cleanup, dd);
+	blk_mq_tagset_busy_iter(&dd->tags, mtip_no_dev_cleanup, dd);
 
 	/*
 	 * Delete our gendisk structure. This also removes the device
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/block/nbd.c linux-libre-4.7-gnu/drivers/block/nbd.c
--- linux-libre-4.6-gnu/drivers/block/nbd.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/block/nbd.c	2016-07-24 15:23:50.000000000 -0400
@@ -693,9 +693,9 @@ static void nbd_parse_flags(struct nbd_d
 	if (nbd->flags & NBD_FLAG_SEND_TRIM)
 		queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue);
 	if (nbd->flags & NBD_FLAG_SEND_FLUSH)
-		blk_queue_flush(nbd->disk->queue, REQ_FLUSH);
+		blk_queue_write_cache(nbd->disk->queue, true, false);
 	else
-		blk_queue_flush(nbd->disk->queue, 0);
+		blk_queue_write_cache(nbd->disk->queue, false, false);
 }
 
 static int nbd_dev_dbg_init(struct nbd_device *nbd);
@@ -941,7 +941,7 @@ static int nbd_dev_dbg_init(struct nbd_d
 	debugfs_create_u64("size_bytes", 0444, dir, &nbd->bytesize);
 	debugfs_create_u32("timeout", 0444, dir, &nbd->xmit_timeout);
 	debugfs_create_u32("blocksize", 0444, dir, &nbd->blksize);
-	debugfs_create_file("flags", 0444, dir, &nbd, &nbd_dbg_flags_ops);
+	debugfs_create_file("flags", 0444, dir, nbd, &nbd_dbg_flags_ops);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/block/osdblk.c linux-libre-4.7-gnu/drivers/block/osdblk.c
--- linux-libre-4.6-gnu/drivers/block/osdblk.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/block/osdblk.c	2016-07-24 15:23:50.000000000 -0400
@@ -437,7 +437,7 @@ static int osdblk_init_disk(struct osdbl
 	blk_queue_stack_limits(q, osd_request_queue(osdev->osd));
 
 	blk_queue_prep_rq(q, blk_queue_start_tag);
-	blk_queue_flush(q, REQ_FLUSH);
+	blk_queue_write_cache(q, true, false);
 
 	disk->queue = q;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/block/ps3disk.c linux-libre-4.7-gnu/drivers/block/ps3disk.c
--- linux-libre-4.6-gnu/drivers/block/ps3disk.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/block/ps3disk.c	2016-07-24 15:23:50.000000000 -0400
@@ -468,7 +468,7 @@ static int ps3disk_probe(struct ps3_syst
 	blk_queue_dma_alignment(queue, dev->blk_size-1);
 	blk_queue_logical_block_size(queue, dev->blk_size);
 
-	blk_queue_flush(queue, REQ_FLUSH);
+	blk_queue_write_cache(queue, true, false);
 
 	blk_queue_max_segments(queue, -1);
 	blk_queue_max_segment_size(queue, dev->bounce_size);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/block/rbd.c linux-libre-4.7-gnu/drivers/block/rbd.c
--- linux-libre-4.6-gnu/drivers/block/rbd.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/block/rbd.c	2016-07-24 15:23:50.000000000 -0400
@@ -350,12 +350,12 @@ struct rbd_device {
 	struct rbd_spec		*spec;
 	struct rbd_options	*opts;
 
-	char			*header_name;
+	struct ceph_object_id	header_oid;
+	struct ceph_object_locator header_oloc;
 
 	struct ceph_file_layout	layout;
 
-	struct ceph_osd_event   *watch_event;
-	struct rbd_obj_request	*watch_request;
+	struct ceph_osd_linger_request *watch_handle;
 
 	struct rbd_spec		*parent_spec;
 	u64			parent_overlap;
@@ -1596,12 +1596,6 @@ static int rbd_obj_request_wait(struct r
 	return __rbd_obj_request_wait(obj_request, 0);
 }
 
-static int rbd_obj_request_wait_timeout(struct rbd_obj_request *obj_request,
-					unsigned long timeout)
-{
-	return __rbd_obj_request_wait(obj_request, timeout);
-}
-
 static void rbd_img_request_complete(struct rbd_img_request *img_request)
 {
 
@@ -1751,12 +1745,6 @@ static void rbd_obj_request_complete(str
 		complete_all(&obj_request->completion);
 }
 
-static void rbd_osd_trivial_callback(struct rbd_obj_request *obj_request)
-{
-	dout("%s: obj %p\n", __func__, obj_request);
-	obj_request_done_set(obj_request);
-}
-
 static void rbd_osd_read_callback(struct rbd_obj_request *obj_request)
 {
 	struct rbd_img_request *img_request = NULL;
@@ -1828,13 +1816,12 @@ static void rbd_osd_call_callback(struct
 		obj_request_done_set(obj_request);
 }
 
-static void rbd_osd_req_callback(struct ceph_osd_request *osd_req,
-				struct ceph_msg *msg)
+static void rbd_osd_req_callback(struct ceph_osd_request *osd_req)
 {
 	struct rbd_obj_request *obj_request = osd_req->r_priv;
 	u16 opcode;
 
-	dout("%s: osd_req %p msg %p\n", __func__, osd_req, msg);
+	dout("%s: osd_req %p\n", __func__, osd_req);
 	rbd_assert(osd_req == obj_request->osd_req);
 	if (obj_request_img_data_test(obj_request)) {
 		rbd_assert(obj_request->img_request);
@@ -1878,10 +1865,6 @@ static void rbd_osd_req_callback(struct
 	case CEPH_OSD_OP_CALL:
 		rbd_osd_call_callback(obj_request);
 		break;
-	case CEPH_OSD_OP_NOTIFY_ACK:
-	case CEPH_OSD_OP_WATCH:
-		rbd_osd_trivial_callback(obj_request);
-		break;
 	default:
 		rbd_warn(NULL, "%s: unsupported op %hu",
 			obj_request->object_name, (unsigned short) opcode);
@@ -1896,27 +1879,17 @@ static void rbd_osd_req_format_read(stru
 {
 	struct rbd_img_request *img_request = obj_request->img_request;
 	struct ceph_osd_request *osd_req = obj_request->osd_req;
-	u64 snap_id;
-
-	rbd_assert(osd_req != NULL);
 
-	snap_id = img_request ? img_request->snap_id : CEPH_NOSNAP;
-	ceph_osdc_build_request(osd_req, obj_request->offset,
-			NULL, snap_id, NULL);
+	if (img_request)
+		osd_req->r_snapid = img_request->snap_id;
 }
 
 static void rbd_osd_req_format_write(struct rbd_obj_request *obj_request)
 {
-	struct rbd_img_request *img_request = obj_request->img_request;
 	struct ceph_osd_request *osd_req = obj_request->osd_req;
-	struct ceph_snap_context *snapc;
-	struct timespec mtime = CURRENT_TIME;
 
-	rbd_assert(osd_req != NULL);
-
-	snapc = img_request ? img_request->snapc : NULL;
-	ceph_osdc_build_request(osd_req, obj_request->offset,
-			snapc, CEPH_NOSNAP, &mtime);
+	osd_req->r_mtime = CURRENT_TIME;
+	osd_req->r_data_offset = obj_request->offset;
 }
 
 /*
@@ -1954,7 +1927,7 @@ static struct ceph_osd_request *rbd_osd_
 	osd_req = ceph_osdc_alloc_request(osdc, snapc, num_ops, false,
 					  GFP_NOIO);
 	if (!osd_req)
-		return NULL;	/* ENOMEM */
+		goto fail;
 
 	if (op_type == OBJ_OP_WRITE || op_type == OBJ_OP_DISCARD)
 		osd_req->r_flags = CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK;
@@ -1965,9 +1938,18 @@ static struct ceph_osd_request *rbd_osd_
 	osd_req->r_priv = obj_request;
 
 	osd_req->r_base_oloc.pool = ceph_file_layout_pg_pool(rbd_dev->layout);
-	ceph_oid_set_name(&osd_req->r_base_oid, obj_request->object_name);
+	if (ceph_oid_aprintf(&osd_req->r_base_oid, GFP_NOIO, "%s",
+			     obj_request->object_name))
+		goto fail;
+
+	if (ceph_osdc_alloc_messages(osd_req, GFP_NOIO))
+		goto fail;
 
 	return osd_req;
+
+fail:
+	ceph_osdc_put_request(osd_req);
+	return NULL;
 }
 
 /*
@@ -2003,16 +1985,25 @@ rbd_osd_req_create_copyup(struct rbd_obj
 	osd_req = ceph_osdc_alloc_request(osdc, snapc, num_osd_ops,
 						false, GFP_NOIO);
 	if (!osd_req)
-		return NULL;	/* ENOMEM */
+		goto fail;
 
 	osd_req->r_flags = CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK;
 	osd_req->r_callback = rbd_osd_req_callback;
 	osd_req->r_priv = obj_request;
 
 	osd_req->r_base_oloc.pool = ceph_file_layout_pg_pool(rbd_dev->layout);
-	ceph_oid_set_name(&osd_req->r_base_oid, obj_request->object_name);
+	if (ceph_oid_aprintf(&osd_req->r_base_oid, GFP_NOIO, "%s",
+			     obj_request->object_name))
+		goto fail;
+
+	if (ceph_osdc_alloc_messages(osd_req, GFP_NOIO))
+		goto fail;
 
 	return osd_req;
+
+fail:
+	ceph_osdc_put_request(osd_req);
+	return NULL;
 }
 
 
@@ -2973,17 +2964,20 @@ static int rbd_img_request_submit(struct
 {
 	struct rbd_obj_request *obj_request;
 	struct rbd_obj_request *next_obj_request;
+	int ret = 0;
 
 	dout("%s: img %p\n", __func__, img_request);
-	for_each_obj_request_safe(img_request, obj_request, next_obj_request) {
-		int ret;
 
+	rbd_img_request_get(img_request);
+	for_each_obj_request_safe(img_request, obj_request, next_obj_request) {
 		ret = rbd_img_obj_request_submit(obj_request);
 		if (ret)
-			return ret;
+			goto out_put_ireq;
 	}
 
-	return 0;
+out_put_ireq:
+	rbd_img_request_put(img_request);
+	return ret;
 }
 
 static void rbd_img_parent_read_callback(struct rbd_img_request *img_request)
@@ -3090,45 +3084,18 @@ out_err:
 	obj_request_done_set(obj_request);
 }
 
-static int rbd_obj_notify_ack_sync(struct rbd_device *rbd_dev, u64 notify_id)
-{
-	struct rbd_obj_request *obj_request;
-	struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc;
-	int ret;
-
-	obj_request = rbd_obj_request_create(rbd_dev->header_name, 0, 0,
-							OBJ_REQUEST_NODATA);
-	if (!obj_request)
-		return -ENOMEM;
-
-	ret = -ENOMEM;
-	obj_request->osd_req = rbd_osd_req_create(rbd_dev, OBJ_OP_READ, 1,
-						  obj_request);
-	if (!obj_request->osd_req)
-		goto out;
-
-	osd_req_op_watch_init(obj_request->osd_req, 0, CEPH_OSD_OP_NOTIFY_ACK,
-					notify_id, 0, 0);
-	rbd_osd_req_format_read(obj_request);
-
-	ret = rbd_obj_request_submit(osdc, obj_request);
-	if (ret)
-		goto out;
-	ret = rbd_obj_request_wait(obj_request);
-out:
-	rbd_obj_request_put(obj_request);
-
-	return ret;
-}
+static int rbd_dev_header_watch_sync(struct rbd_device *rbd_dev);
+static void __rbd_dev_header_unwatch_sync(struct rbd_device *rbd_dev);
 
-static void rbd_watch_cb(u64 ver, u64 notify_id, u8 opcode, void *data)
+static void rbd_watch_cb(void *arg, u64 notify_id, u64 cookie,
+			 u64 notifier_id, void *data, size_t data_len)
 {
-	struct rbd_device *rbd_dev = (struct rbd_device *)data;
+	struct rbd_device *rbd_dev = arg;
+	struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc;
 	int ret;
 
-	dout("%s: \"%s\" notify_id %llu opcode %u\n", __func__,
-		rbd_dev->header_name, (unsigned long long)notify_id,
-		(unsigned int)opcode);
+	dout("%s rbd_dev %p cookie %llu notify_id %llu\n", __func__, rbd_dev,
+	     cookie, notify_id);
 
 	/*
 	 * Until adequate refresh error handling is in place, there is
@@ -3140,63 +3107,31 @@ static void rbd_watch_cb(u64 ver, u64 no
 	if (ret)
 		rbd_warn(rbd_dev, "refresh failed: %d", ret);
 
-	ret = rbd_obj_notify_ack_sync(rbd_dev, notify_id);
+	ret = ceph_osdc_notify_ack(osdc, &rbd_dev->header_oid,
+				   &rbd_dev->header_oloc, notify_id, cookie,
+				   NULL, 0);
 	if (ret)
 		rbd_warn(rbd_dev, "notify_ack ret %d", ret);
 }
 
-/*
- * Send a (un)watch request and wait for the ack.  Return a request
- * with a ref held on success or error.
- */
-static struct rbd_obj_request *rbd_obj_watch_request_helper(
-						struct rbd_device *rbd_dev,
-						bool watch)
+static void rbd_watch_errcb(void *arg, u64 cookie, int err)
 {
-	struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc;
-	struct ceph_options *opts = osdc->client->options;
-	struct rbd_obj_request *obj_request;
+	struct rbd_device *rbd_dev = arg;
 	int ret;
 
-	obj_request = rbd_obj_request_create(rbd_dev->header_name, 0, 0,
-					     OBJ_REQUEST_NODATA);
-	if (!obj_request)
-		return ERR_PTR(-ENOMEM);
-
-	obj_request->osd_req = rbd_osd_req_create(rbd_dev, OBJ_OP_WRITE, 1,
-						  obj_request);
-	if (!obj_request->osd_req) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	osd_req_op_watch_init(obj_request->osd_req, 0, CEPH_OSD_OP_WATCH,
-			      rbd_dev->watch_event->cookie, 0, watch);
-	rbd_osd_req_format_write(obj_request);
-
-	if (watch)
-		ceph_osdc_set_request_linger(osdc, obj_request->osd_req);
-
-	ret = rbd_obj_request_submit(osdc, obj_request);
-	if (ret)
-		goto out;
+	rbd_warn(rbd_dev, "encountered watch error: %d", err);
 
-	ret = rbd_obj_request_wait_timeout(obj_request, opts->mount_timeout);
-	if (ret)
-		goto out;
+	__rbd_dev_header_unwatch_sync(rbd_dev);
 
-	ret = obj_request->result;
+	ret = rbd_dev_header_watch_sync(rbd_dev);
 	if (ret) {
-		if (watch)
-			rbd_obj_request_end(obj_request);
-		goto out;
+		rbd_warn(rbd_dev, "failed to reregister watch: %d", ret);
+		return;
 	}
 
-	return obj_request;
-
-out:
-	rbd_obj_request_put(obj_request);
-	return ERR_PTR(ret);
+	ret = rbd_dev_refresh(rbd_dev);
+	if (ret)
+		rbd_warn(rbd_dev, "reregisteration refresh failed: %d", ret);
 }
 
 /*
@@ -3205,35 +3140,33 @@ out:
 static int rbd_dev_header_watch_sync(struct rbd_device *rbd_dev)
 {
 	struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc;
-	struct rbd_obj_request *obj_request;
-	int ret;
+	struct ceph_osd_linger_request *handle;
 
-	rbd_assert(!rbd_dev->watch_event);
-	rbd_assert(!rbd_dev->watch_request);
+	rbd_assert(!rbd_dev->watch_handle);
 
-	ret = ceph_osdc_create_event(osdc, rbd_watch_cb, rbd_dev,
-				     &rbd_dev->watch_event);
-	if (ret < 0)
-		return ret;
+	handle = ceph_osdc_watch(osdc, &rbd_dev->header_oid,
+				 &rbd_dev->header_oloc, rbd_watch_cb,
+				 rbd_watch_errcb, rbd_dev);
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
 
-	obj_request = rbd_obj_watch_request_helper(rbd_dev, true);
-	if (IS_ERR(obj_request)) {
-		ceph_osdc_cancel_event(rbd_dev->watch_event);
-		rbd_dev->watch_event = NULL;
-		return PTR_ERR(obj_request);
-	}
+	rbd_dev->watch_handle = handle;
+	return 0;
+}
 
-	/*
-	 * A watch request is set to linger, so the underlying osd
-	 * request won't go away until we unregister it.  We retain
-	 * a pointer to the object request during that time (in
-	 * rbd_dev->watch_request), so we'll keep a reference to it.
-	 * We'll drop that reference after we've unregistered it in
-	 * rbd_dev_header_unwatch_sync().
-	 */
-	rbd_dev->watch_request = obj_request;
+static void __rbd_dev_header_unwatch_sync(struct rbd_device *rbd_dev)
+{
+	struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc;
+	int ret;
 
-	return 0;
+	if (!rbd_dev->watch_handle)
+		return;
+
+	ret = ceph_osdc_unwatch(osdc, rbd_dev->watch_handle);
+	if (ret)
+		rbd_warn(rbd_dev, "failed to unwatch: %d", ret);
+
+	rbd_dev->watch_handle = NULL;
 }
 
 /*
@@ -3241,24 +3174,7 @@ static int rbd_dev_header_watch_sync(str
  */
 static void rbd_dev_header_unwatch_sync(struct rbd_device *rbd_dev)
 {
-	struct rbd_obj_request *obj_request;
-
-	rbd_assert(rbd_dev->watch_event);
-	rbd_assert(rbd_dev->watch_request);
-
-	rbd_obj_request_end(rbd_dev->watch_request);
-	rbd_obj_request_put(rbd_dev->watch_request);
-	rbd_dev->watch_request = NULL;
-
-	obj_request = rbd_obj_watch_request_helper(rbd_dev, false);
-	if (!IS_ERR(obj_request))
-		rbd_obj_request_put(obj_request);
-	else
-		rbd_warn(rbd_dev, "unable to tear down watch request (%ld)",
-			 PTR_ERR(obj_request));
-
-	ceph_osdc_cancel_event(rbd_dev->watch_event);
-	rbd_dev->watch_event = NULL;
+	__rbd_dev_header_unwatch_sync(rbd_dev);
 
 	dout("%s flushing notifies\n", __func__);
 	ceph_osdc_flush_notifies(&rbd_dev->rbd_client->client->osdc);
@@ -3591,7 +3507,7 @@ static int rbd_dev_v1_header_info(struct
 		if (!ondisk)
 			return -ENOMEM;
 
-		ret = rbd_obj_read_sync(rbd_dev, rbd_dev->header_name,
+		ret = rbd_obj_read_sync(rbd_dev, rbd_dev->header_oid.name,
 				       0, size, ondisk);
 		if (ret < 0)
 			goto out;
@@ -4033,6 +3949,8 @@ static void rbd_dev_release(struct devic
 	struct rbd_device *rbd_dev = dev_to_rbd_dev(dev);
 	bool need_put = !!rbd_dev->opts;
 
+	ceph_oid_destroy(&rbd_dev->header_oid);
+
 	rbd_put_client(rbd_dev->rbd_client);
 	rbd_spec_put(rbd_dev->spec);
 	kfree(rbd_dev->opts);
@@ -4063,6 +3981,9 @@ static struct rbd_device *rbd_dev_create
 	INIT_LIST_HEAD(&rbd_dev->node);
 	init_rwsem(&rbd_dev->header_rwsem);
 
+	ceph_oid_init(&rbd_dev->header_oid);
+	ceph_oloc_init(&rbd_dev->header_oloc);
+
 	rbd_dev->dev.bus = &rbd_bus_type;
 	rbd_dev->dev.type = &rbd_device_type;
 	rbd_dev->dev.parent = &rbd_root_dev;
@@ -4111,7 +4032,7 @@ static int _rbd_dev_v2_snap_size(struct
 		__le64 size;
 	} __attribute__ ((packed)) size_buf = { 0 };
 
-	ret = rbd_obj_method_sync(rbd_dev, rbd_dev->header_name,
+	ret = rbd_obj_method_sync(rbd_dev, rbd_dev->header_oid.name,
 				"rbd", "get_size",
 				&snapid, sizeof (snapid),
 				&size_buf, sizeof (size_buf));
@@ -4151,7 +4072,7 @@ static int rbd_dev_v2_object_prefix(stru
 	if (!reply_buf)
 		return -ENOMEM;
 
-	ret = rbd_obj_method_sync(rbd_dev, rbd_dev->header_name,
+	ret = rbd_obj_method_sync(rbd_dev, rbd_dev->header_oid.name,
 				"rbd", "get_object_prefix", NULL, 0,
 				reply_buf, RBD_OBJ_PREFIX_LEN_MAX);
 	dout("%s: rbd_obj_method_sync returned %d\n", __func__, ret);
@@ -4186,7 +4107,7 @@ static int _rbd_dev_v2_snap_features(str
 	u64 unsup;
 	int ret;
 
-	ret = rbd_obj_method_sync(rbd_dev, rbd_dev->header_name,
+	ret = rbd_obj_method_sync(rbd_dev, rbd_dev->header_oid.name,
 				"rbd", "get_features",
 				&snapid, sizeof (snapid),
 				&features_buf, sizeof (features_buf));
@@ -4248,7 +4169,7 @@ static int rbd_dev_v2_parent_info(struct
 	}
 
 	snapid = cpu_to_le64(rbd_dev->spec->snap_id);
-	ret = rbd_obj_method_sync(rbd_dev, rbd_dev->header_name,
+	ret = rbd_obj_method_sync(rbd_dev, rbd_dev->header_oid.name,
 				"rbd", "get_parent",
 				&snapid, sizeof (snapid),
 				reply_buf, size);
@@ -4351,7 +4272,7 @@ static int rbd_dev_v2_striping_info(stru
 	u64 stripe_count;
 	int ret;
 
-	ret = rbd_obj_method_sync(rbd_dev, rbd_dev->header_name,
+	ret = rbd_obj_method_sync(rbd_dev, rbd_dev->header_oid.name,
 				"rbd", "get_stripe_unit_count", NULL, 0,
 				(char *)&striping_info_buf, size);
 	dout("%s: rbd_obj_method_sync returned %d\n", __func__, ret);
@@ -4599,7 +4520,7 @@ static int rbd_dev_v2_snap_context(struc
 	if (!reply_buf)
 		return -ENOMEM;
 
-	ret = rbd_obj_method_sync(rbd_dev, rbd_dev->header_name,
+	ret = rbd_obj_method_sync(rbd_dev, rbd_dev->header_oid.name,
 				"rbd", "get_snapcontext", NULL, 0,
 				reply_buf, size);
 	dout("%s: rbd_obj_method_sync returned %d\n", __func__, ret);
@@ -4664,7 +4585,7 @@ static const char *rbd_dev_v2_snap_name(
 		return ERR_PTR(-ENOMEM);
 
 	snapid = cpu_to_le64(snap_id);
-	ret = rbd_obj_method_sync(rbd_dev, rbd_dev->header_name,
+	ret = rbd_obj_method_sync(rbd_dev, rbd_dev->header_oid.name,
 				"rbd", "get_snapshot_name",
 				&snapid, sizeof (snapid),
 				reply_buf, size);
@@ -4975,13 +4896,13 @@ static int rbd_add_get_pool_id(struct rb
 again:
 	ret = ceph_pg_poolid_by_name(rbdc->client->osdc.osdmap, pool_name);
 	if (ret == -ENOENT && tries++ < 1) {
-		ret = ceph_monc_do_get_version(&rbdc->client->monc, "osdmap",
-					       &newest_epoch);
+		ret = ceph_monc_get_version(&rbdc->client->monc, "osdmap",
+					    &newest_epoch);
 		if (ret < 0)
 			return ret;
 
 		if (rbdc->client->osdc.osdmap->epoch < newest_epoch) {
-			ceph_monc_request_next_osdmap(&rbdc->client->monc);
+			ceph_osdc_maybe_request_map(&rbdc->client->osdc);
 			(void) ceph_monc_wait_osdmap(&rbdc->client->monc,
 						     newest_epoch,
 						     opts->mount_timeout);
@@ -5260,35 +5181,26 @@ err_out_unlock:
 static int rbd_dev_header_name(struct rbd_device *rbd_dev)
 {
 	struct rbd_spec *spec = rbd_dev->spec;
-	size_t size;
+	int ret;
 
 	/* Record the header object name for this rbd image. */
 
 	rbd_assert(rbd_image_format_valid(rbd_dev->image_format));
 
+	rbd_dev->header_oloc.pool = ceph_file_layout_pg_pool(rbd_dev->layout);
 	if (rbd_dev->image_format == 1)
-		size = strlen(spec->image_name) + sizeof (RBD_SUFFIX);
+		ret = ceph_oid_aprintf(&rbd_dev->header_oid, GFP_KERNEL, "%s%s",
+				       spec->image_name, RBD_SUFFIX);
 	else
-		size = sizeof (RBD_HEADER_PREFIX) + strlen(spec->image_id);
-
-	rbd_dev->header_name = kmalloc(size, GFP_KERNEL);
-	if (!rbd_dev->header_name)
-		return -ENOMEM;
+		ret = ceph_oid_aprintf(&rbd_dev->header_oid, GFP_KERNEL, "%s%s",
+				       RBD_HEADER_PREFIX, spec->image_id);
 
-	if (rbd_dev->image_format == 1)
-		sprintf(rbd_dev->header_name, "%s%s",
-			spec->image_name, RBD_SUFFIX);
-	else
-		sprintf(rbd_dev->header_name, "%s%s",
-			RBD_HEADER_PREFIX, spec->image_id);
-	return 0;
+	return ret;
 }
 
 static void rbd_dev_image_release(struct rbd_device *rbd_dev)
 {
 	rbd_dev_unprobe(rbd_dev);
-	kfree(rbd_dev->header_name);
-	rbd_dev->header_name = NULL;
 	rbd_dev->image_format = 0;
 	kfree(rbd_dev->spec->image_id);
 	rbd_dev->spec->image_id = NULL;
@@ -5327,7 +5239,7 @@ static int rbd_dev_image_probe(struct rb
 				pr_info("image %s/%s does not exist\n",
 					rbd_dev->spec->pool_name,
 					rbd_dev->spec->image_name);
-			goto out_header_name;
+			goto err_out_format;
 		}
 	}
 
@@ -5373,7 +5285,7 @@ static int rbd_dev_image_probe(struct rb
 		goto err_out_probe;
 
 	dout("discovered format %u image, header name is %s\n",
-		rbd_dev->image_format, rbd_dev->header_name);
+		rbd_dev->image_format, rbd_dev->header_oid.name);
 	return 0;
 
 err_out_probe:
@@ -5381,9 +5293,6 @@ err_out_probe:
 err_out_watch:
 	if (!depth)
 		rbd_dev_header_unwatch_sync(rbd_dev);
-out_header_name:
-	kfree(rbd_dev->header_name);
-	rbd_dev->header_name = NULL;
 err_out_format:
 	rbd_dev->image_format = 0;
 	kfree(rbd_dev->spec->image_id);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/block/skd_main.c linux-libre-4.7-gnu/drivers/block/skd_main.c
--- linux-libre-4.6-gnu/drivers/block/skd_main.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/block/skd_main.c	2016-07-24 15:23:50.000000000 -0400
@@ -133,7 +133,6 @@ MODULE_VERSION(DRV_VERSION "-" DRV_BUILD
 #define SKD_TIMER_MINUTES(minutes) ((minutes) * (60))
 
 #define INQ_STD_NBYTES 36
-#define SKD_DISCARD_CDB_LENGTH	24
 
 enum skd_drvr_state {
 	SKD_DRVR_STATE_LOAD,
@@ -212,7 +211,6 @@ struct skd_request_context {
 
 	struct request *req;
 	u8 flush_cmd;
-	u8 discard_page;
 
 	u32 timeout_stamp;
 	u8 sg_data_dir;
@@ -230,7 +228,6 @@ struct skd_request_context {
 };
 #define SKD_DATA_DIR_HOST_TO_CARD       1
 #define SKD_DATA_DIR_CARD_TO_HOST       2
-#define SKD_DATA_DIR_NONE		3	/* especially for DISCARD requests. */
 
 struct skd_special_context {
 	struct skd_request_context req;
@@ -540,31 +537,6 @@ skd_prep_zerosize_flush_cdb(struct skd_s
 	scsi_req->cdb[9] = 0;
 }
 
-static void
-skd_prep_discard_cdb(struct skd_scsi_request *scsi_req,
-		     struct skd_request_context *skreq,
-		     struct page *page,
-		     u32 lba, u32 count)
-{
-	char *buf;
-	unsigned long len;
-	struct request *req;
-
-	buf = page_address(page);
-	len = SKD_DISCARD_CDB_LENGTH;
-
-	scsi_req->cdb[0] = UNMAP;
-	scsi_req->cdb[8] = len;
-
-	put_unaligned_be16(6 + 16, &buf[0]);
-	put_unaligned_be16(16, &buf[2]);
-	put_unaligned_be64(lba, &buf[8]);
-	put_unaligned_be32(count, &buf[16]);
-
-	req = skreq->req;
-	blk_add_request_payload(req, page, len);
-}
-
 static void skd_request_fn_not_online(struct request_queue *q);
 
 static void skd_request_fn(struct request_queue *q)
@@ -575,7 +547,6 @@ static void skd_request_fn(struct reques
 	struct skd_request_context *skreq;
 	struct request *req = NULL;
 	struct skd_scsi_request *scsi_req;
-	struct page *page;
 	unsigned long io_flags;
 	int error;
 	u32 lba;
@@ -669,7 +640,6 @@ static void skd_request_fn(struct reques
 		skreq->flush_cmd = 0;
 		skreq->n_sg = 0;
 		skreq->sg_byte_count = 0;
-		skreq->discard_page = 0;
 
 		/*
 		 * OK to now dequeue request from q.
@@ -735,18 +705,7 @@ static void skd_request_fn(struct reques
 		else
 			skreq->sg_data_dir = SKD_DATA_DIR_HOST_TO_CARD;
 
-		if (io_flags & REQ_DISCARD) {
-			page = alloc_page(GFP_ATOMIC | __GFP_ZERO);
-			if (!page) {
-				pr_err("request_fn:Page allocation failed.\n");
-				skd_end_request(skdev, skreq, -ENOMEM);
-				break;
-			}
-			skreq->discard_page = 1;
-			req->completion_data = page;
-			skd_prep_discard_cdb(scsi_req, skreq, page, lba, count);
-
-		} else if (flush == SKD_FLUSH_ZERO_SIZE_FIRST) {
+		if (flush == SKD_FLUSH_ZERO_SIZE_FIRST) {
 			skd_prep_zerosize_flush_cdb(scsi_req, skreq);
 			SKD_ASSERT(skreq->flush_cmd == 1);
 
@@ -851,16 +810,6 @@ skip_sg:
 static void skd_end_request(struct skd_device *skdev,
 			    struct skd_request_context *skreq, int error)
 {
-	struct request *req = skreq->req;
-	unsigned int io_flags = req->cmd_flags;
-
-	if ((io_flags & REQ_DISCARD) &&
-		(skreq->discard_page == 1)) {
-		pr_debug("%s:%s:%d, free the page!",
-			 skdev->name, __func__, __LINE__);
-		__free_page(req->completion_data);
-	}
-
 	if (unlikely(error)) {
 		struct request *req = skreq->req;
 		char *cmd = (rq_data_dir(req) == READ) ? "read" : "write";
@@ -4412,19 +4361,13 @@ static int skd_cons_disk(struct skd_devi
 	disk->queue = q;
 	q->queuedata = skdev;
 
-	blk_queue_flush(q, REQ_FLUSH | REQ_FUA);
+	blk_queue_write_cache(q, true, true);
 	blk_queue_max_segments(q, skdev->sgs_per_request);
 	blk_queue_max_hw_sectors(q, SKD_N_MAX_SECTORS);
 
 	/* set sysfs ptimal_io_size to 8K */
 	blk_queue_io_opt(q, 8192);
 
-	/* DISCARD Flag initialization. */
-	q->limits.discard_granularity = 8192;
-	q->limits.discard_alignment = 0;
-	blk_queue_max_discard_sectors(q, UINT_MAX >> 9);
-	q->limits.discard_zeroes_data = 1;
-	queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q);
 	queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q);
 	queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, q);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/block/virtio_blk.c linux-libre-4.7-gnu/drivers/block/virtio_blk.c
--- linux-libre-4.6-gnu/drivers/block/virtio_blk.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/block/virtio_blk.c	2016-07-24 15:23:50.000000000 -0400
@@ -493,11 +493,7 @@ static void virtblk_update_cache_mode(st
 	u8 writeback = virtblk_get_cache_mode(vdev);
 	struct virtio_blk *vblk = vdev->priv;
 
-	if (writeback)
-		blk_queue_flush(vblk->disk->queue, REQ_FLUSH);
-	else
-		blk_queue_flush(vblk->disk->queue, 0);
-
+	blk_queue_write_cache(vblk->disk->queue, writeback, false);
 	revalidate_disk(vblk->disk);
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/block/xen-blkback/xenbus.c linux-libre-4.7-gnu/drivers/block/xen-blkback/xenbus.c
--- linux-libre-4.6-gnu/drivers/block/xen-blkback/xenbus.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/block/xen-blkback/xenbus.c	2016-07-24 15:23:50.000000000 -0400
@@ -477,7 +477,7 @@ static int xen_vbd_create(struct xen_blk
 		vbd->type |= VDISK_REMOVABLE;
 
 	q = bdev_get_queue(bdev);
-	if (q && q->flush_flags)
+	if (q && test_bit(QUEUE_FLAG_WC, &q->queue_flags))
 		vbd->flush_support = true;
 
 	if (q && blk_queue_secdiscard(q))
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/block/xen-blkfront.c linux-libre-4.7-gnu/drivers/block/xen-blkfront.c
--- linux-libre-4.6-gnu/drivers/block/xen-blkfront.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/block/xen-blkfront.c	2016-07-24 15:23:50.000000000 -0400
@@ -207,6 +207,9 @@ struct blkfront_info
 	struct blk_mq_tag_set tag_set;
 	struct blkfront_ring_info *rinfo;
 	unsigned int nr_rings;
+	/* Save uncomplete reqs and bios for migration. */
+	struct list_head requests;
+	struct bio_list bio_list;
 };
 
 static unsigned int nr_minors;
@@ -874,8 +877,12 @@ static int blkif_queue_rq(struct blk_mq_
 			  const struct blk_mq_queue_data *qd)
 {
 	unsigned long flags;
-	struct blkfront_ring_info *rinfo = (struct blkfront_ring_info *)hctx->driver_data;
+	int qid = hctx->queue_num;
+	struct blkfront_info *info = hctx->queue->queuedata;
+	struct blkfront_ring_info *rinfo = NULL;
 
+	BUG_ON(info->nr_rings <= qid);
+	rinfo = &info->rinfo[qid];
 	blk_mq_start_request(qd->rq);
 	spin_lock_irqsave(&rinfo->ring_lock, flags);
 	if (RING_FULL(&rinfo->ring))
@@ -901,20 +908,9 @@ out_busy:
 	return BLK_MQ_RQ_QUEUE_BUSY;
 }
 
-static int blk_mq_init_hctx(struct blk_mq_hw_ctx *hctx, void *data,
-			    unsigned int index)
-{
-	struct blkfront_info *info = (struct blkfront_info *)data;
-
-	BUG_ON(info->nr_rings <= index);
-	hctx->driver_data = &info->rinfo[index];
-	return 0;
-}
-
 static struct blk_mq_ops blkfront_mq_ops = {
 	.queue_rq = blkif_queue_rq,
 	.map_queue = blk_mq_map_queue,
-	.init_hctx = blk_mq_init_hctx,
 };
 
 static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size,
@@ -950,6 +946,7 @@ static int xlvbd_init_blk_queue(struct g
 		return PTR_ERR(rq);
 	}
 
+	rq->queuedata = info;
 	queue_flag_set_unlocked(QUEUE_FLAG_VIRT, rq);
 
 	if (info->feature_discard) {
@@ -998,7 +995,8 @@ static const char *flush_info(unsigned i
 
 static void xlvbd_flush(struct blkfront_info *info)
 {
-	blk_queue_flush(info->rq, info->feature_flush);
+	blk_queue_write_cache(info->rq, info->feature_flush & REQ_FLUSH,
+				info->feature_flush & REQ_FUA);
 	pr_info("blkfront: %s: %s %s %s %s %s\n",
 		info->gd->disk_name, flush_info(info->feature_flush),
 		"persistent grants:", info->feature_persistent ?
@@ -2007,69 +2005,22 @@ static int blkif_recover(struct blkfront
 {
 	unsigned int i, r_index;
 	struct request *req, *n;
-	struct blk_shadow *copy;
 	int rc;
 	struct bio *bio, *cloned_bio;
-	struct bio_list bio_list, merge_bio;
 	unsigned int segs, offset;
 	int pending, size;
 	struct split_bio *split_bio;
-	struct list_head requests;
 
 	blkfront_gather_backend_features(info);
 	segs = info->max_indirect_segments ? : BLKIF_MAX_SEGMENTS_PER_REQUEST;
 	blk_queue_max_segments(info->rq, segs);
-	bio_list_init(&bio_list);
-	INIT_LIST_HEAD(&requests);
 
 	for (r_index = 0; r_index < info->nr_rings; r_index++) {
-		struct blkfront_ring_info *rinfo;
-
-		rinfo = &info->rinfo[r_index];
-		/* Stage 1: Make a safe copy of the shadow state. */
-		copy = kmemdup(rinfo->shadow, sizeof(rinfo->shadow),
-			       GFP_NOIO | __GFP_REPEAT | __GFP_HIGH);
-		if (!copy)
-			return -ENOMEM;
-
-		/* Stage 2: Set up free list. */
-		memset(&rinfo->shadow, 0, sizeof(rinfo->shadow));
-		for (i = 0; i < BLK_RING_SIZE(info); i++)
-			rinfo->shadow[i].req.u.rw.id = i+1;
-		rinfo->shadow_free = rinfo->ring.req_prod_pvt;
-		rinfo->shadow[BLK_RING_SIZE(info)-1].req.u.rw.id = 0x0fffffff;
+		struct blkfront_ring_info *rinfo = &info->rinfo[r_index];
 
 		rc = blkfront_setup_indirect(rinfo);
-		if (rc) {
-			kfree(copy);
+		if (rc)
 			return rc;
-		}
-
-		for (i = 0; i < BLK_RING_SIZE(info); i++) {
-			/* Not in use? */
-			if (!copy[i].request)
-				continue;
-
-			/*
-			 * Get the bios in the request so we can re-queue them.
-			 */
-			if (copy[i].request->cmd_flags &
-			    (REQ_FLUSH | REQ_FUA | REQ_DISCARD | REQ_SECURE)) {
-				/*
-				 * Flush operations don't contain bios, so
-				 * we need to requeue the whole request
-				 */
-				list_add(&copy[i].request->queuelist, &requests);
-				continue;
-			}
-			merge_bio.head = copy[i].request->bio;
-			merge_bio.tail = copy[i].request->biotail;
-			bio_list_merge(&bio_list, &merge_bio);
-			copy[i].request->bio = NULL;
-			blk_end_request_all(copy[i].request, 0);
-		}
-
-		kfree(copy);
 	}
 	xenbus_switch_state(info->xbdev, XenbusStateConnected);
 
@@ -2084,7 +2035,7 @@ static int blkif_recover(struct blkfront
 		kick_pending_request_queues(rinfo);
 	}
 
-	list_for_each_entry_safe(req, n, &requests, queuelist) {
+	list_for_each_entry_safe(req, n, &info->requests, queuelist) {
 		/* Requeue pending requests (flush or discard) */
 		list_del_init(&req->queuelist);
 		BUG_ON(req->nr_phys_segments > segs);
@@ -2092,7 +2043,7 @@ static int blkif_recover(struct blkfront
 	}
 	blk_mq_kick_requeue_list(info->rq);
 
-	while ((bio = bio_list_pop(&bio_list)) != NULL) {
+	while ((bio = bio_list_pop(&info->bio_list)) != NULL) {
 		/* Traverse the list of pending bios and re-queue them */
 		if (bio_segments(bio) > segs) {
 			/*
@@ -2138,9 +2089,42 @@ static int blkfront_resume(struct xenbus
 {
 	struct blkfront_info *info = dev_get_drvdata(&dev->dev);
 	int err = 0;
+	unsigned int i, j;
 
 	dev_dbg(&dev->dev, "blkfront_resume: %s\n", dev->nodename);
 
+	bio_list_init(&info->bio_list);
+	INIT_LIST_HEAD(&info->requests);
+	for (i = 0; i < info->nr_rings; i++) {
+		struct blkfront_ring_info *rinfo = &info->rinfo[i];
+		struct bio_list merge_bio;
+		struct blk_shadow *shadow = rinfo->shadow;
+
+		for (j = 0; j < BLK_RING_SIZE(info); j++) {
+			/* Not in use? */
+			if (!shadow[j].request)
+				continue;
+
+			/*
+			 * Get the bios in the request so we can re-queue them.
+			 */
+			if (shadow[j].request->cmd_flags &
+					(REQ_FLUSH | REQ_FUA | REQ_DISCARD | REQ_SECURE)) {
+				/*
+				 * Flush operations don't contain bios, so
+				 * we need to requeue the whole request
+				 */
+				list_add(&shadow[j].request->queuelist, &info->requests);
+				continue;
+			}
+			merge_bio.head = shadow[j].request->bio;
+			merge_bio.tail = shadow[j].request->biotail;
+			bio_list_merge(&info->bio_list, &merge_bio);
+			shadow[j].request->bio = NULL;
+			blk_mq_end_request(shadow[j].request, 0);
+		}
+	}
+
 	blkif_free(info, info->connected == BLKIF_STATE_CONNECTED);
 
 	err = negotiate_mq(info);
@@ -2148,6 +2132,8 @@ static int blkfront_resume(struct xenbus
 		return err;
 
 	err = talk_to_blkback(dev, info);
+	if (!err)
+		blk_mq_update_nr_hw_queues(&info->tag_set, info->nr_rings);
 
 	/*
 	 * We have to wait for the backend to switch to
@@ -2484,10 +2470,23 @@ static void blkback_changed(struct xenbu
 		break;
 
 	case XenbusStateConnected:
-		if (dev->state != XenbusStateInitialised) {
+		/*
+		 * talk_to_blkback sets state to XenbusStateInitialised
+		 * and blkfront_connect sets it to XenbusStateConnected
+		 * (if connection went OK).
+		 *
+		 * If the backend (or toolstack) decides to poke at backend
+		 * state (and re-trigger the watch by setting the state repeatedly
+		 * to XenbusStateConnected (4)) we need to deal with this.
+		 * This is allowed as this is used to communicate to the guest
+		 * that the size of disk has changed!
+		 */
+		if ((dev->state != XenbusStateInitialised) &&
+		    (dev->state != XenbusStateConnected)) {
 			if (talk_to_blkback(dev, info))
 				break;
 		}
+
 		blkfront_connect(info);
 		break;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/block/zram/zcomp.c linux-libre-4.7-gnu/drivers/block/zram/zcomp.c
--- linux-libre-4.6-gnu/drivers/block/zram/zcomp.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/block/zram/zcomp.c	2016-07-24 15:23:50.000000000 -0400
@@ -13,6 +13,7 @@
 #include <linux/slab.h>
 #include <linux/wait.h>
 #include <linux/sched.h>
+#include <linux/cpu.h>
 
 #include "zcomp.h"
 #include "zcomp_lzo.h"
@@ -20,29 +21,6 @@
 #include "zcomp_lz4.h"
 #endif
 
-/*
- * single zcomp_strm backend
- */
-struct zcomp_strm_single {
-	struct mutex strm_lock;
-	struct zcomp_strm *zstrm;
-};
-
-/*
- * multi zcomp_strm backend
- */
-struct zcomp_strm_multi {
-	/* protect strm list */
-	spinlock_t strm_lock;
-	/* max possible number of zstrm streams */
-	int max_strm;
-	/* number of available zstrm streams */
-	int avail_strm;
-	/* list of available strms */
-	struct list_head idle_strm;
-	wait_queue_head_t strm_wait;
-};
-
 static struct zcomp_backend *backends[] = {
 	&zcomp_lzo,
 #ifdef CONFIG_ZRAM_LZ4_COMPRESS
@@ -93,188 +71,6 @@ static struct zcomp_strm *zcomp_strm_all
 	return zstrm;
 }
 
-/*
- * get idle zcomp_strm or wait until other process release
- * (zcomp_strm_release()) one for us
- */
-static struct zcomp_strm *zcomp_strm_multi_find(struct zcomp *comp)
-{
-	struct zcomp_strm_multi *zs = comp->stream;
-	struct zcomp_strm *zstrm;
-
-	while (1) {
-		spin_lock(&zs->strm_lock);
-		if (!list_empty(&zs->idle_strm)) {
-			zstrm = list_entry(zs->idle_strm.next,
-					struct zcomp_strm, list);
-			list_del(&zstrm->list);
-			spin_unlock(&zs->strm_lock);
-			return zstrm;
-		}
-		/* zstrm streams limit reached, wait for idle stream */
-		if (zs->avail_strm >= zs->max_strm) {
-			spin_unlock(&zs->strm_lock);
-			wait_event(zs->strm_wait, !list_empty(&zs->idle_strm));
-			continue;
-		}
-		/* allocate new zstrm stream */
-		zs->avail_strm++;
-		spin_unlock(&zs->strm_lock);
-		/*
-		 * This function can be called in swapout/fs write path
-		 * so we can't use GFP_FS|IO. And it assumes we already
-		 * have at least one stream in zram initialization so we
-		 * don't do best effort to allocate more stream in here.
-		 * A default stream will work well without further multiple
-		 * streams. That's why we use NORETRY | NOWARN.
-		 */
-		zstrm = zcomp_strm_alloc(comp, GFP_NOIO | __GFP_NORETRY |
-					__GFP_NOWARN);
-		if (!zstrm) {
-			spin_lock(&zs->strm_lock);
-			zs->avail_strm--;
-			spin_unlock(&zs->strm_lock);
-			wait_event(zs->strm_wait, !list_empty(&zs->idle_strm));
-			continue;
-		}
-		break;
-	}
-	return zstrm;
-}
-
-/* add stream back to idle list and wake up waiter or free the stream */
-static void zcomp_strm_multi_release(struct zcomp *comp, struct zcomp_strm *zstrm)
-{
-	struct zcomp_strm_multi *zs = comp->stream;
-
-	spin_lock(&zs->strm_lock);
-	if (zs->avail_strm <= zs->max_strm) {
-		list_add(&zstrm->list, &zs->idle_strm);
-		spin_unlock(&zs->strm_lock);
-		wake_up(&zs->strm_wait);
-		return;
-	}
-
-	zs->avail_strm--;
-	spin_unlock(&zs->strm_lock);
-	zcomp_strm_free(comp, zstrm);
-}
-
-/* change max_strm limit */
-static bool zcomp_strm_multi_set_max_streams(struct zcomp *comp, int num_strm)
-{
-	struct zcomp_strm_multi *zs = comp->stream;
-	struct zcomp_strm *zstrm;
-
-	spin_lock(&zs->strm_lock);
-	zs->max_strm = num_strm;
-	/*
-	 * if user has lowered the limit and there are idle streams,
-	 * immediately free as much streams (and memory) as we can.
-	 */
-	while (zs->avail_strm > num_strm && !list_empty(&zs->idle_strm)) {
-		zstrm = list_entry(zs->idle_strm.next,
-				struct zcomp_strm, list);
-		list_del(&zstrm->list);
-		zcomp_strm_free(comp, zstrm);
-		zs->avail_strm--;
-	}
-	spin_unlock(&zs->strm_lock);
-	return true;
-}
-
-static void zcomp_strm_multi_destroy(struct zcomp *comp)
-{
-	struct zcomp_strm_multi *zs = comp->stream;
-	struct zcomp_strm *zstrm;
-
-	while (!list_empty(&zs->idle_strm)) {
-		zstrm = list_entry(zs->idle_strm.next,
-				struct zcomp_strm, list);
-		list_del(&zstrm->list);
-		zcomp_strm_free(comp, zstrm);
-	}
-	kfree(zs);
-}
-
-static int zcomp_strm_multi_create(struct zcomp *comp, int max_strm)
-{
-	struct zcomp_strm *zstrm;
-	struct zcomp_strm_multi *zs;
-
-	comp->destroy = zcomp_strm_multi_destroy;
-	comp->strm_find = zcomp_strm_multi_find;
-	comp->strm_release = zcomp_strm_multi_release;
-	comp->set_max_streams = zcomp_strm_multi_set_max_streams;
-	zs = kmalloc(sizeof(struct zcomp_strm_multi), GFP_KERNEL);
-	if (!zs)
-		return -ENOMEM;
-
-	comp->stream = zs;
-	spin_lock_init(&zs->strm_lock);
-	INIT_LIST_HEAD(&zs->idle_strm);
-	init_waitqueue_head(&zs->strm_wait);
-	zs->max_strm = max_strm;
-	zs->avail_strm = 1;
-
-	zstrm = zcomp_strm_alloc(comp, GFP_KERNEL);
-	if (!zstrm) {
-		kfree(zs);
-		return -ENOMEM;
-	}
-	list_add(&zstrm->list, &zs->idle_strm);
-	return 0;
-}
-
-static struct zcomp_strm *zcomp_strm_single_find(struct zcomp *comp)
-{
-	struct zcomp_strm_single *zs = comp->stream;
-	mutex_lock(&zs->strm_lock);
-	return zs->zstrm;
-}
-
-static void zcomp_strm_single_release(struct zcomp *comp,
-		struct zcomp_strm *zstrm)
-{
-	struct zcomp_strm_single *zs = comp->stream;
-	mutex_unlock(&zs->strm_lock);
-}
-
-static bool zcomp_strm_single_set_max_streams(struct zcomp *comp, int num_strm)
-{
-	/* zcomp_strm_single support only max_comp_streams == 1 */
-	return false;
-}
-
-static void zcomp_strm_single_destroy(struct zcomp *comp)
-{
-	struct zcomp_strm_single *zs = comp->stream;
-	zcomp_strm_free(comp, zs->zstrm);
-	kfree(zs);
-}
-
-static int zcomp_strm_single_create(struct zcomp *comp)
-{
-	struct zcomp_strm_single *zs;
-
-	comp->destroy = zcomp_strm_single_destroy;
-	comp->strm_find = zcomp_strm_single_find;
-	comp->strm_release = zcomp_strm_single_release;
-	comp->set_max_streams = zcomp_strm_single_set_max_streams;
-	zs = kmalloc(sizeof(struct zcomp_strm_single), GFP_KERNEL);
-	if (!zs)
-		return -ENOMEM;
-
-	comp->stream = zs;
-	mutex_init(&zs->strm_lock);
-	zs->zstrm = zcomp_strm_alloc(comp, GFP_KERNEL);
-	if (!zs->zstrm) {
-		kfree(zs);
-		return -ENOMEM;
-	}
-	return 0;
-}
-
 /* show available compressors */
 ssize_t zcomp_available_show(const char *comp, char *buf)
 {
@@ -299,19 +95,14 @@ bool zcomp_available_algorithm(const cha
 	return find_backend(comp) != NULL;
 }
 
-bool zcomp_set_max_streams(struct zcomp *comp, int num_strm)
-{
-	return comp->set_max_streams(comp, num_strm);
-}
-
 struct zcomp_strm *zcomp_strm_find(struct zcomp *comp)
 {
-	return comp->strm_find(comp);
+	return *get_cpu_ptr(comp->stream);
 }
 
 void zcomp_strm_release(struct zcomp *comp, struct zcomp_strm *zstrm)
 {
-	comp->strm_release(comp, zstrm);
+	put_cpu_ptr(comp->stream);
 }
 
 int zcomp_compress(struct zcomp *comp, struct zcomp_strm *zstrm,
@@ -327,9 +118,83 @@ int zcomp_decompress(struct zcomp *comp,
 	return comp->backend->decompress(src, src_len, dst);
 }
 
+static int __zcomp_cpu_notifier(struct zcomp *comp,
+		unsigned long action, unsigned long cpu)
+{
+	struct zcomp_strm *zstrm;
+
+	switch (action) {
+	case CPU_UP_PREPARE:
+		if (WARN_ON(*per_cpu_ptr(comp->stream, cpu)))
+			break;
+		zstrm = zcomp_strm_alloc(comp, GFP_KERNEL);
+		if (IS_ERR_OR_NULL(zstrm)) {
+			pr_err("Can't allocate a compression stream\n");
+			return NOTIFY_BAD;
+		}
+		*per_cpu_ptr(comp->stream, cpu) = zstrm;
+		break;
+	case CPU_DEAD:
+	case CPU_UP_CANCELED:
+		zstrm = *per_cpu_ptr(comp->stream, cpu);
+		if (!IS_ERR_OR_NULL(zstrm))
+			zcomp_strm_free(comp, zstrm);
+		*per_cpu_ptr(comp->stream, cpu) = NULL;
+		break;
+	default:
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+static int zcomp_cpu_notifier(struct notifier_block *nb,
+		unsigned long action, void *pcpu)
+{
+	unsigned long cpu = (unsigned long)pcpu;
+	struct zcomp *comp = container_of(nb, typeof(*comp), notifier);
+
+	return __zcomp_cpu_notifier(comp, action, cpu);
+}
+
+static int zcomp_init(struct zcomp *comp)
+{
+	unsigned long cpu;
+	int ret;
+
+	comp->notifier.notifier_call = zcomp_cpu_notifier;
+
+	comp->stream = alloc_percpu(struct zcomp_strm *);
+	if (!comp->stream)
+		return -ENOMEM;
+
+	cpu_notifier_register_begin();
+	for_each_online_cpu(cpu) {
+		ret = __zcomp_cpu_notifier(comp, CPU_UP_PREPARE, cpu);
+		if (ret == NOTIFY_BAD)
+			goto cleanup;
+	}
+	__register_cpu_notifier(&comp->notifier);
+	cpu_notifier_register_done();
+	return 0;
+
+cleanup:
+	for_each_online_cpu(cpu)
+		__zcomp_cpu_notifier(comp, CPU_UP_CANCELED, cpu);
+	cpu_notifier_register_done();
+	return -ENOMEM;
+}
+
 void zcomp_destroy(struct zcomp *comp)
 {
-	comp->destroy(comp);
+	unsigned long cpu;
+
+	cpu_notifier_register_begin();
+	for_each_online_cpu(cpu)
+		__zcomp_cpu_notifier(comp, CPU_UP_CANCELED, cpu);
+	__unregister_cpu_notifier(&comp->notifier);
+	cpu_notifier_register_done();
+
+	free_percpu(comp->stream);
 	kfree(comp);
 }
 
@@ -339,9 +204,9 @@ void zcomp_destroy(struct zcomp *comp)
  * backend pointer or ERR_PTR if things went bad. ERR_PTR(-EINVAL)
  * if requested algorithm is not supported, ERR_PTR(-ENOMEM) in
  * case of allocation error, or any other error potentially
- * returned by functions zcomp_strm_{multi,single}_create.
+ * returned by zcomp_init().
  */
-struct zcomp *zcomp_create(const char *compress, int max_strm)
+struct zcomp *zcomp_create(const char *compress)
 {
 	struct zcomp *comp;
 	struct zcomp_backend *backend;
@@ -356,10 +221,7 @@ struct zcomp *zcomp_create(const char *c
 		return ERR_PTR(-ENOMEM);
 
 	comp->backend = backend;
-	if (max_strm > 1)
-		error = zcomp_strm_multi_create(comp, max_strm);
-	else
-		error = zcomp_strm_single_create(comp);
+	error = zcomp_init(comp);
 	if (error) {
 		kfree(comp);
 		return ERR_PTR(error);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/block/zram/zcomp.h linux-libre-4.7-gnu/drivers/block/zram/zcomp.h
--- linux-libre-4.6-gnu/drivers/block/zram/zcomp.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/block/zram/zcomp.h	2016-07-24 15:23:50.000000000 -0400
@@ -10,8 +10,6 @@
 #ifndef _ZCOMP_H_
 #define _ZCOMP_H_
 
-#include <linux/mutex.h>
-
 struct zcomp_strm {
 	/* compression/decompression buffer */
 	void *buffer;
@@ -21,8 +19,6 @@ struct zcomp_strm {
 	 * working memory)
 	 */
 	void *private;
-	/* used in multi stream backend, protected by backend strm_lock */
-	struct list_head list;
 };
 
 /* static compression backend */
@@ -41,19 +37,15 @@ struct zcomp_backend {
 
 /* dynamic per-device compression frontend */
 struct zcomp {
-	void *stream;
+	struct zcomp_strm * __percpu *stream;
 	struct zcomp_backend *backend;
-
-	struct zcomp_strm *(*strm_find)(struct zcomp *comp);
-	void (*strm_release)(struct zcomp *comp, struct zcomp_strm *zstrm);
-	bool (*set_max_streams)(struct zcomp *comp, int num_strm);
-	void (*destroy)(struct zcomp *comp);
+	struct notifier_block notifier;
 };
 
 ssize_t zcomp_available_show(const char *comp, char *buf);
 bool zcomp_available_algorithm(const char *comp);
 
-struct zcomp *zcomp_create(const char *comp, int max_strm);
+struct zcomp *zcomp_create(const char *comp);
 void zcomp_destroy(struct zcomp *comp);
 
 struct zcomp_strm *zcomp_strm_find(struct zcomp *comp);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/block/zram/zram_drv.c linux-libre-4.7-gnu/drivers/block/zram/zram_drv.c
--- linux-libre-4.6-gnu/drivers/block/zram/zram_drv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/block/zram/zram_drv.c	2016-07-24 15:23:50.000000000 -0400
@@ -304,46 +304,25 @@ static ssize_t mem_used_max_store(struct
 	return len;
 }
 
+/*
+ * We switched to per-cpu streams and this attr is not needed anymore.
+ * However, we will keep it around for some time, because:
+ * a) we may revert per-cpu streams in the future
+ * b) it's visible to user space and we need to follow our 2 years
+ *    retirement rule; but we already have a number of 'soon to be
+ *    altered' attrs, so max_comp_streams need to wait for the next
+ *    layoff cycle.
+ */
 static ssize_t max_comp_streams_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
-	int val;
-	struct zram *zram = dev_to_zram(dev);
-
-	down_read(&zram->init_lock);
-	val = zram->max_comp_streams;
-	up_read(&zram->init_lock);
-
-	return scnprintf(buf, PAGE_SIZE, "%d\n", val);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", num_online_cpus());
 }
 
 static ssize_t max_comp_streams_store(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t len)
 {
-	int num;
-	struct zram *zram = dev_to_zram(dev);
-	int ret;
-
-	ret = kstrtoint(buf, 0, &num);
-	if (ret < 0)
-		return ret;
-	if (num < 1)
-		return -EINVAL;
-
-	down_write(&zram->init_lock);
-	if (init_done(zram)) {
-		if (!zcomp_set_max_streams(zram->comp, num)) {
-			pr_info("Cannot change max compression streams\n");
-			ret = -EINVAL;
-			goto out;
-		}
-	}
-
-	zram->max_comp_streams = num;
-	ret = len;
-out:
-	up_write(&zram->init_lock);
-	return ret;
+	return len;
 }
 
 static ssize_t comp_algorithm_show(struct device *dev,
@@ -456,8 +435,26 @@ static ssize_t mm_stat_show(struct devic
 	return ret;
 }
 
+static ssize_t debug_stat_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	int version = 1;
+	struct zram *zram = dev_to_zram(dev);
+	ssize_t ret;
+
+	down_read(&zram->init_lock);
+	ret = scnprintf(buf, PAGE_SIZE,
+			"version: %d\n%8llu\n",
+			version,
+			(u64)atomic64_read(&zram->stats.writestall));
+	up_read(&zram->init_lock);
+
+	return ret;
+}
+
 static DEVICE_ATTR_RO(io_stat);
 static DEVICE_ATTR_RO(mm_stat);
+static DEVICE_ATTR_RO(debug_stat);
 ZRAM_ATTR_RO(num_reads);
 ZRAM_ATTR_RO(num_writes);
 ZRAM_ATTR_RO(failed_reads);
@@ -514,7 +511,7 @@ static struct zram_meta *zram_meta_alloc
 		goto out_error;
 	}
 
-	meta->mem_pool = zs_create_pool(pool_name, GFP_NOIO | __GFP_HIGHMEM);
+	meta->mem_pool = zs_create_pool(pool_name);
 	if (!meta->mem_pool) {
 		pr_err("Error creating memory pool\n");
 		goto out_error;
@@ -650,7 +647,7 @@ static int zram_bvec_write(struct zram *
 {
 	int ret = 0;
 	size_t clen;
-	unsigned long handle;
+	unsigned long handle = 0;
 	struct page *page;
 	unsigned char *user_mem, *cmem, *src, *uncmem = NULL;
 	struct zram_meta *meta = zram->meta;
@@ -673,9 +670,8 @@ static int zram_bvec_write(struct zram *
 			goto out;
 	}
 
-	zstrm = zcomp_strm_find(zram->comp);
+compress_again:
 	user_mem = kmap_atomic(page);
-
 	if (is_partial_io(bvec)) {
 		memcpy(uncmem + offset, user_mem + bvec->bv_offset,
 		       bvec->bv_len);
@@ -699,6 +695,7 @@ static int zram_bvec_write(struct zram *
 		goto out;
 	}
 
+	zstrm = zcomp_strm_find(zram->comp);
 	ret = zcomp_compress(zram->comp, zstrm, uncmem, &clen);
 	if (!is_partial_io(bvec)) {
 		kunmap_atomic(user_mem);
@@ -710,6 +707,7 @@ static int zram_bvec_write(struct zram *
 		pr_err("Compression failed! err=%d\n", ret);
 		goto out;
 	}
+
 	src = zstrm->buffer;
 	if (unlikely(clen > max_zpage_size)) {
 		clen = PAGE_SIZE;
@@ -717,8 +715,35 @@ static int zram_bvec_write(struct zram *
 			src = uncmem;
 	}
 
-	handle = zs_malloc(meta->mem_pool, clen);
+	/*
+	 * handle allocation has 2 paths:
+	 * a) fast path is executed with preemption disabled (for
+	 *  per-cpu streams) and has __GFP_DIRECT_RECLAIM bit clear,
+	 *  since we can't sleep;
+	 * b) slow path enables preemption and attempts to allocate
+	 *  the page with __GFP_DIRECT_RECLAIM bit set. we have to
+	 *  put per-cpu compression stream and, thus, to re-do
+	 *  the compression once handle is allocated.
+	 *
+	 * if we have a 'non-null' handle here then we are coming
+	 * from the slow path and handle has already been allocated.
+	 */
+	if (!handle)
+		handle = zs_malloc(meta->mem_pool, clen,
+				__GFP_KSWAPD_RECLAIM |
+				__GFP_NOWARN |
+				__GFP_HIGHMEM);
 	if (!handle) {
+		zcomp_strm_release(zram->comp, zstrm);
+		zstrm = NULL;
+
+		atomic64_inc(&zram->stats.writestall);
+
+		handle = zs_malloc(meta->mem_pool, clen,
+				GFP_NOIO | __GFP_HIGHMEM);
+		if (handle)
+			goto compress_again;
+
 		pr_err("Error allocating memory for compressed page: %u, size=%zu\n",
 			index, clen);
 		ret = -ENOMEM;
@@ -1009,7 +1034,6 @@ static void zram_reset_device(struct zra
 	/* Reset stats */
 	memset(&zram->stats, 0, sizeof(zram->stats));
 	zram->disksize = 0;
-	zram->max_comp_streams = 1;
 
 	set_capacity(zram->disk, 0);
 	part_stat_set_all(&zram->disk->part0, 0);
@@ -1038,7 +1062,7 @@ static ssize_t disksize_store(struct dev
 	if (!meta)
 		return -ENOMEM;
 
-	comp = zcomp_create(zram->compressor, zram->max_comp_streams);
+	comp = zcomp_create(zram->compressor);
 	if (IS_ERR(comp)) {
 		pr_err("Cannot initialise %s compressing backend\n",
 				zram->compressor);
@@ -1177,6 +1201,7 @@ static struct attribute *zram_disk_attrs
 	&dev_attr_comp_algorithm.attr,
 	&dev_attr_io_stat.attr,
 	&dev_attr_mm_stat.attr,
+	&dev_attr_debug_stat.attr,
 	NULL,
 };
 
@@ -1273,7 +1298,6 @@ static int zram_add(void)
 	}
 	strlcpy(zram->compressor, default_compressor, sizeof(zram->compressor));
 	zram->meta = NULL;
-	zram->max_comp_streams = 1;
 
 	pr_info("Added device: %s\n", zram->disk->disk_name);
 	return device_id;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/block/zram/zram_drv.h linux-libre-4.7-gnu/drivers/block/zram/zram_drv.h
--- linux-libre-4.6-gnu/drivers/block/zram/zram_drv.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/block/zram/zram_drv.h	2016-07-24 15:23:50.000000000 -0400
@@ -85,6 +85,7 @@ struct zram_stats {
 	atomic64_t zero_pages;		/* no. of zero filled pages */
 	atomic64_t pages_stored;	/* no. of pages currently stored */
 	atomic_long_t max_used_pages;	/* no. of maximum pages stored */
+	atomic64_t writestall;		/* no. of write slow paths */
 };
 
 struct zram_meta {
@@ -102,7 +103,6 @@ struct zram {
 	 * the number of pages zram can consume for storing compressed data
 	 */
 	unsigned long limit_pages;
-	int max_comp_streams;
 
 	struct zram_stats stats;
 	atomic_t refcount; /* refcount for zram_meta */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/bluetooth/ath3k.c linux-libre-4.7-gnu/drivers/bluetooth/ath3k.c
--- linux-libre-4.6-gnu/drivers/bluetooth/ath3k.c	2016-05-15 19:39:11.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/bluetooth/ath3k.c	2016-07-24 18:33:46.000000000 -0400
@@ -122,6 +122,7 @@ static const struct usb_device_id ath3k_
 	{ USB_DEVICE(0x13d3, 0x3432) },
 	{ USB_DEVICE(0x13d3, 0x3472) },
 	{ USB_DEVICE(0x13d3, 0x3474) },
+	{ USB_DEVICE(0x13d3, 0x3487) },
 
 	/* Atheros AR5BBU12 with sflash firmware */
 	{ USB_DEVICE(0x0489, 0xE02C) },
@@ -188,6 +189,7 @@ static const struct usb_device_id ath3k_
 	{ USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x13d3, 0x3472), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x13d3, 0x3474), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x13d3, 0x3487), .driver_info = BTUSB_ATH3012 },
 
 	/* Atheros AR5BBU22 with sflash firmware */
 	{ USB_DEVICE(0x0489, 0xE036), .driver_info = BTUSB_ATH3012 },
@@ -206,7 +208,8 @@ static int ath3k_load_firmware(struct us
 				const struct firmware *firmware)
 {
 	u8 *send_buf;
-	int err, pipe, len, size, sent = 0;
+	int len = 0;
+	int err, pipe, size, sent = 0;
 	int count = firmware->size;
 
 	BT_DBG("udev %p", udev);
@@ -302,7 +305,8 @@ static int ath3k_load_fwfile(struct usb_
 		const struct firmware *firmware)
 {
 	u8 *send_buf;
-	int err, pipe, len, size, count, sent = 0;
+	int len = 0;
+	int err, pipe, size, count, sent = 0;
 	int ret;
 
 	count = firmware->size;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/bluetooth/btmrvl_drv.h linux-libre-4.7-gnu/drivers/bluetooth/btmrvl_drv.h
--- linux-libre-4.6-gnu/drivers/bluetooth/btmrvl_drv.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/bluetooth/btmrvl_drv.h	2016-07-24 15:23:50.000000000 -0400
@@ -23,6 +23,17 @@
 #include <linux/bitops.h>
 #include <linux/slab.h>
 #include <net/bluetooth/bluetooth.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/gfp.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/of_gpio.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/of_irq.h>
 
 #define BTM_HEADER_LEN			4
 #define BTM_UPLD_SIZE			2312
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/bluetooth/btmrvl_main.c linux-libre-4.7-gnu/drivers/bluetooth/btmrvl_main.c
--- linux-libre-4.6-gnu/drivers/bluetooth/btmrvl_main.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/bluetooth/btmrvl_main.c	2016-07-24 15:23:50.000000000 -0400
@@ -510,34 +510,39 @@ static int btmrvl_download_cal_data(stru
 static int btmrvl_check_device_tree(struct btmrvl_private *priv)
 {
 	struct device_node *dt_node;
+	struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
 	u8 cal_data[BT_CAL_HDR_LEN + BT_CAL_DATA_SIZE];
-	int ret;
-	u32 val;
+	int ret = 0;
+	u16 gpio, gap;
 
-	for_each_compatible_node(dt_node, NULL, "btmrvl,cfgdata") {
-		ret = of_property_read_u32(dt_node, "btmrvl,gpio-gap", &val);
-		if (!ret)
-			priv->btmrvl_dev.gpio_gap = val;
+	if (card->plt_of_node) {
+		dt_node = card->plt_of_node;
+		ret = of_property_read_u16(dt_node, "marvell,wakeup-pin",
+					   &gpio);
+		if (ret)
+			gpio = (priv->btmrvl_dev.gpio_gap & 0xff00) >> 8;
 
-		ret = of_property_read_u8_array(dt_node, "btmrvl,cal-data",
+		ret = of_property_read_u16(dt_node, "marvell,wakeup-gap-ms",
+					   &gap);
+		if (ret)
+			gap = (u8)(priv->btmrvl_dev.gpio_gap & 0x00ff);
+
+		priv->btmrvl_dev.gpio_gap = (gpio << 8) + gap;
+
+		ret = of_property_read_u8_array(dt_node, "marvell,cal-data",
 						cal_data + BT_CAL_HDR_LEN,
 						BT_CAL_DATA_SIZE);
-		if (ret) {
-			of_node_put(dt_node);
+		if (ret)
 			return ret;
-		}
 
 		BT_DBG("Use cal data from device tree");
 		ret = btmrvl_download_cal_data(priv, cal_data,
 					       BT_CAL_DATA_SIZE);
-		if (ret) {
+		if (ret)
 			BT_ERR("Fail to download calibrate data");
-			of_node_put(dt_node);
-			return ret;
-		}
 	}
 
-	return 0;
+	return ret;
 }
 
 static int btmrvl_setup(struct hci_dev *hdev)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/bluetooth/btmrvl_sdio.c linux-libre-4.7-gnu/drivers/bluetooth/btmrvl_sdio.c
--- linux-libre-4.6-gnu/drivers/bluetooth/btmrvl_sdio.c	2016-05-15 19:39:46.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/bluetooth/btmrvl_sdio.c	2016-07-24 18:34:12.000000000 -0400
@@ -52,6 +52,68 @@ static struct memory_type_mapping mem_ty
 	{"EXTLAST", NULL, 0, 0xFE},
 };
 
+static const struct of_device_id btmrvl_sdio_of_match_table[] = {
+	{ .compatible = "marvell,sd8897-bt" },
+	{ .compatible = "marvell,sd8997-bt" },
+	{ }
+};
+
+static irqreturn_t btmrvl_wake_irq_bt(int irq, void *priv)
+{
+	struct btmrvl_plt_wake_cfg *cfg = priv;
+
+	if (cfg->irq_bt >= 0) {
+		pr_info("%s: wake by bt", __func__);
+		cfg->wake_by_bt = true;
+		disable_irq_nosync(irq);
+	}
+
+	return IRQ_HANDLED;
+}
+
+/* This function parses device tree node using mmc subnode devicetree API.
+ * The device node is saved in card->plt_of_node.
+ * If the device tree node exists and includes interrupts attributes, this
+ * function will request platform specific wakeup interrupt.
+ */
+static int btmrvl_sdio_probe_of(struct device *dev,
+				struct btmrvl_sdio_card *card)
+{
+	struct btmrvl_plt_wake_cfg *cfg;
+	int ret;
+
+	if (!dev->of_node ||
+	    !of_match_node(btmrvl_sdio_of_match_table, dev->of_node)) {
+		pr_err("sdio platform data not available");
+		return -1;
+	}
+
+	card->plt_of_node = dev->of_node;
+
+	card->plt_wake_cfg = devm_kzalloc(dev, sizeof(*card->plt_wake_cfg),
+					  GFP_KERNEL);
+	cfg = card->plt_wake_cfg;
+	if (cfg && card->plt_of_node) {
+		cfg->irq_bt = irq_of_parse_and_map(card->plt_of_node, 0);
+		if (!cfg->irq_bt) {
+			dev_err(dev, "fail to parse irq_bt from device tree");
+		} else {
+			ret = devm_request_irq(dev, cfg->irq_bt,
+					       btmrvl_wake_irq_bt,
+					       IRQF_TRIGGER_LOW,
+					       "bt_wake", cfg);
+			if (ret) {
+				dev_err(dev,
+					"Failed to request irq_bt %d (%d)\n",
+					cfg->irq_bt, ret);
+			}
+			disable_irq(cfg->irq_bt);
+		}
+	}
+
+	return 0;
+}
+
 /* The btmrvl_sdio_remove() callback function is called
  * when user removes this module from kernel space or ejects
  * the card from the slot. The driver handles these 2 cases
@@ -1464,6 +1526,9 @@ static int btmrvl_sdio_probe(struct sdio
 
 	btmrvl_sdio_enable_host_int(card);
 
+	/* Device tree node parsing and platform specific configuration*/
+	btmrvl_sdio_probe_of(&func->dev, card);
+
 	priv = btmrvl_add_card(card);
 	if (!priv) {
 		BT_ERR("Initializing card failed!");
@@ -1544,6 +1609,13 @@ static int btmrvl_sdio_suspend(struct de
 		return 0;
 	}
 
+	/* Enable platform specific wakeup interrupt */
+	if (card->plt_wake_cfg && card->plt_wake_cfg->irq_bt >= 0) {
+		card->plt_wake_cfg->wake_by_bt = false;
+		enable_irq(card->plt_wake_cfg->irq_bt);
+		enable_irq_wake(card->plt_wake_cfg->irq_bt);
+	}
+
 	priv = card->priv;
 	priv->adapter->is_suspending = true;
 	hcidev = priv->btmrvl_dev.hcidev;
@@ -1606,6 +1678,13 @@ static int btmrvl_sdio_resume(struct dev
 	BT_DBG("%s: SDIO resume", hcidev->name);
 	hci_resume_dev(hcidev);
 
+	/* Disable platform specific wakeup interrupt */
+	if (card->plt_wake_cfg && card->plt_wake_cfg->irq_bt >= 0) {
+		disable_irq_wake(card->plt_wake_cfg->irq_bt);
+		if (!card->plt_wake_cfg->wake_by_bt)
+			disable_irq(card->plt_wake_cfg->irq_bt);
+	}
+
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/bluetooth/btmrvl_sdio.h linux-libre-4.7-gnu/drivers/bluetooth/btmrvl_sdio.h
--- linux-libre-4.6-gnu/drivers/bluetooth/btmrvl_sdio.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/bluetooth/btmrvl_sdio.h	2016-07-24 15:23:50.000000000 -0400
@@ -62,6 +62,10 @@
 
 #define FIRMWARE_READY				0xfedc
 
+struct btmrvl_plt_wake_cfg {
+	int irq_bt;
+	bool wake_by_bt;
+};
 
 struct btmrvl_sdio_card_reg {
 	u8 cfg;
@@ -97,6 +101,8 @@ struct btmrvl_sdio_card {
 	u16 sd_blksz_fw_dl;
 	u8 rx_unit;
 	struct btmrvl_private *priv;
+	struct device_node *plt_of_node;
+	struct btmrvl_plt_wake_cfg *plt_wake_cfg;
 };
 
 struct btmrvl_sdio_device {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/bluetooth/btusb.c linux-libre-4.7-gnu/drivers/bluetooth/btusb.c
--- linux-libre-4.6-gnu/drivers/bluetooth/btusb.c	2016-05-15 19:39:33.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/bluetooth/btusb.c	2016-07-24 18:34:04.000000000 -0400
@@ -236,6 +236,7 @@ static const struct usb_device_id blackl
 	{ USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x13d3, 0x3472), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x13d3, 0x3474), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x13d3, 0x3487), .driver_info = BTUSB_ATH3012 },
 
 	/* Atheros AR5BBU12 with sflash firmware */
 	{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
@@ -2001,12 +2002,13 @@ static int btusb_setup_intel_new(struct
 		return -EINVAL;
 	}
 
-	/* At the moment only the hardware variant iBT 3.0 (LnP/SfP) is
-	 * supported by this firmware loading method. This check has been
-	 * put in place to ensure correct forward compatibility options
-	 * when newer hardware variants come along.
+	/* At the moment the iBT 3.0 hardware variants 0x0b (LnP/SfP)
+	 * and 0x0c (WsP) are supported by this firmware loading method.
+	 *
+	 * This check has been put in place to ensure correct forward
+	 * compatibility options when newer hardware variants come along.
 	 */
-	if (ver.hw_variant != 0x0b) {
+	if (ver.hw_variant != 0x0b && ver.hw_variant != 0x0c) {
 		BT_ERR("%s: Unsupported Intel hardware variant (%u)",
 		       hdev->name, ver.hw_variant);
 		return -EINVAL;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/bluetooth/hci_bcm.c linux-libre-4.7-gnu/drivers/bluetooth/hci_bcm.c
--- linux-libre-4.6-gnu/drivers/bluetooth/hci_bcm.c	2016-05-15 19:39:20.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/bluetooth/hci_bcm.c	2016-07-24 18:33:54.000000000 -0400
@@ -825,6 +825,7 @@ static const struct acpi_device_id bcm_a
 	{ "BCM2E64", 0 },
 	{ "BCM2E65", 0 },
 	{ "BCM2E67", 0 },
+	{ "BCM2E71", 0 },
 	{ "BCM2E7B", 0 },
 	{ "BCM2E7C", 0 },
 	{ },
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/bluetooth/hci_bcsp.c linux-libre-4.7-gnu/drivers/bluetooth/hci_bcsp.c
--- linux-libre-4.6-gnu/drivers/bluetooth/hci_bcsp.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/bluetooth/hci_bcsp.c	2016-07-24 15:23:50.000000000 -0400
@@ -102,13 +102,12 @@ static const u16 crc_table[] = {
 /* Initialise the crc calculator */
 #define BCSP_CRC_INIT(x) x = 0xffff
 
-/*
-   Update crc with next data byte
-
-   Implementation note
-        The data byte is treated as two nibbles.  The crc is generated
-        in reverse, i.e., bits are fed into the register from the top.
-*/
+/* Update crc with next data byte
+ *
+ * Implementation note
+ *     The data byte is treated as two nibbles.  The crc is generated
+ *     in reverse, i.e., bits are fed into the register from the top.
+ */
 static void bcsp_crc_update(u16 *crc, u8 d)
 {
 	u16 reg = *crc;
@@ -223,9 +222,10 @@ static struct sk_buff *bcsp_prepare_pkt(
 	}
 
 	/* Max len of packet: (original len +4(bcsp hdr) +2(crc))*2
-	   (because bytes 0xc0 and 0xdb are escaped, worst case is
-	   when the packet is all made of 0xc0 and 0xdb :) )
-	   + 2 (0xc0 delimiters at start and end). */
+	 * (because bytes 0xc0 and 0xdb are escaped, worst case is
+	 * when the packet is all made of 0xc0 and 0xdb :) )
+	 * + 2 (0xc0 delimiters at start and end).
+	 */
 
 	nskb = alloc_skb((len + 6) * 2 + 2, GFP_ATOMIC);
 	if (!nskb)
@@ -285,7 +285,7 @@ static struct sk_buff *bcsp_dequeue(stru
 	struct bcsp_struct *bcsp = hu->priv;
 	unsigned long flags;
 	struct sk_buff *skb;
-	
+
 	/* First of all, check for unreliable messages in the queue,
 	   since they have priority */
 
@@ -305,8 +305,9 @@ static struct sk_buff *bcsp_dequeue(stru
 	}
 
 	/* Now, try to send a reliable pkt. We can only send a
-	   reliable packet if the number of packets sent but not yet ack'ed
-	   is < than the winsize */
+	 * reliable packet if the number of packets sent but not yet ack'ed
+	 * is < than the winsize
+	 */
 
 	spin_lock_irqsave_nested(&bcsp->unack.lock, flags, SINGLE_DEPTH_NESTING);
 
@@ -332,12 +333,14 @@ static struct sk_buff *bcsp_dequeue(stru
 	spin_unlock_irqrestore(&bcsp->unack.lock, flags);
 
 	/* We could not send a reliable packet, either because there are
-	   none or because there are too many unack'ed pkts. Did we receive
-	   any packets we have not acknowledged yet ? */
+	 * none or because there are too many unack'ed pkts. Did we receive
+	 * any packets we have not acknowledged yet ?
+	 */
 
 	if (bcsp->txack_req) {
 		/* if so, craft an empty ACK pkt and send it on BCSP unreliable
-		   channel 0 */
+		 * channel 0
+		 */
 		struct sk_buff *nskb = bcsp_prepare_pkt(bcsp, NULL, 0, BCSP_ACK_PKT);
 		return nskb;
 	}
@@ -399,8 +402,9 @@ static void bcsp_pkt_cull(struct bcsp_st
 }
 
 /* Handle BCSP link-establishment packets. When we
-   detect a "sync" packet, symptom that the BT module has reset,
-   we do nothing :) (yet) */
+ * detect a "sync" packet, symptom that the BT module has reset,
+ * we do nothing :) (yet)
+ */
 static void bcsp_handle_le_pkt(struct hci_uart *hu)
 {
 	struct bcsp_struct *bcsp = hu->priv;
@@ -462,7 +466,7 @@ static inline void bcsp_unslip_one_byte(
 		case 0xdd:
 			memcpy(skb_put(bcsp->rx_skb, 1), &db, 1);
 			if ((bcsp->rx_skb->data[0] & 0x40) != 0 &&
-					bcsp->rx_state != BCSP_W4_CRC) 
+					bcsp->rx_state != BCSP_W4_CRC)
 				bcsp_crc_update(&bcsp->message_crc, 0xdb);
 			bcsp->rx_esc_state = BCSP_ESCSTATE_NOESC;
 			bcsp->rx_count--;
@@ -534,7 +538,7 @@ static void bcsp_complete_rx_pkt(struct
 			} else {
 				BT_ERR("Packet for unknown channel (%u %s)",
 					bcsp->rx_skb->data[1] & 0x0f,
-					bcsp->rx_skb->data[0] & 0x80 ? 
+					bcsp->rx_skb->data[0] & 0x80 ?
 					"reliable" : "unreliable");
 				kfree_skb(bcsp->rx_skb);
 			}
@@ -562,7 +566,7 @@ static int bcsp_recv(struct hci_uart *hu
 	struct bcsp_struct *bcsp = hu->priv;
 	const unsigned char *ptr;
 
-	BT_DBG("hu %p count %d rx_state %d rx_count %ld", 
+	BT_DBG("hu %p count %d rx_state %d rx_count %ld",
 		hu, count, bcsp->rx_state, bcsp->rx_count);
 
 	ptr = data;
@@ -591,7 +595,7 @@ static int bcsp_recv(struct hci_uart *hu
 				continue;
 			}
 			if (bcsp->rx_skb->data[0] & 0x80	/* reliable pkt */
-			    		&& (bcsp->rx_skb->data[0] & 0x07) != bcsp->rxseq_txack) {
+						&& (bcsp->rx_skb->data[0] & 0x07) != bcsp->rxseq_txack) {
 				BT_ERR("Out-of-order packet arrived, got %u expected %u",
 					bcsp->rx_skb->data[0] & 0x07, bcsp->rxseq_txack);
 
@@ -601,7 +605,7 @@ static int bcsp_recv(struct hci_uart *hu
 				continue;
 			}
 			bcsp->rx_state = BCSP_W4_DATA;
-			bcsp->rx_count = (bcsp->rx_skb->data[1] >> 4) + 
+			bcsp->rx_count = (bcsp->rx_skb->data[1] >> 4) +
 					(bcsp->rx_skb->data[2] << 4);	/* May be 0 */
 			continue;
 
@@ -615,7 +619,7 @@ static int bcsp_recv(struct hci_uart *hu
 
 		case BCSP_W4_CRC:
 			if (bitrev16(bcsp->message_crc) != bscp_get_crc(bcsp)) {
-				BT_ERR ("Checksum failed: computed %04x received %04x",
+				BT_ERR("Checksum failed: computed %04x received %04x",
 					bitrev16(bcsp->message_crc),
 					bscp_get_crc(bcsp));
 
@@ -653,8 +657,9 @@ static int bcsp_recv(struct hci_uart *hu
 				BCSP_CRC_INIT(bcsp->message_crc);
 
 				/* Do not increment ptr or decrement count
-				 * Allocate packet. Max len of a BCSP pkt= 
-				 * 0xFFF (payload) +4 (header) +2 (crc) */
+				 * Allocate packet. Max len of a BCSP pkt=
+				 * 0xFFF (payload) +4 (header) +2 (crc)
+				 */
 
 				bcsp->rx_skb = bt_skb_alloc(0x1005, GFP_ATOMIC);
 				if (!bcsp->rx_skb) {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/bluetooth/hci_intel.c linux-libre-4.7-gnu/drivers/bluetooth/hci_intel.c
--- linux-libre-4.6-gnu/drivers/bluetooth/hci_intel.c	2016-05-15 19:39:42.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/bluetooth/hci_intel.c	2016-07-24 18:34:09.000000000 -0400
@@ -1210,8 +1210,7 @@ static int intel_probe(struct platform_d
 
 	idev->pdev = pdev;
 
-	idev->reset = devm_gpiod_get_optional(&pdev->dev, "reset",
-					      GPIOD_OUT_LOW);
+	idev->reset = devm_gpiod_get(&pdev->dev, "reset", GPIOD_OUT_LOW);
 	if (IS_ERR(idev->reset)) {
 		dev_err(&pdev->dev, "Unable to retrieve gpio\n");
 		return PTR_ERR(idev->reset);
@@ -1223,8 +1222,7 @@ static int intel_probe(struct platform_d
 
 		dev_err(&pdev->dev, "No IRQ, falling back to gpio-irq\n");
 
-		host_wake = devm_gpiod_get_optional(&pdev->dev, "host-wake",
-						    GPIOD_IN);
+		host_wake = devm_gpiod_get(&pdev->dev, "host-wake", GPIOD_IN);
 		if (IS_ERR(host_wake)) {
 			dev_err(&pdev->dev, "Unable to retrieve IRQ\n");
 			goto no_irq;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/bluetooth/hci_ldisc.c linux-libre-4.7-gnu/drivers/bluetooth/hci_ldisc.c
--- linux-libre-4.6-gnu/drivers/bluetooth/hci_ldisc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/bluetooth/hci_ldisc.c	2016-07-24 15:23:50.000000000 -0400
@@ -227,7 +227,7 @@ static int hci_uart_flush(struct hci_dev
 	tty_ldisc_flush(tty);
 	tty_driver_flush_buffer(tty);
 
-	if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
+	if (test_bit(HCI_UART_PROTO_READY, &hu->flags))
 		hu->proto->flush(hu);
 
 	return 0;
@@ -492,7 +492,7 @@ static void hci_uart_tty_close(struct tt
 
 	cancel_work_sync(&hu->write_work);
 
-	if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) {
+	if (test_and_clear_bit(HCI_UART_PROTO_READY, &hu->flags)) {
 		if (hdev) {
 			if (test_bit(HCI_UART_REGISTERED, &hu->flags))
 				hci_unregister_dev(hdev);
@@ -500,6 +500,7 @@ static void hci_uart_tty_close(struct tt
 		}
 		hu->proto->close(hu);
 	}
+	clear_bit(HCI_UART_PROTO_SET, &hu->flags);
 
 	kfree(hu);
 }
@@ -526,7 +527,7 @@ static void hci_uart_tty_wakeup(struct t
 	if (tty != hu->tty)
 		return;
 
-	if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
+	if (test_bit(HCI_UART_PROTO_READY, &hu->flags))
 		hci_uart_tx_wakeup(hu);
 }
 
@@ -550,7 +551,7 @@ static void hci_uart_tty_receive(struct
 	if (!hu || tty != hu->tty)
 		return;
 
-	if (!test_bit(HCI_UART_PROTO_SET, &hu->flags))
+	if (!test_bit(HCI_UART_PROTO_READY, &hu->flags))
 		return;
 
 	/* It does not need a lock here as it is already protected by a mutex in
@@ -638,9 +639,11 @@ static int hci_uart_set_proto(struct hci
 		return err;
 
 	hu->proto = p;
+	set_bit(HCI_UART_PROTO_READY, &hu->flags);
 
 	err = hci_uart_register_dev(hu);
 	if (err) {
+		clear_bit(HCI_UART_PROTO_READY, &hu->flags);
 		p->close(hu);
 		return err;
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/bluetooth/hci_uart.h linux-libre-4.7-gnu/drivers/bluetooth/hci_uart.h
--- linux-libre-4.6-gnu/drivers/bluetooth/hci_uart.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/bluetooth/hci_uart.h	2016-07-24 15:23:50.000000000 -0400
@@ -95,6 +95,7 @@ struct hci_uart {
 /* HCI_UART proto flag bits */
 #define HCI_UART_PROTO_SET	0
 #define HCI_UART_REGISTERED	1
+#define HCI_UART_PROTO_READY	2
 
 /* TX states  */
 #define HCI_UART_SENDING	1
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/bluetooth/hci_vhci.c linux-libre-4.7-gnu/drivers/bluetooth/hci_vhci.c
--- linux-libre-4.6-gnu/drivers/bluetooth/hci_vhci.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/bluetooth/hci_vhci.c	2016-07-24 15:23:50.000000000 -0400
@@ -50,6 +50,7 @@ struct vhci_data {
 	wait_queue_head_t read_wait;
 	struct sk_buff_head readq;
 
+	struct mutex open_mutex;
 	struct delayed_work open_timeout;
 };
 
@@ -87,12 +88,15 @@ static int vhci_send_frame(struct hci_de
 	return 0;
 }
 
-static int vhci_create_device(struct vhci_data *data, __u8 opcode)
+static int __vhci_create_device(struct vhci_data *data, __u8 opcode)
 {
 	struct hci_dev *hdev;
 	struct sk_buff *skb;
 	__u8 dev_type;
 
+	if (data->hdev)
+		return -EBADFD;
+
 	/* bits 0-1 are dev_type (BR/EDR or AMP) */
 	dev_type = opcode & 0x03;
 
@@ -151,6 +155,17 @@ static int vhci_create_device(struct vhc
 	return 0;
 }
 
+static int vhci_create_device(struct vhci_data *data, __u8 opcode)
+{
+	int err;
+
+	mutex_lock(&data->open_mutex);
+	err = __vhci_create_device(data, opcode);
+	mutex_unlock(&data->open_mutex);
+
+	return err;
+}
+
 static inline ssize_t vhci_get_user(struct vhci_data *data,
 				    struct iov_iter *from)
 {
@@ -189,11 +204,6 @@ static inline ssize_t vhci_get_user(stru
 		break;
 
 	case HCI_VENDOR_PKT:
-		if (data->hdev) {
-			kfree_skb(skb);
-			return -EBADFD;
-		}
-
 		cancel_delayed_work_sync(&data->open_timeout);
 
 		opcode = *((__u8 *) skb->data);
@@ -320,6 +330,7 @@ static int vhci_open(struct inode *inode
 	skb_queue_head_init(&data->readq);
 	init_waitqueue_head(&data->read_wait);
 
+	mutex_init(&data->open_mutex);
 	INIT_DELAYED_WORK(&data->open_timeout, vhci_open_timeout);
 
 	file->private_data = data;
@@ -333,15 +344,18 @@ static int vhci_open(struct inode *inode
 static int vhci_release(struct inode *inode, struct file *file)
 {
 	struct vhci_data *data = file->private_data;
-	struct hci_dev *hdev = data->hdev;
+	struct hci_dev *hdev;
 
 	cancel_delayed_work_sync(&data->open_timeout);
 
+	hdev = data->hdev;
+
 	if (hdev) {
 		hci_unregister_dev(hdev);
 		hci_free_dev(hdev);
 	}
 
+	skb_queue_purge(&data->readq);
 	file->private_data = NULL;
 	kfree(data);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/bus/arm-ccn.c linux-libre-4.7-gnu/drivers/bus/arm-ccn.c
--- linux-libre-4.6-gnu/drivers/bus/arm-ccn.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/bus/arm-ccn.c	2016-07-24 15:23:50.000000000 -0400
@@ -1189,7 +1189,7 @@ static int arm_ccn_pmu_cpu_notifier(stru
 		perf_pmu_migrate_context(&dt->pmu, cpu, target);
 		cpumask_set_cpu(target, &dt->cpu);
 		if (ccn->irq)
-			WARN_ON(irq_set_affinity(ccn->irq, &dt->cpu) != 0);
+			WARN_ON(irq_set_affinity_hint(ccn->irq, &dt->cpu) != 0);
 	default:
 		break;
 	}
@@ -1278,7 +1278,7 @@ static int arm_ccn_pmu_init(struct arm_c
 
 	/* Also make sure that the overflow interrupt is handled by this CPU */
 	if (ccn->irq) {
-		err = irq_set_affinity(ccn->irq, &ccn->dt.cpu);
+		err = irq_set_affinity_hint(ccn->irq, &ccn->dt.cpu);
 		if (err) {
 			dev_err(ccn->dev, "Failed to set interrupt affinity!\n");
 			goto error_set_affinity;
@@ -1306,7 +1306,8 @@ static void arm_ccn_pmu_cleanup(struct a
 {
 	int i;
 
-	irq_set_affinity(ccn->irq, cpu_possible_mask);
+	if (ccn->irq)
+		irq_set_affinity_hint(ccn->irq, NULL);
 	unregister_cpu_notifier(&ccn->dt.cpu_nb);
 	for (i = 0; i < ccn->num_xps; i++)
 		writel(0, ccn->xp[i].base + CCN_XP_DT_CONTROL);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/bus/brcmstb_gisb.c linux-libre-4.7-gnu/drivers/bus/brcmstb_gisb.c
--- linux-libre-4.6-gnu/drivers/bus/brcmstb_gisb.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/bus/brcmstb_gisb.c	2016-07-24 15:23:50.000000000 -0400
@@ -30,6 +30,10 @@
 #include <asm/signal.h>
 #endif
 
+#ifdef CONFIG_MIPS
+#include <asm/traps.h>
+#endif
+
 #define  ARB_ERR_CAP_CLEAR		(1 << 0)
 #define  ARB_ERR_CAP_STATUS_TIMEOUT	(1 << 12)
 #define  ARB_ERR_CAP_STATUS_TEA		(1 << 11)
@@ -238,6 +242,29 @@ static int brcmstb_bus_error_handler(uns
 }
 #endif
 
+#ifdef CONFIG_MIPS
+static int brcmstb_bus_error_handler(struct pt_regs *regs, int is_fixup)
+{
+	int ret = 0;
+	struct brcmstb_gisb_arb_device *gdev;
+	u32 cap_status;
+
+	list_for_each_entry(gdev, &brcmstb_gisb_arb_device_list, next) {
+		cap_status = gisb_read(gdev, ARB_ERR_CAP_STATUS);
+
+		/* Invalid captured address, bail out */
+		if (!(cap_status & ARB_ERR_CAP_STATUS_VALID)) {
+			is_fixup = 1;
+			goto out;
+		}
+
+		ret |= brcmstb_gisb_arb_decode_addr(gdev, "bus error");
+	}
+out:
+	return is_fixup ? MIPS_BE_FIXUP : MIPS_BE_FATAL;
+}
+#endif
+
 static irqreturn_t brcmstb_gisb_timeout_handler(int irq, void *dev_id)
 {
 	brcmstb_gisb_arb_decode_addr(dev_id, "timeout");
@@ -355,6 +382,9 @@ static int __init brcmstb_gisb_arb_probe
 	hook_fault_code(22, brcmstb_bus_error_handler, SIGBUS, 0,
 			"imprecise external abort");
 #endif
+#ifdef CONFIG_MIPS
+	board_be_handler = brcmstb_bus_error_handler;
+#endif
 
 	dev_info(&pdev->dev, "registered mem: %p, irqs: %d, %d\n",
 			gdev->base, timeout_irq, tea_irq);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/bus/Kconfig linux-libre-4.7-gnu/drivers/bus/Kconfig
--- linux-libre-4.6-gnu/drivers/bus/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/bus/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -48,7 +48,7 @@ config ARM_CCI5xx_PMU
 	  If unsure, say Y
 
 config ARM_CCN
-	bool "ARM CCN driver support"
+	tristate "ARM CCN driver support"
 	depends on ARM || ARM64
 	depends on PERF_EVENTS
 	help
@@ -58,6 +58,7 @@ config ARM_CCN
 config BRCMSTB_GISB_ARB
 	bool "Broadcom STB GISB bus arbiter"
 	depends on ARM || MIPS
+	default ARCH_BRCMSTB || BMIPS_GENERIC
 	help
 	  Driver for the Broadcom Set Top Box System-on-a-chip internal bus
 	  arbiter. This driver provides timeout and target abort error handling
@@ -110,7 +111,7 @@ config OMAP_OCP2SCP
 config SIMPLE_PM_BUS
 	bool "Simple Power-Managed Bus Driver"
 	depends on OF && PM
-	depends on ARCH_SHMOBILE || COMPILE_TEST
+	depends on ARCH_RENESAS || COMPILE_TEST
 	help
 	  Driver for transparent busses that don't need a real driver, but
 	  where the bus controller is part of a PM domain, or under the control
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/bus/mips_cdmm.c linux-libre-4.7-gnu/drivers/bus/mips_cdmm.c
--- linux-libre-4.6-gnu/drivers/bus/mips_cdmm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/bus/mips_cdmm.c	2016-07-24 15:23:50.000000000 -0400
@@ -599,8 +599,8 @@ BUILD_PERDEV_HELPER(cpu_up)         /* i
  * mips_cdmm_bus_down() - Tear down the CDMM bus.
  * @data:	Pointer to unsigned int CPU number.
  *
- * This work_on_cpu callback function is executed on a given CPU to call the
- * CDMM driver cpu_down callback for all devices on that CPU.
+ * This function is executed on the hotplugged CPU and calls the CDMM
+ * driver cpu_down callback for all devices on that CPU.
  */
 static long mips_cdmm_bus_down(void *data)
 {
@@ -630,7 +630,9 @@ static long mips_cdmm_bus_down(void *dat
  * CDMM devices on that CPU, or to call the CDMM driver cpu_up callback for all
  * devices already discovered on that CPU.
  *
- * It is used during initialisation and when CPUs are brought online.
+ * It is used as work_on_cpu callback function during
+ * initialisation. When CPUs are brought online the function is
+ * invoked directly on the hotplugged CPU.
  */
 static long mips_cdmm_bus_up(void *data)
 {
@@ -677,10 +679,10 @@ static int mips_cdmm_cpu_notify(struct n
 	switch (action & ~CPU_TASKS_FROZEN) {
 	case CPU_ONLINE:
 	case CPU_DOWN_FAILED:
-		work_on_cpu(cpu, mips_cdmm_bus_up, &cpu);
+		mips_cdmm_bus_up(&cpu);
 		break;
 	case CPU_DOWN_PREPARE:
-		work_on_cpu(cpu, mips_cdmm_bus_down, &cpu);
+		mips_cdmm_bus_down(&cpu);
 		break;
 	default:
 		return NOTIFY_DONE;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/char/hw_random/exynos-rng.c linux-libre-4.7-gnu/drivers/char/hw_random/exynos-rng.c
--- linux-libre-4.6-gnu/drivers/char/hw_random/exynos-rng.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/char/hw_random/exynos-rng.c	2016-07-24 15:23:50.000000000 -0400
@@ -2,7 +2,7 @@
  * exynos-rng.c - Random Number Generator driver for the exynos
  *
  * Copyright (C) 2012 Samsung Electronics
- * Jonghwa Lee <jonghwa3.lee@smasung.com>
+ * Jonghwa Lee <jonghwa3.lee@samsung.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -77,7 +77,8 @@ static int exynos_init(struct hwrng *rng
 
 	pm_runtime_get_sync(exynos_rng->dev);
 	ret = exynos_rng_configure(exynos_rng);
-	pm_runtime_put_noidle(exynos_rng->dev);
+	pm_runtime_mark_last_busy(exynos_rng->dev);
+	pm_runtime_put_autosuspend(exynos_rng->dev);
 
 	return ret;
 }
@@ -89,6 +90,7 @@ static int exynos_read(struct hwrng *rng
 						struct exynos_rng, rng);
 	u32 *data = buf;
 	int retry = 100;
+	int ret = 4;
 
 	pm_runtime_get_sync(exynos_rng->dev);
 
@@ -97,23 +99,27 @@ static int exynos_read(struct hwrng *rng
 	while (!(exynos_rng_readl(exynos_rng,
 			EXYNOS_PRNG_STATUS_OFFSET) & PRNG_DONE) && --retry)
 		cpu_relax();
-	if (!retry)
-		return -ETIMEDOUT;
+	if (!retry) {
+		ret = -ETIMEDOUT;
+		goto out;
+	}
 
 	exynos_rng_writel(exynos_rng, PRNG_DONE, EXYNOS_PRNG_STATUS_OFFSET);
 
 	*data = exynos_rng_readl(exynos_rng, EXYNOS_PRNG_OUT1_OFFSET);
 
+out:
 	pm_runtime_mark_last_busy(exynos_rng->dev);
 	pm_runtime_put_sync_autosuspend(exynos_rng->dev);
 
-	return 4;
+	return ret;
 }
 
 static int exynos_rng_probe(struct platform_device *pdev)
 {
 	struct exynos_rng *exynos_rng;
 	struct resource *res;
+	int ret;
 
 	exynos_rng = devm_kzalloc(&pdev->dev, sizeof(struct exynos_rng),
 					GFP_KERNEL);
@@ -141,7 +147,21 @@ static int exynos_rng_probe(struct platf
 	pm_runtime_use_autosuspend(&pdev->dev);
 	pm_runtime_enable(&pdev->dev);
 
-	return devm_hwrng_register(&pdev->dev, &exynos_rng->rng);
+	ret = devm_hwrng_register(&pdev->dev, &exynos_rng->rng);
+	if (ret) {
+		pm_runtime_dont_use_autosuspend(&pdev->dev);
+		pm_runtime_disable(&pdev->dev);
+	}
+
+	return ret;
+}
+
+static int exynos_rng_remove(struct platform_device *pdev)
+{
+	pm_runtime_dont_use_autosuspend(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+
+	return 0;
 }
 
 static int __maybe_unused exynos_rng_runtime_suspend(struct device *dev)
@@ -201,6 +221,7 @@ static struct platform_driver exynos_rng
 		.of_match_table = exynos_rng_dt_match,
 	},
 	.probe		= exynos_rng_probe,
+	.remove		= exynos_rng_remove,
 };
 
 module_platform_driver(exynos_rng_driver);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/char/hw_random/hisi-rng.c linux-libre-4.7-gnu/drivers/char/hw_random/hisi-rng.c
--- linux-libre-4.6-gnu/drivers/char/hw_random/hisi-rng.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/char/hw_random/hisi-rng.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2016 HiSilicon Co., Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/hw_random.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/random.h>
+
+#define RNG_SEED	0x0
+#define RNG_CTRL	0x4
+  #define RNG_SEED_SEL	BIT(2)
+  #define RNG_RING_EN	BIT(1)
+  #define RNG_EN	BIT(0)
+#define RNG_RAN_NUM	0x10
+#define RNG_PHY_SEED	0x14
+
+#define to_hisi_rng(p)	container_of(p, struct hisi_rng, rng)
+
+static int seed_sel;
+module_param(seed_sel, int, S_IRUGO);
+MODULE_PARM_DESC(seed_sel, "Auto reload seed. 0, use LFSR(default); 1, use ring oscillator.");
+
+struct hisi_rng {
+	void __iomem *base;
+	struct hwrng rng;
+};
+
+static int hisi_rng_init(struct hwrng *rng)
+{
+	struct hisi_rng *hrng = to_hisi_rng(rng);
+	int val = RNG_EN;
+	u32 seed;
+
+	/* get a random number as initial seed */
+	get_random_bytes(&seed, sizeof(seed));
+
+	writel_relaxed(seed, hrng->base + RNG_SEED);
+
+	/**
+	 * The seed is reload periodically, there are two choice
+	 * of seeds, default seed using the value from LFSR, or
+	 * will use seed generated by ring oscillator.
+	 */
+	if (seed_sel == 1)
+		val |= RNG_RING_EN | RNG_SEED_SEL;
+
+	writel_relaxed(val, hrng->base + RNG_CTRL);
+	return 0;
+}
+
+static void hisi_rng_cleanup(struct hwrng *rng)
+{
+	struct hisi_rng *hrng = to_hisi_rng(rng);
+
+	writel_relaxed(0, hrng->base + RNG_CTRL);
+}
+
+static int hisi_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
+{
+	struct hisi_rng *hrng = to_hisi_rng(rng);
+	u32 *data = buf;
+
+	*data = readl_relaxed(hrng->base + RNG_RAN_NUM);
+	return 4;
+}
+
+static int hisi_rng_probe(struct platform_device *pdev)
+{
+	struct hisi_rng *rng;
+	struct resource *res;
+	int ret;
+
+	rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL);
+	if (!rng)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, rng);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	rng->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(rng->base))
+		return PTR_ERR(rng->base);
+
+	rng->rng.name = pdev->name;
+	rng->rng.init = hisi_rng_init;
+	rng->rng.cleanup = hisi_rng_cleanup;
+	rng->rng.read = hisi_rng_read;
+
+	ret = devm_hwrng_register(&pdev->dev, &rng->rng);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register hwrng\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct of_device_id hisi_rng_dt_ids[] = {
+	{ .compatible = "hisilicon,hip04-rng" },
+	{ .compatible = "hisilicon,hip05-rng" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, hisi_rng_dt_ids);
+
+static struct platform_driver hisi_rng_driver = {
+	.probe		= hisi_rng_probe,
+	.driver		= {
+		.name	= "hisi-rng",
+		.of_match_table = of_match_ptr(hisi_rng_dt_ids),
+	},
+};
+
+module_platform_driver(hisi_rng_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Kefeng Wang <wangkefeng.wang@huawei>");
+MODULE_DESCRIPTION("Hisilicon random number generator driver");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/char/hw_random/Kconfig linux-libre-4.7-gnu/drivers/char/hw_random/Kconfig
--- linux-libre-4.6-gnu/drivers/char/hw_random/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/char/hw_random/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -268,19 +268,6 @@ config HW_RANDOM_NOMADIK
 
 	  If unsure, say Y.
 
-config HW_RANDOM_PPC4XX
-	tristate "PowerPC 4xx generic true random number generator support"
-	depends on PPC && 4xx
-	default HW_RANDOM
-	---help---
-	 This driver provides the kernel-side support for the TRNG hardware
-	 found in the security function of some PowerPC 4xx SoCs.
-
-	 To compile this driver as a module, choose M here: the
-	 module will be called ppc4xx-rng.
-
-	 If unsure, say N.
-
 config HW_RANDOM_PSERIES
 	tristate "pSeries HW Random Number Generator support"
 	depends on PPC64 && IBMVIO
@@ -309,7 +296,8 @@ config HW_RANDOM_POWERNV
 
 config HW_RANDOM_EXYNOS
 	tristate "EXYNOS HW random number generator support"
-	depends on ARCH_EXYNOS
+	depends on ARCH_EXYNOS || COMPILE_TEST
+	depends on HAS_IOMEM
 	default HW_RANDOM
 	---help---
 	  This driver provides kernel-side support for the Random Number
@@ -333,6 +321,19 @@ config HW_RANDOM_TPM
 
 	  If unsure, say Y.
 
+config HW_RANDOM_HISI
+	tristate "Hisilicon Random Number Generator support"
+	depends on HW_RANDOM && ARCH_HISI
+	default HW_RANDOM
+	---help---
+	  This driver provides kernel-side support for the Random Number
+	  Generator hardware found on Hisilicon Hip04 and Hip05 SoC.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called hisi-rng.
+
+	  If unsure, say Y.
+
 config HW_RANDOM_MSM
 	tristate "Qualcomm SoCs Random Number Generator support"
 	depends on HW_RANDOM && ARCH_QCOM
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/char/hw_random/Makefile linux-libre-4.7-gnu/drivers/char/hw_random/Makefile
--- linux-libre-4.6-gnu/drivers/char/hw_random/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/char/hw_random/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -22,10 +22,10 @@ obj-$(CONFIG_HW_RANDOM_TX4939) += tx4939
 obj-$(CONFIG_HW_RANDOM_MXC_RNGA) += mxc-rnga.o
 obj-$(CONFIG_HW_RANDOM_OCTEON) += octeon-rng.o
 obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o
-obj-$(CONFIG_HW_RANDOM_PPC4XX) += ppc4xx-rng.o
 obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o
 obj-$(CONFIG_HW_RANDOM_POWERNV) += powernv-rng.o
 obj-$(CONFIG_HW_RANDOM_EXYNOS)	+= exynos-rng.o
+obj-$(CONFIG_HW_RANDOM_HISI)	+= hisi-rng.o
 obj-$(CONFIG_HW_RANDOM_TPM) += tpm-rng.o
 obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o
 obj-$(CONFIG_HW_RANDOM_IPROC_RNG200) += iproc-rng200.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/char/hw_random/ppc4xx-rng.c linux-libre-4.7-gnu/drivers/char/hw_random/ppc4xx-rng.c
--- linux-libre-4.6-gnu/drivers/char/hw_random/ppc4xx-rng.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/char/hw_random/ppc4xx-rng.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,147 +0,0 @@
-/*
- * Generic PowerPC 44x RNG driver
- *
- * Copyright 2011 IBM 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.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/hw_random.h>
-#include <linux/delay.h>
-#include <linux/of_address.h>
-#include <linux/of_platform.h>
-#include <asm/io.h>
-
-#define PPC4XX_TRNG_DEV_CTRL 0x60080
-
-#define PPC4XX_TRNGE 0x00020000
-#define PPC4XX_TRNG_CTRL 0x0008
-#define PPC4XX_TRNG_CTRL_DALM 0x20
-#define PPC4XX_TRNG_STAT 0x0004
-#define PPC4XX_TRNG_STAT_B 0x1
-#define PPC4XX_TRNG_DATA 0x0000
-
-#define MODULE_NAME "ppc4xx_rng"
-
-static int ppc4xx_rng_data_present(struct hwrng *rng, int wait)
-{
-	void __iomem *rng_regs = (void __iomem *) rng->priv;
-	int busy, i, present = 0;
-
-	for (i = 0; i < 20; i++) {
-		busy = (in_le32(rng_regs + PPC4XX_TRNG_STAT) & PPC4XX_TRNG_STAT_B);
-		if (!busy || !wait) {
-			present = 1;
-			break;
-		}
-		udelay(10);
-	}
-	return present;
-}
-
-static int ppc4xx_rng_data_read(struct hwrng *rng, u32 *data)
-{
-	void __iomem *rng_regs = (void __iomem *) rng->priv;
-	*data = in_le32(rng_regs + PPC4XX_TRNG_DATA);
-	return 4;
-}
-
-static int ppc4xx_rng_enable(int enable)
-{
-	struct device_node *ctrl;
-	void __iomem *ctrl_reg;
-	int err = 0;
-	u32 val;
-
-	/* Find the main crypto device node and map it to turn the TRNG on */
-	ctrl = of_find_compatible_node(NULL, NULL, "amcc,ppc4xx-crypto");
-	if (!ctrl)
-		return -ENODEV;
-
-	ctrl_reg = of_iomap(ctrl, 0);
-	if (!ctrl_reg) {
-		err = -ENODEV;
-		goto out;
-	}
-
-	val = in_le32(ctrl_reg + PPC4XX_TRNG_DEV_CTRL);
-
-	if (enable)
-		val |= PPC4XX_TRNGE;
-	else
-		val = val & ~PPC4XX_TRNGE;
-
-	out_le32(ctrl_reg + PPC4XX_TRNG_DEV_CTRL, val);
-	iounmap(ctrl_reg);
-
-out:
-	of_node_put(ctrl);
-
-	return err;
-}
-
-static struct hwrng ppc4xx_rng = {
-	.name = MODULE_NAME,
-	.data_present = ppc4xx_rng_data_present,
-	.data_read = ppc4xx_rng_data_read,
-};
-
-static int ppc4xx_rng_probe(struct platform_device *dev)
-{
-	void __iomem *rng_regs;
-	int err = 0;
-
-	rng_regs = of_iomap(dev->dev.of_node, 0);
-	if (!rng_regs)
-		return -ENODEV;
-
-	err = ppc4xx_rng_enable(1);
-	if (err)
-		return err;
-
-	out_le32(rng_regs + PPC4XX_TRNG_CTRL, PPC4XX_TRNG_CTRL_DALM);
-	ppc4xx_rng.priv = (unsigned long) rng_regs;
-
-	err = hwrng_register(&ppc4xx_rng);
-
-	return err;
-}
-
-static int ppc4xx_rng_remove(struct platform_device *dev)
-{
-	void __iomem *rng_regs = (void __iomem *) ppc4xx_rng.priv;
-
-	hwrng_unregister(&ppc4xx_rng);
-	ppc4xx_rng_enable(0);
-	iounmap(rng_regs);
-
-	return 0;
-}
-
-static const struct of_device_id ppc4xx_rng_match[] = {
-	{ .compatible = "ppc4xx-rng", },
-	{ .compatible = "amcc,ppc460ex-rng", },
-	{ .compatible = "amcc,ppc440epx-rng", },
-	{},
-};
-MODULE_DEVICE_TABLE(of, ppc4xx_rng_match);
-
-static struct platform_driver ppc4xx_rng_driver = {
-	.driver = {
-		.name = MODULE_NAME,
-		.of_match_table = ppc4xx_rng_match,
-	},
-	.probe = ppc4xx_rng_probe,
-	.remove = ppc4xx_rng_remove,
-};
-
-module_platform_driver(ppc4xx_rng_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Josh Boyer <jwboyer@linux.vnet.ibm.com>");
-MODULE_DESCRIPTION("HW RNG driver for PPC 4xx processors");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/char/ipmi/ipmi_msghandler.c linux-libre-4.7-gnu/drivers/char/ipmi/ipmi_msghandler.c
--- linux-libre-4.6-gnu/drivers/char/ipmi/ipmi_msghandler.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/char/ipmi/ipmi_msghandler.c	2016-07-24 15:23:50.000000000 -0400
@@ -3820,6 +3820,7 @@ static void handle_new_recv_msgs(ipmi_sm
 	while (!list_empty(&intf->waiting_rcv_msgs)) {
 		smi_msg = list_entry(intf->waiting_rcv_msgs.next,
 				     struct ipmi_smi_msg, link);
+		list_del(&smi_msg->link);
 		if (!run_to_completion)
 			spin_unlock_irqrestore(&intf->waiting_rcv_msgs_lock,
 					       flags);
@@ -3829,11 +3830,14 @@ static void handle_new_recv_msgs(ipmi_sm
 		if (rv > 0) {
 			/*
 			 * To preserve message order, quit if we
-			 * can't handle a message.
+			 * can't handle a message.  Add the message
+			 * back at the head, this is safe because this
+			 * tasklet is the only thing that pulls the
+			 * messages.
 			 */
+			list_add(&smi_msg->link, &intf->waiting_rcv_msgs);
 			break;
 		} else {
-			list_del(&smi_msg->link);
 			if (rv == 0)
 				/* Message handled */
 				ipmi_free_smi_msg(smi_msg);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/char/ipmi/ipmi_si_intf.c linux-libre-4.7-gnu/drivers/char/ipmi/ipmi_si_intf.c
--- linux-libre-4.6-gnu/drivers/char/ipmi/ipmi_si_intf.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/char/ipmi/ipmi_si_intf.c	2016-07-24 15:23:50.000000000 -0400
@@ -104,7 +104,7 @@ enum si_intf_state {
 #define IPMI_BT_INTMASK_ENABLE_IRQ_BIT	1
 
 enum si_type {
-    SI_KCS, SI_SMIC, SI_BT
+	SI_KCS, SI_SMIC, SI_BT
 };
 
 static const char * const si_to_str[] = { "kcs", "smic", "bt" };
@@ -410,7 +410,7 @@ static enum si_sm_result start_next_msg(
 
 		rv = SI_SM_CALL_WITHOUT_DELAY;
 	}
- out:
+out:
 	return rv;
 }
 
@@ -539,7 +539,7 @@ static struct ipmi_smi_msg *alloc_msg_ha
 
 static void handle_flags(struct smi_info *smi_info)
 {
- retry:
+retry:
 	if (smi_info->msg_flags & WDT_PRE_TIMEOUT_INT) {
 		/* Watchdog pre-timeout */
 		smi_inc_stat(smi_info, watchdog_pretimeouts);
@@ -831,7 +831,7 @@ static enum si_sm_result smi_event_handl
 {
 	enum si_sm_result si_sm_result;
 
- restart:
+restart:
 	/*
 	 * There used to be a loop here that waited a little while
 	 * (around 25us) before giving up.  That turned out to be
@@ -944,7 +944,7 @@ static enum si_sm_result smi_event_handl
 			smi_info->timer_running = false;
 	}
 
- out:
+out:
 	return si_sm_result;
 }
 
@@ -1190,7 +1190,7 @@ static void smi_timeout(unsigned long da
 		timeout = jiffies + SI_TIMEOUT_JIFFIES;
 	}
 
- do_mod_timer:
+do_mod_timer:
 	if (smi_result != SI_SM_IDLE)
 		smi_mod_timer(smi_info, timeout);
 	else
@@ -1576,10 +1576,9 @@ static int port_setup(struct smi_info *i
 		if (request_region(addr + idx * info->io.regspacing,
 				   info->io.regsize, DEVICE_NAME) == NULL) {
 			/* Undo allocations */
-			while (idx--) {
+			while (idx--)
 				release_region(addr + idx * info->io.regspacing,
 					       info->io.regsize);
-			}
 			return -EIO;
 		}
 	}
@@ -1638,25 +1637,28 @@ static void mem_outq(const struct si_sm_
 }
 #endif
 
-static void mem_cleanup(struct smi_info *info)
+static void mem_region_cleanup(struct smi_info *info, int num)
 {
 	unsigned long addr = info->io.addr_data;
-	int           mapsize;
+	int idx;
+
+	for (idx = 0; idx < num; idx++)
+		release_mem_region(addr + idx * info->io.regspacing,
+				   info->io.regsize);
+}
 
+static void mem_cleanup(struct smi_info *info)
+{
 	if (info->io.addr) {
 		iounmap(info->io.addr);
-
-		mapsize = ((info->io_size * info->io.regspacing)
-			   - (info->io.regspacing - info->io.regsize));
-
-		release_mem_region(addr, mapsize);
+		mem_region_cleanup(info, info->io_size);
 	}
 }
 
 static int mem_setup(struct smi_info *info)
 {
 	unsigned long addr = info->io.addr_data;
-	int           mapsize;
+	int           mapsize, idx;
 
 	if (!addr)
 		return -ENODEV;
@@ -1693,6 +1695,21 @@ static int mem_setup(struct smi_info *in
 	}
 
 	/*
+	 * Some BIOSes reserve disjoint memory regions in their ACPI
+	 * tables.  This causes problems when trying to request the
+	 * entire region.  Therefore we must request each register
+	 * separately.
+	 */
+	for (idx = 0; idx < info->io_size; idx++) {
+		if (request_mem_region(addr + idx * info->io.regspacing,
+				       info->io.regsize, DEVICE_NAME) == NULL) {
+			/* Undo allocations */
+			mem_region_cleanup(info, idx);
+			return -EIO;
+		}
+	}
+
+	/*
 	 * Calculate the total amount of memory to claim.  This is an
 	 * unusual looking calculation, but it avoids claiming any
 	 * more memory than it has to.  It will claim everything
@@ -1701,13 +1718,9 @@ static int mem_setup(struct smi_info *in
 	 */
 	mapsize = ((info->io_size * info->io.regspacing)
 		   - (info->io.regspacing - info->io.regsize));
-
-	if (request_mem_region(addr, mapsize, DEVICE_NAME) == NULL)
-		return -EIO;
-
 	info->io.addr = ioremap(addr, mapsize);
 	if (info->io.addr == NULL) {
-		release_mem_region(addr, mapsize);
+		mem_region_cleanup(info, info->io_size);
 		return -EIO;
 	}
 	return 0;
@@ -1975,7 +1988,7 @@ static int hotmod_handler(const char *va
 		}
 	}
 	rv = len;
- out:
+out:
 	kfree(str);
 	return rv;
 }
@@ -2945,7 +2958,7 @@ static int try_get_dev_id(struct smi_inf
 	/* Check and record info from the get device id, in case we need it. */
 	rv = ipmi_demangle_device_id(resp, resp_len, &smi_info->device_id);
 
- out:
+out:
 	kfree(resp);
 	return rv;
 }
@@ -3192,7 +3205,7 @@ static int try_enable_event_buffer(struc
 	else
 		smi_info->supports_event_msg_buff = true;
 
- out:
+out:
 	kfree(resp);
 	return rv;
 }
@@ -3718,10 +3731,10 @@ static int try_smi_init(struct smi_info
 
 	return 0;
 
- out_err_stop_timer:
+out_err_stop_timer:
 	wait_for_timer_and_thread(new_smi);
 
- out_err:
+out_err:
 	new_smi->interrupt_disabled = true;
 
 	if (new_smi->intf) {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/char/ipmi/ipmi_ssif.c linux-libre-4.7-gnu/drivers/char/ipmi/ipmi_ssif.c
--- linux-libre-4.6-gnu/drivers/char/ipmi/ipmi_ssif.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/char/ipmi/ipmi_ssif.c	2016-07-24 15:23:50.000000000 -0400
@@ -1870,7 +1870,7 @@ static int try_init_spmi(struct SPMITabl
 		return -EIO;
 	}
 
-	myaddr = spmi->addr.address >> 1;
+	myaddr = spmi->addr.address & 0x7f;
 
 	return new_ssif_client(myaddr, NULL, 0, 0, SI_SPMI);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/char/Kconfig linux-libre-4.7-gnu/drivers/char/Kconfig
--- linux-libre-4.6-gnu/drivers/char/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/char/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -279,8 +279,7 @@ if RTC_LIB=n
 
 config RTC
 	tristate "Enhanced Real Time Clock Support (legacy PC RTC driver)"
-	depends on !PPC && !PARISC && !IA64 && !M68K && !SPARC && !FRV \
-			&& !ARM && !SUPERH && !S390 && !AVR32 && !BLACKFIN && !UML
+	depends on ALPHA || (MIPS && MACH_LOONGSON64) || MN10300
 	---help---
 	  If you say Y here and create a character special file /dev/rtc with
 	  major number 10 and minor number 135 using mknod ("man mknod"), you
@@ -585,7 +584,6 @@ config TELCLOCK
 
 config DEVPORT
 	bool
-	depends on !M68K
 	depends on ISA || PCI
 	default y
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/char/pcmcia/synclink_cs.c linux-libre-4.7-gnu/drivers/char/pcmcia/synclink_cs.c
--- linux-libre-4.6-gnu/drivers/char/pcmcia/synclink_cs.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/char/pcmcia/synclink_cs.c	2016-07-24 15:23:50.000000000 -0400
@@ -1101,7 +1101,7 @@ static void dcd_change(MGSLPC_INFO *info
 	wake_up_interruptible(&info->status_event_wait_q);
 	wake_up_interruptible(&info->event_wait_q);
 
-	if (info->port.flags & ASYNC_CHECK_CD) {
+	if (tty_port_check_carrier(&info->port)) {
 		if (debug_level >= DEBUG_LEVEL_ISR)
 			printk("%s CD now %s...", info->device_name,
 			       (info->serial_signals & SerialSignal_DCD) ? "on" : "off");
@@ -1272,7 +1272,7 @@ static int startup(MGSLPC_INFO * info, s
 	if (debug_level >= DEBUG_LEVEL_INFO)
 		printk("%s(%d):startup(%s)\n", __FILE__, __LINE__, info->device_name);
 
-	if (info->port.flags & ASYNC_INITIALIZED)
+	if (tty_port_initialized(&info->port))
 		return 0;
 
 	if (!info->tx_buf) {
@@ -1311,7 +1311,7 @@ static int startup(MGSLPC_INFO * info, s
 	if (tty)
 		clear_bit(TTY_IO_ERROR, &tty->flags);
 
-	info->port.flags |= ASYNC_INITIALIZED;
+	tty_port_set_initialized(&info->port, 1);
 
 	return 0;
 }
@@ -1322,7 +1322,7 @@ static void shutdown(MGSLPC_INFO * info,
 {
 	unsigned long flags;
 
-	if (!(info->port.flags & ASYNC_INITIALIZED))
+	if (!tty_port_initialized(&info->port))
 		return;
 
 	if (debug_level >= DEBUG_LEVEL_INFO)
@@ -1361,7 +1361,7 @@ static void shutdown(MGSLPC_INFO * info,
 	if (tty)
 		set_bit(TTY_IO_ERROR, &tty->flags);
 
-	info->port.flags &= ~ASYNC_INITIALIZED;
+	tty_port_set_initialized(&info->port, 0);
 }
 
 static void mgslpc_program_hw(MGSLPC_INFO *info, struct tty_struct *tty)
@@ -1466,15 +1466,8 @@ static void mgslpc_change_params(MGSLPC_
 	}
 	info->timeout += HZ/50;		/* Add .02 seconds of slop */
 
-	if (cflag & CRTSCTS)
-		info->port.flags |= ASYNC_CTS_FLOW;
-	else
-		info->port.flags &= ~ASYNC_CTS_FLOW;
-
-	if (cflag & CLOCAL)
-		info->port.flags &= ~ASYNC_CHECK_CD;
-	else
-		info->port.flags |= ASYNC_CHECK_CD;
+	tty_port_set_cts_flow(&info->port, cflag & CRTSCTS);
+	tty_port_set_check_carrier(&info->port, ~cflag & CLOCAL);
 
 	/* process tty input control flags */
 
@@ -2246,7 +2239,7 @@ static int mgslpc_ioctl(struct tty_struc
 
 	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
 	    (cmd != TIOCMIWAIT)) {
-		if (tty->flags & (1 << TTY_IO_ERROR))
+		if (tty_io_error(tty))
 		    return -EIO;
 	}
 
@@ -2316,7 +2309,7 @@ static void mgslpc_set_termios(struct tt
 	/* Handle transition away from B0 status */
 	if (!(old_termios->c_cflag & CBAUD) && C_BAUD(tty)) {
 		info->serial_signals |= SerialSignal_DTR;
-		if (!C_CRTSCTS(tty) || !test_bit(TTY_THROTTLED, &tty->flags))
+		if (!C_CRTSCTS(tty) || !tty_throttled(tty))
 			info->serial_signals |= SerialSignal_RTS;
 		spin_lock_irqsave(&info->lock, flags);
 		set_signals(info);
@@ -2345,7 +2338,7 @@ static void mgslpc_close(struct tty_stru
 	if (tty_port_close_start(port, tty, filp) == 0)
 		goto cleanup;
 
-	if (port->flags & ASYNC_INITIALIZED)
+	if (tty_port_initialized(port))
 		mgslpc_wait_until_sent(tty, info->timeout);
 
 	mgslpc_flush_buffer(tty);
@@ -2378,7 +2371,7 @@ static void mgslpc_wait_until_sent(struc
 	if (mgslpc_paranoia_check(info, tty->name, "mgslpc_wait_until_sent"))
 		return;
 
-	if (!(info->port.flags & ASYNC_INITIALIZED))
+	if (!tty_port_initialized(&info->port))
 		goto exit;
 
 	orig_jiffies = jiffies;
@@ -3969,7 +3962,7 @@ static netdev_tx_t hdlcdev_xmit(struct s
 	dev_kfree_skb(skb);
 
 	/* save start time for transmit timeout detection */
-	dev->trans_start = jiffies;
+	netif_trans_update(dev);
 
 	/* start hardware transmitter if necessary */
 	spin_lock_irqsave(&info->lock, flags);
@@ -4032,7 +4025,7 @@ static int hdlcdev_open(struct net_devic
 	tty_kref_put(tty);
 
 	/* enable network layer transmit */
-	dev->trans_start = jiffies;
+	netif_trans_update(dev);
 	netif_start_queue(dev);
 
 	/* inform generic HDLC layer of current DCD status */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/char/random.c linux-libre-4.7-gnu/drivers/char/random.c
--- linux-libre-4.6-gnu/drivers/char/random.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/char/random.c	2016-07-24 15:23:50.000000000 -0400
@@ -260,6 +260,7 @@
 #include <linux/irq.h>
 #include <linux/syscalls.h>
 #include <linux/completion.h>
+#include <linux/uuid.h>
 
 #include <asm/processor.h>
 #include <asm/uaccess.h>
@@ -1621,26 +1622,6 @@ SYSCALL_DEFINE3(getrandom, char __user *
 	return urandom_read(NULL, buf, count, NULL);
 }
 
-/***************************************************************
- * Random UUID interface
- *
- * Used here for a Boot ID, but can be useful for other kernel
- * drivers.
- ***************************************************************/
-
-/*
- * Generate random UUID
- */
-void generate_random_uuid(unsigned char uuid_out[16])
-{
-	get_random_bytes(uuid_out, 16);
-	/* Set UUID version to 4 --- truly random generation */
-	uuid_out[6] = (uuid_out[6] & 0x0F) | 0x40;
-	/* Set the UUID variant to DCE */
-	uuid_out[8] = (uuid_out[8] & 0x3F) | 0x80;
-}
-EXPORT_SYMBOL(generate_random_uuid);
-
 /********************************************************************
  *
  * Sysctl interface
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/char/xillybus/xillybus_of.c linux-libre-4.7-gnu/drivers/char/xillybus/xillybus_of.c
--- linux-libre-4.6-gnu/drivers/char/xillybus/xillybus_of.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/char/xillybus/xillybus_of.c	2016-07-24 15:23:50.000000000 -0400
@@ -81,7 +81,6 @@ static int xilly_map_single_of(struct xi
 {
 	dma_addr_t addr;
 	struct xilly_mapping *this;
-	int rc;
 
 	this = kzalloc(sizeof(*this), GFP_KERNEL);
 	if (!this)
@@ -101,15 +100,7 @@ static int xilly_map_single_of(struct xi
 
 	*ret_dma_handle = addr;
 
-	rc = devm_add_action(ep->dev, xilly_of_unmap, this);
-
-	if (rc) {
-		dma_unmap_single(ep->dev, addr, size, direction);
-		kfree(this);
-		return rc;
-	}
-
-	return 0;
+	return devm_add_action_or_reset(ep->dev, xilly_of_unmap, this);
 }
 
 static struct xilly_endpoint_hardware of_hw = {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/char/xillybus/xillybus_pcie.c linux-libre-4.7-gnu/drivers/char/xillybus/xillybus_pcie.c
--- linux-libre-4.6-gnu/drivers/char/xillybus/xillybus_pcie.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/char/xillybus/xillybus_pcie.c	2016-07-24 15:23:50.000000000 -0400
@@ -98,7 +98,6 @@ static int xilly_map_single_pci(struct x
 	int pci_direction;
 	dma_addr_t addr;
 	struct xilly_mapping *this;
-	int rc;
 
 	this = kzalloc(sizeof(*this), GFP_KERNEL);
 	if (!this)
@@ -120,14 +119,7 @@ static int xilly_map_single_pci(struct x
 
 	*ret_dma_handle = addr;
 
-	rc = devm_add_action(ep->dev, xilly_pci_unmap, this);
-	if (rc) {
-		pci_unmap_single(ep->pdev, addr, size, pci_direction);
-		kfree(this);
-		return rc;
-	}
-
-	return 0;
+	return devm_add_action_or_reset(ep->dev, xilly_pci_unmap, this);
 }
 
 static struct xilly_endpoint_hardware pci_hw = {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/at91/clk-h32mx.c linux-libre-4.7-gnu/drivers/clk/at91/clk-h32mx.c
--- linux-libre-4.6-gnu/drivers/clk/at91/clk-h32mx.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/at91/clk-h32mx.c	2016-07-24 15:23:50.000000000 -0400
@@ -114,7 +114,7 @@ static void __init of_sama5d4_clk_h32mx_
 	h32mxclk->regmap = regmap;
 
 	clk = clk_register(NULL, &h32mxclk->hw);
-	if (!clk) {
+	if (IS_ERR(clk)) {
 		kfree(h32mxclk);
 		return;
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/at91/clk-programmable.c linux-libre-4.7-gnu/drivers/clk/at91/clk-programmable.c
--- linux-libre-4.6-gnu/drivers/clk/at91/clk-programmable.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/at91/clk-programmable.c	2016-07-24 15:23:50.000000000 -0400
@@ -99,7 +99,7 @@ static int clk_programmable_set_parent(s
 	struct clk_programmable *prog = to_clk_programmable(hw);
 	const struct clk_programmable_layout *layout = prog->layout;
 	unsigned int mask = layout->css_mask;
-	unsigned int pckr = 0;
+	unsigned int pckr = index;
 
 	if (layout->have_slck_mck)
 		mask |= AT91_PMC_CSSMCK_MCK;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/axis/clk-artpec6.c linux-libre-4.7-gnu/drivers/clk/axis/clk-artpec6.c
--- linux-libre-4.6-gnu/drivers/clk/axis/clk-artpec6.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/clk/axis/clk-artpec6.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,242 @@
+/*
+ * ARTPEC-6 clock initialization
+ *
+ * Copyright 2015-2016 Axis Comunications AB.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <dt-bindings/clock/axis,artpec6-clkctrl.h>
+
+#define NUM_I2S_CLOCKS 2
+
+struct artpec6_clkctrl_drvdata {
+	struct clk *clk_table[ARTPEC6_CLK_NUMCLOCKS];
+	void __iomem *syscon_base;
+	struct clk_onecell_data clk_data;
+	spinlock_t i2scfg_lock;
+};
+
+static struct artpec6_clkctrl_drvdata *clkdata;
+
+static const char *const i2s_clk_names[NUM_I2S_CLOCKS] = {
+	"i2s0",
+	"i2s1",
+};
+
+static const int i2s_clk_indexes[NUM_I2S_CLOCKS] = {
+	ARTPEC6_CLK_I2S0_CLK,
+	ARTPEC6_CLK_I2S1_CLK,
+};
+
+static void of_artpec6_clkctrl_setup(struct device_node *np)
+{
+	int i;
+	const char *sys_refclk_name;
+	u32 pll_mode, pll_m, pll_n;
+	struct clk **clks;
+
+	/* Mandatory parent clock. */
+	i = of_property_match_string(np, "clock-names", "sys_refclk");
+	if (i < 0)
+		return;
+
+	sys_refclk_name = of_clk_get_parent_name(np, i);
+
+	clkdata = kzalloc(sizeof(*clkdata), GFP_KERNEL);
+	if (!clkdata)
+		return;
+
+	clks = clkdata->clk_table;
+
+	for (i = 0; i < ARTPEC6_CLK_NUMCLOCKS; ++i)
+		clks[i] = ERR_PTR(-EPROBE_DEFER);
+
+	clkdata->syscon_base = of_iomap(np, 0);
+	BUG_ON(clkdata->syscon_base == NULL);
+
+	/* Read PLL1 factors configured by boot strap pins. */
+	pll_mode = (readl(clkdata->syscon_base) >> 6) & 3;
+	switch (pll_mode) {
+	case 0:		/* DDR3-2133 mode */
+		pll_m = 4;
+		pll_n = 85;
+		break;
+	case 1:		/* DDR3-1866 mode */
+		pll_m = 6;
+		pll_n = 112;
+		break;
+	case 2:		/* DDR3-1600 mode */
+		pll_m = 4;
+		pll_n = 64;
+		break;
+	case 3:		/* DDR3-1333 mode */
+		pll_m = 8;
+		pll_n = 106;
+		break;
+	}
+
+	clks[ARTPEC6_CLK_CPU] =
+	    clk_register_fixed_factor(NULL, "cpu", sys_refclk_name, 0, pll_n,
+				      pll_m);
+	clks[ARTPEC6_CLK_CPU_PERIPH] =
+	    clk_register_fixed_factor(NULL, "cpu_periph", "cpu", 0, 1, 2);
+
+	/* EPROBE_DEFER on the apb_clock is not handled in amba devices. */
+	clks[ARTPEC6_CLK_UART_PCLK] =
+	    clk_register_fixed_factor(NULL, "uart_pclk", "cpu", 0, 1, 8);
+	clks[ARTPEC6_CLK_UART_REFCLK] =
+	    clk_register_fixed_rate(NULL, "uart_ref", sys_refclk_name, 0,
+				    50000000);
+
+	clks[ARTPEC6_CLK_SPI_PCLK] =
+	    clk_register_fixed_factor(NULL, "spi_pclk", "cpu", 0, 1, 8);
+	clks[ARTPEC6_CLK_SPI_SSPCLK] =
+	    clk_register_fixed_rate(NULL, "spi_sspclk", sys_refclk_name, 0,
+				    50000000);
+
+	clks[ARTPEC6_CLK_DBG_PCLK] =
+	    clk_register_fixed_factor(NULL, "dbg_pclk", "cpu", 0, 1, 8);
+
+	clkdata->clk_data.clks = clkdata->clk_table;
+	clkdata->clk_data.clk_num = ARTPEC6_CLK_NUMCLOCKS;
+
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clkdata->clk_data);
+}
+
+CLK_OF_DECLARE(artpec6_clkctrl, "axis,artpec6-clkctrl",
+	       of_artpec6_clkctrl_setup);
+
+static int artpec6_clkctrl_probe(struct platform_device *pdev)
+{
+	int propidx;
+	struct device_node *np = pdev->dev.of_node;
+	struct device *dev = &pdev->dev;
+	struct clk **clks = clkdata->clk_table;
+	const char *sys_refclk_name;
+	const char *i2s_refclk_name = NULL;
+	const char *frac_clk_name[2] = { NULL, NULL };
+	const char *i2s_mux_parents[2];
+	u32 muxreg;
+	int i;
+	int err = 0;
+
+	/* Mandatory parent clock. */
+	propidx = of_property_match_string(np, "clock-names", "sys_refclk");
+	if (propidx < 0)
+		return -EINVAL;
+
+	sys_refclk_name = of_clk_get_parent_name(np, propidx);
+
+	/* Find clock names of optional parent clocks. */
+	propidx = of_property_match_string(np, "clock-names", "i2s_refclk");
+	if (propidx >= 0)
+		i2s_refclk_name = of_clk_get_parent_name(np, propidx);
+
+	propidx = of_property_match_string(np, "clock-names", "frac_clk0");
+	if (propidx >= 0)
+		frac_clk_name[0] = of_clk_get_parent_name(np, propidx);
+	propidx = of_property_match_string(np, "clock-names", "frac_clk1");
+	if (propidx >= 0)
+		frac_clk_name[1] = of_clk_get_parent_name(np, propidx);
+
+	spin_lock_init(&clkdata->i2scfg_lock);
+
+	clks[ARTPEC6_CLK_NAND_CLKA] =
+	    clk_register_fixed_factor(dev, "nand_clka", "cpu", 0, 1, 8);
+	clks[ARTPEC6_CLK_NAND_CLKB] =
+	    clk_register_fixed_rate(dev, "nand_clkb", sys_refclk_name, 0,
+				    100000000);
+	clks[ARTPEC6_CLK_ETH_ACLK] =
+	    clk_register_fixed_factor(dev, "eth_aclk", "cpu", 0, 1, 4);
+	clks[ARTPEC6_CLK_DMA_ACLK] =
+	    clk_register_fixed_factor(dev, "dma_aclk", "cpu", 0, 1, 4);
+	clks[ARTPEC6_CLK_PTP_REF] =
+	    clk_register_fixed_rate(dev, "ptp_ref", sys_refclk_name, 0,
+				    100000000);
+	clks[ARTPEC6_CLK_SD_PCLK] =
+	    clk_register_fixed_rate(dev, "sd_pclk", sys_refclk_name, 0,
+				    100000000);
+	clks[ARTPEC6_CLK_SD_IMCLK] =
+	    clk_register_fixed_rate(dev, "sd_imclk", sys_refclk_name, 0,
+				    100000000);
+	clks[ARTPEC6_CLK_I2S_HST] =
+	    clk_register_fixed_factor(dev, "i2s_hst", "cpu", 0, 1, 8);
+
+	for (i = 0; i < NUM_I2S_CLOCKS; ++i) {
+		if (i2s_refclk_name && frac_clk_name[i]) {
+			i2s_mux_parents[0] = frac_clk_name[i];
+			i2s_mux_parents[1] = i2s_refclk_name;
+
+			clks[i2s_clk_indexes[i]] =
+			    clk_register_mux(dev, i2s_clk_names[i],
+					     i2s_mux_parents, 2,
+					     CLK_SET_RATE_NO_REPARENT |
+					     CLK_SET_RATE_PARENT,
+					     clkdata->syscon_base + 0x14, i, 1,
+					     0, &clkdata->i2scfg_lock);
+		} else if (frac_clk_name[i]) {
+			/* Lock the mux for internal clock reference. */
+			muxreg = readl(clkdata->syscon_base + 0x14);
+			muxreg &= ~BIT(i);
+			writel(muxreg, clkdata->syscon_base + 0x14);
+			clks[i2s_clk_indexes[i]] =
+			    clk_register_fixed_factor(dev, i2s_clk_names[i],
+						      frac_clk_name[i], 0, 1,
+						      1);
+		} else if (i2s_refclk_name) {
+			/* Lock the mux for external clock reference. */
+			muxreg = readl(clkdata->syscon_base + 0x14);
+			muxreg |= BIT(i);
+			writel(muxreg, clkdata->syscon_base + 0x14);
+			clks[i2s_clk_indexes[i]] =
+			    clk_register_fixed_factor(dev, i2s_clk_names[i],
+						      i2s_refclk_name, 0, 1, 1);
+		}
+	}
+
+	clks[ARTPEC6_CLK_I2C] =
+	    clk_register_fixed_rate(dev, "i2c", sys_refclk_name, 0, 100000000);
+
+	clks[ARTPEC6_CLK_SYS_TIMER] =
+	    clk_register_fixed_rate(dev, "timer", sys_refclk_name, 0,
+				    100000000);
+	clks[ARTPEC6_CLK_FRACDIV_IN] =
+	    clk_register_fixed_rate(dev, "fracdiv_in", sys_refclk_name, 0,
+				    600000000);
+
+	for (i = 0; i < ARTPEC6_CLK_NUMCLOCKS; ++i) {
+		if (IS_ERR(clks[i]) && PTR_ERR(clks[i]) != -EPROBE_DEFER) {
+			dev_err(dev,
+				"Failed to register clock at index %d err=%ld\n",
+				i, PTR_ERR(clks[i]));
+			err = PTR_ERR(clks[i]);
+		}
+	}
+
+	return err;
+}
+
+static const struct of_device_id artpec_clkctrl_of_match[] = {
+	{ .compatible = "axis,artpec6-clkctrl" },
+	{}
+};
+
+static struct platform_driver artpec6_clkctrl_driver = {
+	.probe = artpec6_clkctrl_probe,
+	.driver = {
+		   .name = "artpec6_clkctrl",
+		   .of_match_table = artpec_clkctrl_of_match,
+	},
+};
+
+builtin_platform_driver(artpec6_clkctrl_driver);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/axis/Makefile linux-libre-4.7-gnu/drivers/clk/axis/Makefile
--- linux-libre-4.6-gnu/drivers/clk/axis/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/clk/axis/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1 @@
+obj-$(CONFIG_MACH_ARTPEC6)	+= clk-artpec6.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/axs10x/i2s_pll_clock.c linux-libre-4.7-gnu/drivers/clk/axs10x/i2s_pll_clock.c
--- linux-libre-4.6-gnu/drivers/clk/axs10x/i2s_pll_clock.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/clk/axs10x/i2s_pll_clock.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,228 @@
+/*
+ * Synopsys AXS10X SDP I2S PLL clock driver
+ *
+ * Copyright (C) 2016 Synopsys
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+
+/* PLL registers addresses */
+#define PLL_IDIV_REG	0x0
+#define PLL_FBDIV_REG	0x4
+#define PLL_ODIV0_REG	0x8
+#define PLL_ODIV1_REG	0xC
+
+struct i2s_pll_cfg {
+	unsigned int rate;
+	unsigned int idiv;
+	unsigned int fbdiv;
+	unsigned int odiv0;
+	unsigned int odiv1;
+};
+
+static const struct i2s_pll_cfg i2s_pll_cfg_27m[] = {
+	/* 27 Mhz */
+	{ 1024000, 0x104, 0x451, 0x10E38, 0x2000 },
+	{ 1411200, 0x104, 0x596, 0x10D35, 0x2000 },
+	{ 1536000, 0x208, 0xA28, 0x10B2C, 0x2000 },
+	{ 2048000, 0x82, 0x451, 0x10E38, 0x2000 },
+	{ 2822400, 0x82, 0x596, 0x10D35, 0x2000 },
+	{ 3072000, 0x104, 0xA28, 0x10B2C, 0x2000 },
+	{ 2116800, 0x82, 0x3CF, 0x10C30, 0x2000 },
+	{ 2304000, 0x104, 0x79E, 0x10B2C, 0x2000 },
+	{ 0, 0, 0, 0, 0 },
+};
+
+static const struct i2s_pll_cfg i2s_pll_cfg_28m[] = {
+	/* 28.224 Mhz */
+	{ 1024000, 0x82, 0x105, 0x107DF, 0x2000 },
+	{ 1411200, 0x28A, 0x1, 0x10001, 0x2000 },
+	{ 1536000, 0xA28, 0x187, 0x10042, 0x2000 },
+	{ 2048000, 0x41, 0x105, 0x107DF, 0x2000 },
+	{ 2822400, 0x145, 0x1, 0x10001, 0x2000 },
+	{ 3072000, 0x514, 0x187, 0x10042, 0x2000 },
+	{ 2116800, 0x514, 0x42, 0x10001, 0x2000 },
+	{ 2304000, 0x619, 0x82, 0x10001, 0x2000 },
+	{ 0, 0, 0, 0, 0 },
+};
+
+struct i2s_pll_clk {
+	void __iomem *base;
+	struct clk_hw hw;
+	struct device *dev;
+};
+
+static inline void i2s_pll_write(struct i2s_pll_clk *clk, unsigned int reg,
+		unsigned int val)
+{
+	writel_relaxed(val, clk->base + reg);
+}
+
+static inline unsigned int i2s_pll_read(struct i2s_pll_clk *clk,
+		unsigned int reg)
+{
+	return readl_relaxed(clk->base + reg);
+}
+
+static inline struct i2s_pll_clk *to_i2s_pll_clk(struct clk_hw *hw)
+{
+	return container_of(hw, struct i2s_pll_clk, hw);
+}
+
+static inline unsigned int i2s_pll_get_value(unsigned int val)
+{
+	return (val & 0x3F) + ((val >> 6) & 0x3F);
+}
+
+static const struct i2s_pll_cfg *i2s_pll_get_cfg(unsigned long prate)
+{
+	switch (prate) {
+	case 27000000:
+		return i2s_pll_cfg_27m;
+	case 28224000:
+		return i2s_pll_cfg_28m;
+	default:
+		return NULL;
+	}
+}
+
+static unsigned long i2s_pll_recalc_rate(struct clk_hw *hw,
+			unsigned long parent_rate)
+{
+	struct i2s_pll_clk *clk = to_i2s_pll_clk(hw);
+	unsigned int idiv, fbdiv, odiv;
+
+	idiv = i2s_pll_get_value(i2s_pll_read(clk, PLL_IDIV_REG));
+	fbdiv = i2s_pll_get_value(i2s_pll_read(clk, PLL_FBDIV_REG));
+	odiv = i2s_pll_get_value(i2s_pll_read(clk, PLL_ODIV0_REG));
+
+	return ((parent_rate / idiv) * fbdiv) / odiv;
+}
+
+static long i2s_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+			unsigned long *prate)
+{
+	struct i2s_pll_clk *clk = to_i2s_pll_clk(hw);
+	const struct i2s_pll_cfg *pll_cfg = i2s_pll_get_cfg(*prate);
+	int i;
+
+	if (!pll_cfg) {
+		dev_err(clk->dev, "invalid parent rate=%ld\n", *prate);
+		return -EINVAL;
+	}
+
+	for (i = 0; pll_cfg[i].rate != 0; i++)
+		if (pll_cfg[i].rate == rate)
+			return rate;
+
+	return -EINVAL;
+}
+
+static int i2s_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+			unsigned long parent_rate)
+{
+	struct i2s_pll_clk *clk = to_i2s_pll_clk(hw);
+	const struct i2s_pll_cfg *pll_cfg = i2s_pll_get_cfg(parent_rate);
+	int i;
+
+	if (!pll_cfg) {
+		dev_err(clk->dev, "invalid parent rate=%ld\n", parent_rate);
+		return -EINVAL;
+	}
+
+	for (i = 0; pll_cfg[i].rate != 0; i++) {
+		if (pll_cfg[i].rate == rate) {
+			i2s_pll_write(clk, PLL_IDIV_REG, pll_cfg[i].idiv);
+			i2s_pll_write(clk, PLL_FBDIV_REG, pll_cfg[i].fbdiv);
+			i2s_pll_write(clk, PLL_ODIV0_REG, pll_cfg[i].odiv0);
+			i2s_pll_write(clk, PLL_ODIV1_REG, pll_cfg[i].odiv1);
+			return 0;
+		}
+	}
+
+	dev_err(clk->dev, "invalid rate=%ld, parent_rate=%ld\n", rate,
+			parent_rate);
+	return -EINVAL;
+}
+
+static const struct clk_ops i2s_pll_ops = {
+	.recalc_rate = i2s_pll_recalc_rate,
+	.round_rate = i2s_pll_round_rate,
+	.set_rate = i2s_pll_set_rate,
+};
+
+static int i2s_pll_clk_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *node = dev->of_node;
+	const char *clk_name;
+	const char *parent_name;
+	struct clk *clk;
+	struct i2s_pll_clk *pll_clk;
+	struct clk_init_data init;
+	struct resource *mem;
+
+	pll_clk = devm_kzalloc(dev, sizeof(*pll_clk), GFP_KERNEL);
+	if (!pll_clk)
+		return -ENOMEM;
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	pll_clk->base = devm_ioremap_resource(dev, mem);
+	if (IS_ERR(pll_clk->base))
+		return PTR_ERR(pll_clk->base);
+
+	clk_name = node->name;
+	init.name = clk_name;
+	init.ops = &i2s_pll_ops;
+	parent_name = of_clk_get_parent_name(node, 0);
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+	pll_clk->hw.init = &init;
+	pll_clk->dev = dev;
+
+	clk = devm_clk_register(dev, &pll_clk->hw);
+	if (IS_ERR(clk)) {
+		dev_err(dev, "failed to register %s clock (%ld)\n",
+				clk_name, PTR_ERR(clk));
+		return PTR_ERR(clk);
+	}
+
+	return of_clk_add_provider(node, of_clk_src_simple_get, clk);
+}
+
+static int i2s_pll_clk_remove(struct platform_device *pdev)
+{
+	of_clk_del_provider(pdev->dev.of_node);
+	return 0;
+}
+
+static const struct of_device_id i2s_pll_clk_id[] = {
+	{ .compatible = "snps,axs10x-i2s-pll-clock", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, i2s_pll_clk_id);
+
+static struct platform_driver i2s_pll_clk_driver = {
+	.driver = {
+		.name = "axs10x-i2s-pll-clock",
+		.of_match_table = i2s_pll_clk_id,
+	},
+	.probe = i2s_pll_clk_probe,
+	.remove = i2s_pll_clk_remove,
+};
+module_platform_driver(i2s_pll_clk_driver);
+
+MODULE_AUTHOR("Jose Abreu <joabreu@synopsys.com>");
+MODULE_DESCRIPTION("Synopsys AXS10X SDP I2S PLL Clock Driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/axs10x/Makefile linux-libre-4.7-gnu/drivers/clk/axs10x/Makefile
--- linux-libre-4.6-gnu/drivers/clk/axs10x/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/clk/axs10x/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1 @@
+obj-y += i2s_pll_clock.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/bcm/clk-bcm2835.c linux-libre-4.7-gnu/drivers/clk/bcm/clk-bcm2835.c
--- linux-libre-4.6-gnu/drivers/clk/bcm/clk-bcm2835.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/bcm/clk-bcm2835.c	2016-07-24 15:23:50.000000000 -0400
@@ -12,9 +12,6 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
 /**
@@ -40,6 +37,7 @@
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/clk/bcm2835.h>
+#include <linux/debugfs.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
@@ -51,6 +49,7 @@
 #define CM_GNRICCTL		0x000
 #define CM_GNRICDIV		0x004
 # define CM_DIV_FRAC_BITS	12
+# define CM_DIV_FRAC_MASK	GENMASK(CM_DIV_FRAC_BITS - 1, 0)
 
 #define CM_VPUCTL		0x008
 #define CM_VPUDIV		0x00c
@@ -118,6 +117,8 @@
 #define CM_SDCCTL		0x1a8
 #define CM_SDCDIV		0x1ac
 #define CM_ARMCTL		0x1b0
+#define CM_AVEOCTL		0x1b8
+#define CM_AVEODIV		0x1bc
 #define CM_EMMCCTL		0x1c0
 #define CM_EMMCDIV		0x1c4
 
@@ -128,6 +129,7 @@
 # define CM_GATE			BIT(CM_GATE_BIT)
 # define CM_BUSY			BIT(7)
 # define CM_BUSYD			BIT(8)
+# define CM_FRAC			BIT(9)
 # define CM_SRC_SHIFT			0
 # define CM_SRC_BITS			4
 # define CM_SRC_MASK			0xf
@@ -297,11 +299,11 @@
 struct bcm2835_cprman {
 	struct device *dev;
 	void __iomem *regs;
-	spinlock_t regs_lock;
+	spinlock_t regs_lock; /* spinlock for all clocks */
 	const char *osc_name;
 
 	struct clk_onecell_data onecell;
-	struct clk *clks[BCM2835_CLOCK_COUNT];
+	struct clk *clks[];
 };
 
 static inline void cprman_write(struct bcm2835_cprman *cprman, u32 reg, u32 val)
@@ -314,6 +316,27 @@ static inline u32 cprman_read(struct bcm
 	return readl(cprman->regs + reg);
 }
 
+static int bcm2835_debugfs_regset(struct bcm2835_cprman *cprman, u32 base,
+				  struct debugfs_reg32 *regs, size_t nregs,
+				  struct dentry *dentry)
+{
+	struct dentry *regdump;
+	struct debugfs_regset32 *regset;
+
+	regset = devm_kzalloc(cprman->dev, sizeof(*regset), GFP_KERNEL);
+	if (!regset)
+		return -ENOMEM;
+
+	regset->regs = regs;
+	regset->nregs = nregs;
+	regset->base = cprman->regs + base;
+
+	regdump = debugfs_create_regset32("regdump", S_IRUGO, dentry,
+					  regset);
+
+	return regdump ? 0 : -ENOMEM;
+}
+
 /*
  * These are fixed clocks. They're probably not all root clocks and it may
  * be possible to turn them on and off but until this is mapped out better
@@ -377,132 +400,27 @@ struct bcm2835_pll_ana_bits {
 static const struct bcm2835_pll_ana_bits bcm2835_ana_default = {
 	.mask0 = 0,
 	.set0 = 0,
-	.mask1 = ~(A2W_PLL_KI_MASK | A2W_PLL_KP_MASK),
+	.mask1 = (u32)~(A2W_PLL_KI_MASK | A2W_PLL_KP_MASK),
 	.set1 = (2 << A2W_PLL_KI_SHIFT) | (8 << A2W_PLL_KP_SHIFT),
-	.mask3 = ~A2W_PLL_KA_MASK,
+	.mask3 = (u32)~A2W_PLL_KA_MASK,
 	.set3 = (2 << A2W_PLL_KA_SHIFT),
 	.fb_prediv_mask = BIT(14),
 };
 
 static const struct bcm2835_pll_ana_bits bcm2835_ana_pllh = {
-	.mask0 = ~(A2W_PLLH_KA_MASK | A2W_PLLH_KI_LOW_MASK),
+	.mask0 = (u32)~(A2W_PLLH_KA_MASK | A2W_PLLH_KI_LOW_MASK),
 	.set0 = (2 << A2W_PLLH_KA_SHIFT) | (2 << A2W_PLLH_KI_LOW_SHIFT),
-	.mask1 = ~(A2W_PLLH_KI_HIGH_MASK | A2W_PLLH_KP_MASK),
+	.mask1 = (u32)~(A2W_PLLH_KI_HIGH_MASK | A2W_PLLH_KP_MASK),
 	.set1 = (6 << A2W_PLLH_KP_SHIFT),
 	.mask3 = 0,
 	.set3 = 0,
 	.fb_prediv_mask = BIT(11),
 };
 
-/*
- * PLLA is the auxiliary PLL, used to drive the CCP2 (Compact Camera
- * Port 2) transmitter clock.
- *
- * It is in the PX LDO power domain, which is on when the AUDIO domain
- * is on.
- */
-static const struct bcm2835_pll_data bcm2835_plla_data = {
-	.name = "plla",
-	.cm_ctrl_reg = CM_PLLA,
-	.a2w_ctrl_reg = A2W_PLLA_CTRL,
-	.frac_reg = A2W_PLLA_FRAC,
-	.ana_reg_base = A2W_PLLA_ANA0,
-	.reference_enable_mask = A2W_XOSC_CTRL_PLLA_ENABLE,
-	.lock_mask = CM_LOCK_FLOCKA,
-
-	.ana = &bcm2835_ana_default,
-
-	.min_rate = 600000000u,
-	.max_rate = 2400000000u,
-	.max_fb_rate = BCM2835_MAX_FB_RATE,
-};
-
-/* PLLB is used for the ARM's clock. */
-static const struct bcm2835_pll_data bcm2835_pllb_data = {
-	.name = "pllb",
-	.cm_ctrl_reg = CM_PLLB,
-	.a2w_ctrl_reg = A2W_PLLB_CTRL,
-	.frac_reg = A2W_PLLB_FRAC,
-	.ana_reg_base = A2W_PLLB_ANA0,
-	.reference_enable_mask = A2W_XOSC_CTRL_PLLB_ENABLE,
-	.lock_mask = CM_LOCK_FLOCKB,
-
-	.ana = &bcm2835_ana_default,
-
-	.min_rate = 600000000u,
-	.max_rate = 3000000000u,
-	.max_fb_rate = BCM2835_MAX_FB_RATE,
-};
-
-/*
- * PLLC is the core PLL, used to drive the core VPU clock.
- *
- * It is in the PX LDO power domain, which is on when the AUDIO domain
- * is on.
-*/
-static const struct bcm2835_pll_data bcm2835_pllc_data = {
-	.name = "pllc",
-	.cm_ctrl_reg = CM_PLLC,
-	.a2w_ctrl_reg = A2W_PLLC_CTRL,
-	.frac_reg = A2W_PLLC_FRAC,
-	.ana_reg_base = A2W_PLLC_ANA0,
-	.reference_enable_mask = A2W_XOSC_CTRL_PLLC_ENABLE,
-	.lock_mask = CM_LOCK_FLOCKC,
-
-	.ana = &bcm2835_ana_default,
-
-	.min_rate = 600000000u,
-	.max_rate = 3000000000u,
-	.max_fb_rate = BCM2835_MAX_FB_RATE,
-};
-
-/*
- * PLLD is the display PLL, used to drive DSI display panels.
- *
- * It is in the PX LDO power domain, which is on when the AUDIO domain
- * is on.
- */
-static const struct bcm2835_pll_data bcm2835_plld_data = {
-	.name = "plld",
-	.cm_ctrl_reg = CM_PLLD,
-	.a2w_ctrl_reg = A2W_PLLD_CTRL,
-	.frac_reg = A2W_PLLD_FRAC,
-	.ana_reg_base = A2W_PLLD_ANA0,
-	.reference_enable_mask = A2W_XOSC_CTRL_DDR_ENABLE,
-	.lock_mask = CM_LOCK_FLOCKD,
-
-	.ana = &bcm2835_ana_default,
-
-	.min_rate = 600000000u,
-	.max_rate = 2400000000u,
-	.max_fb_rate = BCM2835_MAX_FB_RATE,
-};
-
-/*
- * PLLH is used to supply the pixel clock or the AUX clock for the TV
- * encoder.
- *
- * It is in the HDMI power domain.
- */
-static const struct bcm2835_pll_data bcm2835_pllh_data = {
-	"pllh",
-	.cm_ctrl_reg = CM_PLLH,
-	.a2w_ctrl_reg = A2W_PLLH_CTRL,
-	.frac_reg = A2W_PLLH_FRAC,
-	.ana_reg_base = A2W_PLLH_ANA0,
-	.reference_enable_mask = A2W_XOSC_CTRL_PLLC_ENABLE,
-	.lock_mask = CM_LOCK_FLOCKH,
-
-	.ana = &bcm2835_ana_pllh,
-
-	.min_rate = 600000000u,
-	.max_rate = 3000000000u,
-	.max_fb_rate = BCM2835_MAX_FB_RATE,
-};
-
 struct bcm2835_pll_divider_data {
 	const char *name;
-	const struct bcm2835_pll_data *source_pll;
+	const char *source_pll;
+
 	u32 cm_reg;
 	u32 a2w_reg;
 
@@ -511,124 +429,6 @@ struct bcm2835_pll_divider_data {
 	u32 fixed_divider;
 };
 
-static const struct bcm2835_pll_divider_data bcm2835_plla_core_data = {
-	.name = "plla_core",
-	.source_pll = &bcm2835_plla_data,
-	.cm_reg = CM_PLLA,
-	.a2w_reg = A2W_PLLA_CORE,
-	.load_mask = CM_PLLA_LOADCORE,
-	.hold_mask = CM_PLLA_HOLDCORE,
-	.fixed_divider = 1,
-};
-
-static const struct bcm2835_pll_divider_data bcm2835_plla_per_data = {
-	.name = "plla_per",
-	.source_pll = &bcm2835_plla_data,
-	.cm_reg = CM_PLLA,
-	.a2w_reg = A2W_PLLA_PER,
-	.load_mask = CM_PLLA_LOADPER,
-	.hold_mask = CM_PLLA_HOLDPER,
-	.fixed_divider = 1,
-};
-
-static const struct bcm2835_pll_divider_data bcm2835_pllb_arm_data = {
-	.name = "pllb_arm",
-	.source_pll = &bcm2835_pllb_data,
-	.cm_reg = CM_PLLB,
-	.a2w_reg = A2W_PLLB_ARM,
-	.load_mask = CM_PLLB_LOADARM,
-	.hold_mask = CM_PLLB_HOLDARM,
-	.fixed_divider = 1,
-};
-
-static const struct bcm2835_pll_divider_data bcm2835_pllc_core0_data = {
-	.name = "pllc_core0",
-	.source_pll = &bcm2835_pllc_data,
-	.cm_reg = CM_PLLC,
-	.a2w_reg = A2W_PLLC_CORE0,
-	.load_mask = CM_PLLC_LOADCORE0,
-	.hold_mask = CM_PLLC_HOLDCORE0,
-	.fixed_divider = 1,
-};
-
-static const struct bcm2835_pll_divider_data bcm2835_pllc_core1_data = {
-	.name = "pllc_core1", .source_pll = &bcm2835_pllc_data,
-	.cm_reg = CM_PLLC, A2W_PLLC_CORE1,
-	.load_mask = CM_PLLC_LOADCORE1,
-	.hold_mask = CM_PLLC_HOLDCORE1,
-	.fixed_divider = 1,
-};
-
-static const struct bcm2835_pll_divider_data bcm2835_pllc_core2_data = {
-	.name = "pllc_core2",
-	.source_pll = &bcm2835_pllc_data,
-	.cm_reg = CM_PLLC,
-	.a2w_reg = A2W_PLLC_CORE2,
-	.load_mask = CM_PLLC_LOADCORE2,
-	.hold_mask = CM_PLLC_HOLDCORE2,
-	.fixed_divider = 1,
-};
-
-static const struct bcm2835_pll_divider_data bcm2835_pllc_per_data = {
-	.name = "pllc_per",
-	.source_pll = &bcm2835_pllc_data,
-	.cm_reg = CM_PLLC,
-	.a2w_reg = A2W_PLLC_PER,
-	.load_mask = CM_PLLC_LOADPER,
-	.hold_mask = CM_PLLC_HOLDPER,
-	.fixed_divider = 1,
-};
-
-static const struct bcm2835_pll_divider_data bcm2835_plld_core_data = {
-	.name = "plld_core",
-	.source_pll = &bcm2835_plld_data,
-	.cm_reg = CM_PLLD,
-	.a2w_reg = A2W_PLLD_CORE,
-	.load_mask = CM_PLLD_LOADCORE,
-	.hold_mask = CM_PLLD_HOLDCORE,
-	.fixed_divider = 1,
-};
-
-static const struct bcm2835_pll_divider_data bcm2835_plld_per_data = {
-	.name = "plld_per",
-	.source_pll = &bcm2835_plld_data,
-	.cm_reg = CM_PLLD,
-	.a2w_reg = A2W_PLLD_PER,
-	.load_mask = CM_PLLD_LOADPER,
-	.hold_mask = CM_PLLD_HOLDPER,
-	.fixed_divider = 1,
-};
-
-static const struct bcm2835_pll_divider_data bcm2835_pllh_rcal_data = {
-	.name = "pllh_rcal",
-	.source_pll = &bcm2835_pllh_data,
-	.cm_reg = CM_PLLH,
-	.a2w_reg = A2W_PLLH_RCAL,
-	.load_mask = CM_PLLH_LOADRCAL,
-	.hold_mask = 0,
-	.fixed_divider = 10,
-};
-
-static const struct bcm2835_pll_divider_data bcm2835_pllh_aux_data = {
-	.name = "pllh_aux",
-	.source_pll = &bcm2835_pllh_data,
-	.cm_reg = CM_PLLH,
-	.a2w_reg = A2W_PLLH_AUX,
-	.load_mask = CM_PLLH_LOADAUX,
-	.hold_mask = 0,
-	.fixed_divider = 10,
-};
-
-static const struct bcm2835_pll_divider_data bcm2835_pllh_pix_data = {
-	.name = "pllh_pix",
-	.source_pll = &bcm2835_pllh_data,
-	.cm_reg = CM_PLLH,
-	.a2w_reg = A2W_PLLH_PIX,
-	.load_mask = CM_PLLH_LOADPIX,
-	.hold_mask = 0,
-	.fixed_divider = 10,
-};
-
 struct bcm2835_clock_data {
 	const char *name;
 
@@ -644,187 +444,14 @@ struct bcm2835_clock_data {
 	u32 frac_bits;
 
 	bool is_vpu_clock;
+	bool is_mash_clock;
 };
 
-static const char *const bcm2835_clock_per_parents[] = {
-	"gnd",
-	"xosc",
-	"testdebug0",
-	"testdebug1",
-	"plla_per",
-	"pllc_per",
-	"plld_per",
-	"pllh_aux",
-};
-
-static const char *const bcm2835_clock_vpu_parents[] = {
-	"gnd",
-	"xosc",
-	"testdebug0",
-	"testdebug1",
-	"plla_core",
-	"pllc_core0",
-	"plld_core",
-	"pllh_aux",
-	"pllc_core1",
-	"pllc_core2",
-};
-
-static const char *const bcm2835_clock_osc_parents[] = {
-	"gnd",
-	"xosc",
-	"testdebug0",
-	"testdebug1"
-};
-
-/*
- * Used for a 1Mhz clock for the system clocksource, and also used by
- * the watchdog timer and the camera pulse generator.
- */
-static const struct bcm2835_clock_data bcm2835_clock_timer_data = {
-	.name = "timer",
-	.num_mux_parents = ARRAY_SIZE(bcm2835_clock_osc_parents),
-	.parents = bcm2835_clock_osc_parents,
-	.ctl_reg = CM_TIMERCTL,
-	.div_reg = CM_TIMERDIV,
-	.int_bits = 6,
-	.frac_bits = 12,
-};
-
-/* One Time Programmable Memory clock.  Maximum 10Mhz. */
-static const struct bcm2835_clock_data bcm2835_clock_otp_data = {
-	.name = "otp",
-	.num_mux_parents = ARRAY_SIZE(bcm2835_clock_osc_parents),
-	.parents = bcm2835_clock_osc_parents,
-	.ctl_reg = CM_OTPCTL,
-	.div_reg = CM_OTPDIV,
-	.int_bits = 4,
-	.frac_bits = 0,
-};
-
-/*
- * VPU clock.  This doesn't have an enable bit, since it drives the
- * bus for everything else, and is special so it doesn't need to be
- * gated for rate changes.  It is also known as "clk_audio" in various
- * hardware documentation.
- */
-static const struct bcm2835_clock_data bcm2835_clock_vpu_data = {
-	.name = "vpu",
-	.num_mux_parents = ARRAY_SIZE(bcm2835_clock_vpu_parents),
-	.parents = bcm2835_clock_vpu_parents,
-	.ctl_reg = CM_VPUCTL,
-	.div_reg = CM_VPUDIV,
-	.int_bits = 12,
-	.frac_bits = 8,
-	.is_vpu_clock = true,
-};
-
-static const struct bcm2835_clock_data bcm2835_clock_v3d_data = {
-	.name = "v3d",
-	.num_mux_parents = ARRAY_SIZE(bcm2835_clock_vpu_parents),
-	.parents = bcm2835_clock_vpu_parents,
-	.ctl_reg = CM_V3DCTL,
-	.div_reg = CM_V3DDIV,
-	.int_bits = 4,
-	.frac_bits = 8,
-};
-
-static const struct bcm2835_clock_data bcm2835_clock_isp_data = {
-	.name = "isp",
-	.num_mux_parents = ARRAY_SIZE(bcm2835_clock_vpu_parents),
-	.parents = bcm2835_clock_vpu_parents,
-	.ctl_reg = CM_ISPCTL,
-	.div_reg = CM_ISPDIV,
-	.int_bits = 4,
-	.frac_bits = 8,
-};
-
-static const struct bcm2835_clock_data bcm2835_clock_h264_data = {
-	.name = "h264",
-	.num_mux_parents = ARRAY_SIZE(bcm2835_clock_vpu_parents),
-	.parents = bcm2835_clock_vpu_parents,
-	.ctl_reg = CM_H264CTL,
-	.div_reg = CM_H264DIV,
-	.int_bits = 4,
-	.frac_bits = 8,
-};
-
-/* TV encoder clock.  Only operating frequency is 108Mhz.  */
-static const struct bcm2835_clock_data bcm2835_clock_vec_data = {
-	.name = "vec",
-	.num_mux_parents = ARRAY_SIZE(bcm2835_clock_per_parents),
-	.parents = bcm2835_clock_per_parents,
-	.ctl_reg = CM_VECCTL,
-	.div_reg = CM_VECDIV,
-	.int_bits = 4,
-	.frac_bits = 0,
-};
-
-static const struct bcm2835_clock_data bcm2835_clock_uart_data = {
-	.name = "uart",
-	.num_mux_parents = ARRAY_SIZE(bcm2835_clock_per_parents),
-	.parents = bcm2835_clock_per_parents,
-	.ctl_reg = CM_UARTCTL,
-	.div_reg = CM_UARTDIV,
-	.int_bits = 10,
-	.frac_bits = 12,
-};
-
-/* HDMI state machine */
-static const struct bcm2835_clock_data bcm2835_clock_hsm_data = {
-	.name = "hsm",
-	.num_mux_parents = ARRAY_SIZE(bcm2835_clock_per_parents),
-	.parents = bcm2835_clock_per_parents,
-	.ctl_reg = CM_HSMCTL,
-	.div_reg = CM_HSMDIV,
-	.int_bits = 4,
-	.frac_bits = 8,
-};
-
-/*
- * Secondary SDRAM clock.  Used for low-voltage modes when the PLL in
- * the SDRAM controller can't be used.
- */
-static const struct bcm2835_clock_data bcm2835_clock_sdram_data = {
-	.name = "sdram",
-	.num_mux_parents = ARRAY_SIZE(bcm2835_clock_vpu_parents),
-	.parents = bcm2835_clock_vpu_parents,
-	.ctl_reg = CM_SDCCTL,
-	.div_reg = CM_SDCDIV,
-	.int_bits = 6,
-	.frac_bits = 0,
-};
-
-/* Clock for the temperature sensor.  Generally run at 2Mhz, max 5Mhz. */
-static const struct bcm2835_clock_data bcm2835_clock_tsens_data = {
-	.name = "tsens",
-	.num_mux_parents = ARRAY_SIZE(bcm2835_clock_osc_parents),
-	.parents = bcm2835_clock_osc_parents,
-	.ctl_reg = CM_TSENSCTL,
-	.div_reg = CM_TSENSDIV,
-	.int_bits = 5,
-	.frac_bits = 0,
-};
-
-/* Arasan EMMC clock */
-static const struct bcm2835_clock_data bcm2835_clock_emmc_data = {
-	.name = "emmc",
-	.num_mux_parents = ARRAY_SIZE(bcm2835_clock_per_parents),
-	.parents = bcm2835_clock_per_parents,
-	.ctl_reg = CM_EMMCCTL,
-	.div_reg = CM_EMMCDIV,
-	.int_bits = 4,
-	.frac_bits = 8,
-};
+struct bcm2835_gate_data {
+	const char *name;
+	const char *parent;
 
-static const struct bcm2835_clock_data bcm2835_clock_pwm_data = {
-	.name = "pwm",
-	.num_mux_parents = ARRAY_SIZE(bcm2835_clock_per_parents),
-	.parents = bcm2835_clock_per_parents,
-	.ctl_reg = CM_PWMCTL,
-	.div_reg = CM_PWMDIV,
-	.int_bits = 12,
-	.frac_bits = 12,
+	u32 ctl_reg;
 };
 
 struct bcm2835_pll {
@@ -910,8 +537,14 @@ static void bcm2835_pll_off(struct clk_h
 	struct bcm2835_cprman *cprman = pll->cprman;
 	const struct bcm2835_pll_data *data = pll->data;
 
-	cprman_write(cprman, data->cm_ctrl_reg, CM_PLL_ANARST);
-	cprman_write(cprman, data->a2w_ctrl_reg, A2W_PLL_CTRL_PWRDN);
+	spin_lock(&cprman->regs_lock);
+	cprman_write(cprman, data->cm_ctrl_reg,
+		     cprman_read(cprman, data->cm_ctrl_reg) |
+		     CM_PLL_ANARST);
+	cprman_write(cprman, data->a2w_ctrl_reg,
+		     cprman_read(cprman, data->a2w_ctrl_reg) |
+		     A2W_PLL_CTRL_PWRDN);
+	spin_unlock(&cprman->regs_lock);
 }
 
 static int bcm2835_pll_on(struct clk_hw *hw)
@@ -921,6 +554,10 @@ static int bcm2835_pll_on(struct clk_hw
 	const struct bcm2835_pll_data *data = pll->data;
 	ktime_t timeout;
 
+	cprman_write(cprman, data->a2w_ctrl_reg,
+		     cprman_read(cprman, data->a2w_ctrl_reg) &
+		     ~A2W_PLL_CTRL_PWRDN);
+
 	/* Take the PLL out of reset. */
 	cprman_write(cprman, data->cm_ctrl_reg,
 		     cprman_read(cprman, data->cm_ctrl_reg) & ~CM_PLL_ANARST);
@@ -1030,6 +667,36 @@ static int bcm2835_pll_set_rate(struct c
 	return 0;
 }
 
+static int bcm2835_pll_debug_init(struct clk_hw *hw,
+				  struct dentry *dentry)
+{
+	struct bcm2835_pll *pll = container_of(hw, struct bcm2835_pll, hw);
+	struct bcm2835_cprman *cprman = pll->cprman;
+	const struct bcm2835_pll_data *data = pll->data;
+	struct debugfs_reg32 *regs;
+
+	regs = devm_kzalloc(cprman->dev, 7 * sizeof(*regs), GFP_KERNEL);
+	if (!regs)
+		return -ENOMEM;
+
+	regs[0].name = "cm_ctrl";
+	regs[0].offset = data->cm_ctrl_reg;
+	regs[1].name = "a2w_ctrl";
+	regs[1].offset = data->a2w_ctrl_reg;
+	regs[2].name = "frac";
+	regs[2].offset = data->frac_reg;
+	regs[3].name = "ana0";
+	regs[3].offset = data->ana_reg_base + 0 * 4;
+	regs[4].name = "ana1";
+	regs[4].offset = data->ana_reg_base + 1 * 4;
+	regs[5].name = "ana2";
+	regs[5].offset = data->ana_reg_base + 2 * 4;
+	regs[6].name = "ana3";
+	regs[6].offset = data->ana_reg_base + 3 * 4;
+
+	return bcm2835_debugfs_regset(cprman, 0, regs, 7, dentry);
+}
+
 static const struct clk_ops bcm2835_pll_clk_ops = {
 	.is_prepared = bcm2835_pll_is_on,
 	.prepare = bcm2835_pll_on,
@@ -1037,6 +704,7 @@ static const struct clk_ops bcm2835_pll_
 	.recalc_rate = bcm2835_pll_get_rate,
 	.set_rate = bcm2835_pll_set_rate,
 	.round_rate = bcm2835_pll_round_rate,
+	.debug_init = bcm2835_pll_debug_init,
 };
 
 struct bcm2835_pll_divider {
@@ -1079,10 +747,12 @@ static void bcm2835_pll_divider_off(stru
 	struct bcm2835_cprman *cprman = divider->cprman;
 	const struct bcm2835_pll_divider_data *data = divider->data;
 
+	spin_lock(&cprman->regs_lock);
 	cprman_write(cprman, data->cm_reg,
 		     (cprman_read(cprman, data->cm_reg) &
 		      ~data->load_mask) | data->hold_mask);
 	cprman_write(cprman, data->a2w_reg, A2W_PLL_CHANNEL_DISABLE);
+	spin_unlock(&cprman->regs_lock);
 }
 
 static int bcm2835_pll_divider_on(struct clk_hw *hw)
@@ -1091,12 +761,14 @@ static int bcm2835_pll_divider_on(struct
 	struct bcm2835_cprman *cprman = divider->cprman;
 	const struct bcm2835_pll_divider_data *data = divider->data;
 
+	spin_lock(&cprman->regs_lock);
 	cprman_write(cprman, data->a2w_reg,
 		     cprman_read(cprman, data->a2w_reg) &
 		     ~A2W_PLL_CHANNEL_DISABLE);
 
 	cprman_write(cprman, data->cm_reg,
 		     cprman_read(cprman, data->cm_reg) & ~data->hold_mask);
+	spin_unlock(&cprman->regs_lock);
 
 	return 0;
 }
@@ -1124,6 +796,26 @@ static int bcm2835_pll_divider_set_rate(
 	return 0;
 }
 
+static int bcm2835_pll_divider_debug_init(struct clk_hw *hw,
+					  struct dentry *dentry)
+{
+	struct bcm2835_pll_divider *divider = bcm2835_pll_divider_from_hw(hw);
+	struct bcm2835_cprman *cprman = divider->cprman;
+	const struct bcm2835_pll_divider_data *data = divider->data;
+	struct debugfs_reg32 *regs;
+
+	regs = devm_kzalloc(cprman->dev, 7 * sizeof(*regs), GFP_KERNEL);
+	if (!regs)
+		return -ENOMEM;
+
+	regs[0].name = "cm";
+	regs[0].offset = data->cm_reg;
+	regs[1].name = "a2w";
+	regs[1].offset = data->a2w_reg;
+
+	return bcm2835_debugfs_regset(cprman, 0, regs, 2, dentry);
+}
+
 static const struct clk_ops bcm2835_pll_divider_clk_ops = {
 	.is_prepared = bcm2835_pll_divider_is_on,
 	.prepare = bcm2835_pll_divider_on,
@@ -1131,6 +823,7 @@ static const struct clk_ops bcm2835_pll_
 	.recalc_rate = bcm2835_pll_divider_get_rate,
 	.set_rate = bcm2835_pll_divider_set_rate,
 	.round_rate = bcm2835_pll_divider_round_rate,
+	.debug_init = bcm2835_pll_divider_debug_init,
 };
 
 /*
@@ -1170,7 +863,7 @@ static u32 bcm2835_clock_choose_div(stru
 		GENMASK(CM_DIV_FRAC_BITS - data->frac_bits, 0) >> 1;
 	u64 temp = (u64)parent_rate << CM_DIV_FRAC_BITS;
 	u64 rem;
-	u32 div;
+	u32 div, mindiv, maxdiv;
 
 	rem = do_div(temp, rate);
 	div = temp;
@@ -1180,10 +873,23 @@ static u32 bcm2835_clock_choose_div(stru
 		div += unused_frac_mask + 1;
 	div &= ~unused_frac_mask;
 
-	/* Clamp to the limits. */
-	div = max(div, unused_frac_mask + 1);
-	div = min_t(u32, div, GENMASK(data->int_bits + CM_DIV_FRAC_BITS - 1,
-				      CM_DIV_FRAC_BITS - data->frac_bits));
+	/* different clamping limits apply for a mash clock */
+	if (data->is_mash_clock) {
+		/* clamp to min divider of 2 */
+		mindiv = 2 << CM_DIV_FRAC_BITS;
+		/* clamp to the highest possible integer divider */
+		maxdiv = (BIT(data->int_bits) - 1) << CM_DIV_FRAC_BITS;
+	} else {
+		/* clamp to min divider of 1 */
+		mindiv = 1 << CM_DIV_FRAC_BITS;
+		/* clamp to the highest possible fractional divider */
+		maxdiv = GENMASK(data->int_bits + CM_DIV_FRAC_BITS - 1,
+				 CM_DIV_FRAC_BITS - data->frac_bits);
+	}
+
+	/* apply the clamping  limits */
+	div = max_t(u32, div, mindiv);
+	div = min_t(u32, div, maxdiv);
 
 	return div;
 }
@@ -1277,14 +983,31 @@ static int bcm2835_clock_set_rate(struct
 	struct bcm2835_cprman *cprman = clock->cprman;
 	const struct bcm2835_clock_data *data = clock->data;
 	u32 div = bcm2835_clock_choose_div(hw, rate, parent_rate, false);
+	u32 ctl;
+
+	spin_lock(&cprman->regs_lock);
+
+	/*
+	 * Setting up frac support
+	 *
+	 * In principle it is recommended to stop/start the clock first,
+	 * but as we set CLK_SET_RATE_GATE during registration of the
+	 * clock this requirement should be take care of by the
+	 * clk-framework.
+	 */
+	ctl = cprman_read(cprman, data->ctl_reg) & ~CM_FRAC;
+	ctl |= (div & CM_DIV_FRAC_MASK) ? CM_FRAC : 0;
+	cprman_write(cprman, data->ctl_reg, ctl);
 
 	cprman_write(cprman, data->div_reg, div);
 
+	spin_unlock(&cprman->regs_lock);
+
 	return 0;
 }
 
 static int bcm2835_clock_determine_rate(struct clk_hw *hw,
-		struct clk_rate_request *req)
+					struct clk_rate_request *req)
 {
 	struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
 	struct clk_hw *parent, *best_parent = NULL;
@@ -1342,6 +1065,30 @@ static u8 bcm2835_clock_get_parent(struc
 	return (src & CM_SRC_MASK) >> CM_SRC_SHIFT;
 }
 
+static struct debugfs_reg32 bcm2835_debugfs_clock_reg32[] = {
+	{
+		.name = "ctl",
+		.offset = 0,
+	},
+	{
+		.name = "div",
+		.offset = 4,
+	},
+};
+
+static int bcm2835_clock_debug_init(struct clk_hw *hw,
+				    struct dentry *dentry)
+{
+	struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
+	struct bcm2835_cprman *cprman = clock->cprman;
+	const struct bcm2835_clock_data *data = clock->data;
+
+	return bcm2835_debugfs_regset(
+		cprman, data->ctl_reg,
+		bcm2835_debugfs_clock_reg32,
+		ARRAY_SIZE(bcm2835_debugfs_clock_reg32),
+		dentry);
+}
 
 static const struct clk_ops bcm2835_clock_clk_ops = {
 	.is_prepared = bcm2835_clock_is_on,
@@ -1352,6 +1099,7 @@ static const struct clk_ops bcm2835_cloc
 	.determine_rate = bcm2835_clock_determine_rate,
 	.set_parent = bcm2835_clock_set_parent,
 	.get_parent = bcm2835_clock_get_parent,
+	.debug_init = bcm2835_clock_debug_init,
 };
 
 static int bcm2835_vpu_clock_is_on(struct clk_hw *hw)
@@ -1370,6 +1118,7 @@ static const struct clk_ops bcm2835_vpu_
 	.determine_rate = bcm2835_clock_determine_rate,
 	.set_parent = bcm2835_clock_set_parent,
 	.get_parent = bcm2835_clock_get_parent,
+	.debug_init = bcm2835_clock_debug_init,
 };
 
 static struct clk *bcm2835_register_pll(struct bcm2835_cprman *cprman,
@@ -1418,7 +1167,7 @@ bcm2835_register_pll_divider(struct bcm2
 
 	memset(&init, 0, sizeof(init));
 
-	init.parent_names = &data->source_pll->name;
+	init.parent_names = &data->source_pll;
 	init.num_parents = 1;
 	init.name = divider_name;
 	init.ops = &bcm2835_pll_divider_clk_ops;
@@ -1501,14 +1250,559 @@ static struct clk *bcm2835_register_cloc
 	return devm_clk_register(cprman->dev, &clock->hw);
 }
 
+static struct clk *bcm2835_register_gate(struct bcm2835_cprman *cprman,
+					 const struct bcm2835_gate_data *data)
+{
+	return clk_register_gate(cprman->dev, data->name, data->parent,
+				 CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE,
+				 cprman->regs + data->ctl_reg,
+				 CM_GATE_BIT, 0, &cprman->regs_lock);
+}
+
+typedef struct clk *(*bcm2835_clk_register)(struct bcm2835_cprman *cprman,
+					    const void *data);
+struct bcm2835_clk_desc {
+	bcm2835_clk_register clk_register;
+	const void *data;
+};
+
+/* assignment helper macros for different clock types */
+#define _REGISTER(f, ...) { .clk_register = (bcm2835_clk_register)f, \
+			    .data = __VA_ARGS__ }
+#define REGISTER_PLL(...)	_REGISTER(&bcm2835_register_pll,	\
+					  &(struct bcm2835_pll_data)	\
+					  {__VA_ARGS__})
+#define REGISTER_PLL_DIV(...)	_REGISTER(&bcm2835_register_pll_divider, \
+					  &(struct bcm2835_pll_divider_data) \
+					  {__VA_ARGS__})
+#define REGISTER_CLK(...)	_REGISTER(&bcm2835_register_clock,	\
+					  &(struct bcm2835_clock_data)	\
+					  {__VA_ARGS__})
+#define REGISTER_GATE(...)	_REGISTER(&bcm2835_register_gate,	\
+					  &(struct bcm2835_gate_data)	\
+					  {__VA_ARGS__})
+
+/* parent mux arrays plus helper macros */
+
+/* main oscillator parent mux */
+static const char *const bcm2835_clock_osc_parents[] = {
+	"gnd",
+	"xosc",
+	"testdebug0",
+	"testdebug1"
+};
+
+#define REGISTER_OSC_CLK(...)	REGISTER_CLK(				\
+	.num_mux_parents = ARRAY_SIZE(bcm2835_clock_osc_parents),	\
+	.parents = bcm2835_clock_osc_parents,				\
+	__VA_ARGS__)
+
+/* main peripherial parent mux */
+static const char *const bcm2835_clock_per_parents[] = {
+	"gnd",
+	"xosc",
+	"testdebug0",
+	"testdebug1",
+	"plla_per",
+	"pllc_per",
+	"plld_per",
+	"pllh_aux",
+};
+
+#define REGISTER_PER_CLK(...)	REGISTER_CLK(				\
+	.num_mux_parents = ARRAY_SIZE(bcm2835_clock_per_parents),	\
+	.parents = bcm2835_clock_per_parents,				\
+	__VA_ARGS__)
+
+/* main vpu parent mux */
+static const char *const bcm2835_clock_vpu_parents[] = {
+	"gnd",
+	"xosc",
+	"testdebug0",
+	"testdebug1",
+	"plla_core",
+	"pllc_core0",
+	"plld_core",
+	"pllh_aux",
+	"pllc_core1",
+	"pllc_core2",
+};
+
+#define REGISTER_VPU_CLK(...)	REGISTER_CLK(				\
+	.num_mux_parents = ARRAY_SIZE(bcm2835_clock_vpu_parents),	\
+	.parents = bcm2835_clock_vpu_parents,				\
+	__VA_ARGS__)
+
+/*
+ * the real definition of all the pll, pll_dividers and clocks
+ * these make use of the above REGISTER_* macros
+ */
+static const struct bcm2835_clk_desc clk_desc_array[] = {
+	/* the PLL + PLL dividers */
+
+	/*
+	 * PLLA is the auxiliary PLL, used to drive the CCP2
+	 * (Compact Camera Port 2) transmitter clock.
+	 *
+	 * It is in the PX LDO power domain, which is on when the
+	 * AUDIO domain is on.
+	 */
+	[BCM2835_PLLA]		= REGISTER_PLL(
+		.name = "plla",
+		.cm_ctrl_reg = CM_PLLA,
+		.a2w_ctrl_reg = A2W_PLLA_CTRL,
+		.frac_reg = A2W_PLLA_FRAC,
+		.ana_reg_base = A2W_PLLA_ANA0,
+		.reference_enable_mask = A2W_XOSC_CTRL_PLLA_ENABLE,
+		.lock_mask = CM_LOCK_FLOCKA,
+
+		.ana = &bcm2835_ana_default,
+
+		.min_rate = 600000000u,
+		.max_rate = 2400000000u,
+		.max_fb_rate = BCM2835_MAX_FB_RATE),
+	[BCM2835_PLLA_CORE]	= REGISTER_PLL_DIV(
+		.name = "plla_core",
+		.source_pll = "plla",
+		.cm_reg = CM_PLLA,
+		.a2w_reg = A2W_PLLA_CORE,
+		.load_mask = CM_PLLA_LOADCORE,
+		.hold_mask = CM_PLLA_HOLDCORE,
+		.fixed_divider = 1),
+	[BCM2835_PLLA_PER]	= REGISTER_PLL_DIV(
+		.name = "plla_per",
+		.source_pll = "plla",
+		.cm_reg = CM_PLLA,
+		.a2w_reg = A2W_PLLA_PER,
+		.load_mask = CM_PLLA_LOADPER,
+		.hold_mask = CM_PLLA_HOLDPER,
+		.fixed_divider = 1),
+	[BCM2835_PLLA_DSI0]	= REGISTER_PLL_DIV(
+		.name = "plla_dsi0",
+		.source_pll = "plla",
+		.cm_reg = CM_PLLA,
+		.a2w_reg = A2W_PLLA_DSI0,
+		.load_mask = CM_PLLA_LOADDSI0,
+		.hold_mask = CM_PLLA_HOLDDSI0,
+		.fixed_divider = 1),
+	[BCM2835_PLLA_CCP2]	= REGISTER_PLL_DIV(
+		.name = "plla_ccp2",
+		.source_pll = "plla",
+		.cm_reg = CM_PLLA,
+		.a2w_reg = A2W_PLLA_CCP2,
+		.load_mask = CM_PLLA_LOADCCP2,
+		.hold_mask = CM_PLLA_HOLDCCP2,
+		.fixed_divider = 1),
+
+	/* PLLB is used for the ARM's clock. */
+	[BCM2835_PLLB]		= REGISTER_PLL(
+		.name = "pllb",
+		.cm_ctrl_reg = CM_PLLB,
+		.a2w_ctrl_reg = A2W_PLLB_CTRL,
+		.frac_reg = A2W_PLLB_FRAC,
+		.ana_reg_base = A2W_PLLB_ANA0,
+		.reference_enable_mask = A2W_XOSC_CTRL_PLLB_ENABLE,
+		.lock_mask = CM_LOCK_FLOCKB,
+
+		.ana = &bcm2835_ana_default,
+
+		.min_rate = 600000000u,
+		.max_rate = 3000000000u,
+		.max_fb_rate = BCM2835_MAX_FB_RATE),
+	[BCM2835_PLLB_ARM]	= REGISTER_PLL_DIV(
+		.name = "pllb_arm",
+		.source_pll = "pllb",
+		.cm_reg = CM_PLLB,
+		.a2w_reg = A2W_PLLB_ARM,
+		.load_mask = CM_PLLB_LOADARM,
+		.hold_mask = CM_PLLB_HOLDARM,
+		.fixed_divider = 1),
+
+	/*
+	 * PLLC is the core PLL, used to drive the core VPU clock.
+	 *
+	 * It is in the PX LDO power domain, which is on when the
+	 * AUDIO domain is on.
+	 */
+	[BCM2835_PLLC]		= REGISTER_PLL(
+		.name = "pllc",
+		.cm_ctrl_reg = CM_PLLC,
+		.a2w_ctrl_reg = A2W_PLLC_CTRL,
+		.frac_reg = A2W_PLLC_FRAC,
+		.ana_reg_base = A2W_PLLC_ANA0,
+		.reference_enable_mask = A2W_XOSC_CTRL_PLLC_ENABLE,
+		.lock_mask = CM_LOCK_FLOCKC,
+
+		.ana = &bcm2835_ana_default,
+
+		.min_rate = 600000000u,
+		.max_rate = 3000000000u,
+		.max_fb_rate = BCM2835_MAX_FB_RATE),
+	[BCM2835_PLLC_CORE0]	= REGISTER_PLL_DIV(
+		.name = "pllc_core0",
+		.source_pll = "pllc",
+		.cm_reg = CM_PLLC,
+		.a2w_reg = A2W_PLLC_CORE0,
+		.load_mask = CM_PLLC_LOADCORE0,
+		.hold_mask = CM_PLLC_HOLDCORE0,
+		.fixed_divider = 1),
+	[BCM2835_PLLC_CORE1]	= REGISTER_PLL_DIV(
+		.name = "pllc_core1",
+		.source_pll = "pllc",
+		.cm_reg = CM_PLLC,
+		.a2w_reg = A2W_PLLC_CORE1,
+		.load_mask = CM_PLLC_LOADCORE1,
+		.hold_mask = CM_PLLC_HOLDCORE1,
+		.fixed_divider = 1),
+	[BCM2835_PLLC_CORE2]	= REGISTER_PLL_DIV(
+		.name = "pllc_core2",
+		.source_pll = "pllc",
+		.cm_reg = CM_PLLC,
+		.a2w_reg = A2W_PLLC_CORE2,
+		.load_mask = CM_PLLC_LOADCORE2,
+		.hold_mask = CM_PLLC_HOLDCORE2,
+		.fixed_divider = 1),
+	[BCM2835_PLLC_PER]	= REGISTER_PLL_DIV(
+		.name = "pllc_per",
+		.source_pll = "pllc",
+		.cm_reg = CM_PLLC,
+		.a2w_reg = A2W_PLLC_PER,
+		.load_mask = CM_PLLC_LOADPER,
+		.hold_mask = CM_PLLC_HOLDPER,
+		.fixed_divider = 1),
+
+	/*
+	 * PLLD is the display PLL, used to drive DSI display panels.
+	 *
+	 * It is in the PX LDO power domain, which is on when the
+	 * AUDIO domain is on.
+	 */
+	[BCM2835_PLLD]		= REGISTER_PLL(
+		.name = "plld",
+		.cm_ctrl_reg = CM_PLLD,
+		.a2w_ctrl_reg = A2W_PLLD_CTRL,
+		.frac_reg = A2W_PLLD_FRAC,
+		.ana_reg_base = A2W_PLLD_ANA0,
+		.reference_enable_mask = A2W_XOSC_CTRL_DDR_ENABLE,
+		.lock_mask = CM_LOCK_FLOCKD,
+
+		.ana = &bcm2835_ana_default,
+
+		.min_rate = 600000000u,
+		.max_rate = 2400000000u,
+		.max_fb_rate = BCM2835_MAX_FB_RATE),
+	[BCM2835_PLLD_CORE]	= REGISTER_PLL_DIV(
+		.name = "plld_core",
+		.source_pll = "plld",
+		.cm_reg = CM_PLLD,
+		.a2w_reg = A2W_PLLD_CORE,
+		.load_mask = CM_PLLD_LOADCORE,
+		.hold_mask = CM_PLLD_HOLDCORE,
+		.fixed_divider = 1),
+	[BCM2835_PLLD_PER]	= REGISTER_PLL_DIV(
+		.name = "plld_per",
+		.source_pll = "plld",
+		.cm_reg = CM_PLLD,
+		.a2w_reg = A2W_PLLD_PER,
+		.load_mask = CM_PLLD_LOADPER,
+		.hold_mask = CM_PLLD_HOLDPER,
+		.fixed_divider = 1),
+	[BCM2835_PLLD_DSI0]	= REGISTER_PLL_DIV(
+		.name = "plld_dsi0",
+		.source_pll = "plld",
+		.cm_reg = CM_PLLD,
+		.a2w_reg = A2W_PLLD_DSI0,
+		.load_mask = CM_PLLD_LOADDSI0,
+		.hold_mask = CM_PLLD_HOLDDSI0,
+		.fixed_divider = 1),
+	[BCM2835_PLLD_DSI1]	= REGISTER_PLL_DIV(
+		.name = "plld_dsi1",
+		.source_pll = "plld",
+		.cm_reg = CM_PLLD,
+		.a2w_reg = A2W_PLLD_DSI1,
+		.load_mask = CM_PLLD_LOADDSI1,
+		.hold_mask = CM_PLLD_HOLDDSI1,
+		.fixed_divider = 1),
+
+	/*
+	 * PLLH is used to supply the pixel clock or the AUX clock for the
+	 * TV encoder.
+	 *
+	 * It is in the HDMI power domain.
+	 */
+	[BCM2835_PLLH]		= REGISTER_PLL(
+		"pllh",
+		.cm_ctrl_reg = CM_PLLH,
+		.a2w_ctrl_reg = A2W_PLLH_CTRL,
+		.frac_reg = A2W_PLLH_FRAC,
+		.ana_reg_base = A2W_PLLH_ANA0,
+		.reference_enable_mask = A2W_XOSC_CTRL_PLLC_ENABLE,
+		.lock_mask = CM_LOCK_FLOCKH,
+
+		.ana = &bcm2835_ana_pllh,
+
+		.min_rate = 600000000u,
+		.max_rate = 3000000000u,
+		.max_fb_rate = BCM2835_MAX_FB_RATE),
+	[BCM2835_PLLH_RCAL]	= REGISTER_PLL_DIV(
+		.name = "pllh_rcal",
+		.source_pll = "pllh",
+		.cm_reg = CM_PLLH,
+		.a2w_reg = A2W_PLLH_RCAL,
+		.load_mask = CM_PLLH_LOADRCAL,
+		.hold_mask = 0,
+		.fixed_divider = 10),
+	[BCM2835_PLLH_AUX]	= REGISTER_PLL_DIV(
+		.name = "pllh_aux",
+		.source_pll = "pllh",
+		.cm_reg = CM_PLLH,
+		.a2w_reg = A2W_PLLH_AUX,
+		.load_mask = CM_PLLH_LOADAUX,
+		.hold_mask = 0,
+		.fixed_divider = 10),
+	[BCM2835_PLLH_PIX]	= REGISTER_PLL_DIV(
+		.name = "pllh_pix",
+		.source_pll = "pllh",
+		.cm_reg = CM_PLLH,
+		.a2w_reg = A2W_PLLH_PIX,
+		.load_mask = CM_PLLH_LOADPIX,
+		.hold_mask = 0,
+		.fixed_divider = 10),
+
+	/* the clocks */
+
+	/* clocks with oscillator parent mux */
+
+	/* One Time Programmable Memory clock.  Maximum 10Mhz. */
+	[BCM2835_CLOCK_OTP]	= REGISTER_OSC_CLK(
+		.name = "otp",
+		.ctl_reg = CM_OTPCTL,
+		.div_reg = CM_OTPDIV,
+		.int_bits = 4,
+		.frac_bits = 0),
+	/*
+	 * Used for a 1Mhz clock for the system clocksource, and also used
+	 * bythe watchdog timer and the camera pulse generator.
+	 */
+	[BCM2835_CLOCK_TIMER]	= REGISTER_OSC_CLK(
+		.name = "timer",
+		.ctl_reg = CM_TIMERCTL,
+		.div_reg = CM_TIMERDIV,
+		.int_bits = 6,
+		.frac_bits = 12),
+	/*
+	 * Clock for the temperature sensor.
+	 * Generally run at 2Mhz, max 5Mhz.
+	 */
+	[BCM2835_CLOCK_TSENS]	= REGISTER_OSC_CLK(
+		.name = "tsens",
+		.ctl_reg = CM_TSENSCTL,
+		.div_reg = CM_TSENSDIV,
+		.int_bits = 5,
+		.frac_bits = 0),
+	[BCM2835_CLOCK_TEC]	= REGISTER_OSC_CLK(
+		.name = "tec",
+		.ctl_reg = CM_TECCTL,
+		.div_reg = CM_TECDIV,
+		.int_bits = 6,
+		.frac_bits = 0),
+
+	/* clocks with vpu parent mux */
+	[BCM2835_CLOCK_H264]	= REGISTER_VPU_CLK(
+		.name = "h264",
+		.ctl_reg = CM_H264CTL,
+		.div_reg = CM_H264DIV,
+		.int_bits = 4,
+		.frac_bits = 8),
+	[BCM2835_CLOCK_ISP]	= REGISTER_VPU_CLK(
+		.name = "isp",
+		.ctl_reg = CM_ISPCTL,
+		.div_reg = CM_ISPDIV,
+		.int_bits = 4,
+		.frac_bits = 8),
+
+	/*
+	 * Secondary SDRAM clock.  Used for low-voltage modes when the PLL
+	 * in the SDRAM controller can't be used.
+	 */
+	[BCM2835_CLOCK_SDRAM]	= REGISTER_VPU_CLK(
+		.name = "sdram",
+		.ctl_reg = CM_SDCCTL,
+		.div_reg = CM_SDCDIV,
+		.int_bits = 6,
+		.frac_bits = 0),
+	[BCM2835_CLOCK_V3D]	= REGISTER_VPU_CLK(
+		.name = "v3d",
+		.ctl_reg = CM_V3DCTL,
+		.div_reg = CM_V3DDIV,
+		.int_bits = 4,
+		.frac_bits = 8),
+	/*
+	 * VPU clock.  This doesn't have an enable bit, since it drives
+	 * the bus for everything else, and is special so it doesn't need
+	 * to be gated for rate changes.  It is also known as "clk_audio"
+	 * in various hardware documentation.
+	 */
+	[BCM2835_CLOCK_VPU]	= REGISTER_VPU_CLK(
+		.name = "vpu",
+		.ctl_reg = CM_VPUCTL,
+		.div_reg = CM_VPUDIV,
+		.int_bits = 12,
+		.frac_bits = 8,
+		.is_vpu_clock = true),
+
+	/* clocks with per parent mux */
+	[BCM2835_CLOCK_AVEO]	= REGISTER_PER_CLK(
+		.name = "aveo",
+		.ctl_reg = CM_AVEOCTL,
+		.div_reg = CM_AVEODIV,
+		.int_bits = 4,
+		.frac_bits = 0),
+	[BCM2835_CLOCK_CAM0]	= REGISTER_PER_CLK(
+		.name = "cam0",
+		.ctl_reg = CM_CAM0CTL,
+		.div_reg = CM_CAM0DIV,
+		.int_bits = 4,
+		.frac_bits = 8),
+	[BCM2835_CLOCK_CAM1]	= REGISTER_PER_CLK(
+		.name = "cam1",
+		.ctl_reg = CM_CAM1CTL,
+		.div_reg = CM_CAM1DIV,
+		.int_bits = 4,
+		.frac_bits = 8),
+	[BCM2835_CLOCK_DFT]	= REGISTER_PER_CLK(
+		.name = "dft",
+		.ctl_reg = CM_DFTCTL,
+		.div_reg = CM_DFTDIV,
+		.int_bits = 5,
+		.frac_bits = 0),
+	[BCM2835_CLOCK_DPI]	= REGISTER_PER_CLK(
+		.name = "dpi",
+		.ctl_reg = CM_DPICTL,
+		.div_reg = CM_DPIDIV,
+		.int_bits = 4,
+		.frac_bits = 8),
+
+	/* Arasan EMMC clock */
+	[BCM2835_CLOCK_EMMC]	= REGISTER_PER_CLK(
+		.name = "emmc",
+		.ctl_reg = CM_EMMCCTL,
+		.div_reg = CM_EMMCDIV,
+		.int_bits = 4,
+		.frac_bits = 8),
+
+	/* General purpose (GPIO) clocks */
+	[BCM2835_CLOCK_GP0]	= REGISTER_PER_CLK(
+		.name = "gp0",
+		.ctl_reg = CM_GP0CTL,
+		.div_reg = CM_GP0DIV,
+		.int_bits = 12,
+		.frac_bits = 12,
+		.is_mash_clock = true),
+	[BCM2835_CLOCK_GP1]	= REGISTER_PER_CLK(
+		.name = "gp1",
+		.ctl_reg = CM_GP1CTL,
+		.div_reg = CM_GP1DIV,
+		.int_bits = 12,
+		.frac_bits = 12,
+		.is_mash_clock = true),
+	[BCM2835_CLOCK_GP2]	= REGISTER_PER_CLK(
+		.name = "gp2",
+		.ctl_reg = CM_GP2CTL,
+		.div_reg = CM_GP2DIV,
+		.int_bits = 12,
+		.frac_bits = 12),
+
+	/* HDMI state machine */
+	[BCM2835_CLOCK_HSM]	= REGISTER_PER_CLK(
+		.name = "hsm",
+		.ctl_reg = CM_HSMCTL,
+		.div_reg = CM_HSMDIV,
+		.int_bits = 4,
+		.frac_bits = 8),
+	[BCM2835_CLOCK_PCM]	= REGISTER_PER_CLK(
+		.name = "pcm",
+		.ctl_reg = CM_PCMCTL,
+		.div_reg = CM_PCMDIV,
+		.int_bits = 12,
+		.frac_bits = 12,
+		.is_mash_clock = true),
+	[BCM2835_CLOCK_PWM]	= REGISTER_PER_CLK(
+		.name = "pwm",
+		.ctl_reg = CM_PWMCTL,
+		.div_reg = CM_PWMDIV,
+		.int_bits = 12,
+		.frac_bits = 12,
+		.is_mash_clock = true),
+	[BCM2835_CLOCK_SLIM]	= REGISTER_PER_CLK(
+		.name = "slim",
+		.ctl_reg = CM_SLIMCTL,
+		.div_reg = CM_SLIMDIV,
+		.int_bits = 12,
+		.frac_bits = 12,
+		.is_mash_clock = true),
+	[BCM2835_CLOCK_SMI]	= REGISTER_PER_CLK(
+		.name = "smi",
+		.ctl_reg = CM_SMICTL,
+		.div_reg = CM_SMIDIV,
+		.int_bits = 4,
+		.frac_bits = 8),
+	[BCM2835_CLOCK_UART]	= REGISTER_PER_CLK(
+		.name = "uart",
+		.ctl_reg = CM_UARTCTL,
+		.div_reg = CM_UARTDIV,
+		.int_bits = 10,
+		.frac_bits = 12),
+
+	/* TV encoder clock.  Only operating frequency is 108Mhz.  */
+	[BCM2835_CLOCK_VEC]	= REGISTER_PER_CLK(
+		.name = "vec",
+		.ctl_reg = CM_VECCTL,
+		.div_reg = CM_VECDIV,
+		.int_bits = 4,
+		.frac_bits = 0),
+
+	/* dsi clocks */
+	[BCM2835_CLOCK_DSI0E]	= REGISTER_PER_CLK(
+		.name = "dsi0e",
+		.ctl_reg = CM_DSI0ECTL,
+		.div_reg = CM_DSI0EDIV,
+		.int_bits = 4,
+		.frac_bits = 8),
+	[BCM2835_CLOCK_DSI1E]	= REGISTER_PER_CLK(
+		.name = "dsi1e",
+		.ctl_reg = CM_DSI1ECTL,
+		.div_reg = CM_DSI1EDIV,
+		.int_bits = 4,
+		.frac_bits = 8),
+
+	/* the gates */
+
+	/*
+	 * CM_PERIICTL (and CM_PERIACTL, CM_SYSCTL and CM_VPUCTL if
+	 * you have the debug bit set in the power manager, which we
+	 * don't bother exposing) are individual gates off of the
+	 * non-stop vpu clock.
+	 */
+	[BCM2835_CLOCK_PERI_IMAGE] = REGISTER_GATE(
+		.name = "peri_image",
+		.parent = "vpu",
+		.ctl_reg = CM_PERIICTL),
+};
+
 static int bcm2835_clk_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct clk **clks;
 	struct bcm2835_cprman *cprman;
 	struct resource *res;
+	const struct bcm2835_clk_desc *desc;
+	const size_t asize = ARRAY_SIZE(clk_desc_array);
+	size_t i;
 
-	cprman = devm_kzalloc(dev, sizeof(*cprman), GFP_KERNEL);
+	cprman = devm_kzalloc(dev,
+			      sizeof(*cprman) + asize * sizeof(*clks),
+			      GFP_KERNEL);
 	if (!cprman)
 		return -ENOMEM;
 
@@ -1525,80 +1819,15 @@ static int bcm2835_clk_probe(struct plat
 
 	platform_set_drvdata(pdev, cprman);
 
-	cprman->onecell.clk_num = BCM2835_CLOCK_COUNT;
+	cprman->onecell.clk_num = asize;
 	cprman->onecell.clks = cprman->clks;
 	clks = cprman->clks;
 
-	clks[BCM2835_PLLA] = bcm2835_register_pll(cprman, &bcm2835_plla_data);
-	clks[BCM2835_PLLB] = bcm2835_register_pll(cprman, &bcm2835_pllb_data);
-	clks[BCM2835_PLLC] = bcm2835_register_pll(cprman, &bcm2835_pllc_data);
-	clks[BCM2835_PLLD] = bcm2835_register_pll(cprman, &bcm2835_plld_data);
-	clks[BCM2835_PLLH] = bcm2835_register_pll(cprman, &bcm2835_pllh_data);
-
-	clks[BCM2835_PLLA_CORE] =
-		bcm2835_register_pll_divider(cprman, &bcm2835_plla_core_data);
-	clks[BCM2835_PLLA_PER] =
-		bcm2835_register_pll_divider(cprman, &bcm2835_plla_per_data);
-	clks[BCM2835_PLLC_CORE0] =
-		bcm2835_register_pll_divider(cprman, &bcm2835_pllc_core0_data);
-	clks[BCM2835_PLLC_CORE1] =
-		bcm2835_register_pll_divider(cprman, &bcm2835_pllc_core1_data);
-	clks[BCM2835_PLLC_CORE2] =
-		bcm2835_register_pll_divider(cprman, &bcm2835_pllc_core2_data);
-	clks[BCM2835_PLLC_PER] =
-		bcm2835_register_pll_divider(cprman, &bcm2835_pllc_per_data);
-	clks[BCM2835_PLLD_CORE] =
-		bcm2835_register_pll_divider(cprman, &bcm2835_plld_core_data);
-	clks[BCM2835_PLLD_PER] =
-		bcm2835_register_pll_divider(cprman, &bcm2835_plld_per_data);
-	clks[BCM2835_PLLH_RCAL] =
-		bcm2835_register_pll_divider(cprman, &bcm2835_pllh_rcal_data);
-	clks[BCM2835_PLLH_AUX] =
-		bcm2835_register_pll_divider(cprman, &bcm2835_pllh_aux_data);
-	clks[BCM2835_PLLH_PIX] =
-		bcm2835_register_pll_divider(cprman, &bcm2835_pllh_pix_data);
-
-	clks[BCM2835_CLOCK_TIMER] =
-		bcm2835_register_clock(cprman, &bcm2835_clock_timer_data);
-	clks[BCM2835_CLOCK_OTP] =
-		bcm2835_register_clock(cprman, &bcm2835_clock_otp_data);
-	clks[BCM2835_CLOCK_TSENS] =
-		bcm2835_register_clock(cprman, &bcm2835_clock_tsens_data);
-	clks[BCM2835_CLOCK_VPU] =
-		bcm2835_register_clock(cprman, &bcm2835_clock_vpu_data);
-	clks[BCM2835_CLOCK_V3D] =
-		bcm2835_register_clock(cprman, &bcm2835_clock_v3d_data);
-	clks[BCM2835_CLOCK_ISP] =
-		bcm2835_register_clock(cprman, &bcm2835_clock_isp_data);
-	clks[BCM2835_CLOCK_H264] =
-		bcm2835_register_clock(cprman, &bcm2835_clock_h264_data);
-	clks[BCM2835_CLOCK_V3D] =
-		bcm2835_register_clock(cprman, &bcm2835_clock_v3d_data);
-	clks[BCM2835_CLOCK_SDRAM] =
-		bcm2835_register_clock(cprman, &bcm2835_clock_sdram_data);
-	clks[BCM2835_CLOCK_UART] =
-		bcm2835_register_clock(cprman, &bcm2835_clock_uart_data);
-	clks[BCM2835_CLOCK_VEC] =
-		bcm2835_register_clock(cprman, &bcm2835_clock_vec_data);
-	clks[BCM2835_CLOCK_HSM] =
-		bcm2835_register_clock(cprman, &bcm2835_clock_hsm_data);
-	clks[BCM2835_CLOCK_EMMC] =
-		bcm2835_register_clock(cprman, &bcm2835_clock_emmc_data);
-
-	/*
-	 * CM_PERIICTL (and CM_PERIACTL, CM_SYSCTL and CM_VPUCTL if
-	 * you have the debug bit set in the power manager, which we
-	 * don't bother exposing) are individual gates off of the
-	 * non-stop vpu clock.
-	 */
-	clks[BCM2835_CLOCK_PERI_IMAGE] =
-		clk_register_gate(dev, "peri_image", "vpu",
-				  CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE,
-				  cprman->regs + CM_PERIICTL, CM_GATE_BIT,
-				  0, &cprman->regs_lock);
-
-	clks[BCM2835_CLOCK_PWM] =
-		bcm2835_register_clock(cprman, &bcm2835_clock_pwm_data);
+	for (i = 0; i < asize; i++) {
+		desc = &clk_desc_array[i];
+		if (desc->clk_register && desc->data)
+			clks[i] = desc->clk_register(cprman, desc->data);
+	}
 
 	return of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
 				   &cprman->onecell);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/bcm/clk-kona-setup.c linux-libre-4.7-gnu/drivers/clk/bcm/clk-kona-setup.c
--- linux-libre-4.6-gnu/drivers/clk/bcm/clk-kona-setup.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/bcm/clk-kona-setup.c	2016-07-24 15:23:50.000000000 -0400
@@ -577,7 +577,8 @@ static u32 *parent_process(const char *c
 	 * selector is not required, but we allocate space for the
 	 * array anyway to keep things simple.
 	 */
-	parent_names = kmalloc(parent_count * sizeof(parent_names), GFP_KERNEL);
+	parent_names = kmalloc_array(parent_count, sizeof(*parent_names),
+			       GFP_KERNEL);
 	if (!parent_names) {
 		pr_err("%s: error allocating %u parent names\n", __func__,
 				parent_count);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/clk.c linux-libre-4.7-gnu/drivers/clk/clk.c
--- linux-libre-4.6-gnu/drivers/clk/clk.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/clk.c	2016-07-24 15:23:50.000000000 -0400
@@ -574,6 +574,9 @@ static void clk_core_unprepare(struct cl
 	if (WARN_ON(core->prepare_count == 0))
 		return;
 
+	if (WARN_ON(core->prepare_count == 1 && core->flags & CLK_IS_CRITICAL))
+		return;
+
 	if (--core->prepare_count > 0)
 		return;
 
@@ -679,6 +682,9 @@ static void clk_core_disable(struct clk_
 	if (WARN_ON(core->enable_count == 0))
 		return;
 
+	if (WARN_ON(core->enable_count == 1 && core->flags & CLK_IS_CRITICAL))
+		return;
+
 	if (--core->enable_count > 0)
 		return;
 
@@ -2397,6 +2403,16 @@ static int __clk_core_init(struct clk_co
 	if (core->ops->init)
 		core->ops->init(core->hw);
 
+	if (core->flags & CLK_IS_CRITICAL) {
+		unsigned long flags;
+
+		clk_core_prepare(core);
+
+		flags = clk_enable_lock();
+		clk_core_enable(core);
+		clk_enable_unlock(flags);
+	}
+
 	kref_init(&core->ref);
 out:
 	clk_prepare_unlock();
@@ -2536,6 +2552,22 @@ fail_out:
 }
 EXPORT_SYMBOL_GPL(clk_register);
 
+/**
+ * clk_hw_register - register a clk_hw and return an error code
+ * @dev: device that is registering this clock
+ * @hw: link to hardware-specific clock data
+ *
+ * clk_hw_register is the primary interface for populating the clock tree with
+ * new clock nodes. It returns an integer equal to zero indicating success or
+ * less than zero indicating failure. Drivers must test for an error code after
+ * calling clk_hw_register().
+ */
+int clk_hw_register(struct device *dev, struct clk_hw *hw)
+{
+	return PTR_ERR_OR_ZERO(clk_register(dev, hw));
+}
+EXPORT_SYMBOL_GPL(clk_hw_register);
+
 /* Free memory allocated for a clock. */
 static void __clk_release(struct kref *ref)
 {
@@ -2637,11 +2669,26 @@ unlock:
 }
 EXPORT_SYMBOL_GPL(clk_unregister);
 
+/**
+ * clk_hw_unregister - unregister a currently registered clk_hw
+ * @hw: hardware-specific clock data to unregister
+ */
+void clk_hw_unregister(struct clk_hw *hw)
+{
+	clk_unregister(hw->clk);
+}
+EXPORT_SYMBOL_GPL(clk_hw_unregister);
+
 static void devm_clk_release(struct device *dev, void *res)
 {
 	clk_unregister(*(struct clk **)res);
 }
 
+static void devm_clk_hw_release(struct device *dev, void *res)
+{
+	clk_hw_unregister(*(struct clk_hw **)res);
+}
+
 /**
  * devm_clk_register - resource managed clk_register()
  * @dev: device that is registering this clock
@@ -2672,6 +2719,36 @@ struct clk *devm_clk_register(struct dev
 }
 EXPORT_SYMBOL_GPL(devm_clk_register);
 
+/**
+ * devm_clk_hw_register - resource managed clk_hw_register()
+ * @dev: device that is registering this clock
+ * @hw: link to hardware-specific clock data
+ *
+ * Managed clk_hw_register(). Clocks registered by this function are
+ * automatically clk_hw_unregister()ed on driver detach. See clk_hw_register()
+ * for more information.
+ */
+int devm_clk_hw_register(struct device *dev, struct clk_hw *hw)
+{
+	struct clk_hw **hwp;
+	int ret;
+
+	hwp = devres_alloc(devm_clk_hw_release, sizeof(*hwp), GFP_KERNEL);
+	if (!hwp)
+		return -ENOMEM;
+
+	ret = clk_hw_register(dev, hw);
+	if (!ret) {
+		*hwp = hw;
+		devres_add(dev, hwp);
+	} else {
+		devres_free(hwp);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(devm_clk_hw_register);
+
 static int devm_clk_match(struct device *dev, void *res, void *data)
 {
 	struct clk *c = res;
@@ -2680,6 +2757,15 @@ static int devm_clk_match(struct device
 	return c == data;
 }
 
+static int devm_clk_hw_match(struct device *dev, void *res, void *data)
+{
+	struct clk_hw *hw = res;
+
+	if (WARN_ON(!hw))
+		return 0;
+	return hw == data;
+}
+
 /**
  * devm_clk_unregister - resource managed clk_unregister()
  * @clk: clock to unregister
@@ -2694,6 +2780,22 @@ void devm_clk_unregister(struct device *
 }
 EXPORT_SYMBOL_GPL(devm_clk_unregister);
 
+/**
+ * devm_clk_hw_unregister - resource managed clk_hw_unregister()
+ * @dev: device that is unregistering the hardware-specific clock data
+ * @hw: link to hardware-specific clock data
+ *
+ * Unregister a clk_hw registered with devm_clk_hw_register(). Normally
+ * this function will not need to be called and the resource management
+ * code will ensure that the resource is freed.
+ */
+void devm_clk_hw_unregister(struct device *dev, struct clk_hw *hw)
+{
+	WARN_ON(devres_release(dev, devm_clk_hw_release, devm_clk_hw_match,
+				hw));
+}
+EXPORT_SYMBOL_GPL(devm_clk_hw_unregister);
+
 /*
  * clkdev helpers
  */
@@ -2855,6 +2957,7 @@ struct of_clk_provider {
 
 	struct device_node *node;
 	struct clk *(*get)(struct of_phandle_args *clkspec, void *data);
+	struct clk_hw *(*get_hw)(struct of_phandle_args *clkspec, void *data);
 	void *data;
 };
 
@@ -2871,6 +2974,12 @@ struct clk *of_clk_src_simple_get(struct
 }
 EXPORT_SYMBOL_GPL(of_clk_src_simple_get);
 
+struct clk_hw *of_clk_hw_simple_get(struct of_phandle_args *clkspec, void *data)
+{
+	return data;
+}
+EXPORT_SYMBOL_GPL(of_clk_hw_simple_get);
+
 struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data)
 {
 	struct clk_onecell_data *clk_data = data;
@@ -2885,6 +2994,21 @@ struct clk *of_clk_src_onecell_get(struc
 }
 EXPORT_SYMBOL_GPL(of_clk_src_onecell_get);
 
+struct clk_hw *
+of_clk_hw_onecell_get(struct of_phandle_args *clkspec, void *data)
+{
+	struct clk_hw_onecell_data *hw_data = data;
+	unsigned int idx = clkspec->args[0];
+
+	if (idx >= hw_data->num) {
+		pr_err("%s: invalid index %u\n", __func__, idx);
+		return ERR_PTR(-EINVAL);
+	}
+
+	return hw_data->hws[idx];
+}
+EXPORT_SYMBOL_GPL(of_clk_hw_onecell_get);
+
 /**
  * of_clk_add_provider() - Register a clock provider for a node
  * @np: Device node pointer associated with clock provider
@@ -2921,6 +3045,41 @@ int of_clk_add_provider(struct device_no
 EXPORT_SYMBOL_GPL(of_clk_add_provider);
 
 /**
+ * of_clk_add_hw_provider() - Register a clock provider for a node
+ * @np: Device node pointer associated with clock provider
+ * @get: callback for decoding clk_hw
+ * @data: context pointer for @get callback.
+ */
+int of_clk_add_hw_provider(struct device_node *np,
+			   struct clk_hw *(*get)(struct of_phandle_args *clkspec,
+						 void *data),
+			   void *data)
+{
+	struct of_clk_provider *cp;
+	int ret;
+
+	cp = kzalloc(sizeof(*cp), GFP_KERNEL);
+	if (!cp)
+		return -ENOMEM;
+
+	cp->node = of_node_get(np);
+	cp->data = data;
+	cp->get_hw = get;
+
+	mutex_lock(&of_clk_mutex);
+	list_add(&cp->link, &of_clk_providers);
+	mutex_unlock(&of_clk_mutex);
+	pr_debug("Added clk_hw provider from %s\n", np->full_name);
+
+	ret = of_clk_set_defaults(np, true);
+	if (ret < 0)
+		of_clk_del_provider(np);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(of_clk_add_hw_provider);
+
+/**
  * of_clk_del_provider() - Remove a previously registered clock provider
  * @np: Device node pointer associated with clock provider
  */
@@ -2941,11 +3100,32 @@ void of_clk_del_provider(struct device_n
 }
 EXPORT_SYMBOL_GPL(of_clk_del_provider);
 
+static struct clk_hw *
+__of_clk_get_hw_from_provider(struct of_clk_provider *provider,
+			      struct of_phandle_args *clkspec)
+{
+	struct clk *clk;
+	struct clk_hw *hw = ERR_PTR(-EPROBE_DEFER);
+
+	if (provider->get_hw) {
+		hw = provider->get_hw(clkspec, provider->data);
+	} else if (provider->get) {
+		clk = provider->get(clkspec, provider->data);
+		if (!IS_ERR(clk))
+			hw = __clk_get_hw(clk);
+		else
+			hw = ERR_CAST(clk);
+	}
+
+	return hw;
+}
+
 struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec,
 				       const char *dev_id, const char *con_id)
 {
 	struct of_clk_provider *provider;
 	struct clk *clk = ERR_PTR(-EPROBE_DEFER);
+	struct clk_hw *hw = ERR_PTR(-EPROBE_DEFER);
 
 	if (!clkspec)
 		return ERR_PTR(-EINVAL);
@@ -2954,10 +3134,9 @@ struct clk *__of_clk_get_from_provider(s
 	mutex_lock(&of_clk_mutex);
 	list_for_each_entry(provider, &of_clk_providers, link) {
 		if (provider->node == clkspec->np)
-			clk = provider->get(clkspec, provider->data);
-		if (!IS_ERR(clk)) {
-			clk = __clk_create_clk(__clk_get_hw(clk), dev_id,
-					       con_id);
+			hw = __of_clk_get_hw_from_provider(provider, clkspec);
+		if (!IS_ERR(hw)) {
+			clk = __clk_create_clk(hw, dev_id, con_id);
 
 			if (!IS_ERR(clk) && !__clk_get(clk)) {
 				__clk_free_clk(clk);
@@ -3127,6 +3306,41 @@ static int parent_ready(struct device_no
 }
 
 /**
+ * of_clk_detect_critical() - set CLK_IS_CRITICAL flag from Device Tree
+ * @np: Device node pointer associated with clock provider
+ * @index: clock index
+ * @flags: pointer to clk_core->flags
+ *
+ * Detects if the clock-critical property exists and, if so, sets the
+ * corresponding CLK_IS_CRITICAL flag.
+ *
+ * Do not use this function. It exists only for legacy Device Tree
+ * bindings, such as the one-clock-per-node style that are outdated.
+ * Those bindings typically put all clock data into .dts and the Linux
+ * driver has no clock data, thus making it impossible to set this flag
+ * correctly from the driver. Only those drivers may call
+ * of_clk_detect_critical from their setup functions.
+ *
+ * Return: error code or zero on success
+ */
+int of_clk_detect_critical(struct device_node *np,
+					  int index, unsigned long *flags)
+{
+	struct property *prop;
+	const __be32 *cur;
+	uint32_t idx;
+
+	if (!np || !flags)
+		return -EINVAL;
+
+	of_property_for_each_u32(np, "clock-critical", prop, cur, idx)
+		if (index == idx)
+			*flags |= CLK_IS_CRITICAL;
+
+	return 0;
+}
+
+/**
  * of_clk_init() - Scan and init clock providers from the DT
  * @matches: array of compatible values and init functions for providers.
  *
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/clk-clps711x.c linux-libre-4.7-gnu/drivers/clk/clk-clps711x.c
--- linux-libre-4.6-gnu/drivers/clk/clk-clps711x.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/clk-clps711x.c	2016-07-24 15:23:50.000000000 -0400
@@ -107,16 +107,15 @@ static struct clps711x_clk * __init _clp
 	writel(tmp, base + CLPS711X_SYSCON1);
 
 	clps711x_clk->clks[CLPS711X_CLK_DUMMY] =
-		clk_register_fixed_rate(NULL, "dummy", NULL, CLK_IS_ROOT, 0);
+		clk_register_fixed_rate(NULL, "dummy", NULL, 0, 0);
 	clps711x_clk->clks[CLPS711X_CLK_CPU] =
-		clk_register_fixed_rate(NULL, "cpu", NULL, CLK_IS_ROOT, f_cpu);
+		clk_register_fixed_rate(NULL, "cpu", NULL, 0, f_cpu);
 	clps711x_clk->clks[CLPS711X_CLK_BUS] =
-		clk_register_fixed_rate(NULL, "bus", NULL, CLK_IS_ROOT, f_bus);
+		clk_register_fixed_rate(NULL, "bus", NULL, 0, f_bus);
 	clps711x_clk->clks[CLPS711X_CLK_PLL] =
-		clk_register_fixed_rate(NULL, "pll", NULL, CLK_IS_ROOT, f_pll);
+		clk_register_fixed_rate(NULL, "pll", NULL, 0, f_pll);
 	clps711x_clk->clks[CLPS711X_CLK_TIMERREF] =
-		clk_register_fixed_rate(NULL, "timer_ref", NULL, CLK_IS_ROOT,
-					f_tim);
+		clk_register_fixed_rate(NULL, "timer_ref", NULL, 0, f_tim);
 	clps711x_clk->clks[CLPS711X_CLK_TIMER1] =
 		clk_register_divider_table(NULL, "timer1", "timer_ref", 0,
 					   base + CLPS711X_SYSCON1, 5, 1, 0,
@@ -126,10 +125,9 @@ static struct clps711x_clk * __init _clp
 					   base + CLPS711X_SYSCON1, 7, 1, 0,
 					   timer_div_table, &clps711x_clk->lock);
 	clps711x_clk->clks[CLPS711X_CLK_PWM] =
-		clk_register_fixed_rate(NULL, "pwm", NULL, CLK_IS_ROOT, f_pwm);
+		clk_register_fixed_rate(NULL, "pwm", NULL, 0, f_pwm);
 	clps711x_clk->clks[CLPS711X_CLK_SPIREF] =
-		clk_register_fixed_rate(NULL, "spi_ref", NULL, CLK_IS_ROOT,
-					f_spi);
+		clk_register_fixed_rate(NULL, "spi_ref", NULL, 0, f_spi);
 	clps711x_clk->clks[CLPS711X_CLK_SPI] =
 		clk_register_divider_table(NULL, "spi", "spi_ref", 0,
 					   base + CLPS711X_SYSCON1, 16, 2, 0,
@@ -137,8 +135,7 @@ static struct clps711x_clk * __init _clp
 	clps711x_clk->clks[CLPS711X_CLK_UART] =
 		clk_register_fixed_factor(NULL, "uart", "bus", 0, 1, 10);
 	clps711x_clk->clks[CLPS711X_CLK_TICK] =
-		clk_register_fixed_rate(NULL, "tick", NULL, CLK_IS_ROOT, 64);
-
+		clk_register_fixed_rate(NULL, "tick", NULL, 0, 64);
 	for (i = 0; i < CLPS711X_CLK_MAX; i++)
 		if (IS_ERR(clps711x_clk->clks[i]))
 			pr_err("clk %i: register failed with %ld\n",
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/clk-composite.c linux-libre-4.7-gnu/drivers/clk/clk-composite.c
--- linux-libre-4.6-gnu/drivers/clk/clk-composite.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/clk-composite.c	2016-07-24 15:23:50.000000000 -0400
@@ -151,6 +151,33 @@ static int clk_composite_set_rate(struct
 	return rate_ops->set_rate(rate_hw, rate, parent_rate);
 }
 
+static int clk_composite_set_rate_and_parent(struct clk_hw *hw,
+					     unsigned long rate,
+					     unsigned long parent_rate,
+					     u8 index)
+{
+	struct clk_composite *composite = to_clk_composite(hw);
+	const struct clk_ops *rate_ops = composite->rate_ops;
+	const struct clk_ops *mux_ops = composite->mux_ops;
+	struct clk_hw *rate_hw = composite->rate_hw;
+	struct clk_hw *mux_hw = composite->mux_hw;
+	unsigned long temp_rate;
+
+	__clk_hw_set_clk(rate_hw, hw);
+	__clk_hw_set_clk(mux_hw, hw);
+
+	temp_rate = rate_ops->recalc_rate(rate_hw, parent_rate);
+	if (temp_rate > rate) {
+		rate_ops->set_rate(rate_hw, rate, parent_rate);
+		mux_ops->set_parent(mux_hw, index);
+	} else {
+		mux_ops->set_parent(mux_hw, index);
+		rate_ops->set_rate(rate_hw, rate, parent_rate);
+	}
+
+	return 0;
+}
+
 static int clk_composite_is_enabled(struct clk_hw *hw)
 {
 	struct clk_composite *composite = to_clk_composite(hw);
@@ -184,17 +211,18 @@ static void clk_composite_disable(struct
 	gate_ops->disable(gate_hw);
 }
 
-struct clk *clk_register_composite(struct device *dev, const char *name,
+struct clk_hw *clk_hw_register_composite(struct device *dev, const char *name,
 			const char * const *parent_names, int num_parents,
 			struct clk_hw *mux_hw, const struct clk_ops *mux_ops,
 			struct clk_hw *rate_hw, const struct clk_ops *rate_ops,
 			struct clk_hw *gate_hw, const struct clk_ops *gate_ops,
 			unsigned long flags)
 {
-	struct clk *clk;
+	struct clk_hw *hw;
 	struct clk_init_data init;
 	struct clk_composite *composite;
 	struct clk_ops *clk_composite_ops;
+	int ret;
 
 	composite = kzalloc(sizeof(*composite), GFP_KERNEL);
 	if (!composite)
@@ -204,12 +232,13 @@ struct clk *clk_register_composite(struc
 	init.flags = flags | CLK_IS_BASIC;
 	init.parent_names = parent_names;
 	init.num_parents = num_parents;
+	hw = &composite->hw;
 
 	clk_composite_ops = &composite->ops;
 
 	if (mux_hw && mux_ops) {
 		if (!mux_ops->get_parent) {
-			clk = ERR_PTR(-EINVAL);
+			hw = ERR_PTR(-EINVAL);
 			goto err;
 		}
 
@@ -224,7 +253,7 @@ struct clk *clk_register_composite(struc
 
 	if (rate_hw && rate_ops) {
 		if (!rate_ops->recalc_rate) {
-			clk = ERR_PTR(-EINVAL);
+			hw = ERR_PTR(-EINVAL);
 			goto err;
 		}
 		clk_composite_ops->recalc_rate = clk_composite_recalc_rate;
@@ -250,10 +279,16 @@ struct clk *clk_register_composite(struc
 		composite->rate_ops = rate_ops;
 	}
 
+	if (mux_hw && mux_ops && rate_hw && rate_ops) {
+		if (mux_ops->set_parent && rate_ops->set_rate)
+			clk_composite_ops->set_rate_and_parent =
+			clk_composite_set_rate_and_parent;
+	}
+
 	if (gate_hw && gate_ops) {
 		if (!gate_ops->is_enabled || !gate_ops->enable ||
 		    !gate_ops->disable) {
-			clk = ERR_PTR(-EINVAL);
+			hw = ERR_PTR(-EINVAL);
 			goto err;
 		}
 
@@ -267,22 +302,56 @@ struct clk *clk_register_composite(struc
 	init.ops = clk_composite_ops;
 	composite->hw.init = &init;
 
-	clk = clk_register(dev, &composite->hw);
-	if (IS_ERR(clk))
+	ret = clk_hw_register(dev, hw);
+	if (ret) {
+		hw = ERR_PTR(ret);
 		goto err;
+	}
 
 	if (composite->mux_hw)
-		composite->mux_hw->clk = clk;
+		composite->mux_hw->clk = hw->clk;
 
 	if (composite->rate_hw)
-		composite->rate_hw->clk = clk;
+		composite->rate_hw->clk = hw->clk;
 
 	if (composite->gate_hw)
-		composite->gate_hw->clk = clk;
+		composite->gate_hw->clk = hw->clk;
 
-	return clk;
+	return hw;
 
 err:
 	kfree(composite);
-	return clk;
+	return hw;
+}
+
+struct clk *clk_register_composite(struct device *dev, const char *name,
+			const char * const *parent_names, int num_parents,
+			struct clk_hw *mux_hw, const struct clk_ops *mux_ops,
+			struct clk_hw *rate_hw, const struct clk_ops *rate_ops,
+			struct clk_hw *gate_hw, const struct clk_ops *gate_ops,
+			unsigned long flags)
+{
+	struct clk_hw *hw;
+
+	hw = clk_hw_register_composite(dev, name, parent_names, num_parents,
+			mux_hw, mux_ops, rate_hw, rate_ops, gate_hw, gate_ops,
+			flags);
+	if (IS_ERR(hw))
+		return ERR_CAST(hw);
+	return hw->clk;
+}
+
+void clk_unregister_composite(struct clk *clk)
+{
+	struct clk_composite *composite;
+	struct clk_hw *hw;
+
+	hw = __clk_get_hw(clk);
+	if (!hw)
+		return;
+
+	composite = to_clk_composite(hw);
+
+	clk_unregister(clk);
+	kfree(composite);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/clkdev.c linux-libre-4.7-gnu/drivers/clk/clkdev.c
--- linux-libre-4.6-gnu/drivers/clk/clkdev.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/clkdev.c	2016-07-24 15:23:50.000000000 -0400
@@ -301,6 +301,20 @@ clkdev_alloc(struct clk *clk, const char
 }
 EXPORT_SYMBOL(clkdev_alloc);
 
+struct clk_lookup *
+clkdev_hw_alloc(struct clk_hw *hw, const char *con_id, const char *dev_fmt, ...)
+{
+	struct clk_lookup *cl;
+	va_list ap;
+
+	va_start(ap, dev_fmt);
+	cl = vclkdev_alloc(hw, con_id, dev_fmt, ap);
+	va_end(ap);
+
+	return cl;
+}
+EXPORT_SYMBOL(clkdev_hw_alloc);
+
 /**
  * clkdev_create - allocate and add a clkdev lookup structure
  * @clk: struct clk to associate with all clk_lookups
@@ -324,6 +338,29 @@ struct clk_lookup *clkdev_create(struct
 }
 EXPORT_SYMBOL_GPL(clkdev_create);
 
+/**
+ * clkdev_hw_create - allocate and add a clkdev lookup structure
+ * @hw: struct clk_hw to associate with all clk_lookups
+ * @con_id: connection ID string on device
+ * @dev_fmt: format string describing device name
+ *
+ * Returns a clk_lookup structure, which can be later unregistered and
+ * freed.
+ */
+struct clk_lookup *clkdev_hw_create(struct clk_hw *hw, const char *con_id,
+	const char *dev_fmt, ...)
+{
+	struct clk_lookup *cl;
+	va_list ap;
+
+	va_start(ap, dev_fmt);
+	cl = vclkdev_create(hw, con_id, dev_fmt, ap);
+	va_end(ap);
+
+	return cl;
+}
+EXPORT_SYMBOL_GPL(clkdev_hw_create);
+
 int clk_add_alias(const char *alias, const char *alias_dev_name,
 	const char *con_id, struct device *dev)
 {
@@ -404,28 +441,28 @@ int clk_register_clkdev(struct clk *clk,
 EXPORT_SYMBOL(clk_register_clkdev);
 
 /**
- * clk_register_clkdevs - register a set of clk_lookup for a struct clk
- * @clk: struct clk to associate with all clk_lookups
- * @cl: array of clk_lookup structures with con_id and dev_id pre-initialized
- * @num: number of clk_lookup structures to register
+ * clk_hw_register_clkdev - register one clock lookup for a struct clk_hw
+ * @hw: struct clk_hw to associate with all clk_lookups
+ * @con_id: connection ID string on device
+ * @dev_id: format string describing device name
  *
- * To make things easier for mass registration, we detect error clks
- * from a previous clk_register() call, and return the error code for
- * those.  This is to permit this function to be called immediately
- * after clk_register().
+ * con_id or dev_id may be NULL as a wildcard, just as in the rest of
+ * clkdev.
  */
-int clk_register_clkdevs(struct clk *clk, struct clk_lookup *cl, size_t num)
+int clk_hw_register_clkdev(struct clk_hw *hw, const char *con_id,
+	const char *dev_id)
 {
-	unsigned i;
-
-	if (IS_ERR(clk))
-		return PTR_ERR(clk);
+	struct clk_lookup *cl;
 
-	for (i = 0; i < num; i++, cl++) {
-		cl->clk_hw = __clk_get_hw(clk);
-		__clkdev_add(cl);
-	}
+	/*
+	 * Since dev_id can be NULL, and NULL is handled specially, we must
+	 * pass it as either a NULL format string, or with "%s".
+	 */
+	if (dev_id)
+		cl = __clk_register_clkdev(hw, con_id, "%s", dev_id);
+	else
+		cl = __clk_register_clkdev(hw, con_id, NULL);
 
-	return 0;
+	return cl ? 0 : -ENOMEM;
 }
-EXPORT_SYMBOL(clk_register_clkdevs);
+EXPORT_SYMBOL(clk_hw_register_clkdev);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/clk-divider.c linux-libre-4.7-gnu/drivers/clk/clk-divider.c
--- linux-libre-4.6-gnu/drivers/clk/clk-divider.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/clk-divider.c	2016-07-24 15:23:50.000000000 -0400
@@ -426,15 +426,16 @@ const struct clk_ops clk_divider_ro_ops
 };
 EXPORT_SYMBOL_GPL(clk_divider_ro_ops);
 
-static struct clk *_register_divider(struct device *dev, const char *name,
+static struct clk_hw *_register_divider(struct device *dev, const char *name,
 		const char *parent_name, unsigned long flags,
 		void __iomem *reg, u8 shift, u8 width,
 		u8 clk_divider_flags, const struct clk_div_table *table,
 		spinlock_t *lock)
 {
 	struct clk_divider *div;
-	struct clk *clk;
+	struct clk_hw *hw;
 	struct clk_init_data init;
+	int ret;
 
 	if (clk_divider_flags & CLK_DIVIDER_HIWORD_MASK) {
 		if (width + shift > 16) {
@@ -467,12 +468,14 @@ static struct clk *_register_divider(str
 	div->table = table;
 
 	/* register the clock */
-	clk = clk_register(dev, &div->hw);
-
-	if (IS_ERR(clk))
+	hw = &div->hw;
+	ret = clk_hw_register(dev, hw);
+	if (ret) {
 		kfree(div);
+		hw = ERR_PTR(ret);
+	}
 
-	return clk;
+	return hw;
 }
 
 /**
@@ -492,12 +495,39 @@ struct clk *clk_register_divider(struct
 		void __iomem *reg, u8 shift, u8 width,
 		u8 clk_divider_flags, spinlock_t *lock)
 {
-	return _register_divider(dev, name, parent_name, flags, reg, shift,
+	struct clk_hw *hw;
+
+	hw =  _register_divider(dev, name, parent_name, flags, reg, shift,
 			width, clk_divider_flags, NULL, lock);
+	if (IS_ERR(hw))
+		return ERR_CAST(hw);
+	return hw->clk;
 }
 EXPORT_SYMBOL_GPL(clk_register_divider);
 
 /**
+ * clk_hw_register_divider - register a divider clock with the clock framework
+ * @dev: device registering this clock
+ * @name: name of this clock
+ * @parent_name: name of clock's parent
+ * @flags: framework-specific flags
+ * @reg: register address to adjust divider
+ * @shift: number of bits to shift the bitfield
+ * @width: width of the bitfield
+ * @clk_divider_flags: divider-specific flags for this clock
+ * @lock: shared register lock for this clock
+ */
+struct clk_hw *clk_hw_register_divider(struct device *dev, const char *name,
+		const char *parent_name, unsigned long flags,
+		void __iomem *reg, u8 shift, u8 width,
+		u8 clk_divider_flags, spinlock_t *lock)
+{
+	return _register_divider(dev, name, parent_name, flags, reg, shift,
+			width, clk_divider_flags, NULL, lock);
+}
+EXPORT_SYMBOL_GPL(clk_hw_register_divider);
+
+/**
  * clk_register_divider_table - register a table based divider clock with
  * the clock framework
  * @dev: device registering this clock
@@ -517,11 +547,41 @@ struct clk *clk_register_divider_table(s
 		u8 clk_divider_flags, const struct clk_div_table *table,
 		spinlock_t *lock)
 {
-	return _register_divider(dev, name, parent_name, flags, reg, shift,
+	struct clk_hw *hw;
+
+	hw =  _register_divider(dev, name, parent_name, flags, reg, shift,
 			width, clk_divider_flags, table, lock);
+	if (IS_ERR(hw))
+		return ERR_CAST(hw);
+	return hw->clk;
 }
 EXPORT_SYMBOL_GPL(clk_register_divider_table);
 
+/**
+ * clk_hw_register_divider_table - register a table based divider clock with
+ * the clock framework
+ * @dev: device registering this clock
+ * @name: name of this clock
+ * @parent_name: name of clock's parent
+ * @flags: framework-specific flags
+ * @reg: register address to adjust divider
+ * @shift: number of bits to shift the bitfield
+ * @width: width of the bitfield
+ * @clk_divider_flags: divider-specific flags for this clock
+ * @table: array of divider/value pairs ending with a div set to 0
+ * @lock: shared register lock for this clock
+ */
+struct clk_hw *clk_hw_register_divider_table(struct device *dev,
+		const char *name, const char *parent_name, unsigned long flags,
+		void __iomem *reg, u8 shift, u8 width,
+		u8 clk_divider_flags, const struct clk_div_table *table,
+		spinlock_t *lock)
+{
+	return _register_divider(dev, name, parent_name, flags, reg, shift,
+			width, clk_divider_flags, table, lock);
+}
+EXPORT_SYMBOL_GPL(clk_hw_register_divider_table);
+
 void clk_unregister_divider(struct clk *clk)
 {
 	struct clk_divider *div;
@@ -537,3 +597,18 @@ void clk_unregister_divider(struct clk *
 	kfree(div);
 }
 EXPORT_SYMBOL_GPL(clk_unregister_divider);
+
+/**
+ * clk_hw_unregister_divider - unregister a clk divider
+ * @hw: hardware-specific clock data to unregister
+ */
+void clk_hw_unregister_divider(struct clk_hw *hw)
+{
+	struct clk_divider *div;
+
+	div = to_clk_divider(hw);
+
+	clk_hw_unregister(hw);
+	kfree(div);
+}
+EXPORT_SYMBOL_GPL(clk_hw_unregister_divider);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/clk-fixed-factor.c linux-libre-4.7-gnu/drivers/clk/clk-fixed-factor.c
--- linux-libre-4.6-gnu/drivers/clk/clk-fixed-factor.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/clk-fixed-factor.c	2016-07-24 15:23:50.000000000 -0400
@@ -68,13 +68,14 @@ const struct clk_ops clk_fixed_factor_op
 };
 EXPORT_SYMBOL_GPL(clk_fixed_factor_ops);
 
-struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
-		const char *parent_name, unsigned long flags,
+struct clk_hw *clk_hw_register_fixed_factor(struct device *dev,
+		const char *name, const char *parent_name, unsigned long flags,
 		unsigned int mult, unsigned int div)
 {
 	struct clk_fixed_factor *fix;
 	struct clk_init_data init;
-	struct clk *clk;
+	struct clk_hw *hw;
+	int ret;
 
 	fix = kmalloc(sizeof(*fix), GFP_KERNEL);
 	if (!fix)
@@ -91,12 +92,28 @@ struct clk *clk_register_fixed_factor(st
 	init.parent_names = &parent_name;
 	init.num_parents = 1;
 
-	clk = clk_register(dev, &fix->hw);
-
-	if (IS_ERR(clk))
+	hw = &fix->hw;
+	ret = clk_hw_register(dev, hw);
+	if (ret) {
 		kfree(fix);
+		hw = ERR_PTR(ret);
+	}
 
-	return clk;
+	return hw;
+}
+EXPORT_SYMBOL_GPL(clk_hw_register_fixed_factor);
+
+struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
+		const char *parent_name, unsigned long flags,
+		unsigned int mult, unsigned int div)
+{
+	struct clk_hw *hw;
+
+	hw = clk_hw_register_fixed_factor(dev, name, parent_name, flags, mult,
+					  div);
+	if (IS_ERR(hw))
+		return ERR_CAST(hw);
+	return hw->clk;
 }
 EXPORT_SYMBOL_GPL(clk_register_fixed_factor);
 
@@ -113,6 +130,17 @@ void clk_unregister_fixed_factor(struct
 }
 EXPORT_SYMBOL_GPL(clk_unregister_fixed_factor);
 
+void clk_hw_unregister_fixed_factor(struct clk_hw *hw)
+{
+	struct clk_fixed_factor *fix;
+
+	fix = to_clk_fixed_factor(hw);
+
+	clk_hw_unregister(hw);
+	kfree(fix);
+}
+EXPORT_SYMBOL_GPL(clk_hw_unregister_fixed_factor);
+
 #ifdef CONFIG_OF
 /**
  * of_fixed_factor_clk_setup() - Setup function for simple fixed factor clock
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/clk-fixed-rate.c linux-libre-4.7-gnu/drivers/clk/clk-fixed-rate.c
--- linux-libre-4.6-gnu/drivers/clk/clk-fixed-rate.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/clk-fixed-rate.c	2016-07-24 15:23:50.000000000 -0400
@@ -45,8 +45,8 @@ const struct clk_ops clk_fixed_rate_ops
 EXPORT_SYMBOL_GPL(clk_fixed_rate_ops);
 
 /**
- * clk_register_fixed_rate_with_accuracy - register fixed-rate clock with the
- *					   clock framework
+ * clk_hw_register_fixed_rate_with_accuracy - register fixed-rate clock with
+ * the clock framework
  * @dev: device that is registering this clock
  * @name: name of this clock
  * @parent_name: name of clock's parent
@@ -54,13 +54,14 @@ EXPORT_SYMBOL_GPL(clk_fixed_rate_ops);
  * @fixed_rate: non-adjustable clock rate
  * @fixed_accuracy: non-adjustable clock rate
  */
-struct clk *clk_register_fixed_rate_with_accuracy(struct device *dev,
+struct clk_hw *clk_hw_register_fixed_rate_with_accuracy(struct device *dev,
 		const char *name, const char *parent_name, unsigned long flags,
 		unsigned long fixed_rate, unsigned long fixed_accuracy)
 {
 	struct clk_fixed_rate *fixed;
-	struct clk *clk;
+	struct clk_hw *hw;
 	struct clk_init_data init;
+	int ret;
 
 	/* allocate fixed-rate clock */
 	fixed = kzalloc(sizeof(*fixed), GFP_KERNEL);
@@ -79,22 +80,49 @@ struct clk *clk_register_fixed_rate_with
 	fixed->hw.init = &init;
 
 	/* register the clock */
-	clk = clk_register(dev, &fixed->hw);
-	if (IS_ERR(clk))
+	hw = &fixed->hw;
+	ret = clk_hw_register(dev, hw);
+	if (ret) {
 		kfree(fixed);
+		hw = ERR_PTR(ret);
+	}
 
-	return clk;
+	return hw;
+}
+EXPORT_SYMBOL_GPL(clk_hw_register_fixed_rate_with_accuracy);
+
+struct clk *clk_register_fixed_rate_with_accuracy(struct device *dev,
+		const char *name, const char *parent_name, unsigned long flags,
+		unsigned long fixed_rate, unsigned long fixed_accuracy)
+{
+	struct clk_hw *hw;
+
+	hw = clk_hw_register_fixed_rate_with_accuracy(dev, name, parent_name,
+			flags, fixed_rate, fixed_accuracy);
+	if (IS_ERR(hw))
+		return ERR_CAST(hw);
+	return hw->clk;
 }
 EXPORT_SYMBOL_GPL(clk_register_fixed_rate_with_accuracy);
 
 /**
- * clk_register_fixed_rate - register fixed-rate clock with the clock framework
+ * clk_hw_register_fixed_rate - register fixed-rate clock with the clock
+ * framework
  * @dev: device that is registering this clock
  * @name: name of this clock
  * @parent_name: name of clock's parent
  * @flags: framework-specific flags
  * @fixed_rate: non-adjustable clock rate
  */
+struct clk_hw *clk_hw_register_fixed_rate(struct device *dev, const char *name,
+		const char *parent_name, unsigned long flags,
+		unsigned long fixed_rate)
+{
+	return clk_hw_register_fixed_rate_with_accuracy(dev, name, parent_name,
+						     flags, fixed_rate, 0);
+}
+EXPORT_SYMBOL_GPL(clk_hw_register_fixed_rate);
+
 struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
 		const char *parent_name, unsigned long flags,
 		unsigned long fixed_rate)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/clk-fractional-divider.c linux-libre-4.7-gnu/drivers/clk/clk-fractional-divider.c
--- linux-libre-4.6-gnu/drivers/clk/clk-fractional-divider.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/clk-fractional-divider.c	2016-07-24 15:23:50.000000000 -0400
@@ -116,14 +116,15 @@ const struct clk_ops clk_fractional_divi
 };
 EXPORT_SYMBOL_GPL(clk_fractional_divider_ops);
 
-struct clk *clk_register_fractional_divider(struct device *dev,
+struct clk_hw *clk_hw_register_fractional_divider(struct device *dev,
 		const char *name, const char *parent_name, unsigned long flags,
 		void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth,
 		u8 clk_divider_flags, spinlock_t *lock)
 {
 	struct clk_fractional_divider *fd;
 	struct clk_init_data init;
-	struct clk *clk;
+	struct clk_hw *hw;
+	int ret;
 
 	fd = kzalloc(sizeof(*fd), GFP_KERNEL);
 	if (!fd)
@@ -146,10 +147,39 @@ struct clk *clk_register_fractional_divi
 	fd->lock = lock;
 	fd->hw.init = &init;
 
-	clk = clk_register(dev, &fd->hw);
-	if (IS_ERR(clk))
+	hw = &fd->hw;
+	ret = clk_hw_register(dev, hw);
+	if (ret) {
 		kfree(fd);
+		hw = ERR_PTR(ret);
+	}
 
-	return clk;
+	return hw;
+}
+EXPORT_SYMBOL_GPL(clk_hw_register_fractional_divider);
+
+struct clk *clk_register_fractional_divider(struct device *dev,
+		const char *name, const char *parent_name, unsigned long flags,
+		void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth,
+		u8 clk_divider_flags, spinlock_t *lock)
+{
+	struct clk_hw *hw;
+
+	hw = clk_hw_register_fractional_divider(dev, name, parent_name, flags,
+			reg, mshift, mwidth, nshift, nwidth, clk_divider_flags,
+			lock);
+	if (IS_ERR(hw))
+		return ERR_CAST(hw);
+	return hw->clk;
 }
 EXPORT_SYMBOL_GPL(clk_register_fractional_divider);
+
+void clk_hw_unregister_fractional_divider(struct clk_hw *hw)
+{
+	struct clk_fractional_divider *fd;
+
+	fd = to_clk_fd(hw);
+
+	clk_hw_unregister(hw);
+	kfree(fd);
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/clk-gate.c linux-libre-4.7-gnu/drivers/clk/clk-gate.c
--- linux-libre-4.6-gnu/drivers/clk/clk-gate.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/clk-gate.c	2016-07-24 15:23:50.000000000 -0400
@@ -110,7 +110,7 @@ const struct clk_ops clk_gate_ops = {
 EXPORT_SYMBOL_GPL(clk_gate_ops);
 
 /**
- * clk_register_gate - register a gate clock with the clock framework
+ * clk_hw_register_gate - register a gate clock with the clock framework
  * @dev: device that is registering this clock
  * @name: name of this clock
  * @parent_name: name of this clock's parent
@@ -120,14 +120,15 @@ EXPORT_SYMBOL_GPL(clk_gate_ops);
  * @clk_gate_flags: gate-specific flags for this clock
  * @lock: shared register lock for this clock
  */
-struct clk *clk_register_gate(struct device *dev, const char *name,
+struct clk_hw *clk_hw_register_gate(struct device *dev, const char *name,
 		const char *parent_name, unsigned long flags,
 		void __iomem *reg, u8 bit_idx,
 		u8 clk_gate_flags, spinlock_t *lock)
 {
 	struct clk_gate *gate;
-	struct clk *clk;
+	struct clk_hw *hw;
 	struct clk_init_data init;
+	int ret;
 
 	if (clk_gate_flags & CLK_GATE_HIWORD_MASK) {
 		if (bit_idx > 15) {
@@ -154,12 +155,29 @@ struct clk *clk_register_gate(struct dev
 	gate->lock = lock;
 	gate->hw.init = &init;
 
-	clk = clk_register(dev, &gate->hw);
-
-	if (IS_ERR(clk))
+	hw = &gate->hw;
+	ret = clk_hw_register(dev, hw);
+	if (ret) {
 		kfree(gate);
+		hw = ERR_PTR(ret);
+	}
 
-	return clk;
+	return hw;
+}
+EXPORT_SYMBOL_GPL(clk_hw_register_gate);
+
+struct clk *clk_register_gate(struct device *dev, const char *name,
+		const char *parent_name, unsigned long flags,
+		void __iomem *reg, u8 bit_idx,
+		u8 clk_gate_flags, spinlock_t *lock)
+{
+	struct clk_hw *hw;
+
+	hw = clk_hw_register_gate(dev, name, parent_name, flags, reg,
+				  bit_idx, clk_gate_flags, lock);
+	if (IS_ERR(hw))
+		return ERR_CAST(hw);
+	return hw->clk;
 }
 EXPORT_SYMBOL_GPL(clk_register_gate);
 
@@ -178,3 +196,14 @@ void clk_unregister_gate(struct clk *clk
 	kfree(gate);
 }
 EXPORT_SYMBOL_GPL(clk_unregister_gate);
+
+void clk_hw_unregister_gate(struct clk_hw *hw)
+{
+	struct clk_gate *gate;
+
+	gate = to_clk_gate(hw);
+
+	clk_hw_unregister(hw);
+	kfree(gate);
+}
+EXPORT_SYMBOL_GPL(clk_hw_unregister_gate);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/clk-gpio.c linux-libre-4.7-gnu/drivers/clk/clk-gpio.c
--- linux-libre-4.6-gnu/drivers/clk/clk-gpio.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/clk-gpio.c	2016-07-24 15:23:50.000000000 -0400
@@ -94,13 +94,13 @@ const struct clk_ops clk_gpio_mux_ops =
 };
 EXPORT_SYMBOL_GPL(clk_gpio_mux_ops);
 
-static struct clk *clk_register_gpio(struct device *dev, const char *name,
+static struct clk_hw *clk_register_gpio(struct device *dev, const char *name,
 		const char * const *parent_names, u8 num_parents, unsigned gpio,
 		bool active_low, unsigned long flags,
 		const struct clk_ops *clk_gpio_ops)
 {
 	struct clk_gpio *clk_gpio;
-	struct clk *clk;
+	struct clk_hw *hw;
 	struct clk_init_data init = {};
 	unsigned long gpio_flags;
 	int err;
@@ -141,24 +141,26 @@ static struct clk *clk_register_gpio(str
 	clk_gpio->gpiod = gpio_to_desc(gpio);
 	clk_gpio->hw.init = &init;
 
+	hw = &clk_gpio->hw;
 	if (dev)
-		clk = devm_clk_register(dev, &clk_gpio->hw);
+		err = devm_clk_hw_register(dev, hw);
 	else
-		clk = clk_register(NULL, &clk_gpio->hw);
+		err = clk_hw_register(NULL, hw);
 
-	if (!IS_ERR(clk))
-		return clk;
+	if (!err)
+		return hw;
 
 	if (!dev) {
 		gpiod_put(clk_gpio->gpiod);
 		kfree(clk_gpio);
 	}
 
-	return clk;
+	return ERR_PTR(err);
 }
 
 /**
- * clk_register_gpio_gate - register a gpio clock gate with the clock framework
+ * clk_hw_register_gpio_gate - register a gpio clock gate with the clock
+ * framework
  * @dev: device that is registering this clock
  * @name: name of this clock
  * @parent_name: name of this clock's parent
@@ -166,7 +168,7 @@ static struct clk *clk_register_gpio(str
  * @active_low: true if gpio should be set to 0 to enable clock
  * @flags: clock flags
  */
-struct clk *clk_register_gpio_gate(struct device *dev, const char *name,
+struct clk_hw *clk_hw_register_gpio_gate(struct device *dev, const char *name,
 		const char *parent_name, unsigned gpio, bool active_low,
 		unsigned long flags)
 {
@@ -175,10 +177,24 @@ struct clk *clk_register_gpio_gate(struc
 			(parent_name ? 1 : 0), gpio, active_low, flags,
 			&clk_gpio_gate_ops);
 }
+EXPORT_SYMBOL_GPL(clk_hw_register_gpio_gate);
+
+struct clk *clk_register_gpio_gate(struct device *dev, const char *name,
+		const char *parent_name, unsigned gpio, bool active_low,
+		unsigned long flags)
+{
+	struct clk_hw *hw;
+
+	hw = clk_hw_register_gpio_gate(dev, name, parent_name, gpio, active_low,
+				       flags);
+	if (IS_ERR(hw))
+		return ERR_CAST(hw);
+	return hw->clk;
+}
 EXPORT_SYMBOL_GPL(clk_register_gpio_gate);
 
 /**
- * clk_register_gpio_mux - register a gpio clock mux with the clock framework
+ * clk_hw_register_gpio_mux - register a gpio clock mux with the clock framework
  * @dev: device that is registering this clock
  * @name: name of this clock
  * @parent_names: names of this clock's parents
@@ -187,7 +203,7 @@ EXPORT_SYMBOL_GPL(clk_register_gpio_gate
  * @active_low: true if gpio should be set to 0 to enable clock
  * @flags: clock flags
  */
-struct clk *clk_register_gpio_mux(struct device *dev, const char *name,
+struct clk_hw *clk_hw_register_gpio_mux(struct device *dev, const char *name,
 		const char * const *parent_names, u8 num_parents, unsigned gpio,
 		bool active_low, unsigned long flags)
 {
@@ -199,6 +215,20 @@ struct clk *clk_register_gpio_mux(struct
 	return clk_register_gpio(dev, name, parent_names, num_parents,
 			gpio, active_low, flags, &clk_gpio_mux_ops);
 }
+EXPORT_SYMBOL_GPL(clk_hw_register_gpio_mux);
+
+struct clk *clk_register_gpio_mux(struct device *dev, const char *name,
+		const char * const *parent_names, u8 num_parents, unsigned gpio,
+		bool active_low, unsigned long flags)
+{
+	struct clk_hw *hw;
+
+	hw = clk_hw_register_gpio_mux(dev, name, parent_names, num_parents,
+			gpio, active_low, flags);
+	if (IS_ERR(hw))
+		return ERR_CAST(hw);
+	return hw->clk;
+}
 EXPORT_SYMBOL_GPL(clk_register_gpio_mux);
 
 static int gpio_clk_driver_probe(struct platform_device *pdev)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/clk-ls1x.c linux-libre-4.7-gnu/drivers/clk/clk-ls1x.c
--- linux-libre-4.6-gnu/drivers/clk/clk-ls1x.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/clk-ls1x.c	2016-07-24 15:23:50.000000000 -0400
@@ -88,8 +88,7 @@ void __init ls1x_clk_init(void)
 {
 	struct clk *clk;
 
-	clk = clk_register_fixed_rate(NULL, "osc_33m_clk", NULL, CLK_IS_ROOT,
-				      OSC);
+	clk = clk_register_fixed_rate(NULL, "osc_33m_clk", NULL, 0, OSC);
 	clk_register_clkdev(clk, "osc_33m_clk", NULL);
 
 	/* clock derived from 33 MHz OSC clk */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/clk-mux.c linux-libre-4.7-gnu/drivers/clk/clk-mux.c
--- linux-libre-4.6-gnu/drivers/clk/clk-mux.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/clk-mux.c	2016-07-24 15:23:50.000000000 -0400
@@ -113,16 +113,17 @@ const struct clk_ops clk_mux_ro_ops = {
 };
 EXPORT_SYMBOL_GPL(clk_mux_ro_ops);
 
-struct clk *clk_register_mux_table(struct device *dev, const char *name,
+struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name,
 		const char * const *parent_names, u8 num_parents,
 		unsigned long flags,
 		void __iomem *reg, u8 shift, u32 mask,
 		u8 clk_mux_flags, u32 *table, spinlock_t *lock)
 {
 	struct clk_mux *mux;
-	struct clk *clk;
+	struct clk_hw *hw;
 	struct clk_init_data init;
 	u8 width = 0;
+	int ret;
 
 	if (clk_mux_flags & CLK_MUX_HIWORD_MASK) {
 		width = fls(mask) - ffs(mask) + 1;
@@ -157,12 +158,31 @@ struct clk *clk_register_mux_table(struc
 	mux->table = table;
 	mux->hw.init = &init;
 
-	clk = clk_register(dev, &mux->hw);
-
-	if (IS_ERR(clk))
+	hw = &mux->hw;
+	ret = clk_hw_register(dev, hw);
+	if (ret) {
 		kfree(mux);
+		hw = ERR_PTR(ret);
+	}
 
-	return clk;
+	return hw;
+}
+EXPORT_SYMBOL_GPL(clk_hw_register_mux_table);
+
+struct clk *clk_register_mux_table(struct device *dev, const char *name,
+		const char * const *parent_names, u8 num_parents,
+		unsigned long flags,
+		void __iomem *reg, u8 shift, u32 mask,
+		u8 clk_mux_flags, u32 *table, spinlock_t *lock)
+{
+	struct clk_hw *hw;
+
+	hw = clk_hw_register_mux_table(dev, name, parent_names, num_parents,
+				       flags, reg, shift, mask, clk_mux_flags,
+				       table, lock);
+	if (IS_ERR(hw))
+		return ERR_CAST(hw);
+	return hw->clk;
 }
 EXPORT_SYMBOL_GPL(clk_register_mux_table);
 
@@ -180,6 +200,20 @@ struct clk *clk_register_mux(struct devi
 }
 EXPORT_SYMBOL_GPL(clk_register_mux);
 
+struct clk_hw *clk_hw_register_mux(struct device *dev, const char *name,
+		const char * const *parent_names, u8 num_parents,
+		unsigned long flags,
+		void __iomem *reg, u8 shift, u8 width,
+		u8 clk_mux_flags, spinlock_t *lock)
+{
+	u32 mask = BIT(width) - 1;
+
+	return clk_hw_register_mux_table(dev, name, parent_names, num_parents,
+				      flags, reg, shift, mask, clk_mux_flags,
+				      NULL, lock);
+}
+EXPORT_SYMBOL_GPL(clk_hw_register_mux);
+
 void clk_unregister_mux(struct clk *clk)
 {
 	struct clk_mux *mux;
@@ -195,3 +229,14 @@ void clk_unregister_mux(struct clk *clk)
 	kfree(mux);
 }
 EXPORT_SYMBOL_GPL(clk_unregister_mux);
+
+void clk_hw_unregister_mux(struct clk_hw *hw)
+{
+	struct clk_mux *mux;
+
+	mux = to_clk_mux(hw);
+
+	clk_hw_unregister(hw);
+	kfree(mux);
+}
+EXPORT_SYMBOL_GPL(clk_hw_unregister_mux);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/clk-nspire.c linux-libre-4.7-gnu/drivers/clk/clk-nspire.c
--- linux-libre-4.6-gnu/drivers/clk/clk-nspire.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/clk-nspire.c	2016-07-24 15:23:50.000000000 -0400
@@ -125,8 +125,7 @@ static void __init nspire_clk_setup(stru
 
 	of_property_read_string(node, "clock-output-names", &clk_name);
 
-	clk = clk_register_fixed_rate(NULL, clk_name, NULL, CLK_IS_ROOT,
-			info.base_clock);
+	clk = clk_register_fixed_rate(NULL, clk_name, NULL, 0, info.base_clock);
 	if (!IS_ERR(clk))
 		of_clk_add_provider(node, of_clk_src_simple_get, clk);
 	else
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/clk-oxnas.c linux-libre-4.7-gnu/drivers/clk/clk-oxnas.c
--- linux-libre-4.6-gnu/drivers/clk/clk-oxnas.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/clk/clk-oxnas.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2010 Broadcom
+ * Copyright (C) 2012 Stephen Warren
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/stringify.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+
+/* Standard regmap gate clocks */
+struct clk_oxnas {
+	struct clk_hw hw;
+	signed char bit;
+	struct regmap *regmap;
+};
+
+/* Regmap offsets */
+#define CLK_STAT_REGOFFSET	0x24
+#define CLK_SET_REGOFFSET	0x2c
+#define CLK_CLR_REGOFFSET	0x30
+
+static inline struct clk_oxnas *to_clk_oxnas(struct clk_hw *hw)
+{
+	return container_of(hw, struct clk_oxnas, hw);
+}
+
+static int oxnas_clk_is_enabled(struct clk_hw *hw)
+{
+	struct clk_oxnas *std = to_clk_oxnas(hw);
+	int ret;
+	unsigned int val;
+
+	ret = regmap_read(std->regmap, CLK_STAT_REGOFFSET, &val);
+	if (ret < 0)
+		return ret;
+
+	return val & BIT(std->bit);
+}
+
+static int oxnas_clk_enable(struct clk_hw *hw)
+{
+	struct clk_oxnas *std = to_clk_oxnas(hw);
+
+	regmap_write(std->regmap, CLK_SET_REGOFFSET, BIT(std->bit));
+
+	return 0;
+}
+
+static void oxnas_clk_disable(struct clk_hw *hw)
+{
+	struct clk_oxnas *std = to_clk_oxnas(hw);
+
+	regmap_write(std->regmap, CLK_CLR_REGOFFSET, BIT(std->bit));
+}
+
+static const struct clk_ops oxnas_clk_ops = {
+	.enable = oxnas_clk_enable,
+	.disable = oxnas_clk_disable,
+	.is_enabled = oxnas_clk_is_enabled,
+};
+
+static const char *const oxnas_clk_parents[] = {
+	"oscillator",
+};
+
+static const char *const eth_parents[] = {
+	"gmacclk",
+};
+
+#define DECLARE_STD_CLKP(__clk, __parent)			\
+static const struct clk_init_data clk_##__clk##_init = {	\
+	.name = __stringify(__clk),				\
+	.ops = &oxnas_clk_ops,					\
+	.parent_names = __parent,				\
+	.num_parents = ARRAY_SIZE(__parent),			\
+}
+
+#define DECLARE_STD_CLK(__clk) DECLARE_STD_CLKP(__clk, oxnas_clk_parents)
+
+/* Hardware Bit - Clock association */
+struct clk_oxnas_init_data {
+	unsigned long bit;
+	const struct clk_init_data *clk_init;
+};
+
+/* Clk init data declaration */
+DECLARE_STD_CLK(leon);
+DECLARE_STD_CLK(dma_sgdma);
+DECLARE_STD_CLK(cipher);
+DECLARE_STD_CLK(sata);
+DECLARE_STD_CLK(audio);
+DECLARE_STD_CLK(usbmph);
+DECLARE_STD_CLKP(etha, eth_parents);
+DECLARE_STD_CLK(pciea);
+DECLARE_STD_CLK(nand);
+
+/* Table index is clock indice */
+static const struct clk_oxnas_init_data clk_oxnas_init[] = {
+	[0] = {0, &clk_leon_init},
+	[1] = {1, &clk_dma_sgdma_init},
+	[2] = {2, &clk_cipher_init},
+	/* Skip & Do not touch to DDR clock */
+	[3] = {4, &clk_sata_init},
+	[4] = {5, &clk_audio_init},
+	[5] = {6, &clk_usbmph_init},
+	[6] = {7, &clk_etha_init},
+	[7] = {8, &clk_pciea_init},
+	[8] = {9, &clk_nand_init},
+};
+
+struct clk_oxnas_data {
+	struct clk_oxnas clk_oxnas[ARRAY_SIZE(clk_oxnas_init)];
+	struct clk_onecell_data onecell_data[ARRAY_SIZE(clk_oxnas_init)];
+	struct clk *clks[ARRAY_SIZE(clk_oxnas_init)];
+};
+
+static int oxnas_stdclk_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct clk_oxnas_data *clk_oxnas;
+	struct regmap *regmap;
+	int i;
+
+	clk_oxnas = devm_kzalloc(&pdev->dev, sizeof(*clk_oxnas), GFP_KERNEL);
+	if (!clk_oxnas)
+		return -ENOMEM;
+
+	regmap = syscon_node_to_regmap(of_get_parent(np));
+	if (IS_ERR(regmap)) {
+		dev_err(&pdev->dev, "failed to have parent regmap\n");
+		return PTR_ERR(regmap);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(clk_oxnas_init); i++) {
+		struct clk_oxnas *_clk;
+
+		_clk = &clk_oxnas->clk_oxnas[i];
+		_clk->bit = clk_oxnas_init[i].bit;
+		_clk->hw.init = clk_oxnas_init[i].clk_init;
+		_clk->regmap = regmap;
+
+		clk_oxnas->clks[i] =
+			devm_clk_register(&pdev->dev, &_clk->hw);
+		if (WARN_ON(IS_ERR(clk_oxnas->clks[i])))
+			return PTR_ERR(clk_oxnas->clks[i]);
+	}
+
+	clk_oxnas->onecell_data->clks = clk_oxnas->clks;
+	clk_oxnas->onecell_data->clk_num = ARRAY_SIZE(clk_oxnas_init);
+
+	return of_clk_add_provider(np, of_clk_src_onecell_get,
+				   clk_oxnas->onecell_data);
+}
+
+static int oxnas_stdclk_remove(struct platform_device *pdev)
+{
+	of_clk_del_provider(pdev->dev.of_node);
+
+	return 0;
+}
+
+static const struct of_device_id oxnas_stdclk_dt_ids[] = {
+	{ .compatible = "oxsemi,ox810se-stdclk" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, oxnas_stdclk_dt_ids);
+
+static struct platform_driver oxnas_stdclk_driver = {
+	.probe = oxnas_stdclk_probe,
+	.remove = oxnas_stdclk_remove,
+	.driver	= {
+		.name = "oxnas-stdclk",
+		.of_match_table = oxnas_stdclk_dt_ids,
+	},
+};
+
+module_platform_driver(oxnas_stdclk_driver);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/clk-palmas.c linux-libre-4.7-gnu/drivers/clk/clk-palmas.c
--- linux-libre-4.6-gnu/drivers/clk/clk-palmas.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/clk-palmas.c	2016-07-24 15:23:50.000000000 -0400
@@ -132,7 +132,7 @@ static const struct palmas_clks_of_match
 	.init = {
 		.name = "clk32kg",
 		.ops = &palmas_clks_ops,
-		.flags = CLK_IS_ROOT | CLK_IGNORE_UNUSED,
+		.flags = CLK_IGNORE_UNUSED,
 	},
 	.desc = {
 		.clk_name = "clk32kg",
@@ -148,7 +148,7 @@ static const struct palmas_clks_of_match
 	.init = {
 		.name = "clk32kgaudio",
 		.ops = &palmas_clks_ops,
-		.flags = CLK_IS_ROOT | CLK_IGNORE_UNUSED,
+		.flags = CLK_IGNORE_UNUSED,
 	},
 	.desc = {
 		.clk_name = "clk32kgaudio",
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/clk-pwm.c linux-libre-4.7-gnu/drivers/clk/clk-pwm.c
--- linux-libre-4.6-gnu/drivers/clk/clk-pwm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/clk-pwm.c	2016-07-24 15:23:50.000000000 -0400
@@ -59,6 +59,7 @@ static int clk_pwm_probe(struct platform
 	struct clk_init_data init;
 	struct clk_pwm *clk_pwm;
 	struct pwm_device *pwm;
+	struct pwm_args pargs;
 	const char *clk_name;
 	struct clk *clk;
 	int ret;
@@ -71,22 +72,28 @@ static int clk_pwm_probe(struct platform
 	if (IS_ERR(pwm))
 		return PTR_ERR(pwm);
 
-	if (!pwm->period) {
+	pwm_get_args(pwm, &pargs);
+	if (!pargs.period) {
 		dev_err(&pdev->dev, "invalid PWM period\n");
 		return -EINVAL;
 	}
 
 	if (of_property_read_u32(node, "clock-frequency", &clk_pwm->fixed_rate))
-		clk_pwm->fixed_rate = NSEC_PER_SEC / pwm->period;
+		clk_pwm->fixed_rate = NSEC_PER_SEC / pargs.period;
 
-	if (pwm->period != NSEC_PER_SEC / clk_pwm->fixed_rate &&
-	    pwm->period != DIV_ROUND_UP(NSEC_PER_SEC, clk_pwm->fixed_rate)) {
+	if (pargs.period != NSEC_PER_SEC / clk_pwm->fixed_rate &&
+	    pargs.period != DIV_ROUND_UP(NSEC_PER_SEC, clk_pwm->fixed_rate)) {
 		dev_err(&pdev->dev,
 			"clock-frequency does not match PWM period\n");
 		return -EINVAL;
 	}
 
-	ret = pwm_config(pwm, (pwm->period + 1) >> 1, pwm->period);
+	/*
+	 * FIXME: pwm_apply_args() should be removed when switching to the
+	 * atomic PWM API.
+	 */
+	pwm_apply_args(pwm);
+	ret = pwm_config(pwm, (pargs.period + 1) >> 1, pargs.period);
 	if (ret < 0)
 		return ret;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/clk-qoriq.c linux-libre-4.7-gnu/drivers/clk/clk-qoriq.c
--- linux-libre-4.6-gnu/drivers/clk/clk-qoriq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/clk-qoriq.c	2016-07-24 15:23:50.000000000 -0400
@@ -869,14 +869,15 @@ static void __init core_mux_init(struct
 	}
 }
 
-static struct clk *sysclk_from_fixed(struct device_node *node, const char *name)
+static struct clk __init
+*sysclk_from_fixed(struct device_node *node, const char *name)
 {
 	u32 rate;
 
 	if (of_property_read_u32(node, "clock-frequency", &rate))
 		return ERR_PTR(-ENODEV);
 
-	return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate);
+	return clk_register_fixed_rate(NULL, name, NULL, 0, rate);
 }
 
 static struct clk *sysclk_from_parent(const char *name)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/clk-rk808.c linux-libre-4.7-gnu/drivers/clk/clk-rk808.c
--- linux-libre-4.6-gnu/drivers/clk/clk-rk808.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/clk-rk808.c	2016-07-24 15:23:50.000000000 -0400
@@ -106,7 +106,6 @@ static int rk808_clkout_probe(struct pla
 	if (!clk_table)
 		return -ENOMEM;
 
-	init.flags = CLK_IS_ROOT;
 	init.parent_names = NULL;
 	init.num_parents = 0;
 	init.name = "rk808-clkout1";
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/clk-tango4.c linux-libre-4.7-gnu/drivers/clk/clk-tango4.c
--- linux-libre-4.6-gnu/drivers/clk/clk-tango4.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/clk-tango4.c	2016-07-24 15:23:50.000000000 -0400
@@ -4,17 +4,19 @@
 #include <linux/init.h>
 #include <linux/io.h>
 
-static struct clk *out[2];
-static struct clk_onecell_data clk_data = { out, 2 };
+#define CLK_COUNT 4 /* cpu_clk, sys_clk, usb_clk, sdio_clk */
+static struct clk *clks[CLK_COUNT];
+static struct clk_onecell_data clk_data = { clks, CLK_COUNT };
 
-#define SYSCLK_CTRL	0x20
-#define CPUCLK_CTRL	0x24
-#define LEGACY_DIV	0x3c
+#define SYSCLK_DIV	0x20
+#define CPUCLK_DIV	0x24
+#define DIV_BYPASS	BIT(23)
 
-#define PLL_N(val)	(((val) >>  0) & 0x7f)
-#define PLL_K(val)	(((val) >> 13) & 0x7)
-#define PLL_M(val)	(((val) >> 16) & 0x7)
-#define DIV_INDEX(val)	(((val) >>  8) & 0xf)
+/*** CLKGEN_PLL ***/
+#define extract_pll_n(val)	((val >>  0) & ((1u << 7) - 1))
+#define extract_pll_k(val)	((val >> 13) & ((1u << 3) - 1))
+#define extract_pll_m(val)	((val >> 16) & ((1u << 3) - 1))
+#define extract_pll_isel(val)	((val >> 24) & ((1u << 3) - 1))
 
 static void __init make_pll(int idx, const char *parent, void __iomem *base)
 {
@@ -22,40 +24,61 @@ static void __init make_pll(int idx, con
 	u32 val, mul, div;
 
 	sprintf(name, "pll%d", idx);
-	val = readl_relaxed(base + idx*8);
-	mul =  PLL_N(val) + 1;
-	div = (PLL_M(val) + 1) << PLL_K(val);
+	val = readl(base + idx * 8);
+	mul =  extract_pll_n(val) + 1;
+	div = (extract_pll_m(val) + 1) << extract_pll_k(val);
 	clk_register_fixed_factor(NULL, name, parent, 0, mul, div);
+	if (extract_pll_isel(val) != 1)
+		panic("%s: input not set to XTAL_IN\n", name);
 }
 
-static int __init get_div(void __iomem *base)
+static void __init make_cd(int idx, void __iomem *base)
 {
-	u8 sysclk_tab[16] = { 2, 4, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4 };
-	int idx = DIV_INDEX(readl_relaxed(base + LEGACY_DIV));
+	char name[8];
+	u32 val, mul, div;
 
-	return sysclk_tab[idx];
+	sprintf(name, "cd%d", idx);
+	val = readl(base + idx * 8);
+	mul =  1 << 27;
+	div = (2 << 27) + val;
+	clk_register_fixed_factor(NULL, name, "pll2", 0, mul, div);
+	if (val > 0xf0000000)
+		panic("%s: unsupported divider %x\n", name, val);
 }
 
 static void __init tango4_clkgen_setup(struct device_node *np)
 {
-	int div, ret;
+	struct clk **pp = clk_data.clks;
 	void __iomem *base = of_iomap(np, 0);
 	const char *parent = of_clk_get_parent_name(np, 0);
 
 	if (!base)
-		panic("%s: invalid address\n", np->full_name);
+		panic("%s: invalid address\n", np->name);
+
+	if (readl(base + CPUCLK_DIV) & DIV_BYPASS)
+		panic("%s: unsupported cpuclk setup\n", np->name);
+
+	if (readl(base + SYSCLK_DIV) & DIV_BYPASS)
+		panic("%s: unsupported sysclk setup\n", np->name);
+
+	writel(0x100, base + CPUCLK_DIV); /* disable frequency ramping */
 
 	make_pll(0, parent, base);
 	make_pll(1, parent, base);
+	make_pll(2, parent, base);
+	make_cd(2, base + 0x80);
+	make_cd(6, base + 0x80);
 
-	out[0] = clk_register_divider(NULL, "cpuclk", "pll0", 0,
-			base + CPUCLK_CTRL, 8, 8, CLK_DIVIDER_ONE_BASED, NULL);
+	pp[0] = clk_register_divider(NULL, "cpu_clk", "pll0", 0,
+			base + CPUCLK_DIV, 8, 8, CLK_DIVIDER_ONE_BASED, NULL);
+	pp[1] = clk_register_fixed_factor(NULL, "sys_clk", "pll1", 0, 1, 4);
+	pp[2] = clk_register_fixed_factor(NULL,  "usb_clk", "cd2", 0, 1, 2);
+	pp[3] = clk_register_fixed_factor(NULL, "sdio_clk", "cd6", 0, 1, 2);
 
-	div = readl_relaxed(base + SYSCLK_CTRL) & BIT(23) ? get_div(base) : 4;
-	out[1] = clk_register_fixed_factor(NULL, "sysclk", "pll1", 0, 1, div);
+	if (IS_ERR(pp[0]) || IS_ERR(pp[1]) || IS_ERR(pp[2]) || IS_ERR(pp[3]))
+		panic("%s: clk registration failed\n", np->name);
 
-	ret = of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
-	if (IS_ERR(out[0]) || IS_ERR(out[1]) || ret < 0)
-		panic("%s: clk registration failed\n", np->full_name);
+	if (of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data))
+		panic("%s: clk provider registration failed\n", np->name);
 }
 CLK_OF_DECLARE(tango4_clkgen, "sigma,tango4-clkgen", tango4_clkgen_setup);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/clk-twl6040.c linux-libre-4.7-gnu/drivers/clk/clk-twl6040.c
--- linux-libre-4.6-gnu/drivers/clk/clk-twl6040.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/clk-twl6040.c	2016-07-24 15:23:50.000000000 -0400
@@ -74,7 +74,6 @@ static const struct clk_ops twl6040_mcpd
 static struct clk_init_data wm831x_clkout_init = {
 	.name = "mcpdm_fclk",
 	.ops = &twl6040_mcpdm_ops,
-	.flags = CLK_IS_ROOT,
 };
 
 static int twl6040_clk_probe(struct platform_device *pdev)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/clk-wm831x.c linux-libre-4.7-gnu/drivers/clk/clk-wm831x.c
--- linux-libre-4.6-gnu/drivers/clk/clk-wm831x.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/clk-wm831x.c	2016-07-24 15:23:50.000000000 -0400
@@ -58,7 +58,6 @@ static const struct clk_ops wm831x_xtal_
 static struct clk_init_data wm831x_xtal_init = {
 	.name = "xtal",
 	.ops = &wm831x_xtal_ops,
-	.flags = CLK_IS_ROOT,
 };
 
 static const unsigned long wm831x_fll_auto_rates[] = {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/clk-xgene.c linux-libre-4.7-gnu/drivers/clk/clk-xgene.c
--- linux-libre-4.6-gnu/drivers/clk/clk-xgene.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/clk-xgene.c	2016-07-24 15:23:50.000000000 -0400
@@ -198,7 +198,7 @@ static void xgene_pllclk_init(struct dev
 	of_property_read_string(np, "clock-output-names", &clk_name);
 	clk = xgene_register_clk_pll(NULL,
 			clk_name, of_clk_get_parent_name(np, 0),
-			CLK_IS_ROOT, reg, 0, pll_type, &clk_lock,
+			0, reg, 0, pll_type, &clk_lock,
 			version);
 	if (!IS_ERR(clk)) {
 		of_clk_add_provider(np, of_clk_src_simple_get, clk);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/hisilicon/clk.c linux-libre-4.7-gnu/drivers/clk/hisilicon/clk.c
--- linux-libre-4.6-gnu/drivers/clk/hisilicon/clk.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/hisilicon/clk.c	2016-07-24 15:23:50.000000000 -0400
@@ -37,7 +37,7 @@
 
 static DEFINE_SPINLOCK(hisi_clk_lock);
 
-struct hisi_clock_data __init *hisi_clk_init(struct device_node *np,
+struct hisi_clock_data *hisi_clk_init(struct device_node *np,
 					     int nr_clks)
 {
 	struct hisi_clock_data *clk_data;
@@ -71,8 +71,9 @@ err_data:
 err:
 	return NULL;
 }
+EXPORT_SYMBOL_GPL(hisi_clk_init);
 
-void __init hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *clks,
+void hisi_clk_register_fixed_rate(const struct hisi_fixed_rate_clock *clks,
 					 int nums, struct hisi_clock_data *data)
 {
 	struct clk *clk;
@@ -91,8 +92,9 @@ void __init hisi_clk_register_fixed_rate
 		data->clk_data.clks[clks[i].id] = clk;
 	}
 }
+EXPORT_SYMBOL_GPL(hisi_clk_register_fixed_rate);
 
-void __init hisi_clk_register_fixed_factor(struct hisi_fixed_factor_clock *clks,
+void hisi_clk_register_fixed_factor(const struct hisi_fixed_factor_clock *clks,
 					   int nums,
 					   struct hisi_clock_data *data)
 {
@@ -112,8 +114,9 @@ void __init hisi_clk_register_fixed_fact
 		data->clk_data.clks[clks[i].id] = clk;
 	}
 }
+EXPORT_SYMBOL_GPL(hisi_clk_register_fixed_factor);
 
-void __init hisi_clk_register_mux(struct hisi_mux_clock *clks,
+void hisi_clk_register_mux(const struct hisi_mux_clock *clks,
 				  int nums, struct hisi_clock_data *data)
 {
 	struct clk *clk;
@@ -141,8 +144,9 @@ void __init hisi_clk_register_mux(struct
 		data->clk_data.clks[clks[i].id] = clk;
 	}
 }
+EXPORT_SYMBOL_GPL(hisi_clk_register_mux);
 
-void __init hisi_clk_register_divider(struct hisi_divider_clock *clks,
+void hisi_clk_register_divider(const struct hisi_divider_clock *clks,
 				      int nums, struct hisi_clock_data *data)
 {
 	struct clk *clk;
@@ -170,8 +174,9 @@ void __init hisi_clk_register_divider(st
 		data->clk_data.clks[clks[i].id] = clk;
 	}
 }
+EXPORT_SYMBOL_GPL(hisi_clk_register_divider);
 
-void __init hisi_clk_register_gate(struct hisi_gate_clock *clks,
+void hisi_clk_register_gate(const struct hisi_gate_clock *clks,
 				       int nums, struct hisi_clock_data *data)
 {
 	struct clk *clk;
@@ -198,8 +203,9 @@ void __init hisi_clk_register_gate(struc
 		data->clk_data.clks[clks[i].id] = clk;
 	}
 }
+EXPORT_SYMBOL_GPL(hisi_clk_register_gate);
 
-void __init hisi_clk_register_gate_sep(struct hisi_gate_clock *clks,
+void hisi_clk_register_gate_sep(const struct hisi_gate_clock *clks,
 				       int nums, struct hisi_clock_data *data)
 {
 	struct clk *clk;
@@ -226,8 +232,9 @@ void __init hisi_clk_register_gate_sep(s
 		data->clk_data.clks[clks[i].id] = clk;
 	}
 }
+EXPORT_SYMBOL_GPL(hisi_clk_register_gate_sep);
 
-void __init hi6220_clk_register_divider(struct hi6220_divider_clock *clks,
+void __init hi6220_clk_register_divider(const struct hi6220_divider_clock *clks,
 					int nums, struct hisi_clock_data *data)
 {
 	struct clk *clk;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/hisilicon/clk.h linux-libre-4.7-gnu/drivers/clk/hisilicon/clk.h
--- linux-libre-4.6-gnu/drivers/clk/hisilicon/clk.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/hisilicon/clk.h	2016-07-24 15:23:50.000000000 -0400
@@ -111,18 +111,18 @@ struct clk *hi6220_register_clkdiv(struc
 	u8 shift, u8 width, u32 mask_bit, spinlock_t *lock);
 
 struct hisi_clock_data *hisi_clk_init(struct device_node *, int);
-void hisi_clk_register_fixed_rate(struct hisi_fixed_rate_clock *,
+void hisi_clk_register_fixed_rate(const struct hisi_fixed_rate_clock *,
 				int, struct hisi_clock_data *);
-void hisi_clk_register_fixed_factor(struct hisi_fixed_factor_clock *,
+void hisi_clk_register_fixed_factor(const struct hisi_fixed_factor_clock *,
 				int, struct hisi_clock_data *);
-void hisi_clk_register_mux(struct hisi_mux_clock *, int,
+void hisi_clk_register_mux(const struct hisi_mux_clock *, int,
 				struct hisi_clock_data *);
-void hisi_clk_register_divider(struct hisi_divider_clock *,
+void hisi_clk_register_divider(const struct hisi_divider_clock *,
 				int, struct hisi_clock_data *);
-void hisi_clk_register_gate(struct hisi_gate_clock *,
+void hisi_clk_register_gate(const struct hisi_gate_clock *,
 				int, struct hisi_clock_data *);
-void hisi_clk_register_gate_sep(struct hisi_gate_clock *,
+void hisi_clk_register_gate_sep(const struct hisi_gate_clock *,
 				int, struct hisi_clock_data *);
-void hi6220_clk_register_divider(struct hi6220_divider_clock *,
+void hi6220_clk_register_divider(const struct hi6220_divider_clock *,
 				int, struct hisi_clock_data *);
 #endif	/* __HISI_CLK_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/hisilicon/clk-hi3519.c linux-libre-4.7-gnu/drivers/clk/hisilicon/clk-hi3519.c
--- linux-libre-4.6-gnu/drivers/clk/hisilicon/clk-hi3519.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/clk/hisilicon/clk-hi3519.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,131 @@
+/*
+ * Hi3519 Clock Driver
+ *
+ * Copyright (c) 2015-2016 HiSilicon Technologies Co., Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <dt-bindings/clock/hi3519-clock.h>
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include "clk.h"
+#include "reset.h"
+
+#define HI3519_INNER_CLK_OFFSET	64
+#define HI3519_FIXED_24M	65
+#define HI3519_FIXED_50M	66
+#define HI3519_FIXED_75M	67
+#define HI3519_FIXED_125M	68
+#define HI3519_FIXED_150M	69
+#define HI3519_FIXED_200M	70
+#define HI3519_FIXED_250M	71
+#define HI3519_FIXED_300M	72
+#define HI3519_FIXED_400M	73
+#define HI3519_FMC_MUX		74
+
+#define HI3519_NR_CLKS		128
+
+static const struct hisi_fixed_rate_clock hi3519_fixed_rate_clks[] = {
+	{ HI3519_FIXED_24M, "24m", NULL, 0, 24000000, },
+	{ HI3519_FIXED_50M, "50m", NULL, 0, 50000000, },
+	{ HI3519_FIXED_75M, "75m", NULL, 0, 75000000, },
+	{ HI3519_FIXED_125M, "125m", NULL, 0, 125000000, },
+	{ HI3519_FIXED_150M, "150m", NULL, 0, 150000000, },
+	{ HI3519_FIXED_200M, "200m", NULL, 0, 200000000, },
+	{ HI3519_FIXED_250M, "250m", NULL, 0, 250000000, },
+	{ HI3519_FIXED_300M, "300m", NULL, 0, 300000000, },
+	{ HI3519_FIXED_400M, "400m", NULL, 0, 400000000, },
+};
+
+static const char *const fmc_mux_p[] = {
+		"24m", "75m", "125m", "150m", "200m", "250m", "300m", "400m", };
+static u32 fmc_mux_table[] = {0, 1, 2, 3, 4, 5, 6, 7};
+
+static const struct hisi_mux_clock hi3519_mux_clks[] = {
+	{ HI3519_FMC_MUX, "fmc_mux", fmc_mux_p, ARRAY_SIZE(fmc_mux_p),
+		CLK_SET_RATE_PARENT, 0xc0, 2, 3, 0, fmc_mux_table, },
+};
+
+static const struct hisi_gate_clock hi3519_gate_clks[] = {
+	{ HI3519_FMC_CLK, "clk_fmc", "fmc_mux",
+		CLK_SET_RATE_PARENT, 0xc0, 1, 0, },
+	{ HI3519_UART0_CLK, "clk_uart0", "24m",
+		CLK_SET_RATE_PARENT, 0xe4, 20, 0, },
+	{ HI3519_UART1_CLK, "clk_uart1", "24m",
+		CLK_SET_RATE_PARENT, 0xe4, 21, 0, },
+	{ HI3519_UART2_CLK, "clk_uart2", "24m",
+		CLK_SET_RATE_PARENT, 0xe4, 22, 0, },
+	{ HI3519_UART3_CLK, "clk_uart3", "24m",
+		CLK_SET_RATE_PARENT, 0xe4, 23, 0, },
+	{ HI3519_UART4_CLK, "clk_uart4", "24m",
+		CLK_SET_RATE_PARENT, 0xe4, 24, 0, },
+	{ HI3519_SPI0_CLK, "clk_spi0", "50m",
+		CLK_SET_RATE_PARENT, 0xe4, 16, 0, },
+	{ HI3519_SPI1_CLK, "clk_spi1", "50m",
+		CLK_SET_RATE_PARENT, 0xe4, 17, 0, },
+	{ HI3519_SPI2_CLK, "clk_spi2", "50m",
+		CLK_SET_RATE_PARENT, 0xe4, 18, 0, },
+};
+
+static int hi3519_clk_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct hisi_clock_data *clk_data;
+	struct hisi_reset_controller *rstc;
+
+	rstc = hisi_reset_init(np);
+	if (!rstc)
+		return -ENOMEM;
+
+	clk_data = hisi_clk_init(np, HI3519_NR_CLKS);
+	if (!clk_data) {
+		hisi_reset_exit(rstc);
+		return -ENODEV;
+	}
+
+	hisi_clk_register_fixed_rate(hi3519_fixed_rate_clks,
+				     ARRAY_SIZE(hi3519_fixed_rate_clks),
+				     clk_data);
+	hisi_clk_register_mux(hi3519_mux_clks, ARRAY_SIZE(hi3519_mux_clks),
+					clk_data);
+	hisi_clk_register_gate(hi3519_gate_clks,
+			ARRAY_SIZE(hi3519_gate_clks), clk_data);
+
+	return 0;
+}
+
+static const struct of_device_id hi3519_clk_match_table[] = {
+	{ .compatible = "hisilicon,hi3519-crg" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, hi3519_clk_match_table);
+
+static struct platform_driver hi3519_clk_driver = {
+	.probe          = hi3519_clk_probe,
+	.driver         = {
+		.name   = "hi3519-clk",
+		.of_match_table = hi3519_clk_match_table,
+	},
+};
+
+static int __init hi3519_clk_init(void)
+{
+	return platform_driver_register(&hi3519_clk_driver);
+}
+core_initcall(hi3519_clk_init);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("HiSilicon Hi3519 Clock Driver");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/hisilicon/Kconfig linux-libre-4.7-gnu/drivers/clk/hisilicon/Kconfig
--- linux-libre-4.6-gnu/drivers/clk/hisilicon/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/hisilicon/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -1,3 +1,11 @@
+config COMMON_CLK_HI3519
+	tristate "Hi3519 Clock Driver"
+	depends on ARCH_HISI || COMPILE_TEST
+	select RESET_HISI
+	default ARCH_HISI
+	help
+	  Build the clock driver for hi3519.
+
 config COMMON_CLK_HI6220
 	bool "Hi6220 Clock Driver"
 	depends on ARCH_HISI || COMPILE_TEST
@@ -5,6 +13,13 @@ config COMMON_CLK_HI6220
 	help
 	  Build the Hisilicon Hi6220 clock driver based on the common clock framework.
 
+config RESET_HISI
+	bool "HiSilicon Reset Controller Driver"
+	depends on ARCH_HISI || COMPILE_TEST
+	select RESET_CONTROLLER
+	help
+	  Build reset controller driver for HiSilicon device chipsets.
+
 config STUB_CLK_HI6220
 	bool "Hi6220 Stub Clock Driver"
 	depends on COMMON_CLK_HI6220 && MAILBOX
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/hisilicon/Makefile linux-libre-4.7-gnu/drivers/clk/hisilicon/Makefile
--- linux-libre-4.6-gnu/drivers/clk/hisilicon/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/hisilicon/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -7,5 +7,7 @@ obj-y	+= clk.o clkgate-separated.o clkdi
 obj-$(CONFIG_ARCH_HI3xxx)	+= clk-hi3620.o
 obj-$(CONFIG_ARCH_HIP04)	+= clk-hip04.o
 obj-$(CONFIG_ARCH_HIX5HD2)	+= clk-hix5hd2.o
+obj-$(CONFIG_COMMON_CLK_HI3519)	+= clk-hi3519.o
 obj-$(CONFIG_COMMON_CLK_HI6220)	+= clk-hi6220.o
+obj-$(CONFIG_RESET_HISI)	+= reset.o
 obj-$(CONFIG_STUB_CLK_HI6220)	+= clk-hi6220-stub.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/hisilicon/reset.c linux-libre-4.7-gnu/drivers/clk/hisilicon/reset.c
--- linux-libre-4.6-gnu/drivers/clk/hisilicon/reset.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/clk/hisilicon/reset.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,134 @@
+/*
+ * Hisilicon Reset Controller Driver
+ *
+ * Copyright (c) 2015-2016 HiSilicon Technologies Co., Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include "reset.h"
+
+#define	HISI_RESET_BIT_MASK	0x1f
+#define	HISI_RESET_OFFSET_SHIFT	8
+#define	HISI_RESET_OFFSET_MASK	0xffff00
+
+struct hisi_reset_controller {
+	spinlock_t	lock;
+	void __iomem	*membase;
+	struct reset_controller_dev	rcdev;
+};
+
+
+#define to_hisi_reset_controller(rcdev)  \
+	container_of(rcdev, struct hisi_reset_controller, rcdev)
+
+static int hisi_reset_of_xlate(struct reset_controller_dev *rcdev,
+			const struct of_phandle_args *reset_spec)
+{
+	u32 offset;
+	u8 bit;
+
+	offset = (reset_spec->args[0] << HISI_RESET_OFFSET_SHIFT)
+		& HISI_RESET_OFFSET_MASK;
+	bit = reset_spec->args[1] & HISI_RESET_BIT_MASK;
+
+	return (offset | bit);
+}
+
+static int hisi_reset_assert(struct reset_controller_dev *rcdev,
+			      unsigned long id)
+{
+	struct hisi_reset_controller *rstc = to_hisi_reset_controller(rcdev);
+	unsigned long flags;
+	u32 offset, reg;
+	u8 bit;
+
+	offset = (id & HISI_RESET_OFFSET_MASK) >> HISI_RESET_OFFSET_SHIFT;
+	bit = id & HISI_RESET_BIT_MASK;
+
+	spin_lock_irqsave(&rstc->lock, flags);
+
+	reg = readl(rstc->membase + offset);
+	writel(reg | BIT(bit), rstc->membase + offset);
+
+	spin_unlock_irqrestore(&rstc->lock, flags);
+
+	return 0;
+}
+
+static int hisi_reset_deassert(struct reset_controller_dev *rcdev,
+				unsigned long id)
+{
+	struct hisi_reset_controller *rstc = to_hisi_reset_controller(rcdev);
+	unsigned long flags;
+	u32 offset, reg;
+	u8 bit;
+
+	offset = (id & HISI_RESET_OFFSET_MASK) >> HISI_RESET_OFFSET_SHIFT;
+	bit = id & HISI_RESET_BIT_MASK;
+
+	spin_lock_irqsave(&rstc->lock, flags);
+
+	reg = readl(rstc->membase + offset);
+	writel(reg & ~BIT(bit), rstc->membase + offset);
+
+	spin_unlock_irqrestore(&rstc->lock, flags);
+
+	return 0;
+}
+
+static const struct reset_control_ops hisi_reset_ops = {
+	.assert		= hisi_reset_assert,
+	.deassert	= hisi_reset_deassert,
+};
+
+struct hisi_reset_controller *hisi_reset_init(struct device_node *np)
+{
+	struct hisi_reset_controller *rstc;
+
+	rstc = kzalloc(sizeof(*rstc), GFP_KERNEL);
+	if (!rstc)
+		return NULL;
+
+	rstc->membase = of_iomap(np, 0);
+	if (!rstc->membase) {
+		kfree(rstc);
+		return NULL;
+	}
+
+	spin_lock_init(&rstc->lock);
+
+	rstc->rcdev.owner = THIS_MODULE;
+	rstc->rcdev.ops = &hisi_reset_ops;
+	rstc->rcdev.of_node = np;
+	rstc->rcdev.of_reset_n_cells = 2;
+	rstc->rcdev.of_xlate = hisi_reset_of_xlate;
+	reset_controller_register(&rstc->rcdev);
+
+	return rstc;
+}
+EXPORT_SYMBOL_GPL(hisi_reset_init);
+
+void hisi_reset_exit(struct hisi_reset_controller *rstc)
+{
+	reset_controller_unregister(&rstc->rcdev);
+	iounmap(rstc->membase);
+	kfree(rstc);
+}
+EXPORT_SYMBOL_GPL(hisi_reset_exit);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/hisilicon/reset.h linux-libre-4.7-gnu/drivers/clk/hisilicon/reset.h
--- linux-libre-4.6-gnu/drivers/clk/hisilicon/reset.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/clk/hisilicon/reset.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015 HiSilicon Technologies Co., Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef	__HISI_RESET_H
+#define	__HISI_RESET_H
+
+struct device_node;
+struct hisi_reset_controller;
+
+#ifdef CONFIG_RESET_CONTROLLER
+struct hisi_reset_controller *hisi_reset_init(struct device_node *np);
+void hisi_reset_exit(struct hisi_reset_controller *rstc);
+#else
+static inline hisi_reset_controller *hisi_reset_init(struct device_node *np)
+{
+	return 0;
+}
+static inline void hisi_reset_exit(struct hisi_reset_controller *rstc)
+{}
+#endif
+
+#endif	/* __HISI_RESET_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/imx/clk-gate2.c linux-libre-4.7-gnu/drivers/clk/imx/clk-gate2.c
--- linux-libre-4.6-gnu/drivers/clk/imx/clk-gate2.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/imx/clk-gate2.c	2016-07-24 15:23:50.000000000 -0400
@@ -31,6 +31,7 @@ struct clk_gate2 {
 	struct clk_hw hw;
 	void __iomem	*reg;
 	u8		bit_idx;
+	u8		cgr_val;
 	u8		flags;
 	spinlock_t	*lock;
 	unsigned int	*share_count;
@@ -50,7 +51,8 @@ static int clk_gate2_enable(struct clk_h
 		goto out;
 
 	reg = readl(gate->reg);
-	reg |= 3 << gate->bit_idx;
+	reg &= ~(3 << gate->bit_idx);
+	reg |= gate->cgr_val << gate->bit_idx;
 	writel(reg, gate->reg);
 
 out:
@@ -125,7 +127,7 @@ static struct clk_ops clk_gate2_ops = {
 
 struct clk *clk_register_gate2(struct device *dev, const char *name,
 		const char *parent_name, unsigned long flags,
-		void __iomem *reg, u8 bit_idx,
+		void __iomem *reg, u8 bit_idx, u8 cgr_val,
 		u8 clk_gate2_flags, spinlock_t *lock,
 		unsigned int *share_count)
 {
@@ -140,6 +142,7 @@ struct clk *clk_register_gate2(struct de
 	/* struct clk_gate2 assignments */
 	gate->reg = reg;
 	gate->bit_idx = bit_idx;
+	gate->cgr_val = cgr_val;
 	gate->flags = clk_gate2_flags;
 	gate->lock = lock;
 	gate->share_count = share_count;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/imx/clk.h linux-libre-4.7-gnu/drivers/clk/imx/clk.h
--- linux-libre-4.6-gnu/drivers/clk/imx/clk.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/imx/clk.h	2016-07-24 15:23:50.000000000 -0400
@@ -41,7 +41,7 @@ struct clk *imx_clk_pllv3(enum imx_pllv3
 
 struct clk *clk_register_gate2(struct device *dev, const char *name,
 		const char *parent_name, unsigned long flags,
-		void __iomem *reg, u8 bit_idx,
+		void __iomem *reg, u8 bit_idx, u8 cgr_val,
 		u8 clk_gate_flags, spinlock_t *lock,
 		unsigned int *share_count);
 
@@ -55,7 +55,7 @@ static inline struct clk *imx_clk_gate2(
 		void __iomem *reg, u8 shift)
 {
 	return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
-			shift, 0, &imx_ccm_lock, NULL);
+			shift, 0x3, 0, &imx_ccm_lock, NULL);
 }
 
 static inline struct clk *imx_clk_gate2_shared(const char *name,
@@ -63,7 +63,14 @@ static inline struct clk *imx_clk_gate2_
 		unsigned int *share_count)
 {
 	return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
-			shift, 0, &imx_ccm_lock, share_count);
+			shift, 0x3, 0, &imx_ccm_lock, share_count);
+}
+
+static inline struct clk *imx_clk_gate2_cgr(const char *name, const char *parent,
+		void __iomem *reg, u8 shift, u8 cgr_val)
+{
+	return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
+			shift, cgr_val, 0, &imx_ccm_lock, NULL);
 }
 
 struct clk *imx_clk_pfd(const char *name, const char *parent_name,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/imx/clk-imx35.c linux-libre-4.7-gnu/drivers/clk/imx/clk-imx35.c
--- linux-libre-4.6-gnu/drivers/clk/imx/clk-imx35.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/imx/clk-imx35.c	2016-07-24 15:23:50.000000000 -0400
@@ -66,7 +66,7 @@ static const char *std_sel[] = {"ppll",
 static const char *ipg_per_sel[] = {"ahb_per_div", "arm_per_div"};
 
 enum mx35_clks {
-	ckih, ckil, mpll, ppll, mpll_075, arm, hsp, hsp_div, hsp_sel, ahb, ipg,
+	ckih, mpll, ppll, mpll_075, arm, hsp, hsp_div, hsp_sel, ahb, ipg,
 	arm_per_div, ahb_per_div, ipg_per, uart_sel, uart_div, esdhc_sel,
 	esdhc1_div, esdhc2_div, esdhc3_div, spdif_sel, spdif_div_pre,
 	spdif_div_post, ssi_sel, ssi1_div_pre, ssi1_div_post, ssi2_div_pre,
@@ -79,7 +79,7 @@ enum mx35_clks {
 	rtc_gate, rtic_gate, scc_gate, sdma_gate, spba_gate, spdif_gate,
 	ssi1_gate, ssi2_gate, uart1_gate, uart2_gate, uart3_gate, usbotg_gate,
 	wdog_gate, max_gate, admux_gate, csi_gate, csi_div, csi_sel, iim_gate,
-	gpu2d_gate, clk_max
+	gpu2d_gate, ckil, clk_max
 };
 
 static struct clk *clk[clk_max];
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/imx/clk-imx6sx.c linux-libre-4.7-gnu/drivers/clk/imx/clk-imx6sx.c
--- linux-libre-4.6-gnu/drivers/clk/imx/clk-imx6sx.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/imx/clk-imx6sx.c	2016-07-24 15:23:50.000000000 -0400
@@ -134,6 +134,8 @@ static u32 share_count_esai;
 static u32 share_count_ssi1;
 static u32 share_count_ssi2;
 static u32 share_count_ssi3;
+static u32 share_count_sai1;
+static u32 share_count_sai2;
 
 static struct clk ** const uart_clks[] __initconst = {
 	&clks[IMX6SX_CLK_UART_IPG],
@@ -469,10 +471,10 @@ static void __init imx6sx_clocks_init(st
 	clks[IMX6SX_CLK_SSI3]         = imx_clk_gate2_shared("ssi3",          "ssi3_podf",  base + 0x7c, 22, &share_count_ssi3);
 	clks[IMX6SX_CLK_UART_IPG]     = imx_clk_gate2("uart_ipg",      "ipg",               base + 0x7c, 24);
 	clks[IMX6SX_CLK_UART_SERIAL]  = imx_clk_gate2("uart_serial",   "uart_podf",         base + 0x7c, 26);
-	clks[IMX6SX_CLK_SAI1_IPG]     = imx_clk_gate2("sai1_ipg",      "ipg",               base + 0x7c, 28);
-	clks[IMX6SX_CLK_SAI2_IPG]     = imx_clk_gate2("sai2_ipg",      "ipg",               base + 0x7c, 30);
-	clks[IMX6SX_CLK_SAI1]         = imx_clk_gate2("sai1",          "ssi1_podf",         base + 0x7c, 28);
-	clks[IMX6SX_CLK_SAI2]         = imx_clk_gate2("sai2",          "ssi2_podf",         base + 0x7c, 30);
+	clks[IMX6SX_CLK_SAI1_IPG]     = imx_clk_gate2_shared("sai1_ipg", "ipg",             base + 0x7c, 28, &share_count_sai1);
+	clks[IMX6SX_CLK_SAI2_IPG]     = imx_clk_gate2_shared("sai2_ipg", "ipg",             base + 0x7c, 30, &share_count_sai2);
+	clks[IMX6SX_CLK_SAI1]         = imx_clk_gate2_shared("sai1",	"ssi1_podf",        base + 0x7c, 28, &share_count_sai1);
+	clks[IMX6SX_CLK_SAI2]         = imx_clk_gate2_shared("sai2",	"ssi2_podf",        base + 0x7c, 30, &share_count_sai2);
 
 	/* CCGR6 */
 	clks[IMX6SX_CLK_USBOH3]       = imx_clk_gate2("usboh3",        "ipg",               base + 0x80, 0);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/imx/clk-imx7d.c linux-libre-4.7-gnu/drivers/clk/imx/clk-imx7d.c
--- linux-libre-4.6-gnu/drivers/clk/imx/clk-imx7d.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/imx/clk-imx7d.c	2016-07-24 15:23:50.000000000 -0400
@@ -56,7 +56,7 @@ static const char *nand_usdhc_bus_sel[]
 	"pll_sys_pfd2_135m_clk", "pll_sys_pfd6_clk", "pll_enet_250m_clk",
 	"pll_audio_main_clk", };
 
-static const char *ahb_channel_sel[] = { "osc", "pll_sys_pfd2_135m_clk",
+static const char *ahb_channel_sel[] = { "osc", "pll_sys_pfd2_270m_clk",
 	"pll_dram_533m_clk", "pll_sys_pfd0_392m_clk",
 	"pll_enet_125m_clk", "pll_usb_main_clk", "pll_audio_main_clk",
 	"pll_video_main_clk", };
@@ -342,7 +342,7 @@ static const char *clko1_sel[] = { "osc"
 
 static const char *clko2_sel[] = { "osc", "pll_sys_main_240m_clk",
 	"pll_sys_pfd0_392m_clk", "pll_sys_pfd1_166m_clk", "pll_sys_pfd4_clk",
-	"pll_audio_main_clk", "pll_video_main_clk", "osc_32k_clk", };
+	"pll_audio_main_clk", "pll_video_main_clk", "ckil", };
 
 static const char *lvds1_sel[] = { "pll_arm_main_clk",
 	"pll_sys_main_clk", "pll_sys_pfd0_392m_clk", "pll_sys_pfd1_332m_clk",
@@ -382,6 +382,7 @@ static void __init imx7d_clocks_init(str
 
 	clks[IMX7D_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
 	clks[IMX7D_OSC_24M_CLK] = of_clk_get_by_name(ccm_node, "osc");
+	clks[IMX7D_CKIL] = of_clk_get_by_name(ccm_node, "ckil");
 
 	np = of_find_compatible_node(NULL, NULL, "fsl,imx7d-anatop");
 	base = of_iomap(np, 0);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/imx/clk-pllv3.c linux-libre-4.7-gnu/drivers/clk/imx/clk-pllv3.c
--- linux-libre-4.6-gnu/drivers/clk/imx/clk-pllv3.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/imx/clk-pllv3.c	2016-07-24 15:23:50.000000000 -0400
@@ -44,6 +44,7 @@ struct clk_pllv3 {
 	u32		powerdown;
 	u32		div_mask;
 	u32		div_shift;
+	unsigned long	ref_clock;
 };
 
 #define to_clk_pllv3(_hw) container_of(_hw, struct clk_pllv3, hw)
@@ -286,7 +287,9 @@ static const struct clk_ops clk_pllv3_av
 static unsigned long clk_pllv3_enet_recalc_rate(struct clk_hw *hw,
 						unsigned long parent_rate)
 {
-	return 500000000;
+	struct clk_pllv3 *pll = to_clk_pllv3(hw);
+
+	return pll->ref_clock;
 }
 
 static const struct clk_ops clk_pllv3_enet_ops = {
@@ -326,7 +329,11 @@ struct clk *imx_clk_pllv3(enum imx_pllv3
 		break;
 	case IMX_PLLV3_ENET_IMX7:
 		pll->powerdown = IMX7_ENET_PLL_POWER;
+		pll->ref_clock = 1000000000;
+		ops = &clk_pllv3_enet_ops;
+		break;
 	case IMX_PLLV3_ENET:
+		pll->ref_clock = 500000000;
 		ops = &clk_pllv3_enet_ops;
 		break;
 	default:
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/imx/clk-vf610.c linux-libre-4.7-gnu/drivers/clk/imx/clk-vf610.c
--- linux-libre-4.6-gnu/drivers/clk/imx/clk-vf610.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/imx/clk-vf610.c	2016-07-24 15:23:50.000000000 -0400
@@ -10,6 +10,7 @@
 
 #include <linux/of_address.h>
 #include <linux/clk.h>
+#include <linux/syscore_ops.h>
 #include <dt-bindings/clock/vf610-clock.h>
 
 #include "clk.h"
@@ -40,6 +41,7 @@
 #define CCM_CCGR9		(ccm_base + 0x64)
 #define CCM_CCGR10		(ccm_base + 0x68)
 #define CCM_CCGR11		(ccm_base + 0x6c)
+#define CCM_CCGRx(x)		(CCM_CCGR0 + (x) * 4)
 #define CCM_CMEOR0		(ccm_base + 0x70)
 #define CCM_CMEOR1		(ccm_base + 0x74)
 #define CCM_CMEOR2		(ccm_base + 0x78)
@@ -115,10 +117,19 @@ static struct clk_div_table pll4_audio_d
 static struct clk *clk[VF610_CLK_END];
 static struct clk_onecell_data clk_data;
 
+static u32 cscmr1;
+static u32 cscmr2;
+static u32 cscdr1;
+static u32 cscdr2;
+static u32 cscdr3;
+static u32 ccgr[12];
+
 static unsigned int const clks_init_on[] __initconst = {
 	VF610_CLK_SYS_BUS,
 	VF610_CLK_DDR_SEL,
 	VF610_CLK_DAP,
+	VF610_CLK_DDRMC,
+	VF610_CLK_WKPU,
 };
 
 static struct clk * __init vf610_get_fixed_clock(
@@ -132,6 +143,43 @@ static struct clk * __init vf610_get_fix
 	return clk;
 };
 
+static int vf610_clk_suspend(void)
+{
+	int i;
+
+	cscmr1 = readl_relaxed(CCM_CSCMR1);
+	cscmr2 = readl_relaxed(CCM_CSCMR2);
+
+	cscdr1 = readl_relaxed(CCM_CSCDR1);
+	cscdr2 = readl_relaxed(CCM_CSCDR2);
+	cscdr3 = readl_relaxed(CCM_CSCDR3);
+
+	for (i = 0; i < 12; i++)
+		ccgr[i] = readl_relaxed(CCM_CCGRx(i));
+
+	return 0;
+}
+
+static void vf610_clk_resume(void)
+{
+	int i;
+
+	writel_relaxed(cscmr1, CCM_CSCMR1);
+	writel_relaxed(cscmr2, CCM_CSCMR2);
+
+	writel_relaxed(cscdr1, CCM_CSCDR1);
+	writel_relaxed(cscdr2, CCM_CSCDR2);
+	writel_relaxed(cscdr3, CCM_CSCDR3);
+
+	for (i = 0; i < 12; i++)
+		writel_relaxed(ccgr[i], CCM_CCGRx(i));
+}
+
+static struct syscore_ops vf610_clk_syscore_ops = {
+	.suspend = vf610_clk_suspend,
+	.resume = vf610_clk_resume,
+};
+
 static void __init vf610_clocks_init(struct device_node *ccm_node)
 {
 	struct device_node *np;
@@ -233,6 +281,9 @@ static void __init vf610_clocks_init(str
 	clk[VF610_CLK_PLL4_MAIN_DIV] = clk_register_divider_table(NULL, "pll4_audio_div", "pll4_audio", 0, CCM_CACRR, 6, 3, 0, pll4_audio_div_table, &imx_ccm_lock);
 	clk[VF610_CLK_PLL6_MAIN_DIV] = imx_clk_divider("pll6_video_div", "pll6_video", CCM_CACRR, 21, 1);
 
+	clk[VF610_CLK_DDRMC] = imx_clk_gate2_cgr("ddrmc", "ddr_sel", CCM_CCGR6, CCM_CCGRx_CGn(14), 0x2);
+	clk[VF610_CLK_WKPU] = imx_clk_gate2_cgr("wkpu", "ipg_bus", CCM_CCGR4, CCM_CCGRx_CGn(10), 0x2);
+
 	clk[VF610_CLK_USBPHY0] = imx_clk_gate("usbphy0", "pll3_usb_otg", PLL3_CTRL, 6);
 	clk[VF610_CLK_USBPHY1] = imx_clk_gate("usbphy1", "pll7_usb_host", PLL7_CTRL, 6);
 
@@ -321,11 +372,14 @@ static void __init vf610_clocks_init(str
 	clk[VF610_CLK_DCU0_SEL] = imx_clk_mux("dcu0_sel", CCM_CSCMR1, 28, 1, dcu_sels, 2);
 	clk[VF610_CLK_DCU0_EN] = imx_clk_gate("dcu0_en", "dcu0_sel", CCM_CSCDR3, 19);
 	clk[VF610_CLK_DCU0_DIV] = imx_clk_divider("dcu0_div", "dcu0_en", CCM_CSCDR3, 16, 3);
-	clk[VF610_CLK_DCU0] = imx_clk_gate2("dcu0", "dcu0_div", CCM_CCGR3, CCM_CCGRx_CGn(8));
+	clk[VF610_CLK_DCU0] = imx_clk_gate2("dcu0", "ipg_bus", CCM_CCGR3, CCM_CCGRx_CGn(8));
 	clk[VF610_CLK_DCU1_SEL] = imx_clk_mux("dcu1_sel", CCM_CSCMR1, 29, 1, dcu_sels, 2);
 	clk[VF610_CLK_DCU1_EN] = imx_clk_gate("dcu1_en", "dcu1_sel", CCM_CSCDR3, 23);
 	clk[VF610_CLK_DCU1_DIV] = imx_clk_divider("dcu1_div", "dcu1_en", CCM_CSCDR3, 20, 3);
-	clk[VF610_CLK_DCU1] = imx_clk_gate2("dcu1", "dcu1_div", CCM_CCGR9, CCM_CCGRx_CGn(8));
+	clk[VF610_CLK_DCU1] = imx_clk_gate2("dcu1", "ipg_bus", CCM_CCGR9, CCM_CCGRx_CGn(8));
+
+	clk[VF610_CLK_TCON0] = imx_clk_gate2("tcon0", "platform_bus", CCM_CCGR1, CCM_CCGRx_CGn(13));
+	clk[VF610_CLK_TCON1] = imx_clk_gate2("tcon1", "platform_bus", CCM_CCGR7, CCM_CCGRx_CGn(13));
 
 	clk[VF610_CLK_ESAI_SEL] = imx_clk_mux("esai_sel", CCM_CSCMR1, 20, 2, esai_sels, 4);
 	clk[VF610_CLK_ESAI_EN] = imx_clk_gate("esai_en", "esai_sel", CCM_CSCDR2, 30);
@@ -409,6 +463,8 @@ static void __init vf610_clocks_init(str
 	for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
 		clk_prepare_enable(clk[clks_init_on[i]]);
 
+	register_syscore_ops(&vf610_clk_syscore_ops);
+
 	/* Add the clocks to provider list */
 	clk_data.clks = clk;
 	clk_data.clk_num = ARRAY_SIZE(clk);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/ingenic/cgu.c linux-libre-4.7-gnu/drivers/clk/ingenic/cgu.c
--- linux-libre-4.6-gnu/drivers/clk/ingenic/cgu.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/ingenic/cgu.c	2016-07-24 15:23:50.000000000 -0400
@@ -325,6 +325,7 @@ ingenic_clk_recalc_rate(struct clk_hw *h
 		div = (div_reg >> clk_info->div.shift) &
 		      GENMASK(clk_info->div.bits - 1, 0);
 		div += 1;
+		div *= clk_info->div.div;
 
 		rate /= div;
 	}
@@ -345,6 +346,14 @@ ingenic_clk_calc_div(const struct ingeni
 	div = min_t(unsigned, div, 1 << clk_info->div.bits);
 	div = max_t(unsigned, div, 1);
 
+	/*
+	 * If the divider value itself must be divided before being written to
+	 * the divider register, we must ensure we don't have any bits set that
+	 * would be lost as a result of doing so.
+	 */
+	div /= clk_info->div.div;
+	div *= clk_info->div.div;
+
 	return div;
 }
 
@@ -395,7 +404,7 @@ ingenic_clk_set_rate(struct clk_hw *hw,
 		/* update the divide */
 		mask = GENMASK(clk_info->div.bits - 1, 0);
 		reg &= ~(mask << clk_info->div.shift);
-		reg |= (div - 1) << clk_info->div.shift;
+		reg |= ((div / clk_info->div.div) - 1) << clk_info->div.shift;
 
 		/* clear the stop bit */
 		if (clk_info->div.stop_bit != -1)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/ingenic/cgu.h linux-libre-4.7-gnu/drivers/clk/ingenic/cgu.h
--- linux-libre-4.6-gnu/drivers/clk/ingenic/cgu.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/ingenic/cgu.h	2016-07-24 15:23:50.000000000 -0400
@@ -76,8 +76,11 @@ struct ingenic_cgu_mux_info {
 /**
  * struct ingenic_cgu_div_info - information about a divider
  * @reg: offset of the divider control register within the CGU
- * @shift: number of bits to shift the divide value by (ie. the index of
+ * @shift: number of bits to left shift the divide value by (ie. the index of
  *         the lowest bit of the divide value within its control register)
+ * @div: number of bits to divide the divider value by (i.e. if the
+ *	 effective divider value is the value written to the register
+ *	 multiplied by some constant)
  * @bits: the size of the divide value in bits
  * @ce_bit: the index of the change enable bit within reg, or -1 if there
  *          isn't one
@@ -87,6 +90,7 @@ struct ingenic_cgu_mux_info {
 struct ingenic_cgu_div_info {
 	unsigned reg;
 	u8 shift;
+	u8 div;
 	u8 bits;
 	s8 ce_bit;
 	s8 busy_bit;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/ingenic/jz4740-cgu.c linux-libre-4.7-gnu/drivers/clk/ingenic/jz4740-cgu.c
--- linux-libre-4.6-gnu/drivers/clk/ingenic/jz4740-cgu.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/ingenic/jz4740-cgu.c	2016-07-24 15:23:50.000000000 -0400
@@ -90,51 +90,51 @@ static const struct ingenic_cgu_clk_info
 	[JZ4740_CLK_PLL_HALF] = {
 		"pll half", CGU_CLK_DIV,
 		.parents = { JZ4740_CLK_PLL, -1, -1, -1 },
-		.div = { CGU_REG_CPCCR, 21, 1, -1, -1, -1 },
+		.div = { CGU_REG_CPCCR, 21, 1, 1, -1, -1, -1 },
 	},
 
 	[JZ4740_CLK_CCLK] = {
 		"cclk", CGU_CLK_DIV,
 		.parents = { JZ4740_CLK_PLL, -1, -1, -1 },
-		.div = { CGU_REG_CPCCR, 0, 4, 22, -1, -1 },
+		.div = { CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1 },
 	},
 
 	[JZ4740_CLK_HCLK] = {
 		"hclk", CGU_CLK_DIV,
 		.parents = { JZ4740_CLK_PLL, -1, -1, -1 },
-		.div = { CGU_REG_CPCCR, 4, 4, 22, -1, -1 },
+		.div = { CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1 },
 	},
 
 	[JZ4740_CLK_PCLK] = {
 		"pclk", CGU_CLK_DIV,
 		.parents = { JZ4740_CLK_PLL, -1, -1, -1 },
-		.div = { CGU_REG_CPCCR, 8, 4, 22, -1, -1 },
+		.div = { CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1 },
 	},
 
 	[JZ4740_CLK_MCLK] = {
 		"mclk", CGU_CLK_DIV,
 		.parents = { JZ4740_CLK_PLL, -1, -1, -1 },
-		.div = { CGU_REG_CPCCR, 12, 4, 22, -1, -1 },
+		.div = { CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1 },
 	},
 
 	[JZ4740_CLK_LCD] = {
 		"lcd", CGU_CLK_DIV | CGU_CLK_GATE,
 		.parents = { JZ4740_CLK_PLL_HALF, -1, -1, -1 },
-		.div = { CGU_REG_CPCCR, 16, 5, 22, -1, -1 },
+		.div = { CGU_REG_CPCCR, 16, 1, 5, 22, -1, -1 },
 		.gate = { CGU_REG_CLKGR, 10 },
 	},
 
 	[JZ4740_CLK_LCD_PCLK] = {
 		"lcd_pclk", CGU_CLK_DIV,
 		.parents = { JZ4740_CLK_PLL_HALF, -1, -1, -1 },
-		.div = { CGU_REG_LPCDR, 0, 11, -1, -1, -1 },
+		.div = { CGU_REG_LPCDR, 0, 1, 11, -1, -1, -1 },
 	},
 
 	[JZ4740_CLK_I2S] = {
 		"i2s", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
 		.parents = { JZ4740_CLK_EXT, JZ4740_CLK_PLL_HALF, -1, -1 },
 		.mux = { CGU_REG_CPCCR, 31, 1 },
-		.div = { CGU_REG_I2SCDR, 0, 8, -1, -1, -1 },
+		.div = { CGU_REG_I2SCDR, 0, 1, 8, -1, -1, -1 },
 		.gate = { CGU_REG_CLKGR, 6 },
 	},
 
@@ -142,21 +142,21 @@ static const struct ingenic_cgu_clk_info
 		"spi", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
 		.parents = { JZ4740_CLK_EXT, JZ4740_CLK_PLL, -1, -1 },
 		.mux = { CGU_REG_SSICDR, 31, 1 },
-		.div = { CGU_REG_SSICDR, 0, 4, -1, -1, -1 },
+		.div = { CGU_REG_SSICDR, 0, 1, 4, -1, -1, -1 },
 		.gate = { CGU_REG_CLKGR, 4 },
 	},
 
 	[JZ4740_CLK_MMC] = {
 		"mmc", CGU_CLK_DIV | CGU_CLK_GATE,
 		.parents = { JZ4740_CLK_PLL_HALF, -1, -1, -1 },
-		.div = { CGU_REG_MSCCDR, 0, 5, -1, -1, -1 },
+		.div = { CGU_REG_MSCCDR, 0, 1, 5, -1, -1, -1 },
 		.gate = { CGU_REG_CLKGR, 7 },
 	},
 
 	[JZ4740_CLK_UHC] = {
 		"uhc", CGU_CLK_DIV | CGU_CLK_GATE,
 		.parents = { JZ4740_CLK_PLL_HALF, -1, -1, -1 },
-		.div = { CGU_REG_UHCCDR, 0, 4, -1, -1, -1 },
+		.div = { CGU_REG_UHCCDR, 0, 1, 4, -1, -1, -1 },
 		.gate = { CGU_REG_CLKGR, 14 },
 	},
 
@@ -164,7 +164,7 @@ static const struct ingenic_cgu_clk_info
 		"udc", CGU_CLK_MUX | CGU_CLK_DIV,
 		.parents = { JZ4740_CLK_EXT, JZ4740_CLK_PLL_HALF, -1, -1 },
 		.mux = { CGU_REG_CPCCR, 29, 1 },
-		.div = { CGU_REG_CPCCR, 23, 6, -1, -1, -1 },
+		.div = { CGU_REG_CPCCR, 23, 1, 6, -1, -1, -1 },
 		.gate = { CGU_REG_SCR, 6 },
 	},
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/ingenic/jz4780-cgu.c linux-libre-4.7-gnu/drivers/clk/ingenic/jz4780-cgu.c
--- linux-libre-4.6-gnu/drivers/clk/ingenic/jz4780-cgu.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/ingenic/jz4780-cgu.c	2016-07-24 15:23:50.000000000 -0400
@@ -296,13 +296,13 @@ static const struct ingenic_cgu_clk_info
 	[JZ4780_CLK_CPU] = {
 		"cpu", CGU_CLK_DIV,
 		.parents = { JZ4780_CLK_CPUMUX, -1, -1, -1 },
-		.div = { CGU_REG_CLOCKCONTROL, 0, 4, 22, -1, -1 },
+		.div = { CGU_REG_CLOCKCONTROL, 0, 1, 4, 22, -1, -1 },
 	},
 
 	[JZ4780_CLK_L2CACHE] = {
 		"l2cache", CGU_CLK_DIV,
 		.parents = { JZ4780_CLK_CPUMUX, -1, -1, -1 },
-		.div = { CGU_REG_CLOCKCONTROL, 4, 4, -1, -1, -1 },
+		.div = { CGU_REG_CLOCKCONTROL, 4, 1, 4, -1, -1, -1 },
 	},
 
 	[JZ4780_CLK_AHB0] = {
@@ -310,7 +310,7 @@ static const struct ingenic_cgu_clk_info
 		.parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
 			     JZ4780_CLK_EPLL },
 		.mux = { CGU_REG_CLOCKCONTROL, 26, 2 },
-		.div = { CGU_REG_CLOCKCONTROL, 8, 4, 21, -1, -1 },
+		.div = { CGU_REG_CLOCKCONTROL, 8, 1, 4, 21, -1, -1 },
 	},
 
 	[JZ4780_CLK_AHB2PMUX] = {
@@ -323,20 +323,20 @@ static const struct ingenic_cgu_clk_info
 	[JZ4780_CLK_AHB2] = {
 		"ahb2", CGU_CLK_DIV,
 		.parents = { JZ4780_CLK_AHB2PMUX, -1, -1, -1 },
-		.div = { CGU_REG_CLOCKCONTROL, 12, 4, 20, -1, -1 },
+		.div = { CGU_REG_CLOCKCONTROL, 12, 1, 4, 20, -1, -1 },
 	},
 
 	[JZ4780_CLK_PCLK] = {
 		"pclk", CGU_CLK_DIV,
 		.parents = { JZ4780_CLK_AHB2PMUX, -1, -1, -1 },
-		.div = { CGU_REG_CLOCKCONTROL, 16, 4, 20, -1, -1 },
+		.div = { CGU_REG_CLOCKCONTROL, 16, 1, 4, 20, -1, -1 },
 	},
 
 	[JZ4780_CLK_DDR] = {
 		"ddr", CGU_CLK_MUX | CGU_CLK_DIV,
 		.parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, -1 },
 		.mux = { CGU_REG_DDRCDR, 30, 2 },
-		.div = { CGU_REG_DDRCDR, 0, 4, 29, 28, 27 },
+		.div = { CGU_REG_DDRCDR, 0, 1, 4, 29, 28, 27 },
 	},
 
 	[JZ4780_CLK_VPU] = {
@@ -344,7 +344,7 @@ static const struct ingenic_cgu_clk_info
 		.parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
 			     JZ4780_CLK_EPLL, -1 },
 		.mux = { CGU_REG_VPUCDR, 30, 2 },
-		.div = { CGU_REG_VPUCDR, 0, 4, 29, 28, 27 },
+		.div = { CGU_REG_VPUCDR, 0, 1, 4, 29, 28, 27 },
 		.gate = { CGU_REG_CLKGR1, 2 },
 	},
 
@@ -352,7 +352,7 @@ static const struct ingenic_cgu_clk_info
 		"i2s_pll", CGU_CLK_MUX | CGU_CLK_DIV,
 		.parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_EPLL, -1, -1 },
 		.mux = { CGU_REG_I2SCDR, 30, 1 },
-		.div = { CGU_REG_I2SCDR, 0, 8, 29, 28, 27 },
+		.div = { CGU_REG_I2SCDR, 0, 1, 8, 29, 28, 27 },
 	},
 
 	[JZ4780_CLK_I2S] = {
@@ -366,7 +366,7 @@ static const struct ingenic_cgu_clk_info
 		.parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
 			     JZ4780_CLK_VPLL, -1 },
 		.mux = { CGU_REG_LP0CDR, 30, 2 },
-		.div = { CGU_REG_LP0CDR, 0, 8, 28, 27, 26 },
+		.div = { CGU_REG_LP0CDR, 0, 1, 8, 28, 27, 26 },
 	},
 
 	[JZ4780_CLK_LCD1PIXCLK] = {
@@ -374,7 +374,7 @@ static const struct ingenic_cgu_clk_info
 		.parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
 			     JZ4780_CLK_VPLL, -1 },
 		.mux = { CGU_REG_LP1CDR, 30, 2 },
-		.div = { CGU_REG_LP1CDR, 0, 8, 28, 27, 26 },
+		.div = { CGU_REG_LP1CDR, 0, 1, 8, 28, 27, 26 },
 	},
 
 	[JZ4780_CLK_MSCMUX] = {
@@ -386,21 +386,21 @@ static const struct ingenic_cgu_clk_info
 	[JZ4780_CLK_MSC0] = {
 		"msc0", CGU_CLK_DIV | CGU_CLK_GATE,
 		.parents = { JZ4780_CLK_MSCMUX, -1, -1, -1 },
-		.div = { CGU_REG_MSC0CDR, 0, 8, 29, 28, 27 },
+		.div = { CGU_REG_MSC0CDR, 0, 2, 8, 29, 28, 27 },
 		.gate = { CGU_REG_CLKGR0, 3 },
 	},
 
 	[JZ4780_CLK_MSC1] = {
 		"msc1", CGU_CLK_DIV | CGU_CLK_GATE,
 		.parents = { JZ4780_CLK_MSCMUX, -1, -1, -1 },
-		.div = { CGU_REG_MSC1CDR, 0, 8, 29, 28, 27 },
+		.div = { CGU_REG_MSC1CDR, 0, 2, 8, 29, 28, 27 },
 		.gate = { CGU_REG_CLKGR0, 11 },
 	},
 
 	[JZ4780_CLK_MSC2] = {
 		"msc2", CGU_CLK_DIV | CGU_CLK_GATE,
 		.parents = { JZ4780_CLK_MSCMUX, -1, -1, -1 },
-		.div = { CGU_REG_MSC2CDR, 0, 8, 29, 28, 27 },
+		.div = { CGU_REG_MSC2CDR, 0, 2, 8, 29, 28, 27 },
 		.gate = { CGU_REG_CLKGR0, 12 },
 	},
 
@@ -409,7 +409,7 @@ static const struct ingenic_cgu_clk_info
 		.parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
 			     JZ4780_CLK_EPLL, JZ4780_CLK_OTGPHY },
 		.mux = { CGU_REG_UHCCDR, 30, 2 },
-		.div = { CGU_REG_UHCCDR, 0, 8, 29, 28, 27 },
+		.div = { CGU_REG_UHCCDR, 0, 1, 8, 29, 28, 27 },
 		.gate = { CGU_REG_CLKGR0, 24 },
 	},
 
@@ -417,7 +417,7 @@ static const struct ingenic_cgu_clk_info
 		"ssi_pll", CGU_CLK_MUX | CGU_CLK_DIV,
 		.parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, -1, -1 },
 		.mux = { CGU_REG_SSICDR, 30, 1 },
-		.div = { CGU_REG_SSICDR, 0, 8, 29, 28, 27 },
+		.div = { CGU_REG_SSICDR, 0, 1, 8, 29, 28, 27 },
 	},
 
 	[JZ4780_CLK_SSI] = {
@@ -430,7 +430,7 @@ static const struct ingenic_cgu_clk_info
 		"cim_mclk", CGU_CLK_MUX | CGU_CLK_DIV,
 		.parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, -1, -1 },
 		.mux = { CGU_REG_CIMCDR, 31, 1 },
-		.div = { CGU_REG_CIMCDR, 0, 8, 30, 29, 28 },
+		.div = { CGU_REG_CIMCDR, 0, 1, 8, 30, 29, 28 },
 	},
 
 	[JZ4780_CLK_PCMPLL] = {
@@ -438,7 +438,7 @@ static const struct ingenic_cgu_clk_info
 		.parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
 			     JZ4780_CLK_EPLL, JZ4780_CLK_VPLL },
 		.mux = { CGU_REG_PCMCDR, 29, 2 },
-		.div = { CGU_REG_PCMCDR, 0, 8, 28, 27, 26 },
+		.div = { CGU_REG_PCMCDR, 0, 1, 8, 28, 27, 26 },
 	},
 
 	[JZ4780_CLK_PCM] = {
@@ -453,7 +453,7 @@ static const struct ingenic_cgu_clk_info
 		.parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
 			     JZ4780_CLK_EPLL },
 		.mux = { CGU_REG_GPUCDR, 30, 2 },
-		.div = { CGU_REG_GPUCDR, 0, 4, 29, 28, 27 },
+		.div = { CGU_REG_GPUCDR, 0, 1, 4, 29, 28, 27 },
 		.gate = { CGU_REG_CLKGR1, 4 },
 	},
 
@@ -462,7 +462,7 @@ static const struct ingenic_cgu_clk_info
 		.parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
 			     JZ4780_CLK_VPLL, -1 },
 		.mux = { CGU_REG_HDMICDR, 30, 2 },
-		.div = { CGU_REG_HDMICDR, 0, 8, 29, 28, 26 },
+		.div = { CGU_REG_HDMICDR, 0, 1, 8, 29, 28, 26 },
 		.gate = { CGU_REG_CLKGR1, 9 },
 	},
 
@@ -471,7 +471,7 @@ static const struct ingenic_cgu_clk_info
 		.parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
 			     JZ4780_CLK_EPLL },
 		.mux = { CGU_REG_BCHCDR, 30, 2 },
-		.div = { CGU_REG_BCHCDR, 0, 4, 29, 28, 27 },
+		.div = { CGU_REG_BCHCDR, 0, 1, 4, 29, 28, 27 },
 		.gate = { CGU_REG_CLKGR0, 1 },
 	},
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/Kconfig linux-libre-4.7-gnu/drivers/clk/Kconfig
--- linux-libre-4.6-gnu/drivers/clk/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -175,6 +175,7 @@ config COMMON_CLK_KEYSTONE
 config COMMON_CLK_NXP
 	def_bool COMMON_CLK && (ARCH_LPC18XX || ARCH_LPC32XX)
 	select REGMAP_MMIO if ARCH_LPC32XX
+	select MFD_SYSCON if ARCH_LPC18XX
 	---help---
 	  Support for clock providers on NXP platforms.
 
@@ -197,10 +198,20 @@ config COMMON_CLK_PXA
 	---help---
 	  Support for the Marvell PXA SoC.
 
+config COMMON_CLK_PIC32
+	def_bool COMMON_CLK && MACH_PIC32
+
+config COMMON_CLK_OXNAS
+	bool "Clock driver for the OXNAS SoC Family"
+	select MFD_SYSCON
+	---help---
+	  Support for the OXNAS SoC Family clocks.
+
 source "drivers/clk/bcm/Kconfig"
 source "drivers/clk/hisilicon/Kconfig"
 source "drivers/clk/mvebu/Kconfig"
 source "drivers/clk/qcom/Kconfig"
+source "drivers/clk/renesas/Kconfig"
 source "drivers/clk/samsung/Kconfig"
 source "drivers/clk/tegra/Kconfig"
 source "drivers/clk/ti/Kconfig"
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/Makefile linux-libre-4.7-gnu/drivers/clk/Makefile
--- linux-libre-4.6-gnu/drivers/clk/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -33,6 +33,7 @@ obj-$(CONFIG_ARCH_MB86S7X)		+= clk-mb86s
 obj-$(CONFIG_ARCH_MOXART)		+= clk-moxart.o
 obj-$(CONFIG_ARCH_NOMADIK)		+= clk-nomadik.o
 obj-$(CONFIG_ARCH_NSPIRE)		+= clk-nspire.o
+obj-$(CONFIG_COMMON_CLK_OXNAS)		+= clk-oxnas.o
 obj-$(CONFIG_COMMON_CLK_PALMAS)		+= clk-palmas.o
 obj-$(CONFIG_CLK_QORIQ)			+= clk-qoriq.o
 obj-$(CONFIG_COMMON_CLK_RK808)		+= clk-rk808.o
@@ -51,6 +52,7 @@ obj-$(CONFIG_COMMON_CLK_WM831X)		+= clk-
 obj-$(CONFIG_COMMON_CLK_XGENE)		+= clk-xgene.o
 obj-$(CONFIG_COMMON_CLK_PWM)		+= clk-pwm.o
 obj-$(CONFIG_COMMON_CLK_AT91)		+= at91/
+obj-$(CONFIG_ARCH_ARTPEC)		+= axis/
 obj-y					+= bcm/
 obj-$(CONFIG_ARCH_BERLIN)		+= berlin/
 obj-$(CONFIG_ARCH_HISI)			+= hisilicon/
@@ -58,10 +60,11 @@ obj-$(CONFIG_ARCH_MXC)			+= imx/
 obj-$(CONFIG_MACH_INGENIC)		+= ingenic/
 obj-$(CONFIG_COMMON_CLK_KEYSTONE)	+= keystone/
 obj-$(CONFIG_ARCH_MEDIATEK)		+= mediatek/
+obj-$(CONFIG_MACH_PIC32)		+= microchip/
 ifeq ($(CONFIG_COMMON_CLK), y)
 obj-$(CONFIG_ARCH_MMP)			+= mmp/
 endif
-obj-$(CONFIG_PLAT_ORION)		+= mvebu/
+obj-y					+= mvebu/
 obj-$(CONFIG_ARCH_MESON)		+= meson/
 obj-$(CONFIG_ARCH_MXS)			+= mxs/
 obj-$(CONFIG_MACH_PISTACHIO)		+= pistachio/
@@ -84,3 +87,4 @@ obj-$(CONFIG_X86)			+= x86/
 obj-$(CONFIG_ARCH_ZX)			+= zte/
 obj-$(CONFIG_ARCH_ZYNQ)			+= zynq/
 obj-$(CONFIG_H8300)		+= h8300/
+obj-$(CONFIG_ARC_PLAT_AXS10X)		+= axs10x/
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/mediatek/clk-mt8173.c linux-libre-4.7-gnu/drivers/clk/mediatek/clk-mt8173.c
--- linux-libre-4.6-gnu/drivers/clk/mediatek/clk-mt8173.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/mediatek/clk-mt8173.c	2016-07-24 15:23:50.000000000 -0400
@@ -61,7 +61,6 @@ static const struct mtk_fixed_factor top
 	FACTOR(CLK_TOP_CLKRTC_INT, "clkrtc_int", "clk26m", 1, 793),
 	FACTOR(CLK_TOP_FPC, "fpc_ck", "clk26m", 1, 1),
 
-	FACTOR(CLK_TOP_HDMITX_DIG_CTS, "hdmitx_dig_cts", "tvdpll_445p5m", 1, 3),
 	FACTOR(CLK_TOP_HDMITXPLL_D2, "hdmitxpll_d2", "hdmitx_dig_cts", 1, 2),
 	FACTOR(CLK_TOP_HDMITXPLL_D3, "hdmitxpll_d3", "hdmitx_dig_cts", 1, 3),
 
@@ -558,7 +557,11 @@ static const struct mtk_composite top_mu
 	MUX_GATE(CLK_TOP_ATB_SEL, "atb_sel", atb_parents, 0x0090, 16, 2, 23),
 	MUX_GATE(CLK_TOP_VENC_LT_SEL, "venclt_sel", venc_lt_parents, 0x0090, 24, 4, 31),
 	/* CLK_CFG_6 */
-	MUX_GATE(CLK_TOP_DPI0_SEL, "dpi0_sel", dpi0_parents, 0x00a0, 0, 3, 7),
+	/*
+	 * The dpi0_sel clock should not propagate rate changes to its parent
+	 * clock so the dpi driver can have full control over PLL and divider.
+	 */
+	MUX_GATE_FLAGS(CLK_TOP_DPI0_SEL, "dpi0_sel", dpi0_parents, 0x00a0, 0, 3, 7, 0),
 	MUX_GATE(CLK_TOP_IRDA_SEL, "irda_sel", irda_parents, 0x00a0, 8, 2, 15),
 	MUX_GATE(CLK_TOP_CCI400_SEL, "cci400_sel", cci400_parents, 0x00a0, 16, 3, 23),
 	MUX_GATE(CLK_TOP_AUD_1_SEL, "aud_1_sel", aud_1_parents, 0x00a0, 24, 2, 31),
@@ -1091,6 +1094,11 @@ static void __init mtk_apmixedsys_init(s
 		clk_data->clks[cku->id] = clk;
 	}
 
+	clk = clk_register_divider(NULL, "hdmi_ref", "tvdpll_594m", 0,
+				   base + 0x40, 16, 3, CLK_DIVIDER_POWER_OF_TWO,
+				   NULL);
+	clk_data->clks[CLK_APMIXED_HDMI_REF] = clk;
+
 	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
 	if (r)
 		pr_err("%s(): could not register clock provider: %d\n",
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/mediatek/clk-mtk.h linux-libre-4.7-gnu/drivers/clk/mediatek/clk-mtk.h
--- linux-libre-4.6-gnu/drivers/clk/mediatek/clk-mtk.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/mediatek/clk-mtk.h	2016-07-24 15:23:50.000000000 -0400
@@ -83,7 +83,11 @@ struct mtk_composite {
 	signed char num_parents;
 };
 
-#define MUX_GATE(_id, _name, _parents, _reg, _shift, _width, _gate) {	\
+/*
+ * In case the rate change propagation to parent clocks is undesirable,
+ * this macro allows to specify the clock flags manually.
+ */
+#define MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width, _gate, _flags) {	\
 		.id = _id,						\
 		.name = _name,						\
 		.mux_reg = _reg,					\
@@ -94,9 +98,16 @@ struct mtk_composite {
 		.divider_shift = -1,					\
 		.parent_names = _parents,				\
 		.num_parents = ARRAY_SIZE(_parents),			\
-		.flags = CLK_SET_RATE_PARENT,				\
+		.flags = _flags,					\
 	}
 
+/*
+ * Unless necessary, all MUX_GATE clocks propagate rate changes to their
+ * parent clock by default.
+ */
+#define MUX_GATE(_id, _name, _parents, _reg, _shift, _width, _gate)	\
+	MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width, _gate, CLK_SET_RATE_PARENT)
+
 #define MUX(_id, _name, _parents, _reg, _shift, _width) {		\
 		.id = _id,						\
 		.name = _name,						\
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/meson/meson8b-clkc.c linux-libre-4.7-gnu/drivers/clk/meson/meson8b-clkc.c
--- linux-libre-4.6-gnu/drivers/clk/meson/meson8b-clkc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/meson/meson8b-clkc.c	2016-07-24 15:23:50.000000000 -0400
@@ -141,11 +141,11 @@ static const struct composite_conf mali_
 };
 
 static const struct clk_conf meson8b_xtal_conf __initconst =
-	FIXED_RATE_P(MESON8B_REG_CTL0_ADDR, CLKID_XTAL, "xtal",
-		     CLK_IS_ROOT, PARM(0x00, 4, 7));
+	FIXED_RATE_P(MESON8B_REG_CTL0_ADDR, CLKID_XTAL, "xtal", 0,
+			PARM(0x00, 4, 7));
 
 static const struct clk_conf meson8b_clk_confs[] __initconst = {
-	FIXED_RATE(CLKID_ZERO, "zero", CLK_IS_ROOT, 0),
+	FIXED_RATE(CLKID_ZERO, "zero", 0, 0),
 	PLL(MESON8B_REG_PLL_FIXED, CLKID_PLL_FIXED, "fixed_pll",
 	    p_xtal, 0, &pll_confs),
 	PLL(MESON8B_REG_PLL_VID, CLKID_PLL_VID, "vid_pll",
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/microchip/clk-core.c linux-libre-4.7-gnu/drivers/clk/microchip/clk-core.c
--- linux-libre-4.6-gnu/drivers/clk/microchip/clk-core.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/clk/microchip/clk-core.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,1031 @@
+/*
+ * Purna Chandra Mandal,<purna.mandal@microchip.com>
+ * Copyright (C) 2015 Microchip Technology Inc.  All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ */
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/iopoll.h>
+#include <asm/mach-pic32/pic32.h>
+#include <asm/traps.h>
+
+#include "clk-core.h"
+
+/* OSCCON Reg fields */
+#define OSC_CUR_MASK		0x07
+#define OSC_CUR_SHIFT		12
+#define OSC_NEW_MASK		0x07
+#define OSC_NEW_SHIFT		8
+#define OSC_SWEN		BIT(0)
+
+/* SPLLCON Reg fields */
+#define PLL_RANGE_MASK		0x07
+#define PLL_RANGE_SHIFT		0
+#define PLL_ICLK_MASK		0x01
+#define PLL_ICLK_SHIFT		7
+#define PLL_IDIV_MASK		0x07
+#define PLL_IDIV_SHIFT		8
+#define PLL_ODIV_MASK		0x07
+#define PLL_ODIV_SHIFT		24
+#define PLL_MULT_MASK		0x7F
+#define PLL_MULT_SHIFT		16
+#define PLL_MULT_MAX		128
+#define PLL_ODIV_MIN		1
+#define PLL_ODIV_MAX		5
+
+/* Peripheral Bus Clock Reg Fields */
+#define PB_DIV_MASK		0x7f
+#define PB_DIV_SHIFT		0
+#define PB_DIV_READY		BIT(11)
+#define PB_DIV_ENABLE		BIT(15)
+#define PB_DIV_MAX		128
+#define PB_DIV_MIN		0
+
+/* Reference Oscillator Control Reg fields */
+#define REFO_SEL_MASK		0x0f
+#define REFO_SEL_SHIFT		0
+#define REFO_ACTIVE		BIT(8)
+#define REFO_DIVSW_EN		BIT(9)
+#define REFO_OE			BIT(12)
+#define REFO_ON			BIT(15)
+#define REFO_DIV_SHIFT		16
+#define REFO_DIV_MASK		0x7fff
+
+/* Reference Oscillator Trim Register Fields */
+#define REFO_TRIM_REG		0x10
+#define REFO_TRIM_MASK		0x1ff
+#define REFO_TRIM_SHIFT		23
+#define REFO_TRIM_MAX		511
+
+/* Mux Slew Control Register fields */
+#define SLEW_BUSY		BIT(0)
+#define SLEW_DOWNEN		BIT(1)
+#define SLEW_UPEN		BIT(2)
+#define SLEW_DIV		0x07
+#define SLEW_DIV_SHIFT		8
+#define SLEW_SYSDIV		0x0f
+#define SLEW_SYSDIV_SHIFT	20
+
+/* Clock Poll Timeout */
+#define LOCK_TIMEOUT_US         USEC_PER_MSEC
+
+/* SoC specific clock needed during SPLL clock rate switch */
+static struct clk_hw *pic32_sclk_hw;
+
+/* add instruction pipeline delay while CPU clock is in-transition. */
+#define cpu_nop5()			\
+do {					\
+	__asm__ __volatile__("nop");	\
+	__asm__ __volatile__("nop");	\
+	__asm__ __volatile__("nop");	\
+	__asm__ __volatile__("nop");	\
+	__asm__ __volatile__("nop");	\
+} while (0)
+
+/* Perpheral bus clocks */
+struct pic32_periph_clk {
+	struct clk_hw hw;
+	void __iomem *ctrl_reg;
+	struct pic32_clk_common *core;
+};
+
+#define clkhw_to_pbclk(_hw)	container_of(_hw, struct pic32_periph_clk, hw)
+
+static int pbclk_is_enabled(struct clk_hw *hw)
+{
+	struct pic32_periph_clk *pb = clkhw_to_pbclk(hw);
+
+	return readl(pb->ctrl_reg) & PB_DIV_ENABLE;
+}
+
+static int pbclk_enable(struct clk_hw *hw)
+{
+	struct pic32_periph_clk *pb = clkhw_to_pbclk(hw);
+
+	writel(PB_DIV_ENABLE, PIC32_SET(pb->ctrl_reg));
+	return 0;
+}
+
+static void pbclk_disable(struct clk_hw *hw)
+{
+	struct pic32_periph_clk *pb = clkhw_to_pbclk(hw);
+
+	writel(PB_DIV_ENABLE, PIC32_CLR(pb->ctrl_reg));
+}
+
+static unsigned long calc_best_divided_rate(unsigned long rate,
+					    unsigned long parent_rate,
+					    u32 divider_max,
+					    u32 divider_min)
+{
+	unsigned long divided_rate, divided_rate_down, best_rate;
+	unsigned long div, div_up;
+
+	/* eq. clk_rate = parent_rate / divider.
+	 *
+	 * Find best divider to produce closest of target divided rate.
+	 */
+	div = parent_rate / rate;
+	div = clamp_val(div, divider_min, divider_max);
+	div_up = clamp_val(div + 1, divider_min, divider_max);
+
+	divided_rate = parent_rate / div;
+	divided_rate_down = parent_rate / div_up;
+	if (abs(rate - divided_rate_down) < abs(rate - divided_rate))
+		best_rate = divided_rate_down;
+	else
+		best_rate = divided_rate;
+
+	return best_rate;
+}
+
+static inline u32 pbclk_read_pbdiv(struct pic32_periph_clk *pb)
+{
+	return ((readl(pb->ctrl_reg) >> PB_DIV_SHIFT) & PB_DIV_MASK) + 1;
+}
+
+static unsigned long pbclk_recalc_rate(struct clk_hw *hw,
+				       unsigned long parent_rate)
+{
+	struct pic32_periph_clk *pb = clkhw_to_pbclk(hw);
+
+	return parent_rate / pbclk_read_pbdiv(pb);
+}
+
+static long pbclk_round_rate(struct clk_hw *hw, unsigned long rate,
+			     unsigned long *parent_rate)
+{
+	return calc_best_divided_rate(rate, *parent_rate,
+				      PB_DIV_MAX, PB_DIV_MIN);
+}
+
+static int pbclk_set_rate(struct clk_hw *hw, unsigned long rate,
+			  unsigned long parent_rate)
+{
+	struct pic32_periph_clk *pb = clkhw_to_pbclk(hw);
+	unsigned long flags;
+	u32 v, div;
+	int err;
+
+	/* check & wait for DIV_READY */
+	err = readl_poll_timeout(pb->ctrl_reg, v, v & PB_DIV_READY,
+				 1, LOCK_TIMEOUT_US);
+	if (err)
+		return err;
+
+	/* calculate clkdiv and best rate */
+	div = DIV_ROUND_CLOSEST(parent_rate, rate);
+
+	spin_lock_irqsave(&pb->core->reg_lock, flags);
+
+	/* apply new div */
+	v = readl(pb->ctrl_reg);
+	v &= ~PB_DIV_MASK;
+	v |= (div - 1);
+
+	pic32_syskey_unlock();
+
+	writel(v, pb->ctrl_reg);
+
+	spin_unlock_irqrestore(&pb->core->reg_lock, flags);
+
+	/* wait again, for pbdivready */
+	err = readl_poll_timeout_atomic(pb->ctrl_reg, v, v & PB_DIV_READY,
+					1, LOCK_TIMEOUT_US);
+	if (err)
+		return err;
+
+	/* confirm that new div is applied correctly */
+	return (pbclk_read_pbdiv(pb) == div) ? 0 : -EBUSY;
+}
+
+const struct clk_ops pic32_pbclk_ops = {
+	.enable		= pbclk_enable,
+	.disable	= pbclk_disable,
+	.is_enabled	= pbclk_is_enabled,
+	.recalc_rate	= pbclk_recalc_rate,
+	.round_rate	= pbclk_round_rate,
+	.set_rate	= pbclk_set_rate,
+};
+
+struct clk *pic32_periph_clk_register(const struct pic32_periph_clk_data *desc,
+				      struct pic32_clk_common *core)
+{
+	struct pic32_periph_clk *pbclk;
+	struct clk *clk;
+
+	pbclk = devm_kzalloc(core->dev, sizeof(*pbclk), GFP_KERNEL);
+	if (!pbclk)
+		return ERR_PTR(-ENOMEM);
+
+	pbclk->hw.init = &desc->init_data;
+	pbclk->core = core;
+	pbclk->ctrl_reg = desc->ctrl_reg + core->iobase;
+
+	clk = devm_clk_register(core->dev, &pbclk->hw);
+	if (IS_ERR(clk)) {
+		dev_err(core->dev, "%s: clk_register() failed\n", __func__);
+		devm_kfree(core->dev, pbclk);
+	}
+
+	return clk;
+}
+
+/* Reference oscillator operations */
+struct pic32_ref_osc {
+	struct clk_hw hw;
+	void __iomem *ctrl_reg;
+	const u32 *parent_map;
+	struct pic32_clk_common *core;
+};
+
+#define clkhw_to_refosc(_hw)	container_of(_hw, struct pic32_ref_osc, hw)
+
+static int roclk_is_enabled(struct clk_hw *hw)
+{
+	struct pic32_ref_osc *refo = clkhw_to_refosc(hw);
+
+	return readl(refo->ctrl_reg) & REFO_ON;
+}
+
+static int roclk_enable(struct clk_hw *hw)
+{
+	struct pic32_ref_osc *refo = clkhw_to_refosc(hw);
+
+	writel(REFO_ON | REFO_OE, PIC32_SET(refo->ctrl_reg));
+	return 0;
+}
+
+static void roclk_disable(struct clk_hw *hw)
+{
+	struct pic32_ref_osc *refo = clkhw_to_refosc(hw);
+
+	writel(REFO_ON | REFO_OE, PIC32_CLR(refo->ctrl_reg));
+}
+
+static void roclk_init(struct clk_hw *hw)
+{
+	/* initialize clock in disabled state */
+	roclk_disable(hw);
+}
+
+static u8 roclk_get_parent(struct clk_hw *hw)
+{
+	struct pic32_ref_osc *refo = clkhw_to_refosc(hw);
+	u32 v, i;
+
+	v = (readl(refo->ctrl_reg) >> REFO_SEL_SHIFT) & REFO_SEL_MASK;
+
+	if (!refo->parent_map)
+		return v;
+
+	for (i = 0; i < clk_hw_get_num_parents(hw); i++)
+		if (refo->parent_map[i] == v)
+			return i;
+
+	return -EINVAL;
+}
+
+static unsigned long roclk_calc_rate(unsigned long parent_rate,
+				     u32 rodiv, u32 rotrim)
+{
+	u64 rate64;
+
+	/* fout = fin / [2 * {div + (trim / 512)}]
+	 *	= fin * 512 / [1024 * div + 2 * trim]
+	 *	= fin * 256 / (512 * div + trim)
+	 *	= (fin << 8) / ((div << 9) + trim)
+	 */
+	if (rotrim) {
+		rodiv = (rodiv << 9) + rotrim;
+		rate64 = parent_rate;
+		rate64 <<= 8;
+		do_div(rate64, rodiv);
+	} else if (rodiv) {
+		rate64 = parent_rate / (rodiv << 1);
+	} else {
+		rate64 = parent_rate;
+	}
+	return rate64;
+}
+
+static void roclk_calc_div_trim(unsigned long rate,
+				unsigned long parent_rate,
+				u32 *rodiv_p, u32 *rotrim_p)
+{
+	u32 div, rotrim, rodiv;
+	u64 frac;
+
+	/* Find integer approximation of floating-point arithmetic.
+	 *      fout = fin / [2 * {rodiv + (rotrim / 512)}] ... (1)
+	 * i.e. fout = fin / 2 * DIV
+	 *      whereas DIV = rodiv + (rotrim / 512)
+	 *
+	 * Since kernel does not perform floating-point arithmatic so
+	 * (rotrim/512) will be zero. And DIV & rodiv will result same.
+	 *
+	 * ie. fout = (fin * 256) / [(512 * rodiv) + rotrim]  ... from (1)
+	 * ie. rotrim = ((fin * 256) / fout) - (512 * DIV)
+	 */
+	if (parent_rate <= rate) {
+		div = 0;
+		frac = 0;
+		rodiv = 0;
+		rotrim = 0;
+	} else {
+		div = parent_rate / (rate << 1);
+		frac = parent_rate;
+		frac <<= 8;
+		do_div(frac, rate);
+		frac -= (u64)(div << 9);
+
+		rodiv = (div > REFO_DIV_MASK) ? REFO_DIV_MASK : div;
+		rotrim = (frac >= REFO_TRIM_MAX) ? REFO_TRIM_MAX : frac;
+	}
+
+	if (rodiv_p)
+		*rodiv_p = rodiv;
+
+	if (rotrim_p)
+		*rotrim_p = rotrim;
+}
+
+static unsigned long roclk_recalc_rate(struct clk_hw *hw,
+				       unsigned long parent_rate)
+{
+	struct pic32_ref_osc *refo = clkhw_to_refosc(hw);
+	u32 v, rodiv, rotrim;
+
+	/* get rodiv */
+	v = readl(refo->ctrl_reg);
+	rodiv = (v >> REFO_DIV_SHIFT) & REFO_DIV_MASK;
+
+	/* get trim */
+	v = readl(refo->ctrl_reg + REFO_TRIM_REG);
+	rotrim = (v >> REFO_TRIM_SHIFT) & REFO_TRIM_MASK;
+
+	return roclk_calc_rate(parent_rate, rodiv, rotrim);
+}
+
+static long roclk_round_rate(struct clk_hw *hw, unsigned long rate,
+			     unsigned long *parent_rate)
+{
+	u32 rotrim, rodiv;
+
+	/* calculate dividers for new rate */
+	roclk_calc_div_trim(rate, *parent_rate, &rodiv, &rotrim);
+
+	/* caclulate new rate (rounding) based on new rodiv & rotrim */
+	return roclk_calc_rate(*parent_rate, rodiv, rotrim);
+}
+
+static int roclk_determine_rate(struct clk_hw *hw,
+				struct clk_rate_request *req)
+{
+	struct clk_hw *parent_clk, *best_parent_clk = NULL;
+	unsigned int i, delta, best_delta = -1;
+	unsigned long parent_rate, best_parent_rate = 0;
+	unsigned long best = 0, nearest_rate;
+
+	/* find a parent which can generate nearest clkrate >= rate */
+	for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
+		/* get parent */
+		parent_clk = clk_hw_get_parent_by_index(hw, i);
+		if (!parent_clk)
+			continue;
+
+		/* skip if parent runs slower than target rate */
+		parent_rate = clk_hw_get_rate(parent_clk);
+		if (req->rate > parent_rate)
+			continue;
+
+		nearest_rate = roclk_round_rate(hw, req->rate, &parent_rate);
+		delta = abs(nearest_rate - req->rate);
+		if ((nearest_rate >= req->rate) && (delta < best_delta)) {
+			best_parent_clk = parent_clk;
+			best_parent_rate = parent_rate;
+			best = nearest_rate;
+			best_delta = delta;
+
+			if (delta == 0)
+				break;
+		}
+	}
+
+	/* if no match found, retain old rate */
+	if (!best_parent_clk) {
+		pr_err("%s:%s, no parent found for rate %lu.\n",
+		       __func__, clk_hw_get_name(hw), req->rate);
+		return clk_hw_get_rate(hw);
+	}
+
+	pr_debug("%s,rate %lu, best_parent(%s, %lu), best %lu, delta %d\n",
+		 clk_hw_get_name(hw), req->rate,
+		 clk_hw_get_name(best_parent_clk), best_parent_rate,
+		 best, best_delta);
+
+	if (req->best_parent_rate)
+		req->best_parent_rate = best_parent_rate;
+
+	if (req->best_parent_hw)
+		req->best_parent_hw = best_parent_clk;
+
+	return best;
+}
+
+static int roclk_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct pic32_ref_osc *refo = clkhw_to_refosc(hw);
+	unsigned long flags;
+	u32 v;
+	int err;
+
+	if (refo->parent_map)
+		index = refo->parent_map[index];
+
+	/* wait until ACTIVE bit is zero or timeout */
+	err = readl_poll_timeout(refo->ctrl_reg, v, !(v & REFO_ACTIVE),
+				 1, LOCK_TIMEOUT_US);
+	if (err) {
+		pr_err("%s: poll failed, clk active\n", clk_hw_get_name(hw));
+		return err;
+	}
+
+	spin_lock_irqsave(&refo->core->reg_lock, flags);
+
+	pic32_syskey_unlock();
+
+	/* calculate & apply new */
+	v = readl(refo->ctrl_reg);
+	v &= ~(REFO_SEL_MASK << REFO_SEL_SHIFT);
+	v |= index << REFO_SEL_SHIFT;
+
+	writel(v, refo->ctrl_reg);
+
+	spin_unlock_irqrestore(&refo->core->reg_lock, flags);
+
+	return 0;
+}
+
+static int roclk_set_rate_and_parent(struct clk_hw *hw,
+				     unsigned long rate,
+				     unsigned long parent_rate,
+				     u8 index)
+{
+	struct pic32_ref_osc *refo = clkhw_to_refosc(hw);
+	unsigned long flags;
+	u32 trim, rodiv, v;
+	int err;
+
+	/* calculate new rodiv & rotrim for new rate */
+	roclk_calc_div_trim(rate, parent_rate, &rodiv, &trim);
+
+	pr_debug("parent_rate = %lu, rate = %lu, div = %d, trim = %d\n",
+		 parent_rate, rate, rodiv, trim);
+
+	/* wait till source change is active */
+	err = readl_poll_timeout(refo->ctrl_reg, v,
+				 !(v & (REFO_ACTIVE | REFO_DIVSW_EN)),
+				 1, LOCK_TIMEOUT_US);
+	if (err) {
+		pr_err("%s: poll timedout, clock is still active\n", __func__);
+		return err;
+	}
+
+	spin_lock_irqsave(&refo->core->reg_lock, flags);
+	v = readl(refo->ctrl_reg);
+
+	pic32_syskey_unlock();
+
+	/* apply parent, if required */
+	if (refo->parent_map)
+		index = refo->parent_map[index];
+
+	v &= ~(REFO_SEL_MASK << REFO_SEL_SHIFT);
+	v |= index << REFO_SEL_SHIFT;
+
+	/* apply RODIV */
+	v &= ~(REFO_DIV_MASK << REFO_DIV_SHIFT);
+	v |= rodiv << REFO_DIV_SHIFT;
+	writel(v, refo->ctrl_reg);
+
+	/* apply ROTRIM */
+	v = readl(refo->ctrl_reg + REFO_TRIM_REG);
+	v &= ~(REFO_TRIM_MASK << REFO_TRIM_SHIFT);
+	v |= trim << REFO_TRIM_SHIFT;
+	writel(v, refo->ctrl_reg + REFO_TRIM_REG);
+
+	/* enable & activate divider switching */
+	writel(REFO_ON | REFO_DIVSW_EN, PIC32_SET(refo->ctrl_reg));
+
+	/* wait till divswen is in-progress */
+	err = readl_poll_timeout_atomic(refo->ctrl_reg, v, !(v & REFO_DIVSW_EN),
+					1, LOCK_TIMEOUT_US);
+	/* leave the clk gated as it was */
+	writel(REFO_ON, PIC32_CLR(refo->ctrl_reg));
+
+	spin_unlock_irqrestore(&refo->core->reg_lock, flags);
+
+	return err;
+}
+
+static int roclk_set_rate(struct clk_hw *hw, unsigned long rate,
+			  unsigned long parent_rate)
+{
+	u8 index = roclk_get_parent(hw);
+
+	return roclk_set_rate_and_parent(hw, rate, parent_rate, index);
+}
+
+const struct clk_ops pic32_roclk_ops = {
+	.enable			= roclk_enable,
+	.disable		= roclk_disable,
+	.is_enabled		= roclk_is_enabled,
+	.get_parent		= roclk_get_parent,
+	.set_parent		= roclk_set_parent,
+	.determine_rate		= roclk_determine_rate,
+	.recalc_rate		= roclk_recalc_rate,
+	.set_rate_and_parent	= roclk_set_rate_and_parent,
+	.set_rate		= roclk_set_rate,
+	.init			= roclk_init,
+};
+
+struct clk *pic32_refo_clk_register(const struct pic32_ref_osc_data *data,
+				    struct pic32_clk_common *core)
+{
+	struct pic32_ref_osc *refo;
+	struct clk *clk;
+
+	refo = devm_kzalloc(core->dev, sizeof(*refo), GFP_KERNEL);
+	if (!refo)
+		return ERR_PTR(-ENOMEM);
+
+	refo->core = core;
+	refo->hw.init = &data->init_data;
+	refo->ctrl_reg = data->ctrl_reg + core->iobase;
+	refo->parent_map = data->parent_map;
+
+	clk = devm_clk_register(core->dev, &refo->hw);
+	if (IS_ERR(clk))
+		dev_err(core->dev, "%s: clk_register() failed\n", __func__);
+
+	return clk;
+}
+
+struct pic32_sys_pll {
+	struct clk_hw hw;
+	void __iomem *ctrl_reg;
+	void __iomem *status_reg;
+	u32 lock_mask;
+	u32 idiv; /* PLL iclk divider, treated fixed */
+	struct pic32_clk_common *core;
+};
+
+#define clkhw_to_spll(_hw)	container_of(_hw, struct pic32_sys_pll, hw)
+
+static inline u32 spll_odiv_to_divider(u32 odiv)
+{
+	odiv = clamp_val(odiv, PLL_ODIV_MIN, PLL_ODIV_MAX);
+
+	return 1 << odiv;
+}
+
+static unsigned long spll_calc_mult_div(struct pic32_sys_pll *pll,
+					unsigned long rate,
+					unsigned long parent_rate,
+					u32 *mult_p, u32 *odiv_p)
+{
+	u32 mul, div, best_mul = 1, best_div = 1;
+	unsigned long new_rate, best_rate = rate;
+	unsigned int best_delta = -1, delta, match_found = 0;
+	u64 rate64;
+
+	parent_rate /= pll->idiv;
+
+	for (mul = 1; mul <= PLL_MULT_MAX; mul++) {
+		for (div = PLL_ODIV_MIN; div <= PLL_ODIV_MAX; div++) {
+			rate64 = parent_rate;
+			rate64 *= mul;
+			do_div(rate64, 1 << div);
+			new_rate = rate64;
+			delta = abs(rate - new_rate);
+			if ((new_rate >= rate) && (delta < best_delta)) {
+				best_delta = delta;
+				best_rate = new_rate;
+				best_mul = mul;
+				best_div = div;
+				match_found = 1;
+			}
+		}
+	}
+
+	if (!match_found) {
+		pr_warn("spll: no match found\n");
+		return 0;
+	}
+
+	pr_debug("rate %lu, par_rate %lu/mult %u, div %u, best_rate %lu\n",
+		 rate, parent_rate, best_mul, best_div, best_rate);
+
+	if (mult_p)
+		*mult_p = best_mul - 1;
+
+	if (odiv_p)
+		*odiv_p = best_div;
+
+	return best_rate;
+}
+
+static unsigned long spll_clk_recalc_rate(struct clk_hw *hw,
+					  unsigned long parent_rate)
+{
+	struct pic32_sys_pll *pll = clkhw_to_spll(hw);
+	unsigned long pll_in_rate;
+	u32 mult, odiv, div, v;
+	u64 rate64;
+
+	v = readl(pll->ctrl_reg);
+	odiv = ((v >> PLL_ODIV_SHIFT) & PLL_ODIV_MASK);
+	mult = ((v >> PLL_MULT_SHIFT) & PLL_MULT_MASK) + 1;
+	div = spll_odiv_to_divider(odiv);
+
+	/* pll_in_rate = parent_rate / idiv
+	 * pll_out_rate = pll_in_rate * mult / div;
+	 */
+	pll_in_rate = parent_rate / pll->idiv;
+	rate64 = pll_in_rate;
+	rate64 *= mult;
+	do_div(rate64, div);
+
+	return rate64;
+}
+
+static long spll_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long *parent_rate)
+{
+	struct pic32_sys_pll *pll = clkhw_to_spll(hw);
+
+	return spll_calc_mult_div(pll, rate, *parent_rate, NULL, NULL);
+}
+
+static int spll_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+			     unsigned long parent_rate)
+{
+	struct pic32_sys_pll *pll = clkhw_to_spll(hw);
+	unsigned long ret, flags;
+	u32 mult, odiv, v;
+	int err;
+
+	ret = spll_calc_mult_div(pll, rate, parent_rate, &mult, &odiv);
+	if (!ret)
+		return -EINVAL;
+
+	/*
+	 * We can't change SPLL counters when it is in-active use
+	 * by SYSCLK. So check before applying new counters/rate.
+	 */
+
+	/* Is spll_clk active parent of sys_clk ? */
+	if (unlikely(clk_hw_get_parent(pic32_sclk_hw) == hw)) {
+		pr_err("%s: failed, clk in-use\n", __func__);
+		return -EBUSY;
+	}
+
+	spin_lock_irqsave(&pll->core->reg_lock, flags);
+
+	/* apply new multiplier & divisor */
+	v = readl(pll->ctrl_reg);
+	v &= ~(PLL_MULT_MASK << PLL_MULT_SHIFT);
+	v &= ~(PLL_ODIV_MASK << PLL_ODIV_SHIFT);
+	v |= (mult << PLL_MULT_SHIFT) | (odiv << PLL_ODIV_SHIFT);
+
+	/* sys unlock before write */
+	pic32_syskey_unlock();
+
+	writel(v, pll->ctrl_reg);
+	cpu_relax();
+
+	/* insert few nops (5-stage) to ensure CPU does not hang */
+	cpu_nop5();
+	cpu_nop5();
+
+	/* Wait until PLL is locked (maximum 100 usecs). */
+	err = readl_poll_timeout_atomic(pll->status_reg, v,
+					v & pll->lock_mask, 1, 100);
+	spin_unlock_irqrestore(&pll->core->reg_lock, flags);
+
+	return err;
+}
+
+/* SPLL clock operation */
+const struct clk_ops pic32_spll_ops = {
+	.recalc_rate	= spll_clk_recalc_rate,
+	.round_rate	= spll_clk_round_rate,
+	.set_rate	= spll_clk_set_rate,
+};
+
+struct clk *pic32_spll_clk_register(const struct pic32_sys_pll_data *data,
+				    struct pic32_clk_common *core)
+{
+	struct pic32_sys_pll *spll;
+	struct clk *clk;
+
+	spll = devm_kzalloc(core->dev, sizeof(*spll), GFP_KERNEL);
+	if (!spll)
+		return ERR_PTR(-ENOMEM);
+
+	spll->core = core;
+	spll->hw.init = &data->init_data;
+	spll->ctrl_reg = data->ctrl_reg + core->iobase;
+	spll->status_reg = data->status_reg + core->iobase;
+	spll->lock_mask = data->lock_mask;
+
+	/* cache PLL idiv; PLL driver uses it as constant.*/
+	spll->idiv = (readl(spll->ctrl_reg) >> PLL_IDIV_SHIFT) & PLL_IDIV_MASK;
+	spll->idiv += 1;
+
+	clk = devm_clk_register(core->dev, &spll->hw);
+	if (IS_ERR(clk))
+		dev_err(core->dev, "sys_pll: clk_register() failed\n");
+
+	return clk;
+}
+
+/* System mux clock(aka SCLK) */
+
+struct pic32_sys_clk {
+	struct clk_hw hw;
+	void __iomem *mux_reg;
+	void __iomem *slew_reg;
+	u32 slew_div;
+	const u32 *parent_map;
+	struct pic32_clk_common *core;
+};
+
+#define clkhw_to_sys_clk(_hw)	container_of(_hw, struct pic32_sys_clk, hw)
+
+static unsigned long sclk_get_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+	struct pic32_sys_clk *sclk = clkhw_to_sys_clk(hw);
+	u32 div;
+
+	div = (readl(sclk->slew_reg) >> SLEW_SYSDIV_SHIFT) & SLEW_SYSDIV;
+	div += 1; /* sys-div to divider */
+
+	return parent_rate / div;
+}
+
+static long sclk_round_rate(struct clk_hw *hw, unsigned long rate,
+			    unsigned long *parent_rate)
+{
+	return calc_best_divided_rate(rate, *parent_rate, SLEW_SYSDIV, 1);
+}
+
+static int sclk_set_rate(struct clk_hw *hw,
+			 unsigned long rate, unsigned long parent_rate)
+{
+	struct pic32_sys_clk *sclk = clkhw_to_sys_clk(hw);
+	unsigned long flags;
+	u32 v, div;
+	int err;
+
+	div = parent_rate / rate;
+
+	spin_lock_irqsave(&sclk->core->reg_lock, flags);
+
+	/* apply new div */
+	v = readl(sclk->slew_reg);
+	v &= ~(SLEW_SYSDIV << SLEW_SYSDIV_SHIFT);
+	v |= (div - 1) << SLEW_SYSDIV_SHIFT;
+
+	pic32_syskey_unlock();
+
+	writel(v, sclk->slew_reg);
+
+	/* wait until BUSY is cleared */
+	err = readl_poll_timeout_atomic(sclk->slew_reg, v,
+					!(v & SLEW_BUSY), 1, LOCK_TIMEOUT_US);
+
+	spin_unlock_irqrestore(&sclk->core->reg_lock, flags);
+
+	return err;
+}
+
+static u8 sclk_get_parent(struct clk_hw *hw)
+{
+	struct pic32_sys_clk *sclk = clkhw_to_sys_clk(hw);
+	u32 i, v;
+
+	v = (readl(sclk->mux_reg) >> OSC_CUR_SHIFT) & OSC_CUR_MASK;
+
+	if (!sclk->parent_map)
+		return v;
+
+	for (i = 0; i < clk_hw_get_num_parents(hw); i++)
+		if (sclk->parent_map[i] == v)
+			return i;
+	return -EINVAL;
+}
+
+static int sclk_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct pic32_sys_clk *sclk = clkhw_to_sys_clk(hw);
+	unsigned long flags;
+	u32 nosc, cosc, v;
+	int err;
+
+	spin_lock_irqsave(&sclk->core->reg_lock, flags);
+
+	/* find new_osc */
+	nosc = sclk->parent_map ? sclk->parent_map[index] : index;
+
+	/* set new parent */
+	v = readl(sclk->mux_reg);
+	v &= ~(OSC_NEW_MASK << OSC_NEW_SHIFT);
+	v |= nosc << OSC_NEW_SHIFT;
+
+	pic32_syskey_unlock();
+
+	writel(v, sclk->mux_reg);
+
+	/* initate switch */
+	writel(OSC_SWEN, PIC32_SET(sclk->mux_reg));
+	cpu_relax();
+
+	/* add nop to flush pipeline (as cpu_clk is in-flux) */
+	cpu_nop5();
+
+	/* wait for SWEN bit to clear */
+	err = readl_poll_timeout_atomic(sclk->slew_reg, v,
+					!(v & OSC_SWEN), 1, LOCK_TIMEOUT_US);
+
+	spin_unlock_irqrestore(&sclk->core->reg_lock, flags);
+
+	/*
+	 * SCLK clock-switching logic might reject a clock switching request
+	 * if pre-requisites (like new clk_src not present or unstable) are
+	 * not met.
+	 * So confirm before claiming success.
+	 */
+	cosc = (readl(sclk->mux_reg) >> OSC_CUR_SHIFT) & OSC_CUR_MASK;
+	if (cosc != nosc) {
+		pr_err("%s: err, failed to set_parent() to %d, current %d\n",
+		       clk_hw_get_name(hw), nosc, cosc);
+		err = -EBUSY;
+	}
+
+	return err;
+}
+
+static void sclk_init(struct clk_hw *hw)
+{
+	struct pic32_sys_clk *sclk = clkhw_to_sys_clk(hw);
+	unsigned long flags;
+	u32 v;
+
+	/* Maintain reference to this clk, required in spll_clk_set_rate() */
+	pic32_sclk_hw = hw;
+
+	/* apply slew divider on both up and down scaling */
+	if (sclk->slew_div) {
+		spin_lock_irqsave(&sclk->core->reg_lock, flags);
+		v = readl(sclk->slew_reg);
+		v &= ~(SLEW_DIV << SLEW_DIV_SHIFT);
+		v |= sclk->slew_div << SLEW_DIV_SHIFT;
+		v |= SLEW_DOWNEN | SLEW_UPEN;
+		writel(v, sclk->slew_reg);
+		spin_unlock_irqrestore(&sclk->core->reg_lock, flags);
+	}
+}
+
+/* sclk with post-divider */
+const struct clk_ops pic32_sclk_ops = {
+	.get_parent	= sclk_get_parent,
+	.set_parent	= sclk_set_parent,
+	.round_rate	= sclk_round_rate,
+	.set_rate	= sclk_set_rate,
+	.recalc_rate	= sclk_get_rate,
+	.init		= sclk_init,
+	.determine_rate = __clk_mux_determine_rate,
+};
+
+/* sclk with no slew and no post-divider */
+const struct clk_ops pic32_sclk_no_div_ops = {
+	.get_parent	= sclk_get_parent,
+	.set_parent	= sclk_set_parent,
+	.init		= sclk_init,
+	.determine_rate = __clk_mux_determine_rate,
+};
+
+struct clk *pic32_sys_clk_register(const struct pic32_sys_clk_data *data,
+				   struct pic32_clk_common *core)
+{
+	struct pic32_sys_clk *sclk;
+	struct clk *clk;
+
+	sclk = devm_kzalloc(core->dev, sizeof(*sclk), GFP_KERNEL);
+	if (!sclk)
+		return ERR_PTR(-ENOMEM);
+
+	sclk->core = core;
+	sclk->hw.init = &data->init_data;
+	sclk->mux_reg = data->mux_reg + core->iobase;
+	sclk->slew_reg = data->slew_reg + core->iobase;
+	sclk->slew_div = data->slew_div;
+	sclk->parent_map = data->parent_map;
+
+	clk = devm_clk_register(core->dev, &sclk->hw);
+	if (IS_ERR(clk))
+		dev_err(core->dev, "%s: clk register failed\n", __func__);
+
+	return clk;
+}
+
+/* secondary oscillator */
+struct pic32_sec_osc {
+	struct clk_hw hw;
+	void __iomem *enable_reg;
+	void __iomem *status_reg;
+	u32 enable_mask;
+	u32 status_mask;
+	unsigned long fixed_rate;
+	struct pic32_clk_common *core;
+};
+
+#define clkhw_to_sosc(_hw)	container_of(_hw, struct pic32_sec_osc, hw)
+static int sosc_clk_enable(struct clk_hw *hw)
+{
+	struct pic32_sec_osc *sosc = clkhw_to_sosc(hw);
+	u32 v;
+
+	/* enable SOSC */
+	pic32_syskey_unlock();
+	writel(sosc->enable_mask, PIC32_SET(sosc->enable_reg));
+
+	/* wait till warm-up period expires or ready-status is updated */
+	return readl_poll_timeout_atomic(sosc->status_reg, v,
+					 v & sosc->status_mask, 1, 100);
+}
+
+static void sosc_clk_disable(struct clk_hw *hw)
+{
+	struct pic32_sec_osc *sosc = clkhw_to_sosc(hw);
+
+	pic32_syskey_unlock();
+	writel(sosc->enable_mask, PIC32_CLR(sosc->enable_reg));
+}
+
+static int sosc_clk_is_enabled(struct clk_hw *hw)
+{
+	struct pic32_sec_osc *sosc = clkhw_to_sosc(hw);
+	u32 enabled, ready;
+
+	/* check enabled and ready status */
+	enabled = readl(sosc->enable_reg) & sosc->enable_mask;
+	ready = readl(sosc->status_reg) & sosc->status_mask;
+
+	return enabled && ready;
+}
+
+static unsigned long sosc_clk_calc_rate(struct clk_hw *hw,
+					unsigned long parent_rate)
+{
+	return clkhw_to_sosc(hw)->fixed_rate;
+}
+
+const struct clk_ops pic32_sosc_ops = {
+	.enable = sosc_clk_enable,
+	.disable = sosc_clk_disable,
+	.is_enabled = sosc_clk_is_enabled,
+	.recalc_rate = sosc_clk_calc_rate,
+};
+
+struct clk *pic32_sosc_clk_register(const struct pic32_sec_osc_data *data,
+				    struct pic32_clk_common *core)
+{
+	struct pic32_sec_osc *sosc;
+
+	sosc = devm_kzalloc(core->dev, sizeof(*sosc), GFP_KERNEL);
+	if (!sosc)
+		return ERR_PTR(-ENOMEM);
+
+	sosc->core = core;
+	sosc->hw.init = &data->init_data;
+	sosc->fixed_rate = data->fixed_rate;
+	sosc->enable_mask = data->enable_mask;
+	sosc->status_mask = data->status_mask;
+	sosc->enable_reg = data->enable_reg + core->iobase;
+	sosc->status_reg = data->status_reg + core->iobase;
+
+	return devm_clk_register(core->dev, &sosc->hw);
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/microchip/clk-core.h linux-libre-4.7-gnu/drivers/clk/microchip/clk-core.h
--- linux-libre-4.6-gnu/drivers/clk/microchip/clk-core.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/clk/microchip/clk-core.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,84 @@
+/*
+ * Purna Chandra Mandal,<purna.mandal@microchip.com>
+ * Copyright (C) 2015 Microchip Technology Inc.  All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ */
+#ifndef __MICROCHIP_CLK_PIC32_H_
+#define __MICROCHIP_CLK_PIC32_H_
+
+#include <linux/clk-provider.h>
+
+/* PIC32 clock data */
+struct pic32_clk_common {
+	struct device *dev;
+	void __iomem *iobase;
+	spinlock_t reg_lock; /* clock lock */
+};
+
+/* System PLL clock */
+struct pic32_sys_pll_data {
+	struct clk_init_data init_data;
+	const u32 ctrl_reg;
+	const u32 status_reg;
+	const u32 lock_mask;
+};
+
+/* System clock */
+struct pic32_sys_clk_data {
+	struct clk_init_data init_data;
+	const u32 mux_reg;
+	const u32 slew_reg;
+	const u32 *parent_map;
+	const u32 slew_div;
+};
+
+/* Reference Oscillator clock */
+struct pic32_ref_osc_data {
+	struct clk_init_data init_data;
+	const u32 ctrl_reg;
+	const u32 *parent_map;
+};
+
+/* Peripheral Bus clock */
+struct pic32_periph_clk_data {
+	struct clk_init_data init_data;
+	const u32 ctrl_reg;
+};
+
+/* External Secondary Oscillator clock  */
+struct pic32_sec_osc_data {
+	struct clk_init_data init_data;
+	const u32 enable_reg;
+	const u32 status_reg;
+	const u32 enable_mask;
+	const u32 status_mask;
+	const unsigned long fixed_rate;
+};
+
+extern const struct clk_ops pic32_pbclk_ops;
+extern const struct clk_ops pic32_sclk_ops;
+extern const struct clk_ops pic32_sclk_no_div_ops;
+extern const struct clk_ops pic32_spll_ops;
+extern const struct clk_ops pic32_roclk_ops;
+extern const struct clk_ops pic32_sosc_ops;
+
+struct clk *pic32_periph_clk_register(const struct pic32_periph_clk_data *data,
+				      struct pic32_clk_common *core);
+struct clk *pic32_refo_clk_register(const struct pic32_ref_osc_data *data,
+				    struct pic32_clk_common *core);
+struct clk *pic32_sys_clk_register(const struct pic32_sys_clk_data *data,
+				   struct pic32_clk_common *core);
+struct clk *pic32_spll_clk_register(const struct pic32_sys_pll_data *data,
+				    struct pic32_clk_common *core);
+struct clk *pic32_sosc_clk_register(const struct pic32_sec_osc_data *data,
+				    struct pic32_clk_common *core);
+
+#endif /* __MICROCHIP_CLK_PIC32_H_*/
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/microchip/clk-pic32mzda.c linux-libre-4.7-gnu/drivers/clk/microchip/clk-pic32mzda.c
--- linux-libre-4.6-gnu/drivers/clk/microchip/clk-pic32mzda.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/clk/microchip/clk-pic32mzda.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,275 @@
+/*
+ * Purna Chandra Mandal,<purna.mandal@microchip.com>
+ * Copyright (C) 2015 Microchip Technology Inc.  All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ */
+#include <dt-bindings/clock/microchip,pic32-clock.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <asm/traps.h>
+
+#include "clk-core.h"
+
+/* FRC Postscaler */
+#define OSC_FRCDIV_MASK		0x07
+#define OSC_FRCDIV_SHIFT	24
+
+/* SPLL fields */
+#define PLL_ICLK_MASK		0x01
+#define PLL_ICLK_SHIFT		7
+
+#define DECLARE_PERIPHERAL_CLOCK(__clk_name, __reg, __flags)	\
+	{							\
+		.ctrl_reg = (__reg),				\
+		.init_data = {					\
+			.name = (__clk_name),			\
+			.parent_names = (const char *[]) {	\
+				"sys_clk"			\
+			},					\
+			.num_parents = 1,			\
+			.ops = &pic32_pbclk_ops,		\
+			.flags = (__flags),			\
+		},						\
+	}
+
+#define DECLARE_REFO_CLOCK(__clkid, __reg)				\
+	{								\
+		.ctrl_reg = (__reg),					\
+		.init_data = {						\
+			.name = "refo" #__clkid "_clk",			\
+			.parent_names = (const char *[]) {		\
+				"sys_clk", "pb1_clk", "posc_clk",	\
+				"frc_clk", "lprc_clk", "sosc_clk",	\
+				"sys_pll", "refi" #__clkid "_clk",	\
+				"bfrc_clk",				\
+			},						\
+			.num_parents = 9,				\
+			.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE,\
+			.ops = &pic32_roclk_ops,			\
+		},							\
+		.parent_map = (const u32[]) {				\
+			0, 1, 2, 3, 4, 5, 7, 8, 9			\
+		},							\
+	}
+
+static const struct pic32_ref_osc_data ref_clks[] = {
+	DECLARE_REFO_CLOCK(1, 0x80),
+	DECLARE_REFO_CLOCK(2, 0xa0),
+	DECLARE_REFO_CLOCK(3, 0xc0),
+	DECLARE_REFO_CLOCK(4, 0xe0),
+	DECLARE_REFO_CLOCK(5, 0x100),
+};
+
+static const struct pic32_periph_clk_data periph_clocks[] = {
+	DECLARE_PERIPHERAL_CLOCK("pb1_clk", 0x140, 0),
+	DECLARE_PERIPHERAL_CLOCK("pb2_clk", 0x150, CLK_IGNORE_UNUSED),
+	DECLARE_PERIPHERAL_CLOCK("pb3_clk", 0x160, 0),
+	DECLARE_PERIPHERAL_CLOCK("pb4_clk", 0x170, 0),
+	DECLARE_PERIPHERAL_CLOCK("pb5_clk", 0x180, 0),
+	DECLARE_PERIPHERAL_CLOCK("pb6_clk", 0x190, 0),
+	DECLARE_PERIPHERAL_CLOCK("cpu_clk", 0x1a0, CLK_IGNORE_UNUSED),
+};
+
+static const struct pic32_sys_clk_data sys_mux_clk = {
+	.slew_reg = 0x1c0,
+	.slew_div = 2, /* step of div_4 -> div_2 -> no_div */
+	.init_data = {
+		.name = "sys_clk",
+		.parent_names = (const char *[]) {
+			"frcdiv_clk", "sys_pll", "posc_clk",
+			"sosc_clk", "lprc_clk", "frcdiv_clk",
+		},
+		.num_parents = 6,
+		.ops = &pic32_sclk_ops,
+	},
+	.parent_map = (const u32[]) {
+		0, 1, 2, 4, 5, 7,
+	},
+};
+
+static const struct pic32_sys_pll_data sys_pll = {
+	.ctrl_reg = 0x020,
+	.status_reg = 0x1d0,
+	.lock_mask = BIT(7),
+	.init_data = {
+		.name = "sys_pll",
+		.parent_names = (const char *[]) {
+			"spll_mux_clk"
+		},
+		.num_parents = 1,
+		.ops = &pic32_spll_ops,
+	},
+};
+
+static const struct pic32_sec_osc_data sosc_clk = {
+	.status_reg = 0x1d0,
+	.enable_mask = BIT(1),
+	.status_mask = BIT(4),
+	.init_data = {
+		.name = "sosc_clk",
+		.parent_names = NULL,
+		.ops = &pic32_sosc_ops,
+	},
+};
+
+static int pic32mzda_critical_clks[] = {
+	PB2CLK, PB7CLK
+};
+
+/* PIC32MZDA clock data */
+struct pic32mzda_clk_data {
+	struct clk *clks[MAXCLKS];
+	struct pic32_clk_common core;
+	struct clk_onecell_data onecell_data;
+	struct notifier_block failsafe_notifier;
+};
+
+static int pic32_fscm_nmi(struct notifier_block *nb,
+			  unsigned long action, void *data)
+{
+	struct pic32mzda_clk_data *cd;
+
+	cd  = container_of(nb, struct pic32mzda_clk_data, failsafe_notifier);
+
+	/* SYSCLK is now running from BFRCCLK. Report clock failure. */
+	if (readl(cd->core.iobase) & BIT(2))
+		pr_alert("pic32-clk: FSCM detected clk failure.\n");
+
+	/* TODO: detect reason of failure and recover accordingly */
+
+	return NOTIFY_OK;
+}
+
+static int pic32mzda_clk_probe(struct platform_device *pdev)
+{
+	const char *const pll_mux_parents[] = {"posc_clk", "frc_clk"};
+	struct device_node *np = pdev->dev.of_node;
+	struct pic32mzda_clk_data *cd;
+	struct pic32_clk_common *core;
+	struct clk *pll_mux_clk, *clk;
+	struct clk **clks;
+	int nr_clks, i, ret;
+
+	cd = devm_kzalloc(&pdev->dev, sizeof(*cd), GFP_KERNEL);
+	if (!cd)
+		return -ENOMEM;
+
+	core = &cd->core;
+	core->iobase = of_io_request_and_map(np, 0, of_node_full_name(np));
+	if (IS_ERR(core->iobase)) {
+		dev_err(&pdev->dev, "pic32-clk: failed to map registers\n");
+		return PTR_ERR(core->iobase);
+	}
+
+	spin_lock_init(&core->reg_lock);
+	core->dev = &pdev->dev;
+	clks = &cd->clks[0];
+
+	/* register fixed rate clocks */
+	clks[POSCCLK] = clk_register_fixed_rate(&pdev->dev, "posc_clk", NULL,
+						0, 24000000);
+	clks[FRCCLK] =  clk_register_fixed_rate(&pdev->dev, "frc_clk", NULL,
+						0, 8000000);
+	clks[BFRCCLK] = clk_register_fixed_rate(&pdev->dev, "bfrc_clk", NULL,
+						0, 8000000);
+	clks[LPRCCLK] = clk_register_fixed_rate(&pdev->dev, "lprc_clk", NULL,
+						0, 32000);
+	clks[UPLLCLK] = clk_register_fixed_rate(&pdev->dev, "usbphy_clk", NULL,
+						0, 24000000);
+	/* fixed rate (optional) clock */
+	if (of_find_property(np, "microchip,pic32mzda-sosc", NULL)) {
+		pr_info("pic32-clk: dt requests SOSC.\n");
+		clks[SOSCCLK] = pic32_sosc_clk_register(&sosc_clk, core);
+	}
+	/* divider clock */
+	clks[FRCDIVCLK] = clk_register_divider(&pdev->dev, "frcdiv_clk",
+					       "frc_clk", 0,
+					       core->iobase,
+					       OSC_FRCDIV_SHIFT,
+					       OSC_FRCDIV_MASK,
+					       CLK_DIVIDER_POWER_OF_TWO,
+					       &core->reg_lock);
+	/* PLL ICLK mux */
+	pll_mux_clk = clk_register_mux(&pdev->dev, "spll_mux_clk",
+				       pll_mux_parents, 2, 0,
+				       core->iobase + 0x020,
+				       PLL_ICLK_SHIFT, 1, 0, &core->reg_lock);
+	if (IS_ERR(pll_mux_clk))
+		pr_err("spll_mux_clk: clk register failed\n");
+
+	/* PLL */
+	clks[PLLCLK] = pic32_spll_clk_register(&sys_pll, core);
+	/* SYSTEM clock */
+	clks[SCLK] = pic32_sys_clk_register(&sys_mux_clk, core);
+	/* Peripheral bus clocks */
+	for (nr_clks = PB1CLK, i = 0; nr_clks <= PB7CLK; i++, nr_clks++)
+		clks[nr_clks] = pic32_periph_clk_register(&periph_clocks[i],
+							  core);
+	/* Reference oscillator clock */
+	for (nr_clks = REF1CLK, i = 0; nr_clks <= REF5CLK; i++, nr_clks++)
+		clks[nr_clks] = pic32_refo_clk_register(&ref_clks[i], core);
+
+	/* register clkdev */
+	for (i = 0; i < MAXCLKS; i++) {
+		if (IS_ERR(clks[i]))
+			continue;
+		clk_register_clkdev(clks[i], NULL, __clk_get_name(clks[i]));
+	}
+
+	/* register clock provider */
+	cd->onecell_data.clks = clks;
+	cd->onecell_data.clk_num = MAXCLKS;
+	ret = of_clk_add_provider(np, of_clk_src_onecell_get,
+				  &cd->onecell_data);
+	if (ret)
+		return ret;
+
+	/* force enable critical clocks */
+	for (i = 0; i < ARRAY_SIZE(pic32mzda_critical_clks); i++) {
+		clk = clks[pic32mzda_critical_clks[i]];
+		if (clk_prepare_enable(clk))
+			dev_err(&pdev->dev, "clk_prepare_enable(%s) failed\n",
+				__clk_get_name(clk));
+	}
+
+	/* register NMI for failsafe clock monitor */
+	cd->failsafe_notifier.notifier_call = pic32_fscm_nmi;
+	return register_nmi_notifier(&cd->failsafe_notifier);
+}
+
+static const struct of_device_id pic32mzda_clk_match_table[] = {
+	{ .compatible = "microchip,pic32mzda-clk", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, pic32mzda_clk_match_table);
+
+static struct platform_driver pic32mzda_clk_driver = {
+	.probe		= pic32mzda_clk_probe,
+	.driver		= {
+		.name	= "clk-pic32mzda",
+		.of_match_table = pic32mzda_clk_match_table,
+	},
+};
+
+static int __init microchip_pic32mzda_clk_init(void)
+{
+	return platform_driver_register(&pic32mzda_clk_driver);
+}
+core_initcall(microchip_pic32mzda_clk_init);
+
+MODULE_DESCRIPTION("Microchip PIC32MZDA Clock Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:clk-pic32mzda");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/microchip/Makefile linux-libre-4.7-gnu/drivers/clk/microchip/Makefile
--- linux-libre-4.6-gnu/drivers/clk/microchip/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/clk/microchip/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,2 @@
+obj-$(CONFIG_COMMON_CLK_PIC32) += clk-core.o
+obj-$(CONFIG_PIC32MZDA) += clk-pic32mzda.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/mmp/clk-mmp2.c linux-libre-4.7-gnu/drivers/clk/mmp/clk-mmp2.c
--- linux-libre-4.6-gnu/drivers/clk/mmp/clk-mmp2.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/mmp/clk-mmp2.c	2016-07-24 15:23:50.000000000 -0400
@@ -99,23 +99,19 @@ void __init mmp2_clk_init(phys_addr_t mp
 		return;
 	}
 
-	clk = clk_register_fixed_rate(NULL, "clk32", NULL, CLK_IS_ROOT, 3200);
+	clk = clk_register_fixed_rate(NULL, "clk32", NULL, 0, 3200);
 	clk_register_clkdev(clk, "clk32", NULL);
 
-	vctcxo = clk_register_fixed_rate(NULL, "vctcxo", NULL, CLK_IS_ROOT,
-				26000000);
+	vctcxo = clk_register_fixed_rate(NULL, "vctcxo", NULL, 0, 26000000);
 	clk_register_clkdev(vctcxo, "vctcxo", NULL);
 
-	clk = clk_register_fixed_rate(NULL, "pll1", NULL, CLK_IS_ROOT,
-				800000000);
+	clk = clk_register_fixed_rate(NULL, "pll1", NULL, 0, 800000000);
 	clk_register_clkdev(clk, "pll1", NULL);
 
-	clk = clk_register_fixed_rate(NULL, "usb_pll", NULL, CLK_IS_ROOT,
-				480000000);
+	clk = clk_register_fixed_rate(NULL, "usb_pll", NULL, 0, 480000000);
 	clk_register_clkdev(clk, "usb_pll", NULL);
 
-	clk = clk_register_fixed_rate(NULL, "pll2", NULL, CLK_IS_ROOT,
-				960000000);
+	clk = clk_register_fixed_rate(NULL, "pll2", NULL, 0, 960000000);
 	clk_register_clkdev(clk, "pll2", NULL);
 
 	clk = clk_register_fixed_factor(NULL, "pll1_2", "pll1",
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/mmp/clk-of-mmp2.c linux-libre-4.7-gnu/drivers/clk/mmp/clk-of-mmp2.c
--- linux-libre-4.6-gnu/drivers/clk/mmp/clk-of-mmp2.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/mmp/clk-of-mmp2.c	2016-07-24 15:23:50.000000000 -0400
@@ -63,11 +63,11 @@ struct mmp2_clk_unit {
 };
 
 static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = {
-	{MMP2_CLK_CLK32, "clk32", NULL, CLK_IS_ROOT, 32768},
-	{MMP2_CLK_VCTCXO, "vctcxo", NULL, CLK_IS_ROOT, 26000000},
-	{MMP2_CLK_PLL1, "pll1", NULL, CLK_IS_ROOT, 800000000},
-	{MMP2_CLK_PLL2, "pll2", NULL, CLK_IS_ROOT, 960000000},
-	{MMP2_CLK_USB_PLL, "usb_pll", NULL, CLK_IS_ROOT, 480000000},
+	{MMP2_CLK_CLK32, "clk32", NULL, 0, 32768},
+	{MMP2_CLK_VCTCXO, "vctcxo", NULL, 0, 26000000},
+	{MMP2_CLK_PLL1, "pll1", NULL, 0, 800000000},
+	{MMP2_CLK_PLL2, "pll2", NULL, 0, 960000000},
+	{MMP2_CLK_USB_PLL, "usb_pll", NULL, 0, 480000000},
 };
 
 static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/mmp/clk-of-pxa168.c linux-libre-4.7-gnu/drivers/clk/mmp/clk-of-pxa168.c
--- linux-libre-4.6-gnu/drivers/clk/mmp/clk-of-pxa168.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/mmp/clk-of-pxa168.c	2016-07-24 15:23:50.000000000 -0400
@@ -56,10 +56,10 @@ struct pxa168_clk_unit {
 };
 
 static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = {
-	{PXA168_CLK_CLK32, "clk32", NULL, CLK_IS_ROOT, 32768},
-	{PXA168_CLK_VCTCXO, "vctcxo", NULL, CLK_IS_ROOT, 26000000},
-	{PXA168_CLK_PLL1, "pll1", NULL, CLK_IS_ROOT, 624000000},
-	{PXA168_CLK_USB_PLL, "usb_pll", NULL, CLK_IS_ROOT, 480000000},
+	{PXA168_CLK_CLK32, "clk32", NULL, 0, 32768},
+	{PXA168_CLK_VCTCXO, "vctcxo", NULL, 0, 26000000},
+	{PXA168_CLK_PLL1, "pll1", NULL, 0, 624000000},
+	{PXA168_CLK_USB_PLL, "usb_pll", NULL, 0, 480000000},
 };
 
 static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/mmp/clk-of-pxa1928.c linux-libre-4.7-gnu/drivers/clk/mmp/clk-of-pxa1928.c
--- linux-libre-4.6-gnu/drivers/clk/mmp/clk-of-pxa1928.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/mmp/clk-of-pxa1928.c	2016-07-24 15:23:50.000000000 -0400
@@ -34,12 +34,12 @@ struct pxa1928_clk_unit {
 };
 
 static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = {
-	{0, "clk32", NULL, CLK_IS_ROOT, 32768},
-	{0, "vctcxo", NULL, CLK_IS_ROOT, 26000000},
-	{0, "pll1_624", NULL, CLK_IS_ROOT, 624000000},
-	{0, "pll5p", NULL, CLK_IS_ROOT, 832000000},
-	{0, "pll5", NULL, CLK_IS_ROOT, 1248000000},
-	{0, "usb_pll", NULL, CLK_IS_ROOT, 480000000},
+	{0, "clk32", NULL, 0, 32768},
+	{0, "vctcxo", NULL, 0, 26000000},
+	{0, "pll1_624", NULL, 0, 624000000},
+	{0, "pll5p", NULL, 0, 832000000},
+	{0, "pll5", NULL, 0, 1248000000},
+	{0, "usb_pll", NULL, 0, 480000000},
 };
 
 static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/mmp/clk-of-pxa910.c linux-libre-4.7-gnu/drivers/clk/mmp/clk-of-pxa910.c
--- linux-libre-4.6-gnu/drivers/clk/mmp/clk-of-pxa910.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/mmp/clk-of-pxa910.c	2016-07-24 15:23:50.000000000 -0400
@@ -56,10 +56,10 @@ struct pxa910_clk_unit {
 };
 
 static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = {
-	{PXA910_CLK_CLK32, "clk32", NULL, CLK_IS_ROOT, 32768},
-	{PXA910_CLK_VCTCXO, "vctcxo", NULL, CLK_IS_ROOT, 26000000},
-	{PXA910_CLK_PLL1, "pll1", NULL, CLK_IS_ROOT, 624000000},
-	{PXA910_CLK_USB_PLL, "usb_pll", NULL, CLK_IS_ROOT, 480000000},
+	{PXA910_CLK_CLK32, "clk32", NULL, 0, 32768},
+	{PXA910_CLK_VCTCXO, "vctcxo", NULL, 0, 26000000},
+	{PXA910_CLK_PLL1, "pll1", NULL, 0, 624000000},
+	{PXA910_CLK_USB_PLL, "usb_pll", NULL, 0, 480000000},
 };
 
 static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/mmp/clk-pxa168.c linux-libre-4.7-gnu/drivers/clk/mmp/clk-pxa168.c
--- linux-libre-4.6-gnu/drivers/clk/mmp/clk-pxa168.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/mmp/clk-pxa168.c	2016-07-24 15:23:50.000000000 -0400
@@ -92,15 +92,13 @@ void __init pxa168_clk_init(phys_addr_t
 		return;
 	}
 
-	clk = clk_register_fixed_rate(NULL, "clk32", NULL, CLK_IS_ROOT, 3200);
+	clk = clk_register_fixed_rate(NULL, "clk32", NULL, 0, 3200);
 	clk_register_clkdev(clk, "clk32", NULL);
 
-	clk = clk_register_fixed_rate(NULL, "vctcxo", NULL, CLK_IS_ROOT,
-				26000000);
+	clk = clk_register_fixed_rate(NULL, "vctcxo", NULL, 0, 26000000);
 	clk_register_clkdev(clk, "vctcxo", NULL);
 
-	clk = clk_register_fixed_rate(NULL, "pll1", NULL, CLK_IS_ROOT,
-				624000000);
+	clk = clk_register_fixed_rate(NULL, "pll1", NULL, 0, 624000000);
 	clk_register_clkdev(clk, "pll1", NULL);
 
 	clk = clk_register_fixed_factor(NULL, "pll1_2", "pll1",
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/mmp/clk-pxa910.c linux-libre-4.7-gnu/drivers/clk/mmp/clk-pxa910.c
--- linux-libre-4.6-gnu/drivers/clk/mmp/clk-pxa910.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/mmp/clk-pxa910.c	2016-07-24 15:23:50.000000000 -0400
@@ -97,15 +97,13 @@ void __init pxa910_clk_init(phys_addr_t
 		return;
 	}
 
-	clk = clk_register_fixed_rate(NULL, "clk32", NULL, CLK_IS_ROOT, 3200);
+	clk = clk_register_fixed_rate(NULL, "clk32", NULL, 0, 3200);
 	clk_register_clkdev(clk, "clk32", NULL);
 
-	clk = clk_register_fixed_rate(NULL, "vctcxo", NULL, CLK_IS_ROOT,
-				26000000);
+	clk = clk_register_fixed_rate(NULL, "vctcxo", NULL, 0, 26000000);
 	clk_register_clkdev(clk, "vctcxo", NULL);
 
-	clk = clk_register_fixed_rate(NULL, "pll1", NULL, CLK_IS_ROOT,
-				624000000);
+	clk = clk_register_fixed_rate(NULL, "pll1", NULL, 0, 624000000);
 	clk_register_clkdev(clk, "pll1", NULL);
 
 	clk = clk_register_fixed_factor(NULL, "pll1_2", "pll1",
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/mvebu/ap806-system-controller.c linux-libre-4.7-gnu/drivers/clk/mvebu/ap806-system-controller.c
--- linux-libre-4.6-gnu/drivers/clk/mvebu/ap806-system-controller.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/clk/mvebu/ap806-system-controller.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,168 @@
+/*
+ * Marvell Armada AP806 System Controller
+ *
+ * Copyright (C) 2016 Marvell
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#define pr_fmt(fmt) "ap806-system-controller: " fmt
+
+#include <linux/clk-provider.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define AP806_SAR_REG			0x400
+#define AP806_SAR_CLKFREQ_MODE_MASK	0x1f
+
+#define AP806_CLK_NUM			4
+
+static struct clk *ap806_clks[AP806_CLK_NUM];
+
+static struct clk_onecell_data ap806_clk_data = {
+	.clks = ap806_clks,
+	.clk_num = AP806_CLK_NUM,
+};
+
+static int ap806_syscon_clk_probe(struct platform_device *pdev)
+{
+	unsigned int freq_mode, cpuclk_freq;
+	const char *name, *fixedclk_name;
+	struct device_node *np = pdev->dev.of_node;
+	struct regmap *regmap;
+	u32 reg;
+	int ret;
+
+	regmap = syscon_node_to_regmap(np);
+	if (IS_ERR(regmap)) {
+		dev_err(&pdev->dev, "cannot get regmap\n");
+		return PTR_ERR(regmap);
+	}
+
+	ret = regmap_read(regmap, AP806_SAR_REG, &reg);
+	if (ret) {
+		dev_err(&pdev->dev, "cannot read from regmap\n");
+		return ret;
+	}
+
+	freq_mode = reg & AP806_SAR_CLKFREQ_MODE_MASK;
+	switch (freq_mode) {
+	case 0x0 ... 0x5:
+		cpuclk_freq = 2000;
+		break;
+	case 0x6 ... 0xB:
+		cpuclk_freq = 1800;
+		break;
+	case 0xC ... 0x11:
+		cpuclk_freq = 1600;
+		break;
+	case 0x12 ... 0x16:
+		cpuclk_freq = 1400;
+		break;
+	case 0x17 ... 0x19:
+		cpuclk_freq = 1300;
+		break;
+	default:
+		dev_err(&pdev->dev, "invalid SAR value\n");
+		return -EINVAL;
+	}
+
+	/* Convert to hertz */
+	cpuclk_freq *= 1000 * 1000;
+
+	/* CPU clocks depend on the Sample At Reset configuration */
+	of_property_read_string_index(np, "clock-output-names",
+				      0, &name);
+	ap806_clks[0] = clk_register_fixed_rate(&pdev->dev, name, NULL,
+						0, cpuclk_freq);
+	if (IS_ERR(ap806_clks[0])) {
+		ret = PTR_ERR(ap806_clks[0]);
+		goto fail0;
+	}
+
+	of_property_read_string_index(np, "clock-output-names",
+				      1, &name);
+	ap806_clks[1] = clk_register_fixed_rate(&pdev->dev, name, NULL, 0,
+						cpuclk_freq);
+	if (IS_ERR(ap806_clks[1])) {
+		ret = PTR_ERR(ap806_clks[1]);
+		goto fail1;
+	}
+
+	/* Fixed clock is always 1200 Mhz */
+	of_property_read_string_index(np, "clock-output-names",
+				      2, &fixedclk_name);
+	ap806_clks[2] = clk_register_fixed_rate(&pdev->dev, fixedclk_name, NULL,
+						0, 1200 * 1000 * 1000);
+	if (IS_ERR(ap806_clks[2])) {
+		ret = PTR_ERR(ap806_clks[2]);
+		goto fail2;
+	}
+
+	/* MSS Clock is fixed clock divided by 6 */
+	of_property_read_string_index(np, "clock-output-names",
+				      3, &name);
+	ap806_clks[3] = clk_register_fixed_factor(NULL, name, fixedclk_name,
+						  0, 1, 6);
+	if (IS_ERR(ap806_clks[3])) {
+		ret = PTR_ERR(ap806_clks[3]);
+		goto fail3;
+	}
+
+	ret = of_clk_add_provider(np, of_clk_src_onecell_get, &ap806_clk_data);
+	if (ret)
+		goto fail_clk_add;
+
+	return 0;
+
+fail_clk_add:
+	clk_unregister_fixed_factor(ap806_clks[3]);
+fail3:
+	clk_unregister_fixed_rate(ap806_clks[2]);
+fail2:
+	clk_unregister_fixed_rate(ap806_clks[1]);
+fail1:
+	clk_unregister_fixed_rate(ap806_clks[0]);
+fail0:
+	return ret;
+}
+
+static int ap806_syscon_clk_remove(struct platform_device *pdev)
+{
+	of_clk_del_provider(pdev->dev.of_node);
+	clk_unregister_fixed_factor(ap806_clks[3]);
+	clk_unregister_fixed_rate(ap806_clks[2]);
+	clk_unregister_fixed_rate(ap806_clks[1]);
+	clk_unregister_fixed_rate(ap806_clks[0]);
+
+	return 0;
+}
+
+static const struct of_device_id ap806_syscon_of_match[] = {
+	{ .compatible = "marvell,ap806-system-controller", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, armada8k_pcie_of_match);
+
+static struct platform_driver ap806_syscon_driver = {
+	.probe = ap806_syscon_clk_probe,
+	.remove = ap806_syscon_clk_remove,
+	.driver		= {
+		.name	= "marvell-ap806-system-controller",
+		.of_match_table = ap806_syscon_of_match,
+	},
+};
+
+module_platform_driver(ap806_syscon_driver);
+
+MODULE_DESCRIPTION("Marvell AP806 System Controller driver");
+MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/mvebu/cp110-system-controller.c linux-libre-4.7-gnu/drivers/clk/mvebu/cp110-system-controller.c
--- linux-libre-4.6-gnu/drivers/clk/mvebu/cp110-system-controller.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/clk/mvebu/cp110-system-controller.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,406 @@
+/*
+ * Marvell Armada CP110 System Controller
+ *
+ * Copyright (C) 2016 Marvell
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+/*
+ * CP110 has 5 core clocks:
+ *
+ *  - APLL		(1 Ghz)
+ *    - PPv2 core	(1/3 APLL)
+ *    - EIP		(1/2 APLL)
+ *      - Core		(1/2 EIP)
+ *
+ *  - NAND clock, which is either:
+ *    - Equal to the core clock
+ *    - 2/5 APLL
+ *
+ * CP110 has 32 gatable clocks, for the various peripherals in the
+ * IP. They have fairly complicated parent/child relationships.
+ */
+
+#define pr_fmt(fmt) "cp110-system-controller: " fmt
+
+#include <linux/clk-provider.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#define CP110_PM_CLOCK_GATING_REG	0x220
+#define CP110_NAND_FLASH_CLK_CTRL_REG	0x700
+#define    NF_CLOCK_SEL_400_MASK	BIT(0)
+
+enum {
+	CP110_CLK_TYPE_CORE,
+	CP110_CLK_TYPE_GATABLE,
+};
+
+#define CP110_MAX_CORE_CLOCKS		5
+#define CP110_MAX_GATABLE_CLOCKS	32
+
+#define CP110_CLK_NUM \
+	(CP110_MAX_CORE_CLOCKS + CP110_MAX_GATABLE_CLOCKS)
+
+#define CP110_CORE_APLL			0
+#define CP110_CORE_PPV2			1
+#define CP110_CORE_EIP			2
+#define CP110_CORE_CORE			3
+#define CP110_CORE_NAND			4
+
+/* A number of gatable clocks need special handling */
+#define CP110_GATE_AUDIO		0
+#define CP110_GATE_COMM_UNIT		1
+#define CP110_GATE_NAND			2
+#define CP110_GATE_PPV2			3
+#define CP110_GATE_SDIO			4
+#define CP110_GATE_XOR1			7
+#define CP110_GATE_XOR0			8
+#define CP110_GATE_PCIE_X1_0		11
+#define CP110_GATE_PCIE_X1_1		12
+#define CP110_GATE_PCIE_X4		13
+#define CP110_GATE_PCIE_XOR		14
+#define CP110_GATE_SATA			15
+#define CP110_GATE_SATA_USB		16
+#define CP110_GATE_MAIN			17
+#define CP110_GATE_SDMMC		18
+#define CP110_GATE_SLOW_IO		21
+#define CP110_GATE_USB3H0		22
+#define CP110_GATE_USB3H1		23
+#define CP110_GATE_USB3DEV		24
+#define CP110_GATE_EIP150		25
+#define CP110_GATE_EIP197		26
+
+static struct clk *cp110_clks[CP110_CLK_NUM];
+
+static struct clk_onecell_data cp110_clk_data = {
+	.clks = cp110_clks,
+	.clk_num = CP110_CLK_NUM,
+};
+
+struct cp110_gate_clk {
+	struct clk_hw hw;
+	struct regmap *regmap;
+	u8 bit_idx;
+};
+
+#define to_cp110_gate_clk(clk) container_of(clk, struct cp110_gate_clk, hw)
+
+static int cp110_gate_enable(struct clk_hw *hw)
+{
+	struct cp110_gate_clk *gate = to_cp110_gate_clk(hw);
+
+	regmap_update_bits(gate->regmap, CP110_PM_CLOCK_GATING_REG,
+			   BIT(gate->bit_idx), BIT(gate->bit_idx));
+
+	return 0;
+}
+
+static void cp110_gate_disable(struct clk_hw *hw)
+{
+	struct cp110_gate_clk *gate = to_cp110_gate_clk(hw);
+
+	regmap_update_bits(gate->regmap, CP110_PM_CLOCK_GATING_REG,
+			   BIT(gate->bit_idx), 0);
+}
+
+static int cp110_gate_is_enabled(struct clk_hw *hw)
+{
+	struct cp110_gate_clk *gate = to_cp110_gate_clk(hw);
+	u32 val;
+
+	regmap_read(gate->regmap, CP110_PM_CLOCK_GATING_REG, &val);
+
+	return val & BIT(gate->bit_idx);
+}
+
+static const struct clk_ops cp110_gate_ops = {
+	.enable = cp110_gate_enable,
+	.disable = cp110_gate_disable,
+	.is_enabled = cp110_gate_is_enabled,
+};
+
+static struct clk *cp110_register_gate(const char *name,
+				       const char *parent_name,
+				       struct regmap *regmap, u8 bit_idx)
+{
+	struct cp110_gate_clk *gate;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+	if (!gate)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &cp110_gate_ops;
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+
+	gate->regmap = regmap;
+	gate->bit_idx = bit_idx;
+	gate->hw.init = &init;
+
+	clk = clk_register(NULL, &gate->hw);
+	if (IS_ERR(clk))
+		kfree(gate);
+
+	return clk;
+}
+
+static void cp110_unregister_gate(struct clk *clk)
+{
+	struct clk_hw *hw;
+
+	hw = __clk_get_hw(clk);
+	if (!hw)
+		return;
+
+	clk_unregister(clk);
+	kfree(to_cp110_gate_clk(hw));
+}
+
+static struct clk *cp110_of_clk_get(struct of_phandle_args *clkspec, void *data)
+{
+	struct clk_onecell_data *clk_data = data;
+	unsigned int type = clkspec->args[0];
+	unsigned int idx = clkspec->args[1];
+
+	if (type == CP110_CLK_TYPE_CORE) {
+		if (idx > CP110_MAX_CORE_CLOCKS)
+			return ERR_PTR(-EINVAL);
+		return clk_data->clks[idx];
+	} else if (type == CP110_CLK_TYPE_GATABLE) {
+		if (idx > CP110_MAX_GATABLE_CLOCKS)
+			return ERR_PTR(-EINVAL);
+		return clk_data->clks[CP110_MAX_CORE_CLOCKS + idx];
+	}
+
+	return ERR_PTR(-EINVAL);
+}
+
+static int cp110_syscon_clk_probe(struct platform_device *pdev)
+{
+	struct regmap *regmap;
+	struct device_node *np = pdev->dev.of_node;
+	const char *ppv2_name, *apll_name, *core_name, *eip_name, *nand_name;
+	struct clk *clk;
+	u32 nand_clk_ctrl;
+	int i, ret;
+
+	regmap = syscon_node_to_regmap(np);
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
+
+	ret = regmap_read(regmap, CP110_NAND_FLASH_CLK_CTRL_REG,
+			  &nand_clk_ctrl);
+	if (ret)
+		return ret;
+
+	/* Register the APLL which is the root of the clk tree */
+	of_property_read_string_index(np, "core-clock-output-names",
+				      CP110_CORE_APLL, &apll_name);
+	clk = clk_register_fixed_rate(NULL, apll_name, NULL, 0,
+				      1000 * 1000 * 1000);
+	if (IS_ERR(clk)) {
+		ret = PTR_ERR(clk);
+		goto fail0;
+	}
+
+	cp110_clks[CP110_CORE_APLL] = clk;
+
+	/* PPv2 is APLL/3 */
+	of_property_read_string_index(np, "core-clock-output-names",
+				      CP110_CORE_PPV2, &ppv2_name);
+	clk = clk_register_fixed_factor(NULL, ppv2_name, apll_name, 0, 1, 3);
+	if (IS_ERR(clk)) {
+		ret = PTR_ERR(clk);
+		goto fail1;
+	}
+
+	cp110_clks[CP110_CORE_PPV2] = clk;
+
+	/* EIP clock is APLL/2 */
+	of_property_read_string_index(np, "core-clock-output-names",
+				      CP110_CORE_EIP, &eip_name);
+	clk = clk_register_fixed_factor(NULL, eip_name, apll_name, 0, 1, 2);
+	if (IS_ERR(clk)) {
+		ret = PTR_ERR(clk);
+		goto fail2;
+	}
+
+	cp110_clks[CP110_CORE_EIP] = clk;
+
+	/* Core clock is EIP/2 */
+	of_property_read_string_index(np, "core-clock-output-names",
+				      CP110_CORE_CORE, &core_name);
+	clk = clk_register_fixed_factor(NULL, core_name, eip_name, 0, 1, 2);
+	if (IS_ERR(clk)) {
+		ret = PTR_ERR(clk);
+		goto fail3;
+	}
+
+	cp110_clks[CP110_CORE_CORE] = clk;
+
+	/* NAND can be either APLL/2.5 or core clock */
+	of_property_read_string_index(np, "core-clock-output-names",
+				      CP110_CORE_NAND, &nand_name);
+	if (nand_clk_ctrl & NF_CLOCK_SEL_400_MASK)
+		clk = clk_register_fixed_factor(NULL, nand_name,
+						apll_name, 0, 2, 5);
+	else
+		clk = clk_register_fixed_factor(NULL, nand_name,
+						core_name, 0, 1, 1);
+	if (IS_ERR(clk)) {
+		ret = PTR_ERR(clk);
+		goto fail4;
+	}
+
+	cp110_clks[CP110_CORE_NAND] = clk;
+
+	for (i = 0; i < CP110_MAX_GATABLE_CLOCKS; i++) {
+		const char *parent, *name;
+		int ret;
+
+		ret = of_property_read_string_index(np,
+						    "gate-clock-output-names",
+						    i, &name);
+		/* Reached the end of the list? */
+		if (ret < 0)
+			break;
+
+		if (!strcmp(name, "none"))
+			continue;
+
+		switch (i) {
+		case CP110_GATE_AUDIO:
+		case CP110_GATE_COMM_UNIT:
+		case CP110_GATE_EIP150:
+		case CP110_GATE_EIP197:
+		case CP110_GATE_SLOW_IO:
+			of_property_read_string_index(np,
+						      "gate-clock-output-names",
+						      CP110_GATE_MAIN, &parent);
+			break;
+		case CP110_GATE_NAND:
+			parent = nand_name;
+			break;
+		case CP110_GATE_PPV2:
+			parent = ppv2_name;
+			break;
+		case CP110_GATE_SDIO:
+			of_property_read_string_index(np,
+						      "gate-clock-output-names",
+						      CP110_GATE_SDMMC, &parent);
+			break;
+		case CP110_GATE_XOR1:
+		case CP110_GATE_XOR0:
+		case CP110_GATE_PCIE_X1_0:
+		case CP110_GATE_PCIE_X1_1:
+		case CP110_GATE_PCIE_X4:
+			of_property_read_string_index(np,
+						      "gate-clock-output-names",
+						      CP110_GATE_PCIE_XOR, &parent);
+			break;
+		case CP110_GATE_SATA:
+		case CP110_GATE_USB3H0:
+		case CP110_GATE_USB3H1:
+		case CP110_GATE_USB3DEV:
+			of_property_read_string_index(np,
+						      "gate-clock-output-names",
+						      CP110_GATE_SATA_USB, &parent);
+			break;
+		default:
+			parent = core_name;
+			break;
+		}
+
+		clk = cp110_register_gate(name, parent, regmap, i);
+		if (IS_ERR(clk)) {
+			ret = PTR_ERR(clk);
+			goto fail_gate;
+		}
+
+		cp110_clks[CP110_MAX_CORE_CLOCKS + i] = clk;
+	}
+
+	ret = of_clk_add_provider(np, cp110_of_clk_get, &cp110_clk_data);
+	if (ret)
+		goto fail_clk_add;
+
+	return 0;
+
+fail_clk_add:
+fail_gate:
+	for (i = 0; i < CP110_MAX_GATABLE_CLOCKS; i++) {
+		clk = cp110_clks[CP110_MAX_CORE_CLOCKS + i];
+
+		if (clk)
+			cp110_unregister_gate(clk);
+	}
+
+	clk_unregister_fixed_factor(cp110_clks[CP110_CORE_NAND]);
+fail4:
+	clk_unregister_fixed_factor(cp110_clks[CP110_CORE_CORE]);
+fail3:
+	clk_unregister_fixed_factor(cp110_clks[CP110_CORE_EIP]);
+fail2:
+	clk_unregister_fixed_factor(cp110_clks[CP110_CORE_PPV2]);
+fail1:
+	clk_unregister_fixed_rate(cp110_clks[CP110_CORE_APLL]);
+fail0:
+	return ret;
+}
+
+static int cp110_syscon_clk_remove(struct platform_device *pdev)
+{
+	int i;
+
+	of_clk_del_provider(pdev->dev.of_node);
+
+	for (i = 0; i < CP110_MAX_GATABLE_CLOCKS; i++) {
+		struct clk *clk = cp110_clks[CP110_MAX_CORE_CLOCKS + i];
+
+		if (clk)
+			cp110_unregister_gate(clk);
+	}
+
+	clk_unregister_fixed_factor(cp110_clks[CP110_CORE_NAND]);
+	clk_unregister_fixed_factor(cp110_clks[CP110_CORE_CORE]);
+	clk_unregister_fixed_factor(cp110_clks[CP110_CORE_EIP]);
+	clk_unregister_fixed_factor(cp110_clks[CP110_CORE_PPV2]);
+	clk_unregister_fixed_rate(cp110_clks[CP110_CORE_APLL]);
+
+	return 0;
+}
+
+static const struct of_device_id cp110_syscon_of_match[] = {
+	{ .compatible = "marvell,cp110-system-controller0", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, armada8k_pcie_of_match);
+
+static struct platform_driver cp110_syscon_driver = {
+	.probe = cp110_syscon_clk_probe,
+	.remove = cp110_syscon_clk_remove,
+	.driver		= {
+		.name	= "marvell-cp110-system-controller0",
+		.of_match_table = cp110_syscon_of_match,
+	},
+};
+
+module_platform_driver(cp110_syscon_driver);
+
+MODULE_DESCRIPTION("Marvell CP110 System Controller 0 driver");
+MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/mvebu/Kconfig linux-libre-4.7-gnu/drivers/clk/mvebu/Kconfig
--- linux-libre-4.6-gnu/drivers/clk/mvebu/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/mvebu/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -29,6 +29,12 @@ config ARMADA_XP_CLK
 	select MVEBU_CLK_COMMON
 	select MVEBU_CLK_CPU
 
+config ARMADA_AP806_SYSCON
+	bool
+
+config ARMADA_CP110_SYSCON
+	bool
+
 config DOVE_CLK
 	bool
 	select MVEBU_CLK_COMMON
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/mvebu/Makefile linux-libre-4.7-gnu/drivers/clk/mvebu/Makefile
--- linux-libre-4.6-gnu/drivers/clk/mvebu/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/mvebu/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -7,6 +7,8 @@ obj-$(CONFIG_ARMADA_375_CLK)	+= armada-3
 obj-$(CONFIG_ARMADA_38X_CLK)	+= armada-38x.o
 obj-$(CONFIG_ARMADA_39X_CLK)	+= armada-39x.o
 obj-$(CONFIG_ARMADA_XP_CLK)	+= armada-xp.o
+obj-$(CONFIG_ARMADA_AP806_SYSCON) += ap806-system-controller.o
+obj-$(CONFIG_ARMADA_CP110_SYSCON) += cp110-system-controller.o
 obj-$(CONFIG_DOVE_CLK)		+= dove.o dove-divider.o
 obj-$(CONFIG_KIRKWOOD_CLK)	+= kirkwood.o
 obj-$(CONFIG_ORION_CLK)		+= orion.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/nxp/clk-lpc18xx-creg.c linux-libre-4.7-gnu/drivers/clk/nxp/clk-lpc18xx-creg.c
--- linux-libre-4.6-gnu/drivers/clk/nxp/clk-lpc18xx-creg.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/nxp/clk-lpc18xx-creg.c	2016-07-24 15:23:50.000000000 -0400
@@ -147,6 +147,7 @@ static struct clk *clk_register_creg_clk
 	init.name = creg_clk->name;
 	init.parent_names = parent_name;
 	init.num_parents = 1;
+	init.flags = 0;
 
 	creg_clk->reg = syscon;
 	creg_clk->hw.init = &init;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/qcom/gcc-msm8916.c linux-libre-4.7-gnu/drivers/clk/qcom/gcc-msm8916.c
--- linux-libre-4.6-gnu/drivers/clk/qcom/gcc-msm8916.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/qcom/gcc-msm8916.c	2016-07-24 15:23:50.000000000 -0400
@@ -2346,6 +2346,7 @@ static struct clk_branch gcc_crypto_ahb_
 				"pcnoc_bfdcd_clk_src",
 			},
 			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
 			.ops = &clk_branch2_ops,
 		},
 	},
@@ -2381,6 +2382,7 @@ static struct clk_branch gcc_crypto_clk
 				"crypto_clk_src",
 			},
 			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
 			.ops = &clk_branch2_ops,
 		},
 	},
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/qcom/mmcc-msm8996.c linux-libre-4.7-gnu/drivers/clk/qcom/mmcc-msm8996.c
--- linux-libre-4.6-gnu/drivers/clk/qcom/mmcc-msm8996.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/qcom/mmcc-msm8996.c	2016-07-24 15:23:50.000000000 -0400
@@ -1279,21 +1279,6 @@ static struct clk_branch mmss_misc_cxo_c
 	},
 };
 
-static struct clk_branch mmss_mmagic_axi_clk = {
-	.halt_reg = 0x506c,
-	.clkr = {
-		.enable_reg = 0x506c,
-		.enable_mask = BIT(0),
-		.hw.init = &(struct clk_init_data){
-			.name = "mmss_mmagic_axi_clk",
-			.parent_names = (const char *[]){ "axi_clk_src" },
-			.num_parents = 1,
-			.flags = CLK_SET_RATE_PARENT,
-			.ops = &clk_branch2_ops,
-		},
-	},
-};
-
 static struct clk_branch mmss_mmagic_maxi_clk = {
 	.halt_reg = 0x5074,
 	.clkr = {
@@ -1579,21 +1564,6 @@ static struct clk_branch smmu_video_axi_
 	},
 };
 
-static struct clk_branch mmagic_bimc_axi_clk = {
-	.halt_reg = 0x5294,
-	.clkr = {
-		.enable_reg = 0x5294,
-		.enable_mask = BIT(0),
-		.hw.init = &(struct clk_init_data){
-			.name = "mmagic_bimc_axi_clk",
-			.parent_names = (const char *[]){ "axi_clk_src" },
-			.num_parents = 1,
-			.flags = CLK_SET_RATE_PARENT,
-			.ops = &clk_branch2_ops,
-		},
-	},
-};
-
 static struct clk_branch mmagic_bimc_noc_cfg_ahb_clk = {
 	.halt_reg = 0x5298,
 	.clkr = {
@@ -3121,7 +3091,6 @@ static struct clk_regmap *mmcc_msm8996_c
 	[MMSS_MMAGIC_CFG_AHB_CLK] = &mmss_mmagic_cfg_ahb_clk.clkr,
 	[MMSS_MISC_AHB_CLK] = &mmss_misc_ahb_clk.clkr,
 	[MMSS_MISC_CXO_CLK] = &mmss_misc_cxo_clk.clkr,
-	[MMSS_MMAGIC_AXI_CLK] = &mmss_mmagic_axi_clk.clkr,
 	[MMSS_MMAGIC_MAXI_CLK] = &mmss_mmagic_maxi_clk.clkr,
 	[MMAGIC_CAMSS_AXI_CLK] = &mmagic_camss_axi_clk.clkr,
 	[MMAGIC_CAMSS_NOC_CFG_AHB_CLK] = &mmagic_camss_noc_cfg_ahb_clk.clkr,
@@ -3141,7 +3110,6 @@ static struct clk_regmap *mmcc_msm8996_c
 	[MMAGIC_VIDEO_NOC_CFG_AHB_CLK] = &mmagic_video_noc_cfg_ahb_clk.clkr,
 	[SMMU_VIDEO_AHB_CLK] = &smmu_video_ahb_clk.clkr,
 	[SMMU_VIDEO_AXI_CLK] = &smmu_video_axi_clk.clkr,
-	[MMAGIC_BIMC_AXI_CLK] = &mmagic_bimc_axi_clk.clkr,
 	[MMAGIC_BIMC_NOC_CFG_AHB_CLK] = &mmagic_bimc_noc_cfg_ahb_clk.clkr,
 	[GPU_GX_GFX3D_CLK] = &gpu_gx_gfx3d_clk.clkr,
 	[GPU_GX_RBBMTIMER_CLK] = &gpu_gx_rbbmtimer_clk.clkr,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/renesas/clk-mstp.c linux-libre-4.7-gnu/drivers/clk/renesas/clk-mstp.c
--- linux-libre-4.6-gnu/drivers/clk/renesas/clk-mstp.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/renesas/clk-mstp.c	2016-07-24 15:23:50.000000000 -0400
@@ -243,9 +243,7 @@ static void __init cpg_mstp_clocks_init(
 }
 CLK_OF_DECLARE(cpg_mstp_clks, "renesas,cpg-mstp-clocks", cpg_mstp_clocks_init);
 
-
-#ifdef CONFIG_PM_GENERIC_DOMAINS_OF
-int cpg_mstp_attach_dev(struct generic_pm_domain *domain, struct device *dev)
+int cpg_mstp_attach_dev(struct generic_pm_domain *unused, struct device *dev)
 {
 	struct device_node *np = dev->of_node;
 	struct of_phandle_args clkspec;
@@ -297,7 +295,7 @@ fail_put:
 	return error;
 }
 
-void cpg_mstp_detach_dev(struct generic_pm_domain *domain, struct device *dev)
+void cpg_mstp_detach_dev(struct generic_pm_domain *unused, struct device *dev)
 {
 	if (!list_empty(&dev->power.subsys_data->clock_list))
 		pm_clk_destroy(dev);
@@ -318,12 +316,10 @@ void __init cpg_mstp_add_clk_domain(stru
 		return;
 
 	pd->name = np->name;
-
 	pd->flags = GENPD_FLAG_PM_CLK;
-	pm_genpd_init(pd, &simple_qos_governor, false);
 	pd->attach_dev = cpg_mstp_attach_dev;
 	pd->detach_dev = cpg_mstp_detach_dev;
+	pm_genpd_init(pd, &pm_domain_always_on_gov, false);
 
 	of_genpd_add_provider_simple(np, pd);
 }
-#endif /* !CONFIG_PM_GENERIC_DOMAINS_OF */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/renesas/Kconfig linux-libre-4.7-gnu/drivers/clk/renesas/Kconfig
--- linux-libre-4.6-gnu/drivers/clk/renesas/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/clk/renesas/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,16 @@
+config CLK_RENESAS_CPG_MSSR
+	bool
+	default y if ARCH_R8A7795
+
+config CLK_RENESAS_CPG_MSTP
+	bool
+	default y if ARCH_R7S72100
+	default y if ARCH_R8A73A4
+	default y if ARCH_R8A7740
+	default y if ARCH_R8A7778
+	default y if ARCH_R8A7779
+	default y if ARCH_R8A7790
+	default y if ARCH_R8A7791
+	default y if ARCH_R8A7793
+	default y if ARCH_R8A7794
+	default y if ARCH_SH73A0
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/renesas/Makefile linux-libre-4.7-gnu/drivers/clk/renesas/Makefile
--- linux-libre-4.6-gnu/drivers/clk/renesas/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/renesas/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -1,13 +1,15 @@
 obj-$(CONFIG_ARCH_EMEV2)		+= clk-emev2.o
-obj-$(CONFIG_ARCH_R7S72100)		+= clk-rz.o clk-mstp.o
-obj-$(CONFIG_ARCH_R8A73A4)		+= clk-r8a73a4.o clk-mstp.o clk-div6.o
-obj-$(CONFIG_ARCH_R8A7740)		+= clk-r8a7740.o clk-mstp.o clk-div6.o
-obj-$(CONFIG_ARCH_R8A7778)		+= clk-r8a7778.o clk-mstp.o
-obj-$(CONFIG_ARCH_R8A7779)		+= clk-r8a7779.o clk-mstp.o
-obj-$(CONFIG_ARCH_R8A7790)		+= clk-rcar-gen2.o clk-mstp.o clk-div6.o
-obj-$(CONFIG_ARCH_R8A7791)		+= clk-rcar-gen2.o clk-mstp.o clk-div6.o
-obj-$(CONFIG_ARCH_R8A7793)		+= clk-rcar-gen2.o clk-mstp.o clk-div6.o
-obj-$(CONFIG_ARCH_R8A7794)		+= clk-rcar-gen2.o clk-mstp.o clk-div6.o
-obj-$(CONFIG_ARCH_R8A7795)		+= renesas-cpg-mssr.o \
-					   r8a7795-cpg-mssr.o clk-div6.o
-obj-$(CONFIG_ARCH_SH73A0)		+= clk-sh73a0.o clk-mstp.o clk-div6.o
+obj-$(CONFIG_ARCH_R7S72100)		+= clk-rz.o
+obj-$(CONFIG_ARCH_R8A73A4)		+= clk-r8a73a4.o clk-div6.o
+obj-$(CONFIG_ARCH_R8A7740)		+= clk-r8a7740.o clk-div6.o
+obj-$(CONFIG_ARCH_R8A7778)		+= clk-r8a7778.o
+obj-$(CONFIG_ARCH_R8A7779)		+= clk-r8a7779.o
+obj-$(CONFIG_ARCH_R8A7790)		+= clk-rcar-gen2.o clk-div6.o
+obj-$(CONFIG_ARCH_R8A7791)		+= clk-rcar-gen2.o clk-div6.o
+obj-$(CONFIG_ARCH_R8A7793)		+= clk-rcar-gen2.o clk-div6.o
+obj-$(CONFIG_ARCH_R8A7794)		+= clk-rcar-gen2.o clk-div6.o
+obj-$(CONFIG_ARCH_R8A7795)		+= r8a7795-cpg-mssr.o
+obj-$(CONFIG_ARCH_SH73A0)		+= clk-sh73a0.o clk-div6.o
+
+obj-$(CONFIG_CLK_RENESAS_CPG_MSSR)	+= renesas-cpg-mssr.o clk-div6.o
+obj-$(CONFIG_CLK_RENESAS_CPG_MSTP)	+= clk-mstp.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/renesas/r8a7795-cpg-mssr.c linux-libre-4.7-gnu/drivers/clk/renesas/r8a7795-cpg-mssr.c
--- linux-libre-4.6-gnu/drivers/clk/renesas/r8a7795-cpg-mssr.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/renesas/r8a7795-cpg-mssr.c	2016-07-24 15:23:50.000000000 -0400
@@ -13,6 +13,7 @@
  */
 
 #include <linux/bug.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/device.h>
 #include <linux/err.h>
@@ -26,6 +27,7 @@
 
 #include "renesas-cpg-mssr.h"
 
+#define CPG_RCKCR	0x240
 
 enum clk_ids {
 	/* Core Clock Outputs exported to DT */
@@ -50,6 +52,7 @@ enum clk_ids {
 	CLK_S3,
 	CLK_SDSRC,
 	CLK_SSPSRC,
+	CLK_RINT,
 
 	/* Module Clocks */
 	MOD_CLK_BASE
@@ -63,8 +66,12 @@ enum r8a7795_clk_types {
 	CLK_TYPE_GEN3_PLL3,
 	CLK_TYPE_GEN3_PLL4,
 	CLK_TYPE_GEN3_SD,
+	CLK_TYPE_GEN3_R,
 };
 
+#define DEF_GEN3_SD(_name, _id, _parent, _offset)	\
+	DEF_BASE(_name, _id, CLK_TYPE_GEN3_SD, _parent, .offset = _offset)
+
 static const struct cpg_core_clk r8a7795_core_clks[] __initconst = {
 	/* External Clock Inputs */
 	DEF_INPUT("extal",  CLK_EXTAL),
@@ -102,10 +109,10 @@ static const struct cpg_core_clk r8a7795
 	DEF_FIXED("s3d2",       R8A7795_CLK_S3D2,  CLK_S3,         2, 1),
 	DEF_FIXED("s3d4",       R8A7795_CLK_S3D4,  CLK_S3,         4, 1),
 
-	DEF_SD("sd0",           R8A7795_CLK_SD0,   CLK_PLL1_DIV2, 0x0074),
-	DEF_SD("sd1",           R8A7795_CLK_SD1,   CLK_PLL1_DIV2, 0x0078),
-	DEF_SD("sd2",           R8A7795_CLK_SD2,   CLK_PLL1_DIV2, 0x0268),
-	DEF_SD("sd3",           R8A7795_CLK_SD3,   CLK_PLL1_DIV2, 0x026c),
+	DEF_GEN3_SD("sd0",      R8A7795_CLK_SD0,   CLK_PLL1_DIV2, 0x0074),
+	DEF_GEN3_SD("sd1",      R8A7795_CLK_SD1,   CLK_PLL1_DIV2, 0x0078),
+	DEF_GEN3_SD("sd2",      R8A7795_CLK_SD2,   CLK_PLL1_DIV2, 0x0268),
+	DEF_GEN3_SD("sd3",      R8A7795_CLK_SD3,   CLK_PLL1_DIV2, 0x026c),
 
 	DEF_FIXED("cl",         R8A7795_CLK_CL,    CLK_PLL1_DIV2, 48, 1),
 	DEF_FIXED("cp",         R8A7795_CLK_CP,    CLK_EXTAL,      2, 1),
@@ -113,6 +120,12 @@ static const struct cpg_core_clk r8a7795
 	DEF_DIV6P1("mso",       R8A7795_CLK_MSO,   CLK_PLL1_DIV4, 0x014),
 	DEF_DIV6P1("hdmi",      R8A7795_CLK_HDMI,  CLK_PLL1_DIV2, 0x250),
 	DEF_DIV6P1("canfd",     R8A7795_CLK_CANFD, CLK_PLL1_DIV4, 0x244),
+	DEF_DIV6P1("csi0",      R8A7795_CLK_CSI0,  CLK_PLL1_DIV4, 0x00c),
+
+	DEF_DIV6_RO("osc",      R8A7795_CLK_OSC,   CLK_EXTAL, CPG_RCKCR, 8),
+	DEF_DIV6_RO("r_int",    CLK_RINT,          CLK_EXTAL, CPG_RCKCR, 32),
+
+	DEF_BASE("r",           R8A7795_CLK_R, CLK_TYPE_GEN3_R, CLK_RINT),
 };
 
 static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = {
@@ -139,6 +152,7 @@ static const struct mssr_mod_clk r8a7795
 	DEF_MOD("usb3-if0",		 328,	R8A7795_CLK_S3D1),
 	DEF_MOD("usb-dmac0",		 330,	R8A7795_CLK_S3D1),
 	DEF_MOD("usb-dmac1",		 331,	R8A7795_CLK_S3D1),
+	DEF_MOD("rwdt0",		 402,	R8A7795_CLK_R),
 	DEF_MOD("intc-ex",		 407,	R8A7795_CLK_CP),
 	DEF_MOD("intc-ap",		 408,	R8A7795_CLK_S3D1),
 	DEF_MOD("audmac0",		 502,	R8A7795_CLK_S3D4),
@@ -148,6 +162,7 @@ static const struct mssr_mod_clk r8a7795
 	DEF_MOD("hscif2",		 518,	R8A7795_CLK_S3D1),
 	DEF_MOD("hscif1",		 519,	R8A7795_CLK_S3D1),
 	DEF_MOD("hscif0",		 520,	R8A7795_CLK_S3D1),
+	DEF_MOD("pwm",			 523,	R8A7795_CLK_S3D4),
 	DEF_MOD("fcpvd3",		 600,	R8A7795_CLK_S2D1),
 	DEF_MOD("fcpvd2",		 601,	R8A7795_CLK_S2D1),
 	DEF_MOD("fcpvd1",		 602,	R8A7795_CLK_S2D1),
@@ -176,6 +191,10 @@ static const struct mssr_mod_clk r8a7795
 	DEF_MOD("ehci1",		 702,	R8A7795_CLK_S3D4),
 	DEF_MOD("ehci0",		 703,	R8A7795_CLK_S3D4),
 	DEF_MOD("hsusb",		 704,	R8A7795_CLK_S3D4),
+	DEF_MOD("csi21",		 713,	R8A7795_CLK_CSI0),
+	DEF_MOD("csi20",		 714,	R8A7795_CLK_CSI0),
+	DEF_MOD("csi41",		 715,	R8A7795_CLK_CSI0),
+	DEF_MOD("csi40",		 716,	R8A7795_CLK_CSI0),
 	DEF_MOD("du3",			 721,	R8A7795_CLK_S2D1),
 	DEF_MOD("du2",			 722,	R8A7795_CLK_S2D1),
 	DEF_MOD("du1",			 723,	R8A7795_CLK_S2D1),
@@ -183,6 +202,14 @@ static const struct mssr_mod_clk r8a7795
 	DEF_MOD("lvds",			 727,	R8A7795_CLK_S2D1),
 	DEF_MOD("hdmi1",		 728,	R8A7795_CLK_HDMI),
 	DEF_MOD("hdmi0",		 729,	R8A7795_CLK_HDMI),
+	DEF_MOD("vin7",			 804,	R8A7795_CLK_S2D1),
+	DEF_MOD("vin6",			 805,	R8A7795_CLK_S2D1),
+	DEF_MOD("vin5",			 806,	R8A7795_CLK_S2D1),
+	DEF_MOD("vin4",			 807,	R8A7795_CLK_S2D1),
+	DEF_MOD("vin3",			 808,	R8A7795_CLK_S2D1),
+	DEF_MOD("vin2",			 809,	R8A7795_CLK_S2D1),
+	DEF_MOD("vin1",			 810,	R8A7795_CLK_S2D1),
+	DEF_MOD("vin0",			 811,	R8A7795_CLK_S2D1),
 	DEF_MOD("etheravb",		 812,	R8A7795_CLK_S3D2),
 	DEF_MOD("sata0",		 815,	R8A7795_CLK_S3D2),
 	DEF_MOD("gpio7",		 905,	R8A7795_CLK_CP),
@@ -578,6 +605,18 @@ struct clk * __init r8a7795_cpg_clk_regi
 	case CLK_TYPE_GEN3_SD:
 		return cpg_sd_clk_register(core, base, __clk_get_name(parent));
 
+	case CLK_TYPE_GEN3_R:
+		/* RINT is default. Only if EXTALR is populated, we switch to it */
+		value = readl(base + CPG_RCKCR) & 0x3f;
+
+		if (clk_get_rate(clks[CLK_EXTALR])) {
+			parent = clks[CLK_EXTALR];
+			value |= BIT(15);
+		}
+
+		writel(value, base + CPG_RCKCR);
+		break;
+
 	default:
 		return ERR_PTR(-EINVAL);
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/renesas/renesas-cpg-mssr.c linux-libre-4.7-gnu/drivers/clk/renesas/renesas-cpg-mssr.c
--- linux-libre-4.6-gnu/drivers/clk/renesas/renesas-cpg-mssr.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/renesas/renesas-cpg-mssr.c	2016-07-24 15:23:50.000000000 -0400
@@ -15,6 +15,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/clk/renesas.h>
 #include <linux/device.h>
 #include <linux/init.h>
 #include <linux/mod_devicetable.h>
@@ -253,7 +254,7 @@ static void __init cpg_mssr_register_cor
 {
 	struct clk *clk = NULL, *parent;
 	struct device *dev = priv->dev;
-	unsigned int id = core->id;
+	unsigned int id = core->id, div = core->div;
 	const char *parent_name;
 
 	WARN_DEBUG(id >= priv->num_core_clks);
@@ -266,6 +267,7 @@ static void __init cpg_mssr_register_cor
 
 	case CLK_TYPE_FF:
 	case CLK_TYPE_DIV6P1:
+	case CLK_TYPE_DIV6_RO:
 		WARN_DEBUG(core->parent >= priv->num_core_clks);
 		parent = priv->clks[core->parent];
 		if (IS_ERR(parent)) {
@@ -274,13 +276,18 @@ static void __init cpg_mssr_register_cor
 		}
 
 		parent_name = __clk_get_name(parent);
-		if (core->type == CLK_TYPE_FF) {
-			clk = clk_register_fixed_factor(NULL, core->name,
-							parent_name, 0,
-							core->mult, core->div);
-		} else {
+
+		if (core->type == CLK_TYPE_DIV6_RO)
+			/* Multiply with the DIV6 register value */
+			div *= (readl(priv->base + core->offset) & 0x3f) + 1;
+
+		if (core->type == CLK_TYPE_DIV6P1) {
 			clk = cpg_div6_register(core->name, 1, &parent_name,
 						priv->base + core->offset);
+		} else {
+			clk = clk_register_fixed_factor(NULL, core->name,
+							parent_name, 0,
+							core->mult, div);
 		}
 		break;
 
@@ -375,8 +382,6 @@ fail:
 	kfree(clock);
 }
 
-
-#ifdef CONFIG_PM_GENERIC_DOMAINS_OF
 struct cpg_mssr_clk_domain {
 	struct generic_pm_domain genpd;
 	struct device_node *np;
@@ -384,6 +389,8 @@ struct cpg_mssr_clk_domain {
 	unsigned int core_pm_clks[0];
 };
 
+static struct cpg_mssr_clk_domain *cpg_mssr_clk_domain;
+
 static bool cpg_mssr_is_pm_clk(const struct of_phandle_args *clkspec,
 			       struct cpg_mssr_clk_domain *pd)
 {
@@ -407,17 +414,20 @@ static bool cpg_mssr_is_pm_clk(const str
 	}
 }
 
-static int cpg_mssr_attach_dev(struct generic_pm_domain *genpd,
-			       struct device *dev)
+int cpg_mssr_attach_dev(struct generic_pm_domain *unused, struct device *dev)
 {
-	struct cpg_mssr_clk_domain *pd =
-		container_of(genpd, struct cpg_mssr_clk_domain, genpd);
+	struct cpg_mssr_clk_domain *pd = cpg_mssr_clk_domain;
 	struct device_node *np = dev->of_node;
 	struct of_phandle_args clkspec;
 	struct clk *clk;
 	int i = 0;
 	int error;
 
+	if (!pd) {
+		dev_dbg(dev, "CPG/MSSR clock domain not yet available\n");
+		return -EPROBE_DEFER;
+	}
+
 	while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i,
 					   &clkspec)) {
 		if (cpg_mssr_is_pm_clk(&clkspec, pd))
@@ -457,8 +467,7 @@ fail_put:
 	return error;
 }
 
-static void cpg_mssr_detach_dev(struct generic_pm_domain *genpd,
-				struct device *dev)
+void cpg_mssr_detach_dev(struct generic_pm_domain *unused, struct device *dev)
 {
 	if (!list_empty(&dev->power.subsys_data->clock_list))
 		pm_clk_destroy(dev);
@@ -484,22 +493,14 @@ static int __init cpg_mssr_add_clk_domai
 	genpd = &pd->genpd;
 	genpd->name = np->name;
 	genpd->flags = GENPD_FLAG_PM_CLK;
-	pm_genpd_init(genpd, &simple_qos_governor, false);
 	genpd->attach_dev = cpg_mssr_attach_dev;
 	genpd->detach_dev = cpg_mssr_detach_dev;
+	pm_genpd_init(genpd, &pm_domain_always_on_gov, false);
+	cpg_mssr_clk_domain = pd;
 
 	of_genpd_add_provider_simple(np, genpd);
 	return 0;
 }
-#else
-static inline int cpg_mssr_add_clk_domain(struct device *dev,
-					  const unsigned int *core_pm_clks,
-					  unsigned int num_core_pm_clks)
-{
-	return 0;
-}
-#endif /* !CONFIG_PM_GENERIC_DOMAINS_OF */
-
 
 static const struct of_device_id cpg_mssr_match[] = {
 #ifdef CONFIG_ARCH_R8A7795
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/renesas/renesas-cpg-mssr.h linux-libre-4.7-gnu/drivers/clk/renesas/renesas-cpg-mssr.h
--- linux-libre-4.6-gnu/drivers/clk/renesas/renesas-cpg-mssr.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/renesas/renesas-cpg-mssr.h	2016-07-24 15:23:50.000000000 -0400
@@ -37,6 +37,7 @@ enum clk_types {
 	CLK_TYPE_IN,		/* External Clock Input */
 	CLK_TYPE_FF,		/* Fixed Factor Clock */
 	CLK_TYPE_DIV6P1,	/* DIV6 Clock with 1 parent clock */
+	CLK_TYPE_DIV6_RO,	/* DIV6 Clock read only with extra divisor */
 
 	/* Custom definitions start here */
 	CLK_TYPE_CUSTOM,
@@ -53,9 +54,8 @@ enum clk_types {
 	DEF_BASE(_name, _id, CLK_TYPE_FF, _parent, .div = _div, .mult = _mult)
 #define DEF_DIV6P1(_name, _id, _parent, _offset)	\
 	DEF_BASE(_name, _id, CLK_TYPE_DIV6P1, _parent, .offset = _offset)
-#define DEF_SD(_name, _id, _parent, _offset)	\
-	DEF_BASE(_name, _id, CLK_TYPE_GEN3_SD, _parent, .offset = _offset)
-
+#define DEF_DIV6_RO(_name, _id, _parent, _offset, _div)	\
+	DEF_BASE(_name, _id, CLK_TYPE_DIV6_RO, _parent, .offset = _offset, .div = _div, .mult = 1)
 
     /*
      * Definitions of Module Clocks
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/rockchip/clk.c linux-libre-4.7-gnu/drivers/clk/rockchip/clk.c
--- linux-libre-4.6-gnu/drivers/clk/rockchip/clk.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/rockchip/clk.c	2016-07-24 15:23:50.000000000 -0400
@@ -2,6 +2,9 @@
  * Copyright (c) 2014 MundoReader S.L.
  * Author: Heiko Stuebner <heiko@sntech.de>
  *
+ * Copyright (c) 2016 Rockchip Electronics Co. Ltd.
+ * Author: Xing Zheng <zhengxing@rock-chips.com>
+ *
  * based on
  *
  * samsung/clk.c
@@ -39,7 +42,8 @@
  * sometimes without one of those components.
  */
 static struct clk *rockchip_clk_register_branch(const char *name,
-		const char *const *parent_names, u8 num_parents, void __iomem *base,
+		const char *const *parent_names, u8 num_parents,
+		void __iomem *base,
 		int muxdiv_offset, u8 mux_shift, u8 mux_width, u8 mux_flags,
 		u8 div_shift, u8 div_width, u8 div_flags,
 		struct clk_div_table *div_table, int gate_offset,
@@ -136,9 +140,11 @@ static int rockchip_clk_frac_notifier_cb
 	pr_debug("%s: event %lu, old_rate %lu, new_rate: %lu\n",
 		 __func__, event, ndata->old_rate, ndata->new_rate);
 	if (event == PRE_RATE_CHANGE) {
-		frac->rate_change_idx = frac->mux_ops->get_parent(&frac_mux->hw);
+		frac->rate_change_idx =
+				frac->mux_ops->get_parent(&frac_mux->hw);
 		if (frac->rate_change_idx != frac->mux_frac_idx) {
-			frac->mux_ops->set_parent(&frac_mux->hw, frac->mux_frac_idx);
+			frac->mux_ops->set_parent(&frac_mux->hw,
+						  frac->mux_frac_idx);
 			frac->rate_change_remuxed = 1;
 		}
 	} else if (event == POST_RATE_CHANGE) {
@@ -149,7 +155,8 @@ static int rockchip_clk_frac_notifier_cb
 		 * reaches the mux itself.
 		 */
 		if (frac->rate_change_remuxed) {
-			frac->mux_ops->set_parent(&frac_mux->hw, frac->rate_change_idx);
+			frac->mux_ops->set_parent(&frac_mux->hw,
+						  frac->rate_change_idx);
 			frac->rate_change_remuxed = 0;
 		}
 	}
@@ -157,7 +164,8 @@ static int rockchip_clk_frac_notifier_cb
 	return notifier_from_errno(ret);
 }
 
-static struct clk *rockchip_clk_register_frac_branch(const char *name,
+static struct clk *rockchip_clk_register_frac_branch(
+		struct rockchip_clk_provider *ctx, const char *name,
 		const char *const *parent_names, u8 num_parents,
 		void __iomem *base, int muxdiv_offset, u8 div_flags,
 		int gate_offset, u8 gate_shift, u8 gate_flags,
@@ -250,7 +258,7 @@ static struct clk *rockchip_clk_register
 		if (IS_ERR(mux_clk))
 			return clk;
 
-		rockchip_clk_add_lookup(mux_clk, child->id);
+		rockchip_clk_add_lookup(ctx, mux_clk, child->id);
 
 		/* notifier on the fraction divider to catch rate changes */
 		if (frac->mux_frac_idx >= 0) {
@@ -314,66 +322,82 @@ static struct clk *rockchip_clk_register
 	return clk;
 }
 
-static DEFINE_SPINLOCK(clk_lock);
-static struct clk **clk_table;
-static void __iomem *reg_base;
-static struct clk_onecell_data clk_data;
-static struct device_node *cru_node;
-static struct regmap *grf;
-
-void __init rockchip_clk_init(struct device_node *np, void __iomem *base,
-			      unsigned long nr_clks)
+struct rockchip_clk_provider * __init rockchip_clk_init(struct device_node *np,
+			void __iomem *base, unsigned long nr_clks)
 {
-	reg_base = base;
-	cru_node = np;
-	grf = ERR_PTR(-EPROBE_DEFER);
+	struct rockchip_clk_provider *ctx;
+	struct clk **clk_table;
+	int i;
+
+	ctx = kzalloc(sizeof(struct rockchip_clk_provider), GFP_KERNEL);
+	if (!ctx)
+		return ERR_PTR(-ENOMEM);
 
 	clk_table = kcalloc(nr_clks, sizeof(struct clk *), GFP_KERNEL);
 	if (!clk_table)
-		pr_err("%s: could not allocate clock lookup table\n", __func__);
+		goto err_free;
 
-	clk_data.clks = clk_table;
-	clk_data.clk_num = nr_clks;
-	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+	for (i = 0; i < nr_clks; ++i)
+		clk_table[i] = ERR_PTR(-ENOENT);
+
+	ctx->reg_base = base;
+	ctx->clk_data.clks = clk_table;
+	ctx->clk_data.clk_num = nr_clks;
+	ctx->cru_node = np;
+	ctx->grf = ERR_PTR(-EPROBE_DEFER);
+	spin_lock_init(&ctx->lock);
+
+	ctx->grf = syscon_regmap_lookup_by_phandle(ctx->cru_node,
+						   "rockchip,grf");
+
+	return ctx;
+
+err_free:
+	kfree(ctx);
+	return ERR_PTR(-ENOMEM);
 }
 
-struct regmap *rockchip_clk_get_grf(void)
+void __init rockchip_clk_of_add_provider(struct device_node *np,
+				struct rockchip_clk_provider *ctx)
 {
-	if (IS_ERR(grf))
-		grf = syscon_regmap_lookup_by_phandle(cru_node, "rockchip,grf");
-	return grf;
+	if (of_clk_add_provider(np, of_clk_src_onecell_get,
+				&ctx->clk_data))
+		pr_err("%s: could not register clk provider\n", __func__);
 }
 
-void rockchip_clk_add_lookup(struct clk *clk, unsigned int id)
+void rockchip_clk_add_lookup(struct rockchip_clk_provider *ctx,
+			     struct clk *clk, unsigned int id)
 {
-	if (clk_table && id)
-		clk_table[id] = clk;
+	if (ctx->clk_data.clks && id)
+		ctx->clk_data.clks[id] = clk;
 }
 
-void __init rockchip_clk_register_plls(struct rockchip_pll_clock *list,
+void __init rockchip_clk_register_plls(struct rockchip_clk_provider *ctx,
+				struct rockchip_pll_clock *list,
 				unsigned int nr_pll, int grf_lock_offset)
 {
 	struct clk *clk;
 	int idx;
 
 	for (idx = 0; idx < nr_pll; idx++, list++) {
-		clk = rockchip_clk_register_pll(list->type, list->name,
+		clk = rockchip_clk_register_pll(ctx, list->type, list->name,
 				list->parent_names, list->num_parents,
-				reg_base, list->con_offset, grf_lock_offset,
+				list->con_offset, grf_lock_offset,
 				list->lock_shift, list->mode_offset,
 				list->mode_shift, list->rate_table,
-				list->pll_flags, &clk_lock);
+				list->pll_flags);
 		if (IS_ERR(clk)) {
 			pr_err("%s: failed to register clock %s\n", __func__,
 				list->name);
 			continue;
 		}
 
-		rockchip_clk_add_lookup(clk, list->id);
+		rockchip_clk_add_lookup(ctx, clk, list->id);
 	}
 }
 
 void __init rockchip_clk_register_branches(
+				      struct rockchip_clk_provider *ctx,
 				      struct rockchip_clk_branch *list,
 				      unsigned int nr_clk)
 {
@@ -389,56 +413,59 @@ void __init rockchip_clk_register_branch
 		case branch_mux:
 			clk = clk_register_mux(NULL, list->name,
 				list->parent_names, list->num_parents,
-				flags, reg_base + list->muxdiv_offset,
+				flags, ctx->reg_base + list->muxdiv_offset,
 				list->mux_shift, list->mux_width,
-				list->mux_flags, &clk_lock);
+				list->mux_flags, &ctx->lock);
 			break;
 		case branch_divider:
 			if (list->div_table)
 				clk = clk_register_divider_table(NULL,
 					list->name, list->parent_names[0],
-					flags, reg_base + list->muxdiv_offset,
+					flags,
+					ctx->reg_base + list->muxdiv_offset,
 					list->div_shift, list->div_width,
 					list->div_flags, list->div_table,
-					&clk_lock);
+					&ctx->lock);
 			else
 				clk = clk_register_divider(NULL, list->name,
 					list->parent_names[0], flags,
-					reg_base + list->muxdiv_offset,
+					ctx->reg_base + list->muxdiv_offset,
 					list->div_shift, list->div_width,
-					list->div_flags, &clk_lock);
+					list->div_flags, &ctx->lock);
 			break;
 		case branch_fraction_divider:
-			clk = rockchip_clk_register_frac_branch(list->name,
+			clk = rockchip_clk_register_frac_branch(ctx, list->name,
 				list->parent_names, list->num_parents,
-				reg_base, list->muxdiv_offset, list->div_flags,
+				ctx->reg_base, list->muxdiv_offset,
+				list->div_flags,
 				list->gate_offset, list->gate_shift,
 				list->gate_flags, flags, list->child,
-				&clk_lock);
+				&ctx->lock);
 			break;
 		case branch_gate:
 			flags |= CLK_SET_RATE_PARENT;
 
 			clk = clk_register_gate(NULL, list->name,
 				list->parent_names[0], flags,
-				reg_base + list->gate_offset,
-				list->gate_shift, list->gate_flags, &clk_lock);
+				ctx->reg_base + list->gate_offset,
+				list->gate_shift, list->gate_flags, &ctx->lock);
 			break;
 		case branch_composite:
 			clk = rockchip_clk_register_branch(list->name,
 				list->parent_names, list->num_parents,
-				reg_base, list->muxdiv_offset, list->mux_shift,
+				ctx->reg_base, list->muxdiv_offset,
+				list->mux_shift,
 				list->mux_width, list->mux_flags,
 				list->div_shift, list->div_width,
 				list->div_flags, list->div_table,
 				list->gate_offset, list->gate_shift,
-				list->gate_flags, flags, &clk_lock);
+				list->gate_flags, flags, &ctx->lock);
 			break;
 		case branch_mmc:
 			clk = rockchip_clk_register_mmc(
 				list->name,
 				list->parent_names, list->num_parents,
-				reg_base + list->muxdiv_offset,
+				ctx->reg_base + list->muxdiv_offset,
 				list->div_shift
 			);
 			break;
@@ -446,16 +473,16 @@ void __init rockchip_clk_register_branch
 			clk = rockchip_clk_register_inverter(
 				list->name, list->parent_names,
 				list->num_parents,
-				reg_base + list->muxdiv_offset,
-				list->div_shift, list->div_flags, &clk_lock);
+				ctx->reg_base + list->muxdiv_offset,
+				list->div_shift, list->div_flags, &ctx->lock);
 			break;
 		case branch_factor:
 			clk = rockchip_clk_register_factor_branch(
 				list->name, list->parent_names,
-				list->num_parents, reg_base,
+				list->num_parents, ctx->reg_base,
 				list->div_shift, list->div_width,
 				list->gate_offset, list->gate_shift,
-				list->gate_flags, flags, &clk_lock);
+				list->gate_flags, flags, &ctx->lock);
 			break;
 		}
 
@@ -472,11 +499,12 @@ void __init rockchip_clk_register_branch
 			continue;
 		}
 
-		rockchip_clk_add_lookup(clk, list->id);
+		rockchip_clk_add_lookup(ctx, clk, list->id);
 	}
 }
 
-void __init rockchip_clk_register_armclk(unsigned int lookup_id,
+void __init rockchip_clk_register_armclk(struct rockchip_clk_provider *ctx,
+			unsigned int lookup_id,
 			const char *name, const char *const *parent_names,
 			u8 num_parents,
 			const struct rockchip_cpuclk_reg_data *reg_data,
@@ -486,15 +514,15 @@ void __init rockchip_clk_register_armclk
 	struct clk *clk;
 
 	clk = rockchip_clk_register_cpuclk(name, parent_names, num_parents,
-					   reg_data, rates, nrates, reg_base,
-					   &clk_lock);
+					   reg_data, rates, nrates,
+					   ctx->reg_base, &ctx->lock);
 	if (IS_ERR(clk)) {
 		pr_err("%s: failed to register clock %s: %ld\n",
 		       __func__, name, PTR_ERR(clk));
 		return;
 	}
 
-	rockchip_clk_add_lookup(clk, lookup_id);
+	rockchip_clk_add_lookup(ctx, clk, lookup_id);
 }
 
 void __init rockchip_clk_protect_critical(const char *const clocks[],
@@ -511,6 +539,7 @@ void __init rockchip_clk_protect_critica
 	}
 }
 
+static void __iomem *rst_base;
 static unsigned int reg_restart;
 static void (*cb_restart)(void);
 static int rockchip_restart_notify(struct notifier_block *this,
@@ -519,7 +548,7 @@ static int rockchip_restart_notify(struc
 	if (cb_restart)
 		cb_restart();
 
-	writel(0xfdb9, reg_base + reg_restart);
+	writel(0xfdb9, rst_base + reg_restart);
 	return NOTIFY_DONE;
 }
 
@@ -528,10 +557,14 @@ static struct notifier_block rockchip_re
 	.priority = 128,
 };
 
-void __init rockchip_register_restart_notifier(unsigned int reg, void (*cb)(void))
+void __init
+rockchip_register_restart_notifier(struct rockchip_clk_provider *ctx,
+					       unsigned int reg,
+					       void (*cb)(void))
 {
 	int ret;
 
+	rst_base = ctx->reg_base;
 	reg_restart = reg;
 	cb_restart = cb;
 	ret = register_restart_handler(&rockchip_restart_handler);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/rockchip/clk-cpu.c linux-libre-4.7-gnu/drivers/clk/rockchip/clk-cpu.c
--- linux-libre-4.6-gnu/drivers/clk/rockchip/clk-cpu.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/rockchip/clk-cpu.c	2016-07-24 15:23:50.000000000 -0400
@@ -158,12 +158,16 @@ static int rockchip_cpuclk_pre_rate_chan
 
 		writel(HIWORD_UPDATE(alt_div, reg_data->div_core_mask,
 					      reg_data->div_core_shift) |
-		       HIWORD_UPDATE(1, 1, reg_data->mux_core_shift),
+		       HIWORD_UPDATE(reg_data->mux_core_alt,
+				     reg_data->mux_core_mask,
+				     reg_data->mux_core_shift),
 		       cpuclk->reg_base + reg_data->core_reg);
 	} else {
 		/* select alternate parent */
-		writel(HIWORD_UPDATE(1, 1, reg_data->mux_core_shift),
-			cpuclk->reg_base + reg_data->core_reg);
+		writel(HIWORD_UPDATE(reg_data->mux_core_alt,
+				     reg_data->mux_core_mask,
+				     reg_data->mux_core_shift),
+		       cpuclk->reg_base + reg_data->core_reg);
 	}
 
 	spin_unlock_irqrestore(cpuclk->lock, flags);
@@ -198,7 +202,9 @@ static int rockchip_cpuclk_post_rate_cha
 
 	writel(HIWORD_UPDATE(0, reg_data->div_core_mask,
 				reg_data->div_core_shift) |
-	       HIWORD_UPDATE(0, 1, reg_data->mux_core_shift),
+	       HIWORD_UPDATE(reg_data->mux_core_main,
+				reg_data->mux_core_mask,
+				reg_data->mux_core_shift),
 	       cpuclk->reg_base + reg_data->core_reg);
 
 	if (ndata->old_rate > ndata->new_rate)
@@ -252,7 +258,7 @@ struct clk *rockchip_clk_register_cpuclk
 		return ERR_PTR(-ENOMEM);
 
 	init.name = name;
-	init.parent_names = &parent_names[0];
+	init.parent_names = &parent_names[reg_data->mux_core_main];
 	init.num_parents = 1;
 	init.ops = &rockchip_cpuclk_ops;
 
@@ -270,10 +276,10 @@ struct clk *rockchip_clk_register_cpuclk
 	cpuclk->clk_nb.notifier_call = rockchip_cpuclk_notifier_cb;
 	cpuclk->hw.init = &init;
 
-	cpuclk->alt_parent = __clk_lookup(parent_names[1]);
+	cpuclk->alt_parent = __clk_lookup(parent_names[reg_data->mux_core_alt]);
 	if (!cpuclk->alt_parent) {
-		pr_err("%s: could not lookup alternate parent\n",
-		       __func__);
+		pr_err("%s: could not lookup alternate parent: (%d)\n",
+		       __func__, reg_data->mux_core_alt);
 		ret = -EINVAL;
 		goto free_cpuclk;
 	}
@@ -285,10 +291,11 @@ struct clk *rockchip_clk_register_cpuclk
 		goto free_cpuclk;
 	}
 
-	clk = __clk_lookup(parent_names[0]);
+	clk = __clk_lookup(parent_names[reg_data->mux_core_main]);
 	if (!clk) {
-		pr_err("%s: could not lookup parent clock %s\n",
-		       __func__, parent_names[0]);
+		pr_err("%s: could not lookup parent clock: (%d) %s\n",
+		       __func__, reg_data->mux_core_main,
+		       parent_names[reg_data->mux_core_main]);
 		ret = -EINVAL;
 		goto free_alt_parent;
 	}
@@ -314,9 +321,9 @@ struct clk *rockchip_clk_register_cpuclk
 	}
 
 	cclk = clk_register(NULL, &cpuclk->hw);
-	if (IS_ERR(clk)) {
+	if (IS_ERR(cclk)) {
 		pr_err("%s: could not register cpuclk %s\n", __func__,	name);
-		ret = PTR_ERR(clk);
+		ret = PTR_ERR(cclk);
 		goto free_rate_table;
 	}
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/rockchip/clk.h linux-libre-4.7-gnu/drivers/clk/rockchip/clk.h
--- linux-libre-4.6-gnu/drivers/clk/rockchip/clk.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/rockchip/clk.h	2016-07-24 15:23:50.000000000 -0400
@@ -27,13 +27,13 @@
 #define CLK_ROCKCHIP_CLK_H
 
 #include <linux/io.h>
+#include <linux/clk-provider.h>
 
 struct clk;
 
 #define HIWORD_UPDATE(val, mask, shift) \
 		((val) << (shift) | (mask) << ((shift) + 16))
 
-/* register positions shared by RK2928, RK3036, RK3066, RK3188 and RK3228 */
 #define RK2928_PLL_CON(x)		((x) * 0x4)
 #define RK2928_MODE_CON		0x40
 #define RK2928_CLKSEL_CON(x)	((x) * 0x4 + 0x44)
@@ -92,9 +92,30 @@ struct clk;
 #define RK3368_EMMC_CON0		0x418
 #define RK3368_EMMC_CON1		0x41c
 
+#define RK3399_PLL_CON(x)		RK2928_PLL_CON(x)
+#define RK3399_CLKSEL_CON(x)		((x) * 0x4 + 0x100)
+#define RK3399_CLKGATE_CON(x)		((x) * 0x4 + 0x300)
+#define RK3399_SOFTRST_CON(x)		((x) * 0x4 + 0x400)
+#define RK3399_GLB_SRST_FST		0x500
+#define RK3399_GLB_SRST_SND		0x504
+#define RK3399_GLB_CNT_TH		0x508
+#define RK3399_MISC_CON			0x50c
+#define RK3399_RST_CON			0x510
+#define RK3399_RST_ST			0x514
+#define RK3399_SDMMC_CON0		0x580
+#define RK3399_SDMMC_CON1		0x584
+#define RK3399_SDIO_CON0		0x588
+#define RK3399_SDIO_CON1		0x58c
+
+#define RK3399_PMU_PLL_CON(x)		RK2928_PLL_CON(x)
+#define RK3399_PMU_CLKSEL_CON(x)	((x) * 0x4 + 0x80)
+#define RK3399_PMU_CLKGATE_CON(x)	((x) * 0x4 + 0x100)
+#define RK3399_PMU_SOFTRST_CON(x)	((x) * 0x4 + 0x110)
+
 enum rockchip_pll_type {
 	pll_rk3036,
 	pll_rk3066,
+	pll_rk3399,
 };
 
 #define RK3036_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1,	\
@@ -127,13 +148,29 @@ enum rockchip_pll_type {
 	.nb = _nb,						\
 }
 
+/**
+ * struct rockchip_clk_provider - information about clock provider
+ * @reg_base: virtual address for the register base.
+ * @clk_data: holds clock related data like clk* and number of clocks.
+ * @cru_node: device-node of the clock-provider
+ * @grf: regmap of the general-register-files syscon
+ * @lock: maintains exclusion between callbacks for a given clock-provider.
+ */
+struct rockchip_clk_provider {
+	void __iomem *reg_base;
+	struct clk_onecell_data clk_data;
+	struct device_node *cru_node;
+	struct regmap *grf;
+	spinlock_t lock;
+};
+
 struct rockchip_pll_rate_table {
 	unsigned long rate;
 	unsigned int nr;
 	unsigned int nf;
 	unsigned int no;
 	unsigned int nb;
-	/* for RK3036 */
+	/* for RK3036/RK3399 */
 	unsigned int fbdiv;
 	unsigned int postdiv1;
 	unsigned int refdiv;
@@ -143,10 +180,11 @@ struct rockchip_pll_rate_table {
 };
 
 /**
- * struct rockchip_pll_clock: information about pll clock
+ * struct rockchip_pll_clock - information about pll clock
  * @id: platform specific id of the clock.
  * @name: name of this pll clock.
- * @parent_name: name of the parent clock.
+ * @parent_names: name of the parent clock.
+ * @num_parents: number of parents
  * @flags: optional flags for basic clock.
  * @con_offset: offset of the register for configuring the PLL.
  * @mode_offset: offset of the register for configuring the PLL-mode.
@@ -194,12 +232,13 @@ struct rockchip_pll_clock {
 		.rate_table	= _rtable,				\
 	}
 
-struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
+struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx,
+		enum rockchip_pll_type pll_type,
 		const char *name, const char *const *parent_names,
-		u8 num_parents, void __iomem *base, int con_offset,
-		int grf_lock_offset, int lock_shift, int reg_mode,
-		int mode_shift, struct rockchip_pll_rate_table *rate_table,
-		u8 clk_pll_flags, spinlock_t *lock);
+		u8 num_parents, int con_offset, int grf_lock_offset,
+		int lock_shift, int mode_offset, int mode_shift,
+		struct rockchip_pll_rate_table *rate_table,
+		u8 clk_pll_flags);
 
 struct rockchip_cpuclk_clksel {
 	int reg;
@@ -213,18 +252,23 @@ struct rockchip_cpuclk_rate_table {
 };
 
 /**
- * struct rockchip_cpuclk_reg_data: describes register offsets and masks of the cpuclock
+ * struct rockchip_cpuclk_reg_data - register offsets and masks of the cpuclock
  * @core_reg:		register offset of the core settings register
  * @div_core_shift:	core divider offset used to divide the pll value
  * @div_core_mask:	core divider mask
+ * @mux_core_alt:	mux value to select alternate parent
+ * @mux_core_main:	mux value to select main parent of core
  * @mux_core_shift:	offset of the core multiplexer
+ * @mux_core_mask:	core multiplexer mask
  */
 struct rockchip_cpuclk_reg_data {
 	int		core_reg;
 	u8		div_core_shift;
 	u32		div_core_mask;
-	int		mux_core_reg;
+	u8		mux_core_alt;
+	u8		mux_core_main;
 	u8		mux_core_shift;
+	u32		mux_core_mask;
 };
 
 struct clk *rockchip_clk_register_cpuclk(const char *name,
@@ -428,6 +472,22 @@ struct rockchip_clk_branch {
 		.child		= ch,				\
 	}
 
+#define COMPOSITE_FRACMUX_NOGATE(_id, cname, pname, f, mo, df, ch) \
+	{							\
+		.id		= _id,				\
+		.branch_type	= branch_fraction_divider,	\
+		.name		= cname,			\
+		.parent_names	= (const char *[]){ pname },	\
+		.num_parents	= 1,				\
+		.flags		= f,				\
+		.muxdiv_offset	= mo,				\
+		.div_shift	= 16,				\
+		.div_width	= 16,				\
+		.div_flags	= df,				\
+		.gate_offset	= -1,				\
+		.child		= ch,				\
+	}
+
 #define MUX(_id, cname, pnames, f, o, s, w, mf)			\
 	{							\
 		.id		= _id,				\
@@ -536,21 +596,27 @@ struct rockchip_clk_branch {
 		.gate_flags	= gf,				\
 	}
 
-void rockchip_clk_init(struct device_node *np, void __iomem *base,
-		       unsigned long nr_clks);
-struct regmap *rockchip_clk_get_grf(void);
-void rockchip_clk_add_lookup(struct clk *clk, unsigned int id);
-void rockchip_clk_register_branches(struct rockchip_clk_branch *clk_list,
+struct rockchip_clk_provider *rockchip_clk_init(struct device_node *np,
+			void __iomem *base, unsigned long nr_clks);
+void rockchip_clk_of_add_provider(struct device_node *np,
+				struct rockchip_clk_provider *ctx);
+void rockchip_clk_add_lookup(struct rockchip_clk_provider *ctx,
+			     struct clk *clk, unsigned int id);
+void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx,
+				    struct rockchip_clk_branch *list,
 				    unsigned int nr_clk);
-void rockchip_clk_register_plls(struct rockchip_pll_clock *pll_list,
+void rockchip_clk_register_plls(struct rockchip_clk_provider *ctx,
+				struct rockchip_pll_clock *pll_list,
 				unsigned int nr_pll, int grf_lock_offset);
-void rockchip_clk_register_armclk(unsigned int lookup_id, const char *name,
+void rockchip_clk_register_armclk(struct rockchip_clk_provider *ctx,
+			unsigned int lookup_id, const char *name,
 			const char *const *parent_names, u8 num_parents,
 			const struct rockchip_cpuclk_reg_data *reg_data,
 			const struct rockchip_cpuclk_rate_table *rates,
 			int nrates);
 void rockchip_clk_protect_critical(const char *const clocks[], int nclocks);
-void rockchip_register_restart_notifier(unsigned int reg, void (*cb)(void));
+void rockchip_register_restart_notifier(struct rockchip_clk_provider *ctx,
+					unsigned int reg, void (*cb)(void));
 
 #define ROCKCHIP_SOFTRST_HIWORD_MASK	BIT(0)
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/rockchip/clk-mmc-phase.c linux-libre-4.7-gnu/drivers/clk/rockchip/clk-mmc-phase.c
--- linux-libre-4.6-gnu/drivers/clk/rockchip/clk-mmc-phase.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/rockchip/clk-mmc-phase.c	2016-07-24 15:23:50.000000000 -0400
@@ -41,8 +41,6 @@ static unsigned long rockchip_mmc_recalc
 #define ROCKCHIP_MMC_DEGREE_MASK 0x3
 #define ROCKCHIP_MMC_DELAYNUM_OFFSET 2
 #define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
-#define ROCKCHIP_MMC_INIT_STATE_RESET 0x1
-#define ROCKCHIP_MMC_INIT_STATE_SHIFT 1
 
 #define PSECS_PER_SEC 1000000000000LL
 
@@ -123,7 +121,8 @@ static int rockchip_mmc_set_phase(struct
 	raw_value = delay_num ? ROCKCHIP_MMC_DELAY_SEL : 0;
 	raw_value |= delay_num << ROCKCHIP_MMC_DELAYNUM_OFFSET;
 	raw_value |= nineties;
-	writel(HIWORD_UPDATE(raw_value, 0x07ff, mmc_clock->shift), mmc_clock->reg);
+	writel(HIWORD_UPDATE(raw_value, 0x07ff, mmc_clock->shift),
+	       mmc_clock->reg);
 
 	pr_debug("%s->set_phase(%d) delay_nums=%u reg[0x%p]=0x%03x actual_degrees=%d\n",
 		clk_hw_get_name(hw), degrees, delay_num,
@@ -153,6 +152,7 @@ struct clk *rockchip_clk_register_mmc(co
 		return ERR_PTR(-ENOMEM);
 
 	init.name = name;
+	init.flags = 0;
 	init.num_parents = num_parents;
 	init.parent_names = parent_names;
 	init.ops = &rockchip_mmc_clk_ops;
@@ -161,15 +161,6 @@ struct clk *rockchip_clk_register_mmc(co
 	mmc_clock->reg = reg;
 	mmc_clock->shift = shift;
 
-	/*
-	 * Assert init_state to soft reset the CLKGEN
-	 * for mmc tuning phase and degree
-	 */
-	if (mmc_clock->shift == ROCKCHIP_MMC_INIT_STATE_SHIFT)
-		writel(HIWORD_UPDATE(ROCKCHIP_MMC_INIT_STATE_RESET,
-				     ROCKCHIP_MMC_INIT_STATE_RESET,
-				     mmc_clock->shift), mmc_clock->reg);
-
 	clk = clk_register(NULL, &mmc_clock->hw);
 	if (IS_ERR(clk))
 		kfree(mmc_clock);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/rockchip/clk-pll.c linux-libre-4.7-gnu/drivers/clk/rockchip/clk-pll.c
--- linux-libre-4.6-gnu/drivers/clk/rockchip/clk-pll.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/rockchip/clk-pll.c	2016-07-24 15:23:50.000000000 -0400
@@ -46,6 +46,8 @@ struct rockchip_clk_pll {
 	const struct rockchip_pll_rate_table *rate_table;
 	unsigned int		rate_count;
 	spinlock_t		*lock;
+
+	struct rockchip_clk_provider *ctx;
 };
 
 #define to_rockchip_clk_pll(_hw) container_of(_hw, struct rockchip_clk_pll, hw)
@@ -90,15 +92,10 @@ static long rockchip_pll_round_rate(stru
  */
 static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll)
 {
-	struct regmap *grf = rockchip_clk_get_grf();
+	struct regmap *grf = pll->ctx->grf;
 	unsigned int val;
 	int delay = 24000000, ret;
 
-	if (IS_ERR(grf)) {
-		pr_err("%s: grf regmap not available\n", __func__);
-		return PTR_ERR(grf);
-	}
-
 	while (delay > 0) {
 		ret = regmap_read(grf, pll->lock_offset, &val);
 		if (ret) {
@@ -234,7 +231,7 @@ static int rockchip_rk3036_pll_set_param
 	/* wait for the pll to lock */
 	ret = rockchip_pll_wait_lock(pll);
 	if (ret) {
-		pr_warn("%s: pll update unsucessful, trying to restore old params\n",
+		pr_warn("%s: pll update unsuccessful, trying to restore old params\n",
 			__func__);
 		rockchip_rk3036_pll_set_params(pll, &cur);
 	}
@@ -250,17 +247,9 @@ static int rockchip_rk3036_pll_set_rate(
 {
 	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
 	const struct rockchip_pll_rate_table *rate;
-	unsigned long old_rate = rockchip_rk3036_pll_recalc_rate(hw, prate);
-	struct regmap *grf = rockchip_clk_get_grf();
-
-	if (IS_ERR(grf)) {
-		pr_debug("%s: grf regmap not available, aborting rate change\n",
-			 __func__);
-		return PTR_ERR(grf);
-	}
 
-	pr_debug("%s: changing %s from %lu to %lu with a parent rate of %lu\n",
-		 __func__, __clk_get_name(hw->clk), old_rate, drate, prate);
+	pr_debug("%s: changing %s to %lu with a parent rate of %lu\n",
+		 __func__, __clk_get_name(hw->clk), drate, prate);
 
 	/* Get required rate settings from table */
 	rate = rockchip_get_pll_settings(pll, drate);
@@ -473,7 +462,7 @@ static int rockchip_rk3066_pll_set_param
 	/* wait for the pll to lock */
 	ret = rockchip_pll_wait_lock(pll);
 	if (ret) {
-		pr_warn("%s: pll update unsucessful, trying to restore old params\n",
+		pr_warn("%s: pll update unsuccessful, trying to restore old params\n",
 			__func__);
 		rockchip_rk3066_pll_set_params(pll, &cur);
 	}
@@ -489,17 +478,9 @@ static int rockchip_rk3066_pll_set_rate(
 {
 	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
 	const struct rockchip_pll_rate_table *rate;
-	unsigned long old_rate = rockchip_rk3066_pll_recalc_rate(hw, prate);
-	struct regmap *grf = rockchip_clk_get_grf();
 
-	if (IS_ERR(grf)) {
-		pr_debug("%s: grf regmap not available, aborting rate change\n",
-			 __func__);
-		return PTR_ERR(grf);
-	}
-
-	pr_debug("%s: changing %s from %lu to %lu with a parent rate of %lu\n",
-		 __func__, clk_hw_get_name(hw), old_rate, drate, prate);
+	pr_debug("%s: changing %s to %lu with a parent rate of %lu\n",
+		 __func__, clk_hw_get_name(hw), drate, prate);
 
 	/* Get required rate settings from table */
 	rate = rockchip_get_pll_settings(pll, drate);
@@ -563,11 +544,6 @@ static void rockchip_rk3066_pll_init(str
 		 rate->no, cur.no, rate->nf, cur.nf, rate->nb, cur.nb);
 	if (rate->nr != cur.nr || rate->no != cur.no || rate->nf != cur.nf
 						     || rate->nb != cur.nb) {
-		struct regmap *grf = rockchip_clk_get_grf();
-
-		if (IS_ERR(grf))
-			return;
-
 		pr_debug("%s: pll %s: rate params do not match rate table, adjusting\n",
 			 __func__, clk_hw_get_name(hw));
 		rockchip_rk3066_pll_set_params(pll, rate);
@@ -591,16 +567,277 @@ static const struct clk_ops rockchip_rk3
 	.init = rockchip_rk3066_pll_init,
 };
 
+/**
+ * PLL used in RK3399
+ */
+
+#define RK3399_PLLCON(i)			(i * 0x4)
+#define RK3399_PLLCON0_FBDIV_MASK		0xfff
+#define RK3399_PLLCON0_FBDIV_SHIFT		0
+#define RK3399_PLLCON1_REFDIV_MASK		0x3f
+#define RK3399_PLLCON1_REFDIV_SHIFT		0
+#define RK3399_PLLCON1_POSTDIV1_MASK		0x7
+#define RK3399_PLLCON1_POSTDIV1_SHIFT		8
+#define RK3399_PLLCON1_POSTDIV2_MASK		0x7
+#define RK3399_PLLCON1_POSTDIV2_SHIFT		12
+#define RK3399_PLLCON2_FRAC_MASK		0xffffff
+#define RK3399_PLLCON2_FRAC_SHIFT		0
+#define RK3399_PLLCON2_LOCK_STATUS		BIT(31)
+#define RK3399_PLLCON3_PWRDOWN			BIT(0)
+#define RK3399_PLLCON3_DSMPD_MASK		0x1
+#define RK3399_PLLCON3_DSMPD_SHIFT		3
+
+static int rockchip_rk3399_pll_wait_lock(struct rockchip_clk_pll *pll)
+{
+	u32 pllcon;
+	int delay = 24000000;
+
+	/* poll check the lock status in rk3399 xPLLCON2 */
+	while (delay > 0) {
+		pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(2));
+		if (pllcon & RK3399_PLLCON2_LOCK_STATUS)
+			return 0;
+
+		delay--;
+	}
+
+	pr_err("%s: timeout waiting for pll to lock\n", __func__);
+	return -ETIMEDOUT;
+}
+
+static void rockchip_rk3399_pll_get_params(struct rockchip_clk_pll *pll,
+					struct rockchip_pll_rate_table *rate)
+{
+	u32 pllcon;
+
+	pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(0));
+	rate->fbdiv = ((pllcon >> RK3399_PLLCON0_FBDIV_SHIFT)
+				& RK3399_PLLCON0_FBDIV_MASK);
+
+	pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(1));
+	rate->refdiv = ((pllcon >> RK3399_PLLCON1_REFDIV_SHIFT)
+				& RK3399_PLLCON1_REFDIV_MASK);
+	rate->postdiv1 = ((pllcon >> RK3399_PLLCON1_POSTDIV1_SHIFT)
+				& RK3399_PLLCON1_POSTDIV1_MASK);
+	rate->postdiv2 = ((pllcon >> RK3399_PLLCON1_POSTDIV2_SHIFT)
+				& RK3399_PLLCON1_POSTDIV2_MASK);
+
+	pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(2));
+	rate->frac = ((pllcon >> RK3399_PLLCON2_FRAC_SHIFT)
+				& RK3399_PLLCON2_FRAC_MASK);
+
+	pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(3));
+	rate->dsmpd = ((pllcon >> RK3399_PLLCON3_DSMPD_SHIFT)
+				& RK3399_PLLCON3_DSMPD_MASK);
+}
+
+static unsigned long rockchip_rk3399_pll_recalc_rate(struct clk_hw *hw,
+						     unsigned long prate)
+{
+	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+	struct rockchip_pll_rate_table cur;
+	u64 rate64 = prate;
+
+	rockchip_rk3399_pll_get_params(pll, &cur);
+
+	rate64 *= cur.fbdiv;
+	do_div(rate64, cur.refdiv);
+
+	if (cur.dsmpd == 0) {
+		/* fractional mode */
+		u64 frac_rate64 = prate * cur.frac;
+
+		do_div(frac_rate64, cur.refdiv);
+		rate64 += frac_rate64 >> 24;
+	}
+
+	do_div(rate64, cur.postdiv1);
+	do_div(rate64, cur.postdiv2);
+
+	return (unsigned long)rate64;
+}
+
+static int rockchip_rk3399_pll_set_params(struct rockchip_clk_pll *pll,
+				const struct rockchip_pll_rate_table *rate)
+{
+	const struct clk_ops *pll_mux_ops = pll->pll_mux_ops;
+	struct clk_mux *pll_mux = &pll->pll_mux;
+	struct rockchip_pll_rate_table cur;
+	u32 pllcon;
+	int rate_change_remuxed = 0;
+	int cur_parent;
+	int ret;
+
+	pr_debug("%s: rate settings for %lu fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n",
+		__func__, rate->rate, rate->fbdiv, rate->postdiv1, rate->refdiv,
+		rate->postdiv2, rate->dsmpd, rate->frac);
+
+	rockchip_rk3399_pll_get_params(pll, &cur);
+	cur.rate = 0;
+
+	cur_parent = pll_mux_ops->get_parent(&pll_mux->hw);
+	if (cur_parent == PLL_MODE_NORM) {
+		pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW);
+		rate_change_remuxed = 1;
+	}
+
+	/* update pll values */
+	writel_relaxed(HIWORD_UPDATE(rate->fbdiv, RK3399_PLLCON0_FBDIV_MASK,
+						  RK3399_PLLCON0_FBDIV_SHIFT),
+		       pll->reg_base + RK3399_PLLCON(0));
+
+	writel_relaxed(HIWORD_UPDATE(rate->refdiv, RK3399_PLLCON1_REFDIV_MASK,
+						   RK3399_PLLCON1_REFDIV_SHIFT) |
+		       HIWORD_UPDATE(rate->postdiv1, RK3399_PLLCON1_POSTDIV1_MASK,
+						     RK3399_PLLCON1_POSTDIV1_SHIFT) |
+		       HIWORD_UPDATE(rate->postdiv2, RK3399_PLLCON1_POSTDIV2_MASK,
+						     RK3399_PLLCON1_POSTDIV2_SHIFT),
+		       pll->reg_base + RK3399_PLLCON(1));
+
+	/* xPLL CON2 is not HIWORD_MASK */
+	pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(2));
+	pllcon &= ~(RK3399_PLLCON2_FRAC_MASK << RK3399_PLLCON2_FRAC_SHIFT);
+	pllcon |= rate->frac << RK3399_PLLCON2_FRAC_SHIFT;
+	writel_relaxed(pllcon, pll->reg_base + RK3399_PLLCON(2));
+
+	writel_relaxed(HIWORD_UPDATE(rate->dsmpd, RK3399_PLLCON3_DSMPD_MASK,
+					    RK3399_PLLCON3_DSMPD_SHIFT),
+		       pll->reg_base + RK3399_PLLCON(3));
+
+	/* wait for the pll to lock */
+	ret = rockchip_rk3399_pll_wait_lock(pll);
+	if (ret) {
+		pr_warn("%s: pll update unsuccessful, trying to restore old params\n",
+			__func__);
+		rockchip_rk3399_pll_set_params(pll, &cur);
+	}
+
+	if (rate_change_remuxed)
+		pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM);
+
+	return ret;
+}
+
+static int rockchip_rk3399_pll_set_rate(struct clk_hw *hw, unsigned long drate,
+					unsigned long prate)
+{
+	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+	const struct rockchip_pll_rate_table *rate;
+
+	pr_debug("%s: changing %s to %lu with a parent rate of %lu\n",
+		 __func__, __clk_get_name(hw->clk), drate, prate);
+
+	/* Get required rate settings from table */
+	rate = rockchip_get_pll_settings(pll, drate);
+	if (!rate) {
+		pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
+			drate, __clk_get_name(hw->clk));
+		return -EINVAL;
+	}
+
+	return rockchip_rk3399_pll_set_params(pll, rate);
+}
+
+static int rockchip_rk3399_pll_enable(struct clk_hw *hw)
+{
+	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+
+	writel(HIWORD_UPDATE(0, RK3399_PLLCON3_PWRDOWN, 0),
+	       pll->reg_base + RK3399_PLLCON(3));
+
+	return 0;
+}
+
+static void rockchip_rk3399_pll_disable(struct clk_hw *hw)
+{
+	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+
+	writel(HIWORD_UPDATE(RK3399_PLLCON3_PWRDOWN,
+			     RK3399_PLLCON3_PWRDOWN, 0),
+	       pll->reg_base + RK3399_PLLCON(3));
+}
+
+static int rockchip_rk3399_pll_is_enabled(struct clk_hw *hw)
+{
+	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+	u32 pllcon = readl(pll->reg_base + RK3399_PLLCON(3));
+
+	return !(pllcon & RK3399_PLLCON3_PWRDOWN);
+}
+
+static void rockchip_rk3399_pll_init(struct clk_hw *hw)
+{
+	struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+	const struct rockchip_pll_rate_table *rate;
+	struct rockchip_pll_rate_table cur;
+	unsigned long drate;
+
+	if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE))
+		return;
+
+	drate = clk_hw_get_rate(hw);
+	rate = rockchip_get_pll_settings(pll, drate);
+
+	/* when no rate setting for the current rate, rely on clk_set_rate */
+	if (!rate)
+		return;
+
+	rockchip_rk3399_pll_get_params(pll, &cur);
+
+	pr_debug("%s: pll %s@%lu: Hz\n", __func__, __clk_get_name(hw->clk),
+		 drate);
+	pr_debug("old - fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n",
+		 cur.fbdiv, cur.postdiv1, cur.refdiv, cur.postdiv2,
+		 cur.dsmpd, cur.frac);
+	pr_debug("new - fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n",
+		 rate->fbdiv, rate->postdiv1, rate->refdiv, rate->postdiv2,
+		 rate->dsmpd, rate->frac);
+
+	if (rate->fbdiv != cur.fbdiv || rate->postdiv1 != cur.postdiv1 ||
+		rate->refdiv != cur.refdiv || rate->postdiv2 != cur.postdiv2 ||
+		rate->dsmpd != cur.dsmpd || rate->frac != cur.frac) {
+		struct clk *parent = clk_get_parent(hw->clk);
+
+		if (!parent) {
+			pr_warn("%s: parent of %s not available\n",
+				__func__, __clk_get_name(hw->clk));
+			return;
+		}
+
+		pr_debug("%s: pll %s: rate params do not match rate table, adjusting\n",
+			 __func__, __clk_get_name(hw->clk));
+		rockchip_rk3399_pll_set_params(pll, rate);
+	}
+}
+
+static const struct clk_ops rockchip_rk3399_pll_clk_norate_ops = {
+	.recalc_rate = rockchip_rk3399_pll_recalc_rate,
+	.enable = rockchip_rk3399_pll_enable,
+	.disable = rockchip_rk3399_pll_disable,
+	.is_enabled = rockchip_rk3399_pll_is_enabled,
+};
+
+static const struct clk_ops rockchip_rk3399_pll_clk_ops = {
+	.recalc_rate = rockchip_rk3399_pll_recalc_rate,
+	.round_rate = rockchip_pll_round_rate,
+	.set_rate = rockchip_rk3399_pll_set_rate,
+	.enable = rockchip_rk3399_pll_enable,
+	.disable = rockchip_rk3399_pll_disable,
+	.is_enabled = rockchip_rk3399_pll_is_enabled,
+	.init = rockchip_rk3399_pll_init,
+};
+
 /*
  * Common registering of pll clocks
  */
 
-struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
+struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx,
+		enum rockchip_pll_type pll_type,
 		const char *name, const char *const *parent_names,
-		u8 num_parents, void __iomem *base, int con_offset,
-		int grf_lock_offset, int lock_shift, int mode_offset,
-		int mode_shift, struct rockchip_pll_rate_table *rate_table,
-		u8 clk_pll_flags, spinlock_t *lock)
+		u8 num_parents, int con_offset, int grf_lock_offset,
+		int lock_shift, int mode_offset, int mode_shift,
+		struct rockchip_pll_rate_table *rate_table,
+		u8 clk_pll_flags)
 {
 	const char *pll_parents[3];
 	struct clk_init_data init;
@@ -624,14 +861,16 @@ struct clk *rockchip_clk_register_pll(en
 	/* create the mux on top of the real pll */
 	pll->pll_mux_ops = &clk_mux_ops;
 	pll_mux = &pll->pll_mux;
-	pll_mux->reg = base + mode_offset;
+	pll_mux->reg = ctx->reg_base + mode_offset;
 	pll_mux->shift = mode_shift;
 	pll_mux->mask = PLL_MODE_MASK;
 	pll_mux->flags = 0;
-	pll_mux->lock = lock;
+	pll_mux->lock = &ctx->lock;
 	pll_mux->hw.init = &init;
 
-	if (pll_type == pll_rk3036 || pll_type == pll_rk3066)
+	if (pll_type == pll_rk3036 ||
+	    pll_type == pll_rk3066 ||
+	    pll_type == pll_rk3399)
 		pll_mux->flags |= CLK_MUX_HIWORD_MASK;
 
 	/* the actual muxing is xin24m, pll-output, xin32k */
@@ -677,17 +916,23 @@ struct clk *rockchip_clk_register_pll(en
 
 	switch (pll_type) {
 	case pll_rk3036:
-		if (!pll->rate_table)
+		if (!pll->rate_table || IS_ERR(ctx->grf))
 			init.ops = &rockchip_rk3036_pll_clk_norate_ops;
 		else
 			init.ops = &rockchip_rk3036_pll_clk_ops;
 		break;
 	case pll_rk3066:
-		if (!pll->rate_table)
+		if (!pll->rate_table || IS_ERR(ctx->grf))
 			init.ops = &rockchip_rk3066_pll_clk_norate_ops;
 		else
 			init.ops = &rockchip_rk3066_pll_clk_ops;
 		break;
+	case pll_rk3399:
+		if (!pll->rate_table)
+			init.ops = &rockchip_rk3399_pll_clk_norate_ops;
+		else
+			init.ops = &rockchip_rk3399_pll_clk_ops;
+		break;
 	default:
 		pr_warn("%s: Unknown pll type for pll clk %s\n",
 			__func__, name);
@@ -695,11 +940,12 @@ struct clk *rockchip_clk_register_pll(en
 
 	pll->hw.init = &init;
 	pll->type = pll_type;
-	pll->reg_base = base + con_offset;
+	pll->reg_base = ctx->reg_base + con_offset;
 	pll->lock_offset = grf_lock_offset;
 	pll->lock_shift = lock_shift;
 	pll->flags = clk_pll_flags;
-	pll->lock = lock;
+	pll->lock = &ctx->lock;
+	pll->ctx = ctx;
 
 	pll_clk = clk_register(NULL, &pll->hw);
 	if (IS_ERR(pll_clk)) {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/rockchip/clk-rk3036.c linux-libre-4.7-gnu/drivers/clk/rockchip/clk-rk3036.c
--- linux-libre-4.6-gnu/drivers/clk/rockchip/clk-rk3036.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/rockchip/clk-rk3036.c	2016-07-24 15:23:50.000000000 -0400
@@ -113,7 +113,10 @@ static const struct rockchip_cpuclk_reg_
 	.core_reg = RK2928_CLKSEL_CON(0),
 	.div_core_shift = 0,
 	.div_core_mask = 0x1f,
+	.mux_core_alt = 1,
+	.mux_core_main = 0,
 	.mux_core_shift = 7,
+	.mux_core_mask = 0x1,
 };
 
 PNAME(mux_pll_p)		= { "xin24m", "xin24m" };
@@ -437,6 +440,7 @@ static const char *const rk3036_critical
 
 static void __init rk3036_clk_init(struct device_node *np)
 {
+	struct rockchip_clk_provider *ctx;
 	void __iomem *reg_base;
 	struct clk *clk;
 
@@ -446,22 +450,27 @@ static void __init rk3036_clk_init(struc
 		return;
 	}
 
-	rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
+	ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
+	if (IS_ERR(ctx)) {
+		pr_err("%s: rockchip clk init failed\n", __func__);
+		iounmap(reg_base);
+		return;
+	}
 
 	clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1);
 	if (IS_ERR(clk))
 		pr_warn("%s: could not register clock usb480m: %ld\n",
 			__func__, PTR_ERR(clk));
 
-	rockchip_clk_register_plls(rk3036_pll_clks,
+	rockchip_clk_register_plls(ctx, rk3036_pll_clks,
 				   ARRAY_SIZE(rk3036_pll_clks),
 				   RK3036_GRF_SOC_STATUS0);
-	rockchip_clk_register_branches(rk3036_clk_branches,
+	rockchip_clk_register_branches(ctx, rk3036_clk_branches,
 				  ARRAY_SIZE(rk3036_clk_branches));
 	rockchip_clk_protect_critical(rk3036_critical_clocks,
 				      ARRAY_SIZE(rk3036_critical_clocks));
 
-	rockchip_clk_register_armclk(ARMCLK, "armclk",
+	rockchip_clk_register_armclk(ctx, ARMCLK, "armclk",
 			mux_armclk_p, ARRAY_SIZE(mux_armclk_p),
 			&rk3036_cpuclk_data, rk3036_cpuclk_rates,
 			ARRAY_SIZE(rk3036_cpuclk_rates));
@@ -469,6 +478,8 @@ static void __init rk3036_clk_init(struc
 	rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0),
 				  ROCKCHIP_SOFTRST_HIWORD_MASK);
 
-	rockchip_register_restart_notifier(RK2928_GLB_SRST_FST, NULL);
+	rockchip_register_restart_notifier(ctx, RK2928_GLB_SRST_FST, NULL);
+
+	rockchip_clk_of_add_provider(np, ctx);
 }
 CLK_OF_DECLARE(rk3036_cru, "rockchip,rk3036-cru", rk3036_clk_init);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/rockchip/clk-rk3188.c linux-libre-4.7-gnu/drivers/clk/rockchip/clk-rk3188.c
--- linux-libre-4.6-gnu/drivers/clk/rockchip/clk-rk3188.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/rockchip/clk-rk3188.c	2016-07-24 15:23:50.000000000 -0400
@@ -155,7 +155,10 @@ static const struct rockchip_cpuclk_reg_
 	.core_reg = RK2928_CLKSEL_CON(0),
 	.div_core_shift = 0,
 	.div_core_mask = 0x1f,
+	.mux_core_alt = 1,
+	.mux_core_main = 0,
 	.mux_core_shift = 8,
+	.mux_core_mask = 0x1,
 };
 
 #define RK3188_DIV_ACLK_CORE_MASK	0x7
@@ -191,7 +194,10 @@ static const struct rockchip_cpuclk_reg_
 	.core_reg = RK2928_CLKSEL_CON(0),
 	.div_core_shift = 9,
 	.div_core_mask = 0x1f,
+	.mux_core_alt = 1,
+	.mux_core_main = 0,
 	.mux_core_shift = 8,
+	.mux_core_mask = 0x1,
 };
 
 PNAME(mux_pll_p)		= { "xin24m", "xin32k" };
@@ -753,57 +759,75 @@ static const char *const rk3188_critical
 	"hclk_cpubus"
 };
 
-static void __init rk3188_common_clk_init(struct device_node *np)
+static struct rockchip_clk_provider *__init rk3188_common_clk_init(struct device_node *np)
 {
+	struct rockchip_clk_provider *ctx;
 	void __iomem *reg_base;
 
 	reg_base = of_iomap(np, 0);
 	if (!reg_base) {
 		pr_err("%s: could not map cru region\n", __func__);
-		return;
+		return ERR_PTR(-ENOMEM);
 	}
 
-	rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
+	ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
+	if (IS_ERR(ctx)) {
+		pr_err("%s: rockchip clk init failed\n", __func__);
+		iounmap(reg_base);
+		return ERR_PTR(-ENOMEM);
+	}
 
-	rockchip_clk_register_branches(common_clk_branches,
+	rockchip_clk_register_branches(ctx, common_clk_branches,
 				  ARRAY_SIZE(common_clk_branches));
 
 	rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0),
 				  ROCKCHIP_SOFTRST_HIWORD_MASK);
 
-	rockchip_register_restart_notifier(RK2928_GLB_SRST_FST, NULL);
+	rockchip_register_restart_notifier(ctx, RK2928_GLB_SRST_FST, NULL);
+
+	return ctx;
 }
 
 static void __init rk3066a_clk_init(struct device_node *np)
 {
-	rk3188_common_clk_init(np);
-	rockchip_clk_register_plls(rk3066_pll_clks,
+	struct rockchip_clk_provider *ctx;
+
+	ctx = rk3188_common_clk_init(np);
+	if (IS_ERR(ctx))
+		return;
+
+	rockchip_clk_register_plls(ctx, rk3066_pll_clks,
 				   ARRAY_SIZE(rk3066_pll_clks),
 				   RK3066_GRF_SOC_STATUS);
-	rockchip_clk_register_branches(rk3066a_clk_branches,
+	rockchip_clk_register_branches(ctx, rk3066a_clk_branches,
 				  ARRAY_SIZE(rk3066a_clk_branches));
-	rockchip_clk_register_armclk(ARMCLK, "armclk",
+	rockchip_clk_register_armclk(ctx, ARMCLK, "armclk",
 			mux_armclk_p, ARRAY_SIZE(mux_armclk_p),
 			&rk3066_cpuclk_data, rk3066_cpuclk_rates,
 			ARRAY_SIZE(rk3066_cpuclk_rates));
 	rockchip_clk_protect_critical(rk3188_critical_clocks,
 				      ARRAY_SIZE(rk3188_critical_clocks));
+	rockchip_clk_of_add_provider(np, ctx);
 }
 CLK_OF_DECLARE(rk3066a_cru, "rockchip,rk3066a-cru", rk3066a_clk_init);
 
 static void __init rk3188a_clk_init(struct device_node *np)
 {
+	struct rockchip_clk_provider *ctx;
 	struct clk *clk1, *clk2;
 	unsigned long rate;
 	int ret;
 
-	rk3188_common_clk_init(np);
-	rockchip_clk_register_plls(rk3188_pll_clks,
+	ctx = rk3188_common_clk_init(np);
+	if (IS_ERR(ctx))
+		return;
+
+	rockchip_clk_register_plls(ctx, rk3188_pll_clks,
 				   ARRAY_SIZE(rk3188_pll_clks),
 				   RK3188_GRF_SOC_STATUS);
-	rockchip_clk_register_branches(rk3188_clk_branches,
+	rockchip_clk_register_branches(ctx, rk3188_clk_branches,
 				  ARRAY_SIZE(rk3188_clk_branches));
-	rockchip_clk_register_armclk(ARMCLK, "armclk",
+	rockchip_clk_register_armclk(ctx, ARMCLK, "armclk",
 				  mux_armclk_p, ARRAY_SIZE(mux_armclk_p),
 				  &rk3188_cpuclk_data, rk3188_cpuclk_rates,
 				  ARRAY_SIZE(rk3188_cpuclk_rates));
@@ -827,6 +851,7 @@ static void __init rk3188a_clk_init(stru
 
 	rockchip_clk_protect_critical(rk3188_critical_clocks,
 				      ARRAY_SIZE(rk3188_critical_clocks));
+	rockchip_clk_of_add_provider(np, ctx);
 }
 CLK_OF_DECLARE(rk3188a_cru, "rockchip,rk3188a-cru", rk3188a_clk_init);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/rockchip/clk-rk3228.c linux-libre-4.7-gnu/drivers/clk/rockchip/clk-rk3228.c
--- linux-libre-4.6-gnu/drivers/clk/rockchip/clk-rk3228.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/rockchip/clk-rk3228.c	2016-07-24 15:23:50.000000000 -0400
@@ -111,7 +111,10 @@ static const struct rockchip_cpuclk_reg_
 	.core_reg = RK2928_CLKSEL_CON(0),
 	.div_core_shift = 0,
 	.div_core_mask = 0x1f,
+	.mux_core_alt = 1,
+	.mux_core_main = 0,
 	.mux_core_shift = 6,
+	.mux_core_mask = 0x1,
 };
 
 PNAME(mux_pll_p)		= { "clk_24m", "xin24m" };
@@ -625,6 +628,7 @@ static const char *const rk3228_critical
 
 static void __init rk3228_clk_init(struct device_node *np)
 {
+	struct rockchip_clk_provider *ctx;
 	void __iomem *reg_base;
 
 	reg_base = of_iomap(np, 0);
@@ -633,17 +637,22 @@ static void __init rk3228_clk_init(struc
 		return;
 	}
 
-	rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
+	ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
+	if (IS_ERR(ctx)) {
+		pr_err("%s: rockchip clk init failed\n", __func__);
+		iounmap(reg_base);
+		return;
+	}
 
-	rockchip_clk_register_plls(rk3228_pll_clks,
+	rockchip_clk_register_plls(ctx, rk3228_pll_clks,
 				   ARRAY_SIZE(rk3228_pll_clks),
 				   RK3228_GRF_SOC_STATUS0);
-	rockchip_clk_register_branches(rk3228_clk_branches,
+	rockchip_clk_register_branches(ctx, rk3228_clk_branches,
 				  ARRAY_SIZE(rk3228_clk_branches));
 	rockchip_clk_protect_critical(rk3228_critical_clocks,
 				      ARRAY_SIZE(rk3228_critical_clocks));
 
-	rockchip_clk_register_armclk(ARMCLK, "armclk",
+	rockchip_clk_register_armclk(ctx, ARMCLK, "armclk",
 			mux_armclk_p, ARRAY_SIZE(mux_armclk_p),
 			&rk3228_cpuclk_data, rk3228_cpuclk_rates,
 			ARRAY_SIZE(rk3228_cpuclk_rates));
@@ -651,6 +660,8 @@ static void __init rk3228_clk_init(struc
 	rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0),
 				  ROCKCHIP_SOFTRST_HIWORD_MASK);
 
-	rockchip_register_restart_notifier(RK3228_GLB_SRST_FST, NULL);
+	rockchip_register_restart_notifier(ctx, RK3228_GLB_SRST_FST, NULL);
+
+	rockchip_clk_of_add_provider(np, ctx);
 }
 CLK_OF_DECLARE(rk3228_cru, "rockchip,rk3228-cru", rk3228_clk_init);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/rockchip/clk-rk3288.c linux-libre-4.7-gnu/drivers/clk/rockchip/clk-rk3288.c
--- linux-libre-4.6-gnu/drivers/clk/rockchip/clk-rk3288.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/rockchip/clk-rk3288.c	2016-07-24 15:23:50.000000000 -0400
@@ -165,7 +165,10 @@ static const struct rockchip_cpuclk_reg_
 	.core_reg = RK3288_CLKSEL_CON(0),
 	.div_core_shift = 8,
 	.div_core_mask = 0x1f,
+	.mux_core_alt = 1,
+	.mux_core_main = 0,
 	.mux_core_shift = 15,
+	.mux_core_mask = 0x1,
 };
 
 PNAME(mux_pll_p)		= { "xin24m", "xin32k" };
@@ -878,6 +881,7 @@ static struct syscore_ops rk3288_clk_sys
 
 static void __init rk3288_clk_init(struct device_node *np)
 {
+	struct rockchip_clk_provider *ctx;
 	struct clk *clk;
 
 	rk3288_cru_base = of_iomap(np, 0);
@@ -886,7 +890,12 @@ static void __init rk3288_clk_init(struc
 		return;
 	}
 
-	rockchip_clk_init(np, rk3288_cru_base, CLK_NR_CLKS);
+	ctx = rockchip_clk_init(np, rk3288_cru_base, CLK_NR_CLKS);
+	if (IS_ERR(ctx)) {
+		pr_err("%s: rockchip clk init failed\n", __func__);
+		iounmap(rk3288_cru_base);
+		return;
+	}
 
 	/* Watchdog pclk is controlled by RK3288_SGRF_SOC_CON0[1]. */
 	clk = clk_register_fixed_factor(NULL, "pclk_wdt", "pclk_pd_alive", 0, 1, 1);
@@ -894,17 +903,17 @@ static void __init rk3288_clk_init(struc
 		pr_warn("%s: could not register clock pclk_wdt: %ld\n",
 			__func__, PTR_ERR(clk));
 	else
-		rockchip_clk_add_lookup(clk, PCLK_WDT);
+		rockchip_clk_add_lookup(ctx, clk, PCLK_WDT);
 
-	rockchip_clk_register_plls(rk3288_pll_clks,
+	rockchip_clk_register_plls(ctx, rk3288_pll_clks,
 				   ARRAY_SIZE(rk3288_pll_clks),
 				   RK3288_GRF_SOC_STATUS1);
-	rockchip_clk_register_branches(rk3288_clk_branches,
+	rockchip_clk_register_branches(ctx, rk3288_clk_branches,
 				  ARRAY_SIZE(rk3288_clk_branches));
 	rockchip_clk_protect_critical(rk3288_critical_clocks,
 				      ARRAY_SIZE(rk3288_critical_clocks));
 
-	rockchip_clk_register_armclk(ARMCLK, "armclk",
+	rockchip_clk_register_armclk(ctx, ARMCLK, "armclk",
 			mux_armclk_p, ARRAY_SIZE(mux_armclk_p),
 			&rk3288_cpuclk_data, rk3288_cpuclk_rates,
 			ARRAY_SIZE(rk3288_cpuclk_rates));
@@ -913,8 +922,10 @@ static void __init rk3288_clk_init(struc
 				  rk3288_cru_base + RK3288_SOFTRST_CON(0),
 				  ROCKCHIP_SOFTRST_HIWORD_MASK);
 
-	rockchip_register_restart_notifier(RK3288_GLB_SRST_FST,
+	rockchip_register_restart_notifier(ctx, RK3288_GLB_SRST_FST,
 					   rk3288_clk_shutdown);
 	register_syscore_ops(&rk3288_clk_syscore_ops);
+
+	rockchip_clk_of_add_provider(np, ctx);
 }
 CLK_OF_DECLARE(rk3288_cru, "rockchip,rk3288-cru", rk3288_clk_init);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/rockchip/clk-rk3368.c linux-libre-4.7-gnu/drivers/clk/rockchip/clk-rk3368.c
--- linux-libre-4.6-gnu/drivers/clk/rockchip/clk-rk3368.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/rockchip/clk-rk3368.c	2016-07-24 15:23:50.000000000 -0400
@@ -165,14 +165,20 @@ static const struct rockchip_cpuclk_reg_
 	.core_reg = RK3368_CLKSEL_CON(0),
 	.div_core_shift = 0,
 	.div_core_mask = 0x1f,
+	.mux_core_alt = 1,
+	.mux_core_main = 0,
 	.mux_core_shift = 7,
+	.mux_core_mask = 0x1,
 };
 
 static const struct rockchip_cpuclk_reg_data rk3368_cpuclkl_data = {
 	.core_reg = RK3368_CLKSEL_CON(2),
 	.div_core_shift = 0,
+	.mux_core_alt = 1,
+	.mux_core_main = 0,
 	.div_core_mask = 0x1f,
 	.mux_core_shift = 7,
+	.mux_core_mask = 0x1,
 };
 
 #define RK3368_DIV_ACLKM_MASK		0x1f
@@ -856,6 +862,7 @@ static const char *const rk3368_critical
 
 static void __init rk3368_clk_init(struct device_node *np)
 {
+	struct rockchip_clk_provider *ctx;
 	void __iomem *reg_base;
 	struct clk *clk;
 
@@ -865,7 +872,12 @@ static void __init rk3368_clk_init(struc
 		return;
 	}
 
-	rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
+	ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
+	if (IS_ERR(ctx)) {
+		pr_err("%s: rockchip clk init failed\n", __func__);
+		iounmap(reg_base);
+		return;
+	}
 
 	/* Watchdog pclk is controlled by sgrf_soc_con3[7]. */
 	clk = clk_register_fixed_factor(NULL, "pclk_wdt", "pclk_pd_alive", 0, 1, 1);
@@ -873,22 +885,22 @@ static void __init rk3368_clk_init(struc
 		pr_warn("%s: could not register clock pclk_wdt: %ld\n",
 			__func__, PTR_ERR(clk));
 	else
-		rockchip_clk_add_lookup(clk, PCLK_WDT);
+		rockchip_clk_add_lookup(ctx, clk, PCLK_WDT);
 
-	rockchip_clk_register_plls(rk3368_pll_clks,
+	rockchip_clk_register_plls(ctx, rk3368_pll_clks,
 				   ARRAY_SIZE(rk3368_pll_clks),
 				   RK3368_GRF_SOC_STATUS0);
-	rockchip_clk_register_branches(rk3368_clk_branches,
+	rockchip_clk_register_branches(ctx, rk3368_clk_branches,
 				  ARRAY_SIZE(rk3368_clk_branches));
 	rockchip_clk_protect_critical(rk3368_critical_clocks,
 				      ARRAY_SIZE(rk3368_critical_clocks));
 
-	rockchip_clk_register_armclk(ARMCLKB, "armclkb",
+	rockchip_clk_register_armclk(ctx, ARMCLKB, "armclkb",
 			mux_armclkb_p, ARRAY_SIZE(mux_armclkb_p),
 			&rk3368_cpuclkb_data, rk3368_cpuclkb_rates,
 			ARRAY_SIZE(rk3368_cpuclkb_rates));
 
-	rockchip_clk_register_armclk(ARMCLKL, "armclkl",
+	rockchip_clk_register_armclk(ctx, ARMCLKL, "armclkl",
 			mux_armclkl_p, ARRAY_SIZE(mux_armclkl_p),
 			&rk3368_cpuclkl_data, rk3368_cpuclkl_rates,
 			ARRAY_SIZE(rk3368_cpuclkl_rates));
@@ -896,6 +908,8 @@ static void __init rk3368_clk_init(struc
 	rockchip_register_softrst(np, 15, reg_base + RK3368_SOFTRST_CON(0),
 				  ROCKCHIP_SOFTRST_HIWORD_MASK);
 
-	rockchip_register_restart_notifier(RK3368_GLB_SRST_FST, NULL);
+	rockchip_register_restart_notifier(ctx, RK3368_GLB_SRST_FST, NULL);
+
+	rockchip_clk_of_add_provider(np, ctx);
 }
 CLK_OF_DECLARE(rk3368_cru, "rockchip,rk3368-cru", rk3368_clk_init);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/rockchip/clk-rk3399.c linux-libre-4.7-gnu/drivers/clk/rockchip/clk-rk3399.c
--- linux-libre-4.6-gnu/drivers/clk/rockchip/clk-rk3399.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/clk/rockchip/clk-rk3399.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,1577 @@
+/*
+ * Copyright (c) 2016 Rockchip Electronics Co. Ltd.
+ * Author: Xing Zheng <zhengxing@rock-chips.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <dt-bindings/clock/rk3399-cru.h>
+#include "clk.h"
+
+enum rk3399_plls {
+	lpll, bpll, dpll, cpll, gpll, npll, vpll,
+};
+
+enum rk3399_pmu_plls {
+	ppll,
+};
+
+static struct rockchip_pll_rate_table rk3399_pll_rates[] = {
+	/* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
+	RK3036_PLL_RATE(2208000000, 1, 92, 1, 1, 1, 0),
+	RK3036_PLL_RATE(2184000000, 1, 91, 1, 1, 1, 0),
+	RK3036_PLL_RATE(2160000000, 1, 90, 1, 1, 1, 0),
+	RK3036_PLL_RATE(2136000000, 1, 89, 1, 1, 1, 0),
+	RK3036_PLL_RATE(2112000000, 1, 88, 1, 1, 1, 0),
+	RK3036_PLL_RATE(2088000000, 1, 87, 1, 1, 1, 0),
+	RK3036_PLL_RATE(2064000000, 1, 86, 1, 1, 1, 0),
+	RK3036_PLL_RATE(2040000000, 1, 85, 1, 1, 1, 0),
+	RK3036_PLL_RATE(2016000000, 1, 84, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1992000000, 1, 83, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1968000000, 1, 82, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1944000000, 1, 81, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1920000000, 1, 80, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1896000000, 1, 79, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1872000000, 1, 78, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1848000000, 1, 77, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1824000000, 1, 76, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1800000000, 1, 75, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1776000000, 1, 74, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1752000000, 1, 73, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1728000000, 1, 72, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1704000000, 1, 71, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1680000000, 1, 70, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1656000000, 1, 69, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1632000000, 1, 68, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1584000000, 1, 66, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1560000000, 1, 65, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1536000000, 1, 64, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1512000000, 1, 63, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1488000000, 1, 62, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1464000000, 1, 61, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1440000000, 1, 60, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1416000000, 1, 59, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1392000000, 1, 58, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1368000000, 1, 57, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1344000000, 1, 56, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1320000000, 1, 55, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1296000000, 1, 54, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1272000000, 1, 53, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1248000000, 1, 52, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1188000000, 2, 99, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1104000000, 1, 46, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
+	RK3036_PLL_RATE(1000000000, 6, 500, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 984000000, 1, 82, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 960000000, 1, 80, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 936000000, 1, 78, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 912000000, 1, 76, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 900000000, 4, 300, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 888000000, 1, 74, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 864000000, 1, 72, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 840000000, 1, 70, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 816000000, 1, 68, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 800000000, 6, 400, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 700000000, 6, 350, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 696000000, 1, 58, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 676000000, 3, 169, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 600000000, 1, 75, 3, 1, 1, 0),
+	RK3036_PLL_RATE( 594000000, 1, 99, 4, 1, 1, 0),
+	RK3036_PLL_RATE( 504000000, 1, 63, 3, 1, 1, 0),
+	RK3036_PLL_RATE( 500000000, 6, 250, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 408000000, 1, 68, 2, 2, 1, 0),
+	RK3036_PLL_RATE( 312000000, 1, 52, 2, 2, 1, 0),
+	RK3036_PLL_RATE( 297000000, 1, 99, 4, 2, 1, 0),
+	RK3036_PLL_RATE( 216000000, 1, 72, 4, 2, 1, 0),
+	RK3036_PLL_RATE( 148500000, 1, 99, 4, 4, 1, 0),
+	RK3036_PLL_RATE(  96000000, 1, 64, 4, 4, 1, 0),
+	RK3036_PLL_RATE(  74250000, 2, 99, 4, 4, 1, 0),
+	RK3036_PLL_RATE(  54000000, 1, 54, 6, 4, 1, 0),
+	RK3036_PLL_RATE(  27000000, 1, 27, 6, 4, 1, 0),
+	{ /* sentinel */ },
+};
+
+/* CRU parents */
+PNAME(mux_pll_p)				= { "xin24m", "xin32k" };
+
+PNAME(mux_armclkl_p)				= { "clk_core_l_lpll_src",
+						    "clk_core_l_bpll_src",
+						    "clk_core_l_dpll_src",
+						    "clk_core_l_gpll_src" };
+PNAME(mux_armclkb_p)				= { "clk_core_b_lpll_src",
+						    "clk_core_b_bpll_src",
+						    "clk_core_b_dpll_src",
+						    "clk_core_b_gpll_src" };
+PNAME(mux_aclk_cci_p)				= { "cpll_aclk_cci_src",
+						    "gpll_aclk_cci_src",
+						    "npll_aclk_cci_src",
+						    "vpll_aclk_cci_src" };
+PNAME(mux_cci_trace_p)				= { "cpll_cci_trace",
+						    "gpll_cci_trace" };
+PNAME(mux_cs_p)					= { "cpll_cs", "gpll_cs",
+						    "npll_cs"};
+PNAME(mux_aclk_perihp_p)			= { "cpll_aclk_perihp_src",
+						    "gpll_aclk_perihp_src" };
+
+PNAME(mux_pll_src_cpll_gpll_p)			= { "cpll", "gpll" };
+PNAME(mux_pll_src_cpll_gpll_npll_p)		= { "cpll", "gpll", "npll" };
+PNAME(mux_pll_src_cpll_gpll_ppll_p)		= { "cpll", "gpll", "ppll" };
+PNAME(mux_pll_src_cpll_gpll_upll_p)		= { "cpll", "gpll", "upll" };
+PNAME(mux_pll_src_npll_cpll_gpll_p)		= { "npll", "cpll", "gpll" };
+PNAME(mux_pll_src_cpll_gpll_npll_ppll_p)	= { "cpll", "gpll", "npll",
+						    "ppll" };
+PNAME(mux_pll_src_cpll_gpll_npll_24m_p)		= { "cpll", "gpll", "npll",
+						    "xin24m" };
+PNAME(mux_pll_src_cpll_gpll_npll_usbphy480m_p)	= { "cpll", "gpll", "npll",
+						    "clk_usbphy_480m" };
+PNAME(mux_pll_src_ppll_cpll_gpll_npll_p)	= { "ppll", "cpll", "gpll",
+						    "npll", "upll" };
+PNAME(mux_pll_src_cpll_gpll_npll_upll_24m_p)	= { "cpll", "gpll", "npll",
+						    "upll", "xin24m" };
+PNAME(mux_pll_src_cpll_gpll_npll_ppll_upll_24m_p) = { "cpll", "gpll", "npll",
+						    "ppll", "upll", "xin24m" };
+
+PNAME(mux_pll_src_vpll_cpll_gpll_p)		= { "vpll", "cpll", "gpll" };
+PNAME(mux_pll_src_vpll_cpll_gpll_npll_p)	= { "vpll", "cpll", "gpll",
+						    "npll" };
+PNAME(mux_pll_src_vpll_cpll_gpll_24m_p)		= { "vpll", "cpll", "gpll",
+						    "xin24m" };
+
+PNAME(mux_dclk_vop0_p)			= { "dclk_vop0_div",
+					    "dclk_vop0_frac" };
+PNAME(mux_dclk_vop1_p)			= { "dclk_vop1_div",
+					    "dclk_vop1_frac" };
+
+PNAME(mux_clk_cif_p)			= { "clk_cifout_src", "xin24m" };
+
+PNAME(mux_pll_src_24m_usbphy480m_p)	= { "xin24m", "clk_usbphy_480m" };
+PNAME(mux_pll_src_24m_pciephy_p)	= { "xin24m", "clk_pciephy_ref100m" };
+PNAME(mux_pll_src_24m_32k_cpll_gpll_p)	= { "xin24m", "xin32k",
+					    "cpll", "gpll" };
+PNAME(mux_pciecore_cru_phy_p)		= { "clk_pcie_core_cru",
+					    "clk_pcie_core_phy" };
+
+PNAME(mux_aclk_emmc_p)			= { "cpll_aclk_emmc_src",
+					    "gpll_aclk_emmc_src" };
+
+PNAME(mux_aclk_perilp0_p)		= { "cpll_aclk_perilp0_src",
+					    "gpll_aclk_perilp0_src" };
+
+PNAME(mux_fclk_cm0s_p)			= { "cpll_fclk_cm0s_src",
+					    "gpll_fclk_cm0s_src" };
+
+PNAME(mux_hclk_perilp1_p)		= { "cpll_hclk_perilp1_src",
+					    "gpll_hclk_perilp1_src" };
+
+PNAME(mux_clk_testout1_p)		= { "clk_testout1_pll_src", "xin24m" };
+PNAME(mux_clk_testout2_p)		= { "clk_testout2_pll_src", "xin24m" };
+
+PNAME(mux_usbphy_480m_p)		= { "clk_usbphy0_480m_src",
+					    "clk_usbphy1_480m_src" };
+PNAME(mux_aclk_gmac_p)			= { "cpll_aclk_gmac_src",
+					    "gpll_aclk_gmac_src" };
+PNAME(mux_rmii_p)			= { "clk_gmac", "clkin_gmac" };
+PNAME(mux_spdif_p)			= { "clk_spdif_div", "clk_spdif_frac",
+					    "clkin_i2s", "xin12m" };
+PNAME(mux_i2s0_p)			= { "clk_i2s0_div", "clk_i2s0_frac",
+					    "clkin_i2s", "xin12m" };
+PNAME(mux_i2s1_p)			= { "clk_i2s1_div", "clk_i2s1_frac",
+					    "clkin_i2s", "xin12m" };
+PNAME(mux_i2s2_p)			= { "clk_i2s2_div", "clk_i2s2_frac",
+					    "clkin_i2s", "xin12m" };
+PNAME(mux_i2sch_p)			= { "clk_i2s0", "clk_i2s1",
+					    "clk_i2s2" };
+PNAME(mux_i2sout_p)			= { "clk_i2sout_src", "xin12m" };
+
+PNAME(mux_uart0_p)	= { "clk_uart0_div", "clk_uart0_frac", "xin24m" };
+PNAME(mux_uart1_p)	= { "clk_uart1_div", "clk_uart1_frac", "xin24m" };
+PNAME(mux_uart2_p)	= { "clk_uart2_div", "clk_uart2_frac", "xin24m" };
+PNAME(mux_uart3_p)	= { "clk_uart3_div", "clk_uart3_frac", "xin24m" };
+
+/* PMU CRU parents */
+PNAME(mux_ppll_24m_p)		= { "ppll", "xin24m" };
+PNAME(mux_24m_ppll_p)		= { "xin24m", "ppll" };
+PNAME(mux_fclk_cm0s_pmu_ppll_p)	= { "fclk_cm0s_pmu_ppll_src", "xin24m" };
+PNAME(mux_wifi_pmu_p)		= { "clk_wifi_div", "clk_wifi_frac" };
+PNAME(mux_uart4_pmu_p)		= { "clk_uart4_div", "clk_uart4_frac",
+				    "xin24m" };
+PNAME(mux_clk_testout2_2io_p)	= { "clk_testout2", "clk_32k_suspend_pmu" };
+
+static struct rockchip_pll_clock rk3399_pll_clks[] __initdata = {
+	[lpll] = PLL(pll_rk3399, PLL_APLLL, "lpll", mux_pll_p, 0, RK3399_PLL_CON(0),
+		     RK3399_PLL_CON(3), 8, 31, 0, rk3399_pll_rates),
+	[bpll] = PLL(pll_rk3399, PLL_APLLB, "bpll", mux_pll_p, 0, RK3399_PLL_CON(8),
+		     RK3399_PLL_CON(11), 8, 31, 0, rk3399_pll_rates),
+	[dpll] = PLL(pll_rk3399, PLL_DPLL, "dpll", mux_pll_p, 0, RK3399_PLL_CON(16),
+		     RK3399_PLL_CON(19), 8, 31, 0, NULL),
+	[cpll] = PLL(pll_rk3399, PLL_CPLL, "cpll", mux_pll_p, 0, RK3399_PLL_CON(24),
+		     RK3399_PLL_CON(27), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk3399_pll_rates),
+	[gpll] = PLL(pll_rk3399, PLL_GPLL, "gpll", mux_pll_p, 0, RK3399_PLL_CON(32),
+		     RK3399_PLL_CON(35), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk3399_pll_rates),
+	[npll] = PLL(pll_rk3399, PLL_NPLL, "npll",  mux_pll_p, 0, RK3399_PLL_CON(40),
+		     RK3399_PLL_CON(43), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk3399_pll_rates),
+	[vpll] = PLL(pll_rk3399, PLL_VPLL, "vpll",  mux_pll_p, 0, RK3399_PLL_CON(48),
+		     RK3399_PLL_CON(51), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk3399_pll_rates),
+};
+
+static struct rockchip_pll_clock rk3399_pmu_pll_clks[] __initdata = {
+	[ppll] = PLL(pll_rk3399, PLL_PPLL, "ppll",  mux_pll_p, 0, RK3399_PMU_PLL_CON(0),
+		     RK3399_PMU_PLL_CON(3), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk3399_pll_rates),
+};
+
+#define MFLAGS CLK_MUX_HIWORD_MASK
+#define DFLAGS CLK_DIVIDER_HIWORD_MASK
+#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
+#define IFLAGS ROCKCHIP_INVERTER_HIWORD_MASK
+
+static struct rockchip_clk_branch rk3399_spdif_fracmux __initdata =
+	MUX(0, "clk_spdif_mux", mux_spdif_p, CLK_SET_RATE_PARENT,
+			RK3399_CLKSEL_CON(32), 13, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3399_i2s0_fracmux __initdata =
+	MUX(0, "clk_i2s0_mux", mux_i2s0_p, CLK_SET_RATE_PARENT,
+			RK3399_CLKSEL_CON(28), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3399_i2s1_fracmux __initdata =
+	MUX(0, "clk_i2s1_mux", mux_i2s1_p, CLK_SET_RATE_PARENT,
+			RK3399_CLKSEL_CON(29), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3399_i2s2_fracmux __initdata =
+	MUX(0, "clk_i2s2_mux", mux_i2s2_p, CLK_SET_RATE_PARENT,
+			RK3399_CLKSEL_CON(30), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3399_uart0_fracmux __initdata =
+	MUX(SCLK_UART0, "clk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT,
+			RK3399_CLKSEL_CON(33), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3399_uart1_fracmux __initdata =
+	MUX(SCLK_UART1, "clk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT,
+			RK3399_CLKSEL_CON(34), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3399_uart2_fracmux __initdata =
+	MUX(SCLK_UART2, "clk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT,
+			RK3399_CLKSEL_CON(35), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3399_uart3_fracmux __initdata =
+	MUX(SCLK_UART3, "clk_uart3", mux_uart3_p, CLK_SET_RATE_PARENT,
+			RK3399_CLKSEL_CON(36), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3399_uart4_pmu_fracmux __initdata =
+	MUX(SCLK_UART4_PMU, "clk_uart4_pmu", mux_uart4_pmu_p, CLK_SET_RATE_PARENT,
+			RK3399_PMU_CLKSEL_CON(5), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3399_dclk_vop0_fracmux __initdata =
+	MUX(DCLK_VOP0, "dclk_vop0", mux_dclk_vop0_p, CLK_SET_RATE_PARENT,
+			RK3399_CLKSEL_CON(49), 11, 1, MFLAGS);
+
+static struct rockchip_clk_branch rk3399_dclk_vop1_fracmux __initdata =
+	MUX(DCLK_VOP1, "dclk_vop1", mux_dclk_vop1_p, CLK_SET_RATE_PARENT,
+			RK3399_CLKSEL_CON(50), 11, 1, MFLAGS);
+
+static struct rockchip_clk_branch rk3399_pmuclk_wifi_fracmux __initdata =
+	MUX(SCLK_WIFI_PMU, "clk_wifi_pmu", mux_wifi_pmu_p, CLK_SET_RATE_PARENT,
+			RK3399_PMU_CLKSEL_CON(1), 14, 1, MFLAGS);
+
+static const struct rockchip_cpuclk_reg_data rk3399_cpuclkl_data = {
+	.core_reg = RK3399_CLKSEL_CON(0),
+	.div_core_shift = 0,
+	.div_core_mask = 0x1f,
+	.mux_core_alt = 3,
+	.mux_core_main = 0,
+	.mux_core_shift = 6,
+	.mux_core_mask = 0x3,
+};
+
+static const struct rockchip_cpuclk_reg_data rk3399_cpuclkb_data = {
+	.core_reg = RK3399_CLKSEL_CON(2),
+	.div_core_shift = 0,
+	.div_core_mask = 0x1f,
+	.mux_core_alt = 3,
+	.mux_core_main = 1,
+	.mux_core_shift = 6,
+	.mux_core_mask = 0x3,
+};
+
+#define RK3399_DIV_ACLKM_MASK		0x1f
+#define RK3399_DIV_ACLKM_SHIFT		8
+#define RK3399_DIV_ATCLK_MASK		0x1f
+#define RK3399_DIV_ATCLK_SHIFT		0
+#define RK3399_DIV_PCLK_DBG_MASK	0x1f
+#define RK3399_DIV_PCLK_DBG_SHIFT	8
+
+#define RK3399_CLKSEL0(_offs, _aclkm)					\
+	{								\
+		.reg = RK3399_CLKSEL_CON(0 + _offs),			\
+		.val = HIWORD_UPDATE(_aclkm, RK3399_DIV_ACLKM_MASK,	\
+				RK3399_DIV_ACLKM_SHIFT),		\
+	}
+#define RK3399_CLKSEL1(_offs, _atclk, _pdbg)				\
+	{								\
+		.reg = RK3399_CLKSEL_CON(1 + _offs),			\
+		.val = HIWORD_UPDATE(_atclk, RK3399_DIV_ATCLK_MASK,	\
+				RK3399_DIV_ATCLK_SHIFT) |		\
+		       HIWORD_UPDATE(_pdbg, RK3399_DIV_PCLK_DBG_MASK,	\
+				RK3399_DIV_PCLK_DBG_SHIFT),		\
+	}
+
+/* cluster_l: aclkm in clksel0, rest in clksel1 */
+#define RK3399_CPUCLKL_RATE(_prate, _aclkm, _atclk, _pdbg)		\
+	{								\
+		.prate = _prate##U,					\
+		.divs = {						\
+			RK3399_CLKSEL0(0, _aclkm),			\
+			RK3399_CLKSEL1(0, _atclk, _pdbg),		\
+		},							\
+	}
+
+/* cluster_b: aclkm in clksel2, rest in clksel3 */
+#define RK3399_CPUCLKB_RATE(_prate, _aclkm, _atclk, _pdbg)		\
+	{								\
+		.prate = _prate##U,					\
+		.divs = {						\
+			RK3399_CLKSEL0(2, _aclkm),			\
+			RK3399_CLKSEL1(2, _atclk, _pdbg),		\
+		},							\
+	}
+
+static struct rockchip_cpuclk_rate_table rk3399_cpuclkl_rates[] __initdata = {
+	RK3399_CPUCLKL_RATE(1800000000, 1, 8, 8),
+	RK3399_CPUCLKL_RATE(1704000000, 1, 8, 8),
+	RK3399_CPUCLKL_RATE(1608000000, 1, 7, 7),
+	RK3399_CPUCLKL_RATE(1512000000, 1, 7, 7),
+	RK3399_CPUCLKL_RATE(1488000000, 1, 6, 6),
+	RK3399_CPUCLKL_RATE(1416000000, 1, 6, 6),
+	RK3399_CPUCLKL_RATE(1200000000, 1, 5, 5),
+	RK3399_CPUCLKL_RATE(1008000000, 1, 5, 5),
+	RK3399_CPUCLKL_RATE( 816000000, 1, 4, 4),
+	RK3399_CPUCLKL_RATE( 696000000, 1, 3, 3),
+	RK3399_CPUCLKL_RATE( 600000000, 1, 3, 3),
+	RK3399_CPUCLKL_RATE( 408000000, 1, 2, 2),
+	RK3399_CPUCLKL_RATE( 312000000, 1, 1, 1),
+	RK3399_CPUCLKL_RATE( 216000000, 1, 1, 1),
+	RK3399_CPUCLKL_RATE(  96000000, 1, 1, 1),
+};
+
+static struct rockchip_cpuclk_rate_table rk3399_cpuclkb_rates[] __initdata = {
+	RK3399_CPUCLKB_RATE(2208000000, 1, 11, 11),
+	RK3399_CPUCLKB_RATE(2184000000, 1, 11, 11),
+	RK3399_CPUCLKB_RATE(2088000000, 1, 10, 10),
+	RK3399_CPUCLKB_RATE(2040000000, 1, 10, 10),
+	RK3399_CPUCLKB_RATE(1992000000, 1, 9, 9),
+	RK3399_CPUCLKB_RATE(1896000000, 1, 9, 9),
+	RK3399_CPUCLKB_RATE(1800000000, 1, 8, 8),
+	RK3399_CPUCLKB_RATE(1704000000, 1, 8, 8),
+	RK3399_CPUCLKB_RATE(1608000000, 1, 7, 7),
+	RK3399_CPUCLKB_RATE(1512000000, 1, 7, 7),
+	RK3399_CPUCLKB_RATE(1488000000, 1, 6, 6),
+	RK3399_CPUCLKB_RATE(1416000000, 1, 6, 6),
+	RK3399_CPUCLKB_RATE(1200000000, 1, 5, 5),
+	RK3399_CPUCLKB_RATE(1008000000, 1, 5, 5),
+	RK3399_CPUCLKB_RATE( 816000000, 1, 4, 4),
+	RK3399_CPUCLKB_RATE( 696000000, 1, 3, 3),
+	RK3399_CPUCLKB_RATE( 600000000, 1, 3, 3),
+	RK3399_CPUCLKB_RATE( 408000000, 1, 2, 2),
+	RK3399_CPUCLKB_RATE( 312000000, 1, 1, 1),
+	RK3399_CPUCLKB_RATE( 216000000, 1, 1, 1),
+	RK3399_CPUCLKB_RATE(  96000000, 1, 1, 1),
+};
+
+static struct rockchip_clk_branch rk3399_clk_branches[] __initdata = {
+	/*
+	 * CRU Clock-Architecture
+	 */
+
+	/* usbphy */
+	GATE(SCLK_USB2PHY0_REF, "clk_usb2phy0_ref", "xin24m", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(6), 5, GFLAGS),
+	GATE(SCLK_USB2PHY1_REF, "clk_usb2phy1_ref", "xin24m", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(6), 6, GFLAGS),
+
+	GATE(0, "clk_usbphy0_480m_src", "clk_usbphy0_480m", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(13), 12, GFLAGS),
+	GATE(0, "clk_usbphy1_480m_src", "clk_usbphy1_480m", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(13), 12, GFLAGS),
+	MUX(0, "clk_usbphy_480m", mux_usbphy_480m_p, CLK_IGNORE_UNUSED,
+			RK3399_CLKSEL_CON(14), 6, 1, MFLAGS),
+
+	MUX(0, "upll", mux_pll_src_24m_usbphy480m_p, 0,
+			RK3399_CLKSEL_CON(14), 15, 1, MFLAGS),
+
+	COMPOSITE_NODIV(SCLK_HSICPHY, "clk_hsicphy", mux_pll_src_cpll_gpll_npll_usbphy480m_p, 0,
+			RK3399_CLKSEL_CON(19), 0, 2, MFLAGS,
+			RK3399_CLKGATE_CON(6), 4, GFLAGS),
+
+	COMPOSITE(ACLK_USB3, "aclk_usb3", mux_pll_src_cpll_gpll_npll_p, 0,
+			RK3399_CLKSEL_CON(39), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3399_CLKGATE_CON(12), 0, GFLAGS),
+	GATE(ACLK_USB3_NOC, "aclk_usb3_noc", "aclk_usb3", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(30), 0, GFLAGS),
+	GATE(ACLK_USB3OTG0, "aclk_usb3otg0", "aclk_usb3", 0,
+			RK3399_CLKGATE_CON(30), 1, GFLAGS),
+	GATE(ACLK_USB3OTG1, "aclk_usb3otg1", "aclk_usb3", 0,
+			RK3399_CLKGATE_CON(30), 2, GFLAGS),
+	GATE(ACLK_USB3_RKSOC_AXI_PERF, "aclk_usb3_rksoc_axi_perf", "aclk_usb3", 0,
+			RK3399_CLKGATE_CON(30), 3, GFLAGS),
+	GATE(ACLK_USB3_GRF, "aclk_usb3_grf", "aclk_usb3", 0,
+			RK3399_CLKGATE_CON(30), 4, GFLAGS),
+
+	GATE(SCLK_USB3OTG0_REF, "clk_usb3otg0_ref", "xin24m", 0,
+			RK3399_CLKGATE_CON(12), 1, GFLAGS),
+	GATE(SCLK_USB3OTG1_REF, "clk_usb3otg1_ref", "xin24m", 0,
+			RK3399_CLKGATE_CON(12), 2, GFLAGS),
+
+	COMPOSITE(SCLK_USB3OTG0_SUSPEND, "clk_usb3otg0_suspend", mux_pll_p, 0,
+			RK3399_CLKSEL_CON(40), 15, 1, MFLAGS, 0, 10, DFLAGS,
+			RK3399_CLKGATE_CON(12), 3, GFLAGS),
+
+	COMPOSITE(SCLK_USB3OTG1_SUSPEND, "clk_usb3otg1_suspend", mux_pll_p, 0,
+			RK3399_CLKSEL_CON(41), 15, 1, MFLAGS, 0, 10, DFLAGS,
+			RK3399_CLKGATE_CON(12), 4, GFLAGS),
+
+	COMPOSITE(SCLK_UPHY0_TCPDPHY_REF, "clk_uphy0_tcpdphy_ref", mux_pll_p, 0,
+			RK3399_CLKSEL_CON(64), 15, 1, MFLAGS, 8, 5, DFLAGS,
+			RK3399_CLKGATE_CON(13), 4, GFLAGS),
+
+	COMPOSITE(SCLK_UPHY0_TCPDCORE, "clk_uphy0_tcpdcore", mux_pll_src_24m_32k_cpll_gpll_p, 0,
+			RK3399_CLKSEL_CON(64), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3399_CLKGATE_CON(13), 5, GFLAGS),
+
+	COMPOSITE(SCLK_UPHY1_TCPDPHY_REF, "clk_uphy1_tcpdphy_ref", mux_pll_p, 0,
+			RK3399_CLKSEL_CON(65), 15, 1, MFLAGS, 8, 5, DFLAGS,
+			RK3399_CLKGATE_CON(13), 6, GFLAGS),
+
+	COMPOSITE(SCLK_UPHY1_TCPDCORE, "clk_uphy1_tcpdcore", mux_pll_src_24m_32k_cpll_gpll_p, 0,
+			RK3399_CLKSEL_CON(65), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3399_CLKGATE_CON(13), 7, GFLAGS),
+
+	/* little core */
+	GATE(0, "clk_core_l_lpll_src", "lpll", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(0), 0, GFLAGS),
+	GATE(0, "clk_core_l_bpll_src", "bpll", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(0), 1, GFLAGS),
+	GATE(0, "clk_core_l_dpll_src", "dpll", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(0), 2, GFLAGS),
+	GATE(0, "clk_core_l_gpll_src", "gpll", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(0), 3, GFLAGS),
+
+	COMPOSITE_NOMUX(0, "aclkm_core_l", "armclkl", CLK_IGNORE_UNUSED,
+			RK3399_CLKSEL_CON(0), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+			RK3399_CLKGATE_CON(0), 4, GFLAGS),
+	COMPOSITE_NOMUX(0, "atclk_core_l", "armclkl", CLK_IGNORE_UNUSED,
+			RK3399_CLKSEL_CON(1), 0, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+			RK3399_CLKGATE_CON(0), 5, GFLAGS),
+	COMPOSITE_NOMUX(0, "pclk_dbg_core_l", "armclkl", CLK_IGNORE_UNUSED,
+			RK3399_CLKSEL_CON(1), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+			RK3399_CLKGATE_CON(0), 6, GFLAGS),
+
+	GATE(ACLK_CORE_ADB400_CORE_L_2_CCI500, "aclk_core_adb400_core_l_2_cci500", "aclkm_core_l", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(14), 12, GFLAGS),
+	GATE(ACLK_PERF_CORE_L, "aclk_perf_core_l", "aclkm_core_l", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(14), 13, GFLAGS),
+
+	GATE(0, "clk_dbg_pd_core_l", "armclkl", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(14), 9, GFLAGS),
+	GATE(ACLK_GIC_ADB400_GIC_2_CORE_L, "aclk_core_adb400_gic_2_core_l", "armclkl", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(14), 10, GFLAGS),
+	GATE(ACLK_GIC_ADB400_CORE_L_2_GIC, "aclk_core_adb400_core_l_2_gic", "armclkl", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(14), 11, GFLAGS),
+	GATE(SCLK_PVTM_CORE_L, "clk_pvtm_core_l", "xin24m", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(0), 7, GFLAGS),
+
+	/* big core */
+	GATE(0, "clk_core_b_lpll_src", "lpll", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(1), 0, GFLAGS),
+	GATE(0, "clk_core_b_bpll_src", "bpll", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(1), 1, GFLAGS),
+	GATE(0, "clk_core_b_dpll_src", "dpll", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(1), 2, GFLAGS),
+	GATE(0, "clk_core_b_gpll_src", "gpll", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(1), 3, GFLAGS),
+
+	COMPOSITE_NOMUX(0, "aclkm_core_b", "armclkb", CLK_IGNORE_UNUSED,
+			RK3399_CLKSEL_CON(2), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+			RK3399_CLKGATE_CON(1), 4, GFLAGS),
+	COMPOSITE_NOMUX(0, "atclk_core_b", "armclkb", CLK_IGNORE_UNUSED,
+			RK3399_CLKSEL_CON(3), 0, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+			RK3399_CLKGATE_CON(1), 5, GFLAGS),
+	COMPOSITE_NOMUX(0, "pclk_dbg_core_b", "armclkb", CLK_IGNORE_UNUSED,
+			RK3399_CLKSEL_CON(3), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+			RK3399_CLKGATE_CON(1), 6, GFLAGS),
+
+	GATE(ACLK_CORE_ADB400_CORE_B_2_CCI500, "aclk_core_adb400_core_b_2_cci500", "aclkm_core_b", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(14), 5, GFLAGS),
+	GATE(ACLK_PERF_CORE_B, "aclk_perf_core_b", "aclkm_core_b", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(14), 6, GFLAGS),
+
+	GATE(0, "clk_dbg_pd_core_b", "armclkb", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(14), 1, GFLAGS),
+	GATE(ACLK_GIC_ADB400_GIC_2_CORE_B, "aclk_core_adb400_gic_2_core_b", "armclkb", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(14), 3, GFLAGS),
+	GATE(ACLK_GIC_ADB400_CORE_B_2_GIC, "aclk_core_adb400_core_b_2_gic", "armclkb", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(14), 4, GFLAGS),
+
+	DIV(0, "pclken_dbg_core_b", "pclk_dbg_core_b", CLK_IGNORE_UNUSED,
+			RK3399_CLKSEL_CON(3), 13, 2, DFLAGS | CLK_DIVIDER_READ_ONLY),
+
+	GATE(0, "pclk_dbg_cxcs_pd_core_b", "pclk_dbg_core_b", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(14), 2, GFLAGS),
+
+	GATE(SCLK_PVTM_CORE_B, "clk_pvtm_core_b", "xin24m", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(1), 7, GFLAGS),
+
+	/* gmac */
+	GATE(0, "cpll_aclk_gmac_src", "cpll", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(6), 9, GFLAGS),
+	GATE(0, "gpll_aclk_gmac_src", "gpll", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(6), 8, GFLAGS),
+	COMPOSITE(0, "aclk_gmac_pre", mux_aclk_gmac_p, 0,
+			RK3399_CLKSEL_CON(20), 7, 1, MFLAGS, 0, 5, DFLAGS,
+			RK3399_CLKGATE_CON(6), 10, GFLAGS),
+
+	GATE(ACLK_GMAC, "aclk_gmac", "aclk_gmac_pre", 0,
+			RK3399_CLKGATE_CON(32), 0, GFLAGS),
+	GATE(ACLK_GMAC_NOC, "aclk_gmac_noc", "aclk_gmac_pre", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(32), 1, GFLAGS),
+	GATE(ACLK_PERF_GMAC, "aclk_perf_gmac", "aclk_gmac_pre", 0,
+			RK3399_CLKGATE_CON(32), 4, GFLAGS),
+
+	COMPOSITE_NOMUX(0, "pclk_gmac_pre", "aclk_gmac_pre", 0,
+			RK3399_CLKSEL_CON(19), 8, 3, DFLAGS,
+			RK3399_CLKGATE_CON(6), 11, GFLAGS),
+	GATE(PCLK_GMAC, "pclk_gmac", "pclk_gmac_pre", 0,
+			RK3399_CLKGATE_CON(32), 2, GFLAGS),
+	GATE(PCLK_GMAC_NOC, "pclk_gmac_noc", "pclk_gmac_pre", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(32), 3, GFLAGS),
+
+	COMPOSITE(SCLK_MAC, "clk_gmac", mux_pll_src_cpll_gpll_npll_p, 0,
+			RK3399_CLKSEL_CON(20), 14, 2, MFLAGS, 8, 5, DFLAGS,
+			RK3399_CLKGATE_CON(5), 5, GFLAGS),
+
+	MUX(SCLK_RMII_SRC, "clk_rmii_src", mux_rmii_p, CLK_SET_RATE_PARENT,
+			RK3399_CLKSEL_CON(19), 4, 1, MFLAGS),
+	GATE(SCLK_MACREF_OUT, "clk_mac_refout", "clk_rmii_src", 0,
+			RK3399_CLKGATE_CON(5), 6, GFLAGS),
+	GATE(SCLK_MACREF, "clk_mac_ref", "clk_rmii_src", 0,
+			RK3399_CLKGATE_CON(5), 7, GFLAGS),
+	GATE(SCLK_MAC_RX, "clk_rmii_rx", "clk_rmii_src", 0,
+			RK3399_CLKGATE_CON(5), 8, GFLAGS),
+	GATE(SCLK_MAC_TX, "clk_rmii_tx", "clk_rmii_src", 0,
+			RK3399_CLKGATE_CON(5), 9, GFLAGS),
+
+	/* spdif */
+	COMPOSITE(0, "clk_spdif_div", mux_pll_src_cpll_gpll_p, 0,
+			RK3399_CLKSEL_CON(32), 7, 1, MFLAGS, 0, 7, DFLAGS,
+			RK3399_CLKGATE_CON(8), 13, GFLAGS),
+	COMPOSITE_FRACMUX(0, "clk_spdif_frac", "clk_spdif_div", CLK_SET_RATE_PARENT,
+			RK3399_CLKSEL_CON(99), 0,
+			RK3399_CLKGATE_CON(8), 14, GFLAGS,
+			&rk3399_spdif_fracmux),
+	GATE(SCLK_SPDIF_8CH, "clk_spdif", "clk_spdif_mux", CLK_SET_RATE_PARENT,
+			RK3399_CLKGATE_CON(8), 15, GFLAGS),
+
+	COMPOSITE(SCLK_SPDIF_REC_DPTX, "clk_spdif_rec_dptx", mux_pll_src_cpll_gpll_p, 0,
+			RK3399_CLKSEL_CON(32), 15, 1, MFLAGS, 0, 5, DFLAGS,
+			RK3399_CLKGATE_CON(10), 6, GFLAGS),
+	/* i2s */
+	COMPOSITE(0, "clk_i2s0_div", mux_pll_src_cpll_gpll_p, 0,
+			RK3399_CLKSEL_CON(28), 7, 1, MFLAGS, 0, 7, DFLAGS,
+			RK3399_CLKGATE_CON(8), 3, GFLAGS),
+	COMPOSITE_FRACMUX(0, "clk_i2s0_frac", "clk_i2s0_div", CLK_SET_RATE_PARENT,
+			RK3399_CLKSEL_CON(96), 0,
+			RK3399_CLKGATE_CON(8), 4, GFLAGS,
+			&rk3399_i2s0_fracmux),
+	GATE(SCLK_I2S0_8CH, "clk_i2s0", "clk_i2s0_mux", CLK_SET_RATE_PARENT,
+			RK3399_CLKGATE_CON(8), 5, GFLAGS),
+
+	COMPOSITE(0, "clk_i2s1_div", mux_pll_src_cpll_gpll_p, 0,
+			RK3399_CLKSEL_CON(29), 7, 1, MFLAGS, 0, 7, DFLAGS,
+			RK3399_CLKGATE_CON(8), 6, GFLAGS),
+	COMPOSITE_FRACMUX(0, "clk_i2s1_frac", "clk_i2s1_div", CLK_SET_RATE_PARENT,
+			RK3399_CLKSEL_CON(97), 0,
+			RK3399_CLKGATE_CON(8), 7, GFLAGS,
+			&rk3399_i2s1_fracmux),
+	GATE(SCLK_I2S1_8CH, "clk_i2s1", "clk_i2s1_mux", CLK_SET_RATE_PARENT,
+			RK3399_CLKGATE_CON(8), 8, GFLAGS),
+
+	COMPOSITE(0, "clk_i2s2_div", mux_pll_src_cpll_gpll_p, 0,
+			RK3399_CLKSEL_CON(30), 7, 1, MFLAGS, 0, 7, DFLAGS,
+			RK3399_CLKGATE_CON(8), 9, GFLAGS),
+	COMPOSITE_FRACMUX(0, "clk_i2s2_frac", "clk_i2s2_div", CLK_SET_RATE_PARENT,
+			RK3399_CLKSEL_CON(98), 0,
+			RK3399_CLKGATE_CON(8), 10, GFLAGS,
+			&rk3399_i2s2_fracmux),
+	GATE(SCLK_I2S2_8CH, "clk_i2s2", "clk_i2s2_mux", CLK_SET_RATE_PARENT,
+			RK3399_CLKGATE_CON(8), 11, GFLAGS),
+
+	MUX(0, "clk_i2sout_src", mux_i2sch_p, CLK_SET_RATE_PARENT,
+			RK3399_CLKSEL_CON(31), 0, 2, MFLAGS),
+	COMPOSITE_NODIV(SCLK_I2S_8CH_OUT, "clk_i2sout", mux_i2sout_p, CLK_SET_RATE_PARENT,
+			RK3399_CLKSEL_CON(30), 8, 2, MFLAGS,
+			RK3399_CLKGATE_CON(8), 12, GFLAGS),
+
+	/* uart */
+	MUX(0, "clk_uart0_src", mux_pll_src_cpll_gpll_upll_p, 0,
+			RK3399_CLKSEL_CON(33), 12, 2, MFLAGS),
+	COMPOSITE_NOMUX(0, "clk_uart0_div", "clk_uart0_src", 0,
+			RK3399_CLKSEL_CON(33), 0, 7, DFLAGS,
+			RK3399_CLKGATE_CON(9), 0, GFLAGS),
+	COMPOSITE_FRACMUX(0, "clk_uart0_frac", "clk_uart0_div", CLK_SET_RATE_PARENT,
+			RK3399_CLKSEL_CON(100), 0,
+			RK3399_CLKGATE_CON(9), 1, GFLAGS,
+			&rk3399_uart0_fracmux),
+
+	MUX(0, "clk_uart_src", mux_pll_src_cpll_gpll_p, 0,
+			RK3399_CLKSEL_CON(33), 15, 1, MFLAGS),
+	COMPOSITE_NOMUX(0, "clk_uart1_div", "clk_uart_src", 0,
+			RK3399_CLKSEL_CON(34), 0, 7, DFLAGS,
+			RK3399_CLKGATE_CON(9), 2, GFLAGS),
+	COMPOSITE_FRACMUX(0, "clk_uart1_frac", "clk_uart1_div", CLK_SET_RATE_PARENT,
+			RK3399_CLKSEL_CON(101), 0,
+			RK3399_CLKGATE_CON(9), 3, GFLAGS,
+			&rk3399_uart1_fracmux),
+
+	COMPOSITE_NOMUX(0, "clk_uart2_div", "clk_uart_src", 0,
+			RK3399_CLKSEL_CON(35), 0, 7, DFLAGS,
+			RK3399_CLKGATE_CON(9), 4, GFLAGS),
+	COMPOSITE_FRACMUX(0, "clk_uart2_frac", "clk_uart2_div", CLK_SET_RATE_PARENT,
+			RK3399_CLKSEL_CON(102), 0,
+			RK3399_CLKGATE_CON(9), 5, GFLAGS,
+			&rk3399_uart2_fracmux),
+
+	COMPOSITE_NOMUX(0, "clk_uart3_div", "clk_uart_src", 0,
+			RK3399_CLKSEL_CON(36), 0, 7, DFLAGS,
+			RK3399_CLKGATE_CON(9), 6, GFLAGS),
+	COMPOSITE_FRACMUX(0, "clk_uart3_frac", "clk_uart3_div", CLK_SET_RATE_PARENT,
+			RK3399_CLKSEL_CON(103), 0,
+			RK3399_CLKGATE_CON(9), 7, GFLAGS,
+			&rk3399_uart3_fracmux),
+
+	COMPOSITE(0, "pclk_ddr", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED,
+			RK3399_CLKSEL_CON(6), 15, 1, MFLAGS, 8, 5, DFLAGS,
+			RK3399_CLKGATE_CON(3), 4, GFLAGS),
+
+	GATE(PCLK_CENTER_MAIN_NOC, "pclk_center_main_noc", "pclk_ddr", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(18), 10, GFLAGS),
+	GATE(PCLK_DDR_MON, "pclk_ddr_mon", "pclk_ddr", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(18), 12, GFLAGS),
+	GATE(PCLK_CIC, "pclk_cic", "pclk_ddr", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(18), 15, GFLAGS),
+	GATE(PCLK_DDR_SGRF, "pclk_ddr_sgrf", "pclk_ddr", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(19), 2, GFLAGS),
+
+	GATE(SCLK_PVTM_DDR, "clk_pvtm_ddr", "xin24m", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(4), 11, GFLAGS),
+	GATE(SCLK_DFIMON0_TIMER, "clk_dfimon0_timer", "xin24m", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(3), 5, GFLAGS),
+	GATE(SCLK_DFIMON1_TIMER, "clk_dfimon1_timer", "xin24m", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(3), 6, GFLAGS),
+
+	/* cci */
+	GATE(0, "cpll_aclk_cci_src", "cpll", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(2), 0, GFLAGS),
+	GATE(0, "gpll_aclk_cci_src", "gpll", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(2), 1, GFLAGS),
+	GATE(0, "npll_aclk_cci_src", "npll", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(2), 2, GFLAGS),
+	GATE(0, "vpll_aclk_cci_src", "vpll", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(2), 3, GFLAGS),
+
+	COMPOSITE(0, "aclk_cci_pre", mux_aclk_cci_p, CLK_IGNORE_UNUSED,
+			RK3399_CLKSEL_CON(5), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3399_CLKGATE_CON(2), 4, GFLAGS),
+
+	GATE(ACLK_ADB400M_PD_CORE_L, "aclk_adb400m_pd_core_l", "aclk_cci_pre", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(15), 0, GFLAGS),
+	GATE(ACLK_ADB400M_PD_CORE_B, "aclk_adb400m_pd_core_b", "aclk_cci_pre", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(15), 1, GFLAGS),
+	GATE(ACLK_CCI, "aclk_cci", "aclk_cci_pre", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(15), 2, GFLAGS),
+	GATE(ACLK_CCI_NOC0, "aclk_cci_noc0", "aclk_cci_pre", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(15), 3, GFLAGS),
+	GATE(ACLK_CCI_NOC1, "aclk_cci_noc1", "aclk_cci_pre", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(15), 4, GFLAGS),
+	GATE(ACLK_CCI_GRF, "aclk_cci_grf", "aclk_cci_pre", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(15), 7, GFLAGS),
+
+	GATE(0, "cpll_cci_trace", "cpll", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(2), 5, GFLAGS),
+	GATE(0, "gpll_cci_trace", "gpll", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(2), 6, GFLAGS),
+	COMPOSITE(SCLK_CCI_TRACE, "clk_cci_trace", mux_cci_trace_p, CLK_IGNORE_UNUSED,
+			RK3399_CLKSEL_CON(5), 15, 2, MFLAGS, 8, 5, DFLAGS,
+			RK3399_CLKGATE_CON(2), 7, GFLAGS),
+
+	GATE(0, "cpll_cs", "cpll", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(2), 8, GFLAGS),
+	GATE(0, "gpll_cs", "gpll", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(2), 9, GFLAGS),
+	GATE(0, "npll_cs", "npll", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(2), 10, GFLAGS),
+	COMPOSITE_NOGATE(0, "clk_cs", mux_cs_p, CLK_IGNORE_UNUSED,
+			RK3399_CLKSEL_CON(4), 6, 2, MFLAGS, 0, 5, DFLAGS),
+	GATE(0, "clk_dbg_cxcs", "clk_cs", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(15), 5, GFLAGS),
+	GATE(0, "clk_dbg_noc", "clk_cs", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(15), 6, GFLAGS),
+
+	/* vcodec */
+	COMPOSITE(0, "aclk_vcodec_pre", mux_pll_src_cpll_gpll_npll_ppll_p, 0,
+			RK3399_CLKSEL_CON(7), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3399_CLKGATE_CON(4), 0, GFLAGS),
+	COMPOSITE_NOMUX(0, "hclk_vcodec_pre", "aclk_vcodec_pre", 0,
+			RK3399_CLKSEL_CON(7), 8, 5, DFLAGS,
+			RK3399_CLKGATE_CON(4), 1, GFLAGS),
+	GATE(HCLK_VCODEC, "hclk_vcodec", "hclk_vcodec_pre", 0,
+			RK3399_CLKGATE_CON(17), 2, GFLAGS),
+	GATE(0, "hclk_vcodec_noc", "hclk_vcodec_pre", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(17), 3, GFLAGS),
+
+	GATE(ACLK_VCODEC, "aclk_vcodec", "aclk_vcodec_pre", 0,
+			RK3399_CLKGATE_CON(17), 0, GFLAGS),
+	GATE(0, "aclk_vcodec_noc", "aclk_vcodec_pre", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(17), 1, GFLAGS),
+
+	/* vdu */
+	COMPOSITE(SCLK_VDU_CORE, "clk_vdu_core", mux_pll_src_cpll_gpll_npll_p, 0,
+			RK3399_CLKSEL_CON(9), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3399_CLKGATE_CON(4), 4, GFLAGS),
+	COMPOSITE(SCLK_VDU_CA, "clk_vdu_ca", mux_pll_src_cpll_gpll_npll_p, 0,
+			RK3399_CLKSEL_CON(9), 14, 2, MFLAGS, 8, 5, DFLAGS,
+			RK3399_CLKGATE_CON(4), 5, GFLAGS),
+
+	COMPOSITE(0, "aclk_vdu_pre", mux_pll_src_cpll_gpll_npll_ppll_p, 0,
+			RK3399_CLKSEL_CON(8), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3399_CLKGATE_CON(4), 2, GFLAGS),
+	COMPOSITE_NOMUX(0, "hclk_vdu_pre", "aclk_vdu_pre", 0,
+			RK3399_CLKSEL_CON(8), 8, 5, DFLAGS,
+			RK3399_CLKGATE_CON(4), 3, GFLAGS),
+	GATE(HCLK_VDU, "hclk_vdu", "hclk_vdu_pre", 0,
+			RK3399_CLKGATE_CON(17), 10, GFLAGS),
+	GATE(HCLK_VDU_NOC, "hclk_vdu_noc", "hclk_vdu_pre", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(17), 11, GFLAGS),
+
+	GATE(ACLK_VDU, "aclk_vdu", "aclk_vdu_pre", 0,
+			RK3399_CLKGATE_CON(17), 8, GFLAGS),
+	GATE(ACLK_VDU_NOC, "aclk_vdu_noc", "aclk_vdu_pre", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(17), 9, GFLAGS),
+
+	/* iep */
+	COMPOSITE(0, "aclk_iep_pre", mux_pll_src_cpll_gpll_npll_ppll_p, 0,
+			RK3399_CLKSEL_CON(10), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3399_CLKGATE_CON(4), 6, GFLAGS),
+	COMPOSITE_NOMUX(0, "hclk_iep_pre", "aclk_iep_pre", 0,
+			RK3399_CLKSEL_CON(10), 8, 5, DFLAGS,
+			RK3399_CLKGATE_CON(4), 7, GFLAGS),
+	GATE(HCLK_IEP, "hclk_iep", "hclk_iep_pre", 0,
+			RK3399_CLKGATE_CON(16), 2, GFLAGS),
+	GATE(HCLK_IEP_NOC, "hclk_iep_noc", "hclk_iep_pre", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(16), 3, GFLAGS),
+
+	GATE(ACLK_IEP, "aclk_iep", "aclk_iep_pre", 0,
+			RK3399_CLKGATE_CON(16), 0, GFLAGS),
+	GATE(ACLK_IEP_NOC, "aclk_iep_noc", "aclk_iep_pre", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(16), 1, GFLAGS),
+
+	/* rga */
+	COMPOSITE(SCLK_RGA_CORE, "clk_rga_core", mux_pll_src_cpll_gpll_npll_ppll_p, 0,
+			RK3399_CLKSEL_CON(12), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3399_CLKGATE_CON(4), 10, GFLAGS),
+
+	COMPOSITE(0, "aclk_rga_pre", mux_pll_src_cpll_gpll_npll_ppll_p, 0,
+			RK3399_CLKSEL_CON(11), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3399_CLKGATE_CON(4), 8, GFLAGS),
+	COMPOSITE_NOMUX(0, "hclk_rga_pre", "aclk_rga_pre", 0,
+			RK3399_CLKSEL_CON(11), 8, 5, DFLAGS,
+			RK3399_CLKGATE_CON(4), 9, GFLAGS),
+	GATE(HCLK_RGA, "hclk_rga", "hclk_rga_pre", 0,
+			RK3399_CLKGATE_CON(16), 10, GFLAGS),
+	GATE(HCLK_RGA_NOC, "hclk_rga_noc", "hclk_rga_pre", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(16), 11, GFLAGS),
+
+	GATE(ACLK_RGA, "aclk_rga", "aclk_rga_pre", 0,
+			RK3399_CLKGATE_CON(16), 8, GFLAGS),
+	GATE(ACLK_RGA_NOC, "aclk_rga_noc", "aclk_rga_pre", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(16), 9, GFLAGS),
+
+	/* center */
+	COMPOSITE(0, "aclk_center", mux_pll_src_cpll_gpll_npll_p, CLK_IGNORE_UNUSED,
+			RK3399_CLKSEL_CON(12), 14, 2, MFLAGS, 8, 5, DFLAGS,
+			RK3399_CLKGATE_CON(3), 7, GFLAGS),
+	GATE(ACLK_CENTER_MAIN_NOC, "aclk_center_main_noc", "aclk_center", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(19), 0, GFLAGS),
+	GATE(ACLK_CENTER_PERI_NOC, "aclk_center_peri_noc", "aclk_center", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(19), 1, GFLAGS),
+
+	/* gpu */
+	COMPOSITE(0, "aclk_gpu_pre", mux_pll_src_ppll_cpll_gpll_npll_p, CLK_IGNORE_UNUSED,
+			RK3399_CLKSEL_CON(13), 5, 3, MFLAGS, 0, 5, DFLAGS,
+			RK3399_CLKGATE_CON(13), 0, GFLAGS),
+	GATE(ACLK_GPU, "aclk_gpu", "aclk_gpu_pre", 0,
+			RK3399_CLKGATE_CON(30), 8, GFLAGS),
+	GATE(ACLK_PERF_GPU, "aclk_perf_gpu", "aclk_gpu_pre", 0,
+			RK3399_CLKGATE_CON(30), 10, GFLAGS),
+	GATE(ACLK_GPU_GRF, "aclk_gpu_grf", "aclk_gpu_pre", 0,
+			RK3399_CLKGATE_CON(30), 11, GFLAGS),
+	GATE(SCLK_PVTM_GPU, "aclk_pvtm_gpu", "xin24m", 0,
+			RK3399_CLKGATE_CON(13), 1, GFLAGS),
+
+	/* perihp */
+	GATE(0, "cpll_aclk_perihp_src", "cpll", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(5), 0, GFLAGS),
+	GATE(0, "gpll_aclk_perihp_src", "gpll", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(5), 1, GFLAGS),
+	COMPOSITE(ACLK_PERIHP, "aclk_perihp", mux_aclk_perihp_p, CLK_IGNORE_UNUSED,
+			RK3399_CLKSEL_CON(14), 7, 1, MFLAGS, 0, 5, DFLAGS,
+			RK3399_CLKGATE_CON(5), 2, GFLAGS),
+	COMPOSITE_NOMUX(HCLK_PERIHP, "hclk_perihp", "aclk_perihp", CLK_IGNORE_UNUSED,
+			RK3399_CLKSEL_CON(14), 8, 2, DFLAGS,
+			RK3399_CLKGATE_CON(5), 3, GFLAGS),
+	COMPOSITE_NOMUX(PCLK_PERIHP, "pclk_perihp", "aclk_perihp", CLK_IGNORE_UNUSED,
+			RK3399_CLKSEL_CON(14), 12, 2, DFLAGS,
+			RK3399_CLKGATE_CON(5), 4, GFLAGS),
+
+	GATE(ACLK_PERF_PCIE, "aclk_perf_pcie", "aclk_perihp", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(20), 2, GFLAGS),
+	GATE(ACLK_PCIE, "aclk_pcie", "aclk_perihp", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(20), 10, GFLAGS),
+	GATE(0, "aclk_perihp_noc", "aclk_perihp", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(20), 12, GFLAGS),
+
+	GATE(HCLK_HOST0, "hclk_host0", "hclk_perihp", 0,
+			RK3399_CLKGATE_CON(20), 5, GFLAGS),
+	GATE(HCLK_HOST0_ARB, "hclk_host0_arb", "hclk_perihp", 0,
+			RK3399_CLKGATE_CON(20), 6, GFLAGS),
+	GATE(HCLK_HOST1, "hclk_host1", "hclk_perihp", 0,
+			RK3399_CLKGATE_CON(20), 7, GFLAGS),
+	GATE(HCLK_HOST1_ARB, "hclk_host1_arb", "hclk_perihp", 0,
+			RK3399_CLKGATE_CON(20), 8, GFLAGS),
+	GATE(HCLK_HSIC, "hclk_hsic", "hclk_perihp", 0,
+			RK3399_CLKGATE_CON(20), 9, GFLAGS),
+	GATE(0, "hclk_perihp_noc", "hclk_perihp", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(20), 13, GFLAGS),
+	GATE(0, "hclk_ahb1tom", "hclk_perihp", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(20), 15, GFLAGS),
+
+	GATE(PCLK_PERIHP_GRF, "pclk_perihp_grf", "pclk_perihp", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(20), 4, GFLAGS),
+	GATE(PCLK_PCIE, "pclk_pcie", "pclk_perihp", 0,
+			RK3399_CLKGATE_CON(20), 11, GFLAGS),
+	GATE(0, "pclk_perihp_noc", "pclk_perihp", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(20), 14, GFLAGS),
+	GATE(PCLK_HSICPHY, "pclk_hsicphy", "pclk_perihp", 0,
+			RK3399_CLKGATE_CON(31), 8, GFLAGS),
+
+	/* sdio & sdmmc */
+	COMPOSITE(0, "hclk_sd", mux_pll_src_cpll_gpll_p, 0,
+			RK3399_CLKSEL_CON(13), 15, 1, MFLAGS, 8, 5, DFLAGS,
+			RK3399_CLKGATE_CON(12), 13, GFLAGS),
+	GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_sd", 0,
+			RK3399_CLKGATE_CON(33), 8, GFLAGS),
+	GATE(0, "hclk_sdmmc_noc", "hclk_sd", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(33), 9, GFLAGS),
+
+	COMPOSITE(SCLK_SDIO, "clk_sdio", mux_pll_src_cpll_gpll_npll_ppll_upll_24m_p, 0,
+			RK3399_CLKSEL_CON(15), 8, 3, MFLAGS, 0, 7, DFLAGS,
+			RK3399_CLKGATE_CON(6), 0, GFLAGS),
+
+	COMPOSITE(SCLK_SDMMC, "clk_sdmmc", mux_pll_src_cpll_gpll_npll_ppll_upll_24m_p, 0,
+			RK3399_CLKSEL_CON(16), 8, 3, MFLAGS, 0, 7, DFLAGS,
+			RK3399_CLKGATE_CON(6), 1, GFLAGS),
+
+	MMC(SCLK_SDMMC_DRV,     "sdmmc_drv",    "clk_sdmmc", RK3399_SDMMC_CON0, 1),
+	MMC(SCLK_SDMMC_SAMPLE,  "sdmmc_sample", "clk_sdmmc", RK3399_SDMMC_CON1, 1),
+
+	MMC(SCLK_SDIO_DRV,      "sdio_drv",    "clk_sdio",  RK3399_SDIO_CON0,  1),
+	MMC(SCLK_SDIO_SAMPLE,   "sdio_sample", "clk_sdio",  RK3399_SDIO_CON1,  1),
+
+	/* pcie */
+	COMPOSITE(SCLK_PCIE_PM, "clk_pcie_pm", mux_pll_src_cpll_gpll_npll_24m_p, 0,
+			RK3399_CLKSEL_CON(17), 8, 3, MFLAGS, 0, 7, DFLAGS,
+			RK3399_CLKGATE_CON(6), 2, GFLAGS),
+
+	COMPOSITE_NOMUX(SCLK_PCIEPHY_REF100M, "clk_pciephy_ref100m", "npll", 0,
+			RK3399_CLKSEL_CON(18), 11, 5, DFLAGS,
+			RK3399_CLKGATE_CON(12), 6, GFLAGS),
+	MUX(SCLK_PCIEPHY_REF, "clk_pciephy_ref", mux_pll_src_24m_pciephy_p, CLK_SET_RATE_PARENT,
+			RK3399_CLKSEL_CON(18), 10, 1, MFLAGS),
+
+	COMPOSITE(0, "clk_pcie_core_cru", mux_pll_src_cpll_gpll_npll_p, 0,
+			RK3399_CLKSEL_CON(18), 8, 2, MFLAGS, 0, 7, DFLAGS,
+			RK3399_CLKGATE_CON(6), 3, GFLAGS),
+	MUX(SCLK_PCIE_CORE, "clk_pcie_core", mux_pciecore_cru_phy_p, CLK_SET_RATE_PARENT,
+			RK3399_CLKSEL_CON(18), 7, 1, MFLAGS),
+
+	/* emmc */
+	COMPOSITE(SCLK_EMMC, "clk_emmc", mux_pll_src_cpll_gpll_npll_upll_24m_p, 0,
+			RK3399_CLKSEL_CON(22), 8, 3, MFLAGS, 0, 7, DFLAGS,
+			RK3399_CLKGATE_CON(6), 14, GFLAGS),
+
+	GATE(0, "cpll_aclk_emmc_src", "cpll", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(6), 12, GFLAGS),
+	GATE(0, "gpll_aclk_emmc_src", "gpll", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(6), 13, GFLAGS),
+	COMPOSITE_NOGATE(ACLK_EMMC, "aclk_emmc", mux_aclk_emmc_p, CLK_IGNORE_UNUSED,
+			RK3399_CLKSEL_CON(21), 7, 1, MFLAGS, 0, 5, DFLAGS),
+	GATE(ACLK_EMMC_CORE, "aclk_emmccore", "aclk_emmc", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(32), 8, GFLAGS),
+	GATE(ACLK_EMMC_NOC, "aclk_emmc_noc", "aclk_emmc", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(32), 9, GFLAGS),
+	GATE(ACLK_EMMC_GRF, "aclk_emmcgrf", "aclk_emmc", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(32), 10, GFLAGS),
+
+	/* perilp0 */
+	GATE(0, "cpll_aclk_perilp0_src", "cpll", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(7), 1, GFLAGS),
+	GATE(0, "gpll_aclk_perilp0_src", "gpll", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(7), 0, GFLAGS),
+	COMPOSITE(ACLK_PERILP0, "aclk_perilp0", mux_aclk_perilp0_p, CLK_IGNORE_UNUSED,
+			RK3399_CLKSEL_CON(23), 7, 1, MFLAGS, 0, 5, DFLAGS,
+			RK3399_CLKGATE_CON(7), 2, GFLAGS),
+	COMPOSITE_NOMUX(HCLK_PERILP0, "hclk_perilp0", "aclk_perilp0", CLK_IGNORE_UNUSED,
+			RK3399_CLKSEL_CON(23), 8, 2, DFLAGS,
+			RK3399_CLKGATE_CON(7), 3, GFLAGS),
+	COMPOSITE_NOMUX(PCLK_PERILP0, "pclk_perilp0", "aclk_perilp0", 0,
+			RK3399_CLKSEL_CON(23), 12, 3, DFLAGS,
+			RK3399_CLKGATE_CON(7), 4, GFLAGS),
+
+	/* aclk_perilp0 gates */
+	GATE(ACLK_INTMEM, "aclk_intmem", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 0, GFLAGS),
+	GATE(ACLK_TZMA, "aclk_tzma", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 1, GFLAGS),
+	GATE(SCLK_INTMEM0, "clk_intmem0", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 2, GFLAGS),
+	GATE(SCLK_INTMEM1, "clk_intmem1", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 3, GFLAGS),
+	GATE(SCLK_INTMEM2, "clk_intmem2", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 4, GFLAGS),
+	GATE(SCLK_INTMEM3, "clk_intmem3", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 5, GFLAGS),
+	GATE(SCLK_INTMEM4, "clk_intmem4", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 6, GFLAGS),
+	GATE(SCLK_INTMEM5, "clk_intmem5", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 7, GFLAGS),
+	GATE(ACLK_DCF, "aclk_dcf", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 8, GFLAGS),
+	GATE(ACLK_DMAC0_PERILP, "aclk_dmac0_perilp", "aclk_perilp0", 0, RK3399_CLKGATE_CON(25), 5, GFLAGS),
+	GATE(ACLK_DMAC1_PERILP, "aclk_dmac1_perilp", "aclk_perilp0", 0, RK3399_CLKGATE_CON(25), 6, GFLAGS),
+	GATE(ACLK_PERILP0_NOC, "aclk_perilp0_noc", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(25), 7, GFLAGS),
+
+	/* hclk_perilp0 gates */
+	GATE(HCLK_ROM, "hclk_rom", "hclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(24), 4, GFLAGS),
+	GATE(HCLK_M_CRYPTO0, "hclk_m_crypto0", "hclk_perilp0", 0, RK3399_CLKGATE_CON(24), 5, GFLAGS),
+	GATE(HCLK_S_CRYPTO0, "hclk_s_crypto0", "hclk_perilp0", 0, RK3399_CLKGATE_CON(24), 6, GFLAGS),
+	GATE(HCLK_M_CRYPTO1, "hclk_m_crypto1", "hclk_perilp0", 0, RK3399_CLKGATE_CON(24), 14, GFLAGS),
+	GATE(HCLK_S_CRYPTO1, "hclk_s_crypto1", "hclk_perilp0", 0, RK3399_CLKGATE_CON(24), 15, GFLAGS),
+	GATE(HCLK_PERILP0_NOC, "hclk_perilp0_noc", "hclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(25), 8, GFLAGS),
+
+	/* pclk_perilp0 gates */
+	GATE(PCLK_DCF, "pclk_dcf", "pclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 9, GFLAGS),
+
+	/* crypto */
+	COMPOSITE(SCLK_CRYPTO0, "clk_crypto0", mux_pll_src_cpll_gpll_ppll_p, 0,
+			RK3399_CLKSEL_CON(24), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3399_CLKGATE_CON(7), 7, GFLAGS),
+
+	COMPOSITE(SCLK_CRYPTO1, "clk_crypto1", mux_pll_src_cpll_gpll_ppll_p, 0,
+			RK3399_CLKSEL_CON(26), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3399_CLKGATE_CON(7), 8, GFLAGS),
+
+	/* cm0s_perilp */
+	GATE(0, "cpll_fclk_cm0s_src", "cpll", 0,
+			RK3399_CLKGATE_CON(7), 6, GFLAGS),
+	GATE(0, "gpll_fclk_cm0s_src", "gpll", 0,
+			RK3399_CLKGATE_CON(7), 5, GFLAGS),
+	COMPOSITE(FCLK_CM0S, "fclk_cm0s", mux_fclk_cm0s_p, 0,
+			RK3399_CLKSEL_CON(24), 15, 1, MFLAGS, 8, 5, DFLAGS,
+			RK3399_CLKGATE_CON(7), 9, GFLAGS),
+
+	/* fclk_cm0s gates */
+	GATE(SCLK_M0_PERILP, "sclk_m0_perilp", "fclk_cm0s", 0, RK3399_CLKGATE_CON(24), 8, GFLAGS),
+	GATE(HCLK_M0_PERILP, "hclk_m0_perilp", "fclk_cm0s", 0, RK3399_CLKGATE_CON(24), 9, GFLAGS),
+	GATE(DCLK_M0_PERILP, "dclk_m0_perilp", "fclk_cm0s", 0, RK3399_CLKGATE_CON(24), 10, GFLAGS),
+	GATE(SCLK_M0_PERILP_DEC, "clk_m0_perilp_dec", "fclk_cm0s", 0, RK3399_CLKGATE_CON(24), 11, GFLAGS),
+	GATE(HCLK_M0_PERILP_NOC, "hclk_m0_perilp_noc", "fclk_cm0s", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(25), 11, GFLAGS),
+
+	/* perilp1 */
+	GATE(0, "cpll_hclk_perilp1_src", "cpll", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(8), 1, GFLAGS),
+	GATE(0, "gpll_hclk_perilp1_src", "gpll", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(8), 0, GFLAGS),
+	COMPOSITE_NOGATE(HCLK_PERILP1, "hclk_perilp1", mux_hclk_perilp1_p, CLK_IGNORE_UNUSED,
+			RK3399_CLKSEL_CON(25), 7, 1, MFLAGS, 0, 5, DFLAGS),
+	COMPOSITE_NOMUX(PCLK_PERILP1, "pclk_perilp1", "hclk_perilp1", CLK_IGNORE_UNUSED,
+			RK3399_CLKSEL_CON(25), 8, 3, DFLAGS,
+			RK3399_CLKGATE_CON(8), 2, GFLAGS),
+
+	/* hclk_perilp1 gates */
+	GATE(0, "hclk_perilp1_noc", "hclk_perilp1", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(25), 9, GFLAGS),
+	GATE(0, "hclk_sdio_noc", "hclk_perilp1", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(25), 12, GFLAGS),
+	GATE(HCLK_I2S0_8CH, "hclk_i2s0", "hclk_perilp1", 0, RK3399_CLKGATE_CON(34), 0, GFLAGS),
+	GATE(HCLK_I2S1_8CH, "hclk_i2s1", "hclk_perilp1", 0, RK3399_CLKGATE_CON(34), 1, GFLAGS),
+	GATE(HCLK_I2S2_8CH, "hclk_i2s2", "hclk_perilp1", 0, RK3399_CLKGATE_CON(34), 2, GFLAGS),
+	GATE(HCLK_SPDIF, "hclk_spdif", "hclk_perilp1", 0, RK3399_CLKGATE_CON(34), 3, GFLAGS),
+	GATE(HCLK_SDIO, "hclk_sdio", "hclk_perilp1", 0, RK3399_CLKGATE_CON(34), 4, GFLAGS),
+	GATE(PCLK_SPI5, "pclk_spi5", "hclk_perilp1", 0, RK3399_CLKGATE_CON(34), 5, GFLAGS),
+	GATE(0, "hclk_sdioaudio_noc", "hclk_perilp1", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(34), 6, GFLAGS),
+
+	/* pclk_perilp1 gates */
+	GATE(PCLK_UART0, "pclk_uart0", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 0, GFLAGS),
+	GATE(PCLK_UART1, "pclk_uart1", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 1, GFLAGS),
+	GATE(PCLK_UART2, "pclk_uart2", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 2, GFLAGS),
+	GATE(PCLK_UART3, "pclk_uart3", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 3, GFLAGS),
+	GATE(PCLK_I2C7, "pclk_rki2c7", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 5, GFLAGS),
+	GATE(PCLK_I2C1, "pclk_rki2c1", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 6, GFLAGS),
+	GATE(PCLK_I2C5, "pclk_rki2c5", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 7, GFLAGS),
+	GATE(PCLK_I2C6, "pclk_rki2c6", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 8, GFLAGS),
+	GATE(PCLK_I2C2, "pclk_rki2c2", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 9, GFLAGS),
+	GATE(PCLK_I2C3, "pclk_rki2c3", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 10, GFLAGS),
+	GATE(PCLK_MAILBOX0, "pclk_mailbox0", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 11, GFLAGS),
+	GATE(PCLK_SARADC, "pclk_saradc", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 12, GFLAGS),
+	GATE(PCLK_TSADC, "pclk_tsadc", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 13, GFLAGS),
+	GATE(PCLK_EFUSE1024NS, "pclk_efuse1024ns", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 14, GFLAGS),
+	GATE(PCLK_EFUSE1024S, "pclk_efuse1024s", "pclk_perilp1", 0, RK3399_CLKGATE_CON(22), 15, GFLAGS),
+	GATE(PCLK_SPI0, "pclk_spi0", "pclk_perilp1", 0, RK3399_CLKGATE_CON(23), 10, GFLAGS),
+	GATE(PCLK_SPI1, "pclk_spi1", "pclk_perilp1", 0, RK3399_CLKGATE_CON(23), 11, GFLAGS),
+	GATE(PCLK_SPI2, "pclk_spi2", "pclk_perilp1", 0, RK3399_CLKGATE_CON(23), 12, GFLAGS),
+	GATE(PCLK_SPI4, "pclk_spi4", "pclk_perilp1", 0, RK3399_CLKGATE_CON(23), 13, GFLAGS),
+	GATE(PCLK_PERIHP_GRF, "pclk_perilp_sgrf", "pclk_perilp1", 0, RK3399_CLKGATE_CON(24), 13, GFLAGS),
+	GATE(0, "pclk_perilp1_noc", "pclk_perilp1", 0, RK3399_CLKGATE_CON(25), 10, GFLAGS),
+
+	/* saradc */
+	COMPOSITE_NOMUX(SCLK_SARADC, "clk_saradc", "xin24m", 0,
+			RK3399_CLKSEL_CON(26), 8, 8, DFLAGS,
+			RK3399_CLKGATE_CON(9), 11, GFLAGS),
+
+	/* tsadc */
+	COMPOSITE(SCLK_TSADC, "clk_tsadc", mux_pll_p, 0,
+			RK3399_CLKSEL_CON(27), 15, 1, MFLAGS, 0, 10, DFLAGS,
+			RK3399_CLKGATE_CON(9), 10, GFLAGS),
+
+	/* cif_testout */
+	MUX(0, "clk_testout1_pll_src", mux_pll_src_cpll_gpll_npll_p, 0,
+			RK3399_CLKSEL_CON(38), 6, 2, MFLAGS),
+	COMPOSITE(0, "clk_testout1", mux_clk_testout1_p, 0,
+			RK3399_CLKSEL_CON(38), 5, 1, MFLAGS, 0, 5, DFLAGS,
+			RK3399_CLKGATE_CON(13), 14, GFLAGS),
+
+	MUX(0, "clk_testout2_pll_src", mux_pll_src_cpll_gpll_npll_p, 0,
+			RK3399_CLKSEL_CON(38), 14, 2, MFLAGS),
+	COMPOSITE(0, "clk_testout2", mux_clk_testout2_p, 0,
+			RK3399_CLKSEL_CON(38), 13, 1, MFLAGS, 8, 5, DFLAGS,
+			RK3399_CLKGATE_CON(13), 15, GFLAGS),
+
+	/* vio */
+	COMPOSITE(ACLK_VIO, "aclk_vio", mux_pll_src_cpll_gpll_ppll_p, CLK_IGNORE_UNUSED,
+			RK3399_CLKSEL_CON(42), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3399_CLKGATE_CON(11), 10, GFLAGS),
+	COMPOSITE_NOMUX(PCLK_VIO, "pclk_vio", "aclk_vio", 0,
+			RK3399_CLKSEL_CON(43), 0, 5, DFLAGS,
+			RK3399_CLKGATE_CON(11), 1, GFLAGS),
+
+	GATE(ACLK_VIO_NOC, "aclk_vio_noc", "aclk_vio", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(29), 0, GFLAGS),
+
+	GATE(PCLK_MIPI_DSI0, "pclk_mipi_dsi0", "pclk_vio", 0,
+			RK3399_CLKGATE_CON(29), 1, GFLAGS),
+	GATE(PCLK_MIPI_DSI1, "pclk_mipi_dsi1", "pclk_vio", 0,
+			RK3399_CLKGATE_CON(29), 2, GFLAGS),
+	GATE(PCLK_VIO_GRF, "pclk_vio_grf", "pclk_vio", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(29), 12, GFLAGS),
+
+	/* hdcp */
+	COMPOSITE(ACLK_HDCP, "aclk_hdcp", mux_pll_src_cpll_gpll_ppll_p, 0,
+			RK3399_CLKSEL_CON(42), 14, 2, MFLAGS, 8, 5, DFLAGS,
+			RK3399_CLKGATE_CON(11), 12, GFLAGS),
+	COMPOSITE_NOMUX(HCLK_HDCP, "hclk_hdcp", "aclk_hdcp", 0,
+			RK3399_CLKSEL_CON(43), 5, 5, DFLAGS,
+			RK3399_CLKGATE_CON(11), 3, GFLAGS),
+	COMPOSITE_NOMUX(PCLK_HDCP, "pclk_hdcp", "aclk_hdcp", 0,
+			RK3399_CLKSEL_CON(43), 10, 5, DFLAGS,
+			RK3399_CLKGATE_CON(11), 10, GFLAGS),
+
+	GATE(ACLK_HDCP_NOC, "aclk_hdcp_noc", "aclk_hdcp", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(29), 4, GFLAGS),
+	GATE(ACLK_HDCP22, "aclk_hdcp22", "aclk_hdcp", 0,
+			RK3399_CLKGATE_CON(29), 10, GFLAGS),
+
+	GATE(HCLK_HDCP_NOC, "hclk_hdcp_noc", "hclk_hdcp", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(29), 5, GFLAGS),
+	GATE(HCLK_HDCP22, "hclk_hdcp22", "hclk_hdcp", 0,
+			RK3399_CLKGATE_CON(29), 9, GFLAGS),
+
+	GATE(PCLK_HDCP_NOC, "pclk_hdcp_noc", "pclk_hdcp", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(29), 3, GFLAGS),
+	GATE(PCLK_HDMI_CTRL, "pclk_hdmi_ctrl", "pclk_hdcp", 0,
+			RK3399_CLKGATE_CON(29), 6, GFLAGS),
+	GATE(PCLK_DP_CTRL, "pclk_dp_ctrl", "pclk_hdcp", 0,
+			RK3399_CLKGATE_CON(29), 7, GFLAGS),
+	GATE(PCLK_HDCP22, "pclk_hdcp22", "pclk_hdcp", 0,
+			RK3399_CLKGATE_CON(29), 8, GFLAGS),
+	GATE(PCLK_GASKET, "pclk_gasket", "pclk_hdcp", 0,
+			RK3399_CLKGATE_CON(29), 11, GFLAGS),
+
+	/* edp */
+	COMPOSITE(SCLK_DP_CORE, "clk_dp_core", mux_pll_src_npll_cpll_gpll_p, 0,
+			RK3399_CLKSEL_CON(46), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3399_CLKGATE_CON(11), 8, GFLAGS),
+
+	COMPOSITE(PCLK_EDP, "pclk_edp", mux_pll_src_cpll_gpll_p, 0,
+			RK3399_CLKSEL_CON(44), 15, 1, MFLAGS, 8, 5, DFLAGS,
+			RK3399_CLKGATE_CON(11), 11, GFLAGS),
+	GATE(PCLK_EDP_NOC, "pclk_edp_noc", "pclk_edp", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(32), 12, GFLAGS),
+	GATE(PCLK_EDP_CTRL, "pclk_edp_ctrl", "pclk_edp", 0,
+			RK3399_CLKGATE_CON(32), 13, GFLAGS),
+
+	/* hdmi */
+	GATE(SCLK_HDMI_SFR, "clk_hdmi_sfr", "xin24m", 0,
+			RK3399_CLKGATE_CON(11), 6, GFLAGS),
+
+	COMPOSITE(SCLK_HDMI_CEC, "clk_hdmi_cec", mux_pll_p, 0,
+			RK3399_CLKSEL_CON(45), 15, 1, MFLAGS, 0, 10, DFLAGS,
+			RK3399_CLKGATE_CON(11), 7, GFLAGS),
+
+	/* vop0 */
+	COMPOSITE(ACLK_VOP0_PRE, "aclk_vop0_pre", mux_pll_src_vpll_cpll_gpll_npll_p, 0,
+			RK3399_CLKSEL_CON(47), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3399_CLKGATE_CON(10), 8, GFLAGS),
+	COMPOSITE_NOMUX(0, "hclk_vop0_pre", "aclk_vop0_pre", 0,
+			RK3399_CLKSEL_CON(47), 8, 5, DFLAGS,
+			RK3399_CLKGATE_CON(10), 9, GFLAGS),
+
+	GATE(ACLK_VOP0, "aclk_vop0", "aclk_vop0_pre", 0,
+			RK3399_CLKGATE_CON(28), 3, GFLAGS),
+	GATE(ACLK_VOP0_NOC, "aclk_vop0_noc", "aclk_vop0_pre", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(28), 1, GFLAGS),
+
+	GATE(HCLK_VOP0, "hclk_vop0", "hclk_vop0_pre", 0,
+			RK3399_CLKGATE_CON(28), 2, GFLAGS),
+	GATE(HCLK_VOP0_NOC, "hclk_vop0_noc", "hclk_vop0_pre", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(28), 0, GFLAGS),
+
+	COMPOSITE(DCLK_VOP0_DIV, "dclk_vop0_div", mux_pll_src_vpll_cpll_gpll_p, 0,
+			RK3399_CLKSEL_CON(49), 8, 2, MFLAGS, 0, 8, DFLAGS,
+			RK3399_CLKGATE_CON(10), 12, GFLAGS),
+
+	COMPOSITE_FRACMUX_NOGATE(0, "dclk_vop0_frac", "dclk_vop0_div", CLK_SET_RATE_PARENT,
+			RK3399_CLKSEL_CON(106), 0,
+			&rk3399_dclk_vop0_fracmux),
+
+	COMPOSITE(SCLK_VOP0_PWM, "clk_vop0_pwm", mux_pll_src_vpll_cpll_gpll_24m_p, 0,
+			RK3399_CLKSEL_CON(51), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3399_CLKGATE_CON(10), 14, GFLAGS),
+
+	/* vop1 */
+	COMPOSITE(ACLK_VOP1_PRE, "aclk_vop1_pre", mux_pll_src_vpll_cpll_gpll_npll_p, 0,
+			RK3399_CLKSEL_CON(48), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3399_CLKGATE_CON(10), 10, GFLAGS),
+	COMPOSITE_NOMUX(0, "hclk_vop1_pre", "aclk_vop1_pre", 0,
+			RK3399_CLKSEL_CON(48), 8, 5, DFLAGS,
+			RK3399_CLKGATE_CON(10), 11, GFLAGS),
+
+	GATE(ACLK_VOP1, "aclk_vop1", "aclk_vop1_pre", 0,
+			RK3399_CLKGATE_CON(28), 7, GFLAGS),
+	GATE(ACLK_VOP1_NOC, "aclk_vop1_noc", "aclk_vop1_pre", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(28), 5, GFLAGS),
+
+	GATE(HCLK_VOP1, "hclk_vop1", "hclk_vop1_pre", 0,
+			RK3399_CLKGATE_CON(28), 6, GFLAGS),
+	GATE(HCLK_VOP1_NOC, "hclk_vop1_noc", "hclk_vop1_pre", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(28), 4, GFLAGS),
+
+	COMPOSITE(DCLK_VOP1_DIV, "dclk_vop1_div", mux_pll_src_vpll_cpll_gpll_p, 0,
+			RK3399_CLKSEL_CON(50), 8, 2, MFLAGS, 0, 8, DFLAGS,
+			RK3399_CLKGATE_CON(10), 13, GFLAGS),
+
+	COMPOSITE_FRACMUX_NOGATE(0, "dclk_vop1_frac", "dclk_vop1_div", CLK_SET_RATE_PARENT,
+			RK3399_CLKSEL_CON(107), 0,
+			&rk3399_dclk_vop1_fracmux),
+
+	COMPOSITE(SCLK_VOP1_PWM, "clk_vop1_pwm", mux_pll_src_vpll_cpll_gpll_24m_p, CLK_IGNORE_UNUSED,
+			RK3399_CLKSEL_CON(52), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3399_CLKGATE_CON(10), 15, GFLAGS),
+
+	/* isp */
+	COMPOSITE(ACLK_ISP0, "aclk_isp0", mux_pll_src_cpll_gpll_ppll_p, 0,
+			RK3399_CLKSEL_CON(53), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3399_CLKGATE_CON(12), 8, GFLAGS),
+	COMPOSITE_NOMUX(HCLK_ISP0, "hclk_isp0", "aclk_isp0", 0,
+			RK3399_CLKSEL_CON(53), 8, 5, DFLAGS,
+			RK3399_CLKGATE_CON(12), 9, GFLAGS),
+
+	GATE(ACLK_ISP0_NOC, "aclk_isp0_noc", "aclk_isp0", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(27), 1, GFLAGS),
+	GATE(ACLK_ISP0_WRAPPER, "aclk_isp0_wrapper", "aclk_isp0", 0,
+			RK3399_CLKGATE_CON(27), 5, GFLAGS),
+	GATE(HCLK_ISP1_WRAPPER, "hclk_isp1_wrapper", "aclk_isp0", 0,
+			RK3399_CLKGATE_CON(27), 7, GFLAGS),
+
+	GATE(HCLK_ISP0_NOC, "hclk_isp0_noc", "hclk_isp0", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(27), 0, GFLAGS),
+	GATE(HCLK_ISP0_WRAPPER, "hclk_isp0_wrapper", "hclk_isp0", 0,
+			RK3399_CLKGATE_CON(27), 4, GFLAGS),
+
+	COMPOSITE(SCLK_ISP0, "clk_isp0", mux_pll_src_cpll_gpll_npll_p, 0,
+			RK3399_CLKSEL_CON(55), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3399_CLKGATE_CON(11), 4, GFLAGS),
+
+	COMPOSITE(ACLK_ISP1, "aclk_isp1", mux_pll_src_cpll_gpll_ppll_p, 0,
+			RK3399_CLKSEL_CON(54), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3399_CLKGATE_CON(12), 10, GFLAGS),
+	COMPOSITE_NOMUX(HCLK_ISP1, "hclk_isp1", "aclk_isp1", 0,
+			RK3399_CLKSEL_CON(54), 8, 5, DFLAGS,
+			RK3399_CLKGATE_CON(12), 11, GFLAGS),
+
+	GATE(ACLK_ISP1_NOC, "aclk_isp1_noc", "aclk_isp1", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(27), 3, GFLAGS),
+
+	GATE(HCLK_ISP1_NOC, "hclk_isp1_noc", "hclk_isp1", CLK_IGNORE_UNUSED,
+			RK3399_CLKGATE_CON(27), 2, GFLAGS),
+	GATE(ACLK_ISP1_WRAPPER, "aclk_isp1_wrapper", "hclk_isp1", 0,
+			RK3399_CLKGATE_CON(27), 8, GFLAGS),
+
+	COMPOSITE(SCLK_ISP1, "clk_isp1", mux_pll_src_cpll_gpll_npll_p, 0,
+			RK3399_CLKSEL_CON(55), 14, 2, MFLAGS, 8, 5, DFLAGS,
+			RK3399_CLKGATE_CON(11), 5, GFLAGS),
+
+	/*
+	 * We use pclkin_cifinv by default GRF_SOC_CON20[9] (GSC20_9) setting in system,
+	 * so we ignore the mux and make clocks nodes as following,
+	 *
+	 * pclkin_cifinv --|-------\
+	 *                 |GSC20_9|-- pclkin_cifmux -- |G27_6| -- pclkin_isp1_wrapper
+	 * pclkin_cif    --|-------/
+	 */
+	GATE(PCLK_ISP1_WRAPPER, "pclkin_isp1_wrapper", "pclkin_cif", 0,
+			RK3399_CLKGATE_CON(27), 6, GFLAGS),
+
+	/* cif */
+	COMPOSITE_NODIV(0, "clk_cifout_src", mux_pll_src_cpll_gpll_npll_p, 0,
+			RK3399_CLKSEL_CON(56), 6, 2, MFLAGS,
+			RK3399_CLKGATE_CON(10), 7, GFLAGS),
+
+	COMPOSITE_NOGATE(SCLK_CIF_OUT, "clk_cifout", mux_clk_cif_p, 0,
+			 RK3399_CLKSEL_CON(56), 5, 1, MFLAGS, 0, 5, DFLAGS),
+
+	/* gic */
+	COMPOSITE(ACLK_GIC_PRE, "aclk_gic_pre", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED,
+			RK3399_CLKSEL_CON(56), 15, 1, MFLAGS, 8, 5, DFLAGS,
+			RK3399_CLKGATE_CON(12), 12, GFLAGS),
+
+	GATE(ACLK_GIC, "aclk_gic", "aclk_gic_pre", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(33), 0, GFLAGS),
+	GATE(ACLK_GIC_NOC, "aclk_gic_noc", "aclk_gic_pre", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(33), 1, GFLAGS),
+	GATE(ACLK_GIC_ADB400_CORE_L_2_GIC, "aclk_gic_adb400_core_l_2_gic", "aclk_gic_pre", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(33), 2, GFLAGS),
+	GATE(ACLK_GIC_ADB400_CORE_B_2_GIC, "aclk_gic_adb400_core_b_2_gic", "aclk_gic_pre", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(33), 3, GFLAGS),
+	GATE(ACLK_GIC_ADB400_GIC_2_CORE_L, "aclk_gic_adb400_gic_2_core_l", "aclk_gic_pre", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(33), 4, GFLAGS),
+	GATE(ACLK_GIC_ADB400_GIC_2_CORE_B, "aclk_gic_adb400_gic_2_core_b", "aclk_gic_pre", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(33), 5, GFLAGS),
+
+	/* alive */
+	/* pclk_alive_gpll_src is controlled by PMUGRF_SOC_CON0[6] */
+	DIV(PCLK_ALIVE, "pclk_alive", "gpll", 0,
+			RK3399_CLKSEL_CON(57), 0, 5, DFLAGS),
+
+	GATE(PCLK_USBPHY_MUX_G, "pclk_usbphy_mux_g", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 4, GFLAGS),
+	GATE(PCLK_UPHY0_TCPHY_G, "pclk_uphy0_tcphy_g", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 5, GFLAGS),
+	GATE(PCLK_UPHY0_TCPD_G, "pclk_uphy0_tcpd_g", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 6, GFLAGS),
+	GATE(PCLK_UPHY1_TCPHY_G, "pclk_uphy1_tcphy_g", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 8, GFLAGS),
+	GATE(PCLK_UPHY1_TCPD_G, "pclk_uphy1_tcpd_g", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 9, GFLAGS),
+
+	GATE(PCLK_GRF, "pclk_grf", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(31), 1, GFLAGS),
+	GATE(PCLK_INTR_ARB, "pclk_intr_arb", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(31), 2, GFLAGS),
+	GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_alive", 0, RK3399_CLKGATE_CON(31), 3, GFLAGS),
+	GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_alive", 0, RK3399_CLKGATE_CON(31), 4, GFLAGS),
+	GATE(PCLK_GPIO4, "pclk_gpio4", "pclk_alive", 0, RK3399_CLKGATE_CON(31), 5, GFLAGS),
+	GATE(PCLK_TIMER0, "pclk_timer0", "pclk_alive", 0, RK3399_CLKGATE_CON(31), 6, GFLAGS),
+	GATE(PCLK_TIMER1, "pclk_timer1", "pclk_alive", 0, RK3399_CLKGATE_CON(31), 7, GFLAGS),
+	GATE(PCLK_PMU_INTR_ARB, "pclk_pmu_intr_arb", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(31), 9, GFLAGS),
+	GATE(PCLK_SGRF, "pclk_sgrf", "pclk_alive", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(31), 10, GFLAGS),
+
+	GATE(SCLK_MIPIDPHY_REF, "clk_mipidphy_ref", "xin24m", 0, RK3399_CLKGATE_CON(11), 14, GFLAGS),
+	GATE(SCLK_DPHY_PLL, "clk_dphy_pll", "clk_mipidphy_ref", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 0, GFLAGS),
+
+	GATE(SCLK_MIPIDPHY_CFG, "clk_mipidphy_cfg", "xin24m", 0, RK3399_CLKGATE_CON(11), 15, GFLAGS),
+	GATE(SCLK_DPHY_TX0_CFG, "clk_dphy_tx0_cfg", "clk_mipidphy_cfg", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 1, GFLAGS),
+	GATE(SCLK_DPHY_TX1RX1_CFG, "clk_dphy_tx1rx1_cfg", "clk_mipidphy_cfg", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 2, GFLAGS),
+	GATE(SCLK_DPHY_RX0_CFG, "clk_dphy_rx0_cfg", "clk_mipidphy_cfg", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(21), 3, GFLAGS),
+
+	/* testout */
+	MUX(0, "clk_test_pre", mux_pll_src_cpll_gpll_p, CLK_SET_RATE_PARENT,
+			RK3399_CLKSEL_CON(58), 7, 1, MFLAGS),
+	COMPOSITE_FRAC(0, "clk_test_frac", "clk_test_pre", CLK_SET_RATE_PARENT,
+			RK3399_CLKSEL_CON(105), 0,
+			RK3399_CLKGATE_CON(13), 9, GFLAGS),
+
+	DIV(0, "clk_test_24m", "xin24m", 0,
+			RK3399_CLKSEL_CON(57), 6, 10, DFLAGS),
+
+	/* spi */
+	COMPOSITE(SCLK_SPI0, "clk_spi0", mux_pll_src_cpll_gpll_p, 0,
+			RK3399_CLKSEL_CON(59), 7, 1, MFLAGS, 0, 7, DFLAGS,
+			RK3399_CLKGATE_CON(9), 12, GFLAGS),
+
+	COMPOSITE(SCLK_SPI1, "clk_spi1", mux_pll_src_cpll_gpll_p, 0,
+			RK3399_CLKSEL_CON(59), 15, 1, MFLAGS, 8, 7, DFLAGS,
+			RK3399_CLKGATE_CON(9), 13, GFLAGS),
+
+	COMPOSITE(SCLK_SPI2, "clk_spi2", mux_pll_src_cpll_gpll_p, 0,
+			RK3399_CLKSEL_CON(60), 7, 1, MFLAGS, 0, 7, DFLAGS,
+			RK3399_CLKGATE_CON(9), 14, GFLAGS),
+
+	COMPOSITE(SCLK_SPI4, "clk_spi4", mux_pll_src_cpll_gpll_p, 0,
+			RK3399_CLKSEL_CON(60), 15, 1, MFLAGS, 8, 7, DFLAGS,
+			RK3399_CLKGATE_CON(9), 15, GFLAGS),
+
+	COMPOSITE(SCLK_SPI5, "clk_spi5", mux_pll_src_cpll_gpll_p, 0,
+			RK3399_CLKSEL_CON(58), 15, 1, MFLAGS, 8, 7, DFLAGS,
+			RK3399_CLKGATE_CON(13), 13, GFLAGS),
+
+	/* i2c */
+	COMPOSITE(SCLK_I2C1, "clk_i2c1", mux_pll_src_cpll_gpll_p, 0,
+			RK3399_CLKSEL_CON(61), 7, 1, MFLAGS, 0, 7, DFLAGS,
+			RK3399_CLKGATE_CON(10), 0, GFLAGS),
+
+	COMPOSITE(SCLK_I2C2, "clk_i2c2", mux_pll_src_cpll_gpll_p, 0,
+			RK3399_CLKSEL_CON(62), 7, 1, MFLAGS, 0, 7, DFLAGS,
+			RK3399_CLKGATE_CON(10), 2, GFLAGS),
+
+	COMPOSITE(SCLK_I2C3, "clk_i2c3", mux_pll_src_cpll_gpll_p, 0,
+			RK3399_CLKSEL_CON(63), 7, 1, MFLAGS, 0, 7, DFLAGS,
+			RK3399_CLKGATE_CON(10), 4, GFLAGS),
+
+	COMPOSITE(SCLK_I2C5, "clk_i2c5", mux_pll_src_cpll_gpll_p, 0,
+			RK3399_CLKSEL_CON(61), 15, 1, MFLAGS, 8, 7, DFLAGS,
+			RK3399_CLKGATE_CON(10), 1, GFLAGS),
+
+	COMPOSITE(SCLK_I2C6, "clk_i2c6", mux_pll_src_cpll_gpll_p, 0,
+			RK3399_CLKSEL_CON(62), 15, 1, MFLAGS, 8, 7, DFLAGS,
+			RK3399_CLKGATE_CON(10), 3, GFLAGS),
+
+	COMPOSITE(SCLK_I2C7, "clk_i2c7", mux_pll_src_cpll_gpll_p, 0,
+			RK3399_CLKSEL_CON(63), 15, 1, MFLAGS, 8, 7, DFLAGS,
+			RK3399_CLKGATE_CON(10), 5, GFLAGS),
+
+	/* timer */
+	GATE(SCLK_TIMER00, "clk_timer00", "xin24m", 0, RK3399_CLKGATE_CON(26), 0, GFLAGS),
+	GATE(SCLK_TIMER01, "clk_timer01", "xin24m", 0, RK3399_CLKGATE_CON(26), 1, GFLAGS),
+	GATE(SCLK_TIMER02, "clk_timer02", "xin24m", 0, RK3399_CLKGATE_CON(26), 2, GFLAGS),
+	GATE(SCLK_TIMER03, "clk_timer03", "xin24m", 0, RK3399_CLKGATE_CON(26), 3, GFLAGS),
+	GATE(SCLK_TIMER04, "clk_timer04", "xin24m", 0, RK3399_CLKGATE_CON(26), 4, GFLAGS),
+	GATE(SCLK_TIMER05, "clk_timer05", "xin24m", 0, RK3399_CLKGATE_CON(26), 5, GFLAGS),
+	GATE(SCLK_TIMER06, "clk_timer06", "xin24m", 0, RK3399_CLKGATE_CON(26), 6, GFLAGS),
+	GATE(SCLK_TIMER07, "clk_timer07", "xin24m", 0, RK3399_CLKGATE_CON(26), 7, GFLAGS),
+	GATE(SCLK_TIMER08, "clk_timer08", "xin24m", 0, RK3399_CLKGATE_CON(26), 8, GFLAGS),
+	GATE(SCLK_TIMER09, "clk_timer09", "xin24m", 0, RK3399_CLKGATE_CON(26), 9, GFLAGS),
+	GATE(SCLK_TIMER10, "clk_timer10", "xin24m", 0, RK3399_CLKGATE_CON(26), 10, GFLAGS),
+	GATE(SCLK_TIMER11, "clk_timer11", "xin24m", 0, RK3399_CLKGATE_CON(26), 11, GFLAGS),
+
+	/* clk_test */
+	/* clk_test_pre is controlled by CRU_MISC_CON[3] */
+	COMPOSITE_NOMUX(0, "clk_test", "clk_test_pre", CLK_IGNORE_UNUSED,
+			RK3368_CLKSEL_CON(58), 0, 5, DFLAGS,
+			RK3368_CLKGATE_CON(13), 11, GFLAGS),
+};
+
+static struct rockchip_clk_branch rk3399_clk_pmu_branches[] __initdata = {
+	/*
+	 * PMU CRU Clock-Architecture
+	 */
+
+	GATE(0, "fclk_cm0s_pmu_ppll_src", "ppll", 0,
+			RK3399_PMU_CLKGATE_CON(0), 1, GFLAGS),
+
+	COMPOSITE_NOGATE(FCLK_CM0S_SRC_PMU, "fclk_cm0s_src_pmu", mux_fclk_cm0s_pmu_ppll_p, 0,
+			RK3399_PMU_CLKSEL_CON(0), 15, 1, MFLAGS, 8, 5, DFLAGS),
+
+	COMPOSITE(SCLK_SPI3_PMU, "clk_spi3_pmu", mux_24m_ppll_p, 0,
+			RK3399_PMU_CLKSEL_CON(1), 7, 1, MFLAGS, 0, 7, DFLAGS,
+			RK3399_PMU_CLKGATE_CON(0), 2, GFLAGS),
+
+	COMPOSITE(0, "clk_wifi_div", mux_ppll_24m_p, CLK_IGNORE_UNUSED,
+			RK3399_PMU_CLKSEL_CON(1), 13, 1, MFLAGS, 8, 5, DFLAGS,
+			RK3399_PMU_CLKGATE_CON(0), 8, GFLAGS),
+
+	COMPOSITE_FRACMUX_NOGATE(0, "clk_wifi_frac", "clk_wifi_div", CLK_SET_RATE_PARENT,
+			RK3399_PMU_CLKSEL_CON(7), 0,
+			&rk3399_pmuclk_wifi_fracmux),
+
+	MUX(0, "clk_timer_src_pmu", mux_pll_p, CLK_IGNORE_UNUSED,
+			RK3399_PMU_CLKSEL_CON(1), 15, 1, MFLAGS),
+
+	COMPOSITE_NOMUX(SCLK_I2C0_PMU, "clk_i2c0_pmu", "ppll", 0,
+			RK3399_PMU_CLKSEL_CON(2), 0, 7, DFLAGS,
+			RK3399_PMU_CLKGATE_CON(0), 9, GFLAGS),
+
+	COMPOSITE_NOMUX(SCLK_I2C4_PMU, "clk_i2c4_pmu", "ppll", 0,
+			RK3399_PMU_CLKSEL_CON(3), 0, 7, DFLAGS,
+			RK3399_PMU_CLKGATE_CON(0), 10, GFLAGS),
+
+	COMPOSITE_NOMUX(SCLK_I2C8_PMU, "clk_i2c8_pmu", "ppll", 0,
+			RK3399_PMU_CLKSEL_CON(2), 8, 7, DFLAGS,
+			RK3399_PMU_CLKGATE_CON(0), 11, GFLAGS),
+
+	DIV(0, "clk_32k_suspend_pmu", "xin24m", CLK_IGNORE_UNUSED,
+			RK3399_PMU_CLKSEL_CON(4), 0, 10, DFLAGS),
+	MUX(0, "clk_testout_2io", mux_clk_testout2_2io_p, CLK_IGNORE_UNUSED,
+			RK3399_PMU_CLKSEL_CON(4), 15, 1, MFLAGS),
+
+	COMPOSITE(0, "clk_uart4_div", mux_24m_ppll_p, 0,
+			RK3399_PMU_CLKSEL_CON(5), 10, 1, MFLAGS, 0, 7, DFLAGS,
+			RK3399_PMU_CLKGATE_CON(0), 5, GFLAGS),
+
+	COMPOSITE_FRACMUX(0, "clk_uart4_frac", "clk_uart4_div", CLK_SET_RATE_PARENT,
+			RK3399_PMU_CLKSEL_CON(6), 0,
+			RK3399_PMU_CLKGATE_CON(0), 6, GFLAGS,
+			&rk3399_uart4_pmu_fracmux),
+
+	DIV(PCLK_SRC_PMU, "pclk_pmu_src", "ppll", CLK_IGNORE_UNUSED,
+			RK3399_PMU_CLKSEL_CON(0), 0, 5, DFLAGS),
+
+	/* pmu clock gates */
+	GATE(SCLK_TIMER12_PMU, "clk_timer0_pmu", "clk_timer_src_pmu", 0, RK3399_PMU_CLKGATE_CON(0), 3, GFLAGS),
+	GATE(SCLK_TIMER13_PMU, "clk_timer1_pmu", "clk_timer_src_pmu", 0, RK3399_PMU_CLKGATE_CON(0), 4, GFLAGS),
+
+	GATE(SCLK_PVTM_PMU, "clk_pvtm_pmu", "xin24m", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(0), 7, GFLAGS),
+
+	GATE(PCLK_PMU, "pclk_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 0, GFLAGS),
+	GATE(PCLK_PMUGRF_PMU, "pclk_pmugrf_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 1, GFLAGS),
+	GATE(PCLK_INTMEM1_PMU, "pclk_intmem1_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 2, GFLAGS),
+	GATE(PCLK_GPIO0_PMU, "pclk_gpio0_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 3, GFLAGS),
+	GATE(PCLK_GPIO1_PMU, "pclk_gpio1_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 4, GFLAGS),
+	GATE(PCLK_SGRF_PMU, "pclk_sgrf_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 5, GFLAGS),
+	GATE(PCLK_NOC_PMU, "pclk_noc_pmu", "pclk_pmu_src", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(1), 6, GFLAGS),
+	GATE(PCLK_I2C0_PMU, "pclk_i2c0_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 7, GFLAGS),
+	GATE(PCLK_I2C4_PMU, "pclk_i2c4_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 8, GFLAGS),
+	GATE(PCLK_I2C8_PMU, "pclk_i2c8_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 9, GFLAGS),
+	GATE(PCLK_RKPWM_PMU, "pclk_rkpwm_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 10, GFLAGS),
+	GATE(PCLK_SPI3_PMU, "pclk_spi3_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 11, GFLAGS),
+	GATE(PCLK_TIMER_PMU, "pclk_timer_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 12, GFLAGS),
+	GATE(PCLK_MAILBOX_PMU, "pclk_mailbox_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 13, GFLAGS),
+	GATE(PCLK_UART4_PMU, "pclk_uart4_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 14, GFLAGS),
+	GATE(PCLK_WDT_M0_PMU, "pclk_wdt_m0_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 15, GFLAGS),
+
+	GATE(FCLK_CM0S_PMU, "fclk_cm0s_pmu", "fclk_cm0s_src_pmu", 0, RK3399_PMU_CLKGATE_CON(2), 0, GFLAGS),
+	GATE(SCLK_CM0S_PMU, "sclk_cm0s_pmu", "fclk_cm0s_src_pmu", 0, RK3399_PMU_CLKGATE_CON(2), 1, GFLAGS),
+	GATE(HCLK_CM0S_PMU, "hclk_cm0s_pmu", "fclk_cm0s_src_pmu", 0, RK3399_PMU_CLKGATE_CON(2), 2, GFLAGS),
+	GATE(DCLK_CM0S_PMU, "dclk_cm0s_pmu", "fclk_cm0s_src_pmu", 0, RK3399_PMU_CLKGATE_CON(2), 3, GFLAGS),
+	GATE(HCLK_NOC_PMU, "hclk_noc_pmu", "fclk_cm0s_src_pmu", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(2), 5, GFLAGS),
+};
+
+static const char *const rk3399_cru_critical_clocks[] __initconst = {
+	"aclk_cci_pre",
+	"aclk_gic",
+	"aclk_gic_noc",
+	"pclk_perilp0",
+	"pclk_perilp0",
+	"hclk_perilp0",
+	"hclk_perilp0_noc",
+	"pclk_perilp1",
+	"pclk_perilp1_noc",
+	"pclk_perihp",
+	"pclk_perihp_noc",
+	"hclk_perihp",
+	"aclk_perihp",
+	"aclk_perihp_noc",
+	"aclk_perilp0",
+	"aclk_perilp0_noc",
+	"hclk_perilp1",
+	"hclk_perilp1_noc",
+	"aclk_dmac0_perilp",
+	"gpll_hclk_perilp1_src",
+	"gpll_aclk_perilp0_src",
+	"gpll_aclk_perihp_src",
+};
+
+static const char *const rk3399_pmucru_critical_clocks[] __initconst = {
+	"ppll",
+	"pclk_pmu_src",
+	"fclk_cm0s_src_pmu",
+	"clk_timer_src_pmu",
+};
+
+static void __init rk3399_clk_init(struct device_node *np)
+{
+	struct rockchip_clk_provider *ctx;
+	void __iomem *reg_base;
+
+	reg_base = of_iomap(np, 0);
+	if (!reg_base) {
+		pr_err("%s: could not map cru region\n", __func__);
+		return;
+	}
+
+	ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
+	if (IS_ERR(ctx)) {
+		pr_err("%s: rockchip clk init failed\n", __func__);
+		iounmap(reg_base);
+		return;
+	}
+
+	rockchip_clk_register_plls(ctx, rk3399_pll_clks,
+				   ARRAY_SIZE(rk3399_pll_clks), -1);
+
+	rockchip_clk_register_branches(ctx, rk3399_clk_branches,
+				  ARRAY_SIZE(rk3399_clk_branches));
+
+	rockchip_clk_protect_critical(rk3399_cru_critical_clocks,
+				      ARRAY_SIZE(rk3399_cru_critical_clocks));
+
+	rockchip_clk_register_armclk(ctx, ARMCLKL, "armclkl",
+			mux_armclkl_p, ARRAY_SIZE(mux_armclkl_p),
+			&rk3399_cpuclkl_data, rk3399_cpuclkl_rates,
+			ARRAY_SIZE(rk3399_cpuclkl_rates));
+
+	rockchip_clk_register_armclk(ctx, ARMCLKB, "armclkb",
+			mux_armclkb_p, ARRAY_SIZE(mux_armclkb_p),
+			&rk3399_cpuclkb_data, rk3399_cpuclkb_rates,
+			ARRAY_SIZE(rk3399_cpuclkb_rates));
+
+	rockchip_register_softrst(np, 21, reg_base + RK3399_SOFTRST_CON(0),
+				  ROCKCHIP_SOFTRST_HIWORD_MASK);
+
+	rockchip_register_restart_notifier(ctx, RK3399_GLB_SRST_FST, NULL);
+
+	rockchip_clk_of_add_provider(np, ctx);
+}
+CLK_OF_DECLARE(rk3399_cru, "rockchip,rk3399-cru", rk3399_clk_init);
+
+static void __init rk3399_pmu_clk_init(struct device_node *np)
+{
+	struct rockchip_clk_provider *ctx;
+	void __iomem *reg_base;
+
+	reg_base = of_iomap(np, 0);
+	if (!reg_base) {
+		pr_err("%s: could not map cru pmu region\n", __func__);
+		return;
+	}
+
+	ctx = rockchip_clk_init(np, reg_base, CLKPMU_NR_CLKS);
+	if (IS_ERR(ctx)) {
+		pr_err("%s: rockchip pmu clk init failed\n", __func__);
+		iounmap(reg_base);
+		return;
+	}
+
+	rockchip_clk_register_plls(ctx, rk3399_pmu_pll_clks,
+				   ARRAY_SIZE(rk3399_pmu_pll_clks), -1);
+
+	rockchip_clk_register_branches(ctx, rk3399_clk_pmu_branches,
+				  ARRAY_SIZE(rk3399_clk_pmu_branches));
+
+	rockchip_clk_protect_critical(rk3399_pmucru_critical_clocks,
+				  ARRAY_SIZE(rk3399_pmucru_critical_clocks));
+
+	rockchip_register_softrst(np, 2, reg_base + RK3399_PMU_SOFTRST_CON(0),
+				  ROCKCHIP_SOFTRST_HIWORD_MASK);
+
+	rockchip_clk_of_add_provider(np, ctx);
+}
+CLK_OF_DECLARE(rk3399_cru_pmu, "rockchip,rk3399-pmucru", rk3399_pmu_clk_init);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/rockchip/Makefile linux-libre-4.7-gnu/drivers/clk/rockchip/Makefile
--- linux-libre-4.6-gnu/drivers/clk/rockchip/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/rockchip/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -15,3 +15,4 @@ obj-y	+= clk-rk3188.o
 obj-y	+= clk-rk3228.o
 obj-y	+= clk-rk3288.o
 obj-y	+= clk-rk3368.o
+obj-y	+= clk-rk3399.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/samsung/clk-exynos3250.c linux-libre-4.7-gnu/drivers/clk/samsung/clk-exynos3250.c
--- linux-libre-4.6-gnu/drivers/clk/samsung/clk-exynos3250.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/samsung/clk-exynos3250.c	2016-07-24 15:23:50.000000000 -0400
@@ -302,10 +302,12 @@ static struct samsung_mux_clock mux_clks
 
 	/* SRC_FSYS */
 	MUX(CLK_MOUT_TSADC, "mout_tsadc", group_sclk_p, SRC_FSYS, 28, 4),
+	MUX(CLK_MOUT_MMC2, "mout_mmc2", group_sclk_p, SRC_FSYS, 8, 4),
 	MUX(CLK_MOUT_MMC1, "mout_mmc1", group_sclk_p, SRC_FSYS, 4, 4),
 	MUX(CLK_MOUT_MMC0, "mout_mmc0", group_sclk_p, SRC_FSYS, 0, 4),
 
 	/* SRC_PERIL0 */
+	MUX(CLK_MOUT_UART2, "mout_uart2", group_sclk_p, SRC_PERIL0, 8, 4),
 	MUX(CLK_MOUT_UART1, "mout_uart1", group_sclk_p, SRC_PERIL0, 4, 4),
 	MUX(CLK_MOUT_UART0, "mout_uart0", group_sclk_p, SRC_PERIL0, 0, 4),
 
@@ -389,7 +391,13 @@ static struct samsung_div_clock div_clks
 		CLK_SET_RATE_PARENT, 0),
 	DIV(CLK_DIV_MMC0, "div_mmc0", "mout_mmc0", DIV_FSYS1, 0, 4),
 
+	/* DIV_FSYS2 */
+	DIV_F(CLK_DIV_MMC2_PRE, "div_mmc2_pre", "div_mmc2", DIV_FSYS2, 8, 8,
+		CLK_SET_RATE_PARENT, 0),
+	DIV(CLK_DIV_MMC2, "div_mmc2", "mout_mmc2", DIV_FSYS2, 0, 4),
+
 	/* DIV_PERIL0 */
+	DIV(CLK_DIV_UART2, "div_uart2", "mout_uart2", DIV_PERIL0, 8, 4),
 	DIV(CLK_DIV_UART1, "div_uart1", "mout_uart1", DIV_PERIL0, 4, 4),
 	DIV(CLK_DIV_UART0, "div_uart0", "mout_uart0", DIV_PERIL0, 0, 4),
 
@@ -538,6 +546,8 @@ static struct samsung_gate_clock gate_cl
 		GATE_SCLK_FSYS, 9, CLK_SET_RATE_PARENT, 0),
 	GATE(CLK_SCLK_EBI, "sclk_ebi", "div_ebi",
 		GATE_SCLK_FSYS, 6, CLK_SET_RATE_PARENT, 0),
+	GATE(CLK_SCLK_MMC2, "sclk_mmc2", "div_mmc2_pre",
+		GATE_SCLK_FSYS, 2, CLK_SET_RATE_PARENT, 0),
 	GATE(CLK_SCLK_MMC1, "sclk_mmc1", "div_mmc1_pre",
 		GATE_SCLK_FSYS, 1, CLK_SET_RATE_PARENT, 0),
 	GATE(CLK_SCLK_MMC0, "sclk_mmc0", "div_mmc0_pre",
@@ -552,6 +562,9 @@ static struct samsung_gate_clock gate_cl
 		GATE_SCLK_PERIL, 7, CLK_SET_RATE_PARENT, 0),
 	GATE(CLK_SCLK_SPI0, "sclk_spi0", "div_spi0_pre",
 		GATE_SCLK_PERIL, 6, CLK_SET_RATE_PARENT, 0),
+
+	GATE(CLK_SCLK_UART2, "sclk_uart2", "div_uart2",
+		GATE_SCLK_PERIL, 2, CLK_SET_RATE_PARENT, 0),
 	GATE(CLK_SCLK_UART1, "sclk_uart1", "div_uart1",
 		GATE_SCLK_PERIL, 1, CLK_SET_RATE_PARENT, 0),
 	GATE(CLK_SCLK_UART0, "sclk_uart0", "div_uart0",
@@ -630,6 +643,7 @@ static struct samsung_gate_clock gate_cl
 	GATE(CLK_USBOTG, "usbotg", "div_aclk_200", GATE_IP_FSYS, 13, 0, 0),
 	GATE(CLK_USBHOST, "usbhost", "div_aclk_200", GATE_IP_FSYS, 12, 0, 0),
 	GATE(CLK_SROMC, "sromc", "div_aclk_200", GATE_IP_FSYS, 11, 0, 0),
+	GATE(CLK_SDMMC2, "sdmmc2", "div_aclk_200", GATE_IP_FSYS, 7, 0, 0),
 	GATE(CLK_SDMMC1, "sdmmc1", "div_aclk_200", GATE_IP_FSYS, 6, 0, 0),
 	GATE(CLK_SDMMC0, "sdmmc0", "div_aclk_200", GATE_IP_FSYS, 5, 0, 0),
 	GATE(CLK_PDMA1, "pdma1", "div_aclk_200", GATE_IP_FSYS, 1, 0, 0),
@@ -649,6 +663,7 @@ static struct samsung_gate_clock gate_cl
 	GATE(CLK_I2C2, "i2c2", "div_aclk_100", GATE_IP_PERIL, 8, 0, 0),
 	GATE(CLK_I2C1, "i2c1", "div_aclk_100", GATE_IP_PERIL, 7, 0, 0),
 	GATE(CLK_I2C0, "i2c0", "div_aclk_100", GATE_IP_PERIL, 6, 0, 0),
+	GATE(CLK_UART2, "uart2", "div_aclk_100", GATE_IP_PERIL, 2, 0, 0),
 	GATE(CLK_UART1, "uart1", "div_aclk_100", GATE_IP_PERIL, 1, 0, 0),
 	GATE(CLK_UART0, "uart0", "div_aclk_100", GATE_IP_PERIL, 0, 0, 0),
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/samsung/clk-exynos5420.c linux-libre-4.7-gnu/drivers/clk/samsung/clk-exynos5420.c
--- linux-libre-4.6-gnu/drivers/clk/samsung/clk-exynos5420.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/samsung/clk-exynos5420.c	2016-07-24 15:23:50.000000000 -0400
@@ -554,8 +554,8 @@ static struct samsung_mux_clock exynos58
 };
 
 static struct samsung_div_clock exynos5800_div_clks[] __initdata = {
-	DIV(0, "dout_aclk400_wcore", "mout_aclk400_wcore", DIV_TOP0, 16, 3),
-
+	DIV(CLK_DOUT_ACLK400_WCORE, "dout_aclk400_wcore",
+			"mout_aclk400_wcore", DIV_TOP0, 16, 3),
 	DIV(0, "dout_aclk550_cam", "mout_aclk550_cam",
 				DIV_TOP8, 16, 3),
 	DIV(0, "dout_aclkfl1_550_cam", "mout_aclkfl1_550_cam",
@@ -607,8 +607,8 @@ static struct samsung_mux_clock exynos54
 };
 
 static struct samsung_div_clock exynos5420_div_clks[] __initdata = {
-	DIV(0, "dout_aclk400_wcore", "mout_aclk400_wcore_bpll",
-			DIV_TOP0, 16, 3),
+	DIV(CLK_DOUT_ACLK400_WCORE, "dout_aclk400_wcore",
+			"mout_aclk400_wcore_bpll", DIV_TOP0, 16, 3),
 };
 
 static struct samsung_mux_clock exynos5x_mux_clks[] __initdata = {
@@ -785,31 +785,47 @@ static struct samsung_div_clock exynos5x
 	DIV(0, "div_kfc", "mout_kfc", DIV_KFC0, 0, 3),
 	DIV(0, "sclk_kpll", "mout_kpll", DIV_KFC0, 24, 3),
 
-	DIV(0, "dout_aclk400_isp", "mout_aclk400_isp", DIV_TOP0, 0, 3),
-	DIV(0, "dout_aclk400_mscl", "mout_aclk400_mscl", DIV_TOP0, 4, 3),
-	DIV(0, "dout_aclk200", "mout_aclk200", DIV_TOP0, 8, 3),
-	DIV(0, "dout_aclk200_fsys2", "mout_aclk200_fsys2", DIV_TOP0, 12, 3),
-	DIV(0, "dout_aclk100_noc", "mout_aclk100_noc", DIV_TOP0, 20, 3),
-	DIV(0, "dout_pclk200_fsys", "mout_pclk200_fsys", DIV_TOP0, 24, 3),
-	DIV(0, "dout_aclk200_fsys", "mout_aclk200_fsys", DIV_TOP0, 28, 3),
-
-	DIV(0, "dout_aclk333_432_gscl", "mout_aclk333_432_gscl",
-			DIV_TOP1, 0, 3),
-	DIV(0, "dout_aclk333_432_isp", "mout_aclk333_432_isp",
-			DIV_TOP1, 4, 3),
-	DIV(0, "dout_aclk66", "mout_aclk66", DIV_TOP1, 8, 6),
-	DIV(0, "dout_aclk333_432_isp0", "mout_aclk333_432_isp0",
-			DIV_TOP1, 16, 3),
-	DIV(0, "dout_aclk266", "mout_aclk266", DIV_TOP1, 20, 3),
-	DIV(0, "dout_aclk166", "mout_aclk166", DIV_TOP1, 24, 3),
-	DIV(0, "dout_aclk333", "mout_aclk333", DIV_TOP1, 28, 3),
+	DIV(CLK_DOUT_ACLK400_ISP, "dout_aclk400_isp", "mout_aclk400_isp",
+			DIV_TOP0, 0, 3),
+	DIV(CLK_DOUT_ACLK400_MSCL, "dout_aclk400_mscl", "mout_aclk400_mscl",
+			DIV_TOP0, 4, 3),
+	DIV(CLK_DOUT_ACLK200, "dout_aclk200", "mout_aclk200",
+			DIV_TOP0, 8, 3),
+	DIV(CLK_DOUT_ACLK200_FSYS2, "dout_aclk200_fsys2", "mout_aclk200_fsys2",
+			DIV_TOP0, 12, 3),
+	DIV(CLK_DOUT_ACLK100_NOC, "dout_aclk100_noc", "mout_aclk100_noc",
+			DIV_TOP0, 20, 3),
+	DIV(CLK_DOUT_PCLK200_FSYS, "dout_pclk200_fsys", "mout_pclk200_fsys",
+			DIV_TOP0, 24, 3),
+	DIV(CLK_DOUT_ACLK200_FSYS, "dout_aclk200_fsys", "mout_aclk200_fsys",
+			DIV_TOP0, 28, 3),
+	DIV(CLK_DOUT_ACLK333_432_GSCL, "dout_aclk333_432_gscl",
+			"mout_aclk333_432_gscl", DIV_TOP1, 0, 3),
+	DIV(CLK_DOUT_ACLK333_432_ISP, "dout_aclk333_432_isp",
+			"mout_aclk333_432_isp", DIV_TOP1, 4, 3),
+	DIV(CLK_DOUT_ACLK66, "dout_aclk66", "mout_aclk66",
+			DIV_TOP1, 8, 6),
+	DIV(CLK_DOUT_ACLK333_432_ISP0, "dout_aclk333_432_isp0",
+			"mout_aclk333_432_isp0", DIV_TOP1, 16, 3),
+	DIV(CLK_DOUT_ACLK266, "dout_aclk266", "mout_aclk266",
+			DIV_TOP1, 20, 3),
+	DIV(CLK_DOUT_ACLK166, "dout_aclk166", "mout_aclk166",
+			DIV_TOP1, 24, 3),
+	DIV(CLK_DOUT_ACLK333, "dout_aclk333", "mout_aclk333",
+			DIV_TOP1, 28, 3),
 
-	DIV(0, "dout_aclk333_g2d", "mout_aclk333_g2d", DIV_TOP2, 8, 3),
-	DIV(0, "dout_aclk266_g2d", "mout_aclk266_g2d", DIV_TOP2, 12, 3),
-	DIV(0, "dout_aclk_g3d", "mout_aclk_g3d", DIV_TOP2, 16, 3),
-	DIV(0, "dout_aclk300_jpeg", "mout_aclk300_jpeg", DIV_TOP2, 20, 3),
-	DIV(0, "dout_aclk300_disp1", "mout_aclk300_disp1", DIV_TOP2, 24, 3),
-	DIV(0, "dout_aclk300_gscl", "mout_aclk300_gscl", DIV_TOP2, 28, 3),
+	DIV(CLK_DOUT_ACLK333_G2D, "dout_aclk333_g2d", "mout_aclk333_g2d",
+			DIV_TOP2, 8, 3),
+	DIV(CLK_DOUT_ACLK266_G2D, "dout_aclk266_g2d", "mout_aclk266_g2d",
+			DIV_TOP2, 12, 3),
+	DIV(CLK_DOUT_ACLK_G3D, "dout_aclk_g3d", "mout_aclk_g3d", DIV_TOP2,
+			16, 3),
+	DIV(CLK_DOUT_ACLK300_JPEG, "dout_aclk300_jpeg", "mout_aclk300_jpeg",
+			DIV_TOP2, 20, 3),
+	DIV(CLK_DOUT_ACLK300_DISP1, "dout_aclk300_disp1",
+			"mout_aclk300_disp1", DIV_TOP2, 24, 3),
+	DIV(CLK_DOUT_ACLK300_GSCL, "dout_aclk300_gscl", "mout_aclk300_gscl",
+			DIV_TOP2, 28, 3),
 
 	/* DISP1 Block */
 	DIV(0, "dout_fimd1", "mout_fimd1_final", DIV_DISP10, 0, 4),
@@ -817,7 +833,8 @@ static struct samsung_div_clock exynos5x
 	DIV(0, "dout_dp1", "mout_dp1", DIV_DISP10, 24, 4),
 	DIV(CLK_DOUT_PIXEL, "dout_hdmi_pixel", "mout_pixel", DIV_DISP10, 28, 4),
 	DIV(0, "dout_disp1_blk", "aclk200_disp1", DIV2_RATIO0, 16, 2),
-	DIV(0, "dout_aclk400_disp1", "mout_aclk400_disp1", DIV_TOP2, 4, 3),
+	DIV(CLK_DOUT_ACLK400_DISP1, "dout_aclk400_disp1",
+			"mout_aclk400_disp1", DIV_TOP2, 4, 3),
 
 	/* Audio Block */
 	DIV(0, "dout_maudio0", "mout_maudio0", DIV_MAU, 20, 4),
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/sirf/clk-atlas6.c linux-libre-4.7-gnu/drivers/clk/sirf/clk-atlas6.c
--- linux-libre-4.6-gnu/drivers/clk/sirf/clk-atlas6.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/sirf/clk-atlas6.c	2016-07-24 15:23:50.000000000 -0400
@@ -130,10 +130,9 @@ static void __init atlas6_clk_init(struc
 		panic("unable to map clkc registers\n");
 
 	/* These are always available (RTC and 26MHz OSC)*/
-	atlas6_clks[rtc] = clk_register_fixed_rate(NULL, "rtc", NULL,
-		CLK_IS_ROOT, 32768);
-	atlas6_clks[osc] = clk_register_fixed_rate(NULL, "osc", NULL,
-		CLK_IS_ROOT, 26000000);
+	atlas6_clks[rtc] = clk_register_fixed_rate(NULL, "rtc", NULL, 0, 32768);
+	atlas6_clks[osc] = clk_register_fixed_rate(NULL, "osc", NULL, 0,
+						   26000000);
 
 	for (i = pll1; i < maxclk; i++) {
 		atlas6_clks[i] = clk_register(NULL, atlas6_clk_hw_array[i]);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/sirf/clk-prima2.c linux-libre-4.7-gnu/drivers/clk/sirf/clk-prima2.c
--- linux-libre-4.6-gnu/drivers/clk/sirf/clk-prima2.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/sirf/clk-prima2.c	2016-07-24 15:23:50.000000000 -0400
@@ -129,10 +129,9 @@ static void __init prima2_clk_init(struc
 		panic("unable to map clkc registers\n");
 
 	/* These are always available (RTC and 26MHz OSC)*/
-	prima2_clks[rtc] = clk_register_fixed_rate(NULL, "rtc", NULL,
-		CLK_IS_ROOT, 32768);
-	prima2_clks[osc] = clk_register_fixed_rate(NULL, "osc", NULL,
-		CLK_IS_ROOT, 26000000);
+	prima2_clks[rtc] = clk_register_fixed_rate(NULL, "rtc", NULL, 0, 32768);
+	prima2_clks[osc] = clk_register_fixed_rate(NULL, "osc", NULL, 0,
+						   26000000);
 
 	for (i = pll1; i < maxclk; i++) {
 		prima2_clks[i] = clk_register(NULL, prima2_clk_hw_array[i]);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/sunxi/clk-a10-hosc.c linux-libre-4.7-gnu/drivers/clk/sunxi/clk-a10-hosc.c
--- linux-libre-4.6-gnu/drivers/clk/sunxi/clk-a10-hosc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/sunxi/clk-a10-hosc.c	2016-07-24 15:23:50.000000000 -0400
@@ -54,8 +54,7 @@ static void __init sun4i_osc_clk_setup(s
 			NULL, 0,
 			NULL, NULL,
 			&fixed->hw, &clk_fixed_rate_ops,
-			&gate->hw, &clk_gate_ops,
-			CLK_IS_ROOT);
+			&gate->hw, &clk_gate_ops, 0);
 
 	if (IS_ERR(clk))
 		goto err_free_gate;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/sunxi/clk-a10-mod1.c linux-libre-4.7-gnu/drivers/clk/sunxi/clk-a10-mod1.c
--- linux-libre-4.6-gnu/drivers/clk/sunxi/clk-a10-mod1.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/sunxi/clk-a10-mod1.c	2016-07-24 15:23:50.000000000 -0400
@@ -62,7 +62,7 @@ static void __init sun4i_mod1_clk_setup(
 	clk = clk_register_composite(NULL, clk_name, parents, i,
 				     &mux->hw, &clk_mux_ops,
 				     NULL, NULL,
-				     &gate->hw, &clk_gate_ops, 0);
+				     &gate->hw, &clk_gate_ops, CLK_SET_RATE_PARENT);
 	if (IS_ERR(clk))
 		goto err_free_gate;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/sunxi/clk-sun4i-display.c linux-libre-4.7-gnu/drivers/clk/sunxi/clk-sun4i-display.c
--- linux-libre-4.6-gnu/drivers/clk/sunxi/clk-sun4i-display.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/clk/sunxi/clk-sun4i-display.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,264 @@
+/*
+ * Copyright 2015 Maxime Ripard
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/kernel.h>
+#include <linux/of_address.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+struct sun4i_a10_display_clk_data {
+	bool	has_div;
+	u8	num_rst;
+	u8	parents;
+
+	u8	offset_en;
+	u8	offset_div;
+	u8	offset_mux;
+	u8	offset_rst;
+
+	u8	width_div;
+	u8	width_mux;
+
+	u32	flags;
+};
+
+struct reset_data {
+	void __iomem			*reg;
+	spinlock_t			*lock;
+	struct reset_controller_dev	rcdev;
+	u8				offset;
+};
+
+static DEFINE_SPINLOCK(sun4i_a10_display_lock);
+
+static inline struct reset_data *rcdev_to_reset_data(struct reset_controller_dev *rcdev)
+{
+	return container_of(rcdev, struct reset_data, rcdev);
+};
+
+static int sun4i_a10_display_assert(struct reset_controller_dev *rcdev,
+				    unsigned long id)
+{
+	struct reset_data *data = rcdev_to_reset_data(rcdev);
+	unsigned long flags;
+	u32 reg;
+
+	spin_lock_irqsave(data->lock, flags);
+
+	reg = readl(data->reg);
+	writel(reg & ~BIT(data->offset + id), data->reg);
+
+	spin_unlock_irqrestore(data->lock, flags);
+
+	return 0;
+}
+
+static int sun4i_a10_display_deassert(struct reset_controller_dev *rcdev,
+				      unsigned long id)
+{
+	struct reset_data *data = rcdev_to_reset_data(rcdev);
+	unsigned long flags;
+	u32 reg;
+
+	spin_lock_irqsave(data->lock, flags);
+
+	reg = readl(data->reg);
+	writel(reg | BIT(data->offset + id), data->reg);
+
+	spin_unlock_irqrestore(data->lock, flags);
+
+	return 0;
+}
+
+static int sun4i_a10_display_status(struct reset_controller_dev *rcdev,
+				    unsigned long id)
+{
+	struct reset_data *data = rcdev_to_reset_data(rcdev);
+
+	return !(readl(data->reg) & BIT(data->offset + id));
+}
+
+static const struct reset_control_ops sun4i_a10_display_reset_ops = {
+	.assert		= sun4i_a10_display_assert,
+	.deassert	= sun4i_a10_display_deassert,
+	.status		= sun4i_a10_display_status,
+};
+
+static int sun4i_a10_display_reset_xlate(struct reset_controller_dev *rcdev,
+					 const struct of_phandle_args *spec)
+{
+	/* We only have a single reset signal */
+	return 0;
+}
+
+static void __init sun4i_a10_display_init(struct device_node *node,
+					  const struct sun4i_a10_display_clk_data *data)
+{
+	const char *parents[4];
+	const char *clk_name = node->name;
+	struct reset_data *reset_data;
+	struct clk_divider *div = NULL;
+	struct clk_gate *gate;
+	struct resource res;
+	struct clk_mux *mux;
+	void __iomem *reg;
+	struct clk *clk;
+	int ret;
+
+	of_property_read_string(node, "clock-output-names", &clk_name);
+
+	reg = of_io_request_and_map(node, 0, of_node_full_name(node));
+	if (IS_ERR(reg)) {
+		pr_err("%s: Could not map the clock registers\n", clk_name);
+		return;
+	}
+
+	ret = of_clk_parent_fill(node, parents, data->parents);
+	if (ret != data->parents) {
+		pr_err("%s: Could not retrieve the parents\n", clk_name);
+		goto unmap;
+	}
+
+	mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+	if (!mux)
+		goto unmap;
+
+	mux->reg = reg;
+	mux->shift = data->offset_mux;
+	mux->mask = (1 << data->width_mux) - 1;
+	mux->lock = &sun4i_a10_display_lock;
+
+	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+	if (!gate)
+		goto free_mux;
+
+	gate->reg = reg;
+	gate->bit_idx = data->offset_en;
+	gate->lock = &sun4i_a10_display_lock;
+
+	if (data->has_div) {
+		div = kzalloc(sizeof(*div), GFP_KERNEL);
+		if (!div)
+			goto free_gate;
+
+		div->reg = reg;
+		div->shift = data->offset_div;
+		div->width = data->width_div;
+		div->lock = &sun4i_a10_display_lock;
+	}
+
+	clk = clk_register_composite(NULL, clk_name,
+				     parents, data->parents,
+				     &mux->hw, &clk_mux_ops,
+				     data->has_div ? &div->hw : NULL,
+				     data->has_div ? &clk_divider_ops : NULL,
+				     &gate->hw, &clk_gate_ops,
+				     data->flags);
+	if (IS_ERR(clk)) {
+		pr_err("%s: Couldn't register the clock\n", clk_name);
+		goto free_div;
+	}
+
+	ret = of_clk_add_provider(node, of_clk_src_simple_get, clk);
+	if (ret) {
+		pr_err("%s: Couldn't register DT provider\n", clk_name);
+		goto free_clk;
+	}
+
+	if (!data->num_rst)
+		return;
+
+	reset_data = kzalloc(sizeof(*reset_data), GFP_KERNEL);
+	if (!reset_data)
+		goto free_of_clk;
+
+	reset_data->reg = reg;
+	reset_data->offset = data->offset_rst;
+	reset_data->lock = &sun4i_a10_display_lock;
+	reset_data->rcdev.nr_resets = data->num_rst;
+	reset_data->rcdev.ops = &sun4i_a10_display_reset_ops;
+	reset_data->rcdev.of_node = node;
+
+	if (data->num_rst == 1) {
+		reset_data->rcdev.of_reset_n_cells = 0;
+		reset_data->rcdev.of_xlate = &sun4i_a10_display_reset_xlate;
+	} else {
+		reset_data->rcdev.of_reset_n_cells = 1;
+	}
+
+	if (reset_controller_register(&reset_data->rcdev)) {
+		pr_err("%s: Couldn't register the reset controller\n",
+		       clk_name);
+		goto free_reset;
+	}
+
+	return;
+
+free_reset:
+	kfree(reset_data);
+free_of_clk:
+	of_clk_del_provider(node);
+free_clk:
+	clk_unregister_composite(clk);
+free_div:
+	kfree(div);
+free_gate:
+	kfree(gate);
+free_mux:
+	kfree(mux);
+unmap:
+	iounmap(reg);
+	of_address_to_resource(node, 0, &res);
+	release_mem_region(res.start, resource_size(&res));
+}
+
+static const struct sun4i_a10_display_clk_data sun4i_a10_tcon_ch0_data __initconst = {
+	.num_rst	= 2,
+	.parents	= 4,
+	.offset_en	= 31,
+	.offset_rst	= 29,
+	.offset_mux	= 24,
+	.width_mux	= 2,
+	.flags		= CLK_SET_RATE_PARENT,
+};
+
+static void __init sun4i_a10_tcon_ch0_setup(struct device_node *node)
+{
+	sun4i_a10_display_init(node, &sun4i_a10_tcon_ch0_data);
+}
+CLK_OF_DECLARE(sun4i_a10_tcon_ch0, "allwinner,sun4i-a10-tcon-ch0-clk",
+	       sun4i_a10_tcon_ch0_setup);
+
+static const struct sun4i_a10_display_clk_data sun4i_a10_display_data __initconst = {
+	.has_div	= true,
+	.num_rst	= 1,
+	.parents	= 3,
+	.offset_en	= 31,
+	.offset_rst	= 30,
+	.offset_mux	= 24,
+	.offset_div	= 0,
+	.width_mux	= 2,
+	.width_div	= 4,
+};
+
+static void __init sun4i_a10_display_setup(struct device_node *node)
+{
+	sun4i_a10_display_init(node, &sun4i_a10_display_data);
+}
+CLK_OF_DECLARE(sun4i_a10_display, "allwinner,sun4i-a10-display-clk",
+	       sun4i_a10_display_setup);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/sunxi/clk-sun4i-pll3.c linux-libre-4.7-gnu/drivers/clk/sunxi/clk-sun4i-pll3.c
--- linux-libre-4.6-gnu/drivers/clk/sunxi/clk-sun4i-pll3.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/clk/sunxi/clk-sun4i-pll3.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2015 Maxime Ripard
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#define SUN4I_A10_PLL3_GATE_BIT	31
+#define SUN4I_A10_PLL3_DIV_WIDTH	7
+#define SUN4I_A10_PLL3_DIV_SHIFT	0
+
+static DEFINE_SPINLOCK(sun4i_a10_pll3_lock);
+
+static void __init sun4i_a10_pll3_setup(struct device_node *node)
+{
+	const char *clk_name = node->name, *parent;
+	struct clk_multiplier *mult;
+	struct clk_gate *gate;
+	struct resource res;
+	void __iomem *reg;
+	struct clk *clk;
+	int ret;
+
+	of_property_read_string(node, "clock-output-names", &clk_name);
+	parent = of_clk_get_parent_name(node, 0);
+
+	reg = of_io_request_and_map(node, 0, of_node_full_name(node));
+	if (IS_ERR(reg)) {
+		pr_err("%s: Could not map the clock registers\n", clk_name);
+		return;
+	}
+
+	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+	if (!gate)
+		goto err_unmap;
+
+	gate->reg = reg;
+	gate->bit_idx = SUN4I_A10_PLL3_GATE_BIT;
+	gate->lock = &sun4i_a10_pll3_lock;
+
+	mult = kzalloc(sizeof(*mult), GFP_KERNEL);
+	if (!mult)
+		goto err_free_gate;
+
+	mult->reg = reg;
+	mult->shift = SUN4I_A10_PLL3_DIV_SHIFT;
+	mult->width = SUN4I_A10_PLL3_DIV_WIDTH;
+	mult->lock = &sun4i_a10_pll3_lock;
+
+	clk = clk_register_composite(NULL, clk_name,
+				     &parent, 1,
+				     NULL, NULL,
+				     &mult->hw, &clk_multiplier_ops,
+				     &gate->hw, &clk_gate_ops,
+				     0);
+	if (IS_ERR(clk)) {
+		pr_err("%s: Couldn't register the clock\n", clk_name);
+		goto err_free_mult;
+	}
+
+	ret = of_clk_add_provider(node, of_clk_src_simple_get, clk);
+	if (ret) {
+		pr_err("%s: Couldn't register DT provider\n",
+		       clk_name);
+		goto err_clk_unregister;
+	}
+
+	return;
+
+err_clk_unregister:
+	clk_unregister_composite(clk);
+err_free_mult:
+	kfree(mult);
+err_free_gate:
+	kfree(gate);
+err_unmap:
+	iounmap(reg);
+	of_address_to_resource(node, 0, &res);
+	release_mem_region(res.start, resource_size(&res));
+}
+
+CLK_OF_DECLARE(sun4i_a10_pll3, "allwinner,sun4i-a10-pll3-clk",
+	       sun4i_a10_pll3_setup);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/sunxi/clk-sun4i-tcon-ch1.c linux-libre-4.7-gnu/drivers/clk/sunxi/clk-sun4i-tcon-ch1.c
--- linux-libre-4.6-gnu/drivers/clk/sunxi/clk-sun4i-tcon-ch1.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/clk/sunxi/clk-sun4i-tcon-ch1.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,296 @@
+/*
+ * Copyright 2015 Maxime Ripard
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#define TCON_CH1_SCLK2_PARENTS		4
+
+#define TCON_CH1_SCLK2_GATE_BIT		BIT(31)
+#define TCON_CH1_SCLK2_MUX_MASK		3
+#define TCON_CH1_SCLK2_MUX_SHIFT	24
+#define TCON_CH1_SCLK2_DIV_MASK		0xf
+#define TCON_CH1_SCLK2_DIV_SHIFT	0
+
+#define TCON_CH1_SCLK1_GATE_BIT		BIT(15)
+#define TCON_CH1_SCLK1_HALF_BIT		BIT(11)
+
+struct tcon_ch1_clk {
+	struct clk_hw	hw;
+	spinlock_t	lock;
+	void __iomem	*reg;
+};
+
+#define hw_to_tclk(hw)	container_of(hw, struct tcon_ch1_clk, hw)
+
+static void tcon_ch1_disable(struct clk_hw *hw)
+{
+	struct tcon_ch1_clk *tclk = hw_to_tclk(hw);
+	unsigned long flags;
+	u32 reg;
+
+	spin_lock_irqsave(&tclk->lock, flags);
+	reg = readl(tclk->reg);
+	reg &= ~(TCON_CH1_SCLK2_GATE_BIT | TCON_CH1_SCLK1_GATE_BIT);
+	writel(reg, tclk->reg);
+	spin_unlock_irqrestore(&tclk->lock, flags);
+}
+
+static int tcon_ch1_enable(struct clk_hw *hw)
+{
+	struct tcon_ch1_clk *tclk = hw_to_tclk(hw);
+	unsigned long flags;
+	u32 reg;
+
+	spin_lock_irqsave(&tclk->lock, flags);
+	reg = readl(tclk->reg);
+	reg |= TCON_CH1_SCLK2_GATE_BIT | TCON_CH1_SCLK1_GATE_BIT;
+	writel(reg, tclk->reg);
+	spin_unlock_irqrestore(&tclk->lock, flags);
+
+	return 0;
+}
+
+static int tcon_ch1_is_enabled(struct clk_hw *hw)
+{
+	struct tcon_ch1_clk *tclk = hw_to_tclk(hw);
+	u32 reg;
+
+	reg = readl(tclk->reg);
+	return reg & (TCON_CH1_SCLK2_GATE_BIT | TCON_CH1_SCLK1_GATE_BIT);
+}
+
+static u8 tcon_ch1_get_parent(struct clk_hw *hw)
+{
+	struct tcon_ch1_clk *tclk = hw_to_tclk(hw);
+	u32 reg;
+
+	reg = readl(tclk->reg) >> TCON_CH1_SCLK2_MUX_SHIFT;
+	reg &= reg >> TCON_CH1_SCLK2_MUX_MASK;
+
+	return reg;
+}
+
+static int tcon_ch1_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct tcon_ch1_clk *tclk = hw_to_tclk(hw);
+	unsigned long flags;
+	u32 reg;
+
+	spin_lock_irqsave(&tclk->lock, flags);
+	reg = readl(tclk->reg);
+	reg &= ~(TCON_CH1_SCLK2_MUX_MASK << TCON_CH1_SCLK2_MUX_SHIFT);
+	reg |= index << TCON_CH1_SCLK2_MUX_SHIFT;
+	writel(reg, tclk->reg);
+	spin_unlock_irqrestore(&tclk->lock, flags);
+
+	return 0;
+};
+
+static unsigned long tcon_ch1_calc_divider(unsigned long rate,
+					   unsigned long parent_rate,
+					   u8 *div,
+					   bool *half)
+{
+	unsigned long best_rate = 0;
+	u8 best_m = 0, m;
+	bool is_double;
+
+	for (m = 1; m < 16; m++) {
+		u8 d;
+
+		for (d = 1; d < 3; d++) {
+			unsigned long tmp_rate;
+
+			tmp_rate = parent_rate / m / d;
+
+			if (tmp_rate > rate)
+				continue;
+
+			if (!best_rate ||
+			    (rate - tmp_rate) < (rate - best_rate)) {
+				best_rate = tmp_rate;
+				best_m = m;
+				is_double = d;
+			}
+		}
+	}
+
+	if (div && half) {
+		*div = best_m;
+		*half = is_double;
+	}
+
+	return best_rate;
+}
+
+static int tcon_ch1_determine_rate(struct clk_hw *hw,
+				   struct clk_rate_request *req)
+{
+	long best_rate = -EINVAL;
+	int i;
+
+	for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
+		unsigned long parent_rate;
+		unsigned long tmp_rate;
+		struct clk_hw *parent;
+
+		parent = clk_hw_get_parent_by_index(hw, i);
+		if (!parent)
+			continue;
+
+		parent_rate = clk_hw_get_rate(parent);
+
+		tmp_rate = tcon_ch1_calc_divider(req->rate, parent_rate,
+						 NULL, NULL);
+
+		if (best_rate < 0 ||
+		    (req->rate - tmp_rate) < (req->rate - best_rate)) {
+			best_rate = tmp_rate;
+			req->best_parent_rate = parent_rate;
+			req->best_parent_hw = parent;
+		}
+	}
+
+	if (best_rate < 0)
+		return best_rate;
+
+	req->rate = best_rate;
+	return 0;
+}
+
+static unsigned long tcon_ch1_recalc_rate(struct clk_hw *hw,
+					  unsigned long parent_rate)
+{
+	struct tcon_ch1_clk *tclk = hw_to_tclk(hw);
+	u32 reg;
+
+	reg = readl(tclk->reg);
+
+	parent_rate /= (reg & TCON_CH1_SCLK2_DIV_MASK) + 1;
+
+	if (reg & TCON_CH1_SCLK1_HALF_BIT)
+		parent_rate /= 2;
+
+	return parent_rate;
+}
+
+static int tcon_ch1_set_rate(struct clk_hw *hw, unsigned long rate,
+			     unsigned long parent_rate)
+{
+	struct tcon_ch1_clk *tclk = hw_to_tclk(hw);
+	unsigned long flags;
+	bool half;
+	u8 div_m;
+	u32 reg;
+
+	tcon_ch1_calc_divider(rate, parent_rate, &div_m, &half);
+
+	spin_lock_irqsave(&tclk->lock, flags);
+	reg = readl(tclk->reg);
+	reg &= ~(TCON_CH1_SCLK2_DIV_MASK | TCON_CH1_SCLK1_HALF_BIT);
+	reg |= (div_m - 1) & TCON_CH1_SCLK2_DIV_MASK;
+
+	if (half)
+		reg |= TCON_CH1_SCLK1_HALF_BIT;
+
+	writel(reg, tclk->reg);
+	spin_unlock_irqrestore(&tclk->lock, flags);
+
+	return 0;
+}
+
+static const struct clk_ops tcon_ch1_ops = {
+	.disable	= tcon_ch1_disable,
+	.enable		= tcon_ch1_enable,
+	.is_enabled	= tcon_ch1_is_enabled,
+
+	.get_parent	= tcon_ch1_get_parent,
+	.set_parent	= tcon_ch1_set_parent,
+
+	.determine_rate	= tcon_ch1_determine_rate,
+	.recalc_rate	= tcon_ch1_recalc_rate,
+	.set_rate	= tcon_ch1_set_rate,
+};
+
+static void __init tcon_ch1_setup(struct device_node *node)
+{
+	const char *parents[TCON_CH1_SCLK2_PARENTS];
+	const char *clk_name = node->name;
+	struct clk_init_data init;
+	struct tcon_ch1_clk *tclk;
+	struct resource res;
+	struct clk *clk;
+	void __iomem *reg;
+	int ret;
+
+	of_property_read_string(node, "clock-output-names", &clk_name);
+
+	reg = of_io_request_and_map(node, 0, of_node_full_name(node));
+	if (IS_ERR(reg)) {
+		pr_err("%s: Could not map the clock registers\n", clk_name);
+		return;
+	}
+
+	ret = of_clk_parent_fill(node, parents, TCON_CH1_SCLK2_PARENTS);
+	if (ret != TCON_CH1_SCLK2_PARENTS) {
+		pr_err("%s Could not retrieve the parents\n", clk_name);
+		goto err_unmap;
+	}
+
+	tclk = kzalloc(sizeof(*tclk), GFP_KERNEL);
+	if (!tclk)
+		goto err_unmap;
+
+	init.name = clk_name;
+	init.ops = &tcon_ch1_ops;
+	init.parent_names = parents;
+	init.num_parents = TCON_CH1_SCLK2_PARENTS;
+	init.flags = CLK_SET_RATE_PARENT;
+
+	tclk->reg = reg;
+	tclk->hw.init = &init;
+	spin_lock_init(&tclk->lock);
+
+	clk = clk_register(NULL, &tclk->hw);
+	if (IS_ERR(clk)) {
+		pr_err("%s: Couldn't register the clock\n", clk_name);
+		goto err_free_data;
+	}
+
+	ret = of_clk_add_provider(node, of_clk_src_simple_get, clk);
+	if (ret) {
+		pr_err("%s: Couldn't register our clock provider\n", clk_name);
+		goto err_unregister_clk;
+	}
+
+	return;
+
+err_unregister_clk:
+	clk_unregister(clk);
+err_free_data:
+	kfree(tclk);
+err_unmap:
+	iounmap(reg);
+	of_address_to_resource(node, 0, &res);
+	release_mem_region(res.start, resource_size(&res));
+}
+
+CLK_OF_DECLARE(tcon_ch1, "allwinner,sun4i-a10-tcon-ch1-clk",
+	       tcon_ch1_setup);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/sunxi/clk-sun9i-mmc.c linux-libre-4.7-gnu/drivers/clk/sunxi/clk-sun9i-mmc.c
--- linux-libre-4.6-gnu/drivers/clk/sunxi/clk-sun9i-mmc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/sunxi/clk-sun9i-mmc.c	2016-07-24 15:23:50.000000000 -0400
@@ -106,7 +106,7 @@ static int sun9i_a80_mmc_config_clk_prob
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	/* one clock/reset pair per word */
-	count = DIV_ROUND_UP((r->end - r->start + 1), SUN9I_MMC_WIDTH);
+	count = DIV_ROUND_UP((resource_size(r)), SUN9I_MMC_WIDTH);
 	data->membase = devm_ioremap_resource(&pdev->dev, r);
 	if (IS_ERR(data->membase))
 		return PTR_ERR(data->membase);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/sunxi/clk-sunxi.c linux-libre-4.7-gnu/drivers/clk/sunxi/clk-sunxi.c
--- linux-libre-4.6-gnu/drivers/clk/sunxi/clk-sunxi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/sunxi/clk-sunxi.c	2016-07-24 15:23:50.000000000 -0400
@@ -523,21 +523,12 @@ static const struct factors_data sun4i_p
 	.enable = 31,
 	.table = &sun4i_pll5_config,
 	.getter = sun4i_get_pll5_factors,
-	.name = "pll5",
-};
-
-static const struct factors_data sun4i_pll6_data __initconst = {
-	.enable = 31,
-	.table = &sun4i_pll5_config,
-	.getter = sun4i_get_pll5_factors,
-	.name = "pll6",
 };
 
 static const struct factors_data sun6i_a31_pll6_data __initconst = {
 	.enable = 31,
 	.table = &sun6i_a31_pll6_config,
 	.getter = sun6i_a31_get_pll6_factors,
-	.name = "pll6x2",
 };
 
 static const struct factors_data sun5i_a13_ahb_data __initconst = {
@@ -933,7 +924,7 @@ static const struct divs_data pll5_divs_
 };
 
 static const struct divs_data pll6_divs_data __initconst = {
-	.factors = &sun4i_pll6_data,
+	.factors = &sun4i_pll5_data,
 	.ndivs = 4,
 	.div = {
 		{ .shift = 0, .table = pll6_sata_tbl, .gate = 14 }, /* M, SATA */
@@ -975,6 +966,8 @@ static struct clk ** __init sunxi_divs_c
 	struct clk_gate *gate = NULL;
 	struct clk_fixed_factor *fix_factor;
 	struct clk_divider *divider;
+	struct factors_data factors = *data->factors;
+	char *derived_name = NULL;
 	void __iomem *reg;
 	int ndivs = SUNXI_DIVS_MAX_QTY, i = 0;
 	int flags, clkflags;
@@ -983,11 +976,37 @@ static struct clk ** __init sunxi_divs_c
 	if (data->ndivs)
 		ndivs = data->ndivs;
 
+	/* Try to find a name for base factor clock */
+	for (i = 0; i < ndivs; i++) {
+		if (data->div[i].self) {
+			of_property_read_string_index(node, "clock-output-names",
+						      i, &factors.name);
+			break;
+		}
+	}
+	/* If we don't have a .self clk use the first output-name up to '_' */
+	if (factors.name == NULL) {
+		char *endp;
+
+		of_property_read_string_index(node, "clock-output-names",
+						      0, &clk_name);
+		endp = strchr(clk_name, '_');
+		if (endp) {
+			derived_name = kstrndup(clk_name, endp - clk_name,
+						GFP_KERNEL);
+			factors.name = derived_name;
+		} else {
+			factors.name = clk_name;
+		}
+	}
+
 	/* Set up factor clock that we will be dividing */
-	pclk = sunxi_factors_clk_setup(node, data->factors);
+	pclk = sunxi_factors_clk_setup(node, &factors);
 	if (!pclk)
 		return NULL;
+
 	parent = __clk_get_name(pclk);
+	kfree(derived_name);
 
 	reg = of_iomap(node, 0);
 	if (!reg) {
@@ -1127,3 +1146,41 @@ static void __init sun6i_pll6_clk_setup(
 }
 CLK_OF_DECLARE(sun6i_pll6, "allwinner,sun6i-a31-pll6-clk",
 	       sun6i_pll6_clk_setup);
+
+/*
+ * sun6i display
+ *
+ * rate = parent_rate / (m + 1);
+ */
+static void sun6i_display_factors(struct factors_request *req)
+{
+	u8 m;
+
+	if (req->rate > req->parent_rate)
+		req->rate = req->parent_rate;
+
+	m = DIV_ROUND_UP(req->parent_rate, req->rate);
+
+	req->rate = req->parent_rate / m;
+	req->m = m - 1;
+}
+
+static const struct clk_factors_config sun6i_display_config = {
+	.mshift = 0,
+	.mwidth = 4,
+};
+
+static const struct factors_data sun6i_display_data __initconst = {
+	.enable = 31,
+	.mux = 24,
+	.muxmask = BIT(2) | BIT(1) | BIT(0),
+	.table = &sun6i_display_config,
+	.getter = sun6i_display_factors,
+};
+
+static void __init sun6i_display_setup(struct device_node *node)
+{
+	sunxi_factors_clk_setup(node, &sun6i_display_data);
+}
+CLK_OF_DECLARE(sun6i_display, "allwinner,sun6i-a31-display-clk",
+	       sun6i_display_setup);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/sunxi/Makefile linux-libre-4.7-gnu/drivers/clk/sunxi/Makefile
--- linux-libre-4.6-gnu/drivers/clk/sunxi/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/sunxi/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -11,6 +11,9 @@ obj-y += clk-a10-ve.o
 obj-y += clk-a20-gmac.o
 obj-y += clk-mod0.o
 obj-y += clk-simple-gates.o
+obj-y += clk-sun4i-display.o
+obj-y += clk-sun4i-pll3.o
+obj-y += clk-sun4i-tcon-ch1.o
 obj-y += clk-sun8i-bus-gates.o
 obj-y += clk-sun8i-mbus.o
 obj-y += clk-sun9i-core.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/tegra/clk.c linux-libre-4.7-gnu/drivers/clk/tegra/clk.c
--- linux-libre-4.6-gnu/drivers/clk/tegra/clk.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/tegra/clk.c	2016-07-24 15:23:50.000000000 -0400
@@ -84,7 +84,7 @@ static int (*special_reset_assert)(unsig
 static int (*special_reset_deassert)(unsigned long);
 static unsigned int num_special_reset;
 
-static struct tegra_clk_periph_regs periph_regs[] = {
+static const struct tegra_clk_periph_regs periph_regs[] = {
 	[0] = {
 		.enb_reg = CLK_OUT_ENB_L,
 		.enb_set_reg = CLK_OUT_ENB_SET_L,
@@ -182,7 +182,7 @@ static int tegra_clk_rst_deassert(struct
 	return -EINVAL;
 }
 
-struct tegra_clk_periph_regs *get_reg_bank(int clkid)
+const struct tegra_clk_periph_regs *get_reg_bank(int clkid)
 {
 	int reg_bank = clkid / 32;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/tegra/clk-dfll.c linux-libre-4.7-gnu/drivers/clk/tegra/clk-dfll.c
--- linux-libre-4.6-gnu/drivers/clk/tegra/clk-dfll.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/tegra/clk-dfll.c	2016-07-24 15:23:50.000000000 -0400
@@ -55,6 +55,7 @@
 #include <linux/seq_file.h>
 
 #include "clk-dfll.h"
+#include "cvb.h"
 
 /*
  * DFLL control registers - access via dfll_{readl,writel}
@@ -442,8 +443,8 @@ static void dfll_tune_low(struct tegra_d
 {
 	td->tune_range = DFLL_TUNE_LOW;
 
-	dfll_writel(td, td->soc->tune0_low, DFLL_TUNE0);
-	dfll_writel(td, td->soc->tune1, DFLL_TUNE1);
+	dfll_writel(td, td->soc->cvb->cpu_dfll_data.tune0_low, DFLL_TUNE0);
+	dfll_writel(td, td->soc->cvb->cpu_dfll_data.tune1, DFLL_TUNE1);
 	dfll_wmb(td);
 
 	if (td->soc->set_clock_trimmers_low)
@@ -1449,7 +1450,7 @@ static int dfll_build_i2c_lut(struct teg
 	}
 	v_max = dev_pm_opp_get_voltage(opp);
 
-	v = td->soc->min_millivolts * 1000;
+	v = td->soc->cvb->min_millivolts * 1000;
 	lut = find_vdd_map_entry_exact(td, v);
 	if (lut < 0)
 		goto out;
@@ -1461,7 +1462,7 @@ static int dfll_build_i2c_lut(struct teg
 			break;
 		v_opp = dev_pm_opp_get_voltage(opp);
 
-		if (v_opp <= td->soc->min_millivolts * 1000)
+		if (v_opp <= td->soc->cvb->min_millivolts * 1000)
 			td->dvco_rate_min = dev_pm_opp_get_freq(opp);
 
 		for (;;) {
@@ -1490,7 +1491,7 @@ static int dfll_build_i2c_lut(struct teg
 
 	if (!td->dvco_rate_min)
 		dev_err(td->dev, "no opp above DFLL minimum voltage %d mV\n",
-			td->soc->min_millivolts);
+			td->soc->cvb->min_millivolts);
 	else
 		ret = 0;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/tegra/clk-dfll.h linux-libre-4.7-gnu/drivers/clk/tegra/clk-dfll.h
--- linux-libre-4.6-gnu/drivers/clk/tegra/clk-dfll.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/tegra/clk-dfll.h	2016-07-24 15:23:50.000000000 -0400
@@ -24,22 +24,18 @@
 
 /**
  * struct tegra_dfll_soc_data - SoC-specific hooks/integration for the DFLL driver
- * @opp_dev: struct device * that holds the OPP table for the DFLL
- * @min_millivolts: minimum voltage (in mV) that the DFLL can operate
- * @tune0_low: DFLL tuning register 0 (low voltage range)
- * @tune0_high: DFLL tuning register 0 (high voltage range)
- * @tune1: DFLL tuning register 1
- * @assert_dvco_reset: fn ptr to place the DVCO in reset
- * @deassert_dvco_reset: fn ptr to release the DVCO reset
- * @set_clock_trimmers_high: fn ptr to tune clock trimmers for high voltage
- * @set_clock_trimmers_low: fn ptr to tune clock trimmers for low voltage
+ * @dev: struct device * that holds the OPP table for the DFLL
+ * @max_freq: maximum frequency supported on this SoC
+ * @cvb: CPU frequency table for this SoC
+ * @init_clock_trimmers: callback to initialize clock trimmers
+ * @set_clock_trimmers_high: callback to tune clock trimmers for high voltage
+ * @set_clock_trimmers_low: callback to tune clock trimmers for low voltage
  */
 struct tegra_dfll_soc_data {
 	struct device *dev;
-	unsigned int min_millivolts;
-	u32 tune0_low;
-	u32 tune0_high;
-	u32 tune1;
+	unsigned long max_freq;
+	const struct cvb_table *cvb;
+
 	void (*init_clock_trimmers)(void);
 	void (*set_clock_trimmers_high)(void);
 	void (*set_clock_trimmers_low)(void);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/tegra/clk.h linux-libre-4.7-gnu/drivers/clk/tegra/clk.h
--- linux-libre-4.6-gnu/drivers/clk/tegra/clk.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/tegra/clk.h	2016-07-24 15:23:50.000000000 -0400
@@ -386,6 +386,12 @@ struct clk *tegra_clk_register_pllre(con
 			   struct tegra_clk_pll_params *pll_params,
 			   spinlock_t *lock, unsigned long parent_rate);
 
+struct clk *tegra_clk_register_pllre_tegra210(const char *name,
+			   const char *parent_name, void __iomem *clk_base,
+			   void __iomem *pmc, unsigned long flags,
+			   struct tegra_clk_pll_params *pll_params,
+			   spinlock_t *lock, unsigned long parent_rate);
+
 struct clk *tegra_clk_register_plle_tegra114(const char *name,
 				const char *parent_name,
 				void __iomem *clk_base, unsigned long flags,
@@ -496,7 +502,7 @@ struct tegra_clk_periph_gate {
 	u8			flags;
 	int			clk_num;
 	int			*enable_refcnt;
-	struct tegra_clk_periph_regs	*regs;
+	const struct tegra_clk_periph_regs *regs;
 };
 
 #define to_clk_periph_gate(_hw)					\
@@ -516,6 +522,23 @@ struct clk *tegra_clk_register_periph_ga
 		const char *parent_name, u8 gate_flags, void __iomem *clk_base,
 		unsigned long flags, int clk_num, int *enable_refcnt);
 
+struct tegra_clk_periph_fixed {
+	struct clk_hw hw;
+	void __iomem *base;
+	const struct tegra_clk_periph_regs *regs;
+	unsigned int mul;
+	unsigned int div;
+	unsigned int num;
+};
+
+struct clk *tegra_clk_register_periph_fixed(const char *name,
+					    const char *parent,
+					    unsigned long flags,
+					    void __iomem *base,
+					    unsigned int mul,
+					    unsigned int div,
+					    unsigned int num);
+
 /**
  * struct clk-periph - peripheral clock
  *
@@ -716,7 +739,7 @@ void tegra_init_from_table(struct tegra_
 void tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list,
 		struct clk *clks[], int clk_max);
 
-struct tegra_clk_periph_regs *get_reg_bank(int clkid);
+const struct tegra_clk_periph_regs *get_reg_bank(int clkid);
 struct clk **tegra_clk_init(void __iomem *clk_base, int num, int periph_banks);
 
 struct clk **tegra_lookup_dt_id(int clk_id, struct tegra_clk *tegra_clk);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/tegra/clk-id.h linux-libre-4.7-gnu/drivers/clk/tegra/clk-id.h
--- linux-libre-4.6-gnu/drivers/clk/tegra/clk-id.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/tegra/clk-id.h	2016-07-24 15:23:50.000000000 -0400
@@ -71,6 +71,7 @@ enum clk_id {
 	tegra_clk_disp2_8,
 	tegra_clk_dp2,
 	tegra_clk_dpaux,
+	tegra_clk_dpaux1,
 	tegra_clk_dsialp,
 	tegra_clk_dsia_mux,
 	tegra_clk_dsiblp,
@@ -306,6 +307,7 @@ enum clk_id {
 	tegra_clk_xusb_ss_div2,
 	tegra_clk_xusb_ssp_src,
 	tegra_clk_sclk_mux,
+	tegra_clk_sor_safe,
 	tegra_clk_max,
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/tegra/clk-periph.c linux-libre-4.7-gnu/drivers/clk/tegra/clk-periph.c
--- linux-libre-4.6-gnu/drivers/clk/tegra/clk-periph.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/tegra/clk-periph.c	2016-07-24 15:23:50.000000000 -0400
@@ -145,7 +145,7 @@ static struct clk *_tegra_clk_register_p
 {
 	struct clk *clk;
 	struct clk_init_data init;
-	struct tegra_clk_periph_regs *bank;
+	const struct tegra_clk_periph_regs *bank;
 	bool div = !(periph->gate.flags & TEGRA_PERIPH_NO_DIV);
 
 	if (periph->gate.flags & TEGRA_PERIPH_NO_DIV) {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/tegra/clk-periph-fixed.c linux-libre-4.7-gnu/drivers/clk/tegra/clk-periph-fixed.c
--- linux-libre-4.6-gnu/drivers/clk/tegra/clk-periph-fixed.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/clk/tegra/clk-periph-fixed.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2015, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk-provider.h>
+
+#include "clk.h"
+
+static inline struct tegra_clk_periph_fixed *
+to_tegra_clk_periph_fixed(struct clk_hw *hw)
+{
+	return container_of(hw, struct tegra_clk_periph_fixed, hw);
+}
+
+static int tegra_clk_periph_fixed_is_enabled(struct clk_hw *hw)
+{
+	struct tegra_clk_periph_fixed *fixed = to_tegra_clk_periph_fixed(hw);
+	u32 mask = 1 << (fixed->num % 32), value;
+
+	value = readl(fixed->base + fixed->regs->enb_reg);
+	if (value & mask) {
+		value = readl(fixed->base + fixed->regs->rst_reg);
+		if ((value & mask) == 0)
+			return 1;
+	}
+
+	return 0;
+}
+
+static int tegra_clk_periph_fixed_enable(struct clk_hw *hw)
+{
+	struct tegra_clk_periph_fixed *fixed = to_tegra_clk_periph_fixed(hw);
+	u32 mask = 1 << (fixed->num % 32);
+
+	writel(mask, fixed->base + fixed->regs->enb_set_reg);
+
+	return 0;
+}
+
+static void tegra_clk_periph_fixed_disable(struct clk_hw *hw)
+{
+	struct tegra_clk_periph_fixed *fixed = to_tegra_clk_periph_fixed(hw);
+	u32 mask = 1 << (fixed->num % 32);
+
+	writel(mask, fixed->base + fixed->regs->enb_clr_reg);
+}
+
+static unsigned long
+tegra_clk_periph_fixed_recalc_rate(struct clk_hw *hw,
+				   unsigned long parent_rate)
+{
+	struct tegra_clk_periph_fixed *fixed = to_tegra_clk_periph_fixed(hw);
+	unsigned long long rate;
+
+	rate = (unsigned long long)parent_rate * fixed->mul;
+	do_div(rate, fixed->div);
+
+	return (unsigned long)rate;
+}
+
+static const struct clk_ops tegra_clk_periph_fixed_ops = {
+	.is_enabled = tegra_clk_periph_fixed_is_enabled,
+	.enable = tegra_clk_periph_fixed_enable,
+	.disable = tegra_clk_periph_fixed_disable,
+	.recalc_rate = tegra_clk_periph_fixed_recalc_rate,
+};
+
+struct clk *tegra_clk_register_periph_fixed(const char *name,
+					    const char *parent,
+					    unsigned long flags,
+					    void __iomem *base,
+					    unsigned int mul,
+					    unsigned int div,
+					    unsigned int num)
+{
+	const struct tegra_clk_periph_regs *regs;
+	struct tegra_clk_periph_fixed *fixed;
+	struct clk_init_data init;
+	struct clk *clk;
+
+	regs = get_reg_bank(num);
+	if (!regs)
+		return ERR_PTR(-EINVAL);
+
+	fixed = kzalloc(sizeof(*fixed), GFP_KERNEL);
+	if (!fixed)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.flags = flags;
+	init.parent_names = parent ? &parent : NULL;
+	init.num_parents = parent ? 1 : 0;
+	init.ops = &tegra_clk_periph_fixed_ops;
+
+	fixed->base = base;
+	fixed->regs = regs;
+	fixed->mul = mul;
+	fixed->div = div;
+	fixed->num = num;
+
+	fixed->hw.init = &init;
+
+	clk = clk_register(NULL, &fixed->hw);
+	if (IS_ERR(clk))
+		kfree(fixed);
+
+	return clk;
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/tegra/clk-periph-gate.c linux-libre-4.7-gnu/drivers/clk/tegra/clk-periph-gate.c
--- linux-libre-4.6-gnu/drivers/clk/tegra/clk-periph-gate.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/tegra/clk-periph-gate.c	2016-07-24 15:23:50.000000000 -0400
@@ -134,7 +134,7 @@ struct clk *tegra_clk_register_periph_ga
 	struct tegra_clk_periph_gate *gate;
 	struct clk *clk;
 	struct clk_init_data init;
-	struct tegra_clk_periph_regs *pregs;
+	const struct tegra_clk_periph_regs *pregs;
 
 	pregs = get_reg_bank(clk_num);
 	if (!pregs)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/tegra/clk-pll.c linux-libre-4.7-gnu/drivers/clk/tegra/clk-pll.c
--- linux-libre-4.6-gnu/drivers/clk/tegra/clk-pll.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/tegra/clk-pll.c	2016-07-24 15:23:50.000000000 -0400
@@ -2013,6 +2013,52 @@ struct clk *tegra_clk_register_pllss(con
 #endif
 
 #if defined(CONFIG_ARCH_TEGRA_210_SOC)
+struct clk *tegra_clk_register_pllre_tegra210(const char *name,
+			  const char *parent_name, void __iomem *clk_base,
+			  void __iomem *pmc, unsigned long flags,
+			  struct tegra_clk_pll_params *pll_params,
+			  spinlock_t *lock, unsigned long parent_rate)
+{
+	u32 val;
+	struct tegra_clk_pll *pll;
+	struct clk *clk;
+
+	pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);
+
+	if (pll_params->adjust_vco)
+		pll_params->vco_min = pll_params->adjust_vco(pll_params,
+							     parent_rate);
+
+	pll = _tegra_init_pll(clk_base, pmc, pll_params, lock);
+	if (IS_ERR(pll))
+		return ERR_CAST(pll);
+
+	/* program minimum rate by default */
+
+	val = pll_readl_base(pll);
+	if (val & PLL_BASE_ENABLE)
+		WARN_ON(readl_relaxed(clk_base + pll_params->iddq_reg) &
+				BIT(pll_params->iddq_bit_idx));
+	else {
+		val = 0x4 << divm_shift(pll);
+		val |= 0x41 << divn_shift(pll);
+		pll_writel_base(val, pll);
+	}
+
+	/* disable lock override */
+
+	val = pll_readl_misc(pll);
+	val &= ~BIT(29);
+	pll_writel_misc(val, pll);
+
+	clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
+				      &tegra_clk_pllre_ops);
+	if (IS_ERR(clk))
+		kfree(pll);
+
+	return clk;
+}
+
 static int clk_plle_tegra210_enable(struct clk_hw *hw)
 {
 	struct tegra_clk_pll *pll = to_clk_pll(hw);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/tegra/clk-tegra114.c linux-libre-4.7-gnu/drivers/clk/tegra/clk-tegra114.c
--- linux-libre-4.6-gnu/drivers/clk/tegra/clk-tegra114.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/tegra/clk-tegra114.c	2016-07-24 15:23:50.000000000 -0400
@@ -743,7 +743,6 @@ static struct tegra_clk tegra114_clks[te
 	[tegra_clk_csi] = { .dt_id = TEGRA114_CLK_CSI, .present = true },
 	[tegra_clk_i2c2] = { .dt_id = TEGRA114_CLK_I2C2, .present = true },
 	[tegra_clk_uartc] = { .dt_id = TEGRA114_CLK_UARTC, .present = true },
-	[tegra_clk_mipi_cal] = { .dt_id = TEGRA114_CLK_MIPI_CAL, .present = true },
 	[tegra_clk_emc] = { .dt_id = TEGRA114_CLK_EMC, .present = true },
 	[tegra_clk_usb2] = { .dt_id = TEGRA114_CLK_USB2, .present = true },
 	[tegra_clk_usb3] = { .dt_id = TEGRA114_CLK_USB3, .present = true },
@@ -1237,6 +1236,11 @@ static __init void tegra114_periph_clk_i
 				    &emc_lock);
 	clks[TEGRA114_CLK_MC] = clk;
 
+	clk = tegra_clk_register_periph_gate("mipi-cal", "clk_m", 0, clk_base,
+					     CLK_SET_RATE_PARENT, 56,
+					     periph_clk_enb_refcnt);
+	clks[TEGRA114_CLK_MIPI_CAL] = clk;
+
 	for (i = 0; i < ARRAY_SIZE(tegra_periph_clk_list); i++) {
 		data = &tegra_periph_clk_list[i];
 		clk = tegra_clk_register_periph(data->name,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/tegra/clk-tegra124.c linux-libre-4.7-gnu/drivers/clk/tegra/clk-tegra124.c
--- linux-libre-4.6-gnu/drivers/clk/tegra/clk-tegra124.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/tegra/clk-tegra124.c	2016-07-24 15:23:50.000000000 -0400
@@ -1155,6 +1155,10 @@ static __init void tegra124_periph_clk_i
 					1, 2);
 	clks[TEGRA124_CLK_XUSB_SS_DIV2] = clk;
 
+	clk = tegra_clk_register_periph_fixed("dpaux", "pll_p", 0, clk_base,
+					      1, 17, 181);
+	clks[TEGRA124_CLK_DPAUX] = clk;
+
 	clk = clk_register_gate(NULL, "pll_d_dsi_out", "pll_d_out0", 0,
 				clk_base + PLLD_MISC, 30, 0, &pll_d_lock);
 	clks[TEGRA124_CLK_PLL_D_DSI_OUT] = clk;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c linux-libre-4.7-gnu/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c
--- linux-libre-4.6-gnu/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c	2016-07-24 15:23:50.000000000 -0400
@@ -47,32 +47,32 @@ static const struct cvb_table tegra124_c
 		},
 		.speedo_scale = 100,
 		.voltage_scale = 1000,
-		.cvb_table = {
-			{204000000UL,   {1112619, -29295, 402} },
-			{306000000UL,	{1150460, -30585, 402} },
-			{408000000UL,	{1190122, -31865, 402} },
-			{510000000UL,	{1231606, -33155, 402} },
-			{612000000UL,	{1274912, -34435, 402} },
-			{714000000UL,	{1320040, -35725, 402} },
-			{816000000UL,	{1366990, -37005, 402} },
-			{918000000UL,	{1415762, -38295, 402} },
-			{1020000000UL,	{1466355, -39575, 402} },
-			{1122000000UL,	{1518771, -40865, 402} },
-			{1224000000UL,	{1573009, -42145, 402} },
-			{1326000000UL,	{1629068, -43435, 402} },
-			{1428000000UL,	{1686950, -44715, 402} },
-			{1530000000UL,	{1746653, -46005, 402} },
-			{1632000000UL,	{1808179, -47285, 402} },
-			{1734000000UL,	{1871526, -48575, 402} },
-			{1836000000UL,	{1936696, -49855, 402} },
-			{1938000000UL,	{2003687, -51145, 402} },
-			{2014500000UL,	{2054787, -52095, 402} },
-			{2116500000UL,	{2124957, -53385, 402} },
-			{2218500000UL,	{2196950, -54665, 402} },
-			{2320500000UL,	{2270765, -55955, 402} },
-			{2422500000UL,	{2346401, -57235, 402} },
-			{2524500000UL,	{2437299, -58535, 402} },
-			{0,		{      0,      0,   0} },
+		.entries = {
+			{  204000000UL, { 1112619, -29295, 402 } },
+			{  306000000UL, { 1150460, -30585, 402 } },
+			{  408000000UL, { 1190122, -31865, 402 } },
+			{  510000000UL, { 1231606, -33155, 402 } },
+			{  612000000UL, { 1274912, -34435, 402 } },
+			{  714000000UL, { 1320040, -35725, 402 } },
+			{  816000000UL, { 1366990, -37005, 402 } },
+			{  918000000UL, { 1415762, -38295, 402 } },
+			{ 1020000000UL, { 1466355, -39575, 402 } },
+			{ 1122000000UL, { 1518771, -40865, 402 } },
+			{ 1224000000UL, { 1573009, -42145, 402 } },
+			{ 1326000000UL, { 1629068, -43435, 402 } },
+			{ 1428000000UL, { 1686950, -44715, 402 } },
+			{ 1530000000UL, { 1746653, -46005, 402 } },
+			{ 1632000000UL, { 1808179, -47285, 402 } },
+			{ 1734000000UL, { 1871526, -48575, 402 } },
+			{ 1836000000UL, { 1936696, -49855, 402 } },
+			{ 1938000000UL, { 2003687, -51145, 402 } },
+			{ 2014500000UL, { 2054787, -52095, 402 } },
+			{ 2116500000UL, { 2124957, -53385, 402 } },
+			{ 2218500000UL, { 2196950, -54665, 402 } },
+			{ 2320500000UL, { 2270765, -55955, 402 } },
+			{ 2422500000UL, { 2346401, -57235, 402 } },
+			{ 2524500000UL, { 2437299, -58535, 402 } },
+			{          0UL, {       0,      0,   0 } },
 		},
 		.cpu_dfll_data = {
 			.tune0_low = 0x005020ff,
@@ -84,9 +84,8 @@ static const struct cvb_table tegra124_c
 
 static int tegra124_dfll_fcpu_probe(struct platform_device *pdev)
 {
-	int process_id, speedo_id, speedo_value;
+	int process_id, speedo_id, speedo_value, err;
 	struct tegra_dfll_soc_data *soc;
-	const struct cvb_table *cvb;
 
 	process_id = tegra_sku_info.cpu_process_id;
 	speedo_id = tegra_sku_info.cpu_speedo_id;
@@ -108,23 +107,41 @@ static int tegra124_dfll_fcpu_probe(stru
 		return -ENODEV;
 	}
 
-	cvb = tegra_cvb_build_opp_table(tegra124_cpu_cvb_tables,
-					ARRAY_SIZE(tegra124_cpu_cvb_tables),
-					process_id, speedo_id, speedo_value,
-					cpu_max_freq_table[speedo_id],
-					soc->dev);
-	if (IS_ERR(cvb)) {
-		dev_err(&pdev->dev, "couldn't build OPP table: %ld\n",
-			PTR_ERR(cvb));
-		return PTR_ERR(cvb);
+	soc->max_freq = cpu_max_freq_table[speedo_id];
+
+	soc->cvb = tegra_cvb_add_opp_table(soc->dev, tegra124_cpu_cvb_tables,
+					   ARRAY_SIZE(tegra124_cpu_cvb_tables),
+					   process_id, speedo_id, speedo_value,
+					   soc->max_freq);
+	if (IS_ERR(soc->cvb)) {
+		dev_err(&pdev->dev, "couldn't add OPP table: %ld\n",
+			PTR_ERR(soc->cvb));
+		return PTR_ERR(soc->cvb);
 	}
 
-	soc->min_millivolts = cvb->min_millivolts;
-	soc->tune0_low = cvb->cpu_dfll_data.tune0_low;
-	soc->tune0_high = cvb->cpu_dfll_data.tune0_high;
-	soc->tune1 = cvb->cpu_dfll_data.tune1;
+	err = tegra_dfll_register(pdev, soc);
+	if (err < 0) {
+		tegra_cvb_remove_opp_table(soc->dev, soc->cvb, soc->max_freq);
+		return err;
+	}
 
-	return tegra_dfll_register(pdev, soc);
+	platform_set_drvdata(pdev, soc);
+
+	return 0;
+}
+
+static int tegra124_dfll_fcpu_remove(struct platform_device *pdev)
+{
+	struct tegra_dfll_soc_data *soc = platform_get_drvdata(pdev);
+	int err;
+
+	err = tegra_dfll_unregister(pdev);
+	if (err < 0)
+		dev_err(&pdev->dev, "failed to unregister DFLL: %d\n", err);
+
+	tegra_cvb_remove_opp_table(soc->dev, soc->cvb, soc->max_freq);
+
+	return 0;
 }
 
 static const struct of_device_id tegra124_dfll_fcpu_of_match[] = {
@@ -140,7 +157,7 @@ static const struct dev_pm_ops tegra124_
 
 static struct platform_driver tegra124_dfll_fcpu_driver = {
 	.probe = tegra124_dfll_fcpu_probe,
-	.remove = tegra_dfll_unregister,
+	.remove = tegra124_dfll_fcpu_remove,
 	.driver = {
 		.name = "tegra124-dfll",
 		.of_match_table = tegra124_dfll_fcpu_of_match,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/tegra/clk-tegra20.c linux-libre-4.7-gnu/drivers/clk/tegra/clk-tegra20.c
--- linux-libre-4.6-gnu/drivers/clk/tegra/clk-tegra20.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/tegra/clk-tegra20.c	2016-07-24 15:23:50.000000000 -0400
@@ -623,7 +623,7 @@ static unsigned int tegra20_get_pll_ref_
 	case OSC_CTRL_PLL_REF_DIV_4:
 		return 4;
 	default:
-		pr_err("Invalied pll ref divider %d\n", pll_ref_div);
+		pr_err("Invalid pll ref divider %d\n", pll_ref_div);
 		BUG();
 	}
 	return 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/tegra/clk-tegra210.c linux-libre-4.7-gnu/drivers/clk/tegra/clk-tegra210.c
--- linux-libre-4.6-gnu/drivers/clk/tegra/clk-tegra210.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/tegra/clk-tegra210.c	2016-07-24 15:23:50.000000000 -0400
@@ -92,6 +92,7 @@
 #define PLLE_AUX 0x48c
 #define PLLRE_BASE 0x4c4
 #define PLLRE_MISC0 0x4c8
+#define PLLRE_OUT1 0x4cc
 #define PLLDP_BASE 0x590
 #define PLLDP_MISC 0x594
 
@@ -175,6 +176,19 @@
 #define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN BIT(14)
 #define UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN BIT(12)
 
+#define SATA_PLL_CFG0				0x490
+#define SATA_PLL_CFG0_PADPLL_RESET_SWCTL	BIT(0)
+#define SATA_PLL_CFG0_PADPLL_USE_LOCKDET	BIT(2)
+#define SATA_PLL_CFG0_PADPLL_SLEEP_IDDQ		BIT(13)
+#define SATA_PLL_CFG0_SEQ_ENABLE		BIT(24)
+
+#define XUSBIO_PLL_CFG0				0x51c
+#define XUSBIO_PLL_CFG0_PADPLL_RESET_SWCTL	BIT(0)
+#define XUSBIO_PLL_CFG0_CLK_ENABLE_SWCTL	BIT(2)
+#define XUSBIO_PLL_CFG0_PADPLL_USE_LOCKDET	BIT(6)
+#define XUSBIO_PLL_CFG0_PADPLL_SLEEP_IDDQ	BIT(13)
+#define XUSBIO_PLL_CFG0_SEQ_ENABLE		BIT(24)
+
 #define UTMIPLL_HW_PWRDN_CFG0			0x52c
 #define UTMIPLL_HW_PWRDN_CFG0_UTMIPLL_LOCK	BIT(31)
 #define UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE	BIT(25)
@@ -416,6 +430,51 @@ static const char *mux_pllmcp_clkm[] = {
 #define PLLU_MISC0_WRITE_MASK		0xbfffffff
 #define PLLU_MISC1_WRITE_MASK		0x00000007
 
+void tegra210_xusb_pll_hw_control_enable(void)
+{
+	u32 val;
+
+	val = readl_relaxed(clk_base + XUSBIO_PLL_CFG0);
+	val &= ~(XUSBIO_PLL_CFG0_CLK_ENABLE_SWCTL |
+		 XUSBIO_PLL_CFG0_PADPLL_RESET_SWCTL);
+	val |= XUSBIO_PLL_CFG0_PADPLL_USE_LOCKDET |
+	       XUSBIO_PLL_CFG0_PADPLL_SLEEP_IDDQ;
+	writel_relaxed(val, clk_base + XUSBIO_PLL_CFG0);
+}
+EXPORT_SYMBOL_GPL(tegra210_xusb_pll_hw_control_enable);
+
+void tegra210_xusb_pll_hw_sequence_start(void)
+{
+	u32 val;
+
+	val = readl_relaxed(clk_base + XUSBIO_PLL_CFG0);
+	val |= XUSBIO_PLL_CFG0_SEQ_ENABLE;
+	writel_relaxed(val, clk_base + XUSBIO_PLL_CFG0);
+}
+EXPORT_SYMBOL_GPL(tegra210_xusb_pll_hw_sequence_start);
+
+void tegra210_sata_pll_hw_control_enable(void)
+{
+	u32 val;
+
+	val = readl_relaxed(clk_base + SATA_PLL_CFG0);
+	val &= ~SATA_PLL_CFG0_PADPLL_RESET_SWCTL;
+	val |= SATA_PLL_CFG0_PADPLL_USE_LOCKDET |
+	       SATA_PLL_CFG0_PADPLL_SLEEP_IDDQ;
+	writel_relaxed(val, clk_base + SATA_PLL_CFG0);
+}
+EXPORT_SYMBOL_GPL(tegra210_sata_pll_hw_control_enable);
+
+void tegra210_sata_pll_hw_sequence_start(void)
+{
+	u32 val;
+
+	val = readl_relaxed(clk_base + SATA_PLL_CFG0);
+	val |= SATA_PLL_CFG0_SEQ_ENABLE;
+	writel_relaxed(val, clk_base + SATA_PLL_CFG0);
+}
+EXPORT_SYMBOL_GPL(tegra210_sata_pll_hw_sequence_start);
+
 static inline void _pll_misc_chk_default(void __iomem *base,
 					struct tegra_clk_pll_params *params,
 					u8 misc_num, u32 default_val, u32 mask)
@@ -1162,7 +1221,7 @@ static int tegra210_pll_fixed_mdiv_cfg(s
 		p = rate >= params->vco_min ? 1 : -EINVAL;
 	}
 
-	if (IS_ERR_VALUE(p))
+	if (p < 0)
 		return -EINVAL;
 
 	cfg->m = tegra_pll_get_fixed_mdiv(hw, input_rate);
@@ -2092,6 +2151,7 @@ static struct tegra_clk tegra210_clks[te
 	[tegra_clk_clk72Mhz_8] = { .dt_id = TEGRA210_CLK_CLK72MHZ, .present = true },
 	[tegra_clk_vic03_8] = { .dt_id = TEGRA210_CLK_VIC03, .present = true },
 	[tegra_clk_dpaux] = { .dt_id = TEGRA210_CLK_DPAUX, .present = true },
+	[tegra_clk_dpaux1] = { .dt_id = TEGRA210_CLK_DPAUX1, .present = true },
 	[tegra_clk_sor0] = { .dt_id = TEGRA210_CLK_SOR0, .present = true },
 	[tegra_clk_sor0_lvds] = { .dt_id = TEGRA210_CLK_SOR0_LVDS, .present = true },
 	[tegra_clk_gpu] = { .dt_id = TEGRA210_CLK_GPU, .present = true },
@@ -2403,6 +2463,18 @@ static __init void tegra210_periph_clk_i
 					1, 2);
 	clks[TEGRA210_CLK_XUSB_SS_DIV2] = clk;
 
+	clk = tegra_clk_register_periph_fixed("dpaux", "pll_p", 0, clk_base,
+					      1, 17, 181);
+	clks[TEGRA210_CLK_DPAUX] = clk;
+
+	clk = tegra_clk_register_periph_fixed("dpaux1", "pll_p", 0, clk_base,
+					      1, 17, 207);
+	clks[TEGRA210_CLK_DPAUX1] = clk;
+
+	clk = tegra_clk_register_periph_fixed("sor_safe", "pll_p", 0, clk_base,
+					      1, 17, 222);
+	clks[TEGRA210_CLK_SOR_SAFE] = clk;
+
 	/* pll_d_dsi_out */
 	clk = clk_register_gate(NULL, "pll_d_dsi_out", "pll_d_out0", 0,
 				clk_base + PLLD_MISC0, 21, 0, &pll_d_lock);
@@ -2582,8 +2654,10 @@ static void __init tegra210_pll_init(voi
 	clks[TEGRA210_CLK_PLL_D_OUT0] = clk;
 
 	/* PLLRE */
-	clk = tegra_clk_register_pllre("pll_re_vco", "pll_ref", clk_base, pmc,
-			     0, &pll_re_vco_params, &pll_re_lock, pll_ref_freq);
+	clk = tegra_clk_register_pllre_tegra210("pll_re_vco", "pll_ref",
+						clk_base, pmc, 0,
+						&pll_re_vco_params,
+						&pll_re_lock, pll_ref_freq);
 	clk_register_clkdev(clk, "pll_re_vco", NULL);
 	clks[TEGRA210_CLK_PLL_RE_VCO] = clk;
 
@@ -2593,6 +2667,15 @@ static void __init tegra210_pll_init(voi
 	clk_register_clkdev(clk, "pll_re_out", NULL);
 	clks[TEGRA210_CLK_PLL_RE_OUT] = clk;
 
+	clk = tegra_clk_register_divider("pll_re_out1_div", "pll_re_vco",
+					 clk_base + PLLRE_OUT1, 0,
+					 TEGRA_DIVIDER_ROUND_UP,
+					 8, 8, 1, NULL);
+	clk = tegra_clk_register_pll_out("pll_re_out1", "pll_re_out1_div",
+					 clk_base + PLLRE_OUT1, 1, 0,
+					 CLK_SET_RATE_PARENT, 0, NULL);
+	clks[TEGRA210_CLK_PLL_RE_OUT1] = clk;
+
 	/* PLLE */
 	clk = tegra_clk_register_plle_tegra210("pll_e", "pll_ref",
 				      clk_base, 0, &pll_e_params, NULL);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/tegra/clk-tegra30.c linux-libre-4.7-gnu/drivers/clk/tegra/clk-tegra30.c
--- linux-libre-4.6-gnu/drivers/clk/tegra/clk-tegra30.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/tegra/clk-tegra30.c	2016-07-24 15:23:50.000000000 -0400
@@ -339,11 +339,11 @@ static const struct pdiv_map pllu_p[] =
 };
 
 static struct tegra_clk_pll_freq_table pll_u_freq_table[] = {
-	{ 12000000, 480000000, 960, 12, 1, 12 },
-	{ 13000000, 480000000, 960, 13, 1, 12 },
-	{ 16800000, 480000000, 400,  7, 1,  5 },
-	{ 19200000, 480000000, 200,  4, 1,  3 },
-	{ 26000000, 480000000, 960, 26, 1, 12 },
+	{ 12000000, 480000000, 960, 12, 2, 12 },
+	{ 13000000, 480000000, 960, 13, 2, 12 },
+	{ 16800000, 480000000, 400,  7, 2,  5 },
+	{ 19200000, 480000000, 200,  4, 2,  3 },
+	{ 26000000, 480000000, 960, 26, 2, 12 },
 	{        0,         0,   0,  0, 0,  0 },
 };
 
@@ -1372,6 +1372,7 @@ static struct tegra_clk_init_table init_
 	{ TEGRA30_CLK_SBC4, TEGRA30_CLK_PLL_P, 100000000, 0 },
 	{ TEGRA30_CLK_SBC5, TEGRA30_CLK_PLL_P, 100000000, 0 },
 	{ TEGRA30_CLK_SBC6, TEGRA30_CLK_PLL_P, 100000000, 0 },
+	{ TEGRA30_CLK_PLL_C, TEGRA30_CLK_CLK_MAX, 600000000, 0 },
 	{ TEGRA30_CLK_HOST1X, TEGRA30_CLK_PLL_C, 150000000, 0 },
 	{ TEGRA30_CLK_DISP1, TEGRA30_CLK_PLL_P, 600000000, 0 },
 	{ TEGRA30_CLK_DISP2, TEGRA30_CLK_PLL_P, 600000000, 0 },
@@ -1379,6 +1380,7 @@ static struct tegra_clk_init_table init_
 	{ TEGRA30_CLK_GR2D, TEGRA30_CLK_PLL_C, 300000000, 0 },
 	{ TEGRA30_CLK_GR3D, TEGRA30_CLK_PLL_C, 300000000, 0 },
 	{ TEGRA30_CLK_GR3D2, TEGRA30_CLK_PLL_C, 300000000, 0 },
+	{ TEGRA30_CLK_PLL_U, TEGRA30_CLK_CLK_MAX, 480000000, 0 },
 	/* must be the last entry */
 	{ TEGRA30_CLK_CLK_MAX, TEGRA30_CLK_CLK_MAX, 0, 0 },
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/tegra/clk-tegra-fixed.c linux-libre-4.7-gnu/drivers/clk/tegra/clk-tegra-fixed.c
--- linux-libre-4.6-gnu/drivers/clk/tegra/clk-tegra-fixed.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/tegra/clk-tegra-fixed.c	2016-07-24 15:23:50.000000000 -0400
@@ -107,4 +107,3 @@ void __init tegra_fixed_clk_init(struct
 		*dt_clk = clk;
 	}
 }
-
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/tegra/clk-tegra-periph.c linux-libre-4.7-gnu/drivers/clk/tegra/clk-tegra-periph.c
--- linux-libre-4.6-gnu/drivers/clk/tegra/clk-tegra-periph.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/tegra/clk-tegra-periph.c	2016-07-24 15:23:50.000000000 -0400
@@ -803,7 +803,7 @@ static struct tegra_periph_init_data gat
 	GATE("hda2hdmi", "clk_m", 128, TEGRA_PERIPH_ON_APB, tegra_clk_hda2hdmi, 0),
 	GATE("bsea", "clk_m", 62, 0, tegra_clk_bsea, 0),
 	GATE("bsev", "clk_m", 63, 0, tegra_clk_bsev, 0),
-	GATE("mipi-cal", "clk_m", 56, 0, tegra_clk_mipi_cal, 0),
+	GATE("mipi-cal", "clk72mhz", 56, 0, tegra_clk_mipi_cal, 0),
 	GATE("usbd", "clk_m", 22, 0, tegra_clk_usbd, 0),
 	GATE("usb2", "clk_m", 58, 0, tegra_clk_usb2, 0),
 	GATE("usb3", "clk_m", 59, 0, tegra_clk_usb3, 0),
@@ -821,7 +821,6 @@ static struct tegra_periph_init_data gat
 	GATE("ispb", "clk_m", 3, 0, tegra_clk_ispb, 0),
 	GATE("vim2_clk", "clk_m", 11, 0, tegra_clk_vim2_clk, 0),
 	GATE("pcie", "clk_m", 70, 0, tegra_clk_pcie, 0),
-	GATE("dpaux", "clk_m", 181, 0, tegra_clk_dpaux, 0),
 	GATE("gpu", "pll_ref", 184, 0, tegra_clk_gpu, 0),
 	GATE("pllg_ref", "pll_ref", 189, 0, tegra_clk_pll_g_ref, 0),
 	GATE("hsic_trk", "usb2_hsic_trk", 209, TEGRA_PERIPH_NO_RESET, tegra_clk_hsic_trk, 0),
@@ -877,7 +876,7 @@ static void __init periph_clk_init(void
 	struct clk **dt_clk;
 
 	for (i = 0; i < ARRAY_SIZE(periph_clks); i++) {
-		struct tegra_clk_periph_regs *bank;
+		const struct tegra_clk_periph_regs *bank;
 		struct tegra_periph_init_data *data;
 
 		data = periph_clks + i;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/tegra/cvb.c linux-libre-4.7-gnu/drivers/clk/tegra/cvb.c
--- linux-libre-4.6-gnu/drivers/clk/tegra/cvb.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/tegra/cvb.c	2016-07-24 15:23:50.000000000 -0400
@@ -61,29 +61,28 @@ static int round_voltage(int mv, const s
 	return mv;
 }
 
-static int build_opp_table(const struct cvb_table *d,
-			   int speedo_value,
-			   unsigned long max_freq,
-			   struct device *opp_dev)
+static int build_opp_table(struct device *dev, const struct cvb_table *table,
+			   int speedo_value, unsigned long max_freq)
 {
+	const struct rail_alignment *align = &table->alignment;
 	int i, ret, dfll_mv, min_mv, max_mv;
-	const struct cvb_table_freq_entry *table = NULL;
-	const struct rail_alignment *align = &d->alignment;
 
-	min_mv = round_voltage(d->min_millivolts, align, UP);
-	max_mv = round_voltage(d->max_millivolts, align, DOWN);
+	min_mv = round_voltage(table->min_millivolts, align, UP);
+	max_mv = round_voltage(table->max_millivolts, align, DOWN);
 
 	for (i = 0; i < MAX_DVFS_FREQS; i++) {
-		table = &d->cvb_table[i];
-		if (!table->freq || (table->freq > max_freq))
+		const struct cvb_table_freq_entry *entry = &table->entries[i];
+
+		if (!entry->freq || (entry->freq > max_freq))
 			break;
 
-		dfll_mv = get_cvb_voltage(
-			speedo_value, d->speedo_scale, &table->coefficients);
-		dfll_mv = round_cvb_voltage(dfll_mv, d->voltage_scale, align);
+		dfll_mv = get_cvb_voltage(speedo_value, table->speedo_scale,
+					  &entry->coefficients);
+		dfll_mv = round_cvb_voltage(dfll_mv, table->voltage_scale,
+					    align);
 		dfll_mv = clamp(dfll_mv, min_mv, max_mv);
 
-		ret = dev_pm_opp_add(opp_dev, table->freq, dfll_mv * 1000);
+		ret = dev_pm_opp_add(dev, entry->freq, dfll_mv * 1000);
 		if (ret)
 			return ret;
 	}
@@ -92,7 +91,7 @@ static int build_opp_table(const struct
 }
 
 /**
- * tegra_cvb_build_opp_table - build OPP table from Tegra CVB tables
+ * tegra_cvb_add_opp_table - build OPP table from Tegra CVB tables
  * @cvb_tables: array of CVB tables
  * @sz: size of the previously mentioned array
  * @process_id: process id of the HW module
@@ -108,26 +107,42 @@ static int build_opp_table(const struct
  * given @opp_dev. Returns a pointer to the struct cvb_table that matched
  * or an ERR_PTR on failure.
  */
-const struct cvb_table *tegra_cvb_build_opp_table(
-		const struct cvb_table *cvb_tables,
-		size_t sz, int process_id,
-		int speedo_id, int speedo_value,
-		unsigned long max_rate,
-		struct device *opp_dev)
+const struct cvb_table *
+tegra_cvb_add_opp_table(struct device *dev, const struct cvb_table *tables,
+			size_t count, int process_id, int speedo_id,
+			int speedo_value, unsigned long max_freq)
 {
-	int i, ret;
+	size_t i;
+	int ret;
 
-	for (i = 0; i < sz; i++) {
-		const struct cvb_table *d = &cvb_tables[i];
+	for (i = 0; i < count; i++) {
+		const struct cvb_table *table = &tables[i];
 
-		if (d->speedo_id != -1 && d->speedo_id != speedo_id)
+		if (table->speedo_id != -1 && table->speedo_id != speedo_id)
 			continue;
-		if (d->process_id != -1 && d->process_id != process_id)
+
+		if (table->process_id != -1 && table->process_id != process_id)
 			continue;
 
-		ret = build_opp_table(d, speedo_value, max_rate, opp_dev);
-		return ret ? ERR_PTR(ret) : d;
+		ret = build_opp_table(dev, table, speedo_value, max_freq);
+		return ret ? ERR_PTR(ret) : table;
 	}
 
 	return ERR_PTR(-EINVAL);
 }
+
+void tegra_cvb_remove_opp_table(struct device *dev,
+				const struct cvb_table *table,
+				unsigned long max_freq)
+{
+	unsigned int i;
+
+	for (i = 0; i < MAX_DVFS_FREQS; i++) {
+		const struct cvb_table_freq_entry *entry = &table->entries[i];
+
+		if (!entry->freq || (entry->freq > max_freq))
+			break;
+
+		dev_pm_opp_remove(dev, entry->freq);
+	}
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/tegra/cvb.h linux-libre-4.7-gnu/drivers/clk/tegra/cvb.h
--- linux-libre-4.6-gnu/drivers/clk/tegra/cvb.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/tegra/cvb.h	2016-07-24 15:23:50.000000000 -0400
@@ -53,15 +53,16 @@ struct cvb_table {
 
 	int speedo_scale;
 	int voltage_scale;
-	struct cvb_table_freq_entry cvb_table[MAX_DVFS_FREQS];
+	struct cvb_table_freq_entry entries[MAX_DVFS_FREQS];
 	struct cvb_cpu_dfll_data cpu_dfll_data;
 };
 
-const struct cvb_table *tegra_cvb_build_opp_table(
-		const struct cvb_table *cvb_tables,
-		size_t sz, int process_id,
-		int speedo_id, int speedo_value,
-		unsigned long max_rate,
-		struct device *opp_dev);
+const struct cvb_table *
+tegra_cvb_add_opp_table(struct device *dev, const struct cvb_table *cvb_tables,
+			size_t count, int process_id, int speedo_id,
+			int speedo_value, unsigned long max_freq);
+void tegra_cvb_remove_opp_table(struct device *dev,
+				const struct cvb_table *table,
+				unsigned long max_freq);
 
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/tegra/Makefile linux-libre-4.7-gnu/drivers/clk/tegra/Makefile
--- linux-libre-4.6-gnu/drivers/clk/tegra/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/tegra/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -3,6 +3,7 @@ obj-y					+= clk-audio-sync.o
 obj-y					+= clk-dfll.o
 obj-y					+= clk-divider.o
 obj-y					+= clk-periph.o
+obj-y					+= clk-periph-fixed.o
 obj-y					+= clk-periph-gate.o
 obj-y					+= clk-pll.o
 obj-y					+= clk-pll-out.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/ti/clk-54xx.c linux-libre-4.7-gnu/drivers/clk/ti/clk-54xx.c
--- linux-libre-4.6-gnu/drivers/clk/ti/clk-54xx.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/ti/clk-54xx.c	2016-07-24 15:23:50.000000000 -0400
@@ -210,6 +210,7 @@ static struct ti_dt_clk omap54xx_clks[]
 	DT_CLK("usbhs_omap", "usbtll_fck", "dummy_ck"),
 	DT_CLK("omap_wdt", "ick", "dummy_ck"),
 	DT_CLK(NULL, "timer_32k_ck", "sys_32k_ck"),
+	DT_CLK(NULL, "sys_clkin_ck", "sys_clkin"),
 	DT_CLK("4ae18000.timer", "timer_sys_ck", "sys_clkin"),
 	DT_CLK("48032000.timer", "timer_sys_ck", "sys_clkin"),
 	DT_CLK("48034000.timer", "timer_sys_ck", "sys_clkin"),
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/ti/clk-7xx.c linux-libre-4.7-gnu/drivers/clk/ti/clk-7xx.c
--- linux-libre-4.6-gnu/drivers/clk/ti/clk-7xx.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/ti/clk-7xx.c	2016-07-24 15:23:50.000000000 -0400
@@ -223,7 +223,7 @@ static struct ti_dt_clk dra7xx_clks[] =
 	DT_CLK(NULL, "mcasp6_aux_gfclk_mux", "mcasp6_aux_gfclk_mux"),
 	DT_CLK(NULL, "mcasp7_ahclkx_mux", "mcasp7_ahclkx_mux"),
 	DT_CLK(NULL, "mcasp7_aux_gfclk_mux", "mcasp7_aux_gfclk_mux"),
-	DT_CLK(NULL, "mcasp8_ahclk_mux", "mcasp8_ahclk_mux"),
+	DT_CLK(NULL, "mcasp8_ahclkx_mux", "mcasp8_ahclkx_mux"),
 	DT_CLK(NULL, "mcasp8_aux_gfclk_mux", "mcasp8_aux_gfclk_mux"),
 	DT_CLK(NULL, "mmc1_fclk_mux", "mmc1_fclk_mux"),
 	DT_CLK(NULL, "mmc1_fclk_div", "mmc1_fclk_div"),
@@ -289,6 +289,7 @@ static struct ti_dt_clk dra7xx_clks[] =
 	DT_CLK("usbhs_omap", "usbtll_fck", "dummy_ck"),
 	DT_CLK("omap_wdt", "ick", "dummy_ck"),
 	DT_CLK(NULL, "timer_32k_ck", "sys_32k_ck"),
+	DT_CLK(NULL, "sys_clkin_ck", "timer_sys_clk_div"),
 	DT_CLK("4ae18000.timer", "timer_sys_ck", "timer_sys_clk_div"),
 	DT_CLK("48032000.timer", "timer_sys_ck", "timer_sys_clk_div"),
 	DT_CLK("48034000.timer", "timer_sys_ck", "timer_sys_clk_div"),
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/ti/clk-dra7-atl.c linux-libre-4.7-gnu/drivers/clk/ti/clk-dra7-atl.c
--- linux-libre-4.6-gnu/drivers/clk/ti/clk-dra7-atl.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/ti/clk-dra7-atl.c	2016-07-24 15:23:50.000000000 -0400
@@ -265,6 +265,7 @@ static int of_dra7_atl_clk_probe(struct
 
 		/* Get configuration for the ATL instances */
 		snprintf(prop, sizeof(prop), "atl%u", i);
+		of_node_get(node);
 		cfg_node = of_find_node_by_name(node, prop);
 		if (cfg_node) {
 			ret = of_property_read_u32(cfg_node, "bws",
@@ -278,6 +279,7 @@ static int of_dra7_atl_clk_probe(struct
 				atl_write(cinfo, DRA7_ATL_AWSMUX_REG(i),
 					  cdesc->aws);
 			}
+			of_node_put(cfg_node);
 		}
 
 		cdesc->probed = true;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/ti/clkt_dflt.c linux-libre-4.7-gnu/drivers/clk/ti/clkt_dflt.c
--- linux-libre-4.6-gnu/drivers/clk/ti/clkt_dflt.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/ti/clkt_dflt.c	2016-07-24 15:23:50.000000000 -0400
@@ -222,7 +222,7 @@ int omap2_dflt_clk_enable(struct clk_hw
 		}
 	}
 
-	if (unlikely(IS_ERR(clk->enable_reg))) {
+	if (IS_ERR(clk->enable_reg)) {
 		pr_err("%s: %s missing enable_reg\n", __func__,
 		       clk_hw_get_name(hw));
 		ret = -EINVAL;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/ti/clkt_dpll.c linux-libre-4.7-gnu/drivers/clk/ti/clkt_dpll.c
--- linux-libre-4.6-gnu/drivers/clk/ti/clkt_dpll.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/ti/clkt_dpll.c	2016-07-24 15:23:50.000000000 -0400
@@ -301,6 +301,9 @@ long omap2_dpll_round_rate(struct clk_hw
 
 	dd = clk->dpll_data;
 
+	if (dd->max_rate && target_rate > dd->max_rate)
+		target_rate = dd->max_rate;
+
 	ref_rate = clk_hw_get_rate(dd->clk_ref);
 	clk_name = clk_hw_get_name(hw);
 	pr_debug("clock: %s: starting DPLL round_rate, target rate %lu\n",
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/ti/dpll.c linux-libre-4.7-gnu/drivers/clk/ti/dpll.c
--- linux-libre-4.6-gnu/drivers/clk/ti/dpll.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/ti/dpll.c	2016-07-24 15:23:50.000000000 -0400
@@ -655,6 +655,7 @@ static void __init of_ti_am3_no_gate_dpl
 		.max_multiplier = 2047,
 		.max_divider = 128,
 		.min_divider = 1,
+		.max_rate = 1000000000,
 		.modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
 	};
 
@@ -674,6 +675,7 @@ static void __init of_ti_am3_jtype_dpll_
 		.max_divider = 256,
 		.min_divider = 2,
 		.flags = DPLL_J_TYPE,
+		.max_rate = 2000000000,
 		.modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
 	};
 
@@ -692,6 +694,7 @@ static void __init of_ti_am3_no_gate_jty
 		.max_multiplier = 2047,
 		.max_divider = 128,
 		.min_divider = 1,
+		.max_rate = 2000000000,
 		.flags = DPLL_J_TYPE,
 		.modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
 	};
@@ -712,6 +715,7 @@ static void __init of_ti_am3_dpll_setup(
 		.max_multiplier = 2047,
 		.max_divider = 128,
 		.min_divider = 1,
+		.max_rate = 1000000000,
 		.modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
 	};
 
@@ -729,6 +733,7 @@ static void __init of_ti_am3_core_dpll_s
 		.max_multiplier = 2047,
 		.max_divider = 128,
 		.min_divider = 1,
+		.max_rate = 1000000000,
 		.modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
 	};
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clk/zte/clk-zx296702.c linux-libre-4.7-gnu/drivers/clk/zte/clk-zx296702.c
--- linux-libre-4.6-gnu/drivers/clk/zte/clk-zx296702.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clk/zte/clk-zx296702.c	2016-07-24 15:23:50.000000000 -0400
@@ -234,8 +234,7 @@ static void __init zx296702_top_clocks_i
 	WARN_ON(!topcrm_base);
 
 	clk[ZX296702_OSC] =
-		clk_register_fixed_rate(NULL, "osc", NULL, CLK_IS_ROOT,
-				30000000);
+		clk_register_fixed_rate(NULL, "osc", NULL, 0, 30000000);
 	clk[ZX296702_PLL_A9] =
 		clk_register_zx_pll("pll_a9", "osc", 0, topcrm_base
 				+ 0x01c, pll_a9_config,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clocksource/arm_arch_timer.c linux-libre-4.7-gnu/drivers/clocksource/arm_arch_timer.c
--- linux-libre-4.6-gnu/drivers/clocksource/arm_arch_timer.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clocksource/arm_arch_timer.c	2016-07-24 15:23:50.000000000 -0400
@@ -468,11 +468,11 @@ static struct cyclecounter cyclecounter
 	.mask	= CLOCKSOURCE_MASK(56),
 };
 
-static struct timecounter timecounter;
+static struct arch_timer_kvm_info arch_timer_kvm_info;
 
-struct timecounter *arch_timer_get_timecounter(void)
+struct arch_timer_kvm_info *arch_timer_get_kvm_info(void)
 {
-	return &timecounter;
+	return &arch_timer_kvm_info;
 }
 
 static void __init arch_counter_register(unsigned type)
@@ -500,7 +500,8 @@ static void __init arch_counter_register
 	clocksource_register_hz(&clocksource_counter, arch_timer_rate);
 	cyclecounter.mult = clocksource_counter.mult;
 	cyclecounter.shift = clocksource_counter.shift;
-	timecounter_init(&timecounter, &cyclecounter, start_count);
+	timecounter_init(&arch_timer_kvm_info.timecounter,
+			 &cyclecounter, start_count);
 
 	/* 56 bits minimum, so we assume worst case rollover */
 	sched_clock_register(arch_timer_read_counter, 56, arch_timer_rate);
@@ -744,6 +745,8 @@ static void __init arch_timer_init(void)
 
 	arch_timer_register();
 	arch_timer_common_init();
+
+	arch_timer_kvm_info.virtual_irq = arch_timer_ppi[VIRT_PPI];
 }
 
 static void __init arch_timer_of_init(struct device_node *np)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clocksource/dw_apb_timer.c linux-libre-4.7-gnu/drivers/clocksource/dw_apb_timer.c
--- linux-libre-4.6-gnu/drivers/clocksource/dw_apb_timer.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clocksource/dw_apb_timer.c	2016-07-24 15:23:50.000000000 -0400
@@ -264,6 +264,7 @@ dw_apb_clockevent_init(int cpu, const ch
 	dw_ced->ced.set_state_shutdown = apbt_shutdown;
 	dw_ced->ced.set_state_periodic = apbt_set_periodic;
 	dw_ced->ced.set_state_oneshot = apbt_set_oneshot;
+	dw_ced->ced.set_state_oneshot_stopped = apbt_shutdown;
 	dw_ced->ced.tick_resume = apbt_resume;
 	dw_ced->ced.set_next_event = apbt_next_event;
 	dw_ced->ced.irq = dw_ced->timer.irq;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clocksource/Kconfig linux-libre-4.7-gnu/drivers/clocksource/Kconfig
--- linux-libre-4.6-gnu/drivers/clocksource/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clocksource/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -181,11 +181,27 @@ config CLKSRC_TI_32K
 	  This option enables support for Texas Instruments 32.768 Hz clocksource
 	  available on many OMAP-like platforms.
 
+config CLKSRC_NPS
+	bool "NPS400 clocksource driver" if COMPILE_TEST
+	depends on !PHYS_ADDR_T_64BIT
+	select CLKSRC_MMIO
+	select CLKSRC_OF if OF
+	help
+	  NPS400 clocksource support.
+	  Got 64 bit counter with update rate up to 1000MHz.
+	  This counter is accessed via couple of 32 bit memory mapped registers.
+
 config CLKSRC_STM32
 	bool "Clocksource for STM32 SoCs" if !ARCH_STM32
 	depends on OF && ARM && (ARCH_STM32 || COMPILE_TEST)
 	select CLKSRC_MMIO
 
+config CLKSRC_MPS2
+	bool "Clocksource for MPS2 SoCs" if COMPILE_TEST
+	depends on GENERIC_SCHED_CLOCK
+	select CLKSRC_MMIO
+	select CLKSRC_OF
+
 config ARM_ARCH_TIMER
 	bool
 	select CLKSRC_OF if OF
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clocksource/Makefile linux-libre-4.7-gnu/drivers/clocksource/Makefile
--- linux-libre-4.6-gnu/drivers/clocksource/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clocksource/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -39,6 +39,7 @@ obj-$(CONFIG_CLKSRC_EFM32)	+= time-efm32
 obj-$(CONFIG_CLKSRC_STM32)	+= timer-stm32.o
 obj-$(CONFIG_CLKSRC_EXYNOS_MCT)	+= exynos_mct.o
 obj-$(CONFIG_CLKSRC_LPC32XX)	+= time-lpc32xx.o
+obj-$(CONFIG_CLKSRC_MPS2)	+= mps2-timer.o
 obj-$(CONFIG_CLKSRC_SAMSUNG_PWM)	+= samsung_pwm_timer.o
 obj-$(CONFIG_FSL_FTM_TIMER)	+= fsl_ftm_timer.o
 obj-$(CONFIG_VF_PIT_TIMER)	+= vf_pit_timer.o
@@ -46,6 +47,7 @@ obj-$(CONFIG_CLKSRC_QCOM)	+= qcom-timer.
 obj-$(CONFIG_MTK_TIMER)		+= mtk_timer.o
 obj-$(CONFIG_CLKSRC_PISTACHIO)	+= time-pistachio.o
 obj-$(CONFIG_CLKSRC_TI_32K)	+= timer-ti-32k.o
+obj-$(CONFIG_CLKSRC_NPS)	+= timer-nps.o
 
 obj-$(CONFIG_ARM_ARCH_TIMER)		+= arm_arch_timer.o
 obj-$(CONFIG_ARM_GLOBAL_TIMER)		+= arm_global_timer.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clocksource/mps2-timer.c linux-libre-4.7-gnu/drivers/clocksource/mps2-timer.c
--- linux-libre-4.6-gnu/drivers/clocksource/mps2-timer.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/clocksource/mps2-timer.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2015 ARM Limited
+ *
+ * Author: Vladimir Murzin <vladimir.murzin@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/of_address.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/sched_clock.h>
+#include <linux/slab.h>
+
+#define TIMER_CTRL		0x0
+#define TIMER_CTRL_ENABLE	BIT(0)
+#define TIMER_CTRL_IE		BIT(3)
+
+#define TIMER_VALUE		0x4
+#define TIMER_RELOAD		0x8
+#define TIMER_INT		0xc
+
+struct clockevent_mps2 {
+	void __iomem *reg;
+	u32 clock_count_per_tick;
+	struct clock_event_device clkevt;
+};
+
+static void __iomem *sched_clock_base;
+
+static u64 notrace mps2_sched_read(void)
+{
+	return ~readl_relaxed(sched_clock_base + TIMER_VALUE);
+}
+
+static inline struct clockevent_mps2 *to_mps2_clkevt(struct clock_event_device *c)
+{
+	return container_of(c, struct clockevent_mps2, clkevt);
+}
+
+static void clockevent_mps2_writel(u32 val, struct clock_event_device *c, u32 offset)
+{
+	writel_relaxed(val, to_mps2_clkevt(c)->reg + offset);
+}
+
+static int mps2_timer_shutdown(struct clock_event_device *ce)
+{
+	clockevent_mps2_writel(0, ce, TIMER_RELOAD);
+	clockevent_mps2_writel(0, ce, TIMER_CTRL);
+
+	return 0;
+}
+
+static int mps2_timer_set_next_event(unsigned long next, struct clock_event_device *ce)
+{
+	clockevent_mps2_writel(next, ce, TIMER_VALUE);
+	clockevent_mps2_writel(TIMER_CTRL_IE | TIMER_CTRL_ENABLE, ce, TIMER_CTRL);
+
+	return 0;
+}
+
+static int mps2_timer_set_periodic(struct clock_event_device *ce)
+{
+	u32 clock_count_per_tick = to_mps2_clkevt(ce)->clock_count_per_tick;
+
+	clockevent_mps2_writel(clock_count_per_tick, ce, TIMER_RELOAD);
+	clockevent_mps2_writel(clock_count_per_tick, ce, TIMER_VALUE);
+	clockevent_mps2_writel(TIMER_CTRL_IE | TIMER_CTRL_ENABLE, ce, TIMER_CTRL);
+
+	return 0;
+}
+
+static irqreturn_t mps2_timer_interrupt(int irq, void *dev_id)
+{
+	struct clockevent_mps2 *ce = dev_id;
+	u32 status = readl_relaxed(ce->reg + TIMER_INT);
+
+	if (!status) {
+		pr_warn("spurious interrupt\n");
+		return IRQ_NONE;
+	}
+
+	writel_relaxed(1, ce->reg + TIMER_INT);
+
+	ce->clkevt.event_handler(&ce->clkevt);
+
+	return IRQ_HANDLED;
+}
+
+static int __init mps2_clockevent_init(struct device_node *np)
+{
+	void __iomem *base;
+	struct clk *clk = NULL;
+	struct clockevent_mps2 *ce;
+	u32 rate;
+	int irq, ret;
+	const char *name = "mps2-clkevt";
+
+	ret = of_property_read_u32(np, "clock-frequency", &rate);
+	if (ret) {
+		clk = of_clk_get(np, 0);
+		if (IS_ERR(clk)) {
+			ret = PTR_ERR(clk);
+			pr_err("failed to get clock for clockevent: %d\n", ret);
+			goto out;
+		}
+
+		ret = clk_prepare_enable(clk);
+		if (ret) {
+			pr_err("failed to enable clock for clockevent: %d\n", ret);
+			goto out_clk_put;
+		}
+
+		rate = clk_get_rate(clk);
+	}
+
+	base = of_iomap(np, 0);
+	if (!base) {
+		ret = -EADDRNOTAVAIL;
+		pr_err("failed to map register for clockevent: %d\n", ret);
+		goto out_clk_disable;
+	}
+
+	irq = irq_of_parse_and_map(np, 0);
+	if (!irq) {
+		ret = -ENOENT;
+		pr_err("failed to get irq for clockevent: %d\n", ret);
+		goto out_iounmap;
+	}
+
+	ce = kzalloc(sizeof(*ce), GFP_KERNEL);
+	if (!ce) {
+		ret = -ENOMEM;
+		goto out_iounmap;
+	}
+
+	ce->reg = base;
+	ce->clock_count_per_tick = DIV_ROUND_CLOSEST(rate, HZ);
+	ce->clkevt.irq = irq;
+	ce->clkevt.name = name;
+	ce->clkevt.rating = 200;
+	ce->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+	ce->clkevt.cpumask = cpu_possible_mask;
+	ce->clkevt.set_state_shutdown	= mps2_timer_shutdown,
+	ce->clkevt.set_state_periodic	= mps2_timer_set_periodic,
+	ce->clkevt.set_state_oneshot	= mps2_timer_shutdown,
+	ce->clkevt.set_next_event	= mps2_timer_set_next_event;
+
+	/* Ensure timer is disabled */
+	writel_relaxed(0, base + TIMER_CTRL);
+
+	ret = request_irq(irq, mps2_timer_interrupt, IRQF_TIMER, name, ce);
+	if (ret) {
+		pr_err("failed to request irq for clockevent: %d\n", ret);
+		goto out_kfree;
+	}
+
+	clockevents_config_and_register(&ce->clkevt, rate, 0xf, 0xffffffff);
+
+	return 0;
+
+out_kfree:
+	kfree(ce);
+out_iounmap:
+	iounmap(base);
+out_clk_disable:
+	/* clk_{disable, unprepare, put}() can handle NULL as a parameter */
+	clk_disable_unprepare(clk);
+out_clk_put:
+	clk_put(clk);
+out:
+	return ret;
+}
+
+static int __init mps2_clocksource_init(struct device_node *np)
+{
+	void __iomem *base;
+	struct clk *clk = NULL;
+	u32 rate;
+	int ret;
+	const char *name = "mps2-clksrc";
+
+	ret = of_property_read_u32(np, "clock-frequency", &rate);
+	if (ret) {
+		clk = of_clk_get(np, 0);
+		if (IS_ERR(clk)) {
+			ret = PTR_ERR(clk);
+			pr_err("failed to get clock for clocksource: %d\n", ret);
+			goto out;
+		}
+
+		ret = clk_prepare_enable(clk);
+		if (ret) {
+			pr_err("failed to enable clock for clocksource: %d\n", ret);
+			goto out_clk_put;
+		}
+
+		rate = clk_get_rate(clk);
+	}
+
+	base = of_iomap(np, 0);
+	if (!base) {
+		ret = -EADDRNOTAVAIL;
+		pr_err("failed to map register for clocksource: %d\n", ret);
+		goto out_clk_disable;
+	}
+
+	/* Ensure timer is disabled */
+	writel_relaxed(0, base + TIMER_CTRL);
+
+	/* ... and set it up as free-running clocksource */
+	writel_relaxed(0xffffffff, base + TIMER_VALUE);
+	writel_relaxed(0xffffffff, base + TIMER_RELOAD);
+
+	writel_relaxed(TIMER_CTRL_ENABLE, base + TIMER_CTRL);
+
+	ret = clocksource_mmio_init(base + TIMER_VALUE, name,
+				    rate, 200, 32,
+				    clocksource_mmio_readl_down);
+	if (ret) {
+		pr_err("failed to init clocksource: %d\n", ret);
+		goto out_iounmap;
+	}
+
+	sched_clock_base = base;
+	sched_clock_register(mps2_sched_read, 32, rate);
+
+	return 0;
+
+out_iounmap:
+	iounmap(base);
+out_clk_disable:
+	/* clk_{disable, unprepare, put}() can handle NULL as a parameter */
+	clk_disable_unprepare(clk);
+out_clk_put:
+	clk_put(clk);
+out:
+	return ret;
+}
+
+static void __init mps2_timer_init(struct device_node *np)
+{
+	static int has_clocksource, has_clockevent;
+	int ret;
+
+	if (!has_clocksource) {
+		ret = mps2_clocksource_init(np);
+		if (!ret) {
+			has_clocksource = 1;
+			return;
+		}
+	}
+
+	if (!has_clockevent) {
+		ret = mps2_clockevent_init(np);
+		if (!ret) {
+			has_clockevent = 1;
+			return;
+		}
+	}
+}
+
+CLOCKSOURCE_OF_DECLARE(mps2_timer, "arm,mps2-timer", mps2_timer_init);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clocksource/mtk_timer.c linux-libre-4.7-gnu/drivers/clocksource/mtk_timer.c
--- linux-libre-4.6-gnu/drivers/clocksource/mtk_timer.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clocksource/mtk_timer.c	2016-07-24 15:23:50.000000000 -0400
@@ -152,7 +152,7 @@ static irqreturn_t mtk_timer_interrupt(i
 }
 
 static void
-mtk_timer_setup(struct mtk_clock_event_device *evt, u8 timer, u8 option)
+__init mtk_timer_setup(struct mtk_clock_event_device *evt, u8 timer, u8 option)
 {
 	writel(TIMER_CTRL_CLEAR | TIMER_CTRL_DISABLE,
 		evt->gpt_base + TIMER_CTRL_REG(timer));
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clocksource/tegra20_timer.c linux-libre-4.7-gnu/drivers/clocksource/tegra20_timer.c
--- linux-libre-4.6-gnu/drivers/clocksource/tegra20_timer.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/clocksource/tegra20_timer.c	2016-07-24 15:23:50.000000000 -0400
@@ -258,17 +258,3 @@ static void __init tegra20_init_rtc(stru
 	register_persistent_clock(NULL, tegra_read_persistent_clock64);
 }
 CLOCKSOURCE_OF_DECLARE(tegra20_rtc, "nvidia,tegra20-rtc", tegra20_init_rtc);
-
-#ifdef CONFIG_PM
-static u32 usec_config;
-
-void tegra_timer_suspend(void)
-{
-	usec_config = timer_readl(TIMERUS_USEC_CFG);
-}
-
-void tegra_timer_resume(void)
-{
-	timer_writel(usec_config, TIMERUS_USEC_CFG);
-}
-#endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/clocksource/timer-nps.c linux-libre-4.7-gnu/drivers/clocksource/timer-nps.c
--- linux-libre-4.6-gnu/drivers/clocksource/timer-nps.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/clocksource/timer-nps.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2016, Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/cpu.h>
+#include <soc/nps/common.h>
+
+#define NPS_MSU_TICK_LOW	0xC8
+#define NPS_CLUSTER_OFFSET	8
+#define NPS_CLUSTER_NUM		16
+
+/* This array is per cluster of CPUs (Each NPS400 cluster got 256 CPUs) */
+static void *nps_msu_reg_low_addr[NPS_CLUSTER_NUM] __read_mostly;
+
+static unsigned long nps_timer_rate;
+
+static cycle_t nps_clksrc_read(struct clocksource *clksrc)
+{
+	int cluster = raw_smp_processor_id() >> NPS_CLUSTER_OFFSET;
+
+	return (cycle_t)ioread32be(nps_msu_reg_low_addr[cluster]);
+}
+
+static void __init nps_setup_clocksource(struct device_node *node,
+					 struct clk *clk)
+{
+	int ret, cluster;
+
+	for (cluster = 0; cluster < NPS_CLUSTER_NUM; cluster++)
+		nps_msu_reg_low_addr[cluster] =
+			nps_host_reg((cluster << NPS_CLUSTER_OFFSET),
+				 NPS_MSU_BLKID, NPS_MSU_TICK_LOW);
+
+	ret = clk_prepare_enable(clk);
+	if (ret) {
+		pr_err("Couldn't enable parent clock\n");
+		return;
+	}
+
+	nps_timer_rate = clk_get_rate(clk);
+
+	ret = clocksource_mmio_init(nps_msu_reg_low_addr, "EZnps-tick",
+				    nps_timer_rate, 301, 32, nps_clksrc_read);
+	if (ret) {
+		pr_err("Couldn't register clock source.\n");
+		clk_disable_unprepare(clk);
+	}
+}
+
+static void __init nps_timer_init(struct device_node *node)
+{
+	struct clk *clk;
+
+	clk = of_clk_get(node, 0);
+	if (IS_ERR(clk)) {
+		pr_err("Can't get timer clock.\n");
+		return;
+	}
+
+	nps_setup_clocksource(node, clk);
+}
+
+CLOCKSOURCE_OF_DECLARE(ezchip_nps400_clksrc, "ezchip,nps400-timer",
+		       nps_timer_init);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/connector/cn_proc.c linux-libre-4.7-gnu/drivers/connector/cn_proc.c
--- linux-libre-4.6-gnu/drivers/connector/cn_proc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/connector/cn_proc.c	2016-07-24 15:23:50.000000000 -0400
@@ -56,11 +56,21 @@ static struct cb_id cn_proc_event_id = {
 /* proc_event_counts is used as the sequence number of the netlink message */
 static DEFINE_PER_CPU(__u32, proc_event_counts) = { 0 };
 
-static inline void get_seq(__u32 *ts, int *cpu)
+static inline void send_msg(struct cn_msg *msg)
 {
 	preempt_disable();
-	*ts = __this_cpu_inc_return(proc_event_counts) - 1;
-	*cpu = smp_processor_id();
+
+	msg->seq = __this_cpu_inc_return(proc_event_counts) - 1;
+	((struct proc_event *)msg->data)->cpu = smp_processor_id();
+
+	/*
+	 * Preemption remains disabled during send to ensure the messages are
+	 * ordered according to their sequence numbers.
+	 *
+	 * If cn_netlink_send() fails, the data is not sent.
+	 */
+	cn_netlink_send(msg, 0, CN_IDX_PROC, GFP_NOWAIT);
+
 	preempt_enable();
 }
 
@@ -77,7 +87,6 @@ void proc_fork_connector(struct task_str
 	msg = buffer_to_cn_msg(buffer);
 	ev = (struct proc_event *)msg->data;
 	memset(&ev->event_data, 0, sizeof(ev->event_data));
-	get_seq(&msg->seq, &ev->cpu);
 	ev->timestamp_ns = ktime_get_ns();
 	ev->what = PROC_EVENT_FORK;
 	rcu_read_lock();
@@ -92,8 +101,7 @@ void proc_fork_connector(struct task_str
 	msg->ack = 0; /* not used */
 	msg->len = sizeof(*ev);
 	msg->flags = 0; /* not used */
-	/*  If cn_netlink_send() failed, the data is not sent */
-	cn_netlink_send(msg, 0, CN_IDX_PROC, GFP_KERNEL);
+	send_msg(msg);
 }
 
 void proc_exec_connector(struct task_struct *task)
@@ -108,7 +116,6 @@ void proc_exec_connector(struct task_str
 	msg = buffer_to_cn_msg(buffer);
 	ev = (struct proc_event *)msg->data;
 	memset(&ev->event_data, 0, sizeof(ev->event_data));
-	get_seq(&msg->seq, &ev->cpu);
 	ev->timestamp_ns = ktime_get_ns();
 	ev->what = PROC_EVENT_EXEC;
 	ev->event_data.exec.process_pid = task->pid;
@@ -118,7 +125,7 @@ void proc_exec_connector(struct task_str
 	msg->ack = 0; /* not used */
 	msg->len = sizeof(*ev);
 	msg->flags = 0; /* not used */
-	cn_netlink_send(msg, 0, CN_IDX_PROC, GFP_KERNEL);
+	send_msg(msg);
 }
 
 void proc_id_connector(struct task_struct *task, int which_id)
@@ -150,14 +157,13 @@ void proc_id_connector(struct task_struc
 		return;
 	}
 	rcu_read_unlock();
-	get_seq(&msg->seq, &ev->cpu);
 	ev->timestamp_ns = ktime_get_ns();
 
 	memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
 	msg->ack = 0; /* not used */
 	msg->len = sizeof(*ev);
 	msg->flags = 0; /* not used */
-	cn_netlink_send(msg, 0, CN_IDX_PROC, GFP_KERNEL);
+	send_msg(msg);
 }
 
 void proc_sid_connector(struct task_struct *task)
@@ -172,7 +178,6 @@ void proc_sid_connector(struct task_stru
 	msg = buffer_to_cn_msg(buffer);
 	ev = (struct proc_event *)msg->data;
 	memset(&ev->event_data, 0, sizeof(ev->event_data));
-	get_seq(&msg->seq, &ev->cpu);
 	ev->timestamp_ns = ktime_get_ns();
 	ev->what = PROC_EVENT_SID;
 	ev->event_data.sid.process_pid = task->pid;
@@ -182,7 +187,7 @@ void proc_sid_connector(struct task_stru
 	msg->ack = 0; /* not used */
 	msg->len = sizeof(*ev);
 	msg->flags = 0; /* not used */
-	cn_netlink_send(msg, 0, CN_IDX_PROC, GFP_KERNEL);
+	send_msg(msg);
 }
 
 void proc_ptrace_connector(struct task_struct *task, int ptrace_id)
@@ -197,7 +202,6 @@ void proc_ptrace_connector(struct task_s
 	msg = buffer_to_cn_msg(buffer);
 	ev = (struct proc_event *)msg->data;
 	memset(&ev->event_data, 0, sizeof(ev->event_data));
-	get_seq(&msg->seq, &ev->cpu);
 	ev->timestamp_ns = ktime_get_ns();
 	ev->what = PROC_EVENT_PTRACE;
 	ev->event_data.ptrace.process_pid  = task->pid;
@@ -215,7 +219,7 @@ void proc_ptrace_connector(struct task_s
 	msg->ack = 0; /* not used */
 	msg->len = sizeof(*ev);
 	msg->flags = 0; /* not used */
-	cn_netlink_send(msg, 0, CN_IDX_PROC, GFP_KERNEL);
+	send_msg(msg);
 }
 
 void proc_comm_connector(struct task_struct *task)
@@ -230,7 +234,6 @@ void proc_comm_connector(struct task_str
 	msg = buffer_to_cn_msg(buffer);
 	ev = (struct proc_event *)msg->data;
 	memset(&ev->event_data, 0, sizeof(ev->event_data));
-	get_seq(&msg->seq, &ev->cpu);
 	ev->timestamp_ns = ktime_get_ns();
 	ev->what = PROC_EVENT_COMM;
 	ev->event_data.comm.process_pid  = task->pid;
@@ -241,7 +244,7 @@ void proc_comm_connector(struct task_str
 	msg->ack = 0; /* not used */
 	msg->len = sizeof(*ev);
 	msg->flags = 0; /* not used */
-	cn_netlink_send(msg, 0, CN_IDX_PROC, GFP_KERNEL);
+	send_msg(msg);
 }
 
 void proc_coredump_connector(struct task_struct *task)
@@ -256,7 +259,6 @@ void proc_coredump_connector(struct task
 	msg = buffer_to_cn_msg(buffer);
 	ev = (struct proc_event *)msg->data;
 	memset(&ev->event_data, 0, sizeof(ev->event_data));
-	get_seq(&msg->seq, &ev->cpu);
 	ev->timestamp_ns = ktime_get_ns();
 	ev->what = PROC_EVENT_COREDUMP;
 	ev->event_data.coredump.process_pid = task->pid;
@@ -266,7 +268,7 @@ void proc_coredump_connector(struct task
 	msg->ack = 0; /* not used */
 	msg->len = sizeof(*ev);
 	msg->flags = 0; /* not used */
-	cn_netlink_send(msg, 0, CN_IDX_PROC, GFP_KERNEL);
+	send_msg(msg);
 }
 
 void proc_exit_connector(struct task_struct *task)
@@ -281,7 +283,6 @@ void proc_exit_connector(struct task_str
 	msg = buffer_to_cn_msg(buffer);
 	ev = (struct proc_event *)msg->data;
 	memset(&ev->event_data, 0, sizeof(ev->event_data));
-	get_seq(&msg->seq, &ev->cpu);
 	ev->timestamp_ns = ktime_get_ns();
 	ev->what = PROC_EVENT_EXIT;
 	ev->event_data.exit.process_pid = task->pid;
@@ -293,7 +294,7 @@ void proc_exit_connector(struct task_str
 	msg->ack = 0; /* not used */
 	msg->len = sizeof(*ev);
 	msg->flags = 0; /* not used */
-	cn_netlink_send(msg, 0, CN_IDX_PROC, GFP_KERNEL);
+	send_msg(msg);
 }
 
 /*
@@ -325,7 +326,7 @@ static void cn_proc_ack(int err, int rcv
 	msg->ack = rcvd_ack + 1;
 	msg->len = sizeof(*ev);
 	msg->flags = 0; /* not used */
-	cn_netlink_send(msg, 0, CN_IDX_PROC, GFP_KERNEL);
+	send_msg(msg);
 }
 
 /**
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/acpi-cpufreq.c linux-libre-4.7-gnu/drivers/cpufreq/acpi-cpufreq.c
--- linux-libre-4.6-gnu/drivers/cpufreq/acpi-cpufreq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/acpi-cpufreq.c	2016-07-24 15:23:50.000000000 -0400
@@ -25,6 +25,8 @@
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -50,8 +52,6 @@ MODULE_AUTHOR("Paul Diefenbaugh, Dominik
 MODULE_DESCRIPTION("ACPI Processor P-States Driver");
 MODULE_LICENSE("GPL");
 
-#define PFX "acpi-cpufreq: "
-
 enum {
 	UNDEFINED_CAPABLE = 0,
 	SYSTEM_INTEL_MSR_CAPABLE,
@@ -65,7 +65,6 @@ enum {
 #define MSR_K7_HWCR_CPB_DIS	(1ULL << 25)
 
 struct acpi_cpufreq_data {
-	struct cpufreq_frequency_table *freq_table;
 	unsigned int resume;
 	unsigned int cpu_feature;
 	unsigned int acpi_perf_cpu;
@@ -200,8 +199,9 @@ static int check_amd_hwpstate_cpu(unsign
 	return cpu_has(cpu, X86_FEATURE_HW_PSTATE);
 }
 
-static unsigned extract_io(u32 value, struct acpi_cpufreq_data *data)
+static unsigned extract_io(struct cpufreq_policy *policy, u32 value)
 {
+	struct acpi_cpufreq_data *data = policy->driver_data;
 	struct acpi_processor_performance *perf;
 	int i;
 
@@ -209,13 +209,14 @@ static unsigned extract_io(u32 value, st
 
 	for (i = 0; i < perf->state_count; i++) {
 		if (value == perf->states[i].status)
-			return data->freq_table[i].frequency;
+			return policy->freq_table[i].frequency;
 	}
 	return 0;
 }
 
-static unsigned extract_msr(u32 msr, struct acpi_cpufreq_data *data)
+static unsigned extract_msr(struct cpufreq_policy *policy, u32 msr)
 {
+	struct acpi_cpufreq_data *data = policy->driver_data;
 	struct cpufreq_frequency_table *pos;
 	struct acpi_processor_performance *perf;
 
@@ -226,20 +227,22 @@ static unsigned extract_msr(u32 msr, str
 
 	perf = to_perf_data(data);
 
-	cpufreq_for_each_entry(pos, data->freq_table)
+	cpufreq_for_each_entry(pos, policy->freq_table)
 		if (msr == perf->states[pos->driver_data].status)
 			return pos->frequency;
-	return data->freq_table[0].frequency;
+	return policy->freq_table[0].frequency;
 }
 
-static unsigned extract_freq(u32 val, struct acpi_cpufreq_data *data)
+static unsigned extract_freq(struct cpufreq_policy *policy, u32 val)
 {
+	struct acpi_cpufreq_data *data = policy->driver_data;
+
 	switch (data->cpu_feature) {
 	case SYSTEM_INTEL_MSR_CAPABLE:
 	case SYSTEM_AMD_MSR_CAPABLE:
-		return extract_msr(val, data);
+		return extract_msr(policy, val);
 	case SYSTEM_IO_CAPABLE:
-		return extract_io(val, data);
+		return extract_io(policy, val);
 	default:
 		return 0;
 	}
@@ -374,11 +377,11 @@ static unsigned int get_cur_freq_on_cpu(
 		return 0;
 
 	data = policy->driver_data;
-	if (unlikely(!data || !data->freq_table))
+	if (unlikely(!data || !policy->freq_table))
 		return 0;
 
-	cached_freq = data->freq_table[to_perf_data(data)->state].frequency;
-	freq = extract_freq(get_cur_val(cpumask_of(cpu), data), data);
+	cached_freq = policy->freq_table[to_perf_data(data)->state].frequency;
+	freq = extract_freq(policy, get_cur_val(cpumask_of(cpu), data));
 	if (freq != cached_freq) {
 		/*
 		 * The dreaded BIOS frequency change behind our back.
@@ -392,14 +395,15 @@ static unsigned int get_cur_freq_on_cpu(
 	return freq;
 }
 
-static unsigned int check_freqs(const struct cpumask *mask, unsigned int freq,
-				struct acpi_cpufreq_data *data)
+static unsigned int check_freqs(struct cpufreq_policy *policy,
+				const struct cpumask *mask, unsigned int freq)
 {
+	struct acpi_cpufreq_data *data = policy->driver_data;
 	unsigned int cur_freq;
 	unsigned int i;
 
 	for (i = 0; i < 100; i++) {
-		cur_freq = extract_freq(get_cur_val(mask, data), data);
+		cur_freq = extract_freq(policy, get_cur_val(mask, data));
 		if (cur_freq == freq)
 			return 1;
 		udelay(10);
@@ -416,12 +420,12 @@ static int acpi_cpufreq_target(struct cp
 	unsigned int next_perf_state = 0; /* Index into perf table */
 	int result = 0;
 
-	if (unlikely(data == NULL || data->freq_table == NULL)) {
+	if (unlikely(!data)) {
 		return -ENODEV;
 	}
 
 	perf = to_perf_data(data);
-	next_perf_state = data->freq_table[index].driver_data;
+	next_perf_state = policy->freq_table[index].driver_data;
 	if (perf->state == next_perf_state) {
 		if (unlikely(data->resume)) {
 			pr_debug("Called after resume, resetting to P%d\n",
@@ -444,8 +448,8 @@ static int acpi_cpufreq_target(struct cp
 	drv_write(data, mask, perf->states[next_perf_state].control);
 
 	if (acpi_pstate_strict) {
-		if (!check_freqs(mask, data->freq_table[index].frequency,
-					data)) {
+		if (!check_freqs(policy, mask,
+				 policy->freq_table[index].frequency)) {
 			pr_debug("acpi_cpufreq_target failed (%d)\n",
 				policy->cpu);
 			result = -EAGAIN;
@@ -458,6 +462,43 @@ static int acpi_cpufreq_target(struct cp
 	return result;
 }
 
+unsigned int acpi_cpufreq_fast_switch(struct cpufreq_policy *policy,
+				      unsigned int target_freq)
+{
+	struct acpi_cpufreq_data *data = policy->driver_data;
+	struct acpi_processor_performance *perf;
+	struct cpufreq_frequency_table *entry;
+	unsigned int next_perf_state, next_freq, freq;
+
+	/*
+	 * Find the closest frequency above target_freq.
+	 *
+	 * The table is sorted in the reverse order with respect to the
+	 * frequency and all of the entries are valid (see the initialization).
+	 */
+	entry = policy->freq_table;
+	do {
+		entry++;
+		freq = entry->frequency;
+	} while (freq >= target_freq && freq != CPUFREQ_TABLE_END);
+	entry--;
+	next_freq = entry->frequency;
+	next_perf_state = entry->driver_data;
+
+	perf = to_perf_data(data);
+	if (perf->state == next_perf_state) {
+		if (unlikely(data->resume))
+			data->resume = 0;
+		else
+			return next_freq;
+	}
+
+	data->cpu_freq_write(&perf->control_register,
+			     perf->states[next_perf_state].control);
+	perf->state = next_perf_state;
+	return next_freq;
+}
+
 static unsigned long
 acpi_cpufreq_guess_freq(struct acpi_cpufreq_data *data, unsigned int cpu)
 {
@@ -611,10 +652,7 @@ static int acpi_cpufreq_blacklist(struct
 		if ((c->x86 == 15) &&
 		    (c->x86_model == 6) &&
 		    (c->x86_mask == 8)) {
-			printk(KERN_INFO "acpi-cpufreq: Intel(R) "
-			    "Xeon(R) 7100 Errata AL30, processors may "
-			    "lock up on frequency changes: disabling "
-			    "acpi-cpufreq.\n");
+			pr_info("Intel(R) Xeon(R) 7100 Errata AL30, processors may lock up on frequency changes: disabling acpi-cpufreq\n");
 			return -ENODEV;
 		    }
 		}
@@ -631,6 +669,7 @@ static int acpi_cpufreq_cpu_init(struct
 	unsigned int result = 0;
 	struct cpuinfo_x86 *c = &cpu_data(policy->cpu);
 	struct acpi_processor_performance *perf;
+	struct cpufreq_frequency_table *freq_table;
 #ifdef CONFIG_SMP
 	static int blacklisted;
 #endif
@@ -690,7 +729,7 @@ static int acpi_cpufreq_cpu_init(struct
 		cpumask_copy(data->freqdomain_cpus,
 			     topology_sibling_cpumask(cpu));
 		policy->shared_type = CPUFREQ_SHARED_TYPE_HW;
-		pr_info_once(PFX "overriding BIOS provided _PSD data\n");
+		pr_info_once("overriding BIOS provided _PSD data\n");
 	}
 #endif
 
@@ -742,9 +781,9 @@ static int acpi_cpufreq_cpu_init(struct
 		goto err_unreg;
 	}
 
-	data->freq_table = kzalloc(sizeof(*data->freq_table) *
+	freq_table = kzalloc(sizeof(*freq_table) *
 		    (perf->state_count+1), GFP_KERNEL);
-	if (!data->freq_table) {
+	if (!freq_table) {
 		result = -ENOMEM;
 		goto err_unreg;
 	}
@@ -762,30 +801,29 @@ static int acpi_cpufreq_cpu_init(struct
 	if (perf->control_register.space_id == ACPI_ADR_SPACE_FIXED_HARDWARE &&
 	    policy->cpuinfo.transition_latency > 20 * 1000) {
 		policy->cpuinfo.transition_latency = 20 * 1000;
-		printk_once(KERN_INFO
-			    "P-state transition latency capped at 20 uS\n");
+		pr_info_once("P-state transition latency capped at 20 uS\n");
 	}
 
 	/* table init */
 	for (i = 0; i < perf->state_count; i++) {
 		if (i > 0 && perf->states[i].core_frequency >=
-		    data->freq_table[valid_states-1].frequency / 1000)
+		    freq_table[valid_states-1].frequency / 1000)
 			continue;
 
-		data->freq_table[valid_states].driver_data = i;
-		data->freq_table[valid_states].frequency =
+		freq_table[valid_states].driver_data = i;
+		freq_table[valid_states].frequency =
 		    perf->states[i].core_frequency * 1000;
 		valid_states++;
 	}
-	data->freq_table[valid_states].frequency = CPUFREQ_TABLE_END;
+	freq_table[valid_states].frequency = CPUFREQ_TABLE_END;
 	perf->state = 0;
 
-	result = cpufreq_table_validate_and_show(policy, data->freq_table);
+	result = cpufreq_table_validate_and_show(policy, freq_table);
 	if (result)
 		goto err_freqfree;
 
 	if (perf->states[0].core_frequency * 1000 != policy->cpuinfo.max_freq)
-		printk(KERN_WARNING FW_WARN "P-state 0 is not max freq\n");
+		pr_warn(FW_WARN "P-state 0 is not max freq\n");
 
 	switch (perf->control_register.space_id) {
 	case ACPI_ADR_SPACE_SYSTEM_IO:
@@ -821,10 +859,13 @@ static int acpi_cpufreq_cpu_init(struct
 	 */
 	data->resume = 1;
 
+	policy->fast_switch_possible = !acpi_pstate_strict &&
+		!(policy_is_shared(policy) && policy->shared_type != CPUFREQ_SHARED_TYPE_ANY);
+
 	return result;
 
 err_freqfree:
-	kfree(data->freq_table);
+	kfree(freq_table);
 err_unreg:
 	acpi_processor_unregister_performance(cpu);
 err_free_mask:
@@ -842,13 +883,12 @@ static int acpi_cpufreq_cpu_exit(struct
 
 	pr_debug("acpi_cpufreq_cpu_exit\n");
 
-	if (data) {
-		policy->driver_data = NULL;
-		acpi_processor_unregister_performance(data->acpi_perf_cpu);
-		free_cpumask_var(data->freqdomain_cpus);
-		kfree(data->freq_table);
-		kfree(data);
-	}
+	policy->fast_switch_possible = false;
+	policy->driver_data = NULL;
+	acpi_processor_unregister_performance(data->acpi_perf_cpu);
+	free_cpumask_var(data->freqdomain_cpus);
+	kfree(policy->freq_table);
+	kfree(data);
 
 	return 0;
 }
@@ -876,6 +916,7 @@ static struct freq_attr *acpi_cpufreq_at
 static struct cpufreq_driver acpi_cpufreq_driver = {
 	.verify		= cpufreq_generic_frequency_table_verify,
 	.target_index	= acpi_cpufreq_target,
+	.fast_switch	= acpi_cpufreq_fast_switch,
 	.bios_limit	= acpi_processor_get_bios_limit,
 	.init		= acpi_cpufreq_cpu_init,
 	.exit		= acpi_cpufreq_cpu_exit,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/arm_big_little.c linux-libre-4.7-gnu/drivers/cpufreq/arm_big_little.c
--- linux-libre-4.6-gnu/drivers/cpufreq/arm_big_little.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/arm_big_little.c	2016-07-24 15:23:50.000000000 -0400
@@ -298,7 +298,8 @@ static int merge_cluster_tables(void)
 	return 0;
 }
 
-static void _put_cluster_clk_and_freq_table(struct device *cpu_dev)
+static void _put_cluster_clk_and_freq_table(struct device *cpu_dev,
+					    const struct cpumask *cpumask)
 {
 	u32 cluster = raw_cpu_to_cluster(cpu_dev->id);
 
@@ -308,11 +309,12 @@ static void _put_cluster_clk_and_freq_ta
 	clk_put(clk[cluster]);
 	dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table[cluster]);
 	if (arm_bL_ops->free_opp_table)
-		arm_bL_ops->free_opp_table(cpu_dev);
+		arm_bL_ops->free_opp_table(cpumask);
 	dev_dbg(cpu_dev, "%s: cluster: %d\n", __func__, cluster);
 }
 
-static void put_cluster_clk_and_freq_table(struct device *cpu_dev)
+static void put_cluster_clk_and_freq_table(struct device *cpu_dev,
+					   const struct cpumask *cpumask)
 {
 	u32 cluster = cpu_to_cluster(cpu_dev->id);
 	int i;
@@ -321,7 +323,7 @@ static void put_cluster_clk_and_freq_tab
 		return;
 
 	if (cluster < MAX_CLUSTERS)
-		return _put_cluster_clk_and_freq_table(cpu_dev);
+		return _put_cluster_clk_and_freq_table(cpu_dev, cpumask);
 
 	for_each_present_cpu(i) {
 		struct device *cdev = get_cpu_device(i);
@@ -330,14 +332,15 @@ static void put_cluster_clk_and_freq_tab
 			return;
 		}
 
-		_put_cluster_clk_and_freq_table(cdev);
+		_put_cluster_clk_and_freq_table(cdev, cpumask);
 	}
 
 	/* free virtual table */
 	kfree(freq_table[cluster]);
 }
 
-static int _get_cluster_clk_and_freq_table(struct device *cpu_dev)
+static int _get_cluster_clk_and_freq_table(struct device *cpu_dev,
+					   const struct cpumask *cpumask)
 {
 	u32 cluster = raw_cpu_to_cluster(cpu_dev->id);
 	int ret;
@@ -345,7 +348,7 @@ static int _get_cluster_clk_and_freq_tab
 	if (freq_table[cluster])
 		return 0;
 
-	ret = arm_bL_ops->init_opp_table(cpu_dev);
+	ret = arm_bL_ops->init_opp_table(cpumask);
 	if (ret) {
 		dev_err(cpu_dev, "%s: init_opp_table failed, cpu: %d, err: %d\n",
 				__func__, cpu_dev->id, ret);
@@ -374,14 +377,15 @@ static int _get_cluster_clk_and_freq_tab
 
 free_opp_table:
 	if (arm_bL_ops->free_opp_table)
-		arm_bL_ops->free_opp_table(cpu_dev);
+		arm_bL_ops->free_opp_table(cpumask);
 out:
 	dev_err(cpu_dev, "%s: Failed to get data for cluster: %d\n", __func__,
 			cluster);
 	return ret;
 }
 
-static int get_cluster_clk_and_freq_table(struct device *cpu_dev)
+static int get_cluster_clk_and_freq_table(struct device *cpu_dev,
+					  const struct cpumask *cpumask)
 {
 	u32 cluster = cpu_to_cluster(cpu_dev->id);
 	int i, ret;
@@ -390,7 +394,7 @@ static int get_cluster_clk_and_freq_tabl
 		return 0;
 
 	if (cluster < MAX_CLUSTERS) {
-		ret = _get_cluster_clk_and_freq_table(cpu_dev);
+		ret = _get_cluster_clk_and_freq_table(cpu_dev, cpumask);
 		if (ret)
 			atomic_dec(&cluster_usage[cluster]);
 		return ret;
@@ -407,7 +411,7 @@ static int get_cluster_clk_and_freq_tabl
 			return -ENODEV;
 		}
 
-		ret = _get_cluster_clk_and_freq_table(cdev);
+		ret = _get_cluster_clk_and_freq_table(cdev, cpumask);
 		if (ret)
 			goto put_clusters;
 	}
@@ -433,7 +437,7 @@ put_clusters:
 			return -ENODEV;
 		}
 
-		_put_cluster_clk_and_freq_table(cdev);
+		_put_cluster_clk_and_freq_table(cdev, cpumask);
 	}
 
 	atomic_dec(&cluster_usage[cluster]);
@@ -455,18 +459,6 @@ static int bL_cpufreq_init(struct cpufre
 		return -ENODEV;
 	}
 
-	ret = get_cluster_clk_and_freq_table(cpu_dev);
-	if (ret)
-		return ret;
-
-	ret = cpufreq_table_validate_and_show(policy, freq_table[cur_cluster]);
-	if (ret) {
-		dev_err(cpu_dev, "CPU %d, cluster: %d invalid freq table\n",
-				policy->cpu, cur_cluster);
-		put_cluster_clk_and_freq_table(cpu_dev);
-		return ret;
-	}
-
 	if (cur_cluster < MAX_CLUSTERS) {
 		int cpu;
 
@@ -479,6 +471,18 @@ static int bL_cpufreq_init(struct cpufre
 		per_cpu(physical_cluster, policy->cpu) = A15_CLUSTER;
 	}
 
+	ret = get_cluster_clk_and_freq_table(cpu_dev, policy->cpus);
+	if (ret)
+		return ret;
+
+	ret = cpufreq_table_validate_and_show(policy, freq_table[cur_cluster]);
+	if (ret) {
+		dev_err(cpu_dev, "CPU %d, cluster: %d invalid freq table\n",
+			policy->cpu, cur_cluster);
+		put_cluster_clk_and_freq_table(cpu_dev, policy->cpus);
+		return ret;
+	}
+
 	if (arm_bL_ops->get_transition_latency)
 		policy->cpuinfo.transition_latency =
 			arm_bL_ops->get_transition_latency(cpu_dev);
@@ -509,7 +513,7 @@ static int bL_cpufreq_exit(struct cpufre
 		return -ENODEV;
 	}
 
-	put_cluster_clk_and_freq_table(cpu_dev);
+	put_cluster_clk_and_freq_table(cpu_dev, policy->related_cpus);
 	dev_dbg(cpu_dev, "%s: Exited, cpu: %d\n", __func__, policy->cpu);
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/arm_big_little_dt.c linux-libre-4.7-gnu/drivers/cpufreq/arm_big_little_dt.c
--- linux-libre-4.6-gnu/drivers/cpufreq/arm_big_little_dt.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/arm_big_little_dt.c	2016-07-24 15:23:50.000000000 -0400
@@ -43,23 +43,6 @@ static struct device_node *get_cpu_node_
 	return np;
 }
 
-static int dt_init_opp_table(struct device *cpu_dev)
-{
-	struct device_node *np;
-	int ret;
-
-	np = of_node_get(cpu_dev->of_node);
-	if (!np) {
-		pr_err("failed to find cpu%d node\n", cpu_dev->id);
-		return -ENOENT;
-	}
-
-	ret = dev_pm_opp_of_add_table(cpu_dev);
-	of_node_put(np);
-
-	return ret;
-}
-
 static int dt_get_transition_latency(struct device *cpu_dev)
 {
 	struct device_node *np;
@@ -81,8 +64,8 @@ static int dt_get_transition_latency(str
 static struct cpufreq_arm_bL_ops dt_bL_ops = {
 	.name	= "dt-bl",
 	.get_transition_latency = dt_get_transition_latency,
-	.init_opp_table = dt_init_opp_table,
-	.free_opp_table = dev_pm_opp_of_remove_table,
+	.init_opp_table = dev_pm_opp_of_cpumask_add_table,
+	.free_opp_table = dev_pm_opp_of_cpumask_remove_table,
 };
 
 static int generic_bL_probe(struct platform_device *pdev)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/arm_big_little.h linux-libre-4.7-gnu/drivers/cpufreq/arm_big_little.h
--- linux-libre-4.6-gnu/drivers/cpufreq/arm_big_little.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/arm_big_little.h	2016-07-24 15:23:50.000000000 -0400
@@ -30,11 +30,11 @@ struct cpufreq_arm_bL_ops {
 	 * This must set opp table for cpu_dev in a similar way as done by
 	 * dev_pm_opp_of_add_table().
 	 */
-	int (*init_opp_table)(struct device *cpu_dev);
+	int (*init_opp_table)(const struct cpumask *cpumask);
 
 	/* Optional */
 	int (*get_transition_latency)(struct device *cpu_dev);
-	void (*free_opp_table)(struct device *cpu_dev);
+	void (*free_opp_table)(const struct cpumask *cpumask);
 };
 
 int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/cppc_cpufreq.c linux-libre-4.7-gnu/drivers/cpufreq/cppc_cpufreq.c
--- linux-libre-4.6-gnu/drivers/cpufreq/cppc_cpufreq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/cppc_cpufreq.c	2016-07-24 15:23:50.000000000 -0400
@@ -173,4 +173,25 @@ out:
 	return -ENODEV;
 }
 
+static void __exit cppc_cpufreq_exit(void)
+{
+	struct cpudata *cpu;
+	int i;
+
+	cpufreq_unregister_driver(&cppc_cpufreq_driver);
+
+	for_each_possible_cpu(i) {
+		cpu = all_cpu_data[i];
+		free_cpumask_var(cpu->shared_cpu_map);
+		kfree(cpu);
+	}
+
+	kfree(all_cpu_data);
+}
+
+module_exit(cppc_cpufreq_exit);
+MODULE_AUTHOR("Ashwin Chaugule");
+MODULE_DESCRIPTION("CPUFreq driver based on the ACPI CPPC v5.0+ spec");
+MODULE_LICENSE("GPL");
+
 late_initcall(cppc_cpufreq_init);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/cpufreq.c linux-libre-4.7-gnu/drivers/cpufreq/cpufreq.c
--- linux-libre-4.6-gnu/drivers/cpufreq/cpufreq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/cpufreq.c	2016-07-24 15:23:50.000000000 -0400
@@ -78,6 +78,16 @@ static int cpufreq_governor(struct cpufr
 static unsigned int __cpufreq_get(struct cpufreq_policy *policy);
 static int cpufreq_start_governor(struct cpufreq_policy *policy);
 
+static inline void cpufreq_exit_governor(struct cpufreq_policy *policy)
+{
+	(void)cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT);
+}
+
+static inline void cpufreq_stop_governor(struct cpufreq_policy *policy)
+{
+	(void)cpufreq_governor(policy, CPUFREQ_GOV_STOP);
+}
+
 /**
  * Two notifier lists: the "policy" list is involved in the
  * validation process for a new CPU frequency policy; the
@@ -429,6 +439,73 @@ void cpufreq_freq_transition_end(struct
 }
 EXPORT_SYMBOL_GPL(cpufreq_freq_transition_end);
 
+/*
+ * Fast frequency switching status count.  Positive means "enabled", negative
+ * means "disabled" and 0 means "not decided yet".
+ */
+static int cpufreq_fast_switch_count;
+static DEFINE_MUTEX(cpufreq_fast_switch_lock);
+
+static void cpufreq_list_transition_notifiers(void)
+{
+	struct notifier_block *nb;
+
+	pr_info("Registered transition notifiers:\n");
+
+	mutex_lock(&cpufreq_transition_notifier_list.mutex);
+
+	for (nb = cpufreq_transition_notifier_list.head; nb; nb = nb->next)
+		pr_info("%pF\n", nb->notifier_call);
+
+	mutex_unlock(&cpufreq_transition_notifier_list.mutex);
+}
+
+/**
+ * cpufreq_enable_fast_switch - Enable fast frequency switching for policy.
+ * @policy: cpufreq policy to enable fast frequency switching for.
+ *
+ * Try to enable fast frequency switching for @policy.
+ *
+ * The attempt will fail if there is at least one transition notifier registered
+ * at this point, as fast frequency switching is quite fundamentally at odds
+ * with transition notifiers.  Thus if successful, it will make registration of
+ * transition notifiers fail going forward.
+ */
+void cpufreq_enable_fast_switch(struct cpufreq_policy *policy)
+{
+	lockdep_assert_held(&policy->rwsem);
+
+	if (!policy->fast_switch_possible)
+		return;
+
+	mutex_lock(&cpufreq_fast_switch_lock);
+	if (cpufreq_fast_switch_count >= 0) {
+		cpufreq_fast_switch_count++;
+		policy->fast_switch_enabled = true;
+	} else {
+		pr_warn("CPU%u: Fast frequency switching not enabled\n",
+			policy->cpu);
+		cpufreq_list_transition_notifiers();
+	}
+	mutex_unlock(&cpufreq_fast_switch_lock);
+}
+EXPORT_SYMBOL_GPL(cpufreq_enable_fast_switch);
+
+/**
+ * cpufreq_disable_fast_switch - Disable fast frequency switching for policy.
+ * @policy: cpufreq policy to disable fast frequency switching for.
+ */
+void cpufreq_disable_fast_switch(struct cpufreq_policy *policy)
+{
+	mutex_lock(&cpufreq_fast_switch_lock);
+	if (policy->fast_switch_enabled) {
+		policy->fast_switch_enabled = false;
+		if (!WARN_ON(cpufreq_fast_switch_count <= 0))
+			cpufreq_fast_switch_count--;
+	}
+	mutex_unlock(&cpufreq_fast_switch_lock);
+}
+EXPORT_SYMBOL_GPL(cpufreq_disable_fast_switch);
 
 /*********************************************************************
  *                          SYSFS INTERFACE                          *
@@ -954,13 +1031,8 @@ static int cpufreq_add_policy_cpu(struct
 		return 0;
 
 	down_write(&policy->rwsem);
-	if (has_target()) {
-		ret = cpufreq_governor(policy, CPUFREQ_GOV_STOP);
-		if (ret) {
-			pr_err("%s: Failed to stop governor\n", __func__);
-			goto unlock;
-		}
-	}
+	if (has_target())
+		cpufreq_stop_governor(policy);
 
 	cpumask_set_cpu(cpu, policy->cpus);
 
@@ -969,8 +1041,6 @@ static int cpufreq_add_policy_cpu(struct
 		if (ret)
 			pr_err("%s: Failed to start governor\n", __func__);
 	}
-
-unlock:
 	up_write(&policy->rwsem);
 	return ret;
 }
@@ -1248,26 +1318,24 @@ out_free_policy:
  */
 static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
 {
+	struct cpufreq_policy *policy;
 	unsigned cpu = dev->id;
-	int ret;
 
 	dev_dbg(dev, "%s: adding CPU%u\n", __func__, cpu);
 
-	if (cpu_online(cpu)) {
-		ret = cpufreq_online(cpu);
-	} else {
-		/*
-		 * A hotplug notifier will follow and we will handle it as CPU
-		 * online then.  For now, just create the sysfs link, unless
-		 * there is no policy or the link is already present.
-		 */
-		struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu);
+	if (cpu_online(cpu))
+		return cpufreq_online(cpu);
 
-		ret = policy && !cpumask_test_and_set_cpu(cpu, policy->real_cpus)
-			? add_cpu_dev_symlink(policy, cpu) : 0;
-	}
+	/*
+	 * A hotplug notifier will follow and we will handle it as CPU online
+	 * then.  For now, just create the sysfs link, unless there is no policy
+	 * or the link is already present.
+	 */
+	policy = per_cpu(cpufreq_cpu_data, cpu);
+	if (!policy || cpumask_test_and_set_cpu(cpu, policy->real_cpus))
+		return 0;
 
-	return ret;
+	return add_cpu_dev_symlink(policy, cpu);
 }
 
 static void cpufreq_offline(unsigned int cpu)
@@ -1284,11 +1352,8 @@ static void cpufreq_offline(unsigned int
 	}
 
 	down_write(&policy->rwsem);
-	if (has_target()) {
-		ret = cpufreq_governor(policy, CPUFREQ_GOV_STOP);
-		if (ret)
-			pr_err("%s: Failed to stop governor\n", __func__);
-	}
+	if (has_target())
+		cpufreq_stop_governor(policy);
 
 	cpumask_clear_cpu(cpu, policy->cpus);
 
@@ -1317,12 +1382,8 @@ static void cpufreq_offline(unsigned int
 	if (cpufreq_driver->stop_cpu)
 		cpufreq_driver->stop_cpu(policy);
 
-	/* If cpu is last user of policy, free policy */
-	if (has_target()) {
-		ret = cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT);
-		if (ret)
-			pr_err("%s: Failed to exit governor\n", __func__);
-	}
+	if (has_target())
+		cpufreq_exit_governor(policy);
 
 	/*
 	 * Perform the ->exit() even during light-weight tear-down,
@@ -1447,8 +1508,12 @@ static unsigned int __cpufreq_get(struct
 
 	ret_freq = cpufreq_driver->get(policy->cpu);
 
-	/* Updating inactive policies is invalid, so avoid doing that. */
-	if (unlikely(policy_is_inactive(policy)))
+	/*
+	 * Updating inactive policies is invalid, so avoid doing that.  Also
+	 * if fast frequency switching is used with the given policy, the check
+	 * against policy->cur is pointless, so skip it in that case too.
+	 */
+	if (unlikely(policy_is_inactive(policy)) || policy->fast_switch_enabled)
 		return ret_freq;
 
 	if (ret_freq && policy->cur &&
@@ -1552,7 +1617,6 @@ EXPORT_SYMBOL(cpufreq_generic_suspend);
 void cpufreq_suspend(void)
 {
 	struct cpufreq_policy *policy;
-	int ret;
 
 	if (!cpufreq_driver)
 		return;
@@ -1565,14 +1629,8 @@ void cpufreq_suspend(void)
 	for_each_active_policy(policy) {
 		if (has_target()) {
 			down_write(&policy->rwsem);
-			ret = cpufreq_governor(policy, CPUFREQ_GOV_STOP);
+			cpufreq_stop_governor(policy);
 			up_write(&policy->rwsem);
-
-			if (ret) {
-				pr_err("%s: Failed to stop governor for policy: %p\n",
-					__func__, policy);
-				continue;
-			}
 		}
 
 		if (cpufreq_driver->suspend && cpufreq_driver->suspend(policy))
@@ -1679,8 +1737,18 @@ int cpufreq_register_notifier(struct not
 
 	switch (list) {
 	case CPUFREQ_TRANSITION_NOTIFIER:
+		mutex_lock(&cpufreq_fast_switch_lock);
+
+		if (cpufreq_fast_switch_count > 0) {
+			mutex_unlock(&cpufreq_fast_switch_lock);
+			return -EBUSY;
+		}
 		ret = srcu_notifier_chain_register(
 				&cpufreq_transition_notifier_list, nb);
+		if (!ret)
+			cpufreq_fast_switch_count--;
+
+		mutex_unlock(&cpufreq_fast_switch_lock);
 		break;
 	case CPUFREQ_POLICY_NOTIFIER:
 		ret = blocking_notifier_chain_register(
@@ -1713,8 +1781,14 @@ int cpufreq_unregister_notifier(struct n
 
 	switch (list) {
 	case CPUFREQ_TRANSITION_NOTIFIER:
+		mutex_lock(&cpufreq_fast_switch_lock);
+
 		ret = srcu_notifier_chain_unregister(
 				&cpufreq_transition_notifier_list, nb);
+		if (!ret && !WARN_ON(cpufreq_fast_switch_count >= 0))
+			cpufreq_fast_switch_count++;
+
+		mutex_unlock(&cpufreq_fast_switch_lock);
 		break;
 	case CPUFREQ_POLICY_NOTIFIER:
 		ret = blocking_notifier_chain_unregister(
@@ -1733,6 +1807,37 @@ EXPORT_SYMBOL(cpufreq_unregister_notifie
  *                              GOVERNORS                            *
  *********************************************************************/
 
+/**
+ * cpufreq_driver_fast_switch - Carry out a fast CPU frequency switch.
+ * @policy: cpufreq policy to switch the frequency for.
+ * @target_freq: New frequency to set (may be approximate).
+ *
+ * Carry out a fast frequency switch without sleeping.
+ *
+ * The driver's ->fast_switch() callback invoked by this function must be
+ * suitable for being called from within RCU-sched read-side critical sections
+ * and it is expected to select the minimum available frequency greater than or
+ * equal to @target_freq (CPUFREQ_RELATION_L).
+ *
+ * This function must not be called if policy->fast_switch_enabled is unset.
+ *
+ * Governors calling this function must guarantee that it will never be invoked
+ * twice in parallel for the same policy and that it will never be called in
+ * parallel with either ->target() or ->target_index() for the same policy.
+ *
+ * If CPUFREQ_ENTRY_INVALID is returned by the driver's ->fast_switch()
+ * callback to indicate an error condition, the hardware configuration must be
+ * preserved.
+ */
+unsigned int cpufreq_driver_fast_switch(struct cpufreq_policy *policy,
+					unsigned int target_freq)
+{
+	target_freq = clamp_val(target_freq, policy->min, policy->max);
+
+	return cpufreq_driver->fast_switch(policy, target_freq);
+}
+EXPORT_SYMBOL_GPL(cpufreq_driver_fast_switch);
+
 /* Must set freqs->new to intermediate frequency */
 static int __target_intermediate(struct cpufreq_policy *policy,
 				 struct cpufreq_freqs *freqs, int index)
@@ -1928,16 +2033,15 @@ static int cpufreq_governor(struct cpufr
 
 	ret = policy->governor->governor(policy, event);
 
-	if (!ret) {
-		if (event == CPUFREQ_GOV_POLICY_INIT)
+	if (event == CPUFREQ_GOV_POLICY_INIT) {
+		if (ret)
+			module_put(policy->governor->owner);
+		else
 			policy->governor->initialized++;
-		else if (event == CPUFREQ_GOV_POLICY_EXIT)
-			policy->governor->initialized--;
-	}
-
-	if (((event == CPUFREQ_GOV_POLICY_INIT) && ret) ||
-			((event == CPUFREQ_GOV_POLICY_EXIT) && !ret))
+	} else if (event == CPUFREQ_GOV_POLICY_EXIT) {
+		policy->governor->initialized--;
 		module_put(policy->governor->owner);
+	}
 
 	return ret;
 }
@@ -2100,20 +2204,8 @@ static int cpufreq_set_policy(struct cpu
 	old_gov = policy->governor;
 	/* end old governor */
 	if (old_gov) {
-		ret = cpufreq_governor(policy, CPUFREQ_GOV_STOP);
-		if (ret) {
-			/* This can happen due to race with other operations */
-			pr_debug("%s: Failed to Stop Governor: %s (%d)\n",
-				 __func__, old_gov->name, ret);
-			return ret;
-		}
-
-		ret = cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT);
-		if (ret) {
-			pr_err("%s: Failed to Exit Governor: %s (%d)\n",
-			       __func__, old_gov->name, ret);
-			return ret;
-		}
+		cpufreq_stop_governor(policy);
+		cpufreq_exit_governor(policy);
 	}
 
 	/* start new governor */
@@ -2125,7 +2217,7 @@ static int cpufreq_set_policy(struct cpu
 			pr_debug("cpufreq: governor change\n");
 			return 0;
 		}
-		cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT);
+		cpufreq_exit_governor(policy);
 	}
 
 	/* new governor failed, so re-start old one */
@@ -2169,6 +2261,10 @@ int cpufreq_update_policy(unsigned int c
 	 * -> ask driver for current freq and notify governors about a change
 	 */
 	if (cpufreq_driver->get && !cpufreq_driver->setpolicy) {
+		if (cpufreq_suspended) {
+			ret = -EAGAIN;
+			goto unlock;
+		}
 		new_policy.cur = cpufreq_update_current_freq(policy);
 		if (WARN_ON(!new_policy.cur)) {
 			ret = -EIO;
@@ -2193,16 +2289,13 @@ static int cpufreq_cpu_callback(struct n
 
 	switch (action & ~CPU_TASKS_FROZEN) {
 	case CPU_ONLINE:
+	case CPU_DOWN_FAILED:
 		cpufreq_online(cpu);
 		break;
 
 	case CPU_DOWN_PREPARE:
 		cpufreq_offline(cpu);
 		break;
-
-	case CPU_DOWN_FAILED:
-		cpufreq_online(cpu);
-		break;
 	}
 	return NOTIFY_OK;
 }
@@ -2377,10 +2470,7 @@ int cpufreq_register_driver(struct cpufr
 
 	register_hotcpu_notifier(&cpufreq_cpu_notifier);
 	pr_debug("driver %s up and running\n", driver_data->name);
-
-out:
-	put_online_cpus();
-	return ret;
+	goto out;
 
 err_if_unreg:
 	subsys_interface_unregister(&cpufreq_interface);
@@ -2390,7 +2480,9 @@ err_null_driver:
 	write_lock_irqsave(&cpufreq_driver_lock, flags);
 	cpufreq_driver = NULL;
 	write_unlock_irqrestore(&cpufreq_driver_lock, flags);
-	goto out;
+out:
+	put_online_cpus();
+	return ret;
 }
 EXPORT_SYMBOL_GPL(cpufreq_register_driver);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/cpufreq_conservative.c linux-libre-4.7-gnu/drivers/cpufreq/cpufreq_conservative.c
--- linux-libre-4.6-gnu/drivers/cpufreq/cpufreq_conservative.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/cpufreq_conservative.c	2016-07-24 15:23:50.000000000 -0400
@@ -129,9 +129,10 @@ static struct notifier_block cs_cpufreq_
 /************************** sysfs interface ************************/
 static struct dbs_governor cs_dbs_gov;
 
-static ssize_t store_sampling_down_factor(struct dbs_data *dbs_data,
-		const char *buf, size_t count)
+static ssize_t store_sampling_down_factor(struct gov_attr_set *attr_set,
+					  const char *buf, size_t count)
 {
+	struct dbs_data *dbs_data = to_dbs_data(attr_set);
 	unsigned int input;
 	int ret;
 	ret = sscanf(buf, "%u", &input);
@@ -143,9 +144,10 @@ static ssize_t store_sampling_down_facto
 	return count;
 }
 
-static ssize_t store_up_threshold(struct dbs_data *dbs_data, const char *buf,
-		size_t count)
+static ssize_t store_up_threshold(struct gov_attr_set *attr_set,
+				  const char *buf, size_t count)
 {
+	struct dbs_data *dbs_data = to_dbs_data(attr_set);
 	struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
 	unsigned int input;
 	int ret;
@@ -158,9 +160,10 @@ static ssize_t store_up_threshold(struct
 	return count;
 }
 
-static ssize_t store_down_threshold(struct dbs_data *dbs_data, const char *buf,
-		size_t count)
+static ssize_t store_down_threshold(struct gov_attr_set *attr_set,
+				    const char *buf, size_t count)
 {
+	struct dbs_data *dbs_data = to_dbs_data(attr_set);
 	struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
 	unsigned int input;
 	int ret;
@@ -175,9 +178,10 @@ static ssize_t store_down_threshold(stru
 	return count;
 }
 
-static ssize_t store_ignore_nice_load(struct dbs_data *dbs_data,
-		const char *buf, size_t count)
+static ssize_t store_ignore_nice_load(struct gov_attr_set *attr_set,
+				      const char *buf, size_t count)
 {
+	struct dbs_data *dbs_data = to_dbs_data(attr_set);
 	unsigned int input;
 	int ret;
 
@@ -199,9 +203,10 @@ static ssize_t store_ignore_nice_load(st
 	return count;
 }
 
-static ssize_t store_freq_step(struct dbs_data *dbs_data, const char *buf,
-		size_t count)
+static ssize_t store_freq_step(struct gov_attr_set *attr_set, const char *buf,
+			       size_t count)
 {
+	struct dbs_data *dbs_data = to_dbs_data(attr_set);
 	struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
 	unsigned int input;
 	int ret;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/cpufreq-dt.c linux-libre-4.7-gnu/drivers/cpufreq/cpufreq-dt.c
--- linux-libre-4.6-gnu/drivers/cpufreq/cpufreq-dt.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/cpufreq-dt.c	2016-07-24 15:23:50.000000000 -0400
@@ -15,7 +15,6 @@
 #include <linux/cpu.h>
 #include <linux/cpu_cooling.h>
 #include <linux/cpufreq.h>
-#include <linux/cpufreq-dt.h>
 #include <linux/cpumask.h>
 #include <linux/err.h>
 #include <linux/module.h>
@@ -147,7 +146,7 @@ static int cpufreq_init(struct cpufreq_p
 	struct clk *cpu_clk;
 	struct dev_pm_opp *suspend_opp;
 	unsigned int transition_latency;
-	bool opp_v1 = false;
+	bool fallback = false;
 	const char *name;
 	int ret;
 
@@ -167,14 +166,16 @@ static int cpufreq_init(struct cpufreq_p
 	/* Get OPP-sharing information from "operating-points-v2" bindings */
 	ret = dev_pm_opp_of_get_sharing_cpus(cpu_dev, policy->cpus);
 	if (ret) {
+		if (ret != -ENOENT)
+			goto out_put_clk;
+
 		/*
 		 * operating-points-v2 not supported, fallback to old method of
-		 * finding shared-OPPs for backward compatibility.
+		 * finding shared-OPPs for backward compatibility if the
+		 * platform hasn't set sharing CPUs.
 		 */
-		if (ret == -ENOENT)
-			opp_v1 = true;
-		else
-			goto out_put_clk;
+		if (dev_pm_opp_get_sharing_cpus(cpu_dev, policy->cpus))
+			fallback = true;
 	}
 
 	/*
@@ -214,11 +215,8 @@ static int cpufreq_init(struct cpufreq_p
 		goto out_free_opp;
 	}
 
-	if (opp_v1) {
-		struct cpufreq_dt_platform_data *pd = cpufreq_get_driver_data();
-
-		if (!pd || !pd->independent_clocks)
-			cpumask_setall(policy->cpus);
+	if (fallback) {
+		cpumask_setall(policy->cpus);
 
 		/*
 		 * OPP tables are initialized only for policy->cpu, do it for
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/cpufreq-dt-platdev.c linux-libre-4.7-gnu/drivers/cpufreq/cpufreq-dt-platdev.c
--- linux-libre-4.6-gnu/drivers/cpufreq/cpufreq-dt-platdev.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/cpufreq/cpufreq-dt-platdev.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2016 Linaro.
+ * Viresh Kumar <viresh.kumar@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+static const struct of_device_id machines[] __initconst = {
+	{ .compatible = "allwinner,sun4i-a10", },
+	{ .compatible = "allwinner,sun5i-a10s", },
+	{ .compatible = "allwinner,sun5i-a13", },
+	{ .compatible = "allwinner,sun5i-r8", },
+	{ .compatible = "allwinner,sun6i-a31", },
+	{ .compatible = "allwinner,sun6i-a31s", },
+	{ .compatible = "allwinner,sun7i-a20", },
+	{ .compatible = "allwinner,sun8i-a23", },
+	{ .compatible = "allwinner,sun8i-a33", },
+	{ .compatible = "allwinner,sun8i-a83t", },
+	{ .compatible = "allwinner,sun8i-h3", },
+
+	{ .compatible = "hisilicon,hi6220", },
+
+	{ .compatible = "fsl,imx27", },
+	{ .compatible = "fsl,imx51", },
+	{ .compatible = "fsl,imx53", },
+	{ .compatible = "fsl,imx7d", },
+
+	{ .compatible = "marvell,berlin", },
+
+	{ .compatible = "samsung,exynos3250", },
+	{ .compatible = "samsung,exynos4210", },
+	{ .compatible = "samsung,exynos4212", },
+	{ .compatible = "samsung,exynos4412", },
+	{ .compatible = "samsung,exynos5250", },
+#ifndef CONFIG_BL_SWITCHER
+	{ .compatible = "samsung,exynos5420", },
+	{ .compatible = "samsung,exynos5800", },
+#endif
+
+	{ .compatible = "renesas,emev2", },
+	{ .compatible = "renesas,r7s72100", },
+	{ .compatible = "renesas,r8a73a4", },
+	{ .compatible = "renesas,r8a7740", },
+	{ .compatible = "renesas,r8a7778", },
+	{ .compatible = "renesas,r8a7779", },
+	{ .compatible = "renesas,r8a7790", },
+	{ .compatible = "renesas,r8a7791", },
+	{ .compatible = "renesas,r8a7793", },
+	{ .compatible = "renesas,r8a7794", },
+	{ .compatible = "renesas,sh73a0", },
+
+	{ .compatible = "rockchip,rk2928", },
+	{ .compatible = "rockchip,rk3036", },
+	{ .compatible = "rockchip,rk3066a", },
+	{ .compatible = "rockchip,rk3066b", },
+	{ .compatible = "rockchip,rk3188", },
+	{ .compatible = "rockchip,rk3228", },
+	{ .compatible = "rockchip,rk3288", },
+	{ .compatible = "rockchip,rk3366", },
+	{ .compatible = "rockchip,rk3368", },
+	{ .compatible = "rockchip,rk3399", },
+
+	{ .compatible = "sigma,tango4" },
+
+	{ .compatible = "ti,omap2", },
+	{ .compatible = "ti,omap3", },
+	{ .compatible = "ti,omap4", },
+	{ .compatible = "ti,omap5", },
+
+	{ .compatible = "xlnx,zynq-7000", },
+};
+
+static int __init cpufreq_dt_platdev_init(void)
+{
+	struct device_node *np = of_find_node_by_path("/");
+	const struct of_device_id *match;
+
+	if (!np)
+		return -ENODEV;
+
+	match = of_match_node(machines, np);
+	of_node_put(np);
+	if (!match)
+		return -ENODEV;
+
+	return PTR_ERR_OR_ZERO(platform_device_register_simple("cpufreq-dt", -1,
+							       NULL, 0));
+}
+device_initcall(cpufreq_dt_platdev_init);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/cpufreq_governor_attr_set.c linux-libre-4.7-gnu/drivers/cpufreq/cpufreq_governor_attr_set.c
--- linux-libre-4.6-gnu/drivers/cpufreq/cpufreq_governor_attr_set.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/cpufreq/cpufreq_governor_attr_set.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,84 @@
+/*
+ * Abstract code for CPUFreq governor tunable sysfs attributes.
+ *
+ * Copyright (C) 2016, Intel Corporation
+ * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "cpufreq_governor.h"
+
+static inline struct gov_attr_set *to_gov_attr_set(struct kobject *kobj)
+{
+	return container_of(kobj, struct gov_attr_set, kobj);
+}
+
+static inline struct governor_attr *to_gov_attr(struct attribute *attr)
+{
+	return container_of(attr, struct governor_attr, attr);
+}
+
+static ssize_t governor_show(struct kobject *kobj, struct attribute *attr,
+			     char *buf)
+{
+	struct governor_attr *gattr = to_gov_attr(attr);
+
+	return gattr->show(to_gov_attr_set(kobj), buf);
+}
+
+static ssize_t governor_store(struct kobject *kobj, struct attribute *attr,
+			      const char *buf, size_t count)
+{
+	struct gov_attr_set *attr_set = to_gov_attr_set(kobj);
+	struct governor_attr *gattr = to_gov_attr(attr);
+	int ret;
+
+	mutex_lock(&attr_set->update_lock);
+	ret = attr_set->usage_count ? gattr->store(attr_set, buf, count) : -EBUSY;
+	mutex_unlock(&attr_set->update_lock);
+	return ret;
+}
+
+const struct sysfs_ops governor_sysfs_ops = {
+	.show	= governor_show,
+	.store	= governor_store,
+};
+EXPORT_SYMBOL_GPL(governor_sysfs_ops);
+
+void gov_attr_set_init(struct gov_attr_set *attr_set, struct list_head *list_node)
+{
+	INIT_LIST_HEAD(&attr_set->policy_list);
+	mutex_init(&attr_set->update_lock);
+	attr_set->usage_count = 1;
+	list_add(list_node, &attr_set->policy_list);
+}
+EXPORT_SYMBOL_GPL(gov_attr_set_init);
+
+void gov_attr_set_get(struct gov_attr_set *attr_set, struct list_head *list_node)
+{
+	mutex_lock(&attr_set->update_lock);
+	attr_set->usage_count++;
+	list_add(list_node, &attr_set->policy_list);
+	mutex_unlock(&attr_set->update_lock);
+}
+EXPORT_SYMBOL_GPL(gov_attr_set_get);
+
+unsigned int gov_attr_set_put(struct gov_attr_set *attr_set, struct list_head *list_node)
+{
+	unsigned int count;
+
+	mutex_lock(&attr_set->update_lock);
+	list_del(list_node);
+	count = --attr_set->usage_count;
+	mutex_unlock(&attr_set->update_lock);
+	if (count)
+		return count;
+
+	kobject_put(&attr_set->kobj);
+	mutex_destroy(&attr_set->update_lock);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(gov_attr_set_put);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/cpufreq_governor.c linux-libre-4.7-gnu/drivers/cpufreq/cpufreq_governor.c
--- linux-libre-4.6-gnu/drivers/cpufreq/cpufreq_governor.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/cpufreq_governor.c	2016-07-24 15:23:50.000000000 -0400
@@ -43,9 +43,10 @@ static DEFINE_MUTEX(gov_dbs_data_mutex);
  * This must be called with dbs_data->mutex held, otherwise traversing
  * policy_dbs_list isn't safe.
  */
-ssize_t store_sampling_rate(struct dbs_data *dbs_data, const char *buf,
+ssize_t store_sampling_rate(struct gov_attr_set *attr_set, const char *buf,
 			    size_t count)
 {
+	struct dbs_data *dbs_data = to_dbs_data(attr_set);
 	struct policy_dbs_info *policy_dbs;
 	unsigned int rate;
 	int ret;
@@ -59,7 +60,7 @@ ssize_t store_sampling_rate(struct dbs_d
 	 * We are operating under dbs_data->mutex and so the list and its
 	 * entries can't be freed concurrently.
 	 */
-	list_for_each_entry(policy_dbs, &dbs_data->policy_dbs_list, list) {
+	list_for_each_entry(policy_dbs, &attr_set->policy_list, list) {
 		mutex_lock(&policy_dbs->timer_mutex);
 		/*
 		 * On 32-bit architectures this may race with the
@@ -96,13 +97,13 @@ void gov_update_cpu_data(struct dbs_data
 {
 	struct policy_dbs_info *policy_dbs;
 
-	list_for_each_entry(policy_dbs, &dbs_data->policy_dbs_list, list) {
+	list_for_each_entry(policy_dbs, &dbs_data->attr_set.policy_list, list) {
 		unsigned int j;
 
 		for_each_cpu(j, policy_dbs->policy->cpus) {
 			struct cpu_dbs_info *j_cdbs = &per_cpu(cpu_dbs, j);
 
-			j_cdbs->prev_cpu_idle = get_cpu_idle_time(j, &j_cdbs->prev_cpu_wall,
+			j_cdbs->prev_cpu_idle = get_cpu_idle_time(j, &j_cdbs->prev_update_time,
 								  dbs_data->io_is_busy);
 			if (dbs_data->ignore_nice_load)
 				j_cdbs->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE];
@@ -111,54 +112,6 @@ void gov_update_cpu_data(struct dbs_data
 }
 EXPORT_SYMBOL_GPL(gov_update_cpu_data);
 
-static inline struct dbs_data *to_dbs_data(struct kobject *kobj)
-{
-	return container_of(kobj, struct dbs_data, kobj);
-}
-
-static inline struct governor_attr *to_gov_attr(struct attribute *attr)
-{
-	return container_of(attr, struct governor_attr, attr);
-}
-
-static ssize_t governor_show(struct kobject *kobj, struct attribute *attr,
-			     char *buf)
-{
-	struct dbs_data *dbs_data = to_dbs_data(kobj);
-	struct governor_attr *gattr = to_gov_attr(attr);
-
-	return gattr->show(dbs_data, buf);
-}
-
-static ssize_t governor_store(struct kobject *kobj, struct attribute *attr,
-			      const char *buf, size_t count)
-{
-	struct dbs_data *dbs_data = to_dbs_data(kobj);
-	struct governor_attr *gattr = to_gov_attr(attr);
-	int ret = -EBUSY;
-
-	mutex_lock(&dbs_data->mutex);
-
-	if (dbs_data->usage_count)
-		ret = gattr->store(dbs_data, buf, count);
-
-	mutex_unlock(&dbs_data->mutex);
-
-	return ret;
-}
-
-/*
- * Sysfs Ops for accessing governor attributes.
- *
- * All show/store invocations for governor specific sysfs attributes, will first
- * call the below show/store callbacks and the attribute specific callback will
- * be called from within it.
- */
-static const struct sysfs_ops governor_sysfs_ops = {
-	.show	= governor_show,
-	.store	= governor_store,
-};
-
 unsigned int dbs_update(struct cpufreq_policy *policy)
 {
 	struct policy_dbs_info *policy_dbs = policy->governor_data;
@@ -184,14 +137,14 @@ unsigned int dbs_update(struct cpufreq_p
 	/* Get Absolute Load */
 	for_each_cpu(j, policy->cpus) {
 		struct cpu_dbs_info *j_cdbs = &per_cpu(cpu_dbs, j);
-		u64 cur_wall_time, cur_idle_time;
-		unsigned int idle_time, wall_time;
+		u64 update_time, cur_idle_time;
+		unsigned int idle_time, time_elapsed;
 		unsigned int load;
 
-		cur_idle_time = get_cpu_idle_time(j, &cur_wall_time, io_busy);
+		cur_idle_time = get_cpu_idle_time(j, &update_time, io_busy);
 
-		wall_time = cur_wall_time - j_cdbs->prev_cpu_wall;
-		j_cdbs->prev_cpu_wall = cur_wall_time;
+		time_elapsed = update_time - j_cdbs->prev_update_time;
+		j_cdbs->prev_update_time = update_time;
 
 		idle_time = cur_idle_time - j_cdbs->prev_cpu_idle;
 		j_cdbs->prev_cpu_idle = cur_idle_time;
@@ -203,47 +156,62 @@ unsigned int dbs_update(struct cpufreq_p
 			j_cdbs->prev_cpu_nice = cur_nice;
 		}
 
-		if (unlikely(!wall_time || wall_time < idle_time))
-			continue;
-
-		/*
-		 * If the CPU had gone completely idle, and a task just woke up
-		 * on this CPU now, it would be unfair to calculate 'load' the
-		 * usual way for this elapsed time-window, because it will show
-		 * near-zero load, irrespective of how CPU intensive that task
-		 * actually is. This is undesirable for latency-sensitive bursty
-		 * workloads.
-		 *
-		 * To avoid this, we reuse the 'load' from the previous
-		 * time-window and give this task a chance to start with a
-		 * reasonably high CPU frequency. (However, we shouldn't over-do
-		 * this copy, lest we get stuck at a high load (high frequency)
-		 * for too long, even when the current system load has actually
-		 * dropped down. So we perform the copy only once, upon the
-		 * first wake-up from idle.)
-		 *
-		 * Detecting this situation is easy: the governor's utilization
-		 * update handler would not have run during CPU-idle periods.
-		 * Hence, an unusually large 'wall_time' (as compared to the
-		 * sampling rate) indicates this scenario.
-		 *
-		 * prev_load can be zero in two cases and we must recalculate it
-		 * for both cases:
-		 * - during long idle intervals
-		 * - explicitly set to zero
-		 */
-		if (unlikely(wall_time > (2 * sampling_rate) &&
-			     j_cdbs->prev_load)) {
+		if (unlikely(!time_elapsed)) {
+			/*
+			 * That can only happen when this function is called
+			 * twice in a row with a very short interval between the
+			 * calls, so the previous load value can be used then.
+			 */
 			load = j_cdbs->prev_load;
-
+		} else if (unlikely(time_elapsed > 2 * sampling_rate &&
+				    j_cdbs->prev_load)) {
 			/*
-			 * Perform a destructive copy, to ensure that we copy
-			 * the previous load only once, upon the first wake-up
-			 * from idle.
+			 * If the CPU had gone completely idle and a task has
+			 * just woken up on this CPU now, it would be unfair to
+			 * calculate 'load' the usual way for this elapsed
+			 * time-window, because it would show near-zero load,
+			 * irrespective of how CPU intensive that task actually
+			 * was. This is undesirable for latency-sensitive bursty
+			 * workloads.
+			 *
+			 * To avoid this, reuse the 'load' from the previous
+			 * time-window and give this task a chance to start with
+			 * a reasonably high CPU frequency. However, that
+			 * shouldn't be over-done, lest we get stuck at a high
+			 * load (high frequency) for too long, even when the
+			 * current system load has actually dropped down, so
+			 * clear prev_load to guarantee that the load will be
+			 * computed again next time.
+			 *
+			 * Detecting this situation is easy: the governor's
+			 * utilization update handler would not have run during
+			 * CPU-idle periods.  Hence, an unusually large
+			 * 'time_elapsed' (as compared to the sampling rate)
+			 * indicates this scenario.
 			 */
+			load = j_cdbs->prev_load;
 			j_cdbs->prev_load = 0;
 		} else {
-			load = 100 * (wall_time - idle_time) / wall_time;
+			if (time_elapsed >= idle_time) {
+				load = 100 * (time_elapsed - idle_time) / time_elapsed;
+			} else {
+				/*
+				 * That can happen if idle_time is returned by
+				 * get_cpu_idle_time_jiffy().  In that case
+				 * idle_time is roughly equal to the difference
+				 * between time_elapsed and "busy time" obtained
+				 * from CPU statistics.  Then, the "busy time"
+				 * can end up being greater than time_elapsed
+				 * (for example, if jiffies_64 and the CPU
+				 * statistics are updated by different CPUs),
+				 * so idle_time may in fact be negative.  That
+				 * means, though, that the CPU was busy all
+				 * the time (on the rough average) during the
+				 * last sampling interval and 100 can be
+				 * returned as the load.
+				 */
+				load = (int)idle_time < 0 ? 100 : 0;
+			}
 			j_cdbs->prev_load = load;
 		}
 
@@ -254,43 +222,6 @@ unsigned int dbs_update(struct cpufreq_p
 }
 EXPORT_SYMBOL_GPL(dbs_update);
 
-static void gov_set_update_util(struct policy_dbs_info *policy_dbs,
-				unsigned int delay_us)
-{
-	struct cpufreq_policy *policy = policy_dbs->policy;
-	int cpu;
-
-	gov_update_sample_delay(policy_dbs, delay_us);
-	policy_dbs->last_sample_time = 0;
-
-	for_each_cpu(cpu, policy->cpus) {
-		struct cpu_dbs_info *cdbs = &per_cpu(cpu_dbs, cpu);
-
-		cpufreq_set_update_util_data(cpu, &cdbs->update_util);
-	}
-}
-
-static inline void gov_clear_update_util(struct cpufreq_policy *policy)
-{
-	int i;
-
-	for_each_cpu(i, policy->cpus)
-		cpufreq_set_update_util_data(i, NULL);
-
-	synchronize_sched();
-}
-
-static void gov_cancel_work(struct cpufreq_policy *policy)
-{
-	struct policy_dbs_info *policy_dbs = policy->governor_data;
-
-	gov_clear_update_util(policy_dbs->policy);
-	irq_work_sync(&policy_dbs->irq_work);
-	cancel_work_sync(&policy_dbs->work);
-	atomic_set(&policy_dbs->work_count, 0);
-	policy_dbs->work_in_progress = false;
-}
-
 static void dbs_work_handler(struct work_struct *work)
 {
 	struct policy_dbs_info *policy_dbs;
@@ -378,6 +309,44 @@ static void dbs_update_util_handler(stru
 	irq_work_queue(&policy_dbs->irq_work);
 }
 
+static void gov_set_update_util(struct policy_dbs_info *policy_dbs,
+				unsigned int delay_us)
+{
+	struct cpufreq_policy *policy = policy_dbs->policy;
+	int cpu;
+
+	gov_update_sample_delay(policy_dbs, delay_us);
+	policy_dbs->last_sample_time = 0;
+
+	for_each_cpu(cpu, policy->cpus) {
+		struct cpu_dbs_info *cdbs = &per_cpu(cpu_dbs, cpu);
+
+		cpufreq_add_update_util_hook(cpu, &cdbs->update_util,
+					     dbs_update_util_handler);
+	}
+}
+
+static inline void gov_clear_update_util(struct cpufreq_policy *policy)
+{
+	int i;
+
+	for_each_cpu(i, policy->cpus)
+		cpufreq_remove_update_util_hook(i);
+
+	synchronize_sched();
+}
+
+static void gov_cancel_work(struct cpufreq_policy *policy)
+{
+	struct policy_dbs_info *policy_dbs = policy->governor_data;
+
+	gov_clear_update_util(policy_dbs->policy);
+	irq_work_sync(&policy_dbs->irq_work);
+	cancel_work_sync(&policy_dbs->work);
+	atomic_set(&policy_dbs->work_count, 0);
+	policy_dbs->work_in_progress = false;
+}
+
 static struct policy_dbs_info *alloc_policy_dbs_info(struct cpufreq_policy *policy,
 						     struct dbs_governor *gov)
 {
@@ -400,7 +369,6 @@ static struct policy_dbs_info *alloc_pol
 		struct cpu_dbs_info *j_cdbs = &per_cpu(cpu_dbs, j);
 
 		j_cdbs->policy_dbs = policy_dbs;
-		j_cdbs->update_util.func = dbs_update_util_handler;
 	}
 	return policy_dbs;
 }
@@ -449,10 +417,7 @@ static int cpufreq_governor_init(struct
 		policy_dbs->dbs_data = dbs_data;
 		policy->governor_data = policy_dbs;
 
-		mutex_lock(&dbs_data->mutex);
-		dbs_data->usage_count++;
-		list_add(&policy_dbs->list, &dbs_data->policy_dbs_list);
-		mutex_unlock(&dbs_data->mutex);
+		gov_attr_set_get(&dbs_data->attr_set, &policy_dbs->list);
 		goto out;
 	}
 
@@ -462,8 +427,7 @@ static int cpufreq_governor_init(struct
 		goto free_policy_dbs_info;
 	}
 
-	INIT_LIST_HEAD(&dbs_data->policy_dbs_list);
-	mutex_init(&dbs_data->mutex);
+	gov_attr_set_init(&dbs_data->attr_set, &policy_dbs->list);
 
 	ret = gov->init(dbs_data, !policy->governor->initialized);
 	if (ret)
@@ -483,14 +447,11 @@ static int cpufreq_governor_init(struct
 	if (!have_governor_per_policy())
 		gov->gdbs_data = dbs_data;
 
-	policy->governor_data = policy_dbs;
-
 	policy_dbs->dbs_data = dbs_data;
-	dbs_data->usage_count = 1;
-	list_add(&policy_dbs->list, &dbs_data->policy_dbs_list);
+	policy->governor_data = policy_dbs;
 
 	gov->kobj_type.sysfs_ops = &governor_sysfs_ops;
-	ret = kobject_init_and_add(&dbs_data->kobj, &gov->kobj_type,
+	ret = kobject_init_and_add(&dbs_data->attr_set.kobj, &gov->kobj_type,
 				   get_governor_parent_kobj(policy),
 				   "%s", gov->gov.name);
 	if (!ret)
@@ -519,29 +480,21 @@ static int cpufreq_governor_exit(struct
 	struct dbs_governor *gov = dbs_governor_of(policy);
 	struct policy_dbs_info *policy_dbs = policy->governor_data;
 	struct dbs_data *dbs_data = policy_dbs->dbs_data;
-	int count;
+	unsigned int count;
 
 	/* Protect gov->gdbs_data against concurrent updates. */
 	mutex_lock(&gov_dbs_data_mutex);
 
-	mutex_lock(&dbs_data->mutex);
-	list_del(&policy_dbs->list);
-	count = --dbs_data->usage_count;
-	mutex_unlock(&dbs_data->mutex);
-
-	if (!count) {
-		kobject_put(&dbs_data->kobj);
+	count = gov_attr_set_put(&dbs_data->attr_set, &policy_dbs->list);
 
-		policy->governor_data = NULL;
+	policy->governor_data = NULL;
 
+	if (!count) {
 		if (!have_governor_per_policy())
 			gov->gdbs_data = NULL;
 
 		gov->exit(dbs_data, policy->governor->initialized == 1);
-		mutex_destroy(&dbs_data->mutex);
 		kfree(dbs_data);
-	} else {
-		policy->governor_data = NULL;
 	}
 
 	free_policy_dbs_info(policy_dbs, gov);
@@ -570,12 +523,12 @@ static int cpufreq_governor_start(struct
 
 	for_each_cpu(j, policy->cpus) {
 		struct cpu_dbs_info *j_cdbs = &per_cpu(cpu_dbs, j);
-		unsigned int prev_load;
-
-		j_cdbs->prev_cpu_idle = get_cpu_idle_time(j, &j_cdbs->prev_cpu_wall, io_busy);
 
-		prev_load = j_cdbs->prev_cpu_wall - j_cdbs->prev_cpu_idle;
-		j_cdbs->prev_load = 100 * prev_load / (unsigned int)j_cdbs->prev_cpu_wall;
+		j_cdbs->prev_cpu_idle = get_cpu_idle_time(j, &j_cdbs->prev_update_time, io_busy);
+		/*
+		 * Make the first invocation of dbs_update() compute the load.
+		 */
+		j_cdbs->prev_load = 0;
 
 		if (ignore_nice)
 			j_cdbs->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE];
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/cpufreq_governor.h linux-libre-4.7-gnu/drivers/cpufreq/cpufreq_governor.h
--- linux-libre-4.6-gnu/drivers/cpufreq/cpufreq_governor.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/cpufreq_governor.h	2016-07-24 15:23:50.000000000 -0400
@@ -24,20 +24,6 @@
 #include <linux/module.h>
 #include <linux/mutex.h>
 
-/*
- * The polling frequency depends on the capability of the processor. Default
- * polling frequency is 1000 times the transition latency of the processor. The
- * governor will work on any processor with transition latency <= 10ms, using
- * appropriate sampling rate.
- *
- * For CPUs with transition latency > 10ms (mostly drivers with CPUFREQ_ETERNAL)
- * this governor will not work. All times here are in us (micro seconds).
- */
-#define MIN_SAMPLING_RATE_RATIO			(2)
-#define LATENCY_MULTIPLIER			(1000)
-#define MIN_LATENCY_MULTIPLIER			(20)
-#define TRANSITION_LATENCY_LIMIT		(10 * 1000 * 1000)
-
 /* Ondemand Sampling types */
 enum {OD_NORMAL_SAMPLE, OD_SUB_SAMPLE};
 
@@ -52,7 +38,7 @@ enum {OD_NORMAL_SAMPLE, OD_SUB_SAMPLE};
 
 /* Governor demand based switching data (per-policy or global). */
 struct dbs_data {
-	int usage_count;
+	struct gov_attr_set attr_set;
 	void *tuners;
 	unsigned int min_sampling_rate;
 	unsigned int ignore_nice_load;
@@ -60,37 +46,27 @@ struct dbs_data {
 	unsigned int sampling_down_factor;
 	unsigned int up_threshold;
 	unsigned int io_is_busy;
-
-	struct kobject kobj;
-	struct list_head policy_dbs_list;
-	/*
-	 * Protect concurrent updates to governor tunables from sysfs,
-	 * policy_dbs_list and usage_count.
-	 */
-	struct mutex mutex;
 };
 
-/* Governor's specific attributes */
-struct dbs_data;
-struct governor_attr {
-	struct attribute attr;
-	ssize_t (*show)(struct dbs_data *dbs_data, char *buf);
-	ssize_t (*store)(struct dbs_data *dbs_data, const char *buf,
-			 size_t count);
-};
+static inline struct dbs_data *to_dbs_data(struct gov_attr_set *attr_set)
+{
+	return container_of(attr_set, struct dbs_data, attr_set);
+}
 
 #define gov_show_one(_gov, file_name)					\
 static ssize_t show_##file_name						\
-(struct dbs_data *dbs_data, char *buf)					\
+(struct gov_attr_set *attr_set, char *buf)				\
 {									\
+	struct dbs_data *dbs_data = to_dbs_data(attr_set);		\
 	struct _gov##_dbs_tuners *tuners = dbs_data->tuners;		\
 	return sprintf(buf, "%u\n", tuners->file_name);			\
 }
 
 #define gov_show_one_common(file_name)					\
 static ssize_t show_##file_name						\
-(struct dbs_data *dbs_data, char *buf)					\
+(struct gov_attr_set *attr_set, char *buf)				\
 {									\
+	struct dbs_data *dbs_data = to_dbs_data(attr_set);		\
 	return sprintf(buf, "%u\n", dbs_data->file_name);		\
 }
 
@@ -135,7 +111,7 @@ static inline void gov_update_sample_del
 /* Per cpu structures */
 struct cpu_dbs_info {
 	u64 prev_cpu_idle;
-	u64 prev_cpu_wall;
+	u64 prev_update_time;
 	u64 prev_cpu_nice;
 	/*
 	 * Used to keep track of load in the previous interval. However, when
@@ -184,7 +160,7 @@ void od_register_powersave_bias_handler(
 		(struct cpufreq_policy *, unsigned int, unsigned int),
 		unsigned int powersave_bias);
 void od_unregister_powersave_bias_handler(void);
-ssize_t store_sampling_rate(struct dbs_data *dbs_data, const char *buf,
+ssize_t store_sampling_rate(struct gov_attr_set *attr_set, const char *buf,
 			    size_t count);
 void gov_update_cpu_data(struct dbs_data *dbs_data);
 #endif /* _CPUFREQ_GOVERNOR_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/cpufreq-nforce2.c linux-libre-4.7-gnu/drivers/cpufreq/cpufreq-nforce2.c
--- linux-libre-4.6-gnu/drivers/cpufreq/cpufreq-nforce2.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/cpufreq-nforce2.c	2016-07-24 15:23:50.000000000 -0400
@@ -7,6 +7,8 @@
  *  BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous*
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
@@ -56,8 +58,6 @@ MODULE_PARM_DESC(fid, "CPU multiplier to
 MODULE_PARM_DESC(min_fsb,
 		"Minimum FSB to use, if not defined: current FSB - 50");
 
-#define PFX "cpufreq-nforce2: "
-
 /**
  * nforce2_calc_fsb - calculate FSB
  * @pll: PLL value
@@ -174,13 +174,13 @@ static int nforce2_set_fsb(unsigned int
 	int pll = 0;
 
 	if ((fsb > max_fsb) || (fsb < NFORCE2_MIN_FSB)) {
-		printk(KERN_ERR PFX "FSB %d is out of range!\n", fsb);
+		pr_err("FSB %d is out of range!\n", fsb);
 		return -EINVAL;
 	}
 
 	tfsb = nforce2_fsb_read(0);
 	if (!tfsb) {
-		printk(KERN_ERR PFX "Error while reading the FSB\n");
+		pr_err("Error while reading the FSB\n");
 		return -EINVAL;
 	}
 
@@ -276,8 +276,7 @@ static int nforce2_target(struct cpufreq
 	/* local_irq_save(flags); */
 
 	if (nforce2_set_fsb(target_fsb) < 0)
-		printk(KERN_ERR PFX "Changing FSB to %d failed\n",
-			target_fsb);
+		pr_err("Changing FSB to %d failed\n", target_fsb);
 	else
 		pr_debug("Changed FSB successfully to %d\n",
 			target_fsb);
@@ -325,8 +324,7 @@ static int nforce2_cpu_init(struct cpufr
 	/* FIX: Get FID from CPU */
 	if (!fid) {
 		if (!cpu_khz) {
-			printk(KERN_WARNING PFX
-			"cpu_khz not set, can't calculate multiplier!\n");
+			pr_warn("cpu_khz not set, can't calculate multiplier!\n");
 			return -ENODEV;
 		}
 
@@ -341,8 +339,8 @@ static int nforce2_cpu_init(struct cpufr
 		}
 	}
 
-	printk(KERN_INFO PFX "FSB currently at %i MHz, FID %d.%d\n", fsb,
-	       fid / 10, fid % 10);
+	pr_info("FSB currently at %i MHz, FID %d.%d\n",
+		fsb, fid / 10, fid % 10);
 
 	/* Set maximum FSB to FSB at boot time */
 	max_fsb = nforce2_fsb_read(1);
@@ -401,11 +399,9 @@ static int nforce2_detect_chipset(void)
 	if (nforce2_dev == NULL)
 		return -ENODEV;
 
-	printk(KERN_INFO PFX "Detected nForce2 chipset revision %X\n",
-	       nforce2_dev->revision);
-	printk(KERN_INFO PFX
-	       "FSB changing is maybe unstable and can lead to "
-	       "crashes and data loss.\n");
+	pr_info("Detected nForce2 chipset revision %X\n",
+		nforce2_dev->revision);
+	pr_info("FSB changing is maybe unstable and can lead to crashes and data loss\n");
 
 	return 0;
 }
@@ -423,7 +419,7 @@ static int __init nforce2_init(void)
 
 	/* detect chipset */
 	if (nforce2_detect_chipset()) {
-		printk(KERN_INFO PFX "No nForce2 chipset.\n");
+		pr_info("No nForce2 chipset\n");
 		return -ENODEV;
 	}
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/cpufreq_ondemand.c linux-libre-4.7-gnu/drivers/cpufreq/cpufreq_ondemand.c
--- linux-libre-4.6-gnu/drivers/cpufreq/cpufreq_ondemand.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/cpufreq_ondemand.c	2016-07-24 15:23:50.000000000 -0400
@@ -207,9 +207,10 @@ static unsigned int od_dbs_timer(struct
 /************************** sysfs interface ************************/
 static struct dbs_governor od_dbs_gov;
 
-static ssize_t store_io_is_busy(struct dbs_data *dbs_data, const char *buf,
-		size_t count)
+static ssize_t store_io_is_busy(struct gov_attr_set *attr_set, const char *buf,
+				size_t count)
 {
+	struct dbs_data *dbs_data = to_dbs_data(attr_set);
 	unsigned int input;
 	int ret;
 
@@ -224,9 +225,10 @@ static ssize_t store_io_is_busy(struct d
 	return count;
 }
 
-static ssize_t store_up_threshold(struct dbs_data *dbs_data, const char *buf,
-		size_t count)
+static ssize_t store_up_threshold(struct gov_attr_set *attr_set,
+				  const char *buf, size_t count)
 {
+	struct dbs_data *dbs_data = to_dbs_data(attr_set);
 	unsigned int input;
 	int ret;
 	ret = sscanf(buf, "%u", &input);
@@ -240,9 +242,10 @@ static ssize_t store_up_threshold(struct
 	return count;
 }
 
-static ssize_t store_sampling_down_factor(struct dbs_data *dbs_data,
-		const char *buf, size_t count)
+static ssize_t store_sampling_down_factor(struct gov_attr_set *attr_set,
+					  const char *buf, size_t count)
 {
+	struct dbs_data *dbs_data = to_dbs_data(attr_set);
 	struct policy_dbs_info *policy_dbs;
 	unsigned int input;
 	int ret;
@@ -254,7 +257,7 @@ static ssize_t store_sampling_down_facto
 	dbs_data->sampling_down_factor = input;
 
 	/* Reset down sampling multiplier in case it was active */
-	list_for_each_entry(policy_dbs, &dbs_data->policy_dbs_list, list) {
+	list_for_each_entry(policy_dbs, &attr_set->policy_list, list) {
 		/*
 		 * Doing this without locking might lead to using different
 		 * rate_mult values in od_update() and od_dbs_timer().
@@ -267,9 +270,10 @@ static ssize_t store_sampling_down_facto
 	return count;
 }
 
-static ssize_t store_ignore_nice_load(struct dbs_data *dbs_data,
-		const char *buf, size_t count)
+static ssize_t store_ignore_nice_load(struct gov_attr_set *attr_set,
+				      const char *buf, size_t count)
 {
+	struct dbs_data *dbs_data = to_dbs_data(attr_set);
 	unsigned int input;
 	int ret;
 
@@ -291,9 +295,10 @@ static ssize_t store_ignore_nice_load(st
 	return count;
 }
 
-static ssize_t store_powersave_bias(struct dbs_data *dbs_data, const char *buf,
-		size_t count)
+static ssize_t store_powersave_bias(struct gov_attr_set *attr_set,
+				    const char *buf, size_t count)
 {
+	struct dbs_data *dbs_data = to_dbs_data(attr_set);
 	struct od_dbs_tuners *od_tuners = dbs_data->tuners;
 	struct policy_dbs_info *policy_dbs;
 	unsigned int input;
@@ -308,7 +313,7 @@ static ssize_t store_powersave_bias(stru
 
 	od_tuners->powersave_bias = input;
 
-	list_for_each_entry(policy_dbs, &dbs_data->policy_dbs_list, list)
+	list_for_each_entry(policy_dbs, &attr_set->policy_list, list)
 		ondemand_powersave_bias_init(policy_dbs->policy);
 
 	return count;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/cpufreq_userspace.c linux-libre-4.7-gnu/drivers/cpufreq/cpufreq_userspace.c
--- linux-libre-4.6-gnu/drivers/cpufreq/cpufreq_userspace.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/cpufreq_userspace.c	2016-07-24 15:23:50.000000000 -0400
@@ -17,6 +17,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/slab.h>
 
 static DEFINE_PER_CPU(unsigned int, cpu_is_managed);
 static DEFINE_MUTEX(userspace_mutex);
@@ -31,6 +32,7 @@ static DEFINE_MUTEX(userspace_mutex);
 static int cpufreq_set(struct cpufreq_policy *policy, unsigned int freq)
 {
 	int ret = -EINVAL;
+	unsigned int *setspeed = policy->governor_data;
 
 	pr_debug("cpufreq_set for cpu %u, freq %u kHz\n", policy->cpu, freq);
 
@@ -38,6 +40,8 @@ static int cpufreq_set(struct cpufreq_po
 	if (!per_cpu(cpu_is_managed, policy->cpu))
 		goto err;
 
+	*setspeed = freq;
+
 	ret = __cpufreq_driver_target(policy, freq, CPUFREQ_RELATION_L);
  err:
 	mutex_unlock(&userspace_mutex);
@@ -49,19 +53,45 @@ static ssize_t show_speed(struct cpufreq
 	return sprintf(buf, "%u\n", policy->cur);
 }
 
+static int cpufreq_userspace_policy_init(struct cpufreq_policy *policy)
+{
+	unsigned int *setspeed;
+
+	setspeed = kzalloc(sizeof(*setspeed), GFP_KERNEL);
+	if (!setspeed)
+		return -ENOMEM;
+
+	policy->governor_data = setspeed;
+	return 0;
+}
+
 static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
 				   unsigned int event)
 {
+	unsigned int *setspeed = policy->governor_data;
 	unsigned int cpu = policy->cpu;
 	int rc = 0;
 
+	if (event == CPUFREQ_GOV_POLICY_INIT)
+		return cpufreq_userspace_policy_init(policy);
+
+	if (!setspeed)
+		return -EINVAL;
+
 	switch (event) {
+	case CPUFREQ_GOV_POLICY_EXIT:
+		mutex_lock(&userspace_mutex);
+		policy->governor_data = NULL;
+		kfree(setspeed);
+		mutex_unlock(&userspace_mutex);
+		break;
 	case CPUFREQ_GOV_START:
 		BUG_ON(!policy->cur);
 		pr_debug("started managing cpu %u\n", cpu);
 
 		mutex_lock(&userspace_mutex);
 		per_cpu(cpu_is_managed, cpu) = 1;
+		*setspeed = policy->cur;
 		mutex_unlock(&userspace_mutex);
 		break;
 	case CPUFREQ_GOV_STOP:
@@ -69,20 +99,23 @@ static int cpufreq_governor_userspace(st
 
 		mutex_lock(&userspace_mutex);
 		per_cpu(cpu_is_managed, cpu) = 0;
+		*setspeed = 0;
 		mutex_unlock(&userspace_mutex);
 		break;
 	case CPUFREQ_GOV_LIMITS:
 		mutex_lock(&userspace_mutex);
-		pr_debug("limit event for cpu %u: %u - %u kHz, currently %u kHz\n",
-			cpu, policy->min, policy->max,
-			policy->cur);
+		pr_debug("limit event for cpu %u: %u - %u kHz, currently %u kHz, last set to %u kHz\n",
+			cpu, policy->min, policy->max, policy->cur, *setspeed);
 
-		if (policy->max < policy->cur)
+		if (policy->max < *setspeed)
 			__cpufreq_driver_target(policy, policy->max,
 						CPUFREQ_RELATION_H);
-		else if (policy->min > policy->cur)
+		else if (policy->min > *setspeed)
 			__cpufreq_driver_target(policy, policy->min,
 						CPUFREQ_RELATION_L);
+		else
+			__cpufreq_driver_target(policy, *setspeed,
+						CPUFREQ_RELATION_L);
 		mutex_unlock(&userspace_mutex);
 		break;
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/elanfreq.c linux-libre-4.7-gnu/drivers/cpufreq/elanfreq.c
--- linux-libre-4.6-gnu/drivers/cpufreq/elanfreq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/elanfreq.c	2016-07-24 15:23:50.000000000 -0400
@@ -16,6 +16,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -185,7 +187,7 @@ static int elanfreq_cpu_init(struct cpuf
 static int __init elanfreq_setup(char *str)
 {
 	max_freq = simple_strtoul(str, &str, 0);
-	printk(KERN_WARNING "You're using the deprecated elanfreq command line option. Use elanfreq.max_freq instead, please!\n");
+	pr_warn("You're using the deprecated elanfreq command line option. Use elanfreq.max_freq instead, please!\n");
 	return 1;
 }
 __setup("elanfreq=", elanfreq_setup);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/e_powersaver.c linux-libre-4.7-gnu/drivers/cpufreq/e_powersaver.c
--- linux-libre-4.6-gnu/drivers/cpufreq/e_powersaver.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/e_powersaver.c	2016-07-24 15:23:50.000000000 -0400
@@ -6,6 +6,8 @@
  *  BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous*
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -20,7 +22,7 @@
 #include <asm/msr.h>
 #include <asm/tsc.h>
 
-#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
+#if IS_ENABLED(CONFIG_ACPI_PROCESSOR)
 #include <linux/acpi.h>
 #include <acpi/processor.h>
 #endif
@@ -33,7 +35,7 @@
 
 struct eps_cpu_data {
 	u32 fsb;
-#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
+#if IS_ENABLED(CONFIG_ACPI_PROCESSOR)
 	u32 bios_limit;
 #endif
 	struct cpufreq_frequency_table freq_table[];
@@ -46,7 +48,7 @@ static int freq_failsafe_off;
 static int voltage_failsafe_off;
 static int set_max_voltage;
 
-#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
+#if IS_ENABLED(CONFIG_ACPI_PROCESSOR)
 static int ignore_acpi_limit;
 
 static struct acpi_processor_performance *eps_acpi_cpu_perf;
@@ -141,11 +143,9 @@ static int eps_set_state(struct eps_cpu_
 	/* Print voltage and multiplier */
 	rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
 	current_voltage = lo & 0xff;
-	printk(KERN_INFO "eps: Current voltage = %dmV\n",
-		current_voltage * 16 + 700);
+	pr_info("Current voltage = %dmV\n", current_voltage * 16 + 700);
 	current_multiplier = (lo >> 8) & 0xff;
-	printk(KERN_INFO "eps: Current multiplier = %d\n",
-		current_multiplier);
+	pr_info("Current multiplier = %d\n", current_multiplier);
 	}
 #endif
 	return 0;
@@ -166,7 +166,7 @@ static int eps_target(struct cpufreq_pol
 	dest_state = centaur->freq_table[index].driver_data & 0xffff;
 	ret = eps_set_state(centaur, policy, dest_state);
 	if (ret)
-		printk(KERN_ERR "eps: Timeout!\n");
+		pr_err("Timeout!\n");
 	return ret;
 }
 
@@ -186,7 +186,7 @@ static int eps_cpu_init(struct cpufreq_p
 	int k, step, voltage;
 	int ret;
 	int states;
-#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
+#if IS_ENABLED(CONFIG_ACPI_PROCESSOR)
 	unsigned int limit;
 #endif
 
@@ -194,36 +194,36 @@ static int eps_cpu_init(struct cpufreq_p
 		return -ENODEV;
 
 	/* Check brand */
-	printk(KERN_INFO "eps: Detected VIA ");
+	pr_info("Detected VIA ");
 
 	switch (c->x86_model) {
 	case 10:
 		rdmsr(0x1153, lo, hi);
 		brand = (((lo >> 2) ^ lo) >> 18) & 3;
-		printk(KERN_CONT "Model A ");
+		pr_cont("Model A ");
 		break;
 	case 13:
 		rdmsr(0x1154, lo, hi);
 		brand = (((lo >> 4) ^ (lo >> 2))) & 0x000000ff;
-		printk(KERN_CONT "Model D ");
+		pr_cont("Model D ");
 		break;
 	}
 
 	switch (brand) {
 	case EPS_BRAND_C7M:
-		printk(KERN_CONT "C7-M\n");
+		pr_cont("C7-M\n");
 		break;
 	case EPS_BRAND_C7:
-		printk(KERN_CONT "C7\n");
+		pr_cont("C7\n");
 		break;
 	case EPS_BRAND_EDEN:
-		printk(KERN_CONT "Eden\n");
+		pr_cont("Eden\n");
 		break;
 	case EPS_BRAND_C7D:
-		printk(KERN_CONT "C7-D\n");
+		pr_cont("C7-D\n");
 		break;
 	case EPS_BRAND_C3:
-		printk(KERN_CONT "C3\n");
+		pr_cont("C3\n");
 		return -ENODEV;
 		break;
 	}
@@ -235,7 +235,7 @@ static int eps_cpu_init(struct cpufreq_p
 		/* Can be locked at 0 */
 		rdmsrl(MSR_IA32_MISC_ENABLE, val);
 		if (!(val & MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP)) {
-			printk(KERN_INFO "eps: Can't enable Enhanced PowerSaver\n");
+			pr_info("Can't enable Enhanced PowerSaver\n");
 			return -ENODEV;
 		}
 	}
@@ -243,22 +243,19 @@ static int eps_cpu_init(struct cpufreq_p
 	/* Print voltage and multiplier */
 	rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
 	current_voltage = lo & 0xff;
-	printk(KERN_INFO "eps: Current voltage = %dmV\n",
-			current_voltage * 16 + 700);
+	pr_info("Current voltage = %dmV\n", current_voltage * 16 + 700);
 	current_multiplier = (lo >> 8) & 0xff;
-	printk(KERN_INFO "eps: Current multiplier = %d\n", current_multiplier);
+	pr_info("Current multiplier = %d\n", current_multiplier);
 
 	/* Print limits */
 	max_voltage = hi & 0xff;
-	printk(KERN_INFO "eps: Highest voltage = %dmV\n",
-			max_voltage * 16 + 700);
+	pr_info("Highest voltage = %dmV\n", max_voltage * 16 + 700);
 	max_multiplier = (hi >> 8) & 0xff;
-	printk(KERN_INFO "eps: Highest multiplier = %d\n", max_multiplier);
+	pr_info("Highest multiplier = %d\n", max_multiplier);
 	min_voltage = (hi >> 16) & 0xff;
-	printk(KERN_INFO "eps: Lowest voltage = %dmV\n",
-			min_voltage * 16 + 700);
+	pr_info("Lowest voltage = %dmV\n", min_voltage * 16 + 700);
 	min_multiplier = (hi >> 24) & 0xff;
-	printk(KERN_INFO "eps: Lowest multiplier = %d\n", min_multiplier);
+	pr_info("Lowest multiplier = %d\n", min_multiplier);
 
 	/* Sanity checks */
 	if (current_multiplier == 0 || max_multiplier == 0
@@ -276,34 +273,30 @@ static int eps_cpu_init(struct cpufreq_p
 
 	/* Check for systems using underclocked CPU */
 	if (!freq_failsafe_off && max_multiplier != current_multiplier) {
-		printk(KERN_INFO "eps: Your processor is running at different "
-			"frequency then its maximum. Aborting.\n");
-		printk(KERN_INFO "eps: You can use freq_failsafe_off option "
-			"to disable this check.\n");
+		pr_info("Your processor is running at different frequency then its maximum. Aborting.\n");
+		pr_info("You can use freq_failsafe_off option to disable this check.\n");
 		return -EINVAL;
 	}
 	if (!voltage_failsafe_off && max_voltage != current_voltage) {
-		printk(KERN_INFO "eps: Your processor is running at different "
-			"voltage then its maximum. Aborting.\n");
-		printk(KERN_INFO "eps: You can use voltage_failsafe_off "
-			"option to disable this check.\n");
+		pr_info("Your processor is running at different voltage then its maximum. Aborting.\n");
+		pr_info("You can use voltage_failsafe_off option to disable this check.\n");
 		return -EINVAL;
 	}
 
 	/* Calc FSB speed */
 	fsb = cpu_khz / current_multiplier;
 
-#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
+#if IS_ENABLED(CONFIG_ACPI_PROCESSOR)
 	/* Check for ACPI processor speed limit */
 	if (!ignore_acpi_limit && !eps_acpi_init()) {
 		if (!acpi_processor_get_bios_limit(policy->cpu, &limit)) {
-			printk(KERN_INFO "eps: ACPI limit %u.%uGHz\n",
+			pr_info("ACPI limit %u.%uGHz\n",
 				limit/1000000,
 				(limit%1000000)/10000);
 			eps_acpi_exit(policy);
 			/* Check if max_multiplier is in BIOS limits */
 			if (limit && max_multiplier * fsb > limit) {
-				printk(KERN_INFO "eps: Aborting.\n");
+				pr_info("Aborting\n");
 				return -EINVAL;
 			}
 		}
@@ -319,8 +312,7 @@ static int eps_cpu_init(struct cpufreq_p
 		v = (set_max_voltage - 700) / 16;
 		/* Check if voltage is within limits */
 		if (v >= min_voltage && v <= max_voltage) {
-			printk(KERN_INFO "eps: Setting %dmV as maximum.\n",
-				v * 16 + 700);
+			pr_info("Setting %dmV as maximum\n", v * 16 + 700);
 			max_voltage = v;
 		}
 	}
@@ -341,7 +333,7 @@ static int eps_cpu_init(struct cpufreq_p
 
 	/* Copy basic values */
 	centaur->fsb = fsb;
-#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
+#if IS_ENABLED(CONFIG_ACPI_PROCESSOR)
 	centaur->bios_limit = limit;
 #endif
 
@@ -426,7 +418,7 @@ module_param(freq_failsafe_off, int, 064
 MODULE_PARM_DESC(freq_failsafe_off, "Disable current vs max frequency check");
 module_param(voltage_failsafe_off, int, 0644);
 MODULE_PARM_DESC(voltage_failsafe_off, "Disable current vs max voltage check");
-#if defined CONFIG_ACPI_PROCESSOR || defined CONFIG_ACPI_PROCESSOR_MODULE
+#if IS_ENABLED(CONFIG_ACPI_PROCESSOR)
 module_param(ignore_acpi_limit, int, 0644);
 MODULE_PARM_DESC(ignore_acpi_limit, "Don't check ACPI's processor speed limit");
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/hisi-acpu-cpufreq.c linux-libre-4.7-gnu/drivers/cpufreq/hisi-acpu-cpufreq.c
--- linux-libre-4.6-gnu/drivers/cpufreq/hisi-acpu-cpufreq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/hisi-acpu-cpufreq.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,42 +0,0 @@
-/*
- * Hisilicon Platforms Using ACPU CPUFreq Support
- *
- * Copyright (c) 2015 Hisilicon Limited.
- * Copyright (c) 2015 Linaro Limited.
- *
- * Leo Yan <leo.yan@linaro.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/err.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-
-static int __init hisi_acpu_cpufreq_driver_init(void)
-{
-	struct platform_device *pdev;
-
-	if (!of_machine_is_compatible("hisilicon,hi6220"))
-		return -ENODEV;
-
-	pdev = platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
-	return PTR_ERR_OR_ZERO(pdev);
-}
-module_init(hisi_acpu_cpufreq_driver_init);
-
-MODULE_AUTHOR("Leo Yan <leo.yan@linaro.org>");
-MODULE_DESCRIPTION("Hisilicon acpu cpufreq driver");
-MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/ia64-acpi-cpufreq.c linux-libre-4.7-gnu/drivers/cpufreq/ia64-acpi-cpufreq.c
--- linux-libre-4.6-gnu/drivers/cpufreq/ia64-acpi-cpufreq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/ia64-acpi-cpufreq.c	2016-07-24 15:23:50.000000000 -0400
@@ -8,6 +8,8 @@
  *      Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/module.h>
@@ -118,8 +120,7 @@ processor_get_freq (
 
 	if (ret) {
 		set_cpus_allowed_ptr(current, &saved_mask);
-		printk(KERN_WARNING "get performance failed with error %d\n",
-		       ret);
+		pr_warn("get performance failed with error %d\n", ret);
 		ret = 0;
 		goto migrate_end;
 	}
@@ -177,7 +178,7 @@ processor_set_freq (
 
 	ret = processor_set_pstate(value);
 	if (ret) {
-		printk(KERN_WARNING "Transition failed with error %d\n", ret);
+		pr_warn("Transition failed with error %d\n", ret);
 		retval = -ENODEV;
 		goto migrate_end;
 	}
@@ -291,8 +292,7 @@ acpi_cpufreq_cpu_init (
 	/* notify BIOS that we exist */
 	acpi_processor_notify_smm(THIS_MODULE);
 
-	printk(KERN_INFO "acpi-cpufreq: CPU%u - ACPI performance management "
-	       "activated.\n", cpu);
+	pr_info("CPU%u - ACPI performance management activated\n", cpu);
 
 	for (i = 0; i < data->acpi_data.state_count; i++)
 		pr_debug("     %cP%d: %d MHz, %d mW, %d uS, %d uS, 0x%x 0x%x\n",
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/intel_pstate.c linux-libre-4.7-gnu/drivers/cpufreq/intel_pstate.c
--- linux-libre-4.6-gnu/drivers/cpufreq/intel_pstate.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/intel_pstate.c	2016-07-24 15:23:50.000000000 -0400
@@ -10,6 +10,8 @@
  * of the License.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/kernel_stat.h>
 #include <linux/module.h>
@@ -39,10 +41,17 @@
 #define ATOM_TURBO_RATIOS	0x66c
 #define ATOM_TURBO_VIDS		0x66d
 
+#ifdef CONFIG_ACPI
+#include <acpi/processor.h>
+#endif
+
 #define FRAC_BITS 8
 #define int_tofp(X) ((int64_t)(X) << FRAC_BITS)
 #define fp_toint(X) ((X) >> FRAC_BITS)
 
+#define EXT_BITS 6
+#define EXT_FRAC_BITS (EXT_BITS + FRAC_BITS)
+
 static inline int32_t mul_fp(int32_t x, int32_t y)
 {
 	return ((int64_t)x * (int64_t)y) >> FRAC_BITS;
@@ -64,12 +73,22 @@ static inline int ceiling_fp(int32_t x)
 	return ret;
 }
 
+static inline u64 mul_ext_fp(u64 x, u64 y)
+{
+	return (x * y) >> EXT_FRAC_BITS;
+}
+
+static inline u64 div_ext_fp(u64 x, u64 y)
+{
+	return div64_u64(x << EXT_FRAC_BITS, y);
+}
+
 /**
  * struct sample -	Store performance sample
- * @core_pct_busy:	Ratio of APERF/MPERF in percent, which is actual
+ * @core_avg_perf:	Ratio of APERF/MPERF which is the actual average
  *			performance during last sample period
  * @busy_scaled:	Scaled busy value which is used to calculate next
- *			P state. This can be different than core_pct_busy
+ *			P state. This can be different than core_avg_perf
  *			to account for cpu idle period
  * @aperf:		Difference of actual performance frequency clock count
  *			read from APERF MSR between last and current sample
@@ -84,7 +103,7 @@ static inline int ceiling_fp(int32_t x)
  * data for choosing next P State.
  */
 struct sample {
-	int32_t core_pct_busy;
+	int32_t core_avg_perf;
 	int32_t busy_scaled;
 	u64 aperf;
 	u64 mperf;
@@ -162,6 +181,7 @@ struct _pid {
  * struct cpudata -	Per CPU instance data storage
  * @cpu:		CPU number for this instance data
  * @update_util:	CPUFreq utility callback information
+ * @update_util_set:	CPUFreq utility callback is set
  * @pstate:		Stores P state limits for this CPU
  * @vid:		Stores VID limits for this CPU
  * @pid:		Stores PID parameters for this CPU
@@ -172,6 +192,8 @@ struct _pid {
  * @prev_cummulative_iowait: IO Wait time difference from last and
  *			current sample
  * @sample:		Storage for storing last Sample data
+ * @acpi_perf_data:	Stores ACPI perf information read from _PSS
+ * @valid_pss_table:	Set to true for valid ACPI _PSS entries found
  *
  * This structure stores per CPU instance data for all CPUs.
  */
@@ -179,6 +201,7 @@ struct cpudata {
 	int cpu;
 
 	struct update_util_data update_util;
+	bool   update_util_set;
 
 	struct pstate_data pstate;
 	struct vid_data vid;
@@ -190,6 +213,10 @@ struct cpudata {
 	u64	prev_tsc;
 	u64	prev_cummulative_iowait;
 	struct sample sample;
+#ifdef CONFIG_ACPI
+	struct acpi_processor_performance acpi_perf_data;
+	bool valid_pss_table;
+#endif
 };
 
 static struct cpudata **all_cpu_data;
@@ -258,6 +285,9 @@ static struct pstate_adjust_policy pid_p
 static struct pstate_funcs pstate_funcs;
 static int hwp_active;
 
+#ifdef CONFIG_ACPI
+static bool acpi_ppc;
+#endif
 
 /**
  * struct perf_limits - Store user and policy limits
@@ -331,6 +361,106 @@ static struct perf_limits *limits = &per
 static struct perf_limits *limits = &powersave_limits;
 #endif
 
+#ifdef CONFIG_ACPI
+
+static bool intel_pstate_get_ppc_enable_status(void)
+{
+	if (acpi_gbl_FADT.preferred_profile == PM_ENTERPRISE_SERVER ||
+	    acpi_gbl_FADT.preferred_profile == PM_PERFORMANCE_SERVER)
+		return true;
+
+	return acpi_ppc;
+}
+
+static void intel_pstate_init_acpi_perf_limits(struct cpufreq_policy *policy)
+{
+	struct cpudata *cpu;
+	int ret;
+	int i;
+
+	if (hwp_active)
+		return;
+
+	if (!intel_pstate_get_ppc_enable_status())
+		return;
+
+	cpu = all_cpu_data[policy->cpu];
+
+	ret = acpi_processor_register_performance(&cpu->acpi_perf_data,
+						  policy->cpu);
+	if (ret)
+		return;
+
+	/*
+	 * Check if the control value in _PSS is for PERF_CTL MSR, which should
+	 * guarantee that the states returned by it map to the states in our
+	 * list directly.
+	 */
+	if (cpu->acpi_perf_data.control_register.space_id !=
+						ACPI_ADR_SPACE_FIXED_HARDWARE)
+		goto err;
+
+	/*
+	 * If there is only one entry _PSS, simply ignore _PSS and continue as
+	 * usual without taking _PSS into account
+	 */
+	if (cpu->acpi_perf_data.state_count < 2)
+		goto err;
+
+	pr_debug("CPU%u - ACPI _PSS perf data\n", policy->cpu);
+	for (i = 0; i < cpu->acpi_perf_data.state_count; i++) {
+		pr_debug("     %cP%d: %u MHz, %u mW, 0x%x\n",
+			 (i == cpu->acpi_perf_data.state ? '*' : ' '), i,
+			 (u32) cpu->acpi_perf_data.states[i].core_frequency,
+			 (u32) cpu->acpi_perf_data.states[i].power,
+			 (u32) cpu->acpi_perf_data.states[i].control);
+	}
+
+	/*
+	 * The _PSS table doesn't contain whole turbo frequency range.
+	 * This just contains +1 MHZ above the max non turbo frequency,
+	 * with control value corresponding to max turbo ratio. But
+	 * when cpufreq set policy is called, it will call with this
+	 * max frequency, which will cause a reduced performance as
+	 * this driver uses real max turbo frequency as the max
+	 * frequency. So correct this frequency in _PSS table to
+	 * correct max turbo frequency based on the turbo state.
+	 * Also need to convert to MHz as _PSS freq is in MHz.
+	 */
+	if (!limits->turbo_disabled)
+		cpu->acpi_perf_data.states[0].core_frequency =
+					policy->cpuinfo.max_freq / 1000;
+	cpu->valid_pss_table = true;
+	pr_debug("_PPC limits will be enforced\n");
+
+	return;
+
+ err:
+	cpu->valid_pss_table = false;
+	acpi_processor_unregister_performance(policy->cpu);
+}
+
+static void intel_pstate_exit_perf_limits(struct cpufreq_policy *policy)
+{
+	struct cpudata *cpu;
+
+	cpu = all_cpu_data[policy->cpu];
+	if (!cpu->valid_pss_table)
+		return;
+
+	acpi_processor_unregister_performance(policy->cpu);
+}
+
+#else
+static void intel_pstate_init_acpi_perf_limits(struct cpufreq_policy *policy)
+{
+}
+
+static void intel_pstate_exit_perf_limits(struct cpufreq_policy *policy)
+{
+}
+#endif
+
 static inline void pid_reset(struct _pid *pid, int setpoint, int busy,
 			     int deadband, int integral) {
 	pid->setpoint = int_tofp(setpoint);
@@ -341,17 +471,17 @@ static inline void pid_reset(struct _pid
 
 static inline void pid_p_gain_set(struct _pid *pid, int percent)
 {
-	pid->p_gain = div_fp(int_tofp(percent), int_tofp(100));
+	pid->p_gain = div_fp(percent, 100);
 }
 
 static inline void pid_i_gain_set(struct _pid *pid, int percent)
 {
-	pid->i_gain = div_fp(int_tofp(percent), int_tofp(100));
+	pid->i_gain = div_fp(percent, 100);
 }
 
 static inline void pid_d_gain_set(struct _pid *pid, int percent)
 {
-	pid->d_gain = div_fp(int_tofp(percent), int_tofp(100));
+	pid->d_gain = div_fp(percent, 100);
 }
 
 static signed int pid_calc(struct _pid *pid, int32_t busy)
@@ -537,7 +667,7 @@ static ssize_t show_turbo_pct(struct kob
 
 	total = cpu->pstate.turbo_pstate - cpu->pstate.min_pstate + 1;
 	no_turbo = cpu->pstate.max_pstate - cpu->pstate.min_pstate + 1;
-	turbo_fp = div_fp(int_tofp(no_turbo), int_tofp(total));
+	turbo_fp = div_fp(no_turbo, total);
 	turbo_pct = 100 - fp_toint(mul_fp(turbo_fp, int_tofp(100)));
 	return sprintf(buf, "%u\n", turbo_pct);
 }
@@ -579,7 +709,7 @@ static ssize_t store_no_turbo(struct kob
 
 	update_turbo_state();
 	if (limits->turbo_disabled) {
-		pr_warn("intel_pstate: Turbo disabled by BIOS or unavailable on processor\n");
+		pr_warn("Turbo disabled by BIOS or unavailable on processor\n");
 		return -EPERM;
 	}
 
@@ -608,8 +738,7 @@ static ssize_t store_max_perf_pct(struct
 				   limits->max_perf_pct);
 	limits->max_perf_pct = max(limits->min_perf_pct,
 				   limits->max_perf_pct);
-	limits->max_perf = div_fp(int_tofp(limits->max_perf_pct),
-				  int_tofp(100));
+	limits->max_perf = div_fp(limits->max_perf_pct, 100);
 
 	if (hwp_active)
 		intel_pstate_hwp_set_online_cpus();
@@ -633,8 +762,7 @@ static ssize_t store_min_perf_pct(struct
 				   limits->min_perf_pct);
 	limits->min_perf_pct = min(limits->max_perf_pct,
 				   limits->min_perf_pct);
-	limits->min_perf = div_fp(int_tofp(limits->min_perf_pct),
-				  int_tofp(100));
+	limits->min_perf = div_fp(limits->min_perf_pct, 100);
 
 	if (hwp_active)
 		intel_pstate_hwp_set_online_cpus();
@@ -1019,15 +1147,11 @@ static void intel_pstate_get_cpu_pstates
 	intel_pstate_set_min_pstate(cpu);
 }
 
-static inline void intel_pstate_calc_busy(struct cpudata *cpu)
+static inline void intel_pstate_calc_avg_perf(struct cpudata *cpu)
 {
 	struct sample *sample = &cpu->sample;
-	int64_t core_pct;
 
-	core_pct = int_tofp(sample->aperf) * int_tofp(100);
-	core_pct = div64_u64(core_pct, int_tofp(sample->mperf));
-
-	sample->core_pct_busy = (int32_t)core_pct;
+	sample->core_avg_perf = div_ext_fp(sample->aperf, sample->mperf);
 }
 
 static inline bool intel_pstate_sample(struct cpudata *cpu, u64 time)
@@ -1070,9 +1194,14 @@ static inline bool intel_pstate_sample(s
 
 static inline int32_t get_avg_frequency(struct cpudata *cpu)
 {
-	return fp_toint(mul_fp(cpu->sample.core_pct_busy,
-			       int_tofp(cpu->pstate.max_pstate_physical *
-						cpu->pstate.scaling / 100)));
+	return mul_ext_fp(cpu->sample.core_avg_perf,
+			  cpu->pstate.max_pstate_physical * cpu->pstate.scaling);
+}
+
+static inline int32_t get_avg_pstate(struct cpudata *cpu)
+{
+	return mul_ext_fp(cpu->pstate.max_pstate_physical,
+			  cpu->sample.core_avg_perf);
 }
 
 static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu)
@@ -1107,49 +1236,43 @@ static inline int32_t get_target_pstate_
 	cpu_load = div64_u64(int_tofp(100) * mperf, sample->tsc);
 	cpu->sample.busy_scaled = cpu_load;
 
-	return cpu->pstate.current_pstate - pid_calc(&cpu->pid, cpu_load);
+	return get_avg_pstate(cpu) - pid_calc(&cpu->pid, cpu_load);
 }
 
 static inline int32_t get_target_pstate_use_performance(struct cpudata *cpu)
 {
-	int32_t core_busy, max_pstate, current_pstate, sample_ratio;
+	int32_t perf_scaled, max_pstate, current_pstate, sample_ratio;
 	u64 duration_ns;
 
 	/*
-	 * core_busy is the ratio of actual performance to max
-	 * max_pstate is the max non turbo pstate available
-	 * current_pstate was the pstate that was requested during
-	 * 	the last sample period.
-	 *
-	 * We normalize core_busy, which was our actual percent
-	 * performance to what we requested during the last sample
-	 * period. The result will be a percentage of busy at a
-	 * specified pstate.
+	 * perf_scaled is the average performance during the last sampling
+	 * period scaled by the ratio of the maximum P-state to the P-state
+	 * requested last time (in percent).  That measures the system's
+	 * response to the previous P-state selection.
 	 */
-	core_busy = cpu->sample.core_pct_busy;
-	max_pstate = int_tofp(cpu->pstate.max_pstate_physical);
-	current_pstate = int_tofp(cpu->pstate.current_pstate);
-	core_busy = mul_fp(core_busy, div_fp(max_pstate, current_pstate));
+	max_pstate = cpu->pstate.max_pstate_physical;
+	current_pstate = cpu->pstate.current_pstate;
+	perf_scaled = mul_ext_fp(cpu->sample.core_avg_perf,
+			       div_fp(100 * max_pstate, current_pstate));
 
 	/*
 	 * Since our utilization update callback will not run unless we are
 	 * in C0, check if the actual elapsed time is significantly greater (3x)
 	 * than our sample interval.  If it is, then we were idle for a long
-	 * enough period of time to adjust our busyness.
+	 * enough period of time to adjust our performance metric.
 	 */
 	duration_ns = cpu->sample.time - cpu->last_sample_time;
 	if ((s64)duration_ns > pid_params.sample_rate_ns * 3) {
-		sample_ratio = div_fp(int_tofp(pid_params.sample_rate_ns),
-				      int_tofp(duration_ns));
-		core_busy = mul_fp(core_busy, sample_ratio);
+		sample_ratio = div_fp(pid_params.sample_rate_ns, duration_ns);
+		perf_scaled = mul_fp(perf_scaled, sample_ratio);
 	} else {
 		sample_ratio = div_fp(100 * cpu->sample.mperf, cpu->sample.tsc);
 		if (sample_ratio < int_tofp(1))
-			core_busy = 0;
+			perf_scaled = 0;
 	}
 
-	cpu->sample.busy_scaled = core_busy;
-	return cpu->pstate.current_pstate - pid_calc(&cpu->pid, core_busy);
+	cpu->sample.busy_scaled = perf_scaled;
+	return cpu->pstate.current_pstate - pid_calc(&cpu->pid, perf_scaled);
 }
 
 static inline void intel_pstate_update_pstate(struct cpudata *cpu, int pstate)
@@ -1179,7 +1302,7 @@ static inline void intel_pstate_adjust_b
 	intel_pstate_update_pstate(cpu, target_pstate);
 
 	sample = &cpu->sample;
-	trace_pstate_sample(fp_toint(sample->core_pct_busy),
+	trace_pstate_sample(mul_ext_fp(100, sample->core_avg_perf),
 		fp_toint(sample->busy_scaled),
 		from,
 		cpu->pstate.current_pstate,
@@ -1199,7 +1322,7 @@ static void intel_pstate_update_util(str
 		bool sample_taken = intel_pstate_sample(cpu, time);
 
 		if (sample_taken) {
-			intel_pstate_calc_busy(cpu);
+			intel_pstate_calc_avg_perf(cpu);
 			if (!hwp_active)
 				intel_pstate_adjust_busy_pstate(cpu);
 		}
@@ -1261,37 +1384,41 @@ static int intel_pstate_init_cpu(unsigne
 
 	intel_pstate_busy_pid_reset(cpu);
 
-	cpu->update_util.func = intel_pstate_update_util;
-
-	pr_debug("intel_pstate: controlling: cpu %d\n", cpunum);
+	pr_debug("controlling: cpu %d\n", cpunum);
 
 	return 0;
 }
 
 static unsigned int intel_pstate_get(unsigned int cpu_num)
 {
-	struct sample *sample;
-	struct cpudata *cpu;
+	struct cpudata *cpu = all_cpu_data[cpu_num];
 
-	cpu = all_cpu_data[cpu_num];
-	if (!cpu)
-		return 0;
-	sample = &cpu->sample;
-	return get_avg_frequency(cpu);
+	return cpu ? get_avg_frequency(cpu) : 0;
 }
 
 static void intel_pstate_set_update_util_hook(unsigned int cpu_num)
 {
 	struct cpudata *cpu = all_cpu_data[cpu_num];
 
+	if (cpu->update_util_set)
+		return;
+
 	/* Prevent intel_pstate_update_util() from using stale data. */
 	cpu->sample.time = 0;
-	cpufreq_set_update_util_data(cpu_num, &cpu->update_util);
+	cpufreq_add_update_util_hook(cpu_num, &cpu->update_util,
+				     intel_pstate_update_util);
+	cpu->update_util_set = true;
 }
 
 static void intel_pstate_clear_update_util_hook(unsigned int cpu)
 {
-	cpufreq_set_update_util_data(cpu, NULL);
+	struct cpudata *cpu_data = all_cpu_data[cpu];
+
+	if (!cpu_data->update_util_set)
+		return;
+
+	cpufreq_remove_update_util_hook(cpu);
+	cpu_data->update_util_set = false;
 	synchronize_sched();
 }
 
@@ -1311,20 +1438,31 @@ static void intel_pstate_set_performance
 
 static int intel_pstate_set_policy(struct cpufreq_policy *policy)
 {
+	struct cpudata *cpu;
+
 	if (!policy->cpuinfo.max_freq)
 		return -ENODEV;
 
-	intel_pstate_clear_update_util_hook(policy->cpu);
+	pr_debug("set_policy cpuinfo.max %u policy->max %u\n",
+		 policy->cpuinfo.max_freq, policy->max);
+
+	cpu = all_cpu_data[0];
+	if (cpu->pstate.max_pstate_physical > cpu->pstate.max_pstate &&
+	    policy->max < policy->cpuinfo.max_freq &&
+	    policy->max > cpu->pstate.max_pstate * cpu->pstate.scaling) {
+		pr_debug("policy->max > max non turbo frequency\n");
+		policy->max = policy->cpuinfo.max_freq;
+	}
 
 	if (policy->policy == CPUFREQ_POLICY_PERFORMANCE) {
 		limits = &performance_limits;
 		if (policy->max >= policy->cpuinfo.max_freq) {
-			pr_debug("intel_pstate: set performance\n");
+			pr_debug("set performance\n");
 			intel_pstate_set_performance_limits(limits);
 			goto out;
 		}
 	} else {
-		pr_debug("intel_pstate: set powersave\n");
+		pr_debug("set powersave\n");
 		limits = &powersave_limits;
 	}
 
@@ -1343,15 +1481,13 @@ static int intel_pstate_set_policy(struc
 				   limits->max_sysfs_pct);
 	limits->max_perf_pct = max(limits->min_policy_pct,
 				   limits->max_perf_pct);
-	limits->max_perf = round_up(limits->max_perf, FRAC_BITS);
 
 	/* Make sure min_perf_pct <= max_perf_pct */
 	limits->min_perf_pct = min(limits->max_perf_pct, limits->min_perf_pct);
 
-	limits->min_perf = div_fp(int_tofp(limits->min_perf_pct),
-				  int_tofp(100));
-	limits->max_perf = div_fp(int_tofp(limits->max_perf_pct),
-				  int_tofp(100));
+	limits->min_perf = div_fp(limits->min_perf_pct, 100);
+	limits->max_perf = div_fp(limits->max_perf_pct, 100);
+	limits->max_perf = round_up(limits->max_perf, FRAC_BITS);
 
  out:
 	intel_pstate_set_update_util_hook(policy->cpu);
@@ -1377,7 +1513,7 @@ static void intel_pstate_stop_cpu(struct
 	int cpu_num = policy->cpu;
 	struct cpudata *cpu = all_cpu_data[cpu_num];
 
-	pr_debug("intel_pstate: CPU %d exiting\n", cpu_num);
+	pr_debug("CPU %d exiting\n", cpu_num);
 
 	intel_pstate_clear_update_util_hook(cpu_num);
 
@@ -1408,14 +1544,25 @@ static int intel_pstate_cpu_init(struct
 
 	/* cpuinfo and default policy values */
 	policy->cpuinfo.min_freq = cpu->pstate.min_pstate * cpu->pstate.scaling;
-	policy->cpuinfo.max_freq =
-		cpu->pstate.turbo_pstate * cpu->pstate.scaling;
+	update_turbo_state();
+	policy->cpuinfo.max_freq = limits->turbo_disabled ?
+			cpu->pstate.max_pstate : cpu->pstate.turbo_pstate;
+	policy->cpuinfo.max_freq *= cpu->pstate.scaling;
+
+	intel_pstate_init_acpi_perf_limits(policy);
 	policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
 	cpumask_set_cpu(policy->cpu, policy->cpus);
 
 	return 0;
 }
 
+static int intel_pstate_cpu_exit(struct cpufreq_policy *policy)
+{
+	intel_pstate_exit_perf_limits(policy);
+
+	return 0;
+}
+
 static struct cpufreq_driver intel_pstate_driver = {
 	.flags		= CPUFREQ_CONST_LOOPS,
 	.verify		= intel_pstate_verify_policy,
@@ -1423,6 +1570,7 @@ static struct cpufreq_driver intel_pstat
 	.resume		= intel_pstate_hwp_set_policy,
 	.get		= intel_pstate_get,
 	.init		= intel_pstate_cpu_init,
+	.exit		= intel_pstate_cpu_exit,
 	.stop_cpu	= intel_pstate_stop_cpu,
 	.name		= "intel_pstate",
 };
@@ -1466,8 +1614,7 @@ static void copy_cpu_funcs(struct pstate
 
 }
 
-#if IS_ENABLED(CONFIG_ACPI)
-#include <acpi/processor.h>
+#ifdef CONFIG_ACPI
 
 static bool intel_pstate_no_acpi_pss(void)
 {
@@ -1623,7 +1770,7 @@ hwp_cpu_matched:
 	if (intel_pstate_platform_pwr_mgmt_exists())
 		return -ENODEV;
 
-	pr_info("Intel P-state driver initializing.\n");
+	pr_info("Intel P-state driver initializing\n");
 
 	all_cpu_data = vzalloc(sizeof(void *) * num_possible_cpus());
 	if (!all_cpu_data)
@@ -1640,7 +1787,7 @@ hwp_cpu_matched:
 	intel_pstate_sysfs_expose_params();
 
 	if (hwp_active)
-		pr_info("intel_pstate: HWP enabled\n");
+		pr_info("HWP enabled\n");
 
 	return rc;
 out:
@@ -1666,13 +1813,19 @@ static int __init intel_pstate_setup(cha
 	if (!strcmp(str, "disable"))
 		no_load = 1;
 	if (!strcmp(str, "no_hwp")) {
-		pr_info("intel_pstate: HWP disabled\n");
+		pr_info("HWP disabled\n");
 		no_hwp = 1;
 	}
 	if (!strcmp(str, "force"))
 		force_load = 1;
 	if (!strcmp(str, "hwp_only"))
 		hwp_only = 1;
+
+#ifdef CONFIG_ACPI
+	if (!strcmp(str, "support_acpi_ppc"))
+		acpi_ppc = true;
+#endif
+
 	return 0;
 }
 early_param("intel_pstate", intel_pstate_setup);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/Kconfig linux-libre-4.7-gnu/drivers/cpufreq/Kconfig
--- linux-libre-4.6-gnu/drivers/cpufreq/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -18,7 +18,11 @@ config CPU_FREQ
 
 if CPU_FREQ
 
+config CPU_FREQ_GOV_ATTR_SET
+	bool
+
 config CPU_FREQ_GOV_COMMON
+	select CPU_FREQ_GOV_ATTR_SET
 	select IRQ_WORK
 	bool
 
@@ -103,6 +107,17 @@ config CPU_FREQ_DEFAULT_GOV_CONSERVATIVE
 	  Be aware that not all cpufreq drivers support the conservative
 	  governor. If unsure have a look at the help section of the
 	  driver. Fallback governor will be the performance governor.
+
+config CPU_FREQ_DEFAULT_GOV_SCHEDUTIL
+	bool "schedutil"
+	depends on SMP
+	select CPU_FREQ_GOV_SCHEDUTIL
+	select CPU_FREQ_GOV_PERFORMANCE
+	help
+	  Use the 'schedutil' CPUFreq governor by default. If unsure,
+	  have a look at the help section of that governor. The fallback
+	  governor will be 'performance'.
+
 endchoice
 
 config CPU_FREQ_GOV_PERFORMANCE
@@ -184,6 +199,26 @@ config CPU_FREQ_GOV_CONSERVATIVE
 
 	  If in doubt, say N.
 
+config CPU_FREQ_GOV_SCHEDUTIL
+	tristate "'schedutil' cpufreq policy governor"
+	depends on CPU_FREQ && SMP
+	select CPU_FREQ_GOV_ATTR_SET
+	select IRQ_WORK
+	help
+	  This governor makes decisions based on the utilization data provided
+	  by the scheduler.  It sets the CPU frequency to be proportional to
+	  the utilization/capacity ratio coming from the scheduler.  If the
+	  utilization is frequency-invariant, the new frequency is also
+	  proportional to the maximum available frequency.  If that is not the
+	  case, it is proportional to the current frequency of the CPU.  The
+	  frequency tipping point is at utilization/capacity equal to 80% in
+	  both cases.
+
+	  To compile this driver as a module, choose M here: the module will
+	  be called cpufreq_schedutil.
+
+	  If in doubt, say N.
+
 comment "CPU frequency scaling drivers"
 
 config CPUFREQ_DT
@@ -191,6 +226,7 @@ config CPUFREQ_DT
 	depends on HAVE_CLK && OF
 	# if CPU_THERMAL is on and THERMAL=m, CPUFREQ_DT cannot be =y:
 	depends on !CPU_THERMAL || THERMAL
+	select CPUFREQ_DT_PLATDEV
 	select PM_OPP
 	help
 	  This adds a generic DT based cpufreq driver for frequency management.
@@ -199,6 +235,15 @@ config CPUFREQ_DT
 
 	  If in doubt, say N.
 
+config CPUFREQ_DT_PLATDEV
+	bool
+	help
+	  This adds a generic DT based cpufreq platdev driver for frequency
+	  management.  This creates a 'cpufreq-dt' platform device, on the
+	  supported platforms.
+
+	  If in doubt, say N.
+
 if X86
 source "drivers/cpufreq/Kconfig.x86"
 endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/Kconfig.arm linux-libre-4.7-gnu/drivers/cpufreq/Kconfig.arm
--- linux-libre-4.6-gnu/drivers/cpufreq/Kconfig.arm	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/Kconfig.arm	2016-07-24 15:23:50.000000000 -0400
@@ -50,15 +50,6 @@ config ARM_HIGHBANK_CPUFREQ
 
 	  If in doubt, say N.
 
-config ARM_HISI_ACPU_CPUFREQ
-	tristate "Hisilicon ACPU CPUfreq driver"
-	depends on ARCH_HISI && CPUFREQ_DT
-	select PM_OPP
-	help
-	  This enables the hisilicon ACPU CPUfreq driver.
-
-	  If in doubt, say N.
-
 config ARM_IMX6Q_CPUFREQ
 	tristate "Freescale i.MX6 cpufreq support"
 	depends on ARCH_MXC
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/Kconfig.x86 linux-libre-4.7-gnu/drivers/cpufreq/Kconfig.x86
--- linux-libre-4.6-gnu/drivers/cpufreq/Kconfig.x86	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/Kconfig.x86	2016-07-24 15:23:50.000000000 -0400
@@ -5,6 +5,7 @@
 config X86_INTEL_PSTATE
        bool "Intel P state control"
        depends on X86
+       select ACPI_PROCESSOR if ACPI
        help
           This driver provides a P state for Intel core processors.
 	  The driver implements an internal governor and will become
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/longhaul.c linux-libre-4.7-gnu/drivers/cpufreq/longhaul.c
--- linux-libre-4.6-gnu/drivers/cpufreq/longhaul.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/longhaul.c	2016-07-24 15:23:50.000000000 -0400
@@ -21,6 +21,8 @@
  *  BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous*
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
@@ -40,8 +42,6 @@
 
 #include "longhaul.h"
 
-#define PFX "longhaul: "
-
 #define TYPE_LONGHAUL_V1	1
 #define TYPE_LONGHAUL_V2	2
 #define TYPE_POWERSAVER		3
@@ -347,14 +347,13 @@ retry_loop:
 	freqs.new = calc_speed(longhaul_get_cpu_mult());
 	/* Check if requested frequency is set. */
 	if (unlikely(freqs.new != speed)) {
-		printk(KERN_INFO PFX "Failed to set requested frequency!\n");
+		pr_info("Failed to set requested frequency!\n");
 		/* Revision ID = 1 but processor is expecting revision key
 		 * equal to 0. Jumpers at the bottom of processor will change
 		 * multiplier and FSB, but will not change bits in Longhaul
 		 * MSR nor enable voltage scaling. */
 		if (!revid_errata) {
-			printk(KERN_INFO PFX "Enabling \"Ignore Revision ID\" "
-						"option.\n");
+			pr_info("Enabling \"Ignore Revision ID\" option\n");
 			revid_errata = 1;
 			msleep(200);
 			goto retry_loop;
@@ -364,11 +363,10 @@ retry_loop:
 		 * but it doesn't change frequency. I tried poking various
 		 * bits in northbridge registers, but without success. */
 		if (longhaul_flags & USE_ACPI_C3) {
-			printk(KERN_INFO PFX "Disabling ACPI C3 support.\n");
+			pr_info("Disabling ACPI C3 support\n");
 			longhaul_flags &= ~USE_ACPI_C3;
 			if (revid_errata) {
-				printk(KERN_INFO PFX "Disabling \"Ignore "
-						"Revision ID\" option.\n");
+				pr_info("Disabling \"Ignore Revision ID\" option\n");
 				revid_errata = 0;
 			}
 			msleep(200);
@@ -379,7 +377,7 @@ retry_loop:
 		 * RevID = 1. RevID errata will make things right. Just
 		 * to be 100% sure. */
 		if (longhaul_version == TYPE_LONGHAUL_V2) {
-			printk(KERN_INFO PFX "Switching to Longhaul ver. 1\n");
+			pr_info("Switching to Longhaul ver. 1\n");
 			longhaul_version = TYPE_LONGHAUL_V1;
 			msleep(200);
 			goto retry_loop;
@@ -387,8 +385,7 @@ retry_loop:
 	}
 
 	if (!bm_timeout) {
-		printk(KERN_INFO PFX "Warning: Timeout while waiting for "
-				"idle PCI bus.\n");
+		pr_info("Warning: Timeout while waiting for idle PCI bus\n");
 		return -EBUSY;
 	}
 
@@ -433,12 +430,12 @@ static int longhaul_get_ranges(void)
 	/* Get current frequency */
 	mult = longhaul_get_cpu_mult();
 	if (mult == -1) {
-		printk(KERN_INFO PFX "Invalid (reserved) multiplier!\n");
+		pr_info("Invalid (reserved) multiplier!\n");
 		return -EINVAL;
 	}
 	fsb = guess_fsb(mult);
 	if (fsb == 0) {
-		printk(KERN_INFO PFX "Invalid (reserved) FSB!\n");
+		pr_info("Invalid (reserved) FSB!\n");
 		return -EINVAL;
 	}
 	/* Get max multiplier - as we always did.
@@ -468,11 +465,11 @@ static int longhaul_get_ranges(void)
 		 print_speed(highest_speed/1000));
 
 	if (lowest_speed == highest_speed) {
-		printk(KERN_INFO PFX "highestspeed == lowest, aborting.\n");
+		pr_info("highestspeed == lowest, aborting\n");
 		return -EINVAL;
 	}
 	if (lowest_speed > highest_speed) {
-		printk(KERN_INFO PFX "nonsense! lowest (%d > %d) !\n",
+		pr_info("nonsense! lowest (%d > %d) !\n",
 			lowest_speed, highest_speed);
 		return -EINVAL;
 	}
@@ -538,16 +535,16 @@ static void longhaul_setup_voltagescalin
 
 	rdmsrl(MSR_VIA_LONGHAUL, longhaul.val);
 	if (!(longhaul.bits.RevisionID & 1)) {
-		printk(KERN_INFO PFX "Voltage scaling not supported by CPU.\n");
+		pr_info("Voltage scaling not supported by CPU\n");
 		return;
 	}
 
 	if (!longhaul.bits.VRMRev) {
-		printk(KERN_INFO PFX "VRM 8.5\n");
+		pr_info("VRM 8.5\n");
 		vrm_mV_table = &vrm85_mV[0];
 		mV_vrm_table = &mV_vrm85[0];
 	} else {
-		printk(KERN_INFO PFX "Mobile VRM\n");
+		pr_info("Mobile VRM\n");
 		if (cpu_model < CPU_NEHEMIAH)
 			return;
 		vrm_mV_table = &mobilevrm_mV[0];
@@ -558,27 +555,21 @@ static void longhaul_setup_voltagescalin
 	maxvid = vrm_mV_table[longhaul.bits.MaximumVID];
 
 	if (minvid.mV == 0 || maxvid.mV == 0 || minvid.mV > maxvid.mV) {
-		printk(KERN_INFO PFX "Bogus values Min:%d.%03d Max:%d.%03d. "
-					"Voltage scaling disabled.\n",
-					minvid.mV/1000, minvid.mV%1000,
-					maxvid.mV/1000, maxvid.mV%1000);
+		pr_info("Bogus values Min:%d.%03d Max:%d.%03d - Voltage scaling disabled\n",
+			minvid.mV/1000, minvid.mV%1000,
+			maxvid.mV/1000, maxvid.mV%1000);
 		return;
 	}
 
 	if (minvid.mV == maxvid.mV) {
-		printk(KERN_INFO PFX "Claims to support voltage scaling but "
-				"min & max are both %d.%03d. "
-				"Voltage scaling disabled\n",
-				maxvid.mV/1000, maxvid.mV%1000);
+		pr_info("Claims to support voltage scaling but min & max are both %d.%03d - Voltage scaling disabled\n",
+			maxvid.mV/1000, maxvid.mV%1000);
 		return;
 	}
 
 	/* How many voltage steps*/
 	numvscales = maxvid.pos - minvid.pos + 1;
-	printk(KERN_INFO PFX
-		"Max VID=%d.%03d  "
-		"Min VID=%d.%03d, "
-		"%d possible voltage scales\n",
+	pr_info("Max VID=%d.%03d  Min VID=%d.%03d, %d possible voltage scales\n",
 		maxvid.mV/1000, maxvid.mV%1000,
 		minvid.mV/1000, minvid.mV%1000,
 		numvscales);
@@ -617,12 +608,12 @@ static void longhaul_setup_voltagescalin
 			pos = minvid.pos;
 		freq_pos->driver_data |= mV_vrm_table[pos] << 8;
 		vid = vrm_mV_table[mV_vrm_table[pos]];
-		printk(KERN_INFO PFX "f: %d kHz, index: %d, vid: %d mV\n",
+		pr_info("f: %d kHz, index: %d, vid: %d mV\n",
 			speed, (int)(freq_pos - longhaul_table), vid.mV);
 	}
 
 	can_scale_voltage = 1;
-	printk(KERN_INFO PFX "Voltage scaling enabled.\n");
+	pr_info("Voltage scaling enabled\n");
 }
 
 
@@ -720,8 +711,7 @@ static int enable_arbiter_disable(void)
 			pci_write_config_byte(dev, reg, pci_cmd);
 			pci_read_config_byte(dev, reg, &pci_cmd);
 			if (!(pci_cmd & 1<<7)) {
-				printk(KERN_ERR PFX
-					"Can't enable access to port 0x22.\n");
+				pr_err("Can't enable access to port 0x22\n");
 				status = 0;
 			}
 		}
@@ -758,8 +748,7 @@ static int longhaul_setup_southbridge(vo
 		if (pci_cmd & 1 << 7) {
 			pci_read_config_dword(dev, 0x88, &acpi_regs_addr);
 			acpi_regs_addr &= 0xff00;
-			printk(KERN_INFO PFX "ACPI I/O at 0x%x\n",
-					acpi_regs_addr);
+			pr_info("ACPI I/O at 0x%x\n", acpi_regs_addr);
 		}
 
 		pci_dev_put(dev);
@@ -853,14 +842,14 @@ static int longhaul_cpu_init(struct cpuf
 			longhaul_version = TYPE_LONGHAUL_V1;
 	}
 
-	printk(KERN_INFO PFX "VIA %s CPU detected.  ", cpuname);
+	pr_info("VIA %s CPU detected.  ", cpuname);
 	switch (longhaul_version) {
 	case TYPE_LONGHAUL_V1:
 	case TYPE_LONGHAUL_V2:
-		printk(KERN_CONT "Longhaul v%d supported.\n", longhaul_version);
+		pr_cont("Longhaul v%d supported\n", longhaul_version);
 		break;
 	case TYPE_POWERSAVER:
-		printk(KERN_CONT "Powersaver supported.\n");
+		pr_cont("Powersaver supported\n");
 		break;
 	};
 
@@ -889,15 +878,14 @@ static int longhaul_cpu_init(struct cpuf
 	if (!(longhaul_flags & USE_ACPI_C3
 	     || longhaul_flags & USE_NORTHBRIDGE)
 	    && ((pr == NULL) || !(pr->flags.bm_control))) {
-		printk(KERN_ERR PFX
-			"No ACPI support. Unsupported northbridge.\n");
+		pr_err("No ACPI support: Unsupported northbridge\n");
 		return -ENODEV;
 	}
 
 	if (longhaul_flags & USE_NORTHBRIDGE)
-		printk(KERN_INFO PFX "Using northbridge support.\n");
+		pr_info("Using northbridge support\n");
 	if (longhaul_flags & USE_ACPI_C3)
-		printk(KERN_INFO PFX "Using ACPI support.\n");
+		pr_info("Using ACPI support\n");
 
 	ret = longhaul_get_ranges();
 	if (ret != 0)
@@ -934,20 +922,18 @@ static int __init longhaul_init(void)
 		return -ENODEV;
 
 	if (!enable) {
-		printk(KERN_ERR PFX "Option \"enable\" not set. Aborting.\n");
+		pr_err("Option \"enable\" not set - Aborting\n");
 		return -ENODEV;
 	}
 #ifdef CONFIG_SMP
 	if (num_online_cpus() > 1) {
-		printk(KERN_ERR PFX "More than 1 CPU detected, "
-				"longhaul disabled.\n");
+		pr_err("More than 1 CPU detected, longhaul disabled\n");
 		return -ENODEV;
 	}
 #endif
 #ifdef CONFIG_X86_IO_APIC
-	if (cpu_has_apic) {
-		printk(KERN_ERR PFX "APIC detected. Longhaul is currently "
-				"broken in this configuration.\n");
+	if (boot_cpu_has(X86_FEATURE_APIC)) {
+		pr_err("APIC detected. Longhaul is currently broken in this configuration.\n");
 		return -ENODEV;
 	}
 #endif
@@ -955,7 +941,7 @@ static int __init longhaul_init(void)
 	case 6 ... 9:
 		return cpufreq_register_driver(&longhaul_driver);
 	case 10:
-		printk(KERN_ERR PFX "Use acpi-cpufreq driver for VIA C7\n");
+		pr_err("Use acpi-cpufreq driver for VIA C7\n");
 	default:
 		;
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/loongson1-cpufreq.c linux-libre-4.7-gnu/drivers/cpufreq/loongson1-cpufreq.c
--- linux-libre-4.6-gnu/drivers/cpufreq/loongson1-cpufreq.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/cpufreq/loongson1-cpufreq.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,222 @@
+/*
+ * CPU Frequency Scaling for Loongson 1 SoC
+ *
+ * Copyright (C) 2014-2016 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/cpu.h>
+#include <linux/cpufreq.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <cpufreq.h>
+#include <loongson1.h>
+
+struct ls1x_cpufreq {
+	struct device *dev;
+	struct clk *clk;	/* CPU clk */
+	struct clk *mux_clk;	/* MUX of CPU clk */
+	struct clk *pll_clk;	/* PLL clk */
+	struct clk *osc_clk;	/* OSC clk */
+	unsigned int max_freq;
+	unsigned int min_freq;
+};
+
+static struct ls1x_cpufreq *cpufreq;
+
+static int ls1x_cpufreq_notifier(struct notifier_block *nb,
+				 unsigned long val, void *data)
+{
+	if (val == CPUFREQ_POSTCHANGE)
+		current_cpu_data.udelay_val = loops_per_jiffy;
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block ls1x_cpufreq_notifier_block = {
+	.notifier_call = ls1x_cpufreq_notifier
+};
+
+static int ls1x_cpufreq_target(struct cpufreq_policy *policy,
+			       unsigned int index)
+{
+	struct device *cpu_dev = get_cpu_device(policy->cpu);
+	unsigned int old_freq, new_freq;
+
+	old_freq = policy->cur;
+	new_freq = policy->freq_table[index].frequency;
+
+	/*
+	 * The procedure of reconfiguring CPU clk is as below.
+	 *
+	 *  - Reparent CPU clk to OSC clk
+	 *  - Reset CPU clock (very important)
+	 *  - Reconfigure CPU DIV
+	 *  - Reparent CPU clk back to CPU DIV clk
+	 */
+
+	clk_set_parent(policy->clk, cpufreq->osc_clk);
+	__raw_writel(__raw_readl(LS1X_CLK_PLL_DIV) | RST_CPU_EN | RST_CPU,
+		     LS1X_CLK_PLL_DIV);
+	__raw_writel(__raw_readl(LS1X_CLK_PLL_DIV) & ~(RST_CPU_EN | RST_CPU),
+		     LS1X_CLK_PLL_DIV);
+	clk_set_rate(cpufreq->mux_clk, new_freq * 1000);
+	clk_set_parent(policy->clk, cpufreq->mux_clk);
+	dev_dbg(cpu_dev, "%u KHz --> %u KHz\n", old_freq, new_freq);
+
+	return 0;
+}
+
+static int ls1x_cpufreq_init(struct cpufreq_policy *policy)
+{
+	struct device *cpu_dev = get_cpu_device(policy->cpu);
+	struct cpufreq_frequency_table *freq_tbl;
+	unsigned int pll_freq, freq;
+	int steps, i, ret;
+
+	pll_freq = clk_get_rate(cpufreq->pll_clk) / 1000;
+
+	steps = 1 << DIV_CPU_WIDTH;
+	freq_tbl = kcalloc(steps, sizeof(*freq_tbl), GFP_KERNEL);
+	if (!freq_tbl)
+		return -ENOMEM;
+
+	for (i = 0; i < (steps - 1); i++) {
+		freq = pll_freq / (i + 1);
+		if ((freq < cpufreq->min_freq) || (freq > cpufreq->max_freq))
+			freq_tbl[i].frequency = CPUFREQ_ENTRY_INVALID;
+		else
+			freq_tbl[i].frequency = freq;
+		dev_dbg(cpu_dev,
+			"cpufreq table: index %d: frequency %d\n", i,
+			freq_tbl[i].frequency);
+	}
+	freq_tbl[i].frequency = CPUFREQ_TABLE_END;
+
+	policy->clk = cpufreq->clk;
+	ret = cpufreq_generic_init(policy, freq_tbl, 0);
+	if (ret)
+		kfree(freq_tbl);
+
+	return ret;
+}
+
+static int ls1x_cpufreq_exit(struct cpufreq_policy *policy)
+{
+	kfree(policy->freq_table);
+	return 0;
+}
+
+static struct cpufreq_driver ls1x_cpufreq_driver = {
+	.name		= "cpufreq-ls1x",
+	.flags		= CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK,
+	.verify		= cpufreq_generic_frequency_table_verify,
+	.target_index	= ls1x_cpufreq_target,
+	.get		= cpufreq_generic_get,
+	.init		= ls1x_cpufreq_init,
+	.exit		= ls1x_cpufreq_exit,
+	.attr		= cpufreq_generic_attr,
+};
+
+static int ls1x_cpufreq_remove(struct platform_device *pdev)
+{
+	cpufreq_unregister_notifier(&ls1x_cpufreq_notifier_block,
+				    CPUFREQ_TRANSITION_NOTIFIER);
+	cpufreq_unregister_driver(&ls1x_cpufreq_driver);
+
+	return 0;
+}
+
+static int ls1x_cpufreq_probe(struct platform_device *pdev)
+{
+	struct plat_ls1x_cpufreq *pdata = dev_get_platdata(&pdev->dev);
+	struct clk *clk;
+	int ret;
+
+	if (!pdata || !pdata->clk_name || !pdata->osc_clk_name) {
+		dev_err(&pdev->dev, "platform data missing\n");
+		return -EINVAL;
+	}
+
+	cpufreq =
+	    devm_kzalloc(&pdev->dev, sizeof(struct ls1x_cpufreq), GFP_KERNEL);
+	if (!cpufreq)
+		return -ENOMEM;
+
+	cpufreq->dev = &pdev->dev;
+
+	clk = devm_clk_get(&pdev->dev, pdata->clk_name);
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "unable to get %s clock\n",
+			pdata->clk_name);
+		return PTR_ERR(clk);
+	}
+	cpufreq->clk = clk;
+
+	clk = clk_get_parent(clk);
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "unable to get parent of %s clock\n",
+			__clk_get_name(cpufreq->clk));
+		return PTR_ERR(clk);
+	}
+	cpufreq->mux_clk = clk;
+
+	clk = clk_get_parent(clk);
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "unable to get parent of %s clock\n",
+			__clk_get_name(cpufreq->mux_clk));
+		return PTR_ERR(clk);
+	}
+	cpufreq->pll_clk = clk;
+
+	clk = devm_clk_get(&pdev->dev, pdata->osc_clk_name);
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "unable to get %s clock\n",
+			pdata->osc_clk_name);
+		return PTR_ERR(clk);
+	}
+	cpufreq->osc_clk = clk;
+
+	cpufreq->max_freq = pdata->max_freq;
+	cpufreq->min_freq = pdata->min_freq;
+
+	ret = cpufreq_register_driver(&ls1x_cpufreq_driver);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"failed to register CPUFreq driver: %d\n", ret);
+		return ret;
+	}
+
+	ret = cpufreq_register_notifier(&ls1x_cpufreq_notifier_block,
+					CPUFREQ_TRANSITION_NOTIFIER);
+
+	if (ret) {
+		dev_err(&pdev->dev,
+			"failed to register CPUFreq notifier: %d\n",ret);
+		cpufreq_unregister_driver(&ls1x_cpufreq_driver);
+	}
+
+	return ret;
+}
+
+static struct platform_driver ls1x_cpufreq_platdrv = {
+	.probe	= ls1x_cpufreq_probe,
+	.remove	= ls1x_cpufreq_remove,
+	.driver	= {
+		.name	= "ls1x-cpufreq",
+	},
+};
+
+module_platform_driver(ls1x_cpufreq_platdrv);
+
+MODULE_AUTHOR("Kelvin Cheung <keguang.zhang@gmail.com>");
+MODULE_DESCRIPTION("Loongson1 CPUFreq driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/loongson2_cpufreq.c linux-libre-4.7-gnu/drivers/cpufreq/loongson2_cpufreq.c
--- linux-libre-4.6-gnu/drivers/cpufreq/loongson2_cpufreq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/loongson2_cpufreq.c	2016-07-24 15:23:50.000000000 -0400
@@ -10,6 +10,9 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/cpufreq.h>
 #include <linux/module.h>
 #include <linux/err.h>
@@ -76,7 +79,7 @@ static int loongson2_cpufreq_cpu_init(st
 
 	cpuclk = clk_get(NULL, "cpu_clk");
 	if (IS_ERR(cpuclk)) {
-		printk(KERN_ERR "cpufreq: couldn't get CPU clk\n");
+		pr_err("couldn't get CPU clk\n");
 		return PTR_ERR(cpuclk);
 	}
 
@@ -163,7 +166,7 @@ static int __init cpufreq_init(void)
 	if (ret)
 		return ret;
 
-	pr_info("cpufreq: Loongson-2F CPU frequency driver.\n");
+	pr_info("Loongson-2F CPU frequency driver\n");
 
 	cpufreq_register_notifier(&loongson2_cpufreq_notifier_block,
 				  CPUFREQ_TRANSITION_NOTIFIER);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/ls1x-cpufreq.c linux-libre-4.7-gnu/drivers/cpufreq/ls1x-cpufreq.c
--- linux-libre-4.6-gnu/drivers/cpufreq/ls1x-cpufreq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/ls1x-cpufreq.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,222 +0,0 @@
-/*
- * CPU Frequency Scaling for Loongson 1 SoC
- *
- * Copyright (C) 2014 Zhang, Keguang <keguang.zhang@gmail.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/clk.h>
-#include <linux/clk-provider.h>
-#include <linux/cpu.h>
-#include <linux/cpufreq.h>
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-
-#include <cpufreq.h>
-#include <loongson1.h>
-
-static struct {
-	struct device *dev;
-	struct clk *clk;	/* CPU clk */
-	struct clk *mux_clk;	/* MUX of CPU clk */
-	struct clk *pll_clk;	/* PLL clk */
-	struct clk *osc_clk;	/* OSC clk */
-	unsigned int max_freq;
-	unsigned int min_freq;
-} ls1x_cpufreq;
-
-static int ls1x_cpufreq_notifier(struct notifier_block *nb,
-				 unsigned long val, void *data)
-{
-	if (val == CPUFREQ_POSTCHANGE)
-		current_cpu_data.udelay_val = loops_per_jiffy;
-
-	return NOTIFY_OK;
-}
-
-static struct notifier_block ls1x_cpufreq_notifier_block = {
-	.notifier_call = ls1x_cpufreq_notifier
-};
-
-static int ls1x_cpufreq_target(struct cpufreq_policy *policy,
-			       unsigned int index)
-{
-	unsigned int old_freq, new_freq;
-
-	old_freq = policy->cur;
-	new_freq = policy->freq_table[index].frequency;
-
-	/*
-	 * The procedure of reconfiguring CPU clk is as below.
-	 *
-	 *  - Reparent CPU clk to OSC clk
-	 *  - Reset CPU clock (very important)
-	 *  - Reconfigure CPU DIV
-	 *  - Reparent CPU clk back to CPU DIV clk
-	 */
-
-	dev_dbg(ls1x_cpufreq.dev, "%u KHz --> %u KHz\n", old_freq, new_freq);
-	clk_set_parent(policy->clk, ls1x_cpufreq.osc_clk);
-	__raw_writel(__raw_readl(LS1X_CLK_PLL_DIV) | RST_CPU_EN | RST_CPU,
-		     LS1X_CLK_PLL_DIV);
-	__raw_writel(__raw_readl(LS1X_CLK_PLL_DIV) & ~(RST_CPU_EN | RST_CPU),
-		     LS1X_CLK_PLL_DIV);
-	clk_set_rate(ls1x_cpufreq.mux_clk, new_freq * 1000);
-	clk_set_parent(policy->clk, ls1x_cpufreq.mux_clk);
-
-	return 0;
-}
-
-static int ls1x_cpufreq_init(struct cpufreq_policy *policy)
-{
-	struct cpufreq_frequency_table *freq_tbl;
-	unsigned int pll_freq, freq;
-	int steps, i, ret;
-
-	pll_freq = clk_get_rate(ls1x_cpufreq.pll_clk) / 1000;
-
-	steps = 1 << DIV_CPU_WIDTH;
-	freq_tbl = kzalloc(sizeof(*freq_tbl) * steps, GFP_KERNEL);
-	if (!freq_tbl) {
-		dev_err(ls1x_cpufreq.dev,
-			"failed to alloc cpufreq_frequency_table\n");
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	for (i = 0; i < (steps - 1); i++) {
-		freq = pll_freq / (i + 1);
-		if ((freq < ls1x_cpufreq.min_freq) ||
-		    (freq > ls1x_cpufreq.max_freq))
-			freq_tbl[i].frequency = CPUFREQ_ENTRY_INVALID;
-		else
-			freq_tbl[i].frequency = freq;
-		dev_dbg(ls1x_cpufreq.dev,
-			"cpufreq table: index %d: frequency %d\n", i,
-			freq_tbl[i].frequency);
-	}
-	freq_tbl[i].frequency = CPUFREQ_TABLE_END;
-
-	policy->clk = ls1x_cpufreq.clk;
-	ret = cpufreq_generic_init(policy, freq_tbl, 0);
-	if (ret)
-		kfree(freq_tbl);
-out:
-	return ret;
-}
-
-static int ls1x_cpufreq_exit(struct cpufreq_policy *policy)
-{
-	kfree(policy->freq_table);
-	return 0;
-}
-
-static struct cpufreq_driver ls1x_cpufreq_driver = {
-	.name		= "cpufreq-ls1x",
-	.flags		= CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK,
-	.verify		= cpufreq_generic_frequency_table_verify,
-	.target_index	= ls1x_cpufreq_target,
-	.get		= cpufreq_generic_get,
-	.init		= ls1x_cpufreq_init,
-	.exit		= ls1x_cpufreq_exit,
-	.attr		= cpufreq_generic_attr,
-};
-
-static int ls1x_cpufreq_remove(struct platform_device *pdev)
-{
-	cpufreq_unregister_notifier(&ls1x_cpufreq_notifier_block,
-				    CPUFREQ_TRANSITION_NOTIFIER);
-	cpufreq_unregister_driver(&ls1x_cpufreq_driver);
-
-	return 0;
-}
-
-static int ls1x_cpufreq_probe(struct platform_device *pdev)
-{
-	struct plat_ls1x_cpufreq *pdata = pdev->dev.platform_data;
-	struct clk *clk;
-	int ret;
-
-	if (!pdata || !pdata->clk_name || !pdata->osc_clk_name)
-		return -EINVAL;
-
-	ls1x_cpufreq.dev = &pdev->dev;
-
-	clk = devm_clk_get(&pdev->dev, pdata->clk_name);
-	if (IS_ERR(clk)) {
-		dev_err(ls1x_cpufreq.dev, "unable to get %s clock\n",
-			pdata->clk_name);
-		ret = PTR_ERR(clk);
-		goto out;
-	}
-	ls1x_cpufreq.clk = clk;
-
-	clk = clk_get_parent(clk);
-	if (IS_ERR(clk)) {
-		dev_err(ls1x_cpufreq.dev, "unable to get parent of %s clock\n",
-			__clk_get_name(ls1x_cpufreq.clk));
-		ret = PTR_ERR(clk);
-		goto out;
-	}
-	ls1x_cpufreq.mux_clk = clk;
-
-	clk = clk_get_parent(clk);
-	if (IS_ERR(clk)) {
-		dev_err(ls1x_cpufreq.dev, "unable to get parent of %s clock\n",
-			__clk_get_name(ls1x_cpufreq.mux_clk));
-		ret = PTR_ERR(clk);
-		goto out;
-	}
-	ls1x_cpufreq.pll_clk = clk;
-
-	clk = devm_clk_get(&pdev->dev, pdata->osc_clk_name);
-	if (IS_ERR(clk)) {
-		dev_err(ls1x_cpufreq.dev, "unable to get %s clock\n",
-			pdata->osc_clk_name);
-		ret = PTR_ERR(clk);
-		goto out;
-	}
-	ls1x_cpufreq.osc_clk = clk;
-
-	ls1x_cpufreq.max_freq = pdata->max_freq;
-	ls1x_cpufreq.min_freq = pdata->min_freq;
-
-	ret = cpufreq_register_driver(&ls1x_cpufreq_driver);
-	if (ret) {
-		dev_err(ls1x_cpufreq.dev,
-			"failed to register cpufreq driver: %d\n", ret);
-		goto out;
-	}
-
-	ret = cpufreq_register_notifier(&ls1x_cpufreq_notifier_block,
-					CPUFREQ_TRANSITION_NOTIFIER);
-
-	if (!ret)
-		goto out;
-
-	dev_err(ls1x_cpufreq.dev, "failed to register cpufreq notifier: %d\n",
-		ret);
-
-	cpufreq_unregister_driver(&ls1x_cpufreq_driver);
-out:
-	return ret;
-}
-
-static struct platform_driver ls1x_cpufreq_platdrv = {
-	.driver = {
-		.name	= "ls1x-cpufreq",
-	},
-	.probe		= ls1x_cpufreq_probe,
-	.remove		= ls1x_cpufreq_remove,
-};
-
-module_platform_driver(ls1x_cpufreq_platdrv);
-
-MODULE_AUTHOR("Kelvin Cheung <keguang.zhang@gmail.com>");
-MODULE_DESCRIPTION("Loongson 1 CPUFreq driver");
-MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/Makefile linux-libre-4.7-gnu/drivers/cpufreq/Makefile
--- linux-libre-4.6-gnu/drivers/cpufreq/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -11,8 +11,10 @@ obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE)	+=
 obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND)	+= cpufreq_ondemand.o
 obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE)	+= cpufreq_conservative.o
 obj-$(CONFIG_CPU_FREQ_GOV_COMMON)		+= cpufreq_governor.o
+obj-$(CONFIG_CPU_FREQ_GOV_ATTR_SET)	+= cpufreq_governor_attr_set.o
 
 obj-$(CONFIG_CPUFREQ_DT)		+= cpufreq-dt.o
+obj-$(CONFIG_CPUFREQ_DT_PLATDEV)	+= cpufreq-dt-platdev.o
 
 ##################################################################################
 # x86 drivers.
@@ -53,7 +55,6 @@ obj-$(CONFIG_ARCH_DAVINCI)		+= davinci-c
 obj-$(CONFIG_UX500_SOC_DB8500)		+= dbx500-cpufreq.o
 obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ)	+= exynos5440-cpufreq.o
 obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ)	+= highbank-cpufreq.o
-obj-$(CONFIG_ARM_HISI_ACPU_CPUFREQ)	+= hisi-acpu-cpufreq.o
 obj-$(CONFIG_ARM_IMX6Q_CPUFREQ)		+= imx6q-cpufreq.o
 obj-$(CONFIG_ARM_INTEGRATOR)		+= integrator-cpufreq.o
 obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ)	+= kirkwood-cpufreq.o
@@ -78,6 +79,7 @@ obj-$(CONFIG_ARM_TEGRA20_CPUFREQ)	+= teg
 obj-$(CONFIG_ARM_TEGRA124_CPUFREQ)	+= tegra124-cpufreq.o
 obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ)	+= vexpress-spc-cpufreq.o
 obj-$(CONFIG_ACPI_CPPC_CPUFREQ) += cppc_cpufreq.o
+obj-$(CONFIG_MACH_MVEBU_V7)		+= mvebu-cpufreq.o
 
 
 ##################################################################################
@@ -100,7 +102,7 @@ obj-$(CONFIG_CRIS_MACH_ARTPEC3)		+= cris
 obj-$(CONFIG_ETRAXFS)			+= cris-etraxfs-cpufreq.o
 obj-$(CONFIG_IA64_ACPI_CPUFREQ)		+= ia64-acpi-cpufreq.o
 obj-$(CONFIG_LOONGSON2_CPUFREQ)		+= loongson2_cpufreq.o
-obj-$(CONFIG_LOONGSON1_CPUFREQ)		+= ls1x-cpufreq.o
+obj-$(CONFIG_LOONGSON1_CPUFREQ)		+= loongson1-cpufreq.o
 obj-$(CONFIG_SH_CPU_FREQ)		+= sh-cpufreq.o
 obj-$(CONFIG_SPARC_US2E_CPUFREQ)	+= sparc-us2e-cpufreq.o
 obj-$(CONFIG_SPARC_US3_CPUFREQ)		+= sparc-us3-cpufreq.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/maple-cpufreq.c linux-libre-4.7-gnu/drivers/cpufreq/maple-cpufreq.c
--- linux-libre-4.6-gnu/drivers/cpufreq/maple-cpufreq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/maple-cpufreq.c	2016-07-24 15:23:50.000000000 -0400
@@ -13,6 +13,8 @@
 
 #undef DEBUG
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/errno.h>
@@ -174,7 +176,7 @@ static int __init maple_cpufreq_init(voi
 	/* Get first CPU node */
 	cpunode = of_cpu_device_node_get(0);
 	if (cpunode == NULL) {
-		printk(KERN_ERR "cpufreq: Can't find any CPU 0 node\n");
+		pr_err("Can't find any CPU 0 node\n");
 		goto bail_noprops;
 	}
 
@@ -182,8 +184,7 @@ static int __init maple_cpufreq_init(voi
 	/* we actually don't care on which CPU to access PVR */
 	pvr_hi = PVR_VER(mfspr(SPRN_PVR));
 	if (pvr_hi != 0x3c && pvr_hi != 0x44) {
-		printk(KERN_ERR "cpufreq: Unsupported CPU version (%x)\n",
-				pvr_hi);
+		pr_err("Unsupported CPU version (%x)\n", pvr_hi);
 		goto bail_noprops;
 	}
 
@@ -222,8 +223,8 @@ static int __init maple_cpufreq_init(voi
 	maple_pmode_cur = -1;
 	maple_scom_switch_freq(maple_scom_query_freq());
 
-	printk(KERN_INFO "Registering Maple CPU frequency driver\n");
-	printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Cur: %d MHz\n",
+	pr_info("Registering Maple CPU frequency driver\n");
+	pr_info("Low: %d Mhz, High: %d Mhz, Cur: %d MHz\n",
 		maple_cpu_freqs[1].frequency/1000,
 		maple_cpu_freqs[0].frequency/1000,
 		maple_cpu_freqs[maple_pmode_cur].frequency/1000);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/mt8173-cpufreq.c linux-libre-4.7-gnu/drivers/cpufreq/mt8173-cpufreq.c
--- linux-libre-4.6-gnu/drivers/cpufreq/mt8173-cpufreq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/mt8173-cpufreq.c	2016-07-24 15:23:50.000000000 -0400
@@ -59,11 +59,8 @@ static LIST_HEAD(dvfs_info_list);
 static struct mtk_cpu_dvfs_info *mtk_cpu_dvfs_info_lookup(int cpu)
 {
 	struct mtk_cpu_dvfs_info *info;
-	struct list_head *list;
-
-	list_for_each(list, &dvfs_info_list) {
-		info = list_entry(list, struct mtk_cpu_dvfs_info, list_head);
 
+	list_for_each_entry(info, &dvfs_info_list, list_head) {
 		if (cpumask_test_cpu(cpu, &info->cpus))
 			return info;
 	}
@@ -310,17 +307,24 @@ static int mtk_cpufreq_set_target(struct
 	return 0;
 }
 
+#define DYNAMIC_POWER "dynamic-power-coefficient"
+
 static void mtk_cpufreq_ready(struct cpufreq_policy *policy)
 {
 	struct mtk_cpu_dvfs_info *info = policy->driver_data;
 	struct device_node *np = of_node_get(info->cpu_dev->of_node);
+	u32 capacitance = 0;
 
 	if (WARN_ON(!np))
 		return;
 
 	if (of_find_property(np, "#cooling-cells", NULL)) {
-		info->cdev = of_cpufreq_cooling_register(np,
-							 policy->related_cpus);
+		of_property_read_u32(np, DYNAMIC_POWER, &capacitance);
+
+		info->cdev = of_cpufreq_power_cooling_register(np,
+						policy->related_cpus,
+						capacitance,
+						NULL);
 
 		if (IS_ERR(info->cdev)) {
 			dev_err(info->cpu_dev,
@@ -524,8 +528,7 @@ static struct cpufreq_driver mt8173_cpuf
 
 static int mt8173_cpufreq_probe(struct platform_device *pdev)
 {
-	struct mtk_cpu_dvfs_info *info;
-	struct list_head *list, *tmp;
+	struct mtk_cpu_dvfs_info *info, *tmp;
 	int cpu, ret;
 
 	for_each_possible_cpu(cpu) {
@@ -559,11 +562,9 @@ static int mt8173_cpufreq_probe(struct p
 	return 0;
 
 release_dvfs_info_list:
-	list_for_each_safe(list, tmp, &dvfs_info_list) {
-		info = list_entry(list, struct mtk_cpu_dvfs_info, list_head);
-
+	list_for_each_entry_safe(info, tmp, &dvfs_info_list, list_head) {
 		mtk_cpu_dvfs_info_release(info);
-		list_del(list);
+		list_del(&info->list_head);
 	}
 
 	return ret;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/mvebu-cpufreq.c linux-libre-4.7-gnu/drivers/cpufreq/mvebu-cpufreq.c
--- linux-libre-4.6-gnu/drivers/cpufreq/mvebu-cpufreq.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/cpufreq/mvebu-cpufreq.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,107 @@
+/*
+ * CPUFreq support for Armada 370/XP platforms.
+ *
+ * Copyright (C) 2012-2016 Marvell
+ *
+ * Yehuda Yitschak <yehuday@marvell.com>
+ * Gregory Clement <gregory.clement@free-electrons.com>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#define pr_fmt(fmt) "mvebu-pmsu: " fmt
+
+#include <linux/clk.h>
+#include <linux/cpu.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/pm_opp.h>
+#include <linux/resource.h>
+
+static int __init armada_xp_pmsu_cpufreq_init(void)
+{
+	struct device_node *np;
+	struct resource res;
+	int ret, cpu;
+
+	if (!of_machine_is_compatible("marvell,armadaxp"))
+		return 0;
+
+	/*
+	 * In order to have proper cpufreq handling, we need to ensure
+	 * that the Device Tree description of the CPU clock includes
+	 * the definition of the PMU DFS registers. If not, we do not
+	 * register the clock notifier and the cpufreq driver. This
+	 * piece of code is only for compatibility with old Device
+	 * Trees.
+	 */
+	np = of_find_compatible_node(NULL, NULL, "marvell,armada-xp-cpu-clock");
+	if (!np)
+		return 0;
+
+	ret = of_address_to_resource(np, 1, &res);
+	if (ret) {
+		pr_warn(FW_WARN "not enabling cpufreq, deprecated armada-xp-cpu-clock binding\n");
+		of_node_put(np);
+		return 0;
+	}
+
+	of_node_put(np);
+
+	/*
+	 * For each CPU, this loop registers the operating points
+	 * supported (which are the nominal CPU frequency and half of
+	 * it), and registers the clock notifier that will take care
+	 * of doing the PMSU part of a frequency transition.
+	 */
+	for_each_possible_cpu(cpu) {
+		struct device *cpu_dev;
+		struct clk *clk;
+		int ret;
+
+		cpu_dev = get_cpu_device(cpu);
+		if (!cpu_dev) {
+			pr_err("Cannot get CPU %d\n", cpu);
+			continue;
+		}
+
+		clk = clk_get(cpu_dev, 0);
+		if (IS_ERR(clk)) {
+			pr_err("Cannot get clock for CPU %d\n", cpu);
+			return PTR_ERR(clk);
+		}
+
+		/*
+		 * In case of a failure of dev_pm_opp_add(), we don't
+		 * bother with cleaning up the registered OPP (there's
+		 * no function to do so), and simply cancel the
+		 * registration of the cpufreq device.
+		 */
+		ret = dev_pm_opp_add(cpu_dev, clk_get_rate(clk), 0);
+		if (ret) {
+			clk_put(clk);
+			return ret;
+		}
+
+		ret = dev_pm_opp_add(cpu_dev, clk_get_rate(clk) / 2, 0);
+		if (ret) {
+			clk_put(clk);
+			return ret;
+		}
+
+		ret = dev_pm_opp_set_sharing_cpus(cpu_dev,
+						  cpumask_of(cpu_dev->id));
+		if (ret)
+			dev_err(cpu_dev, "%s: failed to mark OPPs as shared: %d\n",
+				__func__, ret);
+	}
+
+	platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
+	return 0;
+}
+device_initcall(armada_xp_pmsu_cpufreq_init);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/omap-cpufreq.c linux-libre-4.7-gnu/drivers/cpufreq/omap-cpufreq.c
--- linux-libre-4.6-gnu/drivers/cpufreq/omap-cpufreq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/omap-cpufreq.c	2016-07-24 15:23:50.000000000 -0400
@@ -13,6 +13,9 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -51,7 +54,7 @@ static int omap_target(struct cpufreq_po
 
 	freq = new_freq * 1000;
 	ret = clk_round_rate(policy->clk, freq);
-	if (IS_ERR_VALUE(ret)) {
+	if (ret < 0) {
 		dev_warn(mpu_dev,
 			 "CPUfreq: Cannot find matching frequency for %lu\n",
 			 freq);
@@ -163,13 +166,13 @@ static int omap_cpufreq_probe(struct pla
 {
 	mpu_dev = get_cpu_device(0);
 	if (!mpu_dev) {
-		pr_warning("%s: unable to get the mpu device\n", __func__);
+		pr_warn("%s: unable to get the MPU device\n", __func__);
 		return -EINVAL;
 	}
 
 	mpu_reg = regulator_get(mpu_dev, "vcc");
 	if (IS_ERR(mpu_reg)) {
-		pr_warning("%s: unable to get MPU regulator\n", __func__);
+		pr_warn("%s: unable to get MPU regulator\n", __func__);
 		mpu_reg = NULL;
 	} else {
 		/* 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/p4-clockmod.c linux-libre-4.7-gnu/drivers/cpufreq/p4-clockmod.c
--- linux-libre-4.6-gnu/drivers/cpufreq/p4-clockmod.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/p4-clockmod.c	2016-07-24 15:23:50.000000000 -0400
@@ -20,6 +20,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -35,8 +37,6 @@
 
 #include "speedstep-lib.h"
 
-#define PFX	"p4-clockmod: "
-
 /*
  * Duty Cycle (3bits), note DC_DISABLE is not specified in
  * intel docs i just use it to mean disable
@@ -124,11 +124,7 @@ static unsigned int cpufreq_p4_get_frequ
 {
 	if (c->x86 == 0x06) {
 		if (cpu_has(c, X86_FEATURE_EST))
-			printk_once(KERN_WARNING PFX "Warning: EST-capable "
-			       "CPU detected. The acpi-cpufreq module offers "
-			       "voltage scaling in addition to frequency "
-			       "scaling. You should use that instead of "
-			       "p4-clockmod, if possible.\n");
+			pr_warn_once("Warning: EST-capable CPU detected. The acpi-cpufreq module offers voltage scaling in addition to frequency scaling. You should use that instead of p4-clockmod, if possible.\n");
 		switch (c->x86_model) {
 		case 0x0E: /* Core */
 		case 0x0F: /* Core Duo */
@@ -152,11 +148,7 @@ static unsigned int cpufreq_p4_get_frequ
 	p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS;
 
 	if (speedstep_detect_processor() == SPEEDSTEP_CPU_P4M) {
-		printk(KERN_WARNING PFX "Warning: Pentium 4-M detected. "
-		       "The speedstep-ich or acpi cpufreq modules offer "
-		       "voltage scaling in addition of frequency scaling. "
-		       "You should use either one instead of p4-clockmod, "
-		       "if possible.\n");
+		pr_warn("Warning: Pentium 4-M detected. The speedstep-ich or acpi cpufreq modules offer voltage scaling in addition of frequency scaling. You should use either one instead of p4-clockmod, if possible.\n");
 		return speedstep_get_frequency(SPEEDSTEP_CPU_P4M);
 	}
 
@@ -265,8 +257,7 @@ static int __init cpufreq_p4_init(void)
 
 	ret = cpufreq_register_driver(&p4clockmod_driver);
 	if (!ret)
-		printk(KERN_INFO PFX "P4/Xeon(TM) CPU On-Demand Clock "
-				"Modulation available\n");
+		pr_info("P4/Xeon(TM) CPU On-Demand Clock Modulation available\n");
 
 	return ret;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/pcc-cpufreq.c linux-libre-4.7-gnu/drivers/cpufreq/pcc-cpufreq.c
--- linux-libre-4.6-gnu/drivers/cpufreq/pcc-cpufreq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/pcc-cpufreq.c	2016-07-24 15:23:50.000000000 -0400
@@ -487,7 +487,7 @@ static int __init pcc_cpufreq_probe(void
 	doorbell.space_id = reg_resource->space_id;
 	doorbell.bit_width = reg_resource->bit_width;
 	doorbell.bit_offset = reg_resource->bit_offset;
-	doorbell.access_width = 64;
+	doorbell.access_width = 4;
 	doorbell.address = reg_resource->address;
 
 	pr_debug("probe: doorbell: space_id is %d, bit_width is %d, "
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/pmac32-cpufreq.c linux-libre-4.7-gnu/drivers/cpufreq/pmac32-cpufreq.c
--- linux-libre-4.6-gnu/drivers/cpufreq/pmac32-cpufreq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/pmac32-cpufreq.c	2016-07-24 15:23:50.000000000 -0400
@@ -13,6 +13,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/errno.h>
@@ -298,7 +300,7 @@ static int pmu_set_cpu_speed(int low_spe
  		_set_L3CR(save_l3cr);
 
 	/* Restore userland MMU context */
-	switch_mmu_context(NULL, current->active_mm);
+	switch_mmu_context(NULL, current->active_mm, NULL);
 
 #ifdef DEBUG_FREQ
 	printk(KERN_DEBUG "HID1, after: %x\n", mfspr(SPRN_HID1));
@@ -481,13 +483,13 @@ static int pmac_cpufreq_init_MacRISC3(st
 		freqs = of_get_property(cpunode, "bus-frequencies", &lenp);
 		lenp /= sizeof(u32);
 		if (freqs == NULL || lenp != 2) {
-			printk(KERN_ERR "cpufreq: bus-frequencies incorrect or missing\n");
+			pr_err("bus-frequencies incorrect or missing\n");
 			return 1;
 		}
 		ratio = of_get_property(cpunode, "processor-to-bus-ratio*2",
 						NULL);
 		if (ratio == NULL) {
-			printk(KERN_ERR "cpufreq: processor-to-bus-ratio*2 missing\n");
+			pr_err("processor-to-bus-ratio*2 missing\n");
 			return 1;
 		}
 
@@ -550,7 +552,7 @@ static int pmac_cpufreq_init_7447A(struc
 	if (volt_gpio_np)
 		voltage_gpio = read_gpio(volt_gpio_np);
 	if (!voltage_gpio){
-		printk(KERN_ERR "cpufreq: missing cpu-vcore-select gpio\n");
+		pr_err("missing cpu-vcore-select gpio\n");
 		return 1;
 	}
 
@@ -675,9 +677,9 @@ out:
 	pmac_cpu_freqs[CPUFREQ_HIGH].frequency = hi_freq;
 	ppc_proc_freq = cur_freq * 1000ul;
 
-	printk(KERN_INFO "Registering PowerMac CPU frequency driver\n");
-	printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Boot: %d Mhz\n",
-	       low_freq/1000, hi_freq/1000, cur_freq/1000);
+	pr_info("Registering PowerMac CPU frequency driver\n");
+	pr_info("Low: %d Mhz, High: %d Mhz, Boot: %d Mhz\n",
+		low_freq/1000, hi_freq/1000, cur_freq/1000);
 
 	return cpufreq_register_driver(&pmac_cpufreq_driver);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/pmac64-cpufreq.c linux-libre-4.7-gnu/drivers/cpufreq/pmac64-cpufreq.c
--- linux-libre-4.6-gnu/drivers/cpufreq/pmac64-cpufreq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/pmac64-cpufreq.c	2016-07-24 15:23:50.000000000 -0400
@@ -12,6 +12,8 @@
 
 #undef DEBUG
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/errno.h>
@@ -138,7 +140,7 @@ static void g5_vdnap_switch_volt(int spe
 		usleep_range(1000, 1000);
 	}
 	if (done == 0)
-		printk(KERN_WARNING "cpufreq: Timeout in clock slewing !\n");
+		pr_warn("Timeout in clock slewing !\n");
 }
 
 
@@ -266,7 +268,7 @@ static int g5_pfunc_switch_freq(int spee
 		rc = pmf_call_one(pfunc_cpu_setfreq_low, NULL);
 
 	if (rc)
-		printk(KERN_WARNING "cpufreq: pfunc switch error %d\n", rc);
+		pr_warn("pfunc switch error %d\n", rc);
 
 	/* It's an irq GPIO so we should be able to just block here,
 	 * I'll do that later after I've properly tested the IRQ code for
@@ -282,7 +284,7 @@ static int g5_pfunc_switch_freq(int spee
 		usleep_range(500, 500);
 	}
 	if (done == 0)
-		printk(KERN_WARNING "cpufreq: Timeout in clock slewing !\n");
+		pr_warn("Timeout in clock slewing !\n");
 
 	/* If frequency is going down, last ramp the voltage */
 	if (speed_mode > g5_pmode_cur)
@@ -368,7 +370,7 @@ static int __init g5_neo2_cpufreq_init(s
 	}
 	pvr_hi = (*valp) >> 16;
 	if (pvr_hi != 0x3c && pvr_hi != 0x44) {
-		printk(KERN_ERR "cpufreq: Unsupported CPU version\n");
+		pr_err("Unsupported CPU version\n");
 		goto bail_noprops;
 	}
 
@@ -403,8 +405,7 @@ static int __init g5_neo2_cpufreq_init(s
 
 		root = of_find_node_by_path("/");
 		if (root == NULL) {
-			printk(KERN_ERR "cpufreq: Can't find root of "
-			       "device tree\n");
+			pr_err("Can't find root of device tree\n");
 			goto bail_noprops;
 		}
 		pfunc_set_vdnap0 = pmf_find_function(root, "set-vdnap0");
@@ -412,8 +413,7 @@ static int __init g5_neo2_cpufreq_init(s
 			pmf_find_function(root, "slewing-done");
 		if (pfunc_set_vdnap0 == NULL ||
 		    pfunc_vdnap0_complete == NULL) {
-			printk(KERN_ERR "cpufreq: Can't find required "
-			       "platform function\n");
+			pr_err("Can't find required platform function\n");
 			goto bail_noprops;
 		}
 
@@ -453,10 +453,10 @@ static int __init g5_neo2_cpufreq_init(s
 	g5_pmode_cur = -1;
 	g5_switch_freq(g5_query_freq());
 
-	printk(KERN_INFO "Registering G5 CPU frequency driver\n");
-	printk(KERN_INFO "Frequency method: %s, Voltage method: %s\n",
-	       freq_method, volt_method);
-	printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Cur: %d MHz\n",
+	pr_info("Registering G5 CPU frequency driver\n");
+	pr_info("Frequency method: %s, Voltage method: %s\n",
+		freq_method, volt_method);
+	pr_info("Low: %d Mhz, High: %d Mhz, Cur: %d MHz\n",
 		g5_cpu_freqs[1].frequency/1000,
 		g5_cpu_freqs[0].frequency/1000,
 		g5_cpu_freqs[g5_pmode_cur].frequency/1000);
@@ -493,7 +493,7 @@ static int __init g5_pm72_cpufreq_init(s
 	if (cpuid != NULL)
 		eeprom = of_get_property(cpuid, "cpuid", NULL);
 	if (eeprom == NULL) {
-		printk(KERN_ERR "cpufreq: Can't find cpuid EEPROM !\n");
+		pr_err("Can't find cpuid EEPROM !\n");
 		rc = -ENODEV;
 		goto bail;
 	}
@@ -511,7 +511,7 @@ static int __init g5_pm72_cpufreq_init(s
 		break;
 	}
 	if (hwclock == NULL) {
-		printk(KERN_ERR "cpufreq: Can't find i2c clock chip !\n");
+		pr_err("Can't find i2c clock chip !\n");
 		rc = -ENODEV;
 		goto bail;
 	}
@@ -539,7 +539,7 @@ static int __init g5_pm72_cpufreq_init(s
 	/* Check we have minimum requirements */
 	if (pfunc_cpu_getfreq == NULL || pfunc_cpu_setfreq_high == NULL ||
 	    pfunc_cpu_setfreq_low == NULL || pfunc_slewing_done == NULL) {
-		printk(KERN_ERR "cpufreq: Can't find platform functions !\n");
+		pr_err("Can't find platform functions !\n");
 		rc = -ENODEV;
 		goto bail;
 	}
@@ -567,7 +567,7 @@ static int __init g5_pm72_cpufreq_init(s
 	/* Get max frequency from device-tree */
 	valp = of_get_property(cpunode, "clock-frequency", NULL);
 	if (!valp) {
-		printk(KERN_ERR "cpufreq: Can't find CPU frequency !\n");
+		pr_err("Can't find CPU frequency !\n");
 		rc = -ENODEV;
 		goto bail;
 	}
@@ -583,8 +583,7 @@ static int __init g5_pm72_cpufreq_init(s
 
 	/* Check for machines with no useful settings */
 	if (il == ih) {
-		printk(KERN_WARNING "cpufreq: No low frequency mode available"
-		       " on this model !\n");
+		pr_warn("No low frequency mode available on this model !\n");
 		rc = -ENODEV;
 		goto bail;
 	}
@@ -595,7 +594,7 @@ static int __init g5_pm72_cpufreq_init(s
 
 	/* Sanity check */
 	if (min_freq >= max_freq || min_freq < 1000) {
-		printk(KERN_ERR "cpufreq: Can't calculate low frequency !\n");
+		pr_err("Can't calculate low frequency !\n");
 		rc = -ENXIO;
 		goto bail;
 	}
@@ -619,10 +618,10 @@ static int __init g5_pm72_cpufreq_init(s
 	g5_pmode_cur = -1;
 	g5_switch_freq(g5_query_freq());
 
-	printk(KERN_INFO "Registering G5 CPU frequency driver\n");
-	printk(KERN_INFO "Frequency method: i2c/pfunc, "
-	       "Voltage method: %s\n", has_volt ? "i2c/pfunc" : "none");
-	printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Cur: %d MHz\n",
+	pr_info("Registering G5 CPU frequency driver\n");
+	pr_info("Frequency method: i2c/pfunc, Voltage method: %s\n",
+		has_volt ? "i2c/pfunc" : "none");
+	pr_info("Low: %d Mhz, High: %d Mhz, Cur: %d MHz\n",
 		g5_cpu_freqs[1].frequency/1000,
 		g5_cpu_freqs[0].frequency/1000,
 		g5_cpu_freqs[g5_pmode_cur].frequency/1000);
@@ -654,7 +653,7 @@ static int __init g5_cpufreq_init(void)
 	/* Get first CPU node */
 	cpunode = of_cpu_device_node_get(0);
 	if (cpunode == NULL) {
-		pr_err("cpufreq: Can't find any CPU node\n");
+		pr_err("Can't find any CPU node\n");
 		return -ENODEV;
 	}
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/powernow-k6.c linux-libre-4.7-gnu/drivers/cpufreq/powernow-k6.c
--- linux-libre-4.6-gnu/drivers/cpufreq/powernow-k6.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/powernow-k6.c	2016-07-24 15:23:50.000000000 -0400
@@ -8,6 +8,8 @@
  *  BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous*
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -22,7 +24,6 @@
 #define POWERNOW_IOPORT 0xfff0          /* it doesn't matter where, as long
 					   as it is unused */
 
-#define PFX "powernow-k6: "
 static unsigned int                     busfreq;   /* FSB, in 10 kHz */
 static unsigned int                     max_multiplier;
 
@@ -141,7 +142,7 @@ static int powernow_k6_target(struct cpu
 {
 
 	if (clock_ratio[best_i].driver_data > max_multiplier) {
-		printk(KERN_ERR PFX "invalid target frequency\n");
+		pr_err("invalid target frequency\n");
 		return -EINVAL;
 	}
 
@@ -175,13 +176,14 @@ static int powernow_k6_cpu_init(struct c
 				max_multiplier = param_max_multiplier;
 				goto have_max_multiplier;
 			}
-		printk(KERN_ERR "powernow-k6: invalid max_multiplier parameter, valid parameters 20, 30, 35, 40, 45, 50, 55, 60\n");
+		pr_err("invalid max_multiplier parameter, valid parameters 20, 30, 35, 40, 45, 50, 55, 60\n");
 		return -EINVAL;
 	}
 
 	if (!max_multiplier) {
-		printk(KERN_WARNING "powernow-k6: unknown frequency %u, cannot determine current multiplier\n", khz);
-		printk(KERN_WARNING "powernow-k6: use module parameters max_multiplier and bus_frequency\n");
+		pr_warn("unknown frequency %u, cannot determine current multiplier\n",
+			khz);
+		pr_warn("use module parameters max_multiplier and bus_frequency\n");
 		return -EOPNOTSUPP;
 	}
 
@@ -193,7 +195,7 @@ have_max_multiplier:
 			busfreq = param_busfreq / 10;
 			goto have_busfreq;
 		}
-		printk(KERN_ERR "powernow-k6: invalid bus_frequency parameter, allowed range 50000 - 150000 kHz\n");
+		pr_err("invalid bus_frequency parameter, allowed range 50000 - 150000 kHz\n");
 		return -EINVAL;
 	}
 
@@ -275,7 +277,7 @@ static int __init powernow_k6_init(void)
 		return -ENODEV;
 
 	if (!request_region(POWERNOW_IOPORT, 16, "PowerNow!")) {
-		printk(KERN_INFO PFX "PowerNow IOPORT region already used.\n");
+		pr_info("PowerNow IOPORT region already used\n");
 		return -EIO;
 	}
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/powernow-k7.c linux-libre-4.7-gnu/drivers/cpufreq/powernow-k7.c
--- linux-libre-4.6-gnu/drivers/cpufreq/powernow-k7.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/powernow-k7.c	2016-07-24 15:23:50.000000000 -0400
@@ -13,6 +13,8 @@
  *  - We disable half multipliers if ACPI is used on A0 stepping CPUs.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
@@ -35,9 +37,6 @@
 
 #include "powernow-k7.h"
 
-#define PFX "powernow: "
-
-
 struct psb_s {
 	u8 signature[10];
 	u8 tableversion;
@@ -127,14 +126,13 @@ static int check_powernow(void)
 	maxei = cpuid_eax(0x80000000);
 	if (maxei < 0x80000007) {	/* Any powernow info ? */
 #ifdef MODULE
-		printk(KERN_INFO PFX "No powernow capabilities detected\n");
+		pr_info("No powernow capabilities detected\n");
 #endif
 		return 0;
 	}
 
 	if ((c->x86_model == 6) && (c->x86_mask == 0)) {
-		printk(KERN_INFO PFX "K7 660[A0] core detected, "
-				"enabling errata workarounds\n");
+		pr_info("K7 660[A0] core detected, enabling errata workarounds\n");
 		have_a0 = 1;
 	}
 
@@ -144,22 +142,22 @@ static int check_powernow(void)
 	if (!(edx & (1 << 1 | 1 << 2)))
 		return 0;
 
-	printk(KERN_INFO PFX "PowerNOW! Technology present. Can scale: ");
+	pr_info("PowerNOW! Technology present. Can scale: ");
 
 	if (edx & 1 << 1) {
-		printk("frequency");
+		pr_cont("frequency");
 		can_scale_bus = 1;
 	}
 
 	if ((edx & (1 << 1 | 1 << 2)) == 0x6)
-		printk(" and ");
+		pr_cont(" and ");
 
 	if (edx & 1 << 2) {
-		printk("voltage");
+		pr_cont("voltage");
 		can_scale_vid = 1;
 	}
 
-	printk(".\n");
+	pr_cont("\n");
 	return 1;
 }
 
@@ -427,16 +425,14 @@ err1:
 err05:
 	kfree(acpi_processor_perf);
 err0:
-	printk(KERN_WARNING PFX "ACPI perflib can not be used on "
-			"this platform\n");
+	pr_warn("ACPI perflib can not be used on this platform\n");
 	acpi_processor_perf = NULL;
 	return retval;
 }
 #else
 static int powernow_acpi_init(void)
 {
-	printk(KERN_INFO PFX "no support for ACPI processor found."
-	       "  Please recompile your kernel with ACPI processor\n");
+	pr_info("no support for ACPI processor found - please recompile your kernel with ACPI processor\n");
 	return -EINVAL;
 }
 #endif
@@ -468,8 +464,7 @@ static int powernow_decode_bios(int maxf
 			psb = (struct psb_s *) p;
 			pr_debug("Table version: 0x%x\n", psb->tableversion);
 			if (psb->tableversion != 0x12) {
-				printk(KERN_INFO PFX "Sorry, only v1.2 tables"
-						" supported right now\n");
+				pr_info("Sorry, only v1.2 tables supported right now\n");
 				return -ENODEV;
 			}
 
@@ -481,10 +476,8 @@ static int powernow_decode_bios(int maxf
 
 			latency = psb->settlingtime;
 			if (latency < 100) {
-				printk(KERN_INFO PFX "BIOS set settling time "
-						"to %d microseconds. "
-						"Should be at least 100. "
-						"Correcting.\n", latency);
+				pr_info("BIOS set settling time to %d microseconds. Should be at least 100. Correcting.\n",
+					latency);
 				latency = 100;
 			}
 			pr_debug("Settling Time: %d microseconds.\n",
@@ -516,10 +509,9 @@ static int powernow_decode_bios(int maxf
 						p += 2;
 				}
 			}
-			printk(KERN_INFO PFX "No PST tables match this cpuid "
-					"(0x%x)\n", etuple);
-			printk(KERN_INFO PFX "This is indicative of a broken "
-					"BIOS.\n");
+			pr_info("No PST tables match this cpuid (0x%x)\n",
+				etuple);
+			pr_info("This is indicative of a broken BIOS\n");
 
 			return -EINVAL;
 		}
@@ -552,7 +544,7 @@ static int fixup_sgtc(void)
 	sgtc = 100 * m * latency;
 	sgtc = sgtc / 3;
 	if (sgtc > 0xfffff) {
-		printk(KERN_WARNING PFX "SGTC too large %d\n", sgtc);
+		pr_warn("SGTC too large %d\n", sgtc);
 		sgtc = 0xfffff;
 	}
 	return sgtc;
@@ -574,14 +566,10 @@ static unsigned int powernow_get(unsigne
 
 static int acer_cpufreq_pst(const struct dmi_system_id *d)
 {
-	printk(KERN_WARNING PFX
-		"%s laptop with broken PST tables in BIOS detected.\n",
+	pr_warn("%s laptop with broken PST tables in BIOS detected\n",
 		d->ident);
-	printk(KERN_WARNING PFX
-		"You need to downgrade to 3A21 (09/09/2002), or try a newer "
-		"BIOS than 3A71 (01/20/2003)\n");
-	printk(KERN_WARNING PFX
-		"cpufreq scaling has been disabled as a result of this.\n");
+	pr_warn("You need to downgrade to 3A21 (09/09/2002), or try a newer BIOS than 3A71 (01/20/2003)\n");
+	pr_warn("cpufreq scaling has been disabled as a result of this\n");
 	return 0;
 }
 
@@ -616,40 +604,38 @@ static int powernow_cpu_init(struct cpuf
 
 	fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.CFID];
 	if (!fsb) {
-		printk(KERN_WARNING PFX "can not determine bus frequency\n");
+		pr_warn("can not determine bus frequency\n");
 		return -EINVAL;
 	}
 	pr_debug("FSB: %3dMHz\n", fsb/1000);
 
 	if (dmi_check_system(powernow_dmi_table) || acpi_force) {
-		printk(KERN_INFO PFX "PSB/PST known to be broken.  "
-				"Trying ACPI instead\n");
+		pr_info("PSB/PST known to be broken - trying ACPI instead\n");
 		result = powernow_acpi_init();
 	} else {
 		result = powernow_decode_bios(fidvidstatus.bits.MFID,
 				fidvidstatus.bits.SVID);
 		if (result) {
-			printk(KERN_INFO PFX "Trying ACPI perflib\n");
+			pr_info("Trying ACPI perflib\n");
 			maximum_speed = 0;
 			minimum_speed = -1;
 			latency = 0;
 			result = powernow_acpi_init();
 			if (result) {
-				printk(KERN_INFO PFX
-					"ACPI and legacy methods failed\n");
+				pr_info("ACPI and legacy methods failed\n");
 			}
 		} else {
 			/* SGTC use the bus clock as timer */
 			latency = fixup_sgtc();
-			printk(KERN_INFO PFX "SGTC: %d\n", latency);
+			pr_info("SGTC: %d\n", latency);
 		}
 	}
 
 	if (result)
 		return result;
 
-	printk(KERN_INFO PFX "Minimum speed %d MHz. Maximum speed %d MHz.\n",
-				minimum_speed/1000, maximum_speed/1000);
+	pr_info("Minimum speed %d MHz - Maximum speed %d MHz\n",
+		minimum_speed/1000, maximum_speed/1000);
 
 	policy->cpuinfo.transition_latency =
 		cpufreq_scale(2000000UL, fsb, latency);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/powernv-cpufreq.c linux-libre-4.7-gnu/drivers/cpufreq/powernv-cpufreq.c
--- linux-libre-4.6-gnu/drivers/cpufreq/powernv-cpufreq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/powernv-cpufreq.c	2016-07-24 15:23:50.000000000 -0400
@@ -36,12 +36,56 @@
 #include <asm/reg.h>
 #include <asm/smp.h> /* Required for cpu_sibling_mask() in UP configs */
 #include <asm/opal.h>
+#include <linux/timer.h>
 
 #define POWERNV_MAX_PSTATES	256
 #define PMSR_PSAFE_ENABLE	(1UL << 30)
 #define PMSR_SPR_EM_DISABLE	(1UL << 31)
 #define PMSR_MAX(x)		((x >> 32) & 0xFF)
 
+#define MAX_RAMP_DOWN_TIME				5120
+/*
+ * On an idle system we want the global pstate to ramp-down from max value to
+ * min over a span of ~5 secs. Also we want it to initially ramp-down slowly and
+ * then ramp-down rapidly later on.
+ *
+ * This gives a percentage rampdown for time elapsed in milliseconds.
+ * ramp_down_percentage = ((ms * ms) >> 18)
+ *			~= 3.8 * (sec * sec)
+ *
+ * At 0 ms	ramp_down_percent = 0
+ * At 5120 ms	ramp_down_percent = 100
+ */
+#define ramp_down_percent(time)		((time * time) >> 18)
+
+/* Interval after which the timer is queued to bring down global pstate */
+#define GPSTATE_TIMER_INTERVAL				2000
+
+/**
+ * struct global_pstate_info -	Per policy data structure to maintain history of
+ *				global pstates
+ * @highest_lpstate:		The local pstate from which we are ramping down
+ * @elapsed_time:		Time in ms spent in ramping down from
+ *				highest_lpstate
+ * @last_sampled_time:		Time from boot in ms when global pstates were
+ *				last set
+ * @last_lpstate,last_gpstate:	Last set values for local and global pstates
+ * @timer:			Is used for ramping down if cpu goes idle for
+ *				a long time with global pstate held high
+ * @gpstate_lock:		A spinlock to maintain synchronization between
+ *				routines called by the timer handler and
+ *				governer's target_index calls
+ */
+struct global_pstate_info {
+	int highest_lpstate;
+	unsigned int elapsed_time;
+	unsigned int last_sampled_time;
+	int last_lpstate;
+	int last_gpstate;
+	spinlock_t gpstate_lock;
+	struct timer_list timer;
+};
+
 static struct cpufreq_frequency_table powernv_freqs[POWERNV_MAX_PSTATES+1];
 static bool rebooting, throttled, occ_reset;
 
@@ -94,6 +138,17 @@ static struct powernv_pstate_info {
 	int nr_pstates;
 } powernv_pstate_info;
 
+static inline void reset_gpstates(struct cpufreq_policy *policy)
+{
+	struct global_pstate_info *gpstates = policy->driver_data;
+
+	gpstates->highest_lpstate = 0;
+	gpstates->elapsed_time = 0;
+	gpstates->last_sampled_time = 0;
+	gpstates->last_lpstate = 0;
+	gpstates->last_gpstate = 0;
+}
+
 /*
  * Initialize the freq table based on data obtained
  * from the firmware passed via device-tree
@@ -285,6 +340,7 @@ static inline void set_pmspr(unsigned lo
 struct powernv_smp_call_data {
 	unsigned int freq;
 	int pstate_id;
+	int gpstate_id;
 };
 
 /*
@@ -343,19 +399,21 @@ static unsigned int powernv_cpufreq_get(
  * (struct powernv_smp_call_data *) and the pstate_id which needs to be set
  * on this CPU should be present in freq_data->pstate_id.
  */
-static void set_pstate(void *freq_data)
+static void set_pstate(void *data)
 {
 	unsigned long val;
-	unsigned long pstate_ul =
-		((struct powernv_smp_call_data *) freq_data)->pstate_id;
+	struct powernv_smp_call_data *freq_data = data;
+	unsigned long pstate_ul = freq_data->pstate_id;
+	unsigned long gpstate_ul = freq_data->gpstate_id;
 
 	val = get_pmspr(SPRN_PMCR);
 	val = val & 0x0000FFFFFFFFFFFFULL;
 
 	pstate_ul = pstate_ul & 0xFF;
+	gpstate_ul = gpstate_ul & 0xFF;
 
 	/* Set both global(bits 56..63) and local(bits 48..55) PStates */
-	val = val | (pstate_ul << 56) | (pstate_ul << 48);
+	val = val | (gpstate_ul << 56) | (pstate_ul << 48);
 
 	pr_debug("Setting cpu %d pmcr to %016lX\n",
 			raw_smp_processor_id(), val);
@@ -424,6 +482,111 @@ next:
 	}
 }
 
+/**
+ * calc_global_pstate - Calculate global pstate
+ * @elapsed_time:	Elapsed time in milliseconds
+ * @local_pstate:	New local pstate
+ * @highest_lpstate:	pstate from which its ramping down
+ *
+ * Finds the appropriate global pstate based on the pstate from which its
+ * ramping down and the time elapsed in ramping down. It follows a quadratic
+ * equation which ensures that it reaches ramping down to pmin in 5sec.
+ */
+static inline int calc_global_pstate(unsigned int elapsed_time,
+				     int highest_lpstate, int local_pstate)
+{
+	int pstate_diff;
+
+	/*
+	 * Using ramp_down_percent we get the percentage of rampdown
+	 * that we are expecting to be dropping. Difference between
+	 * highest_lpstate and powernv_pstate_info.min will give a absolute
+	 * number of how many pstates we will drop eventually by the end of
+	 * 5 seconds, then just scale it get the number pstates to be dropped.
+	 */
+	pstate_diff =  ((int)ramp_down_percent(elapsed_time) *
+			(highest_lpstate - powernv_pstate_info.min)) / 100;
+
+	/* Ensure that global pstate is >= to local pstate */
+	if (highest_lpstate - pstate_diff < local_pstate)
+		return local_pstate;
+	else
+		return highest_lpstate - pstate_diff;
+}
+
+static inline void  queue_gpstate_timer(struct global_pstate_info *gpstates)
+{
+	unsigned int timer_interval;
+
+	/*
+	 * Setting up timer to fire after GPSTATE_TIMER_INTERVAL ms, But
+	 * if it exceeds MAX_RAMP_DOWN_TIME ms for ramp down time.
+	 * Set timer such that it fires exactly at MAX_RAMP_DOWN_TIME
+	 * seconds of ramp down time.
+	 */
+	if ((gpstates->elapsed_time + GPSTATE_TIMER_INTERVAL)
+	     > MAX_RAMP_DOWN_TIME)
+		timer_interval = MAX_RAMP_DOWN_TIME - gpstates->elapsed_time;
+	else
+		timer_interval = GPSTATE_TIMER_INTERVAL;
+
+	mod_timer_pinned(&gpstates->timer, jiffies +
+			msecs_to_jiffies(timer_interval));
+}
+
+/**
+ * gpstate_timer_handler
+ *
+ * @data: pointer to cpufreq_policy on which timer was queued
+ *
+ * This handler brings down the global pstate closer to the local pstate
+ * according quadratic equation. Queues a new timer if it is still not equal
+ * to local pstate
+ */
+void gpstate_timer_handler(unsigned long data)
+{
+	struct cpufreq_policy *policy = (struct cpufreq_policy *)data;
+	struct global_pstate_info *gpstates = policy->driver_data;
+	int gpstate_id;
+	unsigned int time_diff = jiffies_to_msecs(jiffies)
+					- gpstates->last_sampled_time;
+	struct powernv_smp_call_data freq_data;
+
+	if (!spin_trylock(&gpstates->gpstate_lock))
+		return;
+
+	gpstates->last_sampled_time += time_diff;
+	gpstates->elapsed_time += time_diff;
+	freq_data.pstate_id = gpstates->last_lpstate;
+
+	if ((gpstates->last_gpstate == freq_data.pstate_id) ||
+	    (gpstates->elapsed_time > MAX_RAMP_DOWN_TIME)) {
+		gpstate_id = freq_data.pstate_id;
+		reset_gpstates(policy);
+		gpstates->highest_lpstate = freq_data.pstate_id;
+	} else {
+		gpstate_id = calc_global_pstate(gpstates->elapsed_time,
+						gpstates->highest_lpstate,
+						freq_data.pstate_id);
+	}
+
+	/*
+	 * If local pstate is equal to global pstate, rampdown is over
+	 * So timer is not required to be queued.
+	 */
+	if (gpstate_id != freq_data.pstate_id)
+		queue_gpstate_timer(gpstates);
+
+	freq_data.gpstate_id = gpstate_id;
+	gpstates->last_gpstate = freq_data.gpstate_id;
+	gpstates->last_lpstate = freq_data.pstate_id;
+
+	spin_unlock(&gpstates->gpstate_lock);
+
+	/* Timer may get migrated to a different cpu on cpu hot unplug */
+	smp_call_function_any(policy->cpus, set_pstate, &freq_data, 1);
+}
+
 /*
  * powernv_cpufreq_target_index: Sets the frequency corresponding to
  * the cpufreq table entry indexed by new_index on the cpus in the
@@ -433,6 +596,8 @@ static int powernv_cpufreq_target_index(
 					unsigned int new_index)
 {
 	struct powernv_smp_call_data freq_data;
+	unsigned int cur_msec, gpstate_id;
+	struct global_pstate_info *gpstates = policy->driver_data;
 
 	if (unlikely(rebooting) && new_index != get_nominal_index())
 		return 0;
@@ -440,28 +605,81 @@ static int powernv_cpufreq_target_index(
 	if (!throttled)
 		powernv_cpufreq_throttle_check(NULL);
 
+	cur_msec = jiffies_to_msecs(get_jiffies_64());
+
+	spin_lock(&gpstates->gpstate_lock);
 	freq_data.pstate_id = powernv_freqs[new_index].driver_data;
 
+	if (!gpstates->last_sampled_time) {
+		gpstate_id = freq_data.pstate_id;
+		gpstates->highest_lpstate = freq_data.pstate_id;
+		goto gpstates_done;
+	}
+
+	if (gpstates->last_gpstate > freq_data.pstate_id) {
+		gpstates->elapsed_time += cur_msec -
+						 gpstates->last_sampled_time;
+
+		/*
+		 * If its has been ramping down for more than MAX_RAMP_DOWN_TIME
+		 * we should be resetting all global pstate related data. Set it
+		 * equal to local pstate to start fresh.
+		 */
+		if (gpstates->elapsed_time > MAX_RAMP_DOWN_TIME) {
+			reset_gpstates(policy);
+			gpstates->highest_lpstate = freq_data.pstate_id;
+			gpstate_id = freq_data.pstate_id;
+		} else {
+		/* Elaspsed_time is less than 5 seconds, continue to rampdown */
+			gpstate_id = calc_global_pstate(gpstates->elapsed_time,
+							gpstates->highest_lpstate,
+							freq_data.pstate_id);
+		}
+	} else {
+		reset_gpstates(policy);
+		gpstates->highest_lpstate = freq_data.pstate_id;
+		gpstate_id = freq_data.pstate_id;
+	}
+
+	/*
+	 * If local pstate is equal to global pstate, rampdown is over
+	 * So timer is not required to be queued.
+	 */
+	if (gpstate_id != freq_data.pstate_id)
+		queue_gpstate_timer(gpstates);
+	else
+		del_timer_sync(&gpstates->timer);
+
+gpstates_done:
+	freq_data.gpstate_id = gpstate_id;
+	gpstates->last_sampled_time = cur_msec;
+	gpstates->last_gpstate = freq_data.gpstate_id;
+	gpstates->last_lpstate = freq_data.pstate_id;
+
+	spin_unlock(&gpstates->gpstate_lock);
+
 	/*
 	 * Use smp_call_function to send IPI and execute the
 	 * mtspr on target CPU.  We could do that without IPI
 	 * if current CPU is within policy->cpus (core)
 	 */
 	smp_call_function_any(policy->cpus, set_pstate, &freq_data, 1);
-
 	return 0;
 }
 
 static int powernv_cpufreq_cpu_init(struct cpufreq_policy *policy)
 {
-	int base, i;
+	int base, i, ret;
+	struct kernfs_node *kn;
+	struct global_pstate_info *gpstates;
 
 	base = cpu_first_thread_sibling(policy->cpu);
 
 	for (i = 0; i < threads_per_core; i++)
 		cpumask_set_cpu(base + i, policy->cpus);
 
-	if (!policy->driver_data) {
+	kn = kernfs_find_and_get(policy->kobj.sd, throttle_attr_grp.name);
+	if (!kn) {
 		int ret;
 
 		ret = sysfs_create_group(&policy->kobj, &throttle_attr_grp);
@@ -470,13 +688,37 @@ static int powernv_cpufreq_cpu_init(stru
 				policy->cpu);
 			return ret;
 		}
-		/*
-		 * policy->driver_data is used as a flag for one-time
-		 * creation of throttle sysfs files.
-		 */
-		policy->driver_data = policy;
+	} else {
+		kernfs_put(kn);
 	}
-	return cpufreq_table_validate_and_show(policy, powernv_freqs);
+
+	gpstates =  kzalloc(sizeof(*gpstates), GFP_KERNEL);
+	if (!gpstates)
+		return -ENOMEM;
+
+	policy->driver_data = gpstates;
+
+	/* initialize timer */
+	init_timer_deferrable(&gpstates->timer);
+	gpstates->timer.data = (unsigned long)policy;
+	gpstates->timer.function = gpstate_timer_handler;
+	gpstates->timer.expires = jiffies +
+				msecs_to_jiffies(GPSTATE_TIMER_INTERVAL);
+	spin_lock_init(&gpstates->gpstate_lock);
+	ret = cpufreq_table_validate_and_show(policy, powernv_freqs);
+
+	if (ret < 0)
+		kfree(policy->driver_data);
+
+	return ret;
+}
+
+static int powernv_cpufreq_cpu_exit(struct cpufreq_policy *policy)
+{
+	/* timer is deleted in cpufreq_cpu_stop() */
+	kfree(policy->driver_data);
+
+	return 0;
 }
 
 static int powernv_cpufreq_reboot_notifier(struct notifier_block *nb,
@@ -604,15 +846,19 @@ static struct notifier_block powernv_cpu
 static void powernv_cpufreq_stop_cpu(struct cpufreq_policy *policy)
 {
 	struct powernv_smp_call_data freq_data;
+	struct global_pstate_info *gpstates = policy->driver_data;
 
 	freq_data.pstate_id = powernv_pstate_info.min;
+	freq_data.gpstate_id = powernv_pstate_info.min;
 	smp_call_function_single(policy->cpu, set_pstate, &freq_data, 1);
+	del_timer_sync(&gpstates->timer);
 }
 
 static struct cpufreq_driver powernv_cpufreq_driver = {
 	.name		= "powernv-cpufreq",
 	.flags		= CPUFREQ_CONST_LOOPS,
 	.init		= powernv_cpufreq_cpu_init,
+	.exit		= powernv_cpufreq_cpu_exit,
 	.verify		= cpufreq_generic_frequency_table_verify,
 	.target_index	= powernv_cpufreq_target_index,
 	.get		= powernv_cpufreq_get,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/ppc_cbe_cpufreq.h linux-libre-4.7-gnu/drivers/cpufreq/ppc_cbe_cpufreq.h
--- linux-libre-4.6-gnu/drivers/cpufreq/ppc_cbe_cpufreq.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/ppc_cbe_cpufreq.h	2016-07-24 15:23:50.000000000 -0400
@@ -17,7 +17,7 @@ int cbe_cpufreq_get_pmode(int cpu);
 
 int cbe_cpufreq_set_pmode_pmi(int cpu, unsigned int pmode);
 
-#if defined(CONFIG_CPU_FREQ_CBE_PMI) || defined(CONFIG_CPU_FREQ_CBE_PMI_MODULE)
+#if IS_ENABLED(CONFIG_CPU_FREQ_CBE_PMI)
 extern bool cbe_cpufreq_has_pmi;
 #else
 #define cbe_cpufreq_has_pmi (0)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/ppc_cbe_cpufreq_pmi.c linux-libre-4.7-gnu/drivers/cpufreq/ppc_cbe_cpufreq_pmi.c
--- linux-libre-4.6-gnu/drivers/cpufreq/ppc_cbe_cpufreq_pmi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/ppc_cbe_cpufreq_pmi.c	2016-07-24 15:23:50.000000000 -0400
@@ -23,7 +23,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/timer.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/of_platform.h>
 
 #include <asm/processor.h>
@@ -142,15 +142,4 @@ static int __init cbe_cpufreq_pmi_init(v
 
 	return 0;
 }
-
-static void __exit cbe_cpufreq_pmi_exit(void)
-{
-	cpufreq_unregister_notifier(&pmi_notifier_block, CPUFREQ_POLICY_NOTIFIER);
-	pmi_unregister_handler(&cbe_pmi_handler);
-}
-
-module_init(cbe_cpufreq_pmi_init);
-module_exit(cbe_cpufreq_pmi_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Christian Krafft <krafft@de.ibm.com>");
+device_initcall(cbe_cpufreq_pmi_init);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/pxa2xx-cpufreq.c linux-libre-4.7-gnu/drivers/cpufreq/pxa2xx-cpufreq.c
--- linux-libre-4.6-gnu/drivers/cpufreq/pxa2xx-cpufreq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/pxa2xx-cpufreq.c	2016-07-24 15:23:50.000000000 -0400
@@ -29,6 +29,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/sched.h>
@@ -186,8 +188,7 @@ static int pxa_cpufreq_change_voltage(co
 
 	ret = regulator_set_voltage(vcc_core, vmin, vmax);
 	if (ret)
-		pr_err("cpufreq: Failed to set vcc_core in [%dmV..%dmV]\n",
-		       vmin, vmax);
+		pr_err("Failed to set vcc_core in [%dmV..%dmV]\n", vmin, vmax);
 	return ret;
 }
 
@@ -195,10 +196,10 @@ static void __init pxa_cpufreq_init_volt
 {
 	vcc_core = regulator_get(NULL, "vcc_core");
 	if (IS_ERR(vcc_core)) {
-		pr_info("cpufreq: Didn't find vcc_core regulator\n");
+		pr_info("Didn't find vcc_core regulator\n");
 		vcc_core = NULL;
 	} else {
-		pr_info("cpufreq: Found vcc_core regulator\n");
+		pr_info("Found vcc_core regulator\n");
 	}
 }
 #else
@@ -233,9 +234,8 @@ static void pxa27x_guess_max_freq(void)
 {
 	if (!pxa27x_maxfreq) {
 		pxa27x_maxfreq = 416000;
-		printk(KERN_INFO "PXA CPU 27x max frequency not defined "
-		       "(pxa27x_maxfreq), assuming pxa271 with %dkHz maxfreq\n",
-		       pxa27x_maxfreq);
+		pr_info("PXA CPU 27x max frequency not defined (pxa27x_maxfreq), assuming pxa271 with %dkHz maxfreq\n",
+			pxa27x_maxfreq);
 	} else {
 		pxa27x_maxfreq *= 1000;
 	}
@@ -408,7 +408,7 @@ static int pxa_cpufreq_init(struct cpufr
 	 */
 	if (cpu_is_pxa25x()) {
 		find_freq_tables(&pxa255_freq_table, &pxa255_freqs);
-		pr_info("PXA255 cpufreq using %s frequency table\n",
+		pr_info("using %s frequency table\n",
 			pxa255_turbo_table ? "turbo" : "run");
 
 		cpufreq_table_validate_and_show(policy, pxa255_freq_table);
@@ -417,7 +417,7 @@ static int pxa_cpufreq_init(struct cpufr
 		cpufreq_table_validate_and_show(policy, pxa27x_freq_table);
 	}
 
-	printk(KERN_INFO "PXA CPU frequency change support initialized\n");
+	pr_info("frequency change support initialized\n");
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/qoriq-cpufreq.c linux-libre-4.7-gnu/drivers/cpufreq/qoriq-cpufreq.c
--- linux-libre-4.6-gnu/drivers/cpufreq/qoriq-cpufreq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/qoriq-cpufreq.c	2016-07-24 15:23:50.000000000 -0400
@@ -301,10 +301,11 @@ err_np:
 	return -ENODEV;
 }
 
-static int __exit qoriq_cpufreq_cpu_exit(struct cpufreq_policy *policy)
+static int qoriq_cpufreq_cpu_exit(struct cpufreq_policy *policy)
 {
 	struct cpu_data *data = policy->driver_data;
 
+	cpufreq_cooling_unregister(data->cdev);
 	kfree(data->pclk);
 	kfree(data->table);
 	kfree(data);
@@ -333,8 +334,8 @@ static void qoriq_cpufreq_ready(struct c
 		cpud->cdev = of_cpufreq_cooling_register(np,
 							 policy->related_cpus);
 
-		if (IS_ERR(cpud->cdev)) {
-			pr_err("Failed to register cooling device cpu%d: %ld\n",
+		if (IS_ERR(cpud->cdev) && PTR_ERR(cpud->cdev) != -ENOSYS) {
+			pr_err("cpu%d is not running as cooling device: %ld\n",
 					policy->cpu, PTR_ERR(cpud->cdev));
 
 			cpud->cdev = NULL;
@@ -348,7 +349,7 @@ static struct cpufreq_driver qoriq_cpufr
 	.name		= "qoriq_cpufreq",
 	.flags		= CPUFREQ_CONST_LOOPS,
 	.init		= qoriq_cpufreq_cpu_init,
-	.exit		= __exit_p(qoriq_cpufreq_cpu_exit),
+	.exit		= qoriq_cpufreq_cpu_exit,
 	.verify		= cpufreq_generic_frequency_table_verify,
 	.target_index	= qoriq_cpufreq_target,
 	.get		= cpufreq_generic_get,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/s3c2412-cpufreq.c linux-libre-4.7-gnu/drivers/cpufreq/s3c2412-cpufreq.c
--- linux-libre-4.6-gnu/drivers/cpufreq/s3c2412-cpufreq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/s3c2412-cpufreq.c	2016-07-24 15:23:50.000000000 -0400
@@ -10,6 +10,8 @@
  * published by the Free Software Foundation.
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
@@ -197,21 +199,20 @@ static int s3c2412_cpufreq_add(struct de
 
 	hclk = clk_get(NULL, "hclk");
 	if (IS_ERR(hclk)) {
-		printk(KERN_ERR "%s: cannot find hclk clock\n", __func__);
+		pr_err("cannot find hclk clock\n");
 		return -ENOENT;
 	}
 
 	fclk = clk_get(NULL, "fclk");
 	if (IS_ERR(fclk)) {
-		printk(KERN_ERR "%s: cannot find fclk clock\n", __func__);
+		pr_err("cannot find fclk clock\n");
 		goto err_fclk;
 	}
 
 	fclk_rate = clk_get_rate(fclk);
 	if (fclk_rate > 200000000) {
-		printk(KERN_INFO
-		       "%s: fclk %ld MHz, assuming 266MHz capable part\n",
-		       __func__, fclk_rate / 1000000);
+		pr_info("fclk %ld MHz, assuming 266MHz capable part\n",
+			fclk_rate / 1000000);
 		s3c2412_cpufreq_info.max.fclk = 266000000;
 		s3c2412_cpufreq_info.max.hclk = 133000000;
 		s3c2412_cpufreq_info.max.pclk =  66000000;
@@ -219,13 +220,13 @@ static int s3c2412_cpufreq_add(struct de
 
 	armclk = clk_get(NULL, "armclk");
 	if (IS_ERR(armclk)) {
-		printk(KERN_ERR "%s: cannot find arm clock\n", __func__);
+		pr_err("cannot find arm clock\n");
 		goto err_armclk;
 	}
 
 	xtal = clk_get(NULL, "xtal");
 	if (IS_ERR(xtal)) {
-		printk(KERN_ERR "%s: cannot find xtal clock\n", __func__);
+		pr_err("cannot find xtal clock\n");
 		goto err_xtal;
 	}
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/s3c2440-cpufreq.c linux-libre-4.7-gnu/drivers/cpufreq/s3c2440-cpufreq.c
--- linux-libre-4.6-gnu/drivers/cpufreq/s3c2440-cpufreq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/s3c2440-cpufreq.c	2016-07-24 15:23:50.000000000 -0400
@@ -11,6 +11,8 @@
  * published by the Free Software Foundation.
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
@@ -66,7 +68,7 @@ static int s3c2440_cpufreq_calcdivs(stru
 		     __func__, fclk, armclk, hclk_max);
 
 	if (armclk > fclk) {
-		printk(KERN_WARNING "%s: armclk > fclk\n", __func__);
+		pr_warn("%s: armclk > fclk\n", __func__);
 		armclk = fclk;
 	}
 
@@ -273,7 +275,7 @@ static int s3c2440_cpufreq_add(struct de
 	armclk = s3c_cpufreq_clk_get(NULL, "armclk");
 
 	if (IS_ERR(xtal) || IS_ERR(hclk) || IS_ERR(fclk) || IS_ERR(armclk)) {
-		printk(KERN_ERR "%s: failed to get clocks\n", __func__);
+		pr_err("%s: failed to get clocks\n", __func__);
 		return -ENOENT;
 	}
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/s3c24xx-cpufreq.c linux-libre-4.7-gnu/drivers/cpufreq/s3c24xx-cpufreq.c
--- linux-libre-4.6-gnu/drivers/cpufreq/s3c24xx-cpufreq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/s3c24xx-cpufreq.c	2016-07-24 15:23:50.000000000 -0400
@@ -10,6 +10,8 @@
  * published by the Free Software Foundation.
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
@@ -175,7 +177,7 @@ static int s3c_cpufreq_settarget(struct
 	cpu_new.freq.fclk = cpu_new.pll.frequency;
 
 	if (s3c_cpufreq_calcdivs(&cpu_new) < 0) {
-		printk(KERN_ERR "no divisors for %d\n", target_freq);
+		pr_err("no divisors for %d\n", target_freq);
 		goto err_notpossible;
 	}
 
@@ -187,7 +189,7 @@ static int s3c_cpufreq_settarget(struct
 
 	if (cpu_new.freq.hclk != cpu_cur.freq.hclk) {
 		if (s3c_cpufreq_calcio(&cpu_new) < 0) {
-			printk(KERN_ERR "%s: no IO timings\n", __func__);
+			pr_err("%s: no IO timings\n", __func__);
 			goto err_notpossible;
 		}
 	}
@@ -262,7 +264,7 @@ static int s3c_cpufreq_settarget(struct
 	return 0;
 
  err_notpossible:
-	printk(KERN_ERR "no compatible settings for %d\n", target_freq);
+	pr_err("no compatible settings for %d\n", target_freq);
 	return -EINVAL;
 }
 
@@ -331,7 +333,7 @@ static int s3c_cpufreq_target(struct cpu
 						     &index);
 
 		if (ret < 0) {
-			printk(KERN_ERR "%s: no PLL available\n", __func__);
+			pr_err("%s: no PLL available\n", __func__);
 			goto err_notpossible;
 		}
 
@@ -346,7 +348,7 @@ static int s3c_cpufreq_target(struct cpu
 	return s3c_cpufreq_settarget(policy, target_freq, pll);
 
  err_notpossible:
-	printk(KERN_ERR "no compatible settings for %d\n", target_freq);
+	pr_err("no compatible settings for %d\n", target_freq);
 	return -EINVAL;
 }
 
@@ -356,7 +358,7 @@ struct clk *s3c_cpufreq_clk_get(struct d
 
 	clk = clk_get(dev, name);
 	if (IS_ERR(clk))
-		printk(KERN_ERR "cpufreq: failed to get clock '%s'\n", name);
+		pr_err("failed to get clock '%s'\n", name);
 
 	return clk;
 }
@@ -378,15 +380,16 @@ static int __init s3c_cpufreq_initclks(v
 
 	if (IS_ERR(clk_fclk) || IS_ERR(clk_hclk) || IS_ERR(clk_pclk) ||
 	    IS_ERR(_clk_mpll) || IS_ERR(clk_arm) || IS_ERR(_clk_xtal)) {
-		printk(KERN_ERR "%s: could not get clock(s)\n", __func__);
+		pr_err("%s: could not get clock(s)\n", __func__);
 		return -ENOENT;
 	}
 
-	printk(KERN_INFO "%s: clocks f=%lu,h=%lu,p=%lu,a=%lu\n", __func__,
-	       clk_get_rate(clk_fclk) / 1000,
-	       clk_get_rate(clk_hclk) / 1000,
-	       clk_get_rate(clk_pclk) / 1000,
-	       clk_get_rate(clk_arm) / 1000);
+	pr_info("%s: clocks f=%lu,h=%lu,p=%lu,a=%lu\n",
+		__func__,
+		clk_get_rate(clk_fclk) / 1000,
+		clk_get_rate(clk_hclk) / 1000,
+		clk_get_rate(clk_pclk) / 1000,
+		clk_get_rate(clk_arm) / 1000);
 
 	return 0;
 }
@@ -424,7 +427,7 @@ static int s3c_cpufreq_resume(struct cpu
 
 	ret = s3c_cpufreq_settarget(NULL, suspend_freq, &suspend_pll);
 	if (ret) {
-		printk(KERN_ERR "%s: failed to reset pll/freq\n", __func__);
+		pr_err("%s: failed to reset pll/freq\n", __func__);
 		return ret;
 	}
 
@@ -449,13 +452,12 @@ static struct cpufreq_driver s3c24xx_dri
 int s3c_cpufreq_register(struct s3c_cpufreq_info *info)
 {
 	if (!info || !info->name) {
-		printk(KERN_ERR "%s: failed to pass valid information\n",
-		       __func__);
+		pr_err("%s: failed to pass valid information\n", __func__);
 		return -EINVAL;
 	}
 
-	printk(KERN_INFO "S3C24XX CPU Frequency driver, %s cpu support\n",
-	       info->name);
+	pr_info("S3C24XX CPU Frequency driver, %s cpu support\n",
+		info->name);
 
 	/* check our driver info has valid data */
 
@@ -478,7 +480,7 @@ int __init s3c_cpufreq_setboard(struct s
 	struct s3c_cpufreq_board *ours;
 
 	if (!board) {
-		printk(KERN_INFO "%s: no board data\n", __func__);
+		pr_info("%s: no board data\n", __func__);
 		return -EINVAL;
 	}
 
@@ -487,7 +489,7 @@ int __init s3c_cpufreq_setboard(struct s
 
 	ours = kzalloc(sizeof(*ours), GFP_KERNEL);
 	if (ours == NULL) {
-		printk(KERN_ERR "%s: no memory\n", __func__);
+		pr_err("%s: no memory\n", __func__);
 		return -ENOMEM;
 	}
 
@@ -502,15 +504,15 @@ static int __init s3c_cpufreq_auto_io(vo
 	int ret;
 
 	if (!cpu_cur.info->get_iotiming) {
-		printk(KERN_ERR "%s: get_iotiming undefined\n", __func__);
+		pr_err("%s: get_iotiming undefined\n", __func__);
 		return -ENOENT;
 	}
 
-	printk(KERN_INFO "%s: working out IO settings\n", __func__);
+	pr_info("%s: working out IO settings\n", __func__);
 
 	ret = (cpu_cur.info->get_iotiming)(&cpu_cur, &s3c24xx_iotiming);
 	if (ret)
-		printk(KERN_ERR "%s: failed to get timings\n", __func__);
+		pr_err("%s: failed to get timings\n", __func__);
 
 	return ret;
 }
@@ -561,7 +563,7 @@ static void s3c_cpufreq_update_loctkime(
 	val = calc_locktime(rate, cpu_cur.info->locktime_u) << bits;
 	val |= calc_locktime(rate, cpu_cur.info->locktime_m);
 
-	printk(KERN_INFO "%s: new locktime is 0x%08x\n", __func__, val);
+	pr_info("%s: new locktime is 0x%08x\n", __func__, val);
 	__raw_writel(val, S3C2410_LOCKTIME);
 }
 
@@ -580,7 +582,7 @@ static int s3c_cpufreq_build_freq(void)
 
 	ftab = kzalloc(sizeof(*ftab) * size, GFP_KERNEL);
 	if (!ftab) {
-		printk(KERN_ERR "%s: no memory for tables\n", __func__);
+		pr_err("%s: no memory for tables\n", __func__);
 		return -ENOMEM;
 	}
 
@@ -608,15 +610,14 @@ static int __init s3c_cpufreq_initcall(v
 		if (cpu_cur.board->auto_io) {
 			ret = s3c_cpufreq_auto_io();
 			if (ret) {
-				printk(KERN_ERR "%s: failed to get io timing\n",
+				pr_err("%s: failed to get io timing\n",
 				       __func__);
 				goto out;
 			}
 		}
 
 		if (cpu_cur.board->need_io && !cpu_cur.info->set_iotiming) {
-			printk(KERN_ERR "%s: no IO support registered\n",
-			       __func__);
+			pr_err("%s: no IO support registered\n", __func__);
 			ret = -EINVAL;
 			goto out;
 		}
@@ -666,9 +667,9 @@ int s3c_plltab_register(struct cpufreq_f
 		vals += plls_no;
 		vals->frequency = CPUFREQ_TABLE_END;
 
-		printk(KERN_INFO "cpufreq: %d PLL entries\n", plls_no);
+		pr_info("%d PLL entries\n", plls_no);
 	} else
-		printk(KERN_ERR "cpufreq: no memory for PLL tables\n");
+		pr_err("no memory for PLL tables\n");
 
 	return vals ? 0 : -ENOMEM;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/s3c24xx-cpufreq-debugfs.c linux-libre-4.7-gnu/drivers/cpufreq/s3c24xx-cpufreq-debugfs.c
--- linux-libre-4.6-gnu/drivers/cpufreq/s3c24xx-cpufreq-debugfs.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/s3c24xx-cpufreq-debugfs.c	2016-07-24 15:23:50.000000000 -0400
@@ -10,6 +10,8 @@
  * published by the Free Software Foundation.
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
 #include <linux/export.h>
 #include <linux/interrupt.h>
@@ -178,7 +180,7 @@ static int __init s3c_freq_debugfs_init(
 {
 	dbgfs_root = debugfs_create_dir("s3c-cpufreq", NULL);
 	if (IS_ERR(dbgfs_root)) {
-		printk(KERN_ERR "%s: error creating debugfs root\n", __func__);
+		pr_err("%s: error creating debugfs root\n", __func__);
 		return PTR_ERR(dbgfs_root);
 	}
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/s5pv210-cpufreq.c linux-libre-4.7-gnu/drivers/cpufreq/s5pv210-cpufreq.c
--- linux-libre-4.6-gnu/drivers/cpufreq/s5pv210-cpufreq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/s5pv210-cpufreq.c	2016-07-24 15:23:50.000000000 -0400
@@ -9,6 +9,8 @@
  * published by the Free Software Foundation.
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -205,7 +207,7 @@ static void s5pv210_set_refresh(enum s5p
 	} else if (ch == DMC1) {
 		reg = (dmc_base[1] + 0x30);
 	} else {
-		printk(KERN_ERR "Cannot find DMC port\n");
+		pr_err("Cannot find DMC port\n");
 		return;
 	}
 
@@ -534,7 +536,7 @@ static int s5pv210_cpu_init(struct cpufr
 	mem_type = check_mem_type(dmc_base[0]);
 
 	if ((mem_type != LPDDR) && (mem_type != LPDDR2)) {
-		printk(KERN_ERR "CPUFreq doesn't support this memory type\n");
+		pr_err("CPUFreq doesn't support this memory type\n");
 		ret = -EINVAL;
 		goto out_dmc1;
 	}
@@ -635,13 +637,13 @@ static int s5pv210_cpufreq_probe(struct
 
 	arm_regulator = regulator_get(NULL, "vddarm");
 	if (IS_ERR(arm_regulator)) {
-		pr_err("failed to get regulator vddarm");
+		pr_err("failed to get regulator vddarm\n");
 		return PTR_ERR(arm_regulator);
 	}
 
 	int_regulator = regulator_get(NULL, "vddint");
 	if (IS_ERR(int_regulator)) {
-		pr_err("failed to get regulator vddint");
+		pr_err("failed to get regulator vddint\n");
 		regulator_put(arm_regulator);
 		return PTR_ERR(int_regulator);
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/sc520_freq.c linux-libre-4.7-gnu/drivers/cpufreq/sc520_freq.c
--- linux-libre-4.6-gnu/drivers/cpufreq/sc520_freq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/sc520_freq.c	2016-07-24 15:23:50.000000000 -0400
@@ -13,6 +13,8 @@
  *	2005-03-30: - initial revision
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -30,8 +32,6 @@
 
 static __u8 __iomem *cpuctl;
 
-#define PFX "sc520_freq: "
-
 static struct cpufreq_frequency_table sc520_freq_table[] = {
 	{0, 0x01,	100000},
 	{0, 0x02,	133000},
@@ -44,8 +44,8 @@ static unsigned int sc520_freq_get_cpu_f
 
 	switch (clockspeed_reg & 0x03) {
 	default:
-		printk(KERN_ERR PFX "error: cpuctl register has unexpected "
-				"value %02x\n", clockspeed_reg);
+		pr_err("error: cpuctl register has unexpected value %02x\n",
+		       clockspeed_reg);
 	case 0x01:
 		return 100000;
 	case 0x02:
@@ -112,7 +112,7 @@ static int __init sc520_freq_init(void)
 
 	cpuctl = ioremap((unsigned long)(MMCR_BASE + OFFS_CPUCTL), 1);
 	if (!cpuctl) {
-		printk(KERN_ERR "sc520_freq: error: failed to remap memory\n");
+		pr_err("sc520_freq: error: failed to remap memory\n");
 		return -ENOMEM;
 	}
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/scpi-cpufreq.c linux-libre-4.7-gnu/drivers/cpufreq/scpi-cpufreq.c
--- linux-libre-4.6-gnu/drivers/cpufreq/scpi-cpufreq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/scpi-cpufreq.c	2016-07-24 15:23:50.000000000 -0400
@@ -18,6 +18,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/cpu.h>
 #include <linux/cpufreq.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
@@ -38,10 +39,20 @@ static struct scpi_dvfs_info *scpi_get_d
 	return scpi_ops->dvfs_get_info(domain);
 }
 
-static int scpi_opp_table_ops(struct device *cpu_dev, bool remove)
+static int scpi_get_transition_latency(struct device *cpu_dev)
 {
-	int idx, ret = 0;
+	struct scpi_dvfs_info *info = scpi_get_dvfs_info(cpu_dev);
+
+	if (IS_ERR(info))
+		return PTR_ERR(info);
+	return info->latency;
+}
+
+static int scpi_init_opp_table(const struct cpumask *cpumask)
+{
+	int idx, ret;
 	struct scpi_opp *opp;
+	struct device *cpu_dev = get_cpu_device(cpumask_first(cpumask));
 	struct scpi_dvfs_info *info = scpi_get_dvfs_info(cpu_dev);
 
 	if (IS_ERR(info))
@@ -51,11 +62,7 @@ static int scpi_opp_table_ops(struct dev
 		return -EIO;
 
 	for (opp = info->opps, idx = 0; idx < info->count; idx++, opp++) {
-		if (remove)
-			dev_pm_opp_remove(cpu_dev, opp->freq);
-		else
-			ret = dev_pm_opp_add(cpu_dev, opp->freq,
-					     opp->m_volt * 1000);
+		ret = dev_pm_opp_add(cpu_dev, opp->freq, opp->m_volt * 1000);
 		if (ret) {
 			dev_warn(cpu_dev, "failed to add opp %uHz %umV\n",
 				 opp->freq, opp->m_volt);
@@ -64,33 +71,19 @@ static int scpi_opp_table_ops(struct dev
 			return ret;
 		}
 	}
-	return ret;
-}
 
-static int scpi_get_transition_latency(struct device *cpu_dev)
-{
-	struct scpi_dvfs_info *info = scpi_get_dvfs_info(cpu_dev);
-
-	if (IS_ERR(info))
-		return PTR_ERR(info);
-	return info->latency;
-}
-
-static int scpi_init_opp_table(struct device *cpu_dev)
-{
-	return scpi_opp_table_ops(cpu_dev, false);
-}
-
-static void scpi_free_opp_table(struct device *cpu_dev)
-{
-	scpi_opp_table_ops(cpu_dev, true);
+	ret = dev_pm_opp_set_sharing_cpus(cpu_dev, cpumask);
+	if (ret)
+		dev_err(cpu_dev, "%s: failed to mark OPPs as shared: %d\n",
+			__func__, ret);
+	return ret;
 }
 
 static struct cpufreq_arm_bL_ops scpi_cpufreq_ops = {
 	.name	= "scpi",
 	.get_transition_latency = scpi_get_transition_latency,
 	.init_opp_table = scpi_init_opp_table,
-	.free_opp_table = scpi_free_opp_table,
+	.free_opp_table = dev_pm_opp_cpumask_remove_table,
 };
 
 static int scpi_cpufreq_probe(struct platform_device *pdev)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/speedstep-centrino.c linux-libre-4.7-gnu/drivers/cpufreq/speedstep-centrino.c
--- linux-libre-4.6-gnu/drivers/cpufreq/speedstep-centrino.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/speedstep-centrino.c	2016-07-24 15:23:50.000000000 -0400
@@ -13,6 +13,8 @@
  * Copyright (C) 2003 Jeremy Fitzhardinge <jeremy@goop.org>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -27,7 +29,6 @@
 #include <asm/cpufeature.h>
 #include <asm/cpu_device_id.h>
 
-#define PFX		"speedstep-centrino: "
 #define MAINTAINER	"linux-pm@vger.kernel.org"
 
 #define INTEL_MSR_RANGE	(0xffff)
@@ -386,8 +387,7 @@ static int centrino_cpu_init(struct cpuf
 		/* check to see if it stuck */
 		rdmsr(MSR_IA32_MISC_ENABLE, l, h);
 		if (!(l & MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP)) {
-			printk(KERN_INFO PFX
-				"couldn't enable Enhanced SpeedStep\n");
+			pr_info("couldn't enable Enhanced SpeedStep\n");
 			return -ENODEV;
 		}
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/speedstep-ich.c linux-libre-4.7-gnu/drivers/cpufreq/speedstep-ich.c
--- linux-libre-4.6-gnu/drivers/cpufreq/speedstep-ich.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/speedstep-ich.c	2016-07-24 15:23:50.000000000 -0400
@@ -18,6 +18,8 @@
  *                        SPEEDSTEP - DEFINITIONS                    *
  *********************************************************************/
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -68,13 +70,13 @@ static int speedstep_find_register(void)
 	/* get PMBASE */
 	pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase);
 	if (!(pmbase & 0x01)) {
-		printk(KERN_ERR "speedstep-ich: could not find speedstep register\n");
+		pr_err("could not find speedstep register\n");
 		return -ENODEV;
 	}
 
 	pmbase &= 0xFFFFFFFE;
 	if (!pmbase) {
-		printk(KERN_ERR "speedstep-ich: could not find speedstep register\n");
+		pr_err("could not find speedstep register\n");
 		return -ENODEV;
 	}
 
@@ -136,7 +138,7 @@ static void speedstep_set_state(unsigned
 		pr_debug("change to %u MHz succeeded\n",
 			speedstep_get_frequency(speedstep_processor) / 1000);
 	else
-		printk(KERN_ERR "cpufreq: change failed - I/O error\n");
+		pr_err("change failed - I/O error\n");
 
 	return;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/speedstep-lib.c linux-libre-4.7-gnu/drivers/cpufreq/speedstep-lib.c
--- linux-libre-4.6-gnu/drivers/cpufreq/speedstep-lib.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/speedstep-lib.c	2016-07-24 15:23:50.000000000 -0400
@@ -8,6 +8,8 @@
  *  BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous*
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
@@ -153,7 +155,7 @@ static unsigned int pentium_core_get_fre
 		fsb = 333333;
 		break;
 	default:
-		printk(KERN_ERR "PCORE - MSR_FSB_FREQ undefined value");
+		pr_err("PCORE - MSR_FSB_FREQ undefined value\n");
 	}
 
 	rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_tmp);
@@ -453,11 +455,8 @@ unsigned int speedstep_get_freqs(enum sp
 		 */
 		if (*transition_latency > 10000000 ||
 		    *transition_latency < 50000) {
-			printk(KERN_WARNING PFX "frequency transition "
-					"measured seems out of range (%u "
-					"nSec), falling back to a safe one of"
-					"%u nSec.\n",
-					*transition_latency, 500000);
+			pr_warn("frequency transition measured seems out of range (%u nSec), falling back to a safe one of %u nSec\n",
+				*transition_latency, 500000);
 			*transition_latency = 500000;
 		}
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/speedstep-smi.c linux-libre-4.7-gnu/drivers/cpufreq/speedstep-smi.c
--- linux-libre-4.6-gnu/drivers/cpufreq/speedstep-smi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/speedstep-smi.c	2016-07-24 15:23:50.000000000 -0400
@@ -12,6 +12,8 @@
  *                        SPEEDSTEP - DEFINITIONS                    *
  *********************************************************************/
 
+#define pr_fmt(fmt) "cpufreq: " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
@@ -204,9 +206,8 @@ static void speedstep_set_state(unsigned
 			(speedstep_freqs[new_state].frequency / 1000),
 			retry, result);
 	else
-		printk(KERN_ERR "cpufreq: change to state %u "
-			"failed with new_state %u and result %u\n",
-			state, new_state, result);
+		pr_err("change to state %u failed with new_state %u and result %u\n",
+		       state, new_state, result);
 
 	return;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/tegra124-cpufreq.c linux-libre-4.7-gnu/drivers/cpufreq/tegra124-cpufreq.c
--- linux-libre-4.6-gnu/drivers/cpufreq/tegra124-cpufreq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/tegra124-cpufreq.c	2016-07-24 15:23:50.000000000 -0400
@@ -14,7 +14,6 @@
 #define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
 
 #include <linux/clk.h>
-#include <linux/cpufreq-dt.h>
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -69,10 +68,6 @@ static void tegra124_cpu_switch_to_pllx(
 	clk_set_parent(priv->cpu_clk, priv->pllx_clk);
 }
 
-static struct cpufreq_dt_platform_data cpufreq_dt_pd = {
-	.independent_clocks = false,
-};
-
 static int tegra124_cpufreq_probe(struct platform_device *pdev)
 {
 	struct tegra124_cpufreq_priv *priv;
@@ -129,8 +124,6 @@ static int tegra124_cpufreq_probe(struct
 
 	cpufreq_dt_devinfo.name = "cpufreq-dt";
 	cpufreq_dt_devinfo.parent = &pdev->dev;
-	cpufreq_dt_devinfo.data = &cpufreq_dt_pd;
-	cpufreq_dt_devinfo.size_data = sizeof(cpufreq_dt_pd);
 
 	priv->cpufreq_dt_pdev =
 		platform_device_register_full(&cpufreq_dt_devinfo);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpufreq/vexpress-spc-cpufreq.c linux-libre-4.7-gnu/drivers/cpufreq/vexpress-spc-cpufreq.c
--- linux-libre-4.6-gnu/drivers/cpufreq/vexpress-spc-cpufreq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpufreq/vexpress-spc-cpufreq.c	2016-07-24 15:23:50.000000000 -0400
@@ -18,6 +18,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/cpu.h>
 #include <linux/cpufreq.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
@@ -26,8 +27,9 @@
 
 #include "arm_big_little.h"
 
-static int ve_spc_init_opp_table(struct device *cpu_dev)
+static int ve_spc_init_opp_table(const struct cpumask *cpumask)
 {
+	struct device *cpu_dev = get_cpu_device(cpumask_first(cpumask));
 	/*
 	 * platform specific SPC code must initialise the opp table
 	 * so just check if the OPP count is non-zero
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/cpuidle/cpuidle.c linux-libre-4.7-gnu/drivers/cpuidle/cpuidle.c
--- linux-libre-4.6-gnu/drivers/cpuidle/cpuidle.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/cpuidle/cpuidle.c	2016-07-24 15:23:50.000000000 -0400
@@ -195,13 +195,13 @@ int cpuidle_enter_state(struct cpuidle_d
 	sched_idle_set_state(target_state);
 
 	trace_cpu_idle_rcuidle(index, dev->cpu);
-	time_start = ktime_get();
+	time_start = ns_to_ktime(local_clock());
 
 	stop_critical_timings();
 	entered_state = target_state->enter(dev, drv, index);
 	start_critical_timings();
 
-	time_end = ktime_get();
+	time_end = ns_to_ktime(local_clock());
 	trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu);
 
 	/* The cpu is no longer idle or about to enter idle. */
@@ -214,10 +214,10 @@ int cpuidle_enter_state(struct cpuidle_d
 		tick_broadcast_exit();
 	}
 
-	if (!cpuidle_state_is_coupled(drv, entered_state))
+	if (!cpuidle_state_is_coupled(drv, index))
 		local_irq_enable();
 
-	diff = ktime_to_us(ktime_sub(time_end, time_start));
+	diff = ktime_us_delta(time_end, time_start);
 	if (diff > INT_MAX)
 		diff = INT_MAX;
 
@@ -433,6 +433,8 @@ static void __cpuidle_unregister_device(
 	list_del(&dev->device_list);
 	per_cpu(cpuidle_devices, dev->cpu) = NULL;
 	module_put(drv->owner);
+
+	dev->registered = 0;
 }
 
 static void __cpuidle_device_init(struct cpuidle_device *dev)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/amcc/crypto4xx_core.c linux-libre-4.7-gnu/drivers/crypto/amcc/crypto4xx_core.c
--- linux-libre-4.6-gnu/drivers/crypto/amcc/crypto4xx_core.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/amcc/crypto4xx_core.c	2016-07-24 15:23:50.000000000 -0400
@@ -40,6 +40,7 @@
 #include "crypto4xx_reg_def.h"
 #include "crypto4xx_core.h"
 #include "crypto4xx_sa.h"
+#include "crypto4xx_trng.h"
 
 #define PPC4XX_SEC_VERSION_STR			"0.5"
 
@@ -1225,6 +1226,7 @@ static int crypto4xx_probe(struct platfo
 	if (rc)
 		goto err_start_dev;
 
+	ppc4xx_trng_probe(core_dev);
 	return 0;
 
 err_start_dev:
@@ -1252,6 +1254,8 @@ static int crypto4xx_remove(struct platf
 	struct device *dev = &ofdev->dev;
 	struct crypto4xx_core_device *core_dev = dev_get_drvdata(dev);
 
+	ppc4xx_trng_remove(core_dev);
+
 	free_irq(core_dev->irq, dev);
 	irq_dispose_mapping(core_dev->irq);
 
@@ -1272,7 +1276,7 @@ MODULE_DEVICE_TABLE(of, crypto4xx_match)
 
 static struct platform_driver crypto4xx_driver = {
 	.driver = {
-		.name = "crypto4xx",
+		.name = MODULE_NAME,
 		.of_match_table = crypto4xx_match,
 	},
 	.probe		= crypto4xx_probe,
@@ -1284,4 +1288,3 @@ module_platform_driver(crypto4xx_driver)
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("James Hsiao <jhsiao@amcc.com>");
 MODULE_DESCRIPTION("Driver for AMCC PPC4xx crypto accelerator");
-
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/amcc/crypto4xx_core.h linux-libre-4.7-gnu/drivers/crypto/amcc/crypto4xx_core.h
--- linux-libre-4.6-gnu/drivers/crypto/amcc/crypto4xx_core.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/amcc/crypto4xx_core.h	2016-07-24 15:23:50.000000000 -0400
@@ -24,6 +24,8 @@
 
 #include <crypto/internal/hash.h>
 
+#define MODULE_NAME "crypto4xx"
+
 #define PPC460SX_SDR0_SRST                      0x201
 #define PPC405EX_SDR0_SRST                      0x200
 #define PPC460EX_SDR0_SRST                      0x201
@@ -72,6 +74,7 @@ struct crypto4xx_device {
 	char *name;
 	u64  ce_phy_address;
 	void __iomem *ce_base;
+	void __iomem *trng_base;
 
 	void *pdr;			/* base address of packet
 					descriptor ring */
@@ -106,6 +109,7 @@ struct crypto4xx_core_device {
 	struct device *device;
 	struct platform_device *ofdev;
 	struct crypto4xx_device *dev;
+	struct hwrng *trng;
 	u32 int_status;
 	u32 irq;
 	struct tasklet_struct tasklet;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/amcc/crypto4xx_reg_def.h linux-libre-4.7-gnu/drivers/crypto/amcc/crypto4xx_reg_def.h
--- linux-libre-4.6-gnu/drivers/crypto/amcc/crypto4xx_reg_def.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/amcc/crypto4xx_reg_def.h	2016-07-24 15:23:50.000000000 -0400
@@ -125,6 +125,7 @@
 #define PPC4XX_INTERRUPT_CLR			0x3ffff
 #define PPC4XX_PRNG_CTRL_AUTO_EN		0x3
 #define PPC4XX_DC_3DES_EN			1
+#define PPC4XX_TRNG_EN				0x00020000
 #define PPC4XX_INT_DESCR_CNT			4
 #define PPC4XX_INT_TIMEOUT_CNT			0
 #define PPC4XX_INT_CFG				1
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/amcc/crypto4xx_trng.c linux-libre-4.7-gnu/drivers/crypto/amcc/crypto4xx_trng.c
--- linux-libre-4.6-gnu/drivers/crypto/amcc/crypto4xx_trng.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/crypto/amcc/crypto4xx_trng.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,131 @@
+/*
+ * Generic PowerPC 44x RNG driver
+ *
+ * Copyright 2011 IBM 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.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/hw_random.h>
+#include <linux/delay.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/io.h>
+
+#include "crypto4xx_core.h"
+#include "crypto4xx_trng.h"
+#include "crypto4xx_reg_def.h"
+
+#define PPC4XX_TRNG_CTRL	0x0008
+#define PPC4XX_TRNG_CTRL_DALM	0x20
+#define PPC4XX_TRNG_STAT	0x0004
+#define PPC4XX_TRNG_STAT_B	0x1
+#define PPC4XX_TRNG_DATA	0x0000
+
+static int ppc4xx_trng_data_present(struct hwrng *rng, int wait)
+{
+	struct crypto4xx_device *dev = (void *)rng->priv;
+	int busy, i, present = 0;
+
+	for (i = 0; i < 20; i++) {
+		busy = (in_le32(dev->trng_base + PPC4XX_TRNG_STAT) &
+			PPC4XX_TRNG_STAT_B);
+		if (!busy || !wait) {
+			present = 1;
+			break;
+		}
+		udelay(10);
+	}
+	return present;
+}
+
+static int ppc4xx_trng_data_read(struct hwrng *rng, u32 *data)
+{
+	struct crypto4xx_device *dev = (void *)rng->priv;
+	*data = in_le32(dev->trng_base + PPC4XX_TRNG_DATA);
+	return 4;
+}
+
+static void ppc4xx_trng_enable(struct crypto4xx_device *dev, bool enable)
+{
+	u32 device_ctrl;
+
+	device_ctrl = readl(dev->ce_base + CRYPTO4XX_DEVICE_CTRL);
+	if (enable)
+		device_ctrl |= PPC4XX_TRNG_EN;
+	else
+		device_ctrl &= ~PPC4XX_TRNG_EN;
+	writel(device_ctrl, dev->ce_base + CRYPTO4XX_DEVICE_CTRL);
+}
+
+static const struct of_device_id ppc4xx_trng_match[] = {
+	{ .compatible = "ppc4xx-rng", },
+	{ .compatible = "amcc,ppc460ex-rng", },
+	{ .compatible = "amcc,ppc440epx-rng", },
+	{},
+};
+
+void ppc4xx_trng_probe(struct crypto4xx_core_device *core_dev)
+{
+	struct crypto4xx_device *dev = core_dev->dev;
+	struct device_node *trng = NULL;
+	struct hwrng *rng = NULL;
+	int err;
+
+	/* Find the TRNG device node and map it */
+	trng = of_find_matching_node(NULL, ppc4xx_trng_match);
+	if (!trng || !of_device_is_available(trng))
+		return;
+
+	dev->trng_base = of_iomap(trng, 0);
+	of_node_put(trng);
+	if (!dev->trng_base)
+		goto err_out;
+
+	rng = kzalloc(sizeof(*rng), GFP_KERNEL);
+	if (!rng)
+		goto err_out;
+
+	rng->name = MODULE_NAME;
+	rng->data_present = ppc4xx_trng_data_present;
+	rng->data_read = ppc4xx_trng_data_read;
+	rng->priv = (unsigned long) dev;
+	core_dev->trng = rng;
+	ppc4xx_trng_enable(dev, true);
+	out_le32(dev->trng_base + PPC4XX_TRNG_CTRL, PPC4XX_TRNG_CTRL_DALM);
+	err = devm_hwrng_register(core_dev->device, core_dev->trng);
+	if (err) {
+		ppc4xx_trng_enable(dev, false);
+		dev_err(core_dev->device, "failed to register hwrng (%d).\n",
+			err);
+		goto err_out;
+	}
+	return;
+
+err_out:
+	of_node_put(trng);
+	iounmap(dev->trng_base);
+	kfree(rng);
+	dev->trng_base = NULL;
+	core_dev->trng = NULL;
+}
+
+void ppc4xx_trng_remove(struct crypto4xx_core_device *core_dev)
+{
+	if (core_dev && core_dev->trng) {
+		struct crypto4xx_device *dev = core_dev->dev;
+
+		devm_hwrng_unregister(core_dev->device, core_dev->trng);
+		ppc4xx_trng_enable(dev, false);
+		iounmap(dev->trng_base);
+		kfree(core_dev->trng);
+	}
+}
+
+MODULE_ALIAS("ppc4xx_rng");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/amcc/crypto4xx_trng.h linux-libre-4.7-gnu/drivers/crypto/amcc/crypto4xx_trng.h
--- linux-libre-4.6-gnu/drivers/crypto/amcc/crypto4xx_trng.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/crypto/amcc/crypto4xx_trng.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,34 @@
+/**
+ * AMCC SoC PPC4xx Crypto Driver
+ *
+ * Copyright (c) 2008 Applied Micro Circuits Corporation.
+ * All rights reserved. James Hsiao <jhsiao@amcc.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * This file defines the security context
+ * associate format.
+ */
+
+#ifndef __CRYPTO4XX_TRNG_H__
+#define __CRYPTO4XX_TRNG_H__
+
+#ifdef CONFIG_HW_RANDOM_PPC4XX
+void ppc4xx_trng_probe(struct crypto4xx_core_device *core_dev);
+void ppc4xx_trng_remove(struct crypto4xx_core_device *core_dev);
+#else
+static inline void ppc4xx_trng_probe(
+	struct crypto4xx_device *dev __maybe_unused) { }
+static inline void ppc4xx_trng_remove(
+	struct crypto4xx_device *dev __maybe_unused) { }
+#endif
+
+#endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/amcc/Makefile linux-libre-4.7-gnu/drivers/crypto/amcc/Makefile
--- linux-libre-4.6-gnu/drivers/crypto/amcc/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/amcc/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -1,2 +1,3 @@
 obj-$(CONFIG_CRYPTO_DEV_PPC4XX) += crypto4xx.o
 crypto4xx-y :=  crypto4xx_core.o crypto4xx_alg.o crypto4xx_sa.o
+crypto4xx-$(CONFIG_HW_RANDOM_PPC4XX) += crypto4xx_trng.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/caam/ctrl.c linux-libre-4.7-gnu/drivers/crypto/caam/ctrl.c
--- linux-libre-4.6-gnu/drivers/crypto/caam/ctrl.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/caam/ctrl.c	2016-07-24 15:23:50.000000000 -0400
@@ -402,7 +402,7 @@ int caam_get_era(void)
 	ret = of_property_read_u32(caam_node, "fsl,sec-era", &prop);
 	of_node_put(caam_node);
 
-	return IS_ERR_VALUE(ret) ? -ENOTSUPP : prop;
+	return ret ? -ENOTSUPP : prop;
 }
 EXPORT_SYMBOL(caam_get_era);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/caam/jr.c linux-libre-4.7-gnu/drivers/crypto/caam/jr.c
--- linux-libre-4.6-gnu/drivers/crypto/caam/jr.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/caam/jr.c	2016-07-24 15:23:50.000000000 -0400
@@ -248,7 +248,7 @@ static void caam_jr_dequeue(unsigned lon
 struct device *caam_jr_alloc(void)
 {
 	struct caam_drv_private_jr *jrpriv, *min_jrpriv = NULL;
-	struct device *dev = NULL;
+	struct device *dev = ERR_PTR(-ENODEV);
 	int min_tfm_cnt	= INT_MAX;
 	int tfm_cnt;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/ccp/ccp-crypto-aes-xts.c linux-libre-4.7-gnu/drivers/crypto/ccp/ccp-crypto-aes-xts.c
--- linux-libre-4.6-gnu/drivers/crypto/ccp/ccp-crypto-aes-xts.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/ccp/ccp-crypto-aes-xts.c	2016-07-24 15:23:50.000000000 -0400
@@ -122,6 +122,7 @@ static int ccp_aes_xts_crypt(struct ablk
 	struct ccp_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
 	struct ccp_aes_req_ctx *rctx = ablkcipher_request_ctx(req);
 	unsigned int unit;
+	u32 unit_size;
 	int ret;
 
 	if (!ctx->u.aes.key_len)
@@ -133,11 +134,17 @@ static int ccp_aes_xts_crypt(struct ablk
 	if (!req->info)
 		return -EINVAL;
 
-	for (unit = 0; unit < ARRAY_SIZE(unit_size_map); unit++)
-		if (!(req->nbytes & (unit_size_map[unit].size - 1)))
-			break;
+	unit_size = CCP_XTS_AES_UNIT_SIZE__LAST;
+	if (req->nbytes <= unit_size_map[0].size) {
+		for (unit = 0; unit < ARRAY_SIZE(unit_size_map); unit++) {
+			if (!(req->nbytes & (unit_size_map[unit].size - 1))) {
+				unit_size = unit_size_map[unit].value;
+				break;
+			}
+		}
+	}
 
-	if ((unit_size_map[unit].value == CCP_XTS_AES_UNIT_SIZE__LAST) ||
+	if ((unit_size == CCP_XTS_AES_UNIT_SIZE__LAST) ||
 	    (ctx->u.aes.key_len != AES_KEYSIZE_128)) {
 		/* Use the fallback to process the request for any
 		 * unsupported unit sizes or key sizes
@@ -158,7 +165,7 @@ static int ccp_aes_xts_crypt(struct ablk
 	rctx->cmd.engine = CCP_ENGINE_XTS_AES_128;
 	rctx->cmd.u.xts.action = (encrypt) ? CCP_AES_ACTION_ENCRYPT
 					   : CCP_AES_ACTION_DECRYPT;
-	rctx->cmd.u.xts.unit_size = unit_size_map[unit].value;
+	rctx->cmd.u.xts.unit_size = unit_size;
 	rctx->cmd.u.xts.key = &ctx->u.aes.key_sg;
 	rctx->cmd.u.xts.key_len = ctx->u.aes.key_len;
 	rctx->cmd.u.xts.iv = &rctx->iv_sg;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/ccp/ccp-dev.c linux-libre-4.7-gnu/drivers/crypto/ccp/ccp-dev.c
--- linux-libre-4.6-gnu/drivers/crypto/ccp/ccp-dev.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/ccp/ccp-dev.c	2016-07-24 15:23:50.000000000 -0400
@@ -16,7 +16,7 @@
 #include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
-#include <linux/rwlock_types.h>
+#include <linux/spinlock_types.h>
 #include <linux/types.h>
 #include <linux/mutex.h>
 #include <linux/delay.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/ccp/ccp-dev.h linux-libre-4.7-gnu/drivers/crypto/ccp/ccp-dev.h
--- linux-libre-4.6-gnu/drivers/crypto/ccp/ccp-dev.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/ccp/ccp-dev.h	2016-07-24 15:23:50.000000000 -0400
@@ -22,6 +22,9 @@
 #include <linux/dmapool.h>
 #include <linux/hw_random.h>
 #include <linux/bitops.h>
+#include <linux/interrupt.h>
+#include <linux/irqreturn.h>
+#include <linux/dmaengine.h>
 
 #define MAX_CCP_NAME_LEN		16
 #define MAX_DMAPOOL_NAME_LEN		32
@@ -159,7 +162,7 @@ struct ccp_actions {
 /* Structure to hold CCP version-specific values */
 struct ccp_vdata {
 	unsigned int version;
-	struct ccp_actions *perform;
+	const struct ccp_actions *perform;
 };
 
 extern struct ccp_vdata ccpv3;
@@ -167,6 +170,39 @@ extern struct ccp_vdata ccpv3;
 struct ccp_device;
 struct ccp_cmd;
 
+struct ccp_dma_cmd {
+	struct list_head entry;
+
+	struct ccp_cmd ccp_cmd;
+};
+
+struct ccp_dma_desc {
+	struct list_head entry;
+
+	struct ccp_device *ccp;
+
+	struct list_head pending;
+	struct list_head active;
+
+	enum dma_status status;
+	struct dma_async_tx_descriptor tx_desc;
+	size_t len;
+};
+
+struct ccp_dma_chan {
+	struct ccp_device *ccp;
+
+	spinlock_t lock;
+	struct list_head pending;
+	struct list_head active;
+	struct list_head complete;
+
+	struct tasklet_struct cleanup_tasklet;
+
+	enum dma_status status;
+	struct dma_chan dma_chan;
+};
+
 struct ccp_cmd_queue {
 	struct ccp_device *ccp;
 
@@ -261,6 +297,14 @@ struct ccp_device {
 	unsigned int hwrng_retries;
 
 	/*
+	 * Support for the CCP DMA capabilities
+	 */
+	struct dma_device dma_dev;
+	struct ccp_dma_chan *ccp_dma_chan;
+	struct kmem_cache *dma_cmd_cache;
+	struct kmem_cache *dma_desc_cache;
+
+	/*
 	 * A counter used to generate job-ids for cmds submitted to the CCP
 	 */
 	atomic_t current_id ____cacheline_aligned;
@@ -418,4 +462,7 @@ int ccp_cmd_queue_thread(void *data);
 
 int ccp_run_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd);
 
+int ccp_dmaengine_register(struct ccp_device *ccp);
+void ccp_dmaengine_unregister(struct ccp_device *ccp);
+
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/ccp/ccp-dev-v3.c linux-libre-4.7-gnu/drivers/crypto/ccp/ccp-dev-v3.c
--- linux-libre-4.6-gnu/drivers/crypto/ccp/ccp-dev-v3.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/ccp/ccp-dev-v3.c	2016-07-24 15:23:50.000000000 -0400
@@ -406,6 +406,11 @@ static int ccp_init(struct ccp_device *c
 		goto e_kthread;
 	}
 
+	/* Register the DMA engine support */
+	ret = ccp_dmaengine_register(ccp);
+	if (ret)
+		goto e_hwrng;
+
 	ccp_add_device(ccp);
 
 	/* Enable interrupts */
@@ -413,6 +418,9 @@ static int ccp_init(struct ccp_device *c
 
 	return 0;
 
+e_hwrng:
+	hwrng_unregister(&ccp->hwrng);
+
 e_kthread:
 	for (i = 0; i < ccp->cmd_q_count; i++)
 		if (ccp->cmd_q[i].kthread)
@@ -436,6 +444,9 @@ static void ccp_destroy(struct ccp_devic
 	/* Remove this device from the list of available units first */
 	ccp_del_device(ccp);
 
+	/* Unregister the DMA engine */
+	ccp_dmaengine_unregister(ccp);
+
 	/* Unregister the RNG */
 	hwrng_unregister(&ccp->hwrng);
 
@@ -515,7 +526,7 @@ static irqreturn_t ccp_irq_handler(int i
 	return IRQ_HANDLED;
 }
 
-static struct ccp_actions ccp3_actions = {
+static const struct ccp_actions ccp3_actions = {
 	.perform_aes = ccp_perform_aes,
 	.perform_xts_aes = ccp_perform_xts_aes,
 	.perform_sha = ccp_perform_sha,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/ccp/ccp-dmaengine.c linux-libre-4.7-gnu/drivers/crypto/ccp/ccp-dmaengine.c
--- linux-libre-4.6-gnu/drivers/crypto/ccp/ccp-dmaengine.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/crypto/ccp/ccp-dmaengine.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,727 @@
+/*
+ * AMD Cryptographic Coprocessor (CCP) driver
+ *
+ * Copyright (C) 2016 Advanced Micro Devices, Inc.
+ *
+ * Author: Gary R Hook <gary.hook@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/dmaengine.h>
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+#include <linux/ccp.h>
+
+#include "ccp-dev.h"
+#include "../../dma/dmaengine.h"
+
+#define CCP_DMA_WIDTH(_mask)		\
+({					\
+	u64 mask = _mask + 1;		\
+	(mask == 0) ? 64 : fls64(mask);	\
+})
+
+static void ccp_free_cmd_resources(struct ccp_device *ccp,
+				   struct list_head *list)
+{
+	struct ccp_dma_cmd *cmd, *ctmp;
+
+	list_for_each_entry_safe(cmd, ctmp, list, entry) {
+		list_del(&cmd->entry);
+		kmem_cache_free(ccp->dma_cmd_cache, cmd);
+	}
+}
+
+static void ccp_free_desc_resources(struct ccp_device *ccp,
+				    struct list_head *list)
+{
+	struct ccp_dma_desc *desc, *dtmp;
+
+	list_for_each_entry_safe(desc, dtmp, list, entry) {
+		ccp_free_cmd_resources(ccp, &desc->active);
+		ccp_free_cmd_resources(ccp, &desc->pending);
+
+		list_del(&desc->entry);
+		kmem_cache_free(ccp->dma_desc_cache, desc);
+	}
+}
+
+static void ccp_free_chan_resources(struct dma_chan *dma_chan)
+{
+	struct ccp_dma_chan *chan = container_of(dma_chan, struct ccp_dma_chan,
+						 dma_chan);
+	unsigned long flags;
+
+	dev_dbg(chan->ccp->dev, "%s - chan=%p\n", __func__, chan);
+
+	spin_lock_irqsave(&chan->lock, flags);
+
+	ccp_free_desc_resources(chan->ccp, &chan->complete);
+	ccp_free_desc_resources(chan->ccp, &chan->active);
+	ccp_free_desc_resources(chan->ccp, &chan->pending);
+
+	spin_unlock_irqrestore(&chan->lock, flags);
+}
+
+static void ccp_cleanup_desc_resources(struct ccp_device *ccp,
+				       struct list_head *list)
+{
+	struct ccp_dma_desc *desc, *dtmp;
+
+	list_for_each_entry_safe_reverse(desc, dtmp, list, entry) {
+		if (!async_tx_test_ack(&desc->tx_desc))
+			continue;
+
+		dev_dbg(ccp->dev, "%s - desc=%p\n", __func__, desc);
+
+		ccp_free_cmd_resources(ccp, &desc->active);
+		ccp_free_cmd_resources(ccp, &desc->pending);
+
+		list_del(&desc->entry);
+		kmem_cache_free(ccp->dma_desc_cache, desc);
+	}
+}
+
+static void ccp_do_cleanup(unsigned long data)
+{
+	struct ccp_dma_chan *chan = (struct ccp_dma_chan *)data;
+	unsigned long flags;
+
+	dev_dbg(chan->ccp->dev, "%s - chan=%s\n", __func__,
+		dma_chan_name(&chan->dma_chan));
+
+	spin_lock_irqsave(&chan->lock, flags);
+
+	ccp_cleanup_desc_resources(chan->ccp, &chan->complete);
+
+	spin_unlock_irqrestore(&chan->lock, flags);
+}
+
+static int ccp_issue_next_cmd(struct ccp_dma_desc *desc)
+{
+	struct ccp_dma_cmd *cmd;
+	int ret;
+
+	cmd = list_first_entry(&desc->pending, struct ccp_dma_cmd, entry);
+	list_move(&cmd->entry, &desc->active);
+
+	dev_dbg(desc->ccp->dev, "%s - tx %d, cmd=%p\n", __func__,
+		desc->tx_desc.cookie, cmd);
+
+	ret = ccp_enqueue_cmd(&cmd->ccp_cmd);
+	if (!ret || (ret == -EINPROGRESS) || (ret == -EBUSY))
+		return 0;
+
+	dev_dbg(desc->ccp->dev, "%s - error: ret=%d, tx %d, cmd=%p\n", __func__,
+		ret, desc->tx_desc.cookie, cmd);
+
+	return ret;
+}
+
+static void ccp_free_active_cmd(struct ccp_dma_desc *desc)
+{
+	struct ccp_dma_cmd *cmd;
+
+	cmd = list_first_entry_or_null(&desc->active, struct ccp_dma_cmd,
+				       entry);
+	if (!cmd)
+		return;
+
+	dev_dbg(desc->ccp->dev, "%s - freeing tx %d cmd=%p\n",
+		__func__, desc->tx_desc.cookie, cmd);
+
+	list_del(&cmd->entry);
+	kmem_cache_free(desc->ccp->dma_cmd_cache, cmd);
+}
+
+static struct ccp_dma_desc *__ccp_next_dma_desc(struct ccp_dma_chan *chan,
+						struct ccp_dma_desc *desc)
+{
+	/* Move current DMA descriptor to the complete list */
+	if (desc)
+		list_move(&desc->entry, &chan->complete);
+
+	/* Get the next DMA descriptor on the active list */
+	desc = list_first_entry_or_null(&chan->active, struct ccp_dma_desc,
+					entry);
+
+	return desc;
+}
+
+static struct ccp_dma_desc *ccp_handle_active_desc(struct ccp_dma_chan *chan,
+						   struct ccp_dma_desc *desc)
+{
+	struct dma_async_tx_descriptor *tx_desc;
+	unsigned long flags;
+
+	/* Loop over descriptors until one is found with commands */
+	do {
+		if (desc) {
+			/* Remove the DMA command from the list and free it */
+			ccp_free_active_cmd(desc);
+
+			if (!list_empty(&desc->pending)) {
+				/* No errors, keep going */
+				if (desc->status != DMA_ERROR)
+					return desc;
+
+				/* Error, free remaining commands and move on */
+				ccp_free_cmd_resources(desc->ccp,
+						       &desc->pending);
+			}
+
+			tx_desc = &desc->tx_desc;
+		} else {
+			tx_desc = NULL;
+		}
+
+		spin_lock_irqsave(&chan->lock, flags);
+
+		if (desc) {
+			if (desc->status != DMA_ERROR)
+				desc->status = DMA_COMPLETE;
+
+			dev_dbg(desc->ccp->dev,
+				"%s - tx %d complete, status=%u\n", __func__,
+				desc->tx_desc.cookie, desc->status);
+
+			dma_cookie_complete(tx_desc);
+		}
+
+		desc = __ccp_next_dma_desc(chan, desc);
+
+		spin_unlock_irqrestore(&chan->lock, flags);
+
+		if (tx_desc) {
+			if (tx_desc->callback &&
+			    (tx_desc->flags & DMA_PREP_INTERRUPT))
+				tx_desc->callback(tx_desc->callback_param);
+
+			dma_run_dependencies(tx_desc);
+		}
+	} while (desc);
+
+	return NULL;
+}
+
+static struct ccp_dma_desc *__ccp_pending_to_active(struct ccp_dma_chan *chan)
+{
+	struct ccp_dma_desc *desc;
+
+	if (list_empty(&chan->pending))
+		return NULL;
+
+	desc = list_empty(&chan->active)
+		? list_first_entry(&chan->pending, struct ccp_dma_desc, entry)
+		: NULL;
+
+	list_splice_tail_init(&chan->pending, &chan->active);
+
+	return desc;
+}
+
+static void ccp_cmd_callback(void *data, int err)
+{
+	struct ccp_dma_desc *desc = data;
+	struct ccp_dma_chan *chan;
+	int ret;
+
+	if (err == -EINPROGRESS)
+		return;
+
+	chan = container_of(desc->tx_desc.chan, struct ccp_dma_chan,
+			    dma_chan);
+
+	dev_dbg(chan->ccp->dev, "%s - tx %d callback, err=%d\n",
+		__func__, desc->tx_desc.cookie, err);
+
+	if (err)
+		desc->status = DMA_ERROR;
+
+	while (true) {
+		/* Check for DMA descriptor completion */
+		desc = ccp_handle_active_desc(chan, desc);
+
+		/* Don't submit cmd if no descriptor or DMA is paused */
+		if (!desc || (chan->status == DMA_PAUSED))
+			break;
+
+		ret = ccp_issue_next_cmd(desc);
+		if (!ret)
+			break;
+
+		desc->status = DMA_ERROR;
+	}
+
+	tasklet_schedule(&chan->cleanup_tasklet);
+}
+
+static dma_cookie_t ccp_tx_submit(struct dma_async_tx_descriptor *tx_desc)
+{
+	struct ccp_dma_desc *desc = container_of(tx_desc, struct ccp_dma_desc,
+						 tx_desc);
+	struct ccp_dma_chan *chan;
+	dma_cookie_t cookie;
+	unsigned long flags;
+
+	chan = container_of(tx_desc->chan, struct ccp_dma_chan, dma_chan);
+
+	spin_lock_irqsave(&chan->lock, flags);
+
+	cookie = dma_cookie_assign(tx_desc);
+	list_add_tail(&desc->entry, &chan->pending);
+
+	spin_unlock_irqrestore(&chan->lock, flags);
+
+	dev_dbg(chan->ccp->dev, "%s - added tx descriptor %d to pending list\n",
+		__func__, cookie);
+
+	return cookie;
+}
+
+static struct ccp_dma_cmd *ccp_alloc_dma_cmd(struct ccp_dma_chan *chan)
+{
+	struct ccp_dma_cmd *cmd;
+
+	cmd = kmem_cache_alloc(chan->ccp->dma_cmd_cache, GFP_NOWAIT);
+	if (cmd)
+		memset(cmd, 0, sizeof(*cmd));
+
+	return cmd;
+}
+
+static struct ccp_dma_desc *ccp_alloc_dma_desc(struct ccp_dma_chan *chan,
+					       unsigned long flags)
+{
+	struct ccp_dma_desc *desc;
+
+	desc = kmem_cache_alloc(chan->ccp->dma_desc_cache, GFP_NOWAIT);
+	if (!desc)
+		return NULL;
+
+	memset(desc, 0, sizeof(*desc));
+
+	dma_async_tx_descriptor_init(&desc->tx_desc, &chan->dma_chan);
+	desc->tx_desc.flags = flags;
+	desc->tx_desc.tx_submit = ccp_tx_submit;
+	desc->ccp = chan->ccp;
+	INIT_LIST_HEAD(&desc->pending);
+	INIT_LIST_HEAD(&desc->active);
+	desc->status = DMA_IN_PROGRESS;
+
+	return desc;
+}
+
+static struct ccp_dma_desc *ccp_create_desc(struct dma_chan *dma_chan,
+					    struct scatterlist *dst_sg,
+					    unsigned int dst_nents,
+					    struct scatterlist *src_sg,
+					    unsigned int src_nents,
+					    unsigned long flags)
+{
+	struct ccp_dma_chan *chan = container_of(dma_chan, struct ccp_dma_chan,
+						 dma_chan);
+	struct ccp_device *ccp = chan->ccp;
+	struct ccp_dma_desc *desc;
+	struct ccp_dma_cmd *cmd;
+	struct ccp_cmd *ccp_cmd;
+	struct ccp_passthru_nomap_engine *ccp_pt;
+	unsigned int src_offset, src_len;
+	unsigned int dst_offset, dst_len;
+	unsigned int len;
+	unsigned long sflags;
+	size_t total_len;
+
+	if (!dst_sg || !src_sg)
+		return NULL;
+
+	if (!dst_nents || !src_nents)
+		return NULL;
+
+	desc = ccp_alloc_dma_desc(chan, flags);
+	if (!desc)
+		return NULL;
+
+	total_len = 0;
+
+	src_len = sg_dma_len(src_sg);
+	src_offset = 0;
+
+	dst_len = sg_dma_len(dst_sg);
+	dst_offset = 0;
+
+	while (true) {
+		if (!src_len) {
+			src_nents--;
+			if (!src_nents)
+				break;
+
+			src_sg = sg_next(src_sg);
+			if (!src_sg)
+				break;
+
+			src_len = sg_dma_len(src_sg);
+			src_offset = 0;
+			continue;
+		}
+
+		if (!dst_len) {
+			dst_nents--;
+			if (!dst_nents)
+				break;
+
+			dst_sg = sg_next(dst_sg);
+			if (!dst_sg)
+				break;
+
+			dst_len = sg_dma_len(dst_sg);
+			dst_offset = 0;
+			continue;
+		}
+
+		len = min(dst_len, src_len);
+
+		cmd = ccp_alloc_dma_cmd(chan);
+		if (!cmd)
+			goto err;
+
+		ccp_cmd = &cmd->ccp_cmd;
+		ccp_pt = &ccp_cmd->u.passthru_nomap;
+		ccp_cmd->flags = CCP_CMD_MAY_BACKLOG;
+		ccp_cmd->flags |= CCP_CMD_PASSTHRU_NO_DMA_MAP;
+		ccp_cmd->engine = CCP_ENGINE_PASSTHRU;
+		ccp_pt->bit_mod = CCP_PASSTHRU_BITWISE_NOOP;
+		ccp_pt->byte_swap = CCP_PASSTHRU_BYTESWAP_NOOP;
+		ccp_pt->src_dma = sg_dma_address(src_sg) + src_offset;
+		ccp_pt->dst_dma = sg_dma_address(dst_sg) + dst_offset;
+		ccp_pt->src_len = len;
+		ccp_pt->final = 1;
+		ccp_cmd->callback = ccp_cmd_callback;
+		ccp_cmd->data = desc;
+
+		list_add_tail(&cmd->entry, &desc->pending);
+
+		dev_dbg(ccp->dev,
+			"%s - cmd=%p, src=%pad, dst=%pad, len=%llu\n", __func__,
+			cmd, &ccp_pt->src_dma,
+			&ccp_pt->dst_dma, ccp_pt->src_len);
+
+		total_len += len;
+
+		src_len -= len;
+		src_offset += len;
+
+		dst_len -= len;
+		dst_offset += len;
+	}
+
+	desc->len = total_len;
+
+	if (list_empty(&desc->pending))
+		goto err;
+
+	dev_dbg(ccp->dev, "%s - desc=%p\n", __func__, desc);
+
+	spin_lock_irqsave(&chan->lock, sflags);
+
+	list_add_tail(&desc->entry, &chan->pending);
+
+	spin_unlock_irqrestore(&chan->lock, sflags);
+
+	return desc;
+
+err:
+	ccp_free_cmd_resources(ccp, &desc->pending);
+	kmem_cache_free(ccp->dma_desc_cache, desc);
+
+	return NULL;
+}
+
+static struct dma_async_tx_descriptor *ccp_prep_dma_memcpy(
+	struct dma_chan *dma_chan, dma_addr_t dst, dma_addr_t src, size_t len,
+	unsigned long flags)
+{
+	struct ccp_dma_chan *chan = container_of(dma_chan, struct ccp_dma_chan,
+						 dma_chan);
+	struct ccp_dma_desc *desc;
+	struct scatterlist dst_sg, src_sg;
+
+	dev_dbg(chan->ccp->dev,
+		"%s - src=%pad, dst=%pad, len=%zu, flags=%#lx\n",
+		__func__, &src, &dst, len, flags);
+
+	sg_init_table(&dst_sg, 1);
+	sg_dma_address(&dst_sg) = dst;
+	sg_dma_len(&dst_sg) = len;
+
+	sg_init_table(&src_sg, 1);
+	sg_dma_address(&src_sg) = src;
+	sg_dma_len(&src_sg) = len;
+
+	desc = ccp_create_desc(dma_chan, &dst_sg, 1, &src_sg, 1, flags);
+	if (!desc)
+		return NULL;
+
+	return &desc->tx_desc;
+}
+
+static struct dma_async_tx_descriptor *ccp_prep_dma_sg(
+	struct dma_chan *dma_chan, struct scatterlist *dst_sg,
+	unsigned int dst_nents, struct scatterlist *src_sg,
+	unsigned int src_nents, unsigned long flags)
+{
+	struct ccp_dma_chan *chan = container_of(dma_chan, struct ccp_dma_chan,
+						 dma_chan);
+	struct ccp_dma_desc *desc;
+
+	dev_dbg(chan->ccp->dev,
+		"%s - src=%p, src_nents=%u dst=%p, dst_nents=%u, flags=%#lx\n",
+		__func__, src_sg, src_nents, dst_sg, dst_nents, flags);
+
+	desc = ccp_create_desc(dma_chan, dst_sg, dst_nents, src_sg, src_nents,
+			       flags);
+	if (!desc)
+		return NULL;
+
+	return &desc->tx_desc;
+}
+
+static struct dma_async_tx_descriptor *ccp_prep_dma_interrupt(
+	struct dma_chan *dma_chan, unsigned long flags)
+{
+	struct ccp_dma_chan *chan = container_of(dma_chan, struct ccp_dma_chan,
+						 dma_chan);
+	struct ccp_dma_desc *desc;
+
+	desc = ccp_alloc_dma_desc(chan, flags);
+	if (!desc)
+		return NULL;
+
+	return &desc->tx_desc;
+}
+
+static void ccp_issue_pending(struct dma_chan *dma_chan)
+{
+	struct ccp_dma_chan *chan = container_of(dma_chan, struct ccp_dma_chan,
+						 dma_chan);
+	struct ccp_dma_desc *desc;
+	unsigned long flags;
+
+	dev_dbg(chan->ccp->dev, "%s\n", __func__);
+
+	spin_lock_irqsave(&chan->lock, flags);
+
+	desc = __ccp_pending_to_active(chan);
+
+	spin_unlock_irqrestore(&chan->lock, flags);
+
+	/* If there was nothing active, start processing */
+	if (desc)
+		ccp_cmd_callback(desc, 0);
+}
+
+static enum dma_status ccp_tx_status(struct dma_chan *dma_chan,
+				     dma_cookie_t cookie,
+				     struct dma_tx_state *state)
+{
+	struct ccp_dma_chan *chan = container_of(dma_chan, struct ccp_dma_chan,
+						 dma_chan);
+	struct ccp_dma_desc *desc;
+	enum dma_status ret;
+	unsigned long flags;
+
+	if (chan->status == DMA_PAUSED) {
+		ret = DMA_PAUSED;
+		goto out;
+	}
+
+	ret = dma_cookie_status(dma_chan, cookie, state);
+	if (ret == DMA_COMPLETE) {
+		spin_lock_irqsave(&chan->lock, flags);
+
+		/* Get status from complete chain, if still there */
+		list_for_each_entry(desc, &chan->complete, entry) {
+			if (desc->tx_desc.cookie != cookie)
+				continue;
+
+			ret = desc->status;
+			break;
+		}
+
+		spin_unlock_irqrestore(&chan->lock, flags);
+	}
+
+out:
+	dev_dbg(chan->ccp->dev, "%s - %u\n", __func__, ret);
+
+	return ret;
+}
+
+static int ccp_pause(struct dma_chan *dma_chan)
+{
+	struct ccp_dma_chan *chan = container_of(dma_chan, struct ccp_dma_chan,
+						 dma_chan);
+
+	chan->status = DMA_PAUSED;
+
+	/*TODO: Wait for active DMA to complete before returning? */
+
+	return 0;
+}
+
+static int ccp_resume(struct dma_chan *dma_chan)
+{
+	struct ccp_dma_chan *chan = container_of(dma_chan, struct ccp_dma_chan,
+						 dma_chan);
+	struct ccp_dma_desc *desc;
+	unsigned long flags;
+
+	spin_lock_irqsave(&chan->lock, flags);
+
+	desc = list_first_entry_or_null(&chan->active, struct ccp_dma_desc,
+					entry);
+
+	spin_unlock_irqrestore(&chan->lock, flags);
+
+	/* Indicate the channel is running again */
+	chan->status = DMA_IN_PROGRESS;
+
+	/* If there was something active, re-start */
+	if (desc)
+		ccp_cmd_callback(desc, 0);
+
+	return 0;
+}
+
+static int ccp_terminate_all(struct dma_chan *dma_chan)
+{
+	struct ccp_dma_chan *chan = container_of(dma_chan, struct ccp_dma_chan,
+						 dma_chan);
+	unsigned long flags;
+
+	dev_dbg(chan->ccp->dev, "%s\n", __func__);
+
+	/*TODO: Wait for active DMA to complete before continuing */
+
+	spin_lock_irqsave(&chan->lock, flags);
+
+	/*TODO: Purge the complete list? */
+	ccp_free_desc_resources(chan->ccp, &chan->active);
+	ccp_free_desc_resources(chan->ccp, &chan->pending);
+
+	spin_unlock_irqrestore(&chan->lock, flags);
+
+	return 0;
+}
+
+int ccp_dmaengine_register(struct ccp_device *ccp)
+{
+	struct ccp_dma_chan *chan;
+	struct dma_device *dma_dev = &ccp->dma_dev;
+	struct dma_chan *dma_chan;
+	char *dma_cmd_cache_name;
+	char *dma_desc_cache_name;
+	unsigned int i;
+	int ret;
+
+	ccp->ccp_dma_chan = devm_kcalloc(ccp->dev, ccp->cmd_q_count,
+					 sizeof(*(ccp->ccp_dma_chan)),
+					 GFP_KERNEL);
+	if (!ccp->ccp_dma_chan)
+		return -ENOMEM;
+
+	dma_cmd_cache_name = devm_kasprintf(ccp->dev, GFP_KERNEL,
+					    "%s-dmaengine-cmd-cache",
+					    ccp->name);
+	if (!dma_cmd_cache_name)
+		return -ENOMEM;
+
+	ccp->dma_cmd_cache = kmem_cache_create(dma_cmd_cache_name,
+					       sizeof(struct ccp_dma_cmd),
+					       sizeof(void *),
+					       SLAB_HWCACHE_ALIGN, NULL);
+	if (!ccp->dma_cmd_cache)
+		return -ENOMEM;
+
+	dma_desc_cache_name = devm_kasprintf(ccp->dev, GFP_KERNEL,
+					     "%s-dmaengine-desc-cache",
+					     ccp->name);
+	if (!dma_cmd_cache_name)
+		return -ENOMEM;
+	ccp->dma_desc_cache = kmem_cache_create(dma_desc_cache_name,
+						sizeof(struct ccp_dma_desc),
+						sizeof(void *),
+						SLAB_HWCACHE_ALIGN, NULL);
+	if (!ccp->dma_desc_cache) {
+		ret = -ENOMEM;
+		goto err_cache;
+	}
+
+	dma_dev->dev = ccp->dev;
+	dma_dev->src_addr_widths = CCP_DMA_WIDTH(dma_get_mask(ccp->dev));
+	dma_dev->dst_addr_widths = CCP_DMA_WIDTH(dma_get_mask(ccp->dev));
+	dma_dev->directions = DMA_MEM_TO_MEM;
+	dma_dev->residue_granularity = DMA_RESIDUE_GRANULARITY_DESCRIPTOR;
+	dma_cap_set(DMA_MEMCPY, dma_dev->cap_mask);
+	dma_cap_set(DMA_SG, dma_dev->cap_mask);
+	dma_cap_set(DMA_INTERRUPT, dma_dev->cap_mask);
+
+	INIT_LIST_HEAD(&dma_dev->channels);
+	for (i = 0; i < ccp->cmd_q_count; i++) {
+		chan = ccp->ccp_dma_chan + i;
+		dma_chan = &chan->dma_chan;
+
+		chan->ccp = ccp;
+
+		spin_lock_init(&chan->lock);
+		INIT_LIST_HEAD(&chan->pending);
+		INIT_LIST_HEAD(&chan->active);
+		INIT_LIST_HEAD(&chan->complete);
+
+		tasklet_init(&chan->cleanup_tasklet, ccp_do_cleanup,
+			     (unsigned long)chan);
+
+		dma_chan->device = dma_dev;
+		dma_cookie_init(dma_chan);
+
+		list_add_tail(&dma_chan->device_node, &dma_dev->channels);
+	}
+
+	dma_dev->device_free_chan_resources = ccp_free_chan_resources;
+	dma_dev->device_prep_dma_memcpy = ccp_prep_dma_memcpy;
+	dma_dev->device_prep_dma_sg = ccp_prep_dma_sg;
+	dma_dev->device_prep_dma_interrupt = ccp_prep_dma_interrupt;
+	dma_dev->device_issue_pending = ccp_issue_pending;
+	dma_dev->device_tx_status = ccp_tx_status;
+	dma_dev->device_pause = ccp_pause;
+	dma_dev->device_resume = ccp_resume;
+	dma_dev->device_terminate_all = ccp_terminate_all;
+
+	ret = dma_async_device_register(dma_dev);
+	if (ret)
+		goto err_reg;
+
+	return 0;
+
+err_reg:
+	kmem_cache_destroy(ccp->dma_desc_cache);
+
+err_cache:
+	kmem_cache_destroy(ccp->dma_cmd_cache);
+
+	return ret;
+}
+
+void ccp_dmaengine_unregister(struct ccp_device *ccp)
+{
+	struct dma_device *dma_dev = &ccp->dma_dev;
+
+	dma_async_device_unregister(dma_dev);
+
+	kmem_cache_destroy(ccp->dma_desc_cache);
+	kmem_cache_destroy(ccp->dma_cmd_cache);
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/ccp/ccp-ops.c linux-libre-4.7-gnu/drivers/crypto/ccp/ccp-ops.c
--- linux-libre-4.6-gnu/drivers/crypto/ccp/ccp-ops.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/ccp/ccp-ops.c	2016-07-24 15:23:50.000000000 -0400
@@ -1427,6 +1427,70 @@ e_mask:
 	return ret;
 }
 
+static int ccp_run_passthru_nomap_cmd(struct ccp_cmd_queue *cmd_q,
+				      struct ccp_cmd *cmd)
+{
+	struct ccp_passthru_nomap_engine *pt = &cmd->u.passthru_nomap;
+	struct ccp_dm_workarea mask;
+	struct ccp_op op;
+	int ret;
+
+	if (!pt->final && (pt->src_len & (CCP_PASSTHRU_BLOCKSIZE - 1)))
+		return -EINVAL;
+
+	if (!pt->src_dma || !pt->dst_dma)
+		return -EINVAL;
+
+	if (pt->bit_mod != CCP_PASSTHRU_BITWISE_NOOP) {
+		if (pt->mask_len != CCP_PASSTHRU_MASKSIZE)
+			return -EINVAL;
+		if (!pt->mask)
+			return -EINVAL;
+	}
+
+	BUILD_BUG_ON(CCP_PASSTHRU_KSB_COUNT != 1);
+
+	memset(&op, 0, sizeof(op));
+	op.cmd_q = cmd_q;
+	op.jobid = ccp_gen_jobid(cmd_q->ccp);
+
+	if (pt->bit_mod != CCP_PASSTHRU_BITWISE_NOOP) {
+		/* Load the mask */
+		op.ksb_key = cmd_q->ksb_key;
+
+		mask.length = pt->mask_len;
+		mask.dma.address = pt->mask;
+		mask.dma.length = pt->mask_len;
+
+		ret = ccp_copy_to_ksb(cmd_q, &mask, op.jobid, op.ksb_key,
+				     CCP_PASSTHRU_BYTESWAP_NOOP);
+		if (ret) {
+			cmd->engine_error = cmd_q->cmd_error;
+			return ret;
+		}
+	}
+
+	/* Send data to the CCP Passthru engine */
+	op.eom = 1;
+	op.soc = 1;
+
+	op.src.type = CCP_MEMTYPE_SYSTEM;
+	op.src.u.dma.address = pt->src_dma;
+	op.src.u.dma.offset = 0;
+	op.src.u.dma.length = pt->src_len;
+
+	op.dst.type = CCP_MEMTYPE_SYSTEM;
+	op.dst.u.dma.address = pt->dst_dma;
+	op.dst.u.dma.offset = 0;
+	op.dst.u.dma.length = pt->src_len;
+
+	ret = cmd_q->ccp->vdata->perform->perform_passthru(&op);
+	if (ret)
+		cmd->engine_error = cmd_q->cmd_error;
+
+	return ret;
+}
+
 static int ccp_run_ecc_mm_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
 {
 	struct ccp_ecc_engine *ecc = &cmd->u.ecc;
@@ -1762,7 +1826,10 @@ int ccp_run_cmd(struct ccp_cmd_queue *cm
 		ret = ccp_run_rsa_cmd(cmd_q, cmd);
 		break;
 	case CCP_ENGINE_PASSTHRU:
-		ret = ccp_run_passthru_cmd(cmd_q, cmd);
+		if (cmd->flags & CCP_CMD_PASSTHRU_NO_DMA_MAP)
+			ret = ccp_run_passthru_nomap_cmd(cmd_q, cmd);
+		else
+			ret = ccp_run_passthru_cmd(cmd_q, cmd);
 		break;
 	case CCP_ENGINE_ECC:
 		ret = ccp_run_ecc_cmd(cmd_q, cmd);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/ccp/Kconfig linux-libre-4.7-gnu/drivers/crypto/ccp/Kconfig
--- linux-libre-4.6-gnu/drivers/crypto/ccp/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/ccp/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -3,6 +3,8 @@ config CRYPTO_DEV_CCP_DD
 	depends on CRYPTO_DEV_CCP
 	default m
 	select HW_RANDOM
+	select DMA_ENGINE
+	select DMADEVICES
 	select CRYPTO_SHA1
 	select CRYPTO_SHA256
 	help
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/ccp/Makefile linux-libre-4.7-gnu/drivers/crypto/ccp/Makefile
--- linux-libre-4.6-gnu/drivers/crypto/ccp/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/ccp/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -1,5 +1,9 @@
 obj-$(CONFIG_CRYPTO_DEV_CCP_DD) += ccp.o
-ccp-objs := ccp-dev.o ccp-ops.o ccp-dev-v3.o ccp-platform.o
+ccp-objs := ccp-dev.o \
+	    ccp-ops.o \
+	    ccp-dev-v3.o \
+	    ccp-platform.o \
+	    ccp-dmaengine.o
 ccp-$(CONFIG_PCI) += ccp-pci.o
 
 obj-$(CONFIG_CRYPTO_DEV_CCP_CRYPTO) += ccp-crypto.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/Kconfig linux-libre-4.7-gnu/drivers/crypto/Kconfig
--- linux-libre-4.6-gnu/drivers/crypto/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -279,6 +279,14 @@ config CRYPTO_DEV_PPC4XX
 	help
 	  This option allows you to have support for AMCC crypto acceleration.
 
+config HW_RANDOM_PPC4XX
+	bool "PowerPC 4xx generic true random number generator support"
+	depends on CRYPTO_DEV_PPC4XX && HW_RANDOM
+	default y
+	---help---
+	 This option provides the kernel-side support for the TRNG hardware
+	 found in the security function of some PowerPC 4xx SoCs.
+
 config CRYPTO_DEV_OMAP_SHAM
 	tristate "Support for OMAP MD5/SHA1/SHA2 hw accelerator"
 	depends on ARCH_OMAP2PLUS
@@ -302,15 +310,16 @@ config CRYPTO_DEV_OMAP_AES
 	  want to use the OMAP module for AES algorithms.
 
 config CRYPTO_DEV_OMAP_DES
-	tristate "Support for OMAP DES3DES hw engine"
+	tristate "Support for OMAP DES/3DES hw engine"
 	depends on ARCH_OMAP2PLUS
 	select CRYPTO_DES
 	select CRYPTO_BLKCIPHER
+	select CRYPTO_ENGINE
 	help
 	  OMAP processors have DES/3DES module accelerator. Select this if you
 	  want to use the OMAP module for DES and 3DES algorithms. Currently
-	  the ECB and CBC modes of operation supported by the driver. Also
-	  accesses made on unaligned boundaries are also supported.
+	  the ECB and CBC modes of operation are supported by the driver. Also
+	  accesses made on unaligned boundaries are supported.
 
 config CRYPTO_DEV_PICOXCELL
 	tristate "Support for picoXcell IPSEC and Layer2 crypto engines"
@@ -340,9 +349,19 @@ config CRYPTO_DEV_SAHARA
 	  This option enables support for the SAHARA HW crypto accelerator
 	  found in some Freescale i.MX chips.
 
+config CRYPTO_DEV_MXC_SCC
+	tristate "Support for Freescale Security Controller (SCC)"
+	depends on ARCH_MXC && OF
+	select CRYPTO_BLKCIPHER
+	select CRYPTO_DES
+	help
+	  This option enables support for the Security Controller (SCC)
+	  found in Freescale i.MX25 chips.
+
 config CRYPTO_DEV_S5P
 	tristate "Support for Samsung S5PV210/Exynos crypto accelerator"
-	depends on ARCH_S5PV210 || ARCH_EXYNOS
+	depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
+	depends on HAS_IOMEM && HAS_DMA
 	select CRYPTO_AES
 	select CRYPTO_BLKCIPHER
 	help
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/Makefile linux-libre-4.7-gnu/drivers/crypto/Makefile
--- linux-libre-4.6-gnu/drivers/crypto/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -23,6 +23,7 @@ obj-$(CONFIG_CRYPTO_DEV_PICOXCELL) += pi
 obj-$(CONFIG_CRYPTO_DEV_PPC4XX) += amcc/
 obj-$(CONFIG_CRYPTO_DEV_S5P) += s5p-sss.o
 obj-$(CONFIG_CRYPTO_DEV_SAHARA) += sahara.o
+obj-$(CONFIG_CRYPTO_DEV_MXC_SCC) += mxc-scc.o
 obj-$(CONFIG_CRYPTO_DEV_TALITOS) += talitos.o
 obj-$(CONFIG_CRYPTO_DEV_UX500) += ux500/
 obj-$(CONFIG_CRYPTO_DEV_QAT) += qat/
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/marvell/cesa.c linux-libre-4.7-gnu/drivers/crypto/marvell/cesa.c
--- linux-libre-4.6-gnu/drivers/crypto/marvell/cesa.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/marvell/cesa.c	2016-07-24 15:23:50.000000000 -0400
@@ -475,18 +475,18 @@ static int mv_cesa_probe(struct platform
 		engine->regs = cesa->regs + CESA_ENGINE_OFF(i);
 
 		if (dram && cesa->caps->has_tdma)
-			mv_cesa_conf_mbus_windows(&cesa->engines[i], dram);
+			mv_cesa_conf_mbus_windows(engine, dram);
 
-		writel(0, cesa->engines[i].regs + CESA_SA_INT_STATUS);
+		writel(0, engine->regs + CESA_SA_INT_STATUS);
 		writel(CESA_SA_CFG_STOP_DIG_ERR,
-		       cesa->engines[i].regs + CESA_SA_CFG);
+		       engine->regs + CESA_SA_CFG);
 		writel(engine->sram_dma & CESA_SA_SRAM_MSK,
-		       cesa->engines[i].regs + CESA_SA_DESC_P0);
+		       engine->regs + CESA_SA_DESC_P0);
 
 		ret = devm_request_threaded_irq(dev, irq, NULL, mv_cesa_int,
 						IRQF_ONESHOT,
 						dev_name(&pdev->dev),
-						&cesa->engines[i]);
+						engine);
 		if (ret)
 			goto err_cleanup;
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/marvell/hash.c linux-libre-4.7-gnu/drivers/crypto/marvell/hash.c
--- linux-libre-4.6-gnu/drivers/crypto/marvell/hash.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/marvell/hash.c	2016-07-24 15:23:50.000000000 -0400
@@ -768,8 +768,7 @@ static int mv_cesa_ahash_export(struct a
 	*len = creq->len;
 	memcpy(hash, creq->state, digsize);
 	memset(cache, 0, blocksize);
-	if (creq->cache)
-		memcpy(cache, creq->cache, creq->cache_ptr);
+	memcpy(cache, creq->cache, creq->cache_ptr);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/marvell/tdma.c linux-libre-4.7-gnu/drivers/crypto/marvell/tdma.c
--- linux-libre-4.6-gnu/drivers/crypto/marvell/tdma.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/marvell/tdma.c	2016-07-24 15:23:50.000000000 -0400
@@ -99,12 +99,11 @@ mv_cesa_dma_add_desc(struct mv_cesa_tdma
 	struct mv_cesa_tdma_desc *new_tdma = NULL;
 	dma_addr_t dma_handle;
 
-	new_tdma = dma_pool_alloc(cesa_dev->dma->tdma_desc_pool, flags,
-				  &dma_handle);
+	new_tdma = dma_pool_zalloc(cesa_dev->dma->tdma_desc_pool, flags,
+				   &dma_handle);
 	if (!new_tdma)
 		return ERR_PTR(-ENOMEM);
 
-	memset(new_tdma, 0, sizeof(*new_tdma));
 	new_tdma->cur_dma = dma_handle;
 	if (chain->last) {
 		chain->last->next_dma = cpu_to_le32(dma_handle);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/mxc-scc.c linux-libre-4.7-gnu/drivers/crypto/mxc-scc.c
--- linux-libre-4.6-gnu/drivers/crypto/mxc-scc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/crypto/mxc-scc.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,765 @@
+/*
+ * Copyright (C) 2016 Pengutronix, Steffen Trumtrar <kernel@pengutronix.de>
+ *
+ * The driver is based on information gathered from
+ * drivers/mxc/security/mxc_scc.c which can be found in
+ * the Freescale linux-2.6-imx.git in the imx_2.6.35_maintain branch.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2, as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ */
+#include <linux/clk.h>
+#include <linux/crypto.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include <crypto/algapi.h>
+#include <crypto/des.h>
+
+/* Secure Memory (SCM) registers */
+#define SCC_SCM_RED_START		0x0000
+#define SCC_SCM_BLACK_START		0x0004
+#define SCC_SCM_LENGTH			0x0008
+#define SCC_SCM_CTRL			0x000C
+#define SCC_SCM_STATUS			0x0010
+#define SCC_SCM_ERROR_STATUS		0x0014
+#define SCC_SCM_INTR_CTRL		0x0018
+#define SCC_SCM_CFG			0x001C
+#define SCC_SCM_INIT_VECTOR_0		0x0020
+#define SCC_SCM_INIT_VECTOR_1		0x0024
+#define SCC_SCM_RED_MEMORY		0x0400
+#define SCC_SCM_BLACK_MEMORY		0x0800
+
+/* Security Monitor (SMN) Registers */
+#define SCC_SMN_STATUS			0x1000
+#define SCC_SMN_COMMAND		0x1004
+#define SCC_SMN_SEQ_START		0x1008
+#define SCC_SMN_SEQ_END		0x100C
+#define SCC_SMN_SEQ_CHECK		0x1010
+#define SCC_SMN_BIT_COUNT		0x1014
+#define SCC_SMN_BITBANK_INC_SIZE	0x1018
+#define SCC_SMN_BITBANK_DECREMENT	0x101C
+#define SCC_SMN_COMPARE_SIZE		0x1020
+#define SCC_SMN_PLAINTEXT_CHECK	0x1024
+#define SCC_SMN_CIPHERTEXT_CHECK	0x1028
+#define SCC_SMN_TIMER_IV		0x102C
+#define SCC_SMN_TIMER_CONTROL		0x1030
+#define SCC_SMN_DEBUG_DETECT_STAT	0x1034
+#define SCC_SMN_TIMER			0x1038
+
+#define SCC_SCM_CTRL_START_CIPHER	BIT(2)
+#define SCC_SCM_CTRL_CBC_MODE		BIT(1)
+#define SCC_SCM_CTRL_DECRYPT_MODE	BIT(0)
+
+#define SCC_SCM_STATUS_LEN_ERR		BIT(12)
+#define SCC_SCM_STATUS_SMN_UNBLOCKED	BIT(11)
+#define SCC_SCM_STATUS_CIPHERING_DONE	BIT(10)
+#define SCC_SCM_STATUS_ZEROIZING_DONE	BIT(9)
+#define SCC_SCM_STATUS_INTR_STATUS	BIT(8)
+#define SCC_SCM_STATUS_SEC_KEY		BIT(7)
+#define SCC_SCM_STATUS_INTERNAL_ERR	BIT(6)
+#define SCC_SCM_STATUS_BAD_SEC_KEY	BIT(5)
+#define SCC_SCM_STATUS_ZEROIZE_FAIL	BIT(4)
+#define SCC_SCM_STATUS_SMN_BLOCKED	BIT(3)
+#define SCC_SCM_STATUS_CIPHERING	BIT(2)
+#define SCC_SCM_STATUS_ZEROIZING	BIT(1)
+#define SCC_SCM_STATUS_BUSY		BIT(0)
+
+#define SCC_SMN_STATUS_STATE_MASK	0x0000001F
+#define SCC_SMN_STATE_START		0x0
+/* The SMN is zeroizing its RAM during reset */
+#define SCC_SMN_STATE_ZEROIZE_RAM	0x5
+/* SMN has passed internal checks */
+#define SCC_SMN_STATE_HEALTH_CHECK	0x6
+/* Fatal Security Violation. SMN is locked, SCM is inoperative. */
+#define SCC_SMN_STATE_FAIL		0x9
+/* SCC is in secure state. SCM is using secret key. */
+#define SCC_SMN_STATE_SECURE		0xA
+/* SCC is not secure. SCM is using default key. */
+#define SCC_SMN_STATE_NON_SECURE	0xC
+
+#define SCC_SCM_INTR_CTRL_ZEROIZE_MEM	BIT(2)
+#define SCC_SCM_INTR_CTRL_CLR_INTR	BIT(1)
+#define SCC_SCM_INTR_CTRL_MASK_INTR	BIT(0)
+
+/* Size, in blocks, of Red memory. */
+#define SCC_SCM_CFG_BLACK_SIZE_MASK	0x07fe0000
+#define SCC_SCM_CFG_BLACK_SIZE_SHIFT	17
+/* Size, in blocks, of Black memory. */
+#define SCC_SCM_CFG_RED_SIZE_MASK	0x0001ff80
+#define SCC_SCM_CFG_RED_SIZE_SHIFT	7
+/* Number of bytes per block. */
+#define SCC_SCM_CFG_BLOCK_SIZE_MASK	0x0000007f
+
+#define SCC_SMN_COMMAND_TAMPER_LOCK	BIT(4)
+#define SCC_SMN_COMMAND_CLR_INTR	BIT(3)
+#define SCC_SMN_COMMAND_CLR_BIT_BANK	BIT(2)
+#define SCC_SMN_COMMAND_EN_INTR	BIT(1)
+#define SCC_SMN_COMMAND_SET_SOFTWARE_ALARM  BIT(0)
+
+#define SCC_KEY_SLOTS			20
+#define SCC_MAX_KEY_SIZE		32
+#define SCC_KEY_SLOT_SIZE		32
+
+#define SCC_CRC_CCITT_START		0xFFFF
+
+/*
+ * Offset into each RAM of the base of the area which is not
+ * used for Stored Keys.
+ */
+#define SCC_NON_RESERVED_OFFSET	(SCC_KEY_SLOTS * SCC_KEY_SLOT_SIZE)
+
+/* Fixed padding for appending to plaintext to fill out a block */
+static char scc_block_padding[8] = { 0x80, 0, 0, 0, 0, 0, 0, 0 };
+
+enum mxc_scc_state {
+	SCC_STATE_OK,
+	SCC_STATE_UNIMPLEMENTED,
+	SCC_STATE_FAILED
+};
+
+struct mxc_scc {
+	struct device		*dev;
+	void __iomem		*base;
+	struct clk		*clk;
+	bool			hw_busy;
+	spinlock_t		lock;
+	struct crypto_queue	queue;
+	struct crypto_async_request *req;
+	int			block_size_bytes;
+	int			black_ram_size_blocks;
+	int			memory_size_bytes;
+	int			bytes_remaining;
+
+	void __iomem		*red_memory;
+	void __iomem		*black_memory;
+};
+
+struct mxc_scc_ctx {
+	struct mxc_scc		*scc;
+	struct scatterlist	*sg_src;
+	size_t			src_nents;
+	struct scatterlist	*sg_dst;
+	size_t			dst_nents;
+	unsigned int		offset;
+	unsigned int		size;
+	unsigned int		ctrl;
+};
+
+struct mxc_scc_crypto_tmpl {
+	struct mxc_scc *scc;
+	struct crypto_alg alg;
+};
+
+static int mxc_scc_get_data(struct mxc_scc_ctx *ctx,
+			    struct crypto_async_request *req)
+{
+	struct ablkcipher_request *ablkreq = ablkcipher_request_cast(req);
+	struct mxc_scc *scc = ctx->scc;
+	size_t len;
+	void __iomem *from;
+
+	if (ctx->ctrl & SCC_SCM_CTRL_DECRYPT_MODE)
+		from = scc->red_memory;
+	else
+		from = scc->black_memory;
+
+	dev_dbg(scc->dev, "pcopy: from 0x%p %d bytes\n", from,
+		ctx->dst_nents * 8);
+	len = sg_pcopy_from_buffer(ablkreq->dst, ctx->dst_nents,
+				   from, ctx->size, ctx->offset);
+	if (!len) {
+		dev_err(scc->dev, "pcopy err from 0x%p (len=%d)\n", from, len);
+		return -EINVAL;
+	}
+
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR,
+		       "red memory@"__stringify(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4,
+		       scc->red_memory, ctx->size, 1);
+	print_hex_dump(KERN_ERR,
+		       "black memory@"__stringify(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4,
+		       scc->black_memory, ctx->size, 1);
+#endif
+
+	ctx->offset += len;
+
+	if (ctx->offset < ablkreq->nbytes)
+		return -EINPROGRESS;
+
+	return 0;
+}
+
+static int mxc_scc_ablkcipher_req_init(struct ablkcipher_request *req,
+				       struct mxc_scc_ctx *ctx)
+{
+	struct mxc_scc *scc = ctx->scc;
+	int nents;
+
+	nents = sg_nents_for_len(req->src, req->nbytes);
+	if (nents < 0) {
+		dev_err(scc->dev, "Invalid number of src SC");
+		return nents;
+	}
+	ctx->src_nents = nents;
+
+	nents = sg_nents_for_len(req->dst, req->nbytes);
+	if (nents < 0) {
+		dev_err(scc->dev, "Invalid number of dst SC");
+		return nents;
+	}
+	ctx->dst_nents = nents;
+
+	ctx->size = 0;
+	ctx->offset = 0;
+
+	return 0;
+}
+
+static int mxc_scc_ablkcipher_req_complete(struct crypto_async_request *req,
+					   struct mxc_scc_ctx *ctx,
+					   int result)
+{
+	struct ablkcipher_request *ablkreq = ablkcipher_request_cast(req);
+	struct mxc_scc *scc = ctx->scc;
+
+	scc->req = NULL;
+	scc->bytes_remaining = scc->memory_size_bytes;
+
+	if (ctx->ctrl & SCC_SCM_CTRL_CBC_MODE)
+		memcpy(ablkreq->info, scc->base + SCC_SCM_INIT_VECTOR_0,
+		       scc->block_size_bytes);
+
+	req->complete(req, result);
+	scc->hw_busy = false;
+
+	return 0;
+}
+
+static int mxc_scc_put_data(struct mxc_scc_ctx *ctx,
+			     struct ablkcipher_request *req)
+{
+	u8 padding_buffer[sizeof(u16) + sizeof(scc_block_padding)];
+	size_t len = min_t(size_t, req->nbytes - ctx->offset,
+			   ctx->scc->bytes_remaining);
+	unsigned int padding_byte_count = 0;
+	struct mxc_scc *scc = ctx->scc;
+	void __iomem *to;
+
+	if (ctx->ctrl & SCC_SCM_CTRL_DECRYPT_MODE)
+		to = scc->black_memory;
+	else
+		to = scc->red_memory;
+
+	if (ctx->ctrl & SCC_SCM_CTRL_CBC_MODE && req->info)
+		memcpy(scc->base + SCC_SCM_INIT_VECTOR_0, req->info,
+		       scc->block_size_bytes);
+
+	len = sg_pcopy_to_buffer(req->src, ctx->src_nents,
+				 to, len, ctx->offset);
+	if (!len) {
+		dev_err(scc->dev, "pcopy err to 0x%p (len=%d)\n", to, len);
+		return -EINVAL;
+	}
+
+	ctx->size = len;
+
+#ifdef DEBUG
+	dev_dbg(scc->dev, "copied %d bytes to 0x%p\n", len, to);
+	print_hex_dump(KERN_ERR,
+		       "init vector0@"__stringify(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4,
+		       scc->base + SCC_SCM_INIT_VECTOR_0, scc->block_size_bytes,
+		       1);
+	print_hex_dump(KERN_ERR,
+		       "red memory@"__stringify(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4,
+		       scc->red_memory, ctx->size, 1);
+	print_hex_dump(KERN_ERR,
+		       "black memory@"__stringify(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4,
+		       scc->black_memory, ctx->size, 1);
+#endif
+
+	scc->bytes_remaining -= len;
+
+	padding_byte_count = len % scc->block_size_bytes;
+
+	if (padding_byte_count) {
+		memcpy(padding_buffer, scc_block_padding, padding_byte_count);
+		memcpy(to + len, padding_buffer, padding_byte_count);
+		ctx->size += padding_byte_count;
+	}
+
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR,
+		       "data to encrypt@"__stringify(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4,
+		       to, ctx->size, 1);
+#endif
+
+	return 0;
+}
+
+static void mxc_scc_ablkcipher_next(struct mxc_scc_ctx *ctx,
+				    struct crypto_async_request *req)
+{
+	struct ablkcipher_request *ablkreq = ablkcipher_request_cast(req);
+	struct mxc_scc *scc = ctx->scc;
+	int err;
+
+	dev_dbg(scc->dev, "dispatch request (nbytes=%d, src=%p, dst=%p)\n",
+		ablkreq->nbytes, ablkreq->src, ablkreq->dst);
+
+	writel(0, scc->base + SCC_SCM_ERROR_STATUS);
+
+	err = mxc_scc_put_data(ctx, ablkreq);
+	if (err) {
+		mxc_scc_ablkcipher_req_complete(req, ctx, err);
+		return;
+	}
+
+	dev_dbg(scc->dev, "Start encryption (0x%p/0x%p)\n",
+		(void *)readl(scc->base + SCC_SCM_RED_START),
+		(void *)readl(scc->base + SCC_SCM_BLACK_START));
+
+	/* clear interrupt control registers */
+	writel(SCC_SCM_INTR_CTRL_CLR_INTR,
+	       scc->base + SCC_SCM_INTR_CTRL);
+
+	writel((ctx->size / ctx->scc->block_size_bytes) - 1,
+	       scc->base + SCC_SCM_LENGTH);
+
+	dev_dbg(scc->dev, "Process %d block(s) in 0x%p\n",
+		ctx->size / ctx->scc->block_size_bytes,
+		(ctx->ctrl & SCC_SCM_CTRL_DECRYPT_MODE) ? scc->black_memory :
+		scc->red_memory);
+
+	writel(ctx->ctrl, scc->base + SCC_SCM_CTRL);
+}
+
+static irqreturn_t mxc_scc_int(int irq, void *priv)
+{
+	struct crypto_async_request *req;
+	struct mxc_scc_ctx *ctx;
+	struct mxc_scc *scc = priv;
+	int status;
+	int ret;
+
+	status = readl(scc->base + SCC_SCM_STATUS);
+
+	/* clear interrupt control registers */
+	writel(SCC_SCM_INTR_CTRL_CLR_INTR, scc->base + SCC_SCM_INTR_CTRL);
+
+	if (status & SCC_SCM_STATUS_BUSY)
+		return IRQ_NONE;
+
+	req = scc->req;
+	if (req) {
+		ctx = crypto_tfm_ctx(req->tfm);
+		ret = mxc_scc_get_data(ctx, req);
+		if (ret != -EINPROGRESS)
+			mxc_scc_ablkcipher_req_complete(req, ctx, ret);
+		else
+			mxc_scc_ablkcipher_next(ctx, req);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int mxc_scc_cra_init(struct crypto_tfm *tfm)
+{
+	struct mxc_scc_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct crypto_alg *alg = tfm->__crt_alg;
+	struct mxc_scc_crypto_tmpl *algt;
+
+	algt = container_of(alg, struct mxc_scc_crypto_tmpl, alg);
+
+	ctx->scc = algt->scc;
+	return 0;
+}
+
+static void mxc_scc_dequeue_req_unlocked(struct mxc_scc_ctx *ctx)
+{
+	struct crypto_async_request *req, *backlog;
+
+	if (ctx->scc->hw_busy)
+		return;
+
+	spin_lock_bh(&ctx->scc->lock);
+	backlog = crypto_get_backlog(&ctx->scc->queue);
+	req = crypto_dequeue_request(&ctx->scc->queue);
+	ctx->scc->req = req;
+	ctx->scc->hw_busy = true;
+	spin_unlock_bh(&ctx->scc->lock);
+
+	if (!req)
+		return;
+
+	if (backlog)
+		backlog->complete(backlog, -EINPROGRESS);
+
+	mxc_scc_ablkcipher_next(ctx, req);
+}
+
+static int mxc_scc_queue_req(struct mxc_scc_ctx *ctx,
+			     struct crypto_async_request *req)
+{
+	int ret;
+
+	spin_lock_bh(&ctx->scc->lock);
+	ret = crypto_enqueue_request(&ctx->scc->queue, req);
+	spin_unlock_bh(&ctx->scc->lock);
+
+	if (ret != -EINPROGRESS)
+		return ret;
+
+	mxc_scc_dequeue_req_unlocked(ctx);
+
+	return -EINPROGRESS;
+}
+
+static int mxc_scc_des3_op(struct mxc_scc_ctx *ctx,
+			   struct ablkcipher_request *req)
+{
+	int err;
+
+	err = mxc_scc_ablkcipher_req_init(req, ctx);
+	if (err)
+		return err;
+
+	return mxc_scc_queue_req(ctx, &req->base);
+}
+
+static int mxc_scc_ecb_des_encrypt(struct ablkcipher_request *req)
+{
+	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(req);
+	struct mxc_scc_ctx *ctx = crypto_ablkcipher_ctx(cipher);
+
+	ctx->ctrl = SCC_SCM_CTRL_START_CIPHER;
+
+	return mxc_scc_des3_op(ctx, req);
+}
+
+static int mxc_scc_ecb_des_decrypt(struct ablkcipher_request *req)
+{
+	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(req);
+	struct mxc_scc_ctx *ctx = crypto_ablkcipher_ctx(cipher);
+
+	ctx->ctrl = SCC_SCM_CTRL_START_CIPHER;
+	ctx->ctrl |= SCC_SCM_CTRL_DECRYPT_MODE;
+
+	return mxc_scc_des3_op(ctx, req);
+}
+
+static int mxc_scc_cbc_des_encrypt(struct ablkcipher_request *req)
+{
+	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(req);
+	struct mxc_scc_ctx *ctx = crypto_ablkcipher_ctx(cipher);
+
+	ctx->ctrl = SCC_SCM_CTRL_START_CIPHER;
+	ctx->ctrl |= SCC_SCM_CTRL_CBC_MODE;
+
+	return mxc_scc_des3_op(ctx, req);
+}
+
+static int mxc_scc_cbc_des_decrypt(struct ablkcipher_request *req)
+{
+	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(req);
+	struct mxc_scc_ctx *ctx = crypto_ablkcipher_ctx(cipher);
+
+	ctx->ctrl = SCC_SCM_CTRL_START_CIPHER;
+	ctx->ctrl |= SCC_SCM_CTRL_CBC_MODE;
+	ctx->ctrl |= SCC_SCM_CTRL_DECRYPT_MODE;
+
+	return mxc_scc_des3_op(ctx, req);
+}
+
+static void mxc_scc_hw_init(struct mxc_scc *scc)
+{
+	int offset;
+
+	offset = SCC_NON_RESERVED_OFFSET / scc->block_size_bytes;
+
+	/* Fill the RED_START register */
+	writel(offset, scc->base + SCC_SCM_RED_START);
+
+	/* Fill the BLACK_START register */
+	writel(offset, scc->base + SCC_SCM_BLACK_START);
+
+	scc->red_memory = scc->base + SCC_SCM_RED_MEMORY +
+			  SCC_NON_RESERVED_OFFSET;
+
+	scc->black_memory = scc->base + SCC_SCM_BLACK_MEMORY +
+			    SCC_NON_RESERVED_OFFSET;
+
+	scc->bytes_remaining = scc->memory_size_bytes;
+}
+
+static int mxc_scc_get_config(struct mxc_scc *scc)
+{
+	int config;
+
+	config = readl(scc->base + SCC_SCM_CFG);
+
+	scc->block_size_bytes = config & SCC_SCM_CFG_BLOCK_SIZE_MASK;
+
+	scc->black_ram_size_blocks = config & SCC_SCM_CFG_BLACK_SIZE_MASK;
+
+	scc->memory_size_bytes = (scc->block_size_bytes *
+				  scc->black_ram_size_blocks) -
+				  SCC_NON_RESERVED_OFFSET;
+
+	return 0;
+}
+
+static enum mxc_scc_state mxc_scc_get_state(struct mxc_scc *scc)
+{
+	enum mxc_scc_state state;
+	int status;
+
+	status = readl(scc->base + SCC_SMN_STATUS) &
+		       SCC_SMN_STATUS_STATE_MASK;
+
+	/* If in Health Check, try to bringup to secure state */
+	if (status & SCC_SMN_STATE_HEALTH_CHECK) {
+		/*
+		 * Write a simple algorithm to the Algorithm Sequence
+		 * Checker (ASC)
+		 */
+		writel(0xaaaa, scc->base + SCC_SMN_SEQ_START);
+		writel(0x5555, scc->base + SCC_SMN_SEQ_END);
+		writel(0x5555, scc->base + SCC_SMN_SEQ_CHECK);
+
+		status = readl(scc->base + SCC_SMN_STATUS) &
+			       SCC_SMN_STATUS_STATE_MASK;
+	}
+
+	switch (status) {
+	case SCC_SMN_STATE_NON_SECURE:
+	case SCC_SMN_STATE_SECURE:
+		state = SCC_STATE_OK;
+		break;
+	case SCC_SMN_STATE_FAIL:
+		state = SCC_STATE_FAILED;
+		break;
+	default:
+		state = SCC_STATE_UNIMPLEMENTED;
+		break;
+	}
+
+	return state;
+}
+
+static struct mxc_scc_crypto_tmpl scc_ecb_des = {
+	.alg = {
+		.cra_name = "ecb(des3_ede)",
+		.cra_driver_name = "ecb-des3-scc",
+		.cra_priority = 300,
+		.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER,
+		.cra_blocksize = DES3_EDE_BLOCK_SIZE,
+		.cra_ctxsize = sizeof(struct mxc_scc_ctx),
+		.cra_alignmask = 0,
+		.cra_type = &crypto_ablkcipher_type,
+		.cra_module = THIS_MODULE,
+		.cra_init = mxc_scc_cra_init,
+		.cra_u.ablkcipher = {
+			.min_keysize = DES3_EDE_KEY_SIZE,
+			.max_keysize = DES3_EDE_KEY_SIZE,
+			.encrypt = mxc_scc_ecb_des_encrypt,
+			.decrypt = mxc_scc_ecb_des_decrypt,
+		}
+	}
+};
+
+static struct mxc_scc_crypto_tmpl scc_cbc_des = {
+	.alg = {
+		.cra_name = "cbc(des3_ede)",
+		.cra_driver_name = "cbc-des3-scc",
+		.cra_priority = 300,
+		.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER,
+		.cra_blocksize = DES3_EDE_BLOCK_SIZE,
+		.cra_ctxsize = sizeof(struct mxc_scc_ctx),
+		.cra_alignmask = 0,
+		.cra_type = &crypto_ablkcipher_type,
+		.cra_module = THIS_MODULE,
+		.cra_init = mxc_scc_cra_init,
+		.cra_u.ablkcipher = {
+			.min_keysize = DES3_EDE_KEY_SIZE,
+			.max_keysize = DES3_EDE_KEY_SIZE,
+			.encrypt = mxc_scc_cbc_des_encrypt,
+			.decrypt = mxc_scc_cbc_des_decrypt,
+		}
+	}
+};
+
+static struct mxc_scc_crypto_tmpl *scc_crypto_algs[] = {
+	&scc_ecb_des,
+	&scc_cbc_des,
+};
+
+static int mxc_scc_crypto_register(struct mxc_scc *scc)
+{
+	int i;
+	int err = 0;
+
+	for (i = 0; i < ARRAY_SIZE(scc_crypto_algs); i++) {
+		scc_crypto_algs[i]->scc = scc;
+		err = crypto_register_alg(&scc_crypto_algs[i]->alg);
+		if (err)
+			goto err_out;
+	}
+
+	return 0;
+
+err_out:
+	while (--i >= 0)
+		crypto_unregister_alg(&scc_crypto_algs[i]->alg);
+
+	return err;
+}
+
+static void mxc_scc_crypto_unregister(void)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(scc_crypto_algs); i++)
+		crypto_unregister_alg(&scc_crypto_algs[i]->alg);
+}
+
+static int mxc_scc_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct mxc_scc *scc;
+	enum mxc_scc_state state;
+	int irq;
+	int ret;
+	int i;
+
+	scc = devm_kzalloc(dev, sizeof(*scc), GFP_KERNEL);
+	if (!scc)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	scc->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(scc->base))
+		return PTR_ERR(scc->base);
+
+	scc->clk = devm_clk_get(&pdev->dev, "ipg");
+	if (IS_ERR(scc->clk)) {
+		dev_err(dev, "Could not get ipg clock\n");
+		return PTR_ERR(scc->clk);
+	}
+
+	clk_prepare_enable(scc->clk);
+
+	/* clear error status register */
+	writel(0x0, scc->base + SCC_SCM_ERROR_STATUS);
+
+	/* clear interrupt control registers */
+	writel(SCC_SCM_INTR_CTRL_CLR_INTR |
+	       SCC_SCM_INTR_CTRL_MASK_INTR,
+	       scc->base + SCC_SCM_INTR_CTRL);
+
+	writel(SCC_SMN_COMMAND_CLR_INTR |
+	       SCC_SMN_COMMAND_EN_INTR,
+	       scc->base + SCC_SMN_COMMAND);
+
+	scc->dev = dev;
+	platform_set_drvdata(pdev, scc);
+
+	ret = mxc_scc_get_config(scc);
+	if (ret)
+		goto err_out;
+
+	state = mxc_scc_get_state(scc);
+
+	if (state != SCC_STATE_OK) {
+		dev_err(dev, "SCC in unusable state %d\n", state);
+		ret = -EINVAL;
+		goto err_out;
+	}
+
+	mxc_scc_hw_init(scc);
+
+	spin_lock_init(&scc->lock);
+	/* FIXME: calculate queue from RAM slots */
+	crypto_init_queue(&scc->queue, 50);
+
+	for (i = 0; i < 2; i++) {
+		irq = platform_get_irq(pdev, i);
+		if (irq < 0) {
+			dev_err(dev, "failed to get irq resource\n");
+			ret = -EINVAL;
+			goto err_out;
+		}
+
+		ret = devm_request_threaded_irq(dev, irq, NULL, mxc_scc_int,
+						IRQF_ONESHOT, dev_name(dev), scc);
+		if (ret)
+			goto err_out;
+	}
+
+	ret = mxc_scc_crypto_register(scc);
+	if (ret) {
+		dev_err(dev, "could not register algorithms");
+		goto err_out;
+	}
+
+	dev_info(dev, "registered successfully.\n");
+
+	return 0;
+
+err_out:
+	clk_disable_unprepare(scc->clk);
+
+	return ret;
+}
+
+static int mxc_scc_remove(struct platform_device *pdev)
+{
+	struct mxc_scc *scc = platform_get_drvdata(pdev);
+
+	mxc_scc_crypto_unregister();
+
+	clk_disable_unprepare(scc->clk);
+
+	return 0;
+}
+
+static const struct of_device_id mxc_scc_dt_ids[] = {
+	{ .compatible = "fsl,imx25-scc", .data = NULL, },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mxc_scc_dt_ids);
+
+static struct platform_driver mxc_scc_driver = {
+	.probe	= mxc_scc_probe,
+	.remove	= mxc_scc_remove,
+	.driver	= {
+		.name		= "mxc-scc",
+		.of_match_table	= mxc_scc_dt_ids,
+	},
+};
+
+module_platform_driver(mxc_scc_driver);
+MODULE_AUTHOR("Steffen Trumtrar <kernel@pengutronix.de>");
+MODULE_DESCRIPTION("Freescale i.MX25 SCC Crypto driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/n2_core.c linux-libre-4.7-gnu/drivers/crypto/n2_core.c
--- linux-libre-4.6-gnu/drivers/crypto/n2_core.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/n2_core.c	2016-07-24 15:23:50.000000000 -0400
@@ -1598,7 +1598,7 @@ static void *new_queue(unsigned long q_t
 
 static void free_queue(void *p, unsigned long q_type)
 {
-	return kmem_cache_free(queue_cache[q_type - 1], p);
+	kmem_cache_free(queue_cache[q_type - 1], p);
 }
 
 static int queue_cache_init(void)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/omap-aes.c linux-libre-4.7-gnu/drivers/crypto/omap-aes.c
--- linux-libre-4.6-gnu/drivers/crypto/omap-aes.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/omap-aes.c	2016-07-24 15:23:50.000000000 -0400
@@ -26,7 +26,6 @@
 #include <linux/scatterlist.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
-#include <linux/omap-dma.h>
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
@@ -176,9 +175,7 @@ struct omap_aes_dev {
 
 	struct scatter_walk		in_walk;
 	struct scatter_walk		out_walk;
-	int			dma_in;
 	struct dma_chan		*dma_lch_in;
-	int			dma_out;
 	struct dma_chan		*dma_lch_out;
 	int			in_sg_len;
 	int			out_sg_len;
@@ -351,30 +348,21 @@ static void omap_aes_dma_out_callback(vo
 
 static int omap_aes_dma_init(struct omap_aes_dev *dd)
 {
-	int err = -ENOMEM;
-	dma_cap_mask_t mask;
+	int err;
 
 	dd->dma_lch_out = NULL;
 	dd->dma_lch_in = NULL;
 
-	dma_cap_zero(mask);
-	dma_cap_set(DMA_SLAVE, mask);
-
-	dd->dma_lch_in = dma_request_slave_channel_compat(mask,
-							  omap_dma_filter_fn,
-							  &dd->dma_in,
-							  dd->dev, "rx");
-	if (!dd->dma_lch_in) {
+	dd->dma_lch_in = dma_request_chan(dd->dev, "rx");
+	if (IS_ERR(dd->dma_lch_in)) {
 		dev_err(dd->dev, "Unable to request in DMA channel\n");
-		goto err_dma_in;
+		return PTR_ERR(dd->dma_lch_in);
 	}
 
-	dd->dma_lch_out = dma_request_slave_channel_compat(mask,
-							   omap_dma_filter_fn,
-							   &dd->dma_out,
-							   dd->dev, "tx");
-	if (!dd->dma_lch_out) {
+	dd->dma_lch_out = dma_request_chan(dd->dev, "tx");
+	if (IS_ERR(dd->dma_lch_out)) {
 		dev_err(dd->dev, "Unable to request out DMA channel\n");
+		err = PTR_ERR(dd->dma_lch_out);
 		goto err_dma_out;
 	}
 
@@ -382,14 +370,15 @@ static int omap_aes_dma_init(struct omap
 
 err_dma_out:
 	dma_release_channel(dd->dma_lch_in);
-err_dma_in:
-	if (err)
-		pr_err("error: %d\n", err);
+
 	return err;
 }
 
 static void omap_aes_dma_cleanup(struct omap_aes_dev *dd)
 {
+	if (dd->pio_only)
+		return;
+
 	dma_release_channel(dd->dma_lch_out);
 	dma_release_channel(dd->dma_lch_in);
 }
@@ -1080,9 +1069,6 @@ static int omap_aes_get_res_of(struct om
 		goto err;
 	}
 
-	dd->dma_out = -1; /* Dummy value that's unused */
-	dd->dma_in = -1; /* Dummy value that's unused */
-
 	dd->pdata = match->data;
 
 err:
@@ -1116,24 +1102,6 @@ static int omap_aes_get_res_pdev(struct
 	}
 	memcpy(res, r, sizeof(*res));
 
-	/* Get the DMA out channel */
-	r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-	if (!r) {
-		dev_err(dev, "no DMA out resource info\n");
-		err = -ENODEV;
-		goto err;
-	}
-	dd->dma_out = r->start;
-
-	/* Get the DMA in channel */
-	r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
-	if (!r) {
-		dev_err(dev, "no DMA in resource info\n");
-		err = -ENODEV;
-		goto err;
-	}
-	dd->dma_in = r->start;
-
 	/* Only OMAP2/3 can be non-DT */
 	dd->pdata = &omap_aes_pdata_omap2;
 
@@ -1191,7 +1159,9 @@ static int omap_aes_probe(struct platfor
 	tasklet_init(&dd->done_task, omap_aes_done_task, (unsigned long)dd);
 
 	err = omap_aes_dma_init(dd);
-	if (err && AES_REG_IRQ_STATUS(dd) && AES_REG_IRQ_ENABLE(dd)) {
+	if (err == -EPROBE_DEFER) {
+		goto err_irq;
+	} else if (err && AES_REG_IRQ_STATUS(dd) && AES_REG_IRQ_ENABLE(dd)) {
 		dd->pio_only = 1;
 
 		irq = platform_get_irq(pdev, 0);
@@ -1248,8 +1218,8 @@ err_algs:
 		for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--)
 			crypto_unregister_alg(
 					&dd->pdata->algs_info[i].algs_list[j]);
-	if (!dd->pio_only)
-		omap_aes_dma_cleanup(dd);
+
+	omap_aes_dma_cleanup(dd);
 err_irq:
 	tasklet_kill(&dd->done_task);
 	pm_runtime_disable(dev);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/omap-des.c linux-libre-4.7-gnu/drivers/crypto/omap-des.c
--- linux-libre-4.6-gnu/drivers/crypto/omap-des.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/omap-des.c	2016-07-24 15:23:50.000000000 -0400
@@ -29,7 +29,6 @@
 #include <linux/scatterlist.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
-#include <linux/omap-dma.h>
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
@@ -39,6 +38,7 @@
 #include <linux/interrupt.h>
 #include <crypto/scatterwalk.h>
 #include <crypto/des.h>
+#include <crypto/algapi.h>
 
 #define DST_MAXBURST			2
 
@@ -132,14 +132,10 @@ struct omap_des_dev {
 	unsigned long		flags;
 	int			err;
 
-	/* spinlock used for queues */
-	spinlock_t		lock;
-	struct crypto_queue	queue;
-
 	struct tasklet_struct	done_task;
-	struct tasklet_struct	queue_task;
 
 	struct ablkcipher_request	*req;
+	struct crypto_engine		*engine;
 	/*
 	 * total is used by PIO mode for book keeping so introduce
 	 * variable total_save as need it to calc page_order
@@ -158,9 +154,7 @@ struct omap_des_dev {
 
 	struct scatter_walk		in_walk;
 	struct scatter_walk		out_walk;
-	int			dma_in;
 	struct dma_chan		*dma_lch_in;
-	int			dma_out;
 	struct dma_chan		*dma_lch_out;
 	int			in_sg_len;
 	int			out_sg_len;
@@ -340,30 +334,21 @@ static void omap_des_dma_out_callback(vo
 
 static int omap_des_dma_init(struct omap_des_dev *dd)
 {
-	int err = -ENOMEM;
-	dma_cap_mask_t mask;
+	int err;
 
 	dd->dma_lch_out = NULL;
 	dd->dma_lch_in = NULL;
 
-	dma_cap_zero(mask);
-	dma_cap_set(DMA_SLAVE, mask);
-
-	dd->dma_lch_in = dma_request_slave_channel_compat(mask,
-							  omap_dma_filter_fn,
-							  &dd->dma_in,
-							  dd->dev, "rx");
-	if (!dd->dma_lch_in) {
+	dd->dma_lch_in = dma_request_chan(dd->dev, "rx");
+	if (IS_ERR(dd->dma_lch_in)) {
 		dev_err(dd->dev, "Unable to request in DMA channel\n");
-		goto err_dma_in;
+		return PTR_ERR(dd->dma_lch_in);
 	}
 
-	dd->dma_lch_out = dma_request_slave_channel_compat(mask,
-							   omap_dma_filter_fn,
-							   &dd->dma_out,
-							   dd->dev, "tx");
-	if (!dd->dma_lch_out) {
+	dd->dma_lch_out = dma_request_chan(dd->dev, "tx");
+	if (IS_ERR(dd->dma_lch_out)) {
 		dev_err(dd->dev, "Unable to request out DMA channel\n");
+		err = PTR_ERR(dd->dma_lch_out);
 		goto err_dma_out;
 	}
 
@@ -371,14 +356,15 @@ static int omap_des_dma_init(struct omap
 
 err_dma_out:
 	dma_release_channel(dd->dma_lch_in);
-err_dma_in:
-	if (err)
-		pr_err("error: %d\n", err);
+
 	return err;
 }
 
 static void omap_des_dma_cleanup(struct omap_des_dev *dd)
 {
+	if (dd->pio_only)
+		return;
+
 	dma_release_channel(dd->dma_lch_out);
 	dma_release_channel(dd->dma_lch_in);
 }
@@ -520,9 +506,7 @@ static void omap_des_finish_req(struct o
 	pr_debug("err: %d\n", err);
 
 	pm_runtime_put(dd->dev);
-	dd->flags &= ~FLAGS_BUSY;
-
-	req->base.complete(&req->base, err);
+	crypto_finalize_request(dd->engine, req, err);
 }
 
 static int omap_des_crypt_dma_stop(struct omap_des_dev *dd)
@@ -585,34 +569,24 @@ static int omap_des_copy_sgs(struct omap
 }
 
 static int omap_des_handle_queue(struct omap_des_dev *dd,
-			       struct ablkcipher_request *req)
+				 struct ablkcipher_request *req)
 {
-	struct crypto_async_request *async_req, *backlog;
-	struct omap_des_ctx *ctx;
-	struct omap_des_reqctx *rctx;
-	unsigned long flags;
-	int err, ret = 0;
-
-	spin_lock_irqsave(&dd->lock, flags);
 	if (req)
-		ret = ablkcipher_enqueue_request(&dd->queue, req);
-	if (dd->flags & FLAGS_BUSY) {
-		spin_unlock_irqrestore(&dd->lock, flags);
-		return ret;
-	}
-	backlog = crypto_get_backlog(&dd->queue);
-	async_req = crypto_dequeue_request(&dd->queue);
-	if (async_req)
-		dd->flags |= FLAGS_BUSY;
-	spin_unlock_irqrestore(&dd->lock, flags);
+		return crypto_transfer_request_to_engine(dd->engine, req);
 
-	if (!async_req)
-		return ret;
+	return 0;
+}
 
-	if (backlog)
-		backlog->complete(backlog, -EINPROGRESS);
+static int omap_des_prepare_req(struct crypto_engine *engine,
+				struct ablkcipher_request *req)
+{
+	struct omap_des_ctx *ctx = crypto_ablkcipher_ctx(
+			crypto_ablkcipher_reqtfm(req));
+	struct omap_des_dev *dd = omap_des_find_dev(ctx);
+	struct omap_des_reqctx *rctx;
 
-	req = ablkcipher_request_cast(async_req);
+	if (!dd)
+		return -ENODEV;
 
 	/* assign new request to device */
 	dd->req = req;
@@ -642,16 +616,20 @@ static int omap_des_handle_queue(struct
 	dd->ctx = ctx;
 	ctx->dd = dd;
 
-	err = omap_des_write_ctrl(dd);
-	if (!err)
-		err = omap_des_crypt_dma_start(dd);
-	if (err) {
-		/* des_task will not finish it, so do it here */
-		omap_des_finish_req(dd, err);
-		tasklet_schedule(&dd->queue_task);
-	}
+	return omap_des_write_ctrl(dd);
+}
 
-	return ret; /* return ret, which is enqueue return value */
+static int omap_des_crypt_req(struct crypto_engine *engine,
+			      struct ablkcipher_request *req)
+{
+	struct omap_des_ctx *ctx = crypto_ablkcipher_ctx(
+			crypto_ablkcipher_reqtfm(req));
+	struct omap_des_dev *dd = omap_des_find_dev(ctx);
+
+	if (!dd)
+		return -ENODEV;
+
+	return omap_des_crypt_dma_start(dd);
 }
 
 static void omap_des_done_task(unsigned long data)
@@ -683,18 +661,10 @@ static void omap_des_done_task(unsigned
 	}
 
 	omap_des_finish_req(dd, 0);
-	omap_des_handle_queue(dd, NULL);
 
 	pr_debug("exit\n");
 }
 
-static void omap_des_queue_task(unsigned long data)
-{
-	struct omap_des_dev *dd = (struct omap_des_dev *)data;
-
-	omap_des_handle_queue(dd, NULL);
-}
-
 static int omap_des_crypt(struct ablkcipher_request *req, unsigned long mode)
 {
 	struct omap_des_ctx *ctx = crypto_ablkcipher_ctx(
@@ -999,8 +969,6 @@ static int omap_des_get_of(struct omap_d
 		return -EINVAL;
 	}
 
-	dd->dma_out = -1; /* Dummy value that's unused */
-	dd->dma_in = -1; /* Dummy value that's unused */
 	dd->pdata = match->data;
 
 	return 0;
@@ -1016,33 +984,10 @@ static int omap_des_get_of(struct omap_d
 static int omap_des_get_pdev(struct omap_des_dev *dd,
 		struct platform_device *pdev)
 {
-	struct device *dev = &pdev->dev;
-	struct resource *r;
-	int err = 0;
-
-	/* Get the DMA out channel */
-	r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-	if (!r) {
-		dev_err(dev, "no DMA out resource info\n");
-		err = -ENODEV;
-		goto err;
-	}
-	dd->dma_out = r->start;
-
-	/* Get the DMA in channel */
-	r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
-	if (!r) {
-		dev_err(dev, "no DMA in resource info\n");
-		err = -ENODEV;
-		goto err;
-	}
-	dd->dma_in = r->start;
-
 	/* non-DT devices get pdata from pdev */
 	dd->pdata = pdev->dev.platform_data;
 
-err:
-	return err;
+	return 0;
 }
 
 static int omap_des_probe(struct platform_device *pdev)
@@ -1062,9 +1007,6 @@ static int omap_des_probe(struct platfor
 	dd->dev = dev;
 	platform_set_drvdata(pdev, dd);
 
-	spin_lock_init(&dd->lock);
-	crypto_init_queue(&dd->queue, OMAP_DES_QUEUE_LENGTH);
-
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
 		dev_err(dev, "no MEM resource info\n");
@@ -1103,10 +1045,11 @@ static int omap_des_probe(struct platfor
 		 (reg & dd->pdata->minor_mask) >> dd->pdata->minor_shift);
 
 	tasklet_init(&dd->done_task, omap_des_done_task, (unsigned long)dd);
-	tasklet_init(&dd->queue_task, omap_des_queue_task, (unsigned long)dd);
 
 	err = omap_des_dma_init(dd);
-	if (err && DES_REG_IRQ_STATUS(dd) && DES_REG_IRQ_ENABLE(dd)) {
+	if (err == -EPROBE_DEFER) {
+		goto err_irq;
+	} else if (err && DES_REG_IRQ_STATUS(dd) && DES_REG_IRQ_ENABLE(dd)) {
 		dd->pio_only = 1;
 
 		irq = platform_get_irq(pdev, 0);
@@ -1144,17 +1087,30 @@ static int omap_des_probe(struct platfor
 		}
 	}
 
+	/* Initialize des crypto engine */
+	dd->engine = crypto_engine_alloc_init(dev, 1);
+	if (!dd->engine)
+		goto err_algs;
+
+	dd->engine->prepare_request = omap_des_prepare_req;
+	dd->engine->crypt_one_request = omap_des_crypt_req;
+	err = crypto_engine_start(dd->engine);
+	if (err)
+		goto err_engine;
+
 	return 0;
+
+err_engine:
+	crypto_engine_exit(dd->engine);
 err_algs:
 	for (i = dd->pdata->algs_info_size - 1; i >= 0; i--)
 		for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--)
 			crypto_unregister_alg(
 					&dd->pdata->algs_info[i].algs_list[j]);
-	if (!dd->pio_only)
-		omap_des_dma_cleanup(dd);
+
+	omap_des_dma_cleanup(dd);
 err_irq:
 	tasklet_kill(&dd->done_task);
-	tasklet_kill(&dd->queue_task);
 err_get:
 	pm_runtime_disable(dev);
 err_res:
@@ -1182,7 +1138,6 @@ static int omap_des_remove(struct platfo
 					&dd->pdata->algs_info[i].algs_list[j]);
 
 	tasklet_kill(&dd->done_task);
-	tasklet_kill(&dd->queue_task);
 	omap_des_dma_cleanup(dd);
 	pm_runtime_disable(dd->dev);
 	dd = NULL;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/omap-sham.c linux-libre-4.7-gnu/drivers/crypto/omap-sham.c
--- linux-libre-4.6-gnu/drivers/crypto/omap-sham.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/omap-sham.c	2016-07-24 15:23:50.000000000 -0400
@@ -29,7 +29,6 @@
 #include <linux/scatterlist.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
-#include <linux/omap-dma.h>
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
@@ -219,7 +218,6 @@ struct omap_sham_dev {
 	int			irq;
 	spinlock_t		lock;
 	int			err;
-	unsigned int		dma;
 	struct dma_chan		*dma_lch;
 	struct tasklet_struct	done_task;
 	u8			polling_mode;
@@ -1842,7 +1840,6 @@ static int omap_sham_get_res_of(struct o
 		goto err;
 	}
 
-	dd->dma = -1; /* Dummy value that's unused */
 	dd->pdata = match->data;
 
 err:
@@ -1884,15 +1881,6 @@ static int omap_sham_get_res_pdev(struct
 		goto err;
 	}
 
-	/* Get the DMA */
-	r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-	if (!r) {
-		dev_err(dev, "no DMA resource info\n");
-		err = -ENODEV;
-		goto err;
-	}
-	dd->dma = r->start;
-
 	/* Only OMAP2/3 can be non-DT */
 	dd->pdata = &omap_sham_pdata_omap2;
 
@@ -1946,9 +1934,12 @@ static int omap_sham_probe(struct platfo
 	dma_cap_zero(mask);
 	dma_cap_set(DMA_SLAVE, mask);
 
-	dd->dma_lch = dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
-						       &dd->dma, dev, "rx");
-	if (!dd->dma_lch) {
+	dd->dma_lch = dma_request_chan(dev, "rx");
+	if (IS_ERR(dd->dma_lch)) {
+		err = PTR_ERR(dd->dma_lch);
+		if (err == -EPROBE_DEFER)
+			goto data_err;
+
 		dd->polling_mode = 1;
 		dev_dbg(dev, "using polling mode instead of dma\n");
 	}
@@ -1995,7 +1986,7 @@ err_algs:
 					&dd->pdata->algs_info[i].algs_list[j]);
 err_pm:
 	pm_runtime_disable(dev);
-	if (dd->dma_lch)
+	if (!dd->polling_mode)
 		dma_release_channel(dd->dma_lch);
 data_err:
 	dev_err(dev, "initialization failed.\n");
@@ -2021,7 +2012,7 @@ static int omap_sham_remove(struct platf
 	tasklet_kill(&dd->done_task);
 	pm_runtime_disable(&pdev->dev);
 
-	if (dd->dma_lch)
+	if (!dd->polling_mode)
 		dma_release_channel(dd->dma_lch);
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/qat/qat_c3xxx/adf_drv.c linux-libre-4.7-gnu/drivers/crypto/qat/qat_c3xxx/adf_drv.c
--- linux-libre-4.6-gnu/drivers/crypto/qat/qat_c3xxx/adf_drv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/qat/qat_c3xxx/adf_drv.c	2016-07-24 15:23:50.000000000 -0400
@@ -300,9 +300,7 @@ static void adf_remove(struct pci_dev *p
 		pr_err("QAT: Driver removal failed\n");
 		return;
 	}
-	if (adf_dev_stop(accel_dev))
-		dev_err(&GET_DEV(accel_dev), "Failed to stop QAT accel dev\n");
-
+	adf_dev_stop(accel_dev);
 	adf_dev_shutdown(accel_dev);
 	adf_disable_aer(accel_dev);
 	adf_cleanup_accel(accel_dev);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/qat/qat_c3xxxvf/adf_c3xxxvf_hw_data.c linux-libre-4.7-gnu/drivers/crypto/qat/qat_c3xxxvf/adf_c3xxxvf_hw_data.c
--- linux-libre-4.6-gnu/drivers/crypto/qat/qat_c3xxxvf/adf_c3xxxvf_hw_data.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/qat/qat_c3xxxvf/adf_c3xxxvf_hw_data.c	2016-07-24 15:23:50.000000000 -0400
@@ -109,29 +109,6 @@ static void adf_vf_void_noop(struct adf_
 {
 }
 
-static int adf_vf2pf_init(struct adf_accel_dev *accel_dev)
-{
-	u32 msg = (ADF_VF2PF_MSGORIGIN_SYSTEM |
-		(ADF_VF2PF_MSGTYPE_INIT << ADF_VF2PF_MSGTYPE_SHIFT));
-
-	if (adf_iov_putmsg(accel_dev, msg, 0)) {
-		dev_err(&GET_DEV(accel_dev),
-			"Failed to send Init event to PF\n");
-		return -EFAULT;
-	}
-	return 0;
-}
-
-static void adf_vf2pf_shutdown(struct adf_accel_dev *accel_dev)
-{
-	u32 msg = (ADF_VF2PF_MSGORIGIN_SYSTEM |
-	    (ADF_VF2PF_MSGTYPE_SHUTDOWN << ADF_VF2PF_MSGTYPE_SHIFT));
-
-	if (adf_iov_putmsg(accel_dev, msg, 0))
-		dev_err(&GET_DEV(accel_dev),
-			"Failed to send Shutdown event to PF\n");
-}
-
 void adf_init_hw_data_c3xxxiov(struct adf_hw_device_data *hw_data)
 {
 	hw_data->dev_class = &c3xxxiov_class;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/qat/qat_c3xxxvf/adf_drv.c linux-libre-4.7-gnu/drivers/crypto/qat/qat_c3xxxvf/adf_drv.c
--- linux-libre-4.6-gnu/drivers/crypto/qat/qat_c3xxxvf/adf_drv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/qat/qat_c3xxxvf/adf_drv.c	2016-07-24 15:23:50.000000000 -0400
@@ -238,6 +238,8 @@ static int adf_probe(struct pci_dev *pde
 	if (ret)
 		goto out_err_free_reg;
 
+	set_bit(ADF_STATUS_PF_RUNNING, &accel_dev->status);
+
 	ret = adf_dev_init(accel_dev);
 	if (ret)
 		goto out_err_dev_shutdown;
@@ -270,9 +272,7 @@ static void adf_remove(struct pci_dev *p
 		pr_err("QAT: Driver removal failed\n");
 		return;
 	}
-	if (adf_dev_stop(accel_dev))
-		dev_err(&GET_DEV(accel_dev), "Failed to stop QAT accel dev\n");
-
+	adf_dev_stop(accel_dev);
 	adf_dev_shutdown(accel_dev);
 	adf_cleanup_accel(accel_dev);
 	adf_cleanup_pci_dev(accel_dev);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/qat/qat_c62x/adf_drv.c linux-libre-4.7-gnu/drivers/crypto/qat/qat_c62x/adf_drv.c
--- linux-libre-4.6-gnu/drivers/crypto/qat/qat_c62x/adf_drv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/qat/qat_c62x/adf_drv.c	2016-07-24 15:23:50.000000000 -0400
@@ -300,9 +300,7 @@ static void adf_remove(struct pci_dev *p
 		pr_err("QAT: Driver removal failed\n");
 		return;
 	}
-	if (adf_dev_stop(accel_dev))
-		dev_err(&GET_DEV(accel_dev), "Failed to stop QAT accel dev\n");
-
+	adf_dev_stop(accel_dev);
 	adf_dev_shutdown(accel_dev);
 	adf_disable_aer(accel_dev);
 	adf_cleanup_accel(accel_dev);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/qat/qat_c62xvf/adf_c62xvf_hw_data.c linux-libre-4.7-gnu/drivers/crypto/qat/qat_c62xvf/adf_c62xvf_hw_data.c
--- linux-libre-4.6-gnu/drivers/crypto/qat/qat_c62xvf/adf_c62xvf_hw_data.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/qat/qat_c62xvf/adf_c62xvf_hw_data.c	2016-07-24 15:23:50.000000000 -0400
@@ -109,29 +109,6 @@ static void adf_vf_void_noop(struct adf_
 {
 }
 
-static int adf_vf2pf_init(struct adf_accel_dev *accel_dev)
-{
-	u32 msg = (ADF_VF2PF_MSGORIGIN_SYSTEM |
-		(ADF_VF2PF_MSGTYPE_INIT << ADF_VF2PF_MSGTYPE_SHIFT));
-
-	if (adf_iov_putmsg(accel_dev, msg, 0)) {
-		dev_err(&GET_DEV(accel_dev),
-			"Failed to send Init event to PF\n");
-		return -EFAULT;
-	}
-	return 0;
-}
-
-static void adf_vf2pf_shutdown(struct adf_accel_dev *accel_dev)
-{
-	u32 msg = (ADF_VF2PF_MSGORIGIN_SYSTEM |
-	    (ADF_VF2PF_MSGTYPE_SHUTDOWN << ADF_VF2PF_MSGTYPE_SHIFT));
-
-	if (adf_iov_putmsg(accel_dev, msg, 0))
-		dev_err(&GET_DEV(accel_dev),
-			"Failed to send Shutdown event to PF\n");
-}
-
 void adf_init_hw_data_c62xiov(struct adf_hw_device_data *hw_data)
 {
 	hw_data->dev_class = &c62xiov_class;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/qat/qat_c62xvf/adf_drv.c linux-libre-4.7-gnu/drivers/crypto/qat/qat_c62xvf/adf_drv.c
--- linux-libre-4.6-gnu/drivers/crypto/qat/qat_c62xvf/adf_drv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/qat/qat_c62xvf/adf_drv.c	2016-07-24 15:23:50.000000000 -0400
@@ -238,6 +238,8 @@ static int adf_probe(struct pci_dev *pde
 	if (ret)
 		goto out_err_free_reg;
 
+	set_bit(ADF_STATUS_PF_RUNNING, &accel_dev->status);
+
 	ret = adf_dev_init(accel_dev);
 	if (ret)
 		goto out_err_dev_shutdown;
@@ -270,9 +272,7 @@ static void adf_remove(struct pci_dev *p
 		pr_err("QAT: Driver removal failed\n");
 		return;
 	}
-	if (adf_dev_stop(accel_dev))
-		dev_err(&GET_DEV(accel_dev), "Failed to stop QAT accel dev\n");
-
+	adf_dev_stop(accel_dev);
 	adf_dev_shutdown(accel_dev);
 	adf_cleanup_accel(accel_dev);
 	adf_cleanup_pci_dev(accel_dev);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/qat/qat_common/adf_admin.c linux-libre-4.7-gnu/drivers/crypto/qat/qat_common/adf_admin.c
--- linux-libre-4.6-gnu/drivers/crypto/qat/qat_common/adf_admin.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/qat/qat_common/adf_admin.c	2016-07-24 15:23:50.000000000 -0400
@@ -61,7 +61,7 @@
 #define ADF_DH895XCC_MAILBOX_STRIDE 0x1000
 #define ADF_ADMINMSG_LEN 32
 
-static const u8 const_tab[1024] = {
+static const u8 const_tab[1024] __aligned(1024) = {
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/qat/qat_common/adf_cfg_strings.h linux-libre-4.7-gnu/drivers/crypto/qat/qat_common/adf_cfg_strings.h
--- linux-libre-4.6-gnu/drivers/crypto/qat/qat_common/adf_cfg_strings.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/qat/qat_common/adf_cfg_strings.h	2016-07-24 15:23:50.000000000 -0400
@@ -57,10 +57,8 @@
 #define ADF_RING_DC_SIZE "NumConcurrentRequests"
 #define ADF_RING_ASYM_TX "RingAsymTx"
 #define ADF_RING_SYM_TX "RingSymTx"
-#define ADF_RING_RND_TX "RingNrbgTx"
 #define ADF_RING_ASYM_RX "RingAsymRx"
 #define ADF_RING_SYM_RX "RingSymRx"
-#define ADF_RING_RND_RX "RingNrbgRx"
 #define ADF_RING_DC_TX "RingTx"
 #define ADF_RING_DC_RX "RingRx"
 #define ADF_ETRMGR_BANK "Bank"
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/qat/qat_common/adf_common_drv.h linux-libre-4.7-gnu/drivers/crypto/qat/qat_common/adf_common_drv.h
--- linux-libre-4.6-gnu/drivers/crypto/qat/qat_common/adf_common_drv.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/qat/qat_common/adf_common_drv.h	2016-07-24 15:23:50.000000000 -0400
@@ -67,7 +67,7 @@
 #define ADF_STATUS_AE_INITIALISED 4
 #define ADF_STATUS_AE_UCODE_LOADED 5
 #define ADF_STATUS_AE_STARTED 6
-#define ADF_STATUS_ORPHAN_TH_RUNNING 7
+#define ADF_STATUS_PF_RUNNING 7
 #define ADF_STATUS_IRQ_ALLOCATED 8
 
 enum adf_dev_reset_mode {
@@ -103,7 +103,7 @@ int adf_service_unregister(struct servic
 
 int adf_dev_init(struct adf_accel_dev *accel_dev);
 int adf_dev_start(struct adf_accel_dev *accel_dev);
-int adf_dev_stop(struct adf_accel_dev *accel_dev);
+void adf_dev_stop(struct adf_accel_dev *accel_dev);
 void adf_dev_shutdown(struct adf_accel_dev *accel_dev);
 
 int adf_iov_putmsg(struct adf_accel_dev *accel_dev, u32 msg, u8 vf_nr);
@@ -236,8 +236,13 @@ void adf_enable_vf2pf_interrupts(struct
 				 uint32_t vf_mask);
 void adf_enable_pf2vf_interrupts(struct adf_accel_dev *accel_dev);
 void adf_disable_pf2vf_interrupts(struct adf_accel_dev *accel_dev);
+
+int adf_vf2pf_init(struct adf_accel_dev *accel_dev);
+void adf_vf2pf_shutdown(struct adf_accel_dev *accel_dev);
 int adf_init_pf_wq(void);
 void adf_exit_pf_wq(void);
+int adf_init_vf_wq(void);
+void adf_exit_vf_wq(void);
 #else
 static inline int adf_sriov_configure(struct pci_dev *pdev, int numvfs)
 {
@@ -256,6 +261,15 @@ static inline void adf_disable_pf2vf_int
 {
 }
 
+static inline int adf_vf2pf_init(struct adf_accel_dev *accel_dev)
+{
+	return 0;
+}
+
+static inline void adf_vf2pf_shutdown(struct adf_accel_dev *accel_dev)
+{
+}
+
 static inline int adf_init_pf_wq(void)
 {
 	return 0;
@@ -264,5 +278,15 @@ static inline int adf_init_pf_wq(void)
 static inline void adf_exit_pf_wq(void)
 {
 }
+
+static inline int adf_init_vf_wq(void)
+{
+	return 0;
+}
+
+static inline void adf_exit_vf_wq(void)
+{
+}
+
 #endif
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/qat/qat_common/adf_ctl_drv.c linux-libre-4.7-gnu/drivers/crypto/qat/qat_common/adf_ctl_drv.c
--- linux-libre-4.6-gnu/drivers/crypto/qat/qat_common/adf_ctl_drv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/qat/qat_common/adf_ctl_drv.c	2016-07-24 15:23:50.000000000 -0400
@@ -270,26 +270,33 @@ static int adf_ctl_is_device_in_use(int
 	return 0;
 }
 
-static int adf_ctl_stop_devices(uint32_t id)
+static void adf_ctl_stop_devices(uint32_t id)
 {
 	struct adf_accel_dev *accel_dev;
-	int ret = 0;
 
-	list_for_each_entry_reverse(accel_dev, adf_devmgr_get_head(), list) {
+	list_for_each_entry(accel_dev, adf_devmgr_get_head(), list) {
 		if (id == accel_dev->accel_id || id == ADF_CFG_ALL_DEVICES) {
 			if (!adf_dev_started(accel_dev))
 				continue;
 
-			if (adf_dev_stop(accel_dev)) {
-				dev_err(&GET_DEV(accel_dev),
-					"Failed to stop qat_dev%d\n", id);
-				ret = -EFAULT;
-			} else {
-				adf_dev_shutdown(accel_dev);
-			}
+			/* First stop all VFs */
+			if (!accel_dev->is_vf)
+				continue;
+
+			adf_dev_stop(accel_dev);
+			adf_dev_shutdown(accel_dev);
+		}
+	}
+
+	list_for_each_entry(accel_dev, adf_devmgr_get_head(), list) {
+		if (id == accel_dev->accel_id || id == ADF_CFG_ALL_DEVICES) {
+			if (!adf_dev_started(accel_dev))
+				continue;
+
+			adf_dev_stop(accel_dev);
+			adf_dev_shutdown(accel_dev);
 		}
 	}
-	return ret;
 }
 
 static int adf_ctl_ioctl_dev_stop(struct file *fp, unsigned int cmd,
@@ -318,9 +325,8 @@ static int adf_ctl_ioctl_dev_stop(struct
 		pr_info("QAT: Stopping acceleration device qat_dev%d.\n",
 			ctl_data->device_id);
 
-	ret = adf_ctl_stop_devices(ctl_data->device_id);
-	if (ret)
-		pr_err("QAT: failed to stop device.\n");
+	adf_ctl_stop_devices(ctl_data->device_id);
+
 out:
 	kfree(ctl_data);
 	return ret;
@@ -465,12 +471,17 @@ static int __init adf_register_ctl_devic
 	if (adf_init_pf_wq())
 		goto err_pf_wq;
 
+	if (adf_init_vf_wq())
+		goto err_vf_wq;
+
 	if (qat_crypto_register())
 		goto err_crypto_register;
 
 	return 0;
 
 err_crypto_register:
+	adf_exit_vf_wq();
+err_vf_wq:
 	adf_exit_pf_wq();
 err_pf_wq:
 	adf_exit_aer();
@@ -485,6 +496,7 @@ static void __exit adf_unregister_ctl_de
 {
 	adf_chr_drv_destroy();
 	adf_exit_aer();
+	adf_exit_vf_wq();
 	adf_exit_pf_wq();
 	qat_crypto_unregister();
 	adf_clean_vf_map(false);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/qat/qat_common/adf_init.c linux-libre-4.7-gnu/drivers/crypto/qat/qat_common/adf_init.c
--- linux-libre-4.6-gnu/drivers/crypto/qat/qat_common/adf_init.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/qat/qat_common/adf_init.c	2016-07-24 15:23:50.000000000 -0400
@@ -236,9 +236,9 @@ EXPORT_SYMBOL_GPL(adf_dev_start);
  * is shuting down.
  * To be used by QAT device specific drivers.
  *
- * Return: 0 on success, error code otherwise.
+ * Return: void
  */
-int adf_dev_stop(struct adf_accel_dev *accel_dev)
+void adf_dev_stop(struct adf_accel_dev *accel_dev)
 {
 	struct service_hndl *service;
 	struct list_head *list_itr;
@@ -246,9 +246,9 @@ int adf_dev_stop(struct adf_accel_dev *a
 	int ret;
 
 	if (!adf_dev_started(accel_dev) &&
-	    !test_bit(ADF_STATUS_STARTING, &accel_dev->status)) {
-		return 0;
-	}
+	    !test_bit(ADF_STATUS_STARTING, &accel_dev->status))
+		return;
+
 	clear_bit(ADF_STATUS_STARTING, &accel_dev->status);
 	clear_bit(ADF_STATUS_STARTED, &accel_dev->status);
 
@@ -279,8 +279,6 @@ int adf_dev_stop(struct adf_accel_dev *a
 		else
 			clear_bit(ADF_STATUS_AE_STARTED, &accel_dev->status);
 	}
-
-	return 0;
 }
 EXPORT_SYMBOL_GPL(adf_dev_stop);
 
@@ -329,6 +327,8 @@ void adf_dev_shutdown(struct adf_accel_d
 			clear_bit(accel_dev->accel_id, &service->init_status);
 	}
 
+	hw_data->disable_iov(accel_dev);
+
 	if (test_bit(ADF_STATUS_IRQ_ALLOCATED, &accel_dev->status)) {
 		hw_data->free_irq(accel_dev);
 		clear_bit(ADF_STATUS_IRQ_ALLOCATED, &accel_dev->status);
@@ -344,7 +344,6 @@ void adf_dev_shutdown(struct adf_accel_d
 	if (hw_data->exit_admin_comms)
 		hw_data->exit_admin_comms(accel_dev);
 
-	hw_data->disable_iov(accel_dev);
 	adf_cleanup_etr_data(accel_dev);
 	adf_dev_restore(accel_dev);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/qat/qat_common/adf_isr.c linux-libre-4.7-gnu/drivers/crypto/qat/qat_common/adf_isr.c
--- linux-libre-4.6-gnu/drivers/crypto/qat/qat_common/adf_isr.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/qat/qat_common/adf_isr.c	2016-07-24 15:23:50.000000000 -0400
@@ -302,7 +302,7 @@ static void adf_cleanup_bh(struct adf_ac
 }
 
 /**
- * adf_vf_isr_resource_free() - Free IRQ for acceleration device
+ * adf_isr_resource_free() - Free IRQ for acceleration device
  * @accel_dev:  Pointer to acceleration device.
  *
  * Function frees interrupts for acceleration device.
@@ -317,7 +317,7 @@ void adf_isr_resource_free(struct adf_ac
 EXPORT_SYMBOL_GPL(adf_isr_resource_free);
 
 /**
- * adf_vf_isr_resource_alloc() - Allocate IRQ for acceleration device
+ * adf_isr_resource_alloc() - Allocate IRQ for acceleration device
  * @accel_dev:  Pointer to acceleration device.
  *
  * Function allocates interrupts for acceleration device.
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/qat/qat_common/adf_sriov.c linux-libre-4.7-gnu/drivers/crypto/qat/qat_common/adf_sriov.c
--- linux-libre-4.6-gnu/drivers/crypto/qat/qat_common/adf_sriov.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/qat/qat_common/adf_sriov.c	2016-07-24 15:23:50.000000000 -0400
@@ -249,13 +249,7 @@ int adf_sriov_configure(struct pci_dev *
 			return -EBUSY;
 		}
 
-		if (adf_dev_stop(accel_dev)) {
-			dev_err(&GET_DEV(accel_dev),
-				"Failed to stop qat_dev%d\n",
-				accel_dev->accel_id);
-			return -EFAULT;
-		}
-
+		adf_dev_stop(accel_dev);
 		adf_dev_shutdown(accel_dev);
 	}
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/qat/qat_common/adf_vf2pf_msg.c linux-libre-4.7-gnu/drivers/crypto/qat/qat_common/adf_vf2pf_msg.c
--- linux-libre-4.6-gnu/drivers/crypto/qat/qat_common/adf_vf2pf_msg.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/crypto/qat/qat_common/adf_vf2pf_msg.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,92 @@
+/*
+  This file is provided under a dual BSD/GPLv2 license.  When using or
+  redistributing this file, you may do so under either license.
+
+  GPL LICENSE SUMMARY
+  Copyright(c) 2015 Intel Corporation.
+  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.
+
+  Contact Information:
+  qat-linux@intel.com
+
+  BSD LICENSE
+  Copyright(c) 2015 Intel Corporation.
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in
+      the documentation and/or other materials provided with the
+      distribution.
+    * Neither the name of Intel Corporation nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "adf_accel_devices.h"
+#include "adf_common_drv.h"
+#include "adf_pf2vf_msg.h"
+
+/**
+ * adf_vf2pf_init() - send init msg to PF
+ * @accel_dev:  Pointer to acceleration VF device.
+ *
+ * Function sends an init messge from the VF to a PF
+ *
+ * Return: 0 on success, error code otherwise.
+ */
+int adf_vf2pf_init(struct adf_accel_dev *accel_dev)
+{
+	u32 msg = (ADF_VF2PF_MSGORIGIN_SYSTEM |
+		(ADF_VF2PF_MSGTYPE_INIT << ADF_VF2PF_MSGTYPE_SHIFT));
+
+	if (adf_iov_putmsg(accel_dev, msg, 0)) {
+		dev_err(&GET_DEV(accel_dev),
+			"Failed to send Init event to PF\n");
+		return -EFAULT;
+	}
+	set_bit(ADF_STATUS_PF_RUNNING, &accel_dev->status);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(adf_vf2pf_init);
+
+/**
+ * adf_vf2pf_shutdown() - send shutdown msg to PF
+ * @accel_dev:  Pointer to acceleration VF device.
+ *
+ * Function sends a shutdown messge from the VF to a PF
+ *
+ * Return: void
+ */
+void adf_vf2pf_shutdown(struct adf_accel_dev *accel_dev)
+{
+	u32 msg = (ADF_VF2PF_MSGORIGIN_SYSTEM |
+	    (ADF_VF2PF_MSGTYPE_SHUTDOWN << ADF_VF2PF_MSGTYPE_SHIFT));
+
+	if (test_bit(ADF_STATUS_PF_RUNNING, &accel_dev->status))
+		if (adf_iov_putmsg(accel_dev, msg, 0))
+			dev_err(&GET_DEV(accel_dev),
+				"Failed to send Shutdown event to PF\n");
+}
+EXPORT_SYMBOL_GPL(adf_vf2pf_shutdown);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/qat/qat_common/adf_vf_isr.c linux-libre-4.7-gnu/drivers/crypto/qat/qat_common/adf_vf_isr.c
--- linux-libre-4.6-gnu/drivers/crypto/qat/qat_common/adf_vf_isr.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/qat/qat_common/adf_vf_isr.c	2016-07-24 15:23:50.000000000 -0400
@@ -51,6 +51,7 @@
 #include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
+#include <linux/workqueue.h>
 #include "adf_accel_devices.h"
 #include "adf_common_drv.h"
 #include "adf_cfg.h"
@@ -64,6 +65,13 @@
 #define ADF_VINTSOU_BUN		BIT(0)
 #define ADF_VINTSOU_PF2VF	BIT(1)
 
+static struct workqueue_struct *adf_vf_stop_wq;
+
+struct adf_vf_stop_data {
+	struct adf_accel_dev *accel_dev;
+	struct work_struct work;
+};
+
 static int adf_enable_msi(struct adf_accel_dev *accel_dev)
 {
 	struct adf_accel_pci *pci_dev_info = &accel_dev->accel_pci_dev;
@@ -90,6 +98,20 @@ static void adf_disable_msi(struct adf_a
 	pci_disable_msi(pdev);
 }
 
+static void adf_dev_stop_async(struct work_struct *work)
+{
+	struct adf_vf_stop_data *stop_data =
+		container_of(work, struct adf_vf_stop_data, work);
+	struct adf_accel_dev *accel_dev = stop_data->accel_dev;
+
+	adf_dev_stop(accel_dev);
+	adf_dev_shutdown(accel_dev);
+
+	/* Re-enable PF2VF interrupts */
+	adf_enable_pf2vf_interrupts(accel_dev);
+	kfree(stop_data);
+}
+
 static void adf_pf2vf_bh_handler(void *data)
 {
 	struct adf_accel_dev *accel_dev = data;
@@ -107,11 +129,29 @@ static void adf_pf2vf_bh_handler(void *d
 		goto err;
 
 	switch ((msg & ADF_PF2VF_MSGTYPE_MASK) >> ADF_PF2VF_MSGTYPE_SHIFT) {
-	case ADF_PF2VF_MSGTYPE_RESTARTING:
+	case ADF_PF2VF_MSGTYPE_RESTARTING: {
+		struct adf_vf_stop_data *stop_data;
+
 		dev_dbg(&GET_DEV(accel_dev),
 			"Restarting msg received from PF 0x%x\n", msg);
-		adf_dev_stop(accel_dev);
-		break;
+
+		clear_bit(ADF_STATUS_PF_RUNNING, &accel_dev->status);
+
+		stop_data = kzalloc(sizeof(*stop_data), GFP_ATOMIC);
+		if (!stop_data) {
+			dev_err(&GET_DEV(accel_dev),
+				"Couldn't schedule stop for vf_%d\n",
+				accel_dev->accel_id);
+			return;
+		}
+		stop_data->accel_dev = accel_dev;
+		INIT_WORK(&stop_data->work, adf_dev_stop_async);
+		queue_work(adf_vf_stop_wq, &stop_data->work);
+		/* To ack, clear the PF2VFINT bit */
+		msg &= ~BIT(0);
+		ADF_CSR_WR(pmisc_bar_addr, hw_data->get_pf2vf_offset(0), msg);
+		return;
+	}
 	case ADF_PF2VF_MSGTYPE_VERSION_RESP:
 		dev_dbg(&GET_DEV(accel_dev),
 			"Version resp received from PF 0x%x\n", msg);
@@ -278,3 +318,18 @@ err_out:
 	return -EFAULT;
 }
 EXPORT_SYMBOL_GPL(adf_vf_isr_resource_alloc);
+
+int __init adf_init_vf_wq(void)
+{
+	adf_vf_stop_wq = create_workqueue("adf_vf_stop_wq");
+
+	return !adf_vf_stop_wq ? -EFAULT : 0;
+}
+
+void adf_exit_vf_wq(void)
+{
+	if (adf_vf_stop_wq)
+		destroy_workqueue(adf_vf_stop_wq);
+
+	adf_vf_stop_wq = NULL;
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/qat/qat_common/Makefile linux-libre-4.7-gnu/drivers/crypto/qat/qat_common/Makefile
--- linux-libre-4.6-gnu/drivers/crypto/qat/qat_common/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/qat/qat_common/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -2,6 +2,7 @@ $(obj)/qat_rsapubkey-asn1.o: $(obj)/qat_
 			     $(obj)/qat_rsapubkey-asn1.h
 $(obj)/qat_rsaprivkey-asn1.o: $(obj)/qat_rsaprivkey-asn1.c \
 			      $(obj)/qat_rsaprivkey-asn1.h
+$(obj)/qat_asym_algs.o: $(obj)/qat_rsapubkey-asn1.h $(obj)/qat_rsaprivkey-asn1.h
 
 clean-files += qat_rsapubkey-asn1.c qat_rsapubkey-asn1.h
 clean-files += qat_rsaprivkey-asn1.c qat_rsaprivkey-asn1.h
@@ -9,7 +10,6 @@ clean-files += qat_rsaprivkey-asn1.c qat
 obj-$(CONFIG_CRYPTO_DEV_QAT) += intel_qat.o
 intel_qat-objs := adf_cfg.o \
 	adf_isr.o \
-	adf_vf_isr.o \
 	adf_ctl_drv.o \
 	adf_dev_mgr.o \
 	adf_init.o \
@@ -27,4 +27,5 @@ intel_qat-objs := adf_cfg.o \
 	qat_hal.o
 
 intel_qat-$(CONFIG_DEBUG_FS) += adf_transport_debug.o
-intel_qat-$(CONFIG_PCI_IOV) += adf_sriov.o adf_pf2vf_msg.o
+intel_qat-$(CONFIG_PCI_IOV) += adf_sriov.o adf_pf2vf_msg.o \
+			       adf_vf2pf_msg.o adf_vf_isr.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/qat/qat_common/qat_asym_algs.c linux-libre-4.7-gnu/drivers/crypto/qat/qat_common/qat_asym_algs.c
--- linux-libre-4.6-gnu/drivers/crypto/qat/qat_common/qat_asym_algs.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/qat/qat_common/qat_asym_algs.c	2016-07-24 15:23:50.000000000 -0400
@@ -593,7 +593,7 @@ int qat_rsa_get_d(void *context, size_t
 
 	ret = -ENOMEM;
 	ctx->d = dma_zalloc_coherent(dev, ctx->key_sz, &ctx->dma_d, GFP_KERNEL);
-	if (!ctx->n)
+	if (!ctx->d)
 		goto err;
 
 	memcpy(ctx->d + (ctx->key_sz - vlen), ptr, vlen);
@@ -711,7 +711,7 @@ static void qat_rsa_exit_tfm(struct cryp
 	}
 	qat_crypto_put_instance(ctx->inst);
 	ctx->n = NULL;
-	ctx->d = NULL;
+	ctx->e = NULL;
 	ctx->d = NULL;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/qat/qat_dh895xcc/adf_drv.c linux-libre-4.7-gnu/drivers/crypto/qat/qat_dh895xcc/adf_drv.c
--- linux-libre-4.6-gnu/drivers/crypto/qat/qat_dh895xcc/adf_drv.c	2016-05-15 19:19:44.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/qat/qat_dh895xcc/adf_drv.c	2016-07-24 18:15:47.000000000 -0400
@@ -302,9 +302,7 @@ static void adf_remove(struct pci_dev *p
 		pr_err("QAT: Driver removal failed\n");
 		return;
 	}
-	if (adf_dev_stop(accel_dev))
-		dev_err(&GET_DEV(accel_dev), "Failed to stop QAT accel dev\n");
-
+	adf_dev_stop(accel_dev);
 	adf_dev_shutdown(accel_dev);
 	adf_disable_aer(accel_dev);
 	adf_cleanup_accel(accel_dev);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/qat/qat_dh895xccvf/adf_dh895xccvf_hw_data.c linux-libre-4.7-gnu/drivers/crypto/qat/qat_dh895xccvf/adf_dh895xccvf_hw_data.c
--- linux-libre-4.6-gnu/drivers/crypto/qat/qat_dh895xccvf/adf_dh895xccvf_hw_data.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/qat/qat_dh895xccvf/adf_dh895xccvf_hw_data.c	2016-07-24 15:23:50.000000000 -0400
@@ -109,29 +109,6 @@ static void adf_vf_void_noop(struct adf_
 {
 }
 
-static int adf_vf2pf_init(struct adf_accel_dev *accel_dev)
-{
-	u32 msg = (ADF_VF2PF_MSGORIGIN_SYSTEM |
-		(ADF_VF2PF_MSGTYPE_INIT << ADF_VF2PF_MSGTYPE_SHIFT));
-
-	if (adf_iov_putmsg(accel_dev, msg, 0)) {
-		dev_err(&GET_DEV(accel_dev),
-			"Failed to send Init event to PF\n");
-		return -EFAULT;
-	}
-	return 0;
-}
-
-static void adf_vf2pf_shutdown(struct adf_accel_dev *accel_dev)
-{
-	u32 msg = (ADF_VF2PF_MSGORIGIN_SYSTEM |
-	    (ADF_VF2PF_MSGTYPE_SHUTDOWN << ADF_VF2PF_MSGTYPE_SHIFT));
-
-	if (adf_iov_putmsg(accel_dev, msg, 0))
-		dev_err(&GET_DEV(accel_dev),
-			"Failed to send Shutdown event to PF\n");
-}
-
 void adf_init_hw_data_dh895xcciov(struct adf_hw_device_data *hw_data)
 {
 	hw_data->dev_class = &dh895xcciov_class;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/qat/qat_dh895xccvf/adf_drv.c linux-libre-4.7-gnu/drivers/crypto/qat/qat_dh895xccvf/adf_drv.c
--- linux-libre-4.6-gnu/drivers/crypto/qat/qat_dh895xccvf/adf_drv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/qat/qat_dh895xccvf/adf_drv.c	2016-07-24 15:23:50.000000000 -0400
@@ -238,6 +238,8 @@ static int adf_probe(struct pci_dev *pde
 	if (ret)
 		goto out_err_free_reg;
 
+	set_bit(ADF_STATUS_PF_RUNNING, &accel_dev->status);
+
 	ret = adf_dev_init(accel_dev);
 	if (ret)
 		goto out_err_dev_shutdown;
@@ -270,9 +272,7 @@ static void adf_remove(struct pci_dev *p
 		pr_err("QAT: Driver removal failed\n");
 		return;
 	}
-	if (adf_dev_stop(accel_dev))
-		dev_err(&GET_DEV(accel_dev), "Failed to stop QAT accel dev\n");
-
+	adf_dev_stop(accel_dev);
 	adf_dev_shutdown(accel_dev);
 	adf_cleanup_accel(accel_dev);
 	adf_cleanup_pci_dev(accel_dev);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/s5p-sss.c linux-libre-4.7-gnu/drivers/crypto/s5p-sss.c
--- linux-libre-4.6-gnu/drivers/crypto/s5p-sss.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/s5p-sss.c	2016-07-24 15:23:50.000000000 -0400
@@ -11,65 +11,64 @@
  *
  */
 
-#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/crypto.h>
+#include <linux/dma-mapping.h>
 #include <linux/err.h>
-#include <linux/module.h>
-#include <linux/init.h>
 #include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
 #include <linux/kernel.h>
-#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/scatterlist.h>
-#include <linux/dma-mapping.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/crypto.h>
-#include <linux/interrupt.h>
 
-#include <crypto/algapi.h>
-#include <crypto/aes.h>
 #include <crypto/ctr.h>
+#include <crypto/aes.h>
+#include <crypto/algapi.h>
+#include <crypto/scatterwalk.h>
 
 #define _SBF(s, v)                      ((v) << (s))
-#define _BIT(b)                         _SBF(b, 1)
 
 /* Feed control registers */
 #define SSS_REG_FCINTSTAT               0x0000
-#define SSS_FCINTSTAT_BRDMAINT          _BIT(3)
-#define SSS_FCINTSTAT_BTDMAINT          _BIT(2)
-#define SSS_FCINTSTAT_HRDMAINT          _BIT(1)
-#define SSS_FCINTSTAT_PKDMAINT          _BIT(0)
+#define SSS_FCINTSTAT_BRDMAINT          BIT(3)
+#define SSS_FCINTSTAT_BTDMAINT          BIT(2)
+#define SSS_FCINTSTAT_HRDMAINT          BIT(1)
+#define SSS_FCINTSTAT_PKDMAINT          BIT(0)
 
 #define SSS_REG_FCINTENSET              0x0004
-#define SSS_FCINTENSET_BRDMAINTENSET    _BIT(3)
-#define SSS_FCINTENSET_BTDMAINTENSET    _BIT(2)
-#define SSS_FCINTENSET_HRDMAINTENSET    _BIT(1)
-#define SSS_FCINTENSET_PKDMAINTENSET    _BIT(0)
+#define SSS_FCINTENSET_BRDMAINTENSET    BIT(3)
+#define SSS_FCINTENSET_BTDMAINTENSET    BIT(2)
+#define SSS_FCINTENSET_HRDMAINTENSET    BIT(1)
+#define SSS_FCINTENSET_PKDMAINTENSET    BIT(0)
 
 #define SSS_REG_FCINTENCLR              0x0008
-#define SSS_FCINTENCLR_BRDMAINTENCLR    _BIT(3)
-#define SSS_FCINTENCLR_BTDMAINTENCLR    _BIT(2)
-#define SSS_FCINTENCLR_HRDMAINTENCLR    _BIT(1)
-#define SSS_FCINTENCLR_PKDMAINTENCLR    _BIT(0)
+#define SSS_FCINTENCLR_BRDMAINTENCLR    BIT(3)
+#define SSS_FCINTENCLR_BTDMAINTENCLR    BIT(2)
+#define SSS_FCINTENCLR_HRDMAINTENCLR    BIT(1)
+#define SSS_FCINTENCLR_PKDMAINTENCLR    BIT(0)
 
 #define SSS_REG_FCINTPEND               0x000C
-#define SSS_FCINTPEND_BRDMAINTP         _BIT(3)
-#define SSS_FCINTPEND_BTDMAINTP         _BIT(2)
-#define SSS_FCINTPEND_HRDMAINTP         _BIT(1)
-#define SSS_FCINTPEND_PKDMAINTP         _BIT(0)
+#define SSS_FCINTPEND_BRDMAINTP         BIT(3)
+#define SSS_FCINTPEND_BTDMAINTP         BIT(2)
+#define SSS_FCINTPEND_HRDMAINTP         BIT(1)
+#define SSS_FCINTPEND_PKDMAINTP         BIT(0)
 
 #define SSS_REG_FCFIFOSTAT              0x0010
-#define SSS_FCFIFOSTAT_BRFIFOFUL        _BIT(7)
-#define SSS_FCFIFOSTAT_BRFIFOEMP        _BIT(6)
-#define SSS_FCFIFOSTAT_BTFIFOFUL        _BIT(5)
-#define SSS_FCFIFOSTAT_BTFIFOEMP        _BIT(4)
-#define SSS_FCFIFOSTAT_HRFIFOFUL        _BIT(3)
-#define SSS_FCFIFOSTAT_HRFIFOEMP        _BIT(2)
-#define SSS_FCFIFOSTAT_PKFIFOFUL        _BIT(1)
-#define SSS_FCFIFOSTAT_PKFIFOEMP        _BIT(0)
+#define SSS_FCFIFOSTAT_BRFIFOFUL        BIT(7)
+#define SSS_FCFIFOSTAT_BRFIFOEMP        BIT(6)
+#define SSS_FCFIFOSTAT_BTFIFOFUL        BIT(5)
+#define SSS_FCFIFOSTAT_BTFIFOEMP        BIT(4)
+#define SSS_FCFIFOSTAT_HRFIFOFUL        BIT(3)
+#define SSS_FCFIFOSTAT_HRFIFOEMP        BIT(2)
+#define SSS_FCFIFOSTAT_PKFIFOFUL        BIT(1)
+#define SSS_FCFIFOSTAT_PKFIFOEMP        BIT(0)
 
 #define SSS_REG_FCFIFOCTRL              0x0014
-#define SSS_FCFIFOCTRL_DESSEL           _BIT(2)
+#define SSS_FCFIFOCTRL_DESSEL           BIT(2)
 #define SSS_HASHIN_INDEPENDENT          _SBF(0, 0x00)
 #define SSS_HASHIN_CIPHER_INPUT         _SBF(0, 0x01)
 #define SSS_HASHIN_CIPHER_OUTPUT        _SBF(0, 0x02)
@@ -77,52 +76,52 @@
 #define SSS_REG_FCBRDMAS                0x0020
 #define SSS_REG_FCBRDMAL                0x0024
 #define SSS_REG_FCBRDMAC                0x0028
-#define SSS_FCBRDMAC_BYTESWAP           _BIT(1)
-#define SSS_FCBRDMAC_FLUSH              _BIT(0)
+#define SSS_FCBRDMAC_BYTESWAP           BIT(1)
+#define SSS_FCBRDMAC_FLUSH              BIT(0)
 
 #define SSS_REG_FCBTDMAS                0x0030
 #define SSS_REG_FCBTDMAL                0x0034
 #define SSS_REG_FCBTDMAC                0x0038
-#define SSS_FCBTDMAC_BYTESWAP           _BIT(1)
-#define SSS_FCBTDMAC_FLUSH              _BIT(0)
+#define SSS_FCBTDMAC_BYTESWAP           BIT(1)
+#define SSS_FCBTDMAC_FLUSH              BIT(0)
 
 #define SSS_REG_FCHRDMAS                0x0040
 #define SSS_REG_FCHRDMAL                0x0044
 #define SSS_REG_FCHRDMAC                0x0048
-#define SSS_FCHRDMAC_BYTESWAP           _BIT(1)
-#define SSS_FCHRDMAC_FLUSH              _BIT(0)
+#define SSS_FCHRDMAC_BYTESWAP           BIT(1)
+#define SSS_FCHRDMAC_FLUSH              BIT(0)
 
 #define SSS_REG_FCPKDMAS                0x0050
 #define SSS_REG_FCPKDMAL                0x0054
 #define SSS_REG_FCPKDMAC                0x0058
-#define SSS_FCPKDMAC_BYTESWAP           _BIT(3)
-#define SSS_FCPKDMAC_DESCEND            _BIT(2)
-#define SSS_FCPKDMAC_TRANSMIT           _BIT(1)
-#define SSS_FCPKDMAC_FLUSH              _BIT(0)
+#define SSS_FCPKDMAC_BYTESWAP           BIT(3)
+#define SSS_FCPKDMAC_DESCEND            BIT(2)
+#define SSS_FCPKDMAC_TRANSMIT           BIT(1)
+#define SSS_FCPKDMAC_FLUSH              BIT(0)
 
 #define SSS_REG_FCPKDMAO                0x005C
 
 /* AES registers */
 #define SSS_REG_AES_CONTROL		0x00
-#define SSS_AES_BYTESWAP_DI             _BIT(11)
-#define SSS_AES_BYTESWAP_DO             _BIT(10)
-#define SSS_AES_BYTESWAP_IV             _BIT(9)
-#define SSS_AES_BYTESWAP_CNT            _BIT(8)
-#define SSS_AES_BYTESWAP_KEY            _BIT(7)
-#define SSS_AES_KEY_CHANGE_MODE         _BIT(6)
+#define SSS_AES_BYTESWAP_DI             BIT(11)
+#define SSS_AES_BYTESWAP_DO             BIT(10)
+#define SSS_AES_BYTESWAP_IV             BIT(9)
+#define SSS_AES_BYTESWAP_CNT            BIT(8)
+#define SSS_AES_BYTESWAP_KEY            BIT(7)
+#define SSS_AES_KEY_CHANGE_MODE         BIT(6)
 #define SSS_AES_KEY_SIZE_128            _SBF(4, 0x00)
 #define SSS_AES_KEY_SIZE_192            _SBF(4, 0x01)
 #define SSS_AES_KEY_SIZE_256            _SBF(4, 0x02)
-#define SSS_AES_FIFO_MODE               _BIT(3)
+#define SSS_AES_FIFO_MODE               BIT(3)
 #define SSS_AES_CHAIN_MODE_ECB          _SBF(1, 0x00)
 #define SSS_AES_CHAIN_MODE_CBC          _SBF(1, 0x01)
 #define SSS_AES_CHAIN_MODE_CTR          _SBF(1, 0x02)
-#define SSS_AES_MODE_DECRYPT            _BIT(0)
+#define SSS_AES_MODE_DECRYPT            BIT(0)
 
 #define SSS_REG_AES_STATUS		0x04
-#define SSS_AES_BUSY                    _BIT(2)
-#define SSS_AES_INPUT_READY             _BIT(1)
-#define SSS_AES_OUTPUT_READY            _BIT(0)
+#define SSS_AES_BUSY                    BIT(2)
+#define SSS_AES_INPUT_READY             BIT(1)
+#define SSS_AES_OUTPUT_READY            BIT(0)
 
 #define SSS_REG_AES_IN_DATA(s)		(0x10 + (s << 2))
 #define SSS_REG_AES_OUT_DATA(s)		(0x20 + (s << 2))
@@ -139,7 +138,7 @@
 						SSS_AES_REG(dev, reg))
 
 /* HW engine modes */
-#define FLAGS_AES_DECRYPT               _BIT(0)
+#define FLAGS_AES_DECRYPT               BIT(0)
 #define FLAGS_AES_MODE_MASK             _SBF(1, 0x03)
 #define FLAGS_AES_CBC                   _SBF(1, 0x01)
 #define FLAGS_AES_CTR                   _SBF(1, 0x02)
@@ -149,7 +148,6 @@
 
 /**
  * struct samsung_aes_variant - platform specific SSS driver data
- * @has_hash_irq: true if SSS module uses hash interrupt, false otherwise
  * @aes_offset: AES register offset from SSS module's base.
  *
  * Specifies platform specific configuration of SSS module.
@@ -157,7 +155,6 @@
  * expansion of its usage.
  */
 struct samsung_aes_variant {
-	bool			    has_hash_irq;
 	unsigned int		    aes_offset;
 };
 
@@ -178,7 +175,6 @@ struct s5p_aes_dev {
 	struct clk                 *clk;
 	void __iomem               *ioaddr;
 	void __iomem               *aes_ioaddr;
-	int                         irq_hash;
 	int                         irq_fc;
 
 	struct ablkcipher_request  *req;
@@ -186,6 +182,10 @@ struct s5p_aes_dev {
 	struct scatterlist         *sg_src;
 	struct scatterlist         *sg_dst;
 
+	/* In case of unaligned access: */
+	struct scatterlist         *sg_src_cpy;
+	struct scatterlist         *sg_dst_cpy;
+
 	struct tasklet_struct       tasklet;
 	struct crypto_queue         queue;
 	bool                        busy;
@@ -197,12 +197,10 @@ struct s5p_aes_dev {
 static struct s5p_aes_dev *s5p_dev;
 
 static const struct samsung_aes_variant s5p_aes_data = {
-	.has_hash_irq	= true,
 	.aes_offset	= 0x4000,
 };
 
 static const struct samsung_aes_variant exynos_aes_data = {
-	.has_hash_irq	= false,
 	.aes_offset	= 0x200,
 };
 
@@ -245,8 +243,45 @@ static void s5p_set_dma_outdata(struct s
 	SSS_WRITE(dev, FCBTDMAL, sg_dma_len(sg));
 }
 
+static void s5p_free_sg_cpy(struct s5p_aes_dev *dev, struct scatterlist **sg)
+{
+	int len;
+
+	if (!*sg)
+		return;
+
+	len = ALIGN(dev->req->nbytes, AES_BLOCK_SIZE);
+	free_pages((unsigned long)sg_virt(*sg), get_order(len));
+
+	kfree(*sg);
+	*sg = NULL;
+}
+
+static void s5p_sg_copy_buf(void *buf, struct scatterlist *sg,
+			    unsigned int nbytes, int out)
+{
+	struct scatter_walk walk;
+
+	if (!nbytes)
+		return;
+
+	scatterwalk_start(&walk, sg);
+	scatterwalk_copychunks(buf, &walk, nbytes, out);
+	scatterwalk_done(&walk, out, 0);
+}
+
 static void s5p_aes_complete(struct s5p_aes_dev *dev, int err)
 {
+	if (dev->sg_dst_cpy) {
+		dev_dbg(dev->dev,
+			"Copying %d bytes of output data back to original place\n",
+			dev->req->nbytes);
+		s5p_sg_copy_buf(sg_virt(dev->sg_dst_cpy), dev->req->dst,
+				dev->req->nbytes, 1);
+	}
+	s5p_free_sg_cpy(dev, &dev->sg_src_cpy);
+	s5p_free_sg_cpy(dev, &dev->sg_dst_cpy);
+
 	/* holding a lock outside */
 	dev->req->base.complete(&dev->req->base, err);
 	dev->busy = false;
@@ -262,15 +297,37 @@ static void s5p_unset_indata(struct s5p_
 	dma_unmap_sg(dev->dev, dev->sg_src, 1, DMA_TO_DEVICE);
 }
 
+static int s5p_make_sg_cpy(struct s5p_aes_dev *dev, struct scatterlist *src,
+			    struct scatterlist **dst)
+{
+	void *pages;
+	int len;
+
+	*dst = kmalloc(sizeof(**dst), GFP_ATOMIC);
+	if (!*dst)
+		return -ENOMEM;
+
+	len = ALIGN(dev->req->nbytes, AES_BLOCK_SIZE);
+	pages = (void *)__get_free_pages(GFP_ATOMIC, get_order(len));
+	if (!pages) {
+		kfree(*dst);
+		*dst = NULL;
+		return -ENOMEM;
+	}
+
+	s5p_sg_copy_buf(pages, src, dev->req->nbytes, 0);
+
+	sg_init_table(*dst, 1);
+	sg_set_buf(*dst, pages, len);
+
+	return 0;
+}
+
 static int s5p_set_outdata(struct s5p_aes_dev *dev, struct scatterlist *sg)
 {
 	int err;
 
-	if (!IS_ALIGNED(sg_dma_len(sg), AES_BLOCK_SIZE)) {
-		err = -EINVAL;
-		goto exit;
-	}
-	if (!sg_dma_len(sg)) {
+	if (!sg->length) {
 		err = -EINVAL;
 		goto exit;
 	}
@@ -284,7 +341,7 @@ static int s5p_set_outdata(struct s5p_ae
 	dev->sg_dst = sg;
 	err = 0;
 
- exit:
+exit:
 	return err;
 }
 
@@ -292,11 +349,7 @@ static int s5p_set_indata(struct s5p_aes
 {
 	int err;
 
-	if (!IS_ALIGNED(sg_dma_len(sg), AES_BLOCK_SIZE)) {
-		err = -EINVAL;
-		goto exit;
-	}
-	if (!sg_dma_len(sg)) {
+	if (!sg->length) {
 		err = -EINVAL;
 		goto exit;
 	}
@@ -310,47 +363,59 @@ static int s5p_set_indata(struct s5p_aes
 	dev->sg_src = sg;
 	err = 0;
 
- exit:
+exit:
 	return err;
 }
 
-static void s5p_aes_tx(struct s5p_aes_dev *dev)
+/*
+ * Returns true if new transmitting (output) data is ready and its
+ * address+length have to be written to device (by calling
+ * s5p_set_dma_outdata()). False otherwise.
+ */
+static bool s5p_aes_tx(struct s5p_aes_dev *dev)
 {
 	int err = 0;
+	bool ret = false;
 
 	s5p_unset_outdata(dev);
 
 	if (!sg_is_last(dev->sg_dst)) {
 		err = s5p_set_outdata(dev, sg_next(dev->sg_dst));
-		if (err) {
+		if (err)
 			s5p_aes_complete(dev, err);
-			return;
-		}
-
-		s5p_set_dma_outdata(dev, dev->sg_dst);
+		else
+			ret = true;
 	} else {
 		s5p_aes_complete(dev, err);
 
 		dev->busy = true;
 		tasklet_schedule(&dev->tasklet);
 	}
+
+	return ret;
 }
 
-static void s5p_aes_rx(struct s5p_aes_dev *dev)
+/*
+ * Returns true if new receiving (input) data is ready and its
+ * address+length have to be written to device (by calling
+ * s5p_set_dma_indata()). False otherwise.
+ */
+static bool s5p_aes_rx(struct s5p_aes_dev *dev)
 {
 	int err;
+	bool ret = false;
 
 	s5p_unset_indata(dev);
 
 	if (!sg_is_last(dev->sg_src)) {
 		err = s5p_set_indata(dev, sg_next(dev->sg_src));
-		if (err) {
+		if (err)
 			s5p_aes_complete(dev, err);
-			return;
-		}
-
-		s5p_set_dma_indata(dev, dev->sg_src);
+		else
+			ret = true;
 	}
+
+	return ret;
 }
 
 static irqreturn_t s5p_aes_interrupt(int irq, void *dev_id)
@@ -359,18 +424,29 @@ static irqreturn_t s5p_aes_interrupt(int
 	struct s5p_aes_dev     *dev  = platform_get_drvdata(pdev);
 	uint32_t                status;
 	unsigned long           flags;
+	bool			set_dma_tx = false;
+	bool			set_dma_rx = false;
 
 	spin_lock_irqsave(&dev->lock, flags);
 
-	if (irq == dev->irq_fc) {
-		status = SSS_READ(dev, FCINTSTAT);
-		if (status & SSS_FCINTSTAT_BRDMAINT)
-			s5p_aes_rx(dev);
-		if (status & SSS_FCINTSTAT_BTDMAINT)
-			s5p_aes_tx(dev);
+	status = SSS_READ(dev, FCINTSTAT);
+	if (status & SSS_FCINTSTAT_BRDMAINT)
+		set_dma_rx = s5p_aes_rx(dev);
+	if (status & SSS_FCINTSTAT_BTDMAINT)
+		set_dma_tx = s5p_aes_tx(dev);
 
-		SSS_WRITE(dev, FCINTPEND, status);
-	}
+	SSS_WRITE(dev, FCINTPEND, status);
+
+	/*
+	 * Writing length of DMA block (either receiving or transmitting)
+	 * will start the operation immediately, so this should be done
+	 * at the end (even after clearing pending interrupts to not miss the
+	 * interrupt).
+	 */
+	if (set_dma_tx)
+		s5p_set_dma_outdata(dev, dev->sg_dst);
+	if (set_dma_rx)
+		s5p_set_dma_indata(dev, dev->sg_src);
 
 	spin_unlock_irqrestore(&dev->lock, flags);
 
@@ -395,6 +471,71 @@ static void s5p_set_aes(struct s5p_aes_d
 	memcpy_toio(keystart, key, keylen);
 }
 
+static bool s5p_is_sg_aligned(struct scatterlist *sg)
+{
+	while (sg) {
+		if (!IS_ALIGNED(sg->length, AES_BLOCK_SIZE))
+			return false;
+		sg = sg_next(sg);
+	}
+
+	return true;
+}
+
+static int s5p_set_indata_start(struct s5p_aes_dev *dev,
+				struct ablkcipher_request *req)
+{
+	struct scatterlist *sg;
+	int err;
+
+	dev->sg_src_cpy = NULL;
+	sg = req->src;
+	if (!s5p_is_sg_aligned(sg)) {
+		dev_dbg(dev->dev,
+			"At least one unaligned source scatter list, making a copy\n");
+		err = s5p_make_sg_cpy(dev, sg, &dev->sg_src_cpy);
+		if (err)
+			return err;
+
+		sg = dev->sg_src_cpy;
+	}
+
+	err = s5p_set_indata(dev, sg);
+	if (err) {
+		s5p_free_sg_cpy(dev, &dev->sg_src_cpy);
+		return err;
+	}
+
+	return 0;
+}
+
+static int s5p_set_outdata_start(struct s5p_aes_dev *dev,
+				struct ablkcipher_request *req)
+{
+	struct scatterlist *sg;
+	int err;
+
+	dev->sg_dst_cpy = NULL;
+	sg = req->dst;
+	if (!s5p_is_sg_aligned(sg)) {
+		dev_dbg(dev->dev,
+			"At least one unaligned dest scatter list, making a copy\n");
+		err = s5p_make_sg_cpy(dev, sg, &dev->sg_dst_cpy);
+		if (err)
+			return err;
+
+		sg = dev->sg_dst_cpy;
+	}
+
+	err = s5p_set_outdata(dev, sg);
+	if (err) {
+		s5p_free_sg_cpy(dev, &dev->sg_dst_cpy);
+		return err;
+	}
+
+	return 0;
+}
+
 static void s5p_aes_crypt_start(struct s5p_aes_dev *dev, unsigned long mode)
 {
 	struct ablkcipher_request  *req = dev->req;
@@ -431,19 +572,19 @@ static void s5p_aes_crypt_start(struct s
 		  SSS_FCINTENCLR_BTDMAINTENCLR | SSS_FCINTENCLR_BRDMAINTENCLR);
 	SSS_WRITE(dev, FCFIFOCTRL, 0x00);
 
-	err = s5p_set_indata(dev, req->src);
+	err = s5p_set_indata_start(dev, req);
 	if (err)
 		goto indata_error;
 
-	err = s5p_set_outdata(dev, req->dst);
+	err = s5p_set_outdata_start(dev, req);
 	if (err)
 		goto outdata_error;
 
 	SSS_AES_WRITE(dev, AES_CONTROL, aes_control);
 	s5p_set_aes(dev, dev->ctx->aes_key, req->info, dev->ctx->keylen);
 
-	s5p_set_dma_indata(dev,  req->src);
-	s5p_set_dma_outdata(dev, req->dst);
+	s5p_set_dma_indata(dev,  dev->sg_src);
+	s5p_set_dma_outdata(dev, dev->sg_dst);
 
 	SSS_WRITE(dev, FCINTENSET,
 		  SSS_FCINTENSET_BTDMAINTENSET | SSS_FCINTENSET_BRDMAINTENSET);
@@ -452,10 +593,10 @@ static void s5p_aes_crypt_start(struct s
 
 	return;
 
- outdata_error:
+outdata_error:
 	s5p_unset_indata(dev);
 
- indata_error:
+indata_error:
 	s5p_aes_complete(dev, err);
 	spin_unlock_irqrestore(&dev->lock, flags);
 }
@@ -506,7 +647,7 @@ static int s5p_aes_handle_req(struct s5p
 
 	tasklet_schedule(&dev->tasklet);
 
- exit:
+exit:
 	return err;
 }
 
@@ -671,21 +812,6 @@ static int s5p_aes_probe(struct platform
 		goto err_irq;
 	}
 
-	if (variant->has_hash_irq) {
-		pdata->irq_hash = platform_get_irq(pdev, 1);
-		if (pdata->irq_hash < 0) {
-			err = pdata->irq_hash;
-			dev_warn(dev, "hash interrupt is not available.\n");
-			goto err_irq;
-		}
-		err = devm_request_irq(dev, pdata->irq_hash, s5p_aes_interrupt,
-				       IRQF_SHARED, pdev->name, pdev);
-		if (err < 0) {
-			dev_warn(dev, "hash interrupt is not available.\n");
-			goto err_irq;
-		}
-	}
-
 	pdata->busy = false;
 	pdata->variant = variant;
 	pdata->dev = dev;
@@ -705,7 +831,7 @@ static int s5p_aes_probe(struct platform
 
 	return 0;
 
- err_algs:
+err_algs:
 	dev_err(dev, "can't register '%s': %d\n", algs[i].cra_name, err);
 
 	for (j = 0; j < i; j++)
@@ -713,7 +839,7 @@ static int s5p_aes_probe(struct platform
 
 	tasklet_kill(&pdata->tasklet);
 
- err_irq:
+err_irq:
 	clk_disable_unprepare(pdata->clk);
 
 	s5p_dev = NULL;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c linux-libre-4.7-gnu/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c
--- linux-libre-4.6-gnu/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c	2016-07-24 15:23:50.000000000 -0400
@@ -35,6 +35,7 @@ static int sun4i_ss_opti_poll(struct abl
 	unsigned int todo;
 	struct sg_mapping_iter mi, mo;
 	unsigned int oi, oo; /* offset for in and out */
+	unsigned long flags;
 
 	if (areq->nbytes == 0)
 		return 0;
@@ -49,7 +50,7 @@ static int sun4i_ss_opti_poll(struct abl
 		return -EINVAL;
 	}
 
-	spin_lock_bh(&ss->slock);
+	spin_lock_irqsave(&ss->slock, flags);
 
 	for (i = 0; i < op->keylen; i += 4)
 		writel(*(op->key + i / 4), ss->base + SS_KEY0 + i);
@@ -117,7 +118,7 @@ release_ss:
 	sg_miter_stop(&mi);
 	sg_miter_stop(&mo);
 	writel(0, ss->base + SS_CTL);
-	spin_unlock_bh(&ss->slock);
+	spin_unlock_irqrestore(&ss->slock, flags);
 	return err;
 }
 
@@ -149,6 +150,7 @@ static int sun4i_ss_cipher_poll(struct a
 	unsigned int ob = 0;	/* offset in buf */
 	unsigned int obo = 0;	/* offset in bufo*/
 	unsigned int obl = 0;	/* length of data in bufo */
+	unsigned long flags;
 
 	if (areq->nbytes == 0)
 		return 0;
@@ -181,7 +183,7 @@ static int sun4i_ss_cipher_poll(struct a
 	if (no_chunk == 1)
 		return sun4i_ss_opti_poll(areq);
 
-	spin_lock_bh(&ss->slock);
+	spin_lock_irqsave(&ss->slock, flags);
 
 	for (i = 0; i < op->keylen; i += 4)
 		writel(*(op->key + i / 4), ss->base + SS_KEY0 + i);
@@ -307,7 +309,7 @@ release_ss:
 	sg_miter_stop(&mi);
 	sg_miter_stop(&mo);
 	writel(0, ss->base + SS_CTL);
-	spin_unlock_bh(&ss->slock);
+	spin_unlock_irqrestore(&ss->slock, flags);
 
 	return err;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/talitos.c linux-libre-4.7-gnu/drivers/crypto/talitos.c
--- linux-libre-4.6-gnu/drivers/crypto/talitos.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/talitos.c	2016-07-24 15:23:50.000000000 -0400
@@ -835,6 +835,16 @@ struct talitos_ahash_req_ctx {
 	struct scatterlist *psrc;
 };
 
+struct talitos_export_state {
+	u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)];
+	u8 buf[HASH_MAX_BLOCK_SIZE];
+	unsigned int swinit;
+	unsigned int first;
+	unsigned int last;
+	unsigned int to_hash_later;
+	unsigned int nbuf;
+};
+
 static int aead_setkey(struct crypto_aead *authenc,
 		       const u8 *key, unsigned int keylen)
 {
@@ -1981,6 +1991,46 @@ static int ahash_digest(struct ahash_req
 	return ahash_process_req(areq, areq->nbytes);
 }
 
+static int ahash_export(struct ahash_request *areq, void *out)
+{
+	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
+	struct talitos_export_state *export = out;
+
+	memcpy(export->hw_context, req_ctx->hw_context,
+	       req_ctx->hw_context_size);
+	memcpy(export->buf, req_ctx->buf, req_ctx->nbuf);
+	export->swinit = req_ctx->swinit;
+	export->first = req_ctx->first;
+	export->last = req_ctx->last;
+	export->to_hash_later = req_ctx->to_hash_later;
+	export->nbuf = req_ctx->nbuf;
+
+	return 0;
+}
+
+static int ahash_import(struct ahash_request *areq, const void *in)
+{
+	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
+	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
+	const struct talitos_export_state *export = in;
+
+	memset(req_ctx, 0, sizeof(*req_ctx));
+	req_ctx->hw_context_size =
+		(crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE)
+			? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256
+			: TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512;
+	memcpy(req_ctx->hw_context, export->hw_context,
+	       req_ctx->hw_context_size);
+	memcpy(req_ctx->buf, export->buf, export->nbuf);
+	req_ctx->swinit = export->swinit;
+	req_ctx->first = export->first;
+	req_ctx->last = export->last;
+	req_ctx->to_hash_later = export->to_hash_later;
+	req_ctx->nbuf = export->nbuf;
+
+	return 0;
+}
+
 struct keyhash_result {
 	struct completion completion;
 	int err;
@@ -2458,6 +2508,7 @@ static struct talitos_alg_template drive
 	{	.type = CRYPTO_ALG_TYPE_AHASH,
 		.alg.hash = {
 			.halg.digestsize = MD5_DIGEST_SIZE,
+			.halg.statesize = sizeof(struct talitos_export_state),
 			.halg.base = {
 				.cra_name = "md5",
 				.cra_driver_name = "md5-talitos",
@@ -2473,6 +2524,7 @@ static struct talitos_alg_template drive
 	{	.type = CRYPTO_ALG_TYPE_AHASH,
 		.alg.hash = {
 			.halg.digestsize = SHA1_DIGEST_SIZE,
+			.halg.statesize = sizeof(struct talitos_export_state),
 			.halg.base = {
 				.cra_name = "sha1",
 				.cra_driver_name = "sha1-talitos",
@@ -2488,6 +2540,7 @@ static struct talitos_alg_template drive
 	{	.type = CRYPTO_ALG_TYPE_AHASH,
 		.alg.hash = {
 			.halg.digestsize = SHA224_DIGEST_SIZE,
+			.halg.statesize = sizeof(struct talitos_export_state),
 			.halg.base = {
 				.cra_name = "sha224",
 				.cra_driver_name = "sha224-talitos",
@@ -2503,6 +2556,7 @@ static struct talitos_alg_template drive
 	{	.type = CRYPTO_ALG_TYPE_AHASH,
 		.alg.hash = {
 			.halg.digestsize = SHA256_DIGEST_SIZE,
+			.halg.statesize = sizeof(struct talitos_export_state),
 			.halg.base = {
 				.cra_name = "sha256",
 				.cra_driver_name = "sha256-talitos",
@@ -2518,6 +2572,7 @@ static struct talitos_alg_template drive
 	{	.type = CRYPTO_ALG_TYPE_AHASH,
 		.alg.hash = {
 			.halg.digestsize = SHA384_DIGEST_SIZE,
+			.halg.statesize = sizeof(struct talitos_export_state),
 			.halg.base = {
 				.cra_name = "sha384",
 				.cra_driver_name = "sha384-talitos",
@@ -2533,6 +2588,7 @@ static struct talitos_alg_template drive
 	{	.type = CRYPTO_ALG_TYPE_AHASH,
 		.alg.hash = {
 			.halg.digestsize = SHA512_DIGEST_SIZE,
+			.halg.statesize = sizeof(struct talitos_export_state),
 			.halg.base = {
 				.cra_name = "sha512",
 				.cra_driver_name = "sha512-talitos",
@@ -2548,6 +2604,7 @@ static struct talitos_alg_template drive
 	{	.type = CRYPTO_ALG_TYPE_AHASH,
 		.alg.hash = {
 			.halg.digestsize = MD5_DIGEST_SIZE,
+			.halg.statesize = sizeof(struct talitos_export_state),
 			.halg.base = {
 				.cra_name = "hmac(md5)",
 				.cra_driver_name = "hmac-md5-talitos",
@@ -2563,6 +2620,7 @@ static struct talitos_alg_template drive
 	{	.type = CRYPTO_ALG_TYPE_AHASH,
 		.alg.hash = {
 			.halg.digestsize = SHA1_DIGEST_SIZE,
+			.halg.statesize = sizeof(struct talitos_export_state),
 			.halg.base = {
 				.cra_name = "hmac(sha1)",
 				.cra_driver_name = "hmac-sha1-talitos",
@@ -2578,6 +2636,7 @@ static struct talitos_alg_template drive
 	{	.type = CRYPTO_ALG_TYPE_AHASH,
 		.alg.hash = {
 			.halg.digestsize = SHA224_DIGEST_SIZE,
+			.halg.statesize = sizeof(struct talitos_export_state),
 			.halg.base = {
 				.cra_name = "hmac(sha224)",
 				.cra_driver_name = "hmac-sha224-talitos",
@@ -2593,6 +2652,7 @@ static struct talitos_alg_template drive
 	{	.type = CRYPTO_ALG_TYPE_AHASH,
 		.alg.hash = {
 			.halg.digestsize = SHA256_DIGEST_SIZE,
+			.halg.statesize = sizeof(struct talitos_export_state),
 			.halg.base = {
 				.cra_name = "hmac(sha256)",
 				.cra_driver_name = "hmac-sha256-talitos",
@@ -2608,6 +2668,7 @@ static struct talitos_alg_template drive
 	{	.type = CRYPTO_ALG_TYPE_AHASH,
 		.alg.hash = {
 			.halg.digestsize = SHA384_DIGEST_SIZE,
+			.halg.statesize = sizeof(struct talitos_export_state),
 			.halg.base = {
 				.cra_name = "hmac(sha384)",
 				.cra_driver_name = "hmac-sha384-talitos",
@@ -2623,6 +2684,7 @@ static struct talitos_alg_template drive
 	{	.type = CRYPTO_ALG_TYPE_AHASH,
 		.alg.hash = {
 			.halg.digestsize = SHA512_DIGEST_SIZE,
+			.halg.statesize = sizeof(struct talitos_export_state),
 			.halg.base = {
 				.cra_name = "hmac(sha512)",
 				.cra_driver_name = "hmac-sha512-talitos",
@@ -2814,6 +2876,8 @@ static struct talitos_crypto_alg *talito
 		t_alg->algt.alg.hash.finup = ahash_finup;
 		t_alg->algt.alg.hash.digest = ahash_digest;
 		t_alg->algt.alg.hash.setkey = ahash_setkey;
+		t_alg->algt.alg.hash.import = ahash_import;
+		t_alg->algt.alg.hash.export = ahash_export;
 
 		if (!(priv->features & TALITOS_FTR_HMAC_OK) &&
 		    !strncmp(alg->cra_name, "hmac", 4)) {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/ux500/hash/hash_core.c linux-libre-4.7-gnu/drivers/crypto/ux500/hash/hash_core.c
--- linux-libre-4.6-gnu/drivers/crypto/ux500/hash/hash_core.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/ux500/hash/hash_core.c	2016-07-24 15:23:50.000000000 -0400
@@ -781,7 +781,7 @@ static int hash_process_data(struct hash
 						&device_data->state);
 				memmove(req_ctx->state.buffer,
 					device_data->state.buffer,
-					HASH_BLOCK_SIZE / sizeof(u32));
+					HASH_BLOCK_SIZE);
 				if (ret) {
 					dev_err(device_data->dev,
 						"%s: hash_resume_state() failed!\n",
@@ -832,7 +832,7 @@ static int hash_process_data(struct hash
 
 			memmove(device_data->state.buffer,
 				req_ctx->state.buffer,
-				HASH_BLOCK_SIZE / sizeof(u32));
+				HASH_BLOCK_SIZE);
 			if (ret) {
 				dev_err(device_data->dev, "%s: hash_save_state() failed!\n",
 					__func__);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/vmx/aes_cbc.c linux-libre-4.7-gnu/drivers/crypto/vmx/aes_cbc.c
--- linux-libre-4.6-gnu/drivers/crypto/vmx/aes_cbc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/vmx/aes_cbc.c	2016-07-24 15:23:50.000000000 -0400
@@ -182,7 +182,7 @@ struct crypto_alg p8_aes_cbc_alg = {
 	.cra_name = "cbc(aes)",
 	.cra_driver_name = "p8_aes_cbc",
 	.cra_module = THIS_MODULE,
-	.cra_priority = 1000,
+	.cra_priority = 2000,
 	.cra_type = &crypto_blkcipher_type,
 	.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER | CRYPTO_ALG_NEED_FALLBACK,
 	.cra_alignmask = 0,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/vmx/aes_ctr.c linux-libre-4.7-gnu/drivers/crypto/vmx/aes_ctr.c
--- linux-libre-4.6-gnu/drivers/crypto/vmx/aes_ctr.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/vmx/aes_ctr.c	2016-07-24 15:23:50.000000000 -0400
@@ -166,7 +166,7 @@ struct crypto_alg p8_aes_ctr_alg = {
 	.cra_name = "ctr(aes)",
 	.cra_driver_name = "p8_aes_ctr",
 	.cra_module = THIS_MODULE,
-	.cra_priority = 1000,
+	.cra_priority = 2000,
 	.cra_type = &crypto_blkcipher_type,
 	.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER | CRYPTO_ALG_NEED_FALLBACK,
 	.cra_alignmask = 0,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/crypto/vmx/ppc-xlate.pl linux-libre-4.7-gnu/drivers/crypto/vmx/ppc-xlate.pl
--- linux-libre-4.6-gnu/drivers/crypto/vmx/ppc-xlate.pl	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/crypto/vmx/ppc-xlate.pl	2016-07-24 15:23:50.000000000 -0400
@@ -139,6 +139,26 @@ my $vmr = sub {
     "	vor	$vx,$vy,$vy";
 };
 
+# Some ABIs specify vrsave, special-purpose register #256, as reserved
+# for system use.
+my $no_vrsave = ($flavour =~ /linux-ppc64le/);
+my $mtspr = sub {
+    my ($f,$idx,$ra) = @_;
+    if ($idx == 256 && $no_vrsave) {
+	"	or	$ra,$ra,$ra";
+    } else {
+	"	mtspr	$idx,$ra";
+    }
+};
+my $mfspr = sub {
+    my ($f,$rd,$idx) = @_;
+    if ($idx == 256 && $no_vrsave) {
+	"	li	$rd,-1";
+    } else {
+	"	mfspr	$rd,$idx";
+    }
+};
+
 # PowerISA 2.06 stuff
 sub vsxmem_op {
     my ($f, $vrt, $ra, $rb, $op) = @_;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dax/dax.c linux-libre-4.7-gnu/drivers/dax/dax.c
--- linux-libre-4.6-gnu/drivers/dax/dax.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/dax/dax.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,575 @@
+/*
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ *
+ * 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.
+ */
+#include <linux/pagemap.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/pfn_t.h>
+#include <linux/slab.h>
+#include <linux/dax.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+
+static int dax_major;
+static struct class *dax_class;
+static DEFINE_IDA(dax_minor_ida);
+
+/**
+ * struct dax_region - mapping infrastructure for dax devices
+ * @id: kernel-wide unique region for a memory range
+ * @base: linear address corresponding to @res
+ * @kref: to pin while other agents have a need to do lookups
+ * @dev: parent device backing this region
+ * @align: allocation and mapping alignment for child dax devices
+ * @res: physical address range of the region
+ * @pfn_flags: identify whether the pfns are paged back or not
+ */
+struct dax_region {
+	int id;
+	struct ida ida;
+	void *base;
+	struct kref kref;
+	struct device *dev;
+	unsigned int align;
+	struct resource res;
+	unsigned long pfn_flags;
+};
+
+/**
+ * struct dax_dev - subdivision of a dax region
+ * @region - parent region
+ * @dev - device backing the character device
+ * @kref - enable this data to be tracked in filp->private_data
+ * @alive - !alive + rcu grace period == no new mappings can be established
+ * @id - child id in the region
+ * @num_resources - number of physical address extents in this device
+ * @res - array of physical address ranges
+ */
+struct dax_dev {
+	struct dax_region *region;
+	struct device *dev;
+	struct kref kref;
+	bool alive;
+	int id;
+	int num_resources;
+	struct resource res[0];
+};
+
+static void dax_region_free(struct kref *kref)
+{
+	struct dax_region *dax_region;
+
+	dax_region = container_of(kref, struct dax_region, kref);
+	kfree(dax_region);
+}
+
+void dax_region_put(struct dax_region *dax_region)
+{
+	kref_put(&dax_region->kref, dax_region_free);
+}
+EXPORT_SYMBOL_GPL(dax_region_put);
+
+static void dax_dev_free(struct kref *kref)
+{
+	struct dax_dev *dax_dev;
+
+	dax_dev = container_of(kref, struct dax_dev, kref);
+	dax_region_put(dax_dev->region);
+	kfree(dax_dev);
+}
+
+static void dax_dev_put(struct dax_dev *dax_dev)
+{
+	kref_put(&dax_dev->kref, dax_dev_free);
+}
+
+struct dax_region *alloc_dax_region(struct device *parent, int region_id,
+		struct resource *res, unsigned int align, void *addr,
+		unsigned long pfn_flags)
+{
+	struct dax_region *dax_region;
+
+	dax_region = kzalloc(sizeof(*dax_region), GFP_KERNEL);
+
+	if (!dax_region)
+		return NULL;
+
+	memcpy(&dax_region->res, res, sizeof(*res));
+	dax_region->pfn_flags = pfn_flags;
+	kref_init(&dax_region->kref);
+	dax_region->id = region_id;
+	ida_init(&dax_region->ida);
+	dax_region->align = align;
+	dax_region->dev = parent;
+	dax_region->base = addr;
+
+	return dax_region;
+}
+EXPORT_SYMBOL_GPL(alloc_dax_region);
+
+static ssize_t size_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct dax_dev *dax_dev = dev_get_drvdata(dev);
+	unsigned long long size = 0;
+	int i;
+
+	for (i = 0; i < dax_dev->num_resources; i++)
+		size += resource_size(&dax_dev->res[i]);
+
+	return sprintf(buf, "%llu\n", size);
+}
+static DEVICE_ATTR_RO(size);
+
+static struct attribute *dax_device_attributes[] = {
+	&dev_attr_size.attr,
+	NULL,
+};
+
+static const struct attribute_group dax_device_attribute_group = {
+	.attrs = dax_device_attributes,
+};
+
+static const struct attribute_group *dax_attribute_groups[] = {
+	&dax_device_attribute_group,
+	NULL,
+};
+
+static void unregister_dax_dev(void *_dev)
+{
+	struct device *dev = _dev;
+	struct dax_dev *dax_dev = dev_get_drvdata(dev);
+	struct dax_region *dax_region = dax_dev->region;
+
+	dev_dbg(dev, "%s\n", __func__);
+
+	/*
+	 * Note, rcu is not protecting the liveness of dax_dev, rcu is
+	 * ensuring that any fault handlers that might have seen
+	 * dax_dev->alive == true, have completed.  Any fault handlers
+	 * that start after synchronize_rcu() has started will abort
+	 * upon seeing dax_dev->alive == false.
+	 */
+	dax_dev->alive = false;
+	synchronize_rcu();
+
+	get_device(dev);
+	device_unregister(dev);
+	ida_simple_remove(&dax_region->ida, dax_dev->id);
+	ida_simple_remove(&dax_minor_ida, MINOR(dev->devt));
+	put_device(dev);
+	dax_dev_put(dax_dev);
+}
+
+int devm_create_dax_dev(struct dax_region *dax_region, struct resource *res,
+		int count)
+{
+	struct device *parent = dax_region->dev;
+	struct dax_dev *dax_dev;
+	struct device *dev;
+	int rc, minor;
+	dev_t dev_t;
+
+	dax_dev = kzalloc(sizeof(*dax_dev) + sizeof(*res) * count, GFP_KERNEL);
+	if (!dax_dev)
+		return -ENOMEM;
+	memcpy(dax_dev->res, res, sizeof(*res) * count);
+	dax_dev->num_resources = count;
+	kref_init(&dax_dev->kref);
+	dax_dev->alive = true;
+	dax_dev->region = dax_region;
+	kref_get(&dax_region->kref);
+
+	dax_dev->id = ida_simple_get(&dax_region->ida, 0, 0, GFP_KERNEL);
+	if (dax_dev->id < 0) {
+		rc = dax_dev->id;
+		goto err_id;
+	}
+
+	minor = ida_simple_get(&dax_minor_ida, 0, 0, GFP_KERNEL);
+	if (minor < 0) {
+		rc = minor;
+		goto err_minor;
+	}
+
+	dev_t = MKDEV(dax_major, minor);
+	dev = device_create_with_groups(dax_class, parent, dev_t, dax_dev,
+			dax_attribute_groups, "dax%d.%d", dax_region->id,
+			dax_dev->id);
+	if (IS_ERR(dev)) {
+		rc = PTR_ERR(dev);
+		goto err_create;
+	}
+	dax_dev->dev = dev;
+
+	rc = devm_add_action(dax_region->dev, unregister_dax_dev, dev);
+	if (rc) {
+		unregister_dax_dev(dev);
+		return rc;
+	}
+
+	return 0;
+
+ err_create:
+	ida_simple_remove(&dax_minor_ida, minor);
+ err_minor:
+	ida_simple_remove(&dax_region->ida, dax_dev->id);
+ err_id:
+	dax_dev_put(dax_dev);
+
+	return rc;
+}
+EXPORT_SYMBOL_GPL(devm_create_dax_dev);
+
+/* return an unmapped area aligned to the dax region specified alignment */
+static unsigned long dax_dev_get_unmapped_area(struct file *filp,
+		unsigned long addr, unsigned long len, unsigned long pgoff,
+		unsigned long flags)
+{
+	unsigned long off, off_end, off_align, len_align, addr_align, align;
+	struct dax_dev *dax_dev = filp ? filp->private_data : NULL;
+	struct dax_region *dax_region;
+
+	if (!dax_dev || addr)
+		goto out;
+
+	dax_region = dax_dev->region;
+	align = dax_region->align;
+	off = pgoff << PAGE_SHIFT;
+	off_end = off + len;
+	off_align = round_up(off, align);
+
+	if ((off_end <= off_align) || ((off_end - off_align) < align))
+		goto out;
+
+	len_align = len + align;
+	if ((off + len_align) < off)
+		goto out;
+
+	addr_align = current->mm->get_unmapped_area(filp, addr, len_align,
+			pgoff, flags);
+	if (!IS_ERR_VALUE(addr_align)) {
+		addr_align += (off - addr_align) & (align - 1);
+		return addr_align;
+	}
+ out:
+	return current->mm->get_unmapped_area(filp, addr, len, pgoff, flags);
+}
+
+static int __match_devt(struct device *dev, const void *data)
+{
+	const dev_t *devt = data;
+
+	return dev->devt == *devt;
+}
+
+static struct device *dax_dev_find(dev_t dev_t)
+{
+	return class_find_device(dax_class, NULL, &dev_t, __match_devt);
+}
+
+static int dax_dev_open(struct inode *inode, struct file *filp)
+{
+	struct dax_dev *dax_dev = NULL;
+	struct device *dev;
+
+	dev = dax_dev_find(inode->i_rdev);
+	if (!dev)
+		return -ENXIO;
+
+	device_lock(dev);
+	dax_dev = dev_get_drvdata(dev);
+	if (dax_dev) {
+		dev_dbg(dev, "%s\n", __func__);
+		filp->private_data = dax_dev;
+		kref_get(&dax_dev->kref);
+		inode->i_flags = S_DAX;
+	}
+	device_unlock(dev);
+
+	if (!dax_dev) {
+		put_device(dev);
+		return -ENXIO;
+	}
+	return 0;
+}
+
+static int dax_dev_release(struct inode *inode, struct file *filp)
+{
+	struct dax_dev *dax_dev = filp->private_data;
+	struct device *dev = dax_dev->dev;
+
+	dev_dbg(dax_dev->dev, "%s\n", __func__);
+	dax_dev_put(dax_dev);
+	put_device(dev);
+
+	return 0;
+}
+
+static int check_vma(struct dax_dev *dax_dev, struct vm_area_struct *vma,
+		const char *func)
+{
+	struct dax_region *dax_region = dax_dev->region;
+	struct device *dev = dax_dev->dev;
+	unsigned long mask;
+
+	if (!dax_dev->alive)
+		return -ENXIO;
+
+	/* prevent private / writable mappings from being established */
+	if ((vma->vm_flags & (VM_NORESERVE|VM_SHARED|VM_WRITE)) == VM_WRITE) {
+		dev_info(dev, "%s: %s: fail, attempted private mapping\n",
+				current->comm, func);
+		return -EINVAL;
+	}
+
+	mask = dax_region->align - 1;
+	if (vma->vm_start & mask || vma->vm_end & mask) {
+		dev_info(dev, "%s: %s: fail, unaligned vma (%#lx - %#lx, %#lx)\n",
+				current->comm, func, vma->vm_start, vma->vm_end,
+				mask);
+		return -EINVAL;
+	}
+
+	if ((dax_region->pfn_flags & (PFN_DEV|PFN_MAP)) == PFN_DEV
+			&& (vma->vm_flags & VM_DONTCOPY) == 0) {
+		dev_info(dev, "%s: %s: fail, dax range requires MADV_DONTFORK\n",
+				current->comm, func);
+		return -EINVAL;
+	}
+
+	if (!vma_is_dax(vma)) {
+		dev_info(dev, "%s: %s: fail, vma is not DAX capable\n",
+				current->comm, func);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static phys_addr_t pgoff_to_phys(struct dax_dev *dax_dev, pgoff_t pgoff,
+		unsigned long size)
+{
+	struct resource *res;
+	phys_addr_t phys;
+	int i;
+
+	for (i = 0; i < dax_dev->num_resources; i++) {
+		res = &dax_dev->res[i];
+		phys = pgoff * PAGE_SIZE + res->start;
+		if (phys >= res->start && phys <= res->end)
+			break;
+		pgoff -= PHYS_PFN(resource_size(res));
+	}
+
+	if (i < dax_dev->num_resources) {
+		res = &dax_dev->res[i];
+		if (phys + size - 1 <= res->end)
+			return phys;
+	}
+
+	return -1;
+}
+
+static int __dax_dev_fault(struct dax_dev *dax_dev, struct vm_area_struct *vma,
+		struct vm_fault *vmf)
+{
+	unsigned long vaddr = (unsigned long) vmf->virtual_address;
+	struct device *dev = dax_dev->dev;
+	struct dax_region *dax_region;
+	int rc = VM_FAULT_SIGBUS;
+	phys_addr_t phys;
+	pfn_t pfn;
+
+	if (check_vma(dax_dev, vma, __func__))
+		return VM_FAULT_SIGBUS;
+
+	dax_region = dax_dev->region;
+	if (dax_region->align > PAGE_SIZE) {
+		dev_dbg(dev, "%s: alignment > fault size\n", __func__);
+		return VM_FAULT_SIGBUS;
+	}
+
+	phys = pgoff_to_phys(dax_dev, vmf->pgoff, PAGE_SIZE);
+	if (phys == -1) {
+		dev_dbg(dev, "%s: phys_to_pgoff(%#lx) failed\n", __func__,
+				vmf->pgoff);
+		return VM_FAULT_SIGBUS;
+	}
+
+	pfn = phys_to_pfn_t(phys, dax_region->pfn_flags);
+
+	rc = vm_insert_mixed(vma, vaddr, pfn);
+
+	if (rc == -ENOMEM)
+		return VM_FAULT_OOM;
+	if (rc < 0 && rc != -EBUSY)
+		return VM_FAULT_SIGBUS;
+
+	return VM_FAULT_NOPAGE;
+}
+
+static int dax_dev_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+	int rc;
+	struct file *filp = vma->vm_file;
+	struct dax_dev *dax_dev = filp->private_data;
+
+	dev_dbg(dax_dev->dev, "%s: %s: %s (%#lx - %#lx)\n", __func__,
+			current->comm, (vmf->flags & FAULT_FLAG_WRITE)
+			? "write" : "read", vma->vm_start, vma->vm_end);
+	rcu_read_lock();
+	rc = __dax_dev_fault(dax_dev, vma, vmf);
+	rcu_read_unlock();
+
+	return rc;
+}
+
+static int __dax_dev_pmd_fault(struct dax_dev *dax_dev,
+		struct vm_area_struct *vma, unsigned long addr, pmd_t *pmd,
+		unsigned int flags)
+{
+	unsigned long pmd_addr = addr & PMD_MASK;
+	struct device *dev = dax_dev->dev;
+	struct dax_region *dax_region;
+	phys_addr_t phys;
+	pgoff_t pgoff;
+	pfn_t pfn;
+
+	if (check_vma(dax_dev, vma, __func__))
+		return VM_FAULT_SIGBUS;
+
+	dax_region = dax_dev->region;
+	if (dax_region->align > PMD_SIZE) {
+		dev_dbg(dev, "%s: alignment > fault size\n", __func__);
+		return VM_FAULT_SIGBUS;
+	}
+
+	/* dax pmd mappings require pfn_t_devmap() */
+	if ((dax_region->pfn_flags & (PFN_DEV|PFN_MAP)) != (PFN_DEV|PFN_MAP)) {
+		dev_dbg(dev, "%s: alignment > fault size\n", __func__);
+		return VM_FAULT_SIGBUS;
+	}
+
+	pgoff = linear_page_index(vma, pmd_addr);
+	phys = pgoff_to_phys(dax_dev, pgoff, PAGE_SIZE);
+	if (phys == -1) {
+		dev_dbg(dev, "%s: phys_to_pgoff(%#lx) failed\n", __func__,
+				pgoff);
+		return VM_FAULT_SIGBUS;
+	}
+
+	pfn = phys_to_pfn_t(phys, dax_region->pfn_flags);
+
+	return vmf_insert_pfn_pmd(vma, addr, pmd, pfn,
+			flags & FAULT_FLAG_WRITE);
+}
+
+static int dax_dev_pmd_fault(struct vm_area_struct *vma, unsigned long addr,
+		pmd_t *pmd, unsigned int flags)
+{
+	int rc;
+	struct file *filp = vma->vm_file;
+	struct dax_dev *dax_dev = filp->private_data;
+
+	dev_dbg(dax_dev->dev, "%s: %s: %s (%#lx - %#lx)\n", __func__,
+			current->comm, (flags & FAULT_FLAG_WRITE)
+			? "write" : "read", vma->vm_start, vma->vm_end);
+
+	rcu_read_lock();
+	rc = __dax_dev_pmd_fault(dax_dev, vma, addr, pmd, flags);
+	rcu_read_unlock();
+
+	return rc;
+}
+
+static void dax_dev_vm_open(struct vm_area_struct *vma)
+{
+	struct file *filp = vma->vm_file;
+	struct dax_dev *dax_dev = filp->private_data;
+
+	dev_dbg(dax_dev->dev, "%s\n", __func__);
+	kref_get(&dax_dev->kref);
+}
+
+static void dax_dev_vm_close(struct vm_area_struct *vma)
+{
+	struct file *filp = vma->vm_file;
+	struct dax_dev *dax_dev = filp->private_data;
+
+	dev_dbg(dax_dev->dev, "%s\n", __func__);
+	dax_dev_put(dax_dev);
+}
+
+static const struct vm_operations_struct dax_dev_vm_ops = {
+	.fault = dax_dev_fault,
+	.pmd_fault = dax_dev_pmd_fault,
+	.open = dax_dev_vm_open,
+	.close = dax_dev_vm_close,
+};
+
+static int dax_dev_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+	struct dax_dev *dax_dev = filp->private_data;
+	int rc;
+
+	dev_dbg(dax_dev->dev, "%s\n", __func__);
+
+	rc = check_vma(dax_dev, vma, __func__);
+	if (rc)
+		return rc;
+
+	kref_get(&dax_dev->kref);
+	vma->vm_ops = &dax_dev_vm_ops;
+	vma->vm_flags |= VM_MIXEDMAP | VM_HUGEPAGE;
+	return 0;
+
+}
+
+static const struct file_operations dax_fops = {
+	.llseek = noop_llseek,
+	.owner = THIS_MODULE,
+	.open = dax_dev_open,
+	.release = dax_dev_release,
+	.get_unmapped_area = dax_dev_get_unmapped_area,
+	.mmap = dax_dev_mmap,
+};
+
+static int __init dax_init(void)
+{
+	int rc;
+
+	rc = register_chrdev(0, "dax", &dax_fops);
+	if (rc < 0)
+		return rc;
+	dax_major = rc;
+
+	dax_class = class_create(THIS_MODULE, "dax");
+	if (IS_ERR(dax_class)) {
+		unregister_chrdev(dax_major, "dax");
+		return PTR_ERR(dax_class);
+	}
+
+	return 0;
+}
+
+static void __exit dax_exit(void)
+{
+	class_destroy(dax_class);
+	unregister_chrdev(dax_major, "dax");
+	ida_destroy(&dax_minor_ida);
+}
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_LICENSE("GPL v2");
+subsys_initcall(dax_init);
+module_exit(dax_exit);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dax/dax.h linux-libre-4.7-gnu/drivers/dax/dax.h
--- linux-libre-4.6-gnu/drivers/dax/dax.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/dax/dax.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,24 @@
+/*
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ *
+ * 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.
+ */
+#ifndef __DAX_H__
+#define __DAX_H__
+struct device;
+struct resource;
+struct dax_region;
+void dax_region_put(struct dax_region *dax_region);
+struct dax_region *alloc_dax_region(struct device *parent,
+		int region_id, struct resource *res, unsigned int align,
+		void *addr, unsigned long flags);
+int devm_create_dax_dev(struct dax_region *dax_region, struct resource *res,
+		int count);
+#endif /* __DAX_H__ */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dax/Kconfig linux-libre-4.7-gnu/drivers/dax/Kconfig
--- linux-libre-4.6-gnu/drivers/dax/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/dax/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,26 @@
+menuconfig DEV_DAX
+	tristate "DAX: direct access to differentiated memory"
+	default m if NVDIMM_DAX
+	depends on TRANSPARENT_HUGEPAGE
+	help
+	  Support raw access to differentiated (persistence, bandwidth,
+	  latency...) memory via an mmap(2) capable character
+	  device.  Platform firmware or a device driver may identify a
+	  platform memory resource that is differentiated from the
+	  baseline memory pool.  Mappings of a /dev/daxX.Y device impose
+	  restrictions that make the mapping behavior deterministic.
+
+if DEV_DAX
+
+config DEV_DAX_PMEM
+	tristate "PMEM DAX: direct access to persistent memory"
+	depends on NVDIMM_DAX
+	default DEV_DAX
+	help
+	  Support raw access to persistent memory.  Note that this
+	  driver consumes memory ranges allocated and exported by the
+	  libnvdimm sub-system.
+
+	  Say Y if unsure
+
+endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dax/Makefile linux-libre-4.7-gnu/drivers/dax/Makefile
--- linux-libre-4.6-gnu/drivers/dax/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/dax/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,4 @@
+obj-$(CONFIG_DEV_DAX) += dax.o
+obj-$(CONFIG_DEV_DAX_PMEM) += dax_pmem.o
+
+dax_pmem-y := pmem.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dax/pmem.c linux-libre-4.7-gnu/drivers/dax/pmem.c
--- linux-libre-4.6-gnu/drivers/dax/pmem.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/dax/pmem.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,158 @@
+/*
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ *
+ * 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.
+ */
+#include <linux/percpu-refcount.h>
+#include <linux/memremap.h>
+#include <linux/module.h>
+#include <linux/pfn_t.h>
+#include "../nvdimm/pfn.h"
+#include "../nvdimm/nd.h"
+#include "dax.h"
+
+struct dax_pmem {
+	struct device *dev;
+	struct percpu_ref ref;
+	struct completion cmp;
+};
+
+struct dax_pmem *to_dax_pmem(struct percpu_ref *ref)
+{
+	return container_of(ref, struct dax_pmem, ref);
+}
+
+static void dax_pmem_percpu_release(struct percpu_ref *ref)
+{
+	struct dax_pmem *dax_pmem = to_dax_pmem(ref);
+
+	dev_dbg(dax_pmem->dev, "%s\n", __func__);
+	complete(&dax_pmem->cmp);
+}
+
+static void dax_pmem_percpu_exit(void *data)
+{
+	struct percpu_ref *ref = data;
+	struct dax_pmem *dax_pmem = to_dax_pmem(ref);
+
+	dev_dbg(dax_pmem->dev, "%s\n", __func__);
+	percpu_ref_exit(ref);
+	wait_for_completion(&dax_pmem->cmp);
+}
+
+static void dax_pmem_percpu_kill(void *data)
+{
+	struct percpu_ref *ref = data;
+	struct dax_pmem *dax_pmem = to_dax_pmem(ref);
+
+	dev_dbg(dax_pmem->dev, "%s\n", __func__);
+	percpu_ref_kill(ref);
+}
+
+static int dax_pmem_probe(struct device *dev)
+{
+	int rc;
+	void *addr;
+	struct resource res;
+	struct nd_pfn_sb *pfn_sb;
+	struct dax_pmem *dax_pmem;
+	struct nd_region *nd_region;
+	struct nd_namespace_io *nsio;
+	struct dax_region *dax_region;
+	struct nd_namespace_common *ndns;
+	struct nd_dax *nd_dax = to_nd_dax(dev);
+	struct nd_pfn *nd_pfn = &nd_dax->nd_pfn;
+	struct vmem_altmap __altmap, *altmap = NULL;
+
+	ndns = nvdimm_namespace_common_probe(dev);
+	if (IS_ERR(ndns))
+		return PTR_ERR(ndns);
+	nsio = to_nd_namespace_io(&ndns->dev);
+
+	/* parse the 'pfn' info block via ->rw_bytes */
+	devm_nsio_enable(dev, nsio);
+	altmap = nvdimm_setup_pfn(nd_pfn, &res, &__altmap);
+	if (IS_ERR(altmap))
+		return PTR_ERR(altmap);
+	devm_nsio_disable(dev, nsio);
+
+	pfn_sb = nd_pfn->pfn_sb;
+
+	if (!devm_request_mem_region(dev, nsio->res.start,
+				resource_size(&nsio->res), dev_name(dev))) {
+		dev_warn(dev, "could not reserve region %pR\n", &nsio->res);
+		return -EBUSY;
+	}
+
+	dax_pmem = devm_kzalloc(dev, sizeof(*dax_pmem), GFP_KERNEL);
+	if (!dax_pmem)
+		return -ENOMEM;
+
+	dax_pmem->dev = dev;
+	init_completion(&dax_pmem->cmp);
+	rc = percpu_ref_init(&dax_pmem->ref, dax_pmem_percpu_release, 0,
+			GFP_KERNEL);
+	if (rc)
+		return rc;
+
+	rc = devm_add_action(dev, dax_pmem_percpu_exit, &dax_pmem->ref);
+	if (rc) {
+		dax_pmem_percpu_exit(&dax_pmem->ref);
+		return rc;
+	}
+
+	addr = devm_memremap_pages(dev, &res, &dax_pmem->ref, altmap);
+	if (IS_ERR(addr))
+		return PTR_ERR(addr);
+
+	rc = devm_add_action(dev, dax_pmem_percpu_kill, &dax_pmem->ref);
+	if (rc) {
+		dax_pmem_percpu_kill(&dax_pmem->ref);
+		return rc;
+	}
+
+	nd_region = to_nd_region(dev->parent);
+	dax_region = alloc_dax_region(dev, nd_region->id, &res,
+			le32_to_cpu(pfn_sb->align), addr, PFN_DEV|PFN_MAP);
+	if (!dax_region)
+		return -ENOMEM;
+
+	/* TODO: support for subdividing a dax region... */
+	rc = devm_create_dax_dev(dax_region, &res, 1);
+
+	/* child dax_dev instances now own the lifetime of the dax_region */
+	dax_region_put(dax_region);
+
+	return rc;
+}
+
+static struct nd_device_driver dax_pmem_driver = {
+	.probe = dax_pmem_probe,
+	.drv = {
+		.name = "dax_pmem",
+	},
+	.type = ND_DRIVER_DAX_PMEM,
+};
+
+static int __init dax_pmem_init(void)
+{
+	return nd_driver_register(&dax_pmem_driver);
+}
+module_init(dax_pmem_init);
+
+static void __exit dax_pmem_exit(void)
+{
+	driver_unregister(&dax_pmem_driver.drv);
+}
+module_exit(dax_pmem_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Intel Corporation");
+MODULE_ALIAS_ND_DEVICE(ND_DEVICE_DAX_PMEM);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/devfreq/devfreq.c linux-libre-4.7-gnu/drivers/devfreq/devfreq.c
--- linux-libre-4.6-gnu/drivers/devfreq/devfreq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/devfreq/devfreq.c	2016-07-24 15:23:50.000000000 -0400
@@ -25,6 +25,7 @@
 #include <linux/list.h>
 #include <linux/printk.h>
 #include <linux/hrtimer.h>
+#include <linux/of.h>
 #include "governor.h"
 
 static struct class *devfreq_class;
@@ -188,6 +189,29 @@ static struct devfreq_governor *find_dev
 	return ERR_PTR(-ENODEV);
 }
 
+static int devfreq_notify_transition(struct devfreq *devfreq,
+		struct devfreq_freqs *freqs, unsigned int state)
+{
+	if (!devfreq)
+		return -EINVAL;
+
+	switch (state) {
+	case DEVFREQ_PRECHANGE:
+		srcu_notifier_call_chain(&devfreq->transition_notifier_list,
+				DEVFREQ_PRECHANGE, freqs);
+		break;
+
+	case DEVFREQ_POSTCHANGE:
+		srcu_notifier_call_chain(&devfreq->transition_notifier_list,
+				DEVFREQ_POSTCHANGE, freqs);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 /* Load monitoring helper functions for governors use */
 
 /**
@@ -199,7 +223,8 @@ static struct devfreq_governor *find_dev
  */
 int update_devfreq(struct devfreq *devfreq)
 {
-	unsigned long freq;
+	struct devfreq_freqs freqs;
+	unsigned long freq, cur_freq;
 	int err = 0;
 	u32 flags = 0;
 
@@ -233,9 +258,24 @@ int update_devfreq(struct devfreq *devfr
 		flags |= DEVFREQ_FLAG_LEAST_UPPER_BOUND; /* Use LUB */
 	}
 
+	if (devfreq->profile->get_cur_freq)
+		devfreq->profile->get_cur_freq(devfreq->dev.parent, &cur_freq);
+	else
+		cur_freq = devfreq->previous_freq;
+
+	freqs.old = cur_freq;
+	freqs.new = freq;
+	devfreq_notify_transition(devfreq, &freqs, DEVFREQ_PRECHANGE);
+
 	err = devfreq->profile->target(devfreq->dev.parent, &freq, flags);
-	if (err)
+	if (err) {
+		freqs.new = cur_freq;
+		devfreq_notify_transition(devfreq, &freqs, DEVFREQ_POSTCHANGE);
 		return err;
+	}
+
+	freqs.new = freq;
+	devfreq_notify_transition(devfreq, &freqs, DEVFREQ_POSTCHANGE);
 
 	if (devfreq->profile->freq_table)
 		if (devfreq_update_status(devfreq, freq))
@@ -515,6 +555,7 @@ struct devfreq *devfreq_add_device(struc
 	devfreq->profile = profile;
 	strncpy(devfreq->governor_name, governor_name, DEVFREQ_NAME_LEN);
 	devfreq->previous_freq = profile->initial_freq;
+	devfreq->last_status.current_frequency = profile->initial_freq;
 	devfreq->data = data;
 	devfreq->nb.notifier_call = devfreq_notifier_call;
 
@@ -524,22 +565,23 @@ struct devfreq *devfreq_add_device(struc
 		mutex_lock(&devfreq->lock);
 	}
 
-	devfreq->trans_table =	devm_kzalloc(dev, sizeof(unsigned int) *
+	dev_set_name(&devfreq->dev, "%s", dev_name(dev));
+	err = device_register(&devfreq->dev);
+	if (err) {
+		mutex_unlock(&devfreq->lock);
+		goto err_out;
+	}
+
+	devfreq->trans_table =	devm_kzalloc(&devfreq->dev, sizeof(unsigned int) *
 						devfreq->profile->max_state *
 						devfreq->profile->max_state,
 						GFP_KERNEL);
-	devfreq->time_in_state = devm_kzalloc(dev, sizeof(unsigned long) *
+	devfreq->time_in_state = devm_kzalloc(&devfreq->dev, sizeof(unsigned long) *
 						devfreq->profile->max_state,
 						GFP_KERNEL);
 	devfreq->last_stat_updated = jiffies;
 
-	dev_set_name(&devfreq->dev, "%s", dev_name(dev));
-	err = device_register(&devfreq->dev);
-	if (err) {
-		put_device(&devfreq->dev);
-		mutex_unlock(&devfreq->lock);
-		goto err_out;
-	}
+	srcu_init_notifier_head(&devfreq->transition_notifier_list);
 
 	mutex_unlock(&devfreq->lock);
 
@@ -564,7 +606,6 @@ struct devfreq *devfreq_add_device(struc
 err_init:
 	list_del(&devfreq->node);
 	device_unregister(&devfreq->dev);
-	kfree(devfreq);
 err_out:
 	return ERR_PTR(err);
 }
@@ -582,7 +623,6 @@ int devfreq_remove_device(struct devfreq
 		return -EINVAL;
 
 	device_unregister(&devfreq->dev);
-	put_device(&devfreq->dev);
 
 	return 0;
 }
@@ -639,6 +679,49 @@ struct devfreq *devm_devfreq_add_device(
 }
 EXPORT_SYMBOL(devm_devfreq_add_device);
 
+#ifdef CONFIG_OF
+/*
+ * devfreq_get_devfreq_by_phandle - Get the devfreq device from devicetree
+ * @dev - instance to the given device
+ * @index - index into list of devfreq
+ *
+ * return the instance of devfreq device
+ */
+struct devfreq *devfreq_get_devfreq_by_phandle(struct device *dev, int index)
+{
+	struct device_node *node;
+	struct devfreq *devfreq;
+
+	if (!dev)
+		return ERR_PTR(-EINVAL);
+
+	if (!dev->of_node)
+		return ERR_PTR(-EINVAL);
+
+	node = of_parse_phandle(dev->of_node, "devfreq", index);
+	if (!node)
+		return ERR_PTR(-ENODEV);
+
+	mutex_lock(&devfreq_list_lock);
+	list_for_each_entry(devfreq, &devfreq_list, node) {
+		if (devfreq->dev.parent
+			&& devfreq->dev.parent->of_node == node) {
+			mutex_unlock(&devfreq_list_lock);
+			return devfreq;
+		}
+	}
+	mutex_unlock(&devfreq_list_lock);
+
+	return ERR_PTR(-EPROBE_DEFER);
+}
+#else
+struct devfreq *devfreq_get_devfreq_by_phandle(struct device *dev, int index)
+{
+	return ERR_PTR(-ENODEV);
+}
+#endif /* CONFIG_OF */
+EXPORT_SYMBOL_GPL(devfreq_get_devfreq_by_phandle);
+
 /**
  * devm_devfreq_remove_device() - Resource-managed devfreq_remove_device()
  * @dev:	the device to add devfreq feature.
@@ -1266,6 +1349,129 @@ void devm_devfreq_unregister_opp_notifie
 }
 EXPORT_SYMBOL(devm_devfreq_unregister_opp_notifier);
 
+/**
+ * devfreq_register_notifier() - Register a driver with devfreq
+ * @devfreq:	The devfreq object.
+ * @nb:		The notifier block to register.
+ * @list:	DEVFREQ_TRANSITION_NOTIFIER.
+ */
+int devfreq_register_notifier(struct devfreq *devfreq,
+				struct notifier_block *nb,
+				unsigned int list)
+{
+	int ret = 0;
+
+	if (!devfreq)
+		return -EINVAL;
+
+	switch (list) {
+	case DEVFREQ_TRANSITION_NOTIFIER:
+		ret = srcu_notifier_chain_register(
+				&devfreq->transition_notifier_list, nb);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(devfreq_register_notifier);
+
+/*
+ * devfreq_unregister_notifier() - Unregister a driver with devfreq
+ * @devfreq:	The devfreq object.
+ * @nb:		The notifier block to be unregistered.
+ * @list:	DEVFREQ_TRANSITION_NOTIFIER.
+ */
+int devfreq_unregister_notifier(struct devfreq *devfreq,
+				struct notifier_block *nb,
+				unsigned int list)
+{
+	int ret = 0;
+
+	if (!devfreq)
+		return -EINVAL;
+
+	switch (list) {
+	case DEVFREQ_TRANSITION_NOTIFIER:
+		ret = srcu_notifier_chain_unregister(
+				&devfreq->transition_notifier_list, nb);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(devfreq_unregister_notifier);
+
+struct devfreq_notifier_devres {
+	struct devfreq *devfreq;
+	struct notifier_block *nb;
+	unsigned int list;
+};
+
+static void devm_devfreq_notifier_release(struct device *dev, void *res)
+{
+	struct devfreq_notifier_devres *this = res;
+
+	devfreq_unregister_notifier(this->devfreq, this->nb, this->list);
+}
+
+/**
+ * devm_devfreq_register_notifier()
+	- Resource-managed devfreq_register_notifier()
+ * @dev:	The devfreq user device. (parent of devfreq)
+ * @devfreq:	The devfreq object.
+ * @nb:		The notifier block to be unregistered.
+ * @list:	DEVFREQ_TRANSITION_NOTIFIER.
+ */
+int devm_devfreq_register_notifier(struct device *dev,
+				struct devfreq *devfreq,
+				struct notifier_block *nb,
+				unsigned int list)
+{
+	struct devfreq_notifier_devres *ptr;
+	int ret;
+
+	ptr = devres_alloc(devm_devfreq_notifier_release, sizeof(*ptr),
+				GFP_KERNEL);
+	if (!ptr)
+		return -ENOMEM;
+
+	ret = devfreq_register_notifier(devfreq, nb, list);
+	if (ret) {
+		devres_free(ptr);
+		return ret;
+	}
+
+	ptr->devfreq = devfreq;
+	ptr->nb = nb;
+	ptr->list = list;
+	devres_add(dev, ptr);
+
+	return 0;
+}
+EXPORT_SYMBOL(devm_devfreq_register_notifier);
+
+/**
+ * devm_devfreq_unregister_notifier()
+	- Resource-managed devfreq_unregister_notifier()
+ * @dev:	The devfreq user device. (parent of devfreq)
+ * @devfreq:	The devfreq object.
+ * @nb:		The notifier block to be unregistered.
+ * @list:	DEVFREQ_TRANSITION_NOTIFIER.
+ */
+void devm_devfreq_unregister_notifier(struct device *dev,
+				struct devfreq *devfreq,
+				struct notifier_block *nb,
+				unsigned int list)
+{
+	WARN_ON(devres_release(dev, devm_devfreq_notifier_release,
+			       devm_devfreq_dev_match, devfreq));
+}
+EXPORT_SYMBOL(devm_devfreq_unregister_notifier);
+
 MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
 MODULE_DESCRIPTION("devfreq class support");
 MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/devfreq/devfreq-event.c linux-libre-4.7-gnu/drivers/devfreq/devfreq-event.c
--- linux-libre-4.6-gnu/drivers/devfreq/devfreq-event.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/devfreq/devfreq-event.c	2016-07-24 15:23:50.000000000 -0400
@@ -235,6 +235,11 @@ struct devfreq_event_dev *devfreq_event_
 
 	mutex_lock(&devfreq_event_list_lock);
 	list_for_each_entry(edev, &devfreq_event_list, node) {
+		if (edev->dev.parent && edev->dev.parent->of_node == node)
+			goto out;
+	}
+
+	list_for_each_entry(edev, &devfreq_event_list, node) {
 		if (!strcmp(edev->desc->name, node->name))
 			goto out;
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/devfreq/event/exynos-nocp.c linux-libre-4.7-gnu/drivers/devfreq/event/exynos-nocp.c
--- linux-libre-4.6-gnu/drivers/devfreq/event/exynos-nocp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/devfreq/event/exynos-nocp.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,301 @@
+/*
+ * exynos-nocp.c - EXYNOS NoC (Network On Chip) Probe support
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Author : Chanwoo Choi <cw00.choi@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/devfreq-event.h>
+#include <linux/kernel.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include "exynos-nocp.h"
+
+struct exynos_nocp {
+	struct devfreq_event_dev *edev;
+	struct devfreq_event_desc desc;
+
+	struct device *dev;
+
+	struct regmap *regmap;
+	struct clk *clk;
+};
+
+/*
+ * The devfreq-event ops structure for nocp probe.
+ */
+static int exynos_nocp_set_event(struct devfreq_event_dev *edev)
+{
+	struct exynos_nocp *nocp = devfreq_event_get_drvdata(edev);
+	int ret;
+
+	/* Disable NoC probe */
+	ret = regmap_update_bits(nocp->regmap, NOCP_MAIN_CTL,
+				NOCP_MAIN_CTL_STATEN_MASK, 0);
+	if (ret < 0) {
+		dev_err(nocp->dev, "failed to disable the NoC probe device\n");
+		return ret;
+	}
+
+	/* Set a statistics dump period to 0 */
+	ret = regmap_write(nocp->regmap, NOCP_STAT_PERIOD, 0x0);
+	if (ret < 0)
+		goto out;
+
+	/* Set the IntEvent fields of *_SRC */
+	ret = regmap_update_bits(nocp->regmap, NOCP_COUNTERS_0_SRC,
+				NOCP_CNT_SRC_INTEVENT_MASK,
+				NOCP_CNT_SRC_INTEVENT_BYTE_MASK);
+	if (ret < 0)
+		goto out;
+
+	ret = regmap_update_bits(nocp->regmap, NOCP_COUNTERS_1_SRC,
+				NOCP_CNT_SRC_INTEVENT_MASK,
+				NOCP_CNT_SRC_INTEVENT_CHAIN_MASK);
+	if (ret < 0)
+		goto out;
+
+	ret = regmap_update_bits(nocp->regmap, NOCP_COUNTERS_2_SRC,
+				NOCP_CNT_SRC_INTEVENT_MASK,
+				NOCP_CNT_SRC_INTEVENT_CYCLE_MASK);
+	if (ret < 0)
+		goto out;
+
+	ret = regmap_update_bits(nocp->regmap, NOCP_COUNTERS_3_SRC,
+				NOCP_CNT_SRC_INTEVENT_MASK,
+				NOCP_CNT_SRC_INTEVENT_CHAIN_MASK);
+	if (ret < 0)
+		goto out;
+
+
+	/* Set an alarm with a max/min value of 0 to generate StatALARM */
+	ret = regmap_write(nocp->regmap, NOCP_STAT_ALARM_MIN, 0x0);
+	if (ret < 0)
+		goto out;
+
+	ret = regmap_write(nocp->regmap, NOCP_STAT_ALARM_MAX, 0x0);
+	if (ret < 0)
+		goto out;
+
+	/* Set AlarmMode */
+	ret = regmap_update_bits(nocp->regmap, NOCP_COUNTERS_0_ALARM_MODE,
+				NOCP_CNT_ALARM_MODE_MASK,
+				NOCP_CNT_ALARM_MODE_MIN_MAX_MASK);
+	if (ret < 0)
+		goto out;
+
+	ret = regmap_update_bits(nocp->regmap, NOCP_COUNTERS_1_ALARM_MODE,
+				NOCP_CNT_ALARM_MODE_MASK,
+				NOCP_CNT_ALARM_MODE_MIN_MAX_MASK);
+	if (ret < 0)
+		goto out;
+
+	ret = regmap_update_bits(nocp->regmap, NOCP_COUNTERS_2_ALARM_MODE,
+				NOCP_CNT_ALARM_MODE_MASK,
+				NOCP_CNT_ALARM_MODE_MIN_MAX_MASK);
+	if (ret < 0)
+		goto out;
+
+	ret = regmap_update_bits(nocp->regmap, NOCP_COUNTERS_3_ALARM_MODE,
+				NOCP_CNT_ALARM_MODE_MASK,
+				NOCP_CNT_ALARM_MODE_MIN_MAX_MASK);
+	if (ret < 0)
+		goto out;
+
+	/* Enable the measurements by setting AlarmEn and StatEn */
+	ret = regmap_update_bits(nocp->regmap, NOCP_MAIN_CTL,
+			NOCP_MAIN_CTL_STATEN_MASK | NOCP_MAIN_CTL_ALARMEN_MASK,
+			NOCP_MAIN_CTL_STATEN_MASK | NOCP_MAIN_CTL_ALARMEN_MASK);
+	if (ret < 0)
+		goto out;
+
+	/* Set GlobalEN */
+	ret = regmap_update_bits(nocp->regmap, NOCP_CFG_CTL,
+				NOCP_CFG_CTL_GLOBALEN_MASK,
+				NOCP_CFG_CTL_GLOBALEN_MASK);
+	if (ret < 0)
+		goto out;
+
+	/* Enable NoC probe */
+	ret = regmap_update_bits(nocp->regmap, NOCP_MAIN_CTL,
+				NOCP_MAIN_CTL_STATEN_MASK,
+				NOCP_MAIN_CTL_STATEN_MASK);
+	if (ret < 0)
+		goto out;
+
+	return 0;
+
+out:
+	/* Reset NoC probe */
+	if (regmap_update_bits(nocp->regmap, NOCP_MAIN_CTL,
+				NOCP_MAIN_CTL_STATEN_MASK, 0)) {
+		dev_err(nocp->dev, "Failed to reset NoC probe device\n");
+	}
+
+	return ret;
+}
+
+static int exynos_nocp_get_event(struct devfreq_event_dev *edev,
+				struct devfreq_event_data *edata)
+{
+	struct exynos_nocp *nocp = devfreq_event_get_drvdata(edev);
+	unsigned int counter[4];
+	int ret;
+
+	/* Read cycle count */
+	ret = regmap_read(nocp->regmap, NOCP_COUNTERS_0_VAL, &counter[0]);
+	if (ret < 0)
+		goto out;
+
+	ret = regmap_read(nocp->regmap, NOCP_COUNTERS_1_VAL, &counter[1]);
+	if (ret < 0)
+		goto out;
+
+	ret = regmap_read(nocp->regmap, NOCP_COUNTERS_2_VAL, &counter[2]);
+	if (ret < 0)
+		goto out;
+
+	ret = regmap_read(nocp->regmap, NOCP_COUNTERS_3_VAL, &counter[3]);
+	if (ret < 0)
+		goto out;
+
+	edata->load_count = ((counter[1] << 16) | counter[0]);
+	edata->total_count = ((counter[3] << 16) | counter[2]);
+
+	dev_dbg(&edev->dev, "%s (event: %ld/%ld)\n", edev->desc->name,
+					edata->load_count, edata->total_count);
+
+	return 0;
+
+out:
+	edata->load_count = 0;
+	edata->total_count = 0;
+
+	dev_err(nocp->dev, "Failed to read the counter of NoC probe device\n");
+
+	return ret;
+}
+
+static const struct devfreq_event_ops exynos_nocp_ops = {
+	.set_event = exynos_nocp_set_event,
+	.get_event = exynos_nocp_get_event,
+};
+
+static const struct of_device_id exynos_nocp_id_match[] = {
+	{ .compatible = "samsung,exynos5420-nocp", },
+	{ /* sentinel */ },
+};
+
+static struct regmap_config exynos_nocp_regmap_config = {
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4,
+	.max_register = NOCP_COUNTERS_3_VAL,
+};
+
+static int exynos_nocp_parse_dt(struct platform_device *pdev,
+				struct exynos_nocp *nocp)
+{
+	struct device *dev = nocp->dev;
+	struct device_node *np = dev->of_node;
+	struct resource *res;
+	void __iomem *base;
+
+	if (!np) {
+		dev_err(dev, "failed to find devicetree node\n");
+		return -EINVAL;
+	}
+
+	nocp->clk = devm_clk_get(dev, "nocp");
+	if (IS_ERR(nocp->clk))
+		nocp->clk = NULL;
+
+	/* Maps the memory mapped IO to control nocp register */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	exynos_nocp_regmap_config.max_register = resource_size(res) - 4;
+
+	nocp->regmap = devm_regmap_init_mmio(dev, base,
+					&exynos_nocp_regmap_config);
+	if (IS_ERR(nocp->regmap)) {
+		dev_err(dev, "failed to initialize regmap\n");
+		return PTR_ERR(nocp->regmap);
+	}
+
+	return 0;
+}
+
+static int exynos_nocp_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct exynos_nocp *nocp;
+	int ret;
+
+	nocp = devm_kzalloc(&pdev->dev, sizeof(*nocp), GFP_KERNEL);
+	if (!nocp)
+		return -ENOMEM;
+
+	nocp->dev = &pdev->dev;
+
+	/* Parse dt data to get resource */
+	ret = exynos_nocp_parse_dt(pdev, nocp);
+	if (ret < 0) {
+		dev_err(&pdev->dev,
+			"failed to parse devicetree for resource\n");
+		return ret;
+	}
+
+	/* Add devfreq-event device to measure the bandwidth of NoC */
+	nocp->desc.ops = &exynos_nocp_ops;
+	nocp->desc.driver_data = nocp;
+	nocp->desc.name = np->full_name;
+	nocp->edev = devm_devfreq_event_add_edev(&pdev->dev, &nocp->desc);
+	if (IS_ERR(nocp->edev)) {
+		dev_err(&pdev->dev,
+			"failed to add devfreq-event device\n");
+		return PTR_ERR(nocp->edev);
+	}
+	platform_set_drvdata(pdev, nocp);
+
+	clk_prepare_enable(nocp->clk);
+
+	pr_info("exynos-nocp: new NoC Probe device registered: %s\n",
+			dev_name(dev));
+
+	return 0;
+}
+
+static int exynos_nocp_remove(struct platform_device *pdev)
+{
+	struct exynos_nocp *nocp = platform_get_drvdata(pdev);
+
+	clk_disable_unprepare(nocp->clk);
+
+	return 0;
+}
+
+static struct platform_driver exynos_nocp_driver = {
+	.probe	= exynos_nocp_probe,
+	.remove	= exynos_nocp_remove,
+	.driver = {
+		.name	= "exynos-nocp",
+		.of_match_table = exynos_nocp_id_match,
+	},
+};
+module_platform_driver(exynos_nocp_driver);
+
+MODULE_DESCRIPTION("Exynos NoC (Network on Chip) Probe driver");
+MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/devfreq/event/exynos-nocp.h linux-libre-4.7-gnu/drivers/devfreq/event/exynos-nocp.h
--- linux-libre-4.6-gnu/drivers/devfreq/event/exynos-nocp.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/devfreq/event/exynos-nocp.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,78 @@
+/*
+ * exynos-nocp.h - EXYNOS NoC (Network on Chip) Probe header file
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Author : Chanwoo Choi <cw00.choi@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __EXYNOS_NOCP_H__
+#define __EXYNOS_NOCP_H__
+
+enum nocp_reg {
+	NOCP_ID_REVISION_ID		= 0x04,
+	NOCP_MAIN_CTL			= 0x08,
+	NOCP_CFG_CTL			= 0x0C,
+
+	NOCP_STAT_PERIOD		= 0x24,
+	NOCP_STAT_GO			= 0x28,
+	NOCP_STAT_ALARM_MIN		= 0x2C,
+	NOCP_STAT_ALARM_MAX		= 0x30,
+	NOCP_STAT_ALARM_STATUS		= 0x34,
+	NOCP_STAT_ALARM_CLR		= 0x38,
+
+	NOCP_COUNTERS_0_SRC		= 0x138,
+	NOCP_COUNTERS_0_ALARM_MODE	= 0x13C,
+	NOCP_COUNTERS_0_VAL		= 0x140,
+
+	NOCP_COUNTERS_1_SRC		= 0x14C,
+	NOCP_COUNTERS_1_ALARM_MODE	= 0x150,
+	NOCP_COUNTERS_1_VAL		= 0x154,
+
+	NOCP_COUNTERS_2_SRC		= 0x160,
+	NOCP_COUNTERS_2_ALARM_MODE	= 0x164,
+	NOCP_COUNTERS_2_VAL		= 0x168,
+
+	NOCP_COUNTERS_3_SRC		= 0x174,
+	NOCP_COUNTERS_3_ALARM_MODE	= 0x178,
+	NOCP_COUNTERS_3_VAL		= 0x17C,
+};
+
+/* NOCP_MAIN_CTL register */
+#define NOCP_MAIN_CTL_ERREN_MASK		BIT(0)
+#define NOCP_MAIN_CTL_TRACEEN_MASK		BIT(1)
+#define NOCP_MAIN_CTL_PAYLOADEN_MASK		BIT(2)
+#define NOCP_MAIN_CTL_STATEN_MASK		BIT(3)
+#define NOCP_MAIN_CTL_ALARMEN_MASK		BIT(4)
+#define NOCP_MAIN_CTL_STATCONDDUMP_MASK	BIT(5)
+#define NOCP_MAIN_CTL_INTRUSIVEMODE_MASK	BIT(6)
+
+/* NOCP_CFG_CTL register */
+#define NOCP_CFG_CTL_GLOBALEN_MASK		BIT(0)
+#define NOCP_CFG_CTL_ACTIVE_MASK		BIT(1)
+
+/* NOCP_COUNTERS_x_SRC register */
+#define NOCP_CNT_SRC_INTEVENT_SHIFT		0
+#define NOCP_CNT_SRC_INTEVENT_MASK		(0x1F << NOCP_CNT_SRC_INTEVENT_SHIFT)
+#define NOCP_CNT_SRC_INTEVENT_OFF_MASK		(0x0 << NOCP_CNT_SRC_INTEVENT_SHIFT)
+#define NOCP_CNT_SRC_INTEVENT_CYCLE_MASK	(0x1 << NOCP_CNT_SRC_INTEVENT_SHIFT)
+#define NOCP_CNT_SRC_INTEVENT_IDLE_MASK		(0x2 << NOCP_CNT_SRC_INTEVENT_SHIFT)
+#define NOCP_CNT_SRC_INTEVENT_XFER_MASK		(0x3 << NOCP_CNT_SRC_INTEVENT_SHIFT)
+#define NOCP_CNT_SRC_INTEVENT_BUSY_MASK		(0x4 << NOCP_CNT_SRC_INTEVENT_SHIFT)
+#define NOCP_CNT_SRC_INTEVENT_WAIT_MASK		(0x5 << NOCP_CNT_SRC_INTEVENT_SHIFT)
+#define NOCP_CNT_SRC_INTEVENT_PKT_MASK		(0x6 << NOCP_CNT_SRC_INTEVENT_SHIFT)
+#define NOCP_CNT_SRC_INTEVENT_BYTE_MASK		(0x8 << NOCP_CNT_SRC_INTEVENT_SHIFT)
+#define NOCP_CNT_SRC_INTEVENT_CHAIN_MASK	(0x10 << NOCP_CNT_SRC_INTEVENT_SHIFT)
+
+/* NOCP_COUNTERS_x_ALARM_MODE register */
+#define NOCP_CNT_ALARM_MODE_SHIFT		0
+#define NOCP_CNT_ALARM_MODE_MASK		(0x3 << NOCP_CNT_ALARM_MODE_SHIFT)
+#define NOCP_CNT_ALARM_MODE_OFF_MASK		(0x0 << NOCP_CNT_ALARM_MODE_SHIFT)
+#define NOCP_CNT_ALARM_MODE_MIN_MASK		(0x1 << NOCP_CNT_ALARM_MODE_SHIFT)
+#define NOCP_CNT_ALARM_MODE_MAX_MASK		(0x2 << NOCP_CNT_ALARM_MODE_SHIFT)
+#define NOCP_CNT_ALARM_MODE_MIN_MAX_MASK	(0x3 << NOCP_CNT_ALARM_MODE_SHIFT)
+
+#endif /* __EXYNOS_NOCP_H__ */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/devfreq/event/Kconfig linux-libre-4.7-gnu/drivers/devfreq/event/Kconfig
--- linux-libre-4.6-gnu/drivers/devfreq/event/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/devfreq/event/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -13,6 +13,14 @@ menuconfig PM_DEVFREQ_EVENT
 
 if PM_DEVFREQ_EVENT
 
+config DEVFREQ_EVENT_EXYNOS_NOCP
+	bool "EXYNOS NoC (Network On Chip) Probe DEVFREQ event Driver"
+	depends on ARCH_EXYNOS
+	select PM_OPP
+	help
+	  This add the devfreq-event driver for Exynos SoC. It provides NoC
+	  (Network on Chip) Probe counters to measure the bandwidth of AXI bus.
+
 config DEVFREQ_EVENT_EXYNOS_PPMU
 	bool "EXYNOS PPMU (Platform Performance Monitoring Unit) DEVFREQ event Driver"
 	depends on ARCH_EXYNOS
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/devfreq/event/Makefile linux-libre-4.7-gnu/drivers/devfreq/event/Makefile
--- linux-libre-4.6-gnu/drivers/devfreq/event/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/devfreq/event/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -1,2 +1,4 @@
 # Exynos DEVFREQ Event Drivers
+
+obj-$(CONFIG_DEVFREQ_EVENT_EXYNOS_NOCP) += exynos-nocp.o
 obj-$(CONFIG_DEVFREQ_EVENT_EXYNOS_PPMU) += exynos-ppmu.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/devfreq/exynos/exynos4_bus.c linux-libre-4.7-gnu/drivers/devfreq/exynos/exynos4_bus.c
--- linux-libre-4.6-gnu/drivers/devfreq/exynos/exynos4_bus.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/devfreq/exynos/exynos4_bus.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1055 +0,0 @@
-/* drivers/devfreq/exynos4210_memorybus.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *	MyungJoo Ham <myungjoo.ham@samsung.com>
- *
- * EXYNOS4 - Memory/Bus clock frequency scaling support in DEVFREQ framework
- *	This version supports EXYNOS4210 only. This changes bus frequencies
- *	and vddint voltages. Exynos4412/4212 should be able to be supported
- *	with minor modifications.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-#include <linux/suspend.h>
-#include <linux/pm_opp.h>
-#include <linux/devfreq.h>
-#include <linux/platform_device.h>
-#include <linux/regulator/consumer.h>
-#include <linux/module.h>
-
-#include <mach/map.h>
-
-#include "exynos_ppmu.h"
-#include "exynos4_bus.h"
-
-#define MAX_SAFEVOLT	1200000 /* 1.2V */
-
-enum exynos4_busf_type {
-	TYPE_BUSF_EXYNOS4210,
-	TYPE_BUSF_EXYNOS4x12,
-};
-
-/* Assume that the bus is saturated if the utilization is 40% */
-#define BUS_SATURATION_RATIO	40
-
-enum busclk_level_idx {
-	LV_0 = 0,
-	LV_1,
-	LV_2,
-	LV_3,
-	LV_4,
-	_LV_END
-};
-
-enum exynos_ppmu_idx {
-	PPMU_DMC0,
-	PPMU_DMC1,
-	PPMU_END,
-};
-
-#define EX4210_LV_MAX	LV_2
-#define EX4x12_LV_MAX	LV_4
-#define EX4210_LV_NUM	(LV_2 + 1)
-#define EX4x12_LV_NUM	(LV_4 + 1)
-
-/**
- * struct busfreq_opp_info - opp information for bus
- * @rate:	Frequency in hertz
- * @volt:	Voltage in microvolts corresponding to this OPP
- */
-struct busfreq_opp_info {
-	unsigned long rate;
-	unsigned long volt;
-};
-
-struct busfreq_data {
-	enum exynos4_busf_type type;
-	struct device *dev;
-	struct devfreq *devfreq;
-	bool disabled;
-	struct regulator *vdd_int;
-	struct regulator *vdd_mif; /* Exynos4412/4212 only */
-	struct busfreq_opp_info curr_oppinfo;
-	struct busfreq_ppmu_data ppmu_data;
-
-	struct notifier_block pm_notifier;
-	struct mutex lock;
-
-	/* Dividers calculated at boot/probe-time */
-	unsigned int dmc_divtable[_LV_END]; /* DMC0 */
-	unsigned int top_divtable[_LV_END];
-};
-
-/* 4210 controls clock of mif and voltage of int */
-static struct bus_opp_table exynos4210_busclk_table[] = {
-	{LV_0, 400000, 1150000},
-	{LV_1, 267000, 1050000},
-	{LV_2, 133000, 1025000},
-	{0, 0, 0},
-};
-
-/*
- * MIF is the main control knob clock for Exynos4x12 MIF/INT
- * clock and voltage of both mif/int are controlled.
- */
-static struct bus_opp_table exynos4x12_mifclk_table[] = {
-	{LV_0, 400000, 1100000},
-	{LV_1, 267000, 1000000},
-	{LV_2, 160000, 950000},
-	{LV_3, 133000, 950000},
-	{LV_4, 100000, 950000},
-	{0, 0, 0},
-};
-
-/*
- * INT is not the control knob of 4x12. LV_x is not meant to represent
- * the current performance. (MIF does)
- */
-static struct bus_opp_table exynos4x12_intclk_table[] = {
-	{LV_0, 200000, 1000000},
-	{LV_1, 160000, 950000},
-	{LV_2, 133000, 925000},
-	{LV_3, 100000, 900000},
-	{0, 0, 0},
-};
-
-/* TODO: asv volt definitions are "__initdata"? */
-/* Some chips have different operating voltages */
-static unsigned int exynos4210_asv_volt[][EX4210_LV_NUM] = {
-	{1150000, 1050000, 1050000},
-	{1125000, 1025000, 1025000},
-	{1100000, 1000000, 1000000},
-	{1075000, 975000, 975000},
-	{1050000, 950000, 950000},
-};
-
-static unsigned int exynos4x12_mif_step_50[][EX4x12_LV_NUM] = {
-	/* 400      267     160     133     100 */
-	{1050000, 950000, 900000, 900000, 900000}, /* ASV0 */
-	{1050000, 950000, 900000, 900000, 900000}, /* ASV1 */
-	{1050000, 950000, 900000, 900000, 900000}, /* ASV2 */
-	{1050000, 900000, 900000, 900000, 900000}, /* ASV3 */
-	{1050000, 900000, 900000, 900000, 850000}, /* ASV4 */
-	{1050000, 900000, 900000, 850000, 850000}, /* ASV5 */
-	{1050000, 900000, 850000, 850000, 850000}, /* ASV6 */
-	{1050000, 900000, 850000, 850000, 850000}, /* ASV7 */
-	{1050000, 900000, 850000, 850000, 850000}, /* ASV8 */
-};
-
-static unsigned int exynos4x12_int_volt[][EX4x12_LV_NUM] = {
-	/* 200    160      133     100 */
-	{1000000, 950000, 925000, 900000}, /* ASV0 */
-	{975000,  925000, 925000, 900000}, /* ASV1 */
-	{950000,  925000, 900000, 875000}, /* ASV2 */
-	{950000,  900000, 900000, 875000}, /* ASV3 */
-	{925000,  875000, 875000, 875000}, /* ASV4 */
-	{900000,  850000, 850000, 850000}, /* ASV5 */
-	{900000,  850000, 850000, 850000}, /* ASV6 */
-	{900000,  850000, 850000, 850000}, /* ASV7 */
-	{900000,  850000, 850000, 850000}, /* ASV8 */
-};
-
-/*** Clock Divider Data for Exynos4210 ***/
-static unsigned int exynos4210_clkdiv_dmc0[][8] = {
-	/*
-	 * Clock divider value for following
-	 * { DIVACP, DIVACP_PCLK, DIVDPHY, DIVDMC, DIVDMCD
-	 *		DIVDMCP, DIVCOPY2, DIVCORE_TIMERS }
-	 */
-
-	/* DMC L0: 400MHz */
-	{ 3, 1, 1, 1, 1, 1, 3, 1 },
-	/* DMC L1: 266.7MHz */
-	{ 4, 1, 1, 2, 1, 1, 3, 1 },
-	/* DMC L2: 133MHz */
-	{ 5, 1, 1, 5, 1, 1, 3, 1 },
-};
-static unsigned int exynos4210_clkdiv_top[][5] = {
-	/*
-	 * Clock divider value for following
-	 * { DIVACLK200, DIVACLK100, DIVACLK160, DIVACLK133, DIVONENAND }
-	 */
-	/* ACLK200 L0: 200MHz */
-	{ 3, 7, 4, 5, 1 },
-	/* ACLK200 L1: 160MHz */
-	{ 4, 7, 5, 6, 1 },
-	/* ACLK200 L2: 133MHz */
-	{ 5, 7, 7, 7, 1 },
-};
-static unsigned int exynos4210_clkdiv_lr_bus[][2] = {
-	/*
-	 * Clock divider value for following
-	 * { DIVGDL/R, DIVGPL/R }
-	 */
-	/* ACLK_GDL/R L1: 200MHz */
-	{ 3, 1 },
-	/* ACLK_GDL/R L2: 160MHz */
-	{ 4, 1 },
-	/* ACLK_GDL/R L3: 133MHz */
-	{ 5, 1 },
-};
-
-/*** Clock Divider Data for Exynos4212/4412 ***/
-static unsigned int exynos4x12_clkdiv_dmc0[][6] = {
-	/*
-	 * Clock divider value for following
-	 * { DIVACP, DIVACP_PCLK, DIVDPHY, DIVDMC, DIVDMCD
-	 *              DIVDMCP}
-	 */
-
-	/* DMC L0: 400MHz */
-	{3, 1, 1, 1, 1, 1},
-	/* DMC L1: 266.7MHz */
-	{4, 1, 1, 2, 1, 1},
-	/* DMC L2: 160MHz */
-	{5, 1, 1, 4, 1, 1},
-	/* DMC L3: 133MHz */
-	{5, 1, 1, 5, 1, 1},
-	/* DMC L4: 100MHz */
-	{7, 1, 1, 7, 1, 1},
-};
-static unsigned int exynos4x12_clkdiv_dmc1[][6] = {
-	/*
-	 * Clock divider value for following
-	 * { G2DACP, DIVC2C, DIVC2C_ACLK }
-	 */
-
-	/* DMC L0: 400MHz */
-	{3, 1, 1},
-	/* DMC L1: 266.7MHz */
-	{4, 2, 1},
-	/* DMC L2: 160MHz */
-	{5, 4, 1},
-	/* DMC L3: 133MHz */
-	{5, 5, 1},
-	/* DMC L4: 100MHz */
-	{7, 7, 1},
-};
-static unsigned int exynos4x12_clkdiv_top[][5] = {
-	/*
-	 * Clock divider value for following
-	 * { DIVACLK266_GPS, DIVACLK100, DIVACLK160,
-		DIVACLK133, DIVONENAND }
-	 */
-
-	/* ACLK_GDL/R L0: 200MHz */
-	{2, 7, 4, 5, 1},
-	/* ACLK_GDL/R L1: 200MHz */
-	{2, 7, 4, 5, 1},
-	/* ACLK_GDL/R L2: 160MHz */
-	{4, 7, 5, 7, 1},
-	/* ACLK_GDL/R L3: 133MHz */
-	{4, 7, 5, 7, 1},
-	/* ACLK_GDL/R L4: 100MHz */
-	{7, 7, 7, 7, 1},
-};
-static unsigned int exynos4x12_clkdiv_lr_bus[][2] = {
-	/*
-	 * Clock divider value for following
-	 * { DIVGDL/R, DIVGPL/R }
-	 */
-
-	/* ACLK_GDL/R L0: 200MHz */
-	{3, 1},
-	/* ACLK_GDL/R L1: 200MHz */
-	{3, 1},
-	/* ACLK_GDL/R L2: 160MHz */
-	{4, 1},
-	/* ACLK_GDL/R L3: 133MHz */
-	{5, 1},
-	/* ACLK_GDL/R L4: 100MHz */
-	{7, 1},
-};
-static unsigned int exynos4x12_clkdiv_sclkip[][3] = {
-	/*
-	 * Clock divider value for following
-	 * { DIVMFC, DIVJPEG, DIVFIMC0~3}
-	 */
-
-	/* SCLK_MFC: 200MHz */
-	{3, 3, 4},
-	/* SCLK_MFC: 200MHz */
-	{3, 3, 4},
-	/* SCLK_MFC: 160MHz */
-	{4, 4, 5},
-	/* SCLK_MFC: 133MHz */
-	{5, 5, 5},
-	/* SCLK_MFC: 100MHz */
-	{7, 7, 7},
-};
-
-
-static int exynos4210_set_busclk(struct busfreq_data *data,
-				 struct busfreq_opp_info *oppi)
-{
-	unsigned int index;
-	unsigned int tmp;
-
-	for (index = LV_0; index < EX4210_LV_NUM; index++)
-		if (oppi->rate == exynos4210_busclk_table[index].clk)
-			break;
-
-	if (index == EX4210_LV_NUM)
-		return -EINVAL;
-
-	/* Change Divider - DMC0 */
-	tmp = data->dmc_divtable[index];
-
-	__raw_writel(tmp, EXYNOS4_CLKDIV_DMC0);
-
-	do {
-		tmp = __raw_readl(EXYNOS4_CLKDIV_STAT_DMC0);
-	} while (tmp & 0x11111111);
-
-	/* Change Divider - TOP */
-	tmp = data->top_divtable[index];
-
-	__raw_writel(tmp, EXYNOS4_CLKDIV_TOP);
-
-	do {
-		tmp = __raw_readl(EXYNOS4_CLKDIV_STAT_TOP);
-	} while (tmp & 0x11111);
-
-	/* Change Divider - LEFTBUS */
-	tmp = __raw_readl(EXYNOS4_CLKDIV_LEFTBUS);
-
-	tmp &= ~(EXYNOS4_CLKDIV_BUS_GDLR_MASK | EXYNOS4_CLKDIV_BUS_GPLR_MASK);
-
-	tmp |= ((exynos4210_clkdiv_lr_bus[index][0] <<
-				EXYNOS4_CLKDIV_BUS_GDLR_SHIFT) |
-		(exynos4210_clkdiv_lr_bus[index][1] <<
-				EXYNOS4_CLKDIV_BUS_GPLR_SHIFT));
-
-	__raw_writel(tmp, EXYNOS4_CLKDIV_LEFTBUS);
-
-	do {
-		tmp = __raw_readl(EXYNOS4_CLKDIV_STAT_LEFTBUS);
-	} while (tmp & 0x11);
-
-	/* Change Divider - RIGHTBUS */
-	tmp = __raw_readl(EXYNOS4_CLKDIV_RIGHTBUS);
-
-	tmp &= ~(EXYNOS4_CLKDIV_BUS_GDLR_MASK | EXYNOS4_CLKDIV_BUS_GPLR_MASK);
-
-	tmp |= ((exynos4210_clkdiv_lr_bus[index][0] <<
-				EXYNOS4_CLKDIV_BUS_GDLR_SHIFT) |
-		(exynos4210_clkdiv_lr_bus[index][1] <<
-				EXYNOS4_CLKDIV_BUS_GPLR_SHIFT));
-
-	__raw_writel(tmp, EXYNOS4_CLKDIV_RIGHTBUS);
-
-	do {
-		tmp = __raw_readl(EXYNOS4_CLKDIV_STAT_RIGHTBUS);
-	} while (tmp & 0x11);
-
-	return 0;
-}
-
-static int exynos4x12_set_busclk(struct busfreq_data *data,
-				 struct busfreq_opp_info *oppi)
-{
-	unsigned int index;
-	unsigned int tmp;
-
-	for (index = LV_0; index < EX4x12_LV_NUM; index++)
-		if (oppi->rate == exynos4x12_mifclk_table[index].clk)
-			break;
-
-	if (index == EX4x12_LV_NUM)
-		return -EINVAL;
-
-	/* Change Divider - DMC0 */
-	tmp = data->dmc_divtable[index];
-
-	__raw_writel(tmp, EXYNOS4_CLKDIV_DMC0);
-
-	do {
-		tmp = __raw_readl(EXYNOS4_CLKDIV_STAT_DMC0);
-	} while (tmp & 0x11111111);
-
-	/* Change Divider - DMC1 */
-	tmp = __raw_readl(EXYNOS4_CLKDIV_DMC1);
-
-	tmp &= ~(EXYNOS4_CLKDIV_DMC1_G2D_ACP_MASK |
-		EXYNOS4_CLKDIV_DMC1_C2C_MASK |
-		EXYNOS4_CLKDIV_DMC1_C2CACLK_MASK);
-
-	tmp |= ((exynos4x12_clkdiv_dmc1[index][0] <<
-				EXYNOS4_CLKDIV_DMC1_G2D_ACP_SHIFT) |
-		(exynos4x12_clkdiv_dmc1[index][1] <<
-				EXYNOS4_CLKDIV_DMC1_C2C_SHIFT) |
-		(exynos4x12_clkdiv_dmc1[index][2] <<
-				EXYNOS4_CLKDIV_DMC1_C2CACLK_SHIFT));
-
-	__raw_writel(tmp, EXYNOS4_CLKDIV_DMC1);
-
-	do {
-		tmp = __raw_readl(EXYNOS4_CLKDIV_STAT_DMC1);
-	} while (tmp & 0x111111);
-
-	/* Change Divider - TOP */
-	tmp = __raw_readl(EXYNOS4_CLKDIV_TOP);
-
-	tmp &= ~(EXYNOS4_CLKDIV_TOP_ACLK266_GPS_MASK |
-		EXYNOS4_CLKDIV_TOP_ACLK100_MASK |
-		EXYNOS4_CLKDIV_TOP_ACLK160_MASK |
-		EXYNOS4_CLKDIV_TOP_ACLK133_MASK |
-		EXYNOS4_CLKDIV_TOP_ONENAND_MASK);
-
-	tmp |= ((exynos4x12_clkdiv_top[index][0] <<
-				EXYNOS4_CLKDIV_TOP_ACLK266_GPS_SHIFT) |
-		(exynos4x12_clkdiv_top[index][1] <<
-				EXYNOS4_CLKDIV_TOP_ACLK100_SHIFT) |
-		(exynos4x12_clkdiv_top[index][2] <<
-				EXYNOS4_CLKDIV_TOP_ACLK160_SHIFT) |
-		(exynos4x12_clkdiv_top[index][3] <<
-				EXYNOS4_CLKDIV_TOP_ACLK133_SHIFT) |
-		(exynos4x12_clkdiv_top[index][4] <<
-				EXYNOS4_CLKDIV_TOP_ONENAND_SHIFT));
-
-	__raw_writel(tmp, EXYNOS4_CLKDIV_TOP);
-
-	do {
-		tmp = __raw_readl(EXYNOS4_CLKDIV_STAT_TOP);
-	} while (tmp & 0x11111);
-
-	/* Change Divider - LEFTBUS */
-	tmp = __raw_readl(EXYNOS4_CLKDIV_LEFTBUS);
-
-	tmp &= ~(EXYNOS4_CLKDIV_BUS_GDLR_MASK | EXYNOS4_CLKDIV_BUS_GPLR_MASK);
-
-	tmp |= ((exynos4x12_clkdiv_lr_bus[index][0] <<
-				EXYNOS4_CLKDIV_BUS_GDLR_SHIFT) |
-		(exynos4x12_clkdiv_lr_bus[index][1] <<
-				EXYNOS4_CLKDIV_BUS_GPLR_SHIFT));
-
-	__raw_writel(tmp, EXYNOS4_CLKDIV_LEFTBUS);
-
-	do {
-		tmp = __raw_readl(EXYNOS4_CLKDIV_STAT_LEFTBUS);
-	} while (tmp & 0x11);
-
-	/* Change Divider - RIGHTBUS */
-	tmp = __raw_readl(EXYNOS4_CLKDIV_RIGHTBUS);
-
-	tmp &= ~(EXYNOS4_CLKDIV_BUS_GDLR_MASK | EXYNOS4_CLKDIV_BUS_GPLR_MASK);
-
-	tmp |= ((exynos4x12_clkdiv_lr_bus[index][0] <<
-				EXYNOS4_CLKDIV_BUS_GDLR_SHIFT) |
-		(exynos4x12_clkdiv_lr_bus[index][1] <<
-				EXYNOS4_CLKDIV_BUS_GPLR_SHIFT));
-
-	__raw_writel(tmp, EXYNOS4_CLKDIV_RIGHTBUS);
-
-	do {
-		tmp = __raw_readl(EXYNOS4_CLKDIV_STAT_RIGHTBUS);
-	} while (tmp & 0x11);
-
-	/* Change Divider - MFC */
-	tmp = __raw_readl(EXYNOS4_CLKDIV_MFC);
-
-	tmp &= ~(EXYNOS4_CLKDIV_MFC_MASK);
-
-	tmp |= ((exynos4x12_clkdiv_sclkip[index][0] <<
-				EXYNOS4_CLKDIV_MFC_SHIFT));
-
-	__raw_writel(tmp, EXYNOS4_CLKDIV_MFC);
-
-	do {
-		tmp = __raw_readl(EXYNOS4_CLKDIV_STAT_MFC);
-	} while (tmp & 0x1);
-
-	/* Change Divider - JPEG */
-	tmp = __raw_readl(EXYNOS4_CLKDIV_CAM1);
-
-	tmp &= ~(EXYNOS4_CLKDIV_CAM1_JPEG_MASK);
-
-	tmp |= ((exynos4x12_clkdiv_sclkip[index][1] <<
-				EXYNOS4_CLKDIV_CAM1_JPEG_SHIFT));
-
-	__raw_writel(tmp, EXYNOS4_CLKDIV_CAM1);
-
-	do {
-		tmp = __raw_readl(EXYNOS4_CLKDIV_STAT_CAM1);
-	} while (tmp & 0x1);
-
-	/* Change Divider - FIMC0~3 */
-	tmp = __raw_readl(EXYNOS4_CLKDIV_CAM);
-
-	tmp &= ~(EXYNOS4_CLKDIV_CAM_FIMC0_MASK | EXYNOS4_CLKDIV_CAM_FIMC1_MASK |
-		EXYNOS4_CLKDIV_CAM_FIMC2_MASK | EXYNOS4_CLKDIV_CAM_FIMC3_MASK);
-
-	tmp |= ((exynos4x12_clkdiv_sclkip[index][2] <<
-				EXYNOS4_CLKDIV_CAM_FIMC0_SHIFT) |
-		(exynos4x12_clkdiv_sclkip[index][2] <<
-				EXYNOS4_CLKDIV_CAM_FIMC1_SHIFT) |
-		(exynos4x12_clkdiv_sclkip[index][2] <<
-				EXYNOS4_CLKDIV_CAM_FIMC2_SHIFT) |
-		(exynos4x12_clkdiv_sclkip[index][2] <<
-				EXYNOS4_CLKDIV_CAM_FIMC3_SHIFT));
-
-	__raw_writel(tmp, EXYNOS4_CLKDIV_CAM);
-
-	do {
-		tmp = __raw_readl(EXYNOS4_CLKDIV_STAT_CAM1);
-	} while (tmp & 0x1111);
-
-	return 0;
-}
-
-static int exynos4x12_get_intspec(unsigned long mifclk)
-{
-	int i = 0;
-
-	while (exynos4x12_intclk_table[i].clk) {
-		if (exynos4x12_intclk_table[i].clk <= mifclk)
-			return i;
-		i++;
-	}
-
-	return -EINVAL;
-}
-
-static int exynos4_bus_setvolt(struct busfreq_data *data,
-			       struct busfreq_opp_info *oppi,
-			       struct busfreq_opp_info *oldoppi)
-{
-	int err = 0, tmp;
-	unsigned long volt = oppi->volt;
-
-	switch (data->type) {
-	case TYPE_BUSF_EXYNOS4210:
-		/* OPP represents DMC clock + INT voltage */
-		err = regulator_set_voltage(data->vdd_int, volt,
-					    MAX_SAFEVOLT);
-		break;
-	case TYPE_BUSF_EXYNOS4x12:
-		/* OPP represents MIF clock + MIF voltage */
-		err = regulator_set_voltage(data->vdd_mif, volt,
-					    MAX_SAFEVOLT);
-		if (err)
-			break;
-
-		tmp = exynos4x12_get_intspec(oppi->rate);
-		if (tmp < 0) {
-			err = tmp;
-			regulator_set_voltage(data->vdd_mif,
-					      oldoppi->volt,
-					      MAX_SAFEVOLT);
-			break;
-		}
-		err = regulator_set_voltage(data->vdd_int,
-					    exynos4x12_intclk_table[tmp].volt,
-					    MAX_SAFEVOLT);
-		/*  Try to recover */
-		if (err)
-			regulator_set_voltage(data->vdd_mif,
-					      oldoppi->volt,
-					      MAX_SAFEVOLT);
-		break;
-	default:
-		err = -EINVAL;
-	}
-
-	return err;
-}
-
-static int exynos4_bus_target(struct device *dev, unsigned long *_freq,
-			      u32 flags)
-{
-	int err = 0;
-	struct platform_device *pdev = container_of(dev, struct platform_device,
-						    dev);
-	struct busfreq_data *data = platform_get_drvdata(pdev);
-	struct dev_pm_opp *opp;
-	unsigned long freq;
-	unsigned long old_freq = data->curr_oppinfo.rate;
-	struct busfreq_opp_info	new_oppinfo;
-
-	rcu_read_lock();
-	opp = devfreq_recommended_opp(dev, _freq, flags);
-	if (IS_ERR(opp)) {
-		rcu_read_unlock();
-		return PTR_ERR(opp);
-	}
-	new_oppinfo.rate = dev_pm_opp_get_freq(opp);
-	new_oppinfo.volt = dev_pm_opp_get_voltage(opp);
-	rcu_read_unlock();
-	freq = new_oppinfo.rate;
-
-	if (old_freq == freq)
-		return 0;
-
-	dev_dbg(dev, "targeting %lukHz %luuV\n", freq, new_oppinfo.volt);
-
-	mutex_lock(&data->lock);
-
-	if (data->disabled)
-		goto out;
-
-	if (old_freq < freq)
-		err = exynos4_bus_setvolt(data, &new_oppinfo,
-					  &data->curr_oppinfo);
-	if (err)
-		goto out;
-
-	if (old_freq != freq) {
-		switch (data->type) {
-		case TYPE_BUSF_EXYNOS4210:
-			err = exynos4210_set_busclk(data, &new_oppinfo);
-			break;
-		case TYPE_BUSF_EXYNOS4x12:
-			err = exynos4x12_set_busclk(data, &new_oppinfo);
-			break;
-		default:
-			err = -EINVAL;
-		}
-	}
-	if (err)
-		goto out;
-
-	if (old_freq > freq)
-		err = exynos4_bus_setvolt(data, &new_oppinfo,
-					  &data->curr_oppinfo);
-	if (err)
-		goto out;
-
-	data->curr_oppinfo = new_oppinfo;
-out:
-	mutex_unlock(&data->lock);
-	return err;
-}
-
-static int exynos4_bus_get_dev_status(struct device *dev,
-				      struct devfreq_dev_status *stat)
-{
-	struct busfreq_data *data = dev_get_drvdata(dev);
-	struct busfreq_ppmu_data *ppmu_data = &data->ppmu_data;
-	int busier;
-
-	exynos_read_ppmu(ppmu_data);
-	busier = exynos_get_busier_ppmu(ppmu_data);
-	stat->current_frequency = data->curr_oppinfo.rate;
-
-	/* Number of cycles spent on memory access */
-	stat->busy_time = ppmu_data->ppmu[busier].count[PPMU_PMNCNT3];
-	stat->busy_time *= 100 / BUS_SATURATION_RATIO;
-	stat->total_time = ppmu_data->ppmu[busier].ccnt;
-
-	/* If the counters have overflown, retry */
-	if (ppmu_data->ppmu[busier].ccnt_overflow ||
-	    ppmu_data->ppmu[busier].count_overflow[0])
-		return -EAGAIN;
-
-	return 0;
-}
-
-static struct devfreq_dev_profile exynos4_devfreq_profile = {
-	.initial_freq	= 400000,
-	.polling_ms	= 50,
-	.target		= exynos4_bus_target,
-	.get_dev_status	= exynos4_bus_get_dev_status,
-};
-
-static int exynos4210_init_tables(struct busfreq_data *data)
-{
-	u32 tmp;
-	int mgrp;
-	int i, err = 0;
-
-	tmp = __raw_readl(EXYNOS4_CLKDIV_DMC0);
-	for (i = LV_0; i < EX4210_LV_NUM; i++) {
-		tmp &= ~(EXYNOS4_CLKDIV_DMC0_ACP_MASK |
-			EXYNOS4_CLKDIV_DMC0_ACPPCLK_MASK |
-			EXYNOS4_CLKDIV_DMC0_DPHY_MASK |
-			EXYNOS4_CLKDIV_DMC0_DMC_MASK |
-			EXYNOS4_CLKDIV_DMC0_DMCD_MASK |
-			EXYNOS4_CLKDIV_DMC0_DMCP_MASK |
-			EXYNOS4_CLKDIV_DMC0_COPY2_MASK |
-			EXYNOS4_CLKDIV_DMC0_CORETI_MASK);
-
-		tmp |= ((exynos4210_clkdiv_dmc0[i][0] <<
-					EXYNOS4_CLKDIV_DMC0_ACP_SHIFT) |
-			(exynos4210_clkdiv_dmc0[i][1] <<
-					EXYNOS4_CLKDIV_DMC0_ACPPCLK_SHIFT) |
-			(exynos4210_clkdiv_dmc0[i][2] <<
-					EXYNOS4_CLKDIV_DMC0_DPHY_SHIFT) |
-			(exynos4210_clkdiv_dmc0[i][3] <<
-					EXYNOS4_CLKDIV_DMC0_DMC_SHIFT) |
-			(exynos4210_clkdiv_dmc0[i][4] <<
-					EXYNOS4_CLKDIV_DMC0_DMCD_SHIFT) |
-			(exynos4210_clkdiv_dmc0[i][5] <<
-					EXYNOS4_CLKDIV_DMC0_DMCP_SHIFT) |
-			(exynos4210_clkdiv_dmc0[i][6] <<
-					EXYNOS4_CLKDIV_DMC0_COPY2_SHIFT) |
-			(exynos4210_clkdiv_dmc0[i][7] <<
-					EXYNOS4_CLKDIV_DMC0_CORETI_SHIFT));
-
-		data->dmc_divtable[i] = tmp;
-	}
-
-	tmp = __raw_readl(EXYNOS4_CLKDIV_TOP);
-	for (i = LV_0; i <  EX4210_LV_NUM; i++) {
-		tmp &= ~(EXYNOS4_CLKDIV_TOP_ACLK200_MASK |
-			EXYNOS4_CLKDIV_TOP_ACLK100_MASK |
-			EXYNOS4_CLKDIV_TOP_ACLK160_MASK |
-			EXYNOS4_CLKDIV_TOP_ACLK133_MASK |
-			EXYNOS4_CLKDIV_TOP_ONENAND_MASK);
-
-		tmp |= ((exynos4210_clkdiv_top[i][0] <<
-					EXYNOS4_CLKDIV_TOP_ACLK200_SHIFT) |
-			(exynos4210_clkdiv_top[i][1] <<
-					EXYNOS4_CLKDIV_TOP_ACLK100_SHIFT) |
-			(exynos4210_clkdiv_top[i][2] <<
-					EXYNOS4_CLKDIV_TOP_ACLK160_SHIFT) |
-			(exynos4210_clkdiv_top[i][3] <<
-					EXYNOS4_CLKDIV_TOP_ACLK133_SHIFT) |
-			(exynos4210_clkdiv_top[i][4] <<
-					EXYNOS4_CLKDIV_TOP_ONENAND_SHIFT));
-
-		data->top_divtable[i] = tmp;
-	}
-
-	/*
-	 * TODO: init tmp based on busfreq_data
-	 * (device-tree or platform-data)
-	 */
-	tmp = 0; /* Max voltages for the reliability of the unknown */
-
-	pr_debug("ASV Group of Exynos4 is %d\n", tmp);
-	/* Use merged grouping for voltage */
-	switch (tmp) {
-	case 0:
-		mgrp = 0;
-		break;
-	case 1:
-	case 2:
-		mgrp = 1;
-		break;
-	case 3:
-	case 4:
-		mgrp = 2;
-		break;
-	case 5:
-	case 6:
-		mgrp = 3;
-		break;
-	case 7:
-		mgrp = 4;
-		break;
-	default:
-		pr_warn("Unknown ASV Group. Use max voltage.\n");
-		mgrp = 0;
-	}
-
-	for (i = LV_0; i < EX4210_LV_NUM; i++)
-		exynos4210_busclk_table[i].volt = exynos4210_asv_volt[mgrp][i];
-
-	for (i = LV_0; i < EX4210_LV_NUM; i++) {
-		err = dev_pm_opp_add(data->dev, exynos4210_busclk_table[i].clk,
-			      exynos4210_busclk_table[i].volt);
-		if (err) {
-			dev_err(data->dev, "Cannot add opp entries.\n");
-			return err;
-		}
-	}
-
-
-	return 0;
-}
-
-static int exynos4x12_init_tables(struct busfreq_data *data)
-{
-	unsigned int i;
-	unsigned int tmp;
-	int ret;
-
-	/* Enable pause function for DREX2 DVFS */
-	tmp = __raw_readl(EXYNOS4_DMC_PAUSE_CTRL);
-	tmp |= EXYNOS4_DMC_PAUSE_ENABLE;
-	__raw_writel(tmp, EXYNOS4_DMC_PAUSE_CTRL);
-
-	tmp = __raw_readl(EXYNOS4_CLKDIV_DMC0);
-
-	for (i = 0; i <  EX4x12_LV_NUM; i++) {
-		tmp &= ~(EXYNOS4_CLKDIV_DMC0_ACP_MASK |
-			EXYNOS4_CLKDIV_DMC0_ACPPCLK_MASK |
-			EXYNOS4_CLKDIV_DMC0_DPHY_MASK |
-			EXYNOS4_CLKDIV_DMC0_DMC_MASK |
-			EXYNOS4_CLKDIV_DMC0_DMCD_MASK |
-			EXYNOS4_CLKDIV_DMC0_DMCP_MASK);
-
-		tmp |= ((exynos4x12_clkdiv_dmc0[i][0] <<
-					EXYNOS4_CLKDIV_DMC0_ACP_SHIFT) |
-			(exynos4x12_clkdiv_dmc0[i][1] <<
-					EXYNOS4_CLKDIV_DMC0_ACPPCLK_SHIFT) |
-			(exynos4x12_clkdiv_dmc0[i][2] <<
-					EXYNOS4_CLKDIV_DMC0_DPHY_SHIFT) |
-			(exynos4x12_clkdiv_dmc0[i][3] <<
-					EXYNOS4_CLKDIV_DMC0_DMC_SHIFT) |
-			(exynos4x12_clkdiv_dmc0[i][4] <<
-					EXYNOS4_CLKDIV_DMC0_DMCD_SHIFT) |
-			(exynos4x12_clkdiv_dmc0[i][5] <<
-					EXYNOS4_CLKDIV_DMC0_DMCP_SHIFT));
-
-		data->dmc_divtable[i] = tmp;
-	}
-
-	tmp = 0; /* Max voltages for the reliability of the unknown */
-
-	if (tmp > 8)
-		tmp = 0;
-	pr_debug("ASV Group of Exynos4x12 is %d\n", tmp);
-
-	for (i = 0; i < EX4x12_LV_NUM; i++) {
-		exynos4x12_mifclk_table[i].volt =
-			exynos4x12_mif_step_50[tmp][i];
-		exynos4x12_intclk_table[i].volt =
-			exynos4x12_int_volt[tmp][i];
-	}
-
-	for (i = 0; i < EX4x12_LV_NUM; i++) {
-		ret = dev_pm_opp_add(data->dev, exynos4x12_mifclk_table[i].clk,
-			      exynos4x12_mifclk_table[i].volt);
-		if (ret) {
-			dev_err(data->dev, "Fail to add opp entries.\n");
-			return ret;
-		}
-	}
-
-	return 0;
-}
-
-static int exynos4_busfreq_pm_notifier_event(struct notifier_block *this,
-		unsigned long event, void *ptr)
-{
-	struct busfreq_data *data = container_of(this, struct busfreq_data,
-						 pm_notifier);
-	struct dev_pm_opp *opp;
-	struct busfreq_opp_info	new_oppinfo;
-	unsigned long maxfreq = ULONG_MAX;
-	int err = 0;
-
-	switch (event) {
-	case PM_SUSPEND_PREPARE:
-		/* Set Fastest and Deactivate DVFS */
-		mutex_lock(&data->lock);
-
-		data->disabled = true;
-
-		rcu_read_lock();
-		opp = dev_pm_opp_find_freq_floor(data->dev, &maxfreq);
-		if (IS_ERR(opp)) {
-			rcu_read_unlock();
-			dev_err(data->dev, "%s: unable to find a min freq\n",
-				__func__);
-			mutex_unlock(&data->lock);
-			return PTR_ERR(opp);
-		}
-		new_oppinfo.rate = dev_pm_opp_get_freq(opp);
-		new_oppinfo.volt = dev_pm_opp_get_voltage(opp);
-		rcu_read_unlock();
-
-		err = exynos4_bus_setvolt(data, &new_oppinfo,
-					  &data->curr_oppinfo);
-		if (err)
-			goto unlock;
-
-		switch (data->type) {
-		case TYPE_BUSF_EXYNOS4210:
-			err = exynos4210_set_busclk(data, &new_oppinfo);
-			break;
-		case TYPE_BUSF_EXYNOS4x12:
-			err = exynos4x12_set_busclk(data, &new_oppinfo);
-			break;
-		default:
-			err = -EINVAL;
-		}
-		if (err)
-			goto unlock;
-
-		data->curr_oppinfo = new_oppinfo;
-unlock:
-		mutex_unlock(&data->lock);
-		if (err)
-			return err;
-		return NOTIFY_OK;
-	case PM_POST_RESTORE:
-	case PM_POST_SUSPEND:
-		/* Reactivate */
-		mutex_lock(&data->lock);
-		data->disabled = false;
-		mutex_unlock(&data->lock);
-		return NOTIFY_OK;
-	}
-
-	return NOTIFY_DONE;
-}
-
-static int exynos4_busfreq_probe(struct platform_device *pdev)
-{
-	struct busfreq_data *data;
-	struct busfreq_ppmu_data *ppmu_data;
-	struct dev_pm_opp *opp;
-	struct device *dev = &pdev->dev;
-	int err = 0;
-
-	data = devm_kzalloc(&pdev->dev, sizeof(struct busfreq_data), GFP_KERNEL);
-	if (data == NULL) {
-		dev_err(dev, "Cannot allocate memory.\n");
-		return -ENOMEM;
-	}
-
-	ppmu_data = &data->ppmu_data;
-	ppmu_data->ppmu_end = PPMU_END;
-	ppmu_data->ppmu = devm_kzalloc(dev,
-				       sizeof(struct exynos_ppmu) * PPMU_END,
-				       GFP_KERNEL);
-	if (!ppmu_data->ppmu) {
-		dev_err(dev, "Failed to allocate memory for exynos_ppmu\n");
-		return -ENOMEM;
-	}
-
-	data->type = pdev->id_entry->driver_data;
-	ppmu_data->ppmu[PPMU_DMC0].hw_base = S5P_VA_DMC0;
-	ppmu_data->ppmu[PPMU_DMC1].hw_base = S5P_VA_DMC1;
-	data->pm_notifier.notifier_call = exynos4_busfreq_pm_notifier_event;
-	data->dev = dev;
-	mutex_init(&data->lock);
-
-	switch (data->type) {
-	case TYPE_BUSF_EXYNOS4210:
-		err = exynos4210_init_tables(data);
-		break;
-	case TYPE_BUSF_EXYNOS4x12:
-		err = exynos4x12_init_tables(data);
-		break;
-	default:
-		dev_err(dev, "Cannot determine the device id %d\n", data->type);
-		err = -EINVAL;
-	}
-	if (err) {
-		dev_err(dev, "Cannot initialize busfreq table %d\n",
-			     data->type);
-		return err;
-	}
-
-	data->vdd_int = devm_regulator_get(dev, "vdd_int");
-	if (IS_ERR(data->vdd_int)) {
-		dev_err(dev, "Cannot get the regulator \"vdd_int\"\n");
-		return PTR_ERR(data->vdd_int);
-	}
-	if (data->type == TYPE_BUSF_EXYNOS4x12) {
-		data->vdd_mif = devm_regulator_get(dev, "vdd_mif");
-		if (IS_ERR(data->vdd_mif)) {
-			dev_err(dev, "Cannot get the regulator \"vdd_mif\"\n");
-			return PTR_ERR(data->vdd_mif);
-		}
-	}
-
-	rcu_read_lock();
-	opp = dev_pm_opp_find_freq_floor(dev,
-					 &exynos4_devfreq_profile.initial_freq);
-	if (IS_ERR(opp)) {
-		rcu_read_unlock();
-		dev_err(dev, "Invalid initial frequency %lu kHz.\n",
-			exynos4_devfreq_profile.initial_freq);
-		return PTR_ERR(opp);
-	}
-	data->curr_oppinfo.rate = dev_pm_opp_get_freq(opp);
-	data->curr_oppinfo.volt = dev_pm_opp_get_voltage(opp);
-	rcu_read_unlock();
-
-	platform_set_drvdata(pdev, data);
-
-	data->devfreq = devm_devfreq_add_device(dev, &exynos4_devfreq_profile,
-					   "simple_ondemand", NULL);
-	if (IS_ERR(data->devfreq))
-		return PTR_ERR(data->devfreq);
-
-	/*
-	 * Start PPMU (Performance Profiling Monitoring Unit) to check
-	 * utilization of each IP in the Exynos4 SoC.
-	 */
-	busfreq_mon_reset(ppmu_data);
-
-	/* Register opp_notifier for Exynos4 busfreq */
-	err = devm_devfreq_register_opp_notifier(dev, data->devfreq);
-	if (err < 0) {
-		dev_err(dev, "Failed to register opp notifier\n");
-		return err;
-	}
-
-	/* Register pm_notifier for Exynos4 busfreq */
-	err = register_pm_notifier(&data->pm_notifier);
-	if (err) {
-		dev_err(dev, "Failed to setup pm notifier\n");
-		return err;
-	}
-
-	return 0;
-}
-
-static int exynos4_busfreq_remove(struct platform_device *pdev)
-{
-	struct busfreq_data *data = platform_get_drvdata(pdev);
-
-	/* Unregister all of notifier chain */
-	unregister_pm_notifier(&data->pm_notifier);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int exynos4_busfreq_resume(struct device *dev)
-{
-	struct busfreq_data *data = dev_get_drvdata(dev);
-	struct busfreq_ppmu_data *ppmu_data = &data->ppmu_data;
-
-	busfreq_mon_reset(ppmu_data);
-	return 0;
-}
-#endif
-
-static SIMPLE_DEV_PM_OPS(exynos4_busfreq_pm_ops, NULL, exynos4_busfreq_resume);
-
-static const struct platform_device_id exynos4_busfreq_id[] = {
-	{ "exynos4210-busfreq", TYPE_BUSF_EXYNOS4210 },
-	{ "exynos4412-busfreq", TYPE_BUSF_EXYNOS4x12 },
-	{ "exynos4212-busfreq", TYPE_BUSF_EXYNOS4x12 },
-	{ },
-};
-
-static struct platform_driver exynos4_busfreq_driver = {
-	.probe	= exynos4_busfreq_probe,
-	.remove	= exynos4_busfreq_remove,
-	.id_table = exynos4_busfreq_id,
-	.driver = {
-		.name	= "exynos4-busfreq",
-		.pm	= &exynos4_busfreq_pm_ops,
-	},
-};
-
-static int __init exynos4_busfreq_init(void)
-{
-	return platform_driver_register(&exynos4_busfreq_driver);
-}
-late_initcall(exynos4_busfreq_init);
-
-static void __exit exynos4_busfreq_exit(void)
-{
-	platform_driver_unregister(&exynos4_busfreq_driver);
-}
-module_exit(exynos4_busfreq_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("EXYNOS4 busfreq driver with devfreq framework");
-MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/devfreq/exynos/exynos4_bus.h linux-libre-4.7-gnu/drivers/devfreq/exynos/exynos4_bus.h
--- linux-libre-4.6-gnu/drivers/devfreq/exynos/exynos4_bus.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/devfreq/exynos/exynos4_bus.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,110 +0,0 @@
-/*
- * Copyright (c) 2013 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * EXYNOS4 BUS header
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __DEVFREQ_EXYNOS4_BUS_H
-#define __DEVFREQ_EXYNOS4_BUS_H __FILE__
-
-#include <mach/map.h>
-
-#define EXYNOS4_CLKDIV_LEFTBUS			(S5P_VA_CMU + 0x04500)
-#define EXYNOS4_CLKDIV_STAT_LEFTBUS		(S5P_VA_CMU + 0x04600)
-
-#define EXYNOS4_CLKDIV_RIGHTBUS			(S5P_VA_CMU + 0x08500)
-#define EXYNOS4_CLKDIV_STAT_RIGHTBUS		(S5P_VA_CMU + 0x08600)
-
-#define EXYNOS4_CLKDIV_TOP			(S5P_VA_CMU + 0x0C510)
-#define EXYNOS4_CLKDIV_CAM			(S5P_VA_CMU + 0x0C520)
-#define EXYNOS4_CLKDIV_MFC			(S5P_VA_CMU + 0x0C528)
-
-#define EXYNOS4_CLKDIV_STAT_TOP			(S5P_VA_CMU + 0x0C610)
-#define EXYNOS4_CLKDIV_STAT_MFC			(S5P_VA_CMU + 0x0C628)
-
-#define EXYNOS4210_CLKGATE_IP_IMAGE		(S5P_VA_CMU + 0x0C930)
-#define EXYNOS4212_CLKGATE_IP_IMAGE		(S5P_VA_CMU + 0x04930)
-
-#define EXYNOS4_CLKDIV_DMC0			(S5P_VA_CMU + 0x10500)
-#define EXYNOS4_CLKDIV_DMC1			(S5P_VA_CMU + 0x10504)
-#define EXYNOS4_CLKDIV_STAT_DMC0		(S5P_VA_CMU + 0x10600)
-#define EXYNOS4_CLKDIV_STAT_DMC1		(S5P_VA_CMU + 0x10604)
-
-#define EXYNOS4_DMC_PAUSE_CTRL			(S5P_VA_CMU + 0x11094)
-#define EXYNOS4_DMC_PAUSE_ENABLE		(1 << 0)
-
-#define EXYNOS4_CLKDIV_DMC0_ACP_SHIFT		(0)
-#define EXYNOS4_CLKDIV_DMC0_ACP_MASK		(0x7 << EXYNOS4_CLKDIV_DMC0_ACP_SHIFT)
-#define EXYNOS4_CLKDIV_DMC0_ACPPCLK_SHIFT	(4)
-#define EXYNOS4_CLKDIV_DMC0_ACPPCLK_MASK	(0x7 << EXYNOS4_CLKDIV_DMC0_ACPPCLK_SHIFT)
-#define EXYNOS4_CLKDIV_DMC0_DPHY_SHIFT		(8)
-#define EXYNOS4_CLKDIV_DMC0_DPHY_MASK		(0x7 << EXYNOS4_CLKDIV_DMC0_DPHY_SHIFT)
-#define EXYNOS4_CLKDIV_DMC0_DMC_SHIFT		(12)
-#define EXYNOS4_CLKDIV_DMC0_DMC_MASK		(0x7 << EXYNOS4_CLKDIV_DMC0_DMC_SHIFT)
-#define EXYNOS4_CLKDIV_DMC0_DMCD_SHIFT		(16)
-#define EXYNOS4_CLKDIV_DMC0_DMCD_MASK		(0x7 << EXYNOS4_CLKDIV_DMC0_DMCD_SHIFT)
-#define EXYNOS4_CLKDIV_DMC0_DMCP_SHIFT		(20)
-#define EXYNOS4_CLKDIV_DMC0_DMCP_MASK		(0x7 << EXYNOS4_CLKDIV_DMC0_DMCP_SHIFT)
-#define EXYNOS4_CLKDIV_DMC0_COPY2_SHIFT		(24)
-#define EXYNOS4_CLKDIV_DMC0_COPY2_MASK		(0x7 << EXYNOS4_CLKDIV_DMC0_COPY2_SHIFT)
-#define EXYNOS4_CLKDIV_DMC0_CORETI_SHIFT	(28)
-#define EXYNOS4_CLKDIV_DMC0_CORETI_MASK		(0x7 << EXYNOS4_CLKDIV_DMC0_CORETI_SHIFT)
-
-#define EXYNOS4_CLKDIV_DMC1_G2D_ACP_SHIFT	(0)
-#define EXYNOS4_CLKDIV_DMC1_G2D_ACP_MASK	(0xf << EXYNOS4_CLKDIV_DMC1_G2D_ACP_SHIFT)
-#define EXYNOS4_CLKDIV_DMC1_C2C_SHIFT		(4)
-#define EXYNOS4_CLKDIV_DMC1_C2C_MASK		(0x7 << EXYNOS4_CLKDIV_DMC1_C2C_SHIFT)
-#define EXYNOS4_CLKDIV_DMC1_PWI_SHIFT		(8)
-#define EXYNOS4_CLKDIV_DMC1_PWI_MASK		(0xf << EXYNOS4_CLKDIV_DMC1_PWI_SHIFT)
-#define EXYNOS4_CLKDIV_DMC1_C2CACLK_SHIFT	(12)
-#define EXYNOS4_CLKDIV_DMC1_C2CACLK_MASK	(0x7 << EXYNOS4_CLKDIV_DMC1_C2CACLK_SHIFT)
-#define EXYNOS4_CLKDIV_DMC1_DVSEM_SHIFT		(16)
-#define EXYNOS4_CLKDIV_DMC1_DVSEM_MASK		(0x7f << EXYNOS4_CLKDIV_DMC1_DVSEM_SHIFT)
-#define EXYNOS4_CLKDIV_DMC1_DPM_SHIFT		(24)
-#define EXYNOS4_CLKDIV_DMC1_DPM_MASK		(0x7f << EXYNOS4_CLKDIV_DMC1_DPM_SHIFT)
-
-#define EXYNOS4_CLKDIV_MFC_SHIFT		(0)
-#define EXYNOS4_CLKDIV_MFC_MASK			(0x7 << EXYNOS4_CLKDIV_MFC_SHIFT)
-
-#define EXYNOS4_CLKDIV_TOP_ACLK200_SHIFT	(0)
-#define EXYNOS4_CLKDIV_TOP_ACLK200_MASK		(0x7 << EXYNOS4_CLKDIV_TOP_ACLK200_SHIFT)
-#define EXYNOS4_CLKDIV_TOP_ACLK100_SHIFT	(4)
-#define EXYNOS4_CLKDIV_TOP_ACLK100_MASK		(0xF << EXYNOS4_CLKDIV_TOP_ACLK100_SHIFT)
-#define EXYNOS4_CLKDIV_TOP_ACLK160_SHIFT	(8)
-#define EXYNOS4_CLKDIV_TOP_ACLK160_MASK		(0x7 << EXYNOS4_CLKDIV_TOP_ACLK160_SHIFT)
-#define EXYNOS4_CLKDIV_TOP_ACLK133_SHIFT	(12)
-#define EXYNOS4_CLKDIV_TOP_ACLK133_MASK		(0x7 << EXYNOS4_CLKDIV_TOP_ACLK133_SHIFT)
-#define EXYNOS4_CLKDIV_TOP_ONENAND_SHIFT	(16)
-#define EXYNOS4_CLKDIV_TOP_ONENAND_MASK		(0x7 << EXYNOS4_CLKDIV_TOP_ONENAND_SHIFT)
-#define EXYNOS4_CLKDIV_TOP_ACLK266_GPS_SHIFT	(20)
-#define EXYNOS4_CLKDIV_TOP_ACLK266_GPS_MASK	(0x7 << EXYNOS4_CLKDIV_TOP_ACLK266_GPS_SHIFT)
-#define EXYNOS4_CLKDIV_TOP_ACLK400_MCUISP_SHIFT	(24)
-#define EXYNOS4_CLKDIV_TOP_ACLK400_MCUISP_MASK	(0x7 << EXYNOS4_CLKDIV_TOP_ACLK400_MCUISP_SHIFT)
-
-#define EXYNOS4_CLKDIV_BUS_GDLR_SHIFT		(0)
-#define EXYNOS4_CLKDIV_BUS_GDLR_MASK		(0x7 << EXYNOS4_CLKDIV_BUS_GDLR_SHIFT)
-#define EXYNOS4_CLKDIV_BUS_GPLR_SHIFT		(4)
-#define EXYNOS4_CLKDIV_BUS_GPLR_MASK		(0x7 << EXYNOS4_CLKDIV_BUS_GPLR_SHIFT)
-
-#define EXYNOS4_CLKDIV_CAM_FIMC0_SHIFT		(0)
-#define EXYNOS4_CLKDIV_CAM_FIMC0_MASK		(0xf << EXYNOS4_CLKDIV_CAM_FIMC0_SHIFT)
-#define EXYNOS4_CLKDIV_CAM_FIMC1_SHIFT		(4)
-#define EXYNOS4_CLKDIV_CAM_FIMC1_MASK		(0xf << EXYNOS4_CLKDIV_CAM_FIMC1_SHIFT)
-#define EXYNOS4_CLKDIV_CAM_FIMC2_SHIFT		(8)
-#define EXYNOS4_CLKDIV_CAM_FIMC2_MASK		(0xf << EXYNOS4_CLKDIV_CAM_FIMC2_SHIFT)
-#define EXYNOS4_CLKDIV_CAM_FIMC3_SHIFT		(12)
-#define EXYNOS4_CLKDIV_CAM_FIMC3_MASK		(0xf << EXYNOS4_CLKDIV_CAM_FIMC3_SHIFT)
-
-#define EXYNOS4_CLKDIV_CAM1			(S5P_VA_CMU + 0x0C568)
-
-#define EXYNOS4_CLKDIV_STAT_CAM1		(S5P_VA_CMU + 0x0C668)
-
-#define EXYNOS4_CLKDIV_CAM1_JPEG_SHIFT		(0)
-#define EXYNOS4_CLKDIV_CAM1_JPEG_MASK		(0xf << EXYNOS4_CLKDIV_CAM1_JPEG_SHIFT)
-
-#endif /* __DEVFREQ_EXYNOS4_BUS_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/devfreq/exynos/exynos5_bus.c linux-libre-4.7-gnu/drivers/devfreq/exynos/exynos5_bus.c
--- linux-libre-4.6-gnu/drivers/devfreq/exynos/exynos5_bus.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/devfreq/exynos/exynos5_bus.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,431 +0,0 @@
-/*
- * Copyright (c) 2012 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * EXYNOS5 INT clock frequency scaling support using DEVFREQ framework
- * Based on work done by Jonghwan Choi <jhbird.choi@samsung.com>
- * Support for only EXYNOS5250 is present.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#include <linux/module.h>
-#include <linux/devfreq.h>
-#include <linux/io.h>
-#include <linux/pm_opp.h>
-#include <linux/slab.h>
-#include <linux/suspend.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/pm_qos.h>
-#include <linux/regulator/consumer.h>
-#include <linux/of_address.h>
-#include <linux/of_platform.h>
-
-#include "exynos_ppmu.h"
-
-#define MAX_SAFEVOLT			1100000 /* 1.10V */
-/* Assume that the bus is saturated if the utilization is 25% */
-#define INT_BUS_SATURATION_RATIO	25
-
-enum int_level_idx {
-	LV_0,
-	LV_1,
-	LV_2,
-	LV_3,
-	LV_4,
-	_LV_END
-};
-
-enum exynos_ppmu_list {
-	PPMU_RIGHT,
-	PPMU_END,
-};
-
-struct busfreq_data_int {
-	struct device *dev;
-	struct devfreq *devfreq;
-	struct regulator *vdd_int;
-	struct busfreq_ppmu_data ppmu_data;
-	unsigned long curr_freq;
-	bool disabled;
-
-	struct notifier_block pm_notifier;
-	struct mutex lock;
-	struct pm_qos_request int_req;
-	struct clk *int_clk;
-};
-
-struct int_bus_opp_table {
-	unsigned int idx;
-	unsigned long clk;
-	unsigned long volt;
-};
-
-static struct int_bus_opp_table exynos5_int_opp_table[] = {
-	{LV_0, 266000, 1025000},
-	{LV_1, 200000, 1025000},
-	{LV_2, 160000, 1025000},
-	{LV_3, 133000, 1025000},
-	{LV_4, 100000, 1025000},
-	{0, 0, 0},
-};
-
-static int exynos5_int_setvolt(struct busfreq_data_int *data,
-				unsigned long volt)
-{
-	return regulator_set_voltage(data->vdd_int, volt, MAX_SAFEVOLT);
-}
-
-static int exynos5_busfreq_int_target(struct device *dev, unsigned long *_freq,
-			      u32 flags)
-{
-	int err = 0;
-	struct platform_device *pdev = container_of(dev, struct platform_device,
-						    dev);
-	struct busfreq_data_int *data = platform_get_drvdata(pdev);
-	struct dev_pm_opp *opp;
-	unsigned long old_freq, freq;
-	unsigned long volt;
-
-	rcu_read_lock();
-	opp = devfreq_recommended_opp(dev, _freq, flags);
-	if (IS_ERR(opp)) {
-		rcu_read_unlock();
-		dev_err(dev, "%s: Invalid OPP.\n", __func__);
-		return PTR_ERR(opp);
-	}
-
-	freq = dev_pm_opp_get_freq(opp);
-	volt = dev_pm_opp_get_voltage(opp);
-	rcu_read_unlock();
-
-	old_freq = data->curr_freq;
-
-	if (old_freq == freq)
-		return 0;
-
-	dev_dbg(dev, "targeting %lukHz %luuV\n", freq, volt);
-
-	mutex_lock(&data->lock);
-
-	if (data->disabled)
-		goto out;
-
-	if (freq > exynos5_int_opp_table[0].clk)
-		pm_qos_update_request(&data->int_req, freq * 16 / 1000);
-	else
-		pm_qos_update_request(&data->int_req, -1);
-
-	if (old_freq < freq)
-		err = exynos5_int_setvolt(data, volt);
-	if (err)
-		goto out;
-
-	err = clk_set_rate(data->int_clk, freq * 1000);
-
-	if (err)
-		goto out;
-
-	if (old_freq > freq)
-		err = exynos5_int_setvolt(data, volt);
-	if (err)
-		goto out;
-
-	data->curr_freq = freq;
-out:
-	mutex_unlock(&data->lock);
-	return err;
-}
-
-static int exynos5_int_get_dev_status(struct device *dev,
-				      struct devfreq_dev_status *stat)
-{
-	struct platform_device *pdev = container_of(dev, struct platform_device,
-						    dev);
-	struct busfreq_data_int *data = platform_get_drvdata(pdev);
-	struct busfreq_ppmu_data *ppmu_data = &data->ppmu_data;
-	int busier_dmc;
-
-	exynos_read_ppmu(ppmu_data);
-	busier_dmc = exynos_get_busier_ppmu(ppmu_data);
-
-	stat->current_frequency = data->curr_freq;
-
-	/* Number of cycles spent on memory access */
-	stat->busy_time = ppmu_data->ppmu[busier_dmc].count[PPMU_PMNCNT3];
-	stat->busy_time *= 100 / INT_BUS_SATURATION_RATIO;
-	stat->total_time = ppmu_data->ppmu[busier_dmc].ccnt;
-
-	return 0;
-}
-
-static struct devfreq_dev_profile exynos5_devfreq_int_profile = {
-	.initial_freq		= 160000,
-	.polling_ms		= 100,
-	.target			= exynos5_busfreq_int_target,
-	.get_dev_status		= exynos5_int_get_dev_status,
-};
-
-static int exynos5250_init_int_tables(struct busfreq_data_int *data)
-{
-	int i, err = 0;
-
-	for (i = LV_0; i < _LV_END; i++) {
-		err = dev_pm_opp_add(data->dev, exynos5_int_opp_table[i].clk,
-				exynos5_int_opp_table[i].volt);
-		if (err) {
-			dev_err(data->dev, "Cannot add opp entries.\n");
-			return err;
-		}
-	}
-
-	return 0;
-}
-
-static int exynos5_busfreq_int_pm_notifier_event(struct notifier_block *this,
-		unsigned long event, void *ptr)
-{
-	struct busfreq_data_int *data = container_of(this,
-					struct busfreq_data_int, pm_notifier);
-	struct dev_pm_opp *opp;
-	unsigned long maxfreq = ULONG_MAX;
-	unsigned long freq;
-	unsigned long volt;
-	int err = 0;
-
-	switch (event) {
-	case PM_SUSPEND_PREPARE:
-		/* Set Fastest and Deactivate DVFS */
-		mutex_lock(&data->lock);
-
-		data->disabled = true;
-
-		rcu_read_lock();
-		opp = dev_pm_opp_find_freq_floor(data->dev, &maxfreq);
-		if (IS_ERR(opp)) {
-			rcu_read_unlock();
-			err = PTR_ERR(opp);
-			goto unlock;
-		}
-		freq = dev_pm_opp_get_freq(opp);
-		volt = dev_pm_opp_get_voltage(opp);
-		rcu_read_unlock();
-
-		err = exynos5_int_setvolt(data, volt);
-		if (err)
-			goto unlock;
-
-		err = clk_set_rate(data->int_clk, freq * 1000);
-
-		if (err)
-			goto unlock;
-
-		data->curr_freq = freq;
-unlock:
-		mutex_unlock(&data->lock);
-		if (err)
-			return NOTIFY_BAD;
-		return NOTIFY_OK;
-	case PM_POST_RESTORE:
-	case PM_POST_SUSPEND:
-		/* Reactivate */
-		mutex_lock(&data->lock);
-		data->disabled = false;
-		mutex_unlock(&data->lock);
-		return NOTIFY_OK;
-	}
-
-	return NOTIFY_DONE;
-}
-
-static int exynos5_busfreq_int_probe(struct platform_device *pdev)
-{
-	struct busfreq_data_int *data;
-	struct busfreq_ppmu_data *ppmu_data;
-	struct dev_pm_opp *opp;
-	struct device *dev = &pdev->dev;
-	struct device_node *np;
-	unsigned long initial_freq;
-	unsigned long initial_volt;
-	int err = 0;
-	int i;
-
-	data = devm_kzalloc(&pdev->dev, sizeof(struct busfreq_data_int),
-				GFP_KERNEL);
-	if (data == NULL) {
-		dev_err(dev, "Cannot allocate memory.\n");
-		return -ENOMEM;
-	}
-
-	ppmu_data = &data->ppmu_data;
-	ppmu_data->ppmu_end = PPMU_END;
-	ppmu_data->ppmu = devm_kzalloc(dev,
-				       sizeof(struct exynos_ppmu) * PPMU_END,
-				       GFP_KERNEL);
-	if (!ppmu_data->ppmu) {
-		dev_err(dev, "Failed to allocate memory for exynos_ppmu\n");
-		return -ENOMEM;
-	}
-
-	np = of_find_compatible_node(NULL, NULL, "samsung,exynos5250-ppmu");
-	if (np == NULL) {
-		pr_err("Unable to find PPMU node\n");
-		return -ENOENT;
-	}
-
-	for (i = 0; i < ppmu_data->ppmu_end; i++) {
-		/* map PPMU memory region */
-		ppmu_data->ppmu[i].hw_base = of_iomap(np, i);
-		if (ppmu_data->ppmu[i].hw_base == NULL) {
-			dev_err(&pdev->dev, "failed to map memory region\n");
-			return -ENOMEM;
-		}
-	}
-	data->pm_notifier.notifier_call = exynos5_busfreq_int_pm_notifier_event;
-	data->dev = dev;
-	mutex_init(&data->lock);
-
-	err = exynos5250_init_int_tables(data);
-	if (err)
-		return err;
-
-	data->vdd_int = devm_regulator_get(dev, "vdd_int");
-	if (IS_ERR(data->vdd_int)) {
-		dev_err(dev, "Cannot get the regulator \"vdd_int\"\n");
-		return PTR_ERR(data->vdd_int);
-	}
-
-	data->int_clk = devm_clk_get(dev, "int_clk");
-	if (IS_ERR(data->int_clk)) {
-		dev_err(dev, "Cannot get clock \"int_clk\"\n");
-		return PTR_ERR(data->int_clk);
-	}
-
-	rcu_read_lock();
-	opp = dev_pm_opp_find_freq_floor(dev,
-			&exynos5_devfreq_int_profile.initial_freq);
-	if (IS_ERR(opp)) {
-		rcu_read_unlock();
-		dev_err(dev, "Invalid initial frequency %lu kHz.\n",
-		       exynos5_devfreq_int_profile.initial_freq);
-		return PTR_ERR(opp);
-	}
-	initial_freq = dev_pm_opp_get_freq(opp);
-	initial_volt = dev_pm_opp_get_voltage(opp);
-	rcu_read_unlock();
-	data->curr_freq = initial_freq;
-
-	err = clk_set_rate(data->int_clk, initial_freq * 1000);
-	if (err) {
-		dev_err(dev, "Failed to set initial frequency\n");
-		return err;
-	}
-
-	err = exynos5_int_setvolt(data, initial_volt);
-	if (err)
-		return err;
-
-	platform_set_drvdata(pdev, data);
-
-	busfreq_mon_reset(ppmu_data);
-
-	data->devfreq = devm_devfreq_add_device(dev, &exynos5_devfreq_int_profile,
-					   "simple_ondemand", NULL);
-	if (IS_ERR(data->devfreq))
-		return PTR_ERR(data->devfreq);
-
-	err = devm_devfreq_register_opp_notifier(dev, data->devfreq);
-	if (err < 0) {
-		dev_err(dev, "Failed to register opp notifier\n");
-		return err;
-	}
-
-	err = register_pm_notifier(&data->pm_notifier);
-	if (err) {
-		dev_err(dev, "Failed to setup pm notifier\n");
-		return err;
-	}
-
-	/* TODO: Add a new QOS class for int/mif bus */
-	pm_qos_add_request(&data->int_req, PM_QOS_NETWORK_THROUGHPUT, -1);
-
-	return 0;
-}
-
-static int exynos5_busfreq_int_remove(struct platform_device *pdev)
-{
-	struct busfreq_data_int *data = platform_get_drvdata(pdev);
-
-	pm_qos_remove_request(&data->int_req);
-	unregister_pm_notifier(&data->pm_notifier);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int exynos5_busfreq_int_resume(struct device *dev)
-{
-	struct platform_device *pdev = container_of(dev, struct platform_device,
-						    dev);
-	struct busfreq_data_int *data = platform_get_drvdata(pdev);
-	struct busfreq_ppmu_data *ppmu_data = &data->ppmu_data;
-
-	busfreq_mon_reset(ppmu_data);
-	return 0;
-}
-static const struct dev_pm_ops exynos5_busfreq_int_pm = {
-	.resume	= exynos5_busfreq_int_resume,
-};
-#endif
-static SIMPLE_DEV_PM_OPS(exynos5_busfreq_int_pm_ops, NULL,
-			 exynos5_busfreq_int_resume);
-
-/* platform device pointer for exynos5 devfreq device. */
-static struct platform_device *exynos5_devfreq_pdev;
-
-static struct platform_driver exynos5_busfreq_int_driver = {
-	.probe		= exynos5_busfreq_int_probe,
-	.remove		= exynos5_busfreq_int_remove,
-	.driver		= {
-		.name		= "exynos5-bus-int",
-		.pm		= &exynos5_busfreq_int_pm_ops,
-	},
-};
-
-static int __init exynos5_busfreq_int_init(void)
-{
-	int ret;
-
-	ret = platform_driver_register(&exynos5_busfreq_int_driver);
-	if (ret < 0)
-		goto out;
-
-	exynos5_devfreq_pdev =
-		platform_device_register_simple("exynos5-bus-int", -1, NULL, 0);
-	if (IS_ERR(exynos5_devfreq_pdev)) {
-		ret = PTR_ERR(exynos5_devfreq_pdev);
-		goto out1;
-	}
-
-	return 0;
-out1:
-	platform_driver_unregister(&exynos5_busfreq_int_driver);
-out:
-	return ret;
-}
-late_initcall(exynos5_busfreq_int_init);
-
-static void __exit exynos5_busfreq_int_exit(void)
-{
-	platform_device_unregister(exynos5_devfreq_pdev);
-	platform_driver_unregister(&exynos5_busfreq_int_driver);
-}
-module_exit(exynos5_busfreq_int_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("EXYNOS5 busfreq driver with devfreq framework");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/devfreq/exynos/exynos_ppmu.c linux-libre-4.7-gnu/drivers/devfreq/exynos/exynos_ppmu.c
--- linux-libre-4.6-gnu/drivers/devfreq/exynos/exynos_ppmu.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/devfreq/exynos/exynos_ppmu.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,119 +0,0 @@
-/*
- * Copyright (c) 2012 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * EXYNOS - PPMU support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/io.h>
-
-#include "exynos_ppmu.h"
-
-void exynos_ppmu_reset(void __iomem *ppmu_base)
-{
-	__raw_writel(PPMU_CYCLE_RESET | PPMU_COUNTER_RESET, ppmu_base);
-	__raw_writel(PPMU_ENABLE_CYCLE  |
-		     PPMU_ENABLE_COUNT0 |
-		     PPMU_ENABLE_COUNT1 |
-		     PPMU_ENABLE_COUNT2 |
-		     PPMU_ENABLE_COUNT3,
-		     ppmu_base + PPMU_CNTENS);
-}
-
-void exynos_ppmu_setevent(void __iomem *ppmu_base, unsigned int ch,
-			unsigned int evt)
-{
-	__raw_writel(evt, ppmu_base + PPMU_BEVTSEL(ch));
-}
-
-void exynos_ppmu_start(void __iomem *ppmu_base)
-{
-	__raw_writel(PPMU_ENABLE, ppmu_base);
-}
-
-void exynos_ppmu_stop(void __iomem *ppmu_base)
-{
-	__raw_writel(PPMU_DISABLE, ppmu_base);
-}
-
-unsigned int exynos_ppmu_read(void __iomem *ppmu_base, unsigned int ch)
-{
-	unsigned int total;
-
-	if (ch == PPMU_PMNCNT3)
-		total = ((__raw_readl(ppmu_base + PMCNT_OFFSET(ch)) << 8) |
-			  __raw_readl(ppmu_base + PMCNT_OFFSET(ch + 1)));
-	else
-		total = __raw_readl(ppmu_base + PMCNT_OFFSET(ch));
-
-	return total;
-}
-
-void busfreq_mon_reset(struct busfreq_ppmu_data *ppmu_data)
-{
-	unsigned int i;
-
-	for (i = 0; i < ppmu_data->ppmu_end; i++) {
-		void __iomem *ppmu_base = ppmu_data->ppmu[i].hw_base;
-
-		/* Reset the performance and cycle counters */
-		exynos_ppmu_reset(ppmu_base);
-
-		/* Setup count registers to monitor read/write transactions */
-		ppmu_data->ppmu[i].event[PPMU_PMNCNT3] = RDWR_DATA_COUNT;
-		exynos_ppmu_setevent(ppmu_base, PPMU_PMNCNT3,
-					ppmu_data->ppmu[i].event[PPMU_PMNCNT3]);
-
-		exynos_ppmu_start(ppmu_base);
-	}
-}
-EXPORT_SYMBOL(busfreq_mon_reset);
-
-void exynos_read_ppmu(struct busfreq_ppmu_data *ppmu_data)
-{
-	int i, j;
-
-	for (i = 0; i < ppmu_data->ppmu_end; i++) {
-		void __iomem *ppmu_base = ppmu_data->ppmu[i].hw_base;
-
-		exynos_ppmu_stop(ppmu_base);
-
-		/* Update local data from PPMU */
-		ppmu_data->ppmu[i].ccnt = __raw_readl(ppmu_base + PPMU_CCNT);
-
-		for (j = PPMU_PMNCNT0; j < PPMU_PMNCNT_MAX; j++) {
-			if (ppmu_data->ppmu[i].event[j] == 0)
-				ppmu_data->ppmu[i].count[j] = 0;
-			else
-				ppmu_data->ppmu[i].count[j] =
-					exynos_ppmu_read(ppmu_base, j);
-		}
-	}
-
-	busfreq_mon_reset(ppmu_data);
-}
-EXPORT_SYMBOL(exynos_read_ppmu);
-
-int exynos_get_busier_ppmu(struct busfreq_ppmu_data *ppmu_data)
-{
-	unsigned int count = 0;
-	int i, j, busy = 0;
-
-	for (i = 0; i < ppmu_data->ppmu_end; i++) {
-		for (j = PPMU_PMNCNT0; j < PPMU_PMNCNT_MAX; j++) {
-			if (ppmu_data->ppmu[i].count[j] > count) {
-				count = ppmu_data->ppmu[i].count[j];
-				busy = i;
-			}
-		}
-	}
-
-	return busy;
-}
-EXPORT_SYMBOL(exynos_get_busier_ppmu);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/devfreq/exynos/exynos_ppmu.h linux-libre-4.7-gnu/drivers/devfreq/exynos/exynos_ppmu.h
--- linux-libre-4.6-gnu/drivers/devfreq/exynos/exynos_ppmu.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/devfreq/exynos/exynos_ppmu.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,86 +0,0 @@
-/*
- * Copyright (c) 2012 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * EXYNOS PPMU header
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __DEVFREQ_EXYNOS_PPMU_H
-#define __DEVFREQ_EXYNOS_PPMU_H __FILE__
-
-#include <linux/ktime.h>
-
-/* For PPMU Control */
-#define PPMU_ENABLE             BIT(0)
-#define PPMU_DISABLE            0x0
-#define PPMU_CYCLE_RESET        BIT(1)
-#define PPMU_COUNTER_RESET      BIT(2)
-
-#define PPMU_ENABLE_COUNT0      BIT(0)
-#define PPMU_ENABLE_COUNT1      BIT(1)
-#define PPMU_ENABLE_COUNT2      BIT(2)
-#define PPMU_ENABLE_COUNT3      BIT(3)
-#define PPMU_ENABLE_CYCLE       BIT(31)
-
-#define PPMU_CNTENS		0x10
-#define PPMU_FLAG		0x50
-#define PPMU_CCNT_OVERFLOW	BIT(31)
-#define PPMU_CCNT		0x100
-
-#define PPMU_PMCNT0		0x110
-#define PPMU_PMCNT_OFFSET	0x10
-#define PMCNT_OFFSET(x)		(PPMU_PMCNT0 + (PPMU_PMCNT_OFFSET * x))
-
-#define PPMU_BEVT0SEL		0x1000
-#define PPMU_BEVTSEL_OFFSET	0x100
-#define PPMU_BEVTSEL(x)		(PPMU_BEVT0SEL + (ch * PPMU_BEVTSEL_OFFSET))
-
-/* For Event Selection */
-#define RD_DATA_COUNT		0x5
-#define WR_DATA_COUNT		0x6
-#define RDWR_DATA_COUNT		0x7
-
-enum ppmu_counter {
-	PPMU_PMNCNT0,
-	PPMU_PMCCNT1,
-	PPMU_PMNCNT2,
-	PPMU_PMNCNT3,
-	PPMU_PMNCNT_MAX,
-};
-
-struct bus_opp_table {
-	unsigned int idx;
-	unsigned long clk;
-	unsigned long volt;
-};
-
-struct exynos_ppmu {
-	void __iomem *hw_base;
-	unsigned int ccnt;
-	unsigned int event[PPMU_PMNCNT_MAX];
-	unsigned int count[PPMU_PMNCNT_MAX];
-	unsigned long long ns;
-	ktime_t reset_time;
-	bool ccnt_overflow;
-	bool count_overflow[PPMU_PMNCNT_MAX];
-};
-
-struct busfreq_ppmu_data {
-	struct exynos_ppmu *ppmu;
-	int ppmu_end;
-};
-
-void exynos_ppmu_reset(void __iomem *ppmu_base);
-void exynos_ppmu_setevent(void __iomem *ppmu_base, unsigned int ch,
-			unsigned int evt);
-void exynos_ppmu_start(void __iomem *ppmu_base);
-void exynos_ppmu_stop(void __iomem *ppmu_base);
-unsigned int exynos_ppmu_read(void __iomem *ppmu_base, unsigned int ch);
-void busfreq_mon_reset(struct busfreq_ppmu_data *ppmu_data);
-void exynos_read_ppmu(struct busfreq_ppmu_data *ppmu_data);
-int exynos_get_busier_ppmu(struct busfreq_ppmu_data *ppmu_data);
-#endif /* __DEVFREQ_EXYNOS_PPMU_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/devfreq/exynos/Makefile linux-libre-4.7-gnu/drivers/devfreq/exynos/Makefile
--- linux-libre-4.6-gnu/drivers/devfreq/exynos/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/devfreq/exynos/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,3 +0,0 @@
-# Exynos DEVFREQ Drivers
-obj-$(CONFIG_ARM_EXYNOS4_BUS_DEVFREQ)	+= exynos_ppmu.o exynos4_bus.o
-obj-$(CONFIG_ARM_EXYNOS5_BUS_DEVFREQ)	+= exynos_ppmu.o exynos5_bus.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/devfreq/exynos-bus.c linux-libre-4.7-gnu/drivers/devfreq/exynos-bus.c
--- linux-libre-4.6-gnu/drivers/devfreq/exynos-bus.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/devfreq/exynos-bus.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,570 @@
+/*
+ * Generic Exynos Bus frequency driver with DEVFREQ Framework
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Author : Chanwoo Choi <cw00.choi@samsung.com>
+ *
+ * This driver support Exynos Bus frequency feature by using
+ * DEVFREQ framework and is based on drivers/devfreq/exynos/exynos4_bus.c.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/devfreq.h>
+#include <linux/devfreq-event.h>
+#include <linux/device.h>
+#include <linux/export.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/pm_opp.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+
+#define DEFAULT_SATURATION_RATIO	40
+#define DEFAULT_VOLTAGE_TOLERANCE	2
+
+struct exynos_bus {
+	struct device *dev;
+
+	struct devfreq *devfreq;
+	struct devfreq_event_dev **edev;
+	unsigned int edev_count;
+	struct mutex lock;
+
+	struct dev_pm_opp *curr_opp;
+
+	struct regulator *regulator;
+	struct clk *clk;
+	unsigned int voltage_tolerance;
+	unsigned int ratio;
+};
+
+/*
+ * Control the devfreq-event device to get the current state of bus
+ */
+#define exynos_bus_ops_edev(ops)				\
+static int exynos_bus_##ops(struct exynos_bus *bus)		\
+{								\
+	int i, ret;						\
+								\
+	for (i = 0; i < bus->edev_count; i++) {			\
+		if (!bus->edev[i])				\
+			continue;				\
+		ret = devfreq_event_##ops(bus->edev[i]);	\
+		if (ret < 0)					\
+			return ret;				\
+	}							\
+								\
+	return 0;						\
+}
+exynos_bus_ops_edev(enable_edev);
+exynos_bus_ops_edev(disable_edev);
+exynos_bus_ops_edev(set_event);
+
+static int exynos_bus_get_event(struct exynos_bus *bus,
+				struct devfreq_event_data *edata)
+{
+	struct devfreq_event_data event_data;
+	unsigned long load_count = 0, total_count = 0;
+	int i, ret = 0;
+
+	for (i = 0; i < bus->edev_count; i++) {
+		if (!bus->edev[i])
+			continue;
+
+		ret = devfreq_event_get_event(bus->edev[i], &event_data);
+		if (ret < 0)
+			return ret;
+
+		if (i == 0 || event_data.load_count > load_count) {
+			load_count = event_data.load_count;
+			total_count = event_data.total_count;
+		}
+	}
+
+	edata->load_count = load_count;
+	edata->total_count = total_count;
+
+	return ret;
+}
+
+/*
+ * Must necessary function for devfreq simple-ondemand governor
+ */
+static int exynos_bus_target(struct device *dev, unsigned long *freq, u32 flags)
+{
+	struct exynos_bus *bus = dev_get_drvdata(dev);
+	struct dev_pm_opp *new_opp;
+	unsigned long old_freq, new_freq, old_volt, new_volt, tol;
+	int ret = 0;
+
+	/* Get new opp-bus instance according to new bus clock */
+	rcu_read_lock();
+	new_opp = devfreq_recommended_opp(dev, freq, flags);
+	if (IS_ERR(new_opp)) {
+		dev_err(dev, "failed to get recommended opp instance\n");
+		rcu_read_unlock();
+		return PTR_ERR(new_opp);
+	}
+
+	new_freq = dev_pm_opp_get_freq(new_opp);
+	new_volt = dev_pm_opp_get_voltage(new_opp);
+	old_freq = dev_pm_opp_get_freq(bus->curr_opp);
+	old_volt = dev_pm_opp_get_voltage(bus->curr_opp);
+	rcu_read_unlock();
+
+	if (old_freq == new_freq)
+		return 0;
+	tol = new_volt * bus->voltage_tolerance / 100;
+
+	/* Change voltage and frequency according to new OPP level */
+	mutex_lock(&bus->lock);
+
+	if (old_freq < new_freq) {
+		ret = regulator_set_voltage_tol(bus->regulator, new_volt, tol);
+		if (ret < 0) {
+			dev_err(bus->dev, "failed to set voltage\n");
+			goto out;
+		}
+	}
+
+	ret = clk_set_rate(bus->clk, new_freq);
+	if (ret < 0) {
+		dev_err(dev, "failed to change clock of bus\n");
+		clk_set_rate(bus->clk, old_freq);
+		goto out;
+	}
+
+	if (old_freq > new_freq) {
+		ret = regulator_set_voltage_tol(bus->regulator, new_volt, tol);
+		if (ret < 0) {
+			dev_err(bus->dev, "failed to set voltage\n");
+			goto out;
+		}
+	}
+	bus->curr_opp = new_opp;
+
+	dev_dbg(dev, "Set the frequency of bus (%lukHz -> %lukHz)\n",
+			old_freq/1000, new_freq/1000);
+out:
+	mutex_unlock(&bus->lock);
+
+	return ret;
+}
+
+static int exynos_bus_get_dev_status(struct device *dev,
+				     struct devfreq_dev_status *stat)
+{
+	struct exynos_bus *bus = dev_get_drvdata(dev);
+	struct devfreq_event_data edata;
+	int ret;
+
+	rcu_read_lock();
+	stat->current_frequency = dev_pm_opp_get_freq(bus->curr_opp);
+	rcu_read_unlock();
+
+	ret = exynos_bus_get_event(bus, &edata);
+	if (ret < 0) {
+		stat->total_time = stat->busy_time = 0;
+		goto err;
+	}
+
+	stat->busy_time = (edata.load_count * 100) / bus->ratio;
+	stat->total_time = edata.total_count;
+
+	dev_dbg(dev, "Usage of devfreq-event : %lu/%lu\n", stat->busy_time,
+							stat->total_time);
+
+err:
+	ret = exynos_bus_set_event(bus);
+	if (ret < 0) {
+		dev_err(dev, "failed to set event to devfreq-event devices\n");
+		return ret;
+	}
+
+	return ret;
+}
+
+static void exynos_bus_exit(struct device *dev)
+{
+	struct exynos_bus *bus = dev_get_drvdata(dev);
+	int ret;
+
+	ret = exynos_bus_disable_edev(bus);
+	if (ret < 0)
+		dev_warn(dev, "failed to disable the devfreq-event devices\n");
+
+	if (bus->regulator)
+		regulator_disable(bus->regulator);
+
+	dev_pm_opp_of_remove_table(dev);
+	clk_disable_unprepare(bus->clk);
+}
+
+/*
+ * Must necessary function for devfreq passive governor
+ */
+static int exynos_bus_passive_target(struct device *dev, unsigned long *freq,
+					u32 flags)
+{
+	struct exynos_bus *bus = dev_get_drvdata(dev);
+	struct dev_pm_opp *new_opp;
+	unsigned long old_freq, new_freq;
+	int ret = 0;
+
+	/* Get new opp-bus instance according to new bus clock */
+	rcu_read_lock();
+	new_opp = devfreq_recommended_opp(dev, freq, flags);
+	if (IS_ERR(new_opp)) {
+		dev_err(dev, "failed to get recommended opp instance\n");
+		rcu_read_unlock();
+		return PTR_ERR(new_opp);
+	}
+
+	new_freq = dev_pm_opp_get_freq(new_opp);
+	old_freq = dev_pm_opp_get_freq(bus->curr_opp);
+	rcu_read_unlock();
+
+	if (old_freq == new_freq)
+		return 0;
+
+	/* Change the frequency according to new OPP level */
+	mutex_lock(&bus->lock);
+
+	ret = clk_set_rate(bus->clk, new_freq);
+	if (ret < 0) {
+		dev_err(dev, "failed to set the clock of bus\n");
+		goto out;
+	}
+
+	*freq = new_freq;
+	bus->curr_opp = new_opp;
+
+	dev_dbg(dev, "Set the frequency of bus (%lukHz -> %lukHz)\n",
+			old_freq/1000, new_freq/1000);
+out:
+	mutex_unlock(&bus->lock);
+
+	return ret;
+}
+
+static void exynos_bus_passive_exit(struct device *dev)
+{
+	struct exynos_bus *bus = dev_get_drvdata(dev);
+
+	dev_pm_opp_of_remove_table(dev);
+	clk_disable_unprepare(bus->clk);
+}
+
+static int exynos_bus_parent_parse_of(struct device_node *np,
+					struct exynos_bus *bus)
+{
+	struct device *dev = bus->dev;
+	int i, ret, count, size;
+
+	/* Get the regulator to provide each bus with the power */
+	bus->regulator = devm_regulator_get(dev, "vdd");
+	if (IS_ERR(bus->regulator)) {
+		dev_err(dev, "failed to get VDD regulator\n");
+		return PTR_ERR(bus->regulator);
+	}
+
+	ret = regulator_enable(bus->regulator);
+	if (ret < 0) {
+		dev_err(dev, "failed to enable VDD regulator\n");
+		return ret;
+	}
+
+	/*
+	 * Get the devfreq-event devices to get the current utilization of
+	 * buses. This raw data will be used in devfreq ondemand governor.
+	 */
+	count = devfreq_event_get_edev_count(dev);
+	if (count < 0) {
+		dev_err(dev, "failed to get the count of devfreq-event dev\n");
+		ret = count;
+		goto err_regulator;
+	}
+	bus->edev_count = count;
+
+	size = sizeof(*bus->edev) * count;
+	bus->edev = devm_kzalloc(dev, size, GFP_KERNEL);
+	if (!bus->edev) {
+		ret = -ENOMEM;
+		goto err_regulator;
+	}
+
+	for (i = 0; i < count; i++) {
+		bus->edev[i] = devfreq_event_get_edev_by_phandle(dev, i);
+		if (IS_ERR(bus->edev[i])) {
+			ret = -EPROBE_DEFER;
+			goto err_regulator;
+		}
+	}
+
+	/*
+	 * Optionally, Get the saturation ratio according to Exynos SoC
+	 * When measuring the utilization of each AXI bus with devfreq-event
+	 * devices, the measured real cycle might be much lower than the
+	 * total cycle of bus during sampling rate. In result, the devfreq
+	 * simple-ondemand governor might not decide to change the current
+	 * frequency due to too utilization (= real cycle/total cycle).
+	 * So, this property is used to adjust the utilization when calculating
+	 * the busy_time in exynos_bus_get_dev_status().
+	 */
+	if (of_property_read_u32(np, "exynos,saturation-ratio", &bus->ratio))
+		bus->ratio = DEFAULT_SATURATION_RATIO;
+
+	if (of_property_read_u32(np, "exynos,voltage-tolerance",
+					&bus->voltage_tolerance))
+		bus->voltage_tolerance = DEFAULT_VOLTAGE_TOLERANCE;
+
+	return 0;
+
+err_regulator:
+	regulator_disable(bus->regulator);
+
+	return ret;
+}
+
+static int exynos_bus_parse_of(struct device_node *np,
+			      struct exynos_bus *bus)
+{
+	struct device *dev = bus->dev;
+	unsigned long rate;
+	int ret;
+
+	/* Get the clock to provide each bus with source clock */
+	bus->clk = devm_clk_get(dev, "bus");
+	if (IS_ERR(bus->clk)) {
+		dev_err(dev, "failed to get bus clock\n");
+		return PTR_ERR(bus->clk);
+	}
+
+	ret = clk_prepare_enable(bus->clk);
+	if (ret < 0) {
+		dev_err(dev, "failed to get enable clock\n");
+		return ret;
+	}
+
+	/* Get the freq and voltage from OPP table to scale the bus freq */
+	rcu_read_lock();
+	ret = dev_pm_opp_of_add_table(dev);
+	if (ret < 0) {
+		dev_err(dev, "failed to get OPP table\n");
+		rcu_read_unlock();
+		goto err_clk;
+	}
+
+	rate = clk_get_rate(bus->clk);
+	bus->curr_opp = devfreq_recommended_opp(dev, &rate, 0);
+	if (IS_ERR(bus->curr_opp)) {
+		dev_err(dev, "failed to find dev_pm_opp\n");
+		rcu_read_unlock();
+		ret = PTR_ERR(bus->curr_opp);
+		goto err_opp;
+	}
+	rcu_read_unlock();
+
+	return 0;
+
+err_opp:
+	dev_pm_opp_of_remove_table(dev);
+err_clk:
+	clk_disable_unprepare(bus->clk);
+
+	return ret;
+}
+
+static int exynos_bus_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct devfreq_dev_profile *profile;
+	struct devfreq_simple_ondemand_data *ondemand_data;
+	struct devfreq_passive_data *passive_data;
+	struct devfreq *parent_devfreq;
+	struct exynos_bus *bus;
+	int ret, max_state;
+	unsigned long min_freq, max_freq;
+
+	if (!np) {
+		dev_err(dev, "failed to find devicetree node\n");
+		return -EINVAL;
+	}
+
+	bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL);
+	if (!bus)
+		return -ENOMEM;
+	mutex_init(&bus->lock);
+	bus->dev = &pdev->dev;
+	platform_set_drvdata(pdev, bus);
+
+	/* Parse the device-tree to get the resource information */
+	ret = exynos_bus_parse_of(np, bus);
+	if (ret < 0)
+		goto err;
+
+	profile = devm_kzalloc(dev, sizeof(*profile), GFP_KERNEL);
+	if (!profile) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	if (of_parse_phandle(dev->of_node, "devfreq", 0))
+		goto passive;
+	else
+		ret = exynos_bus_parent_parse_of(np, bus);
+
+	if (ret < 0)
+		goto err;
+
+	/* Initialize the struct profile and governor data for parent device */
+	profile->polling_ms = 50;
+	profile->target = exynos_bus_target;
+	profile->get_dev_status = exynos_bus_get_dev_status;
+	profile->exit = exynos_bus_exit;
+
+	ondemand_data = devm_kzalloc(dev, sizeof(*ondemand_data), GFP_KERNEL);
+	if (!ondemand_data) {
+		ret = -ENOMEM;
+		goto err;
+	}
+	ondemand_data->upthreshold = 40;
+	ondemand_data->downdifferential = 5;
+
+	/* Add devfreq device to monitor and handle the exynos bus */
+	bus->devfreq = devm_devfreq_add_device(dev, profile, "simple_ondemand",
+						ondemand_data);
+	if (IS_ERR(bus->devfreq)) {
+		dev_err(dev, "failed to add devfreq device\n");
+		ret = PTR_ERR(bus->devfreq);
+		goto err;
+	}
+
+	/* Register opp_notifier to catch the change of OPP  */
+	ret = devm_devfreq_register_opp_notifier(dev, bus->devfreq);
+	if (ret < 0) {
+		dev_err(dev, "failed to register opp notifier\n");
+		goto err;
+	}
+
+	/*
+	 * Enable devfreq-event to get raw data which is used to determine
+	 * current bus load.
+	 */
+	ret = exynos_bus_enable_edev(bus);
+	if (ret < 0) {
+		dev_err(dev, "failed to enable devfreq-event devices\n");
+		goto err;
+	}
+
+	ret = exynos_bus_set_event(bus);
+	if (ret < 0) {
+		dev_err(dev, "failed to set event to devfreq-event devices\n");
+		goto err;
+	}
+
+	goto out;
+passive:
+	/* Initialize the struct profile and governor data for passive device */
+	profile->target = exynos_bus_passive_target;
+	profile->exit = exynos_bus_passive_exit;
+
+	/* Get the instance of parent devfreq device */
+	parent_devfreq = devfreq_get_devfreq_by_phandle(dev, 0);
+	if (IS_ERR(parent_devfreq)) {
+		ret = -EPROBE_DEFER;
+		goto err;
+	}
+
+	passive_data = devm_kzalloc(dev, sizeof(*passive_data), GFP_KERNEL);
+	if (!passive_data) {
+		ret = -ENOMEM;
+		goto err;
+	}
+	passive_data->parent = parent_devfreq;
+
+	/* Add devfreq device for exynos bus with passive governor */
+	bus->devfreq = devm_devfreq_add_device(dev, profile, "passive",
+						passive_data);
+	if (IS_ERR(bus->devfreq)) {
+		dev_err(dev,
+			"failed to add devfreq dev with passive governor\n");
+		ret = -EPROBE_DEFER;
+		goto err;
+	}
+
+out:
+	max_state = bus->devfreq->profile->max_state;
+	min_freq = (bus->devfreq->profile->freq_table[0] / 1000);
+	max_freq = (bus->devfreq->profile->freq_table[max_state - 1] / 1000);
+	pr_info("exynos-bus: new bus device registered: %s (%6ld KHz ~ %6ld KHz)\n",
+			dev_name(dev), min_freq, max_freq);
+
+	return 0;
+
+err:
+	dev_pm_opp_of_remove_table(dev);
+	clk_disable_unprepare(bus->clk);
+
+	return ret;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int exynos_bus_resume(struct device *dev)
+{
+	struct exynos_bus *bus = dev_get_drvdata(dev);
+	int ret;
+
+	ret = exynos_bus_enable_edev(bus);
+	if (ret < 0) {
+		dev_err(dev, "failed to enable the devfreq-event devices\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int exynos_bus_suspend(struct device *dev)
+{
+	struct exynos_bus *bus = dev_get_drvdata(dev);
+	int ret;
+
+	ret = exynos_bus_disable_edev(bus);
+	if (ret < 0) {
+		dev_err(dev, "failed to disable the devfreq-event devices\n");
+		return ret;
+	}
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops exynos_bus_pm = {
+	SET_SYSTEM_SLEEP_PM_OPS(exynos_bus_suspend, exynos_bus_resume)
+};
+
+static const struct of_device_id exynos_bus_of_match[] = {
+	{ .compatible = "samsung,exynos-bus", },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, exynos_bus_of_match);
+
+static struct platform_driver exynos_bus_platdrv = {
+	.probe		= exynos_bus_probe,
+	.driver = {
+		.name	= "exynos-bus",
+		.pm	= &exynos_bus_pm,
+		.of_match_table = of_match_ptr(exynos_bus_of_match),
+	},
+};
+module_platform_driver(exynos_bus_platdrv);
+
+MODULE_DESCRIPTION("Generic Exynos Bus frequency driver");
+MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/devfreq/governor_passive.c linux-libre-4.7-gnu/drivers/devfreq/governor_passive.c
--- linux-libre-4.6-gnu/drivers/devfreq/governor_passive.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/devfreq/governor_passive.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,205 @@
+/*
+ * linux/drivers/devfreq/governor_passive.c
+ *
+ * Copyright (C) 2016 Samsung Electronics
+ * Author: Chanwoo Choi <cw00.choi@samsung.com>
+ * Author: MyungJoo Ham <myungjoo.ham@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/devfreq.h>
+#include "governor.h"
+
+static int devfreq_passive_get_target_freq(struct devfreq *devfreq,
+					unsigned long *freq)
+{
+	struct devfreq_passive_data *p_data
+			= (struct devfreq_passive_data *)devfreq->data;
+	struct devfreq *parent_devfreq = (struct devfreq *)p_data->parent;
+	unsigned long child_freq = ULONG_MAX;
+	struct dev_pm_opp *opp;
+	int i, count, ret = 0;
+
+	/*
+	 * If the devfreq device with passive governor has the specific method
+	 * to determine the next frequency, should use the get_target_freq()
+	 * of struct devfreq_passive_data.
+	 */
+	if (p_data->get_target_freq) {
+		ret = p_data->get_target_freq(devfreq, freq);
+		goto out;
+	}
+
+	/*
+	 * If the parent and passive devfreq device uses the OPP table,
+	 * get the next frequency by using the OPP table.
+	 */
+
+	/*
+	 * - parent devfreq device uses the governors except for passive.
+	 * - passive devfreq device uses the passive governor.
+	 *
+	 * Each devfreq has the OPP table. After deciding the new frequency
+	 * from the governor of parent devfreq device, the passive governor
+	 * need to get the index of new frequency on OPP table of parent
+	 * device. And then the index is used for getting the suitable
+	 * new frequency for passive devfreq device.
+	 */
+	if (!devfreq->profile || !devfreq->profile->freq_table
+		|| devfreq->profile->max_state <= 0)
+		return -EINVAL;
+
+	/*
+	 * The passive governor have to get the correct frequency from OPP
+	 * list of parent device. Because in this case, *freq is temporary
+	 * value which is decided by ondemand governor.
+	 */
+	rcu_read_lock();
+	opp = devfreq_recommended_opp(parent_devfreq->dev.parent, freq, 0);
+	rcu_read_unlock();
+	if (IS_ERR(opp)) {
+		ret = PTR_ERR(opp);
+		goto out;
+	}
+
+	/*
+	 * Get the OPP table's index of decided freqeuncy by governor
+	 * of parent device.
+	 */
+	for (i = 0; i < parent_devfreq->profile->max_state; i++)
+		if (parent_devfreq->profile->freq_table[i] == *freq)
+			break;
+
+	if (i == parent_devfreq->profile->max_state) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* Get the suitable frequency by using index of parent device. */
+	if (i < devfreq->profile->max_state) {
+		child_freq = devfreq->profile->freq_table[i];
+	} else {
+		count = devfreq->profile->max_state;
+		child_freq = devfreq->profile->freq_table[count - 1];
+	}
+
+	/* Return the suitable frequency for passive device. */
+	*freq = child_freq;
+
+out:
+	return ret;
+}
+
+static int update_devfreq_passive(struct devfreq *devfreq, unsigned long freq)
+{
+	int ret;
+
+	if (!devfreq->governor)
+		return -EINVAL;
+
+	mutex_lock_nested(&devfreq->lock, SINGLE_DEPTH_NESTING);
+
+	ret = devfreq->governor->get_target_freq(devfreq, &freq);
+	if (ret < 0)
+		goto out;
+
+	ret = devfreq->profile->target(devfreq->dev.parent, &freq, 0);
+	if (ret < 0)
+		goto out;
+
+	devfreq->previous_freq = freq;
+
+out:
+	mutex_unlock(&devfreq->lock);
+
+	return 0;
+}
+
+static int devfreq_passive_notifier_call(struct notifier_block *nb,
+				unsigned long event, void *ptr)
+{
+	struct devfreq_passive_data *data
+			= container_of(nb, struct devfreq_passive_data, nb);
+	struct devfreq *devfreq = (struct devfreq *)data->this;
+	struct devfreq *parent = (struct devfreq *)data->parent;
+	struct devfreq_freqs *freqs = (struct devfreq_freqs *)ptr;
+	unsigned long freq = freqs->new;
+
+	switch (event) {
+	case DEVFREQ_PRECHANGE:
+		if (parent->previous_freq > freq)
+			update_devfreq_passive(devfreq, freq);
+		break;
+	case DEVFREQ_POSTCHANGE:
+		if (parent->previous_freq < freq)
+			update_devfreq_passive(devfreq, freq);
+		break;
+	}
+
+	return NOTIFY_DONE;
+}
+
+static int devfreq_passive_event_handler(struct devfreq *devfreq,
+				unsigned int event, void *data)
+{
+	struct device *dev = devfreq->dev.parent;
+	struct devfreq_passive_data *p_data
+			= (struct devfreq_passive_data *)devfreq->data;
+	struct devfreq *parent = (struct devfreq *)p_data->parent;
+	struct notifier_block *nb = &p_data->nb;
+	int ret = 0;
+
+	if (!parent)
+		return -EPROBE_DEFER;
+
+	switch (event) {
+	case DEVFREQ_GOV_START:
+		if (!p_data->this)
+			p_data->this = devfreq;
+
+		nb->notifier_call = devfreq_passive_notifier_call;
+		ret = devm_devfreq_register_notifier(dev, parent, nb,
+					DEVFREQ_TRANSITION_NOTIFIER);
+		break;
+	case DEVFREQ_GOV_STOP:
+		devm_devfreq_unregister_notifier(dev, parent, nb,
+					DEVFREQ_TRANSITION_NOTIFIER);
+		break;
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+static struct devfreq_governor devfreq_passive = {
+	.name = "passive",
+	.get_target_freq = devfreq_passive_get_target_freq,
+	.event_handler = devfreq_passive_event_handler,
+};
+
+static int __init devfreq_passive_init(void)
+{
+	return devfreq_add_governor(&devfreq_passive);
+}
+subsys_initcall(devfreq_passive_init);
+
+static void __exit devfreq_passive_exit(void)
+{
+	int ret;
+
+	ret = devfreq_remove_governor(&devfreq_passive);
+	if (ret)
+		pr_err("%s: failed remove governor %d\n", __func__, ret);
+}
+module_exit(devfreq_passive_exit);
+
+MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
+MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
+MODULE_DESCRIPTION("DEVFREQ Passive governor");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/devfreq/Kconfig linux-libre-4.7-gnu/drivers/devfreq/Kconfig
--- linux-libre-4.6-gnu/drivers/devfreq/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/devfreq/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -64,30 +64,32 @@ config DEVFREQ_GOV_USERSPACE
 	  Otherwise, the governor does not change the frequency
 	  given at the initialization.
 
+config DEVFREQ_GOV_PASSIVE
+	tristate "Passive"
+	help
+	  Sets the frequency based on the frequency of its parent devfreq
+	  device. This governor does not change the frequency by itself
+	  through sysfs entries. The passive governor recommends that
+	  devfreq device uses the OPP table to get the frequency/voltage.
+
 comment "DEVFREQ Drivers"
 
-config ARM_EXYNOS4_BUS_DEVFREQ
-	bool "ARM Exynos4210/4212/4412 Memory Bus DEVFREQ Driver"
-	depends on (CPU_EXYNOS4210 || SOC_EXYNOS4212 || SOC_EXYNOS4412) && !ARCH_MULTIPLATFORM
+config ARM_EXYNOS_BUS_DEVFREQ
+	bool "ARM EXYNOS Generic Memory Bus DEVFREQ Driver"
+	depends on ARCH_EXYNOS
 	select DEVFREQ_GOV_SIMPLE_ONDEMAND
+	select DEVFREQ_GOV_PASSIVE
+	select DEVFREQ_EVENT_EXYNOS_PPMU
+	select PM_DEVFREQ_EVENT
 	select PM_OPP
 	help
-	  This adds the DEVFREQ driver for Exynos4210 memory bus (vdd_int)
-	  and Exynos4212/4412 memory interface and bus (vdd_mif + vdd_int).
-	  It reads PPMU counters of memory controllers and adjusts
-	  the operating frequencies and voltages with OPP support.
+	  This adds the common DEVFREQ driver for Exynos Memory bus. Exynos
+	  Memory bus has one more group of memory bus (e.g, MIF and INT block).
+	  Each memory bus group could contain many memoby bus block. It reads
+	  PPMU counters of memory controllers by using DEVFREQ-event device
+	  and adjusts the operating frequencies and voltages with OPP support.
 	  This does not yet operate with optimal voltages.
 
-config ARM_EXYNOS5_BUS_DEVFREQ
-	tristate "ARM Exynos5250 Bus DEVFREQ Driver"
-	depends on SOC_EXYNOS5250
-	select DEVFREQ_GOV_SIMPLE_ONDEMAND
-	select PM_OPP
-	help
-	  This adds the DEVFREQ driver for Exynos5250 bus interface (vdd_int).
-	  It reads PPMU counters of memory controllers and adjusts the
-	  operating frequencies and voltages with OPP support.
-
 config ARM_TEGRA_DEVFREQ
        tristate "Tegra DEVFREQ Driver"
        depends on ARCH_TEGRA_124_SOC
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/devfreq/Makefile linux-libre-4.7-gnu/drivers/devfreq/Makefile
--- linux-libre-4.6-gnu/drivers/devfreq/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/devfreq/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -4,10 +4,10 @@ obj-$(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND
 obj-$(CONFIG_DEVFREQ_GOV_PERFORMANCE)	+= governor_performance.o
 obj-$(CONFIG_DEVFREQ_GOV_POWERSAVE)	+= governor_powersave.o
 obj-$(CONFIG_DEVFREQ_GOV_USERSPACE)	+= governor_userspace.o
+obj-$(CONFIG_DEVFREQ_GOV_PASSIVE)	+= governor_passive.o
 
 # DEVFREQ Drivers
-obj-$(CONFIG_ARM_EXYNOS4_BUS_DEVFREQ)	+= exynos/
-obj-$(CONFIG_ARM_EXYNOS5_BUS_DEVFREQ)	+= exynos/
+obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ)	+= exynos-bus.o
 obj-$(CONFIG_ARM_TEGRA_DEVFREQ)		+= tegra-devfreq.o
 
 # DEVFREQ Event Drivers
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma/amba-pl08x.c linux-libre-4.7-gnu/drivers/dma/amba-pl08x.c
--- linux-libre-4.6-gnu/drivers/dma/amba-pl08x.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/dma/amba-pl08x.c	2016-07-24 15:23:50.000000000 -0400
@@ -107,16 +107,20 @@ struct pl08x_driver_data;
 /**
  * struct vendor_data - vendor-specific config parameters for PL08x derivatives
  * @channels: the number of channels available in this variant
+ * @signals: the number of request signals available from the hardware
  * @dualmaster: whether this version supports dual AHB masters or not.
  * @nomadik: whether the channels have Nomadik security extension bits
  *	that need to be checked for permission before use and some registers are
  *	missing
  * @pl080s: whether this version is a PL080S, which has separate register and
  *	LLI word for transfer size.
+ * @max_transfer_size: the maximum single element transfer size for this
+ *	PL08x variant.
  */
 struct vendor_data {
 	u8 config_offset;
 	u8 channels;
+	u8 signals;
 	bool dualmaster;
 	bool nomadik;
 	bool pl080s;
@@ -235,7 +239,7 @@ struct pl08x_dma_chan {
 	struct virt_dma_chan vc;
 	struct pl08x_phy_chan *phychan;
 	const char *name;
-	const struct pl08x_channel_data *cd;
+	struct pl08x_channel_data *cd;
 	struct dma_slave_config cfg;
 	struct pl08x_txd *at;
 	struct pl08x_driver_data *host;
@@ -1909,6 +1913,12 @@ static int pl08x_dma_init_virtual_channe
 
 		if (slave) {
 			chan->cd = &pl08x->pd->slave_channels[i];
+			/*
+			 * Some implementations have muxed signals, whereas some
+			 * use a mux in front of the signals and need dynamic
+			 * assignment of signals.
+			 */
+			chan->signal = i;
 			pl08x_dma_slave_init(chan);
 		} else {
 			chan->cd = &pl08x->pd->memcpy_channel;
@@ -2050,40 +2060,33 @@ static struct dma_chan *pl08x_of_xlate(s
 				       struct of_dma *ofdma)
 {
 	struct pl08x_driver_data *pl08x = ofdma->of_dma_data;
-	struct pl08x_channel_data *data;
-	struct pl08x_dma_chan *chan;
 	struct dma_chan *dma_chan;
+	struct pl08x_dma_chan *plchan;
 
 	if (!pl08x)
 		return NULL;
 
-	if (dma_spec->args_count != 2)
+	if (dma_spec->args_count != 2) {
+		dev_err(&pl08x->adev->dev,
+			"DMA channel translation requires two cells\n");
 		return NULL;
+	}
 
 	dma_chan = pl08x_find_chan_id(pl08x, dma_spec->args[0]);
-	if (dma_chan)
-		return dma_get_slave_channel(dma_chan);
-
-	chan = devm_kzalloc(pl08x->slave.dev, sizeof(*chan) + sizeof(*data),
-			    GFP_KERNEL);
-	if (!chan)
+	if (!dma_chan) {
+		dev_err(&pl08x->adev->dev,
+			"DMA slave channel not found\n");
 		return NULL;
+	}
 
-	data = (void *)&chan[1];
-	data->bus_id = "(none)";
-	data->periph_buses = dma_spec->args[1];
-
-	chan->cd = data;
-	chan->host = pl08x;
-	chan->slave = true;
-	chan->name = data->bus_id;
-	chan->state = PL08X_CHAN_IDLE;
-	chan->signal = dma_spec->args[0];
-	chan->vc.desc_free = pl08x_desc_free;
-
-	vchan_init(&chan->vc, &pl08x->slave);
+	plchan = to_pl08x_chan(dma_chan);
+	dev_dbg(&pl08x->adev->dev,
+		"translated channel for signal %d\n",
+		dma_spec->args[0]);
 
-	return dma_get_slave_channel(&chan->vc.chan);
+	/* Augment channel data for applicable AHB buses */
+	plchan->cd->periph_buses = dma_spec->args[1];
+	return dma_get_slave_channel(dma_chan);
 }
 
 static int pl08x_of_probe(struct amba_device *adev,
@@ -2091,9 +2094,11 @@ static int pl08x_of_probe(struct amba_de
 			  struct device_node *np)
 {
 	struct pl08x_platform_data *pd;
+	struct pl08x_channel_data *chanp = NULL;
 	u32 cctl_memcpy = 0;
 	u32 val;
 	int ret;
+	int i;
 
 	pd = devm_kzalloc(&adev->dev, sizeof(*pd), GFP_KERNEL);
 	if (!pd)
@@ -2195,6 +2200,27 @@ static int pl08x_of_probe(struct amba_de
 	/* Use the buses that can access memory, obviously */
 	pd->memcpy_channel.periph_buses = pd->mem_buses;
 
+	/*
+	 * Allocate channel data for all possible slave channels (one
+	 * for each possible signal), channels will then be allocated
+	 * for a device and have it's AHB interfaces set up at
+	 * translation time.
+	 */
+	chanp = devm_kcalloc(&adev->dev,
+			pl08x->vd->signals,
+			sizeof(struct pl08x_channel_data),
+			GFP_KERNEL);
+	if (!chanp)
+		return -ENOMEM;
+
+	pd->slave_channels = chanp;
+	for (i = 0; i < pl08x->vd->signals; i++) {
+		/* chanp->periph_buses will be assigned at translation */
+		chanp->bus_id = kasprintf(GFP_KERNEL, "slave%d", i);
+		chanp++;
+	}
+	pd->num_slave_channels = pl08x->vd->signals;
+
 	pl08x->pd = pd;
 
 	return of_dma_controller_register(adev->dev.of_node, pl08x_of_xlate,
@@ -2234,6 +2260,10 @@ static int pl08x_probe(struct amba_devic
 		goto out_no_pl08x;
 	}
 
+	/* Assign useful pointers to the driver state */
+	pl08x->adev = adev;
+	pl08x->vd = vd;
+
 	/* Initialize memcpy engine */
 	dma_cap_set(DMA_MEMCPY, pl08x->memcpy.cap_mask);
 	pl08x->memcpy.dev = &adev->dev;
@@ -2284,10 +2314,6 @@ static int pl08x_probe(struct amba_devic
 		}
 	}
 
-	/* Assign useful pointers to the driver state */
-	pl08x->adev = adev;
-	pl08x->vd = vd;
-
 	/* By default, AHB1 only.  If dualmaster, from platform */
 	pl08x->lli_buses = PL08X_AHB1;
 	pl08x->mem_buses = PL08X_AHB1;
@@ -2438,6 +2464,7 @@ out_no_pl08x:
 static struct vendor_data vendor_pl080 = {
 	.config_offset = PL080_CH_CONFIG,
 	.channels = 8,
+	.signals = 16,
 	.dualmaster = true,
 	.max_transfer_size = PL080_CONTROL_TRANSFER_SIZE_MASK,
 };
@@ -2445,6 +2472,7 @@ static struct vendor_data vendor_pl080 =
 static struct vendor_data vendor_nomadik = {
 	.config_offset = PL080_CH_CONFIG,
 	.channels = 8,
+	.signals = 32,
 	.dualmaster = true,
 	.nomadik = true,
 	.max_transfer_size = PL080_CONTROL_TRANSFER_SIZE_MASK,
@@ -2453,6 +2481,7 @@ static struct vendor_data vendor_nomadik
 static struct vendor_data vendor_pl080s = {
 	.config_offset = PL080S_CH_CONFIG,
 	.channels = 8,
+	.signals = 32,
 	.pl080s = true,
 	.max_transfer_size = PL080S_CONTROL_TRANSFER_SIZE_MASK,
 };
@@ -2460,6 +2489,7 @@ static struct vendor_data vendor_pl080s
 static struct vendor_data vendor_pl081 = {
 	.config_offset = PL080_CH_CONFIG,
 	.channels = 2,
+	.signals = 16,
 	.dualmaster = false,
 	.max_transfer_size = PL080_CONTROL_TRANSFER_SIZE_MASK,
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma/at_xdmac.c linux-libre-4.7-gnu/drivers/dma/at_xdmac.c
--- linux-libre-4.6-gnu/drivers/dma/at_xdmac.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/dma/at_xdmac.c	2016-07-24 15:23:50.000000000 -0400
@@ -242,7 +242,7 @@ struct at_xdmac_lld {
 	u32		mbr_dus;	/* Destination Microblock Stride Register */
 };
 
-
+/* 64-bit alignment needed to update CNDA and CUBC registers in an atomic way. */
 struct at_xdmac_desc {
 	struct at_xdmac_lld		lld;
 	enum dma_transfer_direction	direction;
@@ -253,7 +253,7 @@ struct at_xdmac_desc {
 	unsigned int			xfer_size;
 	struct list_head		descs_list;
 	struct list_head		xfer_node;
-};
+} __aligned(sizeof(u64));
 
 static inline void __iomem *at_xdmac_chan_reg_base(struct at_xdmac *atxdmac, unsigned int chan_nb)
 {
@@ -1400,6 +1400,7 @@ at_xdmac_tx_status(struct dma_chan *chan
 	u32			cur_nda, check_nda, cur_ubc, mask, value;
 	u8			dwidth = 0;
 	unsigned long		flags;
+	bool			initd;
 
 	ret = dma_cookie_status(chan, cookie, txstate);
 	if (ret == DMA_COMPLETE)
@@ -1424,7 +1425,16 @@ at_xdmac_tx_status(struct dma_chan *chan
 	residue = desc->xfer_size;
 	/*
 	 * Flush FIFO: only relevant when the transfer is source peripheral
-	 * synchronized.
+	 * synchronized. Flush is needed before reading CUBC because data in
+	 * the FIFO are not reported by CUBC. Reporting a residue of the
+	 * transfer length while we have data in FIFO can cause issue.
+	 * Usecase: atmel USART has a timeout which means I have received
+	 * characters but there is no more character received for a while. On
+	 * timeout, it requests the residue. If the data are in the DMA FIFO,
+	 * we will return a residue of the transfer length. It means no data
+	 * received. If an application is waiting for these data, it will hang
+	 * since we won't have another USART timeout without receiving new
+	 * data.
 	 */
 	mask = AT_XDMAC_CC_TYPE | AT_XDMAC_CC_DSYNC;
 	value = AT_XDMAC_CC_TYPE_PER_TRAN | AT_XDMAC_CC_DSYNC_PER2MEM;
@@ -1435,34 +1445,43 @@ at_xdmac_tx_status(struct dma_chan *chan
 	}
 
 	/*
-	 * When processing the residue, we need to read two registers but we
-	 * can't do it in an atomic way. AT_XDMAC_CNDA is used to find where
-	 * we stand in the descriptor list and AT_XDMAC_CUBC is used
-	 * to know how many data are remaining for the current descriptor.
-	 * Since the dma channel is not paused to not loose data, between the
-	 * AT_XDMAC_CNDA and AT_XDMAC_CUBC read, we may have change of
-	 * descriptor.
-	 * For that reason, after reading AT_XDMAC_CUBC, we check if we are
-	 * still using the same descriptor by reading a second time
-	 * AT_XDMAC_CNDA. If AT_XDMAC_CNDA has changed, it means we have to
-	 * read again AT_XDMAC_CUBC.
+	 * The easiest way to compute the residue should be to pause the DMA
+	 * but doing this can lead to miss some data as some devices don't
+	 * have FIFO.
+	 * We need to read several registers because:
+	 * - DMA is running therefore a descriptor change is possible while
+	 * reading these registers
+	 * - When the block transfer is done, the value of the CUBC register
+	 * is set to its initial value until the fetch of the next descriptor.
+	 * This value will corrupt the residue calculation so we have to skip
+	 * it.
+	 *
+	 * INITD --------                    ------------
+	 *              |____________________|
+	 *       _______________________  _______________
+	 * NDA       @desc2             \/   @desc3
+	 *       _______________________/\_______________
+	 *       __________  ___________  _______________
+	 * CUBC       0    \/ MAX desc1 \/  MAX desc2
+	 *       __________/\___________/\_______________
+	 *
+	 * Since descriptors are aligned on 64 bits, we can assume that
+	 * the update of NDA and CUBC is atomic.
 	 * Memory barriers are used to ensure the read order of the registers.
-	 * A max number of retries is set because unlikely it can never ends if
-	 * we are transferring a lot of data with small buffers.
+	 * A max number of retries is set because unlikely it could never ends.
 	 */
-	cur_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc;
-	rmb();
-	cur_ubc = at_xdmac_chan_read(atchan, AT_XDMAC_CUBC);
 	for (retry = 0; retry < AT_XDMAC_RESIDUE_MAX_RETRIES; retry++) {
-		rmb();
 		check_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc;
-
-		if (likely(cur_nda == check_nda))
-			break;
-
-		cur_nda = check_nda;
+		rmb();
+		initd = !!(at_xdmac_chan_read(atchan, AT_XDMAC_CC) & AT_XDMAC_CC_INITD);
 		rmb();
 		cur_ubc = at_xdmac_chan_read(atchan, AT_XDMAC_CUBC);
+		rmb();
+		cur_nda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA) & 0xfffffffc;
+		rmb();
+
+		if ((check_nda == cur_nda) && initd)
+			break;
 	}
 
 	if (unlikely(retry >= AT_XDMAC_RESIDUE_MAX_RETRIES)) {
@@ -1471,6 +1490,19 @@ at_xdmac_tx_status(struct dma_chan *chan
 	}
 
 	/*
+	 * Flush FIFO: only relevant when the transfer is source peripheral
+	 * synchronized. Another flush is needed here because CUBC is updated
+	 * when the controller sends the data write command. It can lead to
+	 * report data that are not written in the memory or the device. The
+	 * FIFO flush ensures that data are really written.
+	 */
+	if ((desc->lld.mbr_cfg & mask) == value) {
+		at_xdmac_write(atxdmac, AT_XDMAC_GSWF, atchan->mask);
+		while (!(at_xdmac_chan_read(atchan, AT_XDMAC_CIS) & AT_XDMAC_CIS_FIS))
+			cpu_relax();
+	}
+
+	/*
 	 * Remove size of all microblocks already transferred and the current
 	 * one. Then add the remaining size to transfer of the current
 	 * microblock.
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma/bcm2835-dma.c linux-libre-4.7-gnu/drivers/dma/bcm2835-dma.c
--- linux-libre-4.6-gnu/drivers/dma/bcm2835-dma.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/dma/bcm2835-dma.c	2016-07-24 15:23:50.000000000 -0400
@@ -46,6 +46,9 @@
 
 #include "virt-dma.h"
 
+#define BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED 14
+#define BCM2835_DMA_CHAN_NAME_SIZE 8
+
 struct bcm2835_dmadev {
 	struct dma_device ddev;
 	spinlock_t lock;
@@ -73,7 +76,6 @@ struct bcm2835_chan {
 	struct list_head node;
 
 	struct dma_slave_config	cfg;
-	bool cyclic;
 	unsigned int dreq;
 
 	int ch;
@@ -82,6 +84,9 @@ struct bcm2835_chan {
 
 	void __iomem *chan_base;
 	int irq_number;
+	unsigned int irq_flags;
+
+	bool is_lite_channel;
 };
 
 struct bcm2835_desc {
@@ -89,47 +94,104 @@ struct bcm2835_desc {
 	struct virt_dma_desc vd;
 	enum dma_transfer_direction dir;
 
-	struct bcm2835_cb_entry *cb_list;
-
 	unsigned int frames;
 	size_t size;
+
+	bool cyclic;
+
+	struct bcm2835_cb_entry cb_list[];
 };
 
 #define BCM2835_DMA_CS		0x00
 #define BCM2835_DMA_ADDR	0x04
+#define BCM2835_DMA_TI		0x08
 #define BCM2835_DMA_SOURCE_AD	0x0c
 #define BCM2835_DMA_DEST_AD	0x10
-#define BCM2835_DMA_NEXTCB	0x1C
+#define BCM2835_DMA_LEN		0x14
+#define BCM2835_DMA_STRIDE	0x18
+#define BCM2835_DMA_NEXTCB	0x1c
+#define BCM2835_DMA_DEBUG	0x20
 
 /* DMA CS Control and Status bits */
-#define BCM2835_DMA_ACTIVE	BIT(0)
-#define BCM2835_DMA_INT	BIT(2)
+#define BCM2835_DMA_ACTIVE	BIT(0)  /* activate the DMA */
+#define BCM2835_DMA_END		BIT(1)  /* current CB has ended */
+#define BCM2835_DMA_INT		BIT(2)  /* interrupt status */
+#define BCM2835_DMA_DREQ	BIT(3)  /* DREQ state */
 #define BCM2835_DMA_ISPAUSED	BIT(4)  /* Pause requested or not active */
 #define BCM2835_DMA_ISHELD	BIT(5)  /* Is held by DREQ flow control */
-#define BCM2835_DMA_ERR	BIT(8)
+#define BCM2835_DMA_WAITING_FOR_WRITES BIT(6) /* waiting for last
+					       * AXI-write to ack
+					       */
+#define BCM2835_DMA_ERR		BIT(8)
+#define BCM2835_DMA_PRIORITY(x) ((x & 15) << 16) /* AXI priority */
+#define BCM2835_DMA_PANIC_PRIORITY(x) ((x & 15) << 20) /* panic priority */
+/* current value of TI.BCM2835_DMA_WAIT_RESP */
+#define BCM2835_DMA_WAIT_FOR_WRITES BIT(28)
+#define BCM2835_DMA_DIS_DEBUG	BIT(29) /* disable debug pause signal */
 #define BCM2835_DMA_ABORT	BIT(30) /* Stop current CB, go to next, WO */
 #define BCM2835_DMA_RESET	BIT(31) /* WO, self clearing */
 
+/* Transfer information bits - also bcm2835_cb.info field */
 #define BCM2835_DMA_INT_EN	BIT(0)
+#define BCM2835_DMA_TDMODE	BIT(1) /* 2D-Mode */
+#define BCM2835_DMA_WAIT_RESP	BIT(3) /* wait for AXI-write to be acked */
 #define BCM2835_DMA_D_INC	BIT(4)
-#define BCM2835_DMA_D_DREQ	BIT(6)
+#define BCM2835_DMA_D_WIDTH	BIT(5) /* 128bit writes if set */
+#define BCM2835_DMA_D_DREQ	BIT(6) /* enable DREQ for destination */
+#define BCM2835_DMA_D_IGNORE	BIT(7) /* ignore destination writes */
 #define BCM2835_DMA_S_INC	BIT(8)
-#define BCM2835_DMA_S_DREQ	BIT(10)
+#define BCM2835_DMA_S_WIDTH	BIT(9) /* 128bit writes if set */
+#define BCM2835_DMA_S_DREQ	BIT(10) /* enable SREQ for source */
+#define BCM2835_DMA_S_IGNORE	BIT(11) /* ignore source reads - read 0 */
+#define BCM2835_DMA_BURST_LENGTH(x) ((x & 15) << 12)
+#define BCM2835_DMA_PER_MAP(x)	((x & 31) << 16) /* REQ source */
+#define BCM2835_DMA_WAIT(x)	((x & 31) << 21) /* add DMA-wait cycles */
+#define BCM2835_DMA_NO_WIDE_BURSTS BIT(26) /* no 2 beat write bursts */
 
-#define BCM2835_DMA_PER_MAP(x)	((x) << 16)
+/* debug register bits */
+#define BCM2835_DMA_DEBUG_LAST_NOT_SET_ERR	BIT(0)
+#define BCM2835_DMA_DEBUG_FIFO_ERR		BIT(1)
+#define BCM2835_DMA_DEBUG_READ_ERR		BIT(2)
+#define BCM2835_DMA_DEBUG_OUTSTANDING_WRITES_SHIFT 4
+#define BCM2835_DMA_DEBUG_OUTSTANDING_WRITES_BITS 4
+#define BCM2835_DMA_DEBUG_ID_SHIFT		16
+#define BCM2835_DMA_DEBUG_ID_BITS		9
+#define BCM2835_DMA_DEBUG_STATE_SHIFT		16
+#define BCM2835_DMA_DEBUG_STATE_BITS		9
+#define BCM2835_DMA_DEBUG_VERSION_SHIFT		25
+#define BCM2835_DMA_DEBUG_VERSION_BITS		3
+#define BCM2835_DMA_DEBUG_LITE			BIT(28)
+
+/* shared registers for all dma channels */
+#define BCM2835_DMA_INT_STATUS         0xfe0
+#define BCM2835_DMA_ENABLE             0xff0
 
 #define BCM2835_DMA_DATA_TYPE_S8	1
 #define BCM2835_DMA_DATA_TYPE_S16	2
 #define BCM2835_DMA_DATA_TYPE_S32	4
 #define BCM2835_DMA_DATA_TYPE_S128	16
 
-#define BCM2835_DMA_BULK_MASK	BIT(0)
-#define BCM2835_DMA_FIQ_MASK	(BIT(2) | BIT(3))
-
 /* Valid only for channels 0 - 14, 15 has its own base address */
 #define BCM2835_DMA_CHAN(n)	((n) << 8) /* Base address */
 #define BCM2835_DMA_CHANIO(base, n) ((base) + BCM2835_DMA_CHAN(n))
 
+/* the max dma length for different channels */
+#define MAX_DMA_LEN SZ_1G
+#define MAX_LITE_DMA_LEN (SZ_64K - 4)
+
+static inline size_t bcm2835_dma_max_frame_length(struct bcm2835_chan *c)
+{
+	/* lite and normal channels have different max frame length */
+	return c->is_lite_channel ? MAX_LITE_DMA_LEN : MAX_DMA_LEN;
+}
+
+/* how many frames of max_len size do we need to transfer len bytes */
+static inline size_t bcm2835_dma_frames_for_length(size_t len,
+						   size_t max_len)
+{
+	return DIV_ROUND_UP(len, max_len);
+}
+
 static inline struct bcm2835_dmadev *to_bcm2835_dma_dev(struct dma_device *d)
 {
 	return container_of(d, struct bcm2835_dmadev, ddev);
@@ -146,19 +208,209 @@ static inline struct bcm2835_desc *to_bc
 	return container_of(t, struct bcm2835_desc, vd.tx);
 }
 
-static void bcm2835_dma_desc_free(struct virt_dma_desc *vd)
+static void bcm2835_dma_free_cb_chain(struct bcm2835_desc *desc)
 {
-	struct bcm2835_desc *desc = container_of(vd, struct bcm2835_desc, vd);
-	int i;
+	size_t i;
 
 	for (i = 0; i < desc->frames; i++)
 		dma_pool_free(desc->c->cb_pool, desc->cb_list[i].cb,
 			      desc->cb_list[i].paddr);
 
-	kfree(desc->cb_list);
 	kfree(desc);
 }
 
+static void bcm2835_dma_desc_free(struct virt_dma_desc *vd)
+{
+	bcm2835_dma_free_cb_chain(
+		container_of(vd, struct bcm2835_desc, vd));
+}
+
+static void bcm2835_dma_create_cb_set_length(
+	struct bcm2835_chan *chan,
+	struct bcm2835_dma_cb *control_block,
+	size_t len,
+	size_t period_len,
+	size_t *total_len,
+	u32 finalextrainfo)
+{
+	size_t max_len = bcm2835_dma_max_frame_length(chan);
+
+	/* set the length taking lite-channel limitations into account */
+	control_block->length = min_t(u32, len, max_len);
+
+	/* finished if we have no period_length */
+	if (!period_len)
+		return;
+
+	/*
+	 * period_len means: that we need to generate
+	 * transfers that are terminating at every
+	 * multiple of period_len - this is typically
+	 * used to set the interrupt flag in info
+	 * which is required during cyclic transfers
+	 */
+
+	/* have we filled in period_length yet? */
+	if (*total_len + control_block->length < period_len)
+		return;
+
+	/* calculate the length that remains to reach period_length */
+	control_block->length = period_len - *total_len;
+
+	/* reset total_length for next period */
+	*total_len = 0;
+
+	/* add extrainfo bits in info */
+	control_block->info |= finalextrainfo;
+}
+
+static inline size_t bcm2835_dma_count_frames_for_sg(
+	struct bcm2835_chan *c,
+	struct scatterlist *sgl,
+	unsigned int sg_len)
+{
+	size_t frames = 0;
+	struct scatterlist *sgent;
+	unsigned int i;
+	size_t plength = bcm2835_dma_max_frame_length(c);
+
+	for_each_sg(sgl, sgent, sg_len, i)
+		frames += bcm2835_dma_frames_for_length(
+			sg_dma_len(sgent), plength);
+
+	return frames;
+}
+
+/**
+ * bcm2835_dma_create_cb_chain - create a control block and fills data in
+ *
+ * @chan:           the @dma_chan for which we run this
+ * @direction:      the direction in which we transfer
+ * @cyclic:         it is a cyclic transfer
+ * @info:           the default info bits to apply per controlblock
+ * @frames:         number of controlblocks to allocate
+ * @src:            the src address to assign (if the S_INC bit is set
+ *                  in @info, then it gets incremented)
+ * @dst:            the dst address to assign (if the D_INC bit is set
+ *                  in @info, then it gets incremented)
+ * @buf_len:        the full buffer length (may also be 0)
+ * @period_len:     the period length when to apply @finalextrainfo
+ *                  in addition to the last transfer
+ *                  this will also break some control-blocks early
+ * @finalextrainfo: additional bits in last controlblock
+ *                  (or when period_len is reached in case of cyclic)
+ * @gfp:            the GFP flag to use for allocation
+ */
+static struct bcm2835_desc *bcm2835_dma_create_cb_chain(
+	struct dma_chan *chan, enum dma_transfer_direction direction,
+	bool cyclic, u32 info, u32 finalextrainfo, size_t frames,
+	dma_addr_t src, dma_addr_t dst, size_t buf_len,
+	size_t period_len, gfp_t gfp)
+{
+	struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
+	size_t len = buf_len, total_len;
+	size_t frame;
+	struct bcm2835_desc *d;
+	struct bcm2835_cb_entry *cb_entry;
+	struct bcm2835_dma_cb *control_block;
+
+	if (!frames)
+		return NULL;
+
+	/* allocate and setup the descriptor. */
+	d = kzalloc(sizeof(*d) + frames * sizeof(struct bcm2835_cb_entry),
+		    gfp);
+	if (!d)
+		return NULL;
+
+	d->c = c;
+	d->dir = direction;
+	d->cyclic = cyclic;
+
+	/*
+	 * Iterate over all frames, create a control block
+	 * for each frame and link them together.
+	 */
+	for (frame = 0, total_len = 0; frame < frames; d->frames++, frame++) {
+		cb_entry = &d->cb_list[frame];
+		cb_entry->cb = dma_pool_alloc(c->cb_pool, gfp,
+					      &cb_entry->paddr);
+		if (!cb_entry->cb)
+			goto error_cb;
+
+		/* fill in the control block */
+		control_block = cb_entry->cb;
+		control_block->info = info;
+		control_block->src = src;
+		control_block->dst = dst;
+		control_block->stride = 0;
+		control_block->next = 0;
+		/* set up length in control_block if requested */
+		if (buf_len) {
+			/* calculate length honoring period_length */
+			bcm2835_dma_create_cb_set_length(
+				c, control_block,
+				len, period_len, &total_len,
+				cyclic ? finalextrainfo : 0);
+
+			/* calculate new remaining length */
+			len -= control_block->length;
+		}
+
+		/* link this the last controlblock */
+		if (frame)
+			d->cb_list[frame - 1].cb->next = cb_entry->paddr;
+
+		/* update src and dst and length */
+		if (src && (info & BCM2835_DMA_S_INC))
+			src += control_block->length;
+		if (dst && (info & BCM2835_DMA_D_INC))
+			dst += control_block->length;
+
+		/* Length of total transfer */
+		d->size += control_block->length;
+	}
+
+	/* the last frame requires extra flags */
+	d->cb_list[d->frames - 1].cb->info |= finalextrainfo;
+
+	/* detect a size missmatch */
+	if (buf_len && (d->size != buf_len))
+		goto error_cb;
+
+	return d;
+error_cb:
+	bcm2835_dma_free_cb_chain(d);
+
+	return NULL;
+}
+
+static void bcm2835_dma_fill_cb_chain_with_sg(
+	struct dma_chan *chan,
+	enum dma_transfer_direction direction,
+	struct bcm2835_cb_entry *cb,
+	struct scatterlist *sgl,
+	unsigned int sg_len)
+{
+	struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
+	size_t max_len = bcm2835_dma_max_frame_length(c);
+	unsigned int i, len;
+	dma_addr_t addr;
+	struct scatterlist *sgent;
+
+	for_each_sg(sgl, sgent, sg_len, i) {
+		for (addr = sg_dma_address(sgent), len = sg_dma_len(sgent);
+		     len > 0;
+		     addr += cb->cb->length, len -= cb->cb->length, cb++) {
+			if (direction == DMA_DEV_TO_MEM)
+				cb->cb->dst = addr;
+			else
+				cb->cb->src = addr;
+			cb->cb->length = min(len, max_len);
+		}
+	}
+}
+
 static int bcm2835_dma_abort(void __iomem *chan_base)
 {
 	unsigned long cs;
@@ -218,6 +470,15 @@ static irqreturn_t bcm2835_dma_callback(
 	struct bcm2835_desc *d;
 	unsigned long flags;
 
+	/* check the shared interrupt */
+	if (c->irq_flags & IRQF_SHARED) {
+		/* check if the interrupt is enabled */
+		flags = readl(c->chan_base + BCM2835_DMA_CS);
+		/* if not set then we are not the reason for the irq */
+		if (!(flags & BCM2835_DMA_INT))
+			return IRQ_NONE;
+	}
+
 	spin_lock_irqsave(&c->vc.lock, flags);
 
 	/* Acknowledge interrupt */
@@ -226,12 +487,18 @@ static irqreturn_t bcm2835_dma_callback(
 	d = c->desc;
 
 	if (d) {
-		/* TODO Only works for cyclic DMA */
-		vchan_cyclic_callback(&d->vd);
-	}
+		if (d->cyclic) {
+			/* call the cyclic callback */
+			vchan_cyclic_callback(&d->vd);
 
-	/* Keep the DMA engine running */
-	writel(BCM2835_DMA_ACTIVE, c->chan_base + BCM2835_DMA_CS);
+			/* Keep the DMA engine running */
+			writel(BCM2835_DMA_ACTIVE,
+			       c->chan_base + BCM2835_DMA_CS);
+		} else {
+			vchan_cookie_complete(&c->desc->vd);
+			bcm2835_dma_start_desc(c);
+		}
+	}
 
 	spin_unlock_irqrestore(&c->vc.lock, flags);
 
@@ -252,8 +519,8 @@ static int bcm2835_dma_alloc_chan_resour
 		return -ENOMEM;
 	}
 
-	return request_irq(c->irq_number,
-			bcm2835_dma_callback, 0, "DMA IRQ", c);
+	return request_irq(c->irq_number, bcm2835_dma_callback,
+			   c->irq_flags, "DMA IRQ", c);
 }
 
 static void bcm2835_dma_free_chan_resources(struct dma_chan *chan)
@@ -339,8 +606,6 @@ static void bcm2835_dma_issue_pending(st
 	struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
 	unsigned long flags;
 
-	c->cyclic = true; /* Nothing else is implemented */
-
 	spin_lock_irqsave(&c->vc.lock, flags);
 	if (vchan_issue_pending(&c->vc) && !c->desc)
 		bcm2835_dma_start_desc(c);
@@ -348,122 +613,160 @@ static void bcm2835_dma_issue_pending(st
 	spin_unlock_irqrestore(&c->vc.lock, flags);
 }
 
-static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic(
-	struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
-	size_t period_len, enum dma_transfer_direction direction,
-	unsigned long flags)
+struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_memcpy(
+	struct dma_chan *chan, dma_addr_t dst, dma_addr_t src,
+	size_t len, unsigned long flags)
 {
 	struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
-	enum dma_slave_buswidth dev_width;
 	struct bcm2835_desc *d;
-	dma_addr_t dev_addr;
-	unsigned int es, sync_type;
-	unsigned int frame;
-	int i;
+	u32 info = BCM2835_DMA_D_INC | BCM2835_DMA_S_INC;
+	u32 extra = BCM2835_DMA_INT_EN | BCM2835_DMA_WAIT_RESP;
+	size_t max_len = bcm2835_dma_max_frame_length(c);
+	size_t frames;
+
+	/* if src, dst or len is not given return with an error */
+	if (!src || !dst || !len)
+		return NULL;
+
+	/* calculate number of frames */
+	frames = bcm2835_dma_frames_for_length(len, max_len);
+
+	/* allocate the CB chain - this also fills in the pointers */
+	d = bcm2835_dma_create_cb_chain(chan, DMA_MEM_TO_MEM, false,
+					info, extra, frames,
+					src, dst, len, 0, GFP_KERNEL);
+	if (!d)
+		return NULL;
+
+	return vchan_tx_prep(&c->vc, &d->vd, flags);
+}
+
+static struct dma_async_tx_descriptor *bcm2835_dma_prep_slave_sg(
+	struct dma_chan *chan,
+	struct scatterlist *sgl, unsigned int sg_len,
+	enum dma_transfer_direction direction,
+	unsigned long flags, void *context)
+{
+	struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
+	struct bcm2835_desc *d;
+	dma_addr_t src = 0, dst = 0;
+	u32 info = BCM2835_DMA_WAIT_RESP;
+	u32 extra = BCM2835_DMA_INT_EN;
+	size_t frames;
 
-	/* Grab configuration */
 	if (!is_slave_direction(direction)) {
-		dev_err(chan->device->dev, "%s: bad direction?\n", __func__);
+		dev_err(chan->device->dev,
+			"%s: bad direction?\n", __func__);
 		return NULL;
 	}
 
+	if (c->dreq != 0)
+		info |= BCM2835_DMA_PER_MAP(c->dreq);
+
 	if (direction == DMA_DEV_TO_MEM) {
-		dev_addr = c->cfg.src_addr;
-		dev_width = c->cfg.src_addr_width;
-		sync_type = BCM2835_DMA_S_DREQ;
+		if (c->cfg.src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES)
+			return NULL;
+		src = c->cfg.src_addr;
+		info |= BCM2835_DMA_S_DREQ | BCM2835_DMA_D_INC;
 	} else {
-		dev_addr = c->cfg.dst_addr;
-		dev_width = c->cfg.dst_addr_width;
-		sync_type = BCM2835_DMA_D_DREQ;
+		if (c->cfg.dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES)
+			return NULL;
+		dst = c->cfg.dst_addr;
+		info |= BCM2835_DMA_D_DREQ | BCM2835_DMA_S_INC;
 	}
 
-	/* Bus width translates to the element size (ES) */
-	switch (dev_width) {
-	case DMA_SLAVE_BUSWIDTH_4_BYTES:
-		es = BCM2835_DMA_DATA_TYPE_S32;
-		break;
-	default:
-		return NULL;
-	}
+	/* count frames in sg list */
+	frames = bcm2835_dma_count_frames_for_sg(c, sgl, sg_len);
 
-	/* Now allocate and setup the descriptor. */
-	d = kzalloc(sizeof(*d), GFP_NOWAIT);
+	/* allocate the CB chain */
+	d = bcm2835_dma_create_cb_chain(chan, direction, false,
+					info, extra,
+					frames, src, dst, 0, 0,
+					GFP_KERNEL);
 	if (!d)
 		return NULL;
 
-	d->c = c;
-	d->dir = direction;
-	d->frames = buf_len / period_len;
+	/* fill in frames with scatterlist pointers */
+	bcm2835_dma_fill_cb_chain_with_sg(chan, direction, d->cb_list,
+					  sgl, sg_len);
 
-	d->cb_list = kcalloc(d->frames, sizeof(*d->cb_list), GFP_KERNEL);
-	if (!d->cb_list) {
-		kfree(d);
+	return vchan_tx_prep(&c->vc, &d->vd, flags);
+}
+
+static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic(
+	struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
+	size_t period_len, enum dma_transfer_direction direction,
+	unsigned long flags)
+{
+	struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
+	struct bcm2835_desc *d;
+	dma_addr_t src, dst;
+	u32 info = BCM2835_DMA_WAIT_RESP;
+	u32 extra = BCM2835_DMA_INT_EN;
+	size_t max_len = bcm2835_dma_max_frame_length(c);
+	size_t frames;
+
+	/* Grab configuration */
+	if (!is_slave_direction(direction)) {
+		dev_err(chan->device->dev, "%s: bad direction?\n", __func__);
 		return NULL;
 	}
-	/* Allocate memory for control blocks */
-	for (i = 0; i < d->frames; i++) {
-		struct bcm2835_cb_entry *cb_entry = &d->cb_list[i];
 
-		cb_entry->cb = dma_pool_zalloc(c->cb_pool, GFP_ATOMIC,
-					       &cb_entry->paddr);
-		if (!cb_entry->cb)
-			goto error_cb;
+	if (!buf_len) {
+		dev_err(chan->device->dev,
+			"%s: bad buffer length (= 0)\n", __func__);
+		return NULL;
 	}
 
 	/*
-	 * Iterate over all frames, create a control block
-	 * for each frame and link them together.
+	 * warn if buf_len is not a multiple of period_len - this may leed
+	 * to unexpected latencies for interrupts and thus audiable clicks
 	 */
-	for (frame = 0; frame < d->frames; frame++) {
-		struct bcm2835_dma_cb *control_block = d->cb_list[frame].cb;
-
-		/* Setup adresses */
-		if (d->dir == DMA_DEV_TO_MEM) {
-			control_block->info = BCM2835_DMA_D_INC;
-			control_block->src = dev_addr;
-			control_block->dst = buf_addr + frame * period_len;
-		} else {
-			control_block->info = BCM2835_DMA_S_INC;
-			control_block->src = buf_addr + frame * period_len;
-			control_block->dst = dev_addr;
-		}
+	if (buf_len % period_len)
+		dev_warn_once(chan->device->dev,
+			      "%s: buffer_length (%zd) is not a multiple of period_len (%zd)\n",
+			      __func__, buf_len, period_len);
 
-		/* Enable interrupt */
-		control_block->info |= BCM2835_DMA_INT_EN;
+	/* Setup DREQ channel */
+	if (c->dreq != 0)
+		info |= BCM2835_DMA_PER_MAP(c->dreq);
 
-		/* Setup synchronization */
-		if (sync_type != 0)
-			control_block->info |= sync_type;
+	if (direction == DMA_DEV_TO_MEM) {
+		if (c->cfg.src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES)
+			return NULL;
+		src = c->cfg.src_addr;
+		dst = buf_addr;
+		info |= BCM2835_DMA_S_DREQ | BCM2835_DMA_D_INC;
+	} else {
+		if (c->cfg.dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES)
+			return NULL;
+		dst = c->cfg.dst_addr;
+		src = buf_addr;
+		info |= BCM2835_DMA_D_DREQ | BCM2835_DMA_S_INC;
+	}
 
-		/* Setup DREQ channel */
-		if (c->dreq != 0)
-			control_block->info |=
-				BCM2835_DMA_PER_MAP(c->dreq);
+	/* calculate number of frames */
+	frames = /* number of periods */
+		 DIV_ROUND_UP(buf_len, period_len) *
+		 /* number of frames per period */
+		 bcm2835_dma_frames_for_length(period_len, max_len);
 
-		/* Length of a frame */
-		control_block->length = period_len;
-		d->size += control_block->length;
+	/*
+	 * allocate the CB chain
+	 * note that we need to use GFP_NOWAIT, as the ALSA i2s dmaengine
+	 * implementation calls prep_dma_cyclic with interrupts disabled.
+	 */
+	d = bcm2835_dma_create_cb_chain(chan, direction, true,
+					info, extra,
+					frames, src, dst, buf_len,
+					period_len, GFP_NOWAIT);
+	if (!d)
+		return NULL;
 
-		/*
-		 * Next block is the next frame.
-		 * This DMA engine driver currently only supports cyclic DMA.
-		 * Therefore, wrap around at number of frames.
-		 */
-		control_block->next = d->cb_list[((frame + 1) % d->frames)].paddr;
-	}
+	/* wrap around into a loop */
+	d->cb_list[d->frames - 1].cb->next = d->cb_list[0].paddr;
 
 	return vchan_tx_prep(&c->vc, &d->vd, flags);
-error_cb:
-	i--;
-	for (; i >= 0; i--) {
-		struct bcm2835_cb_entry *cb_entry = &d->cb_list[i];
-
-		dma_pool_free(c->cb_pool, cb_entry->cb, cb_entry->paddr);
-	}
-
-	kfree(d->cb_list);
-	kfree(d);
-	return NULL;
 }
 
 static int bcm2835_dma_slave_config(struct dma_chan *chan,
@@ -529,7 +832,8 @@ static int bcm2835_dma_terminate_all(str
 	return 0;
 }
 
-static int bcm2835_dma_chan_init(struct bcm2835_dmadev *d, int chan_id, int irq)
+static int bcm2835_dma_chan_init(struct bcm2835_dmadev *d, int chan_id,
+				 int irq, unsigned int irq_flags)
 {
 	struct bcm2835_chan *c;
 
@@ -544,6 +848,12 @@ static int bcm2835_dma_chan_init(struct
 	c->chan_base = BCM2835_DMA_CHANIO(d->base, chan_id);
 	c->ch = chan_id;
 	c->irq_number = irq;
+	c->irq_flags = irq_flags;
+
+	/* check in DEBUG register if this is a LITE channel */
+	if (readl(c->chan_base + BCM2835_DMA_DEBUG) &
+		BCM2835_DMA_DEBUG_LITE)
+		c->is_lite_channel = true;
 
 	return 0;
 }
@@ -587,9 +897,11 @@ static int bcm2835_dma_probe(struct plat
 	struct resource *res;
 	void __iomem *base;
 	int rc;
-	int i;
-	int irq;
+	int i, j;
+	int irq[BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED + 1];
+	int irq_flags;
 	uint32_t chans_available;
+	char chan_name[BCM2835_DMA_CHAN_NAME_SIZE];
 
 	if (!pdev->dev.dma_mask)
 		pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
@@ -615,16 +927,22 @@ static int bcm2835_dma_probe(struct plat
 	dma_cap_set(DMA_SLAVE, od->ddev.cap_mask);
 	dma_cap_set(DMA_PRIVATE, od->ddev.cap_mask);
 	dma_cap_set(DMA_CYCLIC, od->ddev.cap_mask);
+	dma_cap_set(DMA_SLAVE, od->ddev.cap_mask);
+	dma_cap_set(DMA_MEMCPY, od->ddev.cap_mask);
 	od->ddev.device_alloc_chan_resources = bcm2835_dma_alloc_chan_resources;
 	od->ddev.device_free_chan_resources = bcm2835_dma_free_chan_resources;
 	od->ddev.device_tx_status = bcm2835_dma_tx_status;
 	od->ddev.device_issue_pending = bcm2835_dma_issue_pending;
 	od->ddev.device_prep_dma_cyclic = bcm2835_dma_prep_dma_cyclic;
+	od->ddev.device_prep_slave_sg = bcm2835_dma_prep_slave_sg;
+	od->ddev.device_prep_dma_memcpy = bcm2835_dma_prep_dma_memcpy;
 	od->ddev.device_config = bcm2835_dma_slave_config;
 	od->ddev.device_terminate_all = bcm2835_dma_terminate_all;
 	od->ddev.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
 	od->ddev.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
-	od->ddev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
+	od->ddev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV) |
+			      BIT(DMA_MEM_TO_MEM);
+	od->ddev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
 	od->ddev.dev = &pdev->dev;
 	INIT_LIST_HEAD(&od->ddev.channels);
 	spin_lock_init(&od->lock);
@@ -640,22 +958,48 @@ static int bcm2835_dma_probe(struct plat
 		goto err_no_dma;
 	}
 
-	/*
-	 * Do not use the FIQ and BULK channels,
-	 * because they are used by the GPU.
-	 */
-	chans_available &= ~(BCM2835_DMA_FIQ_MASK | BCM2835_DMA_BULK_MASK);
+	/* get irqs for each channel that we support */
+	for (i = 0; i <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; i++) {
+		/* skip masked out channels */
+		if (!(chans_available & (1 << i))) {
+			irq[i] = -1;
+			continue;
+		}
 
-	for (i = 0; i < pdev->num_resources; i++) {
-		irq = platform_get_irq(pdev, i);
-		if (irq < 0)
-			break;
+		/* get the named irq */
+		snprintf(chan_name, sizeof(chan_name), "dma%i", i);
+		irq[i] = platform_get_irq_byname(pdev, chan_name);
+		if (irq[i] >= 0)
+			continue;
 
-		if (chans_available & (1 << i)) {
-			rc = bcm2835_dma_chan_init(od, i, irq);
-			if (rc)
-				goto err_no_dma;
-		}
+		/* legacy device tree case handling */
+		dev_warn_once(&pdev->dev,
+			      "missing interrupt-names property in device tree - legacy interpretation is used\n");
+		/*
+		 * in case of channel >= 11
+		 * use the 11th interrupt and that is shared
+		 */
+		irq[i] = platform_get_irq(pdev, i < 11 ? i : 11);
+	}
+
+	/* get irqs for each channel */
+	for (i = 0; i <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; i++) {
+		/* skip channels without irq */
+		if (irq[i] < 0)
+			continue;
+
+		/* check if there are other channels that also use this irq */
+		irq_flags = 0;
+		for (j = 0; j <= BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED; j++)
+			if ((i != j) && (irq[j] == irq[i])) {
+				irq_flags = IRQF_SHARED;
+				break;
+			}
+
+		/* initialize the channel */
+		rc = bcm2835_dma_chan_init(od, i, irq[i], irq_flags);
+		if (rc)
+			goto err_no_dma;
 	}
 
 	dev_dbg(&pdev->dev, "Initialized %i DMA channels\n", i);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma/dmaengine.c linux-libre-4.7-gnu/drivers/dma/dmaengine.c
--- linux-libre-4.6-gnu/drivers/dma/dmaengine.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/dma/dmaengine.c	2016-07-24 15:23:50.000000000 -0400
@@ -289,7 +289,7 @@ enum dma_status dma_sync_wait(struct dma
 	do {
 		status = dma_async_is_tx_complete(chan, cookie, NULL, NULL);
 		if (time_after_eq(jiffies, dma_sync_wait_timeout)) {
-			pr_err("%s: timeout!\n", __func__);
+			dev_err(chan->device->dev, "%s: timeout!\n", __func__);
 			return DMA_ERROR;
 		}
 		if (status != DMA_IN_PROGRESS)
@@ -482,7 +482,8 @@ int dma_get_slave_caps(struct dma_chan *
 	device = chan->device;
 
 	/* check if the channel supports slave transactions */
-	if (!test_bit(DMA_SLAVE, device->cap_mask.bits))
+	if (!(test_bit(DMA_SLAVE, device->cap_mask.bits) ||
+	      test_bit(DMA_CYCLIC, device->cap_mask.bits)))
 		return -ENXIO;
 
 	/*
@@ -518,7 +519,7 @@ static struct dma_chan *private_candidat
 	struct dma_chan *chan;
 
 	if (mask && !__dma_device_satisfies_mask(dev, mask)) {
-		pr_debug("%s: wrong capabilities\n", __func__);
+		dev_dbg(dev->dev, "%s: wrong capabilities\n", __func__);
 		return NULL;
 	}
 	/* devices with multiple channels need special handling as we need to
@@ -533,12 +534,12 @@ static struct dma_chan *private_candidat
 
 	list_for_each_entry(chan, &dev->channels, device_node) {
 		if (chan->client_count) {
-			pr_debug("%s: %s busy\n",
+			dev_dbg(dev->dev, "%s: %s busy\n",
 				 __func__, dma_chan_name(chan));
 			continue;
 		}
 		if (fn && !fn(chan, fn_param)) {
-			pr_debug("%s: %s filter said false\n",
+			dev_dbg(dev->dev, "%s: %s filter said false\n",
 				 __func__, dma_chan_name(chan));
 			continue;
 		}
@@ -567,11 +568,12 @@ static struct dma_chan *find_candidate(s
 
 		if (err) {
 			if (err == -ENODEV) {
-				pr_debug("%s: %s module removed\n", __func__,
-					 dma_chan_name(chan));
+				dev_dbg(device->dev, "%s: %s module removed\n",
+					__func__, dma_chan_name(chan));
 				list_del_rcu(&device->global_node);
 			} else
-				pr_debug("%s: failed to get %s: (%d)\n",
+				dev_dbg(device->dev,
+					"%s: failed to get %s: (%d)\n",
 					 __func__, dma_chan_name(chan), err);
 
 			if (--device->privatecnt == 0)
@@ -602,7 +604,8 @@ struct dma_chan *dma_get_slave_channel(s
 		device->privatecnt++;
 		err = dma_chan_get(chan);
 		if (err) {
-			pr_debug("%s: failed to get %s: (%d)\n",
+			dev_dbg(chan->device->dev,
+				"%s: failed to get %s: (%d)\n",
 				__func__, dma_chan_name(chan), err);
 			chan = NULL;
 			if (--device->privatecnt == 0)
@@ -814,8 +817,9 @@ void dmaengine_get(void)
 				list_del_rcu(&device->global_node);
 				break;
 			} else if (err)
-				pr_debug("%s: failed to get %s: (%d)\n",
-				       __func__, dma_chan_name(chan), err);
+				dev_dbg(chan->device->dev,
+					"%s: failed to get %s: (%d)\n",
+					__func__, dma_chan_name(chan), err);
 		}
 	}
 
@@ -862,12 +866,12 @@ static bool device_has_all_tx_types(stru
 		return false;
 	#endif
 
-	#if defined(CONFIG_ASYNC_MEMCPY) || defined(CONFIG_ASYNC_MEMCPY_MODULE)
+	#if IS_ENABLED(CONFIG_ASYNC_MEMCPY)
 	if (!dma_has_cap(DMA_MEMCPY, device->cap_mask))
 		return false;
 	#endif
 
-	#if defined(CONFIG_ASYNC_XOR) || defined(CONFIG_ASYNC_XOR_MODULE)
+	#if IS_ENABLED(CONFIG_ASYNC_XOR)
 	if (!dma_has_cap(DMA_XOR, device->cap_mask))
 		return false;
 
@@ -877,7 +881,7 @@ static bool device_has_all_tx_types(stru
 	#endif
 	#endif
 
-	#if defined(CONFIG_ASYNC_PQ) || defined(CONFIG_ASYNC_PQ_MODULE)
+	#if IS_ENABLED(CONFIG_ASYNC_PQ)
 	if (!dma_has_cap(DMA_PQ, device->cap_mask))
 		return false;
 
@@ -1222,8 +1226,9 @@ dma_wait_for_async_tx(struct dma_async_t
 
 	while (tx->cookie == -EBUSY) {
 		if (time_after_eq(jiffies, dma_sync_wait_timeout)) {
-			pr_err("%s timeout waiting for descriptor submission\n",
-			       __func__);
+			dev_err(tx->chan->device->dev,
+				"%s timeout waiting for descriptor submission\n",
+				__func__);
 			return DMA_ERROR;
 		}
 		cpu_relax();
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma/dw/core.c linux-libre-4.7-gnu/drivers/dma/dw/core.c
--- linux-libre-4.6-gnu/drivers/dma/dw/core.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/dma/dw/core.c	2016-07-24 15:23:50.000000000 -0400
@@ -45,22 +45,19 @@
 			DW_DMA_MSIZE_16;			\
 		u8 _dmsize = _is_slave ? _sconfig->dst_maxburst :	\
 			DW_DMA_MSIZE_16;			\
+		u8 _dms = (_dwc->direction == DMA_MEM_TO_DEV) ?		\
+			_dwc->p_master : _dwc->m_master;		\
+		u8 _sms = (_dwc->direction == DMA_DEV_TO_MEM) ?		\
+			_dwc->p_master : _dwc->m_master;		\
 								\
 		(DWC_CTLL_DST_MSIZE(_dmsize)			\
 		 | DWC_CTLL_SRC_MSIZE(_smsize)			\
 		 | DWC_CTLL_LLP_D_EN				\
 		 | DWC_CTLL_LLP_S_EN				\
-		 | DWC_CTLL_DMS(_dwc->dst_master)		\
-		 | DWC_CTLL_SMS(_dwc->src_master));		\
+		 | DWC_CTLL_DMS(_dms)				\
+		 | DWC_CTLL_SMS(_sms));				\
 	})
 
-/*
- * Number of descriptors to allocate for each channel. This should be
- * made configurable somehow; preferably, the clients (at least the
- * ones using slave transfers) should be able to give us a hint.
- */
-#define NR_DESCS_PER_CHANNEL	64
-
 /* The set of bus widths supported by the DMA controller */
 #define DW_DMA_BUSWIDTHS			  \
 	BIT(DMA_SLAVE_BUSWIDTH_UNDEFINED)	| \
@@ -80,51 +77,65 @@ static struct dw_desc *dwc_first_active(
 	return to_dw_desc(dwc->active_list.next);
 }
 
-static struct dw_desc *dwc_desc_get(struct dw_dma_chan *dwc)
+static dma_cookie_t dwc_tx_submit(struct dma_async_tx_descriptor *tx)
 {
-	struct dw_desc *desc, *_desc;
-	struct dw_desc *ret = NULL;
-	unsigned int i = 0;
-	unsigned long flags;
+	struct dw_desc		*desc = txd_to_dw_desc(tx);
+	struct dw_dma_chan	*dwc = to_dw_dma_chan(tx->chan);
+	dma_cookie_t		cookie;
+	unsigned long		flags;
 
 	spin_lock_irqsave(&dwc->lock, flags);
-	list_for_each_entry_safe(desc, _desc, &dwc->free_list, desc_node) {
-		i++;
-		if (async_tx_test_ack(&desc->txd)) {
-			list_del(&desc->desc_node);
-			ret = desc;
-			break;
-		}
-		dev_dbg(chan2dev(&dwc->chan), "desc %p not ACKed\n", desc);
-	}
+	cookie = dma_cookie_assign(tx);
+
+	/*
+	 * REVISIT: We should attempt to chain as many descriptors as
+	 * possible, perhaps even appending to those already submitted
+	 * for DMA. But this is hard to do in a race-free manner.
+	 */
+
+	list_add_tail(&desc->desc_node, &dwc->queue);
 	spin_unlock_irqrestore(&dwc->lock, flags);
+	dev_vdbg(chan2dev(tx->chan), "%s: queued %u\n",
+		 __func__, desc->txd.cookie);
 
-	dev_vdbg(chan2dev(&dwc->chan), "scanned %u descriptors on freelist\n", i);
+	return cookie;
+}
 
-	return ret;
+static struct dw_desc *dwc_desc_get(struct dw_dma_chan *dwc)
+{
+	struct dw_dma *dw = to_dw_dma(dwc->chan.device);
+	struct dw_desc *desc;
+	dma_addr_t phys;
+
+	desc = dma_pool_zalloc(dw->desc_pool, GFP_ATOMIC, &phys);
+	if (!desc)
+		return NULL;
+
+	dwc->descs_allocated++;
+	INIT_LIST_HEAD(&desc->tx_list);
+	dma_async_tx_descriptor_init(&desc->txd, &dwc->chan);
+	desc->txd.tx_submit = dwc_tx_submit;
+	desc->txd.flags = DMA_CTRL_ACK;
+	desc->txd.phys = phys;
+	return desc;
 }
 
-/*
- * Move a descriptor, including any children, to the free list.
- * `desc' must not be on any lists.
- */
 static void dwc_desc_put(struct dw_dma_chan *dwc, struct dw_desc *desc)
 {
-	unsigned long flags;
+	struct dw_dma *dw = to_dw_dma(dwc->chan.device);
+	struct dw_desc *child, *_next;
 
-	if (desc) {
-		struct dw_desc *child;
+	if (unlikely(!desc))
+		return;
 
-		spin_lock_irqsave(&dwc->lock, flags);
-		list_for_each_entry(child, &desc->tx_list, desc_node)
-			dev_vdbg(chan2dev(&dwc->chan),
-					"moving child desc %p to freelist\n",
-					child);
-		list_splice_init(&desc->tx_list, &dwc->free_list);
-		dev_vdbg(chan2dev(&dwc->chan), "moving desc %p to freelist\n", desc);
-		list_add(&desc->desc_node, &dwc->free_list);
-		spin_unlock_irqrestore(&dwc->lock, flags);
+	list_for_each_entry_safe(child, _next, &desc->tx_list, desc_node) {
+		list_del(&child->desc_node);
+		dma_pool_free(dw->desc_pool, child, child->txd.phys);
+		dwc->descs_allocated--;
 	}
+
+	dma_pool_free(dw->desc_pool, desc, desc->txd.phys);
+	dwc->descs_allocated--;
 }
 
 static void dwc_initialize(struct dw_dma_chan *dwc)
@@ -133,7 +144,7 @@ static void dwc_initialize(struct dw_dma
 	u32 cfghi = DWC_CFGH_FIFO_MODE;
 	u32 cfglo = DWC_CFGL_CH_PRIOR(dwc->priority);
 
-	if (dwc->initialized == true)
+	if (test_bit(DW_DMA_IS_INITIALIZED, &dwc->flags))
 		return;
 
 	cfghi |= DWC_CFGH_DST_PER(dwc->dst_id);
@@ -146,26 +157,11 @@ static void dwc_initialize(struct dw_dma
 	channel_set_bit(dw, MASK.XFER, dwc->mask);
 	channel_set_bit(dw, MASK.ERROR, dwc->mask);
 
-	dwc->initialized = true;
+	set_bit(DW_DMA_IS_INITIALIZED, &dwc->flags);
 }
 
 /*----------------------------------------------------------------------*/
 
-static inline unsigned int dwc_fast_ffs(unsigned long long v)
-{
-	/*
-	 * We can be a lot more clever here, but this should take care
-	 * of the most common optimization.
-	 */
-	if (!(v & 7))
-		return 3;
-	else if (!(v & 3))
-		return 2;
-	else if (!(v & 1))
-		return 1;
-	return 0;
-}
-
 static inline void dwc_dump_chan_regs(struct dw_dma_chan *dwc)
 {
 	dev_err(chan2dev(&dwc->chan),
@@ -197,12 +193,12 @@ static inline void dwc_do_single_block(s
 	 * Software emulation of LLP mode relies on interrupts to continue
 	 * multi block transfer.
 	 */
-	ctllo = desc->lli.ctllo | DWC_CTLL_INT_EN;
+	ctllo = lli_read(desc, ctllo) | DWC_CTLL_INT_EN;
 
-	channel_writel(dwc, SAR, desc->lli.sar);
-	channel_writel(dwc, DAR, desc->lli.dar);
+	channel_writel(dwc, SAR, lli_read(desc, sar));
+	channel_writel(dwc, DAR, lli_read(desc, dar));
 	channel_writel(dwc, CTL_LO, ctllo);
-	channel_writel(dwc, CTL_HI, desc->lli.ctlhi);
+	channel_writel(dwc, CTL_HI, lli_read(desc, ctlhi));
 	channel_set_bit(dw, CH_EN, dwc->mask);
 
 	/* Move pointer to next descriptor */
@@ -213,6 +209,7 @@ static inline void dwc_do_single_block(s
 static void dwc_dostart(struct dw_dma_chan *dwc, struct dw_desc *first)
 {
 	struct dw_dma	*dw = to_dw_dma(dwc->chan.device);
+	u8		lms = DWC_LLP_LMS(dwc->m_master);
 	unsigned long	was_soft_llp;
 
 	/* ASSERT:  channel is idle */
@@ -237,7 +234,7 @@ static void dwc_dostart(struct dw_dma_ch
 
 		dwc_initialize(dwc);
 
-		dwc->residue = first->total_len;
+		first->residue = first->total_len;
 		dwc->tx_node_active = &first->tx_list;
 
 		/* Submit first block */
@@ -248,9 +245,8 @@ static void dwc_dostart(struct dw_dma_ch
 
 	dwc_initialize(dwc);
 
-	channel_writel(dwc, LLP, first->txd.phys);
-	channel_writel(dwc, CTL_LO,
-			DWC_CTLL_LLP_D_EN | DWC_CTLL_LLP_S_EN);
+	channel_writel(dwc, LLP, first->txd.phys | lms);
+	channel_writel(dwc, CTL_LO, DWC_CTLL_LLP_D_EN | DWC_CTLL_LLP_S_EN);
 	channel_writel(dwc, CTL_HI, 0);
 	channel_set_bit(dw, CH_EN, dwc->mask);
 }
@@ -293,11 +289,7 @@ dwc_descriptor_complete(struct dw_dma_ch
 	list_for_each_entry(child, &desc->tx_list, desc_node)
 		async_tx_ack(&child->txd);
 	async_tx_ack(&desc->txd);
-
-	list_splice_init(&desc->tx_list, &dwc->free_list);
-	list_move(&desc->desc_node, &dwc->free_list);
-
-	dma_descriptor_unmap(txd);
+	dwc_desc_put(dwc, desc);
 	spin_unlock_irqrestore(&dwc->lock, flags);
 
 	if (callback)
@@ -368,11 +360,11 @@ static void dwc_scan_descriptors(struct
 
 			head = &desc->tx_list;
 			if (active != head) {
-				/* Update desc to reflect last sent one */
-				if (active != head->next)
-					desc = to_dw_desc(active->prev);
-
-				dwc->residue -= desc->len;
+				/* Update residue to reflect last sent descriptor */
+				if (active == head->next)
+					desc->residue -= desc->len;
+				else
+					desc->residue -= to_dw_desc(active->prev)->len;
 
 				child = to_dw_desc(active);
 
@@ -387,8 +379,6 @@ static void dwc_scan_descriptors(struct
 			clear_bit(DW_DMA_IS_SOFT_LLP, &dwc->flags);
 		}
 
-		dwc->residue = 0;
-
 		spin_unlock_irqrestore(&dwc->lock, flags);
 
 		dwc_complete_all(dw, dwc);
@@ -396,7 +386,6 @@ static void dwc_scan_descriptors(struct
 	}
 
 	if (list_empty(&dwc->active_list)) {
-		dwc->residue = 0;
 		spin_unlock_irqrestore(&dwc->lock, flags);
 		return;
 	}
@@ -411,31 +400,31 @@ static void dwc_scan_descriptors(struct
 
 	list_for_each_entry_safe(desc, _desc, &dwc->active_list, desc_node) {
 		/* Initial residue value */
-		dwc->residue = desc->total_len;
+		desc->residue = desc->total_len;
 
 		/* Check first descriptors addr */
-		if (desc->txd.phys == llp) {
+		if (desc->txd.phys == DWC_LLP_LOC(llp)) {
 			spin_unlock_irqrestore(&dwc->lock, flags);
 			return;
 		}
 
 		/* Check first descriptors llp */
-		if (desc->lli.llp == llp) {
+		if (lli_read(desc, llp) == llp) {
 			/* This one is currently in progress */
-			dwc->residue -= dwc_get_sent(dwc);
+			desc->residue -= dwc_get_sent(dwc);
 			spin_unlock_irqrestore(&dwc->lock, flags);
 			return;
 		}
 
-		dwc->residue -= desc->len;
+		desc->residue -= desc->len;
 		list_for_each_entry(child, &desc->tx_list, desc_node) {
-			if (child->lli.llp == llp) {
+			if (lli_read(child, llp) == llp) {
 				/* Currently in progress */
-				dwc->residue -= dwc_get_sent(dwc);
+				desc->residue -= dwc_get_sent(dwc);
 				spin_unlock_irqrestore(&dwc->lock, flags);
 				return;
 			}
-			dwc->residue -= child->len;
+			desc->residue -= child->len;
 		}
 
 		/*
@@ -457,10 +446,14 @@ static void dwc_scan_descriptors(struct
 	spin_unlock_irqrestore(&dwc->lock, flags);
 }
 
-static inline void dwc_dump_lli(struct dw_dma_chan *dwc, struct dw_lli *lli)
+static inline void dwc_dump_lli(struct dw_dma_chan *dwc, struct dw_desc *desc)
 {
 	dev_crit(chan2dev(&dwc->chan), "  desc: s0x%x d0x%x l0x%x c0x%x:%x\n",
-		 lli->sar, lli->dar, lli->llp, lli->ctlhi, lli->ctllo);
+		 lli_read(desc, sar),
+		 lli_read(desc, dar),
+		 lli_read(desc, llp),
+		 lli_read(desc, ctlhi),
+		 lli_read(desc, ctllo));
 }
 
 static void dwc_handle_error(struct dw_dma *dw, struct dw_dma_chan *dwc)
@@ -496,9 +489,9 @@ static void dwc_handle_error(struct dw_d
 	 */
 	dev_WARN(chan2dev(&dwc->chan), "Bad descriptor submitted for DMA!\n"
 				       "  cookie: %d\n", bad_desc->txd.cookie);
-	dwc_dump_lli(dwc, &bad_desc->lli);
+	dwc_dump_lli(dwc, bad_desc);
 	list_for_each_entry(child, &bad_desc->tx_list, desc_node)
-		dwc_dump_lli(dwc, &child->lli);
+		dwc_dump_lli(dwc, child);
 
 	spin_unlock_irqrestore(&dwc->lock, flags);
 
@@ -549,7 +542,7 @@ static void dwc_handle_cyclic(struct dw_
 	 */
 	if (unlikely(status_err & dwc->mask) ||
 			unlikely(status_xfer & dwc->mask)) {
-		int i;
+		unsigned int i;
 
 		dev_err(chan2dev(&dwc->chan),
 			"cyclic DMA unexpected %s interrupt, stopping DMA transfer\n",
@@ -571,7 +564,7 @@ static void dwc_handle_cyclic(struct dw_
 		dma_writel(dw, CLEAR.XFER, dwc->mask);
 
 		for (i = 0; i < dwc->cdesc->periods; i++)
-			dwc_dump_lli(dwc, &dwc->cdesc->desc[i]->lli);
+			dwc_dump_lli(dwc, dwc->cdesc->desc[i]);
 
 		spin_unlock_irqrestore(&dwc->lock, flags);
 	}
@@ -589,7 +582,7 @@ static void dw_dma_tasklet(unsigned long
 	u32 status_block;
 	u32 status_xfer;
 	u32 status_err;
-	int i;
+	unsigned int i;
 
 	status_block = dma_readl(dw, RAW.BLOCK);
 	status_xfer = dma_readl(dw, RAW.XFER);
@@ -658,30 +651,6 @@ static irqreturn_t dw_dma_interrupt(int
 
 /*----------------------------------------------------------------------*/
 
-static dma_cookie_t dwc_tx_submit(struct dma_async_tx_descriptor *tx)
-{
-	struct dw_desc		*desc = txd_to_dw_desc(tx);
-	struct dw_dma_chan	*dwc = to_dw_dma_chan(tx->chan);
-	dma_cookie_t		cookie;
-	unsigned long		flags;
-
-	spin_lock_irqsave(&dwc->lock, flags);
-	cookie = dma_cookie_assign(tx);
-
-	/*
-	 * REVISIT: We should attempt to chain as many descriptors as
-	 * possible, perhaps even appending to those already submitted
-	 * for DMA. But this is hard to do in a race-free manner.
-	 */
-
-	dev_vdbg(chan2dev(tx->chan), "%s: queued %u\n", __func__, desc->txd.cookie);
-	list_add_tail(&desc->desc_node, &dwc->queue);
-
-	spin_unlock_irqrestore(&dwc->lock, flags);
-
-	return cookie;
-}
-
 static struct dma_async_tx_descriptor *
 dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
 		size_t len, unsigned long flags)
@@ -693,10 +662,12 @@ dwc_prep_dma_memcpy(struct dma_chan *cha
 	struct dw_desc		*prev;
 	size_t			xfer_count;
 	size_t			offset;
+	u8			m_master = dwc->m_master;
 	unsigned int		src_width;
 	unsigned int		dst_width;
-	unsigned int		data_width;
+	unsigned int		data_width = dw->pdata->data_width[m_master];
 	u32			ctllo;
+	u8			lms = DWC_LLP_LMS(m_master);
 
 	dev_vdbg(chan2dev(chan),
 			"%s: d%pad s%pad l0x%zx f0x%lx\n", __func__,
@@ -709,11 +680,7 @@ dwc_prep_dma_memcpy(struct dma_chan *cha
 
 	dwc->direction = DMA_MEM_TO_MEM;
 
-	data_width = min_t(unsigned int, dw->data_width[dwc->src_master],
-			   dw->data_width[dwc->dst_master]);
-
-	src_width = dst_width = min_t(unsigned int, data_width,
-				      dwc_fast_ffs(src | dest | len));
+	src_width = dst_width = __ffs(data_width | src | dest | len);
 
 	ctllo = DWC_DEFAULT_CTLLO(chan)
 			| DWC_CTLL_DST_WIDTH(dst_width)
@@ -731,27 +698,27 @@ dwc_prep_dma_memcpy(struct dma_chan *cha
 		if (!desc)
 			goto err_desc_get;
 
-		desc->lli.sar = src + offset;
-		desc->lli.dar = dest + offset;
-		desc->lli.ctllo = ctllo;
-		desc->lli.ctlhi = xfer_count;
+		lli_write(desc, sar, src + offset);
+		lli_write(desc, dar, dest + offset);
+		lli_write(desc, ctllo, ctllo);
+		lli_write(desc, ctlhi, xfer_count);
 		desc->len = xfer_count << src_width;
 
 		if (!first) {
 			first = desc;
 		} else {
-			prev->lli.llp = desc->txd.phys;
-			list_add_tail(&desc->desc_node,
-					&first->tx_list);
+			lli_write(prev, llp, desc->txd.phys | lms);
+			list_add_tail(&desc->desc_node, &first->tx_list);
 		}
 		prev = desc;
 	}
 
 	if (flags & DMA_PREP_INTERRUPT)
 		/* Trigger interrupt after last block */
-		prev->lli.ctllo |= DWC_CTLL_INT_EN;
+		lli_set(prev, ctllo, DWC_CTLL_INT_EN);
 
 	prev->lli.llp = 0;
+	lli_clear(prev, ctllo, DWC_CTLL_LLP_D_EN | DWC_CTLL_LLP_S_EN);
 	first->txd.flags = flags;
 	first->total_len = len;
 
@@ -773,10 +740,12 @@ dwc_prep_slave_sg(struct dma_chan *chan,
 	struct dw_desc		*prev;
 	struct dw_desc		*first;
 	u32			ctllo;
+	u8			m_master = dwc->m_master;
+	u8			lms = DWC_LLP_LMS(m_master);
 	dma_addr_t		reg;
 	unsigned int		reg_width;
 	unsigned int		mem_width;
-	unsigned int		data_width;
+	unsigned int		data_width = dw->pdata->data_width[m_master];
 	unsigned int		i;
 	struct scatterlist	*sg;
 	size_t			total_len = 0;
@@ -802,8 +771,6 @@ dwc_prep_slave_sg(struct dma_chan *chan,
 		ctllo |= sconfig->device_fc ? DWC_CTLL_FC(DW_DMA_FC_P_M2P) :
 			DWC_CTLL_FC(DW_DMA_FC_D_M2P);
 
-		data_width = dw->data_width[dwc->src_master];
-
 		for_each_sg(sgl, sg, sg_len, i) {
 			struct dw_desc	*desc;
 			u32		len, dlen, mem;
@@ -811,17 +778,16 @@ dwc_prep_slave_sg(struct dma_chan *chan,
 			mem = sg_dma_address(sg);
 			len = sg_dma_len(sg);
 
-			mem_width = min_t(unsigned int,
-					  data_width, dwc_fast_ffs(mem | len));
+			mem_width = __ffs(data_width | mem | len);
 
 slave_sg_todev_fill_desc:
 			desc = dwc_desc_get(dwc);
 			if (!desc)
 				goto err_desc_get;
 
-			desc->lli.sar = mem;
-			desc->lli.dar = reg;
-			desc->lli.ctllo = ctllo | DWC_CTLL_SRC_WIDTH(mem_width);
+			lli_write(desc, sar, mem);
+			lli_write(desc, dar, reg);
+			lli_write(desc, ctllo, ctllo | DWC_CTLL_SRC_WIDTH(mem_width));
 			if ((len >> mem_width) > dwc->block_size) {
 				dlen = dwc->block_size << mem_width;
 				mem += dlen;
@@ -831,15 +797,14 @@ slave_sg_todev_fill_desc:
 				len = 0;
 			}
 
-			desc->lli.ctlhi = dlen >> mem_width;
+			lli_write(desc, ctlhi, dlen >> mem_width);
 			desc->len = dlen;
 
 			if (!first) {
 				first = desc;
 			} else {
-				prev->lli.llp = desc->txd.phys;
-				list_add_tail(&desc->desc_node,
-						&first->tx_list);
+				lli_write(prev, llp, desc->txd.phys | lms);
+				list_add_tail(&desc->desc_node, &first->tx_list);
 			}
 			prev = desc;
 			total_len += dlen;
@@ -859,8 +824,6 @@ slave_sg_todev_fill_desc:
 		ctllo |= sconfig->device_fc ? DWC_CTLL_FC(DW_DMA_FC_P_P2M) :
 			DWC_CTLL_FC(DW_DMA_FC_D_P2M);
 
-		data_width = dw->data_width[dwc->dst_master];
-
 		for_each_sg(sgl, sg, sg_len, i) {
 			struct dw_desc	*desc;
 			u32		len, dlen, mem;
@@ -868,17 +831,16 @@ slave_sg_todev_fill_desc:
 			mem = sg_dma_address(sg);
 			len = sg_dma_len(sg);
 
-			mem_width = min_t(unsigned int,
-					  data_width, dwc_fast_ffs(mem | len));
+			mem_width = __ffs(data_width | mem | len);
 
 slave_sg_fromdev_fill_desc:
 			desc = dwc_desc_get(dwc);
 			if (!desc)
 				goto err_desc_get;
 
-			desc->lli.sar = reg;
-			desc->lli.dar = mem;
-			desc->lli.ctllo = ctllo | DWC_CTLL_DST_WIDTH(mem_width);
+			lli_write(desc, sar, reg);
+			lli_write(desc, dar, mem);
+			lli_write(desc, ctllo, ctllo | DWC_CTLL_DST_WIDTH(mem_width));
 			if ((len >> reg_width) > dwc->block_size) {
 				dlen = dwc->block_size << reg_width;
 				mem += dlen;
@@ -887,15 +849,14 @@ slave_sg_fromdev_fill_desc:
 				dlen = len;
 				len = 0;
 			}
-			desc->lli.ctlhi = dlen >> reg_width;
+			lli_write(desc, ctlhi, dlen >> reg_width);
 			desc->len = dlen;
 
 			if (!first) {
 				first = desc;
 			} else {
-				prev->lli.llp = desc->txd.phys;
-				list_add_tail(&desc->desc_node,
-						&first->tx_list);
+				lli_write(prev, llp, desc->txd.phys | lms);
+				list_add_tail(&desc->desc_node, &first->tx_list);
 			}
 			prev = desc;
 			total_len += dlen;
@@ -910,9 +871,10 @@ slave_sg_fromdev_fill_desc:
 
 	if (flags & DMA_PREP_INTERRUPT)
 		/* Trigger interrupt after last block */
-		prev->lli.ctllo |= DWC_CTLL_INT_EN;
+		lli_set(prev, ctllo, DWC_CTLL_INT_EN);
 
 	prev->lli.llp = 0;
+	lli_clear(prev, ctllo, DWC_CTLL_LLP_D_EN | DWC_CTLL_LLP_S_EN);
 	first->total_len = total_len;
 
 	return &first->txd;
@@ -937,8 +899,8 @@ bool dw_dma_filter(struct dma_chan *chan
 	dwc->src_id = dws->src_id;
 	dwc->dst_id = dws->dst_id;
 
-	dwc->src_master = dws->src_master;
-	dwc->dst_master = dws->dst_master;
+	dwc->m_master = dws->m_master;
+	dwc->p_master = dws->p_master;
 
 	return true;
 }
@@ -991,7 +953,7 @@ static int dwc_pause(struct dma_chan *ch
 	while (!(channel_readl(dwc, CFG_LO) & DWC_CFGL_FIFO_EMPTY) && count--)
 		udelay(2);
 
-	dwc->paused = true;
+	set_bit(DW_DMA_IS_PAUSED, &dwc->flags);
 
 	spin_unlock_irqrestore(&dwc->lock, flags);
 
@@ -1004,7 +966,7 @@ static inline void dwc_chan_resume(struc
 
 	channel_writel(dwc, CFG_LO, cfglo & ~DWC_CFGL_CH_SUSP);
 
-	dwc->paused = false;
+	clear_bit(DW_DMA_IS_PAUSED, &dwc->flags);
 }
 
 static int dwc_resume(struct dma_chan *chan)
@@ -1012,12 +974,10 @@ static int dwc_resume(struct dma_chan *c
 	struct dw_dma_chan	*dwc = to_dw_dma_chan(chan);
 	unsigned long		flags;
 
-	if (!dwc->paused)
-		return 0;
-
 	spin_lock_irqsave(&dwc->lock, flags);
 
-	dwc_chan_resume(dwc);
+	if (test_bit(DW_DMA_IS_PAUSED, &dwc->flags))
+		dwc_chan_resume(dwc);
 
 	spin_unlock_irqrestore(&dwc->lock, flags);
 
@@ -1053,16 +1013,37 @@ static int dwc_terminate_all(struct dma_
 	return 0;
 }
 
-static inline u32 dwc_get_residue(struct dw_dma_chan *dwc)
+static struct dw_desc *dwc_find_desc(struct dw_dma_chan *dwc, dma_cookie_t c)
 {
+	struct dw_desc *desc;
+
+	list_for_each_entry(desc, &dwc->active_list, desc_node)
+		if (desc->txd.cookie == c)
+			return desc;
+
+	return NULL;
+}
+
+static u32 dwc_get_residue(struct dw_dma_chan *dwc, dma_cookie_t cookie)
+{
+	struct dw_desc *desc;
 	unsigned long flags;
 	u32 residue;
 
 	spin_lock_irqsave(&dwc->lock, flags);
 
-	residue = dwc->residue;
-	if (test_bit(DW_DMA_IS_SOFT_LLP, &dwc->flags) && residue)
-		residue -= dwc_get_sent(dwc);
+	desc = dwc_find_desc(dwc, cookie);
+	if (desc) {
+		if (desc == dwc_first_active(dwc)) {
+			residue = desc->residue;
+			if (test_bit(DW_DMA_IS_SOFT_LLP, &dwc->flags) && residue)
+				residue -= dwc_get_sent(dwc);
+		} else {
+			residue = desc->total_len;
+		}
+	} else {
+		residue = 0;
+	}
 
 	spin_unlock_irqrestore(&dwc->lock, flags);
 	return residue;
@@ -1083,10 +1064,12 @@ dwc_tx_status(struct dma_chan *chan,
 	dwc_scan_descriptors(to_dw_dma(chan->device), dwc);
 
 	ret = dma_cookie_status(chan, cookie, txstate);
-	if (ret != DMA_COMPLETE)
-		dma_set_residue(txstate, dwc_get_residue(dwc));
+	if (ret == DMA_COMPLETE)
+		return ret;
 
-	if (dwc->paused && ret == DMA_IN_PROGRESS)
+	dma_set_residue(txstate, dwc_get_residue(dwc, cookie));
+
+	if (test_bit(DW_DMA_IS_PAUSED, &dwc->flags) && ret == DMA_IN_PROGRESS)
 		return DMA_PAUSED;
 
 	return ret;
@@ -1107,7 +1090,7 @@ static void dwc_issue_pending(struct dma
 
 static void dw_dma_off(struct dw_dma *dw)
 {
-	int i;
+	unsigned int i;
 
 	dma_writel(dw, CFG, 0);
 
@@ -1121,7 +1104,7 @@ static void dw_dma_off(struct dw_dma *dw
 		cpu_relax();
 
 	for (i = 0; i < dw->dma.chancnt; i++)
-		dw->chan[i].initialized = false;
+		clear_bit(DW_DMA_IS_INITIALIZED, &dw->chan[i].flags);
 }
 
 static void dw_dma_on(struct dw_dma *dw)
@@ -1133,9 +1116,6 @@ static int dwc_alloc_chan_resources(stru
 {
 	struct dw_dma_chan	*dwc = to_dw_dma_chan(chan);
 	struct dw_dma		*dw = to_dw_dma(chan->device);
-	struct dw_desc		*desc;
-	int			i;
-	unsigned long		flags;
 
 	dev_vdbg(chan2dev(chan), "%s\n", __func__);
 
@@ -1166,48 +1146,13 @@ static int dwc_alloc_chan_resources(stru
 		dw_dma_on(dw);
 	dw->in_use |= dwc->mask;
 
-	spin_lock_irqsave(&dwc->lock, flags);
-	i = dwc->descs_allocated;
-	while (dwc->descs_allocated < NR_DESCS_PER_CHANNEL) {
-		dma_addr_t phys;
-
-		spin_unlock_irqrestore(&dwc->lock, flags);
-
-		desc = dma_pool_alloc(dw->desc_pool, GFP_ATOMIC, &phys);
-		if (!desc)
-			goto err_desc_alloc;
-
-		memset(desc, 0, sizeof(struct dw_desc));
-
-		INIT_LIST_HEAD(&desc->tx_list);
-		dma_async_tx_descriptor_init(&desc->txd, chan);
-		desc->txd.tx_submit = dwc_tx_submit;
-		desc->txd.flags = DMA_CTRL_ACK;
-		desc->txd.phys = phys;
-
-		dwc_desc_put(dwc, desc);
-
-		spin_lock_irqsave(&dwc->lock, flags);
-		i = ++dwc->descs_allocated;
-	}
-
-	spin_unlock_irqrestore(&dwc->lock, flags);
-
-	dev_dbg(chan2dev(chan), "%s: allocated %d descriptors\n", __func__, i);
-
-	return i;
-
-err_desc_alloc:
-	dev_info(chan2dev(chan), "only allocated %d descriptors\n", i);
-
-	return i;
+	return 0;
 }
 
 static void dwc_free_chan_resources(struct dma_chan *chan)
 {
 	struct dw_dma_chan	*dwc = to_dw_dma_chan(chan);
 	struct dw_dma		*dw = to_dw_dma(chan->device);
-	struct dw_desc		*desc, *_desc;
 	unsigned long		flags;
 	LIST_HEAD(list);
 
@@ -1220,17 +1165,15 @@ static void dwc_free_chan_resources(stru
 	BUG_ON(dma_readl(to_dw_dma(chan->device), CH_EN) & dwc->mask);
 
 	spin_lock_irqsave(&dwc->lock, flags);
-	list_splice_init(&dwc->free_list, &list);
-	dwc->descs_allocated = 0;
 
 	/* Clear custom channel configuration */
 	dwc->src_id = 0;
 	dwc->dst_id = 0;
 
-	dwc->src_master = 0;
-	dwc->dst_master = 0;
+	dwc->m_master = 0;
+	dwc->p_master = 0;
 
-	dwc->initialized = false;
+	clear_bit(DW_DMA_IS_INITIALIZED, &dwc->flags);
 
 	/* Disable interrupts */
 	channel_clear_bit(dw, MASK.XFER, dwc->mask);
@@ -1244,11 +1187,6 @@ static void dwc_free_chan_resources(stru
 	if (!dw->in_use)
 		dw_dma_off(dw);
 
-	list_for_each_entry_safe(desc, _desc, &list, desc_node) {
-		dev_vdbg(chan2dev(chan), "  freeing descriptor %p\n", desc);
-		dma_pool_free(dw->desc_pool, desc, desc->txd.phys);
-	}
-
 	dev_vdbg(chan2dev(chan), "%s: done\n", __func__);
 }
 
@@ -1326,6 +1264,7 @@ struct dw_cyclic_desc *dw_dma_cyclic_pre
 	struct dw_cyclic_desc		*retval = NULL;
 	struct dw_desc			*desc;
 	struct dw_desc			*last = NULL;
+	u8				lms = DWC_LLP_LMS(dwc->m_master);
 	unsigned long			was_cyclic;
 	unsigned int			reg_width;
 	unsigned int			periods;
@@ -1379,9 +1318,6 @@ struct dw_cyclic_desc *dw_dma_cyclic_pre
 
 	retval = ERR_PTR(-ENOMEM);
 
-	if (periods > NR_DESCS_PER_CHANNEL)
-		goto out_err;
-
 	cdesc = kzalloc(sizeof(struct dw_cyclic_desc), GFP_KERNEL);
 	if (!cdesc)
 		goto out_err;
@@ -1397,50 +1333,50 @@ struct dw_cyclic_desc *dw_dma_cyclic_pre
 
 		switch (direction) {
 		case DMA_MEM_TO_DEV:
-			desc->lli.dar = sconfig->dst_addr;
-			desc->lli.sar = buf_addr + (period_len * i);
-			desc->lli.ctllo = (DWC_DEFAULT_CTLLO(chan)
-					| DWC_CTLL_DST_WIDTH(reg_width)
-					| DWC_CTLL_SRC_WIDTH(reg_width)
-					| DWC_CTLL_DST_FIX
-					| DWC_CTLL_SRC_INC
-					| DWC_CTLL_INT_EN);
+			lli_write(desc, dar, sconfig->dst_addr);
+			lli_write(desc, sar, buf_addr + period_len * i);
+			lli_write(desc, ctllo, (DWC_DEFAULT_CTLLO(chan)
+				| DWC_CTLL_DST_WIDTH(reg_width)
+				| DWC_CTLL_SRC_WIDTH(reg_width)
+				| DWC_CTLL_DST_FIX
+				| DWC_CTLL_SRC_INC
+				| DWC_CTLL_INT_EN));
 
-			desc->lli.ctllo |= sconfig->device_fc ?
-				DWC_CTLL_FC(DW_DMA_FC_P_M2P) :
-				DWC_CTLL_FC(DW_DMA_FC_D_M2P);
+			lli_set(desc, ctllo, sconfig->device_fc ?
+					DWC_CTLL_FC(DW_DMA_FC_P_M2P) :
+					DWC_CTLL_FC(DW_DMA_FC_D_M2P));
 
 			break;
 		case DMA_DEV_TO_MEM:
-			desc->lli.dar = buf_addr + (period_len * i);
-			desc->lli.sar = sconfig->src_addr;
-			desc->lli.ctllo = (DWC_DEFAULT_CTLLO(chan)
-					| DWC_CTLL_SRC_WIDTH(reg_width)
-					| DWC_CTLL_DST_WIDTH(reg_width)
-					| DWC_CTLL_DST_INC
-					| DWC_CTLL_SRC_FIX
-					| DWC_CTLL_INT_EN);
+			lli_write(desc, dar, buf_addr + period_len * i);
+			lli_write(desc, sar, sconfig->src_addr);
+			lli_write(desc, ctllo, (DWC_DEFAULT_CTLLO(chan)
+				| DWC_CTLL_SRC_WIDTH(reg_width)
+				| DWC_CTLL_DST_WIDTH(reg_width)
+				| DWC_CTLL_DST_INC
+				| DWC_CTLL_SRC_FIX
+				| DWC_CTLL_INT_EN));
 
-			desc->lli.ctllo |= sconfig->device_fc ?
-				DWC_CTLL_FC(DW_DMA_FC_P_P2M) :
-				DWC_CTLL_FC(DW_DMA_FC_D_P2M);
+			lli_set(desc, ctllo, sconfig->device_fc ?
+					DWC_CTLL_FC(DW_DMA_FC_P_P2M) :
+					DWC_CTLL_FC(DW_DMA_FC_D_P2M));
 
 			break;
 		default:
 			break;
 		}
 
-		desc->lli.ctlhi = (period_len >> reg_width);
+		lli_write(desc, ctlhi, period_len >> reg_width);
 		cdesc->desc[i] = desc;
 
 		if (last)
-			last->lli.llp = desc->txd.phys;
+			lli_write(last, llp, desc->txd.phys | lms);
 
 		last = desc;
 	}
 
 	/* Let's make a cyclic list */
-	last->lli.llp = cdesc->desc[0]->txd.phys;
+	lli_write(last, llp, cdesc->desc[0]->txd.phys | lms);
 
 	dev_dbg(chan2dev(&dwc->chan),
 			"cyclic prepared buf %pad len %zu period %zu periods %d\n",
@@ -1471,7 +1407,7 @@ void dw_dma_cyclic_free(struct dma_chan
 	struct dw_dma_chan	*dwc = to_dw_dma_chan(chan);
 	struct dw_dma		*dw = to_dw_dma(dwc->chan.device);
 	struct dw_cyclic_desc	*cdesc = dwc->cdesc;
-	int			i;
+	unsigned int		i;
 	unsigned long		flags;
 
 	dev_dbg(chan2dev(&dwc->chan), "%s\n", __func__);
@@ -1495,32 +1431,38 @@ void dw_dma_cyclic_free(struct dma_chan
 	kfree(cdesc->desc);
 	kfree(cdesc);
 
+	dwc->cdesc = NULL;
+
 	clear_bit(DW_DMA_IS_CYCLIC, &dwc->flags);
 }
 EXPORT_SYMBOL(dw_dma_cyclic_free);
 
 /*----------------------------------------------------------------------*/
 
-int dw_dma_probe(struct dw_dma_chip *chip, struct dw_dma_platform_data *pdata)
+int dw_dma_probe(struct dw_dma_chip *chip)
 {
+	struct dw_dma_platform_data *pdata;
 	struct dw_dma		*dw;
 	bool			autocfg = false;
 	unsigned int		dw_params;
-	unsigned int		max_blk_size = 0;
+	unsigned int		i;
 	int			err;
-	int			i;
 
 	dw = devm_kzalloc(chip->dev, sizeof(*dw), GFP_KERNEL);
 	if (!dw)
 		return -ENOMEM;
 
+	dw->pdata = devm_kzalloc(chip->dev, sizeof(*dw->pdata), GFP_KERNEL);
+	if (!dw->pdata)
+		return -ENOMEM;
+
 	dw->regs = chip->regs;
 	chip->dw = dw;
 
 	pm_runtime_get_sync(chip->dev);
 
-	if (!pdata) {
-		dw_params = dma_read_byaddr(chip->regs, DW_PARAMS);
+	if (!chip->pdata) {
+		dw_params = dma_readl(dw, DW_PARAMS);
 		dev_dbg(chip->dev, "DW_PARAMS: 0x%08x\n", dw_params);
 
 		autocfg = dw_params >> DW_PARAMS_EN & 1;
@@ -1529,29 +1471,31 @@ int dw_dma_probe(struct dw_dma_chip *chi
 			goto err_pdata;
 		}
 
-		pdata = devm_kzalloc(chip->dev, sizeof(*pdata), GFP_KERNEL);
-		if (!pdata) {
-			err = -ENOMEM;
-			goto err_pdata;
-		}
+		/* Reassign the platform data pointer */
+		pdata = dw->pdata;
 
 		/* Get hardware configuration parameters */
 		pdata->nr_channels = (dw_params >> DW_PARAMS_NR_CHAN & 7) + 1;
 		pdata->nr_masters = (dw_params >> DW_PARAMS_NR_MASTER & 3) + 1;
 		for (i = 0; i < pdata->nr_masters; i++) {
 			pdata->data_width[i] =
-				(dw_params >> DW_PARAMS_DATA_WIDTH(i) & 3) + 2;
+				4 << (dw_params >> DW_PARAMS_DATA_WIDTH(i) & 3);
 		}
-		max_blk_size = dma_readl(dw, MAX_BLK_SIZE);
+		pdata->block_size = dma_readl(dw, MAX_BLK_SIZE);
 
 		/* Fill platform data with the default values */
 		pdata->is_private = true;
 		pdata->is_memcpy = true;
 		pdata->chan_allocation_order = CHAN_ALLOCATION_ASCENDING;
 		pdata->chan_priority = CHAN_PRIORITY_ASCENDING;
-	} else if (pdata->nr_channels > DW_DMA_MAX_NR_CHANNELS) {
+	} else if (chip->pdata->nr_channels > DW_DMA_MAX_NR_CHANNELS) {
 		err = -EINVAL;
 		goto err_pdata;
+	} else {
+		memcpy(dw->pdata, chip->pdata, sizeof(*dw->pdata));
+
+		/* Reassign the platform data pointer */
+		pdata = dw->pdata;
 	}
 
 	dw->chan = devm_kcalloc(chip->dev, pdata->nr_channels, sizeof(*dw->chan),
@@ -1561,11 +1505,6 @@ int dw_dma_probe(struct dw_dma_chip *chi
 		goto err_pdata;
 	}
 
-	/* Get hardware configuration parameters */
-	dw->nr_masters = pdata->nr_masters;
-	for (i = 0; i < dw->nr_masters; i++)
-		dw->data_width[i] = pdata->data_width[i];
-
 	/* Calculate all channel mask before DMA setup */
 	dw->all_chan_mask = (1 << pdata->nr_channels) - 1;
 
@@ -1612,7 +1551,6 @@ int dw_dma_probe(struct dw_dma_chip *chi
 
 		INIT_LIST_HEAD(&dwc->active_list);
 		INIT_LIST_HEAD(&dwc->queue);
-		INIT_LIST_HEAD(&dwc->free_list);
 
 		channel_clear_bit(dw, CH_EN, dwc->mask);
 
@@ -1620,11 +1558,9 @@ int dw_dma_probe(struct dw_dma_chip *chi
 
 		/* Hardware configuration */
 		if (autocfg) {
-			unsigned int dwc_params;
 			unsigned int r = DW_DMA_MAX_NR_CHANNELS - i - 1;
-			void __iomem *addr = chip->regs + r * sizeof(u32);
-
-			dwc_params = dma_read_byaddr(addr, DWC_PARAMS);
+			void __iomem *addr = &__dw_regs(dw)->DWC_PARAMS[r];
+			unsigned int dwc_params = dma_readl_native(addr);
 
 			dev_dbg(chip->dev, "DWC_PARAMS[%d]: 0x%08x\n", i,
 					   dwc_params);
@@ -1635,16 +1571,15 @@ int dw_dma_probe(struct dw_dma_chip *chi
 			 * up to 0x0a for 4095.
 			 */
 			dwc->block_size =
-				(4 << ((max_blk_size >> 4 * i) & 0xf)) - 1;
+				(4 << ((pdata->block_size >> 4 * i) & 0xf)) - 1;
 			dwc->nollp =
 				(dwc_params >> DWC_PARAMS_MBLK_EN & 0x1) == 0;
 		} else {
 			dwc->block_size = pdata->block_size;
 
 			/* Check if channel supports multi block transfer */
-			channel_writel(dwc, LLP, 0xfffffffc);
-			dwc->nollp =
-				(channel_readl(dwc, LLP) & 0xfffffffc) == 0;
+			channel_writel(dwc, LLP, DWC_LLP_LOC(0xffffffff));
+			dwc->nollp = DWC_LLP_LOC(channel_readl(dwc, LLP)) == 0;
 			channel_writel(dwc, LLP, 0);
 		}
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma/dw/pci.c linux-libre-4.7-gnu/drivers/dma/dw/pci.c
--- linux-libre-4.6-gnu/drivers/dma/dw/pci.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/dma/dw/pci.c	2016-07-24 15:23:50.000000000 -0400
@@ -17,8 +17,8 @@
 
 static int dw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid)
 {
+	const struct dw_dma_platform_data *pdata = (void *)pid->driver_data;
 	struct dw_dma_chip *chip;
-	struct dw_dma_platform_data *pdata = (void *)pid->driver_data;
 	int ret;
 
 	ret = pcim_enable_device(pdev);
@@ -49,8 +49,9 @@ static int dw_pci_probe(struct pci_dev *
 	chip->dev = &pdev->dev;
 	chip->regs = pcim_iomap_table(pdev)[0];
 	chip->irq = pdev->irq;
+	chip->pdata = pdata;
 
-	ret = dw_dma_probe(chip, pdata);
+	ret = dw_dma_probe(chip);
 	if (ret)
 		return ret;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma/dw/platform.c linux-libre-4.7-gnu/drivers/dma/dw/platform.c
--- linux-libre-4.6-gnu/drivers/dma/dw/platform.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/dma/dw/platform.c	2016-07-24 15:23:50.000000000 -0400
@@ -42,13 +42,13 @@ static struct dma_chan *dw_dma_of_xlate(
 
 	slave.src_id = dma_spec->args[0];
 	slave.dst_id = dma_spec->args[0];
-	slave.src_master = dma_spec->args[1];
-	slave.dst_master = dma_spec->args[2];
+	slave.m_master = dma_spec->args[1];
+	slave.p_master = dma_spec->args[2];
 
 	if (WARN_ON(slave.src_id >= DW_DMA_MAX_NR_REQUESTS ||
 		    slave.dst_id >= DW_DMA_MAX_NR_REQUESTS ||
-		    slave.src_master >= dw->nr_masters ||
-		    slave.dst_master >= dw->nr_masters))
+		    slave.m_master >= dw->pdata->nr_masters ||
+		    slave.p_master >= dw->pdata->nr_masters))
 		return NULL;
 
 	dma_cap_zero(cap);
@@ -66,8 +66,8 @@ static bool dw_dma_acpi_filter(struct dm
 		.dma_dev = dma_spec->dev,
 		.src_id = dma_spec->slave_id,
 		.dst_id = dma_spec->slave_id,
-		.src_master = 1,
-		.dst_master = 0,
+		.m_master = 0,
+		.p_master = 1,
 	};
 
 	return dw_dma_filter(chan, &slave);
@@ -103,6 +103,7 @@ dw_dma_parse_dt(struct platform_device *
 	struct device_node *np = pdev->dev.of_node;
 	struct dw_dma_platform_data *pdata;
 	u32 tmp, arr[DW_DMA_MAX_NR_MASTERS];
+	u32 nr_masters;
 	u32 nr_channels;
 
 	if (!np) {
@@ -110,6 +111,11 @@ dw_dma_parse_dt(struct platform_device *
 		return NULL;
 	}
 
+	if (of_property_read_u32(np, "dma-masters", &nr_masters))
+		return NULL;
+	if (nr_masters < 1 || nr_masters > DW_DMA_MAX_NR_MASTERS)
+		return NULL;
+
 	if (of_property_read_u32(np, "dma-channels", &nr_channels))
 		return NULL;
 
@@ -117,6 +123,7 @@ dw_dma_parse_dt(struct platform_device *
 	if (!pdata)
 		return NULL;
 
+	pdata->nr_masters = nr_masters;
 	pdata->nr_channels = nr_channels;
 
 	if (of_property_read_bool(np, "is_private"))
@@ -131,17 +138,13 @@ dw_dma_parse_dt(struct platform_device *
 	if (!of_property_read_u32(np, "block_size", &tmp))
 		pdata->block_size = tmp;
 
-	if (!of_property_read_u32(np, "dma-masters", &tmp)) {
-		if (tmp > DW_DMA_MAX_NR_MASTERS)
-			return NULL;
-
-		pdata->nr_masters = tmp;
-	}
-
-	if (!of_property_read_u32_array(np, "data_width", arr,
-				pdata->nr_masters))
-		for (tmp = 0; tmp < pdata->nr_masters; tmp++)
+	if (!of_property_read_u32_array(np, "data-width", arr, nr_masters)) {
+		for (tmp = 0; tmp < nr_masters; tmp++)
 			pdata->data_width[tmp] = arr[tmp];
+	} else if (!of_property_read_u32_array(np, "data_width", arr, nr_masters)) {
+		for (tmp = 0; tmp < nr_masters; tmp++)
+			pdata->data_width[tmp] = BIT(arr[tmp] & 0x07);
+	}
 
 	return pdata;
 }
@@ -158,7 +161,7 @@ static int dw_probe(struct platform_devi
 	struct dw_dma_chip *chip;
 	struct device *dev = &pdev->dev;
 	struct resource *mem;
-	struct dw_dma_platform_data *pdata;
+	const struct dw_dma_platform_data *pdata;
 	int err;
 
 	chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
@@ -183,6 +186,7 @@ static int dw_probe(struct platform_devi
 		pdata = dw_dma_parse_dt(pdev);
 
 	chip->dev = dev;
+	chip->pdata = pdata;
 
 	chip->clk = devm_clk_get(chip->dev, "hclk");
 	if (IS_ERR(chip->clk))
@@ -193,7 +197,7 @@ static int dw_probe(struct platform_devi
 
 	pm_runtime_enable(&pdev->dev);
 
-	err = dw_dma_probe(chip, pdata);
+	err = dw_dma_probe(chip);
 	if (err)
 		goto err_dw_dma_probe;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma/dw/regs.h linux-libre-4.7-gnu/drivers/dma/dw/regs.h
--- linux-libre-4.6-gnu/drivers/dma/dw/regs.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/dma/dw/regs.h	2016-07-24 15:23:50.000000000 -0400
@@ -114,10 +114,6 @@ struct dw_dma_regs {
 #define dma_writel_native writel
 #endif
 
-/* To access the registers in early stage of probe */
-#define dma_read_byaddr(addr, name) \
-	dma_readl_native((addr) + offsetof(struct dw_dma_regs, name))
-
 /* Bitfields in DW_PARAMS */
 #define DW_PARAMS_NR_CHAN	8		/* number of channels */
 #define DW_PARAMS_NR_MASTER	11		/* number of AHB masters */
@@ -143,6 +139,10 @@ enum dw_dma_msize {
 	DW_DMA_MSIZE_256,
 };
 
+/* Bitfields in LLP */
+#define DWC_LLP_LMS(x)		((x) & 3)	/* list master select */
+#define DWC_LLP_LOC(x)		((x) & ~3)	/* next lli */
+
 /* Bitfields in CTL_LO */
 #define DWC_CTLL_INT_EN		(1 << 0)	/* irqs enabled? */
 #define DWC_CTLL_DST_WIDTH(n)	((n)<<1)	/* bytes per element */
@@ -216,6 +216,8 @@ enum dw_dma_msize {
 enum dw_dmac_flags {
 	DW_DMA_IS_CYCLIC = 0,
 	DW_DMA_IS_SOFT_LLP = 1,
+	DW_DMA_IS_PAUSED = 2,
+	DW_DMA_IS_INITIALIZED = 3,
 };
 
 struct dw_dma_chan {
@@ -224,8 +226,6 @@ struct dw_dma_chan {
 	u8				mask;
 	u8				priority;
 	enum dma_transfer_direction	direction;
-	bool				paused;
-	bool				initialized;
 
 	/* software emulation of the LLP transfers */
 	struct list_head	*tx_node_active;
@@ -236,8 +236,6 @@ struct dw_dma_chan {
 	unsigned long		flags;
 	struct list_head	active_list;
 	struct list_head	queue;
-	struct list_head	free_list;
-	u32			residue;
 	struct dw_cyclic_desc	*cdesc;
 
 	unsigned int		descs_allocated;
@@ -249,8 +247,8 @@ struct dw_dma_chan {
 	/* custom slave configuration */
 	u8			src_id;
 	u8			dst_id;
-	u8			src_master;
-	u8			dst_master;
+	u8			m_master;
+	u8			p_master;
 
 	/* configuration passed via .device_config */
 	struct dma_slave_config dma_sconfig;
@@ -283,9 +281,8 @@ struct dw_dma {
 	u8			all_chan_mask;
 	u8			in_use;
 
-	/* hardware configuration */
-	unsigned char		nr_masters;
-	unsigned char		data_width[DW_DMA_MAX_NR_MASTERS];
+	/* platform data */
+	struct dw_dma_platform_data	*pdata;
 };
 
 static inline struct dw_dma_regs __iomem *__dw_regs(struct dw_dma *dw)
@@ -308,32 +305,51 @@ static inline struct dw_dma *to_dw_dma(s
 	return container_of(ddev, struct dw_dma, dma);
 }
 
+#ifdef CONFIG_DW_DMAC_BIG_ENDIAN_IO
+typedef __be32 __dw32;
+#else
+typedef __le32 __dw32;
+#endif
+
 /* LLI == Linked List Item; a.k.a. DMA block descriptor */
 struct dw_lli {
 	/* values that are not changed by hardware */
-	u32		sar;
-	u32		dar;
-	u32		llp;		/* chain to next lli */
-	u32		ctllo;
+	__dw32		sar;
+	__dw32		dar;
+	__dw32		llp;		/* chain to next lli */
+	__dw32		ctllo;
 	/* values that may get written back: */
-	u32		ctlhi;
+	__dw32		ctlhi;
 	/* sstat and dstat can snapshot peripheral register state.
 	 * silicon config may discard either or both...
 	 */
-	u32		sstat;
-	u32		dstat;
+	__dw32		sstat;
+	__dw32		dstat;
 };
 
 struct dw_desc {
 	/* FIRST values the hardware uses */
 	struct dw_lli			lli;
 
+#ifdef CONFIG_DW_DMAC_BIG_ENDIAN_IO
+#define lli_set(d, reg, v)		((d)->lli.reg |= cpu_to_be32(v))
+#define lli_clear(d, reg, v)		((d)->lli.reg &= ~cpu_to_be32(v))
+#define lli_read(d, reg)		be32_to_cpu((d)->lli.reg)
+#define lli_write(d, reg, v)		((d)->lli.reg = cpu_to_be32(v))
+#else
+#define lli_set(d, reg, v)		((d)->lli.reg |= cpu_to_le32(v))
+#define lli_clear(d, reg, v)		((d)->lli.reg &= ~cpu_to_le32(v))
+#define lli_read(d, reg)		le32_to_cpu((d)->lli.reg)
+#define lli_write(d, reg, v)		((d)->lli.reg = cpu_to_le32(v))
+#endif
+
 	/* THEN values for driver housekeeping */
 	struct list_head		desc_node;
 	struct list_head		tx_list;
 	struct dma_async_tx_descriptor	txd;
 	size_t				len;
 	size_t				total_len;
+	u32				residue;
 };
 
 #define to_dw_desc(h)	list_entry(h, struct dw_desc, desc_node)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma/edma.c linux-libre-4.7-gnu/drivers/dma/edma.c
--- linux-libre-4.6-gnu/drivers/dma/edma.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/dma/edma.c	2016-07-24 15:23:50.000000000 -0400
@@ -1537,8 +1537,17 @@ static irqreturn_t dma_ccerr_handler(int
 
 	dev_vdbg(ecc->dev, "dma_ccerr_handler\n");
 
-	if (!edma_error_pending(ecc))
+	if (!edma_error_pending(ecc)) {
+		/*
+		 * The registers indicate no pending error event but the irq
+		 * handler has been called.
+		 * Ask eDMA to re-evaluate the error registers.
+		 */
+		dev_err(ecc->dev, "%s: Error interrupt without error event!\n",
+			__func__);
+		edma_write(ecc, EDMA_EEVAL, 1);
 		return IRQ_NONE;
+	}
 
 	while (1) {
 		/* Event missed register(s) */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma/fsldma.c linux-libre-4.7-gnu/drivers/dma/fsldma.c
--- linux-libre-4.6-gnu/drivers/dma/fsldma.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/dma/fsldma.c	2016-07-24 15:23:50.000000000 -0400
@@ -462,13 +462,12 @@ static struct fsl_desc_sw *fsl_dma_alloc
 	struct fsl_desc_sw *desc;
 	dma_addr_t pdesc;
 
-	desc = dma_pool_alloc(chan->desc_pool, GFP_ATOMIC, &pdesc);
+	desc = dma_pool_zalloc(chan->desc_pool, GFP_ATOMIC, &pdesc);
 	if (!desc) {
 		chan_dbg(chan, "out of memory for link descriptor\n");
 		return NULL;
 	}
 
-	memset(desc, 0, sizeof(*desc));
 	INIT_LIST_HEAD(&desc->tx_list);
 	dma_async_tx_descriptor_init(&desc->async_tx, &chan->common);
 	desc->async_tx.tx_submit = fsl_dma_tx_submit;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma/hsu/hsu.c linux-libre-4.7-gnu/drivers/dma/hsu/hsu.c
--- linux-libre-4.6-gnu/drivers/dma/hsu/hsu.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/dma/hsu/hsu.c	2016-07-24 15:23:50.000000000 -0400
@@ -77,8 +77,8 @@ static void hsu_dma_chan_start(struct hs
 	hsu_chan_writel(hsuc, HSU_CH_MTSR, mtsr);
 
 	/* Set descriptors */
-	count = (desc->nents - desc->active) % HSU_DMA_CHAN_NR_DESC;
-	for (i = 0; i < count; i++) {
+	count = desc->nents - desc->active;
+	for (i = 0; i < count && i < HSU_DMA_CHAN_NR_DESC; i++) {
 		hsu_chan_writel(hsuc, HSU_CH_DxSAR(i), desc->sg[i].addr);
 		hsu_chan_writel(hsuc, HSU_CH_DxTSR(i), desc->sg[i].len);
 
@@ -160,7 +160,7 @@ irqreturn_t hsu_dma_irq(struct hsu_dma_c
 		return IRQ_NONE;
 
 	/* Timeout IRQ, need wait some time, see Errata 2 */
-	if (hsuc->direction == DMA_DEV_TO_MEM && (sr & HSU_CH_SR_DESCTO_ANY))
+	if (sr & HSU_CH_SR_DESCTO_ANY)
 		udelay(2);
 
 	sr &= ~HSU_CH_SR_DESCTO_ANY;
@@ -420,6 +420,8 @@ int hsu_dma_probe(struct hsu_dma_chip *c
 
 	hsu->dma.dev = chip->dev;
 
+	dma_set_max_seg_size(hsu->dma.dev, HSU_CH_DxTSR_MASK);
+
 	ret = dma_async_device_register(&hsu->dma);
 	if (ret)
 		return ret;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma/hsu/hsu.h linux-libre-4.7-gnu/drivers/dma/hsu/hsu.h
--- linux-libre-4.6-gnu/drivers/dma/hsu/hsu.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/dma/hsu/hsu.h	2016-07-24 15:23:50.000000000 -0400
@@ -58,6 +58,10 @@
 #define HSU_CH_DCR_CHEI		BIT(23)
 #define HSU_CH_DCR_CHTOI(x)	BIT(24 + (x))
 
+/* Bits in HSU_CH_DxTSR */
+#define HSU_CH_DxTSR_MASK	GENMASK(15, 0)
+#define HSU_CH_DxTSR_TSR(x)	((x) & HSU_CH_DxTSR_MASK)
+
 struct hsu_dma_sg {
 	dma_addr_t addr;
 	unsigned int len;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma/ioat/init.c linux-libre-4.7-gnu/drivers/dma/ioat/init.c
--- linux-libre-4.6-gnu/drivers/dma/ioat/init.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/dma/ioat/init.c	2016-07-24 15:23:50.000000000 -0400
@@ -690,12 +690,11 @@ static int ioat_alloc_chan_resources(str
 	/* allocate a completion writeback area */
 	/* doing 2 32bit writes to mmio since 1 64b write doesn't work */
 	ioat_chan->completion =
-		dma_pool_alloc(ioat_chan->ioat_dma->completion_pool,
-			       GFP_KERNEL, &ioat_chan->completion_dma);
+		dma_pool_zalloc(ioat_chan->ioat_dma->completion_pool,
+				GFP_KERNEL, &ioat_chan->completion_dma);
 	if (!ioat_chan->completion)
 		return -ENOMEM;
 
-	memset(ioat_chan->completion, 0, sizeof(*ioat_chan->completion));
 	writel(((u64)ioat_chan->completion_dma) & 0x00000000FFFFFFFF,
 	       ioat_chan->reg_base + IOAT_CHANCMP_OFFSET_LOW);
 	writel(((u64)ioat_chan->completion_dma) >> 32,
@@ -1074,6 +1073,7 @@ static int ioat3_dma_probe(struct ioatdm
 	struct ioatdma_chan *ioat_chan;
 	bool is_raid_device = false;
 	int err;
+	u16 val16;
 
 	dma = &ioat_dma->dma_dev;
 	dma->device_prep_dma_memcpy = ioat_dma_prep_memcpy_lock;
@@ -1173,6 +1173,17 @@ static int ioat3_dma_probe(struct ioatdm
 	if (dca)
 		ioat_dma->dca = ioat_dca_init(pdev, ioat_dma->reg_base);
 
+	/* disable relaxed ordering */
+	err = pcie_capability_read_word(pdev, IOAT_DEVCTRL_OFFSET, &val16);
+	if (err)
+		return err;
+
+	/* clear relaxed ordering enable */
+	val16 &= ~IOAT_DEVCTRL_ROE;
+	err = pcie_capability_write_word(pdev, IOAT_DEVCTRL_OFFSET, val16);
+	if (err)
+		return err;
+
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma/ioat/registers.h linux-libre-4.7-gnu/drivers/dma/ioat/registers.h
--- linux-libre-4.6-gnu/drivers/dma/ioat/registers.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/dma/ioat/registers.h	2016-07-24 15:23:50.000000000 -0400
@@ -26,6 +26,13 @@
 #define IOAT_PCI_CHANERR_INT_OFFSET		0x180
 #define IOAT_PCI_CHANERRMASK_INT_OFFSET		0x184
 
+/* PCIe config registers */
+
+/* EXPCAPID + N */
+#define IOAT_DEVCTRL_OFFSET			0x8
+/* relaxed ordering enable */
+#define IOAT_DEVCTRL_ROE			0x10
+
 /* MMIO Device Registers */
 #define IOAT_CHANCNT_OFFSET			0x00	/*  8-bit */
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma/Kconfig linux-libre-4.7-gnu/drivers/dma/Kconfig
--- linux-libre-4.6-gnu/drivers/dma/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/dma/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -332,7 +332,7 @@ config MPC512X_DMA
 
 config MV_XOR
 	bool "Marvell XOR engine support"
-	depends on PLAT_ORION
+	depends on PLAT_ORION || ARCH_MVEBU || COMPILE_TEST
 	select DMA_ENGINE
 	select DMA_ENGINE_RAID
 	select ASYNC_TX_ENABLE_CHANNEL_SWITCH
@@ -467,6 +467,20 @@ config TEGRA20_APB_DMA
 	  This DMA controller transfers data from memory to peripheral fifo
 	  or vice versa. It does not support memory to memory data transfer.
 
+config TEGRA210_ADMA
+	bool "NVIDIA Tegra210 ADMA support"
+	depends on ARCH_TEGRA_210_SOC
+	select DMA_ENGINE
+	select DMA_VIRTUAL_CHANNELS
+	select PM_CLK
+	help
+	  Support for the NVIDIA Tegra210 ADMA controller driver. The
+	  DMA controller has multiple DMA channels and is used to service
+	  various audio clients in the Tegra210 audio processing engine
+	  (APE). This DMA controller transfers data from memory to
+	  peripheral and vice versa. It does not support memory to
+	  memory data transfer.
+
 config TIMB_DMA
 	tristate "Timberdale FPGA DMA support"
 	depends on MFD_TIMBERDALE
@@ -507,7 +521,7 @@ config XGENE_DMA
 
 config XILINX_VDMA
 	tristate "Xilinx AXI VDMA Engine"
-	depends on (ARCH_ZYNQ || MICROBLAZE)
+	depends on (ARCH_ZYNQ || MICROBLAZE || ARM64)
 	select DMA_ENGINE
 	help
 	  Enable support for Xilinx AXI VDMA Soft IP.
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma/Makefile linux-libre-4.7-gnu/drivers/dma/Makefile
--- linux-libre-4.6-gnu/drivers/dma/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/dma/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -59,6 +59,7 @@ obj-$(CONFIG_STM32_DMA) += stm32-dma.o
 obj-$(CONFIG_S3C24XX_DMAC) += s3c24xx-dma.o
 obj-$(CONFIG_TXX9_DMAC) += txx9dmac.o
 obj-$(CONFIG_TEGRA20_APB_DMA) += tegra20-apb-dma.o
+obj-$(CONFIG_TEGRA210_ADMA) += tegra210-adma.o
 obj-$(CONFIG_TIMB_DMA) += timb_dma.o
 obj-$(CONFIG_TI_CPPI41) += cppi41.o
 obj-$(CONFIG_TI_DMA_CROSSBAR) += ti-dma-crossbar.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma/mmp_pdma.c linux-libre-4.7-gnu/drivers/dma/mmp_pdma.c
--- linux-libre-4.6-gnu/drivers/dma/mmp_pdma.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/dma/mmp_pdma.c	2016-07-24 15:23:50.000000000 -0400
@@ -364,13 +364,12 @@ mmp_pdma_alloc_descriptor(struct mmp_pdm
 	struct mmp_pdma_desc_sw *desc;
 	dma_addr_t pdesc;
 
-	desc = dma_pool_alloc(chan->desc_pool, GFP_ATOMIC, &pdesc);
+	desc = dma_pool_zalloc(chan->desc_pool, GFP_ATOMIC, &pdesc);
 	if (!desc) {
 		dev_err(chan->dev, "out of memory for link descriptor\n");
 		return NULL;
 	}
 
-	memset(desc, 0, sizeof(*desc));
 	INIT_LIST_HEAD(&desc->tx_list);
 	dma_async_tx_descriptor_init(&desc->async_tx, &chan->chan);
 	/* each desc has submit */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma/mpc512x_dma.c linux-libre-4.7-gnu/drivers/dma/mpc512x_dma.c
--- linux-libre-4.6-gnu/drivers/dma/mpc512x_dma.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/dma/mpc512x_dma.c	2016-07-24 15:23:50.000000000 -0400
@@ -3,6 +3,7 @@
  * Copyright (C) Semihalf 2009
  * Copyright (C) Ilya Yanok, Emcraft Systems 2010
  * Copyright (C) Alexander Popov, Promcontroller 2014
+ * Copyright (C) Mario Six, Guntermann & Drunck GmbH, 2016
  *
  * Written by Piotr Ziecik <kosmo@semihalf.com>. Hardware description
  * (defines, structures and comments) was taken from MPC5121 DMA driver
@@ -26,18 +27,19 @@
  */
 
 /*
- * MPC512x and MPC8308 DMA driver. It supports
- * memory to memory data transfers (tested using dmatest module) and
- * data transfers between memory and peripheral I/O memory
- * by means of slave scatter/gather with these limitations:
- *  - chunked transfers (described by s/g lists with more than one item)
- *     are refused as long as proper support for scatter/gather is missing;
- *  - transfers on MPC8308 always start from software as this SoC appears
- *     not to have external request lines for peripheral flow control;
- *  - only peripheral devices with 4-byte FIFO access register are supported;
- *  - minimal memory <-> I/O memory transfer chunk is 4 bytes and consequently
- *     source and destination addresses must be 4-byte aligned
- *     and transfer size must be aligned on (4 * maxburst) boundary;
+ * MPC512x and MPC8308 DMA driver. It supports memory to memory data transfers
+ * (tested using dmatest module) and data transfers between memory and
+ * peripheral I/O memory by means of slave scatter/gather with these
+ * limitations:
+ *  - chunked transfers (described by s/g lists with more than one item) are
+ *     refused as long as proper support for scatter/gather is missing
+ *  - transfers on MPC8308 always start from software as this SoC does not have
+ *     external request lines for peripheral flow control
+ *  - memory <-> I/O memory transfer chunks of sizes of 1, 2, 4, 16 (for
+ *     MPC512x), and 32 bytes are supported, and, consequently, source
+ *     addresses and destination addresses must be aligned accordingly;
+ *     furthermore, for MPC512x SoCs, the transfer size must be aligned on
+ *     (chunk size * maxburst)
  */
 
 #include <linux/module.h>
@@ -213,8 +215,10 @@ struct mpc_dma_chan {
 	/* Settings for access to peripheral FIFO */
 	dma_addr_t			src_per_paddr;
 	u32				src_tcd_nunits;
+	u8				swidth;
 	dma_addr_t			dst_per_paddr;
 	u32				dst_tcd_nunits;
+	u8				dwidth;
 
 	/* Lock for this structure */
 	spinlock_t			lock;
@@ -247,6 +251,7 @@ static inline struct mpc_dma_chan *dma_c
 static inline struct mpc_dma *dma_chan_to_mpc_dma(struct dma_chan *c)
 {
 	struct mpc_dma_chan *mchan = dma_chan_to_mpc_dma_chan(c);
+
 	return container_of(mchan, struct mpc_dma, channels[c->chan_id]);
 }
 
@@ -254,9 +259,9 @@ static inline struct mpc_dma *dma_chan_t
  * Execute all queued DMA descriptors.
  *
  * Following requirements must be met while calling mpc_dma_execute():
- * 	a) mchan->lock is acquired,
- * 	b) mchan->active list is empty,
- * 	c) mchan->queued list contains at least one entry.
+ *	a) mchan->lock is acquired,
+ *	b) mchan->active list is empty,
+ *	c) mchan->queued list contains at least one entry.
  */
 static void mpc_dma_execute(struct mpc_dma_chan *mchan)
 {
@@ -446,20 +451,15 @@ static void mpc_dma_tasklet(unsigned lon
 		if (es & MPC_DMA_DMAES_SAE)
 			dev_err(mdma->dma.dev, "- Source Address Error\n");
 		if (es & MPC_DMA_DMAES_SOE)
-			dev_err(mdma->dma.dev, "- Source Offset"
-						" Configuration Error\n");
+			dev_err(mdma->dma.dev, "- Source Offset Configuration Error\n");
 		if (es & MPC_DMA_DMAES_DAE)
-			dev_err(mdma->dma.dev, "- Destination Address"
-								" Error\n");
+			dev_err(mdma->dma.dev, "- Destination Address Error\n");
 		if (es & MPC_DMA_DMAES_DOE)
-			dev_err(mdma->dma.dev, "- Destination Offset"
-						" Configuration Error\n");
+			dev_err(mdma->dma.dev, "- Destination Offset Configuration Error\n");
 		if (es & MPC_DMA_DMAES_NCE)
-			dev_err(mdma->dma.dev, "- NBytes/Citter"
-						" Configuration Error\n");
+			dev_err(mdma->dma.dev, "- NBytes/Citter Configuration Error\n");
 		if (es & MPC_DMA_DMAES_SGE)
-			dev_err(mdma->dma.dev, "- Scatter/Gather"
-						" Configuration Error\n");
+			dev_err(mdma->dma.dev, "- Scatter/Gather Configuration Error\n");
 		if (es & MPC_DMA_DMAES_SBE)
 			dev_err(mdma->dma.dev, "- Source Bus Error\n");
 		if (es & MPC_DMA_DMAES_DBE)
@@ -518,8 +518,8 @@ static int mpc_dma_alloc_chan_resources(
 	for (i = 0; i < MPC_DMA_DESCRIPTORS; i++) {
 		mdesc = kzalloc(sizeof(struct mpc_dma_desc), GFP_KERNEL);
 		if (!mdesc) {
-			dev_notice(mdma->dma.dev, "Memory allocation error. "
-					"Allocated only %u descriptors\n", i);
+			dev_notice(mdma->dma.dev,
+				"Memory allocation error. Allocated only %u descriptors\n", i);
 			break;
 		}
 
@@ -684,6 +684,15 @@ mpc_dma_prep_memcpy(struct dma_chan *cha
 	return &mdesc->desc;
 }
 
+inline u8 buswidth_to_dmatsize(u8 buswidth)
+{
+	u8 res;
+
+	for (res = 0; buswidth > 1; buswidth /= 2)
+		res++;
+	return res;
+}
+
 static struct dma_async_tx_descriptor *
 mpc_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
 		unsigned int sg_len, enum dma_transfer_direction direction,
@@ -742,39 +751,54 @@ mpc_dma_prep_slave_sg(struct dma_chan *c
 
 		memset(tcd, 0, sizeof(struct mpc_dma_tcd));
 
-		if (!IS_ALIGNED(sg_dma_address(sg), 4))
-			goto err_prep;
-
 		if (direction == DMA_DEV_TO_MEM) {
 			tcd->saddr = per_paddr;
 			tcd->daddr = sg_dma_address(sg);
+
+			if (!IS_ALIGNED(sg_dma_address(sg), mchan->dwidth))
+				goto err_prep;
+
 			tcd->soff = 0;
-			tcd->doff = 4;
+			tcd->doff = mchan->dwidth;
 		} else {
 			tcd->saddr = sg_dma_address(sg);
 			tcd->daddr = per_paddr;
-			tcd->soff = 4;
+
+			if (!IS_ALIGNED(sg_dma_address(sg), mchan->swidth))
+				goto err_prep;
+
+			tcd->soff = mchan->swidth;
 			tcd->doff = 0;
 		}
 
-		tcd->ssize = MPC_DMA_TSIZE_4;
-		tcd->dsize = MPC_DMA_TSIZE_4;
+		tcd->ssize = buswidth_to_dmatsize(mchan->swidth);
+		tcd->dsize = buswidth_to_dmatsize(mchan->dwidth);
 
-		len = sg_dma_len(sg);
-		tcd->nbytes = tcd_nunits * 4;
-		if (!IS_ALIGNED(len, tcd->nbytes))
-			goto err_prep;
+		if (mdma->is_mpc8308) {
+			tcd->nbytes = sg_dma_len(sg);
+			if (!IS_ALIGNED(tcd->nbytes, mchan->swidth))
+				goto err_prep;
 
-		iter = len / tcd->nbytes;
-		if (iter >= 1 << 15) {
-			/* len is too big */
-			goto err_prep;
+			/* No major loops for MPC8303 */
+			tcd->biter = 1;
+			tcd->citer = 1;
+		} else {
+			len = sg_dma_len(sg);
+			tcd->nbytes = tcd_nunits * tcd->ssize;
+			if (!IS_ALIGNED(len, tcd->nbytes))
+				goto err_prep;
+
+			iter = len / tcd->nbytes;
+			if (iter >= 1 << 15) {
+				/* len is too big */
+				goto err_prep;
+			}
+			/* citer_linkch contains the high bits of iter */
+			tcd->biter = iter & 0x1ff;
+			tcd->biter_linkch = iter >> 9;
+			tcd->citer = tcd->biter;
+			tcd->citer_linkch = tcd->biter_linkch;
 		}
-		/* citer_linkch contains the high bits of iter */
-		tcd->biter = iter & 0x1ff;
-		tcd->biter_linkch = iter >> 9;
-		tcd->citer = tcd->biter;
-		tcd->citer_linkch = tcd->biter_linkch;
 
 		tcd->e_sg = 0;
 		tcd->d_req = 1;
@@ -796,40 +820,62 @@ err_prep:
 	return NULL;
 }
 
+inline bool is_buswidth_valid(u8 buswidth, bool is_mpc8308)
+{
+	switch (buswidth) {
+	case 16:
+		if (is_mpc8308)
+			return false;
+	case 1:
+	case 2:
+	case 4:
+	case 32:
+		break;
+	default:
+		return false;
+	}
+
+	return true;
+}
+
 static int mpc_dma_device_config(struct dma_chan *chan,
 				 struct dma_slave_config *cfg)
 {
 	struct mpc_dma_chan *mchan = dma_chan_to_mpc_dma_chan(chan);
+	struct mpc_dma *mdma = dma_chan_to_mpc_dma(&mchan->chan);
 	unsigned long flags;
 
 	/*
 	 * Software constraints:
-	 *  - only transfers between a peripheral device and
-	 *     memory are supported;
-	 *  - only peripheral devices with 4-byte FIFO access register
-	 *     are supported;
-	 *  - minimal transfer chunk is 4 bytes and consequently
-	 *     source and destination addresses must be 4-byte aligned
-	 *     and transfer size must be aligned on (4 * maxburst)
-	 *     boundary;
-	 *  - during the transfer RAM address is being incremented by
-	 *     the size of minimal transfer chunk;
-	 *  - peripheral port's address is constant during the transfer.
+	 *  - only transfers between a peripheral device and memory are
+	 *     supported
+	 *  - transfer chunk sizes of 1, 2, 4, 16 (for MPC512x), and 32 bytes
+	 *     are supported, and, consequently, source addresses and
+	 *     destination addresses; must be aligned accordingly; furthermore,
+	 *     for MPC512x SoCs, the transfer size must be aligned on (chunk
+	 *     size * maxburst)
+	 *  - during the transfer, the RAM address is incremented by the size
+	 *     of transfer chunk
+	 *  - the peripheral port's address is constant during the transfer.
 	 */
 
-	if (cfg->src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES ||
-	    cfg->dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES ||
-	    !IS_ALIGNED(cfg->src_addr, 4) ||
-	    !IS_ALIGNED(cfg->dst_addr, 4)) {
+	if (!IS_ALIGNED(cfg->src_addr, cfg->src_addr_width) ||
+	    !IS_ALIGNED(cfg->dst_addr, cfg->dst_addr_width)) {
 		return -EINVAL;
 	}
 
+	if (!is_buswidth_valid(cfg->src_addr_width, mdma->is_mpc8308) ||
+	    !is_buswidth_valid(cfg->dst_addr_width, mdma->is_mpc8308))
+		return -EINVAL;
+
 	spin_lock_irqsave(&mchan->lock, flags);
 
 	mchan->src_per_paddr = cfg->src_addr;
 	mchan->src_tcd_nunits = cfg->src_maxburst;
+	mchan->swidth = cfg->src_addr_width;
 	mchan->dst_per_paddr = cfg->dst_addr;
 	mchan->dst_tcd_nunits = cfg->dst_maxburst;
+	mchan->dwidth = cfg->dst_addr_width;
 
 	/* Apply defaults */
 	if (mchan->src_tcd_nunits == 0)
@@ -875,7 +921,6 @@ static int mpc_dma_probe(struct platform
 
 	mdma = devm_kzalloc(dev, sizeof(struct mpc_dma), GFP_KERNEL);
 	if (!mdma) {
-		dev_err(dev, "Memory exhausted!\n");
 		retval = -ENOMEM;
 		goto err;
 	}
@@ -999,7 +1044,8 @@ static int mpc_dma_probe(struct platform
 		out_be32(&mdma->regs->dmaerrl, 0xFFFF);
 	} else {
 		out_be32(&mdma->regs->dmacr, MPC_DMA_DMACR_EDCG |
-					MPC_DMA_DMACR_ERGA | MPC_DMA_DMACR_ERCA);
+						MPC_DMA_DMACR_ERGA |
+						MPC_DMA_DMACR_ERCA);
 
 		/* Disable hardware DMA requests */
 		out_be32(&mdma->regs->dmaerqh, 0);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma/mv_xor.c linux-libre-4.7-gnu/drivers/dma/mv_xor.c
--- linux-libre-4.6-gnu/drivers/dma/mv_xor.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/dma/mv_xor.c	2016-07-24 15:23:50.000000000 -0400
@@ -31,6 +31,12 @@
 #include "dmaengine.h"
 #include "mv_xor.h"
 
+enum mv_xor_type {
+	XOR_ORION,
+	XOR_ARMADA_38X,
+	XOR_ARMADA_37XX,
+};
+
 enum mv_xor_mode {
 	XOR_MODE_IN_REG,
 	XOR_MODE_IN_DESC,
@@ -477,7 +483,7 @@ mv_xor_prep_dma_xor(struct dma_chan *cha
 	BUG_ON(len > MV_XOR_MAX_BYTE_COUNT);
 
 	dev_dbg(mv_chan_to_devp(mv_chan),
-		"%s src_cnt: %d len: %u dest %pad flags: %ld\n",
+		"%s src_cnt: %d len: %zu dest %pad flags: %ld\n",
 		__func__, src_cnt, len, &dest, flags);
 
 	sw_desc = mv_chan_alloc_slot(mv_chan);
@@ -697,8 +703,9 @@ static int mv_chan_memcpy_self_test(stru
 		goto free_resources;
 	}
 
-	src_dma = dma_map_page(dma_chan->device->dev, virt_to_page(src), 0,
-				 PAGE_SIZE, DMA_TO_DEVICE);
+	src_dma = dma_map_page(dma_chan->device->dev, virt_to_page(src),
+			       (size_t)src & ~PAGE_MASK, PAGE_SIZE,
+			       DMA_TO_DEVICE);
 	unmap->addr[0] = src_dma;
 
 	ret = dma_mapping_error(dma_chan->device->dev, src_dma);
@@ -708,8 +715,9 @@ static int mv_chan_memcpy_self_test(stru
 	}
 	unmap->to_cnt = 1;
 
-	dest_dma = dma_map_page(dma_chan->device->dev, virt_to_page(dest), 0,
-				  PAGE_SIZE, DMA_FROM_DEVICE);
+	dest_dma = dma_map_page(dma_chan->device->dev, virt_to_page(dest),
+				(size_t)dest & ~PAGE_MASK, PAGE_SIZE,
+				DMA_FROM_DEVICE);
 	unmap->addr[1] = dest_dma;
 
 	ret = dma_mapping_error(dma_chan->device->dev, dest_dma);
@@ -933,7 +941,7 @@ static int mv_xor_channel_remove(struct
 static struct mv_xor_chan *
 mv_xor_channel_add(struct mv_xor_device *xordev,
 		   struct platform_device *pdev,
-		   int idx, dma_cap_mask_t cap_mask, int irq, int op_in_desc)
+		   int idx, dma_cap_mask_t cap_mask, int irq)
 {
 	int ret = 0;
 	struct mv_xor_chan *mv_chan;
@@ -945,7 +953,10 @@ mv_xor_channel_add(struct mv_xor_device
 
 	mv_chan->idx = idx;
 	mv_chan->irq = irq;
-	mv_chan->op_in_desc = op_in_desc;
+	if (xordev->xor_type == XOR_ORION)
+		mv_chan->op_in_desc = XOR_MODE_IN_REG;
+	else
+		mv_chan->op_in_desc = XOR_MODE_IN_DESC;
 
 	dma_dev = &mv_chan->dmadev;
 
@@ -1085,6 +1096,33 @@ mv_xor_conf_mbus_windows(struct mv_xor_d
 	writel(0, base + WINDOW_OVERRIDE_CTRL(1));
 }
 
+static void
+mv_xor_conf_mbus_windows_a3700(struct mv_xor_device *xordev)
+{
+	void __iomem *base = xordev->xor_high_base;
+	u32 win_enable = 0;
+	int i;
+
+	for (i = 0; i < 8; i++) {
+		writel(0, base + WINDOW_BASE(i));
+		writel(0, base + WINDOW_SIZE(i));
+		if (i < 4)
+			writel(0, base + WINDOW_REMAP_HIGH(i));
+	}
+	/*
+	 * For Armada3700 open default 4GB Mbus window. The dram
+	 * related configuration are done at AXIS level.
+	 */
+	writel(0xffff0000, base + WINDOW_SIZE(0));
+	win_enable |= 1;
+	win_enable |= 3 << 16;
+
+	writel(win_enable, base + WINDOW_BAR_ENABLE(0));
+	writel(win_enable, base + WINDOW_BAR_ENABLE(1));
+	writel(0, base + WINDOW_OVERRIDE_CTRL(0));
+	writel(0, base + WINDOW_OVERRIDE_CTRL(1));
+}
+
 /*
  * Since this XOR driver is basically used only for RAID5, we don't
  * need to care about synchronizing ->suspend with DMA activity,
@@ -1129,6 +1167,11 @@ static int mv_xor_resume(struct platform
 			       XOR_INTR_MASK(mv_chan));
 	}
 
+	if (xordev->xor_type == XOR_ARMADA_37XX) {
+		mv_xor_conf_mbus_windows_a3700(xordev);
+		return 0;
+	}
+
 	dram = mv_mbus_dram_info();
 	if (dram)
 		mv_xor_conf_mbus_windows(xordev, dram);
@@ -1137,8 +1180,9 @@ static int mv_xor_resume(struct platform
 }
 
 static const struct of_device_id mv_xor_dt_ids[] = {
-	{ .compatible = "marvell,orion-xor", .data = (void *)XOR_MODE_IN_REG },
-	{ .compatible = "marvell,armada-380-xor", .data = (void *)XOR_MODE_IN_DESC },
+	{ .compatible = "marvell,orion-xor", .data = (void *)XOR_ORION },
+	{ .compatible = "marvell,armada-380-xor", .data = (void *)XOR_ARMADA_38X },
+	{ .compatible = "marvell,armada-3700-xor", .data = (void *)XOR_ARMADA_37XX },
 	{},
 };
 
@@ -1152,7 +1196,6 @@ static int mv_xor_probe(struct platform_
 	struct resource *res;
 	unsigned int max_engines, max_channels;
 	int i, ret;
-	int op_in_desc;
 
 	dev_notice(&pdev->dev, "Marvell shared XOR driver\n");
 
@@ -1180,12 +1223,30 @@ static int mv_xor_probe(struct platform_
 
 	platform_set_drvdata(pdev, xordev);
 
+
+	/*
+	 * We need to know which type of XOR device we use before
+	 * setting up. In non-dt case it can only be the legacy one.
+	 */
+	xordev->xor_type = XOR_ORION;
+	if (pdev->dev.of_node) {
+		const struct of_device_id *of_id =
+			of_match_device(mv_xor_dt_ids,
+					&pdev->dev);
+
+		xordev->xor_type = (uintptr_t)of_id->data;
+	}
+
 	/*
 	 * (Re-)program MBUS remapping windows if we are asked to.
 	 */
-	dram = mv_mbus_dram_info();
-	if (dram)
-		mv_xor_conf_mbus_windows(xordev, dram);
+	if (xordev->xor_type == XOR_ARMADA_37XX) {
+		mv_xor_conf_mbus_windows_a3700(xordev);
+	} else {
+		dram = mv_mbus_dram_info();
+		if (dram)
+			mv_xor_conf_mbus_windows(xordev, dram);
+	}
 
 	/* Not all platforms can gate the clock, so it is not
 	 * an error if the clock does not exists.
@@ -1199,12 +1260,16 @@ static int mv_xor_probe(struct platform_
 	 * order for async_tx to perform well. So we limit the number
 	 * of engines and channels so that we take into account this
 	 * constraint. Note that we also want to use channels from
-	 * separate engines when possible.
+	 * separate engines when possible.  For dual-CPU Armada 3700
+	 * SoC with single XOR engine allow using its both channels.
 	 */
 	max_engines = num_present_cpus();
-	max_channels = min_t(unsigned int,
-			     MV_XOR_MAX_CHANNELS,
-			     DIV_ROUND_UP(num_present_cpus(), 2));
+	if (xordev->xor_type == XOR_ARMADA_37XX)
+		max_channels =	num_present_cpus();
+	else
+		max_channels = min_t(unsigned int,
+				     MV_XOR_MAX_CHANNELS,
+				     DIV_ROUND_UP(num_present_cpus(), 2));
 
 	if (mv_xor_engine_count >= max_engines)
 		return 0;
@@ -1212,15 +1277,11 @@ static int mv_xor_probe(struct platform_
 	if (pdev->dev.of_node) {
 		struct device_node *np;
 		int i = 0;
-		const struct of_device_id *of_id =
-			of_match_device(mv_xor_dt_ids,
-					&pdev->dev);
 
 		for_each_child_of_node(pdev->dev.of_node, np) {
 			struct mv_xor_chan *chan;
 			dma_cap_mask_t cap_mask;
 			int irq;
-			op_in_desc = (int)of_id->data;
 
 			if (i >= max_channels)
 				continue;
@@ -1237,7 +1298,7 @@ static int mv_xor_probe(struct platform_
 			}
 
 			chan = mv_xor_channel_add(xordev, pdev, i,
-						  cap_mask, irq, op_in_desc);
+						  cap_mask, irq);
 			if (IS_ERR(chan)) {
 				ret = PTR_ERR(chan);
 				irq_dispose_mapping(irq);
@@ -1266,8 +1327,7 @@ static int mv_xor_probe(struct platform_
 			}
 
 			chan = mv_xor_channel_add(xordev, pdev, i,
-						  cd->cap_mask, irq,
-						  XOR_MODE_IN_REG);
+						  cd->cap_mask, irq);
 			if (IS_ERR(chan)) {
 				ret = PTR_ERR(chan);
 				goto err_channel_add;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma/mv_xor.h linux-libre-4.7-gnu/drivers/dma/mv_xor.h
--- linux-libre-4.6-gnu/drivers/dma/mv_xor.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/dma/mv_xor.h	2016-07-24 15:23:50.000000000 -0400
@@ -85,6 +85,7 @@ struct mv_xor_device {
 	void __iomem	     *xor_high_base;
 	struct clk	     *clk;
 	struct mv_xor_chan   *channels[MV_XOR_MAX_CHANNELS];
+	int		     xor_type;
 };
 
 /**
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma/of-dma.c linux-libre-4.7-gnu/drivers/dma/of-dma.c
--- linux-libre-4.6-gnu/drivers/dma/of-dma.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/dma/of-dma.c	2016-07-24 15:23:50.000000000 -0400
@@ -240,8 +240,9 @@ struct dma_chan *of_dma_request_slave_ch
 	struct of_phandle_args	dma_spec;
 	struct of_dma		*ofdma;
 	struct dma_chan		*chan;
-	int			count, i;
+	int			count, i, start;
 	int			ret_no_channel = -ENODEV;
+	static atomic_t		last_index;
 
 	if (!np || !name) {
 		pr_err("%s: not enough information provided\n", __func__);
@@ -259,8 +260,15 @@ struct dma_chan *of_dma_request_slave_ch
 		return ERR_PTR(-ENODEV);
 	}
 
+	/*
+	 * approximate an average distribution across multiple
+	 * entries with the same name
+	 */
+	start = atomic_inc_return(&last_index);
 	for (i = 0; i < count; i++) {
-		if (of_dma_match_channel(np, name, i, &dma_spec))
+		if (of_dma_match_channel(np, name,
+					 (i + start) % count,
+					 &dma_spec))
 			continue;
 
 		mutex_lock(&of_dma_lock);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma/pxa_dma.c linux-libre-4.7-gnu/drivers/dma/pxa_dma.c
--- linux-libre-4.6-gnu/drivers/dma/pxa_dma.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/dma/pxa_dma.c	2016-07-24 15:23:50.000000000 -0400
@@ -117,6 +117,7 @@ struct pxad_chan {
 	/* protected by vc->lock */
 	struct pxad_phy		*phy;
 	struct dma_pool		*desc_pool;	/* Descriptors pool */
+	dma_cookie_t		bus_error;
 };
 
 struct pxad_device {
@@ -563,6 +564,7 @@ static void pxad_launch_chan(struct pxad
 			return;
 		}
 	}
+	chan->bus_error = 0;
 
 	/*
 	 * Program the descriptor's address into the DMA controller,
@@ -666,6 +668,7 @@ static irqreturn_t pxad_chan_handler(int
 	struct virt_dma_desc *vd, *tmp;
 	unsigned int dcsr;
 	unsigned long flags;
+	dma_cookie_t last_started = 0;
 
 	BUG_ON(!chan);
 
@@ -678,6 +681,7 @@ static irqreturn_t pxad_chan_handler(int
 		dev_dbg(&chan->vc.chan.dev->device,
 			"%s(): checking txd %p[%x]: completed=%d\n",
 			__func__, vd, vd->tx.cookie, is_desc_completed(vd));
+		last_started = vd->tx.cookie;
 		if (to_pxad_sw_desc(vd)->cyclic) {
 			vchan_cyclic_callback(vd);
 			break;
@@ -690,7 +694,12 @@ static irqreturn_t pxad_chan_handler(int
 		}
 	}
 
-	if (dcsr & PXA_DCSR_STOPSTATE) {
+	if (dcsr & PXA_DCSR_BUSERR) {
+		chan->bus_error = last_started;
+		phy_disable(phy);
+	}
+
+	if (!chan->bus_error && dcsr & PXA_DCSR_STOPSTATE) {
 		dev_dbg(&chan->vc.chan.dev->device,
 		"%s(): channel stopped, submitted_empty=%d issued_empty=%d",
 			__func__,
@@ -1249,6 +1258,9 @@ static enum dma_status pxad_tx_status(st
 	struct pxad_chan *chan = to_pxad_chan(dchan);
 	enum dma_status ret;
 
+	if (cookie == chan->bus_error)
+		return DMA_ERROR;
+
 	ret = dma_cookie_status(dchan, cookie, txstate);
 	if (likely(txstate && (ret != DMA_ERROR)))
 		dma_set_residue(txstate, pxad_residue(chan, cookie));
@@ -1321,7 +1333,7 @@ static int pxad_init_phys(struct platfor
 	return 0;
 }
 
-static const struct of_device_id const pxad_dt_ids[] = {
+static const struct of_device_id pxad_dt_ids[] = {
 	{ .compatible = "marvell,pdma-1.0", },
 	{}
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma/qcom/bam_dma.c linux-libre-4.7-gnu/drivers/dma/qcom/bam_dma.c
--- linux-libre-4.6-gnu/drivers/dma/qcom/bam_dma.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/dma/qcom/bam_dma.c	2016-07-24 15:23:50.000000000 -0400
@@ -342,7 +342,7 @@ static const struct reg_offset_data bam_
 
 #define BAM_DESC_FIFO_SIZE	SZ_32K
 #define MAX_DESCRIPTORS (BAM_DESC_FIFO_SIZE / sizeof(struct bam_desc_hw) - 1)
-#define BAM_MAX_DATA_SIZE	(SZ_32K - 8)
+#define BAM_FIFO_SIZE	(SZ_32K - 8)
 
 struct bam_chan {
 	struct virt_dma_chan vc;
@@ -387,6 +387,7 @@ struct bam_device {
 
 	/* execution environment ID, from DT */
 	u32 ee;
+	bool controlled_remotely;
 
 	const struct reg_offset_data *layout;
 
@@ -458,7 +459,7 @@ static void bam_chan_init_hw(struct bam_
 	 */
 	writel_relaxed(ALIGN(bchan->fifo_phys, sizeof(struct bam_desc_hw)),
 			bam_addr(bdev, bchan->id, BAM_P_DESC_FIFO_ADDR));
-	writel_relaxed(BAM_DESC_FIFO_SIZE,
+	writel_relaxed(BAM_FIFO_SIZE,
 			bam_addr(bdev, bchan->id, BAM_P_FIFO_SIZES));
 
 	/* enable the per pipe interrupts, enable EOT, ERR, and INT irqs */
@@ -604,7 +605,7 @@ static struct dma_async_tx_descriptor *b
 
 	/* calculate number of required entries */
 	for_each_sg(sgl, sg, sg_len, i)
-		num_alloc += DIV_ROUND_UP(sg_dma_len(sg), BAM_MAX_DATA_SIZE);
+		num_alloc += DIV_ROUND_UP(sg_dma_len(sg), BAM_FIFO_SIZE);
 
 	/* allocate enough room to accomodate the number of entries */
 	async_desc = kzalloc(sizeof(*async_desc) +
@@ -635,10 +636,10 @@ static struct dma_async_tx_descriptor *b
 			desc->addr = cpu_to_le32(sg_dma_address(sg) +
 						 curr_offset);
 
-			if (remainder > BAM_MAX_DATA_SIZE) {
-				desc->size = cpu_to_le16(BAM_MAX_DATA_SIZE);
-				remainder -= BAM_MAX_DATA_SIZE;
-				curr_offset += BAM_MAX_DATA_SIZE;
+			if (remainder > BAM_FIFO_SIZE) {
+				desc->size = cpu_to_le16(BAM_FIFO_SIZE);
+				remainder -= BAM_FIFO_SIZE;
+				curr_offset += BAM_FIFO_SIZE;
 			} else {
 				desc->size = cpu_to_le16(remainder);
 				remainder = 0;
@@ -801,13 +802,17 @@ static irqreturn_t bam_dma_irq(int irq,
 	if (srcs & P_IRQ)
 		tasklet_schedule(&bdev->task);
 
-	if (srcs & BAM_IRQ)
+	if (srcs & BAM_IRQ) {
 		clr_mask = readl_relaxed(bam_addr(bdev, 0, BAM_IRQ_STTS));
 
-	/* don't allow reorder of the various accesses to the BAM registers */
-	mb();
+		/*
+		 * don't allow reorder of the various accesses to the BAM
+		 * registers
+		 */
+		mb();
 
-	writel_relaxed(clr_mask, bam_addr(bdev, 0, BAM_IRQ_CLR));
+		writel_relaxed(clr_mask, bam_addr(bdev, 0, BAM_IRQ_CLR));
+	}
 
 	return IRQ_HANDLED;
 }
@@ -1038,6 +1043,9 @@ static int bam_init(struct bam_device *b
 	val = readl_relaxed(bam_addr(bdev, 0, BAM_NUM_PIPES));
 	bdev->num_channels = val & BAM_NUM_PIPES_MASK;
 
+	if (bdev->controlled_remotely)
+		return 0;
+
 	/* s/w reset bam */
 	/* after reset all pipes are disabled and idle */
 	val = readl_relaxed(bam_addr(bdev, 0, BAM_CTRL));
@@ -1125,6 +1133,9 @@ static int bam_dma_probe(struct platform
 		return ret;
 	}
 
+	bdev->controlled_remotely = of_property_read_bool(pdev->dev.of_node,
+						"qcom,controlled-remotely");
+
 	bdev->bamclk = devm_clk_get(bdev->dev, "bam_clk");
 	if (IS_ERR(bdev->bamclk))
 		return PTR_ERR(bdev->bamclk);
@@ -1163,7 +1174,7 @@ static int bam_dma_probe(struct platform
 	/* set max dma segment size */
 	bdev->common.dev = bdev->dev;
 	bdev->common.dev->dma_parms = &bdev->dma_parms;
-	ret = dma_set_max_seg_size(bdev->common.dev, BAM_MAX_DATA_SIZE);
+	ret = dma_set_max_seg_size(bdev->common.dev, BAM_FIFO_SIZE);
 	if (ret) {
 		dev_err(bdev->dev, "cannot set maximum segment size\n");
 		goto err_bam_channel_exit;
@@ -1234,6 +1245,9 @@ static int bam_dma_remove(struct platfor
 		bam_dma_terminate_all(&bdev->channels[i].vc.chan);
 		tasklet_kill(&bdev->channels[i].vc.task);
 
+		if (!bdev->channels[i].fifo_virt)
+			continue;
+
 		dma_free_wc(bdev->dev, BAM_DESC_FIFO_SIZE,
 			    bdev->channels[i].fifo_virt,
 			    bdev->channels[i].fifo_phys);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma/qcom/hidma.c linux-libre-4.7-gnu/drivers/dma/qcom/hidma.c
--- linux-libre-4.6-gnu/drivers/dma/qcom/hidma.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/dma/qcom/hidma.c	2016-07-24 15:23:50.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Qualcomm Technologies HIDMA DMA engine interface
  *
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -404,7 +404,7 @@ static int hidma_terminate_channel(struc
 	spin_unlock_irqrestore(&mchan->lock, irqflags);
 
 	/* this suspends the existing transfer */
-	rc = hidma_ll_pause(dmadev->lldev);
+	rc = hidma_ll_disable(dmadev->lldev);
 	if (rc) {
 		dev_err(dmadev->ddev.dev, "channel did not pause\n");
 		goto out;
@@ -427,7 +427,7 @@ static int hidma_terminate_channel(struc
 		list_move(&mdesc->node, &mchan->free);
 	}
 
-	rc = hidma_ll_resume(dmadev->lldev);
+	rc = hidma_ll_enable(dmadev->lldev);
 out:
 	pm_runtime_mark_last_busy(dmadev->ddev.dev);
 	pm_runtime_put_autosuspend(dmadev->ddev.dev);
@@ -488,7 +488,7 @@ static int hidma_pause(struct dma_chan *
 	dmadev = to_hidma_dev(mchan->chan.device);
 	if (!mchan->paused) {
 		pm_runtime_get_sync(dmadev->ddev.dev);
-		if (hidma_ll_pause(dmadev->lldev))
+		if (hidma_ll_disable(dmadev->lldev))
 			dev_warn(dmadev->ddev.dev, "channel did not stop\n");
 		mchan->paused = true;
 		pm_runtime_mark_last_busy(dmadev->ddev.dev);
@@ -507,7 +507,7 @@ static int hidma_resume(struct dma_chan
 	dmadev = to_hidma_dev(mchan->chan.device);
 	if (mchan->paused) {
 		pm_runtime_get_sync(dmadev->ddev.dev);
-		rc = hidma_ll_resume(dmadev->lldev);
+		rc = hidma_ll_enable(dmadev->lldev);
 		if (!rc)
 			mchan->paused = false;
 		else
@@ -530,6 +530,43 @@ static irqreturn_t hidma_chirq_handler(i
 	return hidma_ll_inthandler(chirq, lldev);
 }
 
+static ssize_t hidma_show_values(struct device *dev,
+				 struct device_attribute *attr, char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct hidma_dev *mdev = platform_get_drvdata(pdev);
+
+	buf[0] = 0;
+
+	if (strcmp(attr->attr.name, "chid") == 0)
+		sprintf(buf, "%d\n", mdev->chidx);
+
+	return strlen(buf);
+}
+
+static int hidma_create_sysfs_entry(struct hidma_dev *dev, char *name,
+				    int mode)
+{
+	struct device_attribute *attrs;
+	char *name_copy;
+
+	attrs = devm_kmalloc(dev->ddev.dev, sizeof(struct device_attribute),
+			     GFP_KERNEL);
+	if (!attrs)
+		return -ENOMEM;
+
+	name_copy = devm_kstrdup(dev->ddev.dev, name, GFP_KERNEL);
+	if (!name_copy)
+		return -ENOMEM;
+
+	attrs->attr.name = name_copy;
+	attrs->attr.mode = mode;
+	attrs->show = hidma_show_values;
+	sysfs_attr_init(&attrs->attr);
+
+	return device_create_file(dev->ddev.dev, attrs);
+}
+
 static int hidma_probe(struct platform_device *pdev)
 {
 	struct hidma_dev *dmadev;
@@ -644,6 +681,8 @@ static int hidma_probe(struct platform_d
 
 	dmadev->irq = chirq;
 	tasklet_init(&dmadev->task, hidma_issue_task, (unsigned long)dmadev);
+	hidma_debug_init(dmadev);
+	hidma_create_sysfs_entry(dmadev, "chid", S_IRUGO);
 	dev_info(&pdev->dev, "HI-DMA engine driver registration complete\n");
 	platform_set_drvdata(pdev, dmadev);
 	pm_runtime_mark_last_busy(dmadev->ddev.dev);
@@ -651,6 +690,7 @@ static int hidma_probe(struct platform_d
 	return 0;
 
 uninit:
+	hidma_debug_uninit(dmadev);
 	hidma_ll_uninit(dmadev->lldev);
 dmafree:
 	if (dmadev)
@@ -668,6 +708,7 @@ static int hidma_remove(struct platform_
 	pm_runtime_get_sync(dmadev->ddev.dev);
 	dma_async_device_unregister(&dmadev->ddev);
 	devm_free_irq(dmadev->ddev.dev, dmadev->irq, dmadev->lldev);
+	hidma_debug_uninit(dmadev);
 	hidma_ll_uninit(dmadev->lldev);
 	hidma_free(dmadev);
 
@@ -689,7 +730,6 @@ static const struct of_device_id hidma_m
 	{.compatible = "qcom,hidma-1.0",},
 	{},
 };
-
 MODULE_DEVICE_TABLE(of, hidma_match);
 
 static struct platform_driver hidma_driver = {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma/qcom/hidma_dbg.c linux-libre-4.7-gnu/drivers/dma/qcom/hidma_dbg.c
--- linux-libre-4.6-gnu/drivers/dma/qcom/hidma_dbg.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/dma/qcom/hidma_dbg.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,217 @@
+/*
+ * Qualcomm Technologies HIDMA debug file
+ *
+ * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 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.
+ */
+
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/pm_runtime.h>
+
+#include "hidma.h"
+
+static void hidma_ll_chstats(struct seq_file *s, void *llhndl, u32 tre_ch)
+{
+	struct hidma_lldev *lldev = llhndl;
+	struct hidma_tre *tre;
+	u32 length;
+	dma_addr_t src_start;
+	dma_addr_t dest_start;
+	u32 *tre_local;
+
+	if (tre_ch >= lldev->nr_tres) {
+		dev_err(lldev->dev, "invalid TRE number in chstats:%d", tre_ch);
+		return;
+	}
+	tre = &lldev->trepool[tre_ch];
+	seq_printf(s, "------Channel %d -----\n", tre_ch);
+	seq_printf(s, "allocated=%d\n", atomic_read(&tre->allocated));
+	seq_printf(s, "queued = 0x%x\n", tre->queued);
+	seq_printf(s, "err_info = 0x%x\n", tre->err_info);
+	seq_printf(s, "err_code = 0x%x\n", tre->err_code);
+	seq_printf(s, "status = 0x%x\n", tre->status);
+	seq_printf(s, "idx = 0x%x\n", tre->idx);
+	seq_printf(s, "dma_sig = 0x%x\n", tre->dma_sig);
+	seq_printf(s, "dev_name=%s\n", tre->dev_name);
+	seq_printf(s, "callback=%p\n", tre->callback);
+	seq_printf(s, "data=%p\n", tre->data);
+	seq_printf(s, "tre_index = 0x%x\n", tre->tre_index);
+
+	tre_local = &tre->tre_local[0];
+	src_start = tre_local[HIDMA_TRE_SRC_LOW_IDX];
+	src_start = ((u64) (tre_local[HIDMA_TRE_SRC_HI_IDX]) << 32) + src_start;
+	dest_start = tre_local[HIDMA_TRE_DEST_LOW_IDX];
+	dest_start += ((u64) (tre_local[HIDMA_TRE_DEST_HI_IDX]) << 32);
+	length = tre_local[HIDMA_TRE_LEN_IDX];
+
+	seq_printf(s, "src=%pap\n", &src_start);
+	seq_printf(s, "dest=%pap\n", &dest_start);
+	seq_printf(s, "length = 0x%x\n", length);
+}
+
+static void hidma_ll_devstats(struct seq_file *s, void *llhndl)
+{
+	struct hidma_lldev *lldev = llhndl;
+
+	seq_puts(s, "------Device -----\n");
+	seq_printf(s, "lldev init = 0x%x\n", lldev->initialized);
+	seq_printf(s, "trch_state = 0x%x\n", lldev->trch_state);
+	seq_printf(s, "evch_state = 0x%x\n", lldev->evch_state);
+	seq_printf(s, "chidx = 0x%x\n", lldev->chidx);
+	seq_printf(s, "nr_tres = 0x%x\n", lldev->nr_tres);
+	seq_printf(s, "trca=%p\n", lldev->trca);
+	seq_printf(s, "tre_ring=%p\n", lldev->tre_ring);
+	seq_printf(s, "tre_ring_handle=%pap\n", &lldev->tre_dma);
+	seq_printf(s, "tre_ring_size = 0x%x\n", lldev->tre_ring_size);
+	seq_printf(s, "tre_processed_off = 0x%x\n", lldev->tre_processed_off);
+	seq_printf(s, "pending_tre_count=%d\n", lldev->pending_tre_count);
+	seq_printf(s, "evca=%p\n", lldev->evca);
+	seq_printf(s, "evre_ring=%p\n", lldev->evre_ring);
+	seq_printf(s, "evre_ring_handle=%pap\n", &lldev->evre_dma);
+	seq_printf(s, "evre_ring_size = 0x%x\n", lldev->evre_ring_size);
+	seq_printf(s, "evre_processed_off = 0x%x\n", lldev->evre_processed_off);
+	seq_printf(s, "tre_write_offset = 0x%x\n", lldev->tre_write_offset);
+}
+
+/*
+ * hidma_chan_stats: display HIDMA channel statistics
+ *
+ * Display the statistics for the current HIDMA virtual channel device.
+ */
+static int hidma_chan_stats(struct seq_file *s, void *unused)
+{
+	struct hidma_chan *mchan = s->private;
+	struct hidma_desc *mdesc;
+	struct hidma_dev *dmadev = mchan->dmadev;
+
+	pm_runtime_get_sync(dmadev->ddev.dev);
+	seq_printf(s, "paused=%u\n", mchan->paused);
+	seq_printf(s, "dma_sig=%u\n", mchan->dma_sig);
+	seq_puts(s, "prepared\n");
+	list_for_each_entry(mdesc, &mchan->prepared, node)
+		hidma_ll_chstats(s, mchan->dmadev->lldev, mdesc->tre_ch);
+
+	seq_puts(s, "active\n");
+	list_for_each_entry(mdesc, &mchan->active, node)
+		hidma_ll_chstats(s, mchan->dmadev->lldev, mdesc->tre_ch);
+
+	seq_puts(s, "completed\n");
+	list_for_each_entry(mdesc, &mchan->completed, node)
+		hidma_ll_chstats(s, mchan->dmadev->lldev, mdesc->tre_ch);
+
+	hidma_ll_devstats(s, mchan->dmadev->lldev);
+	pm_runtime_mark_last_busy(dmadev->ddev.dev);
+	pm_runtime_put_autosuspend(dmadev->ddev.dev);
+	return 0;
+}
+
+/*
+ * hidma_dma_info: display HIDMA device info
+ *
+ * Display the info for the current HIDMA device.
+ */
+static int hidma_dma_info(struct seq_file *s, void *unused)
+{
+	struct hidma_dev *dmadev = s->private;
+	resource_size_t sz;
+
+	seq_printf(s, "nr_descriptors=%d\n", dmadev->nr_descriptors);
+	seq_printf(s, "dev_trca=%p\n", &dmadev->dev_trca);
+	seq_printf(s, "dev_trca_phys=%pa\n", &dmadev->trca_resource->start);
+	sz = resource_size(dmadev->trca_resource);
+	seq_printf(s, "dev_trca_size=%pa\n", &sz);
+	seq_printf(s, "dev_evca=%p\n", &dmadev->dev_evca);
+	seq_printf(s, "dev_evca_phys=%pa\n", &dmadev->evca_resource->start);
+	sz = resource_size(dmadev->evca_resource);
+	seq_printf(s, "dev_evca_size=%pa\n", &sz);
+	return 0;
+}
+
+static int hidma_chan_stats_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, hidma_chan_stats, inode->i_private);
+}
+
+static int hidma_dma_info_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, hidma_dma_info, inode->i_private);
+}
+
+static const struct file_operations hidma_chan_fops = {
+	.open = hidma_chan_stats_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static const struct file_operations hidma_dma_fops = {
+	.open = hidma_dma_info_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+void hidma_debug_uninit(struct hidma_dev *dmadev)
+{
+	debugfs_remove_recursive(dmadev->debugfs);
+	debugfs_remove_recursive(dmadev->stats);
+}
+
+int hidma_debug_init(struct hidma_dev *dmadev)
+{
+	int rc = 0;
+	int chidx = 0;
+	struct list_head *position = NULL;
+
+	dmadev->debugfs = debugfs_create_dir(dev_name(dmadev->ddev.dev), NULL);
+	if (!dmadev->debugfs) {
+		rc = -ENODEV;
+		return rc;
+	}
+
+	/* walk through the virtual channel list */
+	list_for_each(position, &dmadev->ddev.channels) {
+		struct hidma_chan *chan;
+
+		chan = list_entry(position, struct hidma_chan,
+				  chan.device_node);
+		sprintf(chan->dbg_name, "chan%d", chidx);
+		chan->debugfs = debugfs_create_dir(chan->dbg_name,
+						   dmadev->debugfs);
+		if (!chan->debugfs) {
+			rc = -ENOMEM;
+			goto cleanup;
+		}
+		chan->stats = debugfs_create_file("stats", S_IRUGO,
+						  chan->debugfs, chan,
+						  &hidma_chan_fops);
+		if (!chan->stats) {
+			rc = -ENOMEM;
+			goto cleanup;
+		}
+		chidx++;
+	}
+
+	dmadev->stats = debugfs_create_file("stats", S_IRUGO,
+					    dmadev->debugfs, dmadev,
+					    &hidma_dma_fops);
+	if (!dmadev->stats) {
+		rc = -ENOMEM;
+		goto cleanup;
+	}
+
+	return 0;
+cleanup:
+	hidma_debug_uninit(dmadev);
+	return rc;
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma/qcom/hidma.h linux-libre-4.7-gnu/drivers/dma/qcom/hidma.h
--- linux-libre-4.6-gnu/drivers/dma/qcom/hidma.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/dma/qcom/hidma.h	2016-07-24 15:23:50.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Qualcomm Technologies HIDMA data structures
  *
- * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -20,32 +20,29 @@
 #include <linux/interrupt.h>
 #include <linux/dmaengine.h>
 
-#define TRE_SIZE			32 /* each TRE is 32 bytes  */
-#define TRE_CFG_IDX			0
-#define TRE_LEN_IDX			1
-#define TRE_SRC_LOW_IDX		2
-#define TRE_SRC_HI_IDX			3
-#define TRE_DEST_LOW_IDX		4
-#define TRE_DEST_HI_IDX		5
-
-struct hidma_tx_status {
-	u8 err_info;			/* error record in this transfer    */
-	u8 err_code;			/* completion code		    */
-};
+#define HIDMA_TRE_SIZE			32 /* each TRE is 32 bytes  */
+#define HIDMA_TRE_CFG_IDX		0
+#define HIDMA_TRE_LEN_IDX		1
+#define HIDMA_TRE_SRC_LOW_IDX		2
+#define HIDMA_TRE_SRC_HI_IDX		3
+#define HIDMA_TRE_DEST_LOW_IDX		4
+#define HIDMA_TRE_DEST_HI_IDX		5
 
 struct hidma_tre {
 	atomic_t allocated;		/* if this channel is allocated	    */
 	bool queued;			/* flag whether this is pending     */
 	u16 status;			/* status			    */
-	u32 chidx;			/* index of the tre		    */
+	u32 idx;			/* index of the tre		    */
 	u32 dma_sig;			/* signature of the tre		    */
 	const char *dev_name;		/* name of the device		    */
 	void (*callback)(void *data);	/* requester callback		    */
 	void *data;			/* Data associated with this channel*/
 	struct hidma_lldev *lldev;	/* lldma device pointer		    */
-	u32 tre_local[TRE_SIZE / sizeof(u32) + 1]; /* TRE local copy        */
+	u32 tre_local[HIDMA_TRE_SIZE / sizeof(u32) + 1]; /* TRE local copy  */
 	u32 tre_index;			/* the offset where this was written*/
 	u32 int_flags;			/* interrupt flags		    */
+	u8 err_info;			/* error record in this transfer    */
+	u8 err_code;			/* completion code		    */
 };
 
 struct hidma_lldev {
@@ -61,22 +58,21 @@ struct hidma_lldev {
 	void __iomem *evca;		/* Event Channel address          */
 	struct hidma_tre
 		**pending_tre_list;	/* Pointers to pending TREs	  */
-	struct hidma_tx_status
-		*tx_status_list;	/* Pointers to pending TREs status*/
 	s32 pending_tre_count;		/* Number of TREs pending	  */
 
 	void *tre_ring;			/* TRE ring			  */
-	dma_addr_t tre_ring_handle;	/* TRE ring to be shared with HW  */
+	dma_addr_t tre_dma;		/* TRE ring to be shared with HW  */
 	u32 tre_ring_size;		/* Byte size of the ring	  */
 	u32 tre_processed_off;		/* last processed TRE		  */
 
 	void *evre_ring;		/* EVRE ring			   */
-	dma_addr_t evre_ring_handle;	/* EVRE ring to be shared with HW  */
+	dma_addr_t evre_dma;		/* EVRE ring to be shared with HW  */
 	u32 evre_ring_size;		/* Byte size of the ring	   */
 	u32 evre_processed_off;		/* last processed EVRE		   */
 
 	u32 tre_write_offset;           /* TRE write location              */
 	struct tasklet_struct task;	/* task delivering notifications   */
+	struct tasklet_struct rst_task;	/* task to reset HW                */
 	DECLARE_KFIFO_PTR(handoff_fifo,
 		struct hidma_tre *);    /* pending TREs FIFO               */
 };
@@ -145,8 +141,8 @@ enum dma_status hidma_ll_status(struct h
 bool hidma_ll_isenabled(struct hidma_lldev *llhndl);
 void hidma_ll_queue_request(struct hidma_lldev *llhndl, u32 tre_ch);
 void hidma_ll_start(struct hidma_lldev *llhndl);
-int hidma_ll_pause(struct hidma_lldev *llhndl);
-int hidma_ll_resume(struct hidma_lldev *llhndl);
+int hidma_ll_disable(struct hidma_lldev *lldev);
+int hidma_ll_enable(struct hidma_lldev *llhndl);
 void hidma_ll_set_transfer_params(struct hidma_lldev *llhndl, u32 tre_ch,
 	dma_addr_t src, dma_addr_t dest, u32 len, u32 flags);
 int hidma_ll_setup(struct hidma_lldev *lldev);
@@ -157,4 +153,6 @@ int hidma_ll_uninit(struct hidma_lldev *
 irqreturn_t hidma_ll_inthandler(int irq, void *arg);
 void hidma_cleanup_pending_tre(struct hidma_lldev *llhndl, u8 err_info,
 				u8 err_code);
+int hidma_debug_init(struct hidma_dev *dmadev);
+void hidma_debug_uninit(struct hidma_dev *dmadev);
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma/qcom/hidma_ll.c linux-libre-4.7-gnu/drivers/dma/qcom/hidma_ll.c
--- linux-libre-4.6-gnu/drivers/dma/qcom/hidma_ll.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/dma/qcom/hidma_ll.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,872 @@
+/*
+ * Qualcomm Technologies HIDMA DMA engine low level code
+ *
+ * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 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.
+ */
+
+#include <linux/dmaengine.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/atomic.h>
+#include <linux/iopoll.h>
+#include <linux/kfifo.h>
+#include <linux/bitops.h>
+
+#include "hidma.h"
+
+#define HIDMA_EVRE_SIZE			16	/* each EVRE is 16 bytes */
+
+#define HIDMA_TRCA_CTRLSTS_REG			0x000
+#define HIDMA_TRCA_RING_LOW_REG		0x008
+#define HIDMA_TRCA_RING_HIGH_REG		0x00C
+#define HIDMA_TRCA_RING_LEN_REG		0x010
+#define HIDMA_TRCA_DOORBELL_REG		0x400
+
+#define HIDMA_EVCA_CTRLSTS_REG			0x000
+#define HIDMA_EVCA_INTCTRL_REG			0x004
+#define HIDMA_EVCA_RING_LOW_REG		0x008
+#define HIDMA_EVCA_RING_HIGH_REG		0x00C
+#define HIDMA_EVCA_RING_LEN_REG		0x010
+#define HIDMA_EVCA_WRITE_PTR_REG		0x020
+#define HIDMA_EVCA_DOORBELL_REG		0x400
+
+#define HIDMA_EVCA_IRQ_STAT_REG		0x100
+#define HIDMA_EVCA_IRQ_CLR_REG			0x108
+#define HIDMA_EVCA_IRQ_EN_REG			0x110
+
+#define HIDMA_EVRE_CFG_IDX			0
+
+#define HIDMA_EVRE_ERRINFO_BIT_POS		24
+#define HIDMA_EVRE_CODE_BIT_POS		28
+
+#define HIDMA_EVRE_ERRINFO_MASK		GENMASK(3, 0)
+#define HIDMA_EVRE_CODE_MASK			GENMASK(3, 0)
+
+#define HIDMA_CH_CONTROL_MASK			GENMASK(7, 0)
+#define HIDMA_CH_STATE_MASK			GENMASK(7, 0)
+#define HIDMA_CH_STATE_BIT_POS			0x8
+
+#define HIDMA_IRQ_EV_CH_EOB_IRQ_BIT_POS	0
+#define HIDMA_IRQ_EV_CH_WR_RESP_BIT_POS	1
+#define HIDMA_IRQ_TR_CH_TRE_RD_RSP_ER_BIT_POS	9
+#define HIDMA_IRQ_TR_CH_DATA_RD_ER_BIT_POS	10
+#define HIDMA_IRQ_TR_CH_DATA_WR_ER_BIT_POS	11
+#define HIDMA_IRQ_TR_CH_INVALID_TRE_BIT_POS	14
+
+#define ENABLE_IRQS (BIT(HIDMA_IRQ_EV_CH_EOB_IRQ_BIT_POS)	| \
+		     BIT(HIDMA_IRQ_EV_CH_WR_RESP_BIT_POS)	| \
+		     BIT(HIDMA_IRQ_TR_CH_TRE_RD_RSP_ER_BIT_POS)	| \
+		     BIT(HIDMA_IRQ_TR_CH_DATA_RD_ER_BIT_POS)	| \
+		     BIT(HIDMA_IRQ_TR_CH_DATA_WR_ER_BIT_POS)	| \
+		     BIT(HIDMA_IRQ_TR_CH_INVALID_TRE_BIT_POS))
+
+#define HIDMA_INCREMENT_ITERATOR(iter, size, ring_size)	\
+do {								\
+	iter += size;						\
+	if (iter >= ring_size)					\
+		iter -= ring_size;				\
+} while (0)
+
+#define HIDMA_CH_STATE(val)	\
+	((val >> HIDMA_CH_STATE_BIT_POS) & HIDMA_CH_STATE_MASK)
+
+#define HIDMA_ERR_INT_MASK				\
+	(BIT(HIDMA_IRQ_TR_CH_INVALID_TRE_BIT_POS)   |	\
+	 BIT(HIDMA_IRQ_TR_CH_TRE_RD_RSP_ER_BIT_POS) |	\
+	 BIT(HIDMA_IRQ_EV_CH_WR_RESP_BIT_POS)	    |	\
+	 BIT(HIDMA_IRQ_TR_CH_DATA_RD_ER_BIT_POS)    |	\
+	 BIT(HIDMA_IRQ_TR_CH_DATA_WR_ER_BIT_POS))
+
+enum ch_command {
+	HIDMA_CH_DISABLE = 0,
+	HIDMA_CH_ENABLE = 1,
+	HIDMA_CH_SUSPEND = 2,
+	HIDMA_CH_RESET = 9,
+};
+
+enum ch_state {
+	HIDMA_CH_DISABLED = 0,
+	HIDMA_CH_ENABLED = 1,
+	HIDMA_CH_RUNNING = 2,
+	HIDMA_CH_SUSPENDED = 3,
+	HIDMA_CH_STOPPED = 4,
+};
+
+enum tre_type {
+	HIDMA_TRE_MEMCPY = 3,
+};
+
+enum err_code {
+	HIDMA_EVRE_STATUS_COMPLETE = 1,
+	HIDMA_EVRE_STATUS_ERROR = 4,
+};
+
+static int hidma_is_chan_enabled(int state)
+{
+	switch (state) {
+	case HIDMA_CH_ENABLED:
+	case HIDMA_CH_RUNNING:
+		return true;
+	default:
+		return false;
+	}
+}
+
+void hidma_ll_free(struct hidma_lldev *lldev, u32 tre_ch)
+{
+	struct hidma_tre *tre;
+
+	if (tre_ch >= lldev->nr_tres) {
+		dev_err(lldev->dev, "invalid TRE number in free:%d", tre_ch);
+		return;
+	}
+
+	tre = &lldev->trepool[tre_ch];
+	if (atomic_read(&tre->allocated) != true) {
+		dev_err(lldev->dev, "trying to free an unused TRE:%d", tre_ch);
+		return;
+	}
+
+	atomic_set(&tre->allocated, 0);
+}
+
+int hidma_ll_request(struct hidma_lldev *lldev, u32 sig, const char *dev_name,
+		     void (*callback)(void *data), void *data, u32 *tre_ch)
+{
+	unsigned int i;
+	struct hidma_tre *tre;
+	u32 *tre_local;
+
+	if (!tre_ch || !lldev)
+		return -EINVAL;
+
+	/* need to have at least one empty spot in the queue */
+	for (i = 0; i < lldev->nr_tres - 1; i++) {
+		if (atomic_add_unless(&lldev->trepool[i].allocated, 1, 1))
+			break;
+	}
+
+	if (i == (lldev->nr_tres - 1))
+		return -ENOMEM;
+
+	tre = &lldev->trepool[i];
+	tre->dma_sig = sig;
+	tre->dev_name = dev_name;
+	tre->callback = callback;
+	tre->data = data;
+	tre->idx = i;
+	tre->status = 0;
+	tre->queued = 0;
+	tre->err_code = 0;
+	tre->err_info = 0;
+	tre->lldev = lldev;
+	tre_local = &tre->tre_local[0];
+	tre_local[HIDMA_TRE_CFG_IDX] = HIDMA_TRE_MEMCPY;
+	tre_local[HIDMA_TRE_CFG_IDX] |= (lldev->chidx & 0xFF) << 8;
+	tre_local[HIDMA_TRE_CFG_IDX] |= BIT(16);	/* set IEOB */
+	*tre_ch = i;
+	if (callback)
+		callback(data);
+	return 0;
+}
+
+/*
+ * Multiple TREs may be queued and waiting in the pending queue.
+ */
+static void hidma_ll_tre_complete(unsigned long arg)
+{
+	struct hidma_lldev *lldev = (struct hidma_lldev *)arg;
+	struct hidma_tre *tre;
+
+	while (kfifo_out(&lldev->handoff_fifo, &tre, 1)) {
+		/* call the user if it has been read by the hardware */
+		if (tre->callback)
+			tre->callback(tre->data);
+	}
+}
+
+static int hidma_post_completed(struct hidma_lldev *lldev, int tre_iterator,
+				u8 err_info, u8 err_code)
+{
+	struct hidma_tre *tre;
+	unsigned long flags;
+
+	spin_lock_irqsave(&lldev->lock, flags);
+	tre = lldev->pending_tre_list[tre_iterator / HIDMA_TRE_SIZE];
+	if (!tre) {
+		spin_unlock_irqrestore(&lldev->lock, flags);
+		dev_warn(lldev->dev, "tre_index [%d] and tre out of sync\n",
+			 tre_iterator / HIDMA_TRE_SIZE);
+		return -EINVAL;
+	}
+	lldev->pending_tre_list[tre->tre_index] = NULL;
+
+	/*
+	 * Keep track of pending TREs that SW is expecting to receive
+	 * from HW. We got one now. Decrement our counter.
+	 */
+	lldev->pending_tre_count--;
+	if (lldev->pending_tre_count < 0) {
+		dev_warn(lldev->dev, "tre count mismatch on completion");
+		lldev->pending_tre_count = 0;
+	}
+
+	spin_unlock_irqrestore(&lldev->lock, flags);
+
+	tre->err_info = err_info;
+	tre->err_code = err_code;
+	tre->queued = 0;
+
+	kfifo_put(&lldev->handoff_fifo, tre);
+	tasklet_schedule(&lldev->task);
+
+	return 0;
+}
+
+/*
+ * Called to handle the interrupt for the channel.
+ * Return a positive number if TRE or EVRE were consumed on this run.
+ * Return a positive number if there are pending TREs or EVREs.
+ * Return 0 if there is nothing to consume or no pending TREs/EVREs found.
+ */
+static int hidma_handle_tre_completion(struct hidma_lldev *lldev)
+{
+	u32 evre_ring_size = lldev->evre_ring_size;
+	u32 tre_ring_size = lldev->tre_ring_size;
+	u32 err_info, err_code, evre_write_off;
+	u32 tre_iterator, evre_iterator;
+	u32 num_completed = 0;
+
+	evre_write_off = readl_relaxed(lldev->evca + HIDMA_EVCA_WRITE_PTR_REG);
+	tre_iterator = lldev->tre_processed_off;
+	evre_iterator = lldev->evre_processed_off;
+
+	if ((evre_write_off > evre_ring_size) ||
+	    (evre_write_off % HIDMA_EVRE_SIZE)) {
+		dev_err(lldev->dev, "HW reports invalid EVRE write offset\n");
+		return 0;
+	}
+
+	/*
+	 * By the time control reaches here the number of EVREs and TREs
+	 * may not match. Only consume the ones that hardware told us.
+	 */
+	while ((evre_iterator != evre_write_off)) {
+		u32 *current_evre = lldev->evre_ring + evre_iterator;
+		u32 cfg;
+
+		cfg = current_evre[HIDMA_EVRE_CFG_IDX];
+		err_info = cfg >> HIDMA_EVRE_ERRINFO_BIT_POS;
+		err_info &= HIDMA_EVRE_ERRINFO_MASK;
+		err_code =
+		    (cfg >> HIDMA_EVRE_CODE_BIT_POS) & HIDMA_EVRE_CODE_MASK;
+
+		if (hidma_post_completed(lldev, tre_iterator, err_info,
+					 err_code))
+			break;
+
+		HIDMA_INCREMENT_ITERATOR(tre_iterator, HIDMA_TRE_SIZE,
+					 tre_ring_size);
+		HIDMA_INCREMENT_ITERATOR(evre_iterator, HIDMA_EVRE_SIZE,
+					 evre_ring_size);
+
+		/*
+		 * Read the new event descriptor written by the HW.
+		 * As we are processing the delivered events, other events
+		 * get queued to the SW for processing.
+		 */
+		evre_write_off =
+		    readl_relaxed(lldev->evca + HIDMA_EVCA_WRITE_PTR_REG);
+		num_completed++;
+	}
+
+	if (num_completed) {
+		u32 evre_read_off = (lldev->evre_processed_off +
+				     HIDMA_EVRE_SIZE * num_completed);
+		u32 tre_read_off = (lldev->tre_processed_off +
+				    HIDMA_TRE_SIZE * num_completed);
+
+		evre_read_off = evre_read_off % evre_ring_size;
+		tre_read_off = tre_read_off % tre_ring_size;
+
+		writel(evre_read_off, lldev->evca + HIDMA_EVCA_DOORBELL_REG);
+
+		/* record the last processed tre offset */
+		lldev->tre_processed_off = tre_read_off;
+		lldev->evre_processed_off = evre_read_off;
+	}
+
+	return num_completed;
+}
+
+void hidma_cleanup_pending_tre(struct hidma_lldev *lldev, u8 err_info,
+			       u8 err_code)
+{
+	u32 tre_iterator;
+	u32 tre_ring_size = lldev->tre_ring_size;
+	int num_completed = 0;
+	u32 tre_read_off;
+
+	tre_iterator = lldev->tre_processed_off;
+	while (lldev->pending_tre_count) {
+		if (hidma_post_completed(lldev, tre_iterator, err_info,
+					 err_code))
+			break;
+		HIDMA_INCREMENT_ITERATOR(tre_iterator, HIDMA_TRE_SIZE,
+					 tre_ring_size);
+		num_completed++;
+	}
+	tre_read_off = (lldev->tre_processed_off +
+			HIDMA_TRE_SIZE * num_completed);
+
+	tre_read_off = tre_read_off % tre_ring_size;
+
+	/* record the last processed tre offset */
+	lldev->tre_processed_off = tre_read_off;
+}
+
+static int hidma_ll_reset(struct hidma_lldev *lldev)
+{
+	u32 val;
+	int ret;
+
+	val = readl(lldev->trca + HIDMA_TRCA_CTRLSTS_REG);
+	val &= ~(HIDMA_CH_CONTROL_MASK << 16);
+	val |= HIDMA_CH_RESET << 16;
+	writel(val, lldev->trca + HIDMA_TRCA_CTRLSTS_REG);
+
+	/*
+	 * Delay 10ms after reset to allow DMA logic to quiesce.
+	 * Do a polled read up to 1ms and 10ms maximum.
+	 */
+	ret = readl_poll_timeout(lldev->trca + HIDMA_TRCA_CTRLSTS_REG, val,
+				 HIDMA_CH_STATE(val) == HIDMA_CH_DISABLED,
+				 1000, 10000);
+	if (ret) {
+		dev_err(lldev->dev, "transfer channel did not reset\n");
+		return ret;
+	}
+
+	val = readl(lldev->evca + HIDMA_EVCA_CTRLSTS_REG);
+	val &= ~(HIDMA_CH_CONTROL_MASK << 16);
+	val |= HIDMA_CH_RESET << 16;
+	writel(val, lldev->evca + HIDMA_EVCA_CTRLSTS_REG);
+
+	/*
+	 * Delay 10ms after reset to allow DMA logic to quiesce.
+	 * Do a polled read up to 1ms and 10ms maximum.
+	 */
+	ret = readl_poll_timeout(lldev->evca + HIDMA_EVCA_CTRLSTS_REG, val,
+				 HIDMA_CH_STATE(val) == HIDMA_CH_DISABLED,
+				 1000, 10000);
+	if (ret)
+		return ret;
+
+	lldev->trch_state = HIDMA_CH_DISABLED;
+	lldev->evch_state = HIDMA_CH_DISABLED;
+	return 0;
+}
+
+/*
+ * Abort all transactions and perform a reset.
+ */
+static void hidma_ll_abort(unsigned long arg)
+{
+	struct hidma_lldev *lldev = (struct hidma_lldev *)arg;
+	u8 err_code = HIDMA_EVRE_STATUS_ERROR;
+	u8 err_info = 0xFF;
+	int rc;
+
+	hidma_cleanup_pending_tre(lldev, err_info, err_code);
+
+	/* reset the channel for recovery */
+	rc = hidma_ll_setup(lldev);
+	if (rc) {
+		dev_err(lldev->dev, "channel reinitialize failed after error\n");
+		return;
+	}
+	writel(ENABLE_IRQS, lldev->evca + HIDMA_EVCA_IRQ_EN_REG);
+}
+
+/*
+ * The interrupt handler for HIDMA will try to consume as many pending
+ * EVRE from the event queue as possible. Each EVRE has an associated
+ * TRE that holds the user interface parameters. EVRE reports the
+ * result of the transaction. Hardware guarantees ordering between EVREs
+ * and TREs. We use last processed offset to figure out which TRE is
+ * associated with which EVRE. If two TREs are consumed by HW, the EVREs
+ * are in order in the event ring.
+ *
+ * This handler will do a one pass for consuming EVREs. Other EVREs may
+ * be delivered while we are working. It will try to consume incoming
+ * EVREs one more time and return.
+ *
+ * For unprocessed EVREs, hardware will trigger another interrupt until
+ * all the interrupt bits are cleared.
+ *
+ * Hardware guarantees that by the time interrupt is observed, all data
+ * transactions in flight are delivered to their respective places and
+ * are visible to the CPU.
+ *
+ * On demand paging for IOMMU is only supported for PCIe via PRI
+ * (Page Request Interface) not for HIDMA. All other hardware instances
+ * including HIDMA work on pinned DMA addresses.
+ *
+ * HIDMA is not aware of IOMMU presence since it follows the DMA API. All
+ * IOMMU latency will be built into the data movement time. By the time
+ * interrupt happens, IOMMU lookups + data movement has already taken place.
+ *
+ * While the first read in a typical PCI endpoint ISR flushes all outstanding
+ * requests traditionally to the destination, this concept does not apply
+ * here for this HW.
+ */
+irqreturn_t hidma_ll_inthandler(int chirq, void *arg)
+{
+	struct hidma_lldev *lldev = arg;
+	u32 status;
+	u32 enable;
+	u32 cause;
+
+	/*
+	 * Fine tuned for this HW...
+	 *
+	 * This ISR has been designed for this particular hardware. Relaxed
+	 * read and write accessors are used for performance reasons due to
+	 * interrupt delivery guarantees. Do not copy this code blindly and
+	 * expect that to work.
+	 */
+	status = readl_relaxed(lldev->evca + HIDMA_EVCA_IRQ_STAT_REG);
+	enable = readl_relaxed(lldev->evca + HIDMA_EVCA_IRQ_EN_REG);
+	cause = status & enable;
+
+	while (cause) {
+		if (cause & HIDMA_ERR_INT_MASK) {
+			dev_err(lldev->dev, "error 0x%x, resetting...\n",
+					cause);
+
+			/* Clear out pending interrupts */
+			writel(cause, lldev->evca + HIDMA_EVCA_IRQ_CLR_REG);
+
+			tasklet_schedule(&lldev->rst_task);
+			goto out;
+		}
+
+		/*
+		 * Try to consume as many EVREs as possible.
+		 */
+		hidma_handle_tre_completion(lldev);
+
+		/* We consumed TREs or there are pending TREs or EVREs. */
+		writel_relaxed(cause, lldev->evca + HIDMA_EVCA_IRQ_CLR_REG);
+
+		/*
+		 * Another interrupt might have arrived while we are
+		 * processing this one. Read the new cause.
+		 */
+		status = readl_relaxed(lldev->evca + HIDMA_EVCA_IRQ_STAT_REG);
+		enable = readl_relaxed(lldev->evca + HIDMA_EVCA_IRQ_EN_REG);
+		cause = status & enable;
+	}
+
+out:
+	return IRQ_HANDLED;
+}
+
+int hidma_ll_enable(struct hidma_lldev *lldev)
+{
+	u32 val;
+	int ret;
+
+	val = readl(lldev->evca + HIDMA_EVCA_CTRLSTS_REG);
+	val &= ~(HIDMA_CH_CONTROL_MASK << 16);
+	val |= HIDMA_CH_ENABLE << 16;
+	writel(val, lldev->evca + HIDMA_EVCA_CTRLSTS_REG);
+
+	ret = readl_poll_timeout(lldev->evca + HIDMA_EVCA_CTRLSTS_REG, val,
+				 hidma_is_chan_enabled(HIDMA_CH_STATE(val)),
+				 1000, 10000);
+	if (ret) {
+		dev_err(lldev->dev, "event channel did not get enabled\n");
+		return ret;
+	}
+
+	val = readl(lldev->trca + HIDMA_TRCA_CTRLSTS_REG);
+	val &= ~(HIDMA_CH_CONTROL_MASK << 16);
+	val |= HIDMA_CH_ENABLE << 16;
+	writel(val, lldev->trca + HIDMA_TRCA_CTRLSTS_REG);
+
+	ret = readl_poll_timeout(lldev->trca + HIDMA_TRCA_CTRLSTS_REG, val,
+				 hidma_is_chan_enabled(HIDMA_CH_STATE(val)),
+				 1000, 10000);
+	if (ret) {
+		dev_err(lldev->dev, "transfer channel did not get enabled\n");
+		return ret;
+	}
+
+	lldev->trch_state = HIDMA_CH_ENABLED;
+	lldev->evch_state = HIDMA_CH_ENABLED;
+
+	return 0;
+}
+
+void hidma_ll_start(struct hidma_lldev *lldev)
+{
+	unsigned long irqflags;
+
+	spin_lock_irqsave(&lldev->lock, irqflags);
+	writel(lldev->tre_write_offset, lldev->trca + HIDMA_TRCA_DOORBELL_REG);
+	spin_unlock_irqrestore(&lldev->lock, irqflags);
+}
+
+bool hidma_ll_isenabled(struct hidma_lldev *lldev)
+{
+	u32 val;
+
+	val = readl(lldev->trca + HIDMA_TRCA_CTRLSTS_REG);
+	lldev->trch_state = HIDMA_CH_STATE(val);
+	val = readl(lldev->evca + HIDMA_EVCA_CTRLSTS_REG);
+	lldev->evch_state = HIDMA_CH_STATE(val);
+
+	/* both channels have to be enabled before calling this function */
+	if (hidma_is_chan_enabled(lldev->trch_state) &&
+	    hidma_is_chan_enabled(lldev->evch_state))
+		return true;
+
+	return false;
+}
+
+void hidma_ll_queue_request(struct hidma_lldev *lldev, u32 tre_ch)
+{
+	struct hidma_tre *tre;
+	unsigned long flags;
+
+	tre = &lldev->trepool[tre_ch];
+
+	/* copy the TRE into its location in the TRE ring */
+	spin_lock_irqsave(&lldev->lock, flags);
+	tre->tre_index = lldev->tre_write_offset / HIDMA_TRE_SIZE;
+	lldev->pending_tre_list[tre->tre_index] = tre;
+	memcpy(lldev->tre_ring + lldev->tre_write_offset,
+			&tre->tre_local[0], HIDMA_TRE_SIZE);
+	tre->err_code = 0;
+	tre->err_info = 0;
+	tre->queued = 1;
+	lldev->pending_tre_count++;
+	lldev->tre_write_offset = (lldev->tre_write_offset + HIDMA_TRE_SIZE)
+					% lldev->tre_ring_size;
+	spin_unlock_irqrestore(&lldev->lock, flags);
+}
+
+/*
+ * Note that even though we stop this channel if there is a pending transaction
+ * in flight it will complete and follow the callback. This request will
+ * prevent further requests to be made.
+ */
+int hidma_ll_disable(struct hidma_lldev *lldev)
+{
+	u32 val;
+	int ret;
+
+	val = readl(lldev->evca + HIDMA_EVCA_CTRLSTS_REG);
+	lldev->evch_state = HIDMA_CH_STATE(val);
+	val = readl(lldev->trca + HIDMA_TRCA_CTRLSTS_REG);
+	lldev->trch_state = HIDMA_CH_STATE(val);
+
+	/* already suspended by this OS */
+	if ((lldev->trch_state == HIDMA_CH_SUSPENDED) ||
+	    (lldev->evch_state == HIDMA_CH_SUSPENDED))
+		return 0;
+
+	/* already stopped by the manager */
+	if ((lldev->trch_state == HIDMA_CH_STOPPED) ||
+	    (lldev->evch_state == HIDMA_CH_STOPPED))
+		return 0;
+
+	val = readl(lldev->trca + HIDMA_TRCA_CTRLSTS_REG);
+	val &= ~(HIDMA_CH_CONTROL_MASK << 16);
+	val |= HIDMA_CH_SUSPEND << 16;
+	writel(val, lldev->trca + HIDMA_TRCA_CTRLSTS_REG);
+
+	/*
+	 * Start the wait right after the suspend is confirmed.
+	 * Do a polled read up to 1ms and 10ms maximum.
+	 */
+	ret = readl_poll_timeout(lldev->trca + HIDMA_TRCA_CTRLSTS_REG, val,
+				 HIDMA_CH_STATE(val) == HIDMA_CH_SUSPENDED,
+				 1000, 10000);
+	if (ret)
+		return ret;
+
+	val = readl(lldev->evca + HIDMA_EVCA_CTRLSTS_REG);
+	val &= ~(HIDMA_CH_CONTROL_MASK << 16);
+	val |= HIDMA_CH_SUSPEND << 16;
+	writel(val, lldev->evca + HIDMA_EVCA_CTRLSTS_REG);
+
+	/*
+	 * Start the wait right after the suspend is confirmed
+	 * Delay up to 10ms after reset to allow DMA logic to quiesce.
+	 */
+	ret = readl_poll_timeout(lldev->evca + HIDMA_EVCA_CTRLSTS_REG, val,
+				 HIDMA_CH_STATE(val) == HIDMA_CH_SUSPENDED,
+				 1000, 10000);
+	if (ret)
+		return ret;
+
+	lldev->trch_state = HIDMA_CH_SUSPENDED;
+	lldev->evch_state = HIDMA_CH_SUSPENDED;
+	return 0;
+}
+
+void hidma_ll_set_transfer_params(struct hidma_lldev *lldev, u32 tre_ch,
+				  dma_addr_t src, dma_addr_t dest, u32 len,
+				  u32 flags)
+{
+	struct hidma_tre *tre;
+	u32 *tre_local;
+
+	if (tre_ch >= lldev->nr_tres) {
+		dev_err(lldev->dev, "invalid TRE number in transfer params:%d",
+			tre_ch);
+		return;
+	}
+
+	tre = &lldev->trepool[tre_ch];
+	if (atomic_read(&tre->allocated) != true) {
+		dev_err(lldev->dev, "trying to set params on an unused TRE:%d",
+			tre_ch);
+		return;
+	}
+
+	tre_local = &tre->tre_local[0];
+	tre_local[HIDMA_TRE_LEN_IDX] = len;
+	tre_local[HIDMA_TRE_SRC_LOW_IDX] = lower_32_bits(src);
+	tre_local[HIDMA_TRE_SRC_HI_IDX] = upper_32_bits(src);
+	tre_local[HIDMA_TRE_DEST_LOW_IDX] = lower_32_bits(dest);
+	tre_local[HIDMA_TRE_DEST_HI_IDX] = upper_32_bits(dest);
+	tre->int_flags = flags;
+}
+
+/*
+ * Called during initialization and after an error condition
+ * to restore hardware state.
+ */
+int hidma_ll_setup(struct hidma_lldev *lldev)
+{
+	int rc;
+	u64 addr;
+	u32 val;
+	u32 nr_tres = lldev->nr_tres;
+
+	lldev->pending_tre_count = 0;
+	lldev->tre_processed_off = 0;
+	lldev->evre_processed_off = 0;
+	lldev->tre_write_offset = 0;
+
+	/* disable interrupts */
+	writel(0, lldev->evca + HIDMA_EVCA_IRQ_EN_REG);
+
+	/* clear all pending interrupts */
+	val = readl(lldev->evca + HIDMA_EVCA_IRQ_STAT_REG);
+	writel(val, lldev->evca + HIDMA_EVCA_IRQ_CLR_REG);
+
+	rc = hidma_ll_reset(lldev);
+	if (rc)
+		return rc;
+
+	/*
+	 * Clear all pending interrupts again.
+	 * Otherwise, we observe reset complete interrupts.
+	 */
+	val = readl(lldev->evca + HIDMA_EVCA_IRQ_STAT_REG);
+	writel(val, lldev->evca + HIDMA_EVCA_IRQ_CLR_REG);
+
+	/* disable interrupts again after reset */
+	writel(0, lldev->evca + HIDMA_EVCA_IRQ_EN_REG);
+
+	addr = lldev->tre_dma;
+	writel(lower_32_bits(addr), lldev->trca + HIDMA_TRCA_RING_LOW_REG);
+	writel(upper_32_bits(addr), lldev->trca + HIDMA_TRCA_RING_HIGH_REG);
+	writel(lldev->tre_ring_size, lldev->trca + HIDMA_TRCA_RING_LEN_REG);
+
+	addr = lldev->evre_dma;
+	writel(lower_32_bits(addr), lldev->evca + HIDMA_EVCA_RING_LOW_REG);
+	writel(upper_32_bits(addr), lldev->evca + HIDMA_EVCA_RING_HIGH_REG);
+	writel(HIDMA_EVRE_SIZE * nr_tres,
+			lldev->evca + HIDMA_EVCA_RING_LEN_REG);
+
+	/* support IRQ only for now */
+	val = readl(lldev->evca + HIDMA_EVCA_INTCTRL_REG);
+	val &= ~0xF;
+	val |= 0x1;
+	writel(val, lldev->evca + HIDMA_EVCA_INTCTRL_REG);
+
+	/* clear all pending interrupts and enable them */
+	writel(ENABLE_IRQS, lldev->evca + HIDMA_EVCA_IRQ_CLR_REG);
+	writel(ENABLE_IRQS, lldev->evca + HIDMA_EVCA_IRQ_EN_REG);
+
+	return hidma_ll_enable(lldev);
+}
+
+struct hidma_lldev *hidma_ll_init(struct device *dev, u32 nr_tres,
+				  void __iomem *trca, void __iomem *evca,
+				  u8 chidx)
+{
+	u32 required_bytes;
+	struct hidma_lldev *lldev;
+	int rc;
+	size_t sz;
+
+	if (!trca || !evca || !dev || !nr_tres)
+		return NULL;
+
+	/* need at least four TREs */
+	if (nr_tres < 4)
+		return NULL;
+
+	/* need an extra space */
+	nr_tres += 1;
+
+	lldev = devm_kzalloc(dev, sizeof(struct hidma_lldev), GFP_KERNEL);
+	if (!lldev)
+		return NULL;
+
+	lldev->evca = evca;
+	lldev->trca = trca;
+	lldev->dev = dev;
+	sz = sizeof(struct hidma_tre);
+	lldev->trepool = devm_kcalloc(lldev->dev, nr_tres, sz, GFP_KERNEL);
+	if (!lldev->trepool)
+		return NULL;
+
+	required_bytes = sizeof(lldev->pending_tre_list[0]);
+	lldev->pending_tre_list = devm_kcalloc(dev, nr_tres, required_bytes,
+					       GFP_KERNEL);
+	if (!lldev->pending_tre_list)
+		return NULL;
+
+	sz = (HIDMA_TRE_SIZE + 1) * nr_tres;
+	lldev->tre_ring = dmam_alloc_coherent(dev, sz, &lldev->tre_dma,
+					      GFP_KERNEL);
+	if (!lldev->tre_ring)
+		return NULL;
+
+	memset(lldev->tre_ring, 0, (HIDMA_TRE_SIZE + 1) * nr_tres);
+	lldev->tre_ring_size = HIDMA_TRE_SIZE * nr_tres;
+	lldev->nr_tres = nr_tres;
+
+	/* the TRE ring has to be TRE_SIZE aligned */
+	if (!IS_ALIGNED(lldev->tre_dma, HIDMA_TRE_SIZE)) {
+		u8 tre_ring_shift;
+
+		tre_ring_shift = lldev->tre_dma % HIDMA_TRE_SIZE;
+		tre_ring_shift = HIDMA_TRE_SIZE - tre_ring_shift;
+		lldev->tre_dma += tre_ring_shift;
+		lldev->tre_ring += tre_ring_shift;
+	}
+
+	sz = (HIDMA_EVRE_SIZE + 1) * nr_tres;
+	lldev->evre_ring = dmam_alloc_coherent(dev, sz, &lldev->evre_dma,
+					       GFP_KERNEL);
+	if (!lldev->evre_ring)
+		return NULL;
+
+	memset(lldev->evre_ring, 0, (HIDMA_EVRE_SIZE + 1) * nr_tres);
+	lldev->evre_ring_size = HIDMA_EVRE_SIZE * nr_tres;
+
+	/* the EVRE ring has to be EVRE_SIZE aligned */
+	if (!IS_ALIGNED(lldev->evre_dma, HIDMA_EVRE_SIZE)) {
+		u8 evre_ring_shift;
+
+		evre_ring_shift = lldev->evre_dma % HIDMA_EVRE_SIZE;
+		evre_ring_shift = HIDMA_EVRE_SIZE - evre_ring_shift;
+		lldev->evre_dma += evre_ring_shift;
+		lldev->evre_ring += evre_ring_shift;
+	}
+	lldev->nr_tres = nr_tres;
+	lldev->chidx = chidx;
+
+	sz = nr_tres * sizeof(struct hidma_tre *);
+	rc = kfifo_alloc(&lldev->handoff_fifo, sz, GFP_KERNEL);
+	if (rc)
+		return NULL;
+
+	rc = hidma_ll_setup(lldev);
+	if (rc)
+		return NULL;
+
+	spin_lock_init(&lldev->lock);
+	tasklet_init(&lldev->rst_task, hidma_ll_abort, (unsigned long)lldev);
+	tasklet_init(&lldev->task, hidma_ll_tre_complete, (unsigned long)lldev);
+	lldev->initialized = 1;
+	writel(ENABLE_IRQS, lldev->evca + HIDMA_EVCA_IRQ_EN_REG);
+	return lldev;
+}
+
+int hidma_ll_uninit(struct hidma_lldev *lldev)
+{
+	u32 required_bytes;
+	int rc = 0;
+	u32 val;
+
+	if (!lldev)
+		return -ENODEV;
+
+	if (!lldev->initialized)
+		return 0;
+
+	lldev->initialized = 0;
+
+	required_bytes = sizeof(struct hidma_tre) * lldev->nr_tres;
+	tasklet_kill(&lldev->task);
+	memset(lldev->trepool, 0, required_bytes);
+	lldev->trepool = NULL;
+	lldev->pending_tre_count = 0;
+	lldev->tre_write_offset = 0;
+
+	rc = hidma_ll_reset(lldev);
+
+	/*
+	 * Clear all pending interrupts again.
+	 * Otherwise, we observe reset complete interrupts.
+	 */
+	val = readl(lldev->evca + HIDMA_EVCA_IRQ_STAT_REG);
+	writel(val, lldev->evca + HIDMA_EVCA_IRQ_CLR_REG);
+	writel(0, lldev->evca + HIDMA_EVCA_IRQ_EN_REG);
+	return rc;
+}
+
+enum dma_status hidma_ll_status(struct hidma_lldev *lldev, u32 tre_ch)
+{
+	enum dma_status ret = DMA_ERROR;
+	struct hidma_tre *tre;
+	unsigned long flags;
+	u8 err_code;
+
+	spin_lock_irqsave(&lldev->lock, flags);
+
+	tre = &lldev->trepool[tre_ch];
+	err_code = tre->err_code;
+
+	if (err_code & HIDMA_EVRE_STATUS_COMPLETE)
+		ret = DMA_COMPLETE;
+	else if (err_code & HIDMA_EVRE_STATUS_ERROR)
+		ret = DMA_ERROR;
+	else
+		ret = DMA_IN_PROGRESS;
+	spin_unlock_irqrestore(&lldev->lock, flags);
+
+	return ret;
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma/qcom/hidma_mgmt.c linux-libre-4.7-gnu/drivers/dma/qcom/hidma_mgmt.c
--- linux-libre-4.6-gnu/drivers/dma/qcom/hidma_mgmt.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/dma/qcom/hidma_mgmt.c	2016-07-24 15:23:50.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Qualcomm Technologies HIDMA DMA engine Management interface
  *
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -17,13 +17,14 @@
 #include <linux/acpi.h>
 #include <linux/of.h>
 #include <linux/property.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
 #include <linux/module.h>
 #include <linux/uaccess.h>
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
 #include <linux/bitops.h>
+#include <linux/dma-mapping.h>
 
 #include "hidma_mgmt.h"
 
@@ -298,5 +299,109 @@ static struct platform_driver hidma_mgmt
 	},
 };
 
-module_platform_driver(hidma_mgmt_driver);
+#if defined(CONFIG_OF) && defined(CONFIG_OF_IRQ)
+static int object_counter;
+
+static int __init hidma_mgmt_of_populate_channels(struct device_node *np)
+{
+	struct platform_device *pdev_parent = of_find_device_by_node(np);
+	struct platform_device_info pdevinfo;
+	struct of_phandle_args out_irq;
+	struct device_node *child;
+	struct resource *res;
+	const __be32 *cell;
+	int ret = 0, size, i, num;
+	u64 addr, addr_size;
+
+	for_each_available_child_of_node(np, child) {
+		struct resource *res_iter;
+		struct platform_device *new_pdev;
+
+		cell = of_get_property(child, "reg", &size);
+		if (!cell) {
+			ret = -EINVAL;
+			goto out;
+		}
+
+		size /= sizeof(*cell);
+		num = size /
+			(of_n_addr_cells(child) + of_n_size_cells(child)) + 1;
+
+		/* allocate a resource array */
+		res = kcalloc(num, sizeof(*res), GFP_KERNEL);
+		if (!res) {
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		/* read each reg value */
+		i = 0;
+		res_iter = res;
+		while (i < size) {
+			addr = of_read_number(&cell[i],
+					      of_n_addr_cells(child));
+			i += of_n_addr_cells(child);
+
+			addr_size = of_read_number(&cell[i],
+						   of_n_size_cells(child));
+			i += of_n_size_cells(child);
+
+			res_iter->start = addr;
+			res_iter->end = res_iter->start + addr_size - 1;
+			res_iter->flags = IORESOURCE_MEM;
+			res_iter++;
+		}
+
+		ret = of_irq_parse_one(child, 0, &out_irq);
+		if (ret)
+			goto out;
+
+		res_iter->start = irq_create_of_mapping(&out_irq);
+		res_iter->name = "hidma event irq";
+		res_iter->flags = IORESOURCE_IRQ;
+
+		memset(&pdevinfo, 0, sizeof(pdevinfo));
+		pdevinfo.fwnode = &child->fwnode;
+		pdevinfo.parent = pdev_parent ? &pdev_parent->dev : NULL;
+		pdevinfo.name = child->name;
+		pdevinfo.id = object_counter++;
+		pdevinfo.res = res;
+		pdevinfo.num_res = num;
+		pdevinfo.data = NULL;
+		pdevinfo.size_data = 0;
+		pdevinfo.dma_mask = DMA_BIT_MASK(64);
+		new_pdev = platform_device_register_full(&pdevinfo);
+		if (!new_pdev) {
+			ret = -ENODEV;
+			goto out;
+		}
+		of_dma_configure(&new_pdev->dev, child);
+
+		kfree(res);
+		res = NULL;
+	}
+out:
+	kfree(res);
+
+	return ret;
+}
+#endif
+
+static int __init hidma_mgmt_init(void)
+{
+#if defined(CONFIG_OF) && defined(CONFIG_OF_IRQ)
+	struct device_node *child;
+
+	for (child = of_find_matching_node(NULL, hidma_mgmt_match); child;
+	     child = of_find_matching_node(child, hidma_mgmt_match)) {
+		/* device tree based firmware here */
+		hidma_mgmt_of_populate_channels(child);
+		of_node_put(child);
+	}
+#endif
+	platform_driver_register(&hidma_mgmt_driver);
+
+	return 0;
+}
+module_init(hidma_mgmt_init);
 MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma/qcom/Makefile linux-libre-4.7-gnu/drivers/dma/qcom/Makefile
--- linux-libre-4.6-gnu/drivers/dma/qcom/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/dma/qcom/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -1,3 +1,5 @@
 obj-$(CONFIG_QCOM_BAM_DMA) += bam_dma.o
 obj-$(CONFIG_QCOM_HIDMA_MGMT) += hdma_mgmt.o
 hdma_mgmt-objs	 := hidma_mgmt.o hidma_mgmt_sys.o
+obj-$(CONFIG_QCOM_HIDMA) +=  hdma.o
+hdma-objs        := hidma_ll.o hidma.o hidma_dbg.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma/sun4i-dma.c linux-libre-4.7-gnu/drivers/dma/sun4i-dma.c
--- linux-libre-4.6-gnu/drivers/dma/sun4i-dma.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/dma/sun4i-dma.c	2016-07-24 15:23:50.000000000 -0400
@@ -461,25 +461,25 @@ generate_ndma_promise(struct dma_chan *c
 
 	/* Source burst */
 	ret = convert_burst(sconfig->src_maxburst);
-	if (IS_ERR_VALUE(ret))
+	if (ret < 0)
 		goto fail;
 	promise->cfg |= SUN4I_DMA_CFG_SRC_BURST_LENGTH(ret);
 
 	/* Destination burst */
 	ret = convert_burst(sconfig->dst_maxburst);
-	if (IS_ERR_VALUE(ret))
+	if (ret < 0)
 		goto fail;
 	promise->cfg |= SUN4I_DMA_CFG_DST_BURST_LENGTH(ret);
 
 	/* Source bus width */
 	ret = convert_buswidth(sconfig->src_addr_width);
-	if (IS_ERR_VALUE(ret))
+	if (ret < 0)
 		goto fail;
 	promise->cfg |= SUN4I_DMA_CFG_SRC_DATA_WIDTH(ret);
 
 	/* Destination bus width */
 	ret = convert_buswidth(sconfig->dst_addr_width);
-	if (IS_ERR_VALUE(ret))
+	if (ret < 0)
 		goto fail;
 	promise->cfg |= SUN4I_DMA_CFG_DST_DATA_WIDTH(ret);
 
@@ -518,25 +518,25 @@ generate_ddma_promise(struct dma_chan *c
 
 	/* Source burst */
 	ret = convert_burst(sconfig->src_maxburst);
-	if (IS_ERR_VALUE(ret))
+	if (ret < 0)
 		goto fail;
 	promise->cfg |= SUN4I_DMA_CFG_SRC_BURST_LENGTH(ret);
 
 	/* Destination burst */
 	ret = convert_burst(sconfig->dst_maxburst);
-	if (IS_ERR_VALUE(ret))
+	if (ret < 0)
 		goto fail;
 	promise->cfg |= SUN4I_DMA_CFG_DST_BURST_LENGTH(ret);
 
 	/* Source bus width */
 	ret = convert_buswidth(sconfig->src_addr_width);
-	if (IS_ERR_VALUE(ret))
+	if (ret < 0)
 		goto fail;
 	promise->cfg |= SUN4I_DMA_CFG_SRC_DATA_WIDTH(ret);
 
 	/* Destination bus width */
 	ret = convert_buswidth(sconfig->dst_addr_width);
-	if (IS_ERR_VALUE(ret))
+	if (ret < 0)
 		goto fail;
 	promise->cfg |= SUN4I_DMA_CFG_DST_DATA_WIDTH(ret);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma/sun6i-dma.c linux-libre-4.7-gnu/drivers/dma/sun6i-dma.c
--- linux-libre-4.6-gnu/drivers/dma/sun6i-dma.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/dma/sun6i-dma.c	2016-07-24 15:23:50.000000000 -0400
@@ -146,6 +146,8 @@ struct sun6i_vchan {
 	struct dma_slave_config	cfg;
 	struct sun6i_pchan	*phy;
 	u8			port;
+	u8			irq_type;
+	bool			cyclic;
 };
 
 struct sun6i_dma_dev {
@@ -254,6 +256,30 @@ static inline s8 convert_buswidth(enum d
 	return addr_width >> 1;
 }
 
+static size_t sun6i_get_chan_size(struct sun6i_pchan *pchan)
+{
+	struct sun6i_desc *txd = pchan->desc;
+	struct sun6i_dma_lli *lli;
+	size_t bytes;
+	dma_addr_t pos;
+
+	pos = readl(pchan->base + DMA_CHAN_LLI_ADDR);
+	bytes = readl(pchan->base + DMA_CHAN_CUR_CNT);
+
+	if (pos == LLI_LAST_ITEM)
+		return bytes;
+
+	for (lli = txd->v_lli; lli; lli = lli->v_lli_next) {
+		if (lli->p_lli_next == pos) {
+			for (lli = lli->v_lli_next; lli; lli = lli->v_lli_next)
+				bytes += lli->len;
+			break;
+		}
+	}
+
+	return bytes;
+}
+
 static void *sun6i_dma_lli_add(struct sun6i_dma_lli *prev,
 			       struct sun6i_dma_lli *next,
 			       dma_addr_t next_phy,
@@ -276,45 +302,6 @@ static void *sun6i_dma_lli_add(struct su
 	return next;
 }
 
-static inline int sun6i_dma_cfg_lli(struct sun6i_dma_lli *lli,
-				    dma_addr_t src,
-				    dma_addr_t dst, u32 len,
-				    struct dma_slave_config *config)
-{
-	u8 src_width, dst_width, src_burst, dst_burst;
-
-	if (!config)
-		return -EINVAL;
-
-	src_burst = convert_burst(config->src_maxburst);
-	if (src_burst)
-		return src_burst;
-
-	dst_burst = convert_burst(config->dst_maxburst);
-	if (dst_burst)
-		return dst_burst;
-
-	src_width = convert_buswidth(config->src_addr_width);
-	if (src_width)
-		return src_width;
-
-	dst_width = convert_buswidth(config->dst_addr_width);
-	if (dst_width)
-		return dst_width;
-
-	lli->cfg = DMA_CHAN_CFG_SRC_BURST(src_burst) |
-		DMA_CHAN_CFG_SRC_WIDTH(src_width) |
-		DMA_CHAN_CFG_DST_BURST(dst_burst) |
-		DMA_CHAN_CFG_DST_WIDTH(dst_width);
-
-	lli->src = src;
-	lli->dst = dst;
-	lli->len = len;
-	lli->para = NORMAL_WAIT;
-
-	return 0;
-}
-
 static inline void sun6i_dma_dump_lli(struct sun6i_vchan *vchan,
 				      struct sun6i_dma_lli *lli)
 {
@@ -381,9 +368,13 @@ static int sun6i_dma_start_desc(struct s
 	irq_reg = pchan->idx / DMA_IRQ_CHAN_NR;
 	irq_offset = pchan->idx % DMA_IRQ_CHAN_NR;
 
-	irq_val = readl(sdev->base + DMA_IRQ_EN(irq_offset));
-	irq_val |= DMA_IRQ_QUEUE << (irq_offset * DMA_IRQ_CHAN_WIDTH);
-	writel(irq_val, sdev->base + DMA_IRQ_EN(irq_offset));
+	vchan->irq_type = vchan->cyclic ? DMA_IRQ_PKG : DMA_IRQ_QUEUE;
+
+	irq_val = readl(sdev->base + DMA_IRQ_EN(irq_reg));
+	irq_val &= ~((DMA_IRQ_HALF | DMA_IRQ_PKG | DMA_IRQ_QUEUE) <<
+			(irq_offset * DMA_IRQ_CHAN_WIDTH));
+	irq_val |= vchan->irq_type << (irq_offset * DMA_IRQ_CHAN_WIDTH);
+	writel(irq_val, sdev->base + DMA_IRQ_EN(irq_reg));
 
 	writel(pchan->desc->p_lli, pchan->base + DMA_CHAN_LLI_ADDR);
 	writel(DMA_CHAN_ENABLE_START, pchan->base + DMA_CHAN_ENABLE);
@@ -479,11 +470,12 @@ static irqreturn_t sun6i_dma_interrupt(i
 		writel(status, sdev->base + DMA_IRQ_STAT(i));
 
 		for (j = 0; (j < DMA_IRQ_CHAN_NR) && status; j++) {
-			if (status & DMA_IRQ_QUEUE) {
-				pchan = sdev->pchans + j;
-				vchan = pchan->vchan;
-
-				if (vchan) {
+			pchan = sdev->pchans + j;
+			vchan = pchan->vchan;
+			if (vchan && (status & vchan->irq_type)) {
+				if (vchan->cyclic) {
+					vchan_cyclic_callback(&pchan->desc->vd);
+				} else {
 					spin_lock(&vchan->vc.lock);
 					vchan_cookie_complete(&pchan->desc->vd);
 					pchan->done = pchan->desc;
@@ -502,6 +494,55 @@ static irqreturn_t sun6i_dma_interrupt(i
 	return ret;
 }
 
+static int set_config(struct sun6i_dma_dev *sdev,
+			struct dma_slave_config *sconfig,
+			enum dma_transfer_direction direction,
+			u32 *p_cfg)
+{
+	s8 src_width, dst_width, src_burst, dst_burst;
+
+	switch (direction) {
+	case DMA_MEM_TO_DEV:
+		src_burst = convert_burst(sconfig->src_maxburst ?
+					sconfig->src_maxburst : 8);
+		src_width = convert_buswidth(sconfig->src_addr_width !=
+						DMA_SLAVE_BUSWIDTH_UNDEFINED ?
+				sconfig->src_addr_width :
+				DMA_SLAVE_BUSWIDTH_4_BYTES);
+		dst_burst = convert_burst(sconfig->dst_maxburst);
+		dst_width = convert_buswidth(sconfig->dst_addr_width);
+		break;
+	case DMA_DEV_TO_MEM:
+		src_burst = convert_burst(sconfig->src_maxburst);
+		src_width = convert_buswidth(sconfig->src_addr_width);
+		dst_burst = convert_burst(sconfig->dst_maxburst ?
+					sconfig->dst_maxburst : 8);
+		dst_width = convert_buswidth(sconfig->dst_addr_width !=
+						DMA_SLAVE_BUSWIDTH_UNDEFINED ?
+				sconfig->dst_addr_width :
+				DMA_SLAVE_BUSWIDTH_4_BYTES);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (src_burst < 0)
+		return src_burst;
+	if (src_width < 0)
+		return src_width;
+	if (dst_burst < 0)
+		return dst_burst;
+	if (dst_width < 0)
+		return dst_width;
+
+	*p_cfg = DMA_CHAN_CFG_SRC_BURST(src_burst) |
+		DMA_CHAN_CFG_SRC_WIDTH(src_width) |
+		DMA_CHAN_CFG_DST_BURST(dst_burst) |
+		DMA_CHAN_CFG_DST_WIDTH(dst_width);
+
+	return 0;
+}
+
 static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_memcpy(
 		struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
 		size_t len, unsigned long flags)
@@ -569,13 +610,15 @@ static struct dma_async_tx_descriptor *s
 	struct sun6i_desc *txd;
 	struct scatterlist *sg;
 	dma_addr_t p_lli;
+	u32 lli_cfg;
 	int i, ret;
 
 	if (!sgl)
 		return NULL;
 
-	if (!is_slave_direction(dir)) {
-		dev_err(chan2dev(chan), "Invalid DMA direction\n");
+	ret = set_config(sdev, sconfig, dir, &lli_cfg);
+	if (ret) {
+		dev_err(chan2dev(chan), "Invalid DMA configuration\n");
 		return NULL;
 	}
 
@@ -588,14 +631,14 @@ static struct dma_async_tx_descriptor *s
 		if (!v_lli)
 			goto err_lli_free;
 
-		if (dir == DMA_MEM_TO_DEV) {
-			ret = sun6i_dma_cfg_lli(v_lli, sg_dma_address(sg),
-						sconfig->dst_addr, sg_dma_len(sg),
-						sconfig);
-			if (ret)
-				goto err_cur_lli_free;
+		v_lli->len = sg_dma_len(sg);
+		v_lli->para = NORMAL_WAIT;
 
-			v_lli->cfg |= DMA_CHAN_CFG_DST_IO_MODE |
+		if (dir == DMA_MEM_TO_DEV) {
+			v_lli->src = sg_dma_address(sg);
+			v_lli->dst = sconfig->dst_addr;
+			v_lli->cfg = lli_cfg |
+				DMA_CHAN_CFG_DST_IO_MODE |
 				DMA_CHAN_CFG_SRC_LINEAR_MODE |
 				DMA_CHAN_CFG_SRC_DRQ(DRQ_SDRAM) |
 				DMA_CHAN_CFG_DST_DRQ(vchan->port);
@@ -607,13 +650,10 @@ static struct dma_async_tx_descriptor *s
 				sg_dma_len(sg), flags);
 
 		} else {
-			ret = sun6i_dma_cfg_lli(v_lli, sconfig->src_addr,
-						sg_dma_address(sg), sg_dma_len(sg),
-						sconfig);
-			if (ret)
-				goto err_cur_lli_free;
-
-			v_lli->cfg |= DMA_CHAN_CFG_DST_LINEAR_MODE |
+			v_lli->src = sconfig->src_addr;
+			v_lli->dst = sg_dma_address(sg);
+			v_lli->cfg = lli_cfg |
+				DMA_CHAN_CFG_DST_LINEAR_MODE |
 				DMA_CHAN_CFG_SRC_IO_MODE |
 				DMA_CHAN_CFG_DST_DRQ(DRQ_SDRAM) |
 				DMA_CHAN_CFG_SRC_DRQ(vchan->port);
@@ -634,8 +674,78 @@ static struct dma_async_tx_descriptor *s
 
 	return vchan_tx_prep(&vchan->vc, &txd->vd, flags);
 
-err_cur_lli_free:
-	dma_pool_free(sdev->pool, v_lli, p_lli);
+err_lli_free:
+	for (prev = txd->v_lli; prev; prev = prev->v_lli_next)
+		dma_pool_free(sdev->pool, prev, virt_to_phys(prev));
+	kfree(txd);
+	return NULL;
+}
+
+static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_cyclic(
+					struct dma_chan *chan,
+					dma_addr_t buf_addr,
+					size_t buf_len,
+					size_t period_len,
+					enum dma_transfer_direction dir,
+					unsigned long flags)
+{
+	struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(chan->device);
+	struct sun6i_vchan *vchan = to_sun6i_vchan(chan);
+	struct dma_slave_config *sconfig = &vchan->cfg;
+	struct sun6i_dma_lli *v_lli, *prev = NULL;
+	struct sun6i_desc *txd;
+	dma_addr_t p_lli;
+	u32 lli_cfg;
+	unsigned int i, periods = buf_len / period_len;
+	int ret;
+
+	ret = set_config(sdev, sconfig, dir, &lli_cfg);
+	if (ret) {
+		dev_err(chan2dev(chan), "Invalid DMA configuration\n");
+		return NULL;
+	}
+
+	txd = kzalloc(sizeof(*txd), GFP_NOWAIT);
+	if (!txd)
+		return NULL;
+
+	for (i = 0; i < periods; i++) {
+		v_lli = dma_pool_alloc(sdev->pool, GFP_NOWAIT, &p_lli);
+		if (!v_lli) {
+			dev_err(sdev->slave.dev, "Failed to alloc lli memory\n");
+			goto err_lli_free;
+		}
+
+		v_lli->len = period_len;
+		v_lli->para = NORMAL_WAIT;
+
+		if (dir == DMA_MEM_TO_DEV) {
+			v_lli->src = buf_addr + period_len * i;
+			v_lli->dst = sconfig->dst_addr;
+			v_lli->cfg = lli_cfg |
+				DMA_CHAN_CFG_DST_IO_MODE |
+				DMA_CHAN_CFG_SRC_LINEAR_MODE |
+				DMA_CHAN_CFG_SRC_DRQ(DRQ_SDRAM) |
+				DMA_CHAN_CFG_DST_DRQ(vchan->port);
+		} else {
+			v_lli->src = sconfig->src_addr;
+			v_lli->dst = buf_addr + period_len * i;
+			v_lli->cfg = lli_cfg |
+				DMA_CHAN_CFG_DST_LINEAR_MODE |
+				DMA_CHAN_CFG_SRC_IO_MODE |
+				DMA_CHAN_CFG_DST_DRQ(DRQ_SDRAM) |
+				DMA_CHAN_CFG_SRC_DRQ(vchan->port);
+		}
+
+		prev = sun6i_dma_lli_add(prev, v_lli, p_lli, txd);
+	}
+
+	prev->p_lli_next = txd->p_lli;		/* cyclic list */
+
+	vchan->cyclic = true;
+
+	return vchan_tx_prep(&vchan->vc, &txd->vd, flags);
+
 err_lli_free:
 	for (prev = txd->v_lli; prev; prev = prev->v_lli_next)
 		dma_pool_free(sdev->pool, prev, virt_to_phys(prev));
@@ -712,6 +822,16 @@ static int sun6i_dma_terminate_all(struc
 
 	spin_lock_irqsave(&vchan->vc.lock, flags);
 
+	if (vchan->cyclic) {
+		vchan->cyclic = false;
+		if (pchan && pchan->desc) {
+			struct virt_dma_desc *vd = &pchan->desc->vd;
+			struct virt_dma_chan *vc = &vchan->vc;
+
+			list_add_tail(&vd->node, &vc->desc_completed);
+		}
+	}
+
 	vchan_get_all_descriptors(&vchan->vc, &head);
 
 	if (pchan) {
@@ -759,7 +879,7 @@ static enum dma_status sun6i_dma_tx_stat
 	} else if (!pchan || !pchan->desc) {
 		bytes = 0;
 	} else {
-		bytes = readl(pchan->base + DMA_CHAN_CUR_CNT);
+		bytes = sun6i_get_chan_size(pchan);
 	}
 
 	spin_unlock_irqrestore(&vchan->vc.lock, flags);
@@ -963,6 +1083,7 @@ static int sun6i_dma_probe(struct platfo
 	dma_cap_set(DMA_PRIVATE, sdc->slave.cap_mask);
 	dma_cap_set(DMA_MEMCPY, sdc->slave.cap_mask);
 	dma_cap_set(DMA_SLAVE, sdc->slave.cap_mask);
+	dma_cap_set(DMA_CYCLIC, sdc->slave.cap_mask);
 
 	INIT_LIST_HEAD(&sdc->slave.channels);
 	sdc->slave.device_free_chan_resources	= sun6i_dma_free_chan_resources;
@@ -970,6 +1091,7 @@ static int sun6i_dma_probe(struct platfo
 	sdc->slave.device_issue_pending		= sun6i_dma_issue_pending;
 	sdc->slave.device_prep_slave_sg		= sun6i_dma_prep_slave_sg;
 	sdc->slave.device_prep_dma_memcpy	= sun6i_dma_prep_dma_memcpy;
+	sdc->slave.device_prep_dma_cyclic	= sun6i_dma_prep_dma_cyclic;
 	sdc->slave.copy_align			= DMAENGINE_ALIGN_4_BYTES;
 	sdc->slave.device_config		= sun6i_dma_config;
 	sdc->slave.device_pause			= sun6i_dma_pause;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma/tegra20-apb-dma.c linux-libre-4.7-gnu/drivers/dma/tegra20-apb-dma.c
--- linux-libre-4.6-gnu/drivers/dma/tegra20-apb-dma.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/dma/tegra20-apb-dma.c	2016-07-24 15:23:50.000000000 -0400
@@ -54,6 +54,7 @@
 #define TEGRA_APBDMA_CSR_ONCE			BIT(27)
 #define TEGRA_APBDMA_CSR_FLOW			BIT(21)
 #define TEGRA_APBDMA_CSR_REQ_SEL_SHIFT		16
+#define TEGRA_APBDMA_CSR_REQ_SEL_MASK		0x1F
 #define TEGRA_APBDMA_CSR_WCOUNT_MASK		0xFFFC
 
 /* STATUS register */
@@ -114,6 +115,8 @@
 /* Channel base address offset from APBDMA base address */
 #define TEGRA_APBDMA_CHANNEL_BASE_ADD_OFFSET	0x1000
 
+#define TEGRA_APBDMA_SLAVE_ID_INVALID	(TEGRA_APBDMA_CSR_REQ_SEL_MASK + 1)
+
 struct tegra_dma;
 
 /*
@@ -353,8 +356,11 @@ static int tegra_dma_slave_config(struct
 	}
 
 	memcpy(&tdc->dma_sconfig, sconfig, sizeof(*sconfig));
-	if (!tdc->slave_id)
+	if (tdc->slave_id == TEGRA_APBDMA_SLAVE_ID_INVALID) {
+		if (sconfig->slave_id > TEGRA_APBDMA_CSR_REQ_SEL_MASK)
+			return -EINVAL;
 		tdc->slave_id = sconfig->slave_id;
+	}
 	tdc->config_init = true;
 	return 0;
 }
@@ -1236,7 +1242,7 @@ static void tegra_dma_free_chan_resource
 	}
 	pm_runtime_put(tdma->dev);
 
-	tdc->slave_id = 0;
+	tdc->slave_id = TEGRA_APBDMA_SLAVE_ID_INVALID;
 }
 
 static struct dma_chan *tegra_dma_of_xlate(struct of_phandle_args *dma_spec,
@@ -1246,6 +1252,11 @@ static struct dma_chan *tegra_dma_of_xla
 	struct dma_chan *chan;
 	struct tegra_dma_channel *tdc;
 
+	if (dma_spec->args[0] > TEGRA_APBDMA_CSR_REQ_SEL_MASK) {
+		dev_err(tdma->dev, "Invalid slave id: %d\n", dma_spec->args[0]);
+		return NULL;
+	}
+
 	chan = dma_get_any_slave_channel(&tdma->dma_dev);
 	if (!chan)
 		return NULL;
@@ -1389,6 +1400,7 @@ static int tegra_dma_probe(struct platfo
 				&tdma->dma_dev.channels);
 		tdc->tdma = tdma;
 		tdc->id = i;
+		tdc->slave_id = TEGRA_APBDMA_SLAVE_ID_INVALID;
 
 		tasklet_init(&tdc->tasklet, tegra_dma_tasklet,
 				(unsigned long)tdc);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma/tegra210-adma.c linux-libre-4.7-gnu/drivers/dma/tegra210-adma.c
--- linux-libre-4.6-gnu/drivers/dma/tegra210-adma.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/dma/tegra210-adma.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,840 @@
+/*
+ * ADMA driver for Nvidia's Tegra210 ADMA controller.
+ *
+ * Copyright (c) 2016, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_dma.h>
+#include <linux/of_irq.h>
+#include <linux/pm_clock.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+
+#include "virt-dma.h"
+
+#define ADMA_CH_CMD					0x00
+#define ADMA_CH_STATUS					0x0c
+#define ADMA_CH_STATUS_XFER_EN				BIT(0)
+
+#define ADMA_CH_INT_STATUS				0x10
+#define ADMA_CH_INT_STATUS_XFER_DONE			BIT(0)
+
+#define ADMA_CH_INT_CLEAR				0x1c
+#define ADMA_CH_CTRL					0x24
+#define ADMA_CH_CTRL_TX_REQ(val)			(((val) & 0xf) << 28)
+#define ADMA_CH_CTRL_TX_REQ_MAX				10
+#define ADMA_CH_CTRL_RX_REQ(val)			(((val) & 0xf) << 24)
+#define ADMA_CH_CTRL_RX_REQ_MAX				10
+#define ADMA_CH_CTRL_DIR(val)				(((val) & 0xf) << 12)
+#define ADMA_CH_CTRL_DIR_AHUB2MEM			2
+#define ADMA_CH_CTRL_DIR_MEM2AHUB			4
+#define ADMA_CH_CTRL_MODE_CONTINUOUS			(2 << 8)
+#define ADMA_CH_CTRL_FLOWCTRL_EN			BIT(1)
+
+#define ADMA_CH_CONFIG					0x28
+#define ADMA_CH_CONFIG_SRC_BUF(val)			(((val) & 0x7) << 28)
+#define ADMA_CH_CONFIG_TRG_BUF(val)			(((val) & 0x7) << 24)
+#define ADMA_CH_CONFIG_BURST_SIZE(val)			(((val) & 0x7) << 20)
+#define ADMA_CH_CONFIG_BURST_16				5
+#define ADMA_CH_CONFIG_WEIGHT_FOR_WRR(val)		((val) & 0xf)
+#define ADMA_CH_CONFIG_MAX_BUFS				8
+
+#define ADMA_CH_FIFO_CTRL				0x2c
+#define ADMA_CH_FIFO_CTRL_OVRFW_THRES(val)		(((val) & 0xf) << 24)
+#define ADMA_CH_FIFO_CTRL_STARV_THRES(val)		(((val) & 0xf) << 16)
+#define ADMA_CH_FIFO_CTRL_TX_SIZE(val)			(((val) & 0xf) << 8)
+#define ADMA_CH_FIFO_CTRL_RX_SIZE(val)			((val) & 0xf)
+
+#define ADMA_CH_LOWER_SRC_ADDR				0x34
+#define ADMA_CH_LOWER_TRG_ADDR				0x3c
+#define ADMA_CH_TC					0x44
+#define ADMA_CH_TC_COUNT_MASK				0x3ffffffc
+
+#define ADMA_CH_XFER_STATUS				0x54
+#define ADMA_CH_XFER_STATUS_COUNT_MASK			0xffff
+
+#define ADMA_GLOBAL_CMD					0xc00
+#define ADMA_GLOBAL_SOFT_RESET				0xc04
+#define ADMA_GLOBAL_INT_CLEAR				0xc20
+#define ADMA_GLOBAL_CTRL				0xc24
+
+#define ADMA_CH_REG_OFFSET(a)				(a * 0x80)
+
+#define ADMA_CH_FIFO_CTRL_DEFAULT	(ADMA_CH_FIFO_CTRL_OVRFW_THRES(1) | \
+					 ADMA_CH_FIFO_CTRL_STARV_THRES(1) | \
+					 ADMA_CH_FIFO_CTRL_TX_SIZE(3)     | \
+					 ADMA_CH_FIFO_CTRL_RX_SIZE(3))
+struct tegra_adma;
+
+/*
+ * struct tegra_adma_chip_data - Tegra chip specific data
+ * @nr_channels: Number of DMA channels available.
+ */
+struct tegra_adma_chip_data {
+	int nr_channels;
+};
+
+/*
+ * struct tegra_adma_chan_regs - Tegra ADMA channel registers
+ */
+struct tegra_adma_chan_regs {
+	unsigned int ctrl;
+	unsigned int config;
+	unsigned int src_addr;
+	unsigned int trg_addr;
+	unsigned int fifo_ctrl;
+	unsigned int tc;
+};
+
+/*
+ * struct tegra_adma_desc - Tegra ADMA descriptor to manage transfer requests.
+ */
+struct tegra_adma_desc {
+	struct virt_dma_desc		vd;
+	struct tegra_adma_chan_regs	ch_regs;
+	size_t				buf_len;
+	size_t				period_len;
+	size_t				num_periods;
+};
+
+/*
+ * struct tegra_adma_chan - Tegra ADMA channel information
+ */
+struct tegra_adma_chan {
+	struct virt_dma_chan		vc;
+	struct tegra_adma_desc		*desc;
+	struct tegra_adma		*tdma;
+	int				irq;
+	void __iomem			*chan_addr;
+
+	/* Slave channel configuration info */
+	struct dma_slave_config		sconfig;
+	enum dma_transfer_direction	sreq_dir;
+	unsigned int			sreq_index;
+	bool				sreq_reserved;
+
+	/* Transfer count and position info */
+	unsigned int			tx_buf_count;
+	unsigned int			tx_buf_pos;
+};
+
+/*
+ * struct tegra_adma - Tegra ADMA controller information
+ */
+struct tegra_adma {
+	struct dma_device		dma_dev;
+	struct device			*dev;
+	void __iomem			*base_addr;
+	unsigned int			nr_channels;
+	unsigned long			rx_requests_reserved;
+	unsigned long			tx_requests_reserved;
+
+	/* Used to store global command register state when suspending */
+	unsigned int			global_cmd;
+
+	/* Last member of the structure */
+	struct tegra_adma_chan		channels[0];
+};
+
+static inline void tdma_write(struct tegra_adma *tdma, u32 reg, u32 val)
+{
+	writel(val, tdma->base_addr + reg);
+}
+
+static inline u32 tdma_read(struct tegra_adma *tdma, u32 reg)
+{
+	return readl(tdma->base_addr + reg);
+}
+
+static inline void tdma_ch_write(struct tegra_adma_chan *tdc, u32 reg, u32 val)
+{
+	writel(val, tdc->chan_addr + reg);
+}
+
+static inline u32 tdma_ch_read(struct tegra_adma_chan *tdc, u32 reg)
+{
+	return readl(tdc->chan_addr + reg);
+}
+
+static inline struct tegra_adma_chan *to_tegra_adma_chan(struct dma_chan *dc)
+{
+	return container_of(dc, struct tegra_adma_chan, vc.chan);
+}
+
+static inline struct tegra_adma_desc *to_tegra_adma_desc(
+		struct dma_async_tx_descriptor *td)
+{
+	return container_of(td, struct tegra_adma_desc, vd.tx);
+}
+
+static inline struct device *tdc2dev(struct tegra_adma_chan *tdc)
+{
+	return tdc->tdma->dev;
+}
+
+static void tegra_adma_desc_free(struct virt_dma_desc *vd)
+{
+	kfree(container_of(vd, struct tegra_adma_desc, vd));
+}
+
+static int tegra_adma_slave_config(struct dma_chan *dc,
+				   struct dma_slave_config *sconfig)
+{
+	struct tegra_adma_chan *tdc = to_tegra_adma_chan(dc);
+
+	memcpy(&tdc->sconfig, sconfig, sizeof(*sconfig));
+
+	return 0;
+}
+
+static int tegra_adma_init(struct tegra_adma *tdma)
+{
+	u32 status;
+	int ret;
+
+	/* Clear any interrupts */
+	tdma_write(tdma, ADMA_GLOBAL_INT_CLEAR, 0x1);
+
+	/* Assert soft reset */
+	tdma_write(tdma, ADMA_GLOBAL_SOFT_RESET, 0x1);
+
+	/* Wait for reset to clear */
+	ret = readx_poll_timeout(readl,
+				 tdma->base_addr + ADMA_GLOBAL_SOFT_RESET,
+				 status, status == 0, 20, 10000);
+	if (ret)
+		return ret;
+
+	/* Enable global ADMA registers */
+	tdma_write(tdma, ADMA_GLOBAL_CMD, 1);
+
+	return 0;
+}
+
+static int tegra_adma_request_alloc(struct tegra_adma_chan *tdc,
+				    enum dma_transfer_direction direction)
+{
+	struct tegra_adma *tdma = tdc->tdma;
+	unsigned int sreq_index = tdc->sreq_index;
+
+	if (tdc->sreq_reserved)
+		return tdc->sreq_dir == direction ? 0 : -EINVAL;
+
+	switch (direction) {
+	case DMA_MEM_TO_DEV:
+		if (sreq_index > ADMA_CH_CTRL_TX_REQ_MAX) {
+			dev_err(tdma->dev, "invalid DMA request\n");
+			return -EINVAL;
+		}
+
+		if (test_and_set_bit(sreq_index, &tdma->tx_requests_reserved)) {
+			dev_err(tdma->dev, "DMA request reserved\n");
+			return -EINVAL;
+		}
+		break;
+
+	case DMA_DEV_TO_MEM:
+		if (sreq_index > ADMA_CH_CTRL_RX_REQ_MAX) {
+			dev_err(tdma->dev, "invalid DMA request\n");
+			return -EINVAL;
+		}
+
+		if (test_and_set_bit(sreq_index, &tdma->rx_requests_reserved)) {
+			dev_err(tdma->dev, "DMA request reserved\n");
+			return -EINVAL;
+		}
+		break;
+
+	default:
+		dev_WARN(tdma->dev, "channel %s has invalid transfer type\n",
+			 dma_chan_name(&tdc->vc.chan));
+		return -EINVAL;
+	}
+
+	tdc->sreq_dir = direction;
+	tdc->sreq_reserved = true;
+
+	return 0;
+}
+
+static void tegra_adma_request_free(struct tegra_adma_chan *tdc)
+{
+	struct tegra_adma *tdma = tdc->tdma;
+
+	if (!tdc->sreq_reserved)
+		return;
+
+	switch (tdc->sreq_dir) {
+	case DMA_MEM_TO_DEV:
+		clear_bit(tdc->sreq_index, &tdma->tx_requests_reserved);
+		break;
+
+	case DMA_DEV_TO_MEM:
+		clear_bit(tdc->sreq_index, &tdma->rx_requests_reserved);
+		break;
+
+	default:
+		dev_WARN(tdma->dev, "channel %s has invalid transfer type\n",
+			 dma_chan_name(&tdc->vc.chan));
+		return;
+	}
+
+	tdc->sreq_reserved = false;
+}
+
+static u32 tegra_adma_irq_status(struct tegra_adma_chan *tdc)
+{
+	u32 status = tdma_ch_read(tdc, ADMA_CH_INT_STATUS);
+
+	return status & ADMA_CH_INT_STATUS_XFER_DONE;
+}
+
+static u32 tegra_adma_irq_clear(struct tegra_adma_chan *tdc)
+{
+	u32 status = tegra_adma_irq_status(tdc);
+
+	if (status)
+		tdma_ch_write(tdc, ADMA_CH_INT_CLEAR, status);
+
+	return status;
+}
+
+static void tegra_adma_stop(struct tegra_adma_chan *tdc)
+{
+	unsigned int status;
+
+	/* Disable ADMA */
+	tdma_ch_write(tdc, ADMA_CH_CMD, 0);
+
+	/* Clear interrupt status */
+	tegra_adma_irq_clear(tdc);
+
+	if (readx_poll_timeout_atomic(readl, tdc->chan_addr + ADMA_CH_STATUS,
+			status, !(status & ADMA_CH_STATUS_XFER_EN),
+			20, 10000)) {
+		dev_err(tdc2dev(tdc), "unable to stop DMA channel\n");
+		return;
+	}
+
+	kfree(tdc->desc);
+	tdc->desc = NULL;
+}
+
+static void tegra_adma_start(struct tegra_adma_chan *tdc)
+{
+	struct virt_dma_desc *vd = vchan_next_desc(&tdc->vc);
+	struct tegra_adma_chan_regs *ch_regs;
+	struct tegra_adma_desc *desc;
+
+	if (!vd)
+		return;
+
+	list_del(&vd->node);
+
+	desc = to_tegra_adma_desc(&vd->tx);
+
+	if (!desc) {
+		dev_warn(tdc2dev(tdc), "unable to start DMA, no descriptor\n");
+		return;
+	}
+
+	ch_regs = &desc->ch_regs;
+
+	tdc->tx_buf_pos = 0;
+	tdc->tx_buf_count = 0;
+	tdma_ch_write(tdc, ADMA_CH_TC, ch_regs->tc);
+	tdma_ch_write(tdc, ADMA_CH_CTRL, ch_regs->ctrl);
+	tdma_ch_write(tdc, ADMA_CH_LOWER_SRC_ADDR, ch_regs->src_addr);
+	tdma_ch_write(tdc, ADMA_CH_LOWER_TRG_ADDR, ch_regs->trg_addr);
+	tdma_ch_write(tdc, ADMA_CH_FIFO_CTRL, ch_regs->fifo_ctrl);
+	tdma_ch_write(tdc, ADMA_CH_CONFIG, ch_regs->config);
+
+	/* Start ADMA */
+	tdma_ch_write(tdc, ADMA_CH_CMD, 1);
+
+	tdc->desc = desc;
+}
+
+static unsigned int tegra_adma_get_residue(struct tegra_adma_chan *tdc)
+{
+	struct tegra_adma_desc *desc = tdc->desc;
+	unsigned int max = ADMA_CH_XFER_STATUS_COUNT_MASK + 1;
+	unsigned int pos = tdma_ch_read(tdc, ADMA_CH_XFER_STATUS);
+	unsigned int periods_remaining;
+
+	/*
+	 * Handle wrap around of buffer count register
+	 */
+	if (pos < tdc->tx_buf_pos)
+		tdc->tx_buf_count += pos + (max - tdc->tx_buf_pos);
+	else
+		tdc->tx_buf_count += pos - tdc->tx_buf_pos;
+
+	periods_remaining = tdc->tx_buf_count % desc->num_periods;
+	tdc->tx_buf_pos = pos;
+
+	return desc->buf_len - (periods_remaining * desc->period_len);
+}
+
+static irqreturn_t tegra_adma_isr(int irq, void *dev_id)
+{
+	struct tegra_adma_chan *tdc = dev_id;
+	unsigned long status;
+	unsigned long flags;
+
+	spin_lock_irqsave(&tdc->vc.lock, flags);
+
+	status = tegra_adma_irq_clear(tdc);
+	if (status == 0 || !tdc->desc) {
+		spin_unlock_irqrestore(&tdc->vc.lock, flags);
+		return IRQ_NONE;
+	}
+
+	vchan_cyclic_callback(&tdc->desc->vd);
+
+	spin_unlock_irqrestore(&tdc->vc.lock, flags);
+
+	return IRQ_HANDLED;
+}
+
+static void tegra_adma_issue_pending(struct dma_chan *dc)
+{
+	struct tegra_adma_chan *tdc = to_tegra_adma_chan(dc);
+	unsigned long flags;
+
+	spin_lock_irqsave(&tdc->vc.lock, flags);
+
+	if (vchan_issue_pending(&tdc->vc)) {
+		if (!tdc->desc)
+			tegra_adma_start(tdc);
+	}
+
+	spin_unlock_irqrestore(&tdc->vc.lock, flags);
+}
+
+static int tegra_adma_terminate_all(struct dma_chan *dc)
+{
+	struct tegra_adma_chan *tdc = to_tegra_adma_chan(dc);
+	unsigned long flags;
+	LIST_HEAD(head);
+
+	spin_lock_irqsave(&tdc->vc.lock, flags);
+
+	if (tdc->desc)
+		tegra_adma_stop(tdc);
+
+	tegra_adma_request_free(tdc);
+	vchan_get_all_descriptors(&tdc->vc, &head);
+	spin_unlock_irqrestore(&tdc->vc.lock, flags);
+	vchan_dma_desc_free_list(&tdc->vc, &head);
+
+	return 0;
+}
+
+static enum dma_status tegra_adma_tx_status(struct dma_chan *dc,
+					    dma_cookie_t cookie,
+					    struct dma_tx_state *txstate)
+{
+	struct tegra_adma_chan *tdc = to_tegra_adma_chan(dc);
+	struct tegra_adma_desc *desc;
+	struct virt_dma_desc *vd;
+	enum dma_status ret;
+	unsigned long flags;
+	unsigned int residual;
+
+	ret = dma_cookie_status(dc, cookie, txstate);
+	if (ret == DMA_COMPLETE || !txstate)
+		return ret;
+
+	spin_lock_irqsave(&tdc->vc.lock, flags);
+
+	vd = vchan_find_desc(&tdc->vc, cookie);
+	if (vd) {
+		desc = to_tegra_adma_desc(&vd->tx);
+		residual = desc->ch_regs.tc;
+	} else if (tdc->desc && tdc->desc->vd.tx.cookie == cookie) {
+		residual = tegra_adma_get_residue(tdc);
+	} else {
+		residual = 0;
+	}
+
+	spin_unlock_irqrestore(&tdc->vc.lock, flags);
+
+	dma_set_residue(txstate, residual);
+
+	return ret;
+}
+
+static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc,
+				      struct tegra_adma_desc *desc,
+				      dma_addr_t buf_addr,
+				      enum dma_transfer_direction direction)
+{
+	struct tegra_adma_chan_regs *ch_regs = &desc->ch_regs;
+	unsigned int burst_size, adma_dir;
+
+	if (desc->num_periods > ADMA_CH_CONFIG_MAX_BUFS)
+		return -EINVAL;
+
+	switch (direction) {
+	case DMA_MEM_TO_DEV:
+		adma_dir = ADMA_CH_CTRL_DIR_MEM2AHUB;
+		burst_size = fls(tdc->sconfig.dst_maxburst);
+		ch_regs->config = ADMA_CH_CONFIG_SRC_BUF(desc->num_periods - 1);
+		ch_regs->ctrl = ADMA_CH_CTRL_TX_REQ(tdc->sreq_index);
+		ch_regs->src_addr = buf_addr;
+		break;
+
+	case DMA_DEV_TO_MEM:
+		adma_dir = ADMA_CH_CTRL_DIR_AHUB2MEM;
+		burst_size = fls(tdc->sconfig.src_maxburst);
+		ch_regs->config = ADMA_CH_CONFIG_TRG_BUF(desc->num_periods - 1);
+		ch_regs->ctrl = ADMA_CH_CTRL_RX_REQ(tdc->sreq_index);
+		ch_regs->trg_addr = buf_addr;
+		break;
+
+	default:
+		dev_err(tdc2dev(tdc), "DMA direction is not supported\n");
+		return -EINVAL;
+	}
+
+	if (!burst_size || burst_size > ADMA_CH_CONFIG_BURST_16)
+		burst_size = ADMA_CH_CONFIG_BURST_16;
+
+	ch_regs->ctrl |= ADMA_CH_CTRL_DIR(adma_dir) |
+			 ADMA_CH_CTRL_MODE_CONTINUOUS |
+			 ADMA_CH_CTRL_FLOWCTRL_EN;
+	ch_regs->config |= ADMA_CH_CONFIG_BURST_SIZE(burst_size);
+	ch_regs->config |= ADMA_CH_CONFIG_WEIGHT_FOR_WRR(1);
+	ch_regs->fifo_ctrl = ADMA_CH_FIFO_CTRL_DEFAULT;
+	ch_regs->tc = desc->period_len & ADMA_CH_TC_COUNT_MASK;
+
+	return tegra_adma_request_alloc(tdc, direction);
+}
+
+static struct dma_async_tx_descriptor *tegra_adma_prep_dma_cyclic(
+	struct dma_chan *dc, dma_addr_t buf_addr, size_t buf_len,
+	size_t period_len, enum dma_transfer_direction direction,
+	unsigned long flags)
+{
+	struct tegra_adma_chan *tdc = to_tegra_adma_chan(dc);
+	struct tegra_adma_desc *desc = NULL;
+
+	if (!buf_len || !period_len || period_len > ADMA_CH_TC_COUNT_MASK) {
+		dev_err(tdc2dev(tdc), "invalid buffer/period len\n");
+		return NULL;
+	}
+
+	if (buf_len % period_len) {
+		dev_err(tdc2dev(tdc), "buf_len not a multiple of period_len\n");
+		return NULL;
+	}
+
+	if (!IS_ALIGNED(buf_addr, 4)) {
+		dev_err(tdc2dev(tdc), "invalid buffer alignment\n");
+		return NULL;
+	}
+
+	desc = kzalloc(sizeof(*desc), GFP_NOWAIT);
+	if (!desc)
+		return NULL;
+
+	desc->buf_len = buf_len;
+	desc->period_len = period_len;
+	desc->num_periods = buf_len / period_len;
+
+	if (tegra_adma_set_xfer_params(tdc, desc, buf_addr, direction)) {
+		kfree(desc);
+		return NULL;
+	}
+
+	return vchan_tx_prep(&tdc->vc, &desc->vd, flags);
+}
+
+static int tegra_adma_alloc_chan_resources(struct dma_chan *dc)
+{
+	struct tegra_adma_chan *tdc = to_tegra_adma_chan(dc);
+	int ret;
+
+	ret = request_irq(tdc->irq, tegra_adma_isr, 0, dma_chan_name(dc), tdc);
+	if (ret) {
+		dev_err(tdc2dev(tdc), "failed to get interrupt for %s\n",
+			dma_chan_name(dc));
+		return ret;
+	}
+
+	ret = pm_runtime_get_sync(tdc2dev(tdc));
+	if (ret < 0) {
+		free_irq(tdc->irq, tdc);
+		return ret;
+	}
+
+	dma_cookie_init(&tdc->vc.chan);
+
+	return 0;
+}
+
+static void tegra_adma_free_chan_resources(struct dma_chan *dc)
+{
+	struct tegra_adma_chan *tdc = to_tegra_adma_chan(dc);
+
+	tegra_adma_terminate_all(dc);
+	vchan_free_chan_resources(&tdc->vc);
+	tasklet_kill(&tdc->vc.task);
+	free_irq(tdc->irq, tdc);
+	pm_runtime_put(tdc2dev(tdc));
+
+	tdc->sreq_index = 0;
+	tdc->sreq_dir = DMA_TRANS_NONE;
+}
+
+static struct dma_chan *tegra_dma_of_xlate(struct of_phandle_args *dma_spec,
+					   struct of_dma *ofdma)
+{
+	struct tegra_adma *tdma = ofdma->of_dma_data;
+	struct tegra_adma_chan *tdc;
+	struct dma_chan *chan;
+	unsigned int sreq_index;
+
+	if (dma_spec->args_count != 1)
+		return NULL;
+
+	sreq_index = dma_spec->args[0];
+
+	if (sreq_index == 0) {
+		dev_err(tdma->dev, "DMA request must not be 0\n");
+		return NULL;
+	}
+
+	chan = dma_get_any_slave_channel(&tdma->dma_dev);
+	if (!chan)
+		return NULL;
+
+	tdc = to_tegra_adma_chan(chan);
+	tdc->sreq_index = sreq_index;
+
+	return chan;
+}
+
+static int tegra_adma_runtime_suspend(struct device *dev)
+{
+	struct tegra_adma *tdma = dev_get_drvdata(dev);
+
+	tdma->global_cmd = tdma_read(tdma, ADMA_GLOBAL_CMD);
+
+	return pm_clk_suspend(dev);
+}
+
+static int tegra_adma_runtime_resume(struct device *dev)
+{
+	struct tegra_adma *tdma = dev_get_drvdata(dev);
+	int ret;
+
+	ret = pm_clk_resume(dev);
+	if (ret)
+		return ret;
+
+	tdma_write(tdma, ADMA_GLOBAL_CMD, tdma->global_cmd);
+
+	return 0;
+}
+
+static const struct tegra_adma_chip_data tegra210_chip_data = {
+	.nr_channels = 22,
+};
+
+static const struct of_device_id tegra_adma_of_match[] = {
+	{ .compatible = "nvidia,tegra210-adma", .data = &tegra210_chip_data },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, tegra_adma_of_match);
+
+static int tegra_adma_probe(struct platform_device *pdev)
+{
+	const struct tegra_adma_chip_data *cdata;
+	struct tegra_adma *tdma;
+	struct resource	*res;
+	struct clk *clk;
+	int ret, i;
+
+	cdata = of_device_get_match_data(&pdev->dev);
+	if (!cdata) {
+		dev_err(&pdev->dev, "device match data not found\n");
+		return -ENODEV;
+	}
+
+	tdma = devm_kzalloc(&pdev->dev, sizeof(*tdma) + cdata->nr_channels *
+			    sizeof(struct tegra_adma_chan), GFP_KERNEL);
+	if (!tdma)
+		return -ENOMEM;
+
+	tdma->dev = &pdev->dev;
+	tdma->nr_channels = cdata->nr_channels;
+	platform_set_drvdata(pdev, tdma);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	tdma->base_addr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(tdma->base_addr))
+		return PTR_ERR(tdma->base_addr);
+
+	ret = pm_clk_create(&pdev->dev);
+	if (ret)
+		return ret;
+
+	clk = clk_get(&pdev->dev, "d_audio");
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "ADMA clock not found\n");
+		ret = PTR_ERR(clk);
+		goto clk_destroy;
+	}
+
+	ret = pm_clk_add_clk(&pdev->dev, clk);
+	if (ret) {
+		clk_put(clk);
+		goto clk_destroy;
+	}
+
+	pm_runtime_enable(&pdev->dev);
+
+	ret = pm_runtime_get_sync(&pdev->dev);
+	if (ret < 0)
+		goto rpm_disable;
+
+	ret = tegra_adma_init(tdma);
+	if (ret)
+		goto rpm_put;
+
+	INIT_LIST_HEAD(&tdma->dma_dev.channels);
+	for (i = 0; i < tdma->nr_channels; i++) {
+		struct tegra_adma_chan *tdc = &tdma->channels[i];
+
+		tdc->chan_addr = tdma->base_addr + ADMA_CH_REG_OFFSET(i);
+
+		tdc->irq = of_irq_get(pdev->dev.of_node, i);
+		if (tdc->irq < 0) {
+			ret = tdc->irq;
+			goto irq_dispose;
+		}
+
+		vchan_init(&tdc->vc, &tdma->dma_dev);
+		tdc->vc.desc_free = tegra_adma_desc_free;
+		tdc->tdma = tdma;
+	}
+
+	dma_cap_set(DMA_SLAVE, tdma->dma_dev.cap_mask);
+	dma_cap_set(DMA_PRIVATE, tdma->dma_dev.cap_mask);
+	dma_cap_set(DMA_CYCLIC, tdma->dma_dev.cap_mask);
+
+	tdma->dma_dev.dev = &pdev->dev;
+	tdma->dma_dev.device_alloc_chan_resources =
+					tegra_adma_alloc_chan_resources;
+	tdma->dma_dev.device_free_chan_resources =
+					tegra_adma_free_chan_resources;
+	tdma->dma_dev.device_issue_pending = tegra_adma_issue_pending;
+	tdma->dma_dev.device_prep_dma_cyclic = tegra_adma_prep_dma_cyclic;
+	tdma->dma_dev.device_config = tegra_adma_slave_config;
+	tdma->dma_dev.device_tx_status = tegra_adma_tx_status;
+	tdma->dma_dev.device_terminate_all = tegra_adma_terminate_all;
+	tdma->dma_dev.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
+	tdma->dma_dev.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
+	tdma->dma_dev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
+	tdma->dma_dev.residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT;
+
+	ret = dma_async_device_register(&tdma->dma_dev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "ADMA registration failed: %d\n", ret);
+		goto irq_dispose;
+	}
+
+	ret = of_dma_controller_register(pdev->dev.of_node,
+					 tegra_dma_of_xlate, tdma);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "ADMA OF registration failed %d\n", ret);
+		goto dma_remove;
+	}
+
+	pm_runtime_put(&pdev->dev);
+
+	dev_info(&pdev->dev, "Tegra210 ADMA driver registered %d channels\n",
+		 tdma->nr_channels);
+
+	return 0;
+
+dma_remove:
+	dma_async_device_unregister(&tdma->dma_dev);
+irq_dispose:
+	while (--i >= 0)
+		irq_dispose_mapping(tdma->channels[i].irq);
+rpm_put:
+	pm_runtime_put_sync(&pdev->dev);
+rpm_disable:
+	pm_runtime_disable(&pdev->dev);
+clk_destroy:
+	pm_clk_destroy(&pdev->dev);
+
+	return ret;
+}
+
+static int tegra_adma_remove(struct platform_device *pdev)
+{
+	struct tegra_adma *tdma = platform_get_drvdata(pdev);
+	int i;
+
+	dma_async_device_unregister(&tdma->dma_dev);
+
+	for (i = 0; i < tdma->nr_channels; ++i)
+		irq_dispose_mapping(tdma->channels[i].irq);
+
+	pm_runtime_put_sync(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+	pm_clk_destroy(&pdev->dev);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int tegra_adma_pm_suspend(struct device *dev)
+{
+	return pm_runtime_suspended(dev) == false;
+}
+#endif
+
+static const struct dev_pm_ops tegra_adma_dev_pm_ops = {
+	SET_RUNTIME_PM_OPS(tegra_adma_runtime_suspend,
+			   tegra_adma_runtime_resume, NULL)
+	SET_SYSTEM_SLEEP_PM_OPS(tegra_adma_pm_suspend, NULL)
+};
+
+static struct platform_driver tegra_admac_driver = {
+	.driver = {
+		.name	= "tegra-adma",
+		.pm	= &tegra_adma_dev_pm_ops,
+		.of_match_table = tegra_adma_of_match,
+	},
+	.probe		= tegra_adma_probe,
+	.remove		= tegra_adma_remove,
+};
+
+module_platform_driver(tegra_admac_driver);
+
+MODULE_ALIAS("platform:tegra210-adma");
+MODULE_DESCRIPTION("NVIDIA Tegra ADMA driver");
+MODULE_AUTHOR("Dara Ramesh <dramesh@nvidia.com>");
+MODULE_AUTHOR("Jon Hunter <jonathanh@nvidia.com>");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma/xilinx/xilinx_vdma.c linux-libre-4.7-gnu/drivers/dma/xilinx/xilinx_vdma.c
--- linux-libre-4.6-gnu/drivers/dma/xilinx/xilinx_vdma.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/dma/xilinx/xilinx_vdma.c	2016-07-24 15:23:50.000000000 -0400
@@ -16,6 +16,15 @@
  * video device (S2MM). Initialization, status, interrupt and management
  * registers are accessed through an AXI4-Lite slave interface.
  *
+ * The AXI Direct Memory Access (AXI DMA) core is a soft Xilinx IP core that
+ * provides high-bandwidth one dimensional direct memory access between memory
+ * and AXI4-Stream target peripherals. It supports one receive and one
+ * transmit channel, both of them optional at synthesis time.
+ *
+ * The AXI CDMA, is a soft IP, which provides high-bandwidth Direct Memory
+ * Access (DMA) between a memory-mapped source address and a memory-mapped
+ * destination address.
+ *
  * 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
@@ -35,116 +44,138 @@
 #include <linux/of_platform.h>
 #include <linux/of_irq.h>
 #include <linux/slab.h>
+#include <linux/clk.h>
 
 #include "../dmaengine.h"
 
 /* Register/Descriptor Offsets */
-#define XILINX_VDMA_MM2S_CTRL_OFFSET		0x0000
-#define XILINX_VDMA_S2MM_CTRL_OFFSET		0x0030
+#define XILINX_DMA_MM2S_CTRL_OFFSET		0x0000
+#define XILINX_DMA_S2MM_CTRL_OFFSET		0x0030
 #define XILINX_VDMA_MM2S_DESC_OFFSET		0x0050
 #define XILINX_VDMA_S2MM_DESC_OFFSET		0x00a0
 
 /* Control Registers */
-#define XILINX_VDMA_REG_DMACR			0x0000
-#define XILINX_VDMA_DMACR_DELAY_MAX		0xff
-#define XILINX_VDMA_DMACR_DELAY_SHIFT		24
-#define XILINX_VDMA_DMACR_FRAME_COUNT_MAX	0xff
-#define XILINX_VDMA_DMACR_FRAME_COUNT_SHIFT	16
-#define XILINX_VDMA_DMACR_ERR_IRQ		BIT(14)
-#define XILINX_VDMA_DMACR_DLY_CNT_IRQ		BIT(13)
-#define XILINX_VDMA_DMACR_FRM_CNT_IRQ		BIT(12)
-#define XILINX_VDMA_DMACR_MASTER_SHIFT		8
-#define XILINX_VDMA_DMACR_FSYNCSRC_SHIFT	5
-#define XILINX_VDMA_DMACR_FRAMECNT_EN		BIT(4)
-#define XILINX_VDMA_DMACR_GENLOCK_EN		BIT(3)
-#define XILINX_VDMA_DMACR_RESET			BIT(2)
-#define XILINX_VDMA_DMACR_CIRC_EN		BIT(1)
-#define XILINX_VDMA_DMACR_RUNSTOP		BIT(0)
-#define XILINX_VDMA_DMACR_FSYNCSRC_MASK		GENMASK(6, 5)
+#define XILINX_DMA_REG_DMACR			0x0000
+#define XILINX_DMA_DMACR_DELAY_MAX		0xff
+#define XILINX_DMA_DMACR_DELAY_SHIFT		24
+#define XILINX_DMA_DMACR_FRAME_COUNT_MAX	0xff
+#define XILINX_DMA_DMACR_FRAME_COUNT_SHIFT	16
+#define XILINX_DMA_DMACR_ERR_IRQ		BIT(14)
+#define XILINX_DMA_DMACR_DLY_CNT_IRQ		BIT(13)
+#define XILINX_DMA_DMACR_FRM_CNT_IRQ		BIT(12)
+#define XILINX_DMA_DMACR_MASTER_SHIFT		8
+#define XILINX_DMA_DMACR_FSYNCSRC_SHIFT	5
+#define XILINX_DMA_DMACR_FRAMECNT_EN		BIT(4)
+#define XILINX_DMA_DMACR_GENLOCK_EN		BIT(3)
+#define XILINX_DMA_DMACR_RESET			BIT(2)
+#define XILINX_DMA_DMACR_CIRC_EN		BIT(1)
+#define XILINX_DMA_DMACR_RUNSTOP		BIT(0)
+#define XILINX_DMA_DMACR_FSYNCSRC_MASK		GENMASK(6, 5)
 
-#define XILINX_VDMA_REG_DMASR			0x0004
-#define XILINX_VDMA_DMASR_EOL_LATE_ERR		BIT(15)
-#define XILINX_VDMA_DMASR_ERR_IRQ		BIT(14)
-#define XILINX_VDMA_DMASR_DLY_CNT_IRQ		BIT(13)
-#define XILINX_VDMA_DMASR_FRM_CNT_IRQ		BIT(12)
-#define XILINX_VDMA_DMASR_SOF_LATE_ERR		BIT(11)
-#define XILINX_VDMA_DMASR_SG_DEC_ERR		BIT(10)
-#define XILINX_VDMA_DMASR_SG_SLV_ERR		BIT(9)
-#define XILINX_VDMA_DMASR_EOF_EARLY_ERR		BIT(8)
-#define XILINX_VDMA_DMASR_SOF_EARLY_ERR		BIT(7)
-#define XILINX_VDMA_DMASR_DMA_DEC_ERR		BIT(6)
-#define XILINX_VDMA_DMASR_DMA_SLAVE_ERR		BIT(5)
-#define XILINX_VDMA_DMASR_DMA_INT_ERR		BIT(4)
-#define XILINX_VDMA_DMASR_IDLE			BIT(1)
-#define XILINX_VDMA_DMASR_HALTED		BIT(0)
-#define XILINX_VDMA_DMASR_DELAY_MASK		GENMASK(31, 24)
-#define XILINX_VDMA_DMASR_FRAME_COUNT_MASK	GENMASK(23, 16)
+#define XILINX_DMA_REG_DMASR			0x0004
+#define XILINX_DMA_DMASR_EOL_LATE_ERR		BIT(15)
+#define XILINX_DMA_DMASR_ERR_IRQ		BIT(14)
+#define XILINX_DMA_DMASR_DLY_CNT_IRQ		BIT(13)
+#define XILINX_DMA_DMASR_FRM_CNT_IRQ		BIT(12)
+#define XILINX_DMA_DMASR_SOF_LATE_ERR		BIT(11)
+#define XILINX_DMA_DMASR_SG_DEC_ERR		BIT(10)
+#define XILINX_DMA_DMASR_SG_SLV_ERR		BIT(9)
+#define XILINX_DMA_DMASR_EOF_EARLY_ERR		BIT(8)
+#define XILINX_DMA_DMASR_SOF_EARLY_ERR		BIT(7)
+#define XILINX_DMA_DMASR_DMA_DEC_ERR		BIT(6)
+#define XILINX_DMA_DMASR_DMA_SLAVE_ERR		BIT(5)
+#define XILINX_DMA_DMASR_DMA_INT_ERR		BIT(4)
+#define XILINX_DMA_DMASR_IDLE			BIT(1)
+#define XILINX_DMA_DMASR_HALTED		BIT(0)
+#define XILINX_DMA_DMASR_DELAY_MASK		GENMASK(31, 24)
+#define XILINX_DMA_DMASR_FRAME_COUNT_MASK	GENMASK(23, 16)
 
-#define XILINX_VDMA_REG_CURDESC			0x0008
-#define XILINX_VDMA_REG_TAILDESC		0x0010
-#define XILINX_VDMA_REG_REG_INDEX		0x0014
-#define XILINX_VDMA_REG_FRMSTORE		0x0018
-#define XILINX_VDMA_REG_THRESHOLD		0x001c
-#define XILINX_VDMA_REG_FRMPTR_STS		0x0024
-#define XILINX_VDMA_REG_PARK_PTR		0x0028
-#define XILINX_VDMA_PARK_PTR_WR_REF_SHIFT	8
-#define XILINX_VDMA_PARK_PTR_RD_REF_SHIFT	0
-#define XILINX_VDMA_REG_VDMA_VERSION		0x002c
+#define XILINX_DMA_REG_CURDESC			0x0008
+#define XILINX_DMA_REG_TAILDESC		0x0010
+#define XILINX_DMA_REG_REG_INDEX		0x0014
+#define XILINX_DMA_REG_FRMSTORE		0x0018
+#define XILINX_DMA_REG_THRESHOLD		0x001c
+#define XILINX_DMA_REG_FRMPTR_STS		0x0024
+#define XILINX_DMA_REG_PARK_PTR		0x0028
+#define XILINX_DMA_PARK_PTR_WR_REF_SHIFT	8
+#define XILINX_DMA_PARK_PTR_RD_REF_SHIFT	0
+#define XILINX_DMA_REG_VDMA_VERSION		0x002c
 
 /* Register Direct Mode Registers */
-#define XILINX_VDMA_REG_VSIZE			0x0000
-#define XILINX_VDMA_REG_HSIZE			0x0004
+#define XILINX_DMA_REG_VSIZE			0x0000
+#define XILINX_DMA_REG_HSIZE			0x0004
 
-#define XILINX_VDMA_REG_FRMDLY_STRIDE		0x0008
-#define XILINX_VDMA_FRMDLY_STRIDE_FRMDLY_SHIFT	24
-#define XILINX_VDMA_FRMDLY_STRIDE_STRIDE_SHIFT	0
+#define XILINX_DMA_REG_FRMDLY_STRIDE		0x0008
+#define XILINX_DMA_FRMDLY_STRIDE_FRMDLY_SHIFT	24
+#define XILINX_DMA_FRMDLY_STRIDE_STRIDE_SHIFT	0
 
 #define XILINX_VDMA_REG_START_ADDRESS(n)	(0x000c + 4 * (n))
+#define XILINX_VDMA_REG_START_ADDRESS_64(n)	(0x000c + 8 * (n))
 
 /* HW specific definitions */
-#define XILINX_VDMA_MAX_CHANS_PER_DEVICE	0x2
+#define XILINX_DMA_MAX_CHANS_PER_DEVICE	0x2
 
-#define XILINX_VDMA_DMAXR_ALL_IRQ_MASK	\
-		(XILINX_VDMA_DMASR_FRM_CNT_IRQ | \
-		 XILINX_VDMA_DMASR_DLY_CNT_IRQ | \
-		 XILINX_VDMA_DMASR_ERR_IRQ)
+#define XILINX_DMA_DMAXR_ALL_IRQ_MASK	\
+		(XILINX_DMA_DMASR_FRM_CNT_IRQ | \
+		 XILINX_DMA_DMASR_DLY_CNT_IRQ | \
+		 XILINX_DMA_DMASR_ERR_IRQ)
 
-#define XILINX_VDMA_DMASR_ALL_ERR_MASK	\
-		(XILINX_VDMA_DMASR_EOL_LATE_ERR | \
-		 XILINX_VDMA_DMASR_SOF_LATE_ERR | \
-		 XILINX_VDMA_DMASR_SG_DEC_ERR | \
-		 XILINX_VDMA_DMASR_SG_SLV_ERR | \
-		 XILINX_VDMA_DMASR_EOF_EARLY_ERR | \
-		 XILINX_VDMA_DMASR_SOF_EARLY_ERR | \
-		 XILINX_VDMA_DMASR_DMA_DEC_ERR | \
-		 XILINX_VDMA_DMASR_DMA_SLAVE_ERR | \
-		 XILINX_VDMA_DMASR_DMA_INT_ERR)
+#define XILINX_DMA_DMASR_ALL_ERR_MASK	\
+		(XILINX_DMA_DMASR_EOL_LATE_ERR | \
+		 XILINX_DMA_DMASR_SOF_LATE_ERR | \
+		 XILINX_DMA_DMASR_SG_DEC_ERR | \
+		 XILINX_DMA_DMASR_SG_SLV_ERR | \
+		 XILINX_DMA_DMASR_EOF_EARLY_ERR | \
+		 XILINX_DMA_DMASR_SOF_EARLY_ERR | \
+		 XILINX_DMA_DMASR_DMA_DEC_ERR | \
+		 XILINX_DMA_DMASR_DMA_SLAVE_ERR | \
+		 XILINX_DMA_DMASR_DMA_INT_ERR)
 
 /*
  * Recoverable errors are DMA Internal error, SOF Early, EOF Early
  * and SOF Late. They are only recoverable when C_FLUSH_ON_FSYNC
  * is enabled in the h/w system.
  */
-#define XILINX_VDMA_DMASR_ERR_RECOVER_MASK	\
-		(XILINX_VDMA_DMASR_SOF_LATE_ERR | \
-		 XILINX_VDMA_DMASR_EOF_EARLY_ERR | \
-		 XILINX_VDMA_DMASR_SOF_EARLY_ERR | \
-		 XILINX_VDMA_DMASR_DMA_INT_ERR)
+#define XILINX_DMA_DMASR_ERR_RECOVER_MASK	\
+		(XILINX_DMA_DMASR_SOF_LATE_ERR | \
+		 XILINX_DMA_DMASR_EOF_EARLY_ERR | \
+		 XILINX_DMA_DMASR_SOF_EARLY_ERR | \
+		 XILINX_DMA_DMASR_DMA_INT_ERR)
 
 /* Axi VDMA Flush on Fsync bits */
-#define XILINX_VDMA_FLUSH_S2MM		3
-#define XILINX_VDMA_FLUSH_MM2S		2
-#define XILINX_VDMA_FLUSH_BOTH		1
+#define XILINX_DMA_FLUSH_S2MM		3
+#define XILINX_DMA_FLUSH_MM2S		2
+#define XILINX_DMA_FLUSH_BOTH		1
 
 /* Delay loop counter to prevent hardware failure */
-#define XILINX_VDMA_LOOP_COUNT		1000000
+#define XILINX_DMA_LOOP_COUNT		1000000
+
+/* AXI DMA Specific Registers/Offsets */
+#define XILINX_DMA_REG_SRCDSTADDR	0x18
+#define XILINX_DMA_REG_BTT		0x28
+
+/* AXI DMA Specific Masks/Bit fields */
+#define XILINX_DMA_MAX_TRANS_LEN	GENMASK(22, 0)
+#define XILINX_DMA_CR_COALESCE_MAX	GENMASK(23, 16)
+#define XILINX_DMA_CR_COALESCE_SHIFT	16
+#define XILINX_DMA_BD_SOP		BIT(27)
+#define XILINX_DMA_BD_EOP		BIT(26)
+#define XILINX_DMA_COALESCE_MAX		255
+#define XILINX_DMA_NUM_APP_WORDS	5
+
+/* AXI CDMA Specific Registers/Offsets */
+#define XILINX_CDMA_REG_SRCADDR		0x18
+#define XILINX_CDMA_REG_DSTADDR		0x20
+
+/* AXI CDMA Specific Masks */
+#define XILINX_CDMA_CR_SGMODE          BIT(3)
 
 /**
  * struct xilinx_vdma_desc_hw - Hardware Descriptor
  * @next_desc: Next Descriptor Pointer @0x00
  * @pad1: Reserved @0x04
  * @buf_addr: Buffer address @0x08
- * @pad2: Reserved @0x0C
+ * @buf_addr_msb: MSB of Buffer address @0x0C
  * @vsize: Vertical Size @0x10
  * @hsize: Horizontal Size @0x14
  * @stride: Number of bytes between the first
@@ -154,13 +185,59 @@ struct xilinx_vdma_desc_hw {
 	u32 next_desc;
 	u32 pad1;
 	u32 buf_addr;
-	u32 pad2;
+	u32 buf_addr_msb;
 	u32 vsize;
 	u32 hsize;
 	u32 stride;
 } __aligned(64);
 
 /**
+ * struct xilinx_axidma_desc_hw - Hardware Descriptor for AXI DMA
+ * @next_desc: Next Descriptor Pointer @0x00
+ * @pad1: Reserved @0x04
+ * @buf_addr: Buffer address @0x08
+ * @pad2: Reserved @0x0C
+ * @pad3: Reserved @0x10
+ * @pad4: Reserved @0x14
+ * @control: Control field @0x18
+ * @status: Status field @0x1C
+ * @app: APP Fields @0x20 - 0x30
+ */
+struct xilinx_axidma_desc_hw {
+	u32 next_desc;
+	u32 pad1;
+	u32 buf_addr;
+	u32 pad2;
+	u32 pad3;
+	u32 pad4;
+	u32 control;
+	u32 status;
+	u32 app[XILINX_DMA_NUM_APP_WORDS];
+} __aligned(64);
+
+/**
+ * struct xilinx_cdma_desc_hw - Hardware Descriptor
+ * @next_desc: Next Descriptor Pointer @0x00
+ * @pad1: Reserved @0x04
+ * @src_addr: Source address @0x08
+ * @pad2: Reserved @0x0C
+ * @dest_addr: Destination address @0x10
+ * @pad3: Reserved @0x14
+ * @control: Control field @0x18
+ * @status: Status field @0x1C
+ */
+struct xilinx_cdma_desc_hw {
+	u32 next_desc;
+	u32 pad1;
+	u32 src_addr;
+	u32 pad2;
+	u32 dest_addr;
+	u32 pad3;
+	u32 control;
+	u32 status;
+} __aligned(64);
+
+/**
  * struct xilinx_vdma_tx_segment - Descriptor segment
  * @hw: Hardware descriptor
  * @node: Node in the descriptor segments list
@@ -173,19 +250,43 @@ struct xilinx_vdma_tx_segment {
 } __aligned(64);
 
 /**
- * struct xilinx_vdma_tx_descriptor - Per Transaction structure
+ * struct xilinx_axidma_tx_segment - Descriptor segment
+ * @hw: Hardware descriptor
+ * @node: Node in the descriptor segments list
+ * @phys: Physical address of segment
+ */
+struct xilinx_axidma_tx_segment {
+	struct xilinx_axidma_desc_hw hw;
+	struct list_head node;
+	dma_addr_t phys;
+} __aligned(64);
+
+/**
+ * struct xilinx_cdma_tx_segment - Descriptor segment
+ * @hw: Hardware descriptor
+ * @node: Node in the descriptor segments list
+ * @phys: Physical address of segment
+ */
+struct xilinx_cdma_tx_segment {
+	struct xilinx_cdma_desc_hw hw;
+	struct list_head node;
+	dma_addr_t phys;
+} __aligned(64);
+
+/**
+ * struct xilinx_dma_tx_descriptor - Per Transaction structure
  * @async_tx: Async transaction descriptor
  * @segments: TX segments list
  * @node: Node in the channel descriptors list
  */
-struct xilinx_vdma_tx_descriptor {
+struct xilinx_dma_tx_descriptor {
 	struct dma_async_tx_descriptor async_tx;
 	struct list_head segments;
 	struct list_head node;
 };
 
 /**
- * struct xilinx_vdma_chan - Driver specific VDMA channel structure
+ * struct xilinx_dma_chan - Driver specific DMA channel structure
  * @xdev: Driver specific device structure
  * @ctrl_offset: Control registers offset
  * @desc_offset: TX descriptor registers offset
@@ -207,9 +308,14 @@ struct xilinx_vdma_tx_descriptor {
  * @config: Device configuration info
  * @flush_on_fsync: Flush on Frame sync
  * @desc_pendingcount: Descriptor pending count
+ * @ext_addr: Indicates 64 bit addressing is supported by dma channel
+ * @desc_submitcount: Descriptor h/w submitted count
+ * @residue: Residue for AXI DMA
+ * @seg_v: Statically allocated segments base
+ * @start_transfer: Differentiate b/w DMA IP's transfer
  */
-struct xilinx_vdma_chan {
-	struct xilinx_vdma_device *xdev;
+struct xilinx_dma_chan {
+	struct xilinx_dma_device *xdev;
 	u32 ctrl_offset;
 	u32 desc_offset;
 	spinlock_t lock;
@@ -230,73 +336,122 @@ struct xilinx_vdma_chan {
 	struct xilinx_vdma_config config;
 	bool flush_on_fsync;
 	u32 desc_pendingcount;
+	bool ext_addr;
+	u32 desc_submitcount;
+	u32 residue;
+	struct xilinx_axidma_tx_segment *seg_v;
+	void (*start_transfer)(struct xilinx_dma_chan *chan);
+};
+
+struct xilinx_dma_config {
+	enum xdma_ip_type dmatype;
+	int (*clk_init)(struct platform_device *pdev, struct clk **axi_clk,
+			struct clk **tx_clk, struct clk **txs_clk,
+			struct clk **rx_clk, struct clk **rxs_clk);
 };
 
 /**
- * struct xilinx_vdma_device - VDMA device structure
+ * struct xilinx_dma_device - DMA device structure
  * @regs: I/O mapped base address
  * @dev: Device Structure
  * @common: DMA device structure
- * @chan: Driver specific VDMA channel
+ * @chan: Driver specific DMA channel
  * @has_sg: Specifies whether Scatter-Gather is present or not
  * @flush_on_fsync: Flush on frame sync
+ * @ext_addr: Indicates 64 bit addressing is supported by dma device
+ * @pdev: Platform device structure pointer
+ * @dma_config: DMA config structure
+ * @axi_clk: DMA Axi4-lite interace clock
+ * @tx_clk: DMA mm2s clock
+ * @txs_clk: DMA mm2s stream clock
+ * @rx_clk: DMA s2mm clock
+ * @rxs_clk: DMA s2mm stream clock
  */
-struct xilinx_vdma_device {
+struct xilinx_dma_device {
 	void __iomem *regs;
 	struct device *dev;
 	struct dma_device common;
-	struct xilinx_vdma_chan *chan[XILINX_VDMA_MAX_CHANS_PER_DEVICE];
+	struct xilinx_dma_chan *chan[XILINX_DMA_MAX_CHANS_PER_DEVICE];
 	bool has_sg;
 	u32 flush_on_fsync;
+	bool ext_addr;
+	struct platform_device  *pdev;
+	const struct xilinx_dma_config *dma_config;
+	struct clk *axi_clk;
+	struct clk *tx_clk;
+	struct clk *txs_clk;
+	struct clk *rx_clk;
+	struct clk *rxs_clk;
 };
 
 /* Macros */
 #define to_xilinx_chan(chan) \
-	container_of(chan, struct xilinx_vdma_chan, common)
-#define to_vdma_tx_descriptor(tx) \
-	container_of(tx, struct xilinx_vdma_tx_descriptor, async_tx)
-#define xilinx_vdma_poll_timeout(chan, reg, val, cond, delay_us, timeout_us) \
+	container_of(chan, struct xilinx_dma_chan, common)
+#define to_dma_tx_descriptor(tx) \
+	container_of(tx, struct xilinx_dma_tx_descriptor, async_tx)
+#define xilinx_dma_poll_timeout(chan, reg, val, cond, delay_us, timeout_us) \
 	readl_poll_timeout(chan->xdev->regs + chan->ctrl_offset + reg, val, \
 			   cond, delay_us, timeout_us)
 
 /* IO accessors */
-static inline u32 vdma_read(struct xilinx_vdma_chan *chan, u32 reg)
+static inline u32 dma_read(struct xilinx_dma_chan *chan, u32 reg)
 {
 	return ioread32(chan->xdev->regs + reg);
 }
 
-static inline void vdma_write(struct xilinx_vdma_chan *chan, u32 reg, u32 value)
+static inline void dma_write(struct xilinx_dma_chan *chan, u32 reg, u32 value)
 {
 	iowrite32(value, chan->xdev->regs + reg);
 }
 
-static inline void vdma_desc_write(struct xilinx_vdma_chan *chan, u32 reg,
+static inline void vdma_desc_write(struct xilinx_dma_chan *chan, u32 reg,
 				   u32 value)
 {
-	vdma_write(chan, chan->desc_offset + reg, value);
+	dma_write(chan, chan->desc_offset + reg, value);
 }
 
-static inline u32 vdma_ctrl_read(struct xilinx_vdma_chan *chan, u32 reg)
+static inline u32 dma_ctrl_read(struct xilinx_dma_chan *chan, u32 reg)
 {
-	return vdma_read(chan, chan->ctrl_offset + reg);
+	return dma_read(chan, chan->ctrl_offset + reg);
 }
 
-static inline void vdma_ctrl_write(struct xilinx_vdma_chan *chan, u32 reg,
+static inline void dma_ctrl_write(struct xilinx_dma_chan *chan, u32 reg,
 				   u32 value)
 {
-	vdma_write(chan, chan->ctrl_offset + reg, value);
+	dma_write(chan, chan->ctrl_offset + reg, value);
 }
 
-static inline void vdma_ctrl_clr(struct xilinx_vdma_chan *chan, u32 reg,
+static inline void dma_ctrl_clr(struct xilinx_dma_chan *chan, u32 reg,
 				 u32 clr)
 {
-	vdma_ctrl_write(chan, reg, vdma_ctrl_read(chan, reg) & ~clr);
+	dma_ctrl_write(chan, reg, dma_ctrl_read(chan, reg) & ~clr);
 }
 
-static inline void vdma_ctrl_set(struct xilinx_vdma_chan *chan, u32 reg,
+static inline void dma_ctrl_set(struct xilinx_dma_chan *chan, u32 reg,
 				 u32 set)
 {
-	vdma_ctrl_write(chan, reg, vdma_ctrl_read(chan, reg) | set);
+	dma_ctrl_write(chan, reg, dma_ctrl_read(chan, reg) | set);
+}
+
+/**
+ * vdma_desc_write_64 - 64-bit descriptor write
+ * @chan: Driver specific VDMA channel
+ * @reg: Register to write
+ * @value_lsb: lower address of the descriptor.
+ * @value_msb: upper address of the descriptor.
+ *
+ * Since vdma driver is trying to write to a register offset which is not a
+ * multiple of 64 bits(ex : 0x5c), we are writing as two separate 32 bits
+ * instead of a single 64 bit register write.
+ */
+static inline void vdma_desc_write_64(struct xilinx_dma_chan *chan, u32 reg,
+				      u32 value_lsb, u32 value_msb)
+{
+	/* Write the lsb 32 bits*/
+	writel(value_lsb, chan->xdev->regs + chan->desc_offset + reg);
+
+	/* Write the msb 32 bits */
+	writel(value_msb, chan->xdev->regs + chan->desc_offset + reg + 4);
 }
 
 /* -----------------------------------------------------------------------------
@@ -305,16 +460,37 @@ static inline void vdma_ctrl_set(struct
 
 /**
  * xilinx_vdma_alloc_tx_segment - Allocate transaction segment
- * @chan: Driver specific VDMA channel
+ * @chan: Driver specific DMA channel
  *
  * Return: The allocated segment on success and NULL on failure.
  */
 static struct xilinx_vdma_tx_segment *
-xilinx_vdma_alloc_tx_segment(struct xilinx_vdma_chan *chan)
+xilinx_vdma_alloc_tx_segment(struct xilinx_dma_chan *chan)
 {
 	struct xilinx_vdma_tx_segment *segment;
 	dma_addr_t phys;
 
+	segment = dma_pool_zalloc(chan->desc_pool, GFP_ATOMIC, &phys);
+	if (!segment)
+		return NULL;
+
+	segment->phys = phys;
+
+	return segment;
+}
+
+/**
+ * xilinx_cdma_alloc_tx_segment - Allocate transaction segment
+ * @chan: Driver specific DMA channel
+ *
+ * Return: The allocated segment on success and NULL on failure.
+ */
+static struct xilinx_cdma_tx_segment *
+xilinx_cdma_alloc_tx_segment(struct xilinx_dma_chan *chan)
+{
+	struct xilinx_cdma_tx_segment *segment;
+	dma_addr_t phys;
+
 	segment = dma_pool_alloc(chan->desc_pool, GFP_ATOMIC, &phys);
 	if (!segment)
 		return NULL;
@@ -326,26 +502,70 @@ xilinx_vdma_alloc_tx_segment(struct xili
 }
 
 /**
+ * xilinx_axidma_alloc_tx_segment - Allocate transaction segment
+ * @chan: Driver specific DMA channel
+ *
+ * Return: The allocated segment on success and NULL on failure.
+ */
+static struct xilinx_axidma_tx_segment *
+xilinx_axidma_alloc_tx_segment(struct xilinx_dma_chan *chan)
+{
+	struct xilinx_axidma_tx_segment *segment;
+	dma_addr_t phys;
+
+	segment = dma_pool_alloc(chan->desc_pool, GFP_ATOMIC, &phys);
+	if (!segment)
+		return NULL;
+
+	memset(segment, 0, sizeof(*segment));
+	segment->phys = phys;
+
+	return segment;
+}
+
+/**
+ * xilinx_dma_free_tx_segment - Free transaction segment
+ * @chan: Driver specific DMA channel
+ * @segment: DMA transaction segment
+ */
+static void xilinx_dma_free_tx_segment(struct xilinx_dma_chan *chan,
+				struct xilinx_axidma_tx_segment *segment)
+{
+	dma_pool_free(chan->desc_pool, segment, segment->phys);
+}
+
+/**
+ * xilinx_cdma_free_tx_segment - Free transaction segment
+ * @chan: Driver specific DMA channel
+ * @segment: DMA transaction segment
+ */
+static void xilinx_cdma_free_tx_segment(struct xilinx_dma_chan *chan,
+				struct xilinx_cdma_tx_segment *segment)
+{
+	dma_pool_free(chan->desc_pool, segment, segment->phys);
+}
+
+/**
  * xilinx_vdma_free_tx_segment - Free transaction segment
- * @chan: Driver specific VDMA channel
- * @segment: VDMA transaction segment
+ * @chan: Driver specific DMA channel
+ * @segment: DMA transaction segment
  */
-static void xilinx_vdma_free_tx_segment(struct xilinx_vdma_chan *chan,
+static void xilinx_vdma_free_tx_segment(struct xilinx_dma_chan *chan,
 					struct xilinx_vdma_tx_segment *segment)
 {
 	dma_pool_free(chan->desc_pool, segment, segment->phys);
 }
 
 /**
- * xilinx_vdma_tx_descriptor - Allocate transaction descriptor
- * @chan: Driver specific VDMA channel
+ * xilinx_dma_tx_descriptor - Allocate transaction descriptor
+ * @chan: Driver specific DMA channel
  *
  * Return: The allocated descriptor on success and NULL on failure.
  */
-static struct xilinx_vdma_tx_descriptor *
-xilinx_vdma_alloc_tx_descriptor(struct xilinx_vdma_chan *chan)
+static struct xilinx_dma_tx_descriptor *
+xilinx_dma_alloc_tx_descriptor(struct xilinx_dma_chan *chan)
 {
-	struct xilinx_vdma_tx_descriptor *desc;
+	struct xilinx_dma_tx_descriptor *desc;
 
 	desc = kzalloc(sizeof(*desc), GFP_KERNEL);
 	if (!desc)
@@ -357,22 +577,38 @@ xilinx_vdma_alloc_tx_descriptor(struct x
 }
 
 /**
- * xilinx_vdma_free_tx_descriptor - Free transaction descriptor
- * @chan: Driver specific VDMA channel
- * @desc: VDMA transaction descriptor
+ * xilinx_dma_free_tx_descriptor - Free transaction descriptor
+ * @chan: Driver specific DMA channel
+ * @desc: DMA transaction descriptor
  */
 static void
-xilinx_vdma_free_tx_descriptor(struct xilinx_vdma_chan *chan,
-			       struct xilinx_vdma_tx_descriptor *desc)
+xilinx_dma_free_tx_descriptor(struct xilinx_dma_chan *chan,
+			       struct xilinx_dma_tx_descriptor *desc)
 {
 	struct xilinx_vdma_tx_segment *segment, *next;
+	struct xilinx_cdma_tx_segment *cdma_segment, *cdma_next;
+	struct xilinx_axidma_tx_segment *axidma_segment, *axidma_next;
 
 	if (!desc)
 		return;
 
-	list_for_each_entry_safe(segment, next, &desc->segments, node) {
-		list_del(&segment->node);
-		xilinx_vdma_free_tx_segment(chan, segment);
+	if (chan->xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
+		list_for_each_entry_safe(segment, next, &desc->segments, node) {
+			list_del(&segment->node);
+			xilinx_vdma_free_tx_segment(chan, segment);
+		}
+	} else if (chan->xdev->dma_config->dmatype == XDMA_TYPE_CDMA) {
+		list_for_each_entry_safe(cdma_segment, cdma_next,
+					 &desc->segments, node) {
+			list_del(&cdma_segment->node);
+			xilinx_cdma_free_tx_segment(chan, cdma_segment);
+		}
+	} else {
+		list_for_each_entry_safe(axidma_segment, axidma_next,
+					 &desc->segments, node) {
+			list_del(&axidma_segment->node);
+			xilinx_dma_free_tx_segment(chan, axidma_segment);
+		}
 	}
 
 	kfree(desc);
@@ -381,60 +617,62 @@ xilinx_vdma_free_tx_descriptor(struct xi
 /* Required functions */
 
 /**
- * xilinx_vdma_free_desc_list - Free descriptors list
- * @chan: Driver specific VDMA channel
+ * xilinx_dma_free_desc_list - Free descriptors list
+ * @chan: Driver specific DMA channel
  * @list: List to parse and delete the descriptor
  */
-static void xilinx_vdma_free_desc_list(struct xilinx_vdma_chan *chan,
+static void xilinx_dma_free_desc_list(struct xilinx_dma_chan *chan,
 					struct list_head *list)
 {
-	struct xilinx_vdma_tx_descriptor *desc, *next;
+	struct xilinx_dma_tx_descriptor *desc, *next;
 
 	list_for_each_entry_safe(desc, next, list, node) {
 		list_del(&desc->node);
-		xilinx_vdma_free_tx_descriptor(chan, desc);
+		xilinx_dma_free_tx_descriptor(chan, desc);
 	}
 }
 
 /**
- * xilinx_vdma_free_descriptors - Free channel descriptors
- * @chan: Driver specific VDMA channel
+ * xilinx_dma_free_descriptors - Free channel descriptors
+ * @chan: Driver specific DMA channel
  */
-static void xilinx_vdma_free_descriptors(struct xilinx_vdma_chan *chan)
+static void xilinx_dma_free_descriptors(struct xilinx_dma_chan *chan)
 {
 	unsigned long flags;
 
 	spin_lock_irqsave(&chan->lock, flags);
 
-	xilinx_vdma_free_desc_list(chan, &chan->pending_list);
-	xilinx_vdma_free_desc_list(chan, &chan->done_list);
-	xilinx_vdma_free_desc_list(chan, &chan->active_list);
+	xilinx_dma_free_desc_list(chan, &chan->pending_list);
+	xilinx_dma_free_desc_list(chan, &chan->done_list);
+	xilinx_dma_free_desc_list(chan, &chan->active_list);
 
 	spin_unlock_irqrestore(&chan->lock, flags);
 }
 
 /**
- * xilinx_vdma_free_chan_resources - Free channel resources
+ * xilinx_dma_free_chan_resources - Free channel resources
  * @dchan: DMA channel
  */
-static void xilinx_vdma_free_chan_resources(struct dma_chan *dchan)
+static void xilinx_dma_free_chan_resources(struct dma_chan *dchan)
 {
-	struct xilinx_vdma_chan *chan = to_xilinx_chan(dchan);
+	struct xilinx_dma_chan *chan = to_xilinx_chan(dchan);
 
 	dev_dbg(chan->dev, "Free all channel resources.\n");
 
-	xilinx_vdma_free_descriptors(chan);
+	xilinx_dma_free_descriptors(chan);
+	if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA)
+		xilinx_dma_free_tx_segment(chan, chan->seg_v);
 	dma_pool_destroy(chan->desc_pool);
 	chan->desc_pool = NULL;
 }
 
 /**
- * xilinx_vdma_chan_desc_cleanup - Clean channel descriptors
- * @chan: Driver specific VDMA channel
+ * xilinx_dma_chan_desc_cleanup - Clean channel descriptors
+ * @chan: Driver specific DMA channel
  */
-static void xilinx_vdma_chan_desc_cleanup(struct xilinx_vdma_chan *chan)
+static void xilinx_dma_chan_desc_cleanup(struct xilinx_dma_chan *chan)
 {
-	struct xilinx_vdma_tx_descriptor *desc, *next;
+	struct xilinx_dma_tx_descriptor *desc, *next;
 	unsigned long flags;
 
 	spin_lock_irqsave(&chan->lock, flags);
@@ -457,32 +695,32 @@ static void xilinx_vdma_chan_desc_cleanu
 
 		/* Run any dependencies, then free the descriptor */
 		dma_run_dependencies(&desc->async_tx);
-		xilinx_vdma_free_tx_descriptor(chan, desc);
+		xilinx_dma_free_tx_descriptor(chan, desc);
 	}
 
 	spin_unlock_irqrestore(&chan->lock, flags);
 }
 
 /**
- * xilinx_vdma_do_tasklet - Schedule completion tasklet
- * @data: Pointer to the Xilinx VDMA channel structure
+ * xilinx_dma_do_tasklet - Schedule completion tasklet
+ * @data: Pointer to the Xilinx DMA channel structure
  */
-static void xilinx_vdma_do_tasklet(unsigned long data)
+static void xilinx_dma_do_tasklet(unsigned long data)
 {
-	struct xilinx_vdma_chan *chan = (struct xilinx_vdma_chan *)data;
+	struct xilinx_dma_chan *chan = (struct xilinx_dma_chan *)data;
 
-	xilinx_vdma_chan_desc_cleanup(chan);
+	xilinx_dma_chan_desc_cleanup(chan);
 }
 
 /**
- * xilinx_vdma_alloc_chan_resources - Allocate channel resources
+ * xilinx_dma_alloc_chan_resources - Allocate channel resources
  * @dchan: DMA channel
  *
  * Return: '0' on success and failure value on error
  */
-static int xilinx_vdma_alloc_chan_resources(struct dma_chan *dchan)
+static int xilinx_dma_alloc_chan_resources(struct dma_chan *dchan)
 {
-	struct xilinx_vdma_chan *chan = to_xilinx_chan(dchan);
+	struct xilinx_dma_chan *chan = to_xilinx_chan(dchan);
 
 	/* Has this channel already been allocated? */
 	if (chan->desc_pool)
@@ -492,10 +730,26 @@ static int xilinx_vdma_alloc_chan_resour
 	 * We need the descriptor to be aligned to 64bytes
 	 * for meeting Xilinx VDMA specification requirement.
 	 */
-	chan->desc_pool = dma_pool_create("xilinx_vdma_desc_pool",
-				chan->dev,
-				sizeof(struct xilinx_vdma_tx_segment),
-				__alignof__(struct xilinx_vdma_tx_segment), 0);
+	if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
+		chan->desc_pool = dma_pool_create("xilinx_dma_desc_pool",
+				   chan->dev,
+				   sizeof(struct xilinx_axidma_tx_segment),
+				   __alignof__(struct xilinx_axidma_tx_segment),
+				   0);
+	} else if (chan->xdev->dma_config->dmatype == XDMA_TYPE_CDMA) {
+		chan->desc_pool = dma_pool_create("xilinx_cdma_desc_pool",
+				   chan->dev,
+				   sizeof(struct xilinx_cdma_tx_segment),
+				   __alignof__(struct xilinx_cdma_tx_segment),
+				   0);
+	} else {
+		chan->desc_pool = dma_pool_create("xilinx_vdma_desc_pool",
+				     chan->dev,
+				     sizeof(struct xilinx_vdma_tx_segment),
+				     __alignof__(struct xilinx_vdma_tx_segment),
+				     0);
+	}
+
 	if (!chan->desc_pool) {
 		dev_err(chan->dev,
 			"unable to allocate channel %d descriptor pool\n",
@@ -503,110 +757,160 @@ static int xilinx_vdma_alloc_chan_resour
 		return -ENOMEM;
 	}
 
+	if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA)
+		/*
+		 * For AXI DMA case after submitting a pending_list, keep
+		 * an extra segment allocated so that the "next descriptor"
+		 * pointer on the tail descriptor always points to a
+		 * valid descriptor, even when paused after reaching taildesc.
+		 * This way, it is possible to issue additional
+		 * transfers without halting and restarting the channel.
+		 */
+		chan->seg_v = xilinx_axidma_alloc_tx_segment(chan);
+
 	dma_cookie_init(dchan);
+
+	if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
+		/* For AXI DMA resetting once channel will reset the
+		 * other channel as well so enable the interrupts here.
+		 */
+		dma_ctrl_set(chan, XILINX_DMA_REG_DMACR,
+			      XILINX_DMA_DMAXR_ALL_IRQ_MASK);
+	}
+
+	if ((chan->xdev->dma_config->dmatype == XDMA_TYPE_CDMA) && chan->has_sg)
+		dma_ctrl_set(chan, XILINX_DMA_REG_DMACR,
+			     XILINX_CDMA_CR_SGMODE);
+
 	return 0;
 }
 
 /**
- * xilinx_vdma_tx_status - Get VDMA transaction status
+ * xilinx_dma_tx_status - Get DMA transaction status
  * @dchan: DMA channel
  * @cookie: Transaction identifier
  * @txstate: Transaction state
  *
  * Return: DMA transaction status
  */
-static enum dma_status xilinx_vdma_tx_status(struct dma_chan *dchan,
+static enum dma_status xilinx_dma_tx_status(struct dma_chan *dchan,
 					dma_cookie_t cookie,
 					struct dma_tx_state *txstate)
 {
-	return dma_cookie_status(dchan, cookie, txstate);
+	struct xilinx_dma_chan *chan = to_xilinx_chan(dchan);
+	struct xilinx_dma_tx_descriptor *desc;
+	struct xilinx_axidma_tx_segment *segment;
+	struct xilinx_axidma_desc_hw *hw;
+	enum dma_status ret;
+	unsigned long flags;
+	u32 residue = 0;
+
+	ret = dma_cookie_status(dchan, cookie, txstate);
+	if (ret == DMA_COMPLETE || !txstate)
+		return ret;
+
+	if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
+		spin_lock_irqsave(&chan->lock, flags);
+
+		desc = list_last_entry(&chan->active_list,
+				       struct xilinx_dma_tx_descriptor, node);
+		if (chan->has_sg) {
+			list_for_each_entry(segment, &desc->segments, node) {
+				hw = &segment->hw;
+				residue += (hw->control - hw->status) &
+					   XILINX_DMA_MAX_TRANS_LEN;
+			}
+		}
+		spin_unlock_irqrestore(&chan->lock, flags);
+
+		chan->residue = residue;
+		dma_set_residue(txstate, chan->residue);
+	}
+
+	return ret;
 }
 
 /**
- * xilinx_vdma_is_running - Check if VDMA channel is running
- * @chan: Driver specific VDMA channel
+ * xilinx_dma_is_running - Check if DMA channel is running
+ * @chan: Driver specific DMA channel
  *
  * Return: '1' if running, '0' if not.
  */
-static bool xilinx_vdma_is_running(struct xilinx_vdma_chan *chan)
+static bool xilinx_dma_is_running(struct xilinx_dma_chan *chan)
 {
-	return !(vdma_ctrl_read(chan, XILINX_VDMA_REG_DMASR) &
-		 XILINX_VDMA_DMASR_HALTED) &&
-		(vdma_ctrl_read(chan, XILINX_VDMA_REG_DMACR) &
-		 XILINX_VDMA_DMACR_RUNSTOP);
+	return !(dma_ctrl_read(chan, XILINX_DMA_REG_DMASR) &
+		 XILINX_DMA_DMASR_HALTED) &&
+		(dma_ctrl_read(chan, XILINX_DMA_REG_DMACR) &
+		 XILINX_DMA_DMACR_RUNSTOP);
 }
 
 /**
- * xilinx_vdma_is_idle - Check if VDMA channel is idle
- * @chan: Driver specific VDMA channel
+ * xilinx_dma_is_idle - Check if DMA channel is idle
+ * @chan: Driver specific DMA channel
  *
  * Return: '1' if idle, '0' if not.
  */
-static bool xilinx_vdma_is_idle(struct xilinx_vdma_chan *chan)
+static bool xilinx_dma_is_idle(struct xilinx_dma_chan *chan)
 {
-	return vdma_ctrl_read(chan, XILINX_VDMA_REG_DMASR) &
-		XILINX_VDMA_DMASR_IDLE;
+	return dma_ctrl_read(chan, XILINX_DMA_REG_DMASR) &
+		XILINX_DMA_DMASR_IDLE;
 }
 
 /**
- * xilinx_vdma_halt - Halt VDMA channel
- * @chan: Driver specific VDMA channel
+ * xilinx_dma_halt - Halt DMA channel
+ * @chan: Driver specific DMA channel
  */
-static void xilinx_vdma_halt(struct xilinx_vdma_chan *chan)
+static void xilinx_dma_halt(struct xilinx_dma_chan *chan)
 {
 	int err;
 	u32 val;
 
-	vdma_ctrl_clr(chan, XILINX_VDMA_REG_DMACR, XILINX_VDMA_DMACR_RUNSTOP);
+	dma_ctrl_clr(chan, XILINX_DMA_REG_DMACR, XILINX_DMA_DMACR_RUNSTOP);
 
 	/* Wait for the hardware to halt */
-	err = xilinx_vdma_poll_timeout(chan, XILINX_VDMA_REG_DMASR, val,
-				      (val & XILINX_VDMA_DMASR_HALTED), 0,
-				      XILINX_VDMA_LOOP_COUNT);
+	err = xilinx_dma_poll_timeout(chan, XILINX_DMA_REG_DMASR, val,
+				      (val & XILINX_DMA_DMASR_HALTED), 0,
+				      XILINX_DMA_LOOP_COUNT);
 
 	if (err) {
 		dev_err(chan->dev, "Cannot stop channel %p: %x\n",
-			chan, vdma_ctrl_read(chan, XILINX_VDMA_REG_DMASR));
+			chan, dma_ctrl_read(chan, XILINX_DMA_REG_DMASR));
 		chan->err = true;
 	}
-
-	return;
 }
 
 /**
- * xilinx_vdma_start - Start VDMA channel
- * @chan: Driver specific VDMA channel
+ * xilinx_dma_start - Start DMA channel
+ * @chan: Driver specific DMA channel
  */
-static void xilinx_vdma_start(struct xilinx_vdma_chan *chan)
+static void xilinx_dma_start(struct xilinx_dma_chan *chan)
 {
 	int err;
 	u32 val;
 
-	vdma_ctrl_set(chan, XILINX_VDMA_REG_DMACR, XILINX_VDMA_DMACR_RUNSTOP);
+	dma_ctrl_set(chan, XILINX_DMA_REG_DMACR, XILINX_DMA_DMACR_RUNSTOP);
 
 	/* Wait for the hardware to start */
-	err = xilinx_vdma_poll_timeout(chan, XILINX_VDMA_REG_DMASR, val,
-				      !(val & XILINX_VDMA_DMASR_HALTED), 0,
-				      XILINX_VDMA_LOOP_COUNT);
+	err = xilinx_dma_poll_timeout(chan, XILINX_DMA_REG_DMASR, val,
+				      !(val & XILINX_DMA_DMASR_HALTED), 0,
+				      XILINX_DMA_LOOP_COUNT);
 
 	if (err) {
 		dev_err(chan->dev, "Cannot start channel %p: %x\n",
-			chan, vdma_ctrl_read(chan, XILINX_VDMA_REG_DMASR));
+			chan, dma_ctrl_read(chan, XILINX_DMA_REG_DMASR));
 
 		chan->err = true;
 	}
-
-	return;
 }
 
 /**
  * xilinx_vdma_start_transfer - Starts VDMA transfer
  * @chan: Driver specific channel struct pointer
  */
-static void xilinx_vdma_start_transfer(struct xilinx_vdma_chan *chan)
+static void xilinx_vdma_start_transfer(struct xilinx_dma_chan *chan)
 {
 	struct xilinx_vdma_config *config = &chan->config;
-	struct xilinx_vdma_tx_descriptor *desc, *tail_desc;
+	struct xilinx_dma_tx_descriptor *desc, *tail_desc;
 	u32 reg;
 	struct xilinx_vdma_tx_segment *tail_segment;
 
@@ -618,16 +922,16 @@ static void xilinx_vdma_start_transfer(s
 		return;
 
 	desc = list_first_entry(&chan->pending_list,
-				struct xilinx_vdma_tx_descriptor, node);
+				struct xilinx_dma_tx_descriptor, node);
 	tail_desc = list_last_entry(&chan->pending_list,
-				    struct xilinx_vdma_tx_descriptor, node);
+				    struct xilinx_dma_tx_descriptor, node);
 
 	tail_segment = list_last_entry(&tail_desc->segments,
 				       struct xilinx_vdma_tx_segment, node);
 
 	/* If it is SG mode and hardware is busy, cannot submit */
-	if (chan->has_sg && xilinx_vdma_is_running(chan) &&
-	    !xilinx_vdma_is_idle(chan)) {
+	if (chan->has_sg && xilinx_dma_is_running(chan) &&
+	    !xilinx_dma_is_idle(chan)) {
 		dev_dbg(chan->dev, "DMA controller still busy\n");
 		return;
 	}
@@ -637,19 +941,19 @@ static void xilinx_vdma_start_transfer(s
 	 * done, start new transfers
 	 */
 	if (chan->has_sg)
-		vdma_ctrl_write(chan, XILINX_VDMA_REG_CURDESC,
+		dma_ctrl_write(chan, XILINX_DMA_REG_CURDESC,
 				desc->async_tx.phys);
 
 	/* Configure the hardware using info in the config structure */
-	reg = vdma_ctrl_read(chan, XILINX_VDMA_REG_DMACR);
+	reg = dma_ctrl_read(chan, XILINX_DMA_REG_DMACR);
 
 	if (config->frm_cnt_en)
-		reg |= XILINX_VDMA_DMACR_FRAMECNT_EN;
+		reg |= XILINX_DMA_DMACR_FRAMECNT_EN;
 	else
-		reg &= ~XILINX_VDMA_DMACR_FRAMECNT_EN;
+		reg &= ~XILINX_DMA_DMACR_FRAMECNT_EN;
 
 	/* Configure channel to allow number frame buffers */
-	vdma_ctrl_write(chan, XILINX_VDMA_REG_FRMSTORE,
+	dma_ctrl_write(chan, XILINX_DMA_REG_FRMSTORE,
 			chan->desc_pendingcount);
 
 	/*
@@ -657,45 +961,53 @@ static void xilinx_vdma_start_transfer(s
 	 * In direct register mode, if not parking, enable circular mode
 	 */
 	if (chan->has_sg || !config->park)
-		reg |= XILINX_VDMA_DMACR_CIRC_EN;
+		reg |= XILINX_DMA_DMACR_CIRC_EN;
 
 	if (config->park)
-		reg &= ~XILINX_VDMA_DMACR_CIRC_EN;
+		reg &= ~XILINX_DMA_DMACR_CIRC_EN;
 
-	vdma_ctrl_write(chan, XILINX_VDMA_REG_DMACR, reg);
+	dma_ctrl_write(chan, XILINX_DMA_REG_DMACR, reg);
 
 	if (config->park && (config->park_frm >= 0) &&
 			(config->park_frm < chan->num_frms)) {
 		if (chan->direction == DMA_MEM_TO_DEV)
-			vdma_write(chan, XILINX_VDMA_REG_PARK_PTR,
+			dma_write(chan, XILINX_DMA_REG_PARK_PTR,
 				config->park_frm <<
-					XILINX_VDMA_PARK_PTR_RD_REF_SHIFT);
+					XILINX_DMA_PARK_PTR_RD_REF_SHIFT);
 		else
-			vdma_write(chan, XILINX_VDMA_REG_PARK_PTR,
+			dma_write(chan, XILINX_DMA_REG_PARK_PTR,
 				config->park_frm <<
-					XILINX_VDMA_PARK_PTR_WR_REF_SHIFT);
+					XILINX_DMA_PARK_PTR_WR_REF_SHIFT);
 	}
 
 	/* Start the hardware */
-	xilinx_vdma_start(chan);
+	xilinx_dma_start(chan);
 
 	if (chan->err)
 		return;
 
 	/* Start the transfer */
 	if (chan->has_sg) {
-		vdma_ctrl_write(chan, XILINX_VDMA_REG_TAILDESC,
+		dma_ctrl_write(chan, XILINX_DMA_REG_TAILDESC,
 				tail_segment->phys);
 	} else {
 		struct xilinx_vdma_tx_segment *segment, *last = NULL;
 		int i = 0;
 
-		list_for_each_entry(desc, &chan->pending_list, node) {
-			segment = list_first_entry(&desc->segments,
-					   struct xilinx_vdma_tx_segment, node);
-			vdma_desc_write(chan,
+		if (chan->desc_submitcount < chan->num_frms)
+			i = chan->desc_submitcount;
+
+		list_for_each_entry(segment, &desc->segments, node) {
+			if (chan->ext_addr)
+				vdma_desc_write_64(chan,
+					XILINX_VDMA_REG_START_ADDRESS_64(i++),
+					segment->hw.buf_addr,
+					segment->hw.buf_addr_msb);
+			else
+				vdma_desc_write(chan,
 					XILINX_VDMA_REG_START_ADDRESS(i++),
 					segment->hw.buf_addr);
+
 			last = segment;
 		}
 
@@ -703,10 +1015,79 @@ static void xilinx_vdma_start_transfer(s
 			return;
 
 		/* HW expects these parameters to be same for one transaction */
-		vdma_desc_write(chan, XILINX_VDMA_REG_HSIZE, last->hw.hsize);
-		vdma_desc_write(chan, XILINX_VDMA_REG_FRMDLY_STRIDE,
+		vdma_desc_write(chan, XILINX_DMA_REG_HSIZE, last->hw.hsize);
+		vdma_desc_write(chan, XILINX_DMA_REG_FRMDLY_STRIDE,
 				last->hw.stride);
-		vdma_desc_write(chan, XILINX_VDMA_REG_VSIZE, last->hw.vsize);
+		vdma_desc_write(chan, XILINX_DMA_REG_VSIZE, last->hw.vsize);
+	}
+
+	if (!chan->has_sg) {
+		list_del(&desc->node);
+		list_add_tail(&desc->node, &chan->active_list);
+		chan->desc_submitcount++;
+		chan->desc_pendingcount--;
+		if (chan->desc_submitcount == chan->num_frms)
+			chan->desc_submitcount = 0;
+	} else {
+		list_splice_tail_init(&chan->pending_list, &chan->active_list);
+		chan->desc_pendingcount = 0;
+	}
+}
+
+/**
+ * xilinx_cdma_start_transfer - Starts cdma transfer
+ * @chan: Driver specific channel struct pointer
+ */
+static void xilinx_cdma_start_transfer(struct xilinx_dma_chan *chan)
+{
+	struct xilinx_dma_tx_descriptor *head_desc, *tail_desc;
+	struct xilinx_cdma_tx_segment *tail_segment;
+	u32 ctrl_reg = dma_read(chan, XILINX_DMA_REG_DMACR);
+
+	if (chan->err)
+		return;
+
+	if (list_empty(&chan->pending_list))
+		return;
+
+	head_desc = list_first_entry(&chan->pending_list,
+				     struct xilinx_dma_tx_descriptor, node);
+	tail_desc = list_last_entry(&chan->pending_list,
+				    struct xilinx_dma_tx_descriptor, node);
+	tail_segment = list_last_entry(&tail_desc->segments,
+				       struct xilinx_cdma_tx_segment, node);
+
+	if (chan->desc_pendingcount <= XILINX_DMA_COALESCE_MAX) {
+		ctrl_reg &= ~XILINX_DMA_CR_COALESCE_MAX;
+		ctrl_reg |= chan->desc_pendingcount <<
+				XILINX_DMA_CR_COALESCE_SHIFT;
+		dma_ctrl_write(chan, XILINX_DMA_REG_DMACR, ctrl_reg);
+	}
+
+	if (chan->has_sg) {
+		dma_ctrl_write(chan, XILINX_DMA_REG_CURDESC,
+			   head_desc->async_tx.phys);
+
+		/* Update tail ptr register which will start the transfer */
+		dma_ctrl_write(chan, XILINX_DMA_REG_TAILDESC,
+			       tail_segment->phys);
+	} else {
+		/* In simple mode */
+		struct xilinx_cdma_tx_segment *segment;
+		struct xilinx_cdma_desc_hw *hw;
+
+		segment = list_first_entry(&head_desc->segments,
+					   struct xilinx_cdma_tx_segment,
+					   node);
+
+		hw = &segment->hw;
+
+		dma_ctrl_write(chan, XILINX_CDMA_REG_SRCADDR, hw->src_addr);
+		dma_ctrl_write(chan, XILINX_CDMA_REG_DSTADDR, hw->dest_addr);
+
+		/* Start the transfer */
+		dma_ctrl_write(chan, XILINX_DMA_REG_BTT,
+				hw->control & XILINX_DMA_MAX_TRANS_LEN);
 	}
 
 	list_splice_tail_init(&chan->pending_list, &chan->active_list);
@@ -714,28 +1095,113 @@ static void xilinx_vdma_start_transfer(s
 }
 
 /**
- * xilinx_vdma_issue_pending - Issue pending transactions
+ * xilinx_dma_start_transfer - Starts DMA transfer
+ * @chan: Driver specific channel struct pointer
+ */
+static void xilinx_dma_start_transfer(struct xilinx_dma_chan *chan)
+{
+	struct xilinx_dma_tx_descriptor *head_desc, *tail_desc;
+	struct xilinx_axidma_tx_segment *tail_segment, *old_head, *new_head;
+	u32 reg;
+
+	if (chan->err)
+		return;
+
+	if (list_empty(&chan->pending_list))
+		return;
+
+	/* If it is SG mode and hardware is busy, cannot submit */
+	if (chan->has_sg && xilinx_dma_is_running(chan) &&
+	    !xilinx_dma_is_idle(chan)) {
+		dev_dbg(chan->dev, "DMA controller still busy\n");
+		return;
+	}
+
+	head_desc = list_first_entry(&chan->pending_list,
+				     struct xilinx_dma_tx_descriptor, node);
+	tail_desc = list_last_entry(&chan->pending_list,
+				    struct xilinx_dma_tx_descriptor, node);
+	tail_segment = list_last_entry(&tail_desc->segments,
+				       struct xilinx_axidma_tx_segment, node);
+
+	old_head = list_first_entry(&head_desc->segments,
+				struct xilinx_axidma_tx_segment, node);
+	new_head = chan->seg_v;
+	/* Copy Buffer Descriptor fields. */
+	new_head->hw = old_head->hw;
+
+	/* Swap and save new reserve */
+	list_replace_init(&old_head->node, &new_head->node);
+	chan->seg_v = old_head;
+
+	tail_segment->hw.next_desc = chan->seg_v->phys;
+	head_desc->async_tx.phys = new_head->phys;
+
+	reg = dma_ctrl_read(chan, XILINX_DMA_REG_DMACR);
+
+	if (chan->desc_pendingcount <= XILINX_DMA_COALESCE_MAX) {
+		reg &= ~XILINX_DMA_CR_COALESCE_MAX;
+		reg |= chan->desc_pendingcount <<
+				  XILINX_DMA_CR_COALESCE_SHIFT;
+		dma_ctrl_write(chan, XILINX_DMA_REG_DMACR, reg);
+	}
+
+	if (chan->has_sg)
+		dma_ctrl_write(chan, XILINX_DMA_REG_CURDESC,
+			       head_desc->async_tx.phys);
+
+	xilinx_dma_start(chan);
+
+	if (chan->err)
+		return;
+
+	/* Start the transfer */
+	if (chan->has_sg) {
+		dma_ctrl_write(chan, XILINX_DMA_REG_TAILDESC,
+			       tail_segment->phys);
+	} else {
+		struct xilinx_axidma_tx_segment *segment;
+		struct xilinx_axidma_desc_hw *hw;
+
+		segment = list_first_entry(&head_desc->segments,
+					   struct xilinx_axidma_tx_segment,
+					   node);
+		hw = &segment->hw;
+
+		dma_ctrl_write(chan, XILINX_DMA_REG_SRCDSTADDR, hw->buf_addr);
+
+		/* Start the transfer */
+		dma_ctrl_write(chan, XILINX_DMA_REG_BTT,
+			       hw->control & XILINX_DMA_MAX_TRANS_LEN);
+	}
+
+	list_splice_tail_init(&chan->pending_list, &chan->active_list);
+	chan->desc_pendingcount = 0;
+}
+
+/**
+ * xilinx_dma_issue_pending - Issue pending transactions
  * @dchan: DMA channel
  */
-static void xilinx_vdma_issue_pending(struct dma_chan *dchan)
+static void xilinx_dma_issue_pending(struct dma_chan *dchan)
 {
-	struct xilinx_vdma_chan *chan = to_xilinx_chan(dchan);
+	struct xilinx_dma_chan *chan = to_xilinx_chan(dchan);
 	unsigned long flags;
 
 	spin_lock_irqsave(&chan->lock, flags);
-	xilinx_vdma_start_transfer(chan);
+	chan->start_transfer(chan);
 	spin_unlock_irqrestore(&chan->lock, flags);
 }
 
 /**
- * xilinx_vdma_complete_descriptor - Mark the active descriptor as complete
+ * xilinx_dma_complete_descriptor - Mark the active descriptor as complete
  * @chan : xilinx DMA channel
  *
  * CONTEXT: hardirq
  */
-static void xilinx_vdma_complete_descriptor(struct xilinx_vdma_chan *chan)
+static void xilinx_dma_complete_descriptor(struct xilinx_dma_chan *chan)
 {
-	struct xilinx_vdma_tx_descriptor *desc, *next;
+	struct xilinx_dma_tx_descriptor *desc, *next;
 
 	/* This function was invoked with lock held */
 	if (list_empty(&chan->active_list))
@@ -749,27 +1215,27 @@ static void xilinx_vdma_complete_descrip
 }
 
 /**
- * xilinx_vdma_reset - Reset VDMA channel
- * @chan: Driver specific VDMA channel
+ * xilinx_dma_reset - Reset DMA channel
+ * @chan: Driver specific DMA channel
  *
  * Return: '0' on success and failure value on error
  */
-static int xilinx_vdma_reset(struct xilinx_vdma_chan *chan)
+static int xilinx_dma_reset(struct xilinx_dma_chan *chan)
 {
 	int err;
 	u32 tmp;
 
-	vdma_ctrl_set(chan, XILINX_VDMA_REG_DMACR, XILINX_VDMA_DMACR_RESET);
+	dma_ctrl_set(chan, XILINX_DMA_REG_DMACR, XILINX_DMA_DMACR_RESET);
 
 	/* Wait for the hardware to finish reset */
-	err = xilinx_vdma_poll_timeout(chan, XILINX_VDMA_REG_DMACR, tmp,
-				      !(tmp & XILINX_VDMA_DMACR_RESET), 0,
-				      XILINX_VDMA_LOOP_COUNT);
+	err = xilinx_dma_poll_timeout(chan, XILINX_DMA_REG_DMACR, tmp,
+				      !(tmp & XILINX_DMA_DMACR_RESET), 0,
+				      XILINX_DMA_LOOP_COUNT);
 
 	if (err) {
 		dev_err(chan->dev, "reset timeout, cr %x, sr %x\n",
-			vdma_ctrl_read(chan, XILINX_VDMA_REG_DMACR),
-			vdma_ctrl_read(chan, XILINX_VDMA_REG_DMASR));
+			dma_ctrl_read(chan, XILINX_DMA_REG_DMACR),
+			dma_ctrl_read(chan, XILINX_DMA_REG_DMASR));
 		return -ETIMEDOUT;
 	}
 
@@ -779,48 +1245,48 @@ static int xilinx_vdma_reset(struct xili
 }
 
 /**
- * xilinx_vdma_chan_reset - Reset VDMA channel and enable interrupts
- * @chan: Driver specific VDMA channel
+ * xilinx_dma_chan_reset - Reset DMA channel and enable interrupts
+ * @chan: Driver specific DMA channel
  *
  * Return: '0' on success and failure value on error
  */
-static int xilinx_vdma_chan_reset(struct xilinx_vdma_chan *chan)
+static int xilinx_dma_chan_reset(struct xilinx_dma_chan *chan)
 {
 	int err;
 
 	/* Reset VDMA */
-	err = xilinx_vdma_reset(chan);
+	err = xilinx_dma_reset(chan);
 	if (err)
 		return err;
 
 	/* Enable interrupts */
-	vdma_ctrl_set(chan, XILINX_VDMA_REG_DMACR,
-		      XILINX_VDMA_DMAXR_ALL_IRQ_MASK);
+	dma_ctrl_set(chan, XILINX_DMA_REG_DMACR,
+		      XILINX_DMA_DMAXR_ALL_IRQ_MASK);
 
 	return 0;
 }
 
 /**
- * xilinx_vdma_irq_handler - VDMA Interrupt handler
+ * xilinx_dma_irq_handler - DMA Interrupt handler
  * @irq: IRQ number
- * @data: Pointer to the Xilinx VDMA channel structure
+ * @data: Pointer to the Xilinx DMA channel structure
  *
  * Return: IRQ_HANDLED/IRQ_NONE
  */
-static irqreturn_t xilinx_vdma_irq_handler(int irq, void *data)
+static irqreturn_t xilinx_dma_irq_handler(int irq, void *data)
 {
-	struct xilinx_vdma_chan *chan = data;
+	struct xilinx_dma_chan *chan = data;
 	u32 status;
 
 	/* Read the status and ack the interrupts. */
-	status = vdma_ctrl_read(chan, XILINX_VDMA_REG_DMASR);
-	if (!(status & XILINX_VDMA_DMAXR_ALL_IRQ_MASK))
+	status = dma_ctrl_read(chan, XILINX_DMA_REG_DMASR);
+	if (!(status & XILINX_DMA_DMAXR_ALL_IRQ_MASK))
 		return IRQ_NONE;
 
-	vdma_ctrl_write(chan, XILINX_VDMA_REG_DMASR,
-			status & XILINX_VDMA_DMAXR_ALL_IRQ_MASK);
+	dma_ctrl_write(chan, XILINX_DMA_REG_DMASR,
+			status & XILINX_DMA_DMAXR_ALL_IRQ_MASK);
 
-	if (status & XILINX_VDMA_DMASR_ERR_IRQ) {
+	if (status & XILINX_DMA_DMASR_ERR_IRQ) {
 		/*
 		 * An error occurred. If C_FLUSH_ON_FSYNC is enabled and the
 		 * error is recoverable, ignore it. Otherwise flag the error.
@@ -828,22 +1294,23 @@ static irqreturn_t xilinx_vdma_irq_handl
 		 * Only recoverable errors can be cleared in the DMASR register,
 		 * make sure not to write to other error bits to 1.
 		 */
-		u32 errors = status & XILINX_VDMA_DMASR_ALL_ERR_MASK;
-		vdma_ctrl_write(chan, XILINX_VDMA_REG_DMASR,
-				errors & XILINX_VDMA_DMASR_ERR_RECOVER_MASK);
+		u32 errors = status & XILINX_DMA_DMASR_ALL_ERR_MASK;
+
+		dma_ctrl_write(chan, XILINX_DMA_REG_DMASR,
+				errors & XILINX_DMA_DMASR_ERR_RECOVER_MASK);
 
 		if (!chan->flush_on_fsync ||
-		    (errors & ~XILINX_VDMA_DMASR_ERR_RECOVER_MASK)) {
+		    (errors & ~XILINX_DMA_DMASR_ERR_RECOVER_MASK)) {
 			dev_err(chan->dev,
 				"Channel %p has errors %x, cdr %x tdr %x\n",
 				chan, errors,
-				vdma_ctrl_read(chan, XILINX_VDMA_REG_CURDESC),
-				vdma_ctrl_read(chan, XILINX_VDMA_REG_TAILDESC));
+				dma_ctrl_read(chan, XILINX_DMA_REG_CURDESC),
+				dma_ctrl_read(chan, XILINX_DMA_REG_TAILDESC));
 			chan->err = true;
 		}
 	}
 
-	if (status & XILINX_VDMA_DMASR_DLY_CNT_IRQ) {
+	if (status & XILINX_DMA_DMASR_DLY_CNT_IRQ) {
 		/*
 		 * Device takes too long to do the transfer when user requires
 		 * responsiveness.
@@ -851,10 +1318,10 @@ static irqreturn_t xilinx_vdma_irq_handl
 		dev_dbg(chan->dev, "Inter-packet latency too long\n");
 	}
 
-	if (status & XILINX_VDMA_DMASR_FRM_CNT_IRQ) {
+	if (status & XILINX_DMA_DMASR_FRM_CNT_IRQ) {
 		spin_lock(&chan->lock);
-		xilinx_vdma_complete_descriptor(chan);
-		xilinx_vdma_start_transfer(chan);
+		xilinx_dma_complete_descriptor(chan);
+		chan->start_transfer(chan);
 		spin_unlock(&chan->lock);
 	}
 
@@ -867,11 +1334,13 @@ static irqreturn_t xilinx_vdma_irq_handl
  * @chan: Driver specific dma channel
  * @desc: dma transaction descriptor
  */
-static void append_desc_queue(struct xilinx_vdma_chan *chan,
-			      struct xilinx_vdma_tx_descriptor *desc)
+static void append_desc_queue(struct xilinx_dma_chan *chan,
+			      struct xilinx_dma_tx_descriptor *desc)
 {
 	struct xilinx_vdma_tx_segment *tail_segment;
-	struct xilinx_vdma_tx_descriptor *tail_desc;
+	struct xilinx_dma_tx_descriptor *tail_desc;
+	struct xilinx_axidma_tx_segment *axidma_tail_segment;
+	struct xilinx_cdma_tx_segment *cdma_tail_segment;
 
 	if (list_empty(&chan->pending_list))
 		goto append;
@@ -881,10 +1350,23 @@ static void append_desc_queue(struct xil
 	 * that already exists in memory.
 	 */
 	tail_desc = list_last_entry(&chan->pending_list,
-				    struct xilinx_vdma_tx_descriptor, node);
-	tail_segment = list_last_entry(&tail_desc->segments,
-				       struct xilinx_vdma_tx_segment, node);
-	tail_segment->hw.next_desc = (u32)desc->async_tx.phys;
+				    struct xilinx_dma_tx_descriptor, node);
+	if (chan->xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
+		tail_segment = list_last_entry(&tail_desc->segments,
+					       struct xilinx_vdma_tx_segment,
+					       node);
+		tail_segment->hw.next_desc = (u32)desc->async_tx.phys;
+	} else if (chan->xdev->dma_config->dmatype == XDMA_TYPE_CDMA) {
+		cdma_tail_segment = list_last_entry(&tail_desc->segments,
+						struct xilinx_cdma_tx_segment,
+						node);
+		cdma_tail_segment->hw.next_desc = (u32)desc->async_tx.phys;
+	} else {
+		axidma_tail_segment = list_last_entry(&tail_desc->segments,
+					       struct xilinx_axidma_tx_segment,
+					       node);
+		axidma_tail_segment->hw.next_desc = (u32)desc->async_tx.phys;
+	}
 
 	/*
 	 * Add the software descriptor and all children to the list
@@ -894,22 +1376,23 @@ append:
 	list_add_tail(&desc->node, &chan->pending_list);
 	chan->desc_pendingcount++;
 
-	if (unlikely(chan->desc_pendingcount > chan->num_frms)) {
+	if (chan->has_sg && (chan->xdev->dma_config->dmatype == XDMA_TYPE_VDMA)
+	    && unlikely(chan->desc_pendingcount > chan->num_frms)) {
 		dev_dbg(chan->dev, "desc pendingcount is too high\n");
 		chan->desc_pendingcount = chan->num_frms;
 	}
 }
 
 /**
- * xilinx_vdma_tx_submit - Submit DMA transaction
+ * xilinx_dma_tx_submit - Submit DMA transaction
  * @tx: Async transaction descriptor
  *
  * Return: cookie value on success and failure value on error
  */
-static dma_cookie_t xilinx_vdma_tx_submit(struct dma_async_tx_descriptor *tx)
+static dma_cookie_t xilinx_dma_tx_submit(struct dma_async_tx_descriptor *tx)
 {
-	struct xilinx_vdma_tx_descriptor *desc = to_vdma_tx_descriptor(tx);
-	struct xilinx_vdma_chan *chan = to_xilinx_chan(tx->chan);
+	struct xilinx_dma_tx_descriptor *desc = to_dma_tx_descriptor(tx);
+	struct xilinx_dma_chan *chan = to_xilinx_chan(tx->chan);
 	dma_cookie_t cookie;
 	unsigned long flags;
 	int err;
@@ -919,7 +1402,7 @@ static dma_cookie_t xilinx_vdma_tx_submi
 		 * If reset fails, need to hard reset the system.
 		 * Channel is no longer functional
 		 */
-		err = xilinx_vdma_chan_reset(chan);
+		err = xilinx_dma_chan_reset(chan);
 		if (err < 0)
 			return err;
 	}
@@ -950,8 +1433,8 @@ xilinx_vdma_dma_prep_interleaved(struct
 				 struct dma_interleaved_template *xt,
 				 unsigned long flags)
 {
-	struct xilinx_vdma_chan *chan = to_xilinx_chan(dchan);
-	struct xilinx_vdma_tx_descriptor *desc;
+	struct xilinx_dma_chan *chan = to_xilinx_chan(dchan);
+	struct xilinx_dma_tx_descriptor *desc;
 	struct xilinx_vdma_tx_segment *segment, *prev = NULL;
 	struct xilinx_vdma_desc_hw *hw;
 
@@ -965,12 +1448,12 @@ xilinx_vdma_dma_prep_interleaved(struct
 		return NULL;
 
 	/* Allocate a transaction descriptor. */
-	desc = xilinx_vdma_alloc_tx_descriptor(chan);
+	desc = xilinx_dma_alloc_tx_descriptor(chan);
 	if (!desc)
 		return NULL;
 
 	dma_async_tx_descriptor_init(&desc->async_tx, &chan->common);
-	desc->async_tx.tx_submit = xilinx_vdma_tx_submit;
+	desc->async_tx.tx_submit = xilinx_dma_tx_submit;
 	async_tx_ack(&desc->async_tx);
 
 	/* Allocate the link descriptor from DMA pool */
@@ -983,14 +1466,25 @@ xilinx_vdma_dma_prep_interleaved(struct
 	hw->vsize = xt->numf;
 	hw->hsize = xt->sgl[0].size;
 	hw->stride = (xt->sgl[0].icg + xt->sgl[0].size) <<
-			XILINX_VDMA_FRMDLY_STRIDE_STRIDE_SHIFT;
+			XILINX_DMA_FRMDLY_STRIDE_STRIDE_SHIFT;
 	hw->stride |= chan->config.frm_dly <<
-			XILINX_VDMA_FRMDLY_STRIDE_FRMDLY_SHIFT;
+			XILINX_DMA_FRMDLY_STRIDE_FRMDLY_SHIFT;
 
-	if (xt->dir != DMA_MEM_TO_DEV)
-		hw->buf_addr = xt->dst_start;
-	else
-		hw->buf_addr = xt->src_start;
+	if (xt->dir != DMA_MEM_TO_DEV) {
+		if (chan->ext_addr) {
+			hw->buf_addr = lower_32_bits(xt->dst_start);
+			hw->buf_addr_msb = upper_32_bits(xt->dst_start);
+		} else {
+			hw->buf_addr = xt->dst_start;
+		}
+	} else {
+		if (chan->ext_addr) {
+			hw->buf_addr = lower_32_bits(xt->src_start);
+			hw->buf_addr_msb = upper_32_bits(xt->src_start);
+		} else {
+			hw->buf_addr = xt->src_start;
+		}
+	}
 
 	/* Insert the segment into the descriptor segments list. */
 	list_add_tail(&segment->node, &desc->segments);
@@ -1005,29 +1499,194 @@ xilinx_vdma_dma_prep_interleaved(struct
 	return &desc->async_tx;
 
 error:
-	xilinx_vdma_free_tx_descriptor(chan, desc);
+	xilinx_dma_free_tx_descriptor(chan, desc);
 	return NULL;
 }
 
 /**
- * xilinx_vdma_terminate_all - Halt the channel and free descriptors
- * @chan: Driver specific VDMA Channel pointer
+ * xilinx_cdma_prep_memcpy - prepare descriptors for a memcpy transaction
+ * @dchan: DMA channel
+ * @dma_dst: destination address
+ * @dma_src: source address
+ * @len: transfer length
+ * @flags: transfer ack flags
+ *
+ * Return: Async transaction descriptor on success and NULL on failure
  */
-static int xilinx_vdma_terminate_all(struct dma_chan *dchan)
+static struct dma_async_tx_descriptor *
+xilinx_cdma_prep_memcpy(struct dma_chan *dchan, dma_addr_t dma_dst,
+			dma_addr_t dma_src, size_t len, unsigned long flags)
 {
-	struct xilinx_vdma_chan *chan = to_xilinx_chan(dchan);
+	struct xilinx_dma_chan *chan = to_xilinx_chan(dchan);
+	struct xilinx_dma_tx_descriptor *desc;
+	struct xilinx_cdma_tx_segment *segment, *prev;
+	struct xilinx_cdma_desc_hw *hw;
+
+	if (!len || len > XILINX_DMA_MAX_TRANS_LEN)
+		return NULL;
+
+	desc = xilinx_dma_alloc_tx_descriptor(chan);
+	if (!desc)
+		return NULL;
+
+	dma_async_tx_descriptor_init(&desc->async_tx, &chan->common);
+	desc->async_tx.tx_submit = xilinx_dma_tx_submit;
+
+	/* Allocate the link descriptor from DMA pool */
+	segment = xilinx_cdma_alloc_tx_segment(chan);
+	if (!segment)
+		goto error;
+
+	hw = &segment->hw;
+	hw->control = len;
+	hw->src_addr = dma_src;
+	hw->dest_addr = dma_dst;
+
+	/* Fill the previous next descriptor with current */
+	prev = list_last_entry(&desc->segments,
+			       struct xilinx_cdma_tx_segment, node);
+	prev->hw.next_desc = segment->phys;
+
+	/* Insert the segment into the descriptor segments list. */
+	list_add_tail(&segment->node, &desc->segments);
+
+	prev = segment;
+
+	/* Link the last hardware descriptor with the first. */
+	segment = list_first_entry(&desc->segments,
+				struct xilinx_cdma_tx_segment, node);
+	desc->async_tx.phys = segment->phys;
+	prev->hw.next_desc = segment->phys;
+
+	return &desc->async_tx;
+
+error:
+	xilinx_dma_free_tx_descriptor(chan, desc);
+	return NULL;
+}
+
+/**
+ * xilinx_dma_prep_slave_sg - prepare descriptors for a DMA_SLAVE transaction
+ * @dchan: DMA channel
+ * @sgl: scatterlist to transfer to/from
+ * @sg_len: number of entries in @scatterlist
+ * @direction: DMA direction
+ * @flags: transfer ack flags
+ * @context: APP words of the descriptor
+ *
+ * Return: Async transaction descriptor on success and NULL on failure
+ */
+static struct dma_async_tx_descriptor *xilinx_dma_prep_slave_sg(
+	struct dma_chan *dchan, struct scatterlist *sgl, unsigned int sg_len,
+	enum dma_transfer_direction direction, unsigned long flags,
+	void *context)
+{
+	struct xilinx_dma_chan *chan = to_xilinx_chan(dchan);
+	struct xilinx_dma_tx_descriptor *desc;
+	struct xilinx_axidma_tx_segment *segment = NULL, *prev = NULL;
+	u32 *app_w = (u32 *)context;
+	struct scatterlist *sg;
+	size_t copy;
+	size_t sg_used;
+	unsigned int i;
+
+	if (!is_slave_direction(direction))
+		return NULL;
+
+	/* Allocate a transaction descriptor. */
+	desc = xilinx_dma_alloc_tx_descriptor(chan);
+	if (!desc)
+		return NULL;
+
+	dma_async_tx_descriptor_init(&desc->async_tx, &chan->common);
+	desc->async_tx.tx_submit = xilinx_dma_tx_submit;
+
+	/* Build transactions using information in the scatter gather list */
+	for_each_sg(sgl, sg, sg_len, i) {
+		sg_used = 0;
+
+		/* Loop until the entire scatterlist entry is used */
+		while (sg_used < sg_dma_len(sg)) {
+			struct xilinx_axidma_desc_hw *hw;
+
+			/* Get a free segment */
+			segment = xilinx_axidma_alloc_tx_segment(chan);
+			if (!segment)
+				goto error;
+
+			/*
+			 * Calculate the maximum number of bytes to transfer,
+			 * making sure it is less than the hw limit
+			 */
+			copy = min_t(size_t, sg_dma_len(sg) - sg_used,
+				     XILINX_DMA_MAX_TRANS_LEN);
+			hw = &segment->hw;
+
+			/* Fill in the descriptor */
+			hw->buf_addr = sg_dma_address(sg) + sg_used;
+
+			hw->control = copy;
+
+			if (chan->direction == DMA_MEM_TO_DEV) {
+				if (app_w)
+					memcpy(hw->app, app_w, sizeof(u32) *
+					       XILINX_DMA_NUM_APP_WORDS);
+			}
+
+			if (prev)
+				prev->hw.next_desc = segment->phys;
+
+			prev = segment;
+			sg_used += copy;
+
+			/*
+			 * Insert the segment into the descriptor segments
+			 * list.
+			 */
+			list_add_tail(&segment->node, &desc->segments);
+		}
+	}
+
+	segment = list_first_entry(&desc->segments,
+				   struct xilinx_axidma_tx_segment, node);
+	desc->async_tx.phys = segment->phys;
+	prev->hw.next_desc = segment->phys;
+
+	/* For the last DMA_MEM_TO_DEV transfer, set EOP */
+	if (chan->direction == DMA_MEM_TO_DEV) {
+		segment->hw.control |= XILINX_DMA_BD_SOP;
+		segment = list_last_entry(&desc->segments,
+					  struct xilinx_axidma_tx_segment,
+					  node);
+		segment->hw.control |= XILINX_DMA_BD_EOP;
+	}
+
+	return &desc->async_tx;
+
+error:
+	xilinx_dma_free_tx_descriptor(chan, desc);
+	return NULL;
+}
+
+/**
+ * xilinx_dma_terminate_all - Halt the channel and free descriptors
+ * @chan: Driver specific DMA Channel pointer
+ */
+static int xilinx_dma_terminate_all(struct dma_chan *dchan)
+{
+	struct xilinx_dma_chan *chan = to_xilinx_chan(dchan);
 
 	/* Halt the DMA engine */
-	xilinx_vdma_halt(chan);
+	xilinx_dma_halt(chan);
 
 	/* Remove and free all of the descriptors in the lists */
-	xilinx_vdma_free_descriptors(chan);
+	xilinx_dma_free_descriptors(chan);
 
 	return 0;
 }
 
 /**
- * xilinx_vdma_channel_set_config - Configure VDMA channel
+ * xilinx_dma_channel_set_config - Configure VDMA channel
  * Run-time configuration for Axi VDMA, supports:
  * . halt the channel
  * . configure interrupt coalescing and inter-packet delay threshold
@@ -1042,13 +1701,13 @@ static int xilinx_vdma_terminate_all(str
 int xilinx_vdma_channel_set_config(struct dma_chan *dchan,
 					struct xilinx_vdma_config *cfg)
 {
-	struct xilinx_vdma_chan *chan = to_xilinx_chan(dchan);
+	struct xilinx_dma_chan *chan = to_xilinx_chan(dchan);
 	u32 dmacr;
 
 	if (cfg->reset)
-		return xilinx_vdma_chan_reset(chan);
+		return xilinx_dma_chan_reset(chan);
 
-	dmacr = vdma_ctrl_read(chan, XILINX_VDMA_REG_DMACR);
+	dmacr = dma_ctrl_read(chan, XILINX_DMA_REG_DMACR);
 
 	chan->config.frm_dly = cfg->frm_dly;
 	chan->config.park = cfg->park;
@@ -1058,8 +1717,8 @@ int xilinx_vdma_channel_set_config(struc
 	chan->config.master = cfg->master;
 
 	if (cfg->gen_lock && chan->genlock) {
-		dmacr |= XILINX_VDMA_DMACR_GENLOCK_EN;
-		dmacr |= cfg->master << XILINX_VDMA_DMACR_MASTER_SHIFT;
+		dmacr |= XILINX_DMA_DMACR_GENLOCK_EN;
+		dmacr |= cfg->master << XILINX_DMA_DMACR_MASTER_SHIFT;
 	}
 
 	chan->config.frm_cnt_en = cfg->frm_cnt_en;
@@ -1071,21 +1730,21 @@ int xilinx_vdma_channel_set_config(struc
 	chan->config.coalesc = cfg->coalesc;
 	chan->config.delay = cfg->delay;
 
-	if (cfg->coalesc <= XILINX_VDMA_DMACR_FRAME_COUNT_MAX) {
-		dmacr |= cfg->coalesc << XILINX_VDMA_DMACR_FRAME_COUNT_SHIFT;
+	if (cfg->coalesc <= XILINX_DMA_DMACR_FRAME_COUNT_MAX) {
+		dmacr |= cfg->coalesc << XILINX_DMA_DMACR_FRAME_COUNT_SHIFT;
 		chan->config.coalesc = cfg->coalesc;
 	}
 
-	if (cfg->delay <= XILINX_VDMA_DMACR_DELAY_MAX) {
-		dmacr |= cfg->delay << XILINX_VDMA_DMACR_DELAY_SHIFT;
+	if (cfg->delay <= XILINX_DMA_DMACR_DELAY_MAX) {
+		dmacr |= cfg->delay << XILINX_DMA_DMACR_DELAY_SHIFT;
 		chan->config.delay = cfg->delay;
 	}
 
 	/* FSync Source selection */
-	dmacr &= ~XILINX_VDMA_DMACR_FSYNCSRC_MASK;
-	dmacr |= cfg->ext_fsync << XILINX_VDMA_DMACR_FSYNCSRC_SHIFT;
+	dmacr &= ~XILINX_DMA_DMACR_FSYNCSRC_MASK;
+	dmacr |= cfg->ext_fsync << XILINX_DMA_DMACR_FSYNCSRC_SHIFT;
 
-	vdma_ctrl_write(chan, XILINX_VDMA_REG_DMACR, dmacr);
+	dma_ctrl_write(chan, XILINX_DMA_REG_DMACR, dmacr);
 
 	return 0;
 }
@@ -1096,14 +1755,14 @@ EXPORT_SYMBOL(xilinx_vdma_channel_set_co
  */
 
 /**
- * xilinx_vdma_chan_remove - Per Channel remove function
- * @chan: Driver specific VDMA channel
+ * xilinx_dma_chan_remove - Per Channel remove function
+ * @chan: Driver specific DMA channel
  */
-static void xilinx_vdma_chan_remove(struct xilinx_vdma_chan *chan)
+static void xilinx_dma_chan_remove(struct xilinx_dma_chan *chan)
 {
 	/* Disable all interrupts */
-	vdma_ctrl_clr(chan, XILINX_VDMA_REG_DMACR,
-		      XILINX_VDMA_DMAXR_ALL_IRQ_MASK);
+	dma_ctrl_clr(chan, XILINX_DMA_REG_DMACR,
+		      XILINX_DMA_DMAXR_ALL_IRQ_MASK);
 
 	if (chan->irq > 0)
 		free_irq(chan->irq, chan);
@@ -1113,8 +1772,197 @@ static void xilinx_vdma_chan_remove(stru
 	list_del(&chan->common.device_node);
 }
 
+static int axidma_clk_init(struct platform_device *pdev, struct clk **axi_clk,
+			    struct clk **tx_clk, struct clk **rx_clk,
+			    struct clk **sg_clk, struct clk **tmp_clk)
+{
+	int err;
+
+	*tmp_clk = NULL;
+
+	*axi_clk = devm_clk_get(&pdev->dev, "s_axi_lite_aclk");
+	if (IS_ERR(*axi_clk)) {
+		err = PTR_ERR(*axi_clk);
+		dev_err(&pdev->dev, "failed to get axi_aclk (%u)\n", err);
+		return err;
+	}
+
+	*tx_clk = devm_clk_get(&pdev->dev, "m_axi_mm2s_aclk");
+	if (IS_ERR(*tx_clk))
+		*tx_clk = NULL;
+
+	*rx_clk = devm_clk_get(&pdev->dev, "m_axi_s2mm_aclk");
+	if (IS_ERR(*rx_clk))
+		*rx_clk = NULL;
+
+	*sg_clk = devm_clk_get(&pdev->dev, "m_axi_sg_aclk");
+	if (IS_ERR(*sg_clk))
+		*sg_clk = NULL;
+
+	err = clk_prepare_enable(*axi_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable axi_clk (%u)\n", err);
+		return err;
+	}
+
+	err = clk_prepare_enable(*tx_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable tx_clk (%u)\n", err);
+		goto err_disable_axiclk;
+	}
+
+	err = clk_prepare_enable(*rx_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable rx_clk (%u)\n", err);
+		goto err_disable_txclk;
+	}
+
+	err = clk_prepare_enable(*sg_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable sg_clk (%u)\n", err);
+		goto err_disable_rxclk;
+	}
+
+	return 0;
+
+err_disable_rxclk:
+	clk_disable_unprepare(*rx_clk);
+err_disable_txclk:
+	clk_disable_unprepare(*tx_clk);
+err_disable_axiclk:
+	clk_disable_unprepare(*axi_clk);
+
+	return err;
+}
+
+static int axicdma_clk_init(struct platform_device *pdev, struct clk **axi_clk,
+			    struct clk **dev_clk, struct clk **tmp_clk,
+			    struct clk **tmp1_clk, struct clk **tmp2_clk)
+{
+	int err;
+
+	*tmp_clk = NULL;
+	*tmp1_clk = NULL;
+	*tmp2_clk = NULL;
+
+	*axi_clk = devm_clk_get(&pdev->dev, "s_axi_lite_aclk");
+	if (IS_ERR(*axi_clk)) {
+		err = PTR_ERR(*axi_clk);
+		dev_err(&pdev->dev, "failed to get axi_clk (%u)\n", err);
+		return err;
+	}
+
+	*dev_clk = devm_clk_get(&pdev->dev, "m_axi_aclk");
+	if (IS_ERR(*dev_clk)) {
+		err = PTR_ERR(*dev_clk);
+		dev_err(&pdev->dev, "failed to get dev_clk (%u)\n", err);
+		return err;
+	}
+
+	err = clk_prepare_enable(*axi_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable axi_clk (%u)\n", err);
+		return err;
+	}
+
+	err = clk_prepare_enable(*dev_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable dev_clk (%u)\n", err);
+		goto err_disable_axiclk;
+	}
+
+	return 0;
+
+err_disable_axiclk:
+	clk_disable_unprepare(*axi_clk);
+
+	return err;
+}
+
+static int axivdma_clk_init(struct platform_device *pdev, struct clk **axi_clk,
+			    struct clk **tx_clk, struct clk **txs_clk,
+			    struct clk **rx_clk, struct clk **rxs_clk)
+{
+	int err;
+
+	*axi_clk = devm_clk_get(&pdev->dev, "s_axi_lite_aclk");
+	if (IS_ERR(*axi_clk)) {
+		err = PTR_ERR(*axi_clk);
+		dev_err(&pdev->dev, "failed to get axi_aclk (%u)\n", err);
+		return err;
+	}
+
+	*tx_clk = devm_clk_get(&pdev->dev, "m_axi_mm2s_aclk");
+	if (IS_ERR(*tx_clk))
+		*tx_clk = NULL;
+
+	*txs_clk = devm_clk_get(&pdev->dev, "m_axis_mm2s_aclk");
+	if (IS_ERR(*txs_clk))
+		*txs_clk = NULL;
+
+	*rx_clk = devm_clk_get(&pdev->dev, "m_axi_s2mm_aclk");
+	if (IS_ERR(*rx_clk))
+		*rx_clk = NULL;
+
+	*rxs_clk = devm_clk_get(&pdev->dev, "s_axis_s2mm_aclk");
+	if (IS_ERR(*rxs_clk))
+		*rxs_clk = NULL;
+
+	err = clk_prepare_enable(*axi_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable axi_clk (%u)\n", err);
+		return err;
+	}
+
+	err = clk_prepare_enable(*tx_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable tx_clk (%u)\n", err);
+		goto err_disable_axiclk;
+	}
+
+	err = clk_prepare_enable(*txs_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable txs_clk (%u)\n", err);
+		goto err_disable_txclk;
+	}
+
+	err = clk_prepare_enable(*rx_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable rx_clk (%u)\n", err);
+		goto err_disable_txsclk;
+	}
+
+	err = clk_prepare_enable(*rxs_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable rxs_clk (%u)\n", err);
+		goto err_disable_rxclk;
+	}
+
+	return 0;
+
+err_disable_rxclk:
+	clk_disable_unprepare(*rx_clk);
+err_disable_txsclk:
+	clk_disable_unprepare(*txs_clk);
+err_disable_txclk:
+	clk_disable_unprepare(*tx_clk);
+err_disable_axiclk:
+	clk_disable_unprepare(*axi_clk);
+
+	return err;
+}
+
+static void xdma_disable_allclks(struct xilinx_dma_device *xdev)
+{
+	clk_disable_unprepare(xdev->rxs_clk);
+	clk_disable_unprepare(xdev->rx_clk);
+	clk_disable_unprepare(xdev->txs_clk);
+	clk_disable_unprepare(xdev->tx_clk);
+	clk_disable_unprepare(xdev->axi_clk);
+}
+
 /**
- * xilinx_vdma_chan_probe - Per Channel Probing
+ * xilinx_dma_chan_probe - Per Channel Probing
  * It get channel features from the device tree entry and
  * initialize special channel handling routines
  *
@@ -1123,10 +1971,10 @@ static void xilinx_vdma_chan_remove(stru
  *
  * Return: '0' on success and failure value on error
  */
-static int xilinx_vdma_chan_probe(struct xilinx_vdma_device *xdev,
+static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev,
 				  struct device_node *node)
 {
-	struct xilinx_vdma_chan *chan;
+	struct xilinx_dma_chan *chan;
 	bool has_dre = false;
 	u32 value, width;
 	int err;
@@ -1140,6 +1988,7 @@ static int xilinx_vdma_chan_probe(struct
 	chan->xdev = xdev;
 	chan->has_sg = xdev->has_sg;
 	chan->desc_pendingcount = 0x0;
+	chan->ext_addr = xdev->ext_addr;
 
 	spin_lock_init(&chan->lock);
 	INIT_LIST_HEAD(&chan->pending_list);
@@ -1169,23 +2018,27 @@ static int xilinx_vdma_chan_probe(struct
 		chan->direction = DMA_MEM_TO_DEV;
 		chan->id = 0;
 
-		chan->ctrl_offset = XILINX_VDMA_MM2S_CTRL_OFFSET;
-		chan->desc_offset = XILINX_VDMA_MM2S_DESC_OFFSET;
+		chan->ctrl_offset = XILINX_DMA_MM2S_CTRL_OFFSET;
+		if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
+			chan->desc_offset = XILINX_VDMA_MM2S_DESC_OFFSET;
 
-		if (xdev->flush_on_fsync == XILINX_VDMA_FLUSH_BOTH ||
-		    xdev->flush_on_fsync == XILINX_VDMA_FLUSH_MM2S)
-			chan->flush_on_fsync = true;
+			if (xdev->flush_on_fsync == XILINX_DMA_FLUSH_BOTH ||
+			    xdev->flush_on_fsync == XILINX_DMA_FLUSH_MM2S)
+				chan->flush_on_fsync = true;
+		}
 	} else if (of_device_is_compatible(node,
 					    "xlnx,axi-vdma-s2mm-channel")) {
 		chan->direction = DMA_DEV_TO_MEM;
 		chan->id = 1;
 
-		chan->ctrl_offset = XILINX_VDMA_S2MM_CTRL_OFFSET;
-		chan->desc_offset = XILINX_VDMA_S2MM_DESC_OFFSET;
+		chan->ctrl_offset = XILINX_DMA_S2MM_CTRL_OFFSET;
+		if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
+			chan->desc_offset = XILINX_VDMA_S2MM_DESC_OFFSET;
 
-		if (xdev->flush_on_fsync == XILINX_VDMA_FLUSH_BOTH ||
-		    xdev->flush_on_fsync == XILINX_VDMA_FLUSH_S2MM)
-			chan->flush_on_fsync = true;
+			if (xdev->flush_on_fsync == XILINX_DMA_FLUSH_BOTH ||
+			    xdev->flush_on_fsync == XILINX_DMA_FLUSH_S2MM)
+				chan->flush_on_fsync = true;
+		}
 	} else {
 		dev_err(xdev->dev, "Invalid channel compatible node\n");
 		return -EINVAL;
@@ -1193,15 +2046,22 @@ static int xilinx_vdma_chan_probe(struct
 
 	/* Request the interrupt */
 	chan->irq = irq_of_parse_and_map(node, 0);
-	err = request_irq(chan->irq, xilinx_vdma_irq_handler, IRQF_SHARED,
-			  "xilinx-vdma-controller", chan);
+	err = request_irq(chan->irq, xilinx_dma_irq_handler, IRQF_SHARED,
+			  "xilinx-dma-controller", chan);
 	if (err) {
 		dev_err(xdev->dev, "unable to request IRQ %d\n", chan->irq);
 		return err;
 	}
 
+	if (xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA)
+		chan->start_transfer = xilinx_dma_start_transfer;
+	else if (xdev->dma_config->dmatype == XDMA_TYPE_CDMA)
+		chan->start_transfer = xilinx_cdma_start_transfer;
+	else
+		chan->start_transfer = xilinx_vdma_start_transfer;
+
 	/* Initialize the tasklet */
-	tasklet_init(&chan->tasklet, xilinx_vdma_do_tasklet,
+	tasklet_init(&chan->tasklet, xilinx_dma_do_tasklet,
 			(unsigned long)chan);
 
 	/*
@@ -1214,7 +2074,7 @@ static int xilinx_vdma_chan_probe(struct
 	xdev->chan[chan->id] = chan;
 
 	/* Reset the channel */
-	err = xilinx_vdma_chan_reset(chan);
+	err = xilinx_dma_chan_reset(chan);
 	if (err < 0) {
 		dev_err(xdev->dev, "Reset channel failed\n");
 		return err;
@@ -1233,28 +2093,54 @@ static int xilinx_vdma_chan_probe(struct
 static struct dma_chan *of_dma_xilinx_xlate(struct of_phandle_args *dma_spec,
 						struct of_dma *ofdma)
 {
-	struct xilinx_vdma_device *xdev = ofdma->of_dma_data;
+	struct xilinx_dma_device *xdev = ofdma->of_dma_data;
 	int chan_id = dma_spec->args[0];
 
-	if (chan_id >= XILINX_VDMA_MAX_CHANS_PER_DEVICE || !xdev->chan[chan_id])
+	if (chan_id >= XILINX_DMA_MAX_CHANS_PER_DEVICE || !xdev->chan[chan_id])
 		return NULL;
 
 	return dma_get_slave_channel(&xdev->chan[chan_id]->common);
 }
 
+static const struct xilinx_dma_config axidma_config = {
+	.dmatype = XDMA_TYPE_AXIDMA,
+	.clk_init = axidma_clk_init,
+};
+
+static const struct xilinx_dma_config axicdma_config = {
+	.dmatype = XDMA_TYPE_CDMA,
+	.clk_init = axicdma_clk_init,
+};
+
+static const struct xilinx_dma_config axivdma_config = {
+	.dmatype = XDMA_TYPE_VDMA,
+	.clk_init = axivdma_clk_init,
+};
+
+static const struct of_device_id xilinx_dma_of_ids[] = {
+	{ .compatible = "xlnx,axi-dma-1.00.a", .data = &axidma_config },
+	{ .compatible = "xlnx,axi-cdma-1.00.a", .data = &axicdma_config },
+	{ .compatible = "xlnx,axi-vdma-1.00.a", .data = &axivdma_config },
+	{}
+};
+MODULE_DEVICE_TABLE(of, xilinx_dma_of_ids);
+
 /**
- * xilinx_vdma_probe - Driver probe function
+ * xilinx_dma_probe - Driver probe function
  * @pdev: Pointer to the platform_device structure
  *
  * Return: '0' on success and failure value on error
  */
-static int xilinx_vdma_probe(struct platform_device *pdev)
+static int xilinx_dma_probe(struct platform_device *pdev)
 {
+	int (*clk_init)(struct platform_device *, struct clk **, struct clk **,
+			struct clk **, struct clk **, struct clk **)
+					= axivdma_clk_init;
 	struct device_node *node = pdev->dev.of_node;
-	struct xilinx_vdma_device *xdev;
-	struct device_node *child;
+	struct xilinx_dma_device *xdev;
+	struct device_node *child, *np = pdev->dev.of_node;
 	struct resource *io;
-	u32 num_frames;
+	u32 num_frames, addr_width;
 	int i, err;
 
 	/* Allocate and initialize the DMA engine structure */
@@ -1263,6 +2149,20 @@ static int xilinx_vdma_probe(struct plat
 		return -ENOMEM;
 
 	xdev->dev = &pdev->dev;
+	if (np) {
+		const struct of_device_id *match;
+
+		match = of_match_node(xilinx_dma_of_ids, np);
+		if (match && match->data) {
+			xdev->dma_config = match->data;
+			clk_init = xdev->dma_config->clk_init;
+		}
+	}
+
+	err = clk_init(pdev, &xdev->axi_clk, &xdev->tx_clk, &xdev->txs_clk,
+		       &xdev->rx_clk, &xdev->rxs_clk);
+	if (err)
+		return err;
 
 	/* Request and map I/O memory */
 	io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1273,46 +2173,77 @@ static int xilinx_vdma_probe(struct plat
 	/* Retrieve the DMA engine properties from the device tree */
 	xdev->has_sg = of_property_read_bool(node, "xlnx,include-sg");
 
-	err = of_property_read_u32(node, "xlnx,num-fstores", &num_frames);
-	if (err < 0) {
-		dev_err(xdev->dev, "missing xlnx,num-fstores property\n");
-		return err;
+	if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
+		err = of_property_read_u32(node, "xlnx,num-fstores",
+					   &num_frames);
+		if (err < 0) {
+			dev_err(xdev->dev,
+				"missing xlnx,num-fstores property\n");
+			return err;
+		}
+
+		err = of_property_read_u32(node, "xlnx,flush-fsync",
+					   &xdev->flush_on_fsync);
+		if (err < 0)
+			dev_warn(xdev->dev,
+				 "missing xlnx,flush-fsync property\n");
 	}
 
-	err = of_property_read_u32(node, "xlnx,flush-fsync",
-					&xdev->flush_on_fsync);
+	err = of_property_read_u32(node, "xlnx,addrwidth", &addr_width);
 	if (err < 0)
-		dev_warn(xdev->dev, "missing xlnx,flush-fsync property\n");
+		dev_warn(xdev->dev, "missing xlnx,addrwidth property\n");
+
+	if (addr_width > 32)
+		xdev->ext_addr = true;
+	else
+		xdev->ext_addr = false;
+
+	/* Set the dma mask bits */
+	dma_set_mask(xdev->dev, DMA_BIT_MASK(addr_width));
 
 	/* Initialize the DMA engine */
 	xdev->common.dev = &pdev->dev;
 
 	INIT_LIST_HEAD(&xdev->common.channels);
-	dma_cap_set(DMA_SLAVE, xdev->common.cap_mask);
-	dma_cap_set(DMA_PRIVATE, xdev->common.cap_mask);
+	if (!(xdev->dma_config->dmatype == XDMA_TYPE_CDMA)) {
+		dma_cap_set(DMA_SLAVE, xdev->common.cap_mask);
+		dma_cap_set(DMA_PRIVATE, xdev->common.cap_mask);
+	}
 
 	xdev->common.device_alloc_chan_resources =
-				xilinx_vdma_alloc_chan_resources;
+				xilinx_dma_alloc_chan_resources;
 	xdev->common.device_free_chan_resources =
-				xilinx_vdma_free_chan_resources;
-	xdev->common.device_prep_interleaved_dma =
+				xilinx_dma_free_chan_resources;
+	xdev->common.device_terminate_all = xilinx_dma_terminate_all;
+	xdev->common.device_tx_status = xilinx_dma_tx_status;
+	xdev->common.device_issue_pending = xilinx_dma_issue_pending;
+	if (xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
+		xdev->common.device_prep_slave_sg = xilinx_dma_prep_slave_sg;
+		/* Residue calculation is supported by only AXI DMA */
+		xdev->common.residue_granularity =
+					  DMA_RESIDUE_GRANULARITY_SEGMENT;
+	} else if (xdev->dma_config->dmatype == XDMA_TYPE_CDMA) {
+		dma_cap_set(DMA_MEMCPY, xdev->common.cap_mask);
+		xdev->common.device_prep_dma_memcpy = xilinx_cdma_prep_memcpy;
+	} else {
+		xdev->common.device_prep_interleaved_dma =
 				xilinx_vdma_dma_prep_interleaved;
-	xdev->common.device_terminate_all = xilinx_vdma_terminate_all;
-	xdev->common.device_tx_status = xilinx_vdma_tx_status;
-	xdev->common.device_issue_pending = xilinx_vdma_issue_pending;
+	}
 
 	platform_set_drvdata(pdev, xdev);
 
 	/* Initialize the channels */
 	for_each_child_of_node(node, child) {
-		err = xilinx_vdma_chan_probe(xdev, child);
+		err = xilinx_dma_chan_probe(xdev, child);
 		if (err < 0)
-			goto error;
+			goto disable_clks;
 	}
 
-	for (i = 0; i < XILINX_VDMA_MAX_CHANS_PER_DEVICE; i++)
-		if (xdev->chan[i])
-			xdev->chan[i]->num_frms = num_frames;
+	if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
+		for (i = 0; i < XILINX_DMA_MAX_CHANS_PER_DEVICE; i++)
+			if (xdev->chan[i])
+				xdev->chan[i]->num_frms = num_frames;
+	}
 
 	/* Register the DMA engine with the core */
 	dma_async_device_register(&xdev->common);
@@ -1329,49 +2260,47 @@ static int xilinx_vdma_probe(struct plat
 
 	return 0;
 
+disable_clks:
+	xdma_disable_allclks(xdev);
 error:
-	for (i = 0; i < XILINX_VDMA_MAX_CHANS_PER_DEVICE; i++)
+	for (i = 0; i < XILINX_DMA_MAX_CHANS_PER_DEVICE; i++)
 		if (xdev->chan[i])
-			xilinx_vdma_chan_remove(xdev->chan[i]);
+			xilinx_dma_chan_remove(xdev->chan[i]);
 
 	return err;
 }
 
 /**
- * xilinx_vdma_remove - Driver remove function
+ * xilinx_dma_remove - Driver remove function
  * @pdev: Pointer to the platform_device structure
  *
  * Return: Always '0'
  */
-static int xilinx_vdma_remove(struct platform_device *pdev)
+static int xilinx_dma_remove(struct platform_device *pdev)
 {
-	struct xilinx_vdma_device *xdev = platform_get_drvdata(pdev);
+	struct xilinx_dma_device *xdev = platform_get_drvdata(pdev);
 	int i;
 
 	of_dma_controller_free(pdev->dev.of_node);
 
 	dma_async_device_unregister(&xdev->common);
 
-	for (i = 0; i < XILINX_VDMA_MAX_CHANS_PER_DEVICE; i++)
+	for (i = 0; i < XILINX_DMA_MAX_CHANS_PER_DEVICE; i++)
 		if (xdev->chan[i])
-			xilinx_vdma_chan_remove(xdev->chan[i]);
+			xilinx_dma_chan_remove(xdev->chan[i]);
+
+	xdma_disable_allclks(xdev);
 
 	return 0;
 }
 
-static const struct of_device_id xilinx_vdma_of_ids[] = {
-	{ .compatible = "xlnx,axi-vdma-1.00.a",},
-	{}
-};
-MODULE_DEVICE_TABLE(of, xilinx_vdma_of_ids);
-
 static struct platform_driver xilinx_vdma_driver = {
 	.driver = {
 		.name = "xilinx-vdma",
-		.of_match_table = xilinx_vdma_of_ids,
+		.of_match_table = xilinx_dma_of_ids,
 	},
-	.probe = xilinx_vdma_probe,
-	.remove = xilinx_vdma_remove,
+	.probe = xilinx_dma_probe,
+	.remove = xilinx_dma_remove,
 };
 
 module_platform_driver(xilinx_vdma_driver);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma-buf/dma-buf.c linux-libre-4.7-gnu/drivers/dma-buf/dma-buf.c
--- linux-libre-4.6-gnu/drivers/dma-buf/dma-buf.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/dma-buf/dma-buf.c	2016-07-24 15:23:50.000000000 -0400
@@ -33,6 +33,7 @@
 #include <linux/seq_file.h>
 #include <linux/poll.h>
 #include <linux/reservation.h>
+#include <linux/mm.h>
 
 #include <uapi/linux/dma-buf.h>
 
@@ -90,7 +91,7 @@ static int dma_buf_mmap_internal(struct
 	dmabuf = file->private_data;
 
 	/* check for overflowing the buffer's size */
-	if (vma->vm_pgoff + ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) >
+	if (vma->vm_pgoff + vma_pages(vma) >
 	    dmabuf->size >> PAGE_SHIFT)
 		return -EINVAL;
 
@@ -723,11 +724,11 @@ int dma_buf_mmap(struct dma_buf *dmabuf,
 		return -EINVAL;
 
 	/* check for offset overflow */
-	if (pgoff + ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) < pgoff)
+	if (pgoff + vma_pages(vma) < pgoff)
 		return -EOVERFLOW;
 
 	/* check for overflowing the buffer's size */
-	if (pgoff + ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) >
+	if (pgoff + vma_pages(vma) >
 	    dmabuf->size >> PAGE_SHIFT)
 		return -EINVAL;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma-buf/Kconfig linux-libre-4.7-gnu/drivers/dma-buf/Kconfig
--- linux-libre-4.6-gnu/drivers/dma-buf/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/dma-buf/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,11 @@
+menu "DMABUF options"
+
+config SYNC_FILE
+	bool "sync_file support for fences"
+	default n
+	select ANON_INODES
+	select DMA_SHARED_BUFFER
+	---help---
+	  This option enables the fence framework synchronization to export
+	  sync_files to userspace that can represent one or more fences.
+endmenu
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma-buf/Makefile linux-libre-4.7-gnu/drivers/dma-buf/Makefile
--- linux-libre-4.6-gnu/drivers/dma-buf/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/dma-buf/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -1 +1,2 @@
 obj-y := dma-buf.o fence.o reservation.o seqno-fence.o
+obj-$(CONFIG_SYNC_FILE)		+= sync_file.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma-buf/reservation.c linux-libre-4.7-gnu/drivers/dma-buf/reservation.c
--- linux-libre-4.6-gnu/drivers/dma-buf/reservation.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/dma-buf/reservation.c	2016-07-24 15:23:50.000000000 -0400
@@ -35,6 +35,17 @@
 #include <linux/reservation.h>
 #include <linux/export.h>
 
+/**
+ * DOC: Reservation Object Overview
+ *
+ * The reservation object provides a mechanism to manage shared and
+ * exclusive fences associated with a buffer.  A reservation object
+ * can have attached one exclusive fence (normally associated with
+ * write operations) or N shared fences (read operations).  The RCU
+ * mechanism is used to protect read access to fences from locked
+ * write-side updates.
+ */
+
 DEFINE_WW_CLASS(reservation_ww_class);
 EXPORT_SYMBOL(reservation_ww_class);
 
@@ -43,9 +54,17 @@ EXPORT_SYMBOL(reservation_seqcount_class
 
 const char reservation_seqcount_string[] = "reservation_seqcount";
 EXPORT_SYMBOL(reservation_seqcount_string);
-/*
- * Reserve space to add a shared fence to a reservation_object,
- * must be called with obj->lock held.
+
+/**
+ * reservation_object_reserve_shared - Reserve space to add a shared
+ * fence to a reservation_object.
+ * @obj: reservation object
+ *
+ * Should be called before reservation_object_add_shared_fence().  Must
+ * be called with obj->lock held.
+ *
+ * RETURNS
+ * Zero for success, or -errno
  */
 int reservation_object_reserve_shared(struct reservation_object *obj)
 {
@@ -180,7 +199,11 @@ done:
 		fence_put(old_fence);
 }
 
-/*
+/**
+ * reservation_object_add_shared_fence - Add a fence to a shared slot
+ * @obj: the reservation object
+ * @fence: the shared fence to add
+ *
  * Add a fence to a shared slot, obj->lock must be held, and
  * reservation_object_reserve_shared_fence has been called.
  */
@@ -200,6 +223,13 @@ void reservation_object_add_shared_fence
 }
 EXPORT_SYMBOL(reservation_object_add_shared_fence);
 
+/**
+ * reservation_object_add_excl_fence - Add an exclusive fence.
+ * @obj: the reservation object
+ * @fence: the shared fence to add
+ *
+ * Add a fence to the exclusive slot.  The obj->lock must be held.
+ */
 void reservation_object_add_excl_fence(struct reservation_object *obj,
 				       struct fence *fence)
 {
@@ -233,6 +263,18 @@ void reservation_object_add_excl_fence(s
 }
 EXPORT_SYMBOL(reservation_object_add_excl_fence);
 
+/**
+ * reservation_object_get_fences_rcu - Get an object's shared and exclusive
+ * fences without update side lock held
+ * @obj: the reservation object
+ * @pfence_excl: the returned exclusive fence (or NULL)
+ * @pshared_count: the number of shared fences returned
+ * @pshared: the array of shared fence ptrs returned (array is krealloc'd to
+ * the required size, and must be freed by caller)
+ *
+ * RETURNS
+ * Zero or -errno
+ */
 int reservation_object_get_fences_rcu(struct reservation_object *obj,
 				      struct fence **pfence_excl,
 				      unsigned *pshared_count,
@@ -319,6 +361,18 @@ unlock:
 }
 EXPORT_SYMBOL_GPL(reservation_object_get_fences_rcu);
 
+/**
+ * reservation_object_wait_timeout_rcu - Wait on reservation's objects
+ * shared and/or exclusive fences.
+ * @obj: the reservation object
+ * @wait_all: if true, wait on all fences, else wait on just exclusive fence
+ * @intr: if true, do interruptible wait
+ * @timeout: timeout value in jiffies or zero to return immediately
+ *
+ * RETURNS
+ * Returns -ERESTARTSYS if interrupted, 0 if the wait timed out, or
+ * greater than zer on success.
+ */
 long reservation_object_wait_timeout_rcu(struct reservation_object *obj,
 					 bool wait_all, bool intr,
 					 unsigned long timeout)
@@ -416,6 +470,16 @@ reservation_object_test_signaled_single(
 	return ret;
 }
 
+/**
+ * reservation_object_test_signaled_rcu - Test if a reservation object's
+ * fences have been signaled.
+ * @obj: the reservation object
+ * @test_all: if true, test all fences, otherwise only test the exclusive
+ * fence
+ *
+ * RETURNS
+ * true if all fences signaled, else false
+ */
 bool reservation_object_test_signaled_rcu(struct reservation_object *obj,
 					  bool test_all)
 {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/dma-buf/sync_file.c linux-libre-4.7-gnu/drivers/dma-buf/sync_file.c
--- linux-libre-4.6-gnu/drivers/dma-buf/sync_file.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/dma-buf/sync_file.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,395 @@
+/*
+ * drivers/dma-buf/sync_file.c
+ *
+ * Copyright (C) 2012 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/export.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/poll.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/anon_inodes.h>
+#include <linux/sync_file.h>
+#include <uapi/linux/sync_file.h>
+
+static const struct file_operations sync_file_fops;
+
+static struct sync_file *sync_file_alloc(int size)
+{
+	struct sync_file *sync_file;
+
+	sync_file = kzalloc(size, GFP_KERNEL);
+	if (!sync_file)
+		return NULL;
+
+	sync_file->file = anon_inode_getfile("sync_file", &sync_file_fops,
+					     sync_file, 0);
+	if (IS_ERR(sync_file->file))
+		goto err;
+
+	kref_init(&sync_file->kref);
+
+	init_waitqueue_head(&sync_file->wq);
+
+	return sync_file;
+
+err:
+	kfree(sync_file);
+	return NULL;
+}
+
+static void fence_check_cb_func(struct fence *f, struct fence_cb *cb)
+{
+	struct sync_file_cb *check;
+	struct sync_file *sync_file;
+
+	check = container_of(cb, struct sync_file_cb, cb);
+	sync_file = check->sync_file;
+
+	if (atomic_dec_and_test(&sync_file->status))
+		wake_up_all(&sync_file->wq);
+}
+
+/**
+ * sync_file_create() - creates a sync file
+ * @fence:	fence to add to the sync_fence
+ *
+ * Creates a sync_file containg @fence. Once this is called, the sync_file
+ * takes ownership of @fence. The sync_file can be released with
+ * fput(sync_file->file). Returns the sync_file or NULL in case of error.
+ */
+struct sync_file *sync_file_create(struct fence *fence)
+{
+	struct sync_file *sync_file;
+
+	sync_file = sync_file_alloc(offsetof(struct sync_file, cbs[1]));
+	if (!sync_file)
+		return NULL;
+
+	sync_file->num_fences = 1;
+	atomic_set(&sync_file->status, 1);
+	snprintf(sync_file->name, sizeof(sync_file->name), "%s-%s%d-%d",
+		 fence->ops->get_driver_name(fence),
+		 fence->ops->get_timeline_name(fence), fence->context,
+		 fence->seqno);
+
+	sync_file->cbs[0].fence = fence;
+	sync_file->cbs[0].sync_file = sync_file;
+	if (fence_add_callback(fence, &sync_file->cbs[0].cb,
+			       fence_check_cb_func))
+		atomic_dec(&sync_file->status);
+
+	return sync_file;
+}
+EXPORT_SYMBOL(sync_file_create);
+
+/**
+ * sync_file_fdget() - get a sync_file from an fd
+ * @fd:		fd referencing a fence
+ *
+ * Ensures @fd references a valid sync_file, increments the refcount of the
+ * backing file. Returns the sync_file or NULL in case of error.
+ */
+static struct sync_file *sync_file_fdget(int fd)
+{
+	struct file *file = fget(fd);
+
+	if (!file)
+		return NULL;
+
+	if (file->f_op != &sync_file_fops)
+		goto err;
+
+	return file->private_data;
+
+err:
+	fput(file);
+	return NULL;
+}
+
+static void sync_file_add_pt(struct sync_file *sync_file, int *i,
+			     struct fence *fence)
+{
+	sync_file->cbs[*i].fence = fence;
+	sync_file->cbs[*i].sync_file = sync_file;
+
+	if (!fence_add_callback(fence, &sync_file->cbs[*i].cb,
+				fence_check_cb_func)) {
+		fence_get(fence);
+		(*i)++;
+	}
+}
+
+/**
+ * sync_file_merge() - merge two sync_files
+ * @name:	name of new fence
+ * @a:		sync_file a
+ * @b:		sync_file b
+ *
+ * Creates a new sync_file which contains copies of all the fences in both
+ * @a and @b.  @a and @b remain valid, independent sync_file. Returns the
+ * new merged sync_file or NULL in case of error.
+ */
+static struct sync_file *sync_file_merge(const char *name, struct sync_file *a,
+					 struct sync_file *b)
+{
+	int num_fences = a->num_fences + b->num_fences;
+	struct sync_file *sync_file;
+	int i, i_a, i_b;
+	unsigned long size = offsetof(struct sync_file, cbs[num_fences]);
+
+	sync_file = sync_file_alloc(size);
+	if (!sync_file)
+		return NULL;
+
+	atomic_set(&sync_file->status, num_fences);
+
+	/*
+	 * Assume sync_file a and b are both ordered and have no
+	 * duplicates with the same context.
+	 *
+	 * If a sync_file can only be created with sync_file_merge
+	 * and sync_file_create, this is a reasonable assumption.
+	 */
+	for (i = i_a = i_b = 0; i_a < a->num_fences && i_b < b->num_fences; ) {
+		struct fence *pt_a = a->cbs[i_a].fence;
+		struct fence *pt_b = b->cbs[i_b].fence;
+
+		if (pt_a->context < pt_b->context) {
+			sync_file_add_pt(sync_file, &i, pt_a);
+
+			i_a++;
+		} else if (pt_a->context > pt_b->context) {
+			sync_file_add_pt(sync_file, &i, pt_b);
+
+			i_b++;
+		} else {
+			if (pt_a->seqno - pt_b->seqno <= INT_MAX)
+				sync_file_add_pt(sync_file, &i, pt_a);
+			else
+				sync_file_add_pt(sync_file, &i, pt_b);
+
+			i_a++;
+			i_b++;
+		}
+	}
+
+	for (; i_a < a->num_fences; i_a++)
+		sync_file_add_pt(sync_file, &i, a->cbs[i_a].fence);
+
+	for (; i_b < b->num_fences; i_b++)
+		sync_file_add_pt(sync_file, &i, b->cbs[i_b].fence);
+
+	if (num_fences > i)
+		atomic_sub(num_fences - i, &sync_file->status);
+	sync_file->num_fences = i;
+
+	strlcpy(sync_file->name, name, sizeof(sync_file->name));
+	return sync_file;
+}
+
+static void sync_file_free(struct kref *kref)
+{
+	struct sync_file *sync_file = container_of(kref, struct sync_file,
+						     kref);
+	int i;
+
+	for (i = 0; i < sync_file->num_fences; ++i) {
+		fence_remove_callback(sync_file->cbs[i].fence,
+				      &sync_file->cbs[i].cb);
+		fence_put(sync_file->cbs[i].fence);
+	}
+
+	kfree(sync_file);
+}
+
+static int sync_file_release(struct inode *inode, struct file *file)
+{
+	struct sync_file *sync_file = file->private_data;
+
+	kref_put(&sync_file->kref, sync_file_free);
+	return 0;
+}
+
+static unsigned int sync_file_poll(struct file *file, poll_table *wait)
+{
+	struct sync_file *sync_file = file->private_data;
+	int status;
+
+	poll_wait(file, &sync_file->wq, wait);
+
+	status = atomic_read(&sync_file->status);
+
+	if (!status)
+		return POLLIN;
+	if (status < 0)
+		return POLLERR;
+	return 0;
+}
+
+static long sync_file_ioctl_merge(struct sync_file *sync_file,
+				  unsigned long arg)
+{
+	int fd = get_unused_fd_flags(O_CLOEXEC);
+	int err;
+	struct sync_file *fence2, *fence3;
+	struct sync_merge_data data;
+
+	if (fd < 0)
+		return fd;
+
+	if (copy_from_user(&data, (void __user *)arg, sizeof(data))) {
+		err = -EFAULT;
+		goto err_put_fd;
+	}
+
+	if (data.flags || data.pad) {
+		err = -EINVAL;
+		goto err_put_fd;
+	}
+
+	fence2 = sync_file_fdget(data.fd2);
+	if (!fence2) {
+		err = -ENOENT;
+		goto err_put_fd;
+	}
+
+	data.name[sizeof(data.name) - 1] = '\0';
+	fence3 = sync_file_merge(data.name, sync_file, fence2);
+	if (!fence3) {
+		err = -ENOMEM;
+		goto err_put_fence2;
+	}
+
+	data.fence = fd;
+	if (copy_to_user((void __user *)arg, &data, sizeof(data))) {
+		err = -EFAULT;
+		goto err_put_fence3;
+	}
+
+	fd_install(fd, fence3->file);
+	fput(fence2->file);
+	return 0;
+
+err_put_fence3:
+	fput(fence3->file);
+
+err_put_fence2:
+	fput(fence2->file);
+
+err_put_fd:
+	put_unused_fd(fd);
+	return err;
+}
+
+static void sync_fill_fence_info(struct fence *fence,
+				 struct sync_fence_info *info)
+{
+	strlcpy(info->obj_name, fence->ops->get_timeline_name(fence),
+		sizeof(info->obj_name));
+	strlcpy(info->driver_name, fence->ops->get_driver_name(fence),
+		sizeof(info->driver_name));
+	if (fence_is_signaled(fence))
+		info->status = fence->status >= 0 ? 1 : fence->status;
+	else
+		info->status = 0;
+	info->timestamp_ns = ktime_to_ns(fence->timestamp);
+}
+
+static long sync_file_ioctl_fence_info(struct sync_file *sync_file,
+				       unsigned long arg)
+{
+	struct sync_file_info info;
+	struct sync_fence_info *fence_info = NULL;
+	__u32 size;
+	int ret, i;
+
+	if (copy_from_user(&info, (void __user *)arg, sizeof(info)))
+		return -EFAULT;
+
+	if (info.flags || info.pad)
+		return -EINVAL;
+
+	/*
+	 * Passing num_fences = 0 means that userspace doesn't want to
+	 * retrieve any sync_fence_info. If num_fences = 0 we skip filling
+	 * sync_fence_info and return the actual number of fences on
+	 * info->num_fences.
+	 */
+	if (!info.num_fences)
+		goto no_fences;
+
+	if (info.num_fences < sync_file->num_fences)
+		return -EINVAL;
+
+	size = sync_file->num_fences * sizeof(*fence_info);
+	fence_info = kzalloc(size, GFP_KERNEL);
+	if (!fence_info)
+		return -ENOMEM;
+
+	for (i = 0; i < sync_file->num_fences; ++i)
+		sync_fill_fence_info(sync_file->cbs[i].fence, &fence_info[i]);
+
+	if (copy_to_user(u64_to_user_ptr(info.sync_fence_info), fence_info,
+			 size)) {
+		ret = -EFAULT;
+		goto out;
+	}
+
+no_fences:
+	strlcpy(info.name, sync_file->name, sizeof(info.name));
+	info.status = atomic_read(&sync_file->status);
+	if (info.status >= 0)
+		info.status = !info.status;
+
+	info.num_fences = sync_file->num_fences;
+
+	if (copy_to_user((void __user *)arg, &info, sizeof(info)))
+		ret = -EFAULT;
+	else
+		ret = 0;
+
+out:
+	kfree(fence_info);
+
+	return ret;
+}
+
+static long sync_file_ioctl(struct file *file, unsigned int cmd,
+			    unsigned long arg)
+{
+	struct sync_file *sync_file = file->private_data;
+
+	switch (cmd) {
+	case SYNC_IOC_MERGE:
+		return sync_file_ioctl_merge(sync_file, arg);
+
+	case SYNC_IOC_FILE_INFO:
+		return sync_file_ioctl_fence_info(sync_file, arg);
+
+	default:
+		return -ENOTTY;
+	}
+}
+
+static const struct file_operations sync_file_fops = {
+	.release = sync_file_release,
+	.poll = sync_file_poll,
+	.unlocked_ioctl = sync_file_ioctl,
+	.compat_ioctl = sync_file_ioctl,
+};
+
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/edac/altera_edac.c linux-libre-4.7-gnu/drivers/edac/altera_edac.c
--- linux-libre-4.6-gnu/drivers/edac/altera_edac.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/edac/altera_edac.c	2016-07-24 15:23:50.000000000 -0400
@@ -24,6 +24,7 @@
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/mfd/syscon.h>
+#include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/regmap.h>
@@ -78,27 +79,6 @@ static const struct altr_sdram_prv_data
 	.ue_set_mask        = A10_DIAGINT_TDERRA_MASK,
 };
 
-/************************** EDAC Device Defines **************************/
-
-/* OCRAM ECC Management Group Defines */
-#define ALTR_MAN_GRP_OCRAM_ECC_OFFSET   0x04
-#define ALTR_OCR_ECC_EN                 BIT(0)
-#define ALTR_OCR_ECC_INJS               BIT(1)
-#define ALTR_OCR_ECC_INJD               BIT(2)
-#define ALTR_OCR_ECC_SERR               BIT(3)
-#define ALTR_OCR_ECC_DERR               BIT(4)
-
-/* L2 ECC Management Group Defines */
-#define ALTR_MAN_GRP_L2_ECC_OFFSET      0x00
-#define ALTR_L2_ECC_EN                  BIT(0)
-#define ALTR_L2_ECC_INJS                BIT(1)
-#define ALTR_L2_ECC_INJD                BIT(2)
-
-#define ALTR_UE_TRIGGER_CHAR            'U'   /* Trigger for UE */
-#define ALTR_TRIGGER_READ_WRD_CNT       32    /* Line size x 4 */
-#define ALTR_TRIG_OCRAM_BYTE_SIZE       128   /* Line size x 4 */
-#define ALTR_TRIG_L2C_BYTE_SIZE         4096  /* Full Page */
-
 /*********************** EDAC Memory Controller Functions ****************/
 
 /* The SDRAM controller uses the EDAC Memory Controller framework.       */
@@ -252,8 +232,8 @@ static unsigned long get_total_mem(void)
 }
 
 static const struct of_device_id altr_sdram_ctrl_of_match[] = {
-	{ .compatible = "altr,sdram-edac", .data = (void *)&c5_data},
-	{ .compatible = "altr,sdram-edac-a10", .data = (void *)&a10_data},
+	{ .compatible = "altr,sdram-edac", .data = &c5_data},
+	{ .compatible = "altr,sdram-edac-a10", .data = &a10_data},
 	{},
 };
 MODULE_DEVICE_TABLE(of, altr_sdram_ctrl_of_match);
@@ -570,28 +550,8 @@ module_platform_driver(altr_edac_driver)
 
 const struct edac_device_prv_data ocramecc_data;
 const struct edac_device_prv_data l2ecc_data;
-
-struct edac_device_prv_data {
-	int (*setup)(struct platform_device *pdev, void __iomem *base);
-	int ce_clear_mask;
-	int ue_clear_mask;
-	char dbgfs_name[20];
-	void * (*alloc_mem)(size_t size, void **other);
-	void (*free_mem)(void *p, size_t size, void *other);
-	int ecc_enable_mask;
-	int ce_set_mask;
-	int ue_set_mask;
-	int trig_alloc_sz;
-};
-
-struct altr_edac_device_dev {
-	void __iomem *base;
-	int sb_irq;
-	int db_irq;
-	const struct edac_device_prv_data *data;
-	struct dentry *debugfs_dir;
-	char *edac_dev_name;
-};
+const struct edac_device_prv_data a10_ocramecc_data;
+const struct edac_device_prv_data a10_l2ecc_data;
 
 static irqreturn_t altr_edac_device_handler(int irq, void *dev_id)
 {
@@ -665,8 +625,9 @@ static ssize_t altr_edac_device_trig(str
 		if (ACCESS_ONCE(ptemp[i]))
 			result = -1;
 		/* Toggle Error bit (it is latched), leave ECC enabled */
-		writel(error_mask, drvdata->base);
-		writel(priv->ecc_enable_mask, drvdata->base);
+		writel(error_mask, (drvdata->base + priv->set_err_ofst));
+		writel(priv->ecc_enable_mask, (drvdata->base +
+					       priv->set_err_ofst));
 		ptemp[i] = i;
 	}
 	/* Ensure it has been written out */
@@ -694,6 +655,16 @@ static const struct file_operations altr
 	.llseek = generic_file_llseek,
 };
 
+static ssize_t altr_edac_a10_device_trig(struct file *file,
+					 const char __user *user_buf,
+					 size_t count, loff_t *ppos);
+
+static const struct file_operations altr_edac_a10_device_inject_fops = {
+	.open = simple_open,
+	.write = altr_edac_a10_device_trig,
+	.llseek = generic_file_llseek,
+};
+
 static void altr_create_edacdev_dbgfs(struct edac_device_ctl_info *edac_dci,
 				      const struct edac_device_prv_data *priv)
 {
@@ -708,17 +679,18 @@ static void altr_create_edacdev_dbgfs(st
 
 	if (!edac_debugfs_create_file(priv->dbgfs_name, S_IWUSR,
 				      drvdata->debugfs_dir, edac_dci,
-				      &altr_edac_device_inject_fops))
+				      priv->inject_fops))
 		debugfs_remove_recursive(drvdata->debugfs_dir);
 }
 
 static const struct of_device_id altr_edac_device_of_match[] = {
 #ifdef CONFIG_EDAC_ALTERA_L2C
-	{ .compatible = "altr,socfpga-l2-ecc", .data = (void *)&l2ecc_data },
+	{ .compatible = "altr,socfpga-l2-ecc", .data = &l2ecc_data },
+	{ .compatible = "altr,socfpga-a10-l2-ecc", .data = &a10_l2ecc_data },
 #endif
 #ifdef CONFIG_EDAC_ALTERA_OCRAM
-	{ .compatible = "altr,socfpga-ocram-ecc",
-	  .data = (void *)&ocramecc_data },
+	{ .compatible = "altr,socfpga-ocram-ecc", .data = &ocramecc_data },
+	{ .compatible = "altr,socfpga-a10-ocram-ecc", .data = &a10_ocramecc_data },
 #endif
 	{},
 };
@@ -789,7 +761,7 @@ static int altr_edac_device_probe(struct
 
 	/* Check specific dependencies for the module */
 	if (drvdata->data->setup) {
-		res = drvdata->data->setup(pdev, drvdata->base);
+		res = drvdata->data->setup(drvdata);
 		if (res)
 			goto fail1;
 	}
@@ -856,6 +828,25 @@ module_platform_driver(altr_edac_device_
 /*********************** OCRAM EDAC Device Functions *********************/
 
 #ifdef CONFIG_EDAC_ALTERA_OCRAM
+/*
+ *  Test for memory's ECC dependencies upon entry because platform specific
+ *  startup should have initialized the memory and enabled the ECC.
+ *  Can't turn on ECC here because accessing un-initialized memory will
+ *  cause CE/UE errors possibly causing an ABORT.
+ */
+static int altr_check_ecc_deps(struct altr_edac_device_dev *device)
+{
+	void __iomem  *base = device->base;
+	const struct edac_device_prv_data *prv = device->data;
+
+	if (readl(base + prv->ecc_en_ofst) & prv->ecc_enable_mask)
+		return 0;
+
+	edac_printk(KERN_ERR, EDAC_DEVICE,
+		    "%s: No ECC present or ECC disabled.\n",
+		    device->edac_dev_name);
+	return -ENODEV;
+}
 
 static void *ocram_alloc_mem(size_t size, void **other)
 {
@@ -891,36 +882,53 @@ static void ocram_free_mem(void *p, size
 	gen_pool_free((struct gen_pool *)other, (u32)p, size);
 }
 
-/*
- * altr_ocram_check_deps()
- *	Test for OCRAM cache ECC dependencies upon entry because
- *	platform specific startup should have initialized the
- *	On-Chip RAM memory and enabled the ECC.
- *	Can't turn on ECC here because accessing un-initialized
- *	memory will cause CE/UE errors possibly causing an ABORT.
- */
-static int altr_ocram_check_deps(struct platform_device *pdev,
-				 void __iomem *base)
+static irqreturn_t altr_edac_a10_ecc_irq(struct altr_edac_device_dev *dci,
+					 bool sberr)
 {
-	if (readl(base) & ALTR_OCR_ECC_EN)
-		return 0;
+	void __iomem  *base = dci->base;
 
-	edac_printk(KERN_ERR, EDAC_DEVICE,
-		    "OCRAM: No ECC present or ECC disabled.\n");
-	return -ENODEV;
+	if (sberr) {
+		writel(ALTR_A10_ECC_SERRPENA,
+		       base + ALTR_A10_ECC_INTSTAT_OFST);
+		edac_device_handle_ce(dci->edac_dev, 0, 0, dci->edac_dev_name);
+	} else {
+		writel(ALTR_A10_ECC_DERRPENA,
+		       base + ALTR_A10_ECC_INTSTAT_OFST);
+		edac_device_handle_ue(dci->edac_dev, 0, 0, dci->edac_dev_name);
+		panic("\nEDAC:ECC_DEVICE[Uncorrectable errors]\n");
+	}
+	return IRQ_HANDLED;
 }
 
 const struct edac_device_prv_data ocramecc_data = {
-	.setup = altr_ocram_check_deps,
+	.setup = altr_check_ecc_deps,
 	.ce_clear_mask = (ALTR_OCR_ECC_EN | ALTR_OCR_ECC_SERR),
 	.ue_clear_mask = (ALTR_OCR_ECC_EN | ALTR_OCR_ECC_DERR),
 	.dbgfs_name = "altr_ocram_trigger",
 	.alloc_mem = ocram_alloc_mem,
 	.free_mem = ocram_free_mem,
 	.ecc_enable_mask = ALTR_OCR_ECC_EN,
+	.ecc_en_ofst = ALTR_OCR_ECC_REG_OFFSET,
 	.ce_set_mask = (ALTR_OCR_ECC_EN | ALTR_OCR_ECC_INJS),
 	.ue_set_mask = (ALTR_OCR_ECC_EN | ALTR_OCR_ECC_INJD),
+	.set_err_ofst = ALTR_OCR_ECC_REG_OFFSET,
 	.trig_alloc_sz = ALTR_TRIG_OCRAM_BYTE_SIZE,
+	.inject_fops = &altr_edac_device_inject_fops,
+};
+
+const struct edac_device_prv_data a10_ocramecc_data = {
+	.setup = altr_check_ecc_deps,
+	.ce_clear_mask = ALTR_A10_ECC_SERRPENA,
+	.ue_clear_mask = ALTR_A10_ECC_DERRPENA,
+	.irq_status_mask = A10_SYSMGR_ECC_INTSTAT_OCRAM,
+	.dbgfs_name = "altr_ocram_trigger",
+	.ecc_enable_mask = ALTR_A10_OCRAM_ECC_EN_CTL,
+	.ecc_en_ofst = ALTR_A10_ECC_CTRL_OFST,
+	.ce_set_mask = ALTR_A10_ECC_TSERRA,
+	.ue_set_mask = ALTR_A10_ECC_TDERRA,
+	.set_err_ofst = ALTR_A10_ECC_INTTEST_OFST,
+	.ecc_irq_handler = altr_edac_a10_ecc_irq,
+	.inject_fops = &altr_edac_a10_device_inject_fops,
 };
 
 #endif	/* CONFIG_EDAC_ALTERA_OCRAM */
@@ -966,10 +974,13 @@ static void l2_free_mem(void *p, size_t
  *	Bail if ECC is not enabled.
  *	Note that L2 Cache Enable is forced at build time.
  */
-static int altr_l2_check_deps(struct platform_device *pdev,
-			      void __iomem *base)
+static int altr_l2_check_deps(struct altr_edac_device_dev *device)
 {
-	if (readl(base) & ALTR_L2_ECC_EN)
+	void __iomem *base = device->base;
+	const struct edac_device_prv_data *prv = device->data;
+
+	if ((readl(base) & prv->ecc_enable_mask) ==
+	     prv->ecc_enable_mask)
 		return 0;
 
 	edac_printk(KERN_ERR, EDAC_DEVICE,
@@ -977,6 +988,24 @@ static int altr_l2_check_deps(struct pla
 	return -ENODEV;
 }
 
+static irqreturn_t altr_edac_a10_l2_irq(struct altr_edac_device_dev *dci,
+					bool sberr)
+{
+	if (sberr) {
+		regmap_write(dci->edac->ecc_mgr_map,
+			     A10_SYSGMR_MPU_CLEAR_L2_ECC_OFST,
+			     A10_SYSGMR_MPU_CLEAR_L2_ECC_SB);
+		edac_device_handle_ce(dci->edac_dev, 0, 0, dci->edac_dev_name);
+	} else {
+		regmap_write(dci->edac->ecc_mgr_map,
+			     A10_SYSGMR_MPU_CLEAR_L2_ECC_OFST,
+			     A10_SYSGMR_MPU_CLEAR_L2_ECC_MB);
+		edac_device_handle_ue(dci->edac_dev, 0, 0, dci->edac_dev_name);
+		panic("\nEDAC:ECC_DEVICE[Uncorrectable errors]\n");
+	}
+	return IRQ_HANDLED;
+}
+
 const struct edac_device_prv_data l2ecc_data = {
 	.setup = altr_l2_check_deps,
 	.ce_clear_mask = 0,
@@ -987,11 +1016,252 @@ const struct edac_device_prv_data l2ecc_
 	.ecc_enable_mask = ALTR_L2_ECC_EN,
 	.ce_set_mask = (ALTR_L2_ECC_EN | ALTR_L2_ECC_INJS),
 	.ue_set_mask = (ALTR_L2_ECC_EN | ALTR_L2_ECC_INJD),
+	.set_err_ofst = ALTR_L2_ECC_REG_OFFSET,
 	.trig_alloc_sz = ALTR_TRIG_L2C_BYTE_SIZE,
+	.inject_fops = &altr_edac_device_inject_fops,
+};
+
+const struct edac_device_prv_data a10_l2ecc_data = {
+	.setup = altr_l2_check_deps,
+	.ce_clear_mask = ALTR_A10_L2_ECC_SERR_CLR,
+	.ue_clear_mask = ALTR_A10_L2_ECC_MERR_CLR,
+	.irq_status_mask = A10_SYSMGR_ECC_INTSTAT_L2,
+	.dbgfs_name = "altr_l2_trigger",
+	.alloc_mem = l2_alloc_mem,
+	.free_mem = l2_free_mem,
+	.ecc_enable_mask = ALTR_A10_L2_ECC_EN_CTL,
+	.ce_set_mask = ALTR_A10_L2_ECC_CE_INJ_MASK,
+	.ue_set_mask = ALTR_A10_L2_ECC_UE_INJ_MASK,
+	.set_err_ofst = ALTR_A10_L2_ECC_INJ_OFST,
+	.ecc_irq_handler = altr_edac_a10_l2_irq,
+	.trig_alloc_sz = ALTR_TRIG_L2C_BYTE_SIZE,
+	.inject_fops = &altr_edac_device_inject_fops,
 };
 
 #endif	/* CONFIG_EDAC_ALTERA_L2C */
 
+/********************* Arria10 EDAC Device Functions *************************/
+
+/*
+ * The Arria10 EDAC Device Functions differ from the Cyclone5/Arria5
+ * because 2 IRQs are shared among the all ECC peripherals. The ECC
+ * manager manages the IRQs and the children.
+ * Based on xgene_edac.c peripheral code.
+ */
+
+static ssize_t altr_edac_a10_device_trig(struct file *file,
+					 const char __user *user_buf,
+					 size_t count, loff_t *ppos)
+{
+	struct edac_device_ctl_info *edac_dci = file->private_data;
+	struct altr_edac_device_dev *drvdata = edac_dci->pvt_info;
+	const struct edac_device_prv_data *priv = drvdata->data;
+	void __iomem *set_addr = (drvdata->base + priv->set_err_ofst);
+	unsigned long flags;
+	u8 trig_type;
+
+	if (!user_buf || get_user(trig_type, user_buf))
+		return -EFAULT;
+
+	local_irq_save(flags);
+	if (trig_type == ALTR_UE_TRIGGER_CHAR)
+		writel(priv->ue_set_mask, set_addr);
+	else
+		writel(priv->ce_set_mask, set_addr);
+	/* Ensure the interrupt test bits are set */
+	wmb();
+	local_irq_restore(flags);
+
+	return count;
+}
+
+static irqreturn_t altr_edac_a10_irq_handler(int irq, void *dev_id)
+{
+	irqreturn_t rc = IRQ_NONE;
+	struct altr_arria10_edac *edac = dev_id;
+	struct altr_edac_device_dev *dci;
+	int irq_status;
+	bool sberr = (irq == edac->sb_irq) ? 1 : 0;
+	int sm_offset = sberr ? A10_SYSMGR_ECC_INTSTAT_SERR_OFST :
+				A10_SYSMGR_ECC_INTSTAT_DERR_OFST;
+
+	regmap_read(edac->ecc_mgr_map, sm_offset, &irq_status);
+
+	if ((irq != edac->sb_irq) && (irq != edac->db_irq)) {
+		WARN_ON(1);
+	} else {
+		list_for_each_entry(dci, &edac->a10_ecc_devices, next) {
+			if (irq_status & dci->data->irq_status_mask)
+				rc = dci->data->ecc_irq_handler(dci, sberr);
+		}
+	}
+
+	return rc;
+}
+
+static int altr_edac_a10_device_add(struct altr_arria10_edac *edac,
+				    struct device_node *np)
+{
+	struct edac_device_ctl_info *dci;
+	struct altr_edac_device_dev *altdev;
+	char *ecc_name = (char *)np->name;
+	struct resource res;
+	int edac_idx;
+	int rc = 0;
+	const struct edac_device_prv_data *prv;
+	/* Get matching node and check for valid result */
+	const struct of_device_id *pdev_id =
+		of_match_node(altr_edac_device_of_match, np);
+	if (IS_ERR_OR_NULL(pdev_id))
+		return -ENODEV;
+
+	/* Get driver specific data for this EDAC device */
+	prv = pdev_id->data;
+	if (IS_ERR_OR_NULL(prv))
+		return -ENODEV;
+
+	if (!devres_open_group(edac->dev, altr_edac_a10_device_add, GFP_KERNEL))
+		return -ENOMEM;
+
+	rc = of_address_to_resource(np, 0, &res);
+	if (rc < 0) {
+		edac_printk(KERN_ERR, EDAC_DEVICE,
+			    "%s: no resource address\n", ecc_name);
+		goto err_release_group;
+	}
+
+	edac_idx = edac_device_alloc_index();
+	dci = edac_device_alloc_ctl_info(sizeof(*altdev), ecc_name,
+					 1, ecc_name, 1, 0, NULL, 0,
+					 edac_idx);
+
+	if (!dci) {
+		edac_printk(KERN_ERR, EDAC_DEVICE,
+			    "%s: Unable to allocate EDAC device\n", ecc_name);
+		rc = -ENOMEM;
+		goto err_release_group;
+	}
+
+	altdev = dci->pvt_info;
+	dci->dev = edac->dev;
+	altdev->edac_dev_name = ecc_name;
+	altdev->edac_idx = edac_idx;
+	altdev->edac = edac;
+	altdev->edac_dev = dci;
+	altdev->data = prv;
+	altdev->ddev = *edac->dev;
+	dci->dev = &altdev->ddev;
+	dci->ctl_name = "Altera ECC Manager";
+	dci->mod_name = ecc_name;
+	dci->dev_name = ecc_name;
+
+	altdev->base = devm_ioremap_resource(edac->dev, &res);
+	if (IS_ERR(altdev->base)) {
+		rc = PTR_ERR(altdev->base);
+		goto err_release_group1;
+	}
+
+	/* Check specific dependencies for the module */
+	if (altdev->data->setup) {
+		rc = altdev->data->setup(altdev);
+		if (rc)
+			goto err_release_group1;
+	}
+
+	rc = edac_device_add_device(dci);
+	if (rc) {
+		dev_err(edac->dev, "edac_device_add_device failed\n");
+		rc = -ENOMEM;
+		goto err_release_group1;
+	}
+
+	altr_create_edacdev_dbgfs(dci, prv);
+
+	list_add(&altdev->next, &edac->a10_ecc_devices);
+
+	devres_remove_group(edac->dev, altr_edac_a10_device_add);
+
+	return 0;
+
+err_release_group1:
+	edac_device_free_ctl_info(dci);
+err_release_group:
+	edac_printk(KERN_ALERT, EDAC_DEVICE, "%s: %d\n", __func__, __LINE__);
+	devres_release_group(edac->dev, NULL);
+	edac_printk(KERN_ERR, EDAC_DEVICE,
+		    "%s:Error setting up EDAC device: %d\n", ecc_name, rc);
+
+	return rc;
+}
+
+static int altr_edac_a10_probe(struct platform_device *pdev)
+{
+	struct altr_arria10_edac *edac;
+	struct device_node *child;
+	int rc;
+
+	edac = devm_kzalloc(&pdev->dev, sizeof(*edac), GFP_KERNEL);
+	if (!edac)
+		return -ENOMEM;
+
+	edac->dev = &pdev->dev;
+	platform_set_drvdata(pdev, edac);
+	INIT_LIST_HEAD(&edac->a10_ecc_devices);
+
+	edac->ecc_mgr_map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+							"altr,sysmgr-syscon");
+	if (IS_ERR(edac->ecc_mgr_map)) {
+		edac_printk(KERN_ERR, EDAC_DEVICE,
+			    "Unable to get syscon altr,sysmgr-syscon\n");
+		return PTR_ERR(edac->ecc_mgr_map);
+	}
+
+	edac->sb_irq = platform_get_irq(pdev, 0);
+	rc = devm_request_irq(&pdev->dev, edac->sb_irq,
+			      altr_edac_a10_irq_handler,
+			      IRQF_SHARED, dev_name(&pdev->dev), edac);
+	if (rc) {
+		edac_printk(KERN_ERR, EDAC_DEVICE, "No SBERR IRQ resource\n");
+		return rc;
+	}
+
+	edac->db_irq = platform_get_irq(pdev, 1);
+	rc = devm_request_irq(&pdev->dev, edac->db_irq,
+			      altr_edac_a10_irq_handler,
+			      IRQF_SHARED, dev_name(&pdev->dev), edac);
+	if (rc) {
+		edac_printk(KERN_ERR, EDAC_DEVICE, "No DBERR IRQ resource\n");
+		return rc;
+	}
+
+	for_each_child_of_node(pdev->dev.of_node, child) {
+		if (!of_device_is_available(child))
+			continue;
+		if (of_device_is_compatible(child, "altr,socfpga-a10-l2-ecc"))
+			altr_edac_a10_device_add(edac, child);
+		else if (of_device_is_compatible(child,
+						 "altr,socfpga-a10-ocram-ecc"))
+			altr_edac_a10_device_add(edac, child);
+	}
+
+	return 0;
+}
+
+static const struct of_device_id altr_edac_a10_of_match[] = {
+	{ .compatible = "altr,socfpga-a10-ecc-manager" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, altr_edac_a10_of_match);
+
+static struct platform_driver altr_edac_a10_driver = {
+	.probe =  altr_edac_a10_probe,
+	.driver = {
+		.name = "socfpga_a10_ecc_manager",
+		.of_match_table = altr_edac_a10_of_match,
+	},
+};
+module_platform_driver(altr_edac_a10_driver);
+
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Thor Thayer");
 MODULE_DESCRIPTION("EDAC Driver for Altera Memories");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/edac/altera_edac.h linux-libre-4.7-gnu/drivers/edac/altera_edac.h
--- linux-libre-4.6-gnu/drivers/edac/altera_edac.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/edac/altera_edac.h	2016-07-24 15:23:50.000000000 -0400
@@ -195,4 +195,132 @@ struct altr_sdram_mc_data {
 	const struct altr_sdram_prv_data *data;
 };
 
+/************************** EDAC Device Defines **************************/
+/***** General Device Trigger Defines *****/
+#define ALTR_UE_TRIGGER_CHAR            'U'   /* Trigger for UE */
+#define ALTR_TRIGGER_READ_WRD_CNT       32    /* Line size x 4 */
+#define ALTR_TRIG_OCRAM_BYTE_SIZE       128   /* Line size x 4 */
+#define ALTR_TRIG_L2C_BYTE_SIZE         4096  /* Full Page */
+
+/******* Cyclone5 and Arria5 Defines *******/
+/* OCRAM ECC Management Group Defines */
+#define ALTR_MAN_GRP_OCRAM_ECC_OFFSET   0x04
+#define ALTR_OCR_ECC_REG_OFFSET         0x00
+#define ALTR_OCR_ECC_EN                 BIT(0)
+#define ALTR_OCR_ECC_INJS               BIT(1)
+#define ALTR_OCR_ECC_INJD               BIT(2)
+#define ALTR_OCR_ECC_SERR               BIT(3)
+#define ALTR_OCR_ECC_DERR               BIT(4)
+
+/* L2 ECC Management Group Defines */
+#define ALTR_MAN_GRP_L2_ECC_OFFSET      0x00
+#define ALTR_L2_ECC_REG_OFFSET          0x00
+#define ALTR_L2_ECC_EN                  BIT(0)
+#define ALTR_L2_ECC_INJS                BIT(1)
+#define ALTR_L2_ECC_INJD                BIT(2)
+
+/* Arria10 General ECC Block Module Defines */
+#define ALTR_A10_ECC_CTRL_OFST          0x08
+#define ALTR_A10_ECC_EN                 BIT(0)
+#define ALTR_A10_ECC_INITA              BIT(16)
+#define ALTR_A10_ECC_INITB              BIT(24)
+
+#define ALTR_A10_ECC_INITSTAT_OFST      0x0C
+#define ALTR_A10_ECC_INITCOMPLETEA      BIT(0)
+#define ALTR_A10_ECC_INITCOMPLETEB      BIT(8)
+
+#define ALTR_A10_ECC_ERRINTEN_OFST      0x10
+#define ALTR_A10_ECC_SERRINTEN          BIT(0)
+
+#define ALTR_A10_ECC_INTSTAT_OFST       0x20
+#define ALTR_A10_ECC_SERRPENA           BIT(0)
+#define ALTR_A10_ECC_DERRPENA           BIT(8)
+#define ALTR_A10_ECC_ERRPENA_MASK       (ALTR_A10_ECC_SERRPENA | \
+					 ALTR_A10_ECC_DERRPENA)
+#define ALTR_A10_ECC_SERRPENB           BIT(16)
+#define ALTR_A10_ECC_DERRPENB           BIT(24)
+#define ALTR_A10_ECC_ERRPENB_MASK       (ALTR_A10_ECC_SERRPENB | \
+					 ALTR_A10_ECC_DERRPENB)
+
+#define ALTR_A10_ECC_INTTEST_OFST       0x24
+#define ALTR_A10_ECC_TSERRA             BIT(0)
+#define ALTR_A10_ECC_TDERRA             BIT(8)
+
+/* ECC Manager Defines */
+#define A10_SYSMGR_ECC_INTMASK_SET_OFST   0x94
+#define A10_SYSMGR_ECC_INTMASK_CLR_OFST   0x98
+#define A10_SYSMGR_ECC_INTMASK_OCRAM      BIT(1)
+
+#define A10_SYSMGR_ECC_INTSTAT_SERR_OFST  0x9C
+#define A10_SYSMGR_ECC_INTSTAT_DERR_OFST  0xA0
+#define A10_SYSMGR_ECC_INTSTAT_L2         BIT(0)
+#define A10_SYSMGR_ECC_INTSTAT_OCRAM      BIT(1)
+
+#define A10_SYSGMR_MPU_CLEAR_L2_ECC_OFST  0xA8
+#define A10_SYSGMR_MPU_CLEAR_L2_ECC_SB    BIT(15)
+#define A10_SYSGMR_MPU_CLEAR_L2_ECC_MB    BIT(31)
+
+/* Arria 10 L2 ECC Management Group Defines */
+#define ALTR_A10_L2_ECC_CTL_OFST        0x0
+#define ALTR_A10_L2_ECC_EN_CTL          BIT(0)
+
+#define ALTR_A10_L2_ECC_STATUS          0xFFD060A4
+#define ALTR_A10_L2_ECC_STAT_OFST       0xA4
+#define ALTR_A10_L2_ECC_SERR_PEND       BIT(0)
+#define ALTR_A10_L2_ECC_MERR_PEND       BIT(0)
+
+#define ALTR_A10_L2_ECC_CLR_OFST        0x4
+#define ALTR_A10_L2_ECC_SERR_CLR        BIT(15)
+#define ALTR_A10_L2_ECC_MERR_CLR        BIT(31)
+
+#define ALTR_A10_L2_ECC_INJ_OFST        ALTR_A10_L2_ECC_CTL_OFST
+#define ALTR_A10_L2_ECC_CE_INJ_MASK     0x00000101
+#define ALTR_A10_L2_ECC_UE_INJ_MASK     0x00010101
+
+/* Arria 10 OCRAM ECC Management Group Defines */
+#define ALTR_A10_OCRAM_ECC_EN_CTL       (BIT(1) | BIT(0))
+
+struct altr_edac_device_dev;
+
+struct edac_device_prv_data {
+	int (*setup)(struct altr_edac_device_dev *device);
+	int ce_clear_mask;
+	int ue_clear_mask;
+	int irq_status_mask;
+	char dbgfs_name[20];
+	void * (*alloc_mem)(size_t size, void **other);
+	void (*free_mem)(void *p, size_t size, void *other);
+	int ecc_enable_mask;
+	int ecc_en_ofst;
+	int ce_set_mask;
+	int ue_set_mask;
+	int set_err_ofst;
+	irqreturn_t (*ecc_irq_handler)(struct altr_edac_device_dev *dci,
+				       bool sb);
+	int trig_alloc_sz;
+	const struct file_operations *inject_fops;
+};
+
+struct altr_edac_device_dev {
+	struct list_head next;
+	void __iomem *base;
+	int sb_irq;
+	int db_irq;
+	const struct edac_device_prv_data *data;
+	struct dentry *debugfs_dir;
+	char *edac_dev_name;
+	struct altr_arria10_edac *edac;
+	struct edac_device_ctl_info *edac_dev;
+	struct device ddev;
+	int edac_idx;
+};
+
+struct altr_arria10_edac {
+	struct device		*dev;
+	struct regmap		*ecc_mgr_map;
+	int sb_irq;
+	int db_irq;
+	struct list_head	a10_ecc_devices;
+};
+
 #endif	/* #ifndef _ALTERA_EDAC_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/edac/amd64_edac.c linux-libre-4.7-gnu/drivers/edac/amd64_edac.c
--- linux-libre-4.6-gnu/drivers/edac/amd64_edac.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/edac/amd64_edac.c	2016-07-24 15:23:50.000000000 -0400
@@ -15,11 +15,6 @@ module_param(ecc_enable_override, int, 0
 
 static struct msr __percpu *msrs;
 
-/*
- * count successfully initialized driver instances for setup_pci_device()
- */
-static atomic_t drv_instances = ATOMIC_INIT(0);
-
 /* Per-node stuff */
 static struct ecc_settings **ecc_stngs;
 
@@ -645,7 +640,7 @@ static u64 sys_addr_to_input_addr(struct
 	input_addr =
 	    dram_addr_to_input_addr(mci, sys_addr_to_dram_addr(mci, sys_addr));
 
-	edac_dbg(2, "SysAdddr 0x%lx translates to InputAddr 0x%lx\n",
+	edac_dbg(2, "SysAddr 0x%lx translates to InputAddr 0x%lx\n",
 		 (unsigned long)sys_addr, (unsigned long)input_addr);
 
 	return input_addr;
@@ -1918,7 +1913,7 @@ static struct amd64_family_type family_t
 	[K8_CPUS] = {
 		.ctl_name = "K8",
 		.f1_id = PCI_DEVICE_ID_AMD_K8_NB_ADDRMAP,
-		.f3_id = PCI_DEVICE_ID_AMD_K8_NB_MISC,
+		.f2_id = PCI_DEVICE_ID_AMD_K8_NB_MEMCTL,
 		.ops = {
 			.early_channel_count	= k8_early_channel_count,
 			.map_sysaddr_to_csrow	= k8_map_sysaddr_to_csrow,
@@ -1928,7 +1923,7 @@ static struct amd64_family_type family_t
 	[F10_CPUS] = {
 		.ctl_name = "F10h",
 		.f1_id = PCI_DEVICE_ID_AMD_10H_NB_MAP,
-		.f3_id = PCI_DEVICE_ID_AMD_10H_NB_MISC,
+		.f2_id = PCI_DEVICE_ID_AMD_10H_NB_DRAM,
 		.ops = {
 			.early_channel_count	= f1x_early_channel_count,
 			.map_sysaddr_to_csrow	= f1x_map_sysaddr_to_csrow,
@@ -1938,7 +1933,7 @@ static struct amd64_family_type family_t
 	[F15_CPUS] = {
 		.ctl_name = "F15h",
 		.f1_id = PCI_DEVICE_ID_AMD_15H_NB_F1,
-		.f3_id = PCI_DEVICE_ID_AMD_15H_NB_F3,
+		.f2_id = PCI_DEVICE_ID_AMD_15H_NB_F2,
 		.ops = {
 			.early_channel_count	= f1x_early_channel_count,
 			.map_sysaddr_to_csrow	= f1x_map_sysaddr_to_csrow,
@@ -1948,7 +1943,7 @@ static struct amd64_family_type family_t
 	[F15_M30H_CPUS] = {
 		.ctl_name = "F15h_M30h",
 		.f1_id = PCI_DEVICE_ID_AMD_15H_M30H_NB_F1,
-		.f3_id = PCI_DEVICE_ID_AMD_15H_M30H_NB_F3,
+		.f2_id = PCI_DEVICE_ID_AMD_15H_M30H_NB_F2,
 		.ops = {
 			.early_channel_count	= f1x_early_channel_count,
 			.map_sysaddr_to_csrow	= f1x_map_sysaddr_to_csrow,
@@ -1958,7 +1953,7 @@ static struct amd64_family_type family_t
 	[F15_M60H_CPUS] = {
 		.ctl_name = "F15h_M60h",
 		.f1_id = PCI_DEVICE_ID_AMD_15H_M60H_NB_F1,
-		.f3_id = PCI_DEVICE_ID_AMD_15H_M60H_NB_F3,
+		.f2_id = PCI_DEVICE_ID_AMD_15H_M60H_NB_F2,
 		.ops = {
 			.early_channel_count	= f1x_early_channel_count,
 			.map_sysaddr_to_csrow	= f1x_map_sysaddr_to_csrow,
@@ -1968,7 +1963,7 @@ static struct amd64_family_type family_t
 	[F16_CPUS] = {
 		.ctl_name = "F16h",
 		.f1_id = PCI_DEVICE_ID_AMD_16H_NB_F1,
-		.f3_id = PCI_DEVICE_ID_AMD_16H_NB_F3,
+		.f2_id = PCI_DEVICE_ID_AMD_16H_NB_F2,
 		.ops = {
 			.early_channel_count	= f1x_early_channel_count,
 			.map_sysaddr_to_csrow	= f1x_map_sysaddr_to_csrow,
@@ -1978,7 +1973,7 @@ static struct amd64_family_type family_t
 	[F16_M30H_CPUS] = {
 		.ctl_name = "F16h_M30h",
 		.f1_id = PCI_DEVICE_ID_AMD_16H_M30H_NB_F1,
-		.f3_id = PCI_DEVICE_ID_AMD_16H_M30H_NB_F3,
+		.f2_id = PCI_DEVICE_ID_AMD_16H_M30H_NB_F2,
 		.ops = {
 			.early_channel_count	= f1x_early_channel_count,
 			.map_sysaddr_to_csrow	= f1x_map_sysaddr_to_csrow,
@@ -2227,13 +2222,13 @@ static inline void decode_bus_error(int
 }
 
 /*
- * Use pvt->F2 which contains the F2 CPU PCI device to get the related
- * F1 (AddrMap) and F3 (Misc) devices. Return negative value on error.
+ * Use pvt->F3 which contains the F3 CPU PCI device to get the related
+ * F1 (AddrMap) and F2 (Dct) devices. Return negative value on error.
  */
-static int reserve_mc_sibling_devs(struct amd64_pvt *pvt, u16 f1_id, u16 f3_id)
+static int reserve_mc_sibling_devs(struct amd64_pvt *pvt, u16 f1_id, u16 f2_id)
 {
 	/* Reserve the ADDRESS MAP Device */
-	pvt->F1 = pci_get_related_function(pvt->F2->vendor, f1_id, pvt->F2);
+	pvt->F1 = pci_get_related_function(pvt->F3->vendor, f1_id, pvt->F3);
 	if (!pvt->F1) {
 		amd64_err("error address map device not found: "
 			  "vendor %x device 0x%x (broken BIOS?)\n",
@@ -2241,15 +2236,15 @@ static int reserve_mc_sibling_devs(struc
 		return -ENODEV;
 	}
 
-	/* Reserve the MISC Device */
-	pvt->F3 = pci_get_related_function(pvt->F2->vendor, f3_id, pvt->F2);
-	if (!pvt->F3) {
+	/* Reserve the DCT Device */
+	pvt->F2 = pci_get_related_function(pvt->F3->vendor, f2_id, pvt->F3);
+	if (!pvt->F2) {
 		pci_dev_put(pvt->F1);
 		pvt->F1 = NULL;
 
-		amd64_err("error F3 device not found: "
+		amd64_err("error F2 device not found: "
 			  "vendor %x device 0x%x (broken BIOS?)\n",
-			  PCI_VENDOR_ID_AMD, f3_id);
+			  PCI_VENDOR_ID_AMD, f2_id);
 
 		return -ENODEV;
 	}
@@ -2263,7 +2258,7 @@ static int reserve_mc_sibling_devs(struc
 static void free_mc_sibling_devs(struct amd64_pvt *pvt)
 {
 	pci_dev_put(pvt->F1);
-	pci_dev_put(pvt->F3);
+	pci_dev_put(pvt->F2);
 }
 
 /*
@@ -2778,14 +2773,14 @@ static const struct attribute_group *amd
 	NULL
 };
 
-static int init_one_instance(struct pci_dev *F2)
+static int init_one_instance(unsigned int nid)
 {
-	struct amd64_pvt *pvt = NULL;
+	struct pci_dev *F3 = node_to_amd_nb(nid)->misc;
 	struct amd64_family_type *fam_type = NULL;
 	struct mem_ctl_info *mci = NULL;
 	struct edac_mc_layer layers[2];
+	struct amd64_pvt *pvt = NULL;
 	int err = 0, ret;
-	u16 nid = amd_pci_dev_to_node_id(F2);
 
 	ret = -ENOMEM;
 	pvt = kzalloc(sizeof(struct amd64_pvt), GFP_KERNEL);
@@ -2793,7 +2788,7 @@ static int init_one_instance(struct pci_
 		goto err_ret;
 
 	pvt->mc_node_id	= nid;
-	pvt->F2 = F2;
+	pvt->F3 = F3;
 
 	ret = -EINVAL;
 	fam_type = per_family_init(pvt);
@@ -2801,7 +2796,7 @@ static int init_one_instance(struct pci_
 		goto err_free;
 
 	ret = -ENODEV;
-	err = reserve_mc_sibling_devs(pvt, fam_type->f1_id, fam_type->f3_id);
+	err = reserve_mc_sibling_devs(pvt, fam_type->f1_id, fam_type->f2_id);
 	if (err)
 		goto err_free;
 
@@ -2836,7 +2831,7 @@ static int init_one_instance(struct pci_
 		goto err_siblings;
 
 	mci->pvt_info = pvt;
-	mci->pdev = &pvt->F2->dev;
+	mci->pdev = &pvt->F3->dev;
 
 	setup_mci_misc_attrs(mci, fam_type);
 
@@ -2855,8 +2850,6 @@ static int init_one_instance(struct pci_
 
 	amd_register_ecc_decoder(decode_bus_error);
 
-	atomic_inc(&drv_instances);
-
 	return 0;
 
 err_add_mc:
@@ -2872,19 +2865,11 @@ err_ret:
 	return ret;
 }
 
-static int probe_one_instance(struct pci_dev *pdev,
-			      const struct pci_device_id *mc_type)
+static int probe_one_instance(unsigned int nid)
 {
-	u16 nid = amd_pci_dev_to_node_id(pdev);
 	struct pci_dev *F3 = node_to_amd_nb(nid)->misc;
 	struct ecc_settings *s;
-	int ret = 0;
-
-	ret = pci_enable_device(pdev);
-	if (ret < 0) {
-		edac_dbg(0, "ret=%d\n", ret);
-		return -EIO;
-	}
+	int ret;
 
 	ret = -ENOMEM;
 	s = kzalloc(sizeof(struct ecc_settings), GFP_KERNEL);
@@ -2905,7 +2890,7 @@ static int probe_one_instance(struct pci
 			goto err_enable;
 	}
 
-	ret = init_one_instance(pdev);
+	ret = init_one_instance(nid);
 	if (ret < 0) {
 		amd64_err("Error probing instance: %d\n", nid);
 		restore_ecc_error_reporting(s, nid, F3);
@@ -2921,19 +2906,18 @@ err_out:
 	return ret;
 }
 
-static void remove_one_instance(struct pci_dev *pdev)
+static void remove_one_instance(unsigned int nid)
 {
-	struct mem_ctl_info *mci;
-	struct amd64_pvt *pvt;
-	u16 nid = amd_pci_dev_to_node_id(pdev);
 	struct pci_dev *F3 = node_to_amd_nb(nid)->misc;
 	struct ecc_settings *s = ecc_stngs[nid];
+	struct mem_ctl_info *mci;
+	struct amd64_pvt *pvt;
 
-	mci = find_mci_by_dev(&pdev->dev);
+	mci = find_mci_by_dev(&F3->dev);
 	WARN_ON(!mci);
 
 	/* Remove from EDAC CORE tracking list */
-	mci = edac_mc_del_mc(&pdev->dev);
+	mci = edac_mc_del_mc(&F3->dev);
 	if (!mci)
 		return;
 
@@ -2957,31 +2941,6 @@ static void remove_one_instance(struct p
 	edac_mc_free(mci);
 }
 
-/*
- * This table is part of the interface for loading drivers for PCI devices. The
- * PCI core identifies what devices are on a system during boot, and then
- * inquiry this table to see if this driver is for a given device found.
- */
-static const struct pci_device_id amd64_pci_table[] = {
-	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_K8_NB_MEMCTL) },
-	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_10H_NB_DRAM) },
-	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F2) },
-	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M30H_NB_F2) },
-	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M60H_NB_F2) },
-	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_NB_F2) },
-	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F2) },
-	{0, }
-};
-MODULE_DEVICE_TABLE(pci, amd64_pci_table);
-
-static struct pci_driver amd64_pci_driver = {
-	.name		= EDAC_MOD_STR,
-	.probe		= probe_one_instance,
-	.remove		= remove_one_instance,
-	.id_table	= amd64_pci_table,
-	.driver.probe_type = PROBE_FORCE_SYNCHRONOUS,
-};
-
 static void setup_pci_device(void)
 {
 	struct mem_ctl_info *mci;
@@ -3005,8 +2964,7 @@ static void setup_pci_device(void)
 static int __init amd64_edac_init(void)
 {
 	int err = -ENODEV;
-
-	printk(KERN_INFO "AMD64 EDAC driver v%s\n", EDAC_AMD64_VERSION);
+	int i;
 
 	opstate_init();
 
@@ -3022,13 +2980,14 @@ static int __init amd64_edac_init(void)
 	if (!msrs)
 		goto err_free;
 
-	err = pci_register_driver(&amd64_pci_driver);
-	if (err)
-		goto err_pci;
+	for (i = 0; i < amd_nb_num(); i++)
+		if (probe_one_instance(i)) {
+			/* unwind properly */
+			while (--i >= 0)
+				remove_one_instance(i);
 
-	err = -ENODEV;
-	if (!atomic_read(&drv_instances))
-		goto err_no_instances;
+			goto err_pci;
+		}
 
 	setup_pci_device();
 
@@ -3036,10 +2995,9 @@ static int __init amd64_edac_init(void)
 	amd64_err("%s on 32-bit is unsupported. USE AT YOUR OWN RISK!\n", EDAC_MOD_STR);
 #endif
 
-	return 0;
+	printk(KERN_INFO "AMD64 EDAC driver v%s\n", EDAC_AMD64_VERSION);
 
-err_no_instances:
-	pci_unregister_driver(&amd64_pci_driver);
+	return 0;
 
 err_pci:
 	msrs_free(msrs);
@@ -3055,10 +3013,13 @@ err_ret:
 
 static void __exit amd64_edac_exit(void)
 {
+	int i;
+
 	if (pci_ctl)
 		edac_pci_release_generic_ctl(pci_ctl);
 
-	pci_unregister_driver(&amd64_pci_driver);
+	for (i = 0; i < amd_nb_num(); i++)
+		remove_one_instance(i);
 
 	kfree(ecc_stngs);
 	ecc_stngs = NULL;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/edac/amd64_edac.h linux-libre-4.7-gnu/drivers/edac/amd64_edac.h
--- linux-libre-4.6-gnu/drivers/edac/amd64_edac.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/edac/amd64_edac.h	2016-07-24 15:23:50.000000000 -0400
@@ -422,7 +422,7 @@ struct low_ops {
 
 struct amd64_family_type {
 	const char *ctl_name;
-	u16 f1_id, f3_id;
+	u16 f1_id, f2_id;
 	struct low_ops ops;
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/edac/edac_mc.c linux-libre-4.7-gnu/drivers/edac/edac_mc.c
--- linux-libre-4.6-gnu/drivers/edac/edac_mc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/edac/edac_mc.c	2016-07-24 15:23:50.000000000 -0400
@@ -565,7 +565,8 @@ void edac_mc_reset_delay_period(unsigned
 	list_for_each(item, &mc_devices) {
 		mci = list_entry(item, struct mem_ctl_info, link);
 
-		edac_mod_work(&mci->work, value);
+		if (mci->op_state == OP_RUNNING_POLL)
+			edac_mod_work(&mci->work, value);
 	}
 	mutex_unlock(&mem_ctls_mutex);
 }
@@ -923,7 +924,7 @@ static void edac_inc_ue_error(struct mem
 	mci->ue_mc += count;
 
 	if (!enable_per_layer_report) {
-		mci->ce_noinfo_count += count;
+		mci->ue_noinfo_count += count;
 		return;
 	}
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/edac/edac_mc_sysfs.c linux-libre-4.7-gnu/drivers/edac/edac_mc_sysfs.c
--- linux-libre-4.6-gnu/drivers/edac/edac_mc_sysfs.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/edac/edac_mc_sysfs.c	2016-07-24 15:23:50.000000000 -0400
@@ -998,11 +998,12 @@ void edac_remove_sysfs_mci_device(struct
 
 void edac_unregister_sysfs(struct mem_ctl_info *mci)
 {
+	struct bus_type *bus = mci->bus;
 	const char *name = mci->bus->name;
 
 	edac_dbg(1, "Unregistering device %s\n", dev_name(&mci->dev));
 	device_unregister(&mci->dev);
-	bus_unregister(mci->bus);
+	bus_unregister(bus);
 	kfree(name);
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/edac/i7core_edac.c linux-libre-4.7-gnu/drivers/edac/i7core_edac.c
--- linux-libre-4.6-gnu/drivers/edac/i7core_edac.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/edac/i7core_edac.c	2016-07-24 15:23:50.000000000 -0400
@@ -271,16 +271,6 @@ struct i7core_pvt {
 
 	bool		is_registered, enable_scrub;
 
-	/* Fifo double buffers */
-	struct mce		mce_entry[MCE_LOG_LEN];
-	struct mce		mce_outentry[MCE_LOG_LEN];
-
-	/* Fifo in/out counters */
-	unsigned		mce_in, mce_out;
-
-	/* Count indicator to show errors not got */
-	unsigned		mce_overrun;
-
 	/* DCLK Frequency used for computing scrub rate */
 	int			dclk_freq;
 
@@ -1792,56 +1782,15 @@ static void i7core_mce_output_error(stru
  *	i7core_check_error	Retrieve and process errors reported by the
  *				hardware. Called by the Core module.
  */
-static void i7core_check_error(struct mem_ctl_info *mci)
+static void i7core_check_error(struct mem_ctl_info *mci, struct mce *m)
 {
 	struct i7core_pvt *pvt = mci->pvt_info;
-	int i;
-	unsigned count = 0;
-	struct mce *m;
 
-	/*
-	 * MCE first step: Copy all mce errors into a temporary buffer
-	 * We use a double buffering here, to reduce the risk of
-	 * losing an error.
-	 */
-	smp_rmb();
-	count = (pvt->mce_out + MCE_LOG_LEN - pvt->mce_in)
-		% MCE_LOG_LEN;
-	if (!count)
-		goto check_ce_error;
-
-	m = pvt->mce_outentry;
-	if (pvt->mce_in + count > MCE_LOG_LEN) {
-		unsigned l = MCE_LOG_LEN - pvt->mce_in;
-
-		memcpy(m, &pvt->mce_entry[pvt->mce_in], sizeof(*m) * l);
-		smp_wmb();
-		pvt->mce_in = 0;
-		count -= l;
-		m += l;
-	}
-	memcpy(m, &pvt->mce_entry[pvt->mce_in], sizeof(*m) * count);
-	smp_wmb();
-	pvt->mce_in += count;
-
-	smp_rmb();
-	if (pvt->mce_overrun) {
-		i7core_printk(KERN_ERR, "Lost %d memory errors\n",
-			      pvt->mce_overrun);
-		smp_wmb();
-		pvt->mce_overrun = 0;
-	}
-
-	/*
-	 * MCE second step: parse errors and display
-	 */
-	for (i = 0; i < count; i++)
-		i7core_mce_output_error(mci, &pvt->mce_outentry[i]);
+	i7core_mce_output_error(mci, m);
 
 	/*
 	 * Now, let's increment CE error counts
 	 */
-check_ce_error:
 	if (!pvt->is_registered)
 		i7core_udimm_check_mc_ecc_err(mci);
 	else
@@ -1849,12 +1798,8 @@ check_ce_error:
 }
 
 /*
- * i7core_mce_check_error	Replicates mcelog routine to get errors
- *				This routine simply queues mcelog errors, and
- *				return. The error itself should be handled later
- *				by i7core_check_error.
- * WARNING: As this routine should be called at NMI time, extra care should
- * be taken to avoid deadlocks, and to be as fast as possible.
+ * Check that logging is enabled and that this is the right type
+ * of error for us to handle.
  */
 static int i7core_mce_check_error(struct notifier_block *nb, unsigned long val,
 				  void *data)
@@ -1882,21 +1827,7 @@ static int i7core_mce_check_error(struct
 	if (mce->bank != 8)
 		return NOTIFY_DONE;
 
-	smp_rmb();
-	if ((pvt->mce_out + 1) % MCE_LOG_LEN == pvt->mce_in) {
-		smp_wmb();
-		pvt->mce_overrun++;
-		return NOTIFY_DONE;
-	}
-
-	/* Copy memory error at the ringbuffer */
-	memcpy(&pvt->mce_entry[pvt->mce_out], mce, sizeof(*mce));
-	smp_wmb();
-	pvt->mce_out = (pvt->mce_out + 1) % MCE_LOG_LEN;
-
-	/* Handle fatal errors immediately */
-	if (mce->mcgstatus & 1)
-		i7core_check_error(mci);
+	i7core_check_error(mci, mce);
 
 	/* Advise mcelog that the errors were handled */
 	return NOTIFY_STOP;
@@ -2243,8 +2174,6 @@ static int i7core_register_mci(struct i7
 	get_dimm_config(mci);
 	/* record ptr to the generic device */
 	mci->pdev = &i7core_dev->pdev[0]->dev;
-	/* Set the function pointer to an actual operation function */
-	mci->edac_check = i7core_check_error;
 
 	/* Enable scrubrate setting */
 	if (pvt->enable_scrub)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/edac/ie31200_edac.c linux-libre-4.7-gnu/drivers/edac/ie31200_edac.c
--- linux-libre-4.6-gnu/drivers/edac/ie31200_edac.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/edac/ie31200_edac.c	2016-07-24 15:23:50.000000000 -0400
@@ -17,6 +17,7 @@
  * 015c: Xeon E3-1200 v2/3rd Gen Core processor DRAM Controller
  * 0c04: Xeon E3-1200 v3/4th Gen Core Processor DRAM Controller
  * 0c08: Xeon E3-1200 v3 Processor DRAM Controller
+ * 1918: Xeon E3-1200 v5 Skylake Host Bridge/DRAM Registers
  *
  * Based on Intel specification:
  * http://www.intel.com/content/dam/www/public/us/en/documents/datasheets/xeon-e3-1200v3-vol-2-datasheet.pdf
@@ -55,6 +56,7 @@
 #define PCI_DEVICE_ID_INTEL_IE31200_HB_5 0x015c
 #define PCI_DEVICE_ID_INTEL_IE31200_HB_6 0x0c04
 #define PCI_DEVICE_ID_INTEL_IE31200_HB_7 0x0c08
+#define PCI_DEVICE_ID_INTEL_IE31200_HB_8 0x1918
 
 #define IE31200_DIMMS			4
 #define IE31200_RANKS			8
@@ -105,8 +107,11 @@
  *    1  Multiple Bit Error Status (MERRSTS)
  *    0  Correctable Error Status (CERRSTS)
  */
+
 #define IE31200_C0ECCERRLOG			0x40c8
 #define IE31200_C1ECCERRLOG			0x44c8
+#define IE31200_C0ECCERRLOG_SKL			0x4048
+#define IE31200_C1ECCERRLOG_SKL			0x4448
 #define IE31200_ECCERRLOG_CE			BIT(0)
 #define IE31200_ECCERRLOG_UE			BIT(1)
 #define IE31200_ECCERRLOG_RANK_BITS		GENMASK_ULL(28, 27)
@@ -123,17 +128,28 @@
 #define IE31200_CAPID0_DDPCD		BIT(6)
 #define IE31200_CAPID0_ECC		BIT(1)
 
-#define IE31200_MAD_DIMM_0_OFFSET	0x5004
-#define IE31200_MAD_DIMM_SIZE		GENMASK_ULL(7, 0)
-#define IE31200_MAD_DIMM_A_RANK		BIT(17)
-#define IE31200_MAD_DIMM_A_WIDTH	BIT(19)
+#define IE31200_MAD_DIMM_0_OFFSET		0x5004
+#define IE31200_MAD_DIMM_0_OFFSET_SKL		0x500C
+#define IE31200_MAD_DIMM_SIZE			GENMASK_ULL(7, 0)
+#define IE31200_MAD_DIMM_A_RANK			BIT(17)
+#define IE31200_MAD_DIMM_A_RANK_SHIFT		17
+#define IE31200_MAD_DIMM_A_RANK_SKL		BIT(10)
+#define IE31200_MAD_DIMM_A_RANK_SKL_SHIFT	10
+#define IE31200_MAD_DIMM_A_WIDTH		BIT(19)
+#define IE31200_MAD_DIMM_A_WIDTH_SHIFT		19
+#define IE31200_MAD_DIMM_A_WIDTH_SKL		GENMASK_ULL(9, 8)
+#define IE31200_MAD_DIMM_A_WIDTH_SKL_SHIFT	8
 
-#define IE31200_PAGES(n)		(n << (28 - PAGE_SHIFT))
+/* Skylake reports 1GB increments, everything else is 256MB */
+#define IE31200_PAGES(n, skl)	\
+	(n << (28 + (2 * skl) - PAGE_SHIFT))
 
 static int nr_channels;
 
 struct ie31200_priv {
 	void __iomem *window;
+	void __iomem *c0errlog;
+	void __iomem *c1errlog;
 };
 
 enum ie31200_chips {
@@ -157,9 +173,9 @@ static const struct ie31200_dev_info ie3
 };
 
 struct dimm_data {
-	u8 size; /* in 256MB multiples */
+	u8 size; /* in multiples of 256MB, except Skylake is 1GB */
 	u8 dual_rank : 1,
-	   x16_width : 1; /* 0 means x8 width */
+	   x16_width : 2; /* 0 means x8 width */
 };
 
 static int how_many_channels(struct pci_dev *pdev)
@@ -197,11 +213,10 @@ static bool ecc_capable(struct pci_dev *
 	return true;
 }
 
-static int eccerrlog_row(int channel, u64 log)
+static int eccerrlog_row(u64 log)
 {
-	int rank = ((log & IE31200_ECCERRLOG_RANK_BITS) >>
-		IE31200_ECCERRLOG_RANK_SHIFT);
-	return rank | (channel * IE31200_RANKS_PER_CHANNEL);
+	return ((log & IE31200_ECCERRLOG_RANK_BITS) >>
+				IE31200_ECCERRLOG_RANK_SHIFT);
 }
 
 static void ie31200_clear_error_info(struct mem_ctl_info *mci)
@@ -219,7 +234,6 @@ static void ie31200_get_and_clear_error_
 {
 	struct pci_dev *pdev;
 	struct ie31200_priv *priv = mci->pvt_info;
-	void __iomem *window = priv->window;
 
 	pdev = to_pci_dev(mci->pdev);
 
@@ -232,9 +246,9 @@ static void ie31200_get_and_clear_error_
 	if (!(info->errsts & IE31200_ERRSTS_BITS))
 		return;
 
-	info->eccerrlog[0] = lo_hi_readq(window + IE31200_C0ECCERRLOG);
+	info->eccerrlog[0] = lo_hi_readq(priv->c0errlog);
 	if (nr_channels == 2)
-		info->eccerrlog[1] = lo_hi_readq(window + IE31200_C1ECCERRLOG);
+		info->eccerrlog[1] = lo_hi_readq(priv->c1errlog);
 
 	pci_read_config_word(pdev, IE31200_ERRSTS, &info->errsts2);
 
@@ -245,10 +259,10 @@ static void ie31200_get_and_clear_error_
 	 * should be UE info.
 	 */
 	if ((info->errsts ^ info->errsts2) & IE31200_ERRSTS_BITS) {
-		info->eccerrlog[0] = lo_hi_readq(window + IE31200_C0ECCERRLOG);
+		info->eccerrlog[0] = lo_hi_readq(priv->c0errlog);
 		if (nr_channels == 2)
 			info->eccerrlog[1] =
-				lo_hi_readq(window + IE31200_C1ECCERRLOG);
+				lo_hi_readq(priv->c1errlog);
 	}
 
 	ie31200_clear_error_info(mci);
@@ -274,14 +288,14 @@ static void ie31200_process_error_info(s
 		if (log & IE31200_ECCERRLOG_UE) {
 			edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
 					     0, 0, 0,
-					     eccerrlog_row(channel, log),
+					     eccerrlog_row(log),
 					     channel, -1,
 					     "ie31200 UE", "");
 		} else if (log & IE31200_ECCERRLOG_CE) {
 			edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
 					     0, 0,
 					     IE31200_ECCERRLOG_SYNDROME(log),
-					     eccerrlog_row(channel, log),
+					     eccerrlog_row(log),
 					     channel, -1,
 					     "ie31200 CE", "");
 		}
@@ -326,6 +340,33 @@ static void __iomem *ie31200_map_mchbar(
 	return window;
 }
 
+static void __skl_populate_dimm_info(struct dimm_data *dd, u32 addr_decode,
+				     int chan)
+{
+	dd->size = (addr_decode >> (chan << 4)) & IE31200_MAD_DIMM_SIZE;
+	dd->dual_rank = (addr_decode & (IE31200_MAD_DIMM_A_RANK_SKL << (chan << 4))) ? 1 : 0;
+	dd->x16_width = ((addr_decode & (IE31200_MAD_DIMM_A_WIDTH_SKL << (chan << 4))) >>
+				(IE31200_MAD_DIMM_A_WIDTH_SKL_SHIFT + (chan << 4)));
+}
+
+static void __populate_dimm_info(struct dimm_data *dd, u32 addr_decode,
+				 int chan)
+{
+	dd->size = (addr_decode >> (chan << 3)) & IE31200_MAD_DIMM_SIZE;
+	dd->dual_rank = (addr_decode & (IE31200_MAD_DIMM_A_RANK << chan)) ? 1 : 0;
+	dd->x16_width = (addr_decode & (IE31200_MAD_DIMM_A_WIDTH << chan)) ? 1 : 0;
+}
+
+static void populate_dimm_info(struct dimm_data *dd, u32 addr_decode, int chan,
+			       bool skl)
+{
+	if (skl)
+		__skl_populate_dimm_info(dd, addr_decode, chan);
+	else
+		__populate_dimm_info(dd, addr_decode, chan);
+}
+
+
 static int ie31200_probe1(struct pci_dev *pdev, int dev_idx)
 {
 	int i, j, ret;
@@ -334,7 +375,8 @@ static int ie31200_probe1(struct pci_dev
 	struct dimm_data dimm_info[IE31200_CHANNELS][IE31200_DIMMS_PER_CHANNEL];
 	void __iomem *window;
 	struct ie31200_priv *priv;
-	u32 addr_decode;
+	u32 addr_decode, mad_offset;
+	bool skl = (pdev->device == PCI_DEVICE_ID_INTEL_IE31200_HB_8);
 
 	edac_dbg(0, "MC:\n");
 
@@ -363,7 +405,10 @@ static int ie31200_probe1(struct pci_dev
 
 	edac_dbg(3, "MC: init mci\n");
 	mci->pdev = &pdev->dev;
-	mci->mtype_cap = MEM_FLAG_DDR3;
+	if (skl)
+		mci->mtype_cap = MEM_FLAG_DDR4;
+	else
+		mci->mtype_cap = MEM_FLAG_DDR3;
 	mci->edac_ctl_cap = EDAC_FLAG_SECDED;
 	mci->edac_cap = EDAC_FLAG_SECDED;
 	mci->mod_name = EDAC_MOD_STR;
@@ -374,19 +419,24 @@ static int ie31200_probe1(struct pci_dev
 	mci->ctl_page_to_phys = NULL;
 	priv = mci->pvt_info;
 	priv->window = window;
+	if (skl) {
+		priv->c0errlog = window + IE31200_C0ECCERRLOG_SKL;
+		priv->c1errlog = window + IE31200_C1ECCERRLOG_SKL;
+		mad_offset = IE31200_MAD_DIMM_0_OFFSET_SKL;
+	} else {
+		priv->c0errlog = window + IE31200_C0ECCERRLOG;
+		priv->c1errlog = window + IE31200_C1ECCERRLOG;
+		mad_offset = IE31200_MAD_DIMM_0_OFFSET;
+	}
 
 	/* populate DIMM info */
 	for (i = 0; i < IE31200_CHANNELS; i++) {
-		addr_decode = readl(window + IE31200_MAD_DIMM_0_OFFSET +
+		addr_decode = readl(window + mad_offset +
 					(i * 4));
 		edac_dbg(0, "addr_decode: 0x%x\n", addr_decode);
 		for (j = 0; j < IE31200_DIMMS_PER_CHANNEL; j++) {
-			dimm_info[i][j].size = (addr_decode >> (j * 8)) &
-						IE31200_MAD_DIMM_SIZE;
-			dimm_info[i][j].dual_rank = (addr_decode &
-				(IE31200_MAD_DIMM_A_RANK << j)) ? 1 : 0;
-			dimm_info[i][j].x16_width = (addr_decode &
-				(IE31200_MAD_DIMM_A_WIDTH << j)) ? 1 : 0;
+			populate_dimm_info(&dimm_info[i][j], addr_decode, j,
+					   skl);
 			edac_dbg(0, "size: 0x%x, rank: %d, width: %d\n",
 				 dimm_info[i][j].size,
 				 dimm_info[i][j].dual_rank,
@@ -405,7 +455,7 @@ static int ie31200_probe1(struct pci_dev
 			struct dimm_info *dimm;
 			unsigned long nr_pages;
 
-			nr_pages = IE31200_PAGES(dimm_info[j][i].size);
+			nr_pages = IE31200_PAGES(dimm_info[j][i].size, skl);
 			if (nr_pages == 0)
 				continue;
 
@@ -417,7 +467,10 @@ static int ie31200_probe1(struct pci_dev
 				dimm->nr_pages = nr_pages;
 				edac_dbg(0, "set nr pages: 0x%lx\n", nr_pages);
 				dimm->grain = 8; /* just a guess */
-				dimm->mtype = MEM_DDR3;
+				if (skl)
+					dimm->mtype = MEM_DDR4;
+				else
+					dimm->mtype = MEM_DDR3;
 				dimm->dtype = DEV_UNKNOWN;
 				dimm->edac_mode = EDAC_UNKNOWN;
 			}
@@ -426,7 +479,10 @@ static int ie31200_probe1(struct pci_dev
 			dimm->nr_pages = nr_pages;
 			edac_dbg(0, "set nr pages: 0x%lx\n", nr_pages);
 			dimm->grain = 8; /* same guess */
-			dimm->mtype = MEM_DDR3;
+			if (skl)
+				dimm->mtype = MEM_DDR4;
+			else
+				dimm->mtype = MEM_DDR3;
 			dimm->dtype = DEV_UNKNOWN;
 			dimm->edac_mode = EDAC_UNKNOWN;
 		}
@@ -501,6 +557,9 @@ static const struct pci_device_id ie3120
 		PCI_VEND_DEV(INTEL, IE31200_HB_7), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 		IE31200},
 	{
+		PCI_VEND_DEV(INTEL, IE31200_HB_8), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		IE31200},
+	{
 		0,
 	}            /* 0 terminated list. */
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/edac/Kconfig linux-libre-4.7-gnu/drivers/edac/Kconfig
--- linux-libre-4.6-gnu/drivers/edac/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/edac/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -378,12 +378,11 @@ config EDAC_ALTERA
 
 config EDAC_ALTERA_L2C
 	bool "Altera L2 Cache ECC"
-	depends on EDAC_ALTERA=y
-	select CACHE_L2X0
+	depends on EDAC_ALTERA=y && CACHE_L2X0
 	help
 	  Support for error detection and correction on the
 	  Altera L2 cache Memory for Altera SoCs. This option
-	  requires L2 cache so it will force that selection.
+	  requires L2 cache.
 
 config EDAC_ALTERA_OCRAM
 	bool "Altera On-Chip RAM ECC"
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/edac/mce_amd.c linux-libre-4.7-gnu/drivers/edac/mce_amd.c
--- linux-libre-4.6-gnu/drivers/edac/mce_amd.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/edac/mce_amd.c	2016-07-24 15:23:50.000000000 -0400
@@ -1052,7 +1052,6 @@ int amd_decode_mce(struct notifier_block
 	struct mce *m = (struct mce *)data;
 	struct cpuinfo_x86 *c = &cpu_data(m->extcpu);
 	int ecc;
-	u32 ebx = cpuid_ebx(0x80000007);
 
 	if (amd_filter_mce(m))
 		return NOTIFY_STOP;
@@ -1075,7 +1074,7 @@ int amd_decode_mce(struct notifier_block
 			((m->status & MCI_STATUS_DEFERRED) ? "Deferred" : "-"),
 			((m->status & MCI_STATUS_POISON)   ? "Poison"   : "-"));
 
-	if (!!(ebx & BIT(3))) {
+	if (boot_cpu_has(X86_FEATURE_SMCA)) {
 		u32 low, high;
 		u32 addr = MSR_AMD64_SMCA_MCx_CONFIG(m->bank);
 
@@ -1094,7 +1093,7 @@ int amd_decode_mce(struct notifier_block
 	if (m->status & MCI_STATUS_ADDRV)
 		pr_emerg(HW_ERR "MC%d Error Address: 0x%016llx\n", m->bank, m->addr);
 
-	if (!!(ebx & BIT(3))) {
+	if (boot_cpu_has(X86_FEATURE_SMCA)) {
 		decode_smca_errors(m);
 		goto err_code;
 	}
@@ -1149,7 +1148,6 @@ static struct notifier_block amd_mce_dec
 static int __init mce_amd_init(void)
 {
 	struct cpuinfo_x86 *c = &boot_cpu_data;
-	u32 ebx;
 
 	if (c->x86_vendor != X86_VENDOR_AMD)
 		return -ENODEV;
@@ -1205,9 +1203,8 @@ static int __init mce_amd_init(void)
 		break;
 
 	case 0x17:
-		ebx = cpuid_ebx(0x80000007);
 		xec_mask = 0x3f;
-		if (!(ebx & BIT(3))) {
+		if (!boot_cpu_has(X86_FEATURE_SMCA)) {
 			printk(KERN_WARNING "Decoding supported only on Scalable MCA processors.\n");
 			goto err_out;
 		}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/edac/sb_edac.c linux-libre-4.7-gnu/drivers/edac/sb_edac.c
--- linux-libre-4.6-gnu/drivers/edac/sb_edac.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/edac/sb_edac.c	2016-07-24 15:23:50.000000000 -0400
@@ -21,6 +21,8 @@
 #include <linux/smp.h>
 #include <linux/bitmap.h>
 #include <linux/math64.h>
+#include <linux/mod_devicetable.h>
+#include <asm/cpu_device_id.h>
 #include <asm/processor.h>
 #include <asm/mce.h>
 
@@ -28,8 +30,6 @@
 
 /* Static vars */
 static LIST_HEAD(sbridge_edac_list);
-static DEFINE_MUTEX(sbridge_edac_lock);
-static int probed;
 
 /*
  * Alter this version for the module when modifications are made
@@ -239,8 +239,11 @@ static const u32 rir_offset[MAX_RIR_RANG
 	{ 0x1a0, 0x1a4, 0x1a8, 0x1ac, 0x1b0, 0x1b4, 0x1b8, 0x1bc },
 };
 
-#define RIR_RNK_TGT(reg)		GET_BITFIELD(reg, 16, 19)
-#define RIR_OFFSET(reg)		GET_BITFIELD(reg,  2, 14)
+#define RIR_RNK_TGT(type, reg) (((type) == BROADWELL) ? \
+	GET_BITFIELD(reg, 20, 23) : GET_BITFIELD(reg, 16, 19))
+
+#define RIR_OFFSET(type, reg) (((type) == HASWELL || (type) == BROADWELL) ? \
+	GET_BITFIELD(reg,  2, 15) : GET_BITFIELD(reg,  2, 14))
 
 /* Device 16, functions 2-7 */
 
@@ -326,6 +329,7 @@ struct pci_id_descr {
 struct pci_id_table {
 	const struct pci_id_descr	*descr;
 	int				n_devs;
+	enum type			type;
 };
 
 struct sbridge_dev {
@@ -364,16 +368,6 @@ struct sbridge_pvt {
 	bool			is_mirrored, is_lockstep, is_close_pg;
 	bool			is_chan_hash;
 
-	/* Fifo double buffers */
-	struct mce		mce_entry[MCE_LOG_LEN];
-	struct mce		mce_outentry[MCE_LOG_LEN];
-
-	/* Fifo in/out counters */
-	unsigned		mce_in, mce_out;
-
-	/* Count indicator to show errors not got */
-	unsigned		mce_overrun;
-
 	/* Memory description */
 	u64			tolm, tohm;
 	struct knl_pvt knl;
@@ -404,9 +398,14 @@ static const struct pci_id_descr pci_dev
 	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_BR, 0)		},
 };
 
-#define PCI_ID_TABLE_ENTRY(A) { .descr=A, .n_devs = ARRAY_SIZE(A) }
+#define PCI_ID_TABLE_ENTRY(A, T) {	\
+	.descr = A,			\
+	.n_devs = ARRAY_SIZE(A),	\
+	.type = T			\
+}
+
 static const struct pci_id_table pci_dev_descr_sbridge_table[] = {
-	PCI_ID_TABLE_ENTRY(pci_dev_descr_sbridge),
+	PCI_ID_TABLE_ENTRY(pci_dev_descr_sbridge, SANDY_BRIDGE),
 	{0,}			/* 0 terminated list. */
 };
 
@@ -473,7 +472,7 @@ static const struct pci_id_descr pci_dev
 };
 
 static const struct pci_id_table pci_dev_descr_ibridge_table[] = {
-	PCI_ID_TABLE_ENTRY(pci_dev_descr_ibridge),
+	PCI_ID_TABLE_ENTRY(pci_dev_descr_ibridge, IVY_BRIDGE),
 	{0,}			/* 0 terminated list. */
 };
 
@@ -546,7 +545,7 @@ static const struct pci_id_descr pci_dev
 };
 
 static const struct pci_id_table pci_dev_descr_haswell_table[] = {
-	PCI_ID_TABLE_ENTRY(pci_dev_descr_haswell),
+	PCI_ID_TABLE_ENTRY(pci_dev_descr_haswell, HASWELL),
 	{0,}			/* 0 terminated list. */
 };
 
@@ -590,7 +589,7 @@ static const struct pci_id_descr pci_dev
 };
 
 static const struct pci_id_table pci_dev_descr_knl_table[] = {
-	PCI_ID_TABLE_ENTRY(pci_dev_descr_knl),
+	PCI_ID_TABLE_ENTRY(pci_dev_descr_knl, KNIGHTS_LANDING),
 	{0,}
 };
 
@@ -658,19 +657,7 @@ static const struct pci_id_descr pci_dev
 };
 
 static const struct pci_id_table pci_dev_descr_broadwell_table[] = {
-	PCI_ID_TABLE_ENTRY(pci_dev_descr_broadwell),
-	{0,}			/* 0 terminated list. */
-};
-
-/*
- *	pci_device_id	table for which devices we are looking for
- */
-static const struct pci_device_id sbridge_pci_tbl[] = {
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_KNL_IMC_SAD0)},
+	PCI_ID_TABLE_ENTRY(pci_dev_descr_broadwell, BROADWELL),
 	{0,}			/* 0 terminated list. */
 };
 
@@ -1916,14 +1903,14 @@ static void get_memory_layout(const stru
 				pci_read_config_dword(pvt->pci_tad[i],
 						      rir_offset[j][k],
 						      &reg);
-				tmp_mb = RIR_OFFSET(reg) << 6;
+				tmp_mb = RIR_OFFSET(pvt->info.type, reg) << 6;
 
 				gb = div_u64_rem(tmp_mb, 1024, &mb);
 				edac_dbg(0, "CH#%d RIR#%d INTL#%d, offset %u.%03u GB (0x%016Lx), tgt: %d, reg=0x%08x\n",
 					 i, j, k,
 					 gb, (mb*1000)/1024,
 					 ((u64)tmp_mb) << 20L,
-					 (u32)RIR_RNK_TGT(reg),
+					 (u32)RIR_RNK_TGT(pvt->info.type, reg),
 					 reg);
 			}
 		}
@@ -2256,7 +2243,7 @@ static int get_memory_error_data(struct
 	pci_read_config_dword(pvt->pci_tad[ch_add + base_ch],
 			      rir_offset[n_rir][idx],
 			      &reg);
-	*rank = RIR_RNK_TGT(reg);
+	*rank = RIR_RNK_TGT(pvt->info.type, reg);
 
 	edac_dbg(0, "RIR#%d: channel address 0x%08Lx < 0x%08Lx, RIR interleave %d, index %d\n",
 		 n_rir,
@@ -2391,22 +2378,19 @@ static int sbridge_get_onedevice(struct
  * @num_mc: pointer to the memory controllers count, to be incremented in case
  *	    of success.
  * @table: model specific table
- * @allow_dups: allow for multiple devices to exist with the same device id
- *              (as implemented, this isn't expected to work correctly in the
- *              multi-socket case).
- * @multi_bus: don't assume devices on different buses belong to different
- *             memory controllers.
  *
  * returns 0 in case of success or error code
  */
-static int sbridge_get_all_devices_full(u8 *num_mc,
-					const struct pci_id_table *table,
-					int allow_dups,
-					int multi_bus)
+static int sbridge_get_all_devices(u8 *num_mc,
+					const struct pci_id_table *table)
 {
 	int i, rc;
 	struct pci_dev *pdev = NULL;
+	int allow_dups = 0;
+	int multi_bus = 0;
 
+	if (table->type == KNIGHTS_LANDING)
+		allow_dups = multi_bus = 1;
 	while (table && table->descr) {
 		for (i = 0; i < table->n_devs; i++) {
 			if (!allow_dups || i == 0 ||
@@ -2433,11 +2417,6 @@ static int sbridge_get_all_devices_full(
 	return 0;
 }
 
-#define sbridge_get_all_devices(num_mc, table) \
-		sbridge_get_all_devices_full(num_mc, table, 0, 0)
-#define sbridge_get_all_devices_knl(num_mc, table) \
-		sbridge_get_all_devices_full(num_mc, table, 1, 1)
-
 static int sbridge_mci_bind_devs(struct mem_ctl_info *mci,
 				 struct sbridge_dev *sbridge_dev)
 {
@@ -3097,63 +3076,8 @@ err_parsing:
 }
 
 /*
- *	sbridge_check_error	Retrieve and process errors reported by the
- *				hardware. Called by the Core module.
- */
-static void sbridge_check_error(struct mem_ctl_info *mci)
-{
-	struct sbridge_pvt *pvt = mci->pvt_info;
-	int i;
-	unsigned count = 0;
-	struct mce *m;
-
-	/*
-	 * MCE first step: Copy all mce errors into a temporary buffer
-	 * We use a double buffering here, to reduce the risk of
-	 * loosing an error.
-	 */
-	smp_rmb();
-	count = (pvt->mce_out + MCE_LOG_LEN - pvt->mce_in)
-		% MCE_LOG_LEN;
-	if (!count)
-		return;
-
-	m = pvt->mce_outentry;
-	if (pvt->mce_in + count > MCE_LOG_LEN) {
-		unsigned l = MCE_LOG_LEN - pvt->mce_in;
-
-		memcpy(m, &pvt->mce_entry[pvt->mce_in], sizeof(*m) * l);
-		smp_wmb();
-		pvt->mce_in = 0;
-		count -= l;
-		m += l;
-	}
-	memcpy(m, &pvt->mce_entry[pvt->mce_in], sizeof(*m) * count);
-	smp_wmb();
-	pvt->mce_in += count;
-
-	smp_rmb();
-	if (pvt->mce_overrun) {
-		sbridge_printk(KERN_ERR, "Lost %d memory errors\n",
-			      pvt->mce_overrun);
-		smp_wmb();
-		pvt->mce_overrun = 0;
-	}
-
-	/*
-	 * MCE second step: parse errors and display
-	 */
-	for (i = 0; i < count; i++)
-		sbridge_mce_output_error(mci, &pvt->mce_outentry[i]);
-}
-
-/*
- * sbridge_mce_check_error	Replicates mcelog routine to get errors
- *				This routine simply queues mcelog errors, and
- *				return. The error itself should be handled later
- *				by sbridge_check_error.
- * WARNING: As this routine should be called at NMI time, extra care should
- * be taken to avoid deadlocks, and to be as fast as possible.
+ * Check that logging is enabled and that this is the right type
+ * of error for us to handle.
  */
 static int sbridge_mce_check_error(struct notifier_block *nb, unsigned long val,
 				   void *data)
@@ -3198,21 +3122,7 @@ static int sbridge_mce_check_error(struc
 			  "%u APIC %x\n", mce->cpuvendor, mce->cpuid,
 			  mce->time, mce->socketid, mce->apicid);
 
-	smp_rmb();
-	if ((pvt->mce_out + 1) % MCE_LOG_LEN == pvt->mce_in) {
-		smp_wmb();
-		pvt->mce_overrun++;
-		return NOTIFY_DONE;
-	}
-
-	/* Copy memory error at the ringbuffer */
-	memcpy(&pvt->mce_entry[pvt->mce_out], mce, sizeof(*mce));
-	smp_wmb();
-	pvt->mce_out = (pvt->mce_out + 1) % MCE_LOG_LEN;
-
-	/* Handle fatal errors immediately */
-	if (mce->mcgstatus & 1)
-		sbridge_check_error(mci);
+	sbridge_mce_output_error(mci, mce);
 
 	/* Advice mcelog that the error were handled */
 	return NOTIFY_STOP;
@@ -3298,9 +3208,6 @@ static int sbridge_register_mci(struct s
 	mci->dev_name = pci_name(pdev);
 	mci->ctl_page_to_phys = NULL;
 
-	/* Set the function pointer to an actual operation function */
-	mci->edac_check = sbridge_check_error;
-
 	pvt->info.type = type;
 	switch (type) {
 	case IVY_BRIDGE:
@@ -3448,62 +3355,40 @@ fail0:
 	return rc;
 }
 
+#define ICPU(model, table) \
+	{ X86_VENDOR_INTEL, 6, model, 0, (unsigned long)&table }
+
+static const struct x86_cpu_id sbridge_cpuids[] = {
+	ICPU(0x2d, pci_dev_descr_sbridge_table),	/* SANDY_BRIDGE */
+	ICPU(0x3e, pci_dev_descr_ibridge_table),	/* IVY_BRIDGE */
+	ICPU(0x3f, pci_dev_descr_haswell_table),	/* HASWELL */
+	ICPU(0x4f, pci_dev_descr_broadwell_table),	/* BROADWELL */
+	ICPU(0x56, pci_dev_descr_broadwell_table),	/* BROADWELL-DE */
+	ICPU(0x57, pci_dev_descr_knl_table),		/* KNIGHTS_LANDING */
+	{ }
+};
+MODULE_DEVICE_TABLE(x86cpu, sbridge_cpuids);
+
 /*
- *	sbridge_probe	Probe for ONE instance of device to see if it is
+ *	sbridge_probe	Get all devices and register memory controllers
  *			present.
  *	return:
  *		0 for FOUND a device
  *		< 0 for error code
  */
 
-static int sbridge_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+static int sbridge_probe(const struct x86_cpu_id *id)
 {
 	int rc = -ENODEV;
 	u8 mc, num_mc = 0;
 	struct sbridge_dev *sbridge_dev;
-	enum type type = SANDY_BRIDGE;
+	struct pci_id_table *ptable = (struct pci_id_table *)id->driver_data;
 
 	/* get the pci devices we want to reserve for our use */
-	mutex_lock(&sbridge_edac_lock);
-
-	/*
-	 * All memory controllers are allocated at the first pass.
-	 */
-	if (unlikely(probed >= 1)) {
-		mutex_unlock(&sbridge_edac_lock);
-		return -ENODEV;
-	}
-	probed++;
+	rc = sbridge_get_all_devices(&num_mc, ptable);
 
-	switch (pdev->device) {
-	case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA:
-		rc = sbridge_get_all_devices(&num_mc,
-					pci_dev_descr_ibridge_table);
-		type = IVY_BRIDGE;
-		break;
-	case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0:
-		rc = sbridge_get_all_devices(&num_mc,
-					pci_dev_descr_sbridge_table);
-		type = SANDY_BRIDGE;
-		break;
-	case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0:
-		rc = sbridge_get_all_devices(&num_mc,
-					pci_dev_descr_haswell_table);
-		type = HASWELL;
-		break;
-	case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0:
-		rc = sbridge_get_all_devices(&num_mc,
-					pci_dev_descr_broadwell_table);
-		type = BROADWELL;
-	    break;
-	case PCI_DEVICE_ID_INTEL_KNL_IMC_SAD0:
-		rc = sbridge_get_all_devices_knl(&num_mc,
-					pci_dev_descr_knl_table);
-		type = KNIGHTS_LANDING;
-		break;
-	}
 	if (unlikely(rc < 0)) {
-		edac_dbg(0, "couldn't get all devices for 0x%x\n", pdev->device);
+		edac_dbg(0, "couldn't get all devices\n");
 		goto fail0;
 	}
 
@@ -3514,14 +3399,13 @@ static int sbridge_probe(struct pci_dev
 			 mc, mc + 1, num_mc);
 
 		sbridge_dev->mc = mc++;
-		rc = sbridge_register_mci(sbridge_dev, type);
+		rc = sbridge_register_mci(sbridge_dev, ptable->type);
 		if (unlikely(rc < 0))
 			goto fail1;
 	}
 
 	sbridge_printk(KERN_INFO, "%s\n", SBRIDGE_REVISION);
 
-	mutex_unlock(&sbridge_edac_lock);
 	return 0;
 
 fail1:
@@ -3530,74 +3414,47 @@ fail1:
 
 	sbridge_put_all_devices();
 fail0:
-	mutex_unlock(&sbridge_edac_lock);
 	return rc;
 }
 
 /*
- *	sbridge_remove	destructor for one instance of device
+ *	sbridge_remove	cleanup
  *
  */
-static void sbridge_remove(struct pci_dev *pdev)
+static void sbridge_remove(void)
 {
 	struct sbridge_dev *sbridge_dev;
 
 	edac_dbg(0, "\n");
 
-	/*
-	 * we have a trouble here: pdev value for removal will be wrong, since
-	 * it will point to the X58 register used to detect that the machine
-	 * is a Nehalem or upper design. However, due to the way several PCI
-	 * devices are grouped together to provide MC functionality, we need
-	 * to use a different method for releasing the devices
-	 */
-
-	mutex_lock(&sbridge_edac_lock);
-
-	if (unlikely(!probed)) {
-		mutex_unlock(&sbridge_edac_lock);
-		return;
-	}
-
 	list_for_each_entry(sbridge_dev, &sbridge_edac_list, list)
 		sbridge_unregister_mci(sbridge_dev);
 
 	/* Release PCI resources */
 	sbridge_put_all_devices();
-
-	probed--;
-
-	mutex_unlock(&sbridge_edac_lock);
 }
 
-MODULE_DEVICE_TABLE(pci, sbridge_pci_tbl);
-
-/*
- *	sbridge_driver	pci_driver structure for this module
- *
- */
-static struct pci_driver sbridge_driver = {
-	.name     = "sbridge_edac",
-	.probe    = sbridge_probe,
-	.remove   = sbridge_remove,
-	.id_table = sbridge_pci_tbl,
-};
-
 /*
  *	sbridge_init		Module entry function
  *			Try to initialize this module for its devices
  */
 static int __init sbridge_init(void)
 {
-	int pci_rc;
+	const struct x86_cpu_id *id;
+	int rc;
 
 	edac_dbg(2, "\n");
 
+	id = x86_match_cpu(sbridge_cpuids);
+	if (!id)
+		return -ENODEV;
+
 	/* Ensure that the OPSTATE is set correctly for POLL or NMI */
 	opstate_init();
 
-	pci_rc = pci_register_driver(&sbridge_driver);
-	if (pci_rc >= 0) {
+	rc = sbridge_probe(id);
+
+	if (rc >= 0) {
 		mce_register_decode_chain(&sbridge_mce_dec);
 		if (get_edac_report_status() == EDAC_REPORTING_DISABLED)
 			sbridge_printk(KERN_WARNING, "Loading driver, error reporting disabled.\n");
@@ -3605,9 +3462,9 @@ static int __init sbridge_init(void)
 	}
 
 	sbridge_printk(KERN_ERR, "Failed to register device with error %d.\n",
-		      pci_rc);
+		      rc);
 
-	return pci_rc;
+	return rc;
 }
 
 /*
@@ -3617,7 +3474,7 @@ static int __init sbridge_init(void)
 static void __exit sbridge_exit(void)
 {
 	edac_dbg(2, "\n");
-	pci_unregister_driver(&sbridge_driver);
+	sbridge_remove();
 	mce_unregister_decode_chain(&sbridge_mce_dec);
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/extcon/extcon-palmas.c linux-libre-4.7-gnu/drivers/extcon/extcon-palmas.c
--- linux-libre-4.6-gnu/drivers/extcon/extcon-palmas.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/extcon/extcon-palmas.c	2016-07-24 15:23:50.000000000 -0400
@@ -360,6 +360,8 @@ static int palmas_usb_probe(struct platf
 
 	palmas_enable_irq(palmas_usb);
 	/* perform initial detection */
+	if (palmas_usb->enable_gpio_vbus_detection)
+		palmas_vbus_irq_handler(palmas_usb->gpio_vbus_irq, palmas_usb);
 	palmas_gpio_id_detect(&palmas_usb->wq_detectid.work);
 	device_set_wakeup_capable(&pdev->dev, true);
 	return 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/firewire/net.c linux-libre-4.7-gnu/drivers/firewire/net.c
--- linux-libre-4.6-gnu/drivers/firewire/net.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/firewire/net.c	2016-07-24 15:23:50.000000000 -0400
@@ -1023,7 +1023,7 @@ static int fwnet_send_packet(struct fwne
 
 	spin_unlock_irqrestore(&dev->lock, flags);
 
-	dev->netdev->trans_start = jiffies;
+	netif_trans_update(dev->netdev);
  out:
 	if (free)
 		fwnet_free_ptask(ptask);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/firmware/broadcom/bcm47xx_sprom.c linux-libre-4.7-gnu/drivers/firmware/broadcom/bcm47xx_sprom.c
--- linux-libre-4.6-gnu/drivers/firmware/broadcom/bcm47xx_sprom.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/firmware/broadcom/bcm47xx_sprom.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,737 @@
+/*
+ *  Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
+ *  Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
+ *  Copyright (C) 2006 Michael Buesch <m@bues.ch>
+ *  Copyright (C) 2010 Waldemar Brodkorb <wbx@openadk.org>
+ *  Copyright (C) 2010-2012 Hauke Mehrtens <hauke@hauke-m.de>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/bcm47xx_nvram.h>
+#include <linux/bcma/bcma.h>
+#include <linux/etherdevice.h>
+#include <linux/if_ether.h>
+#include <linux/ssb/ssb.h>
+
+static void create_key(const char *prefix, const char *postfix,
+		       const char *name, char *buf, int len)
+{
+	if (prefix && postfix)
+		snprintf(buf, len, "%s%s%s", prefix, name, postfix);
+	else if (prefix)
+		snprintf(buf, len, "%s%s", prefix, name);
+	else if (postfix)
+		snprintf(buf, len, "%s%s", name, postfix);
+	else
+		snprintf(buf, len, "%s", name);
+}
+
+static int get_nvram_var(const char *prefix, const char *postfix,
+			 const char *name, char *buf, int len, bool fallback)
+{
+	char key[40];
+	int err;
+
+	create_key(prefix, postfix, name, key, sizeof(key));
+
+	err = bcm47xx_nvram_getenv(key, buf, len);
+	if (fallback && err == -ENOENT && prefix) {
+		create_key(NULL, postfix, name, key, sizeof(key));
+		err = bcm47xx_nvram_getenv(key, buf, len);
+	}
+	return err;
+}
+
+#define NVRAM_READ_VAL(type)						\
+static void nvram_read_ ## type(const char *prefix,			\
+				const char *postfix, const char *name,	\
+				type *val, type allset, bool fallback)	\
+{									\
+	char buf[100];							\
+	int err;							\
+	type var;							\
+									\
+	err = get_nvram_var(prefix, postfix, name, buf, sizeof(buf),	\
+			    fallback);					\
+	if (err < 0)							\
+		return;							\
+	err = kstrto ## type(strim(buf), 0, &var);			\
+	if (err) {							\
+		pr_warn("can not parse nvram name %s%s%s with value %s got %i\n",	\
+			prefix, name, postfix, buf, err);		\
+		return;							\
+	}								\
+	if (allset && var == allset)					\
+		return;							\
+	*val = var;							\
+}
+
+NVRAM_READ_VAL(u8)
+NVRAM_READ_VAL(s8)
+NVRAM_READ_VAL(u16)
+NVRAM_READ_VAL(u32)
+
+#undef NVRAM_READ_VAL
+
+static void nvram_read_u32_2(const char *prefix, const char *name,
+			     u16 *val_lo, u16 *val_hi, bool fallback)
+{
+	char buf[100];
+	int err;
+	u32 val;
+
+	err = get_nvram_var(prefix, NULL, name, buf, sizeof(buf), fallback);
+	if (err < 0)
+		return;
+	err = kstrtou32(strim(buf), 0, &val);
+	if (err) {
+		pr_warn("can not parse nvram name %s%s with value %s got %i\n",
+			prefix, name, buf, err);
+		return;
+	}
+	*val_lo = (val & 0x0000FFFFU);
+	*val_hi = (val & 0xFFFF0000U) >> 16;
+}
+
+static void nvram_read_leddc(const char *prefix, const char *name,
+			     u8 *leddc_on_time, u8 *leddc_off_time,
+			     bool fallback)
+{
+	char buf[100];
+	int err;
+	u32 val;
+
+	err = get_nvram_var(prefix, NULL, name, buf, sizeof(buf), fallback);
+	if (err < 0)
+		return;
+	err = kstrtou32(strim(buf), 0, &val);
+	if (err) {
+		pr_warn("can not parse nvram name %s%s with value %s got %i\n",
+			prefix, name, buf, err);
+		return;
+	}
+
+	if (val == 0xffff || val == 0xffffffff)
+		return;
+
+	*leddc_on_time = val & 0xff;
+	*leddc_off_time = (val >> 16) & 0xff;
+}
+
+static void bcm47xx_nvram_parse_macaddr(char *buf, u8 macaddr[6])
+{
+	if (strchr(buf, ':'))
+		sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0],
+			&macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4],
+			&macaddr[5]);
+	else if (strchr(buf, '-'))
+		sscanf(buf, "%hhx-%hhx-%hhx-%hhx-%hhx-%hhx", &macaddr[0],
+			&macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4],
+			&macaddr[5]);
+	else
+		pr_warn("Can not parse mac address: %s\n", buf);
+}
+
+static void nvram_read_macaddr(const char *prefix, const char *name,
+			       u8 val[6], bool fallback)
+{
+	char buf[100];
+	int err;
+
+	err = get_nvram_var(prefix, NULL, name, buf, sizeof(buf), fallback);
+	if (err < 0)
+		return;
+
+	bcm47xx_nvram_parse_macaddr(buf, val);
+}
+
+static void nvram_read_alpha2(const char *prefix, const char *name,
+			     char val[2], bool fallback)
+{
+	char buf[10];
+	int err;
+
+	err = get_nvram_var(prefix, NULL, name, buf, sizeof(buf), fallback);
+	if (err < 0)
+		return;
+	if (buf[0] == '0')
+		return;
+	if (strlen(buf) > 2) {
+		pr_warn("alpha2 is too long %s\n", buf);
+		return;
+	}
+	memcpy(val, buf, 2);
+}
+
+/* This is one-function-only macro, it uses local "sprom" variable! */
+#define ENTRY(_revmask, _type, _prefix, _name, _val, _allset, _fallback) \
+	if (_revmask & BIT(sprom->revision)) \
+		nvram_read_ ## _type(_prefix, NULL, _name, &sprom->_val, \
+				     _allset, _fallback)
+/*
+ * Special version of filling function that can be safely called for any SPROM
+ * revision. For every NVRAM to SPROM mapping it contains bitmask of revisions
+ * for which the mapping is valid.
+ * It obviously requires some hexadecimal/bitmasks knowledge, but allows
+ * writing cleaner code (easy revisions handling).
+ * Note that while SPROM revision 0 was never used, we still keep BIT(0)
+ * reserved for it, just to keep numbering sane.
+ */
+static void bcm47xx_sprom_fill_auto(struct ssb_sprom *sprom,
+				    const char *prefix, bool fallback)
+{
+	const char *pre = prefix;
+	bool fb = fallback;
+
+	/* Broadcom extracts it for rev 8+ but it was found on 2 and 4 too */
+	ENTRY(0xfffffffe, u16, pre, "devid", dev_id, 0, fallback);
+
+	ENTRY(0xfffffffe, u16, pre, "boardrev", board_rev, 0, true);
+	ENTRY(0xfffffffe, u32, pre, "boardflags", boardflags, 0, fb);
+	ENTRY(0xfffffff0, u32, pre, "boardflags2", boardflags2, 0, fb);
+	ENTRY(0xfffff800, u32, pre, "boardflags3", boardflags3, 0, fb);
+	ENTRY(0x00000002, u16, pre, "boardflags", boardflags_lo, 0, fb);
+	ENTRY(0xfffffffc, u16, pre, "boardtype", board_type, 0, true);
+	ENTRY(0xfffffffe, u16, pre, "boardnum", board_num, 0, fb);
+	ENTRY(0x00000002, u8, pre, "cc", country_code, 0, fb);
+	ENTRY(0xfffffff8, u8, pre, "regrev", regrev, 0, fb);
+
+	ENTRY(0xfffffffe, u8, pre, "ledbh0", gpio0, 0xff, fb);
+	ENTRY(0xfffffffe, u8, pre, "ledbh1", gpio1, 0xff, fb);
+	ENTRY(0xfffffffe, u8, pre, "ledbh2", gpio2, 0xff, fb);
+	ENTRY(0xfffffffe, u8, pre, "ledbh3", gpio3, 0xff, fb);
+
+	ENTRY(0x0000070e, u16, pre, "pa0b0", pa0b0, 0, fb);
+	ENTRY(0x0000070e, u16, pre, "pa0b1", pa0b1, 0, fb);
+	ENTRY(0x0000070e, u16, pre, "pa0b2", pa0b2, 0, fb);
+	ENTRY(0x0000070e, u8, pre, "pa0itssit", itssi_bg, 0, fb);
+	ENTRY(0x0000070e, u8, pre, "pa0maxpwr", maxpwr_bg, 0, fb);
+
+	ENTRY(0x0000070c, u8, pre, "opo", opo, 0, fb);
+	ENTRY(0xfffffffe, u8, pre, "aa2g", ant_available_bg, 0, fb);
+	ENTRY(0xfffffffe, u8, pre, "aa5g", ant_available_a, 0, fb);
+	ENTRY(0x000007fe, s8, pre, "ag0", antenna_gain.a0, 0, fb);
+	ENTRY(0x000007fe, s8, pre, "ag1", antenna_gain.a1, 0, fb);
+	ENTRY(0x000007f0, s8, pre, "ag2", antenna_gain.a2, 0, fb);
+	ENTRY(0x000007f0, s8, pre, "ag3", antenna_gain.a3, 0, fb);
+
+	ENTRY(0x0000070e, u16, pre, "pa1b0", pa1b0, 0, fb);
+	ENTRY(0x0000070e, u16, pre, "pa1b1", pa1b1, 0, fb);
+	ENTRY(0x0000070e, u16, pre, "pa1b2", pa1b2, 0, fb);
+	ENTRY(0x0000070c, u16, pre, "pa1lob0", pa1lob0, 0, fb);
+	ENTRY(0x0000070c, u16, pre, "pa1lob1", pa1lob1, 0, fb);
+	ENTRY(0x0000070c, u16, pre, "pa1lob2", pa1lob2, 0, fb);
+	ENTRY(0x0000070c, u16, pre, "pa1hib0", pa1hib0, 0, fb);
+	ENTRY(0x0000070c, u16, pre, "pa1hib1", pa1hib1, 0, fb);
+	ENTRY(0x0000070c, u16, pre, "pa1hib2", pa1hib2, 0, fb);
+	ENTRY(0x0000070e, u8, pre, "pa1itssit", itssi_a, 0, fb);
+	ENTRY(0x0000070e, u8, pre, "pa1maxpwr", maxpwr_a, 0, fb);
+	ENTRY(0x0000070c, u8, pre, "pa1lomaxpwr", maxpwr_al, 0, fb);
+	ENTRY(0x0000070c, u8, pre, "pa1himaxpwr", maxpwr_ah, 0, fb);
+
+	ENTRY(0x00000708, u8, pre, "bxa2g", bxa2g, 0, fb);
+	ENTRY(0x00000708, u8, pre, "rssisav2g", rssisav2g, 0, fb);
+	ENTRY(0x00000708, u8, pre, "rssismc2g", rssismc2g, 0, fb);
+	ENTRY(0x00000708, u8, pre, "rssismf2g", rssismf2g, 0, fb);
+	ENTRY(0x00000708, u8, pre, "bxa5g", bxa5g, 0, fb);
+	ENTRY(0x00000708, u8, pre, "rssisav5g", rssisav5g, 0, fb);
+	ENTRY(0x00000708, u8, pre, "rssismc5g", rssismc5g, 0, fb);
+	ENTRY(0x00000708, u8, pre, "rssismf5g", rssismf5g, 0, fb);
+	ENTRY(0x00000708, u8, pre, "tri2g", tri2g, 0, fb);
+	ENTRY(0x00000708, u8, pre, "tri5g", tri5g, 0, fb);
+	ENTRY(0x00000708, u8, pre, "tri5gl", tri5gl, 0, fb);
+	ENTRY(0x00000708, u8, pre, "tri5gh", tri5gh, 0, fb);
+	ENTRY(0x00000708, s8, pre, "rxpo2g", rxpo2g, 0, fb);
+	ENTRY(0x00000708, s8, pre, "rxpo5g", rxpo5g, 0, fb);
+	ENTRY(0xfffffff0, u8, pre, "txchain", txchain, 0xf, fb);
+	ENTRY(0xfffffff0, u8, pre, "rxchain", rxchain, 0xf, fb);
+	ENTRY(0xfffffff0, u8, pre, "antswitch", antswitch, 0xff, fb);
+	ENTRY(0x00000700, u8, pre, "tssipos2g", fem.ghz2.tssipos, 0, fb);
+	ENTRY(0x00000700, u8, pre, "extpagain2g", fem.ghz2.extpa_gain, 0, fb);
+	ENTRY(0x00000700, u8, pre, "pdetrange2g", fem.ghz2.pdet_range, 0, fb);
+	ENTRY(0x00000700, u8, pre, "triso2g", fem.ghz2.tr_iso, 0, fb);
+	ENTRY(0x00000700, u8, pre, "antswctl2g", fem.ghz2.antswlut, 0, fb);
+	ENTRY(0x00000700, u8, pre, "tssipos5g", fem.ghz5.tssipos, 0, fb);
+	ENTRY(0x00000700, u8, pre, "extpagain5g", fem.ghz5.extpa_gain, 0, fb);
+	ENTRY(0x00000700, u8, pre, "pdetrange5g", fem.ghz5.pdet_range, 0, fb);
+	ENTRY(0x00000700, u8, pre, "triso5g", fem.ghz5.tr_iso, 0, fb);
+	ENTRY(0x00000700, u8, pre, "antswctl5g", fem.ghz5.antswlut, 0, fb);
+	ENTRY(0x000000f0, u8, pre, "txpid2ga0", txpid2g[0], 0, fb);
+	ENTRY(0x000000f0, u8, pre, "txpid2ga1", txpid2g[1], 0, fb);
+	ENTRY(0x000000f0, u8, pre, "txpid2ga2", txpid2g[2], 0, fb);
+	ENTRY(0x000000f0, u8, pre, "txpid2ga3", txpid2g[3], 0, fb);
+	ENTRY(0x000000f0, u8, pre, "txpid5ga0", txpid5g[0], 0, fb);
+	ENTRY(0x000000f0, u8, pre, "txpid5ga1", txpid5g[1], 0, fb);
+	ENTRY(0x000000f0, u8, pre, "txpid5ga2", txpid5g[2], 0, fb);
+	ENTRY(0x000000f0, u8, pre, "txpid5ga3", txpid5g[3], 0, fb);
+	ENTRY(0x000000f0, u8, pre, "txpid5gla0", txpid5gl[0], 0, fb);
+	ENTRY(0x000000f0, u8, pre, "txpid5gla1", txpid5gl[1], 0, fb);
+	ENTRY(0x000000f0, u8, pre, "txpid5gla2", txpid5gl[2], 0, fb);
+	ENTRY(0x000000f0, u8, pre, "txpid5gla3", txpid5gl[3], 0, fb);
+	ENTRY(0x000000f0, u8, pre, "txpid5gha0", txpid5gh[0], 0, fb);
+	ENTRY(0x000000f0, u8, pre, "txpid5gha1", txpid5gh[1], 0, fb);
+	ENTRY(0x000000f0, u8, pre, "txpid5gha2", txpid5gh[2], 0, fb);
+	ENTRY(0x000000f0, u8, pre, "txpid5gha3", txpid5gh[3], 0, fb);
+
+	ENTRY(0xffffff00, u8, pre, "tempthresh", tempthresh, 0, fb);
+	ENTRY(0xffffff00, u8, pre, "tempoffset", tempoffset, 0, fb);
+	ENTRY(0xffffff00, u16, pre, "rawtempsense", rawtempsense, 0, fb);
+	ENTRY(0xffffff00, u8, pre, "measpower", measpower, 0, fb);
+	ENTRY(0xffffff00, u8, pre, "tempsense_slope", tempsense_slope, 0, fb);
+	ENTRY(0xffffff00, u8, pre, "tempcorrx", tempcorrx, 0, fb);
+	ENTRY(0xffffff00, u8, pre, "tempsense_option", tempsense_option, 0, fb);
+	ENTRY(0x00000700, u8, pre, "freqoffset_corr", freqoffset_corr, 0, fb);
+	ENTRY(0x00000700, u8, pre, "iqcal_swp_dis", iqcal_swp_dis, 0, fb);
+	ENTRY(0x00000700, u8, pre, "hw_iqcal_en", hw_iqcal_en, 0, fb);
+	ENTRY(0x00000700, u8, pre, "elna2g", elna2g, 0, fb);
+	ENTRY(0x00000700, u8, pre, "elna5g", elna5g, 0, fb);
+	ENTRY(0xffffff00, u8, pre, "phycal_tempdelta", phycal_tempdelta, 0, fb);
+	ENTRY(0xffffff00, u8, pre, "temps_period", temps_period, 0, fb);
+	ENTRY(0xffffff00, u8, pre, "temps_hysteresis", temps_hysteresis, 0, fb);
+	ENTRY(0xffffff00, u8, pre, "measpower1", measpower1, 0, fb);
+	ENTRY(0xffffff00, u8, pre, "measpower2", measpower2, 0, fb);
+
+	ENTRY(0x000001f0, u16, pre, "cck2gpo", cck2gpo, 0, fb);
+	ENTRY(0x000001f0, u32, pre, "ofdm2gpo", ofdm2gpo, 0, fb);
+	ENTRY(0x000001f0, u32, pre, "ofdm5gpo", ofdm5gpo, 0, fb);
+	ENTRY(0x000001f0, u32, pre, "ofdm5glpo", ofdm5glpo, 0, fb);
+	ENTRY(0x000001f0, u32, pre, "ofdm5ghpo", ofdm5ghpo, 0, fb);
+	ENTRY(0x000001f0, u16, pre, "mcs2gpo0", mcs2gpo[0], 0, fb);
+	ENTRY(0x000001f0, u16, pre, "mcs2gpo1", mcs2gpo[1], 0, fb);
+	ENTRY(0x000001f0, u16, pre, "mcs2gpo2", mcs2gpo[2], 0, fb);
+	ENTRY(0x000001f0, u16, pre, "mcs2gpo3", mcs2gpo[3], 0, fb);
+	ENTRY(0x000001f0, u16, pre, "mcs2gpo4", mcs2gpo[4], 0, fb);
+	ENTRY(0x000001f0, u16, pre, "mcs2gpo5", mcs2gpo[5], 0, fb);
+	ENTRY(0x000001f0, u16, pre, "mcs2gpo6", mcs2gpo[6], 0, fb);
+	ENTRY(0x000001f0, u16, pre, "mcs2gpo7", mcs2gpo[7], 0, fb);
+	ENTRY(0x000001f0, u16, pre, "mcs5gpo0", mcs5gpo[0], 0, fb);
+	ENTRY(0x000001f0, u16, pre, "mcs5gpo1", mcs5gpo[1], 0, fb);
+	ENTRY(0x000001f0, u16, pre, "mcs5gpo2", mcs5gpo[2], 0, fb);
+	ENTRY(0x000001f0, u16, pre, "mcs5gpo3", mcs5gpo[3], 0, fb);
+	ENTRY(0x000001f0, u16, pre, "mcs5gpo4", mcs5gpo[4], 0, fb);
+	ENTRY(0x000001f0, u16, pre, "mcs5gpo5", mcs5gpo[5], 0, fb);
+	ENTRY(0x000001f0, u16, pre, "mcs5gpo6", mcs5gpo[6], 0, fb);
+	ENTRY(0x000001f0, u16, pre, "mcs5gpo7", mcs5gpo[7], 0, fb);
+	ENTRY(0x000001f0, u16, pre, "mcs5glpo0", mcs5glpo[0], 0, fb);
+	ENTRY(0x000001f0, u16, pre, "mcs5glpo1", mcs5glpo[1], 0, fb);
+	ENTRY(0x000001f0, u16, pre, "mcs5glpo2", mcs5glpo[2], 0, fb);
+	ENTRY(0x000001f0, u16, pre, "mcs5glpo3", mcs5glpo[3], 0, fb);
+	ENTRY(0x000001f0, u16, pre, "mcs5glpo4", mcs5glpo[4], 0, fb);
+	ENTRY(0x000001f0, u16, pre, "mcs5glpo5", mcs5glpo[5], 0, fb);
+	ENTRY(0x000001f0, u16, pre, "mcs5glpo6", mcs5glpo[6], 0, fb);
+	ENTRY(0x000001f0, u16, pre, "mcs5glpo7", mcs5glpo[7], 0, fb);
+	ENTRY(0x000001f0, u16, pre, "mcs5ghpo0", mcs5ghpo[0], 0, fb);
+	ENTRY(0x000001f0, u16, pre, "mcs5ghpo1", mcs5ghpo[1], 0, fb);
+	ENTRY(0x000001f0, u16, pre, "mcs5ghpo2", mcs5ghpo[2], 0, fb);
+	ENTRY(0x000001f0, u16, pre, "mcs5ghpo3", mcs5ghpo[3], 0, fb);
+	ENTRY(0x000001f0, u16, pre, "mcs5ghpo4", mcs5ghpo[4], 0, fb);
+	ENTRY(0x000001f0, u16, pre, "mcs5ghpo5", mcs5ghpo[5], 0, fb);
+	ENTRY(0x000001f0, u16, pre, "mcs5ghpo6", mcs5ghpo[6], 0, fb);
+	ENTRY(0x000001f0, u16, pre, "mcs5ghpo7", mcs5ghpo[7], 0, fb);
+	ENTRY(0x000001f0, u16, pre, "cddpo", cddpo, 0, fb);
+	ENTRY(0x000001f0, u16, pre, "stbcpo", stbcpo, 0, fb);
+	ENTRY(0x000001f0, u16, pre, "bw40po", bw40po, 0, fb);
+	ENTRY(0x000001f0, u16, pre, "bwduppo", bwduppo, 0, fb);
+
+	ENTRY(0xfffffe00, u16, pre, "cckbw202gpo", cckbw202gpo, 0, fb);
+	ENTRY(0xfffffe00, u16, pre, "cckbw20ul2gpo", cckbw20ul2gpo, 0, fb);
+	ENTRY(0x00000600, u32, pre, "legofdmbw202gpo", legofdmbw202gpo, 0, fb);
+	ENTRY(0x00000600, u32, pre, "legofdmbw20ul2gpo", legofdmbw20ul2gpo, 0, fb);
+	ENTRY(0x00000600, u32, pre, "legofdmbw205glpo", legofdmbw205glpo, 0, fb);
+	ENTRY(0x00000600, u32, pre, "legofdmbw20ul5glpo", legofdmbw20ul5glpo, 0, fb);
+	ENTRY(0x00000600, u32, pre, "legofdmbw205gmpo", legofdmbw205gmpo, 0, fb);
+	ENTRY(0x00000600, u32, pre, "legofdmbw20ul5gmpo", legofdmbw20ul5gmpo, 0, fb);
+	ENTRY(0x00000600, u32, pre, "legofdmbw205ghpo", legofdmbw205ghpo, 0, fb);
+	ENTRY(0x00000600, u32, pre, "legofdmbw20ul5ghpo", legofdmbw20ul5ghpo, 0, fb);
+	ENTRY(0xfffffe00, u32, pre, "mcsbw202gpo", mcsbw202gpo, 0, fb);
+	ENTRY(0x00000600, u32, pre, "mcsbw20ul2gpo", mcsbw20ul2gpo, 0, fb);
+	ENTRY(0xfffffe00, u32, pre, "mcsbw402gpo", mcsbw402gpo, 0, fb);
+	ENTRY(0xfffffe00, u32, pre, "mcsbw205glpo", mcsbw205glpo, 0, fb);
+	ENTRY(0x00000600, u32, pre, "mcsbw20ul5glpo", mcsbw20ul5glpo, 0, fb);
+	ENTRY(0xfffffe00, u32, pre, "mcsbw405glpo", mcsbw405glpo, 0, fb);
+	ENTRY(0xfffffe00, u32, pre, "mcsbw205gmpo", mcsbw205gmpo, 0, fb);
+	ENTRY(0x00000600, u32, pre, "mcsbw20ul5gmpo", mcsbw20ul5gmpo, 0, fb);
+	ENTRY(0xfffffe00, u32, pre, "mcsbw405gmpo", mcsbw405gmpo, 0, fb);
+	ENTRY(0xfffffe00, u32, pre, "mcsbw205ghpo", mcsbw205ghpo, 0, fb);
+	ENTRY(0x00000600, u32, pre, "mcsbw20ul5ghpo", mcsbw20ul5ghpo, 0, fb);
+	ENTRY(0xfffffe00, u32, pre, "mcsbw405ghpo", mcsbw405ghpo, 0, fb);
+	ENTRY(0x00000600, u16, pre, "mcs32po", mcs32po, 0, fb);
+	ENTRY(0x00000600, u16, pre, "legofdm40duppo", legofdm40duppo, 0, fb);
+	ENTRY(0x00000700, u8, pre, "pcieingress_war", pcieingress_war, 0, fb);
+
+	/* TODO: rev 11 support */
+	ENTRY(0x00000700, u8, pre, "rxgainerr2ga0", rxgainerr2ga[0], 0, fb);
+	ENTRY(0x00000700, u8, pre, "rxgainerr2ga1", rxgainerr2ga[1], 0, fb);
+	ENTRY(0x00000700, u8, pre, "rxgainerr2ga2", rxgainerr2ga[2], 0, fb);
+	ENTRY(0x00000700, u8, pre, "rxgainerr5gla0", rxgainerr5gla[0], 0, fb);
+	ENTRY(0x00000700, u8, pre, "rxgainerr5gla1", rxgainerr5gla[1], 0, fb);
+	ENTRY(0x00000700, u8, pre, "rxgainerr5gla2", rxgainerr5gla[2], 0, fb);
+	ENTRY(0x00000700, u8, pre, "rxgainerr5gma0", rxgainerr5gma[0], 0, fb);
+	ENTRY(0x00000700, u8, pre, "rxgainerr5gma1", rxgainerr5gma[1], 0, fb);
+	ENTRY(0x00000700, u8, pre, "rxgainerr5gma2", rxgainerr5gma[2], 0, fb);
+	ENTRY(0x00000700, u8, pre, "rxgainerr5gha0", rxgainerr5gha[0], 0, fb);
+	ENTRY(0x00000700, u8, pre, "rxgainerr5gha1", rxgainerr5gha[1], 0, fb);
+	ENTRY(0x00000700, u8, pre, "rxgainerr5gha2", rxgainerr5gha[2], 0, fb);
+	ENTRY(0x00000700, u8, pre, "rxgainerr5gua0", rxgainerr5gua[0], 0, fb);
+	ENTRY(0x00000700, u8, pre, "rxgainerr5gua1", rxgainerr5gua[1], 0, fb);
+	ENTRY(0x00000700, u8, pre, "rxgainerr5gua2", rxgainerr5gua[2], 0, fb);
+
+	ENTRY(0xfffffe00, u8, pre, "sar2g", sar2g, 0, fb);
+	ENTRY(0xfffffe00, u8, pre, "sar5g", sar5g, 0, fb);
+
+	/* TODO: rev 11 support */
+	ENTRY(0x00000700, u8, pre, "noiselvl2ga0", noiselvl2ga[0], 0, fb);
+	ENTRY(0x00000700, u8, pre, "noiselvl2ga1", noiselvl2ga[1], 0, fb);
+	ENTRY(0x00000700, u8, pre, "noiselvl2ga2", noiselvl2ga[2], 0, fb);
+	ENTRY(0x00000700, u8, pre, "noiselvl5gla0", noiselvl5gla[0], 0, fb);
+	ENTRY(0x00000700, u8, pre, "noiselvl5gla1", noiselvl5gla[1], 0, fb);
+	ENTRY(0x00000700, u8, pre, "noiselvl5gla2", noiselvl5gla[2], 0, fb);
+	ENTRY(0x00000700, u8, pre, "noiselvl5gma0", noiselvl5gma[0], 0, fb);
+	ENTRY(0x00000700, u8, pre, "noiselvl5gma1", noiselvl5gma[1], 0, fb);
+	ENTRY(0x00000700, u8, pre, "noiselvl5gma2", noiselvl5gma[2], 0, fb);
+	ENTRY(0x00000700, u8, pre, "noiselvl5gha0", noiselvl5gha[0], 0, fb);
+	ENTRY(0x00000700, u8, pre, "noiselvl5gha1", noiselvl5gha[1], 0, fb);
+	ENTRY(0x00000700, u8, pre, "noiselvl5gha2", noiselvl5gha[2], 0, fb);
+	ENTRY(0x00000700, u8, pre, "noiselvl5gua0", noiselvl5gua[0], 0, fb);
+	ENTRY(0x00000700, u8, pre, "noiselvl5gua1", noiselvl5gua[1], 0, fb);
+	ENTRY(0x00000700, u8, pre, "noiselvl5gua2", noiselvl5gua[2], 0, fb);
+}
+#undef ENTRY /* It's specififc, uses local variable, don't use it (again). */
+
+static void bcm47xx_fill_sprom_path_r4589(struct ssb_sprom *sprom,
+					  const char *prefix, bool fallback)
+{
+	char postfix[2];
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(sprom->core_pwr_info); i++) {
+		struct ssb_sprom_core_pwr_info *pwr_info;
+
+		pwr_info = &sprom->core_pwr_info[i];
+
+		snprintf(postfix, sizeof(postfix), "%i", i);
+		nvram_read_u8(prefix, postfix, "maxp2ga",
+			      &pwr_info->maxpwr_2g, 0, fallback);
+		nvram_read_u8(prefix, postfix, "itt2ga",
+			      &pwr_info->itssi_2g, 0, fallback);
+		nvram_read_u8(prefix, postfix, "itt5ga",
+			      &pwr_info->itssi_5g, 0, fallback);
+		nvram_read_u16(prefix, postfix, "pa2gw0a",
+			       &pwr_info->pa_2g[0], 0, fallback);
+		nvram_read_u16(prefix, postfix, "pa2gw1a",
+			       &pwr_info->pa_2g[1], 0, fallback);
+		nvram_read_u16(prefix, postfix, "pa2gw2a",
+			       &pwr_info->pa_2g[2], 0, fallback);
+		nvram_read_u8(prefix, postfix, "maxp5ga",
+			      &pwr_info->maxpwr_5g, 0, fallback);
+		nvram_read_u8(prefix, postfix, "maxp5gha",
+			      &pwr_info->maxpwr_5gh, 0, fallback);
+		nvram_read_u8(prefix, postfix, "maxp5gla",
+			      &pwr_info->maxpwr_5gl, 0, fallback);
+		nvram_read_u16(prefix, postfix, "pa5gw0a",
+			       &pwr_info->pa_5g[0], 0, fallback);
+		nvram_read_u16(prefix, postfix, "pa5gw1a",
+			       &pwr_info->pa_5g[1], 0, fallback);
+		nvram_read_u16(prefix, postfix, "pa5gw2a",
+			       &pwr_info->pa_5g[2], 0, fallback);
+		nvram_read_u16(prefix, postfix, "pa5glw0a",
+			       &pwr_info->pa_5gl[0], 0, fallback);
+		nvram_read_u16(prefix, postfix, "pa5glw1a",
+			       &pwr_info->pa_5gl[1], 0, fallback);
+		nvram_read_u16(prefix, postfix, "pa5glw2a",
+			       &pwr_info->pa_5gl[2], 0, fallback);
+		nvram_read_u16(prefix, postfix, "pa5ghw0a",
+			       &pwr_info->pa_5gh[0], 0, fallback);
+		nvram_read_u16(prefix, postfix, "pa5ghw1a",
+			       &pwr_info->pa_5gh[1], 0, fallback);
+		nvram_read_u16(prefix, postfix, "pa5ghw2a",
+			       &pwr_info->pa_5gh[2], 0, fallback);
+	}
+}
+
+static void bcm47xx_fill_sprom_path_r45(struct ssb_sprom *sprom,
+					const char *prefix, bool fallback)
+{
+	char postfix[2];
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(sprom->core_pwr_info); i++) {
+		struct ssb_sprom_core_pwr_info *pwr_info;
+
+		pwr_info = &sprom->core_pwr_info[i];
+
+		snprintf(postfix, sizeof(postfix), "%i", i);
+		nvram_read_u16(prefix, postfix, "pa2gw3a",
+			       &pwr_info->pa_2g[3], 0, fallback);
+		nvram_read_u16(prefix, postfix, "pa5gw3a",
+			       &pwr_info->pa_5g[3], 0, fallback);
+		nvram_read_u16(prefix, postfix, "pa5glw3a",
+			       &pwr_info->pa_5gl[3], 0, fallback);
+		nvram_read_u16(prefix, postfix, "pa5ghw3a",
+			       &pwr_info->pa_5gh[3], 0, fallback);
+	}
+}
+
+static bool bcm47xx_is_valid_mac(u8 *mac)
+{
+	return mac && !(mac[0] == 0x00 && mac[1] == 0x90 && mac[2] == 0x4c);
+}
+
+static int bcm47xx_increase_mac_addr(u8 *mac, u8 num)
+{
+	u8 *oui = mac + ETH_ALEN/2 - 1;
+	u8 *p = mac + ETH_ALEN - 1;
+
+	do {
+		(*p) += num;
+		if (*p > num)
+			break;
+		p--;
+		num = 1;
+	} while (p != oui);
+
+	if (p == oui) {
+		pr_err("unable to fetch mac address\n");
+		return -ENOENT;
+	}
+	return 0;
+}
+
+static int mac_addr_used = 2;
+
+static void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom,
+					const char *prefix, bool fallback)
+{
+	bool fb = fallback;
+
+	nvram_read_macaddr(prefix, "et0macaddr", sprom->et0mac, fallback);
+	nvram_read_u8(prefix, NULL, "et0mdcport", &sprom->et0mdcport, 0,
+		      fallback);
+	nvram_read_u8(prefix, NULL, "et0phyaddr", &sprom->et0phyaddr, 0,
+		      fallback);
+
+	nvram_read_macaddr(prefix, "et1macaddr", sprom->et1mac, fallback);
+	nvram_read_u8(prefix, NULL, "et1mdcport", &sprom->et1mdcport, 0,
+		      fallback);
+	nvram_read_u8(prefix, NULL, "et1phyaddr", &sprom->et1phyaddr, 0,
+		      fallback);
+
+	nvram_read_macaddr(prefix, "et2macaddr", sprom->et2mac, fb);
+	nvram_read_u8(prefix, NULL, "et2mdcport", &sprom->et2mdcport, 0, fb);
+	nvram_read_u8(prefix, NULL, "et2phyaddr", &sprom->et2phyaddr, 0, fb);
+
+	nvram_read_macaddr(prefix, "macaddr", sprom->il0mac, fallback);
+	nvram_read_macaddr(prefix, "il0macaddr", sprom->il0mac, fallback);
+
+	/* The address prefix 00:90:4C is used by Broadcom in their initial
+	 * configuration. When a mac address with the prefix 00:90:4C is used
+	 * all devices from the same series are sharing the same mac address.
+	 * To prevent mac address collisions we replace them with a mac address
+	 * based on the base address.
+	 */
+	if (!bcm47xx_is_valid_mac(sprom->il0mac)) {
+		u8 mac[6];
+
+		nvram_read_macaddr(NULL, "et0macaddr", mac, false);
+		if (bcm47xx_is_valid_mac(mac)) {
+			int err = bcm47xx_increase_mac_addr(mac, mac_addr_used);
+
+			if (!err) {
+				ether_addr_copy(sprom->il0mac, mac);
+				mac_addr_used++;
+			}
+		}
+	}
+}
+
+static void bcm47xx_fill_board_data(struct ssb_sprom *sprom, const char *prefix,
+				    bool fallback)
+{
+	nvram_read_u32_2(prefix, "boardflags", &sprom->boardflags_lo,
+			 &sprom->boardflags_hi, fallback);
+	nvram_read_u32_2(prefix, "boardflags2", &sprom->boardflags2_lo,
+			 &sprom->boardflags2_hi, fallback);
+}
+
+void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix,
+			bool fallback)
+{
+	bcm47xx_fill_sprom_ethernet(sprom, prefix, fallback);
+	bcm47xx_fill_board_data(sprom, prefix, fallback);
+
+	nvram_read_u8(prefix, NULL, "sromrev", &sprom->revision, 0, fallback);
+
+	/* Entries requiring custom functions */
+	nvram_read_alpha2(prefix, "ccode", sprom->alpha2, fallback);
+	if (sprom->revision >= 3)
+		nvram_read_leddc(prefix, "leddc", &sprom->leddc_on_time,
+				 &sprom->leddc_off_time, fallback);
+
+	switch (sprom->revision) {
+	case 4:
+	case 5:
+		bcm47xx_fill_sprom_path_r4589(sprom, prefix, fallback);
+		bcm47xx_fill_sprom_path_r45(sprom, prefix, fallback);
+		break;
+	case 8:
+	case 9:
+		bcm47xx_fill_sprom_path_r4589(sprom, prefix, fallback);
+		break;
+	}
+
+	bcm47xx_sprom_fill_auto(sprom, prefix, fallback);
+}
+
+#if IS_BUILTIN(CONFIG_SSB) && IS_ENABLED(CONFIG_SSB_SPROM)
+static int bcm47xx_get_sprom_ssb(struct ssb_bus *bus, struct ssb_sprom *out)
+{
+	char prefix[10];
+
+	switch (bus->bustype) {
+	case SSB_BUSTYPE_SSB:
+		bcm47xx_fill_sprom(out, NULL, false);
+		return 0;
+	case SSB_BUSTYPE_PCI:
+		memset(out, 0, sizeof(struct ssb_sprom));
+		snprintf(prefix, sizeof(prefix), "pci/%u/%u/",
+			 bus->host_pci->bus->number + 1,
+			 PCI_SLOT(bus->host_pci->devfn));
+		bcm47xx_fill_sprom(out, prefix, false);
+		return 0;
+	default:
+		pr_warn("Unable to fill SPROM for given bustype.\n");
+		return -EINVAL;
+	}
+}
+#endif
+
+#if IS_BUILTIN(CONFIG_BCMA)
+/*
+ * Having many NVRAM entries for PCI devices led to repeating prefixes like
+ * pci/1/1/ all the time and wasting flash space. So at some point Broadcom
+ * decided to introduce prefixes like 0: 1: 2: etc.
+ * If we find e.g. devpath0=pci/2/1 or devpath0=pci/2/1/ we should use 0:
+ * instead of pci/2/1/.
+ */
+static void bcm47xx_sprom_apply_prefix_alias(char *prefix, size_t prefix_size)
+{
+	size_t prefix_len = strlen(prefix);
+	size_t short_len = prefix_len - 1;
+	char nvram_var[10];
+	char buf[20];
+	int i;
+
+	/* Passed prefix has to end with a slash */
+	if (prefix_len <= 0 || prefix[prefix_len - 1] != '/')
+		return;
+
+	for (i = 0; i < 3; i++) {
+		if (snprintf(nvram_var, sizeof(nvram_var), "devpath%d", i) <= 0)
+			continue;
+		if (bcm47xx_nvram_getenv(nvram_var, buf, sizeof(buf)) < 0)
+			continue;
+		if (!strcmp(buf, prefix) ||
+		    (short_len && strlen(buf) == short_len && !strncmp(buf, prefix, short_len))) {
+			snprintf(prefix, prefix_size, "%d:", i);
+			return;
+		}
+	}
+}
+
+static int bcm47xx_get_sprom_bcma(struct bcma_bus *bus, struct ssb_sprom *out)
+{
+	struct bcma_boardinfo *binfo = &bus->boardinfo;
+	struct bcma_device *core;
+	char buf[10];
+	char *prefix;
+	bool fallback = false;
+
+	switch (bus->hosttype) {
+	case BCMA_HOSTTYPE_PCI:
+		memset(out, 0, sizeof(struct ssb_sprom));
+		/* On BCM47XX all PCI buses share the same domain */
+		if (config_enabled(CONFIG_BCM47XX))
+			snprintf(buf, sizeof(buf), "pci/%u/%u/",
+				 bus->host_pci->bus->number + 1,
+				 PCI_SLOT(bus->host_pci->devfn));
+		else
+			snprintf(buf, sizeof(buf), "pci/%u/%u/",
+				 pci_domain_nr(bus->host_pci->bus) + 1,
+				 bus->host_pci->bus->number);
+		bcm47xx_sprom_apply_prefix_alias(buf, sizeof(buf));
+		prefix = buf;
+		break;
+	case BCMA_HOSTTYPE_SOC:
+		memset(out, 0, sizeof(struct ssb_sprom));
+		core = bcma_find_core(bus, BCMA_CORE_80211);
+		if (core) {
+			snprintf(buf, sizeof(buf), "sb/%u/",
+				 core->core_index);
+			prefix = buf;
+			fallback = true;
+		} else {
+			prefix = NULL;
+		}
+		break;
+	default:
+		pr_warn("Unable to fill SPROM for given bustype.\n");
+		return -EINVAL;
+	}
+
+	nvram_read_u16(prefix, NULL, "boardvendor", &binfo->vendor, 0, true);
+	if (!binfo->vendor)
+		binfo->vendor = SSB_BOARDVENDOR_BCM;
+	nvram_read_u16(prefix, NULL, "boardtype", &binfo->type, 0, true);
+
+	bcm47xx_fill_sprom(out, prefix, fallback);
+
+	return 0;
+}
+#endif
+
+static unsigned int bcm47xx_sprom_registered;
+
+/*
+ * On bcm47xx we need to register SPROM fallback handler very early, so we can't
+ * use anything like platform device / driver for this.
+ */
+int bcm47xx_sprom_register_fallbacks(void)
+{
+	if (bcm47xx_sprom_registered)
+		return 0;
+
+#if IS_BUILTIN(CONFIG_SSB) && IS_ENABLED(CONFIG_SSB_SPROM)
+	if (ssb_arch_register_fallback_sprom(&bcm47xx_get_sprom_ssb))
+		pr_warn("Failed to register ssb SPROM handler\n");
+#endif
+
+#if IS_BUILTIN(CONFIG_BCMA)
+	if (bcma_arch_register_fallback_sprom(&bcm47xx_get_sprom_bcma))
+		pr_warn("Failed to register bcma SPROM handler\n");
+#endif
+
+	bcm47xx_sprom_registered = 1;
+
+	return 0;
+}
+
+fs_initcall(bcm47xx_sprom_register_fallbacks);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/firmware/broadcom/Kconfig linux-libre-4.7-gnu/drivers/firmware/broadcom/Kconfig
--- linux-libre-4.6-gnu/drivers/firmware/broadcom/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/firmware/broadcom/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -9,3 +9,14 @@ config BCM47XX_NVRAM
 	  This driver provides an easy way to get value of requested parameter.
 	  It simply reads content of NVRAM and parses it. It doesn't control any
 	  hardware part itself.
+
+config BCM47XX_SPROM
+	bool "Broadcom SPROM driver"
+	depends on BCM47XX_NVRAM
+	help
+	  Broadcom devices store configuration data in SPROM. Accessing it is
+	  specific to the bus host type, e.g. PCI(e) devices have it mapped in
+	  a PCI BAR.
+	  In case of SoC devices SPROM content is stored on a flash used by
+	  bootloader firmware CFE. This driver provides method to ssb and bcma
+	  drivers to read SPROM on SoC.
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/firmware/broadcom/Makefile linux-libre-4.7-gnu/drivers/firmware/broadcom/Makefile
--- linux-libre-4.6-gnu/drivers/firmware/broadcom/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/firmware/broadcom/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -1 +1,2 @@
 obj-$(CONFIG_BCM47XX_NVRAM)		+= bcm47xx_nvram.o
+obj-$(CONFIG_BCM47XX_SPROM)		+= bcm47xx_sprom.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/firmware/efi/arm-init.c linux-libre-4.7-gnu/drivers/firmware/efi/arm-init.c
--- linux-libre-4.6-gnu/drivers/firmware/efi/arm-init.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/firmware/efi/arm-init.c	2016-07-24 15:23:50.000000000 -0400
@@ -11,17 +11,19 @@
  *
  */
 
+#define pr_fmt(fmt)	"efi: " fmt
+
 #include <linux/efi.h>
 #include <linux/init.h>
 #include <linux/memblock.h>
 #include <linux/mm_types.h>
 #include <linux/of.h>
 #include <linux/of_fdt.h>
+#include <linux/platform_device.h>
+#include <linux/screen_info.h>
 
 #include <asm/efi.h>
 
-struct efi_memory_map memmap;
-
 u64 efi_system_table;
 
 static int __init is_normal_ram(efi_memory_desc_t *md)
@@ -40,7 +42,7 @@ static phys_addr_t efi_to_phys(unsigned
 {
 	efi_memory_desc_t *md;
 
-	for_each_efi_memory_desc(&memmap, md) {
+	for_each_efi_memory_desc(md) {
 		if (!(md->attribute & EFI_MEMORY_RUNTIME))
 			continue;
 		if (md->virt_addr == 0)
@@ -53,6 +55,36 @@ static phys_addr_t efi_to_phys(unsigned
 	return addr;
 }
 
+static __initdata unsigned long screen_info_table = EFI_INVALID_TABLE_ADDR;
+
+static __initdata efi_config_table_type_t arch_tables[] = {
+	{LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID, NULL, &screen_info_table},
+	{NULL_GUID, NULL, NULL}
+};
+
+static void __init init_screen_info(void)
+{
+	struct screen_info *si;
+
+	if (screen_info_table != EFI_INVALID_TABLE_ADDR) {
+		si = early_memremap_ro(screen_info_table, sizeof(*si));
+		if (!si) {
+			pr_err("Could not map screen_info config table\n");
+			return;
+		}
+		screen_info = *si;
+		early_memunmap(si, sizeof(*si));
+
+		/* dummycon on ARM needs non-zero values for columns/lines */
+		screen_info.orig_video_cols = 80;
+		screen_info.orig_video_lines = 25;
+	}
+
+	if (screen_info.orig_video_isVGA == VIDEO_TYPE_EFI &&
+	    memblock_is_map_memory(screen_info.lfb_base))
+		memblock_mark_nomap(screen_info.lfb_base, screen_info.lfb_size);
+}
+
 static int __init uefi_init(void)
 {
 	efi_char16_t *c16;
@@ -85,6 +117,8 @@ static int __init uefi_init(void)
 			efi.systab->hdr.revision >> 16,
 			efi.systab->hdr.revision & 0xffff);
 
+	efi.runtime_version = efi.systab->hdr.revision;
+
 	/* Show what we know for posterity */
 	c16 = early_memremap_ro(efi_to_phys(efi.systab->fw_vendor),
 				sizeof(vendor) * sizeof(efi_char16_t));
@@ -108,7 +142,8 @@ static int __init uefi_init(void)
 		goto out;
 	}
 	retval = efi_config_parse_tables(config_tables, efi.systab->nr_tables,
-					 sizeof(efi_config_table_t), NULL);
+					 sizeof(efi_config_table_t),
+					 arch_tables);
 
 	early_memunmap(config_tables, table_size);
 out:
@@ -139,20 +174,31 @@ static __init void reserve_regions(void)
 {
 	efi_memory_desc_t *md;
 	u64 paddr, npages, size;
+	int resv;
 
 	if (efi_enabled(EFI_DBG))
 		pr_info("Processing EFI memory map:\n");
 
-	for_each_efi_memory_desc(&memmap, md) {
+	/*
+	 * Discard memblocks discovered so far: if there are any at this
+	 * point, they originate from memory nodes in the DT, and UEFI
+	 * uses its own memory map instead.
+	 */
+	memblock_dump_all();
+	memblock_remove(0, (phys_addr_t)ULLONG_MAX);
+
+	for_each_efi_memory_desc(md) {
 		paddr = md->phys_addr;
 		npages = md->num_pages;
 
+		resv = is_reserve_region(md);
 		if (efi_enabled(EFI_DBG)) {
 			char buf[64];
 
-			pr_info("  0x%012llx-0x%012llx %s",
+			pr_info("  0x%012llx-0x%012llx %s%s\n",
 				paddr, paddr + (npages << EFI_PAGE_SHIFT) - 1,
-				efi_md_typeattr_format(buf, sizeof(buf), md));
+				efi_md_typeattr_format(buf, sizeof(buf), md),
+				resv ? "*" : "");
 		}
 
 		memrange_efi_to_native(&paddr, &npages);
@@ -161,14 +207,9 @@ static __init void reserve_regions(void)
 		if (is_normal_ram(md))
 			early_init_dt_add_memory_arch(paddr, size);
 
-		if (is_reserve_region(md)) {
+		if (resv)
 			memblock_mark_nomap(paddr, size);
-			if (efi_enabled(EFI_DBG))
-				pr_cont("*");
-		}
 
-		if (efi_enabled(EFI_DBG))
-			pr_cont("\n");
 	}
 
 	set_bit(EFI_MEMMAP, &efi.flags);
@@ -184,9 +225,9 @@ void __init efi_init(void)
 
 	efi_system_table = params.system_table;
 
-	memmap.phys_map = params.mmap;
-	memmap.map = early_memremap_ro(params.mmap, params.mmap_size);
-	if (memmap.map == NULL) {
+	efi.memmap.phys_map = params.mmap;
+	efi.memmap.map = early_memremap_ro(params.mmap, params.mmap_size);
+	if (efi.memmap.map == NULL) {
 		/*
 		* If we are booting via UEFI, the UEFI memory map is the only
 		* description of memory we have, so there is little point in
@@ -194,28 +235,37 @@ void __init efi_init(void)
 		*/
 		panic("Unable to map EFI memory map.\n");
 	}
-	memmap.map_end = memmap.map + params.mmap_size;
-	memmap.desc_size = params.desc_size;
-	memmap.desc_version = params.desc_ver;
+	efi.memmap.map_end = efi.memmap.map + params.mmap_size;
+	efi.memmap.desc_size = params.desc_size;
+	efi.memmap.desc_version = params.desc_ver;
+
+	WARN(efi.memmap.desc_version != 1,
+	     "Unexpected EFI_MEMORY_DESCRIPTOR version %ld",
+	      efi.memmap.desc_version);
 
 	if (uefi_init() < 0)
 		return;
 
 	reserve_regions();
-	early_memunmap(memmap.map, params.mmap_size);
+	efi_memattr_init();
+	early_memunmap(efi.memmap.map, params.mmap_size);
 
-	if (IS_ENABLED(CONFIG_ARM)) {
-		/*
-		 * ARM currently does not allow ioremap_cache() to be called on
-		 * memory regions that are covered by struct page. So remove the
-		 * UEFI memory map from the linear mapping.
-		 */
-		memblock_mark_nomap(params.mmap & PAGE_MASK,
-				    PAGE_ALIGN(params.mmap_size +
-					       (params.mmap & ~PAGE_MASK)));
-	} else {
-		memblock_reserve(params.mmap & PAGE_MASK,
-				 PAGE_ALIGN(params.mmap_size +
-					    (params.mmap & ~PAGE_MASK)));
-	}
+	memblock_reserve(params.mmap & PAGE_MASK,
+			 PAGE_ALIGN(params.mmap_size +
+				    (params.mmap & ~PAGE_MASK)));
+
+	init_screen_info();
+}
+
+static int __init register_gop_device(void)
+{
+	void *pd;
+
+	if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
+		return 0;
+
+	pd = platform_device_register_data(NULL, "efi-framebuffer", 0,
+					   &screen_info, sizeof(screen_info));
+	return PTR_ERR_OR_ZERO(pd);
 }
+subsys_initcall(register_gop_device);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/firmware/efi/arm-runtime.c linux-libre-4.7-gnu/drivers/firmware/efi/arm-runtime.c
--- linux-libre-4.6-gnu/drivers/firmware/efi/arm-runtime.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/firmware/efi/arm-runtime.c	2016-07-24 15:23:50.000000000 -0400
@@ -42,11 +42,13 @@ static struct mm_struct efi_mm = {
 static bool __init efi_virtmap_init(void)
 {
 	efi_memory_desc_t *md;
+	bool systab_found;
 
 	efi_mm.pgd = pgd_alloc(&efi_mm);
 	init_new_context(NULL, &efi_mm);
 
-	for_each_efi_memory_desc(&memmap, md) {
+	systab_found = false;
+	for_each_efi_memory_desc(md) {
 		phys_addr_t phys = md->phys_addr;
 		int ret;
 
@@ -64,7 +66,25 @@ static bool __init efi_virtmap_init(void
 				&phys, ret);
 			return false;
 		}
+		/*
+		 * If this entry covers the address of the UEFI system table,
+		 * calculate and record its virtual address.
+		 */
+		if (efi_system_table >= phys &&
+		    efi_system_table < phys + (md->num_pages * EFI_PAGE_SIZE)) {
+			efi.systab = (void *)(unsigned long)(efi_system_table -
+							     phys + md->virt_addr);
+			systab_found = true;
+		}
+	}
+	if (!systab_found) {
+		pr_err("No virtual mapping found for the UEFI System Table\n");
+		return false;
 	}
+
+	if (efi_memattr_apply_permissions(&efi_mm, efi_set_mapping_permissions))
+		return false;
+
 	return true;
 }
 
@@ -89,26 +109,17 @@ static int __init arm_enable_runtime_ser
 
 	pr_info("Remapping and enabling EFI services.\n");
 
-	mapsize = memmap.map_end - memmap.map;
-	memmap.map = (__force void *)ioremap_cache(memmap.phys_map,
-						   mapsize);
-	if (!memmap.map) {
-		pr_err("Failed to remap EFI memory map\n");
-		return -ENOMEM;
-	}
-	memmap.map_end = memmap.map + mapsize;
-	efi.memmap = &memmap;
+	mapsize = efi.memmap.map_end - efi.memmap.map;
 
-	efi.systab = (__force void *)ioremap_cache(efi_system_table,
-						   sizeof(efi_system_table_t));
-	if (!efi.systab) {
-		pr_err("Failed to remap EFI System Table\n");
+	efi.memmap.map = memremap(efi.memmap.phys_map, mapsize, MEMREMAP_WB);
+	if (!efi.memmap.map) {
+		pr_err("Failed to remap EFI memory map\n");
 		return -ENOMEM;
 	}
-	set_bit(EFI_SYSTEM_TABLES, &efi.flags);
+	efi.memmap.map_end = efi.memmap.map + mapsize;
 
 	if (!efi_virtmap_init()) {
-		pr_err("No UEFI virtual mapping was installed -- runtime services will not be available\n");
+		pr_err("UEFI virtual mapping missing or invalid -- runtime services will not be available\n");
 		return -ENOMEM;
 	}
 
@@ -116,8 +127,6 @@ static int __init arm_enable_runtime_ser
 	efi_native_runtime_setup();
 	set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
 
-	efi.runtime_version = efi.systab->hdr.revision;
-
 	return 0;
 }
 early_initcall(arm_enable_runtime_services);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/firmware/efi/capsule.c linux-libre-4.7-gnu/drivers/firmware/efi/capsule.c
--- linux-libre-4.6-gnu/drivers/firmware/efi/capsule.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/firmware/efi/capsule.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,308 @@
+/*
+ * EFI capsule support.
+ *
+ * Copyright 2013 Intel Corporation; author Matt Fleming
+ *
+ * This file is part of the Linux kernel, and is made available under
+ * the terms of the GNU General Public License version 2.
+ */
+
+#define pr_fmt(fmt) "efi: " fmt
+
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/highmem.h>
+#include <linux/efi.h>
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+
+typedef struct {
+	u64 length;
+	u64 data;
+} efi_capsule_block_desc_t;
+
+static bool capsule_pending;
+static bool stop_capsules;
+static int efi_reset_type = -1;
+
+/*
+ * capsule_mutex serialises access to both capsule_pending and
+ * efi_reset_type and stop_capsules.
+ */
+static DEFINE_MUTEX(capsule_mutex);
+
+/**
+ * efi_capsule_pending - has a capsule been passed to the firmware?
+ * @reset_type: store the type of EFI reset if capsule is pending
+ *
+ * To ensure that the registered capsule is processed correctly by the
+ * firmware we need to perform a specific type of reset. If a capsule is
+ * pending return the reset type in @reset_type.
+ *
+ * This function will race with callers of efi_capsule_update(), for
+ * example, calling this function while somebody else is in
+ * efi_capsule_update() but hasn't reached efi_capsue_update_locked()
+ * will miss the updates to capsule_pending and efi_reset_type after
+ * efi_capsule_update_locked() completes.
+ *
+ * A non-racy use is from platform reboot code because we use
+ * system_state to ensure no capsules can be sent to the firmware once
+ * we're at SYSTEM_RESTART. See efi_capsule_update_locked().
+ */
+bool efi_capsule_pending(int *reset_type)
+{
+	if (!capsule_pending)
+		return false;
+
+	if (reset_type)
+		*reset_type = efi_reset_type;
+
+	return true;
+}
+
+/*
+ * Whitelist of EFI capsule flags that we support.
+ *
+ * We do not handle EFI_CAPSULE_INITIATE_RESET because that would
+ * require us to prepare the kernel for reboot. Refuse to load any
+ * capsules with that flag and any other flags that we do not know how
+ * to handle.
+ */
+#define EFI_CAPSULE_SUPPORTED_FLAG_MASK			\
+	(EFI_CAPSULE_PERSIST_ACROSS_RESET | EFI_CAPSULE_POPULATE_SYSTEM_TABLE)
+
+/**
+ * efi_capsule_supported - does the firmware support the capsule?
+ * @guid: vendor guid of capsule
+ * @flags: capsule flags
+ * @size: size of capsule data
+ * @reset: the reset type required for this capsule
+ *
+ * Check whether a capsule with @flags is supported by the firmware
+ * and that @size doesn't exceed the maximum size for a capsule.
+ *
+ * No attempt is made to check @reset against the reset type required
+ * by any pending capsules because of the races involved.
+ */
+int efi_capsule_supported(efi_guid_t guid, u32 flags, size_t size, int *reset)
+{
+	efi_capsule_header_t capsule;
+	efi_capsule_header_t *cap_list[] = { &capsule };
+	efi_status_t status;
+	u64 max_size;
+
+	if (flags & ~EFI_CAPSULE_SUPPORTED_FLAG_MASK)
+		return -EINVAL;
+
+	capsule.headersize = capsule.imagesize = sizeof(capsule);
+	memcpy(&capsule.guid, &guid, sizeof(efi_guid_t));
+	capsule.flags = flags;
+
+	status = efi.query_capsule_caps(cap_list, 1, &max_size, reset);
+	if (status != EFI_SUCCESS)
+		return efi_status_to_err(status);
+
+	if (size > max_size)
+		return -ENOSPC;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(efi_capsule_supported);
+
+/*
+ * Every scatter gather list (block descriptor) page must end with a
+ * continuation pointer. The last continuation pointer of the last
+ * page must be zero to mark the end of the chain.
+ */
+#define SGLIST_PER_PAGE	((PAGE_SIZE / sizeof(efi_capsule_block_desc_t)) - 1)
+
+/*
+ * How many scatter gather list (block descriptor) pages do we need
+ * to map @count pages?
+ */
+static inline unsigned int sg_pages_num(unsigned int count)
+{
+	return DIV_ROUND_UP(count, SGLIST_PER_PAGE);
+}
+
+/**
+ * efi_capsule_update_locked - pass a single capsule to the firmware
+ * @capsule: capsule to send to the firmware
+ * @sg_pages: array of scatter gather (block descriptor) pages
+ * @reset: the reset type required for @capsule
+ *
+ * Since this function must be called under capsule_mutex check
+ * whether efi_reset_type will conflict with @reset, and atomically
+ * set it and capsule_pending if a capsule was successfully sent to
+ * the firmware.
+ *
+ * We also check to see if the system is about to restart, and if so,
+ * abort. This avoids races between efi_capsule_update() and
+ * efi_capsule_pending().
+ */
+static int
+efi_capsule_update_locked(efi_capsule_header_t *capsule,
+			  struct page **sg_pages, int reset)
+{
+	efi_physical_addr_t sglist_phys;
+	efi_status_t status;
+
+	lockdep_assert_held(&capsule_mutex);
+
+	/*
+	 * If someone has already registered a capsule that requires a
+	 * different reset type, we're out of luck and must abort.
+	 */
+	if (efi_reset_type >= 0 && efi_reset_type != reset) {
+		pr_err("Conflicting capsule reset type %d (%d).\n",
+		       reset, efi_reset_type);
+		return -EINVAL;
+	}
+
+	/*
+	 * If the system is getting ready to restart it may have
+	 * called efi_capsule_pending() to make decisions (such as
+	 * whether to force an EFI reboot), and we're racing against
+	 * that call. Abort in that case.
+	 */
+	if (unlikely(stop_capsules)) {
+		pr_warn("Capsule update raced with reboot, aborting.\n");
+		return -EINVAL;
+	}
+
+	sglist_phys = page_to_phys(sg_pages[0]);
+
+	status = efi.update_capsule(&capsule, 1, sglist_phys);
+	if (status == EFI_SUCCESS) {
+		capsule_pending = true;
+		efi_reset_type = reset;
+	}
+
+	return efi_status_to_err(status);
+}
+
+/**
+ * efi_capsule_update - send a capsule to the firmware
+ * @capsule: capsule to send to firmware
+ * @pages: an array of capsule data pages
+ *
+ * Build a scatter gather list with EFI capsule block descriptors to
+ * map the capsule described by @capsule with its data in @pages and
+ * send it to the firmware via the UpdateCapsule() runtime service.
+ *
+ * @capsule must be a virtual mapping of the first page in @pages
+ * (@pages[0]) in the kernel address space. That is, a
+ * capsule_header_t that describes the entire contents of the capsule
+ * must be at the start of the first data page.
+ *
+ * Even though this function will validate that the firmware supports
+ * the capsule guid, users will likely want to check that
+ * efi_capsule_supported() returns true before calling this function
+ * because it makes it easier to print helpful error messages.
+ *
+ * If the capsule is successfully submitted to the firmware, any
+ * subsequent calls to efi_capsule_pending() will return true. @pages
+ * must not be released or modified if this function returns
+ * successfully.
+ *
+ * Callers must be prepared for this function to fail, which can
+ * happen if we raced with system reboot or if there is already a
+ * pending capsule that has a reset type that conflicts with the one
+ * required by @capsule. Do NOT use efi_capsule_pending() to detect
+ * this conflict since that would be racy. Instead, submit the capsule
+ * to efi_capsule_update() and check the return value.
+ *
+ * Return 0 on success, a converted EFI status code on failure.
+ */
+int efi_capsule_update(efi_capsule_header_t *capsule, struct page **pages)
+{
+	u32 imagesize = capsule->imagesize;
+	efi_guid_t guid = capsule->guid;
+	unsigned int count, sg_count;
+	u32 flags = capsule->flags;
+	struct page **sg_pages;
+	int rv, reset_type;
+	int i, j;
+
+	rv = efi_capsule_supported(guid, flags, imagesize, &reset_type);
+	if (rv)
+		return rv;
+
+	count = DIV_ROUND_UP(imagesize, PAGE_SIZE);
+	sg_count = sg_pages_num(count);
+
+	sg_pages = kzalloc(sg_count * sizeof(*sg_pages), GFP_KERNEL);
+	if (!sg_pages)
+		return -ENOMEM;
+
+	for (i = 0; i < sg_count; i++) {
+		sg_pages[i] = alloc_page(GFP_KERNEL);
+		if (!sg_pages[i]) {
+			rv = -ENOMEM;
+			goto out;
+		}
+	}
+
+	for (i = 0; i < sg_count; i++) {
+		efi_capsule_block_desc_t *sglist;
+
+		sglist = kmap(sg_pages[i]);
+		if (!sglist) {
+			rv = -ENOMEM;
+			goto out;
+		}
+
+		for (j = 0; j < SGLIST_PER_PAGE && count > 0; j++) {
+			u64 sz = min_t(u64, imagesize, PAGE_SIZE);
+
+			sglist[j].length = sz;
+			sglist[j].data = page_to_phys(*pages++);
+
+			imagesize -= sz;
+			count--;
+		}
+
+		/* Continuation pointer */
+		sglist[j].length = 0;
+
+		if (i + 1 == sg_count)
+			sglist[j].data = 0;
+		else
+			sglist[j].data = page_to_phys(sg_pages[i + 1]);
+
+		kunmap(sg_pages[i]);
+	}
+
+	mutex_lock(&capsule_mutex);
+	rv = efi_capsule_update_locked(capsule, sg_pages, reset_type);
+	mutex_unlock(&capsule_mutex);
+
+out:
+	for (i = 0; rv && i < sg_count; i++) {
+		if (sg_pages[i])
+			__free_page(sg_pages[i]);
+	}
+
+	kfree(sg_pages);
+	return rv;
+}
+EXPORT_SYMBOL_GPL(efi_capsule_update);
+
+static int capsule_reboot_notify(struct notifier_block *nb, unsigned long event, void *cmd)
+{
+	mutex_lock(&capsule_mutex);
+	stop_capsules = true;
+	mutex_unlock(&capsule_mutex);
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block capsule_reboot_nb = {
+	.notifier_call = capsule_reboot_notify,
+};
+
+static int __init capsule_reboot_register(void)
+{
+	return register_reboot_notifier(&capsule_reboot_nb);
+}
+core_initcall(capsule_reboot_register);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/firmware/efi/capsule-loader.c linux-libre-4.7-gnu/drivers/firmware/efi/capsule-loader.c
--- linux-libre-4.6-gnu/drivers/firmware/efi/capsule-loader.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/firmware/efi/capsule-loader.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,343 @@
+/*
+ * EFI capsule loader driver.
+ *
+ * Copyright 2015 Intel Corporation
+ *
+ * This file is part of the Linux kernel, and is made available under
+ * the terms of the GNU General Public License version 2.
+ */
+
+#define pr_fmt(fmt) "efi: " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/miscdevice.h>
+#include <linux/highmem.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/efi.h>
+
+#define NO_FURTHER_WRITE_ACTION -1
+
+struct capsule_info {
+	bool		header_obtained;
+	int		reset_type;
+	long		index;
+	size_t		count;
+	size_t		total_size;
+	struct page	**pages;
+	size_t		page_bytes_remain;
+};
+
+/**
+ * efi_free_all_buff_pages - free all previous allocated buffer pages
+ * @cap_info: pointer to current instance of capsule_info structure
+ *
+ *	In addition to freeing buffer pages, it flags NO_FURTHER_WRITE_ACTION
+ *	to cease processing data in subsequent write(2) calls until close(2)
+ *	is called.
+ **/
+static void efi_free_all_buff_pages(struct capsule_info *cap_info)
+{
+	while (cap_info->index > 0)
+		__free_page(cap_info->pages[--cap_info->index]);
+
+	cap_info->index = NO_FURTHER_WRITE_ACTION;
+}
+
+/**
+ * efi_capsule_setup_info - obtain the efi capsule header in the binary and
+ *			    setup capsule_info structure
+ * @cap_info: pointer to current instance of capsule_info structure
+ * @kbuff: a mapped first page buffer pointer
+ * @hdr_bytes: the total received number of bytes for efi header
+ **/
+static ssize_t efi_capsule_setup_info(struct capsule_info *cap_info,
+				      void *kbuff, size_t hdr_bytes)
+{
+	efi_capsule_header_t *cap_hdr;
+	size_t pages_needed;
+	int ret;
+	void *temp_page;
+
+	/* Only process data block that is larger than efi header size */
+	if (hdr_bytes < sizeof(efi_capsule_header_t))
+		return 0;
+
+	/* Reset back to the correct offset of header */
+	cap_hdr = kbuff - cap_info->count;
+	pages_needed = ALIGN(cap_hdr->imagesize, PAGE_SIZE) >> PAGE_SHIFT;
+
+	if (pages_needed == 0) {
+		pr_err("%s: pages count invalid\n", __func__);
+		return -EINVAL;
+	}
+
+	/* Check if the capsule binary supported */
+	ret = efi_capsule_supported(cap_hdr->guid, cap_hdr->flags,
+				    cap_hdr->imagesize,
+				    &cap_info->reset_type);
+	if (ret) {
+		pr_err("%s: efi_capsule_supported() failed\n",
+		       __func__);
+		return ret;
+	}
+
+	cap_info->total_size = cap_hdr->imagesize;
+	temp_page = krealloc(cap_info->pages,
+			     pages_needed * sizeof(void *),
+			     GFP_KERNEL | __GFP_ZERO);
+	if (!temp_page) {
+		pr_debug("%s: krealloc() failed\n", __func__);
+		return -ENOMEM;
+	}
+
+	cap_info->pages = temp_page;
+	cap_info->header_obtained = true;
+
+	return 0;
+}
+
+/**
+ * efi_capsule_submit_update - invoke the efi_capsule_update API once binary
+ *			       upload done
+ * @cap_info: pointer to current instance of capsule_info structure
+ **/
+static ssize_t efi_capsule_submit_update(struct capsule_info *cap_info)
+{
+	int ret;
+	void *cap_hdr_temp;
+
+	cap_hdr_temp = kmap(cap_info->pages[0]);
+	if (!cap_hdr_temp) {
+		pr_debug("%s: kmap() failed\n", __func__);
+		return -EFAULT;
+	}
+
+	ret = efi_capsule_update(cap_hdr_temp, cap_info->pages);
+	kunmap(cap_info->pages[0]);
+	if (ret) {
+		pr_err("%s: efi_capsule_update() failed\n", __func__);
+		return ret;
+	}
+
+	/* Indicate capsule binary uploading is done */
+	cap_info->index = NO_FURTHER_WRITE_ACTION;
+	pr_info("%s: Successfully upload capsule file with reboot type '%s'\n",
+		__func__, !cap_info->reset_type ? "RESET_COLD" :
+		cap_info->reset_type == 1 ? "RESET_WARM" :
+		"RESET_SHUTDOWN");
+	return 0;
+}
+
+/**
+ * efi_capsule_write - store the capsule binary and pass it to
+ *		       efi_capsule_update() API
+ * @file: file pointer
+ * @buff: buffer pointer
+ * @count: number of bytes in @buff
+ * @offp: not used
+ *
+ *	Expectation:
+ *	- A user space tool should start at the beginning of capsule binary and
+ *	  pass data in sequentially.
+ *	- Users should close and re-open this file note in order to upload more
+ *	  capsules.
+ *	- After an error returned, user should close the file and restart the
+ *	  operation for the next try otherwise -EIO will be returned until the
+ *	  file is closed.
+ *	- An EFI capsule header must be located at the beginning of capsule
+ *	  binary file and passed in as first block data of write operation.
+ **/
+static ssize_t efi_capsule_write(struct file *file, const char __user *buff,
+				 size_t count, loff_t *offp)
+{
+	int ret = 0;
+	struct capsule_info *cap_info = file->private_data;
+	struct page *page;
+	void *kbuff = NULL;
+	size_t write_byte;
+
+	if (count == 0)
+		return 0;
+
+	/* Return error while NO_FURTHER_WRITE_ACTION is flagged */
+	if (cap_info->index < 0)
+		return -EIO;
+
+	/* Only alloc a new page when previous page is full */
+	if (!cap_info->page_bytes_remain) {
+		page = alloc_page(GFP_KERNEL);
+		if (!page) {
+			pr_debug("%s: alloc_page() failed\n", __func__);
+			ret = -ENOMEM;
+			goto failed;
+		}
+
+		cap_info->pages[cap_info->index++] = page;
+		cap_info->page_bytes_remain = PAGE_SIZE;
+	}
+
+	page = cap_info->pages[cap_info->index - 1];
+
+	kbuff = kmap(page);
+	if (!kbuff) {
+		pr_debug("%s: kmap() failed\n", __func__);
+		ret = -EFAULT;
+		goto failed;
+	}
+	kbuff += PAGE_SIZE - cap_info->page_bytes_remain;
+
+	/* Copy capsule binary data from user space to kernel space buffer */
+	write_byte = min_t(size_t, count, cap_info->page_bytes_remain);
+	if (copy_from_user(kbuff, buff, write_byte)) {
+		pr_debug("%s: copy_from_user() failed\n", __func__);
+		ret = -EFAULT;
+		goto fail_unmap;
+	}
+	cap_info->page_bytes_remain -= write_byte;
+
+	/* Setup capsule binary info structure */
+	if (!cap_info->header_obtained) {
+		ret = efi_capsule_setup_info(cap_info, kbuff,
+					     cap_info->count + write_byte);
+		if (ret)
+			goto fail_unmap;
+	}
+
+	cap_info->count += write_byte;
+	kunmap(page);
+
+	/* Submit the full binary to efi_capsule_update() API */
+	if (cap_info->header_obtained &&
+	    cap_info->count >= cap_info->total_size) {
+		if (cap_info->count > cap_info->total_size) {
+			pr_err("%s: upload size exceeded header defined size\n",
+			       __func__);
+			ret = -EINVAL;
+			goto failed;
+		}
+
+		ret = efi_capsule_submit_update(cap_info);
+		if (ret)
+			goto failed;
+	}
+
+	return write_byte;
+
+fail_unmap:
+	kunmap(page);
+failed:
+	efi_free_all_buff_pages(cap_info);
+	return ret;
+}
+
+/**
+ * efi_capsule_flush - called by file close or file flush
+ * @file: file pointer
+ * @id: not used
+ *
+ *	If a capsule is being partially uploaded then calling this function
+ *	will be treated as upload termination and will free those completed
+ *	buffer pages and -ECANCELED will be returned.
+ **/
+static int efi_capsule_flush(struct file *file, fl_owner_t id)
+{
+	int ret = 0;
+	struct capsule_info *cap_info = file->private_data;
+
+	if (cap_info->index > 0) {
+		pr_err("%s: capsule upload not complete\n", __func__);
+		efi_free_all_buff_pages(cap_info);
+		ret = -ECANCELED;
+	}
+
+	return ret;
+}
+
+/**
+ * efi_capsule_release - called by file close
+ * @inode: not used
+ * @file: file pointer
+ *
+ *	We will not free successfully submitted pages since efi update
+ *	requires data to be maintained across system reboot.
+ **/
+static int efi_capsule_release(struct inode *inode, struct file *file)
+{
+	struct capsule_info *cap_info = file->private_data;
+
+	kfree(cap_info->pages);
+	kfree(file->private_data);
+	file->private_data = NULL;
+	return 0;
+}
+
+/**
+ * efi_capsule_open - called by file open
+ * @inode: not used
+ * @file: file pointer
+ *
+ *	Will allocate each capsule_info memory for each file open call.
+ *	This provided the capability to support multiple file open feature
+ *	where user is not needed to wait for others to finish in order to
+ *	upload their capsule binary.
+ **/
+static int efi_capsule_open(struct inode *inode, struct file *file)
+{
+	struct capsule_info *cap_info;
+
+	cap_info = kzalloc(sizeof(*cap_info), GFP_KERNEL);
+	if (!cap_info)
+		return -ENOMEM;
+
+	cap_info->pages = kzalloc(sizeof(void *), GFP_KERNEL);
+	if (!cap_info->pages) {
+		kfree(cap_info);
+		return -ENOMEM;
+	}
+
+	file->private_data = cap_info;
+
+	return 0;
+}
+
+static const struct file_operations efi_capsule_fops = {
+	.owner = THIS_MODULE,
+	.open = efi_capsule_open,
+	.write = efi_capsule_write,
+	.flush = efi_capsule_flush,
+	.release = efi_capsule_release,
+	.llseek = no_llseek,
+};
+
+static struct miscdevice efi_capsule_misc = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = "efi_capsule_loader",
+	.fops = &efi_capsule_fops,
+};
+
+static int __init efi_capsule_loader_init(void)
+{
+	int ret;
+
+	if (!efi_enabled(EFI_RUNTIME_SERVICES))
+		return -ENODEV;
+
+	ret = misc_register(&efi_capsule_misc);
+	if (ret)
+		pr_err("%s: Failed to register misc char file note\n",
+		       __func__);
+
+	return ret;
+}
+module_init(efi_capsule_loader_init);
+
+static void __exit efi_capsule_loader_exit(void)
+{
+	misc_deregister(&efi_capsule_misc);
+}
+module_exit(efi_capsule_loader_exit);
+
+MODULE_DESCRIPTION("EFI capsule firmware binary loader");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/firmware/efi/efibc.c linux-libre-4.7-gnu/drivers/firmware/efi/efibc.c
--- linux-libre-4.6-gnu/drivers/firmware/efi/efibc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/firmware/efi/efibc.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,113 @@
+/*
+ * efibc: control EFI bootloaders which obey LoaderEntryOneShot var
+ * Copyright (c) 2013-2016, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ */
+
+#define pr_fmt(fmt) "efibc: " fmt
+
+#include <linux/efi.h>
+#include <linux/module.h>
+#include <linux/reboot.h>
+#include <linux/slab.h>
+
+static void efibc_str_to_str16(const char *str, efi_char16_t *str16)
+{
+	size_t i;
+
+	for (i = 0; i < strlen(str); i++)
+		str16[i] = str[i];
+
+	str16[i] = '\0';
+}
+
+static int efibc_set_variable(const char *name, const char *value)
+{
+	int ret;
+	efi_guid_t guid = LINUX_EFI_LOADER_ENTRY_GUID;
+	struct efivar_entry *entry;
+	size_t size = (strlen(value) + 1) * sizeof(efi_char16_t);
+
+	if (size > sizeof(entry->var.Data)) {
+		pr_err("value is too large");
+		return -EINVAL;
+	}
+
+	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+	if (!entry) {
+		pr_err("failed to allocate efivar entry");
+		return -ENOMEM;
+	}
+
+	efibc_str_to_str16(name, entry->var.VariableName);
+	efibc_str_to_str16(value, (efi_char16_t *)entry->var.Data);
+	memcpy(&entry->var.VendorGuid, &guid, sizeof(guid));
+
+	ret = efivar_entry_set(entry,
+			       EFI_VARIABLE_NON_VOLATILE
+			       | EFI_VARIABLE_BOOTSERVICE_ACCESS
+			       | EFI_VARIABLE_RUNTIME_ACCESS,
+			       size, entry->var.Data, NULL);
+	if (ret)
+		pr_err("failed to set %s EFI variable: 0x%x\n",
+		       name, ret);
+
+	kfree(entry);
+	return ret;
+}
+
+static int efibc_reboot_notifier_call(struct notifier_block *notifier,
+				      unsigned long event, void *data)
+{
+	const char *reason = "shutdown";
+	int ret;
+
+	if (event == SYS_RESTART)
+		reason = "reboot";
+
+	ret = efibc_set_variable("LoaderEntryRebootReason", reason);
+	if (ret || !data)
+		return NOTIFY_DONE;
+
+	efibc_set_variable("LoaderEntryOneShot", (char *)data);
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block efibc_reboot_notifier = {
+	.notifier_call = efibc_reboot_notifier_call,
+};
+
+static int __init efibc_init(void)
+{
+	int ret;
+
+	if (!efi_enabled(EFI_RUNTIME_SERVICES))
+		return -ENODEV;
+
+	ret = register_reboot_notifier(&efibc_reboot_notifier);
+	if (ret)
+		pr_err("unable to register reboot notifier\n");
+
+	return ret;
+}
+module_init(efibc_init);
+
+static void __exit efibc_exit(void)
+{
+	unregister_reboot_notifier(&efibc_reboot_notifier);
+}
+module_exit(efibc_exit);
+
+MODULE_AUTHOR("Jeremy Compostella <jeremy.compostella@intel.com>");
+MODULE_AUTHOR("Matt Gumbel <matthew.k.gumbel@intel.com");
+MODULE_DESCRIPTION("EFI Bootloader Control");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/firmware/efi/efi.c linux-libre-4.7-gnu/drivers/firmware/efi/efi.c
--- linux-libre-4.6-gnu/drivers/firmware/efi/efi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/firmware/efi/efi.c	2016-07-24 15:23:50.000000000 -0400
@@ -43,6 +43,7 @@ struct efi __read_mostly efi = {
 	.config_table		= EFI_INVALID_TABLE_ADDR,
 	.esrt			= EFI_INVALID_TABLE_ADDR,
 	.properties_table	= EFI_INVALID_TABLE_ADDR,
+	.mem_attr_table		= EFI_INVALID_TABLE_ADDR,
 };
 EXPORT_SYMBOL(efi);
 
@@ -256,7 +257,7 @@ subsys_initcall(efisubsys_init);
  */
 int __init efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
 {
-	struct efi_memory_map *map = efi.memmap;
+	struct efi_memory_map *map = &efi.memmap;
 	phys_addr_t p, e;
 
 	if (!efi_enabled(EFI_MEMMAP)) {
@@ -338,6 +339,7 @@ static __initdata efi_config_table_type_
 	{UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga},
 	{EFI_SYSTEM_RESOURCE_TABLE_GUID, "ESRT", &efi.esrt},
 	{EFI_PROPERTIES_TABLE_GUID, "PROP", &efi.properties_table},
+	{EFI_MEMORY_ATTRIBUTES_TABLE_GUID, "MEMATTR", &efi.mem_attr_table},
 	{NULL_GUID, NULL, NULL},
 };
 
@@ -351,8 +353,9 @@ static __init int match_config_table(efi
 		for (i = 0; efi_guidcmp(table_types[i].guid, NULL_GUID); i++) {
 			if (!efi_guidcmp(*guid, table_types[i].guid)) {
 				*(table_types[i].ptr) = table;
-				pr_cont(" %s=0x%lx ",
-					table_types[i].name, table);
+				if (table_types[i].name)
+					pr_cont(" %s=0x%lx ",
+						table_types[i].name, table);
 				return 1;
 			}
 		}
@@ -620,16 +623,12 @@ char * __init efi_md_typeattr_format(cha
  */
 u64 __weak efi_mem_attributes(unsigned long phys_addr)
 {
-	struct efi_memory_map *map;
 	efi_memory_desc_t *md;
-	void *p;
 
 	if (!efi_enabled(EFI_MEMMAP))
 		return 0;
 
-	map = efi.memmap;
-	for (p = map->map; p < map->map_end; p += map->desc_size) {
-		md = p;
+	for_each_efi_memory_desc(md) {
 		if ((md->phys_addr <= phys_addr) &&
 		    (phys_addr < (md->phys_addr +
 		    (md->num_pages << EFI_PAGE_SHIFT))))
@@ -637,3 +636,36 @@ u64 __weak efi_mem_attributes(unsigned l
 	}
 	return 0;
 }
+
+int efi_status_to_err(efi_status_t status)
+{
+	int err;
+
+	switch (status) {
+	case EFI_SUCCESS:
+		err = 0;
+		break;
+	case EFI_INVALID_PARAMETER:
+		err = -EINVAL;
+		break;
+	case EFI_OUT_OF_RESOURCES:
+		err = -ENOSPC;
+		break;
+	case EFI_DEVICE_ERROR:
+		err = -EIO;
+		break;
+	case EFI_WRITE_PROTECTED:
+		err = -EROFS;
+		break;
+	case EFI_SECURITY_VIOLATION:
+		err = -EACCES;
+		break;
+	case EFI_NOT_FOUND:
+		err = -ENOENT;
+		break;
+	default:
+		err = -EINVAL;
+	}
+
+	return err;
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/firmware/efi/efivars.c linux-libre-4.7-gnu/drivers/firmware/efi/efivars.c
--- linux-libre-4.6-gnu/drivers/firmware/efi/efivars.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/firmware/efi/efivars.c	2016-07-24 15:23:50.000000000 -0400
@@ -661,7 +661,7 @@ static void efivar_update_sysfs_entries(
 			return;
 
 		err = efivar_init(efivar_update_sysfs_entry, entry,
-				  true, false, &efivar_sysfs_list);
+				  false, &efivar_sysfs_list);
 		if (!err)
 			break;
 
@@ -730,8 +730,7 @@ int efivars_sysfs_init(void)
 		return -ENOMEM;
 	}
 
-	efivar_init(efivars_sysfs_callback, NULL, false,
-		    true, &efivar_sysfs_list);
+	efivar_init(efivars_sysfs_callback, NULL, true, &efivar_sysfs_list);
 
 	error = create_efivars_bin_attributes();
 	if (error) {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/firmware/efi/fake_mem.c linux-libre-4.7-gnu/drivers/firmware/efi/fake_mem.c
--- linux-libre-4.6-gnu/drivers/firmware/efi/fake_mem.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/firmware/efi/fake_mem.c	2016-07-24 15:23:50.000000000 -0400
@@ -57,7 +57,7 @@ static int __init cmp_fake_mem(const voi
 void __init efi_fake_memmap(void)
 {
 	u64 start, end, m_start, m_end, m_attr;
-	int new_nr_map = memmap.nr_map;
+	int new_nr_map = efi.memmap.nr_map;
 	efi_memory_desc_t *md;
 	phys_addr_t new_memmap_phy;
 	void *new_memmap;
@@ -68,8 +68,7 @@ void __init efi_fake_memmap(void)
 		return;
 
 	/* count up the number of EFI memory descriptor */
-	for (old = memmap.map; old < memmap.map_end; old += memmap.desc_size) {
-		md = old;
+	for_each_efi_memory_desc(md) {
 		start = md->phys_addr;
 		end = start + (md->num_pages << EFI_PAGE_SHIFT) - 1;
 
@@ -95,25 +94,25 @@ void __init efi_fake_memmap(void)
 	}
 
 	/* allocate memory for new EFI memmap */
-	new_memmap_phy = memblock_alloc(memmap.desc_size * new_nr_map,
+	new_memmap_phy = memblock_alloc(efi.memmap.desc_size * new_nr_map,
 					PAGE_SIZE);
 	if (!new_memmap_phy)
 		return;
 
 	/* create new EFI memmap */
 	new_memmap = early_memremap(new_memmap_phy,
-				    memmap.desc_size * new_nr_map);
+				    efi.memmap.desc_size * new_nr_map);
 	if (!new_memmap) {
-		memblock_free(new_memmap_phy, memmap.desc_size * new_nr_map);
+		memblock_free(new_memmap_phy, efi.memmap.desc_size * new_nr_map);
 		return;
 	}
 
-	for (old = memmap.map, new = new_memmap;
-	     old < memmap.map_end;
-	     old += memmap.desc_size, new += memmap.desc_size) {
+	for (old = efi.memmap.map, new = new_memmap;
+	     old < efi.memmap.map_end;
+	     old += efi.memmap.desc_size, new += efi.memmap.desc_size) {
 
 		/* copy original EFI memory descriptor */
-		memcpy(new, old, memmap.desc_size);
+		memcpy(new, old, efi.memmap.desc_size);
 		md = new;
 		start = md->phys_addr;
 		end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1;
@@ -134,8 +133,8 @@ void __init efi_fake_memmap(void)
 				md->num_pages = (m_end - md->phys_addr + 1) >>
 					EFI_PAGE_SHIFT;
 				/* latter part */
-				new += memmap.desc_size;
-				memcpy(new, old, memmap.desc_size);
+				new += efi.memmap.desc_size;
+				memcpy(new, old, efi.memmap.desc_size);
 				md = new;
 				md->phys_addr = m_end + 1;
 				md->num_pages = (end - md->phys_addr + 1) >>
@@ -147,16 +146,16 @@ void __init efi_fake_memmap(void)
 				md->num_pages = (m_start - md->phys_addr) >>
 					EFI_PAGE_SHIFT;
 				/* middle part */
-				new += memmap.desc_size;
-				memcpy(new, old, memmap.desc_size);
+				new += efi.memmap.desc_size;
+				memcpy(new, old, efi.memmap.desc_size);
 				md = new;
 				md->attribute |= m_attr;
 				md->phys_addr = m_start;
 				md->num_pages = (m_end - m_start + 1) >>
 					EFI_PAGE_SHIFT;
 				/* last part */
-				new += memmap.desc_size;
-				memcpy(new, old, memmap.desc_size);
+				new += efi.memmap.desc_size;
+				memcpy(new, old, efi.memmap.desc_size);
 				md = new;
 				md->phys_addr = m_end + 1;
 				md->num_pages = (end - m_end) >>
@@ -169,8 +168,8 @@ void __init efi_fake_memmap(void)
 				md->num_pages = (m_start - md->phys_addr) >>
 					EFI_PAGE_SHIFT;
 				/* latter part */
-				new += memmap.desc_size;
-				memcpy(new, old, memmap.desc_size);
+				new += efi.memmap.desc_size;
+				memcpy(new, old, efi.memmap.desc_size);
 				md = new;
 				md->phys_addr = m_start;
 				md->num_pages = (end - md->phys_addr + 1) >>
@@ -182,10 +181,10 @@ void __init efi_fake_memmap(void)
 
 	/* swap into new EFI memmap */
 	efi_unmap_memmap();
-	memmap.map = new_memmap;
-	memmap.phys_map = new_memmap_phy;
-	memmap.nr_map = new_nr_map;
-	memmap.map_end = memmap.map + memmap.nr_map * memmap.desc_size;
+	efi.memmap.map = new_memmap;
+	efi.memmap.phys_map = new_memmap_phy;
+	efi.memmap.nr_map = new_nr_map;
+	efi.memmap.map_end = efi.memmap.map + efi.memmap.nr_map * efi.memmap.desc_size;
 	set_bit(EFI_MEMMAP, &efi.flags);
 
 	/* print new EFI memmap */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/firmware/efi/Kconfig linux-libre-4.7-gnu/drivers/firmware/efi/Kconfig
--- linux-libre-4.6-gnu/drivers/firmware/efi/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/firmware/efi/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -87,6 +87,31 @@ config EFI_RUNTIME_WRAPPERS
 config EFI_ARMSTUB
 	bool
 
+config EFI_BOOTLOADER_CONTROL
+	tristate "EFI Bootloader Control"
+	depends on EFI_VARS
+	default n
+	---help---
+	  This module installs a reboot hook, such that if reboot() is
+	  invoked with a string argument NNN, "NNN" is copied to the
+	  "LoaderEntryOneShot" EFI variable, to be read by the
+	  bootloader. If the string matches one of the boot labels
+	  defined in its configuration, the bootloader will boot once
+	  to that label. The "LoaderEntryRebootReason" EFI variable is
+	  set with the reboot reason: "reboot" or "shutdown". The
+	  bootloader reads this reboot reason and takes particular
+	  action according to its policy.
+
+config EFI_CAPSULE_LOADER
+	tristate "EFI capsule loader"
+	depends on EFI
+	help
+	  This option exposes a loader interface "/dev/efi_capsule_loader" for
+	  users to load EFI capsules. This driver requires working runtime
+	  capsule support in the firmware, which many OEMs do not provide.
+
+	  Most users should say N.
+
 endmenu
 
 config UEFI_CPER
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/firmware/efi/libstub/arm32-stub.c linux-libre-4.7-gnu/drivers/firmware/efi/libstub/arm32-stub.c
--- linux-libre-4.6-gnu/drivers/firmware/efi/libstub/arm32-stub.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/firmware/efi/libstub/arm32-stub.c	2016-07-24 15:23:50.000000000 -0400
@@ -26,6 +26,43 @@ efi_status_t check_platform_features(efi
 	return EFI_SUCCESS;
 }
 
+static efi_guid_t screen_info_guid = LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID;
+
+struct screen_info *alloc_screen_info(efi_system_table_t *sys_table_arg)
+{
+	struct screen_info *si;
+	efi_status_t status;
+
+	/*
+	 * Unlike on arm64, where we can directly fill out the screen_info
+	 * structure from the stub, we need to allocate a buffer to hold
+	 * its contents while we hand over to the kernel proper from the
+	 * decompressor.
+	 */
+	status = efi_call_early(allocate_pool, EFI_RUNTIME_SERVICES_DATA,
+				sizeof(*si), (void **)&si);
+
+	if (status != EFI_SUCCESS)
+		return NULL;
+
+	status = efi_call_early(install_configuration_table,
+				&screen_info_guid, si);
+	if (status == EFI_SUCCESS)
+		return si;
+
+	efi_call_early(free_pool, si);
+	return NULL;
+}
+
+void free_screen_info(efi_system_table_t *sys_table_arg, struct screen_info *si)
+{
+	if (!si)
+		return;
+
+	efi_call_early(install_configuration_table, &screen_info_guid, NULL);
+	efi_call_early(free_pool, si);
+}
+
 efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
 				 unsigned long *image_addr,
 				 unsigned long *image_size,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/firmware/efi/libstub/arm64-stub.c linux-libre-4.7-gnu/drivers/firmware/efi/libstub/arm64-stub.c
--- linux-libre-4.6-gnu/drivers/firmware/efi/libstub/arm64-stub.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/firmware/efi/libstub/arm64-stub.c	2016-07-24 15:23:50.000000000 -0400
@@ -81,15 +81,24 @@ efi_status_t handle_kernel_image(efi_sys
 
 	if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && phys_seed != 0) {
 		/*
+		 * If CONFIG_DEBUG_ALIGN_RODATA is not set, produce a
+		 * displacement in the interval [0, MIN_KIMG_ALIGN) that
+		 * is a multiple of the minimal segment alignment (SZ_64K)
+		 */
+		u32 mask = (MIN_KIMG_ALIGN - 1) & ~(SZ_64K - 1);
+		u32 offset = !IS_ENABLED(CONFIG_DEBUG_ALIGN_RODATA) ?
+			     (phys_seed >> 32) & mask : TEXT_OFFSET;
+
+		/*
 		 * If KASLR is enabled, and we have some randomness available,
 		 * locate the kernel at a randomized offset in physical memory.
 		 */
-		*reserve_size = kernel_memsize + TEXT_OFFSET;
+		*reserve_size = kernel_memsize + offset;
 		status = efi_random_alloc(sys_table_arg, *reserve_size,
 					  MIN_KIMG_ALIGN, reserve_addr,
-					  phys_seed);
+					  (u32)phys_seed);
 
-		*image_addr = *reserve_addr + TEXT_OFFSET;
+		*image_addr = *reserve_addr + offset;
 	} else {
 		/*
 		 * Else, try a straight allocation at the preferred offset.
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/firmware/efi/libstub/arm-stub.c linux-libre-4.7-gnu/drivers/firmware/efi/libstub/arm-stub.c
--- linux-libre-4.6-gnu/drivers/firmware/efi/libstub/arm-stub.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/firmware/efi/libstub/arm-stub.c	2016-07-24 15:23:50.000000000 -0400
@@ -20,27 +20,49 @@
 
 bool __nokaslr;
 
-static int efi_secureboot_enabled(efi_system_table_t *sys_table_arg)
+static int efi_get_secureboot(efi_system_table_t *sys_table_arg)
 {
-	static efi_guid_t const var_guid = EFI_GLOBAL_VARIABLE_GUID;
-	static efi_char16_t const var_name[] = {
+	static efi_char16_t const sb_var_name[] = {
 		'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', 0 };
+	static efi_char16_t const sm_var_name[] = {
+		'S', 'e', 't', 'u', 'p', 'M', 'o', 'd', 'e', 0 };
 
+	efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID;
 	efi_get_variable_t *f_getvar = sys_table_arg->runtime->get_variable;
-	unsigned long size = sizeof(u8);
-	efi_status_t status;
 	u8 val;
+	unsigned long size = sizeof(val);
+	efi_status_t status;
 
-	status = f_getvar((efi_char16_t *)var_name, (efi_guid_t *)&var_guid,
+	status = f_getvar((efi_char16_t *)sb_var_name, (efi_guid_t *)&var_guid,
 			  NULL, &size, &val);
 
+	if (status != EFI_SUCCESS)
+		goto out_efi_err;
+
+	if (val == 0)
+		return 0;
+
+	status = f_getvar((efi_char16_t *)sm_var_name, (efi_guid_t *)&var_guid,
+			  NULL, &size, &val);
+
+	if (status != EFI_SUCCESS)
+		goto out_efi_err;
+
+	if (val == 1)
+		return 0;
+
+	return 1;
+
+out_efi_err:
 	switch (status) {
-	case EFI_SUCCESS:
-		return val;
 	case EFI_NOT_FOUND:
 		return 0;
+	case EFI_DEVICE_ERROR:
+		return -EIO;
+	case EFI_SECURITY_VIOLATION:
+		return -EACCES;
 	default:
-		return 1;
+		return -EINVAL;
 	}
 }
 
@@ -147,6 +169,25 @@ void efi_char16_printk(efi_system_table_
 	out->output_string(out, str);
 }
 
+static struct screen_info *setup_graphics(efi_system_table_t *sys_table_arg)
+{
+	efi_guid_t gop_proto = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
+	efi_status_t status;
+	unsigned long size;
+	void **gop_handle = NULL;
+	struct screen_info *si = NULL;
+
+	size = 0;
+	status = efi_call_early(locate_handle, EFI_LOCATE_BY_PROTOCOL,
+				&gop_proto, NULL, &size, gop_handle);
+	if (status == EFI_BUFFER_TOO_SMALL) {
+		si = alloc_screen_info(sys_table_arg);
+		if (!si)
+			return NULL;
+		efi_setup_gop(sys_table_arg, si, &gop_proto, size);
+	}
+	return si;
+}
 
 /*
  * This function handles the architcture specific differences between arm and
@@ -185,6 +226,8 @@ unsigned long efi_entry(void *handle, ef
 	efi_guid_t loaded_image_proto = LOADED_IMAGE_PROTOCOL_GUID;
 	unsigned long reserve_addr = 0;
 	unsigned long reserve_size = 0;
+	int secure_boot = 0;
+	struct screen_info *si;
 
 	/* Check if we were booted by the EFI firmware */
 	if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
@@ -237,6 +280,8 @@ unsigned long efi_entry(void *handle, ef
 			__nokaslr = true;
 	}
 
+	si = setup_graphics(sys_table);
+
 	status = handle_kernel_image(sys_table, image_addr, &image_size,
 				     &reserve_addr,
 				     &reserve_size,
@@ -250,12 +295,21 @@ unsigned long efi_entry(void *handle, ef
 	if (status != EFI_SUCCESS)
 		pr_efi_err(sys_table, "Failed to parse EFI cmdline options\n");
 
+	secure_boot = efi_get_secureboot(sys_table);
+	if (secure_boot > 0)
+		pr_efi(sys_table, "UEFI Secure Boot is enabled.\n");
+
+	if (secure_boot < 0) {
+		pr_efi_err(sys_table,
+			"could not determine UEFI Secure Boot status.\n");
+	}
+
 	/*
 	 * Unauthenticated device tree data is a security hazard, so
 	 * ignore 'dtb=' unless UEFI Secure Boot is disabled.
 	 */
-	if (efi_secureboot_enabled(sys_table)) {
-		pr_efi(sys_table, "UEFI Secure Boot is enabled.\n");
+	if (secure_boot != 0 && strstr(cmdline_ptr, "dtb=")) {
+		pr_efi(sys_table, "Ignoring DTB from command line.\n");
 	} else {
 		status = handle_cmdline_files(sys_table, image, cmdline_ptr,
 					      "dtb=",
@@ -309,6 +363,7 @@ fail_free_image:
 	efi_free(sys_table, image_size, *image_addr);
 	efi_free(sys_table, reserve_size, reserve_addr);
 fail_free_cmdline:
+	free_screen_info(sys_table, si);
 	efi_free(sys_table, cmdline_size, (unsigned long)cmdline_ptr);
 fail:
 	return EFI_ERROR;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/firmware/efi/libstub/efi-stub-helper.c linux-libre-4.7-gnu/drivers/firmware/efi/libstub/efi-stub-helper.c
--- linux-libre-4.6-gnu/drivers/firmware/efi/libstub/efi-stub-helper.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/firmware/efi/libstub/efi-stub-helper.c	2016-07-24 15:23:50.000000000 -0400
@@ -125,10 +125,12 @@ unsigned long get_dram_base(efi_system_t
 
 	map.map_end = map.map + map_size;
 
-	for_each_efi_memory_desc(&map, md)
-		if (md->attribute & EFI_MEMORY_WB)
+	for_each_efi_memory_desc_in_map(&map, md) {
+		if (md->attribute & EFI_MEMORY_WB) {
 			if (membase > md->phys_addr)
 				membase = md->phys_addr;
+		}
+	}
 
 	efi_call_early(free_pool, map.map);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/firmware/efi/libstub/fdt.c linux-libre-4.7-gnu/drivers/firmware/efi/libstub/fdt.c
--- linux-libre-4.6-gnu/drivers/firmware/efi/libstub/fdt.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/firmware/efi/libstub/fdt.c	2016-07-24 15:23:50.000000000 -0400
@@ -24,7 +24,7 @@ efi_status_t update_fdt(efi_system_table
 			unsigned long map_size, unsigned long desc_size,
 			u32 desc_ver)
 {
-	int node, prev, num_rsv;
+	int node, num_rsv;
 	int status;
 	u32 fdt_val32;
 	u64 fdt_val64;
@@ -54,28 +54,6 @@ efi_status_t update_fdt(efi_system_table
 		goto fdt_set_fail;
 
 	/*
-	 * Delete any memory nodes present. We must delete nodes which
-	 * early_init_dt_scan_memory may try to use.
-	 */
-	prev = 0;
-	for (;;) {
-		const char *type;
-		int len;
-
-		node = fdt_next_node(fdt, prev, NULL);
-		if (node < 0)
-			break;
-
-		type = fdt_getprop(fdt, node, "device_type", &len);
-		if (type && strncmp(type, "memory", len) == 0) {
-			fdt_del_node(fdt, node);
-			continue;
-		}
-
-		prev = node;
-	}
-
-	/*
 	 * Delete all memory reserve map entries. When booting via UEFI,
 	 * kernel will use the UEFI memory map to find reserved regions.
 	 */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/firmware/efi/libstub/gop.c linux-libre-4.7-gnu/drivers/firmware/efi/libstub/gop.c
--- linux-libre-4.6-gnu/drivers/firmware/efi/libstub/gop.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/firmware/efi/libstub/gop.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,354 @@
+/* -----------------------------------------------------------------------
+ *
+ *   Copyright 2011 Intel Corporation; author Matt Fleming
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <linux/efi.h>
+#include <linux/screen_info.h>
+#include <asm/efi.h>
+#include <asm/setup.h>
+
+static void find_bits(unsigned long mask, u8 *pos, u8 *size)
+{
+	u8 first, len;
+
+	first = 0;
+	len = 0;
+
+	if (mask) {
+		while (!(mask & 0x1)) {
+			mask = mask >> 1;
+			first++;
+		}
+
+		while (mask & 0x1) {
+			mask = mask >> 1;
+			len++;
+		}
+	}
+
+	*pos = first;
+	*size = len;
+}
+
+static void
+setup_pixel_info(struct screen_info *si, u32 pixels_per_scan_line,
+		 struct efi_pixel_bitmask pixel_info, int pixel_format)
+{
+	if (pixel_format == PIXEL_RGB_RESERVED_8BIT_PER_COLOR) {
+		si->lfb_depth = 32;
+		si->lfb_linelength = pixels_per_scan_line * 4;
+		si->red_size = 8;
+		si->red_pos = 0;
+		si->green_size = 8;
+		si->green_pos = 8;
+		si->blue_size = 8;
+		si->blue_pos = 16;
+		si->rsvd_size = 8;
+		si->rsvd_pos = 24;
+	} else if (pixel_format == PIXEL_BGR_RESERVED_8BIT_PER_COLOR) {
+		si->lfb_depth = 32;
+		si->lfb_linelength = pixels_per_scan_line * 4;
+		si->red_size = 8;
+		si->red_pos = 16;
+		si->green_size = 8;
+		si->green_pos = 8;
+		si->blue_size = 8;
+		si->blue_pos = 0;
+		si->rsvd_size = 8;
+		si->rsvd_pos = 24;
+	} else if (pixel_format == PIXEL_BIT_MASK) {
+		find_bits(pixel_info.red_mask, &si->red_pos, &si->red_size);
+		find_bits(pixel_info.green_mask, &si->green_pos,
+			  &si->green_size);
+		find_bits(pixel_info.blue_mask, &si->blue_pos, &si->blue_size);
+		find_bits(pixel_info.reserved_mask, &si->rsvd_pos,
+			  &si->rsvd_size);
+		si->lfb_depth = si->red_size + si->green_size +
+			si->blue_size + si->rsvd_size;
+		si->lfb_linelength = (pixels_per_scan_line * si->lfb_depth) / 8;
+	} else {
+		si->lfb_depth = 4;
+		si->lfb_linelength = si->lfb_width / 2;
+		si->red_size = 0;
+		si->red_pos = 0;
+		si->green_size = 0;
+		si->green_pos = 0;
+		si->blue_size = 0;
+		si->blue_pos = 0;
+		si->rsvd_size = 0;
+		si->rsvd_pos = 0;
+	}
+}
+
+static efi_status_t
+__gop_query32(efi_system_table_t *sys_table_arg,
+	      struct efi_graphics_output_protocol_32 *gop32,
+	      struct efi_graphics_output_mode_info **info,
+	      unsigned long *size, u64 *fb_base)
+{
+	struct efi_graphics_output_protocol_mode_32 *mode;
+	efi_graphics_output_protocol_query_mode query_mode;
+	efi_status_t status;
+	unsigned long m;
+
+	m = gop32->mode;
+	mode = (struct efi_graphics_output_protocol_mode_32 *)m;
+	query_mode = (void *)(unsigned long)gop32->query_mode;
+
+	status = __efi_call_early(query_mode, (void *)gop32, mode->mode, size,
+				  info);
+	if (status != EFI_SUCCESS)
+		return status;
+
+	*fb_base = mode->frame_buffer_base;
+	return status;
+}
+
+static efi_status_t
+setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si,
+            efi_guid_t *proto, unsigned long size, void **gop_handle)
+{
+	struct efi_graphics_output_protocol_32 *gop32, *first_gop;
+	unsigned long nr_gops;
+	u16 width, height;
+	u32 pixels_per_scan_line;
+	u32 ext_lfb_base;
+	u64 fb_base;
+	struct efi_pixel_bitmask pixel_info;
+	int pixel_format;
+	efi_status_t status = EFI_NOT_FOUND;
+	u32 *handles = (u32 *)(unsigned long)gop_handle;
+	int i;
+
+	first_gop = NULL;
+	gop32 = NULL;
+
+	nr_gops = size / sizeof(u32);
+	for (i = 0; i < nr_gops; i++) {
+		struct efi_graphics_output_mode_info *info = NULL;
+		efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
+		bool conout_found = false;
+		void *dummy = NULL;
+		efi_handle_t h = (efi_handle_t)(unsigned long)handles[i];
+		u64 current_fb_base;
+
+		status = efi_call_early(handle_protocol, h,
+					proto, (void **)&gop32);
+		if (status != EFI_SUCCESS)
+			continue;
+
+		status = efi_call_early(handle_protocol, h,
+					&conout_proto, &dummy);
+		if (status == EFI_SUCCESS)
+			conout_found = true;
+
+		status = __gop_query32(sys_table_arg, gop32, &info, &size,
+				       &current_fb_base);
+		if (status == EFI_SUCCESS && (!first_gop || conout_found)) {
+			/*
+			 * Systems that use the UEFI Console Splitter may
+			 * provide multiple GOP devices, not all of which are
+			 * backed by real hardware. The workaround is to search
+			 * for a GOP implementing the ConOut protocol, and if
+			 * one isn't found, to just fall back to the first GOP.
+			 */
+			width = info->horizontal_resolution;
+			height = info->vertical_resolution;
+			pixel_format = info->pixel_format;
+			pixel_info = info->pixel_information;
+			pixels_per_scan_line = info->pixels_per_scan_line;
+			fb_base = current_fb_base;
+
+			/*
+			 * Once we've found a GOP supporting ConOut,
+			 * don't bother looking any further.
+			 */
+			first_gop = gop32;
+			if (conout_found)
+				break;
+		}
+	}
+
+	/* Did we find any GOPs? */
+	if (!first_gop)
+		goto out;
+
+	/* EFI framebuffer */
+	si->orig_video_isVGA = VIDEO_TYPE_EFI;
+
+	si->lfb_width = width;
+	si->lfb_height = height;
+	si->lfb_base = fb_base;
+
+	ext_lfb_base = (u64)(unsigned long)fb_base >> 32;
+	if (ext_lfb_base) {
+		si->capabilities |= VIDEO_CAPABILITY_64BIT_BASE;
+		si->ext_lfb_base = ext_lfb_base;
+	}
+
+	si->pages = 1;
+
+	setup_pixel_info(si, pixels_per_scan_line, pixel_info, pixel_format);
+
+	si->lfb_size = si->lfb_linelength * si->lfb_height;
+
+	si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS;
+out:
+	return status;
+}
+
+static efi_status_t
+__gop_query64(efi_system_table_t *sys_table_arg,
+	      struct efi_graphics_output_protocol_64 *gop64,
+	      struct efi_graphics_output_mode_info **info,
+	      unsigned long *size, u64 *fb_base)
+{
+	struct efi_graphics_output_protocol_mode_64 *mode;
+	efi_graphics_output_protocol_query_mode query_mode;
+	efi_status_t status;
+	unsigned long m;
+
+	m = gop64->mode;
+	mode = (struct efi_graphics_output_protocol_mode_64 *)m;
+	query_mode = (void *)(unsigned long)gop64->query_mode;
+
+	status = __efi_call_early(query_mode, (void *)gop64, mode->mode, size,
+				  info);
+	if (status != EFI_SUCCESS)
+		return status;
+
+	*fb_base = mode->frame_buffer_base;
+	return status;
+}
+
+static efi_status_t
+setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si,
+	    efi_guid_t *proto, unsigned long size, void **gop_handle)
+{
+	struct efi_graphics_output_protocol_64 *gop64, *first_gop;
+	unsigned long nr_gops;
+	u16 width, height;
+	u32 pixels_per_scan_line;
+	u32 ext_lfb_base;
+	u64 fb_base;
+	struct efi_pixel_bitmask pixel_info;
+	int pixel_format;
+	efi_status_t status = EFI_NOT_FOUND;
+	u64 *handles = (u64 *)(unsigned long)gop_handle;
+	int i;
+
+	first_gop = NULL;
+	gop64 = NULL;
+
+	nr_gops = size / sizeof(u64);
+	for (i = 0; i < nr_gops; i++) {
+		struct efi_graphics_output_mode_info *info = NULL;
+		efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
+		bool conout_found = false;
+		void *dummy = NULL;
+		efi_handle_t h = (efi_handle_t)(unsigned long)handles[i];
+		u64 current_fb_base;
+
+		status = efi_call_early(handle_protocol, h,
+					proto, (void **)&gop64);
+		if (status != EFI_SUCCESS)
+			continue;
+
+		status = efi_call_early(handle_protocol, h,
+					&conout_proto, &dummy);
+		if (status == EFI_SUCCESS)
+			conout_found = true;
+
+		status = __gop_query64(sys_table_arg, gop64, &info, &size,
+				       &current_fb_base);
+		if (status == EFI_SUCCESS && (!first_gop || conout_found)) {
+			/*
+			 * Systems that use the UEFI Console Splitter may
+			 * provide multiple GOP devices, not all of which are
+			 * backed by real hardware. The workaround is to search
+			 * for a GOP implementing the ConOut protocol, and if
+			 * one isn't found, to just fall back to the first GOP.
+			 */
+			width = info->horizontal_resolution;
+			height = info->vertical_resolution;
+			pixel_format = info->pixel_format;
+			pixel_info = info->pixel_information;
+			pixels_per_scan_line = info->pixels_per_scan_line;
+			fb_base = current_fb_base;
+
+			/*
+			 * Once we've found a GOP supporting ConOut,
+			 * don't bother looking any further.
+			 */
+			first_gop = gop64;
+			if (conout_found)
+				break;
+		}
+	}
+
+	/* Did we find any GOPs? */
+	if (!first_gop)
+		goto out;
+
+	/* EFI framebuffer */
+	si->orig_video_isVGA = VIDEO_TYPE_EFI;
+
+	si->lfb_width = width;
+	si->lfb_height = height;
+	si->lfb_base = fb_base;
+
+	ext_lfb_base = (u64)(unsigned long)fb_base >> 32;
+	if (ext_lfb_base) {
+		si->capabilities |= VIDEO_CAPABILITY_64BIT_BASE;
+		si->ext_lfb_base = ext_lfb_base;
+	}
+
+	si->pages = 1;
+
+	setup_pixel_info(si, pixels_per_scan_line, pixel_info, pixel_format);
+
+	si->lfb_size = si->lfb_linelength * si->lfb_height;
+
+	si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS;
+out:
+	return status;
+}
+
+/*
+ * See if we have Graphics Output Protocol
+ */
+efi_status_t efi_setup_gop(efi_system_table_t *sys_table_arg,
+			   struct screen_info *si, efi_guid_t *proto,
+			   unsigned long size)
+{
+	efi_status_t status;
+	void **gop_handle = NULL;
+
+	status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
+				size, (void **)&gop_handle);
+	if (status != EFI_SUCCESS)
+		return status;
+
+	status = efi_call_early(locate_handle,
+				EFI_LOCATE_BY_PROTOCOL,
+				proto, NULL, &size, gop_handle);
+	if (status != EFI_SUCCESS)
+		goto free_handle;
+
+	if (efi_is_64bit()) {
+		status = setup_gop64(sys_table_arg, si, proto, size,
+				     gop_handle);
+	} else {
+		status = setup_gop32(sys_table_arg, si, proto, size,
+				     gop_handle);
+	}
+
+free_handle:
+	efi_call_early(free_pool, gop_handle);
+	return status;
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/firmware/efi/libstub/Makefile linux-libre-4.7-gnu/drivers/firmware/efi/libstub/Makefile
--- linux-libre-4.6-gnu/drivers/firmware/efi/libstub/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/firmware/efi/libstub/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -28,7 +28,7 @@ OBJECT_FILES_NON_STANDARD	:= y
 # Prevents link failures: __sanitizer_cov_trace_pc() is not linked in.
 KCOV_INSTRUMENT			:= n
 
-lib-y				:= efi-stub-helper.o
+lib-y				:= efi-stub-helper.o gop.o
 
 # include the stub's generic dependencies from lib/ when building for ARM/arm64
 arm-deps := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c sort.c
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/firmware/efi/Makefile linux-libre-4.7-gnu/drivers/firmware/efi/Makefile
--- linux-libre-4.6-gnu/drivers/firmware/efi/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/firmware/efi/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -9,7 +9,8 @@
 #
 KASAN_SANITIZE_runtime-wrappers.o	:= n
 
-obj-$(CONFIG_EFI)			+= efi.o vars.o reboot.o
+obj-$(CONFIG_EFI)			+= efi.o vars.o reboot.o memattr.o
+obj-$(CONFIG_EFI)			+= capsule.o
 obj-$(CONFIG_EFI_VARS)			+= efivars.o
 obj-$(CONFIG_EFI_ESRT)			+= esrt.o
 obj-$(CONFIG_EFI_VARS_PSTORE)		+= efi-pstore.o
@@ -18,7 +19,9 @@ obj-$(CONFIG_EFI_RUNTIME_MAP)		+= runtim
 obj-$(CONFIG_EFI_RUNTIME_WRAPPERS)	+= runtime-wrappers.o
 obj-$(CONFIG_EFI_STUB)			+= libstub/
 obj-$(CONFIG_EFI_FAKE_MEMMAP)		+= fake_mem.o
+obj-$(CONFIG_EFI_BOOTLOADER_CONTROL)	+= efibc.o
 
 arm-obj-$(CONFIG_EFI)			:= arm-init.o arm-runtime.o
 obj-$(CONFIG_ARM)			+= $(arm-obj-y)
 obj-$(CONFIG_ARM64)			+= $(arm-obj-y)
+obj-$(CONFIG_EFI_CAPSULE_LOADER)	+= capsule-loader.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/firmware/efi/memattr.c linux-libre-4.7-gnu/drivers/firmware/efi/memattr.c
--- linux-libre-4.6-gnu/drivers/firmware/efi/memattr.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/firmware/efi/memattr.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2016 Linaro Ltd. <ard.biesheuvel@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define pr_fmt(fmt)	"efi: memattr: " fmt
+
+#include <linux/efi.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/memblock.h>
+
+#include <asm/early_ioremap.h>
+
+static int __initdata tbl_size;
+
+/*
+ * Reserve the memory associated with the Memory Attributes configuration
+ * table, if it exists.
+ */
+int __init efi_memattr_init(void)
+{
+	efi_memory_attributes_table_t *tbl;
+
+	if (efi.mem_attr_table == EFI_INVALID_TABLE_ADDR)
+		return 0;
+
+	tbl = early_memremap(efi.mem_attr_table, sizeof(*tbl));
+	if (!tbl) {
+		pr_err("Failed to map EFI Memory Attributes table @ 0x%lx\n",
+		       efi.mem_attr_table);
+		return -ENOMEM;
+	}
+
+	if (tbl->version > 1) {
+		pr_warn("Unexpected EFI Memory Attributes table version %d\n",
+			tbl->version);
+		goto unmap;
+	}
+
+	tbl_size = sizeof(*tbl) + tbl->num_entries * tbl->desc_size;
+	memblock_reserve(efi.mem_attr_table, tbl_size);
+
+unmap:
+	early_memunmap(tbl, sizeof(*tbl));
+	return 0;
+}
+
+/*
+ * Returns a copy @out of the UEFI memory descriptor @in if it is covered
+ * entirely by a UEFI memory map entry with matching attributes. The virtual
+ * address of @out is set according to the matching entry that was found.
+ */
+static bool entry_is_valid(const efi_memory_desc_t *in, efi_memory_desc_t *out)
+{
+	u64 in_paddr = in->phys_addr;
+	u64 in_size = in->num_pages << EFI_PAGE_SHIFT;
+	efi_memory_desc_t *md;
+
+	*out = *in;
+
+	if (in->type != EFI_RUNTIME_SERVICES_CODE &&
+	    in->type != EFI_RUNTIME_SERVICES_DATA) {
+		pr_warn("Entry type should be RuntimeServiceCode/Data\n");
+		return false;
+	}
+
+	if (!(in->attribute & (EFI_MEMORY_RO | EFI_MEMORY_XP))) {
+		pr_warn("Entry attributes invalid: RO and XP bits both cleared\n");
+		return false;
+	}
+
+	if (PAGE_SIZE > EFI_PAGE_SIZE &&
+	    (!PAGE_ALIGNED(in->phys_addr) ||
+	     !PAGE_ALIGNED(in->num_pages << EFI_PAGE_SHIFT))) {
+		/*
+		 * Since arm64 may execute with page sizes of up to 64 KB, the
+		 * UEFI spec mandates that RuntimeServices memory regions must
+		 * be 64 KB aligned. We need to validate this here since we will
+		 * not be able to tighten permissions on such regions without
+		 * affecting adjacent regions.
+		 */
+		pr_warn("Entry address region misaligned\n");
+		return false;
+	}
+
+	for_each_efi_memory_desc(md) {
+		u64 md_paddr = md->phys_addr;
+		u64 md_size = md->num_pages << EFI_PAGE_SHIFT;
+
+		if (!(md->attribute & EFI_MEMORY_RUNTIME))
+			continue;
+		if (md->virt_addr == 0) {
+			/* no virtual mapping has been installed by the stub */
+			break;
+		}
+
+		if (md_paddr > in_paddr || (in_paddr - md_paddr) >= md_size)
+			continue;
+
+		/*
+		 * This entry covers the start of @in, check whether
+		 * it covers the end as well.
+		 */
+		if (md_paddr + md_size < in_paddr + in_size) {
+			pr_warn("Entry covers multiple EFI memory map regions\n");
+			return false;
+		}
+
+		if (md->type != in->type) {
+			pr_warn("Entry type deviates from EFI memory map region type\n");
+			return false;
+		}
+
+		out->virt_addr = in_paddr + (md->virt_addr - md_paddr);
+
+		return true;
+	}
+
+	pr_warn("No matching entry found in the EFI memory map\n");
+	return false;
+}
+
+/*
+ * To be called after the EFI page tables have been populated. If a memory
+ * attributes table is available, its contents will be used to update the
+ * mappings with tightened permissions as described by the table.
+ * This requires the UEFI memory map to have already been populated with
+ * virtual addresses.
+ */
+int __init efi_memattr_apply_permissions(struct mm_struct *mm,
+					 efi_memattr_perm_setter fn)
+{
+	efi_memory_attributes_table_t *tbl;
+	int i, ret;
+
+	if (tbl_size <= sizeof(*tbl))
+		return 0;
+
+	/*
+	 * We need the EFI memory map to be setup so we can use it to
+	 * lookup the virtual addresses of all entries in the  of EFI
+	 * Memory Attributes table. If it isn't available, this
+	 * function should not be called.
+	 */
+	if (WARN_ON(!efi_enabled(EFI_MEMMAP)))
+		return 0;
+
+	tbl = memremap(efi.mem_attr_table, tbl_size, MEMREMAP_WB);
+	if (!tbl) {
+		pr_err("Failed to map EFI Memory Attributes table @ 0x%lx\n",
+		       efi.mem_attr_table);
+		return -ENOMEM;
+	}
+
+	if (efi_enabled(EFI_DBG))
+		pr_info("Processing EFI Memory Attributes table:\n");
+
+	for (i = ret = 0; ret == 0 && i < tbl->num_entries; i++) {
+		efi_memory_desc_t md;
+		unsigned long size;
+		bool valid;
+		char buf[64];
+
+		valid = entry_is_valid((void *)tbl->entry + i * tbl->desc_size,
+				       &md);
+		size = md.num_pages << EFI_PAGE_SHIFT;
+		if (efi_enabled(EFI_DBG) || !valid)
+			pr_info("%s 0x%012llx-0x%012llx %s\n",
+				valid ? "" : "!", md.phys_addr,
+				md.phys_addr + size - 1,
+				efi_md_typeattr_format(buf, sizeof(buf), &md));
+
+		if (valid)
+			ret = fn(mm, &md);
+	}
+	memunmap(tbl);
+	return ret;
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/firmware/efi/reboot.c linux-libre-4.7-gnu/drivers/firmware/efi/reboot.c
--- linux-libre-4.6-gnu/drivers/firmware/efi/reboot.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/firmware/efi/reboot.c	2016-07-24 15:23:50.000000000 -0400
@@ -9,7 +9,8 @@ int efi_reboot_quirk_mode = -1;
 
 void efi_reboot(enum reboot_mode reboot_mode, const char *__unused)
 {
-	int efi_mode;
+	const char *str[] = { "cold", "warm", "shutdown", "platform" };
+	int efi_mode, cap_reset_mode;
 
 	if (!efi_enabled(EFI_RUNTIME_SERVICES))
 		return;
@@ -30,6 +31,15 @@ void efi_reboot(enum reboot_mode reboot_
 	if (efi_reboot_quirk_mode != -1)
 		efi_mode = efi_reboot_quirk_mode;
 
+	if (efi_capsule_pending(&cap_reset_mode)) {
+		if (efi_mode != cap_reset_mode)
+			printk(KERN_CRIT "efi: %s reset requested but pending "
+			       "capsule update requires %s reset... Performing "
+			       "%s reset.\n", str[efi_mode], str[cap_reset_mode],
+			       str[cap_reset_mode]);
+		efi_mode = cap_reset_mode;
+	}
+
 	efi.reset_system(efi_mode, EFI_SUCCESS, 0, NULL);
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/firmware/efi/runtime-wrappers.c linux-libre-4.7-gnu/drivers/firmware/efi/runtime-wrappers.c
--- linux-libre-4.6-gnu/drivers/firmware/efi/runtime-wrappers.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/firmware/efi/runtime-wrappers.c	2016-07-24 15:23:50.000000000 -0400
@@ -16,10 +16,70 @@
 
 #include <linux/bug.h>
 #include <linux/efi.h>
+#include <linux/irqflags.h>
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
+#include <linux/stringify.h>
 #include <asm/efi.h>
 
+static void efi_call_virt_check_flags(unsigned long flags, const char *call)
+{
+	unsigned long cur_flags, mismatch;
+
+	local_save_flags(cur_flags);
+
+	mismatch = flags ^ cur_flags;
+	if (!WARN_ON_ONCE(mismatch & ARCH_EFI_IRQ_FLAGS_MASK))
+		return;
+
+	add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_NOW_UNRELIABLE);
+	pr_err_ratelimited(FW_BUG "IRQ flags corrupted (0x%08lx=>0x%08lx) by EFI %s\n",
+			   flags, cur_flags, call);
+	local_irq_restore(flags);
+}
+
+/*
+ * Arch code can implement the following three template macros, avoiding
+ * reptition for the void/non-void return cases of {__,}efi_call_virt:
+ *
+ *  * arch_efi_call_virt_setup
+ *
+ *    Sets up the environment for the call (e.g. switching page tables,
+ *    allowing kernel-mode use of floating point, if required).
+ *
+ *  * arch_efi_call_virt
+ *
+ *    Performs the call. The last expression in the macro must be the call
+ *    itself, allowing the logic to be shared by the void and non-void
+ *    cases.
+ *
+ *  * arch_efi_call_virt_teardown
+ *
+ *    Restores the usual kernel environment once the call has returned.
+ */
+
+#define efi_call_virt(f, args...)					\
+({									\
+	efi_status_t __s;						\
+	unsigned long flags;						\
+	arch_efi_call_virt_setup();					\
+	local_save_flags(flags);					\
+	__s = arch_efi_call_virt(f, args);				\
+	efi_call_virt_check_flags(flags, __stringify(f));		\
+	arch_efi_call_virt_teardown();					\
+	__s;								\
+})
+
+#define __efi_call_virt(f, args...)					\
+({									\
+	unsigned long flags;						\
+	arch_efi_call_virt_setup();					\
+	local_save_flags(flags);					\
+	arch_efi_call_virt(f, args);					\
+	efi_call_virt_check_flags(flags, __stringify(f));		\
+	arch_efi_call_virt_teardown();					\
+})
+
 /*
  * According to section 7.1 of the UEFI spec, Runtime Services are not fully
  * reentrant, and there are particular combinations of calls that need to be
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/firmware/efi/vars.c linux-libre-4.7-gnu/drivers/firmware/efi/vars.c
--- linux-libre-4.6-gnu/drivers/firmware/efi/vars.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/firmware/efi/vars.c	2016-07-24 15:23:50.000000000 -0400
@@ -329,39 +329,6 @@ check_var_size_nonblocking(u32 attribute
 	return fops->query_variable_store(attributes, size, true);
 }
 
-static int efi_status_to_err(efi_status_t status)
-{
-	int err;
-
-	switch (status) {
-	case EFI_SUCCESS:
-		err = 0;
-		break;
-	case EFI_INVALID_PARAMETER:
-		err = -EINVAL;
-		break;
-	case EFI_OUT_OF_RESOURCES:
-		err = -ENOSPC;
-		break;
-	case EFI_DEVICE_ERROR:
-		err = -EIO;
-		break;
-	case EFI_WRITE_PROTECTED:
-		err = -EROFS;
-		break;
-	case EFI_SECURITY_VIOLATION:
-		err = -EACCES;
-		break;
-	case EFI_NOT_FOUND:
-		err = -ENOENT;
-		break;
-	default:
-		err = -EINVAL;
-	}
-
-	return err;
-}
-
 static bool variable_is_present(efi_char16_t *variable_name, efi_guid_t *vendor,
 				struct list_head *head)
 {
@@ -452,8 +419,7 @@ static void dup_variable_bug(efi_char16_
  * Returns 0 on success, or a kernel error code on failure.
  */
 int efivar_init(int (*func)(efi_char16_t *, efi_guid_t, unsigned long, void *),
-		void *data, bool atomic, bool duplicates,
-		struct list_head *head)
+		void *data, bool duplicates, struct list_head *head)
 {
 	const struct efivar_operations *ops = __efivars->ops;
 	unsigned long variable_name_size = 1024;
@@ -483,7 +449,7 @@ int efivar_init(int (*func)(efi_char16_t
 						&vendor_guid);
 		switch (status) {
 		case EFI_SUCCESS:
-			if (!atomic)
+			if (duplicates)
 				spin_unlock_irq(&__efivars->lock);
 
 			variable_name_size = var_name_strnsize(variable_name,
@@ -498,21 +464,19 @@ int efivar_init(int (*func)(efi_char16_t
 			 * and may end up looping here forever.
 			 */
 			if (duplicates &&
-			    variable_is_present(variable_name, &vendor_guid, head)) {
+			    variable_is_present(variable_name, &vendor_guid,
+						head)) {
 				dup_variable_bug(variable_name, &vendor_guid,
 						 variable_name_size);
-				if (!atomic)
-					spin_lock_irq(&__efivars->lock);
-
 				status = EFI_NOT_FOUND;
-				break;
+			} else {
+				err = func(variable_name, vendor_guid,
+					   variable_name_size, data);
+				if (err)
+					status = EFI_NOT_FOUND;
 			}
 
-			err = func(variable_name, vendor_guid, variable_name_size, data);
-			if (err)
-				status = EFI_NOT_FOUND;
-
-			if (!atomic)
+			if (duplicates)
 				spin_lock_irq(&__efivars->lock);
 
 			break;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/firmware/iscsi_ibft.c linux-libre-4.7-gnu/drivers/firmware/iscsi_ibft.c
--- linux-libre-4.6-gnu/drivers/firmware/iscsi_ibft.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/firmware/iscsi_ibft.c	2016-07-24 15:23:50.000000000 -0400
@@ -418,6 +418,31 @@ static ssize_t ibft_attr_show_target(voi
 	return str - buf;
 }
 
+static ssize_t ibft_attr_show_acpitbl(void *data, int type, char *buf)
+{
+	struct ibft_kobject *entry = data;
+	char *str = buf;
+
+	switch (type) {
+	case ISCSI_BOOT_ACPITBL_SIGNATURE:
+		str += sprintf_string(str, ACPI_NAME_SIZE,
+				      entry->header->header.signature);
+		break;
+	case ISCSI_BOOT_ACPITBL_OEM_ID:
+		str += sprintf_string(str, ACPI_OEM_ID_SIZE,
+				      entry->header->header.oem_id);
+		break;
+	case ISCSI_BOOT_ACPITBL_OEM_TABLE_ID:
+		str += sprintf_string(str, ACPI_OEM_TABLE_ID_SIZE,
+				      entry->header->header.oem_table_id);
+		break;
+	default:
+		break;
+	}
+
+	return str - buf;
+}
+
 static int __init ibft_check_device(void)
 {
 	int len;
@@ -576,6 +601,24 @@ static umode_t __init ibft_check_initiat
 	return rc;
 }
 
+static umode_t __init ibft_check_acpitbl_for(void *data, int type)
+{
+
+	umode_t rc = 0;
+
+	switch (type) {
+	case ISCSI_BOOT_ACPITBL_SIGNATURE:
+	case ISCSI_BOOT_ACPITBL_OEM_ID:
+	case ISCSI_BOOT_ACPITBL_OEM_TABLE_ID:
+		rc = S_IRUGO;
+		break;
+	default:
+		break;
+	}
+
+	return rc;
+}
+
 static void ibft_kobj_release(void *data)
 {
 	kfree(data);
@@ -699,6 +742,8 @@ free_ibft_obj:
 static int __init ibft_register_kobjects(struct acpi_table_ibft *header)
 {
 	struct ibft_control *control = NULL;
+	struct iscsi_boot_kobj *boot_kobj;
+	struct ibft_kobject *ibft_kobj;
 	void *ptr, *end;
 	int rc = 0;
 	u16 offset;
@@ -726,6 +771,25 @@ static int __init ibft_register_kobjects
 				break;
 		}
 	}
+	if (rc)
+		return rc;
+
+	ibft_kobj = kzalloc(sizeof(*ibft_kobj), GFP_KERNEL);
+	if (!ibft_kobj)
+		return -ENOMEM;
+
+	ibft_kobj->header = header;
+	ibft_kobj->hdr = NULL; /*for ibft_unregister*/
+
+	boot_kobj = iscsi_boot_create_acpitbl(boot_kset, 0,
+					ibft_kobj,
+					ibft_attr_show_acpitbl,
+					ibft_check_acpitbl_for,
+					ibft_kobj_release);
+	if (!boot_kobj)  {
+		kfree(ibft_kobj);
+		rc = -ENOMEM;
+	}
 
 	return rc;
 }
@@ -738,7 +802,7 @@ static void ibft_unregister(void)
 	list_for_each_entry_safe(boot_kobj, tmp_kobj,
 				 &boot_kset->kobj_list, list) {
 		ibft_kobj = boot_kobj->data;
-		if (ibft_kobj->hdr->id == id_nic)
+		if (ibft_kobj->hdr && ibft_kobj->hdr->id == id_nic)
 			sysfs_remove_link(&boot_kobj->kobj, "device");
 	};
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/firmware/psci.c linux-libre-4.7-gnu/drivers/firmware/psci.c
--- linux-libre-4.6-gnu/drivers/firmware/psci.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/firmware/psci.c	2016-07-24 15:23:50.000000000 -0400
@@ -91,7 +91,7 @@ static inline bool psci_has_ext_power_st
 				PSCI_1_0_FEATURES_CPU_SUSPEND_PF_MASK;
 }
 
-bool psci_power_state_loses_context(u32 state)
+static inline bool psci_power_state_loses_context(u32 state)
 {
 	const u32 mask = psci_has_ext_power_state() ?
 					PSCI_1_0_EXT_POWER_STATE_TYPE_MASK :
@@ -100,7 +100,7 @@ bool psci_power_state_loses_context(u32
 	return state & mask;
 }
 
-bool psci_power_state_is_valid(u32 state)
+static inline bool psci_power_state_is_valid(u32 state)
 {
 	const u32 valid_mask = psci_has_ext_power_state() ?
 			       PSCI_1_0_EXT_POWER_STATE_MASK :
@@ -355,7 +355,7 @@ int psci_cpu_suspend_enter(unsigned long
 
 /* ARM specific CPU idle operations */
 #ifdef CONFIG_ARM
-static struct cpuidle_ops psci_cpuidle_ops __initdata = {
+static const struct cpuidle_ops psci_cpuidle_ops __initconst = {
 	.suspend = psci_cpu_suspend_enter,
 	.init = psci_dt_cpu_init_idle,
 };
@@ -563,7 +563,7 @@ out_put_node:
 	return err;
 }
 
-static const struct of_device_id const psci_of_match[] __initconst = {
+static const struct of_device_id psci_of_match[] __initconst = {
 	{ .compatible = "arm,psci",	.data = psci_0_1_init},
 	{ .compatible = "arm,psci-0.2",	.data = psci_0_2_init},
 	{ .compatible = "arm,psci-1.0",	.data = psci_0_2_init},
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/firmware/qemu_fw_cfg.c linux-libre-4.7-gnu/drivers/firmware/qemu_fw_cfg.c
--- linux-libre-4.6-gnu/drivers/firmware/qemu_fw_cfg.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/firmware/qemu_fw_cfg.c	2016-07-24 15:23:50.000000000 -0400
@@ -125,9 +125,7 @@ static void fw_cfg_io_cleanup(void)
 #  define FW_CFG_CTRL_OFF 0x00
 #  define FW_CFG_DATA_OFF 0x01
 # else
-#  warning "QEMU FW_CFG may not be available on this architecture!"
-#  define FW_CFG_CTRL_OFF 0x00
-#  define FW_CFG_DATA_OFF 0x01
+#  error "QEMU FW_CFG not available on this architecture!"
 # endif
 #endif
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-104-dio-48e.c linux-libre-4.7-gnu/drivers/gpio/gpio-104-dio-48e.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-104-dio-48e.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-104-dio-48e.c	2016-07-24 15:23:50.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * GPIO driver for the ACCES 104-DIO-48E
+ * GPIO driver for the ACCES 104-DIO-48E series
  * Copyright (C) 2016 William Breathitt Gray
  *
  * This program is free software; you can redistribute it and/or modify
@@ -10,6 +10,9 @@
  * 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.
+ *
+ * This driver supports the following ACCES devices: 104-DIO-48E and
+ * 104-DIO-24E.
  */
 #include <linux/bitops.h>
 #include <linux/device.h>
@@ -19,18 +22,23 @@
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/irqdesc.h>
+#include <linux/isa.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/platform_device.h>
 #include <linux/spinlock.h>
 
-static unsigned dio_48e_base;
-module_param(dio_48e_base, uint, 0);
-MODULE_PARM_DESC(dio_48e_base, "ACCES 104-DIO-48E base address");
-static unsigned dio_48e_irq;
-module_param(dio_48e_irq, uint, 0);
-MODULE_PARM_DESC(dio_48e_irq, "ACCES 104-DIO-48E interrupt line number");
+#define DIO48E_EXTENT 16
+#define MAX_NUM_DIO48E max_num_isa_dev(DIO48E_EXTENT)
+
+static unsigned int base[MAX_NUM_DIO48E];
+static unsigned int num_dio48e;
+module_param_array(base, uint, &num_dio48e, 0);
+MODULE_PARM_DESC(base, "ACCES 104-DIO-48E base addresses");
+
+static unsigned int irq[MAX_NUM_DIO48E];
+module_param_array(irq, uint, NULL, 0);
+MODULE_PARM_DESC(irq, "ACCES 104-DIO-48E interrupt line numbers");
 
 /**
  * struct dio48e_gpio - GPIO device private data structure
@@ -67,7 +75,7 @@ static int dio48e_gpio_direction_input(s
 {
 	struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip);
 	const unsigned io_port = offset / 8;
-	const unsigned control_port = io_port / 2;
+	const unsigned int control_port = io_port / 3;
 	const unsigned control_addr = dio48egpio->base + 3 + control_port*4;
 	unsigned long flags;
 	unsigned control;
@@ -107,7 +115,7 @@ static int dio48e_gpio_direction_output(
 {
 	struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip);
 	const unsigned io_port = offset / 8;
-	const unsigned control_port = io_port / 2;
+	const unsigned int control_port = io_port / 3;
 	const unsigned mask = BIT(offset % 8);
 	const unsigned control_addr = dio48egpio->base + 3 + control_port*4;
 	const unsigned out_port = (io_port > 2) ? io_port + 1 : io_port;
@@ -294,23 +302,19 @@ static irqreturn_t dio48e_irq_handler(in
 	return IRQ_HANDLED;
 }
 
-static int __init dio48e_probe(struct platform_device *pdev)
+static int dio48e_probe(struct device *dev, unsigned int id)
 {
-	struct device *dev = &pdev->dev;
 	struct dio48e_gpio *dio48egpio;
-	const unsigned base = dio_48e_base;
-	const unsigned extent = 16;
 	const char *const name = dev_name(dev);
 	int err;
-	const unsigned irq = dio_48e_irq;
 
 	dio48egpio = devm_kzalloc(dev, sizeof(*dio48egpio), GFP_KERNEL);
 	if (!dio48egpio)
 		return -ENOMEM;
 
-	if (!devm_request_region(dev, base, extent, name)) {
+	if (!devm_request_region(dev, base[id], DIO48E_EXTENT, name)) {
 		dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
-			base, base + extent);
+			base[id], base[id] + DIO48E_EXTENT);
 		return -EBUSY;
 	}
 
@@ -324,8 +328,8 @@ static int __init dio48e_probe(struct pl
 	dio48egpio->chip.direction_output = dio48e_gpio_direction_output;
 	dio48egpio->chip.get = dio48e_gpio_get;
 	dio48egpio->chip.set = dio48e_gpio_set;
-	dio48egpio->base = base;
-	dio48egpio->irq = irq;
+	dio48egpio->base = base[id];
+	dio48egpio->irq = irq[id];
 
 	spin_lock_init(&dio48egpio->lock);
 
@@ -338,19 +342,19 @@ static int __init dio48e_probe(struct pl
 	}
 
 	/* initialize all GPIO as output */
-	outb(0x80, base + 3);
-	outb(0x00, base);
-	outb(0x00, base + 1);
-	outb(0x00, base + 2);
-	outb(0x00, base + 3);
-	outb(0x80, base + 7);
-	outb(0x00, base + 4);
-	outb(0x00, base + 5);
-	outb(0x00, base + 6);
-	outb(0x00, base + 7);
+	outb(0x80, base[id] + 3);
+	outb(0x00, base[id]);
+	outb(0x00, base[id] + 1);
+	outb(0x00, base[id] + 2);
+	outb(0x00, base[id] + 3);
+	outb(0x80, base[id] + 7);
+	outb(0x00, base[id] + 4);
+	outb(0x00, base[id] + 5);
+	outb(0x00, base[id] + 6);
+	outb(0x00, base[id] + 7);
 
 	/* disable IRQ by default */
-	inb(base + 0xB);
+	inb(base[id] + 0xB);
 
 	err = gpiochip_irqchip_add(&dio48egpio->chip, &dio48e_irqchip, 0,
 		handle_edge_irq, IRQ_TYPE_NONE);
@@ -359,7 +363,7 @@ static int __init dio48e_probe(struct pl
 		goto err_gpiochip_remove;
 	}
 
-	err = request_irq(irq, dio48e_irq_handler, 0, name, dio48egpio);
+	err = request_irq(irq[id], dio48e_irq_handler, 0, name, dio48egpio);
 	if (err) {
 		dev_err(dev, "IRQ handler registering failed (%d)\n", err);
 		goto err_gpiochip_remove;
@@ -372,9 +376,9 @@ err_gpiochip_remove:
 	return err;
 }
 
-static int dio48e_remove(struct platform_device *pdev)
+static int dio48e_remove(struct device *dev, unsigned int id)
 {
-	struct dio48e_gpio *const dio48egpio = platform_get_drvdata(pdev);
+	struct dio48e_gpio *const dio48egpio = dev_get_drvdata(dev);
 
 	free_irq(dio48egpio->irq, dio48egpio);
 	gpiochip_remove(&dio48egpio->chip);
@@ -382,48 +386,14 @@ static int dio48e_remove(struct platform
 	return 0;
 }
 
-static struct platform_device *dio48e_device;
-
-static struct platform_driver dio48e_driver = {
+static struct isa_driver dio48e_driver = {
+	.probe = dio48e_probe,
 	.driver = {
 		.name = "104-dio-48e"
 	},
 	.remove = dio48e_remove
 };
-
-static void __exit dio48e_exit(void)
-{
-	platform_device_unregister(dio48e_device);
-	platform_driver_unregister(&dio48e_driver);
-}
-
-static int __init dio48e_init(void)
-{
-	int err;
-
-	dio48e_device = platform_device_alloc(dio48e_driver.driver.name, -1);
-	if (!dio48e_device)
-		return -ENOMEM;
-
-	err = platform_device_add(dio48e_device);
-	if (err)
-		goto err_platform_device;
-
-	err = platform_driver_probe(&dio48e_driver, dio48e_probe);
-	if (err)
-		goto err_platform_driver;
-
-	return 0;
-
-err_platform_driver:
-	platform_device_del(dio48e_device);
-err_platform_device:
-	platform_device_put(dio48e_device);
-	return err;
-}
-
-module_init(dio48e_init);
-module_exit(dio48e_exit);
+module_isa_driver(dio48e_driver, num_dio48e);
 
 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
 MODULE_DESCRIPTION("ACCES 104-DIO-48E GPIO driver");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-104-idi-48.c linux-libre-4.7-gnu/drivers/gpio/gpio-104-idi-48.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-104-idi-48.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-104-idi-48.c	2016-07-24 15:23:50.000000000 -0400
@@ -10,6 +10,9 @@
  * 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.
+ *
+ * This driver supports the following ACCES devices: 104-IDI-48A,
+ * 104-IDI-48AC, 104-IDI-48B, and 104-IDI-48BC.
  */
 #include <linux/bitops.h>
 #include <linux/device.h>
@@ -19,18 +22,23 @@
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/irqdesc.h>
+#include <linux/isa.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/platform_device.h>
 #include <linux/spinlock.h>
 
-static unsigned idi_48_base;
-module_param(idi_48_base, uint, 0);
-MODULE_PARM_DESC(idi_48_base, "ACCES 104-IDI-48 base address");
-static unsigned idi_48_irq;
-module_param(idi_48_irq, uint, 0);
-MODULE_PARM_DESC(idi_48_irq, "ACCES 104-IDI-48 interrupt line number");
+#define IDI_48_EXTENT 8
+#define MAX_NUM_IDI_48 max_num_isa_dev(IDI_48_EXTENT)
+
+static unsigned int base[MAX_NUM_IDI_48];
+static unsigned int num_idi_48;
+module_param_array(base, uint, &num_idi_48, 0);
+MODULE_PARM_DESC(base, "ACCES 104-IDI-48 base addresses");
+
+static unsigned int irq[MAX_NUM_IDI_48];
+module_param_array(irq, uint, NULL, 0);
+MODULE_PARM_DESC(irq, "ACCES 104-IDI-48 interrupt line numbers");
 
 /**
  * struct idi_48_gpio - GPIO device private data structure
@@ -211,23 +219,19 @@ static irqreturn_t idi_48_irq_handler(in
 	return IRQ_HANDLED;
 }
 
-static int __init idi_48_probe(struct platform_device *pdev)
+static int idi_48_probe(struct device *dev, unsigned int id)
 {
-	struct device *dev = &pdev->dev;
 	struct idi_48_gpio *idi48gpio;
-	const unsigned base = idi_48_base;
-	const unsigned extent = 8;
 	const char *const name = dev_name(dev);
 	int err;
-	const unsigned irq = idi_48_irq;
 
 	idi48gpio = devm_kzalloc(dev, sizeof(*idi48gpio), GFP_KERNEL);
 	if (!idi48gpio)
 		return -ENOMEM;
 
-	if (!devm_request_region(dev, base, extent, name)) {
+	if (!devm_request_region(dev, base[id], IDI_48_EXTENT, name)) {
 		dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
-			base, base + extent);
+			base[id], base[id] + IDI_48_EXTENT);
 		return -EBUSY;
 	}
 
@@ -239,10 +243,11 @@ static int __init idi_48_probe(struct pl
 	idi48gpio->chip.get_direction = idi_48_gpio_get_direction;
 	idi48gpio->chip.direction_input = idi_48_gpio_direction_input;
 	idi48gpio->chip.get = idi_48_gpio_get;
-	idi48gpio->base = base;
-	idi48gpio->irq = irq;
+	idi48gpio->base = base[id];
+	idi48gpio->irq = irq[id];
 
 	spin_lock_init(&idi48gpio->lock);
+	spin_lock_init(&idi48gpio->ack_lock);
 
 	dev_set_drvdata(dev, idi48gpio);
 
@@ -253,8 +258,8 @@ static int __init idi_48_probe(struct pl
 	}
 
 	/* Disable IRQ by default */
-	outb(0, base + 7);
-	inb(base + 7);
+	outb(0, base[id] + 7);
+	inb(base[id] + 7);
 
 	err = gpiochip_irqchip_add(&idi48gpio->chip, &idi_48_irqchip, 0,
 		handle_edge_irq, IRQ_TYPE_NONE);
@@ -263,7 +268,7 @@ static int __init idi_48_probe(struct pl
 		goto err_gpiochip_remove;
 	}
 
-	err = request_irq(irq, idi_48_irq_handler, IRQF_SHARED, name,
+	err = request_irq(irq[id], idi_48_irq_handler, IRQF_SHARED, name,
 		idi48gpio);
 	if (err) {
 		dev_err(dev, "IRQ handler registering failed (%d)\n", err);
@@ -277,9 +282,9 @@ err_gpiochip_remove:
 	return err;
 }
 
-static int idi_48_remove(struct platform_device *pdev)
+static int idi_48_remove(struct device *dev, unsigned int id)
 {
-	struct idi_48_gpio *const idi48gpio = platform_get_drvdata(pdev);
+	struct idi_48_gpio *const idi48gpio = dev_get_drvdata(dev);
 
 	free_irq(idi48gpio->irq, idi48gpio);
 	gpiochip_remove(&idi48gpio->chip);
@@ -287,48 +292,14 @@ static int idi_48_remove(struct platform
 	return 0;
 }
 
-static struct platform_device *idi_48_device;
-
-static struct platform_driver idi_48_driver = {
+static struct isa_driver idi_48_driver = {
+	.probe = idi_48_probe,
 	.driver = {
 		.name = "104-idi-48"
 	},
 	.remove = idi_48_remove
 };
-
-static void __exit idi_48_exit(void)
-{
-	platform_device_unregister(idi_48_device);
-	platform_driver_unregister(&idi_48_driver);
-}
-
-static int __init idi_48_init(void)
-{
-	int err;
-
-	idi_48_device = platform_device_alloc(idi_48_driver.driver.name, -1);
-	if (!idi_48_device)
-		return -ENOMEM;
-
-	err = platform_device_add(idi_48_device);
-	if (err)
-		goto err_platform_device;
-
-	err = platform_driver_probe(&idi_48_driver, idi_48_probe);
-	if (err)
-		goto err_platform_driver;
-
-	return 0;
-
-err_platform_driver:
-	platform_device_del(idi_48_device);
-err_platform_device:
-	platform_device_put(idi_48_device);
-	return err;
-}
-
-module_init(idi_48_init);
-module_exit(idi_48_exit);
+module_isa_driver(idi_48_driver, num_idi_48);
 
 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
 MODULE_DESCRIPTION("ACCES 104-IDI-48 GPIO driver");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-104-idio-16.c linux-libre-4.7-gnu/drivers/gpio/gpio-104-idio-16.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-104-idio-16.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-104-idio-16.c	2016-07-24 15:23:50.000000000 -0400
@@ -10,6 +10,9 @@
  * 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.
+ *
+ * This driver supports the following ACCES devices: 104-IDIO-16,
+ * 104-IDIO-16E, 104-IDO-16, 104-IDIO-8, 104-IDIO-8E, and 104-IDO-8.
  */
 #include <linux/bitops.h>
 #include <linux/device.h>
@@ -19,18 +22,23 @@
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/irqdesc.h>
+#include <linux/isa.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/platform_device.h>
 #include <linux/spinlock.h>
 
-static unsigned idio_16_base;
-module_param(idio_16_base, uint, 0);
-MODULE_PARM_DESC(idio_16_base, "ACCES 104-IDIO-16 base address");
-static unsigned idio_16_irq;
-module_param(idio_16_irq, uint, 0);
-MODULE_PARM_DESC(idio_16_irq, "ACCES 104-IDIO-16 interrupt line number");
+#define IDIO_16_EXTENT 8
+#define MAX_NUM_IDIO_16 max_num_isa_dev(IDIO_16_EXTENT)
+
+static unsigned int base[MAX_NUM_IDIO_16];
+static unsigned int num_idio_16;
+module_param_array(base, uint, &num_idio_16, 0);
+MODULE_PARM_DESC(base, "ACCES 104-IDIO-16 base addresses");
+
+static unsigned int irq[MAX_NUM_IDIO_16];
+module_param_array(irq, uint, NULL, 0);
+MODULE_PARM_DESC(irq, "ACCES 104-IDIO-16 interrupt line numbers");
 
 /**
  * struct idio_16_gpio - GPIO device private data structure
@@ -185,23 +193,19 @@ static irqreturn_t idio_16_irq_handler(i
 	return IRQ_HANDLED;
 }
 
-static int __init idio_16_probe(struct platform_device *pdev)
+static int idio_16_probe(struct device *dev, unsigned int id)
 {
-	struct device *dev = &pdev->dev;
 	struct idio_16_gpio *idio16gpio;
-	const unsigned base = idio_16_base;
-	const unsigned extent = 8;
 	const char *const name = dev_name(dev);
 	int err;
-	const unsigned irq = idio_16_irq;
 
 	idio16gpio = devm_kzalloc(dev, sizeof(*idio16gpio), GFP_KERNEL);
 	if (!idio16gpio)
 		return -ENOMEM;
 
-	if (!devm_request_region(dev, base, extent, name)) {
+	if (!devm_request_region(dev, base[id], IDIO_16_EXTENT, name)) {
 		dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
-			base, base + extent);
+			base[id], base[id] + IDIO_16_EXTENT);
 		return -EBUSY;
 	}
 
@@ -215,8 +219,8 @@ static int __init idio_16_probe(struct p
 	idio16gpio->chip.direction_output = idio_16_gpio_direction_output;
 	idio16gpio->chip.get = idio_16_gpio_get;
 	idio16gpio->chip.set = idio_16_gpio_set;
-	idio16gpio->base = base;
-	idio16gpio->irq = irq;
+	idio16gpio->base = base[id];
+	idio16gpio->irq = irq[id];
 	idio16gpio->out_state = 0xFFFF;
 
 	spin_lock_init(&idio16gpio->lock);
@@ -230,8 +234,8 @@ static int __init idio_16_probe(struct p
 	}
 
 	/* Disable IRQ by default */
-	outb(0, base + 2);
-	outb(0, base + 1);
+	outb(0, base[id] + 2);
+	outb(0, base[id] + 1);
 
 	err = gpiochip_irqchip_add(&idio16gpio->chip, &idio_16_irqchip, 0,
 		handle_edge_irq, IRQ_TYPE_NONE);
@@ -240,7 +244,7 @@ static int __init idio_16_probe(struct p
 		goto err_gpiochip_remove;
 	}
 
-	err = request_irq(irq, idio_16_irq_handler, 0, name, idio16gpio);
+	err = request_irq(irq[id], idio_16_irq_handler, 0, name, idio16gpio);
 	if (err) {
 		dev_err(dev, "IRQ handler registering failed (%d)\n", err);
 		goto err_gpiochip_remove;
@@ -253,9 +257,9 @@ err_gpiochip_remove:
 	return err;
 }
 
-static int idio_16_remove(struct platform_device *pdev)
+static int idio_16_remove(struct device *dev, unsigned int id)
 {
-	struct idio_16_gpio *const idio16gpio = platform_get_drvdata(pdev);
+	struct idio_16_gpio *const idio16gpio = dev_get_drvdata(dev);
 
 	free_irq(idio16gpio->irq, idio16gpio);
 	gpiochip_remove(&idio16gpio->chip);
@@ -263,48 +267,15 @@ static int idio_16_remove(struct platfor
 	return 0;
 }
 
-static struct platform_device *idio_16_device;
-
-static struct platform_driver idio_16_driver = {
+static struct isa_driver idio_16_driver = {
+	.probe = idio_16_probe,
 	.driver = {
 		.name = "104-idio-16"
 	},
 	.remove = idio_16_remove
 };
 
-static void __exit idio_16_exit(void)
-{
-	platform_device_unregister(idio_16_device);
-	platform_driver_unregister(&idio_16_driver);
-}
-
-static int __init idio_16_init(void)
-{
-	int err;
-
-	idio_16_device = platform_device_alloc(idio_16_driver.driver.name, -1);
-	if (!idio_16_device)
-		return -ENOMEM;
-
-	err = platform_device_add(idio_16_device);
-	if (err)
-		goto err_platform_device;
-
-	err = platform_driver_probe(&idio_16_driver, idio_16_probe);
-	if (err)
-		goto err_platform_driver;
-
-	return 0;
-
-err_platform_driver:
-	platform_device_del(idio_16_device);
-err_platform_device:
-	platform_device_put(idio_16_device);
-	return err;
-}
-
-module_init(idio_16_init);
-module_exit(idio_16_exit);
+module_isa_driver(idio_16_driver, num_idio_16);
 
 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
 MODULE_DESCRIPTION("ACCES 104-IDIO-16 GPIO driver");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-74x164.c linux-libre-4.7-gnu/drivers/gpio/gpio-74x164.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-74x164.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-74x164.c	2016-07-24 15:23:50.000000000 -0400
@@ -75,6 +75,29 @@ static void gen_74x164_set_value(struct
 	mutex_unlock(&chip->lock);
 }
 
+static void gen_74x164_set_multiple(struct gpio_chip *gc, unsigned long *mask,
+				    unsigned long *bits)
+{
+	struct gen_74x164_chip *chip = gpiochip_get_data(gc);
+	unsigned int i, idx, shift;
+	u8 bank, bankmask;
+
+	mutex_lock(&chip->lock);
+	for (i = 0, bank = chip->registers - 1; i < chip->registers;
+	     i++, bank--) {
+		idx = i / sizeof(*mask);
+		shift = i % sizeof(*mask) * BITS_PER_BYTE;
+		bankmask = mask[idx] >> shift;
+		if (!bankmask)
+			continue;
+
+		chip->buffer[bank] &= ~bankmask;
+		chip->buffer[bank] |= bankmask & (bits[idx] >> shift);
+	}
+	__gen_74x164_write_config(chip);
+	mutex_unlock(&chip->lock);
+}
+
 static int gen_74x164_direction_output(struct gpio_chip *gc,
 		unsigned offset, int val)
 {
@@ -114,6 +137,7 @@ static int gen_74x164_probe(struct spi_d
 	chip->gpio_chip.direction_output = gen_74x164_direction_output;
 	chip->gpio_chip.get = gen_74x164_get_value;
 	chip->gpio_chip.set = gen_74x164_set_value;
+	chip->gpio_chip.set_multiple = gen_74x164_set_multiple;
 	chip->gpio_chip.base = -1;
 
 	chip->registers = nregs;
@@ -153,6 +177,7 @@ static int gen_74x164_remove(struct spi_
 
 static const struct of_device_id gen_74x164_dt_ids[] = {
 	{ .compatible = "fairchild,74hc595" },
+	{ .compatible = "nxp,74lvc594" },
 	{},
 };
 MODULE_DEVICE_TABLE(of, gen_74x164_dt_ids);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-amdpt.c linux-libre-4.7-gnu/drivers/gpio/gpio-amdpt.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-amdpt.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-amdpt.c	2016-07-24 15:23:50.000000000 -0400
@@ -28,7 +28,6 @@
 struct pt_gpio_chip {
 	struct gpio_chip         gc;
 	void __iomem             *reg_base;
-	spinlock_t               lock;
 };
 
 static int pt_gpio_request(struct gpio_chip *gc, unsigned offset)
@@ -39,19 +38,19 @@ static int pt_gpio_request(struct gpio_c
 
 	dev_dbg(gc->parent, "pt_gpio_request offset=%x\n", offset);
 
-	spin_lock_irqsave(&pt_gpio->lock, flags);
+	spin_lock_irqsave(&gc->bgpio_lock, flags);
 
 	using_pins = readl(pt_gpio->reg_base + PT_SYNC_REG);
 	if (using_pins & BIT(offset)) {
 		dev_warn(gc->parent, "PT GPIO pin %x reconfigured\n",
 			 offset);
-		spin_unlock_irqrestore(&pt_gpio->lock, flags);
+		spin_unlock_irqrestore(&gc->bgpio_lock, flags);
 		return -EINVAL;
 	}
 
 	writel(using_pins | BIT(offset), pt_gpio->reg_base + PT_SYNC_REG);
 
-	spin_unlock_irqrestore(&pt_gpio->lock, flags);
+	spin_unlock_irqrestore(&gc->bgpio_lock, flags);
 
 	return 0;
 }
@@ -62,111 +61,17 @@ static void pt_gpio_free(struct gpio_chi
 	unsigned long flags;
 	u32 using_pins;
 
-	spin_lock_irqsave(&pt_gpio->lock, flags);
+	spin_lock_irqsave(&gc->bgpio_lock, flags);
 
 	using_pins = readl(pt_gpio->reg_base + PT_SYNC_REG);
 	using_pins &= ~BIT(offset);
 	writel(using_pins, pt_gpio->reg_base + PT_SYNC_REG);
 
-	spin_unlock_irqrestore(&pt_gpio->lock, flags);
+	spin_unlock_irqrestore(&gc->bgpio_lock, flags);
 
 	dev_dbg(gc->parent, "pt_gpio_free offset=%x\n", offset);
 }
 
-static void pt_gpio_set_value(struct gpio_chip *gc, unsigned offset, int value)
-{
-	struct pt_gpio_chip *pt_gpio = gpiochip_get_data(gc);
-	unsigned long flags;
-	u32 data;
-
-	dev_dbg(gc->parent, "pt_gpio_set_value offset=%x, value=%x\n",
-		offset, value);
-
-	spin_lock_irqsave(&pt_gpio->lock, flags);
-
-	data = readl(pt_gpio->reg_base + PT_OUTPUTDATA_REG);
-	data &= ~BIT(offset);
-	if (value)
-		data |= BIT(offset);
-	writel(data, pt_gpio->reg_base + PT_OUTPUTDATA_REG);
-
-	spin_unlock_irqrestore(&pt_gpio->lock, flags);
-}
-
-static int pt_gpio_get_value(struct gpio_chip *gc, unsigned offset)
-{
-	struct pt_gpio_chip *pt_gpio = gpiochip_get_data(gc);
-	unsigned long flags;
-	u32 data;
-
-	spin_lock_irqsave(&pt_gpio->lock, flags);
-
-	data = readl(pt_gpio->reg_base + PT_DIRECTION_REG);
-
-	/* configure as output */
-	if (data & BIT(offset))
-		data = readl(pt_gpio->reg_base + PT_OUTPUTDATA_REG);
-	else	/* configure as input */
-		data = readl(pt_gpio->reg_base + PT_INPUTDATA_REG);
-
-	spin_unlock_irqrestore(&pt_gpio->lock, flags);
-
-	data >>= offset;
-	data &= 1;
-
-	dev_dbg(gc->parent, "pt_gpio_get_value offset=%x, value=%x\n",
-		offset, data);
-
-	return data;
-}
-
-static int pt_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
-{
-	struct pt_gpio_chip *pt_gpio = gpiochip_get_data(gc);
-	unsigned long flags;
-	u32 data;
-
-	dev_dbg(gc->parent, "pt_gpio_dirction_input offset=%x\n", offset);
-
-	spin_lock_irqsave(&pt_gpio->lock, flags);
-
-	data = readl(pt_gpio->reg_base + PT_DIRECTION_REG);
-	data &= ~BIT(offset);
-	writel(data, pt_gpio->reg_base + PT_DIRECTION_REG);
-
-	spin_unlock_irqrestore(&pt_gpio->lock, flags);
-
-	return 0;
-}
-
-static int pt_gpio_direction_output(struct gpio_chip *gc,
-					unsigned offset, int value)
-{
-	struct pt_gpio_chip *pt_gpio = gpiochip_get_data(gc);
-	unsigned long flags;
-	u32 data;
-
-	dev_dbg(gc->parent, "pt_gpio_direction_output offset=%x, value=%x\n",
-		offset, value);
-
-	spin_lock_irqsave(&pt_gpio->lock, flags);
-
-	data = readl(pt_gpio->reg_base + PT_OUTPUTDATA_REG);
-	if (value)
-		data |= BIT(offset);
-	else
-		data &= ~BIT(offset);
-	writel(data, pt_gpio->reg_base + PT_OUTPUTDATA_REG);
-
-	data = readl(pt_gpio->reg_base + PT_DIRECTION_REG);
-	data |= BIT(offset);
-	writel(data, pt_gpio->reg_base + PT_DIRECTION_REG);
-
-	spin_unlock_irqrestore(&pt_gpio->lock, flags);
-
-	return 0;
-}
-
 static int pt_gpio_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -196,18 +101,19 @@ static int pt_gpio_probe(struct platform
 		return PTR_ERR(pt_gpio->reg_base);
 	}
 
-	spin_lock_init(&pt_gpio->lock);
+	ret = bgpio_init(&pt_gpio->gc, dev, 4,
+			 pt_gpio->reg_base + PT_INPUTDATA_REG,
+			 pt_gpio->reg_base + PT_OUTPUTDATA_REG, NULL,
+			 pt_gpio->reg_base + PT_DIRECTION_REG, NULL,
+			 BGPIOF_READ_OUTPUT_REG_SET);
+	if (ret) {
+		dev_err(&pdev->dev, "bgpio_init failed\n");
+		return ret;
+	}
 
-	pt_gpio->gc.label            = pdev->name;
 	pt_gpio->gc.owner            = THIS_MODULE;
-	pt_gpio->gc.parent              = dev;
 	pt_gpio->gc.request          = pt_gpio_request;
 	pt_gpio->gc.free             = pt_gpio_free;
-	pt_gpio->gc.direction_input  = pt_gpio_direction_input;
-	pt_gpio->gc.direction_output = pt_gpio_direction_output;
-	pt_gpio->gc.get              = pt_gpio_get_value;
-	pt_gpio->gc.set              = pt_gpio_set_value;
-	pt_gpio->gc.base             = -1;
 	pt_gpio->gc.ngpio            = PT_TOTAL_GPIO;
 #if defined(CONFIG_OF_GPIO)
 	pt_gpio->gc.of_node          = pdev->dev.of_node;
@@ -239,6 +145,7 @@ static int pt_gpio_remove(struct platfor
 
 static const struct acpi_device_id pt_gpio_acpi_match[] = {
 	{ "AMDF030", 0 },
+	{ "AMDIF030", 0 },
 	{ },
 };
 MODULE_DEVICE_TABLE(acpi, pt_gpio_acpi_match);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-bcm-kona.c linux-libre-4.7-gnu/drivers/gpio/gpio-bcm-kona.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-bcm-kona.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-bcm-kona.c	2016-07-24 15:23:50.000000000 -0400
@@ -1,4 +1,7 @@
 /*
+ * Broadcom Kona GPIO Driver
+ *
+ * Author: Broadcom Corporation <bcm-kernel-feedback-list@broadcom.com>
  * Copyright (C) 2012-2014 Broadcom Corporation
  *
  * This program is free software; you can redistribute it and/or
@@ -17,7 +20,7 @@
 #include <linux/gpio.h>
 #include <linux/of_device.h>
 #include <linux/of_irq.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/irqdomain.h>
 #include <linux/irqchip/chained_irq.h>
 
@@ -502,8 +505,6 @@ static struct of_device_id const bcm_kon
 	{}
 };
 
-MODULE_DEVICE_TABLE(of, bcm_kona_gpio_of_match);
-
 /*
  * This lock class tells lockdep that GPIO irqs are in a different
  * category than their parents, so it won't report false recursion.
@@ -546,11 +547,11 @@ static void bcm_kona_gpio_reset(struct b
 	/* disable interrupts and clear status */
 	for (i = 0; i < kona_gpio->num_bank; i++) {
 		/* Unlock the entire bank first */
-		bcm_kona_gpio_write_lock_regs(kona_gpio, i, UNLOCK_CODE);
+		bcm_kona_gpio_write_lock_regs(reg_base, i, UNLOCK_CODE);
 		writel(0xffffffff, reg_base + GPIO_INT_MASK(i));
 		writel(0xffffffff, reg_base + GPIO_INT_STATUS(i));
 		/* Now re-lock the bank */
-		bcm_kona_gpio_write_lock_regs(kona_gpio, i, LOCK_CODE);
+		bcm_kona_gpio_write_lock_regs(reg_base, i, LOCK_CODE);
 	}
 }
 
@@ -659,9 +660,4 @@ static struct platform_driver bcm_kona_g
 	},
 	.probe = bcm_kona_gpio_probe,
 };
-
-module_platform_driver(bcm_kona_gpio_driver);
-
-MODULE_AUTHOR("Broadcom Corporation <bcm-kernel-feedback-list@broadcom.com>");
-MODULE_DESCRIPTION("Broadcom Kona GPIO Driver");
-MODULE_LICENSE("GPL v2");
+builtin_platform_driver(bcm_kona_gpio_driver);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-brcmstb.c linux-libre-4.7-gnu/drivers/gpio/gpio-brcmstb.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-brcmstb.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-brcmstb.c	2016-07-24 15:23:50.000000000 -0400
@@ -461,6 +461,7 @@ static int brcmstb_gpio_probe(struct pla
 		bank->id = num_banks;
 		if (bank_width <= 0 || bank_width > MAX_GPIO_PER_BANK) {
 			dev_err(dev, "Invalid bank width %d\n", bank_width);
+			err = -EINVAL;
 			goto fail;
 		} else {
 			bank->width = bank_width;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-dwapb.c linux-libre-4.7-gnu/drivers/gpio/gpio-dwapb.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-dwapb.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-dwapb.c	2016-07-24 15:23:50.000000000 -0400
@@ -7,6 +7,7 @@
  *
  * All enquiries to support@picochip.com
  */
+#include <linux/acpi.h>
 #include <linux/gpio/driver.h>
 /* FIXME: for gpio_get_value(), replace this with direct register read */
 #include <linux/gpio.h>
@@ -22,10 +23,13 @@
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/platform_device.h>
+#include <linux/property.h>
 #include <linux/spinlock.h>
 #include <linux/platform_data/gpio-dwapb.h>
 #include <linux/slab.h>
 
+#include "gpiolib.h"
+
 #define GPIO_SWPORTA_DR		0x00
 #define GPIO_SWPORTA_DDR	0x04
 #define GPIO_SWPORTB_DR		0x0c
@@ -290,14 +294,14 @@ static void dwapb_configure_irqs(struct
 				 struct dwapb_port_property *pp)
 {
 	struct gpio_chip *gc = &port->gc;
-	struct device_node *node = pp->node;
+	struct fwnode_handle  *fwnode = pp->fwnode;
 	struct irq_chip_generic	*irq_gc = NULL;
 	unsigned int hwirq, ngpio = gc->ngpio;
 	struct irq_chip_type *ct;
 	int err, i;
 
-	gpio->domain = irq_domain_add_linear(node, ngpio,
-					     &irq_generic_chip_ops, gpio);
+	gpio->domain = irq_domain_create_linear(fwnode, ngpio,
+						 &irq_generic_chip_ops, gpio);
 	if (!gpio->domain)
 		return;
 
@@ -409,13 +413,13 @@ static int dwapb_gpio_add_port(struct dw
 	err = bgpio_init(&port->gc, gpio->dev, 4, dat, set, NULL, dirout,
 			 NULL, false);
 	if (err) {
-		dev_err(gpio->dev, "failed to init gpio chip for %s\n",
-			pp->name);
+		dev_err(gpio->dev, "failed to init gpio chip for port%d\n",
+			port->idx);
 		return err;
 	}
 
 #ifdef CONFIG_OF_GPIO
-	port->gc.of_node = pp->node;
+	port->gc.of_node = to_of_node(pp->fwnode);
 #endif
 	port->gc.ngpio = pp->ngpio;
 	port->gc.base = pp->gpio_base;
@@ -429,11 +433,15 @@ static int dwapb_gpio_add_port(struct dw
 
 	err = gpiochip_add_data(&port->gc, port);
 	if (err)
-		dev_err(gpio->dev, "failed to register gpiochip for %s\n",
-			pp->name);
+		dev_err(gpio->dev, "failed to register gpiochip for port%d\n",
+			port->idx);
 	else
 		port->is_registered = true;
 
+	/* Add GPIO-signaled ACPI event support */
+	if (pp->irq)
+		acpi_gpiochip_request_interrupts(&port->gc);
+
 	return err;
 }
 
@@ -447,19 +455,15 @@ static void dwapb_gpio_unregister(struct
 }
 
 static struct dwapb_platform_data *
-dwapb_gpio_get_pdata_of(struct device *dev)
+dwapb_gpio_get_pdata(struct device *dev)
 {
-	struct device_node *node, *port_np;
+	struct fwnode_handle *fwnode;
 	struct dwapb_platform_data *pdata;
 	struct dwapb_port_property *pp;
 	int nports;
 	int i;
 
-	node = dev->of_node;
-	if (!IS_ENABLED(CONFIG_OF_GPIO) || !node)
-		return ERR_PTR(-ENODEV);
-
-	nports = of_get_child_count(node);
+	nports = device_get_child_node_count(dev);
 	if (nports == 0)
 		return ERR_PTR(-ENODEV);
 
@@ -474,21 +478,22 @@ dwapb_gpio_get_pdata_of(struct device *d
 	pdata->nports = nports;
 
 	i = 0;
-	for_each_child_of_node(node, port_np) {
+	device_for_each_child_node(dev, fwnode)  {
 		pp = &pdata->properties[i++];
-		pp->node = port_np;
+		pp->fwnode = fwnode;
 
-		if (of_property_read_u32(port_np, "reg", &pp->idx) ||
+		if (fwnode_property_read_u32(fwnode, "reg", &pp->idx) ||
 		    pp->idx >= DWAPB_MAX_PORTS) {
-			dev_err(dev, "missing/invalid port index for %s\n",
-				port_np->full_name);
+			dev_err(dev,
+				"missing/invalid port index for port%d\n", i);
 			return ERR_PTR(-EINVAL);
 		}
 
-		if (of_property_read_u32(port_np, "snps,nr-gpios",
+		if (fwnode_property_read_u32(fwnode, "snps,nr-gpios",
 					 &pp->ngpio)) {
-			dev_info(dev, "failed to get number of gpios for %s\n",
-				 port_np->full_name);
+			dev_info(dev,
+				 "failed to get number of gpios for port%d\n",
+				 i);
 			pp->ngpio = 32;
 		}
 
@@ -496,18 +501,19 @@ dwapb_gpio_get_pdata_of(struct device *d
 		 * Only port A can provide interrupts in all configurations of
 		 * the IP.
 		 */
-		if (pp->idx == 0 &&
-		    of_property_read_bool(port_np, "interrupt-controller")) {
-			pp->irq = irq_of_parse_and_map(port_np, 0);
-			if (!pp->irq) {
-				dev_warn(dev, "no irq for bank %s\n",
-					 port_np->full_name);
-			}
+		if (dev->of_node && pp->idx == 0 &&
+			fwnode_property_read_bool(fwnode,
+						  "interrupt-controller")) {
+			pp->irq = irq_of_parse_and_map(to_of_node(fwnode), 0);
+			if (!pp->irq)
+				dev_warn(dev, "no irq for port%d\n", pp->idx);
 		}
 
+		if (has_acpi_companion(dev) && pp->idx == 0)
+			pp->irq = platform_get_irq(to_platform_device(dev), 0);
+
 		pp->irq_shared	= false;
 		pp->gpio_base	= -1;
-		pp->name	= port_np->full_name;
 	}
 
 	return pdata;
@@ -523,7 +529,7 @@ static int dwapb_gpio_probe(struct platf
 	struct dwapb_platform_data *pdata = dev_get_platdata(dev);
 
 	if (!pdata) {
-		pdata = dwapb_gpio_get_pdata_of(dev);
+		pdata = dwapb_gpio_get_pdata(dev);
 		if (IS_ERR(pdata))
 			return PTR_ERR(pdata);
 	}
@@ -580,6 +586,13 @@ static const struct of_device_id dwapb_o
 };
 MODULE_DEVICE_TABLE(of, dwapb_of_match);
 
+static const struct acpi_device_id dwapb_acpi_match[] = {
+	{"HISI0181", 0},
+	{"APMC0D07", 0},
+	{ }
+};
+MODULE_DEVICE_TABLE(acpi, dwapb_acpi_match);
+
 #ifdef CONFIG_PM_SLEEP
 static int dwapb_gpio_suspend(struct device *dev)
 {
@@ -674,6 +687,7 @@ static struct platform_driver dwapb_gpio
 		.name	= "gpio-dwapb",
 		.pm	= &dwapb_gpio_pm_ops,
 		.of_match_table = of_match_ptr(dwapb_of_match),
+		.acpi_match_table = ACPI_PTR(dwapb_acpi_match),
 	},
 	.probe		= dwapb_gpio_probe,
 	.remove		= dwapb_gpio_remove,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-f7188x.c linux-libre-4.7-gnu/drivers/gpio/gpio-f7188x.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-f7188x.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-f7188x.c	2016-07-24 15:23:50.000000000 -0400
@@ -15,7 +15,8 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
+#include <linux/bitops.h>
 
 #define DRVNAME "gpio-f7188x"
 
@@ -129,6 +130,9 @@ static int f7188x_gpio_get(struct gpio_c
 static int f7188x_gpio_direction_out(struct gpio_chip *chip,
 				     unsigned offset, int value);
 static void f7188x_gpio_set(struct gpio_chip *chip, unsigned offset, int value);
+static int f7188x_gpio_set_single_ended(struct gpio_chip *gc,
+					unsigned offset,
+					enum single_ended_mode mode);
 
 #define F7188X_GPIO_BANK(_base, _ngpio, _regbase)			\
 	{								\
@@ -139,6 +143,7 @@ static void f7188x_gpio_set(struct gpio_
 			.get              = f7188x_gpio_get,		\
 			.direction_output = f7188x_gpio_direction_out,	\
 			.set              = f7188x_gpio_set,		\
+			.set_single_ended = f7188x_gpio_set_single_ended, \
 			.base             = _base,			\
 			.ngpio            = _ngpio,			\
 			.can_sleep        = true,			\
@@ -217,7 +222,7 @@ static int f7188x_gpio_direction_in(stru
 	superio_select(sio->addr, SIO_LD_GPIO);
 
 	dir = superio_inb(sio->addr, gpio_dir(bank->regbase));
-	dir &= ~(1 << offset);
+	dir &= ~BIT(offset);
 	superio_outb(sio->addr, gpio_dir(bank->regbase), dir);
 
 	superio_exit(sio->addr);
@@ -238,7 +243,7 @@ static int f7188x_gpio_get(struct gpio_c
 	superio_select(sio->addr, SIO_LD_GPIO);
 
 	dir = superio_inb(sio->addr, gpio_dir(bank->regbase));
-	dir = !!(dir & (1 << offset));
+	dir = !!(dir & BIT(offset));
 	if (dir)
 		data = superio_inb(sio->addr, gpio_data_out(bank->regbase));
 	else
@@ -246,7 +251,7 @@ static int f7188x_gpio_get(struct gpio_c
 
 	superio_exit(sio->addr);
 
-	return !!(data & 1 << offset);
+	return !!(data & BIT(offset));
 }
 
 static int f7188x_gpio_direction_out(struct gpio_chip *chip,
@@ -264,13 +269,13 @@ static int f7188x_gpio_direction_out(str
 
 	data_out = superio_inb(sio->addr, gpio_data_out(bank->regbase));
 	if (value)
-		data_out |= (1 << offset);
+		data_out |= BIT(offset);
 	else
-		data_out &= ~(1 << offset);
+		data_out &= ~BIT(offset);
 	superio_outb(sio->addr, gpio_data_out(bank->regbase), data_out);
 
 	dir = superio_inb(sio->addr, gpio_dir(bank->regbase));
-	dir |= (1 << offset);
+	dir |= BIT(offset);
 	superio_outb(sio->addr, gpio_dir(bank->regbase), dir);
 
 	superio_exit(sio->addr);
@@ -292,14 +297,43 @@ static void f7188x_gpio_set(struct gpio_
 
 	data_out = superio_inb(sio->addr, gpio_data_out(bank->regbase));
 	if (value)
-		data_out |= (1 << offset);
+		data_out |= BIT(offset);
 	else
-		data_out &= ~(1 << offset);
+		data_out &= ~BIT(offset);
 	superio_outb(sio->addr, gpio_data_out(bank->regbase), data_out);
 
 	superio_exit(sio->addr);
 }
 
+static int f7188x_gpio_set_single_ended(struct gpio_chip *chip,
+					unsigned offset,
+					enum single_ended_mode mode)
+{
+	int err;
+	struct f7188x_gpio_bank *bank = gpiochip_get_data(chip);
+	struct f7188x_sio *sio = bank->data->sio;
+	u8 data;
+
+	if (mode != LINE_MODE_OPEN_DRAIN &&
+	    mode != LINE_MODE_PUSH_PULL)
+		return -ENOTSUPP;
+
+	err = superio_enter(sio->addr);
+	if (err)
+		return err;
+	superio_select(sio->addr, SIO_LD_GPIO);
+
+	data = superio_inb(sio->addr, gpio_out_mode(bank->regbase));
+	if (mode == LINE_MODE_OPEN_DRAIN)
+		data &= ~BIT(offset);
+	else
+		data |= BIT(offset);
+	superio_outb(sio->addr, gpio_out_mode(bank->regbase), data);
+
+	superio_exit(sio->addr);
+	return 0;
+}
+
 /*
  * Platform device and driver.
  */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-generic.c linux-libre-4.7-gnu/drivers/gpio/gpio-generic.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-generic.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-generic.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,660 +0,0 @@
-/*
- * Generic driver for memory-mapped GPIO controllers.
- *
- * Copyright 2008 MontaVista Software, Inc.
- * Copyright 2008,2010 Anton Vorontsov <cbouatmailru@gmail.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- * ....``.```~~~~````.`.`.`.`.```````'',,,.........`````......`.......
- * ...``                                                         ```````..
- * ..The simplest form of a GPIO controller that the driver supports is``
- *  `.just a single "data" register, where GPIO state can be read and/or `
- *    `,..written. ,,..``~~~~ .....``.`.`.~~.```.`.........``````.```````
- *        `````````
-                                    ___
-_/~~|___/~|   . ```~~~~~~       ___/___\___     ,~.`.`.`.`````.~~...,,,,...
-__________|~$@~~~        %~    /o*o*o*o*o*o\   .. Implementing such a GPIO .
-o        `                     ~~~~\___/~~~~    ` controller in FPGA is ,.`
-                                                 `....trivial..'~`.```.```
- *                                                    ```````
- *  .```````~~~~`..`.``.``.
- * .  The driver supports  `...       ,..```.`~~~```````````````....````.``,,
- * .   big-endian notation, just`.  .. A bit more sophisticated controllers ,
- *  . register the device with -be`. .with a pair of set/clear-bit registers ,
- *   `.. suffix.  ```~~`````....`.`   . affecting the data register and the .`
- *     ``.`.``...```                  ```.. output pins are also supported.`
- *                        ^^             `````.`````````.,``~``~``~~``````
- *                                                   .                  ^^
- *   ,..`.`.`...````````````......`.`.`.`.`.`..`.`.`..
- * .. The expectation is that in at least some cases .    ,-~~~-,
- *  .this will be used with roll-your-own ASIC/FPGA .`     \   /
- *  .logic in Verilog or VHDL. ~~~`````````..`````~~`       \ /
- *  ..````````......```````````                             \o_
- *                                                           |
- *                              ^^                          / \
- *
- *           ...`````~~`.....``.`..........``````.`.``.```........``.
- *            `  8, 16, 32 and 64 bits registers are supported, and``.
- *            . the number of GPIOs is determined by the width of   ~
- *             .. the registers. ,............```.`.`..`.`.~~~.`.`.`~
- *               `.......````.```
- */
-
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/bug.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <linux/compiler.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/log2.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-#include <linux/gpio/driver.h>
-#include <linux/slab.h>
-#include <linux/bitops.h>
-#include <linux/platform_device.h>
-#include <linux/mod_devicetable.h>
-
-static void bgpio_write8(void __iomem *reg, unsigned long data)
-{
-	writeb(data, reg);
-}
-
-static unsigned long bgpio_read8(void __iomem *reg)
-{
-	return readb(reg);
-}
-
-static void bgpio_write16(void __iomem *reg, unsigned long data)
-{
-	writew(data, reg);
-}
-
-static unsigned long bgpio_read16(void __iomem *reg)
-{
-	return readw(reg);
-}
-
-static void bgpio_write32(void __iomem *reg, unsigned long data)
-{
-	writel(data, reg);
-}
-
-static unsigned long bgpio_read32(void __iomem *reg)
-{
-	return readl(reg);
-}
-
-#if BITS_PER_LONG >= 64
-static void bgpio_write64(void __iomem *reg, unsigned long data)
-{
-	writeq(data, reg);
-}
-
-static unsigned long bgpio_read64(void __iomem *reg)
-{
-	return readq(reg);
-}
-#endif /* BITS_PER_LONG >= 64 */
-
-static void bgpio_write16be(void __iomem *reg, unsigned long data)
-{
-	iowrite16be(data, reg);
-}
-
-static unsigned long bgpio_read16be(void __iomem *reg)
-{
-	return ioread16be(reg);
-}
-
-static void bgpio_write32be(void __iomem *reg, unsigned long data)
-{
-	iowrite32be(data, reg);
-}
-
-static unsigned long bgpio_read32be(void __iomem *reg)
-{
-	return ioread32be(reg);
-}
-
-static unsigned long bgpio_pin2mask(struct gpio_chip *gc, unsigned int pin)
-{
-	return BIT(pin);
-}
-
-static unsigned long bgpio_pin2mask_be(struct gpio_chip *gc,
-				       unsigned int pin)
-{
-	return BIT(gc->bgpio_bits - 1 - pin);
-}
-
-static int bgpio_get_set(struct gpio_chip *gc, unsigned int gpio)
-{
-	unsigned long pinmask = gc->pin2mask(gc, gpio);
-
-	if (gc->bgpio_dir & pinmask)
-		return !!(gc->read_reg(gc->reg_set) & pinmask);
-	else
-		return !!(gc->read_reg(gc->reg_dat) & pinmask);
-}
-
-static int bgpio_get(struct gpio_chip *gc, unsigned int gpio)
-{
-	return !!(gc->read_reg(gc->reg_dat) & gc->pin2mask(gc, gpio));
-}
-
-static void bgpio_set_none(struct gpio_chip *gc, unsigned int gpio, int val)
-{
-}
-
-static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
-{
-	unsigned long mask = gc->pin2mask(gc, gpio);
-	unsigned long flags;
-
-	spin_lock_irqsave(&gc->bgpio_lock, flags);
-
-	if (val)
-		gc->bgpio_data |= mask;
-	else
-		gc->bgpio_data &= ~mask;
-
-	gc->write_reg(gc->reg_dat, gc->bgpio_data);
-
-	spin_unlock_irqrestore(&gc->bgpio_lock, flags);
-}
-
-static void bgpio_set_with_clear(struct gpio_chip *gc, unsigned int gpio,
-				 int val)
-{
-	unsigned long mask = gc->pin2mask(gc, gpio);
-
-	if (val)
-		gc->write_reg(gc->reg_set, mask);
-	else
-		gc->write_reg(gc->reg_clr, mask);
-}
-
-static void bgpio_set_set(struct gpio_chip *gc, unsigned int gpio, int val)
-{
-	unsigned long mask = gc->pin2mask(gc, gpio);
-	unsigned long flags;
-
-	spin_lock_irqsave(&gc->bgpio_lock, flags);
-
-	if (val)
-		gc->bgpio_data |= mask;
-	else
-		gc->bgpio_data &= ~mask;
-
-	gc->write_reg(gc->reg_set, gc->bgpio_data);
-
-	spin_unlock_irqrestore(&gc->bgpio_lock, flags);
-}
-
-static void bgpio_multiple_get_masks(struct gpio_chip *gc,
-				     unsigned long *mask, unsigned long *bits,
-				     unsigned long *set_mask,
-				     unsigned long *clear_mask)
-{
-	int i;
-
-	*set_mask = 0;
-	*clear_mask = 0;
-
-	for (i = 0; i < gc->bgpio_bits; i++) {
-		if (*mask == 0)
-			break;
-		if (__test_and_clear_bit(i, mask)) {
-			if (test_bit(i, bits))
-				*set_mask |= gc->pin2mask(gc, i);
-			else
-				*clear_mask |= gc->pin2mask(gc, i);
-		}
-	}
-}
-
-static void bgpio_set_multiple_single_reg(struct gpio_chip *gc,
-					  unsigned long *mask,
-					  unsigned long *bits,
-					  void __iomem *reg)
-{
-	unsigned long flags;
-	unsigned long set_mask, clear_mask;
-
-	spin_lock_irqsave(&gc->bgpio_lock, flags);
-
-	bgpio_multiple_get_masks(gc, mask, bits, &set_mask, &clear_mask);
-
-	gc->bgpio_data |= set_mask;
-	gc->bgpio_data &= ~clear_mask;
-
-	gc->write_reg(reg, gc->bgpio_data);
-
-	spin_unlock_irqrestore(&gc->bgpio_lock, flags);
-}
-
-static void bgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask,
-			       unsigned long *bits)
-{
-	bgpio_set_multiple_single_reg(gc, mask, bits, gc->reg_dat);
-}
-
-static void bgpio_set_multiple_set(struct gpio_chip *gc, unsigned long *mask,
-				   unsigned long *bits)
-{
-	bgpio_set_multiple_single_reg(gc, mask, bits, gc->reg_set);
-}
-
-static void bgpio_set_multiple_with_clear(struct gpio_chip *gc,
-					  unsigned long *mask,
-					  unsigned long *bits)
-{
-	unsigned long set_mask, clear_mask;
-
-	bgpio_multiple_get_masks(gc, mask, bits, &set_mask, &clear_mask);
-
-	if (set_mask)
-		gc->write_reg(gc->reg_set, set_mask);
-	if (clear_mask)
-		gc->write_reg(gc->reg_clr, clear_mask);
-}
-
-static int bgpio_simple_dir_in(struct gpio_chip *gc, unsigned int gpio)
-{
-	return 0;
-}
-
-static int bgpio_dir_out_err(struct gpio_chip *gc, unsigned int gpio,
-				int val)
-{
-	return -EINVAL;
-}
-
-static int bgpio_simple_dir_out(struct gpio_chip *gc, unsigned int gpio,
-				int val)
-{
-	gc->set(gc, gpio, val);
-
-	return 0;
-}
-
-static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&gc->bgpio_lock, flags);
-
-	gc->bgpio_dir &= ~gc->pin2mask(gc, gpio);
-	gc->write_reg(gc->reg_dir, gc->bgpio_dir);
-
-	spin_unlock_irqrestore(&gc->bgpio_lock, flags);
-
-	return 0;
-}
-
-static int bgpio_get_dir(struct gpio_chip *gc, unsigned int gpio)
-{
-	/* Return 0 if output, 1 of input */
-	return !(gc->read_reg(gc->reg_dir) & gc->pin2mask(gc, gpio));
-}
-
-static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
-{
-	unsigned long flags;
-
-	gc->set(gc, gpio, val);
-
-	spin_lock_irqsave(&gc->bgpio_lock, flags);
-
-	gc->bgpio_dir |= gc->pin2mask(gc, gpio);
-	gc->write_reg(gc->reg_dir, gc->bgpio_dir);
-
-	spin_unlock_irqrestore(&gc->bgpio_lock, flags);
-
-	return 0;
-}
-
-static int bgpio_dir_in_inv(struct gpio_chip *gc, unsigned int gpio)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&gc->bgpio_lock, flags);
-
-	gc->bgpio_dir |= gc->pin2mask(gc, gpio);
-	gc->write_reg(gc->reg_dir, gc->bgpio_dir);
-
-	spin_unlock_irqrestore(&gc->bgpio_lock, flags);
-
-	return 0;
-}
-
-static int bgpio_dir_out_inv(struct gpio_chip *gc, unsigned int gpio, int val)
-{
-	unsigned long flags;
-
-	gc->set(gc, gpio, val);
-
-	spin_lock_irqsave(&gc->bgpio_lock, flags);
-
-	gc->bgpio_dir &= ~gc->pin2mask(gc, gpio);
-	gc->write_reg(gc->reg_dir, gc->bgpio_dir);
-
-	spin_unlock_irqrestore(&gc->bgpio_lock, flags);
-
-	return 0;
-}
-
-static int bgpio_get_dir_inv(struct gpio_chip *gc, unsigned int gpio)
-{
-	/* Return 0 if output, 1 if input */
-	return !!(gc->read_reg(gc->reg_dir) & gc->pin2mask(gc, gpio));
-}
-
-static int bgpio_setup_accessors(struct device *dev,
-				 struct gpio_chip *gc,
-				 bool bit_be,
-				 bool byte_be)
-{
-
-	switch (gc->bgpio_bits) {
-	case 8:
-		gc->read_reg	= bgpio_read8;
-		gc->write_reg	= bgpio_write8;
-		break;
-	case 16:
-		if (byte_be) {
-			gc->read_reg	= bgpio_read16be;
-			gc->write_reg	= bgpio_write16be;
-		} else {
-			gc->read_reg	= bgpio_read16;
-			gc->write_reg	= bgpio_write16;
-		}
-		break;
-	case 32:
-		if (byte_be) {
-			gc->read_reg	= bgpio_read32be;
-			gc->write_reg	= bgpio_write32be;
-		} else {
-			gc->read_reg	= bgpio_read32;
-			gc->write_reg	= bgpio_write32;
-		}
-		break;
-#if BITS_PER_LONG >= 64
-	case 64:
-		if (byte_be) {
-			dev_err(dev,
-				"64 bit big endian byte order unsupported\n");
-			return -EINVAL;
-		} else {
-			gc->read_reg	= bgpio_read64;
-			gc->write_reg	= bgpio_write64;
-		}
-		break;
-#endif /* BITS_PER_LONG >= 64 */
-	default:
-		dev_err(dev, "unsupported data width %u bits\n", gc->bgpio_bits);
-		return -EINVAL;
-	}
-
-	gc->pin2mask = bit_be ? bgpio_pin2mask_be : bgpio_pin2mask;
-
-	return 0;
-}
-
-/*
- * Create the device and allocate the resources.  For setting GPIO's there are
- * three supported configurations:
- *
- *	- single input/output register resource (named "dat").
- *	- set/clear pair (named "set" and "clr").
- *	- single output register resource and single input resource ("set" and
- *	dat").
- *
- * For the single output register, this drives a 1 by setting a bit and a zero
- * by clearing a bit.  For the set clr pair, this drives a 1 by setting a bit
- * in the set register and clears it by setting a bit in the clear register.
- * The configuration is detected by which resources are present.
- *
- * For setting the GPIO direction, there are three supported configurations:
- *
- *	- simple bidirection GPIO that requires no configuration.
- *	- an output direction register (named "dirout") where a 1 bit
- *	indicates the GPIO is an output.
- *	- an input direction register (named "dirin") where a 1 bit indicates
- *	the GPIO is an input.
- */
-static int bgpio_setup_io(struct gpio_chip *gc,
-			  void __iomem *dat,
-			  void __iomem *set,
-			  void __iomem *clr,
-			  unsigned long flags)
-{
-
-	gc->reg_dat = dat;
-	if (!gc->reg_dat)
-		return -EINVAL;
-
-	if (set && clr) {
-		gc->reg_set = set;
-		gc->reg_clr = clr;
-		gc->set = bgpio_set_with_clear;
-		gc->set_multiple = bgpio_set_multiple_with_clear;
-	} else if (set && !clr) {
-		gc->reg_set = set;
-		gc->set = bgpio_set_set;
-		gc->set_multiple = bgpio_set_multiple_set;
-	} else if (flags & BGPIOF_NO_OUTPUT) {
-		gc->set = bgpio_set_none;
-		gc->set_multiple = NULL;
-	} else {
-		gc->set = bgpio_set;
-		gc->set_multiple = bgpio_set_multiple;
-	}
-
-	if (!(flags & BGPIOF_UNREADABLE_REG_SET) &&
-	    (flags & BGPIOF_READ_OUTPUT_REG_SET))
-		gc->get = bgpio_get_set;
-	else
-		gc->get = bgpio_get;
-
-	return 0;
-}
-
-static int bgpio_setup_direction(struct gpio_chip *gc,
-				 void __iomem *dirout,
-				 void __iomem *dirin,
-				 unsigned long flags)
-{
-	if (dirout && dirin) {
-		return -EINVAL;
-	} else if (dirout) {
-		gc->reg_dir = dirout;
-		gc->direction_output = bgpio_dir_out;
-		gc->direction_input = bgpio_dir_in;
-		gc->get_direction = bgpio_get_dir;
-	} else if (dirin) {
-		gc->reg_dir = dirin;
-		gc->direction_output = bgpio_dir_out_inv;
-		gc->direction_input = bgpio_dir_in_inv;
-		gc->get_direction = bgpio_get_dir_inv;
-	} else {
-		if (flags & BGPIOF_NO_OUTPUT)
-			gc->direction_output = bgpio_dir_out_err;
-		else
-			gc->direction_output = bgpio_simple_dir_out;
-		gc->direction_input = bgpio_simple_dir_in;
-	}
-
-	return 0;
-}
-
-static int bgpio_request(struct gpio_chip *chip, unsigned gpio_pin)
-{
-	if (gpio_pin < chip->ngpio)
-		return 0;
-
-	return -EINVAL;
-}
-
-int bgpio_init(struct gpio_chip *gc, struct device *dev,
-	       unsigned long sz, void __iomem *dat, void __iomem *set,
-	       void __iomem *clr, void __iomem *dirout, void __iomem *dirin,
-	       unsigned long flags)
-{
-	int ret;
-
-	if (!is_power_of_2(sz))
-		return -EINVAL;
-
-	gc->bgpio_bits = sz * 8;
-	if (gc->bgpio_bits > BITS_PER_LONG)
-		return -EINVAL;
-
-	spin_lock_init(&gc->bgpio_lock);
-	gc->parent = dev;
-	gc->label = dev_name(dev);
-	gc->base = -1;
-	gc->ngpio = gc->bgpio_bits;
-	gc->request = bgpio_request;
-
-	ret = bgpio_setup_io(gc, dat, set, clr, flags);
-	if (ret)
-		return ret;
-
-	ret = bgpio_setup_accessors(dev, gc, flags & BGPIOF_BIG_ENDIAN,
-				    flags & BGPIOF_BIG_ENDIAN_BYTE_ORDER);
-	if (ret)
-		return ret;
-
-	ret = bgpio_setup_direction(gc, dirout, dirin, flags);
-	if (ret)
-		return ret;
-
-	gc->bgpio_data = gc->read_reg(gc->reg_dat);
-	if (gc->set == bgpio_set_set &&
-			!(flags & BGPIOF_UNREADABLE_REG_SET))
-		gc->bgpio_data = gc->read_reg(gc->reg_set);
-	if (gc->reg_dir && !(flags & BGPIOF_UNREADABLE_REG_DIR))
-		gc->bgpio_dir = gc->read_reg(gc->reg_dir);
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(bgpio_init);
-
-#ifdef CONFIG_GPIO_GENERIC_PLATFORM
-
-static void __iomem *bgpio_map(struct platform_device *pdev,
-			       const char *name,
-			       resource_size_t sane_sz)
-{
-	struct resource *r;
-	resource_size_t sz;
-
-	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
-	if (!r)
-		return NULL;
-
-	sz = resource_size(r);
-	if (sz != sane_sz)
-		return IOMEM_ERR_PTR(-EINVAL);
-
-	return devm_ioremap_resource(&pdev->dev, r);
-}
-
-static int bgpio_pdev_probe(struct platform_device *pdev)
-{
-	struct device *dev = &pdev->dev;
-	struct resource *r;
-	void __iomem *dat;
-	void __iomem *set;
-	void __iomem *clr;
-	void __iomem *dirout;
-	void __iomem *dirin;
-	unsigned long sz;
-	unsigned long flags = pdev->id_entry->driver_data;
-	int err;
-	struct gpio_chip *gc;
-	struct bgpio_pdata *pdata = dev_get_platdata(dev);
-
-	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat");
-	if (!r)
-		return -EINVAL;
-
-	sz = resource_size(r);
-
-	dat = bgpio_map(pdev, "dat", sz);
-	if (IS_ERR(dat))
-		return PTR_ERR(dat);
-
-	set = bgpio_map(pdev, "set", sz);
-	if (IS_ERR(set))
-		return PTR_ERR(set);
-
-	clr = bgpio_map(pdev, "clr", sz);
-	if (IS_ERR(clr))
-		return PTR_ERR(clr);
-
-	dirout = bgpio_map(pdev, "dirout", sz);
-	if (IS_ERR(dirout))
-		return PTR_ERR(dirout);
-
-	dirin = bgpio_map(pdev, "dirin", sz);
-	if (IS_ERR(dirin))
-		return PTR_ERR(dirin);
-
-	gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL);
-	if (!gc)
-		return -ENOMEM;
-
-	err = bgpio_init(gc, dev, sz, dat, set, clr, dirout, dirin, flags);
-	if (err)
-		return err;
-
-	if (pdata) {
-		if (pdata->label)
-			gc->label = pdata->label;
-		gc->base = pdata->base;
-		if (pdata->ngpio > 0)
-			gc->ngpio = pdata->ngpio;
-	}
-
-	platform_set_drvdata(pdev, gc);
-
-	return devm_gpiochip_add_data(&pdev->dev, gc, NULL);
-}
-
-static const struct platform_device_id bgpio_id_table[] = {
-	{
-		.name		= "basic-mmio-gpio",
-		.driver_data	= 0,
-	}, {
-		.name		= "basic-mmio-gpio-be",
-		.driver_data	= BGPIOF_BIG_ENDIAN,
-	},
-	{ }
-};
-MODULE_DEVICE_TABLE(platform, bgpio_id_table);
-
-static struct platform_driver bgpio_driver = {
-	.driver = {
-		.name = "basic-mmio-gpio",
-	},
-	.id_table = bgpio_id_table,
-	.probe = bgpio_pdev_probe,
-};
-
-module_platform_driver(bgpio_driver);
-
-#endif /* CONFIG_GPIO_GENERIC_PLATFORM */
-
-MODULE_DESCRIPTION("Driver for basic memory-mapped GPIO controllers");
-MODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>");
-MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-it87.c linux-libre-4.7-gnu/drivers/gpio/gpio-it87.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-it87.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-it87.c	2016-07-24 15:23:50.000000000 -0400
@@ -34,6 +34,8 @@
 
 /* Chip Id numbers */
 #define NO_DEV_ID	0xffff
+#define IT8620_ID	0x8620
+#define IT8628_ID	0x8628
 #define IT8728_ID	0x8728
 #define IT8732_ID	0x8732
 #define IT8761_ID	0x8761
@@ -302,6 +304,14 @@ static int __init it87_gpio_init(void)
 	it87_gpio->chip = it87_template_chip;
 
 	switch (chip_type) {
+	case IT8620_ID:
+	case IT8628_ID:
+		gpio_ba_reg = 0x62;
+		it87_gpio->io_size = 11;
+		it87_gpio->output_base = 0xc8;
+		it87_gpio->simple_size = 0;
+		it87_gpio->chip.ngpio = 64;
+		break;
 	case IT8728_ID:
 	case IT8732_ID:
 		gpio_ba_reg = 0x62;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpiolib.c linux-libre-4.7-gnu/drivers/gpio/gpiolib.c
--- linux-libre-4.6-gnu/drivers/gpio/gpiolib.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpiolib.c	2016-07-24 15:23:50.000000000 -0400
@@ -20,6 +20,7 @@
 #include <linux/cdev.h>
 #include <linux/fs.h>
 #include <linux/uaccess.h>
+#include <linux/compat.h>
 #include <uapi/linux/gpio.h>
 
 #include "gpiolib.h"
@@ -316,7 +317,7 @@ static long gpio_ioctl(struct file *filp
 {
 	struct gpio_device *gdev = filp->private_data;
 	struct gpio_chip *chip = gdev->chip;
-	int __user *ip = (int __user *)arg;
+	void __user *ip = (void __user *)arg;
 
 	/* We fail any subsequent ioctl():s when the chip is gone */
 	if (!chip)
@@ -388,6 +389,14 @@ static long gpio_ioctl(struct file *filp
 	return -EINVAL;
 }
 
+#ifdef CONFIG_COMPAT
+static long gpio_ioctl_compat(struct file *filp, unsigned int cmd,
+			      unsigned long arg)
+{
+	return gpio_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
+}
+#endif
+
 /**
  * gpio_chrdev_open() - open the chardev for ioctl operations
  * @inode: inode for this chardev
@@ -431,14 +440,15 @@ static const struct file_operations gpio
 	.owner = THIS_MODULE,
 	.llseek = noop_llseek,
 	.unlocked_ioctl = gpio_ioctl,
-	.compat_ioctl = gpio_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = gpio_ioctl_compat,
+#endif
 };
 
 static void gpiodevice_release(struct device *dev)
 {
 	struct gpio_device *gdev = dev_get_drvdata(dev);
 
-	cdev_del(&gdev->chrdev);
 	list_del(&gdev->list);
 	ida_simple_remove(&gpio_ida, gdev->id);
 	kfree(gdev->label);
@@ -471,7 +481,6 @@ static int gpiochip_setup_dev(struct gpi
 
 	/* From this point, the .release() function cleans up gpio_device */
 	gdev->dev.release = gpiodevice_release;
-	get_device(&gdev->dev);
 	pr_debug("%s: registered GPIOs %d to %d on device: %s (%s)\n",
 		 __func__, gdev->base, gdev->base + gdev->ngpio - 1,
 		 dev_name(&gdev->dev), gdev->chip->label ? : "generic");
@@ -618,21 +627,38 @@ int gpiochip_add_data(struct gpio_chip *
 		goto err_free_label;
 	}
 
+	spin_unlock_irqrestore(&gpio_lock, flags);
+
 	for (i = 0; i < chip->ngpio; i++) {
 		struct gpio_desc *desc = &gdev->descs[i];
 
 		desc->gdev = gdev;
-
-		/* REVISIT: most hardware initializes GPIOs as inputs (often
-		 * with pullups enabled) so power usage is minimized. Linux
-		 * code should set the gpio direction first thing; but until
-		 * it does, and in case chip->get_direction is not set, we may
-		 * expose the wrong direction in sysfs.
+		/*
+		 * REVISIT: most hardware initializes GPIOs as inputs
+		 * (often with pullups enabled) so power usage is
+		 * minimized. Linux code should set the gpio direction
+		 * first thing; but until it does, and in case
+		 * chip->get_direction is not set, we may expose the
+		 * wrong direction in sysfs.
 		 */
-		desc->flags = !chip->direction_input ? (1 << FLAG_IS_OUT) : 0;
-	}
 
-	spin_unlock_irqrestore(&gpio_lock, flags);
+		if (chip->get_direction) {
+			/*
+			 * If we have .get_direction, set up the initial
+			 * direction flag from the hardware.
+			 */
+			int dir = chip->get_direction(chip, i);
+
+			if (!dir)
+				set_bit(FLAG_IS_OUT, &desc->flags);
+		} else if (!chip->direction_input) {
+			/*
+			 * If the chip lacks the .direction_input callback
+			 * we logically assume all lines are outputs.
+			 */
+			set_bit(FLAG_IS_OUT, &desc->flags);
+		}
+	}
 
 #ifdef CONFIG_PINCTRL
 	INIT_LIST_HEAD(&gdev->pin_ranges);
@@ -742,6 +768,8 @@ void gpiochip_remove(struct gpio_chip *c
 	 * be removed, else it will be dangling until the last user is
 	 * gone.
 	 */
+	cdev_del(&gdev->chrdev);
+	device_del(&gdev->dev);
 	put_device(&gdev->dev);
 }
 EXPORT_SYMBOL_GPL(gpiochip_remove);
@@ -841,7 +869,7 @@ struct gpio_chip *gpiochip_find(void *da
 
 	spin_lock_irqsave(&gpio_lock, flags);
 	list_for_each_entry(gdev, &gpio_devices, list)
-		if (match(gdev->chip, data))
+		if (gdev->chip && match(gdev->chip, data))
 			break;
 
 	/* No match? */
@@ -1324,14 +1352,6 @@ static int __gpiod_request(struct gpio_d
 		spin_lock_irqsave(&gpio_lock, flags);
 	}
 done:
-	if (status < 0) {
-		/* Clear flags that might have been set by the caller before
-		 * requesting the GPIO.
-		 */
-		clear_bit(FLAG_ACTIVE_LOW, &desc->flags);
-		clear_bit(FLAG_OPEN_DRAIN, &desc->flags);
-		clear_bit(FLAG_OPEN_SOURCE, &desc->flags);
-	}
 	spin_unlock_irqrestore(&gpio_lock, flags);
 	return status;
 }
@@ -1339,11 +1359,18 @@ done:
 /*
  * This descriptor validation needs to be inserted verbatim into each
  * function taking a descriptor, so we need to use a preprocessor
- * macro to avoid endless duplication.
+ * macro to avoid endless duplication. If the desc is NULL it is an
+ * optional GPIO and calls should just bail out.
  */
 #define VALIDATE_DESC(desc) do { \
-	if (!desc || !desc->gdev) { \
-		pr_warn("%s: invalid GPIO\n", __func__); \
+	if (!desc) \
+		return 0; \
+	if (IS_ERR(desc)) {						\
+		pr_warn("%s: invalid GPIO (errorpointer)\n", __func__); \
+		return PTR_ERR(desc); \
+	} \
+	if (!desc->gdev) { \
+		pr_warn("%s: invalid GPIO (no device)\n", __func__); \
 		return -EINVAL; \
 	} \
 	if ( !desc->gdev->chip ) { \
@@ -1353,8 +1380,14 @@ done:
 	} } while (0)
 
 #define VALIDATE_DESC_VOID(desc) do { \
-	if (!desc || !desc->gdev) { \
-		pr_warn("%s: invalid GPIO\n", __func__); \
+	if (!desc) \
+		return; \
+	if (IS_ERR(desc)) {						\
+		pr_warn("%s: invalid GPIO (errorpointer)\n", __func__); \
+		return; \
+	} \
+	if (!desc->gdev) { \
+		pr_warn("%s: invalid GPIO (no device)\n", __func__); \
 		return; \
 	} \
 	if (!desc->gdev->chip) { \
@@ -1547,8 +1580,8 @@ EXPORT_SYMBOL_GPL(gpiod_direction_input)
 
 static int _gpiod_direction_output_raw(struct gpio_desc *desc, int value)
 {
-	struct gpio_chip	*chip;
-	int			status = -EINVAL;
+	struct gpio_chip *gc = desc->gdev->chip;
+	int ret;
 
 	/* GPIOs used for IRQs shall not be set as output */
 	if (test_bit(FLAG_USED_AS_IRQ, &desc->flags)) {
@@ -1558,28 +1591,50 @@ static int _gpiod_direction_output_raw(s
 		return -EIO;
 	}
 
-	/* Open drain pin should not be driven to 1 */
-	if (value && test_bit(FLAG_OPEN_DRAIN,  &desc->flags))
-		return gpiod_direction_input(desc);
-
-	/* Open source pin should not be driven to 0 */
-	if (!value && test_bit(FLAG_OPEN_SOURCE,  &desc->flags))
-		return gpiod_direction_input(desc);
+	if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) {
+		/* First see if we can enable open drain in hardware */
+		if (gc->set_single_ended) {
+			ret = gc->set_single_ended(gc, gpio_chip_hwgpio(desc),
+						   LINE_MODE_OPEN_DRAIN);
+			if (!ret)
+				goto set_output_value;
+		}
+		/* Emulate open drain by not actively driving the line high */
+		if (value)
+			return gpiod_direction_input(desc);
+	}
+	else if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) {
+		if (gc->set_single_ended) {
+			ret = gc->set_single_ended(gc, gpio_chip_hwgpio(desc),
+						   LINE_MODE_OPEN_SOURCE);
+			if (!ret)
+				goto set_output_value;
+		}
+		/* Emulate open source by not actively driving the line low */
+		if (!value)
+			return gpiod_direction_input(desc);
+	} else {
+		/* Make sure to disable open drain/source hardware, if any */
+		if (gc->set_single_ended)
+			gc->set_single_ended(gc,
+					     gpio_chip_hwgpio(desc),
+					     LINE_MODE_PUSH_PULL);
+	}
 
-	chip = desc->gdev->chip;
-	if (!chip->set || !chip->direction_output) {
+set_output_value:
+	if (!gc->set || !gc->direction_output) {
 		gpiod_warn(desc,
 		       "%s: missing set() or direction_output() operations\n",
 		       __func__);
 		return -EIO;
 	}
 
-	status = chip->direction_output(chip, gpio_chip_hwgpio(desc), value);
-	if (status == 0)
+	ret = gc->direction_output(gc, gpio_chip_hwgpio(desc), value);
+	if (!ret)
 		set_bit(FLAG_IS_OUT, &desc->flags);
 	trace_gpio_value(desc_to_gpio(desc), 0, value);
-	trace_gpio_direction(desc_to_gpio(desc), 0, status);
-	return status;
+	trace_gpio_direction(desc_to_gpio(desc), 0, ret);
+	return ret;
 }
 
 /**
@@ -1841,10 +1896,10 @@ static void gpio_chip_set_multiple(struc
 	}
 }
 
-static void gpiod_set_array_value_priv(bool raw, bool can_sleep,
-				       unsigned int array_size,
-				       struct gpio_desc **desc_array,
-				       int *value_array)
+void gpiod_set_array_value_complex(bool raw, bool can_sleep,
+				   unsigned int array_size,
+				   struct gpio_desc **desc_array,
+				   int *value_array)
 {
 	int i = 0;
 
@@ -1950,8 +2005,8 @@ void gpiod_set_raw_array_value(unsigned
 {
 	if (!desc_array)
 		return;
-	gpiod_set_array_value_priv(true, false, array_size, desc_array,
-				   value_array);
+	gpiod_set_array_value_complex(true, false, array_size, desc_array,
+				      value_array);
 }
 EXPORT_SYMBOL_GPL(gpiod_set_raw_array_value);
 
@@ -1972,8 +2027,8 @@ void gpiod_set_array_value(unsigned int
 {
 	if (!desc_array)
 		return;
-	gpiod_set_array_value_priv(false, false, array_size, desc_array,
-				   value_array);
+	gpiod_set_array_value_complex(false, false, array_size, desc_array,
+				      value_array);
 }
 EXPORT_SYMBOL_GPL(gpiod_set_array_value);
 
@@ -1998,13 +2053,29 @@ EXPORT_SYMBOL_GPL(gpiod_cansleep);
  */
 int gpiod_to_irq(const struct gpio_desc *desc)
 {
-	struct gpio_chip	*chip;
-	int			offset;
+	struct gpio_chip *chip;
+	int offset;
+
+	/*
+	 * Cannot VALIDATE_DESC() here as gpiod_to_irq() consumer semantics
+	 * requires this function to not return zero on an invalid descriptor
+	 * but rather a negative error number.
+	 */
+	if (!desc || IS_ERR(desc) || !desc->gdev || !desc->gdev->chip)
+		return -EINVAL;
 
-	VALIDATE_DESC(desc);
 	chip = desc->gdev->chip;
 	offset = gpio_chip_hwgpio(desc);
-	return chip->to_irq ? chip->to_irq(chip, offset) : -ENXIO;
+	if (chip->to_irq) {
+		int retirq = chip->to_irq(chip, offset);
+
+		/* Zero means NO_IRQ */
+		if (!retirq)
+			return -ENXIO;
+
+		return retirq;
+	}
+	return -ENXIO;
 }
 EXPORT_SYMBOL_GPL(gpiod_to_irq);
 
@@ -2018,17 +2089,30 @@ EXPORT_SYMBOL_GPL(gpiod_to_irq);
  */
 int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset)
 {
-	if (offset >= chip->ngpio)
-		return -EINVAL;
+	struct gpio_desc *desc;
 
-	if (test_bit(FLAG_IS_OUT, &chip->gpiodev->descs[offset].flags)) {
+	desc = gpiochip_get_desc(chip, offset);
+	if (IS_ERR(desc))
+		return PTR_ERR(desc);
+
+	/* Flush direction if something changed behind our back */
+	if (chip->get_direction) {
+		int dir = chip->get_direction(chip, offset);
+
+		if (dir)
+			clear_bit(FLAG_IS_OUT, &desc->flags);
+		else
+			set_bit(FLAG_IS_OUT, &desc->flags);
+	}
+
+	if (test_bit(FLAG_IS_OUT, &desc->flags)) {
 		chip_err(chip,
 			  "%s: tried to flag a GPIO set as output for IRQ\n",
 			  __func__);
 		return -EIO;
 	}
 
-	set_bit(FLAG_USED_AS_IRQ, &chip->gpiodev->descs[offset].flags);
+	set_bit(FLAG_USED_AS_IRQ, &desc->flags);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(gpiochip_lock_as_irq);
@@ -2176,8 +2260,8 @@ void gpiod_set_raw_array_value_cansleep(
 	might_sleep_if(extra_checks);
 	if (!desc_array)
 		return;
-	gpiod_set_array_value_priv(true, true, array_size, desc_array,
-				   value_array);
+	gpiod_set_array_value_complex(true, true, array_size, desc_array,
+				      value_array);
 }
 EXPORT_SYMBOL_GPL(gpiod_set_raw_array_value_cansleep);
 
@@ -2199,8 +2283,8 @@ void gpiod_set_array_value_cansleep(unsi
 	might_sleep_if(extra_checks);
 	if (!desc_array)
 		return;
-	gpiod_set_array_value_priv(false, true, array_size, desc_array,
-				   value_array);
+	gpiod_set_array_value_complex(false, true, array_size, desc_array,
+				      value_array);
 }
 EXPORT_SYMBOL_GPL(gpiod_set_array_value_cansleep);
 
@@ -2495,28 +2579,13 @@ struct gpio_desc *__must_check gpiod_get
 }
 EXPORT_SYMBOL_GPL(gpiod_get_optional);
 
-/**
- * gpiod_parse_flags - helper function to parse GPIO lookup flags
- * @desc:	gpio to be setup
- * @lflags:	gpio_lookup_flags - returned from of_find_gpio() or
- *		of_get_gpio_hog()
- *
- * Set the GPIO descriptor flags based on the given GPIO lookup flags.
- */
-static void gpiod_parse_flags(struct gpio_desc *desc, unsigned long lflags)
-{
-	if (lflags & GPIO_ACTIVE_LOW)
-		set_bit(FLAG_ACTIVE_LOW, &desc->flags);
-	if (lflags & GPIO_OPEN_DRAIN)
-		set_bit(FLAG_OPEN_DRAIN, &desc->flags);
-	if (lflags & GPIO_OPEN_SOURCE)
-		set_bit(FLAG_OPEN_SOURCE, &desc->flags);
-}
 
 /**
  * gpiod_configure_flags - helper function to configure a given GPIO
  * @desc:	gpio whose value will be assigned
  * @con_id:	function within the GPIO consumer
+ * @lflags:	gpio_lookup_flags - returned from of_find_gpio() or
+ *		of_get_gpio_hog()
  * @dflags:	gpiod_flags - optional GPIO initialization flags
  *
  * Return 0 on success, -ENOENT if no GPIO has been assigned to the
@@ -2524,10 +2593,17 @@ static void gpiod_parse_flags(struct gpi
  * occurred while trying to acquire the GPIO.
  */
 static int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,
-				 enum gpiod_flags dflags)
+		unsigned long lflags, enum gpiod_flags dflags)
 {
 	int status;
 
+	if (lflags & GPIO_ACTIVE_LOW)
+		set_bit(FLAG_ACTIVE_LOW, &desc->flags);
+	if (lflags & GPIO_OPEN_DRAIN)
+		set_bit(FLAG_OPEN_DRAIN, &desc->flags);
+	if (lflags & GPIO_OPEN_SOURCE)
+		set_bit(FLAG_OPEN_SOURCE, &desc->flags);
+
 	/* No particular flag request, return here... */
 	if (!(dflags & GPIOD_FLAGS_BIT_DIR_SET)) {
 		pr_debug("no flags found for %s\n", con_id);
@@ -2594,13 +2670,11 @@ struct gpio_desc *__must_check gpiod_get
 		return desc;
 	}
 
-	gpiod_parse_flags(desc, lookupflags);
-
 	status = gpiod_request(desc, con_id);
 	if (status < 0)
 		return ERR_PTR(status);
 
-	status = gpiod_configure_flags(desc, con_id, flags);
+	status = gpiod_configure_flags(desc, con_id, lookupflags, flags);
 	if (status < 0) {
 		dev_dbg(dev, "setup of GPIO %s failed\n", con_id);
 		gpiod_put(desc);
@@ -2656,6 +2730,10 @@ struct gpio_desc *fwnode_get_named_gpiod
 	if (IS_ERR(desc))
 		return desc;
 
+	ret = gpiod_request(desc, NULL);
+	if (ret)
+		return ERR_PTR(ret);
+
 	if (active_low)
 		set_bit(FLAG_ACTIVE_LOW, &desc->flags);
 
@@ -2666,10 +2744,6 @@ struct gpio_desc *fwnode_get_named_gpiod
 			set_bit(FLAG_OPEN_SOURCE, &desc->flags);
 	}
 
-	ret = gpiod_request(desc, NULL);
-	if (ret)
-		return ERR_PTR(ret);
-
 	return desc;
 }
 EXPORT_SYMBOL_GPL(fwnode_get_named_gpiod);
@@ -2722,19 +2796,18 @@ int gpiod_hog(struct gpio_desc *desc, co
 	chip = gpiod_to_chip(desc);
 	hwnum = gpio_chip_hwgpio(desc);
 
-	gpiod_parse_flags(desc, lflags);
-
 	local_desc = gpiochip_request_own_desc(chip, hwnum, name);
 	if (IS_ERR(local_desc)) {
-		pr_err("requesting hog GPIO %s (chip %s, offset %d) failed\n",
-		       name, chip->label, hwnum);
-		return PTR_ERR(local_desc);
+		status = PTR_ERR(local_desc);
+		pr_err("requesting hog GPIO %s (chip %s, offset %d) failed, %d\n",
+		       name, chip->label, hwnum, status);
+		return status;
 	}
 
-	status = gpiod_configure_flags(desc, name, dflags);
+	status = gpiod_configure_flags(desc, name, lflags, dflags);
 	if (status < 0) {
-		pr_err("setup of hog GPIO %s (chip %s, offset %d) failed\n",
-		       name, chip->label, hwnum);
+		pr_err("setup of hog GPIO %s (chip %s, offset %d) failed, %d\n",
+		       name, chip->label, hwnum, status);
 		gpiochip_free_own_desc(desc);
 		return status;
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpiolib.h linux-libre-4.7-gnu/drivers/gpio/gpiolib.h
--- linux-libre-4.6-gnu/drivers/gpio/gpiolib.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpiolib.h	2016-07-24 15:23:50.000000000 -0400
@@ -141,6 +141,10 @@ struct gpio_desc *of_get_named_gpiod_fla
 		   const char *list_name, int index, enum of_gpio_flags *flags);
 
 struct gpio_desc *gpiochip_get_desc(struct gpio_chip *chip, u16 hwnum);
+void gpiod_set_array_value_complex(bool raw, bool can_sleep,
+				   unsigned int array_size,
+				   struct gpio_desc **desc_array,
+				   int *value_array);
 
 extern struct spinlock gpio_lock;
 extern struct list_head gpio_devices;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpiolib-legacy.c linux-libre-4.7-gnu/drivers/gpio/gpiolib-legacy.c
--- linux-libre-4.6-gnu/drivers/gpio/gpiolib-legacy.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpiolib-legacy.c	2016-07-24 15:23:50.000000000 -0400
@@ -28,6 +28,10 @@ int gpio_request_one(unsigned gpio, unsi
 	if (!desc && gpio_is_valid(gpio))
 		return -EPROBE_DEFER;
 
+	err = gpiod_request(desc, label);
+	if (err)
+		return err;
+
 	if (flags & GPIOF_OPEN_DRAIN)
 		set_bit(FLAG_OPEN_DRAIN, &desc->flags);
 
@@ -37,10 +41,6 @@ int gpio_request_one(unsigned gpio, unsi
 	if (flags & GPIOF_ACTIVE_LOW)
 		set_bit(FLAG_ACTIVE_LOW, &desc->flags);
 
-	err = gpiod_request(desc, label);
-	if (err)
-		return err;
-
 	if (flags & GPIOF_DIR_IN)
 		err = gpiod_direction_input(desc);
 	else
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpiolib-of.c linux-libre-4.7-gnu/drivers/gpio/gpiolib-of.c
--- linux-libre-4.6-gnu/drivers/gpio/gpiolib-of.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpiolib-of.c	2016-07-24 15:23:50.000000000 -0400
@@ -16,6 +16,7 @@
 #include <linux/errno.h>
 #include <linux/module.h>
 #include <linux/io.h>
+#include <linux/io-mapping.h>
 #include <linux/gpio/consumer.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
@@ -196,21 +197,68 @@ static struct gpio_desc *of_parse_own_gp
 }
 
 /**
+ * of_gpiochip_set_names() - set up the names of the lines
+ * @chip: GPIO chip whose lines should be named, if possible
+ */
+static void of_gpiochip_set_names(struct gpio_chip *gc)
+{
+	struct gpio_device *gdev = gc->gpiodev;
+	struct device_node *np = gc->of_node;
+	int i;
+	int nstrings;
+
+	nstrings = of_property_count_strings(np, "gpio-line-names");
+	if (nstrings <= 0)
+		/* Lines names not present */
+		return;
+
+	/* This is normally not what you want */
+	if (gdev->ngpio != nstrings)
+		dev_info(&gdev->dev, "gpio-line-names specifies %d line "
+			 "names but there are %d lines on the chip\n",
+			 nstrings, gdev->ngpio);
+
+	/*
+	 * Make sure to not index beyond the end of the number of descriptors
+	 * of the GPIO device.
+	 */
+	for (i = 0; i < gdev->ngpio; i++) {
+		const char *name;
+		int ret;
+
+		ret = of_property_read_string_index(np,
+						    "gpio-line-names",
+						    i,
+						    &name);
+		if (ret) {
+			if (ret != -ENODATA)
+                                dev_err(&gdev->dev,
+                                        "unable to name line %d: %d\n",
+                                        i, ret);
+			break;
+		}
+		gdev->descs[i].name = name;
+	}
+}
+
+/**
  * of_gpiochip_scan_gpios - Scan gpio-controller for gpio definitions
  * @chip:	gpio chip to act on
  *
  * This is only used by of_gpiochip_add to request/set GPIO initial
  * configuration.
+ * It retures error if it fails otherwise 0 on success.
  */
-static void of_gpiochip_scan_gpios(struct gpio_chip *chip)
+static int of_gpiochip_scan_gpios(struct gpio_chip *chip)
 {
 	struct gpio_desc *desc = NULL;
 	struct device_node *np;
 	const char *name;
 	enum gpio_lookup_flags lflags;
 	enum gpiod_flags dflags;
+	int ret;
 
-	for_each_child_of_node(chip->of_node, np) {
+	for_each_available_child_of_node(chip->of_node, np) {
 		if (!of_property_read_bool(np, "gpio-hog"))
 			continue;
 
@@ -218,9 +266,12 @@ static void of_gpiochip_scan_gpios(struc
 		if (IS_ERR(desc))
 			continue;
 
-		if (gpiod_hog(desc, name, lflags, dflags))
-			continue;
+		ret = gpiod_hog(desc, name, lflags, dflags);
+		if (ret < 0)
+			return ret;
 	}
+
+	return 0;
 }
 
 /**
@@ -440,11 +491,13 @@ int of_gpiochip_add(struct gpio_chip *ch
 	if (status)
 		return status;
 
-	of_node_get(chip->of_node);
+	/* If the chip defines names itself, these take precedence */
+	if (!chip->names)
+		of_gpiochip_set_names(chip);
 
-	of_gpiochip_scan_gpios(chip);
+	of_node_get(chip->of_node);
 
-	return 0;
+	return of_gpiochip_scan_gpios(chip);
 }
 
 void of_gpiochip_remove(struct gpio_chip *chip)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-loongson1.c linux-libre-4.7-gnu/drivers/gpio/gpio-loongson1.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-loongson1.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-loongson1.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,102 @@
+/*
+ * GPIO Driver for Loongson 1 SoC
+ *
+ * Copyright (C) 2015-2016 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/gpio/driver.h>
+#include <linux/platform_device.h>
+
+/* Loongson 1 GPIO Register Definitions */
+#define GPIO_CFG		0x0
+#define GPIO_DIR		0x10
+#define GPIO_DATA		0x20
+#define GPIO_OUTPUT		0x30
+
+static void __iomem *gpio_reg_base;
+
+static int ls1x_gpio_request(struct gpio_chip *gc, unsigned int offset)
+{
+	unsigned long pinmask = gc->pin2mask(gc, offset);
+	unsigned long flags;
+
+	spin_lock_irqsave(&gc->bgpio_lock, flags);
+	__raw_writel(__raw_readl(gpio_reg_base + GPIO_CFG) | pinmask,
+		     gpio_reg_base + GPIO_CFG);
+	spin_unlock_irqrestore(&gc->bgpio_lock, flags);
+
+	return 0;
+}
+
+static void ls1x_gpio_free(struct gpio_chip *gc, unsigned int offset)
+{
+	unsigned long pinmask = gc->pin2mask(gc, offset);
+	unsigned long flags;
+
+	spin_lock_irqsave(&gc->bgpio_lock, flags);
+	__raw_writel(__raw_readl(gpio_reg_base + GPIO_CFG) & ~pinmask,
+		     gpio_reg_base + GPIO_CFG);
+	spin_unlock_irqrestore(&gc->bgpio_lock, flags);
+}
+
+static int ls1x_gpio_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct gpio_chip *gc;
+	struct resource *res;
+	int ret;
+
+	gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL);
+	if (!gc)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(dev, "failed to get I/O memory\n");
+		return -EINVAL;
+	}
+
+	gpio_reg_base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(gpio_reg_base))
+		return PTR_ERR(gpio_reg_base);
+
+	ret = bgpio_init(gc, dev, 4, gpio_reg_base + GPIO_DATA,
+			 gpio_reg_base + GPIO_OUTPUT, NULL,
+			 NULL, gpio_reg_base + GPIO_DIR, 0);
+	if (ret)
+		goto err;
+
+	gc->owner = THIS_MODULE;
+	gc->request = ls1x_gpio_request;
+	gc->free = ls1x_gpio_free;
+	gc->base = pdev->id * 32;
+
+	ret = devm_gpiochip_add_data(dev, gc, NULL);
+	if (ret)
+		goto err;
+
+	platform_set_drvdata(pdev, gc);
+	dev_info(dev, "Loongson1 GPIO driver registered\n");
+
+	return 0;
+err:
+	dev_err(dev, "failed to register GPIO device\n");
+	return ret;
+}
+
+static struct platform_driver ls1x_gpio_driver = {
+	.probe	= ls1x_gpio_probe,
+	.driver	= {
+		.name	= "ls1x-gpio",
+	},
+};
+
+module_platform_driver(ls1x_gpio_driver);
+
+MODULE_AUTHOR("Kelvin Cheung <keguang.zhang@gmail.com>");
+MODULE_DESCRIPTION("Loongson1 GPIO driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-lpc32xx.c linux-libre-4.7-gnu/drivers/gpio/gpio-lpc32xx.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-lpc32xx.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-lpc32xx.c	2016-07-24 15:23:50.000000000 -0400
@@ -29,7 +29,6 @@
 
 #include <mach/hardware.h>
 #include <mach/platform.h>
-#include <mach/irqs.h>
 
 #define LPC32XX_GPIO_P3_INP_STATE		_GPREG(0x000)
 #define LPC32XX_GPIO_P3_OUTP_SET		_GPREG(0x004)
@@ -371,61 +370,16 @@ static int lpc32xx_gpio_request(struct g
 
 static int lpc32xx_gpio_to_irq_p01(struct gpio_chip *chip, unsigned offset)
 {
-	return IRQ_LPC32XX_P0_P1_IRQ;
+	return -ENXIO;
 }
 
-static const char lpc32xx_gpio_to_irq_gpio_p3_table[] = {
-	IRQ_LPC32XX_GPIO_00,
-	IRQ_LPC32XX_GPIO_01,
-	IRQ_LPC32XX_GPIO_02,
-	IRQ_LPC32XX_GPIO_03,
-	IRQ_LPC32XX_GPIO_04,
-	IRQ_LPC32XX_GPIO_05,
-};
-
 static int lpc32xx_gpio_to_irq_gpio_p3(struct gpio_chip *chip, unsigned offset)
 {
-	if (offset < ARRAY_SIZE(lpc32xx_gpio_to_irq_gpio_p3_table))
-		return lpc32xx_gpio_to_irq_gpio_p3_table[offset];
 	return -ENXIO;
 }
 
-static const char lpc32xx_gpio_to_irq_gpi_p3_table[] = {
-	IRQ_LPC32XX_GPI_00,
-	IRQ_LPC32XX_GPI_01,
-	IRQ_LPC32XX_GPI_02,
-	IRQ_LPC32XX_GPI_03,
-	IRQ_LPC32XX_GPI_04,
-	IRQ_LPC32XX_GPI_05,
-	IRQ_LPC32XX_GPI_06,
-	IRQ_LPC32XX_GPI_07,
-	IRQ_LPC32XX_GPI_08,
-	IRQ_LPC32XX_GPI_09,
-	-ENXIO, /* 10 */
-	-ENXIO, /* 11 */
-	-ENXIO, /* 12 */
-	-ENXIO, /* 13 */
-	-ENXIO, /* 14 */
-	-ENXIO, /* 15 */
-	-ENXIO, /* 16 */
-	-ENXIO, /* 17 */
-	-ENXIO, /* 18 */
-	IRQ_LPC32XX_GPI_19,
-	-ENXIO, /* 20 */
-	-ENXIO, /* 21 */
-	-ENXIO, /* 22 */
-	-ENXIO, /* 23 */
-	-ENXIO, /* 24 */
-	-ENXIO, /* 25 */
-	-ENXIO, /* 26 */
-	-ENXIO, /* 27 */
-	IRQ_LPC32XX_GPI_28,
-};
-
 static int lpc32xx_gpio_to_irq_gpi_p3(struct gpio_chip *chip, unsigned offset)
 {
-	if (offset < ARRAY_SIZE(lpc32xx_gpio_to_irq_gpi_p3_table))
-		return lpc32xx_gpio_to_irq_gpi_p3_table[offset];
 	return -ENXIO;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-mb86s7x.c linux-libre-4.7-gnu/drivers/gpio/gpio-mb86s7x.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-mb86s7x.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-mb86s7x.c	2016-07-24 15:23:50.000000000 -0400
@@ -17,7 +17,6 @@
 #include <linux/io.h>
 #include <linux/init.h>
 #include <linux/clk.h>
-#include <linux/module.h>
 #include <linux/err.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
@@ -185,8 +184,6 @@ static int mb86s70_gpio_probe(struct pla
 	gchip->gc.parent = &pdev->dev;
 	gchip->gc.base = -1;
 
-	platform_set_drvdata(pdev, gchip);
-
 	ret = gpiochip_add_data(&gchip->gc, gchip);
 	if (ret) {
 		dev_err(&pdev->dev, "couldn't register gpio driver\n");
@@ -210,7 +207,6 @@ static const struct of_device_id mb86s70
 	{ .compatible = "fujitsu,mb86s70-gpio" },
 	{ /* sentinel */ }
 };
-MODULE_DEVICE_TABLE(of, mb86s70_gpio_dt_ids);
 
 static struct platform_driver mb86s70_gpio_driver = {
 	.driver = {
@@ -225,8 +221,4 @@ static int __init mb86s70_gpio_init(void
 {
 	return platform_driver_register(&mb86s70_gpio_driver);
 }
-module_init(mb86s70_gpio_init);
-
-MODULE_DESCRIPTION("MB86S7x GPIO Driver");
-MODULE_ALIAS("platform:mb86s70-gpio");
-MODULE_LICENSE("GPL");
+device_initcall(mb86s70_gpio_init);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-mc9s08dz60.c linux-libre-4.7-gnu/drivers/gpio/gpio-mc9s08dz60.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-mc9s08dz60.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-mc9s08dz60.c	2016-07-24 15:23:50.000000000 -0400
@@ -15,7 +15,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/gpio.h>
@@ -111,8 +111,6 @@ static const struct i2c_device_id mc9s08
 	{},
 };
 
-MODULE_DEVICE_TABLE(i2c, mc9s08dz60_id);
-
 static struct i2c_driver mc9s08dz60_i2c_driver = {
 	.driver = {
 		.name = "mc9s08dz60",
@@ -120,10 +118,4 @@ static struct i2c_driver mc9s08dz60_i2c_
 	.probe = mc9s08dz60_probe,
 	.id_table = mc9s08dz60_id,
 };
-
-module_i2c_driver(mc9s08dz60_i2c_driver);
-
-MODULE_AUTHOR("Freescale Semiconductor, Inc. "
-		"Wu Guoxing <b39297@freescale.com>");
-MODULE_DESCRIPTION("mc9s08dz60 gpio function on mx35 3ds board");
-MODULE_LICENSE("GPL v2");
+builtin_i2c_driver(mc9s08dz60_i2c_driver);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-mcp23s08.c linux-libre-4.7-gnu/drivers/gpio/gpio-mcp23s08.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-mcp23s08.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-mcp23s08.c	2016-07-24 15:23:50.000000000 -0400
@@ -77,7 +77,6 @@ struct mcp23s08 {
 	/* lock protects the cached values */
 	struct mutex		lock;
 	struct mutex		irq_lock;
-	struct irq_domain	*irq_domain;
 
 	struct gpio_chip	chip;
 
@@ -96,11 +95,6 @@ struct mcp23s08_driver_data {
 	struct mcp23s08		chip[];
 };
 
-/* This lock class tells lockdep that GPIO irqs are in a different
- * category than their parents, so it won't report false recursion.
- */
-static struct lock_class_key gpio_lock_class;
-
 /*----------------------------------------------------------------------*/
 
 #if IS_ENABLED(CONFIG_I2C)
@@ -368,8 +362,9 @@ static irqreturn_t mcp23s08_irq(int irq,
 	for (i = 0; i < mcp->chip.ngpio; i++) {
 		if ((BIT(i) & mcp->cache[MCP_INTF]) &&
 		    ((BIT(i) & intcap & mcp->irq_rise) ||
-		     (mcp->irq_fall & ~intcap & BIT(i)))) {
-			child_irq = irq_find_mapping(mcp->irq_domain, i);
+		     (mcp->irq_fall & ~intcap & BIT(i)) ||
+		     (BIT(i) & mcp->cache[MCP_INTCON]))) {
+			child_irq = irq_find_mapping(mcp->chip.irqdomain, i);
 			handle_nested_irq(child_irq);
 		}
 	}
@@ -377,16 +372,10 @@ static irqreturn_t mcp23s08_irq(int irq,
 	return IRQ_HANDLED;
 }
 
-static int mcp23s08_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-	struct mcp23s08 *mcp = gpiochip_get_data(chip);
-
-	return irq_find_mapping(mcp->irq_domain, offset);
-}
-
 static void mcp23s08_irq_mask(struct irq_data *data)
 {
-	struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data);
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
+	struct mcp23s08 *mcp = gpiochip_get_data(gc);
 	unsigned int pos = data->hwirq;
 
 	mcp->cache[MCP_GPINTEN] &= ~BIT(pos);
@@ -394,7 +383,8 @@ static void mcp23s08_irq_mask(struct irq
 
 static void mcp23s08_irq_unmask(struct irq_data *data)
 {
-	struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data);
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
+	struct mcp23s08 *mcp = gpiochip_get_data(gc);
 	unsigned int pos = data->hwirq;
 
 	mcp->cache[MCP_GPINTEN] |= BIT(pos);
@@ -402,7 +392,8 @@ static void mcp23s08_irq_unmask(struct i
 
 static int mcp23s08_irq_set_type(struct irq_data *data, unsigned int type)
 {
-	struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data);
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
+	struct mcp23s08 *mcp = gpiochip_get_data(gc);
 	unsigned int pos = data->hwirq;
 	int status = 0;
 
@@ -418,6 +409,12 @@ static int mcp23s08_irq_set_type(struct
 		mcp->cache[MCP_INTCON] &= ~BIT(pos);
 		mcp->irq_rise &= ~BIT(pos);
 		mcp->irq_fall |= BIT(pos);
+	} else if (type & IRQ_TYPE_LEVEL_HIGH) {
+		mcp->cache[MCP_INTCON] |= BIT(pos);
+		mcp->cache[MCP_DEFVAL] &= ~BIT(pos);
+	} else if (type & IRQ_TYPE_LEVEL_LOW) {
+		mcp->cache[MCP_INTCON] |= BIT(pos);
+		mcp->cache[MCP_DEFVAL] |= BIT(pos);
 	} else
 		return -EINVAL;
 
@@ -426,14 +423,16 @@ static int mcp23s08_irq_set_type(struct
 
 static void mcp23s08_irq_bus_lock(struct irq_data *data)
 {
-	struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data);
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
+	struct mcp23s08 *mcp = gpiochip_get_data(gc);
 
 	mutex_lock(&mcp->irq_lock);
 }
 
 static void mcp23s08_irq_bus_unlock(struct irq_data *data)
 {
-	struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data);
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
+	struct mcp23s08 *mcp = gpiochip_get_data(gc);
 
 	mutex_lock(&mcp->lock);
 	mcp->ops->write(mcp, MCP_GPINTEN, mcp->cache[MCP_GPINTEN]);
@@ -443,27 +442,6 @@ static void mcp23s08_irq_bus_unlock(stru
 	mutex_unlock(&mcp->irq_lock);
 }
 
-static int mcp23s08_irq_reqres(struct irq_data *data)
-{
-	struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data);
-
-	if (gpiochip_lock_as_irq(&mcp->chip, data->hwirq)) {
-		dev_err(mcp->chip.parent,
-			"unable to lock HW IRQ %lu for IRQ usage\n",
-			data->hwirq);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static void mcp23s08_irq_relres(struct irq_data *data)
-{
-	struct mcp23s08 *mcp = irq_data_get_irq_chip_data(data);
-
-	gpiochip_unlock_as_irq(&mcp->chip, data->hwirq);
-}
-
 static struct irq_chip mcp23s08_irq_chip = {
 	.name = "gpio-mcp23xxx",
 	.irq_mask = mcp23s08_irq_mask,
@@ -471,24 +449,16 @@ static struct irq_chip mcp23s08_irq_chip
 	.irq_set_type = mcp23s08_irq_set_type,
 	.irq_bus_lock = mcp23s08_irq_bus_lock,
 	.irq_bus_sync_unlock = mcp23s08_irq_bus_unlock,
-	.irq_request_resources = mcp23s08_irq_reqres,
-	.irq_release_resources = mcp23s08_irq_relres,
 };
 
 static int mcp23s08_irq_setup(struct mcp23s08 *mcp)
 {
 	struct gpio_chip *chip = &mcp->chip;
-	int err, irq, j;
+	int err;
 	unsigned long irqflags = IRQF_ONESHOT | IRQF_SHARED;
 
 	mutex_init(&mcp->irq_lock);
 
-	mcp->irq_domain = irq_domain_add_linear(chip->parent->of_node,
-						chip->ngpio,
-						&irq_domain_simple_ops, mcp);
-	if (!mcp->irq_domain)
-		return -ENODEV;
-
 	if (mcp->irq_active_high)
 		irqflags |= IRQF_TRIGGER_HIGH;
 	else
@@ -503,30 +473,23 @@ static int mcp23s08_irq_setup(struct mcp
 		return err;
 	}
 
-	chip->to_irq = mcp23s08_gpio_to_irq;
-
-	for (j = 0; j < mcp->chip.ngpio; j++) {
-		irq = irq_create_mapping(mcp->irq_domain, j);
-		irq_set_lockdep_class(irq, &gpio_lock_class);
-		irq_set_chip_data(irq, mcp);
-		irq_set_chip(irq, &mcp23s08_irq_chip);
-		irq_set_nested_thread(irq, true);
-		irq_set_noprobe(irq);
+	err =  gpiochip_irqchip_add(chip,
+				    &mcp23s08_irq_chip,
+				    0,
+				    handle_simple_irq,
+				    IRQ_TYPE_NONE);
+	if (err) {
+		dev_err(chip->parent,
+			"could not connect irqchip to gpiochip: %d\n", err);
+		return err;
 	}
-	return 0;
-}
-
-static void mcp23s08_irq_teardown(struct mcp23s08 *mcp)
-{
-	unsigned int irq, i;
 
-	for (i = 0; i < mcp->chip.ngpio; i++) {
-		irq = irq_find_mapping(mcp->irq_domain, i);
-		if (irq > 0)
-			irq_dispose_mapping(irq);
-	}
+	gpiochip_set_chained_irqchip(chip,
+				     &mcp23s08_irq_chip,
+				     mcp->irq,
+				     NULL);
 
-	irq_domain_remove(mcp->irq_domain);
+	return 0;
 }
 
 /*----------------------------------------------------------------------*/
@@ -721,7 +684,6 @@ static int mcp23s08_probe_one(struct mcp
 	if (mcp->irq && mcp->irq_controller) {
 		status = mcp23s08_irq_setup(mcp);
 		if (status) {
-			mcp23s08_irq_teardown(mcp);
 			goto fail;
 		}
 	}
@@ -847,9 +809,6 @@ static int mcp230xx_remove(struct i2c_cl
 {
 	struct mcp23s08 *mcp = i2c_get_clientdata(client);
 
-	if (client->irq && mcp->irq_controller)
-		mcp23s08_irq_teardown(mcp);
-
 	gpiochip_remove(&mcp->chip);
 	kfree(mcp);
 
@@ -1017,8 +976,6 @@ static int mcp23s08_remove(struct spi_de
 		if (!data->mcp[addr])
 			continue;
 
-		if (spi->irq && data->mcp[addr]->irq_controller)
-			mcp23s08_irq_teardown(data->mcp[addr]);
 		gpiochip_remove(&data->mcp[addr]->chip);
 	}
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-menz127.c linux-libre-4.7-gnu/drivers/gpio/gpio-menz127.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-menz127.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-menz127.c	2016-07-24 15:23:50.000000000 -0400
@@ -35,7 +35,6 @@
 struct men_z127_gpio {
 	struct gpio_chip gc;
 	void __iomem *reg_base;
-	struct mcb_device *mdev;
 	struct resource *mem;
 };
 
@@ -43,7 +42,7 @@ static int men_z127_debounce(struct gpio
 			     unsigned debounce)
 {
 	struct men_z127_gpio *priv = gpiochip_get_data(gc);
-	struct device *dev = &priv->mdev->dev;
+	struct device *dev = gc->parent;
 	unsigned int rnd;
 	u32 db_en, db_cnt;
 
@@ -88,21 +87,25 @@ static int men_z127_debounce(struct gpio
 	return 0;
 }
 
-static int men_z127_request(struct gpio_chip *gc, unsigned gpio_pin)
+static int men_z127_set_single_ended(struct gpio_chip *gc,
+				     unsigned offset,
+				     enum single_ended_mode mode)
 {
 	struct men_z127_gpio *priv = gpiochip_get_data(gc);
 	u32 od_en;
 
-	if (gpio_pin >= gc->ngpio)
-		return -EINVAL;
+	if (mode != LINE_MODE_OPEN_DRAIN &&
+	    mode != LINE_MODE_PUSH_PULL)
+		return -ENOTSUPP;
 
 	spin_lock(&gc->bgpio_lock);
 	od_en = readl(priv->reg_base + MEN_Z127_ODER);
 
-	if (gpiochip_line_is_open_drain(gc, gpio_pin))
-		od_en |= BIT(gpio_pin);
+	if (mode == LINE_MODE_OPEN_DRAIN)
+		od_en |= BIT(offset);
 	else
-		od_en &= ~BIT(gpio_pin);
+		/* Implicitly LINE_MODE_PUSH_PULL */
+		od_en &= ~BIT(offset);
 
 	writel(od_en, priv->reg_base + MEN_Z127_ODER);
 	spin_unlock(&gc->bgpio_lock);
@@ -135,7 +138,6 @@ static int men_z127_probe(struct mcb_dev
 		goto err_release;
 	}
 
-	men_z127_gpio->mdev = mdev;
 	mcb_set_drvdata(mdev, men_z127_gpio);
 
 	ret = bgpio_init(&men_z127_gpio->gc, &mdev->dev, 4,
@@ -148,7 +150,7 @@ static int men_z127_probe(struct mcb_dev
 		goto err_unmap;
 
 	men_z127_gpio->gc.set_debounce = men_z127_debounce;
-	men_z127_gpio->gc.request = men_z127_request;
+	men_z127_gpio->gc.set_single_ended = men_z127_set_single_ended;
 
 	ret = gpiochip_add_data(&men_z127_gpio->gc, men_z127_gpio);
 	if (ret) {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-mmio.c linux-libre-4.7-gnu/drivers/gpio/gpio-mmio.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-mmio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-mmio.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,660 @@
+/*
+ * Generic driver for memory-mapped GPIO controllers.
+ *
+ * Copyright 2008 MontaVista Software, Inc.
+ * Copyright 2008,2010 Anton Vorontsov <cbouatmailru@gmail.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * ....``.```~~~~````.`.`.`.`.```````'',,,.........`````......`.......
+ * ...``                                                         ```````..
+ * ..The simplest form of a GPIO controller that the driver supports is``
+ *  `.just a single "data" register, where GPIO state can be read and/or `
+ *    `,..written. ,,..``~~~~ .....``.`.`.~~.```.`.........``````.```````
+ *        `````````
+                                    ___
+_/~~|___/~|   . ```~~~~~~       ___/___\___     ,~.`.`.`.`````.~~...,,,,...
+__________|~$@~~~        %~    /o*o*o*o*o*o\   .. Implementing such a GPIO .
+o        `                     ~~~~\___/~~~~    ` controller in FPGA is ,.`
+                                                 `....trivial..'~`.```.```
+ *                                                    ```````
+ *  .```````~~~~`..`.``.``.
+ * .  The driver supports  `...       ,..```.`~~~```````````````....````.``,,
+ * .   big-endian notation, just`.  .. A bit more sophisticated controllers ,
+ *  . register the device with -be`. .with a pair of set/clear-bit registers ,
+ *   `.. suffix.  ```~~`````....`.`   . affecting the data register and the .`
+ *     ``.`.``...```                  ```.. output pins are also supported.`
+ *                        ^^             `````.`````````.,``~``~``~~``````
+ *                                                   .                  ^^
+ *   ,..`.`.`...````````````......`.`.`.`.`.`..`.`.`..
+ * .. The expectation is that in at least some cases .    ,-~~~-,
+ *  .this will be used with roll-your-own ASIC/FPGA .`     \   /
+ *  .logic in Verilog or VHDL. ~~~`````````..`````~~`       \ /
+ *  ..````````......```````````                             \o_
+ *                                                           |
+ *                              ^^                          / \
+ *
+ *           ...`````~~`.....``.`..........``````.`.``.```........``.
+ *            `  8, 16, 32 and 64 bits registers are supported, and``.
+ *            . the number of GPIOs is determined by the width of   ~
+ *             .. the registers. ,............```.`.`..`.`.~~~.`.`.`~
+ *               `.......````.```
+ */
+
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/bug.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/compiler.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/log2.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/gpio/driver.h>
+#include <linux/slab.h>
+#include <linux/bitops.h>
+#include <linux/platform_device.h>
+#include <linux/mod_devicetable.h>
+
+static void bgpio_write8(void __iomem *reg, unsigned long data)
+{
+	writeb(data, reg);
+}
+
+static unsigned long bgpio_read8(void __iomem *reg)
+{
+	return readb(reg);
+}
+
+static void bgpio_write16(void __iomem *reg, unsigned long data)
+{
+	writew(data, reg);
+}
+
+static unsigned long bgpio_read16(void __iomem *reg)
+{
+	return readw(reg);
+}
+
+static void bgpio_write32(void __iomem *reg, unsigned long data)
+{
+	writel(data, reg);
+}
+
+static unsigned long bgpio_read32(void __iomem *reg)
+{
+	return readl(reg);
+}
+
+#if BITS_PER_LONG >= 64
+static void bgpio_write64(void __iomem *reg, unsigned long data)
+{
+	writeq(data, reg);
+}
+
+static unsigned long bgpio_read64(void __iomem *reg)
+{
+	return readq(reg);
+}
+#endif /* BITS_PER_LONG >= 64 */
+
+static void bgpio_write16be(void __iomem *reg, unsigned long data)
+{
+	iowrite16be(data, reg);
+}
+
+static unsigned long bgpio_read16be(void __iomem *reg)
+{
+	return ioread16be(reg);
+}
+
+static void bgpio_write32be(void __iomem *reg, unsigned long data)
+{
+	iowrite32be(data, reg);
+}
+
+static unsigned long bgpio_read32be(void __iomem *reg)
+{
+	return ioread32be(reg);
+}
+
+static unsigned long bgpio_pin2mask(struct gpio_chip *gc, unsigned int pin)
+{
+	return BIT(pin);
+}
+
+static unsigned long bgpio_pin2mask_be(struct gpio_chip *gc,
+				       unsigned int pin)
+{
+	return BIT(gc->bgpio_bits - 1 - pin);
+}
+
+static int bgpio_get_set(struct gpio_chip *gc, unsigned int gpio)
+{
+	unsigned long pinmask = gc->pin2mask(gc, gpio);
+
+	if (gc->bgpio_dir & pinmask)
+		return !!(gc->read_reg(gc->reg_set) & pinmask);
+	else
+		return !!(gc->read_reg(gc->reg_dat) & pinmask);
+}
+
+static int bgpio_get(struct gpio_chip *gc, unsigned int gpio)
+{
+	return !!(gc->read_reg(gc->reg_dat) & gc->pin2mask(gc, gpio));
+}
+
+static void bgpio_set_none(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+}
+
+static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+	unsigned long mask = gc->pin2mask(gc, gpio);
+	unsigned long flags;
+
+	spin_lock_irqsave(&gc->bgpio_lock, flags);
+
+	if (val)
+		gc->bgpio_data |= mask;
+	else
+		gc->bgpio_data &= ~mask;
+
+	gc->write_reg(gc->reg_dat, gc->bgpio_data);
+
+	spin_unlock_irqrestore(&gc->bgpio_lock, flags);
+}
+
+static void bgpio_set_with_clear(struct gpio_chip *gc, unsigned int gpio,
+				 int val)
+{
+	unsigned long mask = gc->pin2mask(gc, gpio);
+
+	if (val)
+		gc->write_reg(gc->reg_set, mask);
+	else
+		gc->write_reg(gc->reg_clr, mask);
+}
+
+static void bgpio_set_set(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+	unsigned long mask = gc->pin2mask(gc, gpio);
+	unsigned long flags;
+
+	spin_lock_irqsave(&gc->bgpio_lock, flags);
+
+	if (val)
+		gc->bgpio_data |= mask;
+	else
+		gc->bgpio_data &= ~mask;
+
+	gc->write_reg(gc->reg_set, gc->bgpio_data);
+
+	spin_unlock_irqrestore(&gc->bgpio_lock, flags);
+}
+
+static void bgpio_multiple_get_masks(struct gpio_chip *gc,
+				     unsigned long *mask, unsigned long *bits,
+				     unsigned long *set_mask,
+				     unsigned long *clear_mask)
+{
+	int i;
+
+	*set_mask = 0;
+	*clear_mask = 0;
+
+	for (i = 0; i < gc->bgpio_bits; i++) {
+		if (*mask == 0)
+			break;
+		if (__test_and_clear_bit(i, mask)) {
+			if (test_bit(i, bits))
+				*set_mask |= gc->pin2mask(gc, i);
+			else
+				*clear_mask |= gc->pin2mask(gc, i);
+		}
+	}
+}
+
+static void bgpio_set_multiple_single_reg(struct gpio_chip *gc,
+					  unsigned long *mask,
+					  unsigned long *bits,
+					  void __iomem *reg)
+{
+	unsigned long flags;
+	unsigned long set_mask, clear_mask;
+
+	spin_lock_irqsave(&gc->bgpio_lock, flags);
+
+	bgpio_multiple_get_masks(gc, mask, bits, &set_mask, &clear_mask);
+
+	gc->bgpio_data |= set_mask;
+	gc->bgpio_data &= ~clear_mask;
+
+	gc->write_reg(reg, gc->bgpio_data);
+
+	spin_unlock_irqrestore(&gc->bgpio_lock, flags);
+}
+
+static void bgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask,
+			       unsigned long *bits)
+{
+	bgpio_set_multiple_single_reg(gc, mask, bits, gc->reg_dat);
+}
+
+static void bgpio_set_multiple_set(struct gpio_chip *gc, unsigned long *mask,
+				   unsigned long *bits)
+{
+	bgpio_set_multiple_single_reg(gc, mask, bits, gc->reg_set);
+}
+
+static void bgpio_set_multiple_with_clear(struct gpio_chip *gc,
+					  unsigned long *mask,
+					  unsigned long *bits)
+{
+	unsigned long set_mask, clear_mask;
+
+	bgpio_multiple_get_masks(gc, mask, bits, &set_mask, &clear_mask);
+
+	if (set_mask)
+		gc->write_reg(gc->reg_set, set_mask);
+	if (clear_mask)
+		gc->write_reg(gc->reg_clr, clear_mask);
+}
+
+static int bgpio_simple_dir_in(struct gpio_chip *gc, unsigned int gpio)
+{
+	return 0;
+}
+
+static int bgpio_dir_out_err(struct gpio_chip *gc, unsigned int gpio,
+				int val)
+{
+	return -EINVAL;
+}
+
+static int bgpio_simple_dir_out(struct gpio_chip *gc, unsigned int gpio,
+				int val)
+{
+	gc->set(gc, gpio, val);
+
+	return 0;
+}
+
+static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&gc->bgpio_lock, flags);
+
+	gc->bgpio_dir &= ~gc->pin2mask(gc, gpio);
+	gc->write_reg(gc->reg_dir, gc->bgpio_dir);
+
+	spin_unlock_irqrestore(&gc->bgpio_lock, flags);
+
+	return 0;
+}
+
+static int bgpio_get_dir(struct gpio_chip *gc, unsigned int gpio)
+{
+	/* Return 0 if output, 1 of input */
+	return !(gc->read_reg(gc->reg_dir) & gc->pin2mask(gc, gpio));
+}
+
+static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+	unsigned long flags;
+
+	gc->set(gc, gpio, val);
+
+	spin_lock_irqsave(&gc->bgpio_lock, flags);
+
+	gc->bgpio_dir |= gc->pin2mask(gc, gpio);
+	gc->write_reg(gc->reg_dir, gc->bgpio_dir);
+
+	spin_unlock_irqrestore(&gc->bgpio_lock, flags);
+
+	return 0;
+}
+
+static int bgpio_dir_in_inv(struct gpio_chip *gc, unsigned int gpio)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&gc->bgpio_lock, flags);
+
+	gc->bgpio_dir |= gc->pin2mask(gc, gpio);
+	gc->write_reg(gc->reg_dir, gc->bgpio_dir);
+
+	spin_unlock_irqrestore(&gc->bgpio_lock, flags);
+
+	return 0;
+}
+
+static int bgpio_dir_out_inv(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+	unsigned long flags;
+
+	gc->set(gc, gpio, val);
+
+	spin_lock_irqsave(&gc->bgpio_lock, flags);
+
+	gc->bgpio_dir &= ~gc->pin2mask(gc, gpio);
+	gc->write_reg(gc->reg_dir, gc->bgpio_dir);
+
+	spin_unlock_irqrestore(&gc->bgpio_lock, flags);
+
+	return 0;
+}
+
+static int bgpio_get_dir_inv(struct gpio_chip *gc, unsigned int gpio)
+{
+	/* Return 0 if output, 1 if input */
+	return !!(gc->read_reg(gc->reg_dir) & gc->pin2mask(gc, gpio));
+}
+
+static int bgpio_setup_accessors(struct device *dev,
+				 struct gpio_chip *gc,
+				 bool bit_be,
+				 bool byte_be)
+{
+
+	switch (gc->bgpio_bits) {
+	case 8:
+		gc->read_reg	= bgpio_read8;
+		gc->write_reg	= bgpio_write8;
+		break;
+	case 16:
+		if (byte_be) {
+			gc->read_reg	= bgpio_read16be;
+			gc->write_reg	= bgpio_write16be;
+		} else {
+			gc->read_reg	= bgpio_read16;
+			gc->write_reg	= bgpio_write16;
+		}
+		break;
+	case 32:
+		if (byte_be) {
+			gc->read_reg	= bgpio_read32be;
+			gc->write_reg	= bgpio_write32be;
+		} else {
+			gc->read_reg	= bgpio_read32;
+			gc->write_reg	= bgpio_write32;
+		}
+		break;
+#if BITS_PER_LONG >= 64
+	case 64:
+		if (byte_be) {
+			dev_err(dev,
+				"64 bit big endian byte order unsupported\n");
+			return -EINVAL;
+		} else {
+			gc->read_reg	= bgpio_read64;
+			gc->write_reg	= bgpio_write64;
+		}
+		break;
+#endif /* BITS_PER_LONG >= 64 */
+	default:
+		dev_err(dev, "unsupported data width %u bits\n", gc->bgpio_bits);
+		return -EINVAL;
+	}
+
+	gc->pin2mask = bit_be ? bgpio_pin2mask_be : bgpio_pin2mask;
+
+	return 0;
+}
+
+/*
+ * Create the device and allocate the resources.  For setting GPIO's there are
+ * three supported configurations:
+ *
+ *	- single input/output register resource (named "dat").
+ *	- set/clear pair (named "set" and "clr").
+ *	- single output register resource and single input resource ("set" and
+ *	dat").
+ *
+ * For the single output register, this drives a 1 by setting a bit and a zero
+ * by clearing a bit.  For the set clr pair, this drives a 1 by setting a bit
+ * in the set register and clears it by setting a bit in the clear register.
+ * The configuration is detected by which resources are present.
+ *
+ * For setting the GPIO direction, there are three supported configurations:
+ *
+ *	- simple bidirection GPIO that requires no configuration.
+ *	- an output direction register (named "dirout") where a 1 bit
+ *	indicates the GPIO is an output.
+ *	- an input direction register (named "dirin") where a 1 bit indicates
+ *	the GPIO is an input.
+ */
+static int bgpio_setup_io(struct gpio_chip *gc,
+			  void __iomem *dat,
+			  void __iomem *set,
+			  void __iomem *clr,
+			  unsigned long flags)
+{
+
+	gc->reg_dat = dat;
+	if (!gc->reg_dat)
+		return -EINVAL;
+
+	if (set && clr) {
+		gc->reg_set = set;
+		gc->reg_clr = clr;
+		gc->set = bgpio_set_with_clear;
+		gc->set_multiple = bgpio_set_multiple_with_clear;
+	} else if (set && !clr) {
+		gc->reg_set = set;
+		gc->set = bgpio_set_set;
+		gc->set_multiple = bgpio_set_multiple_set;
+	} else if (flags & BGPIOF_NO_OUTPUT) {
+		gc->set = bgpio_set_none;
+		gc->set_multiple = NULL;
+	} else {
+		gc->set = bgpio_set;
+		gc->set_multiple = bgpio_set_multiple;
+	}
+
+	if (!(flags & BGPIOF_UNREADABLE_REG_SET) &&
+	    (flags & BGPIOF_READ_OUTPUT_REG_SET))
+		gc->get = bgpio_get_set;
+	else
+		gc->get = bgpio_get;
+
+	return 0;
+}
+
+static int bgpio_setup_direction(struct gpio_chip *gc,
+				 void __iomem *dirout,
+				 void __iomem *dirin,
+				 unsigned long flags)
+{
+	if (dirout && dirin) {
+		return -EINVAL;
+	} else if (dirout) {
+		gc->reg_dir = dirout;
+		gc->direction_output = bgpio_dir_out;
+		gc->direction_input = bgpio_dir_in;
+		gc->get_direction = bgpio_get_dir;
+	} else if (dirin) {
+		gc->reg_dir = dirin;
+		gc->direction_output = bgpio_dir_out_inv;
+		gc->direction_input = bgpio_dir_in_inv;
+		gc->get_direction = bgpio_get_dir_inv;
+	} else {
+		if (flags & BGPIOF_NO_OUTPUT)
+			gc->direction_output = bgpio_dir_out_err;
+		else
+			gc->direction_output = bgpio_simple_dir_out;
+		gc->direction_input = bgpio_simple_dir_in;
+	}
+
+	return 0;
+}
+
+static int bgpio_request(struct gpio_chip *chip, unsigned gpio_pin)
+{
+	if (gpio_pin < chip->ngpio)
+		return 0;
+
+	return -EINVAL;
+}
+
+int bgpio_init(struct gpio_chip *gc, struct device *dev,
+	       unsigned long sz, void __iomem *dat, void __iomem *set,
+	       void __iomem *clr, void __iomem *dirout, void __iomem *dirin,
+	       unsigned long flags)
+{
+	int ret;
+
+	if (!is_power_of_2(sz))
+		return -EINVAL;
+
+	gc->bgpio_bits = sz * 8;
+	if (gc->bgpio_bits > BITS_PER_LONG)
+		return -EINVAL;
+
+	spin_lock_init(&gc->bgpio_lock);
+	gc->parent = dev;
+	gc->label = dev_name(dev);
+	gc->base = -1;
+	gc->ngpio = gc->bgpio_bits;
+	gc->request = bgpio_request;
+
+	ret = bgpio_setup_io(gc, dat, set, clr, flags);
+	if (ret)
+		return ret;
+
+	ret = bgpio_setup_accessors(dev, gc, flags & BGPIOF_BIG_ENDIAN,
+				    flags & BGPIOF_BIG_ENDIAN_BYTE_ORDER);
+	if (ret)
+		return ret;
+
+	ret = bgpio_setup_direction(gc, dirout, dirin, flags);
+	if (ret)
+		return ret;
+
+	gc->bgpio_data = gc->read_reg(gc->reg_dat);
+	if (gc->set == bgpio_set_set &&
+			!(flags & BGPIOF_UNREADABLE_REG_SET))
+		gc->bgpio_data = gc->read_reg(gc->reg_set);
+	if (gc->reg_dir && !(flags & BGPIOF_UNREADABLE_REG_DIR))
+		gc->bgpio_dir = gc->read_reg(gc->reg_dir);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(bgpio_init);
+
+#if IS_ENABLED(CONFIG_GPIO_GENERIC_PLATFORM)
+
+static void __iomem *bgpio_map(struct platform_device *pdev,
+			       const char *name,
+			       resource_size_t sane_sz)
+{
+	struct resource *r;
+	resource_size_t sz;
+
+	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
+	if (!r)
+		return NULL;
+
+	sz = resource_size(r);
+	if (sz != sane_sz)
+		return IOMEM_ERR_PTR(-EINVAL);
+
+	return devm_ioremap_resource(&pdev->dev, r);
+}
+
+static int bgpio_pdev_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *r;
+	void __iomem *dat;
+	void __iomem *set;
+	void __iomem *clr;
+	void __iomem *dirout;
+	void __iomem *dirin;
+	unsigned long sz;
+	unsigned long flags = pdev->id_entry->driver_data;
+	int err;
+	struct gpio_chip *gc;
+	struct bgpio_pdata *pdata = dev_get_platdata(dev);
+
+	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat");
+	if (!r)
+		return -EINVAL;
+
+	sz = resource_size(r);
+
+	dat = bgpio_map(pdev, "dat", sz);
+	if (IS_ERR(dat))
+		return PTR_ERR(dat);
+
+	set = bgpio_map(pdev, "set", sz);
+	if (IS_ERR(set))
+		return PTR_ERR(set);
+
+	clr = bgpio_map(pdev, "clr", sz);
+	if (IS_ERR(clr))
+		return PTR_ERR(clr);
+
+	dirout = bgpio_map(pdev, "dirout", sz);
+	if (IS_ERR(dirout))
+		return PTR_ERR(dirout);
+
+	dirin = bgpio_map(pdev, "dirin", sz);
+	if (IS_ERR(dirin))
+		return PTR_ERR(dirin);
+
+	gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL);
+	if (!gc)
+		return -ENOMEM;
+
+	err = bgpio_init(gc, dev, sz, dat, set, clr, dirout, dirin, flags);
+	if (err)
+		return err;
+
+	if (pdata) {
+		if (pdata->label)
+			gc->label = pdata->label;
+		gc->base = pdata->base;
+		if (pdata->ngpio > 0)
+			gc->ngpio = pdata->ngpio;
+	}
+
+	platform_set_drvdata(pdev, gc);
+
+	return devm_gpiochip_add_data(&pdev->dev, gc, NULL);
+}
+
+static const struct platform_device_id bgpio_id_table[] = {
+	{
+		.name		= "basic-mmio-gpio",
+		.driver_data	= 0,
+	}, {
+		.name		= "basic-mmio-gpio-be",
+		.driver_data	= BGPIOF_BIG_ENDIAN,
+	},
+	{ }
+};
+MODULE_DEVICE_TABLE(platform, bgpio_id_table);
+
+static struct platform_driver bgpio_driver = {
+	.driver = {
+		.name = "basic-mmio-gpio",
+	},
+	.id_table = bgpio_id_table,
+	.probe = bgpio_pdev_probe,
+};
+
+module_platform_driver(bgpio_driver);
+
+#endif /* CONFIG_GPIO_GENERIC_PLATFORM */
+
+MODULE_DESCRIPTION("Driver for basic memory-mapped GPIO controllers");
+MODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-moxart.c linux-libre-4.7-gnu/drivers/gpio/gpio-moxart.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-moxart.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-moxart.c	2016-07-24 15:23:50.000000000 -0400
@@ -15,7 +15,6 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
-#include <linux/module.h>
 #include <linux/of_address.h>
 #include <linux/of_gpio.h>
 #include <linux/pinctrl/consumer.h>
@@ -82,8 +81,4 @@ static struct platform_driver moxart_gpi
 	},
 	.probe	= moxart_gpio_probe,
 };
-module_platform_driver(moxart_gpio_driver);
-
-MODULE_DESCRIPTION("MOXART GPIO chip driver");
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jonas Jensen <jonas.jensen@gmail.com>");
+builtin_platform_driver(moxart_gpio_driver);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-mvebu.c linux-libre-4.7-gnu/drivers/gpio/gpio-mvebu.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-mvebu.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-mvebu.c	2016-07-24 15:23:50.000000000 -0400
@@ -34,7 +34,7 @@
  */
 
 #include <linux/err.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/gpio.h>
 #include <linux/irq.h>
 #include <linux/slab.h>
@@ -557,7 +557,6 @@ static const struct of_device_id mvebu_g
 		/* sentinel */
 	},
 };
-MODULE_DEVICE_TABLE(of, mvebu_gpio_of_match);
 
 static int mvebu_gpio_suspend(struct platform_device *pdev, pm_message_t state)
 {
@@ -838,4 +837,4 @@ static struct platform_driver mvebu_gpio
 	.suspend        = mvebu_gpio_suspend,
 	.resume         = mvebu_gpio_resume,
 };
-module_platform_driver(mvebu_gpio_driver);
+builtin_platform_driver(mvebu_gpio_driver);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-octeon.c linux-libre-4.7-gnu/drivers/gpio/gpio-octeon.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-octeon.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-octeon.c	2016-07-24 15:23:50.000000000 -0400
@@ -83,6 +83,7 @@ static int octeon_gpio_probe(struct plat
 	struct octeon_gpio *gpio;
 	struct gpio_chip *chip;
 	struct resource *res_mem;
+	void __iomem *reg_base;
 	int err = 0;
 
 	gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
@@ -91,21 +92,11 @@ static int octeon_gpio_probe(struct plat
 	chip = &gpio->chip;
 
 	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (res_mem == NULL) {
-		dev_err(&pdev->dev, "found no memory resource\n");
-		err = -ENXIO;
-		goto out;
-	}
-	if (!devm_request_mem_region(&pdev->dev, res_mem->start,
-					resource_size(res_mem),
-				     res_mem->name)) {
-		dev_err(&pdev->dev, "request_mem_region failed\n");
-		err = -ENXIO;
-		goto out;
-	}
-	gpio->register_base = (u64)devm_ioremap(&pdev->dev, res_mem->start,
-						resource_size(res_mem));
+	reg_base = devm_ioremap_resource(&pdev->dev, res_mem);
+	if (IS_ERR(reg_base))
+		return PTR_ERR(reg_base);
 
+	gpio->register_base = (u64)reg_base;
 	pdev->dev.platform_data = chip;
 	chip->label = "octeon-gpio";
 	chip->parent = &pdev->dev;
@@ -119,14 +110,13 @@ static int octeon_gpio_probe(struct plat
 	chip->set = octeon_gpio_set;
 	err = devm_gpiochip_add_data(&pdev->dev, chip, gpio);
 	if (err)
-		goto out;
+		return err;
 
 	dev_info(&pdev->dev, "OCTEON GPIO driver probed.\n");
-out:
-	return err;
+	return 0;
 }
 
-static struct of_device_id octeon_gpio_match[] = {
+static const struct of_device_id octeon_gpio_match[] = {
 	{
 		.compatible = "cavium,octeon-3860-gpio",
 	},
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-omap.c linux-libre-4.7-gnu/drivers/gpio/gpio-omap.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-omap.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-omap.c	2016-07-24 15:23:50.000000000 -0400
@@ -611,51 +611,12 @@ static inline void omap_set_gpio_irqenab
 		omap_disable_gpio_irqbank(bank, BIT(offset));
 }
 
-/*
- * Note that ENAWAKEUP needs to be enabled in GPIO_SYSCONFIG register.
- * 1510 does not seem to have a wake-up register. If JTAG is connected
- * to the target, system will wake up always on GPIO events. While
- * system is running all registered GPIO interrupts need to have wake-up
- * enabled. When system is suspended, only selected GPIO interrupts need
- * to have wake-up enabled.
- */
-static int omap_set_gpio_wakeup(struct gpio_bank *bank, unsigned offset,
-				int enable)
-{
-	u32 gpio_bit = BIT(offset);
-	unsigned long flags;
-
-	if (bank->non_wakeup_gpios & gpio_bit) {
-		dev_err(bank->chip.parent,
-			"Unable to modify wakeup on non-wakeup GPIO%d\n",
-			offset);
-		return -EINVAL;
-	}
-
-	raw_spin_lock_irqsave(&bank->lock, flags);
-	if (enable)
-		bank->context.wake_en |= gpio_bit;
-	else
-		bank->context.wake_en &= ~gpio_bit;
-
-	writel_relaxed(bank->context.wake_en, bank->base + bank->regs->wkup_en);
-	raw_spin_unlock_irqrestore(&bank->lock, flags);
-
-	return 0;
-}
-
 /* Use disable_irq_wake() and enable_irq_wake() functions from drivers */
 static int omap_gpio_wake_enable(struct irq_data *d, unsigned int enable)
 {
 	struct gpio_bank *bank = omap_irq_data_get_bank(d);
-	unsigned offset = d->hwirq;
-	int ret;
-
-	ret = omap_set_gpio_wakeup(bank, offset, enable);
-	if (!ret)
-		ret = irq_set_irq_wake(bank->irq, enable);
 
-	return ret;
+	return irq_set_irq_wake(bank->irq, enable);
 }
 
 static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)
@@ -1187,6 +1148,7 @@ static int omap_gpio_probe(struct platfo
 	irqc->irq_bus_lock = omap_gpio_irq_bus_lock,
 	irqc->irq_bus_sync_unlock = gpio_irq_bus_sync_unlock,
 	irqc->name = dev_name(&pdev->dev);
+	irqc->flags = IRQCHIP_MASK_ON_SUSPEND;
 
 	bank->irq = platform_get_irq(pdev, 0);
 	if (bank->irq <= 0) {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-palmas.c linux-libre-4.7-gnu/drivers/gpio/gpio-palmas.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-palmas.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-palmas.c	2016-07-24 15:23:50.000000000 -0400
@@ -20,7 +20,7 @@
 
 #include <linux/gpio.h>
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/mfd/palmas.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
@@ -218,14 +218,3 @@ static int __init palmas_gpio_init(void)
 	return platform_driver_register(&palmas_gpio_driver);
 }
 subsys_initcall(palmas_gpio_init);
-
-static void __exit palmas_gpio_exit(void)
-{
-	platform_driver_unregister(&palmas_gpio_driver);
-}
-module_exit(palmas_gpio_exit);
-
-MODULE_ALIAS("platform:palmas-gpio");
-MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
-MODULE_DESCRIPTION("GPIO driver for TI Palmas series PMICs");
-MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-pca953x.c linux-libre-4.7-gnu/drivers/gpio/gpio-pca953x.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-pca953x.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-pca953x.c	2016-07-24 15:23:50.000000000 -0400
@@ -38,8 +38,13 @@
 #define PCA957X_MSK		6
 #define PCA957X_INTS		7
 
+#define PCAL953X_IN_LATCH	34
+#define PCAL953X_INT_MASK	37
+#define PCAL953X_INT_STAT	38
+
 #define PCA_GPIO_MASK		0x00FF
 #define PCA_INT			0x0100
+#define PCA_PCAL			0x0200
 #define PCA953X_TYPE		0x1000
 #define PCA957X_TYPE		0x2000
 #define PCA_TYPE_MASK		0xF000
@@ -77,7 +82,7 @@ static const struct i2c_device_id pca953
 MODULE_DEVICE_TABLE(i2c, pca953x_id);
 
 static const struct acpi_device_id pca953x_acpi_ids[] = {
-	{ "INT3491", 16 | PCA953X_TYPE | PCA_INT, },
+	{ "INT3491", 16 | PCA953X_TYPE | PCA_INT | PCA_PCAL, },
 	{ }
 };
 MODULE_DEVICE_TABLE(acpi, pca953x_acpi_ids);
@@ -437,6 +442,18 @@ static void pca953x_irq_bus_sync_unlock(
 	struct pca953x_chip *chip = gpiochip_get_data(gc);
 	u8 new_irqs;
 	int level, i;
+	u8 invert_irq_mask[MAX_BANK];
+
+	if (chip->driver_data & PCA_PCAL) {
+		/* Enable latch on interrupt-enabled inputs */
+		pca953x_write_regs(chip, PCAL953X_IN_LATCH, chip->irq_mask);
+
+		for (i = 0; i < NBANK(chip); i++)
+			invert_irq_mask[i] = ~chip->irq_mask[i];
+
+		/* Unmask enabled interrupts */
+		pca953x_write_regs(chip, PCAL953X_INT_MASK, invert_irq_mask);
+	}
 
 	/* Look for any newly setup interrupt */
 	for (i = 0; i < NBANK(chip); i++) {
@@ -498,6 +515,29 @@ static bool pca953x_irq_pending(struct p
 	u8 trigger[MAX_BANK];
 	int ret, i, offset = 0;
 
+	if (chip->driver_data & PCA_PCAL) {
+		/* Read the current interrupt status from the device */
+		ret = pca953x_read_regs(chip, PCAL953X_INT_STAT, trigger);
+		if (ret)
+			return false;
+
+		/* Check latched inputs and clear interrupt status */
+		ret = pca953x_read_regs(chip, PCA953X_INPUT, cur_stat);
+		if (ret)
+			return false;
+
+		for (i = 0; i < NBANK(chip); i++) {
+			/* Apply filter for rising/falling edge selection */
+			pending[i] = (~cur_stat[i] & chip->irq_trig_fall[i]) |
+				(cur_stat[i] & chip->irq_trig_raise[i]);
+			pending[i] &= trigger[i];
+			if (pending[i])
+				pending_seen = true;
+		}
+
+		return pending_seen;
+	}
+
 	switch (chip->chip_type) {
 	case PCA953X_TYPE:
 		offset = PCA953X_INPUT;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-pl061.c linux-libre-4.7-gnu/drivers/gpio/gpio-pl061.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-pl061.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-pl061.c	2016-07-24 15:23:50.000000000 -0400
@@ -1,6 +1,8 @@
 /*
  * Copyright (C) 2008, 2009 Provigent Ltd.
  *
+ * Author: Baruch Siach <baruch@tkos.co.il>
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
@@ -11,7 +13,7 @@
  */
 #include <linux/spinlock.h>
 #include <linux/errno.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/io.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
@@ -59,15 +61,19 @@ struct pl061_gpio {
 #endif
 };
 
+static int pl061_get_direction(struct gpio_chip *gc, unsigned offset)
+{
+	struct pl061_gpio *chip = gpiochip_get_data(gc);
+
+	return !(readb(chip->base + GPIODIR) & BIT(offset));
+}
+
 static int pl061_direction_input(struct gpio_chip *gc, unsigned offset)
 {
 	struct pl061_gpio *chip = gpiochip_get_data(gc);
 	unsigned long flags;
 	unsigned char gpiodir;
 
-	if (offset >= gc->ngpio)
-		return -EINVAL;
-
 	spin_lock_irqsave(&chip->lock, flags);
 	gpiodir = readb(chip->base + GPIODIR);
 	gpiodir &= ~(BIT(offset));
@@ -84,9 +90,6 @@ static int pl061_direction_output(struct
 	unsigned long flags;
 	unsigned char gpiodir;
 
-	if (offset >= gc->ngpio)
-		return -EINVAL;
-
 	spin_lock_irqsave(&chip->lock, flags);
 	writeb(!!value << offset, chip->base + (BIT(offset + 2)));
 	gpiodir = readb(chip->base + GPIODIR);
@@ -319,6 +322,7 @@ static int pl061_probe(struct amba_devic
 		chip->gc.free = gpiochip_generic_free;
 	}
 
+	chip->gc.get_direction = pl061_get_direction;
 	chip->gc.direction_input = pl061_direction_input;
 	chip->gc.direction_output = pl061_direction_output;
 	chip->gc.get = pl061_get_value;
@@ -429,8 +433,6 @@ static struct amba_id pl061_ids[] = {
 	{ 0, 0 },
 };
 
-MODULE_DEVICE_TABLE(amba, pl061_ids);
-
 static struct amba_driver pl061_gpio_driver = {
 	.drv = {
 		.name	= "pl061_gpio",
@@ -446,8 +448,4 @@ static int __init pl061_gpio_init(void)
 {
 	return amba_driver_register(&pl061_gpio_driver);
 }
-module_init(pl061_gpio_init);
-
-MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
-MODULE_DESCRIPTION("PL061 GPIO driver");
-MODULE_LICENSE("GPL");
+device_initcall(pl061_gpio_init);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-rc5t583.c linux-libre-4.7-gnu/drivers/gpio/gpio-rc5t583.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-rc5t583.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-rc5t583.c	2016-07-24 15:23:50.000000000 -0400
@@ -23,7 +23,6 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/device.h>
 #include <linux/gpio.h>
@@ -152,14 +151,3 @@ static int __init rc5t583_gpio_init(void
 	return platform_driver_register(&rc5t583_gpio_driver);
 }
 subsys_initcall(rc5t583_gpio_init);
-
-static void __exit rc5t583_gpio_exit(void)
-{
-	platform_driver_unregister(&rc5t583_gpio_driver);
-}
-module_exit(rc5t583_gpio_exit);
-
-MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
-MODULE_DESCRIPTION("GPIO interface for RC5T583");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:rc5t583-gpio");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-rcar.c linux-libre-4.7-gnu/drivers/gpio/gpio-rcar.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-rcar.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-rcar.c	2016-07-24 15:23:50.000000000 -0400
@@ -284,6 +284,25 @@ static void gpio_rcar_set(struct gpio_ch
 	spin_unlock_irqrestore(&p->lock, flags);
 }
 
+static void gpio_rcar_set_multiple(struct gpio_chip *chip, unsigned long *mask,
+				   unsigned long *bits)
+{
+	struct gpio_rcar_priv *p = gpiochip_get_data(chip);
+	unsigned long flags;
+	u32 val, bankmask;
+
+	bankmask = mask[0] & GENMASK(chip->ngpio - 1, 0);
+	if (!bankmask)
+		return;
+
+	spin_lock_irqsave(&p->lock, flags);
+	val = gpio_rcar_read(p, OUTDT);
+	val &= ~bankmask;
+	val |= (bankmask & bits[0]);
+	gpio_rcar_write(p, OUTDT, val);
+	spin_unlock_irqrestore(&p->lock, flags);
+}
+
 static int gpio_rcar_direction_output(struct gpio_chip *chip, unsigned offset,
 				      int value)
 {
@@ -425,6 +444,7 @@ static int gpio_rcar_probe(struct platfo
 	gpio_chip->get = gpio_rcar_get;
 	gpio_chip->direction_output = gpio_rcar_direction_output;
 	gpio_chip->set = gpio_rcar_set;
+	gpio_chip->set_multiple = gpio_rcar_set_multiple;
 	gpio_chip->label = name;
 	gpio_chip->parent = dev;
 	gpio_chip->owner = THIS_MODULE;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-sch.c linux-libre-4.7-gnu/drivers/gpio/gpio-sch.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-sch.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-sch.c	2016-07-24 15:23:50.000000000 -0400
@@ -61,9 +61,8 @@ static unsigned sch_gpio_bit(struct sch_
 	return gpio % 8;
 }
 
-static int sch_gpio_reg_get(struct gpio_chip *gc, unsigned gpio, unsigned reg)
+static int sch_gpio_reg_get(struct sch_gpio *sch, unsigned gpio, unsigned reg)
 {
-	struct sch_gpio *sch = gpiochip_get_data(gc);
 	unsigned short offset, bit;
 	u8 reg_val;
 
@@ -75,10 +74,9 @@ static int sch_gpio_reg_get(struct gpio_
 	return reg_val;
 }
 
-static void sch_gpio_reg_set(struct gpio_chip *gc, unsigned gpio, unsigned reg,
+static void sch_gpio_reg_set(struct sch_gpio *sch, unsigned gpio, unsigned reg,
 			     int val)
 {
-	struct sch_gpio *sch = gpiochip_get_data(gc);
 	unsigned short offset, bit;
 	u8 reg_val;
 
@@ -98,14 +96,15 @@ static int sch_gpio_direction_in(struct
 	struct sch_gpio *sch = gpiochip_get_data(gc);
 
 	spin_lock(&sch->lock);
-	sch_gpio_reg_set(gc, gpio_num, GIO, 1);
+	sch_gpio_reg_set(sch, gpio_num, GIO, 1);
 	spin_unlock(&sch->lock);
 	return 0;
 }
 
 static int sch_gpio_get(struct gpio_chip *gc, unsigned gpio_num)
 {
-	return sch_gpio_reg_get(gc, gpio_num, GLV);
+	struct sch_gpio *sch = gpiochip_get_data(gc);
+	return sch_gpio_reg_get(sch, gpio_num, GLV);
 }
 
 static void sch_gpio_set(struct gpio_chip *gc, unsigned gpio_num, int val)
@@ -113,7 +112,7 @@ static void sch_gpio_set(struct gpio_chi
 	struct sch_gpio *sch = gpiochip_get_data(gc);
 
 	spin_lock(&sch->lock);
-	sch_gpio_reg_set(gc, gpio_num, GLV, val);
+	sch_gpio_reg_set(sch, gpio_num, GLV, val);
 	spin_unlock(&sch->lock);
 }
 
@@ -123,7 +122,7 @@ static int sch_gpio_direction_out(struct
 	struct sch_gpio *sch = gpiochip_get_data(gc);
 
 	spin_lock(&sch->lock);
-	sch_gpio_reg_set(gc, gpio_num, GIO, 0);
+	sch_gpio_reg_set(sch, gpio_num, GIO, 0);
 	spin_unlock(&sch->lock);
 
 	/*
@@ -182,13 +181,13 @@ static int sch_gpio_probe(struct platfor
 		 * GPIO7 is configured by the CMC as SLPIOVR
 		 * Enable GPIO[9:8] core powered gpios explicitly
 		 */
-		sch_gpio_reg_set(&sch->chip, 8, GEN, 1);
-		sch_gpio_reg_set(&sch->chip, 9, GEN, 1);
+		sch_gpio_reg_set(sch, 8, GEN, 1);
+		sch_gpio_reg_set(sch, 9, GEN, 1);
 		/*
 		 * SUS_GPIO[2:0] enabled by default
 		 * Enable SUS_GPIO3 resume powered gpio explicitly
 		 */
-		sch_gpio_reg_set(&sch->chip, 13, GEN, 1);
+		sch_gpio_reg_set(sch, 13, GEN, 1);
 		break;
 
 	case PCI_DEVICE_ID_INTEL_ITC_LPC:
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-sodaville.c linux-libre-4.7-gnu/drivers/gpio/gpio-sodaville.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-sodaville.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-sodaville.c	2016-07-24 15:23:50.000000000 -0400
@@ -3,6 +3,8 @@
  *
  *  Copyright (c) 2010, 2011 Intel Corporation
  *
+ *  Author: Hans J. Koch <hjk@linutronix.de>
+ *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License 2 as published
  *  by the Free Software Foundation.
@@ -15,7 +17,6 @@
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
-#include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/platform_device.h>
 #include <linux/of_irq.h>
@@ -257,34 +258,17 @@ done:
 	return ret;
 }
 
-static void sdv_gpio_remove(struct pci_dev *pdev)
-{
-	struct sdv_gpio_chip_data *sd = pci_get_drvdata(pdev);
-
-	free_irq(pdev->irq, sd);
-	irq_free_descs(sd->irq_base, SDV_NUM_PUB_GPIOS);
-
-	gpiochip_remove(&sd->chip);
-	pci_release_region(pdev, GPIO_BAR);
-	iounmap(sd->gpio_pub_base);
-	pci_disable_device(pdev);
-	kfree(sd);
-}
-
 static const struct pci_device_id sdv_gpio_pci_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_SDV_GPIO) },
 	{ 0, },
 };
 
 static struct pci_driver sdv_gpio_driver = {
+	.driver = {
+		.suppress_bind_attrs = true,
+	},
 	.name = DRV_NAME,
 	.id_table = sdv_gpio_pci_ids,
 	.probe = sdv_gpio_probe,
-	.remove = sdv_gpio_remove,
 };
-
-module_pci_driver(sdv_gpio_driver);
-
-MODULE_AUTHOR("Hans J. Koch <hjk@linutronix.de>");
-MODULE_DESCRIPTION("GPIO interface for Intel Sodaville SoCs");
-MODULE_LICENSE("GPL v2");
+builtin_pci_driver(sdv_gpio_driver);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-sta2x11.c linux-libre-4.7-gnu/drivers/gpio/gpio-sta2x11.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-sta2x11.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-sta2x11.c	2016-07-24 15:23:50.000000000 -0400
@@ -20,7 +20,7 @@
  *
  */
 
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/gpio.h>
@@ -432,8 +432,4 @@ static struct platform_driver sta2x11_gp
 	},
 	.probe = gsta_probe,
 };
-
-module_platform_driver(sta2x11_gpio_platform_driver);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("sta2x11_gpio GPIO driver");
+builtin_platform_driver(sta2x11_gpio_platform_driver);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-stmpe.c linux-libre-4.7-gnu/drivers/gpio/gpio-stmpe.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-stmpe.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-stmpe.c	2016-07-24 15:23:50.000000000 -0400
@@ -5,7 +5,6 @@
  * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
  */
 
-#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
@@ -413,23 +412,13 @@ out_free:
 	return ret;
 }
 
-static int stmpe_gpio_remove(struct platform_device *pdev)
-{
-	struct stmpe_gpio *stmpe_gpio = platform_get_drvdata(pdev);
-	struct stmpe *stmpe = stmpe_gpio->stmpe;
-
-	gpiochip_remove(&stmpe_gpio->chip);
-	stmpe_disable(stmpe, STMPE_BLOCK_GPIO);
-	kfree(stmpe_gpio);
-
-	return 0;
-}
-
 static struct platform_driver stmpe_gpio_driver = {
-	.driver.name	= "stmpe-gpio",
-	.driver.owner	= THIS_MODULE,
+	.driver = {
+		.suppress_bind_attrs	= true,
+		.name			= "stmpe-gpio",
+		.owner			= THIS_MODULE,
+	},
 	.probe		= stmpe_gpio_probe,
-	.remove		= stmpe_gpio_remove,
 };
 
 static int __init stmpe_gpio_init(void)
@@ -437,13 +426,3 @@ static int __init stmpe_gpio_init(void)
 	return platform_driver_register(&stmpe_gpio_driver);
 }
 subsys_initcall(stmpe_gpio_init);
-
-static void __exit stmpe_gpio_exit(void)
-{
-	platform_driver_unregister(&stmpe_gpio_driver);
-}
-module_exit(stmpe_gpio_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("STMPExxxx GPIO driver");
-MODULE_AUTHOR("Rabin Vincent <rabin.vincent@stericsson.com>");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-sx150x.c linux-libre-4.7-gnu/drivers/gpio/gpio-sx150x.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-sx150x.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-sx150x.c	2016-07-24 15:23:50.000000000 -0400
@@ -1,5 +1,9 @@
 /* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
  *
+ * Driver for Semtech SX150X I2C GPIO Expanders
+ *
+ * Author: Gregory Bean <gbean@codeaurora.org>
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
  * only version 2 as published by the Free Software Foundation.
@@ -19,10 +23,8 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
-#include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
-#include <linux/i2c/sx150x.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
@@ -82,6 +84,57 @@ struct sx150x_device_data {
 	} pri;
 };
 
+/**
+ * struct sx150x_platform_data - config data for SX150x driver
+ * @gpio_base: The index number of the first GPIO assigned to this
+ *             GPIO expander.  The expander will create a block of
+ *             consecutively numbered gpios beginning at the given base,
+ *             with the size of the block depending on the model of the
+ *             expander chip.
+ * @oscio_is_gpo: If set to true, the driver will configure OSCIO as a GPO
+ *                instead of as an oscillator, increasing the size of the
+ *                GP(I)O pool created by this expander by one.  The
+ *                output-only GPO pin will be added at the end of the block.
+ * @io_pullup_ena: A bit-mask which enables or disables the pull-up resistor
+ *                 for each IO line in the expander.  Setting the bit at
+ *                 position n will enable the pull-up for the IO at
+ *                 the corresponding offset.  For chips with fewer than
+ *                 16 IO pins, high-end bits are ignored.
+ * @io_pulldn_ena: A bit-mask which enables-or disables the pull-down
+ *                 resistor for each IO line in the expander. Setting the
+ *                 bit at position n will enable the pull-down for the IO at
+ *                 the corresponding offset.  For chips with fewer than
+ *                 16 IO pins, high-end bits are ignored.
+ * @io_polarity: A bit-mask which enables polarity inversion for each IO line
+ *               in the expander.  Setting the bit at position n inverts
+ *               the polarity of that IO line, while clearing it results
+ *               in normal polarity. For chips with fewer than 16 IO pins,
+ *               high-end bits are ignored.
+ * @irq_summary: The 'summary IRQ' line to which the GPIO expander's INT line
+ *               is connected, via which it reports interrupt events
+ *               across all GPIO lines.  This must be a real,
+ *               pre-existing IRQ line.
+ *               Setting this value < 0 disables the irq_chip functionality
+ *               of the driver.
+ * @irq_base: The first 'virtual IRQ' line at which our block of GPIO-based
+ *            IRQ lines will appear.  Similarly to gpio_base, the expander
+ *            will create a block of irqs beginning at this number.
+ *            This value is ignored if irq_summary is < 0.
+ * @reset_during_probe: If set to true, the driver will trigger a full
+ *                      reset of the chip at the beginning of the probe
+ *                      in order to place it in a known state.
+ */
+struct sx150x_platform_data {
+	unsigned gpio_base;
+	bool     oscio_is_gpo;
+	u16      io_pullup_ena;
+	u16      io_pulldn_ena;
+	u16      io_polarity;
+	int      irq_summary;
+	unsigned irq_base;
+	bool     reset_during_probe;
+};
+
 struct sx150x_chip {
 	struct gpio_chip                 gpio_chip;
 	struct i2c_client               *client;
@@ -354,6 +407,32 @@ static void sx150x_gpio_set(struct gpio_
 	mutex_unlock(&chip->lock);
 }
 
+static int sx150x_gpio_set_single_ended(struct gpio_chip *gc,
+					unsigned offset,
+                                        enum single_ended_mode mode)
+{
+	struct sx150x_chip *chip = gpiochip_get_data(gc);
+
+	/* On the SX160X 789 we can set open drain */
+	if (chip->dev_cfg->model != SX150X_789)
+		return -ENOTSUPP;
+
+	if (mode == LINE_MODE_PUSH_PULL)
+		return sx150x_write_cfg(chip,
+					offset,
+					1,
+					chip->dev_cfg->pri.x789.reg_drain,
+					0);
+
+	if (mode == LINE_MODE_OPEN_DRAIN)
+		return sx150x_write_cfg(chip,
+					offset,
+					1,
+					chip->dev_cfg->pri.x789.reg_drain,
+					1);
+	return -ENOTSUPP;
+}
+
 static int sx150x_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
 {
 	struct sx150x_chip *chip = gpiochip_get_data(gc);
@@ -508,6 +587,7 @@ static void sx150x_init_chip(struct sx15
 	chip->gpio_chip.direction_output = sx150x_gpio_direction_output;
 	chip->gpio_chip.get              = sx150x_gpio_get;
 	chip->gpio_chip.set              = sx150x_gpio_set;
+	chip->gpio_chip.set_single_ended = sx150x_gpio_set_single_ended;
 	chip->gpio_chip.base             = pdata->gpio_base;
 	chip->gpio_chip.can_sleep        = true;
 	chip->gpio_chip.ngpio            = chip->dev_cfg->ngpios;
@@ -597,12 +677,6 @@ static int sx150x_init_hw(struct sx150x_
 
 	if (chip->dev_cfg->model == SX150X_789) {
 		err = sx150x_init_io(chip,
-				chip->dev_cfg->pri.x789.reg_drain,
-				pdata->io_open_drain_ena);
-		if (err < 0)
-			return err;
-
-		err = sx150x_init_io(chip,
 				chip->dev_cfg->pri.x789.reg_polarity,
 				pdata->io_polarity);
 		if (err < 0)
@@ -718,13 +792,3 @@ static int __init sx150x_init(void)
 	return i2c_add_driver(&sx150x_driver);
 }
 subsys_initcall(sx150x_init);
-
-static void __exit sx150x_exit(void)
-{
-	return i2c_del_driver(&sx150x_driver);
-}
-module_exit(sx150x_exit);
-
-MODULE_AUTHOR("Gregory Bean <gbean@codeaurora.org>");
-MODULE_DESCRIPTION("Driver for Semtech SX150X I2C GPIO Expanders");
-MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-tc3589x.c linux-libre-4.7-gnu/drivers/gpio/gpio-tc3589x.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-tc3589x.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-tc3589x.c	2016-07-24 15:23:50.000000000 -0400
@@ -6,14 +6,14 @@
  * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
  */
 
-#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
-#include <linux/gpio.h>
+#include <linux/gpio/driver.h>
 #include <linux/of.h>
 #include <linux/interrupt.h>
 #include <linux/mfd/tc3589x.h>
+#include <linux/bitops.h>
 
 /*
  * These registers are modified under the irq bus lock and cached to avoid
@@ -39,7 +39,7 @@ static int tc3589x_gpio_get(struct gpio_
 	struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(chip);
 	struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
 	u8 reg = TC3589x_GPIODATA0 + (offset / 8) * 2;
-	u8 mask = 1 << (offset % 8);
+	u8 mask = BIT(offset % 8);
 	int ret;
 
 	ret = tc3589x_reg_read(tc3589x, reg);
@@ -55,7 +55,7 @@ static void tc3589x_gpio_set(struct gpio
 	struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
 	u8 reg = TC3589x_GPIODATA0 + (offset / 8) * 2;
 	unsigned pos = offset % 8;
-	u8 data[] = {!!val << pos, 1 << pos};
+	u8 data[] = {val ? BIT(pos) : 0, BIT(pos)};
 
 	tc3589x_block_write(tc3589x, reg, ARRAY_SIZE(data), data);
 }
@@ -70,7 +70,7 @@ static int tc3589x_gpio_direction_output
 
 	tc3589x_gpio_set(chip, offset, val);
 
-	return tc3589x_set_bits(tc3589x, reg, 1 << pos, 1 << pos);
+	return tc3589x_set_bits(tc3589x, reg, BIT(pos), BIT(pos));
 }
 
 static int tc3589x_gpio_direction_input(struct gpio_chip *chip,
@@ -81,7 +81,47 @@ static int tc3589x_gpio_direction_input(
 	u8 reg = TC3589x_GPIODIR0 + offset / 8;
 	unsigned pos = offset % 8;
 
-	return tc3589x_set_bits(tc3589x, reg, 1 << pos, 0);
+	return tc3589x_set_bits(tc3589x, reg, BIT(pos), 0);
+}
+
+static int tc3589x_gpio_single_ended(struct gpio_chip *chip,
+				     unsigned offset,
+				     enum single_ended_mode mode)
+{
+	struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(chip);
+	struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
+	/*
+	 * These registers are alterated at each second address
+	 * ODM bit 0 = drive to GND or Hi-Z (open drain)
+	 * ODM bit 1 = drive to VDD or Hi-Z (open source)
+	 */
+	u8 odmreg = TC3589x_GPIOODM0 + (offset / 8) * 2;
+	u8 odereg = TC3589x_GPIOODE0 + (offset / 8) * 2;
+	unsigned pos = offset % 8;
+	int ret;
+
+	switch(mode) {
+	case LINE_MODE_OPEN_DRAIN:
+		/* Set open drain mode */
+		ret = tc3589x_set_bits(tc3589x, odmreg, BIT(pos), 0);
+		if (ret)
+			return ret;
+		/* Enable open drain/source mode */
+		return tc3589x_set_bits(tc3589x, odereg, BIT(pos), BIT(pos));
+	case LINE_MODE_OPEN_SOURCE:
+		/* Set open source mode */
+		ret = tc3589x_set_bits(tc3589x, odmreg, BIT(pos), BIT(pos));
+		if (ret)
+			return ret;
+		/* Enable open drain/source mode */
+		return tc3589x_set_bits(tc3589x, odereg, BIT(pos), BIT(pos));
+	case LINE_MODE_PUSH_PULL:
+		/* Disable open drain/source mode */
+		return tc3589x_set_bits(tc3589x, odereg, BIT(pos), 0);
+	default:
+		break;
+	}
+	return -ENOTSUPP;
 }
 
 static struct gpio_chip template_chip = {
@@ -91,6 +131,7 @@ static struct gpio_chip template_chip =
 	.get			= tc3589x_gpio_get,
 	.direction_output	= tc3589x_gpio_direction_output,
 	.set			= tc3589x_gpio_set,
+	.set_single_ended	= tc3589x_gpio_single_ended,
 	.can_sleep		= true,
 };
 
@@ -100,7 +141,7 @@ static int tc3589x_gpio_irq_set_type(str
 	struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(gc);
 	int offset = d->hwirq;
 	int regoffset = offset / 8;
-	int mask = 1 << (offset % 8);
+	int mask = BIT(offset % 8);
 
 	if (type == IRQ_TYPE_EDGE_BOTH) {
 		tc3589x_gpio->regs[REG_IBE][regoffset] |= mask;
@@ -165,7 +206,7 @@ static void tc3589x_gpio_irq_mask(struct
 	struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(gc);
 	int offset = d->hwirq;
 	int regoffset = offset / 8;
-	int mask = 1 << (offset % 8);
+	int mask = BIT(offset % 8);
 
 	tc3589x_gpio->regs[REG_IE][regoffset] &= ~mask;
 }
@@ -176,7 +217,7 @@ static void tc3589x_gpio_irq_unmask(stru
 	struct tc3589x_gpio *tc3589x_gpio = gpiochip_get_data(gc);
 	int offset = d->hwirq;
 	int regoffset = offset / 8;
-	int mask = 1 << (offset % 8);
+	int mask = BIT(offset % 8);
 
 	tc3589x_gpio->regs[REG_IE][regoffset] |= mask;
 }
@@ -311,13 +352,3 @@ static int __init tc3589x_gpio_init(void
 	return platform_driver_register(&tc3589x_gpio_driver);
 }
 subsys_initcall(tc3589x_gpio_init);
-
-static void __exit tc3589x_gpio_exit(void)
-{
-	platform_driver_unregister(&tc3589x_gpio_driver);
-}
-module_exit(tc3589x_gpio_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("TC3589x GPIO driver");
-MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-tegra.c linux-libre-4.7-gnu/drivers/gpio/gpio-tegra.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-tegra.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-tegra.c	2016-07-24 15:23:50.000000000 -0400
@@ -35,24 +35,27 @@
 #define GPIO_PORT(x)		(((x) >> 3) & 0x3)
 #define GPIO_BIT(x)		((x) & 0x7)
 
-#define GPIO_REG(x)		(GPIO_BANK(x) * tegra_gpio_bank_stride + \
+#define GPIO_REG(tgi, x)	(GPIO_BANK(x) * tgi->soc->bank_stride + \
 					GPIO_PORT(x) * 4)
 
-#define GPIO_CNF(x)		(GPIO_REG(x) + 0x00)
-#define GPIO_OE(x)		(GPIO_REG(x) + 0x10)
-#define GPIO_OUT(x)		(GPIO_REG(x) + 0X20)
-#define GPIO_IN(x)		(GPIO_REG(x) + 0x30)
-#define GPIO_INT_STA(x)		(GPIO_REG(x) + 0x40)
-#define GPIO_INT_ENB(x)		(GPIO_REG(x) + 0x50)
-#define GPIO_INT_LVL(x)		(GPIO_REG(x) + 0x60)
-#define GPIO_INT_CLR(x)		(GPIO_REG(x) + 0x70)
+#define GPIO_CNF(t, x)		(GPIO_REG(t, x) + 0x00)
+#define GPIO_OE(t, x)		(GPIO_REG(t, x) + 0x10)
+#define GPIO_OUT(t, x)		(GPIO_REG(t, x) + 0X20)
+#define GPIO_IN(t, x)		(GPIO_REG(t, x) + 0x30)
+#define GPIO_INT_STA(t, x)	(GPIO_REG(t, x) + 0x40)
+#define GPIO_INT_ENB(t, x)	(GPIO_REG(t, x) + 0x50)
+#define GPIO_INT_LVL(t, x)	(GPIO_REG(t, x) + 0x60)
+#define GPIO_INT_CLR(t, x)	(GPIO_REG(t, x) + 0x70)
+#define GPIO_DBC_CNT(t, x)	(GPIO_REG(t, x) + 0xF0)
 
-#define GPIO_MSK_CNF(x)		(GPIO_REG(x) + tegra_gpio_upper_offset + 0x00)
-#define GPIO_MSK_OE(x)		(GPIO_REG(x) + tegra_gpio_upper_offset + 0x10)
-#define GPIO_MSK_OUT(x)		(GPIO_REG(x) + tegra_gpio_upper_offset + 0X20)
-#define GPIO_MSK_INT_STA(x)	(GPIO_REG(x) + tegra_gpio_upper_offset + 0x40)
-#define GPIO_MSK_INT_ENB(x)	(GPIO_REG(x) + tegra_gpio_upper_offset + 0x50)
-#define GPIO_MSK_INT_LVL(x)	(GPIO_REG(x) + tegra_gpio_upper_offset + 0x60)
+
+#define GPIO_MSK_CNF(t, x)	(GPIO_REG(t, x) + t->soc->upper_offset + 0x00)
+#define GPIO_MSK_OE(t, x)	(GPIO_REG(t, x) + t->soc->upper_offset + 0x10)
+#define GPIO_MSK_OUT(t, x)	(GPIO_REG(t, x) + t->soc->upper_offset + 0X20)
+#define GPIO_MSK_DBC_EN(t, x)	(GPIO_REG(t, x) + t->soc->upper_offset + 0x30)
+#define GPIO_MSK_INT_STA(t, x)	(GPIO_REG(t, x) + t->soc->upper_offset + 0x40)
+#define GPIO_MSK_INT_ENB(t, x)	(GPIO_REG(t, x) + t->soc->upper_offset + 0x50)
+#define GPIO_MSK_INT_LVL(t, x)	(GPIO_REG(t, x) + t->soc->upper_offset + 0x60)
 
 #define GPIO_INT_LVL_MASK		0x010101
 #define GPIO_INT_LVL_EDGE_RISING	0x000101
@@ -61,10 +64,13 @@
 #define GPIO_INT_LVL_LEVEL_HIGH		0x000001
 #define GPIO_INT_LVL_LEVEL_LOW		0x000000
 
+struct tegra_gpio_info;
+
 struct tegra_gpio_bank {
 	int bank;
 	int irq;
 	spinlock_t lvl_lock[4];
+	spinlock_t dbc_lock[4];	/* Lock for updating debounce count register */
 #ifdef CONFIG_PM_SLEEP
 	u32 cnf[4];
 	u32 out[4];
@@ -72,25 +78,38 @@ struct tegra_gpio_bank {
 	u32 int_enb[4];
 	u32 int_lvl[4];
 	u32 wake_enb[4];
+	u32 dbc_enb[4];
 #endif
+	u32 dbc_cnt[4];
+	struct tegra_gpio_info *tgi;
 };
 
-static struct device *dev;
-static struct irq_domain *irq_domain;
-static void __iomem *regs;
-static u32 tegra_gpio_bank_count;
-static u32 tegra_gpio_bank_stride;
-static u32 tegra_gpio_upper_offset;
-static struct tegra_gpio_bank *tegra_gpio_banks;
+struct tegra_gpio_soc_config {
+	bool debounce_supported;
+	u32 bank_stride;
+	u32 upper_offset;
+};
 
-static inline void tegra_gpio_writel(u32 val, u32 reg)
+struct tegra_gpio_info {
+	struct device				*dev;
+	void __iomem				*regs;
+	struct irq_domain			*irq_domain;
+	struct tegra_gpio_bank			*bank_info;
+	const struct tegra_gpio_soc_config	*soc;
+	struct gpio_chip			gc;
+	struct irq_chip				ic;
+	u32					bank_count;
+};
+
+static inline void tegra_gpio_writel(struct tegra_gpio_info *tgi,
+				     u32 val, u32 reg)
 {
-	__raw_writel(val, regs + reg);
+	__raw_writel(val, tgi->regs + reg);
 }
 
-static inline u32 tegra_gpio_readl(u32 reg)
+static inline u32 tegra_gpio_readl(struct tegra_gpio_info *tgi, u32 reg)
 {
-	return __raw_readl(regs + reg);
+	return __raw_readl(tgi->regs + reg);
 }
 
 static int tegra_gpio_compose(int bank, int port, int bit)
@@ -98,24 +117,25 @@ static int tegra_gpio_compose(int bank,
 	return (bank << 5) | ((port & 0x3) << 3) | (bit & 0x7);
 }
 
-static void tegra_gpio_mask_write(u32 reg, int gpio, int value)
+static void tegra_gpio_mask_write(struct tegra_gpio_info *tgi, u32 reg,
+				  int gpio, int value)
 {
 	u32 val;
 
 	val = 0x100 << GPIO_BIT(gpio);
 	if (value)
 		val |= 1 << GPIO_BIT(gpio);
-	tegra_gpio_writel(val, reg);
+	tegra_gpio_writel(tgi, val, reg);
 }
 
-static void tegra_gpio_enable(int gpio)
+static void tegra_gpio_enable(struct tegra_gpio_info *tgi, int gpio)
 {
-	tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 1);
+	tegra_gpio_mask_write(tgi, GPIO_MSK_CNF(tgi, gpio), gpio, 1);
 }
 
-static void tegra_gpio_disable(int gpio)
+static void tegra_gpio_disable(struct tegra_gpio_info *tgi, int gpio)
 {
-	tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 0);
+	tegra_gpio_mask_write(tgi, GPIO_MSK_CNF(tgi, gpio), gpio, 0);
 }
 
 static int tegra_gpio_request(struct gpio_chip *chip, unsigned offset)
@@ -125,83 +145,138 @@ static int tegra_gpio_request(struct gpi
 
 static void tegra_gpio_free(struct gpio_chip *chip, unsigned offset)
 {
+	struct tegra_gpio_info *tgi = gpiochip_get_data(chip);
+
 	pinctrl_free_gpio(offset);
-	tegra_gpio_disable(offset);
+	tegra_gpio_disable(tgi, offset);
 }
 
 static void tegra_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 {
-	tegra_gpio_mask_write(GPIO_MSK_OUT(offset), offset, value);
+	struct tegra_gpio_info *tgi = gpiochip_get_data(chip);
+
+	tegra_gpio_mask_write(tgi, GPIO_MSK_OUT(tgi, offset), offset, value);
 }
 
 static int tegra_gpio_get(struct gpio_chip *chip, unsigned offset)
 {
+	struct tegra_gpio_info *tgi = gpiochip_get_data(chip);
+	int bval = BIT(GPIO_BIT(offset));
+
 	/* If gpio is in output mode then read from the out value */
-	if ((tegra_gpio_readl(GPIO_OE(offset)) >> GPIO_BIT(offset)) & 1)
-		return (tegra_gpio_readl(GPIO_OUT(offset)) >>
-				GPIO_BIT(offset)) & 0x1;
+	if (tegra_gpio_readl(tgi, GPIO_OE(tgi, offset)) & bval)
+		return !!(tegra_gpio_readl(tgi, GPIO_OUT(tgi, offset)) & bval);
 
-	return (tegra_gpio_readl(GPIO_IN(offset)) >> GPIO_BIT(offset)) & 0x1;
+	return !!(tegra_gpio_readl(tgi, GPIO_IN(tgi, offset)) & bval);
 }
 
 static int tegra_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
 {
-	tegra_gpio_mask_write(GPIO_MSK_OE(offset), offset, 0);
-	tegra_gpio_enable(offset);
+	struct tegra_gpio_info *tgi = gpiochip_get_data(chip);
+
+	tegra_gpio_mask_write(tgi, GPIO_MSK_OE(tgi, offset), offset, 0);
+	tegra_gpio_enable(tgi, offset);
 	return 0;
 }
 
 static int tegra_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
 					int value)
 {
+	struct tegra_gpio_info *tgi = gpiochip_get_data(chip);
+
 	tegra_gpio_set(chip, offset, value);
-	tegra_gpio_mask_write(GPIO_MSK_OE(offset), offset, 1);
-	tegra_gpio_enable(offset);
+	tegra_gpio_mask_write(tgi, GPIO_MSK_OE(tgi, offset), offset, 1);
+	tegra_gpio_enable(tgi, offset);
 	return 0;
 }
 
-static int tegra_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+static int tegra_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
 {
-	return irq_find_mapping(irq_domain, offset);
+	struct tegra_gpio_info *tgi = gpiochip_get_data(chip);
+	u32 pin_mask = BIT(GPIO_BIT(offset));
+	u32 cnf, oe;
+
+	cnf = tegra_gpio_readl(tgi, GPIO_CNF(tgi, offset));
+	if (!(cnf & pin_mask))
+		return -EINVAL;
+
+	oe = tegra_gpio_readl(tgi, GPIO_OE(tgi, offset));
+
+	return (oe & pin_mask) ? GPIOF_DIR_OUT : GPIOF_DIR_IN;
 }
 
-static struct gpio_chip tegra_gpio_chip = {
-	.label			= "tegra-gpio",
-	.request		= tegra_gpio_request,
-	.free			= tegra_gpio_free,
-	.direction_input	= tegra_gpio_direction_input,
-	.get			= tegra_gpio_get,
-	.direction_output	= tegra_gpio_direction_output,
-	.set			= tegra_gpio_set,
-	.to_irq			= tegra_gpio_to_irq,
-	.base			= 0,
-};
+static int tegra_gpio_set_debounce(struct gpio_chip *chip, unsigned int offset,
+				   unsigned int debounce)
+{
+	struct tegra_gpio_info *tgi = gpiochip_get_data(chip);
+	struct tegra_gpio_bank *bank = &tgi->bank_info[GPIO_BANK(offset)];
+	unsigned int debounce_ms = DIV_ROUND_UP(debounce, 1000);
+	unsigned long flags;
+	int port;
+
+	if (!debounce_ms) {
+		tegra_gpio_mask_write(tgi, GPIO_MSK_DBC_EN(tgi, offset),
+				      offset, 0);
+		return 0;
+	}
+
+	debounce_ms = min(debounce_ms, 255U);
+	port = GPIO_PORT(offset);
+
+	/* There is only one debounce count register per port and hence
+	 * set the maximum of current and requested debounce time.
+	 */
+	spin_lock_irqsave(&bank->dbc_lock[port], flags);
+	if (bank->dbc_cnt[port] < debounce_ms) {
+		tegra_gpio_writel(tgi, debounce_ms, GPIO_DBC_CNT(tgi, offset));
+		bank->dbc_cnt[port] = debounce_ms;
+	}
+	spin_unlock_irqrestore(&bank->dbc_lock[port], flags);
+
+	tegra_gpio_mask_write(tgi, GPIO_MSK_DBC_EN(tgi, offset), offset, 1);
+
+	return 0;
+}
+
+static int tegra_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	struct tegra_gpio_info *tgi = gpiochip_get_data(chip);
+
+	return irq_find_mapping(tgi->irq_domain, offset);
+}
 
 static void tegra_gpio_irq_ack(struct irq_data *d)
 {
+	struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d);
+	struct tegra_gpio_info *tgi = bank->tgi;
 	int gpio = d->hwirq;
 
-	tegra_gpio_writel(1 << GPIO_BIT(gpio), GPIO_INT_CLR(gpio));
+	tegra_gpio_writel(tgi, 1 << GPIO_BIT(gpio), GPIO_INT_CLR(tgi, gpio));
 }
 
 static void tegra_gpio_irq_mask(struct irq_data *d)
 {
+	struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d);
+	struct tegra_gpio_info *tgi = bank->tgi;
 	int gpio = d->hwirq;
 
-	tegra_gpio_mask_write(GPIO_MSK_INT_ENB(gpio), gpio, 0);
+	tegra_gpio_mask_write(tgi, GPIO_MSK_INT_ENB(tgi, gpio), gpio, 0);
 }
 
 static void tegra_gpio_irq_unmask(struct irq_data *d)
 {
+	struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d);
+	struct tegra_gpio_info *tgi = bank->tgi;
 	int gpio = d->hwirq;
 
-	tegra_gpio_mask_write(GPIO_MSK_INT_ENB(gpio), gpio, 1);
+	tegra_gpio_mask_write(tgi, GPIO_MSK_INT_ENB(tgi, gpio), gpio, 1);
 }
 
 static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 {
 	int gpio = d->hwirq;
 	struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d);
+	struct tegra_gpio_info *tgi = bank->tgi;
 	int port = GPIO_PORT(gpio);
 	int lvl_type;
 	int val;
@@ -233,23 +308,24 @@ static int tegra_gpio_irq_set_type(struc
 		return -EINVAL;
 	}
 
-	ret = gpiochip_lock_as_irq(&tegra_gpio_chip, gpio);
+	ret = gpiochip_lock_as_irq(&tgi->gc, gpio);
 	if (ret) {
-		dev_err(dev, "unable to lock Tegra GPIO %d as IRQ\n", gpio);
+		dev_err(tgi->dev,
+			"unable to lock Tegra GPIO %d as IRQ\n", gpio);
 		return ret;
 	}
 
 	spin_lock_irqsave(&bank->lvl_lock[port], flags);
 
-	val = tegra_gpio_readl(GPIO_INT_LVL(gpio));
+	val = tegra_gpio_readl(tgi, GPIO_INT_LVL(tgi, gpio));
 	val &= ~(GPIO_INT_LVL_MASK << GPIO_BIT(gpio));
 	val |= lvl_type << GPIO_BIT(gpio);
-	tegra_gpio_writel(val, GPIO_INT_LVL(gpio));
+	tegra_gpio_writel(tgi, val, GPIO_INT_LVL(tgi, gpio));
 
 	spin_unlock_irqrestore(&bank->lvl_lock[port], flags);
 
-	tegra_gpio_mask_write(GPIO_MSK_OE(gpio), gpio, 0);
-	tegra_gpio_enable(gpio);
+	tegra_gpio_mask_write(tgi, GPIO_MSK_OE(tgi, gpio), gpio, 0);
+	tegra_gpio_enable(tgi, gpio);
 
 	if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
 		irq_set_handler_locked(d, handle_level_irq);
@@ -261,9 +337,11 @@ static int tegra_gpio_irq_set_type(struc
 
 static void tegra_gpio_irq_shutdown(struct irq_data *d)
 {
+	struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d);
+	struct tegra_gpio_info *tgi = bank->tgi;
 	int gpio = d->hwirq;
 
-	gpiochip_unlock_as_irq(&tegra_gpio_chip, gpio);
+	gpiochip_unlock_as_irq(&tgi->gc, gpio);
 }
 
 static void tegra_gpio_irq_handler(struct irq_desc *desc)
@@ -271,19 +349,24 @@ static void tegra_gpio_irq_handler(struc
 	int port;
 	int pin;
 	int unmasked = 0;
+	int gpio;
+	u32 lvl;
+	unsigned long sta;
 	struct irq_chip *chip = irq_desc_get_chip(desc);
 	struct tegra_gpio_bank *bank = irq_desc_get_handler_data(desc);
+	struct tegra_gpio_info *tgi = bank->tgi;
 
 	chained_irq_enter(chip, desc);
 
 	for (port = 0; port < 4; port++) {
-		int gpio = tegra_gpio_compose(bank->bank, port, 0);
-		unsigned long sta = tegra_gpio_readl(GPIO_INT_STA(gpio)) &
-			tegra_gpio_readl(GPIO_INT_ENB(gpio));
-		u32 lvl = tegra_gpio_readl(GPIO_INT_LVL(gpio));
+		gpio = tegra_gpio_compose(bank->bank, port, 0);
+		sta = tegra_gpio_readl(tgi, GPIO_INT_STA(tgi, gpio)) &
+			tegra_gpio_readl(tgi, GPIO_INT_ENB(tgi, gpio));
+		lvl = tegra_gpio_readl(tgi, GPIO_INT_LVL(tgi, gpio));
 
 		for_each_set_bit(pin, &sta, 8) {
-			tegra_gpio_writel(1 << pin, GPIO_INT_CLR(gpio));
+			tegra_gpio_writel(tgi, 1 << pin,
+					  GPIO_INT_CLR(tgi, gpio));
 
 			/* if gpio is edge triggered, clear condition
 			 * before executing the handler so that we don't
@@ -306,22 +389,37 @@ static void tegra_gpio_irq_handler(struc
 #ifdef CONFIG_PM_SLEEP
 static int tegra_gpio_resume(struct device *dev)
 {
+	struct platform_device *pdev = to_platform_device(dev);
+	struct tegra_gpio_info *tgi = platform_get_drvdata(pdev);
 	unsigned long flags;
 	int b;
 	int p;
 
 	local_irq_save(flags);
 
-	for (b = 0; b < tegra_gpio_bank_count; b++) {
-		struct tegra_gpio_bank *bank = &tegra_gpio_banks[b];
+	for (b = 0; b < tgi->bank_count; b++) {
+		struct tegra_gpio_bank *bank = &tgi->bank_info[b];
 
 		for (p = 0; p < ARRAY_SIZE(bank->oe); p++) {
 			unsigned int gpio = (b<<5) | (p<<3);
-			tegra_gpio_writel(bank->cnf[p], GPIO_CNF(gpio));
-			tegra_gpio_writel(bank->out[p], GPIO_OUT(gpio));
-			tegra_gpio_writel(bank->oe[p], GPIO_OE(gpio));
-			tegra_gpio_writel(bank->int_lvl[p], GPIO_INT_LVL(gpio));
-			tegra_gpio_writel(bank->int_enb[p], GPIO_INT_ENB(gpio));
+			tegra_gpio_writel(tgi, bank->cnf[p],
+					  GPIO_CNF(tgi, gpio));
+
+			if (tgi->soc->debounce_supported) {
+				tegra_gpio_writel(tgi, bank->dbc_cnt[p],
+						  GPIO_DBC_CNT(tgi, gpio));
+				tegra_gpio_writel(tgi, bank->dbc_enb[p],
+						  GPIO_MSK_DBC_EN(tgi, gpio));
+			}
+
+			tegra_gpio_writel(tgi, bank->out[p],
+					  GPIO_OUT(tgi, gpio));
+			tegra_gpio_writel(tgi, bank->oe[p],
+					  GPIO_OE(tgi, gpio));
+			tegra_gpio_writel(tgi, bank->int_lvl[p],
+					  GPIO_INT_LVL(tgi, gpio));
+			tegra_gpio_writel(tgi, bank->int_enb[p],
+					  GPIO_INT_ENB(tgi, gpio));
 		}
 	}
 
@@ -331,25 +429,39 @@ static int tegra_gpio_resume(struct devi
 
 static int tegra_gpio_suspend(struct device *dev)
 {
+	struct platform_device *pdev = to_platform_device(dev);
+	struct tegra_gpio_info *tgi = platform_get_drvdata(pdev);
 	unsigned long flags;
 	int b;
 	int p;
 
 	local_irq_save(flags);
-	for (b = 0; b < tegra_gpio_bank_count; b++) {
-		struct tegra_gpio_bank *bank = &tegra_gpio_banks[b];
+	for (b = 0; b < tgi->bank_count; b++) {
+		struct tegra_gpio_bank *bank = &tgi->bank_info[b];
 
 		for (p = 0; p < ARRAY_SIZE(bank->oe); p++) {
 			unsigned int gpio = (b<<5) | (p<<3);
-			bank->cnf[p] = tegra_gpio_readl(GPIO_CNF(gpio));
-			bank->out[p] = tegra_gpio_readl(GPIO_OUT(gpio));
-			bank->oe[p] = tegra_gpio_readl(GPIO_OE(gpio));
-			bank->int_enb[p] = tegra_gpio_readl(GPIO_INT_ENB(gpio));
-			bank->int_lvl[p] = tegra_gpio_readl(GPIO_INT_LVL(gpio));
+			bank->cnf[p] = tegra_gpio_readl(tgi,
+							GPIO_CNF(tgi, gpio));
+			bank->out[p] = tegra_gpio_readl(tgi,
+							GPIO_OUT(tgi, gpio));
+			bank->oe[p] = tegra_gpio_readl(tgi,
+						       GPIO_OE(tgi, gpio));
+			if (tgi->soc->debounce_supported) {
+				bank->dbc_enb[p] = tegra_gpio_readl(tgi,
+						GPIO_MSK_DBC_EN(tgi, gpio));
+				bank->dbc_enb[p] = (bank->dbc_enb[p] << 8) |
+							bank->dbc_enb[p];
+			}
+
+			bank->int_enb[p] = tegra_gpio_readl(tgi,
+						GPIO_INT_ENB(tgi, gpio));
+			bank->int_lvl[p] = tegra_gpio_readl(tgi,
+						GPIO_INT_LVL(tgi, gpio));
 
 			/* Enable gpio irq for wake up source */
-			tegra_gpio_writel(bank->wake_enb[p],
-					  GPIO_INT_ENB(gpio));
+			tegra_gpio_writel(tgi, bank->wake_enb[p],
+					  GPIO_INT_ENB(tgi, gpio));
 		}
 	}
 	local_irq_restore(flags);
@@ -382,22 +494,23 @@ static int tegra_gpio_irq_set_wake(struc
 
 static int dbg_gpio_show(struct seq_file *s, void *unused)
 {
+	struct tegra_gpio_info *tgi = s->private;
 	int i;
 	int j;
 
-	for (i = 0; i < tegra_gpio_bank_count; i++) {
+	for (i = 0; i < tgi->bank_count; i++) {
 		for (j = 0; j < 4; j++) {
 			int gpio = tegra_gpio_compose(i, j, 0);
 			seq_printf(s,
 				"%d:%d %02x %02x %02x %02x %02x %02x %06x\n",
 				i, j,
-				tegra_gpio_readl(GPIO_CNF(gpio)),
-				tegra_gpio_readl(GPIO_OE(gpio)),
-				tegra_gpio_readl(GPIO_OUT(gpio)),
-				tegra_gpio_readl(GPIO_IN(gpio)),
-				tegra_gpio_readl(GPIO_INT_STA(gpio)),
-				tegra_gpio_readl(GPIO_INT_ENB(gpio)),
-				tegra_gpio_readl(GPIO_INT_LVL(gpio)));
+				tegra_gpio_readl(tgi, GPIO_CNF(tgi, gpio)),
+				tegra_gpio_readl(tgi, GPIO_OE(tgi, gpio)),
+				tegra_gpio_readl(tgi, GPIO_OUT(tgi, gpio)),
+				tegra_gpio_readl(tgi, GPIO_IN(tgi, gpio)),
+				tegra_gpio_readl(tgi, GPIO_INT_STA(tgi, gpio)),
+				tegra_gpio_readl(tgi, GPIO_INT_ENB(tgi, gpio)),
+				tegra_gpio_readl(tgi, GPIO_INT_LVL(tgi, gpio)));
 		}
 	}
 	return 0;
@@ -405,7 +518,7 @@ static int dbg_gpio_show(struct seq_file
 
 static int dbg_gpio_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, dbg_gpio_show, &inode->i_private);
+	return single_open(file, dbg_gpio_show, inode->i_private);
 }
 
 static const struct file_operations debug_fops = {
@@ -415,66 +528,34 @@ static const struct file_operations debu
 	.release	= single_release,
 };
 
-static void tegra_gpio_debuginit(void)
+static void tegra_gpio_debuginit(struct tegra_gpio_info *tgi)
 {
 	(void) debugfs_create_file("tegra_gpio", S_IRUGO,
-					NULL, NULL, &debug_fops);
+					NULL, tgi, &debug_fops);
 }
 
 #else
 
-static inline void tegra_gpio_debuginit(void)
+static inline void tegra_gpio_debuginit(struct tegra_gpio_info *tgi)
 {
 }
 
 #endif
 
-static struct irq_chip tegra_gpio_irq_chip = {
-	.name		= "GPIO",
-	.irq_ack	= tegra_gpio_irq_ack,
-	.irq_mask	= tegra_gpio_irq_mask,
-	.irq_unmask	= tegra_gpio_irq_unmask,
-	.irq_set_type	= tegra_gpio_irq_set_type,
-	.irq_shutdown	= tegra_gpio_irq_shutdown,
-#ifdef CONFIG_PM_SLEEP
-	.irq_set_wake	= tegra_gpio_irq_set_wake,
-#endif
-};
-
 static const struct dev_pm_ops tegra_gpio_pm_ops = {
 	SET_SYSTEM_SLEEP_PM_OPS(tegra_gpio_suspend, tegra_gpio_resume)
 };
 
-struct tegra_gpio_soc_config {
-	u32 bank_stride;
-	u32 upper_offset;
-};
-
-static struct tegra_gpio_soc_config tegra20_gpio_config = {
-	.bank_stride = 0x80,
-	.upper_offset = 0x800,
-};
-
-static struct tegra_gpio_soc_config tegra30_gpio_config = {
-	.bank_stride = 0x100,
-	.upper_offset = 0x80,
-};
-
-static const struct of_device_id tegra_gpio_of_match[] = {
-	{ .compatible = "nvidia,tegra30-gpio", .data = &tegra30_gpio_config },
-	{ .compatible = "nvidia,tegra20-gpio", .data = &tegra20_gpio_config },
-	{ },
-};
-
-/* This lock class tells lockdep that GPIO irqs are in a different
- * category than their parents, so it won't report false recursion.
+/*
+ * This lock class tells lockdep that GPIO irqs are in a different category
+ * than their parents, so it won't report false recursion.
  */
 static struct lock_class_key gpio_lock_class;
 
 static int tegra_gpio_probe(struct platform_device *pdev)
 {
-	const struct of_device_id *match;
-	struct tegra_gpio_soc_config *config;
+	const struct tegra_gpio_soc_config *config;
+	struct tegra_gpio_info *tgi;
 	struct resource *res;
 	struct tegra_gpio_bank *bank;
 	int ret;
@@ -482,102 +563,153 @@ static int tegra_gpio_probe(struct platf
 	int i;
 	int j;
 
-	dev = &pdev->dev;
-
-	match = of_match_device(tegra_gpio_of_match, &pdev->dev);
-	if (!match) {
+	config = of_device_get_match_data(&pdev->dev);
+	if (!config) {
 		dev_err(&pdev->dev, "Error: No device match found\n");
 		return -ENODEV;
 	}
-	config = (struct tegra_gpio_soc_config *)match->data;
 
-	tegra_gpio_bank_stride = config->bank_stride;
-	tegra_gpio_upper_offset = config->upper_offset;
+	tgi = devm_kzalloc(&pdev->dev, sizeof(*tgi), GFP_KERNEL);
+	if (!tgi)
+		return -ENODEV;
+
+	tgi->soc = config;
+	tgi->dev = &pdev->dev;
 
 	for (;;) {
-		res = platform_get_resource(pdev, IORESOURCE_IRQ, tegra_gpio_bank_count);
+		res = platform_get_resource(pdev, IORESOURCE_IRQ,
+					    tgi->bank_count);
 		if (!res)
 			break;
-		tegra_gpio_bank_count++;
+		tgi->bank_count++;
 	}
-	if (!tegra_gpio_bank_count) {
+	if (!tgi->bank_count) {
 		dev_err(&pdev->dev, "Missing IRQ resource\n");
 		return -ENODEV;
 	}
 
-	tegra_gpio_chip.ngpio = tegra_gpio_bank_count * 32;
+	tgi->gc.label			= "tegra-gpio";
+	tgi->gc.request			= tegra_gpio_request;
+	tgi->gc.free			= tegra_gpio_free;
+	tgi->gc.direction_input		= tegra_gpio_direction_input;
+	tgi->gc.get			= tegra_gpio_get;
+	tgi->gc.direction_output	= tegra_gpio_direction_output;
+	tgi->gc.set			= tegra_gpio_set;
+	tgi->gc.get_direction		= tegra_gpio_get_direction;
+	tgi->gc.to_irq			= tegra_gpio_to_irq;
+	tgi->gc.base			= 0;
+	tgi->gc.ngpio			= tgi->bank_count * 32;
+	tgi->gc.parent			= &pdev->dev;
+	tgi->gc.of_node			= pdev->dev.of_node;
 
-	tegra_gpio_banks = devm_kzalloc(&pdev->dev,
-			tegra_gpio_bank_count * sizeof(*tegra_gpio_banks),
-			GFP_KERNEL);
-	if (!tegra_gpio_banks)
+	tgi->ic.name			= "GPIO";
+	tgi->ic.irq_ack			= tegra_gpio_irq_ack;
+	tgi->ic.irq_mask		= tegra_gpio_irq_mask;
+	tgi->ic.irq_unmask		= tegra_gpio_irq_unmask;
+	tgi->ic.irq_set_type		= tegra_gpio_irq_set_type;
+	tgi->ic.irq_shutdown		= tegra_gpio_irq_shutdown;
+#ifdef CONFIG_PM_SLEEP
+	tgi->ic.irq_set_wake		= tegra_gpio_irq_set_wake;
+#endif
+
+	platform_set_drvdata(pdev, tgi);
+
+	if (config->debounce_supported)
+		tgi->gc.set_debounce = tegra_gpio_set_debounce;
+
+	tgi->bank_info = devm_kzalloc(&pdev->dev, tgi->bank_count *
+				      sizeof(*tgi->bank_info), GFP_KERNEL);
+	if (!tgi->bank_info)
 		return -ENODEV;
 
-	irq_domain = irq_domain_add_linear(pdev->dev.of_node,
-					   tegra_gpio_chip.ngpio,
-					   &irq_domain_simple_ops, NULL);
-	if (!irq_domain)
+	tgi->irq_domain = irq_domain_add_linear(pdev->dev.of_node,
+						tgi->gc.ngpio,
+						&irq_domain_simple_ops, NULL);
+	if (!tgi->irq_domain)
 		return -ENODEV;
 
-	for (i = 0; i < tegra_gpio_bank_count; i++) {
+	for (i = 0; i < tgi->bank_count; i++) {
 		res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
 		if (!res) {
 			dev_err(&pdev->dev, "Missing IRQ resource\n");
 			return -ENODEV;
 		}
 
-		bank = &tegra_gpio_banks[i];
+		bank = &tgi->bank_info[i];
 		bank->bank = i;
 		bank->irq = res->start;
+		bank->tgi = tgi;
 	}
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	regs = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(regs))
-		return PTR_ERR(regs);
+	tgi->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(tgi->regs))
+		return PTR_ERR(tgi->regs);
 
-	for (i = 0; i < tegra_gpio_bank_count; i++) {
+	for (i = 0; i < tgi->bank_count; i++) {
 		for (j = 0; j < 4; j++) {
 			int gpio = tegra_gpio_compose(i, j, 0);
-			tegra_gpio_writel(0x00, GPIO_INT_ENB(gpio));
+			tegra_gpio_writel(tgi, 0x00, GPIO_INT_ENB(tgi, gpio));
 		}
 	}
 
-	tegra_gpio_chip.of_node = pdev->dev.of_node;
-
-	ret = devm_gpiochip_add_data(&pdev->dev, &tegra_gpio_chip, NULL);
+	ret = devm_gpiochip_add_data(&pdev->dev, &tgi->gc, tgi);
 	if (ret < 0) {
-		irq_domain_remove(irq_domain);
+		irq_domain_remove(tgi->irq_domain);
 		return ret;
 	}
 
-	for (gpio = 0; gpio < tegra_gpio_chip.ngpio; gpio++) {
-		int irq = irq_create_mapping(irq_domain, gpio);
+	for (gpio = 0; gpio < tgi->gc.ngpio; gpio++) {
+		int irq = irq_create_mapping(tgi->irq_domain, gpio);
 		/* No validity check; all Tegra GPIOs are valid IRQs */
 
-		bank = &tegra_gpio_banks[GPIO_BANK(gpio)];
+		bank = &tgi->bank_info[GPIO_BANK(gpio)];
 
 		irq_set_lockdep_class(irq, &gpio_lock_class);
 		irq_set_chip_data(irq, bank);
-		irq_set_chip_and_handler(irq, &tegra_gpio_irq_chip,
-					 handle_simple_irq);
+		irq_set_chip_and_handler(irq, &tgi->ic, handle_simple_irq);
 	}
 
-	for (i = 0; i < tegra_gpio_bank_count; i++) {
-		bank = &tegra_gpio_banks[i];
+	for (i = 0; i < tgi->bank_count; i++) {
+		bank = &tgi->bank_info[i];
 
 		irq_set_chained_handler_and_data(bank->irq,
 						 tegra_gpio_irq_handler, bank);
 
-		for (j = 0; j < 4; j++)
+		for (j = 0; j < 4; j++) {
 			spin_lock_init(&bank->lvl_lock[j]);
+			spin_lock_init(&bank->dbc_lock[j]);
+		}
 	}
 
-	tegra_gpio_debuginit();
+	tegra_gpio_debuginit(tgi);
 
 	return 0;
 }
 
+static const struct tegra_gpio_soc_config tegra20_gpio_config = {
+	.bank_stride = 0x80,
+	.upper_offset = 0x800,
+};
+
+static const struct tegra_gpio_soc_config tegra30_gpio_config = {
+	.bank_stride = 0x100,
+	.upper_offset = 0x80,
+};
+
+static const struct tegra_gpio_soc_config tegra210_gpio_config = {
+	.debounce_supported = true,
+	.bank_stride = 0x100,
+	.upper_offset = 0x80,
+};
+
+static const struct of_device_id tegra_gpio_of_match[] = {
+	{ .compatible = "nvidia,tegra210-gpio", .data = &tegra210_gpio_config },
+	{ .compatible = "nvidia,tegra30-gpio", .data = &tegra30_gpio_config },
+	{ .compatible = "nvidia,tegra20-gpio", .data = &tegra20_gpio_config },
+	{ },
+};
+
 static struct platform_driver tegra_gpio_driver = {
 	.driver		= {
 		.name	= "tegra-gpio",
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-timberdale.c linux-libre-4.7-gnu/drivers/gpio/gpio-timberdale.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-timberdale.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-timberdale.c	2016-07-24 15:23:50.000000000 -0400
@@ -1,5 +1,6 @@
 /*
  * Timberdale FPGA GPIO driver
+ * Author: Mocean Laboratories
  * Copyright (c) 2009 Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
@@ -20,7 +21,7 @@
  * Timberdale FPGA GPIO
  */
 
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/gpio.h>
 #include <linux/platform_device.h>
 #include <linux/irq.h>
@@ -290,40 +291,14 @@ static int timbgpio_probe(struct platfor
 	return 0;
 }
 
-static int timbgpio_remove(struct platform_device *pdev)
-{
-	struct timbgpio_platform_data *pdata = dev_get_platdata(&pdev->dev);
-	struct timbgpio *tgpio = platform_get_drvdata(pdev);
-	int irq = platform_get_irq(pdev, 0);
-
-	if (irq >= 0 && tgpio->irq_base > 0) {
-		int i;
-		for (i = 0; i < pdata->nr_pins; i++) {
-			irq_set_chip(tgpio->irq_base + i, NULL);
-			irq_set_chip_data(tgpio->irq_base + i, NULL);
-		}
-
-		irq_set_handler(irq, NULL);
-		irq_set_handler_data(irq, NULL);
-	}
-
-	return 0;
-}
-
 static struct platform_driver timbgpio_platform_driver = {
 	.driver = {
-		.name	= DRIVER_NAME,
+		.name			= DRIVER_NAME,
+		.suppress_bind_attrs	= true,
 	},
 	.probe		= timbgpio_probe,
-	.remove		= timbgpio_remove,
 };
 
 /*--------------------------------------------------------------------------*/
 
-module_platform_driver(timbgpio_platform_driver);
-
-MODULE_DESCRIPTION("Timberdale GPIO driver");
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Mocean Laboratories");
-MODULE_ALIAS("platform:"DRIVER_NAME);
-
+builtin_platform_driver(timbgpio_platform_driver);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-tpic2810.c linux-libre-4.7-gnu/drivers/gpio/gpio-tpic2810.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-tpic2810.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-tpic2810.c	2016-07-24 15:23:50.000000000 -0400
@@ -57,39 +57,34 @@ static int tpic2810_direction_output(str
 	return 0;
 }
 
-static void tpic2810_set(struct gpio_chip *chip, unsigned offset, int value)
+static void tpic2810_set_mask_bits(struct gpio_chip *chip, u8 mask, u8 bits)
 {
 	struct tpic2810 *gpio = gpiochip_get_data(chip);
+	u8 buffer;
+	int err;
 
 	mutex_lock(&gpio->lock);
 
-	if (value)
-		gpio->buffer |= BIT(offset);
-	else
-		gpio->buffer &= ~BIT(offset);
+	buffer = gpio->buffer & ~mask;
+	buffer |= (mask & bits);
 
-	i2c_smbus_write_byte_data(gpio->client, TPIC2810_WS_COMMAND,
-				  gpio->buffer);
+	err = i2c_smbus_write_byte_data(gpio->client, TPIC2810_WS_COMMAND,
+					buffer);
+	if (!err)
+		gpio->buffer = buffer;
 
 	mutex_unlock(&gpio->lock);
 }
 
+static void tpic2810_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	tpic2810_set_mask_bits(chip, BIT(offset), value ? BIT(offset) : 0);
+}
+
 static void tpic2810_set_multiple(struct gpio_chip *chip, unsigned long *mask,
 				  unsigned long *bits)
 {
-	struct tpic2810 *gpio = gpiochip_get_data(chip);
-
-	mutex_lock(&gpio->lock);
-
-	/* clear bits under mask */
-	gpio->buffer &= ~(*mask);
-	/* set bits under mask */
-	gpio->buffer |= ((*mask) & (*bits));
-
-	i2c_smbus_write_byte_data(gpio->client, TPIC2810_WS_COMMAND,
-				  gpio->buffer);
-
-	mutex_unlock(&gpio->lock);
+	tpic2810_set_mask_bits(chip, *mask, *bits);
 }
 
 static struct gpio_chip template_chip = {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-tps65218.c linux-libre-4.7-gnu/drivers/gpio/gpio-tps65218.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-tps65218.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-tps65218.c	2016-07-24 15:23:50.000000000 -0400
@@ -101,16 +101,6 @@ static int tps65218_gpio_request(struct
 
 		break;
 	case 1:
-		/* GP02 is push-pull by default, can be set as open drain. */
-		if (gpiochip_line_is_open_drain(gc, offset)) {
-			ret = tps65218_clear_bits(tps65218,
-						  TPS65218_REG_CONFIG1,
-						  TPS65218_CONFIG1_GPO2_BUF,
-						  TPS65218_PROTECT_L1);
-			if (ret)
-				return ret;
-		}
-
 		/* Setup GPO2 */
 		ret = tps65218_clear_bits(tps65218, TPS65218_REG_CONFIG1,
 					  TPS65218_CONFIG1_IO1_SEL,
@@ -148,6 +138,40 @@ static int tps65218_gpio_request(struct
 	return 0;
 }
 
+static int tps65218_gpio_set_single_ended(struct gpio_chip *gc,
+					  unsigned offset,
+					  enum single_ended_mode mode)
+{
+	struct tps65218_gpio *tps65218_gpio = gpiochip_get_data(gc);
+	struct tps65218 *tps65218 = tps65218_gpio->tps65218;
+
+	switch (offset) {
+	case 0:
+	case 2:
+		/* GPO1 is hardwired to be open drain */
+		if (mode == LINE_MODE_OPEN_DRAIN)
+			return 0;
+		return -ENOTSUPP;
+	case 1:
+		/* GPO2 is push-pull by default, can be set as open drain. */
+		if (mode == LINE_MODE_OPEN_DRAIN)
+			return tps65218_clear_bits(tps65218,
+						   TPS65218_REG_CONFIG1,
+						   TPS65218_CONFIG1_GPO2_BUF,
+						   TPS65218_PROTECT_L1);
+		if (mode == LINE_MODE_PUSH_PULL)
+			return tps65218_set_bits(tps65218,
+						 TPS65218_REG_CONFIG1,
+						 TPS65218_CONFIG1_GPO2_BUF,
+						 TPS65218_CONFIG1_GPO2_BUF,
+						 TPS65218_PROTECT_L1);
+		return -ENOTSUPP;
+	default:
+		break;
+	}
+	return -ENOTSUPP;
+}
+
 static struct gpio_chip template_chip = {
 	.label			= "gpio-tps65218",
 	.owner			= THIS_MODULE,
@@ -156,6 +180,7 @@ static struct gpio_chip template_chip =
 	.direction_input	= tps65218_gpio_input,
 	.get			= tps65218_gpio_get,
 	.set			= tps65218_gpio_set,
+	.set_single_ended	= tps65218_gpio_set_single_ended,
 	.can_sleep		= true,
 	.ngpio			= 3,
 	.base			= -1,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-tps6586x.c linux-libre-4.7-gnu/drivers/gpio/gpio-tps6586x.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-tps6586x.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-tps6586x.c	2016-07-24 15:23:50.000000000 -0400
@@ -24,7 +24,7 @@
 #include <linux/errno.h>
 #include <linux/gpio.h>
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/mfd/tps6586x.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
@@ -140,14 +140,3 @@ static int __init tps6586x_gpio_init(voi
 	return platform_driver_register(&tps6586x_gpio_driver);
 }
 subsys_initcall(tps6586x_gpio_init);
-
-static void __exit tps6586x_gpio_exit(void)
-{
-	platform_driver_unregister(&tps6586x_gpio_driver);
-}
-module_exit(tps6586x_gpio_exit);
-
-MODULE_ALIAS("platform:tps6586x-gpio");
-MODULE_DESCRIPTION("GPIO interface for TPS6586X PMIC");
-MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
-MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-tps65910.c linux-libre-4.7-gnu/drivers/gpio/gpio-tps65910.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-tps65910.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-tps65910.c	2016-07-24 15:23:50.000000000 -0400
@@ -4,7 +4,7 @@
  * Copyright 2010 Texas Instruments Inc.
  *
  * Author: Graeme Gregory <gg@slimlogic.co.uk>
- * Author: Jorge Eduardo Candelaria jedu@slimlogic.co.uk>
+ * Author: Jorge Eduardo Candelaria <jedu@slimlogic.co.uk>
  *
  *  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
@@ -14,7 +14,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/gpio.h>
 #include <linux/i2c.h>
@@ -193,15 +193,3 @@ static int __init tps65910_gpio_init(voi
 	return platform_driver_register(&tps65910_gpio_driver);
 }
 subsys_initcall(tps65910_gpio_init);
-
-static void __exit tps65910_gpio_exit(void)
-{
-	platform_driver_unregister(&tps65910_gpio_driver);
-}
-module_exit(tps65910_gpio_exit);
-
-MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>");
-MODULE_AUTHOR("Jorge Eduardo Candelaria jedu@slimlogic.co.uk>");
-MODULE_DESCRIPTION("GPIO interface for TPS65910/TPS6511 PMICs");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:tps65910-gpio");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-vx855.c linux-libre-4.7-gnu/drivers/gpio/gpio-vx855.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-vx855.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-vx855.c	2016-07-24 15:23:50.000000000 -0400
@@ -186,6 +186,28 @@ static int vx855gpio_direction_output(st
 	return 0;
 }
 
+static int vx855gpio_set_single_ended(struct gpio_chip *gpio,
+				      unsigned int nr,
+				      enum single_ended_mode mode)
+{
+	/* The GPI cannot be single-ended */
+	if (nr < NR_VX855_GPI)
+		return -EINVAL;
+
+	/* The GPO's are push-pull */
+	if (nr < NR_VX855_GPInO) {
+		if (mode != LINE_MODE_PUSH_PULL)
+			return -ENOTSUPP;
+		return 0;
+	}
+
+	/* The GPIO's are open drain */
+	if (mode != LINE_MODE_OPEN_DRAIN)
+		return -ENOTSUPP;
+
+	return 0;
+}
+
 static const char *vx855gpio_names[NR_VX855_GP] = {
 	"VX855_GPI0", "VX855_GPI1", "VX855_GPI2", "VX855_GPI3", "VX855_GPI4",
 	"VX855_GPI5", "VX855_GPI6", "VX855_GPI7", "VX855_GPI8", "VX855_GPI9",
@@ -209,6 +231,7 @@ static void vx855gpio_gpio_setup(struct
 	c->direction_output = vx855gpio_direction_output;
 	c->get = vx855gpio_get;
 	c->set = vx855gpio_set;
+	c->set_single_ended = vx855gpio_set_single_ended;
 	c->dbg_show = NULL;
 	c->base = 0;
 	c->ngpio = NR_VX855_GP;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-wm831x.c linux-libre-4.7-gnu/drivers/gpio/gpio-wm831x.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-wm831x.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-wm831x.c	2016-07-24 15:23:50.000000000 -0400
@@ -132,6 +132,28 @@ static int wm831x_gpio_set_debounce(stru
 	return wm831x_set_bits(wm831x, reg, WM831X_GPN_FN_MASK, fn);
 }
 
+static int wm831x_set_single_ended(struct gpio_chip *chip,
+				   unsigned int offset,
+				   enum single_ended_mode mode)
+{
+	struct wm831x_gpio *wm831x_gpio = gpiochip_get_data(chip);
+	struct wm831x *wm831x = wm831x_gpio->wm831x;
+	int reg = WM831X_GPIO1_CONTROL + offset;
+
+	switch (mode) {
+	case LINE_MODE_OPEN_DRAIN:
+		return wm831x_set_bits(wm831x, reg,
+				       WM831X_GPN_OD_MASK, WM831X_GPN_OD);
+	case LINE_MODE_PUSH_PULL:
+		return wm831x_set_bits(wm831x, reg,
+				       WM831X_GPN_OD_MASK, 0);
+	default:
+		break;
+	}
+
+	return -ENOTSUPP;
+}
+
 #ifdef CONFIG_DEBUG_FS
 static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
 {
@@ -216,7 +238,7 @@ static void wm831x_gpio_dbg_show(struct
 			   pull,
 			   powerdomain,
 			   reg & WM831X_GPN_POL ? "" : " inverted",
-			   reg & WM831X_GPN_OD ? "open-drain" : "CMOS",
+			   reg & WM831X_GPN_OD ? "open-drain" : "push-pull",
 			   tristated ? " tristated" : "",
 			   reg);
 	}
@@ -234,6 +256,7 @@ static struct gpio_chip template_chip =
 	.set			= wm831x_gpio_set,
 	.to_irq			= wm831x_gpio_to_irq,
 	.set_debounce		= wm831x_gpio_set_debounce,
+	.set_single_ended	= wm831x_set_single_ended,
 	.dbg_show		= wm831x_gpio_dbg_show,
 	.can_sleep		= true,
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-wm8994.c linux-libre-4.7-gnu/drivers/gpio/gpio-wm8994.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-wm8994.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-wm8994.c	2016-07-24 15:23:50.000000000 -0400
@@ -103,6 +103,28 @@ static void wm8994_gpio_set(struct gpio_
 	wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset, WM8994_GPN_LVL, value);
 }
 
+static int wm8994_gpio_set_single_ended(struct gpio_chip *chip,
+					unsigned int offset,
+					enum single_ended_mode mode)
+{
+	struct wm8994_gpio *wm8994_gpio = gpiochip_get_data(chip);
+	struct wm8994 *wm8994 = wm8994_gpio->wm8994;
+
+	switch (mode) {
+	case LINE_MODE_OPEN_DRAIN:
+		return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset,
+				       WM8994_GPN_OP_CFG_MASK,
+				       WM8994_GPN_OP_CFG);
+	case LINE_MODE_PUSH_PULL:
+		return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset,
+				       WM8994_GPN_OP_CFG_MASK, 0);
+	default:
+		break;
+	}
+
+	return -ENOTSUPP;
+}
+
 static int wm8994_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
 {
 	struct wm8994_gpio *wm8994_gpio = gpiochip_get_data(chip);
@@ -217,7 +239,7 @@ static void wm8994_gpio_dbg_show(struct
 		if (reg & WM8994_GPN_OP_CFG)
 			seq_printf(s, "open drain ");
 		else
-			seq_printf(s, "CMOS ");
+			seq_printf(s, "push-pull ");
 
 		seq_printf(s, "%s (%x)\n",
 			   wm8994_gpio_fn(reg & WM8994_GPN_FN_MASK), reg);
@@ -235,6 +257,7 @@ static struct gpio_chip template_chip =
 	.get			= wm8994_gpio_get,
 	.direction_output	= wm8994_gpio_direction_out,
 	.set			= wm8994_gpio_set,
+	.set_single_ended	= wm8994_gpio_set_single_ended,
 	.to_irq			= wm8994_gpio_to_irq,
 	.dbg_show		= wm8994_gpio_dbg_show,
 	.can_sleep		= true,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-ws16c48.c linux-libre-4.7-gnu/drivers/gpio/gpio-ws16c48.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-ws16c48.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-ws16c48.c	2016-07-24 15:23:50.000000000 -0400
@@ -19,18 +19,23 @@
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/irqdesc.h>
+#include <linux/isa.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/platform_device.h>
 #include <linux/spinlock.h>
 
-static unsigned ws16c48_base;
-module_param(ws16c48_base, uint, 0);
-MODULE_PARM_DESC(ws16c48_base, "WinSystems WS16C48 base address");
-static unsigned ws16c48_irq;
-module_param(ws16c48_irq, uint, 0);
-MODULE_PARM_DESC(ws16c48_irq, "WinSystems WS16C48 interrupt line number");
+#define WS16C48_EXTENT 16
+#define MAX_NUM_WS16C48 max_num_isa_dev(WS16C48_EXTENT)
+
+static unsigned int base[MAX_NUM_WS16C48];
+static unsigned int num_ws16c48;
+module_param_array(base, uint, &num_ws16c48, 0);
+MODULE_PARM_DESC(base, "WinSystems WS16C48 base addresses");
+
+static unsigned int irq[MAX_NUM_WS16C48];
+module_param_array(irq, uint, NULL, 0);
+MODULE_PARM_DESC(irq, "WinSystems WS16C48 interrupt line numbers");
 
 /**
  * struct ws16c48_gpio - GPIO device private data structure
@@ -298,23 +303,19 @@ static irqreturn_t ws16c48_irq_handler(i
 	return IRQ_HANDLED;
 }
 
-static int __init ws16c48_probe(struct platform_device *pdev)
+static int ws16c48_probe(struct device *dev, unsigned int id)
 {
-	struct device *dev = &pdev->dev;
 	struct ws16c48_gpio *ws16c48gpio;
-	const unsigned base = ws16c48_base;
-	const unsigned extent = 16;
 	const char *const name = dev_name(dev);
 	int err;
-	const unsigned irq = ws16c48_irq;
 
 	ws16c48gpio = devm_kzalloc(dev, sizeof(*ws16c48gpio), GFP_KERNEL);
 	if (!ws16c48gpio)
 		return -ENOMEM;
 
-	if (!devm_request_region(dev, base, extent, name)) {
+	if (!devm_request_region(dev, base[id], WS16C48_EXTENT, name)) {
 		dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
-			base, base + extent);
+			base[id], base[id] + WS16C48_EXTENT);
 		return -EBUSY;
 	}
 
@@ -328,8 +329,8 @@ static int __init ws16c48_probe(struct p
 	ws16c48gpio->chip.direction_output = ws16c48_gpio_direction_output;
 	ws16c48gpio->chip.get = ws16c48_gpio_get;
 	ws16c48gpio->chip.set = ws16c48_gpio_set;
-	ws16c48gpio->base = base;
-	ws16c48gpio->irq = irq;
+	ws16c48gpio->base = base[id];
+	ws16c48gpio->irq = irq[id];
 
 	spin_lock_init(&ws16c48gpio->lock);
 
@@ -342,11 +343,11 @@ static int __init ws16c48_probe(struct p
 	}
 
 	/* Disable IRQ by default */
-	outb(0x80, base + 7);
-	outb(0, base + 8);
-	outb(0, base + 9);
-	outb(0, base + 10);
-	outb(0xC0, base + 7);
+	outb(0x80, base[id] + 7);
+	outb(0, base[id] + 8);
+	outb(0, base[id] + 9);
+	outb(0, base[id] + 10);
+	outb(0xC0, base[id] + 7);
 
 	err = gpiochip_irqchip_add(&ws16c48gpio->chip, &ws16c48_irqchip, 0,
 		handle_edge_irq, IRQ_TYPE_NONE);
@@ -355,7 +356,7 @@ static int __init ws16c48_probe(struct p
 		goto err_gpiochip_remove;
 	}
 
-	err = request_irq(irq, ws16c48_irq_handler, IRQF_SHARED, name,
+	err = request_irq(irq[id], ws16c48_irq_handler, IRQF_SHARED, name,
 		ws16c48gpio);
 	if (err) {
 		dev_err(dev, "IRQ handler registering failed (%d)\n", err);
@@ -369,9 +370,9 @@ err_gpiochip_remove:
 	return err;
 }
 
-static int ws16c48_remove(struct platform_device *pdev)
+static int ws16c48_remove(struct device *dev, unsigned int id)
 {
-	struct ws16c48_gpio *const ws16c48gpio = platform_get_drvdata(pdev);
+	struct ws16c48_gpio *const ws16c48gpio = dev_get_drvdata(dev);
 
 	free_irq(ws16c48gpio->irq, ws16c48gpio);
 	gpiochip_remove(&ws16c48gpio->chip);
@@ -379,48 +380,15 @@ static int ws16c48_remove(struct platfor
 	return 0;
 }
 
-static struct platform_device *ws16c48_device;
-
-static struct platform_driver ws16c48_driver = {
+static struct isa_driver ws16c48_driver = {
+	.probe = ws16c48_probe,
 	.driver = {
 		.name = "ws16c48"
 	},
 	.remove = ws16c48_remove
 };
 
-static void __exit ws16c48_exit(void)
-{
-	platform_device_unregister(ws16c48_device);
-	platform_driver_unregister(&ws16c48_driver);
-}
-
-static int __init ws16c48_init(void)
-{
-	int err;
-
-	ws16c48_device = platform_device_alloc(ws16c48_driver.driver.name, -1);
-	if (!ws16c48_device)
-		return -ENOMEM;
-
-	err = platform_device_add(ws16c48_device);
-	if (err)
-		goto err_platform_device;
-
-	err = platform_driver_probe(&ws16c48_driver, ws16c48_probe);
-	if (err)
-		goto err_platform_driver;
-
-	return 0;
-
-err_platform_driver:
-	platform_device_del(ws16c48_device);
-err_platform_device:
-	platform_device_put(ws16c48_device);
-	return err;
-}
-
-module_init(ws16c48_init);
-module_exit(ws16c48_exit);
+module_isa_driver(ws16c48_driver, num_ws16c48);
 
 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
 MODULE_DESCRIPTION("WinSystems WS16C48 GPIO driver");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-xgene.c linux-libre-4.7-gnu/drivers/gpio/gpio-xgene.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-xgene.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-xgene.c	2016-07-24 15:23:50.000000000 -0400
@@ -17,7 +17,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <linux/module.h>
+#include <linux/acpi.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/io.h>
@@ -85,6 +85,17 @@ static void xgene_gpio_set(struct gpio_c
 	spin_unlock_irqrestore(&chip->lock, flags);
 }
 
+static int xgene_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
+{
+	struct xgene_gpio *chip = gpiochip_get_data(gc);
+	unsigned long bank_offset, bit_offset;
+
+	bank_offset = GPIO_SET_DR_OFFSET + GPIO_BANK_OFFSET(offset);
+	bit_offset = GPIO_BIT_OFFSET(offset);
+
+	return !!(ioread32(chip->base + bank_offset) & BIT(bit_offset));
+}
+
 static int xgene_gpio_dir_in(struct gpio_chip *gc, unsigned int offset)
 {
 	struct xgene_gpio *chip = gpiochip_get_data(gc);
@@ -189,6 +200,7 @@ static int xgene_gpio_probe(struct platf
 
 	spin_lock_init(&gpio->lock);
 	gpio->chip.parent = &pdev->dev;
+	gpio->chip.get_direction = xgene_gpio_get_direction;
 	gpio->chip.direction_input = xgene_gpio_dir_in;
 	gpio->chip.direction_output = xgene_gpio_dir_out;
 	gpio->chip.get = xgene_gpio_get;
@@ -216,19 +228,21 @@ static const struct of_device_id xgene_g
 	{ .compatible = "apm,xgene-gpio", },
 	{},
 };
-MODULE_DEVICE_TABLE(of, xgene_gpio_of_match);
+
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id xgene_gpio_acpi_match[] = {
+	{ "APMC0D14", 0 },
+	{ },
+};
+#endif
 
 static struct platform_driver xgene_gpio_driver = {
 	.driver = {
 		.name = "xgene-gpio",
 		.of_match_table = xgene_gpio_of_match,
+		.acpi_match_table = ACPI_PTR(xgene_gpio_acpi_match),
 		.pm     = XGENE_GPIO_PM_OPS,
 	},
 	.probe = xgene_gpio_probe,
 };
-
-module_platform_driver(xgene_gpio_driver);
-
-MODULE_AUTHOR("Feng Kan <fkan@apm.com>");
-MODULE_DESCRIPTION("APM X-Gene GPIO driver");
-MODULE_LICENSE("GPL");
+builtin_platform_driver(xgene_gpio_driver);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-xgene-sb.c linux-libre-4.7-gnu/drivers/gpio/gpio-xgene-sb.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-xgene-sb.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-xgene-sb.c	2016-07-24 15:23:50.000000000 -0400
@@ -216,23 +216,10 @@ static int xgene_gpio_sb_domain_alloc(st
 			&parent_fwspec);
 }
 
-static void xgene_gpio_sb_domain_free(struct irq_domain *domain,
-		unsigned int virq,
-		unsigned int nr_irqs)
-{
-	struct irq_data *d;
-	unsigned int i;
-
-	for (i = 0; i < nr_irqs; i++) {
-		d = irq_domain_get_irq_data(domain, virq + i);
-		irq_domain_reset_irq_data(d);
-	}
-}
-
 static const struct irq_domain_ops xgene_gpio_sb_domain_ops = {
 	.translate      = xgene_gpio_sb_domain_translate,
 	.alloc          = xgene_gpio_sb_domain_alloc,
-	.free           = xgene_gpio_sb_domain_free,
+	.free           = irq_domain_free_irqs_common,
 	.activate	= xgene_gpio_sb_domain_activate,
 	.deactivate	= xgene_gpio_sb_domain_deactivate,
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-xlp.c linux-libre-4.7-gnu/drivers/gpio/gpio-xlp.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-xlp.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-xlp.c	2016-07-24 15:23:50.000000000 -0400
@@ -85,7 +85,8 @@ enum {
 	XLP_GPIO_VARIANT_XLP316,
 	XLP_GPIO_VARIANT_XLP208,
 	XLP_GPIO_VARIANT_XLP980,
-	XLP_GPIO_VARIANT_XLP532
+	XLP_GPIO_VARIANT_XLP532,
+	GPIO_VARIANT_VULCAN
 };
 
 struct xlp_gpio_priv {
@@ -285,6 +286,10 @@ static const struct of_device_id xlp_gpi
 		.compatible = "netlogic,xlp532-gpio",
 		.data	    = (void *)XLP_GPIO_VARIANT_XLP532,
 	},
+	{
+		.compatible = "brcm,vulcan-gpio",
+		.data	    = (void *)GPIO_VARIANT_VULCAN,
+	},
 	{ /* sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, xlp_gpio_of_ids);
@@ -347,6 +352,7 @@ static int xlp_gpio_probe(struct platfor
 		break;
 	case XLP_GPIO_VARIANT_XLP980:
 	case XLP_GPIO_VARIANT_XLP532:
+	case GPIO_VARIANT_VULCAN:
 		priv->gpio_out_en = gpio_base + GPIO_9XX_OUTPUT_EN;
 		priv->gpio_paddrv = gpio_base + GPIO_9XX_PADDRV;
 		priv->gpio_intr_stat = gpio_base + GPIO_9XX_INT_STAT;
@@ -354,7 +360,12 @@ static int xlp_gpio_probe(struct platfor
 		priv->gpio_intr_pol = gpio_base + GPIO_9XX_INT_POL;
 		priv->gpio_intr_en = gpio_base + GPIO_9XX_INT_EN00;
 
-		ngpio = (soc_type == XLP_GPIO_VARIANT_XLP980) ? 66 : 67;
+		if (soc_type == XLP_GPIO_VARIANT_XLP980)
+			ngpio = 66;
+		else if (soc_type == XLP_GPIO_VARIANT_XLP532)
+			ngpio = 67;
+		else
+			ngpio = 70;
 		break;
 	default:
 		dev_err(&pdev->dev, "Unknown Processor type!\n");
@@ -377,10 +388,14 @@ static int xlp_gpio_probe(struct platfor
 	gc->get = xlp_gpio_get;
 
 	spin_lock_init(&priv->lock);
-	irq_base = irq_alloc_descs(-1, XLP_GPIO_IRQ_BASE, gc->ngpio, 0);
+	/* XLP has fixed IRQ range for GPIO interrupts */
+	if (soc_type == GPIO_VARIANT_VULCAN)
+		irq_base = irq_alloc_descs(-1, 0, gc->ngpio, 0);
+	else
+		irq_base = irq_alloc_descs(-1, XLP_GPIO_IRQ_BASE, gc->ngpio, 0);
 	if (irq_base < 0) {
 		dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n");
-		return -ENODEV;
+		return irq_base;
 	}
 
 	err = gpiochip_add_data(gc, priv);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-zevio.c linux-libre-4.7-gnu/drivers/gpio/gpio-zevio.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-zevio.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-zevio.c	2016-07-24 15:23:50.000000000 -0400
@@ -10,7 +10,7 @@
 
 #include <linux/spinlock.h>
 #include <linux/errno.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/bitops.h>
 #include <linux/io.h>
 #include <linux/of_device.h>
@@ -203,32 +203,17 @@ static int zevio_gpio_probe(struct platf
 	return 0;
 }
 
-static int zevio_gpio_remove(struct platform_device *pdev)
-{
-	struct zevio_gpio *controller = platform_get_drvdata(pdev);
-
-	of_mm_gpiochip_remove(&controller->chip);
-
-	return 0;
-}
-
 static const struct of_device_id zevio_gpio_of_match[] = {
 	{ .compatible = "lsi,zevio-gpio", },
 	{ },
 };
 
-MODULE_DEVICE_TABLE(of, zevio_gpio_of_match);
-
 static struct platform_driver zevio_gpio_driver = {
 	.driver		= {
 		.name	= "gpio-zevio",
 		.of_match_table = zevio_gpio_of_match,
+		.suppress_bind_attrs = true,
 	},
 	.probe		= zevio_gpio_probe,
-	.remove		= zevio_gpio_remove,
 };
-module_platform_driver(zevio_gpio_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Fabian Vogt <fabian@ritter-vogt.de>");
-MODULE_DESCRIPTION("LSI ZEVIO SoC GPIO driver");
+builtin_platform_driver(zevio_gpio_driver);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-zx.c linux-libre-4.7-gnu/drivers/gpio/gpio-zx.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-zx.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-zx.c	2016-07-24 15:23:50.000000000 -0400
@@ -1,4 +1,8 @@
 /*
+ * ZTE ZX296702 GPIO driver
+ *
+ * Author: Jun Nie <jun.nie@linaro.org>
+ *
  * Copyright (C) 2015 Linaro Ltd.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -10,7 +14,7 @@
 #include <linux/errno.h>
 #include <linux/gpio/driver.h>
 #include <linux/irqchip/chained_irq.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/of.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/platform_device.h>
@@ -282,7 +286,6 @@ static const struct of_device_id zx_gpio
 	},
 	{ },
 };
-MODULE_DEVICE_TABLE(of, zx_gpio_match);
 
 static struct platform_driver zx_gpio_driver = {
 	.probe		= zx_gpio_probe,
@@ -291,9 +294,4 @@ static struct platform_driver zx_gpio_dr
 		.of_match_table = of_match_ptr(zx_gpio_match),
 	},
 };
-
-module_platform_driver(zx_gpio_driver)
-
-MODULE_AUTHOR("Jun Nie <jun.nie@linaro.org>");
-MODULE_DESCRIPTION("ZTE ZX296702 GPIO driver");
-MODULE_LICENSE("GPL");
+builtin_platform_driver(zx_gpio_driver)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/gpio-zynq.c linux-libre-4.7-gnu/drivers/gpio/gpio-zynq.c
--- linux-libre-4.6-gnu/drivers/gpio/gpio-zynq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/gpio-zynq.c	2016-07-24 15:23:50.000000000 -0400
@@ -709,11 +709,17 @@ static int zynq_gpio_probe(struct platfo
 		dev_err(&pdev->dev, "input clock not found.\n");
 		return PTR_ERR(gpio->clk);
 	}
+	ret = clk_prepare_enable(gpio->clk);
+	if (ret) {
+		dev_err(&pdev->dev, "Unable to enable clock.\n");
+		return ret;
+	}
 
+	pm_runtime_set_active(&pdev->dev);
 	pm_runtime_enable(&pdev->dev);
 	ret = pm_runtime_get_sync(&pdev->dev);
 	if (ret < 0)
-		return ret;
+		goto err_pm_dis;
 
 	/* report a bug if gpio chip registration fails */
 	ret = gpiochip_add_data(chip, gpio);
@@ -745,6 +751,9 @@ err_rm_gpiochip:
 	gpiochip_remove(chip);
 err_pm_put:
 	pm_runtime_put(&pdev->dev);
+err_pm_dis:
+	pm_runtime_disable(&pdev->dev);
+	clk_disable_unprepare(gpio->clk);
 
 	return ret;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/Kconfig linux-libre-4.7-gnu/drivers/gpio/Kconfig
--- linux-libre-4.6-gnu/drivers/gpio/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -33,7 +33,7 @@ config ARCH_REQUIRE_GPIOLIB
 
 menuconfig GPIOLIB
 	bool "GPIO Support"
-	depends on ARCH_WANT_OPTIONAL_GPIOLIB || ARCH_REQUIRE_GPIOLIB
+	select ANON_INODES
 	help
 	  This enables GPIO support through the generic GPIO library.
 	  You only need to enable this, if you also want to enable
@@ -122,6 +122,7 @@ config GPIO_ALTERA
 config GPIO_AMDPT
 	tristate "AMD Promontory GPIO support"
 	depends on ACPI
+	select GPIO_GENERIC
 	help
 	  driver for GPIO functionality on Promontory IOHub
 	  Require ACPI ASL code to enumerate as a platform device.
@@ -303,6 +304,7 @@ config GPIO_MPC8XXX
 		   FSL_SOC_BOOKE || PPC_86xx || ARCH_LAYERSCAPE || ARM || \
 		   COMPILE_TEST
 	select GPIO_GENERIC
+	select IRQ_DOMAIN
 	help
 	  Say Y here if you're going to use hardware that connects to the
 	  MPC512x/831x/834x/837x/8572/8610/QorIQ GPIOs.
@@ -399,6 +401,14 @@ config GPIO_TB10X
 	select GENERIC_IRQ_CHIP
 	select OF_GPIO
 
+config GPIO_TEGRA
+	bool "NVIDIA Tegra GPIO support"
+	default ARCH_TEGRA
+	depends on ARCH_TEGRA || COMPILE_TEST
+	depends on OF
+	help
+	  Say yes here to support GPIO pins on NVIDIA Tegra SoCs.
+
 config GPIO_TS4800
 	tristate "TS-4800 DIO blocks and compatibles"
 	depends on OF_GPIO
@@ -473,7 +483,7 @@ config GPIO_XILINX
 
 config GPIO_XLP
 	tristate "Netlogic XLP GPIO support"
-	depends on CPU_XLP && OF_GPIO
+	depends on OF_GPIO && (CPU_XLP || ARCH_VULCAN || COMPILE_TEST)
 	select GPIOLIB_IRQCHIP
 	help
 	  This driver provides support for GPIO interface on Netlogic XLP MIPS64
@@ -510,6 +520,13 @@ config GPIO_ZX
 	help
 	  Say yes here to support the GPIO device on ZTE ZX SoCs.
 
+config GPIO_LOONGSON1
+	tristate "Loongson1 GPIO support"
+	depends on MACH_LOONGSON32
+	select GPIO_GENERIC
+	help
+	  Say Y or M here to support GPIO on Loongson1 SoCs.
+
 endmenu
 
 menu "Port-mapped I/O GPIO drivers"
@@ -517,30 +534,35 @@ menu "Port-mapped I/O GPIO drivers"
 
 config GPIO_104_DIO_48E
 	tristate "ACCES 104-DIO-48E GPIO support"
+	depends on ISA_BUS_API
 	select GPIOLIB_IRQCHIP
 	help
-	  Enables GPIO support for the ACCES 104-DIO-48E family. The base port
-	  address for the device may be configured via the dio_48e_base module
-	  parameter. The interrupt line number for the device may be configured
-	  via the dio_48e_irq module parameter.
+	  Enables GPIO support for the ACCES 104-DIO-48E series (104-DIO-48E,
+	  104-DIO-24E). The base port addresses for the devices may be
+	  configured via the base module parameter. The interrupt line numbers
+	  for the devices may be configured via the irq module parameter.
 
 config GPIO_104_IDIO_16
 	tristate "ACCES 104-IDIO-16 GPIO support"
+	depends on ISA_BUS_API
 	select GPIOLIB_IRQCHIP
 	help
-	  Enables GPIO support for the ACCES 104-IDIO-16 family. The base port
-	  address for the device may be set via the idio_16_base module
-	  parameter. The interrupt line number for the device may be set via the
-	  idio_16_irq module parameter.
+	  Enables GPIO support for the ACCES 104-IDIO-16 family (104-IDIO-16,
+	  104-IDIO-16E, 104-IDO-16, 104-IDIO-8, 104-IDIO-8E, 104-IDO-8). The
+	  base port addresses for the devices may be configured via the base
+	  module parameter. The interrupt line numbers for the devices may be
+	  configured via the irq module parameter.
 
 config GPIO_104_IDI_48
 	tristate "ACCES 104-IDI-48 GPIO support"
+	depends on ISA_BUS_API
 	select GPIOLIB_IRQCHIP
 	help
-	  Enables GPIO support for the ACCES 104-IDI-48 family. The base port
-	  address for the device may be configured via the idi_48_base module
-	  parameter. The interrupt line number for the device may be configured
-	  via the idi_48_irq module parameter.
+	  Enables GPIO support for the ACCES 104-IDI-48 family (104-IDI-48A,
+	  104-IDI-48AC, 104-IDI-48B, 104-IDI-48BC). The base port addresses for
+	  the devices may be configured via the base module parameter. The
+	  interrupt line numbers for the devices may be configured via the irq
+	  module parameter.
 
 config GPIO_F7188X
 	tristate "F71869, F71869A, F71882FG, F71889F and F81866 GPIO support"
@@ -557,7 +579,7 @@ config GPIO_IT87
 	  Say yes here to support GPIO functionality of IT87xx Super I/O chips.
 
 	  This driver is tested with ITE IT8728 and IT8732 Super I/O chips, and
-	  supports the IT8761E Super I/O chip as well.
+	  supports the IT8761E, IT8620E and IT8628E Super I/O chip as well.
 
 	  To compile this driver as a module, choose M here: the module will
 	  be called gpio_it87
@@ -609,12 +631,13 @@ config GPIO_TS5500
 
 config GPIO_WS16C48
 	tristate "WinSystems WS16C48 GPIO support"
+	depends on ISA_BUS_API
 	select GPIOLIB_IRQCHIP
 	help
-	  Enables GPIO support for the WinSystems WS16C48. The base port address
-	  for the device may be configured via the ws16c48_base module
-	  parameter. The interrupt line number for the device may be configured
-	  via the ws16c48_irq module parameter.
+	  Enables GPIO support for the WinSystems WS16C48. The base port
+	  addresses for the devices may be configured via the base module
+	  parameter. The interrupt line numbers for the devices may be
+	  configured via the irq module parameter.
 
 endmenu
 
@@ -1091,6 +1114,7 @@ menu "SPI or I2C GPIO expanders"
 
 config GPIO_MCP23S08
 	tristate "Microchip MCP23xxx I/O expander"
+	select GPIOLIB_IRQCHIP
 	help
 	  SPI/I2C driver for Microchip MCP23S08/MCP23S17/MCP23008/MCP23017
 	  I/O expanders.
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpio/Makefile linux-libre-4.7-gnu/drivers/gpio/Makefile
--- linux-libre-4.6-gnu/drivers/gpio/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpio/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -12,6 +12,9 @@ obj-$(CONFIG_GPIO_ACPI)		+= gpiolib-acpi
 # Device drivers. Generally keep list sorted alphabetically
 obj-$(CONFIG_GPIO_GENERIC)	+= gpio-generic.o
 
+# directly supported by gpio-generic
+gpio-generic-$(CONFIG_GPIO_GENERIC)	+= gpio-mmio.o
+
 obj-$(CONFIG_GPIO_104_DIO_48E)	+= gpio-104-dio-48e.o
 obj-$(CONFIG_GPIO_104_IDIO_16)	+= gpio-104-idio-16.o
 obj-$(CONFIG_GPIO_104_IDI_48)	+= gpio-104-idi-48.o
@@ -95,7 +98,7 @@ obj-$(CONFIG_GPIO_SX150X)	+= gpio-sx150x
 obj-$(CONFIG_GPIO_SYSCON)	+= gpio-syscon.o
 obj-$(CONFIG_GPIO_TB10X)	+= gpio-tb10x.o
 obj-$(CONFIG_GPIO_TC3589X)	+= gpio-tc3589x.o
-obj-$(CONFIG_ARCH_TEGRA)	+= gpio-tegra.o
+obj-$(CONFIG_GPIO_TEGRA)	+= gpio-tegra.o
 obj-$(CONFIG_GPIO_TIMBERDALE)	+= gpio-timberdale.o
 obj-$(CONFIG_GPIO_PALMAS)	+= gpio-palmas.o
 obj-$(CONFIG_GPIO_TPIC2810)	+= gpio-tpic2810.o
@@ -127,3 +130,4 @@ obj-$(CONFIG_GPIO_XTENSA)	+= gpio-xtensa
 obj-$(CONFIG_GPIO_ZEVIO)	+= gpio-zevio.o
 obj-$(CONFIG_GPIO_ZYNQ)		+= gpio-zynq.o
 obj-$(CONFIG_GPIO_ZX)		+= gpio-zx.o
+obj-$(CONFIG_GPIO_LOONGSON1)	+= gpio-loongson1.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/acp/acp_hw.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/acp/acp_hw.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/acp/acp_hw.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/acp/acp_hw.c	2016-07-24 15:23:50.000000000 -0400
@@ -34,7 +34,7 @@
 
 #define mmACP_AZALIA_I2S_SELECT 0x51d4
 
-int amd_acp_hw_init(void *cgs_device,
+int amd_acp_hw_init(struct cgs_device *cgs_device,
 		    unsigned acp_version_major, unsigned acp_version_minor)
 {
 	unsigned int acp_mode = ACP_MODE_I2S;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/acp/include/acp_gfx_if.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/acp/include/acp_gfx_if.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/acp/include/acp_gfx_if.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/acp/include/acp_gfx_if.h	2016-07-24 15:23:50.000000000 -0400
@@ -28,7 +28,7 @@
 #include "cgs_linux.h"
 #include "cgs_common.h"
 
-int amd_acp_hw_init(void *cgs_device,
+int amd_acp_hw_init(struct cgs_device *cgs_device,
 		    unsigned acp_version_major, unsigned acp_version_minor);
 
 #endif /* _ACP_GFX_IF_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/acp/Kconfig linux-libre-4.7-gnu/drivers/gpu/drm/amd/acp/Kconfig
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/acp/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/acp/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -2,6 +2,7 @@ menu "ACP (Audio CoProcessor) Configurat
 
 config DRM_AMD_ACP
        bool "Enable AMD Audio CoProcessor IP support"
+       depends on DRM_AMDGPU
        select MFD_CORE
        select PM_GENERIC_DOMAINS if PM
        help
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c	2016-07-24 15:23:50.000000000 -0400
@@ -467,13 +467,6 @@ static int acp_soft_reset(void *handle)
 	return 0;
 }
 
-static void acp_print_status(void *handle)
-{
-	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-	dev_info(adev->dev, "ACP STATUS\n");
-}
-
 static int acp_set_clockgating_state(void *handle,
 				     enum amd_clockgating_state state)
 {
@@ -487,6 +480,7 @@ static int acp_set_powergating_state(voi
 }
 
 const struct amd_ip_funcs acp_ip_funcs = {
+	.name = "acp_ip",
 	.early_init = acp_early_init,
 	.late_init = NULL,
 	.sw_init = acp_sw_init,
@@ -498,7 +492,6 @@ const struct amd_ip_funcs acp_ip_funcs =
 	.is_idle = acp_is_idle,
 	.wait_for_idle = acp_wait_for_idle,
 	.soft_reset = acp_soft_reset,
-	.print_status = acp_print_status,
 	.set_clockgating_state = acp_set_clockgating_state,
 	.set_powergating_state = acp_set_powergating_state,
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.h	2016-07-24 15:23:50.000000000 -0400
@@ -30,7 +30,7 @@
 
 struct amdgpu_acp {
 	struct device *parent;
-	void *cgs_device;
+	struct cgs_device *cgs_device;
 	struct amd_acp_private *private;
 	struct mfd_cell *acp_cell;
 	struct resource *acp_res;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c	2016-07-24 15:23:50.000000000 -0400
@@ -234,16 +234,6 @@ amdgpu_atombios_get_hpd_info_from_gpio(s
 	return hpd;
 }
 
-static bool amdgpu_atombios_apply_quirks(struct amdgpu_device *adev,
-					 uint32_t supported_device,
-					 int *connector_type,
-					 struct amdgpu_i2c_bus_rec *i2c_bus,
-					 uint16_t *line_mux,
-					 struct amdgpu_hpd *hpd)
-{
-	return true;
-}
-
 static const int object_connector_convert[] = {
 	DRM_MODE_CONNECTOR_Unknown,
 	DRM_MODE_CONNECTOR_DVII,
@@ -514,11 +504,6 @@ bool amdgpu_atombios_get_connector_info_
 
 			conn_id = le16_to_cpu(path->usConnObjectId);
 
-			if (!amdgpu_atombios_apply_quirks
-			    (adev, le16_to_cpu(path->usDeviceTag), &connector_type,
-			     &ddc_bus, &conn_id, &hpd))
-				continue;
-
 			amdgpu_display_add_connector(adev,
 						      conn_id,
 						      le16_to_cpu(path->usDeviceTag),
@@ -699,6 +684,36 @@ int amdgpu_atombios_get_clock_info(struc
 	return ret;
 }
 
+union gfx_info {
+	ATOM_GFX_INFO_V2_1 info;
+};
+
+int amdgpu_atombios_get_gfx_info(struct amdgpu_device *adev)
+{
+	struct amdgpu_mode_info *mode_info = &adev->mode_info;
+	int index = GetIndexIntoMasterTable(DATA, GFX_Info);
+	uint8_t frev, crev;
+	uint16_t data_offset;
+	int ret = -EINVAL;
+
+	if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
+				   &frev, &crev, &data_offset)) {
+		union gfx_info *gfx_info = (union gfx_info *)
+			(mode_info->atom_context->bios + data_offset);
+
+		adev->gfx.config.max_shader_engines = gfx_info->info.max_shader_engines;
+		adev->gfx.config.max_tile_pipes = gfx_info->info.max_tile_pipes;
+		adev->gfx.config.max_cu_per_sh = gfx_info->info.max_cu_per_sh;
+		adev->gfx.config.max_sh_per_se = gfx_info->info.max_sh_per_se;
+		adev->gfx.config.max_backends_per_se = gfx_info->info.max_backends_per_se;
+		adev->gfx.config.max_texture_channel_caches =
+			gfx_info->info.max_texture_channel_caches;
+
+		ret = 0;
+	}
+	return ret;
+}
+
 union igp_info {
 	struct _ATOM_INTEGRATED_SYSTEM_INFO info;
 	struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h	2016-07-24 15:23:50.000000000 -0400
@@ -144,6 +144,8 @@ bool amdgpu_atombios_get_connector_info_
 
 int amdgpu_atombios_get_clock_info(struct amdgpu_device *adev);
 
+int amdgpu_atombios_get_gfx_info(struct amdgpu_device *adev);
+
 bool amdgpu_atombios_get_asic_ss_info(struct amdgpu_device *adev,
 				      struct amdgpu_atom_ss *ss,
 				      int id, u32 clock);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c	2016-07-24 15:23:50.000000000 -0400
@@ -141,7 +141,7 @@ out_cleanup:
 void amdgpu_benchmark(struct amdgpu_device *adev, int test_number)
 {
 	int i;
-	int common_modes[AMDGPU_BENCHMARK_COMMON_MODES_N] = {
+	static const int common_modes[AMDGPU_BENCHMARK_COMMON_MODES_N] = {
 		640 * 480 * 4,
 		720 * 480 * 4,
 		800 * 600 * 4,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c	2016-07-24 15:23:50.000000000 -0400
@@ -349,7 +349,7 @@ static inline bool amdgpu_acpi_vfct_bios
 bool amdgpu_get_bios(struct amdgpu_device *adev)
 {
 	bool r;
-	uint16_t tmp;
+	uint16_t tmp, bios_header_start;
 
 	r = amdgpu_atrm_get_bios(adev);
 	if (r == false)
@@ -383,11 +383,11 @@ bool amdgpu_get_bios(struct amdgpu_devic
 		goto free_bios;
 	}
 
-	adev->bios_header_start = RBIOS16(0x48);
-	if (!adev->bios_header_start) {
+	bios_header_start = RBIOS16(0x48);
+	if (!bios_header_start) {
 		goto free_bios;
 	}
-	tmp = adev->bios_header_start + 4;
+	tmp = bios_header_start + 4;
 	if (!memcmp(adev->bios + tmp, "ATOM", 4) ||
 	    !memcmp(adev->bios + tmp, "MOTA", 4)) {
 		adev->is_atom_bios = true;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c	2016-07-24 15:23:50.000000000 -0400
@@ -106,7 +106,7 @@ static int amdgpu_bo_list_set(struct amd
 		struct amdgpu_bo *bo;
 		struct mm_struct *usermm;
 
-		gobj = drm_gem_object_lookup(adev->ddev, filp, info[i].bo_handle);
+		gobj = drm_gem_object_lookup(filp, info[i].bo_handle);
 		if (!gobj) {
 			r = -ENOENT;
 			goto error_free;
@@ -263,7 +263,7 @@ int amdgpu_bo_list_ioctl(struct drm_devi
 		for (i = 0; i < args->in.bo_number; ++i) {
 			if (copy_from_user(&info[i], uptr, bytes))
 				goto error_free;
-			
+
 			uptr += args->in.bo_info_size;
 		}
 	}
@@ -271,7 +271,7 @@ int amdgpu_bo_list_ioctl(struct drm_devi
 	switch (args->in.operation) {
 	case AMDGPU_BO_LIST_OP_CREATE:
 		r = amdgpu_bo_list_create(fpriv, &list, &handle);
-		if (r) 
+		if (r)
 			goto error_free;
 
 		r = amdgpu_bo_list_set(adev, filp, list, info,
@@ -281,7 +281,7 @@ int amdgpu_bo_list_ioctl(struct drm_devi
 			goto error_free;
 
 		break;
-		
+
 	case AMDGPU_BO_LIST_OP_DESTROY:
 		amdgpu_bo_list_destroy(fpriv, handle);
 		handle = 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c	2016-05-15 19:21:01.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c	2016-07-24 18:17:28.000000000 -0400
@@ -42,7 +42,7 @@ struct amdgpu_cgs_device {
 	struct amdgpu_device *adev =					\
 		((struct amdgpu_cgs_device *)cgs_device)->adev
 
-static int amdgpu_cgs_gpu_mem_info(void *cgs_device, enum cgs_gpu_mem_type type,
+static int amdgpu_cgs_gpu_mem_info(struct cgs_device *cgs_device, enum cgs_gpu_mem_type type,
 				   uint64_t *mc_start, uint64_t *mc_size,
 				   uint64_t *mem_size)
 {
@@ -73,7 +73,7 @@ static int amdgpu_cgs_gpu_mem_info(void
 	return 0;
 }
 
-static int amdgpu_cgs_gmap_kmem(void *cgs_device, void *kmem,
+static int amdgpu_cgs_gmap_kmem(struct cgs_device *cgs_device, void *kmem,
 				uint64_t size,
 				uint64_t min_offset, uint64_t max_offset,
 				cgs_handle_t *kmem_handle, uint64_t *mcaddr)
@@ -102,7 +102,7 @@ static int amdgpu_cgs_gmap_kmem(void *cg
 	return ret;
 }
 
-static int amdgpu_cgs_gunmap_kmem(void *cgs_device, cgs_handle_t kmem_handle)
+static int amdgpu_cgs_gunmap_kmem(struct cgs_device *cgs_device, cgs_handle_t kmem_handle)
 {
 	struct amdgpu_bo *obj = (struct amdgpu_bo *)kmem_handle;
 
@@ -118,7 +118,7 @@ static int amdgpu_cgs_gunmap_kmem(void *
 	return 0;
 }
 
-static int amdgpu_cgs_alloc_gpu_mem(void *cgs_device,
+static int amdgpu_cgs_alloc_gpu_mem(struct cgs_device *cgs_device,
 				    enum cgs_gpu_mem_type type,
 				    uint64_t size, uint64_t align,
 				    uint64_t min_offset, uint64_t max_offset,
@@ -208,7 +208,7 @@ static int amdgpu_cgs_alloc_gpu_mem(void
 	return ret;
 }
 
-static int amdgpu_cgs_free_gpu_mem(void *cgs_device, cgs_handle_t handle)
+static int amdgpu_cgs_free_gpu_mem(struct cgs_device *cgs_device, cgs_handle_t handle)
 {
 	struct amdgpu_bo *obj = (struct amdgpu_bo *)handle;
 
@@ -225,7 +225,7 @@ static int amdgpu_cgs_free_gpu_mem(void
 	return 0;
 }
 
-static int amdgpu_cgs_gmap_gpu_mem(void *cgs_device, cgs_handle_t handle,
+static int amdgpu_cgs_gmap_gpu_mem(struct cgs_device *cgs_device, cgs_handle_t handle,
 				   uint64_t *mcaddr)
 {
 	int r;
@@ -246,7 +246,7 @@ static int amdgpu_cgs_gmap_gpu_mem(void
 	return r;
 }
 
-static int amdgpu_cgs_gunmap_gpu_mem(void *cgs_device, cgs_handle_t handle)
+static int amdgpu_cgs_gunmap_gpu_mem(struct cgs_device *cgs_device, cgs_handle_t handle)
 {
 	int r;
 	struct amdgpu_bo *obj = (struct amdgpu_bo *)handle;
@@ -258,7 +258,7 @@ static int amdgpu_cgs_gunmap_gpu_mem(voi
 	return r;
 }
 
-static int amdgpu_cgs_kmap_gpu_mem(void *cgs_device, cgs_handle_t handle,
+static int amdgpu_cgs_kmap_gpu_mem(struct cgs_device *cgs_device, cgs_handle_t handle,
 				   void **map)
 {
 	int r;
@@ -271,7 +271,7 @@ static int amdgpu_cgs_kmap_gpu_mem(void
 	return r;
 }
 
-static int amdgpu_cgs_kunmap_gpu_mem(void *cgs_device, cgs_handle_t handle)
+static int amdgpu_cgs_kunmap_gpu_mem(struct cgs_device *cgs_device, cgs_handle_t handle)
 {
 	int r;
 	struct amdgpu_bo *obj = (struct amdgpu_bo *)handle;
@@ -283,20 +283,20 @@ static int amdgpu_cgs_kunmap_gpu_mem(voi
 	return r;
 }
 
-static uint32_t amdgpu_cgs_read_register(void *cgs_device, unsigned offset)
+static uint32_t amdgpu_cgs_read_register(struct cgs_device *cgs_device, unsigned offset)
 {
 	CGS_FUNC_ADEV;
 	return RREG32(offset);
 }
 
-static void amdgpu_cgs_write_register(void *cgs_device, unsigned offset,
+static void amdgpu_cgs_write_register(struct cgs_device *cgs_device, unsigned offset,
 				      uint32_t value)
 {
 	CGS_FUNC_ADEV;
 	WREG32(offset, value);
 }
 
-static uint32_t amdgpu_cgs_read_ind_register(void *cgs_device,
+static uint32_t amdgpu_cgs_read_ind_register(struct cgs_device *cgs_device,
 					     enum cgs_ind_reg space,
 					     unsigned index)
 {
@@ -320,7 +320,7 @@ static uint32_t amdgpu_cgs_read_ind_regi
 	return 0;
 }
 
-static void amdgpu_cgs_write_ind_register(void *cgs_device,
+static void amdgpu_cgs_write_ind_register(struct cgs_device *cgs_device,
 					  enum cgs_ind_reg space,
 					  unsigned index, uint32_t value)
 {
@@ -343,7 +343,7 @@ static void amdgpu_cgs_write_ind_registe
 	WARN(1, "Invalid indirect register space");
 }
 
-static uint8_t amdgpu_cgs_read_pci_config_byte(void *cgs_device, unsigned addr)
+static uint8_t amdgpu_cgs_read_pci_config_byte(struct cgs_device *cgs_device, unsigned addr)
 {
 	CGS_FUNC_ADEV;
 	uint8_t val;
@@ -353,7 +353,7 @@ static uint8_t amdgpu_cgs_read_pci_confi
 	return val;
 }
 
-static uint16_t amdgpu_cgs_read_pci_config_word(void *cgs_device, unsigned addr)
+static uint16_t amdgpu_cgs_read_pci_config_word(struct cgs_device *cgs_device, unsigned addr)
 {
 	CGS_FUNC_ADEV;
 	uint16_t val;
@@ -363,7 +363,7 @@ static uint16_t amdgpu_cgs_read_pci_conf
 	return val;
 }
 
-static uint32_t amdgpu_cgs_read_pci_config_dword(void *cgs_device,
+static uint32_t amdgpu_cgs_read_pci_config_dword(struct cgs_device *cgs_device,
 						 unsigned addr)
 {
 	CGS_FUNC_ADEV;
@@ -374,7 +374,7 @@ static uint32_t amdgpu_cgs_read_pci_conf
 	return val;
 }
 
-static void amdgpu_cgs_write_pci_config_byte(void *cgs_device, unsigned addr,
+static void amdgpu_cgs_write_pci_config_byte(struct cgs_device *cgs_device, unsigned addr,
 					     uint8_t value)
 {
 	CGS_FUNC_ADEV;
@@ -382,7 +382,7 @@ static void amdgpu_cgs_write_pci_config_
 	WARN(ret, "pci_write_config_byte error");
 }
 
-static void amdgpu_cgs_write_pci_config_word(void *cgs_device, unsigned addr,
+static void amdgpu_cgs_write_pci_config_word(struct cgs_device *cgs_device, unsigned addr,
 					     uint16_t value)
 {
 	CGS_FUNC_ADEV;
@@ -390,7 +390,7 @@ static void amdgpu_cgs_write_pci_config_
 	WARN(ret, "pci_write_config_word error");
 }
 
-static void amdgpu_cgs_write_pci_config_dword(void *cgs_device, unsigned addr,
+static void amdgpu_cgs_write_pci_config_dword(struct cgs_device *cgs_device, unsigned addr,
 					      uint32_t value)
 {
 	CGS_FUNC_ADEV;
@@ -399,7 +399,7 @@ static void amdgpu_cgs_write_pci_config_
 }
 
 
-static int amdgpu_cgs_get_pci_resource(void *cgs_device,
+static int amdgpu_cgs_get_pci_resource(struct cgs_device *cgs_device,
 				       enum cgs_resource_type resource_type,
 				       uint64_t size,
 				       uint64_t offset,
@@ -433,7 +433,7 @@ static int amdgpu_cgs_get_pci_resource(v
 	}
 }
 
-static const void *amdgpu_cgs_atom_get_data_table(void *cgs_device,
+static const void *amdgpu_cgs_atom_get_data_table(struct cgs_device *cgs_device,
 						  unsigned table, uint16_t *size,
 						  uint8_t *frev, uint8_t *crev)
 {
@@ -449,7 +449,7 @@ static const void *amdgpu_cgs_atom_get_d
 	return NULL;
 }
 
-static int amdgpu_cgs_atom_get_cmd_table_revs(void *cgs_device, unsigned table,
+static int amdgpu_cgs_atom_get_cmd_table_revs(struct cgs_device *cgs_device, unsigned table,
 					      uint8_t *frev, uint8_t *crev)
 {
 	CGS_FUNC_ADEV;
@@ -462,7 +462,7 @@ static int amdgpu_cgs_atom_get_cmd_table
 	return -EINVAL;
 }
 
-static int amdgpu_cgs_atom_exec_cmd_table(void *cgs_device, unsigned table,
+static int amdgpu_cgs_atom_exec_cmd_table(struct cgs_device *cgs_device, unsigned table,
 					  void *args)
 {
 	CGS_FUNC_ADEV;
@@ -471,33 +471,33 @@ static int amdgpu_cgs_atom_exec_cmd_tabl
 		adev->mode_info.atom_context, table, args);
 }
 
-static int amdgpu_cgs_create_pm_request(void *cgs_device, cgs_handle_t *request)
+static int amdgpu_cgs_create_pm_request(struct cgs_device *cgs_device, cgs_handle_t *request)
 {
 	/* TODO */
 	return 0;
 }
 
-static int amdgpu_cgs_destroy_pm_request(void *cgs_device, cgs_handle_t request)
+static int amdgpu_cgs_destroy_pm_request(struct cgs_device *cgs_device, cgs_handle_t request)
 {
 	/* TODO */
 	return 0;
 }
 
-static int amdgpu_cgs_set_pm_request(void *cgs_device, cgs_handle_t request,
+static int amdgpu_cgs_set_pm_request(struct cgs_device *cgs_device, cgs_handle_t request,
 				     int active)
 {
 	/* TODO */
 	return 0;
 }
 
-static int amdgpu_cgs_pm_request_clock(void *cgs_device, cgs_handle_t request,
+static int amdgpu_cgs_pm_request_clock(struct cgs_device *cgs_device, cgs_handle_t request,
 				       enum cgs_clock clock, unsigned freq)
 {
 	/* TODO */
 	return 0;
 }
 
-static int amdgpu_cgs_pm_request_engine(void *cgs_device, cgs_handle_t request,
+static int amdgpu_cgs_pm_request_engine(struct cgs_device *cgs_device, cgs_handle_t request,
 					enum cgs_engine engine, int powered)
 {
 	/* TODO */
@@ -506,7 +506,7 @@ static int amdgpu_cgs_pm_request_engine(
 
 
 
-static int amdgpu_cgs_pm_query_clock_limits(void *cgs_device,
+static int amdgpu_cgs_pm_query_clock_limits(struct cgs_device *cgs_device,
 					    enum cgs_clock clock,
 					    struct cgs_clock_limits *limits)
 {
@@ -514,7 +514,7 @@ static int amdgpu_cgs_pm_query_clock_lim
 	return 0;
 }
 
-static int amdgpu_cgs_set_camera_voltages(void *cgs_device, uint32_t mask,
+static int amdgpu_cgs_set_camera_voltages(struct cgs_device *cgs_device, uint32_t mask,
 					  const uint32_t *voltages)
 {
 	DRM_ERROR("not implemented");
@@ -565,7 +565,7 @@ static const struct amdgpu_irq_src_funcs
 	.process = cgs_process_irq,
 };
 
-static int amdgpu_cgs_add_irq_source(void *cgs_device, unsigned src_id,
+static int amdgpu_cgs_add_irq_source(struct cgs_device *cgs_device, unsigned src_id,
 				     unsigned num_types,
 				     cgs_irq_source_set_func_t set,
 				     cgs_irq_handler_func_t handler,
@@ -600,19 +600,19 @@ static int amdgpu_cgs_add_irq_source(voi
 	return ret;
 }
 
-static int amdgpu_cgs_irq_get(void *cgs_device, unsigned src_id, unsigned type)
+static int amdgpu_cgs_irq_get(struct cgs_device *cgs_device, unsigned src_id, unsigned type)
 {
 	CGS_FUNC_ADEV;
 	return amdgpu_irq_get(adev, adev->irq.sources[src_id], type);
 }
 
-static int amdgpu_cgs_irq_put(void *cgs_device, unsigned src_id, unsigned type)
+static int amdgpu_cgs_irq_put(struct cgs_device *cgs_device, unsigned src_id, unsigned type)
 {
 	CGS_FUNC_ADEV;
 	return amdgpu_irq_put(adev, adev->irq.sources[src_id], type);
 }
 
-int amdgpu_cgs_set_clockgating_state(void *cgs_device,
+int amdgpu_cgs_set_clockgating_state(struct cgs_device *cgs_device,
 				  enum amd_ip_block_type block_type,
 				  enum amd_clockgating_state state)
 {
@@ -633,7 +633,7 @@ int amdgpu_cgs_set_clockgating_state(voi
 	return r;
 }
 
-int amdgpu_cgs_set_powergating_state(void *cgs_device,
+int amdgpu_cgs_set_powergating_state(struct cgs_device *cgs_device,
 				  enum amd_ip_block_type block_type,
 				  enum amd_powergating_state state)
 {
@@ -655,7 +655,7 @@ int amdgpu_cgs_set_powergating_state(voi
 }
 
 
-static uint32_t fw_type_convert(void *cgs_device, uint32_t fw_type)
+static uint32_t fw_type_convert(struct cgs_device *cgs_device, uint32_t fw_type)
 {
 	CGS_FUNC_ADEV;
 	enum AMDGPU_UCODE_ID result = AMDGPU_UCODE_ID_MAXIMUM;
@@ -681,9 +681,10 @@ static uint32_t fw_type_convert(void *cg
 		result = AMDGPU_UCODE_ID_CP_MEC1;
 		break;
 	case CGS_UCODE_ID_CP_MEC_JT2:
-		if (adev->asic_type == CHIP_TONGA)
+		if (adev->asic_type == CHIP_TONGA || adev->asic_type == CHIP_POLARIS11
+		  || adev->asic_type == CHIP_POLARIS10)
 			result = AMDGPU_UCODE_ID_CP_MEC2;
-		else if (adev->asic_type == CHIP_CARRIZO)
+		else
 			result = AMDGPU_UCODE_ID_CP_MEC1;
 		break;
 	case CGS_UCODE_ID_RLC_G:
@@ -695,13 +696,24 @@ static uint32_t fw_type_convert(void *cg
 	return result;
 }
 
-static int amdgpu_cgs_get_firmware_info(void *cgs_device,
+static int amdgpu_cgs_rel_firmware(struct cgs_device *cgs_device, enum cgs_ucode_id type)
+{
+	CGS_FUNC_ADEV;
+	if ((CGS_UCODE_ID_SMU == type) || (CGS_UCODE_ID_SMU_SK == type)) {
+		release_firmware(adev->pm.fw);
+		return 0;
+	}
+	/* cannot release other firmware because they are not created by cgs */
+	return -EINVAL;
+}
+
+static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device,
 					enum cgs_ucode_id type,
 					struct cgs_firmware_info *info)
 {
 	CGS_FUNC_ADEV;
 
-	if (CGS_UCODE_ID_SMU != type) {
+	if ((CGS_UCODE_ID_SMU != type) && (CGS_UCODE_ID_SMU_SK != type)) {
 		uint64_t gpu_addr;
 		uint32_t data_size;
 		const struct gfx_firmware_header_v1_0 *header;
@@ -734,30 +746,44 @@ static int amdgpu_cgs_get_firmware_info(
 		const uint8_t *src;
 		const struct smc_firmware_header_v1_0 *hdr;
 
-		switch (adev->asic_type) {
-		case CHIP_TONGA:
-			strcpy(fw_name, "/*(DEBLOBBED)*/");
-			break;
-		case CHIP_FIJI:
-			strcpy(fw_name, "/*(DEBLOBBED)*/");
-			break;
-		default:
-			DRM_ERROR("SMC firmware not supported\n");
-			return -EINVAL;
-		}
+		if (!adev->pm.fw) {
+			switch (adev->asic_type) {
+			case CHIP_TONGA:
+				strcpy(fw_name, "/*(DEBLOBBED)*/");
+				break;
+			case CHIP_FIJI:
+				strcpy(fw_name, "/*(DEBLOBBED)*/");
+				break;
+			case CHIP_POLARIS11:
+				if (type == CGS_UCODE_ID_SMU)
+					strcpy(fw_name, "/*(DEBLOBBED)*/");
+				else if (type == CGS_UCODE_ID_SMU_SK)
+					strcpy(fw_name, "/*(DEBLOBBED)*/");
+				break;
+			case CHIP_POLARIS10:
+				if (type == CGS_UCODE_ID_SMU)
+					strcpy(fw_name, "/*(DEBLOBBED)*/");
+				else if (type == CGS_UCODE_ID_SMU_SK)
+					strcpy(fw_name, "/*(DEBLOBBED)*/");
+				break;
+			default:
+				DRM_ERROR("SMC firmware not supported\n");
+				return -EINVAL;
+			}
 
-		err = reject_firmware(&adev->pm.fw, fw_name, adev->dev);
-		if (err) {
-			DRM_ERROR("Failed to request firmware\n");
-			return err;
-		}
+			err = reject_firmware(&adev->pm.fw, fw_name, adev->dev);
+			if (err) {
+				DRM_ERROR("Failed to request firmware\n");
+				return err;
+			}
 
-		err = amdgpu_ucode_validate(adev->pm.fw);
-		if (err) {
-			DRM_ERROR("Failed to load firmware \"%s\"", fw_name);
-			release_firmware(adev->pm.fw);
-			adev->pm.fw = NULL;
-			return err;
+			err = amdgpu_ucode_validate(adev->pm.fw);
+			if (err) {
+				DRM_ERROR("Failed to load firmware \"%s\"", fw_name);
+				release_firmware(adev->pm.fw);
+				adev->pm.fw = NULL;
+				return err;
+			}
 		}
 
 		hdr = (const struct smc_firmware_header_v1_0 *)	adev->pm.fw->data;
@@ -774,7 +800,7 @@ static int amdgpu_cgs_get_firmware_info(
 	return 0;
 }
 
-static int amdgpu_cgs_query_system_info(void *cgs_device,
+static int amdgpu_cgs_query_system_info(struct cgs_device *cgs_device,
 				struct cgs_system_info *sys_info)
 {
 	CGS_FUNC_ADEV;
@@ -801,6 +827,9 @@ static int amdgpu_cgs_query_system_info(
 	case CGS_SYSTEM_INFO_PG_FLAGS:
 		sys_info->value = adev->pg_flags;
 		break;
+	case CGS_SYSTEM_INFO_GFX_CU_INFO:
+		sys_info->value = adev->gfx.cu_info.number;
+		break;
 	default:
 		return -ENODEV;
 	}
@@ -808,7 +837,7 @@ static int amdgpu_cgs_query_system_info(
 	return 0;
 }
 
-static int amdgpu_cgs_get_active_displays_info(void *cgs_device,
+static int amdgpu_cgs_get_active_displays_info(struct cgs_device *cgs_device,
 					  struct cgs_display_info *info)
 {
 	CGS_FUNC_ADEV;
@@ -851,7 +880,7 @@ static int amdgpu_cgs_get_active_display
 }
 
 
-static int amdgpu_cgs_notify_dpm_enabled(void *cgs_device, bool enabled)
+static int amdgpu_cgs_notify_dpm_enabled(struct cgs_device *cgs_device, bool enabled)
 {
 	CGS_FUNC_ADEV;
 
@@ -867,7 +896,7 @@ static int amdgpu_cgs_notify_dpm_enabled
  */
 
 #if defined(CONFIG_ACPI)
-static int amdgpu_cgs_acpi_eval_object(void *cgs_device,
+static int amdgpu_cgs_acpi_eval_object(struct cgs_device *cgs_device,
 				    struct cgs_acpi_method_info *info)
 {
 	CGS_FUNC_ADEV;
@@ -880,7 +909,7 @@ static int amdgpu_cgs_acpi_eval_object(v
 	struct cgs_acpi_method_argument *argument = NULL;
 	uint32_t i, count;
 	acpi_status status;
-	int result;
+	int result = 0;
 	uint32_t func_no = 0xFFFFFFFF;
 
 	handle = ACPI_HANDLE(&adev->pdev->dev);
@@ -1030,14 +1059,14 @@ error:
 	return result;
 }
 #else
-static int amdgpu_cgs_acpi_eval_object(void *cgs_device,
+static int amdgpu_cgs_acpi_eval_object(struct cgs_device *cgs_device,
 				struct cgs_acpi_method_info *info)
 {
 	return -EIO;
 }
 #endif
 
-int amdgpu_cgs_call_acpi_method(void *cgs_device,
+int amdgpu_cgs_call_acpi_method(struct cgs_device *cgs_device,
 					uint32_t acpi_method,
 					uint32_t acpi_function,
 					void *pinput, void *poutput,
@@ -1107,6 +1136,7 @@ static const struct cgs_ops amdgpu_cgs_o
 	amdgpu_cgs_pm_query_clock_limits,
 	amdgpu_cgs_set_camera_voltages,
 	amdgpu_cgs_get_firmware_info,
+	amdgpu_cgs_rel_firmware,
 	amdgpu_cgs_set_powergating_state,
 	amdgpu_cgs_set_clockgating_state,
 	amdgpu_cgs_get_active_displays_info,
@@ -1121,7 +1151,7 @@ static const struct cgs_os_ops amdgpu_cg
 	amdgpu_cgs_irq_put
 };
 
-void *amdgpu_cgs_create_device(struct amdgpu_device *adev)
+struct cgs_device *amdgpu_cgs_create_device(struct amdgpu_device *adev)
 {
 	struct amdgpu_cgs_device *cgs_device =
 		kmalloc(sizeof(*cgs_device), GFP_KERNEL);
@@ -1135,10 +1165,10 @@ void *amdgpu_cgs_create_device(struct am
 	cgs_device->base.os_ops = &amdgpu_cgs_os_ops;
 	cgs_device->adev = adev;
 
-	return cgs_device;
+	return (struct cgs_device *)cgs_device;
 }
 
-void amdgpu_cgs_destroy_device(void *cgs_device)
+void amdgpu_cgs_destroy_device(struct cgs_device *cgs_device)
 {
 	kfree(cgs_device);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c	2016-07-24 15:23:50.000000000 -0400
@@ -194,12 +194,12 @@ int amdgpu_connector_get_monitor_bpc(str
 				bpc = 8;
 				DRM_DEBUG("%s: HDMI deep color 10 bpc exceeds max tmds clock. Using %d bpc.\n",
 					  connector->name, bpc);
-			} else if (bpc > 8) {
-				/* max_tmds_clock missing, but hdmi spec mandates it for deep color. */
-				DRM_DEBUG("%s: Required max tmds clock for HDMI deep color missing. Using 8 bpc.\n",
-					  connector->name);
-				bpc = 8;
 			}
+		} else if (bpc > 8) {
+			/* max_tmds_clock missing, but hdmi spec mandates it for deep color. */
+			DRM_DEBUG("%s: Required max tmds clock for HDMI deep color missing. Using 8 bpc.\n",
+				  connector->name);
+			bpc = 8;
 		}
 	}
 
@@ -439,7 +439,7 @@ static void amdgpu_connector_add_common_
 	struct drm_display_mode *mode = NULL;
 	struct drm_display_mode *native_mode = &amdgpu_encoder->native_mode;
 	int i;
-	struct mode_size {
+	static const struct mode_size {
 		int w;
 		int h;
 	} common_modes[17] = {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c	2016-07-24 15:23:50.000000000 -0400
@@ -24,7 +24,6 @@
  * Authors:
  *    Jerome Glisse <glisse@freedesktop.org>
  */
-#include <linux/list_sort.h>
 #include <linux/pagemap.h>
 #include <drm/drmP.h>
 #include <drm/amdgpu_drm.h>
@@ -88,44 +87,41 @@ int amdgpu_cs_get_ring(struct amdgpu_dev
 }
 
 static int amdgpu_cs_user_fence_chunk(struct amdgpu_cs_parser *p,
-				      struct amdgpu_user_fence *uf,
-				      struct drm_amdgpu_cs_chunk_fence *fence_data)
+				      struct drm_amdgpu_cs_chunk_fence *data,
+				      uint32_t *offset)
 {
 	struct drm_gem_object *gobj;
-	uint32_t handle;
 
-	handle = fence_data->handle;
-	gobj = drm_gem_object_lookup(p->adev->ddev, p->filp,
-				     fence_data->handle);
+	gobj = drm_gem_object_lookup(p->filp, data->handle);
 	if (gobj == NULL)
 		return -EINVAL;
 
-	uf->bo = amdgpu_bo_ref(gem_to_amdgpu_bo(gobj));
-	uf->offset = fence_data->offset;
-
-	if (amdgpu_ttm_tt_get_usermm(uf->bo->tbo.ttm)) {
-		drm_gem_object_unreference_unlocked(gobj);
-		return -EINVAL;
-	}
-
-	p->uf_entry.robj = amdgpu_bo_ref(uf->bo);
+	p->uf_entry.robj = amdgpu_bo_ref(gem_to_amdgpu_bo(gobj));
 	p->uf_entry.priority = 0;
 	p->uf_entry.tv.bo = &p->uf_entry.robj->tbo;
 	p->uf_entry.tv.shared = true;
 	p->uf_entry.user_pages = NULL;
+	*offset = data->offset;
 
 	drm_gem_object_unreference_unlocked(gobj);
+
+	if (amdgpu_ttm_tt_get_usermm(p->uf_entry.robj->tbo.ttm)) {
+		amdgpu_bo_unref(&p->uf_entry.robj);
+		return -EINVAL;
+	}
+
 	return 0;
 }
 
 int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
 {
 	struct amdgpu_fpriv *fpriv = p->filp->driver_priv;
+	struct amdgpu_vm *vm = &fpriv->vm;
 	union drm_amdgpu_cs *cs = data;
 	uint64_t *chunk_array_user;
 	uint64_t *chunk_array;
-	struct amdgpu_user_fence uf = {};
 	unsigned size, num_ibs = 0;
+	uint32_t uf_offset = 0;
 	int i;
 	int ret;
 
@@ -200,7 +196,8 @@ int amdgpu_cs_parser_init(struct amdgpu_
 				goto free_partial_kdata;
 			}
 
-			ret = amdgpu_cs_user_fence_chunk(p, &uf, (void *)p->chunks[i].kdata);
+			ret = amdgpu_cs_user_fence_chunk(p, p->chunks[i].kdata,
+							 &uf_offset);
 			if (ret)
 				goto free_partial_kdata;
 
@@ -215,11 +212,14 @@ int amdgpu_cs_parser_init(struct amdgpu_
 		}
 	}
 
-	ret = amdgpu_job_alloc(p->adev, num_ibs, &p->job);
+	ret = amdgpu_job_alloc(p->adev, num_ibs, &p->job, vm);
 	if (ret)
 		goto free_all_kdata;
 
-	p->job->uf = uf;
+	if (p->uf_entry.robj) {
+		p->job->uf_bo = amdgpu_bo_ref(p->uf_entry.robj);
+		p->job->uf_offset = uf_offset;
+	}
 
 	kfree(chunk_array);
 	return 0;
@@ -377,7 +377,7 @@ static int amdgpu_cs_parser_bos(struct a
 	INIT_LIST_HEAD(&duplicates);
 	amdgpu_vm_get_pd_bo(&fpriv->vm, &p->validated, &p->vm_pd);
 
-	if (p->job->uf.bo)
+	if (p->uf_entry.robj)
 		list_add(&p->uf_entry.tv.head, &p->validated);
 
 	if (need_mmap_lock)
@@ -473,6 +473,9 @@ static int amdgpu_cs_parser_bos(struct a
 		goto error_validate;
 
 	if (p->bo_list) {
+		struct amdgpu_bo *gds = p->bo_list->gds_obj;
+		struct amdgpu_bo *gws = p->bo_list->gws_obj;
+		struct amdgpu_bo *oa = p->bo_list->oa_obj;
 		struct amdgpu_vm *vm = &fpriv->vm;
 		unsigned i;
 
@@ -481,6 +484,19 @@ static int amdgpu_cs_parser_bos(struct a
 
 			p->bo_list->array[i].bo_va = amdgpu_vm_bo_find(vm, bo);
 		}
+
+		if (gds) {
+			p->job->gds_base = amdgpu_bo_gpu_offset(gds);
+			p->job->gds_size = amdgpu_bo_size(gds);
+		}
+		if (gws) {
+			p->job->gws_base = amdgpu_bo_gpu_offset(gws);
+			p->job->gws_size = amdgpu_bo_size(gws);
+		}
+		if (oa) {
+			p->job->oa_base = amdgpu_bo_gpu_offset(oa);
+			p->job->oa_size = amdgpu_bo_size(oa);
+		}
 	}
 
 error_validate:
@@ -527,16 +543,6 @@ static int amdgpu_cs_sync_rings(struct a
 	return 0;
 }
 
-static int cmp_size_smaller_first(void *priv, struct list_head *a,
-				  struct list_head *b)
-{
-	struct amdgpu_bo_list_entry *la = list_entry(a, struct amdgpu_bo_list_entry, tv.head);
-	struct amdgpu_bo_list_entry *lb = list_entry(b, struct amdgpu_bo_list_entry, tv.head);
-
-	/* Sort A before B if A is smaller. */
-	return (int)la->robj->tbo.num_pages - (int)lb->robj->tbo.num_pages;
-}
-
 /**
  * cs_parser_fini() - clean parser states
  * @parser:	parser structure holding parsing context.
@@ -553,18 +559,6 @@ static void amdgpu_cs_parser_fini(struct
 	if (!error) {
 		amdgpu_vm_move_pt_bos_in_lru(parser->adev, &fpriv->vm);
 
-		/* Sort the buffer list from the smallest to largest buffer,
-		 * which affects the order of buffers in the LRU list.
-		 * This assures that the smallest buffers are added first
-		 * to the LRU list, so they are likely to be later evicted
-		 * first, instead of large buffers whose eviction is more
-		 * expensive.
-		 *
-		 * This slightly lowers the number of bytes moved by TTM
-		 * per frame under memory pressure.
-		 */
-		list_sort(NULL, &parser->validated, cmp_size_smaller_first);
-
 		ttm_eu_fence_buffer_objects(&parser->ticket,
 					    &parser->validated,
 					    parser->fence);
@@ -763,41 +757,14 @@ static int amdgpu_cs_ib_fill(struct amdg
 
 		ib->length_dw = chunk_ib->ib_bytes / 4;
 		ib->flags = chunk_ib->flags;
-		ib->ctx = parser->ctx;
 		j++;
 	}
 
-	/* add GDS resources to first IB */
-	if (parser->bo_list) {
-		struct amdgpu_bo *gds = parser->bo_list->gds_obj;
-		struct amdgpu_bo *gws = parser->bo_list->gws_obj;
-		struct amdgpu_bo *oa = parser->bo_list->oa_obj;
-		struct amdgpu_ib *ib = &parser->job->ibs[0];
-
-		if (gds) {
-			ib->gds_base = amdgpu_bo_gpu_offset(gds);
-			ib->gds_size = amdgpu_bo_size(gds);
-		}
-		if (gws) {
-			ib->gws_base = amdgpu_bo_gpu_offset(gws);
-			ib->gws_size = amdgpu_bo_size(gws);
-		}
-		if (oa) {
-			ib->oa_base = amdgpu_bo_gpu_offset(oa);
-			ib->oa_size = amdgpu_bo_size(oa);
-		}
-	}
-	/* wrap the last IB with user fence */
-	if (parser->job->uf.bo) {
-		struct amdgpu_ib *ib = &parser->job->ibs[parser->job->num_ibs - 1];
-
-		/* UVD & VCE fw doesn't support user fences */
-		if (parser->job->ring->type == AMDGPU_RING_TYPE_UVD ||
-		    parser->job->ring->type == AMDGPU_RING_TYPE_VCE)
-			return -EINVAL;
-
-		ib->user = &parser->job->uf;
-	}
+	/* UVD & VCE fw doesn't support user fences */
+	if (parser->job->uf_bo && (
+	    parser->job->ring->type == AMDGPU_RING_TYPE_UVD ||
+	    parser->job->ring->type == AMDGPU_RING_TYPE_VCE))
+		return -EINVAL;
 
 	return 0;
 }
@@ -862,28 +829,28 @@ static int amdgpu_cs_submit(struct amdgp
 			    union drm_amdgpu_cs *cs)
 {
 	struct amdgpu_ring *ring = p->job->ring;
-	struct amd_sched_fence *fence;
+	struct amd_sched_entity *entity = &p->ctx->rings[ring->idx].entity;
+	struct fence *fence;
 	struct amdgpu_job *job;
+	int r;
 
 	job = p->job;
 	p->job = NULL;
 
-	job->base.sched = &ring->sched;
-	job->base.s_entity = &p->ctx->rings[ring->idx].entity;
-	job->owner = p->filp;
-
-	fence = amd_sched_fence_create(job->base.s_entity, p->filp);
-	if (!fence) {
+	r = amd_sched_job_init(&job->base, &ring->sched,
+			       entity, amdgpu_job_timeout_func,
+			       amdgpu_job_free_func,
+			       p->filp, &fence);
+	if (r) {
 		amdgpu_job_free(job);
-		return -ENOMEM;
+		return r;
 	}
 
-	job->base.s_fence = fence;
-	p->fence = fence_get(&fence->base);
-
-	cs->out.handle = amdgpu_ctx_add_fence(p->ctx, ring,
-					      &fence->base);
-	job->ibs[job->num_ibs - 1].sequence = cs->out.handle;
+	job->owner = p->filp;
+	job->ctx = entity->fence_context;
+	p->fence = fence_get(fence);
+	cs->out.handle = amdgpu_ctx_add_fence(p->ctx, ring, fence);
+	job->uf_sequence = cs->out.handle;
 
 	trace_amdgpu_cs_ioctl(job);
 	amd_sched_entity_push_job(&job->base);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c	2016-07-24 15:23:50.000000000 -0400
@@ -59,6 +59,8 @@ static const char *amdgpu_asic_name[] =
 	"FIJI",
 	"CARRIZO",
 	"STONEY",
+	"POLARIS10",
+	"POLARIS11",
 	"LAST",
 };
 
@@ -346,7 +348,7 @@ static int amdgpu_doorbell_init(struct a
 	adev->doorbell.base = pci_resource_start(adev->pdev, 2);
 	adev->doorbell.size = pci_resource_len(adev->pdev, 2);
 
-	adev->doorbell.num_doorbells = min_t(u32, adev->doorbell.size / sizeof(u32), 
+	adev->doorbell.num_doorbells = min_t(u32, adev->doorbell.size / sizeof(u32),
 					     AMDGPU_DOORBELL_MAX_ASSIGNMENT+1);
 	if (adev->doorbell.num_doorbells == 0)
 		return -EINVAL;
@@ -825,8 +827,10 @@ static uint32_t cail_ioreg_read(struct c
  */
 static void amdgpu_atombios_fini(struct amdgpu_device *adev)
 {
-	if (adev->mode_info.atom_context)
+	if (adev->mode_info.atom_context) {
 		kfree(adev->mode_info.atom_context->scratch);
+		kfree(adev->mode_info.atom_context->iio);
+	}
 	kfree(adev->mode_info.atom_context);
 	adev->mode_info.atom_context = NULL;
 	kfree(adev->mode_info.atom_card_info);
@@ -936,15 +940,11 @@ static void amdgpu_check_arguments(struc
 	}
 
 	if (amdgpu_gart_size != -1) {
-		/* gtt size must be power of two and greater or equal to 32M */
+		/* gtt size must be greater or equal to 32M */
 		if (amdgpu_gart_size < 32) {
 			dev_warn(adev->dev, "gart size (%d) too small\n",
 				 amdgpu_gart_size);
 			amdgpu_gart_size = -1;
-		} else if (!amdgpu_check_pot_argument(amdgpu_gart_size)) {
-			dev_warn(adev->dev, "gart size (%d) must be a power of 2\n",
-				 amdgpu_gart_size);
-			amdgpu_gart_size = -1;
 		}
 	}
 
@@ -1144,6 +1144,8 @@ static int amdgpu_early_init(struct amdg
 	case CHIP_TOPAZ:
 	case CHIP_TONGA:
 	case CHIP_FIJI:
+	case CHIP_POLARIS11:
+	case CHIP_POLARIS10:
 	case CHIP_CARRIZO:
 	case CHIP_STONEY:
 		if (adev->asic_type == CHIP_CARRIZO || adev->asic_type == CHIP_STONEY)
@@ -1196,7 +1198,7 @@ static int amdgpu_early_init(struct amdg
 				if (r == -ENOENT) {
 					adev->ip_block_status[i].valid = false;
 				} else if (r) {
-					DRM_ERROR("early_init %d failed %d\n", i, r);
+					DRM_ERROR("early_init of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r);
 					return r;
 				} else {
 					adev->ip_block_status[i].valid = true;
@@ -1219,7 +1221,7 @@ static int amdgpu_init(struct amdgpu_dev
 			continue;
 		r = adev->ip_blocks[i].funcs->sw_init((void *)adev);
 		if (r) {
-			DRM_ERROR("sw_init %d failed %d\n", i, r);
+			DRM_ERROR("sw_init of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r);
 			return r;
 		}
 		adev->ip_block_status[i].sw = true;
@@ -1252,7 +1254,7 @@ static int amdgpu_init(struct amdgpu_dev
 			continue;
 		r = adev->ip_blocks[i].funcs->hw_init((void *)adev);
 		if (r) {
-			DRM_ERROR("hw_init %d failed %d\n", i, r);
+			DRM_ERROR("hw_init of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r);
 			return r;
 		}
 		adev->ip_block_status[i].hw = true;
@@ -1272,13 +1274,13 @@ static int amdgpu_late_init(struct amdgp
 		r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev,
 								    AMD_CG_STATE_GATE);
 		if (r) {
-			DRM_ERROR("set_clockgating_state(gate) %d failed %d\n", i, r);
+			DRM_ERROR("set_clockgating_state(gate) of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r);
 			return r;
 		}
 		if (adev->ip_blocks[i].funcs->late_init) {
 			r = adev->ip_blocks[i].funcs->late_init((void *)adev);
 			if (r) {
-				DRM_ERROR("late_init %d failed %d\n", i, r);
+				DRM_ERROR("late_init of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r);
 				return r;
 			}
 		}
@@ -1302,13 +1304,13 @@ static int amdgpu_fini(struct amdgpu_dev
 		r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev,
 								    AMD_CG_STATE_UNGATE);
 		if (r) {
-			DRM_ERROR("set_clockgating_state(ungate) %d failed %d\n", i, r);
+			DRM_ERROR("set_clockgating_state(ungate) of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r);
 			return r;
 		}
 		r = adev->ip_blocks[i].funcs->hw_fini((void *)adev);
 		/* XXX handle errors */
 		if (r) {
-			DRM_DEBUG("hw_fini %d failed %d\n", i, r);
+			DRM_DEBUG("hw_fini of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r);
 		}
 		adev->ip_block_status[i].hw = false;
 	}
@@ -1319,12 +1321,17 @@ static int amdgpu_fini(struct amdgpu_dev
 		r = adev->ip_blocks[i].funcs->sw_fini((void *)adev);
 		/* XXX handle errors */
 		if (r) {
-			DRM_DEBUG("sw_fini %d failed %d\n", i, r);
+			DRM_DEBUG("sw_fini of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r);
 		}
 		adev->ip_block_status[i].sw = false;
 		adev->ip_block_status[i].valid = false;
 	}
 
+	for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
+		if (adev->ip_blocks[i].funcs->late_fini)
+			adev->ip_blocks[i].funcs->late_fini((void *)adev);
+	}
+
 	return 0;
 }
 
@@ -1332,20 +1339,29 @@ static int amdgpu_suspend(struct amdgpu_
 {
 	int i, r;
 
+	/* ungate SMC block first */
+	r = amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_SMC,
+					 AMD_CG_STATE_UNGATE);
+	if (r) {
+		DRM_ERROR("set_clockgating_state(ungate) SMC failed %d\n",r);
+	}
+
 	for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
 		if (!adev->ip_block_status[i].valid)
 			continue;
 		/* ungate blocks so that suspend can properly shut them down */
-		r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev,
-								    AMD_CG_STATE_UNGATE);
-		if (r) {
-			DRM_ERROR("set_clockgating_state(ungate) %d failed %d\n", i, r);
+		if (i != AMD_IP_BLOCK_TYPE_SMC) {
+			r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev,
+									    AMD_CG_STATE_UNGATE);
+			if (r) {
+				DRM_ERROR("set_clockgating_state(ungate) of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r);
+			}
 		}
 		/* XXX handle errors */
 		r = adev->ip_blocks[i].funcs->suspend(adev);
 		/* XXX handle errors */
 		if (r) {
-			DRM_ERROR("suspend %d failed %d\n", i, r);
+			DRM_ERROR("suspend of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r);
 		}
 	}
 
@@ -1361,7 +1377,7 @@ static int amdgpu_resume(struct amdgpu_d
 			continue;
 		r = adev->ip_blocks[i].funcs->resume(adev);
 		if (r) {
-			DRM_ERROR("resume %d failed %d\n", i, r);
+			DRM_ERROR("resume of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r);
 			return r;
 		}
 	}
@@ -1369,6 +1385,15 @@ static int amdgpu_resume(struct amdgpu_d
 	return 0;
 }
 
+static bool amdgpu_device_is_virtual(void)
+{
+#ifdef CONFIG_X86
+	return boot_cpu_has(X86_FEATURE_HYPERVISOR);
+#else
+	return false;
+#endif
+}
+
 /**
  * amdgpu_device_init - initialize the driver
  *
@@ -1503,9 +1528,14 @@ int amdgpu_device_init(struct amdgpu_dev
 	adev->virtualization.supports_sr_iov =
 		amdgpu_atombios_has_gpu_virtualization_table(adev);
 
+	/* Check if we are executing in a virtualized environment */
+	adev->virtualization.is_virtual = amdgpu_device_is_virtual();
+	adev->virtualization.caps = amdgpu_asic_get_virtual_caps(adev);
+
 	/* Post card if necessary */
 	if (!amdgpu_card_posted(adev) ||
-	    adev->virtualization.supports_sr_iov) {
+	    (adev->virtualization.is_virtual &&
+	     !(adev->virtualization.caps & AMDGPU_VIRT_CAPS_SRIOV_EN))) {
 		if (!adev->bios) {
 			dev_err(adev->dev, "Card not posted and no BIOS - ignoring\n");
 			return -EINVAL;
@@ -2007,7 +2037,7 @@ void amdgpu_get_pcie_info(struct amdgpu_
  * Debugfs
  */
 int amdgpu_debugfs_add_files(struct amdgpu_device *adev,
-			     struct drm_info_list *files,
+			     const struct drm_info_list *files,
 			     unsigned nfiles)
 {
 	unsigned i;
@@ -2119,32 +2149,246 @@ static ssize_t amdgpu_debugfs_regs_write
 	return result;
 }
 
+static ssize_t amdgpu_debugfs_regs_pcie_read(struct file *f, char __user *buf,
+					size_t size, loff_t *pos)
+{
+	struct amdgpu_device *adev = f->f_inode->i_private;
+	ssize_t result = 0;
+	int r;
+
+	if (size & 0x3 || *pos & 0x3)
+		return -EINVAL;
+
+	while (size) {
+		uint32_t value;
+
+		value = RREG32_PCIE(*pos >> 2);
+		r = put_user(value, (uint32_t *)buf);
+		if (r)
+			return r;
+
+		result += 4;
+		buf += 4;
+		*pos += 4;
+		size -= 4;
+	}
+
+	return result;
+}
+
+static ssize_t amdgpu_debugfs_regs_pcie_write(struct file *f, const char __user *buf,
+					 size_t size, loff_t *pos)
+{
+	struct amdgpu_device *adev = f->f_inode->i_private;
+	ssize_t result = 0;
+	int r;
+
+	if (size & 0x3 || *pos & 0x3)
+		return -EINVAL;
+
+	while (size) {
+		uint32_t value;
+
+		r = get_user(value, (uint32_t *)buf);
+		if (r)
+			return r;
+
+		WREG32_PCIE(*pos >> 2, value);
+
+		result += 4;
+		buf += 4;
+		*pos += 4;
+		size -= 4;
+	}
+
+	return result;
+}
+
+static ssize_t amdgpu_debugfs_regs_didt_read(struct file *f, char __user *buf,
+					size_t size, loff_t *pos)
+{
+	struct amdgpu_device *adev = f->f_inode->i_private;
+	ssize_t result = 0;
+	int r;
+
+	if (size & 0x3 || *pos & 0x3)
+		return -EINVAL;
+
+	while (size) {
+		uint32_t value;
+
+		value = RREG32_DIDT(*pos >> 2);
+		r = put_user(value, (uint32_t *)buf);
+		if (r)
+			return r;
+
+		result += 4;
+		buf += 4;
+		*pos += 4;
+		size -= 4;
+	}
+
+	return result;
+}
+
+static ssize_t amdgpu_debugfs_regs_didt_write(struct file *f, const char __user *buf,
+					 size_t size, loff_t *pos)
+{
+	struct amdgpu_device *adev = f->f_inode->i_private;
+	ssize_t result = 0;
+	int r;
+
+	if (size & 0x3 || *pos & 0x3)
+		return -EINVAL;
+
+	while (size) {
+		uint32_t value;
+
+		r = get_user(value, (uint32_t *)buf);
+		if (r)
+			return r;
+
+		WREG32_DIDT(*pos >> 2, value);
+
+		result += 4;
+		buf += 4;
+		*pos += 4;
+		size -= 4;
+	}
+
+	return result;
+}
+
+static ssize_t amdgpu_debugfs_regs_smc_read(struct file *f, char __user *buf,
+					size_t size, loff_t *pos)
+{
+	struct amdgpu_device *adev = f->f_inode->i_private;
+	ssize_t result = 0;
+	int r;
+
+	if (size & 0x3 || *pos & 0x3)
+		return -EINVAL;
+
+	while (size) {
+		uint32_t value;
+
+		value = RREG32_SMC(*pos >> 2);
+		r = put_user(value, (uint32_t *)buf);
+		if (r)
+			return r;
+
+		result += 4;
+		buf += 4;
+		*pos += 4;
+		size -= 4;
+	}
+
+	return result;
+}
+
+static ssize_t amdgpu_debugfs_regs_smc_write(struct file *f, const char __user *buf,
+					 size_t size, loff_t *pos)
+{
+	struct amdgpu_device *adev = f->f_inode->i_private;
+	ssize_t result = 0;
+	int r;
+
+	if (size & 0x3 || *pos & 0x3)
+		return -EINVAL;
+
+	while (size) {
+		uint32_t value;
+
+		r = get_user(value, (uint32_t *)buf);
+		if (r)
+			return r;
+
+		WREG32_SMC(*pos >> 2, value);
+
+		result += 4;
+		buf += 4;
+		*pos += 4;
+		size -= 4;
+	}
+
+	return result;
+}
+
 static const struct file_operations amdgpu_debugfs_regs_fops = {
 	.owner = THIS_MODULE,
 	.read = amdgpu_debugfs_regs_read,
 	.write = amdgpu_debugfs_regs_write,
 	.llseek = default_llseek
 };
+static const struct file_operations amdgpu_debugfs_regs_didt_fops = {
+	.owner = THIS_MODULE,
+	.read = amdgpu_debugfs_regs_didt_read,
+	.write = amdgpu_debugfs_regs_didt_write,
+	.llseek = default_llseek
+};
+static const struct file_operations amdgpu_debugfs_regs_pcie_fops = {
+	.owner = THIS_MODULE,
+	.read = amdgpu_debugfs_regs_pcie_read,
+	.write = amdgpu_debugfs_regs_pcie_write,
+	.llseek = default_llseek
+};
+static const struct file_operations amdgpu_debugfs_regs_smc_fops = {
+	.owner = THIS_MODULE,
+	.read = amdgpu_debugfs_regs_smc_read,
+	.write = amdgpu_debugfs_regs_smc_write,
+	.llseek = default_llseek
+};
+
+static const struct file_operations *debugfs_regs[] = {
+	&amdgpu_debugfs_regs_fops,
+	&amdgpu_debugfs_regs_didt_fops,
+	&amdgpu_debugfs_regs_pcie_fops,
+	&amdgpu_debugfs_regs_smc_fops,
+};
+
+static const char *debugfs_regs_names[] = {
+	"amdgpu_regs",
+	"amdgpu_regs_didt",
+	"amdgpu_regs_pcie",
+	"amdgpu_regs_smc",
+};
 
 static int amdgpu_debugfs_regs_init(struct amdgpu_device *adev)
 {
 	struct drm_minor *minor = adev->ddev->primary;
 	struct dentry *ent, *root = minor->debugfs_root;
+	unsigned i, j;
 
-	ent = debugfs_create_file("amdgpu_regs", S_IFREG | S_IRUGO, root,
-				  adev, &amdgpu_debugfs_regs_fops);
-	if (IS_ERR(ent))
-		return PTR_ERR(ent);
-	i_size_write(ent->d_inode, adev->rmmio_size);
-	adev->debugfs_regs = ent;
+	for (i = 0; i < ARRAY_SIZE(debugfs_regs); i++) {
+		ent = debugfs_create_file(debugfs_regs_names[i],
+					  S_IFREG | S_IRUGO, root,
+					  adev, debugfs_regs[i]);
+		if (IS_ERR(ent)) {
+			for (j = 0; j < i; j++) {
+				debugfs_remove(adev->debugfs_regs[i]);
+				adev->debugfs_regs[i] = NULL;
+			}
+			return PTR_ERR(ent);
+		}
+
+		if (!i)
+			i_size_write(ent->d_inode, adev->rmmio_size);
+		adev->debugfs_regs[i] = ent;
+	}
 
 	return 0;
 }
 
 static void amdgpu_debugfs_regs_cleanup(struct amdgpu_device *adev)
 {
-	debugfs_remove(adev->debugfs_regs);
-	adev->debugfs_regs = NULL;
+	unsigned i;
+
+	for (i = 0; i < ARRAY_SIZE(debugfs_regs); i++) {
+		if (adev->debugfs_regs[i]) {
+			debugfs_remove(adev->debugfs_regs[i]);
+			adev->debugfs_regs[i] = NULL;
+		}
+	}
 }
 
 int amdgpu_debugfs_init(struct drm_minor *minor)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c	2016-07-24 15:23:50.000000000 -0400
@@ -131,12 +131,17 @@ static void amdgpu_flip_work_func(struct
 				 vblank->framedur_ns / 1000,
 				 vblank->linedur_ns / 1000, stat, vpos, hpos);
 
-	/* set the flip status */
+	/* Do the flip (mmio) */
+	adev->mode_info.funcs->page_flip(adev, work->crtc_id, work->base, work->async);
+
+	/* Set the flip status */
 	amdgpuCrtc->pflip_status = AMDGPU_FLIP_SUBMITTED;
 	spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
 
-	/* Do the flip (mmio) */
-	adev->mode_info.funcs->page_flip(adev, work->crtc_id, work->base);
+
+	DRM_DEBUG_DRIVER("crtc:%d[%p], pflip_stat:AMDGPU_FLIP_SUBMITTED, work: %p,\n",
+					 amdgpuCrtc->crtc_id, amdgpuCrtc, work);
+
 }
 
 /*
@@ -192,6 +197,7 @@ int amdgpu_crtc_page_flip(struct drm_crt
 	work->event = event;
 	work->adev = adev;
 	work->crtc_id = amdgpu_crtc->crtc_id;
+	work->async = (page_flip_flags & DRM_MODE_PAGE_FLIP_ASYNC) != 0;
 
 	/* schedule unpin of the old buffer */
 	old_amdgpu_fb = to_amdgpu_framebuffer(crtc->primary->fb);
@@ -252,6 +258,9 @@ int amdgpu_crtc_page_flip(struct drm_crt
 	amdgpu_crtc->pflip_status = AMDGPU_FLIP_PENDING;
 	amdgpu_crtc->pflip_works = work;
 
+
+	DRM_DEBUG_DRIVER("crtc:%d[%p], pflip_stat:AMDGPU_FLIP_PENDING, work: %p,\n",
+					 amdgpu_crtc->crtc_id, amdgpu_crtc, work);
 	/* update crtc fb */
 	crtc->primary->fb = fb;
 	spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
@@ -554,7 +563,7 @@ amdgpu_user_framebuffer_create(struct dr
 	struct amdgpu_framebuffer *amdgpu_fb;
 	int ret;
 
-	obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]);
+	obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[0]);
 	if (obj ==  NULL) {
 		dev_err(&dev->pdev->dev, "No GEM object associated to handle 0x%08X, "
 			"can't create framebuffer\n", mode_cmd->handles[0]);
@@ -588,20 +597,20 @@ const struct drm_mode_config_funcs amdgp
 	.output_poll_changed = amdgpu_output_poll_changed
 };
 
-static struct drm_prop_enum_list amdgpu_underscan_enum_list[] =
+static const struct drm_prop_enum_list amdgpu_underscan_enum_list[] =
 {	{ UNDERSCAN_OFF, "off" },
 	{ UNDERSCAN_ON, "on" },
 	{ UNDERSCAN_AUTO, "auto" },
 };
 
-static struct drm_prop_enum_list amdgpu_audio_enum_list[] =
+static const struct drm_prop_enum_list amdgpu_audio_enum_list[] =
 {	{ AMDGPU_AUDIO_DISABLE, "off" },
 	{ AMDGPU_AUDIO_ENABLE, "on" },
 	{ AMDGPU_AUDIO_AUTO, "auto" },
 };
 
 /* XXX support different dither options? spatial, temporal, both, etc. */
-static struct drm_prop_enum_list amdgpu_dither_enum_list[] =
+static const struct drm_prop_enum_list amdgpu_dither_enum_list[] =
 {	{ AMDGPU_FMT_DITHER_DISABLE, "off" },
 	{ AMDGPU_FMT_DITHER_ENABLE, "on" },
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c	2016-07-24 15:23:50.000000000 -0400
@@ -150,7 +150,7 @@ u32 amdgpu_dpm_get_vrefresh(struct amdgp
 		list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 			amdgpu_crtc = to_amdgpu_crtc(crtc);
 			if (crtc->enabled && amdgpu_crtc->enabled && amdgpu_crtc->hw_mode.clock) {
-				vrefresh = amdgpu_crtc->hw_mode.vrefresh;
+				vrefresh = drm_mode_vrefresh(&amdgpu_crtc->hw_mode);
 				break;
 			}
 		}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c	2016-07-24 15:23:50.000000000 -0400
@@ -50,9 +50,11 @@
  * KMS wrapper.
  * - 3.0.0 - initial driver
  * - 3.1.0 - allow reading more status registers (GRBM, SRBM, SDMA, CP)
+ * - 3.2.0 - GFX8: Uses EOP_TC_WB_ACTION_EN, so UMDs don't have to do the same
+ *           at the end of IBs.
  */
 #define KMS_DRIVER_MAJOR	3
-#define KMS_DRIVER_MINOR	1
+#define KMS_DRIVER_MINOR	2
 #define KMS_DRIVER_PATCHLEVEL	0
 
 int amdgpu_vram_limit = 0;
@@ -166,7 +168,7 @@ module_param_named(pcie_gen_cap, amdgpu_
 MODULE_PARM_DESC(pcie_lane_cap, "PCIE Lane Caps (0: autodetect (default))");
 module_param_named(pcie_lane_cap, amdgpu_pcie_lane_cap, uint, 0444);
 
-static struct pci_device_id pciidlist[] = {
+static const struct pci_device_id pciidlist[] = {
 #ifdef CONFIG_DRM_AMDGPU_CIK
 	/* Kaveri */
 	{0x1002, 0x1304, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_KAVERI|AMD_IS_MOBILITY|AMD_IS_APU},
@@ -277,6 +279,28 @@ static struct pci_device_id pciidlist[]
 	{0x1002, 0x9877, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CARRIZO|AMD_IS_APU},
 	/* stoney */
 	{0x1002, 0x98E4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_STONEY|AMD_IS_APU},
+	/* Polaris11 */
+	{0x1002, 0x67E0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS11},
+	{0x1002, 0x67E3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS11},
+	{0x1002, 0x67E8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS11},
+	{0x1002, 0x67EB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS11},
+	{0x1002, 0x67EF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS11},
+	{0x1002, 0x67FF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS11},
+	{0x1002, 0x67E1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS11},
+	{0x1002, 0x67E7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS11},
+	{0x1002, 0x67E9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS11},
+	/* Polaris10 */
+	{0x1002, 0x67C0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
+	{0x1002, 0x67C1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
+	{0x1002, 0x67C2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
+	{0x1002, 0x67C4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
+	{0x1002, 0x67C7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
+	{0x1002, 0x67DF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
+	{0x1002, 0x67C8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
+	{0x1002, 0x67C9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
+	{0x1002, 0x67CA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
+	{0x1002, 0x67CC, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
+	{0x1002, 0x67CF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
 
 	{0, 0, 0}
 };
@@ -514,7 +538,7 @@ static struct drm_driver kms_driver = {
 	.irq_uninstall = amdgpu_irq_uninstall,
 	.irq_handler = amdgpu_irq_handler,
 	.ioctls = amdgpu_ioctls_kms,
-	.gem_free_object = amdgpu_gem_object_free,
+	.gem_free_object_unlocked = amdgpu_gem_object_free,
 	.gem_open_object = amdgpu_gem_object_open,
 	.gem_close_object = amdgpu_gem_object_close,
 	.dumb_create = amdgpu_mode_dumb_create,
@@ -553,22 +577,22 @@ static struct pci_driver amdgpu_kms_pci_
 	.driver.pm = &amdgpu_pm_ops,
 };
 
+
+
 static int __init amdgpu_init(void)
 {
 	amdgpu_sync_init();
-#ifdef CONFIG_VGA_CONSOLE
+	amdgpu_fence_slab_init();
 	if (vgacon_text_force()) {
 		DRM_ERROR("VGACON disables amdgpu kernel modesetting.\n");
 		return -EINVAL;
 	}
-#endif
 	DRM_INFO("amdgpu kernel modesetting enabled.\n");
 	driver = &kms_driver;
 	pdriver = &amdgpu_kms_pci_driver;
 	driver->driver_features |= DRIVER_MODESET;
 	driver->num_ioctls = amdgpu_max_kms_ioctl;
 	amdgpu_register_atpx_handler();
-
 	/* let modprobe override vga console setting */
 	return drm_pci_init(driver, pdriver);
 }
@@ -579,6 +603,7 @@ static void __exit amdgpu_exit(void)
 	drm_pci_exit(driver, pdriver);
 	amdgpu_unregister_atpx_handler();
 	amdgpu_sync_fini();
+	amdgpu_fence_slab_fini();
 }
 
 module_init(amdgpu_init);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c	2016-07-24 15:23:50.000000000 -0400
@@ -55,8 +55,21 @@ struct amdgpu_fence {
 };
 
 static struct kmem_cache *amdgpu_fence_slab;
-static atomic_t amdgpu_fence_slab_ref = ATOMIC_INIT(0);
 
+int amdgpu_fence_slab_init(void)
+{
+	amdgpu_fence_slab = kmem_cache_create(
+		"amdgpu_fence", sizeof(struct amdgpu_fence), 0,
+		SLAB_HWCACHE_ALIGN, NULL);
+	if (!amdgpu_fence_slab)
+		return -ENOMEM;
+	return 0;
+}
+
+void amdgpu_fence_slab_fini(void)
+{
+	kmem_cache_destroy(amdgpu_fence_slab);
+}
 /*
  * Cast helper
  */
@@ -198,7 +211,7 @@ void amdgpu_fence_process(struct amdgpu_
 
 		/* There is always exactly one thread signaling this fence slot */
 		fence = rcu_dereference_protected(*ptr, 1);
-		rcu_assign_pointer(*ptr, NULL);
+		RCU_INIT_POINTER(*ptr, NULL);
 
 		BUG_ON(!fence);
 
@@ -352,9 +365,9 @@ int amdgpu_fence_driver_init_ring(struct
 	setup_timer(&ring->fence_drv.fallback_timer, amdgpu_fence_fallback,
 		    (unsigned long)ring);
 
-	ring->fence_drv.num_fences_mask = num_hw_submission - 1;
+	ring->fence_drv.num_fences_mask = num_hw_submission * 2 - 1;
 	spin_lock_init(&ring->fence_drv.lock);
-	ring->fence_drv.fences = kcalloc(num_hw_submission, sizeof(void *),
+	ring->fence_drv.fences = kcalloc(num_hw_submission * 2, sizeof(void *),
 					 GFP_KERNEL);
 	if (!ring->fence_drv.fences)
 		return -ENOMEM;
@@ -396,13 +409,6 @@ int amdgpu_fence_driver_init_ring(struct
  */
 int amdgpu_fence_driver_init(struct amdgpu_device *adev)
 {
-	if (atomic_inc_return(&amdgpu_fence_slab_ref) == 1) {
-		amdgpu_fence_slab = kmem_cache_create(
-			"amdgpu_fence", sizeof(struct amdgpu_fence), 0,
-			SLAB_HWCACHE_ALIGN, NULL);
-		if (!amdgpu_fence_slab)
-			return -ENOMEM;
-	}
 	if (amdgpu_debugfs_fence_init(adev))
 		dev_err(adev->dev, "fence debugfs file creation failed\n");
 
@@ -437,13 +443,10 @@ void amdgpu_fence_driver_fini(struct amd
 		amd_sched_fini(&ring->sched);
 		del_timer_sync(&ring->fence_drv.fallback_timer);
 		for (j = 0; j <= ring->fence_drv.num_fences_mask; ++j)
-			fence_put(ring->fence_drv.fences[i]);
+			fence_put(ring->fence_drv.fences[j]);
 		kfree(ring->fence_drv.fences);
 		ring->fence_drv.initialized = false;
 	}
-
-	if (atomic_dec_and_test(&amdgpu_fence_slab_ref))
-		kmem_cache_destroy(amdgpu_fence_slab);
 }
 
 /**
@@ -639,7 +642,7 @@ static int amdgpu_debugfs_gpu_reset(stru
 	return 0;
 }
 
-static struct drm_info_list amdgpu_debugfs_fence_list[] = {
+static const struct drm_info_list amdgpu_debugfs_fence_list[] = {
 	{"amdgpu_fence_info", &amdgpu_debugfs_fence_info, 0, NULL},
 	{"amdgpu_gpu_reset", &amdgpu_debugfs_gpu_reset, 0, NULL}
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c	2016-07-24 15:23:50.000000000 -0400
@@ -238,18 +238,17 @@ void amdgpu_gart_unbind(struct amdgpu_de
 	t = offset / AMDGPU_GPU_PAGE_SIZE;
 	p = t / (PAGE_SIZE / AMDGPU_GPU_PAGE_SIZE);
 	for (i = 0; i < pages; i++, p++) {
-		if (adev->gart.pages[p]) {
-			adev->gart.pages[p] = NULL;
-			adev->gart.pages_addr[p] = adev->dummy_page.addr;
-			page_base = adev->gart.pages_addr[p];
-			if (!adev->gart.ptr)
-				continue;
+#ifdef CONFIG_AMDGPU_GART_DEBUGFS
+		adev->gart.pages[p] = NULL;
+#endif
+		page_base = adev->dummy_page.addr;
+		if (!adev->gart.ptr)
+			continue;
 
-			for (j = 0; j < (PAGE_SIZE / AMDGPU_GPU_PAGE_SIZE); j++, t++) {
-				amdgpu_gart_set_pte_pde(adev, adev->gart.ptr,
-							t, page_base, flags);
-				page_base += AMDGPU_GPU_PAGE_SIZE;
-			}
+		for (j = 0; j < (PAGE_SIZE / AMDGPU_GPU_PAGE_SIZE); j++, t++) {
+			amdgpu_gart_set_pte_pde(adev, adev->gart.ptr,
+						t, page_base, flags);
+			page_base += AMDGPU_GPU_PAGE_SIZE;
 		}
 	}
 	mb();
@@ -287,10 +286,11 @@ int amdgpu_gart_bind(struct amdgpu_devic
 	p = t / (PAGE_SIZE / AMDGPU_GPU_PAGE_SIZE);
 
 	for (i = 0; i < pages; i++, p++) {
-		adev->gart.pages_addr[p] = dma_addr[i];
+#ifdef CONFIG_AMDGPU_GART_DEBUGFS
 		adev->gart.pages[p] = pagelist[i];
+#endif
 		if (adev->gart.ptr) {
-			page_base = adev->gart.pages_addr[p];
+			page_base = dma_addr[i];
 			for (j = 0; j < (PAGE_SIZE / AMDGPU_GPU_PAGE_SIZE); j++, t++) {
 				amdgpu_gart_set_pte_pde(adev, adev->gart.ptr, t, page_base, flags);
 				page_base += AMDGPU_GPU_PAGE_SIZE;
@@ -312,11 +312,11 @@ int amdgpu_gart_bind(struct amdgpu_devic
  */
 int amdgpu_gart_init(struct amdgpu_device *adev)
 {
-	int r, i;
+	int r;
 
-	if (adev->gart.pages) {
+	if (adev->dummy_page.page)
 		return 0;
-	}
+
 	/* We need PAGE_SIZE >= AMDGPU_GPU_PAGE_SIZE */
 	if (PAGE_SIZE < AMDGPU_GPU_PAGE_SIZE) {
 		DRM_ERROR("Page size is smaller than GPU page size!\n");
@@ -330,22 +330,16 @@ int amdgpu_gart_init(struct amdgpu_devic
 	adev->gart.num_gpu_pages = adev->mc.gtt_size / AMDGPU_GPU_PAGE_SIZE;
 	DRM_INFO("GART: num cpu pages %u, num gpu pages %u\n",
 		 adev->gart.num_cpu_pages, adev->gart.num_gpu_pages);
+
+#ifdef CONFIG_AMDGPU_GART_DEBUGFS
 	/* Allocate pages table */
 	adev->gart.pages = vzalloc(sizeof(void *) * adev->gart.num_cpu_pages);
 	if (adev->gart.pages == NULL) {
 		amdgpu_gart_fini(adev);
 		return -ENOMEM;
 	}
-	adev->gart.pages_addr = vzalloc(sizeof(dma_addr_t) *
-					adev->gart.num_cpu_pages);
-	if (adev->gart.pages_addr == NULL) {
-		amdgpu_gart_fini(adev);
-		return -ENOMEM;
-	}
-	/* set GART entry to point to the dummy page by default */
-	for (i = 0; i < adev->gart.num_cpu_pages; i++) {
-		adev->gart.pages_addr[i] = adev->dummy_page.addr;
-	}
+#endif
+
 	return 0;
 }
 
@@ -358,15 +352,14 @@ int amdgpu_gart_init(struct amdgpu_devic
  */
 void amdgpu_gart_fini(struct amdgpu_device *adev)
 {
-	if (adev->gart.pages && adev->gart.pages_addr && adev->gart.ready) {
+	if (adev->gart.ready) {
 		/* unbind pages */
 		amdgpu_gart_unbind(adev, 0, adev->gart.num_cpu_pages);
 	}
 	adev->gart.ready = false;
+#ifdef CONFIG_AMDGPU_GART_DEBUGFS
 	vfree(adev->gart.pages);
-	vfree(adev->gart.pages_addr);
 	adev->gart.pages = NULL;
-	adev->gart.pages_addr = NULL;
-
+#endif
 	amdgpu_dummy_page_fini(adev);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gds.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gds.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gds.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gds.h	2016-07-24 15:23:50.000000000 -0400
@@ -43,7 +43,7 @@ struct amdgpu_ring;
 struct amdgpu_bo;
 
 struct amdgpu_gds_asic_info {
-	uint32_t 	total_size;
+	uint32_t	total_size;
 	uint32_t	gfx_partition_size;
 	uint32_t	cs_partition_size;
 };
@@ -52,8 +52,8 @@ struct amdgpu_gds {
 	struct amdgpu_gds_asic_info	mem;
 	struct amdgpu_gds_asic_info	gws;
 	struct amdgpu_gds_asic_info	oa;
-	/* At present, GDS, GWS and OA resources for gfx (graphics) 
-	 * is always pre-allocated and available for graphics operation. 
+	/* At present, GDS, GWS and OA resources for gfx (graphics)
+	 * is always pre-allocated and available for graphics operation.
 	 * Such resource is shared between all gfx clients.
 	 * TODO: move this operation to user space
 	 * */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c	2016-07-24 15:23:50.000000000 -0400
@@ -93,7 +93,7 @@ void amdgpu_gem_force_release(struct amd
 	struct drm_device *ddev = adev->ddev;
 	struct drm_file *file;
 
-	mutex_lock(&ddev->struct_mutex);
+	mutex_lock(&ddev->filelist_mutex);
 
 	list_for_each_entry(file, &ddev->filelist, lhead) {
 		struct drm_gem_object *gobj;
@@ -103,13 +103,13 @@ void amdgpu_gem_force_release(struct amd
 		spin_lock(&file->table_lock);
 		idr_for_each_entry(&file->object_idr, gobj, handle) {
 			WARN_ONCE(1, "And also active allocations!\n");
-			drm_gem_object_unreference(gobj);
+			drm_gem_object_unreference_unlocked(gobj);
 		}
 		idr_destroy(&file->object_idr);
 		spin_unlock(&file->table_lock);
 	}
 
-	mutex_unlock(&ddev->struct_mutex);
+	mutex_unlock(&ddev->filelist_mutex);
 }
 
 /*
@@ -338,7 +338,7 @@ int amdgpu_mode_dumb_mmap(struct drm_fil
 	struct drm_gem_object *gobj;
 	struct amdgpu_bo *robj;
 
-	gobj = drm_gem_object_lookup(dev, filp, handle);
+	gobj = drm_gem_object_lookup(filp, handle);
 	if (gobj == NULL) {
 		return -ENOENT;
 	}
@@ -402,7 +402,7 @@ int amdgpu_gem_wait_idle_ioctl(struct dr
 	int r = 0;
 	long ret;
 
-	gobj = drm_gem_object_lookup(dev, filp, handle);
+	gobj = drm_gem_object_lookup(filp, handle);
 	if (gobj == NULL) {
 		return -ENOENT;
 	}
@@ -436,7 +436,7 @@ int amdgpu_gem_metadata_ioctl(struct drm
 	int r = -1;
 
 	DRM_DEBUG("%d \n", args->handle);
-	gobj = drm_gem_object_lookup(dev, filp, args->handle);
+	gobj = drm_gem_object_lookup(filp, args->handle);
 	if (gobj == NULL)
 		return -ENOENT;
 	robj = gem_to_amdgpu_bo(gobj);
@@ -584,7 +584,7 @@ int amdgpu_gem_va_ioctl(struct drm_devic
 		return -EINVAL;
 	}
 
-	gobj = drm_gem_object_lookup(dev, filp, args->handle);
+	gobj = drm_gem_object_lookup(filp, args->handle);
 	if (gobj == NULL)
 		return -ENOENT;
 	rbo = gem_to_amdgpu_bo(gobj);
@@ -646,7 +646,7 @@ int amdgpu_gem_op_ioctl(struct drm_devic
 	struct amdgpu_bo *robj;
 	int r;
 
-	gobj = drm_gem_object_lookup(dev, filp, args->handle);
+	gobj = drm_gem_object_lookup(filp, args->handle);
 	if (gobj == NULL) {
 		return -ENOENT;
 	}
@@ -769,7 +769,7 @@ static int amdgpu_debugfs_gem_info(struc
 	struct drm_file *file;
 	int r;
 
-	r = mutex_lock_interruptible(&dev->struct_mutex);
+	r = mutex_lock_interruptible(&dev->filelist_mutex);
 	if (r)
 		return r;
 
@@ -793,11 +793,11 @@ static int amdgpu_debugfs_gem_info(struc
 		spin_unlock(&file->table_lock);
 	}
 
-	mutex_unlock(&dev->struct_mutex);
+	mutex_unlock(&dev->filelist_mutex);
 	return 0;
 }
 
-static struct drm_info_list amdgpu_debugfs_gem_list[] = {
+static const struct drm_info_list amdgpu_debugfs_gem_list[] = {
 	{"amdgpu_gem_info", &amdgpu_debugfs_gem_info, 0, NULL},
 };
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu.h	2016-07-24 15:23:50.000000000 -0400
@@ -283,7 +283,8 @@ struct amdgpu_ring_funcs {
 	int (*parse_cs)(struct amdgpu_cs_parser *p, uint32_t ib_idx);
 	/* command emit functions */
 	void (*emit_ib)(struct amdgpu_ring *ring,
-			struct amdgpu_ib *ib);
+			struct amdgpu_ib *ib,
+			unsigned vm_id, bool ctx_switch);
 	void (*emit_fence)(struct amdgpu_ring *ring, uint64_t addr,
 			   uint64_t seq, unsigned flags);
 	void (*emit_pipeline_sync)(struct amdgpu_ring *ring);
@@ -302,6 +303,8 @@ struct amdgpu_ring_funcs {
 	void (*insert_nop)(struct amdgpu_ring *ring, uint32_t count);
 	/* pad the indirect buffer to the necessary number of dw */
 	void (*pad_ib)(struct amdgpu_ring *ring, struct amdgpu_ib *ib);
+	unsigned (*init_cond_exec)(struct amdgpu_ring *ring);
+	void (*patch_cond_exec)(struct amdgpu_ring *ring, unsigned offset);
 };
 
 /*
@@ -365,13 +368,6 @@ struct amdgpu_fence_driver {
 #define AMDGPU_FENCE_FLAG_64BIT         (1 << 0)
 #define AMDGPU_FENCE_FLAG_INT           (1 << 1)
 
-struct amdgpu_user_fence {
-	/* write-back bo */
-	struct amdgpu_bo 	*bo;
-	/* write-back address offset to bo start */
-	uint32_t                offset;
-};
-
 int amdgpu_fence_driver_init(struct amdgpu_device *adev);
 void amdgpu_fence_driver_fini(struct amdgpu_device *adev);
 void amdgpu_fence_driver_force_completion(struct amdgpu_device *adev);
@@ -391,6 +387,14 @@ unsigned amdgpu_fence_count_emitted(stru
 /*
  * TTM.
  */
+
+#define AMDGPU_TTM_LRU_SIZE	20
+
+struct amdgpu_mman_lru {
+	struct list_head		*lru[TTM_NUM_MEM_TYPES];
+	struct list_head		*swap_lru;
+};
+
 struct amdgpu_mman {
 	struct ttm_bo_global_ref        bo_global_ref;
 	struct drm_global_reference	mem_global_ref;
@@ -408,6 +412,9 @@ struct amdgpu_mman {
 	struct amdgpu_ring			*buffer_funcs_ring;
 	/* Scheduler entity for buffer moves */
 	struct amd_sched_entity			entity;
+
+	/* custom LRU management */
+	struct amdgpu_mman_lru			log2_size[AMDGPU_TTM_LRU_SIZE];
 };
 
 int amdgpu_copy_buffer(struct amdgpu_ring *ring,
@@ -494,9 +501,10 @@ void amdgpu_gem_object_close(struct drm_
 				struct drm_file *file_priv);
 unsigned long amdgpu_gem_timeout(uint64_t timeout_ns);
 struct sg_table *amdgpu_gem_prime_get_sg_table(struct drm_gem_object *obj);
-struct drm_gem_object *amdgpu_gem_prime_import_sg_table(struct drm_device *dev,
-							struct dma_buf_attachment *attach,
-							struct sg_table *sg);
+struct drm_gem_object *
+amdgpu_gem_prime_import_sg_table(struct drm_device *dev,
+				 struct dma_buf_attachment *attach,
+				 struct sg_table *sg);
 struct dma_buf *amdgpu_gem_prime_export(struct drm_device *dev,
 					struct drm_gem_object *gobj,
 					int flags);
@@ -586,11 +594,16 @@ int amdgpu_sync_resv(struct amdgpu_devic
 		     struct amdgpu_sync *sync,
 		     struct reservation_object *resv,
 		     void *owner);
+bool amdgpu_sync_is_idle(struct amdgpu_sync *sync);
+int amdgpu_sync_cycle_fences(struct amdgpu_sync *dst, struct amdgpu_sync *src,
+			     struct fence *fence);
 struct fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync);
 int amdgpu_sync_wait(struct amdgpu_sync *sync);
 void amdgpu_sync_free(struct amdgpu_sync *sync);
 int amdgpu_sync_init(void);
 void amdgpu_sync_fini(void);
+int amdgpu_fence_slab_init(void);
+void amdgpu_fence_slab_fini(void);
 
 /*
  * GART structures, functions & helpers
@@ -609,8 +622,9 @@ struct amdgpu_gart {
 	unsigned			num_gpu_pages;
 	unsigned			num_cpu_pages;
 	unsigned			table_size;
+#ifdef CONFIG_DRM_AMDGPU_GART_DEBUGFS
 	struct page			**pages;
-	dma_addr_t			*pages_addr;
+#endif
 	bool				ready;
 	const struct amdgpu_gart_funcs *gart_funcs;
 };
@@ -709,6 +723,7 @@ struct amdgpu_flip_work {
 	unsigned			shared_count;
 	struct fence			**shared;
 	struct fence_cb			cb;
+	bool				async;
 };
 
 
@@ -721,17 +736,7 @@ struct amdgpu_ib {
 	uint32_t			length_dw;
 	uint64_t			gpu_addr;
 	uint32_t			*ptr;
-	struct amdgpu_user_fence        *user;
-	struct amdgpu_vm		*vm;
-	unsigned			vm_id;
-	uint64_t			vm_pd_addr;
-	struct amdgpu_ctx		*ctx;
-	uint32_t			gds_base, gds_size;
-	uint32_t			gws_base, gws_size;
-	uint32_t			oa_base, oa_size;
 	uint32_t			flags;
-	/* resulting sequence number */
-	uint64_t			sequence;
 };
 
 enum amdgpu_ring_type {
@@ -742,22 +747,25 @@ enum amdgpu_ring_type {
 	AMDGPU_RING_TYPE_VCE
 };
 
-extern struct amd_sched_backend_ops amdgpu_sched_ops;
+extern const struct amd_sched_backend_ops amdgpu_sched_ops;
 
 int amdgpu_job_alloc(struct amdgpu_device *adev, unsigned num_ibs,
-		     struct amdgpu_job **job);
+		     struct amdgpu_job **job, struct amdgpu_vm *vm);
 int amdgpu_job_alloc_with_ib(struct amdgpu_device *adev, unsigned size,
 			     struct amdgpu_job **job);
+
 void amdgpu_job_free(struct amdgpu_job *job);
+void amdgpu_job_free_func(struct kref *refcount);
 int amdgpu_job_submit(struct amdgpu_job *job, struct amdgpu_ring *ring,
 		      struct amd_sched_entity *entity, void *owner,
 		      struct fence **f);
+void amdgpu_job_timeout_func(struct work_struct *work);
 
 struct amdgpu_ring {
 	struct amdgpu_device		*adev;
 	const struct amdgpu_ring_funcs	*funcs;
 	struct amdgpu_fence_driver	fence_drv;
-	struct amd_gpu_scheduler 	sched;
+	struct amd_gpu_scheduler	sched;
 
 	spinlock_t              fence_lock;
 	struct amdgpu_bo	*ring_obj;
@@ -785,9 +793,12 @@ struct amdgpu_ring {
 	unsigned		wptr_offs;
 	unsigned		next_rptr_offs;
 	unsigned		fence_offs;
-	struct amdgpu_ctx	*current_ctx;
+	uint64_t		current_ctx;
 	enum amdgpu_ring_type	type;
 	char			name[16];
+	unsigned		cond_exe_offs;
+	u64				cond_exe_gpu_addr;
+	volatile u32	*cond_exe_cpu_addr;
 };
 
 /*
@@ -830,13 +841,6 @@ struct amdgpu_vm_pt {
 	uint64_t			addr;
 };
 
-struct amdgpu_vm_id {
-	struct amdgpu_vm_manager_id	*mgr_id;
-	uint64_t			pd_gpu_addr;
-	/* last flushed PD/PT update */
-	struct fence			*flushed_updates;
-};
-
 struct amdgpu_vm {
 	/* tree of virtual addresses mapped */
 	struct rb_root		va;
@@ -862,19 +866,29 @@ struct amdgpu_vm {
 	struct amdgpu_vm_pt	*page_tables;
 
 	/* for id and flush management per ring */
-	struct amdgpu_vm_id	ids[AMDGPU_MAX_RINGS];
+	struct amdgpu_vm_id	*ids[AMDGPU_MAX_RINGS];
 
 	/* protecting freed */
 	spinlock_t		freed_lock;
 
 	/* Scheduler entity for page table updates */
 	struct amd_sched_entity	entity;
+
+	/* client id */
+	u64                     client_id;
 };
 
-struct amdgpu_vm_manager_id {
+struct amdgpu_vm_id {
 	struct list_head	list;
-	struct fence		*active;
-	atomic_long_t		owner;
+	struct fence		*first;
+	struct amdgpu_sync	active;
+	struct fence		*last_flush;
+	struct amdgpu_ring      *last_user;
+	atomic64_t		owner;
+
+	uint64_t		pd_gpu_addr;
+	/* last flushed PD/PT update */
+	struct fence		*flushed_updates;
 
 	uint32_t		gds_base;
 	uint32_t		gds_size;
@@ -889,7 +903,7 @@ struct amdgpu_vm_manager {
 	struct mutex				lock;
 	unsigned				num_ids;
 	struct list_head			ids_lru;
-	struct amdgpu_vm_manager_id		ids[AMDGPU_NUM_VM];
+	struct amdgpu_vm_id			ids[AMDGPU_NUM_VM];
 
 	uint32_t				max_pfn;
 	/* vram base address for page table entry  */
@@ -901,6 +915,8 @@ struct amdgpu_vm_manager {
 	struct amdgpu_ring                      *vm_pte_rings[AMDGPU_MAX_RINGS];
 	unsigned				vm_pte_num_rings;
 	atomic_t				vm_pte_next_ring;
+	/* client id counter */
+	atomic64_t				client_counter;
 };
 
 void amdgpu_vm_manager_init(struct amdgpu_device *adev);
@@ -916,11 +932,11 @@ void amdgpu_vm_move_pt_bos_in_lru(struct
 int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
 		      struct amdgpu_sync *sync, struct fence *fence,
 		      unsigned *vm_id, uint64_t *vm_pd_addr);
-void amdgpu_vm_flush(struct amdgpu_ring *ring,
-		     unsigned vm_id, uint64_t pd_addr,
-		     uint32_t gds_base, uint32_t gds_size,
-		     uint32_t gws_base, uint32_t gws_size,
-		     uint32_t oa_base, uint32_t oa_size);
+int amdgpu_vm_flush(struct amdgpu_ring *ring,
+		    unsigned vm_id, uint64_t pd_addr,
+		    uint32_t gds_base, uint32_t gds_size,
+		    uint32_t gws_base, uint32_t gws_size,
+		    uint32_t oa_base, uint32_t oa_size);
 void amdgpu_vm_reset_id(struct amdgpu_device *adev, unsigned vm_id);
 uint64_t amdgpu_vm_map_gart(const dma_addr_t *pages_addr, uint64_t addr);
 int amdgpu_vm_update_page_directory(struct amdgpu_device *adev,
@@ -1026,6 +1042,11 @@ void amdgpu_bo_list_free(struct amdgpu_b
  */
 #include "clearstate_defs.h"
 
+struct amdgpu_rlc_funcs {
+	void (*enter_safe_mode)(struct amdgpu_device *adev);
+	void (*exit_safe_mode)(struct amdgpu_device *adev);
+};
+
 struct amdgpu_rlc {
 	/* for power gating */
 	struct amdgpu_bo	*save_restore_obj;
@@ -1044,6 +1065,24 @@ struct amdgpu_rlc {
 	uint64_t		cp_table_gpu_addr;
 	volatile uint32_t	*cp_table_ptr;
 	u32                     cp_table_size;
+
+	/* safe mode for updating CG/PG state */
+	bool in_safe_mode;
+	const struct amdgpu_rlc_funcs *funcs;
+
+	/* for firmware data */
+	u32 save_and_restore_offset;
+	u32 clear_state_descriptor_offset;
+	u32 avail_scratch_ram_locations;
+	u32 reg_restore_list_size;
+	u32 reg_list_format_start;
+	u32 reg_list_format_separate_start;
+	u32 starting_offsets_start;
+	u32 reg_list_format_size_bytes;
+	u32 reg_list_size_bytes;
+
+	u32 *register_list_format;
+	u32 *register_restore;
 };
 
 struct amdgpu_mec {
@@ -1097,6 +1136,12 @@ struct amdgpu_gca_config {
 	uint32_t macrotile_mode_array[16];
 };
 
+struct amdgpu_cu_info {
+	uint32_t number; /* total active CU number */
+	uint32_t ao_cu_mask;
+	uint32_t bitmap[4][4];
+};
+
 struct amdgpu_gfx {
 	struct mutex			gpu_clock_mutex;
 	struct amdgpu_gca_config	config;
@@ -1129,17 +1174,19 @@ struct amdgpu_gfx {
 	struct amdgpu_irq_src		priv_reg_irq;
 	struct amdgpu_irq_src		priv_inst_irq;
 	/* gfx status */
-	uint32_t gfx_current_status;
+	uint32_t			gfx_current_status;
 	/* ce ram size*/
-	unsigned ce_ram_size;
+	unsigned			ce_ram_size;
+	struct amdgpu_cu_info		cu_info;
 };
 
 int amdgpu_ib_get(struct amdgpu_device *adev, struct amdgpu_vm *vm,
 		  unsigned size, struct amdgpu_ib *ib);
-void amdgpu_ib_free(struct amdgpu_device *adev, struct amdgpu_ib *ib, struct fence *f);
+void amdgpu_ib_free(struct amdgpu_device *adev, struct amdgpu_ib *ib,
+		    struct fence *f);
 int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
 		       struct amdgpu_ib *ib, struct fence *last_vm_update,
-		       struct fence **f);
+		       struct amdgpu_job *job, struct fence **f);
 int amdgpu_ib_pool_init(struct amdgpu_device *adev);
 void amdgpu_ib_pool_fini(struct amdgpu_device *adev);
 int amdgpu_ib_ring_tests(struct amdgpu_device *adev);
@@ -1164,7 +1211,7 @@ void amdgpu_ring_fini(struct amdgpu_ring
 struct amdgpu_cs_chunk {
 	uint32_t		chunk_id;
 	uint32_t		length_dw;
-	uint32_t		*kdata;
+	void			*kdata;
 };
 
 struct amdgpu_cs_parser {
@@ -1195,13 +1242,25 @@ struct amdgpu_cs_parser {
 struct amdgpu_job {
 	struct amd_sched_job    base;
 	struct amdgpu_device	*adev;
+	struct amdgpu_vm	*vm;
 	struct amdgpu_ring	*ring;
 	struct amdgpu_sync	sync;
 	struct amdgpu_ib	*ibs;
 	struct fence		*fence; /* the hw fence */
 	uint32_t		num_ibs;
 	void			*owner;
-	struct amdgpu_user_fence uf;
+	uint64_t		ctx;
+	unsigned		vm_id;
+	uint64_t		vm_pd_addr;
+	uint32_t		gds_base, gds_size;
+	uint32_t		gws_base, gws_size;
+	uint32_t		oa_base, oa_size;
+
+	/* user fence handling */
+	struct amdgpu_bo	*uf_bo;
+	uint32_t		uf_offset;
+	uint64_t		uf_sequence;
+
 };
 #define to_amdgpu_job(sched_job)		\
 		container_of((sched_job), struct amdgpu_job, base)
@@ -1582,10 +1641,12 @@ void amdgpu_get_pcie_info(struct amdgpu_
 /*
  * UVD
  */
-#define AMDGPU_MAX_UVD_HANDLES	10
-#define AMDGPU_UVD_STACK_SIZE	(1024*1024)
-#define AMDGPU_UVD_HEAP_SIZE	(1024*1024)
-#define AMDGPU_UVD_FIRMWARE_OFFSET 256
+#define AMDGPU_DEFAULT_UVD_HANDLES	10
+#define AMDGPU_MAX_UVD_HANDLES		40
+#define AMDGPU_UVD_STACK_SIZE		(200*1024)
+#define AMDGPU_UVD_HEAP_SIZE		(256*1024)
+#define AMDGPU_UVD_SESSION_SIZE		(50*1024)
+#define AMDGPU_UVD_FIRMWARE_OFFSET	256
 
 struct amdgpu_uvd {
 	struct amdgpu_bo	*vcpu_bo;
@@ -1593,6 +1654,7 @@ struct amdgpu_uvd {
 	uint64_t		gpu_addr;
 	unsigned		fw_version;
 	void			*saved_bo;
+	unsigned		max_handles;
 	atomic_t		handles[AMDGPU_MAX_UVD_HANDLES];
 	struct drm_file		*filp[AMDGPU_MAX_UVD_HANDLES];
 	struct delayed_work	idle_work;
@@ -1645,7 +1707,7 @@ struct amdgpu_sdma {
 	struct amdgpu_sdma_instance instance[AMDGPU_MAX_SDMA_INSTANCES];
 	struct amdgpu_irq_src	trap_irq;
 	struct amdgpu_irq_src	illegal_inst_irq;
-	int 			num_instances;
+	int			num_instances;
 };
 
 /*
@@ -1691,12 +1753,12 @@ static inline void amdgpu_mn_unregister(
  * Debugfs
  */
 struct amdgpu_debugfs {
-	struct drm_info_list	*files;
+	const struct drm_info_list	*files;
 	unsigned		num_files;
 };
 
 int amdgpu_debugfs_add_files(struct amdgpu_device *adev,
-			     struct drm_info_list *files,
+			     const struct drm_info_list *files,
 			     unsigned nfiles);
 int amdgpu_debugfs_fence_init(struct amdgpu_device *adev);
 
@@ -1738,13 +1800,6 @@ struct amdgpu_allowed_register_entry {
 	bool grbm_indexed;
 };
 
-struct amdgpu_cu_info {
-	uint32_t number; /* total active CU number */
-	uint32_t ao_cu_mask;
-	uint32_t bitmap[4][4];
-};
-
-
 /*
  * ASIC specific functions.
  */
@@ -1762,10 +1817,11 @@ struct amdgpu_asic_funcs {
 	u32 (*get_xclk)(struct amdgpu_device *adev);
 	/* get the gpu clock counter */
 	uint64_t (*get_gpu_clock_counter)(struct amdgpu_device *adev);
-	int (*get_cu_info)(struct amdgpu_device *adev, struct amdgpu_cu_info *info);
 	/* MM block clocks */
 	int (*set_uvd_clocks)(struct amdgpu_device *adev, u32 vclk, u32 dclk);
 	int (*set_vce_clocks)(struct amdgpu_device *adev, u32 evclk, u32 ecclk);
+	/* query virtual capabilities */
+	u32 (*get_virtual_caps)(struct amdgpu_device *adev);
 };
 
 /*
@@ -1855,20 +1911,17 @@ struct amdgpu_atcs {
 /*
  * CGS
  */
-void *amdgpu_cgs_create_device(struct amdgpu_device *adev);
-void amdgpu_cgs_destroy_device(void *cgs_device);
-
-
-/*
- * CGS
- */
-void *amdgpu_cgs_create_device(struct amdgpu_device *adev);
-void amdgpu_cgs_destroy_device(void *cgs_device);
+struct cgs_device *amdgpu_cgs_create_device(struct amdgpu_device *adev);
+void amdgpu_cgs_destroy_device(struct cgs_device *cgs_device);
 
 
 /* GPU virtualization */
+#define AMDGPU_VIRT_CAPS_SRIOV_EN       (1 << 0)
+#define AMDGPU_VIRT_CAPS_IS_VF          (1 << 1)
 struct amdgpu_virtualization {
 	bool supports_sr_iov;
+	bool is_virtual;
+	u32 caps;
 };
 
 /*
@@ -1904,16 +1957,15 @@ struct amdgpu_device {
 	int				usec_timeout;
 	const struct amdgpu_asic_funcs	*asic_funcs;
 	bool				shutdown;
-	bool				suspend;
 	bool				need_dma32;
 	bool				accel_working;
-	struct work_struct 		reset_work;
+	struct work_struct		reset_work;
 	struct notifier_block		acpi_nb;
 	struct amdgpu_i2c_chan		*i2c_bus[AMDGPU_MAX_I2C_BUS];
 	struct amdgpu_debugfs		debugfs[AMDGPU_DEBUGFS_MAX_COMPONENTS];
-	unsigned 			debugfs_count;
+	unsigned			debugfs_count;
 #if defined(CONFIG_DEBUG_FS)
-	struct dentry			*debugfs_regs;
+	struct dentry			*debugfs_regs[AMDGPU_DEBUGFS_MAX_COMPONENTS];
 #endif
 	struct amdgpu_atif		atif;
 	struct amdgpu_atcs		atcs;
@@ -1926,7 +1978,6 @@ struct amdgpu_device {
 	/* BIOS */
 	uint8_t				*bios;
 	bool				is_atom_bios;
-	uint16_t			bios_header_start;
 	struct amdgpu_bo		*stollen_vga_memory;
 	uint32_t			bios_scratch[AMDGPU_BIOS_NUM_SCRATCH];
 
@@ -2159,11 +2210,11 @@ amdgpu_get_sdma_instance(struct amdgpu_r
 #define amdgpu_asic_get_xclk(adev) (adev)->asic_funcs->get_xclk((adev))
 #define amdgpu_asic_set_uvd_clocks(adev, v, d) (adev)->asic_funcs->set_uvd_clocks((adev), (v), (d))
 #define amdgpu_asic_set_vce_clocks(adev, ev, ec) (adev)->asic_funcs->set_vce_clocks((adev), (ev), (ec))
+#define amdgpu_asic_get_virtual_caps(adev) ((adev)->asic_funcs->get_virtual_caps((adev)))
 #define amdgpu_asic_get_gpu_clock_counter(adev) (adev)->asic_funcs->get_gpu_clock_counter((adev))
 #define amdgpu_asic_read_disabled_bios(adev) (adev)->asic_funcs->read_disabled_bios((adev))
 #define amdgpu_asic_read_bios_from_rom(adev, b, l) (adev)->asic_funcs->read_bios_from_rom((adev), (b), (l))
 #define amdgpu_asic_read_register(adev, se, sh, offset, v)((adev)->asic_funcs->read_register((adev), (se), (sh), (offset), (v)))
-#define amdgpu_asic_get_cu_info(adev, info) (adev)->asic_funcs->get_cu_info((adev), (info))
 #define amdgpu_gart_flush_gpu_tlb(adev, vmid) (adev)->gart.gart_funcs->flush_gpu_tlb((adev), (vmid))
 #define amdgpu_gart_set_pte_pde(adev, pt, idx, addr, flags) (adev)->gart.gart_funcs->set_pte_pde((adev), (pt), (idx), (addr), (flags))
 #define amdgpu_vm_copy_pte(adev, ib, pe, src, count) ((adev)->vm_manager.vm_pte_funcs->copy_pte((ib), (pe), (src), (count)))
@@ -2175,7 +2226,7 @@ amdgpu_get_sdma_instance(struct amdgpu_r
 #define amdgpu_ring_get_rptr(r) (r)->funcs->get_rptr((r))
 #define amdgpu_ring_get_wptr(r) (r)->funcs->get_wptr((r))
 #define amdgpu_ring_set_wptr(r) (r)->funcs->set_wptr((r))
-#define amdgpu_ring_emit_ib(r, ib) (r)->funcs->emit_ib((r), (ib))
+#define amdgpu_ring_emit_ib(r, ib, vm_id, c) (r)->funcs->emit_ib((r), (ib), (vm_id), (c))
 #define amdgpu_ring_emit_pipeline_sync(r) (r)->funcs->emit_pipeline_sync((r))
 #define amdgpu_ring_emit_vm_flush(r, vmid, addr) (r)->funcs->emit_vm_flush((r), (vmid), (addr))
 #define amdgpu_ring_emit_fence(r, addr, seq, flags) (r)->funcs->emit_fence((r), (addr), (seq), (flags))
@@ -2183,6 +2234,8 @@ amdgpu_get_sdma_instance(struct amdgpu_r
 #define amdgpu_ring_emit_hdp_flush(r) (r)->funcs->emit_hdp_flush((r))
 #define amdgpu_ring_emit_hdp_invalidate(r) (r)->funcs->emit_hdp_invalidate((r))
 #define amdgpu_ring_pad_ib(r, ib) ((r)->funcs->pad_ib((r), (ib)))
+#define amdgpu_ring_init_cond_exec(r) (r)->funcs->init_cond_exec((r))
+#define amdgpu_ring_patch_cond_exec(r,o) (r)->funcs->patch_cond_exec((r),(o))
 #define amdgpu_ih_get_wptr(adev) (adev)->irq.ih_funcs->get_wptr((adev))
 #define amdgpu_ih_decode_iv(adev, iv) (adev)->irq.ih_funcs->decode_iv((adev), (iv))
 #define amdgpu_ih_set_rptr(adev) (adev)->irq.ih_funcs->set_rptr((adev))
@@ -2196,7 +2249,7 @@ amdgpu_get_sdma_instance(struct amdgpu_r
 #define amdgpu_display_hpd_set_polarity(adev, h) (adev)->mode_info.funcs->hpd_set_polarity((adev), (h))
 #define amdgpu_display_hpd_get_gpio_reg(adev) (adev)->mode_info.funcs->hpd_get_gpio_reg((adev))
 #define amdgpu_display_bandwidth_update(adev) (adev)->mode_info.funcs->bandwidth_update((adev))
-#define amdgpu_display_page_flip(adev, crtc, base) (adev)->mode_info.funcs->page_flip((adev), (crtc), (base))
+#define amdgpu_display_page_flip(adev, crtc, base, async) (adev)->mode_info.funcs->page_flip((adev), (crtc), (base), (async))
 #define amdgpu_display_page_flip_get_scanoutpos(adev, crtc, vbl, pos) (adev)->mode_info.funcs->page_flip_get_scanoutpos((adev), (crtc), (vbl), (pos))
 #define amdgpu_display_add_encoder(adev, e, s, c) (adev)->mode_info.funcs->add_encoder((adev), (e), (s), (c))
 #define amdgpu_display_add_connector(adev, ci, sd, ct, ib, coi, h, r) (adev)->mode_info.funcs->add_connector((adev), (ci), (sd), (ct), (ib), (coi), (h), (r))
@@ -2339,7 +2392,7 @@ static inline void amdgpu_unregister_atp
  * KMS
  */
 extern const struct drm_ioctl_desc amdgpu_ioctls_kms[];
-extern int amdgpu_max_kms_ioctl;
+extern const int amdgpu_max_kms_ioctl;
 
 int amdgpu_driver_load_kms(struct drm_device *dev, unsigned long flags);
 int amdgpu_driver_unload_kms(struct drm_device *dev);
@@ -2398,5 +2451,4 @@ amdgpu_cs_find_mapping(struct amdgpu_cs_
 		       uint64_t addr, struct amdgpu_bo **bo);
 
 #include "amdgpu_object.h"
-
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c	2016-07-24 15:23:50.000000000 -0400
@@ -74,9 +74,6 @@ int amdgpu_ib_get(struct amdgpu_device *
 			ib->gpu_addr = amdgpu_sa_bo_gpu_addr(ib->sa_bo);
 	}
 
-	ib->vm = vm;
-	ib->vm_id = 0;
-
 	return 0;
 }
 
@@ -89,7 +86,8 @@ int amdgpu_ib_get(struct amdgpu_device *
  *
  * Free an IB (all asics).
  */
-void amdgpu_ib_free(struct amdgpu_device *adev, struct amdgpu_ib *ib, struct fence *f)
+void amdgpu_ib_free(struct amdgpu_device *adev, struct amdgpu_ib *ib,
+		    struct fence *f)
 {
 	amdgpu_sa_bo_free(adev, &ib->sa_bo, f);
 }
@@ -117,28 +115,37 @@ void amdgpu_ib_free(struct amdgpu_device
  */
 int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
 		       struct amdgpu_ib *ibs, struct fence *last_vm_update,
-		       struct fence **f)
+		       struct amdgpu_job *job, struct fence **f)
 {
 	struct amdgpu_device *adev = ring->adev;
 	struct amdgpu_ib *ib = &ibs[0];
-	struct amdgpu_ctx *ctx, *old_ctx;
+	bool skip_preamble, need_ctx_switch;
+	unsigned patch_offset = ~0;
 	struct amdgpu_vm *vm;
 	struct fence *hwf;
+	uint64_t ctx;
+
 	unsigned i;
 	int r = 0;
 
 	if (num_ibs == 0)
 		return -EINVAL;
 
-	ctx = ibs->ctx;
-	vm = ibs->vm;
+	/* ring tests don't use a job */
+	if (job) {
+		vm = job->vm;
+		ctx = job->ctx;
+	} else {
+		vm = NULL;
+		ctx = 0;
+	}
 
 	if (!ring->ready) {
 		dev_err(adev->dev, "couldn't schedule ib\n");
 		return -EINVAL;
 	}
 
-	if (vm && !ibs->vm_id) {
+	if (vm && !job->vm_id) {
 		dev_err(adev->dev, "VM IB without ID\n");
 		return -EINVAL;
 	}
@@ -149,58 +156,68 @@ int amdgpu_ib_schedule(struct amdgpu_rin
 		return r;
 	}
 
-	if (vm) {
-		/* do context switch */
-		amdgpu_vm_flush(ring, ib->vm_id, ib->vm_pd_addr,
-				ib->gds_base, ib->gds_size,
-				ib->gws_base, ib->gws_size,
-				ib->oa_base, ib->oa_size);
+	if (ring->type == AMDGPU_RING_TYPE_SDMA && ring->funcs->init_cond_exec)
+		patch_offset = amdgpu_ring_init_cond_exec(ring);
 
-		if (ring->funcs->emit_hdp_flush)
-			amdgpu_ring_emit_hdp_flush(ring);
+	if (vm) {
+		r = amdgpu_vm_flush(ring, job->vm_id, job->vm_pd_addr,
+				    job->gds_base, job->gds_size,
+				    job->gws_base, job->gws_size,
+				    job->oa_base, job->oa_size);
+		if (r) {
+			amdgpu_ring_undo(ring);
+			return r;
+		}
 	}
 
-	old_ctx = ring->current_ctx;
+	if (ring->funcs->emit_hdp_flush)
+		amdgpu_ring_emit_hdp_flush(ring);
+
+	/* always set cond_exec_polling to CONTINUE */
+	*ring->cond_exe_cpu_addr = 1;
+
+	skip_preamble = ring->current_ctx == ctx;
+	need_ctx_switch = ring->current_ctx != ctx;
 	for (i = 0; i < num_ibs; ++i) {
 		ib = &ibs[i];
 
-		if (ib->ctx != ctx || ib->vm != vm) {
-			ring->current_ctx = old_ctx;
-			if (ib->vm_id)
-				amdgpu_vm_reset_id(adev, ib->vm_id);
-			amdgpu_ring_undo(ring);
-			return -EINVAL;
-		}
-		amdgpu_ring_emit_ib(ring, ib);
-		ring->current_ctx = ctx;
-	}
+		/* drop preamble IBs if we don't have a context switch */
+		if ((ib->flags & AMDGPU_IB_FLAG_PREAMBLE) && skip_preamble)
+			continue;
 
-	if (vm) {
-		if (ring->funcs->emit_hdp_invalidate)
-			amdgpu_ring_emit_hdp_invalidate(ring);
+		amdgpu_ring_emit_ib(ring, ib, job ? job->vm_id : 0,
+				    need_ctx_switch);
+		need_ctx_switch = false;
 	}
 
+	if (ring->funcs->emit_hdp_invalidate)
+		amdgpu_ring_emit_hdp_invalidate(ring);
+
 	r = amdgpu_fence_emit(ring, &hwf);
 	if (r) {
 		dev_err(adev->dev, "failed to emit fence (%d)\n", r);
-		ring->current_ctx = old_ctx;
-		if (ib->vm_id)
-			amdgpu_vm_reset_id(adev, ib->vm_id);
+		if (job && job->vm_id)
+			amdgpu_vm_reset_id(adev, job->vm_id);
 		amdgpu_ring_undo(ring);
 		return r;
 	}
 
 	/* wrap the last IB with fence */
-	if (ib->user) {
-		uint64_t addr = amdgpu_bo_gpu_offset(ib->user->bo);
-		addr += ib->user->offset;
-		amdgpu_ring_emit_fence(ring, addr, ib->sequence,
+	if (job && job->uf_bo) {
+		uint64_t addr = amdgpu_bo_gpu_offset(job->uf_bo);
+
+		addr += job->uf_offset;
+		amdgpu_ring_emit_fence(ring, addr, job->uf_sequence,
 				       AMDGPU_FENCE_FLAG_64BIT);
 	}
 
 	if (f)
 		*f = fence_get(hwf);
 
+	if (patch_offset != ~0 && ring->funcs->patch_cond_exec)
+		amdgpu_ring_patch_cond_exec(ring, patch_offset);
+
+	ring->current_ctx = ctx;
 	amdgpu_ring_commit(ring);
 	return 0;
 }
@@ -315,7 +332,7 @@ static int amdgpu_debugfs_sa_info(struct
 
 }
 
-static struct drm_info_list amdgpu_debugfs_sa_list[] = {
+static const struct drm_info_list amdgpu_debugfs_sa_list[] = {
 	{"amdgpu_sa_info", &amdgpu_debugfs_sa_info, 0, NULL},
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c	2016-07-24 15:23:50.000000000 -0400
@@ -219,7 +219,6 @@ int amdgpu_irq_init(struct amdgpu_device
 	if (r) {
 		return r;
 	}
-	adev->ddev->vblank_disable_allowed = true;
 
 	/* enable msi */
 	adev->irq.msi_enabled = false;
@@ -498,7 +497,7 @@ static int amdgpu_irqdomain_map(struct i
 	return 0;
 }
 
-static struct irq_domain_ops amdgpu_hw_irqdomain_ops = {
+static const struct irq_domain_ops amdgpu_hw_irqdomain_ops = {
 	.map = amdgpu_irqdomain_map,
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c	2016-07-24 15:23:50.000000000 -0400
@@ -28,8 +28,25 @@
 #include "amdgpu.h"
 #include "amdgpu_trace.h"
 
+static void amdgpu_job_free_handler(struct work_struct *ws)
+{
+	struct amdgpu_job *job = container_of(ws, struct amdgpu_job, base.work_free_job);
+	amd_sched_job_put(&job->base);
+}
+
+void amdgpu_job_timeout_func(struct work_struct *work)
+{
+	struct amdgpu_job *job = container_of(work, struct amdgpu_job, base.work_tdr.work);
+	DRM_ERROR("ring %s timeout, last signaled seq=%u, last emitted seq=%u\n",
+				job->base.sched->name,
+				(uint32_t)atomic_read(&job->ring->fence_drv.last_seq),
+				job->ring->fence_drv.sync_seq);
+
+	amd_sched_job_put(&job->base);
+}
+
 int amdgpu_job_alloc(struct amdgpu_device *adev, unsigned num_ibs,
-		     struct amdgpu_job **job)
+		     struct amdgpu_job **job, struct amdgpu_vm *vm)
 {
 	size_t size = sizeof(struct amdgpu_job);
 
@@ -43,8 +60,10 @@ int amdgpu_job_alloc(struct amdgpu_devic
 		return -ENOMEM;
 
 	(*job)->adev = adev;
+	(*job)->vm = vm;
 	(*job)->ibs = (void *)&(*job)[1];
 	(*job)->num_ibs = num_ibs;
+	INIT_WORK(&(*job)->base.work_free_job, amdgpu_job_free_handler);
 
 	amdgpu_sync_create(&(*job)->sync);
 
@@ -56,7 +75,7 @@ int amdgpu_job_alloc_with_ib(struct amdg
 {
 	int r;
 
-	r = amdgpu_job_alloc(adev, 1, job);
+	r = amdgpu_job_alloc(adev, 1, job, NULL);
 	if (r)
 		return r;
 
@@ -78,8 +97,16 @@ void amdgpu_job_free(struct amdgpu_job *
 		amdgpu_sa_bo_free(job->adev, &job->ibs[i].sa_bo, f);
 	fence_put(job->fence);
 
-	amdgpu_bo_unref(&job->uf.bo);
+	amdgpu_bo_unref(&job->uf_bo);
 	amdgpu_sync_free(&job->sync);
+
+	if (!job->base.use_sched)
+		kfree(job);
+}
+
+void amdgpu_job_free_func(struct kref *refcount)
+{
+	struct amdgpu_job *job = container_of(refcount, struct amdgpu_job, base.refcount);
 	kfree(job);
 }
 
@@ -87,16 +114,22 @@ int amdgpu_job_submit(struct amdgpu_job
 		      struct amd_sched_entity *entity, void *owner,
 		      struct fence **f)
 {
+	struct fence *fence;
+	int r;
 	job->ring = ring;
-	job->base.sched = &ring->sched;
-	job->base.s_entity = entity;
-	job->base.s_fence = amd_sched_fence_create(job->base.s_entity, owner);
-	if (!job->base.s_fence)
-		return -ENOMEM;
 
-	*f = fence_get(&job->base.s_fence->base);
+	if (!f)
+		return -EINVAL;
+
+	r = amd_sched_job_init(&job->base, &ring->sched,
+			       entity, amdgpu_job_timeout_func,
+			       amdgpu_job_free_func, owner, &fence);
+	if (r)
+		return r;
 
 	job->owner = owner;
+	job->ctx = entity->fence_context;
+	*f = fence_get(fence);
 	amd_sched_entity_push_job(&job->base);
 
 	return 0;
@@ -105,27 +138,19 @@ int amdgpu_job_submit(struct amdgpu_job
 static struct fence *amdgpu_job_dependency(struct amd_sched_job *sched_job)
 {
 	struct amdgpu_job *job = to_amdgpu_job(sched_job);
-	struct amdgpu_vm *vm = job->ibs->vm;
+	struct amdgpu_vm *vm = job->vm;
 
 	struct fence *fence = amdgpu_sync_get_fence(&job->sync);
 
-	if (fence == NULL && vm && !job->ibs->vm_id) {
+	if (fence == NULL && vm && !job->vm_id) {
 		struct amdgpu_ring *ring = job->ring;
-		unsigned i, vm_id;
-		uint64_t vm_pd_addr;
 		int r;
 
 		r = amdgpu_vm_grab_id(vm, ring, &job->sync,
 				      &job->base.s_fence->base,
-				      &vm_id, &vm_pd_addr);
+				      &job->vm_id, &job->vm_pd_addr);
 		if (r)
 			DRM_ERROR("Error getting VM ID (%d)\n", r);
-		else {
-			for (i = 0; i < job->num_ibs; ++i) {
-				job->ibs[i].vm_id = vm_id;
-				job->ibs[i].vm_pd_addr = vm_pd_addr;
-			}
-		}
 
 		fence = amdgpu_sync_get_fence(&job->sync);
 	}
@@ -153,7 +178,7 @@ static struct fence *amdgpu_job_run(stru
 
 	trace_amdgpu_sched_run_job(job);
 	r = amdgpu_ib_schedule(job->ring, job->num_ibs, job->ibs,
-			       job->sync.last_vm_update, &fence);
+			       job->sync.last_vm_update, job, &fence);
 	if (r) {
 		DRM_ERROR("Error scheduling IBs (%d)\n", r);
 		goto err;
@@ -165,7 +190,9 @@ err:
 	return fence;
 }
 
-struct amd_sched_backend_ops amdgpu_sched_ops = {
+const struct amd_sched_backend_ops amdgpu_sched_ops = {
 	.dependency = amdgpu_job_dependency,
 	.run_job = amdgpu_job_run,
+	.begin_job = amd_sched_job_begin,
+	.finish_job = amd_sched_job_finish,
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c	2016-07-24 15:23:50.000000000 -0400
@@ -427,7 +427,6 @@ static int amdgpu_info_ioctl(struct drm_
 	}
 	case AMDGPU_INFO_DEV_INFO: {
 		struct drm_amdgpu_info_device dev_info = {};
-		struct amdgpu_cu_info cu_info;
 
 		dev_info.device_id = dev->pdev->device;
 		dev_info.chip_rev = adev->rev_id;
@@ -448,7 +447,8 @@ static int amdgpu_info_ioctl(struct drm_
 			dev_info.max_memory_clock = adev->pm.default_mclk * 10;
 		}
 		dev_info.enabled_rb_pipes_mask = adev->gfx.config.backend_enable_mask;
-		dev_info.num_rb_pipes = adev->gfx.config.num_rbs;
+		dev_info.num_rb_pipes = adev->gfx.config.max_backends_per_se *
+			adev->gfx.config.max_shader_engines;
 		dev_info.num_hw_gfx_contexts = adev->gfx.config.max_hw_contexts;
 		dev_info._pad = 0;
 		dev_info.ids_flags = 0;
@@ -461,11 +461,11 @@ static int amdgpu_info_ioctl(struct drm_
 					     AMDGPU_GPU_PAGE_SIZE;
 		dev_info.gart_page_size = AMDGPU_GPU_PAGE_SIZE;
 
-		amdgpu_asic_get_cu_info(adev, &cu_info);
-		dev_info.cu_active_number = cu_info.number;
-		dev_info.cu_ao_mask = cu_info.ao_cu_mask;
+		dev_info.cu_active_number = adev->gfx.cu_info.number;
+		dev_info.cu_ao_mask = adev->gfx.cu_info.ao_cu_mask;
 		dev_info.ce_ram_size = adev->gfx.ce_ram_size;
-		memcpy(&dev_info.cu_bitmap[0], &cu_info.bitmap[0], sizeof(cu_info.bitmap));
+		memcpy(&dev_info.cu_bitmap[0], &adev->gfx.cu_info.bitmap[0],
+		       sizeof(adev->gfx.cu_info.bitmap));
 		dev_info.vram_type = adev->mc.vram_type;
 		dev_info.vram_bit_width = adev->mc.vram_width;
 		dev_info.vce_harvest_config = adev->vce.harvest_config;
@@ -755,4 +755,4 @@ const struct drm_ioctl_desc amdgpu_ioctl
 	DRM_IOCTL_DEF_DRV(AMDGPU_GEM_OP, amdgpu_gem_op_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
 	DRM_IOCTL_DEF_DRV(AMDGPU_GEM_USERPTR, amdgpu_gem_userptr_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
 };
-int amdgpu_max_kms_ioctl = ARRAY_SIZE(amdgpu_ioctls_kms);
+const int amdgpu_max_kms_ioctl = ARRAY_SIZE(amdgpu_ioctls_kms);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c	2016-07-24 15:23:50.000000000 -0400
@@ -232,7 +232,10 @@ static struct amdgpu_mn *amdgpu_mn_get(s
 	int r;
 
 	mutex_lock(&adev->mn_lock);
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem)) {
+		mutex_unlock(&adev->mn_lock);
+		return ERR_PTR(-EINTR);
+	}
 
 	hash_for_each_possible(adev->mn_hash, rmn, node, (unsigned long)mm)
 		if (rmn->mm == mm)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h	2016-07-24 15:23:50.000000000 -0400
@@ -283,7 +283,7 @@ struct amdgpu_display_funcs {
 	u32 (*hpd_get_gpio_reg)(struct amdgpu_device *adev);
 	/* pageflipping */
 	void (*page_flip)(struct amdgpu_device *adev,
-			 int crtc_id, u64 crtc_base);
+			  int crtc_id, u64 crtc_base, bool async);
 	int (*page_flip_get_scanoutpos)(struct amdgpu_device *adev, int crtc,
 					u32 *vbl, u32 *position);
 	/* display topology setup */
@@ -530,7 +530,7 @@ struct amdgpu_framebuffer {
 				((em) == ATOM_ENCODER_MODE_DP_MST))
 
 /* Driver internal use only flags of amdgpu_get_crtc_scanoutpos() */
-#define USE_REAL_VBLANKSTART 		(1 << 30)
+#define USE_REAL_VBLANKSTART		(1 << 30)
 #define GET_DISTANCE_TO_VBLANKSTART	(1 << 31)
 
 void amdgpu_link_encoder_connector(struct drm_device *dev);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h	2016-07-24 15:23:50.000000000 -0400
@@ -71,7 +71,7 @@ static inline int amdgpu_bo_reserve(stru
 {
 	int r;
 
-	r = ttm_bo_reserve(&bo->tbo, !no_intr, false, false, 0);
+	r = ttm_bo_reserve(&bo->tbo, !no_intr, false, NULL);
 	if (unlikely(r != 0)) {
 		if (r != -ERESTARTSYS)
 			dev_err(bo->adev->dev, "%p reserve failed\n", bo);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c	2016-07-24 15:23:50.000000000 -0400
@@ -270,30 +270,28 @@ static ssize_t amdgpu_set_pp_force_state
 	struct drm_device *ddev = dev_get_drvdata(dev);
 	struct amdgpu_device *adev = ddev->dev_private;
 	enum amd_pm_state_type state = 0;
-	long idx;
+	unsigned long idx;
 	int ret;
 
 	if (strlen(buf) == 1)
 		adev->pp_force_state_enabled = false;
-	else {
-		ret = kstrtol(buf, 0, &idx);
+	else if (adev->pp_enabled) {
+		struct pp_states_info data;
 
-		if (ret) {
+		ret = kstrtoul(buf, 0, &idx);
+		if (ret || idx >= ARRAY_SIZE(data.states)) {
 			count = -EINVAL;
 			goto fail;
 		}
 
-		if (adev->pp_enabled) {
-			struct pp_states_info data;
-			amdgpu_dpm_get_pp_num_states(adev, &data);
-			state = data.states[idx];
-			/* only set user selected power states */
-			if (state != POWER_STATE_TYPE_INTERNAL_BOOT &&
-				state != POWER_STATE_TYPE_DEFAULT) {
-				amdgpu_dpm_dispatch_task(adev,
-						AMD_PP_EVENT_ENABLE_USER_STATE, &state, NULL);
-				adev->pp_force_state_enabled = true;
-			}
+		amdgpu_dpm_get_pp_num_states(adev, &data);
+		state = data.states[idx];
+		/* only set user selected power states */
+		if (state != POWER_STATE_TYPE_INTERNAL_BOOT &&
+		    state != POWER_STATE_TYPE_DEFAULT) {
+			amdgpu_dpm_dispatch_task(adev,
+					AMD_PP_EVENT_ENABLE_USER_STATE, &state, NULL);
+			adev->pp_force_state_enabled = true;
 		}
 	}
 fail:
@@ -362,16 +360,23 @@ static ssize_t amdgpu_set_pp_dpm_sclk(st
 	struct amdgpu_device *adev = ddev->dev_private;
 	int ret;
 	long level;
+	uint32_t i, mask = 0;
+	char sub_str[2];
 
-	ret = kstrtol(buf, 0, &level);
+	for (i = 0; i < strlen(buf) - 1; i++) {
+		sub_str[0] = *(buf + i);
+		sub_str[1] = '\0';
+		ret = kstrtol(sub_str, 0, &level);
 
-	if (ret) {
-		count = -EINVAL;
-		goto fail;
+		if (ret) {
+			count = -EINVAL;
+			goto fail;
+		}
+		mask |= 1 << level;
 	}
 
 	if (adev->pp_enabled)
-		amdgpu_dpm_force_clock_level(adev, PP_SCLK, level);
+		amdgpu_dpm_force_clock_level(adev, PP_SCLK, mask);
 fail:
 	return count;
 }
@@ -399,16 +404,23 @@ static ssize_t amdgpu_set_pp_dpm_mclk(st
 	struct amdgpu_device *adev = ddev->dev_private;
 	int ret;
 	long level;
+	uint32_t i, mask = 0;
+	char sub_str[2];
 
-	ret = kstrtol(buf, 0, &level);
+	for (i = 0; i < strlen(buf) - 1; i++) {
+		sub_str[0] = *(buf + i);
+		sub_str[1] = '\0';
+		ret = kstrtol(sub_str, 0, &level);
 
-	if (ret) {
-		count = -EINVAL;
-		goto fail;
+		if (ret) {
+			count = -EINVAL;
+			goto fail;
+		}
+		mask |= 1 << level;
 	}
 
 	if (adev->pp_enabled)
-		amdgpu_dpm_force_clock_level(adev, PP_MCLK, level);
+		amdgpu_dpm_force_clock_level(adev, PP_MCLK, mask);
 fail:
 	return count;
 }
@@ -436,16 +448,23 @@ static ssize_t amdgpu_set_pp_dpm_pcie(st
 	struct amdgpu_device *adev = ddev->dev_private;
 	int ret;
 	long level;
+	uint32_t i, mask = 0;
+	char sub_str[2];
 
-	ret = kstrtol(buf, 0, &level);
+	for (i = 0; i < strlen(buf) - 1; i++) {
+		sub_str[0] = *(buf + i);
+		sub_str[1] = '\0';
+		ret = kstrtol(sub_str, 0, &level);
 
-	if (ret) {
-		count = -EINVAL;
-		goto fail;
+		if (ret) {
+			count = -EINVAL;
+			goto fail;
+		}
+		mask |= 1 << level;
 	}
 
 	if (adev->pp_enabled)
-		amdgpu_dpm_force_clock_level(adev, PP_PCIE, level);
+		amdgpu_dpm_force_clock_level(adev, PP_PCIE, mask);
 fail:
 	return count;
 }
@@ -1212,7 +1231,7 @@ static int amdgpu_debugfs_pm_info(struct
 	return 0;
 }
 
-static struct drm_info_list amdgpu_pm_info_list[] = {
+static const struct drm_info_list amdgpu_pm_info_list[] = {
 	{"amdgpu_pm_info", amdgpu_debugfs_pm_info, 0, NULL},
 };
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c	2016-07-24 15:23:50.000000000 -0400
@@ -99,6 +99,10 @@ static int amdgpu_pp_early_init(void *ha
 
 #ifdef CONFIG_DRM_AMD_POWERPLAY
 	switch (adev->asic_type) {
+	case CHIP_POLARIS11:
+	case CHIP_POLARIS10:
+		adev->pp_enabled = true;
+		break;
 	case CHIP_TONGA:
 	case CHIP_FIJI:
 		adev->pp_enabled = (amdgpu_powerplay == 0) ? false : true;
@@ -179,13 +183,6 @@ static int amdgpu_pp_sw_fini(void *handl
 	if (ret)
 		return ret;
 
-#ifdef CONFIG_DRM_AMD_POWERPLAY
-	if (adev->pp_enabled) {
-		amdgpu_pm_sysfs_fini(adev);
-		amd_powerplay_fini(adev->powerplay.pp_handle);
-	}
-#endif
-
 	return ret;
 }
 
@@ -219,6 +216,22 @@ static int amdgpu_pp_hw_fini(void *handl
 	return ret;
 }
 
+static void amdgpu_pp_late_fini(void *handle)
+{
+#ifdef CONFIG_DRM_AMD_POWERPLAY
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+	if (adev->pp_enabled) {
+		amdgpu_pm_sysfs_fini(adev);
+		amd_powerplay_fini(adev->powerplay.pp_handle);
+	}
+
+	if (adev->powerplay.ip_funcs->late_fini)
+		adev->powerplay.ip_funcs->late_fini(
+			  adev->powerplay.pp_handle);
+#endif
+}
+
 static int amdgpu_pp_suspend(void *handle)
 {
 	int ret = 0;
@@ -299,28 +312,20 @@ static int amdgpu_pp_soft_reset(void *ha
 	return ret;
 }
 
-static void amdgpu_pp_print_status(void *handle)
-{
-	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-	if (adev->powerplay.ip_funcs->print_status)
-		adev->powerplay.ip_funcs->print_status(
-					adev->powerplay.pp_handle);
-}
-
 const struct amd_ip_funcs amdgpu_pp_ip_funcs = {
+	.name = "amdgpu_powerplay",
 	.early_init = amdgpu_pp_early_init,
 	.late_init = amdgpu_pp_late_init,
 	.sw_init = amdgpu_pp_sw_init,
 	.sw_fini = amdgpu_pp_sw_fini,
 	.hw_init = amdgpu_pp_hw_init,
 	.hw_fini = amdgpu_pp_hw_fini,
+	.late_fini = amdgpu_pp_late_fini,
 	.suspend = amdgpu_pp_suspend,
 	.resume = amdgpu_pp_resume,
 	.is_idle = amdgpu_pp_is_idle,
 	.wait_for_idle = amdgpu_pp_wait_for_idle,
 	.soft_reset = amdgpu_pp_soft_reset,
-	.print_status = amdgpu_pp_print_status,
 	.set_clockgating_state = amdgpu_pp_set_clockgating_state,
 	.set_powergating_state = amdgpu_pp_set_powergating_state,
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c	2016-07-24 15:23:50.000000000 -0400
@@ -57,9 +57,10 @@ void amdgpu_gem_prime_vunmap(struct drm_
 	ttm_bo_kunmap(&bo->dma_buf_vmap);
 }
 
-struct drm_gem_object *amdgpu_gem_prime_import_sg_table(struct drm_device *dev,
-							struct dma_buf_attachment *attach,
-							struct sg_table *sg)
+struct drm_gem_object *
+amdgpu_gem_prime_import_sg_table(struct drm_device *dev,
+				 struct dma_buf_attachment *attach,
+				 struct sg_table *sg)
 {
 	struct reservation_object *resv = attach->dmabuf->resv;
 	struct amdgpu_device *adev = dev->dev_private;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c	2016-07-24 15:23:50.000000000 -0400
@@ -46,7 +46,8 @@
  * wptr.  The GPU then starts fetching commands and executes
  * them until the pointers are equal again.
  */
-static int amdgpu_debugfs_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring);
+static int amdgpu_debugfs_ring_init(struct amdgpu_device *adev,
+				    struct amdgpu_ring *ring);
 
 /**
  * amdgpu_ring_alloc - allocate space on the ring buffer
@@ -215,18 +216,17 @@ int amdgpu_ring_restore(struct amdgpu_ri
  *
  * @adev: amdgpu_device pointer
  * @ring: amdgpu_ring structure holding ring information
- * @ring_size: size of the ring
+ * @max_ndw: maximum number of dw for ring alloc
  * @nop: nop packet for this ring
  *
  * Initialize the driver information for the selected ring (all asics).
  * Returns 0 on success, error on failure.
  */
 int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
-		     unsigned ring_size, u32 nop, u32 align_mask,
+		     unsigned max_dw, u32 nop, u32 align_mask,
 		     struct amdgpu_irq_src *irq_src, unsigned irq_type,
 		     enum amdgpu_ring_type ring_type)
 {
-	u32 rb_bufsz;
 	int r;
 
 	if (ring->adev == NULL) {
@@ -265,8 +265,17 @@ int amdgpu_ring_init(struct amdgpu_devic
 		dev_err(adev->dev, "(%d) ring next_rptr wb alloc failed\n", r);
 		return r;
 	}
-	ring->next_rptr_gpu_addr = adev->wb.gpu_addr + (ring->next_rptr_offs * 4);
+	ring->next_rptr_gpu_addr = adev->wb.gpu_addr + ring->next_rptr_offs * 4;
 	ring->next_rptr_cpu_addr = &adev->wb.wb[ring->next_rptr_offs];
+
+	r = amdgpu_wb_get(adev, &ring->cond_exe_offs);
+	if (r) {
+		dev_err(adev->dev, "(%d) ring cond_exec_polling wb alloc failed\n", r);
+		return r;
+	}
+	ring->cond_exe_gpu_addr = adev->wb.gpu_addr + (ring->cond_exe_offs * 4);
+	ring->cond_exe_cpu_addr = &adev->wb.wb[ring->cond_exe_offs];
+
 	spin_lock_init(&ring->fence_lock);
 	r = amdgpu_fence_driver_start_ring(ring, irq_src, irq_type);
 	if (r) {
@@ -274,10 +283,8 @@ int amdgpu_ring_init(struct amdgpu_devic
 		return r;
 	}
 
-	/* Align ring size */
-	rb_bufsz = order_base_2(ring_size / 8);
-	ring_size = (1 << (rb_bufsz + 1)) * 4;
-	ring->ring_size = ring_size;
+	ring->ring_size = roundup_pow_of_two(max_dw * 4 *
+					     amdgpu_sched_hw_submission);
 	ring->align_mask = align_mask;
 	ring->nop = nop;
 	ring->type = ring_type;
@@ -310,8 +317,7 @@ int amdgpu_ring_init(struct amdgpu_devic
 		}
 	}
 	ring->ptr_mask = (ring->ring_size / 4) - 1;
-	ring->max_dw = DIV_ROUND_UP(ring->ring_size / 4,
-				    amdgpu_sched_hw_submission);
+	ring->max_dw = max_dw;
 
 	if (amdgpu_debugfs_ring_init(adev, ring)) {
 		DRM_ERROR("Failed to register debugfs file for rings !\n");
@@ -337,6 +343,7 @@ void amdgpu_ring_fini(struct amdgpu_ring
 	ring->ring = NULL;
 	ring->ring_obj = NULL;
 
+	amdgpu_wb_free(ring->adev, ring->cond_exe_offs);
 	amdgpu_wb_free(ring->adev, ring->fence_offs);
 	amdgpu_wb_free(ring->adev, ring->rptr_offs);
 	amdgpu_wb_free(ring->adev, ring->wptr_offs);
@@ -363,9 +370,8 @@ static int amdgpu_debugfs_ring_info(stru
 	struct drm_info_node *node = (struct drm_info_node *) m->private;
 	struct drm_device *dev = node->minor->dev;
 	struct amdgpu_device *adev = dev->dev_private;
-	int roffset = *(int*)node->info_ent->data;
+	int roffset = (unsigned long)node->info_ent->data;
 	struct amdgpu_ring *ring = (void *)(((uint8_t*)adev) + roffset);
-
 	uint32_t rptr, wptr, rptr_next;
 	unsigned i;
 
@@ -408,46 +414,37 @@ static int amdgpu_debugfs_ring_info(stru
 	return 0;
 }
 
-/* TODO: clean this up !*/
-static int amdgpu_gfx_index = offsetof(struct amdgpu_device, gfx.gfx_ring[0]);
-static int cayman_cp1_index = offsetof(struct amdgpu_device, gfx.compute_ring[0]);
-static int cayman_cp2_index = offsetof(struct amdgpu_device, gfx.compute_ring[1]);
-static int amdgpu_dma1_index = offsetof(struct amdgpu_device, sdma.instance[0].ring);
-static int amdgpu_dma2_index = offsetof(struct amdgpu_device, sdma.instance[1].ring);
-static int r600_uvd_index = offsetof(struct amdgpu_device, uvd.ring);
-static int si_vce1_index = offsetof(struct amdgpu_device, vce.ring[0]);
-static int si_vce2_index = offsetof(struct amdgpu_device, vce.ring[1]);
-
-static struct drm_info_list amdgpu_debugfs_ring_info_list[] = {
-	{"amdgpu_ring_gfx", amdgpu_debugfs_ring_info, 0, &amdgpu_gfx_index},
-	{"amdgpu_ring_cp1", amdgpu_debugfs_ring_info, 0, &cayman_cp1_index},
-	{"amdgpu_ring_cp2", amdgpu_debugfs_ring_info, 0, &cayman_cp2_index},
-	{"amdgpu_ring_dma1", amdgpu_debugfs_ring_info, 0, &amdgpu_dma1_index},
-	{"amdgpu_ring_dma2", amdgpu_debugfs_ring_info, 0, &amdgpu_dma2_index},
-	{"amdgpu_ring_uvd", amdgpu_debugfs_ring_info, 0, &r600_uvd_index},
-	{"amdgpu_ring_vce1", amdgpu_debugfs_ring_info, 0, &si_vce1_index},
-	{"amdgpu_ring_vce2", amdgpu_debugfs_ring_info, 0, &si_vce2_index},
-};
+static struct drm_info_list amdgpu_debugfs_ring_info_list[AMDGPU_MAX_RINGS];
+static char amdgpu_debugfs_ring_names[AMDGPU_MAX_RINGS][32];
 
 #endif
 
-static int amdgpu_debugfs_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring)
+static int amdgpu_debugfs_ring_init(struct amdgpu_device *adev,
+				    struct amdgpu_ring *ring)
 {
 #if defined(CONFIG_DEBUG_FS)
+	unsigned offset = (uint8_t*)ring - (uint8_t*)adev;
 	unsigned i;
+	struct drm_info_list *info;
+	char *name;
+
 	for (i = 0; i < ARRAY_SIZE(amdgpu_debugfs_ring_info_list); ++i) {
-		struct drm_info_list *info = &amdgpu_debugfs_ring_info_list[i];
-		int roffset = *(int*)amdgpu_debugfs_ring_info_list[i].data;
-		struct amdgpu_ring *other = (void *)(((uint8_t*)adev) + roffset);
-		unsigned r;
+		info = &amdgpu_debugfs_ring_info_list[i];
+		if (!info->data)
+			break;
+	}
 
-		if (other != ring)
-			continue;
+	if (i == ARRAY_SIZE(amdgpu_debugfs_ring_info_list))
+		return -ENOSPC;
 
-		r = amdgpu_debugfs_add_files(adev, info, 1);
-		if (r)
-			return r;
-	}
+	name = &amdgpu_debugfs_ring_names[i][0];
+	sprintf(name, "amdgpu_ring_%s", ring->name);
+	info->name = name;
+	info->show = amdgpu_debugfs_ring_info;
+	info->driver_features = 0;
+	info->data = (void*)(uintptr_t)offset;
+
+	return amdgpu_debugfs_add_files(adev, info, 1);
 #endif
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c	2016-07-24 15:23:50.000000000 -0400
@@ -115,6 +115,7 @@ int amdgpu_sa_bo_manager_start(struct am
 		return r;
 	}
 	r = amdgpu_bo_kmap(sa_manager->bo, &sa_manager->cpu_ptr);
+	memset(sa_manager->cpu_ptr, 0, sa_manager->size);
 	amdgpu_bo_unreserve(sa_manager->bo);
 	return r;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c	2016-07-24 15:23:50.000000000 -0400
@@ -109,6 +109,29 @@ static void amdgpu_sync_keep_later(struc
 }
 
 /**
+ * amdgpu_sync_add_later - add the fence to the hash
+ *
+ * @sync: sync object to add the fence to
+ * @f: fence to add
+ *
+ * Tries to add the fence to an existing hash entry. Returns true when an entry
+ * was found, false otherwise.
+ */
+static bool amdgpu_sync_add_later(struct amdgpu_sync *sync, struct fence *f)
+{
+	struct amdgpu_sync_entry *e;
+
+	hash_for_each_possible(sync->fences, e, node, f->context) {
+		if (unlikely(e->fence->context != f->context))
+			continue;
+
+		amdgpu_sync_keep_later(&e->fence, f);
+		return true;
+	}
+	return false;
+}
+
+/**
  * amdgpu_sync_fence - remember to sync to this fence
  *
  * @sync: sync object to add fence to
@@ -127,13 +150,8 @@ int amdgpu_sync_fence(struct amdgpu_devi
 	    amdgpu_sync_get_owner(f) == AMDGPU_FENCE_OWNER_VM)
 		amdgpu_sync_keep_later(&sync->last_vm_update, f);
 
-	hash_for_each_possible(sync->fences, e, node, f->context) {
-		if (unlikely(e->fence->context != f->context))
-			continue;
-
-		amdgpu_sync_keep_later(&e->fence, f);
+	if (amdgpu_sync_add_later(sync, f))
 		return 0;
-	}
 
 	e = kmem_cache_alloc(amdgpu_sync_slab, GFP_KERNEL);
 	if (!e)
@@ -204,6 +222,81 @@ int amdgpu_sync_resv(struct amdgpu_devic
 	return r;
 }
 
+/**
+ * amdgpu_sync_is_idle - test if all fences are signaled
+ *
+ * @sync: the sync object
+ *
+ * Returns true if all fences in the sync object are signaled.
+ */
+bool amdgpu_sync_is_idle(struct amdgpu_sync *sync)
+{
+	struct amdgpu_sync_entry *e;
+	struct hlist_node *tmp;
+	int i;
+
+	hash_for_each_safe(sync->fences, i, tmp, e, node) {
+		struct fence *f = e->fence;
+
+		if (fence_is_signaled(f)) {
+			hash_del(&e->node);
+			fence_put(f);
+			kmem_cache_free(amdgpu_sync_slab, e);
+			continue;
+		}
+
+		return false;
+	}
+
+	return true;
+}
+
+/**
+ * amdgpu_sync_cycle_fences - move fences from one sync object into another
+ *
+ * @dst: the destination sync object
+ * @src: the source sync object
+ * @fence: fence to add to source
+ *
+ * Remove all fences from source and put them into destination and add
+ * fence as new one into source.
+ */
+int amdgpu_sync_cycle_fences(struct amdgpu_sync *dst, struct amdgpu_sync *src,
+			     struct fence *fence)
+{
+	struct amdgpu_sync_entry *e, *newone;
+	struct hlist_node *tmp;
+	int i;
+
+	/* Allocate the new entry before moving the old ones */
+	newone = kmem_cache_alloc(amdgpu_sync_slab, GFP_KERNEL);
+	if (!newone)
+		return -ENOMEM;
+
+	hash_for_each_safe(src->fences, i, tmp, e, node) {
+		struct fence *f = e->fence;
+
+		hash_del(&e->node);
+		if (fence_is_signaled(f)) {
+			fence_put(f);
+			kmem_cache_free(amdgpu_sync_slab, e);
+			continue;
+		}
+
+		if (amdgpu_sync_add_later(dst, f)) {
+			kmem_cache_free(amdgpu_sync_slab, e);
+			continue;
+		}
+
+		hash_add(dst->fences, &e->node, f->context);
+	}
+
+	hash_add(src->fences, &newone->node, fence->context);
+	newone->fence = fence_get(fence);
+
+	return 0;
+}
+
 struct fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync)
 {
 	struct amdgpu_sync_entry *e;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c	2016-07-24 15:23:50.000000000 -0400
@@ -911,6 +911,52 @@ uint32_t amdgpu_ttm_tt_pte_flags(struct
 	return flags;
 }
 
+static void amdgpu_ttm_lru_removal(struct ttm_buffer_object *tbo)
+{
+	struct amdgpu_device *adev = amdgpu_get_adev(tbo->bdev);
+	unsigned i, j;
+
+	for (i = 0; i < AMDGPU_TTM_LRU_SIZE; ++i) {
+		struct amdgpu_mman_lru *lru = &adev->mman.log2_size[i];
+
+		for (j = 0; j < TTM_NUM_MEM_TYPES; ++j)
+			if (&tbo->lru == lru->lru[j])
+				lru->lru[j] = tbo->lru.prev;
+
+		if (&tbo->swap == lru->swap_lru)
+			lru->swap_lru = tbo->swap.prev;
+	}
+}
+
+static struct amdgpu_mman_lru *amdgpu_ttm_lru(struct ttm_buffer_object *tbo)
+{
+	struct amdgpu_device *adev = amdgpu_get_adev(tbo->bdev);
+	unsigned log2_size = min(ilog2(tbo->num_pages),
+				 AMDGPU_TTM_LRU_SIZE - 1);
+
+	return &adev->mman.log2_size[log2_size];
+}
+
+static struct list_head *amdgpu_ttm_lru_tail(struct ttm_buffer_object *tbo)
+{
+	struct amdgpu_mman_lru *lru = amdgpu_ttm_lru(tbo);
+	struct list_head *res = lru->lru[tbo->mem.mem_type];
+
+	lru->lru[tbo->mem.mem_type] = &tbo->lru;
+
+	return res;
+}
+
+static struct list_head *amdgpu_ttm_swap_lru_tail(struct ttm_buffer_object *tbo)
+{
+	struct amdgpu_mman_lru *lru = amdgpu_ttm_lru(tbo);
+	struct list_head *res = lru->swap_lru;
+
+	lru->swap_lru = &tbo->swap;
+
+	return res;
+}
+
 static struct ttm_bo_driver amdgpu_bo_driver = {
 	.ttm_tt_create = &amdgpu_ttm_tt_create,
 	.ttm_tt_populate = &amdgpu_ttm_tt_populate,
@@ -924,10 +970,14 @@ static struct ttm_bo_driver amdgpu_bo_dr
 	.fault_reserve_notify = &amdgpu_bo_fault_reserve_notify,
 	.io_mem_reserve = &amdgpu_ttm_io_mem_reserve,
 	.io_mem_free = &amdgpu_ttm_io_mem_free,
+	.lru_removal = &amdgpu_ttm_lru_removal,
+	.lru_tail = &amdgpu_ttm_lru_tail,
+	.swap_lru_tail = &amdgpu_ttm_swap_lru_tail,
 };
 
 int amdgpu_ttm_init(struct amdgpu_device *adev)
 {
+	unsigned i, j;
 	int r;
 
 	r = amdgpu_ttm_global_init(adev);
@@ -945,6 +995,15 @@ int amdgpu_ttm_init(struct amdgpu_device
 		DRM_ERROR("failed initializing buffer object driver(%d).\n", r);
 		return r;
 	}
+
+	for (i = 0; i < AMDGPU_TTM_LRU_SIZE; ++i) {
+		struct amdgpu_mman_lru *lru = &adev->mman.log2_size[i];
+
+		for (j = 0; j < TTM_NUM_MEM_TYPES; ++j)
+			lru->lru[j] = &adev->mman.bdev.man[j].lru;
+		lru->swap_lru = &adev->mman.bdev.glob->swap_lru;
+	}
+
 	adev->mman.initialized = true;
 	r = ttm_bo_init_mm(&adev->mman.bdev, TTM_PL_VRAM,
 				adev->mc.real_vram_size >> PAGE_SHIFT);
@@ -1167,7 +1226,7 @@ static int amdgpu_mm_dump_table(struct s
 static int ttm_pl_vram = TTM_PL_VRAM;
 static int ttm_pl_tt = TTM_PL_TT;
 
-static struct drm_info_list amdgpu_ttm_debugfs_list[] = {
+static const struct drm_info_list amdgpu_ttm_debugfs_list[] = {
 	{"amdgpu_vram_mm", amdgpu_mm_dump_table, 0, &ttm_pl_vram},
 	{"amdgpu_gtt_mm", amdgpu_mm_dump_table, 0, &ttm_pl_tt},
 	{"ttm_page_pool", ttm_page_alloc_debugfs, 0, NULL},
@@ -1218,6 +1277,8 @@ static const struct file_operations amdg
 	.llseek = default_llseek
 };
 
+#ifdef CONFIG_DRM_AMDGPU_GART_DEBUGFS
+
 static ssize_t amdgpu_ttm_gtt_read(struct file *f, char __user *buf,
 				   size_t size, loff_t *pos)
 {
@@ -1265,6 +1326,8 @@ static const struct file_operations amdg
 
 #endif
 
+#endif
+
 static int amdgpu_ttm_debugfs_init(struct amdgpu_device *adev)
 {
 #if defined(CONFIG_DEBUG_FS)
@@ -1280,6 +1343,7 @@ static int amdgpu_ttm_debugfs_init(struc
 	i_size_write(ent->d_inode, adev->mc.mc_vram_size);
 	adev->mman.vram = ent;
 
+#ifdef CONFIG_DRM_AMDGPU_GART_DEBUGFS
 	ent = debugfs_create_file("amdgpu_gtt", S_IFREG | S_IRUGO, root,
 				  adev, &amdgpu_ttm_gtt_fops);
 	if (IS_ERR(ent))
@@ -1287,6 +1351,7 @@ static int amdgpu_ttm_debugfs_init(struc
 	i_size_write(ent->d_inode, adev->mc.gtt_size);
 	adev->mman.gtt = ent;
 
+#endif
 	count = ARRAY_SIZE(amdgpu_ttm_debugfs_list);
 
 #ifdef CONFIG_SWIOTLB
@@ -1308,7 +1373,10 @@ static void amdgpu_ttm_debugfs_fini(stru
 	debugfs_remove(adev->mman.vram);
 	adev->mman.vram = NULL;
 
+#ifdef CONFIG_DRM_AMDGPU_GART_DEBUGFS
 	debugfs_remove(adev->mman.gtt);
 	adev->mman.gtt = NULL;
 #endif
+
+#endif
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c	2016-05-15 19:20:18.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c	2016-07-24 18:16:31.000000000 -0400
@@ -41,19 +41,23 @@
 
 /* 1 second timeout */
 #define UVD_IDLE_TIMEOUT_MS	1000
+/* Polaris10/11 firmware version */
+#define FW_1_66_16 ((1 << 24) | (66 << 16) | (16 << 8))
 
 /* Firmware Names */
 #ifdef CONFIG_DRM_AMDGPU_CIK
 #define FIRMWARE_BONAIRE	"/*(DEBLOBBED)*/"
-#define FIRMWARE_KABINI 	"/*(DEBLOBBED)*/"
-#define FIRMWARE_KAVERI 	"/*(DEBLOBBED)*/"
-#define FIRMWARE_HAWAII 	"/*(DEBLOBBED)*/"
+#define FIRMWARE_KABINI	"/*(DEBLOBBED)*/"
+#define FIRMWARE_KAVERI	"/*(DEBLOBBED)*/"
+#define FIRMWARE_HAWAII	"/*(DEBLOBBED)*/"
 #define FIRMWARE_MULLINS	"/*(DEBLOBBED)*/"
 #endif
 #define FIRMWARE_TONGA		"/*(DEBLOBBED)*/"
 #define FIRMWARE_CARRIZO	"/*(DEBLOBBED)*/"
 #define FIRMWARE_FIJI		"/*(DEBLOBBED)*/"
 #define FIRMWARE_STONEY		"/*(DEBLOBBED)*/"
+#define FIRMWARE_POLARIS10	"/*(DEBLOBBED)*/"
+#define FIRMWARE_POLARIS11	"/*(DEBLOBBED)*/"
 
 /**
  * amdgpu_uvd_cs_ctx - Command submission parser context
@@ -124,6 +128,12 @@ int amdgpu_uvd_sw_init(struct amdgpu_dev
 	case CHIP_STONEY:
 		fw_name = FIRMWARE_STONEY;
 		break;
+	case CHIP_POLARIS10:
+		fw_name = FIRMWARE_POLARIS10;
+		break;
+	case CHIP_POLARIS11:
+		fw_name = FIRMWARE_POLARIS11;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -144,6 +154,9 @@ int amdgpu_uvd_sw_init(struct amdgpu_dev
 		return r;
 	}
 
+	/* Set the default UVD handles that the firmware can handle */
+	adev->uvd.max_handles = AMDGPU_DEFAULT_UVD_HANDLES;
+
 	hdr = (const struct common_firmware_header *)adev->uvd.fw->data;
 	family_id = le32_to_cpu(hdr->ucode_version) & 0xff;
 	version_major = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xff;
@@ -151,11 +164,28 @@ int amdgpu_uvd_sw_init(struct amdgpu_dev
 	DRM_INFO("Found UVD firmware Version: %hu.%hu Family ID: %hu\n",
 		version_major, version_minor, family_id);
 
+	/*
+	 * Limit the number of UVD handles depending on microcode major
+	 * and minor versions. The firmware version which has 40 UVD
+	 * instances support is 1.80. So all subsequent versions should
+	 * also have the same support.
+	 */
+	if ((version_major > 0x01) ||
+	    ((version_major == 0x01) && (version_minor >= 0x50)))
+		adev->uvd.max_handles = AMDGPU_MAX_UVD_HANDLES;
+
 	adev->uvd.fw_version = ((version_major << 24) | (version_minor << 16) |
 				(family_id << 8));
 
+	if ((adev->asic_type == CHIP_POLARIS10 ||
+	     adev->asic_type == CHIP_POLARIS11) &&
+	    (adev->uvd.fw_version < FW_1_66_16))
+		DRM_ERROR("POLARIS10/11 UVD firmware version %hu.%hu is too old.\n",
+			  version_major, version_minor);
+
 	bo_size = AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8)
-		 +  AMDGPU_UVD_STACK_SIZE + AMDGPU_UVD_HEAP_SIZE;
+		  +  AMDGPU_UVD_STACK_SIZE + AMDGPU_UVD_HEAP_SIZE
+		  +  AMDGPU_UVD_SESSION_SIZE * adev->uvd.max_handles;
 	r = amdgpu_bo_create(adev, bo_size, PAGE_SIZE, true,
 			     AMDGPU_GEM_DOMAIN_VRAM,
 			     AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
@@ -198,7 +228,7 @@ int amdgpu_uvd_sw_init(struct amdgpu_dev
 		return r;
 	}
 
-	for (i = 0; i < AMDGPU_MAX_UVD_HANDLES; ++i) {
+	for (i = 0; i < adev->uvd.max_handles; ++i) {
 		atomic_set(&adev->uvd.handles[i], 0);
 		adev->uvd.filp[i] = NULL;
 	}
@@ -214,19 +244,20 @@ int amdgpu_uvd_sw_fini(struct amdgpu_dev
 {
 	int r;
 
-	if (adev->uvd.vcpu_bo == NULL)
-		return 0;
+	kfree(adev->uvd.saved_bo);
 
 	amd_sched_entity_fini(&adev->uvd.ring.sched, &adev->uvd.entity);
 
-	r = amdgpu_bo_reserve(adev->uvd.vcpu_bo, false);
-	if (!r) {
-		amdgpu_bo_kunmap(adev->uvd.vcpu_bo);
-		amdgpu_bo_unpin(adev->uvd.vcpu_bo);
-		amdgpu_bo_unreserve(adev->uvd.vcpu_bo);
-	}
+	if (adev->uvd.vcpu_bo) {
+		r = amdgpu_bo_reserve(adev->uvd.vcpu_bo, false);
+		if (!r) {
+			amdgpu_bo_kunmap(adev->uvd.vcpu_bo);
+			amdgpu_bo_unpin(adev->uvd.vcpu_bo);
+			amdgpu_bo_unreserve(adev->uvd.vcpu_bo);
+		}
 
-	amdgpu_bo_unref(&adev->uvd.vcpu_bo);
+		amdgpu_bo_unref(&adev->uvd.vcpu_bo);
+	}
 
 	amdgpu_ring_fini(&adev->uvd.ring);
 
@@ -244,7 +275,7 @@ int amdgpu_uvd_suspend(struct amdgpu_dev
 	if (adev->uvd.vcpu_bo == NULL)
 		return 0;
 
-	for (i = 0; i < AMDGPU_MAX_UVD_HANDLES; ++i)
+	for (i = 0; i < adev->uvd.max_handles; ++i)
 		if (atomic_read(&adev->uvd.handles[i]))
 			break;
 
@@ -301,7 +332,7 @@ void amdgpu_uvd_free_handles(struct amdg
 	struct amdgpu_ring *ring = &adev->uvd.ring;
 	int i, r;
 
-	for (i = 0; i < AMDGPU_MAX_UVD_HANDLES; ++i) {
+	for (i = 0; i < adev->uvd.max_handles; ++i) {
 		uint32_t handle = atomic_read(&adev->uvd.handles[i]);
 		if (handle != 0 && adev->uvd.filp[i] == filp) {
 			struct fence *fence;
@@ -383,7 +414,8 @@ static int amdgpu_uvd_cs_pass1(struct am
  *
  * Peek into the decode message and calculate the necessary buffer sizes.
  */
-static int amdgpu_uvd_cs_msg_decode(uint32_t *msg, unsigned buf_sizes[])
+static int amdgpu_uvd_cs_msg_decode(struct amdgpu_device *adev, uint32_t *msg,
+	unsigned buf_sizes[])
 {
 	unsigned stream_type = msg[4];
 	unsigned width = msg[6];
@@ -405,7 +437,6 @@ static int amdgpu_uvd_cs_msg_decode(uint
 
 	switch (stream_type) {
 	case 0: /* H264 */
-	case 7: /* H264 Perf */
 		switch(level) {
 		case 30:
 			num_dpb_buffer = 8100 / fs_in_mb;
@@ -483,6 +514,54 @@ static int amdgpu_uvd_cs_msg_decode(uint
 		min_dpb_size += ALIGN(width_in_mb * height_in_mb * 32, 64);
 		break;
 
+	case 7: /* H264 Perf */
+		switch(level) {
+		case 30:
+			num_dpb_buffer = 8100 / fs_in_mb;
+			break;
+		case 31:
+			num_dpb_buffer = 18000 / fs_in_mb;
+			break;
+		case 32:
+			num_dpb_buffer = 20480 / fs_in_mb;
+			break;
+		case 41:
+			num_dpb_buffer = 32768 / fs_in_mb;
+			break;
+		case 42:
+			num_dpb_buffer = 34816 / fs_in_mb;
+			break;
+		case 50:
+			num_dpb_buffer = 110400 / fs_in_mb;
+			break;
+		case 51:
+			num_dpb_buffer = 184320 / fs_in_mb;
+			break;
+		default:
+			num_dpb_buffer = 184320 / fs_in_mb;
+			break;
+		}
+		num_dpb_buffer++;
+		if (num_dpb_buffer > 17)
+			num_dpb_buffer = 17;
+
+		/* reference picture buffer */
+		min_dpb_size = image_size * num_dpb_buffer;
+
+		if (adev->asic_type < CHIP_POLARIS10){
+			/* macroblock context buffer */
+			min_dpb_size +=
+				width_in_mb * height_in_mb * num_dpb_buffer * 192;
+
+			/* IT surface buffer */
+			min_dpb_size += width_in_mb * height_in_mb * 32;
+		} else {
+			/* macroblock context buffer */
+			min_ctx_size =
+				width_in_mb * height_in_mb * num_dpb_buffer * 192;
+		}
+		break;
+
 	case 16: /* H265 */
 		image_size = (ALIGN(width, 16) * ALIGN(height, 16) * 3) / 2;
 		image_size = ALIGN(image_size, 256);
@@ -561,7 +640,7 @@ static int amdgpu_uvd_cs_msg(struct amdg
 		amdgpu_bo_kunmap(bo);
 
 		/* try to alloc a new handle */
-		for (i = 0; i < AMDGPU_MAX_UVD_HANDLES; ++i) {
+		for (i = 0; i < adev->uvd.max_handles; ++i) {
 			if (atomic_read(&adev->uvd.handles[i]) == handle) {
 				DRM_ERROR("Handle 0x%x already in use!\n", handle);
 				return -EINVAL;
@@ -578,13 +657,13 @@ static int amdgpu_uvd_cs_msg(struct amdg
 
 	case 1:
 		/* it's a decode msg, calc buffer sizes */
-		r = amdgpu_uvd_cs_msg_decode(msg, ctx->buf_sizes);
+		r = amdgpu_uvd_cs_msg_decode(adev, msg, ctx->buf_sizes);
 		amdgpu_bo_kunmap(bo);
 		if (r)
 			return r;
 
 		/* validate the handle */
-		for (i = 0; i < AMDGPU_MAX_UVD_HANDLES; ++i) {
+		for (i = 0; i < adev->uvd.max_handles; ++i) {
 			if (atomic_read(&adev->uvd.handles[i]) == handle) {
 				if (adev->uvd.filp[i] != ctx->parser->filp) {
 					DRM_ERROR("UVD handle collision detected!\n");
@@ -599,7 +678,7 @@ static int amdgpu_uvd_cs_msg(struct amdg
 
 	case 2:
 		/* it's a destroy msg, free the handle */
-		for (i = 0; i < AMDGPU_MAX_UVD_HANDLES; ++i)
+		for (i = 0; i < adev->uvd.max_handles; ++i)
 			atomic_cmpxchg(&adev->uvd.handles[i], handle, 0);
 		amdgpu_bo_kunmap(bo);
 		return 0;
@@ -879,7 +958,7 @@ static int amdgpu_uvd_send_msg(struct am
 	ib->length_dw = 16;
 
 	if (direct) {
-		r = amdgpu_ib_schedule(ring, 1, ib, NULL, &f);
+		r = amdgpu_ib_schedule(ring, 1, ib, NULL, NULL, &f);
 		job->fence = f;
 		if (r)
 			goto err_free;
@@ -1011,13 +1090,17 @@ static void amdgpu_uvd_idle_work_handler
 
 	fences = amdgpu_fence_count_emitted(&adev->uvd.ring);
 
-	for (i = 0; i < AMDGPU_MAX_UVD_HANDLES; ++i)
+	for (i = 0; i < adev->uvd.max_handles; ++i)
 		if (atomic_read(&adev->uvd.handles[i]))
 			++handles;
 
 	if (fences == 0 && handles == 0) {
 		if (adev->pm.dpm_enabled) {
 			amdgpu_dpm_enable_uvd(adev, false);
+			/* just work around for uvd clock remain high even
+			 * when uvd dpm disabled on Polaris10 */
+			if (adev->asic_type == CHIP_POLARIS10)
+				amdgpu_asic_set_uvd_clocks(adev, 0, 0);
 		} else {
 			amdgpu_asic_set_uvd_clocks(adev, 0, 0);
 		}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c	2016-05-15 19:20:27.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c	2016-07-24 18:16:37.000000000 -0400
@@ -41,15 +41,17 @@
 /* Firmware Names */
 #ifdef CONFIG_DRM_AMDGPU_CIK
 #define FIRMWARE_BONAIRE	"/*(DEBLOBBED)*/"
-#define FIRMWARE_KABINI 	"/*(DEBLOBBED)*/"
-#define FIRMWARE_KAVERI 	"/*(DEBLOBBED)*/"
-#define FIRMWARE_HAWAII 	"/*(DEBLOBBED)*/"
+#define FIRMWARE_KABINI	"/*(DEBLOBBED)*/"
+#define FIRMWARE_KAVERI	"/*(DEBLOBBED)*/"
+#define FIRMWARE_HAWAII	"/*(DEBLOBBED)*/"
 #define FIRMWARE_MULLINS	"/*(DEBLOBBED)*/"
 #endif
 #define FIRMWARE_TONGA		"/*(DEBLOBBED)*/"
 #define FIRMWARE_CARRIZO	"/*(DEBLOBBED)*/"
 #define FIRMWARE_FIJI		"/*(DEBLOBBED)*/"
 #define FIRMWARE_STONEY		"/*(DEBLOBBED)*/"
+#define FIRMWARE_POLARIS10	"/*(DEBLOBBED)*/"
+#define FIRMWARE_POLARIS11         "/*(DEBLOBBED)*/"
 
 #ifdef CONFIG_DRM_AMDGPU_CIK
 /*(DEBLOBBED)*/
@@ -106,6 +108,12 @@ int amdgpu_vce_sw_init(struct amdgpu_dev
 	case CHIP_STONEY:
 		fw_name = FIRMWARE_STONEY;
 		break;
+	case CHIP_POLARIS10:
+		fw_name = FIRMWARE_POLARIS10;
+		break;
+	case CHIP_POLARIS11:
+		fw_name = FIRMWARE_POLARIS11;
+		break;
 
 	default:
 		return -EINVAL;
@@ -419,7 +427,7 @@ int amdgpu_vce_get_create_msg(struct amd
 	for (i = ib->length_dw; i < ib_size_dw; ++i)
 		ib->ptr[i] = 0x0;
 
-	r = amdgpu_ib_schedule(ring, 1, ib, NULL, &f);
+	r = amdgpu_ib_schedule(ring, 1, ib, NULL, NULL, &f);
 	job->fence = f;
 	if (r)
 		goto err;
@@ -481,7 +489,7 @@ int amdgpu_vce_get_destroy_msg(struct am
 		ib->ptr[i] = 0x0;
 
 	if (direct) {
-		r = amdgpu_ib_schedule(ring, 1, ib, NULL, &f);
+		r = amdgpu_ib_schedule(ring, 1, ib, NULL, NULL, &f);
 		job->fence = f;
 		if (r)
 			goto err;
@@ -745,7 +753,8 @@ out:
  * @ib: the IB to execute
  *
  */
-void amdgpu_vce_ring_emit_ib(struct amdgpu_ring *ring, struct amdgpu_ib *ib)
+void amdgpu_vce_ring_emit_ib(struct amdgpu_ring *ring, struct amdgpu_ib *ib,
+			     unsigned vm_id, bool ctx_switch)
 {
 	amdgpu_ring_write(ring, VCE_CMD_IB);
 	amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr));
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h	2016-07-24 15:23:50.000000000 -0400
@@ -34,7 +34,8 @@ int amdgpu_vce_get_destroy_msg(struct am
 			       bool direct, struct fence **fence);
 void amdgpu_vce_free_handles(struct amdgpu_device *adev, struct drm_file *filp);
 int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, uint32_t ib_idx);
-void amdgpu_vce_ring_emit_ib(struct amdgpu_ring *ring, struct amdgpu_ib *ib);
+void amdgpu_vce_ring_emit_ib(struct amdgpu_ring *ring, struct amdgpu_ib *ib,
+			     unsigned vm_id, bool ctx_switch);
 void amdgpu_vce_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq,
 				unsigned flags);
 int amdgpu_vce_ring_test_ring(struct amdgpu_ring *ring);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c	2016-07-24 15:23:50.000000000 -0400
@@ -53,6 +53,18 @@
 /* Special value that no flush is necessary */
 #define AMDGPU_VM_NO_FLUSH (~0ll)
 
+/* Local structure. Encapsulate some VM table update parameters to reduce
+ * the number of function parameters
+ */
+struct amdgpu_vm_update_params {
+	/* address where to copy page table entries from */
+	uint64_t src;
+	/* DMA addresses to use for mapping */
+	dma_addr_t *pages_addr;
+	/* indirect buffer to fill with commands */
+	struct amdgpu_ib *ib;
+};
+
 /**
  * amdgpu_vm_num_pde - return the number of page directory entries
  *
@@ -166,74 +178,109 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *
 {
 	uint64_t pd_addr = amdgpu_bo_gpu_offset(vm->page_directory);
 	struct amdgpu_device *adev = ring->adev;
-	struct amdgpu_vm_id *id = &vm->ids[ring->idx];
 	struct fence *updates = sync->last_vm_update;
+	struct amdgpu_vm_id *id;
+	unsigned i = ring->idx;
 	int r;
 
 	mutex_lock(&adev->vm_manager.lock);
 
-	/* check if the id is still valid */
-	if (id->mgr_id) {
-		struct fence *flushed = id->flushed_updates;
-		bool is_later;
-		long owner;
+	/* Check if we can use a VMID already assigned to this VM */
+	do {
+		struct fence *flushed;
 
-		if (!flushed)
-			is_later = true;
-		else if (!updates)
-			is_later = false;
-		else
-			is_later = fence_is_later(updates, flushed);
+		id = vm->ids[i++];
+		if (i == AMDGPU_MAX_RINGS)
+			i = 0;
 
-		owner = atomic_long_read(&id->mgr_id->owner);
-		if (!is_later && owner == (long)id &&
-		    pd_addr == id->pd_gpu_addr) {
+		/* Check all the prerequisites to using this VMID */
+		if (!id)
+			continue;
 
+		if (atomic64_read(&id->owner) != vm->client_id)
+			continue;
+
+		if (pd_addr != id->pd_gpu_addr)
+			continue;
+
+		if (id->last_user != ring &&
+		    (!id->last_flush || !fence_is_signaled(id->last_flush)))
+			continue;
+
+		flushed  = id->flushed_updates;
+		if (updates && (!flushed || fence_is_later(updates, flushed)))
+			continue;
+
+		/* Good we can use this VMID */
+		if (id->last_user == ring) {
 			r = amdgpu_sync_fence(ring->adev, sync,
-					      id->mgr_id->active);
-			if (r) {
-				mutex_unlock(&adev->vm_manager.lock);
-				return r;
-			}
+					      id->first);
+			if (r)
+				goto error;
+		}
 
-			fence_put(id->mgr_id->active);
-			id->mgr_id->active = fence_get(fence);
+		/* And remember this submission as user of the VMID */
+		r = amdgpu_sync_fence(ring->adev, &id->active, fence);
+		if (r)
+			goto error;
 
-			list_move_tail(&id->mgr_id->list,
-				       &adev->vm_manager.ids_lru);
+		list_move_tail(&id->list, &adev->vm_manager.ids_lru);
+		vm->ids[ring->idx] = id;
 
-			*vm_id = id->mgr_id - adev->vm_manager.ids;
-			*vm_pd_addr = AMDGPU_VM_NO_FLUSH;
-			trace_amdgpu_vm_grab_id(vm, ring->idx, *vm_id,
-						*vm_pd_addr);
+		*vm_id = id - adev->vm_manager.ids;
+		*vm_pd_addr = AMDGPU_VM_NO_FLUSH;
+		trace_amdgpu_vm_grab_id(vm, ring->idx, *vm_id, *vm_pd_addr);
 
-			mutex_unlock(&adev->vm_manager.lock);
-			return 0;
+		mutex_unlock(&adev->vm_manager.lock);
+		return 0;
+
+	} while (i != ring->idx);
+
+	id = list_first_entry(&adev->vm_manager.ids_lru,
+			      struct amdgpu_vm_id,
+			      list);
+
+	if (!amdgpu_sync_is_idle(&id->active)) {
+		struct list_head *head = &adev->vm_manager.ids_lru;
+		struct amdgpu_vm_id *tmp;
+
+		list_for_each_entry_safe(id, tmp, &adev->vm_manager.ids_lru,
+					 list) {
+			if (amdgpu_sync_is_idle(&id->active)) {
+				list_move(&id->list, head);
+				head = &id->list;
+			}
 		}
+		id = list_first_entry(&adev->vm_manager.ids_lru,
+				      struct amdgpu_vm_id,
+				      list);
 	}
 
-	id->mgr_id = list_first_entry(&adev->vm_manager.ids_lru,
-				      struct amdgpu_vm_manager_id,
-				      list);
+	r = amdgpu_sync_cycle_fences(sync, &id->active, fence);
+	if (r)
+		goto error;
 
-	r = amdgpu_sync_fence(ring->adev, sync, id->mgr_id->active);
-	if (!r) {
-		fence_put(id->mgr_id->active);
-		id->mgr_id->active = fence_get(fence);
+	fence_put(id->first);
+	id->first = fence_get(fence);
 
-		fence_put(id->flushed_updates);
-		id->flushed_updates = fence_get(updates);
+	fence_put(id->last_flush);
+	id->last_flush = NULL;
 
-		id->pd_gpu_addr = pd_addr;
+	fence_put(id->flushed_updates);
+	id->flushed_updates = fence_get(updates);
 
-		list_move_tail(&id->mgr_id->list, &adev->vm_manager.ids_lru);
-		atomic_long_set(&id->mgr_id->owner, (long)id);
+	id->pd_gpu_addr = pd_addr;
 
-		*vm_id = id->mgr_id - adev->vm_manager.ids;
-		*vm_pd_addr = pd_addr;
-		trace_amdgpu_vm_grab_id(vm, ring->idx, *vm_id, *vm_pd_addr);
-	}
+	list_move_tail(&id->list, &adev->vm_manager.ids_lru);
+	id->last_user = ring;
+	atomic64_set(&id->owner, vm->client_id);
+	vm->ids[ring->idx] = id;
+
+	*vm_id = id - adev->vm_manager.ids;
+	*vm_pd_addr = pd_addr;
+	trace_amdgpu_vm_grab_id(vm, ring->idx, *vm_id, *vm_pd_addr);
 
+error:
 	mutex_unlock(&adev->vm_manager.lock);
 	return r;
 }
@@ -247,43 +294,62 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *
  *
  * Emit a VM flush when it is necessary.
  */
-void amdgpu_vm_flush(struct amdgpu_ring *ring,
-		     unsigned vm_id, uint64_t pd_addr,
-		     uint32_t gds_base, uint32_t gds_size,
-		     uint32_t gws_base, uint32_t gws_size,
-		     uint32_t oa_base, uint32_t oa_size)
+int amdgpu_vm_flush(struct amdgpu_ring *ring,
+		    unsigned vm_id, uint64_t pd_addr,
+		    uint32_t gds_base, uint32_t gds_size,
+		    uint32_t gws_base, uint32_t gws_size,
+		    uint32_t oa_base, uint32_t oa_size)
 {
 	struct amdgpu_device *adev = ring->adev;
-	struct amdgpu_vm_manager_id *mgr_id = &adev->vm_manager.ids[vm_id];
+	struct amdgpu_vm_id *id = &adev->vm_manager.ids[vm_id];
 	bool gds_switch_needed = ring->funcs->emit_gds_switch && (
-		mgr_id->gds_base != gds_base ||
-		mgr_id->gds_size != gds_size ||
-		mgr_id->gws_base != gws_base ||
-		mgr_id->gws_size != gws_size ||
-		mgr_id->oa_base != oa_base ||
-		mgr_id->oa_size != oa_size);
+		id->gds_base != gds_base ||
+		id->gds_size != gds_size ||
+		id->gws_base != gws_base ||
+		id->gws_size != gws_size ||
+		id->oa_base != oa_base ||
+		id->oa_size != oa_size);
+	int r;
 
 	if (ring->funcs->emit_pipeline_sync && (
-	    pd_addr != AMDGPU_VM_NO_FLUSH || gds_switch_needed))
+	    pd_addr != AMDGPU_VM_NO_FLUSH || gds_switch_needed ||
+		    ring->type == AMDGPU_RING_TYPE_COMPUTE))
 		amdgpu_ring_emit_pipeline_sync(ring);
 
-	if (pd_addr != AMDGPU_VM_NO_FLUSH) {
+	if (ring->funcs->emit_vm_flush &&
+	    pd_addr != AMDGPU_VM_NO_FLUSH) {
+		struct fence *fence;
+
 		trace_amdgpu_vm_flush(pd_addr, ring->idx, vm_id);
 		amdgpu_ring_emit_vm_flush(ring, vm_id, pd_addr);
+
+		mutex_lock(&adev->vm_manager.lock);
+		if ((id->pd_gpu_addr == pd_addr) && (id->last_user == ring)) {
+			r = amdgpu_fence_emit(ring, &fence);
+			if (r) {
+				mutex_unlock(&adev->vm_manager.lock);
+				return r;
+			}
+			fence_put(id->last_flush);
+			id->last_flush = fence;
+		}
+		mutex_unlock(&adev->vm_manager.lock);
 	}
 
 	if (gds_switch_needed) {
-		mgr_id->gds_base = gds_base;
-		mgr_id->gds_size = gds_size;
-		mgr_id->gws_base = gws_base;
-		mgr_id->gws_size = gws_size;
-		mgr_id->oa_base = oa_base;
-		mgr_id->oa_size = oa_size;
+		id->gds_base = gds_base;
+		id->gds_size = gds_size;
+		id->gws_base = gws_base;
+		id->gws_size = gws_size;
+		id->oa_base = oa_base;
+		id->oa_size = oa_size;
 		amdgpu_ring_emit_gds_switch(ring, vm_id,
 					    gds_base, gds_size,
 					    gws_base, gws_size,
 					    oa_base, oa_size);
 	}
+
+	return 0;
 }
 
 /**
@@ -296,14 +362,14 @@ void amdgpu_vm_flush(struct amdgpu_ring
  */
 void amdgpu_vm_reset_id(struct amdgpu_device *adev, unsigned vm_id)
 {
-	struct amdgpu_vm_manager_id *mgr_id = &adev->vm_manager.ids[vm_id];
+	struct amdgpu_vm_id *id = &adev->vm_manager.ids[vm_id];
 
-	mgr_id->gds_base = 0;
-	mgr_id->gds_size = 0;
-	mgr_id->gws_base = 0;
-	mgr_id->gws_size = 0;
-	mgr_id->oa_base = 0;
-	mgr_id->oa_size = 0;
+	id->gds_base = 0;
+	id->gds_size = 0;
+	id->gws_base = 0;
+	id->gws_size = 0;
+	id->oa_base = 0;
+	id->oa_size = 0;
 }
 
 /**
@@ -335,9 +401,7 @@ struct amdgpu_bo_va *amdgpu_vm_bo_find(s
  * amdgpu_vm_update_pages - helper to call the right asic function
  *
  * @adev: amdgpu_device pointer
- * @gtt: GART instance to use for mapping
- * @gtt_flags: GTT hw access flags
- * @ib: indirect buffer to fill with commands
+ * @vm_update_params: see amdgpu_vm_update_params definition
  * @pe: addr of the page entry
  * @addr: dst addr to write into pe
  * @count: number of page entries to update
@@ -348,30 +412,29 @@ struct amdgpu_bo_va *amdgpu_vm_bo_find(s
  * to setup the page table using the DMA.
  */
 static void amdgpu_vm_update_pages(struct amdgpu_device *adev,
-				   struct amdgpu_gart *gtt,
-				   uint32_t gtt_flags,
-				   struct amdgpu_ib *ib,
+				   struct amdgpu_vm_update_params
+					*vm_update_params,
 				   uint64_t pe, uint64_t addr,
 				   unsigned count, uint32_t incr,
 				   uint32_t flags)
 {
 	trace_amdgpu_vm_set_page(pe, addr, count, incr, flags);
 
-	if ((gtt == &adev->gart) && (flags == gtt_flags)) {
-		uint64_t src = gtt->table_addr + (addr >> 12) * 8;
-		amdgpu_vm_copy_pte(adev, ib, pe, src, count);
+	if (vm_update_params->src) {
+		amdgpu_vm_copy_pte(adev, vm_update_params->ib,
+			pe, (vm_update_params->src + (addr >> 12) * 8), count);
 
-	} else if (gtt) {
-		dma_addr_t *pages_addr = gtt->pages_addr;
-		amdgpu_vm_write_pte(adev, ib, pages_addr, pe, addr,
-				    count, incr, flags);
+	} else if (vm_update_params->pages_addr) {
+		amdgpu_vm_write_pte(adev, vm_update_params->ib,
+			vm_update_params->pages_addr,
+			pe, addr, count, incr, flags);
 
 	} else if (count < 3) {
-		amdgpu_vm_write_pte(adev, ib, NULL, pe, addr,
+		amdgpu_vm_write_pte(adev, vm_update_params->ib, NULL, pe, addr,
 				    count, incr, flags);
 
 	} else {
-		amdgpu_vm_set_pte_pde(adev, ib, pe, addr,
+		amdgpu_vm_set_pte_pde(adev, vm_update_params->ib, pe, addr,
 				      count, incr, flags);
 	}
 }
@@ -391,10 +454,12 @@ static int amdgpu_vm_clear_bo(struct amd
 	struct amdgpu_ring *ring;
 	struct fence *fence = NULL;
 	struct amdgpu_job *job;
+	struct amdgpu_vm_update_params vm_update_params;
 	unsigned entries;
 	uint64_t addr;
 	int r;
 
+	memset(&vm_update_params, 0, sizeof(vm_update_params));
 	ring = container_of(vm->entity.sched, struct amdgpu_ring, sched);
 
 	r = reservation_object_reserve_shared(bo->tbo.resv);
@@ -412,7 +477,8 @@ static int amdgpu_vm_clear_bo(struct amd
 	if (r)
 		goto error;
 
-	amdgpu_vm_update_pages(adev, NULL, 0, &job->ibs[0], addr, 0, entries,
+	vm_update_params.ib = &job->ibs[0];
+	amdgpu_vm_update_pages(adev, &vm_update_params, addr, 0, entries,
 			       0, 0);
 	amdgpu_ring_pad_ib(ring, &job->ibs[0]);
 
@@ -485,11 +551,12 @@ int amdgpu_vm_update_page_directory(stru
 	uint64_t last_pde = ~0, last_pt = ~0;
 	unsigned count = 0, pt_idx, ndw;
 	struct amdgpu_job *job;
-	struct amdgpu_ib *ib;
+	struct amdgpu_vm_update_params vm_update_params;
 	struct fence *fence = NULL;
 
 	int r;
 
+	memset(&vm_update_params, 0, sizeof(vm_update_params));
 	ring = container_of(vm->entity.sched, struct amdgpu_ring, sched);
 
 	/* padding, etc. */
@@ -502,7 +569,7 @@ int amdgpu_vm_update_page_directory(stru
 	if (r)
 		return r;
 
-	ib = &job->ibs[0];
+	vm_update_params.ib = &job->ibs[0];
 
 	/* walk over the address space and update the page directory */
 	for (pt_idx = 0; pt_idx <= vm->max_pde_used; ++pt_idx) {
@@ -522,7 +589,7 @@ int amdgpu_vm_update_page_directory(stru
 		    ((last_pt + incr * count) != pt)) {
 
 			if (count) {
-				amdgpu_vm_update_pages(adev, NULL, 0, ib,
+				amdgpu_vm_update_pages(adev, &vm_update_params,
 						       last_pde, last_pt,
 						       count, incr,
 						       AMDGPU_PTE_VALID);
@@ -537,14 +604,15 @@ int amdgpu_vm_update_page_directory(stru
 	}
 
 	if (count)
-		amdgpu_vm_update_pages(adev, NULL, 0, ib, last_pde, last_pt,
-				       count, incr, AMDGPU_PTE_VALID);
+		amdgpu_vm_update_pages(adev, &vm_update_params,
+					last_pde, last_pt,
+					count, incr, AMDGPU_PTE_VALID);
 
-	if (ib->length_dw != 0) {
-		amdgpu_ring_pad_ib(ring, ib);
+	if (vm_update_params.ib->length_dw != 0) {
+		amdgpu_ring_pad_ib(ring, vm_update_params.ib);
 		amdgpu_sync_resv(adev, &job->sync, pd->tbo.resv,
 				 AMDGPU_FENCE_OWNER_VM);
-		WARN_ON(ib->length_dw > ndw);
+		WARN_ON(vm_update_params.ib->length_dw > ndw);
 		r = amdgpu_job_submit(job, ring, &vm->entity,
 				      AMDGPU_FENCE_OWNER_VM, &fence);
 		if (r)
@@ -570,18 +638,15 @@ error_free:
  * amdgpu_vm_frag_ptes - add fragment information to PTEs
  *
  * @adev: amdgpu_device pointer
- * @gtt: GART instance to use for mapping
- * @gtt_flags: GTT hw mapping flags
- * @ib: IB for the update
+ * @vm_update_params: see amdgpu_vm_update_params definition
  * @pe_start: first PTE to handle
  * @pe_end: last PTE to handle
  * @addr: addr those PTEs should point to
  * @flags: hw mapping flags
  */
 static void amdgpu_vm_frag_ptes(struct amdgpu_device *adev,
-				struct amdgpu_gart *gtt,
-				uint32_t gtt_flags,
-				struct amdgpu_ib *ib,
+				struct amdgpu_vm_update_params
+					*vm_update_params,
 				uint64_t pe_start, uint64_t pe_end,
 				uint64_t addr, uint32_t flags)
 {
@@ -618,10 +683,11 @@ static void amdgpu_vm_frag_ptes(struct a
 		return;
 
 	/* system pages are non continuously */
-	if (gtt || !(flags & AMDGPU_PTE_VALID) || (frag_start >= frag_end)) {
+	if (vm_update_params->src || vm_update_params->pages_addr ||
+		!(flags & AMDGPU_PTE_VALID) || (frag_start >= frag_end)) {
 
 		count = (pe_end - pe_start) / 8;
-		amdgpu_vm_update_pages(adev, gtt, gtt_flags, ib, pe_start,
+		amdgpu_vm_update_pages(adev, vm_update_params, pe_start,
 				       addr, count, AMDGPU_GPU_PAGE_SIZE,
 				       flags);
 		return;
@@ -630,21 +696,21 @@ static void amdgpu_vm_frag_ptes(struct a
 	/* handle the 4K area at the beginning */
 	if (pe_start != frag_start) {
 		count = (frag_start - pe_start) / 8;
-		amdgpu_vm_update_pages(adev, NULL, 0, ib, pe_start, addr,
+		amdgpu_vm_update_pages(adev, vm_update_params, pe_start, addr,
 				       count, AMDGPU_GPU_PAGE_SIZE, flags);
 		addr += AMDGPU_GPU_PAGE_SIZE * count;
 	}
 
 	/* handle the area in the middle */
 	count = (frag_end - frag_start) / 8;
-	amdgpu_vm_update_pages(adev, NULL, 0, ib, frag_start, addr, count,
+	amdgpu_vm_update_pages(adev, vm_update_params, frag_start, addr, count,
 			       AMDGPU_GPU_PAGE_SIZE, flags | frag_flags);
 
 	/* handle the 4K area at the end */
 	if (frag_end != pe_end) {
 		addr += AMDGPU_GPU_PAGE_SIZE * count;
 		count = (pe_end - frag_end) / 8;
-		amdgpu_vm_update_pages(adev, NULL, 0, ib, frag_end, addr,
+		amdgpu_vm_update_pages(adev, vm_update_params, frag_end, addr,
 				       count, AMDGPU_GPU_PAGE_SIZE, flags);
 	}
 }
@@ -653,8 +719,7 @@ static void amdgpu_vm_frag_ptes(struct a
  * amdgpu_vm_update_ptes - make sure that page tables are valid
  *
  * @adev: amdgpu_device pointer
- * @gtt: GART instance to use for mapping
- * @gtt_flags: GTT hw mapping flags
+ * @vm_update_params: see amdgpu_vm_update_params definition
  * @vm: requested vm
  * @start: start of GPU address range
  * @end: end of GPU address range
@@ -664,10 +729,9 @@ static void amdgpu_vm_frag_ptes(struct a
  * Update the page tables in the range @start - @end.
  */
 static void amdgpu_vm_update_ptes(struct amdgpu_device *adev,
-				  struct amdgpu_gart *gtt,
-				  uint32_t gtt_flags,
+				  struct amdgpu_vm_update_params
+					*vm_update_params,
 				  struct amdgpu_vm *vm,
-				  struct amdgpu_ib *ib,
 				  uint64_t start, uint64_t end,
 				  uint64_t dst, uint32_t flags)
 {
@@ -693,7 +757,7 @@ static void amdgpu_vm_update_ptes(struct
 
 		if (last_pe_end != pe_start) {
 
-			amdgpu_vm_frag_ptes(adev, gtt, gtt_flags, ib,
+			amdgpu_vm_frag_ptes(adev, vm_update_params,
 					    last_pe_start, last_pe_end,
 					    last_dst, flags);
 
@@ -708,17 +772,16 @@ static void amdgpu_vm_update_ptes(struct
 		dst += nptes * AMDGPU_GPU_PAGE_SIZE;
 	}
 
-	amdgpu_vm_frag_ptes(adev, gtt, gtt_flags, ib,
-			    last_pe_start, last_pe_end,
-			    last_dst, flags);
+	amdgpu_vm_frag_ptes(adev, vm_update_params, last_pe_start,
+			    last_pe_end, last_dst, flags);
 }
 
 /**
  * amdgpu_vm_bo_update_mapping - update a mapping in the vm page table
  *
  * @adev: amdgpu_device pointer
- * @gtt: GART instance to use for mapping
- * @gtt_flags: flags as they are used for GTT
+ * @src: address where to copy page table entries from
+ * @pages_addr: DMA addresses to use for mapping
  * @vm: requested vm
  * @start: start of mapped range
  * @last: last mapped entry
@@ -730,8 +793,8 @@ static void amdgpu_vm_update_ptes(struct
  * Returns 0 for success, -EINVAL for failure.
  */
 static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev,
-				       struct amdgpu_gart *gtt,
-				       uint32_t gtt_flags,
+				       uint64_t src,
+				       dma_addr_t *pages_addr,
 				       struct amdgpu_vm *vm,
 				       uint64_t start, uint64_t last,
 				       uint32_t flags, uint64_t addr,
@@ -741,11 +804,14 @@ static int amdgpu_vm_bo_update_mapping(s
 	void *owner = AMDGPU_FENCE_OWNER_VM;
 	unsigned nptes, ncmds, ndw;
 	struct amdgpu_job *job;
-	struct amdgpu_ib *ib;
+	struct amdgpu_vm_update_params vm_update_params;
 	struct fence *f = NULL;
 	int r;
 
 	ring = container_of(vm->entity.sched, struct amdgpu_ring, sched);
+	memset(&vm_update_params, 0, sizeof(vm_update_params));
+	vm_update_params.src = src;
+	vm_update_params.pages_addr = pages_addr;
 
 	/* sync to everything on unmapping */
 	if (!(flags & AMDGPU_PTE_VALID))
@@ -762,11 +828,11 @@ static int amdgpu_vm_bo_update_mapping(s
 	/* padding, etc. */
 	ndw = 64;
 
-	if ((gtt == &adev->gart) && (flags == gtt_flags)) {
+	if (vm_update_params.src) {
 		/* only copy commands needed */
 		ndw += ncmds * 7;
 
-	} else if (gtt) {
+	} else if (vm_update_params.pages_addr) {
 		/* header for write data commands */
 		ndw += ncmds * 4;
 
@@ -785,7 +851,7 @@ static int amdgpu_vm_bo_update_mapping(s
 	if (r)
 		return r;
 
-	ib = &job->ibs[0];
+	vm_update_params.ib = &job->ibs[0];
 
 	r = amdgpu_sync_resv(adev, &job->sync, vm->page_directory->tbo.resv,
 			     owner);
@@ -796,11 +862,11 @@ static int amdgpu_vm_bo_update_mapping(s
 	if (r)
 		goto error_free;
 
-	amdgpu_vm_update_ptes(adev, gtt, gtt_flags, vm, ib, start, last + 1,
-			      addr, flags);
+	amdgpu_vm_update_ptes(adev, &vm_update_params, vm, start,
+			      last + 1, addr, flags);
 
-	amdgpu_ring_pad_ib(ring, ib);
-	WARN_ON(ib->length_dw > ndw);
+	amdgpu_ring_pad_ib(ring, vm_update_params.ib);
+	WARN_ON(vm_update_params.ib->length_dw > ndw);
 	r = amdgpu_job_submit(job, ring, &vm->entity,
 			      AMDGPU_FENCE_OWNER_VM, &f);
 	if (r)
@@ -823,11 +889,12 @@ error_free:
  * amdgpu_vm_bo_split_mapping - split a mapping into smaller chunks
  *
  * @adev: amdgpu_device pointer
- * @gtt: GART instance to use for mapping
+ * @gtt_flags: flags as they are used for GTT
+ * @pages_addr: DMA addresses to use for mapping
  * @vm: requested vm
  * @mapping: mapped range and flags to use for the update
  * @addr: addr to set the area to
- * @gtt_flags: flags as they are used for GTT
+ * @flags: HW flags for the mapping
  * @fence: optional resulting fence
  *
  * Split the mapping into smaller chunks so that each update fits
@@ -835,16 +902,16 @@ error_free:
  * Returns 0 for success, -EINVAL for failure.
  */
 static int amdgpu_vm_bo_split_mapping(struct amdgpu_device *adev,
-				      struct amdgpu_gart *gtt,
 				      uint32_t gtt_flags,
+				      dma_addr_t *pages_addr,
 				      struct amdgpu_vm *vm,
 				      struct amdgpu_bo_va_mapping *mapping,
-				      uint64_t addr, struct fence **fence)
+				      uint32_t flags, uint64_t addr,
+				      struct fence **fence)
 {
 	const uint64_t max_size = 64ULL * 1024ULL * 1024ULL / AMDGPU_GPU_PAGE_SIZE;
 
-	uint64_t start = mapping->it.start;
-	uint32_t flags = gtt_flags;
+	uint64_t src = 0, start = mapping->it.start;
 	int r;
 
 	/* normally,bo_va->flags only contians READABLE and WIRTEABLE bit go here
@@ -857,10 +924,15 @@ static int amdgpu_vm_bo_split_mapping(st
 
 	trace_amdgpu_vm_bo_update(mapping);
 
+	if (pages_addr) {
+		if (flags == gtt_flags)
+			src = adev->gart.table_addr + (addr >> 12) * 8;
+		addr = 0;
+	}
 	addr += mapping->offset;
 
-	if (!gtt || ((gtt == &adev->gart) && (flags == gtt_flags)))
-		return amdgpu_vm_bo_update_mapping(adev, gtt, gtt_flags, vm,
+	if (!pages_addr || src)
+		return amdgpu_vm_bo_update_mapping(adev, src, pages_addr, vm,
 						   start, mapping->it.last,
 						   flags, addr, fence);
 
@@ -868,7 +940,7 @@ static int amdgpu_vm_bo_split_mapping(st
 		uint64_t last;
 
 		last = min((uint64_t)mapping->it.last, start + max_size - 1);
-		r = amdgpu_vm_bo_update_mapping(adev, gtt, gtt_flags, vm,
+		r = amdgpu_vm_bo_update_mapping(adev, src, pages_addr, vm,
 						start, last, flags, addr,
 						fence);
 		if (r)
@@ -899,16 +971,20 @@ int amdgpu_vm_bo_update(struct amdgpu_de
 {
 	struct amdgpu_vm *vm = bo_va->vm;
 	struct amdgpu_bo_va_mapping *mapping;
-	struct amdgpu_gart *gtt = NULL;
-	uint32_t flags;
+	dma_addr_t *pages_addr = NULL;
+	uint32_t gtt_flags, flags;
 	uint64_t addr;
 	int r;
 
 	if (mem) {
+		struct ttm_dma_tt *ttm;
+
 		addr = (u64)mem->start << PAGE_SHIFT;
 		switch (mem->mem_type) {
 		case TTM_PL_TT:
-			gtt = &bo_va->bo->adev->gart;
+			ttm = container_of(bo_va->bo->tbo.ttm, struct
+					   ttm_dma_tt, ttm);
+			pages_addr = ttm->dma_address;
 			break;
 
 		case TTM_PL_VRAM:
@@ -923,6 +999,7 @@ int amdgpu_vm_bo_update(struct amdgpu_de
 	}
 
 	flags = amdgpu_ttm_tt_pte_flags(adev, bo_va->bo->tbo.ttm, mem);
+	gtt_flags = (adev == bo_va->bo->adev) ? flags : 0;
 
 	spin_lock(&vm->status_lock);
 	if (!list_empty(&bo_va->vm_status))
@@ -930,7 +1007,8 @@ int amdgpu_vm_bo_update(struct amdgpu_de
 	spin_unlock(&vm->status_lock);
 
 	list_for_each_entry(mapping, &bo_va->invalids, list) {
-		r = amdgpu_vm_bo_split_mapping(adev, gtt, flags, vm, mapping, addr,
+		r = amdgpu_vm_bo_split_mapping(adev, gtt_flags, pages_addr, vm,
+					       mapping, flags, addr,
 					       &bo_va->last_pt_update);
 		if (r)
 			return r;
@@ -976,8 +1054,8 @@ int amdgpu_vm_clear_freed(struct amdgpu_
 			struct amdgpu_bo_va_mapping, list);
 		list_del(&mapping->list);
 
-		r = amdgpu_vm_bo_split_mapping(adev, NULL, 0, vm, mapping,
-					       0, NULL);
+		r = amdgpu_vm_bo_split_mapping(adev, 0, NULL, vm, mapping,
+					       0, 0, NULL);
 		kfree(mapping);
 		if (r)
 			return r;
@@ -1320,11 +1398,10 @@ int amdgpu_vm_init(struct amdgpu_device
 	struct amd_sched_rq *rq;
 	int i, r;
 
-	for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
-		vm->ids[i].mgr_id = NULL;
-		vm->ids[i].flushed_updates = NULL;
-	}
+	for (i = 0; i < AMDGPU_MAX_RINGS; ++i)
+		vm->ids[i] = NULL;
 	vm->va = RB_ROOT;
+	vm->client_id = atomic64_inc_return(&adev->vm_manager.client_counter);
 	spin_lock_init(&vm->status_lock);
 	INIT_LIST_HEAD(&vm->invalidated);
 	INIT_LIST_HEAD(&vm->cleared);
@@ -1416,15 +1493,6 @@ void amdgpu_vm_fini(struct amdgpu_device
 
 	amdgpu_bo_unref(&vm->page_directory);
 	fence_put(vm->page_directory_fence);
-
-	for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
-		struct amdgpu_vm_id *id = &vm->ids[i];
-
-		if (id->mgr_id)
-			atomic_long_cmpxchg(&id->mgr_id->owner,
-					    (long)id, 0);
-		fence_put(id->flushed_updates);
-	}
 }
 
 /**
@@ -1443,11 +1511,13 @@ void amdgpu_vm_manager_init(struct amdgp
 	/* skip over VMID 0, since it is the system VM */
 	for (i = 1; i < adev->vm_manager.num_ids; ++i) {
 		amdgpu_vm_reset_id(adev, i);
+		amdgpu_sync_create(&adev->vm_manager.ids[i].active);
 		list_add_tail(&adev->vm_manager.ids[i].list,
 			      &adev->vm_manager.ids_lru);
 	}
 
 	atomic_set(&adev->vm_manager.vm_pte_next_ring, 0);
+	atomic64_set(&adev->vm_manager.client_counter, 0);
 }
 
 /**
@@ -1461,6 +1531,11 @@ void amdgpu_vm_manager_fini(struct amdgp
 {
 	unsigned i;
 
-	for (i = 0; i < AMDGPU_NUM_VM; ++i)
-		fence_put(adev->vm_manager.ids[i].active);
+	for (i = 0; i < AMDGPU_NUM_VM; ++i) {
+		struct amdgpu_vm_id *id = &adev->vm_manager.ids[i];
+
+		fence_put(adev->vm_manager.ids[i].first);
+		amdgpu_sync_free(&adev->vm_manager.ids[i].active);
+		fence_put(id->flushed_updates);
+	}
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c	2016-07-24 15:23:50.000000000 -0400
@@ -461,13 +461,14 @@ union set_pixel_clock {
 	PIXEL_CLOCK_PARAMETERS_V3 v3;
 	PIXEL_CLOCK_PARAMETERS_V5 v5;
 	PIXEL_CLOCK_PARAMETERS_V6 v6;
+	PIXEL_CLOCK_PARAMETERS_V7 v7;
 };
 
 /* on DCE5, make sure the voltage is high enough to support the
  * required disp clk.
  */
 void amdgpu_atombios_crtc_set_disp_eng_pll(struct amdgpu_device *adev,
-				    u32 dispclk)
+					   u32 dispclk)
 {
 	u8 frev, crev;
 	int index;
@@ -510,6 +511,49 @@ void amdgpu_atombios_crtc_set_disp_eng_p
 	amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args);
 }
 
+union set_dce_clock {
+	SET_DCE_CLOCK_PS_ALLOCATION_V1_1 v1_1;
+	SET_DCE_CLOCK_PS_ALLOCATION_V2_1 v2_1;
+};
+
+u32 amdgpu_atombios_crtc_set_dce_clock(struct amdgpu_device *adev,
+				       u32 freq, u8 clk_type, u8 clk_src)
+{
+	u8 frev, crev;
+	int index;
+	union set_dce_clock args;
+	u32 ret_freq = 0;
+
+	memset(&args, 0, sizeof(args));
+
+	index = GetIndexIntoMasterTable(COMMAND, SetDCEClock);
+	if (!amdgpu_atom_parse_cmd_header(adev->mode_info.atom_context, index, &frev,
+				   &crev))
+		return 0;
+
+	switch (frev) {
+	case 2:
+		switch (crev) {
+		case 1:
+			args.v2_1.asParam.ulDCEClkFreq = cpu_to_le32(freq); /* 10kHz units */
+			args.v2_1.asParam.ucDCEClkType = clk_type;
+			args.v2_1.asParam.ucDCEClkSrc = clk_src;
+			amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args);
+			ret_freq = le32_to_cpu(args.v2_1.asParam.ulDCEClkFreq) * 10;
+			break;
+		default:
+			DRM_ERROR("Unknown table version %d %d\n", frev, crev);
+			return 0;
+		}
+		break;
+	default:
+		DRM_ERROR("Unknown table version %d %d\n", frev, crev);
+		return 0;
+	}
+
+	return ret_freq;
+}
+
 static bool is_pixel_clock_source_from_pll(u32 encoder_mode, int pll_id)
 {
 	if (ENCODER_MODE_IS_DP(encoder_mode)) {
@@ -523,18 +567,18 @@ static bool is_pixel_clock_source_from_p
 }
 
 void amdgpu_atombios_crtc_program_pll(struct drm_crtc *crtc,
-			       u32 crtc_id,
-			       int pll_id,
-			       u32 encoder_mode,
-			       u32 encoder_id,
-			       u32 clock,
-			       u32 ref_div,
-			       u32 fb_div,
-			       u32 frac_fb_div,
-			       u32 post_div,
-			       int bpc,
-			       bool ss_enabled,
-			       struct amdgpu_atom_ss *ss)
+				      u32 crtc_id,
+				      int pll_id,
+				      u32 encoder_mode,
+				      u32 encoder_id,
+				      u32 clock,
+				      u32 ref_div,
+				      u32 fb_div,
+				      u32 frac_fb_div,
+				      u32 post_div,
+				      int bpc,
+				      bool ss_enabled,
+				      struct amdgpu_atom_ss *ss)
 {
 	struct drm_device *dev = crtc->dev;
 	struct amdgpu_device *adev = dev->dev_private;
@@ -652,6 +696,34 @@ void amdgpu_atombios_crtc_program_pll(st
 			args.v6.ucEncoderMode = encoder_mode;
 			args.v6.ucPpll = pll_id;
 			break;
+		case 7:
+			args.v7.ulPixelClock = cpu_to_le32(clock * 10); /* 100 hz units */
+			args.v7.ucMiscInfo = 0;
+			if ((encoder_mode == ATOM_ENCODER_MODE_DVI) &&
+			    (clock > 165000))
+				args.v7.ucMiscInfo |= PIXEL_CLOCK_V7_MISC_DVI_DUALLINK_EN;
+			args.v7.ucCRTC = crtc_id;
+			if (encoder_mode == ATOM_ENCODER_MODE_HDMI) {
+				switch (bpc) {
+				case 8:
+				default:
+					args.v7.ucDeepColorRatio = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_DIS;
+					break;
+				case 10:
+					args.v7.ucDeepColorRatio = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_5_4;
+					break;
+				case 12:
+					args.v7.ucDeepColorRatio = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_3_2;
+					break;
+				case 16:
+					args.v7.ucDeepColorRatio = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_2_1;
+					break;
+				}
+			}
+			args.v7.ucTransmitterID = encoder_id;
+			args.v7.ucEncoderMode = encoder_mode;
+			args.v7.ucPpll = pll_id;
+			break;
 		default:
 			DRM_ERROR("Unknown table version %d %d\n", frev, crev);
 			return;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/atombios_crtc.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/atombios_crtc.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/atombios_crtc.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/atombios_crtc.h	2016-07-24 15:23:50.000000000 -0400
@@ -37,6 +37,8 @@ void amdgpu_atombios_crtc_set_dtd_timing
 				  struct drm_display_mode *mode);
 void amdgpu_atombios_crtc_set_disp_eng_pll(struct amdgpu_device *adev,
 				    u32 dispclk);
+u32 amdgpu_atombios_crtc_set_dce_clock(struct amdgpu_device *adev,
+				       u32 freq, u8 clk_type, u8 clk_src);
 void amdgpu_atombios_crtc_program_pll(struct drm_crtc *crtc,
 			       u32 crtc_id,
 			       int pll_id,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c	2016-07-24 15:23:50.000000000 -0400
@@ -567,6 +567,7 @@ union dig_encoder_control {
 	DIG_ENCODER_CONTROL_PARAMETERS_V2 v2;
 	DIG_ENCODER_CONTROL_PARAMETERS_V3 v3;
 	DIG_ENCODER_CONTROL_PARAMETERS_V4 v4;
+	DIG_ENCODER_CONTROL_PARAMETERS_V5 v5;
 };
 
 void
@@ -694,6 +695,47 @@ amdgpu_atombios_encoder_setup_dig_encode
 			else
 				args.v4.ucHPD_ID = hpd_id + 1;
 			break;
+		case 5:
+			switch (action) {
+			case ATOM_ENCODER_CMD_SETUP_PANEL_MODE:
+				args.v5.asDPPanelModeParam.ucAction = action;
+				args.v5.asDPPanelModeParam.ucPanelMode = panel_mode;
+				args.v5.asDPPanelModeParam.ucDigId = dig->dig_encoder;
+				break;
+			case ATOM_ENCODER_CMD_STREAM_SETUP:
+				args.v5.asStreamParam.ucAction = action;
+				args.v5.asStreamParam.ucDigId = dig->dig_encoder;
+				args.v5.asStreamParam.ucDigMode =
+					amdgpu_atombios_encoder_get_encoder_mode(encoder);
+				if (ENCODER_MODE_IS_DP(args.v5.asStreamParam.ucDigMode))
+					args.v5.asStreamParam.ucLaneNum = dp_lane_count;
+				else if (amdgpu_dig_monitor_is_duallink(encoder,
+									amdgpu_encoder->pixel_clock))
+					args.v5.asStreamParam.ucLaneNum = 8;
+				else
+					args.v5.asStreamParam.ucLaneNum = 4;
+				args.v5.asStreamParam.ulPixelClock =
+					cpu_to_le32(amdgpu_encoder->pixel_clock / 10);
+				args.v5.asStreamParam.ucBitPerColor =
+					amdgpu_atombios_encoder_get_bpc(encoder);
+				args.v5.asStreamParam.ucLinkRateIn270Mhz = dp_clock / 27000;
+				break;
+			case ATOM_ENCODER_CMD_DP_LINK_TRAINING_START:
+			case ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1:
+			case ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN2:
+			case ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN3:
+			case ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN4:
+			case ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE:
+			case ATOM_ENCODER_CMD_DP_VIDEO_OFF:
+			case ATOM_ENCODER_CMD_DP_VIDEO_ON:
+				args.v5.asCmdParam.ucAction = action;
+				args.v5.asCmdParam.ucDigId = dig->dig_encoder;
+				break;
+			default:
+				DRM_ERROR("Unsupported action 0x%x\n", action);
+				break;
+			}
+			break;
 		default:
 			DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
 			break;
@@ -714,11 +756,12 @@ union dig_transmitter_control {
 	DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 v3;
 	DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 v4;
 	DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_5 v5;
+	DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_6 v6;
 };
 
 void
 amdgpu_atombios_encoder_setup_dig_transmitter(struct drm_encoder *encoder, int action,
-				       uint8_t lane_num, uint8_t lane_set)
+					      uint8_t lane_num, uint8_t lane_set)
 {
 	struct drm_device *dev = encoder->dev;
 	struct amdgpu_device *adev = dev->dev_private;
@@ -1070,6 +1113,54 @@ amdgpu_atombios_encoder_setup_dig_transm
 			args.v5.ucDigEncoderSel = 1 << dig_encoder;
 			args.v5.ucDPLaneSet = lane_set;
 			break;
+		case 6:
+			args.v6.ucAction = action;
+			if (is_dp)
+				args.v6.ulSymClock = cpu_to_le32(dp_clock / 10);
+			else
+				args.v6.ulSymClock = cpu_to_le32(amdgpu_encoder->pixel_clock / 10);
+
+			switch (amdgpu_encoder->encoder_id) {
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+				if (dig->linkb)
+					args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYB;
+				else
+					args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYA;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+				if (dig->linkb)
+					args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYD;
+				else
+					args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYC;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+				if (dig->linkb)
+					args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYF;
+				else
+					args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYE;
+				break;
+			case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
+				args.v6.ucPhyId = ATOM_PHY_ID_UNIPHYG;
+				break;
+			}
+			if (is_dp)
+				args.v6.ucLaneNum = dp_lane_count;
+			else if (amdgpu_dig_monitor_is_duallink(encoder, amdgpu_encoder->pixel_clock))
+				args.v6.ucLaneNum = 8;
+			else
+				args.v6.ucLaneNum = 4;
+			args.v6.ucConnObjId = connector_object_id;
+			if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH)
+				args.v6.ucDPLaneSet = lane_set;
+			else
+				args.v6.ucDigMode = amdgpu_atombios_encoder_get_encoder_mode(encoder);
+
+			if (hpd_id == AMDGPU_HPD_NONE)
+				args.v6.ucHPDSel = 0;
+			else
+				args.v6.ucHPDSel = hpd_id + 1;
+			args.v6.ucDigEncoderSel = 1 << dig_encoder;
+			break;
 		default:
 			DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
 			break;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/atombios_i2c.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/atombios_i2c.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/atombios_i2c.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/atombios_i2c.c	2016-07-24 15:23:50.000000000 -0400
@@ -156,3 +156,18 @@ u32 amdgpu_atombios_i2c_func(struct i2c_
 	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 }
 
+void amdgpu_atombios_i2c_channel_trans(struct amdgpu_device* adev, u8 slave_addr, u8 line_number, u8 offset, u8 data)
+{
+	PROCESS_I2C_CHANNEL_TRANSACTION_PS_ALLOCATION args;
+	int index = GetIndexIntoMasterTable(COMMAND, ProcessI2cChannelTransaction);
+
+	args.ucRegIndex = offset;
+	args.lpI2CDataOut = data;
+	args.ucFlag = 1;
+	args.ucI2CSpeed = TARGET_HW_I2C_CLOCK;
+	args.ucTransBytes = 1;
+	args.ucSlaveAddr = slave_addr;
+	args.ucLineNumber = line_number;
+
+	amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args);
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/atombios_i2c.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/atombios_i2c.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/atombios_i2c.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/atombios_i2c.h	2016-07-24 15:23:50.000000000 -0400
@@ -27,5 +27,7 @@
 int amdgpu_atombios_i2c_xfer(struct i2c_adapter *i2c_adap,
 		      struct i2c_msg *msgs, int num);
 u32 amdgpu_atombios_i2c_func(struct i2c_adapter *adap);
+void amdgpu_atombios_i2c_channel_trans(struct amdgpu_device* adev,
+		u8 slave_addr, u8 line_number, u8 offset, u8 data);
 
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/atom.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/atom.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/atom.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/atom.h	2016-07-24 15:23:50.000000000 -0400
@@ -92,7 +92,7 @@
 #define ATOM_WS_AND_MASK	0x45
 #define ATOM_WS_FB_WINDOW	0x46
 #define ATOM_WS_ATTRIBUTES	0x47
-#define ATOM_WS_REGPTR  	0x48
+#define ATOM_WS_REGPTR		0x48
 
 #define ATOM_IIO_NOP		0
 #define ATOM_IIO_START		1
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/ci_dpm.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/ci_dpm.c	2016-05-15 19:21:10.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/ci_dpm.c	2016-07-24 18:17:42.000000000 -0400
@@ -2548,19 +2548,17 @@ static int ci_get_dependency_volt_by_clk
 	return 0;
 }
 
-static u8 ci_get_sleep_divider_id_from_clock(struct amdgpu_device *adev,
-					     u32 sclk, u32 min_sclk_in_sr)
+static u8 ci_get_sleep_divider_id_from_clock(u32 sclk, u32 min_sclk_in_sr)
 {
 	u32 i;
 	u32 tmp;
-	u32 min = (min_sclk_in_sr > CISLAND_MINIMUM_ENGINE_CLOCK) ?
-		min_sclk_in_sr : CISLAND_MINIMUM_ENGINE_CLOCK;
+	u32 min = max(min_sclk_in_sr, (u32)CISLAND_MINIMUM_ENGINE_CLOCK);
 
 	if (sclk < min)
 		return 0;
 
 	for (i = CISLAND_MAX_DEEPSLEEP_DIVIDER_ID;  ; i--) {
-		tmp = sclk / (1 << i);
+		tmp = sclk >> i;
 		if (tmp >= min || i == 0)
 			break;
 	}
@@ -3357,8 +3355,7 @@ static int ci_populate_single_graphic_le
 	graphic_level->PowerThrottle = 0;
 
 	if (pi->caps_sclk_ds)
-		graphic_level->DeepSleepDivId = ci_get_sleep_divider_id_from_clock(adev,
-										   engine_clock,
+		graphic_level->DeepSleepDivId = ci_get_sleep_divider_id_from_clock(engine_clock,
 										   CISLAND_MINIMUM_ENGINE_CLOCK);
 
 	graphic_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
@@ -6223,6 +6220,9 @@ static int ci_dpm_sw_fini(void *handle)
 	ci_dpm_fini(adev);
 	mutex_unlock(&adev->pm.mutex);
 
+	release_firmware(adev->pm.fw);
+	adev->pm.fw = NULL;
+
 	return 0;
 }
 
@@ -6308,215 +6308,6 @@ static int ci_dpm_wait_for_idle(void *ha
 	return 0;
 }
 
-static void ci_dpm_print_status(void *handle)
-{
-	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-	dev_info(adev->dev, "CIK DPM registers\n");
-	dev_info(adev->dev, "  BIOS_SCRATCH_4=0x%08X\n",
-		 RREG32(mmBIOS_SCRATCH_4));
-	dev_info(adev->dev, "  MC_ARB_DRAM_TIMING=0x%08X\n",
-		 RREG32(mmMC_ARB_DRAM_TIMING));
-	dev_info(adev->dev, "  MC_ARB_DRAM_TIMING2=0x%08X\n",
-		 RREG32(mmMC_ARB_DRAM_TIMING2));
-	dev_info(adev->dev, "  MC_ARB_BURST_TIME=0x%08X\n",
-		 RREG32(mmMC_ARB_BURST_TIME));
-	dev_info(adev->dev, "  MC_ARB_DRAM_TIMING_1=0x%08X\n",
-		 RREG32(mmMC_ARB_DRAM_TIMING_1));
-	dev_info(adev->dev, "  MC_ARB_DRAM_TIMING2_1=0x%08X\n",
-		 RREG32(mmMC_ARB_DRAM_TIMING2_1));
-	dev_info(adev->dev, "  MC_CG_CONFIG=0x%08X\n",
-		 RREG32(mmMC_CG_CONFIG));
-	dev_info(adev->dev, "  MC_ARB_CG=0x%08X\n",
-		 RREG32(mmMC_ARB_CG));
-	dev_info(adev->dev, "  DIDT_SQ_CTRL0=0x%08X\n",
-		 RREG32_DIDT(ixDIDT_SQ_CTRL0));
-	dev_info(adev->dev, "  DIDT_DB_CTRL0=0x%08X\n",
-		 RREG32_DIDT(ixDIDT_DB_CTRL0));
-	dev_info(adev->dev, "  DIDT_TD_CTRL0=0x%08X\n",
-		 RREG32_DIDT(ixDIDT_TD_CTRL0));
-	dev_info(adev->dev, "  DIDT_TCP_CTRL0=0x%08X\n",
-		 RREG32_DIDT(ixDIDT_TCP_CTRL0));
-	dev_info(adev->dev, "  CG_THERMAL_INT=0x%08X\n",
-		 RREG32_SMC(ixCG_THERMAL_INT));
-	dev_info(adev->dev, "  CG_THERMAL_CTRL=0x%08X\n",
-		 RREG32_SMC(ixCG_THERMAL_CTRL));
-	dev_info(adev->dev, "  GENERAL_PWRMGT=0x%08X\n",
-		 RREG32_SMC(ixGENERAL_PWRMGT));
-	dev_info(adev->dev, "  MC_SEQ_CNTL_3=0x%08X\n",
-		 RREG32(mmMC_SEQ_CNTL_3));
-	dev_info(adev->dev, "  LCAC_MC0_CNTL=0x%08X\n",
-		 RREG32_SMC(ixLCAC_MC0_CNTL));
-	dev_info(adev->dev, "  LCAC_MC1_CNTL=0x%08X\n",
-		 RREG32_SMC(ixLCAC_MC1_CNTL));
-	dev_info(adev->dev, "  LCAC_CPL_CNTL=0x%08X\n",
-		 RREG32_SMC(ixLCAC_CPL_CNTL));
-	dev_info(adev->dev, "  SCLK_PWRMGT_CNTL=0x%08X\n",
-		 RREG32_SMC(ixSCLK_PWRMGT_CNTL));
-	dev_info(adev->dev, "  BIF_LNCNT_RESET=0x%08X\n",
-		 RREG32(mmBIF_LNCNT_RESET));
-	dev_info(adev->dev, "  FIRMWARE_FLAGS=0x%08X\n",
-		 RREG32_SMC(ixFIRMWARE_FLAGS));
-	dev_info(adev->dev, "  CG_SPLL_FUNC_CNTL=0x%08X\n",
-		 RREG32_SMC(ixCG_SPLL_FUNC_CNTL));
-	dev_info(adev->dev, "  CG_SPLL_FUNC_CNTL_2=0x%08X\n",
-		 RREG32_SMC(ixCG_SPLL_FUNC_CNTL_2));
-	dev_info(adev->dev, "  CG_SPLL_FUNC_CNTL_3=0x%08X\n",
-		 RREG32_SMC(ixCG_SPLL_FUNC_CNTL_3));
-	dev_info(adev->dev, "  CG_SPLL_FUNC_CNTL_4=0x%08X\n",
-		 RREG32_SMC(ixCG_SPLL_FUNC_CNTL_4));
-	dev_info(adev->dev, "  CG_SPLL_SPREAD_SPECTRUM=0x%08X\n",
-		 RREG32_SMC(ixCG_SPLL_SPREAD_SPECTRUM));
-	dev_info(adev->dev, "  CG_SPLL_SPREAD_SPECTRUM_2=0x%08X\n",
-		 RREG32_SMC(ixCG_SPLL_SPREAD_SPECTRUM_2));
-	dev_info(adev->dev, "  DLL_CNTL=0x%08X\n",
-		 RREG32(mmDLL_CNTL));
-	dev_info(adev->dev, "  MCLK_PWRMGT_CNTL=0x%08X\n",
-		 RREG32(mmMCLK_PWRMGT_CNTL));
-	dev_info(adev->dev, "  MPLL_AD_FUNC_CNTL=0x%08X\n",
-		 RREG32(mmMPLL_AD_FUNC_CNTL));
-	dev_info(adev->dev, "  MPLL_DQ_FUNC_CNTL=0x%08X\n",
-		 RREG32(mmMPLL_DQ_FUNC_CNTL));
-	dev_info(adev->dev, "  MPLL_FUNC_CNTL=0x%08X\n",
-		 RREG32(mmMPLL_FUNC_CNTL));
-	dev_info(adev->dev, "  MPLL_FUNC_CNTL_1=0x%08X\n",
-		 RREG32(mmMPLL_FUNC_CNTL_1));
-	dev_info(adev->dev, "  MPLL_FUNC_CNTL_2=0x%08X\n",
-		 RREG32(mmMPLL_FUNC_CNTL_2));
-	dev_info(adev->dev, "  MPLL_SS1=0x%08X\n",
-		 RREG32(mmMPLL_SS1));
-	dev_info(adev->dev, "  MPLL_SS2=0x%08X\n",
-		 RREG32(mmMPLL_SS2));
-	dev_info(adev->dev, "  CG_DISPLAY_GAP_CNTL=0x%08X\n",
-		 RREG32_SMC(ixCG_DISPLAY_GAP_CNTL));
-	dev_info(adev->dev, "  CG_DISPLAY_GAP_CNTL2=0x%08X\n",
-		 RREG32_SMC(ixCG_DISPLAY_GAP_CNTL2));
-	dev_info(adev->dev, "  CG_STATIC_SCREEN_PARAMETER=0x%08X\n",
-		 RREG32_SMC(ixCG_STATIC_SCREEN_PARAMETER));
-	dev_info(adev->dev, "  CG_FREQ_TRAN_VOTING_0=0x%08X\n",
-		 RREG32_SMC(ixCG_FREQ_TRAN_VOTING_0));
-	dev_info(adev->dev, "  CG_FREQ_TRAN_VOTING_1=0x%08X\n",
-		 RREG32_SMC(ixCG_FREQ_TRAN_VOTING_1));
-	dev_info(adev->dev, "  CG_FREQ_TRAN_VOTING_2=0x%08X\n",
-		 RREG32_SMC(ixCG_FREQ_TRAN_VOTING_2));
-	dev_info(adev->dev, "  CG_FREQ_TRAN_VOTING_3=0x%08X\n",
-		 RREG32_SMC(ixCG_FREQ_TRAN_VOTING_3));
-	dev_info(adev->dev, "  CG_FREQ_TRAN_VOTING_4=0x%08X\n",
-		 RREG32_SMC(ixCG_FREQ_TRAN_VOTING_4));
-	dev_info(adev->dev, "  CG_FREQ_TRAN_VOTING_5=0x%08X\n",
-		 RREG32_SMC(ixCG_FREQ_TRAN_VOTING_5));
-	dev_info(adev->dev, "  CG_FREQ_TRAN_VOTING_6=0x%08X\n",
-		 RREG32_SMC(ixCG_FREQ_TRAN_VOTING_6));
-	dev_info(adev->dev, "  CG_FREQ_TRAN_VOTING_7=0x%08X\n",
-		 RREG32_SMC(ixCG_FREQ_TRAN_VOTING_7));
-	dev_info(adev->dev, "  RCU_UC_EVENTS=0x%08X\n",
-		 RREG32_SMC(ixRCU_UC_EVENTS));
-	dev_info(adev->dev, "  DPM_TABLE_475=0x%08X\n",
-		 RREG32_SMC(ixDPM_TABLE_475));
-	dev_info(adev->dev, "  MC_SEQ_RAS_TIMING_LP=0x%08X\n",
-		 RREG32(mmMC_SEQ_RAS_TIMING_LP));
-	dev_info(adev->dev, "  MC_SEQ_RAS_TIMING=0x%08X\n",
-		 RREG32(mmMC_SEQ_RAS_TIMING));
-	dev_info(adev->dev, "  MC_SEQ_CAS_TIMING_LP=0x%08X\n",
-		 RREG32(mmMC_SEQ_CAS_TIMING_LP));
-	dev_info(adev->dev, "  MC_SEQ_CAS_TIMING=0x%08X\n",
-		 RREG32(mmMC_SEQ_CAS_TIMING));
-	dev_info(adev->dev, "  MC_SEQ_DLL_STBY_LP=0x%08X\n",
-		 RREG32(mmMC_SEQ_DLL_STBY_LP));
-	dev_info(adev->dev, "  MC_SEQ_DLL_STBY=0x%08X\n",
-		 RREG32(mmMC_SEQ_DLL_STBY));
-	dev_info(adev->dev, "  MC_SEQ_G5PDX_CMD0_LP=0x%08X\n",
-		 RREG32(mmMC_SEQ_G5PDX_CMD0_LP));
-	dev_info(adev->dev, "  MC_SEQ_G5PDX_CMD0=0x%08X\n",
-		 RREG32(mmMC_SEQ_G5PDX_CMD0));
-	dev_info(adev->dev, "  MC_SEQ_G5PDX_CMD1_LP=0x%08X\n",
-		 RREG32(mmMC_SEQ_G5PDX_CMD1_LP));
-	dev_info(adev->dev, "  MC_SEQ_G5PDX_CMD1=0x%08X\n",
-		 RREG32(mmMC_SEQ_G5PDX_CMD1));
-	dev_info(adev->dev, "  MC_SEQ_G5PDX_CTRL_LP=0x%08X\n",
-		 RREG32(mmMC_SEQ_G5PDX_CTRL_LP));
-	dev_info(adev->dev, "  MC_SEQ_G5PDX_CTRL=0x%08X\n",
-		 RREG32(mmMC_SEQ_G5PDX_CTRL));
-	dev_info(adev->dev, "  MC_SEQ_PMG_DVS_CMD_LP=0x%08X\n",
-		 RREG32(mmMC_SEQ_PMG_DVS_CMD_LP));
-	dev_info(adev->dev, "  MC_SEQ_PMG_DVS_CMD=0x%08X\n",
-		 RREG32(mmMC_SEQ_PMG_DVS_CMD));
-	dev_info(adev->dev, "  MC_SEQ_PMG_DVS_CTL_LP=0x%08X\n",
-		 RREG32(mmMC_SEQ_PMG_DVS_CTL_LP));
-	dev_info(adev->dev, "  MC_SEQ_PMG_DVS_CTL=0x%08X\n",
-		 RREG32(mmMC_SEQ_PMG_DVS_CTL));
-	dev_info(adev->dev, "  MC_SEQ_MISC_TIMING_LP=0x%08X\n",
-		 RREG32(mmMC_SEQ_MISC_TIMING_LP));
-	dev_info(adev->dev, "  MC_SEQ_MISC_TIMING=0x%08X\n",
-		 RREG32(mmMC_SEQ_MISC_TIMING));
-	dev_info(adev->dev, "  MC_SEQ_MISC_TIMING2_LP=0x%08X\n",
-		 RREG32(mmMC_SEQ_MISC_TIMING2_LP));
-	dev_info(adev->dev, "  MC_SEQ_MISC_TIMING2=0x%08X\n",
-		 RREG32(mmMC_SEQ_MISC_TIMING2));
-	dev_info(adev->dev, "  MC_SEQ_PMG_CMD_EMRS_LP=0x%08X\n",
-		 RREG32(mmMC_SEQ_PMG_CMD_EMRS_LP));
-	dev_info(adev->dev, "  MC_PMG_CMD_EMRS=0x%08X\n",
-		 RREG32(mmMC_PMG_CMD_EMRS));
-	dev_info(adev->dev, "  MC_SEQ_PMG_CMD_MRS_LP=0x%08X\n",
-		 RREG32(mmMC_SEQ_PMG_CMD_MRS_LP));
-	dev_info(adev->dev, "  MC_PMG_CMD_MRS=0x%08X\n",
-		 RREG32(mmMC_PMG_CMD_MRS));
-	dev_info(adev->dev, "  MC_SEQ_PMG_CMD_MRS1_LP=0x%08X\n",
-		 RREG32(mmMC_SEQ_PMG_CMD_MRS1_LP));
-	dev_info(adev->dev, "  MC_PMG_CMD_MRS1=0x%08X\n",
-		 RREG32(mmMC_PMG_CMD_MRS1));
-	dev_info(adev->dev, "  MC_SEQ_WR_CTL_D0_LP=0x%08X\n",
-		 RREG32(mmMC_SEQ_WR_CTL_D0_LP));
-	dev_info(adev->dev, "  MC_SEQ_WR_CTL_D0=0x%08X\n",
-		 RREG32(mmMC_SEQ_WR_CTL_D0));
-	dev_info(adev->dev, "  MC_SEQ_WR_CTL_D1_LP=0x%08X\n",
-		 RREG32(mmMC_SEQ_WR_CTL_D1_LP));
-	dev_info(adev->dev, "  MC_SEQ_WR_CTL_D1=0x%08X\n",
-		 RREG32(mmMC_SEQ_WR_CTL_D1));
-	dev_info(adev->dev, "  MC_SEQ_RD_CTL_D0_LP=0x%08X\n",
-		 RREG32(mmMC_SEQ_RD_CTL_D0_LP));
-	dev_info(adev->dev, "  MC_SEQ_RD_CTL_D0=0x%08X\n",
-		 RREG32(mmMC_SEQ_RD_CTL_D0));
-	dev_info(adev->dev, "  MC_SEQ_RD_CTL_D1_LP=0x%08X\n",
-		 RREG32(mmMC_SEQ_RD_CTL_D1_LP));
-	dev_info(adev->dev, "  MC_SEQ_RD_CTL_D1=0x%08X\n",
-		 RREG32(mmMC_SEQ_RD_CTL_D1));
-	dev_info(adev->dev, "  MC_SEQ_PMG_TIMING_LP=0x%08X\n",
-		 RREG32(mmMC_SEQ_PMG_TIMING_LP));
-	dev_info(adev->dev, "  MC_SEQ_PMG_TIMING=0x%08X\n",
-		 RREG32(mmMC_SEQ_PMG_TIMING));
-	dev_info(adev->dev, "  MC_SEQ_PMG_CMD_MRS2_LP=0x%08X\n",
-		 RREG32(mmMC_SEQ_PMG_CMD_MRS2_LP));
-	dev_info(adev->dev, "  MC_PMG_CMD_MRS2=0x%08X\n",
-		 RREG32(mmMC_PMG_CMD_MRS2));
-	dev_info(adev->dev, "  MC_SEQ_WR_CTL_2_LP=0x%08X\n",
-		 RREG32(mmMC_SEQ_WR_CTL_2_LP));
-	dev_info(adev->dev, "  MC_SEQ_WR_CTL_2=0x%08X\n",
-		 RREG32(mmMC_SEQ_WR_CTL_2));
-	dev_info(adev->dev, "  PCIE_LC_SPEED_CNTL=0x%08X\n",
-		 RREG32_PCIE(ixPCIE_LC_SPEED_CNTL));
-	dev_info(adev->dev, "  PCIE_LC_LINK_WIDTH_CNTL=0x%08X\n",
-		 RREG32_PCIE(ixPCIE_LC_LINK_WIDTH_CNTL));
-	dev_info(adev->dev, "  SMC_IND_INDEX_0=0x%08X\n",
-		 RREG32(mmSMC_IND_INDEX_0));
-	dev_info(adev->dev, "  SMC_IND_DATA_0=0x%08X\n",
-		 RREG32(mmSMC_IND_DATA_0));
-	dev_info(adev->dev, "  SMC_IND_ACCESS_CNTL=0x%08X\n",
-		 RREG32(mmSMC_IND_ACCESS_CNTL));
-	dev_info(adev->dev, "  SMC_RESP_0=0x%08X\n",
-		 RREG32(mmSMC_RESP_0));
-	dev_info(adev->dev, "  SMC_MESSAGE_0=0x%08X\n",
-		 RREG32(mmSMC_MESSAGE_0));
-	dev_info(adev->dev, "  SMC_SYSCON_RESET_CNTL=0x%08X\n",
-		 RREG32_SMC(ixSMC_SYSCON_RESET_CNTL));
-	dev_info(adev->dev, "  SMC_SYSCON_CLOCK_CNTL_0=0x%08X\n",
-		 RREG32_SMC(ixSMC_SYSCON_CLOCK_CNTL_0));
-	dev_info(adev->dev, "  SMC_SYSCON_MISC_CNTL=0x%08X\n",
-		 RREG32_SMC(ixSMC_SYSCON_MISC_CNTL));
-	dev_info(adev->dev, "  SMC_PC_C=0x%08X\n",
-		 RREG32_SMC(ixSMC_PC_C));
-}
-
 static int ci_dpm_soft_reset(void *handle)
 {
 	return 0;
@@ -6571,7 +6362,7 @@ static int ci_dpm_set_interrupt_state(st
 }
 
 static int ci_dpm_process_interrupt(struct amdgpu_device *adev,
-				    struct amdgpu_irq_src *source, 
+				    struct amdgpu_irq_src *source,
 				    struct amdgpu_iv_entry *entry)
 {
 	bool queue_thermal = false;
@@ -6613,6 +6404,7 @@ static int ci_dpm_set_powergating_state(
 }
 
 const struct amd_ip_funcs ci_dpm_ip_funcs = {
+	.name = "ci_dpm",
 	.early_init = ci_dpm_early_init,
 	.late_init = ci_dpm_late_init,
 	.sw_init = ci_dpm_sw_init,
@@ -6624,7 +6416,6 @@ const struct amd_ip_funcs ci_dpm_ip_func
 	.is_idle = ci_dpm_is_idle,
 	.wait_for_idle = ci_dpm_wait_for_idle,
 	.soft_reset = ci_dpm_soft_reset,
-	.print_status = ci_dpm_print_status,
 	.set_clockgating_state = ci_dpm_set_clockgating_state,
 	.set_powergating_state = ci_dpm_set_powergating_state,
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/cik.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/cik.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/cik.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/cik.c	2016-07-24 15:23:50.000000000 -0400
@@ -962,7 +962,13 @@ static bool cik_read_bios_from_rom(struc
 	return true;
 }
 
-static struct amdgpu_allowed_register_entry cik_allowed_read_registers[] = {
+static u32 cik_get_virtual_caps(struct amdgpu_device *adev)
+{
+	/* CIK does not support SR-IOV */
+	return 0;
+}
+
+static const struct amdgpu_allowed_register_entry cik_allowed_read_registers[] = {
 	{mmGRBM_STATUS, false},
 	{mmGB_ADDR_CONFIG, false},
 	{mmMC_ARB_RAMCFG, false},
@@ -2007,7 +2013,7 @@ static const struct amdgpu_asic_funcs ci
 	.get_xclk = &cik_get_xclk,
 	.set_uvd_clocks = &cik_set_uvd_clocks,
 	.set_vce_clocks = &cik_set_vce_clocks,
-	.get_cu_info = &gfx_v7_0_get_cu_info,
+	.get_virtual_caps = &cik_get_virtual_caps,
 	/* these should be moved to their own ip modules */
 	.get_gpu_clock_counter = &gfx_v7_0_get_gpu_clock_counter,
 	.wait_for_mc_idle = &gmc_v7_0_mc_wait_for_idle,
@@ -2214,11 +2220,6 @@ static int cik_common_wait_for_idle(void
 	return 0;
 }
 
-static void cik_common_print_status(void *handle)
-{
-
-}
-
 static int cik_common_soft_reset(void *handle)
 {
 	/* XXX hard reset?? */
@@ -2238,6 +2239,7 @@ static int cik_common_set_powergating_st
 }
 
 const struct amd_ip_funcs cik_common_ip_funcs = {
+	.name = "cik_common",
 	.early_init = cik_common_early_init,
 	.late_init = NULL,
 	.sw_init = cik_common_sw_init,
@@ -2249,7 +2251,6 @@ const struct amd_ip_funcs cik_common_ip_
 	.is_idle = cik_common_is_idle,
 	.wait_for_idle = cik_common_wait_for_idle,
 	.soft_reset = cik_common_soft_reset,
-	.print_status = cik_common_print_status,
 	.set_clockgating_state = cik_common_set_clockgating_state,
 	.set_powergating_state = cik_common_set_powergating_state,
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/cikd.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/cikd.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/cikd.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/cikd.h	2016-07-24 15:23:50.000000000 -0400
@@ -190,8 +190,8 @@
 #       define MACRO_TILE_ASPECT(x)				((x) << 4)
 #       define NUM_BANKS(x)					((x) << 6)
 
-#define		MSG_ENTER_RLC_SAFE_MODE      			1
-#define		MSG_EXIT_RLC_SAFE_MODE      			0
+#define		MSG_ENTER_RLC_SAFE_MODE			1
+#define		MSG_EXIT_RLC_SAFE_MODE			0
 
 /*
  * PM4
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/cik_ih.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/cik_ih.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/cik_ih.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/cik_ih.c	2016-07-24 15:23:50.000000000 -0400
@@ -103,7 +103,6 @@ static void cik_ih_disable_interrupts(st
  */
 static int cik_ih_irq_init(struct amdgpu_device *adev)
 {
-	int ret = 0;
 	int rb_bufsz;
 	u32 interrupt_cntl, ih_cntl, ih_rb_cntl;
 	u64 wptr_off;
@@ -156,7 +155,7 @@ static int cik_ih_irq_init(struct amdgpu
 	/* enable irqs */
 	cik_ih_enable_interrupts(adev);
 
-	return ret;
+	return 0;
 }
 
 /**
@@ -243,7 +242,7 @@ static void cik_ih_decode_iv(struct amdg
 	/* wptr/rptr are in bytes! */
 	u32 ring_index = adev->irq.ih.rptr >> 2;
 	uint32_t dw[4];
-	
+
 	dw[0] = le32_to_cpu(adev->irq.ih.ring[ring_index + 0]);
 	dw[1] = le32_to_cpu(adev->irq.ih.ring[ring_index + 1]);
 	dw[2] = le32_to_cpu(adev->irq.ih.ring[ring_index + 2]);
@@ -372,35 +371,6 @@ static int cik_ih_wait_for_idle(void *ha
 	return -ETIMEDOUT;
 }
 
-static void cik_ih_print_status(void *handle)
-{
-	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-	dev_info(adev->dev, "CIK IH registers\n");
-	dev_info(adev->dev, "  SRBM_STATUS=0x%08X\n",
-		RREG32(mmSRBM_STATUS));
-	dev_info(adev->dev, "  SRBM_STATUS2=0x%08X\n",
-		RREG32(mmSRBM_STATUS2));
-	dev_info(adev->dev, "  INTERRUPT_CNTL=0x%08X\n",
-		 RREG32(mmINTERRUPT_CNTL));
-	dev_info(adev->dev, "  INTERRUPT_CNTL2=0x%08X\n",
-		 RREG32(mmINTERRUPT_CNTL2));
-	dev_info(adev->dev, "  IH_CNTL=0x%08X\n",
-		 RREG32(mmIH_CNTL));
-	dev_info(adev->dev, "  IH_RB_CNTL=0x%08X\n",
-		 RREG32(mmIH_RB_CNTL));
-	dev_info(adev->dev, "  IH_RB_BASE=0x%08X\n",
-		 RREG32(mmIH_RB_BASE));
-	dev_info(adev->dev, "  IH_RB_WPTR_ADDR_LO=0x%08X\n",
-		 RREG32(mmIH_RB_WPTR_ADDR_LO));
-	dev_info(adev->dev, "  IH_RB_WPTR_ADDR_HI=0x%08X\n",
-		 RREG32(mmIH_RB_WPTR_ADDR_HI));
-	dev_info(adev->dev, "  IH_RB_RPTR=0x%08X\n",
-		 RREG32(mmIH_RB_RPTR));
-	dev_info(adev->dev, "  IH_RB_WPTR=0x%08X\n",
-		 RREG32(mmIH_RB_WPTR));
-}
-
 static int cik_ih_soft_reset(void *handle)
 {
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
@@ -412,8 +382,6 @@ static int cik_ih_soft_reset(void *handl
 		srbm_soft_reset |= SRBM_SOFT_RESET__SOFT_RESET_IH_MASK;
 
 	if (srbm_soft_reset) {
-		cik_ih_print_status((void *)adev);
-
 		tmp = RREG32(mmSRBM_SOFT_RESET);
 		tmp |= srbm_soft_reset;
 		dev_info(adev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp);
@@ -428,8 +396,6 @@ static int cik_ih_soft_reset(void *handl
 
 		/* Wait a little for things to settle down */
 		udelay(50);
-
-		cik_ih_print_status((void *)adev);
 	}
 
 	return 0;
@@ -448,6 +414,7 @@ static int cik_ih_set_powergating_state(
 }
 
 const struct amd_ip_funcs cik_ih_ip_funcs = {
+	.name = "cik_ih",
 	.early_init = cik_ih_early_init,
 	.late_init = NULL,
 	.sw_init = cik_ih_sw_init,
@@ -459,7 +426,6 @@ const struct amd_ip_funcs cik_ih_ip_func
 	.is_idle = cik_ih_is_idle,
 	.wait_for_idle = cik_ih_wait_for_idle,
 	.soft_reset = cik_ih_soft_reset,
-	.print_status = cik_ih_print_status,
 	.set_clockgating_state = cik_ih_set_clockgating_state,
 	.set_powergating_state = cik_ih_set_powergating_state,
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/cik_sdma.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/cik_sdma.c	2016-05-15 19:21:14.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/cik_sdma.c	2016-07-24 18:17:46.000000000 -0400
@@ -57,6 +57,16 @@ static void cik_sdma_set_vm_pte_funcs(st
 
 u32 amdgpu_cik_gpu_check_soft_reset(struct amdgpu_device *adev);
 
+
+static void cik_sdma_free_microcode(struct amdgpu_device *adev)
+{
+	int i;
+	for (i = 0; i < adev->sdma.num_instances; i++) {
+			release_firmware(adev->sdma.instance[i].fw);
+			adev->sdma.instance[i].fw = NULL;
+	}
+}
+
 /*
  * sDMA - System DMA
  * Starting with CIK, the GPU has new asynchronous
@@ -201,9 +211,10 @@ static void cik_sdma_ring_insert_nop(str
  * Schedule an IB in the DMA ring (CIK).
  */
 static void cik_sdma_ring_emit_ib(struct amdgpu_ring *ring,
-			   struct amdgpu_ib *ib)
+				  struct amdgpu_ib *ib,
+				  unsigned vm_id, bool ctx_switch)
 {
-	u32 extra_bits = ib->vm_id & 0xf;
+	u32 extra_bits = vm_id & 0xf;
 	u32 next_rptr = ring->wptr + 5;
 
 	while ((next_rptr & 7) != 4)
@@ -409,6 +420,8 @@ static int cik_sdma_gfx_resume(struct am
 		/* Initialize the ring buffer's read and write pointers */
 		WREG32(mmSDMA0_GFX_RB_RPTR + sdma_offsets[i], 0);
 		WREG32(mmSDMA0_GFX_RB_WPTR + sdma_offsets[i], 0);
+		WREG32(mmSDMA0_GFX_IB_RPTR + sdma_offsets[i], 0);
+		WREG32(mmSDMA0_GFX_IB_OFFSET + sdma_offsets[i], 0);
 
 		/* set the wb address whether it's enabled or not */
 		WREG32(mmSDMA0_GFX_RB_RPTR_ADDR_HI + sdma_offsets[i],
@@ -436,7 +449,12 @@ static int cik_sdma_gfx_resume(struct am
 		WREG32(mmSDMA0_GFX_IB_CNTL + sdma_offsets[i], ib_cntl);
 
 		ring->ready = true;
+	}
+
+	cik_sdma_enable(adev, true);
 
+	for (i = 0; i < adev->sdma.num_instances; i++) {
+		ring = &adev->sdma.instance[i].ring;
 		r = amdgpu_ring_test_ring(ring);
 		if (r) {
 			ring->ready = false;
@@ -519,8 +537,8 @@ static int cik_sdma_start(struct amdgpu_
 	if (r)
 		return r;
 
-	/* unhalt the MEs */
-	cik_sdma_enable(adev, true);
+	/* halt the engine before programing */
+	cik_sdma_enable(adev, false);
 
 	/* start the gfx rings and rlc compute queues */
 	r = cik_sdma_gfx_resume(adev);
@@ -634,7 +652,7 @@ static int cik_sdma_ring_test_ib(struct
 	ib.ptr[3] = 1;
 	ib.ptr[4] = 0xDEADBEEF;
 	ib.length_dw = 5;
-	r = amdgpu_ib_schedule(ring, 1, &ib, NULL, &f);
+	r = amdgpu_ib_schedule(ring, 1, &ib, NULL, NULL, &f);
 	if (r)
 		goto err1;
 
@@ -967,7 +985,7 @@ static int cik_sdma_sw_init(void *handle
 		ring = &adev->sdma.instance[i].ring;
 		ring->ring_obj = NULL;
 		sprintf(ring->name, "sdma%d", i);
-		r = amdgpu_ring_init(adev, ring, 256 * 1024,
+		r = amdgpu_ring_init(adev, ring, 1024,
 				     SDMA_PACKET(SDMA_OPCODE_NOP, 0, 0), 0xf,
 				     &adev->sdma.trap_irq,
 				     (i == 0) ?
@@ -988,6 +1006,7 @@ static int cik_sdma_sw_fini(void *handle
 	for (i = 0; i < adev->sdma.num_instances; i++)
 		amdgpu_ring_fini(&adev->sdma.instance[i].ring);
 
+	cik_sdma_free_microcode(adev);
 	return 0;
 }
 
@@ -1055,57 +1074,6 @@ static int cik_sdma_wait_for_idle(void *
 	return -ETIMEDOUT;
 }
 
-static void cik_sdma_print_status(void *handle)
-{
-	int i, j;
-	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-	dev_info(adev->dev, "CIK SDMA registers\n");
-	dev_info(adev->dev, "  SRBM_STATUS2=0x%08X\n",
-		 RREG32(mmSRBM_STATUS2));
-	for (i = 0; i < adev->sdma.num_instances; i++) {
-		dev_info(adev->dev, "  SDMA%d_STATUS_REG=0x%08X\n",
-			 i, RREG32(mmSDMA0_STATUS_REG + sdma_offsets[i]));
-		dev_info(adev->dev, "  SDMA%d_ME_CNTL=0x%08X\n",
-			 i, RREG32(mmSDMA0_F32_CNTL + sdma_offsets[i]));
-		dev_info(adev->dev, "  SDMA%d_CNTL=0x%08X\n",
-			 i, RREG32(mmSDMA0_CNTL + sdma_offsets[i]));
-		dev_info(adev->dev, "  SDMA%d_SEM_INCOMPLETE_TIMER_CNTL=0x%08X\n",
-			 i, RREG32(mmSDMA0_SEM_INCOMPLETE_TIMER_CNTL + sdma_offsets[i]));
-		dev_info(adev->dev, "  SDMA%d_SEM_WAIT_FAIL_TIMER_CNTL=0x%08X\n",
-			 i, RREG32(mmSDMA0_SEM_WAIT_FAIL_TIMER_CNTL + sdma_offsets[i]));
-		dev_info(adev->dev, "  SDMA%d_GFX_IB_CNTL=0x%08X\n",
-			 i, RREG32(mmSDMA0_GFX_IB_CNTL + sdma_offsets[i]));
-		dev_info(adev->dev, "  SDMA%d_GFX_RB_CNTL=0x%08X\n",
-			 i, RREG32(mmSDMA0_GFX_RB_CNTL + sdma_offsets[i]));
-		dev_info(adev->dev, "  SDMA%d_GFX_RB_RPTR=0x%08X\n",
-			 i, RREG32(mmSDMA0_GFX_RB_RPTR + sdma_offsets[i]));
-		dev_info(adev->dev, "  SDMA%d_GFX_RB_WPTR=0x%08X\n",
-			 i, RREG32(mmSDMA0_GFX_RB_WPTR + sdma_offsets[i]));
-		dev_info(adev->dev, "  SDMA%d_GFX_RB_RPTR_ADDR_HI=0x%08X\n",
-			 i, RREG32(mmSDMA0_GFX_RB_RPTR_ADDR_HI + sdma_offsets[i]));
-		dev_info(adev->dev, "  SDMA%d_GFX_RB_RPTR_ADDR_LO=0x%08X\n",
-			 i, RREG32(mmSDMA0_GFX_RB_RPTR_ADDR_LO + sdma_offsets[i]));
-		dev_info(adev->dev, "  SDMA%d_GFX_RB_BASE=0x%08X\n",
-			 i, RREG32(mmSDMA0_GFX_RB_BASE + sdma_offsets[i]));
-		dev_info(adev->dev, "  SDMA%d_GFX_RB_BASE_HI=0x%08X\n",
-			 i, RREG32(mmSDMA0_GFX_RB_BASE_HI + sdma_offsets[i]));
-		dev_info(adev->dev, "  SDMA%d_TILING_CONFIG=0x%08X\n",
-			 i, RREG32(mmSDMA0_TILING_CONFIG + sdma_offsets[i]));
-		mutex_lock(&adev->srbm_mutex);
-		for (j = 0; j < 16; j++) {
-			cik_srbm_select(adev, 0, 0, 0, j);
-			dev_info(adev->dev, "  VM %d:\n", j);
-			dev_info(adev->dev, "  SDMA0_GFX_VIRTUAL_ADDR=0x%08X\n",
-				 RREG32(mmSDMA0_GFX_VIRTUAL_ADDR + sdma_offsets[i]));
-			dev_info(adev->dev, "  SDMA0_GFX_APE1_CNTL=0x%08X\n",
-				 RREG32(mmSDMA0_GFX_APE1_CNTL + sdma_offsets[i]));
-		}
-		cik_srbm_select(adev, 0, 0, 0, 0);
-		mutex_unlock(&adev->srbm_mutex);
-	}
-}
-
 static int cik_sdma_soft_reset(void *handle)
 {
 	u32 srbm_soft_reset = 0;
@@ -1128,8 +1096,6 @@ static int cik_sdma_soft_reset(void *han
 	}
 
 	if (srbm_soft_reset) {
-		cik_sdma_print_status((void *)adev);
-
 		tmp = RREG32(mmSRBM_SOFT_RESET);
 		tmp |= srbm_soft_reset;
 		dev_info(adev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp);
@@ -1144,8 +1110,6 @@ static int cik_sdma_soft_reset(void *han
 
 		/* Wait a little for things to settle down */
 		udelay(50);
-
-		cik_sdma_print_status((void *)adev);
 	}
 
 	return 0;
@@ -1269,6 +1233,7 @@ static int cik_sdma_set_powergating_stat
 }
 
 const struct amd_ip_funcs cik_sdma_ip_funcs = {
+	.name = "cik_sdma",
 	.early_init = cik_sdma_early_init,
 	.late_init = NULL,
 	.sw_init = cik_sdma_sw_init,
@@ -1280,7 +1245,6 @@ const struct amd_ip_funcs cik_sdma_ip_fu
 	.is_idle = cik_sdma_is_idle,
 	.wait_for_idle = cik_sdma_wait_for_idle,
 	.soft_reset = cik_sdma_soft_reset,
-	.print_status = cik_sdma_print_status,
 	.set_clockgating_state = cik_sdma_set_clockgating_state,
 	.set_powergating_state = cik_sdma_set_powergating_state,
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/cz_dpm.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/cz_dpm.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/cz_dpm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/cz_dpm.c	2016-07-24 15:23:50.000000000 -0400
@@ -1579,7 +1579,6 @@ static int cz_dpm_update_sclk_limit(stru
 
 static int cz_dpm_set_deep_sleep_sclk_threshold(struct amdgpu_device *adev)
 {
-	int ret = 0;
 	struct cz_power_info *pi = cz_get_pi(adev);
 
 	if (pi->caps_sclk_ds) {
@@ -1588,20 +1587,19 @@ static int cz_dpm_set_deep_sleep_sclk_th
 				CZ_MIN_DEEP_SLEEP_SCLK);
 	}
 
-	return ret;
+	return 0;
 }
 
 /* ?? without dal support, is this still needed in setpowerstate list*/
 static int cz_dpm_set_watermark_threshold(struct amdgpu_device *adev)
 {
-	int ret = 0;
 	struct cz_power_info *pi = cz_get_pi(adev);
 
 	cz_send_msg_to_smc_with_parameter(adev,
 			PPSMC_MSG_SetWatermarkFrequency,
 			pi->sclk_dpm.soft_max_clk);
 
-	return ret;
+	return 0;
 }
 
 static int cz_dpm_enable_nbdpm(struct amdgpu_device *adev)
@@ -1636,7 +1634,6 @@ static void cz_dpm_nbdpm_lm_pstate_enabl
 
 static int cz_dpm_update_low_memory_pstate(struct amdgpu_device *adev)
 {
-	int ret = 0;
 	struct cz_power_info *pi = cz_get_pi(adev);
 	struct cz_ps *ps = &pi->requested_ps;
 
@@ -1647,21 +1644,19 @@ static int cz_dpm_update_low_memory_psta
 			cz_dpm_nbdpm_lm_pstate_enable(adev, true);
 	}
 
-	return ret;
+	return 0;
 }
 
 /* with dpm enabled */
 static int cz_dpm_set_power_state(struct amdgpu_device *adev)
 {
-	int ret = 0;
-
 	cz_dpm_update_sclk_limit(adev);
 	cz_dpm_set_deep_sleep_sclk_threshold(adev);
 	cz_dpm_set_watermark_threshold(adev);
 	cz_dpm_enable_nbdpm(adev);
 	cz_dpm_update_low_memory_pstate(adev);
 
-	return ret;
+	return 0;
 }
 
 static void cz_dpm_post_set_power_state(struct amdgpu_device *adev)
@@ -2230,6 +2225,7 @@ static void cz_dpm_powergate_vce(struct
 }
 
 const struct amd_ip_funcs cz_dpm_ip_funcs = {
+	.name = "cz_dpm",
 	.early_init = cz_dpm_early_init,
 	.late_init = cz_dpm_late_init,
 	.sw_init = cz_dpm_sw_init,
@@ -2241,7 +2237,6 @@ const struct amd_ip_funcs cz_dpm_ip_func
 	.is_idle = NULL,
 	.wait_for_idle = NULL,
 	.soft_reset = NULL,
-	.print_status = NULL,
 	.set_clockgating_state = cz_dpm_set_clockgating_state,
 	.set_powergating_state = cz_dpm_set_powergating_state,
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/cz_ih.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/cz_ih.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/cz_ih.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/cz_ih.c	2016-07-24 15:23:50.000000000 -0400
@@ -103,7 +103,6 @@ static void cz_ih_disable_interrupts(str
  */
 static int cz_ih_irq_init(struct amdgpu_device *adev)
 {
-	int ret = 0;
 	int rb_bufsz;
 	u32 interrupt_cntl, ih_cntl, ih_rb_cntl;
 	u64 wptr_off;
@@ -157,7 +156,7 @@ static int cz_ih_irq_init(struct amdgpu_
 	/* enable interrupts */
 	cz_ih_enable_interrupts(adev);
 
-	return ret;
+	return 0;
 }
 
 /**
@@ -222,7 +221,7 @@ static void cz_ih_decode_iv(struct amdgp
 	/* wptr/rptr are in bytes! */
 	u32 ring_index = adev->irq.ih.rptr >> 2;
 	uint32_t dw[4];
-	
+
 	dw[0] = le32_to_cpu(adev->irq.ih.ring[ring_index + 0]);
 	dw[1] = le32_to_cpu(adev->irq.ih.ring[ring_index + 1]);
 	dw[2] = le32_to_cpu(adev->irq.ih.ring[ring_index + 2]);
@@ -351,35 +350,6 @@ static int cz_ih_wait_for_idle(void *han
 	return -ETIMEDOUT;
 }
 
-static void cz_ih_print_status(void *handle)
-{
-	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-	dev_info(adev->dev, "CZ IH registers\n");
-	dev_info(adev->dev, "  SRBM_STATUS=0x%08X\n",
-		RREG32(mmSRBM_STATUS));
-	dev_info(adev->dev, "  SRBM_STATUS2=0x%08X\n",
-		RREG32(mmSRBM_STATUS2));
-	dev_info(adev->dev, "  INTERRUPT_CNTL=0x%08X\n",
-		 RREG32(mmINTERRUPT_CNTL));
-	dev_info(adev->dev, "  INTERRUPT_CNTL2=0x%08X\n",
-		 RREG32(mmINTERRUPT_CNTL2));
-	dev_info(adev->dev, "  IH_CNTL=0x%08X\n",
-		 RREG32(mmIH_CNTL));
-	dev_info(adev->dev, "  IH_RB_CNTL=0x%08X\n",
-		 RREG32(mmIH_RB_CNTL));
-	dev_info(adev->dev, "  IH_RB_BASE=0x%08X\n",
-		 RREG32(mmIH_RB_BASE));
-	dev_info(adev->dev, "  IH_RB_WPTR_ADDR_LO=0x%08X\n",
-		 RREG32(mmIH_RB_WPTR_ADDR_LO));
-	dev_info(adev->dev, "  IH_RB_WPTR_ADDR_HI=0x%08X\n",
-		 RREG32(mmIH_RB_WPTR_ADDR_HI));
-	dev_info(adev->dev, "  IH_RB_RPTR=0x%08X\n",
-		 RREG32(mmIH_RB_RPTR));
-	dev_info(adev->dev, "  IH_RB_WPTR=0x%08X\n",
-		 RREG32(mmIH_RB_WPTR));
-}
-
 static int cz_ih_soft_reset(void *handle)
 {
 	u32 srbm_soft_reset = 0;
@@ -391,8 +361,6 @@ static int cz_ih_soft_reset(void *handle
 						SOFT_RESET_IH, 1);
 
 	if (srbm_soft_reset) {
-		cz_ih_print_status((void *)adev);
-
 		tmp = RREG32(mmSRBM_SOFT_RESET);
 		tmp |= srbm_soft_reset;
 		dev_info(adev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp);
@@ -407,8 +375,6 @@ static int cz_ih_soft_reset(void *handle
 
 		/* Wait a little for things to settle down */
 		udelay(50);
-
-		cz_ih_print_status((void *)adev);
 	}
 
 	return 0;
@@ -429,6 +395,7 @@ static int cz_ih_set_powergating_state(v
 }
 
 const struct amd_ip_funcs cz_ih_ip_funcs = {
+	.name = "cz_ih",
 	.early_init = cz_ih_early_init,
 	.late_init = NULL,
 	.sw_init = cz_ih_sw_init,
@@ -440,7 +407,6 @@ const struct amd_ip_funcs cz_ih_ip_funcs
 	.is_idle = cz_ih_is_idle,
 	.wait_for_idle = cz_ih_wait_for_idle,
 	.soft_reset = cz_ih_soft_reset,
-	.print_status = cz_ih_print_status,
 	.set_clockgating_state = cz_ih_set_clockgating_state,
 	.set_powergating_state = cz_ih_set_powergating_state,
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/cz_smumgr.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/cz_smumgr.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/cz_smumgr.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/cz_smumgr.h	2016-07-24 15:23:50.000000000 -0400
@@ -77,7 +77,7 @@ struct cz_smu_private_data {
 	uint8_t		driver_buffer_length;
 	uint8_t		scratch_buffer_length;
 	uint16_t	toc_entry_used_count;
-	uint16_t 	toc_entry_initialize_index;
+	uint16_t	toc_entry_initialize_index;
 	uint16_t	toc_entry_power_profiling_index;
 	uint16_t	toc_entry_aram;
 	uint16_t	toc_entry_ih_register_restore_task_index;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c	2016-07-24 15:23:50.000000000 -0400
@@ -284,10 +284,16 @@ static void dce_v10_0_pageflip_interrupt
  * surface base address.
  */
 static void dce_v10_0_page_flip(struct amdgpu_device *adev,
-			      int crtc_id, u64 crtc_base)
+				int crtc_id, u64 crtc_base, bool async)
 {
 	struct amdgpu_crtc *amdgpu_crtc = adev->mode_info.crtcs[crtc_id];
+	u32 tmp;
 
+	/* flip at hsync for async, default is vsync */
+	tmp = RREG32(mmGRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset);
+	tmp = REG_SET_FIELD(tmp, GRPH_FLIP_CONTROL,
+			    GRPH_SURFACE_UPDATE_H_RETRACE_EN, async ? 1 : 0);
+	WREG32(mmGRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset, tmp);
 	/* update the primary scanout address */
 	WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
 	       upper_32_bits(crtc_base));
@@ -2211,6 +2217,14 @@ static int dce_v10_0_crtc_do_set_base(st
 
 	dce_v10_0_vga_enable(crtc, false);
 
+	/* Make sure surface address is updated at vertical blank rather than
+	 * horizontal blank
+	 */
+	tmp = RREG32(mmGRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset);
+	tmp = REG_SET_FIELD(tmp, GRPH_FLIP_CONTROL,
+			    GRPH_SURFACE_UPDATE_H_RETRACE_EN, 0);
+	WREG32(mmGRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset, tmp);
+
 	WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
 	       upper_32_bits(fb_location));
 	WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
@@ -2261,13 +2275,6 @@ static int dce_v10_0_crtc_do_set_base(st
 	WREG32(mmVIEWPORT_SIZE + amdgpu_crtc->crtc_offset,
 	       (viewport_w << 16) | viewport_h);
 
-	/* pageflip setup */
-	/* make sure flip is at vb rather than hb */
-	tmp = RREG32(mmGRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset);
-	tmp = REG_SET_FIELD(tmp, GRPH_FLIP_CONTROL,
-			    GRPH_SURFACE_UPDATE_H_RETRACE_EN, 0);
-	WREG32(mmGRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset, tmp);
-
 	/* set pageflip to happen only at start of vblank interval (front porch) */
 	WREG32(mmMASTER_UPDATE_MODE + amdgpu_crtc->crtc_offset, 3);
 
@@ -2587,7 +2594,7 @@ static int dce_v10_0_crtc_cursor_set2(st
 		return -EINVAL;
 	}
 
-	obj = drm_gem_object_lookup(crtc->dev, file_priv, handle);
+	obj = drm_gem_object_lookup(file_priv, handle);
 	if (!obj) {
 		DRM_ERROR("Cannot find cursor object %x for crtc %d\n", handle, amdgpu_crtc->crtc_id);
 		return -ENOENT;
@@ -2992,6 +2999,8 @@ static int dce_v10_0_sw_init(void *handl
 
 	adev->ddev->mode_config.funcs = &amdgpu_mode_funcs;
 
+	adev->ddev->mode_config.async_page_flip = true;
+
 	adev->ddev->mode_config.max_width = 16384;
 	adev->ddev->mode_config.max_height = 16384;
 
@@ -3130,14 +3139,6 @@ static int dce_v10_0_wait_for_idle(void
 	return 0;
 }
 
-static void dce_v10_0_print_status(void *handle)
-{
-	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-	dev_info(adev->dev, "DCE 10.x registers\n");
-	/* XXX todo */
-}
-
 static int dce_v10_0_soft_reset(void *handle)
 {
 	u32 srbm_soft_reset = 0, tmp;
@@ -3147,8 +3148,6 @@ static int dce_v10_0_soft_reset(void *ha
 		srbm_soft_reset |= SRBM_SOFT_RESET__SOFT_RESET_DC_MASK;
 
 	if (srbm_soft_reset) {
-		dce_v10_0_print_status((void *)adev);
-
 		tmp = RREG32(mmSRBM_SOFT_RESET);
 		tmp |= srbm_soft_reset;
 		dev_info(adev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp);
@@ -3163,7 +3162,6 @@ static int dce_v10_0_soft_reset(void *ha
 
 		/* Wait a little for things to settle down */
 		udelay(50);
-		dce_v10_0_print_status((void *)adev);
 	}
 	return 0;
 }
@@ -3370,7 +3368,7 @@ static int dce_v10_0_pageflip_irq(struct
 
 	/* wakeup usersapce */
 	if (works->event)
-		drm_send_vblank_event(adev->ddev, crtc_id, works->event);
+		drm_crtc_send_vblank_event(&amdgpu_crtc->base, works->event);
 
 	spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
 
@@ -3501,6 +3499,7 @@ static int dce_v10_0_set_powergating_sta
 }
 
 const struct amd_ip_funcs dce_v10_0_ip_funcs = {
+	.name = "dce_v10_0",
 	.early_init = dce_v10_0_early_init,
 	.late_init = NULL,
 	.sw_init = dce_v10_0_sw_init,
@@ -3512,7 +3511,6 @@ const struct amd_ip_funcs dce_v10_0_ip_f
 	.is_idle = dce_v10_0_is_idle,
 	.wait_for_idle = dce_v10_0_wait_for_idle,
 	.soft_reset = dce_v10_0_soft_reset,
-	.print_status = dce_v10_0_print_status,
 	.set_clockgating_state = dce_v10_0_set_clockgating_state,
 	.set_powergating_state = dce_v10_0_set_powergating_state,
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c	2016-07-24 15:23:50.000000000 -0400
@@ -132,6 +132,22 @@ static const u32 stoney_golden_settings_
 	mmFBC_MISC, 0x1f311fff, 0x14302000,
 };
 
+static const u32 polaris11_golden_settings_a11[] =
+{
+	mmDCI_CLK_CNTL, 0x00000080, 0x00000000,
+	mmFBC_DEBUG_COMP, 0x000000f0, 0x00000070,
+	mmFBC_DEBUG1, 0xffffffff, 0x00000008,
+	mmFBC_MISC, 0x9f313fff, 0x14302008,
+	mmHDMI_CONTROL, 0x313f031f, 0x00000011,
+};
+
+static const u32 polaris10_golden_settings_a11[] =
+{
+	mmDCI_CLK_CNTL, 0x00000080, 0x00000000,
+	mmFBC_DEBUG_COMP, 0x000000f0, 0x00000070,
+	mmFBC_MISC, 0x9f313fff, 0x14302008,
+	mmHDMI_CONTROL, 0x313f031f, 0x00000011,
+};
 
 static void dce_v11_0_init_golden_registers(struct amdgpu_device *adev)
 {
@@ -149,6 +165,16 @@ static void dce_v11_0_init_golden_regist
 						 stoney_golden_settings_a11,
 						 (const u32)ARRAY_SIZE(stoney_golden_settings_a11));
 		break;
+	case CHIP_POLARIS11:
+		amdgpu_program_register_sequence(adev,
+						 polaris11_golden_settings_a11,
+						 (const u32)ARRAY_SIZE(polaris11_golden_settings_a11));
+		break;
+	case CHIP_POLARIS10:
+		amdgpu_program_register_sequence(adev,
+						 polaris10_golden_settings_a11,
+						 (const u32)ARRAY_SIZE(polaris10_golden_settings_a11));
+		break;
 	default:
 		break;
 	}
@@ -276,10 +302,17 @@ static void dce_v11_0_pageflip_interrupt
  * surface base address.
  */
 static void dce_v11_0_page_flip(struct amdgpu_device *adev,
-			      int crtc_id, u64 crtc_base)
+				int crtc_id, u64 crtc_base, bool async)
 {
 	struct amdgpu_crtc *amdgpu_crtc = adev->mode_info.crtcs[crtc_id];
+	u32 tmp;
 
+	/* flip at hsync for async, default is vsync */
+	/* use UPDATE_IMMEDIATE_EN instead for async? */
+	tmp = RREG32(mmGRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset);
+	tmp = REG_SET_FIELD(tmp, GRPH_FLIP_CONTROL,
+			    GRPH_SURFACE_UPDATE_H_RETRACE_EN, async ? 1 : 0);
+	WREG32(mmGRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset, tmp);
 	/* update the scanout addresses */
 	WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
 	       upper_32_bits(crtc_base));
@@ -565,35 +598,14 @@ static void dce_v11_0_stop_mc_access(str
 		crtc_enabled = REG_GET_FIELD(RREG32(mmCRTC_CONTROL + crtc_offsets[i]),
 					     CRTC_CONTROL, CRTC_MASTER_EN);
 		if (crtc_enabled) {
-#if 0
-			u32 frame_count;
-			int j;
-
+#if 1
 			save->crtc_enabled[i] = true;
 			tmp = RREG32(mmCRTC_BLANK_CONTROL + crtc_offsets[i]);
 			if (REG_GET_FIELD(tmp, CRTC_BLANK_CONTROL, CRTC_BLANK_DATA_EN) == 0) {
-				amdgpu_display_vblank_wait(adev, i);
-				WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 1);
+				/*it is correct only for RGB ; black is 0*/
+				WREG32(mmCRTC_BLANK_DATA_COLOR + crtc_offsets[i], 0);
 				tmp = REG_SET_FIELD(tmp, CRTC_BLANK_CONTROL, CRTC_BLANK_DATA_EN, 1);
 				WREG32(mmCRTC_BLANK_CONTROL + crtc_offsets[i], tmp);
-				WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 0);
-			}
-			/* wait for the next frame */
-			frame_count = amdgpu_display_vblank_get_counter(adev, i);
-			for (j = 0; j < adev->usec_timeout; j++) {
-				if (amdgpu_display_vblank_get_counter(adev, i) != frame_count)
-					break;
-				udelay(1);
-			}
-			tmp = RREG32(mmGRPH_UPDATE + crtc_offsets[i]);
-			if (REG_GET_FIELD(tmp, GRPH_UPDATE, GRPH_UPDATE_LOCK) == 0) {
-				tmp = REG_SET_FIELD(tmp, GRPH_UPDATE, GRPH_UPDATE_LOCK, 1);
-				WREG32(mmGRPH_UPDATE + crtc_offsets[i], tmp);
-			}
-			tmp = RREG32(mmCRTC_MASTER_UPDATE_LOCK + crtc_offsets[i]);
-			if (REG_GET_FIELD(tmp, CRTC_MASTER_UPDATE_LOCK, MASTER_UPDATE_LOCK) == 0) {
-				tmp = REG_SET_FIELD(tmp, CRTC_MASTER_UPDATE_LOCK, MASTER_UPDATE_LOCK, 1);
-				WREG32(mmCRTC_MASTER_UPDATE_LOCK + crtc_offsets[i], tmp);
 			}
 #else
 			/* XXX this is a hack to avoid strange behavior with EFI on certain systems */
@@ -614,54 +626,20 @@ static void dce_v11_0_stop_mc_access(str
 static void dce_v11_0_resume_mc_access(struct amdgpu_device *adev,
 				       struct amdgpu_mode_mc_save *save)
 {
-	u32 tmp, frame_count;
-	int i, j;
+	u32 tmp;
+	int i;
 
 	/* update crtc base addresses */
 	for (i = 0; i < adev->mode_info.num_crtc; i++) {
 		WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i],
 		       upper_32_bits(adev->mc.vram_start));
-		WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i],
-		       upper_32_bits(adev->mc.vram_start));
 		WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS + crtc_offsets[i],
 		       (u32)adev->mc.vram_start);
-		WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS + crtc_offsets[i],
-		       (u32)adev->mc.vram_start);
 
 		if (save->crtc_enabled[i]) {
-			tmp = RREG32(mmCRTC_MASTER_UPDATE_MODE + crtc_offsets[i]);
-			if (REG_GET_FIELD(tmp, CRTC_MASTER_UPDATE_MODE, MASTER_UPDATE_MODE) != 3) {
-				tmp = REG_SET_FIELD(tmp, CRTC_MASTER_UPDATE_MODE, MASTER_UPDATE_MODE, 3);
-				WREG32(mmCRTC_MASTER_UPDATE_MODE + crtc_offsets[i], tmp);
-			}
-			tmp = RREG32(mmGRPH_UPDATE + crtc_offsets[i]);
-			if (REG_GET_FIELD(tmp, GRPH_UPDATE, GRPH_UPDATE_LOCK)) {
-				tmp = REG_SET_FIELD(tmp, GRPH_UPDATE, GRPH_UPDATE_LOCK, 0);
-				WREG32(mmGRPH_UPDATE + crtc_offsets[i], tmp);
-			}
-			tmp = RREG32(mmCRTC_MASTER_UPDATE_LOCK + crtc_offsets[i]);
-			if (REG_GET_FIELD(tmp, CRTC_MASTER_UPDATE_LOCK, MASTER_UPDATE_LOCK)) {
-				tmp = REG_SET_FIELD(tmp, CRTC_MASTER_UPDATE_LOCK, MASTER_UPDATE_LOCK, 0);
-				WREG32(mmCRTC_MASTER_UPDATE_LOCK + crtc_offsets[i], tmp);
-			}
-			for (j = 0; j < adev->usec_timeout; j++) {
-				tmp = RREG32(mmGRPH_UPDATE + crtc_offsets[i]);
-				if (REG_GET_FIELD(tmp, GRPH_UPDATE, GRPH_SURFACE_UPDATE_PENDING) == 0)
-					break;
-				udelay(1);
-			}
 			tmp = RREG32(mmCRTC_BLANK_CONTROL + crtc_offsets[i]);
 			tmp = REG_SET_FIELD(tmp, CRTC_BLANK_CONTROL, CRTC_BLANK_DATA_EN, 0);
-			WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 1);
 			WREG32(mmCRTC_BLANK_CONTROL + crtc_offsets[i], tmp);
-			WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 0);
-			/* wait for the next frame */
-			frame_count = amdgpu_display_vblank_get_counter(adev, i);
-			for (j = 0; j < adev->usec_timeout; j++) {
-				if (amdgpu_display_vblank_get_counter(adev, i) != frame_count)
-					break;
-				udelay(1);
-			}
 		}
 	}
 
@@ -1624,6 +1602,7 @@ static const u32 pin_offsets[] =
 	AUD4_REGISTER_OFFSET,
 	AUD5_REGISTER_OFFSET,
 	AUD6_REGISTER_OFFSET,
+	AUD7_REGISTER_OFFSET,
 };
 
 static int dce_v11_0_audio_init(struct amdgpu_device *adev)
@@ -1635,7 +1614,20 @@ static int dce_v11_0_audio_init(struct a
 
 	adev->mode_info.audio.enabled = true;
 
-	adev->mode_info.audio.num_pins = 7;
+	switch (adev->asic_type) {
+	case CHIP_CARRIZO:
+	case CHIP_STONEY:
+		adev->mode_info.audio.num_pins = 7;
+		break;
+	case CHIP_POLARIS10:
+		adev->mode_info.audio.num_pins = 8;
+		break;
+	case CHIP_POLARIS11:
+		adev->mode_info.audio.num_pins = 6;
+		break;
+	default:
+		return -EINVAL;
+	}
 
 	for (i = 0; i < adev->mode_info.audio.num_pins; i++) {
 		adev->mode_info.audio.pin[i].channels = -1;
@@ -2201,6 +2193,14 @@ static int dce_v11_0_crtc_do_set_base(st
 
 	dce_v11_0_vga_enable(crtc, false);
 
+	/* Make sure surface address is updated at vertical blank rather than
+	 * horizontal blank
+	 */
+	tmp = RREG32(mmGRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset);
+	tmp = REG_SET_FIELD(tmp, GRPH_FLIP_CONTROL,
+			    GRPH_SURFACE_UPDATE_H_RETRACE_EN, 0);
+	WREG32(mmGRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset, tmp);
+
 	WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
 	       upper_32_bits(fb_location));
 	WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
@@ -2251,13 +2251,6 @@ static int dce_v11_0_crtc_do_set_base(st
 	WREG32(mmVIEWPORT_SIZE + amdgpu_crtc->crtc_offset,
 	       (viewport_w << 16) | viewport_h);
 
-	/* pageflip setup */
-	/* make sure flip is at vb rather than hb */
-	tmp = RREG32(mmGRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset);
-	tmp = REG_SET_FIELD(tmp, GRPH_FLIP_CONTROL,
-			    GRPH_SURFACE_UPDATE_H_RETRACE_EN, 0);
-	WREG32(mmGRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset, tmp);
-
 	/* set pageflip to happen only at start of vblank interval (front porch) */
 	WREG32(mmCRTC_MASTER_UPDATE_MODE + amdgpu_crtc->crtc_offset, 3);
 
@@ -2427,6 +2420,40 @@ static u32 dce_v11_0_pick_pll(struct drm
 	u32 pll_in_use;
 	int pll;
 
+	if ((adev->asic_type == CHIP_POLARIS10) ||
+	    (adev->asic_type == CHIP_POLARIS11)) {
+		struct amdgpu_encoder *amdgpu_encoder =
+			to_amdgpu_encoder(amdgpu_crtc->encoder);
+		struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv;
+
+		if (ENCODER_MODE_IS_DP(amdgpu_atombios_encoder_get_encoder_mode(amdgpu_crtc->encoder)))
+			return ATOM_DP_DTO;
+
+		switch (amdgpu_encoder->encoder_id) {
+		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+			if (dig->linkb)
+				return ATOM_COMBOPHY_PLL1;
+			else
+				return ATOM_COMBOPHY_PLL0;
+			break;
+		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+			if (dig->linkb)
+				return ATOM_COMBOPHY_PLL3;
+			else
+				return ATOM_COMBOPHY_PLL2;
+			break;
+		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+			if (dig->linkb)
+				return ATOM_COMBOPHY_PLL5;
+			else
+				return ATOM_COMBOPHY_PLL4;
+			break;
+		default:
+			DRM_ERROR("invalid encoder_id: 0x%x\n", amdgpu_encoder->encoder_id);
+			return ATOM_PPLL_INVALID;
+		}
+	}
+
 	if (ENCODER_MODE_IS_DP(amdgpu_atombios_encoder_get_encoder_mode(amdgpu_crtc->encoder))) {
 		if (adev->clock.dp_extclk)
 			/* skip PPLL programming if using ext clock */
@@ -2578,7 +2605,7 @@ static int dce_v11_0_crtc_cursor_set2(st
 		return -EINVAL;
 	}
 
-	obj = drm_gem_object_lookup(crtc->dev, file_priv, handle);
+	obj = drm_gem_object_lookup(file_priv, handle);
 	if (!obj) {
 		DRM_ERROR("Cannot find cursor object %x for crtc %d\n", handle, amdgpu_crtc->crtc_id);
 		return -ENOENT;
@@ -2782,7 +2809,17 @@ static void dce_v11_0_crtc_disable(struc
 	case ATOM_PPLL2:
 		/* disable the ppll */
 		amdgpu_atombios_crtc_program_pll(crtc, amdgpu_crtc->crtc_id, amdgpu_crtc->pll_id,
-					  0, 0, ATOM_DISABLE, 0, 0, 0, 0, 0, false, &ss);
+						 0, 0, ATOM_DISABLE, 0, 0, 0, 0, 0, false, &ss);
+		break;
+	case ATOM_COMBOPHY_PLL0:
+	case ATOM_COMBOPHY_PLL1:
+	case ATOM_COMBOPHY_PLL2:
+	case ATOM_COMBOPHY_PLL3:
+	case ATOM_COMBOPHY_PLL4:
+	case ATOM_COMBOPHY_PLL5:
+		/* disable the ppll */
+		amdgpu_atombios_crtc_program_pll(crtc, ATOM_CRTC_INVALID, amdgpu_crtc->pll_id,
+						 0, 0, ATOM_DISABLE, 0, 0, 0, 0, 0, false, &ss);
 		break;
 	default:
 		break;
@@ -2800,11 +2837,28 @@ static int dce_v11_0_crtc_mode_set(struc
 				  int x, int y, struct drm_framebuffer *old_fb)
 {
 	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	struct amdgpu_device *adev = dev->dev_private;
 
 	if (!amdgpu_crtc->adjusted_clock)
 		return -EINVAL;
 
-	amdgpu_atombios_crtc_set_pll(crtc, adjusted_mode);
+	if ((adev->asic_type == CHIP_POLARIS10) ||
+	    (adev->asic_type == CHIP_POLARIS11)) {
+		struct amdgpu_encoder *amdgpu_encoder =
+			to_amdgpu_encoder(amdgpu_crtc->encoder);
+		int encoder_mode =
+			amdgpu_atombios_encoder_get_encoder_mode(amdgpu_crtc->encoder);
+
+		/* SetPixelClock calculates the plls and ss values now */
+		amdgpu_atombios_crtc_program_pll(crtc, amdgpu_crtc->crtc_id,
+						 amdgpu_crtc->pll_id,
+						 encoder_mode, amdgpu_encoder->encoder_id,
+						 adjusted_mode->clock, 0, 0, 0, 0,
+						 amdgpu_crtc->bpc, amdgpu_crtc->ss_enabled, &amdgpu_crtc->ss);
+	} else {
+		amdgpu_atombios_crtc_set_pll(crtc, adjusted_mode);
+	}
 	amdgpu_atombios_crtc_set_dtd_timing(crtc, adjusted_mode);
 	dce_v11_0_crtc_do_set_base(crtc, old_fb, x, y, 0);
 	amdgpu_atombios_crtc_overscan_setup(crtc, mode, adjusted_mode);
@@ -2955,6 +3009,16 @@ static int dce_v11_0_early_init(void *ha
 		adev->mode_info.num_hpd = 6;
 		adev->mode_info.num_dig = 9;
 		break;
+	case CHIP_POLARIS10:
+		adev->mode_info.num_crtc = 6;
+		adev->mode_info.num_hpd = 6;
+		adev->mode_info.num_dig = 6;
+		break;
+	case CHIP_POLARIS11:
+		adev->mode_info.num_crtc = 5;
+		adev->mode_info.num_hpd = 5;
+		adev->mode_info.num_dig = 5;
+		break;
 	default:
 		/* FIXME: not supported yet */
 		return -EINVAL;
@@ -2987,6 +3051,8 @@ static int dce_v11_0_sw_init(void *handl
 
 	adev->ddev->mode_config.funcs = &amdgpu_mode_funcs;
 
+	adev->ddev->mode_config.async_page_flip = true;
+
 	adev->ddev->mode_config.max_width = 16384;
 	adev->ddev->mode_config.max_height = 16384;
 
@@ -3057,7 +3123,15 @@ static int dce_v11_0_hw_init(void *handl
 	/* init dig PHYs, disp eng pll */
 	amdgpu_atombios_crtc_powergate_init(adev);
 	amdgpu_atombios_encoder_init_dig(adev);
-	amdgpu_atombios_crtc_set_disp_eng_pll(adev, adev->clock.default_dispclk);
+	if ((adev->asic_type == CHIP_POLARIS10) ||
+	    (adev->asic_type == CHIP_POLARIS11)) {
+		amdgpu_atombios_crtc_set_dce_clock(adev, adev->clock.default_dispclk,
+						   DCE_CLOCK_TYPE_DISPCLK, ATOM_GCK_DFS);
+		amdgpu_atombios_crtc_set_dce_clock(adev, 0,
+						   DCE_CLOCK_TYPE_DPREFCLK, ATOM_GCK_DFS);
+	} else {
+		amdgpu_atombios_crtc_set_disp_eng_pll(adev, adev->clock.default_dispclk);
+	}
 
 	/* initialize hpd */
 	dce_v11_0_hpd_init(adev);
@@ -3126,14 +3200,6 @@ static int dce_v11_0_wait_for_idle(void
 	return 0;
 }
 
-static void dce_v11_0_print_status(void *handle)
-{
-	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-	dev_info(adev->dev, "DCE 10.x registers\n");
-	/* XXX todo */
-}
-
 static int dce_v11_0_soft_reset(void *handle)
 {
 	u32 srbm_soft_reset = 0, tmp;
@@ -3143,8 +3209,6 @@ static int dce_v11_0_soft_reset(void *ha
 		srbm_soft_reset |= SRBM_SOFT_RESET__SOFT_RESET_DC_MASK;
 
 	if (srbm_soft_reset) {
-		dce_v11_0_print_status((void *)adev);
-
 		tmp = RREG32(mmSRBM_SOFT_RESET);
 		tmp |= srbm_soft_reset;
 		dev_info(adev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp);
@@ -3159,7 +3223,6 @@ static int dce_v11_0_soft_reset(void *ha
 
 		/* Wait a little for things to settle down */
 		udelay(50);
-		dce_v11_0_print_status((void *)adev);
 	}
 	return 0;
 }
@@ -3366,7 +3429,7 @@ static int dce_v11_0_pageflip_irq(struct
 
 	/* wakeup usersapce */
 	if(works->event)
-		drm_send_vblank_event(adev->ddev, crtc_id, works->event);
+		drm_crtc_send_vblank_event(&amdgpu_crtc->base, works->event);
 
 	spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
 
@@ -3497,6 +3560,7 @@ static int dce_v11_0_set_powergating_sta
 }
 
 const struct amd_ip_funcs dce_v11_0_ip_funcs = {
+	.name = "dce_v11_0",
 	.early_init = dce_v11_0_early_init,
 	.late_init = NULL,
 	.sw_init = dce_v11_0_sw_init,
@@ -3508,7 +3572,6 @@ const struct amd_ip_funcs dce_v11_0_ip_f
 	.is_idle = dce_v11_0_is_idle,
 	.wait_for_idle = dce_v11_0_wait_for_idle,
 	.soft_reset = dce_v11_0_soft_reset,
-	.print_status = dce_v11_0_print_status,
 	.set_clockgating_state = dce_v11_0_set_clockgating_state,
 	.set_powergating_state = dce_v11_0_set_powergating_state,
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c	2016-07-24 15:23:50.000000000 -0400
@@ -233,10 +233,13 @@ static void dce_v8_0_pageflip_interrupt_
  * surface base address.
  */
 static void dce_v8_0_page_flip(struct amdgpu_device *adev,
-			      int crtc_id, u64 crtc_base)
+			       int crtc_id, u64 crtc_base, bool async)
 {
 	struct amdgpu_crtc *amdgpu_crtc = adev->mode_info.crtcs[crtc_id];
 
+	/* flip at hsync for async, default is vsync */
+	WREG32(mmGRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset, async ?
+	       GRPH_FLIP_CONTROL__GRPH_SURFACE_UPDATE_H_RETRACE_EN_MASK : 0);
 	/* update the primary scanout addresses */
 	WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
 	       upper_32_bits(crtc_base));
@@ -1999,7 +2002,7 @@ static int dce_v8_0_crtc_do_set_base(str
 	uint32_t fb_format, fb_pitch_pixels;
 	u32 fb_swap = (GRPH_ENDIAN_NONE << GRPH_SWAP_CNTL__GRPH_ENDIAN_SWAP__SHIFT);
 	u32 pipe_config;
-	u32 tmp, viewport_w, viewport_h;
+	u32 viewport_w, viewport_h;
 	int r;
 	bool bypass_lut = false;
 
@@ -2135,6 +2138,11 @@ static int dce_v8_0_crtc_do_set_base(str
 
 	dce_v8_0_vga_enable(crtc, false);
 
+	/* Make sure surface address is updated at vertical blank rather than
+	 * horizontal blank
+	 */
+	WREG32(mmGRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset, 0);
+
 	WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
 	       upper_32_bits(fb_location));
 	WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
@@ -2182,12 +2190,6 @@ static int dce_v8_0_crtc_do_set_base(str
 	WREG32(mmVIEWPORT_SIZE + amdgpu_crtc->crtc_offset,
 	       (viewport_w << 16) | viewport_h);
 
-	/* pageflip setup */
-	/* make sure flip is at vb rather than hb */
-	tmp = RREG32(mmGRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset);
-	tmp &= ~GRPH_FLIP_CONTROL__GRPH_SURFACE_UPDATE_H_RETRACE_EN_MASK;
-	WREG32(mmGRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset, tmp);
-
 	/* set pageflip to happen only at start of vblank interval (front porch) */
 	WREG32(mmMASTER_UPDATE_MODE + amdgpu_crtc->crtc_offset, 3);
 
@@ -2499,7 +2501,7 @@ static int dce_v8_0_crtc_cursor_set2(str
 		return -EINVAL;
 	}
 
-	obj = drm_gem_object_lookup(crtc->dev, file_priv, handle);
+	obj = drm_gem_object_lookup(file_priv, handle);
 	if (!obj) {
 		DRM_ERROR("Cannot find cursor object %x for crtc %d\n", handle, amdgpu_crtc->crtc_id);
 		return -ENOENT;
@@ -2902,6 +2904,8 @@ static int dce_v8_0_sw_init(void *handle
 
 	adev->ddev->mode_config.funcs = &amdgpu_mode_funcs;
 
+	adev->ddev->mode_config.async_page_flip = true;
+
 	adev->ddev->mode_config.max_width = 16384;
 	adev->ddev->mode_config.max_height = 16384;
 
@@ -3038,14 +3042,6 @@ static int dce_v8_0_wait_for_idle(void *
 	return 0;
 }
 
-static void dce_v8_0_print_status(void *handle)
-{
-	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-	dev_info(adev->dev, "DCE 8.x registers\n");
-	/* XXX todo */
-}
-
 static int dce_v8_0_soft_reset(void *handle)
 {
 	u32 srbm_soft_reset = 0, tmp;
@@ -3055,8 +3051,6 @@ static int dce_v8_0_soft_reset(void *han
 		srbm_soft_reset |= SRBM_SOFT_RESET__SOFT_RESET_DC_MASK;
 
 	if (srbm_soft_reset) {
-		dce_v8_0_print_status((void *)adev);
-
 		tmp = RREG32(mmSRBM_SOFT_RESET);
 		tmp |= srbm_soft_reset;
 		dev_info(adev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp);
@@ -3071,7 +3065,6 @@ static int dce_v8_0_soft_reset(void *han
 
 		/* Wait a little for things to settle down */
 		udelay(50);
-		dce_v8_0_print_status((void *)adev);
 	}
 	return 0;
 }
@@ -3379,7 +3372,7 @@ static int dce_v8_0_pageflip_irq(struct
 
 	/* wakeup usersapce */
 	if (works->event)
-		drm_send_vblank_event(adev->ddev, crtc_id, works->event);
+		drm_crtc_send_vblank_event(&amdgpu_crtc->base, works->event);
 
 	spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
 
@@ -3431,6 +3424,7 @@ static int dce_v8_0_set_powergating_stat
 }
 
 const struct amd_ip_funcs dce_v8_0_ip_funcs = {
+	.name = "dce_v8_0",
 	.early_init = dce_v8_0_early_init,
 	.late_init = NULL,
 	.sw_init = dce_v8_0_sw_init,
@@ -3442,7 +3436,6 @@ const struct amd_ip_funcs dce_v8_0_ip_fu
 	.is_idle = dce_v8_0_is_idle,
 	.wait_for_idle = dce_v8_0_wait_for_idle,
 	.soft_reset = dce_v8_0_soft_reset,
-	.print_status = dce_v8_0_print_status,
 	.set_clockgating_state = dce_v8_0_set_clockgating_state,
 	.set_powergating_state = dce_v8_0_set_powergating_state,
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/fiji_dpm.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/fiji_dpm.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/fiji_dpm.c	2016-05-15 19:20:58.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/fiji_dpm.c	2016-07-24 18:17:25.000000000 -0400
@@ -72,6 +72,11 @@ static int fiji_dpm_sw_init(void *handle
 
 static int fiji_dpm_sw_fini(void *handle)
 {
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+	release_firmware(adev->pm.fw);
+	adev->pm.fw = NULL;
+
 	return 0;
 }
 
@@ -143,6 +148,7 @@ static int fiji_dpm_set_powergating_stat
 }
 
 const struct amd_ip_funcs fiji_dpm_ip_funcs = {
+	.name = "fiji_dpm",
 	.early_init = fiji_dpm_early_init,
 	.late_init = NULL,
 	.sw_init = fiji_dpm_sw_init,
@@ -154,7 +160,6 @@ const struct amd_ip_funcs fiji_dpm_ip_fu
 	.is_idle = NULL,
 	.wait_for_idle = NULL,
 	.soft_reset = NULL,
-	.print_status = NULL,
 	.set_clockgating_state = fiji_dpm_set_clockgating_state,
 	.set_powergating_state = fiji_dpm_set_powergating_state,
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c	2016-05-15 19:21:20.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c	2016-07-24 18:17:54.000000000 -0400
@@ -53,7 +53,6 @@
 static void gfx_v7_0_set_ring_funcs(struct amdgpu_device *adev);
 static void gfx_v7_0_set_irq_funcs(struct amdgpu_device *adev);
 static void gfx_v7_0_set_gds_init(struct amdgpu_device *adev);
-int gfx_v7_0_get_cu_info(struct amdgpu_device *, struct amdgpu_cu_info *);
 
 /*(DEBLOBBED)*/
 
@@ -853,6 +852,7 @@ static u32 gfx_v7_0_get_csb_size(struct
 static void gfx_v7_0_get_csb_buffer(struct amdgpu_device *adev, volatile u32 *buffer);
 static void gfx_v7_0_init_cp_pg_table(struct amdgpu_device *adev);
 static void gfx_v7_0_init_pg(struct amdgpu_device *adev);
+static void gfx_v7_0_get_cu_info(struct amdgpu_device *adev);
 
 /*
  * Core functions
@@ -962,6 +962,22 @@ out:
 	return err;
 }
 
+static void gfx_v7_0_free_microcode(struct amdgpu_device *adev)
+{
+	release_firmware(adev->gfx.pfp_fw);
+	adev->gfx.pfp_fw = NULL;
+	release_firmware(adev->gfx.me_fw);
+	adev->gfx.me_fw = NULL;
+	release_firmware(adev->gfx.ce_fw);
+	adev->gfx.ce_fw = NULL;
+	release_firmware(adev->gfx.mec_fw);
+	adev->gfx.mec_fw = NULL;
+	release_firmware(adev->gfx.mec2_fw);
+	adev->gfx.mec2_fw = NULL;
+	release_firmware(adev->gfx.rlc_fw);
+	adev->gfx.rlc_fw = NULL;
+}
+
 /**
  * gfx_v7_0_tiling_mode_table_init - init the hw tiling table
  *
@@ -1689,6 +1705,7 @@ static void gfx_v7_0_gpu_init(struct amd
 	gfx_v7_0_tiling_mode_table_init(adev);
 
 	gfx_v7_0_setup_rb(adev);
+	gfx_v7_0_get_cu_info(adev);
 
 	/* set HW defaults for 3D engine */
 	WREG32(mmCP_MEQ_THRESHOLDS,
@@ -2000,17 +2017,13 @@ static void gfx_v7_0_ring_emit_fence_com
  * on the gfx ring for execution by the GPU.
  */
 static void gfx_v7_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
-				  struct amdgpu_ib *ib)
+				      struct amdgpu_ib *ib,
+				      unsigned vm_id, bool ctx_switch)
 {
-	bool need_ctx_switch = ring->current_ctx != ib->ctx;
 	u32 header, control = 0;
 	u32 next_rptr = ring->wptr + 5;
 
-	/* drop the CE preamble IB for the same context */
-	if ((ib->flags & AMDGPU_IB_FLAG_PREAMBLE) && !need_ctx_switch)
-		return;
-
-	if (need_ctx_switch)
+	if (ctx_switch)
 		next_rptr += 2;
 
 	next_rptr += 4;
@@ -2021,7 +2034,7 @@ static void gfx_v7_0_ring_emit_ib_gfx(st
 	amdgpu_ring_write(ring, next_rptr);
 
 	/* insert SWITCH_BUFFER packet before first IB in the ring frame */
-	if (need_ctx_switch) {
+	if (ctx_switch) {
 		amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
 		amdgpu_ring_write(ring, 0);
 	}
@@ -2031,7 +2044,7 @@ static void gfx_v7_0_ring_emit_ib_gfx(st
 	else
 		header = PACKET3(PACKET3_INDIRECT_BUFFER, 2);
 
-	control |= ib->length_dw | (ib->vm_id << 24);
+	control |= ib->length_dw | (vm_id << 24);
 
 	amdgpu_ring_write(ring, header);
 	amdgpu_ring_write(ring,
@@ -2044,7 +2057,8 @@ static void gfx_v7_0_ring_emit_ib_gfx(st
 }
 
 static void gfx_v7_0_ring_emit_ib_compute(struct amdgpu_ring *ring,
-				  struct amdgpu_ib *ib)
+					  struct amdgpu_ib *ib,
+					  unsigned vm_id, bool ctx_switch)
 {
 	u32 header, control = 0;
 	u32 next_rptr = ring->wptr + 5;
@@ -2059,7 +2073,7 @@ static void gfx_v7_0_ring_emit_ib_comput
 
 	header = PACKET3(PACKET3_INDIRECT_BUFFER, 2);
 
-	control |= ib->length_dw | (ib->vm_id << 24);
+	control |= ib->length_dw | (vm_id << 24);
 
 	amdgpu_ring_write(ring, header);
 	amdgpu_ring_write(ring,
@@ -2107,7 +2121,7 @@ static int gfx_v7_0_ring_test_ib(struct
 	ib.ptr[2] = 0xDEADBEEF;
 	ib.length_dw = 3;
 
-	r = amdgpu_ib_schedule(ring, 1, &ib, NULL, &f);
+	r = amdgpu_ib_schedule(ring, 1, &ib, NULL, NULL, &f);
 	if (r)
 		goto err2;
 
@@ -3024,6 +3038,19 @@ static int gfx_v7_0_cp_resume(struct amd
 static void gfx_v7_0_ring_emit_pipeline_sync(struct amdgpu_ring *ring)
 {
 	int usepfp = (ring->type == AMDGPU_RING_TYPE_GFX);
+	uint32_t seq = ring->fence_drv.sync_seq;
+	uint64_t addr = ring->fence_drv.gpu_addr;
+
+	amdgpu_ring_write(ring, PACKET3(PACKET3_WAIT_REG_MEM, 5));
+	amdgpu_ring_write(ring, (WAIT_REG_MEM_MEM_SPACE(1) | /* memory */
+				 WAIT_REG_MEM_FUNCTION(3) | /* equal */
+				 WAIT_REG_MEM_ENGINE(usepfp)));   /* pfp or me */
+	amdgpu_ring_write(ring, addr & 0xfffffffc);
+	amdgpu_ring_write(ring, upper_32_bits(addr) & 0xffffffff);
+	amdgpu_ring_write(ring, seq);
+	amdgpu_ring_write(ring, 0xffffffff);
+	amdgpu_ring_write(ring, 4); /* poll interval */
+
 	if (usepfp) {
 		/* synce CE with ME to prevent CE fetch CEIB before context switch done */
 		amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
@@ -3051,18 +3078,6 @@ static void gfx_v7_0_ring_emit_vm_flush(
 					unsigned vm_id, uint64_t pd_addr)
 {
 	int usepfp = (ring->type == AMDGPU_RING_TYPE_GFX);
-	uint32_t seq = ring->fence_drv.sync_seq;
-	uint64_t addr = ring->fence_drv.gpu_addr;
-
-	amdgpu_ring_write(ring, PACKET3(PACKET3_WAIT_REG_MEM, 5));
-	amdgpu_ring_write(ring, (WAIT_REG_MEM_MEM_SPACE(1) | /* memory */
-				 WAIT_REG_MEM_FUNCTION(3) | /* equal */
-				 WAIT_REG_MEM_ENGINE(usepfp)));   /* pfp or me */
-	amdgpu_ring_write(ring, addr & 0xfffffffc);
-	amdgpu_ring_write(ring, upper_32_bits(addr) & 0xffffffff);
-	amdgpu_ring_write(ring, seq);
-	amdgpu_ring_write(ring, 0xffffffff);
-	amdgpu_ring_write(ring, 4); /* poll interval */
 
 	amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
 	amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(usepfp) |
@@ -3840,18 +3855,13 @@ static u32 gfx_v7_0_get_cu_active_bitmap
 
 static void gfx_v7_0_init_ao_cu_mask(struct amdgpu_device *adev)
 {
-	uint32_t tmp, active_cu_number;
-	struct amdgpu_cu_info cu_info;
-
-	gfx_v7_0_get_cu_info(adev, &cu_info);
-	tmp = cu_info.ao_cu_mask;
-	active_cu_number = cu_info.number;
+	u32 tmp;
 
-	WREG32(mmRLC_PG_ALWAYS_ON_CU_MASK, tmp);
+	WREG32(mmRLC_PG_ALWAYS_ON_CU_MASK, adev->gfx.cu_info.ao_cu_mask);
 
 	tmp = RREG32(mmRLC_MAX_PG_CU);
 	tmp &= ~RLC_MAX_PG_CU__MAX_POWERED_UP_CU_MASK;
-	tmp |= (active_cu_number << RLC_MAX_PG_CU__MAX_POWERED_UP_CU__SHIFT);
+	tmp |= (adev->gfx.cu_info.number << RLC_MAX_PG_CU__MAX_POWERED_UP_CU__SHIFT);
 	WREG32(mmRLC_MAX_PG_CU, tmp);
 }
 
@@ -4385,7 +4395,7 @@ static int gfx_v7_0_sw_init(void *handle
 		ring = &adev->gfx.gfx_ring[i];
 		ring->ring_obj = NULL;
 		sprintf(ring->name, "gfx");
-		r = amdgpu_ring_init(adev, ring, 1024 * 1024,
+		r = amdgpu_ring_init(adev, ring, 1024,
 				     PACKET3(PACKET3_NOP, 0x3FFF), 0xf,
 				     &adev->gfx.eop_irq, AMDGPU_CP_IRQ_GFX_EOP,
 				     AMDGPU_RING_TYPE_GFX);
@@ -4409,10 +4419,10 @@ static int gfx_v7_0_sw_init(void *handle
 		ring->me = 1; /* first MEC */
 		ring->pipe = i / 8;
 		ring->queue = i % 8;
-		sprintf(ring->name, "comp %d.%d.%d", ring->me, ring->pipe, ring->queue);
+		sprintf(ring->name, "comp_%d.%d.%d", ring->me, ring->pipe, ring->queue);
 		irq_type = AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE0_EOP + ring->pipe;
 		/* type-2 packets are deprecated on MEC, use type-3 instead */
-		r = amdgpu_ring_init(adev, ring, 1024 * 1024,
+		r = amdgpu_ring_init(adev, ring, 1024,
 				     PACKET3(PACKET3_NOP, 0x3FFF), 0xf,
 				     &adev->gfx.eop_irq, irq_type,
 				     AMDGPU_RING_TYPE_COMPUTE);
@@ -4466,6 +4476,7 @@ static int gfx_v7_0_sw_fini(void *handle
 	gfx_v7_0_cp_compute_fini(adev);
 	gfx_v7_0_rlc_fini(adev);
 	gfx_v7_0_mec_fini(adev);
+	gfx_v7_0_free_microcode(adev);
 
 	return 0;
 }
@@ -4543,256 +4554,6 @@ static int gfx_v7_0_wait_for_idle(void *
 	return -ETIMEDOUT;
 }
 
-static void gfx_v7_0_print_status(void *handle)
-{
-	int i;
-	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-	dev_info(adev->dev, "GFX 7.x registers\n");
-	dev_info(adev->dev, "  GRBM_STATUS=0x%08X\n",
-		RREG32(mmGRBM_STATUS));
-	dev_info(adev->dev, "  GRBM_STATUS2=0x%08X\n",
-		RREG32(mmGRBM_STATUS2));
-	dev_info(adev->dev, "  GRBM_STATUS_SE0=0x%08X\n",
-		RREG32(mmGRBM_STATUS_SE0));
-	dev_info(adev->dev, "  GRBM_STATUS_SE1=0x%08X\n",
-		RREG32(mmGRBM_STATUS_SE1));
-	dev_info(adev->dev, "  GRBM_STATUS_SE2=0x%08X\n",
-		RREG32(mmGRBM_STATUS_SE2));
-	dev_info(adev->dev, "  GRBM_STATUS_SE3=0x%08X\n",
-		RREG32(mmGRBM_STATUS_SE3));
-	dev_info(adev->dev, "  CP_STAT = 0x%08x\n", RREG32(mmCP_STAT));
-	dev_info(adev->dev, "  CP_STALLED_STAT1 = 0x%08x\n",
-		 RREG32(mmCP_STALLED_STAT1));
-	dev_info(adev->dev, "  CP_STALLED_STAT2 = 0x%08x\n",
-		 RREG32(mmCP_STALLED_STAT2));
-	dev_info(adev->dev, "  CP_STALLED_STAT3 = 0x%08x\n",
-		 RREG32(mmCP_STALLED_STAT3));
-	dev_info(adev->dev, "  CP_CPF_BUSY_STAT = 0x%08x\n",
-		 RREG32(mmCP_CPF_BUSY_STAT));
-	dev_info(adev->dev, "  CP_CPF_STALLED_STAT1 = 0x%08x\n",
-		 RREG32(mmCP_CPF_STALLED_STAT1));
-	dev_info(adev->dev, "  CP_CPF_STATUS = 0x%08x\n", RREG32(mmCP_CPF_STATUS));
-	dev_info(adev->dev, "  CP_CPC_BUSY_STAT = 0x%08x\n", RREG32(mmCP_CPC_BUSY_STAT));
-	dev_info(adev->dev, "  CP_CPC_STALLED_STAT1 = 0x%08x\n",
-		 RREG32(mmCP_CPC_STALLED_STAT1));
-	dev_info(adev->dev, "  CP_CPC_STATUS = 0x%08x\n", RREG32(mmCP_CPC_STATUS));
-
-	for (i = 0; i < 32; i++) {
-		dev_info(adev->dev, "  GB_TILE_MODE%d=0x%08X\n",
-			 i, RREG32(mmGB_TILE_MODE0 + (i * 4)));
-	}
-	for (i = 0; i < 16; i++) {
-		dev_info(adev->dev, "  GB_MACROTILE_MODE%d=0x%08X\n",
-			 i, RREG32(mmGB_MACROTILE_MODE0 + (i * 4)));
-	}
-	for (i = 0; i < adev->gfx.config.max_shader_engines; i++) {
-		dev_info(adev->dev, "  se: %d\n", i);
-		gfx_v7_0_select_se_sh(adev, i, 0xffffffff);
-		dev_info(adev->dev, "  PA_SC_RASTER_CONFIG=0x%08X\n",
-			 RREG32(mmPA_SC_RASTER_CONFIG));
-		dev_info(adev->dev, "  PA_SC_RASTER_CONFIG_1=0x%08X\n",
-			 RREG32(mmPA_SC_RASTER_CONFIG_1));
-	}
-	gfx_v7_0_select_se_sh(adev, 0xffffffff, 0xffffffff);
-
-	dev_info(adev->dev, "  GB_ADDR_CONFIG=0x%08X\n",
-		 RREG32(mmGB_ADDR_CONFIG));
-	dev_info(adev->dev, "  HDP_ADDR_CONFIG=0x%08X\n",
-		 RREG32(mmHDP_ADDR_CONFIG));
-	dev_info(adev->dev, "  DMIF_ADDR_CALC=0x%08X\n",
-		 RREG32(mmDMIF_ADDR_CALC));
-
-	dev_info(adev->dev, "  CP_MEQ_THRESHOLDS=0x%08X\n",
-		 RREG32(mmCP_MEQ_THRESHOLDS));
-	dev_info(adev->dev, "  SX_DEBUG_1=0x%08X\n",
-		 RREG32(mmSX_DEBUG_1));
-	dev_info(adev->dev, "  TA_CNTL_AUX=0x%08X\n",
-		 RREG32(mmTA_CNTL_AUX));
-	dev_info(adev->dev, "  SPI_CONFIG_CNTL=0x%08X\n",
-		 RREG32(mmSPI_CONFIG_CNTL));
-	dev_info(adev->dev, "  SQ_CONFIG=0x%08X\n",
-		 RREG32(mmSQ_CONFIG));
-	dev_info(adev->dev, "  DB_DEBUG=0x%08X\n",
-		 RREG32(mmDB_DEBUG));
-	dev_info(adev->dev, "  DB_DEBUG2=0x%08X\n",
-		 RREG32(mmDB_DEBUG2));
-	dev_info(adev->dev, "  DB_DEBUG3=0x%08X\n",
-		 RREG32(mmDB_DEBUG3));
-	dev_info(adev->dev, "  CB_HW_CONTROL=0x%08X\n",
-		 RREG32(mmCB_HW_CONTROL));
-	dev_info(adev->dev, "  SPI_CONFIG_CNTL_1=0x%08X\n",
-		 RREG32(mmSPI_CONFIG_CNTL_1));
-	dev_info(adev->dev, "  PA_SC_FIFO_SIZE=0x%08X\n",
-		 RREG32(mmPA_SC_FIFO_SIZE));
-	dev_info(adev->dev, "  VGT_NUM_INSTANCES=0x%08X\n",
-		 RREG32(mmVGT_NUM_INSTANCES));
-	dev_info(adev->dev, "  CP_PERFMON_CNTL=0x%08X\n",
-		 RREG32(mmCP_PERFMON_CNTL));
-	dev_info(adev->dev, "  PA_SC_FORCE_EOV_MAX_CNTS=0x%08X\n",
-		 RREG32(mmPA_SC_FORCE_EOV_MAX_CNTS));
-	dev_info(adev->dev, "  VGT_CACHE_INVALIDATION=0x%08X\n",
-		 RREG32(mmVGT_CACHE_INVALIDATION));
-	dev_info(adev->dev, "  VGT_GS_VERTEX_REUSE=0x%08X\n",
-		 RREG32(mmVGT_GS_VERTEX_REUSE));
-	dev_info(adev->dev, "  PA_SC_LINE_STIPPLE_STATE=0x%08X\n",
-		 RREG32(mmPA_SC_LINE_STIPPLE_STATE));
-	dev_info(adev->dev, "  PA_CL_ENHANCE=0x%08X\n",
-		 RREG32(mmPA_CL_ENHANCE));
-	dev_info(adev->dev, "  PA_SC_ENHANCE=0x%08X\n",
-		 RREG32(mmPA_SC_ENHANCE));
-
-	dev_info(adev->dev, "  CP_ME_CNTL=0x%08X\n",
-		 RREG32(mmCP_ME_CNTL));
-	dev_info(adev->dev, "  CP_MAX_CONTEXT=0x%08X\n",
-		 RREG32(mmCP_MAX_CONTEXT));
-	dev_info(adev->dev, "  CP_ENDIAN_SWAP=0x%08X\n",
-		 RREG32(mmCP_ENDIAN_SWAP));
-	dev_info(adev->dev, "  CP_DEVICE_ID=0x%08X\n",
-		 RREG32(mmCP_DEVICE_ID));
-
-	dev_info(adev->dev, "  CP_SEM_WAIT_TIMER=0x%08X\n",
-		 RREG32(mmCP_SEM_WAIT_TIMER));
-	if (adev->asic_type != CHIP_HAWAII)
-		dev_info(adev->dev, "  CP_SEM_INCOMPLETE_TIMER_CNTL=0x%08X\n",
-			 RREG32(mmCP_SEM_INCOMPLETE_TIMER_CNTL));
-
-	dev_info(adev->dev, "  CP_RB_WPTR_DELAY=0x%08X\n",
-		 RREG32(mmCP_RB_WPTR_DELAY));
-	dev_info(adev->dev, "  CP_RB_VMID=0x%08X\n",
-		 RREG32(mmCP_RB_VMID));
-	dev_info(adev->dev, "  CP_RB0_CNTL=0x%08X\n",
-		 RREG32(mmCP_RB0_CNTL));
-	dev_info(adev->dev, "  CP_RB0_WPTR=0x%08X\n",
-		 RREG32(mmCP_RB0_WPTR));
-	dev_info(adev->dev, "  CP_RB0_RPTR_ADDR=0x%08X\n",
-		 RREG32(mmCP_RB0_RPTR_ADDR));
-	dev_info(adev->dev, "  CP_RB0_RPTR_ADDR_HI=0x%08X\n",
-		 RREG32(mmCP_RB0_RPTR_ADDR_HI));
-	dev_info(adev->dev, "  CP_RB0_CNTL=0x%08X\n",
-		 RREG32(mmCP_RB0_CNTL));
-	dev_info(adev->dev, "  CP_RB0_BASE=0x%08X\n",
-		 RREG32(mmCP_RB0_BASE));
-	dev_info(adev->dev, "  CP_RB0_BASE_HI=0x%08X\n",
-		 RREG32(mmCP_RB0_BASE_HI));
-	dev_info(adev->dev, "  CP_MEC_CNTL=0x%08X\n",
-		 RREG32(mmCP_MEC_CNTL));
-	dev_info(adev->dev, "  CP_CPF_DEBUG=0x%08X\n",
-		 RREG32(mmCP_CPF_DEBUG));
-
-	dev_info(adev->dev, "  SCRATCH_ADDR=0x%08X\n",
-		 RREG32(mmSCRATCH_ADDR));
-	dev_info(adev->dev, "  SCRATCH_UMSK=0x%08X\n",
-		 RREG32(mmSCRATCH_UMSK));
-
-	/* init the pipes */
-	mutex_lock(&adev->srbm_mutex);
-	for (i = 0; i < (adev->gfx.mec.num_pipe * adev->gfx.mec.num_mec); i++) {
-		int me = (i < 4) ? 1 : 2;
-		int pipe = (i < 4) ? i : (i - 4);
-		int queue;
-
-		dev_info(adev->dev, "  me: %d, pipe: %d\n", me, pipe);
-		cik_srbm_select(adev, me, pipe, 0, 0);
-		dev_info(adev->dev, "  CP_HPD_EOP_BASE_ADDR=0x%08X\n",
-			 RREG32(mmCP_HPD_EOP_BASE_ADDR));
-		dev_info(adev->dev, "  CP_HPD_EOP_BASE_ADDR_HI=0x%08X\n",
-			 RREG32(mmCP_HPD_EOP_BASE_ADDR_HI));
-		dev_info(adev->dev, "  CP_HPD_EOP_VMID=0x%08X\n",
-			 RREG32(mmCP_HPD_EOP_VMID));
-		dev_info(adev->dev, "  CP_HPD_EOP_CONTROL=0x%08X\n",
-			 RREG32(mmCP_HPD_EOP_CONTROL));
-
-		for (queue = 0; queue < 8; queue++) {
-			cik_srbm_select(adev, me, pipe, queue, 0);
-			dev_info(adev->dev, "  queue: %d\n", queue);
-			dev_info(adev->dev, "  CP_PQ_WPTR_POLL_CNTL=0x%08X\n",
-				 RREG32(mmCP_PQ_WPTR_POLL_CNTL));
-			dev_info(adev->dev, "  CP_HQD_PQ_DOORBELL_CONTROL=0x%08X\n",
-				 RREG32(mmCP_HQD_PQ_DOORBELL_CONTROL));
-			dev_info(adev->dev, "  CP_HQD_ACTIVE=0x%08X\n",
-				 RREG32(mmCP_HQD_ACTIVE));
-			dev_info(adev->dev, "  CP_HQD_DEQUEUE_REQUEST=0x%08X\n",
-				 RREG32(mmCP_HQD_DEQUEUE_REQUEST));
-			dev_info(adev->dev, "  CP_HQD_PQ_RPTR=0x%08X\n",
-				 RREG32(mmCP_HQD_PQ_RPTR));
-			dev_info(adev->dev, "  CP_HQD_PQ_WPTR=0x%08X\n",
-				 RREG32(mmCP_HQD_PQ_WPTR));
-			dev_info(adev->dev, "  CP_HQD_PQ_BASE=0x%08X\n",
-				 RREG32(mmCP_HQD_PQ_BASE));
-			dev_info(adev->dev, "  CP_HQD_PQ_BASE_HI=0x%08X\n",
-				 RREG32(mmCP_HQD_PQ_BASE_HI));
-			dev_info(adev->dev, "  CP_HQD_PQ_CONTROL=0x%08X\n",
-				 RREG32(mmCP_HQD_PQ_CONTROL));
-			dev_info(adev->dev, "  CP_HQD_PQ_WPTR_POLL_ADDR=0x%08X\n",
-				 RREG32(mmCP_HQD_PQ_WPTR_POLL_ADDR));
-			dev_info(adev->dev, "  CP_HQD_PQ_WPTR_POLL_ADDR_HI=0x%08X\n",
-				 RREG32(mmCP_HQD_PQ_WPTR_POLL_ADDR_HI));
-			dev_info(adev->dev, "  CP_HQD_PQ_RPTR_REPORT_ADDR=0x%08X\n",
-				 RREG32(mmCP_HQD_PQ_RPTR_REPORT_ADDR));
-			dev_info(adev->dev, "  CP_HQD_PQ_RPTR_REPORT_ADDR_HI=0x%08X\n",
-				 RREG32(mmCP_HQD_PQ_RPTR_REPORT_ADDR_HI));
-			dev_info(adev->dev, "  CP_HQD_PQ_DOORBELL_CONTROL=0x%08X\n",
-				 RREG32(mmCP_HQD_PQ_DOORBELL_CONTROL));
-			dev_info(adev->dev, "  CP_HQD_PQ_WPTR=0x%08X\n",
-				 RREG32(mmCP_HQD_PQ_WPTR));
-			dev_info(adev->dev, "  CP_HQD_VMID=0x%08X\n",
-				 RREG32(mmCP_HQD_VMID));
-			dev_info(adev->dev, "  CP_MQD_BASE_ADDR=0x%08X\n",
-				 RREG32(mmCP_MQD_BASE_ADDR));
-			dev_info(adev->dev, "  CP_MQD_BASE_ADDR_HI=0x%08X\n",
-				 RREG32(mmCP_MQD_BASE_ADDR_HI));
-			dev_info(adev->dev, "  CP_MQD_CONTROL=0x%08X\n",
-				 RREG32(mmCP_MQD_CONTROL));
-		}
-	}
-	cik_srbm_select(adev, 0, 0, 0, 0);
-	mutex_unlock(&adev->srbm_mutex);
-
-	dev_info(adev->dev, "  CP_INT_CNTL_RING0=0x%08X\n",
-		 RREG32(mmCP_INT_CNTL_RING0));
-	dev_info(adev->dev, "  RLC_LB_CNTL=0x%08X\n",
-		 RREG32(mmRLC_LB_CNTL));
-	dev_info(adev->dev, "  RLC_CNTL=0x%08X\n",
-		 RREG32(mmRLC_CNTL));
-	dev_info(adev->dev, "  RLC_CGCG_CGLS_CTRL=0x%08X\n",
-		 RREG32(mmRLC_CGCG_CGLS_CTRL));
-	dev_info(adev->dev, "  RLC_LB_CNTR_INIT=0x%08X\n",
-		 RREG32(mmRLC_LB_CNTR_INIT));
-	dev_info(adev->dev, "  RLC_LB_CNTR_MAX=0x%08X\n",
-		 RREG32(mmRLC_LB_CNTR_MAX));
-	dev_info(adev->dev, "  RLC_LB_INIT_CU_MASK=0x%08X\n",
-		 RREG32(mmRLC_LB_INIT_CU_MASK));
-	dev_info(adev->dev, "  RLC_LB_PARAMS=0x%08X\n",
-		 RREG32(mmRLC_LB_PARAMS));
-	dev_info(adev->dev, "  RLC_LB_CNTL=0x%08X\n",
-		 RREG32(mmRLC_LB_CNTL));
-	dev_info(adev->dev, "  RLC_MC_CNTL=0x%08X\n",
-		 RREG32(mmRLC_MC_CNTL));
-	dev_info(adev->dev, "  RLC_UCODE_CNTL=0x%08X\n",
-		 RREG32(mmRLC_UCODE_CNTL));
-
-	if (adev->asic_type == CHIP_BONAIRE)
-		dev_info(adev->dev, "  RLC_DRIVER_CPDMA_STATUS=0x%08X\n",
-			 RREG32(mmRLC_DRIVER_CPDMA_STATUS));
-
-	mutex_lock(&adev->srbm_mutex);
-	for (i = 0; i < 16; i++) {
-		cik_srbm_select(adev, 0, 0, 0, i);
-		dev_info(adev->dev, "  VM %d:\n", i);
-		dev_info(adev->dev, "  SH_MEM_CONFIG=0x%08X\n",
-			 RREG32(mmSH_MEM_CONFIG));
-		dev_info(adev->dev, "  SH_MEM_APE1_BASE=0x%08X\n",
-			 RREG32(mmSH_MEM_APE1_BASE));
-		dev_info(adev->dev, "  SH_MEM_APE1_LIMIT=0x%08X\n",
-			 RREG32(mmSH_MEM_APE1_LIMIT));
-		dev_info(adev->dev, "  SH_MEM_BASES=0x%08X\n",
-			 RREG32(mmSH_MEM_BASES));
-	}
-	cik_srbm_select(adev, 0, 0, 0, 0);
-	mutex_unlock(&adev->srbm_mutex);
-}
-
 static int gfx_v7_0_soft_reset(void *handle)
 {
 	u32 grbm_soft_reset = 0, srbm_soft_reset = 0;
@@ -4826,7 +4587,6 @@ static int gfx_v7_0_soft_reset(void *han
 		srbm_soft_reset |= SRBM_SOFT_RESET__SOFT_RESET_GRBM_MASK;
 
 	if (grbm_soft_reset || srbm_soft_reset) {
-		gfx_v7_0_print_status((void *)adev);
 		/* disable CG/PG */
 		gfx_v7_0_fini_pg(adev);
 		gfx_v7_0_update_cg(adev, false);
@@ -4869,7 +4629,6 @@ static int gfx_v7_0_soft_reset(void *han
 		}
 		/* Wait a little for things to settle down */
 		udelay(50);
-		gfx_v7_0_print_status((void *)adev);
 	}
 	return 0;
 }
@@ -5045,7 +4804,7 @@ static int gfx_v7_0_eop_irq(struct amdgp
 	case 2:
 		for (i = 0; i < adev->gfx.num_compute_rings; i++) {
 			ring = &adev->gfx.compute_ring[i];
-			if ((ring->me == me_id) & (ring->pipe == pipe_id))
+			if ((ring->me == me_id) && (ring->pipe == pipe_id))
 				amdgpu_fence_process(ring);
 		}
 		break;
@@ -5121,6 +4880,7 @@ static int gfx_v7_0_set_powergating_stat
 }
 
 const struct amd_ip_funcs gfx_v7_0_ip_funcs = {
+	.name = "gfx_v7_0",
 	.early_init = gfx_v7_0_early_init,
 	.late_init = gfx_v7_0_late_init,
 	.sw_init = gfx_v7_0_sw_init,
@@ -5132,7 +4892,6 @@ const struct amd_ip_funcs gfx_v7_0_ip_fu
 	.is_idle = gfx_v7_0_is_idle,
 	.wait_for_idle = gfx_v7_0_wait_for_idle,
 	.soft_reset = gfx_v7_0_soft_reset,
-	.print_status = gfx_v7_0_print_status,
 	.set_clockgating_state = gfx_v7_0_set_clockgating_state,
 	.set_powergating_state = gfx_v7_0_set_powergating_state,
 };
@@ -5239,14 +4998,11 @@ static void gfx_v7_0_set_gds_init(struct
 }
 
 
-int gfx_v7_0_get_cu_info(struct amdgpu_device *adev,
-			 struct amdgpu_cu_info *cu_info)
+static void gfx_v7_0_get_cu_info(struct amdgpu_device *adev)
 {
 	int i, j, k, counter, active_cu_number = 0;
 	u32 mask, bitmap, ao_bitmap, ao_cu_mask = 0;
-
-	if (!adev || !cu_info)
-		return -EINVAL;
+	struct amdgpu_cu_info *cu_info = &adev->gfx.cu_info;
 
 	memset(cu_info, 0, sizeof(*cu_info));
 
@@ -5277,6 +5033,4 @@ int gfx_v7_0_get_cu_info(struct amdgpu_d
 
 	cu_info->number = active_cu_number;
 	cu_info->ao_cu_mask = ao_cu_mask;
-
-	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.h	2016-07-24 15:23:50.000000000 -0400
@@ -32,6 +32,5 @@ void gfx_v7_0_exit_rlc_safe_mode(struct
 void gfx_v7_0_rlc_stop(struct amdgpu_device *adev);
 uint64_t gfx_v7_0_get_gpu_clock_counter(struct amdgpu_device *adev);
 void gfx_v7_0_select_se_sh(struct amdgpu_device *adev, u32 se_num, u32 sh_num);
-int gfx_v7_0_get_cu_info(struct amdgpu_device *adev, struct amdgpu_cu_info *cu_info);
 
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c	2016-05-15 19:20:39.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c	2016-07-24 18:16:49.000000000 -0400
@@ -27,6 +27,8 @@
 #include "vi.h"
 #include "vid.h"
 #include "amdgpu_ucode.h"
+#include "amdgpu_atombios.h"
+#include "atombios_i2c.h"
 #include "clearstate_vi.h"
 
 #include "gmc/gmc_8_2_d.h"
@@ -46,11 +48,14 @@
 #include "dce/dce_10_0_d.h"
 #include "dce/dce_10_0_sh_mask.h"
 
+#include "smu/smu_7_1_3_d.h"
+
 #define GFX8_NUM_GFX_RINGS     1
 #define GFX8_NUM_COMPUTE_RINGS 8
 
 #define TOPAZ_GB_ADDR_CONFIG_GOLDEN 0x22010001
 #define CARRIZO_GB_ADDR_CONFIG_GOLDEN 0x22010001
+#define POLARIS11_GB_ADDR_CONFIG_GOLDEN 0x22011002
 #define TONGA_GB_ADDR_CONFIG_GOLDEN 0x22011003
 
 #define ARRAY_MODE(x)					((x) << GB_TILE_MODE0__ARRAY_MODE__SHIFT)
@@ -84,6 +89,8 @@ enum {
 	BPM_REG_FGCG_MAX
 };
 
+#define RLC_FormatDirectRegListLength        14
+
 /*(DEBLOBBED)*/
 
 static const struct amdgpu_gds_reg_offset amdgpu_gds_reg_offset[] =
@@ -216,6 +223,69 @@ static const u32 tonga_mgcg_cgcg_init[]
 	mmCP_MEM_SLP_CNTL, 0x00000001, 0x00000001,
 };
 
+static const u32 golden_settings_polaris11_a11[] =
+{
+	mmCB_HW_CONTROL, 0xfffdf3cf, 0x00006208,
+	mmCB_HW_CONTROL_3, 0x000001ff, 0x00000040,
+	mmDB_DEBUG2, 0xf00fffff, 0x00000400,
+	mmPA_SC_ENHANCE, 0xffffffff, 0x20000001,
+	mmPA_SC_LINE_STIPPLE_STATE, 0x0000ff0f, 0x00000000,
+	mmPA_SC_RASTER_CONFIG, 0x3f3fffff, 0x16000012,
+	mmPA_SC_RASTER_CONFIG_1, 0x0000003f, 0x00000000,
+	mmRLC_CGCG_CGLS_CTRL, 0x00000003, 0x0001003c,
+	mmRLC_CGCG_CGLS_CTRL_3D, 0xffffffff, 0x0001003c,
+	mmSQ_CONFIG, 0x07f80000, 0x07180000,
+	mmTA_CNTL_AUX, 0x000f000f, 0x000b0000,
+	mmTCC_CTRL, 0x00100000, 0xf31fff7f,
+	mmTCP_ADDR_CONFIG, 0x000003ff, 0x000000f3,
+	mmTCP_CHAN_STEER_HI, 0xffffffff, 0x00000000,
+	mmTCP_CHAN_STEER_LO, 0xffffffff, 0x00003210,
+	mmVGT_RESET_DEBUG, 0x00000004, 0x00000004,
+};
+
+static const u32 polaris11_golden_common_all[] =
+{
+	mmGRBM_GFX_INDEX, 0xffffffff, 0xe0000000,
+	mmGB_ADDR_CONFIG, 0xffffffff, 0x22011002,
+	mmSPI_RESOURCE_RESERVE_CU_0, 0xffffffff, 0x00000800,
+	mmSPI_RESOURCE_RESERVE_CU_1, 0xffffffff, 0x00000800,
+	mmSPI_RESOURCE_RESERVE_EN_CU_0, 0xffffffff, 0x00007FBF,
+	mmSPI_RESOURCE_RESERVE_EN_CU_1, 0xffffffff, 0x00007FAF,
+};
+
+static const u32 golden_settings_polaris10_a11[] =
+{
+	mmATC_MISC_CG, 0x000c0fc0, 0x000c0200,
+	mmCB_HW_CONTROL, 0xfffdf3cf, 0x00007208,
+	mmCB_HW_CONTROL_2, 0, 0x0f000000,
+	mmCB_HW_CONTROL_3, 0x000001ff, 0x00000040,
+	mmDB_DEBUG2, 0xf00fffff, 0x00000400,
+	mmPA_SC_ENHANCE, 0xffffffff, 0x20000001,
+	mmPA_SC_LINE_STIPPLE_STATE, 0x0000ff0f, 0x00000000,
+	mmPA_SC_RASTER_CONFIG, 0x3f3fffff, 0x16000012,
+	mmPA_SC_RASTER_CONFIG_1, 0x0000003f, 0x0000002a,
+	mmRLC_CGCG_CGLS_CTRL, 0x00000003, 0x0001003c,
+	mmRLC_CGCG_CGLS_CTRL_3D, 0xffffffff, 0x0001003c,
+	mmSQ_CONFIG, 0x07f80000, 0x07180000,
+	mmTA_CNTL_AUX, 0x000f000f, 0x000b0000,
+	mmTCC_CTRL, 0x00100000, 0xf31fff7f,
+	mmTCP_ADDR_CONFIG, 0x000003ff, 0x000000f7,
+	mmTCP_CHAN_STEER_HI, 0xffffffff, 0x00000000,
+	mmVGT_RESET_DEBUG, 0x00000004, 0x00000004,
+};
+
+static const u32 polaris10_golden_common_all[] =
+{
+	mmGRBM_GFX_INDEX, 0xffffffff, 0xe0000000,
+	mmPA_SC_RASTER_CONFIG, 0xffffffff, 0x16000012,
+	mmPA_SC_RASTER_CONFIG_1, 0xffffffff, 0x0000002A,
+	mmGB_ADDR_CONFIG, 0xffffffff, 0x22011003,
+	mmSPI_RESOURCE_RESERVE_CU_0, 0xffffffff, 0x00000800,
+	mmSPI_RESOURCE_RESERVE_CU_1, 0xffffffff, 0x00000800,
+	mmSPI_RESOURCE_RESERVE_EN_CU_0, 0xffffffff, 0x00007FBF,
+	mmSPI_RESOURCE_RESERVE_EN_CU_1, 0xffffffff, 0x00007FAF,
+};
+
 static const u32 fiji_golden_common_all[] =
 {
 	mmGRBM_GFX_INDEX, 0xffffffff, 0xe0000000,
@@ -496,7 +566,7 @@ static const u32 stoney_golden_settings_
 	mmPA_SC_LINE_STIPPLE_STATE, 0x0000ff0f, 0x00000000,
 	mmRLC_CGCG_CGLS_CTRL, 0x00000003, 0x0001003c,
 	mmTA_CNTL_AUX, 0x000f000f, 0x000b0000,
-  	mmTCC_CTRL, 0x00100000, 0xf31fff7f,
+	mmTCC_CTRL, 0x00100000, 0xf31fff7f,
 	mmTCC_EXE_DISABLE, 0x00000002, 0x00000002,
 	mmTCP_ADDR_CONFIG, 0x0000000f, 0x000000f1,
 	mmTCP_CHAN_STEER_LO, 0xffffffff, 0x10101010,
@@ -527,6 +597,9 @@ static const u32 stoney_mgcg_cgcg_init[]
 static void gfx_v8_0_set_ring_funcs(struct amdgpu_device *adev);
 static void gfx_v8_0_set_irq_funcs(struct amdgpu_device *adev);
 static void gfx_v8_0_set_gds_init(struct amdgpu_device *adev);
+static void gfx_v8_0_set_rlc_funcs(struct amdgpu_device *adev);
+static u32 gfx_v8_0_get_csb_size(struct amdgpu_device *adev);
+static void gfx_v8_0_get_cu_info(struct amdgpu_device *adev);
 
 static void gfx_v8_0_init_golden_registers(struct amdgpu_device *adev)
 {
@@ -565,6 +638,27 @@ static void gfx_v8_0_init_golden_registe
 						 tonga_golden_common_all,
 						 (const u32)ARRAY_SIZE(tonga_golden_common_all));
 		break;
+	case CHIP_POLARIS11:
+		amdgpu_program_register_sequence(adev,
+						 golden_settings_polaris11_a11,
+						 (const u32)ARRAY_SIZE(golden_settings_polaris11_a11));
+		amdgpu_program_register_sequence(adev,
+						 polaris11_golden_common_all,
+						 (const u32)ARRAY_SIZE(polaris11_golden_common_all));
+		break;
+	case CHIP_POLARIS10:
+		amdgpu_program_register_sequence(adev,
+						 golden_settings_polaris10_a11,
+						 (const u32)ARRAY_SIZE(golden_settings_polaris10_a11));
+		amdgpu_program_register_sequence(adev,
+						 polaris10_golden_common_all,
+						 (const u32)ARRAY_SIZE(polaris10_golden_common_all));
+		WREG32_SMC(ixCG_ACLK_CNTL, 0x0000001C);
+		if (adev->pdev->revision == 0xc7) {
+			amdgpu_atombios_i2c_channel_trans(adev, 0x10, 0x96, 0x1E, 0xDD);
+			amdgpu_atombios_i2c_channel_trans(adev, 0x10, 0x96, 0x1F, 0xD0);
+		}
+		break;
 	case CHIP_CARRIZO:
 		amdgpu_program_register_sequence(adev,
 						 cz_mgcg_cgcg_init,
@@ -675,7 +769,7 @@ static int gfx_v8_0_ring_test_ib(struct
 	ib.ptr[2] = 0xDEADBEEF;
 	ib.length_dw = 3;
 
-	r = amdgpu_ib_schedule(ring, 1, &ib, NULL, &f);
+	r = amdgpu_ib_schedule(ring, 1, &ib, NULL, NULL, &f);
 	if (r)
 		goto err2;
 
@@ -708,6 +802,26 @@ err1:
 	return r;
 }
 
+
+static void gfx_v8_0_free_microcode(struct amdgpu_device *adev) {
+	release_firmware(adev->gfx.pfp_fw);
+	adev->gfx.pfp_fw = NULL;
+	release_firmware(adev->gfx.me_fw);
+	adev->gfx.me_fw = NULL;
+	release_firmware(adev->gfx.ce_fw);
+	adev->gfx.ce_fw = NULL;
+	release_firmware(adev->gfx.rlc_fw);
+	adev->gfx.rlc_fw = NULL;
+	release_firmware(adev->gfx.mec_fw);
+	adev->gfx.mec_fw = NULL;
+	if ((adev->asic_type != CHIP_STONEY) &&
+	    (adev->asic_type != CHIP_TOPAZ))
+		release_firmware(adev->gfx.mec2_fw);
+	adev->gfx.mec2_fw = NULL;
+
+	kfree(adev->gfx.rlc.register_list_format);
+}
+
 static int gfx_v8_0_init_microcode(struct amdgpu_device *adev)
 {
 	const char *chip_name;
@@ -716,6 +830,8 @@ static int gfx_v8_0_init_microcode(struc
 	struct amdgpu_firmware_info *info = NULL;
 	const struct common_firmware_header *header = NULL;
 	const struct gfx_firmware_header_v1_0 *cp_hdr;
+	const struct rlc_firmware_header_v2_0 *rlc_hdr;
+	unsigned int *tmp = NULL, i;
 
 	DRM_DEBUG("\n");
 
@@ -732,6 +848,12 @@ static int gfx_v8_0_init_microcode(struc
 	case CHIP_FIJI:
 		chip_name = "fiji";
 		break;
+	case CHIP_POLARIS11:
+		chip_name = "polaris11";
+		break;
+	case CHIP_POLARIS10:
+		chip_name = "polaris10";
+		break;
 	case CHIP_STONEY:
 		chip_name = "stoney";
 		break;
@@ -777,9 +899,49 @@ static int gfx_v8_0_init_microcode(struc
 	if (err)
 		goto out;
 	err = amdgpu_ucode_validate(adev->gfx.rlc_fw);
-	cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.rlc_fw->data;
-	adev->gfx.rlc_fw_version = le32_to_cpu(cp_hdr->header.ucode_version);
-	adev->gfx.rlc_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version);
+	rlc_hdr = (const struct rlc_firmware_header_v2_0 *)adev->gfx.rlc_fw->data;
+	adev->gfx.rlc_fw_version = le32_to_cpu(rlc_hdr->header.ucode_version);
+	adev->gfx.rlc_feature_version = le32_to_cpu(rlc_hdr->ucode_feature_version);
+
+	adev->gfx.rlc.save_and_restore_offset =
+			le32_to_cpu(rlc_hdr->save_and_restore_offset);
+	adev->gfx.rlc.clear_state_descriptor_offset =
+			le32_to_cpu(rlc_hdr->clear_state_descriptor_offset);
+	adev->gfx.rlc.avail_scratch_ram_locations =
+			le32_to_cpu(rlc_hdr->avail_scratch_ram_locations);
+	adev->gfx.rlc.reg_restore_list_size =
+			le32_to_cpu(rlc_hdr->reg_restore_list_size);
+	adev->gfx.rlc.reg_list_format_start =
+			le32_to_cpu(rlc_hdr->reg_list_format_start);
+	adev->gfx.rlc.reg_list_format_separate_start =
+			le32_to_cpu(rlc_hdr->reg_list_format_separate_start);
+	adev->gfx.rlc.starting_offsets_start =
+			le32_to_cpu(rlc_hdr->starting_offsets_start);
+	adev->gfx.rlc.reg_list_format_size_bytes =
+			le32_to_cpu(rlc_hdr->reg_list_format_size_bytes);
+	adev->gfx.rlc.reg_list_size_bytes =
+			le32_to_cpu(rlc_hdr->reg_list_size_bytes);
+
+	adev->gfx.rlc.register_list_format =
+			kmalloc(adev->gfx.rlc.reg_list_format_size_bytes +
+					adev->gfx.rlc.reg_list_size_bytes, GFP_KERNEL);
+
+	if (!adev->gfx.rlc.register_list_format) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	tmp = (unsigned int *)((uintptr_t)rlc_hdr +
+			le32_to_cpu(rlc_hdr->reg_list_format_array_offset_bytes));
+	for (i = 0 ; i < (rlc_hdr->reg_list_format_size_bytes >> 2); i++)
+		adev->gfx.rlc.register_list_format[i] =	le32_to_cpu(tmp[i]);
+
+	adev->gfx.rlc.register_restore = adev->gfx.rlc.register_list_format + i;
+
+	tmp = (unsigned int *)((uintptr_t)rlc_hdr +
+			le32_to_cpu(rlc_hdr->reg_list_array_offset_bytes));
+	for (i = 0 ; i < (rlc_hdr->reg_list_size_bytes >> 2); i++)
+		adev->gfx.rlc.register_restore[i] = le32_to_cpu(tmp[i]);
 
 	snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
 	err = reject_firmware(&adev->gfx.mec_fw, fw_name, adev->dev);
@@ -880,6 +1042,153 @@ out:
 	return err;
 }
 
+static void gfx_v8_0_get_csb_buffer(struct amdgpu_device *adev,
+				    volatile u32 *buffer)
+{
+	u32 count = 0, i;
+	const struct cs_section_def *sect = NULL;
+	const struct cs_extent_def *ext = NULL;
+
+	if (adev->gfx.rlc.cs_data == NULL)
+		return;
+	if (buffer == NULL)
+		return;
+
+	buffer[count++] = cpu_to_le32(PACKET3(PACKET3_PREAMBLE_CNTL, 0));
+	buffer[count++] = cpu_to_le32(PACKET3_PREAMBLE_BEGIN_CLEAR_STATE);
+
+	buffer[count++] = cpu_to_le32(PACKET3(PACKET3_CONTEXT_CONTROL, 1));
+	buffer[count++] = cpu_to_le32(0x80000000);
+	buffer[count++] = cpu_to_le32(0x80000000);
+
+	for (sect = adev->gfx.rlc.cs_data; sect->section != NULL; ++sect) {
+		for (ext = sect->section; ext->extent != NULL; ++ext) {
+			if (sect->id == SECT_CONTEXT) {
+				buffer[count++] =
+					cpu_to_le32(PACKET3(PACKET3_SET_CONTEXT_REG, ext->reg_count));
+				buffer[count++] = cpu_to_le32(ext->reg_index -
+						PACKET3_SET_CONTEXT_REG_START);
+				for (i = 0; i < ext->reg_count; i++)
+					buffer[count++] = cpu_to_le32(ext->extent[i]);
+			} else {
+				return;
+			}
+		}
+	}
+
+	buffer[count++] = cpu_to_le32(PACKET3(PACKET3_SET_CONTEXT_REG, 2));
+	buffer[count++] = cpu_to_le32(mmPA_SC_RASTER_CONFIG -
+			PACKET3_SET_CONTEXT_REG_START);
+	switch (adev->asic_type) {
+	case CHIP_TONGA:
+	case CHIP_POLARIS10:
+		buffer[count++] = cpu_to_le32(0x16000012);
+		buffer[count++] = cpu_to_le32(0x0000002A);
+		break;
+	case CHIP_POLARIS11:
+		buffer[count++] = cpu_to_le32(0x16000012);
+		buffer[count++] = cpu_to_le32(0x00000000);
+		break;
+	case CHIP_FIJI:
+		buffer[count++] = cpu_to_le32(0x3a00161a);
+		buffer[count++] = cpu_to_le32(0x0000002e);
+		break;
+	case CHIP_TOPAZ:
+	case CHIP_CARRIZO:
+		buffer[count++] = cpu_to_le32(0x00000002);
+		buffer[count++] = cpu_to_le32(0x00000000);
+		break;
+	case CHIP_STONEY:
+		buffer[count++] = cpu_to_le32(0x00000000);
+		buffer[count++] = cpu_to_le32(0x00000000);
+		break;
+	default:
+		buffer[count++] = cpu_to_le32(0x00000000);
+		buffer[count++] = cpu_to_le32(0x00000000);
+		break;
+	}
+
+	buffer[count++] = cpu_to_le32(PACKET3(PACKET3_PREAMBLE_CNTL, 0));
+	buffer[count++] = cpu_to_le32(PACKET3_PREAMBLE_END_CLEAR_STATE);
+
+	buffer[count++] = cpu_to_le32(PACKET3(PACKET3_CLEAR_STATE, 0));
+	buffer[count++] = cpu_to_le32(0);
+}
+
+static void gfx_v8_0_rlc_fini(struct amdgpu_device *adev)
+{
+	int r;
+
+	/* clear state block */
+	if (adev->gfx.rlc.clear_state_obj) {
+		r = amdgpu_bo_reserve(adev->gfx.rlc.clear_state_obj, false);
+		if (unlikely(r != 0))
+			dev_warn(adev->dev, "(%d) reserve RLC c bo failed\n", r);
+		amdgpu_bo_unpin(adev->gfx.rlc.clear_state_obj);
+		amdgpu_bo_unreserve(adev->gfx.rlc.clear_state_obj);
+
+		amdgpu_bo_unref(&adev->gfx.rlc.clear_state_obj);
+		adev->gfx.rlc.clear_state_obj = NULL;
+	}
+}
+
+static int gfx_v8_0_rlc_init(struct amdgpu_device *adev)
+{
+	volatile u32 *dst_ptr;
+	u32 dws;
+	const struct cs_section_def *cs_data;
+	int r;
+
+	adev->gfx.rlc.cs_data = vi_cs_data;
+
+	cs_data = adev->gfx.rlc.cs_data;
+
+	if (cs_data) {
+		/* clear state block */
+		adev->gfx.rlc.clear_state_size = dws = gfx_v8_0_get_csb_size(adev);
+
+		if (adev->gfx.rlc.clear_state_obj == NULL) {
+			r = amdgpu_bo_create(adev, dws * 4, PAGE_SIZE, true,
+					     AMDGPU_GEM_DOMAIN_VRAM,
+					     AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+					     NULL, NULL,
+					     &adev->gfx.rlc.clear_state_obj);
+			if (r) {
+				dev_warn(adev->dev, "(%d) create RLC c bo failed\n", r);
+				gfx_v8_0_rlc_fini(adev);
+				return r;
+			}
+		}
+		r = amdgpu_bo_reserve(adev->gfx.rlc.clear_state_obj, false);
+		if (unlikely(r != 0)) {
+			gfx_v8_0_rlc_fini(adev);
+			return r;
+		}
+		r = amdgpu_bo_pin(adev->gfx.rlc.clear_state_obj, AMDGPU_GEM_DOMAIN_VRAM,
+				  &adev->gfx.rlc.clear_state_gpu_addr);
+		if (r) {
+			amdgpu_bo_unreserve(adev->gfx.rlc.clear_state_obj);
+			dev_warn(adev->dev, "(%d) pin RLC c bo failed\n", r);
+			gfx_v8_0_rlc_fini(adev);
+			return r;
+		}
+
+		r = amdgpu_bo_kmap(adev->gfx.rlc.clear_state_obj, (void **)&adev->gfx.rlc.cs_ptr);
+		if (r) {
+			dev_warn(adev->dev, "(%d) map RLC c bo failed\n", r);
+			gfx_v8_0_rlc_fini(adev);
+			return r;
+		}
+		/* set up the cs buffer */
+		dst_ptr = adev->gfx.rlc.cs_ptr;
+		gfx_v8_0_get_csb_buffer(adev, dst_ptr);
+		amdgpu_bo_kunmap(adev->gfx.rlc.clear_state_obj);
+		amdgpu_bo_unreserve(adev->gfx.rlc.clear_state_obj);
+	}
+
+	return 0;
+}
+
 static void gfx_v8_0_mec_fini(struct amdgpu_device *adev)
 {
 	int r;
@@ -1231,7 +1540,7 @@ static int gfx_v8_0_do_edc_gpr_workaroun
 	ib.ptr[ib.length_dw++] = EVENT_TYPE(7) | EVENT_INDEX(4);
 
 	/* shedule the ib on the ring */
-	r = amdgpu_ib_schedule(ring, 1, &ib, NULL, &f);
+	r = amdgpu_ib_schedule(ring, 1, &ib, NULL, NULL, &f);
 	if (r) {
 		DRM_ERROR("amdgpu: ib submit failed (%d).\n", r);
 		goto fail;
@@ -1265,12 +1574,13 @@ fail:
 	return r;
 }
 
-static void gfx_v8_0_gpu_early_init(struct amdgpu_device *adev)
+static int gfx_v8_0_gpu_early_init(struct amdgpu_device *adev)
 {
 	u32 gb_addr_config;
 	u32 mc_shared_chmap, mc_arb_ramcfg;
 	u32 dimm00_addr_map, dimm01_addr_map, dimm10_addr_map, dimm11_addr_map;
 	u32 tmp;
+	int ret;
 
 	switch (adev->asic_type) {
 	case CHIP_TOPAZ:
@@ -1307,6 +1617,34 @@ static void gfx_v8_0_gpu_early_init(stru
 		adev->gfx.config.sc_earlyz_tile_fifo_size = 0x130;
 		gb_addr_config = TONGA_GB_ADDR_CONFIG_GOLDEN;
 		break;
+	case CHIP_POLARIS11:
+		ret = amdgpu_atombios_get_gfx_info(adev);
+		if (ret)
+			return ret;
+		adev->gfx.config.max_gprs = 256;
+		adev->gfx.config.max_gs_threads = 32;
+		adev->gfx.config.max_hw_contexts = 8;
+
+		adev->gfx.config.sc_prim_fifo_size_frontend = 0x20;
+		adev->gfx.config.sc_prim_fifo_size_backend = 0x100;
+		adev->gfx.config.sc_hiz_tile_fifo_size = 0x30;
+		adev->gfx.config.sc_earlyz_tile_fifo_size = 0x130;
+		gb_addr_config = POLARIS11_GB_ADDR_CONFIG_GOLDEN;
+		break;
+	case CHIP_POLARIS10:
+		ret = amdgpu_atombios_get_gfx_info(adev);
+		if (ret)
+			return ret;
+		adev->gfx.config.max_gprs = 256;
+		adev->gfx.config.max_gs_threads = 32;
+		adev->gfx.config.max_hw_contexts = 8;
+
+		adev->gfx.config.sc_prim_fifo_size_frontend = 0x20;
+		adev->gfx.config.sc_prim_fifo_size_backend = 0x100;
+		adev->gfx.config.sc_hiz_tile_fifo_size = 0x30;
+		adev->gfx.config.sc_earlyz_tile_fifo_size = 0x130;
+		gb_addr_config = TONGA_GB_ADDR_CONFIG_GOLDEN;
+		break;
 	case CHIP_TONGA:
 		adev->gfx.config.max_shader_engines = 4;
 		adev->gfx.config.max_tile_pipes = 8;
@@ -1489,6 +1827,8 @@ static void gfx_v8_0_gpu_early_init(stru
 		break;
 	}
 	adev->gfx.config.gb_addr_config = gb_addr_config;
+
+	return 0;
 }
 
 static int gfx_v8_0_sw_init(void *handle)
@@ -1522,6 +1862,12 @@ static int gfx_v8_0_sw_init(void *handle
 		return r;
 	}
 
+	r = gfx_v8_0_rlc_init(adev);
+	if (r) {
+		DRM_ERROR("Failed to init rlc BOs!\n");
+		return r;
+	}
+
 	r = gfx_v8_0_mec_init(adev);
 	if (r) {
 		DRM_ERROR("Failed to init MEC BOs!\n");
@@ -1539,7 +1885,7 @@ static int gfx_v8_0_sw_init(void *handle
 			ring->doorbell_index = AMDGPU_DOORBELL_GFX_RING0;
 		}
 
-		r = amdgpu_ring_init(adev, ring, 1024 * 1024,
+		r = amdgpu_ring_init(adev, ring, 1024,
 				     PACKET3(PACKET3_NOP, 0x3FFF), 0xf,
 				     &adev->gfx.eop_irq, AMDGPU_CP_IRQ_GFX_EOP,
 				     AMDGPU_RING_TYPE_GFX);
@@ -1563,10 +1909,10 @@ static int gfx_v8_0_sw_init(void *handle
 		ring->me = 1; /* first MEC */
 		ring->pipe = i / 8;
 		ring->queue = i % 8;
-		sprintf(ring->name, "comp %d.%d.%d", ring->me, ring->pipe, ring->queue);
+		sprintf(ring->name, "comp_%d.%d.%d", ring->me, ring->pipe, ring->queue);
 		irq_type = AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE0_EOP + ring->pipe;
 		/* type-2 packets are deprecated on MEC, use type-3 instead */
-		r = amdgpu_ring_init(adev, ring, 1024 * 1024,
+		r = amdgpu_ring_init(adev, ring, 1024,
 				     PACKET3(PACKET3_NOP, 0x3FFF), 0xf,
 				     &adev->gfx.eop_irq, irq_type,
 				     AMDGPU_RING_TYPE_COMPUTE);
@@ -1598,7 +1944,9 @@ static int gfx_v8_0_sw_init(void *handle
 
 	adev->gfx.ce_ram_size = 0x8000;
 
-	gfx_v8_0_gpu_early_init(adev);
+	r = gfx_v8_0_gpu_early_init(adev);
+	if (r)
+		return r;
 
 	return 0;
 }
@@ -1619,6 +1967,10 @@ static int gfx_v8_0_sw_fini(void *handle
 
 	gfx_v8_0_mec_fini(adev);
 
+	gfx_v8_0_rlc_fini(adev);
+
+	gfx_v8_0_free_microcode(adev);
+
 	return 0;
 }
 
@@ -2188,6 +2540,410 @@ static void gfx_v8_0_tiling_mode_table_i
 				WREG32(mmGB_MACROTILE_MODE0 + reg_offset, mod2array[reg_offset]);
 
 		break;
+	case CHIP_POLARIS11:
+		modearray[0] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[1] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[2] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[3] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[4] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[5] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[6] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[7] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[8] = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) |
+				PIPE_CONFIG(ADDR_SURF_P4_16x16));
+		modearray[9] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[10] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[11] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+		modearray[12] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+		modearray[13] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[14] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[15] = (ARRAY_MODE(ARRAY_3D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[16] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+		modearray[17] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+		modearray[18] = (ARRAY_MODE(ARRAY_1D_TILED_THICK) |
+				PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[19] = (ARRAY_MODE(ARRAY_1D_TILED_THICK) |
+				PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[20] = (ARRAY_MODE(ARRAY_2D_TILED_THICK) |
+				PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[21] = (ARRAY_MODE(ARRAY_3D_TILED_THICK) |
+				PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[22] = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) |
+				PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[23] = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) |
+				PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[24] = (ARRAY_MODE(ARRAY_2D_TILED_THICK) |
+				PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[25] = (ARRAY_MODE(ARRAY_2D_TILED_XTHICK) |
+				PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[26] = (ARRAY_MODE(ARRAY_3D_TILED_XTHICK) |
+				PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[27] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[28] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[29] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+		modearray[30] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+
+		mod2array[0] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				NUM_BANKS(ADDR_SURF_16_BANK));
+
+		mod2array[1] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				NUM_BANKS(ADDR_SURF_16_BANK));
+
+		mod2array[2] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				NUM_BANKS(ADDR_SURF_16_BANK));
+
+		mod2array[3] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				NUM_BANKS(ADDR_SURF_16_BANK));
+
+		mod2array[4] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+				NUM_BANKS(ADDR_SURF_16_BANK));
+
+		mod2array[5] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+				NUM_BANKS(ADDR_SURF_16_BANK));
+
+		mod2array[6] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+				NUM_BANKS(ADDR_SURF_16_BANK));
+
+		mod2array[8] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_8) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				NUM_BANKS(ADDR_SURF_16_BANK));
+
+		mod2array[9] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				NUM_BANKS(ADDR_SURF_16_BANK));
+
+		mod2array[10] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				NUM_BANKS(ADDR_SURF_16_BANK));
+
+		mod2array[11] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				NUM_BANKS(ADDR_SURF_16_BANK));
+
+		mod2array[12] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+				NUM_BANKS(ADDR_SURF_16_BANK));
+
+		mod2array[13] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+				NUM_BANKS(ADDR_SURF_8_BANK));
+
+		mod2array[14] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+				NUM_BANKS(ADDR_SURF_4_BANK));
+
+		for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++)
+			WREG32(mmGB_TILE_MODE0 + reg_offset, modearray[reg_offset]);
+
+		for (reg_offset = 0; reg_offset < num_secondary_tile_mode_states; reg_offset++)
+			if (reg_offset != 7)
+				WREG32(mmGB_MACROTILE_MODE0 + reg_offset, mod2array[reg_offset]);
+
+		break;
+	case CHIP_POLARIS10:
+		modearray[0] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[1] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[2] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[3] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[4] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[5] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[6] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[7] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
+		modearray[8] = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) |
+				PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16));
+		modearray[9] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[10] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[11] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+		modearray[12] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+		modearray[13] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[14] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[15] = (ARRAY_MODE(ARRAY_3D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[16] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+		modearray[17] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+		modearray[18] = (ARRAY_MODE(ARRAY_1D_TILED_THICK) |
+				PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[19] = (ARRAY_MODE(ARRAY_1D_TILED_THICK) |
+				PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[20] = (ARRAY_MODE(ARRAY_2D_TILED_THICK) |
+				PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[21] = (ARRAY_MODE(ARRAY_3D_TILED_THICK) |
+				PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[22] = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) |
+				PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[23] = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) |
+				PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[24] = (ARRAY_MODE(ARRAY_2D_TILED_THICK) |
+				PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[25] = (ARRAY_MODE(ARRAY_2D_TILED_XTHICK) |
+				PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[26] = (ARRAY_MODE(ARRAY_3D_TILED_XTHICK) |
+				PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1));
+		modearray[27] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[28] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2));
+		modearray[29] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+		modearray[30] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) |
+				PIPE_CONFIG(ADDR_SURF_P4_16x16) |
+				MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+				SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8));
+
+		mod2array[0] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				NUM_BANKS(ADDR_SURF_16_BANK));
+
+		mod2array[1] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				NUM_BANKS(ADDR_SURF_16_BANK));
+
+		mod2array[2] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				NUM_BANKS(ADDR_SURF_16_BANK));
+
+		mod2array[3] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				NUM_BANKS(ADDR_SURF_16_BANK));
+
+		mod2array[4] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+				NUM_BANKS(ADDR_SURF_16_BANK));
+
+		mod2array[5] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+				NUM_BANKS(ADDR_SURF_16_BANK));
+
+		mod2array[6] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+				NUM_BANKS(ADDR_SURF_16_BANK));
+
+		mod2array[8] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_8) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				NUM_BANKS(ADDR_SURF_16_BANK));
+
+		mod2array[9] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+				NUM_BANKS(ADDR_SURF_16_BANK));
+
+		mod2array[10] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+				NUM_BANKS(ADDR_SURF_16_BANK));
+
+		mod2array[11] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+				NUM_BANKS(ADDR_SURF_16_BANK));
+
+		mod2array[12] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+				NUM_BANKS(ADDR_SURF_8_BANK));
+
+		mod2array[13] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+				NUM_BANKS(ADDR_SURF_4_BANK));
+
+		mod2array[14] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+				BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+				MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+				NUM_BANKS(ADDR_SURF_4_BANK));
+
+		for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++)
+			WREG32(mmGB_TILE_MODE0 + reg_offset, modearray[reg_offset]);
+
+		for (reg_offset = 0; reg_offset < num_secondary_tile_mode_states; reg_offset++)
+			if (reg_offset != 7)
+				WREG32(mmGB_MACROTILE_MODE0 + reg_offset, mod2array[reg_offset]);
+
+		break;
 	case CHIP_STONEY:
 		modearray[0] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
 				PIPE_CONFIG(ADDR_SURF_P2) |
@@ -2664,6 +3420,7 @@ static void gfx_v8_0_gpu_init(struct amd
 	gfx_v8_0_tiling_mode_table_init(adev);
 
 	gfx_v8_0_setup_rb(adev);
+	gfx_v8_0_get_cu_info(adev);
 
 	/* XXX SH_MEM regs */
 	/* where to put LDS, scratch, GPUVM in FSA64 space */
@@ -2757,6 +3514,188 @@ static void gfx_v8_0_enable_gui_idle_int
 	WREG32(mmCP_INT_CNTL_RING0, tmp);
 }
 
+static void gfx_v8_0_init_csb(struct amdgpu_device *adev)
+{
+	/* csib */
+	WREG32(mmRLC_CSIB_ADDR_HI,
+			adev->gfx.rlc.clear_state_gpu_addr >> 32);
+	WREG32(mmRLC_CSIB_ADDR_LO,
+			adev->gfx.rlc.clear_state_gpu_addr & 0xfffffffc);
+	WREG32(mmRLC_CSIB_LENGTH,
+			adev->gfx.rlc.clear_state_size);
+}
+
+static void gfx_v8_0_parse_ind_reg_list(int *register_list_format,
+				int ind_offset,
+				int list_size,
+				int *unique_indices,
+				int *indices_count,
+				int max_indices,
+				int *ind_start_offsets,
+				int *offset_count,
+				int max_offset)
+{
+	int indices;
+	bool new_entry = true;
+
+	for (; ind_offset < list_size; ind_offset++) {
+
+		if (new_entry) {
+			new_entry = false;
+			ind_start_offsets[*offset_count] = ind_offset;
+			*offset_count = *offset_count + 1;
+			BUG_ON(*offset_count >= max_offset);
+		}
+
+		if (register_list_format[ind_offset] == 0xFFFFFFFF) {
+			new_entry = true;
+			continue;
+		}
+
+		ind_offset += 2;
+
+		/* look for the matching indice */
+		for (indices = 0;
+			indices < *indices_count;
+			indices++) {
+			if (unique_indices[indices] ==
+				register_list_format[ind_offset])
+				break;
+		}
+
+		if (indices >= *indices_count) {
+			unique_indices[*indices_count] =
+				register_list_format[ind_offset];
+			indices = *indices_count;
+			*indices_count = *indices_count + 1;
+			BUG_ON(*indices_count >= max_indices);
+		}
+
+		register_list_format[ind_offset] = indices;
+	}
+}
+
+static int gfx_v8_0_init_save_restore_list(struct amdgpu_device *adev)
+{
+	int i, temp, data;
+	int unique_indices[] = {0, 0, 0, 0, 0, 0, 0, 0};
+	int indices_count = 0;
+	int indirect_start_offsets[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+	int offset_count = 0;
+
+	int list_size;
+	unsigned int *register_list_format =
+		kmalloc(adev->gfx.rlc.reg_list_format_size_bytes, GFP_KERNEL);
+	if (register_list_format == NULL)
+		return -ENOMEM;
+	memcpy(register_list_format, adev->gfx.rlc.register_list_format,
+			adev->gfx.rlc.reg_list_format_size_bytes);
+
+	gfx_v8_0_parse_ind_reg_list(register_list_format,
+				RLC_FormatDirectRegListLength,
+				adev->gfx.rlc.reg_list_format_size_bytes >> 2,
+				unique_indices,
+				&indices_count,
+				sizeof(unique_indices) / sizeof(int),
+				indirect_start_offsets,
+				&offset_count,
+				sizeof(indirect_start_offsets)/sizeof(int));
+
+	/* save and restore list */
+	temp = RREG32(mmRLC_SRM_CNTL);
+	temp |= RLC_SRM_CNTL__AUTO_INCR_ADDR_MASK;
+	WREG32(mmRLC_SRM_CNTL, temp);
+
+	WREG32(mmRLC_SRM_ARAM_ADDR, 0);
+	for (i = 0; i < adev->gfx.rlc.reg_list_size_bytes >> 2; i++)
+		WREG32(mmRLC_SRM_ARAM_DATA, adev->gfx.rlc.register_restore[i]);
+
+	/* indirect list */
+	WREG32(mmRLC_GPM_SCRATCH_ADDR, adev->gfx.rlc.reg_list_format_start);
+	for (i = 0; i < adev->gfx.rlc.reg_list_format_size_bytes >> 2; i++)
+		WREG32(mmRLC_GPM_SCRATCH_DATA, register_list_format[i]);
+
+	list_size = adev->gfx.rlc.reg_list_size_bytes >> 2;
+	list_size = list_size >> 1;
+	WREG32(mmRLC_GPM_SCRATCH_ADDR, adev->gfx.rlc.reg_restore_list_size);
+	WREG32(mmRLC_GPM_SCRATCH_DATA, list_size);
+
+	/* starting offsets starts */
+	WREG32(mmRLC_GPM_SCRATCH_ADDR,
+		adev->gfx.rlc.starting_offsets_start);
+	for (i = 0; i < sizeof(indirect_start_offsets)/sizeof(int); i++)
+		WREG32(mmRLC_GPM_SCRATCH_DATA,
+				indirect_start_offsets[i]);
+
+	/* unique indices */
+	temp = mmRLC_SRM_INDEX_CNTL_ADDR_0;
+	data = mmRLC_SRM_INDEX_CNTL_DATA_0;
+	for (i = 0; i < sizeof(unique_indices) / sizeof(int); i++) {
+		amdgpu_mm_wreg(adev, temp + i, unique_indices[i] & 0x3FFFF, false);
+		amdgpu_mm_wreg(adev, data + i, unique_indices[i] >> 20, false);
+	}
+	kfree(register_list_format);
+
+	return 0;
+}
+
+static void gfx_v8_0_enable_save_restore_machine(struct amdgpu_device *adev)
+{
+	uint32_t data;
+
+	data = RREG32(mmRLC_SRM_CNTL);
+	data |= RLC_SRM_CNTL__SRM_ENABLE_MASK;
+	WREG32(mmRLC_SRM_CNTL, data);
+}
+
+static void polaris11_init_power_gating(struct amdgpu_device *adev)
+{
+	uint32_t data;
+
+	if (adev->pg_flags & (AMD_PG_SUPPORT_GFX_PG |
+			AMD_PG_SUPPORT_GFX_SMG |
+			AMD_PG_SUPPORT_GFX_DMG)) {
+		data = RREG32(mmCP_RB_WPTR_POLL_CNTL);
+		data &= ~CP_RB_WPTR_POLL_CNTL__IDLE_POLL_COUNT_MASK;
+		data |= (0x60 << CP_RB_WPTR_POLL_CNTL__IDLE_POLL_COUNT__SHIFT);
+		WREG32(mmCP_RB_WPTR_POLL_CNTL, data);
+
+		data = 0;
+		data |= (0x10 << RLC_PG_DELAY__POWER_UP_DELAY__SHIFT);
+		data |= (0x10 << RLC_PG_DELAY__POWER_DOWN_DELAY__SHIFT);
+		data |= (0x10 << RLC_PG_DELAY__CMD_PROPAGATE_DELAY__SHIFT);
+		data |= (0x10 << RLC_PG_DELAY__MEM_SLEEP_DELAY__SHIFT);
+		WREG32(mmRLC_PG_DELAY, data);
+
+		data = RREG32(mmRLC_PG_DELAY_2);
+		data &= ~RLC_PG_DELAY_2__SERDES_CMD_DELAY_MASK;
+		data |= (0x3 << RLC_PG_DELAY_2__SERDES_CMD_DELAY__SHIFT);
+		WREG32(mmRLC_PG_DELAY_2, data);
+
+		data = RREG32(mmRLC_AUTO_PG_CTRL);
+		data &= ~RLC_AUTO_PG_CTRL__GRBM_REG_SAVE_GFX_IDLE_THRESHOLD_MASK;
+		data |= (0x55f0 << RLC_AUTO_PG_CTRL__GRBM_REG_SAVE_GFX_IDLE_THRESHOLD__SHIFT);
+		WREG32(mmRLC_AUTO_PG_CTRL, data);
+	}
+}
+
+static void gfx_v8_0_init_pg(struct amdgpu_device *adev)
+{
+	if (adev->pg_flags & (AMD_PG_SUPPORT_GFX_PG |
+			      AMD_PG_SUPPORT_GFX_SMG |
+			      AMD_PG_SUPPORT_GFX_DMG |
+			      AMD_PG_SUPPORT_CP |
+			      AMD_PG_SUPPORT_GDS |
+			      AMD_PG_SUPPORT_RLC_SMU_HS)) {
+		gfx_v8_0_init_csb(adev);
+		gfx_v8_0_init_save_restore_list(adev);
+		gfx_v8_0_enable_save_restore_machine(adev);
+
+		if (adev->asic_type == CHIP_POLARIS11)
+			polaris11_init_power_gating(adev);
+	}
+}
+
 void gfx_v8_0_rlc_stop(struct amdgpu_device *adev)
 {
 	u32 tmp = RREG32(mmRLC_CNTL);
@@ -2827,12 +3766,17 @@ static int gfx_v8_0_rlc_resume(struct am
 
 	/* disable CG */
 	WREG32(mmRLC_CGCG_CGLS_CTRL, 0);
+	if (adev->asic_type == CHIP_POLARIS11 ||
+		adev->asic_type == CHIP_POLARIS10)
+		WREG32(mmRLC_CGCG_CGLS_CTRL_3D, 0);
 
 	/* disable PG */
 	WREG32(mmRLC_PG_CNTL, 0);
 
 	gfx_v8_0_rlc_reset(adev);
 
+	gfx_v8_0_init_pg(adev);
+
 	if (!adev->pp_enabled) {
 		if (!adev->firmware.smu_load) {
 			/* legacy rlc firmware loading */
@@ -3004,18 +3948,27 @@ static int gfx_v8_0_cp_gfx_start(struct
 	amdgpu_ring_write(ring, mmPA_SC_RASTER_CONFIG - PACKET3_SET_CONTEXT_REG_START);
 	switch (adev->asic_type) {
 	case CHIP_TONGA:
+	case CHIP_POLARIS10:
 		amdgpu_ring_write(ring, 0x16000012);
 		amdgpu_ring_write(ring, 0x0000002A);
 		break;
+	case CHIP_POLARIS11:
+		amdgpu_ring_write(ring, 0x16000012);
+		amdgpu_ring_write(ring, 0x00000000);
+		break;
 	case CHIP_FIJI:
 		amdgpu_ring_write(ring, 0x3a00161a);
 		amdgpu_ring_write(ring, 0x0000002e);
 		break;
-	case CHIP_TOPAZ:
 	case CHIP_CARRIZO:
 		amdgpu_ring_write(ring, 0x00000002);
 		amdgpu_ring_write(ring, 0x00000000);
 		break;
+	case CHIP_TOPAZ:
+		amdgpu_ring_write(ring, adev->gfx.config.num_rbs == 1 ?
+				0x00000000 : 0x00000002);
+		amdgpu_ring_write(ring, 0x00000000);
+		break;
 	case CHIP_STONEY:
 		amdgpu_ring_write(ring, 0x00000000);
 		amdgpu_ring_write(ring, 0x00000000);
@@ -3091,6 +4044,8 @@ static int gfx_v8_0_cp_gfx_resume(struct
 			tmp = REG_SET_FIELD(tmp, CP_RB_DOORBELL_CONTROL,
 					    DOORBELL_OFFSET, ring->doorbell_index);
 			tmp = REG_SET_FIELD(tmp, CP_RB_DOORBELL_CONTROL,
+					    DOORBELL_HIT, 0);
+			tmp = REG_SET_FIELD(tmp, CP_RB_DOORBELL_CONTROL,
 					    DOORBELL_EN, 1);
 		} else {
 			tmp = REG_SET_FIELD(tmp, CP_RB_DOORBELL_CONTROL,
@@ -3648,7 +4603,9 @@ static int gfx_v8_0_cp_compute_resume(st
 		if (use_doorbell) {
 			if ((adev->asic_type == CHIP_CARRIZO) ||
 			    (adev->asic_type == CHIP_FIJI) ||
-			    (adev->asic_type == CHIP_STONEY)) {
+			    (adev->asic_type == CHIP_STONEY) ||
+			    (adev->asic_type == CHIP_POLARIS11) ||
+			    (adev->asic_type == CHIP_POLARIS10)) {
 				WREG32(mmCP_MEC_DOORBELL_RANGE_LOWER,
 				       AMDGPU_DOORBELL_KIQ << 2);
 				WREG32(mmCP_MEC_DOORBELL_RANGE_UPPER,
@@ -3682,7 +4639,9 @@ static int gfx_v8_0_cp_compute_resume(st
 		tmp = REG_SET_FIELD(tmp, CP_HQD_PERSISTENT_STATE, PRELOAD_SIZE, 0x53);
 		WREG32(mmCP_HQD_PERSISTENT_STATE, tmp);
 		mqd->cp_hqd_persistent_state = tmp;
-		if (adev->asic_type == CHIP_STONEY) {
+		if (adev->asic_type == CHIP_STONEY ||
+			adev->asic_type == CHIP_POLARIS11 ||
+			adev->asic_type == CHIP_POLARIS10) {
 			tmp = RREG32(mmCP_ME1_PIPE3_INT_CNTL);
 			tmp = REG_SET_FIELD(tmp, CP_ME1_PIPE3_INT_CNTL, GENERIC2_INT_ENABLE, 1);
 			WREG32(mmCP_ME1_PIPE3_INT_CNTL, tmp);
@@ -3814,6 +4773,9 @@ static int gfx_v8_0_hw_fini(void *handle
 	gfx_v8_0_rlc_stop(adev);
 	gfx_v8_0_cp_compute_fini(adev);
 
+	amdgpu_set_powergating_state(adev,
+			AMD_IP_BLOCK_TYPE_GFX, AMD_PG_STATE_UNGATE);
+
 	return 0;
 }
 
@@ -3858,185 +4820,6 @@ static int gfx_v8_0_wait_for_idle(void *
 	return -ETIMEDOUT;
 }
 
-static void gfx_v8_0_print_status(void *handle)
-{
-	int i;
-	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-	dev_info(adev->dev, "GFX 8.x registers\n");
-	dev_info(adev->dev, "  GRBM_STATUS=0x%08X\n",
-		 RREG32(mmGRBM_STATUS));
-	dev_info(adev->dev, "  GRBM_STATUS2=0x%08X\n",
-		 RREG32(mmGRBM_STATUS2));
-	dev_info(adev->dev, "  GRBM_STATUS_SE0=0x%08X\n",
-		 RREG32(mmGRBM_STATUS_SE0));
-	dev_info(adev->dev, "  GRBM_STATUS_SE1=0x%08X\n",
-		 RREG32(mmGRBM_STATUS_SE1));
-	dev_info(adev->dev, "  GRBM_STATUS_SE2=0x%08X\n",
-		 RREG32(mmGRBM_STATUS_SE2));
-	dev_info(adev->dev, "  GRBM_STATUS_SE3=0x%08X\n",
-		 RREG32(mmGRBM_STATUS_SE3));
-	dev_info(adev->dev, "  CP_STAT = 0x%08x\n", RREG32(mmCP_STAT));
-	dev_info(adev->dev, "  CP_STALLED_STAT1 = 0x%08x\n",
-		 RREG32(mmCP_STALLED_STAT1));
-	dev_info(adev->dev, "  CP_STALLED_STAT2 = 0x%08x\n",
-		 RREG32(mmCP_STALLED_STAT2));
-	dev_info(adev->dev, "  CP_STALLED_STAT3 = 0x%08x\n",
-		 RREG32(mmCP_STALLED_STAT3));
-	dev_info(adev->dev, "  CP_CPF_BUSY_STAT = 0x%08x\n",
-		 RREG32(mmCP_CPF_BUSY_STAT));
-	dev_info(adev->dev, "  CP_CPF_STALLED_STAT1 = 0x%08x\n",
-		 RREG32(mmCP_CPF_STALLED_STAT1));
-	dev_info(adev->dev, "  CP_CPF_STATUS = 0x%08x\n", RREG32(mmCP_CPF_STATUS));
-	dev_info(adev->dev, "  CP_CPC_BUSY_STAT = 0x%08x\n", RREG32(mmCP_CPC_BUSY_STAT));
-	dev_info(adev->dev, "  CP_CPC_STALLED_STAT1 = 0x%08x\n",
-		 RREG32(mmCP_CPC_STALLED_STAT1));
-	dev_info(adev->dev, "  CP_CPC_STATUS = 0x%08x\n", RREG32(mmCP_CPC_STATUS));
-
-	for (i = 0; i < 32; i++) {
-		dev_info(adev->dev, "  GB_TILE_MODE%d=0x%08X\n",
-			 i, RREG32(mmGB_TILE_MODE0 + (i * 4)));
-	}
-	for (i = 0; i < 16; i++) {
-		dev_info(adev->dev, "  GB_MACROTILE_MODE%d=0x%08X\n",
-			 i, RREG32(mmGB_MACROTILE_MODE0 + (i * 4)));
-	}
-	for (i = 0; i < adev->gfx.config.max_shader_engines; i++) {
-		dev_info(adev->dev, "  se: %d\n", i);
-		gfx_v8_0_select_se_sh(adev, i, 0xffffffff);
-		dev_info(adev->dev, "  PA_SC_RASTER_CONFIG=0x%08X\n",
-			 RREG32(mmPA_SC_RASTER_CONFIG));
-		dev_info(adev->dev, "  PA_SC_RASTER_CONFIG_1=0x%08X\n",
-			 RREG32(mmPA_SC_RASTER_CONFIG_1));
-	}
-	gfx_v8_0_select_se_sh(adev, 0xffffffff, 0xffffffff);
-
-	dev_info(adev->dev, "  GB_ADDR_CONFIG=0x%08X\n",
-		 RREG32(mmGB_ADDR_CONFIG));
-	dev_info(adev->dev, "  HDP_ADDR_CONFIG=0x%08X\n",
-		 RREG32(mmHDP_ADDR_CONFIG));
-	dev_info(adev->dev, "  DMIF_ADDR_CALC=0x%08X\n",
-		 RREG32(mmDMIF_ADDR_CALC));
-
-	dev_info(adev->dev, "  CP_MEQ_THRESHOLDS=0x%08X\n",
-		 RREG32(mmCP_MEQ_THRESHOLDS));
-	dev_info(adev->dev, "  SX_DEBUG_1=0x%08X\n",
-		 RREG32(mmSX_DEBUG_1));
-	dev_info(adev->dev, "  TA_CNTL_AUX=0x%08X\n",
-		 RREG32(mmTA_CNTL_AUX));
-	dev_info(adev->dev, "  SPI_CONFIG_CNTL=0x%08X\n",
-		 RREG32(mmSPI_CONFIG_CNTL));
-	dev_info(adev->dev, "  SQ_CONFIG=0x%08X\n",
-		 RREG32(mmSQ_CONFIG));
-	dev_info(adev->dev, "  DB_DEBUG=0x%08X\n",
-		 RREG32(mmDB_DEBUG));
-	dev_info(adev->dev, "  DB_DEBUG2=0x%08X\n",
-		 RREG32(mmDB_DEBUG2));
-	dev_info(adev->dev, "  DB_DEBUG3=0x%08X\n",
-		 RREG32(mmDB_DEBUG3));
-	dev_info(adev->dev, "  CB_HW_CONTROL=0x%08X\n",
-		 RREG32(mmCB_HW_CONTROL));
-	dev_info(adev->dev, "  SPI_CONFIG_CNTL_1=0x%08X\n",
-		 RREG32(mmSPI_CONFIG_CNTL_1));
-	dev_info(adev->dev, "  PA_SC_FIFO_SIZE=0x%08X\n",
-		 RREG32(mmPA_SC_FIFO_SIZE));
-	dev_info(adev->dev, "  VGT_NUM_INSTANCES=0x%08X\n",
-		 RREG32(mmVGT_NUM_INSTANCES));
-	dev_info(adev->dev, "  CP_PERFMON_CNTL=0x%08X\n",
-		 RREG32(mmCP_PERFMON_CNTL));
-	dev_info(adev->dev, "  PA_SC_FORCE_EOV_MAX_CNTS=0x%08X\n",
-		 RREG32(mmPA_SC_FORCE_EOV_MAX_CNTS));
-	dev_info(adev->dev, "  VGT_CACHE_INVALIDATION=0x%08X\n",
-		 RREG32(mmVGT_CACHE_INVALIDATION));
-	dev_info(adev->dev, "  VGT_GS_VERTEX_REUSE=0x%08X\n",
-		 RREG32(mmVGT_GS_VERTEX_REUSE));
-	dev_info(adev->dev, "  PA_SC_LINE_STIPPLE_STATE=0x%08X\n",
-		 RREG32(mmPA_SC_LINE_STIPPLE_STATE));
-	dev_info(adev->dev, "  PA_CL_ENHANCE=0x%08X\n",
-		 RREG32(mmPA_CL_ENHANCE));
-	dev_info(adev->dev, "  PA_SC_ENHANCE=0x%08X\n",
-		 RREG32(mmPA_SC_ENHANCE));
-
-	dev_info(adev->dev, "  CP_ME_CNTL=0x%08X\n",
-		 RREG32(mmCP_ME_CNTL));
-	dev_info(adev->dev, "  CP_MAX_CONTEXT=0x%08X\n",
-		 RREG32(mmCP_MAX_CONTEXT));
-	dev_info(adev->dev, "  CP_ENDIAN_SWAP=0x%08X\n",
-		 RREG32(mmCP_ENDIAN_SWAP));
-	dev_info(adev->dev, "  CP_DEVICE_ID=0x%08X\n",
-		 RREG32(mmCP_DEVICE_ID));
-
-	dev_info(adev->dev, "  CP_SEM_WAIT_TIMER=0x%08X\n",
-		 RREG32(mmCP_SEM_WAIT_TIMER));
-
-	dev_info(adev->dev, "  CP_RB_WPTR_DELAY=0x%08X\n",
-		 RREG32(mmCP_RB_WPTR_DELAY));
-	dev_info(adev->dev, "  CP_RB_VMID=0x%08X\n",
-		 RREG32(mmCP_RB_VMID));
-	dev_info(adev->dev, "  CP_RB0_CNTL=0x%08X\n",
-		 RREG32(mmCP_RB0_CNTL));
-	dev_info(adev->dev, "  CP_RB0_WPTR=0x%08X\n",
-		 RREG32(mmCP_RB0_WPTR));
-	dev_info(adev->dev, "  CP_RB0_RPTR_ADDR=0x%08X\n",
-		 RREG32(mmCP_RB0_RPTR_ADDR));
-	dev_info(adev->dev, "  CP_RB0_RPTR_ADDR_HI=0x%08X\n",
-		 RREG32(mmCP_RB0_RPTR_ADDR_HI));
-	dev_info(adev->dev, "  CP_RB0_CNTL=0x%08X\n",
-		 RREG32(mmCP_RB0_CNTL));
-	dev_info(adev->dev, "  CP_RB0_BASE=0x%08X\n",
-		 RREG32(mmCP_RB0_BASE));
-	dev_info(adev->dev, "  CP_RB0_BASE_HI=0x%08X\n",
-		 RREG32(mmCP_RB0_BASE_HI));
-	dev_info(adev->dev, "  CP_MEC_CNTL=0x%08X\n",
-		 RREG32(mmCP_MEC_CNTL));
-	dev_info(adev->dev, "  CP_CPF_DEBUG=0x%08X\n",
-		 RREG32(mmCP_CPF_DEBUG));
-
-	dev_info(adev->dev, "  SCRATCH_ADDR=0x%08X\n",
-		 RREG32(mmSCRATCH_ADDR));
-	dev_info(adev->dev, "  SCRATCH_UMSK=0x%08X\n",
-		 RREG32(mmSCRATCH_UMSK));
-
-	dev_info(adev->dev, "  CP_INT_CNTL_RING0=0x%08X\n",
-		 RREG32(mmCP_INT_CNTL_RING0));
-	dev_info(adev->dev, "  RLC_LB_CNTL=0x%08X\n",
-		 RREG32(mmRLC_LB_CNTL));
-	dev_info(adev->dev, "  RLC_CNTL=0x%08X\n",
-		 RREG32(mmRLC_CNTL));
-	dev_info(adev->dev, "  RLC_CGCG_CGLS_CTRL=0x%08X\n",
-		 RREG32(mmRLC_CGCG_CGLS_CTRL));
-	dev_info(adev->dev, "  RLC_LB_CNTR_INIT=0x%08X\n",
-		 RREG32(mmRLC_LB_CNTR_INIT));
-	dev_info(adev->dev, "  RLC_LB_CNTR_MAX=0x%08X\n",
-		 RREG32(mmRLC_LB_CNTR_MAX));
-	dev_info(adev->dev, "  RLC_LB_INIT_CU_MASK=0x%08X\n",
-		 RREG32(mmRLC_LB_INIT_CU_MASK));
-	dev_info(adev->dev, "  RLC_LB_PARAMS=0x%08X\n",
-		 RREG32(mmRLC_LB_PARAMS));
-	dev_info(adev->dev, "  RLC_LB_CNTL=0x%08X\n",
-		 RREG32(mmRLC_LB_CNTL));
-	dev_info(adev->dev, "  RLC_MC_CNTL=0x%08X\n",
-		 RREG32(mmRLC_MC_CNTL));
-	dev_info(adev->dev, "  RLC_UCODE_CNTL=0x%08X\n",
-		 RREG32(mmRLC_UCODE_CNTL));
-
-	mutex_lock(&adev->srbm_mutex);
-	for (i = 0; i < 16; i++) {
-		vi_srbm_select(adev, 0, 0, 0, i);
-		dev_info(adev->dev, "  VM %d:\n", i);
-		dev_info(adev->dev, "  SH_MEM_CONFIG=0x%08X\n",
-			 RREG32(mmSH_MEM_CONFIG));
-		dev_info(adev->dev, "  SH_MEM_APE1_BASE=0x%08X\n",
-			 RREG32(mmSH_MEM_APE1_BASE));
-		dev_info(adev->dev, "  SH_MEM_APE1_LIMIT=0x%08X\n",
-			 RREG32(mmSH_MEM_APE1_LIMIT));
-		dev_info(adev->dev, "  SH_MEM_BASES=0x%08X\n",
-			 RREG32(mmSH_MEM_BASES));
-	}
-	vi_srbm_select(adev, 0, 0, 0, 0);
-	mutex_unlock(&adev->srbm_mutex);
-}
-
 static int gfx_v8_0_soft_reset(void *handle)
 {
 	u32 grbm_soft_reset = 0, srbm_soft_reset = 0;
@@ -4077,7 +4860,6 @@ static int gfx_v8_0_soft_reset(void *han
 						SRBM_SOFT_RESET, SOFT_RESET_GRBM, 1);
 
 	if (grbm_soft_reset || srbm_soft_reset) {
-		gfx_v8_0_print_status((void *)adev);
 		/* stop the rlc */
 		gfx_v8_0_rlc_stop(adev);
 
@@ -4137,7 +4919,6 @@ static int gfx_v8_0_soft_reset(void *han
 
 		/* Wait a little for things to settle down */
 		udelay(50);
-		gfx_v8_0_print_status((void *)adev);
 	}
 	return 0;
 }
@@ -4219,6 +5000,7 @@ static int gfx_v8_0_early_init(void *han
 	gfx_v8_0_set_ring_funcs(adev);
 	gfx_v8_0_set_irq_funcs(adev);
 	gfx_v8_0_set_gds_init(adev);
+	gfx_v8_0_set_rlc_funcs(adev);
 
 	return 0;
 }
@@ -4241,17 +5023,109 @@ static int gfx_v8_0_late_init(void *hand
 	if (r)
 		return r;
 
+	amdgpu_set_powergating_state(adev,
+			AMD_IP_BLOCK_TYPE_GFX, AMD_PG_STATE_GATE);
+
 	return 0;
 }
 
+static void polaris11_enable_gfx_static_mg_power_gating(struct amdgpu_device *adev,
+		bool enable)
+{
+	uint32_t data, temp;
+
+	/* Send msg to SMU via Powerplay */
+	amdgpu_set_powergating_state(adev,
+			AMD_IP_BLOCK_TYPE_SMC,
+			enable ? AMD_PG_STATE_GATE : AMD_PG_STATE_UNGATE);
+
+	if (enable) {
+		/* Enable static MGPG */
+		temp = data = RREG32(mmRLC_PG_CNTL);
+		data |= RLC_PG_CNTL__STATIC_PER_CU_PG_ENABLE_MASK;
+
+		if (temp != data)
+			WREG32(mmRLC_PG_CNTL, data);
+	} else {
+		temp = data = RREG32(mmRLC_PG_CNTL);
+		data &= ~RLC_PG_CNTL__STATIC_PER_CU_PG_ENABLE_MASK;
+
+		if (temp != data)
+			WREG32(mmRLC_PG_CNTL, data);
+	}
+}
+
+static void polaris11_enable_gfx_dynamic_mg_power_gating(struct amdgpu_device *adev,
+		bool enable)
+{
+	uint32_t data, temp;
+
+	if (enable) {
+		/* Enable dynamic MGPG */
+		temp = data = RREG32(mmRLC_PG_CNTL);
+		data |= RLC_PG_CNTL__DYN_PER_CU_PG_ENABLE_MASK;
+
+		if (temp != data)
+			WREG32(mmRLC_PG_CNTL, data);
+	} else {
+		temp = data = RREG32(mmRLC_PG_CNTL);
+		data &= ~RLC_PG_CNTL__DYN_PER_CU_PG_ENABLE_MASK;
+
+		if (temp != data)
+			WREG32(mmRLC_PG_CNTL, data);
+	}
+}
+
+static void polaris11_enable_gfx_quick_mg_power_gating(struct amdgpu_device *adev,
+		bool enable)
+{
+	uint32_t data, temp;
+
+	if (enable) {
+		/* Enable quick PG */
+		temp = data = RREG32(mmRLC_PG_CNTL);
+		data |= 0x100000;
+
+		if (temp != data)
+			WREG32(mmRLC_PG_CNTL, data);
+	} else {
+		temp = data = RREG32(mmRLC_PG_CNTL);
+		data &= ~0x100000;
+
+		if (temp != data)
+			WREG32(mmRLC_PG_CNTL, data);
+	}
+}
+
 static int gfx_v8_0_set_powergating_state(void *handle,
 					  enum amd_powergating_state state)
 {
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+	if (!(adev->pg_flags & AMD_PG_SUPPORT_GFX_PG))
+		return 0;
+
+	switch (adev->asic_type) {
+	case CHIP_POLARIS11:
+		if (adev->pg_flags & AMD_PG_SUPPORT_GFX_SMG)
+			polaris11_enable_gfx_static_mg_power_gating(adev,
+					state == AMD_PG_STATE_GATE ? true : false);
+		else if (adev->pg_flags & AMD_PG_SUPPORT_GFX_DMG)
+			polaris11_enable_gfx_dynamic_mg_power_gating(adev,
+					state == AMD_PG_STATE_GATE ? true : false);
+		else
+			polaris11_enable_gfx_quick_mg_power_gating(adev,
+					state == AMD_PG_STATE_GATE ? true : false);
+		break;
+	default:
+		break;
+	}
+
 	return 0;
 }
 
-static void fiji_send_serdes_cmd(struct amdgpu_device *adev,
-		uint32_t reg_addr, uint32_t cmd)
+static void gfx_v8_0_send_serdes_cmd(struct amdgpu_device *adev,
+				     uint32_t reg_addr, uint32_t cmd)
 {
 	uint32_t data;
 
@@ -4261,7 +5135,8 @@ static void fiji_send_serdes_cmd(struct
 	WREG32(mmRLC_SERDES_WR_NONCU_MASTER_MASK, 0xffffffff);
 
 	data = RREG32(mmRLC_SERDES_WR_CTRL);
-	data &= ~(RLC_SERDES_WR_CTRL__WRITE_COMMAND_MASK |
+	if (adev->asic_type == CHIP_STONEY)
+			data &= ~(RLC_SERDES_WR_CTRL__WRITE_COMMAND_MASK |
 			RLC_SERDES_WR_CTRL__READ_COMMAND_MASK |
 			RLC_SERDES_WR_CTRL__P1_SELECT_MASK |
 			RLC_SERDES_WR_CTRL__P2_SELECT_MASK |
@@ -4269,42 +5144,218 @@ static void fiji_send_serdes_cmd(struct
 			RLC_SERDES_WR_CTRL__POWER_DOWN_MASK |
 			RLC_SERDES_WR_CTRL__POWER_UP_MASK |
 			RLC_SERDES_WR_CTRL__SHORT_FORMAT_MASK |
-			RLC_SERDES_WR_CTRL__BPM_DATA_MASK |
-			RLC_SERDES_WR_CTRL__REG_ADDR_MASK |
 			RLC_SERDES_WR_CTRL__SRBM_OVERRIDE_MASK);
+	else
+		data &= ~(RLC_SERDES_WR_CTRL__WRITE_COMMAND_MASK |
+			  RLC_SERDES_WR_CTRL__READ_COMMAND_MASK |
+			  RLC_SERDES_WR_CTRL__P1_SELECT_MASK |
+			  RLC_SERDES_WR_CTRL__P2_SELECT_MASK |
+			  RLC_SERDES_WR_CTRL__RDDATA_RESET_MASK |
+			  RLC_SERDES_WR_CTRL__POWER_DOWN_MASK |
+			  RLC_SERDES_WR_CTRL__POWER_UP_MASK |
+			  RLC_SERDES_WR_CTRL__SHORT_FORMAT_MASK |
+			  RLC_SERDES_WR_CTRL__BPM_DATA_MASK |
+			  RLC_SERDES_WR_CTRL__REG_ADDR_MASK |
+			  RLC_SERDES_WR_CTRL__SRBM_OVERRIDE_MASK);
 	data |= (RLC_SERDES_WR_CTRL__RSVD_BPM_ADDR_MASK |
-			(cmd << RLC_SERDES_WR_CTRL__BPM_DATA__SHIFT) |
-			(reg_addr << RLC_SERDES_WR_CTRL__REG_ADDR__SHIFT) |
-			(0xff << RLC_SERDES_WR_CTRL__BPM_ADDR__SHIFT));
+		 (cmd << RLC_SERDES_WR_CTRL__BPM_DATA__SHIFT) |
+		 (reg_addr << RLC_SERDES_WR_CTRL__REG_ADDR__SHIFT) |
+		 (0xff << RLC_SERDES_WR_CTRL__BPM_ADDR__SHIFT));
 
 	WREG32(mmRLC_SERDES_WR_CTRL, data);
 }
 
-static void fiji_update_medium_grain_clock_gating(struct amdgpu_device *adev,
-		bool enable)
+#define MSG_ENTER_RLC_SAFE_MODE     1
+#define MSG_EXIT_RLC_SAFE_MODE      0
+
+#define RLC_GPR_REG2__REQ_MASK           0x00000001
+#define RLC_GPR_REG2__MESSAGE__SHIFT     0x00000001
+#define RLC_GPR_REG2__MESSAGE_MASK       0x0000001e
+
+static void cz_enter_rlc_safe_mode(struct amdgpu_device *adev)
+{
+	u32 data = 0;
+	unsigned i;
+
+	data = RREG32(mmRLC_CNTL);
+	if ((data & RLC_CNTL__RLC_ENABLE_F32_MASK) == 0)
+		return;
+
+	if ((adev->cg_flags & (AMD_CG_SUPPORT_GFX_CGCG | AMD_CG_SUPPORT_GFX_MGCG)) ||
+	    (adev->pg_flags & (AMD_PG_SUPPORT_GFX_PG | AMD_PG_SUPPORT_GFX_SMG |
+			       AMD_PG_SUPPORT_GFX_DMG))) {
+		data |= RLC_GPR_REG2__REQ_MASK;
+		data &= ~RLC_GPR_REG2__MESSAGE_MASK;
+		data |= (MSG_ENTER_RLC_SAFE_MODE << RLC_GPR_REG2__MESSAGE__SHIFT);
+		WREG32(mmRLC_GPR_REG2, data);
+
+		for (i = 0; i < adev->usec_timeout; i++) {
+			if ((RREG32(mmRLC_GPM_STAT) &
+			     (RLC_GPM_STAT__GFX_CLOCK_STATUS_MASK |
+			      RLC_GPM_STAT__GFX_POWER_STATUS_MASK)) ==
+			    (RLC_GPM_STAT__GFX_CLOCK_STATUS_MASK |
+			     RLC_GPM_STAT__GFX_POWER_STATUS_MASK))
+				break;
+			udelay(1);
+		}
+
+		for (i = 0; i < adev->usec_timeout; i++) {
+			if ((RREG32(mmRLC_GPR_REG2) & RLC_GPR_REG2__REQ_MASK) == 0)
+				break;
+			udelay(1);
+		}
+		adev->gfx.rlc.in_safe_mode = true;
+	}
+}
+
+static void cz_exit_rlc_safe_mode(struct amdgpu_device *adev)
+{
+	u32 data;
+	unsigned i;
+
+	data = RREG32(mmRLC_CNTL);
+	if ((data & RLC_CNTL__RLC_ENABLE_F32_MASK) == 0)
+		return;
+
+	if ((adev->cg_flags & (AMD_CG_SUPPORT_GFX_CGCG | AMD_CG_SUPPORT_GFX_MGCG)) ||
+	    (adev->pg_flags & (AMD_PG_SUPPORT_GFX_PG | AMD_PG_SUPPORT_GFX_SMG |
+			       AMD_PG_SUPPORT_GFX_DMG))) {
+		data |= RLC_GPR_REG2__REQ_MASK;
+		data &= ~RLC_GPR_REG2__MESSAGE_MASK;
+		data |= (MSG_EXIT_RLC_SAFE_MODE << RLC_GPR_REG2__MESSAGE__SHIFT);
+		WREG32(mmRLC_GPR_REG2, data);
+		adev->gfx.rlc.in_safe_mode = false;
+	}
+
+	for (i = 0; i < adev->usec_timeout; i++) {
+		if ((RREG32(mmRLC_GPR_REG2) & RLC_GPR_REG2__REQ_MASK) == 0)
+			break;
+		udelay(1);
+	}
+}
+
+static void iceland_enter_rlc_safe_mode(struct amdgpu_device *adev)
+{
+	u32 data;
+	unsigned i;
+
+	data = RREG32(mmRLC_CNTL);
+	if (!(data & RLC_CNTL__RLC_ENABLE_F32_MASK))
+		return;
+
+	if (adev->cg_flags & (AMD_CG_SUPPORT_GFX_CGCG | AMD_CG_SUPPORT_GFX_MGCG)) {
+		data |= RLC_SAFE_MODE__CMD_MASK;
+		data &= ~RLC_SAFE_MODE__MESSAGE_MASK;
+		data |= (1 << RLC_SAFE_MODE__MESSAGE__SHIFT);
+		WREG32(mmRLC_SAFE_MODE, data);
+
+		for (i = 0; i < adev->usec_timeout; i++) {
+			if ((RREG32(mmRLC_GPM_STAT) &
+			     (RLC_GPM_STAT__GFX_CLOCK_STATUS_MASK |
+			      RLC_GPM_STAT__GFX_POWER_STATUS_MASK)) ==
+			    (RLC_GPM_STAT__GFX_CLOCK_STATUS_MASK |
+			     RLC_GPM_STAT__GFX_POWER_STATUS_MASK))
+				break;
+			udelay(1);
+		}
+
+		for (i = 0; i < adev->usec_timeout; i++) {
+			if ((RREG32(mmRLC_SAFE_MODE) & RLC_SAFE_MODE__CMD_MASK) == 0)
+				break;
+			udelay(1);
+		}
+		adev->gfx.rlc.in_safe_mode = true;
+	}
+}
+
+static void iceland_exit_rlc_safe_mode(struct amdgpu_device *adev)
+{
+	u32 data = 0;
+	unsigned i;
+
+	data = RREG32(mmRLC_CNTL);
+	if (!(data & RLC_CNTL__RLC_ENABLE_F32_MASK))
+		return;
+
+	if (adev->cg_flags & (AMD_CG_SUPPORT_GFX_CGCG | AMD_CG_SUPPORT_GFX_MGCG)) {
+		if (adev->gfx.rlc.in_safe_mode) {
+			data |= RLC_SAFE_MODE__CMD_MASK;
+			data &= ~RLC_SAFE_MODE__MESSAGE_MASK;
+			WREG32(mmRLC_SAFE_MODE, data);
+			adev->gfx.rlc.in_safe_mode = false;
+		}
+	}
+
+	for (i = 0; i < adev->usec_timeout; i++) {
+		if ((RREG32(mmRLC_SAFE_MODE) & RLC_SAFE_MODE__CMD_MASK) == 0)
+			break;
+		udelay(1);
+	}
+}
+
+static void gfx_v8_0_nop_enter_rlc_safe_mode(struct amdgpu_device *adev)
+{
+	adev->gfx.rlc.in_safe_mode = true;
+}
+
+static void gfx_v8_0_nop_exit_rlc_safe_mode(struct amdgpu_device *adev)
+{
+	adev->gfx.rlc.in_safe_mode = false;
+}
+
+static const struct amdgpu_rlc_funcs cz_rlc_funcs = {
+	.enter_safe_mode = cz_enter_rlc_safe_mode,
+	.exit_safe_mode = cz_exit_rlc_safe_mode
+};
+
+static const struct amdgpu_rlc_funcs iceland_rlc_funcs = {
+	.enter_safe_mode = iceland_enter_rlc_safe_mode,
+	.exit_safe_mode = iceland_exit_rlc_safe_mode
+};
+
+static const struct amdgpu_rlc_funcs gfx_v8_0_nop_rlc_funcs = {
+	.enter_safe_mode = gfx_v8_0_nop_enter_rlc_safe_mode,
+	.exit_safe_mode = gfx_v8_0_nop_exit_rlc_safe_mode
+};
+
+static void gfx_v8_0_update_medium_grain_clock_gating(struct amdgpu_device *adev,
+						      bool enable)
 {
 	uint32_t temp, data;
 
+	adev->gfx.rlc.funcs->enter_safe_mode(adev);
+
 	/* It is disabled by HW by default */
-	if (enable) {
-		/* 1 - RLC memory Light sleep */
-		temp = data = RREG32(mmRLC_MEM_SLP_CNTL);
-		data |= RLC_MEM_SLP_CNTL__RLC_MEM_LS_EN_MASK;
-		if (temp != data)
-			WREG32(mmRLC_MEM_SLP_CNTL, data);
+	if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_MGCG)) {
+		if (adev->cg_flags & AMD_CG_SUPPORT_GFX_MGLS) {
+			if (adev->cg_flags & AMD_CG_SUPPORT_GFX_RLC_LS) {
+				/* 1 - RLC memory Light sleep */
+				temp = data = RREG32(mmRLC_MEM_SLP_CNTL);
+				data |= RLC_MEM_SLP_CNTL__RLC_MEM_LS_EN_MASK;
+				if (temp != data)
+					WREG32(mmRLC_MEM_SLP_CNTL, data);
+			}
 
-		/* 2 - CP memory Light sleep */
-		temp = data = RREG32(mmCP_MEM_SLP_CNTL);
-		data |= CP_MEM_SLP_CNTL__CP_MEM_LS_EN_MASK;
-		if (temp != data)
-			WREG32(mmCP_MEM_SLP_CNTL, data);
+			if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CP_LS) {
+				/* 2 - CP memory Light sleep */
+				temp = data = RREG32(mmCP_MEM_SLP_CNTL);
+				data |= CP_MEM_SLP_CNTL__CP_MEM_LS_EN_MASK;
+				if (temp != data)
+					WREG32(mmCP_MEM_SLP_CNTL, data);
+			}
+		}
 
 		/* 3 - RLC_CGTT_MGCG_OVERRIDE */
 		temp = data = RREG32(mmRLC_CGTT_MGCG_OVERRIDE);
-		data &= ~(RLC_CGTT_MGCG_OVERRIDE__CPF_MASK |
-				RLC_CGTT_MGCG_OVERRIDE__RLC_MASK |
-				RLC_CGTT_MGCG_OVERRIDE__MGCG_MASK |
-				RLC_CGTT_MGCG_OVERRIDE__GRBM_MASK);
+		if (adev->flags & AMD_IS_APU)
+			data &= ~(RLC_CGTT_MGCG_OVERRIDE__CPF_MASK |
+				  RLC_CGTT_MGCG_OVERRIDE__RLC_MASK |
+				  RLC_CGTT_MGCG_OVERRIDE__MGCG_MASK);
+		else
+			data &= ~(RLC_CGTT_MGCG_OVERRIDE__CPF_MASK |
+				  RLC_CGTT_MGCG_OVERRIDE__RLC_MASK |
+				  RLC_CGTT_MGCG_OVERRIDE__MGCG_MASK |
+				  RLC_CGTT_MGCG_OVERRIDE__GRBM_MASK);
 
 		if (temp != data)
 			WREG32(mmRLC_CGTT_MGCG_OVERRIDE, data);
@@ -4313,19 +5364,23 @@ static void fiji_update_medium_grain_clo
 		gfx_v8_0_wait_for_rlc_serdes(adev);
 
 		/* 5 - clear mgcg override */
-		fiji_send_serdes_cmd(adev, BPM_REG_MGCG_OVERRIDE, CLE_BPM_SERDES_CMD);
+		gfx_v8_0_send_serdes_cmd(adev, BPM_REG_MGCG_OVERRIDE, CLE_BPM_SERDES_CMD);
 
-		/* 6 - Enable CGTS(Tree Shade) MGCG /MGLS */
-		temp = data = RREG32(mmCGTS_SM_CTRL_REG);
-		data &= ~(CGTS_SM_CTRL_REG__SM_MODE_MASK);
-		data |= (0x2 << CGTS_SM_CTRL_REG__SM_MODE__SHIFT);
-		data |= CGTS_SM_CTRL_REG__SM_MODE_ENABLE_MASK;
-		data &= ~CGTS_SM_CTRL_REG__OVERRIDE_MASK;
-		data &= ~CGTS_SM_CTRL_REG__LS_OVERRIDE_MASK;
-		data |= CGTS_SM_CTRL_REG__ON_MONITOR_ADD_EN_MASK;
-		data |= (0x96 << CGTS_SM_CTRL_REG__ON_MONITOR_ADD__SHIFT);
-		if (temp != data)
-			WREG32(mmCGTS_SM_CTRL_REG, data);
+		if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGTS) {
+			/* 6 - Enable CGTS(Tree Shade) MGCG /MGLS */
+			temp = data = RREG32(mmCGTS_SM_CTRL_REG);
+			data &= ~(CGTS_SM_CTRL_REG__SM_MODE_MASK);
+			data |= (0x2 << CGTS_SM_CTRL_REG__SM_MODE__SHIFT);
+			data |= CGTS_SM_CTRL_REG__SM_MODE_ENABLE_MASK;
+			data &= ~CGTS_SM_CTRL_REG__OVERRIDE_MASK;
+			if ((adev->cg_flags & AMD_CG_SUPPORT_GFX_MGLS) &&
+			    (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGTS_LS))
+				data &= ~CGTS_SM_CTRL_REG__LS_OVERRIDE_MASK;
+			data |= CGTS_SM_CTRL_REG__ON_MONITOR_ADD_EN_MASK;
+			data |= (0x96 << CGTS_SM_CTRL_REG__ON_MONITOR_ADD__SHIFT);
+			if (temp != data)
+				WREG32(mmCGTS_SM_CTRL_REG, data);
+		}
 		udelay(50);
 
 		/* 7 - wait for RLC_SERDES_CU_MASTER & RLC_SERDES_NONCU_MASTER idle */
@@ -4365,23 +5420,27 @@ static void fiji_update_medium_grain_clo
 		gfx_v8_0_wait_for_rlc_serdes(adev);
 
 		/* 6 - set mgcg override */
-		fiji_send_serdes_cmd(adev, BPM_REG_MGCG_OVERRIDE, SET_BPM_SERDES_CMD);
+		gfx_v8_0_send_serdes_cmd(adev, BPM_REG_MGCG_OVERRIDE, SET_BPM_SERDES_CMD);
 
 		udelay(50);
 
 		/* 7- wait for RLC_SERDES_CU_MASTER & RLC_SERDES_NONCU_MASTER idle */
 		gfx_v8_0_wait_for_rlc_serdes(adev);
 	}
+
+	adev->gfx.rlc.funcs->exit_safe_mode(adev);
 }
 
-static void fiji_update_coarse_grain_clock_gating(struct amdgpu_device *adev,
-		bool enable)
+static void gfx_v8_0_update_coarse_grain_clock_gating(struct amdgpu_device *adev,
+						      bool enable)
 {
 	uint32_t temp, temp1, data, data1;
 
 	temp = data = RREG32(mmRLC_CGCG_CGLS_CTRL);
 
-	if (enable) {
+	adev->gfx.rlc.funcs->enter_safe_mode(adev);
+
+	if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGCG)) {
 		/* 1 enable cntx_empty_int_enable/cntx_busy_int_enable/
 		 * Cmp_busy/GFX_Idle interrupts
 		 */
@@ -4396,25 +5455,29 @@ static void fiji_update_coarse_grain_clo
 		gfx_v8_0_wait_for_rlc_serdes(adev);
 
 		/* 3 - clear cgcg override */
-		fiji_send_serdes_cmd(adev, BPM_REG_CGCG_OVERRIDE, CLE_BPM_SERDES_CMD);
+		gfx_v8_0_send_serdes_cmd(adev, BPM_REG_CGCG_OVERRIDE, CLE_BPM_SERDES_CMD);
 
 		/* wait for RLC_SERDES_CU_MASTER & RLC_SERDES_NONCU_MASTER idle */
 		gfx_v8_0_wait_for_rlc_serdes(adev);
 
 		/* 4 - write cmd to set CGLS */
-		fiji_send_serdes_cmd(adev, BPM_REG_CGLS_EN, SET_BPM_SERDES_CMD);
+		gfx_v8_0_send_serdes_cmd(adev, BPM_REG_CGLS_EN, SET_BPM_SERDES_CMD);
 
 		/* 5 - enable cgcg */
 		data |= RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK;
 
-		/* enable cgls*/
-		data |= RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK;
+		if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGLS) {
+			/* enable cgls*/
+			data |= RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK;
 
-		temp1 = data1 =	RREG32(mmRLC_CGTT_MGCG_OVERRIDE);
-		data1 &= ~RLC_CGTT_MGCG_OVERRIDE__CGLS_MASK;
+			temp1 = data1 =	RREG32(mmRLC_CGTT_MGCG_OVERRIDE);
+			data1 &= ~RLC_CGTT_MGCG_OVERRIDE__CGLS_MASK;
 
-		if (temp1 != data1)
-			WREG32(mmRLC_CGTT_MGCG_OVERRIDE, data1);
+			if (temp1 != data1)
+				WREG32(mmRLC_CGTT_MGCG_OVERRIDE, data1);
+		} else {
+			data &= ~RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK;
+		}
 
 		if (temp != data)
 			WREG32(mmRLC_CGCG_CGLS_CTRL, data);
@@ -4439,36 +5502,38 @@ static void fiji_update_coarse_grain_clo
 		gfx_v8_0_wait_for_rlc_serdes(adev);
 
 		/* write cmd to Set CGCG Overrride */
-		fiji_send_serdes_cmd(adev, BPM_REG_CGCG_OVERRIDE, SET_BPM_SERDES_CMD);
+		gfx_v8_0_send_serdes_cmd(adev, BPM_REG_CGCG_OVERRIDE, SET_BPM_SERDES_CMD);
 
 		/* wait for RLC_SERDES_CU_MASTER & RLC_SERDES_NONCU_MASTER idle */
 		gfx_v8_0_wait_for_rlc_serdes(adev);
 
 		/* write cmd to Clear CGLS */
-		fiji_send_serdes_cmd(adev, BPM_REG_CGLS_EN, CLE_BPM_SERDES_CMD);
+		gfx_v8_0_send_serdes_cmd(adev, BPM_REG_CGLS_EN, CLE_BPM_SERDES_CMD);
 
 		/* disable cgcg, cgls should be disabled too. */
 		data &= ~(RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK |
-				RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK);
+			  RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK);
 		if (temp != data)
 			WREG32(mmRLC_CGCG_CGLS_CTRL, data);
 	}
+
+	adev->gfx.rlc.funcs->exit_safe_mode(adev);
 }
-static int fiji_update_gfx_clock_gating(struct amdgpu_device *adev,
-		bool enable)
+static int gfx_v8_0_update_gfx_clock_gating(struct amdgpu_device *adev,
+					    bool enable)
 {
 	if (enable) {
 		/* CGCG/CGLS should be enabled after MGCG/MGLS/TS(CG/LS)
 		 * ===  MGCG + MGLS + TS(CG/LS) ===
 		 */
-		fiji_update_medium_grain_clock_gating(adev, enable);
-		fiji_update_coarse_grain_clock_gating(adev, enable);
+		gfx_v8_0_update_medium_grain_clock_gating(adev, enable);
+		gfx_v8_0_update_coarse_grain_clock_gating(adev, enable);
 	} else {
 		/* CGCG/CGLS should be disabled before MGCG/MGLS/TS(CG/LS)
 		 * ===  CGCG + CGLS ===
 		 */
-		fiji_update_coarse_grain_clock_gating(adev, enable);
-		fiji_update_medium_grain_clock_gating(adev, enable);
+		gfx_v8_0_update_coarse_grain_clock_gating(adev, enable);
+		gfx_v8_0_update_medium_grain_clock_gating(adev, enable);
 	}
 	return 0;
 }
@@ -4480,8 +5545,10 @@ static int gfx_v8_0_set_clockgating_stat
 
 	switch (adev->asic_type) {
 	case CHIP_FIJI:
-		fiji_update_gfx_clock_gating(adev,
-				state == AMD_CG_STATE_GATE ? true : false);
+	case CHIP_CARRIZO:
+	case CHIP_STONEY:
+		gfx_v8_0_update_gfx_clock_gating(adev,
+						 state == AMD_CG_STATE_GATE ? true : false);
 		break;
 	default:
 		break;
@@ -4571,17 +5638,13 @@ static void gfx_v8_0_ring_emit_hdp_inval
 }
 
 static void gfx_v8_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
-				  struct amdgpu_ib *ib)
+				      struct amdgpu_ib *ib,
+				      unsigned vm_id, bool ctx_switch)
 {
-	bool need_ctx_switch = ring->current_ctx != ib->ctx;
 	u32 header, control = 0;
 	u32 next_rptr = ring->wptr + 5;
 
-	/* drop the CE preamble IB for the same context */
-	if ((ib->flags & AMDGPU_IB_FLAG_PREAMBLE) && !need_ctx_switch)
-		return;
-
-	if (need_ctx_switch)
+	if (ctx_switch)
 		next_rptr += 2;
 
 	next_rptr += 4;
@@ -4592,7 +5655,7 @@ static void gfx_v8_0_ring_emit_ib_gfx(st
 	amdgpu_ring_write(ring, next_rptr);
 
 	/* insert SWITCH_BUFFER packet before first IB in the ring frame */
-	if (need_ctx_switch) {
+	if (ctx_switch) {
 		amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
 		amdgpu_ring_write(ring, 0);
 	}
@@ -4602,7 +5665,7 @@ static void gfx_v8_0_ring_emit_ib_gfx(st
 	else
 		header = PACKET3(PACKET3_INDIRECT_BUFFER, 2);
 
-	control |= ib->length_dw | (ib->vm_id << 24);
+	control |= ib->length_dw | (vm_id << 24);
 
 	amdgpu_ring_write(ring, header);
 	amdgpu_ring_write(ring,
@@ -4615,7 +5678,8 @@ static void gfx_v8_0_ring_emit_ib_gfx(st
 }
 
 static void gfx_v8_0_ring_emit_ib_compute(struct amdgpu_ring *ring,
-				  struct amdgpu_ib *ib)
+					  struct amdgpu_ib *ib,
+					  unsigned vm_id, bool ctx_switch)
 {
 	u32 header, control = 0;
 	u32 next_rptr = ring->wptr + 5;
@@ -4631,7 +5695,7 @@ static void gfx_v8_0_ring_emit_ib_comput
 
 	header = PACKET3(PACKET3_INDIRECT_BUFFER, 2);
 
-	control |= ib->length_dw | (ib->vm_id << 24);
+	control |= ib->length_dw | (vm_id << 24);
 
 	amdgpu_ring_write(ring, header);
 	amdgpu_ring_write(ring,
@@ -4653,6 +5717,7 @@ static void gfx_v8_0_ring_emit_fence_gfx
 	amdgpu_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE_EOP, 4));
 	amdgpu_ring_write(ring, (EOP_TCL1_ACTION_EN |
 				 EOP_TC_ACTION_EN |
+				 EOP_TC_WB_ACTION_EN |
 				 EVENT_TYPE(CACHE_FLUSH_AND_INV_TS_EVENT) |
 				 EVENT_INDEX(5)));
 	amdgpu_ring_write(ring, addr & 0xfffffffc);
@@ -4991,6 +6056,7 @@ static int gfx_v8_0_priv_inst_irq(struct
 }
 
 const struct amd_ip_funcs gfx_v8_0_ip_funcs = {
+	.name = "gfx_v8_0",
 	.early_init = gfx_v8_0_early_init,
 	.late_init = gfx_v8_0_late_init,
 	.sw_init = gfx_v8_0_sw_init,
@@ -5002,7 +6068,6 @@ const struct amd_ip_funcs gfx_v8_0_ip_fu
 	.is_idle = gfx_v8_0_is_idle,
 	.wait_for_idle = gfx_v8_0_wait_for_idle,
 	.soft_reset = gfx_v8_0_soft_reset,
-	.print_status = gfx_v8_0_print_status,
 	.set_clockgating_state = gfx_v8_0_set_clockgating_state,
 	.set_powergating_state = gfx_v8_0_set_powergating_state,
 };
@@ -5081,6 +6146,22 @@ static void gfx_v8_0_set_irq_funcs(struc
 	adev->gfx.priv_inst_irq.funcs = &gfx_v8_0_priv_inst_irq_funcs;
 }
 
+static void gfx_v8_0_set_rlc_funcs(struct amdgpu_device *adev)
+{
+	switch (adev->asic_type) {
+	case CHIP_TOPAZ:
+	case CHIP_STONEY:
+		adev->gfx.rlc.funcs = &iceland_rlc_funcs;
+		break;
+	case CHIP_CARRIZO:
+		adev->gfx.rlc.funcs = &cz_rlc_funcs;
+		break;
+	default:
+		adev->gfx.rlc.funcs = &gfx_v8_0_nop_rlc_funcs;
+		break;
+	}
+}
+
 static void gfx_v8_0_set_gds_init(struct amdgpu_device *adev)
 {
 	/* init asci gds info */
@@ -5124,14 +6205,11 @@ static u32 gfx_v8_0_get_cu_active_bitmap
 	return (~data) & mask;
 }
 
-int gfx_v8_0_get_cu_info(struct amdgpu_device *adev,
-			 struct amdgpu_cu_info *cu_info)
+static void gfx_v8_0_get_cu_info(struct amdgpu_device *adev)
 {
 	int i, j, k, counter, active_cu_number = 0;
 	u32 mask, bitmap, ao_bitmap, ao_cu_mask = 0;
-
-	if (!adev || !cu_info)
-		return -EINVAL;
+	struct amdgpu_cu_info *cu_info = &adev->gfx.cu_info;
 
 	memset(cu_info, 0, sizeof(*cu_info));
 
@@ -5162,6 +6240,4 @@ int gfx_v8_0_get_cu_info(struct amdgpu_d
 
 	cu_info->number = active_cu_number;
 	cu_info->ao_cu_mask = ao_cu_mask;
-
-	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.h	2016-07-24 15:23:50.000000000 -0400
@@ -28,6 +28,5 @@ extern const struct amd_ip_funcs gfx_v8_
 
 uint64_t gfx_v8_0_get_gpu_clock_counter(struct amdgpu_device *adev);
 void gfx_v8_0_select_se_sh(struct amdgpu_device *adev, u32 se_num, u32 sh_num);
-int gfx_v8_0_get_cu_info(struct amdgpu_device *adev, struct amdgpu_cu_info *cu_info);
 
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c	2016-05-15 19:21:23.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c	2016-07-24 18:17:58.000000000 -0400
@@ -1115,114 +1115,6 @@ static int gmc_v7_0_wait_for_idle(void *
 
 }
 
-static void gmc_v7_0_print_status(void *handle)
-{
-	int i, j;
-	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-	dev_info(adev->dev, "GMC 8.x registers\n");
-	dev_info(adev->dev, "  SRBM_STATUS=0x%08X\n",
-		RREG32(mmSRBM_STATUS));
-	dev_info(adev->dev, "  SRBM_STATUS2=0x%08X\n",
-		RREG32(mmSRBM_STATUS2));
-
-	dev_info(adev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_ADDR   0x%08X\n",
-		 RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_ADDR));
-	dev_info(adev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n",
-		 RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_STATUS));
-	dev_info(adev->dev, "  MC_VM_MX_L1_TLB_CNTL=0x%08X\n",
-		 RREG32(mmMC_VM_MX_L1_TLB_CNTL));
-	dev_info(adev->dev, "  VM_L2_CNTL=0x%08X\n",
-		 RREG32(mmVM_L2_CNTL));
-	dev_info(adev->dev, "  VM_L2_CNTL2=0x%08X\n",
-		 RREG32(mmVM_L2_CNTL2));
-	dev_info(adev->dev, "  VM_L2_CNTL3=0x%08X\n",
-		 RREG32(mmVM_L2_CNTL3));
-	dev_info(adev->dev, "  VM_CONTEXT0_PAGE_TABLE_START_ADDR=0x%08X\n",
-		 RREG32(mmVM_CONTEXT0_PAGE_TABLE_START_ADDR));
-	dev_info(adev->dev, "  VM_CONTEXT0_PAGE_TABLE_END_ADDR=0x%08X\n",
-		 RREG32(mmVM_CONTEXT0_PAGE_TABLE_END_ADDR));
-	dev_info(adev->dev, "  VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR=0x%08X\n",
-		 RREG32(mmVM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR));
-	dev_info(adev->dev, "  VM_CONTEXT0_CNTL2=0x%08X\n",
-		 RREG32(mmVM_CONTEXT0_CNTL2));
-	dev_info(adev->dev, "  VM_CONTEXT0_CNTL=0x%08X\n",
-		 RREG32(mmVM_CONTEXT0_CNTL));
-	dev_info(adev->dev, "  0x15D4=0x%08X\n",
-		 RREG32(0x575));
-	dev_info(adev->dev, "  0x15D8=0x%08X\n",
-		 RREG32(0x576));
-	dev_info(adev->dev, "  0x15DC=0x%08X\n",
-		 RREG32(0x577));
-	dev_info(adev->dev, "  VM_CONTEXT1_PAGE_TABLE_START_ADDR=0x%08X\n",
-		 RREG32(mmVM_CONTEXT1_PAGE_TABLE_START_ADDR));
-	dev_info(adev->dev, "  VM_CONTEXT1_PAGE_TABLE_END_ADDR=0x%08X\n",
-		 RREG32(mmVM_CONTEXT1_PAGE_TABLE_END_ADDR));
-	dev_info(adev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR=0x%08X\n",
-		 RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR));
-	dev_info(adev->dev, "  VM_CONTEXT1_CNTL2=0x%08X\n",
-		 RREG32(mmVM_CONTEXT1_CNTL2));
-	dev_info(adev->dev, "  VM_CONTEXT1_CNTL=0x%08X\n",
-		 RREG32(mmVM_CONTEXT1_CNTL));
-	for (i = 0; i < 16; i++) {
-		if (i < 8)
-			dev_info(adev->dev, "  VM_CONTEXT%d_PAGE_TABLE_BASE_ADDR=0x%08X\n",
-				 i, RREG32(mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR + i));
-		else
-			dev_info(adev->dev, "  VM_CONTEXT%d_PAGE_TABLE_BASE_ADDR=0x%08X\n",
-				 i, RREG32(mmVM_CONTEXT8_PAGE_TABLE_BASE_ADDR + i - 8));
-	}
-	dev_info(adev->dev, "  MC_VM_SYSTEM_APERTURE_LOW_ADDR=0x%08X\n",
-		 RREG32(mmMC_VM_SYSTEM_APERTURE_LOW_ADDR));
-	dev_info(adev->dev, "  MC_VM_SYSTEM_APERTURE_HIGH_ADDR=0x%08X\n",
-		 RREG32(mmMC_VM_SYSTEM_APERTURE_HIGH_ADDR));
-	dev_info(adev->dev, "  MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR=0x%08X\n",
-		 RREG32(mmMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR));
-	dev_info(adev->dev, "  MC_VM_FB_LOCATION=0x%08X\n",
-		 RREG32(mmMC_VM_FB_LOCATION));
-	dev_info(adev->dev, "  MC_VM_AGP_BASE=0x%08X\n",
-		 RREG32(mmMC_VM_AGP_BASE));
-	dev_info(adev->dev, "  MC_VM_AGP_TOP=0x%08X\n",
-		 RREG32(mmMC_VM_AGP_TOP));
-	dev_info(adev->dev, "  MC_VM_AGP_BOT=0x%08X\n",
-		 RREG32(mmMC_VM_AGP_BOT));
-
-	if (adev->asic_type == CHIP_KAVERI) {
-		dev_info(adev->dev, "  CHUB_CONTROL=0x%08X\n",
-			 RREG32(mmCHUB_CONTROL));
-	}
-
-	dev_info(adev->dev, "  HDP_REG_COHERENCY_FLUSH_CNTL=0x%08X\n",
-		 RREG32(mmHDP_REG_COHERENCY_FLUSH_CNTL));
-	dev_info(adev->dev, "  HDP_NONSURFACE_BASE=0x%08X\n",
-		 RREG32(mmHDP_NONSURFACE_BASE));
-	dev_info(adev->dev, "  HDP_NONSURFACE_INFO=0x%08X\n",
-		 RREG32(mmHDP_NONSURFACE_INFO));
-	dev_info(adev->dev, "  HDP_NONSURFACE_SIZE=0x%08X\n",
-		 RREG32(mmHDP_NONSURFACE_SIZE));
-	dev_info(adev->dev, "  HDP_MISC_CNTL=0x%08X\n",
-		 RREG32(mmHDP_MISC_CNTL));
-	dev_info(adev->dev, "  HDP_HOST_PATH_CNTL=0x%08X\n",
-		 RREG32(mmHDP_HOST_PATH_CNTL));
-
-	for (i = 0, j = 0; i < 32; i++, j += 0x6) {
-		dev_info(adev->dev, "  %d:\n", i);
-		dev_info(adev->dev, "  0x%04X=0x%08X\n",
-			 0xb05 + j, RREG32(0xb05 + j));
-		dev_info(adev->dev, "  0x%04X=0x%08X\n",
-			 0xb06 + j, RREG32(0xb06 + j));
-		dev_info(adev->dev, "  0x%04X=0x%08X\n",
-			 0xb07 + j, RREG32(0xb07 + j));
-		dev_info(adev->dev, "  0x%04X=0x%08X\n",
-			 0xb08 + j, RREG32(0xb08 + j));
-		dev_info(adev->dev, "  0x%04X=0x%08X\n",
-			 0xb09 + j, RREG32(0xb09 + j));
-	}
-
-	dev_info(adev->dev, "  BIF_FB_EN=0x%08X\n",
-		 RREG32(mmBIF_FB_EN));
-}
-
 static int gmc_v7_0_soft_reset(void *handle)
 {
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
@@ -1242,8 +1134,6 @@ static int gmc_v7_0_soft_reset(void *han
 	}
 
 	if (srbm_soft_reset) {
-		gmc_v7_0_print_status((void *)adev);
-
 		gmc_v7_0_mc_stop(adev, &save);
 		if (gmc_v7_0_wait_for_idle(adev)) {
 			dev_warn(adev->dev, "Wait for GMC idle timed out !\n");
@@ -1267,8 +1157,6 @@ static int gmc_v7_0_soft_reset(void *han
 
 		gmc_v7_0_mc_resume(adev, &save);
 		udelay(50);
-
-		gmc_v7_0_print_status((void *)adev);
 	}
 
 	return 0;
@@ -1371,6 +1259,7 @@ static int gmc_v7_0_set_powergating_stat
 }
 
 const struct amd_ip_funcs gmc_v7_0_ip_funcs = {
+	.name = "gmc_v7_0",
 	.early_init = gmc_v7_0_early_init,
 	.late_init = gmc_v7_0_late_init,
 	.sw_init = gmc_v7_0_sw_init,
@@ -1382,7 +1271,6 @@ const struct amd_ip_funcs gmc_v7_0_ip_fu
 	.is_idle = gmc_v7_0_is_idle,
 	.wait_for_idle = gmc_v7_0_wait_for_idle,
 	.soft_reset = gmc_v7_0_soft_reset,
-	.print_status = gmc_v7_0_print_status,
 	.set_clockgating_state = gmc_v7_0_set_clockgating_state,
 	.set_powergating_state = gmc_v7_0_set_powergating_state,
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c	2016-05-15 19:20:45.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c	2016-07-24 18:16:52.000000000 -0400
@@ -73,6 +73,23 @@ static const u32 fiji_mgcg_cgcg_init[] =
 	mmMC_MEM_POWER_LS, 0xffffffff, 0x00000104
 };
 
+static const u32 golden_settings_polaris11_a11[] =
+{
+	mmVM_PRT_APERTURE0_LOW_ADDR, 0x0fffffff, 0x0fffffff,
+	mmVM_PRT_APERTURE1_LOW_ADDR, 0x0fffffff, 0x0fffffff,
+	mmVM_PRT_APERTURE2_LOW_ADDR, 0x0fffffff, 0x0fffffff,
+	mmVM_PRT_APERTURE3_LOW_ADDR, 0x0fffffff, 0x0fffffff
+};
+
+static const u32 golden_settings_polaris10_a11[] =
+{
+	mmMC_ARB_WTM_GRPWT_RD, 0x00000003, 0x00000000,
+	mmVM_PRT_APERTURE0_LOW_ADDR, 0x0fffffff, 0x0fffffff,
+	mmVM_PRT_APERTURE1_LOW_ADDR, 0x0fffffff, 0x0fffffff,
+	mmVM_PRT_APERTURE2_LOW_ADDR, 0x0fffffff, 0x0fffffff,
+	mmVM_PRT_APERTURE3_LOW_ADDR, 0x0fffffff, 0x0fffffff
+};
+
 static const u32 cz_mgcg_cgcg_init[] =
 {
 	mmMC_MEM_POWER_LS, 0xffffffff, 0x00000104
@@ -103,6 +120,16 @@ static void gmc_v8_0_init_golden_registe
 						 golden_settings_tonga_a11,
 						 (const u32)ARRAY_SIZE(golden_settings_tonga_a11));
 		break;
+	case CHIP_POLARIS11:
+		amdgpu_program_register_sequence(adev,
+						 golden_settings_polaris11_a11,
+						 (const u32)ARRAY_SIZE(golden_settings_polaris11_a11));
+		break;
+	case CHIP_POLARIS10:
+		amdgpu_program_register_sequence(adev,
+						 golden_settings_polaris10_a11,
+						 (const u32)ARRAY_SIZE(golden_settings_polaris10_a11));
+		break;
 	case CHIP_CARRIZO:
 		amdgpu_program_register_sequence(adev,
 						 cz_mgcg_cgcg_init,
@@ -209,6 +236,12 @@ static int gmc_v8_0_init_microcode(struc
 	case CHIP_TONGA:
 		chip_name = "tonga";
 		break;
+	case CHIP_POLARIS11:
+		chip_name = "polaris11";
+		break;
+	case CHIP_POLARIS10:
+		chip_name = "polaris10";
+		break;
 	case CHIP_FIJI:
 	case CHIP_CARRIZO:
 	case CHIP_STONEY:
@@ -1085,111 +1118,6 @@ static int gmc_v8_0_wait_for_idle(void *
 
 }
 
-static void gmc_v8_0_print_status(void *handle)
-{
-	int i, j;
-	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-	dev_info(adev->dev, "GMC 8.x registers\n");
-	dev_info(adev->dev, "  SRBM_STATUS=0x%08X\n",
-		RREG32(mmSRBM_STATUS));
-	dev_info(adev->dev, "  SRBM_STATUS2=0x%08X\n",
-		RREG32(mmSRBM_STATUS2));
-
-	dev_info(adev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_ADDR   0x%08X\n",
-		 RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_ADDR));
-	dev_info(adev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n",
-		 RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_STATUS));
-	dev_info(adev->dev, "  MC_VM_MX_L1_TLB_CNTL=0x%08X\n",
-		 RREG32(mmMC_VM_MX_L1_TLB_CNTL));
-	dev_info(adev->dev, "  VM_L2_CNTL=0x%08X\n",
-		 RREG32(mmVM_L2_CNTL));
-	dev_info(adev->dev, "  VM_L2_CNTL2=0x%08X\n",
-		 RREG32(mmVM_L2_CNTL2));
-	dev_info(adev->dev, "  VM_L2_CNTL3=0x%08X\n",
-		 RREG32(mmVM_L2_CNTL3));
-	dev_info(adev->dev, "  VM_L2_CNTL4=0x%08X\n",
-		 RREG32(mmVM_L2_CNTL4));
-	dev_info(adev->dev, "  VM_CONTEXT0_PAGE_TABLE_START_ADDR=0x%08X\n",
-		 RREG32(mmVM_CONTEXT0_PAGE_TABLE_START_ADDR));
-	dev_info(adev->dev, "  VM_CONTEXT0_PAGE_TABLE_END_ADDR=0x%08X\n",
-		 RREG32(mmVM_CONTEXT0_PAGE_TABLE_END_ADDR));
-	dev_info(adev->dev, "  VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR=0x%08X\n",
-		 RREG32(mmVM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR));
-	dev_info(adev->dev, "  VM_CONTEXT0_CNTL2=0x%08X\n",
-		 RREG32(mmVM_CONTEXT0_CNTL2));
-	dev_info(adev->dev, "  VM_CONTEXT0_CNTL=0x%08X\n",
-		 RREG32(mmVM_CONTEXT0_CNTL));
-	dev_info(adev->dev, "  VM_L2_CONTEXT1_IDENTITY_APERTURE_LOW_ADDR=0x%08X\n",
-		 RREG32(mmVM_L2_CONTEXT1_IDENTITY_APERTURE_LOW_ADDR));
-	dev_info(adev->dev, "  VM_L2_CONTEXT1_IDENTITY_APERTURE_HIGH_ADDR=0x%08X\n",
-		 RREG32(mmVM_L2_CONTEXT1_IDENTITY_APERTURE_HIGH_ADDR));
-	dev_info(adev->dev, "  mmVM_L2_CONTEXT_IDENTITY_PHYSICAL_OFFSET=0x%08X\n",
-		 RREG32(mmVM_L2_CONTEXT_IDENTITY_PHYSICAL_OFFSET));
-	dev_info(adev->dev, "  VM_CONTEXT1_PAGE_TABLE_START_ADDR=0x%08X\n",
-		 RREG32(mmVM_CONTEXT1_PAGE_TABLE_START_ADDR));
-	dev_info(adev->dev, "  VM_CONTEXT1_PAGE_TABLE_END_ADDR=0x%08X\n",
-		 RREG32(mmVM_CONTEXT1_PAGE_TABLE_END_ADDR));
-	dev_info(adev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR=0x%08X\n",
-		 RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR));
-	dev_info(adev->dev, "  VM_CONTEXT1_CNTL2=0x%08X\n",
-		 RREG32(mmVM_CONTEXT1_CNTL2));
-	dev_info(adev->dev, "  VM_CONTEXT1_CNTL=0x%08X\n",
-		 RREG32(mmVM_CONTEXT1_CNTL));
-	for (i = 0; i < 16; i++) {
-		if (i < 8)
-			dev_info(adev->dev, "  VM_CONTEXT%d_PAGE_TABLE_BASE_ADDR=0x%08X\n",
-				 i, RREG32(mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR + i));
-		else
-			dev_info(adev->dev, "  VM_CONTEXT%d_PAGE_TABLE_BASE_ADDR=0x%08X\n",
-				 i, RREG32(mmVM_CONTEXT8_PAGE_TABLE_BASE_ADDR + i - 8));
-	}
-	dev_info(adev->dev, "  MC_VM_SYSTEM_APERTURE_LOW_ADDR=0x%08X\n",
-		 RREG32(mmMC_VM_SYSTEM_APERTURE_LOW_ADDR));
-	dev_info(adev->dev, "  MC_VM_SYSTEM_APERTURE_HIGH_ADDR=0x%08X\n",
-		 RREG32(mmMC_VM_SYSTEM_APERTURE_HIGH_ADDR));
-	dev_info(adev->dev, "  MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR=0x%08X\n",
-		 RREG32(mmMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR));
-	dev_info(adev->dev, "  MC_VM_FB_LOCATION=0x%08X\n",
-		 RREG32(mmMC_VM_FB_LOCATION));
-	dev_info(adev->dev, "  MC_VM_AGP_BASE=0x%08X\n",
-		 RREG32(mmMC_VM_AGP_BASE));
-	dev_info(adev->dev, "  MC_VM_AGP_TOP=0x%08X\n",
-		 RREG32(mmMC_VM_AGP_TOP));
-	dev_info(adev->dev, "  MC_VM_AGP_BOT=0x%08X\n",
-		 RREG32(mmMC_VM_AGP_BOT));
-
-	dev_info(adev->dev, "  HDP_REG_COHERENCY_FLUSH_CNTL=0x%08X\n",
-		 RREG32(mmHDP_REG_COHERENCY_FLUSH_CNTL));
-	dev_info(adev->dev, "  HDP_NONSURFACE_BASE=0x%08X\n",
-		 RREG32(mmHDP_NONSURFACE_BASE));
-	dev_info(adev->dev, "  HDP_NONSURFACE_INFO=0x%08X\n",
-		 RREG32(mmHDP_NONSURFACE_INFO));
-	dev_info(adev->dev, "  HDP_NONSURFACE_SIZE=0x%08X\n",
-		 RREG32(mmHDP_NONSURFACE_SIZE));
-	dev_info(adev->dev, "  HDP_MISC_CNTL=0x%08X\n",
-		 RREG32(mmHDP_MISC_CNTL));
-	dev_info(adev->dev, "  HDP_HOST_PATH_CNTL=0x%08X\n",
-		 RREG32(mmHDP_HOST_PATH_CNTL));
-
-	for (i = 0, j = 0; i < 32; i++, j += 0x6) {
-		dev_info(adev->dev, "  %d:\n", i);
-		dev_info(adev->dev, "  0x%04X=0x%08X\n",
-			 0xb05 + j, RREG32(0xb05 + j));
-		dev_info(adev->dev, "  0x%04X=0x%08X\n",
-			 0xb06 + j, RREG32(0xb06 + j));
-		dev_info(adev->dev, "  0x%04X=0x%08X\n",
-			 0xb07 + j, RREG32(0xb07 + j));
-		dev_info(adev->dev, "  0x%04X=0x%08X\n",
-			 0xb08 + j, RREG32(0xb08 + j));
-		dev_info(adev->dev, "  0x%04X=0x%08X\n",
-			 0xb09 + j, RREG32(0xb09 + j));
-	}
-
-	dev_info(adev->dev, "  BIF_FB_EN=0x%08X\n",
-		 RREG32(mmBIF_FB_EN));
-}
-
 static int gmc_v8_0_soft_reset(void *handle)
 {
 	struct amdgpu_mode_mc_save save;
@@ -1209,8 +1137,6 @@ static int gmc_v8_0_soft_reset(void *han
 	}
 
 	if (srbm_soft_reset) {
-		gmc_v8_0_print_status((void *)adev);
-
 		gmc_v8_0_mc_stop(adev, &save);
 		if (gmc_v8_0_wait_for_idle(adev)) {
 			dev_warn(adev->dev, "Wait for GMC idle timed out !\n");
@@ -1234,8 +1160,6 @@ static int gmc_v8_0_soft_reset(void *han
 
 		gmc_v8_0_mc_resume(adev, &save);
 		udelay(50);
-
-		gmc_v8_0_print_status((void *)adev);
 	}
 
 	return 0;
@@ -1313,11 +1237,11 @@ static int gmc_v8_0_process_interrupt(st
 }
 
 static void fiji_update_mc_medium_grain_clock_gating(struct amdgpu_device *adev,
-		bool enable)
+						     bool enable)
 {
 	uint32_t data;
 
-	if (enable) {
+	if (enable && (adev->cg_flags & AMD_CG_SUPPORT_MC_MGCG)) {
 		data = RREG32(mmMC_HUB_MISC_HUB_CG);
 		data |= MC_HUB_MISC_HUB_CG__ENABLE_MASK;
 		WREG32(mmMC_HUB_MISC_HUB_CG, data);
@@ -1393,11 +1317,11 @@ static void fiji_update_mc_medium_grain_
 }
 
 static void fiji_update_mc_light_sleep(struct amdgpu_device *adev,
-		bool enable)
+				       bool enable)
 {
 	uint32_t data;
 
-	if (enable) {
+	if (enable && (adev->cg_flags & AMD_CG_SUPPORT_MC_LS)) {
 		data = RREG32(mmMC_HUB_MISC_HUB_CG);
 		data |= MC_HUB_MISC_HUB_CG__MEM_LS_ENABLE_MASK;
 		WREG32(mmMC_HUB_MISC_HUB_CG, data);
@@ -1497,6 +1421,7 @@ static int gmc_v8_0_set_powergating_stat
 }
 
 const struct amd_ip_funcs gmc_v8_0_ip_funcs = {
+	.name = "gmc_v8_0",
 	.early_init = gmc_v8_0_early_init,
 	.late_init = gmc_v8_0_late_init,
 	.sw_init = gmc_v8_0_sw_init,
@@ -1508,7 +1433,6 @@ const struct amd_ip_funcs gmc_v8_0_ip_fu
 	.is_idle = gmc_v8_0_is_idle,
 	.wait_for_idle = gmc_v8_0_wait_for_idle,
 	.soft_reset = gmc_v8_0_soft_reset,
-	.print_status = gmc_v8_0_print_status,
 	.set_clockgating_state = gmc_v8_0_set_clockgating_state,
 	.set_powergating_state = gmc_v8_0_set_powergating_state,
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/iceland_dpm.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/iceland_dpm.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/iceland_dpm.c	2016-05-15 19:20:47.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/iceland_dpm.c	2016-07-24 18:17:02.000000000 -0400
@@ -72,6 +72,11 @@ static int iceland_dpm_sw_init(void *han
 
 static int iceland_dpm_sw_fini(void *handle)
 {
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+	release_firmware(adev->pm.fw);
+	adev->pm.fw = NULL;
+
 	return 0;
 }
 
@@ -157,6 +162,7 @@ static int iceland_dpm_set_powergating_s
 }
 
 const struct amd_ip_funcs iceland_dpm_ip_funcs = {
+	.name = "iceland_dpm",
 	.early_init = iceland_dpm_early_init,
 	.late_init = NULL,
 	.sw_init = iceland_dpm_sw_init,
@@ -168,7 +174,6 @@ const struct amd_ip_funcs iceland_dpm_ip
 	.is_idle = NULL,
 	.wait_for_idle = NULL,
 	.soft_reset = NULL,
-	.print_status = NULL,
 	.set_clockgating_state = iceland_dpm_set_clockgating_state,
 	.set_powergating_state = iceland_dpm_set_powergating_state,
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/iceland_ih.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/iceland_ih.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/iceland_ih.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/iceland_ih.c	2016-07-24 15:23:50.000000000 -0400
@@ -103,7 +103,6 @@ static void iceland_ih_disable_interrupt
  */
 static int iceland_ih_irq_init(struct amdgpu_device *adev)
 {
-	int ret = 0;
 	int rb_bufsz;
 	u32 interrupt_cntl, ih_cntl, ih_rb_cntl;
 	u64 wptr_off;
@@ -157,7 +156,7 @@ static int iceland_ih_irq_init(struct am
 	/* enable interrupts */
 	iceland_ih_enable_interrupts(adev);
 
-	return ret;
+	return 0;
 }
 
 /**
@@ -351,35 +350,6 @@ static int iceland_ih_wait_for_idle(void
 	return -ETIMEDOUT;
 }
 
-static void iceland_ih_print_status(void *handle)
-{
-	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-	dev_info(adev->dev, "ICELAND IH registers\n");
-	dev_info(adev->dev, "  SRBM_STATUS=0x%08X\n",
-		RREG32(mmSRBM_STATUS));
-	dev_info(adev->dev, "  SRBM_STATUS2=0x%08X\n",
-		RREG32(mmSRBM_STATUS2));
-	dev_info(adev->dev, "  INTERRUPT_CNTL=0x%08X\n",
-		 RREG32(mmINTERRUPT_CNTL));
-	dev_info(adev->dev, "  INTERRUPT_CNTL2=0x%08X\n",
-		 RREG32(mmINTERRUPT_CNTL2));
-	dev_info(adev->dev, "  IH_CNTL=0x%08X\n",
-		 RREG32(mmIH_CNTL));
-	dev_info(adev->dev, "  IH_RB_CNTL=0x%08X\n",
-		 RREG32(mmIH_RB_CNTL));
-	dev_info(adev->dev, "  IH_RB_BASE=0x%08X\n",
-		 RREG32(mmIH_RB_BASE));
-	dev_info(adev->dev, "  IH_RB_WPTR_ADDR_LO=0x%08X\n",
-		 RREG32(mmIH_RB_WPTR_ADDR_LO));
-	dev_info(adev->dev, "  IH_RB_WPTR_ADDR_HI=0x%08X\n",
-		 RREG32(mmIH_RB_WPTR_ADDR_HI));
-	dev_info(adev->dev, "  IH_RB_RPTR=0x%08X\n",
-		 RREG32(mmIH_RB_RPTR));
-	dev_info(adev->dev, "  IH_RB_WPTR=0x%08X\n",
-		 RREG32(mmIH_RB_WPTR));
-}
-
 static int iceland_ih_soft_reset(void *handle)
 {
 	u32 srbm_soft_reset = 0;
@@ -391,8 +361,6 @@ static int iceland_ih_soft_reset(void *h
 						SOFT_RESET_IH, 1);
 
 	if (srbm_soft_reset) {
-		iceland_ih_print_status((void *)adev);
-
 		tmp = RREG32(mmSRBM_SOFT_RESET);
 		tmp |= srbm_soft_reset;
 		dev_info(adev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp);
@@ -407,8 +375,6 @@ static int iceland_ih_soft_reset(void *h
 
 		/* Wait a little for things to settle down */
 		udelay(50);
-
-		iceland_ih_print_status((void *)adev);
 	}
 
 	return 0;
@@ -427,6 +393,7 @@ static int iceland_ih_set_powergating_st
 }
 
 const struct amd_ip_funcs iceland_ih_ip_funcs = {
+	.name = "iceland_ih",
 	.early_init = iceland_ih_early_init,
 	.late_init = NULL,
 	.sw_init = iceland_ih_sw_init,
@@ -438,7 +405,6 @@ const struct amd_ip_funcs iceland_ih_ip_
 	.is_idle = iceland_ih_is_idle,
 	.wait_for_idle = iceland_ih_wait_for_idle,
 	.soft_reset = iceland_ih_soft_reset,
-	.print_status = iceland_ih_print_status,
 	.set_clockgating_state = iceland_ih_set_clockgating_state,
 	.set_powergating_state = iceland_ih_set_powergating_state,
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/Kconfig linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/Kconfig
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -15,3 +15,13 @@ config DRM_AMDGPU_USERPTR
 	help
 	  This option selects CONFIG_MMU_NOTIFIER if it isn't already
 	  selected to enabled full userptr support.
+
+config DRM_AMDGPU_GART_DEBUGFS
+	bool "Allow GART access through debugfs"
+	depends on DRM_AMDGPU
+	depends on DEBUG_FS
+	default n
+	help
+	  Selecting this option creates a debugfs file to inspect the mapped
+	  pages. Uses more memory for housekeeping, enable only for debugging.
+
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/kv_dpm.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/kv_dpm.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/kv_dpm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/kv_dpm.c	2016-07-24 15:23:50.000000000 -0400
@@ -135,11 +135,6 @@ static void sumo_take_smu_control(struct
 #endif
 }
 
-static u32 sumo_get_sleep_divider_from_id(u32 id)
-{
-	return 1 << id;
-}
-
 static void sumo_construct_sclk_voltage_mapping_table(struct amdgpu_device *adev,
 						      struct sumo_sclk_voltage_mapping_table *sclk_voltage_mapping_table,
 						      ATOM_AVAILABLE_SCLK_LIST *table)
@@ -2176,8 +2171,7 @@ static u8 kv_get_sleep_divider_id_from_c
 	struct kv_power_info *pi = kv_get_pi(adev);
 	u32 i;
 	u32 temp;
-	u32 min = (min_sclk_in_sr > KV_MINIMUM_ENGINE_CLOCK) ?
-		min_sclk_in_sr : KV_MINIMUM_ENGINE_CLOCK;
+	u32 min = max(min_sclk_in_sr, (u32)KV_MINIMUM_ENGINE_CLOCK);
 
 	if (sclk < min)
 		return 0;
@@ -2186,7 +2180,7 @@ static u8 kv_get_sleep_divider_id_from_c
 		return 0;
 
 	for (i = KV_MAX_DEEPSLEEP_DIVIDER_ID; i > 0; i--) {
-		temp = sclk / sumo_get_sleep_divider_from_id(i);
+		temp = sclk >> i;
 		if (temp >= min)
 			break;
 	}
@@ -2258,7 +2252,7 @@ static void kv_apply_state_adjust_rules(
 	if (pi->caps_stable_p_state) {
 		stable_p_state_sclk = (max_limits->sclk * 75) / 100;
 
-		for (i = table->count - 1; i >= 0; i++) {
+		for (i = table->count - 1; i >= 0; i--) {
 			if (stable_p_state_sclk >= table->entries[i].clk) {
 				stable_p_state_sclk = table->entries[i].clk;
 				break;
@@ -3147,62 +3141,6 @@ static int kv_dpm_wait_for_idle(void *ha
 	return 0;
 }
 
-static void kv_dpm_print_status(void *handle)
-{
-	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-	dev_info(adev->dev, "KV/KB DPM registers\n");
-	dev_info(adev->dev, "  DIDT_SQ_CTRL0=0x%08X\n",
-		 RREG32_DIDT(ixDIDT_SQ_CTRL0));
-	dev_info(adev->dev, "  DIDT_DB_CTRL0=0x%08X\n",
-		 RREG32_DIDT(ixDIDT_DB_CTRL0));
-	dev_info(adev->dev, "  DIDT_TD_CTRL0=0x%08X\n",
-		 RREG32_DIDT(ixDIDT_TD_CTRL0));
-	dev_info(adev->dev, "  DIDT_TCP_CTRL0=0x%08X\n",
-		 RREG32_DIDT(ixDIDT_TCP_CTRL0));
-	dev_info(adev->dev, "  LCAC_SX0_OVR_SEL=0x%08X\n",
-		 RREG32_SMC(ixLCAC_SX0_OVR_SEL));
-	dev_info(adev->dev, "  LCAC_SX0_OVR_VAL=0x%08X\n",
-		 RREG32_SMC(ixLCAC_SX0_OVR_VAL));
-	dev_info(adev->dev, "  LCAC_MC0_OVR_SEL=0x%08X\n",
-		 RREG32_SMC(ixLCAC_MC0_OVR_SEL));
-	dev_info(adev->dev, "  LCAC_MC0_OVR_VAL=0x%08X\n",
-		 RREG32_SMC(ixLCAC_MC0_OVR_VAL));
-	dev_info(adev->dev, "  LCAC_MC1_OVR_SEL=0x%08X\n",
-		 RREG32_SMC(ixLCAC_MC1_OVR_SEL));
-	dev_info(adev->dev, "  LCAC_MC1_OVR_VAL=0x%08X\n",
-		 RREG32_SMC(ixLCAC_MC1_OVR_VAL));
-	dev_info(adev->dev, "  LCAC_MC2_OVR_SEL=0x%08X\n",
-		 RREG32_SMC(ixLCAC_MC2_OVR_SEL));
-	dev_info(adev->dev, "  LCAC_MC2_OVR_VAL=0x%08X\n",
-		 RREG32_SMC(ixLCAC_MC2_OVR_VAL));
-	dev_info(adev->dev, "  LCAC_MC3_OVR_SEL=0x%08X\n",
-		 RREG32_SMC(ixLCAC_MC3_OVR_SEL));
-	dev_info(adev->dev, "  LCAC_MC3_OVR_VAL=0x%08X\n",
-		 RREG32_SMC(ixLCAC_MC3_OVR_VAL));
-	dev_info(adev->dev, "  LCAC_CPL_OVR_SEL=0x%08X\n",
-		 RREG32_SMC(ixLCAC_CPL_OVR_SEL));
-	dev_info(adev->dev, "  LCAC_CPL_OVR_VAL=0x%08X\n",
-		 RREG32_SMC(ixLCAC_CPL_OVR_VAL));
-	dev_info(adev->dev, "  CG_FREQ_TRAN_VOTING_0=0x%08X\n",
-		 RREG32_SMC(ixCG_FREQ_TRAN_VOTING_0));
-	dev_info(adev->dev, "  GENERAL_PWRMGT=0x%08X\n",
-		 RREG32_SMC(ixGENERAL_PWRMGT));
-	dev_info(adev->dev, "  SCLK_PWRMGT_CNTL=0x%08X\n",
-		 RREG32_SMC(ixSCLK_PWRMGT_CNTL));
-	dev_info(adev->dev, "  SMC_MESSAGE_0=0x%08X\n",
-		 RREG32(mmSMC_MESSAGE_0));
-	dev_info(adev->dev, "  SMC_RESP_0=0x%08X\n",
-		 RREG32(mmSMC_RESP_0));
-	dev_info(adev->dev, "  SMC_MSG_ARG_0=0x%08X\n",
-		 RREG32(mmSMC_MSG_ARG_0));
-	dev_info(adev->dev, "  SMC_IND_INDEX_0=0x%08X\n",
-		 RREG32(mmSMC_IND_INDEX_0));
-	dev_info(adev->dev, "  SMC_IND_DATA_0=0x%08X\n",
-		 RREG32(mmSMC_IND_DATA_0));
-	dev_info(adev->dev, "  SMC_IND_ACCESS_CNTL=0x%08X\n",
-		 RREG32(mmSMC_IND_ACCESS_CNTL));
-}
 
 static int kv_dpm_soft_reset(void *handle)
 {
@@ -3300,6 +3238,7 @@ static int kv_dpm_set_powergating_state(
 }
 
 const struct amd_ip_funcs kv_dpm_ip_funcs = {
+	.name = "kv_dpm",
 	.early_init = kv_dpm_early_init,
 	.late_init = kv_dpm_late_init,
 	.sw_init = kv_dpm_sw_init,
@@ -3311,7 +3250,6 @@ const struct amd_ip_funcs kv_dpm_ip_func
 	.is_idle = kv_dpm_is_idle,
 	.wait_for_idle = kv_dpm_wait_for_idle,
 	.soft_reset = kv_dpm_soft_reset,
-	.print_status = kv_dpm_print_status,
 	.set_clockgating_state = kv_dpm_set_clockgating_state,
 	.set_powergating_state = kv_dpm_set_powergating_state,
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c	2016-05-15 19:20:51.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c	2016-07-24 18:17:11.000000000 -0400
@@ -104,6 +104,15 @@ static void sdma_v2_4_init_golden_regist
 	}
 }
 
+static void sdma_v2_4_free_microcode(struct amdgpu_device *adev)
+{
+	int i;
+	for (i = 0; i < adev->sdma.num_instances; i++) {
+		release_firmware(adev->sdma.instance[i].fw);
+		adev->sdma.instance[i].fw = NULL;
+	}
+}
+
 /**
  * sdma_v2_4_init_microcode - load ucode images from disk
  *
@@ -241,9 +250,10 @@ static void sdma_v2_4_ring_insert_nop(st
  * Schedule an IB in the DMA ring (VI).
  */
 static void sdma_v2_4_ring_emit_ib(struct amdgpu_ring *ring,
-				   struct amdgpu_ib *ib)
+				   struct amdgpu_ib *ib,
+				   unsigned vm_id, bool ctx_switch)
 {
-	u32 vmid = ib->vm_id & 0xf;
+	u32 vmid = vm_id & 0xf;
 	u32 next_rptr = ring->wptr + 5;
 
 	while ((next_rptr & 7) != 2)
@@ -459,6 +469,8 @@ static int sdma_v2_4_gfx_resume(struct a
 		/* Initialize the ring buffer's read and write pointers */
 		WREG32(mmSDMA0_GFX_RB_RPTR + sdma_offsets[i], 0);
 		WREG32(mmSDMA0_GFX_RB_WPTR + sdma_offsets[i], 0);
+		WREG32(mmSDMA0_GFX_IB_RPTR + sdma_offsets[i], 0);
+		WREG32(mmSDMA0_GFX_IB_OFFSET + sdma_offsets[i], 0);
 
 		/* set the wb address whether it's enabled or not */
 		WREG32(mmSDMA0_GFX_RB_RPTR_ADDR_HI + sdma_offsets[i],
@@ -487,7 +499,11 @@ static int sdma_v2_4_gfx_resume(struct a
 		WREG32(mmSDMA0_GFX_IB_CNTL + sdma_offsets[i], ib_cntl);
 
 		ring->ready = true;
+	}
 
+	sdma_v2_4_enable(adev, true);
+	for (i = 0; i < adev->sdma.num_instances; i++) {
+		ring = &adev->sdma.instance[i].ring;
 		r = amdgpu_ring_test_ring(ring);
 		if (r) {
 			ring->ready = false;
@@ -578,8 +594,8 @@ static int sdma_v2_4_start(struct amdgpu
 			return -EINVAL;
 	}
 
-	/* unhalt the MEs */
-	sdma_v2_4_enable(adev, true);
+	/* halt the engine before programing */
+	sdma_v2_4_enable(adev, false);
 
 	/* start the gfx rings and rlc compute queues */
 	r = sdma_v2_4_gfx_resume(adev);
@@ -700,7 +716,7 @@ static int sdma_v2_4_ring_test_ib(struct
 	ib.ptr[7] = SDMA_PKT_HEADER_OP(SDMA_OP_NOP);
 	ib.length_dw = 8;
 
-	r = amdgpu_ib_schedule(ring, 1, &ib, NULL, &f);
+	r = amdgpu_ib_schedule(ring, 1, &ib, NULL, NULL, &f);
 	if (r)
 		goto err1;
 
@@ -989,7 +1005,7 @@ static int sdma_v2_4_sw_init(void *handl
 		ring->ring_obj = NULL;
 		ring->use_doorbell = false;
 		sprintf(ring->name, "sdma%d", i);
-		r = amdgpu_ring_init(adev, ring, 256 * 1024,
+		r = amdgpu_ring_init(adev, ring, 1024,
 				     SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP), 0xf,
 				     &adev->sdma.trap_irq,
 				     (i == 0) ?
@@ -1010,6 +1026,7 @@ static int sdma_v2_4_sw_fini(void *handl
 	for (i = 0; i < adev->sdma.num_instances; i++)
 		amdgpu_ring_fini(&adev->sdma.instance[i].ring);
 
+	sdma_v2_4_free_microcode(adev);
 	return 0;
 }
 
@@ -1079,55 +1096,6 @@ static int sdma_v2_4_wait_for_idle(void
 	return -ETIMEDOUT;
 }
 
-static void sdma_v2_4_print_status(void *handle)
-{
-	int i, j;
-	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-	dev_info(adev->dev, "VI SDMA registers\n");
-	dev_info(adev->dev, "  SRBM_STATUS2=0x%08X\n",
-		 RREG32(mmSRBM_STATUS2));
-	for (i = 0; i < adev->sdma.num_instances; i++) {
-		dev_info(adev->dev, "  SDMA%d_STATUS_REG=0x%08X\n",
-			 i, RREG32(mmSDMA0_STATUS_REG + sdma_offsets[i]));
-		dev_info(adev->dev, "  SDMA%d_F32_CNTL=0x%08X\n",
-			 i, RREG32(mmSDMA0_F32_CNTL + sdma_offsets[i]));
-		dev_info(adev->dev, "  SDMA%d_CNTL=0x%08X\n",
-			 i, RREG32(mmSDMA0_CNTL + sdma_offsets[i]));
-		dev_info(adev->dev, "  SDMA%d_SEM_WAIT_FAIL_TIMER_CNTL=0x%08X\n",
-			 i, RREG32(mmSDMA0_SEM_WAIT_FAIL_TIMER_CNTL + sdma_offsets[i]));
-		dev_info(adev->dev, "  SDMA%d_GFX_IB_CNTL=0x%08X\n",
-			 i, RREG32(mmSDMA0_GFX_IB_CNTL + sdma_offsets[i]));
-		dev_info(adev->dev, "  SDMA%d_GFX_RB_CNTL=0x%08X\n",
-			 i, RREG32(mmSDMA0_GFX_RB_CNTL + sdma_offsets[i]));
-		dev_info(adev->dev, "  SDMA%d_GFX_RB_RPTR=0x%08X\n",
-			 i, RREG32(mmSDMA0_GFX_RB_RPTR + sdma_offsets[i]));
-		dev_info(adev->dev, "  SDMA%d_GFX_RB_WPTR=0x%08X\n",
-			 i, RREG32(mmSDMA0_GFX_RB_WPTR + sdma_offsets[i]));
-		dev_info(adev->dev, "  SDMA%d_GFX_RB_RPTR_ADDR_HI=0x%08X\n",
-			 i, RREG32(mmSDMA0_GFX_RB_RPTR_ADDR_HI + sdma_offsets[i]));
-		dev_info(adev->dev, "  SDMA%d_GFX_RB_RPTR_ADDR_LO=0x%08X\n",
-			 i, RREG32(mmSDMA0_GFX_RB_RPTR_ADDR_LO + sdma_offsets[i]));
-		dev_info(adev->dev, "  SDMA%d_GFX_RB_BASE=0x%08X\n",
-			 i, RREG32(mmSDMA0_GFX_RB_BASE + sdma_offsets[i]));
-		dev_info(adev->dev, "  SDMA%d_GFX_RB_BASE_HI=0x%08X\n",
-			 i, RREG32(mmSDMA0_GFX_RB_BASE_HI + sdma_offsets[i]));
-		dev_info(adev->dev, "  SDMA%d_TILING_CONFIG=0x%08X\n",
-			 i, RREG32(mmSDMA0_TILING_CONFIG + sdma_offsets[i]));
-		mutex_lock(&adev->srbm_mutex);
-		for (j = 0; j < 16; j++) {
-			vi_srbm_select(adev, 0, 0, 0, j);
-			dev_info(adev->dev, "  VM %d:\n", j);
-			dev_info(adev->dev, "  SDMA%d_GFX_VIRTUAL_ADDR=0x%08X\n",
-				 i, RREG32(mmSDMA0_GFX_VIRTUAL_ADDR + sdma_offsets[i]));
-			dev_info(adev->dev, "  SDMA%d_GFX_APE1_CNTL=0x%08X\n",
-				 i, RREG32(mmSDMA0_GFX_APE1_CNTL + sdma_offsets[i]));
-		}
-		vi_srbm_select(adev, 0, 0, 0, 0);
-		mutex_unlock(&adev->srbm_mutex);
-	}
-}
-
 static int sdma_v2_4_soft_reset(void *handle)
 {
 	u32 srbm_soft_reset = 0;
@@ -1150,8 +1118,6 @@ static int sdma_v2_4_soft_reset(void *ha
 	}
 
 	if (srbm_soft_reset) {
-		sdma_v2_4_print_status((void *)adev);
-
 		tmp = RREG32(mmSRBM_SOFT_RESET);
 		tmp |= srbm_soft_reset;
 		dev_info(adev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp);
@@ -1166,8 +1132,6 @@ static int sdma_v2_4_soft_reset(void *ha
 
 		/* Wait a little for things to settle down */
 		udelay(50);
-
-		sdma_v2_4_print_status((void *)adev);
 	}
 
 	return 0;
@@ -1282,6 +1246,7 @@ static int sdma_v2_4_set_powergating_sta
 }
 
 const struct amd_ip_funcs sdma_v2_4_ip_funcs = {
+	.name = "sdma_v2_4",
 	.early_init = sdma_v2_4_early_init,
 	.late_init = NULL,
 	.sw_init = sdma_v2_4_sw_init,
@@ -1293,7 +1258,6 @@ const struct amd_ip_funcs sdma_v2_4_ip_f
 	.is_idle = sdma_v2_4_is_idle,
 	.wait_for_idle = sdma_v2_4_wait_for_idle,
 	.soft_reset = sdma_v2_4_soft_reset,
-	.print_status = sdma_v2_4_print_status,
 	.set_clockgating_state = sdma_v2_4_set_clockgating_state,
 	.set_powergating_state = sdma_v2_4_set_powergating_state,
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c	2016-05-15 19:20:54.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c	2016-07-24 18:17:23.000000000 -0400
@@ -51,6 +51,7 @@ static void sdma_v3_0_set_irq_funcs(stru
 
 /*(DEBLOBBED)*/
 
+
 static const u32 sdma_offsets[SDMA_MAX_INSTANCE] =
 {
 	SDMA0_REGISTER_OFFSET,
@@ -95,6 +96,34 @@ static const u32 fiji_mgcg_cgcg_init[] =
 	mmSDMA1_CLK_CTRL, 0xff000ff0, 0x00000100
 };
 
+static const u32 golden_settings_polaris11_a11[] =
+{
+	mmSDMA0_CHICKEN_BITS, 0xfc910007, 0x00810007,
+	mmSDMA0_CLK_CTRL, 0xff000fff, 0x00000000,
+	mmSDMA0_GFX_IB_CNTL, 0x800f0111, 0x00000100,
+	mmSDMA0_RLC0_IB_CNTL, 0x800f0111, 0x00000100,
+	mmSDMA0_RLC1_IB_CNTL, 0x800f0111, 0x00000100,
+	mmSDMA1_CHICKEN_BITS, 0xfc910007, 0x00810007,
+	mmSDMA1_CLK_CTRL, 0xff000fff, 0x00000000,
+	mmSDMA1_GFX_IB_CNTL, 0x800f0111, 0x00000100,
+	mmSDMA1_RLC0_IB_CNTL, 0x800f0111, 0x00000100,
+	mmSDMA1_RLC1_IB_CNTL, 0x800f0111, 0x00000100,
+};
+
+static const u32 golden_settings_polaris10_a11[] =
+{
+	mmSDMA0_CHICKEN_BITS, 0xfc910007, 0x00810007,
+	mmSDMA0_CLK_CTRL, 0xff000fff, 0x00000000,
+	mmSDMA0_GFX_IB_CNTL, 0x800f0111, 0x00000100,
+	mmSDMA0_RLC0_IB_CNTL, 0x800f0111, 0x00000100,
+	mmSDMA0_RLC1_IB_CNTL, 0x800f0111, 0x00000100,
+	mmSDMA1_CHICKEN_BITS, 0xfc910007, 0x00810007,
+	mmSDMA1_CLK_CTRL, 0xff000fff, 0x00000000,
+	mmSDMA1_GFX_IB_CNTL, 0x800f0111, 0x00000100,
+	mmSDMA1_RLC0_IB_CNTL, 0x800f0111, 0x00000100,
+	mmSDMA1_RLC1_IB_CNTL, 0x800f0111, 0x00000100,
+};
+
 static const u32 cz_golden_settings_a11[] =
 {
 	mmSDMA0_CHICKEN_BITS, 0xfc910007, 0x00810007,
@@ -166,6 +195,16 @@ static void sdma_v3_0_init_golden_regist
 						 golden_settings_tonga_a11,
 						 (const u32)ARRAY_SIZE(golden_settings_tonga_a11));
 		break;
+	case CHIP_POLARIS11:
+		amdgpu_program_register_sequence(adev,
+						 golden_settings_polaris11_a11,
+						 (const u32)ARRAY_SIZE(golden_settings_polaris11_a11));
+		break;
+	case CHIP_POLARIS10:
+		amdgpu_program_register_sequence(adev,
+						 golden_settings_polaris10_a11,
+						 (const u32)ARRAY_SIZE(golden_settings_polaris10_a11));
+		break;
 	case CHIP_CARRIZO:
 		amdgpu_program_register_sequence(adev,
 						 cz_mgcg_cgcg_init,
@@ -187,6 +226,15 @@ static void sdma_v3_0_init_golden_regist
 	}
 }
 
+static void sdma_v3_0_free_microcode(struct amdgpu_device *adev)
+{
+	int i;
+	for (i = 0; i < adev->sdma.num_instances; i++) {
+		release_firmware(adev->sdma.instance[i].fw);
+		adev->sdma.instance[i].fw = NULL;
+	}
+}
+
 /**
  * sdma_v3_0_init_microcode - load ucode images from disk
  *
@@ -214,6 +262,12 @@ static int sdma_v3_0_init_microcode(stru
 	case CHIP_FIJI:
 		chip_name = "fiji";
 		break;
+	case CHIP_POLARIS11:
+		chip_name = "polaris11";
+		break;
+	case CHIP_POLARIS10:
+		chip_name = "polaris10";
+		break;
 	case CHIP_CARRIZO:
 		chip_name = "carrizo";
 		break;
@@ -347,9 +401,10 @@ static void sdma_v3_0_ring_insert_nop(st
  * Schedule an IB in the DMA ring (VI).
  */
 static void sdma_v3_0_ring_emit_ib(struct amdgpu_ring *ring,
-				   struct amdgpu_ib *ib)
+				   struct amdgpu_ib *ib,
+				   unsigned vm_id, bool ctx_switch)
 {
-	u32 vmid = ib->vm_id & 0xf;
+	u32 vmid = vm_id & 0xf;
 	u32 next_rptr = ring->wptr + 5;
 
 	while ((next_rptr & 7) != 2)
@@ -446,6 +501,31 @@ static void sdma_v3_0_ring_emit_fence(st
 	amdgpu_ring_write(ring, SDMA_PKT_TRAP_INT_CONTEXT_INT_CONTEXT(0));
 }
 
+unsigned init_cond_exec(struct amdgpu_ring *ring)
+{
+	unsigned ret;
+	amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_COND_EXE));
+	amdgpu_ring_write(ring, lower_32_bits(ring->cond_exe_gpu_addr));
+	amdgpu_ring_write(ring, upper_32_bits(ring->cond_exe_gpu_addr));
+	amdgpu_ring_write(ring, 1);
+	ret = ring->wptr;/* this is the offset we need patch later */
+	amdgpu_ring_write(ring, 0x55aa55aa);/* insert dummy here and patch it later */
+	return ret;
+}
+
+void patch_cond_exec(struct amdgpu_ring *ring, unsigned offset)
+{
+	unsigned cur;
+	BUG_ON(ring->ring[offset] != 0x55aa55aa);
+
+	cur = ring->wptr - 1;
+	if (likely(cur > offset))
+		ring->ring[offset] = cur - offset;
+	else
+		ring->ring[offset] = (ring->ring_size>>2) - offset + cur;
+}
+
+
 /**
  * sdma_v3_0_gfx_stop - stop the gfx async dma engines
  *
@@ -591,6 +671,8 @@ static int sdma_v3_0_gfx_resume(struct a
 		/* Initialize the ring buffer's read and write pointers */
 		WREG32(mmSDMA0_GFX_RB_RPTR + sdma_offsets[i], 0);
 		WREG32(mmSDMA0_GFX_RB_WPTR + sdma_offsets[i], 0);
+		WREG32(mmSDMA0_GFX_IB_RPTR + sdma_offsets[i], 0);
+		WREG32(mmSDMA0_GFX_IB_OFFSET + sdma_offsets[i], 0);
 
 		/* set the wb address whether it's enabled or not */
 		WREG32(mmSDMA0_GFX_RB_RPTR_ADDR_HI + sdma_offsets[i],
@@ -630,7 +712,15 @@ static int sdma_v3_0_gfx_resume(struct a
 		WREG32(mmSDMA0_GFX_IB_CNTL + sdma_offsets[i], ib_cntl);
 
 		ring->ready = true;
+	}
 
+	/* unhalt the MEs */
+	sdma_v3_0_enable(adev, true);
+	/* enable sdma ring preemption */
+	sdma_v3_0_ctx_switch_enable(adev, true);
+
+	for (i = 0; i < adev->sdma.num_instances; i++) {
+		ring = &adev->sdma.instance[i].ring;
 		r = amdgpu_ring_test_ring(ring);
 		if (r) {
 			ring->ready = false;
@@ -723,10 +813,9 @@ static int sdma_v3_0_start(struct amdgpu
 		}
 	}
 
-	/* unhalt the MEs */
-	sdma_v3_0_enable(adev, true);
-	/* enable sdma ring preemption */
-	sdma_v3_0_ctx_switch_enable(adev, true);
+	/* disble sdma engine before programing it */
+	sdma_v3_0_ctx_switch_enable(adev, false);
+	sdma_v3_0_enable(adev, false);
 
 	/* start the gfx rings and rlc compute queues */
 	r = sdma_v3_0_gfx_resume(adev);
@@ -847,7 +936,7 @@ static int sdma_v3_0_ring_test_ib(struct
 	ib.ptr[7] = SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP);
 	ib.length_dw = 8;
 
-	r = amdgpu_ib_schedule(ring, 1, &ib, NULL, &f);
+	r = amdgpu_ib_schedule(ring, 1, &ib, NULL, NULL, &f);
 	if (r)
 		goto err1;
 
@@ -1145,7 +1234,7 @@ static int sdma_v3_0_sw_init(void *handl
 			AMDGPU_DOORBELL_sDMA_ENGINE0 : AMDGPU_DOORBELL_sDMA_ENGINE1;
 
 		sprintf(ring->name, "sdma%d", i);
-		r = amdgpu_ring_init(adev, ring, 256 * 1024,
+		r = amdgpu_ring_init(adev, ring, 1024,
 				     SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP), 0xf,
 				     &adev->sdma.trap_irq,
 				     (i == 0) ?
@@ -1166,6 +1255,7 @@ static int sdma_v3_0_sw_fini(void *handl
 	for (i = 0; i < adev->sdma.num_instances; i++)
 		amdgpu_ring_fini(&adev->sdma.instance[i].ring);
 
+	sdma_v3_0_free_microcode(adev);
 	return 0;
 }
 
@@ -1236,57 +1326,6 @@ static int sdma_v3_0_wait_for_idle(void
 	return -ETIMEDOUT;
 }
 
-static void sdma_v3_0_print_status(void *handle)
-{
-	int i, j;
-	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-	dev_info(adev->dev, "VI SDMA registers\n");
-	dev_info(adev->dev, "  SRBM_STATUS2=0x%08X\n",
-		 RREG32(mmSRBM_STATUS2));
-	for (i = 0; i < adev->sdma.num_instances; i++) {
-		dev_info(adev->dev, "  SDMA%d_STATUS_REG=0x%08X\n",
-			 i, RREG32(mmSDMA0_STATUS_REG + sdma_offsets[i]));
-		dev_info(adev->dev, "  SDMA%d_F32_CNTL=0x%08X\n",
-			 i, RREG32(mmSDMA0_F32_CNTL + sdma_offsets[i]));
-		dev_info(adev->dev, "  SDMA%d_CNTL=0x%08X\n",
-			 i, RREG32(mmSDMA0_CNTL + sdma_offsets[i]));
-		dev_info(adev->dev, "  SDMA%d_SEM_WAIT_FAIL_TIMER_CNTL=0x%08X\n",
-			 i, RREG32(mmSDMA0_SEM_WAIT_FAIL_TIMER_CNTL + sdma_offsets[i]));
-		dev_info(adev->dev, "  SDMA%d_GFX_IB_CNTL=0x%08X\n",
-			 i, RREG32(mmSDMA0_GFX_IB_CNTL + sdma_offsets[i]));
-		dev_info(adev->dev, "  SDMA%d_GFX_RB_CNTL=0x%08X\n",
-			 i, RREG32(mmSDMA0_GFX_RB_CNTL + sdma_offsets[i]));
-		dev_info(adev->dev, "  SDMA%d_GFX_RB_RPTR=0x%08X\n",
-			 i, RREG32(mmSDMA0_GFX_RB_RPTR + sdma_offsets[i]));
-		dev_info(adev->dev, "  SDMA%d_GFX_RB_WPTR=0x%08X\n",
-			 i, RREG32(mmSDMA0_GFX_RB_WPTR + sdma_offsets[i]));
-		dev_info(adev->dev, "  SDMA%d_GFX_RB_RPTR_ADDR_HI=0x%08X\n",
-			 i, RREG32(mmSDMA0_GFX_RB_RPTR_ADDR_HI + sdma_offsets[i]));
-		dev_info(adev->dev, "  SDMA%d_GFX_RB_RPTR_ADDR_LO=0x%08X\n",
-			 i, RREG32(mmSDMA0_GFX_RB_RPTR_ADDR_LO + sdma_offsets[i]));
-		dev_info(adev->dev, "  SDMA%d_GFX_RB_BASE=0x%08X\n",
-			 i, RREG32(mmSDMA0_GFX_RB_BASE + sdma_offsets[i]));
-		dev_info(adev->dev, "  SDMA%d_GFX_RB_BASE_HI=0x%08X\n",
-			 i, RREG32(mmSDMA0_GFX_RB_BASE_HI + sdma_offsets[i]));
-		dev_info(adev->dev, "  SDMA%d_GFX_DOORBELL=0x%08X\n",
-			 i, RREG32(mmSDMA0_GFX_DOORBELL + sdma_offsets[i]));
-		dev_info(adev->dev, "  SDMA%d_TILING_CONFIG=0x%08X\n",
-			 i, RREG32(mmSDMA0_TILING_CONFIG + sdma_offsets[i]));
-		mutex_lock(&adev->srbm_mutex);
-		for (j = 0; j < 16; j++) {
-			vi_srbm_select(adev, 0, 0, 0, j);
-			dev_info(adev->dev, "  VM %d:\n", j);
-			dev_info(adev->dev, "  SDMA%d_GFX_VIRTUAL_ADDR=0x%08X\n",
-				 i, RREG32(mmSDMA0_GFX_VIRTUAL_ADDR + sdma_offsets[i]));
-			dev_info(adev->dev, "  SDMA%d_GFX_APE1_CNTL=0x%08X\n",
-				 i, RREG32(mmSDMA0_GFX_APE1_CNTL + sdma_offsets[i]));
-		}
-		vi_srbm_select(adev, 0, 0, 0, 0);
-		mutex_unlock(&adev->srbm_mutex);
-	}
-}
-
 static int sdma_v3_0_soft_reset(void *handle)
 {
 	u32 srbm_soft_reset = 0;
@@ -1309,8 +1348,6 @@ static int sdma_v3_0_soft_reset(void *ha
 	}
 
 	if (srbm_soft_reset) {
-		sdma_v3_0_print_status((void *)adev);
-
 		tmp = RREG32(mmSRBM_SOFT_RESET);
 		tmp |= srbm_soft_reset;
 		dev_info(adev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp);
@@ -1325,8 +1362,6 @@ static int sdma_v3_0_soft_reset(void *ha
 
 		/* Wait a little for things to settle down */
 		udelay(50);
-
-		sdma_v3_0_print_status((void *)adev);
 	}
 
 	return 0;
@@ -1427,40 +1462,31 @@ static int sdma_v3_0_process_illegal_ins
 	return 0;
 }
 
-static void fiji_update_sdma_medium_grain_clock_gating(
+static void sdma_v3_0_update_sdma_medium_grain_clock_gating(
 		struct amdgpu_device *adev,
 		bool enable)
 {
 	uint32_t temp, data;
+	int i;
 
-	if (enable) {
-		temp = data = RREG32(mmSDMA0_CLK_CTRL);
-		data &= ~(SDMA0_CLK_CTRL__SOFT_OVERRIDE7_MASK |
-				SDMA0_CLK_CTRL__SOFT_OVERRIDE6_MASK |
-				SDMA0_CLK_CTRL__SOFT_OVERRIDE5_MASK |
-				SDMA0_CLK_CTRL__SOFT_OVERRIDE4_MASK |
-				SDMA0_CLK_CTRL__SOFT_OVERRIDE3_MASK |
-				SDMA0_CLK_CTRL__SOFT_OVERRIDE2_MASK |
-				SDMA0_CLK_CTRL__SOFT_OVERRIDE1_MASK |
-				SDMA0_CLK_CTRL__SOFT_OVERRIDE0_MASK);
-		if (data != temp)
-			WREG32(mmSDMA0_CLK_CTRL, data);
-
-		temp = data = RREG32(mmSDMA1_CLK_CTRL);
-		data &= ~(SDMA1_CLK_CTRL__SOFT_OVERRIDE7_MASK |
-				SDMA1_CLK_CTRL__SOFT_OVERRIDE6_MASK |
-				SDMA1_CLK_CTRL__SOFT_OVERRIDE5_MASK |
-				SDMA1_CLK_CTRL__SOFT_OVERRIDE4_MASK |
-				SDMA1_CLK_CTRL__SOFT_OVERRIDE3_MASK |
-				SDMA1_CLK_CTRL__SOFT_OVERRIDE2_MASK |
-				SDMA1_CLK_CTRL__SOFT_OVERRIDE1_MASK |
-				SDMA1_CLK_CTRL__SOFT_OVERRIDE0_MASK);
-
-		if (data != temp)
-			WREG32(mmSDMA1_CLK_CTRL, data);
+	if (enable && (adev->cg_flags & AMD_CG_SUPPORT_SDMA_MGCG)) {
+		for (i = 0; i < adev->sdma.num_instances; i++) {
+			temp = data = RREG32(mmSDMA0_CLK_CTRL + sdma_offsets[i]);
+			data &= ~(SDMA0_CLK_CTRL__SOFT_OVERRIDE7_MASK |
+				  SDMA0_CLK_CTRL__SOFT_OVERRIDE6_MASK |
+				  SDMA0_CLK_CTRL__SOFT_OVERRIDE5_MASK |
+				  SDMA0_CLK_CTRL__SOFT_OVERRIDE4_MASK |
+				  SDMA0_CLK_CTRL__SOFT_OVERRIDE3_MASK |
+				  SDMA0_CLK_CTRL__SOFT_OVERRIDE2_MASK |
+				  SDMA0_CLK_CTRL__SOFT_OVERRIDE1_MASK |
+				  SDMA0_CLK_CTRL__SOFT_OVERRIDE0_MASK);
+			if (data != temp)
+				WREG32(mmSDMA0_CLK_CTRL + sdma_offsets[i], data);
+		}
 	} else {
-		temp = data = RREG32(mmSDMA0_CLK_CTRL);
-		data |= SDMA0_CLK_CTRL__SOFT_OVERRIDE7_MASK |
+		for (i = 0; i < adev->sdma.num_instances; i++) {
+			temp = data = RREG32(mmSDMA0_CLK_CTRL + sdma_offsets[i]);
+			data |= SDMA0_CLK_CTRL__SOFT_OVERRIDE7_MASK |
 				SDMA0_CLK_CTRL__SOFT_OVERRIDE6_MASK |
 				SDMA0_CLK_CTRL__SOFT_OVERRIDE5_MASK |
 				SDMA0_CLK_CTRL__SOFT_OVERRIDE4_MASK |
@@ -1469,54 +1495,35 @@ static void fiji_update_sdma_medium_grai
 				SDMA0_CLK_CTRL__SOFT_OVERRIDE1_MASK |
 				SDMA0_CLK_CTRL__SOFT_OVERRIDE0_MASK;
 
-		if (data != temp)
-			WREG32(mmSDMA0_CLK_CTRL, data);
-
-		temp = data = RREG32(mmSDMA1_CLK_CTRL);
-		data |= SDMA1_CLK_CTRL__SOFT_OVERRIDE7_MASK |
-				SDMA1_CLK_CTRL__SOFT_OVERRIDE6_MASK |
-				SDMA1_CLK_CTRL__SOFT_OVERRIDE5_MASK |
-				SDMA1_CLK_CTRL__SOFT_OVERRIDE4_MASK |
-				SDMA1_CLK_CTRL__SOFT_OVERRIDE3_MASK |
-				SDMA1_CLK_CTRL__SOFT_OVERRIDE2_MASK |
-				SDMA1_CLK_CTRL__SOFT_OVERRIDE1_MASK |
-				SDMA1_CLK_CTRL__SOFT_OVERRIDE0_MASK;
-
-		if (data != temp)
-			WREG32(mmSDMA1_CLK_CTRL, data);
+			if (data != temp)
+				WREG32(mmSDMA0_CLK_CTRL + sdma_offsets[i], data);
+		}
 	}
 }
 
-static void fiji_update_sdma_medium_grain_light_sleep(
+static void sdma_v3_0_update_sdma_medium_grain_light_sleep(
 		struct amdgpu_device *adev,
 		bool enable)
 {
 	uint32_t temp, data;
+	int i;
 
-	if (enable) {
-		temp = data = RREG32(mmSDMA0_POWER_CNTL);
-		data |= SDMA0_POWER_CNTL__MEM_POWER_OVERRIDE_MASK;
-
-		if (temp != data)
-			WREG32(mmSDMA0_POWER_CNTL, data);
-
-		temp = data = RREG32(mmSDMA1_POWER_CNTL);
-		data |= SDMA1_POWER_CNTL__MEM_POWER_OVERRIDE_MASK;
+	if (enable && (adev->cg_flags & AMD_CG_SUPPORT_SDMA_LS)) {
+		for (i = 0; i < adev->sdma.num_instances; i++) {
+			temp = data = RREG32(mmSDMA0_POWER_CNTL + sdma_offsets[i]);
+			data |= SDMA0_POWER_CNTL__MEM_POWER_OVERRIDE_MASK;
 
-		if (temp != data)
-			WREG32(mmSDMA1_POWER_CNTL, data);
+			if (temp != data)
+				WREG32(mmSDMA0_POWER_CNTL + sdma_offsets[i], data);
+		}
 	} else {
-		temp = data = RREG32(mmSDMA0_POWER_CNTL);
-		data &= ~SDMA0_POWER_CNTL__MEM_POWER_OVERRIDE_MASK;
-
-		if (temp != data)
-			WREG32(mmSDMA0_POWER_CNTL, data);
-
-		temp = data = RREG32(mmSDMA1_POWER_CNTL);
-		data &= ~SDMA1_POWER_CNTL__MEM_POWER_OVERRIDE_MASK;
+		for (i = 0; i < adev->sdma.num_instances; i++) {
+			temp = data = RREG32(mmSDMA0_POWER_CNTL + sdma_offsets[i]);
+			data &= ~SDMA0_POWER_CNTL__MEM_POWER_OVERRIDE_MASK;
 
-		if (temp != data)
-			WREG32(mmSDMA1_POWER_CNTL, data);
+			if (temp != data)
+				WREG32(mmSDMA0_POWER_CNTL + sdma_offsets[i], data);
+		}
 	}
 }
 
@@ -1527,9 +1534,11 @@ static int sdma_v3_0_set_clockgating_sta
 
 	switch (adev->asic_type) {
 	case CHIP_FIJI:
-		fiji_update_sdma_medium_grain_clock_gating(adev,
+	case CHIP_CARRIZO:
+	case CHIP_STONEY:
+		sdma_v3_0_update_sdma_medium_grain_clock_gating(adev,
 				state == AMD_CG_STATE_GATE ? true : false);
-		fiji_update_sdma_medium_grain_light_sleep(adev,
+		sdma_v3_0_update_sdma_medium_grain_light_sleep(adev,
 				state == AMD_CG_STATE_GATE ? true : false);
 		break;
 	default:
@@ -1545,6 +1554,7 @@ static int sdma_v3_0_set_powergating_sta
 }
 
 const struct amd_ip_funcs sdma_v3_0_ip_funcs = {
+	.name = "sdma_v3_0",
 	.early_init = sdma_v3_0_early_init,
 	.late_init = NULL,
 	.sw_init = sdma_v3_0_sw_init,
@@ -1556,7 +1566,6 @@ const struct amd_ip_funcs sdma_v3_0_ip_f
 	.is_idle = sdma_v3_0_is_idle,
 	.wait_for_idle = sdma_v3_0_wait_for_idle,
 	.soft_reset = sdma_v3_0_soft_reset,
-	.print_status = sdma_v3_0_print_status,
 	.set_clockgating_state = sdma_v3_0_set_clockgating_state,
 	.set_powergating_state = sdma_v3_0_set_powergating_state,
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/smu_ucode_xfer_vi.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/smu_ucode_xfer_vi.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/smu_ucode_xfer_vi.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/smu_ucode_xfer_vi.h	2016-07-24 15:23:50.000000000 -0400
@@ -44,6 +44,7 @@
 #define UCODE_ID_IH_REG_RESTORE   11
 #define UCODE_ID_VBIOS            12
 #define UCODE_ID_MISC_METADATA    13
+#define UCODE_ID_SMU_SK		      14
 #define UCODE_ID_RLC_SCRATCH      32
 #define UCODE_ID_RLC_SRM_ARAM     33
 #define UCODE_ID_RLC_SRM_DRAM     34
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/tonga_dpm.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/tonga_dpm.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/tonga_dpm.c	2016-05-15 19:21:04.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/tonga_dpm.c	2016-07-24 18:17:32.000000000 -0400
@@ -71,6 +71,11 @@ static int tonga_dpm_sw_init(void *handl
 
 static int tonga_dpm_sw_fini(void *handle)
 {
+	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+	release_firmware(adev->pm.fw);
+	adev->pm.fw = NULL;
+
 	return 0;
 }
 
@@ -143,6 +148,7 @@ static int tonga_dpm_set_powergating_sta
 }
 
 const struct amd_ip_funcs tonga_dpm_ip_funcs = {
+	.name = "tonga_dpm",
 	.early_init = tonga_dpm_early_init,
 	.late_init = NULL,
 	.sw_init = tonga_dpm_sw_init,
@@ -154,7 +160,6 @@ const struct amd_ip_funcs tonga_dpm_ip_f
 	.is_idle = NULL,
 	.wait_for_idle = NULL,
 	.soft_reset = NULL,
-	.print_status = NULL,
 	.set_clockgating_state = tonga_dpm_set_clockgating_state,
 	.set_powergating_state = tonga_dpm_set_powergating_state,
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/tonga_ih.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/tonga_ih.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/tonga_ih.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/tonga_ih.c	2016-07-24 15:23:50.000000000 -0400
@@ -99,7 +99,6 @@ static void tonga_ih_disable_interrupts(
  */
 static int tonga_ih_irq_init(struct amdgpu_device *adev)
 {
-	int ret = 0;
 	int rb_bufsz;
 	u32 interrupt_cntl, ih_rb_cntl, ih_doorbell_rtpr;
 	u64 wptr_off;
@@ -165,7 +164,7 @@ static int tonga_ih_irq_init(struct amdg
 	/* enable interrupts */
 	tonga_ih_enable_interrupts(adev);
 
-	return ret;
+	return 0;
 }
 
 /**
@@ -374,35 +373,6 @@ static int tonga_ih_wait_for_idle(void *
 	return -ETIMEDOUT;
 }
 
-static void tonga_ih_print_status(void *handle)
-{
-	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-	dev_info(adev->dev, "TONGA IH registers\n");
-	dev_info(adev->dev, "  SRBM_STATUS=0x%08X\n",
-		RREG32(mmSRBM_STATUS));
-	dev_info(adev->dev, "  SRBM_STATUS2=0x%08X\n",
-		RREG32(mmSRBM_STATUS2));
-	dev_info(adev->dev, "  INTERRUPT_CNTL=0x%08X\n",
-		 RREG32(mmINTERRUPT_CNTL));
-	dev_info(adev->dev, "  INTERRUPT_CNTL2=0x%08X\n",
-		 RREG32(mmINTERRUPT_CNTL2));
-	dev_info(adev->dev, "  IH_CNTL=0x%08X\n",
-		 RREG32(mmIH_CNTL));
-	dev_info(adev->dev, "  IH_RB_CNTL=0x%08X\n",
-		 RREG32(mmIH_RB_CNTL));
-	dev_info(adev->dev, "  IH_RB_BASE=0x%08X\n",
-		 RREG32(mmIH_RB_BASE));
-	dev_info(adev->dev, "  IH_RB_WPTR_ADDR_LO=0x%08X\n",
-		 RREG32(mmIH_RB_WPTR_ADDR_LO));
-	dev_info(adev->dev, "  IH_RB_WPTR_ADDR_HI=0x%08X\n",
-		 RREG32(mmIH_RB_WPTR_ADDR_HI));
-	dev_info(adev->dev, "  IH_RB_RPTR=0x%08X\n",
-		 RREG32(mmIH_RB_RPTR));
-	dev_info(adev->dev, "  IH_RB_WPTR=0x%08X\n",
-		 RREG32(mmIH_RB_WPTR));
-}
-
 static int tonga_ih_soft_reset(void *handle)
 {
 	u32 srbm_soft_reset = 0;
@@ -414,8 +384,6 @@ static int tonga_ih_soft_reset(void *han
 						SOFT_RESET_IH, 1);
 
 	if (srbm_soft_reset) {
-		tonga_ih_print_status(adev);
-
 		tmp = RREG32(mmSRBM_SOFT_RESET);
 		tmp |= srbm_soft_reset;
 		dev_info(adev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp);
@@ -430,8 +398,6 @@ static int tonga_ih_soft_reset(void *han
 
 		/* Wait a little for things to settle down */
 		udelay(50);
-
-		tonga_ih_print_status(adev);
 	}
 
 	return 0;
@@ -450,6 +416,7 @@ static int tonga_ih_set_powergating_stat
 }
 
 const struct amd_ip_funcs tonga_ih_ip_funcs = {
+	.name = "tonga_ih",
 	.early_init = tonga_ih_early_init,
 	.late_init = NULL,
 	.sw_init = tonga_ih_sw_init,
@@ -461,7 +428,6 @@ const struct amd_ip_funcs tonga_ih_ip_fu
 	.is_idle = tonga_ih_is_idle,
 	.wait_for_idle = tonga_ih_wait_for_idle,
 	.soft_reset = tonga_ih_soft_reset,
-	.print_status = tonga_ih_print_status,
 	.set_clockgating_state = tonga_ih_set_clockgating_state,
 	.set_powergating_state = tonga_ih_set_powergating_state,
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c	2016-07-24 15:23:50.000000000 -0400
@@ -114,7 +114,7 @@ static int uvd_v4_2_sw_init(void *handle
 
 	ring = &adev->uvd.ring;
 	sprintf(ring->name, "uvd");
-	r = amdgpu_ring_init(adev, ring, 4096, CP_PACKET2, 0xf,
+	r = amdgpu_ring_init(adev, ring, 512, CP_PACKET2, 0xf,
 			     &adev->uvd.irq, 0, AMDGPU_RING_TYPE_UVD);
 
 	return r;
@@ -489,7 +489,8 @@ static int uvd_v4_2_ring_test_ring(struc
  * Write ring commands to execute the indirect buffer
  */
 static void uvd_v4_2_ring_emit_ib(struct amdgpu_ring *ring,
-				  struct amdgpu_ib *ib)
+				  struct amdgpu_ib *ib,
+				  unsigned vm_id, bool ctx_switch)
 {
 	amdgpu_ring_write(ring, PACKET0(mmUVD_RBC_IB_BASE, 0));
 	amdgpu_ring_write(ring, ib->gpu_addr);
@@ -559,12 +560,13 @@ static void uvd_v4_2_mc_resume(struct am
 	WREG32(mmUVD_VCPU_CACHE_SIZE0, size);
 
 	addr += size;
-	size = AMDGPU_UVD_STACK_SIZE >> 3;
+	size = AMDGPU_UVD_HEAP_SIZE >> 3;
 	WREG32(mmUVD_VCPU_CACHE_OFFSET1, addr);
 	WREG32(mmUVD_VCPU_CACHE_SIZE1, size);
 
 	addr += size;
-	size = AMDGPU_UVD_HEAP_SIZE >> 3;
+	size = (AMDGPU_UVD_STACK_SIZE +
+	       (AMDGPU_UVD_SESSION_SIZE * adev->uvd.max_handles)) >> 3;
 	WREG32(mmUVD_VCPU_CACHE_OFFSET2, addr);
 	WREG32(mmUVD_VCPU_CACHE_SIZE2, size);
 
@@ -679,117 +681,6 @@ static int uvd_v4_2_soft_reset(void *han
 	return uvd_v4_2_start(adev);
 }
 
-static void uvd_v4_2_print_status(void *handle)
-{
-	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-	dev_info(adev->dev, "UVD 4.2 registers\n");
-	dev_info(adev->dev, "  UVD_SEMA_ADDR_LOW=0x%08X\n",
-		 RREG32(mmUVD_SEMA_ADDR_LOW));
-	dev_info(adev->dev, "  UVD_SEMA_ADDR_HIGH=0x%08X\n",
-		 RREG32(mmUVD_SEMA_ADDR_HIGH));
-	dev_info(adev->dev, "  UVD_SEMA_CMD=0x%08X\n",
-		 RREG32(mmUVD_SEMA_CMD));
-	dev_info(adev->dev, "  UVD_GPCOM_VCPU_CMD=0x%08X\n",
-		 RREG32(mmUVD_GPCOM_VCPU_CMD));
-	dev_info(adev->dev, "  UVD_GPCOM_VCPU_DATA0=0x%08X\n",
-		 RREG32(mmUVD_GPCOM_VCPU_DATA0));
-	dev_info(adev->dev, "  UVD_GPCOM_VCPU_DATA1=0x%08X\n",
-		 RREG32(mmUVD_GPCOM_VCPU_DATA1));
-	dev_info(adev->dev, "  UVD_ENGINE_CNTL=0x%08X\n",
-		 RREG32(mmUVD_ENGINE_CNTL));
-	dev_info(adev->dev, "  UVD_UDEC_ADDR_CONFIG=0x%08X\n",
-		 RREG32(mmUVD_UDEC_ADDR_CONFIG));
-	dev_info(adev->dev, "  UVD_UDEC_DB_ADDR_CONFIG=0x%08X\n",
-		 RREG32(mmUVD_UDEC_DB_ADDR_CONFIG));
-	dev_info(adev->dev, "  UVD_UDEC_DBW_ADDR_CONFIG=0x%08X\n",
-		 RREG32(mmUVD_UDEC_DBW_ADDR_CONFIG));
-	dev_info(adev->dev, "  UVD_SEMA_CNTL=0x%08X\n",
-		 RREG32(mmUVD_SEMA_CNTL));
-	dev_info(adev->dev, "  UVD_LMI_EXT40_ADDR=0x%08X\n",
-		 RREG32(mmUVD_LMI_EXT40_ADDR));
-	dev_info(adev->dev, "  UVD_CTX_INDEX=0x%08X\n",
-		 RREG32(mmUVD_CTX_INDEX));
-	dev_info(adev->dev, "  UVD_CTX_DATA=0x%08X\n",
-		 RREG32(mmUVD_CTX_DATA));
-	dev_info(adev->dev, "  UVD_CGC_GATE=0x%08X\n",
-		 RREG32(mmUVD_CGC_GATE));
-	dev_info(adev->dev, "  UVD_CGC_CTRL=0x%08X\n",
-		 RREG32(mmUVD_CGC_CTRL));
-	dev_info(adev->dev, "  UVD_LMI_CTRL2=0x%08X\n",
-		 RREG32(mmUVD_LMI_CTRL2));
-	dev_info(adev->dev, "  UVD_MASTINT_EN=0x%08X\n",
-		 RREG32(mmUVD_MASTINT_EN));
-	dev_info(adev->dev, "  UVD_LMI_ADDR_EXT=0x%08X\n",
-		 RREG32(mmUVD_LMI_ADDR_EXT));
-	dev_info(adev->dev, "  UVD_LMI_CTRL=0x%08X\n",
-		 RREG32(mmUVD_LMI_CTRL));
-	dev_info(adev->dev, "  UVD_LMI_SWAP_CNTL=0x%08X\n",
-		 RREG32(mmUVD_LMI_SWAP_CNTL));
-	dev_info(adev->dev, "  UVD_MP_SWAP_CNTL=0x%08X\n",
-		 RREG32(mmUVD_MP_SWAP_CNTL));
-	dev_info(adev->dev, "  UVD_MPC_SET_MUXA0=0x%08X\n",
-		 RREG32(mmUVD_MPC_SET_MUXA0));
-	dev_info(adev->dev, "  UVD_MPC_SET_MUXA1=0x%08X\n",
-		 RREG32(mmUVD_MPC_SET_MUXA1));
-	dev_info(adev->dev, "  UVD_MPC_SET_MUXB0=0x%08X\n",
-		 RREG32(mmUVD_MPC_SET_MUXB0));
-	dev_info(adev->dev, "  UVD_MPC_SET_MUXB1=0x%08X\n",
-		 RREG32(mmUVD_MPC_SET_MUXB1));
-	dev_info(adev->dev, "  UVD_MPC_SET_MUX=0x%08X\n",
-		 RREG32(mmUVD_MPC_SET_MUX));
-	dev_info(adev->dev, "  UVD_MPC_SET_ALU=0x%08X\n",
-		 RREG32(mmUVD_MPC_SET_ALU));
-	dev_info(adev->dev, "  UVD_VCPU_CACHE_OFFSET0=0x%08X\n",
-		 RREG32(mmUVD_VCPU_CACHE_OFFSET0));
-	dev_info(adev->dev, "  UVD_VCPU_CACHE_SIZE0=0x%08X\n",
-		 RREG32(mmUVD_VCPU_CACHE_SIZE0));
-	dev_info(adev->dev, "  UVD_VCPU_CACHE_OFFSET1=0x%08X\n",
-		 RREG32(mmUVD_VCPU_CACHE_OFFSET1));
-	dev_info(adev->dev, "  UVD_VCPU_CACHE_SIZE1=0x%08X\n",
-		 RREG32(mmUVD_VCPU_CACHE_SIZE1));
-	dev_info(adev->dev, "  UVD_VCPU_CACHE_OFFSET2=0x%08X\n",
-		 RREG32(mmUVD_VCPU_CACHE_OFFSET2));
-	dev_info(adev->dev, "  UVD_VCPU_CACHE_SIZE2=0x%08X\n",
-		 RREG32(mmUVD_VCPU_CACHE_SIZE2));
-	dev_info(adev->dev, "  UVD_VCPU_CNTL=0x%08X\n",
-		 RREG32(mmUVD_VCPU_CNTL));
-	dev_info(adev->dev, "  UVD_SOFT_RESET=0x%08X\n",
-		 RREG32(mmUVD_SOFT_RESET));
-	dev_info(adev->dev, "  UVD_RBC_IB_BASE=0x%08X\n",
-		 RREG32(mmUVD_RBC_IB_BASE));
-	dev_info(adev->dev, "  UVD_RBC_IB_SIZE=0x%08X\n",
-		 RREG32(mmUVD_RBC_IB_SIZE));
-	dev_info(adev->dev, "  UVD_RBC_RB_BASE=0x%08X\n",
-		 RREG32(mmUVD_RBC_RB_BASE));
-	dev_info(adev->dev, "  UVD_RBC_RB_RPTR=0x%08X\n",
-		 RREG32(mmUVD_RBC_RB_RPTR));
-	dev_info(adev->dev, "  UVD_RBC_RB_WPTR=0x%08X\n",
-		 RREG32(mmUVD_RBC_RB_WPTR));
-	dev_info(adev->dev, "  UVD_RBC_RB_WPTR_CNTL=0x%08X\n",
-		 RREG32(mmUVD_RBC_RB_WPTR_CNTL));
-	dev_info(adev->dev, "  UVD_RBC_RB_CNTL=0x%08X\n",
-		 RREG32(mmUVD_RBC_RB_CNTL));
-	dev_info(adev->dev, "  UVD_STATUS=0x%08X\n",
-		 RREG32(mmUVD_STATUS));
-	dev_info(adev->dev, "  UVD_SEMA_TIMEOUT_STATUS=0x%08X\n",
-		 RREG32(mmUVD_SEMA_TIMEOUT_STATUS));
-	dev_info(adev->dev, "  UVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL=0x%08X\n",
-		 RREG32(mmUVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL));
-	dev_info(adev->dev, "  UVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL=0x%08X\n",
-		 RREG32(mmUVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL));
-	dev_info(adev->dev, "  UVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL=0x%08X\n",
-		 RREG32(mmUVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL));
-	dev_info(adev->dev, "  UVD_CONTEXT_ID=0x%08X\n",
-		 RREG32(mmUVD_CONTEXT_ID));
-	dev_info(adev->dev, "  UVD_UDEC_ADDR_CONFIG=0x%08X\n",
-		 RREG32(mmUVD_UDEC_ADDR_CONFIG));
-	dev_info(adev->dev, "  UVD_UDEC_DB_ADDR_CONFIG=0x%08X\n",
-		 RREG32(mmUVD_UDEC_DB_ADDR_CONFIG));
-	dev_info(adev->dev, "  UVD_UDEC_DBW_ADDR_CONFIG=0x%08X\n",
-		 RREG32(mmUVD_UDEC_DBW_ADDR_CONFIG));
-
-}
-
 static int uvd_v4_2_set_interrupt_state(struct amdgpu_device *adev,
 					struct amdgpu_irq_src *source,
 					unsigned type,
@@ -849,6 +740,7 @@ static int uvd_v4_2_set_powergating_stat
 }
 
 const struct amd_ip_funcs uvd_v4_2_ip_funcs = {
+	.name = "uvd_v4_2",
 	.early_init = uvd_v4_2_early_init,
 	.late_init = NULL,
 	.sw_init = uvd_v4_2_sw_init,
@@ -860,7 +752,6 @@ const struct amd_ip_funcs uvd_v4_2_ip_fu
 	.is_idle = uvd_v4_2_is_idle,
 	.wait_for_idle = uvd_v4_2_wait_for_idle,
 	.soft_reset = uvd_v4_2_soft_reset,
-	.print_status = uvd_v4_2_print_status,
 	.set_clockgating_state = uvd_v4_2_set_clockgating_state,
 	.set_powergating_state = uvd_v4_2_set_powergating_state,
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c	2016-07-24 15:23:50.000000000 -0400
@@ -31,6 +31,7 @@
 #include "uvd/uvd_5_0_sh_mask.h"
 #include "oss/oss_2_0_d.h"
 #include "oss/oss_2_0_sh_mask.h"
+#include "vi.h"
 
 static void uvd_v5_0_set_ring_funcs(struct amdgpu_device *adev);
 static void uvd_v5_0_set_irq_funcs(struct amdgpu_device *adev);
@@ -110,7 +111,7 @@ static int uvd_v5_0_sw_init(void *handle
 
 	ring = &adev->uvd.ring;
 	sprintf(ring->name, "uvd");
-	r = amdgpu_ring_init(adev, ring, 4096, CP_PACKET2, 0xf,
+	r = amdgpu_ring_init(adev, ring, 512, CP_PACKET2, 0xf,
 			     &adev->uvd.irq, 0, AMDGPU_RING_TYPE_UVD);
 
 	return r;
@@ -271,12 +272,13 @@ static void uvd_v5_0_mc_resume(struct am
 	WREG32(mmUVD_VCPU_CACHE_SIZE0, size);
 
 	offset += size;
-	size = AMDGPU_UVD_STACK_SIZE;
+	size = AMDGPU_UVD_HEAP_SIZE;
 	WREG32(mmUVD_VCPU_CACHE_OFFSET1, offset >> 3);
 	WREG32(mmUVD_VCPU_CACHE_SIZE1, size);
 
 	offset += size;
-	size = AMDGPU_UVD_HEAP_SIZE;
+	size = AMDGPU_UVD_STACK_SIZE +
+	       (AMDGPU_UVD_SESSION_SIZE * adev->uvd.max_handles);
 	WREG32(mmUVD_VCPU_CACHE_OFFSET2, offset >> 3);
 	WREG32(mmUVD_VCPU_CACHE_SIZE2, size);
 
@@ -537,7 +539,8 @@ static int uvd_v5_0_ring_test_ring(struc
  * Write ring commands to execute the indirect buffer
  */
 static void uvd_v5_0_ring_emit_ib(struct amdgpu_ring *ring,
-				  struct amdgpu_ib *ib)
+				  struct amdgpu_ib *ib,
+				  unsigned vm_id, bool ctx_switch)
 {
 	amdgpu_ring_write(ring, PACKET0(mmUVD_LMI_RBC_IB_64BIT_BAR_LOW, 0));
 	amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr));
@@ -622,120 +625,6 @@ static int uvd_v5_0_soft_reset(void *han
 	return uvd_v5_0_start(adev);
 }
 
-static void uvd_v5_0_print_status(void *handle)
-{
-	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-	dev_info(adev->dev, "UVD 5.0 registers\n");
-	dev_info(adev->dev, "  UVD_SEMA_ADDR_LOW=0x%08X\n",
-		 RREG32(mmUVD_SEMA_ADDR_LOW));
-	dev_info(adev->dev, "  UVD_SEMA_ADDR_HIGH=0x%08X\n",
-		 RREG32(mmUVD_SEMA_ADDR_HIGH));
-	dev_info(adev->dev, "  UVD_SEMA_CMD=0x%08X\n",
-		 RREG32(mmUVD_SEMA_CMD));
-	dev_info(adev->dev, "  UVD_GPCOM_VCPU_CMD=0x%08X\n",
-		 RREG32(mmUVD_GPCOM_VCPU_CMD));
-	dev_info(adev->dev, "  UVD_GPCOM_VCPU_DATA0=0x%08X\n",
-		 RREG32(mmUVD_GPCOM_VCPU_DATA0));
-	dev_info(adev->dev, "  UVD_GPCOM_VCPU_DATA1=0x%08X\n",
-		 RREG32(mmUVD_GPCOM_VCPU_DATA1));
-	dev_info(adev->dev, "  UVD_ENGINE_CNTL=0x%08X\n",
-		 RREG32(mmUVD_ENGINE_CNTL));
-	dev_info(adev->dev, "  UVD_UDEC_ADDR_CONFIG=0x%08X\n",
-		 RREG32(mmUVD_UDEC_ADDR_CONFIG));
-	dev_info(adev->dev, "  UVD_UDEC_DB_ADDR_CONFIG=0x%08X\n",
-		 RREG32(mmUVD_UDEC_DB_ADDR_CONFIG));
-	dev_info(adev->dev, "  UVD_UDEC_DBW_ADDR_CONFIG=0x%08X\n",
-		 RREG32(mmUVD_UDEC_DBW_ADDR_CONFIG));
-	dev_info(adev->dev, "  UVD_SEMA_CNTL=0x%08X\n",
-		 RREG32(mmUVD_SEMA_CNTL));
-	dev_info(adev->dev, "  UVD_LMI_EXT40_ADDR=0x%08X\n",
-		 RREG32(mmUVD_LMI_EXT40_ADDR));
-	dev_info(adev->dev, "  UVD_CTX_INDEX=0x%08X\n",
-		 RREG32(mmUVD_CTX_INDEX));
-	dev_info(adev->dev, "  UVD_CTX_DATA=0x%08X\n",
-		 RREG32(mmUVD_CTX_DATA));
-	dev_info(adev->dev, "  UVD_CGC_GATE=0x%08X\n",
-		 RREG32(mmUVD_CGC_GATE));
-	dev_info(adev->dev, "  UVD_CGC_CTRL=0x%08X\n",
-		 RREG32(mmUVD_CGC_CTRL));
-	dev_info(adev->dev, "  UVD_LMI_CTRL2=0x%08X\n",
-		 RREG32(mmUVD_LMI_CTRL2));
-	dev_info(adev->dev, "  UVD_MASTINT_EN=0x%08X\n",
-		 RREG32(mmUVD_MASTINT_EN));
-	dev_info(adev->dev, "  UVD_LMI_ADDR_EXT=0x%08X\n",
-		 RREG32(mmUVD_LMI_ADDR_EXT));
-	dev_info(adev->dev, "  UVD_LMI_CTRL=0x%08X\n",
-		 RREG32(mmUVD_LMI_CTRL));
-	dev_info(adev->dev, "  UVD_LMI_SWAP_CNTL=0x%08X\n",
-		 RREG32(mmUVD_LMI_SWAP_CNTL));
-	dev_info(adev->dev, "  UVD_MP_SWAP_CNTL=0x%08X\n",
-		 RREG32(mmUVD_MP_SWAP_CNTL));
-	dev_info(adev->dev, "  UVD_MPC_SET_MUXA0=0x%08X\n",
-		 RREG32(mmUVD_MPC_SET_MUXA0));
-	dev_info(adev->dev, "  UVD_MPC_SET_MUXA1=0x%08X\n",
-		 RREG32(mmUVD_MPC_SET_MUXA1));
-	dev_info(adev->dev, "  UVD_MPC_SET_MUXB0=0x%08X\n",
-		 RREG32(mmUVD_MPC_SET_MUXB0));
-	dev_info(adev->dev, "  UVD_MPC_SET_MUXB1=0x%08X\n",
-		 RREG32(mmUVD_MPC_SET_MUXB1));
-	dev_info(adev->dev, "  UVD_MPC_SET_MUX=0x%08X\n",
-		 RREG32(mmUVD_MPC_SET_MUX));
-	dev_info(adev->dev, "  UVD_MPC_SET_ALU=0x%08X\n",
-		 RREG32(mmUVD_MPC_SET_ALU));
-	dev_info(adev->dev, "  UVD_VCPU_CACHE_OFFSET0=0x%08X\n",
-		 RREG32(mmUVD_VCPU_CACHE_OFFSET0));
-	dev_info(adev->dev, "  UVD_VCPU_CACHE_SIZE0=0x%08X\n",
-		 RREG32(mmUVD_VCPU_CACHE_SIZE0));
-	dev_info(adev->dev, "  UVD_VCPU_CACHE_OFFSET1=0x%08X\n",
-		 RREG32(mmUVD_VCPU_CACHE_OFFSET1));
-	dev_info(adev->dev, "  UVD_VCPU_CACHE_SIZE1=0x%08X\n",
-		 RREG32(mmUVD_VCPU_CACHE_SIZE1));
-	dev_info(adev->dev, "  UVD_VCPU_CACHE_OFFSET2=0x%08X\n",
-		 RREG32(mmUVD_VCPU_CACHE_OFFSET2));
-	dev_info(adev->dev, "  UVD_VCPU_CACHE_SIZE2=0x%08X\n",
-		 RREG32(mmUVD_VCPU_CACHE_SIZE2));
-	dev_info(adev->dev, "  UVD_VCPU_CNTL=0x%08X\n",
-		 RREG32(mmUVD_VCPU_CNTL));
-	dev_info(adev->dev, "  UVD_SOFT_RESET=0x%08X\n",
-		 RREG32(mmUVD_SOFT_RESET));
-	dev_info(adev->dev, "  UVD_LMI_RBC_IB_64BIT_BAR_LOW=0x%08X\n",
-		 RREG32(mmUVD_LMI_RBC_IB_64BIT_BAR_LOW));
-	dev_info(adev->dev, "  UVD_LMI_RBC_IB_64BIT_BAR_HIGH=0x%08X\n",
-		 RREG32(mmUVD_LMI_RBC_IB_64BIT_BAR_HIGH));
-	dev_info(adev->dev, "  UVD_RBC_IB_SIZE=0x%08X\n",
-		 RREG32(mmUVD_RBC_IB_SIZE));
-	dev_info(adev->dev, "  UVD_LMI_RBC_RB_64BIT_BAR_LOW=0x%08X\n",
-		 RREG32(mmUVD_LMI_RBC_RB_64BIT_BAR_LOW));
-	dev_info(adev->dev, "  UVD_LMI_RBC_RB_64BIT_BAR_HIGH=0x%08X\n",
-		 RREG32(mmUVD_LMI_RBC_RB_64BIT_BAR_HIGH));
-	dev_info(adev->dev, "  UVD_RBC_RB_RPTR=0x%08X\n",
-		 RREG32(mmUVD_RBC_RB_RPTR));
-	dev_info(adev->dev, "  UVD_RBC_RB_WPTR=0x%08X\n",
-		 RREG32(mmUVD_RBC_RB_WPTR));
-	dev_info(adev->dev, "  UVD_RBC_RB_WPTR_CNTL=0x%08X\n",
-		 RREG32(mmUVD_RBC_RB_WPTR_CNTL));
-	dev_info(adev->dev, "  UVD_RBC_RB_CNTL=0x%08X\n",
-		 RREG32(mmUVD_RBC_RB_CNTL));
-	dev_info(adev->dev, "  UVD_STATUS=0x%08X\n",
-		 RREG32(mmUVD_STATUS));
-	dev_info(adev->dev, "  UVD_SEMA_TIMEOUT_STATUS=0x%08X\n",
-		 RREG32(mmUVD_SEMA_TIMEOUT_STATUS));
-	dev_info(adev->dev, "  UVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL=0x%08X\n",
-		 RREG32(mmUVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL));
-	dev_info(adev->dev, "  UVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL=0x%08X\n",
-		 RREG32(mmUVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL));
-	dev_info(adev->dev, "  UVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL=0x%08X\n",
-		 RREG32(mmUVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL));
-	dev_info(adev->dev, "  UVD_CONTEXT_ID=0x%08X\n",
-		 RREG32(mmUVD_CONTEXT_ID));
-	dev_info(adev->dev, "  UVD_UDEC_ADDR_CONFIG=0x%08X\n",
-		 RREG32(mmUVD_UDEC_ADDR_CONFIG));
-	dev_info(adev->dev, "  UVD_UDEC_DB_ADDR_CONFIG=0x%08X\n",
-		 RREG32(mmUVD_UDEC_DB_ADDR_CONFIG));
-	dev_info(adev->dev, "  UVD_UDEC_DBW_ADDR_CONFIG=0x%08X\n",
-		 RREG32(mmUVD_UDEC_DBW_ADDR_CONFIG));
-}
-
 static int uvd_v5_0_set_interrupt_state(struct amdgpu_device *adev,
 					struct amdgpu_irq_src *source,
 					unsigned type,
@@ -754,14 +643,128 @@ static int uvd_v5_0_process_interrupt(st
 	return 0;
 }
 
+static void uvd_v5_0_set_sw_clock_gating(struct amdgpu_device *adev)
+{
+	uint32_t data, data1, data2, suvd_flags;
+
+	data = RREG32(mmUVD_CGC_CTRL);
+	data1 = RREG32(mmUVD_SUVD_CGC_GATE);
+	data2 = RREG32(mmUVD_SUVD_CGC_CTRL);
+
+	data &= ~(UVD_CGC_CTRL__CLK_OFF_DELAY_MASK |
+		  UVD_CGC_CTRL__CLK_GATE_DLY_TIMER_MASK);
+
+	suvd_flags = UVD_SUVD_CGC_GATE__SRE_MASK |
+		     UVD_SUVD_CGC_GATE__SIT_MASK |
+		     UVD_SUVD_CGC_GATE__SMP_MASK |
+		     UVD_SUVD_CGC_GATE__SCM_MASK |
+		     UVD_SUVD_CGC_GATE__SDB_MASK;
+
+	data |= UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK |
+		(1 << REG_FIELD_SHIFT(UVD_CGC_CTRL, CLK_GATE_DLY_TIMER)) |
+		(4 << REG_FIELD_SHIFT(UVD_CGC_CTRL, CLK_OFF_DELAY));
+
+	data &= ~(UVD_CGC_CTRL__UDEC_RE_MODE_MASK |
+			UVD_CGC_CTRL__UDEC_CM_MODE_MASK |
+			UVD_CGC_CTRL__UDEC_IT_MODE_MASK |
+			UVD_CGC_CTRL__UDEC_DB_MODE_MASK |
+			UVD_CGC_CTRL__UDEC_MP_MODE_MASK |
+			UVD_CGC_CTRL__SYS_MODE_MASK |
+			UVD_CGC_CTRL__UDEC_MODE_MASK |
+			UVD_CGC_CTRL__MPEG2_MODE_MASK |
+			UVD_CGC_CTRL__REGS_MODE_MASK |
+			UVD_CGC_CTRL__RBC_MODE_MASK |
+			UVD_CGC_CTRL__LMI_MC_MODE_MASK |
+			UVD_CGC_CTRL__LMI_UMC_MODE_MASK |
+			UVD_CGC_CTRL__IDCT_MODE_MASK |
+			UVD_CGC_CTRL__MPRD_MODE_MASK |
+			UVD_CGC_CTRL__MPC_MODE_MASK |
+			UVD_CGC_CTRL__LBSI_MODE_MASK |
+			UVD_CGC_CTRL__LRBBM_MODE_MASK |
+			UVD_CGC_CTRL__WCB_MODE_MASK |
+			UVD_CGC_CTRL__VCPU_MODE_MASK |
+			UVD_CGC_CTRL__JPEG_MODE_MASK |
+			UVD_CGC_CTRL__SCPU_MODE_MASK);
+	data2 &= ~(UVD_SUVD_CGC_CTRL__SRE_MODE_MASK |
+			UVD_SUVD_CGC_CTRL__SIT_MODE_MASK |
+			UVD_SUVD_CGC_CTRL__SMP_MODE_MASK |
+			UVD_SUVD_CGC_CTRL__SCM_MODE_MASK |
+			UVD_SUVD_CGC_CTRL__SDB_MODE_MASK);
+	data1 |= suvd_flags;
+
+	WREG32(mmUVD_CGC_CTRL, data);
+	WREG32(mmUVD_CGC_GATE, 0);
+	WREG32(mmUVD_SUVD_CGC_GATE, data1);
+	WREG32(mmUVD_SUVD_CGC_CTRL, data2);
+}
+
+#if 0
+static void uvd_v5_0_set_hw_clock_gating(struct amdgpu_device *adev)
+{
+	uint32_t data, data1, cgc_flags, suvd_flags;
+
+	data = RREG32(mmUVD_CGC_GATE);
+	data1 = RREG32(mmUVD_SUVD_CGC_GATE);
+
+	cgc_flags = UVD_CGC_GATE__SYS_MASK |
+				UVD_CGC_GATE__UDEC_MASK |
+				UVD_CGC_GATE__MPEG2_MASK |
+				UVD_CGC_GATE__RBC_MASK |
+				UVD_CGC_GATE__LMI_MC_MASK |
+				UVD_CGC_GATE__IDCT_MASK |
+				UVD_CGC_GATE__MPRD_MASK |
+				UVD_CGC_GATE__MPC_MASK |
+				UVD_CGC_GATE__LBSI_MASK |
+				UVD_CGC_GATE__LRBBM_MASK |
+				UVD_CGC_GATE__UDEC_RE_MASK |
+				UVD_CGC_GATE__UDEC_CM_MASK |
+				UVD_CGC_GATE__UDEC_IT_MASK |
+				UVD_CGC_GATE__UDEC_DB_MASK |
+				UVD_CGC_GATE__UDEC_MP_MASK |
+				UVD_CGC_GATE__WCB_MASK |
+				UVD_CGC_GATE__VCPU_MASK |
+				UVD_CGC_GATE__SCPU_MASK;
+
+	suvd_flags = UVD_SUVD_CGC_GATE__SRE_MASK |
+				UVD_SUVD_CGC_GATE__SIT_MASK |
+				UVD_SUVD_CGC_GATE__SMP_MASK |
+				UVD_SUVD_CGC_GATE__SCM_MASK |
+				UVD_SUVD_CGC_GATE__SDB_MASK;
+
+	data |= cgc_flags;
+	data1 |= suvd_flags;
+
+	WREG32(mmUVD_CGC_GATE, data);
+	WREG32(mmUVD_SUVD_CGC_GATE, data1);
+}
+#endif
+
 static int uvd_v5_0_set_clockgating_state(void *handle,
 					  enum amd_clockgating_state state)
 {
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+	bool enable = (state == AMD_CG_STATE_GATE) ? true : false;
+	static int curstate = -1;
 
 	if (!(adev->cg_flags & AMD_CG_SUPPORT_UVD_MGCG))
 		return 0;
 
+	if (curstate == state)
+		return 0;
+
+	curstate = state;
+	if (enable) {
+		/* disable HW gating and enable Sw gating */
+		uvd_v5_0_set_sw_clock_gating(adev);
+	} else {
+		/* wait for STATUS to clear */
+		if (uvd_v5_0_wait_for_idle(handle))
+			return -EBUSY;
+
+		/* enable HW gates because UVD is idle */
+/*		uvd_v5_0_set_hw_clock_gating(adev); */
+	}
+
 	return 0;
 }
 
@@ -789,6 +792,7 @@ static int uvd_v5_0_set_powergating_stat
 }
 
 const struct amd_ip_funcs uvd_v5_0_ip_funcs = {
+	.name = "uvd_v5_0",
 	.early_init = uvd_v5_0_early_init,
 	.late_init = NULL,
 	.sw_init = uvd_v5_0_sw_init,
@@ -800,7 +804,6 @@ const struct amd_ip_funcs uvd_v5_0_ip_fu
 	.is_idle = uvd_v5_0_is_idle,
 	.wait_for_idle = uvd_v5_0_wait_for_idle,
 	.soft_reset = uvd_v5_0_soft_reset,
-	.print_status = uvd_v5_0_print_status,
 	.set_clockgating_state = uvd_v5_0_set_clockgating_state,
 	.set_powergating_state = uvd_v5_0_set_powergating_state,
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c	2016-07-24 15:23:50.000000000 -0400
@@ -31,11 +31,15 @@
 #include "uvd/uvd_6_0_sh_mask.h"
 #include "oss/oss_2_0_d.h"
 #include "oss/oss_2_0_sh_mask.h"
+#include "smu/smu_7_1_3_d.h"
+#include "smu/smu_7_1_3_sh_mask.h"
+#include "vi.h"
 
 static void uvd_v6_0_set_ring_funcs(struct amdgpu_device *adev);
 static void uvd_v6_0_set_irq_funcs(struct amdgpu_device *adev);
 static int uvd_v6_0_start(struct amdgpu_device *adev);
 static void uvd_v6_0_stop(struct amdgpu_device *adev);
+static void uvd_v6_0_set_sw_clock_gating(struct amdgpu_device *adev);
 
 /**
  * uvd_v6_0_ring_get_rptr - get read pointer
@@ -110,7 +114,7 @@ static int uvd_v6_0_sw_init(void *handle
 
 	ring = &adev->uvd.ring;
 	sprintf(ring->name, "uvd");
-	r = amdgpu_ring_init(adev, ring, 4096, CP_PACKET2, 0xf,
+	r = amdgpu_ring_init(adev, ring, 512, CP_PACKET2, 0xf,
 			     &adev->uvd.irq, 0, AMDGPU_RING_TYPE_UVD);
 
 	return r;
@@ -270,20 +274,24 @@ static void uvd_v6_0_mc_resume(struct am
 	WREG32(mmUVD_VCPU_CACHE_SIZE0, size);
 
 	offset += size;
-	size = AMDGPU_UVD_STACK_SIZE;
+	size = AMDGPU_UVD_HEAP_SIZE;
 	WREG32(mmUVD_VCPU_CACHE_OFFSET1, offset >> 3);
 	WREG32(mmUVD_VCPU_CACHE_SIZE1, size);
 
 	offset += size;
-	size = AMDGPU_UVD_HEAP_SIZE;
+	size = AMDGPU_UVD_STACK_SIZE +
+	       (AMDGPU_UVD_SESSION_SIZE * adev->uvd.max_handles);
 	WREG32(mmUVD_VCPU_CACHE_OFFSET2, offset >> 3);
 	WREG32(mmUVD_VCPU_CACHE_SIZE2, size);
 
 	WREG32(mmUVD_UDEC_ADDR_CONFIG, adev->gfx.config.gb_addr_config);
 	WREG32(mmUVD_UDEC_DB_ADDR_CONFIG, adev->gfx.config.gb_addr_config);
 	WREG32(mmUVD_UDEC_DBW_ADDR_CONFIG, adev->gfx.config.gb_addr_config);
+
+	WREG32(mmUVD_GP_SCRATCH4, adev->uvd.max_handles);
 }
 
+#if 0
 static void cz_set_uvd_clock_gating_branches(struct amdgpu_device *adev,
 		bool enable)
 {
@@ -360,157 +368,7 @@ static void cz_set_uvd_clock_gating_bran
 	WREG32(mmUVD_CGC_GATE, data);
 	WREG32(mmUVD_SUVD_CGC_GATE, data1);
 }
-
-static void tonga_set_uvd_clock_gating_branches(struct amdgpu_device *adev,
-		bool enable)
-{
-	u32 data, data1;
-
-	data = RREG32(mmUVD_CGC_GATE);
-	data1 = RREG32(mmUVD_SUVD_CGC_GATE);
-	if (enable) {
-		data |= UVD_CGC_GATE__SYS_MASK |
-				UVD_CGC_GATE__UDEC_MASK |
-				UVD_CGC_GATE__MPEG2_MASK |
-				UVD_CGC_GATE__RBC_MASK |
-				UVD_CGC_GATE__LMI_MC_MASK |
-				UVD_CGC_GATE__IDCT_MASK |
-				UVD_CGC_GATE__MPRD_MASK |
-				UVD_CGC_GATE__MPC_MASK |
-				UVD_CGC_GATE__LBSI_MASK |
-				UVD_CGC_GATE__LRBBM_MASK |
-				UVD_CGC_GATE__UDEC_RE_MASK |
-				UVD_CGC_GATE__UDEC_CM_MASK |
-				UVD_CGC_GATE__UDEC_IT_MASK |
-				UVD_CGC_GATE__UDEC_DB_MASK |
-				UVD_CGC_GATE__UDEC_MP_MASK |
-				UVD_CGC_GATE__WCB_MASK |
-				UVD_CGC_GATE__VCPU_MASK |
-				UVD_CGC_GATE__SCPU_MASK;
-		data1 |= UVD_SUVD_CGC_GATE__SRE_MASK |
-				UVD_SUVD_CGC_GATE__SIT_MASK |
-				UVD_SUVD_CGC_GATE__SMP_MASK |
-				UVD_SUVD_CGC_GATE__SCM_MASK |
-				UVD_SUVD_CGC_GATE__SDB_MASK;
-	} else {
-		data &= ~(UVD_CGC_GATE__SYS_MASK |
-				UVD_CGC_GATE__UDEC_MASK |
-				UVD_CGC_GATE__MPEG2_MASK |
-				UVD_CGC_GATE__RBC_MASK |
-				UVD_CGC_GATE__LMI_MC_MASK |
-				UVD_CGC_GATE__LMI_UMC_MASK |
-				UVD_CGC_GATE__IDCT_MASK |
-				UVD_CGC_GATE__MPRD_MASK |
-				UVD_CGC_GATE__MPC_MASK |
-				UVD_CGC_GATE__LBSI_MASK |
-				UVD_CGC_GATE__LRBBM_MASK |
-				UVD_CGC_GATE__UDEC_RE_MASK |
-				UVD_CGC_GATE__UDEC_CM_MASK |
-				UVD_CGC_GATE__UDEC_IT_MASK |
-				UVD_CGC_GATE__UDEC_DB_MASK |
-				UVD_CGC_GATE__UDEC_MP_MASK |
-				UVD_CGC_GATE__WCB_MASK |
-				UVD_CGC_GATE__VCPU_MASK |
-				UVD_CGC_GATE__SCPU_MASK);
-		data1 &= ~(UVD_SUVD_CGC_GATE__SRE_MASK |
-				UVD_SUVD_CGC_GATE__SIT_MASK |
-				UVD_SUVD_CGC_GATE__SMP_MASK |
-				UVD_SUVD_CGC_GATE__SCM_MASK |
-				UVD_SUVD_CGC_GATE__SDB_MASK);
-	}
-	WREG32(mmUVD_CGC_GATE, data);
-	WREG32(mmUVD_SUVD_CGC_GATE, data1);
-}
-
-static void uvd_v6_0_set_uvd_dynamic_clock_mode(struct amdgpu_device *adev,
-		bool swmode)
-{
-	u32 data, data1 = 0, data2;
-
-	/* Always un-gate UVD REGS bit */
-	data = RREG32(mmUVD_CGC_GATE);
-	data &= ~(UVD_CGC_GATE__REGS_MASK);
-	WREG32(mmUVD_CGC_GATE, data);
-
-	data = RREG32(mmUVD_CGC_CTRL);
-	data &= ~(UVD_CGC_CTRL__CLK_OFF_DELAY_MASK |
-			UVD_CGC_CTRL__CLK_GATE_DLY_TIMER_MASK);
-	data |= UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK |
-			1 << REG_FIELD_SHIFT(UVD_CGC_CTRL, CLK_GATE_DLY_TIMER) |
-			4 << REG_FIELD_SHIFT(UVD_CGC_CTRL, CLK_OFF_DELAY);
-
-	data2 = RREG32(mmUVD_SUVD_CGC_CTRL);
-	if (swmode) {
-		data &= ~(UVD_CGC_CTRL__UDEC_RE_MODE_MASK |
-				UVD_CGC_CTRL__UDEC_CM_MODE_MASK |
-				UVD_CGC_CTRL__UDEC_IT_MODE_MASK |
-				UVD_CGC_CTRL__UDEC_DB_MODE_MASK |
-				UVD_CGC_CTRL__UDEC_MP_MODE_MASK |
-				UVD_CGC_CTRL__SYS_MODE_MASK |
-				UVD_CGC_CTRL__UDEC_MODE_MASK |
-				UVD_CGC_CTRL__MPEG2_MODE_MASK |
-				UVD_CGC_CTRL__REGS_MODE_MASK |
-				UVD_CGC_CTRL__RBC_MODE_MASK |
-				UVD_CGC_CTRL__LMI_MC_MODE_MASK |
-				UVD_CGC_CTRL__LMI_UMC_MODE_MASK |
-				UVD_CGC_CTRL__IDCT_MODE_MASK |
-				UVD_CGC_CTRL__MPRD_MODE_MASK |
-				UVD_CGC_CTRL__MPC_MODE_MASK |
-				UVD_CGC_CTRL__LBSI_MODE_MASK |
-				UVD_CGC_CTRL__LRBBM_MODE_MASK |
-				UVD_CGC_CTRL__WCB_MODE_MASK |
-				UVD_CGC_CTRL__VCPU_MODE_MASK |
-				UVD_CGC_CTRL__JPEG_MODE_MASK |
-				UVD_CGC_CTRL__SCPU_MODE_MASK);
-		data1 |= UVD_CGC_CTRL2__DYN_OCLK_RAMP_EN_MASK |
-				UVD_CGC_CTRL2__DYN_RCLK_RAMP_EN_MASK;
-		data1 &= ~UVD_CGC_CTRL2__GATER_DIV_ID_MASK;
-		data1 |= 7 << REG_FIELD_SHIFT(UVD_CGC_CTRL2, GATER_DIV_ID);
-		data2 &= ~(UVD_SUVD_CGC_CTRL__SRE_MODE_MASK |
-				UVD_SUVD_CGC_CTRL__SIT_MODE_MASK |
-				UVD_SUVD_CGC_CTRL__SMP_MODE_MASK |
-				UVD_SUVD_CGC_CTRL__SCM_MODE_MASK |
-				UVD_SUVD_CGC_CTRL__SDB_MODE_MASK);
-	} else {
-		data |= UVD_CGC_CTRL__UDEC_RE_MODE_MASK |
-				UVD_CGC_CTRL__UDEC_CM_MODE_MASK |
-				UVD_CGC_CTRL__UDEC_IT_MODE_MASK |
-				UVD_CGC_CTRL__UDEC_DB_MODE_MASK |
-				UVD_CGC_CTRL__UDEC_MP_MODE_MASK |
-				UVD_CGC_CTRL__SYS_MODE_MASK |
-				UVD_CGC_CTRL__UDEC_MODE_MASK |
-				UVD_CGC_CTRL__MPEG2_MODE_MASK |
-				UVD_CGC_CTRL__REGS_MODE_MASK |
-				UVD_CGC_CTRL__RBC_MODE_MASK |
-				UVD_CGC_CTRL__LMI_MC_MODE_MASK |
-				UVD_CGC_CTRL__LMI_UMC_MODE_MASK |
-				UVD_CGC_CTRL__IDCT_MODE_MASK |
-				UVD_CGC_CTRL__MPRD_MODE_MASK |
-				UVD_CGC_CTRL__MPC_MODE_MASK |
-				UVD_CGC_CTRL__LBSI_MODE_MASK |
-				UVD_CGC_CTRL__LRBBM_MODE_MASK |
-				UVD_CGC_CTRL__WCB_MODE_MASK |
-				UVD_CGC_CTRL__VCPU_MODE_MASK |
-				UVD_CGC_CTRL__SCPU_MODE_MASK;
-		data2 |= UVD_SUVD_CGC_CTRL__SRE_MODE_MASK |
-				UVD_SUVD_CGC_CTRL__SIT_MODE_MASK |
-				UVD_SUVD_CGC_CTRL__SMP_MODE_MASK |
-				UVD_SUVD_CGC_CTRL__SCM_MODE_MASK |
-				UVD_SUVD_CGC_CTRL__SDB_MODE_MASK;
-	}
-	WREG32(mmUVD_CGC_CTRL, data);
-	WREG32(mmUVD_SUVD_CGC_CTRL, data2);
-
-	data = RREG32_UVD_CTX(ixUVD_CGC_CTRL2);
-	data &= ~(REG_FIELD_MASK(UVD_CGC_CTRL2, DYN_OCLK_RAMP_EN) |
-			REG_FIELD_MASK(UVD_CGC_CTRL2, DYN_RCLK_RAMP_EN) |
-			REG_FIELD_MASK(UVD_CGC_CTRL2, GATER_DIV_ID));
-	data1 &= (REG_FIELD_MASK(UVD_CGC_CTRL2, DYN_OCLK_RAMP_EN) |
-			REG_FIELD_MASK(UVD_CGC_CTRL2, DYN_RCLK_RAMP_EN) |
-			REG_FIELD_MASK(UVD_CGC_CTRL2, GATER_DIV_ID));
-	data |= data1;
-	WREG32_UVD_CTX(ixUVD_CGC_CTRL2, data);
-}
+#endif
 
 /**
  * uvd_v6_0_start - start UVD block
@@ -538,11 +396,7 @@ static int uvd_v6_0_start(struct amdgpu_
 
 	/* Set dynamic clock gating in S/W control mode */
 	if (adev->cg_flags & AMD_CG_SUPPORT_UVD_MGCG) {
-		if (adev->flags & AMD_IS_APU)
-			cz_set_uvd_clock_gating_branches(adev, false);
-		else
-			tonga_set_uvd_clock_gating_branches(adev, false);
-		uvd_v6_0_set_uvd_dynamic_clock_mode(adev, true);
+		uvd_v6_0_set_sw_clock_gating(adev);
 	} else {
 		/* disable clock gating */
 		uint32_t data = RREG32(mmUVD_CGC_CTRL);
@@ -777,7 +631,8 @@ static int uvd_v6_0_ring_test_ring(struc
  * Write ring commands to execute the indirect buffer
  */
 static void uvd_v6_0_ring_emit_ib(struct amdgpu_ring *ring,
-				  struct amdgpu_ib *ib)
+				  struct amdgpu_ib *ib,
+				  unsigned vm_id, bool ctx_switch)
 {
 	amdgpu_ring_write(ring, PACKET0(mmUVD_LMI_RBC_IB_64BIT_BAR_LOW, 0));
 	amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr));
@@ -854,112 +709,6 @@ static int uvd_v6_0_soft_reset(void *han
 	return uvd_v6_0_start(adev);
 }
 
-static void uvd_v6_0_print_status(void *handle)
-{
-	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-	dev_info(adev->dev, "UVD 6.0 registers\n");
-	dev_info(adev->dev, "  UVD_SEMA_ADDR_LOW=0x%08X\n",
-		 RREG32(mmUVD_SEMA_ADDR_LOW));
-	dev_info(adev->dev, "  UVD_SEMA_ADDR_HIGH=0x%08X\n",
-		 RREG32(mmUVD_SEMA_ADDR_HIGH));
-	dev_info(adev->dev, "  UVD_SEMA_CMD=0x%08X\n",
-		 RREG32(mmUVD_SEMA_CMD));
-	dev_info(adev->dev, "  UVD_GPCOM_VCPU_CMD=0x%08X\n",
-		 RREG32(mmUVD_GPCOM_VCPU_CMD));
-	dev_info(adev->dev, "  UVD_GPCOM_VCPU_DATA0=0x%08X\n",
-		 RREG32(mmUVD_GPCOM_VCPU_DATA0));
-	dev_info(adev->dev, "  UVD_GPCOM_VCPU_DATA1=0x%08X\n",
-		 RREG32(mmUVD_GPCOM_VCPU_DATA1));
-	dev_info(adev->dev, "  UVD_ENGINE_CNTL=0x%08X\n",
-		 RREG32(mmUVD_ENGINE_CNTL));
-	dev_info(adev->dev, "  UVD_UDEC_ADDR_CONFIG=0x%08X\n",
-		 RREG32(mmUVD_UDEC_ADDR_CONFIG));
-	dev_info(adev->dev, "  UVD_UDEC_DB_ADDR_CONFIG=0x%08X\n",
-		 RREG32(mmUVD_UDEC_DB_ADDR_CONFIG));
-	dev_info(adev->dev, "  UVD_UDEC_DBW_ADDR_CONFIG=0x%08X\n",
-		 RREG32(mmUVD_UDEC_DBW_ADDR_CONFIG));
-	dev_info(adev->dev, "  UVD_SEMA_CNTL=0x%08X\n",
-		 RREG32(mmUVD_SEMA_CNTL));
-	dev_info(adev->dev, "  UVD_LMI_EXT40_ADDR=0x%08X\n",
-		 RREG32(mmUVD_LMI_EXT40_ADDR));
-	dev_info(adev->dev, "  UVD_CTX_INDEX=0x%08X\n",
-		 RREG32(mmUVD_CTX_INDEX));
-	dev_info(adev->dev, "  UVD_CTX_DATA=0x%08X\n",
-		 RREG32(mmUVD_CTX_DATA));
-	dev_info(adev->dev, "  UVD_CGC_GATE=0x%08X\n",
-		 RREG32(mmUVD_CGC_GATE));
-	dev_info(adev->dev, "  UVD_CGC_CTRL=0x%08X\n",
-		 RREG32(mmUVD_CGC_CTRL));
-	dev_info(adev->dev, "  UVD_LMI_CTRL2=0x%08X\n",
-		 RREG32(mmUVD_LMI_CTRL2));
-	dev_info(adev->dev, "  UVD_MASTINT_EN=0x%08X\n",
-		 RREG32(mmUVD_MASTINT_EN));
-	dev_info(adev->dev, "  UVD_LMI_ADDR_EXT=0x%08X\n",
-		 RREG32(mmUVD_LMI_ADDR_EXT));
-	dev_info(adev->dev, "  UVD_LMI_CTRL=0x%08X\n",
-		 RREG32(mmUVD_LMI_CTRL));
-	dev_info(adev->dev, "  UVD_LMI_SWAP_CNTL=0x%08X\n",
-		 RREG32(mmUVD_LMI_SWAP_CNTL));
-	dev_info(adev->dev, "  UVD_MP_SWAP_CNTL=0x%08X\n",
-		 RREG32(mmUVD_MP_SWAP_CNTL));
-	dev_info(adev->dev, "  UVD_MPC_SET_MUXA0=0x%08X\n",
-		 RREG32(mmUVD_MPC_SET_MUXA0));
-	dev_info(adev->dev, "  UVD_MPC_SET_MUXA1=0x%08X\n",
-		 RREG32(mmUVD_MPC_SET_MUXA1));
-	dev_info(adev->dev, "  UVD_MPC_SET_MUXB0=0x%08X\n",
-		 RREG32(mmUVD_MPC_SET_MUXB0));
-	dev_info(adev->dev, "  UVD_MPC_SET_MUXB1=0x%08X\n",
-		 RREG32(mmUVD_MPC_SET_MUXB1));
-	dev_info(adev->dev, "  UVD_MPC_SET_MUX=0x%08X\n",
-		 RREG32(mmUVD_MPC_SET_MUX));
-	dev_info(adev->dev, "  UVD_MPC_SET_ALU=0x%08X\n",
-		 RREG32(mmUVD_MPC_SET_ALU));
-	dev_info(adev->dev, "  UVD_VCPU_CACHE_OFFSET0=0x%08X\n",
-		 RREG32(mmUVD_VCPU_CACHE_OFFSET0));
-	dev_info(adev->dev, "  UVD_VCPU_CACHE_SIZE0=0x%08X\n",
-		 RREG32(mmUVD_VCPU_CACHE_SIZE0));
-	dev_info(adev->dev, "  UVD_VCPU_CACHE_OFFSET1=0x%08X\n",
-		 RREG32(mmUVD_VCPU_CACHE_OFFSET1));
-	dev_info(adev->dev, "  UVD_VCPU_CACHE_SIZE1=0x%08X\n",
-		 RREG32(mmUVD_VCPU_CACHE_SIZE1));
-	dev_info(adev->dev, "  UVD_VCPU_CACHE_OFFSET2=0x%08X\n",
-		 RREG32(mmUVD_VCPU_CACHE_OFFSET2));
-	dev_info(adev->dev, "  UVD_VCPU_CACHE_SIZE2=0x%08X\n",
-		 RREG32(mmUVD_VCPU_CACHE_SIZE2));
-	dev_info(adev->dev, "  UVD_VCPU_CNTL=0x%08X\n",
-		 RREG32(mmUVD_VCPU_CNTL));
-	dev_info(adev->dev, "  UVD_SOFT_RESET=0x%08X\n",
-		 RREG32(mmUVD_SOFT_RESET));
-	dev_info(adev->dev, "  UVD_RBC_IB_SIZE=0x%08X\n",
-		 RREG32(mmUVD_RBC_IB_SIZE));
-	dev_info(adev->dev, "  UVD_RBC_RB_RPTR=0x%08X\n",
-		 RREG32(mmUVD_RBC_RB_RPTR));
-	dev_info(adev->dev, "  UVD_RBC_RB_WPTR=0x%08X\n",
-		 RREG32(mmUVD_RBC_RB_WPTR));
-	dev_info(adev->dev, "  UVD_RBC_RB_WPTR_CNTL=0x%08X\n",
-		 RREG32(mmUVD_RBC_RB_WPTR_CNTL));
-	dev_info(adev->dev, "  UVD_RBC_RB_CNTL=0x%08X\n",
-		 RREG32(mmUVD_RBC_RB_CNTL));
-	dev_info(adev->dev, "  UVD_STATUS=0x%08X\n",
-		 RREG32(mmUVD_STATUS));
-	dev_info(adev->dev, "  UVD_SEMA_TIMEOUT_STATUS=0x%08X\n",
-		 RREG32(mmUVD_SEMA_TIMEOUT_STATUS));
-	dev_info(adev->dev, "  UVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL=0x%08X\n",
-		 RREG32(mmUVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL));
-	dev_info(adev->dev, "  UVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL=0x%08X\n",
-		 RREG32(mmUVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL));
-	dev_info(adev->dev, "  UVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL=0x%08X\n",
-		 RREG32(mmUVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL));
-	dev_info(adev->dev, "  UVD_CONTEXT_ID=0x%08X\n",
-		 RREG32(mmUVD_CONTEXT_ID));
-	dev_info(adev->dev, "  UVD_UDEC_ADDR_CONFIG=0x%08X\n",
-		 RREG32(mmUVD_UDEC_ADDR_CONFIG));
-	dev_info(adev->dev, "  UVD_UDEC_DB_ADDR_CONFIG=0x%08X\n",
-		 RREG32(mmUVD_UDEC_DB_ADDR_CONFIG));
-	dev_info(adev->dev, "  UVD_UDEC_DBW_ADDR_CONFIG=0x%08X\n",
-		 RREG32(mmUVD_UDEC_DBW_ADDR_CONFIG));
-}
-
 static int uvd_v6_0_set_interrupt_state(struct amdgpu_device *adev,
 					struct amdgpu_irq_src *source,
 					unsigned type,
@@ -978,25 +727,146 @@ static int uvd_v6_0_process_interrupt(st
 	return 0;
 }
 
+static void uvd_v6_0_set_sw_clock_gating(struct amdgpu_device *adev)
+{
+	uint32_t data, data1, data2, suvd_flags;
+
+	data = RREG32(mmUVD_CGC_CTRL);
+	data1 = RREG32(mmUVD_SUVD_CGC_GATE);
+	data2 = RREG32(mmUVD_SUVD_CGC_CTRL);
+
+	data &= ~(UVD_CGC_CTRL__CLK_OFF_DELAY_MASK |
+		  UVD_CGC_CTRL__CLK_GATE_DLY_TIMER_MASK);
+
+	suvd_flags = UVD_SUVD_CGC_GATE__SRE_MASK |
+		     UVD_SUVD_CGC_GATE__SIT_MASK |
+		     UVD_SUVD_CGC_GATE__SMP_MASK |
+		     UVD_SUVD_CGC_GATE__SCM_MASK |
+		     UVD_SUVD_CGC_GATE__SDB_MASK;
+
+	data |= UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK |
+		(1 << REG_FIELD_SHIFT(UVD_CGC_CTRL, CLK_GATE_DLY_TIMER)) |
+		(4 << REG_FIELD_SHIFT(UVD_CGC_CTRL, CLK_OFF_DELAY));
+
+	data &= ~(UVD_CGC_CTRL__UDEC_RE_MODE_MASK |
+			UVD_CGC_CTRL__UDEC_CM_MODE_MASK |
+			UVD_CGC_CTRL__UDEC_IT_MODE_MASK |
+			UVD_CGC_CTRL__UDEC_DB_MODE_MASK |
+			UVD_CGC_CTRL__UDEC_MP_MODE_MASK |
+			UVD_CGC_CTRL__SYS_MODE_MASK |
+			UVD_CGC_CTRL__UDEC_MODE_MASK |
+			UVD_CGC_CTRL__MPEG2_MODE_MASK |
+			UVD_CGC_CTRL__REGS_MODE_MASK |
+			UVD_CGC_CTRL__RBC_MODE_MASK |
+			UVD_CGC_CTRL__LMI_MC_MODE_MASK |
+			UVD_CGC_CTRL__LMI_UMC_MODE_MASK |
+			UVD_CGC_CTRL__IDCT_MODE_MASK |
+			UVD_CGC_CTRL__MPRD_MODE_MASK |
+			UVD_CGC_CTRL__MPC_MODE_MASK |
+			UVD_CGC_CTRL__LBSI_MODE_MASK |
+			UVD_CGC_CTRL__LRBBM_MODE_MASK |
+			UVD_CGC_CTRL__WCB_MODE_MASK |
+			UVD_CGC_CTRL__VCPU_MODE_MASK |
+			UVD_CGC_CTRL__JPEG_MODE_MASK |
+			UVD_CGC_CTRL__SCPU_MODE_MASK |
+			UVD_CGC_CTRL__JPEG2_MODE_MASK);
+	data2 &= ~(UVD_SUVD_CGC_CTRL__SRE_MODE_MASK |
+			UVD_SUVD_CGC_CTRL__SIT_MODE_MASK |
+			UVD_SUVD_CGC_CTRL__SMP_MODE_MASK |
+			UVD_SUVD_CGC_CTRL__SCM_MODE_MASK |
+			UVD_SUVD_CGC_CTRL__SDB_MODE_MASK);
+	data1 |= suvd_flags;
+
+	WREG32(mmUVD_CGC_CTRL, data);
+	WREG32(mmUVD_CGC_GATE, 0);
+	WREG32(mmUVD_SUVD_CGC_GATE, data1);
+	WREG32(mmUVD_SUVD_CGC_CTRL, data2);
+}
+
+#if 0
+static void uvd_v6_0_set_hw_clock_gating(struct amdgpu_device *adev)
+{
+	uint32_t data, data1, cgc_flags, suvd_flags;
+
+	data = RREG32(mmUVD_CGC_GATE);
+	data1 = RREG32(mmUVD_SUVD_CGC_GATE);
+
+	cgc_flags = UVD_CGC_GATE__SYS_MASK |
+		UVD_CGC_GATE__UDEC_MASK |
+		UVD_CGC_GATE__MPEG2_MASK |
+		UVD_CGC_GATE__RBC_MASK |
+		UVD_CGC_GATE__LMI_MC_MASK |
+		UVD_CGC_GATE__IDCT_MASK |
+		UVD_CGC_GATE__MPRD_MASK |
+		UVD_CGC_GATE__MPC_MASK |
+		UVD_CGC_GATE__LBSI_MASK |
+		UVD_CGC_GATE__LRBBM_MASK |
+		UVD_CGC_GATE__UDEC_RE_MASK |
+		UVD_CGC_GATE__UDEC_CM_MASK |
+		UVD_CGC_GATE__UDEC_IT_MASK |
+		UVD_CGC_GATE__UDEC_DB_MASK |
+		UVD_CGC_GATE__UDEC_MP_MASK |
+		UVD_CGC_GATE__WCB_MASK |
+		UVD_CGC_GATE__VCPU_MASK |
+		UVD_CGC_GATE__SCPU_MASK |
+		UVD_CGC_GATE__JPEG_MASK |
+		UVD_CGC_GATE__JPEG2_MASK;
+
+	suvd_flags = UVD_SUVD_CGC_GATE__SRE_MASK |
+				UVD_SUVD_CGC_GATE__SIT_MASK |
+				UVD_SUVD_CGC_GATE__SMP_MASK |
+				UVD_SUVD_CGC_GATE__SCM_MASK |
+				UVD_SUVD_CGC_GATE__SDB_MASK;
+
+	data |= cgc_flags;
+	data1 |= suvd_flags;
+
+	WREG32(mmUVD_CGC_GATE, data);
+	WREG32(mmUVD_SUVD_CGC_GATE, data1);
+}
+#endif
+
+static void uvd_v6_set_bypass_mode(struct amdgpu_device *adev, bool enable)
+{
+	u32 tmp = RREG32_SMC(ixGCK_DFS_BYPASS_CNTL);
+
+	if (enable)
+		tmp |= (GCK_DFS_BYPASS_CNTL__BYPASSDCLK_MASK |
+			GCK_DFS_BYPASS_CNTL__BYPASSVCLK_MASK);
+	else
+		tmp &= ~(GCK_DFS_BYPASS_CNTL__BYPASSDCLK_MASK |
+			 GCK_DFS_BYPASS_CNTL__BYPASSVCLK_MASK);
+
+	WREG32_SMC(ixGCK_DFS_BYPASS_CNTL, tmp);
+}
+
 static int uvd_v6_0_set_clockgating_state(void *handle,
 					  enum amd_clockgating_state state)
 {
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 	bool enable = (state == AMD_CG_STATE_GATE) ? true : false;
+	static int curstate = -1;
+
+	if (adev->asic_type == CHIP_FIJI)
+		uvd_v6_set_bypass_mode(adev, enable);
 
 	if (!(adev->cg_flags & AMD_CG_SUPPORT_UVD_MGCG))
 		return 0;
 
+	if (curstate == state)
+		return 0;
+
+	curstate = state;
 	if (enable) {
-		if (adev->flags & AMD_IS_APU)
-			cz_set_uvd_clock_gating_branches(adev, enable);
-		else
-			tonga_set_uvd_clock_gating_branches(adev, enable);
-		uvd_v6_0_set_uvd_dynamic_clock_mode(adev, true);
+		/* disable HW gating and enable Sw gating */
+		uvd_v6_0_set_sw_clock_gating(adev);
 	} else {
-		uint32_t data = RREG32(mmUVD_CGC_CTRL);
-		data &= ~UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK;
-		WREG32(mmUVD_CGC_CTRL, data);
+		/* wait for STATUS to clear */
+		if (uvd_v6_0_wait_for_idle(handle))
+			return -EBUSY;
+
+		/* enable HW gates because UVD is idle */
+/*		uvd_v6_0_set_hw_clock_gating(adev); */
 	}
 
 	return 0;
@@ -1026,6 +896,7 @@ static int uvd_v6_0_set_powergating_stat
 }
 
 const struct amd_ip_funcs uvd_v6_0_ip_funcs = {
+	.name = "uvd_v6_0",
 	.early_init = uvd_v6_0_early_init,
 	.late_init = NULL,
 	.sw_init = uvd_v6_0_sw_init,
@@ -1037,7 +908,6 @@ const struct amd_ip_funcs uvd_v6_0_ip_fu
 	.is_idle = uvd_v6_0_is_idle,
 	.wait_for_idle = uvd_v6_0_wait_for_idle,
 	.soft_reset = uvd_v6_0_soft_reset,
-	.print_status = uvd_v6_0_print_status,
 	.set_clockgating_state = uvd_v6_0_set_clockgating_state,
 	.set_powergating_state = uvd_v6_0_set_powergating_state,
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c	2016-07-24 15:23:50.000000000 -0400
@@ -44,7 +44,7 @@
 static void vce_v2_0_mc_resume(struct amdgpu_device *adev);
 static void vce_v2_0_set_ring_funcs(struct amdgpu_device *adev);
 static void vce_v2_0_set_irq_funcs(struct amdgpu_device *adev);
-
+static int vce_v2_0_wait_for_idle(void *handle);
 /**
  * vce_v2_0_ring_get_rptr - get read pointer
  *
@@ -201,14 +201,14 @@ static int vce_v2_0_sw_init(void *handle
 
 	ring = &adev->vce.ring[0];
 	sprintf(ring->name, "vce0");
-	r = amdgpu_ring_init(adev, ring, 4096, VCE_CMD_NO_OP, 0xf,
+	r = amdgpu_ring_init(adev, ring, 512, VCE_CMD_NO_OP, 0xf,
 			     &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE);
 	if (r)
 		return r;
 
 	ring = &adev->vce.ring[1];
 	sprintf(ring->name, "vce1");
-	r = amdgpu_ring_init(adev, ring, 4096, VCE_CMD_NO_OP, 0xf,
+	r = amdgpu_ring_init(adev, ring, 512, VCE_CMD_NO_OP, 0xf,
 			     &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE);
 	if (r)
 		return r;
@@ -240,7 +240,8 @@ static int vce_v2_0_hw_init(void *handle
 
 	r = vce_v2_0_start(adev);
 	if (r)
-		return r;
+/* this error mean vcpu not in running state, so just skip ring test, not stop driver initialize */
+		return 0;
 
 	ring = &adev->vce.ring[0];
 	ring->ready = true;
@@ -318,7 +319,7 @@ static void vce_v2_0_set_sw_cg(struct am
 		WREG32(mmVCE_UENC_REG_CLOCK_GATING, tmp);
 
 		WREG32(mmVCE_CGTT_CLK_OVERRIDE, 0);
-    } else {
+	} else {
 		tmp = RREG32(mmVCE_CLOCK_GATING_B);
 		tmp |= 0xe7;
 		tmp &= ~0xe70000;
@@ -339,6 +340,21 @@ static void vce_v2_0_set_dyn_cg(struct a
 {
 	u32 orig, tmp;
 
+	if (gated) {
+		if (vce_v2_0_wait_for_idle(adev)) {
+			DRM_INFO("VCE is busy, Can't set clock gateing");
+			return;
+		}
+		WREG32_P(mmVCE_VCPU_CNTL, 0, ~VCE_VCPU_CNTL__CLK_EN_MASK);
+		WREG32_P(mmVCE_SOFT_RESET, VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK, ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
+		mdelay(100);
+		WREG32(mmVCE_STATUS, 0);
+	} else {
+		WREG32_P(mmVCE_VCPU_CNTL, VCE_VCPU_CNTL__CLK_EN_MASK, ~VCE_VCPU_CNTL__CLK_EN_MASK);
+		WREG32_P(mmVCE_SOFT_RESET, VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK, ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
+		mdelay(100);
+	}
+
 	tmp = RREG32(mmVCE_CLOCK_GATING_B);
 	tmp &= ~0x00060006;
 	if (gated) {
@@ -362,6 +378,7 @@ static void vce_v2_0_set_dyn_cg(struct a
 
 	if (gated)
 		WREG32(mmVCE_CGTT_CLK_OVERRIDE, 0);
+	WREG32_P(mmVCE_SOFT_RESET, 0, ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
 }
 
 static void vce_v2_0_disable_cg(struct amdgpu_device *adev)
@@ -478,75 +495,6 @@ static int vce_v2_0_soft_reset(void *han
 	return vce_v2_0_start(adev);
 }
 
-static void vce_v2_0_print_status(void *handle)
-{
-	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-	dev_info(adev->dev, "VCE 2.0 registers\n");
-	dev_info(adev->dev, "  VCE_STATUS=0x%08X\n",
-		 RREG32(mmVCE_STATUS));
-	dev_info(adev->dev, "  VCE_VCPU_CNTL=0x%08X\n",
-		 RREG32(mmVCE_VCPU_CNTL));
-	dev_info(adev->dev, "  VCE_VCPU_CACHE_OFFSET0=0x%08X\n",
-		 RREG32(mmVCE_VCPU_CACHE_OFFSET0));
-	dev_info(adev->dev, "  VCE_VCPU_CACHE_SIZE0=0x%08X\n",
-		 RREG32(mmVCE_VCPU_CACHE_SIZE0));
-	dev_info(adev->dev, "  VCE_VCPU_CACHE_OFFSET1=0x%08X\n",
-		 RREG32(mmVCE_VCPU_CACHE_OFFSET1));
-	dev_info(adev->dev, "  VCE_VCPU_CACHE_SIZE1=0x%08X\n",
-		 RREG32(mmVCE_VCPU_CACHE_SIZE1));
-	dev_info(adev->dev, "  VCE_VCPU_CACHE_OFFSET2=0x%08X\n",
-		 RREG32(mmVCE_VCPU_CACHE_OFFSET2));
-	dev_info(adev->dev, "  VCE_VCPU_CACHE_SIZE2=0x%08X\n",
-		 RREG32(mmVCE_VCPU_CACHE_SIZE2));
-	dev_info(adev->dev, "  VCE_SOFT_RESET=0x%08X\n",
-		 RREG32(mmVCE_SOFT_RESET));
-	dev_info(adev->dev, "  VCE_RB_BASE_LO2=0x%08X\n",
-		 RREG32(mmVCE_RB_BASE_LO2));
-	dev_info(adev->dev, "  VCE_RB_BASE_HI2=0x%08X\n",
-		 RREG32(mmVCE_RB_BASE_HI2));
-	dev_info(adev->dev, "  VCE_RB_SIZE2=0x%08X\n",
-		 RREG32(mmVCE_RB_SIZE2));
-	dev_info(adev->dev, "  VCE_RB_RPTR2=0x%08X\n",
-		 RREG32(mmVCE_RB_RPTR2));
-	dev_info(adev->dev, "  VCE_RB_WPTR2=0x%08X\n",
-		 RREG32(mmVCE_RB_WPTR2));
-	dev_info(adev->dev, "  VCE_RB_BASE_LO=0x%08X\n",
-		 RREG32(mmVCE_RB_BASE_LO));
-	dev_info(adev->dev, "  VCE_RB_BASE_HI=0x%08X\n",
-		 RREG32(mmVCE_RB_BASE_HI));
-	dev_info(adev->dev, "  VCE_RB_SIZE=0x%08X\n",
-		 RREG32(mmVCE_RB_SIZE));
-	dev_info(adev->dev, "  VCE_RB_RPTR=0x%08X\n",
-		 RREG32(mmVCE_RB_RPTR));
-	dev_info(adev->dev, "  VCE_RB_WPTR=0x%08X\n",
-		 RREG32(mmVCE_RB_WPTR));
-	dev_info(adev->dev, "  VCE_CLOCK_GATING_A=0x%08X\n",
-		 RREG32(mmVCE_CLOCK_GATING_A));
-	dev_info(adev->dev, "  VCE_CLOCK_GATING_B=0x%08X\n",
-		 RREG32(mmVCE_CLOCK_GATING_B));
-	dev_info(adev->dev, "  VCE_CGTT_CLK_OVERRIDE=0x%08X\n",
-		 RREG32(mmVCE_CGTT_CLK_OVERRIDE));
-	dev_info(adev->dev, "  VCE_UENC_CLOCK_GATING=0x%08X\n",
-		 RREG32(mmVCE_UENC_CLOCK_GATING));
-	dev_info(adev->dev, "  VCE_UENC_REG_CLOCK_GATING=0x%08X\n",
-		 RREG32(mmVCE_UENC_REG_CLOCK_GATING));
-	dev_info(adev->dev, "  VCE_SYS_INT_EN=0x%08X\n",
-		 RREG32(mmVCE_SYS_INT_EN));
-	dev_info(adev->dev, "  VCE_LMI_CTRL2=0x%08X\n",
-		 RREG32(mmVCE_LMI_CTRL2));
-	dev_info(adev->dev, "  VCE_LMI_CTRL=0x%08X\n",
-		 RREG32(mmVCE_LMI_CTRL));
-	dev_info(adev->dev, "  VCE_LMI_VM_CTRL=0x%08X\n",
-		 RREG32(mmVCE_LMI_VM_CTRL));
-	dev_info(adev->dev, "  VCE_LMI_SWAP_CNTL=0x%08X\n",
-		 RREG32(mmVCE_LMI_SWAP_CNTL));
-	dev_info(adev->dev, "  VCE_LMI_SWAP_CNTL1=0x%08X\n",
-		 RREG32(mmVCE_LMI_SWAP_CNTL1));
-	dev_info(adev->dev, "  VCE_LMI_CACHE_CTRL=0x%08X\n",
-		 RREG32(mmVCE_LMI_CACHE_CTRL));
-}
-
 static int vce_v2_0_set_interrupt_state(struct amdgpu_device *adev,
 					struct amdgpu_irq_src *source,
 					unsigned type,
@@ -619,6 +567,7 @@ static int vce_v2_0_set_powergating_stat
 }
 
 const struct amd_ip_funcs vce_v2_0_ip_funcs = {
+	.name = "vce_v2_0",
 	.early_init = vce_v2_0_early_init,
 	.late_init = NULL,
 	.sw_init = vce_v2_0_sw_init,
@@ -630,7 +579,6 @@ const struct amd_ip_funcs vce_v2_0_ip_fu
 	.is_idle = vce_v2_0_is_idle,
 	.wait_for_idle = vce_v2_0_wait_for_idle,
 	.soft_reset = vce_v2_0_soft_reset,
-	.print_status = vce_v2_0_print_status,
 	.set_clockgating_state = vce_v2_0_set_clockgating_state,
 	.set_powergating_state = vce_v2_0_set_powergating_state,
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c	2016-07-24 15:23:50.000000000 -0400
@@ -40,9 +40,9 @@
 
 #define GRBM_GFX_INDEX__VCE_INSTANCE__SHIFT	0x04
 #define GRBM_GFX_INDEX__VCE_INSTANCE_MASK	0x10
-#define mmVCE_LMI_VCPU_CACHE_40BIT_BAR0 	0x8616
-#define mmVCE_LMI_VCPU_CACHE_40BIT_BAR1 	0x8617
-#define mmVCE_LMI_VCPU_CACHE_40BIT_BAR2 	0x8618
+#define mmVCE_LMI_VCPU_CACHE_40BIT_BAR0	0x8616
+#define mmVCE_LMI_VCPU_CACHE_40BIT_BAR1	0x8617
+#define mmVCE_LMI_VCPU_CACHE_40BIT_BAR2	0x8618
 
 #define VCE_V3_0_FW_SIZE	(384 * 1024)
 #define VCE_V3_0_STACK_SIZE	(64 * 1024)
@@ -315,9 +315,11 @@ static unsigned vce_v3_0_get_harvest_con
 {
 	u32 tmp;
 
-	/* Fiji, Stoney are single pipe */
+	/* Fiji, Stoney, Polaris10, Polaris11 are single pipe */
 	if ((adev->asic_type == CHIP_FIJI) ||
-	    (adev->asic_type == CHIP_STONEY))
+	    (adev->asic_type == CHIP_STONEY) ||
+	    (adev->asic_type == CHIP_POLARIS10) ||
+	    (adev->asic_type == CHIP_POLARIS11))
 		return AMDGPU_VCE_HARVEST_VCE1;
 
 	/* Tonga and CZ are dual or single pipe */
@@ -381,14 +383,14 @@ static int vce_v3_0_sw_init(void *handle
 
 	ring = &adev->vce.ring[0];
 	sprintf(ring->name, "vce0");
-	r = amdgpu_ring_init(adev, ring, 4096, VCE_CMD_NO_OP, 0xf,
+	r = amdgpu_ring_init(adev, ring, 512, VCE_CMD_NO_OP, 0xf,
 			     &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE);
 	if (r)
 		return r;
 
 	ring = &adev->vce.ring[1];
 	sprintf(ring->name, "vce1");
-	r = amdgpu_ring_init(adev, ring, 4096, VCE_CMD_NO_OP, 0xf,
+	r = amdgpu_ring_init(adev, ring, 512, VCE_CMD_NO_OP, 0xf,
 			     &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE);
 	if (r)
 		return r;
@@ -564,73 +566,6 @@ static int vce_v3_0_soft_reset(void *han
 	return vce_v3_0_start(adev);
 }
 
-static void vce_v3_0_print_status(void *handle)
-{
-	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-	dev_info(adev->dev, "VCE 3.0 registers\n");
-	dev_info(adev->dev, "  VCE_STATUS=0x%08X\n",
-		 RREG32(mmVCE_STATUS));
-	dev_info(adev->dev, "  VCE_VCPU_CNTL=0x%08X\n",
-		 RREG32(mmVCE_VCPU_CNTL));
-	dev_info(adev->dev, "  VCE_VCPU_CACHE_OFFSET0=0x%08X\n",
-		 RREG32(mmVCE_VCPU_CACHE_OFFSET0));
-	dev_info(adev->dev, "  VCE_VCPU_CACHE_SIZE0=0x%08X\n",
-		 RREG32(mmVCE_VCPU_CACHE_SIZE0));
-	dev_info(adev->dev, "  VCE_VCPU_CACHE_OFFSET1=0x%08X\n",
-		 RREG32(mmVCE_VCPU_CACHE_OFFSET1));
-	dev_info(adev->dev, "  VCE_VCPU_CACHE_SIZE1=0x%08X\n",
-		 RREG32(mmVCE_VCPU_CACHE_SIZE1));
-	dev_info(adev->dev, "  VCE_VCPU_CACHE_OFFSET2=0x%08X\n",
-		 RREG32(mmVCE_VCPU_CACHE_OFFSET2));
-	dev_info(adev->dev, "  VCE_VCPU_CACHE_SIZE2=0x%08X\n",
-		 RREG32(mmVCE_VCPU_CACHE_SIZE2));
-	dev_info(adev->dev, "  VCE_SOFT_RESET=0x%08X\n",
-		 RREG32(mmVCE_SOFT_RESET));
-	dev_info(adev->dev, "  VCE_RB_BASE_LO2=0x%08X\n",
-		 RREG32(mmVCE_RB_BASE_LO2));
-	dev_info(adev->dev, "  VCE_RB_BASE_HI2=0x%08X\n",
-		 RREG32(mmVCE_RB_BASE_HI2));
-	dev_info(adev->dev, "  VCE_RB_SIZE2=0x%08X\n",
-		 RREG32(mmVCE_RB_SIZE2));
-	dev_info(adev->dev, "  VCE_RB_RPTR2=0x%08X\n",
-		 RREG32(mmVCE_RB_RPTR2));
-	dev_info(adev->dev, "  VCE_RB_WPTR2=0x%08X\n",
-		 RREG32(mmVCE_RB_WPTR2));
-	dev_info(adev->dev, "  VCE_RB_BASE_LO=0x%08X\n",
-		 RREG32(mmVCE_RB_BASE_LO));
-	dev_info(adev->dev, "  VCE_RB_BASE_HI=0x%08X\n",
-		 RREG32(mmVCE_RB_BASE_HI));
-	dev_info(adev->dev, "  VCE_RB_SIZE=0x%08X\n",
-		 RREG32(mmVCE_RB_SIZE));
-	dev_info(adev->dev, "  VCE_RB_RPTR=0x%08X\n",
-		 RREG32(mmVCE_RB_RPTR));
-	dev_info(adev->dev, "  VCE_RB_WPTR=0x%08X\n",
-		 RREG32(mmVCE_RB_WPTR));
-	dev_info(adev->dev, "  VCE_CLOCK_GATING_A=0x%08X\n",
-		 RREG32(mmVCE_CLOCK_GATING_A));
-	dev_info(adev->dev, "  VCE_CLOCK_GATING_B=0x%08X\n",
-		 RREG32(mmVCE_CLOCK_GATING_B));
-	dev_info(adev->dev, "  VCE_UENC_CLOCK_GATING=0x%08X\n",
-		 RREG32(mmVCE_UENC_CLOCK_GATING));
-	dev_info(adev->dev, "  VCE_UENC_REG_CLOCK_GATING=0x%08X\n",
-		 RREG32(mmVCE_UENC_REG_CLOCK_GATING));
-	dev_info(adev->dev, "  VCE_SYS_INT_EN=0x%08X\n",
-		 RREG32(mmVCE_SYS_INT_EN));
-	dev_info(adev->dev, "  VCE_LMI_CTRL2=0x%08X\n",
-		 RREG32(mmVCE_LMI_CTRL2));
-	dev_info(adev->dev, "  VCE_LMI_CTRL=0x%08X\n",
-		 RREG32(mmVCE_LMI_CTRL));
-	dev_info(adev->dev, "  VCE_LMI_VM_CTRL=0x%08X\n",
-		 RREG32(mmVCE_LMI_VM_CTRL));
-	dev_info(adev->dev, "  VCE_LMI_SWAP_CNTL=0x%08X\n",
-		 RREG32(mmVCE_LMI_SWAP_CNTL));
-	dev_info(adev->dev, "  VCE_LMI_SWAP_CNTL1=0x%08X\n",
-		 RREG32(mmVCE_LMI_SWAP_CNTL1));
-	dev_info(adev->dev, "  VCE_LMI_CACHE_CTRL=0x%08X\n",
-		 RREG32(mmVCE_LMI_CACHE_CTRL));
-}
-
 static int vce_v3_0_set_interrupt_state(struct amdgpu_device *adev,
 					struct amdgpu_irq_src *source,
 					unsigned type,
@@ -739,6 +674,7 @@ static int vce_v3_0_set_powergating_stat
 }
 
 const struct amd_ip_funcs vce_v3_0_ip_funcs = {
+	.name = "vce_v3_0",
 	.early_init = vce_v3_0_early_init,
 	.late_init = NULL,
 	.sw_init = vce_v3_0_sw_init,
@@ -750,7 +686,6 @@ const struct amd_ip_funcs vce_v3_0_ip_fu
 	.is_idle = vce_v3_0_is_idle,
 	.wait_for_idle = vce_v3_0_wait_for_idle,
 	.soft_reset = vce_v3_0_soft_reset,
-	.print_status = vce_v3_0_print_status,
 	.set_clockgating_state = vce_v3_0_set_clockgating_state,
 	.set_powergating_state = vce_v3_0_set_powergating_state,
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/vi.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/vi.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/vi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/vi.c	2016-07-24 18:17:35.000000000 -0400
@@ -78,6 +78,8 @@
 #include "amdgpu_acp.h"
 #endif
 
+/*(DEBLOBBED)*/
+
 /*
  * Indirect registers accessor
  */
@@ -276,6 +278,8 @@ static void vi_init_golden_registers(str
 						 stoney_mgcg_cgcg_init,
 						 (const u32)ARRAY_SIZE(stoney_mgcg_cgcg_init));
 		break;
+	case CHIP_POLARIS11:
+	case CHIP_POLARIS10:
 	default:
 		break;
 	}
@@ -414,11 +418,25 @@ static bool vi_read_bios_from_rom(struct
 	return true;
 }
 
-static struct amdgpu_allowed_register_entry tonga_allowed_read_registers[] = {
+static u32 vi_get_virtual_caps(struct amdgpu_device *adev)
+{
+	u32 caps = 0;
+	u32 reg = RREG32(mmBIF_IOV_FUNC_IDENTIFIER);
+
+	if (REG_GET_FIELD(reg, BIF_IOV_FUNC_IDENTIFIER, IOV_ENABLE))
+		caps |= AMDGPU_VIRT_CAPS_SRIOV_EN;
+
+	if (REG_GET_FIELD(reg, BIF_IOV_FUNC_IDENTIFIER, FUNC_IDENTIFIER))
+		caps |= AMDGPU_VIRT_CAPS_IS_VF;
+
+	return caps;
+}
+
+static const struct amdgpu_allowed_register_entry tonga_allowed_read_registers[] = {
 	{mmGB_MACROTILE_MODE7, true},
 };
 
-static struct amdgpu_allowed_register_entry cz_allowed_read_registers[] = {
+static const struct amdgpu_allowed_register_entry cz_allowed_read_registers[] = {
 	{mmGB_TILE_MODE7, true},
 	{mmGB_TILE_MODE12, true},
 	{mmGB_TILE_MODE17, true},
@@ -426,7 +444,7 @@ static struct amdgpu_allowed_register_en
 	{mmGB_MACROTILE_MODE7, true},
 };
 
-static struct amdgpu_allowed_register_entry vi_allowed_read_registers[] = {
+static const struct amdgpu_allowed_register_entry vi_allowed_read_registers[] = {
 	{mmGRBM_STATUS, false},
 	{mmGRBM_STATUS2, false},
 	{mmGRBM_STATUS_SE0, false},
@@ -525,8 +543,8 @@ static uint32_t vi_read_indexed_register
 static int vi_read_register(struct amdgpu_device *adev, u32 se_num,
 			    u32 sh_num, u32 reg_offset, u32 *value)
 {
-	struct amdgpu_allowed_register_entry *asic_register_table = NULL;
-	struct amdgpu_allowed_register_entry *asic_register_entry;
+	const struct amdgpu_allowed_register_entry *asic_register_table = NULL;
+	const struct amdgpu_allowed_register_entry *asic_register_entry;
 	uint32_t size, i;
 
 	*value = 0;
@@ -537,6 +555,8 @@ static int vi_read_register(struct amdgp
 		break;
 	case CHIP_FIJI:
 	case CHIP_TONGA:
+	case CHIP_POLARIS11:
+	case CHIP_POLARIS10:
 	case CHIP_CARRIZO:
 	case CHIP_STONEY:
 		asic_register_table = cz_allowed_read_registers;
@@ -907,6 +927,74 @@ static const struct amdgpu_ip_block_vers
 	},
 };
 
+static const struct amdgpu_ip_block_version polaris11_ip_blocks[] =
+{
+	/* ORDER MATTERS! */
+	{
+		.type = AMD_IP_BLOCK_TYPE_COMMON,
+		.major = 2,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &vi_common_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_GMC,
+		.major = 8,
+		.minor = 1,
+		.rev = 0,
+		.funcs = &gmc_v8_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_IH,
+		.major = 3,
+		.minor = 1,
+		.rev = 0,
+		.funcs = &tonga_ih_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_SMC,
+		.major = 7,
+		.minor = 2,
+		.rev = 0,
+		.funcs = &amdgpu_pp_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_DCE,
+		.major = 11,
+		.minor = 2,
+		.rev = 0,
+		.funcs = &dce_v11_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_GFX,
+		.major = 8,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &gfx_v8_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_SDMA,
+		.major = 3,
+		.minor = 1,
+		.rev = 0,
+		.funcs = &sdma_v3_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_UVD,
+		.major = 6,
+		.minor = 3,
+		.rev = 0,
+		.funcs = &uvd_v6_0_ip_funcs,
+	},
+	{
+		.type = AMD_IP_BLOCK_TYPE_VCE,
+		.major = 3,
+		.minor = 4,
+		.rev = 0,
+		.funcs = &vce_v3_0_ip_funcs,
+	},
+};
+
 static const struct amdgpu_ip_block_version cz_ip_blocks[] =
 {
 	/* ORDER MATTERS! */
@@ -999,6 +1087,11 @@ int vi_set_ip_blocks(struct amdgpu_devic
 		adev->ip_blocks = tonga_ip_blocks;
 		adev->num_ip_blocks = ARRAY_SIZE(tonga_ip_blocks);
 		break;
+	case CHIP_POLARIS11:
+	case CHIP_POLARIS10:
+		adev->ip_blocks = polaris11_ip_blocks;
+		adev->num_ip_blocks = ARRAY_SIZE(polaris11_ip_blocks);
+		break;
 	case CHIP_CARRIZO:
 	case CHIP_STONEY:
 		adev->ip_blocks = cz_ip_blocks;
@@ -1036,7 +1129,7 @@ static const struct amdgpu_asic_funcs vi
 	.get_xclk = &vi_get_xclk,
 	.set_uvd_clocks = &vi_set_uvd_clocks,
 	.set_vce_clocks = &vi_set_vce_clocks,
-	.get_cu_info = &gfx_v8_0_get_cu_info,
+	.get_virtual_caps = &vi_get_virtual_caps,
 	/* these should be moved to their own ip modules */
 	.get_gpu_clock_counter = &gfx_v8_0_get_gpu_clock_counter,
 	.wait_for_mc_idle = &gmc_v8_0_mc_wait_for_idle,
@@ -1076,18 +1169,68 @@ static int vi_common_early_init(void *ha
 		adev->external_rev_id = 0x1;
 		break;
 	case CHIP_FIJI:
-		adev->cg_flags = 0;
+		adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG |
+			AMD_CG_SUPPORT_GFX_MGLS |
+			AMD_CG_SUPPORT_GFX_RLC_LS |
+			AMD_CG_SUPPORT_GFX_CP_LS |
+			AMD_CG_SUPPORT_GFX_CGTS |
+			AMD_CG_SUPPORT_GFX_CGTS_LS |
+			AMD_CG_SUPPORT_GFX_CGCG |
+			AMD_CG_SUPPORT_GFX_CGLS |
+			AMD_CG_SUPPORT_SDMA_MGCG |
+			AMD_CG_SUPPORT_SDMA_LS |
+			AMD_CG_SUPPORT_BIF_LS |
+			AMD_CG_SUPPORT_HDP_MGCG |
+			AMD_CG_SUPPORT_HDP_LS |
+			AMD_CG_SUPPORT_ROM_MGCG |
+			AMD_CG_SUPPORT_MC_MGCG |
+			AMD_CG_SUPPORT_MC_LS;
 		adev->pg_flags = 0;
 		adev->external_rev_id = adev->rev_id + 0x3c;
 		break;
 	case CHIP_TONGA:
-		adev->cg_flags = 0;
+		adev->cg_flags = AMD_CG_SUPPORT_UVD_MGCG;
 		adev->pg_flags = 0;
 		adev->external_rev_id = adev->rev_id + 0x14;
 		break;
+	case CHIP_POLARIS11:
+		adev->cg_flags = 0;
+		adev->pg_flags = 0;
+		adev->external_rev_id = adev->rev_id + 0x5A;
+		break;
+	case CHIP_POLARIS10:
+		adev->cg_flags = 0;
+		adev->pg_flags = 0;
+		adev->external_rev_id = adev->rev_id + 0x50;
+		break;
 	case CHIP_CARRIZO:
+		adev->cg_flags = AMD_CG_SUPPORT_UVD_MGCG |
+			AMD_CG_SUPPORT_GFX_MGCG |
+			AMD_CG_SUPPORT_GFX_MGLS |
+			AMD_CG_SUPPORT_GFX_RLC_LS |
+			AMD_CG_SUPPORT_GFX_CP_LS |
+			AMD_CG_SUPPORT_GFX_CGTS |
+			AMD_CG_SUPPORT_GFX_MGLS |
+			AMD_CG_SUPPORT_GFX_CGTS_LS |
+			AMD_CG_SUPPORT_GFX_CGCG |
+			AMD_CG_SUPPORT_GFX_CGLS |
+			AMD_CG_SUPPORT_BIF_LS |
+			AMD_CG_SUPPORT_HDP_MGCG |
+			AMD_CG_SUPPORT_HDP_LS |
+			AMD_CG_SUPPORT_SDMA_MGCG |
+			AMD_CG_SUPPORT_SDMA_LS;
+		adev->pg_flags = 0;
+		adev->external_rev_id = adev->rev_id + 0x1;
+		break;
 	case CHIP_STONEY:
-		adev->cg_flags = 0;
+		adev->cg_flags = AMD_CG_SUPPORT_UVD_MGCG |
+			AMD_CG_SUPPORT_GFX_MGCG |
+			AMD_CG_SUPPORT_GFX_MGLS |
+			AMD_CG_SUPPORT_BIF_LS |
+			AMD_CG_SUPPORT_HDP_MGCG |
+			AMD_CG_SUPPORT_HDP_LS |
+			AMD_CG_SUPPORT_SDMA_MGCG |
+			AMD_CG_SUPPORT_SDMA_LS;
 		adev->pg_flags = 0;
 		adev->external_rev_id = adev->rev_id + 0x1;
 		break;
@@ -1164,24 +1307,19 @@ static int vi_common_wait_for_idle(void
 	return 0;
 }
 
-static void vi_common_print_status(void *handle)
-{
-	return;
-}
-
 static int vi_common_soft_reset(void *handle)
 {
 	return 0;
 }
 
-static void fiji_update_bif_medium_grain_light_sleep(struct amdgpu_device *adev,
-		bool enable)
+static void vi_update_bif_medium_grain_light_sleep(struct amdgpu_device *adev,
+						   bool enable)
 {
 	uint32_t temp, data;
 
 	temp = data = RREG32_PCIE(ixPCIE_CNTL2);
 
-	if (enable)
+	if (enable && (adev->cg_flags & AMD_CG_SUPPORT_BIF_LS))
 		data |= PCIE_CNTL2__SLV_MEM_LS_EN_MASK |
 				PCIE_CNTL2__MST_MEM_LS_EN_MASK |
 				PCIE_CNTL2__REPLAY_MEM_LS_EN_MASK;
@@ -1194,14 +1332,14 @@ static void fiji_update_bif_medium_grain
 		WREG32_PCIE(ixPCIE_CNTL2, data);
 }
 
-static void fiji_update_hdp_medium_grain_clock_gating(struct amdgpu_device *adev,
-		bool enable)
+static void vi_update_hdp_medium_grain_clock_gating(struct amdgpu_device *adev,
+						    bool enable)
 {
 	uint32_t temp, data;
 
 	temp = data = RREG32(mmHDP_HOST_PATH_CNTL);
 
-	if (enable)
+	if (enable && (adev->cg_flags & AMD_CG_SUPPORT_HDP_MGCG))
 		data &= ~HDP_HOST_PATH_CNTL__CLOCK_GATING_DIS_MASK;
 	else
 		data |= HDP_HOST_PATH_CNTL__CLOCK_GATING_DIS_MASK;
@@ -1210,14 +1348,14 @@ static void fiji_update_hdp_medium_grain
 		WREG32(mmHDP_HOST_PATH_CNTL, data);
 }
 
-static void fiji_update_hdp_light_sleep(struct amdgpu_device *adev,
-		bool enable)
+static void vi_update_hdp_light_sleep(struct amdgpu_device *adev,
+				      bool enable)
 {
 	uint32_t temp, data;
 
 	temp = data = RREG32(mmHDP_MEM_POWER_LS);
 
-	if (enable)
+	if (enable && (adev->cg_flags & AMD_CG_SUPPORT_HDP_LS))
 		data |= HDP_MEM_POWER_LS__LS_ENABLE_MASK;
 	else
 		data &= ~HDP_MEM_POWER_LS__LS_ENABLE_MASK;
@@ -1226,14 +1364,14 @@ static void fiji_update_hdp_light_sleep(
 		WREG32(mmHDP_MEM_POWER_LS, data);
 }
 
-static void fiji_update_rom_medium_grain_clock_gating(struct amdgpu_device *adev,
-		bool enable)
+static void vi_update_rom_medium_grain_clock_gating(struct amdgpu_device *adev,
+						    bool enable)
 {
 	uint32_t temp, data;
 
 	temp = data = RREG32_SMC(ixCGTT_ROM_CLK_CTRL0);
 
-	if (enable)
+	if (enable && (adev->cg_flags & AMD_CG_SUPPORT_ROM_MGCG))
 		data &= ~(CGTT_ROM_CLK_CTRL0__SOFT_OVERRIDE0_MASK |
 				CGTT_ROM_CLK_CTRL0__SOFT_OVERRIDE1_MASK);
 	else
@@ -1245,19 +1383,28 @@ static void fiji_update_rom_medium_grain
 }
 
 static int vi_common_set_clockgating_state(void *handle,
-					    enum amd_clockgating_state state)
+					   enum amd_clockgating_state state)
 {
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
 	switch (adev->asic_type) {
 	case CHIP_FIJI:
-		fiji_update_bif_medium_grain_light_sleep(adev,
+		vi_update_bif_medium_grain_light_sleep(adev,
 				state == AMD_CG_STATE_GATE ? true : false);
-		fiji_update_hdp_medium_grain_clock_gating(adev,
+		vi_update_hdp_medium_grain_clock_gating(adev,
 				state == AMD_CG_STATE_GATE ? true : false);
-		fiji_update_hdp_light_sleep(adev,
+		vi_update_hdp_light_sleep(adev,
 				state == AMD_CG_STATE_GATE ? true : false);
-		fiji_update_rom_medium_grain_clock_gating(adev,
+		vi_update_rom_medium_grain_clock_gating(adev,
+				state == AMD_CG_STATE_GATE ? true : false);
+		break;
+	case CHIP_CARRIZO:
+	case CHIP_STONEY:
+		vi_update_bif_medium_grain_light_sleep(adev,
+				state == AMD_CG_STATE_GATE ? true : false);
+		vi_update_hdp_medium_grain_clock_gating(adev,
+				state == AMD_CG_STATE_GATE ? true : false);
+		vi_update_hdp_light_sleep(adev,
 				state == AMD_CG_STATE_GATE ? true : false);
 		break;
 	default:
@@ -1273,6 +1420,7 @@ static int vi_common_set_powergating_sta
 }
 
 const struct amd_ip_funcs vi_common_ip_funcs = {
+	.name = "vi_common",
 	.early_init = vi_common_early_init,
 	.late_init = NULL,
 	.sw_init = vi_common_sw_init,
@@ -1284,7 +1432,6 @@ const struct amd_ip_funcs vi_common_ip_f
 	.is_idle = vi_common_is_idle,
 	.wait_for_idle = vi_common_wait_for_idle,
 	.soft_reset = vi_common_soft_reset,
-	.print_status = vi_common_print_status,
 	.set_clockgating_state = vi_common_set_clockgating_state,
 	.set_powergating_state = vi_common_set_powergating_state,
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/vid.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/vid.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdgpu/vid.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdgpu/vid.h	2016-07-24 15:23:50.000000000 -0400
@@ -54,7 +54,8 @@
 #define AUD3_REGISTER_OFFSET                 (0x17b4 - 0x17a8)
 #define AUD4_REGISTER_OFFSET                 (0x17b8 - 0x17a8)
 #define AUD5_REGISTER_OFFSET                 (0x17bc - 0x17a8)
-#define AUD6_REGISTER_OFFSET                 (0x17c4 - 0x17a8)
+#define AUD6_REGISTER_OFFSET                 (0x17c0 - 0x17a8)
+#define AUD7_REGISTER_OFFSET                 (0x17c4 - 0x17a8)
 
 /* hpd instance offsets */
 #define HPD0_REGISTER_OFFSET                 (0x1898 - 0x1898)
@@ -365,7 +366,7 @@
 #define VCE_CMD_IB		0x00000002
 #define VCE_CMD_FENCE		0x00000003
 #define VCE_CMD_TRAP		0x00000004
-#define VCE_CMD_IB_AUTO 	0x00000005
+#define VCE_CMD_IB_AUTO	0x00000005
 #define VCE_CMD_SEMAPHORE	0x00000006
 
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c	2016-07-24 15:23:50.000000000 -0400
@@ -109,7 +109,7 @@ static int kfd_open(struct inode *inode,
 
 	is_32bit_user_mode = in_compat_syscall();
 
-	if (is_32bit_user_mode == true) {
+	if (is_32bit_user_mode) {
 		dev_warn(kfd_device,
 			"Process %d (32-bit) failed to open /dev/kfd\n"
 			"32-bit processes are not supported by amdkfd\n",
@@ -131,12 +131,11 @@ static int kfd_ioctl_get_version(struct
 					void *data)
 {
 	struct kfd_ioctl_get_version_args *args = data;
-	int err = 0;
 
 	args->major_version = KFD_IOCTL_MAJOR_VERSION;
 	args->minor_version = KFD_IOCTL_MINOR_VERSION;
 
-	return err;
+	return 0;
 }
 
 static int set_queue_properties_from_user(struct queue_properties *q_properties,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c	2016-07-24 15:23:50.000000000 -0400
@@ -216,7 +216,7 @@ static int allocate_hqd(struct device_qu
 		}
 	}
 
-	if (set == false)
+	if (!set)
 		return -EBUSY;
 
 	pr_debug("kfd: DQM %s hqd slot - pipe (%d) queue(%d)\n",
@@ -354,7 +354,7 @@ static int update_queue(struct device_qu
 		return -ENOMEM;
 	}
 
-	if (q->properties.is_active == true)
+	if (q->properties.is_active)
 		prev_active = true;
 
 	/*
@@ -363,9 +363,9 @@ static int update_queue(struct device_qu
 	 * and modify counter accordingly
 	 */
 	retval = mqd->update_mqd(mqd, q->mqd, &q->properties);
-	if ((q->properties.is_active == true) && (prev_active == false))
+	if ((q->properties.is_active) && (!prev_active))
 		dqm->queue_count++;
-	else if ((q->properties.is_active == false) && (prev_active == true))
+	else if ((!q->properties.is_active) && (prev_active))
 		dqm->queue_count--;
 
 	if (sched_policy != KFD_SCHED_POLICY_NO_HWS)
@@ -954,7 +954,7 @@ static int destroy_queues_cpsch(struct d
 
 	if (lock)
 		mutex_lock(&dqm->lock);
-	if (dqm->active_runlist == false)
+	if (!dqm->active_runlist)
 		goto out;
 
 	pr_debug("kfd: Before destroying queues, sdma queue count is : %u\n",
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_events.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdkfd/kfd_events.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_events.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdkfd/kfd_events.c	2016-07-24 15:23:50.000000000 -0400
@@ -177,9 +177,9 @@ static bool allocate_event_notification_
 	bool ret;
 
 	ret = allocate_free_slot(p, page, signal_slot_index);
-	if (ret == false) {
+	if (!ret) {
 		ret = allocate_signal_page(devkfd, p);
-		if (ret == true)
+		if (ret)
 			ret = allocate_free_slot(p, page, signal_slot_index);
 	}
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c	2016-07-24 15:23:50.000000000 -0400
@@ -300,7 +300,7 @@ struct kernel_queue *kernel_queue_init(s
 		break;
 	}
 
-	if (kq->ops.initialize(kq, dev, type, KFD_KERNEL_QUEUE_SIZE) == false) {
+	if (!kq->ops.initialize(kq, dev, type, KFD_KERNEL_QUEUE_SIZE)) {
 		pr_err("amdkfd: failed to init kernel queue\n");
 		kfree(kq);
 		return NULL;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c	2016-07-24 15:23:50.000000000 -0400
@@ -98,7 +98,7 @@ static int pm_allocate_runlist_ib(struct
 	int retval;
 
 	BUG_ON(!pm);
-	BUG_ON(pm->allocated == true);
+	BUG_ON(pm->allocated);
 	BUG_ON(is_over_subscription == NULL);
 
 	pm_calc_rlib_size(pm, rl_buffer_size, is_over_subscription);
@@ -292,7 +292,7 @@ static int pm_create_map_queue(struct pa
 			q->properties.doorbell_off;
 
 	packet->mes_map_queues_ordinals[0].bitfields3.is_static =
-			(use_static == true) ? 1 : 0;
+			(use_static) ? 1 : 0;
 
 	packet->mes_map_queues_ordinals[0].mqd_addr_lo =
 			lower_32_bits(q->gart_mqd_addr);
@@ -357,7 +357,7 @@ static int pm_create_runlist_ib(struct p
 				alloc_size_bytes);
 
 		list_for_each_entry(kq, &qpd->priv_queue_list, list) {
-			if (kq->queue->properties.is_active != true)
+			if (!kq->queue->properties.is_active)
 				continue;
 
 			pr_debug("kfd: static_queue, mapping kernel q %d, is debug status %d\n",
@@ -383,7 +383,7 @@ static int pm_create_runlist_ib(struct p
 		}
 
 		list_for_each_entry(q, &qpd->queues_list, list) {
-			if (q->properties.is_active != true)
+			if (!q->properties.is_active)
 				continue;
 
 			pr_debug("kfd: static_queue, mapping user queue %d, is debug status %d\n",
@@ -531,7 +531,7 @@ fail_create_runlist:
 fail_acquire_packet_buffer:
 	mutex_unlock(&pm->lock);
 fail_create_runlist_ib:
-	if (pm->allocated == true)
+	if (pm->allocated)
 		pm_release_ib(pm);
 	return retval;
 }
@@ -647,7 +647,7 @@ int pm_send_unmap_queue(struct packet_ma
 	default:
 		BUG();
 		break;
-	};
+	}
 
 	pm->priv_queue->ops.submit_packet(pm->priv_queue);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_process.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdkfd/kfd_process.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_process.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdkfd/kfd_process.c	2016-07-24 15:23:50.000000000 -0400
@@ -242,13 +242,19 @@ static void kfd_process_notifier_release
 	pqm_uninit(&p->pqm);
 
 	/* Iterate over all process device data structure and check
-	 * if we should reset all wavefronts */
-	list_for_each_entry(pdd, &p->per_device_data, per_device_list)
+	 * if we should delete debug managers and reset all wavefronts
+	 */
+	list_for_each_entry(pdd, &p->per_device_data, per_device_list) {
+		if ((pdd->dev->dbgmgr) &&
+				(pdd->dev->dbgmgr->pasid == p->pasid))
+			kfd_dbgmgr_destroy(pdd->dev->dbgmgr);
+
 		if (pdd->reset_wavefronts) {
 			pr_warn("amdkfd: Resetting all wave fronts\n");
 			dbgdev_wave_reset_wavefronts(pdd->dev, p);
 			pdd->reset_wavefronts = false;
 		}
+	}
 
 	mutex_unlock(&p->mutex);
 
@@ -404,42 +410,52 @@ void kfd_unbind_process_from_device(stru
 
 	idx = srcu_read_lock(&kfd_processes_srcu);
 
+	/*
+	 * Look for the process that matches the pasid. If there is no such
+	 * process, we either released it in amdkfd's own notifier, or there
+	 * is a bug. Unfortunately, there is no way to tell...
+	 */
 	hash_for_each_rcu(kfd_processes_table, i, p, kfd_processes)
-		if (p->pasid == pasid)
-			break;
+		if (p->pasid == pasid) {
 
-	srcu_read_unlock(&kfd_processes_srcu, idx);
+			srcu_read_unlock(&kfd_processes_srcu, idx);
 
-	BUG_ON(p->pasid != pasid);
+			pr_debug("Unbinding process %d from IOMMU\n", pasid);
 
-	mutex_lock(&p->mutex);
+			mutex_lock(&p->mutex);
 
-	if ((dev->dbgmgr) && (dev->dbgmgr->pasid == p->pasid))
-		kfd_dbgmgr_destroy(dev->dbgmgr);
+			if ((dev->dbgmgr) && (dev->dbgmgr->pasid == p->pasid))
+				kfd_dbgmgr_destroy(dev->dbgmgr);
 
-	pqm_uninit(&p->pqm);
+			pqm_uninit(&p->pqm);
 
-	pdd = kfd_get_process_device_data(dev, p);
+			pdd = kfd_get_process_device_data(dev, p);
 
-	if (!pdd) {
-		mutex_unlock(&p->mutex);
-		return;
-	}
+			if (!pdd) {
+				mutex_unlock(&p->mutex);
+				return;
+			}
 
-	if (pdd->reset_wavefronts) {
-		dbgdev_wave_reset_wavefronts(pdd->dev, p);
-		pdd->reset_wavefronts = false;
-	}
+			if (pdd->reset_wavefronts) {
+				dbgdev_wave_reset_wavefronts(pdd->dev, p);
+				pdd->reset_wavefronts = false;
+			}
 
-	/*
-	 * Just mark pdd as unbound, because we still need it to call
-	 * amd_iommu_unbind_pasid() in when the process exits.
-	 * We don't call amd_iommu_unbind_pasid() here
-	 * because the IOMMU called us.
-	 */
-	pdd->bound = false;
+			/*
+			 * Just mark pdd as unbound, because we still need it
+			 * to call amd_iommu_unbind_pasid() in when the
+			 * process exits.
+			 * We don't call amd_iommu_unbind_pasid() here
+			 * because the IOMMU called us.
+			 */
+			pdd->bound = false;
 
-	mutex_unlock(&p->mutex);
+			mutex_unlock(&p->mutex);
+
+			return;
+		}
+
+	srcu_read_unlock(&kfd_processes_srcu, idx);
 }
 
 struct kfd_process_device *kfd_get_first_process_device_data(struct kfd_process *p)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_topology.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/amdkfd/kfd_topology.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/amdkfd/kfd_topology.c	2016-07-24 15:23:50.000000000 -0400
@@ -666,7 +666,7 @@ static ssize_t node_show(struct kobject
 			dev->node_props.simd_count);
 
 	if (dev->mem_bank_count < dev->node_props.mem_banks_count) {
-		pr_warn("kfd: mem_banks_count truncated from %d to %d\n",
+		pr_info_once("kfd: mem_banks_count truncated from %d to %d\n",
 				dev->node_props.mem_banks_count,
 				dev->mem_bank_count);
 		sysfs_show_32bit_prop(buffer, "mem_banks_count",
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/include/amd_shared.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/include/amd_shared.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/include/amd_shared.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/include/amd_shared.h	2016-07-24 15:23:50.000000000 -0400
@@ -48,6 +48,8 @@ enum amd_asic_type {
 	CHIP_FIJI,
 	CHIP_CARRIZO,
 	CHIP_STONEY,
+	CHIP_POLARIS10,
+	CHIP_POLARIS11,
 	CHIP_LAST,
 };
 
@@ -104,6 +106,7 @@ enum amd_powergating_state {
 #define AMD_CG_SUPPORT_VCE_MGCG			(1 << 14)
 #define AMD_CG_SUPPORT_HDP_LS			(1 << 15)
 #define AMD_CG_SUPPORT_HDP_MGCG			(1 << 16)
+#define AMD_CG_SUPPORT_ROM_MGCG			(1 << 17)
 
 /* PG flags */
 #define AMD_PG_SUPPORT_GFX_PG			(1 << 0)
@@ -140,6 +143,8 @@ enum amd_pm_state_type {
 };
 
 struct amd_ip_funcs {
+	/* Name of IP block */
+	char *name;
 	/* sets up early driver state (pre sw_init), does not configure hw - Optional */
 	int (*early_init)(void *handle);
 	/* sets up late driver/hw state (post hw_init) - Optional */
@@ -152,6 +157,7 @@ struct amd_ip_funcs {
 	int (*hw_init)(void *handle);
 	/* tears down the hw state */
 	int (*hw_fini)(void *handle);
+	void (*late_fini)(void *handle);
 	/* handles IP specific hw/sw changes for suspend */
 	int (*suspend)(void *handle);
 	/* handles IP specific hw/sw changes for resume */
@@ -162,8 +168,6 @@ struct amd_ip_funcs {
 	int (*wait_for_idle)(void *handle);
 	/* soft reset the IP block */
 	int (*soft_reset)(void *handle);
-	/* dump the IP block status registers */
-	void (*print_status)(void *handle);
 	/* enable/disable cg for the IP block */
 	int (*set_clockgating_state)(void *handle,
 				     enum amd_clockgating_state state);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/include/asic_reg/dce/dce_11_2_d.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/include/asic_reg/dce/dce_11_2_d.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/include/asic_reg/dce/dce_11_2_d.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/include/asic_reg/dce/dce_11_2_d.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,10075 @@
+/*
+ * DCE_11_2 Register documentation
+ *
+ * Copyright (C) 2016  Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef DCE_11_2_D_H
+#define DCE_11_2_D_H
+
+#define mmPIPE0_PG_CONFIG                                                       0x2c0
+#define mmPIPE0_PG_ENABLE                                                       0x2c1
+#define mmPIPE0_PG_STATUS                                                       0x2c2
+#define mmPIPE1_PG_CONFIG                                                       0x2c3
+#define mmPIPE1_PG_ENABLE                                                       0x2c4
+#define mmPIPE1_PG_STATUS                                                       0x2c5
+#define mmPIPE2_PG_CONFIG                                                       0x2c6
+#define mmPIPE2_PG_ENABLE                                                       0x2c7
+#define mmPIPE2_PG_STATUS                                                       0x2c8
+#define mmPIPE3_PG_CONFIG                                                       0x2c9
+#define mmPIPE3_PG_ENABLE                                                       0x2ca
+#define mmPIPE3_PG_STATUS                                                       0x2cb
+#define mmPIPE4_PG_CONFIG                                                       0x2cc
+#define mmPIPE4_PG_ENABLE                                                       0x2cd
+#define mmPIPE4_PG_STATUS                                                       0x2ce
+#define mmPIPE5_PG_CONFIG                                                       0x2cf
+#define mmPIPE5_PG_ENABLE                                                       0x2d0
+#define mmPIPE5_PG_STATUS                                                       0x2d1
+#define mmDCPG_INTERRUPT_STATUS                                                 0x2de
+#define mmDCPG_INTERRUPT_CONTROL                                                0x2df
+#define mmDCPG_INTERRUPT_CONTROL2                                               0x2e0
+#define mmDC_IP_REQUEST_CNTL                                                    0x2d2
+#define mmDC_PGFSM_CONFIG_REG                                                   0x2d3
+#define mmDC_PGFSM_WRITE_REG                                                    0x2d4
+#define mmDC_PGCNTL_STATUS_REG                                                  0x2d5
+#define mmDCPG_TEST_DEBUG_INDEX                                                 0x2d6
+#define mmDCPG_TEST_DEBUG_DATA                                                  0x2d7
+#define mmBL1_PWM_AMBIENT_LIGHT_LEVEL                                           0x1628
+#define mmBL1_PWM_USER_LEVEL                                                    0x1629
+#define mmBL1_PWM_TARGET_ABM_LEVEL                                              0x162a
+#define mmBL1_PWM_CURRENT_ABM_LEVEL                                             0x162b
+#define mmBL1_PWM_FINAL_DUTY_CYCLE                                              0x162c
+#define mmBL1_PWM_MINIMUM_DUTY_CYCLE                                            0x162d
+#define mmBL1_PWM_ABM_CNTL                                                      0x162e
+#define mmBL1_PWM_BL_UPDATE_SAMPLE_RATE                                         0x162f
+#define mmBL1_PWM_GRP2_REG_LOCK                                                 0x1630
+#define mmDC_ABM1_CNTL                                                          0x1638
+#define mmDC_ABM1_IPCSC_COEFF_SEL                                               0x1639
+#define mmDC_ABM1_ACE_OFFSET_SLOPE_0                                            0x163a
+#define mmDC_ABM1_ACE_OFFSET_SLOPE_1                                            0x163b
+#define mmDC_ABM1_ACE_OFFSET_SLOPE_2                                            0x163c
+#define mmDC_ABM1_ACE_OFFSET_SLOPE_3                                            0x163d
+#define mmDC_ABM1_ACE_OFFSET_SLOPE_4                                            0x163e
+#define mmDC_ABM1_ACE_THRES_12                                                  0x163f
+#define mmDC_ABM1_ACE_THRES_34                                                  0x1640
+#define mmDC_ABM1_ACE_CNTL_MISC                                                 0x1641
+#define mmDC_ABM1_DEBUG_MISC                                                    0x1649
+#define mmDC_ABM1_HGLS_REG_READ_PROGRESS                                        0x164a
+#define mmDC_ABM1_HG_MISC_CTRL                                                  0x164b
+#define mmDC_ABM1_LS_SUM_OF_LUMA                                                0x164c
+#define mmDC_ABM1_LS_MIN_MAX_LUMA                                               0x164d
+#define mmDC_ABM1_LS_FILTERED_MIN_MAX_LUMA                                      0x164e
+#define mmDC_ABM1_LS_PIXEL_COUNT                                                0x164f
+#define mmDC_ABM1_LS_OVR_SCAN_BIN                                               0x1650
+#define mmDC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES                                  0x1651
+#define mmDC_ABM1_LS_MIN_PIXEL_VALUE_COUNT                                      0x1652
+#define mmDC_ABM1_LS_MAX_PIXEL_VALUE_COUNT                                      0x1653
+#define mmDC_ABM1_HG_SAMPLE_RATE                                                0x1654
+#define mmDC_ABM1_LS_SAMPLE_RATE                                                0x1655
+#define mmDC_ABM1_HG_BIN_1_32_SHIFT_FLAG                                        0x1656
+#define mmDC_ABM1_HG_BIN_1_8_SHIFT_INDEX                                        0x1657
+#define mmDC_ABM1_HG_BIN_9_16_SHIFT_INDEX                                       0x1658
+#define mmDC_ABM1_HG_BIN_17_24_SHIFT_INDEX                                      0x1659
+#define mmDC_ABM1_HG_BIN_25_32_SHIFT_INDEX                                      0x165a
+#define mmDC_ABM1_HG_RESULT_1                                                   0x165b
+#define mmDC_ABM1_HG_RESULT_2                                                   0x165c
+#define mmDC_ABM1_HG_RESULT_3                                                   0x165d
+#define mmDC_ABM1_HG_RESULT_4                                                   0x165e
+#define mmDC_ABM1_HG_RESULT_5                                                   0x165f
+#define mmDC_ABM1_HG_RESULT_6                                                   0x1660
+#define mmDC_ABM1_HG_RESULT_7                                                   0x1661
+#define mmDC_ABM1_HG_RESULT_8                                                   0x1662
+#define mmDC_ABM1_HG_RESULT_9                                                   0x1663
+#define mmDC_ABM1_HG_RESULT_10                                                  0x1664
+#define mmDC_ABM1_HG_RESULT_11                                                  0x1665
+#define mmDC_ABM1_HG_RESULT_12                                                  0x1666
+#define mmDC_ABM1_HG_RESULT_13                                                  0x1667
+#define mmDC_ABM1_HG_RESULT_14                                                  0x1668
+#define mmDC_ABM1_HG_RESULT_15                                                  0x1669
+#define mmDC_ABM1_HG_RESULT_16                                                  0x166a
+#define mmDC_ABM1_HG_RESULT_17                                                  0x166b
+#define mmDC_ABM1_HG_RESULT_18                                                  0x166c
+#define mmDC_ABM1_HG_RESULT_19                                                  0x166d
+#define mmDC_ABM1_HG_RESULT_20                                                  0x166e
+#define mmDC_ABM1_HG_RESULT_21                                                  0x166f
+#define mmDC_ABM1_HG_RESULT_22                                                  0x1670
+#define mmDC_ABM1_HG_RESULT_23                                                  0x1671
+#define mmDC_ABM1_HG_RESULT_24                                                  0x1672
+#define mmDC_ABM1_OVERSCAN_PIXEL_VALUE                                          0x169b
+#define mmDC_ABM1_BL_MASTER_LOCK                                                0x169c
+#define mmABM_TEST_DEBUG_INDEX                                                  0x169e
+#define mmABM_TEST_DEBUG_DATA                                                   0x169f
+#define mmCRTC_H_BLANK_EARLY_NUM                                                0x1b7d
+#define mmCRTC0_CRTC_H_BLANK_EARLY_NUM                                          0x1b7d
+#define mmCRTC1_CRTC_H_BLANK_EARLY_NUM                                          0x1d7d
+#define mmCRTC2_CRTC_H_BLANK_EARLY_NUM                                          0x1f7d
+#define mmCRTC3_CRTC_H_BLANK_EARLY_NUM                                          0x417d
+#define mmCRTC4_CRTC_H_BLANK_EARLY_NUM                                          0x437d
+#define mmCRTC5_CRTC_H_BLANK_EARLY_NUM                                          0x457d
+#define mmCRTC_H_TOTAL                                                          0x1b80
+#define mmCRTC0_CRTC_H_TOTAL                                                    0x1b80
+#define mmCRTC1_CRTC_H_TOTAL                                                    0x1d80
+#define mmCRTC2_CRTC_H_TOTAL                                                    0x1f80
+#define mmCRTC3_CRTC_H_TOTAL                                                    0x4180
+#define mmCRTC4_CRTC_H_TOTAL                                                    0x4380
+#define mmCRTC5_CRTC_H_TOTAL                                                    0x4580
+#define mmCRTC_H_BLANK_START_END                                                0x1b81
+#define mmCRTC0_CRTC_H_BLANK_START_END                                          0x1b81
+#define mmCRTC1_CRTC_H_BLANK_START_END                                          0x1d81
+#define mmCRTC2_CRTC_H_BLANK_START_END                                          0x1f81
+#define mmCRTC3_CRTC_H_BLANK_START_END                                          0x4181
+#define mmCRTC4_CRTC_H_BLANK_START_END                                          0x4381
+#define mmCRTC5_CRTC_H_BLANK_START_END                                          0x4581
+#define mmCRTC_H_SYNC_A                                                         0x1b82
+#define mmCRTC0_CRTC_H_SYNC_A                                                   0x1b82
+#define mmCRTC1_CRTC_H_SYNC_A                                                   0x1d82
+#define mmCRTC2_CRTC_H_SYNC_A                                                   0x1f82
+#define mmCRTC3_CRTC_H_SYNC_A                                                   0x4182
+#define mmCRTC4_CRTC_H_SYNC_A                                                   0x4382
+#define mmCRTC5_CRTC_H_SYNC_A                                                   0x4582
+#define mmCRTC_H_SYNC_A_CNTL                                                    0x1b83
+#define mmCRTC0_CRTC_H_SYNC_A_CNTL                                              0x1b83
+#define mmCRTC1_CRTC_H_SYNC_A_CNTL                                              0x1d83
+#define mmCRTC2_CRTC_H_SYNC_A_CNTL                                              0x1f83
+#define mmCRTC3_CRTC_H_SYNC_A_CNTL                                              0x4183
+#define mmCRTC4_CRTC_H_SYNC_A_CNTL                                              0x4383
+#define mmCRTC5_CRTC_H_SYNC_A_CNTL                                              0x4583
+#define mmCRTC_H_SYNC_B                                                         0x1b84
+#define mmCRTC0_CRTC_H_SYNC_B                                                   0x1b84
+#define mmCRTC1_CRTC_H_SYNC_B                                                   0x1d84
+#define mmCRTC2_CRTC_H_SYNC_B                                                   0x1f84
+#define mmCRTC3_CRTC_H_SYNC_B                                                   0x4184
+#define mmCRTC4_CRTC_H_SYNC_B                                                   0x4384
+#define mmCRTC5_CRTC_H_SYNC_B                                                   0x4584
+#define mmCRTC_H_SYNC_B_CNTL                                                    0x1b85
+#define mmCRTC0_CRTC_H_SYNC_B_CNTL                                              0x1b85
+#define mmCRTC1_CRTC_H_SYNC_B_CNTL                                              0x1d85
+#define mmCRTC2_CRTC_H_SYNC_B_CNTL                                              0x1f85
+#define mmCRTC3_CRTC_H_SYNC_B_CNTL                                              0x4185
+#define mmCRTC4_CRTC_H_SYNC_B_CNTL                                              0x4385
+#define mmCRTC5_CRTC_H_SYNC_B_CNTL                                              0x4585
+#define mmCRTC_VBI_END                                                          0x1b86
+#define mmCRTC0_CRTC_VBI_END                                                    0x1b86
+#define mmCRTC1_CRTC_VBI_END                                                    0x1d86
+#define mmCRTC2_CRTC_VBI_END                                                    0x1f86
+#define mmCRTC3_CRTC_VBI_END                                                    0x4186
+#define mmCRTC4_CRTC_VBI_END                                                    0x4386
+#define mmCRTC5_CRTC_VBI_END                                                    0x4586
+#define mmCRTC_V_TOTAL                                                          0x1b87
+#define mmCRTC0_CRTC_V_TOTAL                                                    0x1b87
+#define mmCRTC1_CRTC_V_TOTAL                                                    0x1d87
+#define mmCRTC2_CRTC_V_TOTAL                                                    0x1f87
+#define mmCRTC3_CRTC_V_TOTAL                                                    0x4187
+#define mmCRTC4_CRTC_V_TOTAL                                                    0x4387
+#define mmCRTC5_CRTC_V_TOTAL                                                    0x4587
+#define mmCRTC_V_TOTAL_MIN                                                      0x1b88
+#define mmCRTC0_CRTC_V_TOTAL_MIN                                                0x1b88
+#define mmCRTC1_CRTC_V_TOTAL_MIN                                                0x1d88
+#define mmCRTC2_CRTC_V_TOTAL_MIN                                                0x1f88
+#define mmCRTC3_CRTC_V_TOTAL_MIN                                                0x4188
+#define mmCRTC4_CRTC_V_TOTAL_MIN                                                0x4388
+#define mmCRTC5_CRTC_V_TOTAL_MIN                                                0x4588
+#define mmCRTC_V_TOTAL_MAX                                                      0x1b89
+#define mmCRTC0_CRTC_V_TOTAL_MAX                                                0x1b89
+#define mmCRTC1_CRTC_V_TOTAL_MAX                                                0x1d89
+#define mmCRTC2_CRTC_V_TOTAL_MAX                                                0x1f89
+#define mmCRTC3_CRTC_V_TOTAL_MAX                                                0x4189
+#define mmCRTC4_CRTC_V_TOTAL_MAX                                                0x4389
+#define mmCRTC5_CRTC_V_TOTAL_MAX                                                0x4589
+#define mmCRTC_V_TOTAL_CONTROL                                                  0x1b8a
+#define mmCRTC0_CRTC_V_TOTAL_CONTROL                                            0x1b8a
+#define mmCRTC1_CRTC_V_TOTAL_CONTROL                                            0x1d8a
+#define mmCRTC2_CRTC_V_TOTAL_CONTROL                                            0x1f8a
+#define mmCRTC3_CRTC_V_TOTAL_CONTROL                                            0x418a
+#define mmCRTC4_CRTC_V_TOTAL_CONTROL                                            0x438a
+#define mmCRTC5_CRTC_V_TOTAL_CONTROL                                            0x458a
+#define mmCRTC_V_TOTAL_INT_STATUS                                               0x1b8b
+#define mmCRTC0_CRTC_V_TOTAL_INT_STATUS                                         0x1b8b
+#define mmCRTC1_CRTC_V_TOTAL_INT_STATUS                                         0x1d8b
+#define mmCRTC2_CRTC_V_TOTAL_INT_STATUS                                         0x1f8b
+#define mmCRTC3_CRTC_V_TOTAL_INT_STATUS                                         0x418b
+#define mmCRTC4_CRTC_V_TOTAL_INT_STATUS                                         0x438b
+#define mmCRTC5_CRTC_V_TOTAL_INT_STATUS                                         0x458b
+#define mmCRTC_VSYNC_NOM_INT_STATUS                                             0x1b8c
+#define mmCRTC0_CRTC_VSYNC_NOM_INT_STATUS                                       0x1b8c
+#define mmCRTC1_CRTC_VSYNC_NOM_INT_STATUS                                       0x1d8c
+#define mmCRTC2_CRTC_VSYNC_NOM_INT_STATUS                                       0x1f8c
+#define mmCRTC3_CRTC_VSYNC_NOM_INT_STATUS                                       0x418c
+#define mmCRTC4_CRTC_VSYNC_NOM_INT_STATUS                                       0x438c
+#define mmCRTC5_CRTC_VSYNC_NOM_INT_STATUS                                       0x458c
+#define mmCRTC_V_BLANK_START_END                                                0x1b8d
+#define mmCRTC0_CRTC_V_BLANK_START_END                                          0x1b8d
+#define mmCRTC1_CRTC_V_BLANK_START_END                                          0x1d8d
+#define mmCRTC2_CRTC_V_BLANK_START_END                                          0x1f8d
+#define mmCRTC3_CRTC_V_BLANK_START_END                                          0x418d
+#define mmCRTC4_CRTC_V_BLANK_START_END                                          0x438d
+#define mmCRTC5_CRTC_V_BLANK_START_END                                          0x458d
+#define mmCRTC_V_SYNC_A                                                         0x1b8e
+#define mmCRTC0_CRTC_V_SYNC_A                                                   0x1b8e
+#define mmCRTC1_CRTC_V_SYNC_A                                                   0x1d8e
+#define mmCRTC2_CRTC_V_SYNC_A                                                   0x1f8e
+#define mmCRTC3_CRTC_V_SYNC_A                                                   0x418e
+#define mmCRTC4_CRTC_V_SYNC_A                                                   0x438e
+#define mmCRTC5_CRTC_V_SYNC_A                                                   0x458e
+#define mmCRTC_V_SYNC_A_CNTL                                                    0x1b8f
+#define mmCRTC0_CRTC_V_SYNC_A_CNTL                                              0x1b8f
+#define mmCRTC1_CRTC_V_SYNC_A_CNTL                                              0x1d8f
+#define mmCRTC2_CRTC_V_SYNC_A_CNTL                                              0x1f8f
+#define mmCRTC3_CRTC_V_SYNC_A_CNTL                                              0x418f
+#define mmCRTC4_CRTC_V_SYNC_A_CNTL                                              0x438f
+#define mmCRTC5_CRTC_V_SYNC_A_CNTL                                              0x458f
+#define mmCRTC_V_SYNC_B                                                         0x1b90
+#define mmCRTC0_CRTC_V_SYNC_B                                                   0x1b90
+#define mmCRTC1_CRTC_V_SYNC_B                                                   0x1d90
+#define mmCRTC2_CRTC_V_SYNC_B                                                   0x1f90
+#define mmCRTC3_CRTC_V_SYNC_B                                                   0x4190
+#define mmCRTC4_CRTC_V_SYNC_B                                                   0x4390
+#define mmCRTC5_CRTC_V_SYNC_B                                                   0x4590
+#define mmCRTC_V_SYNC_B_CNTL                                                    0x1b91
+#define mmCRTC0_CRTC_V_SYNC_B_CNTL                                              0x1b91
+#define mmCRTC1_CRTC_V_SYNC_B_CNTL                                              0x1d91
+#define mmCRTC2_CRTC_V_SYNC_B_CNTL                                              0x1f91
+#define mmCRTC3_CRTC_V_SYNC_B_CNTL                                              0x4191
+#define mmCRTC4_CRTC_V_SYNC_B_CNTL                                              0x4391
+#define mmCRTC5_CRTC_V_SYNC_B_CNTL                                              0x4591
+#define mmCRTC_DTMTEST_CNTL                                                     0x1b92
+#define mmCRTC0_CRTC_DTMTEST_CNTL                                               0x1b92
+#define mmCRTC1_CRTC_DTMTEST_CNTL                                               0x1d92
+#define mmCRTC2_CRTC_DTMTEST_CNTL                                               0x1f92
+#define mmCRTC3_CRTC_DTMTEST_CNTL                                               0x4192
+#define mmCRTC4_CRTC_DTMTEST_CNTL                                               0x4392
+#define mmCRTC5_CRTC_DTMTEST_CNTL                                               0x4592
+#define mmCRTC_DTMTEST_STATUS_POSITION                                          0x1b93
+#define mmCRTC0_CRTC_DTMTEST_STATUS_POSITION                                    0x1b93
+#define mmCRTC1_CRTC_DTMTEST_STATUS_POSITION                                    0x1d93
+#define mmCRTC2_CRTC_DTMTEST_STATUS_POSITION                                    0x1f93
+#define mmCRTC3_CRTC_DTMTEST_STATUS_POSITION                                    0x4193
+#define mmCRTC4_CRTC_DTMTEST_STATUS_POSITION                                    0x4393
+#define mmCRTC5_CRTC_DTMTEST_STATUS_POSITION                                    0x4593
+#define mmCRTC_TRIGA_CNTL                                                       0x1b94
+#define mmCRTC0_CRTC_TRIGA_CNTL                                                 0x1b94
+#define mmCRTC1_CRTC_TRIGA_CNTL                                                 0x1d94
+#define mmCRTC2_CRTC_TRIGA_CNTL                                                 0x1f94
+#define mmCRTC3_CRTC_TRIGA_CNTL                                                 0x4194
+#define mmCRTC4_CRTC_TRIGA_CNTL                                                 0x4394
+#define mmCRTC5_CRTC_TRIGA_CNTL                                                 0x4594
+#define mmCRTC_TRIGA_MANUAL_TRIG                                                0x1b95
+#define mmCRTC0_CRTC_TRIGA_MANUAL_TRIG                                          0x1b95
+#define mmCRTC1_CRTC_TRIGA_MANUAL_TRIG                                          0x1d95
+#define mmCRTC2_CRTC_TRIGA_MANUAL_TRIG                                          0x1f95
+#define mmCRTC3_CRTC_TRIGA_MANUAL_TRIG                                          0x4195
+#define mmCRTC4_CRTC_TRIGA_MANUAL_TRIG                                          0x4395
+#define mmCRTC5_CRTC_TRIGA_MANUAL_TRIG                                          0x4595
+#define mmCRTC_TRIGB_CNTL                                                       0x1b96
+#define mmCRTC0_CRTC_TRIGB_CNTL                                                 0x1b96
+#define mmCRTC1_CRTC_TRIGB_CNTL                                                 0x1d96
+#define mmCRTC2_CRTC_TRIGB_CNTL                                                 0x1f96
+#define mmCRTC3_CRTC_TRIGB_CNTL                                                 0x4196
+#define mmCRTC4_CRTC_TRIGB_CNTL                                                 0x4396
+#define mmCRTC5_CRTC_TRIGB_CNTL                                                 0x4596
+#define mmCRTC_TRIGB_MANUAL_TRIG                                                0x1b97
+#define mmCRTC0_CRTC_TRIGB_MANUAL_TRIG                                          0x1b97
+#define mmCRTC1_CRTC_TRIGB_MANUAL_TRIG                                          0x1d97
+#define mmCRTC2_CRTC_TRIGB_MANUAL_TRIG                                          0x1f97
+#define mmCRTC3_CRTC_TRIGB_MANUAL_TRIG                                          0x4197
+#define mmCRTC4_CRTC_TRIGB_MANUAL_TRIG                                          0x4397
+#define mmCRTC5_CRTC_TRIGB_MANUAL_TRIG                                          0x4597
+#define mmCRTC_FORCE_COUNT_NOW_CNTL                                             0x1b98
+#define mmCRTC0_CRTC_FORCE_COUNT_NOW_CNTL                                       0x1b98
+#define mmCRTC1_CRTC_FORCE_COUNT_NOW_CNTL                                       0x1d98
+#define mmCRTC2_CRTC_FORCE_COUNT_NOW_CNTL                                       0x1f98
+#define mmCRTC3_CRTC_FORCE_COUNT_NOW_CNTL                                       0x4198
+#define mmCRTC4_CRTC_FORCE_COUNT_NOW_CNTL                                       0x4398
+#define mmCRTC5_CRTC_FORCE_COUNT_NOW_CNTL                                       0x4598
+#define mmCRTC_FLOW_CONTROL                                                     0x1b99
+#define mmCRTC0_CRTC_FLOW_CONTROL                                               0x1b99
+#define mmCRTC1_CRTC_FLOW_CONTROL                                               0x1d99
+#define mmCRTC2_CRTC_FLOW_CONTROL                                               0x1f99
+#define mmCRTC3_CRTC_FLOW_CONTROL                                               0x4199
+#define mmCRTC4_CRTC_FLOW_CONTROL                                               0x4399
+#define mmCRTC5_CRTC_FLOW_CONTROL                                               0x4599
+#define mmCRTC_STEREO_FORCE_NEXT_EYE                                            0x1b9a
+#define mmCRTC0_CRTC_STEREO_FORCE_NEXT_EYE                                      0x1b9a
+#define mmCRTC1_CRTC_STEREO_FORCE_NEXT_EYE                                      0x1d9a
+#define mmCRTC2_CRTC_STEREO_FORCE_NEXT_EYE                                      0x1f9a
+#define mmCRTC3_CRTC_STEREO_FORCE_NEXT_EYE                                      0x419a
+#define mmCRTC4_CRTC_STEREO_FORCE_NEXT_EYE                                      0x439a
+#define mmCRTC5_CRTC_STEREO_FORCE_NEXT_EYE                                      0x459a
+#define mmCRTC_AVSYNC_COUNTER                                                   0x1b9b
+#define mmCRTC0_CRTC_AVSYNC_COUNTER                                             0x1b9b
+#define mmCRTC1_CRTC_AVSYNC_COUNTER                                             0x1d9b
+#define mmCRTC2_CRTC_AVSYNC_COUNTER                                             0x1f9b
+#define mmCRTC3_CRTC_AVSYNC_COUNTER                                             0x419b
+#define mmCRTC4_CRTC_AVSYNC_COUNTER                                             0x439b
+#define mmCRTC5_CRTC_AVSYNC_COUNTER                                             0x459b
+#define mmCRTC_CONTROL                                                          0x1b9c
+#define mmCRTC0_CRTC_CONTROL                                                    0x1b9c
+#define mmCRTC1_CRTC_CONTROL                                                    0x1d9c
+#define mmCRTC2_CRTC_CONTROL                                                    0x1f9c
+#define mmCRTC3_CRTC_CONTROL                                                    0x419c
+#define mmCRTC4_CRTC_CONTROL                                                    0x439c
+#define mmCRTC5_CRTC_CONTROL                                                    0x459c
+#define mmCRTC_BLANK_CONTROL                                                    0x1b9d
+#define mmCRTC0_CRTC_BLANK_CONTROL                                              0x1b9d
+#define mmCRTC1_CRTC_BLANK_CONTROL                                              0x1d9d
+#define mmCRTC2_CRTC_BLANK_CONTROL                                              0x1f9d
+#define mmCRTC3_CRTC_BLANK_CONTROL                                              0x419d
+#define mmCRTC4_CRTC_BLANK_CONTROL                                              0x439d
+#define mmCRTC5_CRTC_BLANK_CONTROL                                              0x459d
+#define mmCRTC_INTERLACE_CONTROL                                                0x1b9e
+#define mmCRTC0_CRTC_INTERLACE_CONTROL                                          0x1b9e
+#define mmCRTC1_CRTC_INTERLACE_CONTROL                                          0x1d9e
+#define mmCRTC2_CRTC_INTERLACE_CONTROL                                          0x1f9e
+#define mmCRTC3_CRTC_INTERLACE_CONTROL                                          0x419e
+#define mmCRTC4_CRTC_INTERLACE_CONTROL                                          0x439e
+#define mmCRTC5_CRTC_INTERLACE_CONTROL                                          0x459e
+#define mmCRTC_INTERLACE_STATUS                                                 0x1b9f
+#define mmCRTC0_CRTC_INTERLACE_STATUS                                           0x1b9f
+#define mmCRTC1_CRTC_INTERLACE_STATUS                                           0x1d9f
+#define mmCRTC2_CRTC_INTERLACE_STATUS                                           0x1f9f
+#define mmCRTC3_CRTC_INTERLACE_STATUS                                           0x419f
+#define mmCRTC4_CRTC_INTERLACE_STATUS                                           0x439f
+#define mmCRTC5_CRTC_INTERLACE_STATUS                                           0x459f
+#define mmCRTC_FIELD_INDICATION_CONTROL                                         0x1ba0
+#define mmCRTC0_CRTC_FIELD_INDICATION_CONTROL                                   0x1ba0
+#define mmCRTC1_CRTC_FIELD_INDICATION_CONTROL                                   0x1da0
+#define mmCRTC2_CRTC_FIELD_INDICATION_CONTROL                                   0x1fa0
+#define mmCRTC3_CRTC_FIELD_INDICATION_CONTROL                                   0x41a0
+#define mmCRTC4_CRTC_FIELD_INDICATION_CONTROL                                   0x43a0
+#define mmCRTC5_CRTC_FIELD_INDICATION_CONTROL                                   0x45a0
+#define mmCRTC_PIXEL_DATA_READBACK0                                             0x1ba1
+#define mmCRTC0_CRTC_PIXEL_DATA_READBACK0                                       0x1ba1
+#define mmCRTC1_CRTC_PIXEL_DATA_READBACK0                                       0x1da1
+#define mmCRTC2_CRTC_PIXEL_DATA_READBACK0                                       0x1fa1
+#define mmCRTC3_CRTC_PIXEL_DATA_READBACK0                                       0x41a1
+#define mmCRTC4_CRTC_PIXEL_DATA_READBACK0                                       0x43a1
+#define mmCRTC5_CRTC_PIXEL_DATA_READBACK0                                       0x45a1
+#define mmCRTC_PIXEL_DATA_READBACK1                                             0x1ba2
+#define mmCRTC0_CRTC_PIXEL_DATA_READBACK1                                       0x1ba2
+#define mmCRTC1_CRTC_PIXEL_DATA_READBACK1                                       0x1da2
+#define mmCRTC2_CRTC_PIXEL_DATA_READBACK1                                       0x1fa2
+#define mmCRTC3_CRTC_PIXEL_DATA_READBACK1                                       0x41a2
+#define mmCRTC4_CRTC_PIXEL_DATA_READBACK1                                       0x43a2
+#define mmCRTC5_CRTC_PIXEL_DATA_READBACK1                                       0x45a2
+#define mmCRTC_STATUS                                                           0x1ba3
+#define mmCRTC0_CRTC_STATUS                                                     0x1ba3
+#define mmCRTC1_CRTC_STATUS                                                     0x1da3
+#define mmCRTC2_CRTC_STATUS                                                     0x1fa3
+#define mmCRTC3_CRTC_STATUS                                                     0x41a3
+#define mmCRTC4_CRTC_STATUS                                                     0x43a3
+#define mmCRTC5_CRTC_STATUS                                                     0x45a3
+#define mmCRTC_STATUS_POSITION                                                  0x1ba4
+#define mmCRTC0_CRTC_STATUS_POSITION                                            0x1ba4
+#define mmCRTC1_CRTC_STATUS_POSITION                                            0x1da4
+#define mmCRTC2_CRTC_STATUS_POSITION                                            0x1fa4
+#define mmCRTC3_CRTC_STATUS_POSITION                                            0x41a4
+#define mmCRTC4_CRTC_STATUS_POSITION                                            0x43a4
+#define mmCRTC5_CRTC_STATUS_POSITION                                            0x45a4
+#define mmCRTC_NOM_VERT_POSITION                                                0x1ba5
+#define mmCRTC0_CRTC_NOM_VERT_POSITION                                          0x1ba5
+#define mmCRTC1_CRTC_NOM_VERT_POSITION                                          0x1da5
+#define mmCRTC2_CRTC_NOM_VERT_POSITION                                          0x1fa5
+#define mmCRTC3_CRTC_NOM_VERT_POSITION                                          0x41a5
+#define mmCRTC4_CRTC_NOM_VERT_POSITION                                          0x43a5
+#define mmCRTC5_CRTC_NOM_VERT_POSITION                                          0x45a5
+#define mmCRTC_STATUS_FRAME_COUNT                                               0x1ba6
+#define mmCRTC0_CRTC_STATUS_FRAME_COUNT                                         0x1ba6
+#define mmCRTC1_CRTC_STATUS_FRAME_COUNT                                         0x1da6
+#define mmCRTC2_CRTC_STATUS_FRAME_COUNT                                         0x1fa6
+#define mmCRTC3_CRTC_STATUS_FRAME_COUNT                                         0x41a6
+#define mmCRTC4_CRTC_STATUS_FRAME_COUNT                                         0x43a6
+#define mmCRTC5_CRTC_STATUS_FRAME_COUNT                                         0x45a6
+#define mmCRTC_STATUS_VF_COUNT                                                  0x1ba7
+#define mmCRTC0_CRTC_STATUS_VF_COUNT                                            0x1ba7
+#define mmCRTC1_CRTC_STATUS_VF_COUNT                                            0x1da7
+#define mmCRTC2_CRTC_STATUS_VF_COUNT                                            0x1fa7
+#define mmCRTC3_CRTC_STATUS_VF_COUNT                                            0x41a7
+#define mmCRTC4_CRTC_STATUS_VF_COUNT                                            0x43a7
+#define mmCRTC5_CRTC_STATUS_VF_COUNT                                            0x45a7
+#define mmCRTC_STATUS_HV_COUNT                                                  0x1ba8
+#define mmCRTC0_CRTC_STATUS_HV_COUNT                                            0x1ba8
+#define mmCRTC1_CRTC_STATUS_HV_COUNT                                            0x1da8
+#define mmCRTC2_CRTC_STATUS_HV_COUNT                                            0x1fa8
+#define mmCRTC3_CRTC_STATUS_HV_COUNT                                            0x41a8
+#define mmCRTC4_CRTC_STATUS_HV_COUNT                                            0x43a8
+#define mmCRTC5_CRTC_STATUS_HV_COUNT                                            0x45a8
+#define mmCRTC_COUNT_CONTROL                                                    0x1ba9
+#define mmCRTC0_CRTC_COUNT_CONTROL                                              0x1ba9
+#define mmCRTC1_CRTC_COUNT_CONTROL                                              0x1da9
+#define mmCRTC2_CRTC_COUNT_CONTROL                                              0x1fa9
+#define mmCRTC3_CRTC_COUNT_CONTROL                                              0x41a9
+#define mmCRTC4_CRTC_COUNT_CONTROL                                              0x43a9
+#define mmCRTC5_CRTC_COUNT_CONTROL                                              0x45a9
+#define mmCRTC_COUNT_RESET                                                      0x1baa
+#define mmCRTC0_CRTC_COUNT_RESET                                                0x1baa
+#define mmCRTC1_CRTC_COUNT_RESET                                                0x1daa
+#define mmCRTC2_CRTC_COUNT_RESET                                                0x1faa
+#define mmCRTC3_CRTC_COUNT_RESET                                                0x41aa
+#define mmCRTC4_CRTC_COUNT_RESET                                                0x43aa
+#define mmCRTC5_CRTC_COUNT_RESET                                                0x45aa
+#define mmCRTC_MANUAL_FORCE_VSYNC_NEXT_LINE                                     0x1bab
+#define mmCRTC0_CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE                               0x1bab
+#define mmCRTC1_CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE                               0x1dab
+#define mmCRTC2_CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE                               0x1fab
+#define mmCRTC3_CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE                               0x41ab
+#define mmCRTC4_CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE                               0x43ab
+#define mmCRTC5_CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE                               0x45ab
+#define mmCRTC_VERT_SYNC_CONTROL                                                0x1bac
+#define mmCRTC0_CRTC_VERT_SYNC_CONTROL                                          0x1bac
+#define mmCRTC1_CRTC_VERT_SYNC_CONTROL                                          0x1dac
+#define mmCRTC2_CRTC_VERT_SYNC_CONTROL                                          0x1fac
+#define mmCRTC3_CRTC_VERT_SYNC_CONTROL                                          0x41ac
+#define mmCRTC4_CRTC_VERT_SYNC_CONTROL                                          0x43ac
+#define mmCRTC5_CRTC_VERT_SYNC_CONTROL                                          0x45ac
+#define mmCRTC_STEREO_STATUS                                                    0x1bad
+#define mmCRTC0_CRTC_STEREO_STATUS                                              0x1bad
+#define mmCRTC1_CRTC_STEREO_STATUS                                              0x1dad
+#define mmCRTC2_CRTC_STEREO_STATUS                                              0x1fad
+#define mmCRTC3_CRTC_STEREO_STATUS                                              0x41ad
+#define mmCRTC4_CRTC_STEREO_STATUS                                              0x43ad
+#define mmCRTC5_CRTC_STEREO_STATUS                                              0x45ad
+#define mmCRTC_STEREO_CONTROL                                                   0x1bae
+#define mmCRTC0_CRTC_STEREO_CONTROL                                             0x1bae
+#define mmCRTC1_CRTC_STEREO_CONTROL                                             0x1dae
+#define mmCRTC2_CRTC_STEREO_CONTROL                                             0x1fae
+#define mmCRTC3_CRTC_STEREO_CONTROL                                             0x41ae
+#define mmCRTC4_CRTC_STEREO_CONTROL                                             0x43ae
+#define mmCRTC5_CRTC_STEREO_CONTROL                                             0x45ae
+#define mmCRTC_SNAPSHOT_STATUS                                                  0x1baf
+#define mmCRTC0_CRTC_SNAPSHOT_STATUS                                            0x1baf
+#define mmCRTC1_CRTC_SNAPSHOT_STATUS                                            0x1daf
+#define mmCRTC2_CRTC_SNAPSHOT_STATUS                                            0x1faf
+#define mmCRTC3_CRTC_SNAPSHOT_STATUS                                            0x41af
+#define mmCRTC4_CRTC_SNAPSHOT_STATUS                                            0x43af
+#define mmCRTC5_CRTC_SNAPSHOT_STATUS                                            0x45af
+#define mmCRTC_SNAPSHOT_CONTROL                                                 0x1bb0
+#define mmCRTC0_CRTC_SNAPSHOT_CONTROL                                           0x1bb0
+#define mmCRTC1_CRTC_SNAPSHOT_CONTROL                                           0x1db0
+#define mmCRTC2_CRTC_SNAPSHOT_CONTROL                                           0x1fb0
+#define mmCRTC3_CRTC_SNAPSHOT_CONTROL                                           0x41b0
+#define mmCRTC4_CRTC_SNAPSHOT_CONTROL                                           0x43b0
+#define mmCRTC5_CRTC_SNAPSHOT_CONTROL                                           0x45b0
+#define mmCRTC_SNAPSHOT_POSITION                                                0x1bb1
+#define mmCRTC0_CRTC_SNAPSHOT_POSITION                                          0x1bb1
+#define mmCRTC1_CRTC_SNAPSHOT_POSITION                                          0x1db1
+#define mmCRTC2_CRTC_SNAPSHOT_POSITION                                          0x1fb1
+#define mmCRTC3_CRTC_SNAPSHOT_POSITION                                          0x41b1
+#define mmCRTC4_CRTC_SNAPSHOT_POSITION                                          0x43b1
+#define mmCRTC5_CRTC_SNAPSHOT_POSITION                                          0x45b1
+#define mmCRTC_SNAPSHOT_FRAME                                                   0x1bb2
+#define mmCRTC0_CRTC_SNAPSHOT_FRAME                                             0x1bb2
+#define mmCRTC1_CRTC_SNAPSHOT_FRAME                                             0x1db2
+#define mmCRTC2_CRTC_SNAPSHOT_FRAME                                             0x1fb2
+#define mmCRTC3_CRTC_SNAPSHOT_FRAME                                             0x41b2
+#define mmCRTC4_CRTC_SNAPSHOT_FRAME                                             0x43b2
+#define mmCRTC5_CRTC_SNAPSHOT_FRAME                                             0x45b2
+#define mmCRTC_START_LINE_CONTROL                                               0x1bb3
+#define mmCRTC0_CRTC_START_LINE_CONTROL                                         0x1bb3
+#define mmCRTC1_CRTC_START_LINE_CONTROL                                         0x1db3
+#define mmCRTC2_CRTC_START_LINE_CONTROL                                         0x1fb3
+#define mmCRTC3_CRTC_START_LINE_CONTROL                                         0x41b3
+#define mmCRTC4_CRTC_START_LINE_CONTROL                                         0x43b3
+#define mmCRTC5_CRTC_START_LINE_CONTROL                                         0x45b3
+#define mmCRTC_INTERRUPT_CONTROL                                                0x1bb4
+#define mmCRTC0_CRTC_INTERRUPT_CONTROL                                          0x1bb4
+#define mmCRTC1_CRTC_INTERRUPT_CONTROL                                          0x1db4
+#define mmCRTC2_CRTC_INTERRUPT_CONTROL                                          0x1fb4
+#define mmCRTC3_CRTC_INTERRUPT_CONTROL                                          0x41b4
+#define mmCRTC4_CRTC_INTERRUPT_CONTROL                                          0x43b4
+#define mmCRTC5_CRTC_INTERRUPT_CONTROL                                          0x45b4
+#define mmCRTC_UPDATE_LOCK                                                      0x1bb5
+#define mmCRTC0_CRTC_UPDATE_LOCK                                                0x1bb5
+#define mmCRTC1_CRTC_UPDATE_LOCK                                                0x1db5
+#define mmCRTC2_CRTC_UPDATE_LOCK                                                0x1fb5
+#define mmCRTC3_CRTC_UPDATE_LOCK                                                0x41b5
+#define mmCRTC4_CRTC_UPDATE_LOCK                                                0x43b5
+#define mmCRTC5_CRTC_UPDATE_LOCK                                                0x45b5
+#define mmCRTC_DOUBLE_BUFFER_CONTROL                                            0x1bb6
+#define mmCRTC0_CRTC_DOUBLE_BUFFER_CONTROL                                      0x1bb6
+#define mmCRTC1_CRTC_DOUBLE_BUFFER_CONTROL                                      0x1db6
+#define mmCRTC2_CRTC_DOUBLE_BUFFER_CONTROL                                      0x1fb6
+#define mmCRTC3_CRTC_DOUBLE_BUFFER_CONTROL                                      0x41b6
+#define mmCRTC4_CRTC_DOUBLE_BUFFER_CONTROL                                      0x43b6
+#define mmCRTC5_CRTC_DOUBLE_BUFFER_CONTROL                                      0x45b6
+#define mmCRTC_VGA_PARAMETER_CAPTURE_MODE                                       0x1bb7
+#define mmCRTC0_CRTC_VGA_PARAMETER_CAPTURE_MODE                                 0x1bb7
+#define mmCRTC1_CRTC_VGA_PARAMETER_CAPTURE_MODE                                 0x1db7
+#define mmCRTC2_CRTC_VGA_PARAMETER_CAPTURE_MODE                                 0x1fb7
+#define mmCRTC3_CRTC_VGA_PARAMETER_CAPTURE_MODE                                 0x41b7
+#define mmCRTC4_CRTC_VGA_PARAMETER_CAPTURE_MODE                                 0x43b7
+#define mmCRTC5_CRTC_VGA_PARAMETER_CAPTURE_MODE                                 0x45b7
+#define mmCRTC_TEST_PATTERN_CONTROL                                             0x1bba
+#define mmCRTC0_CRTC_TEST_PATTERN_CONTROL                                       0x1bba
+#define mmCRTC1_CRTC_TEST_PATTERN_CONTROL                                       0x1dba
+#define mmCRTC2_CRTC_TEST_PATTERN_CONTROL                                       0x1fba
+#define mmCRTC3_CRTC_TEST_PATTERN_CONTROL                                       0x41ba
+#define mmCRTC4_CRTC_TEST_PATTERN_CONTROL                                       0x43ba
+#define mmCRTC5_CRTC_TEST_PATTERN_CONTROL                                       0x45ba
+#define mmCRTC_TEST_PATTERN_PARAMETERS                                          0x1bbb
+#define mmCRTC0_CRTC_TEST_PATTERN_PARAMETERS                                    0x1bbb
+#define mmCRTC1_CRTC_TEST_PATTERN_PARAMETERS                                    0x1dbb
+#define mmCRTC2_CRTC_TEST_PATTERN_PARAMETERS                                    0x1fbb
+#define mmCRTC3_CRTC_TEST_PATTERN_PARAMETERS                                    0x41bb
+#define mmCRTC4_CRTC_TEST_PATTERN_PARAMETERS                                    0x43bb
+#define mmCRTC5_CRTC_TEST_PATTERN_PARAMETERS                                    0x45bb
+#define mmCRTC_TEST_PATTERN_COLOR                                               0x1bbc
+#define mmCRTC0_CRTC_TEST_PATTERN_COLOR                                         0x1bbc
+#define mmCRTC1_CRTC_TEST_PATTERN_COLOR                                         0x1dbc
+#define mmCRTC2_CRTC_TEST_PATTERN_COLOR                                         0x1fbc
+#define mmCRTC3_CRTC_TEST_PATTERN_COLOR                                         0x41bc
+#define mmCRTC4_CRTC_TEST_PATTERN_COLOR                                         0x43bc
+#define mmCRTC5_CRTC_TEST_PATTERN_COLOR                                         0x45bc
+#define mmCRTC_MASTER_UPDATE_LOCK                                               0x1bbd
+#define mmCRTC0_CRTC_MASTER_UPDATE_LOCK                                         0x1bbd
+#define mmCRTC1_CRTC_MASTER_UPDATE_LOCK                                         0x1dbd
+#define mmCRTC2_CRTC_MASTER_UPDATE_LOCK                                         0x1fbd
+#define mmCRTC3_CRTC_MASTER_UPDATE_LOCK                                         0x41bd
+#define mmCRTC4_CRTC_MASTER_UPDATE_LOCK                                         0x43bd
+#define mmCRTC5_CRTC_MASTER_UPDATE_LOCK                                         0x45bd
+#define mmCRTC_MASTER_UPDATE_MODE                                               0x1bbe
+#define mmCRTC0_CRTC_MASTER_UPDATE_MODE                                         0x1bbe
+#define mmCRTC1_CRTC_MASTER_UPDATE_MODE                                         0x1dbe
+#define mmCRTC2_CRTC_MASTER_UPDATE_MODE                                         0x1fbe
+#define mmCRTC3_CRTC_MASTER_UPDATE_MODE                                         0x41be
+#define mmCRTC4_CRTC_MASTER_UPDATE_MODE                                         0x43be
+#define mmCRTC5_CRTC_MASTER_UPDATE_MODE                                         0x45be
+#define mmCRTC_MVP_INBAND_CNTL_INSERT                                           0x1bbf
+#define mmCRTC0_CRTC_MVP_INBAND_CNTL_INSERT                                     0x1bbf
+#define mmCRTC1_CRTC_MVP_INBAND_CNTL_INSERT                                     0x1dbf
+#define mmCRTC2_CRTC_MVP_INBAND_CNTL_INSERT                                     0x1fbf
+#define mmCRTC3_CRTC_MVP_INBAND_CNTL_INSERT                                     0x41bf
+#define mmCRTC4_CRTC_MVP_INBAND_CNTL_INSERT                                     0x43bf
+#define mmCRTC5_CRTC_MVP_INBAND_CNTL_INSERT                                     0x45bf
+#define mmCRTC_MVP_INBAND_CNTL_INSERT_TIMER                                     0x1bc0
+#define mmCRTC0_CRTC_MVP_INBAND_CNTL_INSERT_TIMER                               0x1bc0
+#define mmCRTC1_CRTC_MVP_INBAND_CNTL_INSERT_TIMER                               0x1dc0
+#define mmCRTC2_CRTC_MVP_INBAND_CNTL_INSERT_TIMER                               0x1fc0
+#define mmCRTC3_CRTC_MVP_INBAND_CNTL_INSERT_TIMER                               0x41c0
+#define mmCRTC4_CRTC_MVP_INBAND_CNTL_INSERT_TIMER                               0x43c0
+#define mmCRTC5_CRTC_MVP_INBAND_CNTL_INSERT_TIMER                               0x45c0
+#define mmCRTC_MVP_STATUS                                                       0x1bc1
+#define mmCRTC0_CRTC_MVP_STATUS                                                 0x1bc1
+#define mmCRTC1_CRTC_MVP_STATUS                                                 0x1dc1
+#define mmCRTC2_CRTC_MVP_STATUS                                                 0x1fc1
+#define mmCRTC3_CRTC_MVP_STATUS                                                 0x41c1
+#define mmCRTC4_CRTC_MVP_STATUS                                                 0x43c1
+#define mmCRTC5_CRTC_MVP_STATUS                                                 0x45c1
+#define mmCRTC_MASTER_EN                                                        0x1bc2
+#define mmCRTC0_CRTC_MASTER_EN                                                  0x1bc2
+#define mmCRTC1_CRTC_MASTER_EN                                                  0x1dc2
+#define mmCRTC2_CRTC_MASTER_EN                                                  0x1fc2
+#define mmCRTC3_CRTC_MASTER_EN                                                  0x41c2
+#define mmCRTC4_CRTC_MASTER_EN                                                  0x43c2
+#define mmCRTC5_CRTC_MASTER_EN                                                  0x45c2
+#define mmCRTC_ALLOW_STOP_OFF_V_CNT                                             0x1bc3
+#define mmCRTC0_CRTC_ALLOW_STOP_OFF_V_CNT                                       0x1bc3
+#define mmCRTC1_CRTC_ALLOW_STOP_OFF_V_CNT                                       0x1dc3
+#define mmCRTC2_CRTC_ALLOW_STOP_OFF_V_CNT                                       0x1fc3
+#define mmCRTC3_CRTC_ALLOW_STOP_OFF_V_CNT                                       0x41c3
+#define mmCRTC4_CRTC_ALLOW_STOP_OFF_V_CNT                                       0x43c3
+#define mmCRTC5_CRTC_ALLOW_STOP_OFF_V_CNT                                       0x45c3
+#define mmCRTC_V_UPDATE_INT_STATUS                                              0x1bc4
+#define mmCRTC0_CRTC_V_UPDATE_INT_STATUS                                        0x1bc4
+#define mmCRTC1_CRTC_V_UPDATE_INT_STATUS                                        0x1dc4
+#define mmCRTC2_CRTC_V_UPDATE_INT_STATUS                                        0x1fc4
+#define mmCRTC3_CRTC_V_UPDATE_INT_STATUS                                        0x41c4
+#define mmCRTC4_CRTC_V_UPDATE_INT_STATUS                                        0x43c4
+#define mmCRTC5_CRTC_V_UPDATE_INT_STATUS                                        0x45c4
+#define mmCRTC_OVERSCAN_COLOR                                                   0x1bc8
+#define mmCRTC0_CRTC_OVERSCAN_COLOR                                             0x1bc8
+#define mmCRTC1_CRTC_OVERSCAN_COLOR                                             0x1dc8
+#define mmCRTC2_CRTC_OVERSCAN_COLOR                                             0x1fc8
+#define mmCRTC3_CRTC_OVERSCAN_COLOR                                             0x41c8
+#define mmCRTC4_CRTC_OVERSCAN_COLOR                                             0x43c8
+#define mmCRTC5_CRTC_OVERSCAN_COLOR                                             0x45c8
+#define mmCRTC_OVERSCAN_COLOR_EXT                                               0x1bc9
+#define mmCRTC0_CRTC_OVERSCAN_COLOR_EXT                                         0x1bc9
+#define mmCRTC1_CRTC_OVERSCAN_COLOR_EXT                                         0x1dc9
+#define mmCRTC2_CRTC_OVERSCAN_COLOR_EXT                                         0x1fc9
+#define mmCRTC3_CRTC_OVERSCAN_COLOR_EXT                                         0x41c9
+#define mmCRTC4_CRTC_OVERSCAN_COLOR_EXT                                         0x43c9
+#define mmCRTC5_CRTC_OVERSCAN_COLOR_EXT                                         0x45c9
+#define mmCRTC_BLANK_DATA_COLOR                                                 0x1bca
+#define mmCRTC0_CRTC_BLANK_DATA_COLOR                                           0x1bca
+#define mmCRTC1_CRTC_BLANK_DATA_COLOR                                           0x1dca
+#define mmCRTC2_CRTC_BLANK_DATA_COLOR                                           0x1fca
+#define mmCRTC3_CRTC_BLANK_DATA_COLOR                                           0x41ca
+#define mmCRTC4_CRTC_BLANK_DATA_COLOR                                           0x43ca
+#define mmCRTC5_CRTC_BLANK_DATA_COLOR                                           0x45ca
+#define mmCRTC_BLANK_DATA_COLOR_EXT                                             0x1bcb
+#define mmCRTC0_CRTC_BLANK_DATA_COLOR_EXT                                       0x1bcb
+#define mmCRTC1_CRTC_BLANK_DATA_COLOR_EXT                                       0x1dcb
+#define mmCRTC2_CRTC_BLANK_DATA_COLOR_EXT                                       0x1fcb
+#define mmCRTC3_CRTC_BLANK_DATA_COLOR_EXT                                       0x41cb
+#define mmCRTC4_CRTC_BLANK_DATA_COLOR_EXT                                       0x43cb
+#define mmCRTC5_CRTC_BLANK_DATA_COLOR_EXT                                       0x45cb
+#define mmCRTC_BLACK_COLOR                                                      0x1bcc
+#define mmCRTC0_CRTC_BLACK_COLOR                                                0x1bcc
+#define mmCRTC1_CRTC_BLACK_COLOR                                                0x1dcc
+#define mmCRTC2_CRTC_BLACK_COLOR                                                0x1fcc
+#define mmCRTC3_CRTC_BLACK_COLOR                                                0x41cc
+#define mmCRTC4_CRTC_BLACK_COLOR                                                0x43cc
+#define mmCRTC5_CRTC_BLACK_COLOR                                                0x45cc
+#define mmCRTC_BLACK_COLOR_EXT                                                  0x1bcd
+#define mmCRTC0_CRTC_BLACK_COLOR_EXT                                            0x1bcd
+#define mmCRTC1_CRTC_BLACK_COLOR_EXT                                            0x1dcd
+#define mmCRTC2_CRTC_BLACK_COLOR_EXT                                            0x1fcd
+#define mmCRTC3_CRTC_BLACK_COLOR_EXT                                            0x41cd
+#define mmCRTC4_CRTC_BLACK_COLOR_EXT                                            0x43cd
+#define mmCRTC5_CRTC_BLACK_COLOR_EXT                                            0x45cd
+#define mmCRTC_VERTICAL_INTERRUPT0_POSITION                                     0x1bce
+#define mmCRTC0_CRTC_VERTICAL_INTERRUPT0_POSITION                               0x1bce
+#define mmCRTC1_CRTC_VERTICAL_INTERRUPT0_POSITION                               0x1dce
+#define mmCRTC2_CRTC_VERTICAL_INTERRUPT0_POSITION                               0x1fce
+#define mmCRTC3_CRTC_VERTICAL_INTERRUPT0_POSITION                               0x41ce
+#define mmCRTC4_CRTC_VERTICAL_INTERRUPT0_POSITION                               0x43ce
+#define mmCRTC5_CRTC_VERTICAL_INTERRUPT0_POSITION                               0x45ce
+#define mmCRTC_VERTICAL_INTERRUPT0_CONTROL                                      0x1bcf
+#define mmCRTC0_CRTC_VERTICAL_INTERRUPT0_CONTROL                                0x1bcf
+#define mmCRTC1_CRTC_VERTICAL_INTERRUPT0_CONTROL                                0x1dcf
+#define mmCRTC2_CRTC_VERTICAL_INTERRUPT0_CONTROL                                0x1fcf
+#define mmCRTC3_CRTC_VERTICAL_INTERRUPT0_CONTROL                                0x41cf
+#define mmCRTC4_CRTC_VERTICAL_INTERRUPT0_CONTROL                                0x43cf
+#define mmCRTC5_CRTC_VERTICAL_INTERRUPT0_CONTROL                                0x45cf
+#define mmCRTC_VERTICAL_INTERRUPT1_POSITION                                     0x1bd0
+#define mmCRTC0_CRTC_VERTICAL_INTERRUPT1_POSITION                               0x1bd0
+#define mmCRTC1_CRTC_VERTICAL_INTERRUPT1_POSITION                               0x1dd0
+#define mmCRTC2_CRTC_VERTICAL_INTERRUPT1_POSITION                               0x1fd0
+#define mmCRTC3_CRTC_VERTICAL_INTERRUPT1_POSITION                               0x41d0
+#define mmCRTC4_CRTC_VERTICAL_INTERRUPT1_POSITION                               0x43d0
+#define mmCRTC5_CRTC_VERTICAL_INTERRUPT1_POSITION                               0x45d0
+#define mmCRTC_VERTICAL_INTERRUPT1_CONTROL                                      0x1bd1
+#define mmCRTC0_CRTC_VERTICAL_INTERRUPT1_CONTROL                                0x1bd1
+#define mmCRTC1_CRTC_VERTICAL_INTERRUPT1_CONTROL                                0x1dd1
+#define mmCRTC2_CRTC_VERTICAL_INTERRUPT1_CONTROL                                0x1fd1
+#define mmCRTC3_CRTC_VERTICAL_INTERRUPT1_CONTROL                                0x41d1
+#define mmCRTC4_CRTC_VERTICAL_INTERRUPT1_CONTROL                                0x43d1
+#define mmCRTC5_CRTC_VERTICAL_INTERRUPT1_CONTROL                                0x45d1
+#define mmCRTC_VERTICAL_INTERRUPT2_POSITION                                     0x1bd2
+#define mmCRTC0_CRTC_VERTICAL_INTERRUPT2_POSITION                               0x1bd2
+#define mmCRTC1_CRTC_VERTICAL_INTERRUPT2_POSITION                               0x1dd2
+#define mmCRTC2_CRTC_VERTICAL_INTERRUPT2_POSITION                               0x1fd2
+#define mmCRTC3_CRTC_VERTICAL_INTERRUPT2_POSITION                               0x41d2
+#define mmCRTC4_CRTC_VERTICAL_INTERRUPT2_POSITION                               0x43d2
+#define mmCRTC5_CRTC_VERTICAL_INTERRUPT2_POSITION                               0x45d2
+#define mmCRTC_VERTICAL_INTERRUPT2_CONTROL                                      0x1bd3
+#define mmCRTC0_CRTC_VERTICAL_INTERRUPT2_CONTROL                                0x1bd3
+#define mmCRTC1_CRTC_VERTICAL_INTERRUPT2_CONTROL                                0x1dd3
+#define mmCRTC2_CRTC_VERTICAL_INTERRUPT2_CONTROL                                0x1fd3
+#define mmCRTC3_CRTC_VERTICAL_INTERRUPT2_CONTROL                                0x41d3
+#define mmCRTC4_CRTC_VERTICAL_INTERRUPT2_CONTROL                                0x43d3
+#define mmCRTC5_CRTC_VERTICAL_INTERRUPT2_CONTROL                                0x45d3
+#define mmCRTC_CRC_CNTL                                                         0x1bd4
+#define mmCRTC0_CRTC_CRC_CNTL                                                   0x1bd4
+#define mmCRTC1_CRTC_CRC_CNTL                                                   0x1dd4
+#define mmCRTC2_CRTC_CRC_CNTL                                                   0x1fd4
+#define mmCRTC3_CRTC_CRC_CNTL                                                   0x41d4
+#define mmCRTC4_CRTC_CRC_CNTL                                                   0x43d4
+#define mmCRTC5_CRTC_CRC_CNTL                                                   0x45d4
+#define mmCRTC_CRC0_WINDOWA_X_CONTROL                                           0x1bd5
+#define mmCRTC0_CRTC_CRC0_WINDOWA_X_CONTROL                                     0x1bd5
+#define mmCRTC1_CRTC_CRC0_WINDOWA_X_CONTROL                                     0x1dd5
+#define mmCRTC2_CRTC_CRC0_WINDOWA_X_CONTROL                                     0x1fd5
+#define mmCRTC3_CRTC_CRC0_WINDOWA_X_CONTROL                                     0x41d5
+#define mmCRTC4_CRTC_CRC0_WINDOWA_X_CONTROL                                     0x43d5
+#define mmCRTC5_CRTC_CRC0_WINDOWA_X_CONTROL                                     0x45d5
+#define mmCRTC_CRC0_WINDOWA_Y_CONTROL                                           0x1bd6
+#define mmCRTC0_CRTC_CRC0_WINDOWA_Y_CONTROL                                     0x1bd6
+#define mmCRTC1_CRTC_CRC0_WINDOWA_Y_CONTROL                                     0x1dd6
+#define mmCRTC2_CRTC_CRC0_WINDOWA_Y_CONTROL                                     0x1fd6
+#define mmCRTC3_CRTC_CRC0_WINDOWA_Y_CONTROL                                     0x41d6
+#define mmCRTC4_CRTC_CRC0_WINDOWA_Y_CONTROL                                     0x43d6
+#define mmCRTC5_CRTC_CRC0_WINDOWA_Y_CONTROL                                     0x45d6
+#define mmCRTC_CRC0_WINDOWB_X_CONTROL                                           0x1bd7
+#define mmCRTC0_CRTC_CRC0_WINDOWB_X_CONTROL                                     0x1bd7
+#define mmCRTC1_CRTC_CRC0_WINDOWB_X_CONTROL                                     0x1dd7
+#define mmCRTC2_CRTC_CRC0_WINDOWB_X_CONTROL                                     0x1fd7
+#define mmCRTC3_CRTC_CRC0_WINDOWB_X_CONTROL                                     0x41d7
+#define mmCRTC4_CRTC_CRC0_WINDOWB_X_CONTROL                                     0x43d7
+#define mmCRTC5_CRTC_CRC0_WINDOWB_X_CONTROL                                     0x45d7
+#define mmCRTC_CRC0_WINDOWB_Y_CONTROL                                           0x1bd8
+#define mmCRTC0_CRTC_CRC0_WINDOWB_Y_CONTROL                                     0x1bd8
+#define mmCRTC1_CRTC_CRC0_WINDOWB_Y_CONTROL                                     0x1dd8
+#define mmCRTC2_CRTC_CRC0_WINDOWB_Y_CONTROL                                     0x1fd8
+#define mmCRTC3_CRTC_CRC0_WINDOWB_Y_CONTROL                                     0x41d8
+#define mmCRTC4_CRTC_CRC0_WINDOWB_Y_CONTROL                                     0x43d8
+#define mmCRTC5_CRTC_CRC0_WINDOWB_Y_CONTROL                                     0x45d8
+#define mmCRTC_CRC0_DATA_RG                                                     0x1bd9
+#define mmCRTC0_CRTC_CRC0_DATA_RG                                               0x1bd9
+#define mmCRTC1_CRTC_CRC0_DATA_RG                                               0x1dd9
+#define mmCRTC2_CRTC_CRC0_DATA_RG                                               0x1fd9
+#define mmCRTC3_CRTC_CRC0_DATA_RG                                               0x41d9
+#define mmCRTC4_CRTC_CRC0_DATA_RG                                               0x43d9
+#define mmCRTC5_CRTC_CRC0_DATA_RG                                               0x45d9
+#define mmCRTC_CRC0_DATA_B                                                      0x1bda
+#define mmCRTC0_CRTC_CRC0_DATA_B                                                0x1bda
+#define mmCRTC1_CRTC_CRC0_DATA_B                                                0x1dda
+#define mmCRTC2_CRTC_CRC0_DATA_B                                                0x1fda
+#define mmCRTC3_CRTC_CRC0_DATA_B                                                0x41da
+#define mmCRTC4_CRTC_CRC0_DATA_B                                                0x43da
+#define mmCRTC5_CRTC_CRC0_DATA_B                                                0x45da
+#define mmCRTC_CRC1_WINDOWA_X_CONTROL                                           0x1bdb
+#define mmCRTC0_CRTC_CRC1_WINDOWA_X_CONTROL                                     0x1bdb
+#define mmCRTC1_CRTC_CRC1_WINDOWA_X_CONTROL                                     0x1ddb
+#define mmCRTC2_CRTC_CRC1_WINDOWA_X_CONTROL                                     0x1fdb
+#define mmCRTC3_CRTC_CRC1_WINDOWA_X_CONTROL                                     0x41db
+#define mmCRTC4_CRTC_CRC1_WINDOWA_X_CONTROL                                     0x43db
+#define mmCRTC5_CRTC_CRC1_WINDOWA_X_CONTROL                                     0x45db
+#define mmCRTC_CRC1_WINDOWA_Y_CONTROL                                           0x1bdc
+#define mmCRTC0_CRTC_CRC1_WINDOWA_Y_CONTROL                                     0x1bdc
+#define mmCRTC1_CRTC_CRC1_WINDOWA_Y_CONTROL                                     0x1ddc
+#define mmCRTC2_CRTC_CRC1_WINDOWA_Y_CONTROL                                     0x1fdc
+#define mmCRTC3_CRTC_CRC1_WINDOWA_Y_CONTROL                                     0x41dc
+#define mmCRTC4_CRTC_CRC1_WINDOWA_Y_CONTROL                                     0x43dc
+#define mmCRTC5_CRTC_CRC1_WINDOWA_Y_CONTROL                                     0x45dc
+#define mmCRTC_CRC1_WINDOWB_X_CONTROL                                           0x1bdd
+#define mmCRTC0_CRTC_CRC1_WINDOWB_X_CONTROL                                     0x1bdd
+#define mmCRTC1_CRTC_CRC1_WINDOWB_X_CONTROL                                     0x1ddd
+#define mmCRTC2_CRTC_CRC1_WINDOWB_X_CONTROL                                     0x1fdd
+#define mmCRTC3_CRTC_CRC1_WINDOWB_X_CONTROL                                     0x41dd
+#define mmCRTC4_CRTC_CRC1_WINDOWB_X_CONTROL                                     0x43dd
+#define mmCRTC5_CRTC_CRC1_WINDOWB_X_CONTROL                                     0x45dd
+#define mmCRTC_CRC1_WINDOWB_Y_CONTROL                                           0x1bde
+#define mmCRTC0_CRTC_CRC1_WINDOWB_Y_CONTROL                                     0x1bde
+#define mmCRTC1_CRTC_CRC1_WINDOWB_Y_CONTROL                                     0x1dde
+#define mmCRTC2_CRTC_CRC1_WINDOWB_Y_CONTROL                                     0x1fde
+#define mmCRTC3_CRTC_CRC1_WINDOWB_Y_CONTROL                                     0x41de
+#define mmCRTC4_CRTC_CRC1_WINDOWB_Y_CONTROL                                     0x43de
+#define mmCRTC5_CRTC_CRC1_WINDOWB_Y_CONTROL                                     0x45de
+#define mmCRTC_CRC1_DATA_RG                                                     0x1bdf
+#define mmCRTC0_CRTC_CRC1_DATA_RG                                               0x1bdf
+#define mmCRTC1_CRTC_CRC1_DATA_RG                                               0x1ddf
+#define mmCRTC2_CRTC_CRC1_DATA_RG                                               0x1fdf
+#define mmCRTC3_CRTC_CRC1_DATA_RG                                               0x41df
+#define mmCRTC4_CRTC_CRC1_DATA_RG                                               0x43df
+#define mmCRTC5_CRTC_CRC1_DATA_RG                                               0x45df
+#define mmCRTC_CRC1_DATA_B                                                      0x1be0
+#define mmCRTC0_CRTC_CRC1_DATA_B                                                0x1be0
+#define mmCRTC1_CRTC_CRC1_DATA_B                                                0x1de0
+#define mmCRTC2_CRTC_CRC1_DATA_B                                                0x1fe0
+#define mmCRTC3_CRTC_CRC1_DATA_B                                                0x41e0
+#define mmCRTC4_CRTC_CRC1_DATA_B                                                0x43e0
+#define mmCRTC5_CRTC_CRC1_DATA_B                                                0x45e0
+#define mmCRTC_EXT_TIMING_SYNC_CONTROL                                          0x1be1
+#define mmCRTC0_CRTC_EXT_TIMING_SYNC_CONTROL                                    0x1be1
+#define mmCRTC1_CRTC_EXT_TIMING_SYNC_CONTROL                                    0x1de1
+#define mmCRTC2_CRTC_EXT_TIMING_SYNC_CONTROL                                    0x1fe1
+#define mmCRTC3_CRTC_EXT_TIMING_SYNC_CONTROL                                    0x41e1
+#define mmCRTC4_CRTC_EXT_TIMING_SYNC_CONTROL                                    0x43e1
+#define mmCRTC5_CRTC_EXT_TIMING_SYNC_CONTROL                                    0x45e1
+#define mmCRTC_EXT_TIMING_SYNC_WINDOW_START                                     0x1be2
+#define mmCRTC0_CRTC_EXT_TIMING_SYNC_WINDOW_START                               0x1be2
+#define mmCRTC1_CRTC_EXT_TIMING_SYNC_WINDOW_START                               0x1de2
+#define mmCRTC2_CRTC_EXT_TIMING_SYNC_WINDOW_START                               0x1fe2
+#define mmCRTC3_CRTC_EXT_TIMING_SYNC_WINDOW_START                               0x41e2
+#define mmCRTC4_CRTC_EXT_TIMING_SYNC_WINDOW_START                               0x43e2
+#define mmCRTC5_CRTC_EXT_TIMING_SYNC_WINDOW_START                               0x45e2
+#define mmCRTC_EXT_TIMING_SYNC_WINDOW_END                                       0x1be3
+#define mmCRTC0_CRTC_EXT_TIMING_SYNC_WINDOW_END                                 0x1be3
+#define mmCRTC1_CRTC_EXT_TIMING_SYNC_WINDOW_END                                 0x1de3
+#define mmCRTC2_CRTC_EXT_TIMING_SYNC_WINDOW_END                                 0x1fe3
+#define mmCRTC3_CRTC_EXT_TIMING_SYNC_WINDOW_END                                 0x41e3
+#define mmCRTC4_CRTC_EXT_TIMING_SYNC_WINDOW_END                                 0x43e3
+#define mmCRTC5_CRTC_EXT_TIMING_SYNC_WINDOW_END                                 0x45e3
+#define mmCRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL                           0x1be4
+#define mmCRTC0_CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL                     0x1be4
+#define mmCRTC1_CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL                     0x1de4
+#define mmCRTC2_CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL                     0x1fe4
+#define mmCRTC3_CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL                     0x41e4
+#define mmCRTC4_CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL                     0x43e4
+#define mmCRTC5_CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL                     0x45e4
+#define mmCRTC_EXT_TIMING_SYNC_INTERRUPT_CONTROL                                0x1be5
+#define mmCRTC0_CRTC_EXT_TIMING_SYNC_INTERRUPT_CONTROL                          0x1be5
+#define mmCRTC1_CRTC_EXT_TIMING_SYNC_INTERRUPT_CONTROL                          0x1de5
+#define mmCRTC2_CRTC_EXT_TIMING_SYNC_INTERRUPT_CONTROL                          0x1fe5
+#define mmCRTC3_CRTC_EXT_TIMING_SYNC_INTERRUPT_CONTROL                          0x41e5
+#define mmCRTC4_CRTC_EXT_TIMING_SYNC_INTERRUPT_CONTROL                          0x43e5
+#define mmCRTC5_CRTC_EXT_TIMING_SYNC_INTERRUPT_CONTROL                          0x45e5
+#define mmCRTC_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_CONTROL                         0x1be6
+#define mmCRTC0_CRTC_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_CONTROL                   0x1be6
+#define mmCRTC1_CRTC_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_CONTROL                   0x1de6
+#define mmCRTC2_CRTC_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_CONTROL                   0x1fe6
+#define mmCRTC3_CRTC_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_CONTROL                   0x41e6
+#define mmCRTC4_CRTC_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_CONTROL                   0x43e6
+#define mmCRTC5_CRTC_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_CONTROL                   0x45e6
+#define mmCRTC_STATIC_SCREEN_CONTROL                                            0x1be7
+#define mmCRTC0_CRTC_STATIC_SCREEN_CONTROL                                      0x1be7
+#define mmCRTC1_CRTC_STATIC_SCREEN_CONTROL                                      0x1de7
+#define mmCRTC2_CRTC_STATIC_SCREEN_CONTROL                                      0x1fe7
+#define mmCRTC3_CRTC_STATIC_SCREEN_CONTROL                                      0x41e7
+#define mmCRTC4_CRTC_STATIC_SCREEN_CONTROL                                      0x43e7
+#define mmCRTC5_CRTC_STATIC_SCREEN_CONTROL                                      0x45e7
+#define mmCRTC_3D_STRUCTURE_CONTROL                                             0x1b78
+#define mmCRTC0_CRTC_3D_STRUCTURE_CONTROL                                       0x1b78
+#define mmCRTC1_CRTC_3D_STRUCTURE_CONTROL                                       0x1d78
+#define mmCRTC2_CRTC_3D_STRUCTURE_CONTROL                                       0x1f78
+#define mmCRTC3_CRTC_3D_STRUCTURE_CONTROL                                       0x4178
+#define mmCRTC4_CRTC_3D_STRUCTURE_CONTROL                                       0x4378
+#define mmCRTC5_CRTC_3D_STRUCTURE_CONTROL                                       0x4578
+#define mmCRTC_GSL_VSYNC_GAP                                                    0x1b79
+#define mmCRTC0_CRTC_GSL_VSYNC_GAP                                              0x1b79
+#define mmCRTC1_CRTC_GSL_VSYNC_GAP                                              0x1d79
+#define mmCRTC2_CRTC_GSL_VSYNC_GAP                                              0x1f79
+#define mmCRTC3_CRTC_GSL_VSYNC_GAP                                              0x4179
+#define mmCRTC4_CRTC_GSL_VSYNC_GAP                                              0x4379
+#define mmCRTC5_CRTC_GSL_VSYNC_GAP                                              0x4579
+#define mmCRTC_GSL_WINDOW                                                       0x1b7a
+#define mmCRTC0_CRTC_GSL_WINDOW                                                 0x1b7a
+#define mmCRTC1_CRTC_GSL_WINDOW                                                 0x1d7a
+#define mmCRTC2_CRTC_GSL_WINDOW                                                 0x1f7a
+#define mmCRTC3_CRTC_GSL_WINDOW                                                 0x417a
+#define mmCRTC4_CRTC_GSL_WINDOW                                                 0x437a
+#define mmCRTC5_CRTC_GSL_WINDOW                                                 0x457a
+#define mmCRTC_GSL_CONTROL                                                      0x1b7b
+#define mmCRTC0_CRTC_GSL_CONTROL                                                0x1b7b
+#define mmCRTC1_CRTC_GSL_CONTROL                                                0x1d7b
+#define mmCRTC2_CRTC_GSL_CONTROL                                                0x1f7b
+#define mmCRTC3_CRTC_GSL_CONTROL                                                0x417b
+#define mmCRTC4_CRTC_GSL_CONTROL                                                0x437b
+#define mmCRTC5_CRTC_GSL_CONTROL                                                0x457b
+#define mmCRTC_TEST_DEBUG_INDEX                                                 0x1bc6
+#define mmCRTC0_CRTC_TEST_DEBUG_INDEX                                           0x1bc6
+#define mmCRTC1_CRTC_TEST_DEBUG_INDEX                                           0x1dc6
+#define mmCRTC2_CRTC_TEST_DEBUG_INDEX                                           0x1fc6
+#define mmCRTC3_CRTC_TEST_DEBUG_INDEX                                           0x41c6
+#define mmCRTC4_CRTC_TEST_DEBUG_INDEX                                           0x43c6
+#define mmCRTC5_CRTC_TEST_DEBUG_INDEX                                           0x45c6
+#define mmCRTC_TEST_DEBUG_DATA                                                  0x1bc7
+#define mmCRTC0_CRTC_TEST_DEBUG_DATA                                            0x1bc7
+#define mmCRTC1_CRTC_TEST_DEBUG_DATA                                            0x1dc7
+#define mmCRTC2_CRTC_TEST_DEBUG_DATA                                            0x1fc7
+#define mmCRTC3_CRTC_TEST_DEBUG_DATA                                            0x41c7
+#define mmCRTC4_CRTC_TEST_DEBUG_DATA                                            0x43c7
+#define mmCRTC5_CRTC_TEST_DEBUG_DATA                                            0x45c7
+#define mmDAC_ENABLE                                                            0x16aa
+#define mmDAC_SOURCE_SELECT                                                     0x16ab
+#define mmDAC_CRC_EN                                                            0x16ac
+#define mmDAC_CRC_CONTROL                                                       0x16ad
+#define mmDAC_CRC_SIG_RGB_MASK                                                  0x16ae
+#define mmDAC_CRC_SIG_CONTROL_MASK                                              0x16af
+#define mmDAC_CRC_SIG_RGB                                                       0x16b0
+#define mmDAC_CRC_SIG_CONTROL                                                   0x16b1
+#define mmDAC_SYNC_TRISTATE_CONTROL                                             0x16b2
+#define mmDAC_STEREOSYNC_SELECT                                                 0x16b3
+#define mmDAC_AUTODETECT_CONTROL                                                0x16b4
+#define mmDAC_AUTODETECT_CONTROL2                                               0x16b5
+#define mmDAC_AUTODETECT_CONTROL3                                               0x16b6
+#define mmDAC_AUTODETECT_STATUS                                                 0x16b7
+#define mmDAC_AUTODETECT_INT_CONTROL                                            0x16b8
+#define mmDAC_FORCE_OUTPUT_CNTL                                                 0x16b9
+#define mmDAC_FORCE_DATA                                                        0x16ba
+#define mmDAC_POWERDOWN                                                         0x16bb
+#define mmDAC_CONTROL                                                           0x16bc
+#define mmDAC_COMPARATOR_ENABLE                                                 0x16bd
+#define mmDAC_COMPARATOR_OUTPUT                                                 0x16be
+#define mmDAC_PWR_CNTL                                                          0x16bf
+#define mmDAC_DFT_CONFIG                                                        0x16c0
+#define mmDAC_FIFO_STATUS                                                       0x16c1
+#define mmDAC_TEST_DEBUG_INDEX                                                  0x16c2
+#define mmDAC_TEST_DEBUG_DATA                                                   0x16c3
+#define mmPERFCOUNTER_CNTL                                                      0x170
+#define mmDC_PERFMON0_PERFCOUNTER_CNTL                                          0x170
+#define mmDC_PERFMON1_PERFCOUNTER_CNTL                                          0x358
+#define mmDC_PERFMON2_PERFCOUNTER_CNTL                                          0x364
+#define mmDC_PERFMON3_PERFCOUNTER_CNTL                                          0x18c8
+#define mmDC_PERFMON4_PERFCOUNTER_CNTL                                          0x1b24
+#define mmDC_PERFMON5_PERFCOUNTER_CNTL                                          0x1d24
+#define mmDC_PERFMON6_PERFCOUNTER_CNTL                                          0x1f24
+#define mmDC_PERFMON7_PERFCOUNTER_CNTL                                          0x4124
+#define mmDC_PERFMON8_PERFCOUNTER_CNTL                                          0x4324
+#define mmDC_PERFMON9_PERFCOUNTER_CNTL                                          0x4524
+#define mmDC_PERFMON10_PERFCOUNTER_CNTL                                         0x4724
+#define mmDC_PERFMON11_PERFCOUNTER_CNTL                                         0x59a0
+#define mmDC_PERFMON12_PERFCOUNTER_CNTL                                         0x5f68
+#define mmDC_PERFMON13_PERFCOUNTER_CNTL                                         0x9924
+#define mmPERFCOUNTER_STATE                                                     0x171
+#define mmDC_PERFMON0_PERFCOUNTER_STATE                                         0x171
+#define mmDC_PERFMON1_PERFCOUNTER_STATE                                         0x359
+#define mmDC_PERFMON2_PERFCOUNTER_STATE                                         0x365
+#define mmDC_PERFMON3_PERFCOUNTER_STATE                                         0x18c9
+#define mmDC_PERFMON4_PERFCOUNTER_STATE                                         0x1b25
+#define mmDC_PERFMON5_PERFCOUNTER_STATE                                         0x1d25
+#define mmDC_PERFMON6_PERFCOUNTER_STATE                                         0x1f25
+#define mmDC_PERFMON7_PERFCOUNTER_STATE                                         0x4125
+#define mmDC_PERFMON8_PERFCOUNTER_STATE                                         0x4325
+#define mmDC_PERFMON9_PERFCOUNTER_STATE                                         0x4525
+#define mmDC_PERFMON10_PERFCOUNTER_STATE                                        0x4725
+#define mmDC_PERFMON11_PERFCOUNTER_STATE                                        0x59a1
+#define mmDC_PERFMON12_PERFCOUNTER_STATE                                        0x5f69
+#define mmDC_PERFMON13_PERFCOUNTER_STATE                                        0x9925
+#define mmPERFMON_CNTL                                                          0x173
+#define mmDC_PERFMON0_PERFMON_CNTL                                              0x173
+#define mmDC_PERFMON1_PERFMON_CNTL                                              0x35b
+#define mmDC_PERFMON2_PERFMON_CNTL                                              0x367
+#define mmDC_PERFMON3_PERFMON_CNTL                                              0x18cb
+#define mmDC_PERFMON4_PERFMON_CNTL                                              0x1b27
+#define mmDC_PERFMON5_PERFMON_CNTL                                              0x1d27
+#define mmDC_PERFMON6_PERFMON_CNTL                                              0x1f27
+#define mmDC_PERFMON7_PERFMON_CNTL                                              0x4127
+#define mmDC_PERFMON8_PERFMON_CNTL                                              0x4327
+#define mmDC_PERFMON9_PERFMON_CNTL                                              0x4527
+#define mmDC_PERFMON10_PERFMON_CNTL                                             0x4727
+#define mmDC_PERFMON11_PERFMON_CNTL                                             0x59a3
+#define mmDC_PERFMON12_PERFMON_CNTL                                             0x5f6b
+#define mmDC_PERFMON13_PERFMON_CNTL                                             0x9927
+#define mmPERFMON_CNTL2                                                         0x17a
+#define mmDC_PERFMON0_PERFMON_CNTL2                                             0x17a
+#define mmDC_PERFMON1_PERFMON_CNTL2                                             0x362
+#define mmDC_PERFMON2_PERFMON_CNTL2                                             0x36e
+#define mmDC_PERFMON3_PERFMON_CNTL2                                             0x18d2
+#define mmDC_PERFMON4_PERFMON_CNTL2                                             0x1b2e
+#define mmDC_PERFMON5_PERFMON_CNTL2                                             0x1d2e
+#define mmDC_PERFMON6_PERFMON_CNTL2                                             0x1f2e
+#define mmDC_PERFMON7_PERFMON_CNTL2                                             0x412e
+#define mmDC_PERFMON8_PERFMON_CNTL2                                             0x432e
+#define mmDC_PERFMON9_PERFMON_CNTL2                                             0x452e
+#define mmDC_PERFMON10_PERFMON_CNTL2                                            0x472e
+#define mmDC_PERFMON11_PERFMON_CNTL2                                            0x59aa
+#define mmDC_PERFMON12_PERFMON_CNTL2                                            0x5f72
+#define mmDC_PERFMON13_PERFMON_CNTL2                                            0x992e
+#define mmPERFMON_CVALUE_INT_MISC                                               0x172
+#define mmDC_PERFMON0_PERFMON_CVALUE_INT_MISC                                   0x172
+#define mmDC_PERFMON1_PERFMON_CVALUE_INT_MISC                                   0x35a
+#define mmDC_PERFMON2_PERFMON_CVALUE_INT_MISC                                   0x366
+#define mmDC_PERFMON3_PERFMON_CVALUE_INT_MISC                                   0x18ca
+#define mmDC_PERFMON4_PERFMON_CVALUE_INT_MISC                                   0x1b26
+#define mmDC_PERFMON5_PERFMON_CVALUE_INT_MISC                                   0x1d26
+#define mmDC_PERFMON6_PERFMON_CVALUE_INT_MISC                                   0x1f26
+#define mmDC_PERFMON7_PERFMON_CVALUE_INT_MISC                                   0x4126
+#define mmDC_PERFMON8_PERFMON_CVALUE_INT_MISC                                   0x4326
+#define mmDC_PERFMON9_PERFMON_CVALUE_INT_MISC                                   0x4526
+#define mmDC_PERFMON10_PERFMON_CVALUE_INT_MISC                                  0x4726
+#define mmDC_PERFMON11_PERFMON_CVALUE_INT_MISC                                  0x59a2
+#define mmDC_PERFMON12_PERFMON_CVALUE_INT_MISC                                  0x5f6a
+#define mmDC_PERFMON13_PERFMON_CVALUE_INT_MISC                                  0x9926
+#define mmPERFMON_CVALUE_LOW                                                    0x174
+#define mmDC_PERFMON0_PERFMON_CVALUE_LOW                                        0x174
+#define mmDC_PERFMON1_PERFMON_CVALUE_LOW                                        0x35c
+#define mmDC_PERFMON2_PERFMON_CVALUE_LOW                                        0x368
+#define mmDC_PERFMON3_PERFMON_CVALUE_LOW                                        0x18cc
+#define mmDC_PERFMON4_PERFMON_CVALUE_LOW                                        0x1b28
+#define mmDC_PERFMON5_PERFMON_CVALUE_LOW                                        0x1d28
+#define mmDC_PERFMON6_PERFMON_CVALUE_LOW                                        0x1f28
+#define mmDC_PERFMON7_PERFMON_CVALUE_LOW                                        0x4128
+#define mmDC_PERFMON8_PERFMON_CVALUE_LOW                                        0x4328
+#define mmDC_PERFMON9_PERFMON_CVALUE_LOW                                        0x4528
+#define mmDC_PERFMON10_PERFMON_CVALUE_LOW                                       0x4728
+#define mmDC_PERFMON11_PERFMON_CVALUE_LOW                                       0x59a4
+#define mmDC_PERFMON12_PERFMON_CVALUE_LOW                                       0x5f6c
+#define mmDC_PERFMON13_PERFMON_CVALUE_LOW                                       0x9928
+#define mmPERFMON_HI                                                            0x175
+#define mmDC_PERFMON0_PERFMON_HI                                                0x175
+#define mmDC_PERFMON1_PERFMON_HI                                                0x35d
+#define mmDC_PERFMON2_PERFMON_HI                                                0x369
+#define mmDC_PERFMON3_PERFMON_HI                                                0x18cd
+#define mmDC_PERFMON4_PERFMON_HI                                                0x1b29
+#define mmDC_PERFMON5_PERFMON_HI                                                0x1d29
+#define mmDC_PERFMON6_PERFMON_HI                                                0x1f29
+#define mmDC_PERFMON7_PERFMON_HI                                                0x4129
+#define mmDC_PERFMON8_PERFMON_HI                                                0x4329
+#define mmDC_PERFMON9_PERFMON_HI                                                0x4529
+#define mmDC_PERFMON10_PERFMON_HI                                               0x4729
+#define mmDC_PERFMON11_PERFMON_HI                                               0x59a5
+#define mmDC_PERFMON12_PERFMON_HI                                               0x5f6d
+#define mmDC_PERFMON13_PERFMON_HI                                               0x9929
+#define mmPERFMON_LOW                                                           0x176
+#define mmDC_PERFMON0_PERFMON_LOW                                               0x176
+#define mmDC_PERFMON1_PERFMON_LOW                                               0x35e
+#define mmDC_PERFMON2_PERFMON_LOW                                               0x36a
+#define mmDC_PERFMON3_PERFMON_LOW                                               0x18ce
+#define mmDC_PERFMON4_PERFMON_LOW                                               0x1b2a
+#define mmDC_PERFMON5_PERFMON_LOW                                               0x1d2a
+#define mmDC_PERFMON6_PERFMON_LOW                                               0x1f2a
+#define mmDC_PERFMON7_PERFMON_LOW                                               0x412a
+#define mmDC_PERFMON8_PERFMON_LOW                                               0x432a
+#define mmDC_PERFMON9_PERFMON_LOW                                               0x452a
+#define mmDC_PERFMON10_PERFMON_LOW                                              0x472a
+#define mmDC_PERFMON11_PERFMON_LOW                                              0x59a6
+#define mmDC_PERFMON12_PERFMON_LOW                                              0x5f6e
+#define mmDC_PERFMON13_PERFMON_LOW                                              0x992a
+#define mmPERFMON_TEST_DEBUG_INDEX                                              0x177
+#define mmDC_PERFMON0_PERFMON_TEST_DEBUG_INDEX                                  0x177
+#define mmDC_PERFMON1_PERFMON_TEST_DEBUG_INDEX                                  0x35f
+#define mmDC_PERFMON2_PERFMON_TEST_DEBUG_INDEX                                  0x36b
+#define mmDC_PERFMON3_PERFMON_TEST_DEBUG_INDEX                                  0x18cf
+#define mmDC_PERFMON4_PERFMON_TEST_DEBUG_INDEX                                  0x1b2b
+#define mmDC_PERFMON5_PERFMON_TEST_DEBUG_INDEX                                  0x1d2b
+#define mmDC_PERFMON6_PERFMON_TEST_DEBUG_INDEX                                  0x1f2b
+#define mmDC_PERFMON7_PERFMON_TEST_DEBUG_INDEX                                  0x412b
+#define mmDC_PERFMON8_PERFMON_TEST_DEBUG_INDEX                                  0x432b
+#define mmDC_PERFMON9_PERFMON_TEST_DEBUG_INDEX                                  0x452b
+#define mmDC_PERFMON10_PERFMON_TEST_DEBUG_INDEX                                 0x472b
+#define mmDC_PERFMON11_PERFMON_TEST_DEBUG_INDEX                                 0x59a7
+#define mmDC_PERFMON12_PERFMON_TEST_DEBUG_INDEX                                 0x5f6f
+#define mmDC_PERFMON13_PERFMON_TEST_DEBUG_INDEX                                 0x992b
+#define mmPERFMON_TEST_DEBUG_DATA                                               0x178
+#define mmDC_PERFMON0_PERFMON_TEST_DEBUG_DATA                                   0x178
+#define mmDC_PERFMON1_PERFMON_TEST_DEBUG_DATA                                   0x360
+#define mmDC_PERFMON2_PERFMON_TEST_DEBUG_DATA                                   0x36c
+#define mmDC_PERFMON3_PERFMON_TEST_DEBUG_DATA                                   0x18d0
+#define mmDC_PERFMON4_PERFMON_TEST_DEBUG_DATA                                   0x1b2c
+#define mmDC_PERFMON5_PERFMON_TEST_DEBUG_DATA                                   0x1d2c
+#define mmDC_PERFMON6_PERFMON_TEST_DEBUG_DATA                                   0x1f2c
+#define mmDC_PERFMON7_PERFMON_TEST_DEBUG_DATA                                   0x412c
+#define mmDC_PERFMON8_PERFMON_TEST_DEBUG_DATA                                   0x432c
+#define mmDC_PERFMON9_PERFMON_TEST_DEBUG_DATA                                   0x452c
+#define mmDC_PERFMON10_PERFMON_TEST_DEBUG_DATA                                  0x472c
+#define mmDC_PERFMON11_PERFMON_TEST_DEBUG_DATA                                  0x59a8
+#define mmDC_PERFMON12_PERFMON_TEST_DEBUG_DATA                                  0x5f70
+#define mmDC_PERFMON13_PERFMON_TEST_DEBUG_DATA                                  0x992c
+#define mmREFCLK_CNTL                                                           0x109
+#define mmDCCG_CBUS_ANTIGLITCH_RESETB                                           0x15c
+#define mmDCCG_CBUS_SPARE                                                       0x15d
+#define mmDCCG_CBUS_WRCMD_DELAY                                                 0x110
+#define mmDPREFCLK_CNTL                                                         0x118
+#define mmDCE_VERSION                                                           0x11e
+#define mmAVSYNC_COUNTER_WRITE                                                  0x12a
+#define mmAVSYNC_COUNTER_CONTROL                                                0x12b
+#define mmAVSYNC_COUNTER_READ                                                   0x12f
+#define mmDCCG_GTC_CNTL                                                         0x120
+#define mmDCCG_GTC_DTO_INCR                                                     0x121
+#define mmDCCG_GTC_DTO_MODULO                                                   0x122
+#define mmDCCG_GTC_CURRENT                                                      0x123
+#define mmDCCG_DS_DTO_INCR                                                      0x113
+#define mmDCCG_DS_DTO_MODULO                                                    0x114
+#define mmDCCG_DS_CNTL                                                          0x115
+#define mmDCCG_DS_HW_CAL_INTERVAL                                               0x116
+#define mmDCCG_DS_DEBUG_CNTL                                                    0x112
+#define mmDMCU_SMU_INTERRUPT_CNTL                                               0x12c
+#define mmSMU_CONTROL                                                           0x12d
+#define mmSMU_INTERRUPT_CONTROL                                                 0x12e
+#define mmDAC_CLK_ENABLE                                                        0x128
+#define mmDVO_CLK_ENABLE                                                        0x129
+#define mmDCCG_GATE_DISABLE_CNTL                                                0x134
+#define mmDCCG_GATE_DISABLE_CNTL2                                               0x13c
+#define mmDISPCLK_CGTT_BLK_CTRL_REG                                             0x135
+#define mmSCLK_CGTT_BLK_CTRL_REG                                                0x136
+#define mmDPREFCLK_CGTT_BLK_CTRL_REG                                            0x108
+#define mmREFCLK_CGTT_BLK_CTRL_REG                                              0x10b
+#define mmSYMCLK_CGTT_BLK_CTRL_REG                                              0x13d
+#define mmDCCG_CAC_STATUS                                                       0x137
+#define mmPIXCLK0_RESYNC_CNTL                                                   0x13a
+#define mmPHYPLLA_PIXCLK_RESYNC_CNTL                                            0x100
+#define mmPHYPLLB_PIXCLK_RESYNC_CNTL                                            0x101
+#define mmPHYPLLC_PIXCLK_RESYNC_CNTL                                            0x102
+#define mmPHYPLLD_PIXCLK_RESYNC_CNTL                                            0x103
+#define mmPHYPLLE_PIXCLK_RESYNC_CNTL                                            0x10c
+#define mmPHYPLLF_PIXCLK_RESYNC_CNTL                                            0x13e
+#define mmMICROSECOND_TIME_BASE_DIV                                             0x13b
+#define mmDCCG_DISP_CNTL_REG                                                    0x13f
+#define mmMILLISECOND_TIME_BASE_DIV                                             0x130
+#define mmDISPCLK_FREQ_CHANGE_CNTL                                              0x131
+#define mmDC_MEM_GLOBAL_PWR_REQ_CNTL                                            0x132
+#define mmDCCG_PERFMON_CNTL                                                     0x133
+#define mmDCCG_PERFMON_CNTL2                                                    0x10e
+#define mmCRTC0_PIXEL_RATE_CNTL                                                 0x140
+#define mmDP_DTO0_PHASE                                                         0x141
+#define mmDP_DTO0_MODULO                                                        0x142
+#define mmCRTC0_PHYPLL_PIXEL_RATE_CNTL                                          0x143
+#define mmCRTC1_PIXEL_RATE_CNTL                                                 0x144
+#define mmDP_DTO1_PHASE                                                         0x145
+#define mmDP_DTO1_MODULO                                                        0x146
+#define mmCRTC1_PHYPLL_PIXEL_RATE_CNTL                                          0x147
+#define mmCRTC2_PIXEL_RATE_CNTL                                                 0x148
+#define mmDP_DTO2_PHASE                                                         0x149
+#define mmDP_DTO2_MODULO                                                        0x14a
+#define mmCRTC2_PHYPLL_PIXEL_RATE_CNTL                                          0x14b
+#define mmCRTC3_PIXEL_RATE_CNTL                                                 0x14c
+#define mmDP_DTO3_PHASE                                                         0x14d
+#define mmDP_DTO3_MODULO                                                        0x14e
+#define mmCRTC3_PHYPLL_PIXEL_RATE_CNTL                                          0x14f
+#define mmCRTC4_PIXEL_RATE_CNTL                                                 0x150
+#define mmDP_DTO4_PHASE                                                         0x151
+#define mmDP_DTO4_MODULO                                                        0x152
+#define mmCRTC4_PHYPLL_PIXEL_RATE_CNTL                                          0x153
+#define mmCRTC5_PIXEL_RATE_CNTL                                                 0x154
+#define mmDP_DTO5_PHASE                                                         0x155
+#define mmDP_DTO5_MODULO                                                        0x156
+#define mmCRTC5_PHYPLL_PIXEL_RATE_CNTL                                          0x157
+#define mmDCCG_SOFT_RESET                                                       0x15f
+#define mmSYMCLKA_CLOCK_ENABLE                                                  0x160
+#define mmSYMCLKB_CLOCK_ENABLE                                                  0x161
+#define mmSYMCLKC_CLOCK_ENABLE                                                  0x162
+#define mmSYMCLKD_CLOCK_ENABLE                                                  0x163
+#define mmSYMCLKE_CLOCK_ENABLE                                                  0x164
+#define mmSYMCLKF_CLOCK_ENABLE                                                  0x165
+#define mmDPDBG_CLK_FORCE_CONTROL                                               0x10d
+#define mmDCCG_AUDIO_DTO_SOURCE                                                 0x16b
+#define mmDCCG_AUDIO_DTO0_PHASE                                                 0x16c
+#define mmDCCG_AUDIO_DTO0_MODULE                                                0x16d
+#define mmDCCG_AUDIO_DTO1_PHASE                                                 0x16e
+#define mmDCCG_AUDIO_DTO1_MODULE                                                0x16f
+#define mmDCCG_TEST_DEBUG_INDEX                                                 0x17c
+#define mmDCCG_TEST_DEBUG_DATA                                                  0x17d
+#define mmDCCG_TEST_CLK_SEL                                                     0x17e
+#define mmCPLL_MACRO_CNTL_RESERVED0                                             0x5fd0
+#define mmDCCG_CPLL0_CPLL_MACRO_CNTL_RESERVED0                                  0x5fd0
+#define mmDCCG_CPLL1_CPLL_MACRO_CNTL_RESERVED0                                  0x5fdc
+#define mmDCCG_CPLL2_CPLL_MACRO_CNTL_RESERVED0                                  0x5fe8
+#define mmDCCG_CPLL3_CPLL_MACRO_CNTL_RESERVED0                                  0x5ff4
+#define mmCPLL_MACRO_CNTL_RESERVED1                                             0x5fd1
+#define mmDCCG_CPLL0_CPLL_MACRO_CNTL_RESERVED1                                  0x5fd1
+#define mmDCCG_CPLL1_CPLL_MACRO_CNTL_RESERVED1                                  0x5fdd
+#define mmDCCG_CPLL2_CPLL_MACRO_CNTL_RESERVED1                                  0x5fe9
+#define mmDCCG_CPLL3_CPLL_MACRO_CNTL_RESERVED1                                  0x5ff5
+#define mmCPLL_MACRO_CNTL_RESERVED2                                             0x5fd2
+#define mmDCCG_CPLL0_CPLL_MACRO_CNTL_RESERVED2                                  0x5fd2
+#define mmDCCG_CPLL1_CPLL_MACRO_CNTL_RESERVED2                                  0x5fde
+#define mmDCCG_CPLL2_CPLL_MACRO_CNTL_RESERVED2                                  0x5fea
+#define mmDCCG_CPLL3_CPLL_MACRO_CNTL_RESERVED2                                  0x5ff6
+#define mmCPLL_MACRO_CNTL_RESERVED3                                             0x5fd3
+#define mmDCCG_CPLL0_CPLL_MACRO_CNTL_RESERVED3                                  0x5fd3
+#define mmDCCG_CPLL1_CPLL_MACRO_CNTL_RESERVED3                                  0x5fdf
+#define mmDCCG_CPLL2_CPLL_MACRO_CNTL_RESERVED3                                  0x5feb
+#define mmDCCG_CPLL3_CPLL_MACRO_CNTL_RESERVED3                                  0x5ff7
+#define mmCPLL_MACRO_CNTL_RESERVED4                                             0x5fd4
+#define mmDCCG_CPLL0_CPLL_MACRO_CNTL_RESERVED4                                  0x5fd4
+#define mmDCCG_CPLL1_CPLL_MACRO_CNTL_RESERVED4                                  0x5fe0
+#define mmDCCG_CPLL2_CPLL_MACRO_CNTL_RESERVED4                                  0x5fec
+#define mmDCCG_CPLL3_CPLL_MACRO_CNTL_RESERVED4                                  0x5ff8
+#define mmCPLL_MACRO_CNTL_RESERVED5                                             0x5fd5
+#define mmDCCG_CPLL0_CPLL_MACRO_CNTL_RESERVED5                                  0x5fd5
+#define mmDCCG_CPLL1_CPLL_MACRO_CNTL_RESERVED5                                  0x5fe1
+#define mmDCCG_CPLL2_CPLL_MACRO_CNTL_RESERVED5                                  0x5fed
+#define mmDCCG_CPLL3_CPLL_MACRO_CNTL_RESERVED5                                  0x5ff9
+#define mmCPLL_MACRO_CNTL_RESERVED6                                             0x5fd6
+#define mmDCCG_CPLL0_CPLL_MACRO_CNTL_RESERVED6                                  0x5fd6
+#define mmDCCG_CPLL1_CPLL_MACRO_CNTL_RESERVED6                                  0x5fe2
+#define mmDCCG_CPLL2_CPLL_MACRO_CNTL_RESERVED6                                  0x5fee
+#define mmDCCG_CPLL3_CPLL_MACRO_CNTL_RESERVED6                                  0x5ffa
+#define mmCPLL_MACRO_CNTL_RESERVED7                                             0x5fd7
+#define mmDCCG_CPLL0_CPLL_MACRO_CNTL_RESERVED7                                  0x5fd7
+#define mmDCCG_CPLL1_CPLL_MACRO_CNTL_RESERVED7                                  0x5fe3
+#define mmDCCG_CPLL2_CPLL_MACRO_CNTL_RESERVED7                                  0x5fef
+#define mmDCCG_CPLL3_CPLL_MACRO_CNTL_RESERVED7                                  0x5ffb
+#define mmCPLL_MACRO_CNTL_RESERVED8                                             0x5fd8
+#define mmDCCG_CPLL0_CPLL_MACRO_CNTL_RESERVED8                                  0x5fd8
+#define mmDCCG_CPLL1_CPLL_MACRO_CNTL_RESERVED8                                  0x5fe4
+#define mmDCCG_CPLL2_CPLL_MACRO_CNTL_RESERVED8                                  0x5ff0
+#define mmDCCG_CPLL3_CPLL_MACRO_CNTL_RESERVED8                                  0x5ffc
+#define mmCPLL_MACRO_CNTL_RESERVED9                                             0x5fd9
+#define mmDCCG_CPLL0_CPLL_MACRO_CNTL_RESERVED9                                  0x5fd9
+#define mmDCCG_CPLL1_CPLL_MACRO_CNTL_RESERVED9                                  0x5fe5
+#define mmDCCG_CPLL2_CPLL_MACRO_CNTL_RESERVED9                                  0x5ff1
+#define mmDCCG_CPLL3_CPLL_MACRO_CNTL_RESERVED9                                  0x5ffd
+#define mmCPLL_MACRO_CNTL_RESERVED10                                            0x5fda
+#define mmDCCG_CPLL0_CPLL_MACRO_CNTL_RESERVED10                                 0x5fda
+#define mmDCCG_CPLL1_CPLL_MACRO_CNTL_RESERVED10                                 0x5fe6
+#define mmDCCG_CPLL2_CPLL_MACRO_CNTL_RESERVED10                                 0x5ff2
+#define mmDCCG_CPLL3_CPLL_MACRO_CNTL_RESERVED10                                 0x5ffe
+#define mmCPLL_MACRO_CNTL_RESERVED11                                            0x5fdb
+#define mmDCCG_CPLL0_CPLL_MACRO_CNTL_RESERVED11                                 0x5fdb
+#define mmDCCG_CPLL1_CPLL_MACRO_CNTL_RESERVED11                                 0x5fe7
+#define mmDCCG_CPLL2_CPLL_MACRO_CNTL_RESERVED11                                 0x5ff3
+#define mmDCCG_CPLL3_CPLL_MACRO_CNTL_RESERVED11                                 0x5fff
+#define mmPLL_MACRO_CNTL_RESERVED0                                              0x1700
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED0                                    0x1700
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED0                                    0x172a
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED0                                    0x1754
+#define mmPLL_MACRO_CNTL_RESERVED1                                              0x1701
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED1                                    0x1701
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED1                                    0x172b
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED1                                    0x1755
+#define mmPLL_MACRO_CNTL_RESERVED2                                              0x1702
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED2                                    0x1702
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED2                                    0x172c
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED2                                    0x1756
+#define mmPLL_MACRO_CNTL_RESERVED3                                              0x1703
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED3                                    0x1703
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED3                                    0x172d
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED3                                    0x1757
+#define mmPLL_MACRO_CNTL_RESERVED4                                              0x1704
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED4                                    0x1704
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED4                                    0x172e
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED4                                    0x1758
+#define mmPLL_MACRO_CNTL_RESERVED5                                              0x1705
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED5                                    0x1705
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED5                                    0x172f
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED5                                    0x1759
+#define mmPLL_MACRO_CNTL_RESERVED6                                              0x1706
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED6                                    0x1706
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED6                                    0x1730
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED6                                    0x175a
+#define mmPLL_MACRO_CNTL_RESERVED7                                              0x1707
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED7                                    0x1707
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED7                                    0x1731
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED7                                    0x175b
+#define mmPLL_MACRO_CNTL_RESERVED8                                              0x1708
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED8                                    0x1708
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED8                                    0x1732
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED8                                    0x175c
+#define mmPLL_MACRO_CNTL_RESERVED9                                              0x1709
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED9                                    0x1709
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED9                                    0x1733
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED9                                    0x175d
+#define mmPLL_MACRO_CNTL_RESERVED10                                             0x170a
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED10                                   0x170a
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED10                                   0x1734
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED10                                   0x175e
+#define mmPLL_MACRO_CNTL_RESERVED11                                             0x170b
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED11                                   0x170b
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED11                                   0x1735
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED11                                   0x175f
+#define mmPLL_MACRO_CNTL_RESERVED12                                             0x170c
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED12                                   0x170c
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED12                                   0x1736
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED12                                   0x1760
+#define mmPLL_MACRO_CNTL_RESERVED13                                             0x170d
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED13                                   0x170d
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED13                                   0x1737
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED13                                   0x1761
+#define mmPLL_MACRO_CNTL_RESERVED14                                             0x170e
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED14                                   0x170e
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED14                                   0x1738
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED14                                   0x1762
+#define mmPLL_MACRO_CNTL_RESERVED15                                             0x170f
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED15                                   0x170f
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED15                                   0x1739
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED15                                   0x1763
+#define mmPLL_MACRO_CNTL_RESERVED16                                             0x1710
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED16                                   0x1710
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED16                                   0x173a
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED16                                   0x1764
+#define mmPLL_MACRO_CNTL_RESERVED17                                             0x1711
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED17                                   0x1711
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED17                                   0x173b
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED17                                   0x1765
+#define mmPLL_MACRO_CNTL_RESERVED18                                             0x1712
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED18                                   0x1712
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED18                                   0x173c
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED18                                   0x1766
+#define mmPLL_MACRO_CNTL_RESERVED19                                             0x1713
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED19                                   0x1713
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED19                                   0x173d
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED19                                   0x1767
+#define mmPLL_MACRO_CNTL_RESERVED20                                             0x1714
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED20                                   0x1714
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED20                                   0x173e
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED20                                   0x1768
+#define mmPLL_MACRO_CNTL_RESERVED21                                             0x1715
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED21                                   0x1715
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED21                                   0x173f
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED21                                   0x1769
+#define mmPLL_MACRO_CNTL_RESERVED22                                             0x1716
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED22                                   0x1716
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED22                                   0x1740
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED22                                   0x176a
+#define mmPLL_MACRO_CNTL_RESERVED23                                             0x1717
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED23                                   0x1717
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED23                                   0x1741
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED23                                   0x176b
+#define mmPLL_MACRO_CNTL_RESERVED24                                             0x1718
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED24                                   0x1718
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED24                                   0x1742
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED24                                   0x176c
+#define mmPLL_MACRO_CNTL_RESERVED25                                             0x1719
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED25                                   0x1719
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED25                                   0x1743
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED25                                   0x176d
+#define mmPLL_MACRO_CNTL_RESERVED26                                             0x171a
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED26                                   0x171a
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED26                                   0x1744
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED26                                   0x176e
+#define mmPLL_MACRO_CNTL_RESERVED27                                             0x171b
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED27                                   0x171b
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED27                                   0x1745
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED27                                   0x176f
+#define mmPLL_MACRO_CNTL_RESERVED28                                             0x171c
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED28                                   0x171c
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED28                                   0x1746
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED28                                   0x1770
+#define mmPLL_MACRO_CNTL_RESERVED29                                             0x171d
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED29                                   0x171d
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED29                                   0x1747
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED29                                   0x1771
+#define mmPLL_MACRO_CNTL_RESERVED30                                             0x171e
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED30                                   0x171e
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED30                                   0x1748
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED30                                   0x1772
+#define mmPLL_MACRO_CNTL_RESERVED31                                             0x171f
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED31                                   0x171f
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED31                                   0x1749
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED31                                   0x1773
+#define mmPLL_MACRO_CNTL_RESERVED32                                             0x1720
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED32                                   0x1720
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED32                                   0x174a
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED32                                   0x1774
+#define mmPLL_MACRO_CNTL_RESERVED33                                             0x1721
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED33                                   0x1721
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED33                                   0x174b
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED33                                   0x1775
+#define mmPLL_MACRO_CNTL_RESERVED34                                             0x1722
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED34                                   0x1722
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED34                                   0x174c
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED34                                   0x1776
+#define mmPLL_MACRO_CNTL_RESERVED35                                             0x1723
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED35                                   0x1723
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED35                                   0x174d
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED35                                   0x1777
+#define mmPLL_MACRO_CNTL_RESERVED36                                             0x1724
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED36                                   0x1724
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED36                                   0x174e
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED36                                   0x1778
+#define mmPLL_MACRO_CNTL_RESERVED37                                             0x1725
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED37                                   0x1725
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED37                                   0x174f
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED37                                   0x1779
+#define mmPLL_MACRO_CNTL_RESERVED38                                             0x1726
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED38                                   0x1726
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED38                                   0x1750
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED38                                   0x177a
+#define mmPLL_MACRO_CNTL_RESERVED39                                             0x1727
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED39                                   0x1727
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED39                                   0x1751
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED39                                   0x177b
+#define mmPLL_MACRO_CNTL_RESERVED40                                             0x1728
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED40                                   0x1728
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED40                                   0x1752
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED40                                   0x177c
+#define mmPLL_MACRO_CNTL_RESERVED41                                             0x1729
+#define mmDCCG_PLL0_PLL_MACRO_CNTL_RESERVED41                                   0x1729
+#define mmDCCG_PLL1_PLL_MACRO_CNTL_RESERVED41                                   0x1753
+#define mmDCCG_PLL2_PLL_MACRO_CNTL_RESERVED41                                   0x177d
+#define mmDENTIST_DISPCLK_CNTL                                                  0x124
+#define mmDCDEBUG_BUS_CLK1_SEL                                                  0x16c4
+#define mmDCDEBUG_BUS_CLK2_SEL                                                  0x16c5
+#define mmDCDEBUG_BUS_CLK3_SEL                                                  0x16c6
+#define mmDCDEBUG_BUS_CLK4_SEL                                                  0x16c7
+#define mmDCDEBUG_BUS_CLK5_SEL                                                  0x16c8
+#define mmDCDEBUG_OUT_PIN_OVERRIDE                                              0x16c9
+#define mmDCDEBUG_OUT_CNTL                                                      0x16ca
+#define mmDCDEBUG_OUT_DATA                                                      0x16cb
+#define mmDMIF_CONTROL                                                          0x2f6
+#define mmDMIF_STATUS                                                           0x2f7
+#define mmDMIFV_STATUS                                                          0x2f5
+#define mmDMIF_HW_DEBUG                                                         0x2f8
+#define mmDMIF_ARBITRATION_CONTROL                                              0x2f9
+#define mmPIPE0_ARBITRATION_CONTROL3                                            0x2fa
+#define mmPIPE1_ARBITRATION_CONTROL3                                            0x2fb
+#define mmPIPE2_ARBITRATION_CONTROL3                                            0x2fc
+#define mmPIPE3_ARBITRATION_CONTROL3                                            0x2fd
+#define mmPIPE4_ARBITRATION_CONTROL3                                            0x2fe
+#define mmPIPE5_ARBITRATION_CONTROL3                                            0x2ff
+#define mmPIPE6_ARBITRATION_CONTROL3                                            0x32a
+#define mmPIPE7_ARBITRATION_CONTROL3                                            0x32b
+#define mmDMIF_P_VMID                                                           0x300
+#define mmDMIF_URG_OVERRIDE                                                     0x329
+#define mmDMIF_TEST_DEBUG_INDEX                                                 0x301
+#define mmDMIF_TEST_DEBUG_DATA                                                  0x302
+#define ixDMIF_DEBUG02_CORE0                                                    0x2
+#define ixDMIF_DEBUG02_CORE1                                                    0xa
+#define mmDMIF_ADDR_CALC                                                        0x303
+#define mmDMIF_STATUS2                                                          0x304
+#define mmPIPE0_MAX_REQUESTS                                                    0x305
+#define mmPIPE1_MAX_REQUESTS                                                    0x306
+#define mmPIPE2_MAX_REQUESTS                                                    0x307
+#define mmPIPE3_MAX_REQUESTS                                                    0x308
+#define mmPIPE4_MAX_REQUESTS                                                    0x309
+#define mmPIPE5_MAX_REQUESTS                                                    0x30a
+#define mmPIPE6_MAX_REQUESTS                                                    0x32c
+#define mmPIPE7_MAX_REQUESTS                                                    0x32d
+#define mmDVMM_REG_RD_STATUS                                                    0x32e
+#define mmDVMM_REG_RD_DATA                                                      0x32f
+#define mmDVMM_PTE_REQ                                                          0x330
+#define mmDVMM_CNTL                                                             0x331
+#define mmDVMM_FAULT_STATUS                                                     0x332
+#define mmDVMM_FAULT_ADDR                                                       0x333
+#define mmLOW_POWER_TILING_CONTROL                                              0x30b
+#define mmMCIF_CONTROL                                                          0x30c
+#define mmMCIF_WRITE_COMBINE_CONTROL                                            0x30d
+#define mmMCIF_TEST_DEBUG_INDEX                                                 0x30e
+#define mmMCIF_TEST_DEBUG_DATA                                                  0x30f
+#define ixIDDCCIF02_DBG_DCCIF_C                                                 0x9
+#define ixIDDCCIF04_DBG_DCCIF_E                                                 0xb
+#define ixIDDCCIF05_DBG_DCCIF_F                                                 0xc
+#define mmMCIF_VMID                                                             0x310
+#define mmMCIF_MEM_CONTROL                                                      0x311
+#define mmCC_DC_PIPE_DIS                                                        0x312
+#define mmMC_DC_INTERFACE_NACK_STATUS                                           0x313
+#define mmRBBMIF_TIMEOUT                                                        0x314
+#define mmRBBMIF_STATUS                                                         0x315
+#define mmRBBMIF_TIMEOUT_DIS                                                    0x316
+#define mmRBBMIF_STATUS_FLAG                                                    0x327
+#define mmDCI_MEM_PWR_STATUS                                                    0x317
+#define mmDCI_MEM_PWR_STATUS2                                                   0x318
+#define mmDCI_MEM_PWR_STATUS3                                                   0x33d
+#define mmDCI_CLK_CNTL                                                          0x319
+#define mmDCI_CLK_RAMP_CNTL                                                     0x31a
+#define mmDCI_MEM_PWR_CNTL                                                      0x31b
+#define mmDCI_MEM_PWR_CNTL2                                                     0x31c
+#define mmDCI_MEM_PWR_CNTL3                                                     0x31d
+#define mmDCI_MEM_PWR_CNTL4                                                     0x33b
+#define mmDVMM_PTE_PGMEM_CONTROL                                                0x335
+#define mmDVMM_PTE_PGMEM_STATE                                                  0x336
+#define mmDCI_SOFT_RESET                                                        0x328
+#define mmDCI_MISC                                                              0x33c
+#define mmDCI_TEST_DEBUG_INDEX                                                  0x31e
+#define mmDCI_TEST_DEBUG_DATA                                                   0x31f
+#define mmDCI_DEBUG_CONFIG                                                      0x320
+#define mmPIPE0_DMIF_BUFFER_CONTROL                                             0x321
+#define mmPIPE1_DMIF_BUFFER_CONTROL                                             0x322
+#define mmPIPE2_DMIF_BUFFER_CONTROL                                             0x323
+#define mmPIPE3_DMIF_BUFFER_CONTROL                                             0x324
+#define mmPIPE4_DMIF_BUFFER_CONTROL                                             0x325
+#define mmPIPE5_DMIF_BUFFER_CONTROL                                             0x326
+#define mmDC_GENERICA                                                           0x4800
+#define mmDC_GENERICB                                                           0x4801
+#define mmDC_PAD_EXTERN_SIG                                                     0x4802
+#define mmDC_REF_CLK_CNTL                                                       0x4803
+#define mmDC_GPIO_DEBUG                                                         0x4804
+#define mmUNIPHYA_LINK_CNTL                                                     0x4805
+#define mmUNIPHYB_LINK_CNTL                                                     0x4807
+#define mmUNIPHYC_LINK_CNTL                                                     0x4809
+#define mmUNIPHYD_LINK_CNTL                                                     0x480b
+#define mmUNIPHYE_LINK_CNTL                                                     0x480d
+#define mmUNIPHYF_LINK_CNTL                                                     0x480f
+#define mmUNIPHYG_LINK_CNTL                                                     0x4811
+#define mmUNIPHYA_CHANNEL_XBAR_CNTL                                             0x4806
+#define mmUNIPHYB_CHANNEL_XBAR_CNTL                                             0x4808
+#define mmUNIPHYC_CHANNEL_XBAR_CNTL                                             0x480a
+#define mmUNIPHYD_CHANNEL_XBAR_CNTL                                             0x480c
+#define mmUNIPHYE_CHANNEL_XBAR_CNTL                                             0x480e
+#define mmUNIPHYF_CHANNEL_XBAR_CNTL                                             0x4810
+#define mmUNIPHYG_CHANNEL_XBAR_CNTL                                             0x4812
+#define mmUNIPHYLPA_LINK_CNTL                                                   0x4847
+#define mmUNIPHYLPB_LINK_CNTL                                                   0x4848
+#define mmUNIPHYLPA_CHANNEL_XBAR_CNTL                                           0x4849
+#define mmUNIPHYLPB_CHANNEL_XBAR_CNTL                                           0x484a
+#define mmUNIPHY_IMPCAL_LINKA                                                   0x4838
+#define mmUNIPHY_IMPCAL_LINKB                                                   0x4839
+#define mmUNIPHY_IMPCAL_LINKC                                                   0x483f
+#define mmUNIPHY_IMPCAL_LINKD                                                   0x4840
+#define mmUNIPHY_IMPCAL_LINKE                                                   0x4843
+#define mmUNIPHY_IMPCAL_LINKF                                                   0x4844
+#define mmUNIPHY_IMPCAL_PERIOD                                                  0x483a
+#define mmAUXP_IMPCAL                                                           0x483b
+#define mmAUXN_IMPCAL                                                           0x483c
+#define mmDCIO_IMPCAL_CNTL                                                      0x483d
+#define mmUNIPHY_IMPCAL_PSW_AB                                                  0x483e
+#define mmDCIO_IMPCAL_CNTL_CD                                                   0x4841
+#define mmUNIPHY_IMPCAL_PSW_CD                                                  0x4842
+#define mmDCIO_IMPCAL_CNTL_EF                                                   0x4845
+#define mmUNIPHY_IMPCAL_PSW_EF                                                  0x4846
+#define mmDCIO_WRCMD_DELAY                                                      0x4816
+#define mmDC_PINSTRAPS                                                          0x4818
+#define mmDC_DVODATA_CONFIG                                                     0x481a
+#define mmLVTMA_PWRSEQ_CNTL                                                     0x481b
+#define mmLVTMA_PWRSEQ_STATE                                                    0x481c
+#define mmLVTMA_PWRSEQ_REF_DIV                                                  0x481d
+#define mmLVTMA_PWRSEQ_DELAY1                                                   0x481e
+#define mmLVTMA_PWRSEQ_DELAY2                                                   0x481f
+#define mmBL_PWM_CNTL                                                           0x4820
+#define mmBL_PWM_CNTL2                                                          0x4821
+#define mmBL_PWM_PERIOD_CNTL                                                    0x4822
+#define mmBL_PWM_GRP1_REG_LOCK                                                  0x4823
+#define mmDCIO_GSL_GENLK_PAD_CNTL                                               0x4824
+#define mmDCIO_GSL_SWAPLOCK_PAD_CNTL                                            0x4825
+#define mmDCIO_GSL0_CNTL                                                        0x4826
+#define mmDCIO_GSL1_CNTL                                                        0x4827
+#define mmDCIO_GSL2_CNTL                                                        0x4828
+#define mmDC_GPU_TIMER_START_POSITION_V_UPDATE                                  0x4829
+#define mmDC_GPU_TIMER_START_POSITION_P_FLIP                                    0x482a
+#define mmDC_GPU_TIMER_READ                                                     0x482b
+#define mmDC_GPU_TIMER_READ_CNTL                                                0x482c
+#define mmDCIO_CLOCK_CNTL                                                       0x482d
+#define mmDCIO_DEBUG                                                            0x482f
+#define mmDCO_DCFE_EXT_VSYNC_CNTL                                               0x4830
+#define mmDBG_OUT_CNTL                                                          0x4834
+#define mmDCIO_DEBUG_CONFIG                                                     0x4835
+#define mmDCIO_SOFT_RESET                                                       0x4836
+#define mmDCIO_DPHY_SEL                                                         0x4837
+#define mmDCIO_DPCS_TX_INTERRUPT                                                0x484b
+#define mmDCIO_DPCS_RX_INTERRUPT                                                0x484c
+#define mmDCIO_SEMAPHORE0                                                       0x484d
+#define mmDCIO_SEMAPHORE1                                                       0x484e
+#define mmDCIO_SEMAPHORE2                                                       0x484f
+#define mmDCIO_SEMAPHORE3                                                       0x4850
+#define mmDCIO_SEMAPHORE4                                                       0x4851
+#define mmDCIO_SEMAPHORE5                                                       0x4852
+#define mmDCIO_SEMAPHORE6                                                       0x4853
+#define mmDCIO_SEMAPHORE7                                                       0x4854
+#define mmDCIO_TEST_DEBUG_INDEX                                                 0x4831
+#define mmDCIO_TEST_DEBUG_DATA                                                  0x4832
+#define ixDCIO_DEBUG1                                                           0x1
+#define ixDCIO_DEBUG2                                                           0x2
+#define ixDCIO_DEBUG3                                                           0x3
+#define ixDCIO_DEBUG4                                                           0x4
+#define ixDCIO_DEBUG5                                                           0x5
+#define ixDCIO_DEBUG6                                                           0x6
+#define ixDCIO_DEBUG7                                                           0x7
+#define ixDCIO_DEBUG8                                                           0x8
+#define ixDCIO_DEBUG9                                                           0x9
+#define ixDCIO_DEBUGA                                                           0xa
+#define ixDCIO_DEBUGB                                                           0xb
+#define ixDCIO_DEBUGC                                                           0xc
+#define ixDCIO_DEBUGD                                                           0xd
+#define ixDCIO_DEBUGE                                                           0xe
+#define ixDCIO_DEBUGF                                                           0xf
+#define ixDCIO_DEBUG10                                                          0x10
+#define ixDCIO_DEBUG11                                                          0x11
+#define ixDCIO_DEBUG12                                                          0x12
+#define ixDCIO_DEBUG13                                                          0x13
+#define ixDCIO_DEBUG14                                                          0x14
+#define ixDCIO_DEBUG15                                                          0x15
+#define ixDCIO_DEBUG16                                                          0x16
+#define ixDCIO_DEBUG17                                                          0x17
+#define ixDCIO_DEBUG18                                                          0x18
+#define ixDCIO_DEBUG19                                                          0x19
+#define ixDCIO_DEBUG1A                                                          0x1a
+#define ixDCIO_DEBUG1B                                                          0x1b
+#define ixDCIO_DEBUG1C                                                          0x1c
+#define ixDCIO_DEBUG1D                                                          0x1d
+#define ixDCIO_DEBUG1E                                                          0x1e
+#define ixDCIO_DEBUG1F                                                          0x1f
+#define ixDCIO_DEBUG20                                                          0x20
+#define ixDCIO_DEBUG21                                                          0x21
+#define ixDCIO_DEBUG22                                                          0x22
+#define ixDCIO_DEBUG23                                                          0x23
+#define ixDCIO_DEBUG24                                                          0x24
+#define ixDCIO_DEBUG25                                                          0x25
+#define ixDCIO_DEBUG26                                                          0x26
+#define ixDCIO_DEBUG27                                                          0x27
+#define ixDCIO_DEBUG28                                                          0x28
+#define ixDCIO_DEBUG_ID                                                         0x0
+#define mmDC_GPIO_GENERIC_MASK                                                  0x4860
+#define mmDC_GPIO_GENERIC_A                                                     0x4861
+#define mmDC_GPIO_GENERIC_EN                                                    0x4862
+#define mmDC_GPIO_GENERIC_Y                                                     0x4863
+#define mmDC_GPIO_DDC1_MASK                                                     0x4868
+#define mmDC_GPIO_DDC1_A                                                        0x4869
+#define mmDC_GPIO_DDC1_EN                                                       0x486a
+#define mmDC_GPIO_DDC1_Y                                                        0x486b
+#define mmDC_GPIO_DDC2_MASK                                                     0x486c
+#define mmDC_GPIO_DDC2_A                                                        0x486d
+#define mmDC_GPIO_DDC2_EN                                                       0x486e
+#define mmDC_GPIO_DDC2_Y                                                        0x486f
+#define mmDC_GPIO_DDC3_MASK                                                     0x4870
+#define mmDC_GPIO_DDC3_A                                                        0x4871
+#define mmDC_GPIO_DDC3_EN                                                       0x4872
+#define mmDC_GPIO_DDC3_Y                                                        0x4873
+#define mmDC_GPIO_DDC4_MASK                                                     0x4874
+#define mmDC_GPIO_DDC4_A                                                        0x4875
+#define mmDC_GPIO_DDC4_EN                                                       0x4876
+#define mmDC_GPIO_DDC4_Y                                                        0x4877
+#define mmDC_GPIO_DDC5_MASK                                                     0x4878
+#define mmDC_GPIO_DDC5_A                                                        0x4879
+#define mmDC_GPIO_DDC5_EN                                                       0x487a
+#define mmDC_GPIO_DDC5_Y                                                        0x487b
+#define mmDC_GPIO_DDC6_MASK                                                     0x487c
+#define mmDC_GPIO_DDC6_A                                                        0x487d
+#define mmDC_GPIO_DDC6_EN                                                       0x487e
+#define mmDC_GPIO_DDC6_Y                                                        0x487f
+#define mmDC_GPIO_DDCVGA_MASK                                                   0x4880
+#define mmDC_GPIO_DDCVGA_A                                                      0x4881
+#define mmDC_GPIO_DDCVGA_EN                                                     0x4882
+#define mmDC_GPIO_DDCVGA_Y                                                      0x4883
+#define mmDC_GPIO_SYNCA_MASK                                                    0x4884
+#define mmDC_GPIO_SYNCA_A                                                       0x4885
+#define mmDC_GPIO_SYNCA_EN                                                      0x4886
+#define mmDC_GPIO_SYNCA_Y                                                       0x4887
+#define mmDC_GPIO_GENLK_MASK                                                    0x4888
+#define mmDC_GPIO_GENLK_A                                                       0x4889
+#define mmDC_GPIO_GENLK_EN                                                      0x488a
+#define mmDC_GPIO_GENLK_Y                                                       0x488b
+#define mmDC_GPIO_HPD_MASK                                                      0x488c
+#define mmDC_GPIO_HPD_A                                                         0x488d
+#define mmDC_GPIO_HPD_EN                                                        0x488e
+#define mmDC_GPIO_HPD_Y                                                         0x488f
+#define mmDC_GPIO_PWRSEQ_MASK                                                   0x4890
+#define mmDC_GPIO_PWRSEQ_A                                                      0x4891
+#define mmDC_GPIO_PWRSEQ_EN                                                     0x4892
+#define mmDC_GPIO_PWRSEQ_Y                                                      0x4893
+#define mmDC_GPIO_PAD_STRENGTH_1                                                0x4894
+#define mmDC_GPIO_PAD_STRENGTH_2                                                0x4895
+#define mmPHY_AUX_CNTL                                                          0x4897
+#define mmDC_GPIO_I2CPAD_A                                                      0x4899
+#define mmDC_GPIO_I2CPAD_EN                                                     0x489a
+#define mmDC_GPIO_I2CPAD_Y                                                      0x489b
+#define mmDC_GPIO_I2CPAD_STRENGTH                                               0x489c
+#define mmDVO_VREF_CONTROL                                                      0x489e
+#define mmDVO_SKEW_ADJUST                                                       0x489f
+#define mmDC_GPIO_RECEIVER_EN0                                                  0x48a0
+#define mmDC_GPIO_RECEIVER_EN1                                                  0x48a1
+#define mmDC_GPIO_I2S_SPDIF_MASK                                                0x48a8
+#define mmDC_GPIO_I2S_SPDIF_A                                                   0x48a9
+#define mmDC_GPIO_I2S_SPDIF_EN                                                  0x48aa
+#define mmDC_GPIO_I2S_SPDIF_Y                                                   0x48ab
+#define mmDC_GPIO_I2S_SPDIF_STRENGTH                                            0x48ac
+#define mmDC_GPIO_TX12_EN                                                       0x48ad
+#define mmDC_GPIO_AUX_CTRL_0                                                    0x48ae
+#define mmDC_GPIO_AUX_CTRL_1                                                    0x48af
+#define mmDC_GPIO_AUX_CTRL_2                                                    0x48b0
+#define mmDC_GPIO_HPD_CTRL_0                                                    0x48b1
+#define mmDC_GPIO_HPD_CTRL_1                                                    0x48b2
+#define mmDAC_MACRO_CNTL_RESERVED0                                              0x48b8
+#define mmDAC_MACRO_CNTL_RESERVED1                                              0x48b9
+#define mmDAC_MACRO_CNTL_RESERVED2                                              0x48ba
+#define mmDAC_MACRO_CNTL_RESERVED3                                              0x48bb
+#define mmUNIPHY_MACRO_CNTL_RESERVED0                                           0x48c0
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED0                              0x48c0
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED0                              0x4960
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED0                              0x9a00
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED0                              0x9aa0
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED0                              0x9b40
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED0                              0x9be0
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED0                              0x9c80
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED0                              0x9d20
+#define mmUNIPHY_MACRO_CNTL_RESERVED1                                           0x48c1
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED1                              0x48c1
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED1                              0x4961
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED1                              0x9a01
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED1                              0x9aa1
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED1                              0x9b41
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED1                              0x9be1
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED1                              0x9c81
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED1                              0x9d21
+#define mmUNIPHY_MACRO_CNTL_RESERVED2                                           0x48c2
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED2                              0x48c2
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED2                              0x4962
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED2                              0x9a02
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED2                              0x9aa2
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED2                              0x9b42
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED2                              0x9be2
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED2                              0x9c82
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED2                              0x9d22
+#define mmUNIPHY_MACRO_CNTL_RESERVED3                                           0x48c3
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED3                              0x48c3
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED3                              0x4963
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED3                              0x9a03
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED3                              0x9aa3
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED3                              0x9b43
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED3                              0x9be3
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED3                              0x9c83
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED3                              0x9d23
+#define mmUNIPHY_MACRO_CNTL_RESERVED4                                           0x48c4
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED4                              0x48c4
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED4                              0x4964
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED4                              0x9a04
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED4                              0x9aa4
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED4                              0x9b44
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED4                              0x9be4
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED4                              0x9c84
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED4                              0x9d24
+#define mmUNIPHY_MACRO_CNTL_RESERVED5                                           0x48c5
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED5                              0x48c5
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED5                              0x4965
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED5                              0x9a05
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED5                              0x9aa5
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED5                              0x9b45
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED5                              0x9be5
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED5                              0x9c85
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED5                              0x9d25
+#define mmUNIPHY_MACRO_CNTL_RESERVED6                                           0x48c6
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED6                              0x48c6
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED6                              0x4966
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED6                              0x9a06
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED6                              0x9aa6
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED6                              0x9b46
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED6                              0x9be6
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED6                              0x9c86
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED6                              0x9d26
+#define mmUNIPHY_MACRO_CNTL_RESERVED7                                           0x48c7
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED7                              0x48c7
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED7                              0x4967
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED7                              0x9a07
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED7                              0x9aa7
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED7                              0x9b47
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED7                              0x9be7
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED7                              0x9c87
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED7                              0x9d27
+#define mmUNIPHY_MACRO_CNTL_RESERVED8                                           0x48c8
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED8                              0x48c8
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED8                              0x4968
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED8                              0x9a08
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED8                              0x9aa8
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED8                              0x9b48
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED8                              0x9be8
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED8                              0x9c88
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED8                              0x9d28
+#define mmUNIPHY_MACRO_CNTL_RESERVED9                                           0x48c9
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED9                              0x48c9
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED9                              0x4969
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED9                              0x9a09
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED9                              0x9aa9
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED9                              0x9b49
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED9                              0x9be9
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED9                              0x9c89
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED9                              0x9d29
+#define mmUNIPHY_MACRO_CNTL_RESERVED10                                          0x48ca
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED10                             0x48ca
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED10                             0x496a
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED10                             0x9a0a
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED10                             0x9aaa
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED10                             0x9b4a
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED10                             0x9bea
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED10                             0x9c8a
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED10                             0x9d2a
+#define mmUNIPHY_MACRO_CNTL_RESERVED11                                          0x48cb
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED11                             0x48cb
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED11                             0x496b
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED11                             0x9a0b
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED11                             0x9aab
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED11                             0x9b4b
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED11                             0x9beb
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED11                             0x9c8b
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED11                             0x9d2b
+#define mmUNIPHY_MACRO_CNTL_RESERVED12                                          0x48cc
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED12                             0x48cc
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED12                             0x496c
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED12                             0x9a0c
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED12                             0x9aac
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED12                             0x9b4c
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED12                             0x9bec
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED12                             0x9c8c
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED12                             0x9d2c
+#define mmUNIPHY_MACRO_CNTL_RESERVED13                                          0x48cd
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED13                             0x48cd
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED13                             0x496d
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED13                             0x9a0d
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED13                             0x9aad
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED13                             0x9b4d
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED13                             0x9bed
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED13                             0x9c8d
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED13                             0x9d2d
+#define mmUNIPHY_MACRO_CNTL_RESERVED14                                          0x48ce
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED14                             0x48ce
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED14                             0x496e
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED14                             0x9a0e
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED14                             0x9aae
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED14                             0x9b4e
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED14                             0x9bee
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED14                             0x9c8e
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED14                             0x9d2e
+#define mmUNIPHY_MACRO_CNTL_RESERVED15                                          0x48cf
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED15                             0x48cf
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED15                             0x496f
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED15                             0x9a0f
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED15                             0x9aaf
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED15                             0x9b4f
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED15                             0x9bef
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED15                             0x9c8f
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED15                             0x9d2f
+#define mmUNIPHY_MACRO_CNTL_RESERVED16                                          0x48d0
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED16                             0x48d0
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED16                             0x4970
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED16                             0x9a10
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED16                             0x9ab0
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED16                             0x9b50
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED16                             0x9bf0
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED16                             0x9c90
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED16                             0x9d30
+#define mmUNIPHY_MACRO_CNTL_RESERVED17                                          0x48d1
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED17                             0x48d1
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED17                             0x4971
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED17                             0x9a11
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED17                             0x9ab1
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED17                             0x9b51
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED17                             0x9bf1
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED17                             0x9c91
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED17                             0x9d31
+#define mmUNIPHY_MACRO_CNTL_RESERVED18                                          0x48d2
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED18                             0x48d2
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED18                             0x4972
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED18                             0x9a12
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED18                             0x9ab2
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED18                             0x9b52
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED18                             0x9bf2
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED18                             0x9c92
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED18                             0x9d32
+#define mmUNIPHY_MACRO_CNTL_RESERVED19                                          0x48d3
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED19                             0x48d3
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED19                             0x4973
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED19                             0x9a13
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED19                             0x9ab3
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED19                             0x9b53
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED19                             0x9bf3
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED19                             0x9c93
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED19                             0x9d33
+#define mmUNIPHY_MACRO_CNTL_RESERVED20                                          0x48d4
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED20                             0x48d4
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED20                             0x4974
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED20                             0x9a14
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED20                             0x9ab4
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED20                             0x9b54
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED20                             0x9bf4
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED20                             0x9c94
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED20                             0x9d34
+#define mmUNIPHY_MACRO_CNTL_RESERVED21                                          0x48d5
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED21                             0x48d5
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED21                             0x4975
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED21                             0x9a15
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED21                             0x9ab5
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED21                             0x9b55
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED21                             0x9bf5
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED21                             0x9c95
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED21                             0x9d35
+#define mmUNIPHY_MACRO_CNTL_RESERVED22                                          0x48d6
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED22                             0x48d6
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED22                             0x4976
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED22                             0x9a16
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED22                             0x9ab6
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED22                             0x9b56
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED22                             0x9bf6
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED22                             0x9c96
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED22                             0x9d36
+#define mmUNIPHY_MACRO_CNTL_RESERVED23                                          0x48d7
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED23                             0x48d7
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED23                             0x4977
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED23                             0x9a17
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED23                             0x9ab7
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED23                             0x9b57
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED23                             0x9bf7
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED23                             0x9c97
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED23                             0x9d37
+#define mmUNIPHY_MACRO_CNTL_RESERVED24                                          0x48d8
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED24                             0x48d8
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED24                             0x4978
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED24                             0x9a18
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED24                             0x9ab8
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED24                             0x9b58
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED24                             0x9bf8
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED24                             0x9c98
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED24                             0x9d38
+#define mmUNIPHY_MACRO_CNTL_RESERVED25                                          0x48d9
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED25                             0x48d9
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED25                             0x4979
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED25                             0x9a19
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED25                             0x9ab9
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED25                             0x9b59
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED25                             0x9bf9
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED25                             0x9c99
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED25                             0x9d39
+#define mmUNIPHY_MACRO_CNTL_RESERVED26                                          0x48da
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED26                             0x48da
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED26                             0x497a
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED26                             0x9a1a
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED26                             0x9aba
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED26                             0x9b5a
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED26                             0x9bfa
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED26                             0x9c9a
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED26                             0x9d3a
+#define mmUNIPHY_MACRO_CNTL_RESERVED27                                          0x48db
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED27                             0x48db
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED27                             0x497b
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED27                             0x9a1b
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED27                             0x9abb
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED27                             0x9b5b
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED27                             0x9bfb
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED27                             0x9c9b
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED27                             0x9d3b
+#define mmUNIPHY_MACRO_CNTL_RESERVED28                                          0x48dc
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED28                             0x48dc
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED28                             0x497c
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED28                             0x9a1c
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED28                             0x9abc
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED28                             0x9b5c
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED28                             0x9bfc
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED28                             0x9c9c
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED28                             0x9d3c
+#define mmUNIPHY_MACRO_CNTL_RESERVED29                                          0x48dd
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED29                             0x48dd
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED29                             0x497d
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED29                             0x9a1d
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED29                             0x9abd
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED29                             0x9b5d
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED29                             0x9bfd
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED29                             0x9c9d
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED29                             0x9d3d
+#define mmUNIPHY_MACRO_CNTL_RESERVED30                                          0x48de
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED30                             0x48de
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED30                             0x497e
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED30                             0x9a1e
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED30                             0x9abe
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED30                             0x9b5e
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED30                             0x9bfe
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED30                             0x9c9e
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED30                             0x9d3e
+#define mmUNIPHY_MACRO_CNTL_RESERVED31                                          0x48df
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED31                             0x48df
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED31                             0x497f
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED31                             0x9a1f
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED31                             0x9abf
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED31                             0x9b5f
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED31                             0x9bff
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED31                             0x9c9f
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED31                             0x9d3f
+#define mmUNIPHY_MACRO_CNTL_RESERVED32                                          0x48e0
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED32                             0x48e0
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED32                             0x4980
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED32                             0x9a20
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED32                             0x9ac0
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED32                             0x9b60
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED32                             0x9c00
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED32                             0x9ca0
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED32                             0x9d40
+#define mmUNIPHY_MACRO_CNTL_RESERVED33                                          0x48e1
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED33                             0x48e1
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED33                             0x4981
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED33                             0x9a21
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED33                             0x9ac1
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED33                             0x9b61
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED33                             0x9c01
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED33                             0x9ca1
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED33                             0x9d41
+#define mmUNIPHY_MACRO_CNTL_RESERVED34                                          0x48e2
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED34                             0x48e2
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED34                             0x4982
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED34                             0x9a22
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED34                             0x9ac2
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED34                             0x9b62
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED34                             0x9c02
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED34                             0x9ca2
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED34                             0x9d42
+#define mmUNIPHY_MACRO_CNTL_RESERVED35                                          0x48e3
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED35                             0x48e3
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED35                             0x4983
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED35                             0x9a23
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED35                             0x9ac3
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED35                             0x9b63
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED35                             0x9c03
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED35                             0x9ca3
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED35                             0x9d43
+#define mmUNIPHY_MACRO_CNTL_RESERVED36                                          0x48e4
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED36                             0x48e4
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED36                             0x4984
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED36                             0x9a24
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED36                             0x9ac4
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED36                             0x9b64
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED36                             0x9c04
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED36                             0x9ca4
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED36                             0x9d44
+#define mmUNIPHY_MACRO_CNTL_RESERVED37                                          0x48e5
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED37                             0x48e5
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED37                             0x4985
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED37                             0x9a25
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED37                             0x9ac5
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED37                             0x9b65
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED37                             0x9c05
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED37                             0x9ca5
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED37                             0x9d45
+#define mmUNIPHY_MACRO_CNTL_RESERVED38                                          0x48e6
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED38                             0x48e6
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED38                             0x4986
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED38                             0x9a26
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED38                             0x9ac6
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED38                             0x9b66
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED38                             0x9c06
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED38                             0x9ca6
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED38                             0x9d46
+#define mmUNIPHY_MACRO_CNTL_RESERVED39                                          0x48e7
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED39                             0x48e7
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED39                             0x4987
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED39                             0x9a27
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED39                             0x9ac7
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED39                             0x9b67
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED39                             0x9c07
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED39                             0x9ca7
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED39                             0x9d47
+#define mmUNIPHY_MACRO_CNTL_RESERVED40                                          0x48e8
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED40                             0x48e8
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED40                             0x4988
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED40                             0x9a28
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED40                             0x9ac8
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED40                             0x9b68
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED40                             0x9c08
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED40                             0x9ca8
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED40                             0x9d48
+#define mmUNIPHY_MACRO_CNTL_RESERVED41                                          0x48e9
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED41                             0x48e9
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED41                             0x4989
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED41                             0x9a29
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED41                             0x9ac9
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED41                             0x9b69
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED41                             0x9c09
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED41                             0x9ca9
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED41                             0x9d49
+#define mmUNIPHY_MACRO_CNTL_RESERVED42                                          0x48ea
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED42                             0x48ea
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED42                             0x498a
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED42                             0x9a2a
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED42                             0x9aca
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED42                             0x9b6a
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED42                             0x9c0a
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED42                             0x9caa
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED42                             0x9d4a
+#define mmUNIPHY_MACRO_CNTL_RESERVED43                                          0x48eb
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED43                             0x48eb
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED43                             0x498b
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED43                             0x9a2b
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED43                             0x9acb
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED43                             0x9b6b
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED43                             0x9c0b
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED43                             0x9cab
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED43                             0x9d4b
+#define mmUNIPHY_MACRO_CNTL_RESERVED44                                          0x48ec
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED44                             0x48ec
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED44                             0x498c
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED44                             0x9a2c
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED44                             0x9acc
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED44                             0x9b6c
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED44                             0x9c0c
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED44                             0x9cac
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED44                             0x9d4c
+#define mmUNIPHY_MACRO_CNTL_RESERVED45                                          0x48ed
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED45                             0x48ed
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED45                             0x498d
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED45                             0x9a2d
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED45                             0x9acd
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED45                             0x9b6d
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED45                             0x9c0d
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED45                             0x9cad
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED45                             0x9d4d
+#define mmUNIPHY_MACRO_CNTL_RESERVED46                                          0x48ee
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED46                             0x48ee
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED46                             0x498e
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED46                             0x9a2e
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED46                             0x9ace
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED46                             0x9b6e
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED46                             0x9c0e
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED46                             0x9cae
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED46                             0x9d4e
+#define mmUNIPHY_MACRO_CNTL_RESERVED47                                          0x48ef
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED47                             0x48ef
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED47                             0x498f
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED47                             0x9a2f
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED47                             0x9acf
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED47                             0x9b6f
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED47                             0x9c0f
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED47                             0x9caf
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED47                             0x9d4f
+#define mmUNIPHY_MACRO_CNTL_RESERVED48                                          0x48f0
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED48                             0x48f0
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED48                             0x4990
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED48                             0x9a30
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED48                             0x9ad0
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED48                             0x9b70
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED48                             0x9c10
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED48                             0x9cb0
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED48                             0x9d50
+#define mmUNIPHY_MACRO_CNTL_RESERVED49                                          0x48f1
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED49                             0x48f1
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED49                             0x4991
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED49                             0x9a31
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED49                             0x9ad1
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED49                             0x9b71
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED49                             0x9c11
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED49                             0x9cb1
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED49                             0x9d51
+#define mmUNIPHY_MACRO_CNTL_RESERVED50                                          0x48f2
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED50                             0x48f2
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED50                             0x4992
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED50                             0x9a32
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED50                             0x9ad2
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED50                             0x9b72
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED50                             0x9c12
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED50                             0x9cb2
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED50                             0x9d52
+#define mmUNIPHY_MACRO_CNTL_RESERVED51                                          0x48f3
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED51                             0x48f3
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED51                             0x4993
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED51                             0x9a33
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED51                             0x9ad3
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED51                             0x9b73
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED51                             0x9c13
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED51                             0x9cb3
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED51                             0x9d53
+#define mmUNIPHY_MACRO_CNTL_RESERVED52                                          0x48f4
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED52                             0x48f4
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED52                             0x4994
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED52                             0x9a34
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED52                             0x9ad4
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED52                             0x9b74
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED52                             0x9c14
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED52                             0x9cb4
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED52                             0x9d54
+#define mmUNIPHY_MACRO_CNTL_RESERVED53                                          0x48f5
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED53                             0x48f5
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED53                             0x4995
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED53                             0x9a35
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED53                             0x9ad5
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED53                             0x9b75
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED53                             0x9c15
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED53                             0x9cb5
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED53                             0x9d55
+#define mmUNIPHY_MACRO_CNTL_RESERVED54                                          0x48f6
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED54                             0x48f6
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED54                             0x4996
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED54                             0x9a36
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED54                             0x9ad6
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED54                             0x9b76
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED54                             0x9c16
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED54                             0x9cb6
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED54                             0x9d56
+#define mmUNIPHY_MACRO_CNTL_RESERVED55                                          0x48f7
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED55                             0x48f7
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED55                             0x4997
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED55                             0x9a37
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED55                             0x9ad7
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED55                             0x9b77
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED55                             0x9c17
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED55                             0x9cb7
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED55                             0x9d57
+#define mmUNIPHY_MACRO_CNTL_RESERVED56                                          0x48f8
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED56                             0x48f8
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED56                             0x4998
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED56                             0x9a38
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED56                             0x9ad8
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED56                             0x9b78
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED56                             0x9c18
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED56                             0x9cb8
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED56                             0x9d58
+#define mmUNIPHY_MACRO_CNTL_RESERVED57                                          0x48f9
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED57                             0x48f9
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED57                             0x4999
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED57                             0x9a39
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED57                             0x9ad9
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED57                             0x9b79
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED57                             0x9c19
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED57                             0x9cb9
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED57                             0x9d59
+#define mmUNIPHY_MACRO_CNTL_RESERVED58                                          0x48fa
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED58                             0x48fa
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED58                             0x499a
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED58                             0x9a3a
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED58                             0x9ada
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED58                             0x9b7a
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED58                             0x9c1a
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED58                             0x9cba
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED58                             0x9d5a
+#define mmUNIPHY_MACRO_CNTL_RESERVED59                                          0x48fb
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED59                             0x48fb
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED59                             0x499b
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED59                             0x9a3b
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED59                             0x9adb
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED59                             0x9b7b
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED59                             0x9c1b
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED59                             0x9cbb
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED59                             0x9d5b
+#define mmUNIPHY_MACRO_CNTL_RESERVED60                                          0x48fc
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED60                             0x48fc
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED60                             0x499c
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED60                             0x9a3c
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED60                             0x9adc
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED60                             0x9b7c
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED60                             0x9c1c
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED60                             0x9cbc
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED60                             0x9d5c
+#define mmUNIPHY_MACRO_CNTL_RESERVED61                                          0x48fd
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED61                             0x48fd
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED61                             0x499d
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED61                             0x9a3d
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED61                             0x9add
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED61                             0x9b7d
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED61                             0x9c1d
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED61                             0x9cbd
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED61                             0x9d5d
+#define mmUNIPHY_MACRO_CNTL_RESERVED62                                          0x48fe
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED62                             0x48fe
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED62                             0x499e
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED62                             0x9a3e
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED62                             0x9ade
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED62                             0x9b7e
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED62                             0x9c1e
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED62                             0x9cbe
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED62                             0x9d5e
+#define mmUNIPHY_MACRO_CNTL_RESERVED63                                          0x48ff
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED63                             0x48ff
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED63                             0x499f
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED63                             0x9a3f
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED63                             0x9adf
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED63                             0x9b7f
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED63                             0x9c1f
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED63                             0x9cbf
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED63                             0x9d5f
+#define mmUNIPHY_MACRO_CNTL_RESERVED64                                          0x4900
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED64                             0x4900
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED64                             0x49a0
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED64                             0x9a40
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED64                             0x9ae0
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED64                             0x9b80
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED64                             0x9c20
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED64                             0x9cc0
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED64                             0x9d60
+#define mmUNIPHY_MACRO_CNTL_RESERVED65                                          0x4901
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED65                             0x4901
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED65                             0x49a1
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED65                             0x9a41
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED65                             0x9ae1
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED65                             0x9b81
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED65                             0x9c21
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED65                             0x9cc1
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED65                             0x9d61
+#define mmUNIPHY_MACRO_CNTL_RESERVED66                                          0x4902
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED66                             0x4902
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED66                             0x49a2
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED66                             0x9a42
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED66                             0x9ae2
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED66                             0x9b82
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED66                             0x9c22
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED66                             0x9cc2
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED66                             0x9d62
+#define mmUNIPHY_MACRO_CNTL_RESERVED67                                          0x4903
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED67                             0x4903
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED67                             0x49a3
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED67                             0x9a43
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED67                             0x9ae3
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED67                             0x9b83
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED67                             0x9c23
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED67                             0x9cc3
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED67                             0x9d63
+#define mmUNIPHY_MACRO_CNTL_RESERVED68                                          0x4904
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED68                             0x4904
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED68                             0x49a4
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED68                             0x9a44
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED68                             0x9ae4
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED68                             0x9b84
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED68                             0x9c24
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED68                             0x9cc4
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED68                             0x9d64
+#define mmUNIPHY_MACRO_CNTL_RESERVED69                                          0x4905
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED69                             0x4905
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED69                             0x49a5
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED69                             0x9a45
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED69                             0x9ae5
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED69                             0x9b85
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED69                             0x9c25
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED69                             0x9cc5
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED69                             0x9d65
+#define mmUNIPHY_MACRO_CNTL_RESERVED70                                          0x4906
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED70                             0x4906
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED70                             0x49a6
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED70                             0x9a46
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED70                             0x9ae6
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED70                             0x9b86
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED70                             0x9c26
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED70                             0x9cc6
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED70                             0x9d66
+#define mmUNIPHY_MACRO_CNTL_RESERVED71                                          0x4907
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED71                             0x4907
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED71                             0x49a7
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED71                             0x9a47
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED71                             0x9ae7
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED71                             0x9b87
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED71                             0x9c27
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED71                             0x9cc7
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED71                             0x9d67
+#define mmUNIPHY_MACRO_CNTL_RESERVED72                                          0x4908
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED72                             0x4908
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED72                             0x49a8
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED72                             0x9a48
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED72                             0x9ae8
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED72                             0x9b88
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED72                             0x9c28
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED72                             0x9cc8
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED72                             0x9d68
+#define mmUNIPHY_MACRO_CNTL_RESERVED73                                          0x4909
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED73                             0x4909
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED73                             0x49a9
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED73                             0x9a49
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED73                             0x9ae9
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED73                             0x9b89
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED73                             0x9c29
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED73                             0x9cc9
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED73                             0x9d69
+#define mmUNIPHY_MACRO_CNTL_RESERVED74                                          0x490a
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED74                             0x490a
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED74                             0x49aa
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED74                             0x9a4a
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED74                             0x9aea
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED74                             0x9b8a
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED74                             0x9c2a
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED74                             0x9cca
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED74                             0x9d6a
+#define mmUNIPHY_MACRO_CNTL_RESERVED75                                          0x490b
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED75                             0x490b
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED75                             0x49ab
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED75                             0x9a4b
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED75                             0x9aeb
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED75                             0x9b8b
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED75                             0x9c2b
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED75                             0x9ccb
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED75                             0x9d6b
+#define mmUNIPHY_MACRO_CNTL_RESERVED76                                          0x490c
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED76                             0x490c
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED76                             0x49ac
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED76                             0x9a4c
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED76                             0x9aec
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED76                             0x9b8c
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED76                             0x9c2c
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED76                             0x9ccc
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED76                             0x9d6c
+#define mmUNIPHY_MACRO_CNTL_RESERVED77                                          0x490d
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED77                             0x490d
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED77                             0x49ad
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED77                             0x9a4d
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED77                             0x9aed
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED77                             0x9b8d
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED77                             0x9c2d
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED77                             0x9ccd
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED77                             0x9d6d
+#define mmUNIPHY_MACRO_CNTL_RESERVED78                                          0x490e
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED78                             0x490e
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED78                             0x49ae
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED78                             0x9a4e
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED78                             0x9aee
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED78                             0x9b8e
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED78                             0x9c2e
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED78                             0x9cce
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED78                             0x9d6e
+#define mmUNIPHY_MACRO_CNTL_RESERVED79                                          0x490f
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED79                             0x490f
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED79                             0x49af
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED79                             0x9a4f
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED79                             0x9aef
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED79                             0x9b8f
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED79                             0x9c2f
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED79                             0x9ccf
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED79                             0x9d6f
+#define mmUNIPHY_MACRO_CNTL_RESERVED80                                          0x4910
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED80                             0x4910
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED80                             0x49b0
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED80                             0x9a50
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED80                             0x9af0
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED80                             0x9b90
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED80                             0x9c30
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED80                             0x9cd0
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED80                             0x9d70
+#define mmUNIPHY_MACRO_CNTL_RESERVED81                                          0x4911
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED81                             0x4911
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED81                             0x49b1
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED81                             0x9a51
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED81                             0x9af1
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED81                             0x9b91
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED81                             0x9c31
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED81                             0x9cd1
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED81                             0x9d71
+#define mmUNIPHY_MACRO_CNTL_RESERVED82                                          0x4912
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED82                             0x4912
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED82                             0x49b2
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED82                             0x9a52
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED82                             0x9af2
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED82                             0x9b92
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED82                             0x9c32
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED82                             0x9cd2
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED82                             0x9d72
+#define mmUNIPHY_MACRO_CNTL_RESERVED83                                          0x4913
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED83                             0x4913
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED83                             0x49b3
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED83                             0x9a53
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED83                             0x9af3
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED83                             0x9b93
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED83                             0x9c33
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED83                             0x9cd3
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED83                             0x9d73
+#define mmUNIPHY_MACRO_CNTL_RESERVED84                                          0x4914
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED84                             0x4914
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED84                             0x49b4
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED84                             0x9a54
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED84                             0x9af4
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED84                             0x9b94
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED84                             0x9c34
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED84                             0x9cd4
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED84                             0x9d74
+#define mmUNIPHY_MACRO_CNTL_RESERVED85                                          0x4915
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED85                             0x4915
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED85                             0x49b5
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED85                             0x9a55
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED85                             0x9af5
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED85                             0x9b95
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED85                             0x9c35
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED85                             0x9cd5
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED85                             0x9d75
+#define mmUNIPHY_MACRO_CNTL_RESERVED86                                          0x4916
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED86                             0x4916
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED86                             0x49b6
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED86                             0x9a56
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED86                             0x9af6
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED86                             0x9b96
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED86                             0x9c36
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED86                             0x9cd6
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED86                             0x9d76
+#define mmUNIPHY_MACRO_CNTL_RESERVED87                                          0x4917
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED87                             0x4917
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED87                             0x49b7
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED87                             0x9a57
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED87                             0x9af7
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED87                             0x9b97
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED87                             0x9c37
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED87                             0x9cd7
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED87                             0x9d77
+#define mmUNIPHY_MACRO_CNTL_RESERVED88                                          0x4918
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED88                             0x4918
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED88                             0x49b8
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED88                             0x9a58
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED88                             0x9af8
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED88                             0x9b98
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED88                             0x9c38
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED88                             0x9cd8
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED88                             0x9d78
+#define mmUNIPHY_MACRO_CNTL_RESERVED89                                          0x4919
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED89                             0x4919
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED89                             0x49b9
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED89                             0x9a59
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED89                             0x9af9
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED89                             0x9b99
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED89                             0x9c39
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED89                             0x9cd9
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED89                             0x9d79
+#define mmUNIPHY_MACRO_CNTL_RESERVED90                                          0x491a
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED90                             0x491a
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED90                             0x49ba
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED90                             0x9a5a
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED90                             0x9afa
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED90                             0x9b9a
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED90                             0x9c3a
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED90                             0x9cda
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED90                             0x9d7a
+#define mmUNIPHY_MACRO_CNTL_RESERVED91                                          0x491b
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED91                             0x491b
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED91                             0x49bb
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED91                             0x9a5b
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED91                             0x9afb
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED91                             0x9b9b
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED91                             0x9c3b
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED91                             0x9cdb
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED91                             0x9d7b
+#define mmUNIPHY_MACRO_CNTL_RESERVED92                                          0x491c
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED92                             0x491c
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED92                             0x49bc
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED92                             0x9a5c
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED92                             0x9afc
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED92                             0x9b9c
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED92                             0x9c3c
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED92                             0x9cdc
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED92                             0x9d7c
+#define mmUNIPHY_MACRO_CNTL_RESERVED93                                          0x491d
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED93                             0x491d
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED93                             0x49bd
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED93                             0x9a5d
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED93                             0x9afd
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED93                             0x9b9d
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED93                             0x9c3d
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED93                             0x9cdd
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED93                             0x9d7d
+#define mmUNIPHY_MACRO_CNTL_RESERVED94                                          0x491e
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED94                             0x491e
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED94                             0x49be
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED94                             0x9a5e
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED94                             0x9afe
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED94                             0x9b9e
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED94                             0x9c3e
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED94                             0x9cde
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED94                             0x9d7e
+#define mmUNIPHY_MACRO_CNTL_RESERVED95                                          0x491f
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED95                             0x491f
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED95                             0x49bf
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED95                             0x9a5f
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED95                             0x9aff
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED95                             0x9b9f
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED95                             0x9c3f
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED95                             0x9cdf
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED95                             0x9d7f
+#define mmUNIPHY_MACRO_CNTL_RESERVED96                                          0x4920
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED96                             0x4920
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED96                             0x49c0
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED96                             0x9a60
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED96                             0x9b00
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED96                             0x9ba0
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED96                             0x9c40
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED96                             0x9ce0
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED96                             0x9d80
+#define mmUNIPHY_MACRO_CNTL_RESERVED97                                          0x4921
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED97                             0x4921
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED97                             0x49c1
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED97                             0x9a61
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED97                             0x9b01
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED97                             0x9ba1
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED97                             0x9c41
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED97                             0x9ce1
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED97                             0x9d81
+#define mmUNIPHY_MACRO_CNTL_RESERVED98                                          0x4922
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED98                             0x4922
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED98                             0x49c2
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED98                             0x9a62
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED98                             0x9b02
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED98                             0x9ba2
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED98                             0x9c42
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED98                             0x9ce2
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED98                             0x9d82
+#define mmUNIPHY_MACRO_CNTL_RESERVED99                                          0x4923
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED99                             0x4923
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED99                             0x49c3
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED99                             0x9a63
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED99                             0x9b03
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED99                             0x9ba3
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED99                             0x9c43
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED99                             0x9ce3
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED99                             0x9d83
+#define mmUNIPHY_MACRO_CNTL_RESERVED100                                         0x4924
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED100                            0x4924
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED100                            0x49c4
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED100                            0x9a64
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED100                            0x9b04
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED100                            0x9ba4
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED100                            0x9c44
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED100                            0x9ce4
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED100                            0x9d84
+#define mmUNIPHY_MACRO_CNTL_RESERVED101                                         0x4925
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED101                            0x4925
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED101                            0x49c5
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED101                            0x9a65
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED101                            0x9b05
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED101                            0x9ba5
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED101                            0x9c45
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED101                            0x9ce5
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED101                            0x9d85
+#define mmUNIPHY_MACRO_CNTL_RESERVED102                                         0x4926
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED102                            0x4926
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED102                            0x49c6
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED102                            0x9a66
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED102                            0x9b06
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED102                            0x9ba6
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED102                            0x9c46
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED102                            0x9ce6
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED102                            0x9d86
+#define mmUNIPHY_MACRO_CNTL_RESERVED103                                         0x4927
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED103                            0x4927
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED103                            0x49c7
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED103                            0x9a67
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED103                            0x9b07
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED103                            0x9ba7
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED103                            0x9c47
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED103                            0x9ce7
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED103                            0x9d87
+#define mmUNIPHY_MACRO_CNTL_RESERVED104                                         0x4928
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED104                            0x4928
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED104                            0x49c8
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED104                            0x9a68
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED104                            0x9b08
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED104                            0x9ba8
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED104                            0x9c48
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED104                            0x9ce8
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED104                            0x9d88
+#define mmUNIPHY_MACRO_CNTL_RESERVED105                                         0x4929
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED105                            0x4929
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED105                            0x49c9
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED105                            0x9a69
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED105                            0x9b09
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED105                            0x9ba9
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED105                            0x9c49
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED105                            0x9ce9
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED105                            0x9d89
+#define mmUNIPHY_MACRO_CNTL_RESERVED106                                         0x492a
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED106                            0x492a
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED106                            0x49ca
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED106                            0x9a6a
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED106                            0x9b0a
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED106                            0x9baa
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED106                            0x9c4a
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED106                            0x9cea
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED106                            0x9d8a
+#define mmUNIPHY_MACRO_CNTL_RESERVED107                                         0x492b
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED107                            0x492b
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED107                            0x49cb
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED107                            0x9a6b
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED107                            0x9b0b
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED107                            0x9bab
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED107                            0x9c4b
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED107                            0x9ceb
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED107                            0x9d8b
+#define mmUNIPHY_MACRO_CNTL_RESERVED108                                         0x492c
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED108                            0x492c
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED108                            0x49cc
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED108                            0x9a6c
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED108                            0x9b0c
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED108                            0x9bac
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED108                            0x9c4c
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED108                            0x9cec
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED108                            0x9d8c
+#define mmUNIPHY_MACRO_CNTL_RESERVED109                                         0x492d
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED109                            0x492d
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED109                            0x49cd
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED109                            0x9a6d
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED109                            0x9b0d
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED109                            0x9bad
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED109                            0x9c4d
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED109                            0x9ced
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED109                            0x9d8d
+#define mmUNIPHY_MACRO_CNTL_RESERVED110                                         0x492e
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED110                            0x492e
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED110                            0x49ce
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED110                            0x9a6e
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED110                            0x9b0e
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED110                            0x9bae
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED110                            0x9c4e
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED110                            0x9cee
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED110                            0x9d8e
+#define mmUNIPHY_MACRO_CNTL_RESERVED111                                         0x492f
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED111                            0x492f
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED111                            0x49cf
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED111                            0x9a6f
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED111                            0x9b0f
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED111                            0x9baf
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED111                            0x9c4f
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED111                            0x9cef
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED111                            0x9d8f
+#define mmUNIPHY_MACRO_CNTL_RESERVED112                                         0x4930
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED112                            0x4930
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED112                            0x49d0
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED112                            0x9a70
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED112                            0x9b10
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED112                            0x9bb0
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED112                            0x9c50
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED112                            0x9cf0
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED112                            0x9d90
+#define mmUNIPHY_MACRO_CNTL_RESERVED113                                         0x4931
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED113                            0x4931
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED113                            0x49d1
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED113                            0x9a71
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED113                            0x9b11
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED113                            0x9bb1
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED113                            0x9c51
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED113                            0x9cf1
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED113                            0x9d91
+#define mmUNIPHY_MACRO_CNTL_RESERVED114                                         0x4932
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED114                            0x4932
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED114                            0x49d2
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED114                            0x9a72
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED114                            0x9b12
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED114                            0x9bb2
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED114                            0x9c52
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED114                            0x9cf2
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED114                            0x9d92
+#define mmUNIPHY_MACRO_CNTL_RESERVED115                                         0x4933
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED115                            0x4933
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED115                            0x49d3
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED115                            0x9a73
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED115                            0x9b13
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED115                            0x9bb3
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED115                            0x9c53
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED115                            0x9cf3
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED115                            0x9d93
+#define mmUNIPHY_MACRO_CNTL_RESERVED116                                         0x4934
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED116                            0x4934
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED116                            0x49d4
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED116                            0x9a74
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED116                            0x9b14
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED116                            0x9bb4
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED116                            0x9c54
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED116                            0x9cf4
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED116                            0x9d94
+#define mmUNIPHY_MACRO_CNTL_RESERVED117                                         0x4935
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED117                            0x4935
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED117                            0x49d5
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED117                            0x9a75
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED117                            0x9b15
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED117                            0x9bb5
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED117                            0x9c55
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED117                            0x9cf5
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED117                            0x9d95
+#define mmUNIPHY_MACRO_CNTL_RESERVED118                                         0x4936
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED118                            0x4936
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED118                            0x49d6
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED118                            0x9a76
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED118                            0x9b16
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED118                            0x9bb6
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED118                            0x9c56
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED118                            0x9cf6
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED118                            0x9d96
+#define mmUNIPHY_MACRO_CNTL_RESERVED119                                         0x4937
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED119                            0x4937
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED119                            0x49d7
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED119                            0x9a77
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED119                            0x9b17
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED119                            0x9bb7
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED119                            0x9c57
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED119                            0x9cf7
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED119                            0x9d97
+#define mmUNIPHY_MACRO_CNTL_RESERVED120                                         0x4938
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED120                            0x4938
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED120                            0x49d8
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED120                            0x9a78
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED120                            0x9b18
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED120                            0x9bb8
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED120                            0x9c58
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED120                            0x9cf8
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED120                            0x9d98
+#define mmUNIPHY_MACRO_CNTL_RESERVED121                                         0x4939
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED121                            0x4939
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED121                            0x49d9
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED121                            0x9a79
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED121                            0x9b19
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED121                            0x9bb9
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED121                            0x9c59
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED121                            0x9cf9
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED121                            0x9d99
+#define mmUNIPHY_MACRO_CNTL_RESERVED122                                         0x493a
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED122                            0x493a
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED122                            0x49da
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED122                            0x9a7a
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED122                            0x9b1a
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED122                            0x9bba
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED122                            0x9c5a
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED122                            0x9cfa
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED122                            0x9d9a
+#define mmUNIPHY_MACRO_CNTL_RESERVED123                                         0x493b
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED123                            0x493b
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED123                            0x49db
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED123                            0x9a7b
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED123                            0x9b1b
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED123                            0x9bbb
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED123                            0x9c5b
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED123                            0x9cfb
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED123                            0x9d9b
+#define mmUNIPHY_MACRO_CNTL_RESERVED124                                         0x493c
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED124                            0x493c
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED124                            0x49dc
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED124                            0x9a7c
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED124                            0x9b1c
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED124                            0x9bbc
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED124                            0x9c5c
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED124                            0x9cfc
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED124                            0x9d9c
+#define mmUNIPHY_MACRO_CNTL_RESERVED125                                         0x493d
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED125                            0x493d
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED125                            0x49dd
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED125                            0x9a7d
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED125                            0x9b1d
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED125                            0x9bbd
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED125                            0x9c5d
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED125                            0x9cfd
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED125                            0x9d9d
+#define mmUNIPHY_MACRO_CNTL_RESERVED126                                         0x493e
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED126                            0x493e
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED126                            0x49de
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED126                            0x9a7e
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED126                            0x9b1e
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED126                            0x9bbe
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED126                            0x9c5e
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED126                            0x9cfe
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED126                            0x9d9e
+#define mmUNIPHY_MACRO_CNTL_RESERVED127                                         0x493f
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED127                            0x493f
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED127                            0x49df
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED127                            0x9a7f
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED127                            0x9b1f
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED127                            0x9bbf
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED127                            0x9c5f
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED127                            0x9cff
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED127                            0x9d9f
+#define mmUNIPHY_MACRO_CNTL_RESERVED128                                         0x4940
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED128                            0x4940
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED128                            0x49e0
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED128                            0x9a80
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED128                            0x9b20
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED128                            0x9bc0
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED128                            0x9c60
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED128                            0x9d00
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED128                            0x9da0
+#define mmUNIPHY_MACRO_CNTL_RESERVED129                                         0x4941
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED129                            0x4941
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED129                            0x49e1
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED129                            0x9a81
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED129                            0x9b21
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED129                            0x9bc1
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED129                            0x9c61
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED129                            0x9d01
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED129                            0x9da1
+#define mmUNIPHY_MACRO_CNTL_RESERVED130                                         0x4942
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED130                            0x4942
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED130                            0x49e2
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED130                            0x9a82
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED130                            0x9b22
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED130                            0x9bc2
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED130                            0x9c62
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED130                            0x9d02
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED130                            0x9da2
+#define mmUNIPHY_MACRO_CNTL_RESERVED131                                         0x4943
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED131                            0x4943
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED131                            0x49e3
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED131                            0x9a83
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED131                            0x9b23
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED131                            0x9bc3
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED131                            0x9c63
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED131                            0x9d03
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED131                            0x9da3
+#define mmUNIPHY_MACRO_CNTL_RESERVED132                                         0x4944
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED132                            0x4944
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED132                            0x49e4
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED132                            0x9a84
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED132                            0x9b24
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED132                            0x9bc4
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED132                            0x9c64
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED132                            0x9d04
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED132                            0x9da4
+#define mmUNIPHY_MACRO_CNTL_RESERVED133                                         0x4945
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED133                            0x4945
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED133                            0x49e5
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED133                            0x9a85
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED133                            0x9b25
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED133                            0x9bc5
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED133                            0x9c65
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED133                            0x9d05
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED133                            0x9da5
+#define mmUNIPHY_MACRO_CNTL_RESERVED134                                         0x4946
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED134                            0x4946
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED134                            0x49e6
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED134                            0x9a86
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED134                            0x9b26
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED134                            0x9bc6
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED134                            0x9c66
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED134                            0x9d06
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED134                            0x9da6
+#define mmUNIPHY_MACRO_CNTL_RESERVED135                                         0x4947
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED135                            0x4947
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED135                            0x49e7
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED135                            0x9a87
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED135                            0x9b27
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED135                            0x9bc7
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED135                            0x9c67
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED135                            0x9d07
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED135                            0x9da7
+#define mmUNIPHY_MACRO_CNTL_RESERVED136                                         0x4948
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED136                            0x4948
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED136                            0x49e8
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED136                            0x9a88
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED136                            0x9b28
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED136                            0x9bc8
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED136                            0x9c68
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED136                            0x9d08
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED136                            0x9da8
+#define mmUNIPHY_MACRO_CNTL_RESERVED137                                         0x4949
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED137                            0x4949
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED137                            0x49e9
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED137                            0x9a89
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED137                            0x9b29
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED137                            0x9bc9
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED137                            0x9c69
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED137                            0x9d09
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED137                            0x9da9
+#define mmUNIPHY_MACRO_CNTL_RESERVED138                                         0x494a
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED138                            0x494a
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED138                            0x49ea
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED138                            0x9a8a
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED138                            0x9b2a
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED138                            0x9bca
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED138                            0x9c6a
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED138                            0x9d0a
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED138                            0x9daa
+#define mmUNIPHY_MACRO_CNTL_RESERVED139                                         0x494b
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED139                            0x494b
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED139                            0x49eb
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED139                            0x9a8b
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED139                            0x9b2b
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED139                            0x9bcb
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED139                            0x9c6b
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED139                            0x9d0b
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED139                            0x9dab
+#define mmUNIPHY_MACRO_CNTL_RESERVED140                                         0x494c
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED140                            0x494c
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED140                            0x49ec
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED140                            0x9a8c
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED140                            0x9b2c
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED140                            0x9bcc
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED140                            0x9c6c
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED140                            0x9d0c
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED140                            0x9dac
+#define mmUNIPHY_MACRO_CNTL_RESERVED141                                         0x494d
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED141                            0x494d
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED141                            0x49ed
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED141                            0x9a8d
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED141                            0x9b2d
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED141                            0x9bcd
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED141                            0x9c6d
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED141                            0x9d0d
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED141                            0x9dad
+#define mmUNIPHY_MACRO_CNTL_RESERVED142                                         0x494e
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED142                            0x494e
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED142                            0x49ee
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED142                            0x9a8e
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED142                            0x9b2e
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED142                            0x9bce
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED142                            0x9c6e
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED142                            0x9d0e
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED142                            0x9dae
+#define mmUNIPHY_MACRO_CNTL_RESERVED143                                         0x494f
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED143                            0x494f
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED143                            0x49ef
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED143                            0x9a8f
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED143                            0x9b2f
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED143                            0x9bcf
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED143                            0x9c6f
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED143                            0x9d0f
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED143                            0x9daf
+#define mmUNIPHY_MACRO_CNTL_RESERVED144                                         0x4950
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED144                            0x4950
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED144                            0x49f0
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED144                            0x9a90
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED144                            0x9b30
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED144                            0x9bd0
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED144                            0x9c70
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED144                            0x9d10
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED144                            0x9db0
+#define mmUNIPHY_MACRO_CNTL_RESERVED145                                         0x4951
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED145                            0x4951
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED145                            0x49f1
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED145                            0x9a91
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED145                            0x9b31
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED145                            0x9bd1
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED145                            0x9c71
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED145                            0x9d11
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED145                            0x9db1
+#define mmUNIPHY_MACRO_CNTL_RESERVED146                                         0x4952
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED146                            0x4952
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED146                            0x49f2
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED146                            0x9a92
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED146                            0x9b32
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED146                            0x9bd2
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED146                            0x9c72
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED146                            0x9d12
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED146                            0x9db2
+#define mmUNIPHY_MACRO_CNTL_RESERVED147                                         0x4953
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED147                            0x4953
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED147                            0x49f3
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED147                            0x9a93
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED147                            0x9b33
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED147                            0x9bd3
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED147                            0x9c73
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED147                            0x9d13
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED147                            0x9db3
+#define mmUNIPHY_MACRO_CNTL_RESERVED148                                         0x4954
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED148                            0x4954
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED148                            0x49f4
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED148                            0x9a94
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED148                            0x9b34
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED148                            0x9bd4
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED148                            0x9c74
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED148                            0x9d14
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED148                            0x9db4
+#define mmUNIPHY_MACRO_CNTL_RESERVED149                                         0x4955
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED149                            0x4955
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED149                            0x49f5
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED149                            0x9a95
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED149                            0x9b35
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED149                            0x9bd5
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED149                            0x9c75
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED149                            0x9d15
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED149                            0x9db5
+#define mmUNIPHY_MACRO_CNTL_RESERVED150                                         0x4956
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED150                            0x4956
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED150                            0x49f6
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED150                            0x9a96
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED150                            0x9b36
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED150                            0x9bd6
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED150                            0x9c76
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED150                            0x9d16
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED150                            0x9db6
+#define mmUNIPHY_MACRO_CNTL_RESERVED151                                         0x4957
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED151                            0x4957
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED151                            0x49f7
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED151                            0x9a97
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED151                            0x9b37
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED151                            0x9bd7
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED151                            0x9c77
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED151                            0x9d17
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED151                            0x9db7
+#define mmUNIPHY_MACRO_CNTL_RESERVED152                                         0x4958
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED152                            0x4958
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED152                            0x49f8
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED152                            0x9a98
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED152                            0x9b38
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED152                            0x9bd8
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED152                            0x9c78
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED152                            0x9d18
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED152                            0x9db8
+#define mmUNIPHY_MACRO_CNTL_RESERVED153                                         0x4959
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED153                            0x4959
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED153                            0x49f9
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED153                            0x9a99
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED153                            0x9b39
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED153                            0x9bd9
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED153                            0x9c79
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED153                            0x9d19
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED153                            0x9db9
+#define mmUNIPHY_MACRO_CNTL_RESERVED154                                         0x495a
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED154                            0x495a
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED154                            0x49fa
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED154                            0x9a9a
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED154                            0x9b3a
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED154                            0x9bda
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED154                            0x9c7a
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED154                            0x9d1a
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED154                            0x9dba
+#define mmUNIPHY_MACRO_CNTL_RESERVED155                                         0x495b
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED155                            0x495b
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED155                            0x49fb
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED155                            0x9a9b
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED155                            0x9b3b
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED155                            0x9bdb
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED155                            0x9c7b
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED155                            0x9d1b
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED155                            0x9dbb
+#define mmUNIPHY_MACRO_CNTL_RESERVED156                                         0x495c
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED156                            0x495c
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED156                            0x49fc
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED156                            0x9a9c
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED156                            0x9b3c
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED156                            0x9bdc
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED156                            0x9c7c
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED156                            0x9d1c
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED156                            0x9dbc
+#define mmUNIPHY_MACRO_CNTL_RESERVED157                                         0x495d
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED157                            0x495d
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED157                            0x49fd
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED157                            0x9a9d
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED157                            0x9b3d
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED157                            0x9bdd
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED157                            0x9c7d
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED157                            0x9d1d
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED157                            0x9dbd
+#define mmUNIPHY_MACRO_CNTL_RESERVED158                                         0x495e
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED158                            0x495e
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED158                            0x49fe
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED158                            0x9a9e
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED158                            0x9b3e
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED158                            0x9bde
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED158                            0x9c7e
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED158                            0x9d1e
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED158                            0x9dbe
+#define mmUNIPHY_MACRO_CNTL_RESERVED159                                         0x495f
+#define mmDCIO_UNIPHY0_UNIPHY_MACRO_CNTL_RESERVED159                            0x495f
+#define mmDCIO_UNIPHY1_UNIPHY_MACRO_CNTL_RESERVED159                            0x49ff
+#define mmDCIO_UNIPHY2_UNIPHY_MACRO_CNTL_RESERVED159                            0x9a9f
+#define mmDCIO_UNIPHY3_UNIPHY_MACRO_CNTL_RESERVED159                            0x9b3f
+#define mmDCIO_UNIPHY4_UNIPHY_MACRO_CNTL_RESERVED159                            0x9bdf
+#define mmDCIO_UNIPHY5_UNIPHY_MACRO_CNTL_RESERVED159                            0x9c7f
+#define mmDCIO_UNIPHY6_UNIPHY_MACRO_CNTL_RESERVED159                            0x9d1f
+#define mmDCIO_UNIPHY7_UNIPHY_MACRO_CNTL_RESERVED159                            0x9dbf
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED0                                         0x5a84
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED1                                         0x5a85
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED2                                         0x5a86
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED3                                         0x5a87
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED4                                         0x5a88
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED5                                         0x5a89
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED6                                         0x5a8a
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED7                                         0x5a8b
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED8                                         0x5a8c
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED9                                         0x5a8d
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED10                                        0x5a8e
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED11                                        0x5a8f
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED12                                        0x5a90
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED13                                        0x5a91
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED14                                        0x5a92
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED15                                        0x5a93
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED16                                        0x5a94
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED17                                        0x5a95
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED18                                        0x5a96
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED19                                        0x5a97
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED20                                        0x5a98
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED21                                        0x5a99
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED22                                        0x5a9a
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED23                                        0x5a9b
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED24                                        0x5a9c
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED25                                        0x5a9d
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED26                                        0x5a9e
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED27                                        0x5a9f
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED28                                        0x5aa0
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED29                                        0x5aa1
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED30                                        0x5aa2
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED31                                        0x5aa3
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED32                                        0x5aa4
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED33                                        0x5aa5
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED34                                        0x5aa6
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED35                                        0x5aa7
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED36                                        0x5aa8
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED37                                        0x5aa9
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED38                                        0x5aaa
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED39                                        0x5aab
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED40                                        0x5aac
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED41                                        0x5aad
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED42                                        0x5aae
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED43                                        0x5aaf
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED44                                        0x5ab0
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED45                                        0x5ab1
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED46                                        0x5ab2
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED47                                        0x5ab3
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED48                                        0x5ab4
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED49                                        0x5ab5
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED50                                        0x5ab6
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED51                                        0x5ab7
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED52                                        0x5ab8
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED53                                        0x5ab9
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED54                                        0x5aba
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED55                                        0x5abb
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED56                                        0x5abc
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED57                                        0x5abd
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED58                                        0x5abe
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED59                                        0x5abf
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED60                                        0x5ac0
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED61                                        0x5ac1
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED62                                        0x5ac2
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED63                                        0x5ac3
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED64                                        0x5ac4
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED65                                        0x5ac5
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED66                                        0x5ac6
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED67                                        0x5ac7
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED68                                        0x5ac8
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED69                                        0x5ac9
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED70                                        0x5aca
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED71                                        0x5acb
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED72                                        0x5acc
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED73                                        0x5acd
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED74                                        0x5ace
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED75                                        0x5acf
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED76                                        0x5ad0
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED77                                        0x5ad1
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED78                                        0x5ad2
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED79                                        0x5ad3
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED80                                        0x5ad4
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED81                                        0x5ad5
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED82                                        0x5ad6
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED83                                        0x5ad7
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED84                                        0x5ad8
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED85                                        0x5ad9
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED86                                        0x5ada
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED87                                        0x5adb
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED88                                        0x5adc
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED89                                        0x5add
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED90                                        0x5ade
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED91                                        0x5adf
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED92                                        0x5ae0
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED93                                        0x5ae1
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED94                                        0x5ae2
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED95                                        0x5ae3
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED96                                        0x5ae4
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED97                                        0x5ae5
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED98                                        0x5ae6
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED99                                        0x5ae7
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED100                                       0x5ae8
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED101                                       0x5ae9
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED102                                       0x5aea
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED103                                       0x5aeb
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED104                                       0x5aec
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED105                                       0x5aed
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED106                                       0x5aee
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED107                                       0x5aef
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED108                                       0x5af0
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED109                                       0x5af1
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED110                                       0x5af2
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED111                                       0x5af3
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED112                                       0x5af4
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED113                                       0x5af5
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED114                                       0x5af6
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED115                                       0x5af7
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED116                                       0x5af8
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED117                                       0x5af9
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED118                                       0x5afa
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED119                                       0x5afb
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED120                                       0x5afc
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED121                                       0x5afd
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED122                                       0x5afe
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED123                                       0x5aff
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED124                                       0x5b00
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED125                                       0x5b01
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED126                                       0x5b02
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED127                                       0x5b03
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED128                                       0x5b04
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED129                                       0x5b05
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED130                                       0x5b06
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED131                                       0x5b07
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED132                                       0x5b08
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED133                                       0x5b09
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED134                                       0x5b0a
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED135                                       0x5b0b
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED136                                       0x5b0c
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED137                                       0x5b0d
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED138                                       0x5b0e
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED139                                       0x5b0f
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED140                                       0x5b10
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED141                                       0x5b11
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED142                                       0x5b12
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED143                                       0x5b13
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED144                                       0x5b14
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED145                                       0x5b15
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED146                                       0x5b16
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED147                                       0x5b17
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED148                                       0x5b18
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED149                                       0x5b19
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED150                                       0x5b1a
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED151                                       0x5b1b
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED152                                       0x5b1c
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED153                                       0x5b1d
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED154                                       0x5b1e
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED155                                       0x5b1f
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED156                                       0x5b20
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED157                                       0x5b21
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED158                                       0x5b22
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED159                                       0x5b23
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED160                                       0x5b24
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED161                                       0x5b25
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED162                                       0x5b26
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED163                                       0x5b27
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED164                                       0x5b28
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED165                                       0x5b29
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED166                                       0x5b2a
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED167                                       0x5b2b
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED168                                       0x5b2c
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED169                                       0x5b2d
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED170                                       0x5b2e
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED171                                       0x5b2f
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED172                                       0x5b30
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED173                                       0x5b31
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED174                                       0x5b32
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED175                                       0x5b33
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED176                                       0x5b34
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED177                                       0x5b35
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED178                                       0x5b36
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED179                                       0x5b37
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED180                                       0x5b38
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED181                                       0x5b39
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED182                                       0x5b3a
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED183                                       0x5b3b
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED184                                       0x5b3c
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED185                                       0x5b3d
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED186                                       0x5b3e
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED187                                       0x5b3f
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED188                                       0x5b40
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED189                                       0x5b41
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED190                                       0x5b42
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED191                                       0x5b43
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED192                                       0x5b44
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED193                                       0x5b45
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED194                                       0x5b46
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED195                                       0x5b47
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED196                                       0x5b48
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED197                                       0x5b49
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED198                                       0x5b4a
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED199                                       0x5b4b
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED200                                       0x5b4c
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED201                                       0x5b4d
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED202                                       0x5b4e
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED203                                       0x5b4f
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED204                                       0x5b50
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED205                                       0x5b51
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED206                                       0x5b52
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED207                                       0x5b53
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED208                                       0x5b54
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED209                                       0x5b55
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED210                                       0x5b56
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED211                                       0x5b57
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED212                                       0x5b58
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED213                                       0x5b59
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED214                                       0x5b5a
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED215                                       0x5b5b
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED216                                       0x5b5c
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED217                                       0x5b5d
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED218                                       0x5b5e
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED219                                       0x5b5f
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED220                                       0x5b60
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED221                                       0x5b61
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED222                                       0x5b62
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED223                                       0x5b63
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED224                                       0x5b64
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED225                                       0x5b65
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED226                                       0x5b66
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED227                                       0x5b67
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED228                                       0x5b68
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED229                                       0x5b69
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED230                                       0x5b6a
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED231                                       0x5b6b
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED232                                       0x5b6c
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED233                                       0x5b6d
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED234                                       0x5b6e
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED235                                       0x5b6f
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED236                                       0x5b70
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED237                                       0x5b71
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED238                                       0x5b72
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED239                                       0x5b73
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED240                                       0x5b74
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED241                                       0x5b75
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED242                                       0x5b76
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED243                                       0x5b77
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED244                                       0x5b78
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED245                                       0x5b79
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED246                                       0x5b7a
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED247                                       0x5b7b
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED248                                       0x5b7c
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED249                                       0x5b7d
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED250                                       0x5b7e
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED251                                       0x5b7f
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED252                                       0x5b80
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED253                                       0x5b81
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED254                                       0x5b82
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED255                                       0x5b83
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED256                                       0x5b84
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED257                                       0x5b85
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED258                                       0x5b86
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED259                                       0x5b87
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED260                                       0x5b88
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED261                                       0x5b89
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED262                                       0x5b8a
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED263                                       0x5b8b
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED264                                       0x5b8c
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED265                                       0x5b8d
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED266                                       0x5b8e
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED267                                       0x5b8f
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED268                                       0x5b90
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED269                                       0x5b91
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED270                                       0x5b92
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED271                                       0x5b93
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED272                                       0x5b94
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED273                                       0x5b95
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED274                                       0x5b96
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED275                                       0x5b97
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED276                                       0x5b98
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED277                                       0x5b99
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED278                                       0x5b9a
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED279                                       0x5b9b
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED280                                       0x5b9c
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED281                                       0x5b9d
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED282                                       0x5b9e
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED283                                       0x5b9f
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED284                                       0x5ba0
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED285                                       0x5ba1
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED286                                       0x5ba2
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED287                                       0x5ba3
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED288                                       0x5ba4
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED289                                       0x5ba5
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED290                                       0x5ba6
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED291                                       0x5ba7
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED292                                       0x5ba8
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED293                                       0x5ba9
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED294                                       0x5baa
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED295                                       0x5bab
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED296                                       0x5bac
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED297                                       0x5bad
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED298                                       0x5bae
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED299                                       0x5baf
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED300                                       0x5bb0
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED301                                       0x5bb1
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED302                                       0x5bb2
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED303                                       0x5bb3
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED304                                       0x5bb4
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED305                                       0x5bb5
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED306                                       0x5bb6
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED307                                       0x5bb7
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED308                                       0x5bb8
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED309                                       0x5bb9
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED310                                       0x5bba
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED311                                       0x5bbb
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED312                                       0x5bbc
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED313                                       0x5bbd
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED314                                       0x5bbe
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED315                                       0x5bbf
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED316                                       0x5bc0
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED317                                       0x5bc1
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED318                                       0x5bc2
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED319                                       0x5bc3
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED320                                       0x5bc4
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED321                                       0x5bc5
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED322                                       0x5bc6
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED323                                       0x5bc7
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED324                                       0x5bc8
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED325                                       0x5bc9
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED326                                       0x5bca
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED327                                       0x5bcb
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED328                                       0x5bcc
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED329                                       0x5bcd
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED330                                       0x5bce
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED331                                       0x5bcf
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED332                                       0x5bd0
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED333                                       0x5bd1
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED334                                       0x5bd2
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED335                                       0x5bd3
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED336                                       0x5bd4
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED337                                       0x5bd5
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED338                                       0x5bd6
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED339                                       0x5bd7
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED340                                       0x5bd8
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED341                                       0x5bd9
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED342                                       0x5bda
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED343                                       0x5bdb
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED344                                       0x5bdc
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED345                                       0x5bdd
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED346                                       0x5bde
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED347                                       0x5bdf
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED348                                       0x5be0
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED349                                       0x5be1
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED350                                       0x5be2
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED351                                       0x5be3
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED352                                       0x5be4
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED353                                       0x5be5
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED354                                       0x5be6
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED355                                       0x5be7
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED356                                       0x5be8
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED357                                       0x5be9
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED358                                       0x5bea
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED359                                       0x5beb
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED360                                       0x5bec
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED361                                       0x5bed
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED362                                       0x5bee
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED363                                       0x5bef
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED364                                       0x5bf0
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED365                                       0x5bf1
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED366                                       0x5bf2
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED367                                       0x5bf3
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED368                                       0x5bf4
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED369                                       0x5bf5
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED370                                       0x5bf6
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED371                                       0x5bf7
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED372                                       0x5bf8
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED373                                       0x5bf9
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED374                                       0x5bfa
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED375                                       0x5bfb
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED376                                       0x5bfc
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED377                                       0x5bfd
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED378                                       0x5bfe
+#define mmDCRX_PHY_MACRO_CNTL_RESERVED379                                       0x5bff
+#define mmDPHY_MACRO_CNTL_RESERVED0                                             0x5d98
+#define mmDPHY_MACRO_CNTL_RESERVED1                                             0x5d99
+#define mmDPHY_MACRO_CNTL_RESERVED2                                             0x5d9a
+#define mmDPHY_MACRO_CNTL_RESERVED3                                             0x5d9b
+#define mmDPHY_MACRO_CNTL_RESERVED4                                             0x5d9c
+#define mmDPHY_MACRO_CNTL_RESERVED5                                             0x5d9d
+#define mmDPHY_MACRO_CNTL_RESERVED6                                             0x5d9e
+#define mmDPHY_MACRO_CNTL_RESERVED7                                             0x5d9f
+#define mmDPHY_MACRO_CNTL_RESERVED8                                             0x5da0
+#define mmDPHY_MACRO_CNTL_RESERVED9                                             0x5da1
+#define mmDPHY_MACRO_CNTL_RESERVED10                                            0x5da2
+#define mmDPHY_MACRO_CNTL_RESERVED11                                            0x5da3
+#define mmDPHY_MACRO_CNTL_RESERVED12                                            0x5da4
+#define mmDPHY_MACRO_CNTL_RESERVED13                                            0x5da5
+#define mmDPHY_MACRO_CNTL_RESERVED14                                            0x5da6
+#define mmDPHY_MACRO_CNTL_RESERVED15                                            0x5da7
+#define mmDPHY_MACRO_CNTL_RESERVED16                                            0x5da8
+#define mmDPHY_MACRO_CNTL_RESERVED17                                            0x5da9
+#define mmDPHY_MACRO_CNTL_RESERVED18                                            0x5daa
+#define mmDPHY_MACRO_CNTL_RESERVED19                                            0x5dab
+#define mmDPHY_MACRO_CNTL_RESERVED20                                            0x5dac
+#define mmDPHY_MACRO_CNTL_RESERVED21                                            0x5dad
+#define mmDPHY_MACRO_CNTL_RESERVED22                                            0x5dae
+#define mmDPHY_MACRO_CNTL_RESERVED23                                            0x5daf
+#define mmDPHY_MACRO_CNTL_RESERVED24                                            0x5db0
+#define mmDPHY_MACRO_CNTL_RESERVED25                                            0x5db1
+#define mmDPHY_MACRO_CNTL_RESERVED26                                            0x5db2
+#define mmDPHY_MACRO_CNTL_RESERVED27                                            0x5db3
+#define mmDPHY_MACRO_CNTL_RESERVED28                                            0x5db4
+#define mmDPHY_MACRO_CNTL_RESERVED29                                            0x5db5
+#define mmDPHY_MACRO_CNTL_RESERVED30                                            0x5db6
+#define mmDPHY_MACRO_CNTL_RESERVED31                                            0x5db7
+#define mmDPHY_MACRO_CNTL_RESERVED32                                            0x5db8
+#define mmDPHY_MACRO_CNTL_RESERVED33                                            0x5db9
+#define mmDPHY_MACRO_CNTL_RESERVED34                                            0x5dba
+#define mmDPHY_MACRO_CNTL_RESERVED35                                            0x5dbb
+#define mmDPHY_MACRO_CNTL_RESERVED36                                            0x5dbc
+#define mmDPHY_MACRO_CNTL_RESERVED37                                            0x5dbd
+#define mmDPHY_MACRO_CNTL_RESERVED38                                            0x5dbe
+#define mmDPHY_MACRO_CNTL_RESERVED39                                            0x5dbf
+#define mmDPHY_MACRO_CNTL_RESERVED40                                            0x5dc0
+#define mmDPHY_MACRO_CNTL_RESERVED41                                            0x5dc1
+#define mmDPHY_MACRO_CNTL_RESERVED42                                            0x5dc2
+#define mmDPHY_MACRO_CNTL_RESERVED43                                            0x5dc3
+#define mmDPHY_MACRO_CNTL_RESERVED44                                            0x5dc4
+#define mmDPHY_MACRO_CNTL_RESERVED45                                            0x5dc5
+#define mmDPHY_MACRO_CNTL_RESERVED46                                            0x5dc6
+#define mmDPHY_MACRO_CNTL_RESERVED47                                            0x5dc7
+#define mmDPHY_MACRO_CNTL_RESERVED48                                            0x5dc8
+#define mmDPHY_MACRO_CNTL_RESERVED49                                            0x5dc9
+#define mmDPHY_MACRO_CNTL_RESERVED50                                            0x5dca
+#define mmDPHY_MACRO_CNTL_RESERVED51                                            0x5dcb
+#define mmDPHY_MACRO_CNTL_RESERVED52                                            0x5dcc
+#define mmDPHY_MACRO_CNTL_RESERVED53                                            0x5dcd
+#define mmDPHY_MACRO_CNTL_RESERVED54                                            0x5dce
+#define mmDPHY_MACRO_CNTL_RESERVED55                                            0x5dcf
+#define mmDPHY_MACRO_CNTL_RESERVED56                                            0x5dd0
+#define mmDPHY_MACRO_CNTL_RESERVED57                                            0x5dd1
+#define mmDPHY_MACRO_CNTL_RESERVED58                                            0x5dd2
+#define mmDPHY_MACRO_CNTL_RESERVED59                                            0x5dd3
+#define mmDPHY_MACRO_CNTL_RESERVED60                                            0x5dd4
+#define mmDPHY_MACRO_CNTL_RESERVED61                                            0x5dd5
+#define mmDPHY_MACRO_CNTL_RESERVED62                                            0x5dd6
+#define mmDPHY_MACRO_CNTL_RESERVED63                                            0x5dd7
+#define mmGRPH_ENABLE                                                           0x1a00
+#define mmDCP0_GRPH_ENABLE                                                      0x1a00
+#define mmDCP1_GRPH_ENABLE                                                      0x1c00
+#define mmDCP2_GRPH_ENABLE                                                      0x1e00
+#define mmDCP3_GRPH_ENABLE                                                      0x4000
+#define mmDCP4_GRPH_ENABLE                                                      0x4200
+#define mmDCP5_GRPH_ENABLE                                                      0x4400
+#define mmGRPH_CONTROL                                                          0x1a01
+#define mmDCP0_GRPH_CONTROL                                                     0x1a01
+#define mmDCP1_GRPH_CONTROL                                                     0x1c01
+#define mmDCP2_GRPH_CONTROL                                                     0x1e01
+#define mmDCP3_GRPH_CONTROL                                                     0x4001
+#define mmDCP4_GRPH_CONTROL                                                     0x4201
+#define mmDCP5_GRPH_CONTROL                                                     0x4401
+#define mmGRPH_LUT_10BIT_BYPASS                                                 0x1a02
+#define mmDCP0_GRPH_LUT_10BIT_BYPASS                                            0x1a02
+#define mmDCP1_GRPH_LUT_10BIT_BYPASS                                            0x1c02
+#define mmDCP2_GRPH_LUT_10BIT_BYPASS                                            0x1e02
+#define mmDCP3_GRPH_LUT_10BIT_BYPASS                                            0x4002
+#define mmDCP4_GRPH_LUT_10BIT_BYPASS                                            0x4202
+#define mmDCP5_GRPH_LUT_10BIT_BYPASS                                            0x4402
+#define mmGRPH_SWAP_CNTL                                                        0x1a03
+#define mmDCP0_GRPH_SWAP_CNTL                                                   0x1a03
+#define mmDCP1_GRPH_SWAP_CNTL                                                   0x1c03
+#define mmDCP2_GRPH_SWAP_CNTL                                                   0x1e03
+#define mmDCP3_GRPH_SWAP_CNTL                                                   0x4003
+#define mmDCP4_GRPH_SWAP_CNTL                                                   0x4203
+#define mmDCP5_GRPH_SWAP_CNTL                                                   0x4403
+#define mmGRPH_PRIMARY_SURFACE_ADDRESS                                          0x1a04
+#define mmDCP0_GRPH_PRIMARY_SURFACE_ADDRESS                                     0x1a04
+#define mmDCP1_GRPH_PRIMARY_SURFACE_ADDRESS                                     0x1c04
+#define mmDCP2_GRPH_PRIMARY_SURFACE_ADDRESS                                     0x1e04
+#define mmDCP3_GRPH_PRIMARY_SURFACE_ADDRESS                                     0x4004
+#define mmDCP4_GRPH_PRIMARY_SURFACE_ADDRESS                                     0x4204
+#define mmDCP5_GRPH_PRIMARY_SURFACE_ADDRESS                                     0x4404
+#define mmGRPH_SECONDARY_SURFACE_ADDRESS                                        0x1a05
+#define mmDCP0_GRPH_SECONDARY_SURFACE_ADDRESS                                   0x1a05
+#define mmDCP1_GRPH_SECONDARY_SURFACE_ADDRESS                                   0x1c05
+#define mmDCP2_GRPH_SECONDARY_SURFACE_ADDRESS                                   0x1e05
+#define mmDCP3_GRPH_SECONDARY_SURFACE_ADDRESS                                   0x4005
+#define mmDCP4_GRPH_SECONDARY_SURFACE_ADDRESS                                   0x4205
+#define mmDCP5_GRPH_SECONDARY_SURFACE_ADDRESS                                   0x4405
+#define mmGRPH_PITCH                                                            0x1a06
+#define mmDCP0_GRPH_PITCH                                                       0x1a06
+#define mmDCP1_GRPH_PITCH                                                       0x1c06
+#define mmDCP2_GRPH_PITCH                                                       0x1e06
+#define mmDCP3_GRPH_PITCH                                                       0x4006
+#define mmDCP4_GRPH_PITCH                                                       0x4206
+#define mmDCP5_GRPH_PITCH                                                       0x4406
+#define mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH                                     0x1a07
+#define mmDCP0_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH                                0x1a07
+#define mmDCP1_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH                                0x1c07
+#define mmDCP2_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH                                0x1e07
+#define mmDCP3_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH                                0x4007
+#define mmDCP4_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH                                0x4207
+#define mmDCP5_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH                                0x4407
+#define mmGRPH_SECONDARY_SURFACE_ADDRESS_HIGH                                   0x1a08
+#define mmDCP0_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH                              0x1a08
+#define mmDCP1_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH                              0x1c08
+#define mmDCP2_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH                              0x1e08
+#define mmDCP3_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH                              0x4008
+#define mmDCP4_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH                              0x4208
+#define mmDCP5_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH                              0x4408
+#define mmGRPH_SURFACE_OFFSET_X                                                 0x1a09
+#define mmDCP0_GRPH_SURFACE_OFFSET_X                                            0x1a09
+#define mmDCP1_GRPH_SURFACE_OFFSET_X                                            0x1c09
+#define mmDCP2_GRPH_SURFACE_OFFSET_X                                            0x1e09
+#define mmDCP3_GRPH_SURFACE_OFFSET_X                                            0x4009
+#define mmDCP4_GRPH_SURFACE_OFFSET_X                                            0x4209
+#define mmDCP5_GRPH_SURFACE_OFFSET_X                                            0x4409
+#define mmGRPH_SURFACE_OFFSET_Y                                                 0x1a0a
+#define mmDCP0_GRPH_SURFACE_OFFSET_Y                                            0x1a0a
+#define mmDCP1_GRPH_SURFACE_OFFSET_Y                                            0x1c0a
+#define mmDCP2_GRPH_SURFACE_OFFSET_Y                                            0x1e0a
+#define mmDCP3_GRPH_SURFACE_OFFSET_Y                                            0x400a
+#define mmDCP4_GRPH_SURFACE_OFFSET_Y                                            0x420a
+#define mmDCP5_GRPH_SURFACE_OFFSET_Y                                            0x440a
+#define mmGRPH_X_START                                                          0x1a0b
+#define mmDCP0_GRPH_X_START                                                     0x1a0b
+#define mmDCP1_GRPH_X_START                                                     0x1c0b
+#define mmDCP2_GRPH_X_START                                                     0x1e0b
+#define mmDCP3_GRPH_X_START                                                     0x400b
+#define mmDCP4_GRPH_X_START                                                     0x420b
+#define mmDCP5_GRPH_X_START                                                     0x440b
+#define mmGRPH_Y_START                                                          0x1a0c
+#define mmDCP0_GRPH_Y_START                                                     0x1a0c
+#define mmDCP1_GRPH_Y_START                                                     0x1c0c
+#define mmDCP2_GRPH_Y_START                                                     0x1e0c
+#define mmDCP3_GRPH_Y_START                                                     0x400c
+#define mmDCP4_GRPH_Y_START                                                     0x420c
+#define mmDCP5_GRPH_Y_START                                                     0x440c
+#define mmGRPH_X_END                                                            0x1a0d
+#define mmDCP0_GRPH_X_END                                                       0x1a0d
+#define mmDCP1_GRPH_X_END                                                       0x1c0d
+#define mmDCP2_GRPH_X_END                                                       0x1e0d
+#define mmDCP3_GRPH_X_END                                                       0x400d
+#define mmDCP4_GRPH_X_END                                                       0x420d
+#define mmDCP5_GRPH_X_END                                                       0x440d
+#define mmGRPH_Y_END                                                            0x1a0e
+#define mmDCP0_GRPH_Y_END                                                       0x1a0e
+#define mmDCP1_GRPH_Y_END                                                       0x1c0e
+#define mmDCP2_GRPH_Y_END                                                       0x1e0e
+#define mmDCP3_GRPH_Y_END                                                       0x400e
+#define mmDCP4_GRPH_Y_END                                                       0x420e
+#define mmDCP5_GRPH_Y_END                                                       0x440e
+#define mmINPUT_GAMMA_CONTROL                                                   0x1a10
+#define mmDCP0_INPUT_GAMMA_CONTROL                                              0x1a10
+#define mmDCP1_INPUT_GAMMA_CONTROL                                              0x1c10
+#define mmDCP2_INPUT_GAMMA_CONTROL                                              0x1e10
+#define mmDCP3_INPUT_GAMMA_CONTROL                                              0x4010
+#define mmDCP4_INPUT_GAMMA_CONTROL                                              0x4210
+#define mmDCP5_INPUT_GAMMA_CONTROL                                              0x4410
+#define mmGRPH_UPDATE                                                           0x1a11
+#define mmDCP0_GRPH_UPDATE                                                      0x1a11
+#define mmDCP1_GRPH_UPDATE                                                      0x1c11
+#define mmDCP2_GRPH_UPDATE                                                      0x1e11
+#define mmDCP3_GRPH_UPDATE                                                      0x4011
+#define mmDCP4_GRPH_UPDATE                                                      0x4211
+#define mmDCP5_GRPH_UPDATE                                                      0x4411
+#define mmGRPH_FLIP_CONTROL                                                     0x1a12
+#define mmDCP0_GRPH_FLIP_CONTROL                                                0x1a12
+#define mmDCP1_GRPH_FLIP_CONTROL                                                0x1c12
+#define mmDCP2_GRPH_FLIP_CONTROL                                                0x1e12
+#define mmDCP3_GRPH_FLIP_CONTROL                                                0x4012
+#define mmDCP4_GRPH_FLIP_CONTROL                                                0x4212
+#define mmDCP5_GRPH_FLIP_CONTROL                                                0x4412
+#define mmGRPH_SURFACE_ADDRESS_INUSE                                            0x1a13
+#define mmDCP0_GRPH_SURFACE_ADDRESS_INUSE                                       0x1a13
+#define mmDCP1_GRPH_SURFACE_ADDRESS_INUSE                                       0x1c13
+#define mmDCP2_GRPH_SURFACE_ADDRESS_INUSE                                       0x1e13
+#define mmDCP3_GRPH_SURFACE_ADDRESS_INUSE                                       0x4013
+#define mmDCP4_GRPH_SURFACE_ADDRESS_INUSE                                       0x4213
+#define mmDCP5_GRPH_SURFACE_ADDRESS_INUSE                                       0x4413
+#define mmGRPH_DFQ_CONTROL                                                      0x1a14
+#define mmDCP0_GRPH_DFQ_CONTROL                                                 0x1a14
+#define mmDCP1_GRPH_DFQ_CONTROL                                                 0x1c14
+#define mmDCP2_GRPH_DFQ_CONTROL                                                 0x1e14
+#define mmDCP3_GRPH_DFQ_CONTROL                                                 0x4014
+#define mmDCP4_GRPH_DFQ_CONTROL                                                 0x4214
+#define mmDCP5_GRPH_DFQ_CONTROL                                                 0x4414
+#define mmGRPH_DFQ_STATUS                                                       0x1a15
+#define mmDCP0_GRPH_DFQ_STATUS                                                  0x1a15
+#define mmDCP1_GRPH_DFQ_STATUS                                                  0x1c15
+#define mmDCP2_GRPH_DFQ_STATUS                                                  0x1e15
+#define mmDCP3_GRPH_DFQ_STATUS                                                  0x4015
+#define mmDCP4_GRPH_DFQ_STATUS                                                  0x4215
+#define mmDCP5_GRPH_DFQ_STATUS                                                  0x4415
+#define mmGRPH_INTERRUPT_STATUS                                                 0x1a16
+#define mmDCP0_GRPH_INTERRUPT_STATUS                                            0x1a16
+#define mmDCP1_GRPH_INTERRUPT_STATUS                                            0x1c16
+#define mmDCP2_GRPH_INTERRUPT_STATUS                                            0x1e16
+#define mmDCP3_GRPH_INTERRUPT_STATUS                                            0x4016
+#define mmDCP4_GRPH_INTERRUPT_STATUS                                            0x4216
+#define mmDCP5_GRPH_INTERRUPT_STATUS                                            0x4416
+#define mmGRPH_INTERRUPT_CONTROL                                                0x1a17
+#define mmDCP0_GRPH_INTERRUPT_CONTROL                                           0x1a17
+#define mmDCP1_GRPH_INTERRUPT_CONTROL                                           0x1c17
+#define mmDCP2_GRPH_INTERRUPT_CONTROL                                           0x1e17
+#define mmDCP3_GRPH_INTERRUPT_CONTROL                                           0x4017
+#define mmDCP4_GRPH_INTERRUPT_CONTROL                                           0x4217
+#define mmDCP5_GRPH_INTERRUPT_CONTROL                                           0x4417
+#define mmGRPH_SURFACE_ADDRESS_HIGH_INUSE                                       0x1a18
+#define mmDCP0_GRPH_SURFACE_ADDRESS_HIGH_INUSE                                  0x1a18
+#define mmDCP1_GRPH_SURFACE_ADDRESS_HIGH_INUSE                                  0x1c18
+#define mmDCP2_GRPH_SURFACE_ADDRESS_HIGH_INUSE                                  0x1e18
+#define mmDCP3_GRPH_SURFACE_ADDRESS_HIGH_INUSE                                  0x4018
+#define mmDCP4_GRPH_SURFACE_ADDRESS_HIGH_INUSE                                  0x4218
+#define mmDCP5_GRPH_SURFACE_ADDRESS_HIGH_INUSE                                  0x4418
+#define mmGRPH_COMPRESS_SURFACE_ADDRESS                                         0x1a19
+#define mmDCP0_GRPH_COMPRESS_SURFACE_ADDRESS                                    0x1a19
+#define mmDCP1_GRPH_COMPRESS_SURFACE_ADDRESS                                    0x1c19
+#define mmDCP2_GRPH_COMPRESS_SURFACE_ADDRESS                                    0x1e19
+#define mmDCP3_GRPH_COMPRESS_SURFACE_ADDRESS                                    0x4019
+#define mmDCP4_GRPH_COMPRESS_SURFACE_ADDRESS                                    0x4219
+#define mmDCP5_GRPH_COMPRESS_SURFACE_ADDRESS                                    0x4419
+#define mmGRPH_COMPRESS_PITCH                                                   0x1a1a
+#define mmDCP0_GRPH_COMPRESS_PITCH                                              0x1a1a
+#define mmDCP1_GRPH_COMPRESS_PITCH                                              0x1c1a
+#define mmDCP2_GRPH_COMPRESS_PITCH                                              0x1e1a
+#define mmDCP3_GRPH_COMPRESS_PITCH                                              0x401a
+#define mmDCP4_GRPH_COMPRESS_PITCH                                              0x421a
+#define mmDCP5_GRPH_COMPRESS_PITCH                                              0x441a
+#define mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH                                    0x1a1b
+#define mmDCP0_GRPH_COMPRESS_SURFACE_ADDRESS_HIGH                               0x1a1b
+#define mmDCP1_GRPH_COMPRESS_SURFACE_ADDRESS_HIGH                               0x1c1b
+#define mmDCP2_GRPH_COMPRESS_SURFACE_ADDRESS_HIGH                               0x1e1b
+#define mmDCP3_GRPH_COMPRESS_SURFACE_ADDRESS_HIGH                               0x401b
+#define mmDCP4_GRPH_COMPRESS_SURFACE_ADDRESS_HIGH                               0x421b
+#define mmDCP5_GRPH_COMPRESS_SURFACE_ADDRESS_HIGH                               0x441b
+#define mmGRPH_PIPE_OUTSTANDING_REQUEST_LIMIT                                   0x1a1c
+#define mmDCP0_GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT                              0x1a1c
+#define mmDCP1_GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT                              0x1c1c
+#define mmDCP2_GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT                              0x1e1c
+#define mmDCP3_GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT                              0x401c
+#define mmDCP4_GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT                              0x421c
+#define mmDCP5_GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT                              0x441c
+#define mmPRESCALE_GRPH_CONTROL                                                 0x1a2d
+#define mmDCP0_PRESCALE_GRPH_CONTROL                                            0x1a2d
+#define mmDCP1_PRESCALE_GRPH_CONTROL                                            0x1c2d
+#define mmDCP2_PRESCALE_GRPH_CONTROL                                            0x1e2d
+#define mmDCP3_PRESCALE_GRPH_CONTROL                                            0x402d
+#define mmDCP4_PRESCALE_GRPH_CONTROL                                            0x422d
+#define mmDCP5_PRESCALE_GRPH_CONTROL                                            0x442d
+#define mmPRESCALE_VALUES_GRPH_R                                                0x1a2e
+#define mmDCP0_PRESCALE_VALUES_GRPH_R                                           0x1a2e
+#define mmDCP1_PRESCALE_VALUES_GRPH_R                                           0x1c2e
+#define mmDCP2_PRESCALE_VALUES_GRPH_R                                           0x1e2e
+#define mmDCP3_PRESCALE_VALUES_GRPH_R                                           0x402e
+#define mmDCP4_PRESCALE_VALUES_GRPH_R                                           0x422e
+#define mmDCP5_PRESCALE_VALUES_GRPH_R                                           0x442e
+#define mmPRESCALE_VALUES_GRPH_G                                                0x1a2f
+#define mmDCP0_PRESCALE_VALUES_GRPH_G                                           0x1a2f
+#define mmDCP1_PRESCALE_VALUES_GRPH_G                                           0x1c2f
+#define mmDCP2_PRESCALE_VALUES_GRPH_G                                           0x1e2f
+#define mmDCP3_PRESCALE_VALUES_GRPH_G                                           0x402f
+#define mmDCP4_PRESCALE_VALUES_GRPH_G                                           0x422f
+#define mmDCP5_PRESCALE_VALUES_GRPH_G                                           0x442f
+#define mmPRESCALE_VALUES_GRPH_B                                                0x1a30
+#define mmDCP0_PRESCALE_VALUES_GRPH_B                                           0x1a30
+#define mmDCP1_PRESCALE_VALUES_GRPH_B                                           0x1c30
+#define mmDCP2_PRESCALE_VALUES_GRPH_B                                           0x1e30
+#define mmDCP3_PRESCALE_VALUES_GRPH_B                                           0x4030
+#define mmDCP4_PRESCALE_VALUES_GRPH_B                                           0x4230
+#define mmDCP5_PRESCALE_VALUES_GRPH_B                                           0x4430
+#define mmINPUT_CSC_CONTROL                                                     0x1a35
+#define mmDCP0_INPUT_CSC_CONTROL                                                0x1a35
+#define mmDCP1_INPUT_CSC_CONTROL                                                0x1c35
+#define mmDCP2_INPUT_CSC_CONTROL                                                0x1e35
+#define mmDCP3_INPUT_CSC_CONTROL                                                0x4035
+#define mmDCP4_INPUT_CSC_CONTROL                                                0x4235
+#define mmDCP5_INPUT_CSC_CONTROL                                                0x4435
+#define mmINPUT_CSC_C11_C12                                                     0x1a36
+#define mmDCP0_INPUT_CSC_C11_C12                                                0x1a36
+#define mmDCP1_INPUT_CSC_C11_C12                                                0x1c36
+#define mmDCP2_INPUT_CSC_C11_C12                                                0x1e36
+#define mmDCP3_INPUT_CSC_C11_C12                                                0x4036
+#define mmDCP4_INPUT_CSC_C11_C12                                                0x4236
+#define mmDCP5_INPUT_CSC_C11_C12                                                0x4436
+#define mmINPUT_CSC_C13_C14                                                     0x1a37
+#define mmDCP0_INPUT_CSC_C13_C14                                                0x1a37
+#define mmDCP1_INPUT_CSC_C13_C14                                                0x1c37
+#define mmDCP2_INPUT_CSC_C13_C14                                                0x1e37
+#define mmDCP3_INPUT_CSC_C13_C14                                                0x4037
+#define mmDCP4_INPUT_CSC_C13_C14                                                0x4237
+#define mmDCP5_INPUT_CSC_C13_C14                                                0x4437
+#define mmINPUT_CSC_C21_C22                                                     0x1a38
+#define mmDCP0_INPUT_CSC_C21_C22                                                0x1a38
+#define mmDCP1_INPUT_CSC_C21_C22                                                0x1c38
+#define mmDCP2_INPUT_CSC_C21_C22                                                0x1e38
+#define mmDCP3_INPUT_CSC_C21_C22                                                0x4038
+#define mmDCP4_INPUT_CSC_C21_C22                                                0x4238
+#define mmDCP5_INPUT_CSC_C21_C22                                                0x4438
+#define mmINPUT_CSC_C23_C24                                                     0x1a39
+#define mmDCP0_INPUT_CSC_C23_C24                                                0x1a39
+#define mmDCP1_INPUT_CSC_C23_C24                                                0x1c39
+#define mmDCP2_INPUT_CSC_C23_C24                                                0x1e39
+#define mmDCP3_INPUT_CSC_C23_C24                                                0x4039
+#define mmDCP4_INPUT_CSC_C23_C24                                                0x4239
+#define mmDCP5_INPUT_CSC_C23_C24                                                0x4439
+#define mmINPUT_CSC_C31_C32                                                     0x1a3a
+#define mmDCP0_INPUT_CSC_C31_C32                                                0x1a3a
+#define mmDCP1_INPUT_CSC_C31_C32                                                0x1c3a
+#define mmDCP2_INPUT_CSC_C31_C32                                                0x1e3a
+#define mmDCP3_INPUT_CSC_C31_C32                                                0x403a
+#define mmDCP4_INPUT_CSC_C31_C32                                                0x423a
+#define mmDCP5_INPUT_CSC_C31_C32                                                0x443a
+#define mmINPUT_CSC_C33_C34                                                     0x1a3b
+#define mmDCP0_INPUT_CSC_C33_C34                                                0x1a3b
+#define mmDCP1_INPUT_CSC_C33_C34                                                0x1c3b
+#define mmDCP2_INPUT_CSC_C33_C34                                                0x1e3b
+#define mmDCP3_INPUT_CSC_C33_C34                                                0x403b
+#define mmDCP4_INPUT_CSC_C33_C34                                                0x423b
+#define mmDCP5_INPUT_CSC_C33_C34                                                0x443b
+#define mmOUTPUT_CSC_CONTROL                                                    0x1a3c
+#define mmDCP0_OUTPUT_CSC_CONTROL                                               0x1a3c
+#define mmDCP1_OUTPUT_CSC_CONTROL                                               0x1c3c
+#define mmDCP2_OUTPUT_CSC_CONTROL                                               0x1e3c
+#define mmDCP3_OUTPUT_CSC_CONTROL                                               0x403c
+#define mmDCP4_OUTPUT_CSC_CONTROL                                               0x423c
+#define mmDCP5_OUTPUT_CSC_CONTROL                                               0x443c
+#define mmOUTPUT_CSC_C11_C12                                                    0x1a3d
+#define mmDCP0_OUTPUT_CSC_C11_C12                                               0x1a3d
+#define mmDCP1_OUTPUT_CSC_C11_C12                                               0x1c3d
+#define mmDCP2_OUTPUT_CSC_C11_C12                                               0x1e3d
+#define mmDCP3_OUTPUT_CSC_C11_C12                                               0x403d
+#define mmDCP4_OUTPUT_CSC_C11_C12                                               0x423d
+#define mmDCP5_OUTPUT_CSC_C11_C12                                               0x443d
+#define mmOUTPUT_CSC_C13_C14                                                    0x1a3e
+#define mmDCP0_OUTPUT_CSC_C13_C14                                               0x1a3e
+#define mmDCP1_OUTPUT_CSC_C13_C14                                               0x1c3e
+#define mmDCP2_OUTPUT_CSC_C13_C14                                               0x1e3e
+#define mmDCP3_OUTPUT_CSC_C13_C14                                               0x403e
+#define mmDCP4_OUTPUT_CSC_C13_C14                                               0x423e
+#define mmDCP5_OUTPUT_CSC_C13_C14                                               0x443e
+#define mmOUTPUT_CSC_C21_C22                                                    0x1a3f
+#define mmDCP0_OUTPUT_CSC_C21_C22                                               0x1a3f
+#define mmDCP1_OUTPUT_CSC_C21_C22                                               0x1c3f
+#define mmDCP2_OUTPUT_CSC_C21_C22                                               0x1e3f
+#define mmDCP3_OUTPUT_CSC_C21_C22                                               0x403f
+#define mmDCP4_OUTPUT_CSC_C21_C22                                               0x423f
+#define mmDCP5_OUTPUT_CSC_C21_C22                                               0x443f
+#define mmOUTPUT_CSC_C23_C24                                                    0x1a40
+#define mmDCP0_OUTPUT_CSC_C23_C24                                               0x1a40
+#define mmDCP1_OUTPUT_CSC_C23_C24                                               0x1c40
+#define mmDCP2_OUTPUT_CSC_C23_C24                                               0x1e40
+#define mmDCP3_OUTPUT_CSC_C23_C24                                               0x4040
+#define mmDCP4_OUTPUT_CSC_C23_C24                                               0x4240
+#define mmDCP5_OUTPUT_CSC_C23_C24                                               0x4440
+#define mmOUTPUT_CSC_C31_C32                                                    0x1a41
+#define mmDCP0_OUTPUT_CSC_C31_C32                                               0x1a41
+#define mmDCP1_OUTPUT_CSC_C31_C32                                               0x1c41
+#define mmDCP2_OUTPUT_CSC_C31_C32                                               0x1e41
+#define mmDCP3_OUTPUT_CSC_C31_C32                                               0x4041
+#define mmDCP4_OUTPUT_CSC_C31_C32                                               0x4241
+#define mmDCP5_OUTPUT_CSC_C31_C32                                               0x4441
+#define mmOUTPUT_CSC_C33_C34                                                    0x1a42
+#define mmDCP0_OUTPUT_CSC_C33_C34                                               0x1a42
+#define mmDCP1_OUTPUT_CSC_C33_C34                                               0x1c42
+#define mmDCP2_OUTPUT_CSC_C33_C34                                               0x1e42
+#define mmDCP3_OUTPUT_CSC_C33_C34                                               0x4042
+#define mmDCP4_OUTPUT_CSC_C33_C34                                               0x4242
+#define mmDCP5_OUTPUT_CSC_C33_C34                                               0x4442
+#define mmCOMM_MATRIXA_TRANS_C11_C12                                            0x1a43
+#define mmDCP0_COMM_MATRIXA_TRANS_C11_C12                                       0x1a43
+#define mmDCP1_COMM_MATRIXA_TRANS_C11_C12                                       0x1c43
+#define mmDCP2_COMM_MATRIXA_TRANS_C11_C12                                       0x1e43
+#define mmDCP3_COMM_MATRIXA_TRANS_C11_C12                                       0x4043
+#define mmDCP4_COMM_MATRIXA_TRANS_C11_C12                                       0x4243
+#define mmDCP5_COMM_MATRIXA_TRANS_C11_C12                                       0x4443
+#define mmCOMM_MATRIXA_TRANS_C13_C14                                            0x1a44
+#define mmDCP0_COMM_MATRIXA_TRANS_C13_C14                                       0x1a44
+#define mmDCP1_COMM_MATRIXA_TRANS_C13_C14                                       0x1c44
+#define mmDCP2_COMM_MATRIXA_TRANS_C13_C14                                       0x1e44
+#define mmDCP3_COMM_MATRIXA_TRANS_C13_C14                                       0x4044
+#define mmDCP4_COMM_MATRIXA_TRANS_C13_C14                                       0x4244
+#define mmDCP5_COMM_MATRIXA_TRANS_C13_C14                                       0x4444
+#define mmCOMM_MATRIXA_TRANS_C21_C22                                            0x1a45
+#define mmDCP0_COMM_MATRIXA_TRANS_C21_C22                                       0x1a45
+#define mmDCP1_COMM_MATRIXA_TRANS_C21_C22                                       0x1c45
+#define mmDCP2_COMM_MATRIXA_TRANS_C21_C22                                       0x1e45
+#define mmDCP3_COMM_MATRIXA_TRANS_C21_C22                                       0x4045
+#define mmDCP4_COMM_MATRIXA_TRANS_C21_C22                                       0x4245
+#define mmDCP5_COMM_MATRIXA_TRANS_C21_C22                                       0x4445
+#define mmCOMM_MATRIXA_TRANS_C23_C24                                            0x1a46
+#define mmDCP0_COMM_MATRIXA_TRANS_C23_C24                                       0x1a46
+#define mmDCP1_COMM_MATRIXA_TRANS_C23_C24                                       0x1c46
+#define mmDCP2_COMM_MATRIXA_TRANS_C23_C24                                       0x1e46
+#define mmDCP3_COMM_MATRIXA_TRANS_C23_C24                                       0x4046
+#define mmDCP4_COMM_MATRIXA_TRANS_C23_C24                                       0x4246
+#define mmDCP5_COMM_MATRIXA_TRANS_C23_C24                                       0x4446
+#define mmCOMM_MATRIXA_TRANS_C31_C32                                            0x1a47
+#define mmDCP0_COMM_MATRIXA_TRANS_C31_C32                                       0x1a47
+#define mmDCP1_COMM_MATRIXA_TRANS_C31_C32                                       0x1c47
+#define mmDCP2_COMM_MATRIXA_TRANS_C31_C32                                       0x1e47
+#define mmDCP3_COMM_MATRIXA_TRANS_C31_C32                                       0x4047
+#define mmDCP4_COMM_MATRIXA_TRANS_C31_C32                                       0x4247
+#define mmDCP5_COMM_MATRIXA_TRANS_C31_C32                                       0x4447
+#define mmCOMM_MATRIXA_TRANS_C33_C34                                            0x1a48
+#define mmDCP0_COMM_MATRIXA_TRANS_C33_C34                                       0x1a48
+#define mmDCP1_COMM_MATRIXA_TRANS_C33_C34                                       0x1c48
+#define mmDCP2_COMM_MATRIXA_TRANS_C33_C34                                       0x1e48
+#define mmDCP3_COMM_MATRIXA_TRANS_C33_C34                                       0x4048
+#define mmDCP4_COMM_MATRIXA_TRANS_C33_C34                                       0x4248
+#define mmDCP5_COMM_MATRIXA_TRANS_C33_C34                                       0x4448
+#define mmCOMM_MATRIXB_TRANS_C11_C12                                            0x1a49
+#define mmDCP0_COMM_MATRIXB_TRANS_C11_C12                                       0x1a49
+#define mmDCP1_COMM_MATRIXB_TRANS_C11_C12                                       0x1c49
+#define mmDCP2_COMM_MATRIXB_TRANS_C11_C12                                       0x1e49
+#define mmDCP3_COMM_MATRIXB_TRANS_C11_C12                                       0x4049
+#define mmDCP4_COMM_MATRIXB_TRANS_C11_C12                                       0x4249
+#define mmDCP5_COMM_MATRIXB_TRANS_C11_C12                                       0x4449
+#define mmCOMM_MATRIXB_TRANS_C13_C14                                            0x1a4a
+#define mmDCP0_COMM_MATRIXB_TRANS_C13_C14                                       0x1a4a
+#define mmDCP1_COMM_MATRIXB_TRANS_C13_C14                                       0x1c4a
+#define mmDCP2_COMM_MATRIXB_TRANS_C13_C14                                       0x1e4a
+#define mmDCP3_COMM_MATRIXB_TRANS_C13_C14                                       0x404a
+#define mmDCP4_COMM_MATRIXB_TRANS_C13_C14                                       0x424a
+#define mmDCP5_COMM_MATRIXB_TRANS_C13_C14                                       0x444a
+#define mmCOMM_MATRIXB_TRANS_C21_C22                                            0x1a4b
+#define mmDCP0_COMM_MATRIXB_TRANS_C21_C22                                       0x1a4b
+#define mmDCP1_COMM_MATRIXB_TRANS_C21_C22                                       0x1c4b
+#define mmDCP2_COMM_MATRIXB_TRANS_C21_C22                                       0x1e4b
+#define mmDCP3_COMM_MATRIXB_TRANS_C21_C22                                       0x404b
+#define mmDCP4_COMM_MATRIXB_TRANS_C21_C22                                       0x424b
+#define mmDCP5_COMM_MATRIXB_TRANS_C21_C22                                       0x444b
+#define mmCOMM_MATRIXB_TRANS_C23_C24                                            0x1a4c
+#define mmDCP0_COMM_MATRIXB_TRANS_C23_C24                                       0x1a4c
+#define mmDCP1_COMM_MATRIXB_TRANS_C23_C24                                       0x1c4c
+#define mmDCP2_COMM_MATRIXB_TRANS_C23_C24                                       0x1e4c
+#define mmDCP3_COMM_MATRIXB_TRANS_C23_C24                                       0x404c
+#define mmDCP4_COMM_MATRIXB_TRANS_C23_C24                                       0x424c
+#define mmDCP5_COMM_MATRIXB_TRANS_C23_C24                                       0x444c
+#define mmCOMM_MATRIXB_TRANS_C31_C32                                            0x1a4d
+#define mmDCP0_COMM_MATRIXB_TRANS_C31_C32                                       0x1a4d
+#define mmDCP1_COMM_MATRIXB_TRANS_C31_C32                                       0x1c4d
+#define mmDCP2_COMM_MATRIXB_TRANS_C31_C32                                       0x1e4d
+#define mmDCP3_COMM_MATRIXB_TRANS_C31_C32                                       0x404d
+#define mmDCP4_COMM_MATRIXB_TRANS_C31_C32                                       0x424d
+#define mmDCP5_COMM_MATRIXB_TRANS_C31_C32                                       0x444d
+#define mmCOMM_MATRIXB_TRANS_C33_C34                                            0x1a4e
+#define mmDCP0_COMM_MATRIXB_TRANS_C33_C34                                       0x1a4e
+#define mmDCP1_COMM_MATRIXB_TRANS_C33_C34                                       0x1c4e
+#define mmDCP2_COMM_MATRIXB_TRANS_C33_C34                                       0x1e4e
+#define mmDCP3_COMM_MATRIXB_TRANS_C33_C34                                       0x404e
+#define mmDCP4_COMM_MATRIXB_TRANS_C33_C34                                       0x424e
+#define mmDCP5_COMM_MATRIXB_TRANS_C33_C34                                       0x444e
+#define mmDENORM_CONTROL                                                        0x1a50
+#define mmDCP0_DENORM_CONTROL                                                   0x1a50
+#define mmDCP1_DENORM_CONTROL                                                   0x1c50
+#define mmDCP2_DENORM_CONTROL                                                   0x1e50
+#define mmDCP3_DENORM_CONTROL                                                   0x4050
+#define mmDCP4_DENORM_CONTROL                                                   0x4250
+#define mmDCP5_DENORM_CONTROL                                                   0x4450
+#define mmOUT_ROUND_CONTROL                                                     0x1a51
+#define mmDCP0_OUT_ROUND_CONTROL                                                0x1a51
+#define mmDCP1_OUT_ROUND_CONTROL                                                0x1c51
+#define mmDCP2_OUT_ROUND_CONTROL                                                0x1e51
+#define mmDCP3_OUT_ROUND_CONTROL                                                0x4051
+#define mmDCP4_OUT_ROUND_CONTROL                                                0x4251
+#define mmDCP5_OUT_ROUND_CONTROL                                                0x4451
+#define mmOUT_CLAMP_CONTROL_R_CR                                                0x1a52
+#define mmDCP0_OUT_CLAMP_CONTROL_R_CR                                           0x1a52
+#define mmDCP1_OUT_CLAMP_CONTROL_R_CR                                           0x1c52
+#define mmDCP2_OUT_CLAMP_CONTROL_R_CR                                           0x1e52
+#define mmDCP3_OUT_CLAMP_CONTROL_R_CR                                           0x4052
+#define mmDCP4_OUT_CLAMP_CONTROL_R_CR                                           0x4252
+#define mmDCP5_OUT_CLAMP_CONTROL_R_CR                                           0x4452
+#define mmOUT_CLAMP_CONTROL_G_Y                                                 0x1a9c
+#define mmDCP0_OUT_CLAMP_CONTROL_G_Y                                            0x1a9c
+#define mmDCP1_OUT_CLAMP_CONTROL_G_Y                                            0x1c9c
+#define mmDCP2_OUT_CLAMP_CONTROL_G_Y                                            0x1e9c
+#define mmDCP3_OUT_CLAMP_CONTROL_G_Y                                            0x409c
+#define mmDCP4_OUT_CLAMP_CONTROL_G_Y                                            0x429c
+#define mmDCP5_OUT_CLAMP_CONTROL_G_Y                                            0x449c
+#define mmOUT_CLAMP_CONTROL_B_CB                                                0x1a9d
+#define mmDCP0_OUT_CLAMP_CONTROL_B_CB                                           0x1a9d
+#define mmDCP1_OUT_CLAMP_CONTROL_B_CB                                           0x1c9d
+#define mmDCP2_OUT_CLAMP_CONTROL_B_CB                                           0x1e9d
+#define mmDCP3_OUT_CLAMP_CONTROL_B_CB                                           0x409d
+#define mmDCP4_OUT_CLAMP_CONTROL_B_CB                                           0x429d
+#define mmDCP5_OUT_CLAMP_CONTROL_B_CB                                           0x449d
+#define mmKEY_CONTROL                                                           0x1a53
+#define mmDCP0_KEY_CONTROL                                                      0x1a53
+#define mmDCP1_KEY_CONTROL                                                      0x1c53
+#define mmDCP2_KEY_CONTROL                                                      0x1e53
+#define mmDCP3_KEY_CONTROL                                                      0x4053
+#define mmDCP4_KEY_CONTROL                                                      0x4253
+#define mmDCP5_KEY_CONTROL                                                      0x4453
+#define mmKEY_RANGE_ALPHA                                                       0x1a54
+#define mmDCP0_KEY_RANGE_ALPHA                                                  0x1a54
+#define mmDCP1_KEY_RANGE_ALPHA                                                  0x1c54
+#define mmDCP2_KEY_RANGE_ALPHA                                                  0x1e54
+#define mmDCP3_KEY_RANGE_ALPHA                                                  0x4054
+#define mmDCP4_KEY_RANGE_ALPHA                                                  0x4254
+#define mmDCP5_KEY_RANGE_ALPHA                                                  0x4454
+#define mmKEY_RANGE_RED                                                         0x1a55
+#define mmDCP0_KEY_RANGE_RED                                                    0x1a55
+#define mmDCP1_KEY_RANGE_RED                                                    0x1c55
+#define mmDCP2_KEY_RANGE_RED                                                    0x1e55
+#define mmDCP3_KEY_RANGE_RED                                                    0x4055
+#define mmDCP4_KEY_RANGE_RED                                                    0x4255
+#define mmDCP5_KEY_RANGE_RED                                                    0x4455
+#define mmKEY_RANGE_GREEN                                                       0x1a56
+#define mmDCP0_KEY_RANGE_GREEN                                                  0x1a56
+#define mmDCP1_KEY_RANGE_GREEN                                                  0x1c56
+#define mmDCP2_KEY_RANGE_GREEN                                                  0x1e56
+#define mmDCP3_KEY_RANGE_GREEN                                                  0x4056
+#define mmDCP4_KEY_RANGE_GREEN                                                  0x4256
+#define mmDCP5_KEY_RANGE_GREEN                                                  0x4456
+#define mmKEY_RANGE_BLUE                                                        0x1a57
+#define mmDCP0_KEY_RANGE_BLUE                                                   0x1a57
+#define mmDCP1_KEY_RANGE_BLUE                                                   0x1c57
+#define mmDCP2_KEY_RANGE_BLUE                                                   0x1e57
+#define mmDCP3_KEY_RANGE_BLUE                                                   0x4057
+#define mmDCP4_KEY_RANGE_BLUE                                                   0x4257
+#define mmDCP5_KEY_RANGE_BLUE                                                   0x4457
+#define mmDEGAMMA_CONTROL                                                       0x1a58
+#define mmDCP0_DEGAMMA_CONTROL                                                  0x1a58
+#define mmDCP1_DEGAMMA_CONTROL                                                  0x1c58
+#define mmDCP2_DEGAMMA_CONTROL                                                  0x1e58
+#define mmDCP3_DEGAMMA_CONTROL                                                  0x4058
+#define mmDCP4_DEGAMMA_CONTROL                                                  0x4258
+#define mmDCP5_DEGAMMA_CONTROL                                                  0x4458
+#define mmGAMUT_REMAP_CONTROL                                                   0x1a59
+#define mmDCP0_GAMUT_REMAP_CONTROL                                              0x1a59
+#define mmDCP1_GAMUT_REMAP_CONTROL                                              0x1c59
+#define mmDCP2_GAMUT_REMAP_CONTROL                                              0x1e59
+#define mmDCP3_GAMUT_REMAP_CONTROL                                              0x4059
+#define mmDCP4_GAMUT_REMAP_CONTROL                                              0x4259
+#define mmDCP5_GAMUT_REMAP_CONTROL                                              0x4459
+#define mmGAMUT_REMAP_C11_C12                                                   0x1a5a
+#define mmDCP0_GAMUT_REMAP_C11_C12                                              0x1a5a
+#define mmDCP1_GAMUT_REMAP_C11_C12                                              0x1c5a
+#define mmDCP2_GAMUT_REMAP_C11_C12                                              0x1e5a
+#define mmDCP3_GAMUT_REMAP_C11_C12                                              0x405a
+#define mmDCP4_GAMUT_REMAP_C11_C12                                              0x425a
+#define mmDCP5_GAMUT_REMAP_C11_C12                                              0x445a
+#define mmGAMUT_REMAP_C13_C14                                                   0x1a5b
+#define mmDCP0_GAMUT_REMAP_C13_C14                                              0x1a5b
+#define mmDCP1_GAMUT_REMAP_C13_C14                                              0x1c5b
+#define mmDCP2_GAMUT_REMAP_C13_C14                                              0x1e5b
+#define mmDCP3_GAMUT_REMAP_C13_C14                                              0x405b
+#define mmDCP4_GAMUT_REMAP_C13_C14                                              0x425b
+#define mmDCP5_GAMUT_REMAP_C13_C14                                              0x445b
+#define mmGAMUT_REMAP_C21_C22                                                   0x1a5c
+#define mmDCP0_GAMUT_REMAP_C21_C22                                              0x1a5c
+#define mmDCP1_GAMUT_REMAP_C21_C22                                              0x1c5c
+#define mmDCP2_GAMUT_REMAP_C21_C22                                              0x1e5c
+#define mmDCP3_GAMUT_REMAP_C21_C22                                              0x405c
+#define mmDCP4_GAMUT_REMAP_C21_C22                                              0x425c
+#define mmDCP5_GAMUT_REMAP_C21_C22                                              0x445c
+#define mmGAMUT_REMAP_C23_C24                                                   0x1a5d
+#define mmDCP0_GAMUT_REMAP_C23_C24                                              0x1a5d
+#define mmDCP1_GAMUT_REMAP_C23_C24                                              0x1c5d
+#define mmDCP2_GAMUT_REMAP_C23_C24                                              0x1e5d
+#define mmDCP3_GAMUT_REMAP_C23_C24                                              0x405d
+#define mmDCP4_GAMUT_REMAP_C23_C24                                              0x425d
+#define mmDCP5_GAMUT_REMAP_C23_C24                                              0x445d
+#define mmGAMUT_REMAP_C31_C32                                                   0x1a5e
+#define mmDCP0_GAMUT_REMAP_C31_C32                                              0x1a5e
+#define mmDCP1_GAMUT_REMAP_C31_C32                                              0x1c5e
+#define mmDCP2_GAMUT_REMAP_C31_C32                                              0x1e5e
+#define mmDCP3_GAMUT_REMAP_C31_C32                                              0x405e
+#define mmDCP4_GAMUT_REMAP_C31_C32                                              0x425e
+#define mmDCP5_GAMUT_REMAP_C31_C32                                              0x445e
+#define mmGAMUT_REMAP_C33_C34                                                   0x1a5f
+#define mmDCP0_GAMUT_REMAP_C33_C34                                              0x1a5f
+#define mmDCP1_GAMUT_REMAP_C33_C34                                              0x1c5f
+#define mmDCP2_GAMUT_REMAP_C33_C34                                              0x1e5f
+#define mmDCP3_GAMUT_REMAP_C33_C34                                              0x405f
+#define mmDCP4_GAMUT_REMAP_C33_C34                                              0x425f
+#define mmDCP5_GAMUT_REMAP_C33_C34                                              0x445f
+#define mmDCP_SPATIAL_DITHER_CNTL                                               0x1a60
+#define mmDCP0_DCP_SPATIAL_DITHER_CNTL                                          0x1a60
+#define mmDCP1_DCP_SPATIAL_DITHER_CNTL                                          0x1c60
+#define mmDCP2_DCP_SPATIAL_DITHER_CNTL                                          0x1e60
+#define mmDCP3_DCP_SPATIAL_DITHER_CNTL                                          0x4060
+#define mmDCP4_DCP_SPATIAL_DITHER_CNTL                                          0x4260
+#define mmDCP5_DCP_SPATIAL_DITHER_CNTL                                          0x4460
+#define mmDCP_RANDOM_SEEDS                                                      0x1a61
+#define mmDCP0_DCP_RANDOM_SEEDS                                                 0x1a61
+#define mmDCP1_DCP_RANDOM_SEEDS                                                 0x1c61
+#define mmDCP2_DCP_RANDOM_SEEDS                                                 0x1e61
+#define mmDCP3_DCP_RANDOM_SEEDS                                                 0x4061
+#define mmDCP4_DCP_RANDOM_SEEDS                                                 0x4261
+#define mmDCP5_DCP_RANDOM_SEEDS                                                 0x4461
+#define mmDCP_FP_CONVERTED_FIELD                                                0x1a65
+#define mmDCP0_DCP_FP_CONVERTED_FIELD                                           0x1a65
+#define mmDCP1_DCP_FP_CONVERTED_FIELD                                           0x1c65
+#define mmDCP2_DCP_FP_CONVERTED_FIELD                                           0x1e65
+#define mmDCP3_DCP_FP_CONVERTED_FIELD                                           0x4065
+#define mmDCP4_DCP_FP_CONVERTED_FIELD                                           0x4265
+#define mmDCP5_DCP_FP_CONVERTED_FIELD                                           0x4465
+#define mmCUR_CONTROL                                                           0x1a66
+#define mmDCP0_CUR_CONTROL                                                      0x1a66
+#define mmDCP1_CUR_CONTROL                                                      0x1c66
+#define mmDCP2_CUR_CONTROL                                                      0x1e66
+#define mmDCP3_CUR_CONTROL                                                      0x4066
+#define mmDCP4_CUR_CONTROL                                                      0x4266
+#define mmDCP5_CUR_CONTROL                                                      0x4466
+#define mmCUR_SURFACE_ADDRESS                                                   0x1a67
+#define mmDCP0_CUR_SURFACE_ADDRESS                                              0x1a67
+#define mmDCP1_CUR_SURFACE_ADDRESS                                              0x1c67
+#define mmDCP2_CUR_SURFACE_ADDRESS                                              0x1e67
+#define mmDCP3_CUR_SURFACE_ADDRESS                                              0x4067
+#define mmDCP4_CUR_SURFACE_ADDRESS                                              0x4267
+#define mmDCP5_CUR_SURFACE_ADDRESS                                              0x4467
+#define mmCUR_SIZE                                                              0x1a68
+#define mmDCP0_CUR_SIZE                                                         0x1a68
+#define mmDCP1_CUR_SIZE                                                         0x1c68
+#define mmDCP2_CUR_SIZE                                                         0x1e68
+#define mmDCP3_CUR_SIZE                                                         0x4068
+#define mmDCP4_CUR_SIZE                                                         0x4268
+#define mmDCP5_CUR_SIZE                                                         0x4468
+#define mmCUR_SURFACE_ADDRESS_HIGH                                              0x1a69
+#define mmDCP0_CUR_SURFACE_ADDRESS_HIGH                                         0x1a69
+#define mmDCP1_CUR_SURFACE_ADDRESS_HIGH                                         0x1c69
+#define mmDCP2_CUR_SURFACE_ADDRESS_HIGH                                         0x1e69
+#define mmDCP3_CUR_SURFACE_ADDRESS_HIGH                                         0x4069
+#define mmDCP4_CUR_SURFACE_ADDRESS_HIGH                                         0x4269
+#define mmDCP5_CUR_SURFACE_ADDRESS_HIGH                                         0x4469
+#define mmCUR_POSITION                                                          0x1a6a
+#define mmDCP0_CUR_POSITION                                                     0x1a6a
+#define mmDCP1_CUR_POSITION                                                     0x1c6a
+#define mmDCP2_CUR_POSITION                                                     0x1e6a
+#define mmDCP3_CUR_POSITION                                                     0x406a
+#define mmDCP4_CUR_POSITION                                                     0x426a
+#define mmDCP5_CUR_POSITION                                                     0x446a
+#define mmCUR_HOT_SPOT                                                          0x1a6b
+#define mmDCP0_CUR_HOT_SPOT                                                     0x1a6b
+#define mmDCP1_CUR_HOT_SPOT                                                     0x1c6b
+#define mmDCP2_CUR_HOT_SPOT                                                     0x1e6b
+#define mmDCP3_CUR_HOT_SPOT                                                     0x406b
+#define mmDCP4_CUR_HOT_SPOT                                                     0x426b
+#define mmDCP5_CUR_HOT_SPOT                                                     0x446b
+#define mmCUR_COLOR1                                                            0x1a6c
+#define mmDCP0_CUR_COLOR1                                                       0x1a6c
+#define mmDCP1_CUR_COLOR1                                                       0x1c6c
+#define mmDCP2_CUR_COLOR1                                                       0x1e6c
+#define mmDCP3_CUR_COLOR1                                                       0x406c
+#define mmDCP4_CUR_COLOR1                                                       0x426c
+#define mmDCP5_CUR_COLOR1                                                       0x446c
+#define mmCUR_COLOR2                                                            0x1a6d
+#define mmDCP0_CUR_COLOR2                                                       0x1a6d
+#define mmDCP1_CUR_COLOR2                                                       0x1c6d
+#define mmDCP2_CUR_COLOR2                                                       0x1e6d
+#define mmDCP3_CUR_COLOR2                                                       0x406d
+#define mmDCP4_CUR_COLOR2                                                       0x426d
+#define mmDCP5_CUR_COLOR2                                                       0x446d
+#define mmCUR_UPDATE                                                            0x1a6e
+#define mmDCP0_CUR_UPDATE                                                       0x1a6e
+#define mmDCP1_CUR_UPDATE                                                       0x1c6e
+#define mmDCP2_CUR_UPDATE                                                       0x1e6e
+#define mmDCP3_CUR_UPDATE                                                       0x406e
+#define mmDCP4_CUR_UPDATE                                                       0x426e
+#define mmDCP5_CUR_UPDATE                                                       0x446e
+#define mmCUR_REQUEST_FILTER_CNTL                                               0x1a99
+#define mmDCP0_CUR_REQUEST_FILTER_CNTL                                          0x1a99
+#define mmDCP1_CUR_REQUEST_FILTER_CNTL                                          0x1c99
+#define mmDCP2_CUR_REQUEST_FILTER_CNTL                                          0x1e99
+#define mmDCP3_CUR_REQUEST_FILTER_CNTL                                          0x4099
+#define mmDCP4_CUR_REQUEST_FILTER_CNTL                                          0x4299
+#define mmDCP5_CUR_REQUEST_FILTER_CNTL                                          0x4499
+#define mmCUR_STEREO_CONTROL                                                    0x1a9a
+#define mmDCP0_CUR_STEREO_CONTROL                                               0x1a9a
+#define mmDCP1_CUR_STEREO_CONTROL                                               0x1c9a
+#define mmDCP2_CUR_STEREO_CONTROL                                               0x1e9a
+#define mmDCP3_CUR_STEREO_CONTROL                                               0x409a
+#define mmDCP4_CUR_STEREO_CONTROL                                               0x429a
+#define mmDCP5_CUR_STEREO_CONTROL                                               0x449a
+#define mmDC_LUT_RW_MODE                                                        0x1a78
+#define mmDCP0_DC_LUT_RW_MODE                                                   0x1a78
+#define mmDCP1_DC_LUT_RW_MODE                                                   0x1c78
+#define mmDCP2_DC_LUT_RW_MODE                                                   0x1e78
+#define mmDCP3_DC_LUT_RW_MODE                                                   0x4078
+#define mmDCP4_DC_LUT_RW_MODE                                                   0x4278
+#define mmDCP5_DC_LUT_RW_MODE                                                   0x4478
+#define mmDC_LUT_RW_INDEX                                                       0x1a79
+#define mmDCP0_DC_LUT_RW_INDEX                                                  0x1a79
+#define mmDCP1_DC_LUT_RW_INDEX                                                  0x1c79
+#define mmDCP2_DC_LUT_RW_INDEX                                                  0x1e79
+#define mmDCP3_DC_LUT_RW_INDEX                                                  0x4079
+#define mmDCP4_DC_LUT_RW_INDEX                                                  0x4279
+#define mmDCP5_DC_LUT_RW_INDEX                                                  0x4479
+#define mmDC_LUT_SEQ_COLOR                                                      0x1a7a
+#define mmDCP0_DC_LUT_SEQ_COLOR                                                 0x1a7a
+#define mmDCP1_DC_LUT_SEQ_COLOR                                                 0x1c7a
+#define mmDCP2_DC_LUT_SEQ_COLOR                                                 0x1e7a
+#define mmDCP3_DC_LUT_SEQ_COLOR                                                 0x407a
+#define mmDCP4_DC_LUT_SEQ_COLOR                                                 0x427a
+#define mmDCP5_DC_LUT_SEQ_COLOR                                                 0x447a
+#define mmDC_LUT_PWL_DATA                                                       0x1a7b
+#define mmDCP0_DC_LUT_PWL_DATA                                                  0x1a7b
+#define mmDCP1_DC_LUT_PWL_DATA                                                  0x1c7b
+#define mmDCP2_DC_LUT_PWL_DATA                                                  0x1e7b
+#define mmDCP3_DC_LUT_PWL_DATA                                                  0x407b
+#define mmDCP4_DC_LUT_PWL_DATA                                                  0x427b
+#define mmDCP5_DC_LUT_PWL_DATA                                                  0x447b
+#define mmDC_LUT_30_COLOR                                                       0x1a7c
+#define mmDCP0_DC_LUT_30_COLOR                                                  0x1a7c
+#define mmDCP1_DC_LUT_30_COLOR                                                  0x1c7c
+#define mmDCP2_DC_LUT_30_COLOR                                                  0x1e7c
+#define mmDCP3_DC_LUT_30_COLOR                                                  0x407c
+#define mmDCP4_DC_LUT_30_COLOR                                                  0x427c
+#define mmDCP5_DC_LUT_30_COLOR                                                  0x447c
+#define mmDC_LUT_VGA_ACCESS_ENABLE                                              0x1a7d
+#define mmDCP0_DC_LUT_VGA_ACCESS_ENABLE                                         0x1a7d
+#define mmDCP1_DC_LUT_VGA_ACCESS_ENABLE                                         0x1c7d
+#define mmDCP2_DC_LUT_VGA_ACCESS_ENABLE                                         0x1e7d
+#define mmDCP3_DC_LUT_VGA_ACCESS_ENABLE                                         0x407d
+#define mmDCP4_DC_LUT_VGA_ACCESS_ENABLE                                         0x427d
+#define mmDCP5_DC_LUT_VGA_ACCESS_ENABLE                                         0x447d
+#define mmDC_LUT_WRITE_EN_MASK                                                  0x1a7e
+#define mmDCP0_DC_LUT_WRITE_EN_MASK                                             0x1a7e
+#define mmDCP1_DC_LUT_WRITE_EN_MASK                                             0x1c7e
+#define mmDCP2_DC_LUT_WRITE_EN_MASK                                             0x1e7e
+#define mmDCP3_DC_LUT_WRITE_EN_MASK                                             0x407e
+#define mmDCP4_DC_LUT_WRITE_EN_MASK                                             0x427e
+#define mmDCP5_DC_LUT_WRITE_EN_MASK                                             0x447e
+#define mmDC_LUT_AUTOFILL                                                       0x1a7f
+#define mmDCP0_DC_LUT_AUTOFILL                                                  0x1a7f
+#define mmDCP1_DC_LUT_AUTOFILL                                                  0x1c7f
+#define mmDCP2_DC_LUT_AUTOFILL                                                  0x1e7f
+#define mmDCP3_DC_LUT_AUTOFILL                                                  0x407f
+#define mmDCP4_DC_LUT_AUTOFILL                                                  0x427f
+#define mmDCP5_DC_LUT_AUTOFILL                                                  0x447f
+#define mmDC_LUT_CONTROL                                                        0x1a80
+#define mmDCP0_DC_LUT_CONTROL                                                   0x1a80
+#define mmDCP1_DC_LUT_CONTROL                                                   0x1c80
+#define mmDCP2_DC_LUT_CONTROL                                                   0x1e80
+#define mmDCP3_DC_LUT_CONTROL                                                   0x4080
+#define mmDCP4_DC_LUT_CONTROL                                                   0x4280
+#define mmDCP5_DC_LUT_CONTROL                                                   0x4480
+#define mmDC_LUT_BLACK_OFFSET_BLUE                                              0x1a81
+#define mmDCP0_DC_LUT_BLACK_OFFSET_BLUE                                         0x1a81
+#define mmDCP1_DC_LUT_BLACK_OFFSET_BLUE                                         0x1c81
+#define mmDCP2_DC_LUT_BLACK_OFFSET_BLUE                                         0x1e81
+#define mmDCP3_DC_LUT_BLACK_OFFSET_BLUE                                         0x4081
+#define mmDCP4_DC_LUT_BLACK_OFFSET_BLUE                                         0x4281
+#define mmDCP5_DC_LUT_BLACK_OFFSET_BLUE                                         0x4481
+#define mmDC_LUT_BLACK_OFFSET_GREEN                                             0x1a82
+#define mmDCP0_DC_LUT_BLACK_OFFSET_GREEN                                        0x1a82
+#define mmDCP1_DC_LUT_BLACK_OFFSET_GREEN                                        0x1c82
+#define mmDCP2_DC_LUT_BLACK_OFFSET_GREEN                                        0x1e82
+#define mmDCP3_DC_LUT_BLACK_OFFSET_GREEN                                        0x4082
+#define mmDCP4_DC_LUT_BLACK_OFFSET_GREEN                                        0x4282
+#define mmDCP5_DC_LUT_BLACK_OFFSET_GREEN                                        0x4482
+#define mmDC_LUT_BLACK_OFFSET_RED                                               0x1a83
+#define mmDCP0_DC_LUT_BLACK_OFFSET_RED                                          0x1a83
+#define mmDCP1_DC_LUT_BLACK_OFFSET_RED                                          0x1c83
+#define mmDCP2_DC_LUT_BLACK_OFFSET_RED                                          0x1e83
+#define mmDCP3_DC_LUT_BLACK_OFFSET_RED                                          0x4083
+#define mmDCP4_DC_LUT_BLACK_OFFSET_RED                                          0x4283
+#define mmDCP5_DC_LUT_BLACK_OFFSET_RED                                          0x4483
+#define mmDC_LUT_WHITE_OFFSET_BLUE                                              0x1a84
+#define mmDCP0_DC_LUT_WHITE_OFFSET_BLUE                                         0x1a84
+#define mmDCP1_DC_LUT_WHITE_OFFSET_BLUE                                         0x1c84
+#define mmDCP2_DC_LUT_WHITE_OFFSET_BLUE                                         0x1e84
+#define mmDCP3_DC_LUT_WHITE_OFFSET_BLUE                                         0x4084
+#define mmDCP4_DC_LUT_WHITE_OFFSET_BLUE                                         0x4284
+#define mmDCP5_DC_LUT_WHITE_OFFSET_BLUE                                         0x4484
+#define mmDC_LUT_WHITE_OFFSET_GREEN                                             0x1a85
+#define mmDCP0_DC_LUT_WHITE_OFFSET_GREEN                                        0x1a85
+#define mmDCP1_DC_LUT_WHITE_OFFSET_GREEN                                        0x1c85
+#define mmDCP2_DC_LUT_WHITE_OFFSET_GREEN                                        0x1e85
+#define mmDCP3_DC_LUT_WHITE_OFFSET_GREEN                                        0x4085
+#define mmDCP4_DC_LUT_WHITE_OFFSET_GREEN                                        0x4285
+#define mmDCP5_DC_LUT_WHITE_OFFSET_GREEN                                        0x4485
+#define mmDC_LUT_WHITE_OFFSET_RED                                               0x1a86
+#define mmDCP0_DC_LUT_WHITE_OFFSET_RED                                          0x1a86
+#define mmDCP1_DC_LUT_WHITE_OFFSET_RED                                          0x1c86
+#define mmDCP2_DC_LUT_WHITE_OFFSET_RED                                          0x1e86
+#define mmDCP3_DC_LUT_WHITE_OFFSET_RED                                          0x4086
+#define mmDCP4_DC_LUT_WHITE_OFFSET_RED                                          0x4286
+#define mmDCP5_DC_LUT_WHITE_OFFSET_RED                                          0x4486
+#define mmDCP_CRC_CONTROL                                                       0x1a87
+#define mmDCP0_DCP_CRC_CONTROL                                                  0x1a87
+#define mmDCP1_DCP_CRC_CONTROL                                                  0x1c87
+#define mmDCP2_DCP_CRC_CONTROL                                                  0x1e87
+#define mmDCP3_DCP_CRC_CONTROL                                                  0x4087
+#define mmDCP4_DCP_CRC_CONTROL                                                  0x4287
+#define mmDCP5_DCP_CRC_CONTROL                                                  0x4487
+#define mmDCP_CRC_MASK                                                          0x1a88
+#define mmDCP0_DCP_CRC_MASK                                                     0x1a88
+#define mmDCP1_DCP_CRC_MASK                                                     0x1c88
+#define mmDCP2_DCP_CRC_MASK                                                     0x1e88
+#define mmDCP3_DCP_CRC_MASK                                                     0x4088
+#define mmDCP4_DCP_CRC_MASK                                                     0x4288
+#define mmDCP5_DCP_CRC_MASK                                                     0x4488
+#define mmDCP_CRC_CURRENT                                                       0x1a89
+#define mmDCP0_DCP_CRC_CURRENT                                                  0x1a89
+#define mmDCP1_DCP_CRC_CURRENT                                                  0x1c89
+#define mmDCP2_DCP_CRC_CURRENT                                                  0x1e89
+#define mmDCP3_DCP_CRC_CURRENT                                                  0x4089
+#define mmDCP4_DCP_CRC_CURRENT                                                  0x4289
+#define mmDCP5_DCP_CRC_CURRENT                                                  0x4489
+#define mmDVMM_PTE_CONTROL                                                      0x1a8a
+#define mmDCP0_DVMM_PTE_CONTROL                                                 0x1a8a
+#define mmDCP1_DVMM_PTE_CONTROL                                                 0x1c8a
+#define mmDCP2_DVMM_PTE_CONTROL                                                 0x1e8a
+#define mmDCP3_DVMM_PTE_CONTROL                                                 0x408a
+#define mmDCP4_DVMM_PTE_CONTROL                                                 0x428a
+#define mmDCP5_DVMM_PTE_CONTROL                                                 0x448a
+#define mmDCP_CRC_LAST                                                          0x1a8b
+#define mmDCP0_DCP_CRC_LAST                                                     0x1a8b
+#define mmDCP1_DCP_CRC_LAST                                                     0x1c8b
+#define mmDCP2_DCP_CRC_LAST                                                     0x1e8b
+#define mmDCP3_DCP_CRC_LAST                                                     0x408b
+#define mmDCP4_DCP_CRC_LAST                                                     0x428b
+#define mmDCP5_DCP_CRC_LAST                                                     0x448b
+#define mmDCP_DEBUG                                                             0x1a8d
+#define mmDCP0_DCP_DEBUG                                                        0x1a8d
+#define mmDCP1_DCP_DEBUG                                                        0x1c8d
+#define mmDCP2_DCP_DEBUG                                                        0x1e8d
+#define mmDCP3_DCP_DEBUG                                                        0x408d
+#define mmDCP4_DCP_DEBUG                                                        0x428d
+#define mmDCP5_DCP_DEBUG                                                        0x448d
+#define mmGRPH_FLIP_RATE_CNTL                                                   0x1a8e
+#define mmDCP0_GRPH_FLIP_RATE_CNTL                                              0x1a8e
+#define mmDCP1_GRPH_FLIP_RATE_CNTL                                              0x1c8e
+#define mmDCP2_GRPH_FLIP_RATE_CNTL                                              0x1e8e
+#define mmDCP3_GRPH_FLIP_RATE_CNTL                                              0x408e
+#define mmDCP4_GRPH_FLIP_RATE_CNTL                                              0x428e
+#define mmDCP5_GRPH_FLIP_RATE_CNTL                                              0x448e
+#define mmDCP_GSL_CONTROL                                                       0x1a90
+#define mmDCP0_DCP_GSL_CONTROL                                                  0x1a90
+#define mmDCP1_DCP_GSL_CONTROL                                                  0x1c90
+#define mmDCP2_DCP_GSL_CONTROL                                                  0x1e90
+#define mmDCP3_DCP_GSL_CONTROL                                                  0x4090
+#define mmDCP4_DCP_GSL_CONTROL                                                  0x4290
+#define mmDCP5_DCP_GSL_CONTROL                                                  0x4490
+#define mmDCP_LB_DATA_GAP_BETWEEN_CHUNK                                         0x1a91
+#define mmDCP0_DCP_LB_DATA_GAP_BETWEEN_CHUNK                                    0x1a91
+#define mmDCP1_DCP_LB_DATA_GAP_BETWEEN_CHUNK                                    0x1c91
+#define mmDCP2_DCP_LB_DATA_GAP_BETWEEN_CHUNK                                    0x1e91
+#define mmDCP3_DCP_LB_DATA_GAP_BETWEEN_CHUNK                                    0x4091
+#define mmDCP4_DCP_LB_DATA_GAP_BETWEEN_CHUNK                                    0x4291
+#define mmDCP5_DCP_LB_DATA_GAP_BETWEEN_CHUNK                                    0x4491
+#define mmDCP_DEBUG_SG                                                          0x1a92
+#define mmDCP0_DCP_DEBUG_SG                                                     0x1a92
+#define mmDCP1_DCP_DEBUG_SG                                                     0x1c92
+#define mmDCP2_DCP_DEBUG_SG                                                     0x1e92
+#define mmDCP3_DCP_DEBUG_SG                                                     0x4092
+#define mmDCP4_DCP_DEBUG_SG                                                     0x4292
+#define mmDCP5_DCP_DEBUG_SG                                                     0x4492
+#define mmDCP_DEBUG_SG2                                                         0x1a94
+#define mmDCP0_DCP_DEBUG_SG2                                                    0x1a94
+#define mmDCP1_DCP_DEBUG_SG2                                                    0x1c94
+#define mmDCP2_DCP_DEBUG_SG2                                                    0x1e94
+#define mmDCP3_DCP_DEBUG_SG2                                                    0x4094
+#define mmDCP4_DCP_DEBUG_SG2                                                    0x4294
+#define mmDCP5_DCP_DEBUG_SG2                                                    0x4494
+#define mmDCP_DVMM_DEBUG                                                        0x1a93
+#define mmDCP0_DCP_DVMM_DEBUG                                                   0x1a93
+#define mmDCP1_DCP_DVMM_DEBUG                                                   0x1c93
+#define mmDCP2_DCP_DVMM_DEBUG                                                   0x1e93
+#define mmDCP3_DCP_DVMM_DEBUG                                                   0x4093
+#define mmDCP4_DCP_DVMM_DEBUG                                                   0x4293
+#define mmDCP5_DCP_DVMM_DEBUG                                                   0x4493
+#define mmDCP_TEST_DEBUG_INDEX                                                  0x1a95
+#define mmDCP0_DCP_TEST_DEBUG_INDEX                                             0x1a95
+#define mmDCP1_DCP_TEST_DEBUG_INDEX                                             0x1c95
+#define mmDCP2_DCP_TEST_DEBUG_INDEX                                             0x1e95
+#define mmDCP3_DCP_TEST_DEBUG_INDEX                                             0x4095
+#define mmDCP4_DCP_TEST_DEBUG_INDEX                                             0x4295
+#define mmDCP5_DCP_TEST_DEBUG_INDEX                                             0x4495
+#define mmDCP_TEST_DEBUG_DATA                                                   0x1a96
+#define mmDCP0_DCP_TEST_DEBUG_DATA                                              0x1a96
+#define mmDCP1_DCP_TEST_DEBUG_DATA                                              0x1c96
+#define mmDCP2_DCP_TEST_DEBUG_DATA                                              0x1e96
+#define mmDCP3_DCP_TEST_DEBUG_DATA                                              0x4096
+#define mmDCP4_DCP_TEST_DEBUG_DATA                                              0x4296
+#define mmDCP5_DCP_TEST_DEBUG_DATA                                              0x4496
+#define mmGRPH_STEREOSYNC_FLIP                                                  0x1a97
+#define mmDCP0_GRPH_STEREOSYNC_FLIP                                             0x1a97
+#define mmDCP1_GRPH_STEREOSYNC_FLIP                                             0x1c97
+#define mmDCP2_GRPH_STEREOSYNC_FLIP                                             0x1e97
+#define mmDCP3_GRPH_STEREOSYNC_FLIP                                             0x4097
+#define mmDCP4_GRPH_STEREOSYNC_FLIP                                             0x4297
+#define mmDCP5_GRPH_STEREOSYNC_FLIP                                             0x4497
+#define mmDCP_DEBUG2                                                            0x1a98
+#define mmDCP0_DCP_DEBUG2                                                       0x1a98
+#define mmDCP1_DCP_DEBUG2                                                       0x1c98
+#define mmDCP2_DCP_DEBUG2                                                       0x1e98
+#define mmDCP3_DCP_DEBUG2                                                       0x4098
+#define mmDCP4_DCP_DEBUG2                                                       0x4298
+#define mmDCP5_DCP_DEBUG2                                                       0x4498
+#define mmHW_ROTATION                                                           0x1a9e
+#define mmDCP0_HW_ROTATION                                                      0x1a9e
+#define mmDCP1_HW_ROTATION                                                      0x1c9e
+#define mmDCP2_HW_ROTATION                                                      0x1e9e
+#define mmDCP3_HW_ROTATION                                                      0x409e
+#define mmDCP4_HW_ROTATION                                                      0x429e
+#define mmDCP5_HW_ROTATION                                                      0x449e
+#define mmGRPH_XDMA_CACHE_UNDERFLOW_DET_CNTL                                    0x1a9f
+#define mmDCP0_GRPH_XDMA_CACHE_UNDERFLOW_DET_CNTL                               0x1a9f
+#define mmDCP1_GRPH_XDMA_CACHE_UNDERFLOW_DET_CNTL                               0x1c9f
+#define mmDCP2_GRPH_XDMA_CACHE_UNDERFLOW_DET_CNTL                               0x1e9f
+#define mmDCP3_GRPH_XDMA_CACHE_UNDERFLOW_DET_CNTL                               0x409f
+#define mmDCP4_GRPH_XDMA_CACHE_UNDERFLOW_DET_CNTL                               0x429f
+#define mmDCP5_GRPH_XDMA_CACHE_UNDERFLOW_DET_CNTL                               0x449f
+#define mmREGAMMA_CONTROL                                                       0x1aa0
+#define mmDCP0_REGAMMA_CONTROL                                                  0x1aa0
+#define mmDCP1_REGAMMA_CONTROL                                                  0x1ca0
+#define mmDCP2_REGAMMA_CONTROL                                                  0x1ea0
+#define mmDCP3_REGAMMA_CONTROL                                                  0x40a0
+#define mmDCP4_REGAMMA_CONTROL                                                  0x42a0
+#define mmDCP5_REGAMMA_CONTROL                                                  0x44a0
+#define mmREGAMMA_LUT_INDEX                                                     0x1aa1
+#define mmDCP0_REGAMMA_LUT_INDEX                                                0x1aa1
+#define mmDCP1_REGAMMA_LUT_INDEX                                                0x1ca1
+#define mmDCP2_REGAMMA_LUT_INDEX                                                0x1ea1
+#define mmDCP3_REGAMMA_LUT_INDEX                                                0x40a1
+#define mmDCP4_REGAMMA_LUT_INDEX                                                0x42a1
+#define mmDCP5_REGAMMA_LUT_INDEX                                                0x44a1
+#define mmREGAMMA_LUT_DATA                                                      0x1aa2
+#define mmDCP0_REGAMMA_LUT_DATA                                                 0x1aa2
+#define mmDCP1_REGAMMA_LUT_DATA                                                 0x1ca2
+#define mmDCP2_REGAMMA_LUT_DATA                                                 0x1ea2
+#define mmDCP3_REGAMMA_LUT_DATA                                                 0x40a2
+#define mmDCP4_REGAMMA_LUT_DATA                                                 0x42a2
+#define mmDCP5_REGAMMA_LUT_DATA                                                 0x44a2
+#define mmREGAMMA_LUT_WRITE_EN_MASK                                             0x1aa3
+#define mmDCP0_REGAMMA_LUT_WRITE_EN_MASK                                        0x1aa3
+#define mmDCP1_REGAMMA_LUT_WRITE_EN_MASK                                        0x1ca3
+#define mmDCP2_REGAMMA_LUT_WRITE_EN_MASK                                        0x1ea3
+#define mmDCP3_REGAMMA_LUT_WRITE_EN_MASK                                        0x40a3
+#define mmDCP4_REGAMMA_LUT_WRITE_EN_MASK                                        0x42a3
+#define mmDCP5_REGAMMA_LUT_WRITE_EN_MASK                                        0x44a3
+#define mmREGAMMA_CNTLA_START_CNTL                                              0x1aa4
+#define mmDCP0_REGAMMA_CNTLA_START_CNTL                                         0x1aa4
+#define mmDCP1_REGAMMA_CNTLA_START_CNTL                                         0x1ca4
+#define mmDCP2_REGAMMA_CNTLA_START_CNTL                                         0x1ea4
+#define mmDCP3_REGAMMA_CNTLA_START_CNTL                                         0x40a4
+#define mmDCP4_REGAMMA_CNTLA_START_CNTL                                         0x42a4
+#define mmDCP5_REGAMMA_CNTLA_START_CNTL                                         0x44a4
+#define mmREGAMMA_CNTLA_SLOPE_CNTL                                              0x1aa5
+#define mmDCP0_REGAMMA_CNTLA_SLOPE_CNTL                                         0x1aa5
+#define mmDCP1_REGAMMA_CNTLA_SLOPE_CNTL                                         0x1ca5
+#define mmDCP2_REGAMMA_CNTLA_SLOPE_CNTL                                         0x1ea5
+#define mmDCP3_REGAMMA_CNTLA_SLOPE_CNTL                                         0x40a5
+#define mmDCP4_REGAMMA_CNTLA_SLOPE_CNTL                                         0x42a5
+#define mmDCP5_REGAMMA_CNTLA_SLOPE_CNTL                                         0x44a5
+#define mmREGAMMA_CNTLA_END_CNTL1                                               0x1aa6
+#define mmDCP0_REGAMMA_CNTLA_END_CNTL1                                          0x1aa6
+#define mmDCP1_REGAMMA_CNTLA_END_CNTL1                                          0x1ca6
+#define mmDCP2_REGAMMA_CNTLA_END_CNTL1                                          0x1ea6
+#define mmDCP3_REGAMMA_CNTLA_END_CNTL1                                          0x40a6
+#define mmDCP4_REGAMMA_CNTLA_END_CNTL1                                          0x42a6
+#define mmDCP5_REGAMMA_CNTLA_END_CNTL1                                          0x44a6
+#define mmREGAMMA_CNTLA_END_CNTL2                                               0x1aa7
+#define mmDCP0_REGAMMA_CNTLA_END_CNTL2                                          0x1aa7
+#define mmDCP1_REGAMMA_CNTLA_END_CNTL2                                          0x1ca7
+#define mmDCP2_REGAMMA_CNTLA_END_CNTL2                                          0x1ea7
+#define mmDCP3_REGAMMA_CNTLA_END_CNTL2                                          0x40a7
+#define mmDCP4_REGAMMA_CNTLA_END_CNTL2                                          0x42a7
+#define mmDCP5_REGAMMA_CNTLA_END_CNTL2                                          0x44a7
+#define mmREGAMMA_CNTLA_REGION_0_1                                              0x1aa8
+#define mmDCP0_REGAMMA_CNTLA_REGION_0_1                                         0x1aa8
+#define mmDCP1_REGAMMA_CNTLA_REGION_0_1                                         0x1ca8
+#define mmDCP2_REGAMMA_CNTLA_REGION_0_1                                         0x1ea8
+#define mmDCP3_REGAMMA_CNTLA_REGION_0_1                                         0x40a8
+#define mmDCP4_REGAMMA_CNTLA_REGION_0_1                                         0x42a8
+#define mmDCP5_REGAMMA_CNTLA_REGION_0_1                                         0x44a8
+#define mmREGAMMA_CNTLA_REGION_2_3                                              0x1aa9
+#define mmDCP0_REGAMMA_CNTLA_REGION_2_3                                         0x1aa9
+#define mmDCP1_REGAMMA_CNTLA_REGION_2_3                                         0x1ca9
+#define mmDCP2_REGAMMA_CNTLA_REGION_2_3                                         0x1ea9
+#define mmDCP3_REGAMMA_CNTLA_REGION_2_3                                         0x40a9
+#define mmDCP4_REGAMMA_CNTLA_REGION_2_3                                         0x42a9
+#define mmDCP5_REGAMMA_CNTLA_REGION_2_3                                         0x44a9
+#define mmREGAMMA_CNTLA_REGION_4_5                                              0x1aaa
+#define mmDCP0_REGAMMA_CNTLA_REGION_4_5                                         0x1aaa
+#define mmDCP1_REGAMMA_CNTLA_REGION_4_5                                         0x1caa
+#define mmDCP2_REGAMMA_CNTLA_REGION_4_5                                         0x1eaa
+#define mmDCP3_REGAMMA_CNTLA_REGION_4_5                                         0x40aa
+#define mmDCP4_REGAMMA_CNTLA_REGION_4_5                                         0x42aa
+#define mmDCP5_REGAMMA_CNTLA_REGION_4_5                                         0x44aa
+#define mmREGAMMA_CNTLA_REGION_6_7                                              0x1aab
+#define mmDCP0_REGAMMA_CNTLA_REGION_6_7                                         0x1aab
+#define mmDCP1_REGAMMA_CNTLA_REGION_6_7                                         0x1cab
+#define mmDCP2_REGAMMA_CNTLA_REGION_6_7                                         0x1eab
+#define mmDCP3_REGAMMA_CNTLA_REGION_6_7                                         0x40ab
+#define mmDCP4_REGAMMA_CNTLA_REGION_6_7                                         0x42ab
+#define mmDCP5_REGAMMA_CNTLA_REGION_6_7                                         0x44ab
+#define mmREGAMMA_CNTLA_REGION_8_9                                              0x1aac
+#define mmDCP0_REGAMMA_CNTLA_REGION_8_9                                         0x1aac
+#define mmDCP1_REGAMMA_CNTLA_REGION_8_9                                         0x1cac
+#define mmDCP2_REGAMMA_CNTLA_REGION_8_9                                         0x1eac
+#define mmDCP3_REGAMMA_CNTLA_REGION_8_9                                         0x40ac
+#define mmDCP4_REGAMMA_CNTLA_REGION_8_9                                         0x42ac
+#define mmDCP5_REGAMMA_CNTLA_REGION_8_9                                         0x44ac
+#define mmREGAMMA_CNTLA_REGION_10_11                                            0x1aad
+#define mmDCP0_REGAMMA_CNTLA_REGION_10_11                                       0x1aad
+#define mmDCP1_REGAMMA_CNTLA_REGION_10_11                                       0x1cad
+#define mmDCP2_REGAMMA_CNTLA_REGION_10_11                                       0x1ead
+#define mmDCP3_REGAMMA_CNTLA_REGION_10_11                                       0x40ad
+#define mmDCP4_REGAMMA_CNTLA_REGION_10_11                                       0x42ad
+#define mmDCP5_REGAMMA_CNTLA_REGION_10_11                                       0x44ad
+#define mmREGAMMA_CNTLA_REGION_12_13                                            0x1aae
+#define mmDCP0_REGAMMA_CNTLA_REGION_12_13                                       0x1aae
+#define mmDCP1_REGAMMA_CNTLA_REGION_12_13                                       0x1cae
+#define mmDCP2_REGAMMA_CNTLA_REGION_12_13                                       0x1eae
+#define mmDCP3_REGAMMA_CNTLA_REGION_12_13                                       0x40ae
+#define mmDCP4_REGAMMA_CNTLA_REGION_12_13                                       0x42ae
+#define mmDCP5_REGAMMA_CNTLA_REGION_12_13                                       0x44ae
+#define mmREGAMMA_CNTLA_REGION_14_15                                            0x1aaf
+#define mmDCP0_REGAMMA_CNTLA_REGION_14_15                                       0x1aaf
+#define mmDCP1_REGAMMA_CNTLA_REGION_14_15                                       0x1caf
+#define mmDCP2_REGAMMA_CNTLA_REGION_14_15                                       0x1eaf
+#define mmDCP3_REGAMMA_CNTLA_REGION_14_15                                       0x40af
+#define mmDCP4_REGAMMA_CNTLA_REGION_14_15                                       0x42af
+#define mmDCP5_REGAMMA_CNTLA_REGION_14_15                                       0x44af
+#define mmREGAMMA_CNTLB_START_CNTL                                              0x1ab0
+#define mmDCP0_REGAMMA_CNTLB_START_CNTL                                         0x1ab0
+#define mmDCP1_REGAMMA_CNTLB_START_CNTL                                         0x1cb0
+#define mmDCP2_REGAMMA_CNTLB_START_CNTL                                         0x1eb0
+#define mmDCP3_REGAMMA_CNTLB_START_CNTL                                         0x40b0
+#define mmDCP4_REGAMMA_CNTLB_START_CNTL                                         0x42b0
+#define mmDCP5_REGAMMA_CNTLB_START_CNTL                                         0x44b0
+#define mmREGAMMA_CNTLB_SLOPE_CNTL                                              0x1ab1
+#define mmDCP0_REGAMMA_CNTLB_SLOPE_CNTL                                         0x1ab1
+#define mmDCP1_REGAMMA_CNTLB_SLOPE_CNTL                                         0x1cb1
+#define mmDCP2_REGAMMA_CNTLB_SLOPE_CNTL                                         0x1eb1
+#define mmDCP3_REGAMMA_CNTLB_SLOPE_CNTL                                         0x40b1
+#define mmDCP4_REGAMMA_CNTLB_SLOPE_CNTL                                         0x42b1
+#define mmDCP5_REGAMMA_CNTLB_SLOPE_CNTL                                         0x44b1
+#define mmREGAMMA_CNTLB_END_CNTL1                                               0x1ab2
+#define mmDCP0_REGAMMA_CNTLB_END_CNTL1                                          0x1ab2
+#define mmDCP1_REGAMMA_CNTLB_END_CNTL1                                          0x1cb2
+#define mmDCP2_REGAMMA_CNTLB_END_CNTL1                                          0x1eb2
+#define mmDCP3_REGAMMA_CNTLB_END_CNTL1                                          0x40b2
+#define mmDCP4_REGAMMA_CNTLB_END_CNTL1                                          0x42b2
+#define mmDCP5_REGAMMA_CNTLB_END_CNTL1                                          0x44b2
+#define mmREGAMMA_CNTLB_END_CNTL2                                               0x1ab3
+#define mmDCP0_REGAMMA_CNTLB_END_CNTL2                                          0x1ab3
+#define mmDCP1_REGAMMA_CNTLB_END_CNTL2                                          0x1cb3
+#define mmDCP2_REGAMMA_CNTLB_END_CNTL2                                          0x1eb3
+#define mmDCP3_REGAMMA_CNTLB_END_CNTL2                                          0x40b3
+#define mmDCP4_REGAMMA_CNTLB_END_CNTL2                                          0x42b3
+#define mmDCP5_REGAMMA_CNTLB_END_CNTL2                                          0x44b3
+#define mmREGAMMA_CNTLB_REGION_0_1                                              0x1ab4
+#define mmDCP0_REGAMMA_CNTLB_REGION_0_1                                         0x1ab4
+#define mmDCP1_REGAMMA_CNTLB_REGION_0_1                                         0x1cb4
+#define mmDCP2_REGAMMA_CNTLB_REGION_0_1                                         0x1eb4
+#define mmDCP3_REGAMMA_CNTLB_REGION_0_1                                         0x40b4
+#define mmDCP4_REGAMMA_CNTLB_REGION_0_1                                         0x42b4
+#define mmDCP5_REGAMMA_CNTLB_REGION_0_1                                         0x44b4
+#define mmREGAMMA_CNTLB_REGION_2_3                                              0x1ab5
+#define mmDCP0_REGAMMA_CNTLB_REGION_2_3                                         0x1ab5
+#define mmDCP1_REGAMMA_CNTLB_REGION_2_3                                         0x1cb5
+#define mmDCP2_REGAMMA_CNTLB_REGION_2_3                                         0x1eb5
+#define mmDCP3_REGAMMA_CNTLB_REGION_2_3                                         0x40b5
+#define mmDCP4_REGAMMA_CNTLB_REGION_2_3                                         0x42b5
+#define mmDCP5_REGAMMA_CNTLB_REGION_2_3                                         0x44b5
+#define mmREGAMMA_CNTLB_REGION_4_5                                              0x1ab6
+#define mmDCP0_REGAMMA_CNTLB_REGION_4_5                                         0x1ab6
+#define mmDCP1_REGAMMA_CNTLB_REGION_4_5                                         0x1cb6
+#define mmDCP2_REGAMMA_CNTLB_REGION_4_5                                         0x1eb6
+#define mmDCP3_REGAMMA_CNTLB_REGION_4_5                                         0x40b6
+#define mmDCP4_REGAMMA_CNTLB_REGION_4_5                                         0x42b6
+#define mmDCP5_REGAMMA_CNTLB_REGION_4_5                                         0x44b6
+#define mmREGAMMA_CNTLB_REGION_6_7                                              0x1ab7
+#define mmDCP0_REGAMMA_CNTLB_REGION_6_7                                         0x1ab7
+#define mmDCP1_REGAMMA_CNTLB_REGION_6_7                                         0x1cb7
+#define mmDCP2_REGAMMA_CNTLB_REGION_6_7                                         0x1eb7
+#define mmDCP3_REGAMMA_CNTLB_REGION_6_7                                         0x40b7
+#define mmDCP4_REGAMMA_CNTLB_REGION_6_7                                         0x42b7
+#define mmDCP5_REGAMMA_CNTLB_REGION_6_7                                         0x44b7
+#define mmREGAMMA_CNTLB_REGION_8_9                                              0x1ab8
+#define mmDCP0_REGAMMA_CNTLB_REGION_8_9                                         0x1ab8
+#define mmDCP1_REGAMMA_CNTLB_REGION_8_9                                         0x1cb8
+#define mmDCP2_REGAMMA_CNTLB_REGION_8_9                                         0x1eb8
+#define mmDCP3_REGAMMA_CNTLB_REGION_8_9                                         0x40b8
+#define mmDCP4_REGAMMA_CNTLB_REGION_8_9                                         0x42b8
+#define mmDCP5_REGAMMA_CNTLB_REGION_8_9                                         0x44b8
+#define mmREGAMMA_CNTLB_REGION_10_11                                            0x1ab9
+#define mmDCP0_REGAMMA_CNTLB_REGION_10_11                                       0x1ab9
+#define mmDCP1_REGAMMA_CNTLB_REGION_10_11                                       0x1cb9
+#define mmDCP2_REGAMMA_CNTLB_REGION_10_11                                       0x1eb9
+#define mmDCP3_REGAMMA_CNTLB_REGION_10_11                                       0x40b9
+#define mmDCP4_REGAMMA_CNTLB_REGION_10_11                                       0x42b9
+#define mmDCP5_REGAMMA_CNTLB_REGION_10_11                                       0x44b9
+#define mmREGAMMA_CNTLB_REGION_12_13                                            0x1aba
+#define mmDCP0_REGAMMA_CNTLB_REGION_12_13                                       0x1aba
+#define mmDCP1_REGAMMA_CNTLB_REGION_12_13                                       0x1cba
+#define mmDCP2_REGAMMA_CNTLB_REGION_12_13                                       0x1eba
+#define mmDCP3_REGAMMA_CNTLB_REGION_12_13                                       0x40ba
+#define mmDCP4_REGAMMA_CNTLB_REGION_12_13                                       0x42ba
+#define mmDCP5_REGAMMA_CNTLB_REGION_12_13                                       0x44ba
+#define mmREGAMMA_CNTLB_REGION_14_15                                            0x1abb
+#define mmDCP0_REGAMMA_CNTLB_REGION_14_15                                       0x1abb
+#define mmDCP1_REGAMMA_CNTLB_REGION_14_15                                       0x1cbb
+#define mmDCP2_REGAMMA_CNTLB_REGION_14_15                                       0x1ebb
+#define mmDCP3_REGAMMA_CNTLB_REGION_14_15                                       0x40bb
+#define mmDCP4_REGAMMA_CNTLB_REGION_14_15                                       0x42bb
+#define mmDCP5_REGAMMA_CNTLB_REGION_14_15                                       0x44bb
+#define mmALPHA_CONTROL                                                         0x1abc
+#define mmDCP0_ALPHA_CONTROL                                                    0x1abc
+#define mmDCP1_ALPHA_CONTROL                                                    0x1cbc
+#define mmDCP2_ALPHA_CONTROL                                                    0x1ebc
+#define mmDCP3_ALPHA_CONTROL                                                    0x40bc
+#define mmDCP4_ALPHA_CONTROL                                                    0x42bc
+#define mmDCP5_ALPHA_CONTROL                                                    0x44bc
+#define mmGRPH_XDMA_RECOVERY_SURFACE_ADDRESS                                    0x1abd
+#define mmDCP0_GRPH_XDMA_RECOVERY_SURFACE_ADDRESS                               0x1abd
+#define mmDCP1_GRPH_XDMA_RECOVERY_SURFACE_ADDRESS                               0x1cbd
+#define mmDCP2_GRPH_XDMA_RECOVERY_SURFACE_ADDRESS                               0x1ebd
+#define mmDCP3_GRPH_XDMA_RECOVERY_SURFACE_ADDRESS                               0x40bd
+#define mmDCP4_GRPH_XDMA_RECOVERY_SURFACE_ADDRESS                               0x42bd
+#define mmDCP5_GRPH_XDMA_RECOVERY_SURFACE_ADDRESS                               0x44bd
+#define mmGRPH_XDMA_RECOVERY_SURFACE_ADDRESS_HIGH                               0x1abe
+#define mmDCP0_GRPH_XDMA_RECOVERY_SURFACE_ADDRESS_HIGH                          0x1abe
+#define mmDCP1_GRPH_XDMA_RECOVERY_SURFACE_ADDRESS_HIGH                          0x1cbe
+#define mmDCP2_GRPH_XDMA_RECOVERY_SURFACE_ADDRESS_HIGH                          0x1ebe
+#define mmDCP3_GRPH_XDMA_RECOVERY_SURFACE_ADDRESS_HIGH                          0x40be
+#define mmDCP4_GRPH_XDMA_RECOVERY_SURFACE_ADDRESS_HIGH                          0x42be
+#define mmDCP5_GRPH_XDMA_RECOVERY_SURFACE_ADDRESS_HIGH                          0x44be
+#define mmGRPH_XDMA_CACHE_UNDERFLOW_DET_STATUS                                  0x1abf
+#define mmDCP0_GRPH_XDMA_CACHE_UNDERFLOW_DET_STATUS                             0x1abf
+#define mmDCP1_GRPH_XDMA_CACHE_UNDERFLOW_DET_STATUS                             0x1cbf
+#define mmDCP2_GRPH_XDMA_CACHE_UNDERFLOW_DET_STATUS                             0x1ebf
+#define mmDCP3_GRPH_XDMA_CACHE_UNDERFLOW_DET_STATUS                             0x40bf
+#define mmDCP4_GRPH_XDMA_CACHE_UNDERFLOW_DET_STATUS                             0x42bf
+#define mmDCP5_GRPH_XDMA_CACHE_UNDERFLOW_DET_STATUS                             0x44bf
+#define mmGRPH_SURFACE_COUNTER_CONTROL                                          0x1a0f
+#define mmDCP0_GRPH_SURFACE_COUNTER_CONTROL                                     0x1a0f
+#define mmDCP1_GRPH_SURFACE_COUNTER_CONTROL                                     0x1c0f
+#define mmDCP2_GRPH_SURFACE_COUNTER_CONTROL                                     0x1e0f
+#define mmDCP3_GRPH_SURFACE_COUNTER_CONTROL                                     0x400f
+#define mmDCP4_GRPH_SURFACE_COUNTER_CONTROL                                     0x420f
+#define mmDCP5_GRPH_SURFACE_COUNTER_CONTROL                                     0x440f
+#define mmGRPH_SURFACE_COUNTER_OUTPUT                                           0x1a1d
+#define mmDCP0_GRPH_SURFACE_COUNTER_OUTPUT                                      0x1a1d
+#define mmDCP1_GRPH_SURFACE_COUNTER_OUTPUT                                      0x1c1d
+#define mmDCP2_GRPH_SURFACE_COUNTER_OUTPUT                                      0x1e1d
+#define mmDCP3_GRPH_SURFACE_COUNTER_OUTPUT                                      0x401d
+#define mmDCP4_GRPH_SURFACE_COUNTER_OUTPUT                                      0x421d
+#define mmDCP5_GRPH_SURFACE_COUNTER_OUTPUT                                      0x441d
+#define mmDIG_FE_CNTL                                                           0x4a00
+#define mmDIG0_DIG_FE_CNTL                                                      0x4a00
+#define mmDIG1_DIG_FE_CNTL                                                      0x4b00
+#define mmDIG2_DIG_FE_CNTL                                                      0x4c00
+#define mmDIG3_DIG_FE_CNTL                                                      0x4d00
+#define mmDIG4_DIG_FE_CNTL                                                      0x4e00
+#define mmDIG5_DIG_FE_CNTL                                                      0x4f00
+#define mmDIG6_DIG_FE_CNTL                                                      0x5400
+#define mmDIG7_DIG_FE_CNTL                                                      0x5600
+#define mmDIG8_DIG_FE_CNTL                                                      0x5700
+#define mmDIG_OUTPUT_CRC_CNTL                                                   0x4a01
+#define mmDIG0_DIG_OUTPUT_CRC_CNTL                                              0x4a01
+#define mmDIG1_DIG_OUTPUT_CRC_CNTL                                              0x4b01
+#define mmDIG2_DIG_OUTPUT_CRC_CNTL                                              0x4c01
+#define mmDIG3_DIG_OUTPUT_CRC_CNTL                                              0x4d01
+#define mmDIG4_DIG_OUTPUT_CRC_CNTL                                              0x4e01
+#define mmDIG5_DIG_OUTPUT_CRC_CNTL                                              0x4f01
+#define mmDIG6_DIG_OUTPUT_CRC_CNTL                                              0x5401
+#define mmDIG7_DIG_OUTPUT_CRC_CNTL                                              0x5601
+#define mmDIG8_DIG_OUTPUT_CRC_CNTL                                              0x5701
+#define mmDIG_OUTPUT_CRC_RESULT                                                 0x4a02
+#define mmDIG0_DIG_OUTPUT_CRC_RESULT                                            0x4a02
+#define mmDIG1_DIG_OUTPUT_CRC_RESULT                                            0x4b02
+#define mmDIG2_DIG_OUTPUT_CRC_RESULT                                            0x4c02
+#define mmDIG3_DIG_OUTPUT_CRC_RESULT                                            0x4d02
+#define mmDIG4_DIG_OUTPUT_CRC_RESULT                                            0x4e02
+#define mmDIG5_DIG_OUTPUT_CRC_RESULT                                            0x4f02
+#define mmDIG6_DIG_OUTPUT_CRC_RESULT                                            0x5402
+#define mmDIG7_DIG_OUTPUT_CRC_RESULT                                            0x5602
+#define mmDIG8_DIG_OUTPUT_CRC_RESULT                                            0x5702
+#define mmDIG_CLOCK_PATTERN                                                     0x4a03
+#define mmDIG0_DIG_CLOCK_PATTERN                                                0x4a03
+#define mmDIG1_DIG_CLOCK_PATTERN                                                0x4b03
+#define mmDIG2_DIG_CLOCK_PATTERN                                                0x4c03
+#define mmDIG3_DIG_CLOCK_PATTERN                                                0x4d03
+#define mmDIG4_DIG_CLOCK_PATTERN                                                0x4e03
+#define mmDIG5_DIG_CLOCK_PATTERN                                                0x4f03
+#define mmDIG6_DIG_CLOCK_PATTERN                                                0x5403
+#define mmDIG7_DIG_CLOCK_PATTERN                                                0x5603
+#define mmDIG8_DIG_CLOCK_PATTERN                                                0x5703
+#define mmDIG_TEST_PATTERN                                                      0x4a04
+#define mmDIG0_DIG_TEST_PATTERN                                                 0x4a04
+#define mmDIG1_DIG_TEST_PATTERN                                                 0x4b04
+#define mmDIG2_DIG_TEST_PATTERN                                                 0x4c04
+#define mmDIG3_DIG_TEST_PATTERN                                                 0x4d04
+#define mmDIG4_DIG_TEST_PATTERN                                                 0x4e04
+#define mmDIG5_DIG_TEST_PATTERN                                                 0x4f04
+#define mmDIG6_DIG_TEST_PATTERN                                                 0x5404
+#define mmDIG7_DIG_TEST_PATTERN                                                 0x5604
+#define mmDIG8_DIG_TEST_PATTERN                                                 0x5704
+#define mmDIG_RANDOM_PATTERN_SEED                                               0x4a05
+#define mmDIG0_DIG_RANDOM_PATTERN_SEED                                          0x4a05
+#define mmDIG1_DIG_RANDOM_PATTERN_SEED                                          0x4b05
+#define mmDIG2_DIG_RANDOM_PATTERN_SEED                                          0x4c05
+#define mmDIG3_DIG_RANDOM_PATTERN_SEED                                          0x4d05
+#define mmDIG4_DIG_RANDOM_PATTERN_SEED                                          0x4e05
+#define mmDIG5_DIG_RANDOM_PATTERN_SEED                                          0x4f05
+#define mmDIG6_DIG_RANDOM_PATTERN_SEED                                          0x5405
+#define mmDIG7_DIG_RANDOM_PATTERN_SEED                                          0x5605
+#define mmDIG8_DIG_RANDOM_PATTERN_SEED                                          0x5705
+#define mmDIG_FIFO_STATUS                                                       0x4a06
+#define mmDIG0_DIG_FIFO_STATUS                                                  0x4a06
+#define mmDIG1_DIG_FIFO_STATUS                                                  0x4b06
+#define mmDIG2_DIG_FIFO_STATUS                                                  0x4c06
+#define mmDIG3_DIG_FIFO_STATUS                                                  0x4d06
+#define mmDIG4_DIG_FIFO_STATUS                                                  0x4e06
+#define mmDIG5_DIG_FIFO_STATUS                                                  0x4f06
+#define mmDIG6_DIG_FIFO_STATUS                                                  0x5406
+#define mmDIG7_DIG_FIFO_STATUS                                                  0x5606
+#define mmDIG8_DIG_FIFO_STATUS                                                  0x5706
+#define mmDIG_DISPCLK_SWITCH_CNTL                                               0x4a07
+#define mmDIG0_DIG_DISPCLK_SWITCH_CNTL                                          0x4a07
+#define mmDIG1_DIG_DISPCLK_SWITCH_CNTL                                          0x4b07
+#define mmDIG2_DIG_DISPCLK_SWITCH_CNTL                                          0x4c07
+#define mmDIG3_DIG_DISPCLK_SWITCH_CNTL                                          0x4d07
+#define mmDIG4_DIG_DISPCLK_SWITCH_CNTL                                          0x4e07
+#define mmDIG5_DIG_DISPCLK_SWITCH_CNTL                                          0x4f07
+#define mmDIG6_DIG_DISPCLK_SWITCH_CNTL                                          0x5407
+#define mmDIG7_DIG_DISPCLK_SWITCH_CNTL                                          0x5607
+#define mmDIG8_DIG_DISPCLK_SWITCH_CNTL                                          0x5707
+#define mmDIG_DISPCLK_SWITCH_STATUS                                             0x4a08
+#define mmDIG0_DIG_DISPCLK_SWITCH_STATUS                                        0x4a08
+#define mmDIG1_DIG_DISPCLK_SWITCH_STATUS                                        0x4b08
+#define mmDIG2_DIG_DISPCLK_SWITCH_STATUS                                        0x4c08
+#define mmDIG3_DIG_DISPCLK_SWITCH_STATUS                                        0x4d08
+#define mmDIG4_DIG_DISPCLK_SWITCH_STATUS                                        0x4e08
+#define mmDIG5_DIG_DISPCLK_SWITCH_STATUS                                        0x4f08
+#define mmDIG6_DIG_DISPCLK_SWITCH_STATUS                                        0x5408
+#define mmDIG7_DIG_DISPCLK_SWITCH_STATUS                                        0x5608
+#define mmDIG8_DIG_DISPCLK_SWITCH_STATUS                                        0x5708
+#define mmHDMI_CONTROL                                                          0x4a09
+#define mmDIG0_HDMI_CONTROL                                                     0x4a09
+#define mmDIG1_HDMI_CONTROL                                                     0x4b09
+#define mmDIG2_HDMI_CONTROL                                                     0x4c09
+#define mmDIG3_HDMI_CONTROL                                                     0x4d09
+#define mmDIG4_HDMI_CONTROL                                                     0x4e09
+#define mmDIG5_HDMI_CONTROL                                                     0x4f09
+#define mmDIG6_HDMI_CONTROL                                                     0x5409
+#define mmDIG7_HDMI_CONTROL                                                     0x5609
+#define mmDIG8_HDMI_CONTROL                                                     0x5709
+#define mmHDMI_STATUS                                                           0x4a0a
+#define mmDIG0_HDMI_STATUS                                                      0x4a0a
+#define mmDIG1_HDMI_STATUS                                                      0x4b0a
+#define mmDIG2_HDMI_STATUS                                                      0x4c0a
+#define mmDIG3_HDMI_STATUS                                                      0x4d0a
+#define mmDIG4_HDMI_STATUS                                                      0x4e0a
+#define mmDIG5_HDMI_STATUS                                                      0x4f0a
+#define mmDIG6_HDMI_STATUS                                                      0x540a
+#define mmDIG7_HDMI_STATUS                                                      0x560a
+#define mmDIG8_HDMI_STATUS                                                      0x570a
+#define mmHDMI_AUDIO_PACKET_CONTROL                                             0x4a0b
+#define mmDIG0_HDMI_AUDIO_PACKET_CONTROL                                        0x4a0b
+#define mmDIG1_HDMI_AUDIO_PACKET_CONTROL                                        0x4b0b
+#define mmDIG2_HDMI_AUDIO_PACKET_CONTROL                                        0x4c0b
+#define mmDIG3_HDMI_AUDIO_PACKET_CONTROL                                        0x4d0b
+#define mmDIG4_HDMI_AUDIO_PACKET_CONTROL                                        0x4e0b
+#define mmDIG5_HDMI_AUDIO_PACKET_CONTROL                                        0x4f0b
+#define mmDIG6_HDMI_AUDIO_PACKET_CONTROL                                        0x540b
+#define mmDIG7_HDMI_AUDIO_PACKET_CONTROL                                        0x560b
+#define mmDIG8_HDMI_AUDIO_PACKET_CONTROL                                        0x570b
+#define mmHDMI_ACR_PACKET_CONTROL                                               0x4a0c
+#define mmDIG0_HDMI_ACR_PACKET_CONTROL                                          0x4a0c
+#define mmDIG1_HDMI_ACR_PACKET_CONTROL                                          0x4b0c
+#define mmDIG2_HDMI_ACR_PACKET_CONTROL                                          0x4c0c
+#define mmDIG3_HDMI_ACR_PACKET_CONTROL                                          0x4d0c
+#define mmDIG4_HDMI_ACR_PACKET_CONTROL                                          0x4e0c
+#define mmDIG5_HDMI_ACR_PACKET_CONTROL                                          0x4f0c
+#define mmDIG6_HDMI_ACR_PACKET_CONTROL                                          0x540c
+#define mmDIG7_HDMI_ACR_PACKET_CONTROL                                          0x560c
+#define mmDIG8_HDMI_ACR_PACKET_CONTROL                                          0x570c
+#define mmHDMI_VBI_PACKET_CONTROL                                               0x4a0d
+#define mmDIG0_HDMI_VBI_PACKET_CONTROL                                          0x4a0d
+#define mmDIG1_HDMI_VBI_PACKET_CONTROL                                          0x4b0d
+#define mmDIG2_HDMI_VBI_PACKET_CONTROL                                          0x4c0d
+#define mmDIG3_HDMI_VBI_PACKET_CONTROL                                          0x4d0d
+#define mmDIG4_HDMI_VBI_PACKET_CONTROL                                          0x4e0d
+#define mmDIG5_HDMI_VBI_PACKET_CONTROL                                          0x4f0d
+#define mmDIG6_HDMI_VBI_PACKET_CONTROL                                          0x540d
+#define mmDIG7_HDMI_VBI_PACKET_CONTROL                                          0x560d
+#define mmDIG8_HDMI_VBI_PACKET_CONTROL                                          0x570d
+#define mmHDMI_INFOFRAME_CONTROL0                                               0x4a0e
+#define mmDIG0_HDMI_INFOFRAME_CONTROL0                                          0x4a0e
+#define mmDIG1_HDMI_INFOFRAME_CONTROL0                                          0x4b0e
+#define mmDIG2_HDMI_INFOFRAME_CONTROL0                                          0x4c0e
+#define mmDIG3_HDMI_INFOFRAME_CONTROL0                                          0x4d0e
+#define mmDIG4_HDMI_INFOFRAME_CONTROL0                                          0x4e0e
+#define mmDIG5_HDMI_INFOFRAME_CONTROL0                                          0x4f0e
+#define mmDIG6_HDMI_INFOFRAME_CONTROL0                                          0x540e
+#define mmDIG7_HDMI_INFOFRAME_CONTROL0                                          0x560e
+#define mmDIG8_HDMI_INFOFRAME_CONTROL0                                          0x570e
+#define mmHDMI_INFOFRAME_CONTROL1                                               0x4a0f
+#define mmDIG0_HDMI_INFOFRAME_CONTROL1                                          0x4a0f
+#define mmDIG1_HDMI_INFOFRAME_CONTROL1                                          0x4b0f
+#define mmDIG2_HDMI_INFOFRAME_CONTROL1                                          0x4c0f
+#define mmDIG3_HDMI_INFOFRAME_CONTROL1                                          0x4d0f
+#define mmDIG4_HDMI_INFOFRAME_CONTROL1                                          0x4e0f
+#define mmDIG5_HDMI_INFOFRAME_CONTROL1                                          0x4f0f
+#define mmDIG6_HDMI_INFOFRAME_CONTROL1                                          0x540f
+#define mmDIG7_HDMI_INFOFRAME_CONTROL1                                          0x560f
+#define mmDIG8_HDMI_INFOFRAME_CONTROL1                                          0x570f
+#define mmHDMI_GENERIC_PACKET_CONTROL0                                          0x4a10
+#define mmDIG0_HDMI_GENERIC_PACKET_CONTROL0                                     0x4a10
+#define mmDIG1_HDMI_GENERIC_PACKET_CONTROL0                                     0x4b10
+#define mmDIG2_HDMI_GENERIC_PACKET_CONTROL0                                     0x4c10
+#define mmDIG3_HDMI_GENERIC_PACKET_CONTROL0                                     0x4d10
+#define mmDIG4_HDMI_GENERIC_PACKET_CONTROL0                                     0x4e10
+#define mmDIG5_HDMI_GENERIC_PACKET_CONTROL0                                     0x4f10
+#define mmDIG6_HDMI_GENERIC_PACKET_CONTROL0                                     0x5410
+#define mmDIG7_HDMI_GENERIC_PACKET_CONTROL0                                     0x5610
+#define mmDIG8_HDMI_GENERIC_PACKET_CONTROL0                                     0x5710
+#define mmAFMT_INTERRUPT_STATUS                                                 0x4a11
+#define mmDIG0_AFMT_INTERRUPT_STATUS                                            0x4a11
+#define mmDIG1_AFMT_INTERRUPT_STATUS                                            0x4b11
+#define mmDIG2_AFMT_INTERRUPT_STATUS                                            0x4c11
+#define mmDIG3_AFMT_INTERRUPT_STATUS                                            0x4d11
+#define mmDIG4_AFMT_INTERRUPT_STATUS                                            0x4e11
+#define mmDIG5_AFMT_INTERRUPT_STATUS                                            0x4f11
+#define mmDIG6_AFMT_INTERRUPT_STATUS                                            0x5411
+#define mmDIG7_AFMT_INTERRUPT_STATUS                                            0x5611
+#define mmDIG8_AFMT_INTERRUPT_STATUS                                            0x5711
+#define mmHDMI_GC                                                               0x4a13
+#define mmDIG0_HDMI_GC                                                          0x4a13
+#define mmDIG1_HDMI_GC                                                          0x4b13
+#define mmDIG2_HDMI_GC                                                          0x4c13
+#define mmDIG3_HDMI_GC                                                          0x4d13
+#define mmDIG4_HDMI_GC                                                          0x4e13
+#define mmDIG5_HDMI_GC                                                          0x4f13
+#define mmDIG6_HDMI_GC                                                          0x5413
+#define mmDIG7_HDMI_GC                                                          0x5613
+#define mmDIG8_HDMI_GC                                                          0x5713
+#define mmAFMT_AUDIO_PACKET_CONTROL2                                            0x4a14
+#define mmDIG0_AFMT_AUDIO_PACKET_CONTROL2                                       0x4a14
+#define mmDIG1_AFMT_AUDIO_PACKET_CONTROL2                                       0x4b14
+#define mmDIG2_AFMT_AUDIO_PACKET_CONTROL2                                       0x4c14
+#define mmDIG3_AFMT_AUDIO_PACKET_CONTROL2                                       0x4d14
+#define mmDIG4_AFMT_AUDIO_PACKET_CONTROL2                                       0x4e14
+#define mmDIG5_AFMT_AUDIO_PACKET_CONTROL2                                       0x4f14
+#define mmDIG6_AFMT_AUDIO_PACKET_CONTROL2                                       0x5414
+#define mmDIG7_AFMT_AUDIO_PACKET_CONTROL2                                       0x5614
+#define mmDIG8_AFMT_AUDIO_PACKET_CONTROL2                                       0x5714
+#define mmAFMT_ISRC1_0                                                          0x4a15
+#define mmDIG0_AFMT_ISRC1_0                                                     0x4a15
+#define mmDIG1_AFMT_ISRC1_0                                                     0x4b15
+#define mmDIG2_AFMT_ISRC1_0                                                     0x4c15
+#define mmDIG3_AFMT_ISRC1_0                                                     0x4d15
+#define mmDIG4_AFMT_ISRC1_0                                                     0x4e15
+#define mmDIG5_AFMT_ISRC1_0                                                     0x4f15
+#define mmDIG6_AFMT_ISRC1_0                                                     0x5415
+#define mmDIG7_AFMT_ISRC1_0                                                     0x5615
+#define mmDIG8_AFMT_ISRC1_0                                                     0x5715
+#define mmAFMT_ISRC1_1                                                          0x4a16
+#define mmDIG0_AFMT_ISRC1_1                                                     0x4a16
+#define mmDIG1_AFMT_ISRC1_1                                                     0x4b16
+#define mmDIG2_AFMT_ISRC1_1                                                     0x4c16
+#define mmDIG3_AFMT_ISRC1_1                                                     0x4d16
+#define mmDIG4_AFMT_ISRC1_1                                                     0x4e16
+#define mmDIG5_AFMT_ISRC1_1                                                     0x4f16
+#define mmDIG6_AFMT_ISRC1_1                                                     0x5416
+#define mmDIG7_AFMT_ISRC1_1                                                     0x5616
+#define mmDIG8_AFMT_ISRC1_1                                                     0x5716
+#define mmAFMT_ISRC1_2                                                          0x4a17
+#define mmDIG0_AFMT_ISRC1_2                                                     0x4a17
+#define mmDIG1_AFMT_ISRC1_2                                                     0x4b17
+#define mmDIG2_AFMT_ISRC1_2                                                     0x4c17
+#define mmDIG3_AFMT_ISRC1_2                                                     0x4d17
+#define mmDIG4_AFMT_ISRC1_2                                                     0x4e17
+#define mmDIG5_AFMT_ISRC1_2                                                     0x4f17
+#define mmDIG6_AFMT_ISRC1_2                                                     0x5417
+#define mmDIG7_AFMT_ISRC1_2                                                     0x5617
+#define mmDIG8_AFMT_ISRC1_2                                                     0x5717
+#define mmAFMT_ISRC1_3                                                          0x4a18
+#define mmDIG0_AFMT_ISRC1_3                                                     0x4a18
+#define mmDIG1_AFMT_ISRC1_3                                                     0x4b18
+#define mmDIG2_AFMT_ISRC1_3                                                     0x4c18
+#define mmDIG3_AFMT_ISRC1_3                                                     0x4d18
+#define mmDIG4_AFMT_ISRC1_3                                                     0x4e18
+#define mmDIG5_AFMT_ISRC1_3                                                     0x4f18
+#define mmDIG6_AFMT_ISRC1_3                                                     0x5418
+#define mmDIG7_AFMT_ISRC1_3                                                     0x5618
+#define mmDIG8_AFMT_ISRC1_3                                                     0x5718
+#define mmAFMT_ISRC1_4                                                          0x4a19
+#define mmDIG0_AFMT_ISRC1_4                                                     0x4a19
+#define mmDIG1_AFMT_ISRC1_4                                                     0x4b19
+#define mmDIG2_AFMT_ISRC1_4                                                     0x4c19
+#define mmDIG3_AFMT_ISRC1_4                                                     0x4d19
+#define mmDIG4_AFMT_ISRC1_4                                                     0x4e19
+#define mmDIG5_AFMT_ISRC1_4                                                     0x4f19
+#define mmDIG6_AFMT_ISRC1_4                                                     0x5419
+#define mmDIG7_AFMT_ISRC1_4                                                     0x5619
+#define mmDIG8_AFMT_ISRC1_4                                                     0x5719
+#define mmAFMT_ISRC2_0                                                          0x4a1a
+#define mmDIG0_AFMT_ISRC2_0                                                     0x4a1a
+#define mmDIG1_AFMT_ISRC2_0                                                     0x4b1a
+#define mmDIG2_AFMT_ISRC2_0                                                     0x4c1a
+#define mmDIG3_AFMT_ISRC2_0                                                     0x4d1a
+#define mmDIG4_AFMT_ISRC2_0                                                     0x4e1a
+#define mmDIG5_AFMT_ISRC2_0                                                     0x4f1a
+#define mmDIG6_AFMT_ISRC2_0                                                     0x541a
+#define mmDIG7_AFMT_ISRC2_0                                                     0x561a
+#define mmDIG8_AFMT_ISRC2_0                                                     0x571a
+#define mmAFMT_ISRC2_1                                                          0x4a1b
+#define mmDIG0_AFMT_ISRC2_1                                                     0x4a1b
+#define mmDIG1_AFMT_ISRC2_1                                                     0x4b1b
+#define mmDIG2_AFMT_ISRC2_1                                                     0x4c1b
+#define mmDIG3_AFMT_ISRC2_1                                                     0x4d1b
+#define mmDIG4_AFMT_ISRC2_1                                                     0x4e1b
+#define mmDIG5_AFMT_ISRC2_1                                                     0x4f1b
+#define mmDIG6_AFMT_ISRC2_1                                                     0x541b
+#define mmDIG7_AFMT_ISRC2_1                                                     0x561b
+#define mmDIG8_AFMT_ISRC2_1                                                     0x571b
+#define mmAFMT_ISRC2_2                                                          0x4a1c
+#define mmDIG0_AFMT_ISRC2_2                                                     0x4a1c
+#define mmDIG1_AFMT_ISRC2_2                                                     0x4b1c
+#define mmDIG2_AFMT_ISRC2_2                                                     0x4c1c
+#define mmDIG3_AFMT_ISRC2_2                                                     0x4d1c
+#define mmDIG4_AFMT_ISRC2_2                                                     0x4e1c
+#define mmDIG5_AFMT_ISRC2_2                                                     0x4f1c
+#define mmDIG6_AFMT_ISRC2_2                                                     0x541c
+#define mmDIG7_AFMT_ISRC2_2                                                     0x561c
+#define mmDIG8_AFMT_ISRC2_2                                                     0x571c
+#define mmAFMT_ISRC2_3                                                          0x4a1d
+#define mmDIG0_AFMT_ISRC2_3                                                     0x4a1d
+#define mmDIG1_AFMT_ISRC2_3                                                     0x4b1d
+#define mmDIG2_AFMT_ISRC2_3                                                     0x4c1d
+#define mmDIG3_AFMT_ISRC2_3                                                     0x4d1d
+#define mmDIG4_AFMT_ISRC2_3                                                     0x4e1d
+#define mmDIG5_AFMT_ISRC2_3                                                     0x4f1d
+#define mmDIG6_AFMT_ISRC2_3                                                     0x541d
+#define mmDIG7_AFMT_ISRC2_3                                                     0x561d
+#define mmDIG8_AFMT_ISRC2_3                                                     0x571d
+#define mmAFMT_AVI_INFO0                                                        0x4a1e
+#define mmDIG0_AFMT_AVI_INFO0                                                   0x4a1e
+#define mmDIG1_AFMT_AVI_INFO0                                                   0x4b1e
+#define mmDIG2_AFMT_AVI_INFO0                                                   0x4c1e
+#define mmDIG3_AFMT_AVI_INFO0                                                   0x4d1e
+#define mmDIG4_AFMT_AVI_INFO0                                                   0x4e1e
+#define mmDIG5_AFMT_AVI_INFO0                                                   0x4f1e
+#define mmDIG6_AFMT_AVI_INFO0                                                   0x541e
+#define mmDIG7_AFMT_AVI_INFO0                                                   0x561e
+#define mmDIG8_AFMT_AVI_INFO0                                                   0x571e
+#define mmAFMT_AVI_INFO1                                                        0x4a1f
+#define mmDIG0_AFMT_AVI_INFO1                                                   0x4a1f
+#define mmDIG1_AFMT_AVI_INFO1                                                   0x4b1f
+#define mmDIG2_AFMT_AVI_INFO1                                                   0x4c1f
+#define mmDIG3_AFMT_AVI_INFO1                                                   0x4d1f
+#define mmDIG4_AFMT_AVI_INFO1                                                   0x4e1f
+#define mmDIG5_AFMT_AVI_INFO1                                                   0x4f1f
+#define mmDIG6_AFMT_AVI_INFO1                                                   0x541f
+#define mmDIG7_AFMT_AVI_INFO1                                                   0x561f
+#define mmDIG8_AFMT_AVI_INFO1                                                   0x571f
+#define mmAFMT_AVI_INFO2                                                        0x4a20
+#define mmDIG0_AFMT_AVI_INFO2                                                   0x4a20
+#define mmDIG1_AFMT_AVI_INFO2                                                   0x4b20
+#define mmDIG2_AFMT_AVI_INFO2                                                   0x4c20
+#define mmDIG3_AFMT_AVI_INFO2                                                   0x4d20
+#define mmDIG4_AFMT_AVI_INFO2                                                   0x4e20
+#define mmDIG5_AFMT_AVI_INFO2                                                   0x4f20
+#define mmDIG6_AFMT_AVI_INFO2                                                   0x5420
+#define mmDIG7_AFMT_AVI_INFO2                                                   0x5620
+#define mmDIG8_AFMT_AVI_INFO2                                                   0x5720
+#define mmAFMT_AVI_INFO3                                                        0x4a21
+#define mmDIG0_AFMT_AVI_INFO3                                                   0x4a21
+#define mmDIG1_AFMT_AVI_INFO3                                                   0x4b21
+#define mmDIG2_AFMT_AVI_INFO3                                                   0x4c21
+#define mmDIG3_AFMT_AVI_INFO3                                                   0x4d21
+#define mmDIG4_AFMT_AVI_INFO3                                                   0x4e21
+#define mmDIG5_AFMT_AVI_INFO3                                                   0x4f21
+#define mmDIG6_AFMT_AVI_INFO3                                                   0x5421
+#define mmDIG7_AFMT_AVI_INFO3                                                   0x5621
+#define mmDIG8_AFMT_AVI_INFO3                                                   0x5721
+#define mmAFMT_MPEG_INFO0                                                       0x4a22
+#define mmDIG0_AFMT_MPEG_INFO0                                                  0x4a22
+#define mmDIG1_AFMT_MPEG_INFO0                                                  0x4b22
+#define mmDIG2_AFMT_MPEG_INFO0                                                  0x4c22
+#define mmDIG3_AFMT_MPEG_INFO0                                                  0x4d22
+#define mmDIG4_AFMT_MPEG_INFO0                                                  0x4e22
+#define mmDIG5_AFMT_MPEG_INFO0                                                  0x4f22
+#define mmDIG6_AFMT_MPEG_INFO0                                                  0x5422
+#define mmDIG7_AFMT_MPEG_INFO0                                                  0x5622
+#define mmDIG8_AFMT_MPEG_INFO0                                                  0x5722
+#define mmAFMT_MPEG_INFO1                                                       0x4a23
+#define mmDIG0_AFMT_MPEG_INFO1                                                  0x4a23
+#define mmDIG1_AFMT_MPEG_INFO1                                                  0x4b23
+#define mmDIG2_AFMT_MPEG_INFO1                                                  0x4c23
+#define mmDIG3_AFMT_MPEG_INFO1                                                  0x4d23
+#define mmDIG4_AFMT_MPEG_INFO1                                                  0x4e23
+#define mmDIG5_AFMT_MPEG_INFO1                                                  0x4f23
+#define mmDIG6_AFMT_MPEG_INFO1                                                  0x5423
+#define mmDIG7_AFMT_MPEG_INFO1                                                  0x5623
+#define mmDIG8_AFMT_MPEG_INFO1                                                  0x5723
+#define mmAFMT_GENERIC_HDR                                                      0x4a24
+#define mmDIG0_AFMT_GENERIC_HDR                                                 0x4a24
+#define mmDIG1_AFMT_GENERIC_HDR                                                 0x4b24
+#define mmDIG2_AFMT_GENERIC_HDR                                                 0x4c24
+#define mmDIG3_AFMT_GENERIC_HDR                                                 0x4d24
+#define mmDIG4_AFMT_GENERIC_HDR                                                 0x4e24
+#define mmDIG5_AFMT_GENERIC_HDR                                                 0x4f24
+#define mmDIG6_AFMT_GENERIC_HDR                                                 0x5424
+#define mmDIG7_AFMT_GENERIC_HDR                                                 0x5624
+#define mmDIG8_AFMT_GENERIC_HDR                                                 0x5724
+#define mmAFMT_GENERIC_0                                                        0x4a25
+#define mmDIG0_AFMT_GENERIC_0                                                   0x4a25
+#define mmDIG1_AFMT_GENERIC_0                                                   0x4b25
+#define mmDIG2_AFMT_GENERIC_0                                                   0x4c25
+#define mmDIG3_AFMT_GENERIC_0                                                   0x4d25
+#define mmDIG4_AFMT_GENERIC_0                                                   0x4e25
+#define mmDIG5_AFMT_GENERIC_0                                                   0x4f25
+#define mmDIG6_AFMT_GENERIC_0                                                   0x5425
+#define mmDIG7_AFMT_GENERIC_0                                                   0x5625
+#define mmDIG8_AFMT_GENERIC_0                                                   0x5725
+#define mmAFMT_GENERIC_1                                                        0x4a26
+#define mmDIG0_AFMT_GENERIC_1                                                   0x4a26
+#define mmDIG1_AFMT_GENERIC_1                                                   0x4b26
+#define mmDIG2_AFMT_GENERIC_1                                                   0x4c26
+#define mmDIG3_AFMT_GENERIC_1                                                   0x4d26
+#define mmDIG4_AFMT_GENERIC_1                                                   0x4e26
+#define mmDIG5_AFMT_GENERIC_1                                                   0x4f26
+#define mmDIG6_AFMT_GENERIC_1                                                   0x5426
+#define mmDIG7_AFMT_GENERIC_1                                                   0x5626
+#define mmDIG8_AFMT_GENERIC_1                                                   0x5726
+#define mmAFMT_GENERIC_2                                                        0x4a27
+#define mmDIG0_AFMT_GENERIC_2                                                   0x4a27
+#define mmDIG1_AFMT_GENERIC_2                                                   0x4b27
+#define mmDIG2_AFMT_GENERIC_2                                                   0x4c27
+#define mmDIG3_AFMT_GENERIC_2                                                   0x4d27
+#define mmDIG4_AFMT_GENERIC_2                                                   0x4e27
+#define mmDIG5_AFMT_GENERIC_2                                                   0x4f27
+#define mmDIG6_AFMT_GENERIC_2                                                   0x5427
+#define mmDIG7_AFMT_GENERIC_2                                                   0x5627
+#define mmDIG8_AFMT_GENERIC_2                                                   0x5727
+#define mmAFMT_GENERIC_3                                                        0x4a28
+#define mmDIG0_AFMT_GENERIC_3                                                   0x4a28
+#define mmDIG1_AFMT_GENERIC_3                                                   0x4b28
+#define mmDIG2_AFMT_GENERIC_3                                                   0x4c28
+#define mmDIG3_AFMT_GENERIC_3                                                   0x4d28
+#define mmDIG4_AFMT_GENERIC_3                                                   0x4e28
+#define mmDIG5_AFMT_GENERIC_3                                                   0x4f28
+#define mmDIG6_AFMT_GENERIC_3                                                   0x5428
+#define mmDIG7_AFMT_GENERIC_3                                                   0x5628
+#define mmDIG8_AFMT_GENERIC_3                                                   0x5728
+#define mmAFMT_GENERIC_4                                                        0x4a29
+#define mmDIG0_AFMT_GENERIC_4                                                   0x4a29
+#define mmDIG1_AFMT_GENERIC_4                                                   0x4b29
+#define mmDIG2_AFMT_GENERIC_4                                                   0x4c29
+#define mmDIG3_AFMT_GENERIC_4                                                   0x4d29
+#define mmDIG4_AFMT_GENERIC_4                                                   0x4e29
+#define mmDIG5_AFMT_GENERIC_4                                                   0x4f29
+#define mmDIG6_AFMT_GENERIC_4                                                   0x5429
+#define mmDIG7_AFMT_GENERIC_4                                                   0x5629
+#define mmDIG8_AFMT_GENERIC_4                                                   0x5729
+#define mmAFMT_GENERIC_5                                                        0x4a2a
+#define mmDIG0_AFMT_GENERIC_5                                                   0x4a2a
+#define mmDIG1_AFMT_GENERIC_5                                                   0x4b2a
+#define mmDIG2_AFMT_GENERIC_5                                                   0x4c2a
+#define mmDIG3_AFMT_GENERIC_5                                                   0x4d2a
+#define mmDIG4_AFMT_GENERIC_5                                                   0x4e2a
+#define mmDIG5_AFMT_GENERIC_5                                                   0x4f2a
+#define mmDIG6_AFMT_GENERIC_5                                                   0x542a
+#define mmDIG7_AFMT_GENERIC_5                                                   0x562a
+#define mmDIG8_AFMT_GENERIC_5                                                   0x572a
+#define mmAFMT_GENERIC_6                                                        0x4a2b
+#define mmDIG0_AFMT_GENERIC_6                                                   0x4a2b
+#define mmDIG1_AFMT_GENERIC_6                                                   0x4b2b
+#define mmDIG2_AFMT_GENERIC_6                                                   0x4c2b
+#define mmDIG3_AFMT_GENERIC_6                                                   0x4d2b
+#define mmDIG4_AFMT_GENERIC_6                                                   0x4e2b
+#define mmDIG5_AFMT_GENERIC_6                                                   0x4f2b
+#define mmDIG6_AFMT_GENERIC_6                                                   0x542b
+#define mmDIG7_AFMT_GENERIC_6                                                   0x562b
+#define mmDIG8_AFMT_GENERIC_6                                                   0x572b
+#define mmAFMT_GENERIC_7                                                        0x4a2c
+#define mmDIG0_AFMT_GENERIC_7                                                   0x4a2c
+#define mmDIG1_AFMT_GENERIC_7                                                   0x4b2c
+#define mmDIG2_AFMT_GENERIC_7                                                   0x4c2c
+#define mmDIG3_AFMT_GENERIC_7                                                   0x4d2c
+#define mmDIG4_AFMT_GENERIC_7                                                   0x4e2c
+#define mmDIG5_AFMT_GENERIC_7                                                   0x4f2c
+#define mmDIG6_AFMT_GENERIC_7                                                   0x542c
+#define mmDIG7_AFMT_GENERIC_7                                                   0x562c
+#define mmDIG8_AFMT_GENERIC_7                                                   0x572c
+#define mmHDMI_GENERIC_PACKET_CONTROL1                                          0x4a2d
+#define mmDIG0_HDMI_GENERIC_PACKET_CONTROL1                                     0x4a2d
+#define mmDIG1_HDMI_GENERIC_PACKET_CONTROL1                                     0x4b2d
+#define mmDIG2_HDMI_GENERIC_PACKET_CONTROL1                                     0x4c2d
+#define mmDIG3_HDMI_GENERIC_PACKET_CONTROL1                                     0x4d2d
+#define mmDIG4_HDMI_GENERIC_PACKET_CONTROL1                                     0x4e2d
+#define mmDIG5_HDMI_GENERIC_PACKET_CONTROL1                                     0x4f2d
+#define mmDIG6_HDMI_GENERIC_PACKET_CONTROL1                                     0x542d
+#define mmDIG7_HDMI_GENERIC_PACKET_CONTROL1                                     0x562d
+#define mmDIG8_HDMI_GENERIC_PACKET_CONTROL1                                     0x572d
+#define mmHDMI_ACR_32_0                                                         0x4a2e
+#define mmDIG0_HDMI_ACR_32_0                                                    0x4a2e
+#define mmDIG1_HDMI_ACR_32_0                                                    0x4b2e
+#define mmDIG2_HDMI_ACR_32_0                                                    0x4c2e
+#define mmDIG3_HDMI_ACR_32_0                                                    0x4d2e
+#define mmDIG4_HDMI_ACR_32_0                                                    0x4e2e
+#define mmDIG5_HDMI_ACR_32_0                                                    0x4f2e
+#define mmDIG6_HDMI_ACR_32_0                                                    0x542e
+#define mmDIG7_HDMI_ACR_32_0                                                    0x562e
+#define mmDIG8_HDMI_ACR_32_0                                                    0x572e
+#define mmHDMI_ACR_32_1                                                         0x4a2f
+#define mmDIG0_HDMI_ACR_32_1                                                    0x4a2f
+#define mmDIG1_HDMI_ACR_32_1                                                    0x4b2f
+#define mmDIG2_HDMI_ACR_32_1                                                    0x4c2f
+#define mmDIG3_HDMI_ACR_32_1                                                    0x4d2f
+#define mmDIG4_HDMI_ACR_32_1                                                    0x4e2f
+#define mmDIG5_HDMI_ACR_32_1                                                    0x4f2f
+#define mmDIG6_HDMI_ACR_32_1                                                    0x542f
+#define mmDIG7_HDMI_ACR_32_1                                                    0x562f
+#define mmDIG8_HDMI_ACR_32_1                                                    0x572f
+#define mmHDMI_ACR_44_0                                                         0x4a30
+#define mmDIG0_HDMI_ACR_44_0                                                    0x4a30
+#define mmDIG1_HDMI_ACR_44_0                                                    0x4b30
+#define mmDIG2_HDMI_ACR_44_0                                                    0x4c30
+#define mmDIG3_HDMI_ACR_44_0                                                    0x4d30
+#define mmDIG4_HDMI_ACR_44_0                                                    0x4e30
+#define mmDIG5_HDMI_ACR_44_0                                                    0x4f30
+#define mmDIG6_HDMI_ACR_44_0                                                    0x5430
+#define mmDIG7_HDMI_ACR_44_0                                                    0x5630
+#define mmDIG8_HDMI_ACR_44_0                                                    0x5730
+#define mmHDMI_ACR_44_1                                                         0x4a31
+#define mmDIG0_HDMI_ACR_44_1                                                    0x4a31
+#define mmDIG1_HDMI_ACR_44_1                                                    0x4b31
+#define mmDIG2_HDMI_ACR_44_1                                                    0x4c31
+#define mmDIG3_HDMI_ACR_44_1                                                    0x4d31
+#define mmDIG4_HDMI_ACR_44_1                                                    0x4e31
+#define mmDIG5_HDMI_ACR_44_1                                                    0x4f31
+#define mmDIG6_HDMI_ACR_44_1                                                    0x5431
+#define mmDIG7_HDMI_ACR_44_1                                                    0x5631
+#define mmDIG8_HDMI_ACR_44_1                                                    0x5731
+#define mmHDMI_ACR_48_0                                                         0x4a32
+#define mmDIG0_HDMI_ACR_48_0                                                    0x4a32
+#define mmDIG1_HDMI_ACR_48_0                                                    0x4b32
+#define mmDIG2_HDMI_ACR_48_0                                                    0x4c32
+#define mmDIG3_HDMI_ACR_48_0                                                    0x4d32
+#define mmDIG4_HDMI_ACR_48_0                                                    0x4e32
+#define mmDIG5_HDMI_ACR_48_0                                                    0x4f32
+#define mmDIG6_HDMI_ACR_48_0                                                    0x5432
+#define mmDIG7_HDMI_ACR_48_0                                                    0x5632
+#define mmDIG8_HDMI_ACR_48_0                                                    0x5732
+#define mmHDMI_ACR_48_1                                                         0x4a33
+#define mmDIG0_HDMI_ACR_48_1                                                    0x4a33
+#define mmDIG1_HDMI_ACR_48_1                                                    0x4b33
+#define mmDIG2_HDMI_ACR_48_1                                                    0x4c33
+#define mmDIG3_HDMI_ACR_48_1                                                    0x4d33
+#define mmDIG4_HDMI_ACR_48_1                                                    0x4e33
+#define mmDIG5_HDMI_ACR_48_1                                                    0x4f33
+#define mmDIG6_HDMI_ACR_48_1                                                    0x5433
+#define mmDIG7_HDMI_ACR_48_1                                                    0x5633
+#define mmDIG8_HDMI_ACR_48_1                                                    0x5733
+#define mmHDMI_ACR_STATUS_0                                                     0x4a34
+#define mmDIG0_HDMI_ACR_STATUS_0                                                0x4a34
+#define mmDIG1_HDMI_ACR_STATUS_0                                                0x4b34
+#define mmDIG2_HDMI_ACR_STATUS_0                                                0x4c34
+#define mmDIG3_HDMI_ACR_STATUS_0                                                0x4d34
+#define mmDIG4_HDMI_ACR_STATUS_0                                                0x4e34
+#define mmDIG5_HDMI_ACR_STATUS_0                                                0x4f34
+#define mmDIG6_HDMI_ACR_STATUS_0                                                0x5434
+#define mmDIG7_HDMI_ACR_STATUS_0                                                0x5634
+#define mmDIG8_HDMI_ACR_STATUS_0                                                0x5734
+#define mmHDMI_ACR_STATUS_1                                                     0x4a35
+#define mmDIG0_HDMI_ACR_STATUS_1                                                0x4a35
+#define mmDIG1_HDMI_ACR_STATUS_1                                                0x4b35
+#define mmDIG2_HDMI_ACR_STATUS_1                                                0x4c35
+#define mmDIG3_HDMI_ACR_STATUS_1                                                0x4d35
+#define mmDIG4_HDMI_ACR_STATUS_1                                                0x4e35
+#define mmDIG5_HDMI_ACR_STATUS_1                                                0x4f35
+#define mmDIG6_HDMI_ACR_STATUS_1                                                0x5435
+#define mmDIG7_HDMI_ACR_STATUS_1                                                0x5635
+#define mmDIG8_HDMI_ACR_STATUS_1                                                0x5735
+#define mmAFMT_AUDIO_INFO0                                                      0x4a36
+#define mmDIG0_AFMT_AUDIO_INFO0                                                 0x4a36
+#define mmDIG1_AFMT_AUDIO_INFO0                                                 0x4b36
+#define mmDIG2_AFMT_AUDIO_INFO0                                                 0x4c36
+#define mmDIG3_AFMT_AUDIO_INFO0                                                 0x4d36
+#define mmDIG4_AFMT_AUDIO_INFO0                                                 0x4e36
+#define mmDIG5_AFMT_AUDIO_INFO0                                                 0x4f36
+#define mmDIG6_AFMT_AUDIO_INFO0                                                 0x5436
+#define mmDIG7_AFMT_AUDIO_INFO0                                                 0x5636
+#define mmDIG8_AFMT_AUDIO_INFO0                                                 0x5736
+#define mmAFMT_AUDIO_INFO1                                                      0x4a37
+#define mmDIG0_AFMT_AUDIO_INFO1                                                 0x4a37
+#define mmDIG1_AFMT_AUDIO_INFO1                                                 0x4b37
+#define mmDIG2_AFMT_AUDIO_INFO1                                                 0x4c37
+#define mmDIG3_AFMT_AUDIO_INFO1                                                 0x4d37
+#define mmDIG4_AFMT_AUDIO_INFO1                                                 0x4e37
+#define mmDIG5_AFMT_AUDIO_INFO1                                                 0x4f37
+#define mmDIG6_AFMT_AUDIO_INFO1                                                 0x5437
+#define mmDIG7_AFMT_AUDIO_INFO1                                                 0x5637
+#define mmDIG8_AFMT_AUDIO_INFO1                                                 0x5737
+#define mmAFMT_60958_0                                                          0x4a38
+#define mmDIG0_AFMT_60958_0                                                     0x4a38
+#define mmDIG1_AFMT_60958_0                                                     0x4b38
+#define mmDIG2_AFMT_60958_0                                                     0x4c38
+#define mmDIG3_AFMT_60958_0                                                     0x4d38
+#define mmDIG4_AFMT_60958_0                                                     0x4e38
+#define mmDIG5_AFMT_60958_0                                                     0x4f38
+#define mmDIG6_AFMT_60958_0                                                     0x5438
+#define mmDIG7_AFMT_60958_0                                                     0x5638
+#define mmDIG8_AFMT_60958_0                                                     0x5738
+#define mmAFMT_60958_1                                                          0x4a39
+#define mmDIG0_AFMT_60958_1                                                     0x4a39
+#define mmDIG1_AFMT_60958_1                                                     0x4b39
+#define mmDIG2_AFMT_60958_1                                                     0x4c39
+#define mmDIG3_AFMT_60958_1                                                     0x4d39
+#define mmDIG4_AFMT_60958_1                                                     0x4e39
+#define mmDIG5_AFMT_60958_1                                                     0x4f39
+#define mmDIG6_AFMT_60958_1                                                     0x5439
+#define mmDIG7_AFMT_60958_1                                                     0x5639
+#define mmDIG8_AFMT_60958_1                                                     0x5739
+#define mmAFMT_AUDIO_CRC_CONTROL                                                0x4a3a
+#define mmDIG0_AFMT_AUDIO_CRC_CONTROL                                           0x4a3a
+#define mmDIG1_AFMT_AUDIO_CRC_CONTROL                                           0x4b3a
+#define mmDIG2_AFMT_AUDIO_CRC_CONTROL                                           0x4c3a
+#define mmDIG3_AFMT_AUDIO_CRC_CONTROL                                           0x4d3a
+#define mmDIG4_AFMT_AUDIO_CRC_CONTROL                                           0x4e3a
+#define mmDIG5_AFMT_AUDIO_CRC_CONTROL                                           0x4f3a
+#define mmDIG6_AFMT_AUDIO_CRC_CONTROL                                           0x543a
+#define mmDIG7_AFMT_AUDIO_CRC_CONTROL                                           0x563a
+#define mmDIG8_AFMT_AUDIO_CRC_CONTROL                                           0x573a
+#define mmAFMT_RAMP_CONTROL0                                                    0x4a3b
+#define mmDIG0_AFMT_RAMP_CONTROL0                                               0x4a3b
+#define mmDIG1_AFMT_RAMP_CONTROL0                                               0x4b3b
+#define mmDIG2_AFMT_RAMP_CONTROL0                                               0x4c3b
+#define mmDIG3_AFMT_RAMP_CONTROL0                                               0x4d3b
+#define mmDIG4_AFMT_RAMP_CONTROL0                                               0x4e3b
+#define mmDIG5_AFMT_RAMP_CONTROL0                                               0x4f3b
+#define mmDIG6_AFMT_RAMP_CONTROL0                                               0x543b
+#define mmDIG7_AFMT_RAMP_CONTROL0                                               0x563b
+#define mmDIG8_AFMT_RAMP_CONTROL0                                               0x573b
+#define mmAFMT_RAMP_CONTROL1                                                    0x4a3c
+#define mmDIG0_AFMT_RAMP_CONTROL1                                               0x4a3c
+#define mmDIG1_AFMT_RAMP_CONTROL1                                               0x4b3c
+#define mmDIG2_AFMT_RAMP_CONTROL1                                               0x4c3c
+#define mmDIG3_AFMT_RAMP_CONTROL1                                               0x4d3c
+#define mmDIG4_AFMT_RAMP_CONTROL1                                               0x4e3c
+#define mmDIG5_AFMT_RAMP_CONTROL1                                               0x4f3c
+#define mmDIG6_AFMT_RAMP_CONTROL1                                               0x543c
+#define mmDIG7_AFMT_RAMP_CONTROL1                                               0x563c
+#define mmDIG8_AFMT_RAMP_CONTROL1                                               0x573c
+#define mmAFMT_RAMP_CONTROL2                                                    0x4a3d
+#define mmDIG0_AFMT_RAMP_CONTROL2                                               0x4a3d
+#define mmDIG1_AFMT_RAMP_CONTROL2                                               0x4b3d
+#define mmDIG2_AFMT_RAMP_CONTROL2                                               0x4c3d
+#define mmDIG3_AFMT_RAMP_CONTROL2                                               0x4d3d
+#define mmDIG4_AFMT_RAMP_CONTROL2                                               0x4e3d
+#define mmDIG5_AFMT_RAMP_CONTROL2                                               0x4f3d
+#define mmDIG6_AFMT_RAMP_CONTROL2                                               0x543d
+#define mmDIG7_AFMT_RAMP_CONTROL2                                               0x563d
+#define mmDIG8_AFMT_RAMP_CONTROL2                                               0x573d
+#define mmAFMT_RAMP_CONTROL3                                                    0x4a3e
+#define mmDIG0_AFMT_RAMP_CONTROL3                                               0x4a3e
+#define mmDIG1_AFMT_RAMP_CONTROL3                                               0x4b3e
+#define mmDIG2_AFMT_RAMP_CONTROL3                                               0x4c3e
+#define mmDIG3_AFMT_RAMP_CONTROL3                                               0x4d3e
+#define mmDIG4_AFMT_RAMP_CONTROL3                                               0x4e3e
+#define mmDIG5_AFMT_RAMP_CONTROL3                                               0x4f3e
+#define mmDIG6_AFMT_RAMP_CONTROL3                                               0x543e
+#define mmDIG7_AFMT_RAMP_CONTROL3                                               0x563e
+#define mmDIG8_AFMT_RAMP_CONTROL3                                               0x573e
+#define mmAFMT_60958_2                                                          0x4a3f
+#define mmDIG0_AFMT_60958_2                                                     0x4a3f
+#define mmDIG1_AFMT_60958_2                                                     0x4b3f
+#define mmDIG2_AFMT_60958_2                                                     0x4c3f
+#define mmDIG3_AFMT_60958_2                                                     0x4d3f
+#define mmDIG4_AFMT_60958_2                                                     0x4e3f
+#define mmDIG5_AFMT_60958_2                                                     0x4f3f
+#define mmDIG6_AFMT_60958_2                                                     0x543f
+#define mmDIG7_AFMT_60958_2                                                     0x563f
+#define mmDIG8_AFMT_60958_2                                                     0x573f
+#define mmAFMT_AUDIO_CRC_RESULT                                                 0x4a40
+#define mmDIG0_AFMT_AUDIO_CRC_RESULT                                            0x4a40
+#define mmDIG1_AFMT_AUDIO_CRC_RESULT                                            0x4b40
+#define mmDIG2_AFMT_AUDIO_CRC_RESULT                                            0x4c40
+#define mmDIG3_AFMT_AUDIO_CRC_RESULT                                            0x4d40
+#define mmDIG4_AFMT_AUDIO_CRC_RESULT                                            0x4e40
+#define mmDIG5_AFMT_AUDIO_CRC_RESULT                                            0x4f40
+#define mmDIG6_AFMT_AUDIO_CRC_RESULT                                            0x5440
+#define mmDIG7_AFMT_AUDIO_CRC_RESULT                                            0x5640
+#define mmDIG8_AFMT_AUDIO_CRC_RESULT                                            0x5740
+#define mmAFMT_STATUS                                                           0x4a41
+#define mmDIG0_AFMT_STATUS                                                      0x4a41
+#define mmDIG1_AFMT_STATUS                                                      0x4b41
+#define mmDIG2_AFMT_STATUS                                                      0x4c41
+#define mmDIG3_AFMT_STATUS                                                      0x4d41
+#define mmDIG4_AFMT_STATUS                                                      0x4e41
+#define mmDIG5_AFMT_STATUS                                                      0x4f41
+#define mmDIG6_AFMT_STATUS                                                      0x5441
+#define mmDIG7_AFMT_STATUS                                                      0x5641
+#define mmDIG8_AFMT_STATUS                                                      0x5741
+#define mmAFMT_AUDIO_PACKET_CONTROL                                             0x4a42
+#define mmDIG0_AFMT_AUDIO_PACKET_CONTROL                                        0x4a42
+#define mmDIG1_AFMT_AUDIO_PACKET_CONTROL                                        0x4b42
+#define mmDIG2_AFMT_AUDIO_PACKET_CONTROL                                        0x4c42
+#define mmDIG3_AFMT_AUDIO_PACKET_CONTROL                                        0x4d42
+#define mmDIG4_AFMT_AUDIO_PACKET_CONTROL                                        0x4e42
+#define mmDIG5_AFMT_AUDIO_PACKET_CONTROL                                        0x4f42
+#define mmDIG6_AFMT_AUDIO_PACKET_CONTROL                                        0x5442
+#define mmDIG7_AFMT_AUDIO_PACKET_CONTROL                                        0x5642
+#define mmDIG8_AFMT_AUDIO_PACKET_CONTROL                                        0x5742
+#define mmAFMT_VBI_PACKET_CONTROL                                               0x4a43
+#define mmDIG0_AFMT_VBI_PACKET_CONTROL                                          0x4a43
+#define mmDIG1_AFMT_VBI_PACKET_CONTROL                                          0x4b43
+#define mmDIG2_AFMT_VBI_PACKET_CONTROL                                          0x4c43
+#define mmDIG3_AFMT_VBI_PACKET_CONTROL                                          0x4d43
+#define mmDIG4_AFMT_VBI_PACKET_CONTROL                                          0x4e43
+#define mmDIG5_AFMT_VBI_PACKET_CONTROL                                          0x4f43
+#define mmDIG6_AFMT_VBI_PACKET_CONTROL                                          0x5443
+#define mmDIG7_AFMT_VBI_PACKET_CONTROL                                          0x5643
+#define mmDIG8_AFMT_VBI_PACKET_CONTROL                                          0x5743
+#define mmAFMT_INFOFRAME_CONTROL0                                               0x4a44
+#define mmDIG0_AFMT_INFOFRAME_CONTROL0                                          0x4a44
+#define mmDIG1_AFMT_INFOFRAME_CONTROL0                                          0x4b44
+#define mmDIG2_AFMT_INFOFRAME_CONTROL0                                          0x4c44
+#define mmDIG3_AFMT_INFOFRAME_CONTROL0                                          0x4d44
+#define mmDIG4_AFMT_INFOFRAME_CONTROL0                                          0x4e44
+#define mmDIG5_AFMT_INFOFRAME_CONTROL0                                          0x4f44
+#define mmDIG6_AFMT_INFOFRAME_CONTROL0                                          0x5444
+#define mmDIG7_AFMT_INFOFRAME_CONTROL0                                          0x5644
+#define mmDIG8_AFMT_INFOFRAME_CONTROL0                                          0x5744
+#define mmAFMT_AUDIO_SRC_CONTROL                                                0x4a45
+#define mmDIG0_AFMT_AUDIO_SRC_CONTROL                                           0x4a45
+#define mmDIG1_AFMT_AUDIO_SRC_CONTROL                                           0x4b45
+#define mmDIG2_AFMT_AUDIO_SRC_CONTROL                                           0x4c45
+#define mmDIG3_AFMT_AUDIO_SRC_CONTROL                                           0x4d45
+#define mmDIG4_AFMT_AUDIO_SRC_CONTROL                                           0x4e45
+#define mmDIG5_AFMT_AUDIO_SRC_CONTROL                                           0x4f45
+#define mmDIG6_AFMT_AUDIO_SRC_CONTROL                                           0x5445
+#define mmDIG7_AFMT_AUDIO_SRC_CONTROL                                           0x5645
+#define mmDIG8_AFMT_AUDIO_SRC_CONTROL                                           0x5745
+#define mmAFMT_AUDIO_DBG_DTO_CNTL                                               0x4a46
+#define mmDIG0_AFMT_AUDIO_DBG_DTO_CNTL                                          0x4a46
+#define mmDIG1_AFMT_AUDIO_DBG_DTO_CNTL                                          0x4b46
+#define mmDIG2_AFMT_AUDIO_DBG_DTO_CNTL                                          0x4c46
+#define mmDIG3_AFMT_AUDIO_DBG_DTO_CNTL                                          0x4d46
+#define mmDIG4_AFMT_AUDIO_DBG_DTO_CNTL                                          0x4e46
+#define mmDIG5_AFMT_AUDIO_DBG_DTO_CNTL                                          0x4f46
+#define mmDIG6_AFMT_AUDIO_DBG_DTO_CNTL                                          0x5446
+#define mmDIG7_AFMT_AUDIO_DBG_DTO_CNTL                                          0x5646
+#define mmDIG8_AFMT_AUDIO_DBG_DTO_CNTL                                          0x5746
+#define mmAFMT_CNTL                                                             0x4a7e
+#define mmDIG0_AFMT_CNTL                                                        0x4a7e
+#define mmDIG1_AFMT_CNTL                                                        0x4b7e
+#define mmDIG2_AFMT_CNTL                                                        0x4c7e
+#define mmDIG3_AFMT_CNTL                                                        0x4d7e
+#define mmDIG4_AFMT_CNTL                                                        0x4e7e
+#define mmDIG5_AFMT_CNTL                                                        0x4f7e
+#define mmDIG6_AFMT_CNTL                                                        0x547e
+#define mmDIG7_AFMT_CNTL                                                        0x567e
+#define mmDIG8_AFMT_CNTL                                                        0x577e
+#define mmDIG_BE_CNTL                                                           0x4a47
+#define mmDIG0_DIG_BE_CNTL                                                      0x4a47
+#define mmDIG1_DIG_BE_CNTL                                                      0x4b47
+#define mmDIG2_DIG_BE_CNTL                                                      0x4c47
+#define mmDIG3_DIG_BE_CNTL                                                      0x4d47
+#define mmDIG4_DIG_BE_CNTL                                                      0x4e47
+#define mmDIG5_DIG_BE_CNTL                                                      0x4f47
+#define mmDIG6_DIG_BE_CNTL                                                      0x5447
+#define mmDIG7_DIG_BE_CNTL                                                      0x5647
+#define mmDIG8_DIG_BE_CNTL                                                      0x5747
+#define mmDIG_BE_EN_CNTL                                                        0x4a48
+#define mmDIG0_DIG_BE_EN_CNTL                                                   0x4a48
+#define mmDIG1_DIG_BE_EN_CNTL                                                   0x4b48
+#define mmDIG2_DIG_BE_EN_CNTL                                                   0x4c48
+#define mmDIG3_DIG_BE_EN_CNTL                                                   0x4d48
+#define mmDIG4_DIG_BE_EN_CNTL                                                   0x4e48
+#define mmDIG5_DIG_BE_EN_CNTL                                                   0x4f48
+#define mmDIG6_DIG_BE_EN_CNTL                                                   0x5448
+#define mmDIG7_DIG_BE_EN_CNTL                                                   0x5648
+#define mmDIG8_DIG_BE_EN_CNTL                                                   0x5748
+#define mmTMDS_CNTL                                                             0x4a6b
+#define mmDIG0_TMDS_CNTL                                                        0x4a6b
+#define mmDIG1_TMDS_CNTL                                                        0x4b6b
+#define mmDIG2_TMDS_CNTL                                                        0x4c6b
+#define mmDIG3_TMDS_CNTL                                                        0x4d6b
+#define mmDIG4_TMDS_CNTL                                                        0x4e6b
+#define mmDIG5_TMDS_CNTL                                                        0x4f6b
+#define mmDIG6_TMDS_CNTL                                                        0x546b
+#define mmDIG7_TMDS_CNTL                                                        0x566b
+#define mmDIG8_TMDS_CNTL                                                        0x576b
+#define mmTMDS_CONTROL_CHAR                                                     0x4a6c
+#define mmDIG0_TMDS_CONTROL_CHAR                                                0x4a6c
+#define mmDIG1_TMDS_CONTROL_CHAR                                                0x4b6c
+#define mmDIG2_TMDS_CONTROL_CHAR                                                0x4c6c
+#define mmDIG3_TMDS_CONTROL_CHAR                                                0x4d6c
+#define mmDIG4_TMDS_CONTROL_CHAR                                                0x4e6c
+#define mmDIG5_TMDS_CONTROL_CHAR                                                0x4f6c
+#define mmDIG6_TMDS_CONTROL_CHAR                                                0x546c
+#define mmDIG7_TMDS_CONTROL_CHAR                                                0x566c
+#define mmDIG8_TMDS_CONTROL_CHAR                                                0x576c
+#define mmTMDS_CONTROL0_FEEDBACK                                                0x4a6d
+#define mmDIG0_TMDS_CONTROL0_FEEDBACK                                           0x4a6d
+#define mmDIG1_TMDS_CONTROL0_FEEDBACK                                           0x4b6d
+#define mmDIG2_TMDS_CONTROL0_FEEDBACK                                           0x4c6d
+#define mmDIG3_TMDS_CONTROL0_FEEDBACK                                           0x4d6d
+#define mmDIG4_TMDS_CONTROL0_FEEDBACK                                           0x4e6d
+#define mmDIG5_TMDS_CONTROL0_FEEDBACK                                           0x4f6d
+#define mmDIG6_TMDS_CONTROL0_FEEDBACK                                           0x546d
+#define mmDIG7_TMDS_CONTROL0_FEEDBACK                                           0x566d
+#define mmDIG8_TMDS_CONTROL0_FEEDBACK                                           0x576d
+#define mmTMDS_STEREOSYNC_CTL_SEL                                               0x4a6e
+#define mmDIG0_TMDS_STEREOSYNC_CTL_SEL                                          0x4a6e
+#define mmDIG1_TMDS_STEREOSYNC_CTL_SEL                                          0x4b6e
+#define mmDIG2_TMDS_STEREOSYNC_CTL_SEL                                          0x4c6e
+#define mmDIG3_TMDS_STEREOSYNC_CTL_SEL                                          0x4d6e
+#define mmDIG4_TMDS_STEREOSYNC_CTL_SEL                                          0x4e6e
+#define mmDIG5_TMDS_STEREOSYNC_CTL_SEL                                          0x4f6e
+#define mmDIG6_TMDS_STEREOSYNC_CTL_SEL                                          0x546e
+#define mmDIG7_TMDS_STEREOSYNC_CTL_SEL                                          0x566e
+#define mmDIG8_TMDS_STEREOSYNC_CTL_SEL                                          0x576e
+#define mmTMDS_SYNC_CHAR_PATTERN_0_1                                            0x4a6f
+#define mmDIG0_TMDS_SYNC_CHAR_PATTERN_0_1                                       0x4a6f
+#define mmDIG1_TMDS_SYNC_CHAR_PATTERN_0_1                                       0x4b6f
+#define mmDIG2_TMDS_SYNC_CHAR_PATTERN_0_1                                       0x4c6f
+#define mmDIG3_TMDS_SYNC_CHAR_PATTERN_0_1                                       0x4d6f
+#define mmDIG4_TMDS_SYNC_CHAR_PATTERN_0_1                                       0x4e6f
+#define mmDIG5_TMDS_SYNC_CHAR_PATTERN_0_1                                       0x4f6f
+#define mmDIG6_TMDS_SYNC_CHAR_PATTERN_0_1                                       0x546f
+#define mmDIG7_TMDS_SYNC_CHAR_PATTERN_0_1                                       0x566f
+#define mmDIG8_TMDS_SYNC_CHAR_PATTERN_0_1                                       0x576f
+#define mmTMDS_SYNC_CHAR_PATTERN_2_3                                            0x4a70
+#define mmDIG0_TMDS_SYNC_CHAR_PATTERN_2_3                                       0x4a70
+#define mmDIG1_TMDS_SYNC_CHAR_PATTERN_2_3                                       0x4b70
+#define mmDIG2_TMDS_SYNC_CHAR_PATTERN_2_3                                       0x4c70
+#define mmDIG3_TMDS_SYNC_CHAR_PATTERN_2_3                                       0x4d70
+#define mmDIG4_TMDS_SYNC_CHAR_PATTERN_2_3                                       0x4e70
+#define mmDIG5_TMDS_SYNC_CHAR_PATTERN_2_3                                       0x4f70
+#define mmDIG6_TMDS_SYNC_CHAR_PATTERN_2_3                                       0x5470
+#define mmDIG7_TMDS_SYNC_CHAR_PATTERN_2_3                                       0x5670
+#define mmDIG8_TMDS_SYNC_CHAR_PATTERN_2_3                                       0x5770
+#define mmTMDS_DEBUG                                                            0x4a71
+#define mmDIG0_TMDS_DEBUG                                                       0x4a71
+#define mmDIG1_TMDS_DEBUG                                                       0x4b71
+#define mmDIG2_TMDS_DEBUG                                                       0x4c71
+#define mmDIG3_TMDS_DEBUG                                                       0x4d71
+#define mmDIG4_TMDS_DEBUG                                                       0x4e71
+#define mmDIG5_TMDS_DEBUG                                                       0x4f71
+#define mmDIG6_TMDS_DEBUG                                                       0x5471
+#define mmDIG7_TMDS_DEBUG                                                       0x5671
+#define mmDIG8_TMDS_DEBUG                                                       0x5771
+#define mmTMDS_CTL_BITS                                                         0x4a72
+#define mmDIG0_TMDS_CTL_BITS                                                    0x4a72
+#define mmDIG1_TMDS_CTL_BITS                                                    0x4b72
+#define mmDIG2_TMDS_CTL_BITS                                                    0x4c72
+#define mmDIG3_TMDS_CTL_BITS                                                    0x4d72
+#define mmDIG4_TMDS_CTL_BITS                                                    0x4e72
+#define mmDIG5_TMDS_CTL_BITS                                                    0x4f72
+#define mmDIG6_TMDS_CTL_BITS                                                    0x5472
+#define mmDIG7_TMDS_CTL_BITS                                                    0x5672
+#define mmDIG8_TMDS_CTL_BITS                                                    0x5772
+#define mmTMDS_DCBALANCER_CONTROL                                               0x4a73
+#define mmDIG0_TMDS_DCBALANCER_CONTROL                                          0x4a73
+#define mmDIG1_TMDS_DCBALANCER_CONTROL                                          0x4b73
+#define mmDIG2_TMDS_DCBALANCER_CONTROL                                          0x4c73
+#define mmDIG3_TMDS_DCBALANCER_CONTROL                                          0x4d73
+#define mmDIG4_TMDS_DCBALANCER_CONTROL                                          0x4e73
+#define mmDIG5_TMDS_DCBALANCER_CONTROL                                          0x4f73
+#define mmDIG6_TMDS_DCBALANCER_CONTROL                                          0x5473
+#define mmDIG7_TMDS_DCBALANCER_CONTROL                                          0x5673
+#define mmDIG8_TMDS_DCBALANCER_CONTROL                                          0x5773
+#define mmTMDS_CTL0_1_GEN_CNTL                                                  0x4a75
+#define mmDIG0_TMDS_CTL0_1_GEN_CNTL                                             0x4a75
+#define mmDIG1_TMDS_CTL0_1_GEN_CNTL                                             0x4b75
+#define mmDIG2_TMDS_CTL0_1_GEN_CNTL                                             0x4c75
+#define mmDIG3_TMDS_CTL0_1_GEN_CNTL                                             0x4d75
+#define mmDIG4_TMDS_CTL0_1_GEN_CNTL                                             0x4e75
+#define mmDIG5_TMDS_CTL0_1_GEN_CNTL                                             0x4f75
+#define mmDIG6_TMDS_CTL0_1_GEN_CNTL                                             0x5475
+#define mmDIG7_TMDS_CTL0_1_GEN_CNTL                                             0x5675
+#define mmDIG8_TMDS_CTL0_1_GEN_CNTL                                             0x5775
+#define mmTMDS_CTL2_3_GEN_CNTL                                                  0x4a76
+#define mmDIG0_TMDS_CTL2_3_GEN_CNTL                                             0x4a76
+#define mmDIG1_TMDS_CTL2_3_GEN_CNTL                                             0x4b76
+#define mmDIG2_TMDS_CTL2_3_GEN_CNTL                                             0x4c76
+#define mmDIG3_TMDS_CTL2_3_GEN_CNTL                                             0x4d76
+#define mmDIG4_TMDS_CTL2_3_GEN_CNTL                                             0x4e76
+#define mmDIG5_TMDS_CTL2_3_GEN_CNTL                                             0x4f76
+#define mmDIG6_TMDS_CTL2_3_GEN_CNTL                                             0x5476
+#define mmDIG7_TMDS_CTL2_3_GEN_CNTL                                             0x5676
+#define mmDIG8_TMDS_CTL2_3_GEN_CNTL                                             0x5776
+#define mmDIG_VERSION                                                           0x4a78
+#define mmDIG0_DIG_VERSION                                                      0x4a78
+#define mmDIG1_DIG_VERSION                                                      0x4b78
+#define mmDIG2_DIG_VERSION                                                      0x4c78
+#define mmDIG3_DIG_VERSION                                                      0x4d78
+#define mmDIG4_DIG_VERSION                                                      0x4e78
+#define mmDIG5_DIG_VERSION                                                      0x4f78
+#define mmDIG6_DIG_VERSION                                                      0x5478
+#define mmDIG7_DIG_VERSION                                                      0x5678
+#define mmDIG8_DIG_VERSION                                                      0x5778
+#define mmDIG_LANE_ENABLE                                                       0x4a79
+#define mmDIG0_DIG_LANE_ENABLE                                                  0x4a79
+#define mmDIG1_DIG_LANE_ENABLE                                                  0x4b79
+#define mmDIG2_DIG_LANE_ENABLE                                                  0x4c79
+#define mmDIG3_DIG_LANE_ENABLE                                                  0x4d79
+#define mmDIG4_DIG_LANE_ENABLE                                                  0x4e79
+#define mmDIG5_DIG_LANE_ENABLE                                                  0x4f79
+#define mmDIG6_DIG_LANE_ENABLE                                                  0x5479
+#define mmDIG7_DIG_LANE_ENABLE                                                  0x5679
+#define mmDIG8_DIG_LANE_ENABLE                                                  0x5779
+#define mmDIG_TEST_DEBUG_INDEX                                                  0x4a7a
+#define mmDIG0_DIG_TEST_DEBUG_INDEX                                             0x4a7a
+#define mmDIG1_DIG_TEST_DEBUG_INDEX                                             0x4b7a
+#define mmDIG2_DIG_TEST_DEBUG_INDEX                                             0x4c7a
+#define mmDIG3_DIG_TEST_DEBUG_INDEX                                             0x4d7a
+#define mmDIG4_DIG_TEST_DEBUG_INDEX                                             0x4e7a
+#define mmDIG5_DIG_TEST_DEBUG_INDEX                                             0x4f7a
+#define mmDIG6_DIG_TEST_DEBUG_INDEX                                             0x547a
+#define mmDIG7_DIG_TEST_DEBUG_INDEX                                             0x567a
+#define mmDIG8_DIG_TEST_DEBUG_INDEX                                             0x577a
+#define mmDIG_TEST_DEBUG_DATA                                                   0x4a7b
+#define mmDIG0_DIG_TEST_DEBUG_DATA                                              0x4a7b
+#define mmDIG1_DIG_TEST_DEBUG_DATA                                              0x4b7b
+#define mmDIG2_DIG_TEST_DEBUG_DATA                                              0x4c7b
+#define mmDIG3_DIG_TEST_DEBUG_DATA                                              0x4d7b
+#define mmDIG4_DIG_TEST_DEBUG_DATA                                              0x4e7b
+#define mmDIG5_DIG_TEST_DEBUG_DATA                                              0x4f7b
+#define mmDIG6_DIG_TEST_DEBUG_DATA                                              0x547b
+#define mmDIG7_DIG_TEST_DEBUG_DATA                                              0x567b
+#define mmDIG8_DIG_TEST_DEBUG_DATA                                              0x577b
+#define mmDIG_FE_TEST_DEBUG_INDEX                                               0x4a7c
+#define mmDIG0_DIG_FE_TEST_DEBUG_INDEX                                          0x4a7c
+#define mmDIG1_DIG_FE_TEST_DEBUG_INDEX                                          0x4b7c
+#define mmDIG2_DIG_FE_TEST_DEBUG_INDEX                                          0x4c7c
+#define mmDIG3_DIG_FE_TEST_DEBUG_INDEX                                          0x4d7c
+#define mmDIG4_DIG_FE_TEST_DEBUG_INDEX                                          0x4e7c
+#define mmDIG5_DIG_FE_TEST_DEBUG_INDEX                                          0x4f7c
+#define mmDIG6_DIG_FE_TEST_DEBUG_INDEX                                          0x547c
+#define mmDIG7_DIG_FE_TEST_DEBUG_INDEX                                          0x567c
+#define mmDIG8_DIG_FE_TEST_DEBUG_INDEX                                          0x577c
+#define mmDIG_FE_TEST_DEBUG_DATA                                                0x4a7d
+#define mmDIG0_DIG_FE_TEST_DEBUG_DATA                                           0x4a7d
+#define mmDIG1_DIG_FE_TEST_DEBUG_DATA                                           0x4b7d
+#define mmDIG2_DIG_FE_TEST_DEBUG_DATA                                           0x4c7d
+#define mmDIG3_DIG_FE_TEST_DEBUG_DATA                                           0x4d7d
+#define mmDIG4_DIG_FE_TEST_DEBUG_DATA                                           0x4e7d
+#define mmDIG5_DIG_FE_TEST_DEBUG_DATA                                           0x4f7d
+#define mmDIG6_DIG_FE_TEST_DEBUG_DATA                                           0x547d
+#define mmDIG7_DIG_FE_TEST_DEBUG_DATA                                           0x567d
+#define mmDIG8_DIG_FE_TEST_DEBUG_DATA                                           0x577d
+#define mmDMCU_CTRL                                                             0x1600
+#define mmDMCU_STATUS                                                           0x1601
+#define mmDMCU_PC_START_ADDR                                                    0x1602
+#define mmDMCU_FW_START_ADDR                                                    0x1603
+#define mmDMCU_FW_END_ADDR                                                      0x1604
+#define mmDMCU_FW_ISR_START_ADDR                                                0x1605
+#define mmDMCU_FW_CS_HI                                                         0x1606
+#define mmDMCU_FW_CS_LO                                                         0x1607
+#define mmDMCU_RAM_ACCESS_CTRL                                                  0x1608
+#define mmDMCU_ERAM_WR_CTRL                                                     0x1609
+#define mmDMCU_ERAM_WR_DATA                                                     0x160a
+#define mmDMCU_ERAM_RD_CTRL                                                     0x160b
+#define mmDMCU_ERAM_RD_DATA                                                     0x160c
+#define mmDMCU_IRAM_WR_CTRL                                                     0x160d
+#define mmDMCU_IRAM_WR_DATA                                                     0x160e
+#define mmDMCU_IRAM_RD_CTRL                                                     0x160f
+#define mmDMCU_IRAM_RD_DATA                                                     0x1610
+#define mmDMCU_EVENT_TRIGGER                                                    0x1611
+#define mmDMCU_UC_INTERNAL_INT_STATUS                                           0x1612
+#define mmDMCU_SS_INTERRUPT_CNTL_STATUS                                         0x1613
+#define mmDMCU_INTERRUPT_STATUS                                                 0x1614
+#define mmDMCU_INTERRUPT_STATUS_1                                               0x1633
+#define mmDMCU_INTERRUPT_TO_HOST_EN_MASK                                        0x1615
+#define mmDMCU_INTERRUPT_TO_UC_EN_MASK                                          0x1616
+#define mmDMCU_INTERRUPT_TO_UC_EN_MASK_1                                        0x1631
+#define mmDMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL                                     0x1617
+#define mmDMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL_1                                   0x1632
+#define mmDC_DMCU_SCRATCH                                                       0x1618
+#define mmDMCU_INT_CNT                                                          0x1619
+#define mmDMCU_FW_CHECKSUM_SMPL_BYTE_POS                                        0x161a
+#define mmDMCU_UC_CLK_GATING_CNTL                                               0x161b
+#define mmMASTER_COMM_DATA_REG1                                                 0x161c
+#define mmMASTER_COMM_DATA_REG2                                                 0x161d
+#define mmMASTER_COMM_DATA_REG3                                                 0x161e
+#define mmMASTER_COMM_CMD_REG                                                   0x161f
+#define mmMASTER_COMM_CNTL_REG                                                  0x1620
+#define mmSLAVE_COMM_DATA_REG1                                                  0x1621
+#define mmSLAVE_COMM_DATA_REG2                                                  0x1622
+#define mmSLAVE_COMM_DATA_REG3                                                  0x1623
+#define mmSLAVE_COMM_CMD_REG                                                    0x1624
+#define mmSLAVE_COMM_CNTL_REG                                                   0x1625
+#define mmDMCU_TEST_DEBUG_INDEX                                                 0x1626
+#define mmDMCU_TEST_DEBUG_DATA                                                  0x1627
+#define mmDMCU_PERFMON_INTERRUPT_STATUS1                                        0x1644
+#define mmDMCU_PERFMON_INTERRUPT_STATUS2                                        0x1645
+#define mmDMCU_PERFMON_INTERRUPT_STATUS3                                        0x1646
+#define mmDMCU_PERFMON_INTERRUPT_STATUS4                                        0x1647
+#define mmDMCU_PERFMON_INTERRUPT_STATUS5                                        0x1642
+#define mmDMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1                                 0x1674
+#define mmDMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2                                 0x1675
+#define mmDMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3                                 0x1676
+#define mmDMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4                                 0x1677
+#define mmDMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK5                                 0x1643
+#define mmDMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1                            0x1678
+#define mmDMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2                            0x1679
+#define mmDMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3                            0x167a
+#define mmDMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4                            0x167b
+#define mmDMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL5                            0x1673
+#define mmDMCU_DPRX_INTERRUPT_STATUS1                                           0x1634
+#define mmDMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1                                    0x1635
+#define mmDMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1                               0x1636
+#define mmDP_LINK_CNTL                                                          0x4aa0
+#define mmDP0_DP_LINK_CNTL                                                      0x4aa0
+#define mmDP1_DP_LINK_CNTL                                                      0x4ba0
+#define mmDP2_DP_LINK_CNTL                                                      0x4ca0
+#define mmDP3_DP_LINK_CNTL                                                      0x4da0
+#define mmDP4_DP_LINK_CNTL                                                      0x4ea0
+#define mmDP5_DP_LINK_CNTL                                                      0x4fa0
+#define mmDP6_DP_LINK_CNTL                                                      0x54a0
+#define mmDP7_DP_LINK_CNTL                                                      0x56a0
+#define mmDP8_DP_LINK_CNTL                                                      0x57a0
+#define mmDP_PIXEL_FORMAT                                                       0x4aa1
+#define mmDP0_DP_PIXEL_FORMAT                                                   0x4aa1
+#define mmDP1_DP_PIXEL_FORMAT                                                   0x4ba1
+#define mmDP2_DP_PIXEL_FORMAT                                                   0x4ca1
+#define mmDP3_DP_PIXEL_FORMAT                                                   0x4da1
+#define mmDP4_DP_PIXEL_FORMAT                                                   0x4ea1
+#define mmDP5_DP_PIXEL_FORMAT                                                   0x4fa1
+#define mmDP6_DP_PIXEL_FORMAT                                                   0x54a1
+#define mmDP7_DP_PIXEL_FORMAT                                                   0x56a1
+#define mmDP8_DP_PIXEL_FORMAT                                                   0x57a1
+#define mmDP_MSA_COLORIMETRY                                                    0x4aa2
+#define mmDP0_DP_MSA_COLORIMETRY                                                0x4aa2
+#define mmDP1_DP_MSA_COLORIMETRY                                                0x4ba2
+#define mmDP2_DP_MSA_COLORIMETRY                                                0x4ca2
+#define mmDP3_DP_MSA_COLORIMETRY                                                0x4da2
+#define mmDP4_DP_MSA_COLORIMETRY                                                0x4ea2
+#define mmDP5_DP_MSA_COLORIMETRY                                                0x4fa2
+#define mmDP6_DP_MSA_COLORIMETRY                                                0x54a2
+#define mmDP7_DP_MSA_COLORIMETRY                                                0x56a2
+#define mmDP8_DP_MSA_COLORIMETRY                                                0x57a2
+#define mmDP_CONFIG                                                             0x4aa3
+#define mmDP0_DP_CONFIG                                                         0x4aa3
+#define mmDP1_DP_CONFIG                                                         0x4ba3
+#define mmDP2_DP_CONFIG                                                         0x4ca3
+#define mmDP3_DP_CONFIG                                                         0x4da3
+#define mmDP4_DP_CONFIG                                                         0x4ea3
+#define mmDP5_DP_CONFIG                                                         0x4fa3
+#define mmDP6_DP_CONFIG                                                         0x54a3
+#define mmDP7_DP_CONFIG                                                         0x56a3
+#define mmDP8_DP_CONFIG                                                         0x57a3
+#define mmDP_VID_STREAM_CNTL                                                    0x4aa4
+#define mmDP0_DP_VID_STREAM_CNTL                                                0x4aa4
+#define mmDP1_DP_VID_STREAM_CNTL                                                0x4ba4
+#define mmDP2_DP_VID_STREAM_CNTL                                                0x4ca4
+#define mmDP3_DP_VID_STREAM_CNTL                                                0x4da4
+#define mmDP4_DP_VID_STREAM_CNTL                                                0x4ea4
+#define mmDP5_DP_VID_STREAM_CNTL                                                0x4fa4
+#define mmDP6_DP_VID_STREAM_CNTL                                                0x54a4
+#define mmDP7_DP_VID_STREAM_CNTL                                                0x56a4
+#define mmDP8_DP_VID_STREAM_CNTL                                                0x57a4
+#define mmDP_STEER_FIFO                                                         0x4aa5
+#define mmDP0_DP_STEER_FIFO                                                     0x4aa5
+#define mmDP1_DP_STEER_FIFO                                                     0x4ba5
+#define mmDP2_DP_STEER_FIFO                                                     0x4ca5
+#define mmDP3_DP_STEER_FIFO                                                     0x4da5
+#define mmDP4_DP_STEER_FIFO                                                     0x4ea5
+#define mmDP5_DP_STEER_FIFO                                                     0x4fa5
+#define mmDP6_DP_STEER_FIFO                                                     0x54a5
+#define mmDP7_DP_STEER_FIFO                                                     0x56a5
+#define mmDP8_DP_STEER_FIFO                                                     0x57a5
+#define mmDP_MSA_MISC                                                           0x4aa6
+#define mmDP0_DP_MSA_MISC                                                       0x4aa6
+#define mmDP1_DP_MSA_MISC                                                       0x4ba6
+#define mmDP2_DP_MSA_MISC                                                       0x4ca6
+#define mmDP3_DP_MSA_MISC                                                       0x4da6
+#define mmDP4_DP_MSA_MISC                                                       0x4ea6
+#define mmDP5_DP_MSA_MISC                                                       0x4fa6
+#define mmDP6_DP_MSA_MISC                                                       0x54a6
+#define mmDP7_DP_MSA_MISC                                                       0x56a6
+#define mmDP8_DP_MSA_MISC                                                       0x57a6
+#define mmDP_VID_TIMING                                                         0x4aa8
+#define mmDP0_DP_VID_TIMING                                                     0x4aa8
+#define mmDP1_DP_VID_TIMING                                                     0x4ba8
+#define mmDP2_DP_VID_TIMING                                                     0x4ca8
+#define mmDP3_DP_VID_TIMING                                                     0x4da8
+#define mmDP4_DP_VID_TIMING                                                     0x4ea8
+#define mmDP5_DP_VID_TIMING                                                     0x4fa8
+#define mmDP6_DP_VID_TIMING                                                     0x54a8
+#define mmDP7_DP_VID_TIMING                                                     0x56a8
+#define mmDP8_DP_VID_TIMING                                                     0x57a8
+#define mmDP_VID_N                                                              0x4aa9
+#define mmDP0_DP_VID_N                                                          0x4aa9
+#define mmDP1_DP_VID_N                                                          0x4ba9
+#define mmDP2_DP_VID_N                                                          0x4ca9
+#define mmDP3_DP_VID_N                                                          0x4da9
+#define mmDP4_DP_VID_N                                                          0x4ea9
+#define mmDP5_DP_VID_N                                                          0x4fa9
+#define mmDP6_DP_VID_N                                                          0x54a9
+#define mmDP7_DP_VID_N                                                          0x56a9
+#define mmDP8_DP_VID_N                                                          0x57a9
+#define mmDP_VID_M                                                              0x4aaa
+#define mmDP0_DP_VID_M                                                          0x4aaa
+#define mmDP1_DP_VID_M                                                          0x4baa
+#define mmDP2_DP_VID_M                                                          0x4caa
+#define mmDP3_DP_VID_M                                                          0x4daa
+#define mmDP4_DP_VID_M                                                          0x4eaa
+#define mmDP5_DP_VID_M                                                          0x4faa
+#define mmDP6_DP_VID_M                                                          0x54aa
+#define mmDP7_DP_VID_M                                                          0x56aa
+#define mmDP8_DP_VID_M                                                          0x57aa
+#define mmDP_LINK_FRAMING_CNTL                                                  0x4aab
+#define mmDP0_DP_LINK_FRAMING_CNTL                                              0x4aab
+#define mmDP1_DP_LINK_FRAMING_CNTL                                              0x4bab
+#define mmDP2_DP_LINK_FRAMING_CNTL                                              0x4cab
+#define mmDP3_DP_LINK_FRAMING_CNTL                                              0x4dab
+#define mmDP4_DP_LINK_FRAMING_CNTL                                              0x4eab
+#define mmDP5_DP_LINK_FRAMING_CNTL                                              0x4fab
+#define mmDP6_DP_LINK_FRAMING_CNTL                                              0x54ab
+#define mmDP7_DP_LINK_FRAMING_CNTL                                              0x56ab
+#define mmDP8_DP_LINK_FRAMING_CNTL                                              0x57ab
+#define mmDP_HBR2_EYE_PATTERN                                                   0x4aac
+#define mmDP0_DP_HBR2_EYE_PATTERN                                               0x4aac
+#define mmDP1_DP_HBR2_EYE_PATTERN                                               0x4bac
+#define mmDP2_DP_HBR2_EYE_PATTERN                                               0x4cac
+#define mmDP3_DP_HBR2_EYE_PATTERN                                               0x4dac
+#define mmDP4_DP_HBR2_EYE_PATTERN                                               0x4eac
+#define mmDP5_DP_HBR2_EYE_PATTERN                                               0x4fac
+#define mmDP6_DP_HBR2_EYE_PATTERN                                               0x54ac
+#define mmDP7_DP_HBR2_EYE_PATTERN                                               0x56ac
+#define mmDP8_DP_HBR2_EYE_PATTERN                                               0x57ac
+#define mmDP_VID_MSA_VBID                                                       0x4aad
+#define mmDP0_DP_VID_MSA_VBID                                                   0x4aad
+#define mmDP1_DP_VID_MSA_VBID                                                   0x4bad
+#define mmDP2_DP_VID_MSA_VBID                                                   0x4cad
+#define mmDP3_DP_VID_MSA_VBID                                                   0x4dad
+#define mmDP4_DP_VID_MSA_VBID                                                   0x4ead
+#define mmDP5_DP_VID_MSA_VBID                                                   0x4fad
+#define mmDP6_DP_VID_MSA_VBID                                                   0x54ad
+#define mmDP7_DP_VID_MSA_VBID                                                   0x56ad
+#define mmDP8_DP_VID_MSA_VBID                                                   0x57ad
+#define mmDP_VID_INTERRUPT_CNTL                                                 0x4aae
+#define mmDP0_DP_VID_INTERRUPT_CNTL                                             0x4aae
+#define mmDP1_DP_VID_INTERRUPT_CNTL                                             0x4bae
+#define mmDP2_DP_VID_INTERRUPT_CNTL                                             0x4cae
+#define mmDP3_DP_VID_INTERRUPT_CNTL                                             0x4dae
+#define mmDP4_DP_VID_INTERRUPT_CNTL                                             0x4eae
+#define mmDP5_DP_VID_INTERRUPT_CNTL                                             0x4fae
+#define mmDP6_DP_VID_INTERRUPT_CNTL                                             0x54ae
+#define mmDP7_DP_VID_INTERRUPT_CNTL                                             0x56ae
+#define mmDP8_DP_VID_INTERRUPT_CNTL                                             0x57ae
+#define mmDP_DPHY_CNTL                                                          0x4aaf
+#define mmDP0_DP_DPHY_CNTL                                                      0x4aaf
+#define mmDP1_DP_DPHY_CNTL                                                      0x4baf
+#define mmDP2_DP_DPHY_CNTL                                                      0x4caf
+#define mmDP3_DP_DPHY_CNTL                                                      0x4daf
+#define mmDP4_DP_DPHY_CNTL                                                      0x4eaf
+#define mmDP5_DP_DPHY_CNTL                                                      0x4faf
+#define mmDP6_DP_DPHY_CNTL                                                      0x54af
+#define mmDP7_DP_DPHY_CNTL                                                      0x56af
+#define mmDP8_DP_DPHY_CNTL                                                      0x57af
+#define mmDP_DPHY_TRAINING_PATTERN_SEL                                          0x4ab0
+#define mmDP0_DP_DPHY_TRAINING_PATTERN_SEL                                      0x4ab0
+#define mmDP1_DP_DPHY_TRAINING_PATTERN_SEL                                      0x4bb0
+#define mmDP2_DP_DPHY_TRAINING_PATTERN_SEL                                      0x4cb0
+#define mmDP3_DP_DPHY_TRAINING_PATTERN_SEL                                      0x4db0
+#define mmDP4_DP_DPHY_TRAINING_PATTERN_SEL                                      0x4eb0
+#define mmDP5_DP_DPHY_TRAINING_PATTERN_SEL                                      0x4fb0
+#define mmDP6_DP_DPHY_TRAINING_PATTERN_SEL                                      0x54b0
+#define mmDP7_DP_DPHY_TRAINING_PATTERN_SEL                                      0x56b0
+#define mmDP8_DP_DPHY_TRAINING_PATTERN_SEL                                      0x57b0
+#define mmDP_DPHY_SYM0                                                          0x4ab1
+#define mmDP0_DP_DPHY_SYM0                                                      0x4ab1
+#define mmDP1_DP_DPHY_SYM0                                                      0x4bb1
+#define mmDP2_DP_DPHY_SYM0                                                      0x4cb1
+#define mmDP3_DP_DPHY_SYM0                                                      0x4db1
+#define mmDP4_DP_DPHY_SYM0                                                      0x4eb1
+#define mmDP5_DP_DPHY_SYM0                                                      0x4fb1
+#define mmDP6_DP_DPHY_SYM0                                                      0x54b1
+#define mmDP7_DP_DPHY_SYM0                                                      0x56b1
+#define mmDP8_DP_DPHY_SYM0                                                      0x57b1
+#define mmDP_DPHY_SYM1                                                          0x4ab2
+#define mmDP0_DP_DPHY_SYM1                                                      0x4ab2
+#define mmDP1_DP_DPHY_SYM1                                                      0x4bb2
+#define mmDP2_DP_DPHY_SYM1                                                      0x4cb2
+#define mmDP3_DP_DPHY_SYM1                                                      0x4db2
+#define mmDP4_DP_DPHY_SYM1                                                      0x4eb2
+#define mmDP5_DP_DPHY_SYM1                                                      0x4fb2
+#define mmDP6_DP_DPHY_SYM1                                                      0x54b2
+#define mmDP7_DP_DPHY_SYM1                                                      0x56b2
+#define mmDP8_DP_DPHY_SYM1                                                      0x57b2
+#define mmDP_DPHY_SYM2                                                          0x4ab3
+#define mmDP0_DP_DPHY_SYM2                                                      0x4ab3
+#define mmDP1_DP_DPHY_SYM2                                                      0x4bb3
+#define mmDP2_DP_DPHY_SYM2                                                      0x4cb3
+#define mmDP3_DP_DPHY_SYM2                                                      0x4db3
+#define mmDP4_DP_DPHY_SYM2                                                      0x4eb3
+#define mmDP5_DP_DPHY_SYM2                                                      0x4fb3
+#define mmDP6_DP_DPHY_SYM2                                                      0x54b3
+#define mmDP7_DP_DPHY_SYM2                                                      0x56b3
+#define mmDP8_DP_DPHY_SYM2                                                      0x57b3
+#define mmDP_DPHY_8B10B_CNTL                                                    0x4ab4
+#define mmDP0_DP_DPHY_8B10B_CNTL                                                0x4ab4
+#define mmDP1_DP_DPHY_8B10B_CNTL                                                0x4bb4
+#define mmDP2_DP_DPHY_8B10B_CNTL                                                0x4cb4
+#define mmDP3_DP_DPHY_8B10B_CNTL                                                0x4db4
+#define mmDP4_DP_DPHY_8B10B_CNTL                                                0x4eb4
+#define mmDP5_DP_DPHY_8B10B_CNTL                                                0x4fb4
+#define mmDP6_DP_DPHY_8B10B_CNTL                                                0x54b4
+#define mmDP7_DP_DPHY_8B10B_CNTL                                                0x56b4
+#define mmDP8_DP_DPHY_8B10B_CNTL                                                0x57b4
+#define mmDP_DPHY_PRBS_CNTL                                                     0x4ab5
+#define mmDP0_DP_DPHY_PRBS_CNTL                                                 0x4ab5
+#define mmDP1_DP_DPHY_PRBS_CNTL                                                 0x4bb5
+#define mmDP2_DP_DPHY_PRBS_CNTL                                                 0x4cb5
+#define mmDP3_DP_DPHY_PRBS_CNTL                                                 0x4db5
+#define mmDP4_DP_DPHY_PRBS_CNTL                                                 0x4eb5
+#define mmDP5_DP_DPHY_PRBS_CNTL                                                 0x4fb5
+#define mmDP6_DP_DPHY_PRBS_CNTL                                                 0x54b5
+#define mmDP7_DP_DPHY_PRBS_CNTL                                                 0x56b5
+#define mmDP8_DP_DPHY_PRBS_CNTL                                                 0x57b5
+#define mmDP_DPHY_BS_SR_SWAP_CNTL                                               0x4adc
+#define mmDP0_DP_DPHY_BS_SR_SWAP_CNTL                                           0x4adc
+#define mmDP1_DP_DPHY_BS_SR_SWAP_CNTL                                           0x4bdc
+#define mmDP2_DP_DPHY_BS_SR_SWAP_CNTL                                           0x4cdc
+#define mmDP3_DP_DPHY_BS_SR_SWAP_CNTL                                           0x4ddc
+#define mmDP4_DP_DPHY_BS_SR_SWAP_CNTL                                           0x4edc
+#define mmDP5_DP_DPHY_BS_SR_SWAP_CNTL                                           0x4fdc
+#define mmDP6_DP_DPHY_BS_SR_SWAP_CNTL                                           0x54dc
+#define mmDP7_DP_DPHY_BS_SR_SWAP_CNTL                                           0x56dc
+#define mmDP8_DP_DPHY_BS_SR_SWAP_CNTL                                           0x57dc
+#define mmDP_DPHY_CRC_EN                                                        0x4ab7
+#define mmDP0_DP_DPHY_CRC_EN                                                    0x4ab7
+#define mmDP1_DP_DPHY_CRC_EN                                                    0x4bb7
+#define mmDP2_DP_DPHY_CRC_EN                                                    0x4cb7
+#define mmDP3_DP_DPHY_CRC_EN                                                    0x4db7
+#define mmDP4_DP_DPHY_CRC_EN                                                    0x4eb7
+#define mmDP5_DP_DPHY_CRC_EN                                                    0x4fb7
+#define mmDP6_DP_DPHY_CRC_EN                                                    0x54b7
+#define mmDP7_DP_DPHY_CRC_EN                                                    0x56b7
+#define mmDP8_DP_DPHY_CRC_EN                                                    0x57b7
+#define mmDP_DPHY_CRC_CNTL                                                      0x4ab8
+#define mmDP0_DP_DPHY_CRC_CNTL                                                  0x4ab8
+#define mmDP1_DP_DPHY_CRC_CNTL                                                  0x4bb8
+#define mmDP2_DP_DPHY_CRC_CNTL                                                  0x4cb8
+#define mmDP3_DP_DPHY_CRC_CNTL                                                  0x4db8
+#define mmDP4_DP_DPHY_CRC_CNTL                                                  0x4eb8
+#define mmDP5_DP_DPHY_CRC_CNTL                                                  0x4fb8
+#define mmDP6_DP_DPHY_CRC_CNTL                                                  0x54b8
+#define mmDP7_DP_DPHY_CRC_CNTL                                                  0x56b8
+#define mmDP8_DP_DPHY_CRC_CNTL                                                  0x57b8
+#define mmDP_DPHY_CRC_RESULT                                                    0x4ab9
+#define mmDP0_DP_DPHY_CRC_RESULT                                                0x4ab9
+#define mmDP1_DP_DPHY_CRC_RESULT                                                0x4bb9
+#define mmDP2_DP_DPHY_CRC_RESULT                                                0x4cb9
+#define mmDP3_DP_DPHY_CRC_RESULT                                                0x4db9
+#define mmDP4_DP_DPHY_CRC_RESULT                                                0x4eb9
+#define mmDP5_DP_DPHY_CRC_RESULT                                                0x4fb9
+#define mmDP6_DP_DPHY_CRC_RESULT                                                0x54b9
+#define mmDP7_DP_DPHY_CRC_RESULT                                                0x56b9
+#define mmDP8_DP_DPHY_CRC_RESULT                                                0x57b9
+#define mmDP_DPHY_CRC_MST_CNTL                                                  0x4aba
+#define mmDP0_DP_DPHY_CRC_MST_CNTL                                              0x4aba
+#define mmDP1_DP_DPHY_CRC_MST_CNTL                                              0x4bba
+#define mmDP2_DP_DPHY_CRC_MST_CNTL                                              0x4cba
+#define mmDP3_DP_DPHY_CRC_MST_CNTL                                              0x4dba
+#define mmDP4_DP_DPHY_CRC_MST_CNTL                                              0x4eba
+#define mmDP5_DP_DPHY_CRC_MST_CNTL                                              0x4fba
+#define mmDP6_DP_DPHY_CRC_MST_CNTL                                              0x54ba
+#define mmDP7_DP_DPHY_CRC_MST_CNTL                                              0x56ba
+#define mmDP8_DP_DPHY_CRC_MST_CNTL                                              0x57ba
+#define mmDP_DPHY_CRC_MST_STATUS                                                0x4abb
+#define mmDP0_DP_DPHY_CRC_MST_STATUS                                            0x4abb
+#define mmDP1_DP_DPHY_CRC_MST_STATUS                                            0x4bbb
+#define mmDP2_DP_DPHY_CRC_MST_STATUS                                            0x4cbb
+#define mmDP3_DP_DPHY_CRC_MST_STATUS                                            0x4dbb
+#define mmDP4_DP_DPHY_CRC_MST_STATUS                                            0x4ebb
+#define mmDP5_DP_DPHY_CRC_MST_STATUS                                            0x4fbb
+#define mmDP6_DP_DPHY_CRC_MST_STATUS                                            0x54bb
+#define mmDP7_DP_DPHY_CRC_MST_STATUS                                            0x56bb
+#define mmDP8_DP_DPHY_CRC_MST_STATUS                                            0x57bb
+#define mmDP_DPHY_FAST_TRAINING                                                 0x4abc
+#define mmDP0_DP_DPHY_FAST_TRAINING                                             0x4abc
+#define mmDP1_DP_DPHY_FAST_TRAINING                                             0x4bbc
+#define mmDP2_DP_DPHY_FAST_TRAINING                                             0x4cbc
+#define mmDP3_DP_DPHY_FAST_TRAINING                                             0x4dbc
+#define mmDP4_DP_DPHY_FAST_TRAINING                                             0x4ebc
+#define mmDP5_DP_DPHY_FAST_TRAINING                                             0x4fbc
+#define mmDP6_DP_DPHY_FAST_TRAINING                                             0x54bc
+#define mmDP7_DP_DPHY_FAST_TRAINING                                             0x56bc
+#define mmDP8_DP_DPHY_FAST_TRAINING                                             0x57bc
+#define mmDP_DPHY_FAST_TRAINING_STATUS                                          0x4abd
+#define mmDP0_DP_DPHY_FAST_TRAINING_STATUS                                      0x4abd
+#define mmDP1_DP_DPHY_FAST_TRAINING_STATUS                                      0x4bbd
+#define mmDP2_DP_DPHY_FAST_TRAINING_STATUS                                      0x4cbd
+#define mmDP3_DP_DPHY_FAST_TRAINING_STATUS                                      0x4dbd
+#define mmDP4_DP_DPHY_FAST_TRAINING_STATUS                                      0x4ebd
+#define mmDP5_DP_DPHY_FAST_TRAINING_STATUS                                      0x4fbd
+#define mmDP6_DP_DPHY_FAST_TRAINING_STATUS                                      0x54bd
+#define mmDP7_DP_DPHY_FAST_TRAINING_STATUS                                      0x56bd
+#define mmDP8_DP_DPHY_FAST_TRAINING_STATUS                                      0x57bd
+#define mmDP_DPHY_HBR2_PATTERN_CONTROL                                          0x4add
+#define mmDP0_DP_DPHY_HBR2_PATTERN_CONTROL                                      0x4add
+#define mmDP1_DP_DPHY_HBR2_PATTERN_CONTROL                                      0x4bdd
+#define mmDP2_DP_DPHY_HBR2_PATTERN_CONTROL                                      0x4cdd
+#define mmDP3_DP_DPHY_HBR2_PATTERN_CONTROL                                      0x4ddd
+#define mmDP4_DP_DPHY_HBR2_PATTERN_CONTROL                                      0x4edd
+#define mmDP5_DP_DPHY_HBR2_PATTERN_CONTROL                                      0x4fdd
+#define mmDP6_DP_DPHY_HBR2_PATTERN_CONTROL                                      0x54dd
+#define mmDP7_DP_DPHY_HBR2_PATTERN_CONTROL                                      0x56dd
+#define mmDP8_DP_DPHY_HBR2_PATTERN_CONTROL                                      0x57dd
+#define mmDP_MSA_V_TIMING_OVERRIDE1                                             0x4abe
+#define mmDP0_DP_MSA_V_TIMING_OVERRIDE1                                         0x4abe
+#define mmDP1_DP_MSA_V_TIMING_OVERRIDE1                                         0x4bbe
+#define mmDP2_DP_MSA_V_TIMING_OVERRIDE1                                         0x4cbe
+#define mmDP3_DP_MSA_V_TIMING_OVERRIDE1                                         0x4dbe
+#define mmDP4_DP_MSA_V_TIMING_OVERRIDE1                                         0x4ebe
+#define mmDP5_DP_MSA_V_TIMING_OVERRIDE1                                         0x4fbe
+#define mmDP6_DP_MSA_V_TIMING_OVERRIDE1                                         0x54be
+#define mmDP7_DP_MSA_V_TIMING_OVERRIDE1                                         0x56be
+#define mmDP8_DP_MSA_V_TIMING_OVERRIDE1                                         0x57be
+#define mmDP_MSA_V_TIMING_OVERRIDE2                                             0x4abf
+#define mmDP0_DP_MSA_V_TIMING_OVERRIDE2                                         0x4abf
+#define mmDP1_DP_MSA_V_TIMING_OVERRIDE2                                         0x4bbf
+#define mmDP2_DP_MSA_V_TIMING_OVERRIDE2                                         0x4cbf
+#define mmDP3_DP_MSA_V_TIMING_OVERRIDE2                                         0x4dbf
+#define mmDP4_DP_MSA_V_TIMING_OVERRIDE2                                         0x4ebf
+#define mmDP5_DP_MSA_V_TIMING_OVERRIDE2                                         0x4fbf
+#define mmDP6_DP_MSA_V_TIMING_OVERRIDE2                                         0x54bf
+#define mmDP7_DP_MSA_V_TIMING_OVERRIDE2                                         0x56bf
+#define mmDP8_DP_MSA_V_TIMING_OVERRIDE2                                         0x57bf
+#define mmDP_SEC_CNTL                                                           0x4ac3
+#define mmDP0_DP_SEC_CNTL                                                       0x4ac3
+#define mmDP1_DP_SEC_CNTL                                                       0x4bc3
+#define mmDP2_DP_SEC_CNTL                                                       0x4cc3
+#define mmDP3_DP_SEC_CNTL                                                       0x4dc3
+#define mmDP4_DP_SEC_CNTL                                                       0x4ec3
+#define mmDP5_DP_SEC_CNTL                                                       0x4fc3
+#define mmDP6_DP_SEC_CNTL                                                       0x54c3
+#define mmDP7_DP_SEC_CNTL                                                       0x56c3
+#define mmDP8_DP_SEC_CNTL                                                       0x57c3
+#define mmDP_SEC_CNTL1                                                          0x4ac4
+#define mmDP0_DP_SEC_CNTL1                                                      0x4ac4
+#define mmDP1_DP_SEC_CNTL1                                                      0x4bc4
+#define mmDP2_DP_SEC_CNTL1                                                      0x4cc4
+#define mmDP3_DP_SEC_CNTL1                                                      0x4dc4
+#define mmDP4_DP_SEC_CNTL1                                                      0x4ec4
+#define mmDP5_DP_SEC_CNTL1                                                      0x4fc4
+#define mmDP6_DP_SEC_CNTL1                                                      0x54c4
+#define mmDP7_DP_SEC_CNTL1                                                      0x56c4
+#define mmDP8_DP_SEC_CNTL1                                                      0x57c4
+#define mmDP_SEC_FRAMING1                                                       0x4ac5
+#define mmDP0_DP_SEC_FRAMING1                                                   0x4ac5
+#define mmDP1_DP_SEC_FRAMING1                                                   0x4bc5
+#define mmDP2_DP_SEC_FRAMING1                                                   0x4cc5
+#define mmDP3_DP_SEC_FRAMING1                                                   0x4dc5
+#define mmDP4_DP_SEC_FRAMING1                                                   0x4ec5
+#define mmDP5_DP_SEC_FRAMING1                                                   0x4fc5
+#define mmDP6_DP_SEC_FRAMING1                                                   0x54c5
+#define mmDP7_DP_SEC_FRAMING1                                                   0x56c5
+#define mmDP8_DP_SEC_FRAMING1                                                   0x57c5
+#define mmDP_SEC_FRAMING2                                                       0x4ac6
+#define mmDP0_DP_SEC_FRAMING2                                                   0x4ac6
+#define mmDP1_DP_SEC_FRAMING2                                                   0x4bc6
+#define mmDP2_DP_SEC_FRAMING2                                                   0x4cc6
+#define mmDP3_DP_SEC_FRAMING2                                                   0x4dc6
+#define mmDP4_DP_SEC_FRAMING2                                                   0x4ec6
+#define mmDP5_DP_SEC_FRAMING2                                                   0x4fc6
+#define mmDP6_DP_SEC_FRAMING2                                                   0x54c6
+#define mmDP7_DP_SEC_FRAMING2                                                   0x56c6
+#define mmDP8_DP_SEC_FRAMING2                                                   0x57c6
+#define mmDP_SEC_FRAMING3                                                       0x4ac7
+#define mmDP0_DP_SEC_FRAMING3                                                   0x4ac7
+#define mmDP1_DP_SEC_FRAMING3                                                   0x4bc7
+#define mmDP2_DP_SEC_FRAMING3                                                   0x4cc7
+#define mmDP3_DP_SEC_FRAMING3                                                   0x4dc7
+#define mmDP4_DP_SEC_FRAMING3                                                   0x4ec7
+#define mmDP5_DP_SEC_FRAMING3                                                   0x4fc7
+#define mmDP6_DP_SEC_FRAMING3                                                   0x54c7
+#define mmDP7_DP_SEC_FRAMING3                                                   0x56c7
+#define mmDP8_DP_SEC_FRAMING3                                                   0x57c7
+#define mmDP_SEC_FRAMING4                                                       0x4ac8
+#define mmDP0_DP_SEC_FRAMING4                                                   0x4ac8
+#define mmDP1_DP_SEC_FRAMING4                                                   0x4bc8
+#define mmDP2_DP_SEC_FRAMING4                                                   0x4cc8
+#define mmDP3_DP_SEC_FRAMING4                                                   0x4dc8
+#define mmDP4_DP_SEC_FRAMING4                                                   0x4ec8
+#define mmDP5_DP_SEC_FRAMING4                                                   0x4fc8
+#define mmDP6_DP_SEC_FRAMING4                                                   0x54c8
+#define mmDP7_DP_SEC_FRAMING4                                                   0x56c8
+#define mmDP8_DP_SEC_FRAMING4                                                   0x57c8
+#define mmDP_SEC_AUD_N                                                          0x4ac9
+#define mmDP0_DP_SEC_AUD_N                                                      0x4ac9
+#define mmDP1_DP_SEC_AUD_N                                                      0x4bc9
+#define mmDP2_DP_SEC_AUD_N                                                      0x4cc9
+#define mmDP3_DP_SEC_AUD_N                                                      0x4dc9
+#define mmDP4_DP_SEC_AUD_N                                                      0x4ec9
+#define mmDP5_DP_SEC_AUD_N                                                      0x4fc9
+#define mmDP6_DP_SEC_AUD_N                                                      0x54c9
+#define mmDP7_DP_SEC_AUD_N                                                      0x56c9
+#define mmDP8_DP_SEC_AUD_N                                                      0x57c9
+#define mmDP_SEC_AUD_N_READBACK                                                 0x4aca
+#define mmDP0_DP_SEC_AUD_N_READBACK                                             0x4aca
+#define mmDP1_DP_SEC_AUD_N_READBACK                                             0x4bca
+#define mmDP2_DP_SEC_AUD_N_READBACK                                             0x4cca
+#define mmDP3_DP_SEC_AUD_N_READBACK                                             0x4dca
+#define mmDP4_DP_SEC_AUD_N_READBACK                                             0x4eca
+#define mmDP5_DP_SEC_AUD_N_READBACK                                             0x4fca
+#define mmDP6_DP_SEC_AUD_N_READBACK                                             0x54ca
+#define mmDP7_DP_SEC_AUD_N_READBACK                                             0x56ca
+#define mmDP8_DP_SEC_AUD_N_READBACK                                             0x57ca
+#define mmDP_SEC_AUD_M                                                          0x4acb
+#define mmDP0_DP_SEC_AUD_M                                                      0x4acb
+#define mmDP1_DP_SEC_AUD_M                                                      0x4bcb
+#define mmDP2_DP_SEC_AUD_M                                                      0x4ccb
+#define mmDP3_DP_SEC_AUD_M                                                      0x4dcb
+#define mmDP4_DP_SEC_AUD_M                                                      0x4ecb
+#define mmDP5_DP_SEC_AUD_M                                                      0x4fcb
+#define mmDP6_DP_SEC_AUD_M                                                      0x54cb
+#define mmDP7_DP_SEC_AUD_M                                                      0x56cb
+#define mmDP8_DP_SEC_AUD_M                                                      0x57cb
+#define mmDP_SEC_AUD_M_READBACK                                                 0x4acc
+#define mmDP0_DP_SEC_AUD_M_READBACK                                             0x4acc
+#define mmDP1_DP_SEC_AUD_M_READBACK                                             0x4bcc
+#define mmDP2_DP_SEC_AUD_M_READBACK                                             0x4ccc
+#define mmDP3_DP_SEC_AUD_M_READBACK                                             0x4dcc
+#define mmDP4_DP_SEC_AUD_M_READBACK                                             0x4ecc
+#define mmDP5_DP_SEC_AUD_M_READBACK                                             0x4fcc
+#define mmDP6_DP_SEC_AUD_M_READBACK                                             0x54cc
+#define mmDP7_DP_SEC_AUD_M_READBACK                                             0x56cc
+#define mmDP8_DP_SEC_AUD_M_READBACK                                             0x57cc
+#define mmDP_SEC_TIMESTAMP                                                      0x4acd
+#define mmDP0_DP_SEC_TIMESTAMP                                                  0x4acd
+#define mmDP1_DP_SEC_TIMESTAMP                                                  0x4bcd
+#define mmDP2_DP_SEC_TIMESTAMP                                                  0x4ccd
+#define mmDP3_DP_SEC_TIMESTAMP                                                  0x4dcd
+#define mmDP4_DP_SEC_TIMESTAMP                                                  0x4ecd
+#define mmDP5_DP_SEC_TIMESTAMP                                                  0x4fcd
+#define mmDP6_DP_SEC_TIMESTAMP                                                  0x54cd
+#define mmDP7_DP_SEC_TIMESTAMP                                                  0x56cd
+#define mmDP8_DP_SEC_TIMESTAMP                                                  0x57cd
+#define mmDP_SEC_PACKET_CNTL                                                    0x4ace
+#define mmDP0_DP_SEC_PACKET_CNTL                                                0x4ace
+#define mmDP1_DP_SEC_PACKET_CNTL                                                0x4bce
+#define mmDP2_DP_SEC_PACKET_CNTL                                                0x4cce
+#define mmDP3_DP_SEC_PACKET_CNTL                                                0x4dce
+#define mmDP4_DP_SEC_PACKET_CNTL                                                0x4ece
+#define mmDP5_DP_SEC_PACKET_CNTL                                                0x4fce
+#define mmDP6_DP_SEC_PACKET_CNTL                                                0x54ce
+#define mmDP7_DP_SEC_PACKET_CNTL                                                0x56ce
+#define mmDP8_DP_SEC_PACKET_CNTL                                                0x57ce
+#define mmDP_MSE_RATE_CNTL                                                      0x4acf
+#define mmDP0_DP_MSE_RATE_CNTL                                                  0x4acf
+#define mmDP1_DP_MSE_RATE_CNTL                                                  0x4bcf
+#define mmDP2_DP_MSE_RATE_CNTL                                                  0x4ccf
+#define mmDP3_DP_MSE_RATE_CNTL                                                  0x4dcf
+#define mmDP4_DP_MSE_RATE_CNTL                                                  0x4ecf
+#define mmDP5_DP_MSE_RATE_CNTL                                                  0x4fcf
+#define mmDP6_DP_MSE_RATE_CNTL                                                  0x54cf
+#define mmDP7_DP_MSE_RATE_CNTL                                                  0x56cf
+#define mmDP8_DP_MSE_RATE_CNTL                                                  0x57cf
+#define mmDP_MSE_RATE_UPDATE                                                    0x4ad1
+#define mmDP0_DP_MSE_RATE_UPDATE                                                0x4ad1
+#define mmDP1_DP_MSE_RATE_UPDATE                                                0x4bd1
+#define mmDP2_DP_MSE_RATE_UPDATE                                                0x4cd1
+#define mmDP3_DP_MSE_RATE_UPDATE                                                0x4dd1
+#define mmDP4_DP_MSE_RATE_UPDATE                                                0x4ed1
+#define mmDP5_DP_MSE_RATE_UPDATE                                                0x4fd1
+#define mmDP6_DP_MSE_RATE_UPDATE                                                0x54d1
+#define mmDP7_DP_MSE_RATE_UPDATE                                                0x56d1
+#define mmDP8_DP_MSE_RATE_UPDATE                                                0x57d1
+#define mmDP_MSE_SAT0                                                           0x4ad2
+#define mmDP0_DP_MSE_SAT0                                                       0x4ad2
+#define mmDP1_DP_MSE_SAT0                                                       0x4bd2
+#define mmDP2_DP_MSE_SAT0                                                       0x4cd2
+#define mmDP3_DP_MSE_SAT0                                                       0x4dd2
+#define mmDP4_DP_MSE_SAT0                                                       0x4ed2
+#define mmDP5_DP_MSE_SAT0                                                       0x4fd2
+#define mmDP6_DP_MSE_SAT0                                                       0x54d2
+#define mmDP7_DP_MSE_SAT0                                                       0x56d2
+#define mmDP8_DP_MSE_SAT0                                                       0x57d2
+#define mmDP_MSE_SAT1                                                           0x4ad3
+#define mmDP0_DP_MSE_SAT1                                                       0x4ad3
+#define mmDP1_DP_MSE_SAT1                                                       0x4bd3
+#define mmDP2_DP_MSE_SAT1                                                       0x4cd3
+#define mmDP3_DP_MSE_SAT1                                                       0x4dd3
+#define mmDP4_DP_MSE_SAT1                                                       0x4ed3
+#define mmDP5_DP_MSE_SAT1                                                       0x4fd3
+#define mmDP6_DP_MSE_SAT1                                                       0x54d3
+#define mmDP7_DP_MSE_SAT1                                                       0x56d3
+#define mmDP8_DP_MSE_SAT1                                                       0x57d3
+#define mmDP_MSE_SAT2                                                           0x4ad4
+#define mmDP0_DP_MSE_SAT2                                                       0x4ad4
+#define mmDP1_DP_MSE_SAT2                                                       0x4bd4
+#define mmDP2_DP_MSE_SAT2                                                       0x4cd4
+#define mmDP3_DP_MSE_SAT2                                                       0x4dd4
+#define mmDP4_DP_MSE_SAT2                                                       0x4ed4
+#define mmDP5_DP_MSE_SAT2                                                       0x4fd4
+#define mmDP6_DP_MSE_SAT2                                                       0x54d4
+#define mmDP7_DP_MSE_SAT2                                                       0x56d4
+#define mmDP8_DP_MSE_SAT2                                                       0x57d4
+#define mmDP_MSE_SAT_UPDATE                                                     0x4ad5
+#define mmDP0_DP_MSE_SAT_UPDATE                                                 0x4ad5
+#define mmDP1_DP_MSE_SAT_UPDATE                                                 0x4bd5
+#define mmDP2_DP_MSE_SAT_UPDATE                                                 0x4cd5
+#define mmDP3_DP_MSE_SAT_UPDATE                                                 0x4dd5
+#define mmDP4_DP_MSE_SAT_UPDATE                                                 0x4ed5
+#define mmDP5_DP_MSE_SAT_UPDATE                                                 0x4fd5
+#define mmDP6_DP_MSE_SAT_UPDATE                                                 0x54d5
+#define mmDP7_DP_MSE_SAT_UPDATE                                                 0x56d5
+#define mmDP8_DP_MSE_SAT_UPDATE                                                 0x57d5
+#define mmDP_MSE_LINK_TIMING                                                    0x4ad6
+#define mmDP0_DP_MSE_LINK_TIMING                                                0x4ad6
+#define mmDP1_DP_MSE_LINK_TIMING                                                0x4bd6
+#define mmDP2_DP_MSE_LINK_TIMING                                                0x4cd6
+#define mmDP3_DP_MSE_LINK_TIMING                                                0x4dd6
+#define mmDP4_DP_MSE_LINK_TIMING                                                0x4ed6
+#define mmDP5_DP_MSE_LINK_TIMING                                                0x4fd6
+#define mmDP6_DP_MSE_LINK_TIMING                                                0x54d6
+#define mmDP7_DP_MSE_LINK_TIMING                                                0x56d6
+#define mmDP8_DP_MSE_LINK_TIMING                                                0x57d6
+#define mmDP_MSE_MISC_CNTL                                                      0x4ad7
+#define mmDP0_DP_MSE_MISC_CNTL                                                  0x4ad7
+#define mmDP1_DP_MSE_MISC_CNTL                                                  0x4bd7
+#define mmDP2_DP_MSE_MISC_CNTL                                                  0x4cd7
+#define mmDP3_DP_MSE_MISC_CNTL                                                  0x4dd7
+#define mmDP4_DP_MSE_MISC_CNTL                                                  0x4ed7
+#define mmDP5_DP_MSE_MISC_CNTL                                                  0x4fd7
+#define mmDP6_DP_MSE_MISC_CNTL                                                  0x54d7
+#define mmDP7_DP_MSE_MISC_CNTL                                                  0x56d7
+#define mmDP8_DP_MSE_MISC_CNTL                                                  0x57d7
+#define mmDP_MSE_SAT0_STATUS                                                    0x4adf
+#define mmDP0_DP_MSE_SAT0_STATUS                                                0x4adf
+#define mmDP1_DP_MSE_SAT0_STATUS                                                0x4bdf
+#define mmDP2_DP_MSE_SAT0_STATUS                                                0x4cdf
+#define mmDP3_DP_MSE_SAT0_STATUS                                                0x4ddf
+#define mmDP4_DP_MSE_SAT0_STATUS                                                0x4edf
+#define mmDP5_DP_MSE_SAT0_STATUS                                                0x4fdf
+#define mmDP6_DP_MSE_SAT0_STATUS                                                0x54df
+#define mmDP7_DP_MSE_SAT0_STATUS                                                0x56df
+#define mmDP8_DP_MSE_SAT0_STATUS                                                0x57df
+#define mmDP_MSE_SAT1_STATUS                                                    0x4ae0
+#define mmDP0_DP_MSE_SAT1_STATUS                                                0x4ae0
+#define mmDP1_DP_MSE_SAT1_STATUS                                                0x4be0
+#define mmDP2_DP_MSE_SAT1_STATUS                                                0x4ce0
+#define mmDP3_DP_MSE_SAT1_STATUS                                                0x4de0
+#define mmDP4_DP_MSE_SAT1_STATUS                                                0x4ee0
+#define mmDP5_DP_MSE_SAT1_STATUS                                                0x4fe0
+#define mmDP6_DP_MSE_SAT1_STATUS                                                0x54e0
+#define mmDP7_DP_MSE_SAT1_STATUS                                                0x56e0
+#define mmDP8_DP_MSE_SAT1_STATUS                                                0x57e0
+#define mmDP_MSE_SAT2_STATUS                                                    0x4ae1
+#define mmDP0_DP_MSE_SAT2_STATUS                                                0x4ae1
+#define mmDP1_DP_MSE_SAT2_STATUS                                                0x4be1
+#define mmDP2_DP_MSE_SAT2_STATUS                                                0x4ce1
+#define mmDP3_DP_MSE_SAT2_STATUS                                                0x4de1
+#define mmDP4_DP_MSE_SAT2_STATUS                                                0x4ee1
+#define mmDP5_DP_MSE_SAT2_STATUS                                                0x4fe1
+#define mmDP6_DP_MSE_SAT2_STATUS                                                0x54e1
+#define mmDP7_DP_MSE_SAT2_STATUS                                                0x56e1
+#define mmDP8_DP_MSE_SAT2_STATUS                                                0x57e1
+#define mmDP_TEST_DEBUG_INDEX                                                   0x4ad8
+#define mmDP0_DP_TEST_DEBUG_INDEX                                               0x4ad8
+#define mmDP1_DP_TEST_DEBUG_INDEX                                               0x4bd8
+#define mmDP2_DP_TEST_DEBUG_INDEX                                               0x4cd8
+#define mmDP3_DP_TEST_DEBUG_INDEX                                               0x4dd8
+#define mmDP4_DP_TEST_DEBUG_INDEX                                               0x4ed8
+#define mmDP5_DP_TEST_DEBUG_INDEX                                               0x4fd8
+#define mmDP6_DP_TEST_DEBUG_INDEX                                               0x54d8
+#define mmDP7_DP_TEST_DEBUG_INDEX                                               0x56d8
+#define mmDP8_DP_TEST_DEBUG_INDEX                                               0x57d8
+#define mmDP_TEST_DEBUG_DATA                                                    0x4ad9
+#define mmDP0_DP_TEST_DEBUG_DATA                                                0x4ad9
+#define mmDP1_DP_TEST_DEBUG_DATA                                                0x4bd9
+#define mmDP2_DP_TEST_DEBUG_DATA                                                0x4cd9
+#define mmDP3_DP_TEST_DEBUG_DATA                                                0x4dd9
+#define mmDP4_DP_TEST_DEBUG_DATA                                                0x4ed9
+#define mmDP5_DP_TEST_DEBUG_DATA                                                0x4fd9
+#define mmDP6_DP_TEST_DEBUG_DATA                                                0x54d9
+#define mmDP7_DP_TEST_DEBUG_DATA                                                0x56d9
+#define mmDP8_DP_TEST_DEBUG_DATA                                                0x57d9
+#define mmDP_FE_TEST_DEBUG_INDEX                                                0x4ada
+#define mmDP0_DP_FE_TEST_DEBUG_INDEX                                            0x4ada
+#define mmDP1_DP_FE_TEST_DEBUG_INDEX                                            0x4bda
+#define mmDP2_DP_FE_TEST_DEBUG_INDEX                                            0x4cda
+#define mmDP3_DP_FE_TEST_DEBUG_INDEX                                            0x4dda
+#define mmDP4_DP_FE_TEST_DEBUG_INDEX                                            0x4eda
+#define mmDP5_DP_FE_TEST_DEBUG_INDEX                                            0x4fda
+#define mmDP6_DP_FE_TEST_DEBUG_INDEX                                            0x54da
+#define mmDP7_DP_FE_TEST_DEBUG_INDEX                                            0x56da
+#define mmDP8_DP_FE_TEST_DEBUG_INDEX                                            0x57da
+#define mmDP_FE_TEST_DEBUG_DATA                                                 0x4adb
+#define mmDP0_DP_FE_TEST_DEBUG_DATA                                             0x4adb
+#define mmDP1_DP_FE_TEST_DEBUG_DATA                                             0x4bdb
+#define mmDP2_DP_FE_TEST_DEBUG_DATA                                             0x4cdb
+#define mmDP3_DP_FE_TEST_DEBUG_DATA                                             0x4ddb
+#define mmDP4_DP_FE_TEST_DEBUG_DATA                                             0x4edb
+#define mmDP5_DP_FE_TEST_DEBUG_DATA                                             0x4fdb
+#define mmDP6_DP_FE_TEST_DEBUG_DATA                                             0x54db
+#define mmDP7_DP_FE_TEST_DEBUG_DATA                                             0x56db
+#define mmDP8_DP_FE_TEST_DEBUG_DATA                                             0x57db
+#define mmAUX_CONTROL                                                           0x5c00
+#define mmDP_AUX0_AUX_CONTROL                                                   0x5c00
+#define mmDP_AUX1_AUX_CONTROL                                                   0x5c1c
+#define mmDP_AUX2_AUX_CONTROL                                                   0x5c38
+#define mmDP_AUX3_AUX_CONTROL                                                   0x5c54
+#define mmDP_AUX4_AUX_CONTROL                                                   0x5c70
+#define mmDP_AUX5_AUX_CONTROL                                                   0x5c8c
+#define mmAUX_SW_CONTROL                                                        0x5c01
+#define mmDP_AUX0_AUX_SW_CONTROL                                                0x5c01
+#define mmDP_AUX1_AUX_SW_CONTROL                                                0x5c1d
+#define mmDP_AUX2_AUX_SW_CONTROL                                                0x5c39
+#define mmDP_AUX3_AUX_SW_CONTROL                                                0x5c55
+#define mmDP_AUX4_AUX_SW_CONTROL                                                0x5c71
+#define mmDP_AUX5_AUX_SW_CONTROL                                                0x5c8d
+#define mmAUX_ARB_CONTROL                                                       0x5c02
+#define mmDP_AUX0_AUX_ARB_CONTROL                                               0x5c02
+#define mmDP_AUX1_AUX_ARB_CONTROL                                               0x5c1e
+#define mmDP_AUX2_AUX_ARB_CONTROL                                               0x5c3a
+#define mmDP_AUX3_AUX_ARB_CONTROL                                               0x5c56
+#define mmDP_AUX4_AUX_ARB_CONTROL                                               0x5c72
+#define mmDP_AUX5_AUX_ARB_CONTROL                                               0x5c8e
+#define mmAUX_INTERRUPT_CONTROL                                                 0x5c03
+#define mmDP_AUX0_AUX_INTERRUPT_CONTROL                                         0x5c03
+#define mmDP_AUX1_AUX_INTERRUPT_CONTROL                                         0x5c1f
+#define mmDP_AUX2_AUX_INTERRUPT_CONTROL                                         0x5c3b
+#define mmDP_AUX3_AUX_INTERRUPT_CONTROL                                         0x5c57
+#define mmDP_AUX4_AUX_INTERRUPT_CONTROL                                         0x5c73
+#define mmDP_AUX5_AUX_INTERRUPT_CONTROL                                         0x5c8f
+#define mmAUX_SW_STATUS                                                         0x5c04
+#define mmDP_AUX0_AUX_SW_STATUS                                                 0x5c04
+#define mmDP_AUX1_AUX_SW_STATUS                                                 0x5c20
+#define mmDP_AUX2_AUX_SW_STATUS                                                 0x5c3c
+#define mmDP_AUX3_AUX_SW_STATUS                                                 0x5c58
+#define mmDP_AUX4_AUX_SW_STATUS                                                 0x5c74
+#define mmDP_AUX5_AUX_SW_STATUS                                                 0x5c90
+#define mmAUX_LS_STATUS                                                         0x5c05
+#define mmDP_AUX0_AUX_LS_STATUS                                                 0x5c05
+#define mmDP_AUX1_AUX_LS_STATUS                                                 0x5c21
+#define mmDP_AUX2_AUX_LS_STATUS                                                 0x5c3d
+#define mmDP_AUX3_AUX_LS_STATUS                                                 0x5c59
+#define mmDP_AUX4_AUX_LS_STATUS                                                 0x5c75
+#define mmDP_AUX5_AUX_LS_STATUS                                                 0x5c91
+#define mmAUX_SW_DATA                                                           0x5c06
+#define mmDP_AUX0_AUX_SW_DATA                                                   0x5c06
+#define mmDP_AUX1_AUX_SW_DATA                                                   0x5c22
+#define mmDP_AUX2_AUX_SW_DATA                                                   0x5c3e
+#define mmDP_AUX3_AUX_SW_DATA                                                   0x5c5a
+#define mmDP_AUX4_AUX_SW_DATA                                                   0x5c76
+#define mmDP_AUX5_AUX_SW_DATA                                                   0x5c92
+#define mmAUX_LS_DATA                                                           0x5c07
+#define mmDP_AUX0_AUX_LS_DATA                                                   0x5c07
+#define mmDP_AUX1_AUX_LS_DATA                                                   0x5c23
+#define mmDP_AUX2_AUX_LS_DATA                                                   0x5c3f
+#define mmDP_AUX3_AUX_LS_DATA                                                   0x5c5b
+#define mmDP_AUX4_AUX_LS_DATA                                                   0x5c77
+#define mmDP_AUX5_AUX_LS_DATA                                                   0x5c93
+#define mmAUX_DPHY_TX_REF_CONTROL                                               0x5c08
+#define mmDP_AUX0_AUX_DPHY_TX_REF_CONTROL                                       0x5c08
+#define mmDP_AUX1_AUX_DPHY_TX_REF_CONTROL                                       0x5c24
+#define mmDP_AUX2_AUX_DPHY_TX_REF_CONTROL                                       0x5c40
+#define mmDP_AUX3_AUX_DPHY_TX_REF_CONTROL                                       0x5c5c
+#define mmDP_AUX4_AUX_DPHY_TX_REF_CONTROL                                       0x5c78
+#define mmDP_AUX5_AUX_DPHY_TX_REF_CONTROL                                       0x5c94
+#define mmAUX_DPHY_TX_CONTROL                                                   0x5c09
+#define mmDP_AUX0_AUX_DPHY_TX_CONTROL                                           0x5c09
+#define mmDP_AUX1_AUX_DPHY_TX_CONTROL                                           0x5c25
+#define mmDP_AUX2_AUX_DPHY_TX_CONTROL                                           0x5c41
+#define mmDP_AUX3_AUX_DPHY_TX_CONTROL                                           0x5c5d
+#define mmDP_AUX4_AUX_DPHY_TX_CONTROL                                           0x5c79
+#define mmDP_AUX5_AUX_DPHY_TX_CONTROL                                           0x5c95
+#define mmAUX_DPHY_RX_CONTROL0                                                  0x5c0a
+#define mmDP_AUX0_AUX_DPHY_RX_CONTROL0                                          0x5c0a
+#define mmDP_AUX1_AUX_DPHY_RX_CONTROL0                                          0x5c26
+#define mmDP_AUX2_AUX_DPHY_RX_CONTROL0                                          0x5c42
+#define mmDP_AUX3_AUX_DPHY_RX_CONTROL0                                          0x5c5e
+#define mmDP_AUX4_AUX_DPHY_RX_CONTROL0                                          0x5c7a
+#define mmDP_AUX5_AUX_DPHY_RX_CONTROL0                                          0x5c96
+#define mmAUX_DPHY_RX_CONTROL1                                                  0x5c0b
+#define mmDP_AUX0_AUX_DPHY_RX_CONTROL1                                          0x5c0b
+#define mmDP_AUX1_AUX_DPHY_RX_CONTROL1                                          0x5c27
+#define mmDP_AUX2_AUX_DPHY_RX_CONTROL1                                          0x5c43
+#define mmDP_AUX3_AUX_DPHY_RX_CONTROL1                                          0x5c5f
+#define mmDP_AUX4_AUX_DPHY_RX_CONTROL1                                          0x5c7b
+#define mmDP_AUX5_AUX_DPHY_RX_CONTROL1                                          0x5c97
+#define mmAUX_DPHY_TX_STATUS                                                    0x5c0c
+#define mmDP_AUX0_AUX_DPHY_TX_STATUS                                            0x5c0c
+#define mmDP_AUX1_AUX_DPHY_TX_STATUS                                            0x5c28
+#define mmDP_AUX2_AUX_DPHY_TX_STATUS                                            0x5c44
+#define mmDP_AUX3_AUX_DPHY_TX_STATUS                                            0x5c60
+#define mmDP_AUX4_AUX_DPHY_TX_STATUS                                            0x5c7c
+#define mmDP_AUX5_AUX_DPHY_TX_STATUS                                            0x5c98
+#define mmAUX_DPHY_RX_STATUS                                                    0x5c0d
+#define mmDP_AUX0_AUX_DPHY_RX_STATUS                                            0x5c0d
+#define mmDP_AUX1_AUX_DPHY_RX_STATUS                                            0x5c29
+#define mmDP_AUX2_AUX_DPHY_RX_STATUS                                            0x5c45
+#define mmDP_AUX3_AUX_DPHY_RX_STATUS                                            0x5c61
+#define mmDP_AUX4_AUX_DPHY_RX_STATUS                                            0x5c7d
+#define mmDP_AUX5_AUX_DPHY_RX_STATUS                                            0x5c99
+#define mmAUX_GTC_SYNC_ERROR_CONTROL                                            0x5c0f
+#define mmDP_AUX0_AUX_GTC_SYNC_ERROR_CONTROL                                    0x5c0f
+#define mmDP_AUX1_AUX_GTC_SYNC_ERROR_CONTROL                                    0x5c2b
+#define mmDP_AUX2_AUX_GTC_SYNC_ERROR_CONTROL                                    0x5c47
+#define mmDP_AUX3_AUX_GTC_SYNC_ERROR_CONTROL                                    0x5c63
+#define mmDP_AUX4_AUX_GTC_SYNC_ERROR_CONTROL                                    0x5c7f
+#define mmDP_AUX5_AUX_GTC_SYNC_ERROR_CONTROL                                    0x5c9b
+#define mmAUX_GTC_SYNC_CONTROLLER_STATUS                                        0x5c10
+#define mmDP_AUX0_AUX_GTC_SYNC_CONTROLLER_STATUS                                0x5c10
+#define mmDP_AUX1_AUX_GTC_SYNC_CONTROLLER_STATUS                                0x5c2c
+#define mmDP_AUX2_AUX_GTC_SYNC_CONTROLLER_STATUS                                0x5c48
+#define mmDP_AUX3_AUX_GTC_SYNC_CONTROLLER_STATUS                                0x5c64
+#define mmDP_AUX4_AUX_GTC_SYNC_CONTROLLER_STATUS                                0x5c80
+#define mmDP_AUX5_AUX_GTC_SYNC_CONTROLLER_STATUS                                0x5c9c
+#define mmAUX_GTC_SYNC_STATUS                                                   0x5c11
+#define mmDP_AUX0_AUX_GTC_SYNC_STATUS                                           0x5c11
+#define mmDP_AUX1_AUX_GTC_SYNC_STATUS                                           0x5c2d
+#define mmDP_AUX2_AUX_GTC_SYNC_STATUS                                           0x5c49
+#define mmDP_AUX3_AUX_GTC_SYNC_STATUS                                           0x5c65
+#define mmDP_AUX4_AUX_GTC_SYNC_STATUS                                           0x5c81
+#define mmDP_AUX5_AUX_GTC_SYNC_STATUS                                           0x5c9d
+#define mmAUX_TEST_DEBUG_INDEX                                                  0x5c14
+#define mmDP_AUX0_AUX_TEST_DEBUG_INDEX                                          0x5c14
+#define mmDP_AUX1_AUX_TEST_DEBUG_INDEX                                          0x5c30
+#define mmDP_AUX2_AUX_TEST_DEBUG_INDEX                                          0x5c4c
+#define mmDP_AUX3_AUX_TEST_DEBUG_INDEX                                          0x5c68
+#define mmDP_AUX4_AUX_TEST_DEBUG_INDEX                                          0x5c84
+#define mmDP_AUX5_AUX_TEST_DEBUG_INDEX                                          0x5ca0
+#define mmAUX_TEST_DEBUG_DATA                                                   0x5c15
+#define mmDP_AUX0_AUX_TEST_DEBUG_DATA                                           0x5c15
+#define mmDP_AUX1_AUX_TEST_DEBUG_DATA                                           0x5c31
+#define mmDP_AUX2_AUX_TEST_DEBUG_DATA                                           0x5c4d
+#define mmDP_AUX3_AUX_TEST_DEBUG_DATA                                           0x5c69
+#define mmDP_AUX4_AUX_TEST_DEBUG_DATA                                           0x5c85
+#define mmDP_AUX5_AUX_TEST_DEBUG_DATA                                           0x5ca1
+#define ixDP_AUX_DEBUG_A                                                        0x10
+#define ixDP_AUX_DEBUG_B                                                        0x11
+#define ixDP_AUX_DEBUG_C                                                        0x12
+#define ixDP_AUX_DEBUG_D                                                        0x13
+#define ixDP_AUX_DEBUG_E                                                        0x14
+#define ixDP_AUX_DEBUG_F                                                        0x15
+#define ixDP_AUX_DEBUG_G                                                        0x16
+#define ixDP_AUX_DEBUG_H                                                        0x17
+#define ixDP_AUX_DEBUG_I                                                        0x18
+#define ixDP_AUX_DEBUG_J                                                        0x19
+#define ixDP_AUX_DEBUG_K                                                        0x1a
+#define ixDP_AUX_DEBUG_L                                                        0x1b
+#define ixDP_AUX_DEBUG_M                                                        0x1c
+#define ixDP_AUX_DEBUG_N                                                        0x1d
+#define ixDP_AUX_DEBUG_O                                                        0x1e
+#define ixDP_AUX_DEBUG_P                                                        0x1f
+#define ixDP_AUX_DEBUG_Q                                                        0x20
+#define mmDVO_ENABLE                                                            0x16a0
+#define mmDVO_SOURCE_SELECT                                                     0x16a1
+#define mmDVO_OUTPUT                                                            0x16a2
+#define mmDVO_CONTROL                                                           0x16a3
+#define mmDVO_CRC_EN                                                            0x16a4
+#define mmDVO_CRC2_SIG_MASK                                                     0x16a5
+#define mmDVO_CRC2_SIG_RESULT                                                   0x16a6
+#define mmDVO_FIFO_ERROR_STATUS                                                 0x16a7
+#define mmDVO_TEST_DEBUG_INDEX                                                  0x16a8
+#define mmDVO_TEST_DEBUG_DATA                                                   0x16a9
+#define mmFBC_CNTL                                                              0x280
+#define mmFBC_IDLE_FORCE_CLEAR_MASK                                             0x282
+#define mmFBC_START_STOP_DELAY                                                  0x283
+#define mmFBC_COMP_CNTL                                                         0x284
+#define mmFBC_COMP_MODE                                                         0x285
+#define mmFBC_DEBUG0                                                            0x286
+#define mmFBC_DEBUG1                                                            0x287
+#define mmFBC_DEBUG2                                                            0x288
+#define mmFBC_IND_LUT0                                                          0x289
+#define mmFBC_IND_LUT1                                                          0x28a
+#define mmFBC_IND_LUT2                                                          0x28b
+#define mmFBC_IND_LUT3                                                          0x28c
+#define mmFBC_IND_LUT4                                                          0x28d
+#define mmFBC_IND_LUT5                                                          0x28e
+#define mmFBC_IND_LUT6                                                          0x28f
+#define mmFBC_IND_LUT7                                                          0x290
+#define mmFBC_IND_LUT8                                                          0x291
+#define mmFBC_IND_LUT9                                                          0x292
+#define mmFBC_IND_LUT10                                                         0x293
+#define mmFBC_IND_LUT11                                                         0x294
+#define mmFBC_IND_LUT12                                                         0x295
+#define mmFBC_IND_LUT13                                                         0x296
+#define mmFBC_IND_LUT14                                                         0x297
+#define mmFBC_IND_LUT15                                                         0x298
+#define mmFBC_CSM_REGION_OFFSET_01                                              0x299
+#define mmFBC_CSM_REGION_OFFSET_23                                              0x29a
+#define mmFBC_CLIENT_REGION_MASK                                                0x29b
+#define mmFBC_DEBUG_COMP                                                        0x29c
+#define mmFBC_DEBUG_CSR                                                         0x29d
+#define mmFBC_DEBUG_CSR_RDATA                                                   0x29e
+#define mmFBC_DEBUG_CSR_WDATA                                                   0x29f
+#define mmFBC_DEBUG_CSR_RDATA_HI                                                0x2a0
+#define mmFBC_DEBUG_CSR_WDATA_HI                                                0x2a1
+#define mmFBC_MISC                                                              0x2a2
+#define mmFBC_STATUS                                                            0x2a3
+#define mmFBC_ALPHA_CNTL                                                        0x2a6
+#define mmFBC_ALPHA_RGB_OVERRIDE                                                0x2a7
+#define mmFBC_TEST_DEBUG_INDEX                                                  0x2a4
+#define mmFBC_TEST_DEBUG_DATA                                                   0x2a5
+#define mmFMT_CLAMP_COMPONENT_R                                                 0x1be8
+#define mmFMT0_FMT_CLAMP_COMPONENT_R                                            0x1be8
+#define mmFMT1_FMT_CLAMP_COMPONENT_R                                            0x1de8
+#define mmFMT2_FMT_CLAMP_COMPONENT_R                                            0x1fe8
+#define mmFMT3_FMT_CLAMP_COMPONENT_R                                            0x41e8
+#define mmFMT4_FMT_CLAMP_COMPONENT_R                                            0x43e8
+#define mmFMT5_FMT_CLAMP_COMPONENT_R                                            0x45e8
+#define mmFMT_CLAMP_COMPONENT_G                                                 0x1be9
+#define mmFMT0_FMT_CLAMP_COMPONENT_G                                            0x1be9
+#define mmFMT1_FMT_CLAMP_COMPONENT_G                                            0x1de9
+#define mmFMT2_FMT_CLAMP_COMPONENT_G                                            0x1fe9
+#define mmFMT3_FMT_CLAMP_COMPONENT_G                                            0x41e9
+#define mmFMT4_FMT_CLAMP_COMPONENT_G                                            0x43e9
+#define mmFMT5_FMT_CLAMP_COMPONENT_G                                            0x45e9
+#define mmFMT_CLAMP_COMPONENT_B                                                 0x1bea
+#define mmFMT0_FMT_CLAMP_COMPONENT_B                                            0x1bea
+#define mmFMT1_FMT_CLAMP_COMPONENT_B                                            0x1dea
+#define mmFMT2_FMT_CLAMP_COMPONENT_B                                            0x1fea
+#define mmFMT3_FMT_CLAMP_COMPONENT_B                                            0x41ea
+#define mmFMT4_FMT_CLAMP_COMPONENT_B                                            0x43ea
+#define mmFMT5_FMT_CLAMP_COMPONENT_B                                            0x45ea
+#define mmFMT_DYNAMIC_EXP_CNTL                                                  0x1bed
+#define mmFMT0_FMT_DYNAMIC_EXP_CNTL                                             0x1bed
+#define mmFMT1_FMT_DYNAMIC_EXP_CNTL                                             0x1ded
+#define mmFMT2_FMT_DYNAMIC_EXP_CNTL                                             0x1fed
+#define mmFMT3_FMT_DYNAMIC_EXP_CNTL                                             0x41ed
+#define mmFMT4_FMT_DYNAMIC_EXP_CNTL                                             0x43ed
+#define mmFMT5_FMT_DYNAMIC_EXP_CNTL                                             0x45ed
+#define mmFMT_CONTROL                                                           0x1bee
+#define mmFMT0_FMT_CONTROL                                                      0x1bee
+#define mmFMT1_FMT_CONTROL                                                      0x1dee
+#define mmFMT2_FMT_CONTROL                                                      0x1fee
+#define mmFMT3_FMT_CONTROL                                                      0x41ee
+#define mmFMT4_FMT_CONTROL                                                      0x43ee
+#define mmFMT5_FMT_CONTROL                                                      0x45ee
+#define mmFMT_BIT_DEPTH_CONTROL                                                 0x1bf2
+#define mmFMT0_FMT_BIT_DEPTH_CONTROL                                            0x1bf2
+#define mmFMT1_FMT_BIT_DEPTH_CONTROL                                            0x1df2
+#define mmFMT2_FMT_BIT_DEPTH_CONTROL                                            0x1ff2
+#define mmFMT3_FMT_BIT_DEPTH_CONTROL                                            0x41f2
+#define mmFMT4_FMT_BIT_DEPTH_CONTROL                                            0x43f2
+#define mmFMT5_FMT_BIT_DEPTH_CONTROL                                            0x45f2
+#define mmFMT_DITHER_RAND_R_SEED                                                0x1bf3
+#define mmFMT0_FMT_DITHER_RAND_R_SEED                                           0x1bf3
+#define mmFMT1_FMT_DITHER_RAND_R_SEED                                           0x1df3
+#define mmFMT2_FMT_DITHER_RAND_R_SEED                                           0x1ff3
+#define mmFMT3_FMT_DITHER_RAND_R_SEED                                           0x41f3
+#define mmFMT4_FMT_DITHER_RAND_R_SEED                                           0x43f3
+#define mmFMT5_FMT_DITHER_RAND_R_SEED                                           0x45f3
+#define mmFMT_DITHER_RAND_G_SEED                                                0x1bf4
+#define mmFMT0_FMT_DITHER_RAND_G_SEED                                           0x1bf4
+#define mmFMT1_FMT_DITHER_RAND_G_SEED                                           0x1df4
+#define mmFMT2_FMT_DITHER_RAND_G_SEED                                           0x1ff4
+#define mmFMT3_FMT_DITHER_RAND_G_SEED                                           0x41f4
+#define mmFMT4_FMT_DITHER_RAND_G_SEED                                           0x43f4
+#define mmFMT5_FMT_DITHER_RAND_G_SEED                                           0x45f4
+#define mmFMT_DITHER_RAND_B_SEED                                                0x1bf5
+#define mmFMT0_FMT_DITHER_RAND_B_SEED                                           0x1bf5
+#define mmFMT1_FMT_DITHER_RAND_B_SEED                                           0x1df5
+#define mmFMT2_FMT_DITHER_RAND_B_SEED                                           0x1ff5
+#define mmFMT3_FMT_DITHER_RAND_B_SEED                                           0x41f5
+#define mmFMT4_FMT_DITHER_RAND_B_SEED                                           0x43f5
+#define mmFMT5_FMT_DITHER_RAND_B_SEED                                           0x45f5
+#define mmFMT_TEMPORAL_DITHER_PATTERN_CONTROL                                   0x1bf6
+#define mmFMT0_FMT_TEMPORAL_DITHER_PATTERN_CONTROL                              0x1bf6
+#define mmFMT1_FMT_TEMPORAL_DITHER_PATTERN_CONTROL                              0x1df6
+#define mmFMT2_FMT_TEMPORAL_DITHER_PATTERN_CONTROL                              0x1ff6
+#define mmFMT3_FMT_TEMPORAL_DITHER_PATTERN_CONTROL                              0x41f6
+#define mmFMT4_FMT_TEMPORAL_DITHER_PATTERN_CONTROL                              0x43f6
+#define mmFMT5_FMT_TEMPORAL_DITHER_PATTERN_CONTROL                              0x45f6
+#define mmFMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX                     0x1bf7
+#define mmFMT0_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX                0x1bf7
+#define mmFMT1_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX                0x1df7
+#define mmFMT2_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX                0x1ff7
+#define mmFMT3_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX                0x41f7
+#define mmFMT4_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX                0x43f7
+#define mmFMT5_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX                0x45f7
+#define mmFMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX                     0x1bf8
+#define mmFMT0_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX                0x1bf8
+#define mmFMT1_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX                0x1df8
+#define mmFMT2_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX                0x1ff8
+#define mmFMT3_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX                0x41f8
+#define mmFMT4_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX                0x43f8
+#define mmFMT5_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX                0x45f8
+#define mmFMT_CLAMP_CNTL                                                        0x1bf9
+#define mmFMT0_FMT_CLAMP_CNTL                                                   0x1bf9
+#define mmFMT1_FMT_CLAMP_CNTL                                                   0x1df9
+#define mmFMT2_FMT_CLAMP_CNTL                                                   0x1ff9
+#define mmFMT3_FMT_CLAMP_CNTL                                                   0x41f9
+#define mmFMT4_FMT_CLAMP_CNTL                                                   0x43f9
+#define mmFMT5_FMT_CLAMP_CNTL                                                   0x45f9
+#define mmFMT_CRC_CNTL                                                          0x1bfa
+#define mmFMT0_FMT_CRC_CNTL                                                     0x1bfa
+#define mmFMT1_FMT_CRC_CNTL                                                     0x1dfa
+#define mmFMT2_FMT_CRC_CNTL                                                     0x1ffa
+#define mmFMT3_FMT_CRC_CNTL                                                     0x41fa
+#define mmFMT4_FMT_CRC_CNTL                                                     0x43fa
+#define mmFMT5_FMT_CRC_CNTL                                                     0x45fa
+#define mmFMT_CRC_SIG_RED_GREEN_MASK                                            0x1bfb
+#define mmFMT0_FMT_CRC_SIG_RED_GREEN_MASK                                       0x1bfb
+#define mmFMT1_FMT_CRC_SIG_RED_GREEN_MASK                                       0x1dfb
+#define mmFMT2_FMT_CRC_SIG_RED_GREEN_MASK                                       0x1ffb
+#define mmFMT3_FMT_CRC_SIG_RED_GREEN_MASK                                       0x41fb
+#define mmFMT4_FMT_CRC_SIG_RED_GREEN_MASK                                       0x43fb
+#define mmFMT5_FMT_CRC_SIG_RED_GREEN_MASK                                       0x45fb
+#define mmFMT_CRC_SIG_BLUE_CONTROL_MASK                                         0x1bfc
+#define mmFMT0_FMT_CRC_SIG_BLUE_CONTROL_MASK                                    0x1bfc
+#define mmFMT1_FMT_CRC_SIG_BLUE_CONTROL_MASK                                    0x1dfc
+#define mmFMT2_FMT_CRC_SIG_BLUE_CONTROL_MASK                                    0x1ffc
+#define mmFMT3_FMT_CRC_SIG_BLUE_CONTROL_MASK                                    0x41fc
+#define mmFMT4_FMT_CRC_SIG_BLUE_CONTROL_MASK                                    0x43fc
+#define mmFMT5_FMT_CRC_SIG_BLUE_CONTROL_MASK                                    0x45fc
+#define mmFMT_CRC_SIG_RED_GREEN                                                 0x1bfd
+#define mmFMT0_FMT_CRC_SIG_RED_GREEN                                            0x1bfd
+#define mmFMT1_FMT_CRC_SIG_RED_GREEN                                            0x1dfd
+#define mmFMT2_FMT_CRC_SIG_RED_GREEN                                            0x1ffd
+#define mmFMT3_FMT_CRC_SIG_RED_GREEN                                            0x41fd
+#define mmFMT4_FMT_CRC_SIG_RED_GREEN                                            0x43fd
+#define mmFMT5_FMT_CRC_SIG_RED_GREEN                                            0x45fd
+#define mmFMT_CRC_SIG_BLUE_CONTROL                                              0x1bfe
+#define mmFMT0_FMT_CRC_SIG_BLUE_CONTROL                                         0x1bfe
+#define mmFMT1_FMT_CRC_SIG_BLUE_CONTROL                                         0x1dfe
+#define mmFMT2_FMT_CRC_SIG_BLUE_CONTROL                                         0x1ffe
+#define mmFMT3_FMT_CRC_SIG_BLUE_CONTROL                                         0x41fe
+#define mmFMT4_FMT_CRC_SIG_BLUE_CONTROL                                         0x43fe
+#define mmFMT5_FMT_CRC_SIG_BLUE_CONTROL                                         0x45fe
+#define mmFMT_DEBUG_CNTL                                                        0x1bff
+#define mmFMT0_FMT_DEBUG_CNTL                                                   0x1bff
+#define mmFMT1_FMT_DEBUG_CNTL                                                   0x1dff
+#define mmFMT2_FMT_DEBUG_CNTL                                                   0x1fff
+#define mmFMT3_FMT_DEBUG_CNTL                                                   0x41ff
+#define mmFMT4_FMT_DEBUG_CNTL                                                   0x43ff
+#define mmFMT5_FMT_DEBUG_CNTL                                                   0x45ff
+#define mmFMT_SIDE_BY_SIDE_STEREO_CONTROL                                       0x1bf0
+#define mmFMT0_FMT_SIDE_BY_SIDE_STEREO_CONTROL                                  0x1bf0
+#define mmFMT1_FMT_SIDE_BY_SIDE_STEREO_CONTROL                                  0x1df0
+#define mmFMT2_FMT_SIDE_BY_SIDE_STEREO_CONTROL                                  0x1ff0
+#define mmFMT3_FMT_SIDE_BY_SIDE_STEREO_CONTROL                                  0x41f0
+#define mmFMT4_FMT_SIDE_BY_SIDE_STEREO_CONTROL                                  0x43f0
+#define mmFMT5_FMT_SIDE_BY_SIDE_STEREO_CONTROL                                  0x45f0
+#define mmFMT_420_HBLANK_EARLY_START                                            0x1bf1
+#define mmFMT0_FMT_420_HBLANK_EARLY_START                                       0x1bf1
+#define mmFMT1_FMT_420_HBLANK_EARLY_START                                       0x1df1
+#define mmFMT2_FMT_420_HBLANK_EARLY_START                                       0x1ff1
+#define mmFMT3_FMT_420_HBLANK_EARLY_START                                       0x41f1
+#define mmFMT4_FMT_420_HBLANK_EARLY_START                                       0x43f1
+#define mmFMT5_FMT_420_HBLANK_EARLY_START                                       0x45f1
+#define mmFMT_TEST_DEBUG_INDEX                                                  0x1beb
+#define mmFMT0_FMT_TEST_DEBUG_INDEX                                             0x1beb
+#define mmFMT1_FMT_TEST_DEBUG_INDEX                                             0x1deb
+#define mmFMT2_FMT_TEST_DEBUG_INDEX                                             0x1feb
+#define mmFMT3_FMT_TEST_DEBUG_INDEX                                             0x41eb
+#define mmFMT4_FMT_TEST_DEBUG_INDEX                                             0x43eb
+#define mmFMT5_FMT_TEST_DEBUG_INDEX                                             0x45eb
+#define mmFMT_TEST_DEBUG_DATA                                                   0x1bec
+#define mmFMT0_FMT_TEST_DEBUG_DATA                                              0x1bec
+#define mmFMT1_FMT_TEST_DEBUG_DATA                                              0x1dec
+#define mmFMT2_FMT_TEST_DEBUG_DATA                                              0x1fec
+#define mmFMT3_FMT_TEST_DEBUG_DATA                                              0x41ec
+#define mmFMT4_FMT_TEST_DEBUG_DATA                                              0x43ec
+#define mmFMT5_FMT_TEST_DEBUG_DATA                                              0x45ec
+#define ixFMT_DEBUG0                                                            0x1
+#define ixFMT_DEBUG1                                                            0x2
+#define ixFMT_DEBUG2                                                            0x3
+#define ixFMT_DEBUG3                                                            0x4
+#define ixFMT_DEBUG_ID                                                          0x0
+#define mmLB_DATA_FORMAT                                                        0x1ac0
+#define mmLB0_LB_DATA_FORMAT                                                    0x1ac0
+#define mmLB1_LB_DATA_FORMAT                                                    0x1cc0
+#define mmLB2_LB_DATA_FORMAT                                                    0x1ec0
+#define mmLB3_LB_DATA_FORMAT                                                    0x40c0
+#define mmLB4_LB_DATA_FORMAT                                                    0x42c0
+#define mmLB5_LB_DATA_FORMAT                                                    0x44c0
+#define mmLB_MEMORY_CTRL                                                        0x1ac1
+#define mmLB0_LB_MEMORY_CTRL                                                    0x1ac1
+#define mmLB1_LB_MEMORY_CTRL                                                    0x1cc1
+#define mmLB2_LB_MEMORY_CTRL                                                    0x1ec1
+#define mmLB3_LB_MEMORY_CTRL                                                    0x40c1
+#define mmLB4_LB_MEMORY_CTRL                                                    0x42c1
+#define mmLB5_LB_MEMORY_CTRL                                                    0x44c1
+#define mmLB_MEMORY_SIZE_STATUS                                                 0x1ac2
+#define mmLB0_LB_MEMORY_SIZE_STATUS                                             0x1ac2
+#define mmLB1_LB_MEMORY_SIZE_STATUS                                             0x1cc2
+#define mmLB2_LB_MEMORY_SIZE_STATUS                                             0x1ec2
+#define mmLB3_LB_MEMORY_SIZE_STATUS                                             0x40c2
+#define mmLB4_LB_MEMORY_SIZE_STATUS                                             0x42c2
+#define mmLB5_LB_MEMORY_SIZE_STATUS                                             0x44c2
+#define mmLB_DESKTOP_HEIGHT                                                     0x1ac3
+#define mmLB0_LB_DESKTOP_HEIGHT                                                 0x1ac3
+#define mmLB1_LB_DESKTOP_HEIGHT                                                 0x1cc3
+#define mmLB2_LB_DESKTOP_HEIGHT                                                 0x1ec3
+#define mmLB3_LB_DESKTOP_HEIGHT                                                 0x40c3
+#define mmLB4_LB_DESKTOP_HEIGHT                                                 0x42c3
+#define mmLB5_LB_DESKTOP_HEIGHT                                                 0x44c3
+#define mmLB_VLINE_START_END                                                    0x1ac4
+#define mmLB0_LB_VLINE_START_END                                                0x1ac4
+#define mmLB1_LB_VLINE_START_END                                                0x1cc4
+#define mmLB2_LB_VLINE_START_END                                                0x1ec4
+#define mmLB3_LB_VLINE_START_END                                                0x40c4
+#define mmLB4_LB_VLINE_START_END                                                0x42c4
+#define mmLB5_LB_VLINE_START_END                                                0x44c4
+#define mmLB_VLINE2_START_END                                                   0x1ac5
+#define mmLB0_LB_VLINE2_START_END                                               0x1ac5
+#define mmLB1_LB_VLINE2_START_END                                               0x1cc5
+#define mmLB2_LB_VLINE2_START_END                                               0x1ec5
+#define mmLB3_LB_VLINE2_START_END                                               0x40c5
+#define mmLB4_LB_VLINE2_START_END                                               0x42c5
+#define mmLB5_LB_VLINE2_START_END                                               0x44c5
+#define mmLB_V_COUNTER                                                          0x1ac6
+#define mmLB0_LB_V_COUNTER                                                      0x1ac6
+#define mmLB1_LB_V_COUNTER                                                      0x1cc6
+#define mmLB2_LB_V_COUNTER                                                      0x1ec6
+#define mmLB3_LB_V_COUNTER                                                      0x40c6
+#define mmLB4_LB_V_COUNTER                                                      0x42c6
+#define mmLB5_LB_V_COUNTER                                                      0x44c6
+#define mmLB_SNAPSHOT_V_COUNTER                                                 0x1ac7
+#define mmLB0_LB_SNAPSHOT_V_COUNTER                                             0x1ac7
+#define mmLB1_LB_SNAPSHOT_V_COUNTER                                             0x1cc7
+#define mmLB2_LB_SNAPSHOT_V_COUNTER                                             0x1ec7
+#define mmLB3_LB_SNAPSHOT_V_COUNTER                                             0x40c7
+#define mmLB4_LB_SNAPSHOT_V_COUNTER                                             0x42c7
+#define mmLB5_LB_SNAPSHOT_V_COUNTER                                             0x44c7
+#define mmLB_INTERRUPT_MASK                                                     0x1ac8
+#define mmLB0_LB_INTERRUPT_MASK                                                 0x1ac8
+#define mmLB1_LB_INTERRUPT_MASK                                                 0x1cc8
+#define mmLB2_LB_INTERRUPT_MASK                                                 0x1ec8
+#define mmLB3_LB_INTERRUPT_MASK                                                 0x40c8
+#define mmLB4_LB_INTERRUPT_MASK                                                 0x42c8
+#define mmLB5_LB_INTERRUPT_MASK                                                 0x44c8
+#define mmLB_VLINE_STATUS                                                       0x1ac9
+#define mmLB0_LB_VLINE_STATUS                                                   0x1ac9
+#define mmLB1_LB_VLINE_STATUS                                                   0x1cc9
+#define mmLB2_LB_VLINE_STATUS                                                   0x1ec9
+#define mmLB3_LB_VLINE_STATUS                                                   0x40c9
+#define mmLB4_LB_VLINE_STATUS                                                   0x42c9
+#define mmLB5_LB_VLINE_STATUS                                                   0x44c9
+#define mmLB_VLINE2_STATUS                                                      0x1aca
+#define mmLB0_LB_VLINE2_STATUS                                                  0x1aca
+#define mmLB1_LB_VLINE2_STATUS                                                  0x1cca
+#define mmLB2_LB_VLINE2_STATUS                                                  0x1eca
+#define mmLB3_LB_VLINE2_STATUS                                                  0x40ca
+#define mmLB4_LB_VLINE2_STATUS                                                  0x42ca
+#define mmLB5_LB_VLINE2_STATUS                                                  0x44ca
+#define mmLB_VBLANK_STATUS                                                      0x1acb
+#define mmLB0_LB_VBLANK_STATUS                                                  0x1acb
+#define mmLB1_LB_VBLANK_STATUS                                                  0x1ccb
+#define mmLB2_LB_VBLANK_STATUS                                                  0x1ecb
+#define mmLB3_LB_VBLANK_STATUS                                                  0x40cb
+#define mmLB4_LB_VBLANK_STATUS                                                  0x42cb
+#define mmLB5_LB_VBLANK_STATUS                                                  0x44cb
+#define mmLB_SYNC_RESET_SEL                                                     0x1acc
+#define mmLB0_LB_SYNC_RESET_SEL                                                 0x1acc
+#define mmLB1_LB_SYNC_RESET_SEL                                                 0x1ccc
+#define mmLB2_LB_SYNC_RESET_SEL                                                 0x1ecc
+#define mmLB3_LB_SYNC_RESET_SEL                                                 0x40cc
+#define mmLB4_LB_SYNC_RESET_SEL                                                 0x42cc
+#define mmLB5_LB_SYNC_RESET_SEL                                                 0x44cc
+#define mmLB_BLACK_KEYER_R_CR                                                   0x1acd
+#define mmLB0_LB_BLACK_KEYER_R_CR                                               0x1acd
+#define mmLB1_LB_BLACK_KEYER_R_CR                                               0x1ccd
+#define mmLB2_LB_BLACK_KEYER_R_CR                                               0x1ecd
+#define mmLB3_LB_BLACK_KEYER_R_CR                                               0x40cd
+#define mmLB4_LB_BLACK_KEYER_R_CR                                               0x42cd
+#define mmLB5_LB_BLACK_KEYER_R_CR                                               0x44cd
+#define mmLB_BLACK_KEYER_G_Y                                                    0x1ace
+#define mmLB0_LB_BLACK_KEYER_G_Y                                                0x1ace
+#define mmLB1_LB_BLACK_KEYER_G_Y                                                0x1cce
+#define mmLB2_LB_BLACK_KEYER_G_Y                                                0x1ece
+#define mmLB3_LB_BLACK_KEYER_G_Y                                                0x40ce
+#define mmLB4_LB_BLACK_KEYER_G_Y                                                0x42ce
+#define mmLB5_LB_BLACK_KEYER_G_Y                                                0x44ce
+#define mmLB_BLACK_KEYER_B_CB                                                   0x1acf
+#define mmLB0_LB_BLACK_KEYER_B_CB                                               0x1acf
+#define mmLB1_LB_BLACK_KEYER_B_CB                                               0x1ccf
+#define mmLB2_LB_BLACK_KEYER_B_CB                                               0x1ecf
+#define mmLB3_LB_BLACK_KEYER_B_CB                                               0x40cf
+#define mmLB4_LB_BLACK_KEYER_B_CB                                               0x42cf
+#define mmLB5_LB_BLACK_KEYER_B_CB                                               0x44cf
+#define mmLB_KEYER_COLOR_CTRL                                                   0x1ad0
+#define mmLB0_LB_KEYER_COLOR_CTRL                                               0x1ad0
+#define mmLB1_LB_KEYER_COLOR_CTRL                                               0x1cd0
+#define mmLB2_LB_KEYER_COLOR_CTRL                                               0x1ed0
+#define mmLB3_LB_KEYER_COLOR_CTRL                                               0x40d0
+#define mmLB4_LB_KEYER_COLOR_CTRL                                               0x42d0
+#define mmLB5_LB_KEYER_COLOR_CTRL                                               0x44d0
+#define mmLB_KEYER_COLOR_R_CR                                                   0x1ad1
+#define mmLB0_LB_KEYER_COLOR_R_CR                                               0x1ad1
+#define mmLB1_LB_KEYER_COLOR_R_CR                                               0x1cd1
+#define mmLB2_LB_KEYER_COLOR_R_CR                                               0x1ed1
+#define mmLB3_LB_KEYER_COLOR_R_CR                                               0x40d1
+#define mmLB4_LB_KEYER_COLOR_R_CR                                               0x42d1
+#define mmLB5_LB_KEYER_COLOR_R_CR                                               0x44d1
+#define mmLB_KEYER_COLOR_G_Y                                                    0x1ad2
+#define mmLB0_LB_KEYER_COLOR_G_Y                                                0x1ad2
+#define mmLB1_LB_KEYER_COLOR_G_Y                                                0x1cd2
+#define mmLB2_LB_KEYER_COLOR_G_Y                                                0x1ed2
+#define mmLB3_LB_KEYER_COLOR_G_Y                                                0x40d2
+#define mmLB4_LB_KEYER_COLOR_G_Y                                                0x42d2
+#define mmLB5_LB_KEYER_COLOR_G_Y                                                0x44d2
+#define mmLB_KEYER_COLOR_B_CB                                                   0x1ad3
+#define mmLB0_LB_KEYER_COLOR_B_CB                                               0x1ad3
+#define mmLB1_LB_KEYER_COLOR_B_CB                                               0x1cd3
+#define mmLB2_LB_KEYER_COLOR_B_CB                                               0x1ed3
+#define mmLB3_LB_KEYER_COLOR_B_CB                                               0x40d3
+#define mmLB4_LB_KEYER_COLOR_B_CB                                               0x42d3
+#define mmLB5_LB_KEYER_COLOR_B_CB                                               0x44d3
+#define mmLB_KEYER_COLOR_REP_R_CR                                               0x1ad4
+#define mmLB0_LB_KEYER_COLOR_REP_R_CR                                           0x1ad4
+#define mmLB1_LB_KEYER_COLOR_REP_R_CR                                           0x1cd4
+#define mmLB2_LB_KEYER_COLOR_REP_R_CR                                           0x1ed4
+#define mmLB3_LB_KEYER_COLOR_REP_R_CR                                           0x40d4
+#define mmLB4_LB_KEYER_COLOR_REP_R_CR                                           0x42d4
+#define mmLB5_LB_KEYER_COLOR_REP_R_CR                                           0x44d4
+#define mmLB_KEYER_COLOR_REP_G_Y                                                0x1ad5
+#define mmLB0_LB_KEYER_COLOR_REP_G_Y                                            0x1ad5
+#define mmLB1_LB_KEYER_COLOR_REP_G_Y                                            0x1cd5
+#define mmLB2_LB_KEYER_COLOR_REP_G_Y                                            0x1ed5
+#define mmLB3_LB_KEYER_COLOR_REP_G_Y                                            0x40d5
+#define mmLB4_LB_KEYER_COLOR_REP_G_Y                                            0x42d5
+#define mmLB5_LB_KEYER_COLOR_REP_G_Y                                            0x44d5
+#define mmLB_KEYER_COLOR_REP_B_CB                                               0x1ad6
+#define mmLB0_LB_KEYER_COLOR_REP_B_CB                                           0x1ad6
+#define mmLB1_LB_KEYER_COLOR_REP_B_CB                                           0x1cd6
+#define mmLB2_LB_KEYER_COLOR_REP_B_CB                                           0x1ed6
+#define mmLB3_LB_KEYER_COLOR_REP_B_CB                                           0x40d6
+#define mmLB4_LB_KEYER_COLOR_REP_B_CB                                           0x42d6
+#define mmLB5_LB_KEYER_COLOR_REP_B_CB                                           0x44d6
+#define mmLB_BUFFER_LEVEL_STATUS                                                0x1ad7
+#define mmLB0_LB_BUFFER_LEVEL_STATUS                                            0x1ad7
+#define mmLB1_LB_BUFFER_LEVEL_STATUS                                            0x1cd7
+#define mmLB2_LB_BUFFER_LEVEL_STATUS                                            0x1ed7
+#define mmLB3_LB_BUFFER_LEVEL_STATUS                                            0x40d7
+#define mmLB4_LB_BUFFER_LEVEL_STATUS                                            0x42d7
+#define mmLB5_LB_BUFFER_LEVEL_STATUS                                            0x44d7
+#define mmLB_BUFFER_URGENCY_CTRL                                                0x1ad8
+#define mmLB0_LB_BUFFER_URGENCY_CTRL                                            0x1ad8
+#define mmLB1_LB_BUFFER_URGENCY_CTRL                                            0x1cd8
+#define mmLB2_LB_BUFFER_URGENCY_CTRL                                            0x1ed8
+#define mmLB3_LB_BUFFER_URGENCY_CTRL                                            0x40d8
+#define mmLB4_LB_BUFFER_URGENCY_CTRL                                            0x42d8
+#define mmLB5_LB_BUFFER_URGENCY_CTRL                                            0x44d8
+#define mmLB_BUFFER_URGENCY_STATUS                                              0x1ad9
+#define mmLB0_LB_BUFFER_URGENCY_STATUS                                          0x1ad9
+#define mmLB1_LB_BUFFER_URGENCY_STATUS                                          0x1cd9
+#define mmLB2_LB_BUFFER_URGENCY_STATUS                                          0x1ed9
+#define mmLB3_LB_BUFFER_URGENCY_STATUS                                          0x40d9
+#define mmLB4_LB_BUFFER_URGENCY_STATUS                                          0x42d9
+#define mmLB5_LB_BUFFER_URGENCY_STATUS                                          0x44d9
+#define mmLB_BUFFER_STATUS                                                      0x1ada
+#define mmLB0_LB_BUFFER_STATUS                                                  0x1ada
+#define mmLB1_LB_BUFFER_STATUS                                                  0x1cda
+#define mmLB2_LB_BUFFER_STATUS                                                  0x1eda
+#define mmLB3_LB_BUFFER_STATUS                                                  0x40da
+#define mmLB4_LB_BUFFER_STATUS                                                  0x42da
+#define mmLB5_LB_BUFFER_STATUS                                                  0x44da
+#define mmLB_NO_OUTSTANDING_REQ_STATUS                                          0x1adc
+#define mmLB0_LB_NO_OUTSTANDING_REQ_STATUS                                      0x1adc
+#define mmLB1_LB_NO_OUTSTANDING_REQ_STATUS                                      0x1cdc
+#define mmLB2_LB_NO_OUTSTANDING_REQ_STATUS                                      0x1edc
+#define mmLB3_LB_NO_OUTSTANDING_REQ_STATUS                                      0x40dc
+#define mmLB4_LB_NO_OUTSTANDING_REQ_STATUS                                      0x42dc
+#define mmLB5_LB_NO_OUTSTANDING_REQ_STATUS                                      0x44dc
+#define mmMVP_AFR_FLIP_MODE                                                     0x1ae0
+#define mmLB0_MVP_AFR_FLIP_MODE                                                 0x1ae0
+#define mmLB1_MVP_AFR_FLIP_MODE                                                 0x1ce0
+#define mmLB2_MVP_AFR_FLIP_MODE                                                 0x1ee0
+#define mmLB3_MVP_AFR_FLIP_MODE                                                 0x40e0
+#define mmLB4_MVP_AFR_FLIP_MODE                                                 0x42e0
+#define mmLB5_MVP_AFR_FLIP_MODE                                                 0x44e0
+#define mmMVP_AFR_FLIP_FIFO_CNTL                                                0x1ae1
+#define mmLB0_MVP_AFR_FLIP_FIFO_CNTL                                            0x1ae1
+#define mmLB1_MVP_AFR_FLIP_FIFO_CNTL                                            0x1ce1
+#define mmLB2_MVP_AFR_FLIP_FIFO_CNTL                                            0x1ee1
+#define mmLB3_MVP_AFR_FLIP_FIFO_CNTL                                            0x40e1
+#define mmLB4_MVP_AFR_FLIP_FIFO_CNTL                                            0x42e1
+#define mmLB5_MVP_AFR_FLIP_FIFO_CNTL                                            0x44e1
+#define mmMVP_FLIP_LINE_NUM_INSERT                                              0x1ae2
+#define mmLB0_MVP_FLIP_LINE_NUM_INSERT                                          0x1ae2
+#define mmLB1_MVP_FLIP_LINE_NUM_INSERT                                          0x1ce2
+#define mmLB2_MVP_FLIP_LINE_NUM_INSERT                                          0x1ee2
+#define mmLB3_MVP_FLIP_LINE_NUM_INSERT                                          0x40e2
+#define mmLB4_MVP_FLIP_LINE_NUM_INSERT                                          0x42e2
+#define mmLB5_MVP_FLIP_LINE_NUM_INSERT                                          0x44e2
+#define mmDC_MVP_LB_CONTROL                                                     0x1ae3
+#define mmLB0_DC_MVP_LB_CONTROL                                                 0x1ae3
+#define mmLB1_DC_MVP_LB_CONTROL                                                 0x1ce3
+#define mmLB2_DC_MVP_LB_CONTROL                                                 0x1ee3
+#define mmLB3_DC_MVP_LB_CONTROL                                                 0x40e3
+#define mmLB4_DC_MVP_LB_CONTROL                                                 0x42e3
+#define mmLB5_DC_MVP_LB_CONTROL                                                 0x44e3
+#define mmLB_DEBUG                                                              0x1ae4
+#define mmLB0_LB_DEBUG                                                          0x1ae4
+#define mmLB1_LB_DEBUG                                                          0x1ce4
+#define mmLB2_LB_DEBUG                                                          0x1ee4
+#define mmLB3_LB_DEBUG                                                          0x40e4
+#define mmLB4_LB_DEBUG                                                          0x42e4
+#define mmLB5_LB_DEBUG                                                          0x44e4
+#define mmLB_DEBUG2                                                             0x1ae5
+#define mmLB0_LB_DEBUG2                                                         0x1ae5
+#define mmLB1_LB_DEBUG2                                                         0x1ce5
+#define mmLB2_LB_DEBUG2                                                         0x1ee5
+#define mmLB3_LB_DEBUG2                                                         0x40e5
+#define mmLB4_LB_DEBUG2                                                         0x42e5
+#define mmLB5_LB_DEBUG2                                                         0x44e5
+#define mmLB_DEBUG3                                                             0x1ae6
+#define mmLB0_LB_DEBUG3                                                         0x1ae6
+#define mmLB1_LB_DEBUG3                                                         0x1ce6
+#define mmLB2_LB_DEBUG3                                                         0x1ee6
+#define mmLB3_LB_DEBUG3                                                         0x40e6
+#define mmLB4_LB_DEBUG3                                                         0x42e6
+#define mmLB5_LB_DEBUG3                                                         0x44e6
+#define mmLB_TEST_DEBUG_INDEX                                                   0x1afe
+#define mmLB0_LB_TEST_DEBUG_INDEX                                               0x1afe
+#define mmLB1_LB_TEST_DEBUG_INDEX                                               0x1cfe
+#define mmLB2_LB_TEST_DEBUG_INDEX                                               0x1efe
+#define mmLB3_LB_TEST_DEBUG_INDEX                                               0x40fe
+#define mmLB4_LB_TEST_DEBUG_INDEX                                               0x42fe
+#define mmLB5_LB_TEST_DEBUG_INDEX                                               0x44fe
+#define mmLB_TEST_DEBUG_DATA                                                    0x1aff
+#define mmLB0_LB_TEST_DEBUG_DATA                                                0x1aff
+#define mmLB1_LB_TEST_DEBUG_DATA                                                0x1cff
+#define mmLB2_LB_TEST_DEBUG_DATA                                                0x1eff
+#define mmLB3_LB_TEST_DEBUG_DATA                                                0x40ff
+#define mmLB4_LB_TEST_DEBUG_DATA                                                0x42ff
+#define mmLB5_LB_TEST_DEBUG_DATA                                                0x44ff
+#define mmLBV_DATA_FORMAT                                                       0x463c
+#define mmLBV0_LBV_DATA_FORMAT                                                  0x463c
+#define mmLBV1_LBV_DATA_FORMAT                                                  0x983c
+#define mmLBV_MEMORY_CTRL                                                       0x463d
+#define mmLBV0_LBV_MEMORY_CTRL                                                  0x463d
+#define mmLBV1_LBV_MEMORY_CTRL                                                  0x983d
+#define mmLBV_MEMORY_SIZE_STATUS                                                0x463e
+#define mmLBV0_LBV_MEMORY_SIZE_STATUS                                           0x463e
+#define mmLBV1_LBV_MEMORY_SIZE_STATUS                                           0x983e
+#define mmLBV_DESKTOP_HEIGHT                                                    0x463f
+#define mmLBV0_LBV_DESKTOP_HEIGHT                                               0x463f
+#define mmLBV1_LBV_DESKTOP_HEIGHT                                               0x983f
+#define mmLBV_VLINE_START_END                                                   0x4640
+#define mmLBV0_LBV_VLINE_START_END                                              0x4640
+#define mmLBV1_LBV_VLINE_START_END                                              0x9840
+#define mmLBV_VLINE2_START_END                                                  0x4641
+#define mmLBV0_LBV_VLINE2_START_END                                             0x4641
+#define mmLBV1_LBV_VLINE2_START_END                                             0x9841
+#define mmLBV_V_COUNTER                                                         0x4642
+#define mmLBV0_LBV_V_COUNTER                                                    0x4642
+#define mmLBV1_LBV_V_COUNTER                                                    0x9842
+#define mmLBV_SNAPSHOT_V_COUNTER                                                0x4643
+#define mmLBV0_LBV_SNAPSHOT_V_COUNTER                                           0x4643
+#define mmLBV1_LBV_SNAPSHOT_V_COUNTER                                           0x9843
+#define mmLBV_V_COUNTER_CHROMA                                                  0x4644
+#define mmLBV0_LBV_V_COUNTER_CHROMA                                             0x4644
+#define mmLBV1_LBV_V_COUNTER_CHROMA                                             0x9844
+#define mmLBV_SNAPSHOT_V_COUNTER_CHROMA                                         0x4645
+#define mmLBV0_LBV_SNAPSHOT_V_COUNTER_CHROMA                                    0x4645
+#define mmLBV1_LBV_SNAPSHOT_V_COUNTER_CHROMA                                    0x9845
+#define mmLBV_INTERRUPT_MASK                                                    0x4646
+#define mmLBV0_LBV_INTERRUPT_MASK                                               0x4646
+#define mmLBV1_LBV_INTERRUPT_MASK                                               0x9846
+#define mmLBV_VLINE_STATUS                                                      0x4647
+#define mmLBV0_LBV_VLINE_STATUS                                                 0x4647
+#define mmLBV1_LBV_VLINE_STATUS                                                 0x9847
+#define mmLBV_VLINE2_STATUS                                                     0x4648
+#define mmLBV0_LBV_VLINE2_STATUS                                                0x4648
+#define mmLBV1_LBV_VLINE2_STATUS                                                0x9848
+#define mmLBV_VBLANK_STATUS                                                     0x4649
+#define mmLBV0_LBV_VBLANK_STATUS                                                0x4649
+#define mmLBV1_LBV_VBLANK_STATUS                                                0x9849
+#define mmLBV_SYNC_RESET_SEL                                                    0x464a
+#define mmLBV0_LBV_SYNC_RESET_SEL                                               0x464a
+#define mmLBV1_LBV_SYNC_RESET_SEL                                               0x984a
+#define mmLBV_BLACK_KEYER_R_CR                                                  0x464b
+#define mmLBV0_LBV_BLACK_KEYER_R_CR                                             0x464b
+#define mmLBV1_LBV_BLACK_KEYER_R_CR                                             0x984b
+#define mmLBV_BLACK_KEYER_G_Y                                                   0x464c
+#define mmLBV0_LBV_BLACK_KEYER_G_Y                                              0x464c
+#define mmLBV1_LBV_BLACK_KEYER_G_Y                                              0x984c
+#define mmLBV_BLACK_KEYER_B_CB                                                  0x464d
+#define mmLBV0_LBV_BLACK_KEYER_B_CB                                             0x464d
+#define mmLBV1_LBV_BLACK_KEYER_B_CB                                             0x984d
+#define mmLBV_KEYER_COLOR_CTRL                                                  0x464e
+#define mmLBV0_LBV_KEYER_COLOR_CTRL                                             0x464e
+#define mmLBV1_LBV_KEYER_COLOR_CTRL                                             0x984e
+#define mmLBV_KEYER_COLOR_R_CR                                                  0x464f
+#define mmLBV0_LBV_KEYER_COLOR_R_CR                                             0x464f
+#define mmLBV1_LBV_KEYER_COLOR_R_CR                                             0x984f
+#define mmLBV_KEYER_COLOR_G_Y                                                   0x4650
+#define mmLBV0_LBV_KEYER_COLOR_G_Y                                              0x4650
+#define mmLBV1_LBV_KEYER_COLOR_G_Y                                              0x9850
+#define mmLBV_KEYER_COLOR_B_CB                                                  0x4651
+#define mmLBV0_LBV_KEYER_COLOR_B_CB                                             0x4651
+#define mmLBV1_LBV_KEYER_COLOR_B_CB                                             0x9851
+#define mmLBV_KEYER_COLOR_REP_R_CR                                              0x4652
+#define mmLBV0_LBV_KEYER_COLOR_REP_R_CR                                         0x4652
+#define mmLBV1_LBV_KEYER_COLOR_REP_R_CR                                         0x9852
+#define mmLBV_KEYER_COLOR_REP_G_Y                                               0x4653
+#define mmLBV0_LBV_KEYER_COLOR_REP_G_Y                                          0x4653
+#define mmLBV1_LBV_KEYER_COLOR_REP_G_Y                                          0x9853
+#define mmLBV_KEYER_COLOR_REP_B_CB                                              0x4654
+#define mmLBV0_LBV_KEYER_COLOR_REP_B_CB                                         0x4654
+#define mmLBV1_LBV_KEYER_COLOR_REP_B_CB                                         0x9854
+#define mmLBV_BUFFER_LEVEL_STATUS                                               0x4655
+#define mmLBV0_LBV_BUFFER_LEVEL_STATUS                                          0x4655
+#define mmLBV1_LBV_BUFFER_LEVEL_STATUS                                          0x9855
+#define mmLBV_BUFFER_URGENCY_CTRL                                               0x4656
+#define mmLBV0_LBV_BUFFER_URGENCY_CTRL                                          0x4656
+#define mmLBV1_LBV_BUFFER_URGENCY_CTRL                                          0x9856
+#define mmLBV_BUFFER_URGENCY_STATUS                                             0x4657
+#define mmLBV0_LBV_BUFFER_URGENCY_STATUS                                        0x4657
+#define mmLBV1_LBV_BUFFER_URGENCY_STATUS                                        0x9857
+#define mmLBV_BUFFER_STATUS                                                     0x4658
+#define mmLBV0_LBV_BUFFER_STATUS                                                0x4658
+#define mmLBV1_LBV_BUFFER_STATUS                                                0x9858
+#define mmLBV_NO_OUTSTANDING_REQ_STATUS                                         0x4659
+#define mmLBV0_LBV_NO_OUTSTANDING_REQ_STATUS                                    0x4659
+#define mmLBV1_LBV_NO_OUTSTANDING_REQ_STATUS                                    0x9859
+#define mmLBV_DEBUG                                                             0x465a
+#define mmLBV0_LBV_DEBUG                                                        0x465a
+#define mmLBV1_LBV_DEBUG                                                        0x985a
+#define mmLBV_DEBUG2                                                            0x465b
+#define mmLBV0_LBV_DEBUG2                                                       0x465b
+#define mmLBV1_LBV_DEBUG2                                                       0x985b
+#define mmLBV_DEBUG3                                                            0x465c
+#define mmLBV0_LBV_DEBUG3                                                       0x465c
+#define mmLBV1_LBV_DEBUG3                                                       0x985c
+#define mmLBV_TEST_DEBUG_INDEX                                                  0x4666
+#define mmLBV0_LBV_TEST_DEBUG_INDEX                                             0x4666
+#define mmLBV1_LBV_TEST_DEBUG_INDEX                                             0x9866
+#define mmLBV_TEST_DEBUG_DATA                                                   0x4667
+#define mmLBV0_LBV_TEST_DEBUG_DATA                                              0x4667
+#define mmLBV1_LBV_TEST_DEBUG_DATA                                              0x9867
+#define mmMVP_CONTROL1                                                          0x2ac
+#define mmMVP_CONTROL2                                                          0x2ad
+#define mmMVP_FIFO_CONTROL                                                      0x2ae
+#define mmMVP_FIFO_STATUS                                                       0x2af
+#define mmMVP_SLAVE_STATUS                                                      0x2b0
+#define mmMVP_INBAND_CNTL_CAP                                                   0x2b1
+#define mmMVP_BLACK_KEYER                                                       0x2b2
+#define mmMVP_CRC_CNTL                                                          0x2b3
+#define mmMVP_CRC_RESULT_BLUE_GREEN                                             0x2b4
+#define mmMVP_CRC_RESULT_RED                                                    0x2b5
+#define mmMVP_CONTROL3                                                          0x2b6
+#define mmMVP_RECEIVE_CNT_CNTL1                                                 0x2b7
+#define mmMVP_RECEIVE_CNT_CNTL2                                                 0x2b8
+#define mmMVP_DEBUG                                                             0x2bb
+#define mmMVP_TEST_DEBUG_INDEX                                                  0x2b9
+#define mmMVP_TEST_DEBUG_DATA                                                   0x2ba
+#define ixMVP_DEBUG_12                                                          0xc
+#define ixMVP_DEBUG_13                                                          0xd
+#define ixMVP_DEBUG_14                                                          0xe
+#define ixMVP_DEBUG_15                                                          0xf
+#define ixMVP_DEBUG_16                                                          0x10
+#define ixMVP_DEBUG_17                                                          0x11
+#define mmSCL_COEF_RAM_SELECT                                                   0x1b40
+#define mmSCL0_SCL_COEF_RAM_SELECT                                              0x1b40
+#define mmSCL1_SCL_COEF_RAM_SELECT                                              0x1d40
+#define mmSCL2_SCL_COEF_RAM_SELECT                                              0x1f40
+#define mmSCL3_SCL_COEF_RAM_SELECT                                              0x4140
+#define mmSCL4_SCL_COEF_RAM_SELECT                                              0x4340
+#define mmSCL5_SCL_COEF_RAM_SELECT                                              0x4540
+#define mmSCL_COEF_RAM_TAP_DATA                                                 0x1b41
+#define mmSCL0_SCL_COEF_RAM_TAP_DATA                                            0x1b41
+#define mmSCL1_SCL_COEF_RAM_TAP_DATA                                            0x1d41
+#define mmSCL2_SCL_COEF_RAM_TAP_DATA                                            0x1f41
+#define mmSCL3_SCL_COEF_RAM_TAP_DATA                                            0x4141
+#define mmSCL4_SCL_COEF_RAM_TAP_DATA                                            0x4341
+#define mmSCL5_SCL_COEF_RAM_TAP_DATA                                            0x4541
+#define mmSCL_MODE                                                              0x1b42
+#define mmSCL0_SCL_MODE                                                         0x1b42
+#define mmSCL1_SCL_MODE                                                         0x1d42
+#define mmSCL2_SCL_MODE                                                         0x1f42
+#define mmSCL3_SCL_MODE                                                         0x4142
+#define mmSCL4_SCL_MODE                                                         0x4342
+#define mmSCL5_SCL_MODE                                                         0x4542
+#define mmSCL_TAP_CONTROL                                                       0x1b43
+#define mmSCL0_SCL_TAP_CONTROL                                                  0x1b43
+#define mmSCL1_SCL_TAP_CONTROL                                                  0x1d43
+#define mmSCL2_SCL_TAP_CONTROL                                                  0x1f43
+#define mmSCL3_SCL_TAP_CONTROL                                                  0x4143
+#define mmSCL4_SCL_TAP_CONTROL                                                  0x4343
+#define mmSCL5_SCL_TAP_CONTROL                                                  0x4543
+#define mmSCL_CONTROL                                                           0x1b44
+#define mmSCL0_SCL_CONTROL                                                      0x1b44
+#define mmSCL1_SCL_CONTROL                                                      0x1d44
+#define mmSCL2_SCL_CONTROL                                                      0x1f44
+#define mmSCL3_SCL_CONTROL                                                      0x4144
+#define mmSCL4_SCL_CONTROL                                                      0x4344
+#define mmSCL5_SCL_CONTROL                                                      0x4544
+#define mmSCL_BYPASS_CONTROL                                                    0x1b45
+#define mmSCL0_SCL_BYPASS_CONTROL                                               0x1b45
+#define mmSCL1_SCL_BYPASS_CONTROL                                               0x1d45
+#define mmSCL2_SCL_BYPASS_CONTROL                                               0x1f45
+#define mmSCL3_SCL_BYPASS_CONTROL                                               0x4145
+#define mmSCL4_SCL_BYPASS_CONTROL                                               0x4345
+#define mmSCL5_SCL_BYPASS_CONTROL                                               0x4545
+#define mmSCL_MANUAL_REPLICATE_CONTROL                                          0x1b46
+#define mmSCL0_SCL_MANUAL_REPLICATE_CONTROL                                     0x1b46
+#define mmSCL1_SCL_MANUAL_REPLICATE_CONTROL                                     0x1d46
+#define mmSCL2_SCL_MANUAL_REPLICATE_CONTROL                                     0x1f46
+#define mmSCL3_SCL_MANUAL_REPLICATE_CONTROL                                     0x4146
+#define mmSCL4_SCL_MANUAL_REPLICATE_CONTROL                                     0x4346
+#define mmSCL5_SCL_MANUAL_REPLICATE_CONTROL                                     0x4546
+#define mmSCL_AUTOMATIC_MODE_CONTROL                                            0x1b47
+#define mmSCL0_SCL_AUTOMATIC_MODE_CONTROL                                       0x1b47
+#define mmSCL1_SCL_AUTOMATIC_MODE_CONTROL                                       0x1d47
+#define mmSCL2_SCL_AUTOMATIC_MODE_CONTROL                                       0x1f47
+#define mmSCL3_SCL_AUTOMATIC_MODE_CONTROL                                       0x4147
+#define mmSCL4_SCL_AUTOMATIC_MODE_CONTROL                                       0x4347
+#define mmSCL5_SCL_AUTOMATIC_MODE_CONTROL                                       0x4547
+#define mmSCL_HORZ_FILTER_CONTROL                                               0x1b48
+#define mmSCL0_SCL_HORZ_FILTER_CONTROL                                          0x1b48
+#define mmSCL1_SCL_HORZ_FILTER_CONTROL                                          0x1d48
+#define mmSCL2_SCL_HORZ_FILTER_CONTROL                                          0x1f48
+#define mmSCL3_SCL_HORZ_FILTER_CONTROL                                          0x4148
+#define mmSCL4_SCL_HORZ_FILTER_CONTROL                                          0x4348
+#define mmSCL5_SCL_HORZ_FILTER_CONTROL                                          0x4548
+#define mmSCL_HORZ_FILTER_SCALE_RATIO                                           0x1b49
+#define mmSCL0_SCL_HORZ_FILTER_SCALE_RATIO                                      0x1b49
+#define mmSCL1_SCL_HORZ_FILTER_SCALE_RATIO                                      0x1d49
+#define mmSCL2_SCL_HORZ_FILTER_SCALE_RATIO                                      0x1f49
+#define mmSCL3_SCL_HORZ_FILTER_SCALE_RATIO                                      0x4149
+#define mmSCL4_SCL_HORZ_FILTER_SCALE_RATIO                                      0x4349
+#define mmSCL5_SCL_HORZ_FILTER_SCALE_RATIO                                      0x4549
+#define mmSCL_HORZ_FILTER_INIT                                                  0x1b4a
+#define mmSCL0_SCL_HORZ_FILTER_INIT                                             0x1b4a
+#define mmSCL1_SCL_HORZ_FILTER_INIT                                             0x1d4a
+#define mmSCL2_SCL_HORZ_FILTER_INIT                                             0x1f4a
+#define mmSCL3_SCL_HORZ_FILTER_INIT                                             0x414a
+#define mmSCL4_SCL_HORZ_FILTER_INIT                                             0x434a
+#define mmSCL5_SCL_HORZ_FILTER_INIT                                             0x454a
+#define mmSCL_VERT_FILTER_CONTROL                                               0x1b4b
+#define mmSCL0_SCL_VERT_FILTER_CONTROL                                          0x1b4b
+#define mmSCL1_SCL_VERT_FILTER_CONTROL                                          0x1d4b
+#define mmSCL2_SCL_VERT_FILTER_CONTROL                                          0x1f4b
+#define mmSCL3_SCL_VERT_FILTER_CONTROL                                          0x414b
+#define mmSCL4_SCL_VERT_FILTER_CONTROL                                          0x434b
+#define mmSCL5_SCL_VERT_FILTER_CONTROL                                          0x454b
+#define mmSCL_VERT_FILTER_SCALE_RATIO                                           0x1b4c
+#define mmSCL0_SCL_VERT_FILTER_SCALE_RATIO                                      0x1b4c
+#define mmSCL1_SCL_VERT_FILTER_SCALE_RATIO                                      0x1d4c
+#define mmSCL2_SCL_VERT_FILTER_SCALE_RATIO                                      0x1f4c
+#define mmSCL3_SCL_VERT_FILTER_SCALE_RATIO                                      0x414c
+#define mmSCL4_SCL_VERT_FILTER_SCALE_RATIO                                      0x434c
+#define mmSCL5_SCL_VERT_FILTER_SCALE_RATIO                                      0x454c
+#define mmSCL_VERT_FILTER_INIT                                                  0x1b4d
+#define mmSCL0_SCL_VERT_FILTER_INIT                                             0x1b4d
+#define mmSCL1_SCL_VERT_FILTER_INIT                                             0x1d4d
+#define mmSCL2_SCL_VERT_FILTER_INIT                                             0x1f4d
+#define mmSCL3_SCL_VERT_FILTER_INIT                                             0x414d
+#define mmSCL4_SCL_VERT_FILTER_INIT                                             0x434d
+#define mmSCL5_SCL_VERT_FILTER_INIT                                             0x454d
+#define mmSCL_VERT_FILTER_INIT_BOT                                              0x1b4e
+#define mmSCL0_SCL_VERT_FILTER_INIT_BOT                                         0x1b4e
+#define mmSCL1_SCL_VERT_FILTER_INIT_BOT                                         0x1d4e
+#define mmSCL2_SCL_VERT_FILTER_INIT_BOT                                         0x1f4e
+#define mmSCL3_SCL_VERT_FILTER_INIT_BOT                                         0x414e
+#define mmSCL4_SCL_VERT_FILTER_INIT_BOT                                         0x434e
+#define mmSCL5_SCL_VERT_FILTER_INIT_BOT                                         0x454e
+#define mmSCL_ROUND_OFFSET                                                      0x1b4f
+#define mmSCL0_SCL_ROUND_OFFSET                                                 0x1b4f
+#define mmSCL1_SCL_ROUND_OFFSET                                                 0x1d4f
+#define mmSCL2_SCL_ROUND_OFFSET                                                 0x1f4f
+#define mmSCL3_SCL_ROUND_OFFSET                                                 0x414f
+#define mmSCL4_SCL_ROUND_OFFSET                                                 0x434f
+#define mmSCL5_SCL_ROUND_OFFSET                                                 0x454f
+#define mmSCL_UPDATE                                                            0x1b51
+#define mmSCL0_SCL_UPDATE                                                       0x1b51
+#define mmSCL1_SCL_UPDATE                                                       0x1d51
+#define mmSCL2_SCL_UPDATE                                                       0x1f51
+#define mmSCL3_SCL_UPDATE                                                       0x4151
+#define mmSCL4_SCL_UPDATE                                                       0x4351
+#define mmSCL5_SCL_UPDATE                                                       0x4551
+#define mmSCL_F_SHARP_CONTROL                                                   0x1b53
+#define mmSCL0_SCL_F_SHARP_CONTROL                                              0x1b53
+#define mmSCL1_SCL_F_SHARP_CONTROL                                              0x1d53
+#define mmSCL2_SCL_F_SHARP_CONTROL                                              0x1f53
+#define mmSCL3_SCL_F_SHARP_CONTROL                                              0x4153
+#define mmSCL4_SCL_F_SHARP_CONTROL                                              0x4353
+#define mmSCL5_SCL_F_SHARP_CONTROL                                              0x4553
+#define mmSCL_ALU_CONTROL                                                       0x1b54
+#define mmSCL0_SCL_ALU_CONTROL                                                  0x1b54
+#define mmSCL1_SCL_ALU_CONTROL                                                  0x1d54
+#define mmSCL2_SCL_ALU_CONTROL                                                  0x1f54
+#define mmSCL3_SCL_ALU_CONTROL                                                  0x4154
+#define mmSCL4_SCL_ALU_CONTROL                                                  0x4354
+#define mmSCL5_SCL_ALU_CONTROL                                                  0x4554
+#define mmSCL_COEF_RAM_CONFLICT_STATUS                                          0x1b55
+#define mmSCL0_SCL_COEF_RAM_CONFLICT_STATUS                                     0x1b55
+#define mmSCL1_SCL_COEF_RAM_CONFLICT_STATUS                                     0x1d55
+#define mmSCL2_SCL_COEF_RAM_CONFLICT_STATUS                                     0x1f55
+#define mmSCL3_SCL_COEF_RAM_CONFLICT_STATUS                                     0x4155
+#define mmSCL4_SCL_COEF_RAM_CONFLICT_STATUS                                     0x4355
+#define mmSCL5_SCL_COEF_RAM_CONFLICT_STATUS                                     0x4555
+#define mmVIEWPORT_START_SECONDARY                                              0x1b5b
+#define mmSCL0_VIEWPORT_START_SECONDARY                                         0x1b5b
+#define mmSCL1_VIEWPORT_START_SECONDARY                                         0x1d5b
+#define mmSCL2_VIEWPORT_START_SECONDARY                                         0x1f5b
+#define mmSCL3_VIEWPORT_START_SECONDARY                                         0x415b
+#define mmSCL4_VIEWPORT_START_SECONDARY                                         0x435b
+#define mmSCL5_VIEWPORT_START_SECONDARY                                         0x455b
+#define mmVIEWPORT_START                                                        0x1b5c
+#define mmSCL0_VIEWPORT_START                                                   0x1b5c
+#define mmSCL1_VIEWPORT_START                                                   0x1d5c
+#define mmSCL2_VIEWPORT_START                                                   0x1f5c
+#define mmSCL3_VIEWPORT_START                                                   0x415c
+#define mmSCL4_VIEWPORT_START                                                   0x435c
+#define mmSCL5_VIEWPORT_START                                                   0x455c
+#define mmVIEWPORT_SIZE                                                         0x1b5d
+#define mmSCL0_VIEWPORT_SIZE                                                    0x1b5d
+#define mmSCL1_VIEWPORT_SIZE                                                    0x1d5d
+#define mmSCL2_VIEWPORT_SIZE                                                    0x1f5d
+#define mmSCL3_VIEWPORT_SIZE                                                    0x415d
+#define mmSCL4_VIEWPORT_SIZE                                                    0x435d
+#define mmSCL5_VIEWPORT_SIZE                                                    0x455d
+#define mmEXT_OVERSCAN_LEFT_RIGHT                                               0x1b5e
+#define mmSCL0_EXT_OVERSCAN_LEFT_RIGHT                                          0x1b5e
+#define mmSCL1_EXT_OVERSCAN_LEFT_RIGHT                                          0x1d5e
+#define mmSCL2_EXT_OVERSCAN_LEFT_RIGHT                                          0x1f5e
+#define mmSCL3_EXT_OVERSCAN_LEFT_RIGHT                                          0x415e
+#define mmSCL4_EXT_OVERSCAN_LEFT_RIGHT                                          0x435e
+#define mmSCL5_EXT_OVERSCAN_LEFT_RIGHT                                          0x455e
+#define mmEXT_OVERSCAN_TOP_BOTTOM                                               0x1b5f
+#define mmSCL0_EXT_OVERSCAN_TOP_BOTTOM                                          0x1b5f
+#define mmSCL1_EXT_OVERSCAN_TOP_BOTTOM                                          0x1d5f
+#define mmSCL2_EXT_OVERSCAN_TOP_BOTTOM                                          0x1f5f
+#define mmSCL3_EXT_OVERSCAN_TOP_BOTTOM                                          0x415f
+#define mmSCL4_EXT_OVERSCAN_TOP_BOTTOM                                          0x435f
+#define mmSCL5_EXT_OVERSCAN_TOP_BOTTOM                                          0x455f
+#define mmSCL_MODE_CHANGE_DET1                                                  0x1b60
+#define mmSCL0_SCL_MODE_CHANGE_DET1                                             0x1b60
+#define mmSCL1_SCL_MODE_CHANGE_DET1                                             0x1d60
+#define mmSCL2_SCL_MODE_CHANGE_DET1                                             0x1f60
+#define mmSCL3_SCL_MODE_CHANGE_DET1                                             0x4160
+#define mmSCL4_SCL_MODE_CHANGE_DET1                                             0x4360
+#define mmSCL5_SCL_MODE_CHANGE_DET1                                             0x4560
+#define mmSCL_MODE_CHANGE_DET2                                                  0x1b61
+#define mmSCL0_SCL_MODE_CHANGE_DET2                                             0x1b61
+#define mmSCL1_SCL_MODE_CHANGE_DET2                                             0x1d61
+#define mmSCL2_SCL_MODE_CHANGE_DET2                                             0x1f61
+#define mmSCL3_SCL_MODE_CHANGE_DET2                                             0x4161
+#define mmSCL4_SCL_MODE_CHANGE_DET2                                             0x4361
+#define mmSCL5_SCL_MODE_CHANGE_DET2                                             0x4561
+#define mmSCL_MODE_CHANGE_DET3                                                  0x1b62
+#define mmSCL0_SCL_MODE_CHANGE_DET3                                             0x1b62
+#define mmSCL1_SCL_MODE_CHANGE_DET3                                             0x1d62
+#define mmSCL2_SCL_MODE_CHANGE_DET3                                             0x1f62
+#define mmSCL3_SCL_MODE_CHANGE_DET3                                             0x4162
+#define mmSCL4_SCL_MODE_CHANGE_DET3                                             0x4362
+#define mmSCL5_SCL_MODE_CHANGE_DET3                                             0x4562
+#define mmSCL_MODE_CHANGE_MASK                                                  0x1b63
+#define mmSCL0_SCL_MODE_CHANGE_MASK                                             0x1b63
+#define mmSCL1_SCL_MODE_CHANGE_MASK                                             0x1d63
+#define mmSCL2_SCL_MODE_CHANGE_MASK                                             0x1f63
+#define mmSCL3_SCL_MODE_CHANGE_MASK                                             0x4163
+#define mmSCL4_SCL_MODE_CHANGE_MASK                                             0x4363
+#define mmSCL5_SCL_MODE_CHANGE_MASK                                             0x4563
+#define mmSCL_DEBUG2                                                            0x1b69
+#define mmSCL0_SCL_DEBUG2                                                       0x1b69
+#define mmSCL1_SCL_DEBUG2                                                       0x1d69
+#define mmSCL2_SCL_DEBUG2                                                       0x1f69
+#define mmSCL3_SCL_DEBUG2                                                       0x4169
+#define mmSCL4_SCL_DEBUG2                                                       0x4369
+#define mmSCL5_SCL_DEBUG2                                                       0x4569
+#define mmSCL_DEBUG                                                             0x1b6a
+#define mmSCL0_SCL_DEBUG                                                        0x1b6a
+#define mmSCL1_SCL_DEBUG                                                        0x1d6a
+#define mmSCL2_SCL_DEBUG                                                        0x1f6a
+#define mmSCL3_SCL_DEBUG                                                        0x416a
+#define mmSCL4_SCL_DEBUG                                                        0x436a
+#define mmSCL5_SCL_DEBUG                                                        0x456a
+#define mmSCL_TEST_DEBUG_INDEX                                                  0x1b6b
+#define mmSCL0_SCL_TEST_DEBUG_INDEX                                             0x1b6b
+#define mmSCL1_SCL_TEST_DEBUG_INDEX                                             0x1d6b
+#define mmSCL2_SCL_TEST_DEBUG_INDEX                                             0x1f6b
+#define mmSCL3_SCL_TEST_DEBUG_INDEX                                             0x416b
+#define mmSCL4_SCL_TEST_DEBUG_INDEX                                             0x436b
+#define mmSCL5_SCL_TEST_DEBUG_INDEX                                             0x456b
+#define mmSCL_TEST_DEBUG_DATA                                                   0x1b6c
+#define mmSCL0_SCL_TEST_DEBUG_DATA                                              0x1b6c
+#define mmSCL1_SCL_TEST_DEBUG_DATA                                              0x1d6c
+#define mmSCL2_SCL_TEST_DEBUG_DATA                                              0x1f6c
+#define mmSCL3_SCL_TEST_DEBUG_DATA                                              0x416c
+#define mmSCL4_SCL_TEST_DEBUG_DATA                                              0x436c
+#define mmSCL5_SCL_TEST_DEBUG_DATA                                              0x456c
+#define mmSCLV_COEF_RAM_SELECT                                                  0x4670
+#define mmSCLV0_SCLV_COEF_RAM_SELECT                                            0x4670
+#define mmSCLV1_SCLV_COEF_RAM_SELECT                                            0x9870
+#define mmSCLV_COEF_RAM_TAP_DATA                                                0x4671
+#define mmSCLV0_SCLV_COEF_RAM_TAP_DATA                                          0x4671
+#define mmSCLV1_SCLV_COEF_RAM_TAP_DATA                                          0x9871
+#define mmSCLV_MODE                                                             0x4672
+#define mmSCLV0_SCLV_MODE                                                       0x4672
+#define mmSCLV1_SCLV_MODE                                                       0x9872
+#define mmSCLV_TAP_CONTROL                                                      0x4673
+#define mmSCLV0_SCLV_TAP_CONTROL                                                0x4673
+#define mmSCLV1_SCLV_TAP_CONTROL                                                0x9873
+#define mmSCLV_CONTROL                                                          0x4674
+#define mmSCLV0_SCLV_CONTROL                                                    0x4674
+#define mmSCLV1_SCLV_CONTROL                                                    0x9874
+#define mmSCLV_MANUAL_REPLICATE_CONTROL                                         0x4675
+#define mmSCLV0_SCLV_MANUAL_REPLICATE_CONTROL                                   0x4675
+#define mmSCLV1_SCLV_MANUAL_REPLICATE_CONTROL                                   0x9875
+#define mmSCLV_AUTOMATIC_MODE_CONTROL                                           0x4676
+#define mmSCLV0_SCLV_AUTOMATIC_MODE_CONTROL                                     0x4676
+#define mmSCLV1_SCLV_AUTOMATIC_MODE_CONTROL                                     0x9876
+#define mmSCLV_HORZ_FILTER_CONTROL                                              0x4677
+#define mmSCLV0_SCLV_HORZ_FILTER_CONTROL                                        0x4677
+#define mmSCLV1_SCLV_HORZ_FILTER_CONTROL                                        0x9877
+#define mmSCLV_HORZ_FILTER_SCALE_RATIO                                          0x4678
+#define mmSCLV0_SCLV_HORZ_FILTER_SCALE_RATIO                                    0x4678
+#define mmSCLV1_SCLV_HORZ_FILTER_SCALE_RATIO                                    0x9878
+#define mmSCLV_HORZ_FILTER_INIT                                                 0x4679
+#define mmSCLV0_SCLV_HORZ_FILTER_INIT                                           0x4679
+#define mmSCLV1_SCLV_HORZ_FILTER_INIT                                           0x9879
+#define mmSCLV_HORZ_FILTER_SCALE_RATIO_C                                        0x467a
+#define mmSCLV0_SCLV_HORZ_FILTER_SCALE_RATIO_C                                  0x467a
+#define mmSCLV1_SCLV_HORZ_FILTER_SCALE_RATIO_C                                  0x987a
+#define mmSCLV_HORZ_FILTER_INIT_C                                               0x467b
+#define mmSCLV0_SCLV_HORZ_FILTER_INIT_C                                         0x467b
+#define mmSCLV1_SCLV_HORZ_FILTER_INIT_C                                         0x987b
+#define mmSCLV_VERT_FILTER_CONTROL                                              0x467c
+#define mmSCLV0_SCLV_VERT_FILTER_CONTROL                                        0x467c
+#define mmSCLV1_SCLV_VERT_FILTER_CONTROL                                        0x987c
+#define mmSCLV_VERT_FILTER_SCALE_RATIO                                          0x467d
+#define mmSCLV0_SCLV_VERT_FILTER_SCALE_RATIO                                    0x467d
+#define mmSCLV1_SCLV_VERT_FILTER_SCALE_RATIO                                    0x987d
+#define mmSCLV_VERT_FILTER_INIT                                                 0x467e
+#define mmSCLV0_SCLV_VERT_FILTER_INIT                                           0x467e
+#define mmSCLV1_SCLV_VERT_FILTER_INIT                                           0x987e
+#define mmSCLV_VERT_FILTER_INIT_BOT                                             0x467f
+#define mmSCLV0_SCLV_VERT_FILTER_INIT_BOT                                       0x467f
+#define mmSCLV1_SCLV_VERT_FILTER_INIT_BOT                                       0x987f
+#define mmSCLV_VERT_FILTER_SCALE_RATIO_C                                        0x4680
+#define mmSCLV0_SCLV_VERT_FILTER_SCALE_RATIO_C                                  0x4680
+#define mmSCLV1_SCLV_VERT_FILTER_SCALE_RATIO_C                                  0x9880
+#define mmSCLV_VERT_FILTER_INIT_C                                               0x4681
+#define mmSCLV0_SCLV_VERT_FILTER_INIT_C                                         0x4681
+#define mmSCLV1_SCLV_VERT_FILTER_INIT_C                                         0x9881
+#define mmSCLV_VERT_FILTER_INIT_BOT_C                                           0x4682
+#define mmSCLV0_SCLV_VERT_FILTER_INIT_BOT_C                                     0x4682
+#define mmSCLV1_SCLV_VERT_FILTER_INIT_BOT_C                                     0x9882
+#define mmSCLV_ROUND_OFFSET                                                     0x4683
+#define mmSCLV0_SCLV_ROUND_OFFSET                                               0x4683
+#define mmSCLV1_SCLV_ROUND_OFFSET                                               0x9883
+#define mmSCLV_UPDATE                                                           0x4684
+#define mmSCLV0_SCLV_UPDATE                                                     0x4684
+#define mmSCLV1_SCLV_UPDATE                                                     0x9884
+#define mmSCLV_ALU_CONTROL                                                      0x4685
+#define mmSCLV0_SCLV_ALU_CONTROL                                                0x4685
+#define mmSCLV1_SCLV_ALU_CONTROL                                                0x9885
+#define mmSCLV_VIEWPORT_START                                                   0x4686
+#define mmSCLV0_SCLV_VIEWPORT_START                                             0x4686
+#define mmSCLV1_SCLV_VIEWPORT_START                                             0x9886
+#define mmSCLV_VIEWPORT_START_SECONDARY                                         0x4687
+#define mmSCLV0_SCLV_VIEWPORT_START_SECONDARY                                   0x4687
+#define mmSCLV1_SCLV_VIEWPORT_START_SECONDARY                                   0x9887
+#define mmSCLV_VIEWPORT_SIZE                                                    0x4688
+#define mmSCLV0_SCLV_VIEWPORT_SIZE                                              0x4688
+#define mmSCLV1_SCLV_VIEWPORT_SIZE                                              0x9888
+#define mmSCLV_VIEWPORT_START_C                                                 0x4689
+#define mmSCLV0_SCLV_VIEWPORT_START_C                                           0x4689
+#define mmSCLV1_SCLV_VIEWPORT_START_C                                           0x9889
+#define mmSCLV_VIEWPORT_START_SECONDARY_C                                       0x468a
+#define mmSCLV0_SCLV_VIEWPORT_START_SECONDARY_C                                 0x468a
+#define mmSCLV1_SCLV_VIEWPORT_START_SECONDARY_C                                 0x988a
+#define mmSCLV_VIEWPORT_SIZE_C                                                  0x468b
+#define mmSCLV0_SCLV_VIEWPORT_SIZE_C                                            0x468b
+#define mmSCLV1_SCLV_VIEWPORT_SIZE_C                                            0x988b
+#define mmSCLV_EXT_OVERSCAN_LEFT_RIGHT                                          0x468c
+#define mmSCLV0_SCLV_EXT_OVERSCAN_LEFT_RIGHT                                    0x468c
+#define mmSCLV1_SCLV_EXT_OVERSCAN_LEFT_RIGHT                                    0x988c
+#define mmSCLV_EXT_OVERSCAN_TOP_BOTTOM                                          0x468d
+#define mmSCLV0_SCLV_EXT_OVERSCAN_TOP_BOTTOM                                    0x468d
+#define mmSCLV1_SCLV_EXT_OVERSCAN_TOP_BOTTOM                                    0x988d
+#define mmSCLV_MODE_CHANGE_DET1                                                 0x468e
+#define mmSCLV0_SCLV_MODE_CHANGE_DET1                                           0x468e
+#define mmSCLV1_SCLV_MODE_CHANGE_DET1                                           0x988e
+#define mmSCLV_MODE_CHANGE_DET2                                                 0x468f
+#define mmSCLV0_SCLV_MODE_CHANGE_DET2                                           0x468f
+#define mmSCLV1_SCLV_MODE_CHANGE_DET2                                           0x988f
+#define mmSCLV_MODE_CHANGE_DET3                                                 0x4690
+#define mmSCLV0_SCLV_MODE_CHANGE_DET3                                           0x4690
+#define mmSCLV1_SCLV_MODE_CHANGE_DET3                                           0x9890
+#define mmSCLV_MODE_CHANGE_MASK                                                 0x4691
+#define mmSCLV0_SCLV_MODE_CHANGE_MASK                                           0x4691
+#define mmSCLV1_SCLV_MODE_CHANGE_MASK                                           0x9891
+#define mmSCLV_HORZ_FILTER_INIT_BOT                                             0x4692
+#define mmSCLV0_SCLV_HORZ_FILTER_INIT_BOT                                       0x4692
+#define mmSCLV1_SCLV_HORZ_FILTER_INIT_BOT                                       0x9892
+#define mmSCLV_HORZ_FILTER_INIT_BOT_C                                           0x4693
+#define mmSCLV0_SCLV_HORZ_FILTER_INIT_BOT_C                                     0x4693
+#define mmSCLV1_SCLV_HORZ_FILTER_INIT_BOT_C                                     0x9893
+#define mmSCLV_DEBUG2                                                           0x4694
+#define mmSCLV0_SCLV_DEBUG2                                                     0x4694
+#define mmSCLV1_SCLV_DEBUG2                                                     0x9894
+#define mmSCLV_DEBUG                                                            0x4695
+#define mmSCLV0_SCLV_DEBUG                                                      0x4695
+#define mmSCLV1_SCLV_DEBUG                                                      0x9895
+#define mmSCLV_TEST_DEBUG_INDEX                                                 0x4696
+#define mmSCLV0_SCLV_TEST_DEBUG_INDEX                                           0x4696
+#define mmSCLV1_SCLV_TEST_DEBUG_INDEX                                           0x9896
+#define mmSCLV_TEST_DEBUG_DATA                                                  0x4697
+#define mmSCLV0_SCLV_TEST_DEBUG_DATA                                            0x4697
+#define mmSCLV1_SCLV_TEST_DEBUG_DATA                                            0x9897
+#define mmCOL_MAN_UPDATE                                                        0x46a4
+#define mmCOL_MAN0_COL_MAN_UPDATE                                               0x46a4
+#define mmCOL_MAN1_COL_MAN_UPDATE                                               0x98a4
+#define mmCOL_MAN_INPUT_CSC_CONTROL                                             0x46a5
+#define mmCOL_MAN0_COL_MAN_INPUT_CSC_CONTROL                                    0x46a5
+#define mmCOL_MAN1_COL_MAN_INPUT_CSC_CONTROL                                    0x98a5
+#define mmINPUT_CSC_C11_C12_A                                                   0x46a6
+#define mmCOL_MAN0_INPUT_CSC_C11_C12_A                                          0x46a6
+#define mmCOL_MAN1_INPUT_CSC_C11_C12_A                                          0x98a6
+#define mmINPUT_CSC_C13_C14_A                                                   0x46a7
+#define mmCOL_MAN0_INPUT_CSC_C13_C14_A                                          0x46a7
+#define mmCOL_MAN1_INPUT_CSC_C13_C14_A                                          0x98a7
+#define mmINPUT_CSC_C21_C22_A                                                   0x46a8
+#define mmCOL_MAN0_INPUT_CSC_C21_C22_A                                          0x46a8
+#define mmCOL_MAN1_INPUT_CSC_C21_C22_A                                          0x98a8
+#define mmINPUT_CSC_C23_C24_A                                                   0x46a9
+#define mmCOL_MAN0_INPUT_CSC_C23_C24_A                                          0x46a9
+#define mmCOL_MAN1_INPUT_CSC_C23_C24_A                                          0x98a9
+#define mmINPUT_CSC_C31_C32_A                                                   0x46aa
+#define mmCOL_MAN0_INPUT_CSC_C31_C32_A                                          0x46aa
+#define mmCOL_MAN1_INPUT_CSC_C31_C32_A                                          0x98aa
+#define mmINPUT_CSC_C33_C34_A                                                   0x46ab
+#define mmCOL_MAN0_INPUT_CSC_C33_C34_A                                          0x46ab
+#define mmCOL_MAN1_INPUT_CSC_C33_C34_A                                          0x98ab
+#define mmINPUT_CSC_C11_C12_B                                                   0x46ac
+#define mmCOL_MAN0_INPUT_CSC_C11_C12_B                                          0x46ac
+#define mmCOL_MAN1_INPUT_CSC_C11_C12_B                                          0x98ac
+#define mmINPUT_CSC_C13_C14_B                                                   0x46ad
+#define mmCOL_MAN0_INPUT_CSC_C13_C14_B                                          0x46ad
+#define mmCOL_MAN1_INPUT_CSC_C13_C14_B                                          0x98ad
+#define mmINPUT_CSC_C21_C22_B                                                   0x46ae
+#define mmCOL_MAN0_INPUT_CSC_C21_C22_B                                          0x46ae
+#define mmCOL_MAN1_INPUT_CSC_C21_C22_B                                          0x98ae
+#define mmINPUT_CSC_C23_C24_B                                                   0x46af
+#define mmCOL_MAN0_INPUT_CSC_C23_C24_B                                          0x46af
+#define mmCOL_MAN1_INPUT_CSC_C23_C24_B                                          0x98af
+#define mmINPUT_CSC_C31_C32_B                                                   0x46b0
+#define mmCOL_MAN0_INPUT_CSC_C31_C32_B                                          0x46b0
+#define mmCOL_MAN1_INPUT_CSC_C31_C32_B                                          0x98b0
+#define mmINPUT_CSC_C33_C34_B                                                   0x46b1
+#define mmCOL_MAN0_INPUT_CSC_C33_C34_B                                          0x46b1
+#define mmCOL_MAN1_INPUT_CSC_C33_C34_B                                          0x98b1
+#define mmPRESCALE_CONTROL                                                      0x46b2
+#define mmCOL_MAN0_PRESCALE_CONTROL                                             0x46b2
+#define mmCOL_MAN1_PRESCALE_CONTROL                                             0x98b2
+#define mmPRESCALE_VALUES_R                                                     0x46b3
+#define mmCOL_MAN0_PRESCALE_VALUES_R                                            0x46b3
+#define mmCOL_MAN1_PRESCALE_VALUES_R                                            0x98b3
+#define mmPRESCALE_VALUES_G                                                     0x46b4
+#define mmCOL_MAN0_PRESCALE_VALUES_G                                            0x46b4
+#define mmCOL_MAN1_PRESCALE_VALUES_G                                            0x98b4
+#define mmPRESCALE_VALUES_B                                                     0x46b5
+#define mmCOL_MAN0_PRESCALE_VALUES_B                                            0x46b5
+#define mmCOL_MAN1_PRESCALE_VALUES_B                                            0x98b5
+#define mmCOL_MAN_OUTPUT_CSC_CONTROL                                            0x46b6
+#define mmCOL_MAN0_COL_MAN_OUTPUT_CSC_CONTROL                                   0x46b6
+#define mmCOL_MAN1_COL_MAN_OUTPUT_CSC_CONTROL                                   0x98b6
+#define mmOUTPUT_CSC_C11_C12_A                                                  0x46b7
+#define mmCOL_MAN0_OUTPUT_CSC_C11_C12_A                                         0x46b7
+#define mmCOL_MAN1_OUTPUT_CSC_C11_C12_A                                         0x98b7
+#define mmOUTPUT_CSC_C13_C14_A                                                  0x46b8
+#define mmCOL_MAN0_OUTPUT_CSC_C13_C14_A                                         0x46b8
+#define mmCOL_MAN1_OUTPUT_CSC_C13_C14_A                                         0x98b8
+#define mmOUTPUT_CSC_C21_C22_A                                                  0x46b9
+#define mmCOL_MAN0_OUTPUT_CSC_C21_C22_A                                         0x46b9
+#define mmCOL_MAN1_OUTPUT_CSC_C21_C22_A                                         0x98b9
+#define mmOUTPUT_CSC_C23_C24_A                                                  0x46ba
+#define mmCOL_MAN0_OUTPUT_CSC_C23_C24_A                                         0x46ba
+#define mmCOL_MAN1_OUTPUT_CSC_C23_C24_A                                         0x98ba
+#define mmOUTPUT_CSC_C31_C32_A                                                  0x46bb
+#define mmCOL_MAN0_OUTPUT_CSC_C31_C32_A                                         0x46bb
+#define mmCOL_MAN1_OUTPUT_CSC_C31_C32_A                                         0x98bb
+#define mmOUTPUT_CSC_C33_C34_A                                                  0x46bc
+#define mmCOL_MAN0_OUTPUT_CSC_C33_C34_A                                         0x46bc
+#define mmCOL_MAN1_OUTPUT_CSC_C33_C34_A                                         0x98bc
+#define mmOUTPUT_CSC_C11_C12_B                                                  0x46bd
+#define mmCOL_MAN0_OUTPUT_CSC_C11_C12_B                                         0x46bd
+#define mmCOL_MAN1_OUTPUT_CSC_C11_C12_B                                         0x98bd
+#define mmOUTPUT_CSC_C13_C14_B                                                  0x46be
+#define mmCOL_MAN0_OUTPUT_CSC_C13_C14_B                                         0x46be
+#define mmCOL_MAN1_OUTPUT_CSC_C13_C14_B                                         0x98be
+#define mmOUTPUT_CSC_C21_C22_B                                                  0x46bf
+#define mmCOL_MAN0_OUTPUT_CSC_C21_C22_B                                         0x46bf
+#define mmCOL_MAN1_OUTPUT_CSC_C21_C22_B                                         0x98bf
+#define mmOUTPUT_CSC_C23_C24_B                                                  0x46c0
+#define mmCOL_MAN0_OUTPUT_CSC_C23_C24_B                                         0x46c0
+#define mmCOL_MAN1_OUTPUT_CSC_C23_C24_B                                         0x98c0
+#define mmOUTPUT_CSC_C31_C32_B                                                  0x46c1
+#define mmCOL_MAN0_OUTPUT_CSC_C31_C32_B                                         0x46c1
+#define mmCOL_MAN1_OUTPUT_CSC_C31_C32_B                                         0x98c1
+#define mmOUTPUT_CSC_C33_C34_B                                                  0x46c2
+#define mmCOL_MAN0_OUTPUT_CSC_C33_C34_B                                         0x46c2
+#define mmCOL_MAN1_OUTPUT_CSC_C33_C34_B                                         0x98c2
+#define mmDENORM_CLAMP_CONTROL                                                  0x46c3
+#define mmCOL_MAN0_DENORM_CLAMP_CONTROL                                         0x46c3
+#define mmCOL_MAN1_DENORM_CLAMP_CONTROL                                         0x98c3
+#define mmDENORM_CLAMP_RANGE_R_CR                                               0x46c4
+#define mmCOL_MAN0_DENORM_CLAMP_RANGE_R_CR                                      0x46c4
+#define mmCOL_MAN1_DENORM_CLAMP_RANGE_R_CR                                      0x98c4
+#define mmDENORM_CLAMP_RANGE_G_Y                                                0x46c5
+#define mmCOL_MAN0_DENORM_CLAMP_RANGE_G_Y                                       0x46c5
+#define mmCOL_MAN1_DENORM_CLAMP_RANGE_G_Y                                       0x98c5
+#define mmDENORM_CLAMP_RANGE_B_CB                                               0x46c6
+#define mmCOL_MAN0_DENORM_CLAMP_RANGE_B_CB                                      0x46c6
+#define mmCOL_MAN1_DENORM_CLAMP_RANGE_B_CB                                      0x98c6
+#define mmCOL_MAN_FP_CONVERTED_FIELD                                            0x46c7
+#define mmCOL_MAN0_COL_MAN_FP_CONVERTED_FIELD                                   0x46c7
+#define mmCOL_MAN1_COL_MAN_FP_CONVERTED_FIELD                                   0x98c7
+#define mmGAMMA_CORR_CONTROL                                                    0x46c8
+#define mmCOL_MAN0_GAMMA_CORR_CONTROL                                           0x46c8
+#define mmCOL_MAN1_GAMMA_CORR_CONTROL                                           0x98c8
+#define mmGAMMA_CORR_LUT_INDEX                                                  0x46c9
+#define mmCOL_MAN0_GAMMA_CORR_LUT_INDEX                                         0x46c9
+#define mmCOL_MAN1_GAMMA_CORR_LUT_INDEX                                         0x98c9
+#define mmGAMMA_CORR_LUT_DATA                                                   0x46ca
+#define mmCOL_MAN0_GAMMA_CORR_LUT_DATA                                          0x46ca
+#define mmCOL_MAN1_GAMMA_CORR_LUT_DATA                                          0x98ca
+#define mmGAMMA_CORR_LUT_WRITE_EN_MASK                                          0x46cb
+#define mmCOL_MAN0_GAMMA_CORR_LUT_WRITE_EN_MASK                                 0x46cb
+#define mmCOL_MAN1_GAMMA_CORR_LUT_WRITE_EN_MASK                                 0x98cb
+#define mmGAMMA_CORR_CNTLA_START_CNTL                                           0x46cc
+#define mmCOL_MAN0_GAMMA_CORR_CNTLA_START_CNTL                                  0x46cc
+#define mmCOL_MAN1_GAMMA_CORR_CNTLA_START_CNTL                                  0x98cc
+#define mmGAMMA_CORR_CNTLA_SLOPE_CNTL                                           0x46cd
+#define mmCOL_MAN0_GAMMA_CORR_CNTLA_SLOPE_CNTL                                  0x46cd
+#define mmCOL_MAN1_GAMMA_CORR_CNTLA_SLOPE_CNTL                                  0x98cd
+#define mmGAMMA_CORR_CNTLA_END_CNTL1                                            0x46ce
+#define mmCOL_MAN0_GAMMA_CORR_CNTLA_END_CNTL1                                   0x46ce
+#define mmCOL_MAN1_GAMMA_CORR_CNTLA_END_CNTL1                                   0x98ce
+#define mmGAMMA_CORR_CNTLA_END_CNTL2                                            0x46cf
+#define mmCOL_MAN0_GAMMA_CORR_CNTLA_END_CNTL2                                   0x46cf
+#define mmCOL_MAN1_GAMMA_CORR_CNTLA_END_CNTL2                                   0x98cf
+#define mmGAMMA_CORR_CNTLA_REGION_0_1                                           0x46d0
+#define mmCOL_MAN0_GAMMA_CORR_CNTLA_REGION_0_1                                  0x46d0
+#define mmCOL_MAN1_GAMMA_CORR_CNTLA_REGION_0_1                                  0x98d0
+#define mmGAMMA_CORR_CNTLA_REGION_2_3                                           0x46d1
+#define mmCOL_MAN0_GAMMA_CORR_CNTLA_REGION_2_3                                  0x46d1
+#define mmCOL_MAN1_GAMMA_CORR_CNTLA_REGION_2_3                                  0x98d1
+#define mmGAMMA_CORR_CNTLA_REGION_4_5                                           0x46d2
+#define mmCOL_MAN0_GAMMA_CORR_CNTLA_REGION_4_5                                  0x46d2
+#define mmCOL_MAN1_GAMMA_CORR_CNTLA_REGION_4_5                                  0x98d2
+#define mmGAMMA_CORR_CNTLA_REGION_6_7                                           0x46d3
+#define mmCOL_MAN0_GAMMA_CORR_CNTLA_REGION_6_7                                  0x46d3
+#define mmCOL_MAN1_GAMMA_CORR_CNTLA_REGION_6_7                                  0x98d3
+#define mmGAMMA_CORR_CNTLA_REGION_8_9                                           0x46d4
+#define mmCOL_MAN0_GAMMA_CORR_CNTLA_REGION_8_9                                  0x46d4
+#define mmCOL_MAN1_GAMMA_CORR_CNTLA_REGION_8_9                                  0x98d4
+#define mmGAMMA_CORR_CNTLA_REGION_10_11                                         0x46d5
+#define mmCOL_MAN0_GAMMA_CORR_CNTLA_REGION_10_11                                0x46d5
+#define mmCOL_MAN1_GAMMA_CORR_CNTLA_REGION_10_11                                0x98d5
+#define mmGAMMA_CORR_CNTLA_REGION_12_13                                         0x46d6
+#define mmCOL_MAN0_GAMMA_CORR_CNTLA_REGION_12_13                                0x46d6
+#define mmCOL_MAN1_GAMMA_CORR_CNTLA_REGION_12_13                                0x98d6
+#define mmGAMMA_CORR_CNTLA_REGION_14_15                                         0x46d7
+#define mmCOL_MAN0_GAMMA_CORR_CNTLA_REGION_14_15                                0x46d7
+#define mmCOL_MAN1_GAMMA_CORR_CNTLA_REGION_14_15                                0x98d7
+#define mmGAMMA_CORR_CNTLB_START_CNTL                                           0x46d8
+#define mmCOL_MAN0_GAMMA_CORR_CNTLB_START_CNTL                                  0x46d8
+#define mmCOL_MAN1_GAMMA_CORR_CNTLB_START_CNTL                                  0x98d8
+#define mmGAMMA_CORR_CNTLB_SLOPE_CNTL                                           0x46d9
+#define mmCOL_MAN0_GAMMA_CORR_CNTLB_SLOPE_CNTL                                  0x46d9
+#define mmCOL_MAN1_GAMMA_CORR_CNTLB_SLOPE_CNTL                                  0x98d9
+#define mmGAMMA_CORR_CNTLB_END_CNTL1                                            0x46da
+#define mmCOL_MAN0_GAMMA_CORR_CNTLB_END_CNTL1                                   0x46da
+#define mmCOL_MAN1_GAMMA_CORR_CNTLB_END_CNTL1                                   0x98da
+#define mmGAMMA_CORR_CNTLB_END_CNTL2                                            0x46db
+#define mmCOL_MAN0_GAMMA_CORR_CNTLB_END_CNTL2                                   0x46db
+#define mmCOL_MAN1_GAMMA_CORR_CNTLB_END_CNTL2                                   0x98db
+#define mmGAMMA_CORR_CNTLB_REGION_0_1                                           0x46dc
+#define mmCOL_MAN0_GAMMA_CORR_CNTLB_REGION_0_1                                  0x46dc
+#define mmCOL_MAN1_GAMMA_CORR_CNTLB_REGION_0_1                                  0x98dc
+#define mmGAMMA_CORR_CNTLB_REGION_2_3                                           0x46dd
+#define mmCOL_MAN0_GAMMA_CORR_CNTLB_REGION_2_3                                  0x46dd
+#define mmCOL_MAN1_GAMMA_CORR_CNTLB_REGION_2_3                                  0x98dd
+#define mmGAMMA_CORR_CNTLB_REGION_4_5                                           0x46de
+#define mmCOL_MAN0_GAMMA_CORR_CNTLB_REGION_4_5                                  0x46de
+#define mmCOL_MAN1_GAMMA_CORR_CNTLB_REGION_4_5                                  0x98de
+#define mmGAMMA_CORR_CNTLB_REGION_6_7                                           0x46df
+#define mmCOL_MAN0_GAMMA_CORR_CNTLB_REGION_6_7                                  0x46df
+#define mmCOL_MAN1_GAMMA_CORR_CNTLB_REGION_6_7                                  0x98df
+#define mmGAMMA_CORR_CNTLB_REGION_8_9                                           0x46e0
+#define mmCOL_MAN0_GAMMA_CORR_CNTLB_REGION_8_9                                  0x46e0
+#define mmCOL_MAN1_GAMMA_CORR_CNTLB_REGION_8_9                                  0x98e0
+#define mmGAMMA_CORR_CNTLB_REGION_10_11                                         0x46e1
+#define mmCOL_MAN0_GAMMA_CORR_CNTLB_REGION_10_11                                0x46e1
+#define mmCOL_MAN1_GAMMA_CORR_CNTLB_REGION_10_11                                0x98e1
+#define mmGAMMA_CORR_CNTLB_REGION_12_13                                         0x46e2
+#define mmCOL_MAN0_GAMMA_CORR_CNTLB_REGION_12_13                                0x46e2
+#define mmCOL_MAN1_GAMMA_CORR_CNTLB_REGION_12_13                                0x98e2
+#define mmGAMMA_CORR_CNTLB_REGION_14_15                                         0x46e3
+#define mmCOL_MAN0_GAMMA_CORR_CNTLB_REGION_14_15                                0x46e3
+#define mmCOL_MAN1_GAMMA_CORR_CNTLB_REGION_14_15                                0x98e3
+#define mmPACK_FIFO_ERROR                                                       0x46e4
+#define mmCOL_MAN0_PACK_FIFO_ERROR                                              0x46e4
+#define mmCOL_MAN1_PACK_FIFO_ERROR                                              0x98e4
+#define mmOUTPUT_FIFO_ERROR                                                     0x46e5
+#define mmCOL_MAN0_OUTPUT_FIFO_ERROR                                            0x46e5
+#define mmCOL_MAN1_OUTPUT_FIFO_ERROR                                            0x98e5
+#define mmINPUT_GAMMA_LUT_AUTOFILL                                              0x46e6
+#define mmCOL_MAN0_INPUT_GAMMA_LUT_AUTOFILL                                     0x46e6
+#define mmCOL_MAN1_INPUT_GAMMA_LUT_AUTOFILL                                     0x98e6
+#define mmINPUT_GAMMA_LUT_RW_INDEX                                              0x46e7
+#define mmCOL_MAN0_INPUT_GAMMA_LUT_RW_INDEX                                     0x46e7
+#define mmCOL_MAN1_INPUT_GAMMA_LUT_RW_INDEX                                     0x98e7
+#define mmINPUT_GAMMA_LUT_SEQ_COLOR                                             0x46e8
+#define mmCOL_MAN0_INPUT_GAMMA_LUT_SEQ_COLOR                                    0x46e8
+#define mmCOL_MAN1_INPUT_GAMMA_LUT_SEQ_COLOR                                    0x98e8
+#define mmINPUT_GAMMA_LUT_PWL_DATA                                              0x46e9
+#define mmCOL_MAN0_INPUT_GAMMA_LUT_PWL_DATA                                     0x46e9
+#define mmCOL_MAN1_INPUT_GAMMA_LUT_PWL_DATA                                     0x98e9
+#define mmINPUT_GAMMA_LUT_30_COLOR                                              0x46ea
+#define mmCOL_MAN0_INPUT_GAMMA_LUT_30_COLOR                                     0x46ea
+#define mmCOL_MAN1_INPUT_GAMMA_LUT_30_COLOR                                     0x98ea
+#define mmCOL_MAN_INPUT_GAMMA_CONTROL1                                          0x46eb
+#define mmCOL_MAN0_COL_MAN_INPUT_GAMMA_CONTROL1                                 0x46eb
+#define mmCOL_MAN1_COL_MAN_INPUT_GAMMA_CONTROL1                                 0x98eb
+#define mmCOL_MAN_INPUT_GAMMA_CONTROL2                                          0x46ec
+#define mmCOL_MAN0_COL_MAN_INPUT_GAMMA_CONTROL2                                 0x46ec
+#define mmCOL_MAN1_COL_MAN_INPUT_GAMMA_CONTROL2                                 0x98ec
+#define mmINPUT_GAMMA_BW_OFFSETS_B                                              0x46ed
+#define mmCOL_MAN0_INPUT_GAMMA_BW_OFFSETS_B                                     0x46ed
+#define mmCOL_MAN1_INPUT_GAMMA_BW_OFFSETS_B                                     0x98ed
+#define mmINPUT_GAMMA_BW_OFFSETS_G                                              0x46ee
+#define mmCOL_MAN0_INPUT_GAMMA_BW_OFFSETS_G                                     0x46ee
+#define mmCOL_MAN1_INPUT_GAMMA_BW_OFFSETS_G                                     0x98ee
+#define mmINPUT_GAMMA_BW_OFFSETS_R                                              0x46ef
+#define mmCOL_MAN0_INPUT_GAMMA_BW_OFFSETS_R                                     0x46ef
+#define mmCOL_MAN1_INPUT_GAMMA_BW_OFFSETS_R                                     0x98ef
+#define mmCOL_MAN_DEBUG_CONTROL                                                 0x46f0
+#define mmCOL_MAN0_COL_MAN_DEBUG_CONTROL                                        0x46f0
+#define mmCOL_MAN1_COL_MAN_DEBUG_CONTROL                                        0x98f0
+#define mmCOL_MAN_TEST_DEBUG_INDEX                                              0x46f1
+#define mmCOL_MAN0_COL_MAN_TEST_DEBUG_INDEX                                     0x46f1
+#define mmCOL_MAN1_COL_MAN_TEST_DEBUG_INDEX                                     0x98f1
+#define mmCOL_MAN_TEST_DEBUG_DATA                                               0x46f3
+#define mmCOL_MAN0_COL_MAN_TEST_DEBUG_DATA                                      0x46f3
+#define mmCOL_MAN1_COL_MAN_TEST_DEBUG_DATA                                      0x98f3
+#define mmUNP_GRPH_ENABLE                                                       0x4600
+#define mmUNP0_UNP_GRPH_ENABLE                                                  0x4600
+#define mmUNP1_UNP_GRPH_ENABLE                                                  0x9800
+#define mmUNP_GRPH_CONTROL                                                      0x4601
+#define mmUNP0_UNP_GRPH_CONTROL                                                 0x4601
+#define mmUNP1_UNP_GRPH_CONTROL                                                 0x9801
+#define mmUNP_GRPH_CONTROL_C                                                    0x4602
+#define mmUNP0_UNP_GRPH_CONTROL_C                                               0x4602
+#define mmUNP1_UNP_GRPH_CONTROL_C                                               0x9802
+#define mmUNP_GRPH_CONTROL_EXP                                                  0x4603
+#define mmUNP0_UNP_GRPH_CONTROL_EXP                                             0x4603
+#define mmUNP1_UNP_GRPH_CONTROL_EXP                                             0x9803
+#define mmUNP_GRPH_SWAP_CNTL                                                    0x4605
+#define mmUNP0_UNP_GRPH_SWAP_CNTL                                               0x4605
+#define mmUNP1_UNP_GRPH_SWAP_CNTL                                               0x9805
+#define mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_L                                    0x4606
+#define mmUNP0_UNP_GRPH_PRIMARY_SURFACE_ADDRESS_L                               0x4606
+#define mmUNP1_UNP_GRPH_PRIMARY_SURFACE_ADDRESS_L                               0x9806
+#define mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_C                                    0x4607
+#define mmUNP0_UNP_GRPH_PRIMARY_SURFACE_ADDRESS_C                               0x4607
+#define mmUNP1_UNP_GRPH_PRIMARY_SURFACE_ADDRESS_C                               0x9807
+#define mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L                               0x4608
+#define mmUNP0_UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L                          0x4608
+#define mmUNP1_UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L                          0x9808
+#define mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C                               0x4609
+#define mmUNP0_UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C                          0x4609
+#define mmUNP1_UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C                          0x9809
+#define mmUNP_GRPH_PRIMARY_BOTTOM_SURFACE_ADDRESS_L                             0x460a
+#define mmUNP0_UNP_GRPH_PRIMARY_BOTTOM_SURFACE_ADDRESS_L                        0x460a
+#define mmUNP1_UNP_GRPH_PRIMARY_BOTTOM_SURFACE_ADDRESS_L                        0x980a
+#define mmUNP_GRPH_PRIMARY_BOTTOM_SURFACE_ADDRESS_C                             0x460b
+#define mmUNP0_UNP_GRPH_PRIMARY_BOTTOM_SURFACE_ADDRESS_C                        0x460b
+#define mmUNP1_UNP_GRPH_PRIMARY_BOTTOM_SURFACE_ADDRESS_C                        0x980b
+#define mmUNP_GRPH_PRIMARY_BOTTOM_SURFACE_ADDRESS_HIGH_L                        0x460c
+#define mmUNP0_UNP_GRPH_PRIMARY_BOTTOM_SURFACE_ADDRESS_HIGH_L                   0x460c
+#define mmUNP1_UNP_GRPH_PRIMARY_BOTTOM_SURFACE_ADDRESS_HIGH_L                   0x980c
+#define mmUNP_GRPH_PRIMARY_BOTTOM_SURFACE_ADDRESS_HIGH_C                        0x460d
+#define mmUNP0_UNP_GRPH_PRIMARY_BOTTOM_SURFACE_ADDRESS_HIGH_C                   0x460d
+#define mmUNP1_UNP_GRPH_PRIMARY_BOTTOM_SURFACE_ADDRESS_HIGH_C                   0x980d
+#define mmUNP_GRPH_SECONDARY_SURFACE_ADDRESS_L                                  0x460e
+#define mmUNP0_UNP_GRPH_SECONDARY_SURFACE_ADDRESS_L                             0x460e
+#define mmUNP1_UNP_GRPH_SECONDARY_SURFACE_ADDRESS_L                             0x980e
+#define mmUNP_GRPH_SECONDARY_SURFACE_ADDRESS_C                                  0x460f
+#define mmUNP0_UNP_GRPH_SECONDARY_SURFACE_ADDRESS_C                             0x460f
+#define mmUNP1_UNP_GRPH_SECONDARY_SURFACE_ADDRESS_C                             0x980f
+#define mmUNP_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH_L                             0x4610
+#define mmUNP0_UNP_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH_L                        0x4610
+#define mmUNP1_UNP_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH_L                        0x9810
+#define mmUNP_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH_C                             0x4611
+#define mmUNP0_UNP_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH_C                        0x4611
+#define mmUNP1_UNP_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH_C                        0x9811
+#define mmUNP_GRPH_SECONDARY_BOTTOM_SURFACE_ADDRESS_L                           0x4612
+#define mmUNP0_UNP_GRPH_SECONDARY_BOTTOM_SURFACE_ADDRESS_L                      0x4612
+#define mmUNP1_UNP_GRPH_SECONDARY_BOTTOM_SURFACE_ADDRESS_L                      0x9812
+#define mmUNP_GRPH_SECONDARY_BOTTOM_SURFACE_ADDRESS_C                           0x4613
+#define mmUNP0_UNP_GRPH_SECONDARY_BOTTOM_SURFACE_ADDRESS_C                      0x4613
+#define mmUNP1_UNP_GRPH_SECONDARY_BOTTOM_SURFACE_ADDRESS_C                      0x9813
+#define mmUNP_GRPH_SECONDARY_BOTTOM_SURFACE_ADDRESS_HIGH_L                      0x4614
+#define mmUNP0_UNP_GRPH_SECONDARY_BOTTOM_SURFACE_ADDRESS_HIGH_L                 0x4614
+#define mmUNP1_UNP_GRPH_SECONDARY_BOTTOM_SURFACE_ADDRESS_HIGH_L                 0x9814
+#define mmUNP_GRPH_SECONDARY_BOTTOM_SURFACE_ADDRESS_HIGH_C                      0x4615
+#define mmUNP0_UNP_GRPH_SECONDARY_BOTTOM_SURFACE_ADDRESS_HIGH_C                 0x4615
+#define mmUNP1_UNP_GRPH_SECONDARY_BOTTOM_SURFACE_ADDRESS_HIGH_C                 0x9815
+#define mmUNP_GRPH_PITCH_L                                                      0x4616
+#define mmUNP0_UNP_GRPH_PITCH_L                                                 0x4616
+#define mmUNP1_UNP_GRPH_PITCH_L                                                 0x9816
+#define mmUNP_GRPH_PITCH_C                                                      0x4617
+#define mmUNP0_UNP_GRPH_PITCH_C                                                 0x4617
+#define mmUNP1_UNP_GRPH_PITCH_C                                                 0x9817
+#define mmUNP_GRPH_SURFACE_OFFSET_X_L                                           0x4618
+#define mmUNP0_UNP_GRPH_SURFACE_OFFSET_X_L                                      0x4618
+#define mmUNP1_UNP_GRPH_SURFACE_OFFSET_X_L                                      0x9818
+#define mmUNP_GRPH_SURFACE_OFFSET_X_C                                           0x4619
+#define mmUNP0_UNP_GRPH_SURFACE_OFFSET_X_C                                      0x4619
+#define mmUNP1_UNP_GRPH_SURFACE_OFFSET_X_C                                      0x9819
+#define mmUNP_GRPH_SURFACE_OFFSET_Y_L                                           0x461a
+#define mmUNP0_UNP_GRPH_SURFACE_OFFSET_Y_L                                      0x461a
+#define mmUNP1_UNP_GRPH_SURFACE_OFFSET_Y_L                                      0x981a
+#define mmUNP_GRPH_SURFACE_OFFSET_Y_C                                           0x461b
+#define mmUNP0_UNP_GRPH_SURFACE_OFFSET_Y_C                                      0x461b
+#define mmUNP1_UNP_GRPH_SURFACE_OFFSET_Y_C                                      0x981b
+#define mmUNP_GRPH_X_START_L                                                    0x461c
+#define mmUNP0_UNP_GRPH_X_START_L                                               0x461c
+#define mmUNP1_UNP_GRPH_X_START_L                                               0x981c
+#define mmUNP_GRPH_X_START_C                                                    0x461d
+#define mmUNP0_UNP_GRPH_X_START_C                                               0x461d
+#define mmUNP1_UNP_GRPH_X_START_C                                               0x981d
+#define mmUNP_GRPH_Y_START_L                                                    0x461e
+#define mmUNP0_UNP_GRPH_Y_START_L                                               0x461e
+#define mmUNP1_UNP_GRPH_Y_START_L                                               0x981e
+#define mmUNP_GRPH_Y_START_C                                                    0x461f
+#define mmUNP0_UNP_GRPH_Y_START_C                                               0x461f
+#define mmUNP1_UNP_GRPH_Y_START_C                                               0x981f
+#define mmUNP_GRPH_X_END_L                                                      0x4620
+#define mmUNP0_UNP_GRPH_X_END_L                                                 0x4620
+#define mmUNP1_UNP_GRPH_X_END_L                                                 0x9820
+#define mmUNP_GRPH_X_END_C                                                      0x4621
+#define mmUNP0_UNP_GRPH_X_END_C                                                 0x4621
+#define mmUNP1_UNP_GRPH_X_END_C                                                 0x9821
+#define mmUNP_GRPH_Y_END_L                                                      0x4622
+#define mmUNP0_UNP_GRPH_Y_END_L                                                 0x4622
+#define mmUNP1_UNP_GRPH_Y_END_L                                                 0x9822
+#define mmUNP_GRPH_Y_END_C                                                      0x4623
+#define mmUNP0_UNP_GRPH_Y_END_C                                                 0x4623
+#define mmUNP1_UNP_GRPH_Y_END_C                                                 0x9823
+#define mmUNP_GRPH_UPDATE                                                       0x4624
+#define mmUNP0_UNP_GRPH_UPDATE                                                  0x4624
+#define mmUNP1_UNP_GRPH_UPDATE                                                  0x9824
+#define mmUNP_PIPE_OUTSTANDING_REQUEST_LIMIT                                    0x463a
+#define mmUNP0_UNP_PIPE_OUTSTANDING_REQUEST_LIMIT                               0x463a
+#define mmUNP1_UNP_PIPE_OUTSTANDING_REQUEST_LIMIT                               0x983a
+#define mmUNP_GRPH_SURFACE_ADDRESS_INUSE_L                                      0x4625
+#define mmUNP0_UNP_GRPH_SURFACE_ADDRESS_INUSE_L                                 0x4625
+#define mmUNP1_UNP_GRPH_SURFACE_ADDRESS_INUSE_L                                 0x9825
+#define mmUNP_GRPH_SURFACE_ADDRESS_INUSE_C                                      0x4626
+#define mmUNP0_UNP_GRPH_SURFACE_ADDRESS_INUSE_C                                 0x4626
+#define mmUNP1_UNP_GRPH_SURFACE_ADDRESS_INUSE_C                                 0x9826
+#define mmUNP_GRPH_SURFACE_ADDRESS_HIGH_INUSE_L                                 0x4627
+#define mmUNP0_UNP_GRPH_SURFACE_ADDRESS_HIGH_INUSE_L                            0x4627
+#define mmUNP1_UNP_GRPH_SURFACE_ADDRESS_HIGH_INUSE_L                            0x9827
+#define mmUNP_GRPH_SURFACE_ADDRESS_HIGH_INUSE_C                                 0x4628
+#define mmUNP0_UNP_GRPH_SURFACE_ADDRESS_HIGH_INUSE_C                            0x4628
+#define mmUNP1_UNP_GRPH_SURFACE_ADDRESS_HIGH_INUSE_C                            0x9828
+#define mmUNP_DVMM_PTE_CONTROL                                                  0x4629
+#define mmUNP_GRPH_INTERRUPT_STATUS                                             0x462b
+#define mmUNP0_UNP_GRPH_INTERRUPT_STATUS                                        0x462b
+#define mmUNP1_UNP_GRPH_INTERRUPT_STATUS                                        0x982b
+#define mmUNP_GRPH_INTERRUPT_CONTROL                                            0x462c
+#define mmUNP0_UNP_GRPH_INTERRUPT_CONTROL                                       0x462c
+#define mmUNP1_UNP_GRPH_INTERRUPT_CONTROL                                       0x982c
+#define mmUNP_GRPH_STEREOSYNC_FLIP                                              0x462e
+#define mmUNP0_UNP_GRPH_STEREOSYNC_FLIP                                         0x462e
+#define mmUNP1_UNP_GRPH_STEREOSYNC_FLIP                                         0x982e
+#define mmUNP_FLIP_CONTROL                                                      0x462f
+#define mmUNP0_UNP_FLIP_CONTROL                                                 0x462f
+#define mmUNP1_UNP_FLIP_CONTROL                                                 0x982f
+#define mmUNP_CRC_CONTROL                                                       0x4630
+#define mmUNP0_UNP_CRC_CONTROL                                                  0x4630
+#define mmUNP1_UNP_CRC_CONTROL                                                  0x9830
+#define mmUNP_CRC_MASK                                                          0x4631
+#define mmUNP0_UNP_CRC_MASK                                                     0x4631
+#define mmUNP1_UNP_CRC_MASK                                                     0x9831
+#define mmUNP_CRC_CURRENT                                                       0x4632
+#define mmUNP0_UNP_CRC_CURRENT                                                  0x4632
+#define mmUNP1_UNP_CRC_CURRENT                                                  0x9832
+#define mmUNP_CRC_LAST                                                          0x4633
+#define mmUNP0_UNP_CRC_LAST                                                     0x4633
+#define mmUNP1_UNP_CRC_LAST                                                     0x9833
+#define mmUNP_LB_DATA_GAP_BETWEEN_CHUNK                                         0x4634
+#define mmUNP0_UNP_LB_DATA_GAP_BETWEEN_CHUNK                                    0x4634
+#define mmUNP1_UNP_LB_DATA_GAP_BETWEEN_CHUNK                                    0x9834
+#define mmUNP_HW_ROTATION                                                       0x4635
+#define mmUNP0_UNP_HW_ROTATION                                                  0x4635
+#define mmUNP1_UNP_HW_ROTATION                                                  0x9835
+#define mmUNP_DEBUG                                                             0x4636
+#define mmUNP0_UNP_DEBUG                                                        0x4636
+#define mmUNP1_UNP_DEBUG                                                        0x9836
+#define mmUNP_DEBUG2                                                            0x4637
+#define mmUNP0_UNP_DEBUG2                                                       0x4637
+#define mmUNP1_UNP_DEBUG2                                                       0x9837
+#define mmUNP_DVMM_DEBUG                                                        0x463b
+#define mmUNP0_UNP_DVMM_DEBUG                                                   0x463b
+#define mmUNP1_UNP_DVMM_DEBUG                                                   0x983b
+#define mmUNP_TEST_DEBUG_INDEX                                                  0x4638
+#define mmUNP0_UNP_TEST_DEBUG_INDEX                                             0x4638
+#define mmUNP1_UNP_TEST_DEBUG_INDEX                                             0x9838
+#define mmUNP_TEST_DEBUG_DATA                                                   0x4639
+#define mmUNP0_UNP_TEST_DEBUG_DATA                                              0x4639
+#define mmUNP1_UNP_TEST_DEBUG_DATA                                              0x9839
+#define mmGENMO_WT                                                              0xf0
+#define mmGENMO_RD                                                              0xf3
+#define mmGENENB                                                                0xf0
+#define mmGENFC_WT                                                              0xee
+#define mmVGA0_GENFC_WT                                                         0xee
+#define mmVGA1_GENFC_WT                                                         0xf6
+#define mmGENFC_RD                                                              0xf2
+#define mmGENS0                                                                 0xf0
+#define mmGENS1                                                                 0xee
+#define mmVGA0_GENS1                                                            0xee
+#define mmVGA1_GENS1                                                            0xf6
+#define mmDAC_DATA                                                              0xf2
+#define mmDAC_MASK                                                              0xf1
+#define mmDAC_R_INDEX                                                           0xf1
+#define mmDAC_W_INDEX                                                           0xf2
+#define mmSEQ8_IDX                                                              0xf1
+#define mmSEQ8_DATA                                                             0xf1
+#define ixSEQ00                                                                 0x0
+#define ixSEQ01                                                                 0x1
+#define ixSEQ02                                                                 0x2
+#define ixSEQ03                                                                 0x3
+#define ixSEQ04                                                                 0x4
+#define mmCRTC8_IDX                                                             0xed
+#define mmVGA0_CRTC8_IDX                                                        0xed
+#define mmVGA1_CRTC8_IDX                                                        0xf5
+#define mmCRTC8_DATA                                                            0xed
+#define mmVGA0_CRTC8_DATA                                                       0xed
+#define mmVGA1_CRTC8_DATA                                                       0xf5
+#define ixCRT00                                                                 0x0
+#define ixCRT01                                                                 0x1
+#define ixCRT02                                                                 0x2
+#define ixCRT03                                                                 0x3
+#define ixCRT04                                                                 0x4
+#define ixCRT05                                                                 0x5
+#define ixCRT06                                                                 0x6
+#define ixCRT07                                                                 0x7
+#define ixCRT08                                                                 0x8
+#define ixCRT09                                                                 0x9
+#define ixCRT0A                                                                 0xa
+#define ixCRT0B                                                                 0xb
+#define ixCRT0C                                                                 0xc
+#define ixCRT0D                                                                 0xd
+#define ixCRT0E                                                                 0xe
+#define ixCRT0F                                                                 0xf
+#define ixCRT10                                                                 0x10
+#define ixCRT11                                                                 0x11
+#define ixCRT12                                                                 0x12
+#define ixCRT13                                                                 0x13
+#define ixCRT14                                                                 0x14
+#define ixCRT15                                                                 0x15
+#define ixCRT16                                                                 0x16
+#define ixCRT17                                                                 0x17
+#define ixCRT18                                                                 0x18
+#define ixCRT1E                                                                 0x1e
+#define ixCRT1F                                                                 0x1f
+#define ixCRT22                                                                 0x22
+#define mmGRPH8_IDX                                                             0xf3
+#define mmGRPH8_DATA                                                            0xf3
+#define ixGRA00                                                                 0x0
+#define ixGRA01                                                                 0x1
+#define ixGRA02                                                                 0x2
+#define ixGRA03                                                                 0x3
+#define ixGRA04                                                                 0x4
+#define ixGRA05                                                                 0x5
+#define ixGRA06                                                                 0x6
+#define ixGRA07                                                                 0x7
+#define ixGRA08                                                                 0x8
+#define mmATTRX                                                                 0xf0
+#define mmATTRDW                                                                0xf0
+#define mmATTRDR                                                                0xf0
+#define ixATTR00                                                                0x0
+#define ixATTR01                                                                0x1
+#define ixATTR02                                                                0x2
+#define ixATTR03                                                                0x3
+#define ixATTR04                                                                0x4
+#define ixATTR05                                                                0x5
+#define ixATTR06                                                                0x6
+#define ixATTR07                                                                0x7
+#define ixATTR08                                                                0x8
+#define ixATTR09                                                                0x9
+#define ixATTR0A                                                                0xa
+#define ixATTR0B                                                                0xb
+#define ixATTR0C                                                                0xc
+#define ixATTR0D                                                                0xd
+#define ixATTR0E                                                                0xe
+#define ixATTR0F                                                                0xf
+#define ixATTR10                                                                0x10
+#define ixATTR11                                                                0x11
+#define ixATTR12                                                                0x12
+#define ixATTR13                                                                0x13
+#define ixATTR14                                                                0x14
+#define mmVGA_RENDER_CONTROL                                                    0xc0
+#define mmVGA_SOURCE_SELECT                                                     0xfc
+#define mmVGA_SEQUENCER_RESET_CONTROL                                           0xc1
+#define mmVGA_MODE_CONTROL                                                      0xc2
+#define mmVGA_SURFACE_PITCH_SELECT                                              0xc3
+#define mmVGA_MEMORY_BASE_ADDRESS                                               0xc4
+#define mmVGA_MEMORY_BASE_ADDRESS_HIGH                                          0xc9
+#define mmVGA_DISPBUF1_SURFACE_ADDR                                             0xc6
+#define mmVGA_DISPBUF2_SURFACE_ADDR                                             0xc8
+#define mmVGA_HDP_CONTROL                                                       0xca
+#define mmVGA_CACHE_CONTROL                                                     0xcb
+#define mmD1VGA_CONTROL                                                         0xcc
+#define mmD2VGA_CONTROL                                                         0xce
+#define mmD3VGA_CONTROL                                                         0xf8
+#define mmD4VGA_CONTROL                                                         0xf9
+#define mmD5VGA_CONTROL                                                         0xfa
+#define mmD6VGA_CONTROL                                                         0xfb
+#define mmVGA_HW_DEBUG                                                          0xcf
+#define mmVGA_STATUS                                                            0xd0
+#define mmVGA_INTERRUPT_CONTROL                                                 0xd1
+#define mmVGA_STATUS_CLEAR                                                      0xd2
+#define mmVGA_INTERRUPT_STATUS                                                  0xd3
+#define mmVGA_MAIN_CONTROL                                                      0xd4
+#define mmVGA_TEST_CONTROL                                                      0xd5
+#define mmVGA_DEBUG_READBACK_INDEX                                              0xd6
+#define mmVGA_DEBUG_READBACK_DATA                                               0xd7
+#define mmVGA_MEM_WRITE_PAGE_ADDR                                               0x12
+#define mmVGA_MEM_READ_PAGE_ADDR                                                0x13
+#define mmVGA_TEST_DEBUG_INDEX                                                  0xc5
+#define mmVGA_TEST_DEBUG_DATA                                                   0xc7
+#define ixVGADCC_DBG_DCCIF_C                                                    0x7e
+#define mmBPHYC_DAC_MACRO_CNTL                                                  0x48b9
+#define mmBPHYC_DAC_AUTO_CALIB_CONTROL                                          0x48ba
+#define mmDPG_PIPE_ARBITRATION_CONTROL1                                         0x1b30
+#define mmDMIF_PG0_DPG_PIPE_ARBITRATION_CONTROL1                                0x1b30
+#define mmDMIF_PG1_DPG_PIPE_ARBITRATION_CONTROL1                                0x1d30
+#define mmDMIF_PG2_DPG_PIPE_ARBITRATION_CONTROL1                                0x1f30
+#define mmDMIF_PG3_DPG_PIPE_ARBITRATION_CONTROL1                                0x4130
+#define mmDMIF_PG4_DPG_PIPE_ARBITRATION_CONTROL1                                0x4330
+#define mmDMIF_PG5_DPG_PIPE_ARBITRATION_CONTROL1                                0x4530
+#define mmDPG_PIPE_ARBITRATION_CONTROL2                                         0x1b31
+#define mmDMIF_PG0_DPG_PIPE_ARBITRATION_CONTROL2                                0x1b31
+#define mmDMIF_PG1_DPG_PIPE_ARBITRATION_CONTROL2                                0x1d31
+#define mmDMIF_PG2_DPG_PIPE_ARBITRATION_CONTROL2                                0x1f31
+#define mmDMIF_PG3_DPG_PIPE_ARBITRATION_CONTROL2                                0x4131
+#define mmDMIF_PG4_DPG_PIPE_ARBITRATION_CONTROL2                                0x4331
+#define mmDMIF_PG5_DPG_PIPE_ARBITRATION_CONTROL2                                0x4531
+#define mmDPG_WATERMARK_MASK_CONTROL                                            0x1b32
+#define mmDMIF_PG0_DPG_WATERMARK_MASK_CONTROL                                   0x1b32
+#define mmDMIF_PG1_DPG_WATERMARK_MASK_CONTROL                                   0x1d32
+#define mmDMIF_PG2_DPG_WATERMARK_MASK_CONTROL                                   0x1f32
+#define mmDMIF_PG3_DPG_WATERMARK_MASK_CONTROL                                   0x4132
+#define mmDMIF_PG4_DPG_WATERMARK_MASK_CONTROL                                   0x4332
+#define mmDMIF_PG5_DPG_WATERMARK_MASK_CONTROL                                   0x4532
+#define mmDPG_PIPE_URGENCY_CONTROL                                              0x1b33
+#define mmDMIF_PG0_DPG_PIPE_URGENCY_CONTROL                                     0x1b33
+#define mmDMIF_PG1_DPG_PIPE_URGENCY_CONTROL                                     0x1d33
+#define mmDMIF_PG2_DPG_PIPE_URGENCY_CONTROL                                     0x1f33
+#define mmDMIF_PG3_DPG_PIPE_URGENCY_CONTROL                                     0x4133
+#define mmDMIF_PG4_DPG_PIPE_URGENCY_CONTROL                                     0x4333
+#define mmDMIF_PG5_DPG_PIPE_URGENCY_CONTROL                                     0x4533
+#define mmDPG_PIPE_DPM_CONTROL                                                  0x1b34
+#define mmDMIF_PG0_DPG_PIPE_DPM_CONTROL                                         0x1b34
+#define mmDMIF_PG1_DPG_PIPE_DPM_CONTROL                                         0x1d34
+#define mmDMIF_PG2_DPG_PIPE_DPM_CONTROL                                         0x1f34
+#define mmDMIF_PG3_DPG_PIPE_DPM_CONTROL                                         0x4134
+#define mmDMIF_PG4_DPG_PIPE_DPM_CONTROL                                         0x4334
+#define mmDMIF_PG5_DPG_PIPE_DPM_CONTROL                                         0x4534
+#define mmDPG_PIPE_STUTTER_CONTROL                                              0x1b35
+#define mmDMIF_PG0_DPG_PIPE_STUTTER_CONTROL                                     0x1b35
+#define mmDMIF_PG1_DPG_PIPE_STUTTER_CONTROL                                     0x1d35
+#define mmDMIF_PG2_DPG_PIPE_STUTTER_CONTROL                                     0x1f35
+#define mmDMIF_PG3_DPG_PIPE_STUTTER_CONTROL                                     0x4135
+#define mmDMIF_PG4_DPG_PIPE_STUTTER_CONTROL                                     0x4335
+#define mmDMIF_PG5_DPG_PIPE_STUTTER_CONTROL                                     0x4535
+#define mmDPG_PIPE_NB_PSTATE_CHANGE_CONTROL                                     0x1b36
+#define mmDMIF_PG0_DPG_PIPE_NB_PSTATE_CHANGE_CONTROL                            0x1b36
+#define mmDMIF_PG1_DPG_PIPE_NB_PSTATE_CHANGE_CONTROL                            0x1d36
+#define mmDMIF_PG2_DPG_PIPE_NB_PSTATE_CHANGE_CONTROL                            0x1f36
+#define mmDMIF_PG3_DPG_PIPE_NB_PSTATE_CHANGE_CONTROL                            0x4136
+#define mmDMIF_PG4_DPG_PIPE_NB_PSTATE_CHANGE_CONTROL                            0x4336
+#define mmDMIF_PG5_DPG_PIPE_NB_PSTATE_CHANGE_CONTROL                            0x4536
+#define mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH                                     0x1b37
+#define mmDMIF_PG0_DPG_PIPE_STUTTER_CONTROL_NONLPTCH                            0x1b37
+#define mmDMIF_PG1_DPG_PIPE_STUTTER_CONTROL_NONLPTCH                            0x1d37
+#define mmDMIF_PG2_DPG_PIPE_STUTTER_CONTROL_NONLPTCH                            0x1f37
+#define mmDMIF_PG3_DPG_PIPE_STUTTER_CONTROL_NONLPTCH                            0x4137
+#define mmDMIF_PG4_DPG_PIPE_STUTTER_CONTROL_NONLPTCH                            0x4337
+#define mmDMIF_PG5_DPG_PIPE_STUTTER_CONTROL_NONLPTCH                            0x4537
+#define mmDPG_REPEATER_PROGRAM                                                  0x1b3a
+#define mmDMIF_PG0_DPG_REPEATER_PROGRAM                                         0x1b3a
+#define mmDMIF_PG1_DPG_REPEATER_PROGRAM                                         0x1d3a
+#define mmDMIF_PG2_DPG_REPEATER_PROGRAM                                         0x1f3a
+#define mmDMIF_PG3_DPG_REPEATER_PROGRAM                                         0x413a
+#define mmDMIF_PG4_DPG_REPEATER_PROGRAM                                         0x433a
+#define mmDMIF_PG5_DPG_REPEATER_PROGRAM                                         0x453a
+#define mmDPG_HW_DEBUG_A                                                        0x1b3b
+#define mmDMIF_PG0_DPG_HW_DEBUG_A                                               0x1b3b
+#define mmDMIF_PG1_DPG_HW_DEBUG_A                                               0x1d3b
+#define mmDMIF_PG2_DPG_HW_DEBUG_A                                               0x1f3b
+#define mmDMIF_PG3_DPG_HW_DEBUG_A                                               0x413b
+#define mmDMIF_PG4_DPG_HW_DEBUG_A                                               0x433b
+#define mmDMIF_PG5_DPG_HW_DEBUG_A                                               0x453b
+#define mmDPG_HW_DEBUG_B                                                        0x1b3c
+#define mmDMIF_PG0_DPG_HW_DEBUG_B                                               0x1b3c
+#define mmDMIF_PG1_DPG_HW_DEBUG_B                                               0x1d3c
+#define mmDMIF_PG2_DPG_HW_DEBUG_B                                               0x1f3c
+#define mmDMIF_PG3_DPG_HW_DEBUG_B                                               0x413c
+#define mmDMIF_PG4_DPG_HW_DEBUG_B                                               0x433c
+#define mmDMIF_PG5_DPG_HW_DEBUG_B                                               0x453c
+#define mmDPG_HW_DEBUG_11                                                       0x1b3d
+#define mmDMIF_PG0_DPG_HW_DEBUG_11                                              0x1b3d
+#define mmDMIF_PG1_DPG_HW_DEBUG_11                                              0x1d3d
+#define mmDMIF_PG2_DPG_HW_DEBUG_11                                              0x1f3d
+#define mmDMIF_PG3_DPG_HW_DEBUG_11                                              0x413d
+#define mmDMIF_PG4_DPG_HW_DEBUG_11                                              0x433d
+#define mmDMIF_PG5_DPG_HW_DEBUG_11                                              0x453d
+#define mmDPG_CHK_PRE_PROC_CNTL                                                 0x1b3e
+#define mmDMIF_PG0_DPG_CHK_PRE_PROC_CNTL                                        0x1b3e
+#define mmDMIF_PG1_DPG_CHK_PRE_PROC_CNTL                                        0x1d3e
+#define mmDMIF_PG2_DPG_CHK_PRE_PROC_CNTL                                        0x1f3e
+#define mmDMIF_PG3_DPG_CHK_PRE_PROC_CNTL                                        0x413e
+#define mmDMIF_PG4_DPG_CHK_PRE_PROC_CNTL                                        0x433e
+#define mmDMIF_PG5_DPG_CHK_PRE_PROC_CNTL                                        0x453e
+#define mmDPG_DVMM_STATUS                                                       0x1b3f
+#define mmDMIF_PG0_DPG_DVMM_STATUS                                              0x1b3f
+#define mmDMIF_PG1_DPG_DVMM_STATUS                                              0x1d3f
+#define mmDMIF_PG2_DPG_DVMM_STATUS                                              0x1f3f
+#define mmDMIF_PG3_DPG_DVMM_STATUS                                              0x413f
+#define mmDMIF_PG4_DPG_DVMM_STATUS                                              0x433f
+#define mmDMIF_PG5_DPG_DVMM_STATUS                                              0x453f
+#define mmDPG_TEST_DEBUG_INDEX                                                  0x1b38
+#define mmDMIF_PG0_DPG_TEST_DEBUG_INDEX                                         0x1b38
+#define mmDMIF_PG1_DPG_TEST_DEBUG_INDEX                                         0x1d38
+#define mmDMIF_PG2_DPG_TEST_DEBUG_INDEX                                         0x1f38
+#define mmDMIF_PG3_DPG_TEST_DEBUG_INDEX                                         0x4138
+#define mmDMIF_PG4_DPG_TEST_DEBUG_INDEX                                         0x4338
+#define mmDMIF_PG5_DPG_TEST_DEBUG_INDEX                                         0x4538
+#define mmDPG_TEST_DEBUG_DATA                                                   0x1b39
+#define mmDMIF_PG0_DPG_TEST_DEBUG_DATA                                          0x1b39
+#define mmDMIF_PG1_DPG_TEST_DEBUG_DATA                                          0x1d39
+#define mmDMIF_PG2_DPG_TEST_DEBUG_DATA                                          0x1f39
+#define mmDMIF_PG3_DPG_TEST_DEBUG_DATA                                          0x4139
+#define mmDMIF_PG4_DPG_TEST_DEBUG_DATA                                          0x4339
+#define mmDMIF_PG5_DPG_TEST_DEBUG_DATA                                          0x4539
+#define mmDPGV0_PIPE_ARBITRATION_CONTROL1                                       0x4730
+#define mmDMIFV_PG0_DPGV0_PIPE_ARBITRATION_CONTROL1                             0x4730
+#define mmDMIFV_PG1_DPGV0_PIPE_ARBITRATION_CONTROL1                             0x9930
+#define mmDPGV1_PIPE_ARBITRATION_CONTROL1                                       0x473d
+#define mmDMIFV_PG0_DPGV1_PIPE_ARBITRATION_CONTROL1                             0x473d
+#define mmDMIFV_PG1_DPGV1_PIPE_ARBITRATION_CONTROL1                             0x993d
+#define mmDPGV0_PIPE_ARBITRATION_CONTROL2                                       0x4731
+#define mmDMIFV_PG0_DPGV0_PIPE_ARBITRATION_CONTROL2                             0x4731
+#define mmDMIFV_PG1_DPGV0_PIPE_ARBITRATION_CONTROL2                             0x9931
+#define mmDPGV1_PIPE_ARBITRATION_CONTROL2                                       0x473e
+#define mmDMIFV_PG0_DPGV1_PIPE_ARBITRATION_CONTROL2                             0x473e
+#define mmDMIFV_PG1_DPGV1_PIPE_ARBITRATION_CONTROL2                             0x993e
+#define mmDPGV0_WATERMARK_MASK_CONTROL                                          0x4732
+#define mmDMIFV_PG0_DPGV0_WATERMARK_MASK_CONTROL                                0x4732
+#define mmDMIFV_PG1_DPGV0_WATERMARK_MASK_CONTROL                                0x9932
+#define mmDPGV1_WATERMARK_MASK_CONTROL                                          0x473f
+#define mmDMIFV_PG0_DPGV1_WATERMARK_MASK_CONTROL                                0x473f
+#define mmDMIFV_PG1_DPGV1_WATERMARK_MASK_CONTROL                                0x993f
+#define mmDPGV0_PIPE_URGENCY_CONTROL                                            0x4733
+#define mmDMIFV_PG0_DPGV0_PIPE_URGENCY_CONTROL                                  0x4733
+#define mmDMIFV_PG1_DPGV0_PIPE_URGENCY_CONTROL                                  0x9933
+#define mmDPGV1_PIPE_URGENCY_CONTROL                                            0x4740
+#define mmDMIFV_PG0_DPGV1_PIPE_URGENCY_CONTROL                                  0x4740
+#define mmDMIFV_PG1_DPGV1_PIPE_URGENCY_CONTROL                                  0x9940
+#define mmDPGV0_PIPE_DPM_CONTROL                                                0x4734
+#define mmDMIFV_PG0_DPGV0_PIPE_DPM_CONTROL                                      0x4734
+#define mmDMIFV_PG1_DPGV0_PIPE_DPM_CONTROL                                      0x9934
+#define mmDPGV1_PIPE_DPM_CONTROL                                                0x4741
+#define mmDMIFV_PG0_DPGV1_PIPE_DPM_CONTROL                                      0x4741
+#define mmDMIFV_PG1_DPGV1_PIPE_DPM_CONTROL                                      0x9941
+#define mmDPGV0_PIPE_STUTTER_CONTROL                                            0x4735
+#define mmDMIFV_PG0_DPGV0_PIPE_STUTTER_CONTROL                                  0x4735
+#define mmDMIFV_PG1_DPGV0_PIPE_STUTTER_CONTROL                                  0x9935
+#define mmDPGV1_PIPE_STUTTER_CONTROL                                            0x4742
+#define mmDMIFV_PG0_DPGV1_PIPE_STUTTER_CONTROL                                  0x4742
+#define mmDMIFV_PG1_DPGV1_PIPE_STUTTER_CONTROL                                  0x9942
+#define mmDPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL                                   0x4736
+#define mmDMIFV_PG0_DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL                         0x4736
+#define mmDMIFV_PG1_DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL                         0x9936
+#define mmDPGV1_PIPE_NB_PSTATE_CHANGE_CONTROL                                   0x4743
+#define mmDMIFV_PG0_DPGV1_PIPE_NB_PSTATE_CHANGE_CONTROL                         0x4743
+#define mmDMIFV_PG1_DPGV1_PIPE_NB_PSTATE_CHANGE_CONTROL                         0x9943
+#define mmDPGV0_PIPE_STUTTER_CONTROL_NONLPTCH                                   0x4737
+#define mmDMIFV_PG0_DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH                         0x4737
+#define mmDMIFV_PG1_DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH                         0x9937
+#define mmDPGV1_PIPE_STUTTER_CONTROL_NONLPTCH                                   0x4744
+#define mmDMIFV_PG0_DPGV1_PIPE_STUTTER_CONTROL_NONLPTCH                         0x4744
+#define mmDMIFV_PG1_DPGV1_PIPE_STUTTER_CONTROL_NONLPTCH                         0x9944
+#define mmDPGV0_REPEATER_PROGRAM                                                0x4738
+#define mmDMIFV_PG0_DPGV0_REPEATER_PROGRAM                                      0x4738
+#define mmDMIFV_PG1_DPGV0_REPEATER_PROGRAM                                      0x9938
+#define mmDPGV1_REPEATER_PROGRAM                                                0x4745
+#define mmDMIFV_PG0_DPGV1_REPEATER_PROGRAM                                      0x4745
+#define mmDMIFV_PG1_DPGV1_REPEATER_PROGRAM                                      0x9945
+#define mmDPGV0_HW_DEBUG_A                                                      0x4739
+#define mmDMIFV_PG0_DPGV0_HW_DEBUG_A                                            0x4739
+#define mmDMIFV_PG1_DPGV0_HW_DEBUG_A                                            0x9939
+#define mmDPGV1_HW_DEBUG_A                                                      0x4746
+#define mmDMIFV_PG0_DPGV1_HW_DEBUG_A                                            0x4746
+#define mmDMIFV_PG1_DPGV1_HW_DEBUG_A                                            0x9946
+#define mmDPGV0_HW_DEBUG_B                                                      0x473a
+#define mmDMIFV_PG0_DPGV0_HW_DEBUG_B                                            0x473a
+#define mmDMIFV_PG1_DPGV0_HW_DEBUG_B                                            0x993a
+#define mmDPGV1_HW_DEBUG_B                                                      0x4747
+#define mmDMIFV_PG0_DPGV1_HW_DEBUG_B                                            0x4747
+#define mmDMIFV_PG1_DPGV1_HW_DEBUG_B                                            0x9947
+#define mmDPGV0_HW_DEBUG_11                                                     0x473b
+#define mmDMIFV_PG0_DPGV0_HW_DEBUG_11                                           0x473b
+#define mmDMIFV_PG1_DPGV0_HW_DEBUG_11                                           0x993b
+#define mmDPGV1_HW_DEBUG_11                                                     0x4748
+#define mmDMIFV_PG0_DPGV1_HW_DEBUG_11                                           0x4748
+#define mmDMIFV_PG1_DPGV1_HW_DEBUG_11                                           0x9948
+#define mmDPGV0_CHK_PRE_PROC_CNTL                                               0x473c
+#define mmDMIFV_PG0_DPGV0_CHK_PRE_PROC_CNTL                                     0x473c
+#define mmDMIFV_PG1_DPGV0_CHK_PRE_PROC_CNTL                                     0x993c
+#define mmDPGV1_CHK_PRE_PROC_CNTL                                               0x4749
+#define mmDMIFV_PG0_DPGV1_CHK_PRE_PROC_CNTL                                     0x4749
+#define mmDMIFV_PG1_DPGV1_CHK_PRE_PROC_CNTL                                     0x9949
+#define mmDPGV_TEST_DEBUG_INDEX                                                 0x474e
+#define mmDMIFV_PG0_DPGV_TEST_DEBUG_INDEX                                       0x474e
+#define mmDMIFV_PG1_DPGV_TEST_DEBUG_INDEX                                       0x994e
+#define mmDPGV_TEST_DEBUG_DATA                                                  0x474f
+#define mmDMIFV_PG0_DPGV_TEST_DEBUG_DATA                                        0x474f
+#define mmDMIFV_PG1_DPGV_TEST_DEBUG_DATA                                        0x994f
+#define mmAZROOT_IMMEDIATE_COMMAND_OUTPUT_INTERFACE_INDEX                       0x18
+#define mmAZROOT_IMMEDIATE_COMMAND_OUTPUT_INTERFACE_DATA                        0x18
+#define ixAZALIA_F2_CODEC_ROOT_PARAMETER_VENDOR_AND_DEVICE_ID                   0xf00
+#define ixAZALIA_F2_CODEC_ROOT_PARAMETER_REVISION_ID                            0xf02
+#define ixAZALIA_F2_CODEC_ROOT_PARAMETER_SUBORDINATE_NODE_COUNT                 0xf04
+#define ixAZALIA_F2_CODEC_FUNCTION_PARAMETER_SUBORDINATE_NODE_COUNT             0x1f04
+#define ixAZALIA_F2_CODEC_FUNCTION_PARAMETER_GROUP_TYPE                         0x1f05
+#define ixAZALIA_F2_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES               0x1f0a
+#define ixAZALIA_F2_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS                     0x1f0b
+#define ixAZALIA_F2_CODEC_FUNCTION_PARAMETER_POWER_STATES                       0x1f0f
+#define ixAZALIA_F2_CODEC_FUNCTION_CONTROL_POWER_STATE                          0x1705
+#define ixAZALIA_F2_CODEC_FUNCTION_CONTROL_RESET                                0x17ff
+#define ixAZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID                0x1720
+#define ixAZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID_2              0x1721
+#define ixAZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID_3              0x1722
+#define ixAZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID_4              0x1723
+#define ixAZALIA_F2_CODEC_FUNCTION_CONTROL_CONVERTER_SYNCHRONIZATION            0x1770
+#define mmAZALIA_F0_CODEC_ROOT_PARAMETER_VENDOR_AND_DEVICE_ID                   0x1828
+#define mmAZALIA_F0_CODEC_ROOT_PARAMETER_REVISION_ID                            0x1829
+#define mmAZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL                                 0x182a
+#define mmAZALIA_F0_CODEC_RESYNC_FIFO_CONTROL                                   0x182b
+#define mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_GROUP_TYPE                         0x182c
+#define mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES               0x182d
+#define mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS                     0x182e
+#define mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES                       0x182f
+#define mmAZALIA_F0_CODEC_FUNCTION_CONTROL_POWER_STATE                          0x1830
+#define mmAZALIA_F0_CODEC_FUNCTION_CONTROL_RESET                                0x1831
+#define mmAZALIA_F0_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID                0x1832
+#define mmAZALIA_F0_CODEC_FUNCTION_CONTROL_CONVERTER_SYNCHRONIZATION            0x1833
+#define mmCC_RCU_DC_AUDIO_PORT_CONNECTIVITY                                     0x1834
+#define mmCC_RCU_DC_AUDIO_INPUT_PORT_CONNECTIVITY                               0x1835
+#define mmAZALIA_F0_CODEC_DEBUG                                                 0x1836
+#define mmAZALIA_F0_GTC_GROUP_OFFSET0                                           0x1837
+#define mmAZALIA_F0_GTC_GROUP_OFFSET1                                           0x1838
+#define mmAZALIA_F0_GTC_GROUP_OFFSET2                                           0x1839
+#define mmAZALIA_F0_GTC_GROUP_OFFSET3                                           0x183a
+#define mmAZALIA_F0_GTC_GROUP_OFFSET4                                           0x183b
+#define mmAZALIA_F0_GTC_GROUP_OFFSET5                                           0x183c
+#define mmAZALIA_F0_GTC_GROUP_OFFSET6                                           0x183d
+#define mmGLOBAL_CAPABILITIES                                                   0x0
+#define mmMINOR_VERSION                                                         0x0
+#define mmMAJOR_VERSION                                                         0x0
+#define mmOUTPUT_PAYLOAD_CAPABILITY                                             0x1
+#define mmINPUT_PAYLOAD_CAPABILITY                                              0x1
+#define mmGLOBAL_CONTROL                                                        0x2
+#define mmWAKE_ENABLE                                                           0x3
+#define mmSTATE_CHANGE_STATUS                                                   0x3
+#define mmGLOBAL_STATUS                                                         0x4
+#define mmOUTPUT_STREAM_PAYLOAD_CAPABILITY                                      0x6
+#define mmINPUT_STREAM_PAYLOAD_CAPABILITY                                       0x6
+#define mmINTERRUPT_CONTROL                                                     0x8
+#define mmINTERRUPT_STATUS                                                      0x9
+#define mmWALL_CLOCK_COUNTER                                                    0xc
+#define mmSTREAM_SYNCHRONIZATION                                                0xe
+#define mmCORB_LOWER_BASE_ADDRESS                                               0x10
+#define mmCORB_UPPER_BASE_ADDRESS                                               0x11
+#define mmCORB_WRITE_POINTER                                                    0x12
+#define mmCORB_READ_POINTER                                                     0x12
+#define mmCORB_CONTROL                                                          0x13
+#define mmCORB_STATUS                                                           0x13
+#define mmCORB_SIZE                                                             0x13
+#define mmRIRB_LOWER_BASE_ADDRESS                                               0x14
+#define mmRIRB_UPPER_BASE_ADDRESS                                               0x15
+#define mmRIRB_WRITE_POINTER                                                    0x16
+#define mmRESPONSE_INTERRUPT_COUNT                                              0x16
+#define mmRIRB_CONTROL                                                          0x17
+#define mmRIRB_STATUS                                                           0x17
+#define mmRIRB_SIZE                                                             0x17
+#define mmIMMEDIATE_COMMAND_OUTPUT_INTERFACE                                    0x18
+#define mmIMMEDIATE_COMMAND_OUTPUT_INTERFACE_INDEX                              0x18
+#define mmIMMEDIATE_COMMAND_OUTPUT_INTERFACE_DATA                               0x18
+#define mmIMMEDIATE_RESPONSE_INPUT_INTERFACE                                    0x19
+#define mmIMMEDIATE_COMMAND_STATUS                                              0x1a
+#define mmDMA_POSITION_LOWER_BASE_ADDRESS                                       0x1c
+#define mmDMA_POSITION_UPPER_BASE_ADDRESS                                       0x1d
+#define mmWALL_CLOCK_COUNTER_ALIAS                                              0x80c
+#define mmOUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS                           0x20
+#define mmOUTPUT_STREAM_DESCRIPTOR_LINK_POSITION_IN_CURRENT_BUFFER              0x21
+#define mmOUTPUT_STREAM_DESCRIPTOR_CYCLIC_BUFFER_LENGTH                         0x22
+#define mmOUTPUT_STREAM_DESCRIPTOR_LAST_VALID_INDEX                             0x23
+#define mmOUTPUT_STREAM_DESCRIPTOR_FIFO_SIZE                                    0x24
+#define mmOUTPUT_STREAM_DESCRIPTOR_FORMAT                                       0x24
+#define mmOUTPUT_STREAM_DESCRIPTOR_BDL_POINTER_LOWER_BASE_ADDRESS               0x26
+#define mmOUTPUT_STREAM_DESCRIPTOR_BDL_POINTER_UPPER_BASE_ADDRESS               0x27
+#define mmOUTPUT_STREAM_DESCRIPTOR_LINK_POSITION_IN_CURRENT_BUFFER_ALIAS        0x821
+#define mmAZENDPOINT_IMMEDIATE_COMMAND_OUTPUT_INTERFACE_INDEX                   0x18
+#define mmAZENDPOINT_IMMEDIATE_COMMAND_OUTPUT_INTERFACE_DATA                    0x18
+#define ixAZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES         0x2f09
+#define ixAZALIA_F2_CODEC_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES              0x2f0a
+#define ixAZALIA_F2_CODEC_CONVERTER_PARAMETER_STREAM_FORMATS                    0x2f0b
+#define ixAZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT                    0x2200
+#define ixAZALIA_F2_CODEC_CONVERTER_CONTROL_CHANNEL_STREAM_ID                   0x2706
+#define ixAZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER                   0x270d
+#define ixAZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_2                 0x270e
+#define ixAZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_3                 0x273e
+#define ixAZALIA_F2_CODEC_CONVERTER_STRIPE_CONTROL                              0x2724
+#define ixAZALIA_F2_CODEC_CONVERTER_CONTROL_RAMP_RATE                           0x2770
+#define ixAZALIA_F2_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING                       0x2771
+#define ixAZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES               0x3f09
+#define ixAZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES                            0x3f0c
+#define ixAZALIA_F2_CODEC_PIN_PARAMETER_CONNECTION_LIST_LENGTH                  0x3f0e
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONNECTION_LIST_ENTRY            0x3702
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_WIDGET_CONTROL                            0x3707
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE                      0x3708
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_PIN_SENSE                        0x3709
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT            0x371c
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_2          0x371d
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_3          0x371e
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_4          0x371f
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_SPEAKER_ALLOCATION               0x3770
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_CHANNEL_ALLOCATION                        0x3771
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_DOWN_MIX_INFO                             0x3772
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR                          0x3776
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR_DATA                     0x3776
+#define ixAUDIO_DESCRIPTOR0                                                     0x1
+#define ixAUDIO_DESCRIPTOR1                                                     0x2
+#define ixAUDIO_DESCRIPTOR2                                                     0x3
+#define ixAUDIO_DESCRIPTOR3                                                     0x4
+#define ixAUDIO_DESCRIPTOR4                                                     0x5
+#define ixAUDIO_DESCRIPTOR5                                                     0x6
+#define ixAUDIO_DESCRIPTOR6                                                     0x7
+#define ixAUDIO_DESCRIPTOR7                                                     0x8
+#define ixAUDIO_DESCRIPTOR8                                                     0x9
+#define ixAUDIO_DESCRIPTOR9                                                     0xa
+#define ixAUDIO_DESCRIPTOR10                                                    0xb
+#define ixAUDIO_DESCRIPTOR11                                                    0xc
+#define ixAUDIO_DESCRIPTOR12                                                    0xd
+#define ixAUDIO_DESCRIPTOR13                                                    0xe
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL01_ENABLE                     0x3777
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL23_ENABLE                     0x3778
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL45_ENABLE                     0x3779
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL67_ENABLE                     0x377a
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_LIPSYNC                                   0x377b
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_HBR                                       0x377c
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_AUDIO_SINK_INFO_INDEX                     0x3780
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_AUDIO_SINK_INFO_DATA                      0x3781
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_MANUFACTURER_ID                           0x0
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_PRODUCT_ID                                0x1
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_SINK_DESCRIPTION_LEN                      0x2
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_PORTID0                                   0x3
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_PORTID1                                   0x4
+#define ixSINK_DESCRIPTION0                                                     0x5
+#define ixSINK_DESCRIPTION1                                                     0x6
+#define ixSINK_DESCRIPTION2                                                     0x7
+#define ixSINK_DESCRIPTION3                                                     0x8
+#define ixSINK_DESCRIPTION4                                                     0x9
+#define ixSINK_DESCRIPTION5                                                     0xa
+#define ixSINK_DESCRIPTION6                                                     0xb
+#define ixSINK_DESCRIPTION7                                                     0xc
+#define ixSINK_DESCRIPTION8                                                     0xd
+#define ixSINK_DESCRIPTION9                                                     0xe
+#define ixSINK_DESCRIPTION10                                                    0xf
+#define ixSINK_DESCRIPTION11                                                    0x10
+#define ixSINK_DESCRIPTION12                                                    0x11
+#define ixSINK_DESCRIPTION13                                                    0x12
+#define ixSINK_DESCRIPTION14                                                    0x13
+#define ixSINK_DESCRIPTION15                                                    0x14
+#define ixSINK_DESCRIPTION16                                                    0x15
+#define ixSINK_DESCRIPTION17                                                    0x16
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL1_ENABLE                      0x3785
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL3_ENABLE                      0x3786
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL5_ENABLE                      0x3787
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL7_ENABLE                      0x3788
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL_MODE                         0x3789
+#define ixAZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_0                             0x378a
+#define ixAZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_1                             0x378b
+#define ixAZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_2                             0x378c
+#define ixAZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_3                             0x378d
+#define ixAZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_4                             0x378e
+#define ixAZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_5                             0x378f
+#define ixAZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_6                             0x3790
+#define ixAZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_7                             0x3791
+#define ixAZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_8                             0x3792
+#define ixAZALIA_F2_CODEC_PIN_ASSOCIATION_INFO                                  0x3793
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_DIGITAL_OUTPUT_STATUS                     0x3797
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_LPIB_SNAPSHOT_CONTROL                     0x3798
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_LPIB                                      0x3799
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_LPIB_TIMER_SNAPSHOT                       0x379a
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_CODING_TYPE                               0x379b
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_FORMAT_CHANGED                            0x379c
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_WIRELESS_DISPLAY_IDENTIFICATION           0x379d
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_REMOTE_KEEPALIVE                          0x379e
+#define mmAZALIA_CONTROLLER_CLOCK_GATING                                        0x17e4
+#define mmAZALIA_AUDIO_DTO                                                      0x17e5
+#define mmAZALIA_AUDIO_DTO_CONTROL                                              0x17e6
+#define mmAZALIA_SCLK_CONTROL                                                   0x17e7
+#define mmAZALIA_UNDERFLOW_FILLER_SAMPLE                                        0x17e8
+#define mmAZALIA_DATA_DMA_CONTROL                                               0x17e9
+#define mmAZALIA_BDL_DMA_CONTROL                                                0x17ea
+#define mmAZALIA_RIRB_AND_DP_CONTROL                                            0x17eb
+#define mmAZALIA_CORB_DMA_CONTROL                                               0x17ec
+#define mmAZALIA_APPLICATION_POSITION_IN_CYCLIC_BUFFER                          0x17f3
+#define mmAZALIA_CYCLIC_BUFFER_SYNC                                             0x17f4
+#define mmAZALIA_GLOBAL_CAPABILITIES                                            0x17f5
+#define mmAZALIA_OUTPUT_PAYLOAD_CAPABILITY                                      0x17f6
+#define mmAZALIA_OUTPUT_STREAM_ARBITER_CONTROL                                  0x17f7
+#define mmAZALIA_INPUT_PAYLOAD_CAPABILITY                                       0x17f8
+#define mmAZALIA_CONTROLLER_DEBUG                                               0x17f9
+#define mmAZALIA_MEM_PWR_CTRL                                                   0x1810
+#define mmAZALIA_MEM_PWR_STATUS                                                 0x1811
+#define mmDCI_PG_DEBUG_CONFIG                                                   0x1812
+#define mmAZALIA_INPUT_CRC0_CONTROL0                                            0x17fb
+#define mmAZALIA_INPUT_CRC0_CONTROL1                                            0x17fc
+#define mmAZALIA_INPUT_CRC0_CONTROL2                                            0x17fd
+#define mmAZALIA_INPUT_CRC0_CONTROL3                                            0x17fe
+#define mmAZALIA_INPUT_CRC0_RESULT                                              0x17ff
+#define ixAZALIA_INPUT_CRC0_CHANNEL0                                            0x0
+#define ixAZALIA_INPUT_CRC0_CHANNEL1                                            0x1
+#define ixAZALIA_INPUT_CRC0_CHANNEL2                                            0x2
+#define ixAZALIA_INPUT_CRC0_CHANNEL3                                            0x3
+#define ixAZALIA_INPUT_CRC0_CHANNEL4                                            0x4
+#define ixAZALIA_INPUT_CRC0_CHANNEL5                                            0x5
+#define ixAZALIA_INPUT_CRC0_CHANNEL6                                            0x6
+#define ixAZALIA_INPUT_CRC0_CHANNEL7                                            0x7
+#define mmAZALIA_INPUT_CRC1_CONTROL0                                            0x1800
+#define mmAZALIA_INPUT_CRC1_CONTROL1                                            0x1801
+#define mmAZALIA_INPUT_CRC1_CONTROL2                                            0x1802
+#define mmAZALIA_INPUT_CRC1_CONTROL3                                            0x1803
+#define mmAZALIA_INPUT_CRC1_RESULT                                              0x1804
+#define ixAZALIA_INPUT_CRC1_CHANNEL0                                            0x0
+#define ixAZALIA_INPUT_CRC1_CHANNEL1                                            0x1
+#define ixAZALIA_INPUT_CRC1_CHANNEL2                                            0x2
+#define ixAZALIA_INPUT_CRC1_CHANNEL3                                            0x3
+#define ixAZALIA_INPUT_CRC1_CHANNEL4                                            0x4
+#define ixAZALIA_INPUT_CRC1_CHANNEL5                                            0x5
+#define ixAZALIA_INPUT_CRC1_CHANNEL6                                            0x6
+#define ixAZALIA_INPUT_CRC1_CHANNEL7                                            0x7
+#define mmAZALIA_CRC0_CONTROL0                                                  0x1805
+#define mmAZALIA_CRC0_CONTROL1                                                  0x1806
+#define mmAZALIA_CRC0_CONTROL2                                                  0x1807
+#define mmAZALIA_CRC0_CONTROL3                                                  0x1808
+#define mmAZALIA_CRC0_RESULT                                                    0x1809
+#define ixAZALIA_CRC0_CHANNEL0                                                  0x0
+#define ixAZALIA_CRC0_CHANNEL1                                                  0x1
+#define ixAZALIA_CRC0_CHANNEL2                                                  0x2
+#define ixAZALIA_CRC0_CHANNEL3                                                  0x3
+#define ixAZALIA_CRC0_CHANNEL4                                                  0x4
+#define ixAZALIA_CRC0_CHANNEL5                                                  0x5
+#define ixAZALIA_CRC0_CHANNEL6                                                  0x6
+#define ixAZALIA_CRC0_CHANNEL7                                                  0x7
+#define mmAZALIA_CRC1_CONTROL0                                                  0x180a
+#define mmAZALIA_CRC1_CONTROL1                                                  0x180b
+#define mmAZALIA_CRC1_CONTROL2                                                  0x180c
+#define mmAZALIA_CRC1_CONTROL3                                                  0x180d
+#define mmAZALIA_CRC1_RESULT                                                    0x180e
+#define ixAZALIA_CRC1_CHANNEL0                                                  0x0
+#define ixAZALIA_CRC1_CHANNEL1                                                  0x1
+#define ixAZALIA_CRC1_CHANNEL2                                                  0x2
+#define ixAZALIA_CRC1_CHANNEL3                                                  0x3
+#define ixAZALIA_CRC1_CHANNEL4                                                  0x4
+#define ixAZALIA_CRC1_CHANNEL5                                                  0x5
+#define ixAZALIA_CRC1_CHANNEL6                                                  0x6
+#define ixAZALIA_CRC1_CHANNEL7                                                  0x7
+#define mmAZ_TEST_DEBUG_INDEX                                                   0x181f
+#define mmAZ_TEST_DEBUG_DATA                                                    0x1820
+#define mmAZALIA_STREAM_INDEX                                                   0x1780
+#define mmAZF0STREAM0_AZALIA_STREAM_INDEX                                       0x1780
+#define mmAZF0STREAM1_AZALIA_STREAM_INDEX                                       0x1782
+#define mmAZF0STREAM2_AZALIA_STREAM_INDEX                                       0x1784
+#define mmAZF0STREAM3_AZALIA_STREAM_INDEX                                       0x1786
+#define mmAZF0STREAM4_AZALIA_STREAM_INDEX                                       0x1788
+#define mmAZF0STREAM5_AZALIA_STREAM_INDEX                                       0x178a
+#define mmAZF0STREAM6_AZALIA_STREAM_INDEX                                       0x178c
+#define mmAZF0STREAM7_AZALIA_STREAM_INDEX                                       0x178e
+#define mmAZF0STREAM8_AZALIA_STREAM_INDEX                                       0x59c0
+#define mmAZF0STREAM9_AZALIA_STREAM_INDEX                                       0x59c2
+#define mmAZF0STREAM10_AZALIA_STREAM_INDEX                                      0x59c4
+#define mmAZF0STREAM11_AZALIA_STREAM_INDEX                                      0x59c6
+#define mmAZF0STREAM12_AZALIA_STREAM_INDEX                                      0x59c8
+#define mmAZF0STREAM13_AZALIA_STREAM_INDEX                                      0x59ca
+#define mmAZF0STREAM14_AZALIA_STREAM_INDEX                                      0x59cc
+#define mmAZF0STREAM15_AZALIA_STREAM_INDEX                                      0x59ce
+#define mmAZALIA_STREAM_DATA                                                    0x1781
+#define mmAZF0STREAM0_AZALIA_STREAM_DATA                                        0x1781
+#define mmAZF0STREAM1_AZALIA_STREAM_DATA                                        0x1783
+#define mmAZF0STREAM2_AZALIA_STREAM_DATA                                        0x1785
+#define mmAZF0STREAM3_AZALIA_STREAM_DATA                                        0x1787
+#define mmAZF0STREAM4_AZALIA_STREAM_DATA                                        0x1789
+#define mmAZF0STREAM5_AZALIA_STREAM_DATA                                        0x178b
+#define mmAZF0STREAM6_AZALIA_STREAM_DATA                                        0x178d
+#define mmAZF0STREAM7_AZALIA_STREAM_DATA                                        0x178f
+#define mmAZF0STREAM8_AZALIA_STREAM_DATA                                        0x59c1
+#define mmAZF0STREAM9_AZALIA_STREAM_DATA                                        0x59c3
+#define mmAZF0STREAM10_AZALIA_STREAM_DATA                                       0x59c5
+#define mmAZF0STREAM11_AZALIA_STREAM_DATA                                       0x59c7
+#define mmAZF0STREAM12_AZALIA_STREAM_DATA                                       0x59c9
+#define mmAZF0STREAM13_AZALIA_STREAM_DATA                                       0x59cb
+#define mmAZF0STREAM14_AZALIA_STREAM_DATA                                       0x59cd
+#define mmAZF0STREAM15_AZALIA_STREAM_DATA                                       0x59cf
+#define ixAZALIA_FIFO_SIZE_CONTROL                                              0x0
+#define ixAZALIA_LATENCY_COUNTER_CONTROL                                        0x1
+#define ixAZALIA_WORSTCASE_LATENCY_COUNT                                        0x2
+#define ixAZALIA_CUMULATIVE_LATENCY_COUNT                                       0x3
+#define ixAZALIA_CUMULATIVE_REQUEST_COUNT                                       0x4
+#define ixAZALIA_STREAM_DEBUG                                                   0x5
+#define mmAZALIA_F0_CODEC_ENDPOINT_INDEX                                        0x17a8
+#define mmAZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX                          0x17a8
+#define mmAZF0ENDPOINT1_AZALIA_F0_CODEC_ENDPOINT_INDEX                          0x17ac
+#define mmAZF0ENDPOINT2_AZALIA_F0_CODEC_ENDPOINT_INDEX                          0x17b0
+#define mmAZF0ENDPOINT3_AZALIA_F0_CODEC_ENDPOINT_INDEX                          0x17b4
+#define mmAZF0ENDPOINT4_AZALIA_F0_CODEC_ENDPOINT_INDEX                          0x17b8
+#define mmAZF0ENDPOINT5_AZALIA_F0_CODEC_ENDPOINT_INDEX                          0x17bc
+#define mmAZF0ENDPOINT6_AZALIA_F0_CODEC_ENDPOINT_INDEX                          0x17c0
+#define mmAZF0ENDPOINT7_AZALIA_F0_CODEC_ENDPOINT_INDEX                          0x17c4
+#define mmAZALIA_F0_CODEC_ENDPOINT_DATA                                         0x17a9
+#define mmAZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA                           0x17a9
+#define mmAZF0ENDPOINT1_AZALIA_F0_CODEC_ENDPOINT_DATA                           0x17ad
+#define mmAZF0ENDPOINT2_AZALIA_F0_CODEC_ENDPOINT_DATA                           0x17b1
+#define mmAZF0ENDPOINT3_AZALIA_F0_CODEC_ENDPOINT_DATA                           0x17b5
+#define mmAZF0ENDPOINT4_AZALIA_F0_CODEC_ENDPOINT_DATA                           0x17b9
+#define mmAZF0ENDPOINT5_AZALIA_F0_CODEC_ENDPOINT_DATA                           0x17bd
+#define mmAZF0ENDPOINT6_AZALIA_F0_CODEC_ENDPOINT_DATA                           0x17c1
+#define mmAZF0ENDPOINT7_AZALIA_F0_CODEC_ENDPOINT_DATA                           0x17c5
+#define ixAZALIA_F0_CODEC_CONVERTER_PIN_DEBUG                                   0x0
+#define ixAZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES         0x1
+#define ixAZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT                    0x2
+#define ixAZALIA_F0_CODEC_CONVERTER_CONTROL_CHANNEL_STREAM_ID                   0x3
+#define ixAZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER                   0x4
+#define ixAZALIA_F0_CODEC_CONVERTER_PARAMETER_STREAM_FORMATS                    0x5
+#define ixAZALIA_F0_CODEC_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES              0x6
+#define ixAZALIA_F0_CODEC_CONVERTER_STRIPE_CONTROL                              0x7
+#define ixAZALIA_F0_CODEC_CONVERTER_CONTROL_RAMP_RATE                           0x8
+#define ixAZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING                       0x9
+#define ixAZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_OFFSET_DEBUG                    0xa
+#define ixAZALIA_F0_CODEC_CONVERTER_GTC_COUNTER_DELTA                           0xc
+#define ixAZALIA_F0_CODEC_CONVERTER_GTC_COUNTER_DELTA_MIN                       0xd
+#define ixAZALIA_F0_CODEC_CONVERTER_GTC_COUNTER_DELTA_MAX                       0xe
+#define ixAZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES               0x20
+#define ixAZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES                            0x21
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE                      0x22
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_PIN_SENSE                        0x23
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_WIDGET_CONTROL                            0x24
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER                           0x25
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0                         0x28
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR1                         0x29
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR2                         0x2a
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR3                         0x2b
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR4                         0x2c
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR5                         0x2d
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR6                         0x2e
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR7                         0x2f
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR8                         0x30
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR9                         0x31
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR10                        0x32
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR11                        0x33
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR12                        0x34
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR13                        0x35
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE                       0x36
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2                      0x57
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_MODE                         0x58
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC                          0x37
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR                              0x38
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0                                0x3a
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO1                                0x3b
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO2                                0x3c
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO3                                0x3d
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4                                0x3e
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5                                0x3f
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6                                0x40
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7                                0x41
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8                                0x42
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL                          0x54
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE                0x55
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT            0x56
+#define ixAZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_0                             0x59
+#define ixAZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_1                             0x5a
+#define ixAZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_2                             0x5b
+#define ixAZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_3                             0x5c
+#define ixAZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_4                             0x5d
+#define ixAZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_5                             0x5e
+#define ixAZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_6                             0x5f
+#define ixAZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_7                             0x60
+#define ixAZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_8                             0x61
+#define ixAZALIA_F0_CODEC_PIN_ASSOCIATION_INFO                                  0x62
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_DIGITAL_OUTPUT_STATUS                     0x63
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_LPIB_SNAPSHOT_CONTROL                     0x64
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_LPIB                                      0x65
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_LPIB_TIMER_SNAPSHOT                       0x66
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_CODING_TYPE                               0x67
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_FORMAT_CHANGED                            0x68
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_WIRELESS_DISPLAY_IDENTIFICATION           0x69
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_REMOTE_KEEPALIVE                          0x6a
+#define ixAZALIA_F0_AUDIO_ENABLE_STATUS                                         0x6b
+#define ixAZALIA_F0_AUDIO_ENABLED_INT_STATUS                                    0x6c
+#define ixAZALIA_F0_AUDIO_DISABLED_INT_STATUS                                   0x6d
+#define ixAZALIA_F0_AUDIO_FORMAT_CHANGED_INT_STATUS                             0x6e
+#define mmAZALIA_F0_CODEC_INPUT_ENDPOINT_INDEX                                  0x59d4
+#define mmAZF0INPUTENDPOINT0_AZALIA_F0_CODEC_INPUT_ENDPOINT_INDEX               0x59d4
+#define mmAZF0INPUTENDPOINT1_AZALIA_F0_CODEC_INPUT_ENDPOINT_INDEX               0x59d8
+#define mmAZF0INPUTENDPOINT2_AZALIA_F0_CODEC_INPUT_ENDPOINT_INDEX               0x59dc
+#define mmAZF0INPUTENDPOINT3_AZALIA_F0_CODEC_INPUT_ENDPOINT_INDEX               0x59e0
+#define mmAZF0INPUTENDPOINT4_AZALIA_F0_CODEC_INPUT_ENDPOINT_INDEX               0x59e4
+#define mmAZF0INPUTENDPOINT5_AZALIA_F0_CODEC_INPUT_ENDPOINT_INDEX               0x59e8
+#define mmAZF0INPUTENDPOINT6_AZALIA_F0_CODEC_INPUT_ENDPOINT_INDEX               0x59ec
+#define mmAZF0INPUTENDPOINT7_AZALIA_F0_CODEC_INPUT_ENDPOINT_INDEX               0x59f0
+#define mmAZALIA_F0_CODEC_INPUT_ENDPOINT_DATA                                   0x59d5
+#define mmAZF0INPUTENDPOINT0_AZALIA_F0_CODEC_INPUT_ENDPOINT_DATA                0x59d5
+#define mmAZF0INPUTENDPOINT1_AZALIA_F0_CODEC_INPUT_ENDPOINT_DATA                0x59d9
+#define mmAZF0INPUTENDPOINT2_AZALIA_F0_CODEC_INPUT_ENDPOINT_DATA                0x59dd
+#define mmAZF0INPUTENDPOINT3_AZALIA_F0_CODEC_INPUT_ENDPOINT_DATA                0x59e1
+#define mmAZF0INPUTENDPOINT4_AZALIA_F0_CODEC_INPUT_ENDPOINT_DATA                0x59e5
+#define mmAZF0INPUTENDPOINT5_AZALIA_F0_CODEC_INPUT_ENDPOINT_DATA                0x59e9
+#define mmAZF0INPUTENDPOINT6_AZALIA_F0_CODEC_INPUT_ENDPOINT_DATA                0x59ed
+#define mmAZF0INPUTENDPOINT7_AZALIA_F0_CODEC_INPUT_ENDPOINT_DATA                0x59f1
+#define ixAZALIA_F0_CODEC_INPUT_CONVERTER_PIN_DEBUG                             0x0
+#define ixAZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES   0x1
+#define ixAZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT              0x2
+#define ixAZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_CHANNEL_STREAM_ID             0x3
+#define ixAZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER             0x4
+#define ixAZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_STREAM_FORMATS              0x5
+#define ixAZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES        0x6
+#define ixAZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES         0x20
+#define ixAZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES                      0x21
+#define ixAZALIA_F0_CODEC_INPUT_PIN_CONTROL_UNSOLICITED_RESPONSE                0x22
+#define ixAZALIA_F0_CODEC_INPUT_PIN_CONTROL_RESPONSE_INPUT_PIN_SENSE            0x23
+#define ixAZALIA_F0_CODEC_INPUT_PIN_CONTROL_WIDGET_CONTROL                      0x24
+#define ixAZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE                 0x36
+#define ixAZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE2                0x37
+#define ixAZALIA_F0_CODEC_INPUT_PIN_CONTROL_RESPONSE_HBR                        0x38
+#define ixAZALIA_F0_CODEC_INPUT_PIN_CONTROL_CHANNEL_ALLOCATION                  0x53
+#define ixAZALIA_F0_CODEC_INPUT_PIN_CONTROL_HOT_PLUG_CONTROL                    0x54
+#define ixAZALIA_F0_CODEC_INPUT_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE          0x55
+#define ixAZALIA_F0_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT      0x56
+#define ixAZALIA_F0_CODEC_INPUT_PIN_CONTROL_INPUT_STATUS_CONTROL                0x67
+#define ixAZALIA_F0_CODEC_INPUT_PIN_CONTROL_INFOFRAME                           0x68
+#define ixAZALIA_F0_CODEC_INPUT_PIN_CONTROL_LPIB_SNAPSHOT_CONTROL               0x64
+#define ixAZALIA_F0_CODEC_INPUT_PIN_CONTROL_LPIB                                0x65
+#define ixAZALIA_F0_CODEC_INPUT_PIN_CONTROL_LPIB_TIMER_SNAPSHOT                 0x66
+#define mmAZENDPOINT_IMMEDIATE_COMMAND_INPUT_INTERFACE_INDEX                    0x18
+#define mmAZENDPOINT_IMMEDIATE_COMMAND_INPUT_INTERFACE_DATA                     0x18
+#define ixAZALIA_F2_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES   0x6f09
+#define ixAZALIA_F2_CODEC_INPUT_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES        0x6f0a
+#define ixAZALIA_F2_CODEC_INPUT_CONVERTER_PARAMETER_STREAM_FORMATS              0x6f0b
+#define ixAZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT              0x6200
+#define ixAZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CHANNEL_STREAM_ID             0x6706
+#define ixAZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER             0x670d
+#define ixAZALIA_F2_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES         0x7f09
+#define ixAZALIA_F2_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES                      0x7f0c
+#define ixAZALIA_F2_CODEC_INPUT_PIN_CONTROL_WIDGET_CONTROL                      0x7707
+#define ixAZALIA_F2_CODEC_INPUT_PIN_CONTROL_UNSOLICITED_RESPONSE                0x7708
+#define ixAZALIA_F2_CODEC_INPUT_PIN_CONTROL_RESPONSE_PIN_SENSE                  0x7709
+#define ixAZALIA_F2_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT      0x771c
+#define ixAZALIA_F2_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_2    0x771d
+#define ixAZALIA_F2_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_3    0x771e
+#define ixAZALIA_F2_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_4    0x771f
+#define ixAZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL0_ENABLE                0x7777
+#define ixAZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL1_ENABLE                0x7785
+#define ixAZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL2_ENABLE                0x7778
+#define ixAZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL3_ENABLE                0x7786
+#define ixAZALIA_F2_CODEC_INPUT_PIN_CONTROL_HBR                                 0x777c
+#define ixAZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL4_ENABLE                0x7779
+#define ixAZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL5_ENABLE                0x7787
+#define ixAZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL6_ENABLE                0x777a
+#define ixAZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL7_ENABLE                0x7788
+#define ixAZALIA_F2_CODEC_INPUT_PIN_CONTROL_CHANNEL_ALLOCATION                  0x7771
+#define ixAZALIA_F2_CODEC_INPUT_PIN_CONTROL_INPUT_STATUS_CONTROL                0x779b
+#define ixAZALIA_F2_CODEC_INPUT_PIN_CONTROL_INFOFRAME                           0x779c
+#define ixAZALIA_F2_CODEC_INPUT_PIN_CONTROL_CHANNEL_STATUS_L                    0x779d
+#define ixAZALIA_F2_CODEC_INPUT_PIN_CONTROL_CHANNEL_STATUS_H                    0x779e
+#define ixAZALIA_F2_CODEC_INPUT_PIN_CONTROL_LPIB_SNAPSHOT_CONTROL               0x7798
+#define ixAZALIA_F2_CODEC_INPUT_PIN_CONTROL_LPIB                                0x7799
+#define ixAZALIA_F2_CODEC_INPUT_PIN_CONTROL_LPIB_TIMER_SNAPSHOT                 0x779a
+#define mmBLND_CONTROL                                                          0x1b6d
+#define mmBLND0_BLND_CONTROL                                                    0x1b6d
+#define mmBLND1_BLND_CONTROL                                                    0x1d6d
+#define mmBLND2_BLND_CONTROL                                                    0x1f6d
+#define mmBLND3_BLND_CONTROL                                                    0x416d
+#define mmBLND4_BLND_CONTROL                                                    0x436d
+#define mmBLND5_BLND_CONTROL                                                    0x456d
+#define mmBLND_SM_CONTROL2                                                      0x1b6e
+#define mmBLND0_BLND_SM_CONTROL2                                                0x1b6e
+#define mmBLND1_BLND_SM_CONTROL2                                                0x1d6e
+#define mmBLND2_BLND_SM_CONTROL2                                                0x1f6e
+#define mmBLND3_BLND_SM_CONTROL2                                                0x416e
+#define mmBLND4_BLND_SM_CONTROL2                                                0x436e
+#define mmBLND5_BLND_SM_CONTROL2                                                0x456e
+#define mmBLND_CONTROL2                                                         0x1b6f
+#define mmBLND0_BLND_CONTROL2                                                   0x1b6f
+#define mmBLND1_BLND_CONTROL2                                                   0x1d6f
+#define mmBLND2_BLND_CONTROL2                                                   0x1f6f
+#define mmBLND3_BLND_CONTROL2                                                   0x416f
+#define mmBLND4_BLND_CONTROL2                                                   0x436f
+#define mmBLND5_BLND_CONTROL2                                                   0x456f
+#define mmBLND_UPDATE                                                           0x1b70
+#define mmBLND0_BLND_UPDATE                                                     0x1b70
+#define mmBLND1_BLND_UPDATE                                                     0x1d70
+#define mmBLND2_BLND_UPDATE                                                     0x1f70
+#define mmBLND3_BLND_UPDATE                                                     0x4170
+#define mmBLND4_BLND_UPDATE                                                     0x4370
+#define mmBLND5_BLND_UPDATE                                                     0x4570
+#define mmBLND_UNDERFLOW_INTERRUPT                                              0x1b71
+#define mmBLND0_BLND_UNDERFLOW_INTERRUPT                                        0x1b71
+#define mmBLND1_BLND_UNDERFLOW_INTERRUPT                                        0x1d71
+#define mmBLND2_BLND_UNDERFLOW_INTERRUPT                                        0x1f71
+#define mmBLND3_BLND_UNDERFLOW_INTERRUPT                                        0x4171
+#define mmBLND4_BLND_UNDERFLOW_INTERRUPT                                        0x4371
+#define mmBLND5_BLND_UNDERFLOW_INTERRUPT                                        0x4571
+#define mmBLND_V_UPDATE_LOCK                                                    0x1b73
+#define mmBLND0_BLND_V_UPDATE_LOCK                                              0x1b73
+#define mmBLND1_BLND_V_UPDATE_LOCK                                              0x1d73
+#define mmBLND2_BLND_V_UPDATE_LOCK                                              0x1f73
+#define mmBLND3_BLND_V_UPDATE_LOCK                                              0x4173
+#define mmBLND4_BLND_V_UPDATE_LOCK                                              0x4373
+#define mmBLND5_BLND_V_UPDATE_LOCK                                              0x4573
+#define mmBLND_REG_UPDATE_STATUS                                                0x1b77
+#define mmBLND0_BLND_REG_UPDATE_STATUS                                          0x1b77
+#define mmBLND1_BLND_REG_UPDATE_STATUS                                          0x1d77
+#define mmBLND2_BLND_REG_UPDATE_STATUS                                          0x1f77
+#define mmBLND3_BLND_REG_UPDATE_STATUS                                          0x4177
+#define mmBLND4_BLND_REG_UPDATE_STATUS                                          0x4377
+#define mmBLND5_BLND_REG_UPDATE_STATUS                                          0x4577
+#define mmBLND_DEBUG                                                            0x1b74
+#define mmBLND0_BLND_DEBUG                                                      0x1b74
+#define mmBLND1_BLND_DEBUG                                                      0x1d74
+#define mmBLND2_BLND_DEBUG                                                      0x1f74
+#define mmBLND3_BLND_DEBUG                                                      0x4174
+#define mmBLND4_BLND_DEBUG                                                      0x4374
+#define mmBLND5_BLND_DEBUG                                                      0x4574
+#define mmBLND_TEST_DEBUG_INDEX                                                 0x1b75
+#define mmBLND0_BLND_TEST_DEBUG_INDEX                                           0x1b75
+#define mmBLND1_BLND_TEST_DEBUG_INDEX                                           0x1d75
+#define mmBLND2_BLND_TEST_DEBUG_INDEX                                           0x1f75
+#define mmBLND3_BLND_TEST_DEBUG_INDEX                                           0x4175
+#define mmBLND4_BLND_TEST_DEBUG_INDEX                                           0x4375
+#define mmBLND5_BLND_TEST_DEBUG_INDEX                                           0x4575
+#define mmBLND_TEST_DEBUG_DATA                                                  0x1b76
+#define mmBLND0_BLND_TEST_DEBUG_DATA                                            0x1b76
+#define mmBLND1_BLND_TEST_DEBUG_DATA                                            0x1d76
+#define mmBLND2_BLND_TEST_DEBUG_DATA                                            0x1f76
+#define mmBLND3_BLND_TEST_DEBUG_DATA                                            0x4176
+#define mmBLND4_BLND_TEST_DEBUG_DATA                                            0x4376
+#define mmBLND5_BLND_TEST_DEBUG_DATA                                            0x4576
+#define mmWB_ENABLE                                                             0x5e18
+#define mmWB_EC_CONFIG                                                          0x5e19
+#define mmCNV_MODE                                                              0x5e1a
+#define mmCNV_WINDOW_START                                                      0x5e1b
+#define mmCNV_WINDOW_SIZE                                                       0x5e1c
+#define mmCNV_UPDATE                                                            0x5e1d
+#define mmCNV_SOURCE_SIZE                                                       0x5e1e
+#define mmCNV_CSC_CONTROL                                                       0x5e1f
+#define mmCNV_CSC_C11_C12                                                       0x5e20
+#define mmCNV_CSC_C13_C14                                                       0x5e21
+#define mmCNV_CSC_C21_C22                                                       0x5e22
+#define mmCNV_CSC_C23_C24                                                       0x5e23
+#define mmCNV_CSC_C31_C32                                                       0x5e24
+#define mmCNV_CSC_C33_C34                                                       0x5e25
+#define mmCNV_CSC_ROUND_OFFSET_R                                                0x5e26
+#define mmCNV_CSC_ROUND_OFFSET_G                                                0x5e27
+#define mmCNV_CSC_ROUND_OFFSET_B                                                0x5e28
+#define mmCNV_CSC_CLAMP_R                                                       0x5e29
+#define mmCNV_CSC_CLAMP_G                                                       0x5e2a
+#define mmCNV_CSC_CLAMP_B                                                       0x5e2b
+#define mmCNV_TEST_CNTL                                                         0x5e2c
+#define mmCNV_TEST_CRC_RED                                                      0x5e2d
+#define mmCNV_TEST_CRC_GREEN                                                    0x5e2e
+#define mmCNV_TEST_CRC_BLUE                                                     0x5e2f
+#define mmWB_DEBUG_CTRL                                                         0x5e30
+#define mmWB_DBG_MODE                                                           0x5e31
+#define mmWB_HW_DEBUG                                                           0x5e32
+#define mmCNV_INPUT_SELECT                                                      0x5e33
+#define mmWB_SOFT_RESET                                                         0x5e36
+#define mmWB_WARM_UP_MODE_CTL1                                                  0x5e37
+#define mmWB_WARM_UP_MODE_CTL2                                                  0x5e38
+#define mmCNV_TEST_DEBUG_INDEX                                                  0x5e34
+#define mmCNV_TEST_DEBUG_DATA                                                   0x5e35
+#define mmDCFE_CLOCK_CONTROL                                                    0x1b00
+#define mmDCFE0_DCFE_CLOCK_CONTROL                                              0x1b00
+#define mmDCFE1_DCFE_CLOCK_CONTROL                                              0x1d00
+#define mmDCFE2_DCFE_CLOCK_CONTROL                                              0x1f00
+#define mmDCFE3_DCFE_CLOCK_CONTROL                                              0x4100
+#define mmDCFE4_DCFE_CLOCK_CONTROL                                              0x4300
+#define mmDCFE5_DCFE_CLOCK_CONTROL                                              0x4500
+#define mmDCFE_SOFT_RESET                                                       0x1b01
+#define mmDCFE0_DCFE_SOFT_RESET                                                 0x1b01
+#define mmDCFE1_DCFE_SOFT_RESET                                                 0x1d01
+#define mmDCFE2_DCFE_SOFT_RESET                                                 0x1f01
+#define mmDCFE3_DCFE_SOFT_RESET                                                 0x4101
+#define mmDCFE4_DCFE_SOFT_RESET                                                 0x4301
+#define mmDCFE5_DCFE_SOFT_RESET                                                 0x4501
+#define mmDCFE_DBG_CONFIG                                                       0x1b02
+#define mmDCFE0_DCFE_DBG_CONFIG                                                 0x1b02
+#define mmDCFE1_DCFE_DBG_CONFIG                                                 0x1d02
+#define mmDCFE2_DCFE_DBG_CONFIG                                                 0x1f02
+#define mmDCFE3_DCFE_DBG_CONFIG                                                 0x4102
+#define mmDCFE4_DCFE_DBG_CONFIG                                                 0x4302
+#define mmDCFE5_DCFE_DBG_CONFIG                                                 0x4502
+#define mmDCFE_MEM_PWR_CTRL                                                     0x1b03
+#define mmDCFE0_DCFE_MEM_PWR_CTRL                                               0x1b03
+#define mmDCFE1_DCFE_MEM_PWR_CTRL                                               0x1d03
+#define mmDCFE2_DCFE_MEM_PWR_CTRL                                               0x1f03
+#define mmDCFE3_DCFE_MEM_PWR_CTRL                                               0x4103
+#define mmDCFE4_DCFE_MEM_PWR_CTRL                                               0x4303
+#define mmDCFE5_DCFE_MEM_PWR_CTRL                                               0x4503
+#define mmDCFE_MEM_PWR_CTRL2                                                    0x1b04
+#define mmDCFE0_DCFE_MEM_PWR_CTRL2                                              0x1b04
+#define mmDCFE1_DCFE_MEM_PWR_CTRL2                                              0x1d04
+#define mmDCFE2_DCFE_MEM_PWR_CTRL2                                              0x1f04
+#define mmDCFE3_DCFE_MEM_PWR_CTRL2                                              0x4104
+#define mmDCFE4_DCFE_MEM_PWR_CTRL2                                              0x4304
+#define mmDCFE5_DCFE_MEM_PWR_CTRL2                                              0x4504
+#define mmDCFE_MEM_PWR_STATUS                                                   0x1b05
+#define mmDCFE0_DCFE_MEM_PWR_STATUS                                             0x1b05
+#define mmDCFE1_DCFE_MEM_PWR_STATUS                                             0x1d05
+#define mmDCFE2_DCFE_MEM_PWR_STATUS                                             0x1f05
+#define mmDCFE3_DCFE_MEM_PWR_STATUS                                             0x4105
+#define mmDCFE4_DCFE_MEM_PWR_STATUS                                             0x4305
+#define mmDCFE5_DCFE_MEM_PWR_STATUS                                             0x4505
+#define mmDCFE_MISC                                                             0x1b06
+#define mmDCFE0_DCFE_MISC                                                       0x1b06
+#define mmDCFE1_DCFE_MISC                                                       0x1d06
+#define mmDCFE2_DCFE_MISC                                                       0x1f06
+#define mmDCFE3_DCFE_MISC                                                       0x4106
+#define mmDCFE4_DCFE_MISC                                                       0x4306
+#define mmDCFE5_DCFE_MISC                                                       0x4506
+#define mmDCFE_FLUSH                                                            0x1b07
+#define mmDCFE0_DCFE_FLUSH                                                      0x1b07
+#define mmDCFE1_DCFE_FLUSH                                                      0x1d07
+#define mmDCFE2_DCFE_FLUSH                                                      0x1f07
+#define mmDCFE3_DCFE_FLUSH                                                      0x4107
+#define mmDCFE4_DCFE_FLUSH                                                      0x4307
+#define mmDCFE5_DCFE_FLUSH                                                      0x4507
+#define mmDCFEV_CLOCK_CONTROL                                                   0x46f4
+#define mmDCFEV0_DCFEV_CLOCK_CONTROL                                            0x46f4
+#define mmDCFEV1_DCFEV_CLOCK_CONTROL                                            0x98f4
+#define mmDCFEV_SOFT_RESET                                                      0x46f5
+#define mmDCFEV0_DCFEV_SOFT_RESET                                               0x46f5
+#define mmDCFEV1_DCFEV_SOFT_RESET                                               0x98f5
+#define mmDCFEV_DMIFV_CLOCK_CONTROL                                             0x46f6
+#define mmDCFEV0_DCFEV_DMIFV_CLOCK_CONTROL                                      0x46f6
+#define mmDCFEV1_DCFEV_DMIFV_CLOCK_CONTROL                                      0x98f6
+#define mmDCFEV_DBG_CONFIG                                                      0x46f7
+#define mmDCFEV0_DCFEV_DBG_CONFIG                                               0x46f7
+#define mmDCFEV1_DCFEV_DBG_CONFIG                                               0x98f7
+#define mmDCFEV_DMIFV_MEM_PWR_CTRL                                              0x46f8
+#define mmDCFEV0_DCFEV_DMIFV_MEM_PWR_CTRL                                       0x46f8
+#define mmDCFEV1_DCFEV_DMIFV_MEM_PWR_CTRL                                       0x98f8
+#define mmDCFEV_DMIFV_MEM_PWR_STATUS                                            0x46f9
+#define mmDCFEV0_DCFEV_DMIFV_MEM_PWR_STATUS                                     0x46f9
+#define mmDCFEV1_DCFEV_DMIFV_MEM_PWR_STATUS                                     0x98f9
+#define mmDCFEV_MEM_PWR_CTRL                                                    0x46fa
+#define mmDCFEV0_DCFEV_MEM_PWR_CTRL                                             0x46fa
+#define mmDCFEV1_DCFEV_MEM_PWR_CTRL                                             0x98fa
+#define mmDCFEV_MEM_PWR_CTRL2                                                   0x46fb
+#define mmDCFEV0_DCFEV_MEM_PWR_CTRL2                                            0x46fb
+#define mmDCFEV1_DCFEV_MEM_PWR_CTRL2                                            0x98fb
+#define mmDCFEV_MEM_PWR_STATUS                                                  0x46fc
+#define mmDCFEV0_DCFEV_MEM_PWR_STATUS                                           0x46fc
+#define mmDCFEV1_DCFEV_MEM_PWR_STATUS                                           0x98fc
+#define mmDCFEV_L_FLUSH                                                         0x46ff
+#define mmDCFEV0_DCFEV_L_FLUSH                                                  0x46ff
+#define mmDCFEV1_DCFEV_L_FLUSH                                                  0x98ff
+#define mmDCFEV_C_FLUSH                                                         0x4700
+#define mmDCFEV0_DCFEV_C_FLUSH                                                  0x4700
+#define mmDCFEV1_DCFEV_C_FLUSH                                                  0x9900
+#define mmDCFEV_DMIFV_DEBUG                                                     0x46fd
+#define mmDCFEV0_DCFEV_DMIFV_DEBUG                                              0x46fd
+#define mmDCFEV1_DCFEV_DMIFV_DEBUG                                              0x98fd
+#define mmDCFEV_MISC                                                            0x46fe
+#define mmDCFEV0_DCFEV_MISC                                                     0x46fe
+#define mmDCFEV1_DCFEV_MISC                                                     0x98fe
+#define mmDC_HPD_INT_STATUS                                                     0x1898
+#define mmHPD0_DC_HPD_INT_STATUS                                                0x1898
+#define mmHPD1_DC_HPD_INT_STATUS                                                0x18a0
+#define mmHPD2_DC_HPD_INT_STATUS                                                0x18a8
+#define mmHPD3_DC_HPD_INT_STATUS                                                0x18b0
+#define mmHPD4_DC_HPD_INT_STATUS                                                0x18b8
+#define mmHPD5_DC_HPD_INT_STATUS                                                0x18c0
+#define mmDC_HPD_INT_CONTROL                                                    0x1899
+#define mmHPD0_DC_HPD_INT_CONTROL                                               0x1899
+#define mmHPD1_DC_HPD_INT_CONTROL                                               0x18a1
+#define mmHPD2_DC_HPD_INT_CONTROL                                               0x18a9
+#define mmHPD3_DC_HPD_INT_CONTROL                                               0x18b1
+#define mmHPD4_DC_HPD_INT_CONTROL                                               0x18b9
+#define mmHPD5_DC_HPD_INT_CONTROL                                               0x18c1
+#define mmDC_HPD_CONTROL                                                        0x189a
+#define mmHPD0_DC_HPD_CONTROL                                                   0x189a
+#define mmHPD1_DC_HPD_CONTROL                                                   0x18a2
+#define mmHPD2_DC_HPD_CONTROL                                                   0x18aa
+#define mmHPD3_DC_HPD_CONTROL                                                   0x18b2
+#define mmHPD4_DC_HPD_CONTROL                                                   0x18ba
+#define mmHPD5_DC_HPD_CONTROL                                                   0x18c2
+#define mmDC_HPD_FAST_TRAIN_CNTL                                                0x189b
+#define mmHPD0_DC_HPD_FAST_TRAIN_CNTL                                           0x189b
+#define mmHPD1_DC_HPD_FAST_TRAIN_CNTL                                           0x18a3
+#define mmHPD2_DC_HPD_FAST_TRAIN_CNTL                                           0x18ab
+#define mmHPD3_DC_HPD_FAST_TRAIN_CNTL                                           0x18b3
+#define mmHPD4_DC_HPD_FAST_TRAIN_CNTL                                           0x18bb
+#define mmHPD5_DC_HPD_FAST_TRAIN_CNTL                                           0x18c3
+#define mmDC_HPD_TOGGLE_FILT_CNTL                                               0x189c
+#define mmHPD0_DC_HPD_TOGGLE_FILT_CNTL                                          0x189c
+#define mmHPD1_DC_HPD_TOGGLE_FILT_CNTL                                          0x18a4
+#define mmHPD2_DC_HPD_TOGGLE_FILT_CNTL                                          0x18ac
+#define mmHPD3_DC_HPD_TOGGLE_FILT_CNTL                                          0x18b4
+#define mmHPD4_DC_HPD_TOGGLE_FILT_CNTL                                          0x18bc
+#define mmHPD5_DC_HPD_TOGGLE_FILT_CNTL                                          0x18c4
+#define mmDCO_SCRATCH0                                                          0x184e
+#define mmDCO_SCRATCH1                                                          0x184f
+#define mmDCO_SCRATCH2                                                          0x1850
+#define mmDCO_SCRATCH3                                                          0x1851
+#define mmDCO_SCRATCH4                                                          0x1852
+#define mmDCO_SCRATCH5                                                          0x1853
+#define mmDCO_SCRATCH6                                                          0x1854
+#define mmDCO_SCRATCH7                                                          0x1855
+#define mmDCE_VCE_CONTROL                                                       0x1856
+#define mmDISP_INTERRUPT_STATUS                                                 0x1857
+#define mmDISP_INTERRUPT_STATUS_CONTINUE                                        0x1858
+#define mmDISP_INTERRUPT_STATUS_CONTINUE2                                       0x1859
+#define mmDISP_INTERRUPT_STATUS_CONTINUE3                                       0x185a
+#define mmDISP_INTERRUPT_STATUS_CONTINUE4                                       0x185b
+#define mmDISP_INTERRUPT_STATUS_CONTINUE5                                       0x185c
+#define mmDISP_INTERRUPT_STATUS_CONTINUE6                                       0x185d
+#define mmDISP_INTERRUPT_STATUS_CONTINUE7                                       0x185e
+#define mmDISP_INTERRUPT_STATUS_CONTINUE8                                       0x185f
+#define mmDISP_INTERRUPT_STATUS_CONTINUE9                                       0x1860
+#define mmDISP_INTERRUPT_STATUS_CONTINUE10                                      0x1875
+#define mmDCO_MEM_PWR_STATUS                                                    0x1861
+#define mmDCO_MEM_PWR_STATUS1                                                   0x1874
+#define mmDCO_MEM_PWR_CTRL                                                      0x1862
+#define mmDCO_MEM_PWR_CTRL2                                                     0x1863
+#define mmFMT_MEMORY0_CONTROL                                                   0x1888
+#define mmFMT_MEMORY1_CONTROL                                                   0x1889
+#define mmFMT_MEMORY2_CONTROL                                                   0x188a
+#define mmFMT_MEMORY3_CONTROL                                                   0x188b
+#define mmFMT_MEMORY4_CONTROL                                                   0x188c
+#define mmFMT_MEMORY5_CONTROL                                                   0x188d
+#define mmDCO_CLK_CNTL                                                          0x1864
+#define mmDCO_CLK_CNTL2                                                         0x1876
+#define mmDCO_CLK_CNTL3                                                         0x1877
+#define mmDPDBG_CNTL                                                            0x1866
+#define mmDPDBG_INTERRUPT                                                       0x1867
+#define mmDCO_POWER_MANAGEMENT_CNTL                                             0x1868
+#define mmDCO_SOFT_RESET                                                        0x1871
+#define mmDIG_SOFT_RESET                                                        0x1872
+#define mmDIG_SOFT_RESET_2                                                      0x186a
+#define mmDCO_STEREOSYNC_SEL                                                    0x186e
+#define mmDCO_HDMI_RXSTATUS_TIMER_CONTROL                                       0x1883
+#define mmDCO_PSP_INTERRUPT_STATUS                                              0x1884
+#define mmDCO_PSP_INTERRUPT_CLEAR                                               0x1885
+#define mmDCO_GENERIC_INTERRUPT_MESSAGE                                         0x1886
+#define mmDCO_GENERIC_INTERRUPT_CLEAR                                           0x1887
+#define mmDCO_TEST_DEBUG_INDEX                                                  0x186f
+#define mmDCO_TEST_DEBUG_DATA                                                   0x1870
+#define mmDC_I2C_CONTROL                                                        0x16d4
+#define mmDC_I2C_ARBITRATION                                                    0x16d5
+#define mmDC_I2C_INTERRUPT_CONTROL                                              0x16d6
+#define mmDC_I2C_SW_STATUS                                                      0x16d7
+#define mmDC_I2C_DDC1_HW_STATUS                                                 0x16d8
+#define mmDC_I2C_DDC2_HW_STATUS                                                 0x16d9
+#define mmDC_I2C_DDC3_HW_STATUS                                                 0x16da
+#define mmDC_I2C_DDC4_HW_STATUS                                                 0x16db
+#define mmDC_I2C_DDC5_HW_STATUS                                                 0x16dc
+#define mmDC_I2C_DDC6_HW_STATUS                                                 0x16dd
+#define mmDC_I2C_DDC1_SPEED                                                     0x16de
+#define mmDC_I2C_DDC1_SETUP                                                     0x16df
+#define mmDC_I2C_DDC2_SPEED                                                     0x16e0
+#define mmDC_I2C_DDC2_SETUP                                                     0x16e1
+#define mmDC_I2C_DDC3_SPEED                                                     0x16e2
+#define mmDC_I2C_DDC3_SETUP                                                     0x16e3
+#define mmDC_I2C_DDC4_SPEED                                                     0x16e4
+#define mmDC_I2C_DDC4_SETUP                                                     0x16e5
+#define mmDC_I2C_DDC5_SPEED                                                     0x16e6
+#define mmDC_I2C_DDC5_SETUP                                                     0x16e7
+#define mmDC_I2C_DDC6_SPEED                                                     0x16e8
+#define mmDC_I2C_DDC6_SETUP                                                     0x16e9
+#define mmDC_I2C_TRANSACTION0                                                   0x16ea
+#define mmDC_I2C_TRANSACTION1                                                   0x16eb
+#define mmDC_I2C_TRANSACTION2                                                   0x16ec
+#define mmDC_I2C_TRANSACTION3                                                   0x16ed
+#define mmDC_I2C_DATA                                                           0x16ee
+#define mmDC_I2C_DDCVGA_HW_STATUS                                               0x16ef
+#define mmDC_I2C_DDCVGA_SPEED                                                   0x16f0
+#define mmDC_I2C_DDCVGA_SETUP                                                   0x16f1
+#define mmDC_I2C_EDID_DETECT_CTRL                                               0x16f2
+#define mmDC_I2C_READ_REQUEST_INTERRUPT                                         0x16f3
+#define mmGENERIC_I2C_CONTROL                                                   0x16f4
+#define mmGENERIC_I2C_INTERRUPT_CONTROL                                         0x16f5
+#define mmGENERIC_I2C_STATUS                                                    0x16f6
+#define mmGENERIC_I2C_SPEED                                                     0x16f7
+#define mmGENERIC_I2C_SETUP                                                     0x16f8
+#define mmGENERIC_I2C_TRANSACTION                                               0x16f9
+#define mmGENERIC_I2C_DATA                                                      0x16fa
+#define mmGENERIC_I2C_PIN_SELECTION                                             0x16fb
+#define mmGENERIC_I2C_PIN_DEBUG                                                 0x16fc
+#define mmBLNDV_CONTROL                                                         0x476d
+#define mmBLNDV0_BLNDV_CONTROL                                                  0x476d
+#define mmBLNDV1_BLNDV_CONTROL                                                  0x996d
+#define mmBLNDV_SM_CONTROL2                                                     0x476e
+#define mmBLNDV0_BLNDV_SM_CONTROL2                                              0x476e
+#define mmBLNDV1_BLNDV_SM_CONTROL2                                              0x996e
+#define mmBLNDV_CONTROL2                                                        0x476f
+#define mmBLNDV0_BLNDV_CONTROL2                                                 0x476f
+#define mmBLNDV1_BLNDV_CONTROL2                                                 0x996f
+#define mmBLNDV_UPDATE                                                          0x4770
+#define mmBLNDV0_BLNDV_UPDATE                                                   0x4770
+#define mmBLNDV1_BLNDV_UPDATE                                                   0x9970
+#define mmBLNDV_UNDERFLOW_INTERRUPT                                             0x4771
+#define mmBLNDV0_BLNDV_UNDERFLOW_INTERRUPT                                      0x4771
+#define mmBLNDV1_BLNDV_UNDERFLOW_INTERRUPT                                      0x9971
+#define mmBLNDV_V_UPDATE_LOCK                                                   0x4773
+#define mmBLNDV0_BLNDV_V_UPDATE_LOCK                                            0x4773
+#define mmBLNDV1_BLNDV_V_UPDATE_LOCK                                            0x9973
+#define mmBLNDV_REG_UPDATE_STATUS                                               0x4777
+#define mmBLNDV0_BLNDV_REG_UPDATE_STATUS                                        0x4777
+#define mmBLNDV1_BLNDV_REG_UPDATE_STATUS                                        0x9977
+#define mmBLNDV_DEBUG                                                           0x4774
+#define mmBLNDV0_BLNDV_DEBUG                                                    0x4774
+#define mmBLNDV1_BLNDV_DEBUG                                                    0x9974
+#define mmBLNDV_TEST_DEBUG_INDEX                                                0x4775
+#define mmBLNDV0_BLNDV_TEST_DEBUG_INDEX                                         0x4775
+#define mmBLNDV1_BLNDV_TEST_DEBUG_INDEX                                         0x9975
+#define mmBLNDV_TEST_DEBUG_DATA                                                 0x4776
+#define mmBLNDV0_BLNDV_TEST_DEBUG_DATA                                          0x4776
+#define mmBLNDV1_BLNDV_TEST_DEBUG_DATA                                          0x9976
+#define mmCRTCV_H_TOTAL                                                         0x4780
+#define mmCRTCV0_CRTCV_H_TOTAL                                                  0x4780
+#define mmCRTCV1_CRTCV_H_TOTAL                                                  0x9980
+#define mmCRTCV_H_BLANK_START_END                                               0x4781
+#define mmCRTCV0_CRTCV_H_BLANK_START_END                                        0x4781
+#define mmCRTCV1_CRTCV_H_BLANK_START_END                                        0x9981
+#define mmCRTCV_H_SYNC_A                                                        0x4782
+#define mmCRTCV0_CRTCV_H_SYNC_A                                                 0x4782
+#define mmCRTCV1_CRTCV_H_SYNC_A                                                 0x9982
+#define mmCRTCV_V_TOTAL                                                         0x4787
+#define mmCRTCV0_CRTCV_V_TOTAL                                                  0x4787
+#define mmCRTCV1_CRTCV_V_TOTAL                                                  0x9987
+#define mmCRTCV_V_BLANK_START_END                                               0x478d
+#define mmCRTCV0_CRTCV_V_BLANK_START_END                                        0x478d
+#define mmCRTCV1_CRTCV_V_BLANK_START_END                                        0x998d
+#define mmCRTCV_V_SYNC_A                                                        0x478e
+#define mmCRTCV0_CRTCV_V_SYNC_A                                                 0x478e
+#define mmCRTCV1_CRTCV_V_SYNC_A                                                 0x998e
+#define mmCRTCV_CONTROL                                                         0x479c
+#define mmCRTCV0_CRTCV_CONTROL                                                  0x479c
+#define mmCRTCV1_CRTCV_CONTROL                                                  0x999c
+#define mmCRTCV_START_LINE_CONTROL                                              0x47b3
+#define mmCRTCV0_CRTCV_START_LINE_CONTROL                                       0x47b3
+#define mmCRTCV1_CRTCV_START_LINE_CONTROL                                       0x99b3
+#define mmCRTCV_OVERSCAN_COLOR                                                  0x47c8
+#define mmCRTCV0_CRTCV_OVERSCAN_COLOR                                           0x47c8
+#define mmCRTCV1_CRTCV_OVERSCAN_COLOR                                           0x99c8
+#define mmCRTCV_OVERSCAN_COLOR_EXT                                              0x47c9
+#define mmCRTCV0_CRTCV_OVERSCAN_COLOR_EXT                                       0x47c9
+#define mmCRTCV1_CRTCV_OVERSCAN_COLOR_EXT                                       0x99c9
+#define mmCRTCV_BLACK_COLOR                                                     0x47cc
+#define mmCRTCV0_CRTCV_BLACK_COLOR                                              0x47cc
+#define mmCRTCV1_CRTCV_BLACK_COLOR                                              0x99cc
+#define mmCRTCV_BLACK_COLOR_EXT                                                 0x47cd
+#define mmCRTCV0_CRTCV_BLACK_COLOR_EXT                                          0x47cd
+#define mmCRTCV1_CRTCV_BLACK_COLOR_EXT                                          0x99cd
+#define mmCRTCV_CRC_CNTL                                                        0x47d4
+#define mmCRTCV0_CRTCV_CRC_CNTL                                                 0x47d4
+#define mmCRTCV1_CRTCV_CRC_CNTL                                                 0x99d4
+#define mmCRTCV_CRC0_WINDOWA_X_CONTROL                                          0x47d5
+#define mmCRTCV0_CRTCV_CRC0_WINDOWA_X_CONTROL                                   0x47d5
+#define mmCRTCV1_CRTCV_CRC0_WINDOWA_X_CONTROL                                   0x99d5
+#define mmCRTCV_CRC0_WINDOWA_Y_CONTROL                                          0x47d6
+#define mmCRTCV0_CRTCV_CRC0_WINDOWA_Y_CONTROL                                   0x47d6
+#define mmCRTCV1_CRTCV_CRC0_WINDOWA_Y_CONTROL                                   0x99d6
+#define mmCRTCV_CRC0_WINDOWB_X_CONTROL                                          0x47d7
+#define mmCRTCV0_CRTCV_CRC0_WINDOWB_X_CONTROL                                   0x47d7
+#define mmCRTCV1_CRTCV_CRC0_WINDOWB_X_CONTROL                                   0x99d7
+#define mmCRTCV_CRC0_WINDOWB_Y_CONTROL                                          0x47d8
+#define mmCRTCV0_CRTCV_CRC0_WINDOWB_Y_CONTROL                                   0x47d8
+#define mmCRTCV1_CRTCV_CRC0_WINDOWB_Y_CONTROL                                   0x99d8
+#define mmCRTCV_CRC0_DATA_RG                                                    0x47d9
+#define mmCRTCV0_CRTCV_CRC0_DATA_RG                                             0x47d9
+#define mmCRTCV1_CRTCV_CRC0_DATA_RG                                             0x99d9
+#define mmCRTCV_CRC0_DATA_B                                                     0x47da
+#define mmCRTCV0_CRTCV_CRC0_DATA_B                                              0x47da
+#define mmCRTCV1_CRTCV_CRC0_DATA_B                                              0x99da
+#define mmCRTCV_CRC1_WINDOWA_X_CONTROL                                          0x47db
+#define mmCRTCV0_CRTCV_CRC1_WINDOWA_X_CONTROL                                   0x47db
+#define mmCRTCV1_CRTCV_CRC1_WINDOWA_X_CONTROL                                   0x99db
+#define mmCRTCV_CRC1_WINDOWA_Y_CONTROL                                          0x47dc
+#define mmCRTCV0_CRTCV_CRC1_WINDOWA_Y_CONTROL                                   0x47dc
+#define mmCRTCV1_CRTCV_CRC1_WINDOWA_Y_CONTROL                                   0x99dc
+#define mmCRTCV_CRC1_WINDOWB_X_CONTROL                                          0x47dd
+#define mmCRTCV0_CRTCV_CRC1_WINDOWB_X_CONTROL                                   0x47dd
+#define mmCRTCV1_CRTCV_CRC1_WINDOWB_X_CONTROL                                   0x99dd
+#define mmCRTCV_CRC1_WINDOWB_Y_CONTROL                                          0x47de
+#define mmCRTCV0_CRTCV_CRC1_WINDOWB_Y_CONTROL                                   0x47de
+#define mmCRTCV1_CRTCV_CRC1_WINDOWB_Y_CONTROL                                   0x99de
+#define mmCRTCV_CRC1_DATA_RG                                                    0x47df
+#define mmCRTCV0_CRTCV_CRC1_DATA_RG                                             0x47df
+#define mmCRTCV1_CRTCV_CRC1_DATA_RG                                             0x99df
+#define mmCRTCV_CRC1_DATA_B                                                     0x47e0
+#define mmCRTCV0_CRTCV_CRC1_DATA_B                                              0x47e0
+#define mmCRTCV1_CRTCV_CRC1_DATA_B                                              0x99e0
+#define mmCRTCV_TEST_DEBUG_INDEX                                                0x47c6
+#define mmCRTCV0_CRTCV_TEST_DEBUG_INDEX                                         0x47c6
+#define mmCRTCV1_CRTCV_TEST_DEBUG_INDEX                                         0x99c6
+#define mmCRTCV_TEST_DEBUG_DATA                                                 0x47c7
+#define mmCRTCV0_CRTCV_TEST_DEBUG_DATA                                          0x47c7
+#define mmCRTCV1_CRTCV_TEST_DEBUG_DATA                                          0x99c7
+#define mmXDMA_MC_PCIE_CLIENT_CONFIG                                            0x3e0
+#define mmXDMA_LOCAL_SURFACE_TILING1                                            0x3e1
+#define mmXDMA_LOCAL_SURFACE_TILING2                                            0x3e2
+#define mmXDMA_INTERRUPT                                                        0x3e3
+#define mmXDMA_CLOCK_GATING_CNTL                                                0x3e4
+#define mmXDMA_MEM_POWER_CNTL                                                   0x3e6
+#define mmXDMA_IF_BIF_STATUS                                                    0x3e7
+#define mmXDMA_PERF_MEAS_STATUS                                                 0x3e8
+#define mmXDMA_IF_STATUS                                                        0x3e9
+#define mmXDMA_TEST_DEBUG_INDEX                                                 0x3ea
+#define mmXDMA_TEST_DEBUG_DATA                                                  0x3eb
+#define mmXDMA_RBBMIF_RDWR_CNTL                                                 0x3f8
+#define mmXDMA_PG_CONTROL                                                       0x3f9
+#define mmXDMA_PG_WDATA                                                         0x3fa
+#define mmXDMA_PG_STATUS                                                        0x3fb
+#define mmXDMA_AON_TEST_DEBUG_INDEX                                             0x3fc
+#define mmXDMA_AON_TEST_DEBUG_DATA                                              0x3fd
+#define mmXDMA_MSTR_CNTL                                                        0x3ec
+#define mmXDMA_MSTR_STATUS                                                      0x3ed
+#define mmXDMA_MSTR_MEM_CLIENT_CONFIG                                           0x3ee
+#define mmXDMA_MSTR_LOCAL_SURFACE_BASE_ADDR                                     0x3ef
+#define mmXDMA_MSTR_LOCAL_SURFACE_BASE_ADDR_HIGH                                0x3f0
+#define mmXDMA_MSTR_LOCAL_SURFACE_PITCH                                         0x3f1
+#define mmXDMA_MSTR_CMD_URGENT_CNTL                                             0x3f2
+#define mmXDMA_MSTR_MEM_URGENT_CNTL                                             0x3f3
+#define mmXDMA_MSTR_PCIE_NACK_STATUS                                            0x3f5
+#define mmXDMA_MSTR_MEM_NACK_STATUS                                             0x3f6
+#define mmXDMA_MSTR_VSYNC_GSL_CHECK                                             0x3f7
+#define mmXDMA_MSTR_PIPE_CNTL                                                   0x400
+#define mmXDMA_MSTR_PIPE0_XDMA_MSTR_PIPE_CNTL                                   0x400
+#define mmXDMA_MSTR_PIPE1_XDMA_MSTR_PIPE_CNTL                                   0x410
+#define mmXDMA_MSTR_PIPE2_XDMA_MSTR_PIPE_CNTL                                   0x420
+#define mmXDMA_MSTR_PIPE3_XDMA_MSTR_PIPE_CNTL                                   0x430
+#define mmXDMA_MSTR_PIPE4_XDMA_MSTR_PIPE_CNTL                                   0x440
+#define mmXDMA_MSTR_PIPE5_XDMA_MSTR_PIPE_CNTL                                   0x450
+#define mmXDMA_MSTR_READ_COMMAND                                                0x401
+#define mmXDMA_MSTR_PIPE0_XDMA_MSTR_READ_COMMAND                                0x401
+#define mmXDMA_MSTR_PIPE1_XDMA_MSTR_READ_COMMAND                                0x411
+#define mmXDMA_MSTR_PIPE2_XDMA_MSTR_READ_COMMAND                                0x421
+#define mmXDMA_MSTR_PIPE3_XDMA_MSTR_READ_COMMAND                                0x431
+#define mmXDMA_MSTR_PIPE4_XDMA_MSTR_READ_COMMAND                                0x441
+#define mmXDMA_MSTR_PIPE5_XDMA_MSTR_READ_COMMAND                                0x451
+#define mmXDMA_MSTR_CHANNEL_DIM                                                 0x402
+#define mmXDMA_MSTR_PIPE0_XDMA_MSTR_CHANNEL_DIM                                 0x402
+#define mmXDMA_MSTR_PIPE1_XDMA_MSTR_CHANNEL_DIM                                 0x412
+#define mmXDMA_MSTR_PIPE2_XDMA_MSTR_CHANNEL_DIM                                 0x422
+#define mmXDMA_MSTR_PIPE3_XDMA_MSTR_CHANNEL_DIM                                 0x432
+#define mmXDMA_MSTR_PIPE4_XDMA_MSTR_CHANNEL_DIM                                 0x442
+#define mmXDMA_MSTR_PIPE5_XDMA_MSTR_CHANNEL_DIM                                 0x452
+#define mmXDMA_MSTR_HEIGHT                                                      0x403
+#define mmXDMA_MSTR_PIPE0_XDMA_MSTR_HEIGHT                                      0x403
+#define mmXDMA_MSTR_PIPE1_XDMA_MSTR_HEIGHT                                      0x413
+#define mmXDMA_MSTR_PIPE2_XDMA_MSTR_HEIGHT                                      0x423
+#define mmXDMA_MSTR_PIPE3_XDMA_MSTR_HEIGHT                                      0x433
+#define mmXDMA_MSTR_PIPE4_XDMA_MSTR_HEIGHT                                      0x443
+#define mmXDMA_MSTR_PIPE5_XDMA_MSTR_HEIGHT                                      0x453
+#define mmXDMA_MSTR_REMOTE_SURFACE_BASE                                         0x404
+#define mmXDMA_MSTR_PIPE0_XDMA_MSTR_REMOTE_SURFACE_BASE                         0x404
+#define mmXDMA_MSTR_PIPE1_XDMA_MSTR_REMOTE_SURFACE_BASE                         0x414
+#define mmXDMA_MSTR_PIPE2_XDMA_MSTR_REMOTE_SURFACE_BASE                         0x424
+#define mmXDMA_MSTR_PIPE3_XDMA_MSTR_REMOTE_SURFACE_BASE                         0x434
+#define mmXDMA_MSTR_PIPE4_XDMA_MSTR_REMOTE_SURFACE_BASE                         0x444
+#define mmXDMA_MSTR_PIPE5_XDMA_MSTR_REMOTE_SURFACE_BASE                         0x454
+#define mmXDMA_MSTR_REMOTE_SURFACE_BASE_HIGH                                    0x405
+#define mmXDMA_MSTR_PIPE0_XDMA_MSTR_REMOTE_SURFACE_BASE_HIGH                    0x405
+#define mmXDMA_MSTR_PIPE1_XDMA_MSTR_REMOTE_SURFACE_BASE_HIGH                    0x415
+#define mmXDMA_MSTR_PIPE2_XDMA_MSTR_REMOTE_SURFACE_BASE_HIGH                    0x425
+#define mmXDMA_MSTR_PIPE3_XDMA_MSTR_REMOTE_SURFACE_BASE_HIGH                    0x435
+#define mmXDMA_MSTR_PIPE4_XDMA_MSTR_REMOTE_SURFACE_BASE_HIGH                    0x445
+#define mmXDMA_MSTR_PIPE5_XDMA_MSTR_REMOTE_SURFACE_BASE_HIGH                    0x455
+#define mmXDMA_MSTR_REMOTE_GPU_ADDRESS                                          0x406
+#define mmXDMA_MSTR_PIPE0_XDMA_MSTR_REMOTE_GPU_ADDRESS                          0x406
+#define mmXDMA_MSTR_PIPE1_XDMA_MSTR_REMOTE_GPU_ADDRESS                          0x416
+#define mmXDMA_MSTR_PIPE2_XDMA_MSTR_REMOTE_GPU_ADDRESS                          0x426
+#define mmXDMA_MSTR_PIPE3_XDMA_MSTR_REMOTE_GPU_ADDRESS                          0x436
+#define mmXDMA_MSTR_PIPE4_XDMA_MSTR_REMOTE_GPU_ADDRESS                          0x446
+#define mmXDMA_MSTR_PIPE5_XDMA_MSTR_REMOTE_GPU_ADDRESS                          0x456
+#define mmXDMA_MSTR_REMOTE_GPU_ADDRESS_HIGH                                     0x407
+#define mmXDMA_MSTR_PIPE0_XDMA_MSTR_REMOTE_GPU_ADDRESS_HIGH                     0x407
+#define mmXDMA_MSTR_PIPE1_XDMA_MSTR_REMOTE_GPU_ADDRESS_HIGH                     0x417
+#define mmXDMA_MSTR_PIPE2_XDMA_MSTR_REMOTE_GPU_ADDRESS_HIGH                     0x427
+#define mmXDMA_MSTR_PIPE3_XDMA_MSTR_REMOTE_GPU_ADDRESS_HIGH                     0x437
+#define mmXDMA_MSTR_PIPE4_XDMA_MSTR_REMOTE_GPU_ADDRESS_HIGH                     0x447
+#define mmXDMA_MSTR_PIPE5_XDMA_MSTR_REMOTE_GPU_ADDRESS_HIGH                     0x457
+#define mmXDMA_MSTR_CACHE_BASE_ADDR                                             0x408
+#define mmXDMA_MSTR_PIPE0_XDMA_MSTR_CACHE_BASE_ADDR                             0x408
+#define mmXDMA_MSTR_PIPE1_XDMA_MSTR_CACHE_BASE_ADDR                             0x418
+#define mmXDMA_MSTR_PIPE2_XDMA_MSTR_CACHE_BASE_ADDR                             0x428
+#define mmXDMA_MSTR_PIPE3_XDMA_MSTR_CACHE_BASE_ADDR                             0x438
+#define mmXDMA_MSTR_PIPE4_XDMA_MSTR_CACHE_BASE_ADDR                             0x448
+#define mmXDMA_MSTR_PIPE5_XDMA_MSTR_CACHE_BASE_ADDR                             0x458
+#define mmXDMA_MSTR_CACHE_BASE_ADDR_HIGH                                        0x409
+#define mmXDMA_MSTR_PIPE0_XDMA_MSTR_CACHE_BASE_ADDR_HIGH                        0x409
+#define mmXDMA_MSTR_PIPE1_XDMA_MSTR_CACHE_BASE_ADDR_HIGH                        0x419
+#define mmXDMA_MSTR_PIPE2_XDMA_MSTR_CACHE_BASE_ADDR_HIGH                        0x429
+#define mmXDMA_MSTR_PIPE3_XDMA_MSTR_CACHE_BASE_ADDR_HIGH                        0x439
+#define mmXDMA_MSTR_PIPE4_XDMA_MSTR_CACHE_BASE_ADDR_HIGH                        0x449
+#define mmXDMA_MSTR_PIPE5_XDMA_MSTR_CACHE_BASE_ADDR_HIGH                        0x459
+#define mmXDMA_MSTR_CACHE                                                       0x40a
+#define mmXDMA_MSTR_PIPE0_XDMA_MSTR_CACHE                                       0x40a
+#define mmXDMA_MSTR_PIPE1_XDMA_MSTR_CACHE                                       0x41a
+#define mmXDMA_MSTR_PIPE2_XDMA_MSTR_CACHE                                       0x42a
+#define mmXDMA_MSTR_PIPE3_XDMA_MSTR_CACHE                                       0x43a
+#define mmXDMA_MSTR_PIPE4_XDMA_MSTR_CACHE                                       0x44a
+#define mmXDMA_MSTR_PIPE5_XDMA_MSTR_CACHE                                       0x45a
+#define mmXDMA_MSTR_CHANNEL_START                                               0x40b
+#define mmXDMA_MSTR_PIPE0_XDMA_MSTR_CHANNEL_START                               0x40b
+#define mmXDMA_MSTR_PIPE1_XDMA_MSTR_CHANNEL_START                               0x41b
+#define mmXDMA_MSTR_PIPE2_XDMA_MSTR_CHANNEL_START                               0x42b
+#define mmXDMA_MSTR_PIPE3_XDMA_MSTR_CHANNEL_START                               0x43b
+#define mmXDMA_MSTR_PIPE4_XDMA_MSTR_CHANNEL_START                               0x44b
+#define mmXDMA_MSTR_PIPE5_XDMA_MSTR_CHANNEL_START                               0x45b
+#define mmXDMA_MSTR_PERFMEAS_STATUS                                             0x40e
+#define mmXDMA_MSTR_PIPE0_XDMA_MSTR_PERFMEAS_STATUS                             0x40e
+#define mmXDMA_MSTR_PIPE1_XDMA_MSTR_PERFMEAS_STATUS                             0x41e
+#define mmXDMA_MSTR_PIPE2_XDMA_MSTR_PERFMEAS_STATUS                             0x42e
+#define mmXDMA_MSTR_PIPE3_XDMA_MSTR_PERFMEAS_STATUS                             0x43e
+#define mmXDMA_MSTR_PIPE4_XDMA_MSTR_PERFMEAS_STATUS                             0x44e
+#define mmXDMA_MSTR_PIPE5_XDMA_MSTR_PERFMEAS_STATUS                             0x45e
+#define mmXDMA_MSTR_PERFMEAS_CNTL                                               0x40f
+#define mmXDMA_MSTR_PIPE0_XDMA_MSTR_PERFMEAS_CNTL                               0x40f
+#define mmXDMA_MSTR_PIPE1_XDMA_MSTR_PERFMEAS_CNTL                               0x41f
+#define mmXDMA_MSTR_PIPE2_XDMA_MSTR_PERFMEAS_CNTL                               0x42f
+#define mmXDMA_MSTR_PIPE3_XDMA_MSTR_PERFMEAS_CNTL                               0x43f
+#define mmXDMA_MSTR_PIPE4_XDMA_MSTR_PERFMEAS_CNTL                               0x44f
+#define mmXDMA_MSTR_PIPE5_XDMA_MSTR_PERFMEAS_CNTL                               0x45f
+#define mmXDMA_SLV_CNTL                                                         0x460
+#define mmXDMA_SLV_MEM_CLIENT_CONFIG                                            0x461
+#define mmXDMA_SLV_SLS_PITCH                                                    0x462
+#define mmXDMA_SLV_READ_URGENT_CNTL                                             0x463
+#define mmXDMA_SLV_WRITE_URGENT_CNTL                                            0x464
+#define mmXDMA_SLV_WB_RATE_CNTL                                                 0x465
+#define mmXDMA_SLV_READ_LATENCY_MINMAX                                          0x466
+#define mmXDMA_SLV_READ_LATENCY_AVE                                             0x467
+#define mmXDMA_SLV_PCIE_NACK_STATUS                                             0x468
+#define mmXDMA_SLV_MEM_NACK_STATUS                                              0x469
+#define mmXDMA_SLV_RDRET_BUF_STATUS                                             0x46a
+#define mmXDMA_SLV_READ_LATENCY_TIMER                                           0x46b
+#define mmXDMA_SLV_FLIP_PENDING                                                 0x46c
+#define mmXDMA_SLV_CHANNEL_CNTL                                                 0x470
+#define mmXDMA_SLV_CHANNEL0_XDMA_SLV_CHANNEL_CNTL                               0x470
+#define mmXDMA_SLV_CHANNEL1_XDMA_SLV_CHANNEL_CNTL                               0x478
+#define mmXDMA_SLV_CHANNEL2_XDMA_SLV_CHANNEL_CNTL                               0x480
+#define mmXDMA_SLV_CHANNEL3_XDMA_SLV_CHANNEL_CNTL                               0x488
+#define mmXDMA_SLV_CHANNEL4_XDMA_SLV_CHANNEL_CNTL                               0x490
+#define mmXDMA_SLV_CHANNEL5_XDMA_SLV_CHANNEL_CNTL                               0x498
+#define mmXDMA_SLV_REMOTE_GPU_ADDRESS                                           0x471
+#define mmXDMA_SLV_CHANNEL0_XDMA_SLV_REMOTE_GPU_ADDRESS                         0x471
+#define mmXDMA_SLV_CHANNEL1_XDMA_SLV_REMOTE_GPU_ADDRESS                         0x479
+#define mmXDMA_SLV_CHANNEL2_XDMA_SLV_REMOTE_GPU_ADDRESS                         0x481
+#define mmXDMA_SLV_CHANNEL3_XDMA_SLV_REMOTE_GPU_ADDRESS                         0x489
+#define mmXDMA_SLV_CHANNEL4_XDMA_SLV_REMOTE_GPU_ADDRESS                         0x491
+#define mmXDMA_SLV_CHANNEL5_XDMA_SLV_REMOTE_GPU_ADDRESS                         0x499
+#define mmXDMA_SLV_REMOTE_GPU_ADDRESS_HIGH                                      0x472
+#define mmXDMA_SLV_CHANNEL0_XDMA_SLV_REMOTE_GPU_ADDRESS_HIGH                    0x472
+#define mmXDMA_SLV_CHANNEL1_XDMA_SLV_REMOTE_GPU_ADDRESS_HIGH                    0x47a
+#define mmXDMA_SLV_CHANNEL2_XDMA_SLV_REMOTE_GPU_ADDRESS_HIGH                    0x482
+#define mmXDMA_SLV_CHANNEL3_XDMA_SLV_REMOTE_GPU_ADDRESS_HIGH                    0x48a
+#define mmXDMA_SLV_CHANNEL4_XDMA_SLV_REMOTE_GPU_ADDRESS_HIGH                    0x492
+#define mmXDMA_SLV_CHANNEL5_XDMA_SLV_REMOTE_GPU_ADDRESS_HIGH                    0x49a
+#define mmCMD_BUS_TX_CONTROL_LANE0                                              0x48e0
+#define mmDC_COMBOPHYTXREGS0_CMD_BUS_TX_CONTROL_LANE0                           0x48e0
+#define mmDC_COMBOPHYTXREGS1_CMD_BUS_TX_CONTROL_LANE0                           0x4980
+#define mmDC_COMBOPHYTXREGS2_CMD_BUS_TX_CONTROL_LANE0                           0x9a20
+#define mmDC_COMBOPHYTXREGS3_CMD_BUS_TX_CONTROL_LANE0                           0x9ac0
+#define mmDC_COMBOPHYTXREGS4_CMD_BUS_TX_CONTROL_LANE0                           0x9b60
+#define mmDC_COMBOPHYTXREGS5_CMD_BUS_TX_CONTROL_LANE0                           0x9c00
+#define mmDC_COMBOPHYTXREGS6_CMD_BUS_TX_CONTROL_LANE0                           0x9ca0
+#define mmDC_COMBOPHYTXREGS7_CMD_BUS_TX_CONTROL_LANE0                           0x9d40
+#define mmCMD_BUS_TX_CONTROL_LANE1                                              0x48f0
+#define mmDC_COMBOPHYTXREGS0_CMD_BUS_TX_CONTROL_LANE1                           0x48f0
+#define mmDC_COMBOPHYTXREGS1_CMD_BUS_TX_CONTROL_LANE1                           0x4990
+#define mmDC_COMBOPHYTXREGS2_CMD_BUS_TX_CONTROL_LANE1                           0x9a30
+#define mmDC_COMBOPHYTXREGS3_CMD_BUS_TX_CONTROL_LANE1                           0x9ad0
+#define mmDC_COMBOPHYTXREGS4_CMD_BUS_TX_CONTROL_LANE1                           0x9b70
+#define mmDC_COMBOPHYTXREGS5_CMD_BUS_TX_CONTROL_LANE1                           0x9c10
+#define mmDC_COMBOPHYTXREGS6_CMD_BUS_TX_CONTROL_LANE1                           0x9cb0
+#define mmDC_COMBOPHYTXREGS7_CMD_BUS_TX_CONTROL_LANE1                           0x9d50
+#define mmCMD_BUS_TX_CONTROL_LANE2                                              0x4900
+#define mmDC_COMBOPHYTXREGS0_CMD_BUS_TX_CONTROL_LANE2                           0x4900
+#define mmDC_COMBOPHYTXREGS1_CMD_BUS_TX_CONTROL_LANE2                           0x49a0
+#define mmDC_COMBOPHYTXREGS2_CMD_BUS_TX_CONTROL_LANE2                           0x9a40
+#define mmDC_COMBOPHYTXREGS3_CMD_BUS_TX_CONTROL_LANE2                           0x9ae0
+#define mmDC_COMBOPHYTXREGS4_CMD_BUS_TX_CONTROL_LANE2                           0x9b80
+#define mmDC_COMBOPHYTXREGS5_CMD_BUS_TX_CONTROL_LANE2                           0x9c20
+#define mmDC_COMBOPHYTXREGS6_CMD_BUS_TX_CONTROL_LANE2                           0x9cc0
+#define mmDC_COMBOPHYTXREGS7_CMD_BUS_TX_CONTROL_LANE2                           0x9d60
+#define mmCMD_BUS_TX_CONTROL_LANE3                                              0x4910
+#define mmDC_COMBOPHYTXREGS0_CMD_BUS_TX_CONTROL_LANE3                           0x4910
+#define mmDC_COMBOPHYTXREGS1_CMD_BUS_TX_CONTROL_LANE3                           0x49b0
+#define mmDC_COMBOPHYTXREGS2_CMD_BUS_TX_CONTROL_LANE3                           0x9a50
+#define mmDC_COMBOPHYTXREGS3_CMD_BUS_TX_CONTROL_LANE3                           0x9af0
+#define mmDC_COMBOPHYTXREGS4_CMD_BUS_TX_CONTROL_LANE3                           0x9b90
+#define mmDC_COMBOPHYTXREGS5_CMD_BUS_TX_CONTROL_LANE3                           0x9c30
+#define mmDC_COMBOPHYTXREGS6_CMD_BUS_TX_CONTROL_LANE3                           0x9cd0
+#define mmDC_COMBOPHYTXREGS7_CMD_BUS_TX_CONTROL_LANE3                           0x9d70
+#define mmMARGIN_DEEMPH_LANE0                                                   0x48e1
+#define mmDC_COMBOPHYTXREGS0_MARGIN_DEEMPH_LANE0                                0x48e1
+#define mmDC_COMBOPHYTXREGS1_MARGIN_DEEMPH_LANE0                                0x4981
+#define mmDC_COMBOPHYTXREGS2_MARGIN_DEEMPH_LANE0                                0x9a21
+#define mmDC_COMBOPHYTXREGS3_MARGIN_DEEMPH_LANE0                                0x9ac1
+#define mmDC_COMBOPHYTXREGS4_MARGIN_DEEMPH_LANE0                                0x9b61
+#define mmDC_COMBOPHYTXREGS5_MARGIN_DEEMPH_LANE0                                0x9c01
+#define mmDC_COMBOPHYTXREGS6_MARGIN_DEEMPH_LANE0                                0x9ca1
+#define mmDC_COMBOPHYTXREGS7_MARGIN_DEEMPH_LANE0                                0x9d41
+#define mmMARGIN_DEEMPH_LANE1                                                   0x48f1
+#define mmDC_COMBOPHYTXREGS0_MARGIN_DEEMPH_LANE1                                0x48f1
+#define mmDC_COMBOPHYTXREGS1_MARGIN_DEEMPH_LANE1                                0x4991
+#define mmDC_COMBOPHYTXREGS2_MARGIN_DEEMPH_LANE1                                0x9a31
+#define mmDC_COMBOPHYTXREGS3_MARGIN_DEEMPH_LANE1                                0x9ad1
+#define mmDC_COMBOPHYTXREGS4_MARGIN_DEEMPH_LANE1                                0x9b71
+#define mmDC_COMBOPHYTXREGS5_MARGIN_DEEMPH_LANE1                                0x9c11
+#define mmDC_COMBOPHYTXREGS6_MARGIN_DEEMPH_LANE1                                0x9cb1
+#define mmDC_COMBOPHYTXREGS7_MARGIN_DEEMPH_LANE1                                0x9d51
+#define mmMARGIN_DEEMPH_LANE2                                                   0x4901
+#define mmDC_COMBOPHYTXREGS0_MARGIN_DEEMPH_LANE2                                0x4901
+#define mmDC_COMBOPHYTXREGS1_MARGIN_DEEMPH_LANE2                                0x49a1
+#define mmDC_COMBOPHYTXREGS2_MARGIN_DEEMPH_LANE2                                0x9a41
+#define mmDC_COMBOPHYTXREGS3_MARGIN_DEEMPH_LANE2                                0x9ae1
+#define mmDC_COMBOPHYTXREGS4_MARGIN_DEEMPH_LANE2                                0x9b81
+#define mmDC_COMBOPHYTXREGS5_MARGIN_DEEMPH_LANE2                                0x9c21
+#define mmDC_COMBOPHYTXREGS6_MARGIN_DEEMPH_LANE2                                0x9cc1
+#define mmDC_COMBOPHYTXREGS7_MARGIN_DEEMPH_LANE2                                0x9d61
+#define mmMARGIN_DEEMPH_LANE3                                                   0x4911
+#define mmDC_COMBOPHYTXREGS0_MARGIN_DEEMPH_LANE3                                0x4911
+#define mmDC_COMBOPHYTXREGS1_MARGIN_DEEMPH_LANE3                                0x49b1
+#define mmDC_COMBOPHYTXREGS2_MARGIN_DEEMPH_LANE3                                0x9a51
+#define mmDC_COMBOPHYTXREGS3_MARGIN_DEEMPH_LANE3                                0x9af1
+#define mmDC_COMBOPHYTXREGS4_MARGIN_DEEMPH_LANE3                                0x9b91
+#define mmDC_COMBOPHYTXREGS5_MARGIN_DEEMPH_LANE3                                0x9c31
+#define mmDC_COMBOPHYTXREGS6_MARGIN_DEEMPH_LANE3                                0x9cd1
+#define mmDC_COMBOPHYTXREGS7_MARGIN_DEEMPH_LANE3                                0x9d71
+#define mmCMD_BUS_GLOBAL_FOR_TX_LANE0                                           0x48e2
+#define mmDC_COMBOPHYTXREGS0_CMD_BUS_GLOBAL_FOR_TX_LANE0                        0x48e2
+#define mmDC_COMBOPHYTXREGS1_CMD_BUS_GLOBAL_FOR_TX_LANE0                        0x4982
+#define mmDC_COMBOPHYTXREGS2_CMD_BUS_GLOBAL_FOR_TX_LANE0                        0x9a22
+#define mmDC_COMBOPHYTXREGS3_CMD_BUS_GLOBAL_FOR_TX_LANE0                        0x9ac2
+#define mmDC_COMBOPHYTXREGS4_CMD_BUS_GLOBAL_FOR_TX_LANE0                        0x9b62
+#define mmDC_COMBOPHYTXREGS5_CMD_BUS_GLOBAL_FOR_TX_LANE0                        0x9c02
+#define mmDC_COMBOPHYTXREGS6_CMD_BUS_GLOBAL_FOR_TX_LANE0                        0x9ca2
+#define mmDC_COMBOPHYTXREGS7_CMD_BUS_GLOBAL_FOR_TX_LANE0                        0x9d42
+#define mmCMD_BUS_GLOBAL_FOR_TX_LANE1                                           0x48f2
+#define mmDC_COMBOPHYTXREGS0_CMD_BUS_GLOBAL_FOR_TX_LANE1                        0x48f2
+#define mmDC_COMBOPHYTXREGS1_CMD_BUS_GLOBAL_FOR_TX_LANE1                        0x4992
+#define mmDC_COMBOPHYTXREGS2_CMD_BUS_GLOBAL_FOR_TX_LANE1                        0x9a32
+#define mmDC_COMBOPHYTXREGS3_CMD_BUS_GLOBAL_FOR_TX_LANE1                        0x9ad2
+#define mmDC_COMBOPHYTXREGS4_CMD_BUS_GLOBAL_FOR_TX_LANE1                        0x9b72
+#define mmDC_COMBOPHYTXREGS5_CMD_BUS_GLOBAL_FOR_TX_LANE1                        0x9c12
+#define mmDC_COMBOPHYTXREGS6_CMD_BUS_GLOBAL_FOR_TX_LANE1                        0x9cb2
+#define mmDC_COMBOPHYTXREGS7_CMD_BUS_GLOBAL_FOR_TX_LANE1                        0x9d52
+#define mmCMD_BUS_GLOBAL_FOR_TX_LANE2                                           0x4902
+#define mmDC_COMBOPHYTXREGS0_CMD_BUS_GLOBAL_FOR_TX_LANE2                        0x4902
+#define mmDC_COMBOPHYTXREGS1_CMD_BUS_GLOBAL_FOR_TX_LANE2                        0x49a2
+#define mmDC_COMBOPHYTXREGS2_CMD_BUS_GLOBAL_FOR_TX_LANE2                        0x9a42
+#define mmDC_COMBOPHYTXREGS3_CMD_BUS_GLOBAL_FOR_TX_LANE2                        0x9ae2
+#define mmDC_COMBOPHYTXREGS4_CMD_BUS_GLOBAL_FOR_TX_LANE2                        0x9b82
+#define mmDC_COMBOPHYTXREGS5_CMD_BUS_GLOBAL_FOR_TX_LANE2                        0x9c22
+#define mmDC_COMBOPHYTXREGS6_CMD_BUS_GLOBAL_FOR_TX_LANE2                        0x9cc2
+#define mmDC_COMBOPHYTXREGS7_CMD_BUS_GLOBAL_FOR_TX_LANE2                        0x9d62
+#define mmCMD_BUS_GLOBAL_FOR_TX_LANE3                                           0x4912
+#define mmDC_COMBOPHYTXREGS0_CMD_BUS_GLOBAL_FOR_TX_LANE3                        0x4912
+#define mmDC_COMBOPHYTXREGS1_CMD_BUS_GLOBAL_FOR_TX_LANE3                        0x49b2
+#define mmDC_COMBOPHYTXREGS2_CMD_BUS_GLOBAL_FOR_TX_LANE3                        0x9a52
+#define mmDC_COMBOPHYTXREGS3_CMD_BUS_GLOBAL_FOR_TX_LANE3                        0x9af2
+#define mmDC_COMBOPHYTXREGS4_CMD_BUS_GLOBAL_FOR_TX_LANE3                        0x9b92
+#define mmDC_COMBOPHYTXREGS5_CMD_BUS_GLOBAL_FOR_TX_LANE3                        0x9c32
+#define mmDC_COMBOPHYTXREGS6_CMD_BUS_GLOBAL_FOR_TX_LANE3                        0x9cd2
+#define mmDC_COMBOPHYTXREGS7_CMD_BUS_GLOBAL_FOR_TX_LANE3                        0x9d72
+#define mmTX_DISP_RFU0_LANE0                                                    0x48e3
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU0_LANE0                                 0x48e3
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU0_LANE0                                 0x4983
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU0_LANE0                                 0x9a23
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU0_LANE0                                 0x9ac3
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU0_LANE0                                 0x9b63
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU0_LANE0                                 0x9c03
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU0_LANE0                                 0x9ca3
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU0_LANE0                                 0x9d43
+#define mmTX_DISP_RFU0_LANE1                                                    0x48f3
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU0_LANE1                                 0x48f3
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU0_LANE1                                 0x4993
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU0_LANE1                                 0x9a33
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU0_LANE1                                 0x9ad3
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU0_LANE1                                 0x9b73
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU0_LANE1                                 0x9c13
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU0_LANE1                                 0x9cb3
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU0_LANE1                                 0x9d53
+#define mmTX_DISP_RFU0_LANE2                                                    0x4903
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU0_LANE2                                 0x4903
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU0_LANE2                                 0x49a3
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU0_LANE2                                 0x9a43
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU0_LANE2                                 0x9ae3
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU0_LANE2                                 0x9b83
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU0_LANE2                                 0x9c23
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU0_LANE2                                 0x9cc3
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU0_LANE2                                 0x9d63
+#define mmTX_DISP_RFU0_LANE3                                                    0x4913
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU0_LANE3                                 0x4913
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU0_LANE3                                 0x49b3
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU0_LANE3                                 0x9a53
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU0_LANE3                                 0x9af3
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU0_LANE3                                 0x9b93
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU0_LANE3                                 0x9c33
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU0_LANE3                                 0x9cd3
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU0_LANE3                                 0x9d73
+#define mmTX_DISP_RFU1_LANE0                                                    0x48e4
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU1_LANE0                                 0x48e4
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU1_LANE0                                 0x4984
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU1_LANE0                                 0x9a24
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU1_LANE0                                 0x9ac4
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU1_LANE0                                 0x9b64
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU1_LANE0                                 0x9c04
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU1_LANE0                                 0x9ca4
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU1_LANE0                                 0x9d44
+#define mmTX_DISP_RFU1_LANE1                                                    0x48f4
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU1_LANE1                                 0x48f4
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU1_LANE1                                 0x4994
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU1_LANE1                                 0x9a34
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU1_LANE1                                 0x9ad4
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU1_LANE1                                 0x9b74
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU1_LANE1                                 0x9c14
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU1_LANE1                                 0x9cb4
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU1_LANE1                                 0x9d54
+#define mmTX_DISP_RFU1_LANE2                                                    0x4904
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU1_LANE2                                 0x4904
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU1_LANE2                                 0x49a4
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU1_LANE2                                 0x9a44
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU1_LANE2                                 0x9ae4
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU1_LANE2                                 0x9b84
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU1_LANE2                                 0x9c24
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU1_LANE2                                 0x9cc4
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU1_LANE2                                 0x9d64
+#define mmTX_DISP_RFU1_LANE3                                                    0x4914
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU1_LANE3                                 0x4914
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU1_LANE3                                 0x49b4
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU1_LANE3                                 0x9a54
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU1_LANE3                                 0x9af4
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU1_LANE3                                 0x9b94
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU1_LANE3                                 0x9c34
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU1_LANE3                                 0x9cd4
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU1_LANE3                                 0x9d74
+#define mmTX_DISP_RFU2_LANE0                                                    0x48e5
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU2_LANE0                                 0x48e5
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU2_LANE0                                 0x4985
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU2_LANE0                                 0x9a25
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU2_LANE0                                 0x9ac5
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU2_LANE0                                 0x9b65
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU2_LANE0                                 0x9c05
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU2_LANE0                                 0x9ca5
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU2_LANE0                                 0x9d45
+#define mmTX_DISP_RFU2_LANE1                                                    0x48f5
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU2_LANE1                                 0x48f5
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU2_LANE1                                 0x4995
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU2_LANE1                                 0x9a35
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU2_LANE1                                 0x9ad5
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU2_LANE1                                 0x9b75
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU2_LANE1                                 0x9c15
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU2_LANE1                                 0x9cb5
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU2_LANE1                                 0x9d55
+#define mmTX_DISP_RFU2_LANE2                                                    0x4905
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU2_LANE2                                 0x4905
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU2_LANE2                                 0x49a5
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU2_LANE2                                 0x9a45
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU2_LANE2                                 0x9ae5
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU2_LANE2                                 0x9b85
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU2_LANE2                                 0x9c25
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU2_LANE2                                 0x9cc5
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU2_LANE2                                 0x9d65
+#define mmTX_DISP_RFU2_LANE3                                                    0x4915
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU2_LANE3                                 0x4915
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU2_LANE3                                 0x49b5
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU2_LANE3                                 0x9a55
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU2_LANE3                                 0x9af5
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU2_LANE3                                 0x9b95
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU2_LANE3                                 0x9c35
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU2_LANE3                                 0x9cd5
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU2_LANE3                                 0x9d75
+#define mmTX_DISP_RFU3_LANE0                                                    0x48e6
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU3_LANE0                                 0x48e6
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU3_LANE0                                 0x4986
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU3_LANE0                                 0x9a26
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU3_LANE0                                 0x9ac6
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU3_LANE0                                 0x9b66
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU3_LANE0                                 0x9c06
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU3_LANE0                                 0x9ca6
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU3_LANE0                                 0x9d46
+#define mmTX_DISP_RFU3_LANE1                                                    0x48f6
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU3_LANE1                                 0x48f6
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU3_LANE1                                 0x4996
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU3_LANE1                                 0x9a36
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU3_LANE1                                 0x9ad6
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU3_LANE1                                 0x9b76
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU3_LANE1                                 0x9c16
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU3_LANE1                                 0x9cb6
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU3_LANE1                                 0x9d56
+#define mmTX_DISP_RFU3_LANE2                                                    0x4906
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU3_LANE2                                 0x4906
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU3_LANE2                                 0x49a6
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU3_LANE2                                 0x9a46
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU3_LANE2                                 0x9ae6
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU3_LANE2                                 0x9b86
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU3_LANE2                                 0x9c26
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU3_LANE2                                 0x9cc6
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU3_LANE2                                 0x9d66
+#define mmTX_DISP_RFU3_LANE3                                                    0x4916
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU3_LANE3                                 0x4916
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU3_LANE3                                 0x49b6
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU3_LANE3                                 0x9a56
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU3_LANE3                                 0x9af6
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU3_LANE3                                 0x9b96
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU3_LANE3                                 0x9c36
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU3_LANE3                                 0x9cd6
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU3_LANE3                                 0x9d76
+#define mmTX_DISP_RFU4_LANE0                                                    0x48e7
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU4_LANE0                                 0x48e7
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU4_LANE0                                 0x4987
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU4_LANE0                                 0x9a27
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU4_LANE0                                 0x9ac7
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU4_LANE0                                 0x9b67
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU4_LANE0                                 0x9c07
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU4_LANE0                                 0x9ca7
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU4_LANE0                                 0x9d47
+#define mmTX_DISP_RFU4_LANE1                                                    0x48f7
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU4_LANE1                                 0x48f7
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU4_LANE1                                 0x4997
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU4_LANE1                                 0x9a37
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU4_LANE1                                 0x9ad7
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU4_LANE1                                 0x9b77
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU4_LANE1                                 0x9c17
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU4_LANE1                                 0x9cb7
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU4_LANE1                                 0x9d57
+#define mmTX_DISP_RFU4_LANE2                                                    0x4907
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU4_LANE2                                 0x4907
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU4_LANE2                                 0x49a7
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU4_LANE2                                 0x9a47
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU4_LANE2                                 0x9ae7
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU4_LANE2                                 0x9b87
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU4_LANE2                                 0x9c27
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU4_LANE2                                 0x9cc7
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU4_LANE2                                 0x9d67
+#define mmTX_DISP_RFU4_LANE3                                                    0x4917
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU4_LANE3                                 0x4917
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU4_LANE3                                 0x49b7
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU4_LANE3                                 0x9a57
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU4_LANE3                                 0x9af7
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU4_LANE3                                 0x9b97
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU4_LANE3                                 0x9c37
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU4_LANE3                                 0x9cd7
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU4_LANE3                                 0x9d77
+#define mmTX_DISP_RFU5_LANE0                                                    0x48e8
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU5_LANE0                                 0x48e8
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU5_LANE0                                 0x4988
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU5_LANE0                                 0x9a28
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU5_LANE0                                 0x9ac8
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU5_LANE0                                 0x9b68
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU5_LANE0                                 0x9c08
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU5_LANE0                                 0x9ca8
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU5_LANE0                                 0x9d48
+#define mmTX_DISP_RFU5_LANE1                                                    0x48f8
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU5_LANE1                                 0x48f8
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU5_LANE1                                 0x4998
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU5_LANE1                                 0x9a38
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU5_LANE1                                 0x9ad8
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU5_LANE1                                 0x9b78
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU5_LANE1                                 0x9c18
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU5_LANE1                                 0x9cb8
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU5_LANE1                                 0x9d58
+#define mmTX_DISP_RFU5_LANE2                                                    0x4908
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU5_LANE2                                 0x4908
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU5_LANE2                                 0x49a8
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU5_LANE2                                 0x9a48
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU5_LANE2                                 0x9ae8
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU5_LANE2                                 0x9b88
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU5_LANE2                                 0x9c28
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU5_LANE2                                 0x9cc8
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU5_LANE2                                 0x9d68
+#define mmTX_DISP_RFU5_LANE3                                                    0x4918
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU5_LANE3                                 0x4918
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU5_LANE3                                 0x49b8
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU5_LANE3                                 0x9a58
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU5_LANE3                                 0x9af8
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU5_LANE3                                 0x9b98
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU5_LANE3                                 0x9c38
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU5_LANE3                                 0x9cd8
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU5_LANE3                                 0x9d78
+#define mmTX_DISP_RFU6_LANE0                                                    0x48e9
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU6_LANE0                                 0x48e9
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU6_LANE0                                 0x4989
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU6_LANE0                                 0x9a29
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU6_LANE0                                 0x9ac9
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU6_LANE0                                 0x9b69
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU6_LANE0                                 0x9c09
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU6_LANE0                                 0x9ca9
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU6_LANE0                                 0x9d49
+#define mmTX_DISP_RFU6_LANE1                                                    0x48f9
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU6_LANE1                                 0x48f9
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU6_LANE1                                 0x4999
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU6_LANE1                                 0x9a39
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU6_LANE1                                 0x9ad9
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU6_LANE1                                 0x9b79
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU6_LANE1                                 0x9c19
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU6_LANE1                                 0x9cb9
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU6_LANE1                                 0x9d59
+#define mmTX_DISP_RFU6_LANE2                                                    0x4909
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU6_LANE2                                 0x4909
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU6_LANE2                                 0x49a9
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU6_LANE2                                 0x9a49
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU6_LANE2                                 0x9ae9
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU6_LANE2                                 0x9b89
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU6_LANE2                                 0x9c29
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU6_LANE2                                 0x9cc9
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU6_LANE2                                 0x9d69
+#define mmTX_DISP_RFU6_LANE3                                                    0x4919
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU6_LANE3                                 0x4919
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU6_LANE3                                 0x49b9
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU6_LANE3                                 0x9a59
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU6_LANE3                                 0x9af9
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU6_LANE3                                 0x9b99
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU6_LANE3                                 0x9c39
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU6_LANE3                                 0x9cd9
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU6_LANE3                                 0x9d79
+#define mmTX_DISP_RFU7_LANE0                                                    0x48ea
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU7_LANE0                                 0x48ea
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU7_LANE0                                 0x498a
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU7_LANE0                                 0x9a2a
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU7_LANE0                                 0x9aca
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU7_LANE0                                 0x9b6a
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU7_LANE0                                 0x9c0a
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU7_LANE0                                 0x9caa
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU7_LANE0                                 0x9d4a
+#define mmTX_DISP_RFU7_LANE1                                                    0x48fa
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU7_LANE1                                 0x48fa
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU7_LANE1                                 0x499a
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU7_LANE1                                 0x9a3a
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU7_LANE1                                 0x9ada
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU7_LANE1                                 0x9b7a
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU7_LANE1                                 0x9c1a
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU7_LANE1                                 0x9cba
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU7_LANE1                                 0x9d5a
+#define mmTX_DISP_RFU7_LANE2                                                    0x490a
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU7_LANE2                                 0x490a
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU7_LANE2                                 0x49aa
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU7_LANE2                                 0x9a4a
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU7_LANE2                                 0x9aea
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU7_LANE2                                 0x9b8a
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU7_LANE2                                 0x9c2a
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU7_LANE2                                 0x9cca
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU7_LANE2                                 0x9d6a
+#define mmTX_DISP_RFU7_LANE3                                                    0x491a
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU7_LANE3                                 0x491a
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU7_LANE3                                 0x49ba
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU7_LANE3                                 0x9a5a
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU7_LANE3                                 0x9afa
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU7_LANE3                                 0x9b9a
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU7_LANE3                                 0x9c3a
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU7_LANE3                                 0x9cda
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU7_LANE3                                 0x9d7a
+#define mmTX_DISP_RFU8_LANE0                                                    0x48eb
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU8_LANE0                                 0x48eb
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU8_LANE0                                 0x498b
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU8_LANE0                                 0x9a2b
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU8_LANE0                                 0x9acb
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU8_LANE0                                 0x9b6b
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU8_LANE0                                 0x9c0b
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU8_LANE0                                 0x9cab
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU8_LANE0                                 0x9d4b
+#define mmTX_DISP_RFU8_LANE1                                                    0x48fb
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU8_LANE1                                 0x48fb
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU8_LANE1                                 0x499b
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU8_LANE1                                 0x9a3b
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU8_LANE1                                 0x9adb
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU8_LANE1                                 0x9b7b
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU8_LANE1                                 0x9c1b
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU8_LANE1                                 0x9cbb
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU8_LANE1                                 0x9d5b
+#define mmTX_DISP_RFU8_LANE2                                                    0x490b
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU8_LANE2                                 0x490b
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU8_LANE2                                 0x49ab
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU8_LANE2                                 0x9a4b
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU8_LANE2                                 0x9aeb
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU8_LANE2                                 0x9b8b
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU8_LANE2                                 0x9c2b
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU8_LANE2                                 0x9ccb
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU8_LANE2                                 0x9d6b
+#define mmTX_DISP_RFU8_LANE3                                                    0x491b
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU8_LANE3                                 0x491b
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU8_LANE3                                 0x49bb
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU8_LANE3                                 0x9a5b
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU8_LANE3                                 0x9afb
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU8_LANE3                                 0x9b9b
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU8_LANE3                                 0x9c3b
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU8_LANE3                                 0x9cdb
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU8_LANE3                                 0x9d7b
+#define mmTX_DISP_RFU9_LANE0                                                    0x48ec
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU9_LANE0                                 0x48ec
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU9_LANE0                                 0x498c
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU9_LANE0                                 0x9a2c
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU9_LANE0                                 0x9acc
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU9_LANE0                                 0x9b6c
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU9_LANE0                                 0x9c0c
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU9_LANE0                                 0x9cac
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU9_LANE0                                 0x9d4c
+#define mmTX_DISP_RFU9_LANE1                                                    0x48fc
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU9_LANE1                                 0x48fc
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU9_LANE1                                 0x499c
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU9_LANE1                                 0x9a3c
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU9_LANE1                                 0x9adc
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU9_LANE1                                 0x9b7c
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU9_LANE1                                 0x9c1c
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU9_LANE1                                 0x9cbc
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU9_LANE1                                 0x9d5c
+#define mmTX_DISP_RFU9_LANE2                                                    0x490c
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU9_LANE2                                 0x490c
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU9_LANE2                                 0x49ac
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU9_LANE2                                 0x9a4c
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU9_LANE2                                 0x9aec
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU9_LANE2                                 0x9b8c
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU9_LANE2                                 0x9c2c
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU9_LANE2                                 0x9ccc
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU9_LANE2                                 0x9d6c
+#define mmTX_DISP_RFU9_LANE3                                                    0x491c
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU9_LANE3                                 0x491c
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU9_LANE3                                 0x49bc
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU9_LANE3                                 0x9a5c
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU9_LANE3                                 0x9afc
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU9_LANE3                                 0x9b9c
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU9_LANE3                                 0x9c3c
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU9_LANE3                                 0x9cdc
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU9_LANE3                                 0x9d7c
+#define mmTX_DISP_RFU10_LANE0                                                   0x48ed
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU10_LANE0                                0x48ed
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU10_LANE0                                0x498d
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU10_LANE0                                0x9a2d
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU10_LANE0                                0x9acd
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU10_LANE0                                0x9b6d
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU10_LANE0                                0x9c0d
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU10_LANE0                                0x9cad
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU10_LANE0                                0x9d4d
+#define mmTX_DISP_RFU10_LANE1                                                   0x48fd
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU10_LANE1                                0x48fd
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU10_LANE1                                0x499d
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU10_LANE1                                0x9a3d
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU10_LANE1                                0x9add
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU10_LANE1                                0x9b7d
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU10_LANE1                                0x9c1d
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU10_LANE1                                0x9cbd
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU10_LANE1                                0x9d5d
+#define mmTX_DISP_RFU10_LANE2                                                   0x490d
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU10_LANE2                                0x490d
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU10_LANE2                                0x49ad
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU10_LANE2                                0x9a4d
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU10_LANE2                                0x9aed
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU10_LANE2                                0x9b8d
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU10_LANE2                                0x9c2d
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU10_LANE2                                0x9ccd
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU10_LANE2                                0x9d6d
+#define mmTX_DISP_RFU10_LANE3                                                   0x491d
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU10_LANE3                                0x491d
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU10_LANE3                                0x49bd
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU10_LANE3                                0x9a5d
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU10_LANE3                                0x9afd
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU10_LANE3                                0x9b9d
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU10_LANE3                                0x9c3d
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU10_LANE3                                0x9cdd
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU10_LANE3                                0x9d7d
+#define mmTX_DISP_RFU11_LANE0                                                   0x48ee
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU11_LANE0                                0x48ee
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU11_LANE0                                0x498e
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU11_LANE0                                0x9a2e
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU11_LANE0                                0x9ace
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU11_LANE0                                0x9b6e
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU11_LANE0                                0x9c0e
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU11_LANE0                                0x9cae
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU11_LANE0                                0x9d4e
+#define mmTX_DISP_RFU11_LANE1                                                   0x48fe
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU11_LANE1                                0x48fe
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU11_LANE1                                0x499e
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU11_LANE1                                0x9a3e
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU11_LANE1                                0x9ade
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU11_LANE1                                0x9b7e
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU11_LANE1                                0x9c1e
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU11_LANE1                                0x9cbe
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU11_LANE1                                0x9d5e
+#define mmTX_DISP_RFU11_LANE2                                                   0x490e
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU11_LANE2                                0x490e
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU11_LANE2                                0x49ae
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU11_LANE2                                0x9a4e
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU11_LANE2                                0x9aee
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU11_LANE2                                0x9b8e
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU11_LANE2                                0x9c2e
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU11_LANE2                                0x9cce
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU11_LANE2                                0x9d6e
+#define mmTX_DISP_RFU11_LANE3                                                   0x491e
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU11_LANE3                                0x491e
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU11_LANE3                                0x49be
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU11_LANE3                                0x9a5e
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU11_LANE3                                0x9afe
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU11_LANE3                                0x9b9e
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU11_LANE3                                0x9c3e
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU11_LANE3                                0x9cde
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU11_LANE3                                0x9d7e
+#define mmTX_DISP_RFU12_LANE0                                                   0x48ef
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU12_LANE0                                0x48ef
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU12_LANE0                                0x498f
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU12_LANE0                                0x9a2f
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU12_LANE0                                0x9acf
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU12_LANE0                                0x9b6f
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU12_LANE0                                0x9c0f
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU12_LANE0                                0x9caf
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU12_LANE0                                0x9d4f
+#define mmTX_DISP_RFU12_LANE1                                                   0x48ff
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU12_LANE1                                0x48ff
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU12_LANE1                                0x499f
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU12_LANE1                                0x9a3f
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU12_LANE1                                0x9adf
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU12_LANE1                                0x9b7f
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU12_LANE1                                0x9c1f
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU12_LANE1                                0x9cbf
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU12_LANE1                                0x9d5f
+#define mmTX_DISP_RFU12_LANE2                                                   0x490f
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU12_LANE2                                0x490f
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU12_LANE2                                0x49af
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU12_LANE2                                0x9a4f
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU12_LANE2                                0x9aef
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU12_LANE2                                0x9b8f
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU12_LANE2                                0x9c2f
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU12_LANE2                                0x9ccf
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU12_LANE2                                0x9d6f
+#define mmTX_DISP_RFU12_LANE3                                                   0x491f
+#define mmDC_COMBOPHYTXREGS0_TX_DISP_RFU12_LANE3                                0x491f
+#define mmDC_COMBOPHYTXREGS1_TX_DISP_RFU12_LANE3                                0x49bf
+#define mmDC_COMBOPHYTXREGS2_TX_DISP_RFU12_LANE3                                0x9a5f
+#define mmDC_COMBOPHYTXREGS3_TX_DISP_RFU12_LANE3                                0x9aff
+#define mmDC_COMBOPHYTXREGS4_TX_DISP_RFU12_LANE3                                0x9b9f
+#define mmDC_COMBOPHYTXREGS5_TX_DISP_RFU12_LANE3                                0x9c3f
+#define mmDC_COMBOPHYTXREGS6_TX_DISP_RFU12_LANE3                                0x9cdf
+#define mmDC_COMBOPHYTXREGS7_TX_DISP_RFU12_LANE3                                0x9d7f
+#define mmCOMMON_MAR_DEEMPH_NOM                                                 0x48c3
+#define mmDC_COMBOPHYCMREGS0_COMMON_MAR_DEEMPH_NOM                              0x48c3
+#define mmDC_COMBOPHYCMREGS1_COMMON_MAR_DEEMPH_NOM                              0x4963
+#define mmDC_COMBOPHYCMREGS2_COMMON_MAR_DEEMPH_NOM                              0x9a03
+#define mmDC_COMBOPHYCMREGS3_COMMON_MAR_DEEMPH_NOM                              0x9aa3
+#define mmDC_COMBOPHYCMREGS4_COMMON_MAR_DEEMPH_NOM                              0x9b43
+#define mmDC_COMBOPHYCMREGS5_COMMON_MAR_DEEMPH_NOM                              0x9be3
+#define mmDC_COMBOPHYCMREGS6_COMMON_MAR_DEEMPH_NOM                              0x9c83
+#define mmDC_COMBOPHYCMREGS7_COMMON_MAR_DEEMPH_NOM                              0x9d23
+#define mmCOMMON_LANE_PWRMGMT                                                   0x48c4
+#define mmDC_COMBOPHYCMREGS0_COMMON_LANE_PWRMGMT                                0x48c4
+#define mmDC_COMBOPHYCMREGS1_COMMON_LANE_PWRMGMT                                0x4964
+#define mmDC_COMBOPHYCMREGS2_COMMON_LANE_PWRMGMT                                0x9a04
+#define mmDC_COMBOPHYCMREGS3_COMMON_LANE_PWRMGMT                                0x9aa4
+#define mmDC_COMBOPHYCMREGS4_COMMON_LANE_PWRMGMT                                0x9b44
+#define mmDC_COMBOPHYCMREGS5_COMMON_LANE_PWRMGMT                                0x9be4
+#define mmDC_COMBOPHYCMREGS6_COMMON_LANE_PWRMGMT                                0x9c84
+#define mmDC_COMBOPHYCMREGS7_COMMON_LANE_PWRMGMT                                0x9d24
+#define mmCOMMON_TXCNTRL                                                        0x48c5
+#define mmDC_COMBOPHYCMREGS0_COMMON_TXCNTRL                                     0x48c5
+#define mmDC_COMBOPHYCMREGS1_COMMON_TXCNTRL                                     0x4965
+#define mmDC_COMBOPHYCMREGS2_COMMON_TXCNTRL                                     0x9a05
+#define mmDC_COMBOPHYCMREGS3_COMMON_TXCNTRL                                     0x9aa5
+#define mmDC_COMBOPHYCMREGS4_COMMON_TXCNTRL                                     0x9b45
+#define mmDC_COMBOPHYCMREGS5_COMMON_TXCNTRL                                     0x9be5
+#define mmDC_COMBOPHYCMREGS6_COMMON_TXCNTRL                                     0x9c85
+#define mmDC_COMBOPHYCMREGS7_COMMON_TXCNTRL                                     0x9d25
+#define mmCOMMON_TMDP                                                           0x48c6
+#define mmDC_COMBOPHYCMREGS0_COMMON_TMDP                                        0x48c6
+#define mmDC_COMBOPHYCMREGS1_COMMON_TMDP                                        0x4966
+#define mmDC_COMBOPHYCMREGS2_COMMON_TMDP                                        0x9a06
+#define mmDC_COMBOPHYCMREGS3_COMMON_TMDP                                        0x9aa6
+#define mmDC_COMBOPHYCMREGS4_COMMON_TMDP                                        0x9b46
+#define mmDC_COMBOPHYCMREGS5_COMMON_TMDP                                        0x9be6
+#define mmDC_COMBOPHYCMREGS6_COMMON_TMDP                                        0x9c86
+#define mmDC_COMBOPHYCMREGS7_COMMON_TMDP                                        0x9d26
+#define mmCOMMON_LANE_RESETS                                                    0x48c7
+#define mmDC_COMBOPHYCMREGS0_COMMON_LANE_RESETS                                 0x48c7
+#define mmDC_COMBOPHYCMREGS1_COMMON_LANE_RESETS                                 0x4967
+#define mmDC_COMBOPHYCMREGS2_COMMON_LANE_RESETS                                 0x9a07
+#define mmDC_COMBOPHYCMREGS3_COMMON_LANE_RESETS                                 0x9aa7
+#define mmDC_COMBOPHYCMREGS4_COMMON_LANE_RESETS                                 0x9b47
+#define mmDC_COMBOPHYCMREGS5_COMMON_LANE_RESETS                                 0x9be7
+#define mmDC_COMBOPHYCMREGS6_COMMON_LANE_RESETS                                 0x9c87
+#define mmDC_COMBOPHYCMREGS7_COMMON_LANE_RESETS                                 0x9d27
+#define mmCOMMON_ZCALCODE_CTRL                                                  0x48c8
+#define mmDC_COMBOPHYCMREGS0_COMMON_ZCALCODE_CTRL                               0x48c8
+#define mmDC_COMBOPHYCMREGS1_COMMON_ZCALCODE_CTRL                               0x4968
+#define mmDC_COMBOPHYCMREGS2_COMMON_ZCALCODE_CTRL                               0x9a08
+#define mmDC_COMBOPHYCMREGS3_COMMON_ZCALCODE_CTRL                               0x9aa8
+#define mmDC_COMBOPHYCMREGS4_COMMON_ZCALCODE_CTRL                               0x9b48
+#define mmDC_COMBOPHYCMREGS5_COMMON_ZCALCODE_CTRL                               0x9be8
+#define mmDC_COMBOPHYCMREGS6_COMMON_ZCALCODE_CTRL                               0x9c88
+#define mmDC_COMBOPHYCMREGS7_COMMON_ZCALCODE_CTRL                               0x9d28
+#define mmCOMMON_DISP_RFU1                                                      0x48c9
+#define mmDC_COMBOPHYCMREGS0_COMMON_DISP_RFU1                                   0x48c9
+#define mmDC_COMBOPHYCMREGS1_COMMON_DISP_RFU1                                   0x4969
+#define mmDC_COMBOPHYCMREGS2_COMMON_DISP_RFU1                                   0x9a09
+#define mmDC_COMBOPHYCMREGS3_COMMON_DISP_RFU1                                   0x9aa9
+#define mmDC_COMBOPHYCMREGS4_COMMON_DISP_RFU1                                   0x9b49
+#define mmDC_COMBOPHYCMREGS5_COMMON_DISP_RFU1                                   0x9be9
+#define mmDC_COMBOPHYCMREGS6_COMMON_DISP_RFU1                                   0x9c89
+#define mmDC_COMBOPHYCMREGS7_COMMON_DISP_RFU1                                   0x9d29
+#define mmCOMMON_DISP_RFU2                                                      0x48ca
+#define mmDC_COMBOPHYCMREGS0_COMMON_DISP_RFU2                                   0x48ca
+#define mmDC_COMBOPHYCMREGS1_COMMON_DISP_RFU2                                   0x496a
+#define mmDC_COMBOPHYCMREGS2_COMMON_DISP_RFU2                                   0x9a0a
+#define mmDC_COMBOPHYCMREGS3_COMMON_DISP_RFU2                                   0x9aaa
+#define mmDC_COMBOPHYCMREGS4_COMMON_DISP_RFU2                                   0x9b4a
+#define mmDC_COMBOPHYCMREGS5_COMMON_DISP_RFU2                                   0x9bea
+#define mmDC_COMBOPHYCMREGS6_COMMON_DISP_RFU2                                   0x9c8a
+#define mmDC_COMBOPHYCMREGS7_COMMON_DISP_RFU2                                   0x9d2a
+#define mmCOMMON_DISP_RFU3                                                      0x48cb
+#define mmDC_COMBOPHYCMREGS0_COMMON_DISP_RFU3                                   0x48cb
+#define mmDC_COMBOPHYCMREGS1_COMMON_DISP_RFU3                                   0x496b
+#define mmDC_COMBOPHYCMREGS2_COMMON_DISP_RFU3                                   0x9a0b
+#define mmDC_COMBOPHYCMREGS3_COMMON_DISP_RFU3                                   0x9aab
+#define mmDC_COMBOPHYCMREGS4_COMMON_DISP_RFU3                                   0x9b4b
+#define mmDC_COMBOPHYCMREGS5_COMMON_DISP_RFU3                                   0x9beb
+#define mmDC_COMBOPHYCMREGS6_COMMON_DISP_RFU3                                   0x9c8b
+#define mmDC_COMBOPHYCMREGS7_COMMON_DISP_RFU3                                   0x9d2b
+#define mmCOMMON_DISP_RFU4                                                      0x48cc
+#define mmDC_COMBOPHYCMREGS0_COMMON_DISP_RFU4                                   0x48cc
+#define mmDC_COMBOPHYCMREGS1_COMMON_DISP_RFU4                                   0x496c
+#define mmDC_COMBOPHYCMREGS2_COMMON_DISP_RFU4                                   0x9a0c
+#define mmDC_COMBOPHYCMREGS3_COMMON_DISP_RFU4                                   0x9aac
+#define mmDC_COMBOPHYCMREGS4_COMMON_DISP_RFU4                                   0x9b4c
+#define mmDC_COMBOPHYCMREGS5_COMMON_DISP_RFU4                                   0x9bec
+#define mmDC_COMBOPHYCMREGS6_COMMON_DISP_RFU4                                   0x9c8c
+#define mmDC_COMBOPHYCMREGS7_COMMON_DISP_RFU4                                   0x9d2c
+#define mmCOMMON_DISP_RFU5                                                      0x48cd
+#define mmDC_COMBOPHYCMREGS0_COMMON_DISP_RFU5                                   0x48cd
+#define mmDC_COMBOPHYCMREGS1_COMMON_DISP_RFU5                                   0x496d
+#define mmDC_COMBOPHYCMREGS2_COMMON_DISP_RFU5                                   0x9a0d
+#define mmDC_COMBOPHYCMREGS3_COMMON_DISP_RFU5                                   0x9aad
+#define mmDC_COMBOPHYCMREGS4_COMMON_DISP_RFU5                                   0x9b4d
+#define mmDC_COMBOPHYCMREGS5_COMMON_DISP_RFU5                                   0x9bed
+#define mmDC_COMBOPHYCMREGS6_COMMON_DISP_RFU5                                   0x9c8d
+#define mmDC_COMBOPHYCMREGS7_COMMON_DISP_RFU5                                   0x9d2d
+#define mmCOMMON_DISP_RFU6                                                      0x48ce
+#define mmDC_COMBOPHYCMREGS0_COMMON_DISP_RFU6                                   0x48ce
+#define mmDC_COMBOPHYCMREGS1_COMMON_DISP_RFU6                                   0x496e
+#define mmDC_COMBOPHYCMREGS2_COMMON_DISP_RFU6                                   0x9a0e
+#define mmDC_COMBOPHYCMREGS3_COMMON_DISP_RFU6                                   0x9aae
+#define mmDC_COMBOPHYCMREGS4_COMMON_DISP_RFU6                                   0x9b4e
+#define mmDC_COMBOPHYCMREGS5_COMMON_DISP_RFU6                                   0x9bee
+#define mmDC_COMBOPHYCMREGS6_COMMON_DISP_RFU6                                   0x9c8e
+#define mmDC_COMBOPHYCMREGS7_COMMON_DISP_RFU6                                   0x9d2e
+#define mmCOMMON_DISP_RFU7                                                      0x48cf
+#define mmDC_COMBOPHYCMREGS0_COMMON_DISP_RFU7                                   0x48cf
+#define mmDC_COMBOPHYCMREGS1_COMMON_DISP_RFU7                                   0x496f
+#define mmDC_COMBOPHYCMREGS2_COMMON_DISP_RFU7                                   0x9a0f
+#define mmDC_COMBOPHYCMREGS3_COMMON_DISP_RFU7                                   0x9aaf
+#define mmDC_COMBOPHYCMREGS4_COMMON_DISP_RFU7                                   0x9b4f
+#define mmDC_COMBOPHYCMREGS5_COMMON_DISP_RFU7                                   0x9bef
+#define mmDC_COMBOPHYCMREGS6_COMMON_DISP_RFU7                                   0x9c8f
+#define mmDC_COMBOPHYCMREGS7_COMMON_DISP_RFU7                                   0x9d2f
+#define mmFREQ_CTRL0                                                            0x4920
+#define mmDC_COMBOPHYPLLREGS0_FREQ_CTRL0                                        0x4920
+#define mmDC_COMBOPHYPLLREGS1_FREQ_CTRL0                                        0x49c0
+#define mmDC_COMBOPHYPLLREGS2_FREQ_CTRL0                                        0x9a60
+#define mmDC_COMBOPHYPLLREGS3_FREQ_CTRL0                                        0x9b00
+#define mmDC_COMBOPHYPLLREGS4_FREQ_CTRL0                                        0x9ba0
+#define mmDC_COMBOPHYPLLREGS5_FREQ_CTRL0                                        0x9c40
+#define mmDC_COMBOPHYPLLREGS6_FREQ_CTRL0                                        0x9ce0
+#define mmDC_COMBOPHYPLLREGS7_FREQ_CTRL0                                        0x9d80
+#define mmFREQ_CTRL1                                                            0x4921
+#define mmDC_COMBOPHYPLLREGS0_FREQ_CTRL1                                        0x4921
+#define mmDC_COMBOPHYPLLREGS1_FREQ_CTRL1                                        0x49c1
+#define mmDC_COMBOPHYPLLREGS2_FREQ_CTRL1                                        0x9a61
+#define mmDC_COMBOPHYPLLREGS3_FREQ_CTRL1                                        0x9b01
+#define mmDC_COMBOPHYPLLREGS4_FREQ_CTRL1                                        0x9ba1
+#define mmDC_COMBOPHYPLLREGS5_FREQ_CTRL1                                        0x9c41
+#define mmDC_COMBOPHYPLLREGS6_FREQ_CTRL1                                        0x9ce1
+#define mmDC_COMBOPHYPLLREGS7_FREQ_CTRL1                                        0x9d81
+#define mmFREQ_CTRL2                                                            0x4922
+#define mmDC_COMBOPHYPLLREGS0_FREQ_CTRL2                                        0x4922
+#define mmDC_COMBOPHYPLLREGS1_FREQ_CTRL2                                        0x49c2
+#define mmDC_COMBOPHYPLLREGS2_FREQ_CTRL2                                        0x9a62
+#define mmDC_COMBOPHYPLLREGS3_FREQ_CTRL2                                        0x9b02
+#define mmDC_COMBOPHYPLLREGS4_FREQ_CTRL2                                        0x9ba2
+#define mmDC_COMBOPHYPLLREGS5_FREQ_CTRL2                                        0x9c42
+#define mmDC_COMBOPHYPLLREGS6_FREQ_CTRL2                                        0x9ce2
+#define mmDC_COMBOPHYPLLREGS7_FREQ_CTRL2                                        0x9d82
+#define mmFREQ_CTRL3                                                            0x4923
+#define mmDC_COMBOPHYPLLREGS0_FREQ_CTRL3                                        0x4923
+#define mmDC_COMBOPHYPLLREGS1_FREQ_CTRL3                                        0x49c3
+#define mmDC_COMBOPHYPLLREGS2_FREQ_CTRL3                                        0x9a63
+#define mmDC_COMBOPHYPLLREGS3_FREQ_CTRL3                                        0x9b03
+#define mmDC_COMBOPHYPLLREGS4_FREQ_CTRL3                                        0x9ba3
+#define mmDC_COMBOPHYPLLREGS5_FREQ_CTRL3                                        0x9c43
+#define mmDC_COMBOPHYPLLREGS6_FREQ_CTRL3                                        0x9ce3
+#define mmDC_COMBOPHYPLLREGS7_FREQ_CTRL3                                        0x9d83
+#define mmBW_CTRL_COARSE                                                        0x4924
+#define mmDC_COMBOPHYPLLREGS0_BW_CTRL_COARSE                                    0x4924
+#define mmDC_COMBOPHYPLLREGS1_BW_CTRL_COARSE                                    0x49c4
+#define mmDC_COMBOPHYPLLREGS2_BW_CTRL_COARSE                                    0x9a64
+#define mmDC_COMBOPHYPLLREGS3_BW_CTRL_COARSE                                    0x9b04
+#define mmDC_COMBOPHYPLLREGS4_BW_CTRL_COARSE                                    0x9ba4
+#define mmDC_COMBOPHYPLLREGS5_BW_CTRL_COARSE                                    0x9c44
+#define mmDC_COMBOPHYPLLREGS6_BW_CTRL_COARSE                                    0x9ce4
+#define mmDC_COMBOPHYPLLREGS7_BW_CTRL_COARSE                                    0x9d84
+#define mmBW_CTRL_FINE                                                          0x4925
+#define mmDC_COMBOPHYPLLREGS0_BW_CTRL_FINE                                      0x4925
+#define mmDC_COMBOPHYPLLREGS1_BW_CTRL_FINE                                      0x49c5
+#define mmDC_COMBOPHYPLLREGS2_BW_CTRL_FINE                                      0x9a65
+#define mmDC_COMBOPHYPLLREGS3_BW_CTRL_FINE                                      0x9b05
+#define mmDC_COMBOPHYPLLREGS4_BW_CTRL_FINE                                      0x9ba5
+#define mmDC_COMBOPHYPLLREGS5_BW_CTRL_FINE                                      0x9c45
+#define mmDC_COMBOPHYPLLREGS6_BW_CTRL_FINE                                      0x9ce5
+#define mmDC_COMBOPHYPLLREGS7_BW_CTRL_FINE                                      0x9d85
+#define mmCAL_CTRL                                                              0x4926
+#define mmDC_COMBOPHYPLLREGS0_CAL_CTRL                                          0x4926
+#define mmDC_COMBOPHYPLLREGS1_CAL_CTRL                                          0x49c6
+#define mmDC_COMBOPHYPLLREGS2_CAL_CTRL                                          0x9a66
+#define mmDC_COMBOPHYPLLREGS3_CAL_CTRL                                          0x9b06
+#define mmDC_COMBOPHYPLLREGS4_CAL_CTRL                                          0x9ba6
+#define mmDC_COMBOPHYPLLREGS5_CAL_CTRL                                          0x9c46
+#define mmDC_COMBOPHYPLLREGS6_CAL_CTRL                                          0x9ce6
+#define mmDC_COMBOPHYPLLREGS7_CAL_CTRL                                          0x9d86
+#define mmLOOP_CTRL                                                             0x4927
+#define mmDC_COMBOPHYPLLREGS0_LOOP_CTRL                                         0x4927
+#define mmDC_COMBOPHYPLLREGS1_LOOP_CTRL                                         0x49c7
+#define mmDC_COMBOPHYPLLREGS2_LOOP_CTRL                                         0x9a67
+#define mmDC_COMBOPHYPLLREGS3_LOOP_CTRL                                         0x9b07
+#define mmDC_COMBOPHYPLLREGS4_LOOP_CTRL                                         0x9ba7
+#define mmDC_COMBOPHYPLLREGS5_LOOP_CTRL                                         0x9c47
+#define mmDC_COMBOPHYPLLREGS6_LOOP_CTRL                                         0x9ce7
+#define mmDC_COMBOPHYPLLREGS7_LOOP_CTRL                                         0x9d87
+#define mmDEBUG0                                                                0x4928
+#define mmDC_COMBOPHYPLLREGS0_DEBUG0                                            0x4928
+#define mmDC_COMBOPHYPLLREGS1_DEBUG0                                            0x49c8
+#define mmDC_COMBOPHYPLLREGS2_DEBUG0                                            0x9a68
+#define mmDC_COMBOPHYPLLREGS3_DEBUG0                                            0x9b08
+#define mmDC_COMBOPHYPLLREGS4_DEBUG0                                            0x9ba8
+#define mmDC_COMBOPHYPLLREGS5_DEBUG0                                            0x9c48
+#define mmDC_COMBOPHYPLLREGS6_DEBUG0                                            0x9ce8
+#define mmDC_COMBOPHYPLLREGS7_DEBUG0                                            0x9d88
+#define mmVREG_CFG                                                              0x4929
+#define mmDC_COMBOPHYPLLREGS0_VREG_CFG                                          0x4929
+#define mmDC_COMBOPHYPLLREGS1_VREG_CFG                                          0x49c9
+#define mmDC_COMBOPHYPLLREGS2_VREG_CFG                                          0x9a69
+#define mmDC_COMBOPHYPLLREGS3_VREG_CFG                                          0x9b09
+#define mmDC_COMBOPHYPLLREGS4_VREG_CFG                                          0x9ba9
+#define mmDC_COMBOPHYPLLREGS5_VREG_CFG                                          0x9c49
+#define mmDC_COMBOPHYPLLREGS6_VREG_CFG                                          0x9ce9
+#define mmDC_COMBOPHYPLLREGS7_VREG_CFG                                          0x9d89
+#define mmOBSERVE0                                                              0x492a
+#define mmDC_COMBOPHYPLLREGS0_OBSERVE0                                          0x492a
+#define mmDC_COMBOPHYPLLREGS1_OBSERVE0                                          0x49ca
+#define mmDC_COMBOPHYPLLREGS2_OBSERVE0                                          0x9a6a
+#define mmDC_COMBOPHYPLLREGS3_OBSERVE0                                          0x9b0a
+#define mmDC_COMBOPHYPLLREGS4_OBSERVE0                                          0x9baa
+#define mmDC_COMBOPHYPLLREGS5_OBSERVE0                                          0x9c4a
+#define mmDC_COMBOPHYPLLREGS6_OBSERVE0                                          0x9cea
+#define mmDC_COMBOPHYPLLREGS7_OBSERVE0                                          0x9d8a
+#define mmOBSERVE1                                                              0x492b
+#define mmDC_COMBOPHYPLLREGS0_OBSERVE1                                          0x492b
+#define mmDC_COMBOPHYPLLREGS1_OBSERVE1                                          0x49cb
+#define mmDC_COMBOPHYPLLREGS2_OBSERVE1                                          0x9a6b
+#define mmDC_COMBOPHYPLLREGS3_OBSERVE1                                          0x9b0b
+#define mmDC_COMBOPHYPLLREGS4_OBSERVE1                                          0x9bab
+#define mmDC_COMBOPHYPLLREGS5_OBSERVE1                                          0x9c4b
+#define mmDC_COMBOPHYPLLREGS6_OBSERVE1                                          0x9ceb
+#define mmDC_COMBOPHYPLLREGS7_OBSERVE1                                          0x9d8b
+#define mmDFT_OUT                                                               0x492c
+#define mmDC_COMBOPHYPLLREGS0_DFT_OUT                                           0x492c
+#define mmDC_COMBOPHYPLLREGS1_DFT_OUT                                           0x49cc
+#define mmDC_COMBOPHYPLLREGS2_DFT_OUT                                           0x9a6c
+#define mmDC_COMBOPHYPLLREGS3_DFT_OUT                                           0x9b0c
+#define mmDC_COMBOPHYPLLREGS4_DFT_OUT                                           0x9bac
+#define mmDC_COMBOPHYPLLREGS5_DFT_OUT                                           0x9c4c
+#define mmDC_COMBOPHYPLLREGS6_DFT_OUT                                           0x9cec
+#define mmDC_COMBOPHYPLLREGS7_DFT_OUT                                           0x9d8c
+#define mmPLL_WRAP_CNTRL1                                                       0x495e
+#define mmDC_COMBOPHYPLLREGS0_PLL_WRAP_CNTRL1                                   0x495e
+#define mmDC_COMBOPHYPLLREGS1_PLL_WRAP_CNTRL1                                   0x49fe
+#define mmDC_COMBOPHYPLLREGS2_PLL_WRAP_CNTRL1                                   0x9a9e
+#define mmDC_COMBOPHYPLLREGS3_PLL_WRAP_CNTRL1                                   0x9b3e
+#define mmDC_COMBOPHYPLLREGS4_PLL_WRAP_CNTRL1                                   0x9bde
+#define mmDC_COMBOPHYPLLREGS5_PLL_WRAP_CNTRL1                                   0x9c7e
+#define mmDC_COMBOPHYPLLREGS6_PLL_WRAP_CNTRL1                                   0x9d1e
+#define mmDC_COMBOPHYPLLREGS7_PLL_WRAP_CNTRL1                                   0x9dbe
+#define mmPLL_WRAP_CNTRL                                                        0x495f
+#define mmDC_COMBOPHYPLLREGS0_PLL_WRAP_CNTRL                                    0x495f
+#define mmDC_COMBOPHYPLLREGS1_PLL_WRAP_CNTRL                                    0x49ff
+#define mmDC_COMBOPHYPLLREGS2_PLL_WRAP_CNTRL                                    0x9a9f
+#define mmDC_COMBOPHYPLLREGS3_PLL_WRAP_CNTRL                                    0x9b3f
+#define mmDC_COMBOPHYPLLREGS4_PLL_WRAP_CNTRL                                    0x9bdf
+#define mmDC_COMBOPHYPLLREGS5_PLL_WRAP_CNTRL                                    0x9c7f
+#define mmDC_COMBOPHYPLLREGS6_PLL_WRAP_CNTRL                                    0x9d1f
+#define mmDC_COMBOPHYPLLREGS7_PLL_WRAP_CNTRL                                    0x9dbf
+#define mmPPLL_VREG_CFG                                                         0x1700
+#define mmDC_DISPLAYPLLREGS0_PPLL_VREG_CFG                                      0x1700
+#define mmDC_DISPLAYPLLREGS1_PPLL_VREG_CFG                                      0x172a
+#define mmDC_DISPLAYPLLREGS2_PPLL_VREG_CFG                                      0x1754
+#define mmPPLL_MODE_CNTL                                                        0x1701
+#define mmDC_DISPLAYPLLREGS0_PPLL_MODE_CNTL                                     0x1701
+#define mmDC_DISPLAYPLLREGS1_PPLL_MODE_CNTL                                     0x172b
+#define mmDC_DISPLAYPLLREGS2_PPLL_MODE_CNTL                                     0x1755
+#define mmPPLL_FREQ_CTRL0                                                       0x1702
+#define mmDC_DISPLAYPLLREGS0_PPLL_FREQ_CTRL0                                    0x1702
+#define mmDC_DISPLAYPLLREGS1_PPLL_FREQ_CTRL0                                    0x172c
+#define mmDC_DISPLAYPLLREGS2_PPLL_FREQ_CTRL0                                    0x1756
+#define mmPPLL_FREQ_CTRL1                                                       0x1703
+#define mmDC_DISPLAYPLLREGS0_PPLL_FREQ_CTRL1                                    0x1703
+#define mmDC_DISPLAYPLLREGS1_PPLL_FREQ_CTRL1                                    0x172d
+#define mmDC_DISPLAYPLLREGS2_PPLL_FREQ_CTRL1                                    0x1757
+#define mmPPLL_FREQ_CTRL2                                                       0x1704
+#define mmDC_DISPLAYPLLREGS0_PPLL_FREQ_CTRL2                                    0x1704
+#define mmDC_DISPLAYPLLREGS1_PPLL_FREQ_CTRL2                                    0x172e
+#define mmDC_DISPLAYPLLREGS2_PPLL_FREQ_CTRL2                                    0x1758
+#define mmPPLL_FREQ_CTRL3                                                       0x1705
+#define mmDC_DISPLAYPLLREGS0_PPLL_FREQ_CTRL3                                    0x1705
+#define mmDC_DISPLAYPLLREGS1_PPLL_FREQ_CTRL3                                    0x172f
+#define mmDC_DISPLAYPLLREGS2_PPLL_FREQ_CTRL3                                    0x1759
+#define mmPPLL_BW_CTRL_COARSE                                                   0x1706
+#define mmDC_DISPLAYPLLREGS0_PPLL_BW_CTRL_COARSE                                0x1706
+#define mmDC_DISPLAYPLLREGS1_PPLL_BW_CTRL_COARSE                                0x1730
+#define mmDC_DISPLAYPLLREGS2_PPLL_BW_CTRL_COARSE                                0x175a
+#define mmPPLL_BW_CTRL_FINE                                                     0x1708
+#define mmDC_DISPLAYPLLREGS0_PPLL_BW_CTRL_FINE                                  0x1708
+#define mmDC_DISPLAYPLLREGS1_PPLL_BW_CTRL_FINE                                  0x1732
+#define mmDC_DISPLAYPLLREGS2_PPLL_BW_CTRL_FINE                                  0x175c
+#define mmPPLL_CAL_CTRL                                                         0x1709
+#define mmDC_DISPLAYPLLREGS0_PPLL_CAL_CTRL                                      0x1709
+#define mmDC_DISPLAYPLLREGS1_PPLL_CAL_CTRL                                      0x1733
+#define mmDC_DISPLAYPLLREGS2_PPLL_CAL_CTRL                                      0x175d
+#define mmPPLL_LOOP_CTRL                                                        0x170a
+#define mmDC_DISPLAYPLLREGS0_PPLL_LOOP_CTRL                                     0x170a
+#define mmDC_DISPLAYPLLREGS1_PPLL_LOOP_CTRL                                     0x1734
+#define mmDC_DISPLAYPLLREGS2_PPLL_LOOP_CTRL                                     0x175e
+#define mmPPLL_REFCLK_CNTL                                                      0x1718
+#define mmDC_DISPLAYPLLREGS0_PPLL_REFCLK_CNTL                                   0x1718
+#define mmDC_DISPLAYPLLREGS1_PPLL_REFCLK_CNTL                                   0x1742
+#define mmDC_DISPLAYPLLREGS2_PPLL_REFCLK_CNTL                                   0x176c
+#define mmPPLL_CLKOUT_CNTL                                                      0x1719
+#define mmDC_DISPLAYPLLREGS0_PPLL_CLKOUT_CNTL                                   0x1719
+#define mmDC_DISPLAYPLLREGS1_PPLL_CLKOUT_CNTL                                   0x1743
+#define mmDC_DISPLAYPLLREGS2_PPLL_CLKOUT_CNTL                                   0x176d
+#define mmPPLL_DFT_CNTL                                                         0x171a
+#define mmDC_DISPLAYPLLREGS0_PPLL_DFT_CNTL                                      0x171a
+#define mmDC_DISPLAYPLLREGS1_PPLL_DFT_CNTL                                      0x1744
+#define mmDC_DISPLAYPLLREGS2_PPLL_DFT_CNTL                                      0x176e
+#define mmPPLL_ANALOG_CNTL                                                      0x171b
+#define mmDC_DISPLAYPLLREGS0_PPLL_ANALOG_CNTL                                   0x171b
+#define mmDC_DISPLAYPLLREGS1_PPLL_ANALOG_CNTL                                   0x1745
+#define mmDC_DISPLAYPLLREGS2_PPLL_ANALOG_CNTL                                   0x176f
+#define mmPPLL_POSTDIV                                                          0x171c
+#define mmDC_DISPLAYPLLREGS0_PPLL_POSTDIV                                       0x171c
+#define mmDC_DISPLAYPLLREGS1_PPLL_POSTDIV                                       0x1746
+#define mmDC_DISPLAYPLLREGS2_PPLL_POSTDIV                                       0x1770
+#define mmPPLL_DEBUG0                                                           0x1720
+#define mmDC_DISPLAYPLLREGS0_PPLL_DEBUG0                                        0x1720
+#define mmDC_DISPLAYPLLREGS1_PPLL_DEBUG0                                        0x174a
+#define mmDC_DISPLAYPLLREGS2_PPLL_DEBUG0                                        0x1774
+#define mmPPLL_OBSERVE0                                                         0x1721
+#define mmDC_DISPLAYPLLREGS0_PPLL_OBSERVE0                                      0x1721
+#define mmDC_DISPLAYPLLREGS1_PPLL_OBSERVE0                                      0x174b
+#define mmDC_DISPLAYPLLREGS2_PPLL_OBSERVE0                                      0x1775
+#define mmPPLL_OBSERVE1                                                         0x1722
+#define mmDC_DISPLAYPLLREGS0_PPLL_OBSERVE1                                      0x1722
+#define mmDC_DISPLAYPLLREGS1_PPLL_OBSERVE1                                      0x174c
+#define mmDC_DISPLAYPLLREGS2_PPLL_OBSERVE1                                      0x1776
+#define mmPPLL_UPDATE_CNTL                                                      0x1724
+#define mmDC_DISPLAYPLLREGS0_PPLL_UPDATE_CNTL                                   0x1724
+#define mmDC_DISPLAYPLLREGS1_PPLL_UPDATE_CNTL                                   0x174e
+#define mmDC_DISPLAYPLLREGS2_PPLL_UPDATE_CNTL                                   0x1778
+#define mmPPLL_OBSERVE0_OUT                                                     0x1725
+#define mmDC_DISPLAYPLLREGS0_PPLL_OBSERVE0_OUT                                  0x1725
+#define mmDC_DISPLAYPLLREGS1_PPLL_OBSERVE0_OUT                                  0x174f
+#define mmDC_DISPLAYPLLREGS2_PPLL_OBSERVE0_OUT                                  0x1779
+#define mmPPLL_STATUS_DEBUG1                                                    0x1726
+#define mmDC_DISPLAYPLLREGS0_PPLL_STATUS_DEBUG1                                 0x1726
+#define mmDC_DISPLAYPLLREGS1_PPLL_STATUS_DEBUG1                                 0x1750
+#define mmDC_DISPLAYPLLREGS2_PPLL_STATUS_DEBUG1                                 0x177a
+#define mmPPLL_DEBUG_MUX_CNTL                                                   0x1727
+#define mmDC_DISPLAYPLLREGS0_PPLL_DEBUG_MUX_CNTL                                0x1727
+#define mmDC_DISPLAYPLLREGS1_PPLL_DEBUG_MUX_CNTL                                0x1751
+#define mmDC_DISPLAYPLLREGS2_PPLL_DEBUG_MUX_CNTL                                0x177b
+#define mmPPLL_DIV_UPDATE_DEBUG                                                 0x1728
+#define mmDC_DISPLAYPLLREGS0_PPLL_DIV_UPDATE_DEBUG                              0x1728
+#define mmDC_DISPLAYPLLREGS1_PPLL_DIV_UPDATE_DEBUG                              0x1752
+#define mmDC_DISPLAYPLLREGS2_PPLL_DIV_UPDATE_DEBUG                              0x177c
+#define mmPPLL_STATUS_DEBUG0                                                    0x1729
+#define mmDC_DISPLAYPLLREGS0_PPLL_STATUS_DEBUG0                                 0x1729
+#define mmDC_DISPLAYPLLREGS1_PPLL_STATUS_DEBUG0                                 0x1753
+#define mmDC_DISPLAYPLLREGS2_PPLL_STATUS_DEBUG0                                 0x177d
+#define mmCOMP_EN_CTL                                                           0x9dc0
+#define mmDPCSTX_PHY_CNTL                                                       0x48d0
+#define mmDPCSTX0_DPCSTX_PHY_CNTL                                               0x48d0
+#define mmDPCSTX1_DPCSTX_PHY_CNTL                                               0x4970
+#define mmDPCSTX2_DPCSTX_PHY_CNTL                                               0x9a10
+#define mmDPCSTX3_DPCSTX_PHY_CNTL                                               0x9ab0
+#define mmDPCSTX4_DPCSTX_PHY_CNTL                                               0x9b50
+#define mmDPCSTX5_DPCSTX_PHY_CNTL                                               0x9bf0
+#define mmDPCSTX6_DPCSTX_PHY_CNTL                                               0x9c90
+#define mmDPCSTX7_DPCSTX_PHY_CNTL                                               0x9d30
+#define mmDPCSTX_TX_CLOCK_CNTL                                                  0x48d1
+#define mmDPCSTX0_DPCSTX_TX_CLOCK_CNTL                                          0x48d1
+#define mmDPCSTX1_DPCSTX_TX_CLOCK_CNTL                                          0x4971
+#define mmDPCSTX2_DPCSTX_TX_CLOCK_CNTL                                          0x9a11
+#define mmDPCSTX3_DPCSTX_TX_CLOCK_CNTL                                          0x9ab1
+#define mmDPCSTX4_DPCSTX_TX_CLOCK_CNTL                                          0x9b51
+#define mmDPCSTX5_DPCSTX_TX_CLOCK_CNTL                                          0x9bf1
+#define mmDPCSTX6_DPCSTX_TX_CLOCK_CNTL                                          0x9c91
+#define mmDPCSTX7_DPCSTX_TX_CLOCK_CNTL                                          0x9d31
+#define mmDPCSTX_TX_CNTL                                                        0x48d3
+#define mmDPCSTX0_DPCSTX_TX_CNTL                                                0x48d3
+#define mmDPCSTX1_DPCSTX_TX_CNTL                                                0x4973
+#define mmDPCSTX2_DPCSTX_TX_CNTL                                                0x9a13
+#define mmDPCSTX3_DPCSTX_TX_CNTL                                                0x9ab3
+#define mmDPCSTX4_DPCSTX_TX_CNTL                                                0x9b53
+#define mmDPCSTX5_DPCSTX_TX_CNTL                                                0x9bf3
+#define mmDPCSTX6_DPCSTX_TX_CNTL                                                0x9c93
+#define mmDPCSTX7_DPCSTX_TX_CNTL                                                0x9d33
+#define mmDPCSTX_CBUS_CNTL                                                      0x48d5
+#define mmDPCSTX0_DPCSTX_CBUS_CNTL                                              0x48d5
+#define mmDPCSTX1_DPCSTX_CBUS_CNTL                                              0x4975
+#define mmDPCSTX2_DPCSTX_CBUS_CNTL                                              0x9a15
+#define mmDPCSTX3_DPCSTX_CBUS_CNTL                                              0x9ab5
+#define mmDPCSTX4_DPCSTX_CBUS_CNTL                                              0x9b55
+#define mmDPCSTX5_DPCSTX_CBUS_CNTL                                              0x9bf5
+#define mmDPCSTX6_DPCSTX_CBUS_CNTL                                              0x9c95
+#define mmDPCSTX7_DPCSTX_CBUS_CNTL                                              0x9d35
+#define mmDPCSTX_REG_ERROR_STATUS                                               0x48d6
+#define mmDPCSTX0_DPCSTX_REG_ERROR_STATUS                                       0x48d6
+#define mmDPCSTX1_DPCSTX_REG_ERROR_STATUS                                       0x4976
+#define mmDPCSTX2_DPCSTX_REG_ERROR_STATUS                                       0x9a16
+#define mmDPCSTX3_DPCSTX_REG_ERROR_STATUS                                       0x9ab6
+#define mmDPCSTX4_DPCSTX_REG_ERROR_STATUS                                       0x9b56
+#define mmDPCSTX5_DPCSTX_REG_ERROR_STATUS                                       0x9bf6
+#define mmDPCSTX6_DPCSTX_REG_ERROR_STATUS                                       0x9c96
+#define mmDPCSTX7_DPCSTX_REG_ERROR_STATUS                                       0x9d36
+#define mmDPCSTX_TX_ERROR_STATUS                                                0x48d7
+#define mmDPCSTX0_DPCSTX_TX_ERROR_STATUS                                        0x48d7
+#define mmDPCSTX1_DPCSTX_TX_ERROR_STATUS                                        0x4977
+#define mmDPCSTX2_DPCSTX_TX_ERROR_STATUS                                        0x9a17
+#define mmDPCSTX3_DPCSTX_TX_ERROR_STATUS                                        0x9ab7
+#define mmDPCSTX4_DPCSTX_TX_ERROR_STATUS                                        0x9b57
+#define mmDPCSTX5_DPCSTX_TX_ERROR_STATUS                                        0x9bf7
+#define mmDPCSTX6_DPCSTX_TX_ERROR_STATUS                                        0x9c97
+#define mmDPCSTX7_DPCSTX_TX_ERROR_STATUS                                        0x9d37
+#define mmDPCSTX_PLL_UPDATE_ADDR                                                0x48d8
+#define mmDPCSTX0_DPCSTX_PLL_UPDATE_ADDR                                        0x48d8
+#define mmDPCSTX1_DPCSTX_PLL_UPDATE_ADDR                                        0x4978
+#define mmDPCSTX2_DPCSTX_PLL_UPDATE_ADDR                                        0x9a18
+#define mmDPCSTX3_DPCSTX_PLL_UPDATE_ADDR                                        0x9ab8
+#define mmDPCSTX4_DPCSTX_PLL_UPDATE_ADDR                                        0x9b58
+#define mmDPCSTX5_DPCSTX_PLL_UPDATE_ADDR                                        0x9bf8
+#define mmDPCSTX6_DPCSTX_PLL_UPDATE_ADDR                                        0x9c98
+#define mmDPCSTX7_DPCSTX_PLL_UPDATE_ADDR                                        0x9d38
+#define mmDPCSTX_PLL_UPDATE_DATA                                                0x48d9
+#define mmDPCSTX0_DPCSTX_PLL_UPDATE_DATA                                        0x48d9
+#define mmDPCSTX1_DPCSTX_PLL_UPDATE_DATA                                        0x4979
+#define mmDPCSTX2_DPCSTX_PLL_UPDATE_DATA                                        0x9a19
+#define mmDPCSTX3_DPCSTX_PLL_UPDATE_DATA                                        0x9ab9
+#define mmDPCSTX4_DPCSTX_PLL_UPDATE_DATA                                        0x9b59
+#define mmDPCSTX5_DPCSTX_PLL_UPDATE_DATA                                        0x9bf9
+#define mmDPCSTX6_DPCSTX_PLL_UPDATE_DATA                                        0x9c99
+#define mmDPCSTX7_DPCSTX_PLL_UPDATE_DATA                                        0x9d39
+#define mmDPCSTX_INDEX_MODE_ADDR                                                0x48da
+#define mmDPCSTX0_DPCSTX_INDEX_MODE_ADDR                                        0x48da
+#define mmDPCSTX1_DPCSTX_INDEX_MODE_ADDR                                        0x497a
+#define mmDPCSTX2_DPCSTX_INDEX_MODE_ADDR                                        0x9a1a
+#define mmDPCSTX3_DPCSTX_INDEX_MODE_ADDR                                        0x9aba
+#define mmDPCSTX4_DPCSTX_INDEX_MODE_ADDR                                        0x9b5a
+#define mmDPCSTX5_DPCSTX_INDEX_MODE_ADDR                                        0x9bfa
+#define mmDPCSTX6_DPCSTX_INDEX_MODE_ADDR                                        0x9c9a
+#define mmDPCSTX7_DPCSTX_INDEX_MODE_ADDR                                        0x9d3a
+#define mmDPCSTX_INDEX_MODE_DATA                                                0x48db
+#define mmDPCSTX0_DPCSTX_INDEX_MODE_DATA                                        0x48db
+#define mmDPCSTX1_DPCSTX_INDEX_MODE_DATA                                        0x497b
+#define mmDPCSTX2_DPCSTX_INDEX_MODE_DATA                                        0x9a1b
+#define mmDPCSTX3_DPCSTX_INDEX_MODE_DATA                                        0x9abb
+#define mmDPCSTX4_DPCSTX_INDEX_MODE_DATA                                        0x9b5b
+#define mmDPCSTX5_DPCSTX_INDEX_MODE_DATA                                        0x9bfb
+#define mmDPCSTX6_DPCSTX_INDEX_MODE_DATA                                        0x9c9b
+#define mmDPCSTX7_DPCSTX_INDEX_MODE_DATA                                        0x9d3b
+#define mmDPCSTX_DEBUG_CONFIG                                                   0x48dc
+#define mmDPCSTX0_DPCSTX_DEBUG_CONFIG                                           0x48dc
+#define mmDPCSTX1_DPCSTX_DEBUG_CONFIG                                           0x497c
+#define mmDPCSTX2_DPCSTX_DEBUG_CONFIG                                           0x9a1c
+#define mmDPCSTX3_DPCSTX_DEBUG_CONFIG                                           0x9abc
+#define mmDPCSTX4_DPCSTX_DEBUG_CONFIG                                           0x9b5c
+#define mmDPCSTX5_DPCSTX_DEBUG_CONFIG                                           0x9bfc
+#define mmDPCSTX6_DPCSTX_DEBUG_CONFIG                                           0x9c9c
+#define mmDPCSTX7_DPCSTX_DEBUG_CONFIG                                           0x9d3c
+#define mmDPCSTX_TEST_DEBUG_DATA                                                0x48dd
+#define mmDPCSTX0_DPCSTX_TEST_DEBUG_DATA                                        0x48dd
+#define mmDPCSTX1_DPCSTX_TEST_DEBUG_DATA                                        0x497d
+#define mmDPCSTX2_DPCSTX_TEST_DEBUG_DATA                                        0x9a1d
+#define mmDPCSTX3_DPCSTX_TEST_DEBUG_DATA                                        0x9abd
+#define mmDPCSTX4_DPCSTX_TEST_DEBUG_DATA                                        0x9b5d
+#define mmDPCSTX5_DPCSTX_TEST_DEBUG_DATA                                        0x9bfd
+#define mmDPCSTX6_DPCSTX_TEST_DEBUG_DATA                                        0x9c9d
+#define mmDPCSTX7_DPCSTX_TEST_DEBUG_DATA                                        0x9d3d
+
+#endif /* DCE_11_2_D_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/include/asic_reg/dce/dce_11_2_enum.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/include/asic_reg/dce/dce_11_2_enum.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/include/asic_reg/dce/dce_11_2_enum.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/include/asic_reg/dce/dce_11_2_enum.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,6813 @@
+/*
+ * DCE_11_2 Register documentation
+ *
+ * Copyright (C) 2016  Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef DCE_11_2_ENUM_H
+#define DCE_11_2_ENUM_H
+
+typedef enum CRTC_CONTROL_CRTC_START_POINT_CNTL {
+	CRTC_CONTROL_CRTC_START_POINT_CNTL_NORMAL        = 0x0,
+	CRTC_CONTROL_CRTC_START_POINT_CNTL_DP            = 0x1,
+} CRTC_CONTROL_CRTC_START_POINT_CNTL;
+typedef enum CRTC_CONTROL_CRTC_FIELD_NUMBER_CNTL {
+	CRTC_CONTROL_CRTC_FIELD_NUMBER_CNTL_NORMAL       = 0x0,
+	CRTC_CONTROL_CRTC_FIELD_NUMBER_CNTL_DP           = 0x1,
+} CRTC_CONTROL_CRTC_FIELD_NUMBER_CNTL;
+typedef enum CRTC_CONTROL_CRTC_DISABLE_POINT_CNTL {
+	CRTC_CONTROL_CRTC_DISABLE_POINT_CNTL_DISABLE     = 0x0,
+	CRTC_CONTROL_CRTC_DISABLE_POINT_CNTL_DISABLE_CURRENT= 0x1,
+	CRTC_CONTROL_CRTC_DISABLE_POINT_CNTL_RESERVED    = 0x2,
+	CRTC_CONTROL_CRTC_DISABLE_POINT_CNTL_DISABLE_FIRST= 0x3,
+} CRTC_CONTROL_CRTC_DISABLE_POINT_CNTL;
+typedef enum CRTC_CONTROL_CRTC_FIELD_NUMBER_POLARITY {
+	CRTC_CONTROL_CRTC_FIELD_NUMBER_POLARITY_FALSE    = 0x0,
+	CRTC_CONTROL_CRTC_FIELD_NUMBER_POLARITY_TRUE     = 0x1,
+} CRTC_CONTROL_CRTC_FIELD_NUMBER_POLARITY;
+typedef enum CRTC_CONTROL_CRTC_DISP_READ_REQUEST_DISABLE {
+	CRTC_CONTROL_CRTC_DISP_READ_REQUEST_DISABLE_FALSE= 0x0,
+	CRTC_CONTROL_CRTC_DISP_READ_REQUEST_DISABLE_TRUE = 0x1,
+} CRTC_CONTROL_CRTC_DISP_READ_REQUEST_DISABLE;
+typedef enum CRTC_CONTROL_CRTC_SOF_PULL_EN {
+	CRTC_CONTROL_CRTC_SOF_PULL_EN_FALSE              = 0x0,
+	CRTC_CONTROL_CRTC_SOF_PULL_EN_TRUE               = 0x1,
+} CRTC_CONTROL_CRTC_SOF_PULL_EN;
+typedef enum CRTC_H_SYNC_B_CNTL_CRTC_H_SYNC_B_POL {
+	CRTC_H_SYNC_B_CNTL_CRTC_H_SYNC_B_POL_FALSE       = 0x0,
+	CRTC_H_SYNC_B_CNTL_CRTC_H_SYNC_B_POL_TRUE        = 0x1,
+} CRTC_H_SYNC_B_CNTL_CRTC_H_SYNC_B_POL;
+typedef enum CRTC_V_TOTAL_CONTROL_CRTC_V_TOTAL_MAX_SEL {
+	CRTC_V_TOTAL_CONTROL_CRTC_V_TOTAL_MAX_SEL_FALSE  = 0x0,
+	CRTC_V_TOTAL_CONTROL_CRTC_V_TOTAL_MAX_SEL_TRUE   = 0x1,
+} CRTC_V_TOTAL_CONTROL_CRTC_V_TOTAL_MAX_SEL;
+typedef enum CRTC_V_TOTAL_CONTROL_CRTC_V_TOTAL_MIN_SEL {
+	CRTC_V_TOTAL_CONTROL_CRTC_V_TOTAL_MIN_SEL_FALSE  = 0x0,
+	CRTC_V_TOTAL_CONTROL_CRTC_V_TOTAL_MIN_SEL_TRUE   = 0x1,
+} CRTC_V_TOTAL_CONTROL_CRTC_V_TOTAL_MIN_SEL;
+typedef enum CRTC_V_TOTAL_CONTROL_CRTC_SET_V_TOTAL_MIN_MASK_EN {
+	CRTC_V_TOTAL_CONTROL_CRTC_SET_V_TOTAL_MIN_MASK_EN_FALSE= 0x0,
+	CRTC_V_TOTAL_CONTROL_CRTC_SET_V_TOTAL_MIN_MASK_EN_TRUE= 0x1,
+} CRTC_V_TOTAL_CONTROL_CRTC_SET_V_TOTAL_MIN_MASK_EN;
+typedef enum CRTC_V_TOTAL_CONTROL_CRTC_FORCE_LOCK_TO_MASTER_VSYNC {
+	CRTC_V_TOTAL_CONTROL_CRTC_FORCE_LOCK_TO_MASTER_VSYNC_DISABLE= 0x0,
+	CRTC_V_TOTAL_CONTROL_CRTC_FORCE_LOCK_TO_MASTER_VSYNC_ENABLE= 0x1,
+} CRTC_V_TOTAL_CONTROL_CRTC_FORCE_LOCK_TO_MASTER_VSYNC;
+typedef enum CRTC_V_TOTAL_CONTROL_CRTC_FORCE_LOCK_ON_EVENT {
+	CRTC_V_TOTAL_CONTROL_CRTC_FORCE_LOCK_ON_EVENT_DISABLE= 0x0,
+	CRTC_V_TOTAL_CONTROL_CRTC_FORCE_LOCK_ON_EVENT_ENABLE= 0x1,
+} CRTC_V_TOTAL_CONTROL_CRTC_FORCE_LOCK_ON_EVENT;
+typedef enum CRTC_V_TOTAL_CONTROL_CRTC_SET_V_TOTAL_MIN_MASK {
+	CRTC_V_TOTAL_CONTROL_CRTC_SET_V_TOTAL_MIN_MASK_FRAME_START= 0x0,
+	CRTC_V_TOTAL_CONTROL_CRTC_SET_V_TOTAL_MIN_MASK_CRTC_TRIG_A= 0x1,
+	CRTC_V_TOTAL_CONTROL_CRTC_SET_V_TOTAL_MIN_MASK_CRTC_TRIG_B= 0x2,
+	CRTC_V_TOTAL_CONTROL_CRTC_SET_V_TOTAL_MIN_MASK_CURSOR_CHANGE= 0x3,
+	CRTC_V_TOTAL_CONTROL_CRTC_SET_V_TOTAL_MIN_MASK_OTHER_CLIENT= 0x4,
+	CRTC_V_TOTAL_CONTROL_CRTC_SET_V_TOTAL_MIN_MASK_MC_DC_REGION0= 0x5,
+	CRTC_V_TOTAL_CONTROL_CRTC_SET_V_TOTAL_MIN_MASK_MC_DC_REGION1= 0x6,
+	CRTC_V_TOTAL_CONTROL_CRTC_SET_V_TOTAL_MIN_MASK_MC_DC_REGION2= 0x7,
+	CRTC_V_TOTAL_CONTROL_CRTC_SET_V_TOTAL_MIN_MASK_MC_DC_REGION3= 0x8,
+	CRTC_V_TOTAL_CONTROL_CRTC_SET_V_TOTAL_MIN_MASK_GRAPHIC_UPDATE_PENDING= 0x9,
+	CRTC_V_TOTAL_CONTROL_CRTC_SET_V_TOTAL_MIN_MASK_RESERVED2= 0xa,
+	CRTC_V_TOTAL_CONTROL_CRTC_SET_V_TOTAL_MIN_MASK_INVALID= 0xb,
+	CRTC_V_TOTAL_CONTROL_CRTC_SET_V_TOTAL_MIN_MASK_DOUBLE_BUFFER= 0xc,
+	CRTC_V_TOTAL_CONTROL_CRTC_SET_V_TOTAL_MIN_MASK_D1CRTC_VERT_COUNT_NOM= 0xd,
+	CRTC_V_TOTAL_CONTROL_CRTC_SET_V_TOTAL_MIN_MASK_D1CRTC_VERT_COUNT= 0xe,
+	CRTC_V_TOTAL_CONTROL_CRTC_SET_V_TOTAL_MIN_MASK_RESERVED= 0xf,
+} CRTC_V_TOTAL_CONTROL_CRTC_SET_V_TOTAL_MIN_MASK;
+typedef enum CRTC_V_TOTAL_INT_STATUS_CRTC_SET_V_TOTAL_MIN_EVENT_OCCURED_ACK {
+	CRTC_V_TOTAL_INT_STATUS_CRTC_SET_V_TOTAL_MIN_EVENT_OCCURED_ACK_FALSE= 0x0,
+	CRTC_V_TOTAL_INT_STATUS_CRTC_SET_V_TOTAL_MIN_EVENT_OCCURED_ACK_TRUE= 0x1,
+} CRTC_V_TOTAL_INT_STATUS_CRTC_SET_V_TOTAL_MIN_EVENT_OCCURED_ACK;
+typedef enum CRTC_VSYNC_NOM_INT_STATUS_CRTC_VSYNC_NOM_INT_CLEAR {
+	CRTC_VSYNC_NOM_INT_STATUS_CRTC_VSYNC_NOM_INT_CLEAR_FALSE= 0x0,
+	CRTC_VSYNC_NOM_INT_STATUS_CRTC_VSYNC_NOM_INT_CLEAR_TRUE= 0x1,
+} CRTC_VSYNC_NOM_INT_STATUS_CRTC_VSYNC_NOM_INT_CLEAR;
+typedef enum CRTC_V_SYNC_B_CNTL_CRTC_V_SYNC_B_POL {
+	CRTC_V_SYNC_B_CNTL_CRTC_V_SYNC_B_POL_FALSE       = 0x0,
+	CRTC_V_SYNC_B_CNTL_CRTC_V_SYNC_B_POL_TRUE        = 0x1,
+} CRTC_V_SYNC_B_CNTL_CRTC_V_SYNC_B_POL;
+typedef enum CRTC_DTMTEST_CNTL_CRTC_DTMTEST_CRTC_EN {
+	CRTC_DTMTEST_CNTL_CRTC_DTMTEST_CRTC_EN_FALSE     = 0x0,
+	CRTC_DTMTEST_CNTL_CRTC_DTMTEST_CRTC_EN_TRUE      = 0x1,
+} CRTC_DTMTEST_CNTL_CRTC_DTMTEST_CRTC_EN;
+typedef enum CRTC_TRIGA_CNTL_CRTC_TRIGA_SOURCE_SELECT {
+	CRTC_TRIGA_CNTL_CRTC_TRIGA_SOURCE_SELECT_VSYNCA_OTHER= 0x1,
+	CRTC_TRIGA_CNTL_CRTC_TRIGA_SOURCE_SELECT_HSYNCA_OTHER= 0x2,
+	CRTC_TRIGA_CNTL_CRTC_TRIGA_SOURCE_SELECT_GENERICF= 0x5,
+	CRTC_TRIGA_CNTL_CRTC_TRIGA_SOURCE_SELECT_GENERICE= 0x6,
+	CRTC_TRIGA_CNTL_CRTC_TRIGA_SOURCE_SELECT_VSYNCA  = 0x7,
+	CRTC_TRIGA_CNTL_CRTC_TRIGA_SOURCE_SELECT_HSYNCA  = 0x8,
+	CRTC_TRIGA_CNTL_CRTC_TRIGA_SOURCE_SELECT_VSYNCB  = 0x9,
+	CRTC_TRIGA_CNTL_CRTC_TRIGA_SOURCE_SELECT_HSYNCB  = 0xa,
+	CRTC_TRIGA_CNTL_CRTC_TRIGA_SOURCE_SELECT_HPD1    = 0xb,
+	CRTC_TRIGA_CNTL_CRTC_TRIGA_SOURCE_SELECT_HPD2    = 0xc,
+	CRTC_TRIGA_CNTL_CRTC_TRIGA_SOURCE_SELECT_GENERICD= 0xd,
+	CRTC_TRIGA_CNTL_CRTC_TRIGA_SOURCE_SELECT_GENERICC= 0xe,
+	CRTC_TRIGA_CNTL_CRTC_TRIGA_SOURCE_SELECT_IGSL0   = 0x10,
+	CRTC_TRIGA_CNTL_CRTC_TRIGA_SOURCE_SELECT_IGSL1   = 0x11,
+	CRTC_TRIGA_CNTL_CRTC_TRIGA_SOURCE_SELECT_IGSL2   = 0x12,
+	CRTC_TRIGA_CNTL_CRTC_TRIGA_SOURCE_SELECT_IBLON   = 0x13,
+	CRTC_TRIGA_CNTL_CRTC_TRIGA_SOURCE_SELECT_GENERICA= 0x14,
+	CRTC_TRIGA_CNTL_CRTC_TRIGA_SOURCE_SELECT_GENERICB= 0x15,
+	CRTC_TRIGA_CNTL_CRTC_TRIGA_SOURCE_SELECT_IGSL_ALLOW= 0x16,
+	CRTC_TRIGA_CNTL_CRTC_TRIGA_SOURCE_SELECT_MANUAL_FLOW= 0x17,
+} CRTC_TRIGA_CNTL_CRTC_TRIGA_SOURCE_SELECT;
+typedef enum CRTC_TRIGA_CNTL_CRTC_TRIGA_POLARITY_SELECT {
+	CRTC_TRIGA_CNTL_CRTC_TRIGA_POLARITY_SELECT_INTERLACE= 0x1,
+	CRTC_TRIGA_CNTL_CRTC_TRIGA_POLARITY_SELECT_GENERICA= 0x2,
+	CRTC_TRIGA_CNTL_CRTC_TRIGA_POLARITY_SELECT_GENERICB= 0x3,
+	CRTC_TRIGA_CNTL_CRTC_TRIGA_POLARITY_SELECT_HSYNCA= 0x4,
+	CRTC_TRIGA_CNTL_CRTC_TRIGA_POLARITY_SELECT_HSYNCB= 0x5,
+	CRTC_TRIGA_CNTL_CRTC_TRIGA_POLARITY_SELECT_VIDEO = 0x6,
+	CRTC_TRIGA_CNTL_CRTC_TRIGA_POLARITY_SELECT_GENERICC= 0x7,
+} CRTC_TRIGA_CNTL_CRTC_TRIGA_POLARITY_SELECT;
+typedef enum CRTC_TRIGA_CNTL_CRTC_TRIGA_RESYNC_BYPASS_EN {
+	CRTC_TRIGA_CNTL_CRTC_TRIGA_RESYNC_BYPASS_EN_FALSE= 0x0,
+	CRTC_TRIGA_CNTL_CRTC_TRIGA_RESYNC_BYPASS_EN_TRUE = 0x1,
+} CRTC_TRIGA_CNTL_CRTC_TRIGA_RESYNC_BYPASS_EN;
+typedef enum CRTC_TRIGA_CNTL_CRTC_TRIGA_CLEAR {
+	CRTC_TRIGA_CNTL_CRTC_TRIGA_CLEAR_FALSE           = 0x0,
+	CRTC_TRIGA_CNTL_CRTC_TRIGA_CLEAR_TRUE            = 0x1,
+} CRTC_TRIGA_CNTL_CRTC_TRIGA_CLEAR;
+typedef enum CRTC_TRIGB_CNTL_CRTC_TRIGB_SOURCE_SELECT {
+	CRTC_TRIGB_CNTL_CRTC_TRIGB_SOURCE_SELECT_VSYNCA_OTHER= 0x1,
+	CRTC_TRIGB_CNTL_CRTC_TRIGB_SOURCE_SELECT_HSYNCA_OTHER= 0x2,
+	CRTC_TRIGB_CNTL_CRTC_TRIGB_SOURCE_SELECT_GENERICF= 0x5,
+	CRTC_TRIGB_CNTL_CRTC_TRIGB_SOURCE_SELECT_GENERICE= 0x6,
+	CRTC_TRIGB_CNTL_CRTC_TRIGB_SOURCE_SELECT_VSYNCA  = 0x7,
+	CRTC_TRIGB_CNTL_CRTC_TRIGB_SOURCE_SELECT_HSYNCA  = 0x8,
+	CRTC_TRIGB_CNTL_CRTC_TRIGB_SOURCE_SELECT_VSYNCB  = 0x9,
+	CRTC_TRIGB_CNTL_CRTC_TRIGB_SOURCE_SELECT_HSYNCB  = 0xa,
+	CRTC_TRIGB_CNTL_CRTC_TRIGB_SOURCE_SELECT_HPD1    = 0xb,
+	CRTC_TRIGB_CNTL_CRTC_TRIGB_SOURCE_SELECT_HPD2    = 0xc,
+	CRTC_TRIGB_CNTL_CRTC_TRIGB_SOURCE_SELECT_GENERICD= 0xd,
+	CRTC_TRIGB_CNTL_CRTC_TRIGB_SOURCE_SELECT_GENERICC= 0xe,
+	CRTC_TRIGB_CNTL_CRTC_TRIGB_SOURCE_SELECT_IGSL0   = 0x10,
+	CRTC_TRIGB_CNTL_CRTC_TRIGB_SOURCE_SELECT_IGSL1   = 0x11,
+	CRTC_TRIGB_CNTL_CRTC_TRIGB_SOURCE_SELECT_IGSL2   = 0x12,
+	CRTC_TRIGB_CNTL_CRTC_TRIGB_SOURCE_SELECT_IBLON   = 0x13,
+	CRTC_TRIGB_CNTL_CRTC_TRIGB_SOURCE_SELECT_GENERICA= 0x14,
+	CRTC_TRIGB_CNTL_CRTC_TRIGB_SOURCE_SELECT_GENERICB= 0x15,
+	CRTC_TRIGB_CNTL_CRTC_TRIGB_SOURCE_SELECT_IGSL_ALLOW= 0x16,
+	CRTC_TRIGB_CNTL_CRTC_TRIGB_SOURCE_SELECT_MANUAL_FLOW= 0x17,
+} CRTC_TRIGB_CNTL_CRTC_TRIGB_SOURCE_SELECT;
+typedef enum CRTC_TRIGB_CNTL_CRTC_TRIGB_POLARITY_SELECT {
+	CRTC_TRIGB_CNTL_CRTC_TRIGB_POLARITY_SELECT_INTERLACE= 0x1,
+	CRTC_TRIGB_CNTL_CRTC_TRIGB_POLARITY_SELECT_GENERICA= 0x2,
+	CRTC_TRIGB_CNTL_CRTC_TRIGB_POLARITY_SELECT_GENERICB= 0x3,
+	CRTC_TRIGB_CNTL_CRTC_TRIGB_POLARITY_SELECT_HSYNCA= 0x4,
+	CRTC_TRIGB_CNTL_CRTC_TRIGB_POLARITY_SELECT_HSYNCB= 0x5,
+	CRTC_TRIGB_CNTL_CRTC_TRIGB_POLARITY_SELECT_VIDEO = 0x6,
+	CRTC_TRIGB_CNTL_CRTC_TRIGB_POLARITY_SELECT_GENERICC= 0x7,
+} CRTC_TRIGB_CNTL_CRTC_TRIGB_POLARITY_SELECT;
+typedef enum CRTC_TRIGB_CNTL_CRTC_TRIGB_RESYNC_BYPASS_EN {
+	CRTC_TRIGB_CNTL_CRTC_TRIGB_RESYNC_BYPASS_EN_FALSE= 0x0,
+	CRTC_TRIGB_CNTL_CRTC_TRIGB_RESYNC_BYPASS_EN_TRUE = 0x1,
+} CRTC_TRIGB_CNTL_CRTC_TRIGB_RESYNC_BYPASS_EN;
+typedef enum CRTC_TRIGB_CNTL_CRTC_TRIGB_CLEAR {
+	CRTC_TRIGB_CNTL_CRTC_TRIGB_CLEAR_FALSE           = 0x0,
+	CRTC_TRIGB_CNTL_CRTC_TRIGB_CLEAR_TRUE            = 0x1,
+} CRTC_TRIGB_CNTL_CRTC_TRIGB_CLEAR;
+typedef enum CRTC_FORCE_COUNT_NOW_CNTL_CRTC_FORCE_COUNT_NOW_MODE {
+	CRTC_FORCE_COUNT_NOW_CNTL_CRTC_FORCE_COUNT_NOW_MODE_DISABLE= 0x0,
+	CRTC_FORCE_COUNT_NOW_CNTL_CRTC_FORCE_COUNT_NOW_MODE_HCOUNT= 0x1,
+	CRTC_FORCE_COUNT_NOW_CNTL_CRTC_FORCE_COUNT_NOW_MODE_HCOUNT_VCOUNT= 0x2,
+	CRTC_FORCE_COUNT_NOW_CNTL_CRTC_FORCE_COUNT_NOW_MODE_RESERVED= 0x3,
+} CRTC_FORCE_COUNT_NOW_CNTL_CRTC_FORCE_COUNT_NOW_MODE;
+typedef enum CRTC_FORCE_COUNT_NOW_CNTL_CRTC_FORCE_COUNT_NOW_CHECK {
+	CRTC_FORCE_COUNT_NOW_CNTL_CRTC_FORCE_COUNT_NOW_CHECK_FALSE= 0x0,
+	CRTC_FORCE_COUNT_NOW_CNTL_CRTC_FORCE_COUNT_NOW_CHECK_TRUE= 0x1,
+} CRTC_FORCE_COUNT_NOW_CNTL_CRTC_FORCE_COUNT_NOW_CHECK;
+typedef enum CRTC_FORCE_COUNT_NOW_CNTL_CRTC_FORCE_COUNT_NOW_TRIG_SEL {
+	CRTC_FORCE_COUNT_NOW_CNTL_CRTC_FORCE_COUNT_NOW_TRIG_SEL_FALSE= 0x0,
+	CRTC_FORCE_COUNT_NOW_CNTL_CRTC_FORCE_COUNT_NOW_TRIG_SEL_TRUE= 0x1,
+} CRTC_FORCE_COUNT_NOW_CNTL_CRTC_FORCE_COUNT_NOW_TRIG_SEL;
+typedef enum CRTC_FORCE_COUNT_NOW_CNTL_CRTC_FORCE_COUNT_NOW_CLEAR {
+	CRTC_FORCE_COUNT_NOW_CNTL_CRTC_FORCE_COUNT_NOW_CLEAR_FALSE= 0x0,
+	CRTC_FORCE_COUNT_NOW_CNTL_CRTC_FORCE_COUNT_NOW_CLEAR_TRUE= 0x1,
+} CRTC_FORCE_COUNT_NOW_CNTL_CRTC_FORCE_COUNT_NOW_CLEAR;
+typedef enum CRTC_FLOW_CONTROL_CRTC_FLOW_CONTROL_SOURCE_SELECT {
+	CRTC_FLOW_CONTROL_CRTC_FLOW_CONTROL_SOURCE_SELECT_LOGIC0= 0x0,
+	CRTC_FLOW_CONTROL_CRTC_FLOW_CONTROL_SOURCE_SELECT_GENERICF= 0x1,
+	CRTC_FLOW_CONTROL_CRTC_FLOW_CONTROL_SOURCE_SELECT_GENERICE= 0x2,
+	CRTC_FLOW_CONTROL_CRTC_FLOW_CONTROL_SOURCE_SELECT_HPD1= 0x3,
+	CRTC_FLOW_CONTROL_CRTC_FLOW_CONTROL_SOURCE_SELECT_HPD2= 0x4,
+	CRTC_FLOW_CONTROL_CRTC_FLOW_CONTROL_SOURCE_SELECT_DDC1DATA= 0x5,
+	CRTC_FLOW_CONTROL_CRTC_FLOW_CONTROL_SOURCE_SELECT_DDC1CLK= 0x6,
+	CRTC_FLOW_CONTROL_CRTC_FLOW_CONTROL_SOURCE_SELECT_DDC2DATA= 0x7,
+	CRTC_FLOW_CONTROL_CRTC_FLOW_CONTROL_SOURCE_SELECT_DDC2CLK= 0x8,
+	CRTC_FLOW_CONTROL_CRTC_FLOW_CONTROL_SOURCE_SELECT_DVOCLK= 0x9,
+	CRTC_FLOW_CONTROL_CRTC_FLOW_CONTROL_SOURCE_SELECT_MANUAL= 0xa,
+	CRTC_FLOW_CONTROL_CRTC_FLOW_CONTROL_SOURCE_SELECT_LOGIC1= 0xb,
+	CRTC_FLOW_CONTROL_CRTC_FLOW_CONTROL_SOURCE_SELECT_GENERICB= 0xc,
+	CRTC_FLOW_CONTROL_CRTC_FLOW_CONTROL_SOURCE_SELECT_GENERICA= 0xd,
+	CRTC_FLOW_CONTROL_CRTC_FLOW_CONTROL_SOURCE_SELECT_GENERICD= 0xe,
+	CRTC_FLOW_CONTROL_CRTC_FLOW_CONTROL_SOURCE_SELECT_GENERICC= 0xf,
+} CRTC_FLOW_CONTROL_CRTC_FLOW_CONTROL_SOURCE_SELECT;
+typedef enum CRTC_FLOW_CONTROL_CRTC_FLOW_CONTROL_POLARITY {
+	CRTC_FLOW_CONTROL_CRTC_FLOW_CONTROL_POLARITY_FALSE= 0x0,
+	CRTC_FLOW_CONTROL_CRTC_FLOW_CONTROL_POLARITY_TRUE= 0x1,
+} CRTC_FLOW_CONTROL_CRTC_FLOW_CONTROL_POLARITY;
+typedef enum CRTC_FLOW_CONTROL_CRTC_FLOW_CONTROL_GRANULARITY {
+	CRTC_FLOW_CONTROL_CRTC_FLOW_CONTROL_GRANULARITY_FALSE= 0x0,
+	CRTC_FLOW_CONTROL_CRTC_FLOW_CONTROL_GRANULARITY_TRUE= 0x1,
+} CRTC_FLOW_CONTROL_CRTC_FLOW_CONTROL_GRANULARITY;
+typedef enum CRTC_STEREO_FORCE_NEXT_EYE_CRTC_STEREO_FORCE_NEXT_EYE {
+	CRTC_STEREO_FORCE_NEXT_EYE_CRTC_STEREO_FORCE_NEXT_EYE_NO= 0x0,
+	CRTC_STEREO_FORCE_NEXT_EYE_CRTC_STEREO_FORCE_NEXT_EYE_RIGHT= 0x1,
+	CRTC_STEREO_FORCE_NEXT_EYE_CRTC_STEREO_FORCE_NEXT_EYE_LEFT= 0x2,
+	CRTC_STEREO_FORCE_NEXT_EYE_CRTC_STEREO_FORCE_NEXT_EYE_RESERVED= 0x3,
+} CRTC_STEREO_FORCE_NEXT_EYE_CRTC_STEREO_FORCE_NEXT_EYE;
+typedef enum CRTC_CONTROL_CRTC_MASTER_EN {
+	CRTC_CONTROL_CRTC_MASTER_EN_FALSE                = 0x0,
+	CRTC_CONTROL_CRTC_MASTER_EN_TRUE                 = 0x1,
+} CRTC_CONTROL_CRTC_MASTER_EN;
+typedef enum CRTC_BLANK_CONTROL_CRTC_BLANK_DATA_EN {
+	CRTC_BLANK_CONTROL_CRTC_BLANK_DATA_EN_FALSE      = 0x0,
+	CRTC_BLANK_CONTROL_CRTC_BLANK_DATA_EN_TRUE       = 0x1,
+} CRTC_BLANK_CONTROL_CRTC_BLANK_DATA_EN;
+typedef enum CRTC_BLANK_CONTROL_CRTC_BLANK_DE_MODE {
+	CRTC_BLANK_CONTROL_CRTC_BLANK_DE_MODE_FALSE      = 0x0,
+	CRTC_BLANK_CONTROL_CRTC_BLANK_DE_MODE_TRUE       = 0x1,
+} CRTC_BLANK_CONTROL_CRTC_BLANK_DE_MODE;
+typedef enum CRTC_INTERLACE_CONTROL_CRTC_INTERLACE_ENABLE {
+	CRTC_INTERLACE_CONTROL_CRTC_INTERLACE_ENABLE_FALSE= 0x0,
+	CRTC_INTERLACE_CONTROL_CRTC_INTERLACE_ENABLE_TRUE= 0x1,
+} CRTC_INTERLACE_CONTROL_CRTC_INTERLACE_ENABLE;
+typedef enum CRTC_INTERLACE_CONTROL_CRTC_INTERLACE_FORCE_NEXT_FIELD {
+	CRTC_INTERLACE_CONTROL_CRTC_INTERLACE_FORCE_NEXT_FIELD_NOT= 0x0,
+	CRTC_INTERLACE_CONTROL_CRTC_INTERLACE_FORCE_NEXT_FIELD_ODD= 0x1,
+	CRTC_INTERLACE_CONTROL_CRTC_INTERLACE_FORCE_NEXT_FIELD_EVEN= 0x2,
+	CRTC_INTERLACE_CONTROL_CRTC_INTERLACE_FORCE_NEXT_FIELD_NOT2= 0x3,
+} CRTC_INTERLACE_CONTROL_CRTC_INTERLACE_FORCE_NEXT_FIELD;
+typedef enum CRTC_FIELD_INDICATION_CONTROL_CRTC_FIELD_INDICATION_OUTPUT_POLARITY {
+	CRTC_FIELD_INDICATION_CONTROL_CRTC_FIELD_INDICATION_OUTPUT_POLARITY_FALSE= 0x0,
+	CRTC_FIELD_INDICATION_CONTROL_CRTC_FIELD_INDICATION_OUTPUT_POLARITY_TRUE= 0x1,
+} CRTC_FIELD_INDICATION_CONTROL_CRTC_FIELD_INDICATION_OUTPUT_POLARITY;
+typedef enum CRTC_FIELD_INDICATION_CONTROL_CRTC_FIELD_ALIGNMENT {
+	CRTC_FIELD_INDICATION_CONTROL_CRTC_FIELD_ALIGNMENT_FALSE= 0x0,
+	CRTC_FIELD_INDICATION_CONTROL_CRTC_FIELD_ALIGNMENT_TRUE= 0x1,
+} CRTC_FIELD_INDICATION_CONTROL_CRTC_FIELD_ALIGNMENT;
+typedef enum CRTC_COUNT_CONTROL_CRTC_HORZ_COUNT_BY2_EN {
+	CRTC_COUNT_CONTROL_CRTC_HORZ_COUNT_BY2_EN_FALSE  = 0x0,
+	CRTC_COUNT_CONTROL_CRTC_HORZ_COUNT_BY2_EN_TRUE   = 0x1,
+} CRTC_COUNT_CONTROL_CRTC_HORZ_COUNT_BY2_EN;
+typedef enum CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE_CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE {
+	CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE_CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE_FALSE= 0x0,
+	CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE_CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE_TRUE= 0x1,
+} CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE_CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE;
+typedef enum CRTC_VERT_SYNC_CONTROL_CRTC_FORCE_VSYNC_NEXT_LINE_CLEAR {
+	CRTC_VERT_SYNC_CONTROL_CRTC_FORCE_VSYNC_NEXT_LINE_CLEAR_FALSE= 0x0,
+	CRTC_VERT_SYNC_CONTROL_CRTC_FORCE_VSYNC_NEXT_LINE_CLEAR_TRUE= 0x1,
+} CRTC_VERT_SYNC_CONTROL_CRTC_FORCE_VSYNC_NEXT_LINE_CLEAR;
+typedef enum CRTC_VERT_SYNC_CONTROL_CRTC_AUTO_FORCE_VSYNC_MODE {
+	CRTC_VERT_SYNC_CONTROL_CRTC_AUTO_FORCE_VSYNC_MODE_DISABLE= 0x0,
+	CRTC_VERT_SYNC_CONTROL_CRTC_AUTO_FORCE_VSYNC_MODE_TRIGGERA= 0x1,
+	CRTC_VERT_SYNC_CONTROL_CRTC_AUTO_FORCE_VSYNC_MODE_TRIGGERB= 0x2,
+	CRTC_VERT_SYNC_CONTROL_CRTC_AUTO_FORCE_VSYNC_MODE_RESERVED= 0x3,
+} CRTC_VERT_SYNC_CONTROL_CRTC_AUTO_FORCE_VSYNC_MODE;
+typedef enum CRTC_STEREO_CONTROL_CRTC_STEREO_SYNC_OUTPUT_POLARITY {
+	CRTC_STEREO_CONTROL_CRTC_STEREO_SYNC_OUTPUT_POLARITY_FALSE= 0x0,
+	CRTC_STEREO_CONTROL_CRTC_STEREO_SYNC_OUTPUT_POLARITY_TRUE= 0x1,
+} CRTC_STEREO_CONTROL_CRTC_STEREO_SYNC_OUTPUT_POLARITY;
+typedef enum CRTC_STEREO_CONTROL_CRTC_STEREO_SYNC_SELECT_POLARITY {
+	CRTC_STEREO_CONTROL_CRTC_STEREO_SYNC_SELECT_POLARITY_FALSE= 0x0,
+	CRTC_STEREO_CONTROL_CRTC_STEREO_SYNC_SELECT_POLARITY_TRUE= 0x1,
+} CRTC_STEREO_CONTROL_CRTC_STEREO_SYNC_SELECT_POLARITY;
+typedef enum CRTC_STEREO_CONTROL_CRTC_STEREO_EYE_FLAG_POLARITY {
+	CRTC_STEREO_CONTROL_CRTC_STEREO_EYE_FLAG_POLARITY_FALSE= 0x0,
+	CRTC_STEREO_CONTROL_CRTC_STEREO_EYE_FLAG_POLARITY_TRUE= 0x1,
+} CRTC_STEREO_CONTROL_CRTC_STEREO_EYE_FLAG_POLARITY;
+typedef enum CRTC_STEREO_CONTROL_CRTC_STEREO_EN {
+	CRTC_STEREO_CONTROL_CRTC_STEREO_EN_FALSE         = 0x0,
+	CRTC_STEREO_CONTROL_CRTC_STEREO_EN_TRUE          = 0x1,
+} CRTC_STEREO_CONTROL_CRTC_STEREO_EN;
+typedef enum CRTC_SNAPSHOT_STATUS_CRTC_SNAPSHOT_CLEAR {
+	CRTC_SNAPSHOT_STATUS_CRTC_SNAPSHOT_CLEAR_FALSE   = 0x0,
+	CRTC_SNAPSHOT_STATUS_CRTC_SNAPSHOT_CLEAR_TRUE    = 0x1,
+} CRTC_SNAPSHOT_STATUS_CRTC_SNAPSHOT_CLEAR;
+typedef enum CRTC_SNAPSHOT_CONTROL_CRTC_AUTO_SNAPSHOT_TRIG_SEL {
+	CRTC_SNAPSHOT_CONTROL_CRTC_AUTO_SNAPSHOT_TRIG_SEL_DISABLE= 0x0,
+	CRTC_SNAPSHOT_CONTROL_CRTC_AUTO_SNAPSHOT_TRIG_SEL_TRIGGERA= 0x1,
+	CRTC_SNAPSHOT_CONTROL_CRTC_AUTO_SNAPSHOT_TRIG_SEL_TRIGGERB= 0x2,
+	CRTC_SNAPSHOT_CONTROL_CRTC_AUTO_SNAPSHOT_TRIG_SEL_RESERVED= 0x3,
+} CRTC_SNAPSHOT_CONTROL_CRTC_AUTO_SNAPSHOT_TRIG_SEL;
+typedef enum CRTC_START_LINE_CONTROL_CRTC_PROGRESSIVE_START_LINE_EARLY {
+	CRTC_START_LINE_CONTROL_CRTC_PROGRESSIVE_START_LINE_EARLY_FALSE= 0x0,
+	CRTC_START_LINE_CONTROL_CRTC_PROGRESSIVE_START_LINE_EARLY_TRUE= 0x1,
+} CRTC_START_LINE_CONTROL_CRTC_PROGRESSIVE_START_LINE_EARLY;
+typedef enum CRTC_START_LINE_CONTROL_CRTC_INTERLACE_START_LINE_EARLY {
+	CRTC_START_LINE_CONTROL_CRTC_INTERLACE_START_LINE_EARLY_FALSE= 0x0,
+	CRTC_START_LINE_CONTROL_CRTC_INTERLACE_START_LINE_EARLY_TRUE= 0x1,
+} CRTC_START_LINE_CONTROL_CRTC_INTERLACE_START_LINE_EARLY;
+typedef enum CRTC_START_LINE_CONTROL_CRTC_LEGACY_REQUESTOR_EN {
+	CRTC_START_LINE_CONTROL_CRTC_LEGACY_REQUESTOR_EN_FALSE= 0x0,
+	CRTC_START_LINE_CONTROL_CRTC_LEGACY_REQUESTOR_EN_TRUE= 0x1,
+} CRTC_START_LINE_CONTROL_CRTC_LEGACY_REQUESTOR_EN;
+typedef enum CRTC_START_LINE_CONTROL_CRTC_PREFETCH_EN {
+	CRTC_START_LINE_CONTROL_CRTC_PREFETCH_EN_FALSE   = 0x0,
+	CRTC_START_LINE_CONTROL_CRTC_PREFETCH_EN_TRUE    = 0x1,
+} CRTC_START_LINE_CONTROL_CRTC_PREFETCH_EN;
+typedef enum CRTC_INTERRUPT_CONTROL_CRTC_SNAPSHOT_INT_MSK {
+	CRTC_INTERRUPT_CONTROL_CRTC_SNAPSHOT_INT_MSK_FALSE= 0x0,
+	CRTC_INTERRUPT_CONTROL_CRTC_SNAPSHOT_INT_MSK_TRUE= 0x1,
+} CRTC_INTERRUPT_CONTROL_CRTC_SNAPSHOT_INT_MSK;
+typedef enum CRTC_INTERRUPT_CONTROL_CRTC_SNAPSHOT_INT_TYPE {
+	CRTC_INTERRUPT_CONTROL_CRTC_SNAPSHOT_INT_TYPE_FALSE= 0x0,
+	CRTC_INTERRUPT_CONTROL_CRTC_SNAPSHOT_INT_TYPE_TRUE= 0x1,
+} CRTC_INTERRUPT_CONTROL_CRTC_SNAPSHOT_INT_TYPE;
+typedef enum CRTC_INTERRUPT_CONTROL_CRTC_V_UPDATE_INT_MSK {
+	CRTC_INTERRUPT_CONTROL_CRTC_V_UPDATE_INT_MSK_FALSE= 0x0,
+	CRTC_INTERRUPT_CONTROL_CRTC_V_UPDATE_INT_MSK_TRUE= 0x1,
+} CRTC_INTERRUPT_CONTROL_CRTC_V_UPDATE_INT_MSK;
+typedef enum CRTC_INTERRUPT_CONTROL_CRTC_V_UPDATE_INT_TYPE {
+	CRTC_INTERRUPT_CONTROL_CRTC_V_UPDATE_INT_TYPE_FALSE= 0x0,
+	CRTC_INTERRUPT_CONTROL_CRTC_V_UPDATE_INT_TYPE_TRUE= 0x1,
+} CRTC_INTERRUPT_CONTROL_CRTC_V_UPDATE_INT_TYPE;
+typedef enum CRTC_INTERRUPT_CONTROL_CRTC_FORCE_COUNT_NOW_INT_MSK {
+	CRTC_INTERRUPT_CONTROL_CRTC_FORCE_COUNT_NOW_INT_MSK_FALSE= 0x0,
+	CRTC_INTERRUPT_CONTROL_CRTC_FORCE_COUNT_NOW_INT_MSK_TRUE= 0x1,
+} CRTC_INTERRUPT_CONTROL_CRTC_FORCE_COUNT_NOW_INT_MSK;
+typedef enum CRTC_INTERRUPT_CONTROL_CRTC_FORCE_COUNT_NOW_INT_TYPE {
+	CRTC_INTERRUPT_CONTROL_CRTC_FORCE_COUNT_NOW_INT_TYPE_FALSE= 0x0,
+	CRTC_INTERRUPT_CONTROL_CRTC_FORCE_COUNT_NOW_INT_TYPE_TRUE= 0x1,
+} CRTC_INTERRUPT_CONTROL_CRTC_FORCE_COUNT_NOW_INT_TYPE;
+typedef enum CRTC_INTERRUPT_CONTROL_CRTC_FORCE_VSYNC_NEXT_LINE_INT_MSK {
+	CRTC_INTERRUPT_CONTROL_CRTC_FORCE_VSYNC_NEXT_LINE_INT_MSK_FALSE= 0x0,
+	CRTC_INTERRUPT_CONTROL_CRTC_FORCE_VSYNC_NEXT_LINE_INT_MSK_TRUE= 0x1,
+} CRTC_INTERRUPT_CONTROL_CRTC_FORCE_VSYNC_NEXT_LINE_INT_MSK;
+typedef enum CRTC_INTERRUPT_CONTROL_CRTC_FORCE_VSYNC_NEXT_LINE_INT_TYPE {
+	CRTC_INTERRUPT_CONTROL_CRTC_FORCE_VSYNC_NEXT_LINE_INT_TYPE_FALSE= 0x0,
+	CRTC_INTERRUPT_CONTROL_CRTC_FORCE_VSYNC_NEXT_LINE_INT_TYPE_TRUE= 0x1,
+} CRTC_INTERRUPT_CONTROL_CRTC_FORCE_VSYNC_NEXT_LINE_INT_TYPE;
+typedef enum CRTC_INTERRUPT_CONTROL_CRTC_TRIGA_INT_MSK {
+	CRTC_INTERRUPT_CONTROL_CRTC_TRIGA_INT_MSK_FALSE  = 0x0,
+	CRTC_INTERRUPT_CONTROL_CRTC_TRIGA_INT_MSK_TRUE   = 0x1,
+} CRTC_INTERRUPT_CONTROL_CRTC_TRIGA_INT_MSK;
+typedef enum CRTC_INTERRUPT_CONTROL_CRTC_TRIGA_INT_TYPE {
+	CRTC_INTERRUPT_CONTROL_CRTC_TRIGA_INT_TYPE_FALSE = 0x0,
+	CRTC_INTERRUPT_CONTROL_CRTC_TRIGA_INT_TYPE_TRUE  = 0x1,
+} CRTC_INTERRUPT_CONTROL_CRTC_TRIGA_INT_TYPE;
+typedef enum CRTC_INTERRUPT_CONTROL_CRTC_TRIGB_INT_MSK {
+	CRTC_INTERRUPT_CONTROL_CRTC_TRIGB_INT_MSK_FALSE  = 0x0,
+	CRTC_INTERRUPT_CONTROL_CRTC_TRIGB_INT_MSK_TRUE   = 0x1,
+} CRTC_INTERRUPT_CONTROL_CRTC_TRIGB_INT_MSK;
+typedef enum CRTC_INTERRUPT_CONTROL_CRTC_TRIGB_INT_TYPE {
+	CRTC_INTERRUPT_CONTROL_CRTC_TRIGB_INT_TYPE_FALSE = 0x0,
+	CRTC_INTERRUPT_CONTROL_CRTC_TRIGB_INT_TYPE_TRUE  = 0x1,
+} CRTC_INTERRUPT_CONTROL_CRTC_TRIGB_INT_TYPE;
+typedef enum CRTC_INTERRUPT_CONTROL_CRTC_VSYNC_NOM_INT_MSK {
+	CRTC_INTERRUPT_CONTROL_CRTC_VSYNC_NOM_INT_MSK_FALSE= 0x0,
+	CRTC_INTERRUPT_CONTROL_CRTC_VSYNC_NOM_INT_MSK_TRUE= 0x1,
+} CRTC_INTERRUPT_CONTROL_CRTC_VSYNC_NOM_INT_MSK;
+typedef enum CRTC_INTERRUPT_CONTROL_CRTC_VSYNC_NOM_INT_TYPE {
+	CRTC_INTERRUPT_CONTROL_CRTC_VSYNC_NOM_INT_TYPE_FALSE= 0x0,
+	CRTC_INTERRUPT_CONTROL_CRTC_VSYNC_NOM_INT_TYPE_TRUE= 0x1,
+} CRTC_INTERRUPT_CONTROL_CRTC_VSYNC_NOM_INT_TYPE;
+typedef enum CRTC_INTERRUPT_CONTROL_CRTC_GSL_VSYNC_GAP_INT_MSK {
+	CRTC_INTERRUPT_CONTROL_CRTC_GSL_VSYNC_GAP_INT_MSK_FALSE= 0x0,
+	CRTC_INTERRUPT_CONTROL_CRTC_GSL_VSYNC_GAP_INT_MSK_TRUE= 0x1,
+} CRTC_INTERRUPT_CONTROL_CRTC_GSL_VSYNC_GAP_INT_MSK;
+typedef enum CRTC_INTERRUPT_CONTROL_CRTC_GSL_VSYNC_GAP_INT_TYPE {
+	CRTC_INTERRUPT_CONTROL_CRTC_GSL_VSYNC_GAP_INT_TYPE_FALSE= 0x0,
+	CRTC_INTERRUPT_CONTROL_CRTC_GSL_VSYNC_GAP_INT_TYPE_TRUE= 0x1,
+} CRTC_INTERRUPT_CONTROL_CRTC_GSL_VSYNC_GAP_INT_TYPE;
+typedef enum CRTC_UPDATE_LOCK_CRTC_UPDATE_LOCK {
+	CRTC_UPDATE_LOCK_CRTC_UPDATE_LOCK_FALSE          = 0x0,
+	CRTC_UPDATE_LOCK_CRTC_UPDATE_LOCK_TRUE           = 0x1,
+} CRTC_UPDATE_LOCK_CRTC_UPDATE_LOCK;
+typedef enum CRTC_DOUBLE_BUFFER_CONTROL_CRTC_UPDATE_INSTANTLY {
+	CRTC_DOUBLE_BUFFER_CONTROL_CRTC_UPDATE_INSTANTLY_FALSE= 0x0,
+	CRTC_DOUBLE_BUFFER_CONTROL_CRTC_UPDATE_INSTANTLY_TRUE= 0x1,
+} CRTC_DOUBLE_BUFFER_CONTROL_CRTC_UPDATE_INSTANTLY;
+typedef enum CRTC_DOUBLE_BUFFER_CONTROL_CRTC_BLANK_DATA_DOUBLE_BUFFER_EN {
+	CRTC_DOUBLE_BUFFER_CONTROL_CRTC_BLANK_DATA_DOUBLE_BUFFER_EN_FALSE= 0x0,
+	CRTC_DOUBLE_BUFFER_CONTROL_CRTC_BLANK_DATA_DOUBLE_BUFFER_EN_TRUE= 0x1,
+} CRTC_DOUBLE_BUFFER_CONTROL_CRTC_BLANK_DATA_DOUBLE_BUFFER_EN;
+typedef enum CRTC_VGA_PARAMETER_CAPTURE_MODE_CRTC_VGA_PARAMETER_CAPTURE_MODE {
+	CRTC_VGA_PARAMETER_CAPTURE_MODE_CRTC_VGA_PARAMETER_CAPTURE_MODE_FALSE= 0x0,
+	CRTC_VGA_PARAMETER_CAPTURE_MODE_CRTC_VGA_PARAMETER_CAPTURE_MODE_TRUE= 0x1,
+} CRTC_VGA_PARAMETER_CAPTURE_MODE_CRTC_VGA_PARAMETER_CAPTURE_MODE;
+typedef enum CRTC_TEST_PATTERN_CONTROL_CRTC_TEST_PATTERN_EN {
+	CRTC_TEST_PATTERN_CONTROL_CRTC_TEST_PATTERN_EN_FALSE= 0x0,
+	CRTC_TEST_PATTERN_CONTROL_CRTC_TEST_PATTERN_EN_TRUE= 0x1,
+} CRTC_TEST_PATTERN_CONTROL_CRTC_TEST_PATTERN_EN;
+typedef enum CRTC_TEST_PATTERN_CONTROL_CRTC_TEST_PATTERN_MODE {
+	CRTC_TEST_PATTERN_CONTROL_CRTC_TEST_PATTERN_MODE_RGB= 0x0,
+	CRTC_TEST_PATTERN_CONTROL_CRTC_TEST_PATTERN_MODE_YCBCR601= 0x1,
+	CRTC_TEST_PATTERN_CONTROL_CRTC_TEST_PATTERN_MODE_YCBCR709= 0x2,
+	CRTC_TEST_PATTERN_CONTROL_CRTC_TEST_PATTERN_MODE_VBARS= 0x3,
+	CRTC_TEST_PATTERN_CONTROL_CRTC_TEST_PATTERN_MODE_HBARS= 0x4,
+	CRTC_TEST_PATTERN_CONTROL_CRTC_TEST_PATTERN_MODE_SRRGB= 0x5,
+	CRTC_TEST_PATTERN_CONTROL_CRTC_TEST_PATTERN_MODE_DRRGB= 0x6,
+	CRTC_TEST_PATTERN_CONTROL_CRTC_TEST_PATTERN_MODE_XRBIAS= 0x7,
+} CRTC_TEST_PATTERN_CONTROL_CRTC_TEST_PATTERN_MODE;
+typedef enum CRTC_TEST_PATTERN_CONTROL_CRTC_TEST_PATTERN_DYNAMIC_RANGE {
+	CRTC_TEST_PATTERN_CONTROL_CRTC_TEST_PATTERN_DYNAMIC_RANGE_FALSE= 0x0,
+	CRTC_TEST_PATTERN_CONTROL_CRTC_TEST_PATTERN_DYNAMIC_RANGE_TRUE= 0x1,
+} CRTC_TEST_PATTERN_CONTROL_CRTC_TEST_PATTERN_DYNAMIC_RANGE;
+typedef enum CRTC_TEST_PATTERN_CONTROL_CRTC_TEST_PATTERN_COLOR_FORMAT {
+	CRTC_TEST_PATTERN_CONTROL_CRTC_TEST_PATTERN_COLOR_FORMAT_6BPC= 0x0,
+	CRTC_TEST_PATTERN_CONTROL_CRTC_TEST_PATTERN_COLOR_FORMAT_8BPC= 0x1,
+	CRTC_TEST_PATTERN_CONTROL_CRTC_TEST_PATTERN_COLOR_FORMAT_10BPC= 0x2,
+	CRTC_TEST_PATTERN_CONTROL_CRTC_TEST_PATTERN_COLOR_FORMAT_RESERVED= 0x3,
+} CRTC_TEST_PATTERN_CONTROL_CRTC_TEST_PATTERN_COLOR_FORMAT;
+typedef enum MASTER_UPDATE_LOCK_MASTER_UPDATE_LOCK {
+	MASTER_UPDATE_LOCK_MASTER_UPDATE_LOCK_FALSE      = 0x0,
+	MASTER_UPDATE_LOCK_MASTER_UPDATE_LOCK_TRUE       = 0x1,
+} MASTER_UPDATE_LOCK_MASTER_UPDATE_LOCK;
+typedef enum MASTER_UPDATE_LOCK_GSL_CONTROL_MASTER_UPDATE_LOCK {
+	MASTER_UPDATE_LOCK_GSL_CONTROL_MASTER_UPDATE_LOCK_FALSE= 0x0,
+	MASTER_UPDATE_LOCK_GSL_CONTROL_MASTER_UPDATE_LOCK_TRUE= 0x1,
+} MASTER_UPDATE_LOCK_GSL_CONTROL_MASTER_UPDATE_LOCK;
+typedef enum MASTER_UPDATE_LOCK_UNDERFLOW_UPDATE_LOCK {
+	MASTER_UPDATE_LOCK_UNDERFLOW_UPDATE_LOCK_FALSE   = 0x0,
+	MASTER_UPDATE_LOCK_UNDERFLOW_UPDATE_LOCK_TRUE    = 0x1,
+} MASTER_UPDATE_LOCK_UNDERFLOW_UPDATE_LOCK;
+typedef enum MASTER_UPDATE_MODE_MASTER_UPDATE_MODE {
+	MASTER_UPDATE_MODE_MASTER_UPDATE_MODE_BETWEEN    = 0x0,
+	MASTER_UPDATE_MODE_MASTER_UPDATE_MODE_HSYNCA     = 0x1,
+	MASTER_UPDATE_MODE_MASTER_UPDATE_MODE_VSYNCA     = 0x2,
+	MASTER_UPDATE_MODE_MASTER_UPDATE_MODE_BEFORE     = 0x3,
+} MASTER_UPDATE_MODE_MASTER_UPDATE_MODE;
+typedef enum MASTER_UPDATE_MODE_MASTER_UPDATE_INTERLACED_MODE {
+	MASTER_UPDATE_MODE_MASTER_UPDATE_INTERLACED_MODE_BOTH= 0x0,
+	MASTER_UPDATE_MODE_MASTER_UPDATE_INTERLACED_MODE_EVEN= 0x1,
+	MASTER_UPDATE_MODE_MASTER_UPDATE_INTERLACED_MODE_ODD= 0x2,
+	MASTER_UPDATE_MODE_MASTER_UPDATE_INTERLACED_MODE_RESERVED= 0x3,
+} MASTER_UPDATE_MODE_MASTER_UPDATE_INTERLACED_MODE;
+typedef enum CRTC_MVP_INBAND_CNTL_INSERT_CRTC_MVP_INBAND_OUT_MODE {
+	CRTC_MVP_INBAND_CNTL_INSERT_CRTC_MVP_INBAND_OUT_MODE_DISABLE= 0x0,
+	CRTC_MVP_INBAND_CNTL_INSERT_CRTC_MVP_INBAND_OUT_MODE_DEBUG= 0x1,
+	CRTC_MVP_INBAND_CNTL_INSERT_CRTC_MVP_INBAND_OUT_MODE_NORMAL= 0x2,
+} CRTC_MVP_INBAND_CNTL_INSERT_CRTC_MVP_INBAND_OUT_MODE;
+typedef enum CRTC_MVP_STATUS_CRTC_FLIP_NOW_CLEAR {
+	CRTC_MVP_STATUS_CRTC_FLIP_NOW_CLEAR_FALSE        = 0x0,
+	CRTC_MVP_STATUS_CRTC_FLIP_NOW_CLEAR_TRUE         = 0x1,
+} CRTC_MVP_STATUS_CRTC_FLIP_NOW_CLEAR;
+typedef enum CRTC_MVP_STATUS_CRTC_AFR_HSYNC_SWITCH_DONE_CLEAR {
+	CRTC_MVP_STATUS_CRTC_AFR_HSYNC_SWITCH_DONE_CLEAR_FALSE= 0x0,
+	CRTC_MVP_STATUS_CRTC_AFR_HSYNC_SWITCH_DONE_CLEAR_TRUE= 0x1,
+} CRTC_MVP_STATUS_CRTC_AFR_HSYNC_SWITCH_DONE_CLEAR;
+typedef enum CRTC_V_UPDATE_INT_STATUS_CRTC_V_UPDATE_INT_CLEAR {
+	CRTC_V_UPDATE_INT_STATUS_CRTC_V_UPDATE_INT_CLEAR_FALSE= 0x0,
+	CRTC_V_UPDATE_INT_STATUS_CRTC_V_UPDATE_INT_CLEAR_TRUE= 0x1,
+} CRTC_V_UPDATE_INT_STATUS_CRTC_V_UPDATE_INT_CLEAR;
+typedef enum CRTC_VERTICAL_INTERRUPT0_CONTROL_CRTC_VERTICAL_INTERRUPT0_OUTPUT_POLARITY {
+	CRTC_VERTICAL_INTERRUPT0_CONTROL_CRTC_VERTICAL_INTERRUPT0_OUTPUT_POLARITY_FALSE= 0x0,
+	CRTC_VERTICAL_INTERRUPT0_CONTROL_CRTC_VERTICAL_INTERRUPT0_OUTPUT_POLARITY_TRUE= 0x1,
+} CRTC_VERTICAL_INTERRUPT0_CONTROL_CRTC_VERTICAL_INTERRUPT0_OUTPUT_POLARITY;
+typedef enum CRTC_VERTICAL_INTERRUPT0_CONTROL_CRTC_VERTICAL_INTERRUPT0_INT_ENABLE {
+	CRTC_VERTICAL_INTERRUPT0_CONTROL_CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_FALSE= 0x0,
+	CRTC_VERTICAL_INTERRUPT0_CONTROL_CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_TRUE= 0x1,
+} CRTC_VERTICAL_INTERRUPT0_CONTROL_CRTC_VERTICAL_INTERRUPT0_INT_ENABLE;
+typedef enum CRTC_VERTICAL_INTERRUPT0_CONTROL_CRTC_VERTICAL_INTERRUPT0_CLEAR {
+	CRTC_VERTICAL_INTERRUPT0_CONTROL_CRTC_VERTICAL_INTERRUPT0_CLEAR_FALSE= 0x0,
+	CRTC_VERTICAL_INTERRUPT0_CONTROL_CRTC_VERTICAL_INTERRUPT0_CLEAR_TRUE= 0x1,
+} CRTC_VERTICAL_INTERRUPT0_CONTROL_CRTC_VERTICAL_INTERRUPT0_CLEAR;
+typedef enum CRTC_VERTICAL_INTERRUPT0_CONTROL_CRTC_VERTICAL_INTERRUPT0_INT_TYPE {
+	CRTC_VERTICAL_INTERRUPT0_CONTROL_CRTC_VERTICAL_INTERRUPT0_INT_TYPE_FALSE= 0x0,
+	CRTC_VERTICAL_INTERRUPT0_CONTROL_CRTC_VERTICAL_INTERRUPT0_INT_TYPE_TRUE= 0x1,
+} CRTC_VERTICAL_INTERRUPT0_CONTROL_CRTC_VERTICAL_INTERRUPT0_INT_TYPE;
+typedef enum CRTC_VERTICAL_INTERRUPT1_CONTROL_CRTC_VERTICAL_INTERRUPT1_CLEAR {
+	CRTC_VERTICAL_INTERRUPT1_CONTROL_CRTC_VERTICAL_INTERRUPT1_CLEAR_CLEAR_FALSE= 0x0,
+	CRTC_VERTICAL_INTERRUPT1_CONTROL_CRTC_VERTICAL_INTERRUPT1_CLEAR_TRUE= 0x1,
+} CRTC_VERTICAL_INTERRUPT1_CONTROL_CRTC_VERTICAL_INTERRUPT1_CLEAR;
+typedef enum CRTC_VERTICAL_INTERRUPT1_CONTROL_CRTC_VERTICAL_INTERRUPT1_INT_ENABLE {
+	CRTC_VERTICAL_INTERRUPT1_CONTROL_CRTC_VERTICAL_INTERRUPT1_INT_ENABLE_FALSE= 0x0,
+	CRTC_VERTICAL_INTERRUPT1_CONTROL_CRTC_VERTICAL_INTERRUPT1_INT_ENABLE_TRUE= 0x1,
+} CRTC_VERTICAL_INTERRUPT1_CONTROL_CRTC_VERTICAL_INTERRUPT1_INT_ENABLE;
+typedef enum CRTC_VERTICAL_INTERRUPT1_CONTROL_CRTC_VERTICAL_INTERRUPT1_INT_TYPE {
+	CRTC_VERTICAL_INTERRUPT1_CONTROL_CRTC_VERTICAL_INTERRUPT1_INT_TYPE_FALSE= 0x0,
+	CRTC_VERTICAL_INTERRUPT1_CONTROL_CRTC_VERTICAL_INTERRUPT1_INT_TYPE_TRUE= 0x1,
+} CRTC_VERTICAL_INTERRUPT1_CONTROL_CRTC_VERTICAL_INTERRUPT1_INT_TYPE;
+typedef enum CRTC_VERTICAL_INTERRUPT2_CONTROL_CRTC_VERTICAL_INTERRUPT2_CLEAR {
+	CRTC_VERTICAL_INTERRUPT2_CONTROL_CRTC_VERTICAL_INTERRUPT2_CLEAR_CLEAR_FALSE= 0x0,
+	CRTC_VERTICAL_INTERRUPT2_CONTROL_CRTC_VERTICAL_INTERRUPT2_CLEAR_TRUE= 0x1,
+} CRTC_VERTICAL_INTERRUPT2_CONTROL_CRTC_VERTICAL_INTERRUPT2_CLEAR;
+typedef enum CRTC_VERTICAL_INTERRUPT2_CONTROL_CRTC_VERTICAL_INTERRUPT2_INT_ENABLE {
+	CRTC_VERTICAL_INTERRUPT2_CONTROL_CRTC_VERTICAL_INTERRUPT2_INT_ENABLE_FALSE= 0x0,
+	CRTC_VERTICAL_INTERRUPT2_CONTROL_CRTC_VERTICAL_INTERRUPT2_INT_ENABLE_TRUE= 0x1,
+} CRTC_VERTICAL_INTERRUPT2_CONTROL_CRTC_VERTICAL_INTERRUPT2_INT_ENABLE;
+typedef enum CRTC_VERTICAL_INTERRUPT2_CONTROL_CRTC_VERTICAL_INTERRUPT2_INT_TYPE {
+	CRTC_VERTICAL_INTERRUPT2_CONTROL_CRTC_VERTICAL_INTERRUPT2_INT_TYPE_FALSE= 0x0,
+	CRTC_VERTICAL_INTERRUPT2_CONTROL_CRTC_VERTICAL_INTERRUPT2_INT_TYPE_TRUE= 0x1,
+} CRTC_VERTICAL_INTERRUPT2_CONTROL_CRTC_VERTICAL_INTERRUPT2_INT_TYPE;
+typedef enum CRTC_CRC_CNTL_CRTC_CRC_EN {
+	CRTC_CRC_CNTL_CRTC_CRC_EN_FALSE                  = 0x0,
+	CRTC_CRC_CNTL_CRTC_CRC_EN_TRUE                   = 0x1,
+} CRTC_CRC_CNTL_CRTC_CRC_EN;
+typedef enum CRTC_CRC_CNTL_CRTC_CRC_CONT_EN {
+	CRTC_CRC_CNTL_CRTC_CRC_CONT_EN_FALSE             = 0x0,
+	CRTC_CRC_CNTL_CRTC_CRC_CONT_EN_TRUE              = 0x1,
+} CRTC_CRC_CNTL_CRTC_CRC_CONT_EN;
+typedef enum CRTC_CRC_CNTL_CRTC_CRC_STEREO_MODE {
+	CRTC_CRC_CNTL_CRTC_CRC_STEREO_MODE_LEFT          = 0x0,
+	CRTC_CRC_CNTL_CRTC_CRC_STEREO_MODE_RIGHT         = 0x1,
+	CRTC_CRC_CNTL_CRTC_CRC_STEREO_MODE_BOTH_EYES     = 0x2,
+	CRTC_CRC_CNTL_CRTC_CRC_STEREO_MODE_BOTH_FIELDS   = 0x3,
+} CRTC_CRC_CNTL_CRTC_CRC_STEREO_MODE;
+typedef enum CRTC_CRC_CNTL_CRTC_CRC_INTERLACE_MODE {
+	CRTC_CRC_CNTL_CRTC_CRC_INTERLACE_MODE_TOP        = 0x0,
+	CRTC_CRC_CNTL_CRTC_CRC_INTERLACE_MODE_BOTTOM     = 0x1,
+	CRTC_CRC_CNTL_CRTC_CRC_INTERLACE_MODE_BOTH_BOTTOM= 0x2,
+	CRTC_CRC_CNTL_CRTC_CRC_INTERLACE_MODE_BOTH_FIELD = 0x3,
+} CRTC_CRC_CNTL_CRTC_CRC_INTERLACE_MODE;
+typedef enum CRTC_CRC_CNTL_CRTC_CRC_USE_NEW_AND_REPEATED_PIXELS {
+	CRTC_CRC_CNTL_CRTC_CRC_USE_NEW_AND_REPEATED_PIXELS_FALSE= 0x0,
+	CRTC_CRC_CNTL_CRTC_CRC_USE_NEW_AND_REPEATED_PIXELS_TRUE= 0x1,
+} CRTC_CRC_CNTL_CRTC_CRC_USE_NEW_AND_REPEATED_PIXELS;
+typedef enum CRTC_CRC_CNTL_CRTC_CRTC_CRC0_SELECT {
+	CRTC_CRC_CNTL_CRTC_CRTC_CRC0_SELECT_UAB          = 0x0,
+	CRTC_CRC_CNTL_CRTC_CRTC_CRC0_SELECT_UA_B         = 0x1,
+	CRTC_CRC_CNTL_CRTC_CRTC_CRC0_SELECT_U_AB         = 0x2,
+	CRTC_CRC_CNTL_CRTC_CRTC_CRC0_SELECT_U_A_B        = 0x3,
+	CRTC_CRC_CNTL_CRTC_CRTC_CRC0_SELECT_IAB          = 0x4,
+	CRTC_CRC_CNTL_CRTC_CRTC_CRC0_SELECT_IA_B         = 0x5,
+	CRTC_CRC_CNTL_CRTC_CRTC_CRC0_SELECT_I_AB         = 0x6,
+	CRTC_CRC_CNTL_CRTC_CRTC_CRC0_SELECT_I_A_B        = 0x7,
+} CRTC_CRC_CNTL_CRTC_CRTC_CRC0_SELECT;
+typedef enum CRTC_CRC_CNTL_CRTC_CRTC_CRC1_SELECT {
+	CRTC_CRC_CNTL_CRTC_CRTC_CRC1_SELECT_UAB          = 0x0,
+	CRTC_CRC_CNTL_CRTC_CRTC_CRC1_SELECT_UA_B         = 0x1,
+	CRTC_CRC_CNTL_CRTC_CRTC_CRC1_SELECT_U_AB         = 0x2,
+	CRTC_CRC_CNTL_CRTC_CRTC_CRC1_SELECT_U_A_B        = 0x3,
+	CRTC_CRC_CNTL_CRTC_CRTC_CRC1_SELECT_IAB          = 0x4,
+	CRTC_CRC_CNTL_CRTC_CRTC_CRC1_SELECT_IA_B         = 0x5,
+	CRTC_CRC_CNTL_CRTC_CRTC_CRC1_SELECT_I_AB         = 0x6,
+	CRTC_CRC_CNTL_CRTC_CRTC_CRC1_SELECT_I_A_B        = 0x7,
+} CRTC_CRC_CNTL_CRTC_CRTC_CRC1_SELECT;
+typedef enum CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_ENABLE {
+	CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_ENABLE_DISABLE= 0x0,
+	CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_ENABLE_ONESHOT= 0x1,
+	CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_ENABLE_CONTINUOUS= 0x2,
+	CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_ENABLE_RESERVED= 0x3,
+} CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_ENABLE;
+typedef enum CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_HCOUNT_MODE_ENABLE {
+	CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_HCOUNT_MODE_ENABLE_FALSE= 0x0,
+	CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_HCOUNT_MODE_ENABLE_TRUE= 0x1,
+} CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_HCOUNT_MODE_ENABLE;
+typedef enum CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_JITTER_FILTERING_ENABLE {
+	CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_JITTER_FILTERING_ENABLE_FALSE= 0x0,
+	CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_JITTER_FILTERING_ENABLE_TRUE= 0x1,
+} CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_JITTER_FILTERING_ENABLE;
+typedef enum CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_JITTER_FILTERING_WINDOW {
+	CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_JITTER_FILTERING_WINDOW_1pixel= 0x0,
+	CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_JITTER_FILTERING_WINDOW_2pixel= 0x1,
+	CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_JITTER_FILTERING_WINDOW_3pixel= 0x2,
+	CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_JITTER_FILTERING_WINDOW_4pixel= 0x3,
+} CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_JITTER_FILTERING_WINDOW;
+typedef enum CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_WINDOW_ENABLE {
+	CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_WINDOW_ENABLE_FALSE= 0x0,
+	CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_WINDOW_ENABLE_TRUE= 0x1,
+} CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_WINDOW_ENABLE;
+typedef enum CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_WINDOW_UPDATE {
+	CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_WINDOW_UPDATE_FALSE= 0x0,
+	CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_WINDOW_UPDATE_TRUE= 0x1,
+} CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_WINDOW_UPDATE;
+typedef enum CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_VSYNC_POLARITY {
+	CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_VSYNC_POLARITY_FALSE= 0x0,
+	CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_VSYNC_POLARITY_TRUE= 0x1,
+} CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_VSYNC_POLARITY;
+typedef enum CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_HSYNC_POLARITY {
+	CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_HSYNC_POLARITY_FALSE= 0x0,
+	CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_HSYNC_POLARITY_TRUE= 0x1,
+} CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_HSYNC_POLARITY;
+typedef enum CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_INTERLACE_MODE {
+	CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_INTERLACE_MODE_FALSE= 0x0,
+	CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_INTERLACE_MODE_TRUE= 0x1,
+} CRTC_EXT_TIMING_SYNC_CONTROL_CRTC_EXT_TIMING_SYNC_INTERLACE_MODE;
+typedef enum CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_LOSS_INT_ENABLE {
+	CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_LOSS_INT_ENABLE_FALSE= 0x0,
+	CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_LOSS_INT_ENABLE_TRUE= 0x1,
+} CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_LOSS_INT_ENABLE;
+typedef enum CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_LOSS_CLEAR {
+	CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_LOSS_CLEAR_FALSE= 0x0,
+	CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_LOSS_CLEAR_TRUE= 0x1,
+} CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_LOSS_CLEAR;
+typedef enum CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_LOSS_INT_TYPE {
+	CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_LOSS_INT_TYPE_FALSE= 0x0,
+	CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_LOSS_INT_TYPE_TRUE= 0x1,
+} CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_LOSS_INT_TYPE;
+typedef enum CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_LOSS_FRAME_COUNT {
+	CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_LOSS_FRAME_COUNT_1FRAME= 0x0,
+	CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_LOSS_FRAME_COUNT_2FRAME= 0x1,
+	CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_LOSS_FRAME_COUNT_4FRAME= 0x2,
+	CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_LOSS_FRAME_COUNT_8FRAME= 0x3,
+	CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_LOSS_FRAME_COUNT_16FRAME= 0x4,
+	CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_LOSS_FRAME_COUNT_32FRAME= 0x5,
+	CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_LOSS_FRAME_COUNT_64FRAME= 0x6,
+	CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_LOSS_FRAME_COUNT_128FRAME= 0x7,
+} CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_LOSS_FRAME_COUNT;
+typedef enum CRTC_EXT_TIMING_SYNC_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_INT_ENABLE {
+	CRTC_EXT_TIMING_SYNC_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_INT_ENABLE_FALSE= 0x0,
+	CRTC_EXT_TIMING_SYNC_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_INT_ENABLE_TRUE= 0x1,
+} CRTC_EXT_TIMING_SYNC_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_INT_ENABLE;
+typedef enum CRTC_EXT_TIMING_SYNC_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_CLEAR {
+	CRTC_EXT_TIMING_SYNC_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_CLEAR_FALSE= 0x0,
+	CRTC_EXT_TIMING_SYNC_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_CLEAR_TRUE= 0x1,
+} CRTC_EXT_TIMING_SYNC_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_CLEAR;
+typedef enum CRTC_EXT_TIMING_SYNC_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_INT_TYPE {
+	CRTC_EXT_TIMING_SYNC_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_INT_TYPE_FALSE= 0x0,
+	CRTC_EXT_TIMING_SYNC_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_INT_TYPE_TRUE= 0x1,
+} CRTC_EXT_TIMING_SYNC_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_INT_TYPE;
+typedef enum CRTC_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_SIGNAL_INT_ENABLE {
+	CRTC_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_SIGNAL_INT_ENABLE_FALSE= 0x0,
+	CRTC_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_SIGNAL_INT_ENABLE_TRUE= 0x1,
+} CRTC_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_SIGNAL_INT_ENABLE;
+typedef enum CRTC_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_SIGNAL_CLEAR {
+	CRTC_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_SIGNAL_CLEAR_FALSE= 0x0,
+	CRTC_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_SIGNAL_CLEAR_TRUE= 0x1,
+} CRTC_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_SIGNAL_CLEAR;
+typedef enum CRTC_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_SIGNAL_INT_TYPE {
+	CRTC_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_SIGNAL_INT_TYPE_FALSE= 0x0,
+	CRTC_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_SIGNAL_INT_TYPE_TRUE= 0x1,
+} CRTC_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_CONTROL_CRTC_EXT_TIMING_SYNC_SIGNAL_INT_TYPE;
+typedef enum CRTC_STATIC_SCREEN_CONTROL_CRTC_CPU_SS_INT_ENABLE {
+	CRTC_STATIC_SCREEN_CONTROL_CRTC_CPU_SS_INT_ENABLE_FALSE= 0x0,
+	CRTC_STATIC_SCREEN_CONTROL_CRTC_CPU_SS_INT_ENABLE_TRUE= 0x1,
+} CRTC_STATIC_SCREEN_CONTROL_CRTC_CPU_SS_INT_ENABLE;
+typedef enum CRTC_STATIC_SCREEN_CONTROL_CRTC_CPU_SS_INT_CLEAR {
+	CRTC_STATIC_SCREEN_CONTROL_CRTC_CPU_SS_INT_CLEAR_FALSE= 0x0,
+	CRTC_STATIC_SCREEN_CONTROL_CRTC_CPU_SS_INT_CLEAR_TRUE= 0x1,
+} CRTC_STATIC_SCREEN_CONTROL_CRTC_CPU_SS_INT_CLEAR;
+typedef enum CRTC_STATIC_SCREEN_CONTROL_CRTC_CPU_SS_INT_TYPE {
+	CRTC_STATIC_SCREEN_CONTROL_CRTC_CPU_SS_INT_TYPE_FALSE= 0x0,
+	CRTC_STATIC_SCREEN_CONTROL_CRTC_CPU_SS_INT_TYPE_TRUE= 0x1,
+} CRTC_STATIC_SCREEN_CONTROL_CRTC_CPU_SS_INT_TYPE;
+typedef enum CRTC_STATIC_SCREEN_CONTROL_CRTC_STATIC_SCREEN_OVERRIDE {
+	CRTC_STATIC_SCREEN_CONTROL_CRTC_STATIC_SCREEN_OVERRIDE_FALSE= 0x0,
+	CRTC_STATIC_SCREEN_CONTROL_CRTC_STATIC_SCREEN_OVERRIDE_TRUE= 0x1,
+} CRTC_STATIC_SCREEN_CONTROL_CRTC_STATIC_SCREEN_OVERRIDE;
+typedef enum CRTC_STATIC_SCREEN_CONTROL_CRTC_STATIC_SCREEN_OVERRIDE_VALUE {
+	CRTC_STATIC_SCREEN_CONTROL_CRTC_STATIC_SCREEN_OVERRIDE_VALUE_OFF= 0x0,
+	CRTC_STATIC_SCREEN_CONTROL_CRTC_STATIC_SCREEN_OVERRIDE_VALUE_ON= 0x1,
+} CRTC_STATIC_SCREEN_CONTROL_CRTC_STATIC_SCREEN_OVERRIDE_VALUE;
+typedef enum CRTC_3D_STRUCTURE_CONTROL_CRTC_3D_STRUCTURE_EN {
+	CRTC_3D_STRUCTURE_CONTROL_CRTC_3D_STRUCTURE_EN_FALSE= 0x0,
+	CRTC_3D_STRUCTURE_CONTROL_CRTC_3D_STRUCTURE_EN_TRUE= 0x1,
+} CRTC_3D_STRUCTURE_CONTROL_CRTC_3D_STRUCTURE_EN;
+typedef enum CRTC_3D_STRUCTURE_CONTROL_CRTC_3D_STRUCTURE_EN_DB {
+	CRTC_3D_STRUCTURE_CONTROL_CRTC_3D_STRUCTURE_EN_DB_FALSE= 0x0,
+	CRTC_3D_STRUCTURE_CONTROL_CRTC_3D_STRUCTURE_EN_DB_TRUE= 0x1,
+} CRTC_3D_STRUCTURE_CONTROL_CRTC_3D_STRUCTURE_EN_DB;
+typedef enum CRTC_3D_STRUCTURE_CONTROL_CRTC_3D_STRUCTURE_V_UPDATE_MODE {
+	CRTC_3D_STRUCTURE_CONTROL_CRTC_3D_STRUCTURE_V_UPDATE_MODE_BLOCK_BOTH= 0x0,
+	CRTC_3D_STRUCTURE_CONTROL_CRTC_3D_STRUCTURE_V_UPDATE_MODE_BLOCK_INTERLACE= 0x1,
+	CRTC_3D_STRUCTURE_CONTROL_CRTC_3D_STRUCTURE_V_UPDATE_MODE_BLOCK_PROGRASSIVE= 0x2,
+	CRTC_3D_STRUCTURE_CONTROL_CRTC_3D_STRUCTURE_V_UPDATE_MODE_RESERVED= 0x3,
+} CRTC_3D_STRUCTURE_CONTROL_CRTC_3D_STRUCTURE_V_UPDATE_MODE;
+typedef enum CRTC_3D_STRUCTURE_CONTROL_CRTC_3D_STRUCTURE_STEREO_SEL_OVR {
+	CRTC_3D_STRUCTURE_CONTROL_CRTC_3D_STRUCTURE_STEREO_SEL_OVR_FALSE= 0x0,
+	CRTC_3D_STRUCTURE_CONTROL_CRTC_3D_STRUCTURE_STEREO_SEL_OVR_TRUE= 0x1,
+} CRTC_3D_STRUCTURE_CONTROL_CRTC_3D_STRUCTURE_STEREO_SEL_OVR;
+typedef enum CRTC_V_SYNC_A_POL {
+	CRTC_V_SYNC_A_POL_HIGH                           = 0x0,
+	CRTC_V_SYNC_A_POL_LOW                            = 0x1,
+} CRTC_V_SYNC_A_POL;
+typedef enum CRTC_H_SYNC_A_POL {
+	CRTC_H_SYNC_A_POL_HIGH                           = 0x0,
+	CRTC_H_SYNC_A_POL_LOW                            = 0x1,
+} CRTC_H_SYNC_A_POL;
+typedef enum CRTC_HORZ_REPETITION_COUNT {
+	CRTC_HORZ_REPETITION_COUNT_0                     = 0x0,
+	CRTC_HORZ_REPETITION_COUNT_1                     = 0x1,
+	CRTC_HORZ_REPETITION_COUNT_2                     = 0x2,
+	CRTC_HORZ_REPETITION_COUNT_3                     = 0x3,
+	CRTC_HORZ_REPETITION_COUNT_4                     = 0x4,
+	CRTC_HORZ_REPETITION_COUNT_5                     = 0x5,
+	CRTC_HORZ_REPETITION_COUNT_6                     = 0x6,
+	CRTC_HORZ_REPETITION_COUNT_7                     = 0x7,
+	CRTC_HORZ_REPETITION_COUNT_8                     = 0x8,
+	CRTC_HORZ_REPETITION_COUNT_9                     = 0x9,
+	CRTC_HORZ_REPETITION_COUNT_10                    = 0xa,
+	CRTC_HORZ_REPETITION_COUNT_11                    = 0xb,
+	CRTC_HORZ_REPETITION_COUNT_12                    = 0xc,
+	CRTC_HORZ_REPETITION_COUNT_13                    = 0xd,
+	CRTC_HORZ_REPETITION_COUNT_14                    = 0xe,
+	CRTC_HORZ_REPETITION_COUNT_15                    = 0xf,
+} CRTC_HORZ_REPETITION_COUNT;
+typedef enum PERFCOUNTER_CVALUE_SEL {
+	PERFCOUNTER_CVALUE_SEL_47_0                      = 0x0,
+	PERFCOUNTER_CVALUE_SEL_15_0                      = 0x1,
+	PERFCOUNTER_CVALUE_SEL_31_16                     = 0x2,
+	PERFCOUNTER_CVALUE_SEL_47_32                     = 0x3,
+	PERFCOUNTER_CVALUE_SEL_11_0                      = 0x4,
+	PERFCOUNTER_CVALUE_SEL_23_12                     = 0x5,
+	PERFCOUNTER_CVALUE_SEL_35_24                     = 0x6,
+	PERFCOUNTER_CVALUE_SEL_47_36                     = 0x7,
+} PERFCOUNTER_CVALUE_SEL;
+typedef enum PERFCOUNTER_INC_MODE {
+	PERFCOUNTER_INC_MODE_MULTI_BIT                   = 0x0,
+	PERFCOUNTER_INC_MODE_BOTH_EDGE                   = 0x1,
+	PERFCOUNTER_INC_MODE_LSB                         = 0x2,
+	PERFCOUNTER_INC_MODE_POS_EDGE                    = 0x3,
+} PERFCOUNTER_INC_MODE;
+typedef enum PERFCOUNTER_HW_CNTL_SEL {
+	PERFCOUNTER_HW_CNTL_SEL_RUNEN                    = 0x0,
+	PERFCOUNTER_HW_CNTL_SEL_CNTOFF                   = 0x1,
+} PERFCOUNTER_HW_CNTL_SEL;
+typedef enum PERFCOUNTER_RUNEN_MODE {
+	PERFCOUNTER_RUNEN_MODE_LEVEL                     = 0x0,
+	PERFCOUNTER_RUNEN_MODE_EDGE                      = 0x1,
+} PERFCOUNTER_RUNEN_MODE;
+typedef enum PERFCOUNTER_CNTOFF_START_DIS {
+	PERFCOUNTER_CNTOFF_START_ENABLE                  = 0x0,
+	PERFCOUNTER_CNTOFF_START_DISABLE                 = 0x1,
+} PERFCOUNTER_CNTOFF_START_DIS;
+typedef enum PERFCOUNTER_RESTART_EN {
+	PERFCOUNTER_RESTART_DISABLE                      = 0x0,
+	PERFCOUNTER_RESTART_ENABLE                       = 0x1,
+} PERFCOUNTER_RESTART_EN;
+typedef enum PERFCOUNTER_INT_EN {
+	PERFCOUNTER_INT_DISABLE                          = 0x0,
+	PERFCOUNTER_INT_ENABLE                           = 0x1,
+} PERFCOUNTER_INT_EN;
+typedef enum PERFCOUNTER_OFF_MASK {
+	PERFCOUNTER_OFF_MASK_DISABLE                     = 0x0,
+	PERFCOUNTER_OFF_MASK_ENABLE                      = 0x1,
+} PERFCOUNTER_OFF_MASK;
+typedef enum PERFCOUNTER_ACTIVE {
+	PERFCOUNTER_IS_IDLE                              = 0x0,
+	PERFCOUNTER_IS_ACTIVE                            = 0x1,
+} PERFCOUNTER_ACTIVE;
+typedef enum PERFCOUNTER_INT_TYPE {
+	PERFCOUNTER_INT_TYPE_LEVEL                       = 0x0,
+	PERFCOUNTER_INT_TYPE_PULSE                       = 0x1,
+} PERFCOUNTER_INT_TYPE;
+typedef enum PERFCOUNTER_COUNTED_VALUE_TYPE {
+	PERFCOUNTER_COUNTED_VALUE_TYPE_ACC               = 0x0,
+	PERFCOUNTER_COUNTED_VALUE_TYPE_MAX               = 0x1,
+} PERFCOUNTER_COUNTED_VALUE_TYPE;
+typedef enum PERFCOUNTER_CNTL_SEL {
+	PERFCOUNTER_CNTL_SEL_0                           = 0x0,
+	PERFCOUNTER_CNTL_SEL_1                           = 0x1,
+	PERFCOUNTER_CNTL_SEL_2                           = 0x2,
+	PERFCOUNTER_CNTL_SEL_3                           = 0x3,
+	PERFCOUNTER_CNTL_SEL_4                           = 0x4,
+	PERFCOUNTER_CNTL_SEL_5                           = 0x5,
+	PERFCOUNTER_CNTL_SEL_6                           = 0x6,
+	PERFCOUNTER_CNTL_SEL_7                           = 0x7,
+} PERFCOUNTER_CNTL_SEL;
+typedef enum PERFCOUNTER_CNT0_STATE {
+	PERFCOUNTER_CNT0_STATE_RESET                     = 0x0,
+	PERFCOUNTER_CNT0_STATE_START                     = 0x1,
+	PERFCOUNTER_CNT0_STATE_FREEZE                    = 0x2,
+	PERFCOUNTER_CNT0_STATE_HW                        = 0x3,
+} PERFCOUNTER_CNT0_STATE;
+typedef enum PERFCOUNTER_STATE_SEL0 {
+	PERFCOUNTER_STATE_SEL0_GLOBAL                    = 0x0,
+	PERFCOUNTER_STATE_SEL0_LOCAL                     = 0x1,
+} PERFCOUNTER_STATE_SEL0;
+typedef enum PERFCOUNTER_CNT1_STATE {
+	PERFCOUNTER_CNT1_STATE_RESET                     = 0x0,
+	PERFCOUNTER_CNT1_STATE_START                     = 0x1,
+	PERFCOUNTER_CNT1_STATE_FREEZE                    = 0x2,
+	PERFCOUNTER_CNT1_STATE_HW                        = 0x3,
+} PERFCOUNTER_CNT1_STATE;
+typedef enum PERFCOUNTER_STATE_SEL1 {
+	PERFCOUNTER_STATE_SEL1_GLOBAL                    = 0x0,
+	PERFCOUNTER_STATE_SEL1_LOCAL                     = 0x1,
+} PERFCOUNTER_STATE_SEL1;
+typedef enum PERFCOUNTER_CNT2_STATE {
+	PERFCOUNTER_CNT2_STATE_RESET                     = 0x0,
+	PERFCOUNTER_CNT2_STATE_START                     = 0x1,
+	PERFCOUNTER_CNT2_STATE_FREEZE                    = 0x2,
+	PERFCOUNTER_CNT2_STATE_HW                        = 0x3,
+} PERFCOUNTER_CNT2_STATE;
+typedef enum PERFCOUNTER_STATE_SEL2 {
+	PERFCOUNTER_STATE_SEL2_GLOBAL                    = 0x0,
+	PERFCOUNTER_STATE_SEL2_LOCAL                     = 0x1,
+} PERFCOUNTER_STATE_SEL2;
+typedef enum PERFCOUNTER_CNT3_STATE {
+	PERFCOUNTER_CNT3_STATE_RESET                     = 0x0,
+	PERFCOUNTER_CNT3_STATE_START                     = 0x1,
+	PERFCOUNTER_CNT3_STATE_FREEZE                    = 0x2,
+	PERFCOUNTER_CNT3_STATE_HW                        = 0x3,
+} PERFCOUNTER_CNT3_STATE;
+typedef enum PERFCOUNTER_STATE_SEL3 {
+	PERFCOUNTER_STATE_SEL3_GLOBAL                    = 0x0,
+	PERFCOUNTER_STATE_SEL3_LOCAL                     = 0x1,
+} PERFCOUNTER_STATE_SEL3;
+typedef enum PERFCOUNTER_CNT4_STATE {
+	PERFCOUNTER_CNT4_STATE_RESET                     = 0x0,
+	PERFCOUNTER_CNT4_STATE_START                     = 0x1,
+	PERFCOUNTER_CNT4_STATE_FREEZE                    = 0x2,
+	PERFCOUNTER_CNT4_STATE_HW                        = 0x3,
+} PERFCOUNTER_CNT4_STATE;
+typedef enum PERFCOUNTER_STATE_SEL4 {
+	PERFCOUNTER_STATE_SEL4_GLOBAL                    = 0x0,
+	PERFCOUNTER_STATE_SEL4_LOCAL                     = 0x1,
+} PERFCOUNTER_STATE_SEL4;
+typedef enum PERFCOUNTER_CNT5_STATE {
+	PERFCOUNTER_CNT5_STATE_RESET                     = 0x0,
+	PERFCOUNTER_CNT5_STATE_START                     = 0x1,
+	PERFCOUNTER_CNT5_STATE_FREEZE                    = 0x2,
+	PERFCOUNTER_CNT5_STATE_HW                        = 0x3,
+} PERFCOUNTER_CNT5_STATE;
+typedef enum PERFCOUNTER_STATE_SEL5 {
+	PERFCOUNTER_STATE_SEL5_GLOBAL                    = 0x0,
+	PERFCOUNTER_STATE_SEL5_LOCAL                     = 0x1,
+} PERFCOUNTER_STATE_SEL5;
+typedef enum PERFCOUNTER_CNT6_STATE {
+	PERFCOUNTER_CNT6_STATE_RESET                     = 0x0,
+	PERFCOUNTER_CNT6_STATE_START                     = 0x1,
+	PERFCOUNTER_CNT6_STATE_FREEZE                    = 0x2,
+	PERFCOUNTER_CNT6_STATE_HW                        = 0x3,
+} PERFCOUNTER_CNT6_STATE;
+typedef enum PERFCOUNTER_STATE_SEL6 {
+	PERFCOUNTER_STATE_SEL6_GLOBAL                    = 0x0,
+	PERFCOUNTER_STATE_SEL6_LOCAL                     = 0x1,
+} PERFCOUNTER_STATE_SEL6;
+typedef enum PERFCOUNTER_CNT7_STATE {
+	PERFCOUNTER_CNT7_STATE_RESET                     = 0x0,
+	PERFCOUNTER_CNT7_STATE_START                     = 0x1,
+	PERFCOUNTER_CNT7_STATE_FREEZE                    = 0x2,
+	PERFCOUNTER_CNT7_STATE_HW                        = 0x3,
+} PERFCOUNTER_CNT7_STATE;
+typedef enum PERFCOUNTER_STATE_SEL7 {
+	PERFCOUNTER_STATE_SEL7_GLOBAL                    = 0x0,
+	PERFCOUNTER_STATE_SEL7_LOCAL                     = 0x1,
+} PERFCOUNTER_STATE_SEL7;
+typedef enum PERFMON_STATE {
+	PERFMON_STATE_RESET                              = 0x0,
+	PERFMON_STATE_START                              = 0x1,
+	PERFMON_STATE_FREEZE                             = 0x2,
+	PERFMON_STATE_HW                                 = 0x3,
+} PERFMON_STATE;
+typedef enum PERFMON_CNTOFF_AND_OR {
+	PERFMON_CNTOFF_OR                                = 0x0,
+	PERFMON_CNTOFF_AND                               = 0x1,
+} PERFMON_CNTOFF_AND_OR;
+typedef enum PERFMON_CNTOFF_INT_EN {
+	PERFMON_CNTOFF_INT_DISABLE                       = 0x0,
+	PERFMON_CNTOFF_INT_ENABLE                        = 0x1,
+} PERFMON_CNTOFF_INT_EN;
+typedef enum PERFMON_CNTOFF_INT_TYPE {
+	PERFMON_CNTOFF_INT_TYPE_LEVEL                    = 0x0,
+	PERFMON_CNTOFF_INT_TYPE_PULSE                    = 0x1,
+} PERFMON_CNTOFF_INT_TYPE;
+typedef enum ENABLE {
+	DISABLE_THE_FEATURE                              = 0x0,
+	ENABLE_THE_FEATURE                               = 0x1,
+} ENABLE;
+typedef enum ENABLE_CLOCK {
+	DISABLE_THE_CLOCK                                = 0x0,
+	ENABLE_THE_CLOCK                                 = 0x1,
+} ENABLE_CLOCK;
+typedef enum FORCE_VBI {
+	FORCE_VBI_LOW                                    = 0x0,
+	FORCE_VBI_HIGH                                   = 0x1,
+} FORCE_VBI;
+typedef enum OVERRIDE_CGTT_SCLK {
+	OVERRIDE_CGTT_SCLK_NOOP                          = 0x0,
+	SET_OVERRIDE_CGTT_SCLK                           = 0x1,
+} OVERRIDE_CGTT_SCLK;
+typedef enum CLEAR_SMU_INTR {
+	SMU_INTR_STATUS_NOOP                             = 0x0,
+	SMU_INTR_STATUS_CLEAR                            = 0x1,
+} CLEAR_SMU_INTR;
+typedef enum STATIC_SCREEN_SMU_INTR {
+	STATIC_SCREEN_SMU_INTR_NOOP                      = 0x0,
+	SET_STATIC_SCREEN_SMU_INTR                       = 0x1,
+} STATIC_SCREEN_SMU_INTR;
+typedef enum JITTER_REMOVE_DISABLE {
+	ENABLE_JITTER_REMOVAL                            = 0x0,
+	DISABLE_JITTER_REMOVAL                           = 0x1,
+} JITTER_REMOVE_DISABLE;
+typedef enum DISABLE_CLOCK_GATING {
+	CLOCK_GATING_ENABLED                             = 0x0,
+	CLOCK_GATING_DISABLED                            = 0x1,
+} DISABLE_CLOCK_GATING;
+typedef enum DISABLE_CLOCK_GATING_IN_DCO {
+	CLOCK_GATING_ENABLED_IN_DCO                      = 0x0,
+	CLOCK_GATING_DISABLED_IN_DCO                     = 0x1,
+} DISABLE_CLOCK_GATING_IN_DCO;
+typedef enum DCCG_DEEP_COLOR_CNTL {
+	DCCG_DEEP_COLOR_DTO_DISABLE                      = 0x0,
+	DCCG_DEEP_COLOR_DTO_5_4_RATIO                    = 0x1,
+	DCCG_DEEP_COLOR_DTO_3_2_RATIO                    = 0x2,
+	DCCG_DEEP_COLOR_DTO_2_1_RATIO                    = 0x3,
+} DCCG_DEEP_COLOR_CNTL;
+typedef enum REFCLK_CLOCK_EN {
+	REFCLK_CLOCK_EN_PCIE_REFCLK                      = 0x0,
+	REFCLK_CLOCK_EN_ALLOW_SRC                        = 0x1,
+} REFCLK_CLOCK_EN;
+typedef enum REFCLK_SRC_SEL {
+	REFCLK_SRC_SEL_XTALIN                            = 0x0,
+	REFCLK_SRC_SEL_DISPPLL                           = 0x1,
+} REFCLK_SRC_SEL;
+typedef enum DPREFCLK_SRC_SEL {
+	DPREFCLK_SRC_SEL_CK                              = 0x0,
+	DPREFCLK_SRC_SEL_P0PLL                           = 0x1,
+	DPREFCLK_SRC_SEL_P1PLL                           = 0x2,
+	DPREFCLK_SRC_SEL_P2PLL                           = 0x3,
+	DPREFCLK_SRC_SEL_P3PLL                           = 0x4,
+} DPREFCLK_SRC_SEL;
+typedef enum XTAL_REF_SEL {
+	XTAL_REF_SEL_1X                                  = 0x0,
+	XTAL_REF_SEL_2X                                  = 0x1,
+} XTAL_REF_SEL;
+typedef enum XTAL_REF_CLOCK_SOURCE_SEL {
+	XTAL_REF_CLOCK_SOURCE_SEL_XTALIN                 = 0x0,
+	XTAL_REF_CLOCK_SOURCE_SEL_PPLL                   = 0x1,
+} XTAL_REF_CLOCK_SOURCE_SEL;
+typedef enum MICROSECOND_TIME_BASE_CLOCK_SOURCE_SEL {
+	MICROSECOND_TIME_BASE_CLOCK_IS_XTALIN            = 0x0,
+	MICROSECOND_TIME_BASE_CLOCK_IS_PPLL_REFCLK       = 0x1,
+} MICROSECOND_TIME_BASE_CLOCK_SOURCE_SEL;
+typedef enum ALLOW_SR_ON_TRANS_REQ {
+	ALLOW_SR_ON_TRANS_REQ_ENABLE                     = 0x0,
+	ALLOW_SR_ON_TRANS_REQ_DISABLE                    = 0x1,
+} ALLOW_SR_ON_TRANS_REQ;
+typedef enum MILLISECOND_TIME_BASE_CLOCK_SOURCE_SEL {
+	MILLISECOND_TIME_BASE_CLOCK_IS_XTALIN            = 0x0,
+	MILLISECOND_TIME_BASE_CLOCK_IS_PPLL_REFCLK       = 0x1,
+} MILLISECOND_TIME_BASE_CLOCK_SOURCE_SEL;
+typedef enum PIPE_PIXEL_RATE_SOURCE {
+	PIPE_PIXEL_RATE_SOURCE_P0PLL                     = 0x0,
+	PIPE_PIXEL_RATE_SOURCE_P1PLL                     = 0x1,
+	PIPE_PIXEL_RATE_SOURCE_P2PLL                     = 0x2,
+} PIPE_PIXEL_RATE_SOURCE;
+typedef enum PIPE_PHYPLL_PIXEL_RATE_SOURCE {
+	PIPE_PHYPLL_PIXEL_RATE_SOURCE_UNIPHYA            = 0x0,
+	PIPE_PHYPLL_PIXEL_RATE_SOURCE_UNIPHYB            = 0x1,
+	PIPE_PHYPLL_PIXEL_RATE_SOURCE_UNIPHYC            = 0x2,
+	PIPE_PHYPLL_PIXEL_RATE_SOURCE_UNIPHYD            = 0x3,
+	PIPE_PHYPLL_PIXEL_RATE_SOURCE_UNIPHYE            = 0x4,
+	PIPE_PHYPLL_PIXEL_RATE_SOURCE_UNIPHYF            = 0x5,
+	PIPE_PHYPLL_PIXEL_RATE_SOURCE_UNIPHYG            = 0x6,
+} PIPE_PHYPLL_PIXEL_RATE_SOURCE;
+typedef enum PIPE_PIXEL_RATE_PLL_SOURCE {
+	PIPE_PIXEL_RATE_PLL_SOURCE_PHYPLL                = 0x0,
+	PIPE_PIXEL_RATE_PLL_SOURCE_DISPPLL               = 0x1,
+} PIPE_PIXEL_RATE_PLL_SOURCE;
+typedef enum DP_DTO_DS_DISABLE {
+	DP_DTO_DESPREAD_DISABLE                          = 0x0,
+	DP_DTO_DESPREAD_ENABLE                           = 0x1,
+} DP_DTO_DS_DISABLE;
+typedef enum CRTC_ADD_PIXEL {
+	CRTC_ADD_PIXEL_NOOP                              = 0x0,
+	CRTC_ADD_PIXEL_FORCE                             = 0x1,
+} CRTC_ADD_PIXEL;
+typedef enum CRTC_DROP_PIXEL {
+	CRTC_DROP_PIXEL_NOOP                             = 0x0,
+	CRTC_DROP_PIXEL_FORCE                            = 0x1,
+} CRTC_DROP_PIXEL;
+typedef enum SYMCLK_FE_FORCE_EN {
+	SYMCLK_FE_FORCE_EN_DISABLE                       = 0x0,
+	SYMCLK_FE_FORCE_EN_ENABLE                        = 0x1,
+} SYMCLK_FE_FORCE_EN;
+typedef enum SYMCLK_FE_FORCE_SRC {
+	SYMCLK_FE_FORCE_SRC_UNIPHYA                      = 0x0,
+	SYMCLK_FE_FORCE_SRC_UNIPHYB                      = 0x1,
+	SYMCLK_FE_FORCE_SRC_UNIPHYC                      = 0x2,
+	SYMCLK_FE_FORCE_SRC_UNIPHYD                      = 0x3,
+	SYMCLK_FE_FORCE_SRC_UNIPHYE                      = 0x4,
+	SYMCLK_FE_FORCE_SRC_UNIPHYF                      = 0x5,
+	SYMCLK_FE_FORCE_SRC_UNIPHYG                      = 0x6,
+} SYMCLK_FE_FORCE_SRC;
+typedef enum DPDBG_CLK_FORCE_EN {
+	DPDBG_CLK_FORCE_EN_DISABLE                       = 0x0,
+	DPDBG_CLK_FORCE_EN_ENABLE                        = 0x1,
+} DPDBG_CLK_FORCE_EN;
+typedef enum DVOACLK_COARSE_SKEW_CNTL {
+	DVOACLK_COARSE_SKEW_CNTL_NO_ADJUSTMENT           = 0x0,
+	DVOACLK_COARSE_SKEW_CNTL_DELAY_1_STEP            = 0x1,
+	DVOACLK_COARSE_SKEW_CNTL_DELAY_2_STEPS           = 0x2,
+	DVOACLK_COARSE_SKEW_CNTL_DELAY_3_STEPS           = 0x3,
+	DVOACLK_COARSE_SKEW_CNTL_DELAY_4_STEPS           = 0x4,
+	DVOACLK_COARSE_SKEW_CNTL_DELAY_5_STEPS           = 0x5,
+	DVOACLK_COARSE_SKEW_CNTL_DELAY_6_STEPS           = 0x6,
+	DVOACLK_COARSE_SKEW_CNTL_DELAY_7_STEPS           = 0x7,
+	DVOACLK_COARSE_SKEW_CNTL_DELAY_8_STEPS           = 0x8,
+	DVOACLK_COARSE_SKEW_CNTL_DELAY_9_STEPS           = 0x9,
+	DVOACLK_COARSE_SKEW_CNTL_DELAY_10_STEPS          = 0xa,
+	DVOACLK_COARSE_SKEW_CNTL_DELAY_11_STEPS          = 0xb,
+	DVOACLK_COARSE_SKEW_CNTL_DELAY_12_STEPS          = 0xc,
+	DVOACLK_COARSE_SKEW_CNTL_DELAY_13_STEPS          = 0xd,
+	DVOACLK_COARSE_SKEW_CNTL_DELAY_14_STEPS          = 0xe,
+	DVOACLK_COARSE_SKEW_CNTL_DELAY_15_STEPS          = 0xf,
+	DVOACLK_COARSE_SKEW_CNTL_EARLY_1_STEP            = 0x10,
+	DVOACLK_COARSE_SKEW_CNTL_EARLY_2_STEPS           = 0x11,
+	DVOACLK_COARSE_SKEW_CNTL_EARLY_3_STEPS           = 0x12,
+	DVOACLK_COARSE_SKEW_CNTL_EARLY_4_STEPS           = 0x13,
+	DVOACLK_COARSE_SKEW_CNTL_EARLY_5_STEPS           = 0x14,
+	DVOACLK_COARSE_SKEW_CNTL_EARLY_6_STEPS           = 0x15,
+	DVOACLK_COARSE_SKEW_CNTL_EARLY_7_STEPS           = 0x16,
+	DVOACLK_COARSE_SKEW_CNTL_EARLY_8_STEPS           = 0x17,
+	DVOACLK_COARSE_SKEW_CNTL_EARLY_9_STEPS           = 0x18,
+	DVOACLK_COARSE_SKEW_CNTL_EARLY_10_STEPS          = 0x19,
+	DVOACLK_COARSE_SKEW_CNTL_EARLY_11_STEPS          = 0x1a,
+	DVOACLK_COARSE_SKEW_CNTL_EARLY_12_STEPS          = 0x1b,
+	DVOACLK_COARSE_SKEW_CNTL_EARLY_13_STEPS          = 0x1c,
+	DVOACLK_COARSE_SKEW_CNTL_EARLY_14_STEPS          = 0x1d,
+	DVOACLK_COARSE_SKEW_CNTL_EARLY_15_STEPS          = 0x1e,
+} DVOACLK_COARSE_SKEW_CNTL;
+typedef enum DVOACLK_FINE_SKEW_CNTL {
+	DVOACLK_FINE_SKEW_CNTL_NO_ADJUSTMENT             = 0x0,
+	DVOACLK_FINE_SKEW_CNTL_DELAY_1_STEP              = 0x1,
+	DVOACLK_FINE_SKEW_CNTL_DELAY_2_STEPS             = 0x2,
+	DVOACLK_FINE_SKEW_CNTL_DELAY_3_STEPS             = 0x3,
+	DVOACLK_FINE_SKEW_CNTL_EARLY_1_STEP              = 0x4,
+	DVOACLK_FINE_SKEW_CNTL_EARLY_2_STEPS             = 0x5,
+	DVOACLK_FINE_SKEW_CNTL_EARLY_3_STEPS             = 0x6,
+	DVOACLK_FINE_SKEW_CNTL_EARLY_4_STEPS             = 0x7,
+} DVOACLK_FINE_SKEW_CNTL;
+typedef enum DVOACLKD_IN_PHASE {
+	DVOACLKD_IN_OPPOSITE_PHASE_WITH_PCLK_DVO         = 0x0,
+	DVOACLKD_IN_PHASE_WITH_PCLK_DVO                  = 0x1,
+} DVOACLKD_IN_PHASE;
+typedef enum DVOACLKC_IN_PHASE {
+	DVOACLKC_IN_OPPOSITE_PHASE_WITH_PCLK_DVO         = 0x0,
+	DVOACLKC_IN_PHASE_WITH_PCLK_DVO                  = 0x1,
+} DVOACLKC_IN_PHASE;
+typedef enum DVOACLKC_MVP_IN_PHASE {
+	DVOACLKC_MVP_IN_OPPOSITE_PHASE_WITH_PCLK_DVO     = 0x0,
+	DVOACLKC_MVP_IN_PHASE_WITH_PCLK_DVO              = 0x1,
+} DVOACLKC_MVP_IN_PHASE;
+typedef enum DVOACLKC_MVP_SKEW_PHASE_OVERRIDE {
+	DVOACLKC_MVP_SKEW_PHASE_OVERRIDE_DISABLE         = 0x0,
+	DVOACLKC_MVP_SKEW_PHASE_OVERRIDE_ENABLE          = 0x1,
+} DVOACLKC_MVP_SKEW_PHASE_OVERRIDE;
+typedef enum MVP_CLK_SRC_SEL {
+	MVP_CLK_SRC_SEL_RSRV                             = 0x0,
+	MVP_CLK_SRC_SEL_IO_1                             = 0x1,
+	MVP_CLK_SRC_SEL_IO_2                             = 0x2,
+	MVP_CLK_SRC_SEL_REFCLK                           = 0x3,
+} MVP_CLK_SRC_SEL;
+typedef enum DCCG_AUDIO_DTO0_SOURCE_SEL {
+	DCCG_AUDIO_DTO0_SOURCE_SEL_CRTC0                 = 0x0,
+	DCCG_AUDIO_DTO0_SOURCE_SEL_CRTC1                 = 0x1,
+	DCCG_AUDIO_DTO0_SOURCE_SEL_CRTC2                 = 0x2,
+	DCCG_AUDIO_DTO0_SOURCE_SEL_CRTC3                 = 0x3,
+	DCCG_AUDIO_DTO0_SOURCE_SEL_CRTC4                 = 0x4,
+	DCCG_AUDIO_DTO0_SOURCE_SEL_CRTC5                 = 0x5,
+	DCCG_AUDIO_DTO0_SOURCE_SEL_RESERVED              = 0x6,
+} DCCG_AUDIO_DTO0_SOURCE_SEL;
+typedef enum DCCG_AUDIO_DTO_SEL {
+	DCCG_AUDIO_DTO_SEL_AUDIO_DTO0                    = 0x0,
+	DCCG_AUDIO_DTO_SEL_AUDIO_DTO1                    = 0x1,
+	DCCG_AUDIO_DTO_SEL_NO_AUDIO_DTO                  = 0x2,
+} DCCG_AUDIO_DTO_SEL;
+typedef enum DCCG_AUDIO_DTO2_SOURCE_SEL {
+	DCCG_AUDIO_DTO2_SOURCE_SEL_AMCLK0                = 0x0,
+	DCCG_AUDIO_DTO2_SOURCE_SEL_AMCLK1                = 0x1,
+} DCCG_AUDIO_DTO2_SOURCE_SEL;
+typedef enum DCCG_AUDIO_DTO_USE_512FBR_DTO {
+	DCCG_AUDIO_DTO_USE_128FBR_FOR_DP                 = 0x0,
+	DCCG_AUDIO_DTO_USE_512FBR_FOR_DP                 = 0x1,
+} DCCG_AUDIO_DTO_USE_512FBR_DTO;
+typedef enum DCCG_DBG_EN {
+	DCCG_DBG_EN_DISABLE                              = 0x0,
+	DCCG_DBG_EN_ENABLE                               = 0x1,
+} DCCG_DBG_EN;
+typedef enum DCCG_DBG_BLOCK_SEL {
+	DCCG_DBG_BLOCK_SEL_DCCG                          = 0x0,
+	DCCG_DBG_BLOCK_SEL_PMON                          = 0x1,
+	DCCG_DBG_BLOCK_SEL_PMON2                         = 0x2,
+} DCCG_DBG_BLOCK_SEL;
+typedef enum DCCG_DBG_CLOCK_SEL {
+	DCCG_DBG_CLOCK_SEL_DISPCLK                       = 0x0,
+	DCCG_DBG_CLOCK_SEL_SCLK                          = 0x1,
+	DCCG_DBG_CLOCK_SEL_MVPCLK                        = 0x2,
+	DCCG_DBG_CLOCK_SEL_DVOCLK                        = 0x3,
+	DCCG_DBG_CLOCK_SEL_DACCLK                        = 0x4,
+	DCCG_DBG_CLOCK_SEL_REFCLK                        = 0x5,
+	DCCG_DBG_CLOCK_SEL_SYMCLKA                       = 0x6,
+	DCCG_DBG_CLOCK_SEL_SYMCLKB                       = 0x7,
+	DCCG_DBG_CLOCK_SEL_SYMCLKC                       = 0x8,
+	DCCG_DBG_CLOCK_SEL_SYMCLKD                       = 0x9,
+	DCCG_DBG_CLOCK_SEL_SYMCLKE                       = 0xa,
+	DCCG_DBG_CLOCK_SEL_SYMCLKG                       = 0xb,
+	DCCG_DBG_CLOCK_SEL_SYMCLKF                       = 0xc,
+	DCCG_DBG_CLOCK_SEL_RSRV                          = 0xd,
+	DCCG_DBG_CLOCK_SEL_AOMCLK0                       = 0xe,
+	DCCG_DBG_CLOCK_SEL_AOMCLK1                       = 0xf,
+	DCCG_DBG_CLOCK_SEL_AOMCLK2                       = 0x10,
+	DCCG_DBG_CLOCK_SEL_DPREFCLK                      = 0x11,
+	DCCG_DBG_CLOCK_SEL_UNB_DB_CLK                    = 0x12,
+	DCCG_DBG_CLOCK_SEL_DSICLK                        = 0x13,
+	DCCG_DBG_CLOCK_SEL_BYTECLK                       = 0x14,
+	DCCG_DBG_CLOCK_SEL_ESCCLK                        = 0x15,
+	DCCG_DBG_CLOCK_SEL_SYMCLKLPA                     = 0x16,
+	DCCG_DBG_CLOCK_SEL_SYMCLKLPB                     = 0x17,
+} DCCG_DBG_CLOCK_SEL;
+typedef enum DCCG_DBG_OUT_BLOCK_SEL {
+	DCCG_DBG_OUT_BLOCK_SEL_DCCG                      = 0x0,
+	DCCG_DBG_OUT_BLOCK_SEL_DCO                       = 0x1,
+	DCCG_DBG_OUT_BLOCK_SEL_DCIO                      = 0x2,
+	DCCG_DBG_OUT_BLOCK_SEL_DSI                       = 0x3,
+} DCCG_DBG_OUT_BLOCK_SEL;
+typedef enum DISPCLK_FREQ_RAMP_DONE {
+	DISPCLK_FREQ_RAMP_IN_PROGRESS                    = 0x0,
+	DISPCLK_FREQ_RAMP_COMPLETED                      = 0x1,
+} DISPCLK_FREQ_RAMP_DONE;
+typedef enum DCCG_FIFO_ERRDET_RESET {
+	DCCG_FIFO_ERRDET_RESET_NOOP                      = 0x0,
+	DCCG_FIFO_ERRDET_RESET_FORCE                     = 0x1,
+} DCCG_FIFO_ERRDET_RESET;
+typedef enum DCCG_FIFO_ERRDET_STATE {
+	DCCG_FIFO_ERRDET_STATE_DETECTION                 = 0x0,
+	DCCG_FIFO_ERRDET_STATE_CALIBRATION               = 0x1,
+} DCCG_FIFO_ERRDET_STATE;
+typedef enum DCCG_FIFO_ERRDET_OVR_EN {
+	DCCG_FIFO_ERRDET_OVR_DISABLE                     = 0x0,
+	DCCG_FIFO_ERRDET_OVR_ENABLE                      = 0x1,
+} DCCG_FIFO_ERRDET_OVR_EN;
+typedef enum DISPCLK_CHG_FWD_CORR_DISABLE {
+	DISPCLK_CHG_FWD_CORR_ENABLE_AT_BEGINNING         = 0x0,
+	DISPCLK_CHG_FWD_CORR_DISABLE_AT_BEGINNING        = 0x1,
+} DISPCLK_CHG_FWD_CORR_DISABLE;
+typedef enum DC_MEM_GLOBAL_PWR_REQ_DIS {
+	DC_MEM_GLOBAL_PWR_REQ_ENABLE                     = 0x0,
+	DC_MEM_GLOBAL_PWR_REQ_DISABLE                    = 0x1,
+} DC_MEM_GLOBAL_PWR_REQ_DIS;
+typedef enum DCCG_PERF_RUN {
+	DCCG_PERF_RUN_NOOP                               = 0x0,
+	DCCG_PERF_RUN_START                              = 0x1,
+} DCCG_PERF_RUN;
+typedef enum DCCG_PERF_MODE_VSYNC {
+	DCCG_PERF_MODE_VSYNC_NOOP                        = 0x0,
+	DCCG_PERF_MODE_VSYNC_START                       = 0x1,
+} DCCG_PERF_MODE_VSYNC;
+typedef enum DCCG_PERF_MODE_HSYNC {
+	DCCG_PERF_MODE_HSYNC_NOOP                        = 0x0,
+	DCCG_PERF_MODE_HSYNC_START                       = 0x1,
+} DCCG_PERF_MODE_HSYNC;
+typedef enum DCCG_PERF_CRTC_SELECT {
+	DCCG_PERF_SEL_CRTC0                              = 0x0,
+	DCCG_PERF_SEL_CRTC1                              = 0x1,
+	DCCG_PERF_SEL_CRTC2                              = 0x2,
+	DCCG_PERF_SEL_CRTC3                              = 0x3,
+	DCCG_PERF_SEL_CRTC4                              = 0x4,
+	DCCG_PERF_SEL_CRTC5                              = 0x5,
+} DCCG_PERF_CRTC_SELECT;
+typedef enum CLOCK_BRANCH_SOFT_RESET {
+	CLOCK_BRANCH_SOFT_RESET_NOOP                     = 0x0,
+	CLOCK_BRANCH_SOFT_RESET_FORCE                    = 0x1,
+} CLOCK_BRANCH_SOFT_RESET;
+typedef enum PLL_CFG_IF_SOFT_RESET {
+	PLL_CFG_IF_SOFT_RESET_NOOP                       = 0x0,
+	PLL_CFG_IF_SOFT_RESET_FORCE                      = 0x1,
+} PLL_CFG_IF_SOFT_RESET;
+typedef enum DVO_ENABLE_RST {
+	DVO_ENABLE_RST_DISABLE                           = 0x0,
+	DVO_ENABLE_RST_ENABLE                            = 0x1,
+} DVO_ENABLE_RST;
+typedef enum LptNumBanks {
+	LPT_NUM_BANKS_2BANK                              = 0x0,
+	LPT_NUM_BANKS_4BANK                              = 0x1,
+	LPT_NUM_BANKS_8BANK                              = 0x2,
+	LPT_NUM_BANKS_16BANK                             = 0x3,
+	LPT_NUM_BANKS_32BANK                             = 0x4,
+} LptNumBanks;
+typedef enum DCIO_DC_GENERICA_SEL {
+	DCIO_GENERICA_SEL_DACA_STEREOSYNC                = 0x0,
+	DCIO_GENERICA_SEL_STEREOSYNC                     = 0x1,
+	DCIO_GENERICA_SEL_DACA_PIXCLK                    = 0x2,
+	DCIO_GENERICA_SEL_DACB_PIXCLK                    = 0x3,
+	DCIO_GENERICA_SEL_DVOA_CTL3                      = 0x4,
+	DCIO_GENERICA_SEL_P1_PLLCLK                      = 0x5,
+	DCIO_GENERICA_SEL_P2_PLLCLK                      = 0x6,
+	DCIO_GENERICA_SEL_DVOA_STEREOSYNC                = 0x7,
+	DCIO_GENERICA_SEL_DACA_FIELD_NUMBER              = 0x8,
+	DCIO_GENERICA_SEL_DACB_FIELD_NUMBER              = 0x9,
+	DCIO_GENERICA_SEL_GENERICA_DCCG                  = 0xa,
+	DCIO_GENERICA_SEL_SYNCEN                         = 0xb,
+	DCIO_GENERICA_SEL_GENERICA_SCG                   = 0xc,
+	DCIO_GENERICA_SEL_RESERVED_VALUE13               = 0xd,
+	DCIO_GENERICA_SEL_RESERVED_VALUE14               = 0xe,
+	DCIO_GENERICA_SEL_RESERVED_VALUE15               = 0xf,
+	DCIO_GENERICA_SEL_GENERICA_DPRX                  = 0x10,
+	DCIO_GENERICA_SEL_GENERICB_DPRX                  = 0x11,
+} DCIO_DC_GENERICA_SEL;
+typedef enum DCIO_DC_GENERIC_UNIPHY_REFDIV_CLK_SEL {
+	DCIO_UNIPHYA_TEST_REFDIV_CLK                     = 0x0,
+	DCIO_UNIPHYB_TEST_REFDIV_CLK                     = 0x1,
+	DCIO_UNIPHYC_TEST_REFDIV_CLK                     = 0x2,
+	DCIO_UNIPHYD_TEST_REFDIV_CLK                     = 0x3,
+	DCIO_UNIPHYE_TEST_REFDIV_CLK                     = 0x4,
+	DCIO_UNIPHYF_TEST_REFDIV_CLK                     = 0x5,
+	DCIO_UNIPHYG_TEST_REFDIV_CLK                     = 0x6,
+	DCIO_UNIPHYLPA_TEST_REFDIV_CLK                   = 0x7,
+	DCIO_UNIPHYLPB_TEST_REFDIV_CLK                   = 0x8,
+} DCIO_DC_GENERIC_UNIPHY_REFDIV_CLK_SEL;
+typedef enum DCIO_DC_GENERIC_UNIPHY_FBDIV_CLK_SEL {
+	DCIO_UNIPHYA_FBDIV_CLK                           = 0x0,
+	DCIO_UNIPHYB_FBDIV_CLK                           = 0x1,
+	DCIO_UNIPHYC_FBDIV_CLK                           = 0x2,
+	DCIO_UNIPHYD_FBDIV_CLK                           = 0x3,
+	DCIO_UNIPHYE_FBDIV_CLK                           = 0x4,
+	DCIO_UNIPHYF_FBDIV_CLK                           = 0x5,
+	DCIO_UNIPHYG_FBDIV_CLK                           = 0x6,
+	DCIO_UNIPHYLPA_FBDIV_CLK                         = 0x7,
+	DCIO_UNIPHYLPB_FBDIV_CLK                         = 0x8,
+} DCIO_DC_GENERIC_UNIPHY_FBDIV_CLK_SEL;
+typedef enum DCIO_DC_GENERIC_UNIPHY_FBDIV_SSC_CLK_SEL {
+	DCIO_UNIPHYA_FBDIV_SSC_CLK                       = 0x0,
+	DCIO_UNIPHYB_FBDIV_SSC_CLK                       = 0x1,
+	DCIO_UNIPHYC_FBDIV_SSC_CLK                       = 0x2,
+	DCIO_UNIPHYD_FBDIV_SSC_CLK                       = 0x3,
+	DCIO_UNIPHYE_FBDIV_SSC_CLK                       = 0x4,
+	DCIO_UNIPHYF_FBDIV_SSC_CLK                       = 0x5,
+	DCIO_UNIPHYG_FBDIV_SSC_CLK                       = 0x6,
+	DCIO_UNIPHYLPA_FBDIV_SSC_CLK                     = 0x7,
+	DCIO_UNIPHYLPB_FBDIV_SSC_CLK                     = 0x8,
+} DCIO_DC_GENERIC_UNIPHY_FBDIV_SSC_CLK_SEL;
+typedef enum DCIO_DC_GENERIC_UNIPHY_FBDIV_CLK_DIV2_SEL {
+	DCIO_UNIPHYA_TEST_FBDIV_CLK_DIV2                 = 0x0,
+	DCIO_UNIPHYB_TEST_FBDIV_CLK_DIV2                 = 0x1,
+	DCIO_UNIPHYC_TEST_FBDIV_CLK_DIV2                 = 0x2,
+	DCIO_UNIPHYD_TEST_FBDIV_CLK_DIV2                 = 0x3,
+	DCIO_UNIPHYE_TEST_FBDIV_CLK_DIV2                 = 0x4,
+	DCIO_UNIPHYF_TEST_FBDIV_CLK_DIV2                 = 0x5,
+	DCIO_UNIPHYG_TEST_FBDIV_CLK_DIV2                 = 0x6,
+	DCIO_UNIPHYLPA_TEST_FBDIV_CLK_DIV2               = 0x7,
+	DCIO_UNIPHYLPB_TEST_FBDIV_CLK_DIV2               = 0x8,
+} DCIO_DC_GENERIC_UNIPHY_FBDIV_CLK_DIV2_SEL;
+typedef enum DCIO_DC_GENERICB_SEL {
+	DCIO_GENERICB_SEL_DACA_STEREOSYNC                = 0x0,
+	DCIO_GENERICB_SEL_STEREOSYNC                     = 0x1,
+	DCIO_GENERICB_SEL_DACA_PIXCLK                    = 0x2,
+	DCIO_GENERICB_SEL_DACB_PIXCLK                    = 0x3,
+	DCIO_GENERICB_SEL_DVOA_CTL3                      = 0x4,
+	DCIO_GENERICB_SEL_P1_PLLCLK                      = 0x5,
+	DCIO_GENERICB_SEL_P2_PLLCLK                      = 0x6,
+	DCIO_GENERICB_SEL_DVOA_STEREOSYNC                = 0x7,
+	DCIO_GENERICB_SEL_DACA_FIELD_NUMBER              = 0x8,
+	DCIO_GENERICB_SEL_DACB_FIELD_NUMBER              = 0x9,
+	DCIO_GENERICB_SEL_GENERICB_DCCG                  = 0xa,
+	DCIO_GENERICB_SEL_SYNCEN                         = 0xb,
+	DCIO_GENERICB_SEL_GENERICA_SCG                   = 0xc,
+	DCIO_GENERICB_SEL_RESERVED_VALUE13               = 0xd,
+	DCIO_GENERICB_SEL_RESERVED_VALUE14               = 0xe,
+	DCIO_GENERICB_SEL_RESERVED_VALUE15               = 0xf,
+} DCIO_DC_GENERICB_SEL;
+typedef enum DCIO_DC_PAD_EXTERN_SIG_SEL {
+	DCIO_DC_PAD_EXTERN_SIG_SEL_MVP                   = 0x0,
+	DCIO_DC_PAD_EXTERN_SIG_SEL_VSYNCA                = 0x1,
+	DCIO_DC_PAD_EXTERN_SIG_SEL_GENLK_CLK             = 0x2,
+	DCIO_DC_PAD_EXTERN_SIG_SEL_GENLK_VSYNC           = 0x3,
+	DCIO_DC_PAD_EXTERN_SIG_SEL_GENERICA              = 0x4,
+	DCIO_DC_PAD_EXTERN_SIG_SEL_GENERICB              = 0x5,
+	DCIO_DC_PAD_EXTERN_SIG_SEL_GENERICC              = 0x6,
+	DCIO_DC_PAD_EXTERN_SIG_SEL_HPD1                  = 0x7,
+	DCIO_DC_PAD_EXTERN_SIG_SEL_HPD2                  = 0x8,
+	DCIO_DC_PAD_EXTERN_SIG_SEL_DDC1CLK               = 0x9,
+	DCIO_DC_PAD_EXTERN_SIG_SEL_DDC1DATA              = 0xa,
+	DCIO_DC_PAD_EXTERN_SIG_SEL_DDC2CLK               = 0xb,
+	DCIO_DC_PAD_EXTERN_SIG_SEL_DDC2DATA              = 0xc,
+	DCIO_DC_PAD_EXTERN_SIG_SEL_VHAD1                 = 0xd,
+	DCIO_DC_PAD_EXTERN_SIG_SEL_VHAD0                 = 0xe,
+	DCIO_DC_PAD_EXTERN_SIG_SEL_VPHCTL                = 0xf,
+} DCIO_DC_PAD_EXTERN_SIG_SEL;
+typedef enum DCIO_DC_PAD_EXTERN_SIG_MVP_PIXEL_SRC_STATUS {
+	DCIO_MVP_PIXEL_SRC_STATUS_HSYNCA                 = 0x0,
+	DCIO_MVP_PIXEL_SRC_STATUS_HSYNCA_DUPLICATE       = 0x1,
+	DCIO_MVP_PIXEL_SRC_STATUS_CRTC                   = 0x2,
+	DCIO_MVP_PIXEL_SRC_STATUS_LB                     = 0x3,
+} DCIO_DC_PAD_EXTERN_SIG_MVP_PIXEL_SRC_STATUS;
+typedef enum DCIO_DC_REF_CLK_CNTL_HSYNCA_OUTPUT_SEL {
+	DCIO_HSYNCA_OUTPUT_SEL_DISABLE                   = 0x0,
+	DCIO_HSYNCA_OUTPUT_SEL_PPLL1                     = 0x1,
+	DCIO_HSYNCA_OUTPUT_SEL_PPLL2                     = 0x2,
+	DCIO_HSYNCA_OUTPUT_SEL_RESERVED                  = 0x3,
+} DCIO_DC_REF_CLK_CNTL_HSYNCA_OUTPUT_SEL;
+typedef enum DCIO_DC_REF_CLK_CNTL_GENLK_CLK_OUTPUT_SEL {
+	DCIO_GENLK_CLK_OUTPUT_SEL_DISABLE                = 0x0,
+	DCIO_GENLK_CLK_OUTPUT_SEL_PPLL1                  = 0x1,
+	DCIO_GENLK_CLK_OUTPUT_SEL_PPLL2                  = 0x2,
+	DCIO_GENLK_CLK_OUTPUT_SEL_RESERVED_VALUE3        = 0x3,
+} DCIO_DC_REF_CLK_CNTL_GENLK_CLK_OUTPUT_SEL;
+typedef enum DCIO_DC_GPIO_VIP_DEBUG {
+	DCIO_DC_GPIO_VIP_DEBUG_NORMAL                    = 0x0,
+	DCIO_DC_GPIO_VIP_DEBUG_CG_BIG                    = 0x1,
+} DCIO_DC_GPIO_VIP_DEBUG;
+typedef enum DCIO_DC_GPIO_MACRO_DEBUG {
+	DCIO_DC_GPIO_MACRO_DEBUG_NORMAL                  = 0x0,
+	DCIO_DC_GPIO_MACRO_DEBUG_CHIP_BIF                = 0x1,
+	DCIO_DC_GPIO_MACRO_DEBUG_RESERVED_VALUE2         = 0x2,
+	DCIO_DC_GPIO_MACRO_DEBUG_RESERVED_VALUE3         = 0x3,
+} DCIO_DC_GPIO_MACRO_DEBUG;
+typedef enum DCIO_DC_GPIO_CHIP_DEBUG_OUT_PIN_SEL {
+	DCIO_DC_GPIO_CHIP_DEBUG_OUT_PIN_SEL_NORMAL       = 0x0,
+	DCIO_DC_GPIO_CHIP_DEBUG_OUT_PIN_SEL_SWAP         = 0x1,
+} DCIO_DC_GPIO_CHIP_DEBUG_OUT_PIN_SEL;
+typedef enum DCIO_DC_GPIO_DEBUG_BUS_FLOP_EN {
+	DCIO_DC_GPIO_DEBUG_BUS_FLOP_EN_BYPASS            = 0x0,
+	DCIO_DC_GPIO_DEBUG_BUS_FLOP_EN_ENABLE            = 0x1,
+} DCIO_DC_GPIO_DEBUG_BUS_FLOP_EN;
+typedef enum DCIO_DC_GPIO_DEBUG_DPRX_LOOPBACK_ENABLE {
+	DCIO_DPRX_LOOPBACK_ENABLE_NORMAL                 = 0x0,
+	DCIO_DPRX_LOOPBACK_ENABLE_LOOP                   = 0x1,
+} DCIO_DC_GPIO_DEBUG_DPRX_LOOPBACK_ENABLE;
+typedef enum DCIO_UNIPHY_LINK_CNTL_MINIMUM_PIXVLD_LOW_DURATION {
+	DCIO_UNIPHY_MINIMUM_PIXVLD_LOW_DURATION_3_CLOCKS = 0x0,
+	DCIO_UNIPHY_MINIMUM_PIXVLD_LOW_DURATION_7_CLOCKS = 0x1,
+	DCIO_UNIPHY_MINIMUM_PIXVLD_LOW_DURATION_11_CLOCKS= 0x2,
+	DCIO_UNIPHY_MINIMUM_PIXVLD_LOW_DURATION_15_CLOCKS= 0x3,
+	DCIO_UNIPHY_MINIMUM_PIXVLD_LOW_DURATION_19_CLOCKS= 0x4,
+	DCIO_UNIPHY_MINIMUM_PIXVLD_LOW_DURATION_23_CLOCKS= 0x5,
+	DCIO_UNIPHY_MINIMUM_PIXVLD_LOW_DURATION_27_CLOCKS= 0x6,
+	DCIO_UNIPHY_MINIMUM_PIXVLD_LOW_DURATION_31_CLOCKS= 0x7,
+} DCIO_UNIPHY_LINK_CNTL_MINIMUM_PIXVLD_LOW_DURATION;
+typedef enum DCIO_UNIPHY_LINK_CNTL_CHANNEL_INVERT {
+	DCIO_UNIPHY_CHANNEL_NO_INVERSION                 = 0x0,
+	DCIO_UNIPHY_CHANNEL_INVERTED                     = 0x1,
+} DCIO_UNIPHY_LINK_CNTL_CHANNEL_INVERT;
+typedef enum DCIO_UNIPHY_LINK_CNTL_ENABLE_HPD_MASK {
+	DCIO_UNIPHY_LINK_ENABLE_HPD_MASK_DISALLOW        = 0x0,
+	DCIO_UNIPHY_LINK_ENABLE_HPD_MASK_ALLOW           = 0x1,
+	DCIO_UNIPHY_LINK_ENABLE_HPD_MASK_ALLOW_DEBOUNCED = 0x2,
+	DCIO_UNIPHY_LINK_ENABLE_HPD_MASK_ALLOW_TOGGLE_FILTERED= 0x3,
+} DCIO_UNIPHY_LINK_CNTL_ENABLE_HPD_MASK;
+typedef enum DCIO_UNIPHY_CHANNEL_XBAR_SOURCE {
+	DCIO_UNIPHY_CHANNEL_XBAR_SOURCE_CH0              = 0x0,
+	DCIO_UNIPHY_CHANNEL_XBAR_SOURCE_CH1              = 0x1,
+	DCIO_UNIPHY_CHANNEL_XBAR_SOURCE_CH2              = 0x2,
+	DCIO_UNIPHY_CHANNEL_XBAR_SOURCE_CH3              = 0x3,
+} DCIO_UNIPHY_CHANNEL_XBAR_SOURCE;
+typedef enum DCIO_DC_DVODATA_CONFIG_VIP_MUX_EN {
+	DCIO_VIP_MUX_EN_DVO                              = 0x0,
+	DCIO_VIP_MUX_EN_VIP                              = 0x1,
+} DCIO_DC_DVODATA_CONFIG_VIP_MUX_EN;
+typedef enum DCIO_DC_DVODATA_CONFIG_VIP_ALTER_MAPPING_EN {
+	DCIO_VIP_ALTER_MAPPING_EN_DEFAULT                = 0x0,
+	DCIO_VIP_ALTER_MAPPING_EN_ALTERNATIVE            = 0x1,
+} DCIO_DC_DVODATA_CONFIG_VIP_ALTER_MAPPING_EN;
+typedef enum DCIO_DC_DVODATA_CONFIG_DVO_ALTER_MAPPING_EN {
+	DCIO_DVO_ALTER_MAPPING_EN_DEFAULT                = 0x0,
+	DCIO_DVO_ALTER_MAPPING_EN_ALTERNATIVE            = 0x1,
+} DCIO_DC_DVODATA_CONFIG_DVO_ALTER_MAPPING_EN;
+typedef enum DCIO_LVTMA_PWRSEQ_CNTL_DISABLE_SYNCEN_CONTROL_OF_TX_EN {
+	DCIO_LVTMA_PWRSEQ_DISABLE_SYNCEN_CONTROL_OF_TX_ENABLE= 0x0,
+	DCIO_LVTMA_PWRSEQ_DISABLE_SYNCEN_CONTROL_OF_TX_DISABLE= 0x1,
+} DCIO_LVTMA_PWRSEQ_CNTL_DISABLE_SYNCEN_CONTROL_OF_TX_EN;
+typedef enum DCIO_LVTMA_PWRSEQ_CNTL_TARGET_STATE {
+	DCIO_LVTMA_PWRSEQ_TARGET_STATE_LCD_OFF           = 0x0,
+	DCIO_LVTMA_PWRSEQ_TARGET_STATE_LCD_ON            = 0x1,
+} DCIO_LVTMA_PWRSEQ_CNTL_TARGET_STATE;
+typedef enum DCIO_LVTMA_PWRSEQ_CNTL_LVTMA_SYNCEN_POL {
+	DCIO_LVTMA_SYNCEN_POL_NON_INVERT                 = 0x0,
+	DCIO_LVTMA_SYNCEN_POL_INVERT                     = 0x1,
+} DCIO_LVTMA_PWRSEQ_CNTL_LVTMA_SYNCEN_POL;
+typedef enum DCIO_LVTMA_PWRSEQ_CNTL_LVTMA_DIGON {
+	DCIO_LVTMA_DIGON_OFF                             = 0x0,
+	DCIO_LVTMA_DIGON_ON                              = 0x1,
+} DCIO_LVTMA_PWRSEQ_CNTL_LVTMA_DIGON;
+typedef enum DCIO_LVTMA_PWRSEQ_CNTL_LVTMA_DIGON_POL {
+	DCIO_LVTMA_DIGON_POL_NON_INVERT                  = 0x0,
+	DCIO_LVTMA_DIGON_POL_INVERT                      = 0x1,
+} DCIO_LVTMA_PWRSEQ_CNTL_LVTMA_DIGON_POL;
+typedef enum DCIO_LVTMA_PWRSEQ_CNTL_LVTMA_BLON {
+	DCIO_LVTMA_BLON_OFF                              = 0x0,
+	DCIO_LVTMA_BLON_ON                               = 0x1,
+} DCIO_LVTMA_PWRSEQ_CNTL_LVTMA_BLON;
+typedef enum DCIO_LVTMA_PWRSEQ_CNTL_LVTMA_BLON_POL {
+	DCIO_LVTMA_BLON_POL_NON_INVERT                   = 0x0,
+	DCIO_LVTMA_BLON_POL_INVERT                       = 0x1,
+} DCIO_LVTMA_PWRSEQ_CNTL_LVTMA_BLON_POL;
+typedef enum DCIO_LVTMA_PWRSEQ_DELAY2_LVTMA_VARY_BL_OVERRIDE_EN {
+	DCIO_LVTMA_VARY_BL_OVERRIDE_EN_BLON              = 0x0,
+	DCIO_LVTMA_VARY_BL_OVERRIDE_EN_SEPARATE          = 0x1,
+} DCIO_LVTMA_PWRSEQ_DELAY2_LVTMA_VARY_BL_OVERRIDE_EN;
+typedef enum DCIO_BL_PWM_CNTL_BL_PWM_FRACTIONAL_EN {
+	DCIO_BL_PWM_FRACTIONAL_DISABLE                   = 0x0,
+	DCIO_BL_PWM_FRACTIONAL_ENABLE                    = 0x1,
+} DCIO_BL_PWM_CNTL_BL_PWM_FRACTIONAL_EN;
+typedef enum DCIO_BL_PWM_CNTL_BL_PWM_EN {
+	DCIO_BL_PWM_DISABLE                              = 0x0,
+	DCIO_BL_PWM_ENABLE                               = 0x1,
+} DCIO_BL_PWM_CNTL_BL_PWM_EN;
+typedef enum DCIO_BL_PWM_CNTL2_DBG_BL_PWM_INPUT_REFCLK_SELECT {
+	DCIO_DBG_BL_PWM_INPUT_REFCLK_SELECT_NORMAL       = 0x0,
+	DCIO_DBG_BL_PWM_INPUT_REFCLK_SELECT_DEBUG1       = 0x1,
+	DCIO_DBG_BL_PWM_INPUT_REFCLK_SELECT_DEBUG2       = 0x2,
+	DCIO_DBG_BL_PWM_INPUT_REFCLK_SELECT_DEBUG3       = 0x3,
+} DCIO_BL_PWM_CNTL2_DBG_BL_PWM_INPUT_REFCLK_SELECT;
+typedef enum DCIO_BL_PWM_CNTL2_BL_PWM_OVERRIDE_BL_OUT_ENABLE {
+	DCIO_BL_PWM_OVERRIDE_BL_OUT_DISABLE              = 0x0,
+	DCIO_BL_PWM_OVERRIDE_BL_OUT_ENABLE               = 0x1,
+} DCIO_BL_PWM_CNTL2_BL_PWM_OVERRIDE_BL_OUT_ENABLE;
+typedef enum DCIO_BL_PWM_CNTL2_BL_PWM_OVERRIDE_LVTMA_PWRSEQ_EN {
+	DCIO_BL_PWM_OVERRIDE_LVTMA_PWRSEQ_EN_NORMAL      = 0x0,
+	DCIO_BL_PWM_OVERRIDE_LVTMA_PWRSEQ_EN_PWM         = 0x1,
+} DCIO_BL_PWM_CNTL2_BL_PWM_OVERRIDE_LVTMA_PWRSEQ_EN;
+typedef enum DCIO_BL_PWM_GRP1_REG_LOCK {
+	DCIO_BL_PWM_GRP1_REG_LOCK_DISABLE                = 0x0,
+	DCIO_BL_PWM_GRP1_REG_LOCK_ENABLE                 = 0x1,
+} DCIO_BL_PWM_GRP1_REG_LOCK;
+typedef enum DCIO_BL_PWM_GRP1_UPDATE_AT_FRAME_START {
+	DCIO_BL_PWM_GRP1_UPDATE_AT_FRAME_START_DISABLE   = 0x0,
+	DCIO_BL_PWM_GRP1_UPDATE_AT_FRAME_START_ENABLE    = 0x1,
+} DCIO_BL_PWM_GRP1_UPDATE_AT_FRAME_START;
+typedef enum DCIO_BL_PWM_GRP1_FRAME_START_DISP_SEL {
+	DCIO_BL_PWM_GRP1_FRAME_START_DISP_SEL_CONTROLLER1= 0x0,
+	DCIO_BL_PWM_GRP1_FRAME_START_DISP_SEL_CONTROLLER2= 0x1,
+	DCIO_BL_PWM_GRP1_FRAME_START_DISP_SEL_CONTROLLER3= 0x2,
+	DCIO_BL_PWM_GRP1_FRAME_START_DISP_SEL_CONTROLLER4= 0x3,
+	DCIO_BL_PWM_GRP1_FRAME_START_DISP_SEL_CONTROLLER5= 0x4,
+	DCIO_BL_PWM_GRP1_FRAME_START_DISP_SEL_CONTROLLER6= 0x5,
+} DCIO_BL_PWM_GRP1_FRAME_START_DISP_SEL;
+typedef enum DCIO_BL_PWM_GRP1_READBACK_DB_REG_VALUE_EN {
+	DCIO_BL_PWM_GRP1_READBACK_DB_REG_VALUE_EN_BL_PWM = 0x0,
+	DCIO_BL_PWM_GRP1_READBACK_DB_REG_VALUE_EN_BL1_PWM= 0x1,
+} DCIO_BL_PWM_GRP1_READBACK_DB_REG_VALUE_EN;
+typedef enum DCIO_BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN {
+	DCIO_BL_PWM_GRP1_IGNORE_MASTER_LOCK_ENABLE       = 0x0,
+	DCIO_BL_PWM_GRP1_IGNORE_MASTER_LOCK_DISABLE      = 0x1,
+} DCIO_BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN;
+typedef enum DCIO_GSL_SEL {
+	DCIO_GSL_SEL_GROUP_0                             = 0x0,
+	DCIO_GSL_SEL_GROUP_1                             = 0x1,
+	DCIO_GSL_SEL_GROUP_2                             = 0x2,
+} DCIO_GSL_SEL;
+typedef enum DCIO_GENLK_CLK_GSL_MASK {
+	DCIO_GENLK_CLK_GSL_MASK_NO                       = 0x0,
+	DCIO_GENLK_CLK_GSL_MASK_TIMING                   = 0x1,
+	DCIO_GENLK_CLK_GSL_MASK_STEREO                   = 0x2,
+} DCIO_GENLK_CLK_GSL_MASK;
+typedef enum DCIO_GENLK_VSYNC_GSL_MASK {
+	DCIO_GENLK_VSYNC_GSL_MASK_NO                     = 0x0,
+	DCIO_GENLK_VSYNC_GSL_MASK_TIMING                 = 0x1,
+	DCIO_GENLK_VSYNC_GSL_MASK_STEREO                 = 0x2,
+} DCIO_GENLK_VSYNC_GSL_MASK;
+typedef enum DCIO_SWAPLOCK_A_GSL_MASK {
+	DCIO_SWAPLOCK_A_GSL_MASK_NO                      = 0x0,
+	DCIO_SWAPLOCK_A_GSL_MASK_TIMING                  = 0x1,
+	DCIO_SWAPLOCK_A_GSL_MASK_STEREO                  = 0x2,
+} DCIO_SWAPLOCK_A_GSL_MASK;
+typedef enum DCIO_SWAPLOCK_B_GSL_MASK {
+	DCIO_SWAPLOCK_B_GSL_MASK_NO                      = 0x0,
+	DCIO_SWAPLOCK_B_GSL_MASK_TIMING                  = 0x1,
+	DCIO_SWAPLOCK_B_GSL_MASK_STEREO                  = 0x2,
+} DCIO_SWAPLOCK_B_GSL_MASK;
+typedef enum DCIO_GSL_VSYNC_SEL {
+	DCIO_GSL_VSYNC_SEL_PIPE0                         = 0x0,
+	DCIO_GSL_VSYNC_SEL_PIPE1                         = 0x1,
+	DCIO_GSL_VSYNC_SEL_PIPE2                         = 0x2,
+	DCIO_GSL_VSYNC_SEL_PIPE3                         = 0x3,
+	DCIO_GSL_VSYNC_SEL_PIPE4                         = 0x4,
+	DCIO_GSL_VSYNC_SEL_PIPE5                         = 0x5,
+} DCIO_GSL_VSYNC_SEL;
+typedef enum DCIO_GSL0_TIMING_SYNC_SEL {
+	DCIO_GSL0_TIMING_SYNC_SEL_PIPE                   = 0x0,
+	DCIO_GSL0_TIMING_SYNC_SEL_GENCLK_VSYNC           = 0x1,
+	DCIO_GSL0_TIMING_SYNC_SEL_GENCLK_CLK             = 0x2,
+	DCIO_GSL0_TIMING_SYNC_SEL_SWAPLOCK_A             = 0x3,
+	DCIO_GSL0_TIMING_SYNC_SEL_SWAPLOCK_B             = 0x4,
+} DCIO_GSL0_TIMING_SYNC_SEL;
+typedef enum DCIO_GSL0_GLOBAL_UNLOCK_SEL {
+	DCIO_GSL0_GLOBAL_UNLOCK_SEL_INVERSION            = 0x0,
+	DCIO_GSL0_GLOBAL_UNLOCK_SEL_GENCLK_VSYNC         = 0x1,
+	DCIO_GSL0_GLOBAL_UNLOCK_SEL_GENLK_CLK            = 0x2,
+	DCIO_GSL0_GLOBAL_UNLOCK_SEL_SWAPLOCK_A           = 0x3,
+	DCIO_GSL0_GLOBAL_UNLOCK_SEL_SWAPLOCK_B           = 0x4,
+} DCIO_GSL0_GLOBAL_UNLOCK_SEL;
+typedef enum DCIO_GSL1_TIMING_SYNC_SEL {
+	DCIO_GSL1_TIMING_SYNC_SEL_PIPE                   = 0x0,
+	DCIO_GSL1_TIMING_SYNC_SEL_GENCLK_VSYNC           = 0x1,
+	DCIO_GSL1_TIMING_SYNC_SEL_GENCLK_CLK             = 0x2,
+	DCIO_GSL1_TIMING_SYNC_SEL_SWAPLOCK_A             = 0x3,
+	DCIO_GSL1_TIMING_SYNC_SEL_SWAPLOCK_B             = 0x4,
+} DCIO_GSL1_TIMING_SYNC_SEL;
+typedef enum DCIO_GSL1_GLOBAL_UNLOCK_SEL {
+	DCIO_GSL1_GLOBAL_UNLOCK_SEL_INVERSION            = 0x0,
+	DCIO_GSL1_GLOBAL_UNLOCK_SEL_GENCLK_VSYNC         = 0x1,
+	DCIO_GSL1_GLOBAL_UNLOCK_SEL_GENLK_CLK            = 0x2,
+	DCIO_GSL1_GLOBAL_UNLOCK_SEL_SWAPLOCK_A           = 0x3,
+	DCIO_GSL1_GLOBAL_UNLOCK_SEL_SWAPLOCK_B           = 0x4,
+} DCIO_GSL1_GLOBAL_UNLOCK_SEL;
+typedef enum DCIO_GSL2_TIMING_SYNC_SEL {
+	DCIO_GSL2_TIMING_SYNC_SEL_PIPE                   = 0x0,
+	DCIO_GSL2_TIMING_SYNC_SEL_GENCLK_VSYNC           = 0x1,
+	DCIO_GSL2_TIMING_SYNC_SEL_GENCLK_CLK             = 0x2,
+	DCIO_GSL2_TIMING_SYNC_SEL_SWAPLOCK_A             = 0x3,
+	DCIO_GSL2_TIMING_SYNC_SEL_SWAPLOCK_B             = 0x4,
+} DCIO_GSL2_TIMING_SYNC_SEL;
+typedef enum DCIO_GSL2_GLOBAL_UNLOCK_SEL {
+	DCIO_GSL2_GLOBAL_UNLOCK_SEL_INVERSION            = 0x0,
+	DCIO_GSL2_GLOBAL_UNLOCK_SEL_GENCLK_VSYNC         = 0x1,
+	DCIO_GSL2_GLOBAL_UNLOCK_SEL_GENLK_CLK            = 0x2,
+	DCIO_GSL2_GLOBAL_UNLOCK_SEL_SWAPLOCK_A           = 0x3,
+	DCIO_GSL2_GLOBAL_UNLOCK_SEL_SWAPLOCK_B           = 0x4,
+} DCIO_GSL2_GLOBAL_UNLOCK_SEL;
+typedef enum DCIO_DC_GPU_TIMER_START_POSITION {
+	DCIO_GPU_TIMER_START_0_END_27                    = 0x0,
+	DCIO_GPU_TIMER_START_1_END_28                    = 0x1,
+	DCIO_GPU_TIMER_START_2_END_29                    = 0x2,
+	DCIO_GPU_TIMER_START_3_END_30                    = 0x3,
+	DCIO_GPU_TIMER_START_4_END_31                    = 0x4,
+	DCIO_GPU_TIMER_START_6_END_33                    = 0x5,
+	DCIO_GPU_TIMER_START_8_END_35                    = 0x6,
+	DCIO_GPU_TIMER_START_10_END_37                   = 0x7,
+} DCIO_DC_GPU_TIMER_START_POSITION;
+typedef enum DCIO_CLOCK_CNTL_DCIO_TEST_CLK_SEL {
+	DCIO_TEST_CLK_SEL_DISPCLK                        = 0x0,
+	DCIO_TEST_CLK_SEL_GATED_DISPCLK                  = 0x1,
+	DCIO_TEST_CLK_SEL_SCLK                           = 0x2,
+} DCIO_CLOCK_CNTL_DCIO_TEST_CLK_SEL;
+typedef enum DCIO_CLOCK_CNTL_DISPCLK_R_DCIO_GATE_DIS {
+	DCIO_DISPCLK_R_DCIO_GATE_DISABLE                 = 0x0,
+	DCIO_DISPCLK_R_DCIO_GATE_ENABLE                  = 0x1,
+} DCIO_CLOCK_CNTL_DISPCLK_R_DCIO_GATE_DIS;
+typedef enum DCIO_DCO_DCFE_EXT_VSYNC_MUX {
+	DCIO_EXT_VSYNC_MUX_SWAPLOCKB                     = 0x0,
+	DCIO_EXT_VSYNC_MUX_CRTC0                         = 0x1,
+	DCIO_EXT_VSYNC_MUX_CRTC1                         = 0x2,
+	DCIO_EXT_VSYNC_MUX_CRTC2                         = 0x3,
+	DCIO_EXT_VSYNC_MUX_CRTC3                         = 0x4,
+	DCIO_EXT_VSYNC_MUX_CRTC4                         = 0x5,
+	DCIO_EXT_VSYNC_MUX_CRTC5                         = 0x6,
+	DCIO_EXT_VSYNC_MUX_GENERICB                      = 0x7,
+} DCIO_DCO_DCFE_EXT_VSYNC_MUX;
+typedef enum DCIO_DCO_EXT_VSYNC_MASK {
+	DCIO_EXT_VSYNC_MASK_NONE                         = 0x0,
+	DCIO_EXT_VSYNC_MASK_PIPE0                        = 0x1,
+	DCIO_EXT_VSYNC_MASK_PIPE1                        = 0x2,
+	DCIO_EXT_VSYNC_MASK_PIPE2                        = 0x3,
+	DCIO_EXT_VSYNC_MASK_PIPE3                        = 0x4,
+	DCIO_EXT_VSYNC_MASK_PIPE4                        = 0x5,
+	DCIO_EXT_VSYNC_MASK_PIPE5                        = 0x6,
+	DCIO_EXT_VSYNC_MASK_NONE_DUPLICATE               = 0x7,
+} DCIO_DCO_EXT_VSYNC_MASK;
+typedef enum DCIO_DBG_OUT_PIN_SEL {
+	DCIO_DBG_OUT_PIN_SEL_LOW_12BIT                   = 0x0,
+	DCIO_DBG_OUT_PIN_SEL_HIGH_12BIT                  = 0x1,
+} DCIO_DBG_OUT_PIN_SEL;
+typedef enum DCIO_DBG_OUT_12BIT_SEL {
+	DCIO_DBG_OUT_12BIT_SEL_LOW_12BIT                 = 0x0,
+	DCIO_DBG_OUT_12BIT_SEL_MID_12BIT                 = 0x1,
+	DCIO_DBG_OUT_12BIT_SEL_HIGH_12BIT                = 0x2,
+	DCIO_DBG_OUT_12BIT_SEL_OVERRIDE                  = 0x3,
+} DCIO_DBG_OUT_12BIT_SEL;
+typedef enum DCIO_DSYNC_SOFT_RESET {
+	DCIO_DSYNC_SOFT_RESET_DEASSERT                   = 0x0,
+	DCIO_DSYNC_SOFT_RESET_ASSERT                     = 0x1,
+} DCIO_DSYNC_SOFT_RESET;
+typedef enum DCIO_DACA_SOFT_RESET {
+	DCIO_DACA_SOFT_RESET_DEASSERT                    = 0x0,
+	DCIO_DACA_SOFT_RESET_ASSERT                      = 0x1,
+} DCIO_DACA_SOFT_RESET;
+typedef enum DCIO_DCRXPHY_SOFT_RESET {
+	DCIO_DCRXPHY_SOFT_RESET_DEASSERT                 = 0x0,
+	DCIO_DCRXPHY_SOFT_RESET_ASSERT                   = 0x1,
+} DCIO_DCRXPHY_SOFT_RESET;
+typedef enum DCIO_DPHY_LANE_SEL {
+	DCIO_DPHY_LANE_SEL_LANE0                         = 0x0,
+	DCIO_DPHY_LANE_SEL_LANE1                         = 0x1,
+	DCIO_DPHY_LANE_SEL_LANE2                         = 0x2,
+	DCIO_DPHY_LANE_SEL_LANE3                         = 0x3,
+} DCIO_DPHY_LANE_SEL;
+typedef enum DCIO_DPCS_INTERRUPT_TYPE {
+	DCIO_DPCS_INTERRUPT_TYPE_LEVEL_BASED             = 0x0,
+	DCIO_DPCS_INTERRUPT_TYPE_PULSE_BASED             = 0x1,
+} DCIO_DPCS_INTERRUPT_TYPE;
+typedef enum DCIO_DPCS_INTERRUPT_MASK {
+	DCIO_DPCS_INTERRUPT_DISABLE                      = 0x0,
+	DCIO_DPCS_INTERRUPT_ENABLE                       = 0x1,
+} DCIO_DPCS_INTERRUPT_MASK;
+typedef enum DCIO_DC_GPU_TIMER_READ_SELECT {
+	DCIO_GPU_TIMER_READ_SELECT_LOWER_D1_V_UPDATE     = 0x0,
+	DCIO_GPU_TIMER_READ_SELECT_UPPER_D1_V_UPDATE     = 0x1,
+	DCIO_GPU_TIMER_READ_SELECT_LOWER_D2_V_UPDATE     = 0x2,
+	DCIO_GPU_TIMER_READ_SELECT_UPPER_D2_V_UPDATE     = 0x3,
+	DCIO_GPU_TIMER_READ_SELECT_LOWER_D3_V_UPDATE     = 0x4,
+	DCIO_GPU_TIMER_READ_SELECT_UPPER_D3_V_UPDATE     = 0x5,
+	DCIO_GPU_TIMER_READ_SELECT_LOWER_D4_V_UPDATE     = 0x6,
+	DCIO_GPU_TIMER_READ_SELECT_UPPER_D4_V_UPDATE     = 0x7,
+	DCIO_GPU_TIMER_READ_SELECT_LOWER_D5_V_UPDATE     = 0x8,
+	DCIO_GPU_TIMER_READ_SELECT_UPPER_D5_V_UPDATE     = 0x9,
+	DCIO_GPU_TIMER_READ_SELECT_LOWER_D6_V_UPDATE     = 0xa,
+	DCIO_GPU_TIMER_READ_SELECT_UPPER_D6_V_UPDATE     = 0xb,
+	DCIO_GPU_TIMER_READ_SELECT_LOWER_D1_P_FLIP       = 0xc,
+	DCIO_GPU_TIMER_READ_SELECT_UPPER_D1_P_FLIP       = 0xd,
+	DCIO_GPU_TIMER_READ_SELECT_LOWER_D2_P_FLIP       = 0xe,
+	DCIO_GPU_TIMER_READ_SELECT_UPPER_D2_P_FLIP       = 0xf,
+	DCIO_GPU_TIMER_READ_SELECT_LOWER_D3_P_FLIP       = 0x10,
+	DCIO_GPU_TIMER_READ_SELECT_UPPER_D3_P_FLIP       = 0x11,
+	DCIO_GPU_TIMER_READ_SELECT_LOWER_D4_P_FLIP       = 0x12,
+	DCIO_GPU_TIMER_READ_SELECT_UPPER_D4_P_FLIP       = 0x13,
+	DCIO_GPU_TIMER_READ_SELECT_LOWER_D5_P_FLIP       = 0x14,
+	DCIO_GPU_TIMER_READ_SELECT_UPPER_D5_P_FLIP       = 0x15,
+	DCIO_GPU_TIMER_READ_SELECT_LOWER_D6_P_FLIP       = 0x16,
+	DCIO_GPU_TIMER_READ_SELECT_UPPER_D6_P_FLIP       = 0x17,
+	DCIO_GPU_TIMER_READ_SELECT_LOWER_D1_VSYNC_NOM    = 0x18,
+	DCIO_GPU_TIMER_READ_SELECT_UPPER_D1_VSYNC_NOM    = 0x19,
+	DCIO_GPU_TIMER_READ_SELECT_LOWER_D2_VSYNC_NOM    = 0x1a,
+	DCIO_GPU_TIMER_READ_SELECT_UPPER_D2_VSYNC_NOM    = 0x1b,
+	DCIO_GPU_TIMER_READ_SELECT_LOWER_D3_VSYNC_NOM    = 0x1c,
+	DCIO_GPU_TIMER_READ_SELECT_UPPER_D3_VSYNC_NOM    = 0x1d,
+	DCIO_GPU_TIMER_READ_SELECT_LOWER_D4_VSYNC_NOM    = 0x1e,
+	DCIO_GPU_TIMER_READ_SELECT_UPPER_D4_VSYNC_NOM    = 0x1f,
+	DCIO_GPU_TIMER_READ_SELECT_LOWER_D5_VSYNC_NOM    = 0x20,
+	DCIO_GPU_TIMER_READ_SELECT_UPPER_D5_VSYNC_NOM    = 0x21,
+	DCIO_GPU_TIMER_READ_SELECT_LOWER_D6_VSYNC_NOM    = 0x22,
+	DCIO_GPU_TIMER_READ_SELECT_UPPER_D6_VSYNC_NOM    = 0x23,
+} DCIO_DC_GPU_TIMER_READ_SELECT;
+typedef enum DCIO_IMPCAL_STEP_DELAY {
+	DCIO_IMPCAL_STEP_DELAY_1us                       = 0x0,
+	DCIO_IMPCAL_STEP_DELAY_2us                       = 0x1,
+	DCIO_IMPCAL_STEP_DELAY_3us                       = 0x2,
+	DCIO_IMPCAL_STEP_DELAY_4us                       = 0x3,
+	DCIO_IMPCAL_STEP_DELAY_5us                       = 0x4,
+	DCIO_IMPCAL_STEP_DELAY_6us                       = 0x5,
+	DCIO_IMPCAL_STEP_DELAY_7us                       = 0x6,
+	DCIO_IMPCAL_STEP_DELAY_8us                       = 0x7,
+	DCIO_IMPCAL_STEP_DELAY_9us                       = 0x8,
+	DCIO_IMPCAL_STEP_DELAY_10us                      = 0x9,
+	DCIO_IMPCAL_STEP_DELAY_11us                      = 0xa,
+	DCIO_IMPCAL_STEP_DELAY_12us                      = 0xb,
+	DCIO_IMPCAL_STEP_DELAY_13us                      = 0xc,
+	DCIO_IMPCAL_STEP_DELAY_14us                      = 0xd,
+	DCIO_IMPCAL_STEP_DELAY_15us                      = 0xe,
+	DCIO_IMPCAL_STEP_DELAY_16us                      = 0xf,
+} DCIO_IMPCAL_STEP_DELAY;
+typedef enum DCIO_UNIPHY_IMPCAL_SEL {
+	DCIO_UNIPHY_IMPCAL_SEL_TEMPERATURE               = 0x0,
+	DCIO_UNIPHY_IMPCAL_SEL_BINARY                    = 0x1,
+} DCIO_UNIPHY_IMPCAL_SEL;
+typedef enum DCIO_DBG_CLOCK_SEL {
+	DCIO_DBG_CLOCK_SEL_DISPCLK                       = 0x0,
+	DCIO_DBG_CLOCK_SEL_SYMCLKA                       = 0x1,
+	DCIO_DBG_CLOCK_SEL_SYMCLKB                       = 0x2,
+	DCIO_DBG_CLOCK_SEL_SYMCLKC                       = 0x3,
+	DCIO_DBG_CLOCK_SEL_SYMCLKD                       = 0x4,
+	DCIO_DBG_CLOCK_SEL_SYMCLKE                       = 0x5,
+	DCIO_DBG_CLOCK_SEL_SYMCLKF                       = 0x6,
+	DCIO_DBG_CLOCK_SEL_REFCLK                        = 0xb,
+} DCIO_DBG_CLOCK_SEL;
+typedef enum DCIOCHIP_HPD_SEL {
+	DCIOCHIP_HPD_SEL_ASYNC                           = 0x0,
+	DCIOCHIP_HPD_SEL_CLOCKED                         = 0x1,
+} DCIOCHIP_HPD_SEL;
+typedef enum DCIOCHIP_PAD_MODE {
+	DCIOCHIP_PAD_MODE_DDC                            = 0x0,
+	DCIOCHIP_PAD_MODE_DP                             = 0x1,
+} DCIOCHIP_PAD_MODE;
+typedef enum DCIOCHIP_AUXSLAVE_PAD_MODE {
+	DCIOCHIP_AUXSLAVE_PAD_MODE_I2C                   = 0x0,
+	DCIOCHIP_AUXSLAVE_PAD_MODE_AUX                   = 0x1,
+} DCIOCHIP_AUXSLAVE_PAD_MODE;
+typedef enum DCIOCHIP_INVERT {
+	DCIOCHIP_POL_NON_INVERT                          = 0x0,
+	DCIOCHIP_POL_INVERT                              = 0x1,
+} DCIOCHIP_INVERT;
+typedef enum DCIOCHIP_PD_EN {
+	DCIOCHIP_PD_EN_NOTALLOW                          = 0x0,
+	DCIOCHIP_PD_EN_ALLOW                             = 0x1,
+} DCIOCHIP_PD_EN;
+typedef enum DCIOCHIP_GPIO_MASK_EN {
+	DCIOCHIP_GPIO_MASK_EN_HARDWARE                   = 0x0,
+	DCIOCHIP_GPIO_MASK_EN_SOFTWARE                   = 0x1,
+} DCIOCHIP_GPIO_MASK_EN;
+typedef enum DCIOCHIP_MASK {
+	DCIOCHIP_MASK_DISABLE                            = 0x0,
+	DCIOCHIP_MASK_ENABLE                             = 0x1,
+} DCIOCHIP_MASK;
+typedef enum DCIOCHIP_GPIO_I2C_MASK {
+	DCIOCHIP_GPIO_I2C_MASK_DISABLE                   = 0x0,
+	DCIOCHIP_GPIO_I2C_MASK_ENABLE                    = 0x1,
+} DCIOCHIP_GPIO_I2C_MASK;
+typedef enum DCIOCHIP_GPIO_I2C_DRIVE {
+	DCIOCHIP_GPIO_I2C_DRIVE_LOW                      = 0x0,
+	DCIOCHIP_GPIO_I2C_DRIVE_HIGH                     = 0x1,
+} DCIOCHIP_GPIO_I2C_DRIVE;
+typedef enum DCIOCHIP_GPIO_I2C_EN {
+	DCIOCHIP_GPIO_I2C_DISABLE                        = 0x0,
+	DCIOCHIP_GPIO_I2C_ENABLE                         = 0x1,
+} DCIOCHIP_GPIO_I2C_EN;
+typedef enum DCIOCHIP_MASK_4BIT {
+	DCIOCHIP_MASK_4BIT_DISABLE                       = 0x0,
+	DCIOCHIP_MASK_4BIT_ENABLE                        = 0xf,
+} DCIOCHIP_MASK_4BIT;
+typedef enum DCIOCHIP_ENABLE_4BIT {
+	DCIOCHIP_4BIT_DISABLE                            = 0x0,
+	DCIOCHIP_4BIT_ENABLE                             = 0xf,
+} DCIOCHIP_ENABLE_4BIT;
+typedef enum DCIOCHIP_MASK_5BIT {
+	DCIOCHIP_MASIK_5BIT_DISABLE                      = 0x0,
+	DCIOCHIP_MASIK_5BIT_ENABLE                       = 0x1f,
+} DCIOCHIP_MASK_5BIT;
+typedef enum DCIOCHIP_ENABLE_5BIT {
+	DCIOCHIP_5BIT_DISABLE                            = 0x0,
+	DCIOCHIP_5BIT_ENABLE                             = 0x1f,
+} DCIOCHIP_ENABLE_5BIT;
+typedef enum DCIOCHIP_MASK_2BIT {
+	DCIOCHIP_MASK_2BIT_DISABLE                       = 0x0,
+	DCIOCHIP_MASK_2BIT_ENABLE                        = 0x3,
+} DCIOCHIP_MASK_2BIT;
+typedef enum DCIOCHIP_ENABLE_2BIT {
+	DCIOCHIP_2BIT_DISABLE                            = 0x0,
+	DCIOCHIP_2BIT_ENABLE                             = 0x3,
+} DCIOCHIP_ENABLE_2BIT;
+typedef enum DCIOCHIP_REF_27_SRC_SEL {
+	DCIOCHIP_REF_27_SRC_SEL_XTAL_DIVIDER             = 0x0,
+	DCIOCHIP_REF_27_SRC_SEL_DISP_CLKIN2_DIVIDER      = 0x1,
+	DCIOCHIP_REF_27_SRC_SEL_XTAL_BYPASS              = 0x2,
+	DCIOCHIP_REF_27_SRC_SEL_DISP_CLKIN2_BYPASS       = 0x3,
+} DCIOCHIP_REF_27_SRC_SEL;
+typedef enum DCIOCHIP_DVO_VREFPON {
+	DCIOCHIP_DVO_VREFPON_DISABLE                     = 0x0,
+	DCIOCHIP_DVO_VREFPON_ENABLE                      = 0x1,
+} DCIOCHIP_DVO_VREFPON;
+typedef enum DCIOCHIP_DVO_VREFSEL {
+	DCIOCHIP_DVO_VREFSEL_ONCHIP                      = 0x0,
+	DCIOCHIP_DVO_VREFSEL_EXTERNAL                    = 0x1,
+} DCIOCHIP_DVO_VREFSEL;
+typedef enum DCIOCHIP_SPDIF1_IMODE {
+	DCIOCHIP_SPDIF1_IMODE_OE_A                       = 0x0,
+	DCIOCHIP_SPDIF1_IMODE_TSTE_TSTO                  = 0x1,
+} DCIOCHIP_SPDIF1_IMODE;
+typedef enum DCIOCHIP_AUX_FALLSLEWSEL {
+	DCIOCHIP_AUX_FALLSLEWSEL_LOW                     = 0x0,
+	DCIOCHIP_AUX_FALLSLEWSEL_HIGH0                   = 0x1,
+	DCIOCHIP_AUX_FALLSLEWSEL_HIGH1                   = 0x2,
+	DCIOCHIP_AUX_FALLSLEWSEL_ULTRAHIGH               = 0x3,
+} DCIOCHIP_AUX_FALLSLEWSEL;
+typedef enum DCIOCHIP_AUX_SPIKESEL {
+	DCIOCHIP_AUX_SPIKESEL_50NS                       = 0x0,
+	DCIOCHIP_AUX_SPIKESEL_10NS                       = 0x1,
+} DCIOCHIP_AUX_SPIKESEL;
+typedef enum DCIOCHIP_AUX_CSEL0P9 {
+	DCIOCHIP_AUX_CSEL_DEC1P0                         = 0x0,
+	DCIOCHIP_AUX_CSEL_DEC0P9                         = 0x1,
+} DCIOCHIP_AUX_CSEL0P9;
+typedef enum DCIOCHIP_AUX_CSEL1P1 {
+	DCIOCHIP_AUX_CSEL_INC1P0                         = 0x0,
+	DCIOCHIP_AUX_CSEL_INC1P1                         = 0x1,
+} DCIOCHIP_AUX_CSEL1P1;
+typedef enum DCIOCHIP_AUX_RSEL0P9 {
+	DCIOCHIP_AUX_RSEL_DEC1P0                         = 0x0,
+	DCIOCHIP_AUX_RSEL_DEC0P9                         = 0x1,
+} DCIOCHIP_AUX_RSEL0P9;
+typedef enum DCIOCHIP_AUX_RSEL1P1 {
+	DCIOCHIP_AUX_RSEL_INC1P0                         = 0x0,
+	DCIOCHIP_AUX_RSEL_INC1P1                         = 0x1,
+} DCIOCHIP_AUX_RSEL1P1;
+typedef enum DCP_GRPH_ENABLE {
+	DCP_GRPH_ENABLE_FALSE                            = 0x0,
+	DCP_GRPH_ENABLE_TRUE                             = 0x1,
+} DCP_GRPH_ENABLE;
+typedef enum DCP_GRPH_KEYER_ALPHA_SEL {
+	DCP_GRPH_KEYER_ALPHA_SEL_FALSE                   = 0x0,
+	DCP_GRPH_KEYER_ALPHA_SEL_TRUE                    = 0x1,
+} DCP_GRPH_KEYER_ALPHA_SEL;
+typedef enum DCP_GRPH_DEPTH {
+	DCP_GRPH_DEPTH_8BPP                              = 0x0,
+	DCP_GRPH_DEPTH_16BPP                             = 0x1,
+	DCP_GRPH_DEPTH_32BPP                             = 0x2,
+	DCP_GRPH_DEPTH_64BPP                             = 0x3,
+} DCP_GRPH_DEPTH;
+typedef enum DCP_GRPH_NUM_BANKS {
+	DCP_GRPH_NUM_BANKS_2BANK                         = 0x0,
+	DCP_GRPH_NUM_BANKS_4BANK                         = 0x1,
+	DCP_GRPH_NUM_BANKS_8BANK                         = 0x2,
+	DCP_GRPH_NUM_BANKS_16BANK                        = 0x3,
+} DCP_GRPH_NUM_BANKS;
+typedef enum DCP_GRPH_BANK_WIDTH {
+	DCP_GRPH_BANK_WIDTH_1                            = 0x0,
+	DCP_GRPH_BANK_WIDTH_2                            = 0x1,
+	DCP_GRPH_BANK_WIDTH_4                            = 0x2,
+	DCP_GRPH_BANK_WIDTH_8                            = 0x3,
+} DCP_GRPH_BANK_WIDTH;
+typedef enum DCP_GRPH_FORMAT {
+	DCP_GRPH_FORMAT_8BPP                             = 0x0,
+	DCP_GRPH_FORMAT_16BPP                            = 0x1,
+	DCP_GRPH_FORMAT_32BPP                            = 0x2,
+	DCP_GRPH_FORMAT_64BPP                            = 0x3,
+} DCP_GRPH_FORMAT;
+typedef enum DCP_GRPH_BANK_HEIGHT {
+	DCP_GRPH_BANK_HEIGHT_1                           = 0x0,
+	DCP_GRPH_BANK_HEIGHT_2                           = 0x1,
+	DCP_GRPH_BANK_HEIGHT_4                           = 0x2,
+	DCP_GRPH_BANK_HEIGHT_8                           = 0x3,
+} DCP_GRPH_BANK_HEIGHT;
+typedef enum DCP_GRPH_TILE_SPLIT {
+	DCP_GRPH_TILE_SPLIT_64B                          = 0x0,
+	DCP_GRPH_TILE_SPLIT_128B                         = 0x1,
+	DCP_GRPH_TILE_SPLIT_256B                         = 0x2,
+	DCP_GRPH_TILE_SPLIT_512B                         = 0x3,
+	DCP_GRPH_TILE_SPLIT_1B                           = 0x4,
+	DCP_GRPH_TILE_SPLIT_2B                           = 0x5,
+	DCP_GRPH_TILE_SPLIT_4B                           = 0x6,
+} DCP_GRPH_TILE_SPLIT;
+typedef enum DCP_GRPH_ADDRESS_TRANSLATION_ENABLE {
+	DCP_GRPH_ADDRESS_TRANSLATION_ENABLE_FALSE        = 0x0,
+	DCP_GRPH_ADDRESS_TRANSLATION_ENABLE_TRUE         = 0x1,
+} DCP_GRPH_ADDRESS_TRANSLATION_ENABLE;
+typedef enum DCP_GRPH_PRIVILEGED_ACCESS_ENABLE {
+	DCP_GRPH_PRIVILEGED_ACCESS_ENABLE_FALSE          = 0x0,
+	DCP_GRPH_PRIVILEGED_ACCESS_ENABLE_TRUE           = 0x1,
+} DCP_GRPH_PRIVILEGED_ACCESS_ENABLE;
+typedef enum DCP_GRPH_MACRO_TILE_ASPECT {
+	DCP_GRPH_MACRO_TILE_ASPECT_1                     = 0x0,
+	DCP_GRPH_MACRO_TILE_ASPECT_2                     = 0x1,
+	DCP_GRPH_MACRO_TILE_ASPECT_4                     = 0x2,
+	DCP_GRPH_MACRO_TILE_ASPECT_8                     = 0x3,
+} DCP_GRPH_MACRO_TILE_ASPECT;
+typedef enum DCP_GRPH_ARRAY_MODE {
+	DCP_GRPH_ARRAY_MODE_0                            = 0x0,
+	DCP_GRPH_ARRAY_MODE_1                            = 0x1,
+	DCP_GRPH_ARRAY_MODE_2                            = 0x2,
+	DCP_GRPH_ARRAY_MODE_3                            = 0x3,
+	DCP_GRPH_ARRAY_MODE_4                            = 0x4,
+	DCP_GRPH_ARRAY_MODE_7                            = 0x7,
+	DCP_GRPH_ARRAY_MODE_12                           = 0xc,
+	DCP_GRPH_ARRAY_MODE_13                           = 0xd,
+} DCP_GRPH_ARRAY_MODE;
+typedef enum DCP_GRPH_MICRO_TILE_MODE {
+	DCP_GRPH_MICRO_TILE_MODE_0                       = 0x0,
+	DCP_GRPH_MICRO_TILE_MODE_1                       = 0x1,
+	DCP_GRPH_MICRO_TILE_MODE_2                       = 0x2,
+	DCP_GRPH_MICRO_TILE_MODE_3                       = 0x3,
+} DCP_GRPH_MICRO_TILE_MODE;
+typedef enum DCP_GRPH_COLOR_EXPANSION_MODE {
+	DCP_GRPH_COLOR_EXPANSION_MODE_DEXP               = 0x0,
+	DCP_GRPH_COLOR_EXPANSION_MODE_ZEXP               = 0x1,
+} DCP_GRPH_COLOR_EXPANSION_MODE;
+typedef enum DCP_GRPH_LUT_10BIT_BYPASS_EN {
+	DCP_GRPH_LUT_10BIT_BYPASS_EN_FALSE               = 0x0,
+	DCP_GRPH_LUT_10BIT_BYPASS_EN_TRUE                = 0x1,
+} DCP_GRPH_LUT_10BIT_BYPASS_EN;
+typedef enum DCP_GRPH_LUT_10BIT_BYPASS_DBL_BUF_EN {
+	DCP_GRPH_LUT_10BIT_BYPASS_DBL_BUF_EN_FALSE       = 0x0,
+	DCP_GRPH_LUT_10BIT_BYPASS_DBL_BUF_EN_TRUE        = 0x1,
+} DCP_GRPH_LUT_10BIT_BYPASS_DBL_BUF_EN;
+typedef enum DCP_GRPH_ENDIAN_SWAP {
+	DCP_GRPH_ENDIAN_SWAP_NONE                        = 0x0,
+	DCP_GRPH_ENDIAN_SWAP_8IN16                       = 0x1,
+	DCP_GRPH_ENDIAN_SWAP_8IN32                       = 0x2,
+	DCP_GRPH_ENDIAN_SWAP_8IN64                       = 0x3,
+} DCP_GRPH_ENDIAN_SWAP;
+typedef enum DCP_GRPH_RED_CROSSBAR {
+	DCP_GRPH_RED_CROSSBAR_FROM_R                     = 0x0,
+	DCP_GRPH_RED_CROSSBAR_FROM_G                     = 0x1,
+	DCP_GRPH_RED_CROSSBAR_FROM_B                     = 0x2,
+	DCP_GRPH_RED_CROSSBAR_FROM_A                     = 0x3,
+} DCP_GRPH_RED_CROSSBAR;
+typedef enum DCP_GRPH_GREEN_CROSSBAR {
+	DCP_GRPH_GREEN_CROSSBAR_FROM_G                   = 0x0,
+	DCP_GRPH_GREEN_CROSSBAR_FROM_B                   = 0x1,
+	DCP_GRPH_GREEN_CROSSBAR_FROM_A                   = 0x2,
+	DCP_GRPH_GREEN_CROSSBAR_FROM_R                   = 0x3,
+} DCP_GRPH_GREEN_CROSSBAR;
+typedef enum DCP_GRPH_BLUE_CROSSBAR {
+	DCP_GRPH_BLUE_CROSSBAR_FROM_B                    = 0x0,
+	DCP_GRPH_BLUE_CROSSBAR_FROM_A                    = 0x1,
+	DCP_GRPH_BLUE_CROSSBAR_FROM_R                    = 0x2,
+	DCP_GRPH_BLUE_CROSSBAR_FROM_G                    = 0x3,
+} DCP_GRPH_BLUE_CROSSBAR;
+typedef enum DCP_GRPH_ALPHA_CROSSBAR {
+	DCP_GRPH_ALPHA_CROSSBAR_FROM_A                   = 0x0,
+	DCP_GRPH_ALPHA_CROSSBAR_FROM_R                   = 0x1,
+	DCP_GRPH_ALPHA_CROSSBAR_FROM_G                   = 0x2,
+	DCP_GRPH_ALPHA_CROSSBAR_FROM_B                   = 0x3,
+} DCP_GRPH_ALPHA_CROSSBAR;
+typedef enum DCP_GRPH_PRIMARY_DFQ_ENABLE {
+	DCP_GRPH_PRIMARY_DFQ_ENABLE_FALSE                = 0x0,
+	DCP_GRPH_PRIMARY_DFQ_ENABLE_TRUE                 = 0x1,
+} DCP_GRPH_PRIMARY_DFQ_ENABLE;
+typedef enum DCP_GRPH_SECONDARY_DFQ_ENABLE {
+	DCP_GRPH_SECONDARY_DFQ_ENABLE_FALSE              = 0x0,
+	DCP_GRPH_SECONDARY_DFQ_ENABLE_TRUE               = 0x1,
+} DCP_GRPH_SECONDARY_DFQ_ENABLE;
+typedef enum DCP_GRPH_INPUT_GAMMA_MODE {
+	DCP_GRPH_INPUT_GAMMA_MODE_LUT                    = 0x0,
+	DCP_GRPH_INPUT_GAMMA_MODE_BYPASS                 = 0x1,
+} DCP_GRPH_INPUT_GAMMA_MODE;
+typedef enum DCP_GRPH_MODE_UPDATE_PENDING {
+	DCP_GRPH_MODE_UPDATE_PENDING_FALSE               = 0x0,
+	DCP_GRPH_MODE_UPDATE_PENDING_TRUE                = 0x1,
+} DCP_GRPH_MODE_UPDATE_PENDING;
+typedef enum DCP_GRPH_MODE_UPDATE_TAKEN {
+	DCP_GRPH_MODE_UPDATE_TAKEN_FALSE                 = 0x0,
+	DCP_GRPH_MODE_UPDATE_TAKEN_TRUE                  = 0x1,
+} DCP_GRPH_MODE_UPDATE_TAKEN;
+typedef enum DCP_GRPH_SURFACE_UPDATE_PENDING {
+	DCP_GRPH_SURFACE_UPDATE_PENDING_FALSE            = 0x0,
+	DCP_GRPH_SURFACE_UPDATE_PENDING_TRUE             = 0x1,
+} DCP_GRPH_SURFACE_UPDATE_PENDING;
+typedef enum DCP_GRPH_SURFACE_UPDATE_TAKEN {
+	DCP_GRPH_SURFACE_UPDATE_TAKEN_FALSE              = 0x0,
+	DCP_GRPH_SURFACE_UPDATE_TAKEN_TRUE               = 0x1,
+} DCP_GRPH_SURFACE_UPDATE_TAKEN;
+typedef enum DCP_GRPH_SURFACE_XDMA_PENDING_ENABLE {
+	DCP_GRPH_SURFACE_XDMA_PENDING_ENABLE_FALSE       = 0x0,
+	DCP_GRPH_SURFACE_XDMA_PENDING_ENABLE_TRUE        = 0x1,
+} DCP_GRPH_SURFACE_XDMA_PENDING_ENABLE;
+typedef enum DCP_GRPH_UPDATE_LOCK {
+	DCP_GRPH_UPDATE_LOCK_FALSE                       = 0x0,
+	DCP_GRPH_UPDATE_LOCK_TRUE                        = 0x1,
+} DCP_GRPH_UPDATE_LOCK;
+typedef enum DCP_GRPH_SURFACE_IGNORE_UPDATE_LOCK {
+	DCP_GRPH_SURFACE_IGNORE_UPDATE_LOCK_FALSE        = 0x0,
+	DCP_GRPH_SURFACE_IGNORE_UPDATE_LOCK_TRUE         = 0x1,
+} DCP_GRPH_SURFACE_IGNORE_UPDATE_LOCK;
+typedef enum DCP_GRPH_MODE_DISABLE_MULTIPLE_UPDATE {
+	DCP_GRPH_MODE_DISABLE_MULTIPLE_UPDATE_FALSE      = 0x0,
+	DCP_GRPH_MODE_DISABLE_MULTIPLE_UPDATE_TRUE       = 0x1,
+} DCP_GRPH_MODE_DISABLE_MULTIPLE_UPDATE;
+typedef enum DCP_GRPH_SURFACE_DISABLE_MULTIPLE_UPDATE {
+	DCP_GRPH_SURFACE_DISABLE_MULTIPLE_UPDATE_FALSE   = 0x0,
+	DCP_GRPH_SURFACE_DISABLE_MULTIPLE_UPDATE_TRUE    = 0x1,
+} DCP_GRPH_SURFACE_DISABLE_MULTIPLE_UPDATE;
+typedef enum DCP_GRPH_SURFACE_UPDATE_H_RETRACE_EN {
+	DCP_GRPH_SURFACE_UPDATE_H_RETRACE_EN_FALSE       = 0x0,
+	DCP_GRPH_SURFACE_UPDATE_H_RETRACE_EN_TRUE        = 0x1,
+} DCP_GRPH_SURFACE_UPDATE_H_RETRACE_EN;
+typedef enum DCP_GRPH_XDMA_SUPER_AA_EN {
+	DCP_GRPH_XDMA_SUPER_AA_EN_FALSE                  = 0x0,
+	DCP_GRPH_XDMA_SUPER_AA_EN_TRUE                   = 0x1,
+} DCP_GRPH_XDMA_SUPER_AA_EN;
+typedef enum DCP_GRPH_DFQ_RESET {
+	DCP_GRPH_DFQ_RESET_FALSE                         = 0x0,
+	DCP_GRPH_DFQ_RESET_TRUE                          = 0x1,
+} DCP_GRPH_DFQ_RESET;
+typedef enum DCP_GRPH_DFQ_SIZE {
+	DCP_GRPH_DFQ_SIZE_DEEP1                          = 0x0,
+	DCP_GRPH_DFQ_SIZE_DEEP2                          = 0x1,
+	DCP_GRPH_DFQ_SIZE_DEEP3                          = 0x2,
+	DCP_GRPH_DFQ_SIZE_DEEP4                          = 0x3,
+	DCP_GRPH_DFQ_SIZE_DEEP5                          = 0x4,
+	DCP_GRPH_DFQ_SIZE_DEEP6                          = 0x5,
+	DCP_GRPH_DFQ_SIZE_DEEP7                          = 0x6,
+	DCP_GRPH_DFQ_SIZE_DEEP8                          = 0x7,
+} DCP_GRPH_DFQ_SIZE;
+typedef enum DCP_GRPH_DFQ_MIN_FREE_ENTRIES {
+	DCP_GRPH_DFQ_MIN_FREE_ENTRIES_1                  = 0x0,
+	DCP_GRPH_DFQ_MIN_FREE_ENTRIES_2                  = 0x1,
+	DCP_GRPH_DFQ_MIN_FREE_ENTRIES_3                  = 0x2,
+	DCP_GRPH_DFQ_MIN_FREE_ENTRIES_4                  = 0x3,
+	DCP_GRPH_DFQ_MIN_FREE_ENTRIES_5                  = 0x4,
+	DCP_GRPH_DFQ_MIN_FREE_ENTRIES_6                  = 0x5,
+	DCP_GRPH_DFQ_MIN_FREE_ENTRIES_7                  = 0x6,
+	DCP_GRPH_DFQ_MIN_FREE_ENTRIES_8                  = 0x7,
+} DCP_GRPH_DFQ_MIN_FREE_ENTRIES;
+typedef enum DCP_GRPH_DFQ_RESET_ACK {
+	DCP_GRPH_DFQ_RESET_ACK_FALSE                     = 0x0,
+	DCP_GRPH_DFQ_RESET_ACK_TRUE                      = 0x1,
+} DCP_GRPH_DFQ_RESET_ACK;
+typedef enum DCP_GRPH_PFLIP_INT_CLEAR {
+	DCP_GRPH_PFLIP_INT_CLEAR_FALSE                   = 0x0,
+	DCP_GRPH_PFLIP_INT_CLEAR_TRUE                    = 0x1,
+} DCP_GRPH_PFLIP_INT_CLEAR;
+typedef enum DCP_GRPH_PFLIP_INT_MASK {
+	DCP_GRPH_PFLIP_INT_MASK_FALSE                    = 0x0,
+	DCP_GRPH_PFLIP_INT_MASK_TRUE                     = 0x1,
+} DCP_GRPH_PFLIP_INT_MASK;
+typedef enum DCP_GRPH_PFLIP_INT_TYPE {
+	DCP_GRPH_PFLIP_INT_TYPE_LEGACY_LEVEL             = 0x0,
+	DCP_GRPH_PFLIP_INT_TYPE_PULSE                    = 0x1,
+} DCP_GRPH_PFLIP_INT_TYPE;
+typedef enum DCP_GRPH_PRESCALE_SELECT {
+	DCP_GRPH_PRESCALE_SELECT_FIXED                   = 0x0,
+	DCP_GRPH_PRESCALE_SELECT_FLOATING                = 0x1,
+} DCP_GRPH_PRESCALE_SELECT;
+typedef enum DCP_GRPH_PRESCALE_R_SIGN {
+	DCP_GRPH_PRESCALE_R_SIGN_UNSIGNED                = 0x0,
+	DCP_GRPH_PRESCALE_R_SIGN_SIGNED                  = 0x1,
+} DCP_GRPH_PRESCALE_R_SIGN;
+typedef enum DCP_GRPH_PRESCALE_G_SIGN {
+	DCP_GRPH_PRESCALE_G_SIGN_UNSIGNED                = 0x0,
+	DCP_GRPH_PRESCALE_G_SIGN_SIGNED                  = 0x1,
+} DCP_GRPH_PRESCALE_G_SIGN;
+typedef enum DCP_GRPH_PRESCALE_B_SIGN {
+	DCP_GRPH_PRESCALE_B_SIGN_UNSIGNED                = 0x0,
+	DCP_GRPH_PRESCALE_B_SIGN_SIGNED                  = 0x1,
+} DCP_GRPH_PRESCALE_B_SIGN;
+typedef enum DCP_GRPH_PRESCALE_BYPASS {
+	DCP_GRPH_PRESCALE_BYPASS_FALSE                   = 0x0,
+	DCP_GRPH_PRESCALE_BYPASS_TRUE                    = 0x1,
+} DCP_GRPH_PRESCALE_BYPASS;
+typedef enum DCP_INPUT_CSC_GRPH_MODE {
+	DCP_INPUT_CSC_GRPH_MODE_BYPASS                   = 0x0,
+	DCP_INPUT_CSC_GRPH_MODE_INPUT_CSC_COEF           = 0x1,
+	DCP_INPUT_CSC_GRPH_MODE_SHARED_COEF              = 0x2,
+	DCP_INPUT_CSC_GRPH_MODE_RESERVED                 = 0x3,
+} DCP_INPUT_CSC_GRPH_MODE;
+typedef enum DCP_OUTPUT_CSC_GRPH_MODE {
+	DCP_OUTPUT_CSC_GRPH_MODE_BYPASS                  = 0x0,
+	DCP_OUTPUT_CSC_GRPH_MODE_RGB                     = 0x1,
+	DCP_OUTPUT_CSC_GRPH_MODE_YCBCR601                = 0x2,
+	DCP_OUTPUT_CSC_GRPH_MODE_YCBCR709                = 0x3,
+	DCP_OUTPUT_CSC_GRPH_MODE_OUTPUT_CSC_COEF         = 0x4,
+	DCP_OUTPUT_CSC_GRPH_MODE_SHARED_COEF             = 0x5,
+	DCP_OUTPUT_CSC_GRPH_MODE_RESERVED0               = 0x6,
+	DCP_OUTPUT_CSC_GRPH_MODE_RESERVED1               = 0x7,
+} DCP_OUTPUT_CSC_GRPH_MODE;
+typedef enum DCP_DENORM_MODE {
+	DCP_DENORM_MODE_UNITY                            = 0x0,
+	DCP_DENORM_MODE_6BIT                             = 0x1,
+	DCP_DENORM_MODE_8BIT                             = 0x2,
+	DCP_DENORM_MODE_10BIT                            = 0x3,
+	DCP_DENORM_MODE_11BIT                            = 0x4,
+	DCP_DENORM_MODE_12BIT                            = 0x5,
+	DCP_DENORM_MODE_RESERVED0                        = 0x6,
+	DCP_DENORM_MODE_RESERVED1                        = 0x7,
+} DCP_DENORM_MODE;
+typedef enum DCP_DENORM_14BIT_OUT {
+	DCP_DENORM_14BIT_OUT_FALSE                       = 0x0,
+	DCP_DENORM_14BIT_OUT_TRUE                        = 0x1,
+} DCP_DENORM_14BIT_OUT;
+typedef enum DCP_OUT_ROUND_TRUNC_MODE {
+	DCP_OUT_ROUND_TRUNC_MODE_TRUNCATE_12             = 0x0,
+	DCP_OUT_ROUND_TRUNC_MODE_TRUNCATE_11             = 0x1,
+	DCP_OUT_ROUND_TRUNC_MODE_TRUNCATE_10             = 0x2,
+	DCP_OUT_ROUND_TRUNC_MODE_TRUNCATE_9              = 0x3,
+	DCP_OUT_ROUND_TRUNC_MODE_TRUNCATE_8              = 0x4,
+	DCP_OUT_ROUND_TRUNC_MODE_TRUNCATE_RESERVED       = 0x5,
+	DCP_OUT_ROUND_TRUNC_MODE_TRUNCATE_14             = 0x6,
+	DCP_OUT_ROUND_TRUNC_MODE_TRUNCATE_13             = 0x7,
+	DCP_OUT_ROUND_TRUNC_MODE_ROUND_12                = 0x8,
+	DCP_OUT_ROUND_TRUNC_MODE_ROUND_11                = 0x9,
+	DCP_OUT_ROUND_TRUNC_MODE_ROUND_10                = 0xa,
+	DCP_OUT_ROUND_TRUNC_MODE_ROUND_9                 = 0xb,
+	DCP_OUT_ROUND_TRUNC_MODE_ROUND_8                 = 0xc,
+	DCP_OUT_ROUND_TRUNC_MODE_ROUND_RESERVED          = 0xd,
+	DCP_OUT_ROUND_TRUNC_MODE_ROUND_14                = 0xe,
+	DCP_OUT_ROUND_TRUNC_MODE_ROUND_13                = 0xf,
+} DCP_OUT_ROUND_TRUNC_MODE;
+typedef enum DCP_KEY_MODE {
+	DCP_KEY_MODE_ALPHA0                              = 0x0,
+	DCP_KEY_MODE_ALPHA1                              = 0x1,
+	DCP_KEY_MODE_IN_RANGE_ALPHA1                     = 0x2,
+	DCP_KEY_MODE_IN_RANGE_ALPHA0                     = 0x3,
+} DCP_KEY_MODE;
+typedef enum DCP_GRPH_DEGAMMA_MODE {
+	DCP_GRPH_DEGAMMA_MODE_BYPASS                     = 0x0,
+	DCP_GRPH_DEGAMMA_MODE_ROMA                       = 0x1,
+	DCP_GRPH_DEGAMMA_MODE_ROMB                       = 0x2,
+	DCP_GRPH_DEGAMMA_MODE_RESERVED                   = 0x3,
+} DCP_GRPH_DEGAMMA_MODE;
+typedef enum DCP_CURSOR2_DEGAMMA_MODE {
+	DCP_CURSOR2_DEGAMMA_MODE_BYPASS                  = 0x0,
+	DCP_CURSOR2_DEGAMMA_MODE_ROMA                    = 0x1,
+	DCP_CURSOR2_DEGAMMA_MODE_ROMB                    = 0x2,
+	DCP_CURSOR2_DEGAMMA_MODE_RESERVED                = 0x3,
+} DCP_CURSOR2_DEGAMMA_MODE;
+typedef enum DCP_CURSOR_DEGAMMA_MODE {
+	DCP_CURSOR_DEGAMMA_MODE_BYPASS                   = 0x0,
+	DCP_CURSOR_DEGAMMA_MODE_ROMA                     = 0x1,
+	DCP_CURSOR_DEGAMMA_MODE_ROMB                     = 0x2,
+	DCP_CURSOR_DEGAMMA_MODE_RESERVED                 = 0x3,
+} DCP_CURSOR_DEGAMMA_MODE;
+typedef enum DCP_GRPH_GAMUT_REMAP_MODE {
+	DCP_GRPH_GAMUT_REMAP_MODE_BYPASS                 = 0x0,
+	DCP_GRPH_GAMUT_REMAP_MODE_ROMA                   = 0x1,
+	DCP_GRPH_GAMUT_REMAP_MODE_ROMB                   = 0x2,
+	DCP_GRPH_GAMUT_REMAP_MODE_RESERVED               = 0x3,
+} DCP_GRPH_GAMUT_REMAP_MODE;
+typedef enum DCP_SPATIAL_DITHER_EN {
+	DCP_SPATIAL_DITHER_EN_FALSE                      = 0x0,
+	DCP_SPATIAL_DITHER_EN_TRUE                       = 0x1,
+} DCP_SPATIAL_DITHER_EN;
+typedef enum DCP_SPATIAL_DITHER_MODE {
+	DCP_SPATIAL_DITHER_MODE_BYPASS                   = 0x0,
+	DCP_SPATIAL_DITHER_MODE_ROMA                     = 0x1,
+	DCP_SPATIAL_DITHER_MODE_ROMB                     = 0x2,
+	DCP_SPATIAL_DITHER_MODE_RESERVED                 = 0x3,
+} DCP_SPATIAL_DITHER_MODE;
+typedef enum DCP_SPATIAL_DITHER_DEPTH {
+	DCP_SPATIAL_DITHER_DEPTH_30BPP                   = 0x0,
+	DCP_SPATIAL_DITHER_DEPTH_24BPP                   = 0x1,
+	DCP_SPATIAL_DITHER_DEPTH_36BPP                   = 0x2,
+	DCP_SPATIAL_DITHER_DEPTH_UNDEFINED               = 0x3,
+} DCP_SPATIAL_DITHER_DEPTH;
+typedef enum DCP_FRAME_RANDOM_ENABLE {
+	DCP_FRAME_RANDOM_ENABLE_FALSE                    = 0x0,
+	DCP_FRAME_RANDOM_ENABLE_TRUE                     = 0x1,
+} DCP_FRAME_RANDOM_ENABLE;
+typedef enum DCP_RGB_RANDOM_ENABLE {
+	DCP_RGB_RANDOM_ENABLE_FALSE                      = 0x0,
+	DCP_RGB_RANDOM_ENABLE_TRUE                       = 0x1,
+} DCP_RGB_RANDOM_ENABLE;
+typedef enum DCP_HIGHPASS_RANDOM_ENABLE {
+	DCP_HIGHPASS_RANDOM_ENABLE_FALSE                 = 0x0,
+	DCP_HIGHPASS_RANDOM_ENABLE_TRUE                  = 0x1,
+} DCP_HIGHPASS_RANDOM_ENABLE;
+typedef enum DCP_CURSOR_EN {
+	DCP_CURSOR_EN_FALSE                              = 0x0,
+	DCP_CURSOR_EN_TRUE                               = 0x1,
+} DCP_CURSOR_EN;
+typedef enum DCP_CUR_INV_TRANS_CLAMP {
+	DCP_CUR_INV_TRANS_CLAMP_FALSE                    = 0x0,
+	DCP_CUR_INV_TRANS_CLAMP_TRUE                     = 0x1,
+} DCP_CUR_INV_TRANS_CLAMP;
+typedef enum DCP_CURSOR_MODE {
+	DCP_CURSOR_MODE_MONO_2BPP                        = 0x0,
+	DCP_CURSOR_MODE_24BPP_1BIT                       = 0x1,
+	DCP_CURSOR_MODE_24BPP_8BIT_PREMULTI              = 0x2,
+	DCP_CURSOR_MODE_24BPP_8BIT_UNPREMULTI            = 0x3,
+} DCP_CURSOR_MODE;
+typedef enum DCP_CURSOR_2X_MAGNIFY {
+	DCP_CURSOR_2X_MAGNIFY_FALSE                      = 0x0,
+	DCP_CURSOR_2X_MAGNIFY_TRUE                       = 0x1,
+} DCP_CURSOR_2X_MAGNIFY;
+typedef enum DCP_CURSOR_FORCE_MC_ON {
+	DCP_CURSOR_FORCE_MC_ON_FALSE                     = 0x0,
+	DCP_CURSOR_FORCE_MC_ON_TRUE                      = 0x1,
+} DCP_CURSOR_FORCE_MC_ON;
+typedef enum DCP_CURSOR_URGENT_CONTROL {
+	DCP_CURSOR_URGENT_CONTROL_MODE_0                 = 0x0,
+	DCP_CURSOR_URGENT_CONTROL_MODE_1                 = 0x1,
+	DCP_CURSOR_URGENT_CONTROL_MODE_2                 = 0x2,
+	DCP_CURSOR_URGENT_CONTROL_MODE_3                 = 0x3,
+	DCP_CURSOR_URGENT_CONTROL_MODE_4                 = 0x4,
+} DCP_CURSOR_URGENT_CONTROL;
+typedef enum DCP_CURSOR_UPDATE_PENDING {
+	DCP_CURSOR_UPDATE_PENDING_FALSE                  = 0x0,
+	DCP_CURSOR_UPDATE_PENDING_TRUE                   = 0x1,
+} DCP_CURSOR_UPDATE_PENDING;
+typedef enum DCP_CURSOR_UPDATE_TAKEN {
+	DCP_CURSOR_UPDATE_TAKEN_FALSE                    = 0x0,
+	DCP_CURSOR_UPDATE_TAKEN_TRUE                     = 0x1,
+} DCP_CURSOR_UPDATE_TAKEN;
+typedef enum DCP_CURSOR_UPDATE_LOCK {
+	DCP_CURSOR_UPDATE_LOCK_FALSE                     = 0x0,
+	DCP_CURSOR_UPDATE_LOCK_TRUE                      = 0x1,
+} DCP_CURSOR_UPDATE_LOCK;
+typedef enum DCP_CURSOR_DISABLE_MULTIPLE_UPDATE {
+	DCP_CURSOR_DISABLE_MULTIPLE_UPDATE_FALSE         = 0x0,
+	DCP_CURSOR_DISABLE_MULTIPLE_UPDATE_TRUE          = 0x1,
+} DCP_CURSOR_DISABLE_MULTIPLE_UPDATE;
+typedef enum DCP_CURSOR_UPDATE_STEREO_MODE {
+	DCP_CURSOR_UPDATE_STEREO_MODE_BOTH               = 0x0,
+	DCP_CURSOR_UPDATE_STEREO_MODE_SECONDARY_ONLY     = 0x1,
+	DCP_CURSOR_UPDATE_STEREO_MODE_UNDEFINED          = 0x2,
+	DCP_CURSOR_UPDATE_STEREO_MODE_PRIMARY_ONLY       = 0x3,
+} DCP_CURSOR_UPDATE_STEREO_MODE;
+typedef enum DCP_CURSOR2_EN {
+	DCP_CURSOR2_EN_FALSE                             = 0x0,
+	DCP_CURSOR2_EN_TRUE                              = 0x1,
+} DCP_CURSOR2_EN;
+typedef enum DCP_CUR2_INV_TRANS_CLAMP {
+	DCP_CUR2_INV_TRANS_CLAMP_FALSE                   = 0x0,
+	DCP_CUR2_INV_TRANS_CLAMP_TRUE                    = 0x1,
+} DCP_CUR2_INV_TRANS_CLAMP;
+typedef enum DCP_CURSOR2_MODE {
+	DCP_CURSOR2_MODE_MONO_2BPP                       = 0x0,
+	DCP_CURSOR2_MODE_24BPP_1BIT                      = 0x1,
+	DCP_CURSOR2_MODE_24BPP_8BIT_PREMULTI             = 0x2,
+	DCP_CURSOR2_MODE_24BPP_8BIT_UNPREMULTI           = 0x3,
+} DCP_CURSOR2_MODE;
+typedef enum DCP_CURSOR2_2X_MAGNIFY {
+	DCP_CURSOR2_2X_MAGNIFY_FALSE                     = 0x0,
+	DCP_CURSOR2_2X_MAGNIFY_TRUE                      = 0x1,
+} DCP_CURSOR2_2X_MAGNIFY;
+typedef enum DCP_CURSOR2_FORCE_MC_ON {
+	DCP_CURSOR2_FORCE_MC_ON_FALSE                    = 0x0,
+	DCP_CURSOR2_FORCE_MC_ON_TRUE                     = 0x1,
+} DCP_CURSOR2_FORCE_MC_ON;
+typedef enum DCP_CURSOR2_URGENT_CONTROL {
+	DCP_CURSOR2_URGENT_CONTROL_MODE_0                = 0x0,
+	DCP_CURSOR2_URGENT_CONTROL_MODE_1                = 0x1,
+	DCP_CURSOR2_URGENT_CONTROL_MODE_2                = 0x2,
+	DCP_CURSOR2_URGENT_CONTROL_MODE_3                = 0x3,
+	DCP_CURSOR2_URGENT_CONTROL_MODE_4                = 0x4,
+} DCP_CURSOR2_URGENT_CONTROL;
+typedef enum DCP_CURSOR2_UPDATE_PENDING {
+	DCP_CURSOR2_UPDATE_PENDING_FALSE                 = 0x0,
+	DCP_CURSOR2_UPDATE_PENDING_TRUE                  = 0x1,
+} DCP_CURSOR2_UPDATE_PENDING;
+typedef enum DCP_CURSOR2_UPDATE_TAKEN {
+	DCP_CURSOR2_UPDATE_TAKEN_FALSE                   = 0x0,
+	DCP_CURSOR2_UPDATE_TAKEN_TRUE                    = 0x1,
+} DCP_CURSOR2_UPDATE_TAKEN;
+typedef enum DCP_CURSOR2_UPDATE_LOCK {
+	DCP_CURSOR2_UPDATE_LOCK_FALSE                    = 0x0,
+	DCP_CURSOR2_UPDATE_LOCK_TRUE                     = 0x1,
+} DCP_CURSOR2_UPDATE_LOCK;
+typedef enum DCP_CURSOR2_DISABLE_MULTIPLE_UPDATE {
+	DCP_CURSOR2_DISABLE_MULTIPLE_UPDATE_FALSE        = 0x0,
+	DCP_CURSOR2_DISABLE_MULTIPLE_UPDATE_TRUE         = 0x1,
+} DCP_CURSOR2_DISABLE_MULTIPLE_UPDATE;
+typedef enum DCP_CURSOR2_UPDATE_STEREO_MODE {
+	DCP_CURSOR2_UPDATE_STEREO_MODE_BOTH              = 0x0,
+	DCP_CURSOR2_UPDATE_STEREO_MODE_SECONDARY_ONLY    = 0x1,
+	DCP_CURSOR2_UPDATE_STEREO_MODE_UNDEFINED         = 0x2,
+	DCP_CURSOR2_UPDATE_STEREO_MODE_PRIMARY_ONLY      = 0x3,
+} DCP_CURSOR2_UPDATE_STEREO_MODE;
+typedef enum DCP_CUR_REQUEST_FILTER_DIS {
+	DCP_CUR_REQUEST_FILTER_DIS_FALSE                 = 0x0,
+	DCP_CUR_REQUEST_FILTER_DIS_TRUE                  = 0x1,
+} DCP_CUR_REQUEST_FILTER_DIS;
+typedef enum DCP_CURSOR_STEREO_EN {
+	DCP_CURSOR_STEREO_EN_FALSE                       = 0x0,
+	DCP_CURSOR_STEREO_EN_TRUE                        = 0x1,
+} DCP_CURSOR_STEREO_EN;
+typedef enum DCP_CURSOR_STEREO_OFFSET_YNX {
+	DCP_CURSOR_STEREO_OFFSET_YNX_X_POSITION          = 0x0,
+	DCP_CURSOR_STEREO_OFFSET_YNX_Y_POSITION          = 0x1,
+} DCP_CURSOR_STEREO_OFFSET_YNX;
+typedef enum DCP_CURSOR2_STEREO_EN {
+	DCP_CURSOR2_STEREO_EN_FALSE                      = 0x0,
+	DCP_CURSOR2_STEREO_EN_TRUE                       = 0x1,
+} DCP_CURSOR2_STEREO_EN;
+typedef enum DCP_CURSOR2_STEREO_OFFSET_YNX {
+	DCP_CURSOR2_STEREO_OFFSET_YNX_X_POSITION         = 0x0,
+	DCP_CURSOR2_STEREO_OFFSET_YNX_Y_POSITION         = 0x1,
+} DCP_CURSOR2_STEREO_OFFSET_YNX;
+typedef enum DCP_DC_LUT_RW_MODE {
+	DCP_DC_LUT_RW_MODE_256_ENTRY                     = 0x0,
+	DCP_DC_LUT_RW_MODE_PWL                           = 0x1,
+} DCP_DC_LUT_RW_MODE;
+typedef enum DCP_DC_LUT_VGA_ACCESS_ENABLE {
+	DCP_DC_LUT_VGA_ACCESS_ENABLE_FALSE               = 0x0,
+	DCP_DC_LUT_VGA_ACCESS_ENABLE_TRUE                = 0x1,
+} DCP_DC_LUT_VGA_ACCESS_ENABLE;
+typedef enum DCP_DC_LUT_AUTOFILL {
+	DCP_DC_LUT_AUTOFILL_FALSE                        = 0x0,
+	DCP_DC_LUT_AUTOFILL_TRUE                         = 0x1,
+} DCP_DC_LUT_AUTOFILL;
+typedef enum DCP_DC_LUT_AUTOFILL_DONE {
+	DCP_DC_LUT_AUTOFILL_DONE_FALSE                   = 0x0,
+	DCP_DC_LUT_AUTOFILL_DONE_TRUE                    = 0x1,
+} DCP_DC_LUT_AUTOFILL_DONE;
+typedef enum DCP_DC_LUT_INC_B {
+	DCP_DC_LUT_INC_B_NA                              = 0x0,
+	DCP_DC_LUT_INC_B_2                               = 0x1,
+	DCP_DC_LUT_INC_B_4                               = 0x2,
+	DCP_DC_LUT_INC_B_8                               = 0x3,
+	DCP_DC_LUT_INC_B_16                              = 0x4,
+	DCP_DC_LUT_INC_B_32                              = 0x5,
+	DCP_DC_LUT_INC_B_64                              = 0x6,
+	DCP_DC_LUT_INC_B_128                             = 0x7,
+	DCP_DC_LUT_INC_B_256                             = 0x8,
+	DCP_DC_LUT_INC_B_512                             = 0x9,
+} DCP_DC_LUT_INC_B;
+typedef enum DCP_DC_LUT_DATA_B_SIGNED_EN {
+	DCP_DC_LUT_DATA_B_SIGNED_EN_FALSE                = 0x0,
+	DCP_DC_LUT_DATA_B_SIGNED_EN_TRUE                 = 0x1,
+} DCP_DC_LUT_DATA_B_SIGNED_EN;
+typedef enum DCP_DC_LUT_DATA_B_FLOAT_POINT_EN {
+	DCP_DC_LUT_DATA_B_FLOAT_POINT_EN_FALSE           = 0x0,
+	DCP_DC_LUT_DATA_B_FLOAT_POINT_EN_TRUE            = 0x1,
+} DCP_DC_LUT_DATA_B_FLOAT_POINT_EN;
+typedef enum DCP_DC_LUT_DATA_B_FORMAT {
+	DCP_DC_LUT_DATA_B_FORMAT_U0P10                   = 0x0,
+	DCP_DC_LUT_DATA_B_FORMAT_S1P10                   = 0x1,
+	DCP_DC_LUT_DATA_B_FORMAT_U1P11                   = 0x2,
+	DCP_DC_LUT_DATA_B_FORMAT_U0P12                   = 0x3,
+} DCP_DC_LUT_DATA_B_FORMAT;
+typedef enum DCP_DC_LUT_INC_G {
+	DCP_DC_LUT_INC_G_NA                              = 0x0,
+	DCP_DC_LUT_INC_G_2                               = 0x1,
+	DCP_DC_LUT_INC_G_4                               = 0x2,
+	DCP_DC_LUT_INC_G_8                               = 0x3,
+	DCP_DC_LUT_INC_G_16                              = 0x4,
+	DCP_DC_LUT_INC_G_32                              = 0x5,
+	DCP_DC_LUT_INC_G_64                              = 0x6,
+	DCP_DC_LUT_INC_G_128                             = 0x7,
+	DCP_DC_LUT_INC_G_256                             = 0x8,
+	DCP_DC_LUT_INC_G_512                             = 0x9,
+} DCP_DC_LUT_INC_G;
+typedef enum DCP_DC_LUT_DATA_G_SIGNED_EN {
+	DCP_DC_LUT_DATA_G_SIGNED_EN_FALSE                = 0x0,
+	DCP_DC_LUT_DATA_G_SIGNED_EN_TRUE                 = 0x1,
+} DCP_DC_LUT_DATA_G_SIGNED_EN;
+typedef enum DCP_DC_LUT_DATA_G_FLOAT_POINT_EN {
+	DCP_DC_LUT_DATA_G_FLOAT_POINT_EN_FALSE           = 0x0,
+	DCP_DC_LUT_DATA_G_FLOAT_POINT_EN_TRUE            = 0x1,
+} DCP_DC_LUT_DATA_G_FLOAT_POINT_EN;
+typedef enum DCP_DC_LUT_DATA_G_FORMAT {
+	DCP_DC_LUT_DATA_G_FORMAT_U0P10                   = 0x0,
+	DCP_DC_LUT_DATA_G_FORMAT_S1P10                   = 0x1,
+	DCP_DC_LUT_DATA_G_FORMAT_U1P11                   = 0x2,
+	DCP_DC_LUT_DATA_G_FORMAT_U0P12                   = 0x3,
+} DCP_DC_LUT_DATA_G_FORMAT;
+typedef enum DCP_DC_LUT_INC_R {
+	DCP_DC_LUT_INC_R_NA                              = 0x0,
+	DCP_DC_LUT_INC_R_2                               = 0x1,
+	DCP_DC_LUT_INC_R_4                               = 0x2,
+	DCP_DC_LUT_INC_R_8                               = 0x3,
+	DCP_DC_LUT_INC_R_16                              = 0x4,
+	DCP_DC_LUT_INC_R_32                              = 0x5,
+	DCP_DC_LUT_INC_R_64                              = 0x6,
+	DCP_DC_LUT_INC_R_128                             = 0x7,
+	DCP_DC_LUT_INC_R_256                             = 0x8,
+	DCP_DC_LUT_INC_R_512                             = 0x9,
+} DCP_DC_LUT_INC_R;
+typedef enum DCP_DC_LUT_DATA_R_SIGNED_EN {
+	DCP_DC_LUT_DATA_R_SIGNED_EN_FALSE                = 0x0,
+	DCP_DC_LUT_DATA_R_SIGNED_EN_TRUE                 = 0x1,
+} DCP_DC_LUT_DATA_R_SIGNED_EN;
+typedef enum DCP_DC_LUT_DATA_R_FLOAT_POINT_EN {
+	DCP_DC_LUT_DATA_R_FLOAT_POINT_EN_FALSE           = 0x0,
+	DCP_DC_LUT_DATA_R_FLOAT_POINT_EN_TRUE            = 0x1,
+} DCP_DC_LUT_DATA_R_FLOAT_POINT_EN;
+typedef enum DCP_DC_LUT_DATA_R_FORMAT {
+	DCP_DC_LUT_DATA_R_FORMAT_U0P10                   = 0x0,
+	DCP_DC_LUT_DATA_R_FORMAT_S1P10                   = 0x1,
+	DCP_DC_LUT_DATA_R_FORMAT_U1P11                   = 0x2,
+	DCP_DC_LUT_DATA_R_FORMAT_U0P12                   = 0x3,
+} DCP_DC_LUT_DATA_R_FORMAT;
+typedef enum DCP_CRC_ENABLE {
+	DCP_CRC_ENABLE_FALSE                             = 0x0,
+	DCP_CRC_ENABLE_TRUE                              = 0x1,
+} DCP_CRC_ENABLE;
+typedef enum DCP_CRC_SOURCE_SEL {
+	DCP_CRC_SOURCE_SEL_OUTPUT_PIX                    = 0x0,
+	DCP_CRC_SOURCE_SEL_INPUT_L32                     = 0x1,
+	DCP_CRC_SOURCE_SEL_INPUT_H32                     = 0x2,
+	DCP_CRC_SOURCE_SEL_OUTPUT_CNTL                   = 0x4,
+} DCP_CRC_SOURCE_SEL;
+typedef enum DCP_CRC_LINE_SEL {
+	DCP_CRC_LINE_SEL_RESERVED                        = 0x0,
+	DCP_CRC_LINE_SEL_EVEN                            = 0x1,
+	DCP_CRC_LINE_SEL_ODD                             = 0x2,
+	DCP_CRC_LINE_SEL_BOTH                            = 0x3,
+} DCP_CRC_LINE_SEL;
+typedef enum DCP_GRPH_FLIP_RATE {
+	DCP_GRPH_FLIP_RATE_1FRAME                        = 0x0,
+	DCP_GRPH_FLIP_RATE_2FRAME                        = 0x1,
+	DCP_GRPH_FLIP_RATE_3FRAME                        = 0x2,
+	DCP_GRPH_FLIP_RATE_4FRAME                        = 0x3,
+	DCP_GRPH_FLIP_RATE_5FRAME                        = 0x4,
+	DCP_GRPH_FLIP_RATE_6FRAME                        = 0x5,
+	DCP_GRPH_FLIP_RATE_7FRAME                        = 0x6,
+	DCP_GRPH_FLIP_RATE_8FRAME                        = 0x7,
+} DCP_GRPH_FLIP_RATE;
+typedef enum DCP_GRPH_FLIP_RATE_ENABLE {
+	DCP_GRPH_FLIP_RATE_ENABLE_FALSE                  = 0x0,
+	DCP_GRPH_FLIP_RATE_ENABLE_TRUE                   = 0x1,
+} DCP_GRPH_FLIP_RATE_ENABLE;
+typedef enum DCP_GSL0_EN {
+	DCP_GSL0_EN_FALSE                                = 0x0,
+	DCP_GSL0_EN_TRUE                                 = 0x1,
+} DCP_GSL0_EN;
+typedef enum DCP_GSL1_EN {
+	DCP_GSL1_EN_FALSE                                = 0x0,
+	DCP_GSL1_EN_TRUE                                 = 0x1,
+} DCP_GSL1_EN;
+typedef enum DCP_GSL2_EN {
+	DCP_GSL2_EN_FALSE                                = 0x0,
+	DCP_GSL2_EN_TRUE                                 = 0x1,
+} DCP_GSL2_EN;
+typedef enum DCP_GSL_MASTER_EN {
+	DCP_GSL_MASTER_EN_FALSE                          = 0x0,
+	DCP_GSL_MASTER_EN_TRUE                           = 0x1,
+} DCP_GSL_MASTER_EN;
+typedef enum DCP_GSL_XDMA_GROUP {
+	DCP_GSL_XDMA_GROUP_VSYNC                         = 0x0,
+	DCP_GSL_XDMA_GROUP_HSYNC0                        = 0x1,
+	DCP_GSL_XDMA_GROUP_HSYNC1                        = 0x2,
+	DCP_GSL_XDMA_GROUP_HSYNC2                        = 0x3,
+} DCP_GSL_XDMA_GROUP;
+typedef enum DCP_GSL_XDMA_GROUP_UNDERFLOW_EN {
+	DCP_GSL_XDMA_GROUP_UNDERFLOW_EN_FALSE            = 0x0,
+	DCP_GSL_XDMA_GROUP_UNDERFLOW_EN_TRUE             = 0x1,
+} DCP_GSL_XDMA_GROUP_UNDERFLOW_EN;
+typedef enum DCP_GSL_SYNC_SOURCE {
+	DCP_GSL_SYNC_SOURCE_FLIP                         = 0x0,
+	DCP_GSL_SYNC_SOURCE_PHASE0                       = 0x1,
+	DCP_GSL_SYNC_SOURCE_RESET                        = 0x2,
+	DCP_GSL_SYNC_SOURCE_PHASE1                       = 0x3,
+} DCP_GSL_SYNC_SOURCE;
+typedef enum DCP_GSL_DELAY_SURFACE_UPDATE_PENDING {
+	DCP_GSL_DELAY_SURFACE_UPDATE_PENDING_FALSE       = 0x0,
+	DCP_GSL_DELAY_SURFACE_UPDATE_PENDING_TRUE        = 0x1,
+} DCP_GSL_DELAY_SURFACE_UPDATE_PENDING;
+typedef enum DCP_TEST_DEBUG_WRITE_EN {
+	DCP_TEST_DEBUG_WRITE_EN_FALSE                    = 0x0,
+	DCP_TEST_DEBUG_WRITE_EN_TRUE                     = 0x1,
+} DCP_TEST_DEBUG_WRITE_EN;
+typedef enum DCP_GRPH_STEREOSYNC_FLIP_EN {
+	DCP_GRPH_STEREOSYNC_FLIP_EN_FALSE                = 0x0,
+	DCP_GRPH_STEREOSYNC_FLIP_EN_TRUE                 = 0x1,
+} DCP_GRPH_STEREOSYNC_FLIP_EN;
+typedef enum DCP_GRPH_STEREOSYNC_FLIP_MODE {
+	DCP_GRPH_STEREOSYNC_FLIP_MODE_FLIP               = 0x0,
+	DCP_GRPH_STEREOSYNC_FLIP_MODE_PHASE0             = 0x1,
+	DCP_GRPH_STEREOSYNC_FLIP_MODE_RESET              = 0x2,
+	DCP_GRPH_STEREOSYNC_FLIP_MODE_PHASE1             = 0x3,
+} DCP_GRPH_STEREOSYNC_FLIP_MODE;
+typedef enum DCP_GRPH_STEREOSYNC_SELECT_DISABLE {
+	DCP_GRPH_STEREOSYNC_SELECT_DISABLE_FALSE         = 0x0,
+	DCP_GRPH_STEREOSYNC_SELECT_DISABLE_TRUE          = 0x1,
+} DCP_GRPH_STEREOSYNC_SELECT_DISABLE;
+typedef enum DCP_GRPH_ROTATION_ANGLE {
+	DCP_GRPH_ROTATION_ANGLE_0                        = 0x0,
+	DCP_GRPH_ROTATION_ANGLE_90                       = 0x1,
+	DCP_GRPH_ROTATION_ANGLE_180                      = 0x2,
+	DCP_GRPH_ROTATION_ANGLE_270                      = 0x3,
+} DCP_GRPH_ROTATION_ANGLE;
+typedef enum DCP_GRPH_XDMA_CACHE_UNDERFLOW_CNT_EN {
+	DCP_GRPH_XDMA_CACHE_UNDERFLOW_CNT_EN_FALSE       = 0x0,
+	DCP_GRPH_XDMA_CACHE_UNDERFLOW_CNT_EN_TRUE        = 0x1,
+} DCP_GRPH_XDMA_CACHE_UNDERFLOW_CNT_EN;
+typedef enum DCP_GRPH_XDMA_CACHE_UNDERFLOW_CNT_MODE {
+	DCP_GRPH_XDMA_CACHE_UNDERFLOW_CNT_MODE_RELY_NUM  = 0x0,
+	DCP_GRPH_XDMA_CACHE_UNDERFLOW_CNT_MODE_RELY_ENABLE= 0x1,
+} DCP_GRPH_XDMA_CACHE_UNDERFLOW_CNT_MODE;
+typedef enum DCP_GRPH_REGAMMA_MODE {
+	DCP_GRPH_REGAMMA_MODE_BYPASS                     = 0x0,
+	DCP_GRPH_REGAMMA_MODE_SRGB                       = 0x1,
+	DCP_GRPH_REGAMMA_MODE_XVYCC                      = 0x2,
+	DCP_GRPH_REGAMMA_MODE_PROGA                      = 0x3,
+	DCP_GRPH_REGAMMA_MODE_PROGB                      = 0x4,
+} DCP_GRPH_REGAMMA_MODE;
+typedef enum DCP_ALPHA_ROUND_TRUNC_MODE {
+	DCP_ALPHA_ROUND_TRUNC_MODE_ROUND                 = 0x0,
+	DCP_ALPHA_ROUND_TRUNC_MODE_TRUNC                 = 0x1,
+} DCP_ALPHA_ROUND_TRUNC_MODE;
+typedef enum DCP_CURSOR_ALPHA_BLND_ENA {
+	DCP_CURSOR_ALPHA_BLND_ENA_FALSE                  = 0x0,
+	DCP_CURSOR_ALPHA_BLND_ENA_TRUE                   = 0x1,
+} DCP_CURSOR_ALPHA_BLND_ENA;
+typedef enum DCP_GRPH_XDMA_CACHE_UNDERFLOW_FRAME_MASK {
+	DCP_GRPH_XDMA_CACHE_UNDERFLOW_FRAME_MASK_FALSE   = 0x0,
+	DCP_GRPH_XDMA_CACHE_UNDERFLOW_FRAME_MASK_TRUE    = 0x1,
+} DCP_GRPH_XDMA_CACHE_UNDERFLOW_FRAME_MASK;
+typedef enum DCP_GRPH_XDMA_CACHE_UNDERFLOW_FRAME_ACK {
+	DCP_GRPH_XDMA_CACHE_UNDERFLOW_FRAME_ACK_FALSE    = 0x0,
+	DCP_GRPH_XDMA_CACHE_UNDERFLOW_FRAME_ACK_TRUE     = 0x1,
+} DCP_GRPH_XDMA_CACHE_UNDERFLOW_FRAME_ACK;
+typedef enum DCP_GRPH_XDMA_CACHE_UNDERFLOW_INT_MASK {
+	DCP_GRPH_XDMA_CACHE_UNDERFLOW_INT_MASK_FALSE     = 0x0,
+	DCP_GRPH_XDMA_CACHE_UNDERFLOW_INT_MASK_TRUE      = 0x1,
+} DCP_GRPH_XDMA_CACHE_UNDERFLOW_INT_MASK;
+typedef enum DCP_GRPH_XDMA_CACHE_UNDERFLOW_INT_ACK {
+	DCP_GRPH_XDMA_CACHE_UNDERFLOW_INT_ACK_FALSE      = 0x0,
+	DCP_GRPH_XDMA_CACHE_UNDERFLOW_INT_ACK_TRUE       = 0x1,
+} DCP_GRPH_XDMA_CACHE_UNDERFLOW_INT_ACK;
+typedef enum DCP_GRPH_SURFACE_COUNTER_EN {
+	DCP_GRPH_SURFACE_COUNTER_EN_DISABLE              = 0x0,
+	DCP_GRPH_SURFACE_COUNTER_EN_ENABLE               = 0x1,
+} DCP_GRPH_SURFACE_COUNTER_EN;
+typedef enum DCP_GRPH_SURFACE_COUNTER_EVENT_SELECT {
+	DCP_GRPH_SURFACE_COUNTER_EVENT_SELECT_0          = 0x0,
+	DCP_GRPH_SURFACE_COUNTER_EVENT_SELECT_1          = 0x1,
+	DCP_GRPH_SURFACE_COUNTER_EVENT_SELECT_2          = 0x2,
+	DCP_GRPH_SURFACE_COUNTER_EVENT_SELECT_3          = 0x3,
+	DCP_GRPH_SURFACE_COUNTER_EVENT_SELECT_4          = 0x4,
+	DCP_GRPH_SURFACE_COUNTER_EVENT_SELECT_5          = 0x5,
+	DCP_GRPH_SURFACE_COUNTER_EVENT_SELECT_6          = 0x6,
+	DCP_GRPH_SURFACE_COUNTER_EVENT_SELECT_7          = 0x7,
+	DCP_GRPH_SURFACE_COUNTER_EVENT_SELECT_8          = 0x8,
+	DCP_GRPH_SURFACE_COUNTER_EVENT_SELECT_9          = 0x9,
+	DCP_GRPH_SURFACE_COUNTER_EVENT_SELECT_10         = 0xa,
+	DCP_GRPH_SURFACE_COUNTER_EVENT_SELECT_11         = 0xb,
+} DCP_GRPH_SURFACE_COUNTER_EVENT_SELECT;
+typedef enum DCP_GRPH_SURFACE_COUNTER_ERR_WRAP_OCCURED {
+	DCP_GRPH_SURFACE_COUNTER_ERR_WRAP_OCCURED_NO     = 0x0,
+	DCP_GRPH_SURFACE_COUNTER_ERR_WRAP_OCCURED_YES    = 0x1,
+} DCP_GRPH_SURFACE_COUNTER_ERR_WRAP_OCCURED;
+typedef enum HDMI_KEEPOUT_MODE {
+	HDMI_KEEPOUT_0_650PIX_AFTER_VSYNC                = 0x0,
+	HDMI_KEEPOUT_509_650PIX_AFTER_VSYNC              = 0x1,
+} HDMI_KEEPOUT_MODE;
+typedef enum HDMI_CLOCK_CHANNEL_RATE {
+	HDMI_CLOCK_CHANNEL_FREQ_EQUAL_TO_CHAR_RATE       = 0x0,
+	HDMI_CLOCK_CHANNEL_FREQ_QUARTER_TO_CHAR_RATE     = 0x1,
+} HDMI_CLOCK_CHANNEL_RATE;
+typedef enum HDMI_NO_EXTRA_NULL_PACKET_FILLED {
+	HDMI_EXTRA_NULL_PACKET_FILLED_ENABLE             = 0x0,
+	HDMI_EXTRA_NULL_PACKET_FILLED_DISABLE            = 0x1,
+} HDMI_NO_EXTRA_NULL_PACKET_FILLED;
+typedef enum HDMI_PACKET_GEN_VERSION {
+	HDMI_PACKET_GEN_VERSION_OLD                      = 0x0,
+	HDMI_PACKET_GEN_VERSION_NEW                      = 0x1,
+} HDMI_PACKET_GEN_VERSION;
+typedef enum HDMI_ERROR_ACK {
+	HDMI_ERROR_ACK_INT                               = 0x0,
+	HDMI_ERROR_NOT_ACK                               = 0x1,
+} HDMI_ERROR_ACK;
+typedef enum HDMI_ERROR_MASK {
+	HDMI_ERROR_MASK_INT                              = 0x0,
+	HDMI_ERROR_NOT_MASK                              = 0x1,
+} HDMI_ERROR_MASK;
+typedef enum HDMI_DEEP_COLOR_DEPTH {
+	HDMI_DEEP_COLOR_DEPTH_24BPP                      = 0x0,
+	HDMI_DEEP_COLOR_DEPTH_30BPP                      = 0x1,
+	HDMI_DEEP_COLOR_DEPTH_36BPP                      = 0x2,
+	HDMI_DEEP_COLOR_DEPTH_RESERVED                   = 0x3,
+} HDMI_DEEP_COLOR_DEPTH;
+typedef enum HDMI_AUDIO_DELAY_EN {
+	HDMI_AUDIO_DELAY_DISABLE                         = 0x0,
+	HDMI_AUDIO_DELAY_58CLK                           = 0x1,
+	HDMI_AUDIO_DELAY_56CLK                           = 0x2,
+	HDMI_AUDIO_DELAY_RESERVED                        = 0x3,
+} HDMI_AUDIO_DELAY_EN;
+typedef enum HDMI_AUDIO_SEND_MAX_PACKETS {
+	HDMI_NOT_SEND_MAX_AUDIO_PACKETS                  = 0x0,
+	HDMI_SEND_MAX_AUDIO_PACKETS                      = 0x1,
+} HDMI_AUDIO_SEND_MAX_PACKETS;
+typedef enum HDMI_ACR_SEND {
+	HDMI_ACR_NOT_SEND                                = 0x0,
+	HDMI_ACR_PKT_SEND                                = 0x1,
+} HDMI_ACR_SEND;
+typedef enum HDMI_ACR_CONT {
+	HDMI_ACR_CONT_DISABLE                            = 0x0,
+	HDMI_ACR_CONT_ENABLE                             = 0x1,
+} HDMI_ACR_CONT;
+typedef enum HDMI_ACR_SELECT {
+	HDMI_ACR_SELECT_HW                               = 0x0,
+	HDMI_ACR_SELECT_32K                              = 0x1,
+	HDMI_ACR_SELECT_44K                              = 0x2,
+	HDMI_ACR_SELECT_48K                              = 0x3,
+} HDMI_ACR_SELECT;
+typedef enum HDMI_ACR_SOURCE {
+	HDMI_ACR_SOURCE_HW                               = 0x0,
+	HDMI_ACR_SOURCE_SW                               = 0x1,
+} HDMI_ACR_SOURCE;
+typedef enum HDMI_ACR_N_MULTIPLE {
+	HDMI_ACR_0_MULTIPLE_RESERVED                     = 0x0,
+	HDMI_ACR_1_MULTIPLE                              = 0x1,
+	HDMI_ACR_2_MULTIPLE                              = 0x2,
+	HDMI_ACR_3_MULTIPLE_RESERVED                     = 0x3,
+	HDMI_ACR_4_MULTIPLE                              = 0x4,
+	HDMI_ACR_5_MULTIPLE_RESERVED                     = 0x5,
+	HDMI_ACR_6_MULTIPLE_RESERVED                     = 0x6,
+	HDMI_ACR_7_MULTIPLE_RESERVED                     = 0x7,
+} HDMI_ACR_N_MULTIPLE;
+typedef enum HDMI_ACR_AUDIO_PRIORITY {
+	HDMI_ACR_PKT_HIGH_PRIORITY_THAN_AUDIO_SAMPLE     = 0x0,
+	HDMI_AUDIO_SAMPLE_HIGH_PRIORITY_THAN_ACR_PKT     = 0x1,
+} HDMI_ACR_AUDIO_PRIORITY;
+typedef enum HDMI_NULL_SEND {
+	HDMI_NULL_NOT_SEND                               = 0x0,
+	HDMI_NULL_PKT_SEND                               = 0x1,
+} HDMI_NULL_SEND;
+typedef enum HDMI_GC_SEND {
+	HDMI_GC_NOT_SEND                                 = 0x0,
+	HDMI_GC_PKT_SEND                                 = 0x1,
+} HDMI_GC_SEND;
+typedef enum HDMI_GC_CONT {
+	HDMI_GC_CONT_DISABLE                             = 0x0,
+	HDMI_GC_CONT_ENABLE                              = 0x1,
+} HDMI_GC_CONT;
+typedef enum HDMI_ISRC_SEND {
+	HDMI_ISRC_NOT_SEND                               = 0x0,
+	HDMI_ISRC_PKT_SEND                               = 0x1,
+} HDMI_ISRC_SEND;
+typedef enum HDMI_ISRC_CONT {
+	HDMI_ISRC_CONT_DISABLE                           = 0x0,
+	HDMI_ISRC_CONT_ENABLE                            = 0x1,
+} HDMI_ISRC_CONT;
+typedef enum HDMI_AVI_INFO_SEND {
+	HDMI_AVI_INFO_NOT_SEND                           = 0x0,
+	HDMI_AVI_INFO_PKT_SEND                           = 0x1,
+} HDMI_AVI_INFO_SEND;
+typedef enum HDMI_AVI_INFO_CONT {
+	HDMI_AVI_INFO_CONT_DISABLE                       = 0x0,
+	HDMI_AVI_INFO_CONT_ENABLE                        = 0x1,
+} HDMI_AVI_INFO_CONT;
+typedef enum HDMI_AUDIO_INFO_SEND {
+	HDMI_AUDIO_INFO_NOT_SEND                         = 0x0,
+	HDMI_AUDIO_INFO_PKT_SEND                         = 0x1,
+} HDMI_AUDIO_INFO_SEND;
+typedef enum HDMI_AUDIO_INFO_CONT {
+	HDMI_AUDIO_INFO_CONT_DISABLE                     = 0x0,
+	HDMI_AUDIO_INFO_CONT_ENABLE                      = 0x1,
+} HDMI_AUDIO_INFO_CONT;
+typedef enum HDMI_MPEG_INFO_SEND {
+	HDMI_MPEG_INFO_NOT_SEND                          = 0x0,
+	HDMI_MPEG_INFO_PKT_SEND                          = 0x1,
+} HDMI_MPEG_INFO_SEND;
+typedef enum HDMI_MPEG_INFO_CONT {
+	HDMI_MPEG_INFO_CONT_DISABLE                      = 0x0,
+	HDMI_MPEG_INFO_CONT_ENABLE                       = 0x1,
+} HDMI_MPEG_INFO_CONT;
+typedef enum HDMI_GENERIC0_SEND {
+	HDMI_GENERIC0_NOT_SEND                           = 0x0,
+	HDMI_GENERIC0_PKT_SEND                           = 0x1,
+} HDMI_GENERIC0_SEND;
+typedef enum HDMI_GENERIC0_CONT {
+	HDMI_GENERIC0_CONT_DISABLE                       = 0x0,
+	HDMI_GENERIC0_CONT_ENABLE                        = 0x1,
+} HDMI_GENERIC0_CONT;
+typedef enum HDMI_GENERIC1_SEND {
+	HDMI_GENERIC1_NOT_SEND                           = 0x0,
+	HDMI_GENERIC1_PKT_SEND                           = 0x1,
+} HDMI_GENERIC1_SEND;
+typedef enum HDMI_GENERIC1_CONT {
+	HDMI_GENERIC1_CONT_DISABLE                       = 0x0,
+	HDMI_GENERIC1_CONT_ENABLE                        = 0x1,
+} HDMI_GENERIC1_CONT;
+typedef enum HDMI_GC_AVMUTE_CONT {
+	HDMI_GC_AVMUTE_CONT_DISABLE                      = 0x0,
+	HDMI_GC_AVMUTE_CONT_ENABLE                       = 0x1,
+} HDMI_GC_AVMUTE_CONT;
+typedef enum HDMI_PACKING_PHASE_OVERRIDE {
+	HDMI_PACKING_PHASE_SET_BY_HW                     = 0x0,
+	HDMI_PACKING_PHASE_SET_BY_SW                     = 0x1,
+} HDMI_PACKING_PHASE_OVERRIDE;
+typedef enum HDMI_GENERIC2_SEND {
+	HDMI_GENERIC2_NOT_SEND                           = 0x0,
+	HDMI_GENERIC2_PKT_SEND                           = 0x1,
+} HDMI_GENERIC2_SEND;
+typedef enum HDMI_GENERIC2_CONT {
+	HDMI_GENERIC2_CONT_DISABLE                       = 0x0,
+	HDMI_GENERIC2_CONT_ENABLE                        = 0x1,
+} HDMI_GENERIC2_CONT;
+typedef enum HDMI_GENERIC3_SEND {
+	HDMI_GENERIC3_NOT_SEND                           = 0x0,
+	HDMI_GENERIC3_PKT_SEND                           = 0x1,
+} HDMI_GENERIC3_SEND;
+typedef enum HDMI_GENERIC3_CONT {
+	HDMI_GENERIC3_CONT_DISABLE                       = 0x0,
+	HDMI_GENERIC3_CONT_ENABLE                        = 0x1,
+} HDMI_GENERIC3_CONT;
+typedef enum TMDS_PIXEL_ENCODING {
+	TMDS_PIXEL_ENCODING_444_OR_420                   = 0x0,
+	TMDS_PIXEL_ENCODING_422                          = 0x1,
+} TMDS_PIXEL_ENCODING;
+typedef enum TMDS_COLOR_FORMAT {
+	TMDS_COLOR_FORMAT__24BPP__TWIN30BPP_MSB__DUAL48BPP= 0x0,
+	TMDS_COLOR_FORMAT_TWIN30BPP_LSB                  = 0x1,
+	TMDS_COLOR_FORMAT_DUAL30BPP                      = 0x2,
+	TMDS_COLOR_FORMAT_RESERVED                       = 0x3,
+} TMDS_COLOR_FORMAT;
+typedef enum TMDS_STEREOSYNC_CTL_SEL_REG {
+	TMDS_STEREOSYNC_CTL0                             = 0x0,
+	TMDS_STEREOSYNC_CTL1                             = 0x1,
+	TMDS_STEREOSYNC_CTL2                             = 0x2,
+	TMDS_STEREOSYNC_CTL3                             = 0x3,
+} TMDS_STEREOSYNC_CTL_SEL_REG;
+typedef enum TMDS_CTL0_DATA_SEL {
+	TMDS_CTL0_DATA_SEL0_RESERVED                     = 0x0,
+	TMDS_CTL0_DATA_SEL1_DISPLAY_ENABLE               = 0x1,
+	TMDS_CTL0_DATA_SEL2_VSYNC                        = 0x2,
+	TMDS_CTL0_DATA_SEL3_RESERVED                     = 0x3,
+	TMDS_CTL0_DATA_SEL4_HSYNC                        = 0x4,
+	TMDS_CTL0_DATA_SEL5_SEL7_RESERVED                = 0x5,
+	TMDS_CTL0_DATA_SEL8_RANDOM_DATA                  = 0x6,
+	TMDS_CTL0_DATA_SEL9_SEL15_RANDOM_DATA            = 0x7,
+} TMDS_CTL0_DATA_SEL;
+typedef enum TMDS_CTL0_DATA_INVERT {
+	TMDS_CTL0_DATA_NORMAL                            = 0x0,
+	TMDS_CTL0_DATA_INVERT_EN                         = 0x1,
+} TMDS_CTL0_DATA_INVERT;
+typedef enum TMDS_CTL0_DATA_MODULATION {
+	TMDS_CTL0_DATA_MODULATION_DISABLE                = 0x0,
+	TMDS_CTL0_DATA_MODULATION_BIT0                   = 0x1,
+	TMDS_CTL0_DATA_MODULATION_BIT1                   = 0x2,
+	TMDS_CTL0_DATA_MODULATION_BIT2                   = 0x3,
+} TMDS_CTL0_DATA_MODULATION;
+typedef enum TMDS_CTL0_PATTERN_OUT_EN {
+	TMDS_CTL0_PATTERN_OUT_DISABLE                    = 0x0,
+	TMDS_CTL0_PATTERN_OUT_ENABLE                     = 0x1,
+} TMDS_CTL0_PATTERN_OUT_EN;
+typedef enum TMDS_CTL1_DATA_SEL {
+	TMDS_CTL1_DATA_SEL0_RESERVED                     = 0x0,
+	TMDS_CTL1_DATA_SEL1_DISPLAY_ENABLE               = 0x1,
+	TMDS_CTL1_DATA_SEL2_VSYNC                        = 0x2,
+	TMDS_CTL1_DATA_SEL3_RESERVED                     = 0x3,
+	TMDS_CTL1_DATA_SEL4_HSYNC                        = 0x4,
+	TMDS_CTL1_DATA_SEL5_SEL7_RESERVED                = 0x5,
+	TMDS_CTL1_DATA_SEL8_BLANK_TIME                   = 0x6,
+	TMDS_CTL1_DATA_SEL9_SEL15_RESERVED               = 0x7,
+} TMDS_CTL1_DATA_SEL;
+typedef enum TMDS_CTL1_DATA_INVERT {
+	TMDS_CTL1_DATA_NORMAL                            = 0x0,
+	TMDS_CTL1_DATA_INVERT_EN                         = 0x1,
+} TMDS_CTL1_DATA_INVERT;
+typedef enum TMDS_CTL1_DATA_MODULATION {
+	TMDS_CTL1_DATA_MODULATION_DISABLE                = 0x0,
+	TMDS_CTL1_DATA_MODULATION_BIT0                   = 0x1,
+	TMDS_CTL1_DATA_MODULATION_BIT1                   = 0x2,
+	TMDS_CTL1_DATA_MODULATION_BIT2                   = 0x3,
+} TMDS_CTL1_DATA_MODULATION;
+typedef enum TMDS_CTL1_PATTERN_OUT_EN {
+	TMDS_CTL1_PATTERN_OUT_DISABLE                    = 0x0,
+	TMDS_CTL1_PATTERN_OUT_ENABLE                     = 0x1,
+} TMDS_CTL1_PATTERN_OUT_EN;
+typedef enum TMDS_CTL2_DATA_SEL {
+	TMDS_CTL2_DATA_SEL0_RESERVED                     = 0x0,
+	TMDS_CTL2_DATA_SEL1_DISPLAY_ENABLE               = 0x1,
+	TMDS_CTL2_DATA_SEL2_VSYNC                        = 0x2,
+	TMDS_CTL2_DATA_SEL3_RESERVED                     = 0x3,
+	TMDS_CTL2_DATA_SEL4_HSYNC                        = 0x4,
+	TMDS_CTL2_DATA_SEL5_SEL7_RESERVED                = 0x5,
+	TMDS_CTL2_DATA_SEL8_BLANK_TIME                   = 0x6,
+	TMDS_CTL2_DATA_SEL9_SEL15_RESERVED               = 0x7,
+} TMDS_CTL2_DATA_SEL;
+typedef enum TMDS_CTL2_DATA_INVERT {
+	TMDS_CTL2_DATA_NORMAL                            = 0x0,
+	TMDS_CTL2_DATA_INVERT_EN                         = 0x1,
+} TMDS_CTL2_DATA_INVERT;
+typedef enum TMDS_CTL2_DATA_MODULATION {
+	TMDS_CTL2_DATA_MODULATION_DISABLE                = 0x0,
+	TMDS_CTL2_DATA_MODULATION_BIT0                   = 0x1,
+	TMDS_CTL2_DATA_MODULATION_BIT1                   = 0x2,
+	TMDS_CTL2_DATA_MODULATION_BIT2                   = 0x3,
+} TMDS_CTL2_DATA_MODULATION;
+typedef enum TMDS_CTL2_PATTERN_OUT_EN {
+	TMDS_CTL2_PATTERN_OUT_DISABLE                    = 0x0,
+	TMDS_CTL2_PATTERN_OUT_ENABLE                     = 0x1,
+} TMDS_CTL2_PATTERN_OUT_EN;
+typedef enum TMDS_CTL3_DATA_INVERT {
+	TMDS_CTL3_DATA_NORMAL                            = 0x0,
+	TMDS_CTL3_DATA_INVERT_EN                         = 0x1,
+} TMDS_CTL3_DATA_INVERT;
+typedef enum TMDS_CTL3_DATA_MODULATION {
+	TMDS_CTL3_DATA_MODULATION_DISABLE                = 0x0,
+	TMDS_CTL3_DATA_MODULATION_BIT0                   = 0x1,
+	TMDS_CTL3_DATA_MODULATION_BIT1                   = 0x2,
+	TMDS_CTL3_DATA_MODULATION_BIT2                   = 0x3,
+} TMDS_CTL3_DATA_MODULATION;
+typedef enum TMDS_CTL3_PATTERN_OUT_EN {
+	TMDS_CTL3_PATTERN_OUT_DISABLE                    = 0x0,
+	TMDS_CTL3_PATTERN_OUT_ENABLE                     = 0x1,
+} TMDS_CTL3_PATTERN_OUT_EN;
+typedef enum TMDS_CTL3_DATA_SEL {
+	TMDS_CTL3_DATA_SEL0_RESERVED                     = 0x0,
+	TMDS_CTL3_DATA_SEL1_DISPLAY_ENABLE               = 0x1,
+	TMDS_CTL3_DATA_SEL2_VSYNC                        = 0x2,
+	TMDS_CTL3_DATA_SEL3_RESERVED                     = 0x3,
+	TMDS_CTL3_DATA_SEL4_HSYNC                        = 0x4,
+	TMDS_CTL3_DATA_SEL5_SEL7_RESERVED                = 0x5,
+	TMDS_CTL3_DATA_SEL8_BLANK_TIME                   = 0x6,
+	TMDS_CTL3_DATA_SEL9_SEL15_RESERVED               = 0x7,
+} TMDS_CTL3_DATA_SEL;
+typedef enum DIG_FE_CNTL_SOURCE_SELECT {
+	DIG_FE_SOURCE_FROM_FMT0                          = 0x0,
+	DIG_FE_SOURCE_FROM_FMT1                          = 0x1,
+	DIG_FE_SOURCE_FROM_FMT2                          = 0x2,
+	DIG_FE_SOURCE_FROM_FMT3                          = 0x3,
+	DIG_FE_SOURCE_FROM_FMT4                          = 0x4,
+	DIG_FE_SOURCE_FROM_FMT5                          = 0x5,
+} DIG_FE_CNTL_SOURCE_SELECT;
+typedef enum DIG_FE_CNTL_STEREOSYNC_SELECT {
+	DIG_FE_STEREOSYNC_FROM_FMT0                      = 0x0,
+	DIG_FE_STEREOSYNC_FROM_FMT1                      = 0x1,
+	DIG_FE_STEREOSYNC_FROM_FMT2                      = 0x2,
+	DIG_FE_STEREOSYNC_FROM_FMT3                      = 0x3,
+	DIG_FE_STEREOSYNC_FROM_FMT4                      = 0x4,
+	DIG_FE_STEREOSYNC_FROM_FMT5                      = 0x5,
+} DIG_FE_CNTL_STEREOSYNC_SELECT;
+typedef enum DIG_FIFO_READ_CLOCK_SRC {
+	DIG_FIFO_READ_CLOCK_SRC_FROM_DCCG                = 0x0,
+	DIG_FIFO_READ_CLOCK_SRC_FROM_DISPLAY_PIPE        = 0x1,
+} DIG_FIFO_READ_CLOCK_SRC;
+typedef enum DIG_OUTPUT_CRC_CNTL_LINK_SEL {
+	DIG_OUTPUT_CRC_ON_LINK0                          = 0x0,
+	DIG_OUTPUT_CRC_ON_LINK1                          = 0x1,
+} DIG_OUTPUT_CRC_CNTL_LINK_SEL;
+typedef enum DIG_OUTPUT_CRC_DATA_SEL {
+	DIG_OUTPUT_CRC_FOR_FULLFRAME                     = 0x0,
+	DIG_OUTPUT_CRC_FOR_ACTIVEONLY                    = 0x1,
+	DIG_OUTPUT_CRC_FOR_VBI                           = 0x2,
+	DIG_OUTPUT_CRC_FOR_AUDIO                         = 0x3,
+} DIG_OUTPUT_CRC_DATA_SEL;
+typedef enum DIG_TEST_PATTERN_TEST_PATTERN_OUT_EN {
+	DIG_IN_NORMAL_OPERATION                          = 0x0,
+	DIG_IN_DEBUG_MODE                                = 0x1,
+} DIG_TEST_PATTERN_TEST_PATTERN_OUT_EN;
+typedef enum DIG_TEST_PATTERN_HALF_CLOCK_PATTERN_SEL {
+	DIG_10BIT_TEST_PATTERN                           = 0x0,
+	DIG_ALTERNATING_TEST_PATTERN                     = 0x1,
+} DIG_TEST_PATTERN_HALF_CLOCK_PATTERN_SEL;
+typedef enum DIG_TEST_PATTERN_RANDOM_PATTERN_OUT_EN {
+	DIG_TEST_PATTERN_NORMAL                          = 0x0,
+	DIG_TEST_PATTERN_RANDOM                          = 0x1,
+} DIG_TEST_PATTERN_RANDOM_PATTERN_OUT_EN;
+typedef enum DIG_TEST_PATTERN_RANDOM_PATTERN_RESET {
+	DIG_RANDOM_PATTERN_ENABLED                       = 0x0,
+	DIG_RANDOM_PATTERN_RESETED                       = 0x1,
+} DIG_TEST_PATTERN_RANDOM_PATTERN_RESET;
+typedef enum DIG_TEST_PATTERN_EXTERNAL_RESET_EN {
+	DIG_TEST_PATTERN_EXTERNAL_RESET_ENABLE           = 0x0,
+	DIG_TEST_PATTERN_EXTERNAL_RESET_BY_EXT_SIG       = 0x1,
+} DIG_TEST_PATTERN_EXTERNAL_RESET_EN;
+typedef enum DIG_RANDOM_PATTERN_SEED_RAN_PAT {
+	DIG_RANDOM_PATTERN_SEED_RAN_PAT_ALL_PIXELS       = 0x0,
+	DIG_RANDOM_PATTERN_SEED_RAN_PAT_DE_HIGH          = 0x1,
+} DIG_RANDOM_PATTERN_SEED_RAN_PAT;
+typedef enum DIG_FIFO_STATUS_USE_OVERWRITE_LEVEL {
+	DIG_FIFO_USE_OVERWRITE_LEVEL                     = 0x0,
+	DIG_FIFO_USE_CAL_AVERAGE_LEVEL                   = 0x1,
+} DIG_FIFO_STATUS_USE_OVERWRITE_LEVEL;
+typedef enum DIG_FIFO_ERROR_ACK {
+	DIG_FIFO_ERROR_ACK_INT                           = 0x0,
+	DIG_FIFO_ERROR_NOT_ACK                           = 0x1,
+} DIG_FIFO_ERROR_ACK;
+typedef enum DIG_FIFO_STATUS_FORCE_RECAL_AVERAGE {
+	DIG_FIFO_NOT_FORCE_RECAL_AVERAGE                 = 0x0,
+	DIG_FIFO_FORCE_RECAL_AVERAGE_LEVEL               = 0x1,
+} DIG_FIFO_STATUS_FORCE_RECAL_AVERAGE;
+typedef enum DIG_FIFO_STATUS_FORCE_RECOMP_MINMAX {
+	DIG_FIFO_NOT_FORCE_RECOMP_MINMAX                 = 0x0,
+	DIG_FIFO_FORCE_RECOMP_MINMAX                     = 0x1,
+} DIG_FIFO_STATUS_FORCE_RECOMP_MINMAX;
+typedef enum DIG_DISPCLK_SWITCH_CNTL_SWITCH_POINT {
+	DIG_DISPCLK_SWITCH_AT_EARLY_VBLANK               = 0x0,
+	DIG_DISPCLK_SWITCH_AT_FIRST_HSYNC                = 0x1,
+} DIG_DISPCLK_SWITCH_CNTL_SWITCH_POINT;
+typedef enum DIG_DISPCLK_SWITCH_ALLOWED_INT_ACK {
+	DIG_DISPCLK_SWITCH_ALLOWED_ACK_INT               = 0x0,
+	DIG_DISPCLK_SWITCH_ALLOWED_INT_NOT_ACK           = 0x1,
+} DIG_DISPCLK_SWITCH_ALLOWED_INT_ACK;
+typedef enum DIG_DISPCLK_SWITCH_ALLOWED_INT_MASK {
+	DIG_DISPCLK_SWITCH_ALLOWED_MASK_INT              = 0x0,
+	DIG_DISPCLK_SWITCH_ALLOWED_INT_UNMASK            = 0x1,
+} DIG_DISPCLK_SWITCH_ALLOWED_INT_MASK;
+typedef enum AFMT_INTERRUPT_STATUS_CHG_MASK {
+	AFMT_INTERRUPT_DISABLE                           = 0x0,
+	AFMT_INTERRUPT_ENABLE                            = 0x1,
+} AFMT_INTERRUPT_STATUS_CHG_MASK;
+typedef enum HDMI_GC_AVMUTE {
+	HDMI_GC_AVMUTE_SET                               = 0x0,
+	HDMI_GC_AVMUTE_UNSET                             = 0x1,
+} HDMI_GC_AVMUTE;
+typedef enum HDMI_DEFAULT_PAHSE {
+	HDMI_DEFAULT_PHASE_IS_0                          = 0x0,
+	HDMI_DEFAULT_PHASE_IS_1                          = 0x1,
+} HDMI_DEFAULT_PAHSE;
+typedef enum AFMT_AUDIO_PACKET_CONTROL2_AUDIO_LAYOUT_OVRD {
+	AFMT_AUDIO_LAYOUT_DETERMINED_BY_AZ_AUDIO_CHANNEL_STATUS= 0x0,
+	AFMT_AUDIO_LAYOUT_OVRD_BY_REGISTER               = 0x1,
+} AFMT_AUDIO_PACKET_CONTROL2_AUDIO_LAYOUT_OVRD;
+typedef enum AUDIO_LAYOUT_SELECT {
+	AUDIO_LAYOUT_0                                   = 0x0,
+	AUDIO_LAYOUT_1                                   = 0x1,
+} AUDIO_LAYOUT_SELECT;
+typedef enum AFMT_AUDIO_CRC_CONTROL_CONT {
+	AFMT_AUDIO_CRC_ONESHOT                           = 0x0,
+	AFMT_AUDIO_CRC_AUTO_RESTART                      = 0x1,
+} AFMT_AUDIO_CRC_CONTROL_CONT;
+typedef enum AFMT_AUDIO_CRC_CONTROL_SOURCE {
+	AFMT_AUDIO_CRC_SOURCE_FROM_FIFO_INPUT            = 0x0,
+	AFMT_AUDIO_CRC_SOURCE_FROM_FIFO_OUTPUT           = 0x1,
+} AFMT_AUDIO_CRC_CONTROL_SOURCE;
+typedef enum AFMT_AUDIO_CRC_CONTROL_CH_SEL {
+	AFMT_AUDIO_CRC_CH0_SIG                           = 0x0,
+	AFMT_AUDIO_CRC_CH1_SIG                           = 0x1,
+	AFMT_AUDIO_CRC_CH2_SIG                           = 0x2,
+	AFMT_AUDIO_CRC_CH3_SIG                           = 0x3,
+	AFMT_AUDIO_CRC_CH4_SIG                           = 0x4,
+	AFMT_AUDIO_CRC_CH5_SIG                           = 0x5,
+	AFMT_AUDIO_CRC_CH6_SIG                           = 0x6,
+	AFMT_AUDIO_CRC_CH7_SIG                           = 0x7,
+	AFMT_AUDIO_CRC_RESERVED                          = 0x8,
+	AFMT_AUDIO_CRC_AUDIO_SAMPLE_COUNT                = 0x9,
+} AFMT_AUDIO_CRC_CONTROL_CH_SEL;
+typedef enum AFMT_RAMP_CONTROL0_SIGN {
+	AFMT_RAMP_SIGNED                                 = 0x0,
+	AFMT_RAMP_UNSIGNED                               = 0x1,
+} AFMT_RAMP_CONTROL0_SIGN;
+typedef enum AFMT_AUDIO_PACKET_CONTROL_AUDIO_SAMPLE_SEND {
+	AFMT_AUDIO_PACKET_SENT_DISABLED                  = 0x0,
+	AFMT_AUDIO_PACKET_SENT_ENABLED                   = 0x1,
+} AFMT_AUDIO_PACKET_CONTROL_AUDIO_SAMPLE_SEND;
+typedef enum AFMT_AUDIO_PACKET_CONTROL_RESET_FIFO_WHEN_AUDIO_DIS {
+	AFMT_NOT_RESET_AUDIO_FIFO_WHEN_AUDIO_DISABLED_RESERVED= 0x0,
+	AFMT_RESET_AUDIO_FIFO_WHEN_AUDIO_DISABLED        = 0x1,
+} AFMT_AUDIO_PACKET_CONTROL_RESET_FIFO_WHEN_AUDIO_DIS;
+typedef enum AFMT_INFOFRAME_CONTROL0_AUDIO_INFO_SOURCE {
+	AFMT_INFOFRAME_SOURCE_FROM_AZALIA_BLOCK          = 0x0,
+	AFMT_INFOFRAME_SOURCE_FROM_AFMT_REGISTERS        = 0x1,
+} AFMT_INFOFRAME_CONTROL0_AUDIO_INFO_SOURCE;
+typedef enum AFMT_AUDIO_SRC_CONTROL_SELECT {
+	AFMT_AUDIO_SRC_FROM_AZ_STREAM0                   = 0x0,
+	AFMT_AUDIO_SRC_FROM_AZ_STREAM1                   = 0x1,
+	AFMT_AUDIO_SRC_FROM_AZ_STREAM2                   = 0x2,
+	AFMT_AUDIO_SRC_FROM_AZ_STREAM3                   = 0x3,
+	AFMT_AUDIO_SRC_FROM_AZ_STREAM4                   = 0x4,
+	AFMT_AUDIO_SRC_FROM_AZ_STREAM5                   = 0x5,
+	AFMT_AUDIO_SRC_RESERVED                          = 0x6,
+} AFMT_AUDIO_SRC_CONTROL_SELECT;
+typedef enum DIG_BE_CNTL_MODE {
+	DIG_BE_DP_SST_MODE                               = 0x0,
+	DIG_BE_RESERVED1                                 = 0x1,
+	DIG_BE_TMDS_DVI_MODE                             = 0x2,
+	DIG_BE_TMDS_HDMI_MODE                            = 0x3,
+	DIG_BE_SDVO_RESERVED                             = 0x4,
+	DIG_BE_DP_MST_MODE                               = 0x5,
+	DIG_BE_RESERVED2                                 = 0x6,
+	DIG_BE_RESERVED3                                 = 0x7,
+} DIG_BE_CNTL_MODE;
+typedef enum DIG_BE_CNTL_HPD_SELECT {
+	DIG_BE_CNTL_HPD1                                 = 0x0,
+	DIG_BE_CNTL_HPD2                                 = 0x1,
+	DIG_BE_CNTL_HPD3                                 = 0x2,
+	DIG_BE_CNTL_HPD4                                 = 0x3,
+	DIG_BE_CNTL_HPD5                                 = 0x4,
+	DIG_BE_CNTL_HPD6                                 = 0x5,
+} DIG_BE_CNTL_HPD_SELECT;
+typedef enum LVTMA_RANDOM_PATTERN_SEED_RAN_PAT {
+	LVTMA_RANDOM_PATTERN_SEED_ALL_PIXELS             = 0x0,
+	LVTMA_RANDOM_PATTERN_SEED_ONLY_DE_HIGH           = 0x1,
+} LVTMA_RANDOM_PATTERN_SEED_RAN_PAT;
+typedef enum TMDS_SYNC_PHASE {
+	TMDS_NOT_SYNC_PHASE_ON_FRAME_START               = 0x0,
+	TMDS_SYNC_PHASE_ON_FRAME_START                   = 0x1,
+} TMDS_SYNC_PHASE;
+typedef enum TMDS_DATA_SYNCHRONIZATION_DSINTSEL {
+	TMDS_DATA_SYNCHRONIZATION_DSINTSEL_PCLK_TMDS     = 0x0,
+	TMDS_DATA_SYNCHRONIZATION_DSINTSEL_TMDS_PLL      = 0x1,
+} TMDS_DATA_SYNCHRONIZATION_DSINTSEL;
+typedef enum TMDS_TRANSMITTER_ENABLE_HPD_MASK {
+	TMDS_TRANSMITTER_HPD_MASK_NOT_OVERRIDE           = 0x0,
+	TMDS_TRANSMITTER_HPD_MASK_OVERRIDE               = 0x1,
+} TMDS_TRANSMITTER_ENABLE_HPD_MASK;
+typedef enum TMDS_TRANSMITTER_ENABLE_LNKCEN_HPD_MASK {
+	TMDS_TRANSMITTER_LNKCEN_HPD_MASK_NOT_OVERRIDE    = 0x0,
+	TMDS_TRANSMITTER_LNKCEN_HPD_MASK_OVERRIDE        = 0x1,
+} TMDS_TRANSMITTER_ENABLE_LNKCEN_HPD_MASK;
+typedef enum TMDS_TRANSMITTER_ENABLE_LNKDEN_HPD_MASK {
+	TMDS_TRANSMITTER_LNKDEN_HPD_MASK_NOT_OVERRIDE    = 0x0,
+	TMDS_TRANSMITTER_LNKDEN_HPD_MASK_OVERRIDE        = 0x1,
+} TMDS_TRANSMITTER_ENABLE_LNKDEN_HPD_MASK;
+typedef enum TMDS_TRANSMITTER_CONTROL_PLL_ENABLE_HPD_MASK {
+	TMDS_TRANSMITTER_HPD_NOT_OVERRIDE_PLL_ENABLE     = 0x0,
+	TMDS_TRANSMITTER_HPD_OVERRIDE_PLL_ENABLE_ON_DISCON= 0x1,
+	TMDS_TRANSMITTER_HPD_OVERRIDE_PLL_ENABLE_ON_CON  = 0x2,
+	TMDS_TRANSMITTER_HPD_OVERRIDE_PLL_ENABLE         = 0x3,
+} TMDS_TRANSMITTER_CONTROL_PLL_ENABLE_HPD_MASK;
+typedef enum TMDS_TRANSMITTER_CONTROL_IDSCKSELA {
+	TMDS_TRANSMITTER_IDSCKSELA_USE_IPIXCLK           = 0x0,
+	TMDS_TRANSMITTER_IDSCKSELA_USE_IDCLK             = 0x1,
+} TMDS_TRANSMITTER_CONTROL_IDSCKSELA;
+typedef enum TMDS_TRANSMITTER_CONTROL_IDSCKSELB {
+	TMDS_TRANSMITTER_IDSCKSELB_USE_IPIXCLK           = 0x0,
+	TMDS_TRANSMITTER_IDSCKSELB_USE_IDCLK             = 0x1,
+} TMDS_TRANSMITTER_CONTROL_IDSCKSELB;
+typedef enum TMDS_TRANSMITTER_CONTROL_PLL_PWRUP_SEQ_EN {
+	TMDS_TRANSMITTER_PLL_PWRUP_SEQ_DISABLE           = 0x0,
+	TMDS_TRANSMITTER_PLL_PWRUP_SEQ_ENABLE            = 0x1,
+} TMDS_TRANSMITTER_CONTROL_PLL_PWRUP_SEQ_EN;
+typedef enum TMDS_TRANSMITTER_CONTROL_PLL_RESET_HPD_MASK {
+	TMDS_TRANSMITTER_PLL_NOT_RST_ON_HPD              = 0x0,
+	TMDS_TRANSMITTER_PLL_RST_ON_HPD                  = 0x1,
+} TMDS_TRANSMITTER_CONTROL_PLL_RESET_HPD_MASK;
+typedef enum TMDS_TRANSMITTER_CONTROL_TMCLK_FROM_PADS {
+	TMDS_TRANSMITTER_TMCLK_FROM_TMDS_TMCLK           = 0x0,
+	TMDS_TRANSMITTER_TMCLK_FROM_PADS                 = 0x1,
+} TMDS_TRANSMITTER_CONTROL_TMCLK_FROM_PADS;
+typedef enum TMDS_TRANSMITTER_CONTROL_TDCLK_FROM_PADS {
+	TMDS_TRANSMITTER_TDCLK_FROM_TMDS_TDCLK           = 0x0,
+	TMDS_TRANSMITTER_TDCLK_FROM_PADS                 = 0x1,
+} TMDS_TRANSMITTER_CONTROL_TDCLK_FROM_PADS;
+typedef enum TMDS_TRANSMITTER_CONTROL_PLLSEL_OVERWRITE_EN {
+	TMDS_TRANSMITTER_PLLSEL_BY_HW                    = 0x0,
+	TMDS_TRANSMITTER_PLLSEL_OVERWRITE_BY_SW          = 0x1,
+} TMDS_TRANSMITTER_CONTROL_PLLSEL_OVERWRITE_EN;
+typedef enum TMDS_TRANSMITTER_CONTROL_BYPASS_PLLA {
+	TMDS_TRANSMITTER_BYPASS_PLLA_COHERENT            = 0x0,
+	TMDS_TRANSMITTER_BYPASS_PLLA_INCOHERENT          = 0x1,
+} TMDS_TRANSMITTER_CONTROL_BYPASS_PLLA;
+typedef enum TMDS_TRANSMITTER_CONTROL_BYPASS_PLLB {
+	TMDS_TRANSMITTER_BYPASS_PLLB_COHERENT            = 0x0,
+	TMDS_TRANSMITTER_BYPASS_PLLB_INCOHERENT          = 0x1,
+} TMDS_TRANSMITTER_CONTROL_BYPASS_PLLB;
+typedef enum TMDS_REG_TEST_OUTPUTA_CNTLA {
+	TMDS_REG_TEST_OUTPUTA_CNTLA_OTDATA0              = 0x0,
+	TMDS_REG_TEST_OUTPUTA_CNTLA_OTDATA1              = 0x1,
+	TMDS_REG_TEST_OUTPUTA_CNTLA_OTDATA2              = 0x2,
+	TMDS_REG_TEST_OUTPUTA_CNTLA_NA                   = 0x3,
+} TMDS_REG_TEST_OUTPUTA_CNTLA;
+typedef enum TMDS_REG_TEST_OUTPUTB_CNTLB {
+	TMDS_REG_TEST_OUTPUTB_CNTLB_OTDATB0              = 0x0,
+	TMDS_REG_TEST_OUTPUTB_CNTLB_OTDATB1              = 0x1,
+	TMDS_REG_TEST_OUTPUTB_CNTLB_OTDATB2              = 0x2,
+	TMDS_REG_TEST_OUTPUTB_CNTLB_NA                   = 0x3,
+} TMDS_REG_TEST_OUTPUTB_CNTLB;
+typedef enum DP_LINK_TRAINING_COMPLETE {
+	DP_LINK_TRAINING_NOT_COMPLETE                    = 0x0,
+	DP_LINK_TRAINING_ALREADY_COMPLETE                = 0x1,
+} DP_LINK_TRAINING_COMPLETE;
+typedef enum DP_EMBEDDED_PANEL_MODE {
+	DP_EXTERNAL_PANEL                                = 0x0,
+	DP_EMBEDDED_PANEL                                = 0x1,
+} DP_EMBEDDED_PANEL_MODE;
+typedef enum DP_PIXEL_ENCODING {
+	DP_PIXEL_ENCODING_RGB444                         = 0x0,
+	DP_PIXEL_ENCODING_YCBCR422                       = 0x1,
+	DP_PIXEL_ENCODING_YCBCR444                       = 0x2,
+	DP_PIXEL_ENCODING_RGB_WIDE_GAMUT                 = 0x3,
+	DP_PIXEL_ENCODING_Y_ONLY                         = 0x4,
+	DP_PIXEL_ENCODING_YCBCR420                       = 0x5,
+	DP_PIXEL_ENCODING_RESERVED                       = 0x6,
+} DP_PIXEL_ENCODING;
+typedef enum DP_DYN_RANGE {
+	DP_DYN_VESA_RANGE                                = 0x0,
+	DP_DYN_CEA_RANGE                                 = 0x1,
+} DP_DYN_RANGE;
+typedef enum DP_YCBCR_RANGE {
+	DP_YCBCR_RANGE_BT601_5                           = 0x0,
+	DP_YCBCR_RANGE_BT709_5                           = 0x1,
+} DP_YCBCR_RANGE;
+typedef enum DP_COMPONENT_DEPTH {
+	DP_COMPONENT_DEPTH_6BPC                          = 0x0,
+	DP_COMPONENT_DEPTH_8BPC                          = 0x1,
+	DP_COMPONENT_DEPTH_10BPC                         = 0x2,
+	DP_COMPONENT_DEPTH_12BPC                         = 0x3,
+	DP_COMPONENT_DEPTH_16BPC                         = 0x4,
+	DP_COMPONENT_DEPTH_RESERVED                      = 0x5,
+} DP_COMPONENT_DEPTH;
+typedef enum DP_MSA_MISC0_OVERRIDE_ENABLE {
+	MSA_MISC0_OVERRIDE_DISABLE                       = 0x0,
+	MSA_MISC0_OVERRIDE_ENABLE                        = 0x1,
+} DP_MSA_MISC0_OVERRIDE_ENABLE;
+typedef enum DP_MSA_MISC1_BIT7_OVERRIDE_ENABLE {
+	MSA_MISC1_BIT7_OVERRIDE_DISABLE                  = 0x0,
+	MSA_MISC1_BIT7_OVERRIDE_ENABLE                   = 0x1,
+} DP_MSA_MISC1_BIT7_OVERRIDE_ENABLE;
+typedef enum DP_UDI_LANES {
+	DP_UDI_1_LANE                                    = 0x0,
+	DP_UDI_2_LANES                                   = 0x1,
+	DP_UDI_LANES_RESERVED                            = 0x2,
+	DP_UDI_4_LANES                                   = 0x3,
+} DP_UDI_LANES;
+typedef enum DP_VID_STREAM_DIS_DEFER {
+	DP_VID_STREAM_DIS_NO_DEFER                       = 0x0,
+	DP_VID_STREAM_DIS_DEFER_TO_HBLANK                = 0x1,
+	DP_VID_STREAM_DIS_DEFER_TO_VBLANK                = 0x2,
+} DP_VID_STREAM_DIS_DEFER;
+typedef enum DP_STEER_OVERFLOW_ACK {
+	DP_STEER_OVERFLOW_ACK_NO_EFFECT                  = 0x0,
+	DP_STEER_OVERFLOW_ACK_CLR_INTERRUPT              = 0x1,
+} DP_STEER_OVERFLOW_ACK;
+typedef enum DP_STEER_OVERFLOW_MASK {
+	DP_STEER_OVERFLOW_MASKED                         = 0x0,
+	DP_STEER_OVERFLOW_UNMASK                         = 0x1,
+} DP_STEER_OVERFLOW_MASK;
+typedef enum DP_TU_OVERFLOW_ACK {
+	DP_TU_OVERFLOW_ACK_NO_EFFECT                     = 0x0,
+	DP_TU_OVERFLOW_ACK_CLR_INTERRUPT                 = 0x1,
+} DP_TU_OVERFLOW_ACK;
+typedef enum DP_VID_TIMING_MODE {
+	DP_VID_TIMING_MODE_ASYNC                         = 0x0,
+	DP_VID_TIMING_MODE_SYNC                          = 0x1,
+} DP_VID_TIMING_MODE;
+typedef enum DP_VID_M_N_DOUBLE_BUFFER_MODE {
+	DP_VID_M_N_DOUBLE_BUFFER_AFTER_VID_M_UPDATE      = 0x0,
+	DP_VID_M_N_DOUBLE_BUFFER_AT_FRAME_START          = 0x1,
+} DP_VID_M_N_DOUBLE_BUFFER_MODE;
+typedef enum DP_VID_M_N_GEN_EN {
+	DP_VID_M_N_PROGRAMMED_VIA_REG                    = 0x0,
+	DP_VID_M_N_CALC_AUTO                             = 0x1,
+} DP_VID_M_N_GEN_EN;
+typedef enum DP_VID_M_DOUBLE_VALUE_EN {
+	DP_VID_M_INPUT_PIXEL_RATE                        = 0x0,
+	DP_VID_M_DOUBLE_INPUT_PIXEL_RATE                 = 0x1,
+} DP_VID_M_DOUBLE_VALUE_EN;
+typedef enum DP_VID_ENHANCED_FRAME_MODE {
+	VID_NORMAL_FRAME_MODE                            = 0x0,
+	VID_ENHANCED_MODE                                = 0x1,
+} DP_VID_ENHANCED_FRAME_MODE;
+typedef enum DP_VID_MSA_TOP_FIELD_MODE {
+	DP_TOP_FIELD_ONLY                                = 0x0,
+	DP_TOP_PLUS_BOTTOM_FIELD                         = 0x1,
+} DP_VID_MSA_TOP_FIELD_MODE;
+typedef enum DP_VID_VBID_FIELD_POL {
+	DP_VID_VBID_FIELD_POL_NORMAL                     = 0x0,
+	DP_VID_VBID_FIELD_POL_INV                        = 0x1,
+} DP_VID_VBID_FIELD_POL;
+typedef enum DP_VID_STREAM_DISABLE_ACK {
+	ID_STREAM_DISABLE_NO_ACK                         = 0x0,
+	ID_STREAM_DISABLE_ACKED                          = 0x1,
+} DP_VID_STREAM_DISABLE_ACK;
+typedef enum DP_VID_STREAM_DISABLE_MASK {
+	VID_STREAM_DISABLE_MASKED                        = 0x0,
+	VID_STREAM_DISABLE_UNMASK                        = 0x1,
+} DP_VID_STREAM_DISABLE_MASK;
+typedef enum DPHY_ATEST_SEL_LANE0 {
+	DPHY_ATEST_LANE0_PRBS_PATTERN                    = 0x0,
+	DPHY_ATEST_LANE0_REG_PATTERN                     = 0x1,
+} DPHY_ATEST_SEL_LANE0;
+typedef enum DPHY_ATEST_SEL_LANE1 {
+	DPHY_ATEST_LANE1_PRBS_PATTERN                    = 0x0,
+	DPHY_ATEST_LANE1_REG_PATTERN                     = 0x1,
+} DPHY_ATEST_SEL_LANE1;
+typedef enum DPHY_ATEST_SEL_LANE2 {
+	DPHY_ATEST_LANE2_PRBS_PATTERN                    = 0x0,
+	DPHY_ATEST_LANE2_REG_PATTERN                     = 0x1,
+} DPHY_ATEST_SEL_LANE2;
+typedef enum DPHY_ATEST_SEL_LANE3 {
+	DPHY_ATEST_LANE3_PRBS_PATTERN                    = 0x0,
+	DPHY_ATEST_LANE3_REG_PATTERN                     = 0x1,
+} DPHY_ATEST_SEL_LANE3;
+typedef enum DPHY_BYPASS {
+	DPHY_8B10B_OUTPUT                                = 0x0,
+	DPHY_DBG_OUTPUT                                  = 0x1,
+} DPHY_BYPASS;
+typedef enum DPHY_SKEW_BYPASS {
+	DPHY_WITH_SKEW                                   = 0x0,
+	DPHY_NO_SKEW                                     = 0x1,
+} DPHY_SKEW_BYPASS;
+typedef enum DPHY_TRAINING_PATTERN_SEL {
+	DPHY_TRAINING_PATTERN_1                          = 0x0,
+	DPHY_TRAINING_PATTERN_2                          = 0x1,
+	DPHY_TRAINING_PATTERN_3                          = 0x2,
+	DPHY_TRAINING_PATTERN_4                          = 0x3,
+} DPHY_TRAINING_PATTERN_SEL;
+typedef enum DPHY_8B10B_RESET {
+	DPHY_8B10B_NOT_RESET                             = 0x0,
+	DPHY_8B10B_RESETET                               = 0x1,
+} DPHY_8B10B_RESET;
+typedef enum DP_DPHY_8B10B_EXT_DISP {
+	DP_DPHY_8B10B_EXT_DISP_ZERO                      = 0x0,
+	DP_DPHY_8B10B_EXT_DISP_ONE                       = 0x1,
+} DP_DPHY_8B10B_EXT_DISP;
+typedef enum DPHY_8B10B_CUR_DISP {
+	DPHY_8B10B_CUR_DISP_ZERO                         = 0x0,
+	DPHY_8B10B_CUR_DISP_ONE                          = 0x1,
+} DPHY_8B10B_CUR_DISP;
+typedef enum DPHY_PRBS_EN {
+	DPHY_PRBS_DISABLE                                = 0x0,
+	DPHY_PRBS_ENABLE                                 = 0x1,
+} DPHY_PRBS_EN;
+typedef enum DPHY_PRBS_SEL {
+	DPHY_PRBS7_SELECTED                              = 0x0,
+	DPHY_PRBS23_SELECTED                             = 0x1,
+	DPHY_PRBS11_SELECTED                             = 0x2,
+} DPHY_PRBS_SEL;
+typedef enum DPHY_LOAD_BS_COUNT_START {
+	DPHY_LOAD_BS_COUNT_STARTED                       = 0x0,
+	DPHY_LOAD_BS_COUNT_NOT_STARTED                   = 0x1,
+} DPHY_LOAD_BS_COUNT_START;
+typedef enum DPHY_CRC_EN {
+	DPHY_CRC_DISABLED                                = 0x0,
+	DPHY_CRC_ENABLED                                 = 0x1,
+} DPHY_CRC_EN;
+typedef enum DPHY_CRC_CONT_EN {
+	DPHY_CRC_ONE_SHOT                                = 0x0,
+	DPHY_CRC_CONTINUOUS                              = 0x1,
+} DPHY_CRC_CONT_EN;
+typedef enum DPHY_CRC_FIELD {
+	DPHY_CRC_START_FROM_TOP_FIELD                    = 0x0,
+	DPHY_CRC_START_FROM_BOTTOM_FIELD                 = 0x1,
+} DPHY_CRC_FIELD;
+typedef enum DPHY_CRC_SEL {
+	DPHY_CRC_LANE0_SELECTED                          = 0x0,
+	DPHY_CRC_LANE1_SELECTED                          = 0x1,
+	DPHY_CRC_LANE2_SELECTED                          = 0x2,
+	DPHY_CRC_LANE3_SELECTED                          = 0x3,
+} DPHY_CRC_SEL;
+typedef enum DPHY_RX_FAST_TRAINING_CAPABLE {
+	DPHY_FAST_TRAINING_NOT_CAPABLE_0                 = 0x0,
+	DPHY_FAST_TRAINING_CAPABLE                       = 0x1,
+} DPHY_RX_FAST_TRAINING_CAPABLE;
+typedef enum DP_SEC_COLLISION_ACK {
+	DP_SEC_COLLISION_ACK_NO_EFFECT                   = 0x0,
+	DP_SEC_COLLISION_ACK_CLR_FLAG                    = 0x1,
+} DP_SEC_COLLISION_ACK;
+typedef enum DP_SEC_AUDIO_MUTE {
+	DP_SEC_AUDIO_MUTE_HW_CTRL                        = 0x0,
+	DP_SEC_AUDIO_MUTE_SW_CTRL                        = 0x1,
+} DP_SEC_AUDIO_MUTE;
+typedef enum DP_SEC_TIMESTAMP_MODE {
+	DP_SEC_TIMESTAMP_PROGRAMMABLE_MODE               = 0x0,
+	DP_SEC_TIMESTAMP_AUTO_CALC_MODE                  = 0x1,
+} DP_SEC_TIMESTAMP_MODE;
+typedef enum DP_SEC_ASP_PRIORITY {
+	DP_SEC_ASP_LOW_PRIORITY                          = 0x0,
+	DP_SEC_ASP_HIGH_PRIORITY                         = 0x1,
+} DP_SEC_ASP_PRIORITY;
+typedef enum DP_SEC_ASP_CHANNEL_COUNT_OVERRIDE {
+	DP_SEC_ASP_CHANNEL_COUNT_FROM_AZ                 = 0x0,
+	DP_SEC_ASP_CHANNEL_COUNT_OVERRIDE_ENABLED        = 0x1,
+} DP_SEC_ASP_CHANNEL_COUNT_OVERRIDE;
+typedef enum DP_MSE_SAT_UPDATE_ACT {
+	DP_MSE_SAT_UPDATE_NO_ACTION                      = 0x0,
+	DP_MSE_SAT_UPDATE_WITH_TRIGGER                   = 0x1,
+	DP_MSE_SAT_UPDATE_WITHOUT_TRIGGER                = 0x2,
+} DP_MSE_SAT_UPDATE_ACT;
+typedef enum DP_MSE_LINK_LINE {
+	DP_MSE_LINK_LINE_32_MTP_LONG                     = 0x0,
+	DP_MSE_LINK_LINE_64_MTP_LONG                     = 0x1,
+	DP_MSE_LINK_LINE_128_MTP_LONG                    = 0x2,
+	DP_MSE_LINK_LINE_256_MTP_LONG                    = 0x3,
+} DP_MSE_LINK_LINE;
+typedef enum DP_MSE_BLANK_CODE {
+	DP_MSE_BLANK_CODE_SF_FILLED                      = 0x0,
+	DP_MSE_BLANK_CODE_ZERO_FILLED                    = 0x1,
+} DP_MSE_BLANK_CODE;
+typedef enum DP_MSE_TIMESTAMP_MODE {
+	DP_MSE_TIMESTAMP_CALC_BASED_ON_LINK_RATE         = 0x0,
+	DP_MSE_TIMESTAMP_CALC_BASED_ON_VC_RATE           = 0x1,
+} DP_MSE_TIMESTAMP_MODE;
+typedef enum DP_MSE_ZERO_ENCODER {
+	DP_MSE_NOT_ZERO_FE_ENCODER                       = 0x0,
+	DP_MSE_ZERO_FE_ENCODER                           = 0x1,
+} DP_MSE_ZERO_ENCODER;
+typedef enum DP_MSE_OUTPUT_DPDBG_DATA {
+	DP_MSE_OUTPUT_DPDBG_DATA_DIS                     = 0x0,
+	DP_MSE_OUTPUT_DPDBG_DATA_EN                      = 0x1,
+} DP_MSE_OUTPUT_DPDBG_DATA;
+typedef enum DP_DPHY_HBR2_PATTERN_CONTROL_MODE {
+	DP_DPHY_HBR2_PASS_THROUGH                        = 0x0,
+	DP_DPHY_HBR2_PATTERN_1                           = 0x1,
+	DP_DPHY_HBR2_PATTERN_2_NEG                       = 0x2,
+	DP_DPHY_HBR2_PATTERN_3                           = 0x3,
+	DP_DPHY_HBR2_PATTERN_2_POS                       = 0x6,
+} DP_DPHY_HBR2_PATTERN_CONTROL_MODE;
+typedef enum DPHY_CRC_MST_PHASE_ERROR_ACK {
+	DPHY_CRC_MST_PHASE_ERROR_NO_ACK                  = 0x0,
+	DPHY_CRC_MST_PHASE_ERROR_ACKED                   = 0x1,
+} DPHY_CRC_MST_PHASE_ERROR_ACK;
+typedef enum DPHY_SW_FAST_TRAINING_START {
+	DPHY_SW_FAST_TRAINING_NOT_STARTED                = 0x0,
+	DPHY_SW_FAST_TRAINING_STARTED                    = 0x1,
+} DPHY_SW_FAST_TRAINING_START;
+typedef enum DP_DPHY_FAST_TRAINING_VBLANK_EDGE_DETECT_EN {
+	DP_DPHY_FAST_TRAINING_VBLANK_EDGE_DETECT_DISABLED= 0x0,
+	DP_DPHY_FAST_TRAINING_VBLANK_EDGE_DETECT_ENABLED = 0x1,
+} DP_DPHY_FAST_TRAINING_VBLANK_EDGE_DETECT_EN;
+typedef enum DP_DPHY_FAST_TRAINING_COMPLETE_MASK {
+	DP_DPHY_FAST_TRAINING_COMPLETE_MASKED            = 0x0,
+	DP_DPHY_FAST_TRAINING_COMPLETE_NOT_MASKED        = 0x1,
+} DP_DPHY_FAST_TRAINING_COMPLETE_MASK;
+typedef enum DP_DPHY_FAST_TRAINING_COMPLETE_ACK {
+	DP_DPHY_FAST_TRAINING_COMPLETE_NOT_ACKED         = 0x0,
+	DP_DPHY_FAST_TRAINING_COMPLETE_ACKED             = 0x1,
+} DP_DPHY_FAST_TRAINING_COMPLETE_ACK;
+typedef enum DP_MSA_V_TIMING_OVERRIDE_EN {
+	MSA_V_TIMING_OVERRIDE_DISABLED                   = 0x0,
+	MSA_V_TIMING_OVERRIDE_ENABLED                    = 0x1,
+} DP_MSA_V_TIMING_OVERRIDE_EN;
+typedef enum DP_SEC_GSP0_PRIORITY {
+	SEC_GSP0_PRIORITY_LOW                            = 0x0,
+	SEC_GSP0_PRIORITY_HIGH                           = 0x1,
+} DP_SEC_GSP0_PRIORITY;
+typedef enum DP_SEC_GSP0_SEND {
+	NOT_SENT                                         = 0x0,
+	FORCE_SENT                                       = 0x1,
+} DP_SEC_GSP0_SEND;
+typedef enum DP_AUX_CONTROL_HPD_SEL {
+	DP_AUX_CONTROL_HPD1_SELECTED                     = 0x0,
+	DP_AUX_CONTROL_HPD2_SELECTED                     = 0x1,
+	DP_AUX_CONTROL_HPD3_SELECTED                     = 0x2,
+	DP_AUX_CONTROL_HPD4_SELECTED                     = 0x3,
+	DP_AUX_CONTROL_HPD5_SELECTED                     = 0x4,
+	DP_AUX_CONTROL_HPD6_SELECTED                     = 0x5,
+} DP_AUX_CONTROL_HPD_SEL;
+typedef enum DP_AUX_CONTROL_TEST_MODE {
+	DP_AUX_CONTROL_TEST_MODE_DISABLE                 = 0x0,
+	DP_AUX_CONTROL_TEST_MODE_ENABLE                  = 0x1,
+} DP_AUX_CONTROL_TEST_MODE;
+typedef enum DP_AUX_SW_CONTROL_SW_GO {
+	DP_AUX_SW_CONTROL_SW__NOT_GO                     = 0x0,
+	DP_AUX_SW_CONTROL_SW__GO                         = 0x1,
+} DP_AUX_SW_CONTROL_SW_GO;
+typedef enum DP_AUX_SW_CONTROL_LS_READ_TRIG {
+	DP_AUX_SW_CONTROL_LS_READ__NOT_TRIG              = 0x0,
+	DP_AUX_SW_CONTROL_LS_READ__TRIG                  = 0x1,
+} DP_AUX_SW_CONTROL_LS_READ_TRIG;
+typedef enum DP_AUX_ARB_CONTROL_ARB_PRIORITY {
+	DP_AUX_ARB_CONTROL_ARB_PRIORITY__GTC_LS_SW       = 0x0,
+	DP_AUX_ARB_CONTROL_ARB_PRIORITY__LS_GTC_SW       = 0x1,
+	DP_AUX_ARB_CONTROL_ARB_PRIORITY__SW_LS_GTC       = 0x2,
+	DP_AUX_ARB_CONTROL_ARB_PRIORITY__SW_GTC_LS       = 0x3,
+} DP_AUX_ARB_CONTROL_ARB_PRIORITY;
+typedef enum DP_AUX_ARB_CONTROL_USE_AUX_REG_REQ {
+	DP_AUX_ARB_CONTROL__NOT_USE_AUX_REG_REQ          = 0x0,
+	DP_AUX_ARB_CONTROL__USE_AUX_REG_REQ              = 0x1,
+} DP_AUX_ARB_CONTROL_USE_AUX_REG_REQ;
+typedef enum DP_AUX_ARB_CONTROL_DONE_USING_AUX_REG {
+	DP_AUX_ARB_CONTROL__DONE_NOT_USING_AUX_REG       = 0x0,
+	DP_AUX_ARB_CONTROL__DONE_USING_AUX_REG           = 0x1,
+} DP_AUX_ARB_CONTROL_DONE_USING_AUX_REG;
+typedef enum DP_AUX_INT_ACK {
+	DP_AUX_INT__NOT_ACK                              = 0x0,
+	DP_AUX_INT__ACK                                  = 0x1,
+} DP_AUX_INT_ACK;
+typedef enum DP_AUX_LS_UPDATE_ACK {
+	DP_AUX_INT_LS_UPDATE_NOT_ACK                     = 0x0,
+	DP_AUX_INT_LS_UPDATE_ACK                         = 0x1,
+} DP_AUX_LS_UPDATE_ACK;
+typedef enum DP_AUX_DPHY_TX_REF_CONTROL_TX_REF_SEL {
+	DP_AUX_DPHY_TX_REF_CONTROL_TX_REF_SEL__DIVIDED_SYM_CLK= 0x0,
+	DP_AUX_DPHY_TX_REF_CONTROL_TX_REF_SEL__FROM_DCCG_MICROSECOND_REF= 0x1,
+} DP_AUX_DPHY_TX_REF_CONTROL_TX_REF_SEL;
+typedef enum DP_AUX_DPHY_TX_REF_CONTROL_TX_RATE {
+	DP_AUX_DPHY_TX_REF_CONTROL_TX_RATE__1MHZ         = 0x0,
+	DP_AUX_DPHY_TX_REF_CONTROL_TX_RATE__2MHZ         = 0x1,
+	DP_AUX_DPHY_TX_REF_CONTROL_TX_RATE__4MHZ         = 0x2,
+	DP_AUX_DPHY_TX_REF_CONTROL_TX_RATE__8MHZ         = 0x3,
+} DP_AUX_DPHY_TX_REF_CONTROL_TX_RATE;
+typedef enum DP_AUX_DPHY_TX_CONTROL_PRECHARGE_LEN {
+	DP_AUX_DPHY_TX_CONTROL_PRECHARGE_LEN__0US        = 0x0,
+	DP_AUX_DPHY_TX_CONTROL_PRECHARGE_LEN__8US        = 0x1,
+	DP_AUX_DPHY_TX_CONTROL_PRECHARGE_LEN__16US       = 0x2,
+	DP_AUX_DPHY_TX_CONTROL_PRECHARGE_LEN__24US       = 0x3,
+	DP_AUX_DPHY_TX_CONTROL_PRECHARGE_LEN__32US       = 0x4,
+	DP_AUX_DPHY_TX_CONTROL_PRECHARGE_LEN__40US       = 0x5,
+	DP_AUX_DPHY_TX_CONTROL_PRECHARGE_LEN__48US       = 0x6,
+	DP_AUX_DPHY_TX_CONTROL_PRECHARGE_LEN__56US       = 0x7,
+} DP_AUX_DPHY_TX_CONTROL_PRECHARGE_LEN;
+typedef enum DP_AUX_DPHY_TX_CONTROL_MODE_DET_CHECK_DELAY {
+	DP_AUX_DPHY_TX_CONTROL_MODE_DET_CHECK_DELAY__0   = 0x0,
+	DP_AUX_DPHY_TX_CONTROL_MODE_DET_CHECK_DELAY__16US= 0x1,
+	DP_AUX_DPHY_TX_CONTROL_MODE_DET_CHECK_DELAY__32US= 0x2,
+	DP_AUX_DPHY_TX_CONTROL_MODE_DET_CHECK_DELAY__64US= 0x3,
+	DP_AUX_DPHY_TX_CONTROL_MODE_DET_CHECK_DELAY__128US= 0x4,
+	DP_AUX_DPHY_TX_CONTROL_MODE_DET_CHECK_DELAY__256US= 0x5,
+} DP_AUX_DPHY_TX_CONTROL_MODE_DET_CHECK_DELAY;
+typedef enum DP_AUX_DPHY_RX_CONTROL_START_WINDOW {
+	DP_AUX_DPHY_RX_CONTROL_START_WINDOW__1TO2_PERIOD = 0x0,
+	DP_AUX_DPHY_RX_CONTROL_START_WINDOW__1TO4_PERIOD = 0x1,
+	DP_AUX_DPHY_RX_CONTROL_START_WINDOW__1TO8_PERIOD = 0x2,
+	DP_AUX_DPHY_RX_CONTROL_START_WINDOW__1TO16_PERIOD= 0x3,
+	DP_AUX_DPHY_RX_CONTROL_START_WINDOW__1TO32_PERIOD= 0x4,
+	DP_AUX_DPHY_RX_CONTROL_START_WINDOW__1TO64_PERIOD= 0x5,
+	DP_AUX_DPHY_RX_CONTROL_START_WINDOW__1TO128_PERIOD= 0x6,
+	DP_AUX_DPHY_RX_CONTROL_START_WINDOW__1TO256_PERIOD= 0x7,
+} DP_AUX_DPHY_RX_CONTROL_START_WINDOW;
+typedef enum DP_AUX_DPHY_RX_CONTROL_RECEIVE_WINDOW {
+	DP_AUX_DPHY_RX_CONTROL_RECEIVE_WINDOW__1TO2_PERIOD= 0x0,
+	DP_AUX_DPHY_RX_CONTROL_RECEIVE_WINDOW__1TO4_PERIOD= 0x1,
+	DP_AUX_DPHY_RX_CONTROL_RECEIVE_WINDOW__1TO8_PERIOD= 0x2,
+	DP_AUX_DPHY_RX_CONTROL_RECEIVE_WINDOW__1TO16_PERIOD= 0x3,
+	DP_AUX_DPHY_RX_CONTROL_RECEIVE_WINDOW__1TO32_PERIOD= 0x4,
+	DP_AUX_DPHY_RX_CONTROL_RECEIVE_WINDOW__1TO64_PERIOD= 0x5,
+	DP_AUX_DPHY_RX_CONTROL_RECEIVE_WINDOW__1TO128_PERIOD= 0x6,
+	DP_AUX_DPHY_RX_CONTROL_RECEIVE_WINDOW__1TO256_PERIOD= 0x7,
+} DP_AUX_DPHY_RX_CONTROL_RECEIVE_WINDOW;
+typedef enum DP_AUX_DPHY_RX_CONTROL_HALF_SYM_DETECT_LEN {
+	DP_AUX_DPHY_RX_CONTROL_HALF_SYM_DETECT_LEN__6_EDGES= 0x0,
+	DP_AUX_DPHY_RX_CONTROL_HALF_SYM_DETECT_LEN__10_EDGES= 0x1,
+	DP_AUX_DPHY_RX_CONTROL_HALF_SYM_DETECT_LEN__18_EDGES= 0x2,
+	DP_AUX_DPHY_RX_CONTROL_HALF_SYM_DETECT_LEN__RESERVED= 0x3,
+} DP_AUX_DPHY_RX_CONTROL_HALF_SYM_DETECT_LEN;
+typedef enum DP_AUX_DPHY_RX_CONTROL_ALLOW_BELOW_THRESHOLD_PHASE_DETECT {
+	DP_AUX_DPHY_RX_CONTROL__NOT_ALLOW_BELOW_THRESHOLD_PHASE_DETECT= 0x0,
+	DP_AUX_DPHY_RX_CONTROL__ALLOW_BELOW_THRESHOLD_PHASE_DETECT= 0x1,
+} DP_AUX_DPHY_RX_CONTROL_ALLOW_BELOW_THRESHOLD_PHASE_DETECT;
+typedef enum DP_AUX_DPHY_RX_CONTROL_ALLOW_BELOW_THRESHOLD_START {
+	DP_AUX_DPHY_RX_CONTROL__NOT_ALLOW_BELOW_THRESHOLD_START= 0x0,
+	DP_AUX_DPHY_RX_CONTROL__ALLOW_BELOW_THRESHOLD_START= 0x1,
+} DP_AUX_DPHY_RX_CONTROL_ALLOW_BELOW_THRESHOLD_START;
+typedef enum DP_AUX_DPHY_RX_CONTROL_ALLOW_BELOW_THRESHOLD_STOP {
+	DP_AUX_DPHY_RX_CONTROL__NOT_ALLOW_BELOW_THRESHOLD_STOP= 0x0,
+	DP_AUX_DPHY_RX_CONTROL__ALLOW_BELOW_THRESHOLD_STOP= 0x1,
+} DP_AUX_DPHY_RX_CONTROL_ALLOW_BELOW_THRESHOLD_STOP;
+typedef enum DP_AUX_DPHY_RX_CONTROL_PHASE_DETECT_LEN {
+	DP_AUX_DPHY_RX_CONTROL_PHASE_DETECT_LEN__2_HALF_SYMBOLS= 0x0,
+	DP_AUX_DPHY_RX_CONTROL_PHASE_DETECT_LEN__4_HALF_SYMBOLS= 0x1,
+	DP_AUX_DPHY_RX_CONTROL_PHASE_DETECT_LEN__6_HALF_SYMBOLS= 0x2,
+	DP_AUX_DPHY_RX_CONTROL_PHASE_DETECT_LEN__8_HALF_SYMBOLS= 0x3,
+} DP_AUX_DPHY_RX_CONTROL_PHASE_DETECT_LEN;
+typedef enum DP_AUX_DPHY_RX_CONTROL_TIMEOUT_LEN {
+	DP_AUX_DPHY_RX_CONTROL_TIMEOUT_LEN_450US         = 0x0,
+	DP_AUX_DPHY_RX_CONTROL_TIMEOUT_LEN_500US         = 0x1,
+	DP_AUX_DPHY_RX_CONTROL_TIMEOUT_LEN_550US         = 0x2,
+	DP_AUX_DPHY_RX_CONTROL_TIMEOUT_LEN_600US         = 0x3,
+	DP_AUX_DPHY_RX_CONTROL_TIMEOUT_LEN_650US         = 0x4,
+	DP_AUX_DPHY_RX_CONTROL_TIMEOUT_LEN_700US         = 0x5,
+	DP_AUX_DPHY_RX_CONTROL_TIMEOUT_LEN_750US         = 0x6,
+	DP_AUX_DPHY_RX_CONTROL_TIMEOUT_LEN_800US         = 0x7,
+} DP_AUX_DPHY_RX_CONTROL_TIMEOUT_LEN;
+typedef enum DP_AUX_DPHY_RX_DETECTION_THRESHOLD {
+	DP_AUX_DPHY_RX_DETECTION_THRESHOLD__1to2         = 0x0,
+	DP_AUX_DPHY_RX_DETECTION_THRESHOLD__3to4         = 0x1,
+	DP_AUX_DPHY_RX_DETECTION_THRESHOLD__7to8         = 0x2,
+	DP_AUX_DPHY_RX_DETECTION_THRESHOLD__15to16       = 0x3,
+	DP_AUX_DPHY_RX_DETECTION_THRESHOLD__31to32       = 0x4,
+	DP_AUX_DPHY_RX_DETECTION_THRESHOLD__63to64       = 0x5,
+	DP_AUX_DPHY_RX_DETECTION_THRESHOLD__127to128     = 0x6,
+	DP_AUX_DPHY_RX_DETECTION_THRESHOLD__255to256     = 0x7,
+} DP_AUX_DPHY_RX_DETECTION_THRESHOLD;
+typedef enum DP_AUX_GTC_SYNC_CONTROL_GTC_SYNC_BLOCK_REQ {
+	DP_AUX_GTC_SYNC_CONTROL_GTC_SYNC_ALLOW_REQ_FROM_OTHER_AUX= 0x0,
+	DP_AUX_GTC_SYNC_CONTROL_GTC_SYNC_BLOCK_REQ_FROM_OTHER_AUX= 0x1,
+} DP_AUX_GTC_SYNC_CONTROL_GTC_SYNC_BLOCK_REQ;
+typedef enum DP_AUX_GTC_SYNC_CONTROL_INTERVAL_RESET_WINDOW {
+	DP_AUX_GTC_SYNC_CONTROL_INTERVAL_RESET_WINDOW__300US= 0x0,
+	DP_AUX_GTC_SYNC_CONTROL_INTERVAL_RESET_WINDOW__400US= 0x1,
+	DP_AUX_GTC_SYNC_CONTROL_INTERVAL_RESET_WINDOW__500US= 0x2,
+	DP_AUX_GTC_SYNC_CONTROL_INTERVAL_RESET_WINDOW__600US= 0x3,
+} DP_AUX_GTC_SYNC_CONTROL_INTERVAL_RESET_WINDOW;
+typedef enum DP_AUX_GTC_SYNC_CONTROL_OFFSET_CALC_MAX_ATTEMPT {
+	DP_AUX_GTC_SYNC_CONTROL_OFFSET_CALC_MAX_ATTEMPT__4_ATTAMPS= 0x0,
+	DP_AUX_GTC_SYNC_CONTROL_OFFSET_CALC_MAX_ATTEMPT__8_ATTAMPS= 0x1,
+	DP_AUX_GTC_SYNC_CONTROL_OFFSET_CALC_MAX_ATTEMPT__16_ATTAMPS= 0x2,
+	DP_AUX_GTC_SYNC_CONTROL_OFFSET_CALC_MAX_ATTEMPT__RESERVED= 0x3,
+} DP_AUX_GTC_SYNC_CONTROL_OFFSET_CALC_MAX_ATTEMPT;
+typedef enum DP_AUX_GTC_SYNC_ERROR_CONTROL_LOCK_ACQ_TIMEOUT_LEN {
+	DP_AUX_GTC_SYNC_ERROR_CONTROL_LOCK_ACQ_TIMEOUT_LEN__0= 0x0,
+	DP_AUX_GTC_SYNC_ERROR_CONTROL_LOCK_ACQ_TIMEOUT_LEN__64= 0x1,
+	DP_AUX_GTC_SYNC_ERROR_CONTROL_LOCK_ACQ_TIMEOUT_LEN__128= 0x2,
+	DP_AUX_GTC_SYNC_ERROR_CONTROL_LOCK_ACQ_TIMEOUT_LEN__256= 0x3,
+} DP_AUX_GTC_SYNC_ERROR_CONTROL_LOCK_ACQ_TIMEOUT_LEN;
+typedef enum DP_AUX_ERR_OCCURRED_ACK {
+	DP_AUX_ERR_OCCURRED__NOT_ACK                     = 0x0,
+	DP_AUX_ERR_OCCURRED__ACK                         = 0x1,
+} DP_AUX_ERR_OCCURRED_ACK;
+typedef enum DP_AUX_POTENTIAL_ERR_REACHED_ACK {
+	DP_AUX_POTENTIAL_ERR_REACHED__NOT_ACK            = 0x0,
+	DP_AUX_POTENTIAL_ERR_REACHED__ACK                = 0x1,
+} DP_AUX_POTENTIAL_ERR_REACHED_ACK;
+typedef enum DP_AUX_DEFINITE_ERR_REACHED_ACK {
+	ALPHA_DP_AUX_DEFINITE_ERR_REACHED_NOT_ACK        = 0x0,
+	ALPHA_DP_AUX_DEFINITE_ERR_REACHED_ACK            = 0x1,
+} DP_AUX_DEFINITE_ERR_REACHED_ACK;
+typedef enum DP_AUX_RESET {
+	DP_AUX_RESET_DEASSERTED                          = 0x0,
+	DP_AUX_RESET_ASSERTED                            = 0x1,
+} DP_AUX_RESET;
+typedef enum DP_AUX_RESET_DONE {
+	DP_AUX_RESET_SEQUENCE_NOT_DONE                   = 0x0,
+	DP_AUX_RESET_SEQUENCE_DONE                       = 0x1,
+} DP_AUX_RESET_DONE;
+typedef enum FBC_IDLE_MASK_MASK_BITS {
+	FBC_IDLE_MASK_DISP_REG_UPDATE                    = 0x0,
+	FBC_IDLE_MASK_RESERVED1                          = 0x1,
+	FBC_IDLE_MASK_FBC_GRPH_COMP_EN                   = 0x2,
+	FBC_IDLE_MASK_FBC_MIN_COMPRESSION                = 0x3,
+	FBC_IDLE_MASK_FBC_ALPHA_COMP_EN                  = 0x4,
+	FBC_IDLE_MASK_FBC_ZERO_ALPHA_CHUNK_SKIP_EN       = 0x5,
+	FBC_IDLE_MASK_FBC_FORCE_COPY_TO_COMP_BUF         = 0x6,
+	FBC_IDLE_MASK_RESERVED7                          = 0x7,
+	FBC_IDLE_MASK_RESERVED8                          = 0x8,
+	FBC_IDLE_MASK_RESERVED9                          = 0x9,
+	FBC_IDLE_MASK_RESERVED10                         = 0xa,
+	FBC_IDLE_MASK_RESERVED11                         = 0xb,
+	FBC_IDLE_MASK_RESERVED12                         = 0xc,
+	FBC_IDLE_MASK_RESERVED13                         = 0xd,
+	FBC_IDLE_MASK_RESERVED14                         = 0xe,
+	FBC_IDLE_MASK_RESERVED15                         = 0xf,
+	FBC_IDLE_MASK_RESERVED16                         = 0x10,
+	FBC_IDLE_MASK_RESERVED17                         = 0x11,
+	FBC_IDLE_MASK_RESERVED18                         = 0x12,
+	FBC_IDLE_MASK_RESERVED19                         = 0x13,
+	FBC_IDLE_MASK_RESERVED20                         = 0x14,
+	FBC_IDLE_MASK_RESERVED21                         = 0x15,
+	FBC_IDLE_MASK_RESERVED22                         = 0x16,
+	FBC_IDLE_MASK_RESERVED23                         = 0x17,
+	FBC_IDLE_MASK_MC_HIT_REGION_0                    = 0x18,
+	FBC_IDLE_MASK_MC_HIT_REGION_1                    = 0x19,
+	FBC_IDLE_MASK_MC_HIT_REGION_2                    = 0x1a,
+	FBC_IDLE_MASK_MC_HIT_REGION_3                    = 0x1b,
+	FBC_IDLE_MASK_MC_WRITE                           = 0x1c,
+	FBC_IDLE_MASK_CG_STATIC_SCREEN                   = 0x1d,
+	FBC_IDLE_MASK_RESERVED30                         = 0x1e,
+	FBC_IDLE_MASK_RESERVED31                         = 0x1f,
+} FBC_IDLE_MASK_MASK_BITS;
+typedef enum FMT_CONTROL_PIXEL_ENCODING {
+	FMT_CONTROL_PIXEL_ENCODING_RGB444_OR_YCBCR444    = 0x0,
+	FMT_CONTROL_PIXEL_ENCODING_YCBCR422              = 0x1,
+	FMT_CONTROL_PIXEL_ENCODING_YCBCR420              = 0x2,
+	FMT_CONTROL_PIXEL_ENCODING_RESERVED              = 0x3,
+} FMT_CONTROL_PIXEL_ENCODING;
+typedef enum FMT_CONTROL_SUBSAMPLING_MODE {
+	FMT_CONTROL_SUBSAMPLING_MODE_DROP                = 0x0,
+	FMT_CONTROL_SUBSAMPLING_MODE_AVERAGE             = 0x1,
+	FMT_CONTROL_SUBSAMPLING_MODE_3_TAP               = 0x2,
+	FMT_CONTROL_SUBSAMPLING_MODE_RESERVED            = 0x3,
+} FMT_CONTROL_SUBSAMPLING_MODE;
+typedef enum FMT_CONTROL_SUBSAMPLING_ORDER {
+	FMT_CONTROL_SUBSAMPLING_ORDER_CB_BEFORE_CR       = 0x0,
+	FMT_CONTROL_SUBSAMPLING_ORDER_CR_BEFORE_CB       = 0x1,
+} FMT_CONTROL_SUBSAMPLING_ORDER;
+typedef enum FMT_CONTROL_CBCR_BIT_REDUCTION_BYPASS {
+	FMT_CONTROL_CBCR_BIT_REDUCTION_BYPASS_DISABLE    = 0x0,
+	FMT_CONTROL_CBCR_BIT_REDUCTION_BYPASS_ENABLE     = 0x1,
+} FMT_CONTROL_CBCR_BIT_REDUCTION_BYPASS;
+typedef enum FMT_BIT_DEPTH_CONTROL_TRUNCATE_MODE {
+	FMT_BIT_DEPTH_CONTROL_TRUNCATE_MODE_TRUNCATION   = 0x0,
+	FMT_BIT_DEPTH_CONTROL_TRUNCATE_MODE_ROUNDING     = 0x1,
+} FMT_BIT_DEPTH_CONTROL_TRUNCATE_MODE;
+typedef enum FMT_BIT_DEPTH_CONTROL_TRUNCATE_DEPTH {
+	FMT_BIT_DEPTH_CONTROL_TRUNCATE_DEPTH_18BPP       = 0x0,
+	FMT_BIT_DEPTH_CONTROL_TRUNCATE_DEPTH_24BPP       = 0x1,
+	FMT_BIT_DEPTH_CONTROL_TRUNCATE_DEPTH_30BPP       = 0x2,
+} FMT_BIT_DEPTH_CONTROL_TRUNCATE_DEPTH;
+typedef enum FMT_BIT_DEPTH_CONTROL_SPATIAL_DITHER_DEPTH {
+	FMT_BIT_DEPTH_CONTROL_SPATIAL_DITHER_DEPTH_18BPP = 0x0,
+	FMT_BIT_DEPTH_CONTROL_SPATIAL_DITHER_DEPTH_24BPP = 0x1,
+	FMT_BIT_DEPTH_CONTROL_SPATIAL_DITHER_DEPTH_30BPP = 0x2,
+} FMT_BIT_DEPTH_CONTROL_SPATIAL_DITHER_DEPTH;
+typedef enum FMT_BIT_DEPTH_CONTROL_TEMPORAL_DITHER_DEPTH {
+	FMT_BIT_DEPTH_CONTROL_TEMPORAL_DITHER_DEPTH_18BPP= 0x0,
+	FMT_BIT_DEPTH_CONTROL_TEMPORAL_DITHER_DEPTH_24BPP= 0x1,
+	FMT_BIT_DEPTH_CONTROL_TEMPORAL_DITHER_DEPTH_30BPP= 0x2,
+} FMT_BIT_DEPTH_CONTROL_TEMPORAL_DITHER_DEPTH;
+typedef enum FMT_BIT_DEPTH_CONTROL_TEMPORAL_LEVEL {
+	FMT_BIT_DEPTH_CONTROL_TEMPORAL_LEVEL_GREY_LEVEL2 = 0x0,
+	FMT_BIT_DEPTH_CONTROL_TEMPORAL_LEVEL_GREY_LEVEL4 = 0x1,
+} FMT_BIT_DEPTH_CONTROL_TEMPORAL_LEVEL;
+typedef enum FMT_BIT_DEPTH_CONTROL_25FRC_SEL {
+	FMT_BIT_DEPTH_CONTROL_25FRC_SEL_Ei               = 0x0,
+	FMT_BIT_DEPTH_CONTROL_25FRC_SEL_Fi               = 0x1,
+	FMT_BIT_DEPTH_CONTROL_25FRC_SEL_Gi               = 0x2,
+	FMT_BIT_DEPTH_CONTROL_25FRC_SEL_RESERVED         = 0x3,
+} FMT_BIT_DEPTH_CONTROL_25FRC_SEL;
+typedef enum FMT_BIT_DEPTH_CONTROL_50FRC_SEL {
+	FMT_BIT_DEPTH_CONTROL_50FRC_SEL_A                = 0x0,
+	FMT_BIT_DEPTH_CONTROL_50FRC_SEL_B                = 0x1,
+	FMT_BIT_DEPTH_CONTROL_50FRC_SEL_C                = 0x2,
+	FMT_BIT_DEPTH_CONTROL_50FRC_SEL_D                = 0x3,
+} FMT_BIT_DEPTH_CONTROL_50FRC_SEL;
+typedef enum FMT_BIT_DEPTH_CONTROL_75FRC_SEL {
+	FMT_BIT_DEPTH_CONTROL_75FRC_SEL_E                = 0x0,
+	FMT_BIT_DEPTH_CONTROL_75FRC_SEL_F                = 0x1,
+	FMT_BIT_DEPTH_CONTROL_75FRC_SEL_G                = 0x2,
+	FMT_BIT_DEPTH_CONTROL_75FRC_SEL_RESERVED         = 0x3,
+} FMT_BIT_DEPTH_CONTROL_75FRC_SEL;
+typedef enum FMT_TEMPORAL_DITHER_PATTERN_CONTROL_SELECT {
+	FMT_TEMPORAL_DITHER_PATTERN_CONTROL_SELECT_LEGACY_HARDCODED_PATTERN= 0x0,
+	FMT_TEMPORAL_DITHER_PATTERN_CONTROL_SELECT_PROGRAMMABLE_PATTERN= 0x1,
+} FMT_TEMPORAL_DITHER_PATTERN_CONTROL_SELECT;
+typedef enum FMT_TEMPORAL_DITHER_PATTERN_CONTROL_RGB1_BGR0 {
+	FMT_TEMPORAL_DITHER_PATTERN_CONTROL_RGB1_BGR0_BGR= 0x0,
+	FMT_TEMPORAL_DITHER_PATTERN_CONTROL_RGB1_BGR0_RGB= 0x1,
+} FMT_TEMPORAL_DITHER_PATTERN_CONTROL_RGB1_BGR0;
+typedef enum FMT_CLAMP_CNTL_COLOR_FORMAT {
+	FMT_CLAMP_CNTL_COLOR_FORMAT_6BPC                 = 0x0,
+	FMT_CLAMP_CNTL_COLOR_FORMAT_8BPC                 = 0x1,
+	FMT_CLAMP_CNTL_COLOR_FORMAT_10BPC                = 0x2,
+	FMT_CLAMP_CNTL_COLOR_FORMAT_12BPC                = 0x3,
+	FMT_CLAMP_CNTL_COLOR_FORMAT_RESERVED1            = 0x4,
+	FMT_CLAMP_CNTL_COLOR_FORMAT_RESERVED2            = 0x5,
+	FMT_CLAMP_CNTL_COLOR_FORMAT_RESERVED3            = 0x6,
+	FMT_CLAMP_CNTL_COLOR_FORMAT_PROGRAMMABLE         = 0x7,
+} FMT_CLAMP_CNTL_COLOR_FORMAT;
+typedef enum FMT_CRC_CNTL_CONT_EN {
+	FMT_CRC_CNTL_CONT_EN_ONE_SHOT                    = 0x0,
+	FMT_CRC_CNTL_CONT_EN_CONT                        = 0x1,
+} FMT_CRC_CNTL_CONT_EN;
+typedef enum FMT_CRC_CNTL_INCLUDE_OVERSCAN {
+	FMT_CRC_CNTL_INCLUDE_OVERSCAN_NOT_INCLUDE        = 0x0,
+	FMT_CRC_CNTL_INCLUDE_OVERSCAN_INCLUDE            = 0x1,
+} FMT_CRC_CNTL_INCLUDE_OVERSCAN;
+typedef enum FMT_CRC_CNTL_ONLY_BLANKB {
+	FMT_CRC_CNTL_ONLY_BLANKB_ENTIRE_FIELD            = 0x0,
+	FMT_CRC_CNTL_ONLY_BLANKB_NON_BLANK               = 0x1,
+} FMT_CRC_CNTL_ONLY_BLANKB;
+typedef enum FMT_CRC_CNTL_PSR_MODE_ENABLE {
+	FMT_CRC_CNTL_PSR_MODE_ENABLE_NORMAL              = 0x0,
+	FMT_CRC_CNTL_PSR_MODE_ENABLE_EDP_PSR_CRC         = 0x1,
+} FMT_CRC_CNTL_PSR_MODE_ENABLE;
+typedef enum FMT_CRC_CNTL_INTERLACE_MODE {
+	FMT_CRC_CNTL_INTERLACE_MODE_TOP                  = 0x0,
+	FMT_CRC_CNTL_INTERLACE_MODE_BOTTOM               = 0x1,
+	FMT_CRC_CNTL_INTERLACE_MODE_BOTH_BOTTOM          = 0x2,
+	FMT_CRC_CNTL_INTERLACE_MODE_BOTH_EACH            = 0x3,
+} FMT_CRC_CNTL_INTERLACE_MODE;
+typedef enum FMT_CRC_CNTL_EVEN_ODD_PIX_ENABLE {
+	FMT_CRC_CNTL_EVEN_ODD_PIX_ENABLE_ALL             = 0x0,
+	FMT_CRC_CNTL_EVEN_ODD_PIX_ENABLE_ODD_EVEN        = 0x1,
+} FMT_CRC_CNTL_EVEN_ODD_PIX_ENABLE;
+typedef enum FMT_CRC_CNTL_EVEN_ODD_PIX_SELECT {
+	FMT_CRC_CNTL_EVEN_ODD_PIX_SELECT_EVEN            = 0x0,
+	FMT_CRC_CNTL_EVEN_ODD_PIX_SELECT_ODD             = 0x1,
+} FMT_CRC_CNTL_EVEN_ODD_PIX_SELECT;
+typedef enum FMT_DEBUG_CNTL_COLOR_SELECT {
+	FMT_DEBUG_CNTL_COLOR_SELECT_BLUE                 = 0x0,
+	FMT_DEBUG_CNTL_COLOR_SELECT_GREEN                = 0x1,
+	FMT_DEBUG_CNTL_COLOR_SELECT_RED1                 = 0x2,
+	FMT_DEBUG_CNTL_COLOR_SELECT_RED2                 = 0x3,
+} FMT_DEBUG_CNTL_COLOR_SELECT;
+typedef enum FMT_SPATIAL_DITHER_MODE {
+	FMT_SPATIAL_DITHER_MODE_0                        = 0x0,
+	FMT_SPATIAL_DITHER_MODE_1                        = 0x1,
+	FMT_SPATIAL_DITHER_MODE_2                        = 0x2,
+	FMT_SPATIAL_DITHER_MODE_3                        = 0x3,
+} FMT_SPATIAL_DITHER_MODE;
+typedef enum FMT_STEREOSYNC_OVR_POL {
+	FMT_STEREOSYNC_OVR_POL_INVERTED                  = 0x0,
+	FMT_STEREOSYNC_OVR_POL_NOT_INVERTED              = 0x1,
+} FMT_STEREOSYNC_OVR_POL;
+typedef enum FMT_DYNAMIC_EXP_MODE {
+	FMT_DYNAMIC_EXP_MODE_10to12                      = 0x0,
+	FMT_DYNAMIC_EXP_MODE_8to12                       = 0x1,
+} FMT_DYNAMIC_EXP_MODE;
+typedef enum LB_DATA_FORMAT_PIXEL_DEPTH {
+	LB_DATA_FORMAT_PIXEL_DEPTH_30BPP                 = 0x0,
+	LB_DATA_FORMAT_PIXEL_DEPTH_24BPP                 = 0x1,
+	LB_DATA_FORMAT_PIXEL_DEPTH_18BPP                 = 0x2,
+	LB_DATA_FORMAT_PIXEL_DEPTH_36BPP                 = 0x3,
+} LB_DATA_FORMAT_PIXEL_DEPTH;
+typedef enum LB_DATA_FORMAT_PIXEL_EXPAN_MODE {
+	LB_DATA_FORMAT_PIXEL_EXPAN_MODE_ZERO_PIXEL_EXPANSION= 0x0,
+	LB_DATA_FORMAT_PIXEL_EXPAN_MODE_DYNAMIC_PIXEL_EXPANSION= 0x1,
+} LB_DATA_FORMAT_PIXEL_EXPAN_MODE;
+typedef enum LB_DATA_FORMAT_PIXEL_REDUCE_MODE {
+	LB_DATA_FORMAT_PIXEL_REDUCE_MODE_TRUNCATION      = 0x0,
+	LB_DATA_FORMAT_PIXEL_REDUCE_MODE_ROUNDING        = 0x1,
+} LB_DATA_FORMAT_PIXEL_REDUCE_MODE;
+typedef enum LB_DATA_FORMAT_DYNAMIC_PIXEL_DEPTH {
+	LB_DATA_FORMAT_DYNAMIC_PIXEL_DEPTH_36BPP         = 0x0,
+	LB_DATA_FORMAT_DYNAMIC_PIXEL_DEPTH_30BPP         = 0x1,
+} LB_DATA_FORMAT_DYNAMIC_PIXEL_DEPTH;
+typedef enum LB_DATA_FORMAT_INTERLEAVE_EN {
+	LB_DATA_FORMAT_INTERLEAVE_DISABLE                = 0x0,
+	LB_DATA_FORMAT_INTERLEAVE_ENABLE                 = 0x1,
+} LB_DATA_FORMAT_INTERLEAVE_EN;
+typedef enum LB_DATA_FORMAT_PREFILL_EN {
+	LB_DATA_FORMAT_PREFILL_DISABLE                   = 0x0,
+	LB_DATA_FORMAT_PREFILL_ENABLE                    = 0x1,
+} LB_DATA_FORMAT_PREFILL_EN;
+typedef enum LB_DATA_FORMAT_REQUEST_MODE {
+	LB_DATA_FORMAT_REQUEST_MODE_NORMAL               = 0x0,
+	LB_DATA_FORMAT_REQUEST_MODE_START_OF_LINE        = 0x1,
+} LB_DATA_FORMAT_REQUEST_MODE;
+typedef enum LB_DATA_FORMAT_ALPHA_EN {
+	LB_DATA_FORMAT_ALPHA_DISABLE                     = 0x0,
+	LB_DATA_FORMAT_ALPHA_ENABLE                      = 0x1,
+} LB_DATA_FORMAT_ALPHA_EN;
+typedef enum LB_VLINE_START_END_VLINE_INV {
+	LB_VLINE_START_END_VLINE_NORMAL                  = 0x0,
+	LB_VLINE_START_END_VLINE_INVERSE                 = 0x1,
+} LB_VLINE_START_END_VLINE_INV;
+typedef enum LB_VLINE2_START_END_VLINE2_INV {
+	LB_VLINE2_START_END_VLINE2_NORMAL                = 0x0,
+	LB_VLINE2_START_END_VLINE2_INVERSE               = 0x1,
+} LB_VLINE2_START_END_VLINE2_INV;
+typedef enum LB_INTERRUPT_MASK_VBLANK_INTERRUPT_MASK {
+	LB_INTERRUPT_MASK_VBLANK_INTERRUPT_DISABLE       = 0x0,
+	LB_INTERRUPT_MASK_VBLANK_INTERRUPT_ENABLE        = 0x1,
+} LB_INTERRUPT_MASK_VBLANK_INTERRUPT_MASK;
+typedef enum LB_INTERRUPT_MASK_VLINE_INTERRUPT_MASK {
+	LB_INTERRUPT_MASK_VLINE_INTERRUPT_DISABLE        = 0x0,
+	LB_INTERRUPT_MASK_VLINE_INTERRUPT_ENABLE         = 0x1,
+} LB_INTERRUPT_MASK_VLINE_INTERRUPT_MASK;
+typedef enum LB_INTERRUPT_MASK_VLINE2_INTERRUPT_MASK {
+	LB_INTERRUPT_MASK_VLINE2_INTERRUPT_DISABLE       = 0x0,
+	LB_INTERRUPT_MASK_VLINE2_INTERRUPT_ENABLE        = 0x1,
+} LB_INTERRUPT_MASK_VLINE2_INTERRUPT_MASK;
+typedef enum LB_VLINE_STATUS_VLINE_ACK {
+	LB_VLINE_STATUS_VLINE_NORMAL                     = 0x0,
+	LB_VLINE_STATUS_VLINE_CLEAR                      = 0x1,
+} LB_VLINE_STATUS_VLINE_ACK;
+typedef enum LB_VLINE_STATUS_VLINE_INTERRUPT_TYPE {
+	LB_VLINE_STATUS_VLINE_INTERRUPT_TYPE_LEVEL_BASED = 0x0,
+	LB_VLINE_STATUS_VLINE_INTERRUPT_TYPE_PULSE_BASED = 0x1,
+} LB_VLINE_STATUS_VLINE_INTERRUPT_TYPE;
+typedef enum LB_VLINE2_STATUS_VLINE2_ACK {
+	LB_VLINE2_STATUS_VLINE2_NORMAL                   = 0x0,
+	LB_VLINE2_STATUS_VLINE2_CLEAR                    = 0x1,
+} LB_VLINE2_STATUS_VLINE2_ACK;
+typedef enum LB_VLINE2_STATUS_VLINE2_INTERRUPT_TYPE {
+	LB_VLINE2_STATUS_VLINE2_INTERRUPT_TYPE_LEVEL_BASED= 0x0,
+	LB_VLINE2_STATUS_VLINE2_INTERRUPT_TYPE_PULSE_BASED= 0x1,
+} LB_VLINE2_STATUS_VLINE2_INTERRUPT_TYPE;
+typedef enum LB_VBLANK_STATUS_VBLANK_ACK {
+	LB_VBLANK_STATUS_VBLANK_NORMAL                   = 0x0,
+	LB_VBLANK_STATUS_VBLANK_CLEAR                    = 0x1,
+} LB_VBLANK_STATUS_VBLANK_ACK;
+typedef enum LB_VBLANK_STATUS_VBLANK_INTERRUPT_TYPE {
+	LB_VBLANK_STATUS_VBLANK_INTERRUPT_TYPE_LEVEL_BASED= 0x0,
+	LB_VBLANK_STATUS_VBLANK_INTERRUPT_TYPE_PULSE_BASED= 0x1,
+} LB_VBLANK_STATUS_VBLANK_INTERRUPT_TYPE;
+typedef enum LB_SYNC_RESET_SEL_LB_SYNC_RESET_SEL {
+	LB_SYNC_RESET_SEL_LB_SYNC_RESET_SEL_DISABLE      = 0x0,
+	LB_SYNC_RESET_SEL_LB_SYNC_RESET_SEL_FROM_VSYNC_VBLANK= 0x1,
+	LB_SYNC_RESET_SEL_LB_SYNC_RESET_SEL_FROM_POWERDOWN_RESET= 0x2,
+	LB_SYNC_RESET_SEL_LB_SYNC_RESET_SEL_FROM_VSYNC_VBLANK_POWERDOWN_RESET= 0x3,
+} LB_SYNC_RESET_SEL_LB_SYNC_RESET_SEL;
+typedef enum LB_SYNC_RESET_SEL_LB_SYNC_RESET_SEL2 {
+	LB_SYNC_RESET_SEL_LB_SYNC_RESET_SEL2_USE_VBLANK  = 0x0,
+	LB_SYNC_RESET_SEL_LB_SYNC_RESET_SEL2_USE_VSYNC   = 0x1,
+} LB_SYNC_RESET_SEL_LB_SYNC_RESET_SEL2;
+typedef enum LB_SYNC_RESET_SEL_LB_SYNC_DURATION {
+	LB_SYNC_RESET_SEL_LB_SYNC_DURATION_16_CLOCKS     = 0x0,
+	LB_SYNC_RESET_SEL_LB_SYNC_DURATION_32_CLOCKS     = 0x1,
+	LB_SYNC_RESET_SEL_LB_SYNC_DURATION_64_CLOCKS     = 0x2,
+	LB_SYNC_RESET_SEL_LB_SYNC_DURATION_128_CLOCKS    = 0x3,
+} LB_SYNC_RESET_SEL_LB_SYNC_DURATION;
+typedef enum LB_KEYER_COLOR_CTRL_LB_KEYER_COLOR_EN {
+	LB_KEYER_COLOR_CTRL_LB_KEYER_COLOR_DISABLE       = 0x0,
+	LB_KEYER_COLOR_CTRL_LB_KEYER_COLOR_ENABLE        = 0x1,
+} LB_KEYER_COLOR_CTRL_LB_KEYER_COLOR_EN;
+typedef enum LB_KEYER_COLOR_CTRL_LB_KEYER_COLOR_REP_EN {
+	LB_KEYER_COLOR_CTRL_LB_KEYER_COLOR_REPLACEMENT_DISABLE= 0x0,
+	LB_KEYER_COLOR_CTRL_LB_KEYER_COLOR_REPLACEMENT_ENABLE= 0x1,
+} LB_KEYER_COLOR_CTRL_LB_KEYER_COLOR_REP_EN;
+typedef enum LB_BUFFER_STATUS_LB_BUFFER_EMPTY_ACK {
+	LB_BUFFER_STATUS_LB_BUFFER_EMPTY_NORMAL          = 0x0,
+	LB_BUFFER_STATUS_LB_BUFFER_EMPTY_RESET           = 0x1,
+} LB_BUFFER_STATUS_LB_BUFFER_EMPTY_ACK;
+typedef enum LB_BUFFER_STATUS_LB_BUFFER_FULL_ACK {
+	LB_BUFFER_STATUS_LB_BUFFER_FULL_NORMAL           = 0x0,
+	LB_BUFFER_STATUS_LB_BUFFER_FULL_RESET            = 0x1,
+} LB_BUFFER_STATUS_LB_BUFFER_FULL_ACK;
+typedef enum LB_MVP_AFR_FLIP_MODE_MVP_AFR_FLIP_MODE {
+	LB_MVP_AFR_FLIP_MODE_MVP_AFR_FLIP_MODE_REAL_FLIP = 0x2,
+	LB_MVP_AFR_FLIP_MODE_MVP_AFR_FLIP_MODE_DUMMY_FLIP= 0x3,
+} LB_MVP_AFR_FLIP_MODE_MVP_AFR_FLIP_MODE;
+typedef enum LB_MVP_AFR_FLIP_FIFO_CNTL_MVP_AFR_FLIP_FIFO_RESET {
+	LB_MVP_AFR_FLIP_FIFO_CNTL_MVP_AFR_FLIP_FIFO_NORMAL= 0x0,
+	LB_MVP_AFR_FLIP_FIFO_CNTL_MVP_AFR_FLIP_FIFO_RESET_ACTIVE= 0x1,
+} LB_MVP_AFR_FLIP_FIFO_CNTL_MVP_AFR_FLIP_FIFO_RESET;
+typedef enum LB_MVP_AFR_FLIP_FIFO_CNTL_MVP_AFR_FLIP_FIFO_RESET_ACK {
+	LB_MVP_AFR_FLIP_FIFO_CNTL_MVP_AFR_FLIP_FIFO_RESET_ACK_NOT_USED0= 0x0,
+	LB_MVP_AFR_FLIP_FIFO_CNTL_MVP_AFR_FLIP_FIFO_RESET_ACK_NOT_USED1= 0x1,
+} LB_MVP_AFR_FLIP_FIFO_CNTL_MVP_AFR_FLIP_FIFO_RESET_ACK;
+typedef enum LB_MVP_FLIP_LINE_NUM_INSERT_MVP_FLIP_LINE_NUM_INSERT_MODE {
+	LB_MVP_FLIP_LINE_NUM_INSERT_MVP_FLIP_LINE_NUM_INSERT_MODE_NO_INSERT= 0x0,
+	LB_MVP_FLIP_LINE_NUM_INSERT_MVP_FLIP_LINE_NUM_INSERT_MODE_DEBUG= 0x1,
+	LB_MVP_FLIP_LINE_NUM_INSERT_MVP_FLIP_LINE_NUM_INSERT_MODE_HSYNC_MODE= 0x2,
+} LB_MVP_FLIP_LINE_NUM_INSERT_MVP_FLIP_LINE_NUM_INSERT_MODE;
+typedef enum LB_MVP_FLIP_LINE_NUM_INSERT_MVP_FLIP_AUTO_ENABLE {
+	LB_MVP_FLIP_LINE_NUM_INSERT_MVP_FLIP_AUTO_DISABLE= 0x0,
+	LB_MVP_FLIP_LINE_NUM_INSERT_MVP_FLIP_AUTO_EN     = 0x1,
+} LB_MVP_FLIP_LINE_NUM_INSERT_MVP_FLIP_AUTO_ENABLE;
+typedef enum LB_DC_MVP_LB_CONTROL_MVP_SWAP_LOCK_IN_MODE {
+	ALPHA_LB_DC_MVP_LB_CONTROL_MVP_SWAP_LOCK_IN_MODE_MASTER= 0x1,
+	ALPHA_LB_DC_MVP_LB_CONTROL_MVP_SWAP_LOCK_IN_MODE_SLAVE= 0x2,
+} LB_DC_MVP_LB_CONTROL_MVP_SWAP_LOCK_IN_MODE;
+typedef enum LB_DC_MVP_LB_CONTROL_DC_MVP_SWAP_LOCK_OUT_SEL {
+	LB_DC_MVP_LB_CONTROL_DC_MVP_SWAP_LOCK_OUT_SEL_NOT_USED0= 0x0,
+	LB_DC_MVP_LB_CONTROL_DC_MVP_SWAP_LOCK_OUT_SEL_NOT_USED1= 0x1,
+} LB_DC_MVP_LB_CONTROL_DC_MVP_SWAP_LOCK_OUT_SEL;
+typedef enum LB_DC_MVP_LB_CONTROL_DC_MVP_SWAP_LOCK_OUT_FORCE_ONE {
+	LB_DC_MVP_LB_CONTROL_DC_MVP_SWAP_LOCK_OUT_NO_FORCE_ONE= 0x0,
+	LB_DC_MVP_LB_CONTROL_DC_MVP_SWAP_LOCK_OUT_FORCE_TO_ONE= 0x1,
+} LB_DC_MVP_LB_CONTROL_DC_MVP_SWAP_LOCK_OUT_FORCE_ONE;
+typedef enum LB_DC_MVP_LB_CONTROL_DC_MVP_SWAP_LOCK_OUT_FORCE_ZERO {
+	LB_DC_MVP_LB_CONTROL_DC_MVP_SWAP_LOCK_OUT_NO_FORCE_ZERO= 0x0,
+	LB_DC_MVP_LB_CONTROL_DC_MVP_SWAP_LOCK_OUT_FORCE_TO_ZERO= 0x1,
+} LB_DC_MVP_LB_CONTROL_DC_MVP_SWAP_LOCK_OUT_FORCE_ZERO;
+typedef enum LB_TEST_DEBUG_INDEX_LB_TEST_DEBUG_WRITE_EN {
+	LB_TEST_DEBUG_INDEX_LB_TEST_DEBUG_WRITE_EN_NOT_USED0= 0x0,
+	LB_TEST_DEBUG_INDEX_LB_TEST_DEBUG_WRITE_EN_NOT_USED1= 0x1,
+} LB_TEST_DEBUG_INDEX_LB_TEST_DEBUG_WRITE_EN;
+typedef enum LBV_PIXEL_DEPTH {
+	PIXEL_DEPTH_30BPP                                = 0x0,
+	PIXEL_DEPTH_24BPP                                = 0x1,
+	PIXEL_DEPTH_18BPP                                = 0x2,
+	PIXEL_DEPTH_38BPP                                = 0x3,
+} LBV_PIXEL_DEPTH;
+typedef enum LBV_PIXEL_EXPAN_MODE {
+	PIXEL_EXPAN_MODE_ZERO_EXP                        = 0x0,
+	PIXEL_EXPAN_MODE_DYN_EXP                         = 0x1,
+} LBV_PIXEL_EXPAN_MODE;
+typedef enum LBV_INTERLEAVE_EN {
+	INTERLEAVE_DIS                                   = 0x0,
+	INTERLEAVE_EN                                    = 0x1,
+} LBV_INTERLEAVE_EN;
+typedef enum LBV_PIXEL_REDUCE_MODE {
+	PIXEL_REDUCE_MODE_TRUNCATION                     = 0x0,
+	PIXEL_REDUCE_MODE_ROUNDING                       = 0x1,
+} LBV_PIXEL_REDUCE_MODE;
+typedef enum LBV_DYNAMIC_PIXEL_DEPTH {
+	DYNAMIC_PIXEL_DEPTH_36BPP                        = 0x0,
+	DYNAMIC_PIXEL_DEPTH_30BPP                        = 0x1,
+} LBV_DYNAMIC_PIXEL_DEPTH;
+typedef enum LBV_DITHER_EN {
+	DITHER_DIS                                       = 0x0,
+	DITHER_EN                                        = 0x1,
+} LBV_DITHER_EN;
+typedef enum LBV_DOWNSCALE_PREFETCH_EN {
+	DOWNSCALE_PREFETCH_DIS                           = 0x0,
+	DOWNSCALE_PREFETCH_EN                            = 0x1,
+} LBV_DOWNSCALE_PREFETCH_EN;
+typedef enum LBV_MEMORY_CONFIG {
+	MEMORY_CONFIG_0                                  = 0x0,
+	MEMORY_CONFIG_1                                  = 0x1,
+	MEMORY_CONFIG_2                                  = 0x2,
+	MEMORY_CONFIG_3                                  = 0x3,
+} LBV_MEMORY_CONFIG;
+typedef enum LBV_SYNC_RESET_SEL2 {
+	SYNC_RESET_SEL2_VBLANK                           = 0x0,
+	SYNC_RESET_SEL2_VSYNC                            = 0x1,
+} LBV_SYNC_RESET_SEL2;
+typedef enum LBV_SYNC_DURATION {
+	SYNC_DURATION_16                                 = 0x0,
+	SYNC_DURATION_32                                 = 0x1,
+	SYNC_DURATION_64                                 = 0x2,
+	SYNC_DURATION_128                                = 0x3,
+} LBV_SYNC_DURATION;
+typedef enum SCL_C_RAM_TAP_PAIR_IDX {
+	SCL_C_RAM_TAP_PAIR_ID0                           = 0x0,
+	SCL_C_RAM_TAP_PAIR_ID1                           = 0x1,
+	SCL_C_RAM_TAP_PAIR_ID2                           = 0x2,
+	SCL_C_RAM_TAP_PAIR_ID3                           = 0x3,
+	SCL_C_RAM_TAP_PAIR_ID4                           = 0x4,
+} SCL_C_RAM_TAP_PAIR_IDX;
+typedef enum SCL_C_RAM_PHASE {
+	SCL_C_RAM_PHASE_0                                = 0x0,
+	SCL_C_RAM_PHASE_1                                = 0x1,
+	SCL_C_RAM_PHASE_2                                = 0x2,
+	SCL_C_RAM_PHASE_3                                = 0x3,
+	SCL_C_RAM_PHASE_4                                = 0x4,
+	SCL_C_RAM_PHASE_5                                = 0x5,
+	SCL_C_RAM_PHASE_6                                = 0x6,
+	SCL_C_RAM_PHASE_7                                = 0x7,
+	SCL_C_RAM_PHASE_8                                = 0x8,
+} SCL_C_RAM_PHASE;
+typedef enum SCL_C_RAM_FILTER_TYPE {
+	SCL_C_RAM_FILTER_TYPE_VERT_LUMA_RGB_LUT          = 0x0,
+	SCL_C_RAM_FILTER_TYPE_VERT_CHROMA_LUT            = 0x1,
+	SCL_C_RAM_FILTER_TYPE_HORI_LUMA_RGB_LUT          = 0x2,
+	SCL_C_RAM_FILTER_TYPE_HORI_CHROMA_LUT            = 0x3,
+} SCL_C_RAM_FILTER_TYPE;
+typedef enum SCL_MODE_SEL {
+	SCL_MODE_RGB_BYPASS                              = 0x0,
+	SCL_MODE_RGB_SCALING                             = 0x1,
+	SCL_MODE_YCBCR_SCALING                           = 0x2,
+	SCL_MODE_YCBCR_BYPASS                            = 0x3,
+} SCL_MODE_SEL;
+typedef enum SCL_PSCL_EN {
+	SCL_PSCL_DISABLE                                 = 0x0,
+	SCL_PSCL_ENANBLE                                 = 0x1,
+} SCL_PSCL_EN;
+typedef enum SCL_V_NUM_OF_TAPS {
+	SCL_V_NUM_OF_TAPS_1                              = 0x0,
+	SCL_V_NUM_OF_TAPS_2                              = 0x1,
+	SCL_V_NUM_OF_TAPS_3                              = 0x2,
+	SCL_V_NUM_OF_TAPS_4                              = 0x3,
+	SCL_V_NUM_OF_TAPS_5                              = 0x4,
+	SCL_V_NUM_OF_TAPS_6                              = 0x5,
+} SCL_V_NUM_OF_TAPS;
+typedef enum SCL_H_NUM_OF_TAPS {
+	SCL_H_NUM_OF_TAPS_1                              = 0x0,
+	SCL_H_NUM_OF_TAPS_2                              = 0x1,
+	SCL_H_NUM_OF_TAPS_4                              = 0x3,
+	SCL_H_NUM_OF_TAPS_6                              = 0x5,
+	SCL_H_NUM_OF_TAPS_8                              = 0x7,
+	SCL_H_NUM_OF_TAPS_10                             = 0x9,
+} SCL_H_NUM_OF_TAPS;
+typedef enum SCL_BOUNDARY_MODE {
+	SCL_BOUNDARY_MODE_BLACK                          = 0x0,
+	SCL_BOUNDARY_MODE_EDGE                           = 0x1,
+} SCL_BOUNDARY_MODE;
+typedef enum SCL_EARLY_EOL_MOD {
+	SCL_EARLY_EOL_MODE_CRTC                          = 0x0,
+	SCL_EARLY_EOL_MODE_INTERNAL                      = 0x1,
+} SCL_EARLY_EOL_MOD;
+typedef enum SCL_BYPASS_MODE {
+	SCL_BYPASS_MODE_MC_MR                            = 0x0,
+	SCL_BYPASS_MODE_AC_NR                            = 0x1,
+	SCL_BYPASS_MODE_AC_AR                            = 0x2,
+	SCL_BYPASS_MODE_RESERVED                         = 0x3,
+} SCL_BYPASS_MODE;
+typedef enum SCL_V_MANUAL_REPLICATE_FACTOR {
+	SCL_V_MANUAL_REPLICATE_FACTOR_1                  = 0x0,
+	SCL_V_MANUAL_REPLICATE_FACTOR_2                  = 0x1,
+	SCL_V_MANUAL_REPLICATE_FACTOR_3                  = 0x2,
+	SCL_V_MANUAL_REPLICATE_FACTOR_4                  = 0x3,
+	SCL_V_MANUAL_REPLICATE_FACTOR_5                  = 0x4,
+	SCL_V_MANUAL_REPLICATE_FACTOR_6                  = 0x5,
+	SCL_V_MANUAL_REPLICATE_FACTOR_7                  = 0x6,
+	SCL_V_MANUAL_REPLICATE_FACTOR_8                  = 0x7,
+	SCL_V_MANUAL_REPLICATE_FACTOR_9                  = 0x8,
+	SCL_V_MANUAL_REPLICATE_FACTOR_10                 = 0x9,
+	SCL_V_MANUAL_REPLICATE_FACTOR_11                 = 0xa,
+	SCL_V_MANUAL_REPLICATE_FACTOR_12                 = 0xb,
+	SCL_V_MANUAL_REPLICATE_FACTOR_13                 = 0xc,
+	SCL_V_MANUAL_REPLICATE_FACTOR_14                 = 0xd,
+	SCL_V_MANUAL_REPLICATE_FACTOR_15                 = 0xe,
+	SCL_V_MANUAL_REPLICATE_FACTOR_16                 = 0xf,
+} SCL_V_MANUAL_REPLICATE_FACTOR;
+typedef enum SCL_H_MANUAL_REPLICATE_FACTOR {
+	SCL_H_MANUAL_REPLICATE_FACTOR_1                  = 0x0,
+	SCL_H_MANUAL_REPLICATE_FACTOR_2                  = 0x1,
+	SCL_H_MANUAL_REPLICATE_FACTOR_3                  = 0x2,
+	SCL_H_MANUAL_REPLICATE_FACTOR_4                  = 0x3,
+	SCL_H_MANUAL_REPLICATE_FACTOR_5                  = 0x4,
+	SCL_H_MANUAL_REPLICATE_FACTOR_6                  = 0x5,
+	SCL_H_MANUAL_REPLICATE_FACTOR_7                  = 0x6,
+	SCL_H_MANUAL_REPLICATE_FACTOR_8                  = 0x7,
+	SCL_H_MANUAL_REPLICATE_FACTOR_9                  = 0x8,
+	SCL_H_MANUAL_REPLICATE_FACTOR_10                 = 0x9,
+	SCL_H_MANUAL_REPLICATE_FACTOR_11                 = 0xa,
+	SCL_H_MANUAL_REPLICATE_FACTOR_12                 = 0xb,
+	SCL_H_MANUAL_REPLICATE_FACTOR_13                 = 0xc,
+	SCL_H_MANUAL_REPLICATE_FACTOR_14                 = 0xd,
+	SCL_H_MANUAL_REPLICATE_FACTOR_15                 = 0xe,
+	SCL_H_MANUAL_REPLICATE_FACTOR_16                 = 0xf,
+} SCL_H_MANUAL_REPLICATE_FACTOR;
+typedef enum SCL_V_CALC_AUTO_RATIO_EN {
+	SCL_V_CALC_AUTO_RATIO_DISABLE                    = 0x0,
+	SCL_V_CALC_AUTO_RATIO_ENABLE                     = 0x1,
+} SCL_V_CALC_AUTO_RATIO_EN;
+typedef enum SCL_H_CALC_AUTO_RATIO_EN {
+	SCL_H_CALC_AUTO_RATIO_DISABLE                    = 0x0,
+	SCL_H_CALC_AUTO_RATIO_ENABLE                     = 0x1,
+} SCL_H_CALC_AUTO_RATIO_EN;
+typedef enum SCL_H_FILTER_PICK_NEAREST {
+	SCL_H_FILTER_PICK_NEAREST_DISABLE                = 0x0,
+	SCL_H_FILTER_PICK_NEAREST_ENABLE                 = 0x1,
+} SCL_H_FILTER_PICK_NEAREST;
+typedef enum SCL_H_2TAP_HARDCODE_COEF_EN {
+	SCL_H_2TAP_HARDCODE_COEF_DISABLE                 = 0x0,
+	SCL_H_2TAP_HARDCODE_COEF_ENABLE                  = 0x1,
+} SCL_H_2TAP_HARDCODE_COEF_EN;
+typedef enum SCL_V_FILTER_PICK_NEAREST {
+	SCL_V_FILTER_PICK_NEAREST_DISABLE                = 0x0,
+	SCL_V_FILTER_PICK_NEAREST_ENABLE                 = 0x1,
+} SCL_V_FILTER_PICK_NEAREST;
+typedef enum SCL_V_2TAP_HARDCODE_COEF_EN {
+	SCL_V_2TAP_HARDCODE_COEF_DISABLE                 = 0x0,
+	SCL_V_2TAP_HARDCODE_COEF_ENABLE                  = 0x1,
+} SCL_V_2TAP_HARDCODE_COEF_EN;
+typedef enum SCL_UPDATE_TAKEN {
+	SCL_UPDATE_TAKEN_NO                              = 0x0,
+	SCL_UPDATE_TAKEN_YES                             = 0x1,
+} SCL_UPDATE_TAKEN;
+typedef enum SCL_UPDATE_LOCK {
+	SCL_UPDATE_UNLOCKED                              = 0x0,
+	SCL_UPDATE_LOCKED                                = 0x1,
+} SCL_UPDATE_LOCK;
+typedef enum SCL_COEF_UPDATE_COMPLETE {
+	SCL_COEF_UPDATE_NOT_COMPLETED                    = 0x0,
+	SCL_COEF_UPDATE_COMPLETED                        = 0x1,
+} SCL_COEF_UPDATE_COMPLETE;
+typedef enum SCL_HF_SHARP_SCALE_FACTOR {
+	SCL_HF_SHARP_SCALE_FACTOR_0                      = 0x0,
+	SCL_HF_SHARP_SCALE_FACTOR_1                      = 0x1,
+	SCL_HF_SHARP_SCALE_FACTOR_2                      = 0x2,
+	SCL_HF_SHARP_SCALE_FACTOR_3                      = 0x3,
+	SCL_HF_SHARP_SCALE_FACTOR_4                      = 0x4,
+	SCL_HF_SHARP_SCALE_FACTOR_5                      = 0x5,
+	SCL_HF_SHARP_SCALE_FACTOR_6                      = 0x6,
+	SCL_HF_SHARP_SCALE_FACTOR_7                      = 0x7,
+} SCL_HF_SHARP_SCALE_FACTOR;
+typedef enum SCL_HF_SHARP_EN {
+	SCL_HF_SHARP_DISABLE                             = 0x0,
+	SCL_HF_SHARP_ENABLE                              = 0x1,
+} SCL_HF_SHARP_EN;
+typedef enum SCL_VF_SHARP_SCALE_FACTOR {
+	SCL_VF_SHARP_SCALE_FACTOR_0                      = 0x0,
+	SCL_VF_SHARP_SCALE_FACTOR_1                      = 0x1,
+	SCL_VF_SHARP_SCALE_FACTOR_2                      = 0x2,
+	SCL_VF_SHARP_SCALE_FACTOR_3                      = 0x3,
+	SCL_VF_SHARP_SCALE_FACTOR_4                      = 0x4,
+	SCL_VF_SHARP_SCALE_FACTOR_5                      = 0x5,
+	SCL_VF_SHARP_SCALE_FACTOR_6                      = 0x6,
+	SCL_VF_SHARP_SCALE_FACTOR_7                      = 0x7,
+} SCL_VF_SHARP_SCALE_FACTOR;
+typedef enum SCL_VF_SHARP_EN {
+	SCL_VF_SHARP_DISABLE                             = 0x0,
+	SCL_VF_SHARP_ENABLE                              = 0x1,
+} SCL_VF_SHARP_EN;
+typedef enum SCL_ALU_DISABLE {
+	SCL_ALU_ENABLED                                  = 0x0,
+	SCL_ALU_DISABLED                                 = 0x1,
+} SCL_ALU_DISABLE;
+typedef enum SCL_HOST_CONFLICT_MASK {
+	SCL_HOST_CONFLICT_DISABLE_INTERRUPT              = 0x0,
+	SCL_HOST_CONFLICT_ENABLE_INTERRUPT               = 0x1,
+} SCL_HOST_CONFLICT_MASK;
+typedef enum SCL_SCL_MODE_CHANGE_MASK {
+	SCL_MODE_CHANGE_DISABLE_INTERRUPT                = 0x0,
+	SCL_MODE_CHANGE_ENABLE_INTERRUPT                 = 0x1,
+} SCL_SCL_MODE_CHANGE_MASK;
+typedef enum SCLV_MODE_SEL {
+	SCLV_MODE_RGB_BYPASS                             = 0x0,
+	SCLV_MODE_RGB_SCALING                            = 0x1,
+	SCLV_MODE_YCBCR_SCALING                          = 0x2,
+	SCLV_MODE_YCBCR_BYPASS                           = 0x3,
+} SCLV_MODE_SEL;
+typedef enum SCLV_INTERLACE_SOURCE {
+	INTERLACE_SOURCE_PROGRESSIVE                     = 0x0,
+	INTERLACE_SOURCE_INTERLEAVE                      = 0x1,
+	INTERLACE_SOURCE_STACK                           = 0x2,
+} SCLV_INTERLACE_SOURCE;
+typedef enum SCLV_UPDATE_LOCK {
+	UPDATE_UNLOCKED                                  = 0x0,
+	UPDATE_LOCKED                                    = 0x1,
+} SCLV_UPDATE_LOCK;
+typedef enum SCLV_COEF_UPDATE_COMPLETE {
+	COEF_UPDATE_NOT_COMPLETE                         = 0x0,
+	COEF_UPDATE_COMPLETE                             = 0x1,
+} SCLV_COEF_UPDATE_COMPLETE;
+typedef enum COL_MAN_UPDATE_LOCK {
+	COL_MAN_UPDATE_UNLOCKED                          = 0x0,
+	COL_MAN_UPDATE_LOCKED                            = 0x1,
+} COL_MAN_UPDATE_LOCK;
+typedef enum COL_MAN_DISABLE_MULTIPLE_UPDATE {
+	COL_MAN_MULTIPLE_UPDATE                          = 0x0,
+	COL_MAN_MULTIPLE_UPDAT_EDISABLE                  = 0x1,
+} COL_MAN_DISABLE_MULTIPLE_UPDATE;
+typedef enum COL_MAN_INPUTCSC_MODE {
+	INPUTCSC_MODE_BYPASS                             = 0x0,
+	INPUTCSC_MODE_A                                  = 0x1,
+	INPUTCSC_MODE_B                                  = 0x2,
+	INPUTCSC_MODE_UNITY                              = 0x3,
+} COL_MAN_INPUTCSC_MODE;
+typedef enum COL_MAN_INPUTCSC_TYPE {
+	INPUTCSC_TYPE_12_0                               = 0x0,
+	INPUTCSC_TYPE_10_2                               = 0x1,
+	INPUTCSC_TYPE_8_4                                = 0x2,
+} COL_MAN_INPUTCSC_TYPE;
+typedef enum COL_MAN_INPUTCSC_CONVERT {
+	INPUTCSC_ROUND                                   = 0x0,
+	INPUTCSC_TRUNCATE                                = 0x1,
+} COL_MAN_INPUTCSC_CONVERT;
+typedef enum COL_MAN_PRESCALE_MODE {
+	PRESCALE_MODE_BYPASS                             = 0x0,
+	PRESCALE_MODE_PROGRAM                            = 0x1,
+	PRESCALE_MODE_UNITY                              = 0x2,
+} COL_MAN_PRESCALE_MODE;
+typedef enum COL_MAN_INPUT_GAMMA_MODE {
+	INGAMMA_MODE_BYPASS                              = 0x0,
+	INGAMMA_MODE_FIX                                 = 0x1,
+	INGAMMA_MODE_FLOAT                               = 0x2,
+} COL_MAN_INPUT_GAMMA_MODE;
+typedef enum COL_MAN_OUTPUT_CSC_MODE {
+	COL_MAN_OUTPUT_CSC_BYPASS                        = 0x0,
+	COL_MAN_OUTPUT_CSC_RGB                           = 0x1,
+	COL_MAN_OUTPUT_CSC_YCrCb601                      = 0x2,
+	COL_MAN_OUTPUT_CSC_YCrCb709                      = 0x3,
+	COL_MAN_OUTPUT_CSC_A                             = 0x4,
+	COL_MAN_OUTPUT_CSC_B                             = 0x5,
+	COL_MAN_OUTPUT_CSC_UNITY                         = 0x6,
+} COL_MAN_OUTPUT_CSC_MODE;
+typedef enum COL_MAN_DENORM_CLAMP_CONTROL {
+	DENORM_CLAMP_MODE_UNITY                          = 0x0,
+	DENORM_CLAMP_MODE_8                              = 0x1,
+	DENORM_CLAMP_MODE_10                             = 0x2,
+	DENORM_CLAMP_MODE_12                             = 0x3,
+} COL_MAN_DENORM_CLAMP_CONTROL;
+typedef enum COL_MAN_GAMMA_CORR_CONTROL {
+	GAMMA_CORR_MODE_BYPASS                           = 0x0,
+	GAMMA_CORR_MODE_A                                = 0x1,
+	GAMMA_CORR_MODE_B                                = 0x2,
+} COL_MAN_GAMMA_CORR_CONTROL;
+typedef enum COL_MAN_GLOBAL_PASSTHROUGH_ENABLE {
+	CM_GLOBAL_PASSTHROUGH_DISBALE                    = 0x0,
+	CM_GLOBAL_PASSTHROUGH_ENABLE                     = 0x1,
+} COL_MAN_GLOBAL_PASSTHROUGH_ENABLE;
+typedef enum UNP_GRPH_EN {
+	UNP_GRPH_DISABLED                                = 0x0,
+	UNP_GRPH_ENABLED                                 = 0x1,
+} UNP_GRPH_EN;
+typedef enum UNP_GRPH_DEPTH {
+	UNP_GRPH_8BPP                                    = 0x0,
+	UNP_GRPH_16BPP                                   = 0x1,
+	UNP_GRPH_32BPP                                   = 0x2,
+} UNP_GRPH_DEPTH;
+typedef enum UNP_GRPH_NUM_BANKS {
+	UNP_GRPH_ADDR_SURF_2_BANK                        = 0x0,
+	UNP_GRPH_ADDR_SURF_4_BANK                        = 0x1,
+	UNP_GRPH_ADDR_SURF_8_BANK                        = 0x2,
+	UNP_GRPH_ADDR_SURF_16_BANK                       = 0x3,
+} UNP_GRPH_NUM_BANKS;
+typedef enum UNP_GRPH_BANK_WIDTH {
+	UNP_GRPH_ADDR_SURF_BANK_WIDTH_1                  = 0x0,
+	UNP_GRPH_ADDR_SURF_BANK_WIDTH_2                  = 0x1,
+	UNP_GRPH_ADDR_SURF_BANK_WIDTH_4                  = 0x2,
+	UNP_GRPH_ADDR_SURF_BANK_WIDTH_8                  = 0x3,
+} UNP_GRPH_BANK_WIDTH;
+typedef enum UNP_GRPH_BANK_HEIGHT {
+	UNP_GRPH_ADDR_SURF_BANK_HEIGHT_1                 = 0x0,
+	UNP_GRPH_ADDR_SURF_BANK_HEIGHT_2                 = 0x1,
+	UNP_GRPH_ADDR_SURF_BANK_HEIGHT_4                 = 0x2,
+	UNP_GRPH_ADDR_SURF_BANK_HEIGHT_8                 = 0x3,
+} UNP_GRPH_BANK_HEIGHT;
+typedef enum UNP_GRPH_TILE_SPLIT {
+	UNP_ADDR_SURF_TILE_SPLIT_64B                     = 0x0,
+	UNP_ADDR_SURF_TILE_SPLIT_128B                    = 0x1,
+	UNP_ADDR_SURF_TILE_SPLIT_256B                    = 0x2,
+	UNP_ADDR_SURF_TILE_SPLIT_512B                    = 0x3,
+	UNP_ADDR_SURF_TILE_SPLIT_1KB                     = 0x4,
+	UNP_ADDR_SURF_TILE_SPLIT_2KB                     = 0x5,
+	UNP_ADDR_SURF_TILE_SPLIT_4KB                     = 0x6,
+} UNP_GRPH_TILE_SPLIT;
+typedef enum UNP_GRPH_ADDRESS_TRANSLATION_ENABLE {
+	UNP_GRPH_ADDRESS_TRANSLATION_ENABLE0             = 0x0,
+	UNP_GRPH_ADDRESS_TRANSLATION_ENABLE1             = 0x1,
+} UNP_GRPH_ADDRESS_TRANSLATION_ENABLE;
+typedef enum UNP_GRPH_PRIVILEGED_ACCESS_ENABLE {
+	UNP_GRPH_PRIVILEGED_ACCESS_DIS                   = 0x0,
+	UNP_GRPH_PRIVILEGED_ACCESS_EN                    = 0x1,
+} UNP_GRPH_PRIVILEGED_ACCESS_ENABLE;
+typedef enum UNP_GRPH_MACRO_TILE_ASPECT {
+	UNP_ADDR_SURF_MACRO_ASPECT_1                     = 0x0,
+	UNP_ADDR_SURF_MACRO_ASPECT_2                     = 0x1,
+	UNP_ADDR_SURF_MACRO_ASPECT_4                     = 0x2,
+	UNP_ADDR_SURF_MACRO_ASPECT_8                     = 0x3,
+} UNP_GRPH_MACRO_TILE_ASPECT;
+typedef enum UNP_GRPH_COLOR_EXPANSION_MODE {
+	UNP_GRPH_DYNAMIC_EXPANSION                       = 0x0,
+	UNP_GRPH_ZERO_EXPANSION                          = 0x1,
+} UNP_GRPH_COLOR_EXPANSION_MODE;
+typedef enum UNP_VIDEO_FORMAT {
+	UNP_VIDEO_FORMAT0                                = 0x0,
+	UNP_VIDEO_FORMAT1                                = 0x1,
+	UNP_VIDEO_FORMAT_YUV420_YCbCr                    = 0x2,
+	UNP_VIDEO_FORMAT_YUV420_YCrCb                    = 0x3,
+	UNP_VIDEO_FORMAT_YUV422_YCb                      = 0x4,
+	UNP_VIDEO_FORMAT_YUV422_YCr                      = 0x5,
+	UNP_VIDEO_FORMAT_YUV422_CbY                      = 0x6,
+	UNP_VIDEO_FORMAT_YUV422_CrY                      = 0x7,
+} UNP_VIDEO_FORMAT;
+typedef enum UNP_GRPH_ENDIAN_SWAP {
+	UNP_GRPH_ENDIAN_SWAP_NONE                        = 0x0,
+	UNP_GRPH_ENDIAN_SWAP_8IN16                       = 0x1,
+	UNP_GRPH_ENDIAN_SWAP_8IN32                       = 0x2,
+	UNP_GRPH_ENDIAN_SWAP_8IN43                       = 0x3,
+} UNP_GRPH_ENDIAN_SWAP;
+typedef enum UNP_GRPH_RED_CROSSBAR {
+	UNP_GRPH_RED_CROSSBAR_R_Cr                       = 0x0,
+	UNP_GRPH_RED_CROSSBAR_G_Y                        = 0x1,
+	UNP_GRPH_RED_CROSSBAR_B_Cb                       = 0x2,
+	UNP_GRPH_RED_CROSSBAR_A                          = 0x3,
+} UNP_GRPH_RED_CROSSBAR;
+typedef enum UNP_GRPH_GREEN_CROSSBAR {
+	UNP_UNP_GRPH_GREEN_CROSSBAR_GY_AND_Y             = 0x0,
+	UNP_UNP_GRPH_GREEN_CROSSBAR_B_Cb_AND_C           = 0x1,
+	UNP_UNP_GRPH_GREEN_CROSSBAR_A                    = 0x2,
+	UNP_UNP_GRPH_GREEN_CROSSBAR_R_Cr                 = 0x3,
+} UNP_GRPH_GREEN_CROSSBAR;
+typedef enum UNP_GRPH_BLUE_CROSSBAR {
+	UNP_GRPH_BLUE_CROSSBAR_B_Cb_AND_C                = 0x0,
+	UNP_GRPH_BLUE_CROSSBAR_A                         = 0x1,
+	UNP_GRPH_BLUE_CROSSBAR_R_Cr                      = 0x2,
+	UNP_GRPH_BLUE_CROSSBAR_GY_AND_Y                  = 0x3,
+} UNP_GRPH_BLUE_CROSSBAR;
+typedef enum UNP_GRPH_MODE_UPDATE_LOCKG {
+	UNP_GRPH_UPDATE_LOCK_0                           = 0x0,
+	UNP_GRPH_UPDATE_LOCK_1                           = 0x1,
+} UNP_GRPH_MODE_UPDATE_LOCKG;
+typedef enum UNP_GRPH_SURFACE_IGNORE_UPDATE_LOCK {
+	UNP_GRPH_SURFACE_IGNORE_UPDATE_LOCK_0            = 0x0,
+	UNP_GRPH_SURFACE_IGNORE_UPDATE_LOCK_1            = 0x1,
+} UNP_GRPH_SURFACE_IGNORE_UPDATE_LOCK;
+typedef enum UNP_GRPH_MODE_DISABLE_MULTIPLE_UPDATE {
+	UNP_GRPH_MODE_DISABLE_MULTIPLE_UPDATE_0          = 0x0,
+	UNP_GRPH_MODE_DISABLE_MULTIPLE_UPDATE_1          = 0x1,
+} UNP_GRPH_MODE_DISABLE_MULTIPLE_UPDATE;
+typedef enum UNP_GRPH_SURFACE_DISABLE_MULTIPLE_UPDATE {
+	UNP_GRPH_SURFACE_DISABLE_MULTIPLE_UPDATE_0       = 0x0,
+	UNP_GRPH_SURFACE_DISABLE_MULTIPLE_UPDATE_1       = 0x1,
+} UNP_GRPH_SURFACE_DISABLE_MULTIPLE_UPDATE;
+typedef enum UNP_GRPH_STEREOSYNC_FLIP_EN {
+	UNP_GRPH_STEREOSYNC_FLIP_DISABLE                 = 0x0,
+	UNP_GRPH_STEREOSYNC_FLIP_ENABLE                  = 0x1,
+} UNP_GRPH_STEREOSYNC_FLIP_EN;
+typedef enum UNP_GRPH_STEREOSYNC_FLIP_MODE {
+	UNP_GRPH_STEREOSYNC_FLIP_MODE_0                  = 0x0,
+	UNP_GRPH_STEREOSYNC_FLIP_MODE_1                  = 0x1,
+	UNP_GRPH_STEREOSYNC_FLIP_MODE_2                  = 0x2,
+	UNP_GRPH_STEREOSYNC_FLIP_MODE_3                  = 0x3,
+} UNP_GRPH_STEREOSYNC_FLIP_MODE;
+typedef enum UNP_GRPH_STACK_INTERLACE_FLIP_EN {
+	UNP_GRPH_STACK_INTERLACE_FLIP_DISABLE            = 0x0,
+	UNP_GRPH_STACK_INTERLACE_FLIP_ENABLE             = 0x1,
+} UNP_GRPH_STACK_INTERLACE_FLIP_EN;
+typedef enum UNP_GRPH_STACK_INTERLACE_FLIP_MODE {
+	UNP_GRPH_STACK_INTERLACE_FLIP_MODE_0             = 0x0,
+	UNP_GRPH_STACK_INTERLACE_FLIP_MODE_1             = 0x1,
+	UNP_GRPH_STACK_INTERLACE_FLIP_MODE_2             = 0x2,
+	UNP_GRPH_STACK_INTERLACE_FLIP_MODE_3             = 0x3,
+} UNP_GRPH_STACK_INTERLACE_FLIP_MODE;
+typedef enum UNP_GRPH_STEREOSYNC_SELECT_DISABLE {
+	UNP_GRPH_STEREOSYNC_SELECT_EN                    = 0x0,
+	UNP_GRPH_STEREOSYNC_SELECT_DIS                   = 0x1,
+} UNP_GRPH_STEREOSYNC_SELECT_DISABLE;
+typedef enum UNP_CRC_SOURCE_SEL {
+	UNP_CRC_SOURCE_SEL_NP_TO_LBV                     = 0x0,
+	UNP_CRC_SOURCE_SEL_LOWER32                       = 0x1,
+	UNP_CRC_SOURCE_SEL_RESERVED                      = 0x2,
+	UNP_CRC_SOURCE_SEL_LOWER16                       = 0x3,
+	UNP_CRC_SOURCE_SEL_UNP_TO_LBV                    = 0x4,
+} UNP_CRC_SOURCE_SEL;
+typedef enum UNP_CRC_LINE_SEL {
+	UNP_CRC_LINE_SEL_RESERVED                        = 0x0,
+	UNP_CRC_LINE_SEL_EVEN_ONLY                       = 0x1,
+	UNP_CRC_LINE_SEL_ODD_ONLY                        = 0x2,
+	UNP_CRC_LINE_SEL_ODD_EVEN                        = 0x3,
+} UNP_CRC_LINE_SEL;
+typedef enum UNP_ROTATION_ANGLE {
+	UNP_ROTATION_ANGLE_0                             = 0x0,
+	UNP_ROTATION_ANGLE_90                            = 0x1,
+	UNP_ROTATION_ANGLE_180                           = 0x2,
+	UNP_ROTATION_ANGLE_270                           = 0x3,
+	UNP_ROTATION_ANGLE_0m                            = 0x4,
+	UNP_ROTATION_ANGLE_90m                           = 0x5,
+	UNP_ROTATION_ANGLE_180m                          = 0x6,
+	UNP_ROTATION_ANGLE_270m                          = 0x7,
+} UNP_ROTATION_ANGLE;
+typedef enum UNP_PIXEL_DROP {
+	UNP_PIXEL_NO_DROP                                = 0x0,
+	UNP_PIXEL_DROPPING                               = 0x1,
+} UNP_PIXEL_DROP;
+typedef enum UNP_BUFFER_MODE {
+	UNP_BUFFER_MODE_LUMA                             = 0x0,
+	UNP_BUFFER_MODE_LUMA_CHROMA                      = 0x1,
+} UNP_BUFFER_MODE;
+typedef enum WATERMARK_MASK_CONTROL {
+	WM_MASK_CONTROL_SET_A                            = 0x0,
+	WM_MASK_CONTROL_SET_B                            = 0x1,
+	WM_MASK_CONTROL_SET_C                            = 0x2,
+	WM_MASK_CONTROL_SET_D                            = 0x3,
+	WM_MASK_CONTROL_RESERVED1                        = 0x4,
+	WM_MASK_CONTROL_RESERVED2                        = 0x5,
+	WM_MASK_CONTROL_RESERVED3                        = 0x6,
+	WM_MASK_CONTROL_ACTIVE_SET                       = 0x7,
+} WATERMARK_MASK_CONTROL;
+typedef enum AZALIA_F2_CODEC_FUNCTION_CONTROL_RESET_CODEC_RESET {
+	AZALIA_F2_CODEC_FUNCTION_CONTROL_RESET_CODEC_NOT_RESET= 0x0,
+	AZALIA_F2_CODEC_FUNCTION_CONTROL_RESET_CODEC_DO_RESET= 0x1,
+} AZALIA_F2_CODEC_FUNCTION_CONTROL_RESET_CODEC_RESET;
+typedef enum CC_RCU_DC_AUDIO_PORT_CONNECTIVITY_PORT_CONNECTIVITY {
+	CC_RCU_DC_AUDIO_PORT_CONNECTIVITY_PORT_CONNECTIVITY_ALL= 0x0,
+	CC_RCU_DC_AUDIO_PORT_CONNECTIVITY_PORT_CONNECTIVITY_6= 0x1,
+	CC_RCU_DC_AUDIO_PORT_CONNECTIVITY_PORT_CONNECTIVITY_5= 0x2,
+	CC_RCU_DC_AUDIO_PORT_CONNECTIVITY_PORT_CONNECTIVITY_4= 0x3,
+	CC_RCU_DC_AUDIO_PORT_CONNECTIVITY_PORT_CONNECTIVITY_3= 0x4,
+	CC_RCU_DC_AUDIO_PORT_CONNECTIVITY_PORT_CONNECTIVITY_2= 0x5,
+	CC_RCU_DC_AUDIO_PORT_CONNECTIVITY_PORT_CONNECTIVITY_1= 0x6,
+	CC_RCU_DC_AUDIO_PORT_CONNECTIVITY_PORT_CONNECTIVITY_0= 0x7,
+} CC_RCU_DC_AUDIO_PORT_CONNECTIVITY_PORT_CONNECTIVITY;
+typedef enum CC_RCU_DC_AUDIO_INPUT_PORT_CONNECTIVITY_INPUT_PORT_CONNECTIVITY {
+	CC_RCU_DC_AUDIO_INPUT_PORT_CONNECTIVITY_INPUT_PORT_CONNECTIVITY_ALL= 0x0,
+	CC_RCU_DC_AUDIO_INPUT_PORT_CONNECTIVITY_INPUT_PORT_CONNECTIVITY_6= 0x1,
+	CC_RCU_DC_AUDIO_INPUT_PORT_CONNECTIVITY_INPUT_PORT_CONNECTIVITY_5= 0x2,
+	CC_RCU_DC_AUDIO_INPUT_PORT_CONNECTIVITY_INPUT_PORT_CONNECTIVITY_4= 0x3,
+	CC_RCU_DC_AUDIO_INPUT_PORT_CONNECTIVITY_INPUT_PORT_CONNECTIVITY_3= 0x4,
+	CC_RCU_DC_AUDIO_INPUT_PORT_CONNECTIVITY_INPUT_PORT_CONNECTIVITY_2= 0x5,
+	CC_RCU_DC_AUDIO_INPUT_PORT_CONNECTIVITY_INPUT_PORT_CONNECTIVITY_1= 0x6,
+	CC_RCU_DC_AUDIO_INPUT_PORT_CONNECTIVITY_INPUT_PORT_CONNECTIVITY_0= 0x7,
+} CC_RCU_DC_AUDIO_INPUT_PORT_CONNECTIVITY_INPUT_PORT_CONNECTIVITY;
+typedef enum GENERIC_AZ_CONTROLLER_REGISTER_ENABLE_CONTROL {
+	GENERIC_AZ_CONTROLLER_REGISTER_DISABLE           = 0x0,
+	GENERIC_AZ_CONTROLLER_REGISTER_ENABLE            = 0x1,
+} GENERIC_AZ_CONTROLLER_REGISTER_ENABLE_CONTROL;
+typedef enum GENERIC_AZ_CONTROLLER_REGISTER_ENABLE_CONTROL_RESERVED {
+	GENERIC_AZ_CONTROLLER_REGISTER_DISABLE_RESERVED  = 0x0,
+	GENERIC_AZ_CONTROLLER_REGISTER_ENABLE_RESERVED   = 0x1,
+} GENERIC_AZ_CONTROLLER_REGISTER_ENABLE_CONTROL_RESERVED;
+typedef enum GENERIC_AZ_CONTROLLER_REGISTER_STATUS {
+	GENERIC_AZ_CONTROLLER_REGISTER_STATUS_NOT_SET    = 0x0,
+	GENERIC_AZ_CONTROLLER_REGISTER_STATUS_SET        = 0x1,
+} GENERIC_AZ_CONTROLLER_REGISTER_STATUS;
+typedef enum GENERIC_AZ_CONTROLLER_REGISTER_STATUS_RESERVED {
+	GENERIC_AZ_CONTROLLER_REGISTER_STATUS_NOT_SET_RESERVED= 0x0,
+	GENERIC_AZ_CONTROLLER_REGISTER_STATUS_SET_RESERVED= 0x1,
+} GENERIC_AZ_CONTROLLER_REGISTER_STATUS_RESERVED;
+typedef enum AZ_GLOBAL_CAPABILITIES {
+	AZ_GLOBAL_CAPABILITIES_SIXTY_FOUR_BIT_ADDRESS_NOT_SUPPORTED= 0x0,
+	AZ_GLOBAL_CAPABILITIES_SIXTY_FOUR_BIT_ADDRESS_SUPPORTED= 0x1,
+} AZ_GLOBAL_CAPABILITIES;
+typedef enum GLOBAL_CONTROL_ACCEPT_UNSOLICITED_RESPONSE {
+	ACCEPT_UNSOLICITED_RESPONSE_NOT_ENABLE           = 0x0,
+	ACCEPT_UNSOLICITED_RESPONSE_ENABLE               = 0x1,
+} GLOBAL_CONTROL_ACCEPT_UNSOLICITED_RESPONSE;
+typedef enum GLOBAL_CONTROL_FLUSH_CONTROL {
+	FLUSH_CONTROL_FLUSH_NOT_STARTED                  = 0x0,
+	FLUSH_CONTROL_FLUSH_STARTED                      = 0x1,
+} GLOBAL_CONTROL_FLUSH_CONTROL;
+typedef enum GLOBAL_CONTROL_CONTROLLER_RESET {
+	CONTROLLER_RESET_AZ_CONTROLLER_IN_RESET          = 0x0,
+	CONTROLLER_RESET_AZ_CONTROLLER_NOT_IN_RESET      = 0x1,
+} GLOBAL_CONTROL_CONTROLLER_RESET;
+typedef enum AZ_STATE_CHANGE_STATUS {
+	AZ_STATE_CHANGE_STATUS_CODEC_NOT_PRESENT         = 0x0,
+	AZ_STATE_CHANGE_STATUS_CODEC_PRESENT             = 0x1,
+} AZ_STATE_CHANGE_STATUS;
+typedef enum GLOBAL_STATUS_FLUSH_STATUS {
+	GLOBAL_STATUS_FLUSH_STATUS_FLUSH_NOT_ENDED       = 0x0,
+	GLOBAL_STATUS_FLUSH_STATUS_FLUSH_ENDED           = 0x1,
+} GLOBAL_STATUS_FLUSH_STATUS;
+typedef enum STREAM_0_SYNCHRONIZATION {
+	STREAM_0_SYNCHRONIZATION_STEAM_NOT_STOPPED       = 0x0,
+	STREAM_0_SYNCHRONIZATION_STEAM_STOPPED           = 0x1,
+} STREAM_0_SYNCHRONIZATION;
+typedef enum STREAM_1_SYNCHRONIZATION {
+	STREAM_1_SYNCHRONIZATION_STEAM_NOT_STOPPED       = 0x0,
+	STREAM_1_SYNCHRONIZATION_STEAM_STOPPED           = 0x1,
+} STREAM_1_SYNCHRONIZATION;
+typedef enum STREAM_2_SYNCHRONIZATION {
+	STREAM_2_SYNCHRONIZATION_STEAM_NOT_STOPPED       = 0x0,
+	STREAM_2_SYNCHRONIZATION_STEAM_STOPPED           = 0x1,
+} STREAM_2_SYNCHRONIZATION;
+typedef enum STREAM_3_SYNCHRONIZATION {
+	STREAM_3_SYNCHRONIZATION_STEAM_NOT_STOPPED       = 0x0,
+	STREAM_3_SYNCHRONIZATION_STEAM_STOPPED           = 0x1,
+} STREAM_3_SYNCHRONIZATION;
+typedef enum STREAM_4_SYNCHRONIZATION {
+	STREAM_4_SYNCHRONIZATION_STEAM_NOT_STOPPED       = 0x0,
+	STREAM_4_SYNCHRONIZATION_STEAM_STOPPED           = 0x1,
+} STREAM_4_SYNCHRONIZATION;
+typedef enum STREAM_5_SYNCHRONIZATION {
+	STREAM_5_SYNCHRONIZATION_STEAM_NOT_STOPPED       = 0x0,
+	STREAM_5_SYNCHRONIZATION_STEAM_STOPPED           = 0x1,
+} STREAM_5_SYNCHRONIZATION;
+typedef enum STREAM_6_SYNCHRONIZATION {
+	STREAM_6_SYNCHRONIZATION_STEAM_NOT_STOPPED_RESERVED= 0x0,
+	STREAM_6_SYNCHRONIZATION_STEAM_STOPPED_RESERVED  = 0x1,
+} STREAM_6_SYNCHRONIZATION;
+typedef enum STREAM_7_SYNCHRONIZATION {
+	STREAM_7_SYNCHRONIZATION_STEAM_NOT_STOPPED_RESERVED= 0x0,
+	STREAM_7_SYNCHRONIZATION_STEAM_STOPPED_RESERVED  = 0x1,
+} STREAM_7_SYNCHRONIZATION;
+typedef enum STREAM_8_SYNCHRONIZATION {
+	STREAM_8_SYNCHRONIZATION_STEAM_NOT_STOPPED_RESERVED= 0x0,
+	STREAM_8_SYNCHRONIZATION_STEAM_STOPPED_RESERVED  = 0x1,
+} STREAM_8_SYNCHRONIZATION;
+typedef enum STREAM_9_SYNCHRONIZATION {
+	STREAM_9_SYNCHRONIZATION_STEAM_NOT_STOPPED_RESERVED= 0x0,
+	STREAM_9_SYNCHRONIZATION_STEAM_STOPPED_RESERVED  = 0x1,
+} STREAM_9_SYNCHRONIZATION;
+typedef enum STREAM_10_SYNCHRONIZATION {
+	STREAM_10_SYNCHRONIZATION_STEAM_NOT_STOPPED_RESERVED= 0x0,
+	STREAM_10_SYNCHRONIZATION_STEAM_STOPPED_RESERVED = 0x1,
+} STREAM_10_SYNCHRONIZATION;
+typedef enum STREAM_11_SYNCHRONIZATION {
+	STREAM_11_SYNCHRONIZATION_STEAM_NOT_STOPPED_RESERVED= 0x0,
+	STREAM_11_SYNCHRONIZATION_STEAM_STOPPED_RESERVED = 0x1,
+} STREAM_11_SYNCHRONIZATION;
+typedef enum STREAM_12_SYNCHRONIZATION {
+	STREAM_12_SYNCHRONIZATION_STEAM_NOT_STOPPED_RESERVED= 0x0,
+	STREAM_12_SYNCHRONIZATION_STEAM_STOPPED_RESERVED = 0x1,
+} STREAM_12_SYNCHRONIZATION;
+typedef enum STREAM_13_SYNCHRONIZATION {
+	STREAM_13_SYNCHRONIZATION_STEAM_NOT_STOPPED_RESERVED= 0x0,
+	STREAM_13_SYNCHRONIZATION_STEAM_STOPPED_RESERVED = 0x1,
+} STREAM_13_SYNCHRONIZATION;
+typedef enum STREAM_14_SYNCHRONIZATION {
+	STREAM_14_SYNCHRONIZATION_STEAM_NOT_STOPPED_RESERVED= 0x0,
+	STREAM_14_SYNCHRONIZATION_STEAM_STOPPED_RESERVED = 0x1,
+} STREAM_14_SYNCHRONIZATION;
+typedef enum STREAM_15_SYNCHRONIZATION {
+	STREAM_15_SYNCHRONIZATION_STEAM_NOT_STOPPED_RESERVED= 0x0,
+	STREAM_15_SYNCHRONIZATION_STEAM_STOPPED_RESERVED = 0x1,
+} STREAM_15_SYNCHRONIZATION;
+typedef enum CORB_READ_POINTER_RESET {
+	CORB_READ_POINTER_RESET_CORB_DMA_IS_NOT_RESET    = 0x0,
+	CORB_READ_POINTER_RESET_CORB_DMA_IS_RESET        = 0x1,
+} CORB_READ_POINTER_RESET;
+typedef enum AZ_CORB_SIZE {
+	AZ_CORB_SIZE_2ENTRIES_RESERVED                   = 0x0,
+	AZ_CORB_SIZE_16ENTRIES_RESERVED                  = 0x1,
+	AZ_CORB_SIZE_256ENTRIES                          = 0x2,
+	AZ_CORB_SIZE_RESERVED                            = 0x3,
+} AZ_CORB_SIZE;
+typedef enum AZ_RIRB_WRITE_POINTER_RESET {
+	AZ_RIRB_WRITE_POINTER_NOT_RESET                  = 0x0,
+	AZ_RIRB_WRITE_POINTER_DO_RESET                   = 0x1,
+} AZ_RIRB_WRITE_POINTER_RESET;
+typedef enum RIRB_CONTROL_RESPONSE_OVERRUN_INTERRUPT_CONTROL {
+	RIRB_CONTROL_RESPONSE_OVERRUN_INTERRUPT_CONTROL_INTERRUPT_DISABLED= 0x0,
+	RIRB_CONTROL_RESPONSE_OVERRUN_INTERRUPT_CONTROL_INTERRUPT_ENABLED= 0x1,
+} RIRB_CONTROL_RESPONSE_OVERRUN_INTERRUPT_CONTROL;
+typedef enum RIRB_CONTROL_RESPONSE_INTERRUPT_CONTROL {
+	RIRB_CONTROL_RESPONSE_INTERRUPT_CONTROL_INTERRUPT_DISABLED= 0x0,
+	RIRB_CONTROL_RESPONSE_INTERRUPT_CONTROL_INTERRUPT_ENABLED= 0x1,
+} RIRB_CONTROL_RESPONSE_INTERRUPT_CONTROL;
+typedef enum AZ_RIRB_SIZE {
+	AZ_RIRB_SIZE_2ENTRIES_RESERVED                   = 0x0,
+	AZ_RIRB_SIZE_16ENTRIES_RESERVED                  = 0x1,
+	AZ_RIRB_SIZE_256ENTRIES                          = 0x2,
+	AZ_RIRB_SIZE_UNDEFINED                           = 0x3,
+} AZ_RIRB_SIZE;
+typedef enum IMMEDIATE_COMMAND_STATUS_IMMEDIATE_RESULT_VALID {
+	IMMEDIATE_COMMAND_STATUS_IMMEDIATE_RESULT_VALID_NO_IMMEDIATE_RESPONSE_VALID= 0x0,
+	IMMEDIATE_COMMAND_STATUS_IMMEDIATE_RESULT_VALID_IMMEDIATE_RESPONSE_VALID= 0x1,
+} IMMEDIATE_COMMAND_STATUS_IMMEDIATE_RESULT_VALID;
+typedef enum IMMEDIATE_COMMAND_STATUS_IMMEDIATE_COMMAND_BUSY {
+	IMMEDIATE_COMMAND_STATUS_IMMEDIATE_COMMAND_NOT_BUSY= 0x0,
+	IMMEDIATE_COMMAND_STATUS_IMMEDIATE_COMMAND_IS_BUSY= 0x1,
+} IMMEDIATE_COMMAND_STATUS_IMMEDIATE_COMMAND_BUSY;
+typedef enum DMA_POSITION_LOWER_BASE_ADDRESS_BUFFER_ENABLE {
+	DMA_POSITION_LOWER_BASE_ADDRESS_BUFFER_ENABLE_DMA_DISABLE= 0x0,
+	DMA_POSITION_LOWER_BASE_ADDRESS_BUFFER_ENABLE_DMA_ENABLE= 0x1,
+} DMA_POSITION_LOWER_BASE_ADDRESS_BUFFER_ENABLE;
+typedef enum OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS_DESCRIPTOR_ERROR {
+	OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS_DESCRIPTOR_ERROR_STATUS_NOT_SET= 0x0,
+	OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS_DESCRIPTOR_ERROR_STATUS_SET= 0x1,
+} OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS_DESCRIPTOR_ERROR;
+typedef enum OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS_FIFO_ERROR {
+	OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS_FIFO_ERROR_STATUS_NOT_SET= 0x0,
+	OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS_FIFO_ERROR_STATUS_SET= 0x1,
+} OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS_FIFO_ERROR;
+typedef enum OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS_BUFFER_COMPLETION_INTERRUPT_STATUS {
+	OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS_BUFFER_COMPLETION_INTERRUPT_STATUS_NOT_SET= 0x0,
+	OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS_BUFFER_COMPLETION_INTERRUPT_STATUS_SET= 0x1,
+} OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS_BUFFER_COMPLETION_INTERRUPT_STATUS;
+typedef enum OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS_TRAFFIC_PRIORITY {
+	OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS_NO_TRAFFIC_PRIORITY= 0x0,
+	OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS_YES_TRAFFIC_PRIORITY= 0x1,
+} OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS_TRAFFIC_PRIORITY;
+typedef enum OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS_DESCRIPTOR_ERROR_INTERRUPT_ENABLE {
+	OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS_DESCRIPTOR_ERROR_INTERRUPT_DISABLED= 0x0,
+	OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS_DESCRIPTOR_ERROR_INTERRUPT_ENABLED= 0x1,
+} OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS_DESCRIPTOR_ERROR_INTERRUPT_ENABLE;
+typedef enum OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS_FIFO_ERROR_INTERRUPT_ENABLE {
+	OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS_FIFO_ERROR_INTERRUPT_DISABLED= 0x0,
+	OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS_FIFO_ERROR_INTERRUPT_ENABLED= 0x1,
+} OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS_FIFO_ERROR_INTERRUPT_ENABLE;
+typedef enum OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS_INTERRUPT_ON_COMPLETION_ENABLE {
+	OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS_INTERRUPT_ON_COMPLETION_ENABLE_INTERRUPT_DISABLED= 0x0,
+	OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS_INTERRUPT_ON_COMPLETION_ENABLE_INTERRUPT_ENABLED= 0x1,
+} OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS_INTERRUPT_ON_COMPLETION_ENABLE;
+typedef enum OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS_STREAM_RUN {
+	OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS_STREAM_NOT_RUN= 0x0,
+	OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS_STREAM_DO_RUN= 0x1,
+} OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS_STREAM_RUN;
+typedef enum OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS_STREAM_RESET {
+	OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS_STREAM_NOT_RESET= 0x0,
+	OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS_STREAM_IS_RESET= 0x1,
+} OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS_STREAM_RESET;
+typedef enum OUTPUT_STREAM_DESCRIPTOR_FORMAT_SAMPLE_BASE_RATE {
+	OUTPUT_STREAM_DESCRIPTOR_FORMAT_SAMPLE_BASE_RATE_48KHZ= 0x0,
+	OUTPUT_STREAM_DESCRIPTOR_FORMAT_SAMPLE_BASE_RATE_44P1KHZ= 0x1,
+} OUTPUT_STREAM_DESCRIPTOR_FORMAT_SAMPLE_BASE_RATE;
+typedef enum OUTPUT_STREAM_DESCRIPTOR_FORMAT_SAMPLE_BASE_MULTIPLE {
+	OUTPUT_STREAM_DESCRIPTOR_FORMAT_SAMPLE_BASE_MULTIPLE_BY1= 0x0,
+	OUTPUT_STREAM_DESCRIPTOR_FORMAT_SAMPLE_BASE_MULTIPLE_BY2= 0x1,
+	OUTPUT_STREAM_DESCRIPTOR_FORMAT_SAMPLE_BASE_MULTIPLE_BY3_RESERVED= 0x2,
+	OUTPUT_STREAM_DESCRIPTOR_FORMAT_SAMPLE_BASE_MULTIPLE_BY4= 0x3,
+	OUTPUT_STREAM_DESCRIPTOR_FORMAT_SAMPLE_BASE_MULTIPLE_RESERVED= 0x4,
+} OUTPUT_STREAM_DESCRIPTOR_FORMAT_SAMPLE_BASE_MULTIPLE;
+typedef enum OUTPUT_STREAM_DESCRIPTOR_FORMAT_SAMPLE_BASE_DIVISOR {
+	OUTPUT_STREAM_DESCRIPTOR_FORMAT_SAMPLE_BASE_DIVISOR_BY1= 0x0,
+	OUTPUT_STREAM_DESCRIPTOR_FORMAT_SAMPLE_BASE_DIVISOR_BY2_RESERVED= 0x1,
+	OUTPUT_STREAM_DESCRIPTOR_FORMAT_SAMPLE_BASE_DIVISOR_BY3= 0x2,
+	OUTPUT_STREAM_DESCRIPTOR_FORMAT_SAMPLE_BASE_DIVISOR_BY4_RESERVED= 0x3,
+	OUTPUT_STREAM_DESCRIPTOR_FORMAT_SAMPLE_BASE_DIVISOR_BY5_RESERVED= 0x4,
+	OUTPUT_STREAM_DESCRIPTOR_FORMAT_SAMPLE_BASE_DIVISOR_BY6_RESERVED= 0x5,
+	OUTPUT_STREAM_DESCRIPTOR_FORMAT_SAMPLE_BASE_DIVISOR_BY7_RESERVED= 0x6,
+	OUTPUT_STREAM_DESCRIPTOR_FORMAT_SAMPLE_BASE_DIVISOR_BY8_RESERVED= 0x7,
+} OUTPUT_STREAM_DESCRIPTOR_FORMAT_SAMPLE_BASE_DIVISOR;
+typedef enum OUTPUT_STREAM_DESCRIPTOR_FORMAT_BITS_PER_SAMPLE {
+	OUTPUT_STREAM_DESCRIPTOR_FORMAT_BITS_PER_SAMPLE_8_RESERVED= 0x0,
+	OUTPUT_STREAM_DESCRIPTOR_FORMAT_BITS_PER_SAMPLE_16= 0x1,
+	OUTPUT_STREAM_DESCRIPTOR_FORMAT_BITS_PER_SAMPLE_20= 0x2,
+	OUTPUT_STREAM_DESCRIPTOR_FORMAT_BITS_PER_SAMPLE_24= 0x3,
+	OUTPUT_STREAM_DESCRIPTOR_FORMAT_BITS_PER_SAMPLE_32_RESERVED= 0x4,
+	OUTPUT_STREAM_DESCRIPTOR_FORMAT_BITS_PER_SAMPLE_RESERVED= 0x5,
+} OUTPUT_STREAM_DESCRIPTOR_FORMAT_BITS_PER_SAMPLE;
+typedef enum OUTPUT_STREAM_DESCRIPTOR_FORMAT_NUMBER_OF_CHANNELS {
+	OUTPUT_STREAM_DESCRIPTOR_FORMAT_NUMBER_OF_CHANNELS_1= 0x0,
+	OUTPUT_STREAM_DESCRIPTOR_FORMAT_NUMBER_OF_CHANNELS_2= 0x1,
+	OUTPUT_STREAM_DESCRIPTOR_FORMAT_NUMBER_OF_CHANNELS_3= 0x2,
+	OUTPUT_STREAM_DESCRIPTOR_FORMAT_NUMBER_OF_CHANNELS_4= 0x3,
+	OUTPUT_STREAM_DESCRIPTOR_FORMAT_NUMBER_OF_CHANNELS_5= 0x4,
+	OUTPUT_STREAM_DESCRIPTOR_FORMAT_NUMBER_OF_CHANNELS_6= 0x5,
+	OUTPUT_STREAM_DESCRIPTOR_FORMAT_NUMBER_OF_CHANNELS_7= 0x6,
+	OUTPUT_STREAM_DESCRIPTOR_FORMAT_NUMBER_OF_CHANNELS_8= 0x7,
+	OUTPUT_STREAM_DESCRIPTOR_FORMAT_NUMBER_OF_CHANNELS_9_RESERVED= 0x8,
+	OUTPUT_STREAM_DESCRIPTOR_FORMAT_NUMBER_OF_CHANNELS_10_RESERVED= 0x9,
+	OUTPUT_STREAM_DESCRIPTOR_FORMAT_NUMBER_OF_CHANNELS_11_RESERVED= 0xa,
+	OUTPUT_STREAM_DESCRIPTOR_FORMAT_NUMBER_OF_CHANNELS_12_RESERVED= 0xb,
+	OUTPUT_STREAM_DESCRIPTOR_FORMAT_NUMBER_OF_CHANNELS_13_RESERVED= 0xc,
+	OUTPUT_STREAM_DESCRIPTOR_FORMAT_NUMBER_OF_CHANNELS_14_RESERVED= 0xd,
+	OUTPUT_STREAM_DESCRIPTOR_FORMAT_NUMBER_OF_CHANNELS_15_RESERVED= 0xe,
+	OUTPUT_STREAM_DESCRIPTOR_FORMAT_NUMBER_OF_CHANNELS_16_RESERVED= 0xf,
+} OUTPUT_STREAM_DESCRIPTOR_FORMAT_NUMBER_OF_CHANNELS;
+typedef enum AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_STREAM_TYPE {
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_STREAM_TYPE_PCM= 0x0,
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_STREAM_TYPE_NOT_PCM= 0x1,
+} AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_STREAM_TYPE;
+typedef enum AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_RATE {
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_RATE_48KHZ= 0x0,
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_RATE_44P1KHZ= 0x1,
+} AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_RATE;
+typedef enum AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_MULTIPLE {
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_MULTIPLE_BY1= 0x0,
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_MULTIPLE_BY2= 0x1,
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_MULTIPLE_BY3_RESERVED= 0x2,
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_MULTIPLE_BY4= 0x3,
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_MULTIPLE_RESERVED= 0x4,
+} AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_MULTIPLE;
+typedef enum AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_DIVISOR {
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_DIVISOR_BY1= 0x0,
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_DIVISOR_BY2_RESERVED= 0x1,
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_DIVISOR_BY3= 0x2,
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_DIVISOR_BY4_RESERVED= 0x3,
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_DIVISOR_BY5_RESERVED= 0x4,
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_DIVISOR_BY6_RESERVED= 0x5,
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_DIVISOR_BY7_RESERVED= 0x6,
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_DIVISOR_BY8_RESERVED= 0x7,
+} AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_DIVISOR;
+typedef enum AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_BITS_PER_SAMPLE {
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_BITS_PER_SAMPLE_8_RESERVED= 0x0,
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_BITS_PER_SAMPLE_16= 0x1,
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_BITS_PER_SAMPLE_20= 0x2,
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_BITS_PER_SAMPLE_24= 0x3,
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_BITS_PER_SAMPLE_32_RESERVED= 0x4,
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_BITS_PER_SAMPLE_RESERVED= 0x5,
+} AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_BITS_PER_SAMPLE;
+typedef enum AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_NUMBER_OF_CHANNELS {
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_NUMBER_OF_CHANNELS_1= 0x0,
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_NUMBER_OF_CHANNELS_2= 0x1,
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_NUMBER_OF_CHANNELS_3= 0x2,
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_NUMBER_OF_CHANNELS_4= 0x3,
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_NUMBER_OF_CHANNELS_5= 0x4,
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_NUMBER_OF_CHANNELS_6= 0x5,
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_NUMBER_OF_CHANNELS_7= 0x6,
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_NUMBER_OF_CHANNELS_8= 0x7,
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_NUMBER_OF_CHANNELS_RESERVED= 0x8,
+} AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT_NUMBER_OF_CHANNELS;
+typedef enum AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_L {
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_L_BIT7_NOT_SET= 0x0,
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_L_BIT7_IS_SET= 0x1,
+} AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_L;
+typedef enum AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_PRO {
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_PRO_BIT_A_NOT_SET= 0x0,
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_PRO_BIT_A_IS_SET= 0x1,
+} AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_PRO;
+typedef enum AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_NON_AUDIO {
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_NON_AUDIO_BIT_B_NOT_SET= 0x0,
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_NON_AUDIO_BIT_B_IS_SET= 0x1,
+} AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_NON_AUDIO;
+typedef enum AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_COPY {
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_COPY_BIT_C_IS_SET= 0x0,
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_COPY_BIT_C_NOT_SET= 0x1,
+} AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_COPY;
+typedef enum AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_PRE {
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_PRE_LSB_OF_D_NOT_SET= 0x0,
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_PRE_LSB_OF_D_IS_SET= 0x1,
+} AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_PRE;
+typedef enum AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_VCFG {
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_VALIDITY_CFG_NOT_ON= 0x0,
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_VALIDITY_CFG_ON= 0x1,
+} AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_VCFG;
+typedef enum AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_V {
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_V_BIT28_IS_ZERO= 0x0,
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_V_BIT28_IS_ONE= 0x1,
+} AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_V;
+typedef enum AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_DIGEN {
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_DIGEN_DIGITAL_TRANSMISSION_DISABLED= 0x0,
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_DIGEN_DIGITAL_TRANSMISSION_ENABLED= 0x1,
+} AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_DIGEN;
+typedef enum AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_3_KEEPALIVE {
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_3_KEEPALIVE_SILENT_STREAM_NOT_ENABLE= 0x0,
+	AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_3_KEEPALIVE_SILENT_STREAM_ENABLE= 0x1,
+} AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_3_KEEPALIVE;
+typedef enum AZALIA_F2_CODEC_PIN_CONTROL_WIDGET_CONTROL_OUT_ENABLE {
+	AZALIA_F2_CODEC_PIN_CONTROL_WIDGET_CONTROL_OUT_ENABLE_PIN_SHUT_OFF= 0x0,
+	AZALIA_F2_CODEC_PIN_CONTROL_WIDGET_CONTROL_OUT_ENABLE_PIN_DRIVEN= 0x1,
+} AZALIA_F2_CODEC_PIN_CONTROL_WIDGET_CONTROL_OUT_ENABLE;
+typedef enum AZALIA_F2_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_ENABLE {
+	AZALIA_F2_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_DISABLED= 0x0,
+	AZALIA_F2_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_ENABLED= 0x1,
+} AZALIA_F2_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_ENABLE;
+typedef enum AZALIA_F2_CODEC_PIN_CONTROL_DOWN_MIX_INFO_DOWN_MIX_INHIBIT {
+	AZALIA_F2_CODEC_PIN_CONTROL_DOWN_MIX_NO_INFO_OR_PERMITTED= 0x0,
+	AZALIA_F2_CODEC_PIN_CONTROL_DOWN_MIX_FORBIDDEN   = 0x1,
+} AZALIA_F2_CODEC_PIN_CONTROL_DOWN_MIX_INFO_DOWN_MIX_INHIBIT;
+typedef enum AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL01_ENABLE_MULTICHANNEL01_MUTE {
+	AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL01_ENABLE_MULTICHANNEL01_NOT_MUTED= 0x0,
+	AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL01_ENABLE_MULTICHANNEL01_MUTED= 0x1,
+} AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL01_ENABLE_MULTICHANNEL01_MUTE;
+typedef enum AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL23_ENABLE_MULTICHANNEL23_MUTE {
+	AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL23_ENABLE_MULTICHANNEL23_NOT_MUTED= 0x0,
+	AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL23_ENABLE_MULTICHANNEL23_MUTED= 0x1,
+} AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL23_ENABLE_MULTICHANNEL23_MUTE;
+typedef enum AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL45_ENABLE_MULTICHANNEL45_MUTE {
+	AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL45_ENABLE_MULTICHANNEL45_NOT_MUTED= 0x0,
+	AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL45_ENABLE_MULTICHANNEL45_MUTED= 0x1,
+} AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL45_ENABLE_MULTICHANNEL45_MUTE;
+typedef enum AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL67_ENABLE_MULTICHANNEL67_MUTE {
+	AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL67_ENABLE_MULTICHANNEL67_NOT_MUTED= 0x0,
+	AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL67_ENABLE_MULTICHANNEL67_MUTED= 0x1,
+} AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL67_ENABLE_MULTICHANNEL67_MUTE;
+typedef enum AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL1_ENABLE_MULTICHANNEL1_MUTE {
+	AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL1_ENABLE_MULTICHANNEL1_NOT_MUTED= 0x0,
+	AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL1_ENABLE_MULTICHANNEL1_MUTED= 0x1,
+} AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL1_ENABLE_MULTICHANNEL1_MUTE;
+typedef enum AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL3_ENABLE_MULTICHANNEL3_MUTE {
+	AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL3_ENABLE_MULTICHANNEL3_NOT_MUTED= 0x0,
+	AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL3_ENABLE_MULTICHANNEL3_MUTED= 0x1,
+} AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL3_ENABLE_MULTICHANNEL3_MUTE;
+typedef enum AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL5_ENABLE_MULTICHANNEL5_MUTE {
+	AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL5_ENABLE_MULTICHANNEL5_NOT_MUTED= 0x0,
+	AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL5_ENABLE_MULTICHANNEL5_MUTED= 0x1,
+} AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL5_ENABLE_MULTICHANNEL5_MUTE;
+typedef enum AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL7_ENABLE_MULTICHANNEL7_MUTE {
+	AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL7_ENABLE_MULTICHANNEL7_NOT_MUTED= 0x0,
+	AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL7_ENABLE_MULTICHANNEL7_MUTED= 0x1,
+} AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL7_ENABLE_MULTICHANNEL7_MUTE;
+typedef enum AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL_MODE_MULTICHANNEL_MODE {
+	AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL_MODE_MULTICHANNEL_PAIR_MODE= 0x0,
+	AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL_MODE_MULTICHANNEL_SINGLE_MODE= 0x1,
+} AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL_MODE_MULTICHANNEL_MODE;
+typedef enum AZ_LATENCY_COUNTER_CONTROL {
+	AZ_LATENCY_COUNTER_NO_RESET                      = 0x0,
+	AZ_LATENCY_COUNTER_RESET_DONE                    = 0x1,
+} AZ_LATENCY_COUNTER_CONTROL;
+typedef enum AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE {
+	AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_OUTPUT_CONVERTER_RESERVED= 0x0,
+	AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_INPUT_CONVERTER_RESERVED= 0x1,
+	AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_MIXER_RESERVED= 0x2,
+	AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_SELECTOR_RESERVED= 0x3,
+	AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_PIN_RESERVED= 0x4,
+	AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_POWER_WIDGET_RESERVED= 0x5,
+	AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_VOLUME_KNOB_RESERVED= 0x6,
+	AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_BEEP_GENERATOR_RESERVED= 0x7,
+	AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_RESERVED_RESERVED= 0x8,
+	AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_VENDOR_DEFINED_RESERVED= 0x9,
+} AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE;
+typedef enum AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_LR_SWAP {
+	AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_NO_LR_SWAP_CAPABILITY= 0x0,
+	AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_HAVE_LR_SWAP_CAPABILITY= 0x1,
+} AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_LR_SWAP;
+typedef enum AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_POWER_CONTROL {
+	AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_NO_POWER_CONTROL_CAPABILITY= 0x0,
+	AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_HAVE_POWER_CONTROL_CAPABILITY= 0x1,
+} AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_POWER_CONTROL;
+typedef enum AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_DIGITAL {
+	AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_IS_ANALOG= 0x0,
+	AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_IS_DIGITAL= 0x1,
+} AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_DIGITAL;
+typedef enum AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_CONNECTION_LIST {
+	AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_NO_CONNECTION_LIST= 0x0,
+	AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_HAVE_CONNECTION_LIST= 0x1,
+} AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_CONNECTION_LIST;
+typedef enum AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_UNSOLICITED_RESPONSE_CAPABILITY {
+	AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_NO_UNSOLICITED_RESPONSE_CAPABILITY= 0x0,
+	AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_HAVE_UNSOLICITED_RESPONSE_CAPABILITY= 0x1,
+} AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_UNSOLICITED_RESPONSE_CAPABILITY;
+typedef enum AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_PROCESSING_WIDGET {
+	AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_PROCESSING_WIDGET_NO_PROCESSING_CAPABILITIES= 0x0,
+	AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_PROCESSING_WIDGET_HAVE_PROCESSING_CAPABILITIES= 0x1,
+} AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_PROCESSING_WIDGET;
+typedef enum AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_STRIPE {
+	AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_NO_SUPPORT_STRIPING= 0x0,
+	AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_SUPPORT_STRIPING= 0x1,
+} AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_STRIPE;
+typedef enum AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_FORMAT_OVERRIDE {
+	AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_NO_FORMAT_OVERRIDE= 0x0,
+	AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_SUPPORT_FORMAT_OVERRIDE= 0x1,
+} AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_FORMAT_OVERRIDE;
+typedef enum AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_AMPLIFIER_PARAMETER_OVERRIDE {
+	AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_NO_AMPLIFIER_PARAMETER= 0x0,
+	AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_HAVE_AMPLIFIER_PARAMETER_OVERRIDE= 0x1,
+} AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_AMPLIFIER_PARAMETER_OVERRIDE;
+typedef enum AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_OUTPUT_AMPLIFIER_PRESENT {
+	AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_NO_OUTPUT_AMPLIFIER= 0x0,
+	AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_HAVE_OUTPUT_AMPLIFIER= 0x1,
+} AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_OUTPUT_AMPLIFIER_PRESENT;
+typedef enum AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_INPUT_AMPLIFIER_PRESENT {
+	AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_NO_INPUT_AMPLIFIER= 0x0,
+	AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_HAVE_INPUT_AMPLIFIER= 0x1,
+} AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_INPUT_AMPLIFIER_PRESENT;
+typedef enum AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_AUDIO_CHANNEL_CAPABILITIES {
+	AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_AUDIO_CHANNEL_CAPABILITIES_MONOPHONIC= 0x0,
+	AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_AUDIO_CHANNEL_CAPABILITIES_STEREO= 0x1,
+} AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_AUDIO_CHANNEL_CAPABILITIES;
+typedef enum AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE {
+	AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_OUTPUT_CONVERTER_RESERVED= 0x0,
+	AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_INPUT_CONVERTER_RESERVED= 0x1,
+	AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_MIXER_RESERVED= 0x2,
+	AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_SELECTOR_RESERVED= 0x3,
+	AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_PIN_RESERVED= 0x4,
+	AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_POWER_WIDGET_RESERVED= 0x5,
+	AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_VOLUME_KNOB_RESERVED= 0x6,
+	AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_BEEP_GENERATOR_RESERVED= 0x7,
+	AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_RESERVED_RESERVED= 0x8,
+	AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_VENDOR_DEFINED_RESERVED= 0x9,
+} AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE;
+typedef enum AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_LR_SWAP {
+	AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_NO_LR_SWAP_CAPABILITY= 0x0,
+	AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_HAVE_LR_SWAP_CAPABILITY= 0x1,
+} AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_LR_SWAP;
+typedef enum AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_POWER_CONTROL {
+	AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_NO_POWER_CONTROL_CAPABILITY= 0x0,
+	AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_HAVE_POWER_CONTROL_CAPABILITY= 0x1,
+} AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_POWER_CONTROL;
+typedef enum AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_DIGITAL {
+	AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_IS_ANALOG= 0x0,
+	AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_IS_DIGITAL= 0x1,
+} AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_DIGITAL;
+typedef enum AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_CONNECTION_LIST {
+	AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_NO_CONNECTION_LIST= 0x0,
+	AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_HAVE_CONNECTION_LIST= 0x1,
+} AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_CONNECTION_LIST;
+typedef enum AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_UNSOLICITED_RESPONSE_CAPABILITY {
+	AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_NO_UNSOLICITED_RESPONSE_CAPABILITY= 0x0,
+	AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_HAVE_UNSOLICITED_RESPONSE_CAPABILITY= 0x1,
+} AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_UNSOLICITED_RESPONSE_CAPABILITY;
+typedef enum AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_PROCESSING_WIDGET {
+	AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_PROCESSING_WIDGET_NO_PROCESSING_CAPABILITIES= 0x0,
+	AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_PROCESSING_WIDGET_HAVE_PROCESSING_CAPABILITIES= 0x1,
+} AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_PROCESSING_WIDGET;
+typedef enum AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_STRIPE {
+	AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_NO_SUPPORT_STRIPING= 0x0,
+	AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_SUPPORT_STRIPING= 0x1,
+} AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_STRIPE;
+typedef enum AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_AMPLIFIER_PARAMETER_OVERRIDE {
+	AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_NO_AMPLIFIER_PARAMETER= 0x0,
+	AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_HAVE_AMPLIFIER_PARAMETER_OVERRIDE= 0x1,
+} AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_AMPLIFIER_PARAMETER_OVERRIDE;
+typedef enum AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_OUTPUT_AMPLIFIER_PRESENT {
+	AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_NO_OUTPUT_AMPLIFIER= 0x0,
+	AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_HAVE_OUTPUT_AMPLIFIER= 0x1,
+} AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_OUTPUT_AMPLIFIER_PRESENT;
+typedef enum AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_INPUT_AMPLIFIER_PRESENT {
+	AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_NO_INPUT_AMPLIFIER_PRESENT= 0x0,
+	AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_HAVE_INPUT_AMPLIFIER= 0x1,
+} AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_INPUT_AMPLIFIER_PRESENT;
+typedef enum AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES_EAPD_CAPABLE {
+	AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES_NO_EAPD_PIN= 0x0,
+	AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES_HAVE_EAPD_PIN= 0x1,
+} AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES_EAPD_CAPABLE;
+typedef enum AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES_BALANCED_I_O_PINS {
+	AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES_I_O_PINS_ARE_NOT_BALANCED= 0x0,
+	AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES_I_O_PINS_ARE_BALANCED= 0x1,
+} AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES_BALANCED_I_O_PINS;
+typedef enum AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES_INPUT_CAPABLE {
+	AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES_NO_INPUT_PIN= 0x0,
+	AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES_HAVE_INPUT_PIN= 0x1,
+} AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES_INPUT_CAPABLE;
+typedef enum AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES_OUTPUT_CAPABLE {
+	AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES_NO_OUTPUT_PIN= 0x0,
+	AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES_HAVE_OUTPUT_PIN= 0x1,
+} AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES_OUTPUT_CAPABLE;
+typedef enum AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES_HEADPHONE_DRIVE_CAPABLE {
+	AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES_NO_HEADPHONE_DRIVE_CAPABILITY= 0x0,
+	AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES_HAVE_HEADPHONE_DRIVE_CAPABILITY= 0x1,
+} AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES_HEADPHONE_DRIVE_CAPABLE;
+typedef enum AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES_JACK_DETECTION_CAPABILITY {
+	AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES_NO_JACK_DETECTION_CAPABILITY= 0x0,
+	AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES_HAVE_JACK_DETECTION_CAPABILITY= 0x1,
+} AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES_JACK_DETECTION_CAPABILITY;
+typedef enum AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES_TRIGGER_REQUIRED {
+	AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES_NO_TRIGGER_REQUIRED_FOR_IMPEDANCE_MEASUREMENT= 0x0,
+	AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES_TRIGGER_REQUIRED_FOR_IMPEDANCE_MEASUREMENT= 0x1,
+} AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES_TRIGGER_REQUIRED;
+typedef enum AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES_IMPEDANCE_SENSE_CAPABLE {
+	AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES_NO_IMPEDANCE_SENSE_CAPABILITY= 0x0,
+	AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES_HAVE_IMPEDANCE_SENSE_CAPABILITY= 0x1,
+} AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES_IMPEDANCE_SENSE_CAPABLE;
+typedef enum AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_MODE_MULTICHANNEL_MODE {
+	AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_MODE_MULTICHANNEL_PAIR_MODE= 0x0,
+	AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_MODE_MULTICHANNEL_SINGLE_MODE= 0x1,
+} AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_MODE_MULTICHANNEL_MODE;
+typedef enum AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR_HBR_CAPABLE {
+	AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR_NO_HBR_CAPABLILITY= 0x0,
+	AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR_HAVE_HBR_CAPABLILITY= 0x1,
+} AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR_HBR_CAPABLE;
+typedef enum AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE {
+	AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_OUTPUT_CONVERTER_RESERVED= 0x0,
+	AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_INPUT_CONVERTER_RESERVED= 0x1,
+	AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_MIXER_RESERVED= 0x2,
+	AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_SELECTOR_RESERVED= 0x3,
+	AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_PIN_RESERVED= 0x4,
+	AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_POWER_WIDGET_RESERVED= 0x5,
+	AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_VOLUME_KNOB_RESERVED= 0x6,
+	AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_BEEP_GENERATOR_RESERVED= 0x7,
+	AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_RESERVED= 0x8,
+	AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_VENDOR_DEFINED_RESERVED= 0x9,
+} AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE;
+typedef enum AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_LR_SWAP {
+	AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_NO_LR_SWAP_CAPABILITY= 0x0,
+	AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_HAVE_LR_SWAP_CAPABILITY= 0x1,
+} AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_LR_SWAP;
+typedef enum AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_POWER_CONTROL {
+	AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_NO_POWER_CONTROL_CAPABILITY= 0x0,
+	AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_HAVE_POWER_CONTROL_CAPABILITY= 0x1,
+} AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_POWER_CONTROL;
+typedef enum AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_DIGITAL {
+	AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_CODEC_CONVERTER0_IS_ANALOG= 0x0,
+	AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_CODEC_CONVERTER0_IS_DIGITAL= 0x1,
+} AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_DIGITAL;
+typedef enum AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_CONNECTION_LIST {
+	AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_NO_CONNECTION_LIST= 0x0,
+	AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_HAVE_CONNECTION_LIST= 0x1,
+} AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_CONNECTION_LIST;
+typedef enum AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_UNSOLICITED_RESPONSE_CAPABILITY {
+	AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_NO_UNSOLICITED_RESPONSE_CAPABILITY= 0x0,
+	AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_HAVE_UNSOLICITED_RESPONSE_CAPABILITY= 0x1,
+} AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_UNSOLICITED_RESPONSE_CAPABILITY;
+typedef enum AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_PROCESSING_WIDGET {
+	AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_PROCESSING_WIDGET_CODEC_CONVERTER0_HAVE_NO_PROCESSING_CAPABILITIES= 0x0,
+	AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_PROCESSING_WIDGET_CODEC_CONVERTER0_HAVE_PROCESSING_CAPABILITIES= 0x1,
+} AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_PROCESSING_WIDGET;
+typedef enum AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_STRIPE {
+	AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_NOT_SUPPORT_STRIPING= 0x0,
+	AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_SUPPORT_STRIPING= 0x1,
+} AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_STRIPE;
+typedef enum AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_FORMAT_OVERRIDE {
+	AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_NO_FORMAT_OVERRIDE= 0x0,
+	AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_HAVE_FORMAT_OVERRIDE= 0x1,
+} AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_FORMAT_OVERRIDE;
+typedef enum AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_AMPLIFIER_PARAMETER_OVERRIDE {
+	AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_NO_AMPLIFIER_PARAMETER= 0x0,
+	AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_HAVE_AMPLIFIER_PARAMETER= 0x1,
+} AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_AMPLIFIER_PARAMETER_OVERRIDE;
+typedef enum AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_OUTPUT_AMPLIFIER_PRESENT {
+	AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_NO_OUTPUT_AMPLIFIER= 0x0,
+	AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_HAVE_OUTPUT_AMPLIFIER= 0x1,
+} AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_OUTPUT_AMPLIFIER_PRESENT;
+typedef enum AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_INPUT_AMPLIFIER_PRESENT {
+	AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_NO_INPUT_AMPLIFIER= 0x0,
+	AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_HAVE_INPUT_AMPLIFIER= 0x1,
+} AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_INPUT_AMPLIFIER_PRESENT;
+typedef enum AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_AUDIO_CHANNEL_CAPABILITIES {
+	AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_AUDIO_CHANNEL_CAPABILITIES_MONOPHONIC= 0x0,
+	AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_AUDIO_CHANNEL_CAPABILITIES_STEREO= 0x1,
+} AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES_AUDIO_CHANNEL_CAPABILITIES;
+typedef enum AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE {
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_OUTPUT_CONVERTER_RESERVED= 0x0,
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_INPUT_CONVERTER_RESERVED= 0x1,
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_MIXER_RESERVED= 0x2,
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_SELECTOR_RESERVED= 0x3,
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_PIN_RESERVED= 0x4,
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_POWER_WIDGET_RESERVED= 0x5,
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_VOLUME_KNOB_RESERVED= 0x6,
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_BEEP_GENERATOR_RESERVED= 0x7,
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_RESERVED= 0x8,
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE_VENDOR_DEFINED_RESERVED= 0x9,
+} AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_TYPE;
+typedef enum AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_LR_SWAP {
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_NO_LR_SWAP= 0x0,
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_HAVE_LR_SWAP= 0x1,
+} AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_LR_SWAP;
+typedef enum AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_POWER_CONTROL {
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_NO_POWER_CONTROL_CAPABILITY= 0x0,
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_HAVE_POWER_CONTROL_CAPABILITY= 0x1,
+} AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_POWER_CONTROL;
+typedef enum AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_DIGITAL {
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_IS_ANALOG= 0x0,
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_IS_DIGITAL= 0x1,
+} AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_DIGITAL;
+typedef enum AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_CONNECTION_LIST {
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_NO_CONNECTION_LIST= 0x0,
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_HAVE_CONNECTION_LIST= 0x1,
+} AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_CONNECTION_LIST;
+typedef enum AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_UNSOLICITED_RESPONSE_CAPABILITY {
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_NO_UNSOLICITED_RESPONSE_CAPABILITY= 0x0,
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_HAVE_UNSOLICITED_RESPONSE_CAPABILITY= 0x1,
+} AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_UNSOLICITED_RESPONSE_CAPABILITY;
+typedef enum AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_PROCESSING_WIDGET {
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_PROCESSING_WIDGET_NO_PROCESING_CAPABILITIES= 0x0,
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_PROCESSING_WIDGET_HAVE_PROCESING_CAPABILITIES= 0x1,
+} AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_PROCESSING_WIDGET;
+typedef enum AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_STRIPE {
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_NO_SUPPORT_STRIPING= 0x0,
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_SUPPORT_STRIPING= 0x1,
+} AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_STRIPE;
+typedef enum AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_AMPLIFIER_PARAMETER_OVERRIDE {
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_NO_AMPLIFIER_PARAMETER= 0x0,
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_HAVE_AMPLIFIER_PARAMETER_OVERRIDE= 0x1,
+} AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_AMPLIFIER_PARAMETER_OVERRIDE;
+typedef enum AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_OUTPUT_AMPLIFIER_PRESENT {
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_NO_OUTPUT_AMPLIFIER= 0x0,
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_HAVE_OUTPUT_AMPLIFIER= 0x1,
+} AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_OUTPUT_AMPLIFIER_PRESENT;
+typedef enum AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_INPUT_AMPLIFIER_PRESENT {
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_NO_INPUT_AMPLIFIER= 0x0,
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_HAVE_INPUT_AMPLIFIER= 0x1,
+} AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES_INPUT_AMPLIFIER_PRESENT;
+typedef enum AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_DP {
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_DP_NOT_ENABLED= 0x0,
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_DP_ENABLED= 0x1,
+} AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_DP;
+typedef enum AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_EAPD_CAPABLE {
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_EAPD_CAPABLE_NO_EAPD_PIN= 0x0,
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_EAPD_CAPABLE_HAVE_EAPD_PIN= 0x1,
+} AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_EAPD_CAPABLE;
+typedef enum AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_HDMI {
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_HDMI_NOT_ENABLED= 0x0,
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_HDMI_ENABLED= 0x1,
+} AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_HDMI;
+typedef enum AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_BALANCED_I_O_PINS {
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_I_O_PINS_NOT_BALANCED= 0x0,
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_I_O_PINS_ARE_BALANCED= 0x1,
+} AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_BALANCED_I_O_PINS;
+typedef enum AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_INPUT_CAPABLE {
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_NO_INPUT_PIN= 0x0,
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_HAVE_INPUT_PIN= 0x1,
+} AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_INPUT_CAPABLE;
+typedef enum AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_OUTPUT_CAPABLE {
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_NO_OUTPUT_PIN= 0x0,
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_HAVE_OUTPUT_PIN= 0x1,
+} AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_OUTPUT_CAPABLE;
+typedef enum AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_HEADPHONE_DRIVE_CAPABLE {
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_NO_HEADPHONE_DRIVE_CAPABILITY= 0x0,
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_HAVE_HEADPHONE_DRIVE_CAPABILITY= 0x1,
+} AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_HEADPHONE_DRIVE_CAPABLE;
+typedef enum AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_JACK_DETECTION_CAPABILITY {
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_NO_JACK_PRESENCE_DETECTION_CAPABILITY= 0x0,
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_HAVE_JACK_PRESENCE_DETECTION_CAPABILITY= 0x1,
+} AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_JACK_DETECTION_CAPABILITY;
+typedef enum AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_TRIGGER_REQUIRED {
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_NO_TRIGGER_REQUIRED_FOR_IMPEDANCE_MEASUREMENT= 0x0,
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_TRIGGER_REQUIRED_FOR_IMPEDANCE_MEASUREMENT= 0x1,
+} AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_TRIGGER_REQUIRED;
+typedef enum AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_IMPEDANCE_SENSE_CAPABLE {
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_NO_IMPEDANCE_SENSE_CAPABILITY= 0x0,
+	AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_HAVE_IMPEDANCE_SENSE_CAPABILITY= 0x1,
+} AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES_IMPEDANCE_SENSE_CAPABLE;
+typedef enum AZALIA_F0_CODEC_INPUT_PIN_CONTROL_RESPONSE_HBR_HBR_CAPABLE {
+	AZALIA_F0_CODEC_INPUT_PIN_CONTROL_RESPONSE_HBR_NO_HBR_CAPABILITY= 0x0,
+	AZALIA_F0_CODEC_INPUT_PIN_CONTROL_RESPONSE_HBR_HAVE_HBR_CAPABILITY= 0x1,
+} AZALIA_F0_CODEC_INPUT_PIN_CONTROL_RESPONSE_HBR_HBR_CAPABLE;
+typedef enum AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_STREAM_TYPE {
+	AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_STREAM_TYPE_PCM= 0x0,
+	AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_STREAM_TYPE_NOT_PCM= 0x1,
+} AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_STREAM_TYPE;
+typedef enum AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_RATE {
+	AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_RATE_48KHZ= 0x0,
+	AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_RATE_44P1KHZ= 0x1,
+} AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_RATE;
+typedef enum AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_MULTIPLE {
+	AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_MULTIPLE_BY1= 0x0,
+	AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_MULTIPLE_BY2= 0x1,
+	AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_MULTIPLE_BY3_RESERVED= 0x2,
+	AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_MULTIPLE_BY4= 0x3,
+	AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_MULTIPLE_RESERVED= 0x4,
+} AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_MULTIPLE;
+typedef enum AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_DIVISOR {
+	AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_DIVISOR_BY1= 0x0,
+	AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_DIVISOR_BY2_RESERVED= 0x1,
+	AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_DIVISOR_BY3= 0x2,
+	AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_DIVISOR_BY4_RESERVED= 0x3,
+	AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_DIVISOR_BY5_RESERVED= 0x4,
+	AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_DIVISOR_BY6_RESERVED= 0x5,
+	AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_DIVISOR_BY7_RESERVED= 0x6,
+	AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_DIVISOR_BY8_RESERVED= 0x7,
+} AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_SAMPLE_BASE_DIVISOR;
+typedef enum AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_BITS_PER_SAMPLE {
+	AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_BITS_PER_SAMPLE_8_RESERVED= 0x0,
+	AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_BITS_PER_SAMPLE_16= 0x1,
+	AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_BITS_PER_SAMPLE_20= 0x2,
+	AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_BITS_PER_SAMPLE_24= 0x3,
+	AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_BITS_PER_SAMPLE_32_RESERVED= 0x4,
+	AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_BITS_PER_SAMPLE_RESERVED= 0x5,
+} AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_BITS_PER_SAMPLE;
+typedef enum AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_NUMBER_OF_CHANNELS {
+	AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_NUMBER_OF_CHANNELS_1= 0x0,
+	AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_NUMBER_OF_CHANNELS_2= 0x1,
+	AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_NUMBER_OF_CHANNELS_3= 0x2,
+	AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_NUMBER_OF_CHANNELS_4= 0x3,
+	AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_NUMBER_OF_CHANNELS_5= 0x4,
+	AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_NUMBER_OF_CHANNELS_6= 0x5,
+	AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_NUMBER_OF_CHANNELS_7= 0x6,
+	AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_NUMBER_OF_CHANNELS_8= 0x7,
+	AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_NUMBER_OF_CHANNELS_RESERVED= 0x8,
+} AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT_NUMBER_OF_CHANNELS;
+typedef enum AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER_DIGEN {
+	AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER_DIGEN_DIGITAL_TRANSMISSION_DISABLED= 0x0,
+	AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER_DIGEN_DIGITAL_TRANSMISSION_ENABLED= 0x1,
+} AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER_DIGEN;
+typedef enum AZALIA_F2_CODEC_INPUT_PIN_CONTROL_WIDGET_CONTROL_IN_ENABLE {
+	AZALIA_F2_CODEC_INPUT_PIN_CONTROL_WIDGET_CONTROL_IN_ENABLE_PIN_SHUT_OFF= 0x0,
+	AZALIA_F2_CODEC_INPUT_PIN_CONTROL_WIDGET_CONTROL_IN_ENABLE_PIN_DRIVEN= 0x1,
+} AZALIA_F2_CODEC_INPUT_PIN_CONTROL_WIDGET_CONTROL_IN_ENABLE;
+typedef enum AZALIA_F2_CODEC_INPUT_PIN_CONTROL_UNSOLICITED_RESPONSE_ENABLE {
+	AZALIA_F2_CODEC_INPUT_PIN_CONTROL_UNSOLICITED_RESPONSE_DISABLED= 0x0,
+	AZALIA_F2_CODEC_INPUT_PIN_CONTROL_UNSOLICITED_RESPONSE_ENABLED= 0x1,
+} AZALIA_F2_CODEC_INPUT_PIN_CONTROL_UNSOLICITED_RESPONSE_ENABLE;
+typedef enum AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL0_ENABLE_MULTICHANNEL0_MUTE {
+	AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL0_ENABLE_MULTICHANNEL0_NOT_MUTED= 0x0,
+	AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL0_ENABLE_MULTICHANNEL0_MUTED= 0x1,
+} AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL0_ENABLE_MULTICHANNEL0_MUTE;
+typedef enum AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL1_ENABLE_MULTICHANNEL1_MUTE {
+	AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL1_ENABLE_MULTICHANNEL1_NOT_MUTED= 0x0,
+	AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL1_ENABLE_MULTICHANNEL1_MUTED= 0x1,
+} AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL1_ENABLE_MULTICHANNEL1_MUTE;
+typedef enum AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL2_ENABLE_MULTICHANNEL2_MUTE {
+	AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL2_ENABLE_MULTICHANNEL2_NOT_MUTED= 0x0,
+	AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL2_ENABLE_MULTICHANNEL2_MUTED= 0x1,
+} AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL2_ENABLE_MULTICHANNEL2_MUTE;
+typedef enum AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL3_ENABLE_MULTICHANNEL3_MUTE {
+	AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL3_ENABLE_MULTICHANNEL3_NOT_MUTED= 0x0,
+	AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL3_ENABLE_MULTICHANNEL3_MUTED= 0x1,
+} AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL3_ENABLE_MULTICHANNEL3_MUTE;
+typedef enum AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL4_ENABLE_MULTICHANNEL4_MUTE {
+	AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL4_ENABLE_MULTICHANNEL4_NOT_MUTED= 0x0,
+	AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL4_ENABLE_MULTICHANNEL4_MUTED= 0x1,
+} AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL4_ENABLE_MULTICHANNEL4_MUTE;
+typedef enum AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL5_ENABLE_MULTICHANNEL5_MUTE {
+	AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL5_ENABLE_MULTICHANNEL5_NOT_MUTED= 0x0,
+	AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL5_ENABLE_MULTICHANNEL5_MUTED= 0x1,
+} AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL5_ENABLE_MULTICHANNEL5_MUTE;
+typedef enum AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL6_ENABLE_MULTICHANNEL6_MUTE {
+	AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL6_ENABLE_MULTICHANNEL6_NOT_MUTED= 0x0,
+	AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL6_ENABLE_MULTICHANNEL6_MUTED= 0x1,
+} AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL6_ENABLE_MULTICHANNEL6_MUTE;
+typedef enum AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL7_ENABLE_MULTICHANNEL7_MUTE {
+	AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL7_ENABLE_MULTICHANNEL7_NOT_MUTED= 0x0,
+	AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL7_ENABLE_MULTICHANNEL7_MUTED= 0x1,
+} AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL7_ENABLE_MULTICHANNEL7_MUTE;
+typedef enum BLND_CONTROL_BLND_MODE {
+	BLND_CONTROL_BLND_MODE_CURRENT_PIPE_ONLY         = 0x0,
+	BLND_CONTROL_BLND_MODE_OTHER_PIPE_ONLY           = 0x1,
+	BLND_CONTROL_BLND_MODE_ALPHA_BLENDING_MODE       = 0x2,
+	BLND_CONTROL_BLND_MODE_OTHER_STEREO_TYPE         = 0x3,
+} BLND_CONTROL_BLND_MODE;
+typedef enum BLND_CONTROL_BLND_STEREO_TYPE {
+	BLND_CONTROL_BLND_STEREO_TYPE_NON_SINGLE_PIPE_STEREO= 0x0,
+	BLND_CONTROL_BLND_STEREO_TYPE_SIDE_BY_SIDE_SINGLE_PIPE_STEREO= 0x1,
+	BLND_CONTROL_BLND_STEREO_TYPE_TOP_BOTTOM_SINGLE_PIPE_STEREO= 0x2,
+	BLND_CONTROL_BLND_STEREO_TYPE_UNUSED             = 0x3,
+} BLND_CONTROL_BLND_STEREO_TYPE;
+typedef enum BLND_CONTROL_BLND_STEREO_POLARITY {
+	BLND_CONTROL_BLND_STEREO_POLARITY_LOW            = 0x0,
+	BLND_CONTROL_BLND_STEREO_POLARITY_HIGH           = 0x1,
+} BLND_CONTROL_BLND_STEREO_POLARITY;
+typedef enum BLND_CONTROL_BLND_FEEDTHROUGH_EN {
+	BLND_CONTROL_BLND_FEEDTHROUGH_EN_FALSE           = 0x0,
+	BLND_CONTROL_BLND_FEEDTHROUGH_EN_TRUE            = 0x1,
+} BLND_CONTROL_BLND_FEEDTHROUGH_EN;
+typedef enum BLND_CONTROL_BLND_ALPHA_MODE {
+	BLND_CONTROL_BLND_ALPHA_MODE_CURRENT_PIXEL_ALPHA = 0x0,
+	BLND_CONTROL_BLND_ALPHA_MODE_PIXEL_ALPHA_COMBINED_GLOBAL_GAIN= 0x1,
+	BLND_CONTROL_BLND_ALPHA_MODE_GLOBAL_ALPHA_ONLY   = 0x2,
+	BLND_CONTROL_BLND_ALPHA_MODE_UNUSED              = 0x3,
+} BLND_CONTROL_BLND_ALPHA_MODE;
+typedef enum BLND_CONTROL_BLND_ACTIVE_OVERLAP_ONLY {
+	BLND_CONTROL_BLND_ACTIVE_OVERLAY_ONLY_FALSE      = 0x0,
+	BLND_CONTROL_BLND_ACTIVE_OVERLAY_ONLY_TRUE       = 0x1,
+} BLND_CONTROL_BLND_ACTIVE_OVERLAP_ONLY;
+typedef enum BLND_CONTROL_BLND_MULTIPLIED_MODE {
+	BLND_CONTROL_BLND_MULTIPLIED_MODE_FALSE          = 0x0,
+	BLND_CONTROL_BLND_MULTIPLIED_MODE_TRUE           = 0x1,
+} BLND_CONTROL_BLND_MULTIPLIED_MODE;
+typedef enum BLND_SM_CONTROL2_SM_MODE {
+	BLND_SM_CONTROL2_SM_MODE_SINGLE_PLANE            = 0x0,
+	BLND_SM_CONTROL2_SM_MODE_ROW_SUBSAMPLING         = 0x2,
+	BLND_SM_CONTROL2_SM_MODE_COLUMN_SUBSAMPLING      = 0x4,
+	BLND_SM_CONTROL2_SM_MODE_CHECKERBOARD_SUBSAMPLING= 0x6,
+} BLND_SM_CONTROL2_SM_MODE;
+typedef enum BLND_SM_CONTROL2_SM_FRAME_ALTERNATE {
+	BLND_SM_CONTROL2_SM_FRAME_ALTERNATE_FALSE        = 0x0,
+	BLND_SM_CONTROL2_SM_FRAME_ALTERNATE_TRUE         = 0x1,
+} BLND_SM_CONTROL2_SM_FRAME_ALTERNATE;
+typedef enum BLND_SM_CONTROL2_SM_FIELD_ALTERNATE {
+	BLND_SM_CONTROL2_SM_FIELD_ALTERNATE_FALSE        = 0x0,
+	BLND_SM_CONTROL2_SM_FIELD_ALTERNATE_TRUE         = 0x1,
+} BLND_SM_CONTROL2_SM_FIELD_ALTERNATE;
+typedef enum BLND_SM_CONTROL2_SM_FORCE_NEXT_FRAME_POL {
+	BLND_SM_CONTROL2_SM_FORCE_NEXT_FRAME_POL_NO_FORCE= 0x0,
+	BLND_SM_CONTROL2_SM_FORCE_NEXT_FRAME_POL_RESERVED= 0x1,
+	BLND_SM_CONTROL2_SM_FORCE_NEXT_FRAME_POL_FORCE_LOW= 0x2,
+	BLND_SM_CONTROL2_SM_FORCE_NEXT_FRAME_POL_FORCE_HIGH= 0x3,
+} BLND_SM_CONTROL2_SM_FORCE_NEXT_FRAME_POL;
+typedef enum BLND_SM_CONTROL2_SM_FORCE_NEXT_TOP_POL {
+	BLND_SM_CONTROL2_SM_FORCE_NEXT_TOP_POL_NO_FORCE  = 0x0,
+	BLND_SM_CONTROL2_SM_FORCE_NEXT_TOP_POL_RESERVED  = 0x1,
+	BLND_SM_CONTROL2_SM_FORCE_NEXT_TOP_POL_FORCE_LOW = 0x2,
+	BLND_SM_CONTROL2_SM_FORCE_NEXT_TOP_POL_FORCE_HIGH= 0x3,
+} BLND_SM_CONTROL2_SM_FORCE_NEXT_TOP_POL;
+typedef enum BLND_CONTROL2_PTI_ENABLE {
+	BLND_CONTROL2_PTI_ENABLE_FALSE                   = 0x0,
+	BLND_CONTROL2_PTI_ENABLE_TRUE                    = 0x1,
+} BLND_CONTROL2_PTI_ENABLE;
+typedef enum BLND_CONTROL2_BLND_SUPERAA_DEGAMMA_EN {
+	BLND_CONTROL2_BLND_SUPERAA_DEGAMMA_EN_FALSE      = 0x0,
+	BLND_CONTROL2_BLND_SUPERAA_DEGAMMA_EN_TRUE       = 0x1,
+} BLND_CONTROL2_BLND_SUPERAA_DEGAMMA_EN;
+typedef enum BLND_CONTROL2_BLND_SUPERAA_REGAMMA_EN {
+	BLND_CONTROL2_BLND_SUPERAA_REGAMMA_EN_FALSE      = 0x0,
+	BLND_CONTROL2_BLND_SUPERAA_REGAMMA_EN_TRUE       = 0x1,
+} BLND_CONTROL2_BLND_SUPERAA_REGAMMA_EN;
+typedef enum BLND_UNDERFLOW_INTERRUPT_BLND_UNDERFLOW_INT_ACK {
+	BLND_UNDERFLOW_INTERRUPT_BLND_UNDERFLOW_INT_ACK_FALSE= 0x0,
+	BLND_UNDERFLOW_INTERRUPT_BLND_UNDERFLOW_INT_ACK_TRUE= 0x1,
+} BLND_UNDERFLOW_INTERRUPT_BLND_UNDERFLOW_INT_ACK;
+typedef enum BLND_UNDERFLOW_INTERRUPT_BLND_UNDERFLOW_INT_MASK {
+	BLND_UNDERFLOW_INTERRUPT_BLND_UNDERFLOW_INT_MASK_FALSE= 0x0,
+	BLND_UNDERFLOW_INTERRUPT_BLND_UNDERFLOW_INT_MASK_TRUE= 0x1,
+} BLND_UNDERFLOW_INTERRUPT_BLND_UNDERFLOW_INT_MASK;
+typedef enum BLND_V_UPDATE_LOCK_BLND_DCP_GRPH_V_UPDATE_LOCK {
+	BLND_V_UPDATE_LOCK_BLND_DCP_GRPH_V_UPDATE_LOCK_FALSE= 0x0,
+	BLND_V_UPDATE_LOCK_BLND_DCP_GRPH_V_UPDATE_LOCK_TRUE= 0x1,
+} BLND_V_UPDATE_LOCK_BLND_DCP_GRPH_V_UPDATE_LOCK;
+typedef enum BLND_V_UPDATE_LOCK_BLND_DCP_GRPH_SURF_V_UPDATE_LOCK {
+	BLND_V_UPDATE_LOCK_BLND_DCP_GRPH_SURF_V_UPDATE_LOCK_FALSE= 0x0,
+	BLND_V_UPDATE_LOCK_BLND_DCP_GRPH_SURF_V_UPDATE_LOCK_TRUE= 0x1,
+} BLND_V_UPDATE_LOCK_BLND_DCP_GRPH_SURF_V_UPDATE_LOCK;
+typedef enum BLND_V_UPDATE_LOCK_BLND_DCP_CUR_V_UPDATE_LOCK {
+	BLND_V_UPDATE_LOCK_BLND_DCP_CUR_V_UPDATE_LOCK_FALSE= 0x0,
+	BLND_V_UPDATE_LOCK_BLND_DCP_CUR_V_UPDATE_LOCK_TRUE= 0x1,
+} BLND_V_UPDATE_LOCK_BLND_DCP_CUR_V_UPDATE_LOCK;
+typedef enum BLND_V_UPDATE_LOCK_BLND_DCP_CUR2_V_UPDATE_LOCK {
+	BLND_V_UPDATE_LOCK_BLND_DCP_CUR2_V_UPDATE_LOCK_FALSE= 0x0,
+	BLND_V_UPDATE_LOCK_BLND_DCP_CUR2_V_UPDATE_LOCK_TRUE= 0x1,
+} BLND_V_UPDATE_LOCK_BLND_DCP_CUR2_V_UPDATE_LOCK;
+typedef enum BLND_V_UPDATE_LOCK_BLND_SCL_V_UPDATE_LOCK {
+	BLND_V_UPDATE_LOCK_BLND_SCL_V_UPDATE_LOCK_FALSE  = 0x0,
+	BLND_V_UPDATE_LOCK_BLND_SCL_V_UPDATE_LOCK_TRUE   = 0x1,
+} BLND_V_UPDATE_LOCK_BLND_SCL_V_UPDATE_LOCK;
+typedef enum BLND_V_UPDATE_LOCK_BLND_BLND_V_UPDATE_LOCK {
+	BLND_V_UPDATE_LOCK_BLND_BLND_V_UPDATE_LOCK_FALSE = 0x0,
+	BLND_V_UPDATE_LOCK_BLND_BLND_V_UPDATE_LOCK_TRUE  = 0x1,
+} BLND_V_UPDATE_LOCK_BLND_BLND_V_UPDATE_LOCK;
+typedef enum BLND_V_UPDATE_LOCK_BLND_V_UPDATE_LOCK_MODE {
+	BLND_V_UPDATE_LOCK_BLND_V_UPDATE_LOCK_MODE_FALSE = 0x0,
+	BLND_V_UPDATE_LOCK_BLND_V_UPDATE_LOCK_MODE_TRUE  = 0x1,
+} BLND_V_UPDATE_LOCK_BLND_V_UPDATE_LOCK_MODE;
+typedef enum BLND_DEBUG_BLND_CNV_MUX_SELECT {
+	BLND_DEBUG_BLND_CNV_MUX_SELECT_LOW               = 0x0,
+	BLND_DEBUG_BLND_CNV_MUX_SELECT_HIGH              = 0x1,
+} BLND_DEBUG_BLND_CNV_MUX_SELECT;
+typedef enum BLND_TEST_DEBUG_INDEX_BLND_TEST_DEBUG_WRITE_EN {
+	BLND_TEST_DEBUG_INDEX_BLND_TEST_DEBUG_WRITE_EN_FALSE= 0x0,
+	BLND_TEST_DEBUG_INDEX_BLND_TEST_DEBUG_WRITE_EN_TRUE= 0x1,
+} BLND_TEST_DEBUG_INDEX_BLND_TEST_DEBUG_WRITE_EN;
+typedef enum SurfaceEndian {
+	ENDIAN_NONE                                      = 0x0,
+	ENDIAN_8IN16                                     = 0x1,
+	ENDIAN_8IN32                                     = 0x2,
+	ENDIAN_8IN64                                     = 0x3,
+} SurfaceEndian;
+typedef enum ArrayMode {
+	ARRAY_LINEAR_GENERAL                             = 0x0,
+	ARRAY_LINEAR_ALIGNED                             = 0x1,
+	ARRAY_1D_TILED_THIN1                             = 0x2,
+	ARRAY_1D_TILED_THICK                             = 0x3,
+	ARRAY_2D_TILED_THIN1                             = 0x4,
+	ARRAY_PRT_TILED_THIN1                            = 0x5,
+	ARRAY_PRT_2D_TILED_THIN1                         = 0x6,
+	ARRAY_2D_TILED_THICK                             = 0x7,
+	ARRAY_2D_TILED_XTHICK                            = 0x8,
+	ARRAY_PRT_TILED_THICK                            = 0x9,
+	ARRAY_PRT_2D_TILED_THICK                         = 0xa,
+	ARRAY_PRT_3D_TILED_THIN1                         = 0xb,
+	ARRAY_3D_TILED_THIN1                             = 0xc,
+	ARRAY_3D_TILED_THICK                             = 0xd,
+	ARRAY_3D_TILED_XTHICK                            = 0xe,
+	ARRAY_PRT_3D_TILED_THICK                         = 0xf,
+} ArrayMode;
+typedef enum PipeTiling {
+	CONFIG_1_PIPE                                    = 0x0,
+	CONFIG_2_PIPE                                    = 0x1,
+	CONFIG_4_PIPE                                    = 0x2,
+	CONFIG_8_PIPE                                    = 0x3,
+} PipeTiling;
+typedef enum BankTiling {
+	CONFIG_4_BANK                                    = 0x0,
+	CONFIG_8_BANK                                    = 0x1,
+} BankTiling;
+typedef enum GroupInterleave {
+	CONFIG_256B_GROUP                                = 0x0,
+	CONFIG_512B_GROUP                                = 0x1,
+} GroupInterleave;
+typedef enum RowTiling {
+	CONFIG_1KB_ROW                                   = 0x0,
+	CONFIG_2KB_ROW                                   = 0x1,
+	CONFIG_4KB_ROW                                   = 0x2,
+	CONFIG_8KB_ROW                                   = 0x3,
+	CONFIG_1KB_ROW_OPT                               = 0x4,
+	CONFIG_2KB_ROW_OPT                               = 0x5,
+	CONFIG_4KB_ROW_OPT                               = 0x6,
+	CONFIG_8KB_ROW_OPT                               = 0x7,
+} RowTiling;
+typedef enum BankSwapBytes {
+	CONFIG_128B_SWAPS                                = 0x0,
+	CONFIG_256B_SWAPS                                = 0x1,
+	CONFIG_512B_SWAPS                                = 0x2,
+	CONFIG_1KB_SWAPS                                 = 0x3,
+} BankSwapBytes;
+typedef enum SampleSplitBytes {
+	CONFIG_1KB_SPLIT                                 = 0x0,
+	CONFIG_2KB_SPLIT                                 = 0x1,
+	CONFIG_4KB_SPLIT                                 = 0x2,
+	CONFIG_8KB_SPLIT                                 = 0x3,
+} SampleSplitBytes;
+typedef enum NumPipes {
+	ADDR_CONFIG_1_PIPE                               = 0x0,
+	ADDR_CONFIG_2_PIPE                               = 0x1,
+	ADDR_CONFIG_4_PIPE                               = 0x2,
+	ADDR_CONFIG_8_PIPE                               = 0x3,
+} NumPipes;
+typedef enum PipeInterleaveSize {
+	ADDR_CONFIG_PIPE_INTERLEAVE_256B                 = 0x0,
+	ADDR_CONFIG_PIPE_INTERLEAVE_512B                 = 0x1,
+} PipeInterleaveSize;
+typedef enum BankInterleaveSize {
+	ADDR_CONFIG_BANK_INTERLEAVE_1                    = 0x0,
+	ADDR_CONFIG_BANK_INTERLEAVE_2                    = 0x1,
+	ADDR_CONFIG_BANK_INTERLEAVE_4                    = 0x2,
+	ADDR_CONFIG_BANK_INTERLEAVE_8                    = 0x3,
+} BankInterleaveSize;
+typedef enum NumShaderEngines {
+	ADDR_CONFIG_1_SHADER_ENGINE                      = 0x0,
+	ADDR_CONFIG_2_SHADER_ENGINE                      = 0x1,
+} NumShaderEngines;
+typedef enum ShaderEngineTileSize {
+	ADDR_CONFIG_SE_TILE_16                           = 0x0,
+	ADDR_CONFIG_SE_TILE_32                           = 0x1,
+} ShaderEngineTileSize;
+typedef enum NumGPUs {
+	ADDR_CONFIG_1_GPU                                = 0x0,
+	ADDR_CONFIG_2_GPU                                = 0x1,
+	ADDR_CONFIG_4_GPU                                = 0x2,
+} NumGPUs;
+typedef enum MultiGPUTileSize {
+	ADDR_CONFIG_GPU_TILE_16                          = 0x0,
+	ADDR_CONFIG_GPU_TILE_32                          = 0x1,
+	ADDR_CONFIG_GPU_TILE_64                          = 0x2,
+	ADDR_CONFIG_GPU_TILE_128                         = 0x3,
+} MultiGPUTileSize;
+typedef enum RowSize {
+	ADDR_CONFIG_1KB_ROW                              = 0x0,
+	ADDR_CONFIG_2KB_ROW                              = 0x1,
+	ADDR_CONFIG_4KB_ROW                              = 0x2,
+} RowSize;
+typedef enum NumLowerPipes {
+	ADDR_CONFIG_1_LOWER_PIPES                        = 0x0,
+	ADDR_CONFIG_2_LOWER_PIPES                        = 0x1,
+} NumLowerPipes;
+typedef enum DebugBlockId {
+	DBG_CLIENT_BLKID_RESERVED                        = 0x0,
+	DBG_CLIENT_BLKID_dbg                             = 0x1,
+	DBG_CLIENT_BLKID_scf2                            = 0x2,
+	DBG_CLIENT_BLKID_mcd5                            = 0x3,
+	DBG_CLIENT_BLKID_vmc                             = 0x4,
+	DBG_CLIENT_BLKID_sx30                            = 0x5,
+	DBG_CLIENT_BLKID_mcd2                            = 0x6,
+	DBG_CLIENT_BLKID_bci1                            = 0x7,
+	DBG_CLIENT_BLKID_xdma_dbg_client_wrapper         = 0x8,
+	DBG_CLIENT_BLKID_mcc0                            = 0x9,
+	DBG_CLIENT_BLKID_uvdf_2                          = 0xa,
+	DBG_CLIENT_BLKID_uvdf_3                          = 0xb,
+	DBG_CLIENT_BLKID_uvdt_0                          = 0xc,
+	DBG_CLIENT_BLKID_uvdi_0                          = 0xd,
+	DBG_CLIENT_BLKID_bci0                            = 0xe,
+	DBG_CLIENT_BLKID_vceb0_1                         = 0xf,
+	DBG_CLIENT_BLKID_cb100                           = 0x10,
+	DBG_CLIENT_BLKID_cb001                           = 0x11,
+	DBG_CLIENT_BLKID_mcd4                            = 0x12,
+	DBG_CLIENT_BLKID_tmonw00                         = 0x13,
+	DBG_CLIENT_BLKID_cb101                           = 0x14,
+	DBG_CLIENT_BLKID_sx10                            = 0x15,
+	DBG_CLIENT_BLKID_cb301                           = 0x16,
+	DBG_CLIENT_BLKID_tmonw01                         = 0x17,
+	DBG_CLIENT_BLKID_vcea0_0                         = 0x18,
+	DBG_CLIENT_BLKID_vcea0_1                         = 0x19,
+	DBG_CLIENT_BLKID_vcea0_2                         = 0x1a,
+	DBG_CLIENT_BLKID_vcea0_3                         = 0x1b,
+	DBG_CLIENT_BLKID_scf1                            = 0x1c,
+	DBG_CLIENT_BLKID_sx20                            = 0x1d,
+	DBG_CLIENT_BLKID_spim1                           = 0x1e,
+	DBG_CLIENT_BLKID_pa10                            = 0x1f,
+	DBG_CLIENT_BLKID_pa00                            = 0x20,
+	DBG_CLIENT_BLKID_gmcon                           = 0x21,
+	DBG_CLIENT_BLKID_mcb                             = 0x22,
+	DBG_CLIENT_BLKID_vgt0                            = 0x23,
+	DBG_CLIENT_BLKID_pc0                             = 0x24,
+	DBG_CLIENT_BLKID_bci2                            = 0x25,
+	DBG_CLIENT_BLKID_uvdb_0                          = 0x26,
+	DBG_CLIENT_BLKID_spim3                           = 0x27,
+	DBG_CLIENT_BLKID_cpc_0                           = 0x28,
+	DBG_CLIENT_BLKID_cpc_1                           = 0x29,
+	DBG_CLIENT_BLKID_uvdm_0                          = 0x2a,
+	DBG_CLIENT_BLKID_uvdm_1                          = 0x2b,
+	DBG_CLIENT_BLKID_uvdm_2                          = 0x2c,
+	DBG_CLIENT_BLKID_uvdm_3                          = 0x2d,
+	DBG_CLIENT_BLKID_cb000                           = 0x2e,
+	DBG_CLIENT_BLKID_spim0                           = 0x2f,
+	DBG_CLIENT_BLKID_mcc2                            = 0x30,
+	DBG_CLIENT_BLKID_ds0                             = 0x31,
+	DBG_CLIENT_BLKID_srbm                            = 0x32,
+	DBG_CLIENT_BLKID_ih                              = 0x33,
+	DBG_CLIENT_BLKID_sem                             = 0x34,
+	DBG_CLIENT_BLKID_sdma_0                          = 0x35,
+	DBG_CLIENT_BLKID_sdma_1                          = 0x36,
+	DBG_CLIENT_BLKID_hdp                             = 0x37,
+	DBG_CLIENT_BLKID_cb200                           = 0x38,
+	DBG_CLIENT_BLKID_scf3                            = 0x39,
+	DBG_CLIENT_BLKID_vceb1_0                         = 0x3a,
+	DBG_CLIENT_BLKID_vcea1_0                         = 0x3b,
+	DBG_CLIENT_BLKID_vcea1_1                         = 0x3c,
+	DBG_CLIENT_BLKID_vcea1_2                         = 0x3d,
+	DBG_CLIENT_BLKID_vcea1_3                         = 0x3e,
+	DBG_CLIENT_BLKID_bci3                            = 0x3f,
+	DBG_CLIENT_BLKID_mcd0                            = 0x40,
+	DBG_CLIENT_BLKID_pa11                            = 0x41,
+	DBG_CLIENT_BLKID_pa01                            = 0x42,
+	DBG_CLIENT_BLKID_cb201                           = 0x43,
+	DBG_CLIENT_BLKID_spim2                           = 0x44,
+	DBG_CLIENT_BLKID_vgt2                            = 0x45,
+	DBG_CLIENT_BLKID_pc2                             = 0x46,
+	DBG_CLIENT_BLKID_smu_0                           = 0x47,
+	DBG_CLIENT_BLKID_smu_1                           = 0x48,
+	DBG_CLIENT_BLKID_smu_2                           = 0x49,
+	DBG_CLIENT_BLKID_cb1                             = 0x4a,
+	DBG_CLIENT_BLKID_ia0                             = 0x4b,
+	DBG_CLIENT_BLKID_wd                              = 0x4c,
+	DBG_CLIENT_BLKID_ia1                             = 0x4d,
+	DBG_CLIENT_BLKID_vcec1_0                         = 0x4e,
+	DBG_CLIENT_BLKID_scf0                            = 0x4f,
+	DBG_CLIENT_BLKID_vgt1                            = 0x50,
+	DBG_CLIENT_BLKID_pc1                             = 0x51,
+	DBG_CLIENT_BLKID_cb0                             = 0x52,
+	DBG_CLIENT_BLKID_gdc_one_0                       = 0x53,
+	DBG_CLIENT_BLKID_gdc_one_1                       = 0x54,
+	DBG_CLIENT_BLKID_gdc_one_2                       = 0x55,
+	DBG_CLIENT_BLKID_gdc_one_3                       = 0x56,
+	DBG_CLIENT_BLKID_gdc_one_4                       = 0x57,
+	DBG_CLIENT_BLKID_gdc_one_5                       = 0x58,
+	DBG_CLIENT_BLKID_gdc_one_6                       = 0x59,
+	DBG_CLIENT_BLKID_gdc_one_7                       = 0x5a,
+	DBG_CLIENT_BLKID_gdc_one_8                       = 0x5b,
+	DBG_CLIENT_BLKID_gdc_one_9                       = 0x5c,
+	DBG_CLIENT_BLKID_gdc_one_10                      = 0x5d,
+	DBG_CLIENT_BLKID_gdc_one_11                      = 0x5e,
+	DBG_CLIENT_BLKID_gdc_one_12                      = 0x5f,
+	DBG_CLIENT_BLKID_gdc_one_13                      = 0x60,
+	DBG_CLIENT_BLKID_gdc_one_14                      = 0x61,
+	DBG_CLIENT_BLKID_gdc_one_15                      = 0x62,
+	DBG_CLIENT_BLKID_gdc_one_16                      = 0x63,
+	DBG_CLIENT_BLKID_gdc_one_17                      = 0x64,
+	DBG_CLIENT_BLKID_gdc_one_18                      = 0x65,
+	DBG_CLIENT_BLKID_gdc_one_19                      = 0x66,
+	DBG_CLIENT_BLKID_gdc_one_20                      = 0x67,
+	DBG_CLIENT_BLKID_gdc_one_21                      = 0x68,
+	DBG_CLIENT_BLKID_gdc_one_22                      = 0x69,
+	DBG_CLIENT_BLKID_gdc_one_23                      = 0x6a,
+	DBG_CLIENT_BLKID_gdc_one_24                      = 0x6b,
+	DBG_CLIENT_BLKID_gdc_one_25                      = 0x6c,
+	DBG_CLIENT_BLKID_gdc_one_26                      = 0x6d,
+	DBG_CLIENT_BLKID_gdc_one_27                      = 0x6e,
+	DBG_CLIENT_BLKID_gdc_one_28                      = 0x6f,
+	DBG_CLIENT_BLKID_gdc_one_29                      = 0x70,
+	DBG_CLIENT_BLKID_gdc_one_30                      = 0x71,
+	DBG_CLIENT_BLKID_gdc_one_31                      = 0x72,
+	DBG_CLIENT_BLKID_gdc_one_32                      = 0x73,
+	DBG_CLIENT_BLKID_gdc_one_33                      = 0x74,
+	DBG_CLIENT_BLKID_gdc_one_34                      = 0x75,
+	DBG_CLIENT_BLKID_gdc_one_35                      = 0x76,
+	DBG_CLIENT_BLKID_vceb0_0                         = 0x77,
+	DBG_CLIENT_BLKID_vgt3                            = 0x78,
+	DBG_CLIENT_BLKID_pc3                             = 0x79,
+	DBG_CLIENT_BLKID_mcd3                            = 0x7a,
+	DBG_CLIENT_BLKID_uvdu_0                          = 0x7b,
+	DBG_CLIENT_BLKID_uvdu_1                          = 0x7c,
+	DBG_CLIENT_BLKID_uvdu_2                          = 0x7d,
+	DBG_CLIENT_BLKID_uvdu_3                          = 0x7e,
+	DBG_CLIENT_BLKID_uvdu_4                          = 0x7f,
+	DBG_CLIENT_BLKID_uvdu_5                          = 0x80,
+	DBG_CLIENT_BLKID_uvdu_6                          = 0x81,
+	DBG_CLIENT_BLKID_cb300                           = 0x82,
+	DBG_CLIENT_BLKID_mcd1                            = 0x83,
+	DBG_CLIENT_BLKID_sx00                            = 0x84,
+	DBG_CLIENT_BLKID_uvdf_0                          = 0x85,
+	DBG_CLIENT_BLKID_uvdf_1                          = 0x86,
+	DBG_CLIENT_BLKID_mcc3                            = 0x87,
+	DBG_CLIENT_BLKID_cpg_0                           = 0x88,
+	DBG_CLIENT_BLKID_cpg_1                           = 0x89,
+	DBG_CLIENT_BLKID_gck                             = 0x8a,
+	DBG_CLIENT_BLKID_mcc1                            = 0x8b,
+	DBG_CLIENT_BLKID_cpf_0                           = 0x8c,
+	DBG_CLIENT_BLKID_cpf_1                           = 0x8d,
+	DBG_CLIENT_BLKID_rlc                             = 0x8e,
+	DBG_CLIENT_BLKID_grbm                            = 0x8f,
+	DBG_CLIENT_BLKID_sammsp                          = 0x90,
+	DBG_CLIENT_BLKID_dci_pg                          = 0x91,
+	DBG_CLIENT_BLKID_dci_0                           = 0x92,
+	DBG_CLIENT_BLKID_dccg0_0                         = 0x93,
+	DBG_CLIENT_BLKID_dccg0_1                         = 0x94,
+	DBG_CLIENT_BLKID_dccg0_2                         = 0x95,
+	DBG_CLIENT_BLKID_dccg0_3                         = 0x96,
+	DBG_CLIENT_BLKID_dccg0_4                         = 0x97,
+	DBG_CLIENT_BLKID_dccg0_5                         = 0x98,
+	DBG_CLIENT_BLKID_dccg0_6                         = 0x99,
+	DBG_CLIENT_BLKID_dccg0_7                         = 0x9a,
+	DBG_CLIENT_BLKID_dccg0_8                         = 0x9b,
+	DBG_CLIENT_BLKID_dcfe01_0                        = 0x9c,
+	DBG_CLIENT_BLKID_dcfe02_0                        = 0x9d,
+	DBG_CLIENT_BLKID_dcfe03_0                        = 0x9e,
+	DBG_CLIENT_BLKID_dcfe04_0                        = 0x9f,
+	DBG_CLIENT_BLKID_dcfe05_0                        = 0xa0,
+	DBG_CLIENT_BLKID_dcfe06_0                        = 0xa1,
+	DBG_CLIENT_BLKID_uvde_0                          = 0xa2,
+	DBG_CLIENT_BLKID_RESERVED_LAST                   = 0xa3,
+} DebugBlockId;
+typedef enum DebugBlockId_OLD {
+	DBG_BLOCK_ID_RESERVED                            = 0x0,
+	DBG_BLOCK_ID_DBG                                 = 0x1,
+	DBG_BLOCK_ID_VMC                                 = 0x2,
+	DBG_BLOCK_ID_PDMA                                = 0x3,
+	DBG_BLOCK_ID_CG                                  = 0x4,
+	DBG_BLOCK_ID_SRBM                                = 0x5,
+	DBG_BLOCK_ID_GRBM                                = 0x6,
+	DBG_BLOCK_ID_RLC                                 = 0x7,
+	DBG_BLOCK_ID_CSC                                 = 0x8,
+	DBG_BLOCK_ID_SEM                                 = 0x9,
+	DBG_BLOCK_ID_IH                                  = 0xa,
+	DBG_BLOCK_ID_SC                                  = 0xb,
+	DBG_BLOCK_ID_SQ                                  = 0xc,
+	DBG_BLOCK_ID_AVP                                 = 0xd,
+	DBG_BLOCK_ID_GMCON                               = 0xe,
+	DBG_BLOCK_ID_SMU                                 = 0xf,
+	DBG_BLOCK_ID_DMA0                                = 0x10,
+	DBG_BLOCK_ID_DMA1                                = 0x11,
+	DBG_BLOCK_ID_SPIM                                = 0x12,
+	DBG_BLOCK_ID_GDS                                 = 0x13,
+	DBG_BLOCK_ID_SPIS                                = 0x14,
+	DBG_BLOCK_ID_UNUSED0                             = 0x15,
+	DBG_BLOCK_ID_PA0                                 = 0x16,
+	DBG_BLOCK_ID_PA1                                 = 0x17,
+	DBG_BLOCK_ID_CP0                                 = 0x18,
+	DBG_BLOCK_ID_CP1                                 = 0x19,
+	DBG_BLOCK_ID_CP2                                 = 0x1a,
+	DBG_BLOCK_ID_UNUSED1                             = 0x1b,
+	DBG_BLOCK_ID_UVDU                                = 0x1c,
+	DBG_BLOCK_ID_UVDM                                = 0x1d,
+	DBG_BLOCK_ID_VCE                                 = 0x1e,
+	DBG_BLOCK_ID_UNUSED2                             = 0x1f,
+	DBG_BLOCK_ID_VGT0                                = 0x20,
+	DBG_BLOCK_ID_VGT1                                = 0x21,
+	DBG_BLOCK_ID_IA                                  = 0x22,
+	DBG_BLOCK_ID_UNUSED3                             = 0x23,
+	DBG_BLOCK_ID_SCT0                                = 0x24,
+	DBG_BLOCK_ID_SCT1                                = 0x25,
+	DBG_BLOCK_ID_SPM0                                = 0x26,
+	DBG_BLOCK_ID_SPM1                                = 0x27,
+	DBG_BLOCK_ID_TCAA                                = 0x28,
+	DBG_BLOCK_ID_TCAB                                = 0x29,
+	DBG_BLOCK_ID_TCCA                                = 0x2a,
+	DBG_BLOCK_ID_TCCB                                = 0x2b,
+	DBG_BLOCK_ID_MCC0                                = 0x2c,
+	DBG_BLOCK_ID_MCC1                                = 0x2d,
+	DBG_BLOCK_ID_MCC2                                = 0x2e,
+	DBG_BLOCK_ID_MCC3                                = 0x2f,
+	DBG_BLOCK_ID_SX0                                 = 0x30,
+	DBG_BLOCK_ID_SX1                                 = 0x31,
+	DBG_BLOCK_ID_SX2                                 = 0x32,
+	DBG_BLOCK_ID_SX3                                 = 0x33,
+	DBG_BLOCK_ID_UNUSED4                             = 0x34,
+	DBG_BLOCK_ID_UNUSED5                             = 0x35,
+	DBG_BLOCK_ID_UNUSED6                             = 0x36,
+	DBG_BLOCK_ID_UNUSED7                             = 0x37,
+	DBG_BLOCK_ID_PC0                                 = 0x38,
+	DBG_BLOCK_ID_PC1                                 = 0x39,
+	DBG_BLOCK_ID_UNUSED8                             = 0x3a,
+	DBG_BLOCK_ID_UNUSED9                             = 0x3b,
+	DBG_BLOCK_ID_UNUSED10                            = 0x3c,
+	DBG_BLOCK_ID_UNUSED11                            = 0x3d,
+	DBG_BLOCK_ID_MCB                                 = 0x3e,
+	DBG_BLOCK_ID_UNUSED12                            = 0x3f,
+	DBG_BLOCK_ID_SCB0                                = 0x40,
+	DBG_BLOCK_ID_SCB1                                = 0x41,
+	DBG_BLOCK_ID_UNUSED13                            = 0x42,
+	DBG_BLOCK_ID_UNUSED14                            = 0x43,
+	DBG_BLOCK_ID_SCF0                                = 0x44,
+	DBG_BLOCK_ID_SCF1                                = 0x45,
+	DBG_BLOCK_ID_UNUSED15                            = 0x46,
+	DBG_BLOCK_ID_UNUSED16                            = 0x47,
+	DBG_BLOCK_ID_BCI0                                = 0x48,
+	DBG_BLOCK_ID_BCI1                                = 0x49,
+	DBG_BLOCK_ID_BCI2                                = 0x4a,
+	DBG_BLOCK_ID_BCI3                                = 0x4b,
+	DBG_BLOCK_ID_UNUSED17                            = 0x4c,
+	DBG_BLOCK_ID_UNUSED18                            = 0x4d,
+	DBG_BLOCK_ID_UNUSED19                            = 0x4e,
+	DBG_BLOCK_ID_UNUSED20                            = 0x4f,
+	DBG_BLOCK_ID_CB00                                = 0x50,
+	DBG_BLOCK_ID_CB01                                = 0x51,
+	DBG_BLOCK_ID_CB02                                = 0x52,
+	DBG_BLOCK_ID_CB03                                = 0x53,
+	DBG_BLOCK_ID_CB04                                = 0x54,
+	DBG_BLOCK_ID_UNUSED21                            = 0x55,
+	DBG_BLOCK_ID_UNUSED22                            = 0x56,
+	DBG_BLOCK_ID_UNUSED23                            = 0x57,
+	DBG_BLOCK_ID_CB10                                = 0x58,
+	DBG_BLOCK_ID_CB11                                = 0x59,
+	DBG_BLOCK_ID_CB12                                = 0x5a,
+	DBG_BLOCK_ID_CB13                                = 0x5b,
+	DBG_BLOCK_ID_CB14                                = 0x5c,
+	DBG_BLOCK_ID_UNUSED24                            = 0x5d,
+	DBG_BLOCK_ID_UNUSED25                            = 0x5e,
+	DBG_BLOCK_ID_UNUSED26                            = 0x5f,
+	DBG_BLOCK_ID_TCP0                                = 0x60,
+	DBG_BLOCK_ID_TCP1                                = 0x61,
+	DBG_BLOCK_ID_TCP2                                = 0x62,
+	DBG_BLOCK_ID_TCP3                                = 0x63,
+	DBG_BLOCK_ID_TCP4                                = 0x64,
+	DBG_BLOCK_ID_TCP5                                = 0x65,
+	DBG_BLOCK_ID_TCP6                                = 0x66,
+	DBG_BLOCK_ID_TCP7                                = 0x67,
+	DBG_BLOCK_ID_TCP8                                = 0x68,
+	DBG_BLOCK_ID_TCP9                                = 0x69,
+	DBG_BLOCK_ID_TCP10                               = 0x6a,
+	DBG_BLOCK_ID_TCP11                               = 0x6b,
+	DBG_BLOCK_ID_TCP12                               = 0x6c,
+	DBG_BLOCK_ID_TCP13                               = 0x6d,
+	DBG_BLOCK_ID_TCP14                               = 0x6e,
+	DBG_BLOCK_ID_TCP15                               = 0x6f,
+	DBG_BLOCK_ID_TCP16                               = 0x70,
+	DBG_BLOCK_ID_TCP17                               = 0x71,
+	DBG_BLOCK_ID_TCP18                               = 0x72,
+	DBG_BLOCK_ID_TCP19                               = 0x73,
+	DBG_BLOCK_ID_TCP20                               = 0x74,
+	DBG_BLOCK_ID_TCP21                               = 0x75,
+	DBG_BLOCK_ID_TCP22                               = 0x76,
+	DBG_BLOCK_ID_TCP23                               = 0x77,
+	DBG_BLOCK_ID_TCP_RESERVED0                       = 0x78,
+	DBG_BLOCK_ID_TCP_RESERVED1                       = 0x79,
+	DBG_BLOCK_ID_TCP_RESERVED2                       = 0x7a,
+	DBG_BLOCK_ID_TCP_RESERVED3                       = 0x7b,
+	DBG_BLOCK_ID_TCP_RESERVED4                       = 0x7c,
+	DBG_BLOCK_ID_TCP_RESERVED5                       = 0x7d,
+	DBG_BLOCK_ID_TCP_RESERVED6                       = 0x7e,
+	DBG_BLOCK_ID_TCP_RESERVED7                       = 0x7f,
+	DBG_BLOCK_ID_DB00                                = 0x80,
+	DBG_BLOCK_ID_DB01                                = 0x81,
+	DBG_BLOCK_ID_DB02                                = 0x82,
+	DBG_BLOCK_ID_DB03                                = 0x83,
+	DBG_BLOCK_ID_DB04                                = 0x84,
+	DBG_BLOCK_ID_UNUSED27                            = 0x85,
+	DBG_BLOCK_ID_UNUSED28                            = 0x86,
+	DBG_BLOCK_ID_UNUSED29                            = 0x87,
+	DBG_BLOCK_ID_DB10                                = 0x88,
+	DBG_BLOCK_ID_DB11                                = 0x89,
+	DBG_BLOCK_ID_DB12                                = 0x8a,
+	DBG_BLOCK_ID_DB13                                = 0x8b,
+	DBG_BLOCK_ID_DB14                                = 0x8c,
+	DBG_BLOCK_ID_UNUSED30                            = 0x8d,
+	DBG_BLOCK_ID_UNUSED31                            = 0x8e,
+	DBG_BLOCK_ID_UNUSED32                            = 0x8f,
+	DBG_BLOCK_ID_TCC0                                = 0x90,
+	DBG_BLOCK_ID_TCC1                                = 0x91,
+	DBG_BLOCK_ID_TCC2                                = 0x92,
+	DBG_BLOCK_ID_TCC3                                = 0x93,
+	DBG_BLOCK_ID_TCC4                                = 0x94,
+	DBG_BLOCK_ID_TCC5                                = 0x95,
+	DBG_BLOCK_ID_TCC6                                = 0x96,
+	DBG_BLOCK_ID_TCC7                                = 0x97,
+	DBG_BLOCK_ID_SPS00                               = 0x98,
+	DBG_BLOCK_ID_SPS01                               = 0x99,
+	DBG_BLOCK_ID_SPS02                               = 0x9a,
+	DBG_BLOCK_ID_SPS10                               = 0x9b,
+	DBG_BLOCK_ID_SPS11                               = 0x9c,
+	DBG_BLOCK_ID_SPS12                               = 0x9d,
+	DBG_BLOCK_ID_UNUSED33                            = 0x9e,
+	DBG_BLOCK_ID_UNUSED34                            = 0x9f,
+	DBG_BLOCK_ID_TA00                                = 0xa0,
+	DBG_BLOCK_ID_TA01                                = 0xa1,
+	DBG_BLOCK_ID_TA02                                = 0xa2,
+	DBG_BLOCK_ID_TA03                                = 0xa3,
+	DBG_BLOCK_ID_TA04                                = 0xa4,
+	DBG_BLOCK_ID_TA05                                = 0xa5,
+	DBG_BLOCK_ID_TA06                                = 0xa6,
+	DBG_BLOCK_ID_TA07                                = 0xa7,
+	DBG_BLOCK_ID_TA08                                = 0xa8,
+	DBG_BLOCK_ID_TA09                                = 0xa9,
+	DBG_BLOCK_ID_TA0A                                = 0xaa,
+	DBG_BLOCK_ID_TA0B                                = 0xab,
+	DBG_BLOCK_ID_UNUSED35                            = 0xac,
+	DBG_BLOCK_ID_UNUSED36                            = 0xad,
+	DBG_BLOCK_ID_UNUSED37                            = 0xae,
+	DBG_BLOCK_ID_UNUSED38                            = 0xaf,
+	DBG_BLOCK_ID_TA10                                = 0xb0,
+	DBG_BLOCK_ID_TA11                                = 0xb1,
+	DBG_BLOCK_ID_TA12                                = 0xb2,
+	DBG_BLOCK_ID_TA13                                = 0xb3,
+	DBG_BLOCK_ID_TA14                                = 0xb4,
+	DBG_BLOCK_ID_TA15                                = 0xb5,
+	DBG_BLOCK_ID_TA16                                = 0xb6,
+	DBG_BLOCK_ID_TA17                                = 0xb7,
+	DBG_BLOCK_ID_TA18                                = 0xb8,
+	DBG_BLOCK_ID_TA19                                = 0xb9,
+	DBG_BLOCK_ID_TA1A                                = 0xba,
+	DBG_BLOCK_ID_TA1B                                = 0xbb,
+	DBG_BLOCK_ID_UNUSED39                            = 0xbc,
+	DBG_BLOCK_ID_UNUSED40                            = 0xbd,
+	DBG_BLOCK_ID_UNUSED41                            = 0xbe,
+	DBG_BLOCK_ID_UNUSED42                            = 0xbf,
+	DBG_BLOCK_ID_TD00                                = 0xc0,
+	DBG_BLOCK_ID_TD01                                = 0xc1,
+	DBG_BLOCK_ID_TD02                                = 0xc2,
+	DBG_BLOCK_ID_TD03                                = 0xc3,
+	DBG_BLOCK_ID_TD04                                = 0xc4,
+	DBG_BLOCK_ID_TD05                                = 0xc5,
+	DBG_BLOCK_ID_TD06                                = 0xc6,
+	DBG_BLOCK_ID_TD07                                = 0xc7,
+	DBG_BLOCK_ID_TD08                                = 0xc8,
+	DBG_BLOCK_ID_TD09                                = 0xc9,
+	DBG_BLOCK_ID_TD0A                                = 0xca,
+	DBG_BLOCK_ID_TD0B                                = 0xcb,
+	DBG_BLOCK_ID_UNUSED43                            = 0xcc,
+	DBG_BLOCK_ID_UNUSED44                            = 0xcd,
+	DBG_BLOCK_ID_UNUSED45                            = 0xce,
+	DBG_BLOCK_ID_UNUSED46                            = 0xcf,
+	DBG_BLOCK_ID_TD10                                = 0xd0,
+	DBG_BLOCK_ID_TD11                                = 0xd1,
+	DBG_BLOCK_ID_TD12                                = 0xd2,
+	DBG_BLOCK_ID_TD13                                = 0xd3,
+	DBG_BLOCK_ID_TD14                                = 0xd4,
+	DBG_BLOCK_ID_TD15                                = 0xd5,
+	DBG_BLOCK_ID_TD16                                = 0xd6,
+	DBG_BLOCK_ID_TD17                                = 0xd7,
+	DBG_BLOCK_ID_TD18                                = 0xd8,
+	DBG_BLOCK_ID_TD19                                = 0xd9,
+	DBG_BLOCK_ID_TD1A                                = 0xda,
+	DBG_BLOCK_ID_TD1B                                = 0xdb,
+	DBG_BLOCK_ID_UNUSED47                            = 0xdc,
+	DBG_BLOCK_ID_UNUSED48                            = 0xdd,
+	DBG_BLOCK_ID_UNUSED49                            = 0xde,
+	DBG_BLOCK_ID_UNUSED50                            = 0xdf,
+	DBG_BLOCK_ID_MCD0                                = 0xe0,
+	DBG_BLOCK_ID_MCD1                                = 0xe1,
+	DBG_BLOCK_ID_MCD2                                = 0xe2,
+	DBG_BLOCK_ID_MCD3                                = 0xe3,
+	DBG_BLOCK_ID_MCD4                                = 0xe4,
+	DBG_BLOCK_ID_MCD5                                = 0xe5,
+	DBG_BLOCK_ID_UNUSED51                            = 0xe6,
+	DBG_BLOCK_ID_UNUSED52                            = 0xe7,
+} DebugBlockId_OLD;
+typedef enum DebugBlockId_BY2 {
+	DBG_BLOCK_ID_RESERVED_BY2                        = 0x0,
+	DBG_BLOCK_ID_VMC_BY2                             = 0x1,
+	DBG_BLOCK_ID_CG_BY2                              = 0x2,
+	DBG_BLOCK_ID_GRBM_BY2                            = 0x3,
+	DBG_BLOCK_ID_CSC_BY2                             = 0x4,
+	DBG_BLOCK_ID_IH_BY2                              = 0x5,
+	DBG_BLOCK_ID_SQ_BY2                              = 0x6,
+	DBG_BLOCK_ID_GMCON_BY2                           = 0x7,
+	DBG_BLOCK_ID_DMA0_BY2                            = 0x8,
+	DBG_BLOCK_ID_SPIM_BY2                            = 0x9,
+	DBG_BLOCK_ID_SPIS_BY2                            = 0xa,
+	DBG_BLOCK_ID_PA0_BY2                             = 0xb,
+	DBG_BLOCK_ID_CP0_BY2                             = 0xc,
+	DBG_BLOCK_ID_CP2_BY2                             = 0xd,
+	DBG_BLOCK_ID_UVDU_BY2                            = 0xe,
+	DBG_BLOCK_ID_VCE_BY2                             = 0xf,
+	DBG_BLOCK_ID_VGT0_BY2                            = 0x10,
+	DBG_BLOCK_ID_IA_BY2                              = 0x11,
+	DBG_BLOCK_ID_SCT0_BY2                            = 0x12,
+	DBG_BLOCK_ID_SPM0_BY2                            = 0x13,
+	DBG_BLOCK_ID_TCAA_BY2                            = 0x14,
+	DBG_BLOCK_ID_TCCA_BY2                            = 0x15,
+	DBG_BLOCK_ID_MCC0_BY2                            = 0x16,
+	DBG_BLOCK_ID_MCC2_BY2                            = 0x17,
+	DBG_BLOCK_ID_SX0_BY2                             = 0x18,
+	DBG_BLOCK_ID_SX2_BY2                             = 0x19,
+	DBG_BLOCK_ID_UNUSED4_BY2                         = 0x1a,
+	DBG_BLOCK_ID_UNUSED6_BY2                         = 0x1b,
+	DBG_BLOCK_ID_PC0_BY2                             = 0x1c,
+	DBG_BLOCK_ID_UNUSED8_BY2                         = 0x1d,
+	DBG_BLOCK_ID_UNUSED10_BY2                        = 0x1e,
+	DBG_BLOCK_ID_MCB_BY2                             = 0x1f,
+	DBG_BLOCK_ID_SCB0_BY2                            = 0x20,
+	DBG_BLOCK_ID_UNUSED13_BY2                        = 0x21,
+	DBG_BLOCK_ID_SCF0_BY2                            = 0x22,
+	DBG_BLOCK_ID_UNUSED15_BY2                        = 0x23,
+	DBG_BLOCK_ID_BCI0_BY2                            = 0x24,
+	DBG_BLOCK_ID_BCI2_BY2                            = 0x25,
+	DBG_BLOCK_ID_UNUSED17_BY2                        = 0x26,
+	DBG_BLOCK_ID_UNUSED19_BY2                        = 0x27,
+	DBG_BLOCK_ID_CB00_BY2                            = 0x28,
+	DBG_BLOCK_ID_CB02_BY2                            = 0x29,
+	DBG_BLOCK_ID_CB04_BY2                            = 0x2a,
+	DBG_BLOCK_ID_UNUSED22_BY2                        = 0x2b,
+	DBG_BLOCK_ID_CB10_BY2                            = 0x2c,
+	DBG_BLOCK_ID_CB12_BY2                            = 0x2d,
+	DBG_BLOCK_ID_CB14_BY2                            = 0x2e,
+	DBG_BLOCK_ID_UNUSED25_BY2                        = 0x2f,
+	DBG_BLOCK_ID_TCP0_BY2                            = 0x30,
+	DBG_BLOCK_ID_TCP2_BY2                            = 0x31,
+	DBG_BLOCK_ID_TCP4_BY2                            = 0x32,
+	DBG_BLOCK_ID_TCP6_BY2                            = 0x33,
+	DBG_BLOCK_ID_TCP8_BY2                            = 0x34,
+	DBG_BLOCK_ID_TCP10_BY2                           = 0x35,
+	DBG_BLOCK_ID_TCP12_BY2                           = 0x36,
+	DBG_BLOCK_ID_TCP14_BY2                           = 0x37,
+	DBG_BLOCK_ID_TCP16_BY2                           = 0x38,
+	DBG_BLOCK_ID_TCP18_BY2                           = 0x39,
+	DBG_BLOCK_ID_TCP20_BY2                           = 0x3a,
+	DBG_BLOCK_ID_TCP22_BY2                           = 0x3b,
+	DBG_BLOCK_ID_TCP_RESERVED0_BY2                   = 0x3c,
+	DBG_BLOCK_ID_TCP_RESERVED2_BY2                   = 0x3d,
+	DBG_BLOCK_ID_TCP_RESERVED4_BY2                   = 0x3e,
+	DBG_BLOCK_ID_TCP_RESERVED6_BY2                   = 0x3f,
+	DBG_BLOCK_ID_DB00_BY2                            = 0x40,
+	DBG_BLOCK_ID_DB02_BY2                            = 0x41,
+	DBG_BLOCK_ID_DB04_BY2                            = 0x42,
+	DBG_BLOCK_ID_UNUSED28_BY2                        = 0x43,
+	DBG_BLOCK_ID_DB10_BY2                            = 0x44,
+	DBG_BLOCK_ID_DB12_BY2                            = 0x45,
+	DBG_BLOCK_ID_DB14_BY2                            = 0x46,
+	DBG_BLOCK_ID_UNUSED31_BY2                        = 0x47,
+	DBG_BLOCK_ID_TCC0_BY2                            = 0x48,
+	DBG_BLOCK_ID_TCC2_BY2                            = 0x49,
+	DBG_BLOCK_ID_TCC4_BY2                            = 0x4a,
+	DBG_BLOCK_ID_TCC6_BY2                            = 0x4b,
+	DBG_BLOCK_ID_SPS00_BY2                           = 0x4c,
+	DBG_BLOCK_ID_SPS02_BY2                           = 0x4d,
+	DBG_BLOCK_ID_SPS11_BY2                           = 0x4e,
+	DBG_BLOCK_ID_UNUSED33_BY2                        = 0x4f,
+	DBG_BLOCK_ID_TA00_BY2                            = 0x50,
+	DBG_BLOCK_ID_TA02_BY2                            = 0x51,
+	DBG_BLOCK_ID_TA04_BY2                            = 0x52,
+	DBG_BLOCK_ID_TA06_BY2                            = 0x53,
+	DBG_BLOCK_ID_TA08_BY2                            = 0x54,
+	DBG_BLOCK_ID_TA0A_BY2                            = 0x55,
+	DBG_BLOCK_ID_UNUSED35_BY2                        = 0x56,
+	DBG_BLOCK_ID_UNUSED37_BY2                        = 0x57,
+	DBG_BLOCK_ID_TA10_BY2                            = 0x58,
+	DBG_BLOCK_ID_TA12_BY2                            = 0x59,
+	DBG_BLOCK_ID_TA14_BY2                            = 0x5a,
+	DBG_BLOCK_ID_TA16_BY2                            = 0x5b,
+	DBG_BLOCK_ID_TA18_BY2                            = 0x5c,
+	DBG_BLOCK_ID_TA1A_BY2                            = 0x5d,
+	DBG_BLOCK_ID_UNUSED39_BY2                        = 0x5e,
+	DBG_BLOCK_ID_UNUSED41_BY2                        = 0x5f,
+	DBG_BLOCK_ID_TD00_BY2                            = 0x60,
+	DBG_BLOCK_ID_TD02_BY2                            = 0x61,
+	DBG_BLOCK_ID_TD04_BY2                            = 0x62,
+	DBG_BLOCK_ID_TD06_BY2                            = 0x63,
+	DBG_BLOCK_ID_TD08_BY2                            = 0x64,
+	DBG_BLOCK_ID_TD0A_BY2                            = 0x65,
+	DBG_BLOCK_ID_UNUSED43_BY2                        = 0x66,
+	DBG_BLOCK_ID_UNUSED45_BY2                        = 0x67,
+	DBG_BLOCK_ID_TD10_BY2                            = 0x68,
+	DBG_BLOCK_ID_TD12_BY2                            = 0x69,
+	DBG_BLOCK_ID_TD14_BY2                            = 0x6a,
+	DBG_BLOCK_ID_TD16_BY2                            = 0x6b,
+	DBG_BLOCK_ID_TD18_BY2                            = 0x6c,
+	DBG_BLOCK_ID_TD1A_BY2                            = 0x6d,
+	DBG_BLOCK_ID_UNUSED47_BY2                        = 0x6e,
+	DBG_BLOCK_ID_UNUSED49_BY2                        = 0x6f,
+	DBG_BLOCK_ID_MCD0_BY2                            = 0x70,
+	DBG_BLOCK_ID_MCD2_BY2                            = 0x71,
+	DBG_BLOCK_ID_MCD4_BY2                            = 0x72,
+	DBG_BLOCK_ID_UNUSED51_BY2                        = 0x73,
+} DebugBlockId_BY2;
+typedef enum DebugBlockId_BY4 {
+	DBG_BLOCK_ID_RESERVED_BY4                        = 0x0,
+	DBG_BLOCK_ID_CG_BY4                              = 0x1,
+	DBG_BLOCK_ID_CSC_BY4                             = 0x2,
+	DBG_BLOCK_ID_SQ_BY4                              = 0x3,
+	DBG_BLOCK_ID_DMA0_BY4                            = 0x4,
+	DBG_BLOCK_ID_SPIS_BY4                            = 0x5,
+	DBG_BLOCK_ID_CP0_BY4                             = 0x6,
+	DBG_BLOCK_ID_UVDU_BY4                            = 0x7,
+	DBG_BLOCK_ID_VGT0_BY4                            = 0x8,
+	DBG_BLOCK_ID_SCT0_BY4                            = 0x9,
+	DBG_BLOCK_ID_TCAA_BY4                            = 0xa,
+	DBG_BLOCK_ID_MCC0_BY4                            = 0xb,
+	DBG_BLOCK_ID_SX0_BY4                             = 0xc,
+	DBG_BLOCK_ID_UNUSED4_BY4                         = 0xd,
+	DBG_BLOCK_ID_PC0_BY4                             = 0xe,
+	DBG_BLOCK_ID_UNUSED10_BY4                        = 0xf,
+	DBG_BLOCK_ID_SCB0_BY4                            = 0x10,
+	DBG_BLOCK_ID_SCF0_BY4                            = 0x11,
+	DBG_BLOCK_ID_BCI0_BY4                            = 0x12,
+	DBG_BLOCK_ID_UNUSED17_BY4                        = 0x13,
+	DBG_BLOCK_ID_CB00_BY4                            = 0x14,
+	DBG_BLOCK_ID_CB04_BY4                            = 0x15,
+	DBG_BLOCK_ID_CB10_BY4                            = 0x16,
+	DBG_BLOCK_ID_CB14_BY4                            = 0x17,
+	DBG_BLOCK_ID_TCP0_BY4                            = 0x18,
+	DBG_BLOCK_ID_TCP4_BY4                            = 0x19,
+	DBG_BLOCK_ID_TCP8_BY4                            = 0x1a,
+	DBG_BLOCK_ID_TCP12_BY4                           = 0x1b,
+	DBG_BLOCK_ID_TCP16_BY4                           = 0x1c,
+	DBG_BLOCK_ID_TCP20_BY4                           = 0x1d,
+	DBG_BLOCK_ID_TCP_RESERVED0_BY4                   = 0x1e,
+	DBG_BLOCK_ID_TCP_RESERVED4_BY4                   = 0x1f,
+	DBG_BLOCK_ID_DB_BY4                              = 0x20,
+	DBG_BLOCK_ID_DB04_BY4                            = 0x21,
+	DBG_BLOCK_ID_DB10_BY4                            = 0x22,
+	DBG_BLOCK_ID_DB14_BY4                            = 0x23,
+	DBG_BLOCK_ID_TCC0_BY4                            = 0x24,
+	DBG_BLOCK_ID_TCC4_BY4                            = 0x25,
+	DBG_BLOCK_ID_SPS00_BY4                           = 0x26,
+	DBG_BLOCK_ID_SPS11_BY4                           = 0x27,
+	DBG_BLOCK_ID_TA00_BY4                            = 0x28,
+	DBG_BLOCK_ID_TA04_BY4                            = 0x29,
+	DBG_BLOCK_ID_TA08_BY4                            = 0x2a,
+	DBG_BLOCK_ID_UNUSED35_BY4                        = 0x2b,
+	DBG_BLOCK_ID_TA10_BY4                            = 0x2c,
+	DBG_BLOCK_ID_TA14_BY4                            = 0x2d,
+	DBG_BLOCK_ID_TA18_BY4                            = 0x2e,
+	DBG_BLOCK_ID_UNUSED39_BY4                        = 0x2f,
+	DBG_BLOCK_ID_TD00_BY4                            = 0x30,
+	DBG_BLOCK_ID_TD04_BY4                            = 0x31,
+	DBG_BLOCK_ID_TD08_BY4                            = 0x32,
+	DBG_BLOCK_ID_UNUSED43_BY4                        = 0x33,
+	DBG_BLOCK_ID_TD10_BY4                            = 0x34,
+	DBG_BLOCK_ID_TD14_BY4                            = 0x35,
+	DBG_BLOCK_ID_TD18_BY4                            = 0x36,
+	DBG_BLOCK_ID_UNUSED47_BY4                        = 0x37,
+	DBG_BLOCK_ID_MCD0_BY4                            = 0x38,
+	DBG_BLOCK_ID_MCD4_BY4                            = 0x39,
+} DebugBlockId_BY4;
+typedef enum DebugBlockId_BY8 {
+	DBG_BLOCK_ID_RESERVED_BY8                        = 0x0,
+	DBG_BLOCK_ID_CSC_BY8                             = 0x1,
+	DBG_BLOCK_ID_DMA0_BY8                            = 0x2,
+	DBG_BLOCK_ID_CP0_BY8                             = 0x3,
+	DBG_BLOCK_ID_VGT0_BY8                            = 0x4,
+	DBG_BLOCK_ID_TCAA_BY8                            = 0x5,
+	DBG_BLOCK_ID_SX0_BY8                             = 0x6,
+	DBG_BLOCK_ID_PC0_BY8                             = 0x7,
+	DBG_BLOCK_ID_SCB0_BY8                            = 0x8,
+	DBG_BLOCK_ID_BCI0_BY8                            = 0x9,
+	DBG_BLOCK_ID_CB00_BY8                            = 0xa,
+	DBG_BLOCK_ID_CB10_BY8                            = 0xb,
+	DBG_BLOCK_ID_TCP0_BY8                            = 0xc,
+	DBG_BLOCK_ID_TCP8_BY8                            = 0xd,
+	DBG_BLOCK_ID_TCP16_BY8                           = 0xe,
+	DBG_BLOCK_ID_TCP_RESERVED0_BY8                   = 0xf,
+	DBG_BLOCK_ID_DB00_BY8                            = 0x10,
+	DBG_BLOCK_ID_DB10_BY8                            = 0x11,
+	DBG_BLOCK_ID_TCC0_BY8                            = 0x12,
+	DBG_BLOCK_ID_SPS00_BY8                           = 0x13,
+	DBG_BLOCK_ID_TA00_BY8                            = 0x14,
+	DBG_BLOCK_ID_TA08_BY8                            = 0x15,
+	DBG_BLOCK_ID_TA10_BY8                            = 0x16,
+	DBG_BLOCK_ID_TA18_BY8                            = 0x17,
+	DBG_BLOCK_ID_TD00_BY8                            = 0x18,
+	DBG_BLOCK_ID_TD08_BY8                            = 0x19,
+	DBG_BLOCK_ID_TD10_BY8                            = 0x1a,
+	DBG_BLOCK_ID_TD18_BY8                            = 0x1b,
+	DBG_BLOCK_ID_MCD0_BY8                            = 0x1c,
+} DebugBlockId_BY8;
+typedef enum DebugBlockId_BY16 {
+	DBG_BLOCK_ID_RESERVED_BY16                       = 0x0,
+	DBG_BLOCK_ID_DMA0_BY16                           = 0x1,
+	DBG_BLOCK_ID_VGT0_BY16                           = 0x2,
+	DBG_BLOCK_ID_SX0_BY16                            = 0x3,
+	DBG_BLOCK_ID_SCB0_BY16                           = 0x4,
+	DBG_BLOCK_ID_CB00_BY16                           = 0x5,
+	DBG_BLOCK_ID_TCP0_BY16                           = 0x6,
+	DBG_BLOCK_ID_TCP16_BY16                          = 0x7,
+	DBG_BLOCK_ID_DB00_BY16                           = 0x8,
+	DBG_BLOCK_ID_TCC0_BY16                           = 0x9,
+	DBG_BLOCK_ID_TA00_BY16                           = 0xa,
+	DBG_BLOCK_ID_TA10_BY16                           = 0xb,
+	DBG_BLOCK_ID_TD00_BY16                           = 0xc,
+	DBG_BLOCK_ID_TD10_BY16                           = 0xd,
+	DBG_BLOCK_ID_MCD0_BY16                           = 0xe,
+} DebugBlockId_BY16;
+typedef enum ColorTransform {
+	DCC_CT_AUTO                                      = 0x0,
+	DCC_CT_NONE                                      = 0x1,
+	ABGR_TO_A_BG_G_RB                                = 0x2,
+	BGRA_TO_BG_G_RB_A                                = 0x3,
+} ColorTransform;
+typedef enum CompareRef {
+	REF_NEVER                                        = 0x0,
+	REF_LESS                                         = 0x1,
+	REF_EQUAL                                        = 0x2,
+	REF_LEQUAL                                       = 0x3,
+	REF_GREATER                                      = 0x4,
+	REF_NOTEQUAL                                     = 0x5,
+	REF_GEQUAL                                       = 0x6,
+	REF_ALWAYS                                       = 0x7,
+} CompareRef;
+typedef enum ReadSize {
+	READ_256_BITS                                    = 0x0,
+	READ_512_BITS                                    = 0x1,
+} ReadSize;
+typedef enum DepthFormat {
+	DEPTH_INVALID                                    = 0x0,
+	DEPTH_16                                         = 0x1,
+	DEPTH_X8_24                                      = 0x2,
+	DEPTH_8_24                                       = 0x3,
+	DEPTH_X8_24_FLOAT                                = 0x4,
+	DEPTH_8_24_FLOAT                                 = 0x5,
+	DEPTH_32_FLOAT                                   = 0x6,
+	DEPTH_X24_8_32_FLOAT                             = 0x7,
+} DepthFormat;
+typedef enum ZFormat {
+	Z_INVALID                                        = 0x0,
+	Z_16                                             = 0x1,
+	Z_24                                             = 0x2,
+	Z_32_FLOAT                                       = 0x3,
+} ZFormat;
+typedef enum StencilFormat {
+	STENCIL_INVALID                                  = 0x0,
+	STENCIL_8                                        = 0x1,
+} StencilFormat;
+typedef enum CmaskMode {
+	CMASK_CLEAR_NONE                                 = 0x0,
+	CMASK_CLEAR_ONE                                  = 0x1,
+	CMASK_CLEAR_ALL                                  = 0x2,
+	CMASK_ANY_EXPANDED                               = 0x3,
+	CMASK_ALPHA0_FRAG1                               = 0x4,
+	CMASK_ALPHA0_FRAG2                               = 0x5,
+	CMASK_ALPHA0_FRAG4                               = 0x6,
+	CMASK_ALPHA0_FRAGS                               = 0x7,
+	CMASK_ALPHA1_FRAG1                               = 0x8,
+	CMASK_ALPHA1_FRAG2                               = 0x9,
+	CMASK_ALPHA1_FRAG4                               = 0xa,
+	CMASK_ALPHA1_FRAGS                               = 0xb,
+	CMASK_ALPHAX_FRAG1                               = 0xc,
+	CMASK_ALPHAX_FRAG2                               = 0xd,
+	CMASK_ALPHAX_FRAG4                               = 0xe,
+	CMASK_ALPHAX_FRAGS                               = 0xf,
+} CmaskMode;
+typedef enum QuadExportFormat {
+	EXPORT_UNUSED                                    = 0x0,
+	EXPORT_32_R                                      = 0x1,
+	EXPORT_32_GR                                     = 0x2,
+	EXPORT_32_AR                                     = 0x3,
+	EXPORT_FP16_ABGR                                 = 0x4,
+	EXPORT_UNSIGNED16_ABGR                           = 0x5,
+	EXPORT_SIGNED16_ABGR                             = 0x6,
+	EXPORT_32_ABGR                                   = 0x7,
+} QuadExportFormat;
+typedef enum QuadExportFormatOld {
+	EXPORT_4P_32BPC_ABGR                             = 0x0,
+	EXPORT_4P_16BPC_ABGR                             = 0x1,
+	EXPORT_4P_32BPC_GR                               = 0x2,
+	EXPORT_4P_32BPC_AR                               = 0x3,
+	EXPORT_2P_32BPC_ABGR                             = 0x4,
+	EXPORT_8P_32BPC_R                                = 0x5,
+} QuadExportFormatOld;
+typedef enum ColorFormat {
+	COLOR_INVALID                                    = 0x0,
+	COLOR_8                                          = 0x1,
+	COLOR_16                                         = 0x2,
+	COLOR_8_8                                        = 0x3,
+	COLOR_32                                         = 0x4,
+	COLOR_16_16                                      = 0x5,
+	COLOR_10_11_11                                   = 0x6,
+	COLOR_11_11_10                                   = 0x7,
+	COLOR_10_10_10_2                                 = 0x8,
+	COLOR_2_10_10_10                                 = 0x9,
+	COLOR_8_8_8_8                                    = 0xa,
+	COLOR_32_32                                      = 0xb,
+	COLOR_16_16_16_16                                = 0xc,
+	COLOR_RESERVED_13                                = 0xd,
+	COLOR_32_32_32_32                                = 0xe,
+	COLOR_RESERVED_15                                = 0xf,
+	COLOR_5_6_5                                      = 0x10,
+	COLOR_1_5_5_5                                    = 0x11,
+	COLOR_5_5_5_1                                    = 0x12,
+	COLOR_4_4_4_4                                    = 0x13,
+	COLOR_8_24                                       = 0x14,
+	COLOR_24_8                                       = 0x15,
+	COLOR_X24_8_32_FLOAT                             = 0x16,
+	COLOR_RESERVED_23                                = 0x17,
+} ColorFormat;
+typedef enum SurfaceFormat {
+	FMT_INVALID                                      = 0x0,
+	FMT_8                                            = 0x1,
+	FMT_16                                           = 0x2,
+	FMT_8_8                                          = 0x3,
+	FMT_32                                           = 0x4,
+	FMT_16_16                                        = 0x5,
+	FMT_10_11_11                                     = 0x6,
+	FMT_11_11_10                                     = 0x7,
+	FMT_10_10_10_2                                   = 0x8,
+	FMT_2_10_10_10                                   = 0x9,
+	FMT_8_8_8_8                                      = 0xa,
+	FMT_32_32                                        = 0xb,
+	FMT_16_16_16_16                                  = 0xc,
+	FMT_32_32_32                                     = 0xd,
+	FMT_32_32_32_32                                  = 0xe,
+	FMT_RESERVED_4                                   = 0xf,
+	FMT_5_6_5                                        = 0x10,
+	FMT_1_5_5_5                                      = 0x11,
+	FMT_5_5_5_1                                      = 0x12,
+	FMT_4_4_4_4                                      = 0x13,
+	FMT_8_24                                         = 0x14,
+	FMT_24_8                                         = 0x15,
+	FMT_X24_8_32_FLOAT                               = 0x16,
+	FMT_RESERVED_33                                  = 0x17,
+	FMT_11_11_10_FLOAT                               = 0x18,
+	FMT_16_FLOAT                                     = 0x19,
+	FMT_32_FLOAT                                     = 0x1a,
+	FMT_16_16_FLOAT                                  = 0x1b,
+	FMT_8_24_FLOAT                                   = 0x1c,
+	FMT_24_8_FLOAT                                   = 0x1d,
+	FMT_32_32_FLOAT                                  = 0x1e,
+	FMT_10_11_11_FLOAT                               = 0x1f,
+	FMT_16_16_16_16_FLOAT                            = 0x20,
+	FMT_3_3_2                                        = 0x21,
+	FMT_6_5_5                                        = 0x22,
+	FMT_32_32_32_32_FLOAT                            = 0x23,
+	FMT_RESERVED_36                                  = 0x24,
+	FMT_1                                            = 0x25,
+	FMT_1_REVERSED                                   = 0x26,
+	FMT_GB_GR                                        = 0x27,
+	FMT_BG_RG                                        = 0x28,
+	FMT_32_AS_8                                      = 0x29,
+	FMT_32_AS_8_8                                    = 0x2a,
+	FMT_5_9_9_9_SHAREDEXP                            = 0x2b,
+	FMT_8_8_8                                        = 0x2c,
+	FMT_16_16_16                                     = 0x2d,
+	FMT_16_16_16_FLOAT                               = 0x2e,
+	FMT_4_4                                          = 0x2f,
+	FMT_32_32_32_FLOAT                               = 0x30,
+	FMT_BC1                                          = 0x31,
+	FMT_BC2                                          = 0x32,
+	FMT_BC3                                          = 0x33,
+	FMT_BC4                                          = 0x34,
+	FMT_BC5                                          = 0x35,
+	FMT_BC6                                          = 0x36,
+	FMT_BC7                                          = 0x37,
+	FMT_32_AS_32_32_32_32                            = 0x38,
+	FMT_APC3                                         = 0x39,
+	FMT_APC4                                         = 0x3a,
+	FMT_APC5                                         = 0x3b,
+	FMT_APC6                                         = 0x3c,
+	FMT_APC7                                         = 0x3d,
+	FMT_CTX1                                         = 0x3e,
+	FMT_RESERVED_63                                  = 0x3f,
+} SurfaceFormat;
+typedef enum BUF_DATA_FORMAT {
+	BUF_DATA_FORMAT_INVALID                          = 0x0,
+	BUF_DATA_FORMAT_8                                = 0x1,
+	BUF_DATA_FORMAT_16                               = 0x2,
+	BUF_DATA_FORMAT_8_8                              = 0x3,
+	BUF_DATA_FORMAT_32                               = 0x4,
+	BUF_DATA_FORMAT_16_16                            = 0x5,
+	BUF_DATA_FORMAT_10_11_11                         = 0x6,
+	BUF_DATA_FORMAT_11_11_10                         = 0x7,
+	BUF_DATA_FORMAT_10_10_10_2                       = 0x8,
+	BUF_DATA_FORMAT_2_10_10_10                       = 0x9,
+	BUF_DATA_FORMAT_8_8_8_8                          = 0xa,
+	BUF_DATA_FORMAT_32_32                            = 0xb,
+	BUF_DATA_FORMAT_16_16_16_16                      = 0xc,
+	BUF_DATA_FORMAT_32_32_32                         = 0xd,
+	BUF_DATA_FORMAT_32_32_32_32                      = 0xe,
+	BUF_DATA_FORMAT_RESERVED_15                      = 0xf,
+} BUF_DATA_FORMAT;
+typedef enum IMG_DATA_FORMAT {
+	IMG_DATA_FORMAT_INVALID                          = 0x0,
+	IMG_DATA_FORMAT_8                                = 0x1,
+	IMG_DATA_FORMAT_16                               = 0x2,
+	IMG_DATA_FORMAT_8_8                              = 0x3,
+	IMG_DATA_FORMAT_32                               = 0x4,
+	IMG_DATA_FORMAT_16_16                            = 0x5,
+	IMG_DATA_FORMAT_10_11_11                         = 0x6,
+	IMG_DATA_FORMAT_11_11_10                         = 0x7,
+	IMG_DATA_FORMAT_10_10_10_2                       = 0x8,
+	IMG_DATA_FORMAT_2_10_10_10                       = 0x9,
+	IMG_DATA_FORMAT_8_8_8_8                          = 0xa,
+	IMG_DATA_FORMAT_32_32                            = 0xb,
+	IMG_DATA_FORMAT_16_16_16_16                      = 0xc,
+	IMG_DATA_FORMAT_32_32_32                         = 0xd,
+	IMG_DATA_FORMAT_32_32_32_32                      = 0xe,
+	IMG_DATA_FORMAT_RESERVED_15                      = 0xf,
+	IMG_DATA_FORMAT_5_6_5                            = 0x10,
+	IMG_DATA_FORMAT_1_5_5_5                          = 0x11,
+	IMG_DATA_FORMAT_5_5_5_1                          = 0x12,
+	IMG_DATA_FORMAT_4_4_4_4                          = 0x13,
+	IMG_DATA_FORMAT_8_24                             = 0x14,
+	IMG_DATA_FORMAT_24_8                             = 0x15,
+	IMG_DATA_FORMAT_X24_8_32                         = 0x16,
+	IMG_DATA_FORMAT_RESERVED_23                      = 0x17,
+	IMG_DATA_FORMAT_RESERVED_24                      = 0x18,
+	IMG_DATA_FORMAT_RESERVED_25                      = 0x19,
+	IMG_DATA_FORMAT_RESERVED_26                      = 0x1a,
+	IMG_DATA_FORMAT_RESERVED_27                      = 0x1b,
+	IMG_DATA_FORMAT_RESERVED_28                      = 0x1c,
+	IMG_DATA_FORMAT_RESERVED_29                      = 0x1d,
+	IMG_DATA_FORMAT_RESERVED_30                      = 0x1e,
+	IMG_DATA_FORMAT_RESERVED_31                      = 0x1f,
+	IMG_DATA_FORMAT_GB_GR                            = 0x20,
+	IMG_DATA_FORMAT_BG_RG                            = 0x21,
+	IMG_DATA_FORMAT_5_9_9_9                          = 0x22,
+	IMG_DATA_FORMAT_BC1                              = 0x23,
+	IMG_DATA_FORMAT_BC2                              = 0x24,
+	IMG_DATA_FORMAT_BC3                              = 0x25,
+	IMG_DATA_FORMAT_BC4                              = 0x26,
+	IMG_DATA_FORMAT_BC5                              = 0x27,
+	IMG_DATA_FORMAT_BC6                              = 0x28,
+	IMG_DATA_FORMAT_BC7                              = 0x29,
+	IMG_DATA_FORMAT_RESERVED_42                      = 0x2a,
+	IMG_DATA_FORMAT_RESERVED_43                      = 0x2b,
+	IMG_DATA_FORMAT_FMASK8_S2_F1                     = 0x2c,
+	IMG_DATA_FORMAT_FMASK8_S4_F1                     = 0x2d,
+	IMG_DATA_FORMAT_FMASK8_S8_F1                     = 0x2e,
+	IMG_DATA_FORMAT_FMASK8_S2_F2                     = 0x2f,
+	IMG_DATA_FORMAT_FMASK8_S4_F2                     = 0x30,
+	IMG_DATA_FORMAT_FMASK8_S4_F4                     = 0x31,
+	IMG_DATA_FORMAT_FMASK16_S16_F1                   = 0x32,
+	IMG_DATA_FORMAT_FMASK16_S8_F2                    = 0x33,
+	IMG_DATA_FORMAT_FMASK32_S16_F2                   = 0x34,
+	IMG_DATA_FORMAT_FMASK32_S8_F4                    = 0x35,
+	IMG_DATA_FORMAT_FMASK32_S8_F8                    = 0x36,
+	IMG_DATA_FORMAT_FMASK64_S16_F4                   = 0x37,
+	IMG_DATA_FORMAT_FMASK64_S16_F8                   = 0x38,
+	IMG_DATA_FORMAT_4_4                              = 0x39,
+	IMG_DATA_FORMAT_6_5_5                            = 0x3a,
+	IMG_DATA_FORMAT_1                                = 0x3b,
+	IMG_DATA_FORMAT_1_REVERSED                       = 0x3c,
+	IMG_DATA_FORMAT_32_AS_8                          = 0x3d,
+	IMG_DATA_FORMAT_32_AS_8_8                        = 0x3e,
+	IMG_DATA_FORMAT_32_AS_32_32_32_32                = 0x3f,
+} IMG_DATA_FORMAT;
+typedef enum BUF_NUM_FORMAT {
+	BUF_NUM_FORMAT_UNORM                             = 0x0,
+	BUF_NUM_FORMAT_SNORM                             = 0x1,
+	BUF_NUM_FORMAT_USCALED                           = 0x2,
+	BUF_NUM_FORMAT_SSCALED                           = 0x3,
+	BUF_NUM_FORMAT_UINT                              = 0x4,
+	BUF_NUM_FORMAT_SINT                              = 0x5,
+	BUF_NUM_FORMAT_RESERVED_6                        = 0x6,
+	BUF_NUM_FORMAT_FLOAT                             = 0x7,
+} BUF_NUM_FORMAT;
+typedef enum IMG_NUM_FORMAT {
+	IMG_NUM_FORMAT_UNORM                             = 0x0,
+	IMG_NUM_FORMAT_SNORM                             = 0x1,
+	IMG_NUM_FORMAT_USCALED                           = 0x2,
+	IMG_NUM_FORMAT_SSCALED                           = 0x3,
+	IMG_NUM_FORMAT_UINT                              = 0x4,
+	IMG_NUM_FORMAT_SINT                              = 0x5,
+	IMG_NUM_FORMAT_RESERVED_6                        = 0x6,
+	IMG_NUM_FORMAT_FLOAT                             = 0x7,
+	IMG_NUM_FORMAT_RESERVED_8                        = 0x8,
+	IMG_NUM_FORMAT_SRGB                              = 0x9,
+	IMG_NUM_FORMAT_RESERVED_10                       = 0xa,
+	IMG_NUM_FORMAT_RESERVED_11                       = 0xb,
+	IMG_NUM_FORMAT_RESERVED_12                       = 0xc,
+	IMG_NUM_FORMAT_RESERVED_13                       = 0xd,
+	IMG_NUM_FORMAT_RESERVED_14                       = 0xe,
+	IMG_NUM_FORMAT_RESERVED_15                       = 0xf,
+} IMG_NUM_FORMAT;
+typedef enum TileType {
+	ARRAY_COLOR_TILE                                 = 0x0,
+	ARRAY_DEPTH_TILE                                 = 0x1,
+} TileType;
+typedef enum NonDispTilingOrder {
+	ADDR_SURF_MICRO_TILING_DISPLAY                   = 0x0,
+	ADDR_SURF_MICRO_TILING_NON_DISPLAY               = 0x1,
+} NonDispTilingOrder;
+typedef enum MicroTileMode {
+	ADDR_SURF_DISPLAY_MICRO_TILING                   = 0x0,
+	ADDR_SURF_THIN_MICRO_TILING                      = 0x1,
+	ADDR_SURF_DEPTH_MICRO_TILING                     = 0x2,
+	ADDR_SURF_ROTATED_MICRO_TILING                   = 0x3,
+	ADDR_SURF_THICK_MICRO_TILING                     = 0x4,
+} MicroTileMode;
+typedef enum TileSplit {
+	ADDR_SURF_TILE_SPLIT_64B                         = 0x0,
+	ADDR_SURF_TILE_SPLIT_128B                        = 0x1,
+	ADDR_SURF_TILE_SPLIT_256B                        = 0x2,
+	ADDR_SURF_TILE_SPLIT_512B                        = 0x3,
+	ADDR_SURF_TILE_SPLIT_1KB                         = 0x4,
+	ADDR_SURF_TILE_SPLIT_2KB                         = 0x5,
+	ADDR_SURF_TILE_SPLIT_4KB                         = 0x6,
+} TileSplit;
+typedef enum SampleSplit {
+	ADDR_SURF_SAMPLE_SPLIT_1                         = 0x0,
+	ADDR_SURF_SAMPLE_SPLIT_2                         = 0x1,
+	ADDR_SURF_SAMPLE_SPLIT_4                         = 0x2,
+	ADDR_SURF_SAMPLE_SPLIT_8                         = 0x3,
+} SampleSplit;
+typedef enum PipeConfig {
+	ADDR_SURF_P2                                     = 0x0,
+	ADDR_SURF_P2_RESERVED0                           = 0x1,
+	ADDR_SURF_P2_RESERVED1                           = 0x2,
+	ADDR_SURF_P2_RESERVED2                           = 0x3,
+	ADDR_SURF_P4_8x16                                = 0x4,
+	ADDR_SURF_P4_16x16                               = 0x5,
+	ADDR_SURF_P4_16x32                               = 0x6,
+	ADDR_SURF_P4_32x32                               = 0x7,
+	ADDR_SURF_P8_16x16_8x16                          = 0x8,
+	ADDR_SURF_P8_16x32_8x16                          = 0x9,
+	ADDR_SURF_P8_32x32_8x16                          = 0xa,
+	ADDR_SURF_P8_16x32_16x16                         = 0xb,
+	ADDR_SURF_P8_32x32_16x16                         = 0xc,
+	ADDR_SURF_P8_32x32_16x32                         = 0xd,
+	ADDR_SURF_P8_32x64_32x32                         = 0xe,
+	ADDR_SURF_P8_RESERVED0                           = 0xf,
+	ADDR_SURF_P16_32x32_8x16                         = 0x10,
+	ADDR_SURF_P16_32x32_16x16                        = 0x11,
+} PipeConfig;
+typedef enum NumBanks {
+	ADDR_SURF_2_BANK                                 = 0x0,
+	ADDR_SURF_4_BANK                                 = 0x1,
+	ADDR_SURF_8_BANK                                 = 0x2,
+	ADDR_SURF_16_BANK                                = 0x3,
+} NumBanks;
+typedef enum BankWidth {
+	ADDR_SURF_BANK_WIDTH_1                           = 0x0,
+	ADDR_SURF_BANK_WIDTH_2                           = 0x1,
+	ADDR_SURF_BANK_WIDTH_4                           = 0x2,
+	ADDR_SURF_BANK_WIDTH_8                           = 0x3,
+} BankWidth;
+typedef enum BankHeight {
+	ADDR_SURF_BANK_HEIGHT_1                          = 0x0,
+	ADDR_SURF_BANK_HEIGHT_2                          = 0x1,
+	ADDR_SURF_BANK_HEIGHT_4                          = 0x2,
+	ADDR_SURF_BANK_HEIGHT_8                          = 0x3,
+} BankHeight;
+typedef enum BankWidthHeight {
+	ADDR_SURF_BANK_WH_1                              = 0x0,
+	ADDR_SURF_BANK_WH_2                              = 0x1,
+	ADDR_SURF_BANK_WH_4                              = 0x2,
+	ADDR_SURF_BANK_WH_8                              = 0x3,
+} BankWidthHeight;
+typedef enum MacroTileAspect {
+	ADDR_SURF_MACRO_ASPECT_1                         = 0x0,
+	ADDR_SURF_MACRO_ASPECT_2                         = 0x1,
+	ADDR_SURF_MACRO_ASPECT_4                         = 0x2,
+	ADDR_SURF_MACRO_ASPECT_8                         = 0x3,
+} MacroTileAspect;
+typedef enum GATCL1RequestType {
+	GATCL1_TYPE_NORMAL                               = 0x0,
+	GATCL1_TYPE_SHOOTDOWN                            = 0x1,
+	GATCL1_TYPE_BYPASS                               = 0x2,
+} GATCL1RequestType;
+typedef enum TCC_CACHE_POLICIES {
+	TCC_CACHE_POLICY_LRU                             = 0x0,
+	TCC_CACHE_POLICY_STREAM                          = 0x1,
+} TCC_CACHE_POLICIES;
+typedef enum MTYPE {
+	MTYPE_NC_NV                                      = 0x0,
+	MTYPE_NC                                         = 0x1,
+	MTYPE_CC                                         = 0x2,
+	MTYPE_UC                                         = 0x3,
+} MTYPE;
+typedef enum PERFMON_COUNTER_MODE {
+	PERFMON_COUNTER_MODE_ACCUM                       = 0x0,
+	PERFMON_COUNTER_MODE_ACTIVE_CYCLES               = 0x1,
+	PERFMON_COUNTER_MODE_MAX                         = 0x2,
+	PERFMON_COUNTER_MODE_DIRTY                       = 0x3,
+	PERFMON_COUNTER_MODE_SAMPLE                      = 0x4,
+	PERFMON_COUNTER_MODE_CYCLES_SINCE_FIRST_EVENT    = 0x5,
+	PERFMON_COUNTER_MODE_CYCLES_SINCE_LAST_EVENT     = 0x6,
+	PERFMON_COUNTER_MODE_CYCLES_GE_HI                = 0x7,
+	PERFMON_COUNTER_MODE_CYCLES_EQ_HI                = 0x8,
+	PERFMON_COUNTER_MODE_INACTIVE_CYCLES             = 0x9,
+	PERFMON_COUNTER_MODE_RESERVED                    = 0xf,
+} PERFMON_COUNTER_MODE;
+typedef enum PERFMON_SPM_MODE {
+	PERFMON_SPM_MODE_OFF                             = 0x0,
+	PERFMON_SPM_MODE_16BIT_CLAMP                     = 0x1,
+	PERFMON_SPM_MODE_16BIT_NO_CLAMP                  = 0x2,
+	PERFMON_SPM_MODE_32BIT_CLAMP                     = 0x3,
+	PERFMON_SPM_MODE_32BIT_NO_CLAMP                  = 0x4,
+	PERFMON_SPM_MODE_RESERVED_5                      = 0x5,
+	PERFMON_SPM_MODE_RESERVED_6                      = 0x6,
+	PERFMON_SPM_MODE_RESERVED_7                      = 0x7,
+	PERFMON_SPM_MODE_TEST_MODE_0                     = 0x8,
+	PERFMON_SPM_MODE_TEST_MODE_1                     = 0x9,
+	PERFMON_SPM_MODE_TEST_MODE_2                     = 0xa,
+} PERFMON_SPM_MODE;
+typedef enum SurfaceTiling {
+	ARRAY_LINEAR                                     = 0x0,
+	ARRAY_TILED                                      = 0x1,
+} SurfaceTiling;
+typedef enum SurfaceArray {
+	ARRAY_1D                                         = 0x0,
+	ARRAY_2D                                         = 0x1,
+	ARRAY_3D                                         = 0x2,
+	ARRAY_3D_SLICE                                   = 0x3,
+} SurfaceArray;
+typedef enum ColorArray {
+	ARRAY_2D_ALT_COLOR                               = 0x0,
+	ARRAY_2D_COLOR                                   = 0x1,
+	ARRAY_3D_SLICE_COLOR                             = 0x3,
+} ColorArray;
+typedef enum DepthArray {
+	ARRAY_2D_ALT_DEPTH                               = 0x0,
+	ARRAY_2D_DEPTH                                   = 0x1,
+} DepthArray;
+typedef enum ENUM_NUM_SIMD_PER_CU {
+	NUM_SIMD_PER_CU                                  = 0x4,
+} ENUM_NUM_SIMD_PER_CU;
+typedef enum MEM_PWR_FORCE_CTRL {
+	NO_FORCE_REQUEST                                 = 0x0,
+	FORCE_LIGHT_SLEEP_REQUEST                        = 0x1,
+	FORCE_DEEP_SLEEP_REQUEST                         = 0x2,
+	FORCE_SHUT_DOWN_REQUEST                          = 0x3,
+} MEM_PWR_FORCE_CTRL;
+typedef enum MEM_PWR_FORCE_CTRL2 {
+	NO_FORCE_REQ                                     = 0x0,
+	FORCE_LIGHT_SLEEP_REQ                            = 0x1,
+} MEM_PWR_FORCE_CTRL2;
+typedef enum MEM_PWR_DIS_CTRL {
+	ENABLE_MEM_PWR_CTRL                              = 0x0,
+	DISABLE_MEM_PWR_CTRL                             = 0x1,
+} MEM_PWR_DIS_CTRL;
+typedef enum MEM_PWR_SEL_CTRL {
+	DYNAMIC_SHUT_DOWN_ENABLE                         = 0x0,
+	DYNAMIC_DEEP_SLEEP_ENABLE                        = 0x1,
+	DYNAMIC_LIGHT_SLEEP_ENABLE                       = 0x2,
+} MEM_PWR_SEL_CTRL;
+typedef enum MEM_PWR_SEL_CTRL2 {
+	DYNAMIC_DEEP_SLEEP_EN                            = 0x0,
+	DYNAMIC_LIGHT_SLEEP_EN                           = 0x1,
+} MEM_PWR_SEL_CTRL2;
+typedef enum HPD_INT_CONTROL_ACK {
+	HPD_INT_CONTROL_ACK_0                            = 0x0,
+	HPD_INT_CONTROL_ACK_1                            = 0x1,
+} HPD_INT_CONTROL_ACK;
+typedef enum HPD_INT_CONTROL_POLARITY {
+	HPD_INT_CONTROL_GEN_INT_ON_DISCON                = 0x0,
+	HPD_INT_CONTROL_GEN_INT_ON_CON                   = 0x1,
+} HPD_INT_CONTROL_POLARITY;
+typedef enum HPD_INT_CONTROL_RX_INT_ACK {
+	HPD_INT_CONTROL_RX_INT_ACK_0                     = 0x0,
+	HPD_INT_CONTROL_RX_INT_ACK_1                     = 0x1,
+} HPD_INT_CONTROL_RX_INT_ACK;
+typedef enum DPDBG_EN {
+	DPDBG_DISABLE                                    = 0x0,
+	DPDBG_ENABLE                                     = 0x1,
+} DPDBG_EN;
+typedef enum DPDBG_INPUT_EN {
+	DPDBG_INPUT_DISABLE                              = 0x0,
+	DPDBG_INPUT_ENABLE                               = 0x1,
+} DPDBG_INPUT_EN;
+typedef enum DPDBG_ERROR_DETECTION_MODE {
+	DPDBG_ERROR_DETECTION_MODE_CSC                   = 0x0,
+	DPDBG_ERROR_DETECTION_MODE_RS_ENCODING           = 0x1,
+} DPDBG_ERROR_DETECTION_MODE;
+typedef enum DPDBG_FIFO_OVERFLOW_INTERRUPT_MASK {
+	DPDBG_FIFO_OVERFLOW_INT_DISABLE                  = 0x0,
+	DPDBG_FIFO_OVERFLOW_INT_ENABLE                   = 0x1,
+} DPDBG_FIFO_OVERFLOW_INTERRUPT_MASK;
+typedef enum DPDBG_FIFO_OVERFLOW_INTERRUPT_TYPE {
+	DPDBG_FIFO_OVERFLOW_INT_LEVEL_BASED              = 0x0,
+	DPDBG_FIFO_OVERFLOW_INT_PULSE_BASED              = 0x1,
+} DPDBG_FIFO_OVERFLOW_INTERRUPT_TYPE;
+typedef enum DPDBG_FIFO_OVERFLOW_INTERRUPT_ACK {
+	DPDBG_FIFO_OVERFLOW_INT_NO_ACK                   = 0x0,
+	DPDBG_FIFO_OVERFLOW_INT_CLEAR                    = 0x1,
+} DPDBG_FIFO_OVERFLOW_INTERRUPT_ACK;
+typedef enum PM_ASSERT_RESET {
+	PM_ASSERT_RESET_0                                = 0x0,
+	PM_ASSERT_RESET_1                                = 0x1,
+} PM_ASSERT_RESET;
+typedef enum DAC_MUX_SELECT {
+	DAC_MUX_SELECT_DACA                              = 0x0,
+	DAC_MUX_SELECT_DACB                              = 0x1,
+} DAC_MUX_SELECT;
+typedef enum TMDS_DVO_MUX_SELECT {
+	TMDS_DVO_MUX_SELECT_B                            = 0x0,
+	TMDS_DVO_MUX_SELECT_G                            = 0x1,
+	TMDS_DVO_MUX_SELECT_R                            = 0x2,
+	TMDS_DVO_MUX_SELECT_RESERVED                     = 0x3,
+} TMDS_DVO_MUX_SELECT;
+typedef enum DACA_SOFT_RESET {
+	DACA_SOFT_RESET_0                                = 0x0,
+	DACA_SOFT_RESET_1                                = 0x1,
+} DACA_SOFT_RESET;
+typedef enum I2S0_SPDIF0_SOFT_RESET {
+	I2S0_SPDIF0_SOFT_RESET_0                         = 0x0,
+	I2S0_SPDIF0_SOFT_RESET_1                         = 0x1,
+} I2S0_SPDIF0_SOFT_RESET;
+typedef enum I2S1_SOFT_RESET {
+	I2S1_SOFT_RESET_0                                = 0x0,
+	I2S1_SOFT_RESET_1                                = 0x1,
+} I2S1_SOFT_RESET;
+typedef enum SPDIF1_SOFT_RESET {
+	SPDIF1_SOFT_RESET_0                              = 0x0,
+	SPDIF1_SOFT_RESET_1                              = 0x1,
+} SPDIF1_SOFT_RESET;
+typedef enum DB_CLK_SOFT_RESET {
+	DB_CLK_SOFT_RESET_0                              = 0x0,
+	DB_CLK_SOFT_RESET_1                              = 0x1,
+} DB_CLK_SOFT_RESET;
+typedef enum FMT0_SOFT_RESET {
+	FMT0_SOFT_RESET_0                                = 0x0,
+	FMT0_SOFT_RESET_1                                = 0x1,
+} FMT0_SOFT_RESET;
+typedef enum FMT1_SOFT_RESET {
+	FMT1_SOFT_RESET_0                                = 0x0,
+	FMT1_SOFT_RESET_1                                = 0x1,
+} FMT1_SOFT_RESET;
+typedef enum FMT2_SOFT_RESET {
+	FMT2_SOFT_RESET_0                                = 0x0,
+	FMT2_SOFT_RESET_1                                = 0x1,
+} FMT2_SOFT_RESET;
+typedef enum FMT3_SOFT_RESET {
+	FMT3_SOFT_RESET_0                                = 0x0,
+	FMT3_SOFT_RESET_1                                = 0x1,
+} FMT3_SOFT_RESET;
+typedef enum FMT4_SOFT_RESET {
+	FMT4_SOFT_RESET_0                                = 0x0,
+	FMT4_SOFT_RESET_1                                = 0x1,
+} FMT4_SOFT_RESET;
+typedef enum FMT5_SOFT_RESET {
+	FMT5_SOFT_RESET_0                                = 0x0,
+	FMT5_SOFT_RESET_1                                = 0x1,
+} FMT5_SOFT_RESET;
+typedef enum MVP_SOFT_RESET {
+	MVP_SOFT_RESET_0                                 = 0x0,
+	MVP_SOFT_RESET_1                                 = 0x1,
+} MVP_SOFT_RESET;
+typedef enum ABM_SOFT_RESET {
+	ABM_SOFT_RESET_0                                 = 0x0,
+	ABM_SOFT_RESET_1                                 = 0x1,
+} ABM_SOFT_RESET;
+typedef enum DVO_SOFT_RESET {
+	DVO_SOFT_RESET_0                                 = 0x0,
+	DVO_SOFT_RESET_1                                 = 0x1,
+} DVO_SOFT_RESET;
+typedef enum DIGA_FE_SOFT_RESET {
+	DIGA_FE_SOFT_RESET_0                             = 0x0,
+	DIGA_FE_SOFT_RESET_1                             = 0x1,
+} DIGA_FE_SOFT_RESET;
+typedef enum DIGA_BE_SOFT_RESET {
+	DIGA_BE_SOFT_RESET_0                             = 0x0,
+	DIGA_BE_SOFT_RESET_1                             = 0x1,
+} DIGA_BE_SOFT_RESET;
+typedef enum DIGB_FE_SOFT_RESET {
+	DIGB_FE_SOFT_RESET_0                             = 0x0,
+	DIGB_FE_SOFT_RESET_1                             = 0x1,
+} DIGB_FE_SOFT_RESET;
+typedef enum DIGB_BE_SOFT_RESET {
+	DIGB_BE_SOFT_RESET_0                             = 0x0,
+	DIGB_BE_SOFT_RESET_1                             = 0x1,
+} DIGB_BE_SOFT_RESET;
+typedef enum DIGC_FE_SOFT_RESET {
+	DIGC_FE_SOFT_RESET_0                             = 0x0,
+	DIGC_FE_SOFT_RESET_1                             = 0x1,
+} DIGC_FE_SOFT_RESET;
+typedef enum DIGC_BE_SOFT_RESET {
+	DIGC_BE_SOFT_RESET_0                             = 0x0,
+	DIGC_BE_SOFT_RESET_1                             = 0x1,
+} DIGC_BE_SOFT_RESET;
+typedef enum DIGD_FE_SOFT_RESET {
+	DIGD_FE_SOFT_RESET_0                             = 0x0,
+	DIGD_FE_SOFT_RESET_1                             = 0x1,
+} DIGD_FE_SOFT_RESET;
+typedef enum DIGD_BE_SOFT_RESET {
+	DIGD_BE_SOFT_RESET_0                             = 0x0,
+	DIGD_BE_SOFT_RESET_1                             = 0x1,
+} DIGD_BE_SOFT_RESET;
+typedef enum DIGE_FE_SOFT_RESET {
+	DIGE_FE_SOFT_RESET_0                             = 0x0,
+	DIGE_FE_SOFT_RESET_1                             = 0x1,
+} DIGE_FE_SOFT_RESET;
+typedef enum DIGE_BE_SOFT_RESET {
+	DIGE_BE_SOFT_RESET_0                             = 0x0,
+	DIGE_BE_SOFT_RESET_1                             = 0x1,
+} DIGE_BE_SOFT_RESET;
+typedef enum DIGF_FE_SOFT_RESET {
+	DIGF_FE_SOFT_RESET_0                             = 0x0,
+	DIGF_FE_SOFT_RESET_1                             = 0x1,
+} DIGF_FE_SOFT_RESET;
+typedef enum DIGF_BE_SOFT_RESET {
+	DIGF_BE_SOFT_RESET_0                             = 0x0,
+	DIGF_BE_SOFT_RESET_1                             = 0x1,
+} DIGF_BE_SOFT_RESET;
+typedef enum DIGG_FE_SOFT_RESET {
+	DIGG_FE_SOFT_RESET_0                             = 0x0,
+	DIGG_FE_SOFT_RESET_1                             = 0x1,
+} DIGG_FE_SOFT_RESET;
+typedef enum DIGG_BE_SOFT_RESET {
+	DIGG_BE_SOFT_RESET_0                             = 0x0,
+	DIGG_BE_SOFT_RESET_1                             = 0x1,
+} DIGG_BE_SOFT_RESET;
+typedef enum DPDBG_SOFT_RESET {
+	DPDBG_SOFT_RESET_0                               = 0x0,
+	DPDBG_SOFT_RESET_1                               = 0x1,
+} DPDBG_SOFT_RESET;
+typedef enum DIGLPA_FE_SOFT_RESET {
+	DIGLPA_FE_SOFT_RESET_0                           = 0x0,
+	DIGLPA_FE_SOFT_RESET_1                           = 0x1,
+} DIGLPA_FE_SOFT_RESET;
+typedef enum DIGLPA_BE_SOFT_RESET {
+	DIGLPA_BE_SOFT_RESET_0                           = 0x0,
+	DIGLPA_BE_SOFT_RESET_1                           = 0x1,
+} DIGLPA_BE_SOFT_RESET;
+typedef enum DIGLPB_FE_SOFT_RESET {
+	DIGLPB_FE_SOFT_RESET_0                           = 0x0,
+	DIGLPB_FE_SOFT_RESET_1                           = 0x1,
+} DIGLPB_FE_SOFT_RESET;
+typedef enum DIGLPB_BE_SOFT_RESET {
+	DIGLPB_BE_SOFT_RESET_0                           = 0x0,
+	DIGLPB_BE_SOFT_RESET_1                           = 0x1,
+} DIGLPB_BE_SOFT_RESET;
+typedef enum GENERICA_STEREOSYNC_SEL {
+	GENERICA_STEREOSYNC_SEL_D1                       = 0x0,
+	GENERICA_STEREOSYNC_SEL_D2                       = 0x1,
+	GENERICA_STEREOSYNC_SEL_D3                       = 0x2,
+	GENERICA_STEREOSYNC_SEL_D4                       = 0x3,
+	GENERICA_STEREOSYNC_SEL_D5                       = 0x4,
+	GENERICA_STEREOSYNC_SEL_D6                       = 0x5,
+	GENERICA_STEREOSYNC_SEL_RESERVED                 = 0x6,
+} GENERICA_STEREOSYNC_SEL;
+typedef enum GENERICB_STEREOSYNC_SEL {
+	GENERICB_STEREOSYNC_SEL_D1                       = 0x0,
+	GENERICB_STEREOSYNC_SEL_D2                       = 0x1,
+	GENERICB_STEREOSYNC_SEL_D3                       = 0x2,
+	GENERICB_STEREOSYNC_SEL_D4                       = 0x3,
+	GENERICB_STEREOSYNC_SEL_D5                       = 0x4,
+	GENERICB_STEREOSYNC_SEL_D6                       = 0x5,
+	GENERICB_STEREOSYNC_SEL_RESERVED                 = 0x6,
+} GENERICB_STEREOSYNC_SEL;
+typedef enum DCO_DBG_BLOCK_SEL {
+	DCO_DBG_BLOCK_SEL_DCO                            = 0x0,
+	DCO_DBG_BLOCK_SEL_ABM                            = 0x1,
+	DCO_DBG_BLOCK_SEL_DVO                            = 0x2,
+	DCO_DBG_BLOCK_SEL_DAC                            = 0x3,
+	DCO_DBG_BLOCK_SEL_MVP                            = 0x4,
+	DCO_DBG_BLOCK_SEL_FMT0                           = 0x5,
+	DCO_DBG_BLOCK_SEL_FMT1                           = 0x6,
+	DCO_DBG_BLOCK_SEL_FMT2                           = 0x7,
+	DCO_DBG_BLOCK_SEL_FMT3                           = 0x8,
+	DCO_DBG_BLOCK_SEL_FMT4                           = 0x9,
+	DCO_DBG_BLOCK_SEL_FMT5                           = 0xa,
+	DCO_DBG_BLOCK_SEL_DIGFE_A                        = 0xb,
+	DCO_DBG_BLOCK_SEL_DIGFE_B                        = 0xc,
+	DCO_DBG_BLOCK_SEL_DIGFE_C                        = 0xd,
+	DCO_DBG_BLOCK_SEL_DIGFE_D                        = 0xe,
+	DCO_DBG_BLOCK_SEL_DIGFE_E                        = 0xf,
+	DCO_DBG_BLOCK_SEL_DIGFE_F                        = 0x10,
+	DCO_DBG_BLOCK_SEL_DIGFE_G                        = 0x11,
+	DCO_DBG_BLOCK_SEL_DIGA                           = 0x12,
+	DCO_DBG_BLOCK_SEL_DIGB                           = 0x13,
+	DCO_DBG_BLOCK_SEL_DIGC                           = 0x14,
+	DCO_DBG_BLOCK_SEL_DIGD                           = 0x15,
+	DCO_DBG_BLOCK_SEL_DIGE                           = 0x16,
+	DCO_DBG_BLOCK_SEL_DIGF                           = 0x17,
+	DCO_DBG_BLOCK_SEL_DIGG                           = 0x18,
+	DCO_DBG_BLOCK_SEL_DPFE_A                         = 0x19,
+	DCO_DBG_BLOCK_SEL_DPFE_B                         = 0x1a,
+	DCO_DBG_BLOCK_SEL_DPFE_C                         = 0x1b,
+	DCO_DBG_BLOCK_SEL_DPFE_D                         = 0x1c,
+	DCO_DBG_BLOCK_SEL_DPFE_E                         = 0x1d,
+	DCO_DBG_BLOCK_SEL_DPFE_F                         = 0x1e,
+	DCO_DBG_BLOCK_SEL_DPFE_G                         = 0x1f,
+	DCO_DBG_BLOCK_SEL_DPA                            = 0x20,
+	DCO_DBG_BLOCK_SEL_DPB                            = 0x21,
+	DCO_DBG_BLOCK_SEL_DPC                            = 0x22,
+	DCO_DBG_BLOCK_SEL_DPD                            = 0x23,
+	DCO_DBG_BLOCK_SEL_DPE                            = 0x24,
+	DCO_DBG_BLOCK_SEL_DPF                            = 0x25,
+	DCO_DBG_BLOCK_SEL_DPG                            = 0x26,
+	DCO_DBG_BLOCK_SEL_AUX0                           = 0x27,
+	DCO_DBG_BLOCK_SEL_AUX1                           = 0x28,
+	DCO_DBG_BLOCK_SEL_AUX2                           = 0x29,
+	DCO_DBG_BLOCK_SEL_AUX3                           = 0x2a,
+	DCO_DBG_BLOCK_SEL_AUX4                           = 0x2b,
+	DCO_DBG_BLOCK_SEL_AUX5                           = 0x2c,
+	DCO_DBG_BLOCK_SEL_PERFMON_DCO                    = 0x2d,
+	DCO_DBG_BLOCK_SEL_AUDIO_OUT                      = 0x2e,
+	DCO_DBG_BLOCK_SEL_DIGLPFEA                       = 0x2f,
+	DCO_DBG_BLOCK_SEL_DIGLPFEB                       = 0x30,
+	DCO_DBG_BLOCK_SEL_DIGLPA                         = 0x31,
+	DCO_DBG_BLOCK_SEL_DIGLPB                         = 0x32,
+	DCO_DBG_BLOCK_SEL_DPLPFEA                        = 0x33,
+	DCO_DBG_BLOCK_SEL_DPLPFEB                        = 0x34,
+	DCO_DBG_BLOCK_SEL_DPLPA                          = 0x35,
+	DCO_DBG_BLOCK_SEL_DPLPB                          = 0x36,
+} DCO_DBG_BLOCK_SEL;
+typedef enum DCO_DBG_CLOCK_SEL {
+	DCO_DBG_CLOCK_SEL_DISPCLK                        = 0x0,
+	DCO_DBG_CLOCK_SEL_SCLK                           = 0x1,
+	DCO_DBG_CLOCK_SEL_MVPCLK                         = 0x2,
+	DCO_DBG_CLOCK_SEL_DVOCLK                         = 0x3,
+	DCO_DBG_CLOCK_SEL_DACCLK                         = 0x4,
+	DCO_DBG_CLOCK_SEL_REFCLK                         = 0x5,
+	DCO_DBG_CLOCK_SEL_SYMCLKA                        = 0x6,
+	DCO_DBG_CLOCK_SEL_SYMCLKB                        = 0x7,
+	DCO_DBG_CLOCK_SEL_SYMCLKC                        = 0x8,
+	DCO_DBG_CLOCK_SEL_SYMCLKD                        = 0x9,
+	DCO_DBG_CLOCK_SEL_SYMCLKE                        = 0xa,
+	DCO_DBG_CLOCK_SEL_SYMCLKF                        = 0xb,
+	DCO_DBG_CLOCK_SEL_SYMCLKG                        = 0xc,
+	DCO_DBG_CLOCK_SEL_RESERVED                       = 0xd,
+	DCO_DBG_CLOCK_SEL_AM0CLK                         = 0xe,
+	DCO_DBG_CLOCK_SEL_AM1CLK                         = 0xf,
+	DCO_DBG_CLOCK_SEL_AM2CLK                         = 0x10,
+	DCO_DBG_CLOCK_SEL_SYMCLKLPA                      = 0x11,
+	DCO_DBG_CLOCK_SEL_SYMCLKLPB                      = 0x12,
+} DCO_DBG_CLOCK_SEL;
+typedef enum DCO_HDMI_RXSTATUS_TIMER_CONTROL_DCO_HDMI_RXSTATUS_TIMER_TYPE {
+	DCO_HDMI_RXSTATUS_TIMER_TYPE_LEVEL               = 0x0,
+	DCO_HDMI_RXSTATUS_TIMER_TYPE_PULSE               = 0x1,
+} DCO_HDMI_RXSTATUS_TIMER_CONTROL_DCO_HDMI_RXSTATUS_TIMER_TYPE;
+typedef enum FMT420_MEMORY_SOURCE_SEL {
+	FMT420_MEMORY_SOURCE_SEL_FMT0                    = 0x0,
+	FMT420_MEMORY_SOURCE_SEL_FMT1                    = 0x1,
+	FMT420_MEMORY_SOURCE_SEL_FMT2                    = 0x2,
+	FMT420_MEMORY_SOURCE_SEL_FMT3                    = 0x3,
+	FMT420_MEMORY_SOURCE_SEL_FMT4                    = 0x4,
+	FMT420_MEMORY_SOURCE_SEL_FMT5                    = 0x5,
+	FMT420_MEMORY_SOURCE_SEL_FMT_RESERVED            = 0x6,
+} FMT420_MEMORY_SOURCE_SEL;
+typedef enum DOUT_I2C_CONTROL_GO {
+	DOUT_I2C_CONTROL_STOP_TRANSFER                   = 0x0,
+	DOUT_I2C_CONTROL_START_TRANSFER                  = 0x1,
+} DOUT_I2C_CONTROL_GO;
+typedef enum DOUT_I2C_CONTROL_SOFT_RESET {
+	DOUT_I2C_CONTROL_NOT_RESET_I2C_CONTROLLER        = 0x0,
+	DOUT_I2C_CONTROL_RESET_I2C_CONTROLLER            = 0x1,
+} DOUT_I2C_CONTROL_SOFT_RESET;
+typedef enum DOUT_I2C_CONTROL_SEND_RESET {
+	DOUT_I2C_CONTROL__NOT_SEND_RESET                 = 0x0,
+	DOUT_I2C_CONTROL__SEND_RESET                     = 0x1,
+} DOUT_I2C_CONTROL_SEND_RESET;
+typedef enum DOUT_I2C_CONTROL_SW_STATUS_RESET {
+	DOUT_I2C_CONTROL_NOT_RESET_SW_STATUS             = 0x0,
+	DOUT_I2C_CONTROL_RESET_SW_STATUS                 = 0x1,
+} DOUT_I2C_CONTROL_SW_STATUS_RESET;
+typedef enum DOUT_I2C_CONTROL_DDC_SELECT {
+	DOUT_I2C_CONTROL_SELECT_DDC1                     = 0x0,
+	DOUT_I2C_CONTROL_SELECT_DDC2                     = 0x1,
+	DOUT_I2C_CONTROL_SELECT_DDC3                     = 0x2,
+	DOUT_I2C_CONTROL_SELECT_DDC4                     = 0x3,
+	DOUT_I2C_CONTROL_SELECT_DDC5                     = 0x4,
+	DOUT_I2C_CONTROL_SELECT_DDC6                     = 0x5,
+	DOUT_I2C_CONTROL_SELECT_DDCVGA                   = 0x6,
+} DOUT_I2C_CONTROL_DDC_SELECT;
+typedef enum DOUT_I2C_CONTROL_TRANSACTION_COUNT {
+	DOUT_I2C_CONTROL_TRANS0                          = 0x0,
+	DOUT_I2C_CONTROL_TRANS0_TRANS1                   = 0x1,
+	DOUT_I2C_CONTROL_TRANS0_TRANS1_TRANS2            = 0x2,
+	DOUT_I2C_CONTROL_TRANS0_TRANS1_TRANS2_TRANS3     = 0x3,
+} DOUT_I2C_CONTROL_TRANSACTION_COUNT;
+typedef enum DOUT_I2C_CONTROL_DBG_REF_SEL {
+	DOUT_I2C_CONTROL_NORMAL_DEBUG                    = 0x0,
+	DOUT_I2C_CONTROL_FAST_REFERENCE_DEBUG            = 0x1,
+} DOUT_I2C_CONTROL_DBG_REF_SEL;
+typedef enum DOUT_I2C_ARBITRATION_SW_PRIORITY {
+	DOUT_I2C_ARBITRATION_SW_PRIORITY_NORMAL          = 0x0,
+	DOUT_I2C_ARBITRATION_SW_PRIORITY_HIGH            = 0x1,
+	DOUT_I2C_ARBITRATION_SW_PRIORITY_0_RESERVED      = 0x2,
+	DOUT_I2C_ARBITRATION_SW_PRIORITY_1_RESERVED      = 0x3,
+} DOUT_I2C_ARBITRATION_SW_PRIORITY;
+typedef enum DOUT_I2C_ARBITRATION_NO_QUEUED_SW_GO {
+	DOUT_I2C_ARBITRATION_SW_QUEUE_ENABLED            = 0x0,
+	DOUT_I2C_ARBITRATION_SW_QUEUE_DISABLED           = 0x1,
+} DOUT_I2C_ARBITRATION_NO_QUEUED_SW_GO;
+typedef enum DOUT_I2C_ARBITRATION_ABORT_XFER {
+	DOUT_I2C_ARBITRATION_NOT_ABORT_CURRENT_TRANSFER  = 0x0,
+	DOUT_I2C_ARBITRATION_ABORT_CURRENT_TRANSFER      = 0x1,
+} DOUT_I2C_ARBITRATION_ABORT_XFER;
+typedef enum DOUT_I2C_ARBITRATION_USE_I2C_REG_REQ {
+	DOUT_I2C_ARBITRATION__NOT_USE_I2C_REG_REQ        = 0x0,
+	DOUT_I2C_ARBITRATION__USE_I2C_REG_REQ            = 0x1,
+} DOUT_I2C_ARBITRATION_USE_I2C_REG_REQ;
+typedef enum DOUT_I2C_ARBITRATION_DONE_USING_I2C_REG {
+	DOUT_I2C_ARBITRATION_DONE__NOT_USING_I2C_REG     = 0x0,
+	DOUT_I2C_ARBITRATION_DONE__USING_I2C_REG         = 0x1,
+} DOUT_I2C_ARBITRATION_DONE_USING_I2C_REG;
+typedef enum DOUT_I2C_ACK {
+	DOUT_I2C_NO_ACK                                  = 0x0,
+	DOUT_I2C_ACK_TO_CLEAN                            = 0x1,
+} DOUT_I2C_ACK;
+typedef enum DOUT_I2C_DDC_SPEED_THRESHOLD {
+	DOUT_I2C_DDC_SPEED_THRESHOLD_BIG_THAN_ZERO       = 0x0,
+	DOUT_I2C_DDC_SPEED_THRESHOLD_QUATER_OF_TOTAL_SAMPLE= 0x1,
+	DOUT_I2C_DDC_SPEED_THRESHOLD_HALF_OF_TOTAL_SAMPLE= 0x2,
+	DOUT_I2C_DDC_SPEED_THRESHOLD_THREE_QUATERS_OF_TOTAL_SAMPLE= 0x3,
+} DOUT_I2C_DDC_SPEED_THRESHOLD;
+typedef enum DOUT_I2C_DDC_SETUP_DATA_DRIVE_EN {
+	DOUT_I2C_DDC_SETUP_DATA_DRIVE_BY_EXTERNAL_RESISTOR= 0x0,
+	DOUT_I2C_DDC_SETUP_I2C_PAD_DRIVE_SDA             = 0x1,
+} DOUT_I2C_DDC_SETUP_DATA_DRIVE_EN;
+typedef enum DOUT_I2C_DDC_SETUP_DATA_DRIVE_SEL {
+	DOUT_I2C_DDC_SETUP_DATA_DRIVE_FOR_10MCLKS        = 0x0,
+	DOUT_I2C_DDC_SETUP_DATA_DRIVE_FOR_20MCLKS        = 0x1,
+} DOUT_I2C_DDC_SETUP_DATA_DRIVE_SEL;
+typedef enum DOUT_I2C_DDC_SETUP_EDID_DETECT_MODE {
+	DOUT_I2C_DDC_SETUP_EDID_DETECT_CONNECT           = 0x0,
+	DOUT_I2C_DDC_SETUP_EDID_DETECT_DISCONNECT        = 0x1,
+} DOUT_I2C_DDC_SETUP_EDID_DETECT_MODE;
+typedef enum DOUT_I2C_DDC_SETUP_CLK_DRIVE_EN {
+	DOUT_I2C_DDC_SETUP_CLK_DRIVE_BY_EXTERNAL_RESISTOR= 0x0,
+	DOUT_I2C_DDC_SETUP_I2C_PAD_DRIVE_SCL             = 0x1,
+} DOUT_I2C_DDC_SETUP_CLK_DRIVE_EN;
+typedef enum DOUT_I2C_TRANSACTION_STOP_ON_NACK {
+	DOUT_I2C_TRANSACTION_STOP_CURRENT_TRANS          = 0x0,
+	DOUT_I2C_TRANSACTION_STOP_ALL_TRANS              = 0x1,
+} DOUT_I2C_TRANSACTION_STOP_ON_NACK;
+typedef enum DOUT_I2C_DATA_INDEX_WRITE {
+	DOUT_I2C_DATA__NOT_INDEX_WRITE                   = 0x0,
+	DOUT_I2C_DATA__INDEX_WRITE                       = 0x1,
+} DOUT_I2C_DATA_INDEX_WRITE;
+typedef enum DOUT_I2C_EDID_DETECT_CTRL_SEND_RESET {
+	DOUT_I2C_EDID_NOT_SEND_RESET_BEFORE_EDID_READ_TRACTION= 0x0,
+	DOUT_I2C_EDID_SEND_RESET_BEFORE_EDID_READ_TRACTION= 0x1,
+} DOUT_I2C_EDID_DETECT_CTRL_SEND_RESET;
+typedef enum DOUT_I2C_READ_REQUEST_INTERRUPT_TYPE {
+	DOUT_I2C_READ_REQUEST_INTERRUPT_TYPE__LEVEL      = 0x0,
+	DOUT_I2C_READ_REQUEST_INTERRUPT_TYPE__PULSE      = 0x1,
+} DOUT_I2C_READ_REQUEST_INTERRUPT_TYPE;
+typedef enum BLNDV_CONTROL_BLND_MODE {
+	BLNDV_CONTROL_BLND_MODE_CURRENT_PIPE_ONLY        = 0x0,
+	BLNDV_CONTROL_BLND_MODE_OTHER_PIPE_ONLY          = 0x1,
+	BLNDV_CONTROL_BLND_MODE_ALPHA_BLENDING_MODE      = 0x2,
+	BLNDV_CONTROL_BLND_MODE_OTHER_STEREO_TYPE        = 0x3,
+} BLNDV_CONTROL_BLND_MODE;
+typedef enum BLNDV_CONTROL_BLND_STEREO_TYPE {
+	BLNDV_CONTROL_BLND_STEREO_TYPE_NON_SINGLE_PIPE_STEREO= 0x0,
+	BLNDV_CONTROL_BLND_STEREO_TYPE_SIDE_BY_SIDE_SINGLE_PIPE_STEREO= 0x1,
+	BLNDV_CONTROL_BLND_STEREO_TYPE_TOP_BOTTOM_SINGLE_PIPE_STEREO= 0x2,
+	BLNDV_CONTROL_BLND_STEREO_TYPE_UNUSED            = 0x3,
+} BLNDV_CONTROL_BLND_STEREO_TYPE;
+typedef enum BLNDV_CONTROL_BLND_STEREO_POLARITY {
+	BLNDV_CONTROL_BLND_STEREO_POLARITY_LOW           = 0x0,
+	BLNDV_CONTROL_BLND_STEREO_POLARITY_HIGH          = 0x1,
+} BLNDV_CONTROL_BLND_STEREO_POLARITY;
+typedef enum BLNDV_CONTROL_BLND_FEEDTHROUGH_EN {
+	BLNDV_CONTROL_BLND_FEEDTHROUGH_EN_FALSE          = 0x0,
+	BLNDV_CONTROL_BLND_FEEDTHROUGH_EN_TRUE           = 0x1,
+} BLNDV_CONTROL_BLND_FEEDTHROUGH_EN;
+typedef enum BLNDV_CONTROL_BLND_ALPHA_MODE {
+	BLNDV_CONTROL_BLND_ALPHA_MODE_CURRENT_PIXEL_ALPHA= 0x0,
+	BLNDV_CONTROL_BLND_ALPHA_MODE_PIXEL_ALPHA_COMBINED_GLOBAL_GAIN= 0x1,
+	BLNDV_CONTROL_BLND_ALPHA_MODE_GLOBAL_ALPHA_ONLY  = 0x2,
+	BLNDV_CONTROL_BLND_ALPHA_MODE_UNUSED             = 0x3,
+} BLNDV_CONTROL_BLND_ALPHA_MODE;
+typedef enum BLNDV_CONTROL_BLND_ACTIVE_OVERLAP_ONLY {
+	BLNDV_CONTROL_BLND_ACTIVE_OVERLAP_ONLY_FALSE     = 0x0,
+	BLNDV_CONTROL_BLND_ACTIVE_OVERLAP_ONLY_TRUE      = 0x1,
+} BLNDV_CONTROL_BLND_ACTIVE_OVERLAP_ONLY;
+typedef enum BLNDV_CONTROL_BLND_MULTIPLIED_MODE {
+	BLNDV_CONTROL_BLND_MULTIPLIED_MODE_FALSE         = 0x0,
+	BLNDV_CONTROL_BLND_MULTIPLIED_MODE_TRUE          = 0x1,
+} BLNDV_CONTROL_BLND_MULTIPLIED_MODE;
+typedef enum BLNDV_SM_CONTROL2_SM_MODE {
+	BLNDV_SM_CONTROL2_SM_MODE_SINGLE_PLANE           = 0x0,
+	BLNDV_SM_CONTROL2_SM_MODE_ROW_SUBSAMPLING        = 0x2,
+	BLNDV_SM_CONTROL2_SM_MODE_COLUMN_SUBSAMPLING     = 0x4,
+	BLNDV_SM_CONTROL2_SM_MODE_CHECKERBOARD_SUBSAMPLING= 0x6,
+} BLNDV_SM_CONTROL2_SM_MODE;
+typedef enum BLNDV_SM_CONTROL2_SM_FRAME_ALTERNATE {
+	BLNDV_SM_CONTROL2_SM_FRAME_ALTERNATE_FALSE       = 0x0,
+	BLNDV_SM_CONTROL2_SM_FRAME_ALTERNATE_TRUE        = 0x1,
+} BLNDV_SM_CONTROL2_SM_FRAME_ALTERNATE;
+typedef enum BLNDV_SM_CONTROL2_SM_FIELD_ALTERNATE {
+	BLNDV_SM_CONTROL2_SM_FIELD_ALTERNATE_FALSE       = 0x0,
+	BLNDV_SM_CONTROL2_SM_FIELD_ALTERNATE_TRUE        = 0x1,
+} BLNDV_SM_CONTROL2_SM_FIELD_ALTERNATE;
+typedef enum BLNDV_SM_CONTROL2_SM_FORCE_NEXT_FRAME_POL {
+	BLNDV_SM_CONTROL2_SM_FORCE_NEXT_FRAME_POL_NO_FORCE= 0x0,
+	BLNDV_SM_CONTROL2_SM_FORCE_NEXT_FRAME_POL_RESERVED= 0x1,
+	BLNDV_SM_CONTROL2_SM_FORCE_NEXT_FRAME_POL_FORCE_LOW= 0x2,
+	BLNDV_SM_CONTROL2_SM_FORCE_NEXT_FRAME_POL_FORCE_HIGH= 0x3,
+} BLNDV_SM_CONTROL2_SM_FORCE_NEXT_FRAME_POL;
+typedef enum BLNDV_SM_CONTROL2_SM_FORCE_NEXT_TOP_POL {
+	BLNDV_SM_CONTROL2_SM_FORCE_NEXT_TOP_POL_NO_FORCE = 0x0,
+	BLNDV_SM_CONTROL2_SM_FORCE_NEXT_TOP_POL_RESERVED = 0x1,
+	BLNDV_SM_CONTROL2_SM_FORCE_NEXT_TOP_POL_FORCE_LOW= 0x2,
+	BLNDV_SM_CONTROL2_SM_FORCE_NEXT_TOP_POL_FORCE_HIGH= 0x3,
+} BLNDV_SM_CONTROL2_SM_FORCE_NEXT_TOP_POL;
+typedef enum BLNDV_CONTROL2_PTI_ENABLE {
+	BLNDV_CONTROL2_PTI_ENABLE_FALSE                  = 0x0,
+	BLNDV_CONTROL2_PTI_ENABLE_TRUE                   = 0x1,
+} BLNDV_CONTROL2_PTI_ENABLE;
+typedef enum BLNDV_CONTROL2_BLND_SUPERAA_DEGAMMA_EN {
+	BLNDV_CONTROL2_BLND_SUPERAA_DEGAMMA_EN_FALSE     = 0x0,
+	BLNDV_CONTROL2_BLND_SUPERAA_DEGAMMA_EN_TRUE      = 0x1,
+} BLNDV_CONTROL2_BLND_SUPERAA_DEGAMMA_EN;
+typedef enum BLNDV_CONTROL2_BLND_SUPERAA_REGAMMA_EN {
+	BLNDV_CONTROL2_BLND_SUPERAA_REGAMMA_EN_FALSE     = 0x0,
+	BLNDV_CONTROL2_BLND_SUPERAA_REGAMMA_EN_TRUE      = 0x1,
+} BLNDV_CONTROL2_BLND_SUPERAA_REGAMMA_EN;
+typedef enum BLNDV_UNDERFLOW_INTERRUPT_BLND_UNDERFLOW_INT_ACK {
+	BLNDV_UNDERFLOW_INTERRUPT_BLND_UNDERFLOW_INT_ACK_FALSE= 0x0,
+	BLNDV_UNDERFLOW_INTERRUPT_BLND_UNDERFLOW_INT_ACK_TRUE= 0x1,
+} BLNDV_UNDERFLOW_INTERRUPT_BLND_UNDERFLOW_INT_ACK;
+typedef enum BLNDV_UNDERFLOW_INTERRUPT_BLND_UNDERFLOW_INT_MASK {
+	BLNDV_UNDERFLOW_INTERRUPT_BLND_UNDERFLOW_INT_MASK_FALSE= 0x0,
+	BLNDV_UNDERFLOW_INTERRUPT_BLND_UNDERFLOW_INT_MASK_TRUE= 0x1,
+} BLNDV_UNDERFLOW_INTERRUPT_BLND_UNDERFLOW_INT_MASK;
+typedef enum BLNDV_V_UPDATE_LOCK_BLND_DCP_GRPH_V_UPDATE_LOCK {
+	BLNDV_V_UPDATE_LOCK_BLND_DCP_GRPH_V_UPDATE_LOCK_FALSE= 0x0,
+	BLNDV_V_UPDATE_LOCK_BLND_DCP_GRPH_V_UPDATE_LOCK_TRUE= 0x1,
+} BLNDV_V_UPDATE_LOCK_BLND_DCP_GRPH_V_UPDATE_LOCK;
+typedef enum BLNDV_V_UPDATE_LOCK_BLND_DCP_GRPH_SURF_V_UPDATE_LOCK {
+	BLNDV_V_UPDATE_LOCK_BLND_DCP_GRPH_SURF_V_UPDATE_LOCK_FALSE= 0x0,
+	BLNDV_V_UPDATE_LOCK_BLND_DCP_GRPH_SURF_V_UPDATE_LOCK_TRUE= 0x1,
+} BLNDV_V_UPDATE_LOCK_BLND_DCP_GRPH_SURF_V_UPDATE_LOCK;
+typedef enum BLNDV_V_UPDATE_LOCK_BLND_DCP_CUR_V_UPDATE_LOCK {
+	BLNDV_V_UPDATE_LOCK_BLND_DCP_CUR_V_UPDATE_LOCK_FALSE= 0x0,
+	BLNDV_V_UPDATE_LOCK_BLND_DCP_CUR_V_UPDATE_LOCK_TRUE= 0x1,
+} BLNDV_V_UPDATE_LOCK_BLND_DCP_CUR_V_UPDATE_LOCK;
+typedef enum BLNDV_V_UPDATE_LOCK_BLND_DCP_CUR2_V_UPDATE_LOCK {
+	BLNDV_V_UPDATE_LOCK_BLND_DCP_CUR2_V_UPDATE_LOCK_FALSE= 0x0,
+	BLNDV_V_UPDATE_LOCK_BLND_DCP_CUR2_V_UPDATE_LOCK_TRUE= 0x1,
+} BLNDV_V_UPDATE_LOCK_BLND_DCP_CUR2_V_UPDATE_LOCK;
+typedef enum BLNDV_V_UPDATE_LOCK_BLND_SCL_V_UPDATE_LOCK {
+	BLNDV_V_UPDATE_LOCK_BLND_SCL_V_UPDATE_LOCK_FALSE = 0x0,
+	BLNDV_V_UPDATE_LOCK_BLND_SCL_V_UPDATE_LOCK_TRUE  = 0x1,
+} BLNDV_V_UPDATE_LOCK_BLND_SCL_V_UPDATE_LOCK;
+typedef enum BLNDV_V_UPDATE_LOCK_BLND_BLND_V_UPDATE_LOCK {
+	BLNDV_V_UPDATE_LOCK_BLND_BLND_V_UPDATE_LOCK_FALSE= 0x0,
+	BLNDV_V_UPDATE_LOCK_BLND_BLND_V_UPDATE_LOCK_TRUE = 0x1,
+} BLNDV_V_UPDATE_LOCK_BLND_BLND_V_UPDATE_LOCK;
+typedef enum BLNDV_V_UPDATE_LOCK_BLND_V_UPDATE_LOCK_MODE {
+	BLNDV_V_UPDATE_LOCK_BLND_V_UPDATE_LOCK_MODE_FALSE= 0x0,
+	BLNDV_V_UPDATE_LOCK_BLND_V_UPDATE_LOCK_MODE_TRUE = 0x1,
+} BLNDV_V_UPDATE_LOCK_BLND_V_UPDATE_LOCK_MODE;
+typedef enum BLNDV_DEBUG_BLND_CNV_MUX_SELECT {
+	BLNDV_DEBUG_BLND_CNV_MUX_SELECT_LOW              = 0x0,
+	BLNDV_DEBUG_BLND_CNV_MUX_SELECT_HIGH             = 0x1,
+} BLNDV_DEBUG_BLND_CNV_MUX_SELECT;
+typedef enum BLNDV_TEST_DEBUG_INDEX_BLND_TEST_DEBUG_WRITE_EN {
+	BLNDV_TEST_DEBUG_INDEX_BLND_TEST_DEBUG_WRITE_EN_FALSE= 0x0,
+	BLNDV_TEST_DEBUG_INDEX_BLND_TEST_DEBUG_WRITE_EN_TRUE= 0x1,
+} BLNDV_TEST_DEBUG_INDEX_BLND_TEST_DEBUG_WRITE_EN;
+typedef enum DPCSTX_DBG_CFGCLK_SEL {
+	DPCSTX_DBG_CFGCLK_SEL_DC_DPCS_INF                = 0x0,
+	DPCSTX_DBG_CFGCLK_SEL_DPCS_BPHY_INF              = 0x1,
+	DPCSTX_DBG_CFGCLK_SEL_CBUS_SLAVE                 = 0x2,
+	DPCSTX_DBG_CFGCLK_SEL_CBUS_MASTER                = 0x3,
+} DPCSTX_DBG_CFGCLK_SEL;
+typedef enum DPCSTX_TX_SYMCLK_SEL {
+	DPCSTX_DBG_TX_SYMCLK_SEL_IN0                     = 0x0,
+	DPCSTX_DBG_TX_SYMCLK_SEL_IN1                     = 0x1,
+	DPCSTX_DBG_TX_SYMCLK_SEL_FIFO_WR                 = 0x2,
+} DPCSTX_TX_SYMCLK_SEL;
+typedef enum DPCSTX_TX_SYMCLK_DIV2_SEL {
+	DPCSTX_DBG_TX_SYMCLK_DIV2_SEL_OUT0               = 0x0,
+	DPCSTX_DBG_TX_SYMCLK_DIV2_SEL_OUT1               = 0x1,
+	DPCSTX_DBG_TX_SYMCLK_DIV2_SEL_OUT2               = 0x2,
+	DPCSTX_DBG_TX_SYMCLK_DIV2_SEL_OUT3               = 0x3,
+	DPCSTX_DBG_TX_SYMCLK_DIV2_SEL_FIFO_RD            = 0x4,
+	DPCSTX_DBG_TX_SYMCLK_DIV2_SEL_INT                = 0x5,
+} DPCSTX_TX_SYMCLK_DIV2_SEL;
+typedef enum DPCSTX_DBG_CLOCK_SEL {
+	DPCSTX_DBG_CLOCK_SEL_DC_CFGCLK                   = 0x0,
+	DPCSTX_DBG_CLOCK_SEL_PHY_CFGCLK                  = 0x1,
+	DPCSTX_DBG_CLOCK_SEL_TXSYMCLK                    = 0x2,
+} DPCSTX_DBG_CLOCK_SEL;
+typedef enum DPCSTX_DVI_LINK_MODE {
+	DPCSTX_DVI_LINK_MODE_NORMAL                      = 0x0,
+	DPCSTX_DVI_LINK_MODE_DUAL_LINK_MASTER            = 0x1,
+	DPCSTX_DVI_LINK_MODE_DUAL_LINK_SLAVER            = 0x2,
+} DPCSTX_DVI_LINK_MODE;
+
+#endif /* DCE_11_2_ENUM_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/include/asic_reg/dce/dce_11_2_sh_mask.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/include/asic_reg/dce/dce_11_2_sh_mask.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/include/asic_reg/dce/dce_11_2_sh_mask.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/include/asic_reg/dce/dce_11_2_sh_mask.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,18687 @@
+/*
+ * DCE_11_2 Register documentation
+ *
+ * Copyright (C) 2016  Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef DCE_11_2_SH_MASK_H
+#define DCE_11_2_SH_MASK_H
+
+#define PIPE0_PG_CONFIG__PIPE0_POWER_FORCEON_MASK 0x1
+#define PIPE0_PG_CONFIG__PIPE0_POWER_FORCEON__SHIFT 0x0
+#define PIPE0_PG_ENABLE__PIPE0_POWER_GATE_MASK 0x1
+#define PIPE0_PG_ENABLE__PIPE0_POWER_GATE__SHIFT 0x0
+#define PIPE0_PG_STATUS__PIPE0_PGFSM_READ_DATA_MASK 0xffffff
+#define PIPE0_PG_STATUS__PIPE0_PGFSM_READ_DATA__SHIFT 0x0
+#define PIPE0_PG_STATUS__PIPE0_DEBUG_PWR_STATUS_MASK 0x3000000
+#define PIPE0_PG_STATUS__PIPE0_DEBUG_PWR_STATUS__SHIFT 0x18
+#define PIPE0_PG_STATUS__PIPE0_DESIRED_PWR_STATE_MASK 0x10000000
+#define PIPE0_PG_STATUS__PIPE0_DESIRED_PWR_STATE__SHIFT 0x1c
+#define PIPE0_PG_STATUS__PIPE0_REQUESTED_PWR_STATE_MASK 0x20000000
+#define PIPE0_PG_STATUS__PIPE0_REQUESTED_PWR_STATE__SHIFT 0x1d
+#define PIPE0_PG_STATUS__PIPE0_PGFSM_PWR_STATUS_MASK 0xc0000000
+#define PIPE0_PG_STATUS__PIPE0_PGFSM_PWR_STATUS__SHIFT 0x1e
+#define PIPE1_PG_CONFIG__PIPE1_POWER_FORCEON_MASK 0x1
+#define PIPE1_PG_CONFIG__PIPE1_POWER_FORCEON__SHIFT 0x0
+#define PIPE1_PG_ENABLE__PIPE1_POWER_GATE_MASK 0x1
+#define PIPE1_PG_ENABLE__PIPE1_POWER_GATE__SHIFT 0x0
+#define PIPE1_PG_STATUS__PIPE1_PGFSM_READ_DATA_MASK 0xffffff
+#define PIPE1_PG_STATUS__PIPE1_PGFSM_READ_DATA__SHIFT 0x0
+#define PIPE1_PG_STATUS__PIPE1_DEBUG_PWR_STATUS_MASK 0x3000000
+#define PIPE1_PG_STATUS__PIPE1_DEBUG_PWR_STATUS__SHIFT 0x18
+#define PIPE1_PG_STATUS__PIPE1_DESIRED_PWR_STATE_MASK 0x10000000
+#define PIPE1_PG_STATUS__PIPE1_DESIRED_PWR_STATE__SHIFT 0x1c
+#define PIPE1_PG_STATUS__PIPE1_REQUESTED_PWR_STATE_MASK 0x20000000
+#define PIPE1_PG_STATUS__PIPE1_REQUESTED_PWR_STATE__SHIFT 0x1d
+#define PIPE1_PG_STATUS__PIPE1_PGFSM_PWR_STATUS_MASK 0xc0000000
+#define PIPE1_PG_STATUS__PIPE1_PGFSM_PWR_STATUS__SHIFT 0x1e
+#define PIPE2_PG_CONFIG__PIPE2_POWER_FORCEON_MASK 0x1
+#define PIPE2_PG_CONFIG__PIPE2_POWER_FORCEON__SHIFT 0x0
+#define PIPE2_PG_ENABLE__PIPE2_POWER_GATE_MASK 0x1
+#define PIPE2_PG_ENABLE__PIPE2_POWER_GATE__SHIFT 0x0
+#define PIPE2_PG_STATUS__PIPE2_PGFSM_READ_DATA_MASK 0xffffff
+#define PIPE2_PG_STATUS__PIPE2_PGFSM_READ_DATA__SHIFT 0x0
+#define PIPE2_PG_STATUS__PIPE2_DEBUG_PWR_STATUS_MASK 0x3000000
+#define PIPE2_PG_STATUS__PIPE2_DEBUG_PWR_STATUS__SHIFT 0x18
+#define PIPE2_PG_STATUS__PIPE2_DESIRED_PWR_STATE_MASK 0x10000000
+#define PIPE2_PG_STATUS__PIPE2_DESIRED_PWR_STATE__SHIFT 0x1c
+#define PIPE2_PG_STATUS__PIPE2_REQUESTED_PWR_STATE_MASK 0x20000000
+#define PIPE2_PG_STATUS__PIPE2_REQUESTED_PWR_STATE__SHIFT 0x1d
+#define PIPE2_PG_STATUS__PIPE2_PGFSM_PWR_STATUS_MASK 0xc0000000
+#define PIPE2_PG_STATUS__PIPE2_PGFSM_PWR_STATUS__SHIFT 0x1e
+#define PIPE3_PG_CONFIG__PIPE3_POWER_FORCEON_MASK 0x1
+#define PIPE3_PG_CONFIG__PIPE3_POWER_FORCEON__SHIFT 0x0
+#define PIPE3_PG_ENABLE__PIPE3_POWER_GATE_MASK 0x1
+#define PIPE3_PG_ENABLE__PIPE3_POWER_GATE__SHIFT 0x0
+#define PIPE3_PG_STATUS__PIPE3_PGFSM_READ_DATA_MASK 0xffffff
+#define PIPE3_PG_STATUS__PIPE3_PGFSM_READ_DATA__SHIFT 0x0
+#define PIPE3_PG_STATUS__PIPE3_DEBUG_PWR_STATUS_MASK 0x3000000
+#define PIPE3_PG_STATUS__PIPE3_DEBUG_PWR_STATUS__SHIFT 0x18
+#define PIPE3_PG_STATUS__PIPE3_DESIRED_PWR_STATE_MASK 0x10000000
+#define PIPE3_PG_STATUS__PIPE3_DESIRED_PWR_STATE__SHIFT 0x1c
+#define PIPE3_PG_STATUS__PIPE3_REQUESTED_PWR_STATE_MASK 0x20000000
+#define PIPE3_PG_STATUS__PIPE3_REQUESTED_PWR_STATE__SHIFT 0x1d
+#define PIPE3_PG_STATUS__PIPE3_PGFSM_PWR_STATUS_MASK 0xc0000000
+#define PIPE3_PG_STATUS__PIPE3_PGFSM_PWR_STATUS__SHIFT 0x1e
+#define PIPE4_PG_CONFIG__PIPE4_POWER_FORCEON_MASK 0x1
+#define PIPE4_PG_CONFIG__PIPE4_POWER_FORCEON__SHIFT 0x0
+#define PIPE4_PG_ENABLE__PIPE4_POWER_GATE_MASK 0x1
+#define PIPE4_PG_ENABLE__PIPE4_POWER_GATE__SHIFT 0x0
+#define PIPE4_PG_STATUS__PIPE4_PGFSM_READ_DATA_MASK 0xffffff
+#define PIPE4_PG_STATUS__PIPE4_PGFSM_READ_DATA__SHIFT 0x0
+#define PIPE4_PG_STATUS__PIPE4_DEBUG_PWR_STATUS_MASK 0x3000000
+#define PIPE4_PG_STATUS__PIPE4_DEBUG_PWR_STATUS__SHIFT 0x18
+#define PIPE4_PG_STATUS__PIPE4_DESIRED_PWR_STATE_MASK 0x10000000
+#define PIPE4_PG_STATUS__PIPE4_DESIRED_PWR_STATE__SHIFT 0x1c
+#define PIPE4_PG_STATUS__PIPE4_REQUESTED_PWR_STATE_MASK 0x20000000
+#define PIPE4_PG_STATUS__PIPE4_REQUESTED_PWR_STATE__SHIFT 0x1d
+#define PIPE4_PG_STATUS__PIPE4_PGFSM_PWR_STATUS_MASK 0xc0000000
+#define PIPE4_PG_STATUS__PIPE4_PGFSM_PWR_STATUS__SHIFT 0x1e
+#define PIPE5_PG_CONFIG__PIPE5_POWER_FORCEON_MASK 0x1
+#define PIPE5_PG_CONFIG__PIPE5_POWER_FORCEON__SHIFT 0x0
+#define PIPE5_PG_ENABLE__PIPE5_POWER_GATE_MASK 0x1
+#define PIPE5_PG_ENABLE__PIPE5_POWER_GATE__SHIFT 0x0
+#define PIPE5_PG_STATUS__PIPE5_PGFSM_READ_DATA_MASK 0xffffff
+#define PIPE5_PG_STATUS__PIPE5_PGFSM_READ_DATA__SHIFT 0x0
+#define PIPE5_PG_STATUS__PIPE5_DEBUG_PWR_STATUS_MASK 0x3000000
+#define PIPE5_PG_STATUS__PIPE5_DEBUG_PWR_STATUS__SHIFT 0x18
+#define PIPE5_PG_STATUS__PIPE5_DESIRED_PWR_STATE_MASK 0x10000000
+#define PIPE5_PG_STATUS__PIPE5_DESIRED_PWR_STATE__SHIFT 0x1c
+#define PIPE5_PG_STATUS__PIPE5_REQUESTED_PWR_STATE_MASK 0x20000000
+#define PIPE5_PG_STATUS__PIPE5_REQUESTED_PWR_STATE__SHIFT 0x1d
+#define PIPE5_PG_STATUS__PIPE5_PGFSM_PWR_STATUS_MASK 0xc0000000
+#define PIPE5_PG_STATUS__PIPE5_PGFSM_PWR_STATUS__SHIFT 0x1e
+#define DCPG_INTERRUPT_STATUS__DCFE0_POWER_UP_INT_OCCURRED_MASK 0x1
+#define DCPG_INTERRUPT_STATUS__DCFE0_POWER_UP_INT_OCCURRED__SHIFT 0x0
+#define DCPG_INTERRUPT_STATUS__DCFE0_POWER_DOWN_INT_OCCURRED_MASK 0x2
+#define DCPG_INTERRUPT_STATUS__DCFE0_POWER_DOWN_INT_OCCURRED__SHIFT 0x1
+#define DCPG_INTERRUPT_STATUS__DCFE1_POWER_UP_INT_OCCURRED_MASK 0x4
+#define DCPG_INTERRUPT_STATUS__DCFE1_POWER_UP_INT_OCCURRED__SHIFT 0x2
+#define DCPG_INTERRUPT_STATUS__DCFE1_POWER_DOWN_INT_OCCURRED_MASK 0x8
+#define DCPG_INTERRUPT_STATUS__DCFE1_POWER_DOWN_INT_OCCURRED__SHIFT 0x3
+#define DCPG_INTERRUPT_STATUS__DCFE2_POWER_UP_INT_OCCURRED_MASK 0x10
+#define DCPG_INTERRUPT_STATUS__DCFE2_POWER_UP_INT_OCCURRED__SHIFT 0x4
+#define DCPG_INTERRUPT_STATUS__DCFE2_POWER_DOWN_INT_OCCURRED_MASK 0x20
+#define DCPG_INTERRUPT_STATUS__DCFE2_POWER_DOWN_INT_OCCURRED__SHIFT 0x5
+#define DCPG_INTERRUPT_STATUS__DCFE3_POWER_UP_INT_OCCURRED_MASK 0x40
+#define DCPG_INTERRUPT_STATUS__DCFE3_POWER_UP_INT_OCCURRED__SHIFT 0x6
+#define DCPG_INTERRUPT_STATUS__DCFE3_POWER_DOWN_INT_OCCURRED_MASK 0x80
+#define DCPG_INTERRUPT_STATUS__DCFE3_POWER_DOWN_INT_OCCURRED__SHIFT 0x7
+#define DCPG_INTERRUPT_STATUS__DCFE4_POWER_UP_INT_OCCURRED_MASK 0x100
+#define DCPG_INTERRUPT_STATUS__DCFE4_POWER_UP_INT_OCCURRED__SHIFT 0x8
+#define DCPG_INTERRUPT_STATUS__DCFE4_POWER_DOWN_INT_OCCURRED_MASK 0x200
+#define DCPG_INTERRUPT_STATUS__DCFE4_POWER_DOWN_INT_OCCURRED__SHIFT 0x9
+#define DCPG_INTERRUPT_STATUS__DCFE5_POWER_UP_INT_OCCURRED_MASK 0x400
+#define DCPG_INTERRUPT_STATUS__DCFE5_POWER_UP_INT_OCCURRED__SHIFT 0xa
+#define DCPG_INTERRUPT_STATUS__DCFE5_POWER_DOWN_INT_OCCURRED_MASK 0x800
+#define DCPG_INTERRUPT_STATUS__DCFE5_POWER_DOWN_INT_OCCURRED__SHIFT 0xb
+#define DCPG_INTERRUPT_STATUS__DCFEV0_POWER_UP_INT_OCCURRED_MASK 0x1000
+#define DCPG_INTERRUPT_STATUS__DCFEV0_POWER_UP_INT_OCCURRED__SHIFT 0xc
+#define DCPG_INTERRUPT_STATUS__DCFEV0_POWER_DOWN_INT_OCCURRED_MASK 0x2000
+#define DCPG_INTERRUPT_STATUS__DCFEV0_POWER_DOWN_INT_OCCURRED__SHIFT 0xd
+#define DCPG_INTERRUPT_STATUS__DSI_POWER_UP_INT_OCCURRED_MASK 0x4000
+#define DCPG_INTERRUPT_STATUS__DSI_POWER_UP_INT_OCCURRED__SHIFT 0xe
+#define DCPG_INTERRUPT_STATUS__DSI_POWER_DOWN_INT_OCCURRED_MASK 0x8000
+#define DCPG_INTERRUPT_STATUS__DSI_POWER_DOWN_INT_OCCURRED__SHIFT 0xf
+#define DCPG_INTERRUPT_STATUS__DCFEV1_POWER_UP_INT_OCCURRED_MASK 0x10000
+#define DCPG_INTERRUPT_STATUS__DCFEV1_POWER_UP_INT_OCCURRED__SHIFT 0x10
+#define DCPG_INTERRUPT_STATUS__DCFEV1_POWER_DOWN_INT_OCCURRED_MASK 0x20000
+#define DCPG_INTERRUPT_STATUS__DCFEV1_POWER_DOWN_INT_OCCURRED__SHIFT 0x11
+#define DCPG_INTERRUPT_CONTROL__DCFE0_POWER_UP_INT_MASK_MASK 0x1
+#define DCPG_INTERRUPT_CONTROL__DCFE0_POWER_UP_INT_MASK__SHIFT 0x0
+#define DCPG_INTERRUPT_CONTROL__DCFE0_POWER_UP_INT_CLEAR_MASK 0x2
+#define DCPG_INTERRUPT_CONTROL__DCFE0_POWER_UP_INT_CLEAR__SHIFT 0x1
+#define DCPG_INTERRUPT_CONTROL__DCFE0_POWER_DOWN_INT_MASK_MASK 0x4
+#define DCPG_INTERRUPT_CONTROL__DCFE0_POWER_DOWN_INT_MASK__SHIFT 0x2
+#define DCPG_INTERRUPT_CONTROL__DCFE0_POWER_DOWN_INT_CLEAR_MASK 0x8
+#define DCPG_INTERRUPT_CONTROL__DCFE0_POWER_DOWN_INT_CLEAR__SHIFT 0x3
+#define DCPG_INTERRUPT_CONTROL__DCFE1_POWER_UP_INT_MASK_MASK 0x10
+#define DCPG_INTERRUPT_CONTROL__DCFE1_POWER_UP_INT_MASK__SHIFT 0x4
+#define DCPG_INTERRUPT_CONTROL__DCFE1_POWER_UP_INT_CLEAR_MASK 0x20
+#define DCPG_INTERRUPT_CONTROL__DCFE1_POWER_UP_INT_CLEAR__SHIFT 0x5
+#define DCPG_INTERRUPT_CONTROL__DCFE1_POWER_DOWN_INT_MASK_MASK 0x40
+#define DCPG_INTERRUPT_CONTROL__DCFE1_POWER_DOWN_INT_MASK__SHIFT 0x6
+#define DCPG_INTERRUPT_CONTROL__DCFE1_POWER_DOWN_INT_CLEAR_MASK 0x80
+#define DCPG_INTERRUPT_CONTROL__DCFE1_POWER_DOWN_INT_CLEAR__SHIFT 0x7
+#define DCPG_INTERRUPT_CONTROL__DCFE2_POWER_UP_INT_MASK_MASK 0x100
+#define DCPG_INTERRUPT_CONTROL__DCFE2_POWER_UP_INT_MASK__SHIFT 0x8
+#define DCPG_INTERRUPT_CONTROL__DCFE2_POWER_UP_INT_CLEAR_MASK 0x200
+#define DCPG_INTERRUPT_CONTROL__DCFE2_POWER_UP_INT_CLEAR__SHIFT 0x9
+#define DCPG_INTERRUPT_CONTROL__DCFE2_POWER_DOWN_INT_MASK_MASK 0x400
+#define DCPG_INTERRUPT_CONTROL__DCFE2_POWER_DOWN_INT_MASK__SHIFT 0xa
+#define DCPG_INTERRUPT_CONTROL__DCFE2_POWER_DOWN_INT_CLEAR_MASK 0x800
+#define DCPG_INTERRUPT_CONTROL__DCFE2_POWER_DOWN_INT_CLEAR__SHIFT 0xb
+#define DCPG_INTERRUPT_CONTROL__DCFE3_POWER_UP_INT_MASK_MASK 0x1000
+#define DCPG_INTERRUPT_CONTROL__DCFE3_POWER_UP_INT_MASK__SHIFT 0xc
+#define DCPG_INTERRUPT_CONTROL__DCFE3_POWER_UP_INT_CLEAR_MASK 0x2000
+#define DCPG_INTERRUPT_CONTROL__DCFE3_POWER_UP_INT_CLEAR__SHIFT 0xd
+#define DCPG_INTERRUPT_CONTROL__DCFE3_POWER_DOWN_INT_MASK_MASK 0x4000
+#define DCPG_INTERRUPT_CONTROL__DCFE3_POWER_DOWN_INT_MASK__SHIFT 0xe
+#define DCPG_INTERRUPT_CONTROL__DCFE3_POWER_DOWN_INT_CLEAR_MASK 0x8000
+#define DCPG_INTERRUPT_CONTROL__DCFE3_POWER_DOWN_INT_CLEAR__SHIFT 0xf
+#define DCPG_INTERRUPT_CONTROL__DCFE4_POWER_UP_INT_MASK_MASK 0x10000
+#define DCPG_INTERRUPT_CONTROL__DCFE4_POWER_UP_INT_MASK__SHIFT 0x10
+#define DCPG_INTERRUPT_CONTROL__DCFE4_POWER_UP_INT_CLEAR_MASK 0x20000
+#define DCPG_INTERRUPT_CONTROL__DCFE4_POWER_UP_INT_CLEAR__SHIFT 0x11
+#define DCPG_INTERRUPT_CONTROL__DCFE4_POWER_DOWN_INT_MASK_MASK 0x40000
+#define DCPG_INTERRUPT_CONTROL__DCFE4_POWER_DOWN_INT_MASK__SHIFT 0x12
+#define DCPG_INTERRUPT_CONTROL__DCFE4_POWER_DOWN_INT_CLEAR_MASK 0x80000
+#define DCPG_INTERRUPT_CONTROL__DCFE4_POWER_DOWN_INT_CLEAR__SHIFT 0x13
+#define DCPG_INTERRUPT_CONTROL__DCFE5_POWER_UP_INT_MASK_MASK 0x100000
+#define DCPG_INTERRUPT_CONTROL__DCFE5_POWER_UP_INT_MASK__SHIFT 0x14
+#define DCPG_INTERRUPT_CONTROL__DCFE5_POWER_UP_INT_CLEAR_MASK 0x200000
+#define DCPG_INTERRUPT_CONTROL__DCFE5_POWER_UP_INT_CLEAR__SHIFT 0x15
+#define DCPG_INTERRUPT_CONTROL__DCFE5_POWER_DOWN_INT_MASK_MASK 0x400000
+#define DCPG_INTERRUPT_CONTROL__DCFE5_POWER_DOWN_INT_MASK__SHIFT 0x16
+#define DCPG_INTERRUPT_CONTROL__DCFE5_POWER_DOWN_INT_CLEAR_MASK 0x800000
+#define DCPG_INTERRUPT_CONTROL__DCFE5_POWER_DOWN_INT_CLEAR__SHIFT 0x17
+#define DCPG_INTERRUPT_CONTROL__DCFEV0_POWER_UP_INT_MASK_MASK 0x1000000
+#define DCPG_INTERRUPT_CONTROL__DCFEV0_POWER_UP_INT_MASK__SHIFT 0x18
+#define DCPG_INTERRUPT_CONTROL__DCFEV0_POWER_UP_INT_CLEAR_MASK 0x2000000
+#define DCPG_INTERRUPT_CONTROL__DCFEV0_POWER_UP_INT_CLEAR__SHIFT 0x19
+#define DCPG_INTERRUPT_CONTROL__DCFEV0_POWER_DOWN_INT_MASK_MASK 0x4000000
+#define DCPG_INTERRUPT_CONTROL__DCFEV0_POWER_DOWN_INT_MASK__SHIFT 0x1a
+#define DCPG_INTERRUPT_CONTROL__DCFEV0_POWER_DOWN_INT_CLEAR_MASK 0x8000000
+#define DCPG_INTERRUPT_CONTROL__DCFEV0_POWER_DOWN_INT_CLEAR__SHIFT 0x1b
+#define DCPG_INTERRUPT_CONTROL__DSI_POWER_UP_INT_MASK_MASK 0x10000000
+#define DCPG_INTERRUPT_CONTROL__DSI_POWER_UP_INT_MASK__SHIFT 0x1c
+#define DCPG_INTERRUPT_CONTROL__DSI_POWER_UP_INT_CLEAR_MASK 0x20000000
+#define DCPG_INTERRUPT_CONTROL__DSI_POWER_UP_INT_CLEAR__SHIFT 0x1d
+#define DCPG_INTERRUPT_CONTROL__DSI_POWER_DOWN_INT_MASK_MASK 0x40000000
+#define DCPG_INTERRUPT_CONTROL__DSI_POWER_DOWN_INT_MASK__SHIFT 0x1e
+#define DCPG_INTERRUPT_CONTROL__DSI_POWER_DOWN_INT_CLEAR_MASK 0x80000000
+#define DCPG_INTERRUPT_CONTROL__DSI_POWER_DOWN_INT_CLEAR__SHIFT 0x1f
+#define DCPG_INTERRUPT_CONTROL2__DCFEV1_POWER_UP_INT_MASK_MASK 0x1000000
+#define DCPG_INTERRUPT_CONTROL2__DCFEV1_POWER_UP_INT_MASK__SHIFT 0x18
+#define DCPG_INTERRUPT_CONTROL2__DCFEV1_POWER_UP_INT_CLEAR_MASK 0x2000000
+#define DCPG_INTERRUPT_CONTROL2__DCFEV1_POWER_UP_INT_CLEAR__SHIFT 0x19
+#define DCPG_INTERRUPT_CONTROL2__DCFEV1_POWER_DOWN_INT_MASK_MASK 0x4000000
+#define DCPG_INTERRUPT_CONTROL2__DCFEV1_POWER_DOWN_INT_MASK__SHIFT 0x1a
+#define DCPG_INTERRUPT_CONTROL2__DCFEV1_POWER_DOWN_INT_CLEAR_MASK 0x8000000
+#define DCPG_INTERRUPT_CONTROL2__DCFEV1_POWER_DOWN_INT_CLEAR__SHIFT 0x1b
+#define DC_IP_REQUEST_CNTL__IP_REQUEST_EN_MASK 0x1
+#define DC_IP_REQUEST_CNTL__IP_REQUEST_EN__SHIFT 0x0
+#define DC_PGFSM_CONFIG_REG__PGFSM_CONFIG_REG_MASK 0xffffffff
+#define DC_PGFSM_CONFIG_REG__PGFSM_CONFIG_REG__SHIFT 0x0
+#define DC_PGFSM_WRITE_REG__PGFSM_WRITE_REG_MASK 0xffffffff
+#define DC_PGFSM_WRITE_REG__PGFSM_WRITE_REG__SHIFT 0x0
+#define DC_PGCNTL_STATUS_REG__SWREQ_RWOP_BUSY_MASK 0x1
+#define DC_PGCNTL_STATUS_REG__SWREQ_RWOP_BUSY__SHIFT 0x0
+#define DC_PGCNTL_STATUS_REG__SWREQ_RWOP_FORCE_MASK 0x2
+#define DC_PGCNTL_STATUS_REG__SWREQ_RWOP_FORCE__SHIFT 0x1
+#define DC_PGCNTL_STATUS_REG__IPREQ_IGNORE_STATUS_MASK 0x4
+#define DC_PGCNTL_STATUS_REG__IPREQ_IGNORE_STATUS__SHIFT 0x2
+#define DC_PGCNTL_STATUS_REG__DCPG_ECO_DEBUG_MASK 0xffff0000
+#define DC_PGCNTL_STATUS_REG__DCPG_ECO_DEBUG__SHIFT 0x10
+#define DCPG_TEST_DEBUG_INDEX__DCPG_TEST_DEBUG_INDEX_MASK 0xff
+#define DCPG_TEST_DEBUG_INDEX__DCPG_TEST_DEBUG_INDEX__SHIFT 0x0
+#define DCPG_TEST_DEBUG_INDEX__DCPG_TEST_DEBUG_WRITE_EN_MASK 0x100
+#define DCPG_TEST_DEBUG_INDEX__DCPG_TEST_DEBUG_WRITE_EN__SHIFT 0x8
+#define DCPG_TEST_DEBUG_DATA__DCPG_TEST_DEBUG_DATA_MASK 0xffffffff
+#define DCPG_TEST_DEBUG_DATA__DCPG_TEST_DEBUG_DATA__SHIFT 0x0
+#define BL1_PWM_AMBIENT_LIGHT_LEVEL__BL1_PWM_AMBIENT_LIGHT_LEVEL_MASK 0x1ffff
+#define BL1_PWM_AMBIENT_LIGHT_LEVEL__BL1_PWM_AMBIENT_LIGHT_LEVEL__SHIFT 0x0
+#define BL1_PWM_USER_LEVEL__BL1_PWM_USER_LEVEL_MASK 0x1ffff
+#define BL1_PWM_USER_LEVEL__BL1_PWM_USER_LEVEL__SHIFT 0x0
+#define BL1_PWM_TARGET_ABM_LEVEL__BL1_PWM_TARGET_ABM_LEVEL_MASK 0x1ffff
+#define BL1_PWM_TARGET_ABM_LEVEL__BL1_PWM_TARGET_ABM_LEVEL__SHIFT 0x0
+#define BL1_PWM_CURRENT_ABM_LEVEL__BL1_PWM_CURRENT_ABM_LEVEL_MASK 0x1ffff
+#define BL1_PWM_CURRENT_ABM_LEVEL__BL1_PWM_CURRENT_ABM_LEVEL__SHIFT 0x0
+#define BL1_PWM_FINAL_DUTY_CYCLE__BL1_PWM_FINAL_DUTY_CYCLE_MASK 0x1ffff
+#define BL1_PWM_FINAL_DUTY_CYCLE__BL1_PWM_FINAL_DUTY_CYCLE__SHIFT 0x0
+#define BL1_PWM_MINIMUM_DUTY_CYCLE__BL1_PWM_MINIMUM_DUTY_CYCLE_MASK 0x1ffff
+#define BL1_PWM_MINIMUM_DUTY_CYCLE__BL1_PWM_MINIMUM_DUTY_CYCLE__SHIFT 0x0
+#define BL1_PWM_ABM_CNTL__BL1_PWM_USE_ABM_EN_MASK 0x1
+#define BL1_PWM_ABM_CNTL__BL1_PWM_USE_ABM_EN__SHIFT 0x0
+#define BL1_PWM_ABM_CNTL__BL1_PWM_USE_AMBIENT_LEVEL_EN_MASK 0x2
+#define BL1_PWM_ABM_CNTL__BL1_PWM_USE_AMBIENT_LEVEL_EN__SHIFT 0x1
+#define BL1_PWM_ABM_CNTL__BL1_PWM_AUTO_UPDATE_CURRENT_ABM_LEVEL_EN_MASK 0x4
+#define BL1_PWM_ABM_CNTL__BL1_PWM_AUTO_UPDATE_CURRENT_ABM_LEVEL_EN__SHIFT 0x2
+#define BL1_PWM_ABM_CNTL__BL1_PWM_AUTO_CALC_FINAL_DUTY_CYCLE_EN_MASK 0x8
+#define BL1_PWM_ABM_CNTL__BL1_PWM_AUTO_CALC_FINAL_DUTY_CYCLE_EN__SHIFT 0x3
+#define BL1_PWM_ABM_CNTL__BL1_PWM_AUTO_UPDATE_CURRENT_ABM_STEP_SIZE_MASK 0xffff0000
+#define BL1_PWM_ABM_CNTL__BL1_PWM_AUTO_UPDATE_CURRENT_ABM_STEP_SIZE__SHIFT 0x10
+#define BL1_PWM_BL_UPDATE_SAMPLE_RATE__BL1_PWM_BL_UPDATE_SAMPLE_RATE_COUNT_EN_MASK 0x1
+#define BL1_PWM_BL_UPDATE_SAMPLE_RATE__BL1_PWM_BL_UPDATE_SAMPLE_RATE_COUNT_EN__SHIFT 0x0
+#define BL1_PWM_BL_UPDATE_SAMPLE_RATE__BL1_PWM_BL_UPDATE_RESET_SAMPLE_RATE_FRAME_COUNTER_MASK 0x2
+#define BL1_PWM_BL_UPDATE_SAMPLE_RATE__BL1_PWM_BL_UPDATE_RESET_SAMPLE_RATE_FRAME_COUNTER__SHIFT 0x1
+#define BL1_PWM_BL_UPDATE_SAMPLE_RATE__BL1_PWM_BL_UPDATE_SAMPLE_RATE_FRAME_COUNT_MASK 0xff00
+#define BL1_PWM_BL_UPDATE_SAMPLE_RATE__BL1_PWM_BL_UPDATE_SAMPLE_RATE_FRAME_COUNT__SHIFT 0x8
+#define BL1_PWM_BL_UPDATE_SAMPLE_RATE__BL1_PWM_BL_UPDATE_INITIAL_SAMPLE_RATE_COUNT_VALUE_WHEN_RESET_MASK 0xff0000
+#define BL1_PWM_BL_UPDATE_SAMPLE_RATE__BL1_PWM_BL_UPDATE_INITIAL_SAMPLE_RATE_COUNT_VALUE_WHEN_RESET__SHIFT 0x10
+#define BL1_PWM_BL_UPDATE_SAMPLE_RATE__ABM1_HGLS_REG_LOCK_MASK 0x80000000
+#define BL1_PWM_BL_UPDATE_SAMPLE_RATE__ABM1_HGLS_REG_LOCK__SHIFT 0x1f
+#define BL1_PWM_GRP2_REG_LOCK__BL1_PWM_GRP2_REG_LOCK_MASK 0x1
+#define BL1_PWM_GRP2_REG_LOCK__BL1_PWM_GRP2_REG_LOCK__SHIFT 0x0
+#define BL1_PWM_GRP2_REG_LOCK__BL1_PWM_GRP2_REG_UPDATE_PENDING_MASK 0x100
+#define BL1_PWM_GRP2_REG_LOCK__BL1_PWM_GRP2_REG_UPDATE_PENDING__SHIFT 0x8
+#define BL1_PWM_GRP2_REG_LOCK__BL1_PWM_GRP2_UPDATE_AT_FRAME_START_MASK 0x10000
+#define BL1_PWM_GRP2_REG_LOCK__BL1_PWM_GRP2_UPDATE_AT_FRAME_START__SHIFT 0x10
+#define BL1_PWM_GRP2_REG_LOCK__BL1_PWM_GRP2_FRAME_START_DISP_SEL_MASK 0xe0000
+#define BL1_PWM_GRP2_REG_LOCK__BL1_PWM_GRP2_FRAME_START_DISP_SEL__SHIFT 0x11
+#define BL1_PWM_GRP2_REG_LOCK__BL1_PWM_GRP2_READBACK_DB_REG_VALUE_EN_MASK 0x1000000
+#define BL1_PWM_GRP2_REG_LOCK__BL1_PWM_GRP2_READBACK_DB_REG_VALUE_EN__SHIFT 0x18
+#define BL1_PWM_GRP2_REG_LOCK__BL1_PWM_GRP2_IGNORE_MASTER_LOCK_EN_MASK 0x80000000
+#define BL1_PWM_GRP2_REG_LOCK__BL1_PWM_GRP2_IGNORE_MASTER_LOCK_EN__SHIFT 0x1f
+#define DC_ABM1_CNTL__ABM1_EN_MASK 0x1
+#define DC_ABM1_CNTL__ABM1_EN__SHIFT 0x0
+#define DC_ABM1_CNTL__ABM1_SOURCE_SELECT_MASK 0x700
+#define DC_ABM1_CNTL__ABM1_SOURCE_SELECT__SHIFT 0x8
+#define DC_ABM1_CNTL__ABM1_BLANK_MODE_SUPPORT_ENABLE_MASK 0x80000000
+#define DC_ABM1_CNTL__ABM1_BLANK_MODE_SUPPORT_ENABLE__SHIFT 0x1f
+#define DC_ABM1_IPCSC_COEFF_SEL__ABM1_IPCSC_COEFF_SEL_B_MASK 0xf
+#define DC_ABM1_IPCSC_COEFF_SEL__ABM1_IPCSC_COEFF_SEL_B__SHIFT 0x0
+#define DC_ABM1_IPCSC_COEFF_SEL__ABM1_IPCSC_COEFF_SEL_G_MASK 0xf00
+#define DC_ABM1_IPCSC_COEFF_SEL__ABM1_IPCSC_COEFF_SEL_G__SHIFT 0x8
+#define DC_ABM1_IPCSC_COEFF_SEL__ABM1_IPCSC_COEFF_SEL_R_MASK 0xf0000
+#define DC_ABM1_IPCSC_COEFF_SEL__ABM1_IPCSC_COEFF_SEL_R__SHIFT 0x10
+#define DC_ABM1_IPCSC_COEFF_SEL__ABM1_HGLS_REG_LOCK_MASK 0x80000000
+#define DC_ABM1_IPCSC_COEFF_SEL__ABM1_HGLS_REG_LOCK__SHIFT 0x1f
+#define DC_ABM1_ACE_OFFSET_SLOPE_0__ABM1_ACE_SLOPE_0_MASK 0x7fff
+#define DC_ABM1_ACE_OFFSET_SLOPE_0__ABM1_ACE_SLOPE_0__SHIFT 0x0
+#define DC_ABM1_ACE_OFFSET_SLOPE_0__ABM1_ACE_OFFSET_0_MASK 0x7ff0000
+#define DC_ABM1_ACE_OFFSET_SLOPE_0__ABM1_ACE_OFFSET_0__SHIFT 0x10
+#define DC_ABM1_ACE_OFFSET_SLOPE_0__ABM1_ACE_LOCK_MASK 0x80000000
+#define DC_ABM1_ACE_OFFSET_SLOPE_0__ABM1_ACE_LOCK__SHIFT 0x1f
+#define DC_ABM1_ACE_OFFSET_SLOPE_1__ABM1_ACE_SLOPE_1_MASK 0x7fff
+#define DC_ABM1_ACE_OFFSET_SLOPE_1__ABM1_ACE_SLOPE_1__SHIFT 0x0
+#define DC_ABM1_ACE_OFFSET_SLOPE_1__ABM1_ACE_OFFSET_1_MASK 0x7ff0000
+#define DC_ABM1_ACE_OFFSET_SLOPE_1__ABM1_ACE_OFFSET_1__SHIFT 0x10
+#define DC_ABM1_ACE_OFFSET_SLOPE_1__ABM1_ACE_LOCK_MASK 0x80000000
+#define DC_ABM1_ACE_OFFSET_SLOPE_1__ABM1_ACE_LOCK__SHIFT 0x1f
+#define DC_ABM1_ACE_OFFSET_SLOPE_2__ABM1_ACE_SLOPE_2_MASK 0x7fff
+#define DC_ABM1_ACE_OFFSET_SLOPE_2__ABM1_ACE_SLOPE_2__SHIFT 0x0
+#define DC_ABM1_ACE_OFFSET_SLOPE_2__ABM1_ACE_OFFSET_2_MASK 0x7ff0000
+#define DC_ABM1_ACE_OFFSET_SLOPE_2__ABM1_ACE_OFFSET_2__SHIFT 0x10
+#define DC_ABM1_ACE_OFFSET_SLOPE_2__ABM1_ACE_LOCK_MASK 0x80000000
+#define DC_ABM1_ACE_OFFSET_SLOPE_2__ABM1_ACE_LOCK__SHIFT 0x1f
+#define DC_ABM1_ACE_OFFSET_SLOPE_3__ABM1_ACE_SLOPE_3_MASK 0x7fff
+#define DC_ABM1_ACE_OFFSET_SLOPE_3__ABM1_ACE_SLOPE_3__SHIFT 0x0
+#define DC_ABM1_ACE_OFFSET_SLOPE_3__ABM1_ACE_OFFSET_3_MASK 0x7ff0000
+#define DC_ABM1_ACE_OFFSET_SLOPE_3__ABM1_ACE_OFFSET_3__SHIFT 0x10
+#define DC_ABM1_ACE_OFFSET_SLOPE_3__ABM1_ACE_LOCK_MASK 0x80000000
+#define DC_ABM1_ACE_OFFSET_SLOPE_3__ABM1_ACE_LOCK__SHIFT 0x1f
+#define DC_ABM1_ACE_OFFSET_SLOPE_4__ABM1_ACE_SLOPE_4_MASK 0x7fff
+#define DC_ABM1_ACE_OFFSET_SLOPE_4__ABM1_ACE_SLOPE_4__SHIFT 0x0
+#define DC_ABM1_ACE_OFFSET_SLOPE_4__ABM1_ACE_OFFSET_4_MASK 0x7ff0000
+#define DC_ABM1_ACE_OFFSET_SLOPE_4__ABM1_ACE_OFFSET_4__SHIFT 0x10
+#define DC_ABM1_ACE_OFFSET_SLOPE_4__ABM1_ACE_LOCK_MASK 0x80000000
+#define DC_ABM1_ACE_OFFSET_SLOPE_4__ABM1_ACE_LOCK__SHIFT 0x1f
+#define DC_ABM1_ACE_THRES_12__ABM1_ACE_THRES_1_MASK 0x3ff
+#define DC_ABM1_ACE_THRES_12__ABM1_ACE_THRES_1__SHIFT 0x0
+#define DC_ABM1_ACE_THRES_12__ABM1_ACE_THRES_2_MASK 0x3ff0000
+#define DC_ABM1_ACE_THRES_12__ABM1_ACE_THRES_2__SHIFT 0x10
+#define DC_ABM1_ACE_THRES_12__ABM1_ACE_LOCK_MASK 0x80000000
+#define DC_ABM1_ACE_THRES_12__ABM1_ACE_LOCK__SHIFT 0x1f
+#define DC_ABM1_ACE_THRES_34__ABM1_ACE_THRES_3_MASK 0x3ff
+#define DC_ABM1_ACE_THRES_34__ABM1_ACE_THRES_3__SHIFT 0x0
+#define DC_ABM1_ACE_THRES_34__ABM1_ACE_THRES_4_MASK 0x3ff0000
+#define DC_ABM1_ACE_THRES_34__ABM1_ACE_THRES_4__SHIFT 0x10
+#define DC_ABM1_ACE_THRES_34__ABM1_ACE_IGNORE_MASTER_LOCK_EN_MASK 0x10000000
+#define DC_ABM1_ACE_THRES_34__ABM1_ACE_IGNORE_MASTER_LOCK_EN__SHIFT 0x1c
+#define DC_ABM1_ACE_THRES_34__ABM1_ACE_READBACK_DB_REG_VALUE_EN_MASK 0x20000000
+#define DC_ABM1_ACE_THRES_34__ABM1_ACE_READBACK_DB_REG_VALUE_EN__SHIFT 0x1d
+#define DC_ABM1_ACE_THRES_34__ABM1_ACE_DBUF_REG_UPDATE_PENDING_MASK 0x40000000
+#define DC_ABM1_ACE_THRES_34__ABM1_ACE_DBUF_REG_UPDATE_PENDING__SHIFT 0x1e
+#define DC_ABM1_ACE_THRES_34__ABM1_ACE_LOCK_MASK 0x80000000
+#define DC_ABM1_ACE_THRES_34__ABM1_ACE_LOCK__SHIFT 0x1f
+#define DC_ABM1_ACE_CNTL_MISC__ABM1_ACE_REG_WR_MISSED_FRAME_MASK 0x1
+#define DC_ABM1_ACE_CNTL_MISC__ABM1_ACE_REG_WR_MISSED_FRAME__SHIFT 0x0
+#define DC_ABM1_ACE_CNTL_MISC__ABM1_ACE_REG_WR_MISSED_FRAME_CLEAR_MASK 0x100
+#define DC_ABM1_ACE_CNTL_MISC__ABM1_ACE_REG_WR_MISSED_FRAME_CLEAR__SHIFT 0x8
+#define DC_ABM1_DEBUG_MISC__ABM1_HG_FORCE_INTERRUPT_MASK 0x1
+#define DC_ABM1_DEBUG_MISC__ABM1_HG_FORCE_INTERRUPT__SHIFT 0x0
+#define DC_ABM1_DEBUG_MISC__ABM1_LS_FORCE_INTERRUPT_MASK 0x100
+#define DC_ABM1_DEBUG_MISC__ABM1_LS_FORCE_INTERRUPT__SHIFT 0x8
+#define DC_ABM1_DEBUG_MISC__ABM1_BL_FORCE_INTERRUPT_MASK 0x10000
+#define DC_ABM1_DEBUG_MISC__ABM1_BL_FORCE_INTERRUPT__SHIFT 0x10
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_HG_REG_READ_IN_PROGRESS_MASK 0x1
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_HG_REG_READ_IN_PROGRESS__SHIFT 0x0
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_LS_REG_READ_IN_PROGRESS_MASK 0x2
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_LS_REG_READ_IN_PROGRESS__SHIFT 0x1
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_BL_REG_READ_IN_PROGRESS_MASK 0x4
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_BL_REG_READ_IN_PROGRESS__SHIFT 0x2
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_HG_REG_READ_MISSED_FRAME_MASK 0x100
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_HG_REG_READ_MISSED_FRAME__SHIFT 0x8
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_LS_REG_READ_MISSED_FRAME_MASK 0x200
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_LS_REG_READ_MISSED_FRAME__SHIFT 0x9
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_BL_REG_READ_MISSED_FRAME_MASK 0x400
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_BL_REG_READ_MISSED_FRAME__SHIFT 0xa
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_HG_REG_READ_MISSED_FRAME_CLEAR_MASK 0x10000
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_HG_REG_READ_MISSED_FRAME_CLEAR__SHIFT 0x10
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_LS_REG_READ_MISSED_FRAME_CLEAR_MASK 0x1000000
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_LS_REG_READ_MISSED_FRAME_CLEAR__SHIFT 0x18
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_BL_REG_READ_MISSED_FRAME_CLEAR_MASK 0x80000000
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_BL_REG_READ_MISSED_FRAME_CLEAR__SHIFT 0x1f
+#define DC_ABM1_HG_MISC_CTRL__ABM1_HG_NUM_OF_BINS_SEL_MASK 0x3
+#define DC_ABM1_HG_MISC_CTRL__ABM1_HG_NUM_OF_BINS_SEL__SHIFT 0x0
+#define DC_ABM1_HG_MISC_CTRL__ABM1_HG_VMAX_SEL_MASK 0x100
+#define DC_ABM1_HG_MISC_CTRL__ABM1_HG_VMAX_SEL__SHIFT 0x8
+#define DC_ABM1_HG_MISC_CTRL__ABM1_HG_FINE_MODE_BIN_SEL_MASK 0x1000
+#define DC_ABM1_HG_MISC_CTRL__ABM1_HG_FINE_MODE_BIN_SEL__SHIFT 0xc
+#define DC_ABM1_HG_MISC_CTRL__ABM1_HG_BIN_BITWIDTH_SIZE_SEL_MASK 0x30000
+#define DC_ABM1_HG_MISC_CTRL__ABM1_HG_BIN_BITWIDTH_SIZE_SEL__SHIFT 0x10
+#define DC_ABM1_HG_MISC_CTRL__ABM1_OVR_SCAN_PIXEL_PROCESS_EN_MASK 0x100000
+#define DC_ABM1_HG_MISC_CTRL__ABM1_OVR_SCAN_PIXEL_PROCESS_EN__SHIFT 0x14
+#define DC_ABM1_HG_MISC_CTRL__ABM1_DBUF_HGLS_READBACK_DB_REG_VALUE_EN_MASK 0x800000
+#define DC_ABM1_HG_MISC_CTRL__ABM1_DBUF_HGLS_READBACK_DB_REG_VALUE_EN__SHIFT 0x17
+#define DC_ABM1_HG_MISC_CTRL__ABM1_DBUF_HGLS_REG_FRAME_START_DISP_SEL_MASK 0x7000000
+#define DC_ABM1_HG_MISC_CTRL__ABM1_DBUF_HGLS_REG_FRAME_START_DISP_SEL__SHIFT 0x18
+#define DC_ABM1_HG_MISC_CTRL__ABM1_DBUF_HGLS_REG_UPDATE_AT_FRAME_START_MASK 0x10000000
+#define DC_ABM1_HG_MISC_CTRL__ABM1_DBUF_HGLS_REG_UPDATE_AT_FRAME_START__SHIFT 0x1c
+#define DC_ABM1_HG_MISC_CTRL__ABM1_HGLS_IGNORE_MASTER_LOCK_EN_MASK 0x20000000
+#define DC_ABM1_HG_MISC_CTRL__ABM1_HGLS_IGNORE_MASTER_LOCK_EN__SHIFT 0x1d
+#define DC_ABM1_HG_MISC_CTRL__ABM1_DBUF_HGLS_REG_UPDATE_PENDING_MASK 0x40000000
+#define DC_ABM1_HG_MISC_CTRL__ABM1_DBUF_HGLS_REG_UPDATE_PENDING__SHIFT 0x1e
+#define DC_ABM1_HG_MISC_CTRL__ABM1_HGLS_REG_LOCK_MASK 0x80000000
+#define DC_ABM1_HG_MISC_CTRL__ABM1_HGLS_REG_LOCK__SHIFT 0x1f
+#define DC_ABM1_LS_SUM_OF_LUMA__ABM1_LS_SUM_OF_LUMA_MASK 0xffffffff
+#define DC_ABM1_LS_SUM_OF_LUMA__ABM1_LS_SUM_OF_LUMA__SHIFT 0x0
+#define DC_ABM1_LS_MIN_MAX_LUMA__ABM1_LS_MIN_LUMA_MASK 0x3ff
+#define DC_ABM1_LS_MIN_MAX_LUMA__ABM1_LS_MIN_LUMA__SHIFT 0x0
+#define DC_ABM1_LS_MIN_MAX_LUMA__ABM1_LS_MAX_LUMA_MASK 0x3ff0000
+#define DC_ABM1_LS_MIN_MAX_LUMA__ABM1_LS_MAX_LUMA__SHIFT 0x10
+#define DC_ABM1_LS_FILTERED_MIN_MAX_LUMA__ABM1_LS_FILTERED_MIN_LUMA_MASK 0x3ff
+#define DC_ABM1_LS_FILTERED_MIN_MAX_LUMA__ABM1_LS_FILTERED_MIN_LUMA__SHIFT 0x0
+#define DC_ABM1_LS_FILTERED_MIN_MAX_LUMA__ABM1_LS_FILTERED_MAX_LUMA_MASK 0x3ff0000
+#define DC_ABM1_LS_FILTERED_MIN_MAX_LUMA__ABM1_LS_FILTERED_MAX_LUMA__SHIFT 0x10
+#define DC_ABM1_LS_PIXEL_COUNT__ABM1_LS_PIXEL_COUNT_MASK 0xffffff
+#define DC_ABM1_LS_PIXEL_COUNT__ABM1_LS_PIXEL_COUNT__SHIFT 0x0
+#define DC_ABM1_LS_OVR_SCAN_BIN__ABM1_LS_OVR_SCAN_BIN_MASK 0xffffff
+#define DC_ABM1_LS_OVR_SCAN_BIN__ABM1_LS_OVR_SCAN_BIN__SHIFT 0x0
+#define DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES__ABM1_LS_MIN_PIXEL_VALUE_THRES_MASK 0x3ff
+#define DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES__ABM1_LS_MIN_PIXEL_VALUE_THRES__SHIFT 0x0
+#define DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES__ABM1_LS_MAX_PIXEL_VALUE_THRES_MASK 0x3ff0000
+#define DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES__ABM1_LS_MAX_PIXEL_VALUE_THRES__SHIFT 0x10
+#define DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES__ABM1_HGLS_REG_LOCK_MASK 0x80000000
+#define DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES__ABM1_HGLS_REG_LOCK__SHIFT 0x1f
+#define DC_ABM1_LS_MIN_PIXEL_VALUE_COUNT__ABM1_LS_MIN_PIXEL_VALUE_COUNT_MASK 0xffffff
+#define DC_ABM1_LS_MIN_PIXEL_VALUE_COUNT__ABM1_LS_MIN_PIXEL_VALUE_COUNT__SHIFT 0x0
+#define DC_ABM1_LS_MAX_PIXEL_VALUE_COUNT__ABM1_LS_MAX_PIXEL_VALUE_COUNT_MASK 0xffffff
+#define DC_ABM1_LS_MAX_PIXEL_VALUE_COUNT__ABM1_LS_MAX_PIXEL_VALUE_COUNT__SHIFT 0x0
+#define DC_ABM1_HG_SAMPLE_RATE__ABM1_HG_SAMPLE_RATE_COUNT_EN_MASK 0x1
+#define DC_ABM1_HG_SAMPLE_RATE__ABM1_HG_SAMPLE_RATE_COUNT_EN__SHIFT 0x0
+#define DC_ABM1_HG_SAMPLE_RATE__ABM1_HG_RESET_SAMPLE_RATE_FRAME_COUNTER_MASK 0x2
+#define DC_ABM1_HG_SAMPLE_RATE__ABM1_HG_RESET_SAMPLE_RATE_FRAME_COUNTER__SHIFT 0x1
+#define DC_ABM1_HG_SAMPLE_RATE__ABM1_HG_SAMPLE_RATE_FRAME_COUNT_MASK 0xff00
+#define DC_ABM1_HG_SAMPLE_RATE__ABM1_HG_SAMPLE_RATE_FRAME_COUNT__SHIFT 0x8
+#define DC_ABM1_HG_SAMPLE_RATE__ABM1_HG_INITIAL_SAMPLE_RATE_COUNT_VALUE_WHEN_RESET_MASK 0xff0000
+#define DC_ABM1_HG_SAMPLE_RATE__ABM1_HG_INITIAL_SAMPLE_RATE_COUNT_VALUE_WHEN_RESET__SHIFT 0x10
+#define DC_ABM1_HG_SAMPLE_RATE__ABM1_HGLS_REG_LOCK_MASK 0x80000000
+#define DC_ABM1_HG_SAMPLE_RATE__ABM1_HGLS_REG_LOCK__SHIFT 0x1f
+#define DC_ABM1_LS_SAMPLE_RATE__ABM1_LS_SAMPLE_RATE_COUNT_EN_MASK 0x1
+#define DC_ABM1_LS_SAMPLE_RATE__ABM1_LS_SAMPLE_RATE_COUNT_EN__SHIFT 0x0
+#define DC_ABM1_LS_SAMPLE_RATE__ABM1_LS_RESET_SAMPLE_RATE_FRAME_COUNTER_MASK 0x2
+#define DC_ABM1_LS_SAMPLE_RATE__ABM1_LS_RESET_SAMPLE_RATE_FRAME_COUNTER__SHIFT 0x1
+#define DC_ABM1_LS_SAMPLE_RATE__ABM1_LS_SAMPLE_RATE_FRAME_COUNT_MASK 0xff00
+#define DC_ABM1_LS_SAMPLE_RATE__ABM1_LS_SAMPLE_RATE_FRAME_COUNT__SHIFT 0x8
+#define DC_ABM1_LS_SAMPLE_RATE__ABM1_LS_INITIAL_SAMPLE_RATE_COUNT_VALUE_WHEN_RESET_MASK 0xff0000
+#define DC_ABM1_LS_SAMPLE_RATE__ABM1_LS_INITIAL_SAMPLE_RATE_COUNT_VALUE_WHEN_RESET__SHIFT 0x10
+#define DC_ABM1_LS_SAMPLE_RATE__ABM1_HGLS_REG_LOCK_MASK 0x80000000
+#define DC_ABM1_LS_SAMPLE_RATE__ABM1_HGLS_REG_LOCK__SHIFT 0x1f
+#define DC_ABM1_HG_BIN_1_32_SHIFT_FLAG__ABM1_HG_BIN_1_32_SHIFT_FLAG_MASK 0xffffffff
+#define DC_ABM1_HG_BIN_1_32_SHIFT_FLAG__ABM1_HG_BIN_1_32_SHIFT_FLAG__SHIFT 0x0
+#define DC_ABM1_HG_BIN_1_8_SHIFT_INDEX__ABM1_HG_BIN_1_8_SHIFT_INDEX_MASK 0xffffffff
+#define DC_ABM1_HG_BIN_1_8_SHIFT_INDEX__ABM1_HG_BIN_1_8_SHIFT_INDEX__SHIFT 0x0
+#define DC_ABM1_HG_BIN_9_16_SHIFT_INDEX__ABM1_HG_BIN_9_16_SHIFT_INDEX_MASK 0xffffffff
+#define DC_ABM1_HG_BIN_9_16_SHIFT_INDEX__ABM1_HG_BIN_9_16_SHIFT_INDEX__SHIFT 0x0
+#define DC_ABM1_HG_BIN_17_24_SHIFT_INDEX__ABM1_HG_BIN_17_24_SHIFT_INDEX_MASK 0xffffffff
+#define DC_ABM1_HG_BIN_17_24_SHIFT_INDEX__ABM1_HG_BIN_17_24_SHIFT_INDEX__SHIFT 0x0
+#define DC_ABM1_HG_BIN_25_32_SHIFT_INDEX__ABM1_HG_BIN_25_32_SHIFT_INDEX_MASK 0xffffffff
+#define DC_ABM1_HG_BIN_25_32_SHIFT_INDEX__ABM1_HG_BIN_25_32_SHIFT_INDEX__SHIFT 0x0
+#define DC_ABM1_HG_RESULT_1__ABM1_HG_RESULT_1_MASK 0xffffffff
+#define DC_ABM1_HG_RESULT_1__ABM1_HG_RESULT_1__SHIFT 0x0
+#define DC_ABM1_HG_RESULT_2__ABM1_HG_RESULT_2_MASK 0xffffffff
+#define DC_ABM1_HG_RESULT_2__ABM1_HG_RESULT_2__SHIFT 0x0
+#define DC_ABM1_HG_RESULT_3__ABM1_HG_RESULT_3_MASK 0xffffffff
+#define DC_ABM1_HG_RESULT_3__ABM1_HG_RESULT_3__SHIFT 0x0
+#define DC_ABM1_HG_RESULT_4__ABM1_HG_RESULT_4_MASK 0xffffffff
+#define DC_ABM1_HG_RESULT_4__ABM1_HG_RESULT_4__SHIFT 0x0
+#define DC_ABM1_HG_RESULT_5__ABM1_HG_RESULT_5_MASK 0xffffffff
+#define DC_ABM1_HG_RESULT_5__ABM1_HG_RESULT_5__SHIFT 0x0
+#define DC_ABM1_HG_RESULT_6__ABM1_HG_RESULT_6_MASK 0xffffffff
+#define DC_ABM1_HG_RESULT_6__ABM1_HG_RESULT_6__SHIFT 0x0
+#define DC_ABM1_HG_RESULT_7__ABM1_HG_RESULT_7_MASK 0xffffffff
+#define DC_ABM1_HG_RESULT_7__ABM1_HG_RESULT_7__SHIFT 0x0
+#define DC_ABM1_HG_RESULT_8__ABM1_HG_RESULT_8_MASK 0xffffffff
+#define DC_ABM1_HG_RESULT_8__ABM1_HG_RESULT_8__SHIFT 0x0
+#define DC_ABM1_HG_RESULT_9__ABM1_HG_RESULT_9_MASK 0xffffffff
+#define DC_ABM1_HG_RESULT_9__ABM1_HG_RESULT_9__SHIFT 0x0
+#define DC_ABM1_HG_RESULT_10__ABM1_HG_RESULT_10_MASK 0xffffffff
+#define DC_ABM1_HG_RESULT_10__ABM1_HG_RESULT_10__SHIFT 0x0
+#define DC_ABM1_HG_RESULT_11__ABM1_HG_RESULT_11_MASK 0xffffffff
+#define DC_ABM1_HG_RESULT_11__ABM1_HG_RESULT_11__SHIFT 0x0
+#define DC_ABM1_HG_RESULT_12__ABM1_HG_RESULT_12_MASK 0xffffffff
+#define DC_ABM1_HG_RESULT_12__ABM1_HG_RESULT_12__SHIFT 0x0
+#define DC_ABM1_HG_RESULT_13__ABM1_HG_RESULT_13_MASK 0xffffffff
+#define DC_ABM1_HG_RESULT_13__ABM1_HG_RESULT_13__SHIFT 0x0
+#define DC_ABM1_HG_RESULT_14__ABM1_HG_RESULT_14_MASK 0xffffffff
+#define DC_ABM1_HG_RESULT_14__ABM1_HG_RESULT_14__SHIFT 0x0
+#define DC_ABM1_HG_RESULT_15__ABM1_HG_RESULT_15_MASK 0xffffffff
+#define DC_ABM1_HG_RESULT_15__ABM1_HG_RESULT_15__SHIFT 0x0
+#define DC_ABM1_HG_RESULT_16__ABM1_HG_RESULT_16_MASK 0xffffffff
+#define DC_ABM1_HG_RESULT_16__ABM1_HG_RESULT_16__SHIFT 0x0
+#define DC_ABM1_HG_RESULT_17__ABM1_HG_RESULT_17_MASK 0xffffffff
+#define DC_ABM1_HG_RESULT_17__ABM1_HG_RESULT_17__SHIFT 0x0
+#define DC_ABM1_HG_RESULT_18__ABM1_HG_RESULT_18_MASK 0xffffffff
+#define DC_ABM1_HG_RESULT_18__ABM1_HG_RESULT_18__SHIFT 0x0
+#define DC_ABM1_HG_RESULT_19__ABM1_HG_RESULT_19_MASK 0xffffffff
+#define DC_ABM1_HG_RESULT_19__ABM1_HG_RESULT_19__SHIFT 0x0
+#define DC_ABM1_HG_RESULT_20__ABM1_HG_RESULT_20_MASK 0xffffffff
+#define DC_ABM1_HG_RESULT_20__ABM1_HG_RESULT_20__SHIFT 0x0
+#define DC_ABM1_HG_RESULT_21__ABM1_HG_RESULT_21_MASK 0xffffffff
+#define DC_ABM1_HG_RESULT_21__ABM1_HG_RESULT_21__SHIFT 0x0
+#define DC_ABM1_HG_RESULT_22__ABM1_HG_RESULT_22_MASK 0xffffffff
+#define DC_ABM1_HG_RESULT_22__ABM1_HG_RESULT_22__SHIFT 0x0
+#define DC_ABM1_HG_RESULT_23__ABM1_HG_RESULT_23_MASK 0xffffffff
+#define DC_ABM1_HG_RESULT_23__ABM1_HG_RESULT_23__SHIFT 0x0
+#define DC_ABM1_HG_RESULT_24__ABM1_HG_RESULT_24_MASK 0xffffffff
+#define DC_ABM1_HG_RESULT_24__ABM1_HG_RESULT_24__SHIFT 0x0
+#define DC_ABM1_OVERSCAN_PIXEL_VALUE__ABM1_OVERSCAN_R_PIXEL_VALUE_MASK 0x3ff
+#define DC_ABM1_OVERSCAN_PIXEL_VALUE__ABM1_OVERSCAN_R_PIXEL_VALUE__SHIFT 0x0
+#define DC_ABM1_OVERSCAN_PIXEL_VALUE__ABM1_OVERSCAN_G_PIXEL_VALUE_MASK 0xffc00
+#define DC_ABM1_OVERSCAN_PIXEL_VALUE__ABM1_OVERSCAN_G_PIXEL_VALUE__SHIFT 0xa
+#define DC_ABM1_OVERSCAN_PIXEL_VALUE__ABM1_OVERSCAN_B_PIXEL_VALUE_MASK 0x3ff00000
+#define DC_ABM1_OVERSCAN_PIXEL_VALUE__ABM1_OVERSCAN_B_PIXEL_VALUE__SHIFT 0x14
+#define DC_ABM1_BL_MASTER_LOCK__ABM1_BL_MASTER_LOCK_MASK 0x80000000
+#define DC_ABM1_BL_MASTER_LOCK__ABM1_BL_MASTER_LOCK__SHIFT 0x1f
+#define ABM_TEST_DEBUG_INDEX__ABM_TEST_DEBUG_INDEX_MASK 0xff
+#define ABM_TEST_DEBUG_INDEX__ABM_TEST_DEBUG_INDEX__SHIFT 0x0
+#define ABM_TEST_DEBUG_INDEX__ABM_TEST_DEBUG_WRITE_EN_MASK 0x100
+#define ABM_TEST_DEBUG_INDEX__ABM_TEST_DEBUG_WRITE_EN__SHIFT 0x8
+#define ABM_TEST_DEBUG_DATA__ABM_TEST_DEBUG_DATA_MASK 0xffffffff
+#define ABM_TEST_DEBUG_DATA__ABM_TEST_DEBUG_DATA__SHIFT 0x0
+#define CRTC_H_BLANK_EARLY_NUM__CRTC_H_BLANK_EARLY_NUM_MASK 0x3ff
+#define CRTC_H_BLANK_EARLY_NUM__CRTC_H_BLANK_EARLY_NUM__SHIFT 0x0
+#define CRTC_H_BLANK_EARLY_NUM__CRTC_H_BLANK_EARLY_NUM_DIS_MASK 0x10000
+#define CRTC_H_BLANK_EARLY_NUM__CRTC_H_BLANK_EARLY_NUM_DIS__SHIFT 0x10
+#define CRTC_H_TOTAL__CRTC_H_TOTAL_MASK 0x3fff
+#define CRTC_H_TOTAL__CRTC_H_TOTAL__SHIFT 0x0
+#define CRTC_H_BLANK_START_END__CRTC_H_BLANK_START_MASK 0x3fff
+#define CRTC_H_BLANK_START_END__CRTC_H_BLANK_START__SHIFT 0x0
+#define CRTC_H_BLANK_START_END__CRTC_H_BLANK_END_MASK 0x3fff0000
+#define CRTC_H_BLANK_START_END__CRTC_H_BLANK_END__SHIFT 0x10
+#define CRTC_H_SYNC_A__CRTC_H_SYNC_A_START_MASK 0x3fff
+#define CRTC_H_SYNC_A__CRTC_H_SYNC_A_START__SHIFT 0x0
+#define CRTC_H_SYNC_A__CRTC_H_SYNC_A_END_MASK 0x3fff0000
+#define CRTC_H_SYNC_A__CRTC_H_SYNC_A_END__SHIFT 0x10
+#define CRTC_H_SYNC_A_CNTL__CRTC_H_SYNC_A_POL_MASK 0x1
+#define CRTC_H_SYNC_A_CNTL__CRTC_H_SYNC_A_POL__SHIFT 0x0
+#define CRTC_H_SYNC_A_CNTL__CRTC_COMP_SYNC_A_EN_MASK 0x10000
+#define CRTC_H_SYNC_A_CNTL__CRTC_COMP_SYNC_A_EN__SHIFT 0x10
+#define CRTC_H_SYNC_A_CNTL__CRTC_H_SYNC_A_CUTOFF_MASK 0x20000
+#define CRTC_H_SYNC_A_CNTL__CRTC_H_SYNC_A_CUTOFF__SHIFT 0x11
+#define CRTC_H_SYNC_B__CRTC_H_SYNC_B_START_MASK 0x3fff
+#define CRTC_H_SYNC_B__CRTC_H_SYNC_B_START__SHIFT 0x0
+#define CRTC_H_SYNC_B__CRTC_H_SYNC_B_END_MASK 0x3fff0000
+#define CRTC_H_SYNC_B__CRTC_H_SYNC_B_END__SHIFT 0x10
+#define CRTC_H_SYNC_B_CNTL__CRTC_H_SYNC_B_POL_MASK 0x1
+#define CRTC_H_SYNC_B_CNTL__CRTC_H_SYNC_B_POL__SHIFT 0x0
+#define CRTC_H_SYNC_B_CNTL__CRTC_COMP_SYNC_B_EN_MASK 0x10000
+#define CRTC_H_SYNC_B_CNTL__CRTC_COMP_SYNC_B_EN__SHIFT 0x10
+#define CRTC_H_SYNC_B_CNTL__CRTC_H_SYNC_B_CUTOFF_MASK 0x20000
+#define CRTC_H_SYNC_B_CNTL__CRTC_H_SYNC_B_CUTOFF__SHIFT 0x11
+#define CRTC_VBI_END__CRTC_VBI_V_END_MASK 0x3fff
+#define CRTC_VBI_END__CRTC_VBI_V_END__SHIFT 0x0
+#define CRTC_VBI_END__CRTC_VBI_H_END_MASK 0x3fff0000
+#define CRTC_VBI_END__CRTC_VBI_H_END__SHIFT 0x10
+#define CRTC_V_TOTAL__CRTC_V_TOTAL_MASK 0x3fff
+#define CRTC_V_TOTAL__CRTC_V_TOTAL__SHIFT 0x0
+#define CRTC_V_TOTAL_MIN__CRTC_V_TOTAL_MIN_MASK 0x3fff
+#define CRTC_V_TOTAL_MIN__CRTC_V_TOTAL_MIN__SHIFT 0x0
+#define CRTC_V_TOTAL_MAX__CRTC_V_TOTAL_MAX_MASK 0x3fff
+#define CRTC_V_TOTAL_MAX__CRTC_V_TOTAL_MAX__SHIFT 0x0
+#define CRTC_V_TOTAL_MAX__CRTC_ALLOW_VBLANK_EXTENSION_FOR_MC_TRAINING_MASK 0x10000
+#define CRTC_V_TOTAL_MAX__CRTC_ALLOW_VBLANK_EXTENSION_FOR_MC_TRAINING__SHIFT 0x10
+#define CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MIN_SEL_MASK 0x1
+#define CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MIN_SEL__SHIFT 0x0
+#define CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MAX_SEL_MASK 0x10
+#define CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MAX_SEL__SHIFT 0x4
+#define CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_ON_EVENT_MASK 0x100
+#define CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_ON_EVENT__SHIFT 0x8
+#define CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_TO_MASTER_VSYNC_MASK 0x1000
+#define CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_TO_MASTER_VSYNC__SHIFT 0xc
+#define CRTC_V_TOTAL_CONTROL__CRTC_SET_V_TOTAL_MIN_MASK_EN_MASK 0x8000
+#define CRTC_V_TOTAL_CONTROL__CRTC_SET_V_TOTAL_MIN_MASK_EN__SHIFT 0xf
+#define CRTC_V_TOTAL_CONTROL__CRTC_SET_V_TOTAL_MIN_MASK_MASK 0xffff0000
+#define CRTC_V_TOTAL_CONTROL__CRTC_SET_V_TOTAL_MIN_MASK__SHIFT 0x10
+#define CRTC_V_TOTAL_INT_STATUS__CRTC_SET_V_TOTAL_MIN_EVENT_OCCURED_MASK 0x1
+#define CRTC_V_TOTAL_INT_STATUS__CRTC_SET_V_TOTAL_MIN_EVENT_OCCURED__SHIFT 0x0
+#define CRTC_V_TOTAL_INT_STATUS__CRTC_SET_V_TOTAL_MIN_EVENT_OCCURED_INT_MASK 0x10
+#define CRTC_V_TOTAL_INT_STATUS__CRTC_SET_V_TOTAL_MIN_EVENT_OCCURED_INT__SHIFT 0x4
+#define CRTC_V_TOTAL_INT_STATUS__CRTC_SET_V_TOTAL_MIN_EVENT_OCCURED_ACK_MASK 0x100
+#define CRTC_V_TOTAL_INT_STATUS__CRTC_SET_V_TOTAL_MIN_EVENT_OCCURED_ACK__SHIFT 0x8
+#define CRTC_V_TOTAL_INT_STATUS__CRTC_SET_V_TOTAL_MIN_EVENT_OCCURED_MSK_MASK 0x1000
+#define CRTC_V_TOTAL_INT_STATUS__CRTC_SET_V_TOTAL_MIN_EVENT_OCCURED_MSK__SHIFT 0xc
+#define CRTC_VSYNC_NOM_INT_STATUS__CRTC_VSYNC_NOM_MASK 0x1
+#define CRTC_VSYNC_NOM_INT_STATUS__CRTC_VSYNC_NOM__SHIFT 0x0
+#define CRTC_VSYNC_NOM_INT_STATUS__CRTC_VSYNC_NOM_INT_CLEAR_MASK 0x10
+#define CRTC_VSYNC_NOM_INT_STATUS__CRTC_VSYNC_NOM_INT_CLEAR__SHIFT 0x4
+#define CRTC_V_BLANK_START_END__CRTC_V_BLANK_START_MASK 0x3fff
+#define CRTC_V_BLANK_START_END__CRTC_V_BLANK_START__SHIFT 0x0
+#define CRTC_V_BLANK_START_END__CRTC_V_BLANK_END_MASK 0x3fff0000
+#define CRTC_V_BLANK_START_END__CRTC_V_BLANK_END__SHIFT 0x10
+#define CRTC_V_SYNC_A__CRTC_V_SYNC_A_START_MASK 0x3fff
+#define CRTC_V_SYNC_A__CRTC_V_SYNC_A_START__SHIFT 0x0
+#define CRTC_V_SYNC_A__CRTC_V_SYNC_A_END_MASK 0x3fff0000
+#define CRTC_V_SYNC_A__CRTC_V_SYNC_A_END__SHIFT 0x10
+#define CRTC_V_SYNC_A_CNTL__CRTC_V_SYNC_A_POL_MASK 0x1
+#define CRTC_V_SYNC_A_CNTL__CRTC_V_SYNC_A_POL__SHIFT 0x0
+#define CRTC_V_SYNC_B__CRTC_V_SYNC_B_START_MASK 0x3fff
+#define CRTC_V_SYNC_B__CRTC_V_SYNC_B_START__SHIFT 0x0
+#define CRTC_V_SYNC_B__CRTC_V_SYNC_B_END_MASK 0x3fff0000
+#define CRTC_V_SYNC_B__CRTC_V_SYNC_B_END__SHIFT 0x10
+#define CRTC_V_SYNC_B_CNTL__CRTC_V_SYNC_B_POL_MASK 0x1
+#define CRTC_V_SYNC_B_CNTL__CRTC_V_SYNC_B_POL__SHIFT 0x0
+#define CRTC_DTMTEST_CNTL__CRTC_DTMTEST_CRTC_EN_MASK 0x1
+#define CRTC_DTMTEST_CNTL__CRTC_DTMTEST_CRTC_EN__SHIFT 0x0
+#define CRTC_DTMTEST_CNTL__CRTC_DTMTEST_CLK_DIV_MASK 0x1e
+#define CRTC_DTMTEST_CNTL__CRTC_DTMTEST_CLK_DIV__SHIFT 0x1
+#define CRTC_DTMTEST_STATUS_POSITION__CRTC_DTMTEST_VERT_COUNT_MASK 0x3fff
+#define CRTC_DTMTEST_STATUS_POSITION__CRTC_DTMTEST_VERT_COUNT__SHIFT 0x0
+#define CRTC_DTMTEST_STATUS_POSITION__CRTC_DTMTEST_HORZ_COUNT_MASK 0x3fff0000
+#define CRTC_DTMTEST_STATUS_POSITION__CRTC_DTMTEST_HORZ_COUNT__SHIFT 0x10
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_SOURCE_SELECT_MASK 0x1f
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_SOURCE_SELECT__SHIFT 0x0
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_POLARITY_SELECT_MASK 0xe0
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_POLARITY_SELECT__SHIFT 0x5
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_RESYNC_BYPASS_EN_MASK 0x100
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_RESYNC_BYPASS_EN__SHIFT 0x8
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_INPUT_STATUS_MASK 0x200
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_INPUT_STATUS__SHIFT 0x9
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_POLARITY_STATUS_MASK 0x400
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_POLARITY_STATUS__SHIFT 0xa
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_OCCURRED_MASK 0x800
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_OCCURRED__SHIFT 0xb
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_RISING_EDGE_DETECT_CNTL_MASK 0x3000
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_RISING_EDGE_DETECT_CNTL__SHIFT 0xc
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_FALLING_EDGE_DETECT_CNTL_MASK 0x30000
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_FALLING_EDGE_DETECT_CNTL__SHIFT 0x10
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_FREQUENCY_SELECT_MASK 0x300000
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_FREQUENCY_SELECT__SHIFT 0x14
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_DELAY_MASK 0x1f000000
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_DELAY__SHIFT 0x18
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_CLEAR_MASK 0x80000000
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_CLEAR__SHIFT 0x1f
+#define CRTC_TRIGA_MANUAL_TRIG__CRTC_TRIGA_MANUAL_TRIG_MASK 0x1
+#define CRTC_TRIGA_MANUAL_TRIG__CRTC_TRIGA_MANUAL_TRIG__SHIFT 0x0
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_SOURCE_SELECT_MASK 0x1f
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_SOURCE_SELECT__SHIFT 0x0
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_POLARITY_SELECT_MASK 0xe0
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_POLARITY_SELECT__SHIFT 0x5
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_RESYNC_BYPASS_EN_MASK 0x100
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_RESYNC_BYPASS_EN__SHIFT 0x8
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_INPUT_STATUS_MASK 0x200
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_INPUT_STATUS__SHIFT 0x9
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_POLARITY_STATUS_MASK 0x400
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_POLARITY_STATUS__SHIFT 0xa
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_OCCURRED_MASK 0x800
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_OCCURRED__SHIFT 0xb
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_RISING_EDGE_DETECT_CNTL_MASK 0x3000
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_RISING_EDGE_DETECT_CNTL__SHIFT 0xc
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_FALLING_EDGE_DETECT_CNTL_MASK 0x30000
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_FALLING_EDGE_DETECT_CNTL__SHIFT 0x10
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_FREQUENCY_SELECT_MASK 0x300000
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_FREQUENCY_SELECT__SHIFT 0x14
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_DELAY_MASK 0x1f000000
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_DELAY__SHIFT 0x18
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_CLEAR_MASK 0x80000000
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_CLEAR__SHIFT 0x1f
+#define CRTC_TRIGB_MANUAL_TRIG__CRTC_TRIGB_MANUAL_TRIG_MASK 0x1
+#define CRTC_TRIGB_MANUAL_TRIG__CRTC_TRIGB_MANUAL_TRIG__SHIFT 0x0
+#define CRTC_FORCE_COUNT_NOW_CNTL__CRTC_FORCE_COUNT_NOW_MODE_MASK 0x3
+#define CRTC_FORCE_COUNT_NOW_CNTL__CRTC_FORCE_COUNT_NOW_MODE__SHIFT 0x0
+#define CRTC_FORCE_COUNT_NOW_CNTL__CRTC_FORCE_COUNT_NOW_CHECK_MASK 0x10
+#define CRTC_FORCE_COUNT_NOW_CNTL__CRTC_FORCE_COUNT_NOW_CHECK__SHIFT 0x4
+#define CRTC_FORCE_COUNT_NOW_CNTL__CRTC_FORCE_COUNT_NOW_TRIG_SEL_MASK 0x100
+#define CRTC_FORCE_COUNT_NOW_CNTL__CRTC_FORCE_COUNT_NOW_TRIG_SEL__SHIFT 0x8
+#define CRTC_FORCE_COUNT_NOW_CNTL__CRTC_FORCE_COUNT_NOW_OCCURRED_MASK 0x10000
+#define CRTC_FORCE_COUNT_NOW_CNTL__CRTC_FORCE_COUNT_NOW_OCCURRED__SHIFT 0x10
+#define CRTC_FORCE_COUNT_NOW_CNTL__CRTC_FORCE_COUNT_NOW_CLEAR_MASK 0x1000000
+#define CRTC_FORCE_COUNT_NOW_CNTL__CRTC_FORCE_COUNT_NOW_CLEAR__SHIFT 0x18
+#define CRTC_FLOW_CONTROL__CRTC_FLOW_CONTROL_SOURCE_SELECT_MASK 0x1f
+#define CRTC_FLOW_CONTROL__CRTC_FLOW_CONTROL_SOURCE_SELECT__SHIFT 0x0
+#define CRTC_FLOW_CONTROL__CRTC_FLOW_CONTROL_POLARITY_MASK 0x100
+#define CRTC_FLOW_CONTROL__CRTC_FLOW_CONTROL_POLARITY__SHIFT 0x8
+#define CRTC_FLOW_CONTROL__CRTC_FLOW_CONTROL_GRANULARITY_MASK 0x10000
+#define CRTC_FLOW_CONTROL__CRTC_FLOW_CONTROL_GRANULARITY__SHIFT 0x10
+#define CRTC_FLOW_CONTROL__CRTC_FLOW_CONTROL_INPUT_STATUS_MASK 0x1000000
+#define CRTC_FLOW_CONTROL__CRTC_FLOW_CONTROL_INPUT_STATUS__SHIFT 0x18
+#define CRTC_STEREO_FORCE_NEXT_EYE__CRTC_STEREO_FORCE_NEXT_EYE_MASK 0x3
+#define CRTC_STEREO_FORCE_NEXT_EYE__CRTC_STEREO_FORCE_NEXT_EYE__SHIFT 0x0
+#define CRTC_STEREO_FORCE_NEXT_EYE__CRTC_AVSYNC_FRAME_COUNTER_MASK 0xff00
+#define CRTC_STEREO_FORCE_NEXT_EYE__CRTC_AVSYNC_FRAME_COUNTER__SHIFT 0x8
+#define CRTC_STEREO_FORCE_NEXT_EYE__CRTC_AVSYNC_LINE_COUNTER_MASK 0x1fff0000
+#define CRTC_STEREO_FORCE_NEXT_EYE__CRTC_AVSYNC_LINE_COUNTER__SHIFT 0x10
+#define CRTC_AVSYNC_COUNTER__CRTC_AVSYNC_COUNTER_MASK 0xffffffff
+#define CRTC_AVSYNC_COUNTER__CRTC_AVSYNC_COUNTER__SHIFT 0x0
+#define CRTC_CONTROL__CRTC_MASTER_EN_MASK 0x1
+#define CRTC_CONTROL__CRTC_MASTER_EN__SHIFT 0x0
+#define CRTC_CONTROL__CRTC_SYNC_RESET_SEL_MASK 0x10
+#define CRTC_CONTROL__CRTC_SYNC_RESET_SEL__SHIFT 0x4
+#define CRTC_CONTROL__CRTC_DISABLE_POINT_CNTL_MASK 0x300
+#define CRTC_CONTROL__CRTC_DISABLE_POINT_CNTL__SHIFT 0x8
+#define CRTC_CONTROL__CRTC_START_POINT_CNTL_MASK 0x1000
+#define CRTC_CONTROL__CRTC_START_POINT_CNTL__SHIFT 0xc
+#define CRTC_CONTROL__CRTC_FIELD_NUMBER_CNTL_MASK 0x2000
+#define CRTC_CONTROL__CRTC_FIELD_NUMBER_CNTL__SHIFT 0xd
+#define CRTC_CONTROL__CRTC_FIELD_NUMBER_POLARITY_MASK 0x4000
+#define CRTC_CONTROL__CRTC_FIELD_NUMBER_POLARITY__SHIFT 0xe
+#define CRTC_CONTROL__CRTC_CURRENT_MASTER_EN_STATE_MASK 0x10000
+#define CRTC_CONTROL__CRTC_CURRENT_MASTER_EN_STATE__SHIFT 0x10
+#define CRTC_CONTROL__CRTC_HBLANK_EARLY_CONTROL_MASK 0x700000
+#define CRTC_CONTROL__CRTC_HBLANK_EARLY_CONTROL__SHIFT 0x14
+#define CRTC_CONTROL__CRTC_DISP_READ_REQUEST_DISABLE_MASK 0x1000000
+#define CRTC_CONTROL__CRTC_DISP_READ_REQUEST_DISABLE__SHIFT 0x18
+#define CRTC_CONTROL__CRTC_SOF_PULL_EN_MASK 0x20000000
+#define CRTC_CONTROL__CRTC_SOF_PULL_EN__SHIFT 0x1d
+#define CRTC_CONTROL__CRTC_AVSYNC_LOCK_SNAPSHOT_MASK 0x40000000
+#define CRTC_CONTROL__CRTC_AVSYNC_LOCK_SNAPSHOT__SHIFT 0x1e
+#define CRTC_CONTROL__CRTC_AVSYNC_VSYNC_N_HSYNC_MODE_MASK 0x80000000
+#define CRTC_CONTROL__CRTC_AVSYNC_VSYNC_N_HSYNC_MODE__SHIFT 0x1f
+#define CRTC_BLANK_CONTROL__CRTC_CURRENT_BLANK_STATE_MASK 0x1
+#define CRTC_BLANK_CONTROL__CRTC_CURRENT_BLANK_STATE__SHIFT 0x0
+#define CRTC_BLANK_CONTROL__CRTC_BLANK_DATA_EN_MASK 0x100
+#define CRTC_BLANK_CONTROL__CRTC_BLANK_DATA_EN__SHIFT 0x8
+#define CRTC_BLANK_CONTROL__CRTC_BLANK_DE_MODE_MASK 0x10000
+#define CRTC_BLANK_CONTROL__CRTC_BLANK_DE_MODE__SHIFT 0x10
+#define CRTC_INTERLACE_CONTROL__CRTC_INTERLACE_ENABLE_MASK 0x1
+#define CRTC_INTERLACE_CONTROL__CRTC_INTERLACE_ENABLE__SHIFT 0x0
+#define CRTC_INTERLACE_CONTROL__CRTC_INTERLACE_FORCE_NEXT_FIELD_MASK 0x30000
+#define CRTC_INTERLACE_CONTROL__CRTC_INTERLACE_FORCE_NEXT_FIELD__SHIFT 0x10
+#define CRTC_INTERLACE_STATUS__CRTC_INTERLACE_CURRENT_FIELD_MASK 0x1
+#define CRTC_INTERLACE_STATUS__CRTC_INTERLACE_CURRENT_FIELD__SHIFT 0x0
+#define CRTC_INTERLACE_STATUS__CRTC_INTERLACE_NEXT_FIELD_MASK 0x2
+#define CRTC_INTERLACE_STATUS__CRTC_INTERLACE_NEXT_FIELD__SHIFT 0x1
+#define CRTC_FIELD_INDICATION_CONTROL__CRTC_FIELD_INDICATION_OUTPUT_POLARITY_MASK 0x1
+#define CRTC_FIELD_INDICATION_CONTROL__CRTC_FIELD_INDICATION_OUTPUT_POLARITY__SHIFT 0x0
+#define CRTC_FIELD_INDICATION_CONTROL__CRTC_FIELD_ALIGNMENT_MASK 0x2
+#define CRTC_FIELD_INDICATION_CONTROL__CRTC_FIELD_ALIGNMENT__SHIFT 0x1
+#define CRTC_PIXEL_DATA_READBACK0__CRTC_PIXEL_DATA_BLUE_CB_MASK 0xfff
+#define CRTC_PIXEL_DATA_READBACK0__CRTC_PIXEL_DATA_BLUE_CB__SHIFT 0x0
+#define CRTC_PIXEL_DATA_READBACK0__CRTC_PIXEL_DATA_GREEN_Y_MASK 0xfff0000
+#define CRTC_PIXEL_DATA_READBACK0__CRTC_PIXEL_DATA_GREEN_Y__SHIFT 0x10
+#define CRTC_PIXEL_DATA_READBACK1__CRTC_PIXEL_DATA_RED_CR_MASK 0xfff
+#define CRTC_PIXEL_DATA_READBACK1__CRTC_PIXEL_DATA_RED_CR__SHIFT 0x0
+#define CRTC_STATUS__CRTC_V_BLANK_MASK 0x1
+#define CRTC_STATUS__CRTC_V_BLANK__SHIFT 0x0
+#define CRTC_STATUS__CRTC_V_ACTIVE_DISP_MASK 0x2
+#define CRTC_STATUS__CRTC_V_ACTIVE_DISP__SHIFT 0x1
+#define CRTC_STATUS__CRTC_V_SYNC_A_MASK 0x4
+#define CRTC_STATUS__CRTC_V_SYNC_A__SHIFT 0x2
+#define CRTC_STATUS__CRTC_V_UPDATE_MASK 0x8
+#define CRTC_STATUS__CRTC_V_UPDATE__SHIFT 0x3
+#define CRTC_STATUS__CRTC_V_START_LINE_MASK 0x10
+#define CRTC_STATUS__CRTC_V_START_LINE__SHIFT 0x4
+#define CRTC_STATUS__CRTC_V_BLANK_3D_STRUCTURE_MASK 0x20
+#define CRTC_STATUS__CRTC_V_BLANK_3D_STRUCTURE__SHIFT 0x5
+#define CRTC_STATUS__CRTC_H_BLANK_MASK 0x10000
+#define CRTC_STATUS__CRTC_H_BLANK__SHIFT 0x10
+#define CRTC_STATUS__CRTC_H_ACTIVE_DISP_MASK 0x20000
+#define CRTC_STATUS__CRTC_H_ACTIVE_DISP__SHIFT 0x11
+#define CRTC_STATUS__CRTC_H_SYNC_A_MASK 0x40000
+#define CRTC_STATUS__CRTC_H_SYNC_A__SHIFT 0x12
+#define CRTC_STATUS_POSITION__CRTC_VERT_COUNT_MASK 0x3fff
+#define CRTC_STATUS_POSITION__CRTC_VERT_COUNT__SHIFT 0x0
+#define CRTC_STATUS_POSITION__CRTC_HORZ_COUNT_MASK 0x3fff0000
+#define CRTC_STATUS_POSITION__CRTC_HORZ_COUNT__SHIFT 0x10
+#define CRTC_NOM_VERT_POSITION__CRTC_VERT_COUNT_NOM_MASK 0x3fff
+#define CRTC_NOM_VERT_POSITION__CRTC_VERT_COUNT_NOM__SHIFT 0x0
+#define CRTC_STATUS_FRAME_COUNT__CRTC_FRAME_COUNT_MASK 0xffffff
+#define CRTC_STATUS_FRAME_COUNT__CRTC_FRAME_COUNT__SHIFT 0x0
+#define CRTC_STATUS_VF_COUNT__CRTC_VF_COUNT_MASK 0x3fffffff
+#define CRTC_STATUS_VF_COUNT__CRTC_VF_COUNT__SHIFT 0x0
+#define CRTC_STATUS_HV_COUNT__CRTC_HV_COUNT_MASK 0x3fffffff
+#define CRTC_STATUS_HV_COUNT__CRTC_HV_COUNT__SHIFT 0x0
+#define CRTC_COUNT_CONTROL__CRTC_HORZ_COUNT_BY2_EN_MASK 0x1
+#define CRTC_COUNT_CONTROL__CRTC_HORZ_COUNT_BY2_EN__SHIFT 0x0
+#define CRTC_COUNT_CONTROL__CRTC_HORZ_REPETITION_COUNT_MASK 0x1e
+#define CRTC_COUNT_CONTROL__CRTC_HORZ_REPETITION_COUNT__SHIFT 0x1
+#define CRTC_COUNT_RESET__CRTC_RESET_FRAME_COUNT_MASK 0x1
+#define CRTC_COUNT_RESET__CRTC_RESET_FRAME_COUNT__SHIFT 0x0
+#define CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE__CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE_MASK 0x1
+#define CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE__CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE__SHIFT 0x0
+#define CRTC_VERT_SYNC_CONTROL__CRTC_FORCE_VSYNC_NEXT_LINE_OCCURRED_MASK 0x1
+#define CRTC_VERT_SYNC_CONTROL__CRTC_FORCE_VSYNC_NEXT_LINE_OCCURRED__SHIFT 0x0
+#define CRTC_VERT_SYNC_CONTROL__CRTC_FORCE_VSYNC_NEXT_LINE_CLEAR_MASK 0x100
+#define CRTC_VERT_SYNC_CONTROL__CRTC_FORCE_VSYNC_NEXT_LINE_CLEAR__SHIFT 0x8
+#define CRTC_VERT_SYNC_CONTROL__CRTC_AUTO_FORCE_VSYNC_MODE_MASK 0x30000
+#define CRTC_VERT_SYNC_CONTROL__CRTC_AUTO_FORCE_VSYNC_MODE__SHIFT 0x10
+#define CRTC_STEREO_STATUS__CRTC_STEREO_CURRENT_EYE_MASK 0x1
+#define CRTC_STEREO_STATUS__CRTC_STEREO_CURRENT_EYE__SHIFT 0x0
+#define CRTC_STEREO_STATUS__CRTC_STEREO_SYNC_OUTPUT_MASK 0x100
+#define CRTC_STEREO_STATUS__CRTC_STEREO_SYNC_OUTPUT__SHIFT 0x8
+#define CRTC_STEREO_STATUS__CRTC_STEREO_SYNC_SELECT_MASK 0x10000
+#define CRTC_STEREO_STATUS__CRTC_STEREO_SYNC_SELECT__SHIFT 0x10
+#define CRTC_STEREO_STATUS__CRTC_STEREO_EYE_FLAG_MASK 0x100000
+#define CRTC_STEREO_STATUS__CRTC_STEREO_EYE_FLAG__SHIFT 0x14
+#define CRTC_STEREO_STATUS__CRTC_STEREO_FORCE_NEXT_EYE_PENDING_MASK 0x3000000
+#define CRTC_STEREO_STATUS__CRTC_STEREO_FORCE_NEXT_EYE_PENDING__SHIFT 0x18
+#define CRTC_STEREO_CONTROL__CRTC_STEREO_SYNC_OUTPUT_LINE_NUM_MASK 0x3fff
+#define CRTC_STEREO_CONTROL__CRTC_STEREO_SYNC_OUTPUT_LINE_NUM__SHIFT 0x0
+#define CRTC_STEREO_CONTROL__CRTC_STEREO_SYNC_OUTPUT_POLARITY_MASK 0x8000
+#define CRTC_STEREO_CONTROL__CRTC_STEREO_SYNC_OUTPUT_POLARITY__SHIFT 0xf
+#define CRTC_STEREO_CONTROL__CRTC_STEREO_SYNC_SELECT_POLARITY_MASK 0x10000
+#define CRTC_STEREO_CONTROL__CRTC_STEREO_SYNC_SELECT_POLARITY__SHIFT 0x10
+#define CRTC_STEREO_CONTROL__CRTC_STEREO_EYE_FLAG_POLARITY_MASK 0x20000
+#define CRTC_STEREO_CONTROL__CRTC_STEREO_EYE_FLAG_POLARITY__SHIFT 0x11
+#define CRTC_STEREO_CONTROL__CRTC_DISABLE_STEREOSYNC_OUTPUT_FOR_DP_MASK 0x40000
+#define CRTC_STEREO_CONTROL__CRTC_DISABLE_STEREOSYNC_OUTPUT_FOR_DP__SHIFT 0x12
+#define CRTC_STEREO_CONTROL__CRTC_DISABLE_FIELD_NUM_MASK 0x80000
+#define CRTC_STEREO_CONTROL__CRTC_DISABLE_FIELD_NUM__SHIFT 0x13
+#define CRTC_STEREO_CONTROL__CRTC_DISABLE_V_BLANK_FOR_DP_FIX_MASK 0x100000
+#define CRTC_STEREO_CONTROL__CRTC_DISABLE_V_BLANK_FOR_DP_FIX__SHIFT 0x14
+#define CRTC_STEREO_CONTROL__CRTC_STEREO_EN_MASK 0x1000000
+#define CRTC_STEREO_CONTROL__CRTC_STEREO_EN__SHIFT 0x18
+#define CRTC_SNAPSHOT_STATUS__CRTC_SNAPSHOT_OCCURRED_MASK 0x1
+#define CRTC_SNAPSHOT_STATUS__CRTC_SNAPSHOT_OCCURRED__SHIFT 0x0
+#define CRTC_SNAPSHOT_STATUS__CRTC_SNAPSHOT_CLEAR_MASK 0x2
+#define CRTC_SNAPSHOT_STATUS__CRTC_SNAPSHOT_CLEAR__SHIFT 0x1
+#define CRTC_SNAPSHOT_STATUS__CRTC_SNAPSHOT_MANUAL_TRIGGER_MASK 0x4
+#define CRTC_SNAPSHOT_STATUS__CRTC_SNAPSHOT_MANUAL_TRIGGER__SHIFT 0x2
+#define CRTC_SNAPSHOT_CONTROL__CRTC_AUTO_SNAPSHOT_TRIG_SEL_MASK 0x3
+#define CRTC_SNAPSHOT_CONTROL__CRTC_AUTO_SNAPSHOT_TRIG_SEL__SHIFT 0x0
+#define CRTC_SNAPSHOT_POSITION__CRTC_SNAPSHOT_VERT_COUNT_MASK 0x3fff
+#define CRTC_SNAPSHOT_POSITION__CRTC_SNAPSHOT_VERT_COUNT__SHIFT 0x0
+#define CRTC_SNAPSHOT_POSITION__CRTC_SNAPSHOT_HORZ_COUNT_MASK 0x3fff0000
+#define CRTC_SNAPSHOT_POSITION__CRTC_SNAPSHOT_HORZ_COUNT__SHIFT 0x10
+#define CRTC_SNAPSHOT_FRAME__CRTC_SNAPSHOT_FRAME_COUNT_MASK 0xffffff
+#define CRTC_SNAPSHOT_FRAME__CRTC_SNAPSHOT_FRAME_COUNT__SHIFT 0x0
+#define CRTC_START_LINE_CONTROL__CRTC_PROGRESSIVE_START_LINE_EARLY_MASK 0x1
+#define CRTC_START_LINE_CONTROL__CRTC_PROGRESSIVE_START_LINE_EARLY__SHIFT 0x0
+#define CRTC_START_LINE_CONTROL__CRTC_INTERLACE_START_LINE_EARLY_MASK 0x2
+#define CRTC_START_LINE_CONTROL__CRTC_INTERLACE_START_LINE_EARLY__SHIFT 0x1
+#define CRTC_START_LINE_CONTROL__CRTC_PREFETCH_EN_MASK 0x4
+#define CRTC_START_LINE_CONTROL__CRTC_PREFETCH_EN__SHIFT 0x2
+#define CRTC_START_LINE_CONTROL__CRTC_LEGACY_REQUESTOR_EN_MASK 0x100
+#define CRTC_START_LINE_CONTROL__CRTC_LEGACY_REQUESTOR_EN__SHIFT 0x8
+#define CRTC_START_LINE_CONTROL__CRTC_ADVANCED_START_LINE_POSITION_MASK 0xff000
+#define CRTC_START_LINE_CONTROL__CRTC_ADVANCED_START_LINE_POSITION__SHIFT 0xc
+#define CRTC_INTERRUPT_CONTROL__CRTC_SNAPSHOT_INT_MSK_MASK 0x1
+#define CRTC_INTERRUPT_CONTROL__CRTC_SNAPSHOT_INT_MSK__SHIFT 0x0
+#define CRTC_INTERRUPT_CONTROL__CRTC_SNAPSHOT_INT_TYPE_MASK 0x2
+#define CRTC_INTERRUPT_CONTROL__CRTC_SNAPSHOT_INT_TYPE__SHIFT 0x1
+#define CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK 0x10
+#define CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK__SHIFT 0x4
+#define CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_TYPE_MASK 0x20
+#define CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_TYPE__SHIFT 0x5
+#define CRTC_INTERRUPT_CONTROL__CRTC_FORCE_COUNT_NOW_INT_MSK_MASK 0x100
+#define CRTC_INTERRUPT_CONTROL__CRTC_FORCE_COUNT_NOW_INT_MSK__SHIFT 0x8
+#define CRTC_INTERRUPT_CONTROL__CRTC_FORCE_COUNT_NOW_INT_TYPE_MASK 0x200
+#define CRTC_INTERRUPT_CONTROL__CRTC_FORCE_COUNT_NOW_INT_TYPE__SHIFT 0x9
+#define CRTC_INTERRUPT_CONTROL__CRTC_FORCE_VSYNC_NEXT_LINE_INT_MSK_MASK 0x10000
+#define CRTC_INTERRUPT_CONTROL__CRTC_FORCE_VSYNC_NEXT_LINE_INT_MSK__SHIFT 0x10
+#define CRTC_INTERRUPT_CONTROL__CRTC_FORCE_VSYNC_NEXT_LINE_INT_TYPE_MASK 0x20000
+#define CRTC_INTERRUPT_CONTROL__CRTC_FORCE_VSYNC_NEXT_LINE_INT_TYPE__SHIFT 0x11
+#define CRTC_INTERRUPT_CONTROL__CRTC_TRIGA_INT_MSK_MASK 0x1000000
+#define CRTC_INTERRUPT_CONTROL__CRTC_TRIGA_INT_MSK__SHIFT 0x18
+#define CRTC_INTERRUPT_CONTROL__CRTC_TRIGB_INT_MSK_MASK 0x2000000
+#define CRTC_INTERRUPT_CONTROL__CRTC_TRIGB_INT_MSK__SHIFT 0x19
+#define CRTC_INTERRUPT_CONTROL__CRTC_TRIGA_INT_TYPE_MASK 0x4000000
+#define CRTC_INTERRUPT_CONTROL__CRTC_TRIGA_INT_TYPE__SHIFT 0x1a
+#define CRTC_INTERRUPT_CONTROL__CRTC_TRIGB_INT_TYPE_MASK 0x8000000
+#define CRTC_INTERRUPT_CONTROL__CRTC_TRIGB_INT_TYPE__SHIFT 0x1b
+#define CRTC_INTERRUPT_CONTROL__CRTC_VSYNC_NOM_INT_MSK_MASK 0x10000000
+#define CRTC_INTERRUPT_CONTROL__CRTC_VSYNC_NOM_INT_MSK__SHIFT 0x1c
+#define CRTC_INTERRUPT_CONTROL__CRTC_VSYNC_NOM_INT_TYPE_MASK 0x20000000
+#define CRTC_INTERRUPT_CONTROL__CRTC_VSYNC_NOM_INT_TYPE__SHIFT 0x1d
+#define CRTC_INTERRUPT_CONTROL__CRTC_GSL_VSYNC_GAP_INT_MSK_MASK 0x40000000
+#define CRTC_INTERRUPT_CONTROL__CRTC_GSL_VSYNC_GAP_INT_MSK__SHIFT 0x1e
+#define CRTC_INTERRUPT_CONTROL__CRTC_GSL_VSYNC_GAP_INT_TYPE_MASK 0x80000000
+#define CRTC_INTERRUPT_CONTROL__CRTC_GSL_VSYNC_GAP_INT_TYPE__SHIFT 0x1f
+#define CRTC_UPDATE_LOCK__CRTC_UPDATE_LOCK_MASK 0x1
+#define CRTC_UPDATE_LOCK__CRTC_UPDATE_LOCK__SHIFT 0x0
+#define CRTC_DOUBLE_BUFFER_CONTROL__CRTC_UPDATE_PENDING_MASK 0x1
+#define CRTC_DOUBLE_BUFFER_CONTROL__CRTC_UPDATE_PENDING__SHIFT 0x0
+#define CRTC_DOUBLE_BUFFER_CONTROL__CRTC_UPDATE_INSTANTLY_MASK 0x100
+#define CRTC_DOUBLE_BUFFER_CONTROL__CRTC_UPDATE_INSTANTLY__SHIFT 0x8
+#define CRTC_DOUBLE_BUFFER_CONTROL__CRTC_BLANK_DATA_DOUBLE_BUFFER_EN_MASK 0x10000
+#define CRTC_DOUBLE_BUFFER_CONTROL__CRTC_BLANK_DATA_DOUBLE_BUFFER_EN__SHIFT 0x10
+#define CRTC_VGA_PARAMETER_CAPTURE_MODE__CRTC_VGA_PARAMETER_CAPTURE_MODE_MASK 0x1
+#define CRTC_VGA_PARAMETER_CAPTURE_MODE__CRTC_VGA_PARAMETER_CAPTURE_MODE__SHIFT 0x0
+#define CRTC_TEST_PATTERN_CONTROL__CRTC_TEST_PATTERN_EN_MASK 0x1
+#define CRTC_TEST_PATTERN_CONTROL__CRTC_TEST_PATTERN_EN__SHIFT 0x0
+#define CRTC_TEST_PATTERN_CONTROL__CRTC_TEST_PATTERN_MODE_MASK 0x700
+#define CRTC_TEST_PATTERN_CONTROL__CRTC_TEST_PATTERN_MODE__SHIFT 0x8
+#define CRTC_TEST_PATTERN_CONTROL__CRTC_TEST_PATTERN_DYNAMIC_RANGE_MASK 0x10000
+#define CRTC_TEST_PATTERN_CONTROL__CRTC_TEST_PATTERN_DYNAMIC_RANGE__SHIFT 0x10
+#define CRTC_TEST_PATTERN_CONTROL__CRTC_TEST_PATTERN_COLOR_FORMAT_MASK 0xff000000
+#define CRTC_TEST_PATTERN_CONTROL__CRTC_TEST_PATTERN_COLOR_FORMAT__SHIFT 0x18
+#define CRTC_TEST_PATTERN_PARAMETERS__CRTC_TEST_PATTERN_INC0_MASK 0xf
+#define CRTC_TEST_PATTERN_PARAMETERS__CRTC_TEST_PATTERN_INC0__SHIFT 0x0
+#define CRTC_TEST_PATTERN_PARAMETERS__CRTC_TEST_PATTERN_INC1_MASK 0xf0
+#define CRTC_TEST_PATTERN_PARAMETERS__CRTC_TEST_PATTERN_INC1__SHIFT 0x4
+#define CRTC_TEST_PATTERN_PARAMETERS__CRTC_TEST_PATTERN_VRES_MASK 0xf00
+#define CRTC_TEST_PATTERN_PARAMETERS__CRTC_TEST_PATTERN_VRES__SHIFT 0x8
+#define CRTC_TEST_PATTERN_PARAMETERS__CRTC_TEST_PATTERN_HRES_MASK 0xf000
+#define CRTC_TEST_PATTERN_PARAMETERS__CRTC_TEST_PATTERN_HRES__SHIFT 0xc
+#define CRTC_TEST_PATTERN_PARAMETERS__CRTC_TEST_PATTERN_RAMP0_OFFSET_MASK 0xffff0000
+#define CRTC_TEST_PATTERN_PARAMETERS__CRTC_TEST_PATTERN_RAMP0_OFFSET__SHIFT 0x10
+#define CRTC_TEST_PATTERN_COLOR__CRTC_TEST_PATTERN_DATA_MASK 0xffff
+#define CRTC_TEST_PATTERN_COLOR__CRTC_TEST_PATTERN_DATA__SHIFT 0x0
+#define CRTC_TEST_PATTERN_COLOR__CRTC_TEST_PATTERN_MASK_MASK 0x3f0000
+#define CRTC_TEST_PATTERN_COLOR__CRTC_TEST_PATTERN_MASK__SHIFT 0x10
+#define CRTC_MASTER_UPDATE_LOCK__MASTER_UPDATE_LOCK_MASK 0x1
+#define CRTC_MASTER_UPDATE_LOCK__MASTER_UPDATE_LOCK__SHIFT 0x0
+#define CRTC_MASTER_UPDATE_LOCK__GSL_CONTROL_MASTER_UPDATE_LOCK_MASK 0x100
+#define CRTC_MASTER_UPDATE_LOCK__GSL_CONTROL_MASTER_UPDATE_LOCK__SHIFT 0x8
+#define CRTC_MASTER_UPDATE_LOCK__UNDERFLOW_UPDATE_LOCK_MASK 0x10000
+#define CRTC_MASTER_UPDATE_LOCK__UNDERFLOW_UPDATE_LOCK__SHIFT 0x10
+#define CRTC_MASTER_UPDATE_MODE__MASTER_UPDATE_MODE_MASK 0x7
+#define CRTC_MASTER_UPDATE_MODE__MASTER_UPDATE_MODE__SHIFT 0x0
+#define CRTC_MASTER_UPDATE_MODE__MASTER_UPDATE_INTERLACED_MODE_MASK 0x30000
+#define CRTC_MASTER_UPDATE_MODE__MASTER_UPDATE_INTERLACED_MODE__SHIFT 0x10
+#define CRTC_MVP_INBAND_CNTL_INSERT__CRTC_MVP_INBAND_OUT_MODE_MASK 0x3
+#define CRTC_MVP_INBAND_CNTL_INSERT__CRTC_MVP_INBAND_OUT_MODE__SHIFT 0x0
+#define CRTC_MVP_INBAND_CNTL_INSERT__CRTC_MVP_INBAND_CNTL_CHAR_INSERT_MASK 0xffffff00
+#define CRTC_MVP_INBAND_CNTL_INSERT__CRTC_MVP_INBAND_CNTL_CHAR_INSERT__SHIFT 0x8
+#define CRTC_MVP_INBAND_CNTL_INSERT_TIMER__CRTC_MVP_INBAND_CNTL_CHAR_INSERT_TIMER_MASK 0xff
+#define CRTC_MVP_INBAND_CNTL_INSERT_TIMER__CRTC_MVP_INBAND_CNTL_CHAR_INSERT_TIMER__SHIFT 0x0
+#define CRTC_MVP_STATUS__CRTC_FLIP_NOW_OCCURRED_MASK 0x1
+#define CRTC_MVP_STATUS__CRTC_FLIP_NOW_OCCURRED__SHIFT 0x0
+#define CRTC_MVP_STATUS__CRTC_AFR_HSYNC_SWITCH_DONE_OCCURRED_MASK 0x10
+#define CRTC_MVP_STATUS__CRTC_AFR_HSYNC_SWITCH_DONE_OCCURRED__SHIFT 0x4
+#define CRTC_MVP_STATUS__CRTC_FLIP_NOW_CLEAR_MASK 0x10000
+#define CRTC_MVP_STATUS__CRTC_FLIP_NOW_CLEAR__SHIFT 0x10
+#define CRTC_MVP_STATUS__CRTC_AFR_HSYNC_SWITCH_DONE_CLEAR_MASK 0x100000
+#define CRTC_MVP_STATUS__CRTC_AFR_HSYNC_SWITCH_DONE_CLEAR__SHIFT 0x14
+#define CRTC_MASTER_EN__CRTC_MASTER_EN_MASK 0x1
+#define CRTC_MASTER_EN__CRTC_MASTER_EN__SHIFT 0x0
+#define CRTC_ALLOW_STOP_OFF_V_CNT__CRTC_ALLOW_STOP_OFF_V_CNT_MASK 0xff
+#define CRTC_ALLOW_STOP_OFF_V_CNT__CRTC_ALLOW_STOP_OFF_V_CNT__SHIFT 0x0
+#define CRTC_ALLOW_STOP_OFF_V_CNT__CRTC_DISABLE_ALLOW_STOP_OFF_V_CNT_MASK 0x10000
+#define CRTC_ALLOW_STOP_OFF_V_CNT__CRTC_DISABLE_ALLOW_STOP_OFF_V_CNT__SHIFT 0x10
+#define CRTC_V_UPDATE_INT_STATUS__CRTC_V_UPDATE_INT_OCCURRED_MASK 0x1
+#define CRTC_V_UPDATE_INT_STATUS__CRTC_V_UPDATE_INT_OCCURRED__SHIFT 0x0
+#define CRTC_V_UPDATE_INT_STATUS__CRTC_V_UPDATE_INT_CLEAR_MASK 0x100
+#define CRTC_V_UPDATE_INT_STATUS__CRTC_V_UPDATE_INT_CLEAR__SHIFT 0x8
+#define CRTC_OVERSCAN_COLOR__CRTC_OVERSCAN_COLOR_BLUE_MASK 0x3ff
+#define CRTC_OVERSCAN_COLOR__CRTC_OVERSCAN_COLOR_BLUE__SHIFT 0x0
+#define CRTC_OVERSCAN_COLOR__CRTC_OVERSCAN_COLOR_GREEN_MASK 0xffc00
+#define CRTC_OVERSCAN_COLOR__CRTC_OVERSCAN_COLOR_GREEN__SHIFT 0xa
+#define CRTC_OVERSCAN_COLOR__CRTC_OVERSCAN_COLOR_RED_MASK 0x3ff00000
+#define CRTC_OVERSCAN_COLOR__CRTC_OVERSCAN_COLOR_RED__SHIFT 0x14
+#define CRTC_OVERSCAN_COLOR_EXT__CRTC_OVERSCAN_COLOR_BLUE_EXT_MASK 0x3
+#define CRTC_OVERSCAN_COLOR_EXT__CRTC_OVERSCAN_COLOR_BLUE_EXT__SHIFT 0x0
+#define CRTC_OVERSCAN_COLOR_EXT__CRTC_OVERSCAN_COLOR_GREEN_EXT_MASK 0x300
+#define CRTC_OVERSCAN_COLOR_EXT__CRTC_OVERSCAN_COLOR_GREEN_EXT__SHIFT 0x8
+#define CRTC_OVERSCAN_COLOR_EXT__CRTC_OVERSCAN_COLOR_RED_EXT_MASK 0x30000
+#define CRTC_OVERSCAN_COLOR_EXT__CRTC_OVERSCAN_COLOR_RED_EXT__SHIFT 0x10
+#define CRTC_BLANK_DATA_COLOR__CRTC_BLANK_DATA_COLOR_BLUE_CB_MASK 0x3ff
+#define CRTC_BLANK_DATA_COLOR__CRTC_BLANK_DATA_COLOR_BLUE_CB__SHIFT 0x0
+#define CRTC_BLANK_DATA_COLOR__CRTC_BLANK_DATA_COLOR_GREEN_Y_MASK 0xffc00
+#define CRTC_BLANK_DATA_COLOR__CRTC_BLANK_DATA_COLOR_GREEN_Y__SHIFT 0xa
+#define CRTC_BLANK_DATA_COLOR__CRTC_BLANK_DATA_COLOR_RED_CR_MASK 0x3ff00000
+#define CRTC_BLANK_DATA_COLOR__CRTC_BLANK_DATA_COLOR_RED_CR__SHIFT 0x14
+#define CRTC_BLANK_DATA_COLOR_EXT__CRTC_BLANK_DATA_COLOR_BLUE_CB_EXT_MASK 0x3
+#define CRTC_BLANK_DATA_COLOR_EXT__CRTC_BLANK_DATA_COLOR_BLUE_CB_EXT__SHIFT 0x0
+#define CRTC_BLANK_DATA_COLOR_EXT__CRTC_BLANK_DATA_COLOR_GREEN_Y_EXT_MASK 0x300
+#define CRTC_BLANK_DATA_COLOR_EXT__CRTC_BLANK_DATA_COLOR_GREEN_Y_EXT__SHIFT 0x8
+#define CRTC_BLANK_DATA_COLOR_EXT__CRTC_BLANK_DATA_COLOR_RED_CR_EXT_MASK 0x30000
+#define CRTC_BLANK_DATA_COLOR_EXT__CRTC_BLANK_DATA_COLOR_RED_CR_EXT__SHIFT 0x10
+#define CRTC_BLACK_COLOR__CRTC_BLACK_COLOR_B_CB_MASK 0x3ff
+#define CRTC_BLACK_COLOR__CRTC_BLACK_COLOR_B_CB__SHIFT 0x0
+#define CRTC_BLACK_COLOR__CRTC_BLACK_COLOR_G_Y_MASK 0xffc00
+#define CRTC_BLACK_COLOR__CRTC_BLACK_COLOR_G_Y__SHIFT 0xa
+#define CRTC_BLACK_COLOR__CRTC_BLACK_COLOR_R_CR_MASK 0x3ff00000
+#define CRTC_BLACK_COLOR__CRTC_BLACK_COLOR_R_CR__SHIFT 0x14
+#define CRTC_BLACK_COLOR_EXT__CRTC_BLACK_COLOR_B_CB_EXT_MASK 0x3
+#define CRTC_BLACK_COLOR_EXT__CRTC_BLACK_COLOR_B_CB_EXT__SHIFT 0x0
+#define CRTC_BLACK_COLOR_EXT__CRTC_BLACK_COLOR_G_Y_EXT_MASK 0x300
+#define CRTC_BLACK_COLOR_EXT__CRTC_BLACK_COLOR_G_Y_EXT__SHIFT 0x8
+#define CRTC_BLACK_COLOR_EXT__CRTC_BLACK_COLOR_R_CR_EXT_MASK 0x30000
+#define CRTC_BLACK_COLOR_EXT__CRTC_BLACK_COLOR_R_CR_EXT__SHIFT 0x10
+#define CRTC_VERTICAL_INTERRUPT0_POSITION__CRTC_VERTICAL_INTERRUPT0_LINE_START_MASK 0x3fff
+#define CRTC_VERTICAL_INTERRUPT0_POSITION__CRTC_VERTICAL_INTERRUPT0_LINE_START__SHIFT 0x0
+#define CRTC_VERTICAL_INTERRUPT0_POSITION__CRTC_VERTICAL_INTERRUPT0_LINE_END_MASK 0x3fff0000
+#define CRTC_VERTICAL_INTERRUPT0_POSITION__CRTC_VERTICAL_INTERRUPT0_LINE_END__SHIFT 0x10
+#define CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_OUTPUT_POLARITY_MASK 0x10
+#define CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_OUTPUT_POLARITY__SHIFT 0x4
+#define CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK 0x100
+#define CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE__SHIFT 0x8
+#define CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_STATUS_MASK 0x1000
+#define CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_STATUS__SHIFT 0xc
+#define CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_STATUS_MASK 0x10000
+#define CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_STATUS__SHIFT 0x10
+#define CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_CLEAR_MASK 0x100000
+#define CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_CLEAR__SHIFT 0x14
+#define CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_TYPE_MASK 0x1000000
+#define CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_TYPE__SHIFT 0x18
+#define CRTC_VERTICAL_INTERRUPT1_POSITION__CRTC_VERTICAL_INTERRUPT1_LINE_START_MASK 0x3fff
+#define CRTC_VERTICAL_INTERRUPT1_POSITION__CRTC_VERTICAL_INTERRUPT1_LINE_START__SHIFT 0x0
+#define CRTC_VERTICAL_INTERRUPT1_CONTROL__CRTC_VERTICAL_INTERRUPT1_INT_ENABLE_MASK 0x100
+#define CRTC_VERTICAL_INTERRUPT1_CONTROL__CRTC_VERTICAL_INTERRUPT1_INT_ENABLE__SHIFT 0x8
+#define CRTC_VERTICAL_INTERRUPT1_CONTROL__CRTC_VERTICAL_INTERRUPT1_STATUS_MASK 0x1000
+#define CRTC_VERTICAL_INTERRUPT1_CONTROL__CRTC_VERTICAL_INTERRUPT1_STATUS__SHIFT 0xc
+#define CRTC_VERTICAL_INTERRUPT1_CONTROL__CRTC_VERTICAL_INTERRUPT1_INT_STATUS_MASK 0x10000
+#define CRTC_VERTICAL_INTERRUPT1_CONTROL__CRTC_VERTICAL_INTERRUPT1_INT_STATUS__SHIFT 0x10
+#define CRTC_VERTICAL_INTERRUPT1_CONTROL__CRTC_VERTICAL_INTERRUPT1_CLEAR_MASK 0x100000
+#define CRTC_VERTICAL_INTERRUPT1_CONTROL__CRTC_VERTICAL_INTERRUPT1_CLEAR__SHIFT 0x14
+#define CRTC_VERTICAL_INTERRUPT1_CONTROL__CRTC_VERTICAL_INTERRUPT1_INT_TYPE_MASK 0x1000000
+#define CRTC_VERTICAL_INTERRUPT1_CONTROL__CRTC_VERTICAL_INTERRUPT1_INT_TYPE__SHIFT 0x18
+#define CRTC_VERTICAL_INTERRUPT2_POSITION__CRTC_VERTICAL_INTERRUPT2_LINE_START_MASK 0x3fff
+#define CRTC_VERTICAL_INTERRUPT2_POSITION__CRTC_VERTICAL_INTERRUPT2_LINE_START__SHIFT 0x0
+#define CRTC_VERTICAL_INTERRUPT2_CONTROL__CRTC_VERTICAL_INTERRUPT2_INT_ENABLE_MASK 0x100
+#define CRTC_VERTICAL_INTERRUPT2_CONTROL__CRTC_VERTICAL_INTERRUPT2_INT_ENABLE__SHIFT 0x8
+#define CRTC_VERTICAL_INTERRUPT2_CONTROL__CRTC_VERTICAL_INTERRUPT2_STATUS_MASK 0x1000
+#define CRTC_VERTICAL_INTERRUPT2_CONTROL__CRTC_VERTICAL_INTERRUPT2_STATUS__SHIFT 0xc
+#define CRTC_VERTICAL_INTERRUPT2_CONTROL__CRTC_VERTICAL_INTERRUPT2_INT_STATUS_MASK 0x10000
+#define CRTC_VERTICAL_INTERRUPT2_CONTROL__CRTC_VERTICAL_INTERRUPT2_INT_STATUS__SHIFT 0x10
+#define CRTC_VERTICAL_INTERRUPT2_CONTROL__CRTC_VERTICAL_INTERRUPT2_CLEAR_MASK 0x100000
+#define CRTC_VERTICAL_INTERRUPT2_CONTROL__CRTC_VERTICAL_INTERRUPT2_CLEAR__SHIFT 0x14
+#define CRTC_VERTICAL_INTERRUPT2_CONTROL__CRTC_VERTICAL_INTERRUPT2_INT_TYPE_MASK 0x1000000
+#define CRTC_VERTICAL_INTERRUPT2_CONTROL__CRTC_VERTICAL_INTERRUPT2_INT_TYPE__SHIFT 0x18
+#define CRTC_CRC_CNTL__CRTC_CRC_EN_MASK 0x1
+#define CRTC_CRC_CNTL__CRTC_CRC_EN__SHIFT 0x0
+#define CRTC_CRC_CNTL__CRTC_CRC_CONT_EN_MASK 0x10
+#define CRTC_CRC_CNTL__CRTC_CRC_CONT_EN__SHIFT 0x4
+#define CRTC_CRC_CNTL__CRTC_CRC_STEREO_MODE_MASK 0x300
+#define CRTC_CRC_CNTL__CRTC_CRC_STEREO_MODE__SHIFT 0x8
+#define CRTC_CRC_CNTL__CRTC_CRC_INTERLACE_MODE_MASK 0x3000
+#define CRTC_CRC_CNTL__CRTC_CRC_INTERLACE_MODE__SHIFT 0xc
+#define CRTC_CRC_CNTL__CRTC_CRC_USE_NEW_AND_REPEATED_PIXELS_MASK 0x10000
+#define CRTC_CRC_CNTL__CRTC_CRC_USE_NEW_AND_REPEATED_PIXELS__SHIFT 0x10
+#define CRTC_CRC_CNTL__CRTC_CRC0_SELECT_MASK 0x700000
+#define CRTC_CRC_CNTL__CRTC_CRC0_SELECT__SHIFT 0x14
+#define CRTC_CRC_CNTL__CRTC_CRC1_SELECT_MASK 0x7000000
+#define CRTC_CRC_CNTL__CRTC_CRC1_SELECT__SHIFT 0x18
+#define CRTC_CRC0_WINDOWA_X_CONTROL__CRTC_CRC0_WINDOWA_X_START_MASK 0x3fff
+#define CRTC_CRC0_WINDOWA_X_CONTROL__CRTC_CRC0_WINDOWA_X_START__SHIFT 0x0
+#define CRTC_CRC0_WINDOWA_X_CONTROL__CRTC_CRC0_WINDOWA_X_END_MASK 0x3fff0000
+#define CRTC_CRC0_WINDOWA_X_CONTROL__CRTC_CRC0_WINDOWA_X_END__SHIFT 0x10
+#define CRTC_CRC0_WINDOWA_Y_CONTROL__CRTC_CRC0_WINDOWA_Y_START_MASK 0x3fff
+#define CRTC_CRC0_WINDOWA_Y_CONTROL__CRTC_CRC0_WINDOWA_Y_START__SHIFT 0x0
+#define CRTC_CRC0_WINDOWA_Y_CONTROL__CRTC_CRC0_WINDOWA_Y_END_MASK 0x3fff0000
+#define CRTC_CRC0_WINDOWA_Y_CONTROL__CRTC_CRC0_WINDOWA_Y_END__SHIFT 0x10
+#define CRTC_CRC0_WINDOWB_X_CONTROL__CRTC_CRC0_WINDOWB_X_START_MASK 0x3fff
+#define CRTC_CRC0_WINDOWB_X_CONTROL__CRTC_CRC0_WINDOWB_X_START__SHIFT 0x0
+#define CRTC_CRC0_WINDOWB_X_CONTROL__CRTC_CRC0_WINDOWB_X_END_MASK 0x3fff0000
+#define CRTC_CRC0_WINDOWB_X_CONTROL__CRTC_CRC0_WINDOWB_X_END__SHIFT 0x10
+#define CRTC_CRC0_WINDOWB_Y_CONTROL__CRTC_CRC0_WINDOWB_Y_START_MASK 0x3fff
+#define CRTC_CRC0_WINDOWB_Y_CONTROL__CRTC_CRC0_WINDOWB_Y_START__SHIFT 0x0
+#define CRTC_CRC0_WINDOWB_Y_CONTROL__CRTC_CRC0_WINDOWB_Y_END_MASK 0x3fff0000
+#define CRTC_CRC0_WINDOWB_Y_CONTROL__CRTC_CRC0_WINDOWB_Y_END__SHIFT 0x10
+#define CRTC_CRC0_DATA_RG__CRC0_R_CR_MASK 0xffff
+#define CRTC_CRC0_DATA_RG__CRC0_R_CR__SHIFT 0x0
+#define CRTC_CRC0_DATA_RG__CRC0_G_Y_MASK 0xffff0000
+#define CRTC_CRC0_DATA_RG__CRC0_G_Y__SHIFT 0x10
+#define CRTC_CRC0_DATA_B__CRC0_B_CB_MASK 0xffff
+#define CRTC_CRC0_DATA_B__CRC0_B_CB__SHIFT 0x0
+#define CRTC_CRC1_WINDOWA_X_CONTROL__CRTC_CRC1_WINDOWA_X_START_MASK 0x3fff
+#define CRTC_CRC1_WINDOWA_X_CONTROL__CRTC_CRC1_WINDOWA_X_START__SHIFT 0x0
+#define CRTC_CRC1_WINDOWA_X_CONTROL__CRTC_CRC1_WINDOWA_X_END_MASK 0x3fff0000
+#define CRTC_CRC1_WINDOWA_X_CONTROL__CRTC_CRC1_WINDOWA_X_END__SHIFT 0x10
+#define CRTC_CRC1_WINDOWA_Y_CONTROL__CRTC_CRC1_WINDOWA_Y_START_MASK 0x3fff
+#define CRTC_CRC1_WINDOWA_Y_CONTROL__CRTC_CRC1_WINDOWA_Y_START__SHIFT 0x0
+#define CRTC_CRC1_WINDOWA_Y_CONTROL__CRTC_CRC1_WINDOWA_Y_END_MASK 0x3fff0000
+#define CRTC_CRC1_WINDOWA_Y_CONTROL__CRTC_CRC1_WINDOWA_Y_END__SHIFT 0x10
+#define CRTC_CRC1_WINDOWB_X_CONTROL__CRTC_CRC1_WINDOWB_X_START_MASK 0x3fff
+#define CRTC_CRC1_WINDOWB_X_CONTROL__CRTC_CRC1_WINDOWB_X_START__SHIFT 0x0
+#define CRTC_CRC1_WINDOWB_X_CONTROL__CRTC_CRC1_WINDOWB_X_END_MASK 0x3fff0000
+#define CRTC_CRC1_WINDOWB_X_CONTROL__CRTC_CRC1_WINDOWB_X_END__SHIFT 0x10
+#define CRTC_CRC1_WINDOWB_Y_CONTROL__CRTC_CRC1_WINDOWB_Y_START_MASK 0x3fff
+#define CRTC_CRC1_WINDOWB_Y_CONTROL__CRTC_CRC1_WINDOWB_Y_START__SHIFT 0x0
+#define CRTC_CRC1_WINDOWB_Y_CONTROL__CRTC_CRC1_WINDOWB_Y_END_MASK 0x3fff0000
+#define CRTC_CRC1_WINDOWB_Y_CONTROL__CRTC_CRC1_WINDOWB_Y_END__SHIFT 0x10
+#define CRTC_CRC1_DATA_RG__CRC1_R_CR_MASK 0xffff
+#define CRTC_CRC1_DATA_RG__CRC1_R_CR__SHIFT 0x0
+#define CRTC_CRC1_DATA_RG__CRC1_G_Y_MASK 0xffff0000
+#define CRTC_CRC1_DATA_RG__CRC1_G_Y__SHIFT 0x10
+#define CRTC_CRC1_DATA_B__CRC1_B_CB_MASK 0xffff
+#define CRTC_CRC1_DATA_B__CRC1_B_CB__SHIFT 0x0
+#define CRTC_EXT_TIMING_SYNC_CONTROL__CRTC_EXT_TIMING_SYNC_ENABLE_MASK 0x3
+#define CRTC_EXT_TIMING_SYNC_CONTROL__CRTC_EXT_TIMING_SYNC_ENABLE__SHIFT 0x0
+#define CRTC_EXT_TIMING_SYNC_CONTROL__CRTC_EXT_TIMING_SYNC_HCOUNT_MODE_ENABLE_MASK 0x8
+#define CRTC_EXT_TIMING_SYNC_CONTROL__CRTC_EXT_TIMING_SYNC_HCOUNT_MODE_ENABLE__SHIFT 0x3
+#define CRTC_EXT_TIMING_SYNC_CONTROL__CRTC_EXT_TIMING_SYNC_JITTER_FILTERING_ENABLE_MASK 0x10
+#define CRTC_EXT_TIMING_SYNC_CONTROL__CRTC_EXT_TIMING_SYNC_JITTER_FILTERING_ENABLE__SHIFT 0x4
+#define CRTC_EXT_TIMING_SYNC_CONTROL__CRTC_EXT_TIMING_SYNC_JITTER_FILTERING_WINDOW_MASK 0x60
+#define CRTC_EXT_TIMING_SYNC_CONTROL__CRTC_EXT_TIMING_SYNC_JITTER_FILTERING_WINDOW__SHIFT 0x5
+#define CRTC_EXT_TIMING_SYNC_CONTROL__CRTC_EXT_TIMING_SYNC_WINDOW_ENABLE_MASK 0x100
+#define CRTC_EXT_TIMING_SYNC_CONTROL__CRTC_EXT_TIMING_SYNC_WINDOW_ENABLE__SHIFT 0x8
+#define CRTC_EXT_TIMING_SYNC_CONTROL__CRTC_EXT_TIMING_SYNC_WINDOW_UPDATE_MASK 0x200
+#define CRTC_EXT_TIMING_SYNC_CONTROL__CRTC_EXT_TIMING_SYNC_WINDOW_UPDATE__SHIFT 0x9
+#define CRTC_EXT_TIMING_SYNC_CONTROL__CRTC_EXT_TIMING_SYNC_VSYNC_POLARITY_MASK 0x1000
+#define CRTC_EXT_TIMING_SYNC_CONTROL__CRTC_EXT_TIMING_SYNC_VSYNC_POLARITY__SHIFT 0xc
+#define CRTC_EXT_TIMING_SYNC_CONTROL__CRTC_EXT_TIMING_SYNC_HSYNC_POLARITY_MASK 0x2000
+#define CRTC_EXT_TIMING_SYNC_CONTROL__CRTC_EXT_TIMING_SYNC_HSYNC_POLARITY__SHIFT 0xd
+#define CRTC_EXT_TIMING_SYNC_CONTROL__CRTC_EXT_TIMING_SYNC_INTERLACE_MODE_MASK 0x4000
+#define CRTC_EXT_TIMING_SYNC_CONTROL__CRTC_EXT_TIMING_SYNC_INTERLACE_MODE__SHIFT 0xe
+#define CRTC_EXT_TIMING_SYNC_CONTROL__CRTC_EXT_TIMING_SYNC_MASTER_FRAME_RATE_MASK 0x7000000
+#define CRTC_EXT_TIMING_SYNC_CONTROL__CRTC_EXT_TIMING_SYNC_MASTER_FRAME_RATE__SHIFT 0x18
+#define CRTC_EXT_TIMING_SYNC_CONTROL__CRTC_EXT_TIMING_SYNC_SLAVE_FRAME_RATE_MASK 0x70000000
+#define CRTC_EXT_TIMING_SYNC_CONTROL__CRTC_EXT_TIMING_SYNC_SLAVE_FRAME_RATE__SHIFT 0x1c
+#define CRTC_EXT_TIMING_SYNC_WINDOW_START__CRTC_EXT_TIMING_SYNC_WINDOW_START_X_MASK 0x3fff
+#define CRTC_EXT_TIMING_SYNC_WINDOW_START__CRTC_EXT_TIMING_SYNC_WINDOW_START_X__SHIFT 0x0
+#define CRTC_EXT_TIMING_SYNC_WINDOW_START__CRTC_EXT_TIMING_SYNC_WINDOW_START_Y_MASK 0x3fff0000
+#define CRTC_EXT_TIMING_SYNC_WINDOW_START__CRTC_EXT_TIMING_SYNC_WINDOW_START_Y__SHIFT 0x10
+#define CRTC_EXT_TIMING_SYNC_WINDOW_END__CRTC_EXT_TIMING_SYNC_WINDOW_END_X_MASK 0x3fff
+#define CRTC_EXT_TIMING_SYNC_WINDOW_END__CRTC_EXT_TIMING_SYNC_WINDOW_END_X__SHIFT 0x0
+#define CRTC_EXT_TIMING_SYNC_WINDOW_END__CRTC_EXT_TIMING_SYNC_WINDOW_END_Y_MASK 0x3fff0000
+#define CRTC_EXT_TIMING_SYNC_WINDOW_END__CRTC_EXT_TIMING_SYNC_WINDOW_END_Y__SHIFT 0x10
+#define CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL__CRTC_EXT_TIMING_SYNC_LOSS_INT_ENABLE_MASK 0x1
+#define CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL__CRTC_EXT_TIMING_SYNC_LOSS_INT_ENABLE__SHIFT 0x0
+#define CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL__CRTC_EXT_TIMING_SYNC_LOSS_STATUS_MASK 0x10
+#define CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL__CRTC_EXT_TIMING_SYNC_LOSS_STATUS__SHIFT 0x4
+#define CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL__CRTC_EXT_TIMING_SYNC_LOSS_INT_STATUS_MASK 0x100
+#define CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL__CRTC_EXT_TIMING_SYNC_LOSS_INT_STATUS__SHIFT 0x8
+#define CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL__CRTC_EXT_TIMING_SYNC_LOSS_CLEAR_MASK 0x10000
+#define CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL__CRTC_EXT_TIMING_SYNC_LOSS_CLEAR__SHIFT 0x10
+#define CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL__CRTC_EXT_TIMING_SYNC_LOSS_INT_TYPE_MASK 0x100000
+#define CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL__CRTC_EXT_TIMING_SYNC_LOSS_INT_TYPE__SHIFT 0x14
+#define CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL__CRTC_EXT_TIMING_SYNC_LOSS_FRAME_COUNT_MASK 0xe0000000
+#define CRTC_EXT_TIMING_SYNC_LOSS_INTERRUPT_CONTROL__CRTC_EXT_TIMING_SYNC_LOSS_FRAME_COUNT__SHIFT 0x1d
+#define CRTC_EXT_TIMING_SYNC_INTERRUPT_CONTROL__CRTC_EXT_TIMING_SYNC_INT_ENABLE_MASK 0x1
+#define CRTC_EXT_TIMING_SYNC_INTERRUPT_CONTROL__CRTC_EXT_TIMING_SYNC_INT_ENABLE__SHIFT 0x0
+#define CRTC_EXT_TIMING_SYNC_INTERRUPT_CONTROL__CRTC_EXT_TIMING_SYNC_STATUS_MASK 0x10
+#define CRTC_EXT_TIMING_SYNC_INTERRUPT_CONTROL__CRTC_EXT_TIMING_SYNC_STATUS__SHIFT 0x4
+#define CRTC_EXT_TIMING_SYNC_INTERRUPT_CONTROL__CRTC_EXT_TIMING_SYNC_INT_STATUS_MASK 0x100
+#define CRTC_EXT_TIMING_SYNC_INTERRUPT_CONTROL__CRTC_EXT_TIMING_SYNC_INT_STATUS__SHIFT 0x8
+#define CRTC_EXT_TIMING_SYNC_INTERRUPT_CONTROL__CRTC_EXT_TIMING_SYNC_CLEAR_MASK 0x10000
+#define CRTC_EXT_TIMING_SYNC_INTERRUPT_CONTROL__CRTC_EXT_TIMING_SYNC_CLEAR__SHIFT 0x10
+#define CRTC_EXT_TIMING_SYNC_INTERRUPT_CONTROL__CRTC_EXT_TIMING_SYNC_INT_TYPE_MASK 0x100000
+#define CRTC_EXT_TIMING_SYNC_INTERRUPT_CONTROL__CRTC_EXT_TIMING_SYNC_INT_TYPE__SHIFT 0x14
+#define CRTC_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_CONTROL__CRTC_EXT_TIMING_SYNC_SIGNAL_INT_ENABLE_MASK 0x1
+#define CRTC_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_CONTROL__CRTC_EXT_TIMING_SYNC_SIGNAL_INT_ENABLE__SHIFT 0x0
+#define CRTC_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_CONTROL__CRTC_EXT_TIMING_SYNC_SIGNAL_STATUS_MASK 0x10
+#define CRTC_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_CONTROL__CRTC_EXT_TIMING_SYNC_SIGNAL_STATUS__SHIFT 0x4
+#define CRTC_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_CONTROL__CRTC_EXT_TIMING_SYNC_SIGNAL_INT_STATUS_MASK 0x100
+#define CRTC_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_CONTROL__CRTC_EXT_TIMING_SYNC_SIGNAL_INT_STATUS__SHIFT 0x8
+#define CRTC_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_CONTROL__CRTC_EXT_TIMING_SYNC_SIGNAL_CLEAR_MASK 0x10000
+#define CRTC_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_CONTROL__CRTC_EXT_TIMING_SYNC_SIGNAL_CLEAR__SHIFT 0x10
+#define CRTC_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_CONTROL__CRTC_EXT_TIMING_SYNC_SIGNAL_INT_TYPE_MASK 0x100000
+#define CRTC_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_CONTROL__CRTC_EXT_TIMING_SYNC_SIGNAL_INT_TYPE__SHIFT 0x14
+#define CRTC_STATIC_SCREEN_CONTROL__CRTC_STATIC_SCREEN_EVENT_MASK_MASK 0xffff
+#define CRTC_STATIC_SCREEN_CONTROL__CRTC_STATIC_SCREEN_EVENT_MASK__SHIFT 0x0
+#define CRTC_STATIC_SCREEN_CONTROL__CRTC_STATIC_SCREEN_FRAME_COUNT_MASK 0xff0000
+#define CRTC_STATIC_SCREEN_CONTROL__CRTC_STATIC_SCREEN_FRAME_COUNT__SHIFT 0x10
+#define CRTC_STATIC_SCREEN_CONTROL__CRTC_CPU_SS_INT_ENABLE_MASK 0x1000000
+#define CRTC_STATIC_SCREEN_CONTROL__CRTC_CPU_SS_INT_ENABLE__SHIFT 0x18
+#define CRTC_STATIC_SCREEN_CONTROL__CRTC_SS_STATUS_MASK 0x2000000
+#define CRTC_STATIC_SCREEN_CONTROL__CRTC_SS_STATUS__SHIFT 0x19
+#define CRTC_STATIC_SCREEN_CONTROL__CRTC_CPU_SS_INT_STATUS_MASK 0x4000000
+#define CRTC_STATIC_SCREEN_CONTROL__CRTC_CPU_SS_INT_STATUS__SHIFT 0x1a
+#define CRTC_STATIC_SCREEN_CONTROL__CRTC_CPU_SS_INT_CLEAR_MASK 0x8000000
+#define CRTC_STATIC_SCREEN_CONTROL__CRTC_CPU_SS_INT_CLEAR__SHIFT 0x1b
+#define CRTC_STATIC_SCREEN_CONTROL__CRTC_CPU_SS_INT_TYPE_MASK 0x10000000
+#define CRTC_STATIC_SCREEN_CONTROL__CRTC_CPU_SS_INT_TYPE__SHIFT 0x1c
+#define CRTC_STATIC_SCREEN_CONTROL__CRTC_STATIC_SCREEN_OVERRIDE_MASK 0x40000000
+#define CRTC_STATIC_SCREEN_CONTROL__CRTC_STATIC_SCREEN_OVERRIDE__SHIFT 0x1e
+#define CRTC_STATIC_SCREEN_CONTROL__CRTC_STATIC_SCREEN_OVERRIDE_VALUE_MASK 0x80000000
+#define CRTC_STATIC_SCREEN_CONTROL__CRTC_STATIC_SCREEN_OVERRIDE_VALUE__SHIFT 0x1f
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_EN_MASK 0x1
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_EN__SHIFT 0x0
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_EN_DB_MASK 0x10
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_EN_DB__SHIFT 0x4
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_V_UPDATE_MODE_MASK 0x300
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_V_UPDATE_MODE__SHIFT 0x8
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_STEREO_SEL_OVR_MASK 0x1000
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_STEREO_SEL_OVR__SHIFT 0xc
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_F_COUNT_RESET_MASK 0x10000
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_F_COUNT_RESET__SHIFT 0x10
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_F_COUNT_RESET_PENDING_MASK 0x20000
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_F_COUNT_RESET_PENDING__SHIFT 0x11
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_F_COUNT_MASK 0xc0000
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_F_COUNT__SHIFT 0x12
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_LIMIT_MASK 0xff
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_LIMIT__SHIFT 0x0
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_DELAY_MASK 0xff00
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_DELAY__SHIFT 0x8
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_SOURCE_SEL_MASK 0x10000
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_SOURCE_SEL__SHIFT 0x10
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_MODE_MASK 0x60000
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_MODE__SHIFT 0x11
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_CLEAR_MASK 0x80000
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_CLEAR__SHIFT 0x13
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_OCCURRED_MASK 0x100000
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_OCCURRED__SHIFT 0x14
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_MASTER_FASTER_MASK 0x800000
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_MASTER_FASTER__SHIFT 0x17
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_MASK 0xff000000
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP__SHIFT 0x18
+#define CRTC_GSL_WINDOW__CRTC_GSL_WINDOW_START_MASK 0x3fff
+#define CRTC_GSL_WINDOW__CRTC_GSL_WINDOW_START__SHIFT 0x0
+#define CRTC_GSL_WINDOW__CRTC_GSL_WINDOW_END_MASK 0x3fff0000
+#define CRTC_GSL_WINDOW__CRTC_GSL_WINDOW_END__SHIFT 0x10
+#define CRTC_GSL_CONTROL__CRTC_GSL_CHECK_LINE_NUM_MASK 0x3fff
+#define CRTC_GSL_CONTROL__CRTC_GSL_CHECK_LINE_NUM__SHIFT 0x0
+#define CRTC_GSL_CONTROL__CRTC_GSL_FORCE_DELAY_MASK 0x1f0000
+#define CRTC_GSL_CONTROL__CRTC_GSL_FORCE_DELAY__SHIFT 0x10
+#define CRTC_GSL_CONTROL__CRTC_GSL_CHECK_ALL_FIELDS_MASK 0x10000000
+#define CRTC_GSL_CONTROL__CRTC_GSL_CHECK_ALL_FIELDS__SHIFT 0x1c
+#define CRTC_TEST_DEBUG_INDEX__CRTC_TEST_DEBUG_INDEX_MASK 0xff
+#define CRTC_TEST_DEBUG_INDEX__CRTC_TEST_DEBUG_INDEX__SHIFT 0x0
+#define CRTC_TEST_DEBUG_INDEX__CRTC_TEST_DEBUG_WRITE_EN_MASK 0x100
+#define CRTC_TEST_DEBUG_INDEX__CRTC_TEST_DEBUG_WRITE_EN__SHIFT 0x8
+#define CRTC_TEST_DEBUG_DATA__CRTC_TEST_DEBUG_DATA_MASK 0xffffffff
+#define CRTC_TEST_DEBUG_DATA__CRTC_TEST_DEBUG_DATA__SHIFT 0x0
+#define DAC_ENABLE__DAC_ENABLE_MASK 0x1
+#define DAC_ENABLE__DAC_ENABLE__SHIFT 0x0
+#define DAC_ENABLE__DAC_RESYNC_FIFO_ENABLE_MASK 0x2
+#define DAC_ENABLE__DAC_RESYNC_FIFO_ENABLE__SHIFT 0x1
+#define DAC_ENABLE__DAC_RESYNC_FIFO_POINTER_SKEW_MASK 0xc
+#define DAC_ENABLE__DAC_RESYNC_FIFO_POINTER_SKEW__SHIFT 0x2
+#define DAC_ENABLE__DAC_RESYNC_FIFO_ERROR_MASK 0x10
+#define DAC_ENABLE__DAC_RESYNC_FIFO_ERROR__SHIFT 0x4
+#define DAC_ENABLE__DAC_RESYNC_FIFO_ERROR_ACK_MASK 0x20
+#define DAC_ENABLE__DAC_RESYNC_FIFO_ERROR_ACK__SHIFT 0x5
+#define DAC_ENABLE__DAC_RESYNC_FIFO_TVOUT_SIM_MASK 0x100
+#define DAC_ENABLE__DAC_RESYNC_FIFO_TVOUT_SIM__SHIFT 0x8
+#define DAC_SOURCE_SELECT__DAC_SOURCE_SELECT_MASK 0x7
+#define DAC_SOURCE_SELECT__DAC_SOURCE_SELECT__SHIFT 0x0
+#define DAC_SOURCE_SELECT__DAC_TV_SELECT_MASK 0x8
+#define DAC_SOURCE_SELECT__DAC_TV_SELECT__SHIFT 0x3
+#define DAC_CRC_EN__DAC_CRC_EN_MASK 0x1
+#define DAC_CRC_EN__DAC_CRC_EN__SHIFT 0x0
+#define DAC_CRC_EN__DAC_CRC_CONT_EN_MASK 0x10000
+#define DAC_CRC_EN__DAC_CRC_CONT_EN__SHIFT 0x10
+#define DAC_CRC_CONTROL__DAC_CRC_FIELD_MASK 0x1
+#define DAC_CRC_CONTROL__DAC_CRC_FIELD__SHIFT 0x0
+#define DAC_CRC_CONTROL__DAC_CRC_ONLY_BLANKB_MASK 0x100
+#define DAC_CRC_CONTROL__DAC_CRC_ONLY_BLANKB__SHIFT 0x8
+#define DAC_CRC_SIG_RGB_MASK__DAC_CRC_SIG_BLUE_MASK_MASK 0x3ff
+#define DAC_CRC_SIG_RGB_MASK__DAC_CRC_SIG_BLUE_MASK__SHIFT 0x0
+#define DAC_CRC_SIG_RGB_MASK__DAC_CRC_SIG_GREEN_MASK_MASK 0xffc00
+#define DAC_CRC_SIG_RGB_MASK__DAC_CRC_SIG_GREEN_MASK__SHIFT 0xa
+#define DAC_CRC_SIG_RGB_MASK__DAC_CRC_SIG_RED_MASK_MASK 0x3ff00000
+#define DAC_CRC_SIG_RGB_MASK__DAC_CRC_SIG_RED_MASK__SHIFT 0x14
+#define DAC_CRC_SIG_CONTROL_MASK__DAC_CRC_SIG_CONTROL_MASK_MASK 0x3f
+#define DAC_CRC_SIG_CONTROL_MASK__DAC_CRC_SIG_CONTROL_MASK__SHIFT 0x0
+#define DAC_CRC_SIG_RGB__DAC_CRC_SIG_BLUE_MASK 0x3ff
+#define DAC_CRC_SIG_RGB__DAC_CRC_SIG_BLUE__SHIFT 0x0
+#define DAC_CRC_SIG_RGB__DAC_CRC_SIG_GREEN_MASK 0xffc00
+#define DAC_CRC_SIG_RGB__DAC_CRC_SIG_GREEN__SHIFT 0xa
+#define DAC_CRC_SIG_RGB__DAC_CRC_SIG_RED_MASK 0x3ff00000
+#define DAC_CRC_SIG_RGB__DAC_CRC_SIG_RED__SHIFT 0x14
+#define DAC_CRC_SIG_CONTROL__DAC_CRC_SIG_CONTROL_MASK 0x3f
+#define DAC_CRC_SIG_CONTROL__DAC_CRC_SIG_CONTROL__SHIFT 0x0
+#define DAC_SYNC_TRISTATE_CONTROL__DAC_HSYNCA_TRISTATE_MASK 0x1
+#define DAC_SYNC_TRISTATE_CONTROL__DAC_HSYNCA_TRISTATE__SHIFT 0x0
+#define DAC_SYNC_TRISTATE_CONTROL__DAC_VSYNCA_TRISTATE_MASK 0x100
+#define DAC_SYNC_TRISTATE_CONTROL__DAC_VSYNCA_TRISTATE__SHIFT 0x8
+#define DAC_SYNC_TRISTATE_CONTROL__DAC_SYNCA_TRISTATE_MASK 0x10000
+#define DAC_SYNC_TRISTATE_CONTROL__DAC_SYNCA_TRISTATE__SHIFT 0x10
+#define DAC_STEREOSYNC_SELECT__DAC_STEREOSYNC_SELECT_MASK 0x7
+#define DAC_STEREOSYNC_SELECT__DAC_STEREOSYNC_SELECT__SHIFT 0x0
+#define DAC_AUTODETECT_CONTROL__DAC_AUTODETECT_MODE_MASK 0x3
+#define DAC_AUTODETECT_CONTROL__DAC_AUTODETECT_MODE__SHIFT 0x0
+#define DAC_AUTODETECT_CONTROL__DAC_AUTODETECT_FRAME_TIME_COUNTER_MASK 0xff00
+#define DAC_AUTODETECT_CONTROL__DAC_AUTODETECT_FRAME_TIME_COUNTER__SHIFT 0x8
+#define DAC_AUTODETECT_CONTROL__DAC_AUTODETECT_CHECK_MASK_MASK 0x70000
+#define DAC_AUTODETECT_CONTROL__DAC_AUTODETECT_CHECK_MASK__SHIFT 0x10
+#define DAC_AUTODETECT_CONTROL2__DAC_AUTODETECT_POWERUP_COUNTER_MASK 0xff
+#define DAC_AUTODETECT_CONTROL2__DAC_AUTODETECT_POWERUP_COUNTER__SHIFT 0x0
+#define DAC_AUTODETECT_CONTROL2__DAC_AUTODETECT_TESTMODE_MASK 0x100
+#define DAC_AUTODETECT_CONTROL2__DAC_AUTODETECT_TESTMODE__SHIFT 0x8
+#define DAC_AUTODETECT_CONTROL3__DAC_AUTODET_COMPARATOR_IN_DELAY_MASK 0xff
+#define DAC_AUTODETECT_CONTROL3__DAC_AUTODET_COMPARATOR_IN_DELAY__SHIFT 0x0
+#define DAC_AUTODETECT_CONTROL3__DAC_AUTODET_COMPARATOR_OUT_DELAY_MASK 0xff00
+#define DAC_AUTODETECT_CONTROL3__DAC_AUTODET_COMPARATOR_OUT_DELAY__SHIFT 0x8
+#define DAC_AUTODETECT_STATUS__DAC_AUTODETECT_STATUS_MASK 0x1
+#define DAC_AUTODETECT_STATUS__DAC_AUTODETECT_STATUS__SHIFT 0x0
+#define DAC_AUTODETECT_STATUS__DAC_AUTODETECT_CONNECT_MASK 0x10
+#define DAC_AUTODETECT_STATUS__DAC_AUTODETECT_CONNECT__SHIFT 0x4
+#define DAC_AUTODETECT_STATUS__DAC_AUTODETECT_RED_SENSE_MASK 0x300
+#define DAC_AUTODETECT_STATUS__DAC_AUTODETECT_RED_SENSE__SHIFT 0x8
+#define DAC_AUTODETECT_STATUS__DAC_AUTODETECT_GREEN_SENSE_MASK 0x30000
+#define DAC_AUTODETECT_STATUS__DAC_AUTODETECT_GREEN_SENSE__SHIFT 0x10
+#define DAC_AUTODETECT_STATUS__DAC_AUTODETECT_BLUE_SENSE_MASK 0x3000000
+#define DAC_AUTODETECT_STATUS__DAC_AUTODETECT_BLUE_SENSE__SHIFT 0x18
+#define DAC_AUTODETECT_INT_CONTROL__DAC_AUTODETECT_ACK_MASK 0x1
+#define DAC_AUTODETECT_INT_CONTROL__DAC_AUTODETECT_ACK__SHIFT 0x0
+#define DAC_AUTODETECT_INT_CONTROL__DAC_AUTODETECT_INT_ENABLE_MASK 0x10000
+#define DAC_AUTODETECT_INT_CONTROL__DAC_AUTODETECT_INT_ENABLE__SHIFT 0x10
+#define DAC_FORCE_OUTPUT_CNTL__DAC_FORCE_DATA_EN_MASK 0x1
+#define DAC_FORCE_OUTPUT_CNTL__DAC_FORCE_DATA_EN__SHIFT 0x0
+#define DAC_FORCE_OUTPUT_CNTL__DAC_FORCE_DATA_SEL_MASK 0x700
+#define DAC_FORCE_OUTPUT_CNTL__DAC_FORCE_DATA_SEL__SHIFT 0x8
+#define DAC_FORCE_OUTPUT_CNTL__DAC_FORCE_DATA_ON_BLANKB_ONLY_MASK 0x1000000
+#define DAC_FORCE_OUTPUT_CNTL__DAC_FORCE_DATA_ON_BLANKB_ONLY__SHIFT 0x18
+#define DAC_FORCE_DATA__DAC_FORCE_DATA_MASK 0x3ff
+#define DAC_FORCE_DATA__DAC_FORCE_DATA__SHIFT 0x0
+#define DAC_POWERDOWN__DAC_POWERDOWN_MASK 0x1
+#define DAC_POWERDOWN__DAC_POWERDOWN__SHIFT 0x0
+#define DAC_POWERDOWN__DAC_POWERDOWN_BLUE_MASK 0x100
+#define DAC_POWERDOWN__DAC_POWERDOWN_BLUE__SHIFT 0x8
+#define DAC_POWERDOWN__DAC_POWERDOWN_GREEN_MASK 0x10000
+#define DAC_POWERDOWN__DAC_POWERDOWN_GREEN__SHIFT 0x10
+#define DAC_POWERDOWN__DAC_POWERDOWN_RED_MASK 0x1000000
+#define DAC_POWERDOWN__DAC_POWERDOWN_RED__SHIFT 0x18
+#define DAC_CONTROL__DAC_DFORCE_EN_MASK 0x1
+#define DAC_CONTROL__DAC_DFORCE_EN__SHIFT 0x0
+#define DAC_CONTROL__DAC_TV_ENABLE_MASK 0x100
+#define DAC_CONTROL__DAC_TV_ENABLE__SHIFT 0x8
+#define DAC_CONTROL__DAC_ZSCALE_SHIFT_MASK 0x10000
+#define DAC_CONTROL__DAC_ZSCALE_SHIFT__SHIFT 0x10
+#define DAC_COMPARATOR_ENABLE__DAC_COMP_DDET_REF_EN_MASK 0x1
+#define DAC_COMPARATOR_ENABLE__DAC_COMP_DDET_REF_EN__SHIFT 0x0
+#define DAC_COMPARATOR_ENABLE__DAC_COMP_SDET_REF_EN_MASK 0x100
+#define DAC_COMPARATOR_ENABLE__DAC_COMP_SDET_REF_EN__SHIFT 0x8
+#define DAC_COMPARATOR_ENABLE__DAC_R_ASYNC_ENABLE_MASK 0x10000
+#define DAC_COMPARATOR_ENABLE__DAC_R_ASYNC_ENABLE__SHIFT 0x10
+#define DAC_COMPARATOR_ENABLE__DAC_G_ASYNC_ENABLE_MASK 0x20000
+#define DAC_COMPARATOR_ENABLE__DAC_G_ASYNC_ENABLE__SHIFT 0x11
+#define DAC_COMPARATOR_ENABLE__DAC_B_ASYNC_ENABLE_MASK 0x40000
+#define DAC_COMPARATOR_ENABLE__DAC_B_ASYNC_ENABLE__SHIFT 0x12
+#define DAC_COMPARATOR_OUTPUT__DAC_COMPARATOR_OUTPUT_MASK 0x1
+#define DAC_COMPARATOR_OUTPUT__DAC_COMPARATOR_OUTPUT__SHIFT 0x0
+#define DAC_COMPARATOR_OUTPUT__DAC_COMPARATOR_OUTPUT_BLUE_MASK 0x2
+#define DAC_COMPARATOR_OUTPUT__DAC_COMPARATOR_OUTPUT_BLUE__SHIFT 0x1
+#define DAC_COMPARATOR_OUTPUT__DAC_COMPARATOR_OUTPUT_GREEN_MASK 0x4
+#define DAC_COMPARATOR_OUTPUT__DAC_COMPARATOR_OUTPUT_GREEN__SHIFT 0x2
+#define DAC_COMPARATOR_OUTPUT__DAC_COMPARATOR_OUTPUT_RED_MASK 0x8
+#define DAC_COMPARATOR_OUTPUT__DAC_COMPARATOR_OUTPUT_RED__SHIFT 0x3
+#define DAC_PWR_CNTL__DAC_BG_MODE_MASK 0x3
+#define DAC_PWR_CNTL__DAC_BG_MODE__SHIFT 0x0
+#define DAC_PWR_CNTL__DAC_PWRCNTL_MASK 0x30000
+#define DAC_PWR_CNTL__DAC_PWRCNTL__SHIFT 0x10
+#define DAC_DFT_CONFIG__DAC_DFT_CONFIG_MASK 0xffffffff
+#define DAC_DFT_CONFIG__DAC_DFT_CONFIG__SHIFT 0x0
+#define DAC_FIFO_STATUS__DAC_FIFO_USE_OVERWRITE_LEVEL_MASK 0x2
+#define DAC_FIFO_STATUS__DAC_FIFO_USE_OVERWRITE_LEVEL__SHIFT 0x1
+#define DAC_FIFO_STATUS__DAC_FIFO_OVERWRITE_LEVEL_MASK 0xfc
+#define DAC_FIFO_STATUS__DAC_FIFO_OVERWRITE_LEVEL__SHIFT 0x2
+#define DAC_FIFO_STATUS__DAC_FIFO_CAL_AVERAGE_LEVEL_MASK 0xfc00
+#define DAC_FIFO_STATUS__DAC_FIFO_CAL_AVERAGE_LEVEL__SHIFT 0xa
+#define DAC_FIFO_STATUS__DAC_FIFO_MAXIMUM_LEVEL_MASK 0xf0000
+#define DAC_FIFO_STATUS__DAC_FIFO_MAXIMUM_LEVEL__SHIFT 0x10
+#define DAC_FIFO_STATUS__DAC_FIFO_MINIMUM_LEVEL_MASK 0x3c00000
+#define DAC_FIFO_STATUS__DAC_FIFO_MINIMUM_LEVEL__SHIFT 0x16
+#define DAC_FIFO_STATUS__DAC_FIFO_CALIBRATED_MASK 0x20000000
+#define DAC_FIFO_STATUS__DAC_FIFO_CALIBRATED__SHIFT 0x1d
+#define DAC_FIFO_STATUS__DAC_FIFO_FORCE_RECAL_AVERAGE_MASK 0x40000000
+#define DAC_FIFO_STATUS__DAC_FIFO_FORCE_RECAL_AVERAGE__SHIFT 0x1e
+#define DAC_FIFO_STATUS__DAC_FIFO_FORCE_RECOMP_MINMAX_MASK 0x80000000
+#define DAC_FIFO_STATUS__DAC_FIFO_FORCE_RECOMP_MINMAX__SHIFT 0x1f
+#define DAC_TEST_DEBUG_INDEX__DAC_TEST_DEBUG_INDEX_MASK 0xff
+#define DAC_TEST_DEBUG_INDEX__DAC_TEST_DEBUG_INDEX__SHIFT 0x0
+#define DAC_TEST_DEBUG_INDEX__DAC_TEST_DEBUG_WRITE_EN_MASK 0x100
+#define DAC_TEST_DEBUG_INDEX__DAC_TEST_DEBUG_WRITE_EN__SHIFT 0x8
+#define DAC_TEST_DEBUG_DATA__DAC_TEST_DEBUG_DATA_MASK 0xffffffff
+#define DAC_TEST_DEBUG_DATA__DAC_TEST_DEBUG_DATA__SHIFT 0x0
+#define PERFCOUNTER_CNTL__PERFCOUNTER_EVENT_SEL_MASK 0x1ff
+#define PERFCOUNTER_CNTL__PERFCOUNTER_EVENT_SEL__SHIFT 0x0
+#define PERFCOUNTER_CNTL__PERFCOUNTER_CVALUE_SEL_MASK 0xe00
+#define PERFCOUNTER_CNTL__PERFCOUNTER_CVALUE_SEL__SHIFT 0x9
+#define PERFCOUNTER_CNTL__PERFCOUNTER_INC_MODE_MASK 0x3000
+#define PERFCOUNTER_CNTL__PERFCOUNTER_INC_MODE__SHIFT 0xc
+#define PERFCOUNTER_CNTL__PERFCOUNTER_HW_CNTL_SEL_MASK 0x4000
+#define PERFCOUNTER_CNTL__PERFCOUNTER_HW_CNTL_SEL__SHIFT 0xe
+#define PERFCOUNTER_CNTL__PERFCOUNTER_RUNEN_MODE_MASK 0x8000
+#define PERFCOUNTER_CNTL__PERFCOUNTER_RUNEN_MODE__SHIFT 0xf
+#define PERFCOUNTER_CNTL__PERFCOUNTER_CNTOFF_SEL_MASK 0x1f0000
+#define PERFCOUNTER_CNTL__PERFCOUNTER_CNTOFF_SEL__SHIFT 0x10
+#define PERFCOUNTER_CNTL__PERFCOUNTER_CNTOFF_START_DIS_MASK 0x200000
+#define PERFCOUNTER_CNTL__PERFCOUNTER_CNTOFF_START_DIS__SHIFT 0x15
+#define PERFCOUNTER_CNTL__PERFCOUNTER_RESTART_EN_MASK 0x400000
+#define PERFCOUNTER_CNTL__PERFCOUNTER_RESTART_EN__SHIFT 0x16
+#define PERFCOUNTER_CNTL__PERFCOUNTER_INT_EN_MASK 0x800000
+#define PERFCOUNTER_CNTL__PERFCOUNTER_INT_EN__SHIFT 0x17
+#define PERFCOUNTER_CNTL__PERFCOUNTER_OFF_MASK_MASK 0x1000000
+#define PERFCOUNTER_CNTL__PERFCOUNTER_OFF_MASK__SHIFT 0x18
+#define PERFCOUNTER_CNTL__PERFCOUNTER_ACTIVE_MASK 0x2000000
+#define PERFCOUNTER_CNTL__PERFCOUNTER_ACTIVE__SHIFT 0x19
+#define PERFCOUNTER_CNTL__PERFCOUNTER_INT_TYPE_MASK 0x4000000
+#define PERFCOUNTER_CNTL__PERFCOUNTER_INT_TYPE__SHIFT 0x1a
+#define PERFCOUNTER_CNTL__PERFCOUNTER_COUNTED_VALUE_TYPE_MASK 0x8000000
+#define PERFCOUNTER_CNTL__PERFCOUNTER_COUNTED_VALUE_TYPE__SHIFT 0x1b
+#define PERFCOUNTER_CNTL__PERFCOUNTER_CNTL_SEL_MASK 0xe0000000
+#define PERFCOUNTER_CNTL__PERFCOUNTER_CNTL_SEL__SHIFT 0x1d
+#define PERFCOUNTER_STATE__PERFCOUNTER_CNT0_STATE_MASK 0x3
+#define PERFCOUNTER_STATE__PERFCOUNTER_CNT0_STATE__SHIFT 0x0
+#define PERFCOUNTER_STATE__PERFCOUNTER_STATE_SEL0_MASK 0x4
+#define PERFCOUNTER_STATE__PERFCOUNTER_STATE_SEL0__SHIFT 0x2
+#define PERFCOUNTER_STATE__PERFCOUNTER_CNT1_STATE_MASK 0x30
+#define PERFCOUNTER_STATE__PERFCOUNTER_CNT1_STATE__SHIFT 0x4
+#define PERFCOUNTER_STATE__PERFCOUNTER_STATE_SEL1_MASK 0x40
+#define PERFCOUNTER_STATE__PERFCOUNTER_STATE_SEL1__SHIFT 0x6
+#define PERFCOUNTER_STATE__PERFCOUNTER_CNT2_STATE_MASK 0x300
+#define PERFCOUNTER_STATE__PERFCOUNTER_CNT2_STATE__SHIFT 0x8
+#define PERFCOUNTER_STATE__PERFCOUNTER_STATE_SEL2_MASK 0x400
+#define PERFCOUNTER_STATE__PERFCOUNTER_STATE_SEL2__SHIFT 0xa
+#define PERFCOUNTER_STATE__PERFCOUNTER_CNT3_STATE_MASK 0x3000
+#define PERFCOUNTER_STATE__PERFCOUNTER_CNT3_STATE__SHIFT 0xc
+#define PERFCOUNTER_STATE__PERFCOUNTER_STATE_SEL3_MASK 0x4000
+#define PERFCOUNTER_STATE__PERFCOUNTER_STATE_SEL3__SHIFT 0xe
+#define PERFCOUNTER_STATE__PERFCOUNTER_CNT4_STATE_MASK 0x30000
+#define PERFCOUNTER_STATE__PERFCOUNTER_CNT4_STATE__SHIFT 0x10
+#define PERFCOUNTER_STATE__PERFCOUNTER_STATE_SEL4_MASK 0x40000
+#define PERFCOUNTER_STATE__PERFCOUNTER_STATE_SEL4__SHIFT 0x12
+#define PERFCOUNTER_STATE__PERFCOUNTER_CNT5_STATE_MASK 0x300000
+#define PERFCOUNTER_STATE__PERFCOUNTER_CNT5_STATE__SHIFT 0x14
+#define PERFCOUNTER_STATE__PERFCOUNTER_STATE_SEL5_MASK 0x400000
+#define PERFCOUNTER_STATE__PERFCOUNTER_STATE_SEL5__SHIFT 0x16
+#define PERFCOUNTER_STATE__PERFCOUNTER_CNT6_STATE_MASK 0x3000000
+#define PERFCOUNTER_STATE__PERFCOUNTER_CNT6_STATE__SHIFT 0x18
+#define PERFCOUNTER_STATE__PERFCOUNTER_STATE_SEL6_MASK 0x4000000
+#define PERFCOUNTER_STATE__PERFCOUNTER_STATE_SEL6__SHIFT 0x1a
+#define PERFCOUNTER_STATE__PERFCOUNTER_CNT7_STATE_MASK 0x30000000
+#define PERFCOUNTER_STATE__PERFCOUNTER_CNT7_STATE__SHIFT 0x1c
+#define PERFCOUNTER_STATE__PERFCOUNTER_STATE_SEL7_MASK 0x40000000
+#define PERFCOUNTER_STATE__PERFCOUNTER_STATE_SEL7__SHIFT 0x1e
+#define PERFMON_CNTL__PERFMON_STATE_MASK 0x3
+#define PERFMON_CNTL__PERFMON_STATE__SHIFT 0x0
+#define PERFMON_CNTL__PERFMON_RUN_ENABLE_SEL_MASK 0xfc
+#define PERFMON_CNTL__PERFMON_RUN_ENABLE_SEL__SHIFT 0x2
+#define PERFMON_CNTL__PERFMON_RPT_COUNT_MASK 0xfffff00
+#define PERFMON_CNTL__PERFMON_RPT_COUNT__SHIFT 0x8
+#define PERFMON_CNTL__PERFMON_CNTOFF_AND_OR_MASK 0x10000000
+#define PERFMON_CNTL__PERFMON_CNTOFF_AND_OR__SHIFT 0x1c
+#define PERFMON_CNTL__PERFMON_CNTOFF_INT_EN_MASK 0x20000000
+#define PERFMON_CNTL__PERFMON_CNTOFF_INT_EN__SHIFT 0x1d
+#define PERFMON_CNTL__PERFMON_CNTOFF_INT_STATUS_MASK 0x40000000
+#define PERFMON_CNTL__PERFMON_CNTOFF_INT_STATUS__SHIFT 0x1e
+#define PERFMON_CNTL__PERFMON_CNTOFF_INT_ACK_MASK 0x80000000
+#define PERFMON_CNTL__PERFMON_CNTOFF_INT_ACK__SHIFT 0x1f
+#define PERFMON_CNTL2__PERFMON_CNTOFF_INT_TYPE_MASK 0x1
+#define PERFMON_CNTL2__PERFMON_CNTOFF_INT_TYPE__SHIFT 0x0
+#define PERFMON_CNTL2__PERFMON_CLK_ENABLE_MASK 0x2
+#define PERFMON_CNTL2__PERFMON_CLK_ENABLE__SHIFT 0x1
+#define PERFMON_CVALUE_INT_MISC__PERFCOUNTER_INT0_STATUS_MASK 0x1
+#define PERFMON_CVALUE_INT_MISC__PERFCOUNTER_INT0_STATUS__SHIFT 0x0
+#define PERFMON_CVALUE_INT_MISC__PERFCOUNTER_INT1_STATUS_MASK 0x2
+#define PERFMON_CVALUE_INT_MISC__PERFCOUNTER_INT1_STATUS__SHIFT 0x1
+#define PERFMON_CVALUE_INT_MISC__PERFCOUNTER_INT2_STATUS_MASK 0x4
+#define PERFMON_CVALUE_INT_MISC__PERFCOUNTER_INT2_STATUS__SHIFT 0x2
+#define PERFMON_CVALUE_INT_MISC__PERFCOUNTER_INT3_STATUS_MASK 0x8
+#define PERFMON_CVALUE_INT_MISC__PERFCOUNTER_INT3_STATUS__SHIFT 0x3
+#define PERFMON_CVALUE_INT_MISC__PERFCOUNTER_INT4_STATUS_MASK 0x10
+#define PERFMON_CVALUE_INT_MISC__PERFCOUNTER_INT4_STATUS__SHIFT 0x4
+#define PERFMON_CVALUE_INT_MISC__PERFCOUNTER_INT5_STATUS_MASK 0x20
+#define PERFMON_CVALUE_INT_MISC__PERFCOUNTER_INT5_STATUS__SHIFT 0x5
+#define PERFMON_CVALUE_INT_MISC__PERFCOUNTER_INT6_STATUS_MASK 0x40
+#define PERFMON_CVALUE_INT_MISC__PERFCOUNTER_INT6_STATUS__SHIFT 0x6
+#define PERFMON_CVALUE_INT_MISC__PERFCOUNTER_INT7_STATUS_MASK 0x80
+#define PERFMON_CVALUE_INT_MISC__PERFCOUNTER_INT7_STATUS__SHIFT 0x7
+#define PERFMON_CVALUE_INT_MISC__PERFCOUNTER_INT0_ACK_MASK 0x100
+#define PERFMON_CVALUE_INT_MISC__PERFCOUNTER_INT0_ACK__SHIFT 0x8
+#define PERFMON_CVALUE_INT_MISC__PERFCOUNTER_INT1_ACK_MASK 0x200
+#define PERFMON_CVALUE_INT_MISC__PERFCOUNTER_INT1_ACK__SHIFT 0x9
+#define PERFMON_CVALUE_INT_MISC__PERFCOUNTER_INT2_ACK_MASK 0x400
+#define PERFMON_CVALUE_INT_MISC__PERFCOUNTER_INT2_ACK__SHIFT 0xa
+#define PERFMON_CVALUE_INT_MISC__PERFCOUNTER_INT3_ACK_MASK 0x800
+#define PERFMON_CVALUE_INT_MISC__PERFCOUNTER_INT3_ACK__SHIFT 0xb
+#define PERFMON_CVALUE_INT_MISC__PERFCOUNTER_INT4_ACK_MASK 0x1000
+#define PERFMON_CVALUE_INT_MISC__PERFCOUNTER_INT4_ACK__SHIFT 0xc
+#define PERFMON_CVALUE_INT_MISC__PERFCOUNTER_INT5_ACK_MASK 0x2000
+#define PERFMON_CVALUE_INT_MISC__PERFCOUNTER_INT5_ACK__SHIFT 0xd
+#define PERFMON_CVALUE_INT_MISC__PERFCOUNTER_INT6_ACK_MASK 0x4000
+#define PERFMON_CVALUE_INT_MISC__PERFCOUNTER_INT6_ACK__SHIFT 0xe
+#define PERFMON_CVALUE_INT_MISC__PERFCOUNTER_INT7_ACK_MASK 0x8000
+#define PERFMON_CVALUE_INT_MISC__PERFCOUNTER_INT7_ACK__SHIFT 0xf
+#define PERFMON_CVALUE_INT_MISC__PERFMON_CVALUE_HI_MASK 0xffff0000
+#define PERFMON_CVALUE_INT_MISC__PERFMON_CVALUE_HI__SHIFT 0x10
+#define PERFMON_CVALUE_LOW__PERFMON_CVALUE_LOW_MASK 0xffffffff
+#define PERFMON_CVALUE_LOW__PERFMON_CVALUE_LOW__SHIFT 0x0
+#define PERFMON_HI__PERFMON_HI_MASK 0xffff
+#define PERFMON_HI__PERFMON_HI__SHIFT 0x0
+#define PERFMON_HI__PERFMON_READ_SEL_MASK 0xe0000000
+#define PERFMON_HI__PERFMON_READ_SEL__SHIFT 0x1d
+#define PERFMON_LOW__PERFMON_LOW_MASK 0xffffffff
+#define PERFMON_LOW__PERFMON_LOW__SHIFT 0x0
+#define PERFMON_TEST_DEBUG_INDEX__PERFMON_TEST_DEBUG_INDEX_MASK 0xff
+#define PERFMON_TEST_DEBUG_INDEX__PERFMON_TEST_DEBUG_INDEX__SHIFT 0x0
+#define PERFMON_TEST_DEBUG_INDEX__PERFMON_TEST_DEBUG_WRITE_EN_MASK 0x100
+#define PERFMON_TEST_DEBUG_INDEX__PERFMON_TEST_DEBUG_WRITE_EN__SHIFT 0x8
+#define PERFMON_TEST_DEBUG_DATA__PERFMON_TEST_DEBUG_DATA_MASK 0xffffffff
+#define PERFMON_TEST_DEBUG_DATA__PERFMON_TEST_DEBUG_DATA__SHIFT 0x0
+#define REFCLK_CNTL__REFCLK_CLOCK_EN_MASK 0x1
+#define REFCLK_CNTL__REFCLK_CLOCK_EN__SHIFT 0x0
+#define REFCLK_CNTL__REFCLK_SRC_SEL_MASK 0x2
+#define REFCLK_CNTL__REFCLK_SRC_SEL__SHIFT 0x1
+#define DCCG_CBUS_ANTIGLITCH_RESETB__P0PLL_CBUS_ANTIGLITCH_RESETB_MASK 0x1
+#define DCCG_CBUS_ANTIGLITCH_RESETB__P0PLL_CBUS_ANTIGLITCH_RESETB__SHIFT 0x0
+#define DCCG_CBUS_ANTIGLITCH_RESETB__P1PLL_CBUS_ANTIGLITCH_RESETB_MASK 0x2
+#define DCCG_CBUS_ANTIGLITCH_RESETB__P1PLL_CBUS_ANTIGLITCH_RESETB__SHIFT 0x1
+#define DCCG_CBUS_ANTIGLITCH_RESETB__P2PLL_CBUS_ANTIGLITCH_RESETB_MASK 0x4
+#define DCCG_CBUS_ANTIGLITCH_RESETB__P2PLL_CBUS_ANTIGLITCH_RESETB__SHIFT 0x2
+#define DCCG_CBUS_ANTIGLITCH_RESETB__P3PLL_CBUS_ANTIGLITCH_RESETB_MASK 0x8
+#define DCCG_CBUS_ANTIGLITCH_RESETB__P3PLL_CBUS_ANTIGLITCH_RESETB__SHIFT 0x3
+#define DCCG_CBUS_SPARE__P0PLL_CBUS_SPARE_MASK 0xff
+#define DCCG_CBUS_SPARE__P0PLL_CBUS_SPARE__SHIFT 0x0
+#define DCCG_CBUS_SPARE__P1PLL_CBUS_SPARE_MASK 0xff00
+#define DCCG_CBUS_SPARE__P1PLL_CBUS_SPARE__SHIFT 0x8
+#define DCCG_CBUS_SPARE__P2PLL_CBUS_SPARE_MASK 0xff0000
+#define DCCG_CBUS_SPARE__P2PLL_CBUS_SPARE__SHIFT 0x10
+#define DCCG_CBUS_SPARE__P3PLL_CBUS_SPARE_MASK 0xff000000
+#define DCCG_CBUS_SPARE__P3PLL_CBUS_SPARE__SHIFT 0x18
+#define DCCG_CBUS_WRCMD_DELAY__CBUS_PLL_WRCMD_DELAY_MASK 0xf
+#define DCCG_CBUS_WRCMD_DELAY__CBUS_PLL_WRCMD_DELAY__SHIFT 0x0
+#define DPREFCLK_CNTL__DPREFCLK_SRC_SEL_MASK 0x7
+#define DPREFCLK_CNTL__DPREFCLK_SRC_SEL__SHIFT 0x0
+#define DPREFCLK_CNTL__UNB_DB_CLK_ENABLE_MASK 0x100
+#define DPREFCLK_CNTL__UNB_DB_CLK_ENABLE__SHIFT 0x8
+#define DCE_VERSION__MAJOR_VERSION_MASK 0xff
+#define DCE_VERSION__MAJOR_VERSION__SHIFT 0x0
+#define DCE_VERSION__MINOR_VERSION_MASK 0xff00
+#define DCE_VERSION__MINOR_VERSION__SHIFT 0x8
+#define AVSYNC_COUNTER_WRITE__AVSYNC_COUNTER_WRVALUE_MASK 0xffffffff
+#define AVSYNC_COUNTER_WRITE__AVSYNC_COUNTER_WRVALUE__SHIFT 0x0
+#define AVSYNC_COUNTER_CONTROL__AVSYNC_COUNTER_ENABLE_MASK 0x1
+#define AVSYNC_COUNTER_CONTROL__AVSYNC_COUNTER_ENABLE__SHIFT 0x0
+#define AVSYNC_COUNTER_READ__AVSYNC_COUNTER_RDVALUE_MASK 0xffffffff
+#define AVSYNC_COUNTER_READ__AVSYNC_COUNTER_RDVALUE__SHIFT 0x0
+#define DCCG_GTC_CNTL__DCCG_GTC_ENABLE_MASK 0x1
+#define DCCG_GTC_CNTL__DCCG_GTC_ENABLE__SHIFT 0x0
+#define DCCG_GTC_DTO_INCR__DCCG_GTC_DTO_INCR_MASK 0xffffffff
+#define DCCG_GTC_DTO_INCR__DCCG_GTC_DTO_INCR__SHIFT 0x0
+#define DCCG_GTC_DTO_MODULO__DCCG_GTC_DTO_MODULO_MASK 0xffffffff
+#define DCCG_GTC_DTO_MODULO__DCCG_GTC_DTO_MODULO__SHIFT 0x0
+#define DCCG_GTC_CURRENT__DCCG_GTC_CURRENT_MASK 0xffffffff
+#define DCCG_GTC_CURRENT__DCCG_GTC_CURRENT__SHIFT 0x0
+#define DCCG_DS_DTO_INCR__DCCG_DS_DTO_INCR_MASK 0xffffffff
+#define DCCG_DS_DTO_INCR__DCCG_DS_DTO_INCR__SHIFT 0x0
+#define DCCG_DS_DTO_MODULO__DCCG_DS_DTO_MODULO_MASK 0xffffffff
+#define DCCG_DS_DTO_MODULO__DCCG_DS_DTO_MODULO__SHIFT 0x0
+#define DCCG_DS_CNTL__DCCG_DS_ENABLE_MASK 0x1
+#define DCCG_DS_CNTL__DCCG_DS_ENABLE__SHIFT 0x0
+#define DCCG_DS_CNTL__DCCG_DS_REF_SRC_MASK 0x30
+#define DCCG_DS_CNTL__DCCG_DS_REF_SRC__SHIFT 0x4
+#define DCCG_DS_CNTL__DCCG_DS_HW_CAL_ENABLE_MASK 0x100
+#define DCCG_DS_CNTL__DCCG_DS_HW_CAL_ENABLE__SHIFT 0x8
+#define DCCG_DS_CNTL__DCCG_DS_ENABLED_STATUS_MASK 0x200
+#define DCCG_DS_CNTL__DCCG_DS_ENABLED_STATUS__SHIFT 0x9
+#define DCCG_DS_CNTL__DCCG_DS_XTALIN_RATE_DIV_MASK 0x30000
+#define DCCG_DS_CNTL__DCCG_DS_XTALIN_RATE_DIV__SHIFT 0x10
+#define DCCG_DS_CNTL__DCCG_DS_JITTER_REMOVE_DIS_MASK 0x1000000
+#define DCCG_DS_CNTL__DCCG_DS_JITTER_REMOVE_DIS__SHIFT 0x18
+#define DCCG_DS_CNTL__DCCG_DS_DELAY_XTAL_SEL_MASK 0x2000000
+#define DCCG_DS_CNTL__DCCG_DS_DELAY_XTAL_SEL__SHIFT 0x19
+#define DCCG_DS_HW_CAL_INTERVAL__DCCG_DS_HW_CAL_INTERVAL_MASK 0xffffffff
+#define DCCG_DS_HW_CAL_INTERVAL__DCCG_DS_HW_CAL_INTERVAL__SHIFT 0x0
+#define DCCG_DS_DEBUG_CNTL__DCCG_DS_DEBUG_COUNT_ENABLE_MASK 0x1
+#define DCCG_DS_DEBUG_CNTL__DCCG_DS_DEBUG_COUNT_ENABLE__SHIFT 0x0
+#define DCCG_DS_DEBUG_CNTL__DCCG_DS_DEBUG_COUNT_TRIG_VALUE_MASK 0x1ff0
+#define DCCG_DS_DEBUG_CNTL__DCCG_DS_DEBUG_COUNT_TRIG_VALUE__SHIFT 0x4
+#define DCCG_DS_DEBUG_CNTL__DCCG_DS_DEBUG_COUNT_TRIG_OCCURRED_MASK 0x10000
+#define DCCG_DS_DEBUG_CNTL__DCCG_DS_DEBUG_COUNT_TRIG_OCCURRED__SHIFT 0x10
+#define DCCG_DS_DEBUG_CNTL__DCCG_DS_DEBUG_COUNT_TRIG_CLEAR_MASK 0x20000
+#define DCCG_DS_DEBUG_CNTL__DCCG_DS_DEBUG_COUNT_TRIG_CLEAR__SHIFT 0x11
+#define DCCG_DS_DEBUG_CNTL__DCCG_DS_JITTER_COUNT_ENABLE_MASK 0x100000
+#define DCCG_DS_DEBUG_CNTL__DCCG_DS_JITTER_COUNT_ENABLE__SHIFT 0x14
+#define DCCG_DS_DEBUG_CNTL__DCCG_DS_JITTER_COUNT_SRC_SEL_MASK 0x200000
+#define DCCG_DS_DEBUG_CNTL__DCCG_DS_JITTER_COUNT_SRC_SEL__SHIFT 0x15
+#define DCCG_DS_DEBUG_CNTL__DCCG_DS_JITTER_COUNT_MASK 0xff000000
+#define DCCG_DS_DEBUG_CNTL__DCCG_DS_JITTER_COUNT__SHIFT 0x18
+#define DMCU_SMU_INTERRUPT_CNTL__DMCU_SMU_STATIC_SCREEN_INT_MASK 0x1
+#define DMCU_SMU_INTERRUPT_CNTL__DMCU_SMU_STATIC_SCREEN_INT__SHIFT 0x0
+#define DMCU_SMU_INTERRUPT_CNTL__DMCU_SMU_STATIC_SCREEN_STATUS_MASK 0xffff0000
+#define DMCU_SMU_INTERRUPT_CNTL__DMCU_SMU_STATIC_SCREEN_STATUS__SHIFT 0x10
+#define SMU_CONTROL__DISPLAY0_FORCE_VBI_MASK 0x1
+#define SMU_CONTROL__DISPLAY0_FORCE_VBI__SHIFT 0x0
+#define SMU_CONTROL__DISPLAY1_FORCE_VBI_MASK 0x2
+#define SMU_CONTROL__DISPLAY1_FORCE_VBI__SHIFT 0x1
+#define SMU_CONTROL__DISPLAY2_FORCE_VBI_MASK 0x4
+#define SMU_CONTROL__DISPLAY2_FORCE_VBI__SHIFT 0x2
+#define SMU_CONTROL__DISPLAY3_FORCE_VBI_MASK 0x8
+#define SMU_CONTROL__DISPLAY3_FORCE_VBI__SHIFT 0x3
+#define SMU_CONTROL__DISPLAY4_FORCE_VBI_MASK 0x10
+#define SMU_CONTROL__DISPLAY4_FORCE_VBI__SHIFT 0x4
+#define SMU_CONTROL__DISPLAY5_FORCE_VBI_MASK 0x20
+#define SMU_CONTROL__DISPLAY5_FORCE_VBI__SHIFT 0x5
+#define SMU_CONTROL__DISPLAY_V0_FORCE_VBI_MASK 0x40
+#define SMU_CONTROL__DISPLAY_V0_FORCE_VBI__SHIFT 0x6
+#define SMU_CONTROL__DISPLAY_V1_FORCE_VBI_MASK 0x80
+#define SMU_CONTROL__DISPLAY_V1_FORCE_VBI__SHIFT 0x7
+#define SMU_CONTROL__MCIF_WB_FORCE_VBI_MASK 0x100
+#define SMU_CONTROL__MCIF_WB_FORCE_VBI__SHIFT 0x8
+#define SMU_CONTROL__SMU_DC_INT_CLEAR_MASK 0x10000
+#define SMU_CONTROL__SMU_DC_INT_CLEAR__SHIFT 0x10
+#define SMU_INTERRUPT_CONTROL__DC_SMU_INT_ENABLE_MASK 0x1
+#define SMU_INTERRUPT_CONTROL__DC_SMU_INT_ENABLE__SHIFT 0x0
+#define SMU_INTERRUPT_CONTROL__DC_SMU_INT_STATUS_MASK 0x10
+#define SMU_INTERRUPT_CONTROL__DC_SMU_INT_STATUS__SHIFT 0x4
+#define SMU_INTERRUPT_CONTROL__DC_SMU_INT_EVENT_MASK 0xffff0000
+#define SMU_INTERRUPT_CONTROL__DC_SMU_INT_EVENT__SHIFT 0x10
+#define DAC_CLK_ENABLE__DACA_CLK_ENABLE_MASK 0x1
+#define DAC_CLK_ENABLE__DACA_CLK_ENABLE__SHIFT 0x0
+#define DAC_CLK_ENABLE__DACB_CLK_ENABLE_MASK 0x10
+#define DAC_CLK_ENABLE__DACB_CLK_ENABLE__SHIFT 0x4
+#define DVO_CLK_ENABLE__DVO_CLK_ENABLE_MASK 0x1
+#define DVO_CLK_ENABLE__DVO_CLK_ENABLE__SHIFT 0x0
+#define DCCG_GATE_DISABLE_CNTL__DISPCLK_DCCG_GATE_DISABLE_MASK 0x1
+#define DCCG_GATE_DISABLE_CNTL__DISPCLK_DCCG_GATE_DISABLE__SHIFT 0x0
+#define DCCG_GATE_DISABLE_CNTL__DISPCLK_R_DCCG_GATE_DISABLE_MASK 0x2
+#define DCCG_GATE_DISABLE_CNTL__DISPCLK_R_DCCG_GATE_DISABLE__SHIFT 0x1
+#define DCCG_GATE_DISABLE_CNTL__SCLK_GATE_DISABLE_MASK 0x4
+#define DCCG_GATE_DISABLE_CNTL__SCLK_GATE_DISABLE__SHIFT 0x2
+#define DCCG_GATE_DISABLE_CNTL__DPREFCLK_GATE_DISABLE_MASK 0x8
+#define DCCG_GATE_DISABLE_CNTL__DPREFCLK_GATE_DISABLE__SHIFT 0x3
+#define DCCG_GATE_DISABLE_CNTL__DACACLK_GATE_DISABLE_MASK 0x10
+#define DCCG_GATE_DISABLE_CNTL__DACACLK_GATE_DISABLE__SHIFT 0x4
+#define DCCG_GATE_DISABLE_CNTL__DACBCLK_GATE_DISABLE_MASK 0x20
+#define DCCG_GATE_DISABLE_CNTL__DACBCLK_GATE_DISABLE__SHIFT 0x5
+#define DCCG_GATE_DISABLE_CNTL__DVOACLK_GATE_DISABLE_MASK 0x40
+#define DCCG_GATE_DISABLE_CNTL__DVOACLK_GATE_DISABLE__SHIFT 0x6
+#define DCCG_GATE_DISABLE_CNTL__DPDBG_CLK_GATE_DISABLE_MASK 0x80
+#define DCCG_GATE_DISABLE_CNTL__DPDBG_CLK_GATE_DISABLE__SHIFT 0x7
+#define DCCG_GATE_DISABLE_CNTL__DPREFCLK_R_DCCG_GATE_DISABLE_MASK 0x100
+#define DCCG_GATE_DISABLE_CNTL__DPREFCLK_R_DCCG_GATE_DISABLE__SHIFT 0x8
+#define DCCG_GATE_DISABLE_CNTL__AOMCLK0_GATE_DISABLE_MASK 0x20000
+#define DCCG_GATE_DISABLE_CNTL__AOMCLK0_GATE_DISABLE__SHIFT 0x11
+#define DCCG_GATE_DISABLE_CNTL__AOMCLK1_GATE_DISABLE_MASK 0x40000
+#define DCCG_GATE_DISABLE_CNTL__AOMCLK1_GATE_DISABLE__SHIFT 0x12
+#define DCCG_GATE_DISABLE_CNTL__AOMCLK2_GATE_DISABLE_MASK 0x80000
+#define DCCG_GATE_DISABLE_CNTL__AOMCLK2_GATE_DISABLE__SHIFT 0x13
+#define DCCG_GATE_DISABLE_CNTL__AUDIO_DTO2_CLK_GATE_DISABLE_MASK 0x200000
+#define DCCG_GATE_DISABLE_CNTL__AUDIO_DTO2_CLK_GATE_DISABLE__SHIFT 0x15
+#define DCCG_GATE_DISABLE_CNTL__DPREFCLK_GTC_GATE_DISABLE_MASK 0x400000
+#define DCCG_GATE_DISABLE_CNTL__DPREFCLK_GTC_GATE_DISABLE__SHIFT 0x16
+#define DCCG_GATE_DISABLE_CNTL__UNB_DB_CLK_GATE_DISABLE_MASK 0x800000
+#define DCCG_GATE_DISABLE_CNTL__UNB_DB_CLK_GATE_DISABLE__SHIFT 0x17
+#define DCCG_GATE_DISABLE_CNTL__REFCLK_GATE_DISABLE_MASK 0x4000000
+#define DCCG_GATE_DISABLE_CNTL__REFCLK_GATE_DISABLE__SHIFT 0x1a
+#define DCCG_GATE_DISABLE_CNTL__REFCLK_R_DIG_GATE_DISABLE_MASK 0x8000000
+#define DCCG_GATE_DISABLE_CNTL__REFCLK_R_DIG_GATE_DISABLE__SHIFT 0x1b
+#define DCCG_GATE_DISABLE_CNTL__DSICLK_GATE_DISABLE_MASK 0x10000000
+#define DCCG_GATE_DISABLE_CNTL__DSICLK_GATE_DISABLE__SHIFT 0x1c
+#define DCCG_GATE_DISABLE_CNTL__BYTECLK_GATE_DISABLE_MASK 0x20000000
+#define DCCG_GATE_DISABLE_CNTL__BYTECLK_GATE_DISABLE__SHIFT 0x1d
+#define DCCG_GATE_DISABLE_CNTL__ESCCLK_GATE_DISABLE_MASK 0x40000000
+#define DCCG_GATE_DISABLE_CNTL__ESCCLK_GATE_DISABLE__SHIFT 0x1e
+#define DCCG_GATE_DISABLE_CNTL2__SYMCLKA_FE_GATE_DISABLE_MASK 0x1
+#define DCCG_GATE_DISABLE_CNTL2__SYMCLKA_FE_GATE_DISABLE__SHIFT 0x0
+#define DCCG_GATE_DISABLE_CNTL2__SYMCLKB_FE_GATE_DISABLE_MASK 0x2
+#define DCCG_GATE_DISABLE_CNTL2__SYMCLKB_FE_GATE_DISABLE__SHIFT 0x1
+#define DCCG_GATE_DISABLE_CNTL2__SYMCLKC_FE_GATE_DISABLE_MASK 0x4
+#define DCCG_GATE_DISABLE_CNTL2__SYMCLKC_FE_GATE_DISABLE__SHIFT 0x2
+#define DCCG_GATE_DISABLE_CNTL2__SYMCLKD_FE_GATE_DISABLE_MASK 0x8
+#define DCCG_GATE_DISABLE_CNTL2__SYMCLKD_FE_GATE_DISABLE__SHIFT 0x3
+#define DCCG_GATE_DISABLE_CNTL2__SYMCLKE_FE_GATE_DISABLE_MASK 0x10
+#define DCCG_GATE_DISABLE_CNTL2__SYMCLKE_FE_GATE_DISABLE__SHIFT 0x4
+#define DCCG_GATE_DISABLE_CNTL2__SYMCLKF_FE_GATE_DISABLE_MASK 0x20
+#define DCCG_GATE_DISABLE_CNTL2__SYMCLKF_FE_GATE_DISABLE__SHIFT 0x5
+#define DCCG_GATE_DISABLE_CNTL2__SYMCLKG_FE_GATE_DISABLE_MASK 0x40
+#define DCCG_GATE_DISABLE_CNTL2__SYMCLKG_FE_GATE_DISABLE__SHIFT 0x6
+#define DCCG_GATE_DISABLE_CNTL2__SYMCLKLPA_FE_GATE_DISABLE_MASK 0x100
+#define DCCG_GATE_DISABLE_CNTL2__SYMCLKLPA_FE_GATE_DISABLE__SHIFT 0x8
+#define DCCG_GATE_DISABLE_CNTL2__SYMCLKLPB_FE_GATE_DISABLE_MASK 0x200
+#define DCCG_GATE_DISABLE_CNTL2__SYMCLKLPB_FE_GATE_DISABLE__SHIFT 0x9
+#define DCCG_GATE_DISABLE_CNTL2__SYMCLKA_GATE_DISABLE_MASK 0x10000
+#define DCCG_GATE_DISABLE_CNTL2__SYMCLKA_GATE_DISABLE__SHIFT 0x10
+#define DCCG_GATE_DISABLE_CNTL2__SYMCLKB_GATE_DISABLE_MASK 0x20000
+#define DCCG_GATE_DISABLE_CNTL2__SYMCLKB_GATE_DISABLE__SHIFT 0x11
+#define DCCG_GATE_DISABLE_CNTL2__SYMCLKC_GATE_DISABLE_MASK 0x40000
+#define DCCG_GATE_DISABLE_CNTL2__SYMCLKC_GATE_DISABLE__SHIFT 0x12
+#define DCCG_GATE_DISABLE_CNTL2__SYMCLKD_GATE_DISABLE_MASK 0x80000
+#define DCCG_GATE_DISABLE_CNTL2__SYMCLKD_GATE_DISABLE__SHIFT 0x13
+#define DCCG_GATE_DISABLE_CNTL2__SYMCLKE_GATE_DISABLE_MASK 0x100000
+#define DCCG_GATE_DISABLE_CNTL2__SYMCLKE_GATE_DISABLE__SHIFT 0x14
+#define DCCG_GATE_DISABLE_CNTL2__SYMCLKF_GATE_DISABLE_MASK 0x200000
+#define DCCG_GATE_DISABLE_CNTL2__SYMCLKF_GATE_DISABLE__SHIFT 0x15
+#define DCCG_GATE_DISABLE_CNTL2__SYMCLKG_GATE_DISABLE_MASK 0x400000
+#define DCCG_GATE_DISABLE_CNTL2__SYMCLKG_GATE_DISABLE__SHIFT 0x16
+#define DCCG_GATE_DISABLE_CNTL2__SYMCLKLPA_GATE_DISABLE_MASK 0x1000000
+#define DCCG_GATE_DISABLE_CNTL2__SYMCLKLPA_GATE_DISABLE__SHIFT 0x18
+#define DCCG_GATE_DISABLE_CNTL2__SYMCLKLPB_GATE_DISABLE_MASK 0x2000000
+#define DCCG_GATE_DISABLE_CNTL2__SYMCLKLPB_GATE_DISABLE__SHIFT 0x19
+#define DISPCLK_CGTT_BLK_CTRL_REG__DISPCLK_TURN_ON_DELAY_MASK 0xf
+#define DISPCLK_CGTT_BLK_CTRL_REG__DISPCLK_TURN_ON_DELAY__SHIFT 0x0
+#define DISPCLK_CGTT_BLK_CTRL_REG__DISPCLK_TURN_OFF_DELAY_MASK 0xff0
+#define DISPCLK_CGTT_BLK_CTRL_REG__DISPCLK_TURN_OFF_DELAY__SHIFT 0x4
+#define SCLK_CGTT_BLK_CTRL_REG__SCLK_TURN_ON_DELAY_MASK 0xf
+#define SCLK_CGTT_BLK_CTRL_REG__SCLK_TURN_ON_DELAY__SHIFT 0x0
+#define SCLK_CGTT_BLK_CTRL_REG__SCLK_TURN_OFF_DELAY_MASK 0xff0
+#define SCLK_CGTT_BLK_CTRL_REG__SCLK_TURN_OFF_DELAY__SHIFT 0x4
+#define SCLK_CGTT_BLK_CTRL_REG__CGTT_SCLK_OVERRIDE_MASK 0x1000
+#define SCLK_CGTT_BLK_CTRL_REG__CGTT_SCLK_OVERRIDE__SHIFT 0xc
+#define DPREFCLK_CGTT_BLK_CTRL_REG__DPREFCLK_TURN_ON_DELAY_MASK 0xf
+#define DPREFCLK_CGTT_BLK_CTRL_REG__DPREFCLK_TURN_ON_DELAY__SHIFT 0x0
+#define DPREFCLK_CGTT_BLK_CTRL_REG__DPREFCLK_TURN_OFF_DELAY_MASK 0xff0
+#define DPREFCLK_CGTT_BLK_CTRL_REG__DPREFCLK_TURN_OFF_DELAY__SHIFT 0x4
+#define REFCLK_CGTT_BLK_CTRL_REG__REFCLK_TURN_ON_DELAY_MASK 0xf
+#define REFCLK_CGTT_BLK_CTRL_REG__REFCLK_TURN_ON_DELAY__SHIFT 0x0
+#define REFCLK_CGTT_BLK_CTRL_REG__REFCLK_TURN_OFF_DELAY_MASK 0xff0
+#define REFCLK_CGTT_BLK_CTRL_REG__REFCLK_TURN_OFF_DELAY__SHIFT 0x4
+#define SYMCLK_CGTT_BLK_CTRL_REG__SYMCLK_TURN_ON_DELAY_MASK 0xf
+#define SYMCLK_CGTT_BLK_CTRL_REG__SYMCLK_TURN_ON_DELAY__SHIFT 0x0
+#define SYMCLK_CGTT_BLK_CTRL_REG__SYMCLK_TURN_OFF_DELAY_MASK 0xff0
+#define SYMCLK_CGTT_BLK_CTRL_REG__SYMCLK_TURN_OFF_DELAY__SHIFT 0x4
+#define DCCG_CAC_STATUS__CAC_STATUS_RDDATA_MASK 0xffffffff
+#define DCCG_CAC_STATUS__CAC_STATUS_RDDATA__SHIFT 0x0
+#define PIXCLK0_RESYNC_CNTL__PIXCLK0_RESYNC_ENABLE_MASK 0x1
+#define PIXCLK0_RESYNC_CNTL__PIXCLK0_RESYNC_ENABLE__SHIFT 0x0
+#define PIXCLK0_RESYNC_CNTL__DCCG_DEEP_COLOR_CNTL0_MASK 0x30
+#define PIXCLK0_RESYNC_CNTL__DCCG_DEEP_COLOR_CNTL0__SHIFT 0x4
+#define PHYPLLA_PIXCLK_RESYNC_CNTL__PHYPLLA_PIXCLK_RESYNC_ENABLE_MASK 0x1
+#define PHYPLLA_PIXCLK_RESYNC_CNTL__PHYPLLA_PIXCLK_RESYNC_ENABLE__SHIFT 0x0
+#define PHYPLLA_PIXCLK_RESYNC_CNTL__PHYPLLA_DCCG_DEEP_COLOR_CNTL_MASK 0x30
+#define PHYPLLA_PIXCLK_RESYNC_CNTL__PHYPLLA_DCCG_DEEP_COLOR_CNTL__SHIFT 0x4
+#define PHYPLLA_PIXCLK_RESYNC_CNTL__PHYPLLA_PIXCLK_ENABLE_MASK 0x100
+#define PHYPLLA_PIXCLK_RESYNC_CNTL__PHYPLLA_PIXCLK_ENABLE__SHIFT 0x8
+#define PHYPLLA_PIXCLK_RESYNC_CNTL__PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE_MASK 0x200
+#define PHYPLLA_PIXCLK_RESYNC_CNTL__PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE__SHIFT 0x9
+#define PHYPLLB_PIXCLK_RESYNC_CNTL__PHYPLLB_PIXCLK_RESYNC_ENABLE_MASK 0x1
+#define PHYPLLB_PIXCLK_RESYNC_CNTL__PHYPLLB_PIXCLK_RESYNC_ENABLE__SHIFT 0x0
+#define PHYPLLB_PIXCLK_RESYNC_CNTL__PHYPLLB_DCCG_DEEP_COLOR_CNTL_MASK 0x30
+#define PHYPLLB_PIXCLK_RESYNC_CNTL__PHYPLLB_DCCG_DEEP_COLOR_CNTL__SHIFT 0x4
+#define PHYPLLB_PIXCLK_RESYNC_CNTL__PHYPLLB_PIXCLK_ENABLE_MASK 0x100
+#define PHYPLLB_PIXCLK_RESYNC_CNTL__PHYPLLB_PIXCLK_ENABLE__SHIFT 0x8
+#define PHYPLLB_PIXCLK_RESYNC_CNTL__PHYPLLB_PIXCLK_DOUBLE_RATE_ENABLE_MASK 0x200
+#define PHYPLLB_PIXCLK_RESYNC_CNTL__PHYPLLB_PIXCLK_DOUBLE_RATE_ENABLE__SHIFT 0x9
+#define PHYPLLC_PIXCLK_RESYNC_CNTL__PHYPLLC_PIXCLK_RESYNC_ENABLE_MASK 0x1
+#define PHYPLLC_PIXCLK_RESYNC_CNTL__PHYPLLC_PIXCLK_RESYNC_ENABLE__SHIFT 0x0
+#define PHYPLLC_PIXCLK_RESYNC_CNTL__PHYPLLC_DCCG_DEEP_COLOR_CNTL_MASK 0x30
+#define PHYPLLC_PIXCLK_RESYNC_CNTL__PHYPLLC_DCCG_DEEP_COLOR_CNTL__SHIFT 0x4
+#define PHYPLLC_PIXCLK_RESYNC_CNTL__PHYPLLC_PIXCLK_ENABLE_MASK 0x100
+#define PHYPLLC_PIXCLK_RESYNC_CNTL__PHYPLLC_PIXCLK_ENABLE__SHIFT 0x8
+#define PHYPLLC_PIXCLK_RESYNC_CNTL__PHYPLLC_PIXCLK_DOUBLE_RATE_ENABLE_MASK 0x200
+#define PHYPLLC_PIXCLK_RESYNC_CNTL__PHYPLLC_PIXCLK_DOUBLE_RATE_ENABLE__SHIFT 0x9
+#define PHYPLLD_PIXCLK_RESYNC_CNTL__PHYPLLD_PIXCLK_RESYNC_ENABLE_MASK 0x1
+#define PHYPLLD_PIXCLK_RESYNC_CNTL__PHYPLLD_PIXCLK_RESYNC_ENABLE__SHIFT 0x0
+#define PHYPLLD_PIXCLK_RESYNC_CNTL__PHYPLLD_DCCG_DEEP_COLOR_CNTL_MASK 0x30
+#define PHYPLLD_PIXCLK_RESYNC_CNTL__PHYPLLD_DCCG_DEEP_COLOR_CNTL__SHIFT 0x4
+#define PHYPLLD_PIXCLK_RESYNC_CNTL__PHYPLLD_PIXCLK_ENABLE_MASK 0x100
+#define PHYPLLD_PIXCLK_RESYNC_CNTL__PHYPLLD_PIXCLK_ENABLE__SHIFT 0x8
+#define PHYPLLD_PIXCLK_RESYNC_CNTL__PHYPLLD_PIXCLK_DOUBLE_RATE_ENABLE_MASK 0x200
+#define PHYPLLD_PIXCLK_RESYNC_CNTL__PHYPLLD_PIXCLK_DOUBLE_RATE_ENABLE__SHIFT 0x9
+#define PHYPLLE_PIXCLK_RESYNC_CNTL__PHYPLLE_PIXCLK_RESYNC_ENABLE_MASK 0x1
+#define PHYPLLE_PIXCLK_RESYNC_CNTL__PHYPLLE_PIXCLK_RESYNC_ENABLE__SHIFT 0x0
+#define PHYPLLE_PIXCLK_RESYNC_CNTL__PHYPLLE_DCCG_DEEP_COLOR_CNTL_MASK 0x30
+#define PHYPLLE_PIXCLK_RESYNC_CNTL__PHYPLLE_DCCG_DEEP_COLOR_CNTL__SHIFT 0x4
+#define PHYPLLE_PIXCLK_RESYNC_CNTL__PHYPLLE_PIXCLK_ENABLE_MASK 0x100
+#define PHYPLLE_PIXCLK_RESYNC_CNTL__PHYPLLE_PIXCLK_ENABLE__SHIFT 0x8
+#define PHYPLLE_PIXCLK_RESYNC_CNTL__PHYPLLE_PIXCLK_DOUBLE_RATE_ENABLE_MASK 0x200
+#define PHYPLLE_PIXCLK_RESYNC_CNTL__PHYPLLE_PIXCLK_DOUBLE_RATE_ENABLE__SHIFT 0x9
+#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_PIXCLK_RESYNC_ENABLE_MASK 0x1
+#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_PIXCLK_RESYNC_ENABLE__SHIFT 0x0
+#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_DCCG_DEEP_COLOR_CNTL_MASK 0x30
+#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_DCCG_DEEP_COLOR_CNTL__SHIFT 0x4
+#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_PIXCLK_ENABLE_MASK 0x100
+#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_PIXCLK_ENABLE__SHIFT 0x8
+#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_PIXCLK_DOUBLE_RATE_ENABLE_MASK 0x200
+#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_PIXCLK_DOUBLE_RATE_ENABLE__SHIFT 0x9
+#define MICROSECOND_TIME_BASE_DIV__MICROSECOND_TIME_BASE_DIV_MASK 0x7f
+#define MICROSECOND_TIME_BASE_DIV__MICROSECOND_TIME_BASE_DIV__SHIFT 0x0
+#define MICROSECOND_TIME_BASE_DIV__XTAL_REF_DIV_MASK 0x7f00
+#define MICROSECOND_TIME_BASE_DIV__XTAL_REF_DIV__SHIFT 0x8
+#define MICROSECOND_TIME_BASE_DIV__XTAL_REF_SEL_MASK 0x10000
+#define MICROSECOND_TIME_BASE_DIV__XTAL_REF_SEL__SHIFT 0x10
+#define MICROSECOND_TIME_BASE_DIV__XTAL_REF_CLOCK_SOURCE_SEL_MASK 0x20000
+#define MICROSECOND_TIME_BASE_DIV__XTAL_REF_CLOCK_SOURCE_SEL__SHIFT 0x11
+#define MICROSECOND_TIME_BASE_DIV__MICROSECOND_TIME_BASE_CLOCK_SOURCE_SEL_MASK 0x100000
+#define MICROSECOND_TIME_BASE_DIV__MICROSECOND_TIME_BASE_CLOCK_SOURCE_SEL__SHIFT 0x14
+#define DCCG_DISP_CNTL_REG__ALLOW_SR_ON_TRANS_REQ_MASK 0x100
+#define DCCG_DISP_CNTL_REG__ALLOW_SR_ON_TRANS_REQ__SHIFT 0x8
+#define MILLISECOND_TIME_BASE_DIV__MILLISECOND_TIME_BASE_DIV_MASK 0x1ffff
+#define MILLISECOND_TIME_BASE_DIV__MILLISECOND_TIME_BASE_DIV__SHIFT 0x0
+#define MILLISECOND_TIME_BASE_DIV__MILLISECOND_TIME_BASE_CLOCK_SOURCE_SEL_MASK 0x100000
+#define MILLISECOND_TIME_BASE_DIV__MILLISECOND_TIME_BASE_CLOCK_SOURCE_SEL__SHIFT 0x14
+#define DISPCLK_FREQ_CHANGE_CNTL__DISPCLK_STEP_DELAY_MASK 0x3fff
+#define DISPCLK_FREQ_CHANGE_CNTL__DISPCLK_STEP_DELAY__SHIFT 0x0
+#define DISPCLK_FREQ_CHANGE_CNTL__DISPCLK_STEP_SIZE_MASK 0xf0000
+#define DISPCLK_FREQ_CHANGE_CNTL__DISPCLK_STEP_SIZE__SHIFT 0x10
+#define DISPCLK_FREQ_CHANGE_CNTL__DISPCLK_FREQ_RAMP_DONE_MASK 0x100000
+#define DISPCLK_FREQ_CHANGE_CNTL__DISPCLK_FREQ_RAMP_DONE__SHIFT 0x14
+#define DISPCLK_FREQ_CHANGE_CNTL__DISPCLK_MAX_ERRDET_CYCLES_MASK 0xe000000
+#define DISPCLK_FREQ_CHANGE_CNTL__DISPCLK_MAX_ERRDET_CYCLES__SHIFT 0x19
+#define DISPCLK_FREQ_CHANGE_CNTL__DCCG_FIFO_ERRDET_RESET_MASK 0x10000000
+#define DISPCLK_FREQ_CHANGE_CNTL__DCCG_FIFO_ERRDET_RESET__SHIFT 0x1c
+#define DISPCLK_FREQ_CHANGE_CNTL__DCCG_FIFO_ERRDET_STATE_MASK 0x20000000
+#define DISPCLK_FREQ_CHANGE_CNTL__DCCG_FIFO_ERRDET_STATE__SHIFT 0x1d
+#define DISPCLK_FREQ_CHANGE_CNTL__DCCG_FIFO_ERRDET_OVR_EN_MASK 0x40000000
+#define DISPCLK_FREQ_CHANGE_CNTL__DCCG_FIFO_ERRDET_OVR_EN__SHIFT 0x1e
+#define DISPCLK_FREQ_CHANGE_CNTL__DISPCLK_CHG_FWD_CORR_DISABLE_MASK 0x80000000
+#define DISPCLK_FREQ_CHANGE_CNTL__DISPCLK_CHG_FWD_CORR_DISABLE__SHIFT 0x1f
+#define DC_MEM_GLOBAL_PWR_REQ_CNTL__DC_MEM_GLOBAL_PWR_REQ_DIS_MASK 0x1
+#define DC_MEM_GLOBAL_PWR_REQ_CNTL__DC_MEM_GLOBAL_PWR_REQ_DIS__SHIFT 0x0
+#define DCCG_PERFMON_CNTL__DCCG_PERF_DISPCLK_ENABLE_MASK 0x1
+#define DCCG_PERFMON_CNTL__DCCG_PERF_DISPCLK_ENABLE__SHIFT 0x0
+#define DCCG_PERFMON_CNTL__DCCG_PERF_DPREFCLK_ENABLE_MASK 0x2
+#define DCCG_PERFMON_CNTL__DCCG_PERF_DPREFCLK_ENABLE__SHIFT 0x1
+#define DCCG_PERFMON_CNTL__DCCG_PERF_UNIPHYA_PIXCLK_ENABLE_MASK 0x4
+#define DCCG_PERFMON_CNTL__DCCG_PERF_UNIPHYA_PIXCLK_ENABLE__SHIFT 0x2
+#define DCCG_PERFMON_CNTL__DCCG_PERF_UNIPHYB_PIXCLK_ENABLE_MASK 0x8
+#define DCCG_PERFMON_CNTL__DCCG_PERF_UNIPHYB_PIXCLK_ENABLE__SHIFT 0x3
+#define DCCG_PERFMON_CNTL__DCCG_PERF_PIXCLK0_ENABLE_MASK 0x10
+#define DCCG_PERFMON_CNTL__DCCG_PERF_PIXCLK0_ENABLE__SHIFT 0x4
+#define DCCG_PERFMON_CNTL__DCCG_PERF_RUN_MASK 0x20
+#define DCCG_PERFMON_CNTL__DCCG_PERF_RUN__SHIFT 0x5
+#define DCCG_PERFMON_CNTL__DCCG_PERF_MODE_VSYNC_MASK 0x40
+#define DCCG_PERFMON_CNTL__DCCG_PERF_MODE_VSYNC__SHIFT 0x6
+#define DCCG_PERFMON_CNTL__DCCG_PERF_MODE_HSYNC_MASK 0x80
+#define DCCG_PERFMON_CNTL__DCCG_PERF_MODE_HSYNC__SHIFT 0x7
+#define DCCG_PERFMON_CNTL__DCCG_PERF_CRTC_SEL_MASK 0x700
+#define DCCG_PERFMON_CNTL__DCCG_PERF_CRTC_SEL__SHIFT 0x8
+#define DCCG_PERFMON_CNTL__DCCG_PERF_XTALIN_PULSE_DIV_MASK 0xfffff800
+#define DCCG_PERFMON_CNTL__DCCG_PERF_XTALIN_PULSE_DIV__SHIFT 0xb
+#define DCCG_PERFMON_CNTL2__DCCG_PERF_DSICLK_ENABLE_MASK 0x1
+#define DCCG_PERFMON_CNTL2__DCCG_PERF_DSICLK_ENABLE__SHIFT 0x0
+#define DCCG_PERFMON_CNTL2__DCCG_PERF_REFCLK_ENABLE_MASK 0x2
+#define DCCG_PERFMON_CNTL2__DCCG_PERF_REFCLK_ENABLE__SHIFT 0x1
+#define DCCG_PERFMON_CNTL2__DCCG_PERF_PIXCLK1_ENABLE_MASK 0x4
+#define DCCG_PERFMON_CNTL2__DCCG_PERF_PIXCLK1_ENABLE__SHIFT 0x2
+#define DCCG_PERFMON_CNTL2__DCCG_PERF_PIXCLK2_ENABLE_MASK 0x8
+#define DCCG_PERFMON_CNTL2__DCCG_PERF_PIXCLK2_ENABLE__SHIFT 0x3
+#define DCCG_PERFMON_CNTL2__DCCG_PERF_UNIPHYC_PIXCLK_ENABLE_MASK 0x10
+#define DCCG_PERFMON_CNTL2__DCCG_PERF_UNIPHYC_PIXCLK_ENABLE__SHIFT 0x4
+#define DCCG_PERFMON_CNTL2__DCCG_PERF_UNIPHYD_PIXCLK_ENABLE_MASK 0x20
+#define DCCG_PERFMON_CNTL2__DCCG_PERF_UNIPHYD_PIXCLK_ENABLE__SHIFT 0x5
+#define DCCG_PERFMON_CNTL2__DCCG_PERF_UNIPHYE_PIXCLK_ENABLE_MASK 0x40
+#define DCCG_PERFMON_CNTL2__DCCG_PERF_UNIPHYE_PIXCLK_ENABLE__SHIFT 0x6
+#define DCCG_PERFMON_CNTL2__DCCG_PERF_UNIPHYF_PIXCLK_ENABLE_MASK 0x80
+#define DCCG_PERFMON_CNTL2__DCCG_PERF_UNIPHYF_PIXCLK_ENABLE__SHIFT 0x7
+#define DCCG_PERFMON_CNTL2__DCCG_PERF_UNIPHYG_PIXCLK_ENABLE_MASK 0x100
+#define DCCG_PERFMON_CNTL2__DCCG_PERF_UNIPHYG_PIXCLK_ENABLE__SHIFT 0x8
+#define CRTC0_PIXEL_RATE_CNTL__CRTC0_PIXEL_RATE_SOURCE_MASK 0x3
+#define CRTC0_PIXEL_RATE_CNTL__CRTC0_PIXEL_RATE_SOURCE__SHIFT 0x0
+#define CRTC0_PIXEL_RATE_CNTL__DP_DTO0_ENABLE_MASK 0x10
+#define CRTC0_PIXEL_RATE_CNTL__DP_DTO0_ENABLE__SHIFT 0x4
+#define CRTC0_PIXEL_RATE_CNTL__DP_DTO0_DS_DISABLE_MASK 0x20
+#define CRTC0_PIXEL_RATE_CNTL__DP_DTO0_DS_DISABLE__SHIFT 0x5
+#define CRTC0_PIXEL_RATE_CNTL__CRTC0_ADD_PIXEL_MASK 0x100
+#define CRTC0_PIXEL_RATE_CNTL__CRTC0_ADD_PIXEL__SHIFT 0x8
+#define CRTC0_PIXEL_RATE_CNTL__CRTC0_DROP_PIXEL_MASK 0x200
+#define CRTC0_PIXEL_RATE_CNTL__CRTC0_DROP_PIXEL__SHIFT 0x9
+#define CRTC0_PIXEL_RATE_CNTL__CRTC0_DISPOUT_HALF_RATE_EN_MASK 0x800
+#define CRTC0_PIXEL_RATE_CNTL__CRTC0_DISPOUT_HALF_RATE_EN__SHIFT 0xb
+#define CRTC0_PIXEL_RATE_CNTL__CRTC0_DISPOUT_FIFO_ERROR_MASK 0xc000
+#define CRTC0_PIXEL_RATE_CNTL__CRTC0_DISPOUT_FIFO_ERROR__SHIFT 0xe
+#define CRTC0_PIXEL_RATE_CNTL__CRTC0_DISPOUT_ERROR_COUNT_MASK 0xfff0000
+#define CRTC0_PIXEL_RATE_CNTL__CRTC0_DISPOUT_ERROR_COUNT__SHIFT 0x10
+#define DP_DTO0_PHASE__DP_DTO0_PHASE_MASK 0xffffffff
+#define DP_DTO0_PHASE__DP_DTO0_PHASE__SHIFT 0x0
+#define DP_DTO0_MODULO__DP_DTO0_MODULO_MASK 0xffffffff
+#define DP_DTO0_MODULO__DP_DTO0_MODULO__SHIFT 0x0
+#define CRTC0_PHYPLL_PIXEL_RATE_CNTL__CRTC0_PHYPLL_PIXEL_RATE_SOURCE_MASK 0x7
+#define CRTC0_PHYPLL_PIXEL_RATE_CNTL__CRTC0_PHYPLL_PIXEL_RATE_SOURCE__SHIFT 0x0
+#define CRTC0_PHYPLL_PIXEL_RATE_CNTL__CRTC0_PIXEL_RATE_PLL_SOURCE_MASK 0x10
+#define CRTC0_PHYPLL_PIXEL_RATE_CNTL__CRTC0_PIXEL_RATE_PLL_SOURCE__SHIFT 0x4
+#define CRTC1_PIXEL_RATE_CNTL__CRTC1_PIXEL_RATE_SOURCE_MASK 0x3
+#define CRTC1_PIXEL_RATE_CNTL__CRTC1_PIXEL_RATE_SOURCE__SHIFT 0x0
+#define CRTC1_PIXEL_RATE_CNTL__DP_DTO1_ENABLE_MASK 0x10
+#define CRTC1_PIXEL_RATE_CNTL__DP_DTO1_ENABLE__SHIFT 0x4
+#define CRTC1_PIXEL_RATE_CNTL__DP_DTO1_DS_DISABLE_MASK 0x20
+#define CRTC1_PIXEL_RATE_CNTL__DP_DTO1_DS_DISABLE__SHIFT 0x5
+#define CRTC1_PIXEL_RATE_CNTL__CRTC1_ADD_PIXEL_MASK 0x100
+#define CRTC1_PIXEL_RATE_CNTL__CRTC1_ADD_PIXEL__SHIFT 0x8
+#define CRTC1_PIXEL_RATE_CNTL__CRTC1_DROP_PIXEL_MASK 0x200
+#define CRTC1_PIXEL_RATE_CNTL__CRTC1_DROP_PIXEL__SHIFT 0x9
+#define CRTC1_PIXEL_RATE_CNTL__CRTC1_DISPOUT_HALF_RATE_EN_MASK 0x800
+#define CRTC1_PIXEL_RATE_CNTL__CRTC1_DISPOUT_HALF_RATE_EN__SHIFT 0xb
+#define CRTC1_PIXEL_RATE_CNTL__CRTC1_DISPOUT_FIFO_ERROR_MASK 0xc000
+#define CRTC1_PIXEL_RATE_CNTL__CRTC1_DISPOUT_FIFO_ERROR__SHIFT 0xe
+#define CRTC1_PIXEL_RATE_CNTL__CRTC1_DISPOUT_ERROR_COUNT_MASK 0xfff0000
+#define CRTC1_PIXEL_RATE_CNTL__CRTC1_DISPOUT_ERROR_COUNT__SHIFT 0x10
+#define DP_DTO1_PHASE__DP_DTO1_PHASE_MASK 0xffffffff
+#define DP_DTO1_PHASE__DP_DTO1_PHASE__SHIFT 0x0
+#define DP_DTO1_MODULO__DP_DTO1_MODULO_MASK 0xffffffff
+#define DP_DTO1_MODULO__DP_DTO1_MODULO__SHIFT 0x0
+#define CRTC1_PHYPLL_PIXEL_RATE_CNTL__CRTC1_PHYPLL_PIXEL_RATE_SOURCE_MASK 0x7
+#define CRTC1_PHYPLL_PIXEL_RATE_CNTL__CRTC1_PHYPLL_PIXEL_RATE_SOURCE__SHIFT 0x0
+#define CRTC1_PHYPLL_PIXEL_RATE_CNTL__CRTC1_PIXEL_RATE_PLL_SOURCE_MASK 0x10
+#define CRTC1_PHYPLL_PIXEL_RATE_CNTL__CRTC1_PIXEL_RATE_PLL_SOURCE__SHIFT 0x4
+#define CRTC2_PIXEL_RATE_CNTL__CRTC2_PIXEL_RATE_SOURCE_MASK 0x3
+#define CRTC2_PIXEL_RATE_CNTL__CRTC2_PIXEL_RATE_SOURCE__SHIFT 0x0
+#define CRTC2_PIXEL_RATE_CNTL__DP_DTO2_ENABLE_MASK 0x10
+#define CRTC2_PIXEL_RATE_CNTL__DP_DTO2_ENABLE__SHIFT 0x4
+#define CRTC2_PIXEL_RATE_CNTL__DP_DTO2_DS_DISABLE_MASK 0x20
+#define CRTC2_PIXEL_RATE_CNTL__DP_DTO2_DS_DISABLE__SHIFT 0x5
+#define CRTC2_PIXEL_RATE_CNTL__CRTC2_ADD_PIXEL_MASK 0x100
+#define CRTC2_PIXEL_RATE_CNTL__CRTC2_ADD_PIXEL__SHIFT 0x8
+#define CRTC2_PIXEL_RATE_CNTL__CRTC2_DROP_PIXEL_MASK 0x200
+#define CRTC2_PIXEL_RATE_CNTL__CRTC2_DROP_PIXEL__SHIFT 0x9
+#define CRTC2_PIXEL_RATE_CNTL__CRTC2_DISPOUT_HALF_RATE_EN_MASK 0x800
+#define CRTC2_PIXEL_RATE_CNTL__CRTC2_DISPOUT_HALF_RATE_EN__SHIFT 0xb
+#define CRTC2_PIXEL_RATE_CNTL__CRTC2_DISPOUT_FIFO_ERROR_MASK 0xc000
+#define CRTC2_PIXEL_RATE_CNTL__CRTC2_DISPOUT_FIFO_ERROR__SHIFT 0xe
+#define CRTC2_PIXEL_RATE_CNTL__CRTC2_DISPOUT_ERROR_COUNT_MASK 0xfff0000
+#define CRTC2_PIXEL_RATE_CNTL__CRTC2_DISPOUT_ERROR_COUNT__SHIFT 0x10
+#define DP_DTO2_PHASE__DP_DTO2_PHASE_MASK 0xffffffff
+#define DP_DTO2_PHASE__DP_DTO2_PHASE__SHIFT 0x0
+#define DP_DTO2_MODULO__DP_DTO2_MODULO_MASK 0xffffffff
+#define DP_DTO2_MODULO__DP_DTO2_MODULO__SHIFT 0x0
+#define CRTC2_PHYPLL_PIXEL_RATE_CNTL__CRTC2_PHYPLL_PIXEL_RATE_SOURCE_MASK 0x7
+#define CRTC2_PHYPLL_PIXEL_RATE_CNTL__CRTC2_PHYPLL_PIXEL_RATE_SOURCE__SHIFT 0x0
+#define CRTC2_PHYPLL_PIXEL_RATE_CNTL__CRTC2_PIXEL_RATE_PLL_SOURCE_MASK 0x10
+#define CRTC2_PHYPLL_PIXEL_RATE_CNTL__CRTC2_PIXEL_RATE_PLL_SOURCE__SHIFT 0x4
+#define CRTC3_PIXEL_RATE_CNTL__CRTC3_PIXEL_RATE_SOURCE_MASK 0x3
+#define CRTC3_PIXEL_RATE_CNTL__CRTC3_PIXEL_RATE_SOURCE__SHIFT 0x0
+#define CRTC3_PIXEL_RATE_CNTL__DP_DTO3_ENABLE_MASK 0x10
+#define CRTC3_PIXEL_RATE_CNTL__DP_DTO3_ENABLE__SHIFT 0x4
+#define CRTC3_PIXEL_RATE_CNTL__DP_DTO3_DS_DISABLE_MASK 0x20
+#define CRTC3_PIXEL_RATE_CNTL__DP_DTO3_DS_DISABLE__SHIFT 0x5
+#define CRTC3_PIXEL_RATE_CNTL__CRTC3_ADD_PIXEL_MASK 0x100
+#define CRTC3_PIXEL_RATE_CNTL__CRTC3_ADD_PIXEL__SHIFT 0x8
+#define CRTC3_PIXEL_RATE_CNTL__CRTC3_DROP_PIXEL_MASK 0x200
+#define CRTC3_PIXEL_RATE_CNTL__CRTC3_DROP_PIXEL__SHIFT 0x9
+#define CRTC3_PIXEL_RATE_CNTL__CRTC3_DISPOUT_HALF_RATE_EN_MASK 0x800
+#define CRTC3_PIXEL_RATE_CNTL__CRTC3_DISPOUT_HALF_RATE_EN__SHIFT 0xb
+#define CRTC3_PIXEL_RATE_CNTL__CRTC3_DISPOUT_FIFO_ERROR_MASK 0xc000
+#define CRTC3_PIXEL_RATE_CNTL__CRTC3_DISPOUT_FIFO_ERROR__SHIFT 0xe
+#define CRTC3_PIXEL_RATE_CNTL__CRTC3_DISPOUT_ERROR_COUNT_MASK 0xfff0000
+#define CRTC3_PIXEL_RATE_CNTL__CRTC3_DISPOUT_ERROR_COUNT__SHIFT 0x10
+#define DP_DTO3_PHASE__DP_DTO3_PHASE_MASK 0xffffffff
+#define DP_DTO3_PHASE__DP_DTO3_PHASE__SHIFT 0x0
+#define DP_DTO3_MODULO__DP_DTO3_MODULO_MASK 0xffffffff
+#define DP_DTO3_MODULO__DP_DTO3_MODULO__SHIFT 0x0
+#define CRTC3_PHYPLL_PIXEL_RATE_CNTL__CRTC3_PHYPLL_PIXEL_RATE_SOURCE_MASK 0x7
+#define CRTC3_PHYPLL_PIXEL_RATE_CNTL__CRTC3_PHYPLL_PIXEL_RATE_SOURCE__SHIFT 0x0
+#define CRTC3_PHYPLL_PIXEL_RATE_CNTL__CRTC3_PIXEL_RATE_PLL_SOURCE_MASK 0x10
+#define CRTC3_PHYPLL_PIXEL_RATE_CNTL__CRTC3_PIXEL_RATE_PLL_SOURCE__SHIFT 0x4
+#define CRTC4_PIXEL_RATE_CNTL__CRTC4_PIXEL_RATE_SOURCE_MASK 0x3
+#define CRTC4_PIXEL_RATE_CNTL__CRTC4_PIXEL_RATE_SOURCE__SHIFT 0x0
+#define CRTC4_PIXEL_RATE_CNTL__DP_DTO4_ENABLE_MASK 0x10
+#define CRTC4_PIXEL_RATE_CNTL__DP_DTO4_ENABLE__SHIFT 0x4
+#define CRTC4_PIXEL_RATE_CNTL__DP_DTO4_DS_DISABLE_MASK 0x20
+#define CRTC4_PIXEL_RATE_CNTL__DP_DTO4_DS_DISABLE__SHIFT 0x5
+#define CRTC4_PIXEL_RATE_CNTL__CRTC4_ADD_PIXEL_MASK 0x100
+#define CRTC4_PIXEL_RATE_CNTL__CRTC4_ADD_PIXEL__SHIFT 0x8
+#define CRTC4_PIXEL_RATE_CNTL__CRTC4_DROP_PIXEL_MASK 0x200
+#define CRTC4_PIXEL_RATE_CNTL__CRTC4_DROP_PIXEL__SHIFT 0x9
+#define CRTC4_PIXEL_RATE_CNTL__CRTC4_DISPOUT_HALF_RATE_EN_MASK 0x800
+#define CRTC4_PIXEL_RATE_CNTL__CRTC4_DISPOUT_HALF_RATE_EN__SHIFT 0xb
+#define CRTC4_PIXEL_RATE_CNTL__CRTC4_DISPOUT_FIFO_ERROR_MASK 0xc000
+#define CRTC4_PIXEL_RATE_CNTL__CRTC4_DISPOUT_FIFO_ERROR__SHIFT 0xe
+#define CRTC4_PIXEL_RATE_CNTL__CRTC4_DISPOUT_ERROR_COUNT_MASK 0xfff0000
+#define CRTC4_PIXEL_RATE_CNTL__CRTC4_DISPOUT_ERROR_COUNT__SHIFT 0x10
+#define DP_DTO4_PHASE__DP_DTO4_PHASE_MASK 0xffffffff
+#define DP_DTO4_PHASE__DP_DTO4_PHASE__SHIFT 0x0
+#define DP_DTO4_MODULO__DP_DTO4_MODULO_MASK 0xffffffff
+#define DP_DTO4_MODULO__DP_DTO4_MODULO__SHIFT 0x0
+#define CRTC4_PHYPLL_PIXEL_RATE_CNTL__CRTC4_PHYPLL_PIXEL_RATE_SOURCE_MASK 0x7
+#define CRTC4_PHYPLL_PIXEL_RATE_CNTL__CRTC4_PHYPLL_PIXEL_RATE_SOURCE__SHIFT 0x0
+#define CRTC4_PHYPLL_PIXEL_RATE_CNTL__CRTC4_PIXEL_RATE_PLL_SOURCE_MASK 0x10
+#define CRTC4_PHYPLL_PIXEL_RATE_CNTL__CRTC4_PIXEL_RATE_PLL_SOURCE__SHIFT 0x4
+#define CRTC5_PIXEL_RATE_CNTL__CRTC5_PIXEL_RATE_SOURCE_MASK 0x3
+#define CRTC5_PIXEL_RATE_CNTL__CRTC5_PIXEL_RATE_SOURCE__SHIFT 0x0
+#define CRTC5_PIXEL_RATE_CNTL__DP_DTO5_ENABLE_MASK 0x10
+#define CRTC5_PIXEL_RATE_CNTL__DP_DTO5_ENABLE__SHIFT 0x4
+#define CRTC5_PIXEL_RATE_CNTL__DP_DTO5_DS_DISABLE_MASK 0x20
+#define CRTC5_PIXEL_RATE_CNTL__DP_DTO5_DS_DISABLE__SHIFT 0x5
+#define CRTC5_PIXEL_RATE_CNTL__CRTC5_ADD_PIXEL_MASK 0x100
+#define CRTC5_PIXEL_RATE_CNTL__CRTC5_ADD_PIXEL__SHIFT 0x8
+#define CRTC5_PIXEL_RATE_CNTL__CRTC5_DROP_PIXEL_MASK 0x200
+#define CRTC5_PIXEL_RATE_CNTL__CRTC5_DROP_PIXEL__SHIFT 0x9
+#define CRTC5_PIXEL_RATE_CNTL__CRTC5_DISPOUT_HALF_RATE_EN_MASK 0x800
+#define CRTC5_PIXEL_RATE_CNTL__CRTC5_DISPOUT_HALF_RATE_EN__SHIFT 0xb
+#define CRTC5_PIXEL_RATE_CNTL__CRTC5_DISPOUT_FIFO_ERROR_MASK 0xc000
+#define CRTC5_PIXEL_RATE_CNTL__CRTC5_DISPOUT_FIFO_ERROR__SHIFT 0xe
+#define CRTC5_PIXEL_RATE_CNTL__CRTC5_DISPOUT_ERROR_COUNT_MASK 0xfff0000
+#define CRTC5_PIXEL_RATE_CNTL__CRTC5_DISPOUT_ERROR_COUNT__SHIFT 0x10
+#define DP_DTO5_PHASE__DP_DTO5_PHASE_MASK 0xffffffff
+#define DP_DTO5_PHASE__DP_DTO5_PHASE__SHIFT 0x0
+#define DP_DTO5_MODULO__DP_DTO5_MODULO_MASK 0xffffffff
+#define DP_DTO5_MODULO__DP_DTO5_MODULO__SHIFT 0x0
+#define CRTC5_PHYPLL_PIXEL_RATE_CNTL__CRTC5_PHYPLL_PIXEL_RATE_SOURCE_MASK 0x7
+#define CRTC5_PHYPLL_PIXEL_RATE_CNTL__CRTC5_PHYPLL_PIXEL_RATE_SOURCE__SHIFT 0x0
+#define CRTC5_PHYPLL_PIXEL_RATE_CNTL__CRTC5_PIXEL_RATE_PLL_SOURCE_MASK 0x10
+#define CRTC5_PHYPLL_PIXEL_RATE_CNTL__CRTC5_PIXEL_RATE_PLL_SOURCE__SHIFT 0x4
+#define DCCG_SOFT_RESET__REFCLK_SOFT_RESET_MASK 0x1
+#define DCCG_SOFT_RESET__REFCLK_SOFT_RESET__SHIFT 0x0
+#define DCCG_SOFT_RESET__PCIE_REFCLK_SOFT_RESET_MASK 0x2
+#define DCCG_SOFT_RESET__PCIE_REFCLK_SOFT_RESET__SHIFT 0x1
+#define DCCG_SOFT_RESET__SOFT_RESET_DVO_MASK 0x4
+#define DCCG_SOFT_RESET__SOFT_RESET_DVO__SHIFT 0x2
+#define DCCG_SOFT_RESET__DVO_ENABLE_RST_MASK 0x8
+#define DCCG_SOFT_RESET__DVO_ENABLE_RST__SHIFT 0x3
+#define DCCG_SOFT_RESET__AUDIO_DTO2_CLK_SOFT_RESET_MASK 0x10
+#define DCCG_SOFT_RESET__AUDIO_DTO2_CLK_SOFT_RESET__SHIFT 0x4
+#define DCCG_SOFT_RESET__DPREFCLK_SOFT_RESET_MASK 0x100
+#define DCCG_SOFT_RESET__DPREFCLK_SOFT_RESET__SHIFT 0x8
+#define DCCG_SOFT_RESET__AMCLK0_SOFT_RESET_MASK 0x1000
+#define DCCG_SOFT_RESET__AMCLK0_SOFT_RESET__SHIFT 0xc
+#define DCCG_SOFT_RESET__AMCLK1_SOFT_RESET_MASK 0x2000
+#define DCCG_SOFT_RESET__AMCLK1_SOFT_RESET__SHIFT 0xd
+#define DCCG_SOFT_RESET__P0PLL_CFG_IF_SOFT_RESET_MASK 0x4000
+#define DCCG_SOFT_RESET__P0PLL_CFG_IF_SOFT_RESET__SHIFT 0xe
+#define DCCG_SOFT_RESET__P1PLL_CFG_IF_SOFT_RESET_MASK 0x8000
+#define DCCG_SOFT_RESET__P1PLL_CFG_IF_SOFT_RESET__SHIFT 0xf
+#define DCCG_SOFT_RESET__P2PLL_CFG_IF_SOFT_RESET_MASK 0x10000
+#define DCCG_SOFT_RESET__P2PLL_CFG_IF_SOFT_RESET__SHIFT 0x10
+#define DCCG_SOFT_RESET__A0PLL_CFG_IF_SOFT_RESET_MASK 0x20000
+#define DCCG_SOFT_RESET__A0PLL_CFG_IF_SOFT_RESET__SHIFT 0x11
+#define DCCG_SOFT_RESET__A1PLL_CFG_IF_SOFT_RESET_MASK 0x40000
+#define DCCG_SOFT_RESET__A1PLL_CFG_IF_SOFT_RESET__SHIFT 0x12
+#define DCCG_SOFT_RESET__C0PLL_CFG_IF_SOFT_RESET_MASK 0x80000
+#define DCCG_SOFT_RESET__C0PLL_CFG_IF_SOFT_RESET__SHIFT 0x13
+#define DCCG_SOFT_RESET__C1PLL_CFG_IF_SOFT_RESET_MASK 0x100000
+#define DCCG_SOFT_RESET__C1PLL_CFG_IF_SOFT_RESET__SHIFT 0x14
+#define DCCG_SOFT_RESET__C2PLL_CFG_IF_SOFT_RESET_MASK 0x200000
+#define DCCG_SOFT_RESET__C2PLL_CFG_IF_SOFT_RESET__SHIFT 0x15
+#define SYMCLKA_CLOCK_ENABLE__SYMCLKA_CLOCK_ENABLE_MASK 0x1
+#define SYMCLKA_CLOCK_ENABLE__SYMCLKA_CLOCK_ENABLE__SHIFT 0x0
+#define SYMCLKA_CLOCK_ENABLE__SYMCLKA_FE_FORCE_EN_MASK 0x10
+#define SYMCLKA_CLOCK_ENABLE__SYMCLKA_FE_FORCE_EN__SHIFT 0x4
+#define SYMCLKA_CLOCK_ENABLE__SYMCLKA_FE_FORCE_SRC_MASK 0x700
+#define SYMCLKA_CLOCK_ENABLE__SYMCLKA_FE_FORCE_SRC__SHIFT 0x8
+#define SYMCLKB_CLOCK_ENABLE__SYMCLKB_CLOCK_ENABLE_MASK 0x1
+#define SYMCLKB_CLOCK_ENABLE__SYMCLKB_CLOCK_ENABLE__SHIFT 0x0
+#define SYMCLKB_CLOCK_ENABLE__SYMCLKB_FE_FORCE_EN_MASK 0x10
+#define SYMCLKB_CLOCK_ENABLE__SYMCLKB_FE_FORCE_EN__SHIFT 0x4
+#define SYMCLKB_CLOCK_ENABLE__SYMCLKB_FE_FORCE_SRC_MASK 0x700
+#define SYMCLKB_CLOCK_ENABLE__SYMCLKB_FE_FORCE_SRC__SHIFT 0x8
+#define SYMCLKC_CLOCK_ENABLE__SYMCLKC_CLOCK_ENABLE_MASK 0x1
+#define SYMCLKC_CLOCK_ENABLE__SYMCLKC_CLOCK_ENABLE__SHIFT 0x0
+#define SYMCLKC_CLOCK_ENABLE__SYMCLKC_FE_FORCE_EN_MASK 0x10
+#define SYMCLKC_CLOCK_ENABLE__SYMCLKC_FE_FORCE_EN__SHIFT 0x4
+#define SYMCLKC_CLOCK_ENABLE__SYMCLKC_FE_FORCE_SRC_MASK 0x700
+#define SYMCLKC_CLOCK_ENABLE__SYMCLKC_FE_FORCE_SRC__SHIFT 0x8
+#define SYMCLKD_CLOCK_ENABLE__SYMCLKD_CLOCK_ENABLE_MASK 0x1
+#define SYMCLKD_CLOCK_ENABLE__SYMCLKD_CLOCK_ENABLE__SHIFT 0x0
+#define SYMCLKD_CLOCK_ENABLE__SYMCLKD_FE_FORCE_EN_MASK 0x10
+#define SYMCLKD_CLOCK_ENABLE__SYMCLKD_FE_FORCE_EN__SHIFT 0x4
+#define SYMCLKD_CLOCK_ENABLE__SYMCLKD_FE_FORCE_SRC_MASK 0x700
+#define SYMCLKD_CLOCK_ENABLE__SYMCLKD_FE_FORCE_SRC__SHIFT 0x8
+#define SYMCLKE_CLOCK_ENABLE__SYMCLKE_CLOCK_ENABLE_MASK 0x1
+#define SYMCLKE_CLOCK_ENABLE__SYMCLKE_CLOCK_ENABLE__SHIFT 0x0
+#define SYMCLKE_CLOCK_ENABLE__SYMCLKE_FE_FORCE_EN_MASK 0x10
+#define SYMCLKE_CLOCK_ENABLE__SYMCLKE_FE_FORCE_EN__SHIFT 0x4
+#define SYMCLKE_CLOCK_ENABLE__SYMCLKE_FE_FORCE_SRC_MASK 0x700
+#define SYMCLKE_CLOCK_ENABLE__SYMCLKE_FE_FORCE_SRC__SHIFT 0x8
+#define SYMCLKF_CLOCK_ENABLE__SYMCLKF_CLOCK_ENABLE_MASK 0x1
+#define SYMCLKF_CLOCK_ENABLE__SYMCLKF_CLOCK_ENABLE__SHIFT 0x0
+#define SYMCLKF_CLOCK_ENABLE__SYMCLKF_FE_FORCE_EN_MASK 0x10
+#define SYMCLKF_CLOCK_ENABLE__SYMCLKF_FE_FORCE_EN__SHIFT 0x4
+#define SYMCLKF_CLOCK_ENABLE__SYMCLKF_FE_FORCE_SRC_MASK 0x700
+#define SYMCLKF_CLOCK_ENABLE__SYMCLKF_FE_FORCE_SRC__SHIFT 0x8
+#define DPDBG_CLK_FORCE_CONTROL__DPDBG_CLK_FORCE_EN_MASK 0x10
+#define DPDBG_CLK_FORCE_CONTROL__DPDBG_CLK_FORCE_EN__SHIFT 0x4
+#define DPDBG_CLK_FORCE_CONTROL__DPDBG_CLK_FORCE_SRC_MASK 0x700
+#define DPDBG_CLK_FORCE_CONTROL__DPDBG_CLK_FORCE_SRC__SHIFT 0x8
+#define DCCG_AUDIO_DTO_SOURCE__DCCG_AUDIO_DTO0_SOURCE_SEL_MASK 0x7
+#define DCCG_AUDIO_DTO_SOURCE__DCCG_AUDIO_DTO0_SOURCE_SEL__SHIFT 0x0
+#define DCCG_AUDIO_DTO_SOURCE__DCCG_AUDIO_DTO_SEL_MASK 0x30
+#define DCCG_AUDIO_DTO_SOURCE__DCCG_AUDIO_DTO_SEL__SHIFT 0x4
+#define DCCG_AUDIO_DTO_SOURCE__DCCG_AUDIO_DTO2_SOURCE_SEL_MASK 0x3000
+#define DCCG_AUDIO_DTO_SOURCE__DCCG_AUDIO_DTO2_SOURCE_SEL__SHIFT 0xc
+#define DCCG_AUDIO_DTO_SOURCE__DCCG_AUDIO_DTO2_CLOCK_EN_MASK 0x10000
+#define DCCG_AUDIO_DTO_SOURCE__DCCG_AUDIO_DTO2_CLOCK_EN__SHIFT 0x10
+#define DCCG_AUDIO_DTO_SOURCE__DCCG_AUDIO_DTO2_USE_512FBR_DTO_MASK 0x100000
+#define DCCG_AUDIO_DTO_SOURCE__DCCG_AUDIO_DTO2_USE_512FBR_DTO__SHIFT 0x14
+#define DCCG_AUDIO_DTO_SOURCE__DCCG_AUDIO_DTO0_USE_512FBR_DTO_MASK 0x1000000
+#define DCCG_AUDIO_DTO_SOURCE__DCCG_AUDIO_DTO0_USE_512FBR_DTO__SHIFT 0x18
+#define DCCG_AUDIO_DTO_SOURCE__DCCG_AUDIO_DTO1_USE_512FBR_DTO_MASK 0x10000000
+#define DCCG_AUDIO_DTO_SOURCE__DCCG_AUDIO_DTO1_USE_512FBR_DTO__SHIFT 0x1c
+#define DCCG_AUDIO_DTO0_PHASE__DCCG_AUDIO_DTO0_PHASE_MASK 0xffffffff
+#define DCCG_AUDIO_DTO0_PHASE__DCCG_AUDIO_DTO0_PHASE__SHIFT 0x0
+#define DCCG_AUDIO_DTO0_MODULE__DCCG_AUDIO_DTO0_MODULE_MASK 0xffffffff
+#define DCCG_AUDIO_DTO0_MODULE__DCCG_AUDIO_DTO0_MODULE__SHIFT 0x0
+#define DCCG_AUDIO_DTO1_PHASE__DCCG_AUDIO_DTO1_PHASE_MASK 0xffffffff
+#define DCCG_AUDIO_DTO1_PHASE__DCCG_AUDIO_DTO1_PHASE__SHIFT 0x0
+#define DCCG_AUDIO_DTO1_MODULE__DCCG_AUDIO_DTO1_MODULE_MASK 0xffffffff
+#define DCCG_AUDIO_DTO1_MODULE__DCCG_AUDIO_DTO1_MODULE__SHIFT 0x0
+#define DCCG_TEST_DEBUG_INDEX__DCCG_TEST_DEBUG_INDEX_MASK 0xff
+#define DCCG_TEST_DEBUG_INDEX__DCCG_TEST_DEBUG_INDEX__SHIFT 0x0
+#define DCCG_TEST_DEBUG_INDEX__DCCG_TEST_DEBUG_WRITE_EN_MASK 0x100
+#define DCCG_TEST_DEBUG_INDEX__DCCG_TEST_DEBUG_WRITE_EN__SHIFT 0x8
+#define DCCG_TEST_DEBUG_DATA__DCCG_TEST_DEBUG_DATA_MASK 0xffffffff
+#define DCCG_TEST_DEBUG_DATA__DCCG_TEST_DEBUG_DATA__SHIFT 0x0
+#define DCCG_TEST_CLK_SEL__DCCG_TEST_CLK_GENERICA_SEL_MASK 0x1ff
+#define DCCG_TEST_CLK_SEL__DCCG_TEST_CLK_GENERICA_SEL__SHIFT 0x0
+#define DCCG_TEST_CLK_SEL__DCCG_TEST_CLK_GENERICA_INV_MASK 0x1000
+#define DCCG_TEST_CLK_SEL__DCCG_TEST_CLK_GENERICA_INV__SHIFT 0xc
+#define DCCG_TEST_CLK_SEL__DCCG_TEST_CLK_GENERICB_SEL_MASK 0x1ff0000
+#define DCCG_TEST_CLK_SEL__DCCG_TEST_CLK_GENERICB_SEL__SHIFT 0x10
+#define DCCG_TEST_CLK_SEL__DCCG_TEST_CLK_GENERICB_INV_MASK 0x10000000
+#define DCCG_TEST_CLK_SEL__DCCG_TEST_CLK_GENERICB_INV__SHIFT 0x1c
+#define CPLL_MACRO_CNTL_RESERVED0__CPLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define CPLL_MACRO_CNTL_RESERVED0__CPLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define CPLL_MACRO_CNTL_RESERVED1__CPLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define CPLL_MACRO_CNTL_RESERVED1__CPLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define CPLL_MACRO_CNTL_RESERVED2__CPLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define CPLL_MACRO_CNTL_RESERVED2__CPLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define CPLL_MACRO_CNTL_RESERVED3__CPLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define CPLL_MACRO_CNTL_RESERVED3__CPLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define CPLL_MACRO_CNTL_RESERVED4__CPLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define CPLL_MACRO_CNTL_RESERVED4__CPLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define CPLL_MACRO_CNTL_RESERVED5__CPLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define CPLL_MACRO_CNTL_RESERVED5__CPLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define CPLL_MACRO_CNTL_RESERVED6__CPLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define CPLL_MACRO_CNTL_RESERVED6__CPLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define CPLL_MACRO_CNTL_RESERVED7__CPLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define CPLL_MACRO_CNTL_RESERVED7__CPLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define CPLL_MACRO_CNTL_RESERVED8__CPLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define CPLL_MACRO_CNTL_RESERVED8__CPLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define CPLL_MACRO_CNTL_RESERVED9__CPLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define CPLL_MACRO_CNTL_RESERVED9__CPLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define CPLL_MACRO_CNTL_RESERVED10__CPLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define CPLL_MACRO_CNTL_RESERVED10__CPLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define CPLL_MACRO_CNTL_RESERVED11__CPLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define CPLL_MACRO_CNTL_RESERVED11__CPLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED0__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED0__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED1__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED1__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED2__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED2__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED3__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED3__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED4__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED4__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED5__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED5__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED6__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED6__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED7__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED7__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED8__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED8__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED9__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED9__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED10__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED10__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED11__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED11__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED12__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED12__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED13__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED13__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED14__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED14__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED15__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED15__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED16__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED16__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED17__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED17__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED18__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED18__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED19__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED19__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED20__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED20__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED21__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED21__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED22__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED22__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED23__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED23__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED24__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED24__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED25__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED25__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED26__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED26__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED27__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED27__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED28__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED28__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED29__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED29__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED30__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED30__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED31__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED31__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED32__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED32__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED33__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED33__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED34__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED34__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED35__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED35__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED36__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED36__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED37__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED37__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED38__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED38__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED39__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED39__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED40__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED40__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define PLL_MACRO_CNTL_RESERVED41__PLL_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define PLL_MACRO_CNTL_RESERVED41__PLL_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_WDIVIDER_MASK 0x7f
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_WDIVIDER__SHIFT 0x0
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_RDIVIDER_MASK 0x7f00
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_RDIVIDER__SHIFT 0x8
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_CHG_MODE_MASK 0x18000
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_CHG_MODE__SHIFT 0xf
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_CHGTOG_MASK 0x20000
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_CHGTOG__SHIFT 0x11
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_DONETOG_MASK 0x40000
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_DONETOG__SHIFT 0x12
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_CHG_DONE_MASK 0x80000
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_CHG_DONE__SHIFT 0x13
+#define DENTIST_DISPCLK_CNTL__DENTIST_DPREFCLK_CHG_DONE_MASK 0x100000
+#define DENTIST_DISPCLK_CNTL__DENTIST_DPREFCLK_CHG_DONE__SHIFT 0x14
+#define DENTIST_DISPCLK_CNTL__DENTIST_DPREFCLK_CHGTOG_MASK 0x200000
+#define DENTIST_DISPCLK_CNTL__DENTIST_DPREFCLK_CHGTOG__SHIFT 0x15
+#define DENTIST_DISPCLK_CNTL__DENTIST_DPREFCLK_DONETOG_MASK 0x400000
+#define DENTIST_DISPCLK_CNTL__DENTIST_DPREFCLK_DONETOG__SHIFT 0x16
+#define DENTIST_DISPCLK_CNTL__DENTIST_DPREFCLK_WDIVIDER_MASK 0x7f000000
+#define DENTIST_DISPCLK_CNTL__DENTIST_DPREFCLK_WDIVIDER__SHIFT 0x18
+#define DCDEBUG_BUS_CLK1_SEL__DCDEBUG_BUS_CLK1_SEL_MASK 0xffffffff
+#define DCDEBUG_BUS_CLK1_SEL__DCDEBUG_BUS_CLK1_SEL__SHIFT 0x0
+#define DCDEBUG_BUS_CLK2_SEL__DCDEBUG_BUS_CLK2_SEL_MASK 0xffffffff
+#define DCDEBUG_BUS_CLK2_SEL__DCDEBUG_BUS_CLK2_SEL__SHIFT 0x0
+#define DCDEBUG_BUS_CLK3_SEL__DCDEBUG_BUS_CLK3_SEL_MASK 0xffffffff
+#define DCDEBUG_BUS_CLK3_SEL__DCDEBUG_BUS_CLK3_SEL__SHIFT 0x0
+#define DCDEBUG_BUS_CLK4_SEL__DCDEBUG_BUS_CLK4_SEL_MASK 0xffffffff
+#define DCDEBUG_BUS_CLK4_SEL__DCDEBUG_BUS_CLK4_SEL__SHIFT 0x0
+#define DCDEBUG_BUS_CLK5_SEL__DCDEBUG_BUS_CLK5_SEL_MASK 0xffffffff
+#define DCDEBUG_BUS_CLK5_SEL__DCDEBUG_BUS_CLK5_SEL__SHIFT 0x0
+#define DCDEBUG_OUT_PIN_OVERRIDE__DCDEBUG_OUT_OVERRIDE1_PIN_SEL_MASK 0x1f
+#define DCDEBUG_OUT_PIN_OVERRIDE__DCDEBUG_OUT_OVERRIDE1_PIN_SEL__SHIFT 0x0
+#define DCDEBUG_OUT_PIN_OVERRIDE__DCDEBUG_OUT_OVERRIDE1_REGBIT_SEL_MASK 0x3e0
+#define DCDEBUG_OUT_PIN_OVERRIDE__DCDEBUG_OUT_OVERRIDE1_REGBIT_SEL__SHIFT 0x5
+#define DCDEBUG_OUT_PIN_OVERRIDE__DCDEBUG_OUT_OVERRIDE1_EN_MASK 0x1000
+#define DCDEBUG_OUT_PIN_OVERRIDE__DCDEBUG_OUT_OVERRIDE1_EN__SHIFT 0xc
+#define DCDEBUG_OUT_PIN_OVERRIDE__DCDEBUG_OUT_OVERRIDE2_PIN_SEL_MASK 0xf8000
+#define DCDEBUG_OUT_PIN_OVERRIDE__DCDEBUG_OUT_OVERRIDE2_PIN_SEL__SHIFT 0xf
+#define DCDEBUG_OUT_PIN_OVERRIDE__DCDEBUG_OUT_OVERRIDE2_REGBIT_SEL_MASK 0x1f00000
+#define DCDEBUG_OUT_PIN_OVERRIDE__DCDEBUG_OUT_OVERRIDE2_REGBIT_SEL__SHIFT 0x14
+#define DCDEBUG_OUT_PIN_OVERRIDE__DCDEBUG_OUT_OVERRIDE2_EN_MASK 0x10000000
+#define DCDEBUG_OUT_PIN_OVERRIDE__DCDEBUG_OUT_OVERRIDE2_EN__SHIFT 0x1c
+#define DCDEBUG_OUT_CNTL__DCDEBUG_BLOCK_SEL_MASK 0x1f
+#define DCDEBUG_OUT_CNTL__DCDEBUG_BLOCK_SEL__SHIFT 0x0
+#define DCDEBUG_OUT_CNTL__DCDEBUG_OUT_24BIT_SEL_MASK 0x800000
+#define DCDEBUG_OUT_CNTL__DCDEBUG_OUT_24BIT_SEL__SHIFT 0x17
+#define DCDEBUG_OUT_CNTL__DCDEBUG_CLK_SEL_MASK 0x1f000000
+#define DCDEBUG_OUT_CNTL__DCDEBUG_CLK_SEL__SHIFT 0x18
+#define DCDEBUG_OUT_DATA__DCDEBUG_OUT_DATA_MASK 0xffffffff
+#define DCDEBUG_OUT_DATA__DCDEBUG_OUT_DATA__SHIFT 0x0
+#define DMIF_CONTROL__DMIF_BUFF_SIZE_MASK 0x3
+#define DMIF_CONTROL__DMIF_BUFF_SIZE__SHIFT 0x0
+#define DMIF_CONTROL__DMIF_GROUP_REQUESTS_IN_CHUNK_MASK 0x4
+#define DMIF_CONTROL__DMIF_GROUP_REQUESTS_IN_CHUNK__SHIFT 0x2
+#define DMIF_CONTROL__DMIF_DISABLE_EARLY_RECEIVED_LEVEL_COUNT_MASK 0x10
+#define DMIF_CONTROL__DMIF_DISABLE_EARLY_RECEIVED_LEVEL_COUNT__SHIFT 0x4
+#define DMIF_CONTROL__DMIF_REQ_BURST_SIZE_MASK 0x700
+#define DMIF_CONTROL__DMIF_REQ_BURST_SIZE__SHIFT 0x8
+#define DMIF_CONTROL__DMIF_UNDERFLOW_RECOVERY_EN_MASK 0x800
+#define DMIF_CONTROL__DMIF_UNDERFLOW_RECOVERY_EN__SHIFT 0xb
+#define DMIF_CONTROL__DMIF_FORCE_TOTAL_REQ_BURST_SIZE_MASK 0x1f000
+#define DMIF_CONTROL__DMIF_FORCE_TOTAL_REQ_BURST_SIZE__SHIFT 0xc
+#define DMIF_CONTROL__DMIF_MAX_TOTAL_OUTSTANDING_CHUNK_REQUESTS_MASK 0x7e0000
+#define DMIF_CONTROL__DMIF_MAX_TOTAL_OUTSTANDING_CHUNK_REQUESTS__SHIFT 0x11
+#define DMIF_CONTROL__DMIF_DELAY_ARBITRATION_MASK 0x1f000000
+#define DMIF_CONTROL__DMIF_DELAY_ARBITRATION__SHIFT 0x18
+#define DMIF_CONTROL__DMIF_CHUNK_BUFF_MARGIN_MASK 0x60000000
+#define DMIF_CONTROL__DMIF_CHUNK_BUFF_MARGIN__SHIFT 0x1d
+#define DMIF_CONTROL__DMIF_PSTATE_URGENT_DISABLE_MASK 0x80000000
+#define DMIF_CONTROL__DMIF_PSTATE_URGENT_DISABLE__SHIFT 0x1f
+#define DMIF_STATUS__DMIF_MC_SEND_ON_IDLE_MASK 0x3f
+#define DMIF_STATUS__DMIF_MC_SEND_ON_IDLE__SHIFT 0x0
+#define DMIF_STATUS__DMIF_CLEAR_MC_SEND_ON_IDLE_MASK 0x3f00
+#define DMIF_STATUS__DMIF_CLEAR_MC_SEND_ON_IDLE__SHIFT 0x8
+#define DMIF_STATUS__DMIF_MC_LATENCY_COUNTER_ENABLE_MASK 0x10000
+#define DMIF_STATUS__DMIF_MC_LATENCY_COUNTER_ENABLE__SHIFT 0x10
+#define DMIF_STATUS__DMIF_MC_LATENCY_COUNTER_URGENT_ONLY_MASK 0x20000
+#define DMIF_STATUS__DMIF_MC_LATENCY_COUNTER_URGENT_ONLY__SHIFT 0x11
+#define DMIF_STATUS__DMIF_MC_LATENCY_COUNTER_SOURCE_SELECT_MASK 0xf00000
+#define DMIF_STATUS__DMIF_MC_LATENCY_COUNTER_SOURCE_SELECT__SHIFT 0x14
+#define DMIF_STATUS__DMIF_PERFORMANCE_COUNTER_SOURCE_SELECT_MASK 0xf000000
+#define DMIF_STATUS__DMIF_PERFORMANCE_COUNTER_SOURCE_SELECT__SHIFT 0x18
+#define DMIF_STATUS__DMIF_UNDERFLOW_MASK 0x10000000
+#define DMIF_STATUS__DMIF_UNDERFLOW__SHIFT 0x1c
+#define DMIF_STATUS__DMIF_MC_LATENCY_TAP_POINT_MASK 0x60000000
+#define DMIF_STATUS__DMIF_MC_LATENCY_TAP_POINT__SHIFT 0x1d
+#define DMIF_STATUS__DMIF_MC_LATENCY_REQ_TYPE_MASK 0x80000000
+#define DMIF_STATUS__DMIF_MC_LATENCY_REQ_TYPE__SHIFT 0x1f
+#define DMIFV_STATUS__DMIFV_MC_SEND_ON_IDLE_MASK 0xf
+#define DMIFV_STATUS__DMIFV_MC_SEND_ON_IDLE__SHIFT 0x0
+#define DMIFV_STATUS__DMIFV_CLEAR_MC_SEND_ON_IDLE_MASK 0xf00
+#define DMIFV_STATUS__DMIFV_CLEAR_MC_SEND_ON_IDLE__SHIFT 0x8
+#define DMIF_HW_DEBUG__DMIF_HW_DEBUG_MASK 0xffffffff
+#define DMIF_HW_DEBUG__DMIF_HW_DEBUG__SHIFT 0x0
+#define DMIF_ARBITRATION_CONTROL__DMIF_ARBITRATION_REFERENCE_CLOCK_PERIOD_MASK 0xffff
+#define DMIF_ARBITRATION_CONTROL__DMIF_ARBITRATION_REFERENCE_CLOCK_PERIOD__SHIFT 0x0
+#define DMIF_ARBITRATION_CONTROL__PIPE_SWITCH_EFFICIENCY_WEIGHT_MASK 0xffff0000
+#define DMIF_ARBITRATION_CONTROL__PIPE_SWITCH_EFFICIENCY_WEIGHT__SHIFT 0x10
+#define PIPE0_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT_MASK 0xffff
+#define PIPE0_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT__SHIFT 0x0
+#define PIPE1_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT_MASK 0xffff
+#define PIPE1_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT__SHIFT 0x0
+#define PIPE2_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT_MASK 0xffff
+#define PIPE2_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT__SHIFT 0x0
+#define PIPE3_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT_MASK 0xffff
+#define PIPE3_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT__SHIFT 0x0
+#define PIPE4_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT_MASK 0xffff
+#define PIPE4_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT__SHIFT 0x0
+#define PIPE5_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT_MASK 0xffff
+#define PIPE5_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT__SHIFT 0x0
+#define PIPE6_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT_MASK 0xffff
+#define PIPE6_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT__SHIFT 0x0
+#define PIPE7_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT_MASK 0xffff
+#define PIPE7_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT__SHIFT 0x0
+#define DMIF_P_VMID__P_VMID_PIPE0_MASK 0xf
+#define DMIF_P_VMID__P_VMID_PIPE0__SHIFT 0x0
+#define DMIF_P_VMID__P_VMID_PIPE1_MASK 0xf0
+#define DMIF_P_VMID__P_VMID_PIPE1__SHIFT 0x4
+#define DMIF_P_VMID__P_VMID_PIPE2_MASK 0xf00
+#define DMIF_P_VMID__P_VMID_PIPE2__SHIFT 0x8
+#define DMIF_P_VMID__P_VMID_PIPE3_MASK 0xf000
+#define DMIF_P_VMID__P_VMID_PIPE3__SHIFT 0xc
+#define DMIF_P_VMID__P_VMID_PIPE4_MASK 0xf0000
+#define DMIF_P_VMID__P_VMID_PIPE4__SHIFT 0x10
+#define DMIF_P_VMID__P_VMID_PIPE5_MASK 0xf00000
+#define DMIF_P_VMID__P_VMID_PIPE5__SHIFT 0x14
+#define DMIF_P_VMID__P_VMID_PIPE6_MASK 0xf000000
+#define DMIF_P_VMID__P_VMID_PIPE6__SHIFT 0x18
+#define DMIF_P_VMID__P_VMID_PIPE7_MASK 0xf0000000
+#define DMIF_P_VMID__P_VMID_PIPE7__SHIFT 0x1c
+#define DMIF_URG_OVERRIDE__DMIF_URG_OVERRIDE_EN_MASK 0x1
+#define DMIF_URG_OVERRIDE__DMIF_URG_OVERRIDE_EN__SHIFT 0x0
+#define DMIF_URG_OVERRIDE__DMIF_URG_OVERRIDE_LEVEL_MASK 0xf0
+#define DMIF_URG_OVERRIDE__DMIF_URG_OVERRIDE_LEVEL__SHIFT 0x4
+#define DMIF_TEST_DEBUG_INDEX__DMIF_TEST_DEBUG_INDEX_MASK 0xff
+#define DMIF_TEST_DEBUG_INDEX__DMIF_TEST_DEBUG_INDEX__SHIFT 0x0
+#define DMIF_TEST_DEBUG_INDEX__DMIF_TEST_DEBUG_WRITE_EN_MASK 0x100
+#define DMIF_TEST_DEBUG_INDEX__DMIF_TEST_DEBUG_WRITE_EN__SHIFT 0x8
+#define DMIF_TEST_DEBUG_DATA__DMIF_TEST_DEBUG_DATA_MASK 0xffffffff
+#define DMIF_TEST_DEBUG_DATA__DMIF_TEST_DEBUG_DATA__SHIFT 0x0
+#define DMIF_DEBUG02_CORE0__DB_DATA_MASK 0xffff
+#define DMIF_DEBUG02_CORE0__DB_DATA__SHIFT 0x0
+#define DMIF_DEBUG02_CORE0__MC_RDRET_COUNT_EN_MASK 0x10000
+#define DMIF_DEBUG02_CORE0__MC_RDRET_COUNT_EN__SHIFT 0x10
+#define DMIF_DEBUG02_CORE0__MC_RDRET_COUNTER_MASK 0xffe0000
+#define DMIF_DEBUG02_CORE0__MC_RDRET_COUNTER__SHIFT 0x11
+#define DMIF_DEBUG02_CORE1__DB_DATA_MASK 0xffff
+#define DMIF_DEBUG02_CORE1__DB_DATA__SHIFT 0x0
+#define DMIF_DEBUG02_CORE1__MC_RDRET_COUNT_EN_MASK 0x10000
+#define DMIF_DEBUG02_CORE1__MC_RDRET_COUNT_EN__SHIFT 0x10
+#define DMIF_DEBUG02_CORE1__MC_RDRET_COUNTER_MASK 0xffe0000
+#define DMIF_DEBUG02_CORE1__MC_RDRET_COUNTER__SHIFT 0x11
+#define DMIF_ADDR_CALC__ADDR_CONFIG_PIPE_INTERLEAVE_SIZE_MASK 0x70
+#define DMIF_ADDR_CALC__ADDR_CONFIG_PIPE_INTERLEAVE_SIZE__SHIFT 0x4
+#define DMIF_ADDR_CALC__ADDR_CONFIG_ROW_SIZE_MASK 0x30000000
+#define DMIF_ADDR_CALC__ADDR_CONFIG_ROW_SIZE__SHIFT 0x1c
+#define DMIF_STATUS2__DMIF_PIPE0_DISPCLK_STATUS_MASK 0x1
+#define DMIF_STATUS2__DMIF_PIPE0_DISPCLK_STATUS__SHIFT 0x0
+#define DMIF_STATUS2__DMIF_PIPE1_DISPCLK_STATUS_MASK 0x2
+#define DMIF_STATUS2__DMIF_PIPE1_DISPCLK_STATUS__SHIFT 0x1
+#define DMIF_STATUS2__DMIF_PIPE2_DISPCLK_STATUS_MASK 0x4
+#define DMIF_STATUS2__DMIF_PIPE2_DISPCLK_STATUS__SHIFT 0x2
+#define DMIF_STATUS2__DMIF_PIPE3_DISPCLK_STATUS_MASK 0x8
+#define DMIF_STATUS2__DMIF_PIPE3_DISPCLK_STATUS__SHIFT 0x3
+#define DMIF_STATUS2__DMIF_PIPE4_DISPCLK_STATUS_MASK 0x10
+#define DMIF_STATUS2__DMIF_PIPE4_DISPCLK_STATUS__SHIFT 0x4
+#define DMIF_STATUS2__DMIF_PIPE5_DISPCLK_STATUS_MASK 0x20
+#define DMIF_STATUS2__DMIF_PIPE5_DISPCLK_STATUS__SHIFT 0x5
+#define DMIF_STATUS2__DMIF_CHUNK_TRACKER_SCLK_STATUS_MASK 0x100
+#define DMIF_STATUS2__DMIF_CHUNK_TRACKER_SCLK_STATUS__SHIFT 0x8
+#define DMIF_STATUS2__DMIF_FBC_TRACKER_SCLK_STATUS_MASK 0x200
+#define DMIF_STATUS2__DMIF_FBC_TRACKER_SCLK_STATUS__SHIFT 0x9
+#define PIPE0_MAX_REQUESTS__MAX_REQUESTS_MASK 0x3ff
+#define PIPE0_MAX_REQUESTS__MAX_REQUESTS__SHIFT 0x0
+#define PIPE1_MAX_REQUESTS__MAX_REQUESTS_MASK 0x3ff
+#define PIPE1_MAX_REQUESTS__MAX_REQUESTS__SHIFT 0x0
+#define PIPE2_MAX_REQUESTS__MAX_REQUESTS_MASK 0x3ff
+#define PIPE2_MAX_REQUESTS__MAX_REQUESTS__SHIFT 0x0
+#define PIPE3_MAX_REQUESTS__MAX_REQUESTS_MASK 0x3ff
+#define PIPE3_MAX_REQUESTS__MAX_REQUESTS__SHIFT 0x0
+#define PIPE4_MAX_REQUESTS__MAX_REQUESTS_MASK 0x3ff
+#define PIPE4_MAX_REQUESTS__MAX_REQUESTS__SHIFT 0x0
+#define PIPE5_MAX_REQUESTS__MAX_REQUESTS_MASK 0x3ff
+#define PIPE5_MAX_REQUESTS__MAX_REQUESTS__SHIFT 0x0
+#define PIPE6_MAX_REQUESTS__MAX_REQUESTS_MASK 0x3ff
+#define PIPE6_MAX_REQUESTS__MAX_REQUESTS__SHIFT 0x0
+#define PIPE7_MAX_REQUESTS__MAX_REQUESTS_MASK 0x3ff
+#define PIPE7_MAX_REQUESTS__MAX_REQUESTS__SHIFT 0x0
+#define DVMM_REG_RD_STATUS__DVMM_REG_RD_STATUS_MASK 0x1
+#define DVMM_REG_RD_STATUS__DVMM_REG_RD_STATUS__SHIFT 0x0
+#define DVMM_REG_RD_DATA__DVMM_REG_RD_DATA_MASK 0xffffffff
+#define DVMM_REG_RD_DATA__DVMM_REG_RD_DATA__SHIFT 0x0
+#define DVMM_PTE_REQ__MAX_PTEREQ_TO_ISSUE_MASK 0xff
+#define DVMM_PTE_REQ__MAX_PTEREQ_TO_ISSUE__SHIFT 0x0
+#define DVMM_PTE_REQ__HFLIP_PTEREQ_PER_CHUNK_INT_MASK 0xff00
+#define DVMM_PTE_REQ__HFLIP_PTEREQ_PER_CHUNK_INT__SHIFT 0x8
+#define DVMM_PTE_REQ__HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER_MASK 0x3f0000
+#define DVMM_PTE_REQ__HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER__SHIFT 0x10
+#define DVMM_CNTL__PDE_CACHE_INVALIDATE_CNTL_MASK 0x3
+#define DVMM_CNTL__PDE_CACHE_INVALIDATE_CNTL__SHIFT 0x0
+#define DVMM_CNTL__DEBUG_SYSTEM_ACCESS_MODE_MASK 0x30
+#define DVMM_CNTL__DEBUG_SYSTEM_ACCESS_MODE__SHIFT 0x4
+#define DVMM_CNTL__FORCE_SYSTEM_ACCESS_MODE_MASK 0x80
+#define DVMM_CNTL__FORCE_SYSTEM_ACCESS_MODE__SHIFT 0x7
+#define DVMM_CNTL__DBG_DCE_VMID_MASK 0xf00
+#define DVMM_CNTL__DBG_DCE_VMID__SHIFT 0x8
+#define DVMM_CNTL__FORCE_DBG_DCE_VMID_MASK 0x8000
+#define DVMM_CNTL__FORCE_DBG_DCE_VMID__SHIFT 0xf
+#define DVMM_CNTL__OVERRIDE_SNOOP_MASK 0x20000
+#define DVMM_CNTL__OVERRIDE_SNOOP__SHIFT 0x11
+#define DVMM_CNTL__ENABLE_PDE_INVALIDATE_MASK 0x40000
+#define DVMM_CNTL__ENABLE_PDE_INVALIDATE__SHIFT 0x12
+#define DVMM_FAULT_STATUS__DVMM_FAULT_STATUS_MASK 0xffffffff
+#define DVMM_FAULT_STATUS__DVMM_FAULT_STATUS__SHIFT 0x0
+#define DVMM_FAULT_ADDR__DVMM_FAULT_ADDR_MASK 0xffffffff
+#define DVMM_FAULT_ADDR__DVMM_FAULT_ADDR__SHIFT 0x0
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_ENABLE_MASK 0x1
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_ENABLE__SHIFT 0x0
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_MODE_MASK 0x18
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_MODE__SHIFT 0x3
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_NUM_PIPES_MASK 0xe0
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_NUM_PIPES__SHIFT 0x5
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_NUM_BANKS_MASK 0x700
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_NUM_BANKS__SHIFT 0x8
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE_MASK 0x800
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE__SHIFT 0xb
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_ROW_SIZE_MASK 0x7000
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_ROW_SIZE__SHIFT 0xc
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_ROWS_PER_CHAN_MASK 0xfff0000
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_ROWS_PER_CHAN__SHIFT 0x10
+#define MCIF_CONTROL__MCIF_BUFF_SIZE_MASK 0x3
+#define MCIF_CONTROL__MCIF_BUFF_SIZE__SHIFT 0x0
+#define MCIF_CONTROL__ADDRESS_TRANSLATION_ENABLE_MASK 0x10
+#define MCIF_CONTROL__ADDRESS_TRANSLATION_ENABLE__SHIFT 0x4
+#define MCIF_CONTROL__PRIVILEGED_ACCESS_ENABLE_MASK 0x100
+#define MCIF_CONTROL__PRIVILEGED_ACCESS_ENABLE__SHIFT 0x8
+#define MCIF_CONTROL__MCIF_SLOW_REQ_INTERVAL_MASK 0xf000
+#define MCIF_CONTROL__MCIF_SLOW_REQ_INTERVAL__SHIFT 0xc
+#define MCIF_CONTROL__LOW_READ_URG_LEVEL_MASK 0xff0000
+#define MCIF_CONTROL__LOW_READ_URG_LEVEL__SHIFT 0x10
+#define MCIF_CONTROL__MC_CLEAN_DEASSERT_LATENCY_MASK 0x3f000000
+#define MCIF_CONTROL__MC_CLEAN_DEASSERT_LATENCY__SHIFT 0x18
+#define MCIF_CONTROL__MCIF_MC_LATENCY_COUNTER_ENABLE_MASK 0x40000000
+#define MCIF_CONTROL__MCIF_MC_LATENCY_COUNTER_ENABLE__SHIFT 0x1e
+#define MCIF_CONTROL__MCIF_MC_LATENCY_COUNTER_URGENT_ONLY_MASK 0x80000000
+#define MCIF_CONTROL__MCIF_MC_LATENCY_COUNTER_URGENT_ONLY__SHIFT 0x1f
+#define MCIF_WRITE_COMBINE_CONTROL__MCIF_WRITE_COMBINE_TIMEOUT_MASK 0xff
+#define MCIF_WRITE_COMBINE_CONTROL__MCIF_WRITE_COMBINE_TIMEOUT__SHIFT 0x0
+#define MCIF_WRITE_COMBINE_CONTROL__VIP_WRITE_COMBINE_TIMEOUT_MASK 0xff00
+#define MCIF_WRITE_COMBINE_CONTROL__VIP_WRITE_COMBINE_TIMEOUT__SHIFT 0x8
+#define MCIF_TEST_DEBUG_INDEX__MCIF_TEST_DEBUG_INDEX_MASK 0xff
+#define MCIF_TEST_DEBUG_INDEX__MCIF_TEST_DEBUG_INDEX__SHIFT 0x0
+#define MCIF_TEST_DEBUG_INDEX__MCIF_TEST_DEBUG_WRITE_EN_MASK 0x100
+#define MCIF_TEST_DEBUG_INDEX__MCIF_TEST_DEBUG_WRITE_EN__SHIFT 0x8
+#define MCIF_TEST_DEBUG_DATA__MCIF_TEST_DEBUG_DATA_MASK 0xffffffff
+#define MCIF_TEST_DEBUG_DATA__MCIF_TEST_DEBUG_DATA__SHIFT 0x0
+#define IDDCCIF02_DBG_DCCIF_C__DBG_DCCIF_C_MASK 0xffffffff
+#define IDDCCIF02_DBG_DCCIF_C__DBG_DCCIF_C__SHIFT 0x0
+#define IDDCCIF04_DBG_DCCIF_E__DBG_DCCIF_E_MASK 0xffffffff
+#define IDDCCIF04_DBG_DCCIF_E__DBG_DCCIF_E__SHIFT 0x0
+#define IDDCCIF05_DBG_DCCIF_F__DBG_DCCIF_F_MASK 0xffffffff
+#define IDDCCIF05_DBG_DCCIF_F__DBG_DCCIF_F__SHIFT 0x0
+#define MCIF_VMID__MCIF_WR_VMID_MASK 0xf
+#define MCIF_VMID__MCIF_WR_VMID__SHIFT 0x0
+#define MCIF_VMID__VIP_WR_VMID_MASK 0xf0
+#define MCIF_VMID__VIP_WR_VMID__SHIFT 0x4
+#define MCIF_MEM_CONTROL__MCIFMEM_CACHE_MODE_DIS_MASK 0x1
+#define MCIF_MEM_CONTROL__MCIFMEM_CACHE_MODE_DIS__SHIFT 0x0
+#define MCIF_MEM_CONTROL__MCIFMEM_CACHE_MODE_MASK 0x30
+#define MCIF_MEM_CONTROL__MCIFMEM_CACHE_MODE__SHIFT 0x4
+#define MCIF_MEM_CONTROL__MCIFMEM_CACHE_SIZE_MASK 0xff00
+#define MCIF_MEM_CONTROL__MCIFMEM_CACHE_SIZE__SHIFT 0x8
+#define MCIF_MEM_CONTROL__MCIFMEM_CACHE_PIPE_MASK 0x70000
+#define MCIF_MEM_CONTROL__MCIFMEM_CACHE_PIPE__SHIFT 0x10
+#define MCIF_MEM_CONTROL__MCIFMEM_CACHE_TYPE_MASK 0x180000
+#define MCIF_MEM_CONTROL__MCIFMEM_CACHE_TYPE__SHIFT 0x13
+#define CC_DC_PIPE_DIS__DC_PIPE_DIS_MASK 0x7e
+#define CC_DC_PIPE_DIS__DC_PIPE_DIS__SHIFT 0x1
+#define CC_DC_PIPE_DIS__DC_UNDERLAY_PIPE_DIS_MASK 0x3f0000
+#define CC_DC_PIPE_DIS__DC_UNDERLAY_PIPE_DIS__SHIFT 0x10
+#define MC_DC_INTERFACE_NACK_STATUS__DMIF_RDRET_NACK_OCCURRED_MASK 0x1
+#define MC_DC_INTERFACE_NACK_STATUS__DMIF_RDRET_NACK_OCCURRED__SHIFT 0x0
+#define MC_DC_INTERFACE_NACK_STATUS__DMIF_RDRET_NACK_CLEAR_MASK 0x10
+#define MC_DC_INTERFACE_NACK_STATUS__DMIF_RDRET_NACK_CLEAR__SHIFT 0x4
+#define MC_DC_INTERFACE_NACK_STATUS__VIP_WRRET_NACK_OCCURRED_MASK 0x100
+#define MC_DC_INTERFACE_NACK_STATUS__VIP_WRRET_NACK_OCCURRED__SHIFT 0x8
+#define MC_DC_INTERFACE_NACK_STATUS__VIP_WRRET_NACK_CLEAR_MASK 0x1000
+#define MC_DC_INTERFACE_NACK_STATUS__VIP_WRRET_NACK_CLEAR__SHIFT 0xc
+#define MC_DC_INTERFACE_NACK_STATUS__MCIF_RDRET_NACK_OCCURRED_MASK 0x10000
+#define MC_DC_INTERFACE_NACK_STATUS__MCIF_RDRET_NACK_OCCURRED__SHIFT 0x10
+#define MC_DC_INTERFACE_NACK_STATUS__MCIF_RDRET_NACK_CLEAR_MASK 0x100000
+#define MC_DC_INTERFACE_NACK_STATUS__MCIF_RDRET_NACK_CLEAR__SHIFT 0x14
+#define MC_DC_INTERFACE_NACK_STATUS__MCIF_WRRET_NACK_OCCURRED_MASK 0x1000000
+#define MC_DC_INTERFACE_NACK_STATUS__MCIF_WRRET_NACK_OCCURRED__SHIFT 0x18
+#define MC_DC_INTERFACE_NACK_STATUS__MCIF_WRRET_NACK_CLEAR_MASK 0x10000000
+#define MC_DC_INTERFACE_NACK_STATUS__MCIF_WRRET_NACK_CLEAR__SHIFT 0x1c
+#define RBBMIF_TIMEOUT__RBBMIF_TIMEOUT_DELAY_MASK 0xfffff
+#define RBBMIF_TIMEOUT__RBBMIF_TIMEOUT_DELAY__SHIFT 0x0
+#define RBBMIF_TIMEOUT__RBBMIF_TIMEOUT_TO_REQ_HOLD_MASK 0xfff00000
+#define RBBMIF_TIMEOUT__RBBMIF_TIMEOUT_TO_REQ_HOLD__SHIFT 0x14
+#define RBBMIF_STATUS__RBBMIF_TIMEOUT_CLIENTS_DEC_MASK 0xffff
+#define RBBMIF_STATUS__RBBMIF_TIMEOUT_CLIENTS_DEC__SHIFT 0x0
+#define RBBMIF_STATUS__RBBMIF_TIMEOUT_OP_MASK 0x10000000
+#define RBBMIF_STATUS__RBBMIF_TIMEOUT_OP__SHIFT 0x1c
+#define RBBMIF_STATUS__RBBMIF_TIMEOUT_RDWR_STATUS_MASK 0x20000000
+#define RBBMIF_STATUS__RBBMIF_TIMEOUT_RDWR_STATUS__SHIFT 0x1d
+#define RBBMIF_STATUS__RBBMIF_TIMEOUT_ACK_MASK 0x40000000
+#define RBBMIF_STATUS__RBBMIF_TIMEOUT_ACK__SHIFT 0x1e
+#define RBBMIF_STATUS__RBBMIF_TIMEOUT_MASK_MASK 0x80000000
+#define RBBMIF_STATUS__RBBMIF_TIMEOUT_MASK__SHIFT 0x1f
+#define RBBMIF_TIMEOUT_DIS__CLIENT0_TIMEOUT_DIS_MASK 0x1
+#define RBBMIF_TIMEOUT_DIS__CLIENT0_TIMEOUT_DIS__SHIFT 0x0
+#define RBBMIF_TIMEOUT_DIS__CLIENT1_TIMEOUT_DIS_MASK 0x2
+#define RBBMIF_TIMEOUT_DIS__CLIENT1_TIMEOUT_DIS__SHIFT 0x1
+#define RBBMIF_TIMEOUT_DIS__CLIENT2_TIMEOUT_DIS_MASK 0x4
+#define RBBMIF_TIMEOUT_DIS__CLIENT2_TIMEOUT_DIS__SHIFT 0x2
+#define RBBMIF_TIMEOUT_DIS__CLIENT3_TIMEOUT_DIS_MASK 0x8
+#define RBBMIF_TIMEOUT_DIS__CLIENT3_TIMEOUT_DIS__SHIFT 0x3
+#define RBBMIF_TIMEOUT_DIS__CLIENT4_TIMEOUT_DIS_MASK 0x10
+#define RBBMIF_TIMEOUT_DIS__CLIENT4_TIMEOUT_DIS__SHIFT 0x4
+#define RBBMIF_TIMEOUT_DIS__CLIENT5_TIMEOUT_DIS_MASK 0x20
+#define RBBMIF_TIMEOUT_DIS__CLIENT5_TIMEOUT_DIS__SHIFT 0x5
+#define RBBMIF_TIMEOUT_DIS__CLIENT6_TIMEOUT_DIS_MASK 0x40
+#define RBBMIF_TIMEOUT_DIS__CLIENT6_TIMEOUT_DIS__SHIFT 0x6
+#define RBBMIF_TIMEOUT_DIS__CLIENT7_TIMEOUT_DIS_MASK 0x80
+#define RBBMIF_TIMEOUT_DIS__CLIENT7_TIMEOUT_DIS__SHIFT 0x7
+#define RBBMIF_TIMEOUT_DIS__CLIENT8_TIMEOUT_DIS_MASK 0x100
+#define RBBMIF_TIMEOUT_DIS__CLIENT8_TIMEOUT_DIS__SHIFT 0x8
+#define RBBMIF_TIMEOUT_DIS__CLIENT9_TIMEOUT_DIS_MASK 0x200
+#define RBBMIF_TIMEOUT_DIS__CLIENT9_TIMEOUT_DIS__SHIFT 0x9
+#define RBBMIF_TIMEOUT_DIS__CLIENT10_TIMEOUT_DIS_MASK 0x400
+#define RBBMIF_TIMEOUT_DIS__CLIENT10_TIMEOUT_DIS__SHIFT 0xa
+#define RBBMIF_TIMEOUT_DIS__CLIENT11_TIMEOUT_DIS_MASK 0x800
+#define RBBMIF_TIMEOUT_DIS__CLIENT11_TIMEOUT_DIS__SHIFT 0xb
+#define RBBMIF_TIMEOUT_DIS__CLIENT12_TIMEOUT_DIS_MASK 0x1000
+#define RBBMIF_TIMEOUT_DIS__CLIENT12_TIMEOUT_DIS__SHIFT 0xc
+#define RBBMIF_TIMEOUT_DIS__CLIENT13_TIMEOUT_DIS_MASK 0x2000
+#define RBBMIF_TIMEOUT_DIS__CLIENT13_TIMEOUT_DIS__SHIFT 0xd
+#define RBBMIF_TIMEOUT_DIS__CLIENT14_TIMEOUT_DIS_MASK 0x4000
+#define RBBMIF_TIMEOUT_DIS__CLIENT14_TIMEOUT_DIS__SHIFT 0xe
+#define RBBMIF_TIMEOUT_DIS__CLIENT15_TIMEOUT_DIS_MASK 0x8000
+#define RBBMIF_TIMEOUT_DIS__CLIENT15_TIMEOUT_DIS__SHIFT 0xf
+#define RBBMIF_STATUS_FLAG__RBBMIF_STATE_MASK 0x3
+#define RBBMIF_STATUS_FLAG__RBBMIF_STATE__SHIFT 0x0
+#define RBBMIF_STATUS_FLAG__RBBMIF_READ_TIMEOUT_MASK 0x10
+#define RBBMIF_STATUS_FLAG__RBBMIF_READ_TIMEOUT__SHIFT 0x4
+#define RBBMIF_STATUS_FLAG__RBBMIF_FIFO_EMPTY_MASK 0x20
+#define RBBMIF_STATUS_FLAG__RBBMIF_FIFO_EMPTY__SHIFT 0x5
+#define RBBMIF_STATUS_FLAG__RBBMIF_FIFO_FULL_MASK 0x40
+#define RBBMIF_STATUS_FLAG__RBBMIF_FIFO_FULL__SHIFT 0x6
+#define DCI_MEM_PWR_STATUS__DMIF_RDREQ_MEM1_PWR_STATE_MASK 0x3
+#define DCI_MEM_PWR_STATUS__DMIF_RDREQ_MEM1_PWR_STATE__SHIFT 0x0
+#define DCI_MEM_PWR_STATUS__DMIF_RDREQ_MEM2_PWR_STATE_MASK 0xc
+#define DCI_MEM_PWR_STATUS__DMIF_RDREQ_MEM2_PWR_STATE__SHIFT 0x2
+#define DCI_MEM_PWR_STATUS__MCIF_RDREQ_MEM_PWR_STATE_MASK 0x10
+#define DCI_MEM_PWR_STATUS__MCIF_RDREQ_MEM_PWR_STATE__SHIFT 0x4
+#define DCI_MEM_PWR_STATUS__MCIF_WRREQ_MEM_PWR_STATE_MASK 0x40
+#define DCI_MEM_PWR_STATUS__MCIF_WRREQ_MEM_PWR_STATE__SHIFT 0x6
+#define DCI_MEM_PWR_STATUS__VGA_MEM_PWR_STATE_MASK 0x100
+#define DCI_MEM_PWR_STATUS__VGA_MEM_PWR_STATE__SHIFT 0x8
+#define DCI_MEM_PWR_STATUS__DMCU_ERAM_MEM_PWR_STATE_MASK 0x600
+#define DCI_MEM_PWR_STATUS__DMCU_ERAM_MEM_PWR_STATE__SHIFT 0x9
+#define DCI_MEM_PWR_STATUS__DMCU_IRAM_MEM_PWR_STATE_MASK 0x800
+#define DCI_MEM_PWR_STATUS__DMCU_IRAM_MEM_PWR_STATE__SHIFT 0xb
+#define DCI_MEM_PWR_STATUS__FBC_MEM_PWR_STATE_MASK 0x3000
+#define DCI_MEM_PWR_STATUS__FBC_MEM_PWR_STATE__SHIFT 0xc
+#define DCI_MEM_PWR_STATUS__MCIF_MEM_PWR_STATE_MASK 0xc000
+#define DCI_MEM_PWR_STATUS__MCIF_MEM_PWR_STATE__SHIFT 0xe
+#define DCI_MEM_PWR_STATUS__VIP_MEM_PWR_STATE_MASK 0x400000
+#define DCI_MEM_PWR_STATUS__VIP_MEM_PWR_STATE__SHIFT 0x16
+#define DCI_MEM_PWR_STATUS__DMIF0_ASYNC_MEM_PWR_STATE_MASK 0x3000000
+#define DCI_MEM_PWR_STATUS__DMIF0_ASYNC_MEM_PWR_STATE__SHIFT 0x18
+#define DCI_MEM_PWR_STATUS__DMIF0_DATA_MEM_PWR_STATE_MASK 0xc000000
+#define DCI_MEM_PWR_STATUS__DMIF0_DATA_MEM_PWR_STATE__SHIFT 0x1a
+#define DCI_MEM_PWR_STATUS__DMIF0_CHUNK_MEM_PWR_STATE_MASK 0x10000000
+#define DCI_MEM_PWR_STATUS__DMIF0_CHUNK_MEM_PWR_STATE__SHIFT 0x1c
+#define DCI_MEM_PWR_STATUS__DMIF_RDREQ_MEM3_PWR_STATE_MASK 0xc0000000
+#define DCI_MEM_PWR_STATUS__DMIF_RDREQ_MEM3_PWR_STATE__SHIFT 0x1e
+#define DCI_MEM_PWR_STATUS2__DMIF1_ASYNC_MEM_PWR_STATE_MASK 0x3
+#define DCI_MEM_PWR_STATUS2__DMIF1_ASYNC_MEM_PWR_STATE__SHIFT 0x0
+#define DCI_MEM_PWR_STATUS2__DMIF1_DATA_MEM_PWR_STATE_MASK 0xc
+#define DCI_MEM_PWR_STATUS2__DMIF1_DATA_MEM_PWR_STATE__SHIFT 0x2
+#define DCI_MEM_PWR_STATUS2__DMIF1_CHUNK_MEM_PWR_STATE_MASK 0x10
+#define DCI_MEM_PWR_STATUS2__DMIF1_CHUNK_MEM_PWR_STATE__SHIFT 0x4
+#define DCI_MEM_PWR_STATUS2__DMIF2_ASYNC_MEM_PWR_STATE_MASK 0x60
+#define DCI_MEM_PWR_STATUS2__DMIF2_ASYNC_MEM_PWR_STATE__SHIFT 0x5
+#define DCI_MEM_PWR_STATUS2__DMIF2_DATA_MEM_PWR_STATE_MASK 0x180
+#define DCI_MEM_PWR_STATUS2__DMIF2_DATA_MEM_PWR_STATE__SHIFT 0x7
+#define DCI_MEM_PWR_STATUS2__DMIF2_CHUNK_MEM_PWR_STATE_MASK 0x200
+#define DCI_MEM_PWR_STATUS2__DMIF2_CHUNK_MEM_PWR_STATE__SHIFT 0x9
+#define DCI_MEM_PWR_STATUS2__DMIF3_ASYNC_MEM_PWR_STATE_MASK 0xc00
+#define DCI_MEM_PWR_STATUS2__DMIF3_ASYNC_MEM_PWR_STATE__SHIFT 0xa
+#define DCI_MEM_PWR_STATUS2__DMIF3_DATA_MEM_PWR_STATE_MASK 0x3000
+#define DCI_MEM_PWR_STATUS2__DMIF3_DATA_MEM_PWR_STATE__SHIFT 0xc
+#define DCI_MEM_PWR_STATUS2__DMIF3_CHUNK_MEM_PWR_STATE_MASK 0x4000
+#define DCI_MEM_PWR_STATUS2__DMIF3_CHUNK_MEM_PWR_STATE__SHIFT 0xe
+#define DCI_MEM_PWR_STATUS2__DMIF4_ASYNC_MEM_PWR_STATE_MASK 0x18000
+#define DCI_MEM_PWR_STATUS2__DMIF4_ASYNC_MEM_PWR_STATE__SHIFT 0xf
+#define DCI_MEM_PWR_STATUS2__DMIF4_DATA_MEM_PWR_STATE_MASK 0x60000
+#define DCI_MEM_PWR_STATUS2__DMIF4_DATA_MEM_PWR_STATE__SHIFT 0x11
+#define DCI_MEM_PWR_STATUS2__DMIF4_CHUNK_MEM_PWR_STATE_MASK 0x80000
+#define DCI_MEM_PWR_STATUS2__DMIF4_CHUNK_MEM_PWR_STATE__SHIFT 0x13
+#define DCI_MEM_PWR_STATUS2__DMIF5_ASYNC_MEM_PWR_STATE_MASK 0x300000
+#define DCI_MEM_PWR_STATUS2__DMIF5_ASYNC_MEM_PWR_STATE__SHIFT 0x14
+#define DCI_MEM_PWR_STATUS2__DMIF5_DATA_MEM_PWR_STATE_MASK 0xc00000
+#define DCI_MEM_PWR_STATUS2__DMIF5_DATA_MEM_PWR_STATE__SHIFT 0x16
+#define DCI_MEM_PWR_STATUS2__DMIF5_CHUNK_MEM_PWR_STATE_MASK 0x1000000
+#define DCI_MEM_PWR_STATUS2__DMIF5_CHUNK_MEM_PWR_STATE__SHIFT 0x18
+#define DCI_MEM_PWR_STATUS3__MCIF_DWB_LUMA_MEM0_PWR_STATE_MASK 0x3
+#define DCI_MEM_PWR_STATUS3__MCIF_DWB_LUMA_MEM0_PWR_STATE__SHIFT 0x0
+#define DCI_MEM_PWR_STATUS3__MCIF_DWB_LUMA_MEM1_PWR_STATE_MASK 0xc
+#define DCI_MEM_PWR_STATUS3__MCIF_DWB_LUMA_MEM1_PWR_STATE__SHIFT 0x2
+#define DCI_MEM_PWR_STATUS3__MCIF_DWB_CHROMA_MEM0_PWR_STATE_MASK 0x30
+#define DCI_MEM_PWR_STATUS3__MCIF_DWB_CHROMA_MEM0_PWR_STATE__SHIFT 0x4
+#define DCI_MEM_PWR_STATUS3__MCIF_DWB_CHROMA_MEM1_PWR_STATE_MASK 0xc0
+#define DCI_MEM_PWR_STATUS3__MCIF_DWB_CHROMA_MEM1_PWR_STATE__SHIFT 0x6
+#define DCI_MEM_PWR_STATUS3__MCIF_CWB0_LUMA_MEM0_PWR_STATE_MASK 0x300
+#define DCI_MEM_PWR_STATUS3__MCIF_CWB0_LUMA_MEM0_PWR_STATE__SHIFT 0x8
+#define DCI_MEM_PWR_STATUS3__MCIF_CWB0_LUMA_MEM1_PWR_STATE_MASK 0xc00
+#define DCI_MEM_PWR_STATUS3__MCIF_CWB0_LUMA_MEM1_PWR_STATE__SHIFT 0xa
+#define DCI_MEM_PWR_STATUS3__MCIF_CWB0_CHROMA_MEM0_PWR_STATE_MASK 0x3000
+#define DCI_MEM_PWR_STATUS3__MCIF_CWB0_CHROMA_MEM0_PWR_STATE__SHIFT 0xc
+#define DCI_MEM_PWR_STATUS3__MCIF_CWB0_CHROMA_MEM1_PWR_STATE_MASK 0xc000
+#define DCI_MEM_PWR_STATUS3__MCIF_CWB0_CHROMA_MEM1_PWR_STATE__SHIFT 0xe
+#define DCI_MEM_PWR_STATUS3__MCIF_CWB1_LUMA_MEM0_PWR_STATE_MASK 0x30000
+#define DCI_MEM_PWR_STATUS3__MCIF_CWB1_LUMA_MEM0_PWR_STATE__SHIFT 0x10
+#define DCI_MEM_PWR_STATUS3__MCIF_CWB1_LUMA_MEM1_PWR_STATE_MASK 0xc0000
+#define DCI_MEM_PWR_STATUS3__MCIF_CWB1_LUMA_MEM1_PWR_STATE__SHIFT 0x12
+#define DCI_MEM_PWR_STATUS3__MCIF_CWB1_CHROMA_MEM0_PWR_STATE_MASK 0x300000
+#define DCI_MEM_PWR_STATUS3__MCIF_CWB1_CHROMA_MEM0_PWR_STATE__SHIFT 0x14
+#define DCI_MEM_PWR_STATUS3__MCIF_CWB1_CHROMA_MEM1_PWR_STATE_MASK 0xc00000
+#define DCI_MEM_PWR_STATUS3__MCIF_CWB1_CHROMA_MEM1_PWR_STATE__SHIFT 0x16
+#define DCI_CLK_CNTL__DCI_TEST_CLK_SEL_MASK 0x1f
+#define DCI_CLK_CNTL__DCI_TEST_CLK_SEL__SHIFT 0x0
+#define DCI_CLK_CNTL__DISPCLK_R_DCI_GATE_DIS_MASK 0x20
+#define DCI_CLK_CNTL__DISPCLK_R_DCI_GATE_DIS__SHIFT 0x5
+#define DCI_CLK_CNTL__DISPCLK_M_GATE_DIS_MASK 0x40
+#define DCI_CLK_CNTL__DISPCLK_M_GATE_DIS__SHIFT 0x6
+#define DCI_CLK_CNTL__SCLK_G_STREAM_AZ_GATE_DIS_MASK 0x80
+#define DCI_CLK_CNTL__SCLK_G_STREAM_AZ_GATE_DIS__SHIFT 0x7
+#define DCI_CLK_CNTL__SCLK_R_AZ_GATE_DIS_MASK 0x100
+#define DCI_CLK_CNTL__SCLK_R_AZ_GATE_DIS__SHIFT 0x8
+#define DCI_CLK_CNTL__DISPCLK_G_FBC_GATE_DIS_MASK 0x200
+#define DCI_CLK_CNTL__DISPCLK_G_FBC_GATE_DIS__SHIFT 0x9
+#define DCI_CLK_CNTL__DISPCLK_G_DMIFV1_L_GATE_DIS_MASK 0x400
+#define DCI_CLK_CNTL__DISPCLK_G_DMIFV1_L_GATE_DIS__SHIFT 0xa
+#define DCI_CLK_CNTL__DISPCLK_G_VGA_GATE_DIS_MASK 0x800
+#define DCI_CLK_CNTL__DISPCLK_G_VGA_GATE_DIS__SHIFT 0xb
+#define DCI_CLK_CNTL__DISPCLK_G_DMIFV1_C_GATE_DIS_MASK 0x1000
+#define DCI_CLK_CNTL__DISPCLK_G_DMIFV1_C_GATE_DIS__SHIFT 0xc
+#define DCI_CLK_CNTL__DISPCLK_G_VIP_GATE_DIS_MASK 0x2000
+#define DCI_CLK_CNTL__DISPCLK_G_VIP_GATE_DIS__SHIFT 0xd
+#define DCI_CLK_CNTL__VPCLK_POL_MASK 0x4000
+#define DCI_CLK_CNTL__VPCLK_POL__SHIFT 0xe
+#define DCI_CLK_CNTL__DISPCLK_G_DMCU_GATE_DIS_MASK 0x8000
+#define DCI_CLK_CNTL__DISPCLK_G_DMCU_GATE_DIS__SHIFT 0xf
+#define DCI_CLK_CNTL__DISPCLK_G_DMIF0_GATE_DIS_MASK 0x10000
+#define DCI_CLK_CNTL__DISPCLK_G_DMIF0_GATE_DIS__SHIFT 0x10
+#define DCI_CLK_CNTL__DISPCLK_G_DMIF1_GATE_DIS_MASK 0x20000
+#define DCI_CLK_CNTL__DISPCLK_G_DMIF1_GATE_DIS__SHIFT 0x11
+#define DCI_CLK_CNTL__DISPCLK_G_DMIF2_GATE_DIS_MASK 0x40000
+#define DCI_CLK_CNTL__DISPCLK_G_DMIF2_GATE_DIS__SHIFT 0x12
+#define DCI_CLK_CNTL__DISPCLK_G_DMIF3_GATE_DIS_MASK 0x80000
+#define DCI_CLK_CNTL__DISPCLK_G_DMIF3_GATE_DIS__SHIFT 0x13
+#define DCI_CLK_CNTL__DISPCLK_G_DMIF4_GATE_DIS_MASK 0x100000
+#define DCI_CLK_CNTL__DISPCLK_G_DMIF4_GATE_DIS__SHIFT 0x14
+#define DCI_CLK_CNTL__DISPCLK_G_DMIF5_GATE_DIS_MASK 0x200000
+#define DCI_CLK_CNTL__DISPCLK_G_DMIF5_GATE_DIS__SHIFT 0x15
+#define DCI_CLK_CNTL__SCLK_G_DMIF_GATE_DIS_MASK 0x400000
+#define DCI_CLK_CNTL__SCLK_G_DMIF_GATE_DIS__SHIFT 0x16
+#define DCI_CLK_CNTL__SCLK_G_DMIFTRK_GATE_DIS_MASK 0x800000
+#define DCI_CLK_CNTL__SCLK_G_DMIFTRK_GATE_DIS__SHIFT 0x17
+#define DCI_CLK_CNTL__SCLK_G_CNTL_AZ_GATE_DIS_MASK 0x1000000
+#define DCI_CLK_CNTL__SCLK_G_CNTL_AZ_GATE_DIS__SHIFT 0x18
+#define DCI_CLK_CNTL__DISPCLK_G_DMIFV0_L_GATE_DIS_MASK 0x2000000
+#define DCI_CLK_CNTL__DISPCLK_G_DMIFV0_L_GATE_DIS__SHIFT 0x19
+#define DCI_CLK_CNTL__DISPCLK_G_DMIFV0_C_GATE_DIS_MASK 0x4000000
+#define DCI_CLK_CNTL__DISPCLK_G_DMIFV0_C_GATE_DIS__SHIFT 0x1a
+#define DCI_CLK_CNTL__DCI_PG_TEST_CLK_SEL_MASK 0xf8000000
+#define DCI_CLK_CNTL__DCI_PG_TEST_CLK_SEL__SHIFT 0x1b
+#define DCI_CLK_RAMP_CNTL__DISPCLK_G_MCIF_DWB_GATE_DIS_MASK 0x1
+#define DCI_CLK_RAMP_CNTL__DISPCLK_G_MCIF_DWB_GATE_DIS__SHIFT 0x0
+#define DCI_CLK_RAMP_CNTL__SCLK_G_MCIF_DWB_GATE_DIS_MASK 0x2
+#define DCI_CLK_RAMP_CNTL__SCLK_G_MCIF_DWB_GATE_DIS__SHIFT 0x1
+#define DCI_CLK_RAMP_CNTL__DISPCLK_G_MCIF_CWB0_GATE_DIS_MASK 0x4
+#define DCI_CLK_RAMP_CNTL__DISPCLK_G_MCIF_CWB0_GATE_DIS__SHIFT 0x2
+#define DCI_CLK_RAMP_CNTL__SCLK_G_MCIF_CWB0_GATE_DIS_MASK 0x8
+#define DCI_CLK_RAMP_CNTL__SCLK_G_MCIF_CWB0_GATE_DIS__SHIFT 0x3
+#define DCI_CLK_RAMP_CNTL__DISPCLK_G_MCIF_CWB1_GATE_DIS_MASK 0x10
+#define DCI_CLK_RAMP_CNTL__DISPCLK_G_MCIF_CWB1_GATE_DIS__SHIFT 0x4
+#define DCI_CLK_RAMP_CNTL__SCLK_G_MCIF_CWB1_GATE_DIS_MASK 0x80000000
+#define DCI_CLK_RAMP_CNTL__SCLK_G_MCIF_CWB1_GATE_DIS__SHIFT 0x1f
+#define DCI_MEM_PWR_CNTL__DMIF_RDREQ_MEM_PWR_FORCE_MASK 0x3
+#define DCI_MEM_PWR_CNTL__DMIF_RDREQ_MEM_PWR_FORCE__SHIFT 0x0
+#define DCI_MEM_PWR_CNTL__DMIF_RDREQ_MEM_PWR_DIS_MASK 0x4
+#define DCI_MEM_PWR_CNTL__DMIF_RDREQ_MEM_PWR_DIS__SHIFT 0x2
+#define DCI_MEM_PWR_CNTL__MCIF_RDREQ_MEM_PWR_FORCE_MASK 0x8
+#define DCI_MEM_PWR_CNTL__MCIF_RDREQ_MEM_PWR_FORCE__SHIFT 0x3
+#define DCI_MEM_PWR_CNTL__MCIF_RDREQ_MEM_PWR_DIS_MASK 0x10
+#define DCI_MEM_PWR_CNTL__MCIF_RDREQ_MEM_PWR_DIS__SHIFT 0x4
+#define DCI_MEM_PWR_CNTL__MCIF_WRREQ_MEM_PWR_FORCE_MASK 0x20
+#define DCI_MEM_PWR_CNTL__MCIF_WRREQ_MEM_PWR_FORCE__SHIFT 0x5
+#define DCI_MEM_PWR_CNTL__MCIF_WRREQ_MEM_PWR_DIS_MASK 0x40
+#define DCI_MEM_PWR_CNTL__MCIF_WRREQ_MEM_PWR_DIS__SHIFT 0x6
+#define DCI_MEM_PWR_CNTL__VGA_MEM_PWR_FORCE_MASK 0x80
+#define DCI_MEM_PWR_CNTL__VGA_MEM_PWR_FORCE__SHIFT 0x7
+#define DCI_MEM_PWR_CNTL__VGA_MEM_PWR_DIS_MASK 0x100
+#define DCI_MEM_PWR_CNTL__VGA_MEM_PWR_DIS__SHIFT 0x8
+#define DCI_MEM_PWR_CNTL__DMCU_ERAM_MEM_PWR_FORCE_MASK 0x600
+#define DCI_MEM_PWR_CNTL__DMCU_ERAM_MEM_PWR_FORCE__SHIFT 0x9
+#define DCI_MEM_PWR_CNTL__DMCU_ERAM_MEM_PWR_DIS_MASK 0x800
+#define DCI_MEM_PWR_CNTL__DMCU_ERAM_MEM_PWR_DIS__SHIFT 0xb
+#define DCI_MEM_PWR_CNTL__DMCU_IRAM_MEM_PWR_FORCE_MASK 0x1000
+#define DCI_MEM_PWR_CNTL__DMCU_IRAM_MEM_PWR_FORCE__SHIFT 0xc
+#define DCI_MEM_PWR_CNTL__DMCU_IRAM_MEM_PWR_DIS_MASK 0x2000
+#define DCI_MEM_PWR_CNTL__DMCU_IRAM_MEM_PWR_DIS__SHIFT 0xd
+#define DCI_MEM_PWR_CNTL__FBC_MEM_PWR_FORCE_MASK 0xc000
+#define DCI_MEM_PWR_CNTL__FBC_MEM_PWR_FORCE__SHIFT 0xe
+#define DCI_MEM_PWR_CNTL__FBC_MEM_PWR_DIS_MASK 0x10000
+#define DCI_MEM_PWR_CNTL__FBC_MEM_PWR_DIS__SHIFT 0x10
+#define DCI_MEM_PWR_CNTL__MCIF_MEM_PWR_FORCE_MASK 0x60000
+#define DCI_MEM_PWR_CNTL__MCIF_MEM_PWR_FORCE__SHIFT 0x11
+#define DCI_MEM_PWR_CNTL__MCIF_MEM_PWR_DIS_MASK 0x80000
+#define DCI_MEM_PWR_CNTL__MCIF_MEM_PWR_DIS__SHIFT 0x13
+#define DCI_MEM_PWR_CNTL__MCIF_DWB_MEM_PWR_FORCE_MASK 0x300000
+#define DCI_MEM_PWR_CNTL__MCIF_DWB_MEM_PWR_FORCE__SHIFT 0x14
+#define DCI_MEM_PWR_CNTL__MCIF_DWB_MEM_PWR_DIS_MASK 0x400000
+#define DCI_MEM_PWR_CNTL__MCIF_DWB_MEM_PWR_DIS__SHIFT 0x16
+#define DCI_MEM_PWR_CNTL__MCIF_CWB0_MEM_PWR_FORCE_MASK 0x1800000
+#define DCI_MEM_PWR_CNTL__MCIF_CWB0_MEM_PWR_FORCE__SHIFT 0x17
+#define DCI_MEM_PWR_CNTL__MCIF_CWB0_MEM_PWR_DIS_MASK 0x2000000
+#define DCI_MEM_PWR_CNTL__MCIF_CWB0_MEM_PWR_DIS__SHIFT 0x19
+#define DCI_MEM_PWR_CNTL__MCIF_CWB1_MEM_PWR_FORCE_MASK 0xc000000
+#define DCI_MEM_PWR_CNTL__MCIF_CWB1_MEM_PWR_FORCE__SHIFT 0x1a
+#define DCI_MEM_PWR_CNTL__MCIF_CWB1_MEM_PWR_DIS_MASK 0x10000000
+#define DCI_MEM_PWR_CNTL__MCIF_CWB1_MEM_PWR_DIS__SHIFT 0x1c
+#define DCI_MEM_PWR_CNTL__VIP_MEM_PWR_FORCE_MASK 0x20000000
+#define DCI_MEM_PWR_CNTL__VIP_MEM_PWR_FORCE__SHIFT 0x1d
+#define DCI_MEM_PWR_CNTL__VIP_MEM_PWR_DIS_MASK 0x40000000
+#define DCI_MEM_PWR_CNTL__VIP_MEM_PWR_DIS__SHIFT 0x1e
+#define DCI_MEM_PWR_CNTL2__DMIF0_ASYNC_MEM_PWR_FORCE_MASK 0x3
+#define DCI_MEM_PWR_CNTL2__DMIF0_ASYNC_MEM_PWR_FORCE__SHIFT 0x0
+#define DCI_MEM_PWR_CNTL2__DMIF0_ASYNC_MEM_PWR_DIS_MASK 0x4
+#define DCI_MEM_PWR_CNTL2__DMIF0_ASYNC_MEM_PWR_DIS__SHIFT 0x2
+#define DCI_MEM_PWR_CNTL2__DMIF0_DATA_MEM_PWR_FORCE_MASK 0x18
+#define DCI_MEM_PWR_CNTL2__DMIF0_DATA_MEM_PWR_FORCE__SHIFT 0x3
+#define DCI_MEM_PWR_CNTL2__DMIF0_DATA_MEM_PWR_DIS_MASK 0x20
+#define DCI_MEM_PWR_CNTL2__DMIF0_DATA_MEM_PWR_DIS__SHIFT 0x5
+#define DCI_MEM_PWR_CNTL2__DMIF0_CHUNK_MEM_PWR_FORCE_MASK 0x40
+#define DCI_MEM_PWR_CNTL2__DMIF0_CHUNK_MEM_PWR_FORCE__SHIFT 0x6
+#define DCI_MEM_PWR_CNTL2__DMIF0_CHUNK_MEM_PWR_DIS_MASK 0x80
+#define DCI_MEM_PWR_CNTL2__DMIF0_CHUNK_MEM_PWR_DIS__SHIFT 0x7
+#define DCI_MEM_PWR_CNTL2__DMIF1_ASYNC_MEM_PWR_FORCE_MASK 0x300
+#define DCI_MEM_PWR_CNTL2__DMIF1_ASYNC_MEM_PWR_FORCE__SHIFT 0x8
+#define DCI_MEM_PWR_CNTL2__DMIF1_ASYNC_MEM_PWR_DIS_MASK 0x400
+#define DCI_MEM_PWR_CNTL2__DMIF1_ASYNC_MEM_PWR_DIS__SHIFT 0xa
+#define DCI_MEM_PWR_CNTL2__DMIF1_DATA_MEM_PWR_FORCE_MASK 0x1800
+#define DCI_MEM_PWR_CNTL2__DMIF1_DATA_MEM_PWR_FORCE__SHIFT 0xb
+#define DCI_MEM_PWR_CNTL2__DMIF1_DATA_MEM_PWR_DIS_MASK 0x2000
+#define DCI_MEM_PWR_CNTL2__DMIF1_DATA_MEM_PWR_DIS__SHIFT 0xd
+#define DCI_MEM_PWR_CNTL2__DMIF1_CHUNK_MEM_PWR_FORCE_MASK 0x4000
+#define DCI_MEM_PWR_CNTL2__DMIF1_CHUNK_MEM_PWR_FORCE__SHIFT 0xe
+#define DCI_MEM_PWR_CNTL2__DMIF1_CHUNK_MEM_PWR_DIS_MASK 0x8000
+#define DCI_MEM_PWR_CNTL2__DMIF1_CHUNK_MEM_PWR_DIS__SHIFT 0xf
+#define DCI_MEM_PWR_CNTL2__DMIF2_ASYNC_MEM_PWR_FORCE_MASK 0x30000
+#define DCI_MEM_PWR_CNTL2__DMIF2_ASYNC_MEM_PWR_FORCE__SHIFT 0x10
+#define DCI_MEM_PWR_CNTL2__DMIF2_ASYNC_MEM_PWR_DIS_MASK 0x40000
+#define DCI_MEM_PWR_CNTL2__DMIF2_ASYNC_MEM_PWR_DIS__SHIFT 0x12
+#define DCI_MEM_PWR_CNTL2__DMIF2_DATA_MEM_PWR_FORCE_MASK 0x180000
+#define DCI_MEM_PWR_CNTL2__DMIF2_DATA_MEM_PWR_FORCE__SHIFT 0x13
+#define DCI_MEM_PWR_CNTL2__DMIF2_DATA_MEM_PWR_DIS_MASK 0x200000
+#define DCI_MEM_PWR_CNTL2__DMIF2_DATA_MEM_PWR_DIS__SHIFT 0x15
+#define DCI_MEM_PWR_CNTL2__DMIF2_CHUNK_MEM_PWR_FORCE_MASK 0x400000
+#define DCI_MEM_PWR_CNTL2__DMIF2_CHUNK_MEM_PWR_FORCE__SHIFT 0x16
+#define DCI_MEM_PWR_CNTL2__DMIF2_CHUNK_MEM_PWR_DIS_MASK 0x800000
+#define DCI_MEM_PWR_CNTL2__DMIF2_CHUNK_MEM_PWR_DIS__SHIFT 0x17
+#define DCI_MEM_PWR_CNTL2__DMIF3_ASYNC_MEM_PWR_FORCE_MASK 0x3000000
+#define DCI_MEM_PWR_CNTL2__DMIF3_ASYNC_MEM_PWR_FORCE__SHIFT 0x18
+#define DCI_MEM_PWR_CNTL2__DMIF3_ASYNC_MEM_PWR_DIS_MASK 0x4000000
+#define DCI_MEM_PWR_CNTL2__DMIF3_ASYNC_MEM_PWR_DIS__SHIFT 0x1a
+#define DCI_MEM_PWR_CNTL2__DMIF3_DATA_MEM_PWR_FORCE_MASK 0x18000000
+#define DCI_MEM_PWR_CNTL2__DMIF3_DATA_MEM_PWR_FORCE__SHIFT 0x1b
+#define DCI_MEM_PWR_CNTL2__DMIF3_DATA_MEM_PWR_DIS_MASK 0x20000000
+#define DCI_MEM_PWR_CNTL2__DMIF3_DATA_MEM_PWR_DIS__SHIFT 0x1d
+#define DCI_MEM_PWR_CNTL2__DMIF3_CHUNK_MEM_PWR_FORCE_MASK 0x40000000
+#define DCI_MEM_PWR_CNTL2__DMIF3_CHUNK_MEM_PWR_FORCE__SHIFT 0x1e
+#define DCI_MEM_PWR_CNTL2__DMIF3_CHUNK_MEM_PWR_DIS_MASK 0x80000000
+#define DCI_MEM_PWR_CNTL2__DMIF3_CHUNK_MEM_PWR_DIS__SHIFT 0x1f
+#define DCI_MEM_PWR_CNTL3__DMIF4_ASYNC_MEM_PWR_FORCE_MASK 0x3
+#define DCI_MEM_PWR_CNTL3__DMIF4_ASYNC_MEM_PWR_FORCE__SHIFT 0x0
+#define DCI_MEM_PWR_CNTL3__DMIF4_ASYNC_MEM_PWR_DIS_MASK 0x4
+#define DCI_MEM_PWR_CNTL3__DMIF4_ASYNC_MEM_PWR_DIS__SHIFT 0x2
+#define DCI_MEM_PWR_CNTL3__DMIF4_DATA_MEM_PWR_FORCE_MASK 0x18
+#define DCI_MEM_PWR_CNTL3__DMIF4_DATA_MEM_PWR_FORCE__SHIFT 0x3
+#define DCI_MEM_PWR_CNTL3__DMIF4_DATA_MEM_PWR_DIS_MASK 0x20
+#define DCI_MEM_PWR_CNTL3__DMIF4_DATA_MEM_PWR_DIS__SHIFT 0x5
+#define DCI_MEM_PWR_CNTL3__DMIF4_CHUNK_MEM_PWR_FORCE_MASK 0x40
+#define DCI_MEM_PWR_CNTL3__DMIF4_CHUNK_MEM_PWR_FORCE__SHIFT 0x6
+#define DCI_MEM_PWR_CNTL3__DMIF4_CHUNK_MEM_PWR_DIS_MASK 0x80
+#define DCI_MEM_PWR_CNTL3__DMIF4_CHUNK_MEM_PWR_DIS__SHIFT 0x7
+#define DCI_MEM_PWR_CNTL3__DMIF5_ASYNC_MEM_PWR_FORCE_MASK 0x300
+#define DCI_MEM_PWR_CNTL3__DMIF5_ASYNC_MEM_PWR_FORCE__SHIFT 0x8
+#define DCI_MEM_PWR_CNTL3__DMIF5_ASYNC_MEM_PWR_DIS_MASK 0x400
+#define DCI_MEM_PWR_CNTL3__DMIF5_ASYNC_MEM_PWR_DIS__SHIFT 0xa
+#define DCI_MEM_PWR_CNTL3__DMIF5_DATA_MEM_PWR_FORCE_MASK 0x1800
+#define DCI_MEM_PWR_CNTL3__DMIF5_DATA_MEM_PWR_FORCE__SHIFT 0xb
+#define DCI_MEM_PWR_CNTL3__DMIF5_DATA_MEM_PWR_DIS_MASK 0x2000
+#define DCI_MEM_PWR_CNTL3__DMIF5_DATA_MEM_PWR_DIS__SHIFT 0xd
+#define DCI_MEM_PWR_CNTL3__DMIF5_CHUNK_MEM_PWR_FORCE_MASK 0x4000
+#define DCI_MEM_PWR_CNTL3__DMIF5_CHUNK_MEM_PWR_FORCE__SHIFT 0xe
+#define DCI_MEM_PWR_CNTL3__DMIF5_CHUNK_MEM_PWR_DIS_MASK 0x8000
+#define DCI_MEM_PWR_CNTL3__DMIF5_CHUNK_MEM_PWR_DIS__SHIFT 0xf
+#define DCI_MEM_PWR_CNTL3__DMIF_RDREQ_MEM_PWR_MODE_SEL_MASK 0x30000
+#define DCI_MEM_PWR_CNTL3__DMIF_RDREQ_MEM_PWR_MODE_SEL__SHIFT 0x10
+#define DCI_MEM_PWR_CNTL3__DMIF_ASYNC_MEM_PWR_MODE_SEL_MASK 0xc0000
+#define DCI_MEM_PWR_CNTL3__DMIF_ASYNC_MEM_PWR_MODE_SEL__SHIFT 0x12
+#define DCI_MEM_PWR_CNTL3__DMIF_DATA_MEM_PWR_MODE_SEL_MASK 0x300000
+#define DCI_MEM_PWR_CNTL3__DMIF_DATA_MEM_PWR_MODE_SEL__SHIFT 0x14
+#define DCI_MEM_PWR_CNTL3__DMCU_ERAM_MEM_PWR_MODE_SEL_MASK 0x400000
+#define DCI_MEM_PWR_CNTL3__DMCU_ERAM_MEM_PWR_MODE_SEL__SHIFT 0x16
+#define DCI_MEM_PWR_CNTL3__FBC_MEM_PWR_MODE_SEL_MASK 0x1800000
+#define DCI_MEM_PWR_CNTL3__FBC_MEM_PWR_MODE_SEL__SHIFT 0x17
+#define DCI_MEM_PWR_CNTL3__MCIF_CWB0_MEM_PWR_MODE_SEL_MASK 0x6000000
+#define DCI_MEM_PWR_CNTL3__MCIF_CWB0_MEM_PWR_MODE_SEL__SHIFT 0x19
+#define DCI_MEM_PWR_CNTL3__MCIF_CWB1_MEM_PWR_MODE_SEL_MASK 0x18000000
+#define DCI_MEM_PWR_CNTL3__MCIF_CWB1_MEM_PWR_MODE_SEL__SHIFT 0x1b
+#define DCI_MEM_PWR_CNTL3__MCIF_DWB_MEM_PWR_MODE_SEL_MASK 0x60000000
+#define DCI_MEM_PWR_CNTL3__MCIF_DWB_MEM_PWR_MODE_SEL__SHIFT 0x1d
+#define DCI_MEM_PWR_CNTL4__MCIF_DWB_LUMA_MEM_EN_NUM_MASK 0x1
+#define DCI_MEM_PWR_CNTL4__MCIF_DWB_LUMA_MEM_EN_NUM__SHIFT 0x0
+#define DCI_MEM_PWR_CNTL4__MCIF_DWB_CHROMA_MEM_EN_NUM_MASK 0x2
+#define DCI_MEM_PWR_CNTL4__MCIF_DWB_CHROMA_MEM_EN_NUM__SHIFT 0x1
+#define DCI_MEM_PWR_CNTL4__MCIF_CWB0_LUMA_MEM_EN_NUM_MASK 0x4
+#define DCI_MEM_PWR_CNTL4__MCIF_CWB0_LUMA_MEM_EN_NUM__SHIFT 0x2
+#define DCI_MEM_PWR_CNTL4__MCIF_CWB0_CHROMA_MEM_EN_NUM_MASK 0x8
+#define DCI_MEM_PWR_CNTL4__MCIF_CWB0_CHROMA_MEM_EN_NUM__SHIFT 0x3
+#define DCI_MEM_PWR_CNTL4__MCIF_CWB1_LUMA_MEM_EN_NUM_MASK 0x10
+#define DCI_MEM_PWR_CNTL4__MCIF_CWB1_LUMA_MEM_EN_NUM__SHIFT 0x4
+#define DCI_MEM_PWR_CNTL4__MCIF_CWB1_CHROMA_MEM_EN_NUM_MASK 0x20
+#define DCI_MEM_PWR_CNTL4__MCIF_CWB1_CHROMA_MEM_EN_NUM__SHIFT 0x5
+#define DVMM_PTE_PGMEM_CONTROL__DVMM_PTE0_MEM_PWR_FORCE_MASK 0x3
+#define DVMM_PTE_PGMEM_CONTROL__DVMM_PTE0_MEM_PWR_FORCE__SHIFT 0x0
+#define DVMM_PTE_PGMEM_CONTROL__DVMM_PTE0_MEM_PWR_DIS_MASK 0x4
+#define DVMM_PTE_PGMEM_CONTROL__DVMM_PTE0_MEM_PWR_DIS__SHIFT 0x2
+#define DVMM_PTE_PGMEM_CONTROL__DVMM_PTE1_MEM_PWR_FORCE_MASK 0x18
+#define DVMM_PTE_PGMEM_CONTROL__DVMM_PTE1_MEM_PWR_FORCE__SHIFT 0x3
+#define DVMM_PTE_PGMEM_CONTROL__DVMM_PTE1_MEM_PWR_DIS_MASK 0x20
+#define DVMM_PTE_PGMEM_CONTROL__DVMM_PTE1_MEM_PWR_DIS__SHIFT 0x5
+#define DVMM_PTE_PGMEM_CONTROL__DVMM_PTE2_MEM_PWR_FORCE_MASK 0xc0
+#define DVMM_PTE_PGMEM_CONTROL__DVMM_PTE2_MEM_PWR_FORCE__SHIFT 0x6
+#define DVMM_PTE_PGMEM_CONTROL__DVMM_PTE2_MEM_PWR_DIS_MASK 0x100
+#define DVMM_PTE_PGMEM_CONTROL__DVMM_PTE2_MEM_PWR_DIS__SHIFT 0x8
+#define DVMM_PTE_PGMEM_CONTROL__DVMM_PTE3_MEM_PWR_FORCE_MASK 0x600
+#define DVMM_PTE_PGMEM_CONTROL__DVMM_PTE3_MEM_PWR_FORCE__SHIFT 0x9
+#define DVMM_PTE_PGMEM_CONTROL__DVMM_PTE3_MEM_PWR_DIS_MASK 0x800
+#define DVMM_PTE_PGMEM_CONTROL__DVMM_PTE3_MEM_PWR_DIS__SHIFT 0xb
+#define DVMM_PTE_PGMEM_CONTROL__DVMM_PTE4_MEM_PWR_FORCE_MASK 0x3000
+#define DVMM_PTE_PGMEM_CONTROL__DVMM_PTE4_MEM_PWR_FORCE__SHIFT 0xc
+#define DVMM_PTE_PGMEM_CONTROL__DVMM_PTE4_MEM_PWR_DIS_MASK 0x4000
+#define DVMM_PTE_PGMEM_CONTROL__DVMM_PTE4_MEM_PWR_DIS__SHIFT 0xe
+#define DVMM_PTE_PGMEM_CONTROL__DVMM_PTE5_MEM_PWR_FORCE_MASK 0x18000
+#define DVMM_PTE_PGMEM_CONTROL__DVMM_PTE5_MEM_PWR_FORCE__SHIFT 0xf
+#define DVMM_PTE_PGMEM_CONTROL__DVMM_PTE5_MEM_PWR_DIS_MASK 0x20000
+#define DVMM_PTE_PGMEM_CONTROL__DVMM_PTE5_MEM_PWR_DIS__SHIFT 0x11
+#define DVMM_PTE_PGMEM_CONTROL__DVMM_PTE6_MEM_PWR_FORCE_MASK 0xc0000
+#define DVMM_PTE_PGMEM_CONTROL__DVMM_PTE6_MEM_PWR_FORCE__SHIFT 0x12
+#define DVMM_PTE_PGMEM_CONTROL__DVMM_PTE6_MEM_PWR_DIS_MASK 0x100000
+#define DVMM_PTE_PGMEM_CONTROL__DVMM_PTE6_MEM_PWR_DIS__SHIFT 0x14
+#define DVMM_PTE_PGMEM_CONTROL__DVMM_PTE7_MEM_PWR_FORCE_MASK 0x600000
+#define DVMM_PTE_PGMEM_CONTROL__DVMM_PTE7_MEM_PWR_FORCE__SHIFT 0x15
+#define DVMM_PTE_PGMEM_CONTROL__DVMM_PTE7_MEM_PWR_DIS_MASK 0x800000
+#define DVMM_PTE_PGMEM_CONTROL__DVMM_PTE7_MEM_PWR_DIS__SHIFT 0x17
+#define DVMM_PTE_PGMEM_CONTROL__DVMM_PTE_MEM_PWR_MODE_SEL_MASK 0x3000000
+#define DVMM_PTE_PGMEM_CONTROL__DVMM_PTE_MEM_PWR_MODE_SEL__SHIFT 0x18
+#define DVMM_PTE_PGMEM_STATE__DVMM_PIPE0_PTE_PGMEM_STATE_MASK 0x3
+#define DVMM_PTE_PGMEM_STATE__DVMM_PIPE0_PTE_PGMEM_STATE__SHIFT 0x0
+#define DVMM_PTE_PGMEM_STATE__DVMM_PIPE1_PTE_PGMEM_STATE_MASK 0xc
+#define DVMM_PTE_PGMEM_STATE__DVMM_PIPE1_PTE_PGMEM_STATE__SHIFT 0x2
+#define DVMM_PTE_PGMEM_STATE__DVMM_PIPE2_PTE_PGMEM_STATE_MASK 0x30
+#define DVMM_PTE_PGMEM_STATE__DVMM_PIPE2_PTE_PGMEM_STATE__SHIFT 0x4
+#define DVMM_PTE_PGMEM_STATE__DVMM_PIPE3_PTE_PGMEM_STATE_MASK 0xc0
+#define DVMM_PTE_PGMEM_STATE__DVMM_PIPE3_PTE_PGMEM_STATE__SHIFT 0x6
+#define DVMM_PTE_PGMEM_STATE__DVMM_PIPE4_PTE_PGMEM_STATE_MASK 0x300
+#define DVMM_PTE_PGMEM_STATE__DVMM_PIPE4_PTE_PGMEM_STATE__SHIFT 0x8
+#define DVMM_PTE_PGMEM_STATE__DVMM_PIPE5_PTE_PGMEM_STATE_MASK 0xc00
+#define DVMM_PTE_PGMEM_STATE__DVMM_PIPE5_PTE_PGMEM_STATE__SHIFT 0xa
+#define DVMM_PTE_PGMEM_STATE__DVMM_PIPE6_PTE_PGMEM_STATE_MASK 0x3000
+#define DVMM_PTE_PGMEM_STATE__DVMM_PIPE6_PTE_PGMEM_STATE__SHIFT 0xc
+#define DVMM_PTE_PGMEM_STATE__DVMM_PIPE7_PTE_PGMEM_STATE_MASK 0xc000
+#define DVMM_PTE_PGMEM_STATE__DVMM_PIPE7_PTE_PGMEM_STATE__SHIFT 0xe
+#define DCI_SOFT_RESET__VGA_SOFT_RESET_MASK 0x1
+#define DCI_SOFT_RESET__VGA_SOFT_RESET__SHIFT 0x0
+#define DCI_SOFT_RESET__VIP_SOFT_RESET_MASK 0x2
+#define DCI_SOFT_RESET__VIP_SOFT_RESET__SHIFT 0x1
+#define DCI_SOFT_RESET__MCIF_SOFT_RESET_MASK 0x4
+#define DCI_SOFT_RESET__MCIF_SOFT_RESET__SHIFT 0x2
+#define DCI_SOFT_RESET__FBC_SOFT_RESET_MASK 0x8
+#define DCI_SOFT_RESET__FBC_SOFT_RESET__SHIFT 0x3
+#define DCI_SOFT_RESET__DMIF0_SOFT_RESET_MASK 0x10
+#define DCI_SOFT_RESET__DMIF0_SOFT_RESET__SHIFT 0x4
+#define DCI_SOFT_RESET__DMIF1_SOFT_RESET_MASK 0x20
+#define DCI_SOFT_RESET__DMIF1_SOFT_RESET__SHIFT 0x5
+#define DCI_SOFT_RESET__DMIF2_SOFT_RESET_MASK 0x40
+#define DCI_SOFT_RESET__DMIF2_SOFT_RESET__SHIFT 0x6
+#define DCI_SOFT_RESET__DMIF3_SOFT_RESET_MASK 0x80
+#define DCI_SOFT_RESET__DMIF3_SOFT_RESET__SHIFT 0x7
+#define DCI_SOFT_RESET__DMIF4_SOFT_RESET_MASK 0x100
+#define DCI_SOFT_RESET__DMIF4_SOFT_RESET__SHIFT 0x8
+#define DCI_SOFT_RESET__DMIF5_SOFT_RESET_MASK 0x200
+#define DCI_SOFT_RESET__DMIF5_SOFT_RESET__SHIFT 0x9
+#define DCI_SOFT_RESET__DCFEV0_L_SOFT_RESET_MASK 0x400
+#define DCI_SOFT_RESET__DCFEV0_L_SOFT_RESET__SHIFT 0xa
+#define DCI_SOFT_RESET__DCFEV0_C_SOFT_RESET_MASK 0x800
+#define DCI_SOFT_RESET__DCFEV0_C_SOFT_RESET__SHIFT 0xb
+#define DCI_SOFT_RESET__DCFEV1_L_SOFT_RESET_MASK 0x1000
+#define DCI_SOFT_RESET__DCFEV1_L_SOFT_RESET__SHIFT 0xc
+#define DCI_SOFT_RESET__DCFEV1_C_SOFT_RESET_MASK 0x2000
+#define DCI_SOFT_RESET__DCFEV1_C_SOFT_RESET__SHIFT 0xd
+#define DCI_SOFT_RESET__DMIFARB_SOFT_RESET_MASK 0x4000
+#define DCI_SOFT_RESET__DMIFARB_SOFT_RESET__SHIFT 0xe
+#define DCI_SOFT_RESET__MCIF_DWB_SOFT_RESET_MASK 0x10000
+#define DCI_SOFT_RESET__MCIF_DWB_SOFT_RESET__SHIFT 0x10
+#define DCI_SOFT_RESET__MCIF_CWB0_SOFT_RESET_MASK 0x20000
+#define DCI_SOFT_RESET__MCIF_CWB0_SOFT_RESET__SHIFT 0x11
+#define DCI_SOFT_RESET__MCIF_CWB1_SOFT_RESET_MASK 0x40000
+#define DCI_SOFT_RESET__MCIF_CWB1_SOFT_RESET__SHIFT 0x12
+#define DCI_SOFT_RESET__MCIF_WB_SOFT_RESET_MASK 0x80000
+#define DCI_SOFT_RESET__MCIF_WB_SOFT_RESET__SHIFT 0x13
+#define DCI_MISC__MCIF_WB_URG_OVRD_MASK 0x1
+#define DCI_MISC__MCIF_WB_URG_OVRD__SHIFT 0x0
+#define DCI_MISC__MCIF_WB_URG_LVL_MASK 0x1e
+#define DCI_MISC__MCIF_WB_URG_LVL__SHIFT 0x1
+#define DCI_TEST_DEBUG_INDEX__DCI_TEST_DEBUG_INDEX_MASK 0xff
+#define DCI_TEST_DEBUG_INDEX__DCI_TEST_DEBUG_INDEX__SHIFT 0x0
+#define DCI_TEST_DEBUG_INDEX__DCI_TEST_DEBUG_WRITE_EN_MASK 0x100
+#define DCI_TEST_DEBUG_INDEX__DCI_TEST_DEBUG_WRITE_EN__SHIFT 0x8
+#define DCI_TEST_DEBUG_DATA__DCI_TEST_DEBUG_DATA_MASK 0xffffffff
+#define DCI_TEST_DEBUG_DATA__DCI_TEST_DEBUG_DATA__SHIFT 0x0
+#define DCI_DEBUG_CONFIG__DCI_DBG_EN_MASK 0x1
+#define DCI_DEBUG_CONFIG__DCI_DBG_EN__SHIFT 0x0
+#define DCI_DEBUG_CONFIG__DCI_DBG_BLOCK_SEL_MASK 0xf0
+#define DCI_DEBUG_CONFIG__DCI_DBG_BLOCK_SEL__SHIFT 0x4
+#define DCI_DEBUG_CONFIG__DCI_DBG_CLOCK_SEL_MASK 0xf00
+#define DCI_DEBUG_CONFIG__DCI_DBG_CLOCK_SEL__SHIFT 0x8
+#define PIPE0_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED_MASK 0x7
+#define PIPE0_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED__SHIFT 0x0
+#define PIPE0_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED_MASK 0x10
+#define PIPE0_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED__SHIFT 0x4
+#define PIPE1_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED_MASK 0x7
+#define PIPE1_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED__SHIFT 0x0
+#define PIPE1_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED_MASK 0x10
+#define PIPE1_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED__SHIFT 0x4
+#define PIPE2_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED_MASK 0x7
+#define PIPE2_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED__SHIFT 0x0
+#define PIPE2_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED_MASK 0x10
+#define PIPE2_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED__SHIFT 0x4
+#define PIPE3_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED_MASK 0x7
+#define PIPE3_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED__SHIFT 0x0
+#define PIPE3_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED_MASK 0x10
+#define PIPE3_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED__SHIFT 0x4
+#define PIPE4_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED_MASK 0x7
+#define PIPE4_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED__SHIFT 0x0
+#define PIPE4_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED_MASK 0x10
+#define PIPE4_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED__SHIFT 0x4
+#define PIPE5_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED_MASK 0x7
+#define PIPE5_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED__SHIFT 0x0
+#define PIPE5_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED_MASK 0x10
+#define PIPE5_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED__SHIFT 0x4
+#define DC_GENERICA__GENERICA_EN_MASK 0x1
+#define DC_GENERICA__GENERICA_EN__SHIFT 0x0
+#define DC_GENERICA__GENERICA_SEL_MASK 0xf80
+#define DC_GENERICA__GENERICA_SEL__SHIFT 0x7
+#define DC_GENERICA__GENERICA_UNIPHY_REFDIV_CLK_SEL_MASK 0xf000
+#define DC_GENERICA__GENERICA_UNIPHY_REFDIV_CLK_SEL__SHIFT 0xc
+#define DC_GENERICA__GENERICA_UNIPHY_FBDIV_CLK_SEL_MASK 0xf0000
+#define DC_GENERICA__GENERICA_UNIPHY_FBDIV_CLK_SEL__SHIFT 0x10
+#define DC_GENERICA__GENERICA_UNIPHY_FBDIV_SSC_CLK_SEL_MASK 0xf00000
+#define DC_GENERICA__GENERICA_UNIPHY_FBDIV_SSC_CLK_SEL__SHIFT 0x14
+#define DC_GENERICA__GENERICA_UNIPHY_FBDIV_CLK_DIV2_SEL_MASK 0xf000000
+#define DC_GENERICA__GENERICA_UNIPHY_FBDIV_CLK_DIV2_SEL__SHIFT 0x18
+#define DC_GENERICB__GENERICB_EN_MASK 0x1
+#define DC_GENERICB__GENERICB_EN__SHIFT 0x0
+#define DC_GENERICB__GENERICB_SEL_MASK 0xf00
+#define DC_GENERICB__GENERICB_SEL__SHIFT 0x8
+#define DC_GENERICB__GENERICB_UNIPHY_REFDIV_CLK_SEL_MASK 0xf000
+#define DC_GENERICB__GENERICB_UNIPHY_REFDIV_CLK_SEL__SHIFT 0xc
+#define DC_GENERICB__GENERICB_UNIPHY_FBDIV_CLK_SEL_MASK 0xf0000
+#define DC_GENERICB__GENERICB_UNIPHY_FBDIV_CLK_SEL__SHIFT 0x10
+#define DC_GENERICB__GENERICB_UNIPHY_FBDIV_SSC_CLK_SEL_MASK 0xf00000
+#define DC_GENERICB__GENERICB_UNIPHY_FBDIV_SSC_CLK_SEL__SHIFT 0x14
+#define DC_GENERICB__GENERICB_UNIPHY_FBDIV_CLK_DIV2_SEL_MASK 0xf000000
+#define DC_GENERICB__GENERICB_UNIPHY_FBDIV_CLK_DIV2_SEL__SHIFT 0x18
+#define DC_PAD_EXTERN_SIG__DC_PAD_EXTERN_SIG_SEL_MASK 0xf
+#define DC_PAD_EXTERN_SIG__DC_PAD_EXTERN_SIG_SEL__SHIFT 0x0
+#define DC_PAD_EXTERN_SIG__MVP_PIXEL_SRC_STATUS_MASK 0x30
+#define DC_PAD_EXTERN_SIG__MVP_PIXEL_SRC_STATUS__SHIFT 0x4
+#define DC_REF_CLK_CNTL__HSYNCA_OUTPUT_SEL_MASK 0x3
+#define DC_REF_CLK_CNTL__HSYNCA_OUTPUT_SEL__SHIFT 0x0
+#define DC_REF_CLK_CNTL__GENLK_CLK_OUTPUT_SEL_MASK 0x300
+#define DC_REF_CLK_CNTL__GENLK_CLK_OUTPUT_SEL__SHIFT 0x8
+#define DC_GPIO_DEBUG__DC_GPIO_VIP_DEBUG_MASK 0x1
+#define DC_GPIO_DEBUG__DC_GPIO_VIP_DEBUG__SHIFT 0x0
+#define DC_GPIO_DEBUG__DC_GPIO_MACRO_DEBUG_MASK 0x300
+#define DC_GPIO_DEBUG__DC_GPIO_MACRO_DEBUG__SHIFT 0x8
+#define DC_GPIO_DEBUG__DC_GPIO_CHIP_DEBUG_OUT_PIN_SEL_MASK 0x10000
+#define DC_GPIO_DEBUG__DC_GPIO_CHIP_DEBUG_OUT_PIN_SEL__SHIFT 0x10
+#define DC_GPIO_DEBUG__DC_GPIO_DEBUG_BUS_FLOP_EN_MASK 0x20000
+#define DC_GPIO_DEBUG__DC_GPIO_DEBUG_BUS_FLOP_EN__SHIFT 0x11
+#define DC_GPIO_DEBUG__DPRX_LOOPBACK_ENABLE_MASK 0x80000000
+#define DC_GPIO_DEBUG__DPRX_LOOPBACK_ENABLE__SHIFT 0x1f
+#define UNIPHYA_LINK_CNTL__UNIPHY_PFREQCHG_MASK 0x1
+#define UNIPHYA_LINK_CNTL__UNIPHY_PFREQCHG__SHIFT 0x0
+#define UNIPHYA_LINK_CNTL__UNIPHY_PIXVLD_RESET_MASK 0x10
+#define UNIPHYA_LINK_CNTL__UNIPHY_PIXVLD_RESET__SHIFT 0x4
+#define UNIPHYA_LINK_CNTL__UNIPHY_MINIMUM_PIXVLD_LOW_DURATION_MASK 0x700
+#define UNIPHYA_LINK_CNTL__UNIPHY_MINIMUM_PIXVLD_LOW_DURATION__SHIFT 0x8
+#define UNIPHYA_LINK_CNTL__UNIPHY_CHANNEL0_INVERT_MASK 0x1000
+#define UNIPHYA_LINK_CNTL__UNIPHY_CHANNEL0_INVERT__SHIFT 0xc
+#define UNIPHYA_LINK_CNTL__UNIPHY_CHANNEL1_INVERT_MASK 0x2000
+#define UNIPHYA_LINK_CNTL__UNIPHY_CHANNEL1_INVERT__SHIFT 0xd
+#define UNIPHYA_LINK_CNTL__UNIPHY_CHANNEL2_INVERT_MASK 0x4000
+#define UNIPHYA_LINK_CNTL__UNIPHY_CHANNEL2_INVERT__SHIFT 0xe
+#define UNIPHYA_LINK_CNTL__UNIPHY_CHANNEL3_INVERT_MASK 0x8000
+#define UNIPHYA_LINK_CNTL__UNIPHY_CHANNEL3_INVERT__SHIFT 0xf
+#define UNIPHYA_LINK_CNTL__UNIPHY_LANE_STAGGER_DELAY_MASK 0x700000
+#define UNIPHYA_LINK_CNTL__UNIPHY_LANE_STAGGER_DELAY__SHIFT 0x14
+#define UNIPHYA_LINK_CNTL__UNIPHY_LINK_ENABLE_HPD_MASK_MASK 0x3000000
+#define UNIPHYA_LINK_CNTL__UNIPHY_LINK_ENABLE_HPD_MASK__SHIFT 0x18
+#define UNIPHYB_LINK_CNTL__UNIPHY_PFREQCHG_MASK 0x1
+#define UNIPHYB_LINK_CNTL__UNIPHY_PFREQCHG__SHIFT 0x0
+#define UNIPHYB_LINK_CNTL__UNIPHY_PIXVLD_RESET_MASK 0x10
+#define UNIPHYB_LINK_CNTL__UNIPHY_PIXVLD_RESET__SHIFT 0x4
+#define UNIPHYB_LINK_CNTL__UNIPHY_MINIMUM_PIXVLD_LOW_DURATION_MASK 0x700
+#define UNIPHYB_LINK_CNTL__UNIPHY_MINIMUM_PIXVLD_LOW_DURATION__SHIFT 0x8
+#define UNIPHYB_LINK_CNTL__UNIPHY_CHANNEL0_INVERT_MASK 0x1000
+#define UNIPHYB_LINK_CNTL__UNIPHY_CHANNEL0_INVERT__SHIFT 0xc
+#define UNIPHYB_LINK_CNTL__UNIPHY_CHANNEL1_INVERT_MASK 0x2000
+#define UNIPHYB_LINK_CNTL__UNIPHY_CHANNEL1_INVERT__SHIFT 0xd
+#define UNIPHYB_LINK_CNTL__UNIPHY_CHANNEL2_INVERT_MASK 0x4000
+#define UNIPHYB_LINK_CNTL__UNIPHY_CHANNEL2_INVERT__SHIFT 0xe
+#define UNIPHYB_LINK_CNTL__UNIPHY_CHANNEL3_INVERT_MASK 0x8000
+#define UNIPHYB_LINK_CNTL__UNIPHY_CHANNEL3_INVERT__SHIFT 0xf
+#define UNIPHYB_LINK_CNTL__UNIPHY_LANE_STAGGER_DELAY_MASK 0x700000
+#define UNIPHYB_LINK_CNTL__UNIPHY_LANE_STAGGER_DELAY__SHIFT 0x14
+#define UNIPHYB_LINK_CNTL__UNIPHY_LINK_ENABLE_HPD_MASK_MASK 0x3000000
+#define UNIPHYB_LINK_CNTL__UNIPHY_LINK_ENABLE_HPD_MASK__SHIFT 0x18
+#define UNIPHYC_LINK_CNTL__UNIPHY_PFREQCHG_MASK 0x1
+#define UNIPHYC_LINK_CNTL__UNIPHY_PFREQCHG__SHIFT 0x0
+#define UNIPHYC_LINK_CNTL__UNIPHY_PIXVLD_RESET_MASK 0x10
+#define UNIPHYC_LINK_CNTL__UNIPHY_PIXVLD_RESET__SHIFT 0x4
+#define UNIPHYC_LINK_CNTL__UNIPHY_MINIMUM_PIXVLD_LOW_DURATION_MASK 0x700
+#define UNIPHYC_LINK_CNTL__UNIPHY_MINIMUM_PIXVLD_LOW_DURATION__SHIFT 0x8
+#define UNIPHYC_LINK_CNTL__UNIPHY_CHANNEL0_INVERT_MASK 0x1000
+#define UNIPHYC_LINK_CNTL__UNIPHY_CHANNEL0_INVERT__SHIFT 0xc
+#define UNIPHYC_LINK_CNTL__UNIPHY_CHANNEL1_INVERT_MASK 0x2000
+#define UNIPHYC_LINK_CNTL__UNIPHY_CHANNEL1_INVERT__SHIFT 0xd
+#define UNIPHYC_LINK_CNTL__UNIPHY_CHANNEL2_INVERT_MASK 0x4000
+#define UNIPHYC_LINK_CNTL__UNIPHY_CHANNEL2_INVERT__SHIFT 0xe
+#define UNIPHYC_LINK_CNTL__UNIPHY_CHANNEL3_INVERT_MASK 0x8000
+#define UNIPHYC_LINK_CNTL__UNIPHY_CHANNEL3_INVERT__SHIFT 0xf
+#define UNIPHYC_LINK_CNTL__UNIPHY_LANE_STAGGER_DELAY_MASK 0x700000
+#define UNIPHYC_LINK_CNTL__UNIPHY_LANE_STAGGER_DELAY__SHIFT 0x14
+#define UNIPHYC_LINK_CNTL__UNIPHY_LINK_ENABLE_HPD_MASK_MASK 0x3000000
+#define UNIPHYC_LINK_CNTL__UNIPHY_LINK_ENABLE_HPD_MASK__SHIFT 0x18
+#define UNIPHYD_LINK_CNTL__UNIPHY_PFREQCHG_MASK 0x1
+#define UNIPHYD_LINK_CNTL__UNIPHY_PFREQCHG__SHIFT 0x0
+#define UNIPHYD_LINK_CNTL__UNIPHY_PIXVLD_RESET_MASK 0x10
+#define UNIPHYD_LINK_CNTL__UNIPHY_PIXVLD_RESET__SHIFT 0x4
+#define UNIPHYD_LINK_CNTL__UNIPHY_MINIMUM_PIXVLD_LOW_DURATION_MASK 0x700
+#define UNIPHYD_LINK_CNTL__UNIPHY_MINIMUM_PIXVLD_LOW_DURATION__SHIFT 0x8
+#define UNIPHYD_LINK_CNTL__UNIPHY_CHANNEL0_INVERT_MASK 0x1000
+#define UNIPHYD_LINK_CNTL__UNIPHY_CHANNEL0_INVERT__SHIFT 0xc
+#define UNIPHYD_LINK_CNTL__UNIPHY_CHANNEL1_INVERT_MASK 0x2000
+#define UNIPHYD_LINK_CNTL__UNIPHY_CHANNEL1_INVERT__SHIFT 0xd
+#define UNIPHYD_LINK_CNTL__UNIPHY_CHANNEL2_INVERT_MASK 0x4000
+#define UNIPHYD_LINK_CNTL__UNIPHY_CHANNEL2_INVERT__SHIFT 0xe
+#define UNIPHYD_LINK_CNTL__UNIPHY_CHANNEL3_INVERT_MASK 0x8000
+#define UNIPHYD_LINK_CNTL__UNIPHY_CHANNEL3_INVERT__SHIFT 0xf
+#define UNIPHYD_LINK_CNTL__UNIPHY_LANE_STAGGER_DELAY_MASK 0x700000
+#define UNIPHYD_LINK_CNTL__UNIPHY_LANE_STAGGER_DELAY__SHIFT 0x14
+#define UNIPHYD_LINK_CNTL__UNIPHY_LINK_ENABLE_HPD_MASK_MASK 0x3000000
+#define UNIPHYD_LINK_CNTL__UNIPHY_LINK_ENABLE_HPD_MASK__SHIFT 0x18
+#define UNIPHYE_LINK_CNTL__UNIPHY_PFREQCHG_MASK 0x1
+#define UNIPHYE_LINK_CNTL__UNIPHY_PFREQCHG__SHIFT 0x0
+#define UNIPHYE_LINK_CNTL__UNIPHY_PIXVLD_RESET_MASK 0x10
+#define UNIPHYE_LINK_CNTL__UNIPHY_PIXVLD_RESET__SHIFT 0x4
+#define UNIPHYE_LINK_CNTL__UNIPHY_MINIMUM_PIXVLD_LOW_DURATION_MASK 0x700
+#define UNIPHYE_LINK_CNTL__UNIPHY_MINIMUM_PIXVLD_LOW_DURATION__SHIFT 0x8
+#define UNIPHYE_LINK_CNTL__UNIPHY_CHANNEL0_INVERT_MASK 0x1000
+#define UNIPHYE_LINK_CNTL__UNIPHY_CHANNEL0_INVERT__SHIFT 0xc
+#define UNIPHYE_LINK_CNTL__UNIPHY_CHANNEL1_INVERT_MASK 0x2000
+#define UNIPHYE_LINK_CNTL__UNIPHY_CHANNEL1_INVERT__SHIFT 0xd
+#define UNIPHYE_LINK_CNTL__UNIPHY_CHANNEL2_INVERT_MASK 0x4000
+#define UNIPHYE_LINK_CNTL__UNIPHY_CHANNEL2_INVERT__SHIFT 0xe
+#define UNIPHYE_LINK_CNTL__UNIPHY_CHANNEL3_INVERT_MASK 0x8000
+#define UNIPHYE_LINK_CNTL__UNIPHY_CHANNEL3_INVERT__SHIFT 0xf
+#define UNIPHYE_LINK_CNTL__UNIPHY_LANE_STAGGER_DELAY_MASK 0x700000
+#define UNIPHYE_LINK_CNTL__UNIPHY_LANE_STAGGER_DELAY__SHIFT 0x14
+#define UNIPHYE_LINK_CNTL__UNIPHY_LINK_ENABLE_HPD_MASK_MASK 0x3000000
+#define UNIPHYE_LINK_CNTL__UNIPHY_LINK_ENABLE_HPD_MASK__SHIFT 0x18
+#define UNIPHYF_LINK_CNTL__UNIPHY_PFREQCHG_MASK 0x1
+#define UNIPHYF_LINK_CNTL__UNIPHY_PFREQCHG__SHIFT 0x0
+#define UNIPHYF_LINK_CNTL__UNIPHY_PIXVLD_RESET_MASK 0x10
+#define UNIPHYF_LINK_CNTL__UNIPHY_PIXVLD_RESET__SHIFT 0x4
+#define UNIPHYF_LINK_CNTL__UNIPHY_MINIMUM_PIXVLD_LOW_DURATION_MASK 0x700
+#define UNIPHYF_LINK_CNTL__UNIPHY_MINIMUM_PIXVLD_LOW_DURATION__SHIFT 0x8
+#define UNIPHYF_LINK_CNTL__UNIPHY_CHANNEL0_INVERT_MASK 0x1000
+#define UNIPHYF_LINK_CNTL__UNIPHY_CHANNEL0_INVERT__SHIFT 0xc
+#define UNIPHYF_LINK_CNTL__UNIPHY_CHANNEL1_INVERT_MASK 0x2000
+#define UNIPHYF_LINK_CNTL__UNIPHY_CHANNEL1_INVERT__SHIFT 0xd
+#define UNIPHYF_LINK_CNTL__UNIPHY_CHANNEL2_INVERT_MASK 0x4000
+#define UNIPHYF_LINK_CNTL__UNIPHY_CHANNEL2_INVERT__SHIFT 0xe
+#define UNIPHYF_LINK_CNTL__UNIPHY_CHANNEL3_INVERT_MASK 0x8000
+#define UNIPHYF_LINK_CNTL__UNIPHY_CHANNEL3_INVERT__SHIFT 0xf
+#define UNIPHYF_LINK_CNTL__UNIPHY_LANE_STAGGER_DELAY_MASK 0x700000
+#define UNIPHYF_LINK_CNTL__UNIPHY_LANE_STAGGER_DELAY__SHIFT 0x14
+#define UNIPHYF_LINK_CNTL__UNIPHY_LINK_ENABLE_HPD_MASK_MASK 0x3000000
+#define UNIPHYF_LINK_CNTL__UNIPHY_LINK_ENABLE_HPD_MASK__SHIFT 0x18
+#define UNIPHYG_LINK_CNTL__UNIPHY_PFREQCHG_MASK 0x1
+#define UNIPHYG_LINK_CNTL__UNIPHY_PFREQCHG__SHIFT 0x0
+#define UNIPHYG_LINK_CNTL__UNIPHY_PIXVLD_RESET_MASK 0x10
+#define UNIPHYG_LINK_CNTL__UNIPHY_PIXVLD_RESET__SHIFT 0x4
+#define UNIPHYG_LINK_CNTL__UNIPHY_MINIMUM_PIXVLD_LOW_DURATION_MASK 0x700
+#define UNIPHYG_LINK_CNTL__UNIPHY_MINIMUM_PIXVLD_LOW_DURATION__SHIFT 0x8
+#define UNIPHYG_LINK_CNTL__UNIPHY_CHANNEL0_INVERT_MASK 0x1000
+#define UNIPHYG_LINK_CNTL__UNIPHY_CHANNEL0_INVERT__SHIFT 0xc
+#define UNIPHYG_LINK_CNTL__UNIPHY_CHANNEL1_INVERT_MASK 0x2000
+#define UNIPHYG_LINK_CNTL__UNIPHY_CHANNEL1_INVERT__SHIFT 0xd
+#define UNIPHYG_LINK_CNTL__UNIPHY_CHANNEL2_INVERT_MASK 0x4000
+#define UNIPHYG_LINK_CNTL__UNIPHY_CHANNEL2_INVERT__SHIFT 0xe
+#define UNIPHYG_LINK_CNTL__UNIPHY_CHANNEL3_INVERT_MASK 0x8000
+#define UNIPHYG_LINK_CNTL__UNIPHY_CHANNEL3_INVERT__SHIFT 0xf
+#define UNIPHYG_LINK_CNTL__UNIPHY_LANE_STAGGER_DELAY_MASK 0x700000
+#define UNIPHYG_LINK_CNTL__UNIPHY_LANE_STAGGER_DELAY__SHIFT 0x14
+#define UNIPHYG_LINK_CNTL__UNIPHY_LINK_ENABLE_HPD_MASK_MASK 0x3000000
+#define UNIPHYG_LINK_CNTL__UNIPHY_LINK_ENABLE_HPD_MASK__SHIFT 0x18
+#define UNIPHYA_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL0_XBAR_SOURCE_MASK 0x3
+#define UNIPHYA_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL0_XBAR_SOURCE__SHIFT 0x0
+#define UNIPHYA_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL1_XBAR_SOURCE_MASK 0x300
+#define UNIPHYA_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL1_XBAR_SOURCE__SHIFT 0x8
+#define UNIPHYA_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL2_XBAR_SOURCE_MASK 0x30000
+#define UNIPHYA_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL2_XBAR_SOURCE__SHIFT 0x10
+#define UNIPHYA_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL3_XBAR_SOURCE_MASK 0x3000000
+#define UNIPHYA_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL3_XBAR_SOURCE__SHIFT 0x18
+#define UNIPHYA_CHANNEL_XBAR_CNTL__UNIPHY_LINK_ENABLE_MASK 0x10000000
+#define UNIPHYA_CHANNEL_XBAR_CNTL__UNIPHY_LINK_ENABLE__SHIFT 0x1c
+#define UNIPHYB_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL0_XBAR_SOURCE_MASK 0x3
+#define UNIPHYB_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL0_XBAR_SOURCE__SHIFT 0x0
+#define UNIPHYB_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL1_XBAR_SOURCE_MASK 0x300
+#define UNIPHYB_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL1_XBAR_SOURCE__SHIFT 0x8
+#define UNIPHYB_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL2_XBAR_SOURCE_MASK 0x30000
+#define UNIPHYB_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL2_XBAR_SOURCE__SHIFT 0x10
+#define UNIPHYB_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL3_XBAR_SOURCE_MASK 0x3000000
+#define UNIPHYB_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL3_XBAR_SOURCE__SHIFT 0x18
+#define UNIPHYB_CHANNEL_XBAR_CNTL__UNIPHY_LINK_ENABLE_MASK 0x10000000
+#define UNIPHYB_CHANNEL_XBAR_CNTL__UNIPHY_LINK_ENABLE__SHIFT 0x1c
+#define UNIPHYC_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL0_XBAR_SOURCE_MASK 0x3
+#define UNIPHYC_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL0_XBAR_SOURCE__SHIFT 0x0
+#define UNIPHYC_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL1_XBAR_SOURCE_MASK 0x300
+#define UNIPHYC_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL1_XBAR_SOURCE__SHIFT 0x8
+#define UNIPHYC_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL2_XBAR_SOURCE_MASK 0x30000
+#define UNIPHYC_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL2_XBAR_SOURCE__SHIFT 0x10
+#define UNIPHYC_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL3_XBAR_SOURCE_MASK 0x3000000
+#define UNIPHYC_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL3_XBAR_SOURCE__SHIFT 0x18
+#define UNIPHYC_CHANNEL_XBAR_CNTL__UNIPHY_LINK_ENABLE_MASK 0x10000000
+#define UNIPHYC_CHANNEL_XBAR_CNTL__UNIPHY_LINK_ENABLE__SHIFT 0x1c
+#define UNIPHYD_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL0_XBAR_SOURCE_MASK 0x3
+#define UNIPHYD_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL0_XBAR_SOURCE__SHIFT 0x0
+#define UNIPHYD_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL1_XBAR_SOURCE_MASK 0x300
+#define UNIPHYD_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL1_XBAR_SOURCE__SHIFT 0x8
+#define UNIPHYD_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL2_XBAR_SOURCE_MASK 0x30000
+#define UNIPHYD_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL2_XBAR_SOURCE__SHIFT 0x10
+#define UNIPHYD_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL3_XBAR_SOURCE_MASK 0x3000000
+#define UNIPHYD_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL3_XBAR_SOURCE__SHIFT 0x18
+#define UNIPHYD_CHANNEL_XBAR_CNTL__UNIPHY_LINK_ENABLE_MASK 0x10000000
+#define UNIPHYD_CHANNEL_XBAR_CNTL__UNIPHY_LINK_ENABLE__SHIFT 0x1c
+#define UNIPHYE_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL0_XBAR_SOURCE_MASK 0x3
+#define UNIPHYE_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL0_XBAR_SOURCE__SHIFT 0x0
+#define UNIPHYE_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL1_XBAR_SOURCE_MASK 0x300
+#define UNIPHYE_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL1_XBAR_SOURCE__SHIFT 0x8
+#define UNIPHYE_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL2_XBAR_SOURCE_MASK 0x30000
+#define UNIPHYE_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL2_XBAR_SOURCE__SHIFT 0x10
+#define UNIPHYE_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL3_XBAR_SOURCE_MASK 0x3000000
+#define UNIPHYE_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL3_XBAR_SOURCE__SHIFT 0x18
+#define UNIPHYE_CHANNEL_XBAR_CNTL__UNIPHY_LINK_ENABLE_MASK 0x10000000
+#define UNIPHYE_CHANNEL_XBAR_CNTL__UNIPHY_LINK_ENABLE__SHIFT 0x1c
+#define UNIPHYF_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL0_XBAR_SOURCE_MASK 0x3
+#define UNIPHYF_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL0_XBAR_SOURCE__SHIFT 0x0
+#define UNIPHYF_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL1_XBAR_SOURCE_MASK 0x300
+#define UNIPHYF_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL1_XBAR_SOURCE__SHIFT 0x8
+#define UNIPHYF_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL2_XBAR_SOURCE_MASK 0x30000
+#define UNIPHYF_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL2_XBAR_SOURCE__SHIFT 0x10
+#define UNIPHYF_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL3_XBAR_SOURCE_MASK 0x3000000
+#define UNIPHYF_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL3_XBAR_SOURCE__SHIFT 0x18
+#define UNIPHYF_CHANNEL_XBAR_CNTL__UNIPHY_LINK_ENABLE_MASK 0x10000000
+#define UNIPHYF_CHANNEL_XBAR_CNTL__UNIPHY_LINK_ENABLE__SHIFT 0x1c
+#define UNIPHYG_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL0_XBAR_SOURCE_MASK 0x3
+#define UNIPHYG_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL0_XBAR_SOURCE__SHIFT 0x0
+#define UNIPHYG_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL1_XBAR_SOURCE_MASK 0x300
+#define UNIPHYG_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL1_XBAR_SOURCE__SHIFT 0x8
+#define UNIPHYG_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL2_XBAR_SOURCE_MASK 0x30000
+#define UNIPHYG_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL2_XBAR_SOURCE__SHIFT 0x10
+#define UNIPHYG_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL3_XBAR_SOURCE_MASK 0x3000000
+#define UNIPHYG_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL3_XBAR_SOURCE__SHIFT 0x18
+#define UNIPHYG_CHANNEL_XBAR_CNTL__UNIPHY_LINK_ENABLE_MASK 0x10000000
+#define UNIPHYG_CHANNEL_XBAR_CNTL__UNIPHY_LINK_ENABLE__SHIFT 0x1c
+#define UNIPHYLPA_LINK_CNTL__UNIPHYLP_PFREQCHG_MASK 0x1
+#define UNIPHYLPA_LINK_CNTL__UNIPHYLP_PFREQCHG__SHIFT 0x0
+#define UNIPHYLPA_LINK_CNTL__UNIPHYLP_PIXVLD_RESET_MASK 0x10
+#define UNIPHYLPA_LINK_CNTL__UNIPHYLP_PIXVLD_RESET__SHIFT 0x4
+#define UNIPHYLPA_LINK_CNTL__UNIPHYLP_MINIMUM_PIXVLD_LOW_DURATION_MASK 0x700
+#define UNIPHYLPA_LINK_CNTL__UNIPHYLP_MINIMUM_PIXVLD_LOW_DURATION__SHIFT 0x8
+#define UNIPHYLPA_LINK_CNTL__UNIPHYLP_CHANNEL0_INVERT_MASK 0x1000
+#define UNIPHYLPA_LINK_CNTL__UNIPHYLP_CHANNEL0_INVERT__SHIFT 0xc
+#define UNIPHYLPA_LINK_CNTL__UNIPHYLP_CHANNEL1_INVERT_MASK 0x2000
+#define UNIPHYLPA_LINK_CNTL__UNIPHYLP_CHANNEL1_INVERT__SHIFT 0xd
+#define UNIPHYLPA_LINK_CNTL__UNIPHYLP_CHANNEL2_INVERT_MASK 0x4000
+#define UNIPHYLPA_LINK_CNTL__UNIPHYLP_CHANNEL2_INVERT__SHIFT 0xe
+#define UNIPHYLPA_LINK_CNTL__UNIPHYLP_CHANNEL3_INVERT_MASK 0x8000
+#define UNIPHYLPA_LINK_CNTL__UNIPHYLP_CHANNEL3_INVERT__SHIFT 0xf
+#define UNIPHYLPA_LINK_CNTL__UNIPHYLP_LANE_STAGGER_DELAY_MASK 0x700000
+#define UNIPHYLPA_LINK_CNTL__UNIPHYLP_LANE_STAGGER_DELAY__SHIFT 0x14
+#define UNIPHYLPA_LINK_CNTL__UNIPHYLP_LINK_ENABLE_HPD_MASK_MASK 0x3000000
+#define UNIPHYLPA_LINK_CNTL__UNIPHYLP_LINK_ENABLE_HPD_MASK__SHIFT 0x18
+#define UNIPHYLPB_LINK_CNTL__UNIPHYLP_PFREQCHG_MASK 0x1
+#define UNIPHYLPB_LINK_CNTL__UNIPHYLP_PFREQCHG__SHIFT 0x0
+#define UNIPHYLPB_LINK_CNTL__UNIPHYLP_PIXVLD_RESET_MASK 0x10
+#define UNIPHYLPB_LINK_CNTL__UNIPHYLP_PIXVLD_RESET__SHIFT 0x4
+#define UNIPHYLPB_LINK_CNTL__UNIPHYLP_MINIMUM_PIXVLD_LOW_DURATION_MASK 0x700
+#define UNIPHYLPB_LINK_CNTL__UNIPHYLP_MINIMUM_PIXVLD_LOW_DURATION__SHIFT 0x8
+#define UNIPHYLPB_LINK_CNTL__UNIPHYLP_CHANNEL0_INVERT_MASK 0x1000
+#define UNIPHYLPB_LINK_CNTL__UNIPHYLP_CHANNEL0_INVERT__SHIFT 0xc
+#define UNIPHYLPB_LINK_CNTL__UNIPHYLP_CHANNEL1_INVERT_MASK 0x2000
+#define UNIPHYLPB_LINK_CNTL__UNIPHYLP_CHANNEL1_INVERT__SHIFT 0xd
+#define UNIPHYLPB_LINK_CNTL__UNIPHYLP_CHANNEL2_INVERT_MASK 0x4000
+#define UNIPHYLPB_LINK_CNTL__UNIPHYLP_CHANNEL2_INVERT__SHIFT 0xe
+#define UNIPHYLPB_LINK_CNTL__UNIPHYLP_CHANNEL3_INVERT_MASK 0x8000
+#define UNIPHYLPB_LINK_CNTL__UNIPHYLP_CHANNEL3_INVERT__SHIFT 0xf
+#define UNIPHYLPB_LINK_CNTL__UNIPHYLP_LANE_STAGGER_DELAY_MASK 0x700000
+#define UNIPHYLPB_LINK_CNTL__UNIPHYLP_LANE_STAGGER_DELAY__SHIFT 0x14
+#define UNIPHYLPB_LINK_CNTL__UNIPHYLP_LINK_ENABLE_HPD_MASK_MASK 0x3000000
+#define UNIPHYLPB_LINK_CNTL__UNIPHYLP_LINK_ENABLE_HPD_MASK__SHIFT 0x18
+#define UNIPHYLPA_CHANNEL_XBAR_CNTL__UNIPHYLP_CHANNEL0_XBAR_SOURCE_MASK 0x3
+#define UNIPHYLPA_CHANNEL_XBAR_CNTL__UNIPHYLP_CHANNEL0_XBAR_SOURCE__SHIFT 0x0
+#define UNIPHYLPA_CHANNEL_XBAR_CNTL__UNIPHYLP_CHANNEL1_XBAR_SOURCE_MASK 0x300
+#define UNIPHYLPA_CHANNEL_XBAR_CNTL__UNIPHYLP_CHANNEL1_XBAR_SOURCE__SHIFT 0x8
+#define UNIPHYLPA_CHANNEL_XBAR_CNTL__UNIPHYLP_CHANNEL2_XBAR_SOURCE_MASK 0x30000
+#define UNIPHYLPA_CHANNEL_XBAR_CNTL__UNIPHYLP_CHANNEL2_XBAR_SOURCE__SHIFT 0x10
+#define UNIPHYLPA_CHANNEL_XBAR_CNTL__UNIPHYLP_CHANNEL3_XBAR_SOURCE_MASK 0x3000000
+#define UNIPHYLPA_CHANNEL_XBAR_CNTL__UNIPHYLP_CHANNEL3_XBAR_SOURCE__SHIFT 0x18
+#define UNIPHYLPA_CHANNEL_XBAR_CNTL__UNIPHYLP_LINK_ENABLE_MASK 0x10000000
+#define UNIPHYLPA_CHANNEL_XBAR_CNTL__UNIPHYLP_LINK_ENABLE__SHIFT 0x1c
+#define UNIPHYLPB_CHANNEL_XBAR_CNTL__UNIPHYLP_CHANNEL0_XBAR_SOURCE_MASK 0x3
+#define UNIPHYLPB_CHANNEL_XBAR_CNTL__UNIPHYLP_CHANNEL0_XBAR_SOURCE__SHIFT 0x0
+#define UNIPHYLPB_CHANNEL_XBAR_CNTL__UNIPHYLP_CHANNEL1_XBAR_SOURCE_MASK 0x300
+#define UNIPHYLPB_CHANNEL_XBAR_CNTL__UNIPHYLP_CHANNEL1_XBAR_SOURCE__SHIFT 0x8
+#define UNIPHYLPB_CHANNEL_XBAR_CNTL__UNIPHYLP_CHANNEL2_XBAR_SOURCE_MASK 0x30000
+#define UNIPHYLPB_CHANNEL_XBAR_CNTL__UNIPHYLP_CHANNEL2_XBAR_SOURCE__SHIFT 0x10
+#define UNIPHYLPB_CHANNEL_XBAR_CNTL__UNIPHYLP_CHANNEL3_XBAR_SOURCE_MASK 0x3000000
+#define UNIPHYLPB_CHANNEL_XBAR_CNTL__UNIPHYLP_CHANNEL3_XBAR_SOURCE__SHIFT 0x18
+#define UNIPHYLPB_CHANNEL_XBAR_CNTL__UNIPHYLP_LINK_ENABLE_MASK 0x10000000
+#define UNIPHYLPB_CHANNEL_XBAR_CNTL__UNIPHYLP_LINK_ENABLE__SHIFT 0x1c
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_ENABLE_LINKA_MASK 0x1
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_ENABLE_LINKA__SHIFT 0x0
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_CALOUT_LINKA_MASK 0x100
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_CALOUT_LINKA__SHIFT 0x8
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_CALOUT_ERROR_LINKA_MASK 0x200
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_CALOUT_ERROR_LINKA__SHIFT 0x9
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_CALOUT_ERROR_LINKA_AK_MASK 0x400
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_CALOUT_ERROR_LINKA_AK__SHIFT 0xa
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_VALUE_LINKA_MASK 0xf0000
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_VALUE_LINKA__SHIFT 0x10
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_STEP_DELAY_LINKA_MASK 0xf00000
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_STEP_DELAY_LINKA__SHIFT 0x14
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_OVERRIDE_LINKA_MASK 0xf000000
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_OVERRIDE_LINKA__SHIFT 0x18
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_OVERRIDE_ENABLE_LINKA_MASK 0x10000000
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_OVERRIDE_ENABLE_LINKA__SHIFT 0x1c
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_SEL_LINKA_MASK 0x40000000
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_SEL_LINKA__SHIFT 0x1e
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_ENABLE_LINKB_MASK 0x1
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_ENABLE_LINKB__SHIFT 0x0
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_CALOUT_LINKB_MASK 0x100
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_CALOUT_LINKB__SHIFT 0x8
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_CALOUT_ERROR_LINKB_MASK 0x200
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_CALOUT_ERROR_LINKB__SHIFT 0x9
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_CALOUT_ERROR_LINKB_AK_MASK 0x400
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_CALOUT_ERROR_LINKB_AK__SHIFT 0xa
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_VALUE_LINKB_MASK 0xf0000
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_VALUE_LINKB__SHIFT 0x10
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_STEP_DELAY_LINKB_MASK 0xf00000
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_STEP_DELAY_LINKB__SHIFT 0x14
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_OVERRIDE_LINKB_MASK 0xf000000
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_OVERRIDE_LINKB__SHIFT 0x18
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_OVERRIDE_ENABLE_LINKB_MASK 0x10000000
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_OVERRIDE_ENABLE_LINKB__SHIFT 0x1c
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_SEL_LINKB_MASK 0x40000000
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_SEL_LINKB__SHIFT 0x1e
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_ENABLE_LINKC_MASK 0x1
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_ENABLE_LINKC__SHIFT 0x0
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_CALOUT_LINKC_MASK 0x100
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_CALOUT_LINKC__SHIFT 0x8
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_CALOUT_ERROR_LINKC_MASK 0x200
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_CALOUT_ERROR_LINKC__SHIFT 0x9
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_CALOUT_ERROR_LINKC_AK_MASK 0x400
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_CALOUT_ERROR_LINKC_AK__SHIFT 0xa
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_VALUE_LINKC_MASK 0xf0000
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_VALUE_LINKC__SHIFT 0x10
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_STEP_DELAY_LINKC_MASK 0xf00000
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_STEP_DELAY_LINKC__SHIFT 0x14
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_OVERRIDE_LINKC_MASK 0xf000000
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_OVERRIDE_LINKC__SHIFT 0x18
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_OVERRIDE_ENABLE_LINKC_MASK 0x10000000
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_OVERRIDE_ENABLE_LINKC__SHIFT 0x1c
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_SEL_LINKC_MASK 0x40000000
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_SEL_LINKC__SHIFT 0x1e
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_ENABLE_LINKD_MASK 0x1
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_ENABLE_LINKD__SHIFT 0x0
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_CALOUT_LINKD_MASK 0x100
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_CALOUT_LINKD__SHIFT 0x8
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_CALOUT_ERROR_LINKD_MASK 0x200
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_CALOUT_ERROR_LINKD__SHIFT 0x9
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_CALOUT_ERROR_LINKD_AK_MASK 0x400
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_CALOUT_ERROR_LINKD_AK__SHIFT 0xa
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_VALUE_LINKD_MASK 0xf0000
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_VALUE_LINKD__SHIFT 0x10
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_STEP_DELAY_LINKD_MASK 0xf00000
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_STEP_DELAY_LINKD__SHIFT 0x14
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_OVERRIDE_LINKD_MASK 0xf000000
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_OVERRIDE_LINKD__SHIFT 0x18
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_OVERRIDE_ENABLE_LINKD_MASK 0x10000000
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_OVERRIDE_ENABLE_LINKD__SHIFT 0x1c
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_SEL_LINKD_MASK 0x40000000
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_SEL_LINKD__SHIFT 0x1e
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_ENABLE_LINKE_MASK 0x1
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_ENABLE_LINKE__SHIFT 0x0
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_CALOUT_LINKE_MASK 0x100
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_CALOUT_LINKE__SHIFT 0x8
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_CALOUT_ERROR_LINKE_MASK 0x200
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_CALOUT_ERROR_LINKE__SHIFT 0x9
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_CALOUT_ERROR_LINKE_AK_MASK 0x400
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_CALOUT_ERROR_LINKE_AK__SHIFT 0xa
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_VALUE_LINKE_MASK 0xf0000
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_VALUE_LINKE__SHIFT 0x10
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_STEP_DELAY_LINKE_MASK 0xf00000
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_STEP_DELAY_LINKE__SHIFT 0x14
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_OVERRIDE_LINKE_MASK 0xf000000
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_OVERRIDE_LINKE__SHIFT 0x18
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_OVERRIDE_ENABLE_LINKE_MASK 0x10000000
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_OVERRIDE_ENABLE_LINKE__SHIFT 0x1c
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_SEL_LINKE_MASK 0x40000000
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_SEL_LINKE__SHIFT 0x1e
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_ENABLE_LINKF_MASK 0x1
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_ENABLE_LINKF__SHIFT 0x0
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_CALOUT_LINKF_MASK 0x100
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_CALOUT_LINKF__SHIFT 0x8
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_CALOUT_ERROR_LINKF_MASK 0x200
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_CALOUT_ERROR_LINKF__SHIFT 0x9
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_CALOUT_ERROR_LINKF_AK_MASK 0x400
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_CALOUT_ERROR_LINKF_AK__SHIFT 0xa
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_VALUE_LINKF_MASK 0xf0000
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_VALUE_LINKF__SHIFT 0x10
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_STEP_DELAY_LINKF_MASK 0xf00000
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_STEP_DELAY_LINKF__SHIFT 0x14
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_OVERRIDE_LINKF_MASK 0xf000000
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_OVERRIDE_LINKF__SHIFT 0x18
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_OVERRIDE_ENABLE_LINKF_MASK 0x10000000
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_OVERRIDE_ENABLE_LINKF__SHIFT 0x1c
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_SEL_LINKF_MASK 0x40000000
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_SEL_LINKF__SHIFT 0x1e
+#define UNIPHY_IMPCAL_PERIOD__UNIPHY_IMPCAL_PERIOD_MASK 0xffffffff
+#define UNIPHY_IMPCAL_PERIOD__UNIPHY_IMPCAL_PERIOD__SHIFT 0x0
+#define AUXP_IMPCAL__AUXP_IMPCAL_ENABLE_MASK 0x1
+#define AUXP_IMPCAL__AUXP_IMPCAL_ENABLE__SHIFT 0x0
+#define AUXP_IMPCAL__AUXP_IMPCAL_CALOUT_MASK 0x100
+#define AUXP_IMPCAL__AUXP_IMPCAL_CALOUT__SHIFT 0x8
+#define AUXP_IMPCAL__AUXP_CALOUT_ERROR_MASK 0x200
+#define AUXP_IMPCAL__AUXP_CALOUT_ERROR__SHIFT 0x9
+#define AUXP_IMPCAL__AUXP_CALOUT_ERROR_AK_MASK 0x400
+#define AUXP_IMPCAL__AUXP_CALOUT_ERROR_AK__SHIFT 0xa
+#define AUXP_IMPCAL__AUXP_IMPCAL_VALUE_MASK 0xf0000
+#define AUXP_IMPCAL__AUXP_IMPCAL_VALUE__SHIFT 0x10
+#define AUXP_IMPCAL__AUXP_IMPCAL_STEP_DELAY_MASK 0xf00000
+#define AUXP_IMPCAL__AUXP_IMPCAL_STEP_DELAY__SHIFT 0x14
+#define AUXP_IMPCAL__AUXP_IMPCAL_OVERRIDE_MASK 0xf000000
+#define AUXP_IMPCAL__AUXP_IMPCAL_OVERRIDE__SHIFT 0x18
+#define AUXP_IMPCAL__AUXP_IMPCAL_OVERRIDE_ENABLE_MASK 0x10000000
+#define AUXP_IMPCAL__AUXP_IMPCAL_OVERRIDE_ENABLE__SHIFT 0x1c
+#define AUXN_IMPCAL__AUXN_IMPCAL_ENABLE_MASK 0x1
+#define AUXN_IMPCAL__AUXN_IMPCAL_ENABLE__SHIFT 0x0
+#define AUXN_IMPCAL__AUXN_IMPCAL_CALOUT_MASK 0x100
+#define AUXN_IMPCAL__AUXN_IMPCAL_CALOUT__SHIFT 0x8
+#define AUXN_IMPCAL__AUXN_CALOUT_ERROR_MASK 0x200
+#define AUXN_IMPCAL__AUXN_CALOUT_ERROR__SHIFT 0x9
+#define AUXN_IMPCAL__AUXN_CALOUT_ERROR_AK_MASK 0x400
+#define AUXN_IMPCAL__AUXN_CALOUT_ERROR_AK__SHIFT 0xa
+#define AUXN_IMPCAL__AUXN_IMPCAL_VALUE_MASK 0xf0000
+#define AUXN_IMPCAL__AUXN_IMPCAL_VALUE__SHIFT 0x10
+#define AUXN_IMPCAL__AUXN_IMPCAL_STEP_DELAY_MASK 0xf00000
+#define AUXN_IMPCAL__AUXN_IMPCAL_STEP_DELAY__SHIFT 0x14
+#define AUXN_IMPCAL__AUXN_IMPCAL_OVERRIDE_MASK 0xf000000
+#define AUXN_IMPCAL__AUXN_IMPCAL_OVERRIDE__SHIFT 0x18
+#define AUXN_IMPCAL__AUXN_IMPCAL_OVERRIDE_ENABLE_MASK 0x10000000
+#define AUXN_IMPCAL__AUXN_IMPCAL_OVERRIDE_ENABLE__SHIFT 0x1c
+#define DCIO_IMPCAL_CNTL__CALR_CNTL_OVERRIDE_MASK 0xf
+#define DCIO_IMPCAL_CNTL__CALR_CNTL_OVERRIDE__SHIFT 0x0
+#define DCIO_IMPCAL_CNTL__IMPCAL_SOFT_RESET_MASK 0x20
+#define DCIO_IMPCAL_CNTL__IMPCAL_SOFT_RESET__SHIFT 0x5
+#define DCIO_IMPCAL_CNTL__IMPCAL_STATUS_MASK 0x300
+#define DCIO_IMPCAL_CNTL__IMPCAL_STATUS__SHIFT 0x8
+#define DCIO_IMPCAL_CNTL__IMPCAL_ARB_STATE_MASK 0x7000
+#define DCIO_IMPCAL_CNTL__IMPCAL_ARB_STATE__SHIFT 0xc
+#define DCIO_IMPCAL_CNTL__AUX_IMPCAL_INTERVAL_MASK 0x78000
+#define DCIO_IMPCAL_CNTL__AUX_IMPCAL_INTERVAL__SHIFT 0xf
+#define DCIO_IMPCAL_CNTL__AUX_IMPCAL_BIASENTST_MASK 0x380000
+#define DCIO_IMPCAL_CNTL__AUX_IMPCAL_BIASENTST__SHIFT 0x13
+#define DCIO_IMPCAL_CNTL__AUX_IMPCAL_RESBIASEN_MASK 0x400000
+#define DCIO_IMPCAL_CNTL__AUX_IMPCAL_RESBIASEN__SHIFT 0x16
+#define DCIO_IMPCAL_CNTL__AUX_IMPCAL_SPARE_CONTROL_MASK 0x1800000
+#define DCIO_IMPCAL_CNTL__AUX_IMPCAL_SPARE_CONTROL__SHIFT 0x17
+#define UNIPHY_IMPCAL_PSW_AB__UNIPHY_IMPCAL_PSW_LINKA_MASK 0x7fff
+#define UNIPHY_IMPCAL_PSW_AB__UNIPHY_IMPCAL_PSW_LINKA__SHIFT 0x0
+#define UNIPHY_IMPCAL_PSW_AB__UNIPHY_IMPCAL_PSW_LINKB_MASK 0x7fff0000
+#define UNIPHY_IMPCAL_PSW_AB__UNIPHY_IMPCAL_PSW_LINKB__SHIFT 0x10
+#define DCIO_IMPCAL_CNTL_CD__CALR_CNTL_OVERRIDE_MASK 0xf
+#define DCIO_IMPCAL_CNTL_CD__CALR_CNTL_OVERRIDE__SHIFT 0x0
+#define DCIO_IMPCAL_CNTL_CD__IMPCAL_SOFT_RESET_MASK 0x20
+#define DCIO_IMPCAL_CNTL_CD__IMPCAL_SOFT_RESET__SHIFT 0x5
+#define DCIO_IMPCAL_CNTL_CD__IMPCAL_STATUS_MASK 0x300
+#define DCIO_IMPCAL_CNTL_CD__IMPCAL_STATUS__SHIFT 0x8
+#define DCIO_IMPCAL_CNTL_CD__IMPCAL_ARB_STATE_MASK 0x7000
+#define DCIO_IMPCAL_CNTL_CD__IMPCAL_ARB_STATE__SHIFT 0xc
+#define UNIPHY_IMPCAL_PSW_CD__UNIPHY_IMPCAL_PSW_LINKC_MASK 0x7fff
+#define UNIPHY_IMPCAL_PSW_CD__UNIPHY_IMPCAL_PSW_LINKC__SHIFT 0x0
+#define UNIPHY_IMPCAL_PSW_CD__UNIPHY_IMPCAL_PSW_LINKD_MASK 0x7fff0000
+#define UNIPHY_IMPCAL_PSW_CD__UNIPHY_IMPCAL_PSW_LINKD__SHIFT 0x10
+#define DCIO_IMPCAL_CNTL_EF__CALR_CNTL_OVERRIDE_MASK 0xf
+#define DCIO_IMPCAL_CNTL_EF__CALR_CNTL_OVERRIDE__SHIFT 0x0
+#define DCIO_IMPCAL_CNTL_EF__IMPCAL_SOFT_RESET_MASK 0x20
+#define DCIO_IMPCAL_CNTL_EF__IMPCAL_SOFT_RESET__SHIFT 0x5
+#define DCIO_IMPCAL_CNTL_EF__IMPCAL_STATUS_MASK 0x300
+#define DCIO_IMPCAL_CNTL_EF__IMPCAL_STATUS__SHIFT 0x8
+#define DCIO_IMPCAL_CNTL_EF__IMPCAL_ARB_STATE_MASK 0x7000
+#define DCIO_IMPCAL_CNTL_EF__IMPCAL_ARB_STATE__SHIFT 0xc
+#define UNIPHY_IMPCAL_PSW_EF__UNIPHY_IMPCAL_PSW_LINKE_MASK 0x7fff
+#define UNIPHY_IMPCAL_PSW_EF__UNIPHY_IMPCAL_PSW_LINKE__SHIFT 0x0
+#define UNIPHY_IMPCAL_PSW_EF__UNIPHY_IMPCAL_PSW_LINKF_MASK 0x7fff0000
+#define UNIPHY_IMPCAL_PSW_EF__UNIPHY_IMPCAL_PSW_LINKF__SHIFT 0x10
+#define DCIO_WRCMD_DELAY__UNIPHY_DELAY_MASK 0xf
+#define DCIO_WRCMD_DELAY__UNIPHY_DELAY__SHIFT 0x0
+#define DCIO_WRCMD_DELAY__DAC_DELAY_MASK 0xf0
+#define DCIO_WRCMD_DELAY__DAC_DELAY__SHIFT 0x4
+#define DCIO_WRCMD_DELAY__DPHY_DELAY_MASK 0xf00
+#define DCIO_WRCMD_DELAY__DPHY_DELAY__SHIFT 0x8
+#define DCIO_WRCMD_DELAY__DCRXPHY_DELAY_MASK 0xf000
+#define DCIO_WRCMD_DELAY__DCRXPHY_DELAY__SHIFT 0xc
+#define DCIO_WRCMD_DELAY__ZCAL_DELAY_MASK 0xf0000
+#define DCIO_WRCMD_DELAY__ZCAL_DELAY__SHIFT 0x10
+#define DC_PINSTRAPS__DC_PINSTRAPS_BIF_CEC_DIS_MASK 0x400
+#define DC_PINSTRAPS__DC_PINSTRAPS_BIF_CEC_DIS__SHIFT 0xa
+#define DC_PINSTRAPS__DC_PINSTRAPS_SMS_EN_HARD_MASK 0x2000
+#define DC_PINSTRAPS__DC_PINSTRAPS_SMS_EN_HARD__SHIFT 0xd
+#define DC_PINSTRAPS__DC_PINSTRAPS_AUDIO_MASK 0xc000
+#define DC_PINSTRAPS__DC_PINSTRAPS_AUDIO__SHIFT 0xe
+#define DC_PINSTRAPS__DC_PINSTRAPS_CCBYPASS_MASK 0x10000
+#define DC_PINSTRAPS__DC_PINSTRAPS_CCBYPASS__SHIFT 0x10
+#define DC_PINSTRAPS__DC_PINSTRAPS_CONNECTIVITY_MASK 0xe0000
+#define DC_PINSTRAPS__DC_PINSTRAPS_CONNECTIVITY__SHIFT 0x11
+#define DC_DVODATA_CONFIG__VIP_MUX_EN_MASK 0x80000
+#define DC_DVODATA_CONFIG__VIP_MUX_EN__SHIFT 0x13
+#define DC_DVODATA_CONFIG__VIP_ALTER_MAPPING_EN_MASK 0x100000
+#define DC_DVODATA_CONFIG__VIP_ALTER_MAPPING_EN__SHIFT 0x14
+#define DC_DVODATA_CONFIG__DVO_ALTER_MAPPING_EN_MASK 0x200000
+#define DC_DVODATA_CONFIG__DVO_ALTER_MAPPING_EN__SHIFT 0x15
+#define LVTMA_PWRSEQ_CNTL__LVTMA_PWRSEQ_EN_MASK 0x1
+#define LVTMA_PWRSEQ_CNTL__LVTMA_PWRSEQ_EN__SHIFT 0x0
+#define LVTMA_PWRSEQ_CNTL__LVTMA_PWRSEQ_DISABLE_SYNCEN_CONTROL_OF_TX_EN_MASK 0x2
+#define LVTMA_PWRSEQ_CNTL__LVTMA_PWRSEQ_DISABLE_SYNCEN_CONTROL_OF_TX_EN__SHIFT 0x1
+#define LVTMA_PWRSEQ_CNTL__LVTMA_PWRSEQ_TARGET_STATE_MASK 0x10
+#define LVTMA_PWRSEQ_CNTL__LVTMA_PWRSEQ_TARGET_STATE__SHIFT 0x4
+#define LVTMA_PWRSEQ_CNTL__LVTMA_SYNCEN_MASK 0x100
+#define LVTMA_PWRSEQ_CNTL__LVTMA_SYNCEN__SHIFT 0x8
+#define LVTMA_PWRSEQ_CNTL__LVTMA_SYNCEN_OVRD_MASK 0x200
+#define LVTMA_PWRSEQ_CNTL__LVTMA_SYNCEN_OVRD__SHIFT 0x9
+#define LVTMA_PWRSEQ_CNTL__LVTMA_SYNCEN_POL_MASK 0x400
+#define LVTMA_PWRSEQ_CNTL__LVTMA_SYNCEN_POL__SHIFT 0xa
+#define LVTMA_PWRSEQ_CNTL__LVTMA_DIGON_MASK 0x10000
+#define LVTMA_PWRSEQ_CNTL__LVTMA_DIGON__SHIFT 0x10
+#define LVTMA_PWRSEQ_CNTL__LVTMA_DIGON_OVRD_MASK 0x20000
+#define LVTMA_PWRSEQ_CNTL__LVTMA_DIGON_OVRD__SHIFT 0x11
+#define LVTMA_PWRSEQ_CNTL__LVTMA_DIGON_POL_MASK 0x40000
+#define LVTMA_PWRSEQ_CNTL__LVTMA_DIGON_POL__SHIFT 0x12
+#define LVTMA_PWRSEQ_CNTL__LVTMA_BLON_MASK 0x1000000
+#define LVTMA_PWRSEQ_CNTL__LVTMA_BLON__SHIFT 0x18
+#define LVTMA_PWRSEQ_CNTL__LVTMA_BLON_OVRD_MASK 0x2000000
+#define LVTMA_PWRSEQ_CNTL__LVTMA_BLON_OVRD__SHIFT 0x19
+#define LVTMA_PWRSEQ_CNTL__LVTMA_BLON_POL_MASK 0x4000000
+#define LVTMA_PWRSEQ_CNTL__LVTMA_BLON_POL__SHIFT 0x1a
+#define LVTMA_PWRSEQ_STATE__LVTMA_PWRSEQ_TARGET_STATE_R_MASK 0x1
+#define LVTMA_PWRSEQ_STATE__LVTMA_PWRSEQ_TARGET_STATE_R__SHIFT 0x0
+#define LVTMA_PWRSEQ_STATE__LVTMA_PWRSEQ_DIGON_MASK 0x2
+#define LVTMA_PWRSEQ_STATE__LVTMA_PWRSEQ_DIGON__SHIFT 0x1
+#define LVTMA_PWRSEQ_STATE__LVTMA_PWRSEQ_SYNCEN_MASK 0x4
+#define LVTMA_PWRSEQ_STATE__LVTMA_PWRSEQ_SYNCEN__SHIFT 0x2
+#define LVTMA_PWRSEQ_STATE__LVTMA_PWRSEQ_BLON_MASK 0x8
+#define LVTMA_PWRSEQ_STATE__LVTMA_PWRSEQ_BLON__SHIFT 0x3
+#define LVTMA_PWRSEQ_STATE__LVTMA_PWRSEQ_DONE_MASK 0x10
+#define LVTMA_PWRSEQ_STATE__LVTMA_PWRSEQ_DONE__SHIFT 0x4
+#define LVTMA_PWRSEQ_STATE__LVTMA_PWRSEQ_STATE_MASK 0xf00
+#define LVTMA_PWRSEQ_STATE__LVTMA_PWRSEQ_STATE__SHIFT 0x8
+#define LVTMA_PWRSEQ_REF_DIV__LVTMA_PWRSEQ_REF_DIV_MASK 0xfff
+#define LVTMA_PWRSEQ_REF_DIV__LVTMA_PWRSEQ_REF_DIV__SHIFT 0x0
+#define LVTMA_PWRSEQ_REF_DIV__BL_PWM_REF_DIV_MASK 0xffff0000
+#define LVTMA_PWRSEQ_REF_DIV__BL_PWM_REF_DIV__SHIFT 0x10
+#define LVTMA_PWRSEQ_DELAY1__LVTMA_PWRUP_DELAY1_MASK 0xff
+#define LVTMA_PWRSEQ_DELAY1__LVTMA_PWRUP_DELAY1__SHIFT 0x0
+#define LVTMA_PWRSEQ_DELAY1__LVTMA_PWRUP_DELAY2_MASK 0xff00
+#define LVTMA_PWRSEQ_DELAY1__LVTMA_PWRUP_DELAY2__SHIFT 0x8
+#define LVTMA_PWRSEQ_DELAY1__LVTMA_PWRDN_DELAY1_MASK 0xff0000
+#define LVTMA_PWRSEQ_DELAY1__LVTMA_PWRDN_DELAY1__SHIFT 0x10
+#define LVTMA_PWRSEQ_DELAY1__LVTMA_PWRDN_DELAY2_MASK 0xff000000
+#define LVTMA_PWRSEQ_DELAY1__LVTMA_PWRDN_DELAY2__SHIFT 0x18
+#define LVTMA_PWRSEQ_DELAY2__LVTMA_PWRDN_MIN_LENGTH_MASK 0xff
+#define LVTMA_PWRSEQ_DELAY2__LVTMA_PWRDN_MIN_LENGTH__SHIFT 0x0
+#define LVTMA_PWRSEQ_DELAY2__LVTMA_PWRUP_DELAY3_MASK 0xff00
+#define LVTMA_PWRSEQ_DELAY2__LVTMA_PWRUP_DELAY3__SHIFT 0x8
+#define LVTMA_PWRSEQ_DELAY2__LVTMA_PWRDN_DELAY3_MASK 0xff0000
+#define LVTMA_PWRSEQ_DELAY2__LVTMA_PWRDN_DELAY3__SHIFT 0x10
+#define LVTMA_PWRSEQ_DELAY2__LVTMA_VARY_BL_OVERRIDE_EN_MASK 0x1000000
+#define LVTMA_PWRSEQ_DELAY2__LVTMA_VARY_BL_OVERRIDE_EN__SHIFT 0x18
+#define BL_PWM_CNTL__BL_ACTIVE_INT_FRAC_CNT_MASK 0xffff
+#define BL_PWM_CNTL__BL_ACTIVE_INT_FRAC_CNT__SHIFT 0x0
+#define BL_PWM_CNTL__BL_PWM_FRACTIONAL_EN_MASK 0x40000000
+#define BL_PWM_CNTL__BL_PWM_FRACTIONAL_EN__SHIFT 0x1e
+#define BL_PWM_CNTL__BL_PWM_EN_MASK 0x80000000
+#define BL_PWM_CNTL__BL_PWM_EN__SHIFT 0x1f
+#define BL_PWM_CNTL2__BL_PWM_POST_FRAME_START_DELAY_BEFORE_UPDATE_MASK 0xffff
+#define BL_PWM_CNTL2__BL_PWM_POST_FRAME_START_DELAY_BEFORE_UPDATE__SHIFT 0x0
+#define BL_PWM_CNTL2__DBG_BL_PWM_INPUT_REFCLK_SELECT_MASK 0x30000000
+#define BL_PWM_CNTL2__DBG_BL_PWM_INPUT_REFCLK_SELECT__SHIFT 0x1c
+#define BL_PWM_CNTL2__BL_PWM_OVERRIDE_BL_OUT_ENABLE_MASK 0x40000000
+#define BL_PWM_CNTL2__BL_PWM_OVERRIDE_BL_OUT_ENABLE__SHIFT 0x1e
+#define BL_PWM_CNTL2__BL_PWM_OVERRIDE_LVTMA_PWRSEQ_EN_MASK 0x80000000
+#define BL_PWM_CNTL2__BL_PWM_OVERRIDE_LVTMA_PWRSEQ_EN__SHIFT 0x1f
+#define BL_PWM_PERIOD_CNTL__BL_PWM_PERIOD_MASK 0xffff
+#define BL_PWM_PERIOD_CNTL__BL_PWM_PERIOD__SHIFT 0x0
+#define BL_PWM_PERIOD_CNTL__BL_PWM_PERIOD_BITCNT_MASK 0xf0000
+#define BL_PWM_PERIOD_CNTL__BL_PWM_PERIOD_BITCNT__SHIFT 0x10
+#define BL_PWM_GRP1_REG_LOCK__BL_PWM_GRP1_REG_LOCK_MASK 0x1
+#define BL_PWM_GRP1_REG_LOCK__BL_PWM_GRP1_REG_LOCK__SHIFT 0x0
+#define BL_PWM_GRP1_REG_LOCK__BL_PWM_GRP1_REG_UPDATE_PENDING_MASK 0x100
+#define BL_PWM_GRP1_REG_LOCK__BL_PWM_GRP1_REG_UPDATE_PENDING__SHIFT 0x8
+#define BL_PWM_GRP1_REG_LOCK__BL_PWM_GRP1_UPDATE_AT_FRAME_START_MASK 0x10000
+#define BL_PWM_GRP1_REG_LOCK__BL_PWM_GRP1_UPDATE_AT_FRAME_START__SHIFT 0x10
+#define BL_PWM_GRP1_REG_LOCK__BL_PWM_GRP1_FRAME_START_DISP_SEL_MASK 0xe0000
+#define BL_PWM_GRP1_REG_LOCK__BL_PWM_GRP1_FRAME_START_DISP_SEL__SHIFT 0x11
+#define BL_PWM_GRP1_REG_LOCK__BL_PWM_GRP1_READBACK_DB_REG_VALUE_EN_MASK 0x1000000
+#define BL_PWM_GRP1_REG_LOCK__BL_PWM_GRP1_READBACK_DB_REG_VALUE_EN__SHIFT 0x18
+#define BL_PWM_GRP1_REG_LOCK__BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN_MASK 0x80000000
+#define BL_PWM_GRP1_REG_LOCK__BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN__SHIFT 0x1f
+#define DCIO_GSL_GENLK_PAD_CNTL__DCIO_GENLK_CLK_GSL_TIMING_SYNC_SEL_MASK 0x3
+#define DCIO_GSL_GENLK_PAD_CNTL__DCIO_GENLK_CLK_GSL_TIMING_SYNC_SEL__SHIFT 0x0
+#define DCIO_GSL_GENLK_PAD_CNTL__DCIO_GENLK_CLK_GSL_FLIP_LOCK_SEL_MASK 0x30
+#define DCIO_GSL_GENLK_PAD_CNTL__DCIO_GENLK_CLK_GSL_FLIP_LOCK_SEL__SHIFT 0x4
+#define DCIO_GSL_GENLK_PAD_CNTL__DCIO_GENLK_CLK_GSL_MASK_MASK 0x300
+#define DCIO_GSL_GENLK_PAD_CNTL__DCIO_GENLK_CLK_GSL_MASK__SHIFT 0x8
+#define DCIO_GSL_GENLK_PAD_CNTL__DCIO_GENLK_VSYNC_GSL_TIMING_SYNC_SEL_MASK 0x30000
+#define DCIO_GSL_GENLK_PAD_CNTL__DCIO_GENLK_VSYNC_GSL_TIMING_SYNC_SEL__SHIFT 0x10
+#define DCIO_GSL_GENLK_PAD_CNTL__DCIO_GENLK_VSYNC_GSL_FLIP_LOCK_SEL_MASK 0x300000
+#define DCIO_GSL_GENLK_PAD_CNTL__DCIO_GENLK_VSYNC_GSL_FLIP_LOCK_SEL__SHIFT 0x14
+#define DCIO_GSL_GENLK_PAD_CNTL__DCIO_GENLK_VSYNC_GSL_MASK_MASK 0x3000000
+#define DCIO_GSL_GENLK_PAD_CNTL__DCIO_GENLK_VSYNC_GSL_MASK__SHIFT 0x18
+#define DCIO_GSL_SWAPLOCK_PAD_CNTL__DCIO_SWAPLOCK_A_GSL_TIMING_SYNC_SEL_MASK 0x3
+#define DCIO_GSL_SWAPLOCK_PAD_CNTL__DCIO_SWAPLOCK_A_GSL_TIMING_SYNC_SEL__SHIFT 0x0
+#define DCIO_GSL_SWAPLOCK_PAD_CNTL__DCIO_SWAPLOCK_A_GSL_FLIP_LOCK_SEL_MASK 0x30
+#define DCIO_GSL_SWAPLOCK_PAD_CNTL__DCIO_SWAPLOCK_A_GSL_FLIP_LOCK_SEL__SHIFT 0x4
+#define DCIO_GSL_SWAPLOCK_PAD_CNTL__DCIO_SWAPLOCK_A_GSL_MASK_MASK 0x300
+#define DCIO_GSL_SWAPLOCK_PAD_CNTL__DCIO_SWAPLOCK_A_GSL_MASK__SHIFT 0x8
+#define DCIO_GSL_SWAPLOCK_PAD_CNTL__DCIO_SWAPLOCK_B_GSL_TIMING_SYNC_SEL_MASK 0x30000
+#define DCIO_GSL_SWAPLOCK_PAD_CNTL__DCIO_SWAPLOCK_B_GSL_TIMING_SYNC_SEL__SHIFT 0x10
+#define DCIO_GSL_SWAPLOCK_PAD_CNTL__DCIO_SWAPLOCK_B_GSL_FLIP_LOCK_SEL_MASK 0x300000
+#define DCIO_GSL_SWAPLOCK_PAD_CNTL__DCIO_SWAPLOCK_B_GSL_FLIP_LOCK_SEL__SHIFT 0x14
+#define DCIO_GSL_SWAPLOCK_PAD_CNTL__DCIO_SWAPLOCK_B_GSL_MASK_MASK 0x3000000
+#define DCIO_GSL_SWAPLOCK_PAD_CNTL__DCIO_SWAPLOCK_B_GSL_MASK__SHIFT 0x18
+#define DCIO_GSL0_CNTL__DCIO_GSL0_VSYNC_SEL_MASK 0x7
+#define DCIO_GSL0_CNTL__DCIO_GSL0_VSYNC_SEL__SHIFT 0x0
+#define DCIO_GSL0_CNTL__DCIO_GSL0_TIMING_SYNC_SEL_MASK 0x700
+#define DCIO_GSL0_CNTL__DCIO_GSL0_TIMING_SYNC_SEL__SHIFT 0x8
+#define DCIO_GSL0_CNTL__DCIO_GSL0_GLOBAL_UNLOCK_SEL_MASK 0x70000
+#define DCIO_GSL0_CNTL__DCIO_GSL0_GLOBAL_UNLOCK_SEL__SHIFT 0x10
+#define DCIO_GSL1_CNTL__DCIO_GSL1_VSYNC_SEL_MASK 0x7
+#define DCIO_GSL1_CNTL__DCIO_GSL1_VSYNC_SEL__SHIFT 0x0
+#define DCIO_GSL1_CNTL__DCIO_GSL1_TIMING_SYNC_SEL_MASK 0x700
+#define DCIO_GSL1_CNTL__DCIO_GSL1_TIMING_SYNC_SEL__SHIFT 0x8
+#define DCIO_GSL1_CNTL__DCIO_GSL1_GLOBAL_UNLOCK_SEL_MASK 0x70000
+#define DCIO_GSL1_CNTL__DCIO_GSL1_GLOBAL_UNLOCK_SEL__SHIFT 0x10
+#define DCIO_GSL2_CNTL__DCIO_GSL2_VSYNC_SEL_MASK 0x7
+#define DCIO_GSL2_CNTL__DCIO_GSL2_VSYNC_SEL__SHIFT 0x0
+#define DCIO_GSL2_CNTL__DCIO_GSL2_TIMING_SYNC_SEL_MASK 0x700
+#define DCIO_GSL2_CNTL__DCIO_GSL2_TIMING_SYNC_SEL__SHIFT 0x8
+#define DCIO_GSL2_CNTL__DCIO_GSL2_GLOBAL_UNLOCK_SEL_MASK 0x70000
+#define DCIO_GSL2_CNTL__DCIO_GSL2_GLOBAL_UNLOCK_SEL__SHIFT 0x10
+#define DC_GPU_TIMER_START_POSITION_V_UPDATE__DC_GPU_TIMER_START_POSITION_D1_V_UPDATE_MASK 0x7
+#define DC_GPU_TIMER_START_POSITION_V_UPDATE__DC_GPU_TIMER_START_POSITION_D1_V_UPDATE__SHIFT 0x0
+#define DC_GPU_TIMER_START_POSITION_V_UPDATE__DC_GPU_TIMER_START_POSITION_D2_V_UPDATE_MASK 0x70
+#define DC_GPU_TIMER_START_POSITION_V_UPDATE__DC_GPU_TIMER_START_POSITION_D2_V_UPDATE__SHIFT 0x4
+#define DC_GPU_TIMER_START_POSITION_V_UPDATE__DC_GPU_TIMER_START_POSITION_D3_V_UPDATE_MASK 0x700
+#define DC_GPU_TIMER_START_POSITION_V_UPDATE__DC_GPU_TIMER_START_POSITION_D3_V_UPDATE__SHIFT 0x8
+#define DC_GPU_TIMER_START_POSITION_V_UPDATE__DC_GPU_TIMER_START_POSITION_D4_V_UPDATE_MASK 0x7000
+#define DC_GPU_TIMER_START_POSITION_V_UPDATE__DC_GPU_TIMER_START_POSITION_D4_V_UPDATE__SHIFT 0xc
+#define DC_GPU_TIMER_START_POSITION_V_UPDATE__DC_GPU_TIMER_START_POSITION_D5_V_UPDATE_MASK 0x70000
+#define DC_GPU_TIMER_START_POSITION_V_UPDATE__DC_GPU_TIMER_START_POSITION_D5_V_UPDATE__SHIFT 0x10
+#define DC_GPU_TIMER_START_POSITION_V_UPDATE__DC_GPU_TIMER_START_POSITION_D6_V_UPDATE_MASK 0x700000
+#define DC_GPU_TIMER_START_POSITION_V_UPDATE__DC_GPU_TIMER_START_POSITION_D6_V_UPDATE__SHIFT 0x14
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_D1_P_FLIP_MASK 0x7
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_D1_P_FLIP__SHIFT 0x0
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_D2_P_FLIP_MASK 0x70
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_D2_P_FLIP__SHIFT 0x4
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_D3_P_FLIP_MASK 0x700
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_D3_P_FLIP__SHIFT 0x8
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_D4_P_FLIP_MASK 0x7000
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_D4_P_FLIP__SHIFT 0xc
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_D5_P_FLIP_MASK 0x70000
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_D5_P_FLIP__SHIFT 0x10
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_D6_P_FLIP_MASK 0x700000
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_D6_P_FLIP__SHIFT 0x14
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_DCFEV0_P_FLIP_MASK 0x3800000
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_DCFEV0_P_FLIP__SHIFT 0x17
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_DCFEV1_P_FLIP_MASK 0x1c000000
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_DCFEV1_P_FLIP__SHIFT 0x1a
+#define DC_GPU_TIMER_READ__DC_GPU_TIMER_READ_MASK 0xffffffff
+#define DC_GPU_TIMER_READ__DC_GPU_TIMER_READ__SHIFT 0x0
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_READ_SELECT_MASK 0x3f
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_READ_SELECT__SHIFT 0x0
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_START_POSITION_D1_VSYNC_NOM_MASK 0x700
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_START_POSITION_D1_VSYNC_NOM__SHIFT 0x8
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_START_POSITION_D2_VSYNC_NOM_MASK 0x3800
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_START_POSITION_D2_VSYNC_NOM__SHIFT 0xb
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_START_POSITION_D3_VSYNC_NOM_MASK 0x1c000
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_START_POSITION_D3_VSYNC_NOM__SHIFT 0xe
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_START_POSITION_D4_VSYNC_NOM_MASK 0xe0000
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_START_POSITION_D4_VSYNC_NOM__SHIFT 0x11
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_START_POSITION_D5_VSYNC_NOM_MASK 0x700000
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_START_POSITION_D5_VSYNC_NOM__SHIFT 0x14
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_START_POSITION_D6_VSYNC_NOM_MASK 0x3800000
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_START_POSITION_D6_VSYNC_NOM__SHIFT 0x17
+#define DCIO_CLOCK_CNTL__DCIO_TEST_CLK_SEL_MASK 0x1f
+#define DCIO_CLOCK_CNTL__DCIO_TEST_CLK_SEL__SHIFT 0x0
+#define DCIO_CLOCK_CNTL__DISPCLK_R_DCIO_GATE_DIS_MASK 0x20
+#define DCIO_CLOCK_CNTL__DISPCLK_R_DCIO_GATE_DIS__SHIFT 0x5
+#define DCIO_DEBUG__DCIO_DEBUG_MASK 0xffffffff
+#define DCIO_DEBUG__DCIO_DEBUG__SHIFT 0x0
+#define DCO_DCFE_EXT_VSYNC_CNTL__DCO_DCFE0_EXT_VSYNC_MUX_MASK 0x7
+#define DCO_DCFE_EXT_VSYNC_CNTL__DCO_DCFE0_EXT_VSYNC_MUX__SHIFT 0x0
+#define DCO_DCFE_EXT_VSYNC_CNTL__DCO_DCFE1_EXT_VSYNC_MUX_MASK 0x70
+#define DCO_DCFE_EXT_VSYNC_CNTL__DCO_DCFE1_EXT_VSYNC_MUX__SHIFT 0x4
+#define DCO_DCFE_EXT_VSYNC_CNTL__DCO_DCFE2_EXT_VSYNC_MUX_MASK 0x700
+#define DCO_DCFE_EXT_VSYNC_CNTL__DCO_DCFE2_EXT_VSYNC_MUX__SHIFT 0x8
+#define DCO_DCFE_EXT_VSYNC_CNTL__DCO_DCFE3_EXT_VSYNC_MUX_MASK 0x7000
+#define DCO_DCFE_EXT_VSYNC_CNTL__DCO_DCFE3_EXT_VSYNC_MUX__SHIFT 0xc
+#define DCO_DCFE_EXT_VSYNC_CNTL__DCO_DCFE4_EXT_VSYNC_MUX_MASK 0x70000
+#define DCO_DCFE_EXT_VSYNC_CNTL__DCO_DCFE4_EXT_VSYNC_MUX__SHIFT 0x10
+#define DCO_DCFE_EXT_VSYNC_CNTL__DCO_DCFE5_EXT_VSYNC_MUX_MASK 0x700000
+#define DCO_DCFE_EXT_VSYNC_CNTL__DCO_DCFE5_EXT_VSYNC_MUX__SHIFT 0x14
+#define DCO_DCFE_EXT_VSYNC_CNTL__DCO_SWAPLOCKB_EXT_VSYNC_MASK_MASK 0x7000000
+#define DCO_DCFE_EXT_VSYNC_CNTL__DCO_SWAPLOCKB_EXT_VSYNC_MASK__SHIFT 0x18
+#define DCO_DCFE_EXT_VSYNC_CNTL__DCO_GENERICB_EXT_VSYNC_MASK_MASK 0x70000000
+#define DCO_DCFE_EXT_VSYNC_CNTL__DCO_GENERICB_EXT_VSYNC_MASK__SHIFT 0x1c
+#define DCO_DCFE_EXT_VSYNC_CNTL__DCO_CRTC_MANUAL_FLOW_CONTROL_MASK 0x80000000
+#define DCO_DCFE_EXT_VSYNC_CNTL__DCO_CRTC_MANUAL_FLOW_CONTROL__SHIFT 0x1f
+#define DBG_OUT_CNTL__DBG_OUT_PIN_EN_MASK 0x1
+#define DBG_OUT_CNTL__DBG_OUT_PIN_EN__SHIFT 0x0
+#define DBG_OUT_CNTL__DBG_OUT_PIN_SEL_MASK 0x10
+#define DBG_OUT_CNTL__DBG_OUT_PIN_SEL__SHIFT 0x4
+#define DBG_OUT_CNTL__DBG_OUT_12BIT_SEL_MASK 0x300
+#define DBG_OUT_CNTL__DBG_OUT_12BIT_SEL__SHIFT 0x8
+#define DBG_OUT_CNTL__DBG_OUT_TEST_DATA_MASK 0xfff000
+#define DBG_OUT_CNTL__DBG_OUT_TEST_DATA__SHIFT 0xc
+#define DCIO_DEBUG_CONFIG__DCIO_DBG_EN_MASK 0x1
+#define DCIO_DEBUG_CONFIG__DCIO_DBG_EN__SHIFT 0x0
+#define DCIO_DEBUG_CONFIG__DCIO_DBG_SEL_MASK 0xf00
+#define DCIO_DEBUG_CONFIG__DCIO_DBG_SEL__SHIFT 0x8
+#define DCIO_SOFT_RESET__UNIPHYA_SOFT_RESET_MASK 0x1
+#define DCIO_SOFT_RESET__UNIPHYA_SOFT_RESET__SHIFT 0x0
+#define DCIO_SOFT_RESET__DSYNCA_SOFT_RESET_MASK 0x2
+#define DCIO_SOFT_RESET__DSYNCA_SOFT_RESET__SHIFT 0x1
+#define DCIO_SOFT_RESET__UNIPHYB_SOFT_RESET_MASK 0x4
+#define DCIO_SOFT_RESET__UNIPHYB_SOFT_RESET__SHIFT 0x2
+#define DCIO_SOFT_RESET__DSYNCB_SOFT_RESET_MASK 0x8
+#define DCIO_SOFT_RESET__DSYNCB_SOFT_RESET__SHIFT 0x3
+#define DCIO_SOFT_RESET__UNIPHYC_SOFT_RESET_MASK 0x10
+#define DCIO_SOFT_RESET__UNIPHYC_SOFT_RESET__SHIFT 0x4
+#define DCIO_SOFT_RESET__DSYNCC_SOFT_RESET_MASK 0x20
+#define DCIO_SOFT_RESET__DSYNCC_SOFT_RESET__SHIFT 0x5
+#define DCIO_SOFT_RESET__UNIPHYD_SOFT_RESET_MASK 0x40
+#define DCIO_SOFT_RESET__UNIPHYD_SOFT_RESET__SHIFT 0x6
+#define DCIO_SOFT_RESET__DSYNCD_SOFT_RESET_MASK 0x80
+#define DCIO_SOFT_RESET__DSYNCD_SOFT_RESET__SHIFT 0x7
+#define DCIO_SOFT_RESET__UNIPHYE_SOFT_RESET_MASK 0x100
+#define DCIO_SOFT_RESET__UNIPHYE_SOFT_RESET__SHIFT 0x8
+#define DCIO_SOFT_RESET__DSYNCE_SOFT_RESET_MASK 0x200
+#define DCIO_SOFT_RESET__DSYNCE_SOFT_RESET__SHIFT 0x9
+#define DCIO_SOFT_RESET__UNIPHYF_SOFT_RESET_MASK 0x400
+#define DCIO_SOFT_RESET__UNIPHYF_SOFT_RESET__SHIFT 0xa
+#define DCIO_SOFT_RESET__DSYNCF_SOFT_RESET_MASK 0x800
+#define DCIO_SOFT_RESET__DSYNCF_SOFT_RESET__SHIFT 0xb
+#define DCIO_SOFT_RESET__UNIPHYG_SOFT_RESET_MASK 0x1000
+#define DCIO_SOFT_RESET__UNIPHYG_SOFT_RESET__SHIFT 0xc
+#define DCIO_SOFT_RESET__DSYNCG_SOFT_RESET_MASK 0x2000
+#define DCIO_SOFT_RESET__DSYNCG_SOFT_RESET__SHIFT 0xd
+#define DCIO_SOFT_RESET__DACA_SOFT_RESET_MASK 0x10000
+#define DCIO_SOFT_RESET__DACA_SOFT_RESET__SHIFT 0x10
+#define DCIO_SOFT_RESET__DCRXPHY_SOFT_RESET_MASK 0x100000
+#define DCIO_SOFT_RESET__DCRXPHY_SOFT_RESET__SHIFT 0x14
+#define DCIO_SOFT_RESET__DPHY_SOFT_RESET_MASK 0x1000000
+#define DCIO_SOFT_RESET__DPHY_SOFT_RESET__SHIFT 0x18
+#define DCIO_SOFT_RESET__ZCAL_SOFT_RESET_MASK 0x4000000
+#define DCIO_SOFT_RESET__ZCAL_SOFT_RESET__SHIFT 0x1a
+#define DCIO_SOFT_RESET__UNIPHYLPA_SOFT_RESET_MASK 0x10000000
+#define DCIO_SOFT_RESET__UNIPHYLPA_SOFT_RESET__SHIFT 0x1c
+#define DCIO_SOFT_RESET__DSYNCLPA_SOFT_RESET_MASK 0x20000000
+#define DCIO_SOFT_RESET__DSYNCLPA_SOFT_RESET__SHIFT 0x1d
+#define DCIO_SOFT_RESET__UNIPHYLPB_SOFT_RESET_MASK 0x40000000
+#define DCIO_SOFT_RESET__UNIPHYLPB_SOFT_RESET__SHIFT 0x1e
+#define DCIO_SOFT_RESET__DSYNCLPB_SOFT_RESET_MASK 0x80000000
+#define DCIO_SOFT_RESET__DSYNCLPB_SOFT_RESET__SHIFT 0x1f
+#define DCIO_DPHY_SEL__DPHY_LANE0_SEL_MASK 0x3
+#define DCIO_DPHY_SEL__DPHY_LANE0_SEL__SHIFT 0x0
+#define DCIO_DPHY_SEL__DPHY_LANE1_SEL_MASK 0xc
+#define DCIO_DPHY_SEL__DPHY_LANE1_SEL__SHIFT 0x2
+#define DCIO_DPHY_SEL__DPHY_LANE2_SEL_MASK 0x30
+#define DCIO_DPHY_SEL__DPHY_LANE2_SEL__SHIFT 0x4
+#define DCIO_DPHY_SEL__DPHY_LANE3_SEL_MASK 0xc0
+#define DCIO_DPHY_SEL__DPHY_LANE3_SEL__SHIFT 0x6
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXA_INT_TYPE_MASK 0x1
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXA_INT_TYPE__SHIFT 0x0
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXA_INT_MASK_MASK 0x2
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXA_INT_MASK__SHIFT 0x1
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXA_INT_OCCUR_MASK 0x4
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXA_INT_OCCUR__SHIFT 0x2
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXB_INT_TYPE_MASK 0x8
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXB_INT_TYPE__SHIFT 0x3
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXB_INT_MASK_MASK 0x10
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXB_INT_MASK__SHIFT 0x4
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXB_INT_OCCUR_MASK 0x20
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXB_INT_OCCUR__SHIFT 0x5
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXC_INT_TYPE_MASK 0x40
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXC_INT_TYPE__SHIFT 0x6
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXC_INT_MASK_MASK 0x80
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXC_INT_MASK__SHIFT 0x7
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXC_INT_OCCUR_MASK 0x100
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXC_INT_OCCUR__SHIFT 0x8
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXD_INT_TYPE_MASK 0x200
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXD_INT_TYPE__SHIFT 0x9
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXD_INT_MASK_MASK 0x400
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXD_INT_MASK__SHIFT 0xa
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXD_INT_OCCUR_MASK 0x800
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXD_INT_OCCUR__SHIFT 0xb
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXE_INT_TYPE_MASK 0x1000
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXE_INT_TYPE__SHIFT 0xc
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXE_INT_MASK_MASK 0x2000
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXE_INT_MASK__SHIFT 0xd
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXE_INT_OCCUR_MASK 0x4000
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXE_INT_OCCUR__SHIFT 0xe
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXF_INT_TYPE_MASK 0x8000
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXF_INT_TYPE__SHIFT 0xf
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXF_INT_MASK_MASK 0x10000
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXF_INT_MASK__SHIFT 0x10
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXF_INT_OCCUR_MASK 0x20000
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXF_INT_OCCUR__SHIFT 0x11
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXG_INT_TYPE_MASK 0x40000
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXG_INT_TYPE__SHIFT 0x12
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXG_INT_MASK_MASK 0x80000
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXG_INT_MASK__SHIFT 0x13
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXG_INT_OCCUR_MASK 0x100000
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXG_INT_OCCUR__SHIFT 0x14
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXLPA_INT_TYPE_MASK 0x1000000
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXLPA_INT_TYPE__SHIFT 0x18
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXLPA_INT_MASK_MASK 0x2000000
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXLPA_INT_MASK__SHIFT 0x19
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXLPA_INT_OCCUR_MASK 0x4000000
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXLPA_INT_OCCUR__SHIFT 0x1a
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXLPB_INT_TYPE_MASK 0x8000000
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXLPB_INT_TYPE__SHIFT 0x1b
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXLPB_INT_MASK_MASK 0x10000000
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXLPB_INT_MASK__SHIFT 0x1c
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXLPB_INT_OCCUR_MASK 0x20000000
+#define DCIO_DPCS_TX_INTERRUPT__DCIO_DPCS_TXLPB_INT_OCCUR__SHIFT 0x1d
+#define DCIO_DPCS_RX_INTERRUPT__DCIO_DPCS_RXA_INT_TYPE_MASK 0x1
+#define DCIO_DPCS_RX_INTERRUPT__DCIO_DPCS_RXA_INT_TYPE__SHIFT 0x0
+#define DCIO_DPCS_RX_INTERRUPT__DCIO_DPCS_RXA_INT_MASK_MASK 0x2
+#define DCIO_DPCS_RX_INTERRUPT__DCIO_DPCS_RXA_INT_MASK__SHIFT 0x1
+#define DCIO_DPCS_RX_INTERRUPT__DCIO_DPCS_RXA_INT_OCCUR_MASK 0x4
+#define DCIO_DPCS_RX_INTERRUPT__DCIO_DPCS_RXA_INT_OCCUR__SHIFT 0x2
+#define DCIO_SEMAPHORE0__DCIO_SEMAPHORE0_REQ_MASK 0xffff
+#define DCIO_SEMAPHORE0__DCIO_SEMAPHORE0_REQ__SHIFT 0x0
+#define DCIO_SEMAPHORE0__DCIO_SEMAPHORE0_GNT_MASK 0xffff0000
+#define DCIO_SEMAPHORE0__DCIO_SEMAPHORE0_GNT__SHIFT 0x10
+#define DCIO_SEMAPHORE1__DCIO_SEMAPHORE1_REQ_MASK 0xffff
+#define DCIO_SEMAPHORE1__DCIO_SEMAPHORE1_REQ__SHIFT 0x0
+#define DCIO_SEMAPHORE1__DCIO_SEMAPHORE1_GNT_MASK 0xffff0000
+#define DCIO_SEMAPHORE1__DCIO_SEMAPHORE1_GNT__SHIFT 0x10
+#define DCIO_SEMAPHORE2__DCIO_SEMAPHORE2_REQ_MASK 0xffff
+#define DCIO_SEMAPHORE2__DCIO_SEMAPHORE2_REQ__SHIFT 0x0
+#define DCIO_SEMAPHORE2__DCIO_SEMAPHORE2_GNT_MASK 0xffff0000
+#define DCIO_SEMAPHORE2__DCIO_SEMAPHORE2_GNT__SHIFT 0x10
+#define DCIO_SEMAPHORE3__DCIO_SEMAPHORE3_REQ_MASK 0xffff
+#define DCIO_SEMAPHORE3__DCIO_SEMAPHORE3_REQ__SHIFT 0x0
+#define DCIO_SEMAPHORE3__DCIO_SEMAPHORE3_GNT_MASK 0xffff0000
+#define DCIO_SEMAPHORE3__DCIO_SEMAPHORE3_GNT__SHIFT 0x10
+#define DCIO_SEMAPHORE4__DCIO_SEMAPHORE4_REQ_MASK 0xffff
+#define DCIO_SEMAPHORE4__DCIO_SEMAPHORE4_REQ__SHIFT 0x0
+#define DCIO_SEMAPHORE4__DCIO_SEMAPHORE4_GNT_MASK 0xffff0000
+#define DCIO_SEMAPHORE4__DCIO_SEMAPHORE4_GNT__SHIFT 0x10
+#define DCIO_SEMAPHORE5__DCIO_SEMAPHORE5_REQ_MASK 0xffff
+#define DCIO_SEMAPHORE5__DCIO_SEMAPHORE5_REQ__SHIFT 0x0
+#define DCIO_SEMAPHORE5__DCIO_SEMAPHORE5_GNT_MASK 0xffff0000
+#define DCIO_SEMAPHORE5__DCIO_SEMAPHORE5_GNT__SHIFT 0x10
+#define DCIO_SEMAPHORE6__DCIO_SEMAPHORE6_REQ_MASK 0xffff
+#define DCIO_SEMAPHORE6__DCIO_SEMAPHORE6_REQ__SHIFT 0x0
+#define DCIO_SEMAPHORE6__DCIO_SEMAPHORE6_GNT_MASK 0xffff0000
+#define DCIO_SEMAPHORE6__DCIO_SEMAPHORE6_GNT__SHIFT 0x10
+#define DCIO_SEMAPHORE7__DCIO_SEMAPHORE7_REQ_MASK 0xffff
+#define DCIO_SEMAPHORE7__DCIO_SEMAPHORE7_REQ__SHIFT 0x0
+#define DCIO_SEMAPHORE7__DCIO_SEMAPHORE7_GNT_MASK 0xffff0000
+#define DCIO_SEMAPHORE7__DCIO_SEMAPHORE7_GNT__SHIFT 0x10
+#define DCIO_TEST_DEBUG_INDEX__DCIO_TEST_DEBUG_INDEX_MASK 0xff
+#define DCIO_TEST_DEBUG_INDEX__DCIO_TEST_DEBUG_INDEX__SHIFT 0x0
+#define DCIO_TEST_DEBUG_INDEX__DCIO_TEST_DEBUG_WRITE_EN_MASK 0x100
+#define DCIO_TEST_DEBUG_INDEX__DCIO_TEST_DEBUG_WRITE_EN__SHIFT 0x8
+#define DCIO_TEST_DEBUG_DATA__DCIO_TEST_DEBUG_DATA_MASK 0xffffffff
+#define DCIO_TEST_DEBUG_DATA__DCIO_TEST_DEBUG_DATA__SHIFT 0x0
+#define DCIO_DEBUG1__DCO_DCIO_MVP_DVOCNTL_A0_REG_MASK 0x3
+#define DCIO_DEBUG1__DCO_DCIO_MVP_DVOCNTL_A0_REG__SHIFT 0x0
+#define DCIO_DEBUG1__DCO_DCIO_MVP_DVOCNTL_MASK_REG_MASK 0xc
+#define DCIO_DEBUG1__DCO_DCIO_MVP_DVOCNTL_MASK_REG__SHIFT 0x2
+#define DCIO_DEBUG1__DCO_DCIO_MVP_DVOCNTL_EN_REG_MASK 0x30
+#define DCIO_DEBUG1__DCO_DCIO_MVP_DVOCNTL_EN_REG__SHIFT 0x4
+#define DCIO_DEBUG1__DCO_DCIO_MVP_DVOCNTL_A0_MASK 0xc0
+#define DCIO_DEBUG1__DCO_DCIO_MVP_DVOCNTL_A0__SHIFT 0x6
+#define DCIO_DEBUG1__DCO_DCIO_MVP_DVOCNTL_SEL0_MASK 0x300
+#define DCIO_DEBUG1__DCO_DCIO_MVP_DVOCNTL_SEL0__SHIFT 0x8
+#define DCIO_DEBUG1__DCO_DCIO_MVP_DVOCNTL_EN_MASK 0xc00
+#define DCIO_DEBUG1__DCO_DCIO_MVP_DVOCNTL_EN__SHIFT 0xa
+#define DCIO_DEBUG1__DCO_DCIO_MVP_DVOCLK_C_MASK 0x1000
+#define DCIO_DEBUG1__DCO_DCIO_MVP_DVOCLK_C__SHIFT 0xc
+#define DCIO_DEBUG1__DCO_DCIO_DVOCNTL1_A0_REG_MASK 0x2000
+#define DCIO_DEBUG1__DCO_DCIO_DVOCNTL1_A0_REG__SHIFT 0xd
+#define DCIO_DEBUG1__DCO_DCIO_DVOCNTL1_A0_PREMUX_MASK 0x4000
+#define DCIO_DEBUG1__DCO_DCIO_DVOCNTL1_A0_PREMUX__SHIFT 0xe
+#define DCIO_DEBUG1__DCO_DCIO_DVOCNTL1_A0_MASK 0x8000
+#define DCIO_DEBUG1__DCO_DCIO_DVOCNTL1_A0__SHIFT 0xf
+#define DCIO_DEBUG1__DCO_DCIO_DVOCNTL1_EN_REG_MASK 0x10000
+#define DCIO_DEBUG1__DCO_DCIO_DVOCNTL1_EN_REG__SHIFT 0x10
+#define DCIO_DEBUG1__DCO_DCIO_DVO_HSYNC_TRISTATE_MASK 0x20000
+#define DCIO_DEBUG1__DCO_DCIO_DVO_HSYNC_TRISTATE__SHIFT 0x11
+#define DCIO_DEBUG1__DCO_DCIO_DVO_CLK_TRISTATE_MASK 0x40000
+#define DCIO_DEBUG1__DCO_DCIO_DVO_CLK_TRISTATE__SHIFT 0x12
+#define DCIO_DEBUG1__DCO_DCIO_DVOCNTL1_EN_PREMUX_MASK 0x80000
+#define DCIO_DEBUG1__DCO_DCIO_DVOCNTL1_EN_PREMUX__SHIFT 0x13
+#define DCIO_DEBUG1__DCO_DCIO_DVOCNTL1_EN_MASK 0x100000
+#define DCIO_DEBUG1__DCO_DCIO_DVOCNTL1_EN__SHIFT 0x14
+#define DCIO_DEBUG1__DCO_DCIO_DVOCNTL1_MUX_MASK 0x200000
+#define DCIO_DEBUG1__DCO_DCIO_DVOCNTL1_MUX__SHIFT 0x15
+#define DCIO_DEBUG1__DCO_DCIO_DVOCNTL1_MASK_REG_MASK 0x400000
+#define DCIO_DEBUG1__DCO_DCIO_DVOCNTL1_MASK_REG__SHIFT 0x16
+#define DCIO_DEBUG1__DCO_DCIO_DVO_ENABLE_MASK 0x800000
+#define DCIO_DEBUG1__DCO_DCIO_DVO_ENABLE__SHIFT 0x17
+#define DCIO_DEBUG1__DCO_DCIO_DVO_VSYNC_TRISTATE_MASK 0x1000000
+#define DCIO_DEBUG1__DCO_DCIO_DVO_VSYNC_TRISTATE__SHIFT 0x18
+#define DCIO_DEBUG1__DCO_DCIO_DVO_RATE_SEL_MASK 0x2000000
+#define DCIO_DEBUG1__DCO_DCIO_DVO_RATE_SEL__SHIFT 0x19
+#define DCIO_DEBUG1__DCO_DCIO_DVOCNTL1_SEL0_PREMUX_MASK 0x4000000
+#define DCIO_DEBUG1__DCO_DCIO_DVOCNTL1_SEL0_PREMUX__SHIFT 0x1a
+#define DCIO_DEBUG1__DCO_DCIO_DVOCNTL1_SEL0_MASK 0x8000000
+#define DCIO_DEBUG1__DCO_DCIO_DVOCNTL1_SEL0__SHIFT 0x1b
+#define DCIO_DEBUG2__DCIO_DEBUG2_MASK 0xffffffff
+#define DCIO_DEBUG2__DCIO_DEBUG2__SHIFT 0x0
+#define DCIO_DEBUG3__DCIO_DEBUG3_MASK 0xffffffff
+#define DCIO_DEBUG3__DCIO_DEBUG3__SHIFT 0x0
+#define DCIO_DEBUG4__DCIO_DEBUG4_MASK 0xffffffff
+#define DCIO_DEBUG4__DCIO_DEBUG4__SHIFT 0x0
+#define DCIO_DEBUG5__DCIO_DEBUG5_MASK 0xffffffff
+#define DCIO_DEBUG5__DCIO_DEBUG5__SHIFT 0x0
+#define DCIO_DEBUG6__DCIO_DEBUG6_MASK 0xffffffff
+#define DCIO_DEBUG6__DCIO_DEBUG6__SHIFT 0x0
+#define DCIO_DEBUG7__DCIO_DEBUG7_MASK 0xffffffff
+#define DCIO_DEBUG7__DCIO_DEBUG7__SHIFT 0x0
+#define DCIO_DEBUG8__DCIO_DEBUG8_MASK 0xffffffff
+#define DCIO_DEBUG8__DCIO_DEBUG8__SHIFT 0x0
+#define DCIO_DEBUG9__DCIO_DEBUG9_MASK 0xffffffff
+#define DCIO_DEBUG9__DCIO_DEBUG9__SHIFT 0x0
+#define DCIO_DEBUGA__DCIO_DEBUGA_MASK 0xffffffff
+#define DCIO_DEBUGA__DCIO_DEBUGA__SHIFT 0x0
+#define DCIO_DEBUGB__DCIO_DEBUGB_MASK 0xffffffff
+#define DCIO_DEBUGB__DCIO_DEBUGB__SHIFT 0x0
+#define DCIO_DEBUGC__DCIO_DEBUGC_MASK 0xffffffff
+#define DCIO_DEBUGC__DCIO_DEBUGC__SHIFT 0x0
+#define DCIO_DEBUGD__DCIO_DEBUGD_MASK 0xffffffff
+#define DCIO_DEBUGD__DCIO_DEBUGD__SHIFT 0x0
+#define DCIO_DEBUGE__DCIO_DIGA_DEBUG_MASK 0xffffffff
+#define DCIO_DEBUGE__DCIO_DIGA_DEBUG__SHIFT 0x0
+#define DCIO_DEBUGF__DCIO_DIGB_DEBUG_MASK 0xffffffff
+#define DCIO_DEBUGF__DCIO_DIGB_DEBUG__SHIFT 0x0
+#define DCIO_DEBUG10__DCIO_DIGC_DEBUG_MASK 0xffffffff
+#define DCIO_DEBUG10__DCIO_DIGC_DEBUG__SHIFT 0x0
+#define DCIO_DEBUG11__DCIO_DIGD_DEBUG_MASK 0xffffffff
+#define DCIO_DEBUG11__DCIO_DIGD_DEBUG__SHIFT 0x0
+#define DCIO_DEBUG12__DCIO_DIGE_DEBUG_MASK 0xffffffff
+#define DCIO_DEBUG12__DCIO_DIGE_DEBUG__SHIFT 0x0
+#define DCIO_DEBUG13__DCIO_DIGF_DEBUG_MASK 0xffffffff
+#define DCIO_DEBUG13__DCIO_DIGF_DEBUG__SHIFT 0x0
+#define DCIO_DEBUG14__DCIO_DIGG_DEBUG_MASK 0xffffffff
+#define DCIO_DEBUG14__DCIO_DIGG_DEBUG__SHIFT 0x0
+#define DCIO_DEBUG15__DCIO_DEBUG15_MASK 0xffffffff
+#define DCIO_DEBUG15__DCIO_DEBUG15__SHIFT 0x0
+#define DCIO_DEBUG16__DCIO_DEBUG16_MASK 0xffffffff
+#define DCIO_DEBUG16__DCIO_DEBUG16__SHIFT 0x0
+#define DCIO_DEBUG17__DCIO_DEBUG17_MASK 0xffffffff
+#define DCIO_DEBUG17__DCIO_DEBUG17__SHIFT 0x0
+#define DCIO_DEBUG18__DCIO_DEBUG18_MASK 0xffffffff
+#define DCIO_DEBUG18__DCIO_DEBUG18__SHIFT 0x0
+#define DCIO_DEBUG19__DCIO_DIGLPA_DEBUG_MASK 0xffffffff
+#define DCIO_DEBUG19__DCIO_DIGLPA_DEBUG__SHIFT 0x0
+#define DCIO_DEBUG1A__DCIO_DIGLPB_DEBUG_MASK 0xffffffff
+#define DCIO_DEBUG1A__DCIO_DIGLPB_DEBUG__SHIFT 0x0
+#define DCIO_DEBUG1B__DCIO_DEBUGHPD_MASK 0xffffffff
+#define DCIO_DEBUG1B__DCIO_DEBUGHPD__SHIFT 0x0
+#define DCIO_DEBUG1C__DCIO_DEBUG_UNIPHYA_CFG_MASK 0xffffffff
+#define DCIO_DEBUG1C__DCIO_DEBUG_UNIPHYA_CFG__SHIFT 0x0
+#define DCIO_DEBUG1D__DCIO_DEBUG_UNIPHYB_CFG_MASK 0xffffffff
+#define DCIO_DEBUG1D__DCIO_DEBUG_UNIPHYB_CFG__SHIFT 0x0
+#define DCIO_DEBUG1E__DCIO_DEBUG_UNIPHYC_CFG_MASK 0xffffffff
+#define DCIO_DEBUG1E__DCIO_DEBUG_UNIPHYC_CFG__SHIFT 0x0
+#define DCIO_DEBUG1F__DCIO_DEBUG_UNIPHYD_CFG_MASK 0xffffffff
+#define DCIO_DEBUG1F__DCIO_DEBUG_UNIPHYD_CFG__SHIFT 0x0
+#define DCIO_DEBUG20__DCIO_DEBUG_UNIPHYE_CFG_MASK 0xffffffff
+#define DCIO_DEBUG20__DCIO_DEBUG_UNIPHYE_CFG__SHIFT 0x0
+#define DCIO_DEBUG21__DCIO_DEBUG_UNIPHYF_CFG_MASK 0xffffffff
+#define DCIO_DEBUG21__DCIO_DEBUG_UNIPHYF_CFG__SHIFT 0x0
+#define DCIO_DEBUG22__DCIO_DEBUG_UNIPHYG_CFG_MASK 0xffffffff
+#define DCIO_DEBUG22__DCIO_DEBUG_UNIPHYG_CFG__SHIFT 0x0
+#define DCIO_DEBUG23__DCIO_DEBUG_UNIPHYLPA_CFG_MASK 0xffffffff
+#define DCIO_DEBUG23__DCIO_DEBUG_UNIPHYLPA_CFG__SHIFT 0x0
+#define DCIO_DEBUG24__DCIO_DEBUG_UNIPHYLPB_CFG_MASK 0xffffffff
+#define DCIO_DEBUG24__DCIO_DEBUG_UNIPHYLPB_CFG__SHIFT 0x0
+#define DCIO_DEBUG25__DCIO_DEBUG_DCRXPHY_CFG_MASK 0xffffffff
+#define DCIO_DEBUG25__DCIO_DEBUG_DCRXPHY_CFG__SHIFT 0x0
+#define DCIO_DEBUG26__DCIO_DEBUG_DPHY_CFG_MASK 0xffffffff
+#define DCIO_DEBUG26__DCIO_DEBUG_DPHY_CFG__SHIFT 0x0
+#define DCIO_DEBUG27__DCIO_DEBUG_DACA_CFG_MASK 0xffffffff
+#define DCIO_DEBUG27__DCIO_DEBUG_DACA_CFG__SHIFT 0x0
+#define DCIO_DEBUG28__DCIO_DEBUG_ZCAL_CFG_MASK 0xffffffff
+#define DCIO_DEBUG28__DCIO_DEBUG_ZCAL_CFG__SHIFT 0x0
+#define DCIO_DEBUG_ID__DCIO_DEBUG_ID_MASK 0xffffffff
+#define DCIO_DEBUG_ID__DCIO_DEBUG_ID__SHIFT 0x0
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICA_MASK_MASK 0x1
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICA_MASK__SHIFT 0x0
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICA_PD_DIS_MASK 0x2
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICA_PD_DIS__SHIFT 0x1
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICA_RECV_MASK 0x4
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICA_RECV__SHIFT 0x2
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICA_RECV1_MASK 0x8
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICA_RECV1__SHIFT 0x3
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICB_MASK_MASK 0x10
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICB_MASK__SHIFT 0x4
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICB_PD_DIS_MASK 0x20
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICB_PD_DIS__SHIFT 0x5
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICB_RECV_MASK 0x40
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICB_RECV__SHIFT 0x6
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICB_RECV1_MASK 0x80
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICB_RECV1__SHIFT 0x7
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICC_MASK_MASK 0x100
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICC_MASK__SHIFT 0x8
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICC_PD_DIS_MASK 0x200
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICC_PD_DIS__SHIFT 0x9
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICC_RECV_MASK 0x400
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICC_RECV__SHIFT 0xa
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICC_RECV1_MASK 0x800
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICC_RECV1__SHIFT 0xb
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICD_MASK_MASK 0x1000
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICD_MASK__SHIFT 0xc
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICD_PD_DIS_MASK 0x2000
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICD_PD_DIS__SHIFT 0xd
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICD_RECV_MASK 0x4000
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICD_RECV__SHIFT 0xe
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICD_RECV1_MASK 0x8000
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICD_RECV1__SHIFT 0xf
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICE_MASK_MASK 0x10000
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICE_MASK__SHIFT 0x10
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICE_PD_DIS_MASK 0x20000
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICE_PD_DIS__SHIFT 0x11
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICE_RECV_MASK 0x40000
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICE_RECV__SHIFT 0x12
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICE_RECV1_MASK 0x80000
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICE_RECV1__SHIFT 0x13
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICF_MASK_MASK 0x100000
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICF_MASK__SHIFT 0x14
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICF_PD_DIS_MASK 0x200000
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICF_PD_DIS__SHIFT 0x15
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICF_RECV_MASK 0x400000
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICF_RECV__SHIFT 0x16
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICF_RECV1_MASK 0x800000
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICF_RECV1__SHIFT 0x17
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICG_MASK_MASK 0x1000000
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICG_MASK__SHIFT 0x18
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICG_PD_DIS_MASK 0x2000000
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICG_PD_DIS__SHIFT 0x19
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICG_RECV_MASK 0x4000000
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICG_RECV__SHIFT 0x1a
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICG_RECV1_MASK 0x8000000
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICG_RECV1__SHIFT 0x1b
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A_MASK 0x1
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A__SHIFT 0x0
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A_MASK 0x100
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A__SHIFT 0x8
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A_MASK 0x10000
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A__SHIFT 0x10
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A_MASK 0x100000
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A__SHIFT 0x14
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A_MASK 0x200000
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A__SHIFT 0x15
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A_MASK 0x400000
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A__SHIFT 0x16
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A_MASK 0x800000
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A__SHIFT 0x17
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICA_EN_MASK 0x1
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICA_EN__SHIFT 0x0
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICB_EN_MASK 0x100
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICB_EN__SHIFT 0x8
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICC_EN_MASK 0x10000
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICC_EN__SHIFT 0x10
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICD_EN_MASK 0x100000
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICD_EN__SHIFT 0x14
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICE_EN_MASK 0x200000
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICE_EN__SHIFT 0x15
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICF_EN_MASK 0x400000
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICF_EN__SHIFT 0x16
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICG_EN_MASK 0x800000
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICG_EN__SHIFT 0x17
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICA_Y_MASK 0x1
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICA_Y__SHIFT 0x0
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICB_Y_MASK 0x100
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICB_Y__SHIFT 0x8
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICC_Y_MASK 0x10000
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICC_Y__SHIFT 0x10
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICD_Y_MASK 0x100000
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICD_Y__SHIFT 0x14
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICE_Y_MASK 0x200000
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICE_Y__SHIFT 0x15
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICF_Y_MASK 0x400000
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICF_Y__SHIFT 0x16
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICG_Y_MASK 0x800000
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICG_Y__SHIFT 0x17
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_MASK_MASK 0x1
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_MASK__SHIFT 0x0
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_PD_EN_MASK 0x10
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_PD_EN__SHIFT 0x4
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_RECV_MASK 0x40
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_RECV__SHIFT 0x6
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_RECV1_MASK 0x80
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_RECV1__SHIFT 0x7
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_MASK_MASK 0x100
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_MASK__SHIFT 0x8
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_PD_EN_MASK 0x1000
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_PD_EN__SHIFT 0xc
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_RECV_MASK 0x4000
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_RECV__SHIFT 0xe
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_RECV1_MASK 0x8000
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_RECV1__SHIFT 0xf
+#define DC_GPIO_DDC1_MASK__AUX_PAD1_MODE_MASK 0x10000
+#define DC_GPIO_DDC1_MASK__AUX_PAD1_MODE__SHIFT 0x10
+#define DC_GPIO_DDC1_MASK__AUX1_POL_MASK 0x100000
+#define DC_GPIO_DDC1_MASK__AUX1_POL__SHIFT 0x14
+#define DC_GPIO_DDC1_MASK__ALLOW_HW_DDC1_PD_EN_MASK 0x400000
+#define DC_GPIO_DDC1_MASK__ALLOW_HW_DDC1_PD_EN__SHIFT 0x16
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_STR_MASK 0xf000000
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_STR__SHIFT 0x18
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_STR_MASK 0xf0000000
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_STR__SHIFT 0x1c
+#define DC_GPIO_DDC1_A__DC_GPIO_DDC1CLK_A_MASK 0x1
+#define DC_GPIO_DDC1_A__DC_GPIO_DDC1CLK_A__SHIFT 0x0
+#define DC_GPIO_DDC1_A__DC_GPIO_DDC1DATA_A_MASK 0x100
+#define DC_GPIO_DDC1_A__DC_GPIO_DDC1DATA_A__SHIFT 0x8
+#define DC_GPIO_DDC1_EN__DC_GPIO_DDC1CLK_EN_MASK 0x1
+#define DC_GPIO_DDC1_EN__DC_GPIO_DDC1CLK_EN__SHIFT 0x0
+#define DC_GPIO_DDC1_EN__DC_GPIO_DDC1DATA_EN_MASK 0x100
+#define DC_GPIO_DDC1_EN__DC_GPIO_DDC1DATA_EN__SHIFT 0x8
+#define DC_GPIO_DDC1_Y__DC_GPIO_DDC1CLK_Y_MASK 0x1
+#define DC_GPIO_DDC1_Y__DC_GPIO_DDC1CLK_Y__SHIFT 0x0
+#define DC_GPIO_DDC1_Y__DC_GPIO_DDC1DATA_Y_MASK 0x100
+#define DC_GPIO_DDC1_Y__DC_GPIO_DDC1DATA_Y__SHIFT 0x8
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_MASK_MASK 0x1
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_MASK__SHIFT 0x0
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_PD_EN_MASK 0x10
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_PD_EN__SHIFT 0x4
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_RECV_MASK 0x40
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_RECV__SHIFT 0x6
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_RECV1_MASK 0x80
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_RECV1__SHIFT 0x7
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_MASK_MASK 0x100
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_MASK__SHIFT 0x8
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_PD_EN_MASK 0x1000
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_PD_EN__SHIFT 0xc
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_RECV_MASK 0x4000
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_RECV__SHIFT 0xe
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_RECV1_MASK 0x8000
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_RECV1__SHIFT 0xf
+#define DC_GPIO_DDC2_MASK__AUX_PAD2_MODE_MASK 0x10000
+#define DC_GPIO_DDC2_MASK__AUX_PAD2_MODE__SHIFT 0x10
+#define DC_GPIO_DDC2_MASK__AUX2_POL_MASK 0x100000
+#define DC_GPIO_DDC2_MASK__AUX2_POL__SHIFT 0x14
+#define DC_GPIO_DDC2_MASK__ALLOW_HW_DDC2_PD_EN_MASK 0x400000
+#define DC_GPIO_DDC2_MASK__ALLOW_HW_DDC2_PD_EN__SHIFT 0x16
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_STR_MASK 0xf000000
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_STR__SHIFT 0x18
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_STR_MASK 0xf0000000
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_STR__SHIFT 0x1c
+#define DC_GPIO_DDC2_A__DC_GPIO_DDC2CLK_A_MASK 0x1
+#define DC_GPIO_DDC2_A__DC_GPIO_DDC2CLK_A__SHIFT 0x0
+#define DC_GPIO_DDC2_A__DC_GPIO_DDC2DATA_A_MASK 0x100
+#define DC_GPIO_DDC2_A__DC_GPIO_DDC2DATA_A__SHIFT 0x8
+#define DC_GPIO_DDC2_EN__DC_GPIO_DDC2CLK_EN_MASK 0x1
+#define DC_GPIO_DDC2_EN__DC_GPIO_DDC2CLK_EN__SHIFT 0x0
+#define DC_GPIO_DDC2_EN__DC_GPIO_DDC2DATA_EN_MASK 0x100
+#define DC_GPIO_DDC2_EN__DC_GPIO_DDC2DATA_EN__SHIFT 0x8
+#define DC_GPIO_DDC2_Y__DC_GPIO_DDC2CLK_Y_MASK 0x1
+#define DC_GPIO_DDC2_Y__DC_GPIO_DDC2CLK_Y__SHIFT 0x0
+#define DC_GPIO_DDC2_Y__DC_GPIO_DDC2DATA_Y_MASK 0x100
+#define DC_GPIO_DDC2_Y__DC_GPIO_DDC2DATA_Y__SHIFT 0x8
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_MASK_MASK 0x1
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_MASK__SHIFT 0x0
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_PD_EN_MASK 0x10
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_PD_EN__SHIFT 0x4
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_RECV_MASK 0x40
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_RECV__SHIFT 0x6
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_RECV1_MASK 0x80
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_RECV1__SHIFT 0x7
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_MASK_MASK 0x100
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_MASK__SHIFT 0x8
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_PD_EN_MASK 0x1000
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_PD_EN__SHIFT 0xc
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_RECV_MASK 0x4000
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_RECV__SHIFT 0xe
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_RECV1_MASK 0x8000
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_RECV1__SHIFT 0xf
+#define DC_GPIO_DDC3_MASK__AUX_PAD3_MODE_MASK 0x10000
+#define DC_GPIO_DDC3_MASK__AUX_PAD3_MODE__SHIFT 0x10
+#define DC_GPIO_DDC3_MASK__AUX3_POL_MASK 0x100000
+#define DC_GPIO_DDC3_MASK__AUX3_POL__SHIFT 0x14
+#define DC_GPIO_DDC3_MASK__ALLOW_HW_DDC3_PD_EN_MASK 0x400000
+#define DC_GPIO_DDC3_MASK__ALLOW_HW_DDC3_PD_EN__SHIFT 0x16
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_STR_MASK 0xf000000
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_STR__SHIFT 0x18
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_STR_MASK 0xf0000000
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_STR__SHIFT 0x1c
+#define DC_GPIO_DDC3_A__DC_GPIO_DDC3CLK_A_MASK 0x1
+#define DC_GPIO_DDC3_A__DC_GPIO_DDC3CLK_A__SHIFT 0x0
+#define DC_GPIO_DDC3_A__DC_GPIO_DDC3DATA_A_MASK 0x100
+#define DC_GPIO_DDC3_A__DC_GPIO_DDC3DATA_A__SHIFT 0x8
+#define DC_GPIO_DDC3_EN__DC_GPIO_DDC3CLK_EN_MASK 0x1
+#define DC_GPIO_DDC3_EN__DC_GPIO_DDC3CLK_EN__SHIFT 0x0
+#define DC_GPIO_DDC3_EN__DC_GPIO_DDC3DATA_EN_MASK 0x100
+#define DC_GPIO_DDC3_EN__DC_GPIO_DDC3DATA_EN__SHIFT 0x8
+#define DC_GPIO_DDC3_Y__DC_GPIO_DDC3CLK_Y_MASK 0x1
+#define DC_GPIO_DDC3_Y__DC_GPIO_DDC3CLK_Y__SHIFT 0x0
+#define DC_GPIO_DDC3_Y__DC_GPIO_DDC3DATA_Y_MASK 0x100
+#define DC_GPIO_DDC3_Y__DC_GPIO_DDC3DATA_Y__SHIFT 0x8
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_MASK_MASK 0x1
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_MASK__SHIFT 0x0
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_PD_EN_MASK 0x10
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_PD_EN__SHIFT 0x4
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_RECV_MASK 0x40
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_RECV__SHIFT 0x6
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_RECV1_MASK 0x80
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_RECV1__SHIFT 0x7
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_MASK_MASK 0x100
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_MASK__SHIFT 0x8
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_PD_EN_MASK 0x1000
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_PD_EN__SHIFT 0xc
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_RECV_MASK 0x4000
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_RECV__SHIFT 0xe
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_RECV1_MASK 0x8000
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_RECV1__SHIFT 0xf
+#define DC_GPIO_DDC4_MASK__AUX_PAD4_MODE_MASK 0x10000
+#define DC_GPIO_DDC4_MASK__AUX_PAD4_MODE__SHIFT 0x10
+#define DC_GPIO_DDC4_MASK__AUX4_POL_MASK 0x100000
+#define DC_GPIO_DDC4_MASK__AUX4_POL__SHIFT 0x14
+#define DC_GPIO_DDC4_MASK__ALLOW_HW_DDC4_PD_EN_MASK 0x400000
+#define DC_GPIO_DDC4_MASK__ALLOW_HW_DDC4_PD_EN__SHIFT 0x16
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_STR_MASK 0xf000000
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_STR__SHIFT 0x18
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_STR_MASK 0xf0000000
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_STR__SHIFT 0x1c
+#define DC_GPIO_DDC4_A__DC_GPIO_DDC4CLK_A_MASK 0x1
+#define DC_GPIO_DDC4_A__DC_GPIO_DDC4CLK_A__SHIFT 0x0
+#define DC_GPIO_DDC4_A__DC_GPIO_DDC4DATA_A_MASK 0x100
+#define DC_GPIO_DDC4_A__DC_GPIO_DDC4DATA_A__SHIFT 0x8
+#define DC_GPIO_DDC4_EN__DC_GPIO_DDC4CLK_EN_MASK 0x1
+#define DC_GPIO_DDC4_EN__DC_GPIO_DDC4CLK_EN__SHIFT 0x0
+#define DC_GPIO_DDC4_EN__DC_GPIO_DDC4DATA_EN_MASK 0x100
+#define DC_GPIO_DDC4_EN__DC_GPIO_DDC4DATA_EN__SHIFT 0x8
+#define DC_GPIO_DDC4_Y__DC_GPIO_DDC4CLK_Y_MASK 0x1
+#define DC_GPIO_DDC4_Y__DC_GPIO_DDC4CLK_Y__SHIFT 0x0
+#define DC_GPIO_DDC4_Y__DC_GPIO_DDC4DATA_Y_MASK 0x100
+#define DC_GPIO_DDC4_Y__DC_GPIO_DDC4DATA_Y__SHIFT 0x8
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_MASK_MASK 0x1
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_MASK__SHIFT 0x0
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_PD_EN_MASK 0x10
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_PD_EN__SHIFT 0x4
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_RECV_MASK 0x40
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_RECV__SHIFT 0x6
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_RECV1_MASK 0x80
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_RECV1__SHIFT 0x7
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_MASK_MASK 0x100
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_MASK__SHIFT 0x8
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_PD_EN_MASK 0x1000
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_PD_EN__SHIFT 0xc
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_RECV_MASK 0x4000
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_RECV__SHIFT 0xe
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_RECV1_MASK 0x8000
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_RECV1__SHIFT 0xf
+#define DC_GPIO_DDC5_MASK__AUX_PAD5_MODE_MASK 0x10000
+#define DC_GPIO_DDC5_MASK__AUX_PAD5_MODE__SHIFT 0x10
+#define DC_GPIO_DDC5_MASK__AUX5_POL_MASK 0x100000
+#define DC_GPIO_DDC5_MASK__AUX5_POL__SHIFT 0x14
+#define DC_GPIO_DDC5_MASK__ALLOW_HW_DDC5_PD_EN_MASK 0x400000
+#define DC_GPIO_DDC5_MASK__ALLOW_HW_DDC5_PD_EN__SHIFT 0x16
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_STR_MASK 0xf000000
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_STR__SHIFT 0x18
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_STR_MASK 0xf0000000
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_STR__SHIFT 0x1c
+#define DC_GPIO_DDC5_A__DC_GPIO_DDC5CLK_A_MASK 0x1
+#define DC_GPIO_DDC5_A__DC_GPIO_DDC5CLK_A__SHIFT 0x0
+#define DC_GPIO_DDC5_A__DC_GPIO_DDC5DATA_A_MASK 0x100
+#define DC_GPIO_DDC5_A__DC_GPIO_DDC5DATA_A__SHIFT 0x8
+#define DC_GPIO_DDC5_EN__DC_GPIO_DDC5CLK_EN_MASK 0x1
+#define DC_GPIO_DDC5_EN__DC_GPIO_DDC5CLK_EN__SHIFT 0x0
+#define DC_GPIO_DDC5_EN__DC_GPIO_DDC5DATA_EN_MASK 0x100
+#define DC_GPIO_DDC5_EN__DC_GPIO_DDC5DATA_EN__SHIFT 0x8
+#define DC_GPIO_DDC5_Y__DC_GPIO_DDC5CLK_Y_MASK 0x1
+#define DC_GPIO_DDC5_Y__DC_GPIO_DDC5CLK_Y__SHIFT 0x0
+#define DC_GPIO_DDC5_Y__DC_GPIO_DDC5DATA_Y_MASK 0x100
+#define DC_GPIO_DDC5_Y__DC_GPIO_DDC5DATA_Y__SHIFT 0x8
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_MASK_MASK 0x1
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_MASK__SHIFT 0x0
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_PD_EN_MASK 0x10
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_PD_EN__SHIFT 0x4
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_RECV_MASK 0x40
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_RECV__SHIFT 0x6
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_RECV1_MASK 0x80
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_RECV1__SHIFT 0x7
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_MASK_MASK 0x100
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_MASK__SHIFT 0x8
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_PD_EN_MASK 0x1000
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_PD_EN__SHIFT 0xc
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_RECV_MASK 0x4000
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_RECV__SHIFT 0xe
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_RECV1_MASK 0x8000
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_RECV1__SHIFT 0xf
+#define DC_GPIO_DDC6_MASK__AUX_PAD6_MODE_MASK 0x10000
+#define DC_GPIO_DDC6_MASK__AUX_PAD6_MODE__SHIFT 0x10
+#define DC_GPIO_DDC6_MASK__AUX6_POL_MASK 0x100000
+#define DC_GPIO_DDC6_MASK__AUX6_POL__SHIFT 0x14
+#define DC_GPIO_DDC6_MASK__ALLOW_HW_DDC6_PD_EN_MASK 0x400000
+#define DC_GPIO_DDC6_MASK__ALLOW_HW_DDC6_PD_EN__SHIFT 0x16
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_STR_MASK 0xf000000
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_STR__SHIFT 0x18
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_STR_MASK 0xf0000000
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_STR__SHIFT 0x1c
+#define DC_GPIO_DDC6_A__DC_GPIO_DDC6CLK_A_MASK 0x1
+#define DC_GPIO_DDC6_A__DC_GPIO_DDC6CLK_A__SHIFT 0x0
+#define DC_GPIO_DDC6_A__DC_GPIO_DDC6DATA_A_MASK 0x100
+#define DC_GPIO_DDC6_A__DC_GPIO_DDC6DATA_A__SHIFT 0x8
+#define DC_GPIO_DDC6_EN__DC_GPIO_DDC6CLK_EN_MASK 0x1
+#define DC_GPIO_DDC6_EN__DC_GPIO_DDC6CLK_EN__SHIFT 0x0
+#define DC_GPIO_DDC6_EN__DC_GPIO_DDC6DATA_EN_MASK 0x100
+#define DC_GPIO_DDC6_EN__DC_GPIO_DDC6DATA_EN__SHIFT 0x8
+#define DC_GPIO_DDC6_Y__DC_GPIO_DDC6CLK_Y_MASK 0x1
+#define DC_GPIO_DDC6_Y__DC_GPIO_DDC6CLK_Y__SHIFT 0x0
+#define DC_GPIO_DDC6_Y__DC_GPIO_DDC6DATA_Y_MASK 0x100
+#define DC_GPIO_DDC6_Y__DC_GPIO_DDC6DATA_Y__SHIFT 0x8
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_MASK_MASK 0x1
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_MASK__SHIFT 0x0
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_RECV_MASK 0x40
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_RECV__SHIFT 0x6
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_RECV1_MASK 0x80
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_RECV1__SHIFT 0x7
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_MASK_MASK 0x100
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_MASK__SHIFT 0x8
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_PD_EN_MASK 0x1000
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_PD_EN__SHIFT 0xc
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_RECV_MASK 0x4000
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_RECV__SHIFT 0xe
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_RECV1_MASK 0x8000
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_RECV1__SHIFT 0xf
+#define DC_GPIO_DDCVGA_MASK__AUX_PADVGA_MODE_MASK 0x10000
+#define DC_GPIO_DDCVGA_MASK__AUX_PADVGA_MODE__SHIFT 0x10
+#define DC_GPIO_DDCVGA_MASK__AUXVGA_POL_MASK 0x100000
+#define DC_GPIO_DDCVGA_MASK__AUXVGA_POL__SHIFT 0x14
+#define DC_GPIO_DDCVGA_MASK__ALLOW_HW_DDCVGA_PD_EN_MASK 0x400000
+#define DC_GPIO_DDCVGA_MASK__ALLOW_HW_DDCVGA_PD_EN__SHIFT 0x16
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_STR_MASK 0xf000000
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_STR__SHIFT 0x18
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_STR_MASK 0xf0000000
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_STR__SHIFT 0x1c
+#define DC_GPIO_DDCVGA_A__DC_GPIO_DDCVGACLK_A_MASK 0x1
+#define DC_GPIO_DDCVGA_A__DC_GPIO_DDCVGACLK_A__SHIFT 0x0
+#define DC_GPIO_DDCVGA_A__DC_GPIO_DDCVGADATA_A_MASK 0x100
+#define DC_GPIO_DDCVGA_A__DC_GPIO_DDCVGADATA_A__SHIFT 0x8
+#define DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGACLK_EN_MASK 0x1
+#define DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGACLK_EN__SHIFT 0x0
+#define DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGADATA_EN_MASK 0x100
+#define DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGADATA_EN__SHIFT 0x8
+#define DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGADATA_PAD_RXSEL_MASK 0x30000
+#define DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGADATA_PAD_RXSEL__SHIFT 0x10
+#define DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGADATA_PAD_SPARE_MASK 0xc0000
+#define DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGADATA_PAD_SPARE__SHIFT 0x12
+#define DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGADATA_PAD_BIASCRTEN_MASK 0x100000
+#define DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGADATA_PAD_BIASCRTEN__SHIFT 0x14
+#define DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGADATA_PAD_CSEL0P9_MASK 0x200000
+#define DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGADATA_PAD_CSEL0P9__SHIFT 0x15
+#define DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGADATA_PAD_CSEL1P1_MASK 0x400000
+#define DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGADATA_PAD_CSEL1P1__SHIFT 0x16
+#define DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGADATA_PAD_COMPSEL_MASK 0x800000
+#define DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGADATA_PAD_COMPSEL__SHIFT 0x17
+#define DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGADATA_PAD_RSEL0P9_MASK 0x1000000
+#define DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGADATA_PAD_RSEL0P9__SHIFT 0x18
+#define DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGADATA_PAD_RSEL1P1_MASK 0x2000000
+#define DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGADATA_PAD_RSEL1P1__SHIFT 0x19
+#define DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGADATA_PAD_SPIKERCEN_MASK 0x4000000
+#define DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGADATA_PAD_SPIKERCEN__SHIFT 0x1a
+#define DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGADATA_PAD_SPIKERCSEL_MASK 0x8000000
+#define DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGADATA_PAD_SPIKERCSEL__SHIFT 0x1b
+#define DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGADATA_PAD_FALLSLEWSEL_MASK 0x30000000
+#define DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGADATA_PAD_FALLSLEWSEL__SHIFT 0x1c
+#define DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGADATA_PAD_RESBIASEN_MASK 0x40000000
+#define DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGADATA_PAD_RESBIASEN__SHIFT 0x1e
+#define DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGADATA_PAD_SLEWN_MASK 0x80000000
+#define DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGADATA_PAD_SLEWN__SHIFT 0x1f
+#define DC_GPIO_DDCVGA_Y__DC_GPIO_DDCVGACLK_Y_MASK 0x1
+#define DC_GPIO_DDCVGA_Y__DC_GPIO_DDCVGACLK_Y__SHIFT 0x0
+#define DC_GPIO_DDCVGA_Y__DC_GPIO_DDCVGADATA_Y_MASK 0x100
+#define DC_GPIO_DDCVGA_Y__DC_GPIO_DDCVGADATA_Y__SHIFT 0x8
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_HSYNCA_MASK_MASK 0x1
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_HSYNCA_MASK__SHIFT 0x0
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_HSYNCA_PD_DIS_MASK 0x10
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_HSYNCA_PD_DIS__SHIFT 0x4
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_HSYNCA_RECV_MASK 0x40
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_HSYNCA_RECV__SHIFT 0x6
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_HSYNCA_RECV1_MASK 0x80
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_HSYNCA_RECV1__SHIFT 0x7
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_VSYNCA_MASK_MASK 0x100
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_VSYNCA_MASK__SHIFT 0x8
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_VSYNCA_PD_DIS_MASK 0x1000
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_VSYNCA_PD_DIS__SHIFT 0xc
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_VSYNCA_RECV_MASK 0x4000
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_VSYNCA_RECV__SHIFT 0xe
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_VSYNCA_RECV1_MASK 0x8000
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_VSYNCA_RECV1__SHIFT 0xf
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_HSYNCA_CRTC_HSYNC_MASK_MASK 0x7000000
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_HSYNCA_CRTC_HSYNC_MASK__SHIFT 0x18
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_VSYNCA_CRTC_VSYNC_MASK_MASK 0x70000000
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_VSYNCA_CRTC_VSYNC_MASK__SHIFT 0x1c
+#define DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A_MASK 0x1
+#define DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A__SHIFT 0x0
+#define DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A_MASK 0x100
+#define DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A__SHIFT 0x8
+#define DC_GPIO_SYNCA_EN__DC_GPIO_HSYNCA_EN_MASK 0x1
+#define DC_GPIO_SYNCA_EN__DC_GPIO_HSYNCA_EN__SHIFT 0x0
+#define DC_GPIO_SYNCA_EN__DC_GPIO_VSYNCA_EN_MASK 0x100
+#define DC_GPIO_SYNCA_EN__DC_GPIO_VSYNCA_EN__SHIFT 0x8
+#define DC_GPIO_SYNCA_Y__DC_GPIO_HSYNCA_Y_MASK 0x1
+#define DC_GPIO_SYNCA_Y__DC_GPIO_HSYNCA_Y__SHIFT 0x0
+#define DC_GPIO_SYNCA_Y__DC_GPIO_VSYNCA_Y_MASK 0x100
+#define DC_GPIO_SYNCA_Y__DC_GPIO_VSYNCA_Y__SHIFT 0x8
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_CLK_MASK_MASK 0x1
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_CLK_MASK__SHIFT 0x0
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_CLK_PD_DIS_MASK 0x2
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_CLK_PD_DIS__SHIFT 0x1
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_CLK_RECV_MASK 0x4
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_CLK_RECV__SHIFT 0x2
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_CLK_PU_EN_MASK 0x8
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_CLK_PU_EN__SHIFT 0x3
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_CLK_RECV1_MASK 0x10
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_CLK_RECV1__SHIFT 0x4
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_VSYNC_RECV1_MASK 0x20
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_VSYNC_RECV1__SHIFT 0x5
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_VSYNC_MASK_MASK 0x100
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_VSYNC_MASK__SHIFT 0x8
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_VSYNC_PD_DIS_MASK 0x200
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_VSYNC_PD_DIS__SHIFT 0x9
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_VSYNC_RECV_MASK 0x400
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_VSYNC_RECV__SHIFT 0xa
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_VSYNC_PU_EN_MASK 0x800
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_VSYNC_PU_EN__SHIFT 0xb
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_A_MASK_MASK 0x10000
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_A_MASK__SHIFT 0x10
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_A_PD_DIS_MASK 0x20000
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_A_PD_DIS__SHIFT 0x11
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_A_RECV_MASK 0x40000
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_A_RECV__SHIFT 0x12
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_A_PU_EN_MASK 0x80000
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_A_PU_EN__SHIFT 0x13
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_A_RECV1_MASK 0x100000
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_A_RECV1__SHIFT 0x14
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_B_RECV1_MASK 0x800000
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_B_RECV1__SHIFT 0x17
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_B_MASK_MASK 0x1000000
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_B_MASK__SHIFT 0x18
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_B_PD_DIS_MASK 0x2000000
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_B_PD_DIS__SHIFT 0x19
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_B_RECV_MASK 0x4000000
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_B_RECV__SHIFT 0x1a
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_B_PU_EN_MASK 0x8000000
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_B_PU_EN__SHIFT 0x1b
+#define DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A_MASK 0x1
+#define DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A__SHIFT 0x0
+#define DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A_MASK 0x100
+#define DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A__SHIFT 0x8
+#define DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A_MASK 0x10000
+#define DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A__SHIFT 0x10
+#define DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A_MASK 0x1000000
+#define DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A__SHIFT 0x18
+#define DC_GPIO_GENLK_EN__DC_GPIO_GENLK_CLK_EN_MASK 0x1
+#define DC_GPIO_GENLK_EN__DC_GPIO_GENLK_CLK_EN__SHIFT 0x0
+#define DC_GPIO_GENLK_EN__DC_GPIO_GENLK_VSYNC_EN_MASK 0x100
+#define DC_GPIO_GENLK_EN__DC_GPIO_GENLK_VSYNC_EN__SHIFT 0x8
+#define DC_GPIO_GENLK_EN__DC_GPIO_SWAPLOCK_A_EN_MASK 0x10000
+#define DC_GPIO_GENLK_EN__DC_GPIO_SWAPLOCK_A_EN__SHIFT 0x10
+#define DC_GPIO_GENLK_EN__DC_GPIO_SWAPLOCK_B_EN_MASK 0x1000000
+#define DC_GPIO_GENLK_EN__DC_GPIO_SWAPLOCK_B_EN__SHIFT 0x18
+#define DC_GPIO_GENLK_Y__DC_GPIO_GENLK_CLK_Y_MASK 0x1
+#define DC_GPIO_GENLK_Y__DC_GPIO_GENLK_CLK_Y__SHIFT 0x0
+#define DC_GPIO_GENLK_Y__DC_GPIO_GENLK_VSYNC_Y_MASK 0x100
+#define DC_GPIO_GENLK_Y__DC_GPIO_GENLK_VSYNC_Y__SHIFT 0x8
+#define DC_GPIO_GENLK_Y__DC_GPIO_SWAPLOCK_A_Y_MASK 0x10000
+#define DC_GPIO_GENLK_Y__DC_GPIO_SWAPLOCK_A_Y__SHIFT 0x10
+#define DC_GPIO_GENLK_Y__DC_GPIO_SWAPLOCK_B_Y_MASK 0x1000000
+#define DC_GPIO_GENLK_Y__DC_GPIO_SWAPLOCK_B_Y__SHIFT 0x18
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD1_MASK_MASK 0x1
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD1_MASK__SHIFT 0x0
+#define DC_GPIO_HPD_MASK__DC_GPIO_RX_HPD_MASK_MASK 0x2
+#define DC_GPIO_HPD_MASK__DC_GPIO_RX_HPD_MASK__SHIFT 0x1
+#define DC_GPIO_HPD_MASK__DC_GPIO_RX_HPD_PD_DIS_MASK 0x4
+#define DC_GPIO_HPD_MASK__DC_GPIO_RX_HPD_PD_DIS__SHIFT 0x2
+#define DC_GPIO_HPD_MASK__DC_GPIO_RX_HPD_RECV_MASK 0x8
+#define DC_GPIO_HPD_MASK__DC_GPIO_RX_HPD_RECV__SHIFT 0x3
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD1_PD_DIS_MASK 0x10
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD1_PD_DIS__SHIFT 0x4
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD1_RECV1_MASK 0x20
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD1_RECV1__SHIFT 0x5
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD1_RECV_MASK 0x40
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD1_RECV__SHIFT 0x6
+#define DC_GPIO_HPD_MASK__DC_GPIO_RX_HPD_RECV1_MASK 0x80
+#define DC_GPIO_HPD_MASK__DC_GPIO_RX_HPD_RECV1__SHIFT 0x7
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD2_MASK_MASK 0x100
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD2_MASK__SHIFT 0x8
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD2_PD_DIS_MASK 0x200
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD2_PD_DIS__SHIFT 0x9
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD2_RECV_MASK 0x400
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD2_RECV__SHIFT 0xa
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD2_RECV1_MASK 0x800
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD2_RECV1__SHIFT 0xb
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD3_MASK_MASK 0x10000
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD3_MASK__SHIFT 0x10
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD3_PD_DIS_MASK 0x20000
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD3_PD_DIS__SHIFT 0x11
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD3_RECV_MASK 0x40000
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD3_RECV__SHIFT 0x12
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD3_RECV1_MASK 0x80000
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD3_RECV1__SHIFT 0x13
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD4_MASK_MASK 0x100000
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD4_MASK__SHIFT 0x14
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD4_PD_DIS_MASK 0x200000
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD4_PD_DIS__SHIFT 0x15
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD4_RECV_MASK 0x400000
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD4_RECV__SHIFT 0x16
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD4_RECV1_MASK 0x800000
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD4_RECV1__SHIFT 0x17
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD5_MASK_MASK 0x1000000
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD5_MASK__SHIFT 0x18
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD5_PD_DIS_MASK 0x2000000
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD5_PD_DIS__SHIFT 0x19
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD5_RECV_MASK 0x4000000
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD5_RECV__SHIFT 0x1a
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD5_RECV1_MASK 0x8000000
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD5_RECV1__SHIFT 0x1b
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD6_MASK_MASK 0x10000000
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD6_MASK__SHIFT 0x1c
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD6_PD_DIS_MASK 0x20000000
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD6_PD_DIS__SHIFT 0x1d
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD6_RECV_MASK 0x40000000
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD6_RECV__SHIFT 0x1e
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD6_RECV1_MASK 0x80000000
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD6_RECV1__SHIFT 0x1f
+#define DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK 0x1
+#define DC_GPIO_HPD_A__DC_GPIO_HPD1_A__SHIFT 0x0
+#define DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK 0x100
+#define DC_GPIO_HPD_A__DC_GPIO_HPD2_A__SHIFT 0x8
+#define DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK 0x10000
+#define DC_GPIO_HPD_A__DC_GPIO_HPD3_A__SHIFT 0x10
+#define DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK 0x1000000
+#define DC_GPIO_HPD_A__DC_GPIO_HPD4_A__SHIFT 0x18
+#define DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK 0x4000000
+#define DC_GPIO_HPD_A__DC_GPIO_HPD5_A__SHIFT 0x1a
+#define DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK 0x10000000
+#define DC_GPIO_HPD_A__DC_GPIO_HPD6_A__SHIFT 0x1c
+#define DC_GPIO_HPD_EN__DC_GPIO_HPD1_EN_MASK 0x1
+#define DC_GPIO_HPD_EN__DC_GPIO_HPD1_EN__SHIFT 0x0
+#define DC_GPIO_HPD_EN__HPD1_SCHMEN_PI_MASK 0x2
+#define DC_GPIO_HPD_EN__HPD1_SCHMEN_PI__SHIFT 0x1
+#define DC_GPIO_HPD_EN__HPD1_SLEWNCORE_MASK 0x4
+#define DC_GPIO_HPD_EN__HPD1_SLEWNCORE__SHIFT 0x2
+#define DC_GPIO_HPD_EN__RX_HPD_SCHMEN_PI_MASK 0x8
+#define DC_GPIO_HPD_EN__RX_HPD_SCHMEN_PI__SHIFT 0x3
+#define DC_GPIO_HPD_EN__RX_HPD_SLEWNCORE_MASK 0x10
+#define DC_GPIO_HPD_EN__RX_HPD_SLEWNCORE__SHIFT 0x4
+#define DC_GPIO_HPD_EN__HPD12_SPARE0_MASK 0x20
+#define DC_GPIO_HPD_EN__HPD12_SPARE0__SHIFT 0x5
+#define DC_GPIO_HPD_EN__HPD1_SEL0_MASK 0x40
+#define DC_GPIO_HPD_EN__HPD1_SEL0__SHIFT 0x6
+#define DC_GPIO_HPD_EN__RX_HPD_SEL0_MASK 0x80
+#define DC_GPIO_HPD_EN__RX_HPD_SEL0__SHIFT 0x7
+#define DC_GPIO_HPD_EN__DC_GPIO_HPD2_EN_MASK 0x100
+#define DC_GPIO_HPD_EN__DC_GPIO_HPD2_EN__SHIFT 0x8
+#define DC_GPIO_HPD_EN__HPD2_SCHMEN_PI_MASK 0x200
+#define DC_GPIO_HPD_EN__HPD2_SCHMEN_PI__SHIFT 0x9
+#define DC_GPIO_HPD_EN__HPD12_SPARE1_MASK 0x400
+#define DC_GPIO_HPD_EN__HPD12_SPARE1__SHIFT 0xa
+#define DC_GPIO_HPD_EN__DC_GPIO_HPD3_EN_MASK 0x10000
+#define DC_GPIO_HPD_EN__DC_GPIO_HPD3_EN__SHIFT 0x10
+#define DC_GPIO_HPD_EN__HPD3_SCHMEN_PI_MASK 0x20000
+#define DC_GPIO_HPD_EN__HPD3_SCHMEN_PI__SHIFT 0x11
+#define DC_GPIO_HPD_EN__HPD34_SPARE0_MASK 0x40000
+#define DC_GPIO_HPD_EN__HPD34_SPARE0__SHIFT 0x12
+#define DC_GPIO_HPD_EN__DC_GPIO_HPD4_EN_MASK 0x100000
+#define DC_GPIO_HPD_EN__DC_GPIO_HPD4_EN__SHIFT 0x14
+#define DC_GPIO_HPD_EN__HPD4_SCHMEN_PI_MASK 0x200000
+#define DC_GPIO_HPD_EN__HPD4_SCHMEN_PI__SHIFT 0x15
+#define DC_GPIO_HPD_EN__HPD34_SPARE1_MASK 0x400000
+#define DC_GPIO_HPD_EN__HPD34_SPARE1__SHIFT 0x16
+#define DC_GPIO_HPD_EN__DC_GPIO_HPD5_EN_MASK 0x1000000
+#define DC_GPIO_HPD_EN__DC_GPIO_HPD5_EN__SHIFT 0x18
+#define DC_GPIO_HPD_EN__HPD5_SCHMEN_PI_MASK 0x2000000
+#define DC_GPIO_HPD_EN__HPD5_SCHMEN_PI__SHIFT 0x19
+#define DC_GPIO_HPD_EN__HPD56_SPARE0_MASK 0x4000000
+#define DC_GPIO_HPD_EN__HPD56_SPARE0__SHIFT 0x1a
+#define DC_GPIO_HPD_EN__DC_GPIO_HPD6_EN_MASK 0x10000000
+#define DC_GPIO_HPD_EN__DC_GPIO_HPD6_EN__SHIFT 0x1c
+#define DC_GPIO_HPD_EN__HPD6_SCHMEN_PI_MASK 0x20000000
+#define DC_GPIO_HPD_EN__HPD6_SCHMEN_PI__SHIFT 0x1d
+#define DC_GPIO_HPD_EN__HPD56_SPARE1_MASK 0x40000000
+#define DC_GPIO_HPD_EN__HPD56_SPARE1__SHIFT 0x1e
+#define DC_GPIO_HPD_Y__DC_GPIO_HPD1_Y_MASK 0x1
+#define DC_GPIO_HPD_Y__DC_GPIO_HPD1_Y__SHIFT 0x0
+#define DC_GPIO_HPD_Y__DC_GPIO_HPD2_Y_MASK 0x100
+#define DC_GPIO_HPD_Y__DC_GPIO_HPD2_Y__SHIFT 0x8
+#define DC_GPIO_HPD_Y__DC_GPIO_HPD3_Y_MASK 0x10000
+#define DC_GPIO_HPD_Y__DC_GPIO_HPD3_Y__SHIFT 0x10
+#define DC_GPIO_HPD_Y__DC_GPIO_HPD4_Y_MASK 0x1000000
+#define DC_GPIO_HPD_Y__DC_GPIO_HPD4_Y__SHIFT 0x18
+#define DC_GPIO_HPD_Y__DC_GPIO_HPD5_Y_MASK 0x4000000
+#define DC_GPIO_HPD_Y__DC_GPIO_HPD5_Y__SHIFT 0x1a
+#define DC_GPIO_HPD_Y__DC_GPIO_HPD6_Y_MASK 0x10000000
+#define DC_GPIO_HPD_Y__DC_GPIO_HPD6_Y__SHIFT 0x1c
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_BLON_MASK_MASK 0x1
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_BLON_MASK__SHIFT 0x0
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_BLON_PD_DIS_MASK 0x10
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_BLON_PD_DIS__SHIFT 0x4
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_BLON_RECV_MASK 0x40
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_BLON_RECV__SHIFT 0x6
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_BLON_RECV1_MASK 0x80
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_BLON_RECV1__SHIFT 0x7
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_DIGON_MASK_MASK 0x100
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_DIGON_MASK__SHIFT 0x8
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_DIGON_PD_DIS_MASK 0x1000
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_DIGON_PD_DIS__SHIFT 0xc
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_DIGON_RECV_MASK 0x4000
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_DIGON_RECV__SHIFT 0xe
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_DIGON_RECV1_MASK 0x8000
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_DIGON_RECV1__SHIFT 0xf
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_ENA_BL_MASK_MASK 0x10000
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_ENA_BL_MASK__SHIFT 0x10
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_ENA_BL_PD_DIS_MASK 0x100000
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_ENA_BL_PD_DIS__SHIFT 0x14
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_ENA_BL_RECV_MASK 0x400000
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_ENA_BL_RECV__SHIFT 0x16
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_ENA_BL_RECV1_MASK 0x800000
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_ENA_BL_RECV1__SHIFT 0x17
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_VSYNC_IN_MASK_MASK 0x1000000
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_VSYNC_IN_MASK__SHIFT 0x18
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_VSYNC_IN_PD_DIS_MASK 0x2000000
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_VSYNC_IN_PD_DIS__SHIFT 0x19
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_VSYNC_IN_RECV_MASK 0x4000000
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_VSYNC_IN_RECV__SHIFT 0x1a
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_VSYNC_IN_RECV1_MASK 0x8000000
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_VSYNC_IN_RECV1__SHIFT 0x1b
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_HSYNC_IN_MASK_MASK 0x10000000
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_HSYNC_IN_MASK__SHIFT 0x1c
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_HSYNC_IN_PD_DIS_MASK 0x20000000
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_HSYNC_IN_PD_DIS__SHIFT 0x1d
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_HSYNC_IN_RECV_MASK 0x40000000
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_HSYNC_IN_RECV__SHIFT 0x1e
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_HSYNC_IN_RECV1_MASK 0x80000000
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_HSYNC_IN_RECV1__SHIFT 0x1f
+#define DC_GPIO_PWRSEQ_A__DC_GPIO_BLON_A_MASK 0x1
+#define DC_GPIO_PWRSEQ_A__DC_GPIO_BLON_A__SHIFT 0x0
+#define DC_GPIO_PWRSEQ_A__DC_GPIO_DIGON_A_MASK 0x100
+#define DC_GPIO_PWRSEQ_A__DC_GPIO_DIGON_A__SHIFT 0x8
+#define DC_GPIO_PWRSEQ_A__DC_GPIO_ENA_BL_A_MASK 0x10000
+#define DC_GPIO_PWRSEQ_A__DC_GPIO_ENA_BL_A__SHIFT 0x10
+#define DC_GPIO_PWRSEQ_A__DC_GPIO_VSYNC_IN_A_MASK 0x1000000
+#define DC_GPIO_PWRSEQ_A__DC_GPIO_VSYNC_IN_A__SHIFT 0x18
+#define DC_GPIO_PWRSEQ_A__DC_GPIO_HSYNC_IN_A_MASK 0x80000000
+#define DC_GPIO_PWRSEQ_A__DC_GPIO_HSYNC_IN_A__SHIFT 0x1f
+#define DC_GPIO_PWRSEQ_EN__DC_GPIO_BLON_EN_MASK 0x1
+#define DC_GPIO_PWRSEQ_EN__DC_GPIO_BLON_EN__SHIFT 0x0
+#define DC_GPIO_PWRSEQ_EN__DC_GPIO_VARY_BL_GENERICA_EN_MASK 0x2
+#define DC_GPIO_PWRSEQ_EN__DC_GPIO_VARY_BL_GENERICA_EN__SHIFT 0x1
+#define DC_GPIO_PWRSEQ_EN__DC_GPIO_DIGON_EN_MASK 0x100
+#define DC_GPIO_PWRSEQ_EN__DC_GPIO_DIGON_EN__SHIFT 0x8
+#define DC_GPIO_PWRSEQ_EN__DC_GPIO_ENA_BL_EN_MASK 0x10000
+#define DC_GPIO_PWRSEQ_EN__DC_GPIO_ENA_BL_EN__SHIFT 0x10
+#define DC_GPIO_PWRSEQ_EN__DC_GPIO_VSYNC_IN_EN_MASK 0x1000000
+#define DC_GPIO_PWRSEQ_EN__DC_GPIO_VSYNC_IN_EN__SHIFT 0x18
+#define DC_GPIO_PWRSEQ_EN__DC_GPIO_HSYNC_IN_EN_MASK 0x80000000
+#define DC_GPIO_PWRSEQ_EN__DC_GPIO_HSYNC_IN_EN__SHIFT 0x1f
+#define DC_GPIO_PWRSEQ_Y__DC_GPIO_BLON_Y_MASK 0x1
+#define DC_GPIO_PWRSEQ_Y__DC_GPIO_BLON_Y__SHIFT 0x0
+#define DC_GPIO_PWRSEQ_Y__DC_GPIO_DIGON_Y_MASK 0x100
+#define DC_GPIO_PWRSEQ_Y__DC_GPIO_DIGON_Y__SHIFT 0x8
+#define DC_GPIO_PWRSEQ_Y__DC_GPIO_ENA_BL_Y_MASK 0x10000
+#define DC_GPIO_PWRSEQ_Y__DC_GPIO_ENA_BL_Y__SHIFT 0x10
+#define DC_GPIO_PWRSEQ_Y__DC_GPIO_VSYNC_IN_MASK 0x1000000
+#define DC_GPIO_PWRSEQ_Y__DC_GPIO_VSYNC_IN__SHIFT 0x18
+#define DC_GPIO_PWRSEQ_Y__DC_GPIO_HSYNC_IN_MASK 0x80000000
+#define DC_GPIO_PWRSEQ_Y__DC_GPIO_HSYNC_IN__SHIFT 0x1f
+#define DC_GPIO_PAD_STRENGTH_1__GENLK_STRENGTH_SN_MASK 0xf
+#define DC_GPIO_PAD_STRENGTH_1__GENLK_STRENGTH_SN__SHIFT 0x0
+#define DC_GPIO_PAD_STRENGTH_1__GENLK_STRENGTH_SP_MASK 0xf0
+#define DC_GPIO_PAD_STRENGTH_1__GENLK_STRENGTH_SP__SHIFT 0x4
+#define DC_GPIO_PAD_STRENGTH_1__RX_HPD_STRENGTH_SN_MASK 0xf00
+#define DC_GPIO_PAD_STRENGTH_1__RX_HPD_STRENGTH_SN__SHIFT 0x8
+#define DC_GPIO_PAD_STRENGTH_1__RX_HPD_STRENGTH_SP_MASK 0xf000
+#define DC_GPIO_PAD_STRENGTH_1__RX_HPD_STRENGTH_SP__SHIFT 0xc
+#define DC_GPIO_PAD_STRENGTH_1__TX_HPD_STRENGTH_SN_MASK 0xf0000
+#define DC_GPIO_PAD_STRENGTH_1__TX_HPD_STRENGTH_SN__SHIFT 0x10
+#define DC_GPIO_PAD_STRENGTH_1__TX_HPD_STRENGTH_SP_MASK 0xf00000
+#define DC_GPIO_PAD_STRENGTH_1__TX_HPD_STRENGTH_SP__SHIFT 0x14
+#define DC_GPIO_PAD_STRENGTH_1__SYNC_STRENGTH_SN_MASK 0xf000000
+#define DC_GPIO_PAD_STRENGTH_1__SYNC_STRENGTH_SN__SHIFT 0x18
+#define DC_GPIO_PAD_STRENGTH_1__SYNC_STRENGTH_SP_MASK 0xf0000000
+#define DC_GPIO_PAD_STRENGTH_1__SYNC_STRENGTH_SP__SHIFT 0x1c
+#define DC_GPIO_PAD_STRENGTH_2__STRENGTH_SN_MASK 0xf
+#define DC_GPIO_PAD_STRENGTH_2__STRENGTH_SN__SHIFT 0x0
+#define DC_GPIO_PAD_STRENGTH_2__STRENGTH_SP_MASK 0xf0
+#define DC_GPIO_PAD_STRENGTH_2__STRENGTH_SP__SHIFT 0x4
+#define DC_GPIO_PAD_STRENGTH_2__EXT_RESET_DRVSTRENGTH_MASK 0x700
+#define DC_GPIO_PAD_STRENGTH_2__EXT_RESET_DRVSTRENGTH__SHIFT 0x8
+#define DC_GPIO_PAD_STRENGTH_2__REF_27_DRVSTRENGTH_MASK 0x7000
+#define DC_GPIO_PAD_STRENGTH_2__REF_27_DRVSTRENGTH__SHIFT 0xc
+#define DC_GPIO_PAD_STRENGTH_2__PWRSEQ_STRENGTH_SN_MASK 0xf0000
+#define DC_GPIO_PAD_STRENGTH_2__PWRSEQ_STRENGTH_SN__SHIFT 0x10
+#define DC_GPIO_PAD_STRENGTH_2__PWRSEQ_STRENGTH_SP_MASK 0xf00000
+#define DC_GPIO_PAD_STRENGTH_2__PWRSEQ_STRENGTH_SP__SHIFT 0x14
+#define DC_GPIO_PAD_STRENGTH_2__REF_27_SRC_SEL_MASK 0xc0000000
+#define DC_GPIO_PAD_STRENGTH_2__REF_27_SRC_SEL__SHIFT 0x1e
+#define PHY_AUX_CNTL__AUXSLAVE_PAD_SLEWN_MASK 0x1
+#define PHY_AUX_CNTL__AUXSLAVE_PAD_SLEWN__SHIFT 0x0
+#define PHY_AUX_CNTL__AUXSLAVE_PAD_WAKE_MASK 0x2
+#define PHY_AUX_CNTL__AUXSLAVE_PAD_WAKE__SHIFT 0x1
+#define PHY_AUX_CNTL__AUXSLAVE_PAD_RXSEL_MASK 0x4
+#define PHY_AUX_CNTL__AUXSLAVE_PAD_RXSEL__SHIFT 0x2
+#define PHY_AUX_CNTL__AUXSLAVE_PAD_MODE_MASK 0x8
+#define PHY_AUX_CNTL__AUXSLAVE_PAD_MODE__SHIFT 0x3
+#define PHY_AUX_CNTL__DDCSLAVE_DATA_PD_EN_MASK 0x10
+#define PHY_AUX_CNTL__DDCSLAVE_DATA_PD_EN__SHIFT 0x4
+#define PHY_AUX_CNTL__DDCSLAVE_DATA_EN_MASK 0x20
+#define PHY_AUX_CNTL__DDCSLAVE_DATA_EN__SHIFT 0x5
+#define PHY_AUX_CNTL__DDCSLAVE_CLK_PD_EN_MASK 0x40
+#define PHY_AUX_CNTL__DDCSLAVE_CLK_PD_EN__SHIFT 0x6
+#define PHY_AUX_CNTL__DDCSLAVE_CLK_EN_MASK 0x80
+#define PHY_AUX_CNTL__DDCSLAVE_CLK_EN__SHIFT 0x7
+#define PHY_AUX_CNTL__AUX_PAD_SLEWN_MASK 0x1000
+#define PHY_AUX_CNTL__AUX_PAD_SLEWN__SHIFT 0xc
+#define PHY_AUX_CNTL__AUXSLAVE_CLK_PD_EN_MASK 0x2000
+#define PHY_AUX_CNTL__AUXSLAVE_CLK_PD_EN__SHIFT 0xd
+#define PHY_AUX_CNTL__AUX_PAD_WAKE_MASK 0x4000
+#define PHY_AUX_CNTL__AUX_PAD_WAKE__SHIFT 0xe
+#define PHY_AUX_CNTL__AUX_PAD_RXSEL_MASK 0x30000
+#define PHY_AUX_CNTL__AUX_PAD_RXSEL__SHIFT 0x10
+#define PHY_AUX_CNTL__AUX_PAD_RESBIASEN_MASK 0x40000
+#define PHY_AUX_CNTL__AUX_PAD_RESBIASEN__SHIFT 0x12
+#define PHY_AUX_CNTL__AUX_PAD_COMPSEL_MASK 0x80000
+#define PHY_AUX_CNTL__AUX_PAD_COMPSEL__SHIFT 0x13
+#define DC_GPIO_I2CPAD_A__DC_GPIO_SCL_A_MASK 0x1
+#define DC_GPIO_I2CPAD_A__DC_GPIO_SCL_A__SHIFT 0x0
+#define DC_GPIO_I2CPAD_A__DC_GPIO_SDA_A_MASK 0x2
+#define DC_GPIO_I2CPAD_A__DC_GPIO_SDA_A__SHIFT 0x1
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_SCL_EN_MASK 0x1
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_SCL_EN__SHIFT 0x0
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_SDA_EN_MASK 0x2
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_SDA_EN__SHIFT 0x1
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_I2C_PAD_DATA_PD_EN_MASK 0x4
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_I2C_PAD_DATA_PD_EN__SHIFT 0x2
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_I2C_PAD_RXSEL_MASK 0x30000
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_I2C_PAD_RXSEL__SHIFT 0x10
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_I2C_PAD_SPARE_MASK 0xc0000
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_I2C_PAD_SPARE__SHIFT 0x12
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_I2C_PAD_BIASCRTEN_MASK 0x100000
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_I2C_PAD_BIASCRTEN__SHIFT 0x14
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_I2C_PAD_CSEL0P9_MASK 0x200000
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_I2C_PAD_CSEL0P9__SHIFT 0x15
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_I2C_PAD_CSEL1P1_MASK 0x400000
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_I2C_PAD_CSEL1P1__SHIFT 0x16
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_I2C_PAD_COMPSEL_MASK 0x800000
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_I2C_PAD_COMPSEL__SHIFT 0x17
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_I2C_PAD_RSEL0P9_MASK 0x1000000
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_I2C_PAD_RSEL0P9__SHIFT 0x18
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_I2C_PAD_RSEL1P1_MASK 0x2000000
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_I2C_PAD_RSEL1P1__SHIFT 0x19
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_I2C_PAD_SPIKERCEN_MASK 0x4000000
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_I2C_PAD_SPIKERCEN__SHIFT 0x1a
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_I2C_PAD_SPIKERCSEL_MASK 0x8000000
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_I2C_PAD_SPIKERCSEL__SHIFT 0x1b
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_I2C_PAD_FALLSLEWSEL_MASK 0x30000000
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_I2C_PAD_FALLSLEWSEL__SHIFT 0x1c
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_I2C_PAD_RESBIASEN_MASK 0x40000000
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_I2C_PAD_RESBIASEN__SHIFT 0x1e
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_I2C_PAD_SLEWN_MASK 0x80000000
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_I2C_PAD_SLEWN__SHIFT 0x1f
+#define DC_GPIO_I2CPAD_Y__DC_GPIO_SCL_Y_MASK 0x1
+#define DC_GPIO_I2CPAD_Y__DC_GPIO_SCL_Y__SHIFT 0x0
+#define DC_GPIO_I2CPAD_Y__DC_GPIO_SDA_Y_MASK 0x2
+#define DC_GPIO_I2CPAD_Y__DC_GPIO_SDA_Y__SHIFT 0x1
+#define DC_GPIO_I2CPAD_STRENGTH__I2C_STRENGTH_SN_MASK 0xf
+#define DC_GPIO_I2CPAD_STRENGTH__I2C_STRENGTH_SN__SHIFT 0x0
+#define DC_GPIO_I2CPAD_STRENGTH__I2C_STRENGTH_SP_MASK 0xf0
+#define DC_GPIO_I2CPAD_STRENGTH__I2C_STRENGTH_SP__SHIFT 0x4
+#define DVO_VREF_CONTROL__DVO_VREFPON_MASK 0x1
+#define DVO_VREF_CONTROL__DVO_VREFPON__SHIFT 0x0
+#define DVO_VREF_CONTROL__DVO_VREFSEL_MASK 0x2
+#define DVO_VREF_CONTROL__DVO_VREFSEL__SHIFT 0x1
+#define DVO_VREF_CONTROL__DVO_VREFCAL_MASK 0xf0
+#define DVO_VREF_CONTROL__DVO_VREFCAL__SHIFT 0x4
+#define DVO_SKEW_ADJUST__DVO_SKEW_ADJUST_MASK 0xffffffff
+#define DVO_SKEW_ADJUST__DVO_SKEW_ADJUST__SHIFT 0x0
+#define DC_GPIO_RECEIVER_EN0__VIPPAD_SCL_RECEN_MASK 0x1
+#define DC_GPIO_RECEIVER_EN0__VIPPAD_SCL_RECEN__SHIFT 0x0
+#define DC_GPIO_RECEIVER_EN0__VIPPAD_SDA_RECEN_MASK 0x2
+#define DC_GPIO_RECEIVER_EN0__VIPPAD_SDA_RECEN__SHIFT 0x1
+#define DC_GPIO_RECEIVER_EN0__DC_GPIO_RX_HPD_RECEN_MASK 0x10000
+#define DC_GPIO_RECEIVER_EN0__DC_GPIO_RX_HPD_RECEN__SHIFT 0x10
+#define DC_GPIO_RECEIVER_EN0__DC_GPIO_HPD1_RECEN_MASK 0x20000
+#define DC_GPIO_RECEIVER_EN0__DC_GPIO_HPD1_RECEN__SHIFT 0x11
+#define DC_GPIO_RECEIVER_EN0__DC_GPIO_GENLK_VSYNC_RECEN_MASK 0x40000
+#define DC_GPIO_RECEIVER_EN0__DC_GPIO_GENLK_VSYNC_RECEN__SHIFT 0x12
+#define DC_GPIO_RECEIVER_EN0__DC_GPIO_GENLK_CLK_RECEN_MASK 0x80000
+#define DC_GPIO_RECEIVER_EN0__DC_GPIO_GENLK_CLK_RECEN__SHIFT 0x13
+#define DC_GPIO_RECEIVER_EN0__DC_GPIO_VSYNCA_RECEN_MASK 0x100000
+#define DC_GPIO_RECEIVER_EN0__DC_GPIO_VSYNCA_RECEN__SHIFT 0x14
+#define DC_GPIO_RECEIVER_EN0__DC_GPIO_HSYNCA_RECEN_MASK 0x200000
+#define DC_GPIO_RECEIVER_EN0__DC_GPIO_HSYNCA_RECEN__SHIFT 0x15
+#define DC_GPIO_RECEIVER_EN0__DC_GPIO_GENERICG_RECEN_MASK 0x400000
+#define DC_GPIO_RECEIVER_EN0__DC_GPIO_GENERICG_RECEN__SHIFT 0x16
+#define DC_GPIO_RECEIVER_EN0__DC_GPIO_GENERICF_RECEN_MASK 0x800000
+#define DC_GPIO_RECEIVER_EN0__DC_GPIO_GENERICF_RECEN__SHIFT 0x17
+#define DC_GPIO_RECEIVER_EN0__DC_GPIO_GENERICE_RECEN_MASK 0x1000000
+#define DC_GPIO_RECEIVER_EN0__DC_GPIO_GENERICE_RECEN__SHIFT 0x18
+#define DC_GPIO_RECEIVER_EN0__DC_GPIO_GENERICD_RECEN_MASK 0x2000000
+#define DC_GPIO_RECEIVER_EN0__DC_GPIO_GENERICD_RECEN__SHIFT 0x19
+#define DC_GPIO_RECEIVER_EN0__DC_GPIO_GENERICC_RECEN_MASK 0x4000000
+#define DC_GPIO_RECEIVER_EN0__DC_GPIO_GENERICC_RECEN__SHIFT 0x1a
+#define DC_GPIO_RECEIVER_EN0__DC_GPIO_GENERICB_RECEN_MASK 0x8000000
+#define DC_GPIO_RECEIVER_EN0__DC_GPIO_GENERICB_RECEN__SHIFT 0x1b
+#define DC_GPIO_RECEIVER_EN0__DC_GPIO_GENERICA_RECEN_MASK 0x10000000
+#define DC_GPIO_RECEIVER_EN0__DC_GPIO_GENERICA_RECEN__SHIFT 0x1c
+#define DC_GPIO_RECEIVER_EN0__DC_GPIO_BLON_RECEN_MASK 0x20000000
+#define DC_GPIO_RECEIVER_EN0__DC_GPIO_BLON_RECEN__SHIFT 0x1d
+#define DC_GPIO_RECEIVER_EN0__DC_GPIO_DIGON_RECEN_MASK 0x40000000
+#define DC_GPIO_RECEIVER_EN0__DC_GPIO_DIGON_RECEN__SHIFT 0x1e
+#define DC_GPIO_RECEIVER_EN0__DC_GPIO_DDC2DATA_RECEN_MASK 0x80000000
+#define DC_GPIO_RECEIVER_EN0__DC_GPIO_DDC2DATA_RECEN__SHIFT 0x1f
+#define DC_GPIO_RECEIVER_EN1__DC_GPIO_DDC2CLK_RECEN_MASK 0x1
+#define DC_GPIO_RECEIVER_EN1__DC_GPIO_DDC2CLK_RECEN__SHIFT 0x0
+#define DC_GPIO_RECEIVER_EN1__DC_GPIO_DDC1DATA_RECEN_MASK 0x2
+#define DC_GPIO_RECEIVER_EN1__DC_GPIO_DDC1DATA_RECEN__SHIFT 0x1
+#define DC_GPIO_RECEIVER_EN1__DC_GPIO_DDC1CLK_RECEN_MASK 0x4
+#define DC_GPIO_RECEIVER_EN1__DC_GPIO_DDC1CLK_RECEN__SHIFT 0x2
+#define DC_GPIO_RECEIVER_EN1__DC_GPIO_DDC3DATA_RECEN_MASK 0x8
+#define DC_GPIO_RECEIVER_EN1__DC_GPIO_DDC3DATA_RECEN__SHIFT 0x3
+#define DC_GPIO_RECEIVER_EN1__DC_GPIO_DDC3CLK_RECEN_MASK 0x10
+#define DC_GPIO_RECEIVER_EN1__DC_GPIO_DDC3CLK_RECEN__SHIFT 0x4
+#define DC_GPIO_RECEIVER_EN1__DC_GPIO_DDC4DATA_RECEN_MASK 0x20
+#define DC_GPIO_RECEIVER_EN1__DC_GPIO_DDC4DATA_RECEN__SHIFT 0x5
+#define DC_GPIO_RECEIVER_EN1__DC_GPIO_DDC4CLK_RECEN_MASK 0x40
+#define DC_GPIO_RECEIVER_EN1__DC_GPIO_DDC4CLK_RECEN__SHIFT 0x6
+#define DC_GPIO_RECEIVER_EN1__DC_GPIO_DDC5DATA_RECEN_MASK 0x80
+#define DC_GPIO_RECEIVER_EN1__DC_GPIO_DDC5DATA_RECEN__SHIFT 0x7
+#define DC_GPIO_RECEIVER_EN1__DC_GPIO_DDC5CLK_RECEN_MASK 0x100
+#define DC_GPIO_RECEIVER_EN1__DC_GPIO_DDC5CLK_RECEN__SHIFT 0x8
+#define DC_GPIO_RECEIVER_EN1__DC_GPIO_DDC6DATA_RECEN_MASK 0x200
+#define DC_GPIO_RECEIVER_EN1__DC_GPIO_DDC6DATA_RECEN__SHIFT 0x9
+#define DC_GPIO_RECEIVER_EN1__DC_GPIO_DDC6CLK_RECEN_MASK 0x400
+#define DC_GPIO_RECEIVER_EN1__DC_GPIO_DDC6CLK_RECEN__SHIFT 0xa
+#define DC_GPIO_RECEIVER_EN1__DC_GPIO_HPD2_RECEN_MASK 0x800
+#define DC_GPIO_RECEIVER_EN1__DC_GPIO_HPD2_RECEN__SHIFT 0xb
+#define DC_GPIO_RECEIVER_EN1__DC_GPIO_HPD3_RECEN_MASK 0x1000
+#define DC_GPIO_RECEIVER_EN1__DC_GPIO_HPD3_RECEN__SHIFT 0xc
+#define DC_GPIO_RECEIVER_EN1__DC_GPIO_HPD4_RECEN_MASK 0x2000
+#define DC_GPIO_RECEIVER_EN1__DC_GPIO_HPD4_RECEN__SHIFT 0xd
+#define DC_GPIO_RECEIVER_EN1__DC_GPIO_HPD5_RECEN_MASK 0x4000
+#define DC_GPIO_RECEIVER_EN1__DC_GPIO_HPD5_RECEN__SHIFT 0xe
+#define DC_GPIO_RECEIVER_EN1__DC_GPIO_HPD6_RECEN_MASK 0x8000
+#define DC_GPIO_RECEIVER_EN1__DC_GPIO_HPD6_RECEN__SHIFT 0xf
+#define DC_GPIO_RECEIVER_EN1__DC_GPIO_ENA_BL_RECEN_MASK 0x10000
+#define DC_GPIO_RECEIVER_EN1__DC_GPIO_ENA_BL_RECEN__SHIFT 0x10
+#define DC_GPIO_RECEIVER_EN1__DC_GPIO_SWAPLOCK_A_RECEN_MASK 0x20000
+#define DC_GPIO_RECEIVER_EN1__DC_GPIO_SWAPLOCK_A_RECEN__SHIFT 0x11
+#define DC_GPIO_RECEIVER_EN1__DC_GPIO_SWAPLOCK_B_RECEN_MASK 0x40000
+#define DC_GPIO_RECEIVER_EN1__DC_GPIO_SWAPLOCK_B_RECEN__SHIFT 0x12
+#define DC_GPIO_I2S_SPDIF_MASK__DC_GPIO_I2SDATA0_MASK_MASK 0xf
+#define DC_GPIO_I2S_SPDIF_MASK__DC_GPIO_I2SDATA0_MASK__SHIFT 0x0
+#define DC_GPIO_I2S_SPDIF_MASK__DC_GPIO_MCLK0_MASK_MASK 0x10
+#define DC_GPIO_I2S_SPDIF_MASK__DC_GPIO_MCLK0_MASK__SHIFT 0x4
+#define DC_GPIO_I2S_SPDIF_MASK__DC_GPIO_BCLK0_MASK_MASK 0x20
+#define DC_GPIO_I2S_SPDIF_MASK__DC_GPIO_BCLK0_MASK__SHIFT 0x5
+#define DC_GPIO_I2S_SPDIF_MASK__DC_GPIO_LRCK0_MASK_MASK 0x40
+#define DC_GPIO_I2S_SPDIF_MASK__DC_GPIO_LRCK0_MASK__SHIFT 0x6
+#define DC_GPIO_I2S_SPDIF_MASK__DC_GPIO_SPDIF0_MASK_MASK 0x80
+#define DC_GPIO_I2S_SPDIF_MASK__DC_GPIO_SPDIF0_MASK__SHIFT 0x7
+#define DC_GPIO_I2S_SPDIF_MASK__DC_GPIO_I2SDATA1_MASK_MASK 0x100
+#define DC_GPIO_I2S_SPDIF_MASK__DC_GPIO_I2SDATA1_MASK__SHIFT 0x8
+#define DC_GPIO_I2S_SPDIF_MASK__DC_GPIO_MCLK1_MASK_MASK 0x200
+#define DC_GPIO_I2S_SPDIF_MASK__DC_GPIO_MCLK1_MASK__SHIFT 0x9
+#define DC_GPIO_I2S_SPDIF_MASK__DC_GPIO_BCLK1_MASK_MASK 0x400
+#define DC_GPIO_I2S_SPDIF_MASK__DC_GPIO_BCLK1_MASK__SHIFT 0xa
+#define DC_GPIO_I2S_SPDIF_MASK__DC_GPIO_LRCK1_MASK_MASK 0x800
+#define DC_GPIO_I2S_SPDIF_MASK__DC_GPIO_LRCK1_MASK__SHIFT 0xb
+#define DC_GPIO_I2S_SPDIF_MASK__DC_GPIO_SPDIF1_MASK_MASK 0x1000
+#define DC_GPIO_I2S_SPDIF_MASK__DC_GPIO_SPDIF1_MASK__SHIFT 0xc
+#define DC_GPIO_I2S_SPDIF_A__DC_GPIO_I2SDATA0_A_MASK 0xf
+#define DC_GPIO_I2S_SPDIF_A__DC_GPIO_I2SDATA0_A__SHIFT 0x0
+#define DC_GPIO_I2S_SPDIF_A__DC_GPIO_MCLK0_A_MASK 0x10
+#define DC_GPIO_I2S_SPDIF_A__DC_GPIO_MCLK0_A__SHIFT 0x4
+#define DC_GPIO_I2S_SPDIF_A__DC_GPIO_BCLK0_A_MASK 0x20
+#define DC_GPIO_I2S_SPDIF_A__DC_GPIO_BCLK0_A__SHIFT 0x5
+#define DC_GPIO_I2S_SPDIF_A__DC_GPIO_LRCK0_A_MASK 0x40
+#define DC_GPIO_I2S_SPDIF_A__DC_GPIO_LRCK0_A__SHIFT 0x6
+#define DC_GPIO_I2S_SPDIF_A__DC_GPIO_SPDIF0_A_MASK 0x80
+#define DC_GPIO_I2S_SPDIF_A__DC_GPIO_SPDIF0_A__SHIFT 0x7
+#define DC_GPIO_I2S_SPDIF_A__DC_GPIO_I2SDATA1_A_MASK 0x100
+#define DC_GPIO_I2S_SPDIF_A__DC_GPIO_I2SDATA1_A__SHIFT 0x8
+#define DC_GPIO_I2S_SPDIF_A__DC_GPIO_MCLK1_A_MASK 0x200
+#define DC_GPIO_I2S_SPDIF_A__DC_GPIO_MCLK1_A__SHIFT 0x9
+#define DC_GPIO_I2S_SPDIF_A__DC_GPIO_BCLK1_A_MASK 0x400
+#define DC_GPIO_I2S_SPDIF_A__DC_GPIO_BCLK1_A__SHIFT 0xa
+#define DC_GPIO_I2S_SPDIF_A__DC_GPIO_LRCK1_A_MASK 0x800
+#define DC_GPIO_I2S_SPDIF_A__DC_GPIO_LRCK1_A__SHIFT 0xb
+#define DC_GPIO_I2S_SPDIF_A__DC_GPIO_SPDIF1_A_MASK 0x1000
+#define DC_GPIO_I2S_SPDIF_A__DC_GPIO_SPDIF1_A__SHIFT 0xc
+#define DC_GPIO_I2S_SPDIF_EN__DC_GPIO_I2SDATA0_EN_MASK 0xf
+#define DC_GPIO_I2S_SPDIF_EN__DC_GPIO_I2SDATA0_EN__SHIFT 0x0
+#define DC_GPIO_I2S_SPDIF_EN__DC_GPIO_MCLK0_EN_MASK 0x10
+#define DC_GPIO_I2S_SPDIF_EN__DC_GPIO_MCLK0_EN__SHIFT 0x4
+#define DC_GPIO_I2S_SPDIF_EN__DC_GPIO_BCLK0_EN_MASK 0x20
+#define DC_GPIO_I2S_SPDIF_EN__DC_GPIO_BCLK0_EN__SHIFT 0x5
+#define DC_GPIO_I2S_SPDIF_EN__DC_GPIO_LRCK0_EN_MASK 0x40
+#define DC_GPIO_I2S_SPDIF_EN__DC_GPIO_LRCK0_EN__SHIFT 0x6
+#define DC_GPIO_I2S_SPDIF_EN__DC_GPIO_SPDIF0_EN_MASK 0x80
+#define DC_GPIO_I2S_SPDIF_EN__DC_GPIO_SPDIF0_EN__SHIFT 0x7
+#define DC_GPIO_I2S_SPDIF_EN__DC_GPIO_I2SDATA1_EN_MASK 0x100
+#define DC_GPIO_I2S_SPDIF_EN__DC_GPIO_I2SDATA1_EN__SHIFT 0x8
+#define DC_GPIO_I2S_SPDIF_EN__DC_GPIO_MCLK1_EN_MASK 0x200
+#define DC_GPIO_I2S_SPDIF_EN__DC_GPIO_MCLK1_EN__SHIFT 0x9
+#define DC_GPIO_I2S_SPDIF_EN__DC_GPIO_BCLK1_EN_MASK 0x400
+#define DC_GPIO_I2S_SPDIF_EN__DC_GPIO_BCLK1_EN__SHIFT 0xa
+#define DC_GPIO_I2S_SPDIF_EN__DC_GPIO_LRCK1_EN_MASK 0x800
+#define DC_GPIO_I2S_SPDIF_EN__DC_GPIO_LRCK1_EN__SHIFT 0xb
+#define DC_GPIO_I2S_SPDIF_EN__DC_GPIO_SPDIF1_EN_MASK 0x1000
+#define DC_GPIO_I2S_SPDIF_EN__DC_GPIO_SPDIF1_EN__SHIFT 0xc
+#define DC_GPIO_I2S_SPDIF_EN__SPDIF1_APORT_MASK 0x2000
+#define DC_GPIO_I2S_SPDIF_EN__SPDIF1_APORT__SHIFT 0xd
+#define DC_GPIO_I2S_SPDIF_EN__SPDIF1_PU_MASK 0x4000
+#define DC_GPIO_I2S_SPDIF_EN__SPDIF1_PU__SHIFT 0xe
+#define DC_GPIO_I2S_SPDIF_EN__SPDIF1_RXSEL_MASK 0x8000
+#define DC_GPIO_I2S_SPDIF_EN__SPDIF1_RXSEL__SHIFT 0xf
+#define DC_GPIO_I2S_SPDIF_EN__SPDIF1_SCHMEN_MASK 0x10000
+#define DC_GPIO_I2S_SPDIF_EN__SPDIF1_SCHMEN__SHIFT 0x10
+#define DC_GPIO_I2S_SPDIF_EN__SPDIF1_SMODE_EN_MASK 0x20000
+#define DC_GPIO_I2S_SPDIF_EN__SPDIF1_SMODE_EN__SHIFT 0x11
+#define DC_GPIO_I2S_SPDIF_EN__SPDIF1_IMODE_MASK 0x40000
+#define DC_GPIO_I2S_SPDIF_EN__SPDIF1_IMODE__SHIFT 0x12
+#define DC_GPIO_I2S_SPDIF_Y__DC_GPIO_I2SDATA0_Y_MASK 0xf
+#define DC_GPIO_I2S_SPDIF_Y__DC_GPIO_I2SDATA0_Y__SHIFT 0x0
+#define DC_GPIO_I2S_SPDIF_Y__DC_GPIO_MCLK0_Y_MASK 0x10
+#define DC_GPIO_I2S_SPDIF_Y__DC_GPIO_MCLK0_Y__SHIFT 0x4
+#define DC_GPIO_I2S_SPDIF_Y__DC_GPIO_BCLK0_Y_MASK 0x20
+#define DC_GPIO_I2S_SPDIF_Y__DC_GPIO_BCLK0_Y__SHIFT 0x5
+#define DC_GPIO_I2S_SPDIF_Y__DC_GPIO_LRCK0_Y_MASK 0x40
+#define DC_GPIO_I2S_SPDIF_Y__DC_GPIO_LRCK0_Y__SHIFT 0x6
+#define DC_GPIO_I2S_SPDIF_Y__DC_GPIO_SPDIF0_Y_MASK 0x80
+#define DC_GPIO_I2S_SPDIF_Y__DC_GPIO_SPDIF0_Y__SHIFT 0x7
+#define DC_GPIO_I2S_SPDIF_Y__DC_GPIO_I2SDATA1_Y_MASK 0x100
+#define DC_GPIO_I2S_SPDIF_Y__DC_GPIO_I2SDATA1_Y__SHIFT 0x8
+#define DC_GPIO_I2S_SPDIF_Y__DC_GPIO_MCLK1_Y_MASK 0x200
+#define DC_GPIO_I2S_SPDIF_Y__DC_GPIO_MCLK1_Y__SHIFT 0x9
+#define DC_GPIO_I2S_SPDIF_Y__DC_GPIO_BCLK1_Y_MASK 0x400
+#define DC_GPIO_I2S_SPDIF_Y__DC_GPIO_BCLK1_Y__SHIFT 0xa
+#define DC_GPIO_I2S_SPDIF_Y__DC_GPIO_LRCK1_Y_MASK 0x800
+#define DC_GPIO_I2S_SPDIF_Y__DC_GPIO_LRCK1_Y__SHIFT 0xb
+#define DC_GPIO_I2S_SPDIF_Y__DC_GPIO_SPDIF1_Y_MASK 0x1000
+#define DC_GPIO_I2S_SPDIF_Y__DC_GPIO_SPDIF1_Y__SHIFT 0xc
+#define DC_GPIO_I2S_SPDIF_STRENGTH__I2S0_DRVSTRENGTH_MASK 0x7
+#define DC_GPIO_I2S_SPDIF_STRENGTH__I2S0_DRVSTRENGTH__SHIFT 0x0
+#define DC_GPIO_I2S_SPDIF_STRENGTH__SPDIF0_DRVSTRENGTH_SN_MASK 0x700
+#define DC_GPIO_I2S_SPDIF_STRENGTH__SPDIF0_DRVSTRENGTH_SN__SHIFT 0x8
+#define DC_GPIO_I2S_SPDIF_STRENGTH__SPDIF0_DRVSTRENGTH_SP_MASK 0x3800
+#define DC_GPIO_I2S_SPDIF_STRENGTH__SPDIF0_DRVSTRENGTH_SP__SHIFT 0xb
+#define DC_GPIO_I2S_SPDIF_STRENGTH__I2S1_DRVSTRENGTH_MASK 0x70000
+#define DC_GPIO_I2S_SPDIF_STRENGTH__I2S1_DRVSTRENGTH__SHIFT 0x10
+#define DC_GPIO_I2S_SPDIF_STRENGTH__SPDIF1_DRVSTRENGTH_SN_MASK 0x7000000
+#define DC_GPIO_I2S_SPDIF_STRENGTH__SPDIF1_DRVSTRENGTH_SN__SHIFT 0x18
+#define DC_GPIO_I2S_SPDIF_STRENGTH__SPDIF1_DRVSTRENGTH_SP_MASK 0x38000000
+#define DC_GPIO_I2S_SPDIF_STRENGTH__SPDIF1_DRVSTRENGTH_SP__SHIFT 0x1b
+#define DC_GPIO_TX12_EN__DC_GPIO_BLON_TX12_EN_MASK 0x1
+#define DC_GPIO_TX12_EN__DC_GPIO_BLON_TX12_EN__SHIFT 0x0
+#define DC_GPIO_TX12_EN__DC_GPIO_DIGON_TX12_EN_MASK 0x2
+#define DC_GPIO_TX12_EN__DC_GPIO_DIGON_TX12_EN__SHIFT 0x1
+#define DC_GPIO_TX12_EN__DC_GPIO_ENA_BL_TX12_EN_MASK 0x4
+#define DC_GPIO_TX12_EN__DC_GPIO_ENA_BL_TX12_EN__SHIFT 0x2
+#define DC_GPIO_TX12_EN__DC_GPIO_GENERICA_TX12_EN_MASK 0x8
+#define DC_GPIO_TX12_EN__DC_GPIO_GENERICA_TX12_EN__SHIFT 0x3
+#define DC_GPIO_TX12_EN__DC_GPIO_GENERICB_TX12_EN_MASK 0x10
+#define DC_GPIO_TX12_EN__DC_GPIO_GENERICB_TX12_EN__SHIFT 0x4
+#define DC_GPIO_TX12_EN__DC_GPIO_GENERICC_TX12_EN_MASK 0x20
+#define DC_GPIO_TX12_EN__DC_GPIO_GENERICC_TX12_EN__SHIFT 0x5
+#define DC_GPIO_TX12_EN__DC_GPIO_GENERICD_TX12_EN_MASK 0x40
+#define DC_GPIO_TX12_EN__DC_GPIO_GENERICD_TX12_EN__SHIFT 0x6
+#define DC_GPIO_TX12_EN__DC_GPIO_GENERICE_TX12_EN_MASK 0x80
+#define DC_GPIO_TX12_EN__DC_GPIO_GENERICE_TX12_EN__SHIFT 0x7
+#define DC_GPIO_TX12_EN__DC_GPIO_GENERICF_TX12_EN_MASK 0x100
+#define DC_GPIO_TX12_EN__DC_GPIO_GENERICF_TX12_EN__SHIFT 0x8
+#define DC_GPIO_TX12_EN__DC_GPIO_GENERICG_TX12_EN_MASK 0x200
+#define DC_GPIO_TX12_EN__DC_GPIO_GENERICG_TX12_EN__SHIFT 0x9
+#define DC_GPIO_AUX_CTRL_0__DC_GPIO_AUX1_FALLSLEWSEL_MASK 0x3
+#define DC_GPIO_AUX_CTRL_0__DC_GPIO_AUX1_FALLSLEWSEL__SHIFT 0x0
+#define DC_GPIO_AUX_CTRL_0__DC_GPIO_AUX2_FALLSLEWSEL_MASK 0xc
+#define DC_GPIO_AUX_CTRL_0__DC_GPIO_AUX2_FALLSLEWSEL__SHIFT 0x2
+#define DC_GPIO_AUX_CTRL_0__DC_GPIO_AUX3_FALLSLEWSEL_MASK 0x30
+#define DC_GPIO_AUX_CTRL_0__DC_GPIO_AUX3_FALLSLEWSEL__SHIFT 0x4
+#define DC_GPIO_AUX_CTRL_0__DC_GPIO_AUX4_FALLSLEWSEL_MASK 0xc0
+#define DC_GPIO_AUX_CTRL_0__DC_GPIO_AUX4_FALLSLEWSEL__SHIFT 0x6
+#define DC_GPIO_AUX_CTRL_0__DC_GPIO_AUX5_FALLSLEWSEL_MASK 0x300
+#define DC_GPIO_AUX_CTRL_0__DC_GPIO_AUX5_FALLSLEWSEL__SHIFT 0x8
+#define DC_GPIO_AUX_CTRL_0__DC_GPIO_AUX6_FALLSLEWSEL_MASK 0xc00
+#define DC_GPIO_AUX_CTRL_0__DC_GPIO_AUX6_FALLSLEWSEL__SHIFT 0xa
+#define DC_GPIO_AUX_CTRL_0__DC_GPIO_AUX1_SPIKERCEN_MASK 0x10000
+#define DC_GPIO_AUX_CTRL_0__DC_GPIO_AUX1_SPIKERCEN__SHIFT 0x10
+#define DC_GPIO_AUX_CTRL_0__DC_GPIO_AUX2_SPIKERCEN_MASK 0x20000
+#define DC_GPIO_AUX_CTRL_0__DC_GPIO_AUX2_SPIKERCEN__SHIFT 0x11
+#define DC_GPIO_AUX_CTRL_0__DC_GPIO_AUX3_SPIKERCEN_MASK 0x40000
+#define DC_GPIO_AUX_CTRL_0__DC_GPIO_AUX3_SPIKERCEN__SHIFT 0x12
+#define DC_GPIO_AUX_CTRL_0__DC_GPIO_AUX4_SPIKERCEN_MASK 0x80000
+#define DC_GPIO_AUX_CTRL_0__DC_GPIO_AUX4_SPIKERCEN__SHIFT 0x13
+#define DC_GPIO_AUX_CTRL_0__DC_GPIO_AUX5_SPIKERCEN_MASK 0x100000
+#define DC_GPIO_AUX_CTRL_0__DC_GPIO_AUX5_SPIKERCEN__SHIFT 0x14
+#define DC_GPIO_AUX_CTRL_0__DC_GPIO_AUX6_SPIKERCEN_MASK 0x200000
+#define DC_GPIO_AUX_CTRL_0__DC_GPIO_AUX6_SPIKERCEN__SHIFT 0x15
+#define DC_GPIO_AUX_CTRL_0__DC_GPIO_AUX1_SPIKERCSEL_MASK 0x1000000
+#define DC_GPIO_AUX_CTRL_0__DC_GPIO_AUX1_SPIKERCSEL__SHIFT 0x18
+#define DC_GPIO_AUX_CTRL_0__DC_GPIO_AUX2_SPIKERCSEL_MASK 0x2000000
+#define DC_GPIO_AUX_CTRL_0__DC_GPIO_AUX2_SPIKERCSEL__SHIFT 0x19
+#define DC_GPIO_AUX_CTRL_0__DC_GPIO_AUX3_SPIKERCSEL_MASK 0x4000000
+#define DC_GPIO_AUX_CTRL_0__DC_GPIO_AUX3_SPIKERCSEL__SHIFT 0x1a
+#define DC_GPIO_AUX_CTRL_0__DC_GPIO_AUX4_SPIKERCSEL_MASK 0x8000000
+#define DC_GPIO_AUX_CTRL_0__DC_GPIO_AUX4_SPIKERCSEL__SHIFT 0x1b
+#define DC_GPIO_AUX_CTRL_0__DC_GPIO_AUX5_SPIKERCSEL_MASK 0x10000000
+#define DC_GPIO_AUX_CTRL_0__DC_GPIO_AUX5_SPIKERCSEL__SHIFT 0x1c
+#define DC_GPIO_AUX_CTRL_0__DC_GPIO_AUX6_SPIKERCSEL_MASK 0x20000000
+#define DC_GPIO_AUX_CTRL_0__DC_GPIO_AUX6_SPIKERCSEL__SHIFT 0x1d
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX1_CSEL_0P9_MASK 0x1
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX1_CSEL_0P9__SHIFT 0x0
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX2_CSEL_0P9_MASK 0x2
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX2_CSEL_0P9__SHIFT 0x1
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX3_CSEL_0P9_MASK 0x4
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX3_CSEL_0P9__SHIFT 0x2
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX4_CSEL_0P9_MASK 0x8
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX4_CSEL_0P9__SHIFT 0x3
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX5_CSEL_0P9_MASK 0x10
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX5_CSEL_0P9__SHIFT 0x4
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX6_CSEL_0P9_MASK 0x20
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX6_CSEL_0P9__SHIFT 0x5
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX1_CSEL_1P1_MASK 0x100
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX1_CSEL_1P1__SHIFT 0x8
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX2_CSEL_1P1_MASK 0x200
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX2_CSEL_1P1__SHIFT 0x9
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX3_CSEL_1P1_MASK 0x400
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX3_CSEL_1P1__SHIFT 0xa
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX4_CSEL_1P1_MASK 0x800
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX4_CSEL_1P1__SHIFT 0xb
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX5_CSEL_1P1_MASK 0x1000
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX5_CSEL_1P1__SHIFT 0xc
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX6_CSEL_1P1_MASK 0x2000
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX6_CSEL_1P1__SHIFT 0xd
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX1_RSEL_0P9_MASK 0x10000
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX1_RSEL_0P9__SHIFT 0x10
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX2_RSEL_0P9_MASK 0x20000
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX2_RSEL_0P9__SHIFT 0x11
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX3_RSEL_0P9_MASK 0x40000
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX3_RSEL_0P9__SHIFT 0x12
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX4_RSEL_0P9_MASK 0x80000
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX4_RSEL_0P9__SHIFT 0x13
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX5_RSEL_0P9_MASK 0x100000
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX5_RSEL_0P9__SHIFT 0x14
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX6_RSEL_0P9_MASK 0x200000
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX6_RSEL_0P9__SHIFT 0x15
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX1_RSEL_1P1_MASK 0x1000000
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX1_RSEL_1P1__SHIFT 0x18
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX2_RSEL_1P1_MASK 0x2000000
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX2_RSEL_1P1__SHIFT 0x19
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX3_RSEL_1P1_MASK 0x4000000
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX3_RSEL_1P1__SHIFT 0x1a
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX4_RSEL_1P1_MASK 0x8000000
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX4_RSEL_1P1__SHIFT 0x1b
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX5_RSEL_1P1_MASK 0x10000000
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX5_RSEL_1P1__SHIFT 0x1c
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX6_RSEL_1P1_MASK 0x20000000
+#define DC_GPIO_AUX_CTRL_1__DC_GPIO_AUX6_RSEL_1P1__SHIFT 0x1d
+#define DC_GPIO_AUX_CTRL_2__DC_GPIO_AUX1_BIASCRTEN_MASK 0x1
+#define DC_GPIO_AUX_CTRL_2__DC_GPIO_AUX1_BIASCRTEN__SHIFT 0x0
+#define DC_GPIO_AUX_CTRL_2__DC_GPIO_AUX2_BIASCRTEN_MASK 0x2
+#define DC_GPIO_AUX_CTRL_2__DC_GPIO_AUX2_BIASCRTEN__SHIFT 0x1
+#define DC_GPIO_AUX_CTRL_2__DC_GPIO_AUX3_BIASCRTEN_MASK 0x4
+#define DC_GPIO_AUX_CTRL_2__DC_GPIO_AUX3_BIASCRTEN__SHIFT 0x2
+#define DC_GPIO_AUX_CTRL_2__DC_GPIO_AUX4_BIASCRTEN_MASK 0x8
+#define DC_GPIO_AUX_CTRL_2__DC_GPIO_AUX4_BIASCRTEN__SHIFT 0x3
+#define DC_GPIO_AUX_CTRL_2__DC_GPIO_AUX5_BIASCRTEN_MASK 0x10
+#define DC_GPIO_AUX_CTRL_2__DC_GPIO_AUX5_BIASCRTEN__SHIFT 0x4
+#define DC_GPIO_AUX_CTRL_2__DC_GPIO_AUX6_BIASCRTEN_MASK 0x20
+#define DC_GPIO_AUX_CTRL_2__DC_GPIO_AUX6_BIASCRTEN__SHIFT 0x5
+#define DC_GPIO_AUX_CTRL_2__DC_IO_AUX1_SPARE_MASK 0xc0
+#define DC_GPIO_AUX_CTRL_2__DC_IO_AUX1_SPARE__SHIFT 0x6
+#define DC_GPIO_AUX_CTRL_2__DC_IO_AUX2_SPARE_MASK 0x300
+#define DC_GPIO_AUX_CTRL_2__DC_IO_AUX2_SPARE__SHIFT 0x8
+#define DC_GPIO_AUX_CTRL_2__DC_IO_AUX3_SPARE_MASK 0xc00
+#define DC_GPIO_AUX_CTRL_2__DC_IO_AUX3_SPARE__SHIFT 0xa
+#define DC_GPIO_AUX_CTRL_2__DC_IO_AUX4_SPARE_MASK 0x3000
+#define DC_GPIO_AUX_CTRL_2__DC_IO_AUX4_SPARE__SHIFT 0xc
+#define DC_GPIO_AUX_CTRL_2__DC_IO_AUX5_SPARE_MASK 0xc000
+#define DC_GPIO_AUX_CTRL_2__DC_IO_AUX5_SPARE__SHIFT 0xe
+#define DC_GPIO_AUX_CTRL_2__DC_IO_AUX6_SPARE_MASK 0x30000
+#define DC_GPIO_AUX_CTRL_2__DC_IO_AUX6_SPARE__SHIFT 0x10
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD12_FALLSLEWSEL_MASK 0x3
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD12_FALLSLEWSEL__SHIFT 0x0
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD34_FALLSLEWSEL_MASK 0xc
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD34_FALLSLEWSEL__SHIFT 0x2
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD56_FALLSLEWSEL_MASK 0x30
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD56_FALLSLEWSEL__SHIFT 0x4
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD12_SPIKERCEN_MASK 0x100
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD12_SPIKERCEN__SHIFT 0x8
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD34_SPIKERCEN_MASK 0x200
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD34_SPIKERCEN__SHIFT 0x9
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD56_SPIKERCEN_MASK 0x400
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD56_SPIKERCEN__SHIFT 0xa
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD12_SPIKERCSEL_MASK 0x1000
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD12_SPIKERCSEL__SHIFT 0xc
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD34_SPIKERCSEL_MASK 0x2000
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD34_SPIKERCSEL__SHIFT 0xd
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD56_SPIKERCSEL_MASK 0x4000
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD56_SPIKERCSEL__SHIFT 0xe
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD12_CSEL_0P9_MASK 0x10000
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD12_CSEL_0P9__SHIFT 0x10
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD34_CSEL_0P9_MASK 0x20000
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD34_CSEL_0P9__SHIFT 0x11
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD56_CSEL_0P9_MASK 0x40000
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD56_CSEL_0P9__SHIFT 0x12
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD12_CSEL_1P1_MASK 0x100000
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD12_CSEL_1P1__SHIFT 0x14
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD34_CSEL_1P1_MASK 0x200000
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD34_CSEL_1P1__SHIFT 0x15
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD56_CSEL_1P1_MASK 0x400000
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD56_CSEL_1P1__SHIFT 0x16
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD12_RSEL_0P9_MASK 0x1000000
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD12_RSEL_0P9__SHIFT 0x18
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD34_RSEL_0P9_MASK 0x2000000
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD34_RSEL_0P9__SHIFT 0x19
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD56_RSEL_0P9_MASK 0x4000000
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD56_RSEL_0P9__SHIFT 0x1a
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD12_RSEL_1P1_MASK 0x10000000
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD12_RSEL_1P1__SHIFT 0x1c
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD34_RSEL_1P1_MASK 0x20000000
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD34_RSEL_1P1__SHIFT 0x1d
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD56_RSEL_1P1_MASK 0x40000000
+#define DC_GPIO_HPD_CTRL_0__DC_GPIO_HPD56_RSEL_1P1__SHIFT 0x1e
+#define DC_GPIO_HPD_CTRL_1__DC_GPIO_HPD12_BIASCRTEN_MASK 0x1
+#define DC_GPIO_HPD_CTRL_1__DC_GPIO_HPD12_BIASCRTEN__SHIFT 0x0
+#define DC_GPIO_HPD_CTRL_1__DC_GPIO_HPD34_BIASCRTEN_MASK 0x2
+#define DC_GPIO_HPD_CTRL_1__DC_GPIO_HPD34_BIASCRTEN__SHIFT 0x1
+#define DC_GPIO_HPD_CTRL_1__DC_GPIO_HPD56_BIASCRTEN_MASK 0x4
+#define DC_GPIO_HPD_CTRL_1__DC_GPIO_HPD56_BIASCRTEN__SHIFT 0x2
+#define DC_GPIO_HPD_CTRL_1__DC_GPIO_HPD12_SLEWN_MASK 0x10
+#define DC_GPIO_HPD_CTRL_1__DC_GPIO_HPD12_SLEWN__SHIFT 0x4
+#define DC_GPIO_HPD_CTRL_1__DC_GPIO_HPD34_SLEWN_MASK 0x20
+#define DC_GPIO_HPD_CTRL_1__DC_GPIO_HPD34_SLEWN__SHIFT 0x5
+#define DC_GPIO_HPD_CTRL_1__DC_GPIO_HPD56_SLEWN_MASK 0x40
+#define DC_GPIO_HPD_CTRL_1__DC_GPIO_HPD56_SLEWN__SHIFT 0x6
+#define DAC_MACRO_CNTL_RESERVED0__DAC_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DAC_MACRO_CNTL_RESERVED0__DAC_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DAC_MACRO_CNTL_RESERVED1__DAC_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DAC_MACRO_CNTL_RESERVED1__DAC_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DAC_MACRO_CNTL_RESERVED2__DAC_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DAC_MACRO_CNTL_RESERVED2__DAC_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DAC_MACRO_CNTL_RESERVED3__DAC_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DAC_MACRO_CNTL_RESERVED3__DAC_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED0__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED0__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED1__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED1__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED2__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED2__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED3__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED3__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED4__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED4__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED5__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED5__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED6__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED6__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED7__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED7__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED8__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED8__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED9__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED9__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED10__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED10__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED11__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED11__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED12__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED12__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED13__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED13__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED14__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED14__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED15__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED15__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED16__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED16__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED17__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED17__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED18__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED18__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED19__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED19__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED20__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED20__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED21__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED21__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED22__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED22__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED23__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED23__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED24__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED24__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED25__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED25__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED26__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED26__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED27__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED27__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED28__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED28__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED29__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED29__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED30__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED30__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED31__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED31__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED32__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED32__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED33__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED33__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED34__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED34__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED35__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED35__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED36__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED36__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED37__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED37__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED38__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED38__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED39__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED39__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED40__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED40__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED41__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED41__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED42__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED42__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED43__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED43__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED44__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED44__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED45__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED45__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED46__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED46__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED47__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED47__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED48__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED48__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED49__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED49__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED50__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED50__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED51__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED51__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED52__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED52__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED53__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED53__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED54__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED54__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED55__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED55__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED56__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED56__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED57__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED57__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED58__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED58__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED59__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED59__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED60__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED60__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED61__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED61__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED62__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED62__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED63__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED63__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED64__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED64__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED65__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED65__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED66__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED66__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED67__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED67__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED68__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED68__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED69__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED69__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED70__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED70__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED71__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED71__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED72__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED72__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED73__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED73__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED74__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED74__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED75__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED75__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED76__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED76__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED77__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED77__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED78__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED78__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED79__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED79__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED80__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED80__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED81__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED81__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED82__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED82__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED83__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED83__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED84__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED84__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED85__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED85__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED86__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED86__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED87__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED87__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED88__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED88__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED89__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED89__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED90__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED90__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED91__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED91__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED92__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED92__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED93__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED93__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED94__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED94__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED95__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED95__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED96__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED96__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED97__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED97__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED98__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED98__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED99__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED99__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED100__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED100__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED101__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED101__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED102__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED102__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED103__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED103__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED104__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED104__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED105__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED105__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED106__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED106__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED107__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED107__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED108__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED108__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED109__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED109__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED110__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED110__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED111__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED111__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED112__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED112__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED113__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED113__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED114__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED114__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED115__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED115__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED116__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED116__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED117__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED117__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED118__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED118__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED119__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED119__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED120__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED120__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED121__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED121__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED122__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED122__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED123__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED123__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED124__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED124__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED125__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED125__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED126__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED126__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED127__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED127__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED128__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED128__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED129__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED129__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED130__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED130__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED131__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED131__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED132__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED132__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED133__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED133__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED134__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED134__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED135__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED135__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED136__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED136__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED137__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED137__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED138__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED138__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED139__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED139__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED140__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED140__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED141__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED141__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED142__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED142__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED143__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED143__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED144__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED144__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED145__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED145__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED146__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED146__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED147__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED147__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED148__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED148__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED149__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED149__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED150__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED150__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED151__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED151__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED152__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED152__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED153__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED153__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED154__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED154__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED155__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED155__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED156__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED156__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED157__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED157__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED158__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED158__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define UNIPHY_MACRO_CNTL_RESERVED159__UNIPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define UNIPHY_MACRO_CNTL_RESERVED159__UNIPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED0__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED0__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED1__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED1__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED2__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED2__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED3__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED3__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED4__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED4__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED5__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED5__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED6__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED6__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED7__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED7__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED8__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED8__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED9__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED9__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED10__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED10__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED11__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED11__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED12__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED12__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED13__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED13__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED14__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED14__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED15__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED15__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED16__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED16__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED17__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED17__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED18__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED18__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED19__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED19__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED20__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED20__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED21__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED21__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED22__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED22__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED23__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED23__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED24__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED24__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED25__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED25__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED26__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED26__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED27__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED27__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED28__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED28__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED29__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED29__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED30__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED30__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED31__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED31__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED32__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED32__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED33__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED33__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED34__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED34__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED35__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED35__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED36__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED36__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED37__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED37__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED38__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED38__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED39__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED39__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED40__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED40__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED41__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED41__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED42__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED42__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED43__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED43__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED44__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED44__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED45__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED45__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED46__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED46__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED47__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED47__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED48__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED48__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED49__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED49__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED50__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED50__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED51__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED51__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED52__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED52__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED53__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED53__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED54__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED54__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED55__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED55__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED56__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED56__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED57__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED57__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED58__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED58__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED59__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED59__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED60__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED60__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED61__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED61__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED62__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED62__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED63__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED63__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED64__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED64__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED65__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED65__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED66__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED66__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED67__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED67__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED68__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED68__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED69__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED69__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED70__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED70__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED71__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED71__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED72__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED72__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED73__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED73__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED74__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED74__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED75__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED75__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED76__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED76__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED77__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED77__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED78__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED78__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED79__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED79__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED80__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED80__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED81__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED81__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED82__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED82__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED83__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED83__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED84__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED84__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED85__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED85__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED86__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED86__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED87__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED87__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED88__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED88__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED89__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED89__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED90__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED90__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED91__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED91__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED92__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED92__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED93__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED93__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED94__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED94__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED95__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED95__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED96__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED96__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED97__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED97__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED98__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED98__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED99__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED99__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED100__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED100__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED101__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED101__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED102__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED102__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED103__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED103__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED104__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED104__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED105__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED105__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED106__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED106__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED107__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED107__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED108__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED108__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED109__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED109__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED110__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED110__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED111__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED111__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED112__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED112__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED113__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED113__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED114__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED114__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED115__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED115__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED116__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED116__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED117__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED117__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED118__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED118__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED119__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED119__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED120__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED120__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED121__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED121__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED122__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED122__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED123__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED123__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED124__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED124__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED125__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED125__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED126__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED126__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED127__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED127__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED128__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED128__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED129__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED129__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED130__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED130__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED131__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED131__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED132__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED132__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED133__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED133__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED134__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED134__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED135__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED135__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED136__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED136__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED137__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED137__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED138__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED138__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED139__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED139__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED140__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED140__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED141__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED141__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED142__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED142__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED143__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED143__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED144__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED144__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED145__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED145__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED146__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED146__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED147__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED147__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED148__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED148__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED149__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED149__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED150__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED150__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED151__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED151__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED152__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED152__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED153__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED153__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED154__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED154__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED155__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED155__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED156__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED156__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED157__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED157__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED158__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED158__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED159__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED159__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED160__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED160__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED161__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED161__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED162__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED162__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED163__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED163__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED164__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED164__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED165__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED165__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED166__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED166__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED167__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED167__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED168__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED168__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED169__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED169__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED170__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED170__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED171__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED171__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED172__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED172__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED173__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED173__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED174__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED174__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED175__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED175__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED176__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED176__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED177__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED177__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED178__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED178__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED179__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED179__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED180__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED180__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED181__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED181__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED182__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED182__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED183__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED183__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED184__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED184__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED185__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED185__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED186__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED186__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED187__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED187__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED188__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED188__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED189__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED189__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED190__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED190__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED191__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED191__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED192__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED192__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED193__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED193__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED194__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED194__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED195__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED195__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED196__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED196__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED197__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED197__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED198__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED198__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED199__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED199__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED200__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED200__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED201__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED201__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED202__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED202__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED203__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED203__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED204__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED204__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED205__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED205__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED206__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED206__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED207__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED207__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED208__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED208__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED209__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED209__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED210__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED210__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED211__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED211__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED212__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED212__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED213__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED213__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED214__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED214__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED215__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED215__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED216__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED216__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED217__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED217__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED218__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED218__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED219__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED219__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED220__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED220__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED221__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED221__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED222__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED222__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED223__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED223__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED224__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED224__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED225__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED225__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED226__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED226__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED227__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED227__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED228__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED228__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED229__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED229__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED230__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED230__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED231__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED231__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED232__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED232__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED233__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED233__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED234__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED234__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED235__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED235__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED236__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED236__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED237__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED237__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED238__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED238__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED239__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED239__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED240__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED240__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED241__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED241__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED242__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED242__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED243__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED243__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED244__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED244__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED245__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED245__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED246__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED246__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED247__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED247__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED248__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED248__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED249__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED249__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED250__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED250__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED251__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED251__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED252__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED252__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED253__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED253__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED254__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED254__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED255__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED255__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED256__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED256__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED257__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED257__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED258__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED258__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED259__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED259__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED260__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED260__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED261__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED261__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED262__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED262__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED263__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED263__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED264__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED264__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED265__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED265__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED266__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED266__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED267__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED267__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED268__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED268__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED269__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED269__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED270__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED270__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED271__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED271__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED272__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED272__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED273__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED273__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED274__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED274__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED275__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED275__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED276__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED276__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED277__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED277__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED278__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED278__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED279__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED279__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED280__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED280__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED281__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED281__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED282__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED282__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED283__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED283__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED284__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED284__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED285__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED285__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED286__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED286__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED287__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED287__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED288__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED288__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED289__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED289__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED290__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED290__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED291__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED291__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED292__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED292__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED293__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED293__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED294__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED294__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED295__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED295__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED296__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED296__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED297__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED297__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED298__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED298__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED299__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED299__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED300__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED300__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED301__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED301__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED302__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED302__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED303__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED303__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED304__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED304__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED305__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED305__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED306__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED306__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED307__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED307__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED308__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED308__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED309__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED309__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED310__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED310__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED311__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED311__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED312__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED312__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED313__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED313__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED314__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED314__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED315__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED315__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED316__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED316__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED317__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED317__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED318__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED318__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED319__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED319__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED320__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED320__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED321__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED321__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED322__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED322__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED323__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED323__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED324__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED324__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED325__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED325__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED326__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED326__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED327__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED327__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED328__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED328__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED329__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED329__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED330__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED330__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED331__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED331__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED332__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED332__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED333__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED333__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED334__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED334__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED335__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED335__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED336__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED336__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED337__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED337__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED338__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED338__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED339__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED339__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED340__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED340__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED341__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED341__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED342__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED342__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED343__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED343__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED344__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED344__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED345__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED345__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED346__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED346__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED347__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED347__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED348__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED348__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED349__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED349__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED350__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED350__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED351__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED351__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED352__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED352__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED353__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED353__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED354__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED354__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED355__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED355__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED356__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED356__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED357__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED357__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED358__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED358__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED359__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED359__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED360__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED360__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED361__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED361__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED362__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED362__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED363__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED363__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED364__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED364__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED365__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED365__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED366__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED366__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED367__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED367__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED368__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED368__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED369__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED369__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED370__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED370__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED371__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED371__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED372__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED372__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED373__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED373__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED374__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED374__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED375__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED375__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED376__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED376__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED377__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED377__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED378__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED378__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DCRX_PHY_MACRO_CNTL_RESERVED379__DCRX_PHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DCRX_PHY_MACRO_CNTL_RESERVED379__DCRX_PHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED0__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED0__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED1__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED1__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED2__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED2__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED3__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED3__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED4__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED4__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED5__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED5__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED6__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED6__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED7__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED7__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED8__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED8__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED9__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED9__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED10__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED10__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED11__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED11__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED12__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED12__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED13__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED13__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED14__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED14__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED15__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED15__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED16__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED16__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED17__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED17__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED18__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED18__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED19__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED19__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED20__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED20__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED21__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED21__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED22__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED22__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED23__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED23__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED24__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED24__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED25__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED25__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED26__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED26__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED27__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED27__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED28__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED28__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED29__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED29__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED30__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED30__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED31__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED31__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED32__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED32__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED33__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED33__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED34__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED34__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED35__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED35__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED36__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED36__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED37__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED37__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED38__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED38__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED39__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED39__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED40__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED40__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED41__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED41__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED42__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED42__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED43__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED43__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED44__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED44__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED45__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED45__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED46__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED46__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED47__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED47__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED48__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED48__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED49__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED49__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED50__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED50__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED51__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED51__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED52__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED52__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED53__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED53__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED54__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED54__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED55__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED55__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED56__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED56__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED57__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED57__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED58__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED58__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED59__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED59__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED60__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED60__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED61__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED61__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED62__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED62__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define DPHY_MACRO_CNTL_RESERVED63__DPHY_MACRO_CNTL_RESERVED_MASK 0xffffffff
+#define DPHY_MACRO_CNTL_RESERVED63__DPHY_MACRO_CNTL_RESERVED__SHIFT 0x0
+#define GRPH_ENABLE__GRPH_ENABLE_MASK 0x1
+#define GRPH_ENABLE__GRPH_ENABLE__SHIFT 0x0
+#define GRPH_ENABLE__GRPH_KEYER_ALPHA_SEL_MASK 0x2
+#define GRPH_ENABLE__GRPH_KEYER_ALPHA_SEL__SHIFT 0x1
+#define GRPH_CONTROL__GRPH_DEPTH_MASK 0x3
+#define GRPH_CONTROL__GRPH_DEPTH__SHIFT 0x0
+#define GRPH_CONTROL__GRPH_NUM_BANKS_MASK 0xc
+#define GRPH_CONTROL__GRPH_NUM_BANKS__SHIFT 0x2
+#define GRPH_CONTROL__GRPH_Z_MASK 0x30
+#define GRPH_CONTROL__GRPH_Z__SHIFT 0x4
+#define GRPH_CONTROL__GRPH_BANK_WIDTH_MASK 0xc0
+#define GRPH_CONTROL__GRPH_BANK_WIDTH__SHIFT 0x6
+#define GRPH_CONTROL__GRPH_FORMAT_MASK 0x700
+#define GRPH_CONTROL__GRPH_FORMAT__SHIFT 0x8
+#define GRPH_CONTROL__GRPH_BANK_HEIGHT_MASK 0x1800
+#define GRPH_CONTROL__GRPH_BANK_HEIGHT__SHIFT 0xb
+#define GRPH_CONTROL__GRPH_TILE_SPLIT_MASK 0xe000
+#define GRPH_CONTROL__GRPH_TILE_SPLIT__SHIFT 0xd
+#define GRPH_CONTROL__GRPH_ADDRESS_TRANSLATION_ENABLE_MASK 0x10000
+#define GRPH_CONTROL__GRPH_ADDRESS_TRANSLATION_ENABLE__SHIFT 0x10
+#define GRPH_CONTROL__GRPH_PRIVILEGED_ACCESS_ENABLE_MASK 0x20000
+#define GRPH_CONTROL__GRPH_PRIVILEGED_ACCESS_ENABLE__SHIFT 0x11
+#define GRPH_CONTROL__GRPH_MACRO_TILE_ASPECT_MASK 0xc0000
+#define GRPH_CONTROL__GRPH_MACRO_TILE_ASPECT__SHIFT 0x12
+#define GRPH_CONTROL__GRPH_ARRAY_MODE_MASK 0xf00000
+#define GRPH_CONTROL__GRPH_ARRAY_MODE__SHIFT 0x14
+#define GRPH_CONTROL__GRPH_PIPE_CONFIG_MASK 0x1f000000
+#define GRPH_CONTROL__GRPH_PIPE_CONFIG__SHIFT 0x18
+#define GRPH_CONTROL__GRPH_MICRO_TILE_MODE_MASK 0x60000000
+#define GRPH_CONTROL__GRPH_MICRO_TILE_MODE__SHIFT 0x1d
+#define GRPH_CONTROL__GRPH_COLOR_EXPANSION_MODE_MASK 0x80000000
+#define GRPH_CONTROL__GRPH_COLOR_EXPANSION_MODE__SHIFT 0x1f
+#define GRPH_LUT_10BIT_BYPASS__GRPH_LUT_10BIT_BYPASS_EN_MASK 0x100
+#define GRPH_LUT_10BIT_BYPASS__GRPH_LUT_10BIT_BYPASS_EN__SHIFT 0x8
+#define GRPH_LUT_10BIT_BYPASS__GRPH_LUT_10BIT_BYPASS_DBL_BUF_EN_MASK 0x10000
+#define GRPH_LUT_10BIT_BYPASS__GRPH_LUT_10BIT_BYPASS_DBL_BUF_EN__SHIFT 0x10
+#define GRPH_SWAP_CNTL__GRPH_ENDIAN_SWAP_MASK 0x3
+#define GRPH_SWAP_CNTL__GRPH_ENDIAN_SWAP__SHIFT 0x0
+#define GRPH_SWAP_CNTL__GRPH_RED_CROSSBAR_MASK 0x30
+#define GRPH_SWAP_CNTL__GRPH_RED_CROSSBAR__SHIFT 0x4
+#define GRPH_SWAP_CNTL__GRPH_GREEN_CROSSBAR_MASK 0xc0
+#define GRPH_SWAP_CNTL__GRPH_GREEN_CROSSBAR__SHIFT 0x6
+#define GRPH_SWAP_CNTL__GRPH_BLUE_CROSSBAR_MASK 0x300
+#define GRPH_SWAP_CNTL__GRPH_BLUE_CROSSBAR__SHIFT 0x8
+#define GRPH_SWAP_CNTL__GRPH_ALPHA_CROSSBAR_MASK 0xc00
+#define GRPH_SWAP_CNTL__GRPH_ALPHA_CROSSBAR__SHIFT 0xa
+#define GRPH_PRIMARY_SURFACE_ADDRESS__GRPH_PRIMARY_DFQ_ENABLE_MASK 0x1
+#define GRPH_PRIMARY_SURFACE_ADDRESS__GRPH_PRIMARY_DFQ_ENABLE__SHIFT 0x0
+#define GRPH_PRIMARY_SURFACE_ADDRESS__GRPH_PRIMARY_SURFACE_ADDRESS_MASK 0xffffff00
+#define GRPH_PRIMARY_SURFACE_ADDRESS__GRPH_PRIMARY_SURFACE_ADDRESS__SHIFT 0x8
+#define GRPH_SECONDARY_SURFACE_ADDRESS__GRPH_SECONDARY_DFQ_ENABLE_MASK 0x1
+#define GRPH_SECONDARY_SURFACE_ADDRESS__GRPH_SECONDARY_DFQ_ENABLE__SHIFT 0x0
+#define GRPH_SECONDARY_SURFACE_ADDRESS__GRPH_SECONDARY_SURFACE_ADDRESS_MASK 0xffffff00
+#define GRPH_SECONDARY_SURFACE_ADDRESS__GRPH_SECONDARY_SURFACE_ADDRESS__SHIFT 0x8
+#define GRPH_PITCH__GRPH_PITCH_MASK 0x7fff
+#define GRPH_PITCH__GRPH_PITCH__SHIFT 0x0
+#define GRPH_PRIMARY_SURFACE_ADDRESS_HIGH__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_MASK 0xff
+#define GRPH_PRIMARY_SURFACE_ADDRESS_HIGH__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH__SHIFT 0x0
+#define GRPH_SECONDARY_SURFACE_ADDRESS_HIGH__GRPH_SECONDARY_SURFACE_ADDRESS_HIGH_MASK 0xff
+#define GRPH_SECONDARY_SURFACE_ADDRESS_HIGH__GRPH_SECONDARY_SURFACE_ADDRESS_HIGH__SHIFT 0x0
+#define GRPH_SURFACE_OFFSET_X__GRPH_SURFACE_OFFSET_X_MASK 0x3fff
+#define GRPH_SURFACE_OFFSET_X__GRPH_SURFACE_OFFSET_X__SHIFT 0x0
+#define GRPH_SURFACE_OFFSET_Y__GRPH_SURFACE_OFFSET_Y_MASK 0x3fff
+#define GRPH_SURFACE_OFFSET_Y__GRPH_SURFACE_OFFSET_Y__SHIFT 0x0
+#define GRPH_X_START__GRPH_X_START_MASK 0x3fff
+#define GRPH_X_START__GRPH_X_START__SHIFT 0x0
+#define GRPH_Y_START__GRPH_Y_START_MASK 0x3fff
+#define GRPH_Y_START__GRPH_Y_START__SHIFT 0x0
+#define GRPH_X_END__GRPH_X_END_MASK 0x7fff
+#define GRPH_X_END__GRPH_X_END__SHIFT 0x0
+#define GRPH_Y_END__GRPH_Y_END_MASK 0x7fff
+#define GRPH_Y_END__GRPH_Y_END__SHIFT 0x0
+#define INPUT_GAMMA_CONTROL__GRPH_INPUT_GAMMA_MODE_MASK 0x1
+#define INPUT_GAMMA_CONTROL__GRPH_INPUT_GAMMA_MODE__SHIFT 0x0
+#define GRPH_UPDATE__GRPH_MODE_UPDATE_PENDING_MASK 0x1
+#define GRPH_UPDATE__GRPH_MODE_UPDATE_PENDING__SHIFT 0x0
+#define GRPH_UPDATE__GRPH_MODE_UPDATE_TAKEN_MASK 0x2
+#define GRPH_UPDATE__GRPH_MODE_UPDATE_TAKEN__SHIFT 0x1
+#define GRPH_UPDATE__GRPH_SURFACE_UPDATE_PENDING_MASK 0x4
+#define GRPH_UPDATE__GRPH_SURFACE_UPDATE_PENDING__SHIFT 0x2
+#define GRPH_UPDATE__GRPH_SURFACE_UPDATE_TAKEN_MASK 0x8
+#define GRPH_UPDATE__GRPH_SURFACE_UPDATE_TAKEN__SHIFT 0x3
+#define GRPH_UPDATE__GRPH_SURFACE_XDMA_PENDING_ENABLE_MASK 0x100
+#define GRPH_UPDATE__GRPH_SURFACE_XDMA_PENDING_ENABLE__SHIFT 0x8
+#define GRPH_UPDATE__GRPH_UPDATE_LOCK_MASK 0x10000
+#define GRPH_UPDATE__GRPH_UPDATE_LOCK__SHIFT 0x10
+#define GRPH_UPDATE__GRPH_SURFACE_IGNORE_UPDATE_LOCK_MASK 0x100000
+#define GRPH_UPDATE__GRPH_SURFACE_IGNORE_UPDATE_LOCK__SHIFT 0x14
+#define GRPH_UPDATE__GRPH_MODE_DISABLE_MULTIPLE_UPDATE_MASK 0x1000000
+#define GRPH_UPDATE__GRPH_MODE_DISABLE_MULTIPLE_UPDATE__SHIFT 0x18
+#define GRPH_UPDATE__GRPH_SURFACE_DISABLE_MULTIPLE_UPDATE_MASK 0x10000000
+#define GRPH_UPDATE__GRPH_SURFACE_DISABLE_MULTIPLE_UPDATE__SHIFT 0x1c
+#define GRPH_FLIP_CONTROL__GRPH_SURFACE_UPDATE_H_RETRACE_EN_MASK 0x1
+#define GRPH_FLIP_CONTROL__GRPH_SURFACE_UPDATE_H_RETRACE_EN__SHIFT 0x0
+#define GRPH_FLIP_CONTROL__GRPH_XDMA_SUPER_AA_EN_MASK 0x2
+#define GRPH_FLIP_CONTROL__GRPH_XDMA_SUPER_AA_EN__SHIFT 0x1
+#define GRPH_FLIP_CONTROL__GRPH_SURFACE_UPDATE_IMMEDIATE_EN_MASK 0x10
+#define GRPH_FLIP_CONTROL__GRPH_SURFACE_UPDATE_IMMEDIATE_EN__SHIFT 0x4
+#define GRPH_FLIP_CONTROL__GRPH_SURFACE_UPDATE_PENDING_MODE_MASK 0x20
+#define GRPH_FLIP_CONTROL__GRPH_SURFACE_UPDATE_PENDING_MODE__SHIFT 0x5
+#define GRPH_SURFACE_ADDRESS_INUSE__GRPH_SURFACE_ADDRESS_INUSE_MASK 0xffffff00
+#define GRPH_SURFACE_ADDRESS_INUSE__GRPH_SURFACE_ADDRESS_INUSE__SHIFT 0x8
+#define GRPH_DFQ_CONTROL__GRPH_DFQ_RESET_MASK 0x1
+#define GRPH_DFQ_CONTROL__GRPH_DFQ_RESET__SHIFT 0x0
+#define GRPH_DFQ_CONTROL__GRPH_DFQ_SIZE_MASK 0x70
+#define GRPH_DFQ_CONTROL__GRPH_DFQ_SIZE__SHIFT 0x4
+#define GRPH_DFQ_CONTROL__GRPH_DFQ_MIN_FREE_ENTRIES_MASK 0x700
+#define GRPH_DFQ_CONTROL__GRPH_DFQ_MIN_FREE_ENTRIES__SHIFT 0x8
+#define GRPH_DFQ_STATUS__GRPH_PRIMARY_DFQ_NUM_ENTRIES_MASK 0xf
+#define GRPH_DFQ_STATUS__GRPH_PRIMARY_DFQ_NUM_ENTRIES__SHIFT 0x0
+#define GRPH_DFQ_STATUS__GRPH_SECONDARY_DFQ_NUM_ENTRIES_MASK 0xf0
+#define GRPH_DFQ_STATUS__GRPH_SECONDARY_DFQ_NUM_ENTRIES__SHIFT 0x4
+#define GRPH_DFQ_STATUS__GRPH_DFQ_RESET_FLAG_MASK 0x100
+#define GRPH_DFQ_STATUS__GRPH_DFQ_RESET_FLAG__SHIFT 0x8
+#define GRPH_DFQ_STATUS__GRPH_DFQ_RESET_ACK_MASK 0x200
+#define GRPH_DFQ_STATUS__GRPH_DFQ_RESET_ACK__SHIFT 0x9
+#define GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_OCCURRED_MASK 0x1
+#define GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_OCCURRED__SHIFT 0x0
+#define GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK 0x100
+#define GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR__SHIFT 0x8
+#define GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK 0x1
+#define GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK__SHIFT 0x0
+#define GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_TYPE_MASK 0x100
+#define GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_TYPE__SHIFT 0x8
+#define GRPH_SURFACE_ADDRESS_HIGH_INUSE__GRPH_SURFACE_ADDRESS_HIGH_INUSE_MASK 0xff
+#define GRPH_SURFACE_ADDRESS_HIGH_INUSE__GRPH_SURFACE_ADDRESS_HIGH_INUSE__SHIFT 0x0
+#define GRPH_COMPRESS_SURFACE_ADDRESS__GRPH_COMPRESS_SURFACE_ADDRESS_MASK 0xffffff00
+#define GRPH_COMPRESS_SURFACE_ADDRESS__GRPH_COMPRESS_SURFACE_ADDRESS__SHIFT 0x8
+#define GRPH_COMPRESS_PITCH__GRPH_COMPRESS_PITCH_MASK 0x1ffc0
+#define GRPH_COMPRESS_PITCH__GRPH_COMPRESS_PITCH__SHIFT 0x6
+#define GRPH_COMPRESS_SURFACE_ADDRESS_HIGH__GRPH_COMPRESS_SURFACE_ADDRESS_HIGH_MASK 0xff
+#define GRPH_COMPRESS_SURFACE_ADDRESS_HIGH__GRPH_COMPRESS_SURFACE_ADDRESS_HIGH__SHIFT 0x0
+#define GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT__GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT_MASK 0xff
+#define GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT__GRPH_PIPE_OUTSTANDING_REQUEST_LIMIT__SHIFT 0x0
+#define PRESCALE_GRPH_CONTROL__GRPH_PRESCALE_SELECT_MASK 0x1
+#define PRESCALE_GRPH_CONTROL__GRPH_PRESCALE_SELECT__SHIFT 0x0
+#define PRESCALE_GRPH_CONTROL__GRPH_PRESCALE_R_SIGN_MASK 0x2
+#define PRESCALE_GRPH_CONTROL__GRPH_PRESCALE_R_SIGN__SHIFT 0x1
+#define PRESCALE_GRPH_CONTROL__GRPH_PRESCALE_G_SIGN_MASK 0x4
+#define PRESCALE_GRPH_CONTROL__GRPH_PRESCALE_G_SIGN__SHIFT 0x2
+#define PRESCALE_GRPH_CONTROL__GRPH_PRESCALE_B_SIGN_MASK 0x8
+#define PRESCALE_GRPH_CONTROL__GRPH_PRESCALE_B_SIGN__SHIFT 0x3
+#define PRESCALE_GRPH_CONTROL__GRPH_PRESCALE_BYPASS_MASK 0x10
+#define PRESCALE_GRPH_CONTROL__GRPH_PRESCALE_BYPASS__SHIFT 0x4
+#define PRESCALE_VALUES_GRPH_R__GRPH_PRESCALE_BIAS_R_MASK 0xffff
+#define PRESCALE_VALUES_GRPH_R__GRPH_PRESCALE_BIAS_R__SHIFT 0x0
+#define PRESCALE_VALUES_GRPH_R__GRPH_PRESCALE_SCALE_R_MASK 0xffff0000
+#define PRESCALE_VALUES_GRPH_R__GRPH_PRESCALE_SCALE_R__SHIFT 0x10
+#define PRESCALE_VALUES_GRPH_G__GRPH_PRESCALE_BIAS_G_MASK 0xffff
+#define PRESCALE_VALUES_GRPH_G__GRPH_PRESCALE_BIAS_G__SHIFT 0x0
+#define PRESCALE_VALUES_GRPH_G__GRPH_PRESCALE_SCALE_G_MASK 0xffff0000
+#define PRESCALE_VALUES_GRPH_G__GRPH_PRESCALE_SCALE_G__SHIFT 0x10
+#define PRESCALE_VALUES_GRPH_B__GRPH_PRESCALE_BIAS_B_MASK 0xffff
+#define PRESCALE_VALUES_GRPH_B__GRPH_PRESCALE_BIAS_B__SHIFT 0x0
+#define PRESCALE_VALUES_GRPH_B__GRPH_PRESCALE_SCALE_B_MASK 0xffff0000
+#define PRESCALE_VALUES_GRPH_B__GRPH_PRESCALE_SCALE_B__SHIFT 0x10
+#define INPUT_CSC_CONTROL__INPUT_CSC_GRPH_MODE_MASK 0x3
+#define INPUT_CSC_CONTROL__INPUT_CSC_GRPH_MODE__SHIFT 0x0
+#define INPUT_CSC_C11_C12__INPUT_CSC_C11_MASK 0xffff
+#define INPUT_CSC_C11_C12__INPUT_CSC_C11__SHIFT 0x0
+#define INPUT_CSC_C11_C12__INPUT_CSC_C12_MASK 0xffff0000
+#define INPUT_CSC_C11_C12__INPUT_CSC_C12__SHIFT 0x10
+#define INPUT_CSC_C13_C14__INPUT_CSC_C13_MASK 0xffff
+#define INPUT_CSC_C13_C14__INPUT_CSC_C13__SHIFT 0x0
+#define INPUT_CSC_C13_C14__INPUT_CSC_C14_MASK 0xffff0000
+#define INPUT_CSC_C13_C14__INPUT_CSC_C14__SHIFT 0x10
+#define INPUT_CSC_C21_C22__INPUT_CSC_C21_MASK 0xffff
+#define INPUT_CSC_C21_C22__INPUT_CSC_C21__SHIFT 0x0
+#define INPUT_CSC_C21_C22__INPUT_CSC_C22_MASK 0xffff0000
+#define INPUT_CSC_C21_C22__INPUT_CSC_C22__SHIFT 0x10
+#define INPUT_CSC_C23_C24__INPUT_CSC_C23_MASK 0xffff
+#define INPUT_CSC_C23_C24__INPUT_CSC_C23__SHIFT 0x0
+#define INPUT_CSC_C23_C24__INPUT_CSC_C24_MASK 0xffff0000
+#define INPUT_CSC_C23_C24__INPUT_CSC_C24__SHIFT 0x10
+#define INPUT_CSC_C31_C32__INPUT_CSC_C31_MASK 0xffff
+#define INPUT_CSC_C31_C32__INPUT_CSC_C31__SHIFT 0x0
+#define INPUT_CSC_C31_C32__INPUT_CSC_C32_MASK 0xffff0000
+#define INPUT_CSC_C31_C32__INPUT_CSC_C32__SHIFT 0x10
+#define INPUT_CSC_C33_C34__INPUT_CSC_C33_MASK 0xffff
+#define INPUT_CSC_C33_C34__INPUT_CSC_C33__SHIFT 0x0
+#define INPUT_CSC_C33_C34__INPUT_CSC_C34_MASK 0xffff0000
+#define INPUT_CSC_C33_C34__INPUT_CSC_C34__SHIFT 0x10
+#define OUTPUT_CSC_CONTROL__OUTPUT_CSC_GRPH_MODE_MASK 0x7
+#define OUTPUT_CSC_CONTROL__OUTPUT_CSC_GRPH_MODE__SHIFT 0x0
+#define OUTPUT_CSC_C11_C12__OUTPUT_CSC_C11_MASK 0xffff
+#define OUTPUT_CSC_C11_C12__OUTPUT_CSC_C11__SHIFT 0x0
+#define OUTPUT_CSC_C11_C12__OUTPUT_CSC_C12_MASK 0xffff0000
+#define OUTPUT_CSC_C11_C12__OUTPUT_CSC_C12__SHIFT 0x10
+#define OUTPUT_CSC_C13_C14__OUTPUT_CSC_C13_MASK 0xffff
+#define OUTPUT_CSC_C13_C14__OUTPUT_CSC_C13__SHIFT 0x0
+#define OUTPUT_CSC_C13_C14__OUTPUT_CSC_C14_MASK 0xffff0000
+#define OUTPUT_CSC_C13_C14__OUTPUT_CSC_C14__SHIFT 0x10
+#define OUTPUT_CSC_C21_C22__OUTPUT_CSC_C21_MASK 0xffff
+#define OUTPUT_CSC_C21_C22__OUTPUT_CSC_C21__SHIFT 0x0
+#define OUTPUT_CSC_C21_C22__OUTPUT_CSC_C22_MASK 0xffff0000
+#define OUTPUT_CSC_C21_C22__OUTPUT_CSC_C22__SHIFT 0x10
+#define OUTPUT_CSC_C23_C24__OUTPUT_CSC_C23_MASK 0xffff
+#define OUTPUT_CSC_C23_C24__OUTPUT_CSC_C23__SHIFT 0x0
+#define OUTPUT_CSC_C23_C24__OUTPUT_CSC_C24_MASK 0xffff0000
+#define OUTPUT_CSC_C23_C24__OUTPUT_CSC_C24__SHIFT 0x10
+#define OUTPUT_CSC_C31_C32__OUTPUT_CSC_C31_MASK 0xffff
+#define OUTPUT_CSC_C31_C32__OUTPUT_CSC_C31__SHIFT 0x0
+#define OUTPUT_CSC_C31_C32__OUTPUT_CSC_C32_MASK 0xffff0000
+#define OUTPUT_CSC_C31_C32__OUTPUT_CSC_C32__SHIFT 0x10
+#define OUTPUT_CSC_C33_C34__OUTPUT_CSC_C33_MASK 0xffff
+#define OUTPUT_CSC_C33_C34__OUTPUT_CSC_C33__SHIFT 0x0
+#define OUTPUT_CSC_C33_C34__OUTPUT_CSC_C34_MASK 0xffff0000
+#define OUTPUT_CSC_C33_C34__OUTPUT_CSC_C34__SHIFT 0x10
+#define COMM_MATRIXA_TRANS_C11_C12__COMM_MATRIXA_TRANS_C11_MASK 0xffff
+#define COMM_MATRIXA_TRANS_C11_C12__COMM_MATRIXA_TRANS_C11__SHIFT 0x0
+#define COMM_MATRIXA_TRANS_C11_C12__COMM_MATRIXA_TRANS_C12_MASK 0xffff0000
+#define COMM_MATRIXA_TRANS_C11_C12__COMM_MATRIXA_TRANS_C12__SHIFT 0x10
+#define COMM_MATRIXA_TRANS_C13_C14__COMM_MATRIXA_TRANS_C13_MASK 0xffff
+#define COMM_MATRIXA_TRANS_C13_C14__COMM_MATRIXA_TRANS_C13__SHIFT 0x0
+#define COMM_MATRIXA_TRANS_C13_C14__COMM_MATRIXA_TRANS_C14_MASK 0xffff0000
+#define COMM_MATRIXA_TRANS_C13_C14__COMM_MATRIXA_TRANS_C14__SHIFT 0x10
+#define COMM_MATRIXA_TRANS_C21_C22__COMM_MATRIXA_TRANS_C21_MASK 0xffff
+#define COMM_MATRIXA_TRANS_C21_C22__COMM_MATRIXA_TRANS_C21__SHIFT 0x0
+#define COMM_MATRIXA_TRANS_C21_C22__COMM_MATRIXA_TRANS_C22_MASK 0xffff0000
+#define COMM_MATRIXA_TRANS_C21_C22__COMM_MATRIXA_TRANS_C22__SHIFT 0x10
+#define COMM_MATRIXA_TRANS_C23_C24__COMM_MATRIXA_TRANS_C23_MASK 0xffff
+#define COMM_MATRIXA_TRANS_C23_C24__COMM_MATRIXA_TRANS_C23__SHIFT 0x0
+#define COMM_MATRIXA_TRANS_C23_C24__COMM_MATRIXA_TRANS_C24_MASK 0xffff0000
+#define COMM_MATRIXA_TRANS_C23_C24__COMM_MATRIXA_TRANS_C24__SHIFT 0x10
+#define COMM_MATRIXA_TRANS_C31_C32__COMM_MATRIXA_TRANS_C31_MASK 0xffff
+#define COMM_MATRIXA_TRANS_C31_C32__COMM_MATRIXA_TRANS_C31__SHIFT 0x0
+#define COMM_MATRIXA_TRANS_C31_C32__COMM_MATRIXA_TRANS_C32_MASK 0xffff0000
+#define COMM_MATRIXA_TRANS_C31_C32__COMM_MATRIXA_TRANS_C32__SHIFT 0x10
+#define COMM_MATRIXA_TRANS_C33_C34__COMM_MATRIXA_TRANS_C33_MASK 0xffff
+#define COMM_MATRIXA_TRANS_C33_C34__COMM_MATRIXA_TRANS_C33__SHIFT 0x0
+#define COMM_MATRIXA_TRANS_C33_C34__COMM_MATRIXA_TRANS_C34_MASK 0xffff0000
+#define COMM_MATRIXA_TRANS_C33_C34__COMM_MATRIXA_TRANS_C34__SHIFT 0x10
+#define COMM_MATRIXB_TRANS_C11_C12__COMM_MATRIXB_TRANS_C11_MASK 0xffff
+#define COMM_MATRIXB_TRANS_C11_C12__COMM_MATRIXB_TRANS_C11__SHIFT 0x0
+#define COMM_MATRIXB_TRANS_C11_C12__COMM_MATRIXB_TRANS_C12_MASK 0xffff0000
+#define COMM_MATRIXB_TRANS_C11_C12__COMM_MATRIXB_TRANS_C12__SHIFT 0x10
+#define COMM_MATRIXB_TRANS_C13_C14__COMM_MATRIXB_TRANS_C13_MASK 0xffff
+#define COMM_MATRIXB_TRANS_C13_C14__COMM_MATRIXB_TRANS_C13__SHIFT 0x0
+#define COMM_MATRIXB_TRANS_C13_C14__COMM_MATRIXB_TRANS_C14_MASK 0xffff0000
+#define COMM_MATRIXB_TRANS_C13_C14__COMM_MATRIXB_TRANS_C14__SHIFT 0x10
+#define COMM_MATRIXB_TRANS_C21_C22__COMM_MATRIXB_TRANS_C21_MASK 0xffff
+#define COMM_MATRIXB_TRANS_C21_C22__COMM_MATRIXB_TRANS_C21__SHIFT 0x0
+#define COMM_MATRIXB_TRANS_C21_C22__COMM_MATRIXB_TRANS_C22_MASK 0xffff0000
+#define COMM_MATRIXB_TRANS_C21_C22__COMM_MATRIXB_TRANS_C22__SHIFT 0x10
+#define COMM_MATRIXB_TRANS_C23_C24__COMM_MATRIXB_TRANS_C23_MASK 0xffff
+#define COMM_MATRIXB_TRANS_C23_C24__COMM_MATRIXB_TRANS_C23__SHIFT 0x0
+#define COMM_MATRIXB_TRANS_C23_C24__COMM_MATRIXB_TRANS_C24_MASK 0xffff0000
+#define COMM_MATRIXB_TRANS_C23_C24__COMM_MATRIXB_TRANS_C24__SHIFT 0x10
+#define COMM_MATRIXB_TRANS_C31_C32__COMM_MATRIXB_TRANS_C31_MASK 0xffff
+#define COMM_MATRIXB_TRANS_C31_C32__COMM_MATRIXB_TRANS_C31__SHIFT 0x0
+#define COMM_MATRIXB_TRANS_C31_C32__COMM_MATRIXB_TRANS_C32_MASK 0xffff0000
+#define COMM_MATRIXB_TRANS_C31_C32__COMM_MATRIXB_TRANS_C32__SHIFT 0x10
+#define COMM_MATRIXB_TRANS_C33_C34__COMM_MATRIXB_TRANS_C33_MASK 0xffff
+#define COMM_MATRIXB_TRANS_C33_C34__COMM_MATRIXB_TRANS_C33__SHIFT 0x0
+#define COMM_MATRIXB_TRANS_C33_C34__COMM_MATRIXB_TRANS_C34_MASK 0xffff0000
+#define COMM_MATRIXB_TRANS_C33_C34__COMM_MATRIXB_TRANS_C34__SHIFT 0x10
+#define DENORM_CONTROL__DENORM_MODE_MASK 0x7
+#define DENORM_CONTROL__DENORM_MODE__SHIFT 0x0
+#define DENORM_CONTROL__DENORM_14BIT_OUT_MASK 0x10
+#define DENORM_CONTROL__DENORM_14BIT_OUT__SHIFT 0x4
+#define OUT_ROUND_CONTROL__OUT_ROUND_TRUNC_MODE_MASK 0xf
+#define OUT_ROUND_CONTROL__OUT_ROUND_TRUNC_MODE__SHIFT 0x0
+#define OUT_CLAMP_CONTROL_R_CR__OUT_CLAMP_MAX_R_CR_MASK 0x3fff
+#define OUT_CLAMP_CONTROL_R_CR__OUT_CLAMP_MAX_R_CR__SHIFT 0x0
+#define OUT_CLAMP_CONTROL_R_CR__OUT_CLAMP_MIN_R_CR_MASK 0x3fff0000
+#define OUT_CLAMP_CONTROL_R_CR__OUT_CLAMP_MIN_R_CR__SHIFT 0x10
+#define OUT_CLAMP_CONTROL_G_Y__OUT_CLAMP_MAX_G_Y_MASK 0x3fff
+#define OUT_CLAMP_CONTROL_G_Y__OUT_CLAMP_MAX_G_Y__SHIFT 0x0
+#define OUT_CLAMP_CONTROL_G_Y__OUT_CLAMP_MIN_G_Y_MASK 0x3fff0000
+#define OUT_CLAMP_CONTROL_G_Y__OUT_CLAMP_MIN_G_Y__SHIFT 0x10
+#define OUT_CLAMP_CONTROL_B_CB__OUT_CLAMP_MAX_B_CB_MASK 0x3fff
+#define OUT_CLAMP_CONTROL_B_CB__OUT_CLAMP_MAX_B_CB__SHIFT 0x0
+#define OUT_CLAMP_CONTROL_B_CB__OUT_CLAMP_MIN_B_CB_MASK 0x3fff0000
+#define OUT_CLAMP_CONTROL_B_CB__OUT_CLAMP_MIN_B_CB__SHIFT 0x10
+#define KEY_CONTROL__KEY_MODE_MASK 0x6
+#define KEY_CONTROL__KEY_MODE__SHIFT 0x1
+#define KEY_RANGE_ALPHA__KEY_ALPHA_LOW_MASK 0xffff
+#define KEY_RANGE_ALPHA__KEY_ALPHA_LOW__SHIFT 0x0
+#define KEY_RANGE_ALPHA__KEY_ALPHA_HIGH_MASK 0xffff0000
+#define KEY_RANGE_ALPHA__KEY_ALPHA_HIGH__SHIFT 0x10
+#define KEY_RANGE_RED__KEY_RED_LOW_MASK 0xffff
+#define KEY_RANGE_RED__KEY_RED_LOW__SHIFT 0x0
+#define KEY_RANGE_RED__KEY_RED_HIGH_MASK 0xffff0000
+#define KEY_RANGE_RED__KEY_RED_HIGH__SHIFT 0x10
+#define KEY_RANGE_GREEN__KEY_GREEN_LOW_MASK 0xffff
+#define KEY_RANGE_GREEN__KEY_GREEN_LOW__SHIFT 0x0
+#define KEY_RANGE_GREEN__KEY_GREEN_HIGH_MASK 0xffff0000
+#define KEY_RANGE_GREEN__KEY_GREEN_HIGH__SHIFT 0x10
+#define KEY_RANGE_BLUE__KEY_BLUE_LOW_MASK 0xffff
+#define KEY_RANGE_BLUE__KEY_BLUE_LOW__SHIFT 0x0
+#define KEY_RANGE_BLUE__KEY_BLUE_HIGH_MASK 0xffff0000
+#define KEY_RANGE_BLUE__KEY_BLUE_HIGH__SHIFT 0x10
+#define DEGAMMA_CONTROL__GRPH_DEGAMMA_MODE_MASK 0x3
+#define DEGAMMA_CONTROL__GRPH_DEGAMMA_MODE__SHIFT 0x0
+#define DEGAMMA_CONTROL__CURSOR2_DEGAMMA_MODE_MASK 0x300
+#define DEGAMMA_CONTROL__CURSOR2_DEGAMMA_MODE__SHIFT 0x8
+#define DEGAMMA_CONTROL__CURSOR_DEGAMMA_MODE_MASK 0x3000
+#define DEGAMMA_CONTROL__CURSOR_DEGAMMA_MODE__SHIFT 0xc
+#define GAMUT_REMAP_CONTROL__GRPH_GAMUT_REMAP_MODE_MASK 0x3
+#define GAMUT_REMAP_CONTROL__GRPH_GAMUT_REMAP_MODE__SHIFT 0x0
+#define GAMUT_REMAP_C11_C12__GAMUT_REMAP_C11_MASK 0xffff
+#define GAMUT_REMAP_C11_C12__GAMUT_REMAP_C11__SHIFT 0x0
+#define GAMUT_REMAP_C11_C12__GAMUT_REMAP_C12_MASK 0xffff0000
+#define GAMUT_REMAP_C11_C12__GAMUT_REMAP_C12__SHIFT 0x10
+#define GAMUT_REMAP_C13_C14__GAMUT_REMAP_C13_MASK 0xffff
+#define GAMUT_REMAP_C13_C14__GAMUT_REMAP_C13__SHIFT 0x0
+#define GAMUT_REMAP_C13_C14__GAMUT_REMAP_C14_MASK 0xffff0000
+#define GAMUT_REMAP_C13_C14__GAMUT_REMAP_C14__SHIFT 0x10
+#define GAMUT_REMAP_C21_C22__GAMUT_REMAP_C21_MASK 0xffff
+#define GAMUT_REMAP_C21_C22__GAMUT_REMAP_C21__SHIFT 0x0
+#define GAMUT_REMAP_C21_C22__GAMUT_REMAP_C22_MASK 0xffff0000
+#define GAMUT_REMAP_C21_C22__GAMUT_REMAP_C22__SHIFT 0x10
+#define GAMUT_REMAP_C23_C24__GAMUT_REMAP_C23_MASK 0xffff
+#define GAMUT_REMAP_C23_C24__GAMUT_REMAP_C23__SHIFT 0x0
+#define GAMUT_REMAP_C23_C24__GAMUT_REMAP_C24_MASK 0xffff0000
+#define GAMUT_REMAP_C23_C24__GAMUT_REMAP_C24__SHIFT 0x10
+#define GAMUT_REMAP_C31_C32__GAMUT_REMAP_C31_MASK 0xffff
+#define GAMUT_REMAP_C31_C32__GAMUT_REMAP_C31__SHIFT 0x0
+#define GAMUT_REMAP_C31_C32__GAMUT_REMAP_C32_MASK 0xffff0000
+#define GAMUT_REMAP_C31_C32__GAMUT_REMAP_C32__SHIFT 0x10
+#define GAMUT_REMAP_C33_C34__GAMUT_REMAP_C33_MASK 0xffff
+#define GAMUT_REMAP_C33_C34__GAMUT_REMAP_C33__SHIFT 0x0
+#define GAMUT_REMAP_C33_C34__GAMUT_REMAP_C34_MASK 0xffff0000
+#define GAMUT_REMAP_C33_C34__GAMUT_REMAP_C34__SHIFT 0x10
+#define DCP_SPATIAL_DITHER_CNTL__DCP_SPATIAL_DITHER_EN_MASK 0x1
+#define DCP_SPATIAL_DITHER_CNTL__DCP_SPATIAL_DITHER_EN__SHIFT 0x0
+#define DCP_SPATIAL_DITHER_CNTL__DCP_SPATIAL_DITHER_MODE_MASK 0x30
+#define DCP_SPATIAL_DITHER_CNTL__DCP_SPATIAL_DITHER_MODE__SHIFT 0x4
+#define DCP_SPATIAL_DITHER_CNTL__DCP_SPATIAL_DITHER_DEPTH_MASK 0xc0
+#define DCP_SPATIAL_DITHER_CNTL__DCP_SPATIAL_DITHER_DEPTH__SHIFT 0x6
+#define DCP_SPATIAL_DITHER_CNTL__DCP_FRAME_RANDOM_ENABLE_MASK 0x100
+#define DCP_SPATIAL_DITHER_CNTL__DCP_FRAME_RANDOM_ENABLE__SHIFT 0x8
+#define DCP_SPATIAL_DITHER_CNTL__DCP_RGB_RANDOM_ENABLE_MASK 0x200
+#define DCP_SPATIAL_DITHER_CNTL__DCP_RGB_RANDOM_ENABLE__SHIFT 0x9
+#define DCP_SPATIAL_DITHER_CNTL__DCP_HIGHPASS_RANDOM_ENABLE_MASK 0x400
+#define DCP_SPATIAL_DITHER_CNTL__DCP_HIGHPASS_RANDOM_ENABLE__SHIFT 0xa
+#define DCP_RANDOM_SEEDS__DCP_RAND_R_SEED_MASK 0xff
+#define DCP_RANDOM_SEEDS__DCP_RAND_R_SEED__SHIFT 0x0
+#define DCP_RANDOM_SEEDS__DCP_RAND_G_SEED_MASK 0xff00
+#define DCP_RANDOM_SEEDS__DCP_RAND_G_SEED__SHIFT 0x8
+#define DCP_RANDOM_SEEDS__DCP_RAND_B_SEED_MASK 0xff0000
+#define DCP_RANDOM_SEEDS__DCP_RAND_B_SEED__SHIFT 0x10
+#define DCP_FP_CONVERTED_FIELD__DCP_FP_CONVERTED_FIELD_DATA_MASK 0x3ffff
+#define DCP_FP_CONVERTED_FIELD__DCP_FP_CONVERTED_FIELD_DATA__SHIFT 0x0
+#define DCP_FP_CONVERTED_FIELD__DCP_FP_CONVERTED_FIELD_INDEX_MASK 0x7f00000
+#define DCP_FP_CONVERTED_FIELD__DCP_FP_CONVERTED_FIELD_INDEX__SHIFT 0x14
+#define CUR_CONTROL__CURSOR_EN_MASK 0x1
+#define CUR_CONTROL__CURSOR_EN__SHIFT 0x0
+#define CUR_CONTROL__CUR_INV_TRANS_CLAMP_MASK 0x10
+#define CUR_CONTROL__CUR_INV_TRANS_CLAMP__SHIFT 0x4
+#define CUR_CONTROL__CURSOR_MODE_MASK 0x300
+#define CUR_CONTROL__CURSOR_MODE__SHIFT 0x8
+#define CUR_CONTROL__CURSOR_BUSY_START_LINE_POSITION_MASK 0xf000
+#define CUR_CONTROL__CURSOR_BUSY_START_LINE_POSITION__SHIFT 0xc
+#define CUR_CONTROL__CURSOR_2X_MAGNIFY_MASK 0x10000
+#define CUR_CONTROL__CURSOR_2X_MAGNIFY__SHIFT 0x10
+#define CUR_CONTROL__CURSOR_FORCE_MC_ON_MASK 0x100000
+#define CUR_CONTROL__CURSOR_FORCE_MC_ON__SHIFT 0x14
+#define CUR_CONTROL__CURSOR_URGENT_CONTROL_MASK 0x7000000
+#define CUR_CONTROL__CURSOR_URGENT_CONTROL__SHIFT 0x18
+#define CUR_SURFACE_ADDRESS__CURSOR_SURFACE_ADDRESS_MASK 0xffffffff
+#define CUR_SURFACE_ADDRESS__CURSOR_SURFACE_ADDRESS__SHIFT 0x0
+#define CUR_SIZE__CURSOR_HEIGHT_MASK 0x7f
+#define CUR_SIZE__CURSOR_HEIGHT__SHIFT 0x0
+#define CUR_SIZE__CURSOR_WIDTH_MASK 0x7f0000
+#define CUR_SIZE__CURSOR_WIDTH__SHIFT 0x10
+#define CUR_SURFACE_ADDRESS_HIGH__CURSOR_SURFACE_ADDRESS_HIGH_MASK 0xff
+#define CUR_SURFACE_ADDRESS_HIGH__CURSOR_SURFACE_ADDRESS_HIGH__SHIFT 0x0
+#define CUR_POSITION__CURSOR_Y_POSITION_MASK 0x3fff
+#define CUR_POSITION__CURSOR_Y_POSITION__SHIFT 0x0
+#define CUR_POSITION__CURSOR_X_POSITION_MASK 0x3fff0000
+#define CUR_POSITION__CURSOR_X_POSITION__SHIFT 0x10
+#define CUR_HOT_SPOT__CURSOR_HOT_SPOT_Y_MASK 0x7f
+#define CUR_HOT_SPOT__CURSOR_HOT_SPOT_Y__SHIFT 0x0
+#define CUR_HOT_SPOT__CURSOR_HOT_SPOT_X_MASK 0x7f0000
+#define CUR_HOT_SPOT__CURSOR_HOT_SPOT_X__SHIFT 0x10
+#define CUR_COLOR1__CUR_COLOR1_BLUE_MASK 0xff
+#define CUR_COLOR1__CUR_COLOR1_BLUE__SHIFT 0x0
+#define CUR_COLOR1__CUR_COLOR1_GREEN_MASK 0xff00
+#define CUR_COLOR1__CUR_COLOR1_GREEN__SHIFT 0x8
+#define CUR_COLOR1__CUR_COLOR1_RED_MASK 0xff0000
+#define CUR_COLOR1__CUR_COLOR1_RED__SHIFT 0x10
+#define CUR_COLOR2__CUR_COLOR2_BLUE_MASK 0xff
+#define CUR_COLOR2__CUR_COLOR2_BLUE__SHIFT 0x0
+#define CUR_COLOR2__CUR_COLOR2_GREEN_MASK 0xff00
+#define CUR_COLOR2__CUR_COLOR2_GREEN__SHIFT 0x8
+#define CUR_COLOR2__CUR_COLOR2_RED_MASK 0xff0000
+#define CUR_COLOR2__CUR_COLOR2_RED__SHIFT 0x10
+#define CUR_UPDATE__CURSOR_UPDATE_PENDING_MASK 0x1
+#define CUR_UPDATE__CURSOR_UPDATE_PENDING__SHIFT 0x0
+#define CUR_UPDATE__CURSOR_UPDATE_TAKEN_MASK 0x2
+#define CUR_UPDATE__CURSOR_UPDATE_TAKEN__SHIFT 0x1
+#define CUR_UPDATE__CURSOR_UPDATE_LOCK_MASK 0x10000
+#define CUR_UPDATE__CURSOR_UPDATE_LOCK__SHIFT 0x10
+#define CUR_UPDATE__CURSOR_DISABLE_MULTIPLE_UPDATE_MASK 0x1000000
+#define CUR_UPDATE__CURSOR_DISABLE_MULTIPLE_UPDATE__SHIFT 0x18
+#define CUR_UPDATE__CURSOR_UPDATE_STEREO_MODE_MASK 0x6000000
+#define CUR_UPDATE__CURSOR_UPDATE_STEREO_MODE__SHIFT 0x19
+#define CUR_REQUEST_FILTER_CNTL__CUR_REQUEST_FILTER_DIS_MASK 0x1
+#define CUR_REQUEST_FILTER_CNTL__CUR_REQUEST_FILTER_DIS__SHIFT 0x0
+#define CUR_STEREO_CONTROL__CURSOR_STEREO_EN_MASK 0x1
+#define CUR_STEREO_CONTROL__CURSOR_STEREO_EN__SHIFT 0x0
+#define CUR_STEREO_CONTROL__CURSOR_STEREO_OFFSET_YNX_MASK 0x2
+#define CUR_STEREO_CONTROL__CURSOR_STEREO_OFFSET_YNX__SHIFT 0x1
+#define CUR_STEREO_CONTROL__CURSOR_PRIMARY_OFFSET_MASK 0x3ff0
+#define CUR_STEREO_CONTROL__CURSOR_PRIMARY_OFFSET__SHIFT 0x4
+#define CUR_STEREO_CONTROL__CURSOR_SECONDARY_OFFSET_MASK 0x3ff0000
+#define CUR_STEREO_CONTROL__CURSOR_SECONDARY_OFFSET__SHIFT 0x10
+#define DC_LUT_RW_MODE__DC_LUT_RW_MODE_MASK 0x1
+#define DC_LUT_RW_MODE__DC_LUT_RW_MODE__SHIFT 0x0
+#define DC_LUT_RW_MODE__DC_LUT_ERROR_MASK 0x10000
+#define DC_LUT_RW_MODE__DC_LUT_ERROR__SHIFT 0x10
+#define DC_LUT_RW_MODE__DC_LUT_ERROR_RST_MASK 0x20000
+#define DC_LUT_RW_MODE__DC_LUT_ERROR_RST__SHIFT 0x11
+#define DC_LUT_RW_INDEX__DC_LUT_RW_INDEX_MASK 0xff
+#define DC_LUT_RW_INDEX__DC_LUT_RW_INDEX__SHIFT 0x0
+#define DC_LUT_SEQ_COLOR__DC_LUT_SEQ_COLOR_MASK 0xffff
+#define DC_LUT_SEQ_COLOR__DC_LUT_SEQ_COLOR__SHIFT 0x0
+#define DC_LUT_PWL_DATA__DC_LUT_BASE_MASK 0xffff
+#define DC_LUT_PWL_DATA__DC_LUT_BASE__SHIFT 0x0
+#define DC_LUT_PWL_DATA__DC_LUT_DELTA_MASK 0xffff0000
+#define DC_LUT_PWL_DATA__DC_LUT_DELTA__SHIFT 0x10
+#define DC_LUT_30_COLOR__DC_LUT_COLOR_10_BLUE_MASK 0x3ff
+#define DC_LUT_30_COLOR__DC_LUT_COLOR_10_BLUE__SHIFT 0x0
+#define DC_LUT_30_COLOR__DC_LUT_COLOR_10_GREEN_MASK 0xffc00
+#define DC_LUT_30_COLOR__DC_LUT_COLOR_10_GREEN__SHIFT 0xa
+#define DC_LUT_30_COLOR__DC_LUT_COLOR_10_RED_MASK 0x3ff00000
+#define DC_LUT_30_COLOR__DC_LUT_COLOR_10_RED__SHIFT 0x14
+#define DC_LUT_VGA_ACCESS_ENABLE__DC_LUT_VGA_ACCESS_ENABLE_MASK 0x1
+#define DC_LUT_VGA_ACCESS_ENABLE__DC_LUT_VGA_ACCESS_ENABLE__SHIFT 0x0
+#define DC_LUT_WRITE_EN_MASK__DC_LUT_WRITE_EN_MASK_MASK 0x7
+#define DC_LUT_WRITE_EN_MASK__DC_LUT_WRITE_EN_MASK__SHIFT 0x0
+#define DC_LUT_AUTOFILL__DC_LUT_AUTOFILL_MASK 0x1
+#define DC_LUT_AUTOFILL__DC_LUT_AUTOFILL__SHIFT 0x0
+#define DC_LUT_AUTOFILL__DC_LUT_AUTOFILL_DONE_MASK 0x2
+#define DC_LUT_AUTOFILL__DC_LUT_AUTOFILL_DONE__SHIFT 0x1
+#define DC_LUT_CONTROL__DC_LUT_INC_B_MASK 0xf
+#define DC_LUT_CONTROL__DC_LUT_INC_B__SHIFT 0x0
+#define DC_LUT_CONTROL__DC_LUT_DATA_B_SIGNED_EN_MASK 0x10
+#define DC_LUT_CONTROL__DC_LUT_DATA_B_SIGNED_EN__SHIFT 0x4
+#define DC_LUT_CONTROL__DC_LUT_DATA_B_FLOAT_POINT_EN_MASK 0x20
+#define DC_LUT_CONTROL__DC_LUT_DATA_B_FLOAT_POINT_EN__SHIFT 0x5
+#define DC_LUT_CONTROL__DC_LUT_DATA_B_FORMAT_MASK 0xc0
+#define DC_LUT_CONTROL__DC_LUT_DATA_B_FORMAT__SHIFT 0x6
+#define DC_LUT_CONTROL__DC_LUT_INC_G_MASK 0xf00
+#define DC_LUT_CONTROL__DC_LUT_INC_G__SHIFT 0x8
+#define DC_LUT_CONTROL__DC_LUT_DATA_G_SIGNED_EN_MASK 0x1000
+#define DC_LUT_CONTROL__DC_LUT_DATA_G_SIGNED_EN__SHIFT 0xc
+#define DC_LUT_CONTROL__DC_LUT_DATA_G_FLOAT_POINT_EN_MASK 0x2000
+#define DC_LUT_CONTROL__DC_LUT_DATA_G_FLOAT_POINT_EN__SHIFT 0xd
+#define DC_LUT_CONTROL__DC_LUT_DATA_G_FORMAT_MASK 0xc000
+#define DC_LUT_CONTROL__DC_LUT_DATA_G_FORMAT__SHIFT 0xe
+#define DC_LUT_CONTROL__DC_LUT_INC_R_MASK 0xf0000
+#define DC_LUT_CONTROL__DC_LUT_INC_R__SHIFT 0x10
+#define DC_LUT_CONTROL__DC_LUT_DATA_R_SIGNED_EN_MASK 0x100000
+#define DC_LUT_CONTROL__DC_LUT_DATA_R_SIGNED_EN__SHIFT 0x14
+#define DC_LUT_CONTROL__DC_LUT_DATA_R_FLOAT_POINT_EN_MASK 0x200000
+#define DC_LUT_CONTROL__DC_LUT_DATA_R_FLOAT_POINT_EN__SHIFT 0x15
+#define DC_LUT_CONTROL__DC_LUT_DATA_R_FORMAT_MASK 0xc00000
+#define DC_LUT_CONTROL__DC_LUT_DATA_R_FORMAT__SHIFT 0x16
+#define DC_LUT_BLACK_OFFSET_BLUE__DC_LUT_BLACK_OFFSET_BLUE_MASK 0xffff
+#define DC_LUT_BLACK_OFFSET_BLUE__DC_LUT_BLACK_OFFSET_BLUE__SHIFT 0x0
+#define DC_LUT_BLACK_OFFSET_GREEN__DC_LUT_BLACK_OFFSET_GREEN_MASK 0xffff
+#define DC_LUT_BLACK_OFFSET_GREEN__DC_LUT_BLACK_OFFSET_GREEN__SHIFT 0x0
+#define DC_LUT_BLACK_OFFSET_RED__DC_LUT_BLACK_OFFSET_RED_MASK 0xffff
+#define DC_LUT_BLACK_OFFSET_RED__DC_LUT_BLACK_OFFSET_RED__SHIFT 0x0
+#define DC_LUT_WHITE_OFFSET_BLUE__DC_LUT_WHITE_OFFSET_BLUE_MASK 0xffff
+#define DC_LUT_WHITE_OFFSET_BLUE__DC_LUT_WHITE_OFFSET_BLUE__SHIFT 0x0
+#define DC_LUT_WHITE_OFFSET_GREEN__DC_LUT_WHITE_OFFSET_GREEN_MASK 0xffff
+#define DC_LUT_WHITE_OFFSET_GREEN__DC_LUT_WHITE_OFFSET_GREEN__SHIFT 0x0
+#define DC_LUT_WHITE_OFFSET_RED__DC_LUT_WHITE_OFFSET_RED_MASK 0xffff
+#define DC_LUT_WHITE_OFFSET_RED__DC_LUT_WHITE_OFFSET_RED__SHIFT 0x0
+#define DCP_CRC_CONTROL__DCP_CRC_ENABLE_MASK 0x1
+#define DCP_CRC_CONTROL__DCP_CRC_ENABLE__SHIFT 0x0
+#define DCP_CRC_CONTROL__DCP_CRC_SOURCE_SEL_MASK 0x1c
+#define DCP_CRC_CONTROL__DCP_CRC_SOURCE_SEL__SHIFT 0x2
+#define DCP_CRC_CONTROL__DCP_CRC_LINE_SEL_MASK 0x300
+#define DCP_CRC_CONTROL__DCP_CRC_LINE_SEL__SHIFT 0x8
+#define DCP_CRC_MASK__DCP_CRC_MASK_MASK 0xffffffff
+#define DCP_CRC_MASK__DCP_CRC_MASK__SHIFT 0x0
+#define DCP_CRC_CURRENT__DCP_CRC_CURRENT_MASK 0xffffffff
+#define DCP_CRC_CURRENT__DCP_CRC_CURRENT__SHIFT 0x0
+#define DVMM_PTE_CONTROL__DVMM_USE_SINGLE_PTE_MASK 0x1
+#define DVMM_PTE_CONTROL__DVMM_USE_SINGLE_PTE__SHIFT 0x0
+#define DVMM_PTE_CONTROL__DVMM_PAGE_WIDTH_MASK 0x1e
+#define DVMM_PTE_CONTROL__DVMM_PAGE_WIDTH__SHIFT 0x1
+#define DVMM_PTE_CONTROL__DVMM_PAGE_HEIGHT_MASK 0x1e0
+#define DVMM_PTE_CONTROL__DVMM_PAGE_HEIGHT__SHIFT 0x5
+#define DVMM_PTE_CONTROL__DVMM_MIN_PTE_BEFORE_FLIP_MASK 0x7fe00
+#define DVMM_PTE_CONTROL__DVMM_MIN_PTE_BEFORE_FLIP__SHIFT 0x9
+#define DVMM_PTE_CONTROL__DVMM_PTE_BUFFER_MODE0_MASK 0x100000
+#define DVMM_PTE_CONTROL__DVMM_PTE_BUFFER_MODE0__SHIFT 0x14
+#define DVMM_PTE_CONTROL__DVMM_PTE_BUFFER_MODE1_MASK 0x200000
+#define DVMM_PTE_CONTROL__DVMM_PTE_BUFFER_MODE1__SHIFT 0x15
+#define DCP_CRC_LAST__DCP_CRC_LAST_MASK 0xffffffff
+#define DCP_CRC_LAST__DCP_CRC_LAST__SHIFT 0x0
+#define DCP_DEBUG__DCP_DEBUG_MASK 0xffffffff
+#define DCP_DEBUG__DCP_DEBUG__SHIFT 0x0
+#define GRPH_FLIP_RATE_CNTL__GRPH_FLIP_RATE_MASK 0x7
+#define GRPH_FLIP_RATE_CNTL__GRPH_FLIP_RATE__SHIFT 0x0
+#define GRPH_FLIP_RATE_CNTL__GRPH_FLIP_RATE_ENABLE_MASK 0x8
+#define GRPH_FLIP_RATE_CNTL__GRPH_FLIP_RATE_ENABLE__SHIFT 0x3
+#define DCP_GSL_CONTROL__DCP_GSL0_EN_MASK 0x1
+#define DCP_GSL_CONTROL__DCP_GSL0_EN__SHIFT 0x0
+#define DCP_GSL_CONTROL__DCP_GSL1_EN_MASK 0x2
+#define DCP_GSL_CONTROL__DCP_GSL1_EN__SHIFT 0x1
+#define DCP_GSL_CONTROL__DCP_GSL2_EN_MASK 0x4
+#define DCP_GSL_CONTROL__DCP_GSL2_EN__SHIFT 0x2
+#define DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_FORCE_DELAY_MASK 0xf000
+#define DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_FORCE_DELAY__SHIFT 0xc
+#define DCP_GSL_CONTROL__DCP_GSL_MASTER_EN_MASK 0x10000
+#define DCP_GSL_CONTROL__DCP_GSL_MASTER_EN__SHIFT 0x10
+#define DCP_GSL_CONTROL__DCP_GSL_XDMA_GROUP_MASK 0x60000
+#define DCP_GSL_CONTROL__DCP_GSL_XDMA_GROUP__SHIFT 0x11
+#define DCP_GSL_CONTROL__DCP_GSL_XDMA_GROUP_UNDERFLOW_EN_MASK 0x80000
+#define DCP_GSL_CONTROL__DCP_GSL_XDMA_GROUP_UNDERFLOW_EN__SHIFT 0x13
+#define DCP_GSL_CONTROL__DCP_GSL_SYNC_SOURCE_MASK 0x3000000
+#define DCP_GSL_CONTROL__DCP_GSL_SYNC_SOURCE__SHIFT 0x18
+#define DCP_GSL_CONTROL__DCP_GSL_DELAY_SURFACE_UPDATE_PENDING_MASK 0x8000000
+#define DCP_GSL_CONTROL__DCP_GSL_DELAY_SURFACE_UPDATE_PENDING__SHIFT 0x1b
+#define DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_CHECK_DELAY_MASK 0xf0000000
+#define DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_CHECK_DELAY__SHIFT 0x1c
+#define DCP_LB_DATA_GAP_BETWEEN_CHUNK__DCP_LB_GAP_BETWEEN_CHUNK_20BPP_MASK 0xf
+#define DCP_LB_DATA_GAP_BETWEEN_CHUNK__DCP_LB_GAP_BETWEEN_CHUNK_20BPP__SHIFT 0x0
+#define DCP_LB_DATA_GAP_BETWEEN_CHUNK__DCP_LB_GAP_BETWEEN_CHUNK_30BPP_MASK 0x1f0
+#define DCP_LB_DATA_GAP_BETWEEN_CHUNK__DCP_LB_GAP_BETWEEN_CHUNK_30BPP__SHIFT 0x4
+#define DCP_DEBUG_SG__DCP_DEBUG_SG_MASK 0xffffffff
+#define DCP_DEBUG_SG__DCP_DEBUG_SG__SHIFT 0x0
+#define DCP_DEBUG_SG2__DCP_DEBUG_SG2_MASK 0xffffffff
+#define DCP_DEBUG_SG2__DCP_DEBUG_SG2__SHIFT 0x0
+#define DCP_DVMM_DEBUG__DCP_DVMM_DEBUG_MASK 0xffffffff
+#define DCP_DVMM_DEBUG__DCP_DVMM_DEBUG__SHIFT 0x0
+#define DCP_TEST_DEBUG_INDEX__DCP_TEST_DEBUG_INDEX_MASK 0xff
+#define DCP_TEST_DEBUG_INDEX__DCP_TEST_DEBUG_INDEX__SHIFT 0x0
+#define DCP_TEST_DEBUG_INDEX__DCP_TEST_DEBUG_WRITE_EN_MASK 0x100
+#define DCP_TEST_DEBUG_INDEX__DCP_TEST_DEBUG_WRITE_EN__SHIFT 0x8
+#define DCP_TEST_DEBUG_DATA__DCP_TEST_DEBUG_DATA_MASK 0xffffffff
+#define DCP_TEST_DEBUG_DATA__DCP_TEST_DEBUG_DATA__SHIFT 0x0
+#define GRPH_STEREOSYNC_FLIP__GRPH_STEREOSYNC_FLIP_EN_MASK 0x1
+#define GRPH_STEREOSYNC_FLIP__GRPH_STEREOSYNC_FLIP_EN__SHIFT 0x0
+#define GRPH_STEREOSYNC_FLIP__GRPH_STEREOSYNC_FLIP_MODE_MASK 0x300
+#define GRPH_STEREOSYNC_FLIP__GRPH_STEREOSYNC_FLIP_MODE__SHIFT 0x8
+#define GRPH_STEREOSYNC_FLIP__GRPH_PRIMARY_SURFACE_PENDING_MASK 0x10000
+#define GRPH_STEREOSYNC_FLIP__GRPH_PRIMARY_SURFACE_PENDING__SHIFT 0x10
+#define GRPH_STEREOSYNC_FLIP__GRPH_SECONDARY_SURFACE_PENDING_MASK 0x20000
+#define GRPH_STEREOSYNC_FLIP__GRPH_SECONDARY_SURFACE_PENDING__SHIFT 0x11
+#define GRPH_STEREOSYNC_FLIP__GRPH_STEREOSYNC_SELECT_DISABLE_MASK 0x10000000
+#define GRPH_STEREOSYNC_FLIP__GRPH_STEREOSYNC_SELECT_DISABLE__SHIFT 0x1c
+#define DCP_DEBUG2__DCP_DEBUG2_MASK 0xffffffff
+#define DCP_DEBUG2__DCP_DEBUG2__SHIFT 0x0
+#define HW_ROTATION__GRPH_ROTATION_ANGLE_MASK 0x7
+#define HW_ROTATION__GRPH_ROTATION_ANGLE__SHIFT 0x0
+#define GRPH_XDMA_CACHE_UNDERFLOW_DET_CNTL__GRPH_XDMA_CACHE_UNDERFLOW_CNT_EN_MASK 0x1
+#define GRPH_XDMA_CACHE_UNDERFLOW_DET_CNTL__GRPH_XDMA_CACHE_UNDERFLOW_CNT_EN__SHIFT 0x0
+#define GRPH_XDMA_CACHE_UNDERFLOW_DET_CNTL__GRPH_XDMA_CACHE_UNDERFLOW_CNT_MODE_MASK 0x2
+#define GRPH_XDMA_CACHE_UNDERFLOW_DET_CNTL__GRPH_XDMA_CACHE_UNDERFLOW_CNT_MODE__SHIFT 0x1
+#define GRPH_XDMA_CACHE_UNDERFLOW_DET_CNTL__GRPH_XDMA_CACHE_UNDERFLOW_FRAME_CNT_MASK 0x1fff0
+#define GRPH_XDMA_CACHE_UNDERFLOW_DET_CNTL__GRPH_XDMA_CACHE_UNDERFLOW_FRAME_CNT__SHIFT 0x4
+#define REGAMMA_CONTROL__GRPH_REGAMMA_MODE_MASK 0x7
+#define REGAMMA_CONTROL__GRPH_REGAMMA_MODE__SHIFT 0x0
+#define REGAMMA_LUT_INDEX__REGAMMA_LUT_INDEX_MASK 0x1ff
+#define REGAMMA_LUT_INDEX__REGAMMA_LUT_INDEX__SHIFT 0x0
+#define REGAMMA_LUT_DATA__REGAMMA_LUT_DATA_MASK 0x7ffff
+#define REGAMMA_LUT_DATA__REGAMMA_LUT_DATA__SHIFT 0x0
+#define REGAMMA_LUT_WRITE_EN_MASK__REGAMMA_LUT_WRITE_EN_MASK_MASK 0x7
+#define REGAMMA_LUT_WRITE_EN_MASK__REGAMMA_LUT_WRITE_EN_MASK__SHIFT 0x0
+#define REGAMMA_CNTLA_START_CNTL__REGAMMA_CNTLA_EXP_REGION_START_MASK 0x3ffff
+#define REGAMMA_CNTLA_START_CNTL__REGAMMA_CNTLA_EXP_REGION_START__SHIFT 0x0
+#define REGAMMA_CNTLA_START_CNTL__REGAMMA_CNTLA_EXP_REGION_START_SEGMENT_MASK 0x7f00000
+#define REGAMMA_CNTLA_START_CNTL__REGAMMA_CNTLA_EXP_REGION_START_SEGMENT__SHIFT 0x14
+#define REGAMMA_CNTLA_SLOPE_CNTL__REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE_MASK 0x3ffff
+#define REGAMMA_CNTLA_SLOPE_CNTL__REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE__SHIFT 0x0
+#define REGAMMA_CNTLA_END_CNTL1__REGAMMA_CNTLA_EXP_REGION_END_MASK 0xffff
+#define REGAMMA_CNTLA_END_CNTL1__REGAMMA_CNTLA_EXP_REGION_END__SHIFT 0x0
+#define REGAMMA_CNTLA_END_CNTL2__REGAMMA_CNTLA_EXP_REGION_END_SLOPE_MASK 0xffff
+#define REGAMMA_CNTLA_END_CNTL2__REGAMMA_CNTLA_EXP_REGION_END_SLOPE__SHIFT 0x0
+#define REGAMMA_CNTLA_END_CNTL2__REGAMMA_CNTLA_EXP_REGION_END_BASE_MASK 0xffff0000
+#define REGAMMA_CNTLA_END_CNTL2__REGAMMA_CNTLA_EXP_REGION_END_BASE__SHIFT 0x10
+#define REGAMMA_CNTLA_REGION_0_1__REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET_MASK 0x1ff
+#define REGAMMA_CNTLA_REGION_0_1__REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET__SHIFT 0x0
+#define REGAMMA_CNTLA_REGION_0_1__REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS_MASK 0x7000
+#define REGAMMA_CNTLA_REGION_0_1__REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS__SHIFT 0xc
+#define REGAMMA_CNTLA_REGION_0_1__REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET_MASK 0x1ff0000
+#define REGAMMA_CNTLA_REGION_0_1__REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET__SHIFT 0x10
+#define REGAMMA_CNTLA_REGION_0_1__REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS_MASK 0x70000000
+#define REGAMMA_CNTLA_REGION_0_1__REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS__SHIFT 0x1c
+#define REGAMMA_CNTLA_REGION_2_3__REGAMMA_CNTLA_EXP_REGION2_LUT_OFFSET_MASK 0x1ff
+#define REGAMMA_CNTLA_REGION_2_3__REGAMMA_CNTLA_EXP_REGION2_LUT_OFFSET__SHIFT 0x0
+#define REGAMMA_CNTLA_REGION_2_3__REGAMMA_CNTLA_EXP_REGION2_NUM_SEGMENTS_MASK 0x7000
+#define REGAMMA_CNTLA_REGION_2_3__REGAMMA_CNTLA_EXP_REGION2_NUM_SEGMENTS__SHIFT 0xc
+#define REGAMMA_CNTLA_REGION_2_3__REGAMMA_CNTLA_EXP_REGION3_LUT_OFFSET_MASK 0x1ff0000
+#define REGAMMA_CNTLA_REGION_2_3__REGAMMA_CNTLA_EXP_REGION3_LUT_OFFSET__SHIFT 0x10
+#define REGAMMA_CNTLA_REGION_2_3__REGAMMA_CNTLA_EXP_REGION3_NUM_SEGMENTS_MASK 0x70000000
+#define REGAMMA_CNTLA_REGION_2_3__REGAMMA_CNTLA_EXP_REGION3_NUM_SEGMENTS__SHIFT 0x1c
+#define REGAMMA_CNTLA_REGION_4_5__REGAMMA_CNTLA_EXP_REGION4_LUT_OFFSET_MASK 0x1ff
+#define REGAMMA_CNTLA_REGION_4_5__REGAMMA_CNTLA_EXP_REGION4_LUT_OFFSET__SHIFT 0x0
+#define REGAMMA_CNTLA_REGION_4_5__REGAMMA_CNTLA_EXP_REGION4_NUM_SEGMENTS_MASK 0x7000
+#define REGAMMA_CNTLA_REGION_4_5__REGAMMA_CNTLA_EXP_REGION4_NUM_SEGMENTS__SHIFT 0xc
+#define REGAMMA_CNTLA_REGION_4_5__REGAMMA_CNTLA_EXP_REGION5_LUT_OFFSET_MASK 0x1ff0000
+#define REGAMMA_CNTLA_REGION_4_5__REGAMMA_CNTLA_EXP_REGION5_LUT_OFFSET__SHIFT 0x10
+#define REGAMMA_CNTLA_REGION_4_5__REGAMMA_CNTLA_EXP_REGION5_NUM_SEGMENTS_MASK 0x70000000
+#define REGAMMA_CNTLA_REGION_4_5__REGAMMA_CNTLA_EXP_REGION5_NUM_SEGMENTS__SHIFT 0x1c
+#define REGAMMA_CNTLA_REGION_6_7__REGAMMA_CNTLA_EXP_REGION6_LUT_OFFSET_MASK 0x1ff
+#define REGAMMA_CNTLA_REGION_6_7__REGAMMA_CNTLA_EXP_REGION6_LUT_OFFSET__SHIFT 0x0
+#define REGAMMA_CNTLA_REGION_6_7__REGAMMA_CNTLA_EXP_REGION6_NUM_SEGMENTS_MASK 0x7000
+#define REGAMMA_CNTLA_REGION_6_7__REGAMMA_CNTLA_EXP_REGION6_NUM_SEGMENTS__SHIFT 0xc
+#define REGAMMA_CNTLA_REGION_6_7__REGAMMA_CNTLA_EXP_REGION7_LUT_OFFSET_MASK 0x1ff0000
+#define REGAMMA_CNTLA_REGION_6_7__REGAMMA_CNTLA_EXP_REGION7_LUT_OFFSET__SHIFT 0x10
+#define REGAMMA_CNTLA_REGION_6_7__REGAMMA_CNTLA_EXP_REGION7_NUM_SEGMENTS_MASK 0x70000000
+#define REGAMMA_CNTLA_REGION_6_7__REGAMMA_CNTLA_EXP_REGION7_NUM_SEGMENTS__SHIFT 0x1c
+#define REGAMMA_CNTLA_REGION_8_9__REGAMMA_CNTLA_EXP_REGION8_LUT_OFFSET_MASK 0x1ff
+#define REGAMMA_CNTLA_REGION_8_9__REGAMMA_CNTLA_EXP_REGION8_LUT_OFFSET__SHIFT 0x0
+#define REGAMMA_CNTLA_REGION_8_9__REGAMMA_CNTLA_EXP_REGION8_NUM_SEGMENTS_MASK 0x7000
+#define REGAMMA_CNTLA_REGION_8_9__REGAMMA_CNTLA_EXP_REGION8_NUM_SEGMENTS__SHIFT 0xc
+#define REGAMMA_CNTLA_REGION_8_9__REGAMMA_CNTLA_EXP_REGION9_LUT_OFFSET_MASK 0x1ff0000
+#define REGAMMA_CNTLA_REGION_8_9__REGAMMA_CNTLA_EXP_REGION9_LUT_OFFSET__SHIFT 0x10
+#define REGAMMA_CNTLA_REGION_8_9__REGAMMA_CNTLA_EXP_REGION9_NUM_SEGMENTS_MASK 0x70000000
+#define REGAMMA_CNTLA_REGION_8_9__REGAMMA_CNTLA_EXP_REGION9_NUM_SEGMENTS__SHIFT 0x1c
+#define REGAMMA_CNTLA_REGION_10_11__REGAMMA_CNTLA_EXP_REGION10_LUT_OFFSET_MASK 0x1ff
+#define REGAMMA_CNTLA_REGION_10_11__REGAMMA_CNTLA_EXP_REGION10_LUT_OFFSET__SHIFT 0x0
+#define REGAMMA_CNTLA_REGION_10_11__REGAMMA_CNTLA_EXP_REGION10_NUM_SEGMENTS_MASK 0x7000
+#define REGAMMA_CNTLA_REGION_10_11__REGAMMA_CNTLA_EXP_REGION10_NUM_SEGMENTS__SHIFT 0xc
+#define REGAMMA_CNTLA_REGION_10_11__REGAMMA_CNTLA_EXP_REGION11_LUT_OFFSET_MASK 0x1ff0000
+#define REGAMMA_CNTLA_REGION_10_11__REGAMMA_CNTLA_EXP_REGION11_LUT_OFFSET__SHIFT 0x10
+#define REGAMMA_CNTLA_REGION_10_11__REGAMMA_CNTLA_EXP_REGION11_NUM_SEGMENTS_MASK 0x70000000
+#define REGAMMA_CNTLA_REGION_10_11__REGAMMA_CNTLA_EXP_REGION11_NUM_SEGMENTS__SHIFT 0x1c
+#define REGAMMA_CNTLA_REGION_12_13__REGAMMA_CNTLA_EXP_REGION12_LUT_OFFSET_MASK 0x1ff
+#define REGAMMA_CNTLA_REGION_12_13__REGAMMA_CNTLA_EXP_REGION12_LUT_OFFSET__SHIFT 0x0
+#define REGAMMA_CNTLA_REGION_12_13__REGAMMA_CNTLA_EXP_REGION12_NUM_SEGMENTS_MASK 0x7000
+#define REGAMMA_CNTLA_REGION_12_13__REGAMMA_CNTLA_EXP_REGION12_NUM_SEGMENTS__SHIFT 0xc
+#define REGAMMA_CNTLA_REGION_12_13__REGAMMA_CNTLA_EXP_REGION13_LUT_OFFSET_MASK 0x1ff0000
+#define REGAMMA_CNTLA_REGION_12_13__REGAMMA_CNTLA_EXP_REGION13_LUT_OFFSET__SHIFT 0x10
+#define REGAMMA_CNTLA_REGION_12_13__REGAMMA_CNTLA_EXP_REGION13_NUM_SEGMENTS_MASK 0x70000000
+#define REGAMMA_CNTLA_REGION_12_13__REGAMMA_CNTLA_EXP_REGION13_NUM_SEGMENTS__SHIFT 0x1c
+#define REGAMMA_CNTLA_REGION_14_15__REGAMMA_CNTLA_EXP_REGION14_LUT_OFFSET_MASK 0x1ff
+#define REGAMMA_CNTLA_REGION_14_15__REGAMMA_CNTLA_EXP_REGION14_LUT_OFFSET__SHIFT 0x0
+#define REGAMMA_CNTLA_REGION_14_15__REGAMMA_CNTLA_EXP_REGION14_NUM_SEGMENTS_MASK 0x7000
+#define REGAMMA_CNTLA_REGION_14_15__REGAMMA_CNTLA_EXP_REGION14_NUM_SEGMENTS__SHIFT 0xc
+#define REGAMMA_CNTLA_REGION_14_15__REGAMMA_CNTLA_EXP_REGION15_LUT_OFFSET_MASK 0x1ff0000
+#define REGAMMA_CNTLA_REGION_14_15__REGAMMA_CNTLA_EXP_REGION15_LUT_OFFSET__SHIFT 0x10
+#define REGAMMA_CNTLA_REGION_14_15__REGAMMA_CNTLA_EXP_REGION15_NUM_SEGMENTS_MASK 0x70000000
+#define REGAMMA_CNTLA_REGION_14_15__REGAMMA_CNTLA_EXP_REGION15_NUM_SEGMENTS__SHIFT 0x1c
+#define REGAMMA_CNTLB_START_CNTL__REGAMMA_CNTLB_EXP_REGION_START_MASK 0x3ffff
+#define REGAMMA_CNTLB_START_CNTL__REGAMMA_CNTLB_EXP_REGION_START__SHIFT 0x0
+#define REGAMMA_CNTLB_START_CNTL__REGAMMA_CNTLB_EXP_REGION_START_SEGMENT_MASK 0x7f00000
+#define REGAMMA_CNTLB_START_CNTL__REGAMMA_CNTLB_EXP_REGION_START_SEGMENT__SHIFT 0x14
+#define REGAMMA_CNTLB_SLOPE_CNTL__REGAMMA_CNTLB_EXP_REGION_LINEAR_SLOPE_MASK 0x3ffff
+#define REGAMMA_CNTLB_SLOPE_CNTL__REGAMMA_CNTLB_EXP_REGION_LINEAR_SLOPE__SHIFT 0x0
+#define REGAMMA_CNTLB_END_CNTL1__REGAMMA_CNTLB_EXP_REGION_END_MASK 0xffff
+#define REGAMMA_CNTLB_END_CNTL1__REGAMMA_CNTLB_EXP_REGION_END__SHIFT 0x0
+#define REGAMMA_CNTLB_END_CNTL2__REGAMMA_CNTLB_EXP_REGION_END_SLOPE_MASK 0xffff
+#define REGAMMA_CNTLB_END_CNTL2__REGAMMA_CNTLB_EXP_REGION_END_SLOPE__SHIFT 0x0
+#define REGAMMA_CNTLB_END_CNTL2__REGAMMA_CNTLB_EXP_REGION_END_BASE_MASK 0xffff0000
+#define REGAMMA_CNTLB_END_CNTL2__REGAMMA_CNTLB_EXP_REGION_END_BASE__SHIFT 0x10
+#define REGAMMA_CNTLB_REGION_0_1__REGAMMA_CNTLB_EXP_REGION0_LUT_OFFSET_MASK 0x1ff
+#define REGAMMA_CNTLB_REGION_0_1__REGAMMA_CNTLB_EXP_REGION0_LUT_OFFSET__SHIFT 0x0
+#define REGAMMA_CNTLB_REGION_0_1__REGAMMA_CNTLB_EXP_REGION0_NUM_SEGMENTS_MASK 0x7000
+#define REGAMMA_CNTLB_REGION_0_1__REGAMMA_CNTLB_EXP_REGION0_NUM_SEGMENTS__SHIFT 0xc
+#define REGAMMA_CNTLB_REGION_0_1__REGAMMA_CNTLB_EXP_REGION1_LUT_OFFSET_MASK 0x1ff0000
+#define REGAMMA_CNTLB_REGION_0_1__REGAMMA_CNTLB_EXP_REGION1_LUT_OFFSET__SHIFT 0x10
+#define REGAMMA_CNTLB_REGION_0_1__REGAMMA_CNTLB_EXP_REGION1_NUM_SEGMENTS_MASK 0x70000000
+#define REGAMMA_CNTLB_REGION_0_1__REGAMMA_CNTLB_EXP_REGION1_NUM_SEGMENTS__SHIFT 0x1c
+#define REGAMMA_CNTLB_REGION_2_3__REGAMMA_CNTLB_EXP_REGION2_LUT_OFFSET_MASK 0x1ff
+#define REGAMMA_CNTLB_REGION_2_3__REGAMMA_CNTLB_EXP_REGION2_LUT_OFFSET__SHIFT 0x0
+#define REGAMMA_CNTLB_REGION_2_3__REGAMMA_CNTLB_EXP_REGION2_NUM_SEGMENTS_MASK 0x7000
+#define REGAMMA_CNTLB_REGION_2_3__REGAMMA_CNTLB_EXP_REGION2_NUM_SEGMENTS__SHIFT 0xc
+#define REGAMMA_CNTLB_REGION_2_3__REGAMMA_CNTLB_EXP_REGION3_LUT_OFFSET_MASK 0x1ff0000
+#define REGAMMA_CNTLB_REGION_2_3__REGAMMA_CNTLB_EXP_REGION3_LUT_OFFSET__SHIFT 0x10
+#define REGAMMA_CNTLB_REGION_2_3__REGAMMA_CNTLB_EXP_REGION3_NUM_SEGMENTS_MASK 0x70000000
+#define REGAMMA_CNTLB_REGION_2_3__REGAMMA_CNTLB_EXP_REGION3_NUM_SEGMENTS__SHIFT 0x1c
+#define REGAMMA_CNTLB_REGION_4_5__REGAMMA_CNTLB_EXP_REGION4_LUT_OFFSET_MASK 0x1ff
+#define REGAMMA_CNTLB_REGION_4_5__REGAMMA_CNTLB_EXP_REGION4_LUT_OFFSET__SHIFT 0x0
+#define REGAMMA_CNTLB_REGION_4_5__REGAMMA_CNTLB_EXP_REGION4_NUM_SEGMENTS_MASK 0x7000
+#define REGAMMA_CNTLB_REGION_4_5__REGAMMA_CNTLB_EXP_REGION4_NUM_SEGMENTS__SHIFT 0xc
+#define REGAMMA_CNTLB_REGION_4_5__REGAMMA_CNTLB_EXP_REGION5_LUT_OFFSET_MASK 0x1ff0000
+#define REGAMMA_CNTLB_REGION_4_5__REGAMMA_CNTLB_EXP_REGION5_LUT_OFFSET__SHIFT 0x10
+#define REGAMMA_CNTLB_REGION_4_5__REGAMMA_CNTLB_EXP_REGION5_NUM_SEGMENTS_MASK 0x70000000
+#define REGAMMA_CNTLB_REGION_4_5__REGAMMA_CNTLB_EXP_REGION5_NUM_SEGMENTS__SHIFT 0x1c
+#define REGAMMA_CNTLB_REGION_6_7__REGAMMA_CNTLB_EXP_REGION6_LUT_OFFSET_MASK 0x1ff
+#define REGAMMA_CNTLB_REGION_6_7__REGAMMA_CNTLB_EXP_REGION6_LUT_OFFSET__SHIFT 0x0
+#define REGAMMA_CNTLB_REGION_6_7__REGAMMA_CNTLB_EXP_REGION6_NUM_SEGMENTS_MASK 0x7000
+#define REGAMMA_CNTLB_REGION_6_7__REGAMMA_CNTLB_EXP_REGION6_NUM_SEGMENTS__SHIFT 0xc
+#define REGAMMA_CNTLB_REGION_6_7__REGAMMA_CNTLB_EXP_REGION7_LUT_OFFSET_MASK 0x1ff0000
+#define REGAMMA_CNTLB_REGION_6_7__REGAMMA_CNTLB_EXP_REGION7_LUT_OFFSET__SHIFT 0x10
+#define REGAMMA_CNTLB_REGION_6_7__REGAMMA_CNTLB_EXP_REGION7_NUM_SEGMENTS_MASK 0x70000000
+#define REGAMMA_CNTLB_REGION_6_7__REGAMMA_CNTLB_EXP_REGION7_NUM_SEGMENTS__SHIFT 0x1c
+#define REGAMMA_CNTLB_REGION_8_9__REGAMMA_CNTLB_EXP_REGION8_LUT_OFFSET_MASK 0x1ff
+#define REGAMMA_CNTLB_REGION_8_9__REGAMMA_CNTLB_EXP_REGION8_LUT_OFFSET__SHIFT 0x0
+#define REGAMMA_CNTLB_REGION_8_9__REGAMMA_CNTLB_EXP_REGION8_NUM_SEGMENTS_MASK 0x7000
+#define REGAMMA_CNTLB_REGION_8_9__REGAMMA_CNTLB_EXP_REGION8_NUM_SEGMENTS__SHIFT 0xc
+#define REGAMMA_CNTLB_REGION_8_9__REGAMMA_CNTLB_EXP_REGION9_LUT_OFFSET_MASK 0x1ff0000
+#define REGAMMA_CNTLB_REGION_8_9__REGAMMA_CNTLB_EXP_REGION9_LUT_OFFSET__SHIFT 0x10
+#define REGAMMA_CNTLB_REGION_8_9__REGAMMA_CNTLB_EXP_REGION9_NUM_SEGMENTS_MASK 0x70000000
+#define REGAMMA_CNTLB_REGION_8_9__REGAMMA_CNTLB_EXP_REGION9_NUM_SEGMENTS__SHIFT 0x1c
+#define REGAMMA_CNTLB_REGION_10_11__REGAMMA_CNTLB_EXP_REGION10_LUT_OFFSET_MASK 0x1ff
+#define REGAMMA_CNTLB_REGION_10_11__REGAMMA_CNTLB_EXP_REGION10_LUT_OFFSET__SHIFT 0x0
+#define REGAMMA_CNTLB_REGION_10_11__REGAMMA_CNTLB_EXP_REGION10_NUM_SEGMENTS_MASK 0x7000
+#define REGAMMA_CNTLB_REGION_10_11__REGAMMA_CNTLB_EXP_REGION10_NUM_SEGMENTS__SHIFT 0xc
+#define REGAMMA_CNTLB_REGION_10_11__REGAMMA_CNTLB_EXP_REGION11_LUT_OFFSET_MASK 0x1ff0000
+#define REGAMMA_CNTLB_REGION_10_11__REGAMMA_CNTLB_EXP_REGION11_LUT_OFFSET__SHIFT 0x10
+#define REGAMMA_CNTLB_REGION_10_11__REGAMMA_CNTLB_EXP_REGION11_NUM_SEGMENTS_MASK 0x70000000
+#define REGAMMA_CNTLB_REGION_10_11__REGAMMA_CNTLB_EXP_REGION11_NUM_SEGMENTS__SHIFT 0x1c
+#define REGAMMA_CNTLB_REGION_12_13__REGAMMA_CNTLB_EXP_REGION12_LUT_OFFSET_MASK 0x1ff
+#define REGAMMA_CNTLB_REGION_12_13__REGAMMA_CNTLB_EXP_REGION12_LUT_OFFSET__SHIFT 0x0
+#define REGAMMA_CNTLB_REGION_12_13__REGAMMA_CNTLB_EXP_REGION12_NUM_SEGMENTS_MASK 0x7000
+#define REGAMMA_CNTLB_REGION_12_13__REGAMMA_CNTLB_EXP_REGION12_NUM_SEGMENTS__SHIFT 0xc
+#define REGAMMA_CNTLB_REGION_12_13__REGAMMA_CNTLB_EXP_REGION13_LUT_OFFSET_MASK 0x1ff0000
+#define REGAMMA_CNTLB_REGION_12_13__REGAMMA_CNTLB_EXP_REGION13_LUT_OFFSET__SHIFT 0x10
+#define REGAMMA_CNTLB_REGION_12_13__REGAMMA_CNTLB_EXP_REGION13_NUM_SEGMENTS_MASK 0x70000000
+#define REGAMMA_CNTLB_REGION_12_13__REGAMMA_CNTLB_EXP_REGION13_NUM_SEGMENTS__SHIFT 0x1c
+#define REGAMMA_CNTLB_REGION_14_15__REGAMMA_CNTLB_EXP_REGION14_LUT_OFFSET_MASK 0x1ff
+#define REGAMMA_CNTLB_REGION_14_15__REGAMMA_CNTLB_EXP_REGION14_LUT_OFFSET__SHIFT 0x0
+#define REGAMMA_CNTLB_REGION_14_15__REGAMMA_CNTLB_EXP_REGION14_NUM_SEGMENTS_MASK 0x7000
+#define REGAMMA_CNTLB_REGION_14_15__REGAMMA_CNTLB_EXP_REGION14_NUM_SEGMENTS__SHIFT 0xc
+#define REGAMMA_CNTLB_REGION_14_15__REGAMMA_CNTLB_EXP_REGION15_LUT_OFFSET_MASK 0x1ff0000
+#define REGAMMA_CNTLB_REGION_14_15__REGAMMA_CNTLB_EXP_REGION15_LUT_OFFSET__SHIFT 0x10
+#define REGAMMA_CNTLB_REGION_14_15__REGAMMA_CNTLB_EXP_REGION15_NUM_SEGMENTS_MASK 0x70000000
+#define REGAMMA_CNTLB_REGION_14_15__REGAMMA_CNTLB_EXP_REGION15_NUM_SEGMENTS__SHIFT 0x1c
+#define ALPHA_CONTROL__ALPHA_ROUND_TRUNC_MODE_MASK 0x1
+#define ALPHA_CONTROL__ALPHA_ROUND_TRUNC_MODE__SHIFT 0x0
+#define ALPHA_CONTROL__CURSOR_ALPHA_BLND_ENA_MASK 0x2
+#define ALPHA_CONTROL__CURSOR_ALPHA_BLND_ENA__SHIFT 0x1
+#define GRPH_XDMA_RECOVERY_SURFACE_ADDRESS__GRPH_XDMA_RECOVERY_SURFACE_ADDRESS_MASK 0xffffff00
+#define GRPH_XDMA_RECOVERY_SURFACE_ADDRESS__GRPH_XDMA_RECOVERY_SURFACE_ADDRESS__SHIFT 0x8
+#define GRPH_XDMA_RECOVERY_SURFACE_ADDRESS_HIGH__GRPH_XDMA_RECOVERY_SURFACE_ADDRESS_HIGH_MASK 0xff
+#define GRPH_XDMA_RECOVERY_SURFACE_ADDRESS_HIGH__GRPH_XDMA_RECOVERY_SURFACE_ADDRESS_HIGH__SHIFT 0x0
+#define GRPH_XDMA_CACHE_UNDERFLOW_DET_STATUS__GRPH_XDMA_CACHE_UNDERFLOW_CNT_MASK 0xfffff
+#define GRPH_XDMA_CACHE_UNDERFLOW_DET_STATUS__GRPH_XDMA_CACHE_UNDERFLOW_CNT__SHIFT 0x0
+#define GRPH_XDMA_CACHE_UNDERFLOW_DET_STATUS__GRPH_XDMA_CACHE_UNDERFLOW_CNT_STATUS_MASK 0x1000000
+#define GRPH_XDMA_CACHE_UNDERFLOW_DET_STATUS__GRPH_XDMA_CACHE_UNDERFLOW_CNT_STATUS__SHIFT 0x18
+#define GRPH_XDMA_CACHE_UNDERFLOW_DET_STATUS__GRPH_XDMA_CACHE_UNDERFLOW_FRAME_MASK_MASK 0x2000000
+#define GRPH_XDMA_CACHE_UNDERFLOW_DET_STATUS__GRPH_XDMA_CACHE_UNDERFLOW_FRAME_MASK__SHIFT 0x19
+#define GRPH_XDMA_CACHE_UNDERFLOW_DET_STATUS__GRPH_XDMA_CACHE_UNDERFLOW_FRAME_ACK_MASK 0x4000000
+#define GRPH_XDMA_CACHE_UNDERFLOW_DET_STATUS__GRPH_XDMA_CACHE_UNDERFLOW_FRAME_ACK__SHIFT 0x1a
+#define GRPH_XDMA_CACHE_UNDERFLOW_DET_STATUS__GRPH_XDMA_CACHE_UNDERFLOW_INT_MASK 0x10000000
+#define GRPH_XDMA_CACHE_UNDERFLOW_DET_STATUS__GRPH_XDMA_CACHE_UNDERFLOW_INT__SHIFT 0x1c
+#define GRPH_XDMA_CACHE_UNDERFLOW_DET_STATUS__GRPH_XDMA_CACHE_UNDERFLOW_INT_MASK_MASK 0x20000000
+#define GRPH_XDMA_CACHE_UNDERFLOW_DET_STATUS__GRPH_XDMA_CACHE_UNDERFLOW_INT_MASK__SHIFT 0x1d
+#define GRPH_XDMA_CACHE_UNDERFLOW_DET_STATUS__GRPH_XDMA_CACHE_UNDERFLOW_INT_ACK_MASK 0x40000000
+#define GRPH_XDMA_CACHE_UNDERFLOW_DET_STATUS__GRPH_XDMA_CACHE_UNDERFLOW_INT_ACK__SHIFT 0x1e
+#define GRPH_SURFACE_COUNTER_CONTROL__GRPH_SURFACE_COUNTER_EN_MASK 0x1
+#define GRPH_SURFACE_COUNTER_CONTROL__GRPH_SURFACE_COUNTER_EN__SHIFT 0x0
+#define GRPH_SURFACE_COUNTER_CONTROL__GRPH_SURFACE_COUNTER_EVENT_SELECT_MASK 0x1e
+#define GRPH_SURFACE_COUNTER_CONTROL__GRPH_SURFACE_COUNTER_EVENT_SELECT__SHIFT 0x1
+#define GRPH_SURFACE_COUNTER_CONTROL__GRPH_SURFACE_COUNTER_ERR_WRAP_OCCURED_MASK 0x200
+#define GRPH_SURFACE_COUNTER_CONTROL__GRPH_SURFACE_COUNTER_ERR_WRAP_OCCURED__SHIFT 0x9
+#define GRPH_SURFACE_COUNTER_OUTPUT__GRPH_SURFACE_COUNTER_MIN_MASK 0xffff
+#define GRPH_SURFACE_COUNTER_OUTPUT__GRPH_SURFACE_COUNTER_MIN__SHIFT 0x0
+#define GRPH_SURFACE_COUNTER_OUTPUT__GRPH_SURFACE_COUNTER_MAX_MASK 0xffff0000
+#define GRPH_SURFACE_COUNTER_OUTPUT__GRPH_SURFACE_COUNTER_MAX__SHIFT 0x10
+#define DIG_FE_CNTL__DIG_SOURCE_SELECT_MASK 0x7
+#define DIG_FE_CNTL__DIG_SOURCE_SELECT__SHIFT 0x0
+#define DIG_FE_CNTL__DIG_STEREOSYNC_SELECT_MASK 0x70
+#define DIG_FE_CNTL__DIG_STEREOSYNC_SELECT__SHIFT 0x4
+#define DIG_FE_CNTL__DIG_STEREOSYNC_GATE_EN_MASK 0x100
+#define DIG_FE_CNTL__DIG_STEREOSYNC_GATE_EN__SHIFT 0x8
+#define DIG_FE_CNTL__DIG_START_MASK 0x400
+#define DIG_FE_CNTL__DIG_START__SHIFT 0xa
+#define DIG_FE_CNTL__DIG_SYMCLK_FE_ON_MASK 0x1000000
+#define DIG_FE_CNTL__DIG_SYMCLK_FE_ON__SHIFT 0x18
+#define DIG_FE_CNTL__TMDS_PIXEL_ENCODING_MASK 0x10000000
+#define DIG_FE_CNTL__TMDS_PIXEL_ENCODING__SHIFT 0x1c
+#define DIG_FE_CNTL__TMDS_COLOR_FORMAT_MASK 0xc0000000
+#define DIG_FE_CNTL__TMDS_COLOR_FORMAT__SHIFT 0x1e
+#define DIG_OUTPUT_CRC_CNTL__DIG_OUTPUT_CRC_EN_MASK 0x1
+#define DIG_OUTPUT_CRC_CNTL__DIG_OUTPUT_CRC_EN__SHIFT 0x0
+#define DIG_OUTPUT_CRC_CNTL__DIG_OUTPUT_CRC_LINK_SEL_MASK 0x10
+#define DIG_OUTPUT_CRC_CNTL__DIG_OUTPUT_CRC_LINK_SEL__SHIFT 0x4
+#define DIG_OUTPUT_CRC_CNTL__DIG_OUTPUT_CRC_DATA_SEL_MASK 0x300
+#define DIG_OUTPUT_CRC_CNTL__DIG_OUTPUT_CRC_DATA_SEL__SHIFT 0x8
+#define DIG_OUTPUT_CRC_RESULT__DIG_OUTPUT_CRC_RESULT_MASK 0x3fffffff
+#define DIG_OUTPUT_CRC_RESULT__DIG_OUTPUT_CRC_RESULT__SHIFT 0x0
+#define DIG_CLOCK_PATTERN__DIG_CLOCK_PATTERN_MASK 0x3ff
+#define DIG_CLOCK_PATTERN__DIG_CLOCK_PATTERN__SHIFT 0x0
+#define DIG_TEST_PATTERN__DIG_TEST_PATTERN_OUT_EN_MASK 0x1
+#define DIG_TEST_PATTERN__DIG_TEST_PATTERN_OUT_EN__SHIFT 0x0
+#define DIG_TEST_PATTERN__DIG_HALF_CLOCK_PATTERN_SEL_MASK 0x2
+#define DIG_TEST_PATTERN__DIG_HALF_CLOCK_PATTERN_SEL__SHIFT 0x1
+#define DIG_TEST_PATTERN__DIG_RANDOM_PATTERN_OUT_EN_MASK 0x10
+#define DIG_TEST_PATTERN__DIG_RANDOM_PATTERN_OUT_EN__SHIFT 0x4
+#define DIG_TEST_PATTERN__DIG_RANDOM_PATTERN_RESET_MASK 0x20
+#define DIG_TEST_PATTERN__DIG_RANDOM_PATTERN_RESET__SHIFT 0x5
+#define DIG_TEST_PATTERN__DIG_TEST_PATTERN_EXTERNAL_RESET_EN_MASK 0x40
+#define DIG_TEST_PATTERN__DIG_TEST_PATTERN_EXTERNAL_RESET_EN__SHIFT 0x6
+#define DIG_TEST_PATTERN__DIG_STATIC_TEST_PATTERN_MASK 0x3ff0000
+#define DIG_TEST_PATTERN__DIG_STATIC_TEST_PATTERN__SHIFT 0x10
+#define DIG_RANDOM_PATTERN_SEED__DIG_RANDOM_PATTERN_SEED_MASK 0xffffff
+#define DIG_RANDOM_PATTERN_SEED__DIG_RANDOM_PATTERN_SEED__SHIFT 0x0
+#define DIG_RANDOM_PATTERN_SEED__DIG_RAN_PAT_DURING_DE_ONLY_MASK 0x1000000
+#define DIG_RANDOM_PATTERN_SEED__DIG_RAN_PAT_DURING_DE_ONLY__SHIFT 0x18
+#define DIG_FIFO_STATUS__DIG_FIFO_LEVEL_ERROR_MASK 0x1
+#define DIG_FIFO_STATUS__DIG_FIFO_LEVEL_ERROR__SHIFT 0x0
+#define DIG_FIFO_STATUS__DIG_FIFO_USE_OVERWRITE_LEVEL_MASK 0x2
+#define DIG_FIFO_STATUS__DIG_FIFO_USE_OVERWRITE_LEVEL__SHIFT 0x1
+#define DIG_FIFO_STATUS__DIG_FIFO_OVERWRITE_LEVEL_MASK 0xfc
+#define DIG_FIFO_STATUS__DIG_FIFO_OVERWRITE_LEVEL__SHIFT 0x2
+#define DIG_FIFO_STATUS__DIG_FIFO_ERROR_ACK_MASK 0x100
+#define DIG_FIFO_STATUS__DIG_FIFO_ERROR_ACK__SHIFT 0x8
+#define DIG_FIFO_STATUS__DIG_FIFO_CAL_AVERAGE_LEVEL_MASK 0xfc00
+#define DIG_FIFO_STATUS__DIG_FIFO_CAL_AVERAGE_LEVEL__SHIFT 0xa
+#define DIG_FIFO_STATUS__DIG_FIFO_MAXIMUM_LEVEL_MASK 0x1f0000
+#define DIG_FIFO_STATUS__DIG_FIFO_MAXIMUM_LEVEL__SHIFT 0x10
+#define DIG_FIFO_STATUS__DIG_FIFO_MINIMUM_LEVEL_MASK 0x3c00000
+#define DIG_FIFO_STATUS__DIG_FIFO_MINIMUM_LEVEL__SHIFT 0x16
+#define DIG_FIFO_STATUS__DIG_FIFO_READ_CLOCK_SRC_MASK 0x4000000
+#define DIG_FIFO_STATUS__DIG_FIFO_READ_CLOCK_SRC__SHIFT 0x1a
+#define DIG_FIFO_STATUS__DIG_FIFO_CALIBRATED_MASK 0x20000000
+#define DIG_FIFO_STATUS__DIG_FIFO_CALIBRATED__SHIFT 0x1d
+#define DIG_FIFO_STATUS__DIG_FIFO_FORCE_RECAL_AVERAGE_MASK 0x40000000
+#define DIG_FIFO_STATUS__DIG_FIFO_FORCE_RECAL_AVERAGE__SHIFT 0x1e
+#define DIG_FIFO_STATUS__DIG_FIFO_FORCE_RECOMP_MINMAX_MASK 0x80000000
+#define DIG_FIFO_STATUS__DIG_FIFO_FORCE_RECOMP_MINMAX__SHIFT 0x1f
+#define DIG_DISPCLK_SWITCH_CNTL__DIG_DISPCLK_SWITCH_POINT_MASK 0x1
+#define DIG_DISPCLK_SWITCH_CNTL__DIG_DISPCLK_SWITCH_POINT__SHIFT 0x0
+#define DIG_DISPCLK_SWITCH_STATUS__DIG_DISPCLK_SWITCH_ALLOWED_MASK 0x1
+#define DIG_DISPCLK_SWITCH_STATUS__DIG_DISPCLK_SWITCH_ALLOWED__SHIFT 0x0
+#define DIG_DISPCLK_SWITCH_STATUS__DIG_DISPCLK_SWITCH_ALLOWED_INT_MASK 0x10
+#define DIG_DISPCLK_SWITCH_STATUS__DIG_DISPCLK_SWITCH_ALLOWED_INT__SHIFT 0x4
+#define DIG_DISPCLK_SWITCH_STATUS__DIG_DISPCLK_SWITCH_ALLOWED_INT_ACK_MASK 0x100
+#define DIG_DISPCLK_SWITCH_STATUS__DIG_DISPCLK_SWITCH_ALLOWED_INT_ACK__SHIFT 0x8
+#define DIG_DISPCLK_SWITCH_STATUS__DIG_DISPCLK_SWITCH_ALLOWED_INT_MASK_MASK 0x1000
+#define DIG_DISPCLK_SWITCH_STATUS__DIG_DISPCLK_SWITCH_ALLOWED_INT_MASK__SHIFT 0xc
+#define HDMI_CONTROL__HDMI_KEEPOUT_MODE_MASK 0x1
+#define HDMI_CONTROL__HDMI_KEEPOUT_MODE__SHIFT 0x0
+#define HDMI_CONTROL__HDMI_CLOCK_CHANNEL_RATE_MASK 0x4
+#define HDMI_CONTROL__HDMI_CLOCK_CHANNEL_RATE__SHIFT 0x2
+#define HDMI_CONTROL__HDMI_NO_EXTRA_NULL_PACKET_FILLED_MASK 0x8
+#define HDMI_CONTROL__HDMI_NO_EXTRA_NULL_PACKET_FILLED__SHIFT 0x3
+#define HDMI_CONTROL__HDMI_PACKET_GEN_VERSION_MASK 0x10
+#define HDMI_CONTROL__HDMI_PACKET_GEN_VERSION__SHIFT 0x4
+#define HDMI_CONTROL__HDMI_ERROR_ACK_MASK 0x100
+#define HDMI_CONTROL__HDMI_ERROR_ACK__SHIFT 0x8
+#define HDMI_CONTROL__HDMI_ERROR_MASK_MASK 0x200
+#define HDMI_CONTROL__HDMI_ERROR_MASK__SHIFT 0x9
+#define HDMI_CONTROL__HDMI_DEEP_COLOR_ENABLE_MASK 0x1000000
+#define HDMI_CONTROL__HDMI_DEEP_COLOR_ENABLE__SHIFT 0x18
+#define HDMI_CONTROL__HDMI_DEEP_COLOR_DEPTH_MASK 0x30000000
+#define HDMI_CONTROL__HDMI_DEEP_COLOR_DEPTH__SHIFT 0x1c
+#define HDMI_STATUS__HDMI_ACTIVE_AVMUTE_MASK 0x1
+#define HDMI_STATUS__HDMI_ACTIVE_AVMUTE__SHIFT 0x0
+#define HDMI_STATUS__HDMI_AUDIO_PACKET_ERROR_MASK 0x10000
+#define HDMI_STATUS__HDMI_AUDIO_PACKET_ERROR__SHIFT 0x10
+#define HDMI_STATUS__HDMI_VBI_PACKET_ERROR_MASK 0x100000
+#define HDMI_STATUS__HDMI_VBI_PACKET_ERROR__SHIFT 0x14
+#define HDMI_STATUS__HDMI_ERROR_INT_MASK 0x8000000
+#define HDMI_STATUS__HDMI_ERROR_INT__SHIFT 0x1b
+#define HDMI_AUDIO_PACKET_CONTROL__HDMI_AUDIO_DELAY_EN_MASK 0x30
+#define HDMI_AUDIO_PACKET_CONTROL__HDMI_AUDIO_DELAY_EN__SHIFT 0x4
+#define HDMI_AUDIO_PACKET_CONTROL__HDMI_AUDIO_SEND_MAX_PACKETS_MASK 0x100
+#define HDMI_AUDIO_PACKET_CONTROL__HDMI_AUDIO_SEND_MAX_PACKETS__SHIFT 0x8
+#define HDMI_AUDIO_PACKET_CONTROL__HDMI_AUDIO_PACKETS_PER_LINE_MASK 0x1f0000
+#define HDMI_AUDIO_PACKET_CONTROL__HDMI_AUDIO_PACKETS_PER_LINE__SHIFT 0x10
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_SEND_MASK 0x1
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_SEND__SHIFT 0x0
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_CONT_MASK 0x2
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_CONT__SHIFT 0x1
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_SELECT_MASK 0x30
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_SELECT__SHIFT 0x4
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_SOURCE_MASK 0x100
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_SOURCE__SHIFT 0x8
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_AUTO_SEND_MASK 0x1000
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_AUTO_SEND__SHIFT 0xc
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_N_MULTIPLE_MASK 0x70000
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_N_MULTIPLE__SHIFT 0x10
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_AUDIO_PRIORITY_MASK 0x80000000
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_AUDIO_PRIORITY__SHIFT 0x1f
+#define HDMI_VBI_PACKET_CONTROL__HDMI_NULL_SEND_MASK 0x1
+#define HDMI_VBI_PACKET_CONTROL__HDMI_NULL_SEND__SHIFT 0x0
+#define HDMI_VBI_PACKET_CONTROL__HDMI_GC_SEND_MASK 0x10
+#define HDMI_VBI_PACKET_CONTROL__HDMI_GC_SEND__SHIFT 0x4
+#define HDMI_VBI_PACKET_CONTROL__HDMI_GC_CONT_MASK 0x20
+#define HDMI_VBI_PACKET_CONTROL__HDMI_GC_CONT__SHIFT 0x5
+#define HDMI_VBI_PACKET_CONTROL__HDMI_ISRC_SEND_MASK 0x100
+#define HDMI_VBI_PACKET_CONTROL__HDMI_ISRC_SEND__SHIFT 0x8
+#define HDMI_VBI_PACKET_CONTROL__HDMI_ISRC_CONT_MASK 0x200
+#define HDMI_VBI_PACKET_CONTROL__HDMI_ISRC_CONT__SHIFT 0x9
+#define HDMI_VBI_PACKET_CONTROL__HDMI_ISRC_LINE_MASK 0x3f0000
+#define HDMI_VBI_PACKET_CONTROL__HDMI_ISRC_LINE__SHIFT 0x10
+#define HDMI_INFOFRAME_CONTROL0__HDMI_AVI_INFO_SEND_MASK 0x1
+#define HDMI_INFOFRAME_CONTROL0__HDMI_AVI_INFO_SEND__SHIFT 0x0
+#define HDMI_INFOFRAME_CONTROL0__HDMI_AVI_INFO_CONT_MASK 0x2
+#define HDMI_INFOFRAME_CONTROL0__HDMI_AVI_INFO_CONT__SHIFT 0x1
+#define HDMI_INFOFRAME_CONTROL0__HDMI_AUDIO_INFO_SEND_MASK 0x10
+#define HDMI_INFOFRAME_CONTROL0__HDMI_AUDIO_INFO_SEND__SHIFT 0x4
+#define HDMI_INFOFRAME_CONTROL0__HDMI_AUDIO_INFO_CONT_MASK 0x20
+#define HDMI_INFOFRAME_CONTROL0__HDMI_AUDIO_INFO_CONT__SHIFT 0x5
+#define HDMI_INFOFRAME_CONTROL0__HDMI_MPEG_INFO_SEND_MASK 0x100
+#define HDMI_INFOFRAME_CONTROL0__HDMI_MPEG_INFO_SEND__SHIFT 0x8
+#define HDMI_INFOFRAME_CONTROL0__HDMI_MPEG_INFO_CONT_MASK 0x200
+#define HDMI_INFOFRAME_CONTROL0__HDMI_MPEG_INFO_CONT__SHIFT 0x9
+#define HDMI_INFOFRAME_CONTROL1__HDMI_AVI_INFO_LINE_MASK 0x3f
+#define HDMI_INFOFRAME_CONTROL1__HDMI_AVI_INFO_LINE__SHIFT 0x0
+#define HDMI_INFOFRAME_CONTROL1__HDMI_AUDIO_INFO_LINE_MASK 0x3f00
+#define HDMI_INFOFRAME_CONTROL1__HDMI_AUDIO_INFO_LINE__SHIFT 0x8
+#define HDMI_INFOFRAME_CONTROL1__HDMI_MPEG_INFO_LINE_MASK 0x3f0000
+#define HDMI_INFOFRAME_CONTROL1__HDMI_MPEG_INFO_LINE__SHIFT 0x10
+#define HDMI_GENERIC_PACKET_CONTROL0__HDMI_GENERIC0_SEND_MASK 0x1
+#define HDMI_GENERIC_PACKET_CONTROL0__HDMI_GENERIC0_SEND__SHIFT 0x0
+#define HDMI_GENERIC_PACKET_CONTROL0__HDMI_GENERIC0_CONT_MASK 0x2
+#define HDMI_GENERIC_PACKET_CONTROL0__HDMI_GENERIC0_CONT__SHIFT 0x1
+#define HDMI_GENERIC_PACKET_CONTROL0__HDMI_GENERIC1_SEND_MASK 0x10
+#define HDMI_GENERIC_PACKET_CONTROL0__HDMI_GENERIC1_SEND__SHIFT 0x4
+#define HDMI_GENERIC_PACKET_CONTROL0__HDMI_GENERIC1_CONT_MASK 0x20
+#define HDMI_GENERIC_PACKET_CONTROL0__HDMI_GENERIC1_CONT__SHIFT 0x5
+#define HDMI_GENERIC_PACKET_CONTROL0__HDMI_GENERIC0_LINE_MASK 0x3f0000
+#define HDMI_GENERIC_PACKET_CONTROL0__HDMI_GENERIC0_LINE__SHIFT 0x10
+#define HDMI_GENERIC_PACKET_CONTROL0__HDMI_GENERIC1_LINE_MASK 0x3f000000
+#define HDMI_GENERIC_PACKET_CONTROL0__HDMI_GENERIC1_LINE__SHIFT 0x18
+#define HDMI_GC__HDMI_GC_AVMUTE_MASK 0x1
+#define HDMI_GC__HDMI_GC_AVMUTE__SHIFT 0x0
+#define HDMI_GC__HDMI_GC_AVMUTE_CONT_MASK 0x4
+#define HDMI_GC__HDMI_GC_AVMUTE_CONT__SHIFT 0x2
+#define HDMI_GC__HDMI_DEFAULT_PHASE_MASK 0x10
+#define HDMI_GC__HDMI_DEFAULT_PHASE__SHIFT 0x4
+#define HDMI_GC__HDMI_PACKING_PHASE_MASK 0xf00
+#define HDMI_GC__HDMI_PACKING_PHASE__SHIFT 0x8
+#define HDMI_GC__HDMI_PACKING_PHASE_OVERRIDE_MASK 0x1000
+#define HDMI_GC__HDMI_PACKING_PHASE_OVERRIDE__SHIFT 0xc
+#define AFMT_AUDIO_PACKET_CONTROL2__AFMT_AUDIO_LAYOUT_OVRD_MASK 0x1
+#define AFMT_AUDIO_PACKET_CONTROL2__AFMT_AUDIO_LAYOUT_OVRD__SHIFT 0x0
+#define AFMT_AUDIO_PACKET_CONTROL2__AFMT_AUDIO_LAYOUT_SELECT_MASK 0x2
+#define AFMT_AUDIO_PACKET_CONTROL2__AFMT_AUDIO_LAYOUT_SELECT__SHIFT 0x1
+#define AFMT_AUDIO_PACKET_CONTROL2__AFMT_AUDIO_CHANNEL_ENABLE_MASK 0xff00
+#define AFMT_AUDIO_PACKET_CONTROL2__AFMT_AUDIO_CHANNEL_ENABLE__SHIFT 0x8
+#define AFMT_AUDIO_PACKET_CONTROL2__AFMT_DP_AUDIO_STREAM_ID_MASK 0xff0000
+#define AFMT_AUDIO_PACKET_CONTROL2__AFMT_DP_AUDIO_STREAM_ID__SHIFT 0x10
+#define AFMT_AUDIO_PACKET_CONTROL2__AFMT_HBR_ENABLE_OVRD_MASK 0x1000000
+#define AFMT_AUDIO_PACKET_CONTROL2__AFMT_HBR_ENABLE_OVRD__SHIFT 0x18
+#define AFMT_AUDIO_PACKET_CONTROL2__AFMT_60958_OSF_OVRD_MASK 0x10000000
+#define AFMT_AUDIO_PACKET_CONTROL2__AFMT_60958_OSF_OVRD__SHIFT 0x1c
+#define AFMT_ISRC1_0__AFMT_ISRC_STATUS_MASK 0x7
+#define AFMT_ISRC1_0__AFMT_ISRC_STATUS__SHIFT 0x0
+#define AFMT_ISRC1_0__AFMT_ISRC_CONTINUE_MASK 0x40
+#define AFMT_ISRC1_0__AFMT_ISRC_CONTINUE__SHIFT 0x6
+#define AFMT_ISRC1_0__AFMT_ISRC_VALID_MASK 0x80
+#define AFMT_ISRC1_0__AFMT_ISRC_VALID__SHIFT 0x7
+#define AFMT_ISRC1_1__AFMT_UPC_EAN_ISRC0_MASK 0xff
+#define AFMT_ISRC1_1__AFMT_UPC_EAN_ISRC0__SHIFT 0x0
+#define AFMT_ISRC1_1__AFMT_UPC_EAN_ISRC1_MASK 0xff00
+#define AFMT_ISRC1_1__AFMT_UPC_EAN_ISRC1__SHIFT 0x8
+#define AFMT_ISRC1_1__AFMT_UPC_EAN_ISRC2_MASK 0xff0000
+#define AFMT_ISRC1_1__AFMT_UPC_EAN_ISRC2__SHIFT 0x10
+#define AFMT_ISRC1_1__AFMT_UPC_EAN_ISRC3_MASK 0xff000000
+#define AFMT_ISRC1_1__AFMT_UPC_EAN_ISRC3__SHIFT 0x18
+#define AFMT_ISRC1_2__AFMT_UPC_EAN_ISRC4_MASK 0xff
+#define AFMT_ISRC1_2__AFMT_UPC_EAN_ISRC4__SHIFT 0x0
+#define AFMT_ISRC1_2__AFMT_UPC_EAN_ISRC5_MASK 0xff00
+#define AFMT_ISRC1_2__AFMT_UPC_EAN_ISRC5__SHIFT 0x8
+#define AFMT_ISRC1_2__AFMT_UPC_EAN_ISRC6_MASK 0xff0000
+#define AFMT_ISRC1_2__AFMT_UPC_EAN_ISRC6__SHIFT 0x10
+#define AFMT_ISRC1_2__AFMT_UPC_EAN_ISRC7_MASK 0xff000000
+#define AFMT_ISRC1_2__AFMT_UPC_EAN_ISRC7__SHIFT 0x18
+#define AFMT_ISRC1_3__AFMT_UPC_EAN_ISRC8_MASK 0xff
+#define AFMT_ISRC1_3__AFMT_UPC_EAN_ISRC8__SHIFT 0x0
+#define AFMT_ISRC1_3__AFMT_UPC_EAN_ISRC9_MASK 0xff00
+#define AFMT_ISRC1_3__AFMT_UPC_EAN_ISRC9__SHIFT 0x8
+#define AFMT_ISRC1_3__AFMT_UPC_EAN_ISRC10_MASK 0xff0000
+#define AFMT_ISRC1_3__AFMT_UPC_EAN_ISRC10__SHIFT 0x10
+#define AFMT_ISRC1_3__AFMT_UPC_EAN_ISRC11_MASK 0xff000000
+#define AFMT_ISRC1_3__AFMT_UPC_EAN_ISRC11__SHIFT 0x18
+#define AFMT_ISRC1_4__AFMT_UPC_EAN_ISRC12_MASK 0xff
+#define AFMT_ISRC1_4__AFMT_UPC_EAN_ISRC12__SHIFT 0x0
+#define AFMT_ISRC1_4__AFMT_UPC_EAN_ISRC13_MASK 0xff00
+#define AFMT_ISRC1_4__AFMT_UPC_EAN_ISRC13__SHIFT 0x8
+#define AFMT_ISRC1_4__AFMT_UPC_EAN_ISRC14_MASK 0xff0000
+#define AFMT_ISRC1_4__AFMT_UPC_EAN_ISRC14__SHIFT 0x10
+#define AFMT_ISRC1_4__AFMT_UPC_EAN_ISRC15_MASK 0xff000000
+#define AFMT_ISRC1_4__AFMT_UPC_EAN_ISRC15__SHIFT 0x18
+#define AFMT_ISRC2_0__AFMT_UPC_EAN_ISRC16_MASK 0xff
+#define AFMT_ISRC2_0__AFMT_UPC_EAN_ISRC16__SHIFT 0x0
+#define AFMT_ISRC2_0__AFMT_UPC_EAN_ISRC17_MASK 0xff00
+#define AFMT_ISRC2_0__AFMT_UPC_EAN_ISRC17__SHIFT 0x8
+#define AFMT_ISRC2_0__AFMT_UPC_EAN_ISRC18_MASK 0xff0000
+#define AFMT_ISRC2_0__AFMT_UPC_EAN_ISRC18__SHIFT 0x10
+#define AFMT_ISRC2_0__AFMT_UPC_EAN_ISRC19_MASK 0xff000000
+#define AFMT_ISRC2_0__AFMT_UPC_EAN_ISRC19__SHIFT 0x18
+#define AFMT_ISRC2_1__AFMT_UPC_EAN_ISRC20_MASK 0xff
+#define AFMT_ISRC2_1__AFMT_UPC_EAN_ISRC20__SHIFT 0x0
+#define AFMT_ISRC2_1__AFMT_UPC_EAN_ISRC21_MASK 0xff00
+#define AFMT_ISRC2_1__AFMT_UPC_EAN_ISRC21__SHIFT 0x8
+#define AFMT_ISRC2_1__AFMT_UPC_EAN_ISRC22_MASK 0xff0000
+#define AFMT_ISRC2_1__AFMT_UPC_EAN_ISRC22__SHIFT 0x10
+#define AFMT_ISRC2_1__AFMT_UPC_EAN_ISRC23_MASK 0xff000000
+#define AFMT_ISRC2_1__AFMT_UPC_EAN_ISRC23__SHIFT 0x18
+#define AFMT_ISRC2_2__AFMT_UPC_EAN_ISRC24_MASK 0xff
+#define AFMT_ISRC2_2__AFMT_UPC_EAN_ISRC24__SHIFT 0x0
+#define AFMT_ISRC2_2__AFMT_UPC_EAN_ISRC25_MASK 0xff00
+#define AFMT_ISRC2_2__AFMT_UPC_EAN_ISRC25__SHIFT 0x8
+#define AFMT_ISRC2_2__AFMT_UPC_EAN_ISRC26_MASK 0xff0000
+#define AFMT_ISRC2_2__AFMT_UPC_EAN_ISRC26__SHIFT 0x10
+#define AFMT_ISRC2_2__AFMT_UPC_EAN_ISRC27_MASK 0xff000000
+#define AFMT_ISRC2_2__AFMT_UPC_EAN_ISRC27__SHIFT 0x18
+#define AFMT_ISRC2_3__AFMT_UPC_EAN_ISRC28_MASK 0xff
+#define AFMT_ISRC2_3__AFMT_UPC_EAN_ISRC28__SHIFT 0x0
+#define AFMT_ISRC2_3__AFMT_UPC_EAN_ISRC29_MASK 0xff00
+#define AFMT_ISRC2_3__AFMT_UPC_EAN_ISRC29__SHIFT 0x8
+#define AFMT_ISRC2_3__AFMT_UPC_EAN_ISRC30_MASK 0xff0000
+#define AFMT_ISRC2_3__AFMT_UPC_EAN_ISRC30__SHIFT 0x10
+#define AFMT_ISRC2_3__AFMT_UPC_EAN_ISRC31_MASK 0xff000000
+#define AFMT_ISRC2_3__AFMT_UPC_EAN_ISRC31__SHIFT 0x18
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_CHECKSUM_MASK 0xff
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_CHECKSUM__SHIFT 0x0
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_S_MASK 0x300
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_S__SHIFT 0x8
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_B_MASK 0xc00
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_B__SHIFT 0xa
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_A_MASK 0x1000
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_A__SHIFT 0xc
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_Y_MASK 0xe000
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_Y__SHIFT 0xd
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_R_MASK 0xf0000
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_R__SHIFT 0x10
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_M_MASK 0x300000
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_M__SHIFT 0x14
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_C_MASK 0xc00000
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_C__SHIFT 0x16
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_SC_MASK 0x3000000
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_SC__SHIFT 0x18
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_Q_MASK 0xc000000
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_Q__SHIFT 0x1a
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_EC_MASK 0x70000000
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_EC__SHIFT 0x1c
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_ITC_MASK 0x80000000
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_ITC__SHIFT 0x1f
+#define AFMT_AVI_INFO1__AFMT_AVI_INFO_VIC_MASK 0xff
+#define AFMT_AVI_INFO1__AFMT_AVI_INFO_VIC__SHIFT 0x0
+#define AFMT_AVI_INFO1__AFMT_AVI_INFO_PR_MASK 0xf00
+#define AFMT_AVI_INFO1__AFMT_AVI_INFO_PR__SHIFT 0x8
+#define AFMT_AVI_INFO1__AFMT_AVI_INFO_CN_MASK 0x3000
+#define AFMT_AVI_INFO1__AFMT_AVI_INFO_CN__SHIFT 0xc
+#define AFMT_AVI_INFO1__AFMT_AVI_INFO_YQ_MASK 0xc000
+#define AFMT_AVI_INFO1__AFMT_AVI_INFO_YQ__SHIFT 0xe
+#define AFMT_AVI_INFO1__AFMT_AVI_INFO_TOP_MASK 0xffff0000
+#define AFMT_AVI_INFO1__AFMT_AVI_INFO_TOP__SHIFT 0x10
+#define AFMT_AVI_INFO2__AFMT_AVI_INFO_BOTTOM_MASK 0xffff
+#define AFMT_AVI_INFO2__AFMT_AVI_INFO_BOTTOM__SHIFT 0x0
+#define AFMT_AVI_INFO2__AFMT_AVI_INFO_LEFT_MASK 0xffff0000
+#define AFMT_AVI_INFO2__AFMT_AVI_INFO_LEFT__SHIFT 0x10
+#define AFMT_AVI_INFO3__AFMT_AVI_INFO_RIGHT_MASK 0xffff
+#define AFMT_AVI_INFO3__AFMT_AVI_INFO_RIGHT__SHIFT 0x0
+#define AFMT_AVI_INFO3__AFMT_AVI_INFO_VERSION_MASK 0xff000000
+#define AFMT_AVI_INFO3__AFMT_AVI_INFO_VERSION__SHIFT 0x18
+#define AFMT_MPEG_INFO0__AFMT_MPEG_INFO_CHECKSUM_MASK 0xff
+#define AFMT_MPEG_INFO0__AFMT_MPEG_INFO_CHECKSUM__SHIFT 0x0
+#define AFMT_MPEG_INFO0__AFMT_MPEG_INFO_MB0_MASK 0xff00
+#define AFMT_MPEG_INFO0__AFMT_MPEG_INFO_MB0__SHIFT 0x8
+#define AFMT_MPEG_INFO0__AFMT_MPEG_INFO_MB1_MASK 0xff0000
+#define AFMT_MPEG_INFO0__AFMT_MPEG_INFO_MB1__SHIFT 0x10
+#define AFMT_MPEG_INFO0__AFMT_MPEG_INFO_MB2_MASK 0xff000000
+#define AFMT_MPEG_INFO0__AFMT_MPEG_INFO_MB2__SHIFT 0x18
+#define AFMT_MPEG_INFO1__AFMT_MPEG_INFO_MB3_MASK 0xff
+#define AFMT_MPEG_INFO1__AFMT_MPEG_INFO_MB3__SHIFT 0x0
+#define AFMT_MPEG_INFO1__AFMT_MPEG_INFO_MF_MASK 0x300
+#define AFMT_MPEG_INFO1__AFMT_MPEG_INFO_MF__SHIFT 0x8
+#define AFMT_MPEG_INFO1__AFMT_MPEG_INFO_FR_MASK 0x1000
+#define AFMT_MPEG_INFO1__AFMT_MPEG_INFO_FR__SHIFT 0xc
+#define AFMT_GENERIC_HDR__AFMT_GENERIC_HB0_MASK 0xff
+#define AFMT_GENERIC_HDR__AFMT_GENERIC_HB0__SHIFT 0x0
+#define AFMT_GENERIC_HDR__AFMT_GENERIC_HB1_MASK 0xff00
+#define AFMT_GENERIC_HDR__AFMT_GENERIC_HB1__SHIFT 0x8
+#define AFMT_GENERIC_HDR__AFMT_GENERIC_HB2_MASK 0xff0000
+#define AFMT_GENERIC_HDR__AFMT_GENERIC_HB2__SHIFT 0x10
+#define AFMT_GENERIC_HDR__AFMT_GENERIC_HB3_MASK 0xff000000
+#define AFMT_GENERIC_HDR__AFMT_GENERIC_HB3__SHIFT 0x18
+#define AFMT_GENERIC_0__AFMT_GENERIC_BYTE0_MASK 0xff
+#define AFMT_GENERIC_0__AFMT_GENERIC_BYTE0__SHIFT 0x0
+#define AFMT_GENERIC_0__AFMT_GENERIC_BYTE1_MASK 0xff00
+#define AFMT_GENERIC_0__AFMT_GENERIC_BYTE1__SHIFT 0x8
+#define AFMT_GENERIC_0__AFMT_GENERIC_BYTE2_MASK 0xff0000
+#define AFMT_GENERIC_0__AFMT_GENERIC_BYTE2__SHIFT 0x10
+#define AFMT_GENERIC_0__AFMT_GENERIC_BYTE3_MASK 0xff000000
+#define AFMT_GENERIC_0__AFMT_GENERIC_BYTE3__SHIFT 0x18
+#define AFMT_GENERIC_1__AFMT_GENERIC_BYTE4_MASK 0xff
+#define AFMT_GENERIC_1__AFMT_GENERIC_BYTE4__SHIFT 0x0
+#define AFMT_GENERIC_1__AFMT_GENERIC_BYTE5_MASK 0xff00
+#define AFMT_GENERIC_1__AFMT_GENERIC_BYTE5__SHIFT 0x8
+#define AFMT_GENERIC_1__AFMT_GENERIC_BYTE6_MASK 0xff0000
+#define AFMT_GENERIC_1__AFMT_GENERIC_BYTE6__SHIFT 0x10
+#define AFMT_GENERIC_1__AFMT_GENERIC_BYTE7_MASK 0xff000000
+#define AFMT_GENERIC_1__AFMT_GENERIC_BYTE7__SHIFT 0x18
+#define AFMT_GENERIC_2__AFMT_GENERIC_BYTE8_MASK 0xff
+#define AFMT_GENERIC_2__AFMT_GENERIC_BYTE8__SHIFT 0x0
+#define AFMT_GENERIC_2__AFMT_GENERIC_BYTE9_MASK 0xff00
+#define AFMT_GENERIC_2__AFMT_GENERIC_BYTE9__SHIFT 0x8
+#define AFMT_GENERIC_2__AFMT_GENERIC_BYTE10_MASK 0xff0000
+#define AFMT_GENERIC_2__AFMT_GENERIC_BYTE10__SHIFT 0x10
+#define AFMT_GENERIC_2__AFMT_GENERIC_BYTE11_MASK 0xff000000
+#define AFMT_GENERIC_2__AFMT_GENERIC_BYTE11__SHIFT 0x18
+#define AFMT_GENERIC_3__AFMT_GENERIC_BYTE12_MASK 0xff
+#define AFMT_GENERIC_3__AFMT_GENERIC_BYTE12__SHIFT 0x0
+#define AFMT_GENERIC_3__AFMT_GENERIC_BYTE13_MASK 0xff00
+#define AFMT_GENERIC_3__AFMT_GENERIC_BYTE13__SHIFT 0x8
+#define AFMT_GENERIC_3__AFMT_GENERIC_BYTE14_MASK 0xff0000
+#define AFMT_GENERIC_3__AFMT_GENERIC_BYTE14__SHIFT 0x10
+#define AFMT_GENERIC_3__AFMT_GENERIC_BYTE15_MASK 0xff000000
+#define AFMT_GENERIC_3__AFMT_GENERIC_BYTE15__SHIFT 0x18
+#define AFMT_GENERIC_4__AFMT_GENERIC_BYTE16_MASK 0xff
+#define AFMT_GENERIC_4__AFMT_GENERIC_BYTE16__SHIFT 0x0
+#define AFMT_GENERIC_4__AFMT_GENERIC_BYTE17_MASK 0xff00
+#define AFMT_GENERIC_4__AFMT_GENERIC_BYTE17__SHIFT 0x8
+#define AFMT_GENERIC_4__AFMT_GENERIC_BYTE18_MASK 0xff0000
+#define AFMT_GENERIC_4__AFMT_GENERIC_BYTE18__SHIFT 0x10
+#define AFMT_GENERIC_4__AFMT_GENERIC_BYTE19_MASK 0xff000000
+#define AFMT_GENERIC_4__AFMT_GENERIC_BYTE19__SHIFT 0x18
+#define AFMT_GENERIC_5__AFMT_GENERIC_BYTE20_MASK 0xff
+#define AFMT_GENERIC_5__AFMT_GENERIC_BYTE20__SHIFT 0x0
+#define AFMT_GENERIC_5__AFMT_GENERIC_BYTE21_MASK 0xff00
+#define AFMT_GENERIC_5__AFMT_GENERIC_BYTE21__SHIFT 0x8
+#define AFMT_GENERIC_5__AFMT_GENERIC_BYTE22_MASK 0xff0000
+#define AFMT_GENERIC_5__AFMT_GENERIC_BYTE22__SHIFT 0x10
+#define AFMT_GENERIC_5__AFMT_GENERIC_BYTE23_MASK 0xff000000
+#define AFMT_GENERIC_5__AFMT_GENERIC_BYTE23__SHIFT 0x18
+#define AFMT_GENERIC_6__AFMT_GENERIC_BYTE24_MASK 0xff
+#define AFMT_GENERIC_6__AFMT_GENERIC_BYTE24__SHIFT 0x0
+#define AFMT_GENERIC_6__AFMT_GENERIC_BYTE25_MASK 0xff00
+#define AFMT_GENERIC_6__AFMT_GENERIC_BYTE25__SHIFT 0x8
+#define AFMT_GENERIC_6__AFMT_GENERIC_BYTE26_MASK 0xff0000
+#define AFMT_GENERIC_6__AFMT_GENERIC_BYTE26__SHIFT 0x10
+#define AFMT_GENERIC_6__AFMT_GENERIC_BYTE27_MASK 0xff000000
+#define AFMT_GENERIC_6__AFMT_GENERIC_BYTE27__SHIFT 0x18
+#define AFMT_GENERIC_7__AFMT_GENERIC_BYTE28_MASK 0xff
+#define AFMT_GENERIC_7__AFMT_GENERIC_BYTE28__SHIFT 0x0
+#define AFMT_GENERIC_7__AFMT_GENERIC_BYTE29_MASK 0xff00
+#define AFMT_GENERIC_7__AFMT_GENERIC_BYTE29__SHIFT 0x8
+#define AFMT_GENERIC_7__AFMT_GENERIC_BYTE30_MASK 0xff0000
+#define AFMT_GENERIC_7__AFMT_GENERIC_BYTE30__SHIFT 0x10
+#define AFMT_GENERIC_7__AFMT_GENERIC_BYTE31_MASK 0xff000000
+#define AFMT_GENERIC_7__AFMT_GENERIC_BYTE31__SHIFT 0x18
+#define HDMI_GENERIC_PACKET_CONTROL1__HDMI_GENERIC2_SEND_MASK 0x1
+#define HDMI_GENERIC_PACKET_CONTROL1__HDMI_GENERIC2_SEND__SHIFT 0x0
+#define HDMI_GENERIC_PACKET_CONTROL1__HDMI_GENERIC2_CONT_MASK 0x2
+#define HDMI_GENERIC_PACKET_CONTROL1__HDMI_GENERIC2_CONT__SHIFT 0x1
+#define HDMI_GENERIC_PACKET_CONTROL1__HDMI_GENERIC3_SEND_MASK 0x10
+#define HDMI_GENERIC_PACKET_CONTROL1__HDMI_GENERIC3_SEND__SHIFT 0x4
+#define HDMI_GENERIC_PACKET_CONTROL1__HDMI_GENERIC3_CONT_MASK 0x20
+#define HDMI_GENERIC_PACKET_CONTROL1__HDMI_GENERIC3_CONT__SHIFT 0x5
+#define HDMI_GENERIC_PACKET_CONTROL1__HDMI_GENERIC2_LINE_MASK 0x3f0000
+#define HDMI_GENERIC_PACKET_CONTROL1__HDMI_GENERIC2_LINE__SHIFT 0x10
+#define HDMI_GENERIC_PACKET_CONTROL1__HDMI_GENERIC3_LINE_MASK 0x3f000000
+#define HDMI_GENERIC_PACKET_CONTROL1__HDMI_GENERIC3_LINE__SHIFT 0x18
+#define HDMI_ACR_32_0__HDMI_ACR_CTS_32_MASK 0xfffff000
+#define HDMI_ACR_32_0__HDMI_ACR_CTS_32__SHIFT 0xc
+#define HDMI_ACR_32_1__HDMI_ACR_N_32_MASK 0xfffff
+#define HDMI_ACR_32_1__HDMI_ACR_N_32__SHIFT 0x0
+#define HDMI_ACR_44_0__HDMI_ACR_CTS_44_MASK 0xfffff000
+#define HDMI_ACR_44_0__HDMI_ACR_CTS_44__SHIFT 0xc
+#define HDMI_ACR_44_1__HDMI_ACR_N_44_MASK 0xfffff
+#define HDMI_ACR_44_1__HDMI_ACR_N_44__SHIFT 0x0
+#define HDMI_ACR_48_0__HDMI_ACR_CTS_48_MASK 0xfffff000
+#define HDMI_ACR_48_0__HDMI_ACR_CTS_48__SHIFT 0xc
+#define HDMI_ACR_48_1__HDMI_ACR_N_48_MASK 0xfffff
+#define HDMI_ACR_48_1__HDMI_ACR_N_48__SHIFT 0x0
+#define HDMI_ACR_STATUS_0__HDMI_ACR_CTS_MASK 0xfffff000
+#define HDMI_ACR_STATUS_0__HDMI_ACR_CTS__SHIFT 0xc
+#define HDMI_ACR_STATUS_1__HDMI_ACR_N_MASK 0xfffff
+#define HDMI_ACR_STATUS_1__HDMI_ACR_N__SHIFT 0x0
+#define AFMT_AUDIO_INFO0__AFMT_AUDIO_INFO_CHECKSUM_MASK 0xff
+#define AFMT_AUDIO_INFO0__AFMT_AUDIO_INFO_CHECKSUM__SHIFT 0x0
+#define AFMT_AUDIO_INFO0__AFMT_AUDIO_INFO_CC_MASK 0x700
+#define AFMT_AUDIO_INFO0__AFMT_AUDIO_INFO_CC__SHIFT 0x8
+#define AFMT_AUDIO_INFO0__AFMT_AUDIO_INFO_CT_MASK 0x7800
+#define AFMT_AUDIO_INFO0__AFMT_AUDIO_INFO_CT__SHIFT 0xb
+#define AFMT_AUDIO_INFO0__AFMT_AUDIO_INFO_CHECKSUM_OFFSET_MASK 0xff0000
+#define AFMT_AUDIO_INFO0__AFMT_AUDIO_INFO_CHECKSUM_OFFSET__SHIFT 0x10
+#define AFMT_AUDIO_INFO0__AFMT_AUDIO_INFO_CXT_MASK 0x1f000000
+#define AFMT_AUDIO_INFO0__AFMT_AUDIO_INFO_CXT__SHIFT 0x18
+#define AFMT_AUDIO_INFO1__AFMT_AUDIO_INFO_CA_MASK 0xff
+#define AFMT_AUDIO_INFO1__AFMT_AUDIO_INFO_CA__SHIFT 0x0
+#define AFMT_AUDIO_INFO1__AFMT_AUDIO_INFO_LSV_MASK 0x7800
+#define AFMT_AUDIO_INFO1__AFMT_AUDIO_INFO_LSV__SHIFT 0xb
+#define AFMT_AUDIO_INFO1__AFMT_AUDIO_INFO_DM_INH_MASK 0x8000
+#define AFMT_AUDIO_INFO1__AFMT_AUDIO_INFO_DM_INH__SHIFT 0xf
+#define AFMT_AUDIO_INFO1__AFMT_AUDIO_INFO_LFEPBL_MASK 0x30000
+#define AFMT_AUDIO_INFO1__AFMT_AUDIO_INFO_LFEPBL__SHIFT 0x10
+#define AFMT_60958_0__AFMT_60958_CS_A_MASK 0x1
+#define AFMT_60958_0__AFMT_60958_CS_A__SHIFT 0x0
+#define AFMT_60958_0__AFMT_60958_CS_B_MASK 0x2
+#define AFMT_60958_0__AFMT_60958_CS_B__SHIFT 0x1
+#define AFMT_60958_0__AFMT_60958_CS_C_MASK 0x4
+#define AFMT_60958_0__AFMT_60958_CS_C__SHIFT 0x2
+#define AFMT_60958_0__AFMT_60958_CS_D_MASK 0x38
+#define AFMT_60958_0__AFMT_60958_CS_D__SHIFT 0x3
+#define AFMT_60958_0__AFMT_60958_CS_MODE_MASK 0xc0
+#define AFMT_60958_0__AFMT_60958_CS_MODE__SHIFT 0x6
+#define AFMT_60958_0__AFMT_60958_CS_CATEGORY_CODE_MASK 0xff00
+#define AFMT_60958_0__AFMT_60958_CS_CATEGORY_CODE__SHIFT 0x8
+#define AFMT_60958_0__AFMT_60958_CS_SOURCE_NUMBER_MASK 0xf0000
+#define AFMT_60958_0__AFMT_60958_CS_SOURCE_NUMBER__SHIFT 0x10
+#define AFMT_60958_0__AFMT_60958_CS_CHANNEL_NUMBER_L_MASK 0xf00000
+#define AFMT_60958_0__AFMT_60958_CS_CHANNEL_NUMBER_L__SHIFT 0x14
+#define AFMT_60958_0__AFMT_60958_CS_SAMPLING_FREQUENCY_MASK 0xf000000
+#define AFMT_60958_0__AFMT_60958_CS_SAMPLING_FREQUENCY__SHIFT 0x18
+#define AFMT_60958_0__AFMT_60958_CS_CLOCK_ACCURACY_MASK 0x30000000
+#define AFMT_60958_0__AFMT_60958_CS_CLOCK_ACCURACY__SHIFT 0x1c
+#define AFMT_60958_1__AFMT_60958_CS_WORD_LENGTH_MASK 0xf
+#define AFMT_60958_1__AFMT_60958_CS_WORD_LENGTH__SHIFT 0x0
+#define AFMT_60958_1__AFMT_60958_CS_ORIGINAL_SAMPLING_FREQUENCY_MASK 0xf0
+#define AFMT_60958_1__AFMT_60958_CS_ORIGINAL_SAMPLING_FREQUENCY__SHIFT 0x4
+#define AFMT_60958_1__AFMT_60958_VALID_L_MASK 0x10000
+#define AFMT_60958_1__AFMT_60958_VALID_L__SHIFT 0x10
+#define AFMT_60958_1__AFMT_60958_VALID_R_MASK 0x40000
+#define AFMT_60958_1__AFMT_60958_VALID_R__SHIFT 0x12
+#define AFMT_60958_1__AFMT_60958_CS_CHANNEL_NUMBER_R_MASK 0xf00000
+#define AFMT_60958_1__AFMT_60958_CS_CHANNEL_NUMBER_R__SHIFT 0x14
+#define AFMT_AUDIO_CRC_CONTROL__AFMT_AUDIO_CRC_EN_MASK 0x1
+#define AFMT_AUDIO_CRC_CONTROL__AFMT_AUDIO_CRC_EN__SHIFT 0x0
+#define AFMT_AUDIO_CRC_CONTROL__AFMT_AUDIO_CRC_CONT_MASK 0x10
+#define AFMT_AUDIO_CRC_CONTROL__AFMT_AUDIO_CRC_CONT__SHIFT 0x4
+#define AFMT_AUDIO_CRC_CONTROL__AFMT_AUDIO_CRC_SOURCE_MASK 0x100
+#define AFMT_AUDIO_CRC_CONTROL__AFMT_AUDIO_CRC_SOURCE__SHIFT 0x8
+#define AFMT_AUDIO_CRC_CONTROL__AFMT_AUDIO_CRC_CH_SEL_MASK 0xf000
+#define AFMT_AUDIO_CRC_CONTROL__AFMT_AUDIO_CRC_CH_SEL__SHIFT 0xc
+#define AFMT_AUDIO_CRC_CONTROL__AFMT_AUDIO_CRC_COUNT_MASK 0xffff0000
+#define AFMT_AUDIO_CRC_CONTROL__AFMT_AUDIO_CRC_COUNT__SHIFT 0x10
+#define AFMT_RAMP_CONTROL0__AFMT_RAMP_MAX_COUNT_MASK 0xffffff
+#define AFMT_RAMP_CONTROL0__AFMT_RAMP_MAX_COUNT__SHIFT 0x0
+#define AFMT_RAMP_CONTROL0__AFMT_RAMP_DATA_SIGN_MASK 0x80000000
+#define AFMT_RAMP_CONTROL0__AFMT_RAMP_DATA_SIGN__SHIFT 0x1f
+#define AFMT_RAMP_CONTROL1__AFMT_RAMP_MIN_COUNT_MASK 0xffffff
+#define AFMT_RAMP_CONTROL1__AFMT_RAMP_MIN_COUNT__SHIFT 0x0
+#define AFMT_RAMP_CONTROL1__AFMT_AUDIO_TEST_CH_DISABLE_MASK 0xff000000
+#define AFMT_RAMP_CONTROL1__AFMT_AUDIO_TEST_CH_DISABLE__SHIFT 0x18
+#define AFMT_RAMP_CONTROL2__AFMT_RAMP_INC_COUNT_MASK 0xffffff
+#define AFMT_RAMP_CONTROL2__AFMT_RAMP_INC_COUNT__SHIFT 0x0
+#define AFMT_RAMP_CONTROL3__AFMT_RAMP_DEC_COUNT_MASK 0xffffff
+#define AFMT_RAMP_CONTROL3__AFMT_RAMP_DEC_COUNT__SHIFT 0x0
+#define AFMT_60958_2__AFMT_60958_CS_CHANNEL_NUMBER_2_MASK 0xf
+#define AFMT_60958_2__AFMT_60958_CS_CHANNEL_NUMBER_2__SHIFT 0x0
+#define AFMT_60958_2__AFMT_60958_CS_CHANNEL_NUMBER_3_MASK 0xf0
+#define AFMT_60958_2__AFMT_60958_CS_CHANNEL_NUMBER_3__SHIFT 0x4
+#define AFMT_60958_2__AFMT_60958_CS_CHANNEL_NUMBER_4_MASK 0xf00
+#define AFMT_60958_2__AFMT_60958_CS_CHANNEL_NUMBER_4__SHIFT 0x8
+#define AFMT_60958_2__AFMT_60958_CS_CHANNEL_NUMBER_5_MASK 0xf000
+#define AFMT_60958_2__AFMT_60958_CS_CHANNEL_NUMBER_5__SHIFT 0xc
+#define AFMT_60958_2__AFMT_60958_CS_CHANNEL_NUMBER_6_MASK 0xf0000
+#define AFMT_60958_2__AFMT_60958_CS_CHANNEL_NUMBER_6__SHIFT 0x10
+#define AFMT_60958_2__AFMT_60958_CS_CHANNEL_NUMBER_7_MASK 0xf00000
+#define AFMT_60958_2__AFMT_60958_CS_CHANNEL_NUMBER_7__SHIFT 0x14
+#define AFMT_AUDIO_CRC_RESULT__AFMT_AUDIO_CRC_DONE_MASK 0x1
+#define AFMT_AUDIO_CRC_RESULT__AFMT_AUDIO_CRC_DONE__SHIFT 0x0
+#define AFMT_AUDIO_CRC_RESULT__AFMT_AUDIO_CRC_MASK 0xffffff00
+#define AFMT_AUDIO_CRC_RESULT__AFMT_AUDIO_CRC__SHIFT 0x8
+#define AFMT_STATUS__AFMT_AUDIO_ENABLE_MASK 0x10
+#define AFMT_STATUS__AFMT_AUDIO_ENABLE__SHIFT 0x4
+#define AFMT_STATUS__AFMT_AZ_HBR_ENABLE_MASK 0x100
+#define AFMT_STATUS__AFMT_AZ_HBR_ENABLE__SHIFT 0x8
+#define AFMT_STATUS__AFMT_AUDIO_FIFO_OVERFLOW_MASK 0x1000000
+#define AFMT_STATUS__AFMT_AUDIO_FIFO_OVERFLOW__SHIFT 0x18
+#define AFMT_STATUS__AFMT_AZ_AUDIO_ENABLE_CHG_MASK 0x40000000
+#define AFMT_STATUS__AFMT_AZ_AUDIO_ENABLE_CHG__SHIFT 0x1e
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_AUDIO_SAMPLE_SEND_MASK 0x1
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_AUDIO_SAMPLE_SEND__SHIFT 0x0
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_RESET_FIFO_WHEN_AUDIO_DIS_MASK 0x800
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_RESET_FIFO_WHEN_AUDIO_DIS__SHIFT 0xb
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_AUDIO_TEST_EN_MASK 0x1000
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_AUDIO_TEST_EN__SHIFT 0xc
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_AUDIO_TEST_MODE_MASK 0x4000
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_AUDIO_TEST_MODE__SHIFT 0xe
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_AUDIO_FIFO_OVERFLOW_ACK_MASK 0x800000
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_AUDIO_FIFO_OVERFLOW_ACK__SHIFT 0x17
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_AUDIO_CHANNEL_SWAP_MASK 0x1000000
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_AUDIO_CHANNEL_SWAP__SHIFT 0x18
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_60958_CS_UPDATE_MASK 0x4000000
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_60958_CS_UPDATE__SHIFT 0x1a
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_AZ_AUDIO_ENABLE_CHG_ACK_MASK 0x40000000
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_AZ_AUDIO_ENABLE_CHG_ACK__SHIFT 0x1e
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_BLANK_TEST_DATA_ON_ENC_ENB_MASK 0x80000000
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_BLANK_TEST_DATA_ON_ENC_ENB__SHIFT 0x1f
+#define AFMT_VBI_PACKET_CONTROL__AFMT_GENERIC0_UPDATE_MASK 0x4
+#define AFMT_VBI_PACKET_CONTROL__AFMT_GENERIC0_UPDATE__SHIFT 0x2
+#define AFMT_VBI_PACKET_CONTROL__AFMT_GENERIC2_UPDATE_MASK 0x8
+#define AFMT_VBI_PACKET_CONTROL__AFMT_GENERIC2_UPDATE__SHIFT 0x3
+#define AFMT_VBI_PACKET_CONTROL__AFMT_GENERIC_INDEX_MASK 0xc0000000
+#define AFMT_VBI_PACKET_CONTROL__AFMT_GENERIC_INDEX__SHIFT 0x1e
+#define AFMT_INFOFRAME_CONTROL0__AFMT_AUDIO_INFO_SOURCE_MASK 0x40
+#define AFMT_INFOFRAME_CONTROL0__AFMT_AUDIO_INFO_SOURCE__SHIFT 0x6
+#define AFMT_INFOFRAME_CONTROL0__AFMT_AUDIO_INFO_UPDATE_MASK 0x80
+#define AFMT_INFOFRAME_CONTROL0__AFMT_AUDIO_INFO_UPDATE__SHIFT 0x7
+#define AFMT_INFOFRAME_CONTROL0__AFMT_MPEG_INFO_UPDATE_MASK 0x400
+#define AFMT_INFOFRAME_CONTROL0__AFMT_MPEG_INFO_UPDATE__SHIFT 0xa
+#define AFMT_AUDIO_SRC_CONTROL__AFMT_AUDIO_SRC_SELECT_MASK 0x7
+#define AFMT_AUDIO_SRC_CONTROL__AFMT_AUDIO_SRC_SELECT__SHIFT 0x0
+#define AFMT_AUDIO_DBG_DTO_CNTL__AFMT_AUDIO_DTO_FS_DIV_SEL_MASK 0x7
+#define AFMT_AUDIO_DBG_DTO_CNTL__AFMT_AUDIO_DTO_FS_DIV_SEL__SHIFT 0x0
+#define AFMT_AUDIO_DBG_DTO_CNTL__AFMT_AUDIO_DTO_DBG_BASE_MASK 0x100
+#define AFMT_AUDIO_DBG_DTO_CNTL__AFMT_AUDIO_DTO_DBG_BASE__SHIFT 0x8
+#define AFMT_AUDIO_DBG_DTO_CNTL__AFMT_AUDIO_DTO_DBG_MULTI_MASK 0x7000
+#define AFMT_AUDIO_DBG_DTO_CNTL__AFMT_AUDIO_DTO_DBG_MULTI__SHIFT 0xc
+#define AFMT_AUDIO_DBG_DTO_CNTL__AFMT_AUDIO_DTO_DBG_DIV_MASK 0x70000
+#define AFMT_AUDIO_DBG_DTO_CNTL__AFMT_AUDIO_DTO_DBG_DIV__SHIFT 0x10
+#define AFMT_CNTL__AFMT_AUDIO_CLOCK_EN_MASK 0x1
+#define AFMT_CNTL__AFMT_AUDIO_CLOCK_EN__SHIFT 0x0
+#define AFMT_CNTL__AFMT_AUDIO_CLOCK_ON_MASK 0x100
+#define AFMT_CNTL__AFMT_AUDIO_CLOCK_ON__SHIFT 0x8
+#define DIG_BE_CNTL__DIG_DUAL_LINK_ENABLE_MASK 0x1
+#define DIG_BE_CNTL__DIG_DUAL_LINK_ENABLE__SHIFT 0x0
+#define DIG_BE_CNTL__DIG_SWAP_MASK 0x2
+#define DIG_BE_CNTL__DIG_SWAP__SHIFT 0x1
+#define DIG_BE_CNTL__DIG_RB_SWITCH_EN_MASK 0x4
+#define DIG_BE_CNTL__DIG_RB_SWITCH_EN__SHIFT 0x2
+#define DIG_BE_CNTL__DIG_FE_SOURCE_SELECT_MASK 0x7f00
+#define DIG_BE_CNTL__DIG_FE_SOURCE_SELECT__SHIFT 0x8
+#define DIG_BE_CNTL__DIG_MODE_MASK 0x70000
+#define DIG_BE_CNTL__DIG_MODE__SHIFT 0x10
+#define DIG_BE_CNTL__DIG_HPD_SELECT_MASK 0x70000000
+#define DIG_BE_CNTL__DIG_HPD_SELECT__SHIFT 0x1c
+#define DIG_BE_EN_CNTL__DIG_ENABLE_MASK 0x1
+#define DIG_BE_EN_CNTL__DIG_ENABLE__SHIFT 0x0
+#define DIG_BE_EN_CNTL__DIG_SYMCLK_BE_ON_MASK 0x100
+#define DIG_BE_EN_CNTL__DIG_SYMCLK_BE_ON__SHIFT 0x8
+#define TMDS_CNTL__TMDS_SYNC_PHASE_MASK 0x1
+#define TMDS_CNTL__TMDS_SYNC_PHASE__SHIFT 0x0
+#define TMDS_CONTROL_CHAR__TMDS_CONTROL_CHAR0_OUT_EN_MASK 0x1
+#define TMDS_CONTROL_CHAR__TMDS_CONTROL_CHAR0_OUT_EN__SHIFT 0x0
+#define TMDS_CONTROL_CHAR__TMDS_CONTROL_CHAR1_OUT_EN_MASK 0x2
+#define TMDS_CONTROL_CHAR__TMDS_CONTROL_CHAR1_OUT_EN__SHIFT 0x1
+#define TMDS_CONTROL_CHAR__TMDS_CONTROL_CHAR2_OUT_EN_MASK 0x4
+#define TMDS_CONTROL_CHAR__TMDS_CONTROL_CHAR2_OUT_EN__SHIFT 0x2
+#define TMDS_CONTROL_CHAR__TMDS_CONTROL_CHAR3_OUT_EN_MASK 0x8
+#define TMDS_CONTROL_CHAR__TMDS_CONTROL_CHAR3_OUT_EN__SHIFT 0x3
+#define TMDS_CONTROL0_FEEDBACK__TMDS_CONTROL0_FEEDBACK_SELECT_MASK 0x3
+#define TMDS_CONTROL0_FEEDBACK__TMDS_CONTROL0_FEEDBACK_SELECT__SHIFT 0x0
+#define TMDS_CONTROL0_FEEDBACK__TMDS_CONTROL0_FEEDBACK_DELAY_MASK 0x300
+#define TMDS_CONTROL0_FEEDBACK__TMDS_CONTROL0_FEEDBACK_DELAY__SHIFT 0x8
+#define TMDS_STEREOSYNC_CTL_SEL__TMDS_STEREOSYNC_CTL_SEL_MASK 0x3
+#define TMDS_STEREOSYNC_CTL_SEL__TMDS_STEREOSYNC_CTL_SEL__SHIFT 0x0
+#define TMDS_SYNC_CHAR_PATTERN_0_1__TMDS_SYNC_CHAR_PATTERN0_MASK 0x3ff
+#define TMDS_SYNC_CHAR_PATTERN_0_1__TMDS_SYNC_CHAR_PATTERN0__SHIFT 0x0
+#define TMDS_SYNC_CHAR_PATTERN_0_1__TMDS_SYNC_CHAR_PATTERN1_MASK 0x3ff0000
+#define TMDS_SYNC_CHAR_PATTERN_0_1__TMDS_SYNC_CHAR_PATTERN1__SHIFT 0x10
+#define TMDS_SYNC_CHAR_PATTERN_2_3__TMDS_SYNC_CHAR_PATTERN2_MASK 0x3ff
+#define TMDS_SYNC_CHAR_PATTERN_2_3__TMDS_SYNC_CHAR_PATTERN2__SHIFT 0x0
+#define TMDS_SYNC_CHAR_PATTERN_2_3__TMDS_SYNC_CHAR_PATTERN3_MASK 0x3ff0000
+#define TMDS_SYNC_CHAR_PATTERN_2_3__TMDS_SYNC_CHAR_PATTERN3__SHIFT 0x10
+#define TMDS_DEBUG__TMDS_DEBUG_EN_MASK 0x1
+#define TMDS_DEBUG__TMDS_DEBUG_EN__SHIFT 0x0
+#define TMDS_DEBUG__TMDS_DEBUG_HSYNC_MASK 0x100
+#define TMDS_DEBUG__TMDS_DEBUG_HSYNC__SHIFT 0x8
+#define TMDS_DEBUG__TMDS_DEBUG_HSYNC_EN_MASK 0x200
+#define TMDS_DEBUG__TMDS_DEBUG_HSYNC_EN__SHIFT 0x9
+#define TMDS_DEBUG__TMDS_DEBUG_VSYNC_MASK 0x10000
+#define TMDS_DEBUG__TMDS_DEBUG_VSYNC__SHIFT 0x10
+#define TMDS_DEBUG__TMDS_DEBUG_VSYNC_EN_MASK 0x20000
+#define TMDS_DEBUG__TMDS_DEBUG_VSYNC_EN__SHIFT 0x11
+#define TMDS_DEBUG__TMDS_DEBUG_DE_MASK 0x1000000
+#define TMDS_DEBUG__TMDS_DEBUG_DE__SHIFT 0x18
+#define TMDS_DEBUG__TMDS_DEBUG_DE_EN_MASK 0x2000000
+#define TMDS_DEBUG__TMDS_DEBUG_DE_EN__SHIFT 0x19
+#define TMDS_CTL_BITS__TMDS_CTL0_MASK 0x1
+#define TMDS_CTL_BITS__TMDS_CTL0__SHIFT 0x0
+#define TMDS_CTL_BITS__TMDS_CTL1_MASK 0x100
+#define TMDS_CTL_BITS__TMDS_CTL1__SHIFT 0x8
+#define TMDS_CTL_BITS__TMDS_CTL2_MASK 0x10000
+#define TMDS_CTL_BITS__TMDS_CTL2__SHIFT 0x10
+#define TMDS_CTL_BITS__TMDS_CTL3_MASK 0x1000000
+#define TMDS_CTL_BITS__TMDS_CTL3__SHIFT 0x18
+#define TMDS_DCBALANCER_CONTROL__TMDS_DCBALANCER_EN_MASK 0x1
+#define TMDS_DCBALANCER_CONTROL__TMDS_DCBALANCER_EN__SHIFT 0x0
+#define TMDS_DCBALANCER_CONTROL__TMDS_SYNC_DCBAL_EN_MASK 0x70
+#define TMDS_DCBALANCER_CONTROL__TMDS_SYNC_DCBAL_EN__SHIFT 0x4
+#define TMDS_DCBALANCER_CONTROL__TMDS_DCBALANCER_TEST_EN_MASK 0x100
+#define TMDS_DCBALANCER_CONTROL__TMDS_DCBALANCER_TEST_EN__SHIFT 0x8
+#define TMDS_DCBALANCER_CONTROL__TMDS_DCBALANCER_TEST_IN_MASK 0xf0000
+#define TMDS_DCBALANCER_CONTROL__TMDS_DCBALANCER_TEST_IN__SHIFT 0x10
+#define TMDS_DCBALANCER_CONTROL__TMDS_DCBALANCER_FORCE_MASK 0x1000000
+#define TMDS_DCBALANCER_CONTROL__TMDS_DCBALANCER_FORCE__SHIFT 0x18
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_DATA_SEL_MASK 0xf
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_DATA_SEL__SHIFT 0x0
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_DATA_DELAY_MASK 0x70
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_DATA_DELAY__SHIFT 0x4
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_DATA_INVERT_MASK 0x80
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_DATA_INVERT__SHIFT 0x7
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_DATA_MODULATION_MASK 0x300
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_DATA_MODULATION__SHIFT 0x8
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_USE_FEEDBACK_PATH_MASK 0x400
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_USE_FEEDBACK_PATH__SHIFT 0xa
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_FB_SYNC_CONT_MASK 0x800
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_FB_SYNC_CONT__SHIFT 0xb
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_PATTERN_OUT_EN_MASK 0x1000
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_PATTERN_OUT_EN__SHIFT 0xc
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_DATA_SEL_MASK 0xf0000
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_DATA_SEL__SHIFT 0x10
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_DATA_DELAY_MASK 0x700000
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_DATA_DELAY__SHIFT 0x14
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_DATA_INVERT_MASK 0x800000
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_DATA_INVERT__SHIFT 0x17
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_DATA_MODULATION_MASK 0x3000000
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_DATA_MODULATION__SHIFT 0x18
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_USE_FEEDBACK_PATH_MASK 0x4000000
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_USE_FEEDBACK_PATH__SHIFT 0x1a
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_FB_SYNC_CONT_MASK 0x8000000
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_FB_SYNC_CONT__SHIFT 0x1b
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_PATTERN_OUT_EN_MASK 0x10000000
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_PATTERN_OUT_EN__SHIFT 0x1c
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_2BIT_COUNTER_EN_MASK 0x80000000
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_2BIT_COUNTER_EN__SHIFT 0x1f
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_DATA_SEL_MASK 0xf
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_DATA_SEL__SHIFT 0x0
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_DATA_DELAY_MASK 0x70
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_DATA_DELAY__SHIFT 0x4
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_DATA_INVERT_MASK 0x80
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_DATA_INVERT__SHIFT 0x7
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_DATA_MODULATION_MASK 0x300
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_DATA_MODULATION__SHIFT 0x8
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_USE_FEEDBACK_PATH_MASK 0x400
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_USE_FEEDBACK_PATH__SHIFT 0xa
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_FB_SYNC_CONT_MASK 0x800
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_FB_SYNC_CONT__SHIFT 0xb
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_PATTERN_OUT_EN_MASK 0x1000
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_PATTERN_OUT_EN__SHIFT 0xc
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_DATA_SEL_MASK 0xf0000
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_DATA_SEL__SHIFT 0x10
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_DATA_DELAY_MASK 0x700000
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_DATA_DELAY__SHIFT 0x14
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_DATA_INVERT_MASK 0x800000
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_DATA_INVERT__SHIFT 0x17
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_DATA_MODULATION_MASK 0x3000000
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_DATA_MODULATION__SHIFT 0x18
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_USE_FEEDBACK_PATH_MASK 0x4000000
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_USE_FEEDBACK_PATH__SHIFT 0x1a
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_FB_SYNC_CONT_MASK 0x8000000
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_FB_SYNC_CONT__SHIFT 0x1b
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_PATTERN_OUT_EN_MASK 0x10000000
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_PATTERN_OUT_EN__SHIFT 0x1c
+#define DIG_VERSION__DIG_TYPE_MASK 0x1
+#define DIG_VERSION__DIG_TYPE__SHIFT 0x0
+#define DIG_LANE_ENABLE__DIG_LANE0EN_MASK 0x1
+#define DIG_LANE_ENABLE__DIG_LANE0EN__SHIFT 0x0
+#define DIG_LANE_ENABLE__DIG_LANE1EN_MASK 0x2
+#define DIG_LANE_ENABLE__DIG_LANE1EN__SHIFT 0x1
+#define DIG_LANE_ENABLE__DIG_LANE2EN_MASK 0x4
+#define DIG_LANE_ENABLE__DIG_LANE2EN__SHIFT 0x2
+#define DIG_LANE_ENABLE__DIG_LANE3EN_MASK 0x8
+#define DIG_LANE_ENABLE__DIG_LANE3EN__SHIFT 0x3
+#define DIG_LANE_ENABLE__DIG_CLK_EN_MASK 0x100
+#define DIG_LANE_ENABLE__DIG_CLK_EN__SHIFT 0x8
+#define DIG_TEST_DEBUG_INDEX__DIG_TEST_DEBUG_INDEX_MASK 0xff
+#define DIG_TEST_DEBUG_INDEX__DIG_TEST_DEBUG_INDEX__SHIFT 0x0
+#define DIG_TEST_DEBUG_INDEX__DIG_TEST_DEBUG_WRITE_EN_MASK 0x100
+#define DIG_TEST_DEBUG_INDEX__DIG_TEST_DEBUG_WRITE_EN__SHIFT 0x8
+#define DIG_TEST_DEBUG_DATA__DIG_TEST_DEBUG_DATA_MASK 0xffffffff
+#define DIG_TEST_DEBUG_DATA__DIG_TEST_DEBUG_DATA__SHIFT 0x0
+#define DIG_FE_TEST_DEBUG_INDEX__DIG_FE_TEST_DEBUG_INDEX_MASK 0xff
+#define DIG_FE_TEST_DEBUG_INDEX__DIG_FE_TEST_DEBUG_INDEX__SHIFT 0x0
+#define DIG_FE_TEST_DEBUG_INDEX__DIG_FE_TEST_DEBUG_WRITE_EN_MASK 0x100
+#define DIG_FE_TEST_DEBUG_INDEX__DIG_FE_TEST_DEBUG_WRITE_EN__SHIFT 0x8
+#define DIG_FE_TEST_DEBUG_DATA__DIG_FE_TEST_DEBUG_DATA_MASK 0xffffffff
+#define DIG_FE_TEST_DEBUG_DATA__DIG_FE_TEST_DEBUG_DATA__SHIFT 0x0
+#define DMCU_CTRL__RESET_UC_MASK 0x1
+#define DMCU_CTRL__RESET_UC__SHIFT 0x0
+#define DMCU_CTRL__IGNORE_PWRMGT_MASK 0x2
+#define DMCU_CTRL__IGNORE_PWRMGT__SHIFT 0x1
+#define DMCU_CTRL__DISABLE_IRQ_TO_UC_MASK 0x4
+#define DMCU_CTRL__DISABLE_IRQ_TO_UC__SHIFT 0x2
+#define DMCU_CTRL__DISABLE_XIRQ_TO_UC_MASK 0x8
+#define DMCU_CTRL__DISABLE_XIRQ_TO_UC__SHIFT 0x3
+#define DMCU_CTRL__DMCU_ENABLE_MASK 0x10
+#define DMCU_CTRL__DMCU_ENABLE__SHIFT 0x4
+#define DMCU_CTRL__DMCU_DYN_CLK_GATING_EN_MASK 0x100
+#define DMCU_CTRL__DMCU_DYN_CLK_GATING_EN__SHIFT 0x8
+#define DMCU_CTRL__UC_REG_RD_TIMEOUT_MASK 0xffff0000
+#define DMCU_CTRL__UC_REG_RD_TIMEOUT__SHIFT 0x10
+#define DMCU_STATUS__UC_IN_RESET_MASK 0x1
+#define DMCU_STATUS__UC_IN_RESET__SHIFT 0x0
+#define DMCU_STATUS__UC_IN_WAIT_MODE_MASK 0x2
+#define DMCU_STATUS__UC_IN_WAIT_MODE__SHIFT 0x1
+#define DMCU_STATUS__UC_IN_STOP_MODE_MASK 0x4
+#define DMCU_STATUS__UC_IN_STOP_MODE__SHIFT 0x2
+#define DMCU_PC_START_ADDR__PC_START_ADDR_LSB_MASK 0xff
+#define DMCU_PC_START_ADDR__PC_START_ADDR_LSB__SHIFT 0x0
+#define DMCU_PC_START_ADDR__PC_START_ADDR_MSB_MASK 0xff00
+#define DMCU_PC_START_ADDR__PC_START_ADDR_MSB__SHIFT 0x8
+#define DMCU_FW_START_ADDR__FW_START_ADDR_LSB_MASK 0xff
+#define DMCU_FW_START_ADDR__FW_START_ADDR_LSB__SHIFT 0x0
+#define DMCU_FW_START_ADDR__FW_START_ADDR_MSB_MASK 0xff00
+#define DMCU_FW_START_ADDR__FW_START_ADDR_MSB__SHIFT 0x8
+#define DMCU_FW_END_ADDR__FW_END_ADDR_LSB_MASK 0xff
+#define DMCU_FW_END_ADDR__FW_END_ADDR_LSB__SHIFT 0x0
+#define DMCU_FW_END_ADDR__FW_END_ADDR_MSB_MASK 0xff00
+#define DMCU_FW_END_ADDR__FW_END_ADDR_MSB__SHIFT 0x8
+#define DMCU_FW_ISR_START_ADDR__FW_ISR_START_ADDR_LSB_MASK 0xff
+#define DMCU_FW_ISR_START_ADDR__FW_ISR_START_ADDR_LSB__SHIFT 0x0
+#define DMCU_FW_ISR_START_ADDR__FW_ISR_START_ADDR_MSB_MASK 0xff00
+#define DMCU_FW_ISR_START_ADDR__FW_ISR_START_ADDR_MSB__SHIFT 0x8
+#define DMCU_FW_CS_HI__FW_CHECKSUM_HI_MASK 0xffffffff
+#define DMCU_FW_CS_HI__FW_CHECKSUM_HI__SHIFT 0x0
+#define DMCU_FW_CS_LO__FW_CHECKSUM_LO_MASK 0xffffffff
+#define DMCU_FW_CS_LO__FW_CHECKSUM_LO__SHIFT 0x0
+#define DMCU_RAM_ACCESS_CTRL__ERAM_WR_ADDR_AUTO_INC_MASK 0x1
+#define DMCU_RAM_ACCESS_CTRL__ERAM_WR_ADDR_AUTO_INC__SHIFT 0x0
+#define DMCU_RAM_ACCESS_CTRL__ERAM_RD_ADDR_AUTO_INC_MASK 0x2
+#define DMCU_RAM_ACCESS_CTRL__ERAM_RD_ADDR_AUTO_INC__SHIFT 0x1
+#define DMCU_RAM_ACCESS_CTRL__IRAM_WR_ADDR_AUTO_INC_MASK 0x4
+#define DMCU_RAM_ACCESS_CTRL__IRAM_WR_ADDR_AUTO_INC__SHIFT 0x2
+#define DMCU_RAM_ACCESS_CTRL__IRAM_RD_ADDR_AUTO_INC_MASK 0x8
+#define DMCU_RAM_ACCESS_CTRL__IRAM_RD_ADDR_AUTO_INC__SHIFT 0x3
+#define DMCU_RAM_ACCESS_CTRL__ERAM_HOST_ACCESS_EN_MASK 0x10
+#define DMCU_RAM_ACCESS_CTRL__ERAM_HOST_ACCESS_EN__SHIFT 0x4
+#define DMCU_RAM_ACCESS_CTRL__IRAM_HOST_ACCESS_EN_MASK 0x20
+#define DMCU_RAM_ACCESS_CTRL__IRAM_HOST_ACCESS_EN__SHIFT 0x5
+#define DMCU_ERAM_WR_CTRL__ERAM_WR_ADDR_MASK 0xffff
+#define DMCU_ERAM_WR_CTRL__ERAM_WR_ADDR__SHIFT 0x0
+#define DMCU_ERAM_WR_CTRL__ERAM_WR_BE_MASK 0xf0000
+#define DMCU_ERAM_WR_CTRL__ERAM_WR_BE__SHIFT 0x10
+#define DMCU_ERAM_WR_CTRL__ERAM_WR_BYTE_MODE_MASK 0x100000
+#define DMCU_ERAM_WR_CTRL__ERAM_WR_BYTE_MODE__SHIFT 0x14
+#define DMCU_ERAM_WR_DATA__ERAM_WR_DATA_MASK 0xffffffff
+#define DMCU_ERAM_WR_DATA__ERAM_WR_DATA__SHIFT 0x0
+#define DMCU_ERAM_RD_CTRL__ERAM_RD_ADDR_MASK 0xffff
+#define DMCU_ERAM_RD_CTRL__ERAM_RD_ADDR__SHIFT 0x0
+#define DMCU_ERAM_RD_CTRL__ERAM_RD_BE_MASK 0xf0000
+#define DMCU_ERAM_RD_CTRL__ERAM_RD_BE__SHIFT 0x10
+#define DMCU_ERAM_RD_CTRL__ERAM_RD_BYTE_MODE_MASK 0x100000
+#define DMCU_ERAM_RD_CTRL__ERAM_RD_BYTE_MODE__SHIFT 0x14
+#define DMCU_ERAM_RD_DATA__ERAM_RD_DATA_MASK 0xffffffff
+#define DMCU_ERAM_RD_DATA__ERAM_RD_DATA__SHIFT 0x0
+#define DMCU_IRAM_WR_CTRL__IRAM_WR_ADDR_MASK 0x3ff
+#define DMCU_IRAM_WR_CTRL__IRAM_WR_ADDR__SHIFT 0x0
+#define DMCU_IRAM_WR_DATA__IRAM_WR_DATA_MASK 0xff
+#define DMCU_IRAM_WR_DATA__IRAM_WR_DATA__SHIFT 0x0
+#define DMCU_IRAM_RD_CTRL__IRAM_RD_ADDR_MASK 0x3ff
+#define DMCU_IRAM_RD_CTRL__IRAM_RD_ADDR__SHIFT 0x0
+#define DMCU_IRAM_RD_DATA__IRAM_RD_DATA_MASK 0xff
+#define DMCU_IRAM_RD_DATA__IRAM_RD_DATA__SHIFT 0x0
+#define DMCU_EVENT_TRIGGER__GEN_SW_INT_TO_UC_MASK 0x1
+#define DMCU_EVENT_TRIGGER__GEN_SW_INT_TO_UC__SHIFT 0x0
+#define DMCU_EVENT_TRIGGER__UC_INTERNAL_INT_CODE_MASK 0x7f0000
+#define DMCU_EVENT_TRIGGER__UC_INTERNAL_INT_CODE__SHIFT 0x10
+#define DMCU_EVENT_TRIGGER__GEN_UC_INTERNAL_INT_TO_HOST_MASK 0x800000
+#define DMCU_EVENT_TRIGGER__GEN_UC_INTERNAL_INT_TO_HOST__SHIFT 0x17
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_IRQ_N_PIN_MASK 0x1
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_IRQ_N_PIN__SHIFT 0x0
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_XIRQ_N_PIN_MASK 0x2
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_XIRQ_N_PIN__SHIFT 0x1
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_SOFTWARE_INTERRUPT_MASK 0x4
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_SOFTWARE_INTERRUPT__SHIFT 0x2
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_ILLEGAL_OPCODE_TRAP_MASK 0x8
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_ILLEGAL_OPCODE_TRAP__SHIFT 0x3
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_OUTPUT_COMPARE_4_MASK 0x10
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_OUTPUT_COMPARE_4__SHIFT 0x4
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_OUTPUT_COMPARE_3_MASK 0x20
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_OUTPUT_COMPARE_3__SHIFT 0x5
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_OUTPUT_COMPARE_2_MASK 0x40
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_OUTPUT_COMPARE_2__SHIFT 0x6
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_OUTPUT_COMPARE_1_MASK 0x80
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_OUTPUT_COMPARE_1__SHIFT 0x7
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_OVERFLOW_MASK 0x100
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_OVERFLOW__SHIFT 0x8
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_REAL_TIME_INTERRUPT_MASK 0x200
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_REAL_TIME_INTERRUPT__SHIFT 0x9
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_INPUT_CAPTURE_4_OUTPUT_COMPARE_5_MASK 0x400
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_INPUT_CAPTURE_4_OUTPUT_COMPARE_5__SHIFT 0xa
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_INPUT_CAPTURE_3_MASK 0x800
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_INPUT_CAPTURE_3__SHIFT 0xb
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_INPUT_CAPTURE_2_MASK 0x1000
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_INPUT_CAPTURE_2__SHIFT 0xc
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_INPUT_CAPTURE_1_MASK 0x2000
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_INPUT_CAPTURE_1__SHIFT 0xd
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_PULSE_ACCUMULATOR_INPUT_EDGE_MASK 0x4000
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_PULSE_ACCUMULATOR_INPUT_EDGE__SHIFT 0xe
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_PULSE_ACCUMULATOR_OVERFLOW_MASK 0x8000
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_PULSE_ACCUMULATOR_OVERFLOW__SHIFT 0xf
+#define DMCU_SS_INTERRUPT_CNTL_STATUS__STATIC_SCREEN1_INT_STATUS_MASK 0x2000
+#define DMCU_SS_INTERRUPT_CNTL_STATUS__STATIC_SCREEN1_INT_STATUS__SHIFT 0xd
+#define DMCU_SS_INTERRUPT_CNTL_STATUS__STATIC_SCREEN1_INT_OCCURRED_MASK 0x4000
+#define DMCU_SS_INTERRUPT_CNTL_STATUS__STATIC_SCREEN1_INT_OCCURRED__SHIFT 0xe
+#define DMCU_SS_INTERRUPT_CNTL_STATUS__STATIC_SCREEN1_INT_CLEAR_MASK 0x4000
+#define DMCU_SS_INTERRUPT_CNTL_STATUS__STATIC_SCREEN1_INT_CLEAR__SHIFT 0xe
+#define DMCU_SS_INTERRUPT_CNTL_STATUS__STATIC_SCREEN2_INT_STATUS_MASK 0x8000
+#define DMCU_SS_INTERRUPT_CNTL_STATUS__STATIC_SCREEN2_INT_STATUS__SHIFT 0xf
+#define DMCU_SS_INTERRUPT_CNTL_STATUS__STATIC_SCREEN2_INT_OCCURRED_MASK 0x10000
+#define DMCU_SS_INTERRUPT_CNTL_STATUS__STATIC_SCREEN2_INT_OCCURRED__SHIFT 0x10
+#define DMCU_SS_INTERRUPT_CNTL_STATUS__STATIC_SCREEN2_INT_CLEAR_MASK 0x10000
+#define DMCU_SS_INTERRUPT_CNTL_STATUS__STATIC_SCREEN2_INT_CLEAR__SHIFT 0x10
+#define DMCU_SS_INTERRUPT_CNTL_STATUS__STATIC_SCREEN3_INT_STATUS_MASK 0x20000
+#define DMCU_SS_INTERRUPT_CNTL_STATUS__STATIC_SCREEN3_INT_STATUS__SHIFT 0x11
+#define DMCU_SS_INTERRUPT_CNTL_STATUS__STATIC_SCREEN3_INT_OCCURRED_MASK 0x40000
+#define DMCU_SS_INTERRUPT_CNTL_STATUS__STATIC_SCREEN3_INT_OCCURRED__SHIFT 0x12
+#define DMCU_SS_INTERRUPT_CNTL_STATUS__STATIC_SCREEN3_INT_CLEAR_MASK 0x40000
+#define DMCU_SS_INTERRUPT_CNTL_STATUS__STATIC_SCREEN3_INT_CLEAR__SHIFT 0x12
+#define DMCU_SS_INTERRUPT_CNTL_STATUS__STATIC_SCREEN4_INT_STATUS_MASK 0x80000
+#define DMCU_SS_INTERRUPT_CNTL_STATUS__STATIC_SCREEN4_INT_STATUS__SHIFT 0x13
+#define DMCU_SS_INTERRUPT_CNTL_STATUS__STATIC_SCREEN4_INT_OCCURRED_MASK 0x100000
+#define DMCU_SS_INTERRUPT_CNTL_STATUS__STATIC_SCREEN4_INT_OCCURRED__SHIFT 0x14
+#define DMCU_SS_INTERRUPT_CNTL_STATUS__STATIC_SCREEN4_INT_CLEAR_MASK 0x100000
+#define DMCU_SS_INTERRUPT_CNTL_STATUS__STATIC_SCREEN4_INT_CLEAR__SHIFT 0x14
+#define DMCU_SS_INTERRUPT_CNTL_STATUS__STATIC_SCREEN5_INT_STATUS_MASK 0x200000
+#define DMCU_SS_INTERRUPT_CNTL_STATUS__STATIC_SCREEN5_INT_STATUS__SHIFT 0x15
+#define DMCU_SS_INTERRUPT_CNTL_STATUS__STATIC_SCREEN5_INT_OCCURRED_MASK 0x400000
+#define DMCU_SS_INTERRUPT_CNTL_STATUS__STATIC_SCREEN5_INT_OCCURRED__SHIFT 0x16
+#define DMCU_SS_INTERRUPT_CNTL_STATUS__STATIC_SCREEN5_INT_CLEAR_MASK 0x400000
+#define DMCU_SS_INTERRUPT_CNTL_STATUS__STATIC_SCREEN5_INT_CLEAR__SHIFT 0x16
+#define DMCU_SS_INTERRUPT_CNTL_STATUS__STATIC_SCREEN6_INT_STATUS_MASK 0x800000
+#define DMCU_SS_INTERRUPT_CNTL_STATUS__STATIC_SCREEN6_INT_STATUS__SHIFT 0x17
+#define DMCU_SS_INTERRUPT_CNTL_STATUS__STATIC_SCREEN6_INT_OCCURRED_MASK 0x1000000
+#define DMCU_SS_INTERRUPT_CNTL_STATUS__STATIC_SCREEN6_INT_OCCURRED__SHIFT 0x18
+#define DMCU_SS_INTERRUPT_CNTL_STATUS__STATIC_SCREEN6_INT_CLEAR_MASK 0x1000000
+#define DMCU_SS_INTERRUPT_CNTL_STATUS__STATIC_SCREEN6_INT_CLEAR__SHIFT 0x18
+#define DMCU_INTERRUPT_STATUS__ABM1_HG_READY_INT_OCCURRED_MASK 0x1
+#define DMCU_INTERRUPT_STATUS__ABM1_HG_READY_INT_OCCURRED__SHIFT 0x0
+#define DMCU_INTERRUPT_STATUS__ABM1_HG_READY_INT_CLEAR_MASK 0x1
+#define DMCU_INTERRUPT_STATUS__ABM1_HG_READY_INT_CLEAR__SHIFT 0x0
+#define DMCU_INTERRUPT_STATUS__ABM1_LS_READY_INT_OCCURRED_MASK 0x2
+#define DMCU_INTERRUPT_STATUS__ABM1_LS_READY_INT_OCCURRED__SHIFT 0x1
+#define DMCU_INTERRUPT_STATUS__ABM1_LS_READY_INT_CLEAR_MASK 0x2
+#define DMCU_INTERRUPT_STATUS__ABM1_LS_READY_INT_CLEAR__SHIFT 0x1
+#define DMCU_INTERRUPT_STATUS__ABM1_BL_UPDATE_INT_OCCURRED_MASK 0x4
+#define DMCU_INTERRUPT_STATUS__ABM1_BL_UPDATE_INT_OCCURRED__SHIFT 0x2
+#define DMCU_INTERRUPT_STATUS__ABM1_BL_UPDATE_INT_CLEAR_MASK 0x4
+#define DMCU_INTERRUPT_STATUS__ABM1_BL_UPDATE_INT_CLEAR__SHIFT 0x2
+#define DMCU_INTERRUPT_STATUS__MCP_INT_OCCURRED_MASK 0x8
+#define DMCU_INTERRUPT_STATUS__MCP_INT_OCCURRED__SHIFT 0x3
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DSI_POWER_UP_INT_OCCURRED_MASK 0x10
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DSI_POWER_UP_INT_OCCURRED__SHIFT 0x4
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DSI_POWER_UP_INT_CLEAR_MASK 0x10
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DSI_POWER_UP_INT_CLEAR__SHIFT 0x4
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DSI_POWER_DOWN_INT_OCCURRED_MASK 0x20
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DSI_POWER_DOWN_INT_OCCURRED__SHIFT 0x5
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DSI_POWER_DOWN_INT_CLEAR_MASK 0x20
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DSI_POWER_DOWN_INT_CLEAR__SHIFT 0x5
+#define DMCU_INTERRUPT_STATUS__EXTERNAL_SW_INT_OCCURRED_MASK 0x100
+#define DMCU_INTERRUPT_STATUS__EXTERNAL_SW_INT_OCCURRED__SHIFT 0x8
+#define DMCU_INTERRUPT_STATUS__EXTERNAL_SW_INT_CLEAR_MASK 0x100
+#define DMCU_INTERRUPT_STATUS__EXTERNAL_SW_INT_CLEAR__SHIFT 0x8
+#define DMCU_INTERRUPT_STATUS__SCP_INT_OCCURRED_MASK 0x200
+#define DMCU_INTERRUPT_STATUS__SCP_INT_OCCURRED__SHIFT 0x9
+#define DMCU_INTERRUPT_STATUS__UC_INTERNAL_INT_OCCURRED_MASK 0x400
+#define DMCU_INTERRUPT_STATUS__UC_INTERNAL_INT_OCCURRED__SHIFT 0xa
+#define DMCU_INTERRUPT_STATUS__UC_INTERNAL_INT_CLEAR_MASK 0x400
+#define DMCU_INTERRUPT_STATUS__UC_INTERNAL_INT_CLEAR__SHIFT 0xa
+#define DMCU_INTERRUPT_STATUS__UC_REG_RD_TIMEOUT_INT_OCCURRED_MASK 0x800
+#define DMCU_INTERRUPT_STATUS__UC_REG_RD_TIMEOUT_INT_OCCURRED__SHIFT 0xb
+#define DMCU_INTERRUPT_STATUS__UC_REG_RD_TIMEOUT_INT_CLEAR_MASK 0x800
+#define DMCU_INTERRUPT_STATUS__UC_REG_RD_TIMEOUT_INT_CLEAR__SHIFT 0xb
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE0_POWER_UP_INT_OCCURRED_MASK 0x1000
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE0_POWER_UP_INT_OCCURRED__SHIFT 0xc
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE0_POWER_UP_INT_CLEAR_MASK 0x1000
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE0_POWER_UP_INT_CLEAR__SHIFT 0xc
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE1_POWER_UP_INT_OCCURRED_MASK 0x2000
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE1_POWER_UP_INT_OCCURRED__SHIFT 0xd
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE1_POWER_UP_INT_CLEAR_MASK 0x2000
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE1_POWER_UP_INT_CLEAR__SHIFT 0xd
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE2_POWER_UP_INT_OCCURRED_MASK 0x4000
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE2_POWER_UP_INT_OCCURRED__SHIFT 0xe
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE2_POWER_UP_INT_CLEAR_MASK 0x4000
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE2_POWER_UP_INT_CLEAR__SHIFT 0xe
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE3_POWER_UP_INT_OCCURRED_MASK 0x8000
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE3_POWER_UP_INT_OCCURRED__SHIFT 0xf
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE3_POWER_UP_INT_CLEAR_MASK 0x8000
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE3_POWER_UP_INT_CLEAR__SHIFT 0xf
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE4_POWER_UP_INT_OCCURRED_MASK 0x10000
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE4_POWER_UP_INT_OCCURRED__SHIFT 0x10
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE4_POWER_UP_INT_CLEAR_MASK 0x10000
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE4_POWER_UP_INT_CLEAR__SHIFT 0x10
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE5_POWER_UP_INT_OCCURRED_MASK 0x20000
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE5_POWER_UP_INT_OCCURRED__SHIFT 0x11
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE5_POWER_UP_INT_CLEAR_MASK 0x20000
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE5_POWER_UP_INT_CLEAR__SHIFT 0x11
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE0_POWER_DOWN_INT_OCCURRED_MASK 0x40000
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE0_POWER_DOWN_INT_OCCURRED__SHIFT 0x12
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE0_POWER_DOWN_INT_CLEAR_MASK 0x40000
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE0_POWER_DOWN_INT_CLEAR__SHIFT 0x12
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE1_POWER_DOWN_INT_OCCURRED_MASK 0x80000
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE1_POWER_DOWN_INT_OCCURRED__SHIFT 0x13
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE1_POWER_DOWN_INT_CLEAR_MASK 0x80000
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE1_POWER_DOWN_INT_CLEAR__SHIFT 0x13
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE2_POWER_DOWN_INT_OCCURRED_MASK 0x100000
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE2_POWER_DOWN_INT_OCCURRED__SHIFT 0x14
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE2_POWER_DOWN_INT_CLEAR_MASK 0x100000
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE2_POWER_DOWN_INT_CLEAR__SHIFT 0x14
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE3_POWER_DOWN_INT_OCCURRED_MASK 0x200000
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE3_POWER_DOWN_INT_OCCURRED__SHIFT 0x15
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE3_POWER_DOWN_INT_CLEAR_MASK 0x200000
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE3_POWER_DOWN_INT_CLEAR__SHIFT 0x15
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE4_POWER_DOWN_INT_OCCURRED_MASK 0x400000
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE4_POWER_DOWN_INT_OCCURRED__SHIFT 0x16
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE4_POWER_DOWN_INT_CLEAR_MASK 0x400000
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE4_POWER_DOWN_INT_CLEAR__SHIFT 0x16
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE5_POWER_DOWN_INT_OCCURRED_MASK 0x800000
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE5_POWER_DOWN_INT_OCCURRED__SHIFT 0x17
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE5_POWER_DOWN_INT_CLEAR_MASK 0x800000
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE5_POWER_DOWN_INT_CLEAR__SHIFT 0x17
+#define DMCU_INTERRUPT_STATUS__VBLANK1_INT_OCCURRED_MASK 0x1000000
+#define DMCU_INTERRUPT_STATUS__VBLANK1_INT_OCCURRED__SHIFT 0x18
+#define DMCU_INTERRUPT_STATUS__VBLANK1_INT_CLEAR_MASK 0x1000000
+#define DMCU_INTERRUPT_STATUS__VBLANK1_INT_CLEAR__SHIFT 0x18
+#define DMCU_INTERRUPT_STATUS__VBLANK2_INT_OCCURRED_MASK 0x2000000
+#define DMCU_INTERRUPT_STATUS__VBLANK2_INT_OCCURRED__SHIFT 0x19
+#define DMCU_INTERRUPT_STATUS__VBLANK2_INT_CLEAR_MASK 0x2000000
+#define DMCU_INTERRUPT_STATUS__VBLANK2_INT_CLEAR__SHIFT 0x19
+#define DMCU_INTERRUPT_STATUS__VBLANK3_INT_OCCURRED_MASK 0x4000000
+#define DMCU_INTERRUPT_STATUS__VBLANK3_INT_OCCURRED__SHIFT 0x1a
+#define DMCU_INTERRUPT_STATUS__VBLANK3_INT_CLEAR_MASK 0x4000000
+#define DMCU_INTERRUPT_STATUS__VBLANK3_INT_CLEAR__SHIFT 0x1a
+#define DMCU_INTERRUPT_STATUS__VBLANK4_INT_OCCURRED_MASK 0x8000000
+#define DMCU_INTERRUPT_STATUS__VBLANK4_INT_OCCURRED__SHIFT 0x1b
+#define DMCU_INTERRUPT_STATUS__VBLANK4_INT_CLEAR_MASK 0x8000000
+#define DMCU_INTERRUPT_STATUS__VBLANK4_INT_CLEAR__SHIFT 0x1b
+#define DMCU_INTERRUPT_STATUS__VBLANK5_INT_OCCURRED_MASK 0x10000000
+#define DMCU_INTERRUPT_STATUS__VBLANK5_INT_OCCURRED__SHIFT 0x1c
+#define DMCU_INTERRUPT_STATUS__VBLANK5_INT_CLEAR_MASK 0x10000000
+#define DMCU_INTERRUPT_STATUS__VBLANK5_INT_CLEAR__SHIFT 0x1c
+#define DMCU_INTERRUPT_STATUS__VBLANK6_INT_OCCURRED_MASK 0x20000000
+#define DMCU_INTERRUPT_STATUS__VBLANK6_INT_OCCURRED__SHIFT 0x1d
+#define DMCU_INTERRUPT_STATUS__VBLANK6_INT_CLEAR_MASK 0x20000000
+#define DMCU_INTERRUPT_STATUS__VBLANK6_INT_CLEAR__SHIFT 0x1d
+#define DMCU_INTERRUPT_STATUS_1__DCPG_IHC_DCFEV0_POWER_UP_INT_OCCURRED_MASK 0x1
+#define DMCU_INTERRUPT_STATUS_1__DCPG_IHC_DCFEV0_POWER_UP_INT_OCCURRED__SHIFT 0x0
+#define DMCU_INTERRUPT_STATUS_1__DCPG_IHC_DCFEV0_POWER_UP_INT_CLEAR_MASK 0x1
+#define DMCU_INTERRUPT_STATUS_1__DCPG_IHC_DCFEV0_POWER_UP_INT_CLEAR__SHIFT 0x0
+#define DMCU_INTERRUPT_STATUS_1__DCPG_IHC_DCFEV1_POWER_UP_INT_OCCURRED_MASK 0x2
+#define DMCU_INTERRUPT_STATUS_1__DCPG_IHC_DCFEV1_POWER_UP_INT_OCCURRED__SHIFT 0x1
+#define DMCU_INTERRUPT_STATUS_1__DCPG_IHC_DCFEV1_POWER_UP_INT_CLEAR_MASK 0x2
+#define DMCU_INTERRUPT_STATUS_1__DCPG_IHC_DCFEV1_POWER_UP_INT_CLEAR__SHIFT 0x1
+#define DMCU_INTERRUPT_STATUS_1__DCPG_IHC_DCFEV0_POWER_DOWN_INT_OCCURRED_MASK 0x4
+#define DMCU_INTERRUPT_STATUS_1__DCPG_IHC_DCFEV0_POWER_DOWN_INT_OCCURRED__SHIFT 0x2
+#define DMCU_INTERRUPT_STATUS_1__DCPG_IHC_DCFEV0_POWER_DOWN_INT_CLEAR_MASK 0x4
+#define DMCU_INTERRUPT_STATUS_1__DCPG_IHC_DCFEV0_POWER_DOWN_INT_CLEAR__SHIFT 0x2
+#define DMCU_INTERRUPT_STATUS_1__DCPG_IHC_DCFEV1_POWER_DOWN_INT_OCCURRED_MASK 0x8
+#define DMCU_INTERRUPT_STATUS_1__DCPG_IHC_DCFEV1_POWER_DOWN_INT_OCCURRED__SHIFT 0x3
+#define DMCU_INTERRUPT_STATUS_1__DCPG_IHC_DCFEV1_POWER_DOWN_INT_CLEAR_MASK 0x8
+#define DMCU_INTERRUPT_STATUS_1__DCPG_IHC_DCFEV1_POWER_DOWN_INT_CLEAR__SHIFT 0x3
+#define DMCU_INTERRUPT_STATUS_1__DCFEV0_VBLANK_INT_OCCURRED_MASK 0x10
+#define DMCU_INTERRUPT_STATUS_1__DCFEV0_VBLANK_INT_OCCURRED__SHIFT 0x4
+#define DMCU_INTERRUPT_STATUS_1__DCFEV0_VBLANK_INT_CLEAR_MASK 0x10
+#define DMCU_INTERRUPT_STATUS_1__DCFEV0_VBLANK_INT_CLEAR__SHIFT 0x4
+#define DMCU_INTERRUPT_STATUS_1__DCFEV1_VBLANK_INT_OCCURRED_MASK 0x20
+#define DMCU_INTERRUPT_STATUS_1__DCFEV1_VBLANK_INT_OCCURRED__SHIFT 0x5
+#define DMCU_INTERRUPT_STATUS_1__DCFEV1_VBLANK_INT_CLEAR_MASK 0x20
+#define DMCU_INTERRUPT_STATUS_1__DCFEV1_VBLANK_INT_CLEAR__SHIFT 0x5
+#define DMCU_INTERRUPT_STATUS_1__DMCU_GENERIC_INTERRUPT_OCCURRED_MASK 0x2000
+#define DMCU_INTERRUPT_STATUS_1__DMCU_GENERIC_INTERRUPT_OCCURRED__SHIFT 0xd
+#define DMCU_INTERRUPT_STATUS_1__DMCU_GENERIC_INTERRUPT_CLEAR_MASK 0x2000
+#define DMCU_INTERRUPT_STATUS_1__DMCU_GENERIC_INTERRUPT_CLEAR__SHIFT 0xd
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__ABM1_HG_READY_INT_MASK_MASK 0x1
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__ABM1_HG_READY_INT_MASK__SHIFT 0x0
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__ABM1_LS_READY_INT_MASK_MASK 0x2
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__ABM1_LS_READY_INT_MASK__SHIFT 0x1
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__ABM1_BL_UPDATE_INT_MASK_MASK 0x4
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__ABM1_BL_UPDATE_INT_MASK__SHIFT 0x2
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__SCP_INT_MASK_MASK 0x200
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__SCP_INT_MASK__SHIFT 0x9
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__UC_INTERNAL_INT_MASK_MASK 0x400
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__UC_INTERNAL_INT_MASK__SHIFT 0xa
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__UC_REG_RD_TIMEOUT_INT_MASK_MASK 0x800
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__UC_REG_RD_TIMEOUT_INT_MASK__SHIFT 0xb
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__ABM1_HG_READY_INT_TO_UC_EN_MASK 0x1
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__ABM1_HG_READY_INT_TO_UC_EN__SHIFT 0x0
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__ABM1_LS_READY_INT_TO_UC_EN_MASK 0x2
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__ABM1_LS_READY_INT_TO_UC_EN__SHIFT 0x1
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__ABM1_BL_UPDATE_INT_TO_UC_EN_MASK 0x4
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__ABM1_BL_UPDATE_INT_TO_UC_EN__SHIFT 0x2
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__MCP_INT_TO_UC_EN_MASK 0x8
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__MCP_INT_TO_UC_EN__SHIFT 0x3
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DSI_POWER_UP_INT_TO_UC_EN_MASK 0x10
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DSI_POWER_UP_INT_TO_UC_EN__SHIFT 0x4
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DSI_POWER_DOWN_INT_TO_UC_EN_MASK 0x20
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DSI_POWER_DOWN_INT_TO_UC_EN__SHIFT 0x5
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__STATIC_SCREEN1_INT_TO_UC_EN_MASK 0x40
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__STATIC_SCREEN1_INT_TO_UC_EN__SHIFT 0x6
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__STATIC_SCREEN2_INT_TO_UC_EN_MASK 0x80
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__STATIC_SCREEN2_INT_TO_UC_EN__SHIFT 0x7
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__EXTERNAL_SW_INT_TO_UC_EN_MASK 0x100
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__EXTERNAL_SW_INT_TO_UC_EN__SHIFT 0x8
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__STATIC_SCREEN3_INT_TO_UC_EN_MASK 0x200
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__STATIC_SCREEN3_INT_TO_UC_EN__SHIFT 0x9
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__STATIC_SCREEN4_INT_TO_UC_EN_MASK 0x400
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__STATIC_SCREEN4_INT_TO_UC_EN__SHIFT 0xa
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__STATIC_SCREEN5_INT_TO_UC_EN_MASK 0x800
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__STATIC_SCREEN5_INT_TO_UC_EN__SHIFT 0xb
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE0_POWER_UP_INT_TO_UC_EN_MASK 0x1000
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE0_POWER_UP_INT_TO_UC_EN__SHIFT 0xc
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE1_POWER_UP_INT_TO_UC_EN_MASK 0x2000
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE1_POWER_UP_INT_TO_UC_EN__SHIFT 0xd
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE2_POWER_UP_INT_TO_UC_EN_MASK 0x4000
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE2_POWER_UP_INT_TO_UC_EN__SHIFT 0xe
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE3_POWER_UP_INT_TO_UC_EN_MASK 0x8000
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE3_POWER_UP_INT_TO_UC_EN__SHIFT 0xf
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE4_POWER_UP_INT_TO_UC_EN_MASK 0x10000
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE4_POWER_UP_INT_TO_UC_EN__SHIFT 0x10
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE5_POWER_UP_INT_TO_UC_EN_MASK 0x20000
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE5_POWER_UP_INT_TO_UC_EN__SHIFT 0x11
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE0_POWER_DOWN_INT_TO_UC_EN_MASK 0x40000
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE0_POWER_DOWN_INT_TO_UC_EN__SHIFT 0x12
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE1_POWER_DOWN_INT_TO_UC_EN_MASK 0x80000
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE1_POWER_DOWN_INT_TO_UC_EN__SHIFT 0x13
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE2_POWER_DOWN_INT_TO_UC_EN_MASK 0x100000
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE2_POWER_DOWN_INT_TO_UC_EN__SHIFT 0x14
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE3_POWER_DOWN_INT_TO_UC_EN_MASK 0x200000
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE3_POWER_DOWN_INT_TO_UC_EN__SHIFT 0x15
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE4_POWER_DOWN_INT_TO_UC_EN_MASK 0x400000
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE4_POWER_DOWN_INT_TO_UC_EN__SHIFT 0x16
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE5_POWER_DOWN_INT_TO_UC_EN_MASK 0x800000
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE5_POWER_DOWN_INT_TO_UC_EN__SHIFT 0x17
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__VBLANK1_INT_TO_UC_EN_MASK 0x1000000
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__VBLANK1_INT_TO_UC_EN__SHIFT 0x18
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__VBLANK2_INT_TO_UC_EN_MASK 0x2000000
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__VBLANK2_INT_TO_UC_EN__SHIFT 0x19
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__VBLANK3_INT_TO_UC_EN_MASK 0x4000000
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__VBLANK3_INT_TO_UC_EN__SHIFT 0x1a
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__VBLANK4_INT_TO_UC_EN_MASK 0x8000000
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__VBLANK4_INT_TO_UC_EN__SHIFT 0x1b
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__VBLANK5_INT_TO_UC_EN_MASK 0x10000000
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__VBLANK5_INT_TO_UC_EN__SHIFT 0x1c
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__VBLANK6_INT_TO_UC_EN_MASK 0x20000000
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__VBLANK6_INT_TO_UC_EN__SHIFT 0x1d
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__STATIC_SCREEN6_INT_TO_UC_EN_MASK 0x40000000
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__STATIC_SCREEN6_INT_TO_UC_EN__SHIFT 0x1e
+#define DMCU_INTERRUPT_TO_UC_EN_MASK_1__DCPG_IHC_DCFEV0_POWER_UP_INT_TO_UC_EN_MASK 0x1
+#define DMCU_INTERRUPT_TO_UC_EN_MASK_1__DCPG_IHC_DCFEV0_POWER_UP_INT_TO_UC_EN__SHIFT 0x0
+#define DMCU_INTERRUPT_TO_UC_EN_MASK_1__DCPG_IHC_DCFEV0_POWER_DOWN_INT_TO_UC_EN_MASK 0x2
+#define DMCU_INTERRUPT_TO_UC_EN_MASK_1__DCPG_IHC_DCFEV0_POWER_DOWN_INT_TO_UC_EN__SHIFT 0x1
+#define DMCU_INTERRUPT_TO_UC_EN_MASK_1__DCFEV0_VBLANK_INT_TO_UC_EN_MASK 0x4
+#define DMCU_INTERRUPT_TO_UC_EN_MASK_1__DCFEV0_VBLANK_INT_TO_UC_EN__SHIFT 0x2
+#define DMCU_INTERRUPT_TO_UC_EN_MASK_1__DCPG_IHC_DCFEV1_POWER_UP_INT_TO_UC_EN_MASK 0x8
+#define DMCU_INTERRUPT_TO_UC_EN_MASK_1__DCPG_IHC_DCFEV1_POWER_UP_INT_TO_UC_EN__SHIFT 0x3
+#define DMCU_INTERRUPT_TO_UC_EN_MASK_1__DCPG_IHC_DCFEV1_POWER_DOWN_INT_TO_UC_EN_MASK 0x10
+#define DMCU_INTERRUPT_TO_UC_EN_MASK_1__DCPG_IHC_DCFEV1_POWER_DOWN_INT_TO_UC_EN__SHIFT 0x4
+#define DMCU_INTERRUPT_TO_UC_EN_MASK_1__DCFEV1_VBLANK_INT_TO_UC_EN_MASK 0x20
+#define DMCU_INTERRUPT_TO_UC_EN_MASK_1__DCFEV1_VBLANK_INT_TO_UC_EN__SHIFT 0x5
+#define DMCU_INTERRUPT_TO_UC_EN_MASK_1__DMCU_GENERIC_INT_TO_UC_EN_MASK 0x2000
+#define DMCU_INTERRUPT_TO_UC_EN_MASK_1__DMCU_GENERIC_INT_TO_UC_EN__SHIFT 0xd
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__ABM1_HG_READY_INT_XIRQ_IRQ_SEL_MASK 0x1
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__ABM1_HG_READY_INT_XIRQ_IRQ_SEL__SHIFT 0x0
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__ABM1_LS_READY_INT_XIRQ_IRQ_SEL_MASK 0x2
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__ABM1_LS_READY_INT_XIRQ_IRQ_SEL__SHIFT 0x1
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__ABM1_BL_UPDATE_INT_XIRQ_IRQ_SEL_MASK 0x4
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__ABM1_BL_UPDATE_INT_XIRQ_IRQ_SEL__SHIFT 0x2
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__MCP_INT_XIRQ_IRQ_SEL_MASK 0x8
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__MCP_INT_XIRQ_IRQ_SEL__SHIFT 0x3
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DSI_POWER_UP_INT_XIRQ_IRQ_SEL_MASK 0x10
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DSI_POWER_UP_INT_XIRQ_IRQ_SEL__SHIFT 0x4
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DSI_POWER_DOWN_INT_XIRQ_IRQ_SEL_MASK 0x20
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DSI_POWER_DOWN_INT_XIRQ_IRQ_SEL__SHIFT 0x5
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__STATIC_SCREEN1_INT_XIRQ_IRQ_SEL_MASK 0x40
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__STATIC_SCREEN1_INT_XIRQ_IRQ_SEL__SHIFT 0x6
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__STATIC_SCREEN2_INT_XIRQ_IRQ_SEL_MASK 0x80
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__STATIC_SCREEN2_INT_XIRQ_IRQ_SEL__SHIFT 0x7
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__EXTERNAL_SW_INT_XIRQ_IRQ_SEL_MASK 0x100
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__EXTERNAL_SW_INT_XIRQ_IRQ_SEL__SHIFT 0x8
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__STATIC_SCREEN3_INT_XIRQ_IRQ_SEL_MASK 0x200
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__STATIC_SCREEN3_INT_XIRQ_IRQ_SEL__SHIFT 0x9
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__STATIC_SCREEN4_INT_XIRQ_IRQ_SEL_MASK 0x400
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__STATIC_SCREEN4_INT_XIRQ_IRQ_SEL__SHIFT 0xa
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__STATIC_SCREEN5_INT_XIRQ_IRQ_SEL_MASK 0x800
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__STATIC_SCREEN5_INT_XIRQ_IRQ_SEL__SHIFT 0xb
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE0_POWER_UP_INT_XIRQ_IRQ_SEL_MASK 0x1000
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE0_POWER_UP_INT_XIRQ_IRQ_SEL__SHIFT 0xc
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE1_POWER_UP_INT_XIRQ_IRQ_SEL_MASK 0x2000
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE1_POWER_UP_INT_XIRQ_IRQ_SEL__SHIFT 0xd
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE2_POWER_UP_INT_XIRQ_IRQ_SEL_MASK 0x4000
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE2_POWER_UP_INT_XIRQ_IRQ_SEL__SHIFT 0xe
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE3_POWER_UP_INT_XIRQ_IRQ_SEL_MASK 0x8000
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE3_POWER_UP_INT_XIRQ_IRQ_SEL__SHIFT 0xf
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE4_POWER_UP_INT_XIRQ_IRQ_SEL_MASK 0x10000
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE4_POWER_UP_INT_XIRQ_IRQ_SEL__SHIFT 0x10
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE5_POWER_UP_INT_XIRQ_IRQ_SEL_MASK 0x20000
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE5_POWER_UP_INT_XIRQ_IRQ_SEL__SHIFT 0x11
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE0_POWER_DOWN_INT_XIRQ_IRQ_SEL_MASK 0x40000
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE0_POWER_DOWN_INT_XIRQ_IRQ_SEL__SHIFT 0x12
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE1_POWER_DOWN_INT_XIRQ_IRQ_SEL_MASK 0x80000
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE1_POWER_DOWN_INT_XIRQ_IRQ_SEL__SHIFT 0x13
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE2_POWER_DOWN_INT_XIRQ_IRQ_SEL_MASK 0x100000
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE2_POWER_DOWN_INT_XIRQ_IRQ_SEL__SHIFT 0x14
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE3_POWER_DOWN_INT_XIRQ_IRQ_SEL_MASK 0x200000
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE3_POWER_DOWN_INT_XIRQ_IRQ_SEL__SHIFT 0x15
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE4_POWER_DOWN_INT_XIRQ_IRQ_SEL_MASK 0x400000
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE4_POWER_DOWN_INT_XIRQ_IRQ_SEL__SHIFT 0x16
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE5_POWER_DOWN_INT_XIRQ_IRQ_SEL_MASK 0x800000
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE5_POWER_DOWN_INT_XIRQ_IRQ_SEL__SHIFT 0x17
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__VBLANK1_INT_XIRQ_IRQ_SEL_MASK 0x1000000
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__VBLANK1_INT_XIRQ_IRQ_SEL__SHIFT 0x18
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__VBLANK2_INT_XIRQ_IRQ_SEL_MASK 0x2000000
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__VBLANK2_INT_XIRQ_IRQ_SEL__SHIFT 0x19
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__VBLANK3_INT_XIRQ_IRQ_SEL_MASK 0x4000000
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__VBLANK3_INT_XIRQ_IRQ_SEL__SHIFT 0x1a
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__VBLANK4_INT_XIRQ_IRQ_SEL_MASK 0x8000000
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__VBLANK4_INT_XIRQ_IRQ_SEL__SHIFT 0x1b
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__VBLANK5_INT_XIRQ_IRQ_SEL_MASK 0x10000000
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__VBLANK5_INT_XIRQ_IRQ_SEL__SHIFT 0x1c
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__VBLANK6_INT_XIRQ_IRQ_SEL_MASK 0x20000000
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__VBLANK6_INT_XIRQ_IRQ_SEL__SHIFT 0x1d
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__STATIC_SCREEN6_INT_XIRQ_IRQ_SEL_MASK 0x40000000
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__STATIC_SCREEN6_INT_XIRQ_IRQ_SEL__SHIFT 0x1e
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL_1__DCPG_IHC_DCFEV0_POWER_UP_INT_XIRQ_IRQ_SEL_MASK 0x1
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL_1__DCPG_IHC_DCFEV0_POWER_UP_INT_XIRQ_IRQ_SEL__SHIFT 0x0
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL_1__DCPG_IHC_DCFEV0_POWER_DOWN_INT_XIRQ_IRQ_SEL_MASK 0x2
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL_1__DCPG_IHC_DCFEV0_POWER_DOWN_INT_XIRQ_IRQ_SEL__SHIFT 0x1
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL_1__DCFEV0_VBLANK_INT_XIRQ_IRQ_SEL_MASK 0x4
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL_1__DCFEV0_VBLANK_INT_XIRQ_IRQ_SEL__SHIFT 0x2
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL_1__DCPG_IHC_DCFEV1_POWER_UP_INT_XIRQ_IRQ_SEL_MASK 0x8
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL_1__DCPG_IHC_DCFEV1_POWER_UP_INT_XIRQ_IRQ_SEL__SHIFT 0x3
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL_1__DCPG_IHC_DCFEV1_POWER_DOWN_INT_XIRQ_IRQ_SEL_MASK 0x10
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL_1__DCPG_IHC_DCFEV1_POWER_DOWN_INT_XIRQ_IRQ_SEL__SHIFT 0x4
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL_1__DCFEV1_VBLANK_INT_XIRQ_IRQ_SEL_MASK 0x20
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL_1__DCFEV1_VBLANK_INT_XIRQ_IRQ_SEL__SHIFT 0x5
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL_1__DMCU_GENERIC_INT_XIRQ_IRQ_SEL_MASK 0x2000
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL_1__DMCU_GENERIC_INT_XIRQ_IRQ_SEL__SHIFT 0xd
+#define DC_DMCU_SCRATCH__DMCU_SCRATCH_MASK 0xffffffff
+#define DC_DMCU_SCRATCH__DMCU_SCRATCH__SHIFT 0x0
+#define DMCU_INT_CNT__DMCU_ABM1_HG_READY_INT_CNT_MASK 0xff
+#define DMCU_INT_CNT__DMCU_ABM1_HG_READY_INT_CNT__SHIFT 0x0
+#define DMCU_INT_CNT__DMCU_ABM1_LS_READY_INT_CNT_MASK 0xff00
+#define DMCU_INT_CNT__DMCU_ABM1_LS_READY_INT_CNT__SHIFT 0x8
+#define DMCU_INT_CNT__DMCU_ABM1_BL_UPDATE_INT_CNT_MASK 0xff0000
+#define DMCU_INT_CNT__DMCU_ABM1_BL_UPDATE_INT_CNT__SHIFT 0x10
+#define DMCU_FW_CHECKSUM_SMPL_BYTE_POS__DMCU_FW_CHECKSUM_LO_SMPL_BYTE_POS_MASK 0x3
+#define DMCU_FW_CHECKSUM_SMPL_BYTE_POS__DMCU_FW_CHECKSUM_LO_SMPL_BYTE_POS__SHIFT 0x0
+#define DMCU_FW_CHECKSUM_SMPL_BYTE_POS__DMCU_FW_CHECKSUM_HI_SMPL_BYTE_POS_MASK 0xc
+#define DMCU_FW_CHECKSUM_SMPL_BYTE_POS__DMCU_FW_CHECKSUM_HI_SMPL_BYTE_POS__SHIFT 0x2
+#define DMCU_UC_CLK_GATING_CNTL__UC_IRAM_RD_DELAY_MASK 0x7
+#define DMCU_UC_CLK_GATING_CNTL__UC_IRAM_RD_DELAY__SHIFT 0x0
+#define DMCU_UC_CLK_GATING_CNTL__UC_ERAM_RD_DELAY_MASK 0x700
+#define DMCU_UC_CLK_GATING_CNTL__UC_ERAM_RD_DELAY__SHIFT 0x8
+#define DMCU_UC_CLK_GATING_CNTL__UC_RBBM_RD_CLK_GATING_EN_MASK 0x10000
+#define DMCU_UC_CLK_GATING_CNTL__UC_RBBM_RD_CLK_GATING_EN__SHIFT 0x10
+#define MASTER_COMM_DATA_REG1__MASTER_COMM_DATA_REG1_BYTE0_MASK 0xff
+#define MASTER_COMM_DATA_REG1__MASTER_COMM_DATA_REG1_BYTE0__SHIFT 0x0
+#define MASTER_COMM_DATA_REG1__MASTER_COMM_DATA_REG1_BYTE1_MASK 0xff00
+#define MASTER_COMM_DATA_REG1__MASTER_COMM_DATA_REG1_BYTE1__SHIFT 0x8
+#define MASTER_COMM_DATA_REG1__MASTER_COMM_DATA_REG1_BYTE2_MASK 0xff0000
+#define MASTER_COMM_DATA_REG1__MASTER_COMM_DATA_REG1_BYTE2__SHIFT 0x10
+#define MASTER_COMM_DATA_REG1__MASTER_COMM_DATA_REG1_BYTE3_MASK 0xff000000
+#define MASTER_COMM_DATA_REG1__MASTER_COMM_DATA_REG1_BYTE3__SHIFT 0x18
+#define MASTER_COMM_DATA_REG2__MASTER_COMM_DATA_REG2_BYTE0_MASK 0xff
+#define MASTER_COMM_DATA_REG2__MASTER_COMM_DATA_REG2_BYTE0__SHIFT 0x0
+#define MASTER_COMM_DATA_REG2__MASTER_COMM_DATA_REG2_BYTE1_MASK 0xff00
+#define MASTER_COMM_DATA_REG2__MASTER_COMM_DATA_REG2_BYTE1__SHIFT 0x8
+#define MASTER_COMM_DATA_REG2__MASTER_COMM_DATA_REG2_BYTE2_MASK 0xff0000
+#define MASTER_COMM_DATA_REG2__MASTER_COMM_DATA_REG2_BYTE2__SHIFT 0x10
+#define MASTER_COMM_DATA_REG2__MASTER_COMM_DATA_REG2_BYTE3_MASK 0xff000000
+#define MASTER_COMM_DATA_REG2__MASTER_COMM_DATA_REG2_BYTE3__SHIFT 0x18
+#define MASTER_COMM_DATA_REG3__MASTER_COMM_DATA_REG3_BYTE0_MASK 0xff
+#define MASTER_COMM_DATA_REG3__MASTER_COMM_DATA_REG3_BYTE0__SHIFT 0x0
+#define MASTER_COMM_DATA_REG3__MASTER_COMM_DATA_REG3_BYTE1_MASK 0xff00
+#define MASTER_COMM_DATA_REG3__MASTER_COMM_DATA_REG3_BYTE1__SHIFT 0x8
+#define MASTER_COMM_DATA_REG3__MASTER_COMM_DATA_REG3_BYTE2_MASK 0xff0000
+#define MASTER_COMM_DATA_REG3__MASTER_COMM_DATA_REG3_BYTE2__SHIFT 0x10
+#define MASTER_COMM_DATA_REG3__MASTER_COMM_DATA_REG3_BYTE3_MASK 0xff000000
+#define MASTER_COMM_DATA_REG3__MASTER_COMM_DATA_REG3_BYTE3__SHIFT 0x18
+#define MASTER_COMM_CMD_REG__MASTER_COMM_CMD_REG_BYTE0_MASK 0xff
+#define MASTER_COMM_CMD_REG__MASTER_COMM_CMD_REG_BYTE0__SHIFT 0x0
+#define MASTER_COMM_CMD_REG__MASTER_COMM_CMD_REG_BYTE1_MASK 0xff00
+#define MASTER_COMM_CMD_REG__MASTER_COMM_CMD_REG_BYTE1__SHIFT 0x8
+#define MASTER_COMM_CMD_REG__MASTER_COMM_CMD_REG_BYTE2_MASK 0xff0000
+#define MASTER_COMM_CMD_REG__MASTER_COMM_CMD_REG_BYTE2__SHIFT 0x10
+#define MASTER_COMM_CMD_REG__MASTER_COMM_CMD_REG_BYTE3_MASK 0xff000000
+#define MASTER_COMM_CMD_REG__MASTER_COMM_CMD_REG_BYTE3__SHIFT 0x18
+#define MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK 0x1
+#define MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT__SHIFT 0x0
+#define SLAVE_COMM_DATA_REG1__SLAVE_COMM_DATA_REG1_BYTE0_MASK 0xff
+#define SLAVE_COMM_DATA_REG1__SLAVE_COMM_DATA_REG1_BYTE0__SHIFT 0x0
+#define SLAVE_COMM_DATA_REG1__SLAVE_COMM_DATA_REG1_BYTE1_MASK 0xff00
+#define SLAVE_COMM_DATA_REG1__SLAVE_COMM_DATA_REG1_BYTE1__SHIFT 0x8
+#define SLAVE_COMM_DATA_REG1__SLAVE_COMM_DATA_REG1_BYTE2_MASK 0xff0000
+#define SLAVE_COMM_DATA_REG1__SLAVE_COMM_DATA_REG1_BYTE2__SHIFT 0x10
+#define SLAVE_COMM_DATA_REG1__SLAVE_COMM_DATA_REG1_BYTE3_MASK 0xff000000
+#define SLAVE_COMM_DATA_REG1__SLAVE_COMM_DATA_REG1_BYTE3__SHIFT 0x18
+#define SLAVE_COMM_DATA_REG2__SLAVE_COMM_DATA_REG2_BYTE0_MASK 0xff
+#define SLAVE_COMM_DATA_REG2__SLAVE_COMM_DATA_REG2_BYTE0__SHIFT 0x0
+#define SLAVE_COMM_DATA_REG2__SLAVE_COMM_DATA_REG2_BYTE1_MASK 0xff00
+#define SLAVE_COMM_DATA_REG2__SLAVE_COMM_DATA_REG2_BYTE1__SHIFT 0x8
+#define SLAVE_COMM_DATA_REG2__SLAVE_COMM_DATA_REG2_BYTE2_MASK 0xff0000
+#define SLAVE_COMM_DATA_REG2__SLAVE_COMM_DATA_REG2_BYTE2__SHIFT 0x10
+#define SLAVE_COMM_DATA_REG2__SLAVE_COMM_DATA_REG2_BYTE3_MASK 0xff000000
+#define SLAVE_COMM_DATA_REG2__SLAVE_COMM_DATA_REG2_BYTE3__SHIFT 0x18
+#define SLAVE_COMM_DATA_REG3__SLAVE_COMM_DATA_REG3_BYTE0_MASK 0xff
+#define SLAVE_COMM_DATA_REG3__SLAVE_COMM_DATA_REG3_BYTE0__SHIFT 0x0
+#define SLAVE_COMM_DATA_REG3__SLAVE_COMM_DATA_REG3_BYTE1_MASK 0xff00
+#define SLAVE_COMM_DATA_REG3__SLAVE_COMM_DATA_REG3_BYTE1__SHIFT 0x8
+#define SLAVE_COMM_DATA_REG3__SLAVE_COMM_DATA_REG3_BYTE2_MASK 0xff0000
+#define SLAVE_COMM_DATA_REG3__SLAVE_COMM_DATA_REG3_BYTE2__SHIFT 0x10
+#define SLAVE_COMM_DATA_REG3__SLAVE_COMM_DATA_REG3_BYTE3_MASK 0xff000000
+#define SLAVE_COMM_DATA_REG3__SLAVE_COMM_DATA_REG3_BYTE3__SHIFT 0x18
+#define SLAVE_COMM_CMD_REG__SLAVE_COMM_CMD_REG_BYTE0_MASK 0xff
+#define SLAVE_COMM_CMD_REG__SLAVE_COMM_CMD_REG_BYTE0__SHIFT 0x0
+#define SLAVE_COMM_CMD_REG__SLAVE_COMM_CMD_REG_BYTE1_MASK 0xff00
+#define SLAVE_COMM_CMD_REG__SLAVE_COMM_CMD_REG_BYTE1__SHIFT 0x8
+#define SLAVE_COMM_CMD_REG__SLAVE_COMM_CMD_REG_BYTE2_MASK 0xff0000
+#define SLAVE_COMM_CMD_REG__SLAVE_COMM_CMD_REG_BYTE2__SHIFT 0x10
+#define SLAVE_COMM_CMD_REG__SLAVE_COMM_CMD_REG_BYTE3_MASK 0xff000000
+#define SLAVE_COMM_CMD_REG__SLAVE_COMM_CMD_REG_BYTE3__SHIFT 0x18
+#define SLAVE_COMM_CNTL_REG__SLAVE_COMM_INTERRUPT_MASK 0x1
+#define SLAVE_COMM_CNTL_REG__SLAVE_COMM_INTERRUPT__SHIFT 0x0
+#define SLAVE_COMM_CNTL_REG__COMM_PORT_MSG_TO_HOST_IN_PROGRESS_MASK 0x100
+#define SLAVE_COMM_CNTL_REG__COMM_PORT_MSG_TO_HOST_IN_PROGRESS__SHIFT 0x8
+#define DMCU_TEST_DEBUG_INDEX__DMCU_TEST_DEBUG_INDEX_MASK 0xff
+#define DMCU_TEST_DEBUG_INDEX__DMCU_TEST_DEBUG_INDEX__SHIFT 0x0
+#define DMCU_TEST_DEBUG_INDEX__DMCU_TEST_DEBUG_WRITE_EN_MASK 0x100
+#define DMCU_TEST_DEBUG_INDEX__DMCU_TEST_DEBUG_WRITE_EN__SHIFT 0x8
+#define DMCU_TEST_DEBUG_DATA__DMCU_TEST_DEBUG_DATA_MASK 0xffffffff
+#define DMCU_TEST_DEBUG_DATA__DMCU_TEST_DEBUG_DATA__SHIFT 0x0
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCI_PERFMON_COUNTER0_INT_OCCURRED_MASK 0x1
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCI_PERFMON_COUNTER0_INT_OCCURRED__SHIFT 0x0
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCI_PERFMON_COUNTER0_INT_CLEAR_MASK 0x1
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCI_PERFMON_COUNTER0_INT_CLEAR__SHIFT 0x0
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCI_PERFMON_COUNTER1_INT_OCCURRED_MASK 0x2
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCI_PERFMON_COUNTER1_INT_OCCURRED__SHIFT 0x1
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCI_PERFMON_COUNTER1_INT_CLEAR_MASK 0x2
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCI_PERFMON_COUNTER1_INT_CLEAR__SHIFT 0x1
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCI_PERFMON_COUNTER2_INT_OCCURRED_MASK 0x4
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCI_PERFMON_COUNTER2_INT_OCCURRED__SHIFT 0x2
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCI_PERFMON_COUNTER2_INT_CLEAR_MASK 0x4
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCI_PERFMON_COUNTER2_INT_CLEAR__SHIFT 0x2
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCI_PERFMON_COUNTER3_INT_OCCURRED_MASK 0x8
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCI_PERFMON_COUNTER3_INT_OCCURRED__SHIFT 0x3
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCI_PERFMON_COUNTER3_INT_CLEAR_MASK 0x8
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCI_PERFMON_COUNTER3_INT_CLEAR__SHIFT 0x3
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCI_PERFMON_COUNTER4_INT_OCCURRED_MASK 0x10
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCI_PERFMON_COUNTER4_INT_OCCURRED__SHIFT 0x4
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCI_PERFMON_COUNTER4_INT_CLEAR_MASK 0x10
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCI_PERFMON_COUNTER4_INT_CLEAR__SHIFT 0x4
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCI_PERFMON_COUNTER5_INT_OCCURRED_MASK 0x20
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCI_PERFMON_COUNTER5_INT_OCCURRED__SHIFT 0x5
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCI_PERFMON_COUNTER5_INT_CLEAR_MASK 0x20
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCI_PERFMON_COUNTER5_INT_CLEAR__SHIFT 0x5
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCI_PERFMON_COUNTER6_INT_OCCURRED_MASK 0x40
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCI_PERFMON_COUNTER6_INT_OCCURRED__SHIFT 0x6
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCI_PERFMON_COUNTER6_INT_CLEAR_MASK 0x40
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCI_PERFMON_COUNTER6_INT_CLEAR__SHIFT 0x6
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCI_PERFMON_COUNTER7_INT_OCCURRED_MASK 0x80
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCI_PERFMON_COUNTER7_INT_OCCURRED__SHIFT 0x7
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCI_PERFMON_COUNTER7_INT_CLEAR_MASK 0x80
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCI_PERFMON_COUNTER7_INT_CLEAR__SHIFT 0x7
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCO_PERFMON_COUNTER0_INT_OCCURRED_MASK 0x100
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCO_PERFMON_COUNTER0_INT_OCCURRED__SHIFT 0x8
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCO_PERFMON_COUNTER0_INT_CLEAR_MASK 0x100
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCO_PERFMON_COUNTER0_INT_CLEAR__SHIFT 0x8
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCO_PERFMON_COUNTER1_INT_OCCURRED_MASK 0x200
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCO_PERFMON_COUNTER1_INT_OCCURRED__SHIFT 0x9
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCO_PERFMON_COUNTER1_INT_CLEAR_MASK 0x200
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCO_PERFMON_COUNTER1_INT_CLEAR__SHIFT 0x9
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCO_PERFMON_COUNTER2_INT_OCCURRED_MASK 0x400
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCO_PERFMON_COUNTER2_INT_OCCURRED__SHIFT 0xa
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCO_PERFMON_COUNTER2_INT_CLEAR_MASK 0x400
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCO_PERFMON_COUNTER2_INT_CLEAR__SHIFT 0xa
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCO_PERFMON_COUNTER3_INT_OCCURRED_MASK 0x800
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCO_PERFMON_COUNTER3_INT_OCCURRED__SHIFT 0xb
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCO_PERFMON_COUNTER3_INT_CLEAR_MASK 0x800
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCO_PERFMON_COUNTER3_INT_CLEAR__SHIFT 0xb
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCO_PERFMON_COUNTER4_INT_OCCURRED_MASK 0x1000
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCO_PERFMON_COUNTER4_INT_OCCURRED__SHIFT 0xc
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCO_PERFMON_COUNTER4_INT_CLEAR_MASK 0x1000
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCO_PERFMON_COUNTER4_INT_CLEAR__SHIFT 0xc
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCO_PERFMON_COUNTER5_INT_OCCURRED_MASK 0x2000
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCO_PERFMON_COUNTER5_INT_OCCURRED__SHIFT 0xd
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCO_PERFMON_COUNTER5_INT_CLEAR_MASK 0x2000
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCO_PERFMON_COUNTER5_INT_CLEAR__SHIFT 0xd
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCO_PERFMON_COUNTER6_INT_OCCURRED_MASK 0x4000
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCO_PERFMON_COUNTER6_INT_OCCURRED__SHIFT 0xe
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCO_PERFMON_COUNTER6_INT_CLEAR_MASK 0x4000
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCO_PERFMON_COUNTER6_INT_CLEAR__SHIFT 0xe
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCO_PERFMON_COUNTER7_INT_OCCURRED_MASK 0x8000
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCO_PERFMON_COUNTER7_INT_OCCURRED__SHIFT 0xf
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCO_PERFMON_COUNTER7_INT_CLEAR_MASK 0x8000
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCO_PERFMON_COUNTER7_INT_CLEAR__SHIFT 0xf
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCCG_PERFMON_COUNTER0_INT_OCCURRED_MASK 0x10000
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCCG_PERFMON_COUNTER0_INT_OCCURRED__SHIFT 0x10
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCCG_PERFMON_COUNTER0_INT_CLEAR_MASK 0x10000
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCCG_PERFMON_COUNTER0_INT_CLEAR__SHIFT 0x10
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCCG_PERFMON_COUNTER1_INT_OCCURRED_MASK 0x20000
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCCG_PERFMON_COUNTER1_INT_OCCURRED__SHIFT 0x11
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCCG_PERFMON_COUNTER1_INT_CLEAR_MASK 0x20000
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCCG_PERFMON_COUNTER1_INT_CLEAR__SHIFT 0x11
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCCG_PERFMON_COUNTER2_INT_OCCURRED_MASK 0x40000
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCCG_PERFMON_COUNTER2_INT_OCCURRED__SHIFT 0x12
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCCG_PERFMON_COUNTER2_INT_CLEAR_MASK 0x40000
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCCG_PERFMON_COUNTER2_INT_CLEAR__SHIFT 0x12
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCCG_PERFMON_COUNTER3_INT_OCCURRED_MASK 0x80000
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCCG_PERFMON_COUNTER3_INT_OCCURRED__SHIFT 0x13
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCCG_PERFMON_COUNTER3_INT_CLEAR_MASK 0x80000
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCCG_PERFMON_COUNTER3_INT_CLEAR__SHIFT 0x13
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCCG_PERFMON_COUNTER4_INT_OCCURRED_MASK 0x100000
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCCG_PERFMON_COUNTER4_INT_OCCURRED__SHIFT 0x14
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCCG_PERFMON_COUNTER4_INT_CLEAR_MASK 0x100000
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCCG_PERFMON_COUNTER4_INT_CLEAR__SHIFT 0x14
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCCG_PERFMON_COUNTER5_INT_OCCURRED_MASK 0x200000
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCCG_PERFMON_COUNTER5_INT_OCCURRED__SHIFT 0x15
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCCG_PERFMON_COUNTER5_INT_CLEAR_MASK 0x200000
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCCG_PERFMON_COUNTER5_INT_CLEAR__SHIFT 0x15
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCCG_PERFMON_COUNTER6_INT_OCCURRED_MASK 0x400000
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCCG_PERFMON_COUNTER6_INT_OCCURRED__SHIFT 0x16
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCCG_PERFMON_COUNTER6_INT_CLEAR_MASK 0x400000
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCCG_PERFMON_COUNTER6_INT_CLEAR__SHIFT 0x16
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCCG_PERFMON_COUNTER7_INT_OCCURRED_MASK 0x800000
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCCG_PERFMON_COUNTER7_INT_OCCURRED__SHIFT 0x17
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCCG_PERFMON_COUNTER7_INT_CLEAR_MASK 0x800000
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCCG_PERFMON_COUNTER7_INT_CLEAR__SHIFT 0x17
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCI_PERFMON_COUNTER_OFF_INT_OCCURRED_MASK 0x1000000
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCI_PERFMON_COUNTER_OFF_INT_OCCURRED__SHIFT 0x18
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCI_PERFMON_COUNTER_OFF_INT_CLEAR_MASK 0x1000000
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCI_PERFMON_COUNTER_OFF_INT_CLEAR__SHIFT 0x18
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCO_PERFMON_COUNTER_OFF_INT_OCCURRED_MASK 0x2000000
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCO_PERFMON_COUNTER_OFF_INT_OCCURRED__SHIFT 0x19
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCO_PERFMON_COUNTER_OFF_INT_CLEAR_MASK 0x2000000
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCO_PERFMON_COUNTER_OFF_INT_CLEAR__SHIFT 0x19
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCCG_PERFMON_COUNTER_OFF_INT_OCCURRED_MASK 0x4000000
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCCG_PERFMON_COUNTER_OFF_INT_OCCURRED__SHIFT 0x1a
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCCG_PERFMON_COUNTER_OFF_INT_CLEAR_MASK 0x4000000
+#define DMCU_PERFMON_INTERRUPT_STATUS1__DCCG_PERFMON_COUNTER_OFF_INT_CLEAR__SHIFT 0x1a
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE0_PERFMON_COUNTER0_INT_OCCURRED_MASK 0x1
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE0_PERFMON_COUNTER0_INT_OCCURRED__SHIFT 0x0
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE0_PERFMON_COUNTER0_INT_CLEAR_MASK 0x1
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE0_PERFMON_COUNTER0_INT_CLEAR__SHIFT 0x0
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE0_PERFMON_COUNTER1_INT_OCCURRED_MASK 0x2
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE0_PERFMON_COUNTER1_INT_OCCURRED__SHIFT 0x1
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE0_PERFMON_COUNTER1_INT_CLEAR_MASK 0x2
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE0_PERFMON_COUNTER1_INT_CLEAR__SHIFT 0x1
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE0_PERFMON_COUNTER2_INT_OCCURRED_MASK 0x4
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE0_PERFMON_COUNTER2_INT_OCCURRED__SHIFT 0x2
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE0_PERFMON_COUNTER2_INT_CLEAR_MASK 0x4
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE0_PERFMON_COUNTER2_INT_CLEAR__SHIFT 0x2
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE0_PERFMON_COUNTER3_INT_OCCURRED_MASK 0x8
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE0_PERFMON_COUNTER3_INT_OCCURRED__SHIFT 0x3
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE0_PERFMON_COUNTER3_INT_CLEAR_MASK 0x8
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE0_PERFMON_COUNTER3_INT_CLEAR__SHIFT 0x3
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE0_PERFMON_COUNTER4_INT_OCCURRED_MASK 0x10
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE0_PERFMON_COUNTER4_INT_OCCURRED__SHIFT 0x4
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE0_PERFMON_COUNTER4_INT_CLEAR_MASK 0x10
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE0_PERFMON_COUNTER4_INT_CLEAR__SHIFT 0x4
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE0_PERFMON_COUNTER5_INT_OCCURRED_MASK 0x20
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE0_PERFMON_COUNTER5_INT_OCCURRED__SHIFT 0x5
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE0_PERFMON_COUNTER5_INT_CLEAR_MASK 0x20
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE0_PERFMON_COUNTER5_INT_CLEAR__SHIFT 0x5
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE0_PERFMON_COUNTER6_INT_OCCURRED_MASK 0x40
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE0_PERFMON_COUNTER6_INT_OCCURRED__SHIFT 0x6
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE0_PERFMON_COUNTER6_INT_CLEAR_MASK 0x40
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE0_PERFMON_COUNTER6_INT_CLEAR__SHIFT 0x6
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE0_PERFMON_COUNTER7_INT_OCCURRED_MASK 0x80
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE0_PERFMON_COUNTER7_INT_OCCURRED__SHIFT 0x7
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE0_PERFMON_COUNTER7_INT_CLEAR_MASK 0x80
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE0_PERFMON_COUNTER7_INT_CLEAR__SHIFT 0x7
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE1_PERFMON_COUNTER0_INT_OCCURRED_MASK 0x100
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE1_PERFMON_COUNTER0_INT_OCCURRED__SHIFT 0x8
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE1_PERFMON_COUNTER0_INT_CLEAR_MASK 0x100
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE1_PERFMON_COUNTER0_INT_CLEAR__SHIFT 0x8
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE1_PERFMON_COUNTER1_INT_OCCURRED_MASK 0x200
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE1_PERFMON_COUNTER1_INT_OCCURRED__SHIFT 0x9
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE1_PERFMON_COUNTER1_INT_CLEAR_MASK 0x200
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE1_PERFMON_COUNTER1_INT_CLEAR__SHIFT 0x9
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE1_PERFMON_COUNTER2_INT_OCCURRED_MASK 0x400
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE1_PERFMON_COUNTER2_INT_OCCURRED__SHIFT 0xa
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE1_PERFMON_COUNTER2_INT_CLEAR_MASK 0x400
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE1_PERFMON_COUNTER2_INT_CLEAR__SHIFT 0xa
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE1_PERFMON_COUNTER3_INT_OCCURRED_MASK 0x800
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE1_PERFMON_COUNTER3_INT_OCCURRED__SHIFT 0xb
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE1_PERFMON_COUNTER3_INT_CLEAR_MASK 0x800
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE1_PERFMON_COUNTER3_INT_CLEAR__SHIFT 0xb
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE1_PERFMON_COUNTER4_INT_OCCURRED_MASK 0x1000
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE1_PERFMON_COUNTER4_INT_OCCURRED__SHIFT 0xc
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE1_PERFMON_COUNTER4_INT_CLEAR_MASK 0x1000
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE1_PERFMON_COUNTER4_INT_CLEAR__SHIFT 0xc
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE1_PERFMON_COUNTER5_INT_OCCURRED_MASK 0x2000
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE1_PERFMON_COUNTER5_INT_OCCURRED__SHIFT 0xd
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE1_PERFMON_COUNTER5_INT_CLEAR_MASK 0x2000
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE1_PERFMON_COUNTER5_INT_CLEAR__SHIFT 0xd
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE1_PERFMON_COUNTER6_INT_OCCURRED_MASK 0x4000
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE1_PERFMON_COUNTER6_INT_OCCURRED__SHIFT 0xe
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE1_PERFMON_COUNTER6_INT_CLEAR_MASK 0x4000
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE1_PERFMON_COUNTER6_INT_CLEAR__SHIFT 0xe
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE1_PERFMON_COUNTER7_INT_OCCURRED_MASK 0x8000
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE1_PERFMON_COUNTER7_INT_OCCURRED__SHIFT 0xf
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE1_PERFMON_COUNTER7_INT_CLEAR_MASK 0x8000
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE1_PERFMON_COUNTER7_INT_CLEAR__SHIFT 0xf
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE2_PERFMON_COUNTER0_INT_OCCURRED_MASK 0x10000
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE2_PERFMON_COUNTER0_INT_OCCURRED__SHIFT 0x10
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE2_PERFMON_COUNTER0_INT_CLEAR_MASK 0x10000
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE2_PERFMON_COUNTER0_INT_CLEAR__SHIFT 0x10
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE2_PERFMON_COUNTER1_INT_OCCURRED_MASK 0x20000
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE2_PERFMON_COUNTER1_INT_OCCURRED__SHIFT 0x11
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE2_PERFMON_COUNTER1_INT_CLEAR_MASK 0x20000
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE2_PERFMON_COUNTER1_INT_CLEAR__SHIFT 0x11
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE2_PERFMON_COUNTER2_INT_OCCURRED_MASK 0x40000
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE2_PERFMON_COUNTER2_INT_OCCURRED__SHIFT 0x12
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE2_PERFMON_COUNTER2_INT_CLEAR_MASK 0x40000
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE2_PERFMON_COUNTER2_INT_CLEAR__SHIFT 0x12
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE2_PERFMON_COUNTER3_INT_OCCURRED_MASK 0x80000
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE2_PERFMON_COUNTER3_INT_OCCURRED__SHIFT 0x13
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE2_PERFMON_COUNTER3_INT_CLEAR_MASK 0x80000
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE2_PERFMON_COUNTER3_INT_CLEAR__SHIFT 0x13
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE2_PERFMON_COUNTER4_INT_OCCURRED_MASK 0x100000
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE2_PERFMON_COUNTER4_INT_OCCURRED__SHIFT 0x14
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE2_PERFMON_COUNTER4_INT_CLEAR_MASK 0x100000
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE2_PERFMON_COUNTER4_INT_CLEAR__SHIFT 0x14
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE2_PERFMON_COUNTER5_INT_OCCURRED_MASK 0x200000
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE2_PERFMON_COUNTER5_INT_OCCURRED__SHIFT 0x15
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE2_PERFMON_COUNTER5_INT_CLEAR_MASK 0x200000
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE2_PERFMON_COUNTER5_INT_CLEAR__SHIFT 0x15
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE2_PERFMON_COUNTER6_INT_OCCURRED_MASK 0x400000
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE2_PERFMON_COUNTER6_INT_OCCURRED__SHIFT 0x16
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE2_PERFMON_COUNTER6_INT_CLEAR_MASK 0x400000
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE2_PERFMON_COUNTER6_INT_CLEAR__SHIFT 0x16
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE2_PERFMON_COUNTER7_INT_OCCURRED_MASK 0x800000
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE2_PERFMON_COUNTER7_INT_OCCURRED__SHIFT 0x17
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE2_PERFMON_COUNTER7_INT_CLEAR_MASK 0x800000
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE2_PERFMON_COUNTER7_INT_CLEAR__SHIFT 0x17
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE0_PERFMON_COUNTER_OFF_INT_OCCURRED_MASK 0x1000000
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE0_PERFMON_COUNTER_OFF_INT_OCCURRED__SHIFT 0x18
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE0_PERFMON_COUNTER_OFF_INT_CLEAR_MASK 0x1000000
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE0_PERFMON_COUNTER_OFF_INT_CLEAR__SHIFT 0x18
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE1_PERFMON_COUNTER_OFF_INT_OCCURRED_MASK 0x2000000
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE1_PERFMON_COUNTER_OFF_INT_OCCURRED__SHIFT 0x19
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE1_PERFMON_COUNTER_OFF_INT_CLEAR_MASK 0x2000000
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE1_PERFMON_COUNTER_OFF_INT_CLEAR__SHIFT 0x19
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE2_PERFMON_COUNTER_OFF_INT_OCCURRED_MASK 0x4000000
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE2_PERFMON_COUNTER_OFF_INT_OCCURRED__SHIFT 0x1a
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE2_PERFMON_COUNTER_OFF_INT_CLEAR_MASK 0x4000000
+#define DMCU_PERFMON_INTERRUPT_STATUS2__DCFE2_PERFMON_COUNTER_OFF_INT_CLEAR__SHIFT 0x1a
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE3_PERFMON_COUNTER0_INT_OCCURRED_MASK 0x1
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE3_PERFMON_COUNTER0_INT_OCCURRED__SHIFT 0x0
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE3_PERFMON_COUNTER0_INT_CLEAR_MASK 0x1
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE3_PERFMON_COUNTER0_INT_CLEAR__SHIFT 0x0
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE3_PERFMON_COUNTER1_INT_OCCURRED_MASK 0x2
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE3_PERFMON_COUNTER1_INT_OCCURRED__SHIFT 0x1
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE3_PERFMON_COUNTER1_INT_CLEAR_MASK 0x2
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE3_PERFMON_COUNTER1_INT_CLEAR__SHIFT 0x1
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE3_PERFMON_COUNTER2_INT_OCCURRED_MASK 0x4
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE3_PERFMON_COUNTER2_INT_OCCURRED__SHIFT 0x2
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE3_PERFMON_COUNTER2_INT_CLEAR_MASK 0x4
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE3_PERFMON_COUNTER2_INT_CLEAR__SHIFT 0x2
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE3_PERFMON_COUNTER3_INT_OCCURRED_MASK 0x8
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE3_PERFMON_COUNTER3_INT_OCCURRED__SHIFT 0x3
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE3_PERFMON_COUNTER3_INT_CLEAR_MASK 0x8
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE3_PERFMON_COUNTER3_INT_CLEAR__SHIFT 0x3
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE3_PERFMON_COUNTER4_INT_OCCURRED_MASK 0x10
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE3_PERFMON_COUNTER4_INT_OCCURRED__SHIFT 0x4
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE3_PERFMON_COUNTER4_INT_CLEAR_MASK 0x10
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE3_PERFMON_COUNTER4_INT_CLEAR__SHIFT 0x4
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE3_PERFMON_COUNTER5_INT_OCCURRED_MASK 0x20
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE3_PERFMON_COUNTER5_INT_OCCURRED__SHIFT 0x5
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE3_PERFMON_COUNTER5_INT_CLEAR_MASK 0x20
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE3_PERFMON_COUNTER5_INT_CLEAR__SHIFT 0x5
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE3_PERFMON_COUNTER6_INT_OCCURRED_MASK 0x40
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE3_PERFMON_COUNTER6_INT_OCCURRED__SHIFT 0x6
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE3_PERFMON_COUNTER6_INT_CLEAR_MASK 0x40
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE3_PERFMON_COUNTER6_INT_CLEAR__SHIFT 0x6
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE3_PERFMON_COUNTER7_INT_OCCURRED_MASK 0x80
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE3_PERFMON_COUNTER7_INT_OCCURRED__SHIFT 0x7
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE3_PERFMON_COUNTER7_INT_CLEAR_MASK 0x80
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE3_PERFMON_COUNTER7_INT_CLEAR__SHIFT 0x7
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE4_PERFMON_COUNTER0_INT_OCCURRED_MASK 0x100
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE4_PERFMON_COUNTER0_INT_OCCURRED__SHIFT 0x8
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE4_PERFMON_COUNTER0_INT_CLEAR_MASK 0x100
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE4_PERFMON_COUNTER0_INT_CLEAR__SHIFT 0x8
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE4_PERFMON_COUNTER1_INT_OCCURRED_MASK 0x200
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE4_PERFMON_COUNTER1_INT_OCCURRED__SHIFT 0x9
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE4_PERFMON_COUNTER1_INT_CLEAR_MASK 0x200
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE4_PERFMON_COUNTER1_INT_CLEAR__SHIFT 0x9
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE4_PERFMON_COUNTER2_INT_OCCURRED_MASK 0x400
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE4_PERFMON_COUNTER2_INT_OCCURRED__SHIFT 0xa
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE4_PERFMON_COUNTER2_INT_CLEAR_MASK 0x400
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE4_PERFMON_COUNTER2_INT_CLEAR__SHIFT 0xa
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE4_PERFMON_COUNTER3_INT_OCCURRED_MASK 0x800
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE4_PERFMON_COUNTER3_INT_OCCURRED__SHIFT 0xb
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE4_PERFMON_COUNTER3_INT_CLEAR_MASK 0x800
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE4_PERFMON_COUNTER3_INT_CLEAR__SHIFT 0xb
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE4_PERFMON_COUNTER4_INT_OCCURRED_MASK 0x1000
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE4_PERFMON_COUNTER4_INT_OCCURRED__SHIFT 0xc
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE4_PERFMON_COUNTER4_INT_CLEAR_MASK 0x1000
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE4_PERFMON_COUNTER4_INT_CLEAR__SHIFT 0xc
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE4_PERFMON_COUNTER5_INT_OCCURRED_MASK 0x2000
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE4_PERFMON_COUNTER5_INT_OCCURRED__SHIFT 0xd
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE4_PERFMON_COUNTER5_INT_CLEAR_MASK 0x2000
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE4_PERFMON_COUNTER5_INT_CLEAR__SHIFT 0xd
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE4_PERFMON_COUNTER6_INT_OCCURRED_MASK 0x4000
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE4_PERFMON_COUNTER6_INT_OCCURRED__SHIFT 0xe
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE4_PERFMON_COUNTER6_INT_CLEAR_MASK 0x4000
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE4_PERFMON_COUNTER6_INT_CLEAR__SHIFT 0xe
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE4_PERFMON_COUNTER7_INT_OCCURRED_MASK 0x8000
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE4_PERFMON_COUNTER7_INT_OCCURRED__SHIFT 0xf
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE4_PERFMON_COUNTER7_INT_CLEAR_MASK 0x8000
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE4_PERFMON_COUNTER7_INT_CLEAR__SHIFT 0xf
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE5_PERFMON_COUNTER0_INT_OCCURRED_MASK 0x10000
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE5_PERFMON_COUNTER0_INT_OCCURRED__SHIFT 0x10
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE5_PERFMON_COUNTER0_INT_CLEAR_MASK 0x10000
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE5_PERFMON_COUNTER0_INT_CLEAR__SHIFT 0x10
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE5_PERFMON_COUNTER1_INT_OCCURRED_MASK 0x20000
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE5_PERFMON_COUNTER1_INT_OCCURRED__SHIFT 0x11
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE5_PERFMON_COUNTER1_INT_CLEAR_MASK 0x20000
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE5_PERFMON_COUNTER1_INT_CLEAR__SHIFT 0x11
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE5_PERFMON_COUNTER2_INT_OCCURRED_MASK 0x40000
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE5_PERFMON_COUNTER2_INT_OCCURRED__SHIFT 0x12
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE5_PERFMON_COUNTER2_INT_CLEAR_MASK 0x40000
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE5_PERFMON_COUNTER2_INT_CLEAR__SHIFT 0x12
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE5_PERFMON_COUNTER3_INT_OCCURRED_MASK 0x80000
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE5_PERFMON_COUNTER3_INT_OCCURRED__SHIFT 0x13
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE5_PERFMON_COUNTER3_INT_CLEAR_MASK 0x80000
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE5_PERFMON_COUNTER3_INT_CLEAR__SHIFT 0x13
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE5_PERFMON_COUNTER4_INT_OCCURRED_MASK 0x100000
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE5_PERFMON_COUNTER4_INT_OCCURRED__SHIFT 0x14
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE5_PERFMON_COUNTER4_INT_CLEAR_MASK 0x100000
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE5_PERFMON_COUNTER4_INT_CLEAR__SHIFT 0x14
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE5_PERFMON_COUNTER5_INT_OCCURRED_MASK 0x200000
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE5_PERFMON_COUNTER5_INT_OCCURRED__SHIFT 0x15
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE5_PERFMON_COUNTER5_INT_CLEAR_MASK 0x200000
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE5_PERFMON_COUNTER5_INT_CLEAR__SHIFT 0x15
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE5_PERFMON_COUNTER6_INT_OCCURRED_MASK 0x400000
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE5_PERFMON_COUNTER6_INT_OCCURRED__SHIFT 0x16
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE5_PERFMON_COUNTER6_INT_CLEAR_MASK 0x400000
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE5_PERFMON_COUNTER6_INT_CLEAR__SHIFT 0x16
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE5_PERFMON_COUNTER7_INT_OCCURRED_MASK 0x800000
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE5_PERFMON_COUNTER7_INT_OCCURRED__SHIFT 0x17
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE5_PERFMON_COUNTER7_INT_CLEAR_MASK 0x800000
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE5_PERFMON_COUNTER7_INT_CLEAR__SHIFT 0x17
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE3_PERFMON_COUNTER_OFF_INT_OCCURRED_MASK 0x1000000
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE3_PERFMON_COUNTER_OFF_INT_OCCURRED__SHIFT 0x18
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE3_PERFMON_COUNTER_OFF_INT_CLEAR_MASK 0x1000000
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE3_PERFMON_COUNTER_OFF_INT_CLEAR__SHIFT 0x18
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE4_PERFMON_COUNTER_OFF_INT_OCCURRED_MASK 0x2000000
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE4_PERFMON_COUNTER_OFF_INT_OCCURRED__SHIFT 0x19
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE4_PERFMON_COUNTER_OFF_INT_CLEAR_MASK 0x2000000
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE4_PERFMON_COUNTER_OFF_INT_CLEAR__SHIFT 0x19
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE5_PERFMON_COUNTER_OFF_INT_OCCURRED_MASK 0x4000000
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE5_PERFMON_COUNTER_OFF_INT_OCCURRED__SHIFT 0x1a
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE5_PERFMON_COUNTER_OFF_INT_CLEAR_MASK 0x4000000
+#define DMCU_PERFMON_INTERRUPT_STATUS3__DCFE5_PERFMON_COUNTER_OFF_INT_CLEAR__SHIFT 0x1a
+#define DMCU_PERFMON_INTERRUPT_STATUS4__WB_PERFMON_COUNTER0_INT_OCCURRED_MASK 0x1
+#define DMCU_PERFMON_INTERRUPT_STATUS4__WB_PERFMON_COUNTER0_INT_OCCURRED__SHIFT 0x0
+#define DMCU_PERFMON_INTERRUPT_STATUS4__WB_PERFMON_COUNTER0_INT_CLEAR_MASK 0x1
+#define DMCU_PERFMON_INTERRUPT_STATUS4__WB_PERFMON_COUNTER0_INT_CLEAR__SHIFT 0x0
+#define DMCU_PERFMON_INTERRUPT_STATUS4__WB_PERFMON_COUNTER1_INT_OCCURRED_MASK 0x2
+#define DMCU_PERFMON_INTERRUPT_STATUS4__WB_PERFMON_COUNTER1_INT_OCCURRED__SHIFT 0x1
+#define DMCU_PERFMON_INTERRUPT_STATUS4__WB_PERFMON_COUNTER1_INT_CLEAR_MASK 0x2
+#define DMCU_PERFMON_INTERRUPT_STATUS4__WB_PERFMON_COUNTER1_INT_CLEAR__SHIFT 0x1
+#define DMCU_PERFMON_INTERRUPT_STATUS4__WB_PERFMON_COUNTER2_INT_OCCURRED_MASK 0x4
+#define DMCU_PERFMON_INTERRUPT_STATUS4__WB_PERFMON_COUNTER2_INT_OCCURRED__SHIFT 0x2
+#define DMCU_PERFMON_INTERRUPT_STATUS4__WB_PERFMON_COUNTER2_INT_CLEAR_MASK 0x4
+#define DMCU_PERFMON_INTERRUPT_STATUS4__WB_PERFMON_COUNTER2_INT_CLEAR__SHIFT 0x2
+#define DMCU_PERFMON_INTERRUPT_STATUS4__WB_PERFMON_COUNTER3_INT_OCCURRED_MASK 0x8
+#define DMCU_PERFMON_INTERRUPT_STATUS4__WB_PERFMON_COUNTER3_INT_OCCURRED__SHIFT 0x3
+#define DMCU_PERFMON_INTERRUPT_STATUS4__WB_PERFMON_COUNTER3_INT_CLEAR_MASK 0x8
+#define DMCU_PERFMON_INTERRUPT_STATUS4__WB_PERFMON_COUNTER3_INT_CLEAR__SHIFT 0x3
+#define DMCU_PERFMON_INTERRUPT_STATUS4__WB_PERFMON_COUNTER4_INT_OCCURRED_MASK 0x10
+#define DMCU_PERFMON_INTERRUPT_STATUS4__WB_PERFMON_COUNTER4_INT_OCCURRED__SHIFT 0x4
+#define DMCU_PERFMON_INTERRUPT_STATUS4__WB_PERFMON_COUNTER4_INT_CLEAR_MASK 0x10
+#define DMCU_PERFMON_INTERRUPT_STATUS4__WB_PERFMON_COUNTER4_INT_CLEAR__SHIFT 0x4
+#define DMCU_PERFMON_INTERRUPT_STATUS4__WB_PERFMON_COUNTER5_INT_OCCURRED_MASK 0x20
+#define DMCU_PERFMON_INTERRUPT_STATUS4__WB_PERFMON_COUNTER5_INT_OCCURRED__SHIFT 0x5
+#define DMCU_PERFMON_INTERRUPT_STATUS4__WB_PERFMON_COUNTER5_INT_CLEAR_MASK 0x20
+#define DMCU_PERFMON_INTERRUPT_STATUS4__WB_PERFMON_COUNTER5_INT_CLEAR__SHIFT 0x5
+#define DMCU_PERFMON_INTERRUPT_STATUS4__WB_PERFMON_COUNTER6_INT_OCCURRED_MASK 0x40
+#define DMCU_PERFMON_INTERRUPT_STATUS4__WB_PERFMON_COUNTER6_INT_OCCURRED__SHIFT 0x6
+#define DMCU_PERFMON_INTERRUPT_STATUS4__WB_PERFMON_COUNTER6_INT_CLEAR_MASK 0x40
+#define DMCU_PERFMON_INTERRUPT_STATUS4__WB_PERFMON_COUNTER6_INT_CLEAR__SHIFT 0x6
+#define DMCU_PERFMON_INTERRUPT_STATUS4__WB_PERFMON_COUNTER7_INT_OCCURRED_MASK 0x80
+#define DMCU_PERFMON_INTERRUPT_STATUS4__WB_PERFMON_COUNTER7_INT_OCCURRED__SHIFT 0x7
+#define DMCU_PERFMON_INTERRUPT_STATUS4__WB_PERFMON_COUNTER7_INT_CLEAR_MASK 0x80
+#define DMCU_PERFMON_INTERRUPT_STATUS4__WB_PERFMON_COUNTER7_INT_CLEAR__SHIFT 0x7
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCRX_PERFMON_COUNTER0_INT_OCCURRED_MASK 0x100
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCRX_PERFMON_COUNTER0_INT_OCCURRED__SHIFT 0x8
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCRX_PERFMON_COUNTER0_INT_CLEAR_MASK 0x100
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCRX_PERFMON_COUNTER0_INT_CLEAR__SHIFT 0x8
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCRX_PERFMON_COUNTER1_INT_OCCURRED_MASK 0x200
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCRX_PERFMON_COUNTER1_INT_OCCURRED__SHIFT 0x9
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCRX_PERFMON_COUNTER1_INT_CLEAR_MASK 0x200
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCRX_PERFMON_COUNTER1_INT_CLEAR__SHIFT 0x9
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCRX_PERFMON_COUNTER2_INT_OCCURRED_MASK 0x400
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCRX_PERFMON_COUNTER2_INT_OCCURRED__SHIFT 0xa
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCRX_PERFMON_COUNTER2_INT_CLEAR_MASK 0x400
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCRX_PERFMON_COUNTER2_INT_CLEAR__SHIFT 0xa
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCRX_PERFMON_COUNTER3_INT_OCCURRED_MASK 0x800
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCRX_PERFMON_COUNTER3_INT_OCCURRED__SHIFT 0xb
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCRX_PERFMON_COUNTER3_INT_CLEAR_MASK 0x800
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCRX_PERFMON_COUNTER3_INT_CLEAR__SHIFT 0xb
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCRX_PERFMON_COUNTER4_INT_OCCURRED_MASK 0x1000
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCRX_PERFMON_COUNTER4_INT_OCCURRED__SHIFT 0xc
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCRX_PERFMON_COUNTER4_INT_CLEAR_MASK 0x1000
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCRX_PERFMON_COUNTER4_INT_CLEAR__SHIFT 0xc
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCRX_PERFMON_COUNTER5_INT_OCCURRED_MASK 0x2000
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCRX_PERFMON_COUNTER5_INT_OCCURRED__SHIFT 0xd
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCRX_PERFMON_COUNTER5_INT_CLEAR_MASK 0x2000
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCRX_PERFMON_COUNTER5_INT_CLEAR__SHIFT 0xd
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCRX_PERFMON_COUNTER6_INT_OCCURRED_MASK 0x4000
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCRX_PERFMON_COUNTER6_INT_OCCURRED__SHIFT 0xe
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCRX_PERFMON_COUNTER6_INT_CLEAR_MASK 0x4000
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCRX_PERFMON_COUNTER6_INT_CLEAR__SHIFT 0xe
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCRX_PERFMON_COUNTER7_INT_OCCURRED_MASK 0x8000
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCRX_PERFMON_COUNTER7_INT_OCCURRED__SHIFT 0xf
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCRX_PERFMON_COUNTER7_INT_CLEAR_MASK 0x8000
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCRX_PERFMON_COUNTER7_INT_CLEAR__SHIFT 0xf
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCCG_PERFMON2_COUNTER0_INT_OCCURRED_MASK 0x10000
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCCG_PERFMON2_COUNTER0_INT_OCCURRED__SHIFT 0x10
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCCG_PERFMON2_COUNTER0_INT_CLEAR_MASK 0x10000
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCCG_PERFMON2_COUNTER0_INT_CLEAR__SHIFT 0x10
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCCG_PERFMON2_COUNTER1_INT_OCCURRED_MASK 0x20000
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCCG_PERFMON2_COUNTER1_INT_OCCURRED__SHIFT 0x11
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCCG_PERFMON2_COUNTER1_INT_CLEAR_MASK 0x20000
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCCG_PERFMON2_COUNTER1_INT_CLEAR__SHIFT 0x11
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCCG_PERFMON2_COUNTER2_INT_OCCURRED_MASK 0x40000
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCCG_PERFMON2_COUNTER2_INT_OCCURRED__SHIFT 0x12
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCCG_PERFMON2_COUNTER2_INT_CLEAR_MASK 0x40000
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCCG_PERFMON2_COUNTER2_INT_CLEAR__SHIFT 0x12
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCCG_PERFMON2_COUNTER3_INT_OCCURRED_MASK 0x80000
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCCG_PERFMON2_COUNTER3_INT_OCCURRED__SHIFT 0x13
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCCG_PERFMON2_COUNTER3_INT_CLEAR_MASK 0x80000
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCCG_PERFMON2_COUNTER3_INT_CLEAR__SHIFT 0x13
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCCG_PERFMON2_COUNTER4_INT_OCCURRED_MASK 0x100000
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCCG_PERFMON2_COUNTER4_INT_OCCURRED__SHIFT 0x14
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCCG_PERFMON2_COUNTER4_INT_CLEAR_MASK 0x100000
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCCG_PERFMON2_COUNTER4_INT_CLEAR__SHIFT 0x14
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCCG_PERFMON2_COUNTER5_INT_OCCURRED_MASK 0x200000
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCCG_PERFMON2_COUNTER5_INT_OCCURRED__SHIFT 0x15
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCCG_PERFMON2_COUNTER5_INT_CLEAR_MASK 0x200000
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCCG_PERFMON2_COUNTER5_INT_CLEAR__SHIFT 0x15
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCCG_PERFMON2_COUNTER6_INT_OCCURRED_MASK 0x400000
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCCG_PERFMON2_COUNTER6_INT_OCCURRED__SHIFT 0x16
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCCG_PERFMON2_COUNTER6_INT_CLEAR_MASK 0x400000
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCCG_PERFMON2_COUNTER6_INT_CLEAR__SHIFT 0x16
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCCG_PERFMON2_COUNTER7_INT_OCCURRED_MASK 0x800000
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCCG_PERFMON2_COUNTER7_INT_OCCURRED__SHIFT 0x17
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCCG_PERFMON2_COUNTER7_INT_CLEAR_MASK 0x800000
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCCG_PERFMON2_COUNTER7_INT_CLEAR__SHIFT 0x17
+#define DMCU_PERFMON_INTERRUPT_STATUS4__WB_PERFMON_COUNTER_OFF_INT_OCCURRED_MASK 0x1000000
+#define DMCU_PERFMON_INTERRUPT_STATUS4__WB_PERFMON_COUNTER_OFF_INT_OCCURRED__SHIFT 0x18
+#define DMCU_PERFMON_INTERRUPT_STATUS4__WB_PERFMON_COUNTER_OFF_INT_CLEAR_MASK 0x1000000
+#define DMCU_PERFMON_INTERRUPT_STATUS4__WB_PERFMON_COUNTER_OFF_INT_CLEAR__SHIFT 0x18
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCRX_PERFMON_COUNTER_OFF_INT_OCCURRED_MASK 0x2000000
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCRX_PERFMON_COUNTER_OFF_INT_OCCURRED__SHIFT 0x19
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCRX_PERFMON_COUNTER_OFF_INT_CLEAR_MASK 0x2000000
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCRX_PERFMON_COUNTER_OFF_INT_CLEAR__SHIFT 0x19
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCCG_PERFMON2_COUNTER_OFF_INT_OCCURRED_MASK 0x4000000
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCCG_PERFMON2_COUNTER_OFF_INT_OCCURRED__SHIFT 0x1a
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCCG_PERFMON2_COUNTER_OFF_INT_CLEAR_MASK 0x4000000
+#define DMCU_PERFMON_INTERRUPT_STATUS4__DCCG_PERFMON2_COUNTER_OFF_INT_CLEAR__SHIFT 0x1a
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV0_PERFMON_COUNTER0_INT_OCCURRED_MASK 0x1
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV0_PERFMON_COUNTER0_INT_OCCURRED__SHIFT 0x0
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV0_PERFMON_COUNTER0_INT_CLEAR_MASK 0x1
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV0_PERFMON_COUNTER0_INT_CLEAR__SHIFT 0x0
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV0_PERFMON_COUNTER1_INT_OCCURRED_MASK 0x2
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV0_PERFMON_COUNTER1_INT_OCCURRED__SHIFT 0x1
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV0_PERFMON_COUNTER1_INT_CLEAR_MASK 0x2
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV0_PERFMON_COUNTER1_INT_CLEAR__SHIFT 0x1
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV0_PERFMON_COUNTER2_INT_OCCURRED_MASK 0x4
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV0_PERFMON_COUNTER2_INT_OCCURRED__SHIFT 0x2
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV0_PERFMON_COUNTER2_INT_CLEAR_MASK 0x4
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV0_PERFMON_COUNTER2_INT_CLEAR__SHIFT 0x2
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV0_PERFMON_COUNTER3_INT_OCCURRED_MASK 0x8
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV0_PERFMON_COUNTER3_INT_OCCURRED__SHIFT 0x3
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV0_PERFMON_COUNTER3_INT_CLEAR_MASK 0x8
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV0_PERFMON_COUNTER3_INT_CLEAR__SHIFT 0x3
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV0_PERFMON_COUNTER4_INT_OCCURRED_MASK 0x10
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV0_PERFMON_COUNTER4_INT_OCCURRED__SHIFT 0x4
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV0_PERFMON_COUNTER4_INT_CLEAR_MASK 0x10
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV0_PERFMON_COUNTER4_INT_CLEAR__SHIFT 0x4
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV0_PERFMON_COUNTER5_INT_OCCURRED_MASK 0x20
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV0_PERFMON_COUNTER5_INT_OCCURRED__SHIFT 0x5
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV0_PERFMON_COUNTER5_INT_CLEAR_MASK 0x20
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV0_PERFMON_COUNTER5_INT_CLEAR__SHIFT 0x5
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV0_PERFMON_COUNTER6_INT_OCCURRED_MASK 0x40
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV0_PERFMON_COUNTER6_INT_OCCURRED__SHIFT 0x6
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV0_PERFMON_COUNTER6_INT_CLEAR_MASK 0x40
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV0_PERFMON_COUNTER6_INT_CLEAR__SHIFT 0x6
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV0_PERFMON_COUNTER7_INT_OCCURRED_MASK 0x80
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV0_PERFMON_COUNTER7_INT_OCCURRED__SHIFT 0x7
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV0_PERFMON_COUNTER7_INT_CLEAR_MASK 0x80
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV0_PERFMON_COUNTER7_INT_CLEAR__SHIFT 0x7
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV1_PERFMON_COUNTER0_INT_OCCURRED_MASK 0x100
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV1_PERFMON_COUNTER0_INT_OCCURRED__SHIFT 0x8
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV1_PERFMON_COUNTER0_INT_CLEAR_MASK 0x100
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV1_PERFMON_COUNTER0_INT_CLEAR__SHIFT 0x8
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV1_PERFMON_COUNTER1_INT_OCCURRED_MASK 0x200
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV1_PERFMON_COUNTER1_INT_OCCURRED__SHIFT 0x9
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV1_PERFMON_COUNTER1_INT_CLEAR_MASK 0x200
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV1_PERFMON_COUNTER1_INT_CLEAR__SHIFT 0x9
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV1_PERFMON_COUNTER2_INT_OCCURRED_MASK 0x400
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV1_PERFMON_COUNTER2_INT_OCCURRED__SHIFT 0xa
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV1_PERFMON_COUNTER2_INT_CLEAR_MASK 0x400
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV1_PERFMON_COUNTER2_INT_CLEAR__SHIFT 0xa
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV1_PERFMON_COUNTER3_INT_OCCURRED_MASK 0x800
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV1_PERFMON_COUNTER3_INT_OCCURRED__SHIFT 0xb
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV1_PERFMON_COUNTER3_INT_CLEAR_MASK 0x800
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV1_PERFMON_COUNTER3_INT_CLEAR__SHIFT 0xb
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV1_PERFMON_COUNTER4_INT_OCCURRED_MASK 0x1000
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV1_PERFMON_COUNTER4_INT_OCCURRED__SHIFT 0xc
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV1_PERFMON_COUNTER4_INT_CLEAR_MASK 0x1000
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV1_PERFMON_COUNTER4_INT_CLEAR__SHIFT 0xc
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV1_PERFMON_COUNTER5_INT_OCCURRED_MASK 0x2000
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV1_PERFMON_COUNTER5_INT_OCCURRED__SHIFT 0xd
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV1_PERFMON_COUNTER5_INT_CLEAR_MASK 0x2000
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV1_PERFMON_COUNTER5_INT_CLEAR__SHIFT 0xd
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV1_PERFMON_COUNTER6_INT_OCCURRED_MASK 0x4000
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV1_PERFMON_COUNTER6_INT_OCCURRED__SHIFT 0xe
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV1_PERFMON_COUNTER6_INT_CLEAR_MASK 0x4000
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV1_PERFMON_COUNTER6_INT_CLEAR__SHIFT 0xe
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV1_PERFMON_COUNTER7_INT_OCCURRED_MASK 0x8000
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV1_PERFMON_COUNTER7_INT_OCCURRED__SHIFT 0xf
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV1_PERFMON_COUNTER7_INT_CLEAR_MASK 0x8000
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV1_PERFMON_COUNTER7_INT_CLEAR__SHIFT 0xf
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV0_PERFMON_COUNTER_OFF_INT_OCCURRED_MASK 0x10000
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV0_PERFMON_COUNTER_OFF_INT_OCCURRED__SHIFT 0x10
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV0_PERFMON_COUNTER_OFF_INT_CLEAR_MASK 0x10000
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV0_PERFMON_COUNTER_OFF_INT_CLEAR__SHIFT 0x10
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV1_PERFMON_COUNTER_OFF_INT_OCCURRED_MASK 0x20000
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV1_PERFMON_COUNTER_OFF_INT_OCCURRED__SHIFT 0x11
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV1_PERFMON_COUNTER_OFF_INT_CLEAR_MASK 0x20000
+#define DMCU_PERFMON_INTERRUPT_STATUS5__DCFEV1_PERFMON_COUNTER_OFF_INT_CLEAR__SHIFT 0x11
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCI_PERFMON_COUNTER0_INT_TO_UC_EN_MASK 0x1
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCI_PERFMON_COUNTER0_INT_TO_UC_EN__SHIFT 0x0
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCI_PERFMON_COUNTER1_INT_TO_UC_EN_MASK 0x2
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCI_PERFMON_COUNTER1_INT_TO_UC_EN__SHIFT 0x1
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCI_PERFMON_COUNTER2_INT_TO_UC_EN_MASK 0x4
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCI_PERFMON_COUNTER2_INT_TO_UC_EN__SHIFT 0x2
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCI_PERFMON_COUNTER3_INT_TO_UC_EN_MASK 0x8
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCI_PERFMON_COUNTER3_INT_TO_UC_EN__SHIFT 0x3
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCI_PERFMON_COUNTER4_INT_TO_UC_EN_MASK 0x10
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCI_PERFMON_COUNTER4_INT_TO_UC_EN__SHIFT 0x4
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCI_PERFMON_COUNTER5_INT_TO_UC_EN_MASK 0x20
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCI_PERFMON_COUNTER5_INT_TO_UC_EN__SHIFT 0x5
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCI_PERFMON_COUNTER6_INT_TO_UC_EN_MASK 0x40
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCI_PERFMON_COUNTER6_INT_TO_UC_EN__SHIFT 0x6
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCI_PERFMON_COUNTER7_INT_TO_UC_EN_MASK 0x80
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCI_PERFMON_COUNTER7_INT_TO_UC_EN__SHIFT 0x7
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCO_PERFMON_COUNTER0_INT_TO_UC_EN_MASK 0x100
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCO_PERFMON_COUNTER0_INT_TO_UC_EN__SHIFT 0x8
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCO_PERFMON_COUNTER1_INT_TO_UC_EN_MASK 0x200
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCO_PERFMON_COUNTER1_INT_TO_UC_EN__SHIFT 0x9
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCO_PERFMON_COUNTER2_INT_TO_UC_EN_MASK 0x400
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCO_PERFMON_COUNTER2_INT_TO_UC_EN__SHIFT 0xa
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCO_PERFMON_COUNTER3_INT_TO_UC_EN_MASK 0x800
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCO_PERFMON_COUNTER3_INT_TO_UC_EN__SHIFT 0xb
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCO_PERFMON_COUNTER4_INT_TO_UC_EN_MASK 0x1000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCO_PERFMON_COUNTER4_INT_TO_UC_EN__SHIFT 0xc
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCO_PERFMON_COUNTER5_INT_TO_UC_EN_MASK 0x2000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCO_PERFMON_COUNTER5_INT_TO_UC_EN__SHIFT 0xd
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCO_PERFMON_COUNTER6_INT_TO_UC_EN_MASK 0x4000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCO_PERFMON_COUNTER6_INT_TO_UC_EN__SHIFT 0xe
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCO_PERFMON_COUNTER7_INT_TO_UC_EN_MASK 0x8000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCO_PERFMON_COUNTER7_INT_TO_UC_EN__SHIFT 0xf
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCCG_PERFMON_COUNTER0_INT_TO_UC_EN_MASK 0x10000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCCG_PERFMON_COUNTER0_INT_TO_UC_EN__SHIFT 0x10
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCCG_PERFMON_COUNTER1_INT_TO_UC_EN_MASK 0x20000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCCG_PERFMON_COUNTER1_INT_TO_UC_EN__SHIFT 0x11
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCCG_PERFMON_COUNTER2_INT_TO_UC_EN_MASK 0x40000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCCG_PERFMON_COUNTER2_INT_TO_UC_EN__SHIFT 0x12
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCCG_PERFMON_COUNTER3_INT_TO_UC_EN_MASK 0x80000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCCG_PERFMON_COUNTER3_INT_TO_UC_EN__SHIFT 0x13
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCCG_PERFMON_COUNTER4_INT_TO_UC_EN_MASK 0x100000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCCG_PERFMON_COUNTER4_INT_TO_UC_EN__SHIFT 0x14
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCCG_PERFMON_COUNTER5_INT_TO_UC_EN_MASK 0x200000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCCG_PERFMON_COUNTER5_INT_TO_UC_EN__SHIFT 0x15
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCCG_PERFMON_COUNTER6_INT_TO_UC_EN_MASK 0x400000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCCG_PERFMON_COUNTER6_INT_TO_UC_EN__SHIFT 0x16
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCCG_PERFMON_COUNTER7_INT_TO_UC_EN_MASK 0x800000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCCG_PERFMON_COUNTER7_INT_TO_UC_EN__SHIFT 0x17
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCI_PERFMON_COUNTER_OFF_INT_TO_UC_EN_MASK 0x1000000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCI_PERFMON_COUNTER_OFF_INT_TO_UC_EN__SHIFT 0x18
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCO_PERFMON_COUNTER_OFF_INT_TO_UC_EN_MASK 0x2000000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCO_PERFMON_COUNTER_OFF_INT_TO_UC_EN__SHIFT 0x19
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCCG_PERFMON_COUNTER_OFF_INT_TO_UC_EN_MASK 0x4000000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK1__DCCG_PERFMON_COUNTER_OFF_INT_TO_UC_EN__SHIFT 0x1a
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE0_PERFMON_COUNTER0_INT_TO_UC_EN_MASK 0x1
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE0_PERFMON_COUNTER0_INT_TO_UC_EN__SHIFT 0x0
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE0_PERFMON_COUNTER1_INT_TO_UC_EN_MASK 0x2
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE0_PERFMON_COUNTER1_INT_TO_UC_EN__SHIFT 0x1
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE0_PERFMON_COUNTER2_INT_TO_UC_EN_MASK 0x4
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE0_PERFMON_COUNTER2_INT_TO_UC_EN__SHIFT 0x2
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE0_PERFMON_COUNTER3_INT_TO_UC_EN_MASK 0x8
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE0_PERFMON_COUNTER3_INT_TO_UC_EN__SHIFT 0x3
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE0_PERFMON_COUNTER4_INT_TO_UC_EN_MASK 0x10
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE0_PERFMON_COUNTER4_INT_TO_UC_EN__SHIFT 0x4
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE0_PERFMON_COUNTER5_INT_TO_UC_EN_MASK 0x20
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE0_PERFMON_COUNTER5_INT_TO_UC_EN__SHIFT 0x5
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE0_PERFMON_COUNTER6_INT_TO_UC_EN_MASK 0x40
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE0_PERFMON_COUNTER6_INT_TO_UC_EN__SHIFT 0x6
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE0_PERFMON_COUNTER7_INT_TO_UC_EN_MASK 0x80
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE0_PERFMON_COUNTER7_INT_TO_UC_EN__SHIFT 0x7
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE1_PERFMON_COUNTER0_INT_TO_UC_EN_MASK 0x100
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE1_PERFMON_COUNTER0_INT_TO_UC_EN__SHIFT 0x8
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE1_PERFMON_COUNTER1_INT_TO_UC_EN_MASK 0x200
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE1_PERFMON_COUNTER1_INT_TO_UC_EN__SHIFT 0x9
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE1_PERFMON_COUNTER2_INT_TO_UC_EN_MASK 0x400
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE1_PERFMON_COUNTER2_INT_TO_UC_EN__SHIFT 0xa
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE1_PERFMON_COUNTER3_INT_TO_UC_EN_MASK 0x800
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE1_PERFMON_COUNTER3_INT_TO_UC_EN__SHIFT 0xb
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE1_PERFMON_COUNTER4_INT_TO_UC_EN_MASK 0x1000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE1_PERFMON_COUNTER4_INT_TO_UC_EN__SHIFT 0xc
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE1_PERFMON_COUNTER5_INT_TO_UC_EN_MASK 0x2000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE1_PERFMON_COUNTER5_INT_TO_UC_EN__SHIFT 0xd
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE1_PERFMON_COUNTER6_INT_TO_UC_EN_MASK 0x4000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE1_PERFMON_COUNTER6_INT_TO_UC_EN__SHIFT 0xe
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE1_PERFMON_COUNTER7_INT_TO_UC_EN_MASK 0x8000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE1_PERFMON_COUNTER7_INT_TO_UC_EN__SHIFT 0xf
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE2_PERFMON_COUNTER0_INT_TO_UC_EN_MASK 0x10000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE2_PERFMON_COUNTER0_INT_TO_UC_EN__SHIFT 0x10
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE2_PERFMON_COUNTER1_INT_TO_UC_EN_MASK 0x20000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE2_PERFMON_COUNTER1_INT_TO_UC_EN__SHIFT 0x11
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE2_PERFMON_COUNTER2_INT_TO_UC_EN_MASK 0x40000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE2_PERFMON_COUNTER2_INT_TO_UC_EN__SHIFT 0x12
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE2_PERFMON_COUNTER3_INT_TO_UC_EN_MASK 0x80000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE2_PERFMON_COUNTER3_INT_TO_UC_EN__SHIFT 0x13
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE2_PERFMON_COUNTER4_INT_TO_UC_EN_MASK 0x100000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE2_PERFMON_COUNTER4_INT_TO_UC_EN__SHIFT 0x14
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE2_PERFMON_COUNTER5_INT_TO_UC_EN_MASK 0x200000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE2_PERFMON_COUNTER5_INT_TO_UC_EN__SHIFT 0x15
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE2_PERFMON_COUNTER6_INT_TO_UC_EN_MASK 0x400000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE2_PERFMON_COUNTER6_INT_TO_UC_EN__SHIFT 0x16
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE2_PERFMON_COUNTER7_INT_TO_UC_EN_MASK 0x800000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE2_PERFMON_COUNTER7_INT_TO_UC_EN__SHIFT 0x17
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE0_PERFMON_COUNTER_OFF_INT_TO_UC_EN_MASK 0x1000000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE0_PERFMON_COUNTER_OFF_INT_TO_UC_EN__SHIFT 0x18
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE1_PERFMON_COUNTER_OFF_INT_TO_UC_EN_MASK 0x2000000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE1_PERFMON_COUNTER_OFF_INT_TO_UC_EN__SHIFT 0x19
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE2_PERFMON_COUNTER_OFF_INT_TO_UC_EN_MASK 0x4000000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK2__DCFE2_PERFMON_COUNTER_OFF_INT_TO_UC_EN__SHIFT 0x1a
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE3_PERFMON_COUNTER0_INT_TO_UC_EN_MASK 0x1
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE3_PERFMON_COUNTER0_INT_TO_UC_EN__SHIFT 0x0
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE3_PERFMON_COUNTER1_INT_TO_UC_EN_MASK 0x2
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE3_PERFMON_COUNTER1_INT_TO_UC_EN__SHIFT 0x1
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE3_PERFMON_COUNTER2_INT_TO_UC_EN_MASK 0x4
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE3_PERFMON_COUNTER2_INT_TO_UC_EN__SHIFT 0x2
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE3_PERFMON_COUNTER3_INT_TO_UC_EN_MASK 0x8
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE3_PERFMON_COUNTER3_INT_TO_UC_EN__SHIFT 0x3
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE3_PERFMON_COUNTER4_INT_TO_UC_EN_MASK 0x10
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE3_PERFMON_COUNTER4_INT_TO_UC_EN__SHIFT 0x4
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE3_PERFMON_COUNTER5_INT_TO_UC_EN_MASK 0x20
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE3_PERFMON_COUNTER5_INT_TO_UC_EN__SHIFT 0x5
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE3_PERFMON_COUNTER6_INT_TO_UC_EN_MASK 0x40
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE3_PERFMON_COUNTER6_INT_TO_UC_EN__SHIFT 0x6
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE3_PERFMON_COUNTER7_INT_TO_UC_EN_MASK 0x80
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE3_PERFMON_COUNTER7_INT_TO_UC_EN__SHIFT 0x7
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE4_PERFMON_COUNTER0_INT_TO_UC_EN_MASK 0x100
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE4_PERFMON_COUNTER0_INT_TO_UC_EN__SHIFT 0x8
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE4_PERFMON_COUNTER1_INT_TO_UC_EN_MASK 0x200
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE4_PERFMON_COUNTER1_INT_TO_UC_EN__SHIFT 0x9
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE4_PERFMON_COUNTER2_INT_TO_UC_EN_MASK 0x400
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE4_PERFMON_COUNTER2_INT_TO_UC_EN__SHIFT 0xa
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE4_PERFMON_COUNTER3_INT_TO_UC_EN_MASK 0x800
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE4_PERFMON_COUNTER3_INT_TO_UC_EN__SHIFT 0xb
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE4_PERFMON_COUNTER4_INT_TO_UC_EN_MASK 0x1000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE4_PERFMON_COUNTER4_INT_TO_UC_EN__SHIFT 0xc
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE4_PERFMON_COUNTER5_INT_TO_UC_EN_MASK 0x2000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE4_PERFMON_COUNTER5_INT_TO_UC_EN__SHIFT 0xd
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE4_PERFMON_COUNTER6_INT_TO_UC_EN_MASK 0x4000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE4_PERFMON_COUNTER6_INT_TO_UC_EN__SHIFT 0xe
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE4_PERFMON_COUNTER7_INT_TO_UC_EN_MASK 0x8000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE4_PERFMON_COUNTER7_INT_TO_UC_EN__SHIFT 0xf
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE5_PERFMON_COUNTER0_INT_TO_UC_EN_MASK 0x10000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE5_PERFMON_COUNTER0_INT_TO_UC_EN__SHIFT 0x10
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE5_PERFMON_COUNTER1_INT_TO_UC_EN_MASK 0x20000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE5_PERFMON_COUNTER1_INT_TO_UC_EN__SHIFT 0x11
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE5_PERFMON_COUNTER2_INT_TO_UC_EN_MASK 0x40000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE5_PERFMON_COUNTER2_INT_TO_UC_EN__SHIFT 0x12
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE5_PERFMON_COUNTER3_INT_TO_UC_EN_MASK 0x80000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE5_PERFMON_COUNTER3_INT_TO_UC_EN__SHIFT 0x13
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE5_PERFMON_COUNTER4_INT_TO_UC_EN_MASK 0x100000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE5_PERFMON_COUNTER4_INT_TO_UC_EN__SHIFT 0x14
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE5_PERFMON_COUNTER5_INT_TO_UC_EN_MASK 0x200000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE5_PERFMON_COUNTER5_INT_TO_UC_EN__SHIFT 0x15
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE5_PERFMON_COUNTER6_INT_TO_UC_EN_MASK 0x400000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE5_PERFMON_COUNTER6_INT_TO_UC_EN__SHIFT 0x16
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE5_PERFMON_COUNTER7_INT_TO_UC_EN_MASK 0x800000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE5_PERFMON_COUNTER7_INT_TO_UC_EN__SHIFT 0x17
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE3_PERFMON_COUNTER_OFF_INT_TO_UC_EN_MASK 0x1000000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE3_PERFMON_COUNTER_OFF_INT_TO_UC_EN__SHIFT 0x18
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE4_PERFMON_COUNTER_OFF_INT_TO_UC_EN_MASK 0x2000000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE4_PERFMON_COUNTER_OFF_INT_TO_UC_EN__SHIFT 0x19
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE5_PERFMON_COUNTER_OFF_INT_TO_UC_EN_MASK 0x4000000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK3__DCFE5_PERFMON_COUNTER_OFF_INT_TO_UC_EN__SHIFT 0x1a
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__WB_PERFMON_COUNTER0_INT_TO_UC_EN_MASK 0x1
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__WB_PERFMON_COUNTER0_INT_TO_UC_EN__SHIFT 0x0
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__WB_PERFMON_COUNTER1_INT_TO_UC_EN_MASK 0x2
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__WB_PERFMON_COUNTER1_INT_TO_UC_EN__SHIFT 0x1
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__WB_PERFMON_COUNTER2_INT_TO_UC_EN_MASK 0x4
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__WB_PERFMON_COUNTER2_INT_TO_UC_EN__SHIFT 0x2
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__WB_PERFMON_COUNTER3_INT_TO_UC_EN_MASK 0x8
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__WB_PERFMON_COUNTER3_INT_TO_UC_EN__SHIFT 0x3
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__WB_PERFMON_COUNTER4_INT_TO_UC_EN_MASK 0x10
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__WB_PERFMON_COUNTER4_INT_TO_UC_EN__SHIFT 0x4
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__WB_PERFMON_COUNTER5_INT_TO_UC_EN_MASK 0x20
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__WB_PERFMON_COUNTER5_INT_TO_UC_EN__SHIFT 0x5
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__WB_PERFMON_COUNTER6_INT_TO_UC_EN_MASK 0x40
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__WB_PERFMON_COUNTER6_INT_TO_UC_EN__SHIFT 0x6
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__WB_PERFMON_COUNTER7_INT_TO_UC_EN_MASK 0x80
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__WB_PERFMON_COUNTER7_INT_TO_UC_EN__SHIFT 0x7
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__DCRX_PERFMON_COUNTER0_INT_TO_UC_EN_MASK 0x100
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__DCRX_PERFMON_COUNTER0_INT_TO_UC_EN__SHIFT 0x8
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__DCRX_PERFMON_COUNTER1_INT_TO_UC_EN_MASK 0x200
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__DCRX_PERFMON_COUNTER1_INT_TO_UC_EN__SHIFT 0x9
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__DCRX_PERFMON_COUNTER2_INT_TO_UC_EN_MASK 0x400
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__DCRX_PERFMON_COUNTER2_INT_TO_UC_EN__SHIFT 0xa
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__DCRX_PERFMON_COUNTER3_INT_TO_UC_EN_MASK 0x800
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__DCRX_PERFMON_COUNTER3_INT_TO_UC_EN__SHIFT 0xb
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__DCRX_PERFMON_COUNTER4_INT_TO_UC_EN_MASK 0x1000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__DCRX_PERFMON_COUNTER4_INT_TO_UC_EN__SHIFT 0xc
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__DCRX_PERFMON_COUNTER5_INT_TO_UC_EN_MASK 0x2000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__DCRX_PERFMON_COUNTER5_INT_TO_UC_EN__SHIFT 0xd
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__DCRX_PERFMON_COUNTER6_INT_TO_UC_EN_MASK 0x4000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__DCRX_PERFMON_COUNTER6_INT_TO_UC_EN__SHIFT 0xe
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__DCRX_PERFMON_COUNTER7_INT_TO_UC_EN_MASK 0x8000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__DCRX_PERFMON_COUNTER7_INT_TO_UC_EN__SHIFT 0xf
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__DCCG_PERFMON2_COUNTER0_INT_TO_UC_EN_MASK 0x10000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__DCCG_PERFMON2_COUNTER0_INT_TO_UC_EN__SHIFT 0x10
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__DCCG_PERFMON2_COUNTER1_INT_TO_UC_EN_MASK 0x20000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__DCCG_PERFMON2_COUNTER1_INT_TO_UC_EN__SHIFT 0x11
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__DCCG_PERFMON2_COUNTER2_INT_TO_UC_EN_MASK 0x40000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__DCCG_PERFMON2_COUNTER2_INT_TO_UC_EN__SHIFT 0x12
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__DCCG_PERFMON2_COUNTER3_INT_TO_UC_EN_MASK 0x80000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__DCCG_PERFMON2_COUNTER3_INT_TO_UC_EN__SHIFT 0x13
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__DCCG_PERFMON2_COUNTER4_INT_TO_UC_EN_MASK 0x100000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__DCCG_PERFMON2_COUNTER4_INT_TO_UC_EN__SHIFT 0x14
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__DCCG_PERFMON2_COUNTER5_INT_TO_UC_EN_MASK 0x200000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__DCCG_PERFMON2_COUNTER5_INT_TO_UC_EN__SHIFT 0x15
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__DCCG_PERFMON2_COUNTER6_INT_TO_UC_EN_MASK 0x400000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__DCCG_PERFMON2_COUNTER6_INT_TO_UC_EN__SHIFT 0x16
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__DCCG_PERFMON2_COUNTER7_INT_TO_UC_EN_MASK 0x800000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__DCCG_PERFMON2_COUNTER7_INT_TO_UC_EN__SHIFT 0x17
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__WB_PERFMON_COUNTER_OFF_INT_TO_UC_EN_MASK 0x1000000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__WB_PERFMON_COUNTER_OFF_INT_TO_UC_EN__SHIFT 0x18
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__DCRX_PERFMON_COUNTER_OFF_INT_TO_UC_EN_MASK 0x2000000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__DCRX_PERFMON_COUNTER_OFF_INT_TO_UC_EN__SHIFT 0x19
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__DCCG_PERFMON2_COUNTER_OFF_INT_TO_UC_EN_MASK 0x4000000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK4__DCCG_PERFMON2_COUNTER_OFF_INT_TO_UC_EN__SHIFT 0x1a
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK5__DCFEV0_PERFMON_COUNTER0_INT_TO_UC_EN_MASK 0x1
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK5__DCFEV0_PERFMON_COUNTER0_INT_TO_UC_EN__SHIFT 0x0
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK5__DCFEV0_PERFMON_COUNTER1_INT_TO_UC_EN_MASK 0x2
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK5__DCFEV0_PERFMON_COUNTER1_INT_TO_UC_EN__SHIFT 0x1
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK5__DCFEV0_PERFMON_COUNTER2_INT_TO_UC_EN_MASK 0x4
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK5__DCFEV0_PERFMON_COUNTER2_INT_TO_UC_EN__SHIFT 0x2
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK5__DCFEV0_PERFMON_COUNTER3_INT_TO_UC_EN_MASK 0x8
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK5__DCFEV0_PERFMON_COUNTER3_INT_TO_UC_EN__SHIFT 0x3
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK5__DCFEV0_PERFMON_COUNTER4_INT_TO_UC_EN_MASK 0x10
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK5__DCFEV0_PERFMON_COUNTER4_INT_TO_UC_EN__SHIFT 0x4
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK5__DCFEV0_PERFMON_COUNTER5_INT_TO_UC_EN_MASK 0x20
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK5__DCFEV0_PERFMON_COUNTER5_INT_TO_UC_EN__SHIFT 0x5
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK5__DCFEV0_PERFMON_COUNTER6_INT_TO_UC_EN_MASK 0x40
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK5__DCFEV0_PERFMON_COUNTER6_INT_TO_UC_EN__SHIFT 0x6
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK5__DCFEV0_PERFMON_COUNTER7_INT_TO_UC_EN_MASK 0x80
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK5__DCFEV0_PERFMON_COUNTER7_INT_TO_UC_EN__SHIFT 0x7
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK5__DCFEV0_PERFMON_COUNTER_OFF_INT_TO_UC_EN_MASK 0x100
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK5__DCFEV0_PERFMON_COUNTER_OFF_INT_TO_UC_EN__SHIFT 0x8
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK5__DCFEV1_PERFMON_COUNTER0_INT_TO_UC_EN_MASK 0x200
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK5__DCFEV1_PERFMON_COUNTER0_INT_TO_UC_EN__SHIFT 0x9
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK5__DCFEV1_PERFMON_COUNTER1_INT_TO_UC_EN_MASK 0x400
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK5__DCFEV1_PERFMON_COUNTER1_INT_TO_UC_EN__SHIFT 0xa
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK5__DCFEV1_PERFMON_COUNTER2_INT_TO_UC_EN_MASK 0x800
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK5__DCFEV1_PERFMON_COUNTER2_INT_TO_UC_EN__SHIFT 0xb
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK5__DCFEV1_PERFMON_COUNTER3_INT_TO_UC_EN_MASK 0x1000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK5__DCFEV1_PERFMON_COUNTER3_INT_TO_UC_EN__SHIFT 0xc
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK5__DCFEV1_PERFMON_COUNTER4_INT_TO_UC_EN_MASK 0x2000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK5__DCFEV1_PERFMON_COUNTER4_INT_TO_UC_EN__SHIFT 0xd
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK5__DCFEV1_PERFMON_COUNTER5_INT_TO_UC_EN_MASK 0x4000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK5__DCFEV1_PERFMON_COUNTER5_INT_TO_UC_EN__SHIFT 0xe
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK5__DCFEV1_PERFMON_COUNTER6_INT_TO_UC_EN_MASK 0x8000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK5__DCFEV1_PERFMON_COUNTER6_INT_TO_UC_EN__SHIFT 0xf
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK5__DCFEV1_PERFMON_COUNTER7_INT_TO_UC_EN_MASK 0x10000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK5__DCFEV1_PERFMON_COUNTER7_INT_TO_UC_EN__SHIFT 0x10
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK5__DCFEV1_PERFMON_COUNTER_OFF_INT_TO_UC_EN_MASK 0x20000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_EN_MASK5__DCFEV1_PERFMON_COUNTER_OFF_INT_TO_UC_EN__SHIFT 0x11
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCI_PERFMON_COUNTER0_INT_XIRQ_IRQ_SEL_MASK 0x1
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCI_PERFMON_COUNTER0_INT_XIRQ_IRQ_SEL__SHIFT 0x0
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCI_PERFMON_COUNTER1_INT_XIRQ_IRQ_SEL_MASK 0x2
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCI_PERFMON_COUNTER1_INT_XIRQ_IRQ_SEL__SHIFT 0x1
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCI_PERFMON_COUNTER2_INT_XIRQ_IRQ_SEL_MASK 0x4
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCI_PERFMON_COUNTER2_INT_XIRQ_IRQ_SEL__SHIFT 0x2
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCI_PERFMON_COUNTER3_INT_XIRQ_IRQ_SEL_MASK 0x8
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCI_PERFMON_COUNTER3_INT_XIRQ_IRQ_SEL__SHIFT 0x3
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCI_PERFMON_COUNTER4_INT_XIRQ_IRQ_SEL_MASK 0x10
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCI_PERFMON_COUNTER4_INT_XIRQ_IRQ_SEL__SHIFT 0x4
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCI_PERFMON_COUNTER5_INT_XIRQ_IRQ_SEL_MASK 0x20
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCI_PERFMON_COUNTER5_INT_XIRQ_IRQ_SEL__SHIFT 0x5
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCI_PERFMON_COUNTER6_INT_XIRQ_IRQ_SEL_MASK 0x40
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCI_PERFMON_COUNTER6_INT_XIRQ_IRQ_SEL__SHIFT 0x6
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCI_PERFMON_COUNTER7_INT_XIRQ_IRQ_SEL_MASK 0x80
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCI_PERFMON_COUNTER7_INT_XIRQ_IRQ_SEL__SHIFT 0x7
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCO_PERFMON_COUNTER0_INT_XIRQ_IRQ_SEL_MASK 0x100
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCO_PERFMON_COUNTER0_INT_XIRQ_IRQ_SEL__SHIFT 0x8
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCO_PERFMON_COUNTER1_INT_XIRQ_IRQ_SEL_MASK 0x200
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCO_PERFMON_COUNTER1_INT_XIRQ_IRQ_SEL__SHIFT 0x9
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCO_PERFMON_COUNTER2_INT_XIRQ_IRQ_SEL_MASK 0x400
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCO_PERFMON_COUNTER2_INT_XIRQ_IRQ_SEL__SHIFT 0xa
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCO_PERFMON_COUNTER3_INT_XIRQ_IRQ_SEL_MASK 0x800
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCO_PERFMON_COUNTER3_INT_XIRQ_IRQ_SEL__SHIFT 0xb
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCO_PERFMON_COUNTER4_INT_XIRQ_IRQ_SEL_MASK 0x1000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCO_PERFMON_COUNTER4_INT_XIRQ_IRQ_SEL__SHIFT 0xc
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCO_PERFMON_COUNTER5_INT_XIRQ_IRQ_SEL_MASK 0x2000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCO_PERFMON_COUNTER5_INT_XIRQ_IRQ_SEL__SHIFT 0xd
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCO_PERFMON_COUNTER6_INT_XIRQ_IRQ_SEL_MASK 0x4000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCO_PERFMON_COUNTER6_INT_XIRQ_IRQ_SEL__SHIFT 0xe
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCO_PERFMON_COUNTER7_INT_XIRQ_IRQ_SEL_MASK 0x8000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCO_PERFMON_COUNTER7_INT_XIRQ_IRQ_SEL__SHIFT 0xf
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCCG_PERFMON_COUNTER0_INT_XIRQ_IRQ_SEL_MASK 0x10000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCCG_PERFMON_COUNTER0_INT_XIRQ_IRQ_SEL__SHIFT 0x10
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCCG_PERFMON_COUNTER1_INT_XIRQ_IRQ_SEL_MASK 0x20000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCCG_PERFMON_COUNTER1_INT_XIRQ_IRQ_SEL__SHIFT 0x11
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCCG_PERFMON_COUNTER2_INT_XIRQ_IRQ_SEL_MASK 0x40000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCCG_PERFMON_COUNTER2_INT_XIRQ_IRQ_SEL__SHIFT 0x12
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCCG_PERFMON_COUNTER3_INT_XIRQ_IRQ_SEL_MASK 0x80000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCCG_PERFMON_COUNTER3_INT_XIRQ_IRQ_SEL__SHIFT 0x13
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCCG_PERFMON_COUNTER4_INT_XIRQ_IRQ_SEL_MASK 0x100000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCCG_PERFMON_COUNTER4_INT_XIRQ_IRQ_SEL__SHIFT 0x14
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCCG_PERFMON_COUNTER5_INT_XIRQ_IRQ_SEL_MASK 0x200000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCCG_PERFMON_COUNTER5_INT_XIRQ_IRQ_SEL__SHIFT 0x15
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCCG_PERFMON_COUNTER6_INT_XIRQ_IRQ_SEL_MASK 0x400000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCCG_PERFMON_COUNTER6_INT_XIRQ_IRQ_SEL__SHIFT 0x16
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCCG_PERFMON_COUNTER7_INT_XIRQ_IRQ_SEL_MASK 0x800000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCCG_PERFMON_COUNTER7_INT_XIRQ_IRQ_SEL__SHIFT 0x17
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCI_PERFMON_COUNTER_OFF_INT_XIRQ_IRQ_SEL_MASK 0x1000000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCI_PERFMON_COUNTER_OFF_INT_XIRQ_IRQ_SEL__SHIFT 0x18
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCO_PERFMON_COUNTER_OFF_INT_XIRQ_IRQ_SEL_MASK 0x2000000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCO_PERFMON_COUNTER_OFF_INT_XIRQ_IRQ_SEL__SHIFT 0x19
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCCG_PERFMON_COUNTER_OFF_INT_XIRQ_IRQ_SEL_MASK 0x4000000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DCCG_PERFMON_COUNTER_OFF_INT_XIRQ_IRQ_SEL__SHIFT 0x1a
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE0_PERFMON_COUNTER0_INT_XIRQ_IRQ_SEL_MASK 0x1
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE0_PERFMON_COUNTER0_INT_XIRQ_IRQ_SEL__SHIFT 0x0
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE0_PERFMON_COUNTER1_INT_XIRQ_IRQ_SEL_MASK 0x2
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE0_PERFMON_COUNTER1_INT_XIRQ_IRQ_SEL__SHIFT 0x1
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE0_PERFMON_COUNTER2_INT_XIRQ_IRQ_SEL_MASK 0x4
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE0_PERFMON_COUNTER2_INT_XIRQ_IRQ_SEL__SHIFT 0x2
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE0_PERFMON_COUNTER3_INT_XIRQ_IRQ_SEL_MASK 0x8
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE0_PERFMON_COUNTER3_INT_XIRQ_IRQ_SEL__SHIFT 0x3
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE0_PERFMON_COUNTER4_INT_XIRQ_IRQ_SEL_MASK 0x10
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE0_PERFMON_COUNTER4_INT_XIRQ_IRQ_SEL__SHIFT 0x4
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE0_PERFMON_COUNTER5_INT_XIRQ_IRQ_SEL_MASK 0x20
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE0_PERFMON_COUNTER5_INT_XIRQ_IRQ_SEL__SHIFT 0x5
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE0_PERFMON_COUNTER6_INT_XIRQ_IRQ_SEL_MASK 0x40
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE0_PERFMON_COUNTER6_INT_XIRQ_IRQ_SEL__SHIFT 0x6
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE0_PERFMON_COUNTER7_INT_XIRQ_IRQ_SEL_MASK 0x80
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE0_PERFMON_COUNTER7_INT_XIRQ_IRQ_SEL__SHIFT 0x7
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE1_PERFMON_COUNTER0_INT_XIRQ_IRQ_SEL_MASK 0x100
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE1_PERFMON_COUNTER0_INT_XIRQ_IRQ_SEL__SHIFT 0x8
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE1_PERFMON_COUNTER1_INT_XIRQ_IRQ_SEL_MASK 0x200
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE1_PERFMON_COUNTER1_INT_XIRQ_IRQ_SEL__SHIFT 0x9
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE1_PERFMON_COUNTER2_INT_XIRQ_IRQ_SEL_MASK 0x400
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE1_PERFMON_COUNTER2_INT_XIRQ_IRQ_SEL__SHIFT 0xa
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE1_PERFMON_COUNTER3_INT_XIRQ_IRQ_SEL_MASK 0x800
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE1_PERFMON_COUNTER3_INT_XIRQ_IRQ_SEL__SHIFT 0xb
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE1_PERFMON_COUNTER4_INT_XIRQ_IRQ_SEL_MASK 0x1000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE1_PERFMON_COUNTER4_INT_XIRQ_IRQ_SEL__SHIFT 0xc
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE1_PERFMON_COUNTER5_INT_XIRQ_IRQ_SEL_MASK 0x2000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE1_PERFMON_COUNTER5_INT_XIRQ_IRQ_SEL__SHIFT 0xd
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE1_PERFMON_COUNTER6_INT_XIRQ_IRQ_SEL_MASK 0x4000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE1_PERFMON_COUNTER6_INT_XIRQ_IRQ_SEL__SHIFT 0xe
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE1_PERFMON_COUNTER7_INT_XIRQ_IRQ_SEL_MASK 0x8000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE1_PERFMON_COUNTER7_INT_XIRQ_IRQ_SEL__SHIFT 0xf
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE2_PERFMON_COUNTER0_INT_XIRQ_IRQ_SEL_MASK 0x10000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE2_PERFMON_COUNTER0_INT_XIRQ_IRQ_SEL__SHIFT 0x10
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE2_PERFMON_COUNTER1_INT_XIRQ_IRQ_SEL_MASK 0x20000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE2_PERFMON_COUNTER1_INT_XIRQ_IRQ_SEL__SHIFT 0x11
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE2_PERFMON_COUNTER2_INT_XIRQ_IRQ_SEL_MASK 0x40000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE2_PERFMON_COUNTER2_INT_XIRQ_IRQ_SEL__SHIFT 0x12
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE2_PERFMON_COUNTER3_INT_XIRQ_IRQ_SEL_MASK 0x80000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE2_PERFMON_COUNTER3_INT_XIRQ_IRQ_SEL__SHIFT 0x13
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE2_PERFMON_COUNTER4_INT_XIRQ_IRQ_SEL_MASK 0x100000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE2_PERFMON_COUNTER4_INT_XIRQ_IRQ_SEL__SHIFT 0x14
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE2_PERFMON_COUNTER5_INT_XIRQ_IRQ_SEL_MASK 0x200000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE2_PERFMON_COUNTER5_INT_XIRQ_IRQ_SEL__SHIFT 0x15
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE2_PERFMON_COUNTER6_INT_XIRQ_IRQ_SEL_MASK 0x400000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE2_PERFMON_COUNTER6_INT_XIRQ_IRQ_SEL__SHIFT 0x16
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE2_PERFMON_COUNTER7_INT_XIRQ_IRQ_SEL_MASK 0x800000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE2_PERFMON_COUNTER7_INT_XIRQ_IRQ_SEL__SHIFT 0x17
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE0_PERFMON_COUNTER_OFF_INT_XIRQ_IRQ_SEL_MASK 0x1000000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE0_PERFMON_COUNTER_OFF_INT_XIRQ_IRQ_SEL__SHIFT 0x18
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE1_PERFMON_COUNTER_OFF_INT_XIRQ_IRQ_SEL_MASK 0x2000000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE1_PERFMON_COUNTER_OFF_INT_XIRQ_IRQ_SEL__SHIFT 0x19
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE2_PERFMON_COUNTER_OFF_INT_XIRQ_IRQ_SEL_MASK 0x4000000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL2__DCFE2_PERFMON_COUNTER_OFF_INT_XIRQ_IRQ_SEL__SHIFT 0x1a
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE3_PERFMON_COUNTER0_INT_XIRQ_IRQ_SEL_MASK 0x1
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE3_PERFMON_COUNTER0_INT_XIRQ_IRQ_SEL__SHIFT 0x0
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE3_PERFMON_COUNTER1_INT_XIRQ_IRQ_SEL_MASK 0x2
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE3_PERFMON_COUNTER1_INT_XIRQ_IRQ_SEL__SHIFT 0x1
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE3_PERFMON_COUNTER2_INT_XIRQ_IRQ_SEL_MASK 0x4
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE3_PERFMON_COUNTER2_INT_XIRQ_IRQ_SEL__SHIFT 0x2
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE3_PERFMON_COUNTER3_INT_XIRQ_IRQ_SEL_MASK 0x8
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE3_PERFMON_COUNTER3_INT_XIRQ_IRQ_SEL__SHIFT 0x3
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE3_PERFMON_COUNTER4_INT_XIRQ_IRQ_SEL_MASK 0x10
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE3_PERFMON_COUNTER4_INT_XIRQ_IRQ_SEL__SHIFT 0x4
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE3_PERFMON_COUNTER5_INT_XIRQ_IRQ_SEL_MASK 0x20
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE3_PERFMON_COUNTER5_INT_XIRQ_IRQ_SEL__SHIFT 0x5
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE3_PERFMON_COUNTER6_INT_XIRQ_IRQ_SEL_MASK 0x40
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE3_PERFMON_COUNTER6_INT_XIRQ_IRQ_SEL__SHIFT 0x6
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE3_PERFMON_COUNTER7_INT_XIRQ_IRQ_SEL_MASK 0x80
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE3_PERFMON_COUNTER7_INT_XIRQ_IRQ_SEL__SHIFT 0x7
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE4_PERFMON_COUNTER0_INT_XIRQ_IRQ_SEL_MASK 0x100
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE4_PERFMON_COUNTER0_INT_XIRQ_IRQ_SEL__SHIFT 0x8
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE4_PERFMON_COUNTER1_INT_XIRQ_IRQ_SEL_MASK 0x200
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE4_PERFMON_COUNTER1_INT_XIRQ_IRQ_SEL__SHIFT 0x9
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE4_PERFMON_COUNTER2_INT_XIRQ_IRQ_SEL_MASK 0x400
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE4_PERFMON_COUNTER2_INT_XIRQ_IRQ_SEL__SHIFT 0xa
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE4_PERFMON_COUNTER3_INT_XIRQ_IRQ_SEL_MASK 0x800
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE4_PERFMON_COUNTER3_INT_XIRQ_IRQ_SEL__SHIFT 0xb
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE4_PERFMON_COUNTER4_INT_XIRQ_IRQ_SEL_MASK 0x1000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE4_PERFMON_COUNTER4_INT_XIRQ_IRQ_SEL__SHIFT 0xc
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE4_PERFMON_COUNTER5_INT_XIRQ_IRQ_SEL_MASK 0x2000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE4_PERFMON_COUNTER5_INT_XIRQ_IRQ_SEL__SHIFT 0xd
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE4_PERFMON_COUNTER6_INT_XIRQ_IRQ_SEL_MASK 0x4000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE4_PERFMON_COUNTER6_INT_XIRQ_IRQ_SEL__SHIFT 0xe
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE4_PERFMON_COUNTER7_INT_XIRQ_IRQ_SEL_MASK 0x8000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE4_PERFMON_COUNTER7_INT_XIRQ_IRQ_SEL__SHIFT 0xf
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE5_PERFMON_COUNTER0_INT_XIRQ_IRQ_SEL_MASK 0x10000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE5_PERFMON_COUNTER0_INT_XIRQ_IRQ_SEL__SHIFT 0x10
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE5_PERFMON_COUNTER1_INT_XIRQ_IRQ_SEL_MASK 0x20000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE5_PERFMON_COUNTER1_INT_XIRQ_IRQ_SEL__SHIFT 0x11
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE5_PERFMON_COUNTER2_INT_XIRQ_IRQ_SEL_MASK 0x40000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE5_PERFMON_COUNTER2_INT_XIRQ_IRQ_SEL__SHIFT 0x12
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE5_PERFMON_COUNTER3_INT_XIRQ_IRQ_SEL_MASK 0x80000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE5_PERFMON_COUNTER3_INT_XIRQ_IRQ_SEL__SHIFT 0x13
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE5_PERFMON_COUNTER4_INT_XIRQ_IRQ_SEL_MASK 0x100000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE5_PERFMON_COUNTER4_INT_XIRQ_IRQ_SEL__SHIFT 0x14
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE5_PERFMON_COUNTER5_INT_XIRQ_IRQ_SEL_MASK 0x200000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE5_PERFMON_COUNTER5_INT_XIRQ_IRQ_SEL__SHIFT 0x15
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE5_PERFMON_COUNTER6_INT_XIRQ_IRQ_SEL_MASK 0x400000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE5_PERFMON_COUNTER6_INT_XIRQ_IRQ_SEL__SHIFT 0x16
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE5_PERFMON_COUNTER7_INT_XIRQ_IRQ_SEL_MASK 0x800000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE5_PERFMON_COUNTER7_INT_XIRQ_IRQ_SEL__SHIFT 0x17
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE3_PERFMON_COUNTER_OFF_INT_XIRQ_IRQ_SEL_MASK 0x1000000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE3_PERFMON_COUNTER_OFF_INT_XIRQ_IRQ_SEL__SHIFT 0x18
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE4_PERFMON_COUNTER_OFF_INT_XIRQ_IRQ_SEL_MASK 0x2000000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE4_PERFMON_COUNTER_OFF_INT_XIRQ_IRQ_SEL__SHIFT 0x19
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE5_PERFMON_COUNTER_OFF_INT_XIRQ_IRQ_SEL_MASK 0x4000000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL3__DCFE5_PERFMON_COUNTER_OFF_INT_XIRQ_IRQ_SEL__SHIFT 0x1a
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__WB_PERFMON_COUNTER0_INT_XIRQ_IRQ_SEL_MASK 0x1
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__WB_PERFMON_COUNTER0_INT_XIRQ_IRQ_SEL__SHIFT 0x0
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__WB_PERFMON_COUNTER1_INT_XIRQ_IRQ_SEL_MASK 0x2
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__WB_PERFMON_COUNTER1_INT_XIRQ_IRQ_SEL__SHIFT 0x1
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__WB_PERFMON_COUNTER2_INT_XIRQ_IRQ_SEL_MASK 0x4
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__WB_PERFMON_COUNTER2_INT_XIRQ_IRQ_SEL__SHIFT 0x2
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__WB_PERFMON_COUNTER3_INT_XIRQ_IRQ_SEL_MASK 0x8
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__WB_PERFMON_COUNTER3_INT_XIRQ_IRQ_SEL__SHIFT 0x3
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__WB_PERFMON_COUNTER4_INT_XIRQ_IRQ_SEL_MASK 0x10
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__WB_PERFMON_COUNTER4_INT_XIRQ_IRQ_SEL__SHIFT 0x4
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__WB_PERFMON_COUNTER5_INT_XIRQ_IRQ_SEL_MASK 0x20
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__WB_PERFMON_COUNTER5_INT_XIRQ_IRQ_SEL__SHIFT 0x5
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__WB_PERFMON_COUNTER6_INT_XIRQ_IRQ_SEL_MASK 0x40
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__WB_PERFMON_COUNTER6_INT_XIRQ_IRQ_SEL__SHIFT 0x6
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__WB_PERFMON_COUNTER7_INT_XIRQ_IRQ_SEL_MASK 0x80
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__WB_PERFMON_COUNTER7_INT_XIRQ_IRQ_SEL__SHIFT 0x7
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__DCRX_PERFMON_COUNTER0_INT_XIRQ_IRQ_SEL_MASK 0x100
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__DCRX_PERFMON_COUNTER0_INT_XIRQ_IRQ_SEL__SHIFT 0x8
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__DCRX_PERFMON_COUNTER1_INT_XIRQ_IRQ_SEL_MASK 0x200
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__DCRX_PERFMON_COUNTER1_INT_XIRQ_IRQ_SEL__SHIFT 0x9
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__DCRX_PERFMON_COUNTER2_INT_XIRQ_IRQ_SEL_MASK 0x400
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__DCRX_PERFMON_COUNTER2_INT_XIRQ_IRQ_SEL__SHIFT 0xa
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__DCRX_PERFMON_COUNTER3_INT_XIRQ_IRQ_SEL_MASK 0x800
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__DCRX_PERFMON_COUNTER3_INT_XIRQ_IRQ_SEL__SHIFT 0xb
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__DCRX_PERFMON_COUNTER4_INT_XIRQ_IRQ_SEL_MASK 0x1000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__DCRX_PERFMON_COUNTER4_INT_XIRQ_IRQ_SEL__SHIFT 0xc
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__DCRX_PERFMON_COUNTER5_INT_XIRQ_IRQ_SEL_MASK 0x2000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__DCRX_PERFMON_COUNTER5_INT_XIRQ_IRQ_SEL__SHIFT 0xd
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__DCRX_PERFMON_COUNTER6_INT_XIRQ_IRQ_SEL_MASK 0x4000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__DCRX_PERFMON_COUNTER6_INT_XIRQ_IRQ_SEL__SHIFT 0xe
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__DCRX_PERFMON_COUNTER7_INT_XIRQ_IRQ_SEL_MASK 0x8000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__DCRX_PERFMON_COUNTER7_INT_XIRQ_IRQ_SEL__SHIFT 0xf
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__DCCG_PERFMON2_COUNTER0_INT_XIRQ_IRQ_SEL_MASK 0x10000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__DCCG_PERFMON2_COUNTER0_INT_XIRQ_IRQ_SEL__SHIFT 0x10
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__DCCG_PERFMON2_COUNTER1_INT_XIRQ_IRQ_SEL_MASK 0x20000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__DCCG_PERFMON2_COUNTER1_INT_XIRQ_IRQ_SEL__SHIFT 0x11
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__DCCG_PERFMON2_COUNTER2_INT_XIRQ_IRQ_SEL_MASK 0x40000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__DCCG_PERFMON2_COUNTER2_INT_XIRQ_IRQ_SEL__SHIFT 0x12
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__DCCG_PERFMON2_COUNTER3_INT_XIRQ_IRQ_SEL_MASK 0x80000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__DCCG_PERFMON2_COUNTER3_INT_XIRQ_IRQ_SEL__SHIFT 0x13
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__DCCG_PERFMON2_COUNTER4_INT_XIRQ_IRQ_SEL_MASK 0x100000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__DCCG_PERFMON2_COUNTER4_INT_XIRQ_IRQ_SEL__SHIFT 0x14
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__DCCG_PERFMON2_COUNTER5_INT_XIRQ_IRQ_SEL_MASK 0x200000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__DCCG_PERFMON2_COUNTER5_INT_XIRQ_IRQ_SEL__SHIFT 0x15
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__DCCG_PERFMON2_COUNTER6_INT_XIRQ_IRQ_SEL_MASK 0x400000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__DCCG_PERFMON2_COUNTER6_INT_XIRQ_IRQ_SEL__SHIFT 0x16
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__DCCG_PERFMON2_COUNTER7_INT_XIRQ_IRQ_SEL_MASK 0x800000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__DCCG_PERFMON2_COUNTER7_INT_XIRQ_IRQ_SEL__SHIFT 0x17
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__WB_PERFMON_COUNTER_OFF_INT_XIRQ_IRQ_SEL_MASK 0x1000000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__WB_PERFMON_COUNTER_OFF_INT_XIRQ_IRQ_SEL__SHIFT 0x18
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__DCRX_PERFMON_COUNTER_OFF_INT_XIRQ_IRQ_SEL_MASK 0x2000000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__DCRX_PERFMON_COUNTER_OFF_INT_XIRQ_IRQ_SEL__SHIFT 0x19
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__DCCG_PERFMON2_COUNTER_OFF_INT_XIRQ_IRQ_SEL_MASK 0x4000000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL4__DCCG_PERFMON2_COUNTER_OFF_INT_XIRQ_IRQ_SEL__SHIFT 0x1a
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL5__DCFEV0_PERFMON_COUNTER0_INT_XIRQ_IRQ_SEL_MASK 0x1
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL5__DCFEV0_PERFMON_COUNTER0_INT_XIRQ_IRQ_SEL__SHIFT 0x0
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL5__DCFEV0_PERFMON_COUNTER1_INT_XIRQ_IRQ_SEL_MASK 0x2
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL5__DCFEV0_PERFMON_COUNTER1_INT_XIRQ_IRQ_SEL__SHIFT 0x1
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL5__DCFEV0_PERFMON_COUNTER2_INT_XIRQ_IRQ_SEL_MASK 0x4
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL5__DCFEV0_PERFMON_COUNTER2_INT_XIRQ_IRQ_SEL__SHIFT 0x2
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL5__DCFEV0_PERFMON_COUNTER3_INT_XIRQ_IRQ_SEL_MASK 0x8
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL5__DCFEV0_PERFMON_COUNTER3_INT_XIRQ_IRQ_SEL__SHIFT 0x3
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL5__DCFEV0_PERFMON_COUNTER4_INT_XIRQ_IRQ_SEL_MASK 0x10
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL5__DCFEV0_PERFMON_COUNTER4_INT_XIRQ_IRQ_SEL__SHIFT 0x4
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL5__DCFEV0_PERFMON_COUNTER5_INT_XIRQ_IRQ_SEL_MASK 0x20
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL5__DCFEV0_PERFMON_COUNTER5_INT_XIRQ_IRQ_SEL__SHIFT 0x5
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL5__DCFEV0_PERFMON_COUNTER6_INT_XIRQ_IRQ_SEL_MASK 0x40
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL5__DCFEV0_PERFMON_COUNTER6_INT_XIRQ_IRQ_SEL__SHIFT 0x6
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL5__DCFEV0_PERFMON_COUNTER7_INT_XIRQ_IRQ_SEL_MASK 0x80
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL5__DCFEV0_PERFMON_COUNTER7_INT_XIRQ_IRQ_SEL__SHIFT 0x7
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL5__DCFEV0_PERFMON_COUNTER_OFF_INT_XIRQ_IRQ_SEL_MASK 0x100
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL5__DCFEV0_PERFMON_COUNTER_OFF_INT_XIRQ_IRQ_SEL__SHIFT 0x8
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL5__DCFEV1_PERFMON_COUNTER0_INT_XIRQ_IRQ_SEL_MASK 0x200
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL5__DCFEV1_PERFMON_COUNTER0_INT_XIRQ_IRQ_SEL__SHIFT 0x9
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL5__DCFEV1_PERFMON_COUNTER1_INT_XIRQ_IRQ_SEL_MASK 0x400
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL5__DCFEV1_PERFMON_COUNTER1_INT_XIRQ_IRQ_SEL__SHIFT 0xa
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL5__DCFEV1_PERFMON_COUNTER2_INT_XIRQ_IRQ_SEL_MASK 0x800
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL5__DCFEV1_PERFMON_COUNTER2_INT_XIRQ_IRQ_SEL__SHIFT 0xb
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL5__DCFEV1_PERFMON_COUNTER3_INT_XIRQ_IRQ_SEL_MASK 0x1000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL5__DCFEV1_PERFMON_COUNTER3_INT_XIRQ_IRQ_SEL__SHIFT 0xc
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL5__DCFEV1_PERFMON_COUNTER4_INT_XIRQ_IRQ_SEL_MASK 0x2000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL5__DCFEV1_PERFMON_COUNTER4_INT_XIRQ_IRQ_SEL__SHIFT 0xd
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL5__DCFEV1_PERFMON_COUNTER5_INT_XIRQ_IRQ_SEL_MASK 0x4000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL5__DCFEV1_PERFMON_COUNTER5_INT_XIRQ_IRQ_SEL__SHIFT 0xe
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL5__DCFEV1_PERFMON_COUNTER6_INT_XIRQ_IRQ_SEL_MASK 0x8000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL5__DCFEV1_PERFMON_COUNTER6_INT_XIRQ_IRQ_SEL__SHIFT 0xf
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL5__DCFEV1_PERFMON_COUNTER7_INT_XIRQ_IRQ_SEL_MASK 0x10000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL5__DCFEV1_PERFMON_COUNTER7_INT_XIRQ_IRQ_SEL__SHIFT 0x10
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL5__DCFEV1_PERFMON_COUNTER_OFF_INT_XIRQ_IRQ_SEL_MASK 0x20000
+#define DMCU_PERFMON_INTERRUPT_TO_UC_XIRQ_IRQ_SEL5__DCFEV1_PERFMON_COUNTER_OFF_INT_XIRQ_IRQ_SEL__SHIFT 0x11
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD0P0_MSA_RECEIVED_INT_OCCURRED_MASK 0x1
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD0P0_MSA_RECEIVED_INT_OCCURRED__SHIFT 0x0
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD0P0_MSA_RECEIVED_INT_CLEAR_MASK 0x1
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD0P0_MSA_RECEIVED_INT_CLEAR__SHIFT 0x0
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD0P0_VBID_VID_STREAM_STATUS_TOGGLED_INT_OCCURRED_MASK 0x2
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD0P0_VBID_VID_STREAM_STATUS_TOGGLED_INT_OCCURRED__SHIFT 0x1
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD0P0_VBID_VID_STREAM_STATUS_TOGGLED_INT_CLEAR_MASK 0x2
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD0P0_VBID_VID_STREAM_STATUS_TOGGLED_INT_CLEAR__SHIFT 0x1
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD0P0_VERTICAL_INT0_OCCURRED_MASK 0x4
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD0P0_VERTICAL_INT0_OCCURRED__SHIFT 0x2
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD0P0_VERTICAL_INT0_CLEAR_MASK 0x4
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD0P0_VERTICAL_INT0_CLEAR__SHIFT 0x2
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD0P0_VERTICAL_INT1_OCCURRED_MASK 0x8
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD0P0_VERTICAL_INT1_OCCURRED__SHIFT 0x3
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD0P0_VERTICAL_INT1_CLEAR_MASK 0x8
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD0P0_VERTICAL_INT1_CLEAR__SHIFT 0x3
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD0P0_SDP_RECEIVED_INT_OCCURRED_MASK 0x10
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD0P0_SDP_RECEIVED_INT_OCCURRED__SHIFT 0x4
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD0P0_SDP_RECEIVED_INT_CLEAR_MASK 0x10
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD0P0_SDP_RECEIVED_INT_CLEAR__SHIFT 0x4
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD1P0_MSA_RECEIVED_INT_OCCURRED_MASK 0x20
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD1P0_MSA_RECEIVED_INT_OCCURRED__SHIFT 0x5
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD1P0_MSA_RECEIVED_INT_CLEAR_MASK 0x20
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD1P0_MSA_RECEIVED_INT_CLEAR__SHIFT 0x5
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD1P0_VBID_VID_STREAM_STATUS_TOGGLED_INT_OCCURRED_MASK 0x40
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD1P0_VBID_VID_STREAM_STATUS_TOGGLED_INT_OCCURRED__SHIFT 0x6
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD1P0_VBID_VID_STREAM_STATUS_TOGGLED_INT_CLEAR_MASK 0x40
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD1P0_VBID_VID_STREAM_STATUS_TOGGLED_INT_CLEAR__SHIFT 0x6
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD1P0_VERTICAL_INT0_OCCURRED_MASK 0x80
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD1P0_VERTICAL_INT0_OCCURRED__SHIFT 0x7
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD1P0_VERTICAL_INT0_CLEAR_MASK 0x80
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD1P0_VERTICAL_INT0_CLEAR__SHIFT 0x7
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD1P0_VERTICAL_INT1_OCCURRED_MASK 0x100
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD1P0_VERTICAL_INT1_OCCURRED__SHIFT 0x8
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD1P0_VERTICAL_INT1_CLEAR_MASK 0x100
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD1P0_VERTICAL_INT1_CLEAR__SHIFT 0x8
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD1P0_SDP_RECEIVED_INT_OCCURRED_MASK 0x200
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD1P0_SDP_RECEIVED_INT_OCCURRED__SHIFT 0x9
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD1P0_SDP_RECEIVED_INT_CLEAR_MASK 0x200
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_SD1P0_SDP_RECEIVED_INT_CLEAR__SHIFT 0x9
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_BS_INTERVAL_ERROR_THRESH_EXCEEDED_INT_OCCURRED_MASK 0x400
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_BS_INTERVAL_ERROR_THRESH_EXCEEDED_INT_OCCURRED__SHIFT 0xa
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_BS_INTERVAL_ERROR_THRESH_EXCEEDED_INT_CLEAR_MASK 0x400
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_BS_INTERVAL_ERROR_THRESH_EXCEEDED_INT_CLEAR__SHIFT 0xa
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_SR_INTERVAL_ERROR_THRESH_EXCEEDED_INT_OCCURRED_MASK 0x800
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_SR_INTERVAL_ERROR_THRESH_EXCEEDED_INT_OCCURRED__SHIFT 0xb
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_SR_INTERVAL_ERROR_THRESH_EXCEEDED_INT_CLEAR_MASK 0x800
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_SR_INTERVAL_ERROR_THRESH_EXCEEDED_INT_CLEAR__SHIFT 0xb
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_SYMBOL_ERROR_THRESH_EXCEEDED_INT_OCCURRED_MASK 0x1000
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_SYMBOL_ERROR_THRESH_EXCEEDED_INT_OCCURRED__SHIFT 0xc
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_SYMBOL_ERROR_THRESH_EXCEEDED_INT_CLEAR_MASK 0x1000
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_SYMBOL_ERROR_THRESH_EXCEEDED_INT_CLEAR__SHIFT 0xc
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_DISPARITY_ERROR_THRESH_EXCEEDED_INT_OCCURRED_MASK 0x2000
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_DISPARITY_ERROR_THRESH_EXCEEDED_INT_OCCURRED__SHIFT 0xd
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_DISPARITY_ERROR_THRESH_EXCEEDED_INT_CLEAR_MASK 0x2000
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_DISPARITY_ERROR_THRESH_EXCEEDED_INT_CLEAR__SHIFT 0xd
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_TRAINING_ERROR_THRESH_EXCEEDED_INT_OCCURRED_MASK 0x4000
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_TRAINING_ERROR_THRESH_EXCEEDED_INT_OCCURRED__SHIFT 0xe
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_TRAINING_ERROR_THRESH_EXCEEDED_INT_CLEAR_MASK 0x4000
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_TRAINING_ERROR_THRESH_EXCEEDED_INT_CLEAR__SHIFT 0xe
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_TEST_PATTERN_ERROR_THRESH_EXCEEDED_INT_OCCURRED_MASK 0x8000
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_TEST_PATTERN_ERROR_THRESH_EXCEEDED_INT_OCCURRED__SHIFT 0xf
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_TEST_PATTERN_ERROR_THRESH_EXCEEDED_INT_CLEAR_MASK 0x8000
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_TEST_PATTERN_ERROR_THRESH_EXCEEDED_INT_CLEAR__SHIFT 0xf
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_ECF_ERROR_THRESH_EXCEEDED_INT_OCCURRED_MASK 0x10000
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_ECF_ERROR_THRESH_EXCEEDED_INT_OCCURRED__SHIFT 0x10
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_ECF_ERROR_THRESH_EXCEEDED_INT_CLEAR_MASK 0x10000
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_ECF_ERROR_THRESH_EXCEEDED_INT_CLEAR__SHIFT 0x10
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_DETECT_SR_LOCK_INT_OCCURRED_MASK 0x20000
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_DETECT_SR_LOCK_INT_OCCURRED__SHIFT 0x11
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_DETECT_SR_LOCK_INT_CLEAR_MASK 0x20000
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_DETECT_SR_LOCK_INT_CLEAR__SHIFT 0x11
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_LOSS_OF_ALIGN_INT_OCCURRED_MASK 0x40000
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_LOSS_OF_ALIGN_INT_OCCURRED__SHIFT 0x12
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_LOSS_OF_ALIGN_INT_CLEAR_MASK 0x40000
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_LOSS_OF_ALIGN_INT_CLEAR__SHIFT 0x12
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_LOSS_OF_DESKEW_INT_OCCURRED_MASK 0x80000
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_LOSS_OF_DESKEW_INT_OCCURRED__SHIFT 0x13
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_LOSS_OF_DESKEW_INT_CLEAR_MASK 0x80000
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_LOSS_OF_DESKEW_INT_CLEAR__SHIFT 0x13
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_EXCESSIVE_ERROR_INT_OCCURRED_MASK 0x100000
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_EXCESSIVE_ERROR_INT_OCCURRED__SHIFT 0x14
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_EXCESSIVE_ERROR_INT_CLEAR_MASK 0x100000
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_EXCESSIVE_ERROR_INT_CLEAR__SHIFT 0x14
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_DESKEW_FIFO_OVERFLOW_INT_OCCURRED_MASK 0x200000
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_DESKEW_FIFO_OVERFLOW_INT_OCCURRED__SHIFT 0x15
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_DESKEW_FIFO_OVERFLOW_INT_CLEAR_MASK 0x200000
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_DPHY_P0_DESKEW_FIFO_OVERFLOW_INT_CLEAR__SHIFT 0x15
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_AUX_P0_AUX_INT_OCCURRED_MASK 0x400000
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_AUX_P0_AUX_INT_OCCURRED__SHIFT 0x16
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_AUX_P0_AUX_INT_CLEAR_MASK 0x400000
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_AUX_P0_AUX_INT_CLEAR__SHIFT 0x16
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_AUX_P0_I2C_INT_OCCURRED_MASK 0x800000
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_AUX_P0_I2C_INT_OCCURRED__SHIFT 0x17
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_AUX_P0_I2C_INT_CLEAR_MASK 0x800000
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_AUX_P0_I2C_INT_CLEAR__SHIFT 0x17
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_AUX_P0_CPU_INT_OCCURRED_MASK 0x1000000
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_AUX_P0_CPU_INT_OCCURRED__SHIFT 0x18
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_AUX_P0_CPU_INT_CLEAR_MASK 0x1000000
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_AUX_P0_CPU_INT_CLEAR__SHIFT 0x18
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_AUX_P0_MSG1_TIMEOUT_INT_OCCURRED_MASK 0x2000000
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_AUX_P0_MSG1_TIMEOUT_INT_OCCURRED__SHIFT 0x19
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_AUX_P0_MSG1_TIMEOUT_INT_CLEAR_MASK 0x2000000
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_AUX_P0_MSG1_TIMEOUT_INT_CLEAR__SHIFT 0x19
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_AUX_P0_MSG2_TIMEOUT_INT_OCCURRED_MASK 0x4000000
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_AUX_P0_MSG2_TIMEOUT_INT_OCCURRED__SHIFT 0x1a
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_AUX_P0_MSG2_TIMEOUT_INT_CLEAR_MASK 0x4000000
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_AUX_P0_MSG2_TIMEOUT_INT_CLEAR__SHIFT 0x1a
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_AUX_P0_MSG3_TIMEOUT_INT_OCCURRED_MASK 0x8000000
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_AUX_P0_MSG3_TIMEOUT_INT_OCCURRED__SHIFT 0x1b
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_AUX_P0_MSG3_TIMEOUT_INT_CLEAR_MASK 0x8000000
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_AUX_P0_MSG3_TIMEOUT_INT_CLEAR__SHIFT 0x1b
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_AUX_P0_MSG4_TIMEOUT_INT_OCCURRED_MASK 0x10000000
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_AUX_P0_MSG4_TIMEOUT_INT_OCCURRED__SHIFT 0x1c
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_AUX_P0_MSG4_TIMEOUT_INT_CLEAR_MASK 0x10000000
+#define DMCU_DPRX_INTERRUPT_STATUS1__DPRX_AUX_P0_MSG4_TIMEOUT_INT_CLEAR__SHIFT 0x1c
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_SD0P0_MSA_RECEIVED_INT_TO_UC_EN_MASK 0x1
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_SD0P0_MSA_RECEIVED_INT_TO_UC_EN__SHIFT 0x0
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_SD0P0_VBID_VID_STREAM_STATUS_TOGGLED_INT_TO_UC_EN_MASK 0x2
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_SD0P0_VBID_VID_STREAM_STATUS_TOGGLED_INT_TO_UC_EN__SHIFT 0x1
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_SD0P0_VERTICAL_INT0_TO_UC_EN_MASK 0x4
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_SD0P0_VERTICAL_INT0_TO_UC_EN__SHIFT 0x2
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_SD0P0_VERTICAL_INT1_TO_UC_EN_MASK 0x8
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_SD0P0_VERTICAL_INT1_TO_UC_EN__SHIFT 0x3
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_SD0P0_SDP_RECEIVED_INT_TO_UC_EN_MASK 0x10
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_SD0P0_SDP_RECEIVED_INT_TO_UC_EN__SHIFT 0x4
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_SD1P0_MSA_RECEIVED_INT_TO_UC_EN_MASK 0x20
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_SD1P0_MSA_RECEIVED_INT_TO_UC_EN__SHIFT 0x5
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_SD1P0_VBID_VID_STREAM_STATUS_TOGGLED_INT_TO_UC_EN_MASK 0x40
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_SD1P0_VBID_VID_STREAM_STATUS_TOGGLED_INT_TO_UC_EN__SHIFT 0x6
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_SD1P0_VERTICAL_INT0_TO_UC_EN_MASK 0x80
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_SD1P0_VERTICAL_INT0_TO_UC_EN__SHIFT 0x7
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_SD1P0_VERTICAL_INT1_TO_UC_EN_MASK 0x100
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_SD1P0_VERTICAL_INT1_TO_UC_EN__SHIFT 0x8
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_SD1P0_SDP_RECEIVED_INT_TO_UC_EN_MASK 0x200
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_SD1P0_SDP_RECEIVED_INT_TO_UC_EN__SHIFT 0x9
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_DPHY_P0_BS_INTERVAL_ERROR_THRESH_EXCEEDED_INT_TO_UC_EN_MASK 0x400
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_DPHY_P0_BS_INTERVAL_ERROR_THRESH_EXCEEDED_INT_TO_UC_EN__SHIFT 0xa
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_DPHY_P0_SR_INTERVAL_ERROR_THRESH_EXCEEDED_INT_TO_UC_EN_MASK 0x800
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_DPHY_P0_SR_INTERVAL_ERROR_THRESH_EXCEEDED_INT_TO_UC_EN__SHIFT 0xb
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_DPHY_P0_SYMBOL_ERROR_THRESH_EXCEEDED_INT_TO_UC_EN_MASK 0x1000
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_DPHY_P0_SYMBOL_ERROR_THRESH_EXCEEDED_INT_TO_UC_EN__SHIFT 0xc
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_DPHY_P0_DISPARITY_ERROR_THRESH_EXCEEDED_INT_TO_UC_EN_MASK 0x2000
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_DPHY_P0_DISPARITY_ERROR_THRESH_EXCEEDED_INT_TO_UC_EN__SHIFT 0xd
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_DPHY_P0_TRAINING_ERROR_THRESH_EXCEEDED_INT_TO_UC_EN_MASK 0x4000
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_DPHY_P0_TRAINING_ERROR_THRESH_EXCEEDED_INT_TO_UC_EN__SHIFT 0xe
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_DPHY_P0_TEST_PATTERN_ERROR_THRESH_EXCEEDED_INT_TO_UC_EN_MASK 0x8000
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_DPHY_P0_TEST_PATTERN_ERROR_THRESH_EXCEEDED_INT_TO_UC_EN__SHIFT 0xf
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_DPHY_P0_ECF_ERROR_THRESH_EXCEEDED_INT_TO_UC_EN_MASK 0x10000
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_DPHY_P0_ECF_ERROR_THRESH_EXCEEDED_INT_TO_UC_EN__SHIFT 0x10
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_DPHY_P0_DETECT_SR_LOCK_INT_TO_UC_EN_MASK 0x20000
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_DPHY_P0_DETECT_SR_LOCK_INT_TO_UC_EN__SHIFT 0x11
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_DPHY_P0_LOSS_OF_ALIGN_INT_TO_UC_EN_MASK 0x40000
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_DPHY_P0_LOSS_OF_ALIGN_INT_TO_UC_EN__SHIFT 0x12
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_DPHY_P0_LOSS_OF_DESKEW_INT_TO_UC_EN_MASK 0x80000
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_DPHY_P0_LOSS_OF_DESKEW_INT_TO_UC_EN__SHIFT 0x13
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_DPHY_P0_EXCESSIVE_ERROR_INT_TO_UC_EN_MASK 0x100000
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_DPHY_P0_EXCESSIVE_ERROR_INT_TO_UC_EN__SHIFT 0x14
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_DPHY_P0_DESKEW_FIFO_OVERFLOW_INT_TO_UC_EN_MASK 0x200000
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_DPHY_P0_DESKEW_FIFO_OVERFLOW_INT_TO_UC_EN__SHIFT 0x15
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_AUX_P0_AUX_INT_TO_UC_EN_MASK 0x400000
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_AUX_P0_AUX_INT_TO_UC_EN__SHIFT 0x16
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_AUX_P0_I2C_INT_TO_UC_EN_MASK 0x800000
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_AUX_P0_I2C_INT_TO_UC_EN__SHIFT 0x17
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_AUX_P0_CPU_INT_TO_UC_EN_MASK 0x1000000
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_AUX_P0_CPU_INT_TO_UC_EN__SHIFT 0x18
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_AUX_P0_MSG1_TIMEOUT_INT_TO_UC_EN_MASK 0x2000000
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_AUX_P0_MSG1_TIMEOUT_INT_TO_UC_EN__SHIFT 0x19
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_AUX_P0_MSG2_TIMEOUT_INT_TO_UC_EN_MASK 0x4000000
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_AUX_P0_MSG2_TIMEOUT_INT_TO_UC_EN__SHIFT 0x1a
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_AUX_P0_MSG3_TIMEOUT_INT_TO_UC_EN_MASK 0x8000000
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_AUX_P0_MSG3_TIMEOUT_INT_TO_UC_EN__SHIFT 0x1b
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_AUX_P0_MSG4_TIMEOUT_INT_TO_UC_EN_MASK 0x10000000
+#define DMCU_DPRX_INTERRUPT_TO_UC_EN_MASK1__DPRX_AUX_P0_MSG4_TIMEOUT_INT_TO_UC_EN__SHIFT 0x1c
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_SD0P0_MSA_RECEIVED_INT_XIRQ_IRQ_SEL_MASK 0x1
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_SD0P0_MSA_RECEIVED_INT_XIRQ_IRQ_SEL__SHIFT 0x0
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_SD0P0_VBID_VID_STREAM_STATUS_TOGGLED_INT_XIRQ_IRQ_SEL_MASK 0x2
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_SD0P0_VBID_VID_STREAM_STATUS_TOGGLED_INT_XIRQ_IRQ_SEL__SHIFT 0x1
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_SD0P0_VERTICAL_INT0_XIRQ_IRQ_SEL_MASK 0x4
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_SD0P0_VERTICAL_INT0_XIRQ_IRQ_SEL__SHIFT 0x2
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_SD0P0_VERTICAL_INT1_XIRQ_IRQ_SEL_MASK 0x8
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_SD0P0_VERTICAL_INT1_XIRQ_IRQ_SEL__SHIFT 0x3
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_SD0P0_SDP_RECEIVED_INT_XIRQ_IRQ_SEL_MASK 0x10
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_SD0P0_SDP_RECEIVED_INT_XIRQ_IRQ_SEL__SHIFT 0x4
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_SD1P0_MSA_RECEIVED_INT_XIRQ_IRQ_SEL_MASK 0x20
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_SD1P0_MSA_RECEIVED_INT_XIRQ_IRQ_SEL__SHIFT 0x5
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_SD1P0_VBID_VID_STREAM_STATUS_TOGGLED_INT_XIRQ_IRQ_SEL_MASK 0x40
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_SD1P0_VBID_VID_STREAM_STATUS_TOGGLED_INT_XIRQ_IRQ_SEL__SHIFT 0x6
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_SD1P0_VERTICAL_INT0_XIRQ_IRQ_SEL_MASK 0x80
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_SD1P0_VERTICAL_INT0_XIRQ_IRQ_SEL__SHIFT 0x7
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_SD1P0_VERTICAL_INT1_XIRQ_IRQ_SEL_MASK 0x100
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_SD1P0_VERTICAL_INT1_XIRQ_IRQ_SEL__SHIFT 0x8
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_SD1P0_SDP_RECEIVED_INT_XIRQ_IRQ_SEL_MASK 0x200
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_SD1P0_SDP_RECEIVED_INT_XIRQ_IRQ_SEL__SHIFT 0x9
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_DPHY_P0_BS_INTERVAL_ERROR_THRESH_EXCEEDED_INT_XIRQ_IRQ_SEL_MASK 0x400
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_DPHY_P0_BS_INTERVAL_ERROR_THRESH_EXCEEDED_INT_XIRQ_IRQ_SEL__SHIFT 0xa
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_DPHY_P0_SR_INTERVAL_ERROR_THRESH_EXCEEDED_INT_XIRQ_IRQ_SEL_MASK 0x800
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_DPHY_P0_SR_INTERVAL_ERROR_THRESH_EXCEEDED_INT_XIRQ_IRQ_SEL__SHIFT 0xb
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_DPHY_P0_SYMBOL_ERROR_THRESH_EXCEEDED_INT_XIRQ_IRQ_SEL_MASK 0x1000
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_DPHY_P0_SYMBOL_ERROR_THRESH_EXCEEDED_INT_XIRQ_IRQ_SEL__SHIFT 0xc
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_DPHY_P0_DISPARITY_ERROR_THRESH_EXCEEDED_INT_XIRQ_IRQ_SEL_MASK 0x2000
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_DPHY_P0_DISPARITY_ERROR_THRESH_EXCEEDED_INT_XIRQ_IRQ_SEL__SHIFT 0xd
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_DPHY_P0_TRAINING_ERROR_THRESH_EXCEEDED_INT_XIRQ_IRQ_SEL_MASK 0x4000
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_DPHY_P0_TRAINING_ERROR_THRESH_EXCEEDED_INT_XIRQ_IRQ_SEL__SHIFT 0xe
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_DPHY_P0_TEST_PATTERN_ERROR_THRESH_EXCEEDED_INT_XIRQ_IRQ_SEL_MASK 0x8000
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_DPHY_P0_TEST_PATTERN_ERROR_THRESH_EXCEEDED_INT_XIRQ_IRQ_SEL__SHIFT 0xf
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_DPHY_P0_ECF_ERROR_THRESH_EXCEEDED_INT_XIRQ_IRQ_SEL_MASK 0x10000
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_DPHY_P0_ECF_ERROR_THRESH_EXCEEDED_INT_XIRQ_IRQ_SEL__SHIFT 0x10
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_DPHY_P0_DETECT_SR_LOCK_INT_XIRQ_IRQ_SEL_MASK 0x20000
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_DPHY_P0_DETECT_SR_LOCK_INT_XIRQ_IRQ_SEL__SHIFT 0x11
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_DPHY_P0_LOSS_OF_ALIGN_INT_XIRQ_IRQ_SEL_MASK 0x40000
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_DPHY_P0_LOSS_OF_ALIGN_INT_XIRQ_IRQ_SEL__SHIFT 0x12
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_DPHY_P0_LOSS_OF_DESKEW_INT_XIRQ_IRQ_SEL_MASK 0x80000
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_DPHY_P0_LOSS_OF_DESKEW_INT_XIRQ_IRQ_SEL__SHIFT 0x13
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_DPHY_P0_EXCESSIVE_ERROR_INT_XIRQ_IRQ_SEL_MASK 0x100000
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_DPHY_P0_EXCESSIVE_ERROR_INT_XIRQ_IRQ_SEL__SHIFT 0x14
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_DPHY_P0_DESKEW_FIFO_OVERFLOW_INT_XIRQ_IRQ_SEL_MASK 0x200000
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_DPHY_P0_DESKEW_FIFO_OVERFLOW_INT_XIRQ_IRQ_SEL__SHIFT 0x15
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_AUX_P0_AUX_INT_XIRQ_IRQ_SEL_MASK 0x400000
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_AUX_P0_AUX_INT_XIRQ_IRQ_SEL__SHIFT 0x16
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_AUX_P0_I2C_INT_XIRQ_IRQ_SEL_MASK 0x800000
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_AUX_P0_I2C_INT_XIRQ_IRQ_SEL__SHIFT 0x17
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_AUX_P0_CPU_INT_XIRQ_IRQ_SEL_MASK 0x1000000
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_AUX_P0_CPU_INT_XIRQ_IRQ_SEL__SHIFT 0x18
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_AUX_P0_MSG1_TIMEOUT_INT_XIRQ_IRQ_SEL_MASK 0x2000000
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_AUX_P0_MSG1_TIMEOUT_INT_XIRQ_IRQ_SEL__SHIFT 0x19
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_AUX_P0_MSG2_TIMEOUT_INT_XIRQ_IRQ_SEL_MASK 0x4000000
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_AUX_P0_MSG2_TIMEOUT_INT_XIRQ_IRQ_SEL__SHIFT 0x1a
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_AUX_P0_MSG3_TIMEOUT_INT_XIRQ_IRQ_SEL_MASK 0x8000000
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_AUX_P0_MSG3_TIMEOUT_INT_XIRQ_IRQ_SEL__SHIFT 0x1b
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_AUX_P0_MSG4_TIMEOUT_INT_XIRQ_IRQ_SEL_MASK 0x10000000
+#define DMCU_DPRX_INTERRUPT_TO_UC_XIRQ_IRQ_SEL1__DPRX_AUX_P0_MSG4_TIMEOUT_INT_XIRQ_IRQ_SEL__SHIFT 0x1c
+#define DP_LINK_CNTL__DP_LINK_TRAINING_COMPLETE_MASK 0x10
+#define DP_LINK_CNTL__DP_LINK_TRAINING_COMPLETE__SHIFT 0x4
+#define DP_LINK_CNTL__DP_LINK_STATUS_MASK 0x100
+#define DP_LINK_CNTL__DP_LINK_STATUS__SHIFT 0x8
+#define DP_LINK_CNTL__DP_EMBEDDED_PANEL_MODE_MASK 0x20000
+#define DP_LINK_CNTL__DP_EMBEDDED_PANEL_MODE__SHIFT 0x11
+#define DP_PIXEL_FORMAT__DP_PIXEL_ENCODING_MASK 0x7
+#define DP_PIXEL_FORMAT__DP_PIXEL_ENCODING__SHIFT 0x0
+#define DP_PIXEL_FORMAT__DP_DYN_RANGE_MASK 0x100
+#define DP_PIXEL_FORMAT__DP_DYN_RANGE__SHIFT 0x8
+#define DP_PIXEL_FORMAT__DP_YCBCR_RANGE_MASK 0x10000
+#define DP_PIXEL_FORMAT__DP_YCBCR_RANGE__SHIFT 0x10
+#define DP_PIXEL_FORMAT__DP_COMPONENT_DEPTH_MASK 0x7000000
+#define DP_PIXEL_FORMAT__DP_COMPONENT_DEPTH__SHIFT 0x18
+#define DP_MSA_COLORIMETRY__DP_MSA_MISC0_OVERRIDE_MASK 0xff
+#define DP_MSA_COLORIMETRY__DP_MSA_MISC0_OVERRIDE__SHIFT 0x0
+#define DP_MSA_COLORIMETRY__DP_MSA_MISC0_OVERRIDE_ENABLE_MASK 0x100
+#define DP_MSA_COLORIMETRY__DP_MSA_MISC0_OVERRIDE_ENABLE__SHIFT 0x8
+#define DP_MSA_COLORIMETRY__DP_MSA_MISC1_BIT7_OVERRIDE_MASK 0x200
+#define DP_MSA_COLORIMETRY__DP_MSA_MISC1_BIT7_OVERRIDE__SHIFT 0x9
+#define DP_MSA_COLORIMETRY__DP_MSA_MISC1_BIT7_OVERRIDE_ENABLE_MASK 0x20000
+#define DP_MSA_COLORIMETRY__DP_MSA_MISC1_BIT7_OVERRIDE_ENABLE__SHIFT 0x11
+#define DP_CONFIG__DP_UDI_LANES_MASK 0x3
+#define DP_CONFIG__DP_UDI_LANES__SHIFT 0x0
+#define DP_VID_STREAM_CNTL__DP_VID_STREAM_ENABLE_MASK 0x1
+#define DP_VID_STREAM_CNTL__DP_VID_STREAM_ENABLE__SHIFT 0x0
+#define DP_VID_STREAM_CNTL__DP_VID_STREAM_DIS_DEFER_MASK 0x300
+#define DP_VID_STREAM_CNTL__DP_VID_STREAM_DIS_DEFER__SHIFT 0x8
+#define DP_VID_STREAM_CNTL__DP_VID_STREAM_STATUS_MASK 0x10000
+#define DP_VID_STREAM_CNTL__DP_VID_STREAM_STATUS__SHIFT 0x10
+#define DP_VID_STREAM_CNTL__DP_VID_STREAM_CHANGE_KEEPOUT_MASK 0x100000
+#define DP_VID_STREAM_CNTL__DP_VID_STREAM_CHANGE_KEEPOUT__SHIFT 0x14
+#define DP_STEER_FIFO__DP_STEER_FIFO_RESET_MASK 0x1
+#define DP_STEER_FIFO__DP_STEER_FIFO_RESET__SHIFT 0x0
+#define DP_STEER_FIFO__DP_STEER_OVERFLOW_FLAG_MASK 0x10
+#define DP_STEER_FIFO__DP_STEER_OVERFLOW_FLAG__SHIFT 0x4
+#define DP_STEER_FIFO__DP_STEER_OVERFLOW_INT_MASK 0x20
+#define DP_STEER_FIFO__DP_STEER_OVERFLOW_INT__SHIFT 0x5
+#define DP_STEER_FIFO__DP_STEER_OVERFLOW_ACK_MASK 0x40
+#define DP_STEER_FIFO__DP_STEER_OVERFLOW_ACK__SHIFT 0x6
+#define DP_STEER_FIFO__DP_STEER_OVERFLOW_MASK_MASK 0x80
+#define DP_STEER_FIFO__DP_STEER_OVERFLOW_MASK__SHIFT 0x7
+#define DP_STEER_FIFO__DP_TU_OVERFLOW_FLAG_MASK 0x100
+#define DP_STEER_FIFO__DP_TU_OVERFLOW_FLAG__SHIFT 0x8
+#define DP_STEER_FIFO__DP_TU_OVERFLOW_ACK_MASK 0x1000
+#define DP_STEER_FIFO__DP_TU_OVERFLOW_ACK__SHIFT 0xc
+#define DP_MSA_MISC__DP_MSA_MISC1_MASK 0x78
+#define DP_MSA_MISC__DP_MSA_MISC1__SHIFT 0x3
+#define DP_MSA_MISC__DP_MSA_MISC2_MASK 0xff00
+#define DP_MSA_MISC__DP_MSA_MISC2__SHIFT 0x8
+#define DP_MSA_MISC__DP_MSA_MISC3_MASK 0xff0000
+#define DP_MSA_MISC__DP_MSA_MISC3__SHIFT 0x10
+#define DP_MSA_MISC__DP_MSA_MISC4_MASK 0xff000000
+#define DP_MSA_MISC__DP_MSA_MISC4__SHIFT 0x18
+#define DP_VID_TIMING__DP_VID_TIMING_MODE_MASK 0x1
+#define DP_VID_TIMING__DP_VID_TIMING_MODE__SHIFT 0x0
+#define DP_VID_TIMING__DP_VID_M_N_DOUBLE_BUFFER_MODE_MASK 0x10
+#define DP_VID_TIMING__DP_VID_M_N_DOUBLE_BUFFER_MODE__SHIFT 0x4
+#define DP_VID_TIMING__DP_VID_M_N_GEN_EN_MASK 0x100
+#define DP_VID_TIMING__DP_VID_M_N_GEN_EN__SHIFT 0x8
+#define DP_VID_TIMING__DP_VID_M_DOUBLE_VALUE_EN_MASK 0x200
+#define DP_VID_TIMING__DP_VID_M_DOUBLE_VALUE_EN__SHIFT 0x9
+#define DP_VID_TIMING__DP_VID_N_DIV_MASK 0xff000000
+#define DP_VID_TIMING__DP_VID_N_DIV__SHIFT 0x18
+#define DP_VID_N__DP_VID_N_MASK 0xffffff
+#define DP_VID_N__DP_VID_N__SHIFT 0x0
+#define DP_VID_M__DP_VID_M_MASK 0xffffff
+#define DP_VID_M__DP_VID_M__SHIFT 0x0
+#define DP_LINK_FRAMING_CNTL__DP_IDLE_BS_INTERVAL_MASK 0x3ffff
+#define DP_LINK_FRAMING_CNTL__DP_IDLE_BS_INTERVAL__SHIFT 0x0
+#define DP_LINK_FRAMING_CNTL__DP_VBID_DISABLE_MASK 0x1000000
+#define DP_LINK_FRAMING_CNTL__DP_VBID_DISABLE__SHIFT 0x18
+#define DP_LINK_FRAMING_CNTL__DP_VID_ENHANCED_FRAME_MODE_MASK 0x10000000
+#define DP_LINK_FRAMING_CNTL__DP_VID_ENHANCED_FRAME_MODE__SHIFT 0x1c
+#define DP_HBR2_EYE_PATTERN__DP_HBR2_EYE_PATTERN_ENABLE_MASK 0x1
+#define DP_HBR2_EYE_PATTERN__DP_HBR2_EYE_PATTERN_ENABLE__SHIFT 0x0
+#define DP_VID_MSA_VBID__DP_VID_MSA_LOCATION_MASK 0xfff
+#define DP_VID_MSA_VBID__DP_VID_MSA_LOCATION__SHIFT 0x0
+#define DP_VID_MSA_VBID__DP_VID_MSA_TOP_FIELD_MODE_MASK 0x10000
+#define DP_VID_MSA_VBID__DP_VID_MSA_TOP_FIELD_MODE__SHIFT 0x10
+#define DP_VID_MSA_VBID__DP_VID_VBID_FIELD_POL_MASK 0x1000000
+#define DP_VID_MSA_VBID__DP_VID_VBID_FIELD_POL__SHIFT 0x18
+#define DP_VID_INTERRUPT_CNTL__DP_VID_STREAM_DISABLE_INT_MASK 0x1
+#define DP_VID_INTERRUPT_CNTL__DP_VID_STREAM_DISABLE_INT__SHIFT 0x0
+#define DP_VID_INTERRUPT_CNTL__DP_VID_STREAM_DISABLE_ACK_MASK 0x2
+#define DP_VID_INTERRUPT_CNTL__DP_VID_STREAM_DISABLE_ACK__SHIFT 0x1
+#define DP_VID_INTERRUPT_CNTL__DP_VID_STREAM_DISABLE_MASK_MASK 0x4
+#define DP_VID_INTERRUPT_CNTL__DP_VID_STREAM_DISABLE_MASK__SHIFT 0x2
+#define DP_DPHY_CNTL__DPHY_ATEST_SEL_LANE0_MASK 0x1
+#define DP_DPHY_CNTL__DPHY_ATEST_SEL_LANE0__SHIFT 0x0
+#define DP_DPHY_CNTL__DPHY_ATEST_SEL_LANE1_MASK 0x2
+#define DP_DPHY_CNTL__DPHY_ATEST_SEL_LANE1__SHIFT 0x1
+#define DP_DPHY_CNTL__DPHY_ATEST_SEL_LANE2_MASK 0x4
+#define DP_DPHY_CNTL__DPHY_ATEST_SEL_LANE2__SHIFT 0x2
+#define DP_DPHY_CNTL__DPHY_ATEST_SEL_LANE3_MASK 0x8
+#define DP_DPHY_CNTL__DPHY_ATEST_SEL_LANE3__SHIFT 0x3
+#define DP_DPHY_CNTL__DPHY_BYPASS_MASK 0x10000
+#define DP_DPHY_CNTL__DPHY_BYPASS__SHIFT 0x10
+#define DP_DPHY_CNTL__DPHY_SKEW_BYPASS_MASK 0x1000000
+#define DP_DPHY_CNTL__DPHY_SKEW_BYPASS__SHIFT 0x18
+#define DP_DPHY_TRAINING_PATTERN_SEL__DPHY_TRAINING_PATTERN_SEL_MASK 0x3
+#define DP_DPHY_TRAINING_PATTERN_SEL__DPHY_TRAINING_PATTERN_SEL__SHIFT 0x0
+#define DP_DPHY_SYM0__DPHY_SYM1_MASK 0x3ff
+#define DP_DPHY_SYM0__DPHY_SYM1__SHIFT 0x0
+#define DP_DPHY_SYM0__DPHY_SYM2_MASK 0xffc00
+#define DP_DPHY_SYM0__DPHY_SYM2__SHIFT 0xa
+#define DP_DPHY_SYM0__DPHY_SYM3_MASK 0x3ff00000
+#define DP_DPHY_SYM0__DPHY_SYM3__SHIFT 0x14
+#define DP_DPHY_SYM1__DPHY_SYM4_MASK 0x3ff
+#define DP_DPHY_SYM1__DPHY_SYM4__SHIFT 0x0
+#define DP_DPHY_SYM1__DPHY_SYM5_MASK 0xffc00
+#define DP_DPHY_SYM1__DPHY_SYM5__SHIFT 0xa
+#define DP_DPHY_SYM1__DPHY_SYM6_MASK 0x3ff00000
+#define DP_DPHY_SYM1__DPHY_SYM6__SHIFT 0x14
+#define DP_DPHY_SYM2__DPHY_SYM7_MASK 0x3ff
+#define DP_DPHY_SYM2__DPHY_SYM7__SHIFT 0x0
+#define DP_DPHY_SYM2__DPHY_SYM8_MASK 0xffc00
+#define DP_DPHY_SYM2__DPHY_SYM8__SHIFT 0xa
+#define DP_DPHY_8B10B_CNTL__DPHY_8B10B_RESET_MASK 0x100
+#define DP_DPHY_8B10B_CNTL__DPHY_8B10B_RESET__SHIFT 0x8
+#define DP_DPHY_8B10B_CNTL__DPHY_8B10B_EXT_DISP_MASK 0x10000
+#define DP_DPHY_8B10B_CNTL__DPHY_8B10B_EXT_DISP__SHIFT 0x10
+#define DP_DPHY_8B10B_CNTL__DPHY_8B10B_CUR_DISP_MASK 0x1000000
+#define DP_DPHY_8B10B_CNTL__DPHY_8B10B_CUR_DISP__SHIFT 0x18
+#define DP_DPHY_PRBS_CNTL__DPHY_PRBS_EN_MASK 0x1
+#define DP_DPHY_PRBS_CNTL__DPHY_PRBS_EN__SHIFT 0x0
+#define DP_DPHY_PRBS_CNTL__DPHY_PRBS_SEL_MASK 0x30
+#define DP_DPHY_PRBS_CNTL__DPHY_PRBS_SEL__SHIFT 0x4
+#define DP_DPHY_PRBS_CNTL__DPHY_PRBS_SEED_MASK 0x7fffff00
+#define DP_DPHY_PRBS_CNTL__DPHY_PRBS_SEED__SHIFT 0x8
+#define DP_DPHY_BS_SR_SWAP_CNTL__DPHY_LOAD_BS_COUNT_MASK 0x3ff
+#define DP_DPHY_BS_SR_SWAP_CNTL__DPHY_LOAD_BS_COUNT__SHIFT 0x0
+#define DP_DPHY_BS_SR_SWAP_CNTL__DPHY_BS_SR_SWAP_DONE_MASK 0x8000
+#define DP_DPHY_BS_SR_SWAP_CNTL__DPHY_BS_SR_SWAP_DONE__SHIFT 0xf
+#define DP_DPHY_BS_SR_SWAP_CNTL__DPHY_LOAD_BS_COUNT_START_MASK 0x10000
+#define DP_DPHY_BS_SR_SWAP_CNTL__DPHY_LOAD_BS_COUNT_START__SHIFT 0x10
+#define DP_DPHY_CRC_EN__DPHY_CRC_EN_MASK 0x1
+#define DP_DPHY_CRC_EN__DPHY_CRC_EN__SHIFT 0x0
+#define DP_DPHY_CRC_EN__DPHY_CRC_CONT_EN_MASK 0x10
+#define DP_DPHY_CRC_EN__DPHY_CRC_CONT_EN__SHIFT 0x4
+#define DP_DPHY_CRC_EN__DPHY_CRC_RESULT_VALID_MASK 0x100
+#define DP_DPHY_CRC_EN__DPHY_CRC_RESULT_VALID__SHIFT 0x8
+#define DP_DPHY_CRC_CNTL__DPHY_CRC_FIELD_MASK 0x1
+#define DP_DPHY_CRC_CNTL__DPHY_CRC_FIELD__SHIFT 0x0
+#define DP_DPHY_CRC_CNTL__DPHY_CRC_SEL_MASK 0x30
+#define DP_DPHY_CRC_CNTL__DPHY_CRC_SEL__SHIFT 0x4
+#define DP_DPHY_CRC_CNTL__DPHY_CRC_MASK_MASK 0xff0000
+#define DP_DPHY_CRC_CNTL__DPHY_CRC_MASK__SHIFT 0x10
+#define DP_DPHY_CRC_RESULT__DPHY_CRC_RESULT_MASK 0xff
+#define DP_DPHY_CRC_RESULT__DPHY_CRC_RESULT__SHIFT 0x0
+#define DP_DPHY_CRC_RESULT__DPHY_CRC_RESULT1_MASK 0xff00
+#define DP_DPHY_CRC_RESULT__DPHY_CRC_RESULT1__SHIFT 0x8
+#define DP_DPHY_CRC_RESULT__DPHY_CRC_RESULT2_MASK 0xff0000
+#define DP_DPHY_CRC_RESULT__DPHY_CRC_RESULT2__SHIFT 0x10
+#define DP_DPHY_CRC_RESULT__DPHY_CRC_RESULT3_MASK 0xff000000
+#define DP_DPHY_CRC_RESULT__DPHY_CRC_RESULT3__SHIFT 0x18
+#define DP_DPHY_CRC_MST_CNTL__DPHY_CRC_MST_FIRST_SLOT_MASK 0x3f
+#define DP_DPHY_CRC_MST_CNTL__DPHY_CRC_MST_FIRST_SLOT__SHIFT 0x0
+#define DP_DPHY_CRC_MST_CNTL__DPHY_CRC_MST_LAST_SLOT_MASK 0x3f00
+#define DP_DPHY_CRC_MST_CNTL__DPHY_CRC_MST_LAST_SLOT__SHIFT 0x8
+#define DP_DPHY_CRC_MST_STATUS__DPHY_CRC_MST_PHASE_LOCK_MASK 0x1
+#define DP_DPHY_CRC_MST_STATUS__DPHY_CRC_MST_PHASE_LOCK__SHIFT 0x0
+#define DP_DPHY_CRC_MST_STATUS__DPHY_CRC_MST_PHASE_ERROR_MASK 0x100
+#define DP_DPHY_CRC_MST_STATUS__DPHY_CRC_MST_PHASE_ERROR__SHIFT 0x8
+#define DP_DPHY_CRC_MST_STATUS__DPHY_CRC_MST_PHASE_ERROR_ACK_MASK 0x10000
+#define DP_DPHY_CRC_MST_STATUS__DPHY_CRC_MST_PHASE_ERROR_ACK__SHIFT 0x10
+#define DP_DPHY_FAST_TRAINING__DPHY_RX_FAST_TRAINING_CAPABLE_MASK 0x1
+#define DP_DPHY_FAST_TRAINING__DPHY_RX_FAST_TRAINING_CAPABLE__SHIFT 0x0
+#define DP_DPHY_FAST_TRAINING__DPHY_SW_FAST_TRAINING_START_MASK 0x2
+#define DP_DPHY_FAST_TRAINING__DPHY_SW_FAST_TRAINING_START__SHIFT 0x1
+#define DP_DPHY_FAST_TRAINING__DPHY_FAST_TRAINING_VBLANK_EDGE_DETECT_EN_MASK 0x4
+#define DP_DPHY_FAST_TRAINING__DPHY_FAST_TRAINING_VBLANK_EDGE_DETECT_EN__SHIFT 0x2
+#define DP_DPHY_FAST_TRAINING__DPHY_FAST_TRAINING_TP1_TIME_MASK 0xfff00
+#define DP_DPHY_FAST_TRAINING__DPHY_FAST_TRAINING_TP1_TIME__SHIFT 0x8
+#define DP_DPHY_FAST_TRAINING__DPHY_FAST_TRAINING_TP2_TIME_MASK 0xfff00000
+#define DP_DPHY_FAST_TRAINING__DPHY_FAST_TRAINING_TP2_TIME__SHIFT 0x14
+#define DP_DPHY_FAST_TRAINING_STATUS__DPHY_FAST_TRAINING_STATE_MASK 0x7
+#define DP_DPHY_FAST_TRAINING_STATUS__DPHY_FAST_TRAINING_STATE__SHIFT 0x0
+#define DP_DPHY_FAST_TRAINING_STATUS__DPHY_FAST_TRAINING_COMPLETE_OCCURRED_MASK 0x10
+#define DP_DPHY_FAST_TRAINING_STATUS__DPHY_FAST_TRAINING_COMPLETE_OCCURRED__SHIFT 0x4
+#define DP_DPHY_FAST_TRAINING_STATUS__DPHY_FAST_TRAINING_COMPLETE_MASK_MASK 0x100
+#define DP_DPHY_FAST_TRAINING_STATUS__DPHY_FAST_TRAINING_COMPLETE_MASK__SHIFT 0x8
+#define DP_DPHY_FAST_TRAINING_STATUS__DPHY_FAST_TRAINING_COMPLETE_ACK_MASK 0x1000
+#define DP_DPHY_FAST_TRAINING_STATUS__DPHY_FAST_TRAINING_COMPLETE_ACK__SHIFT 0xc
+#define DP_DPHY_HBR2_PATTERN_CONTROL__DP_DPHY_HBR2_PATTERN_CONTROL_MASK 0x7
+#define DP_DPHY_HBR2_PATTERN_CONTROL__DP_DPHY_HBR2_PATTERN_CONTROL__SHIFT 0x0
+#define DP_MSA_V_TIMING_OVERRIDE1__DP_MSA_V_TIMING_OVERRIDE_EN_MASK 0x1
+#define DP_MSA_V_TIMING_OVERRIDE1__DP_MSA_V_TIMING_OVERRIDE_EN__SHIFT 0x0
+#define DP_MSA_V_TIMING_OVERRIDE1__DP_MSA_V_TOTAL_OVERRIDE_MASK 0x3fff0
+#define DP_MSA_V_TIMING_OVERRIDE1__DP_MSA_V_TOTAL_OVERRIDE__SHIFT 0x4
+#define DP_MSA_V_TIMING_OVERRIDE2__DP_MSA_V_BLANK_START_OVERRIDE_MASK 0x3fff
+#define DP_MSA_V_TIMING_OVERRIDE2__DP_MSA_V_BLANK_START_OVERRIDE__SHIFT 0x0
+#define DP_MSA_V_TIMING_OVERRIDE2__DP_MSA_V_BLANK_END_OVERRIDE_MASK 0x3fff0000
+#define DP_MSA_V_TIMING_OVERRIDE2__DP_MSA_V_BLANK_END_OVERRIDE__SHIFT 0x10
+#define DP_SEC_CNTL__DP_SEC_STREAM_ENABLE_MASK 0x1
+#define DP_SEC_CNTL__DP_SEC_STREAM_ENABLE__SHIFT 0x0
+#define DP_SEC_CNTL__DP_SEC_ASP_ENABLE_MASK 0x10
+#define DP_SEC_CNTL__DP_SEC_ASP_ENABLE__SHIFT 0x4
+#define DP_SEC_CNTL__DP_SEC_ATP_ENABLE_MASK 0x100
+#define DP_SEC_CNTL__DP_SEC_ATP_ENABLE__SHIFT 0x8
+#define DP_SEC_CNTL__DP_SEC_AIP_ENABLE_MASK 0x1000
+#define DP_SEC_CNTL__DP_SEC_AIP_ENABLE__SHIFT 0xc
+#define DP_SEC_CNTL__DP_SEC_ACM_ENABLE_MASK 0x10000
+#define DP_SEC_CNTL__DP_SEC_ACM_ENABLE__SHIFT 0x10
+#define DP_SEC_CNTL__DP_SEC_GSP0_ENABLE_MASK 0x100000
+#define DP_SEC_CNTL__DP_SEC_GSP0_ENABLE__SHIFT 0x14
+#define DP_SEC_CNTL__DP_SEC_GSP1_ENABLE_MASK 0x200000
+#define DP_SEC_CNTL__DP_SEC_GSP1_ENABLE__SHIFT 0x15
+#define DP_SEC_CNTL__DP_SEC_GSP2_ENABLE_MASK 0x400000
+#define DP_SEC_CNTL__DP_SEC_GSP2_ENABLE__SHIFT 0x16
+#define DP_SEC_CNTL__DP_SEC_GSP3_ENABLE_MASK 0x800000
+#define DP_SEC_CNTL__DP_SEC_GSP3_ENABLE__SHIFT 0x17
+#define DP_SEC_CNTL__DP_SEC_AVI_ENABLE_MASK 0x1000000
+#define DP_SEC_CNTL__DP_SEC_AVI_ENABLE__SHIFT 0x18
+#define DP_SEC_CNTL__DP_SEC_MPG_ENABLE_MASK 0x10000000
+#define DP_SEC_CNTL__DP_SEC_MPG_ENABLE__SHIFT 0x1c
+#define DP_SEC_CNTL1__DP_SEC_ISRC_ENABLE_MASK 0x1
+#define DP_SEC_CNTL1__DP_SEC_ISRC_ENABLE__SHIFT 0x0
+#define DP_SEC_CNTL1__DP_SEC_GSP0_PRIORITY_MASK 0x10
+#define DP_SEC_CNTL1__DP_SEC_GSP0_PRIORITY__SHIFT 0x4
+#define DP_SEC_CNTL1__DP_SEC_GSP0_SEND_MASK 0x20
+#define DP_SEC_CNTL1__DP_SEC_GSP0_SEND__SHIFT 0x5
+#define DP_SEC_CNTL1__DP_SEC_GSP0_SEND_PENDING_MASK 0x40
+#define DP_SEC_CNTL1__DP_SEC_GSP0_SEND_PENDING__SHIFT 0x6
+#define DP_SEC_CNTL1__DP_SEC_GSP0_SEND_DEADLINE_MISSED_MASK 0x80
+#define DP_SEC_CNTL1__DP_SEC_GSP0_SEND_DEADLINE_MISSED__SHIFT 0x7
+#define DP_SEC_CNTL1__DP_SEC_GSP0_LINE_NUM_MASK 0xffff0000
+#define DP_SEC_CNTL1__DP_SEC_GSP0_LINE_NUM__SHIFT 0x10
+#define DP_SEC_FRAMING1__DP_SEC_FRAME_START_LOCATION_MASK 0xfff
+#define DP_SEC_FRAMING1__DP_SEC_FRAME_START_LOCATION__SHIFT 0x0
+#define DP_SEC_FRAMING1__DP_SEC_VBLANK_TRANSMIT_WIDTH_MASK 0xffff0000
+#define DP_SEC_FRAMING1__DP_SEC_VBLANK_TRANSMIT_WIDTH__SHIFT 0x10
+#define DP_SEC_FRAMING2__DP_SEC_START_POSITION_MASK 0xffff
+#define DP_SEC_FRAMING2__DP_SEC_START_POSITION__SHIFT 0x0
+#define DP_SEC_FRAMING2__DP_SEC_HBLANK_TRANSMIT_WIDTH_MASK 0xffff0000
+#define DP_SEC_FRAMING2__DP_SEC_HBLANK_TRANSMIT_WIDTH__SHIFT 0x10
+#define DP_SEC_FRAMING3__DP_SEC_IDLE_FRAME_SIZE_MASK 0x3fff
+#define DP_SEC_FRAMING3__DP_SEC_IDLE_FRAME_SIZE__SHIFT 0x0
+#define DP_SEC_FRAMING3__DP_SEC_IDLE_TRANSMIT_WIDTH_MASK 0xffff0000
+#define DP_SEC_FRAMING3__DP_SEC_IDLE_TRANSMIT_WIDTH__SHIFT 0x10
+#define DP_SEC_FRAMING4__DP_SEC_COLLISION_STATUS_MASK 0x100000
+#define DP_SEC_FRAMING4__DP_SEC_COLLISION_STATUS__SHIFT 0x14
+#define DP_SEC_FRAMING4__DP_SEC_COLLISION_ACK_MASK 0x1000000
+#define DP_SEC_FRAMING4__DP_SEC_COLLISION_ACK__SHIFT 0x18
+#define DP_SEC_FRAMING4__DP_SEC_AUDIO_MUTE_MASK 0x10000000
+#define DP_SEC_FRAMING4__DP_SEC_AUDIO_MUTE__SHIFT 0x1c
+#define DP_SEC_FRAMING4__DP_SEC_AUDIO_MUTE_STATUS_MASK 0x20000000
+#define DP_SEC_FRAMING4__DP_SEC_AUDIO_MUTE_STATUS__SHIFT 0x1d
+#define DP_SEC_AUD_N__DP_SEC_AUD_N_MASK 0xffffff
+#define DP_SEC_AUD_N__DP_SEC_AUD_N__SHIFT 0x0
+#define DP_SEC_AUD_N_READBACK__DP_SEC_AUD_N_READBACK_MASK 0xffffff
+#define DP_SEC_AUD_N_READBACK__DP_SEC_AUD_N_READBACK__SHIFT 0x0
+#define DP_SEC_AUD_M__DP_SEC_AUD_M_MASK 0xffffff
+#define DP_SEC_AUD_M__DP_SEC_AUD_M__SHIFT 0x0
+#define DP_SEC_AUD_M_READBACK__DP_SEC_AUD_M_READBACK_MASK 0xffffff
+#define DP_SEC_AUD_M_READBACK__DP_SEC_AUD_M_READBACK__SHIFT 0x0
+#define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE_MASK 0x1
+#define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__SHIFT 0x0
+#define DP_SEC_PACKET_CNTL__DP_SEC_ASP_CODING_TYPE_MASK 0xe
+#define DP_SEC_PACKET_CNTL__DP_SEC_ASP_CODING_TYPE__SHIFT 0x1
+#define DP_SEC_PACKET_CNTL__DP_SEC_ASP_PRIORITY_MASK 0x10
+#define DP_SEC_PACKET_CNTL__DP_SEC_ASP_PRIORITY__SHIFT 0x4
+#define DP_SEC_PACKET_CNTL__DP_SEC_VERSION_MASK 0x3f00
+#define DP_SEC_PACKET_CNTL__DP_SEC_VERSION__SHIFT 0x8
+#define DP_SEC_PACKET_CNTL__DP_SEC_ASP_CHANNEL_COUNT_OVERRIDE_MASK 0x10000
+#define DP_SEC_PACKET_CNTL__DP_SEC_ASP_CHANNEL_COUNT_OVERRIDE__SHIFT 0x10
+#define DP_MSE_RATE_CNTL__DP_MSE_RATE_Y_MASK 0x3ffffff
+#define DP_MSE_RATE_CNTL__DP_MSE_RATE_Y__SHIFT 0x0
+#define DP_MSE_RATE_CNTL__DP_MSE_RATE_X_MASK 0xfc000000
+#define DP_MSE_RATE_CNTL__DP_MSE_RATE_X__SHIFT 0x1a
+#define DP_MSE_RATE_UPDATE__DP_MSE_RATE_UPDATE_PENDING_MASK 0x1
+#define DP_MSE_RATE_UPDATE__DP_MSE_RATE_UPDATE_PENDING__SHIFT 0x0
+#define DP_MSE_SAT0__DP_MSE_SAT_SRC0_MASK 0x7
+#define DP_MSE_SAT0__DP_MSE_SAT_SRC0__SHIFT 0x0
+#define DP_MSE_SAT0__DP_MSE_SAT_SLOT_COUNT0_MASK 0x3f00
+#define DP_MSE_SAT0__DP_MSE_SAT_SLOT_COUNT0__SHIFT 0x8
+#define DP_MSE_SAT0__DP_MSE_SAT_SRC1_MASK 0x70000
+#define DP_MSE_SAT0__DP_MSE_SAT_SRC1__SHIFT 0x10
+#define DP_MSE_SAT0__DP_MSE_SAT_SLOT_COUNT1_MASK 0x3f000000
+#define DP_MSE_SAT0__DP_MSE_SAT_SLOT_COUNT1__SHIFT 0x18
+#define DP_MSE_SAT1__DP_MSE_SAT_SRC2_MASK 0x7
+#define DP_MSE_SAT1__DP_MSE_SAT_SRC2__SHIFT 0x0
+#define DP_MSE_SAT1__DP_MSE_SAT_SLOT_COUNT2_MASK 0x3f00
+#define DP_MSE_SAT1__DP_MSE_SAT_SLOT_COUNT2__SHIFT 0x8
+#define DP_MSE_SAT1__DP_MSE_SAT_SRC3_MASK 0x70000
+#define DP_MSE_SAT1__DP_MSE_SAT_SRC3__SHIFT 0x10
+#define DP_MSE_SAT1__DP_MSE_SAT_SLOT_COUNT3_MASK 0x3f000000
+#define DP_MSE_SAT1__DP_MSE_SAT_SLOT_COUNT3__SHIFT 0x18
+#define DP_MSE_SAT2__DP_MSE_SAT_SRC4_MASK 0x7
+#define DP_MSE_SAT2__DP_MSE_SAT_SRC4__SHIFT 0x0
+#define DP_MSE_SAT2__DP_MSE_SAT_SLOT_COUNT4_MASK 0x3f00
+#define DP_MSE_SAT2__DP_MSE_SAT_SLOT_COUNT4__SHIFT 0x8
+#define DP_MSE_SAT2__DP_MSE_SAT_SRC5_MASK 0x70000
+#define DP_MSE_SAT2__DP_MSE_SAT_SRC5__SHIFT 0x10
+#define DP_MSE_SAT2__DP_MSE_SAT_SLOT_COUNT5_MASK 0x3f000000
+#define DP_MSE_SAT2__DP_MSE_SAT_SLOT_COUNT5__SHIFT 0x18
+#define DP_MSE_SAT_UPDATE__DP_MSE_SAT_UPDATE_MASK 0x3
+#define DP_MSE_SAT_UPDATE__DP_MSE_SAT_UPDATE__SHIFT 0x0
+#define DP_MSE_SAT_UPDATE__DP_MSE_16_MTP_KEEPOUT_MASK 0x100
+#define DP_MSE_SAT_UPDATE__DP_MSE_16_MTP_KEEPOUT__SHIFT 0x8
+#define DP_MSE_LINK_TIMING__DP_MSE_LINK_FRAME_MASK 0x3ff
+#define DP_MSE_LINK_TIMING__DP_MSE_LINK_FRAME__SHIFT 0x0
+#define DP_MSE_LINK_TIMING__DP_MSE_LINK_LINE_MASK 0x30000
+#define DP_MSE_LINK_TIMING__DP_MSE_LINK_LINE__SHIFT 0x10
+#define DP_MSE_MISC_CNTL__DP_MSE_BLANK_CODE_MASK 0x1
+#define DP_MSE_MISC_CNTL__DP_MSE_BLANK_CODE__SHIFT 0x0
+#define DP_MSE_MISC_CNTL__DP_MSE_TIMESTAMP_MODE_MASK 0x10
+#define DP_MSE_MISC_CNTL__DP_MSE_TIMESTAMP_MODE__SHIFT 0x4
+#define DP_MSE_MISC_CNTL__DP_MSE_ZERO_ENCODER_MASK 0x100
+#define DP_MSE_MISC_CNTL__DP_MSE_ZERO_ENCODER__SHIFT 0x8
+#define DP_MSE_MISC_CNTL__DP_MSE_OUTPUT_DPDBG_DATA_MASK 0x10000
+#define DP_MSE_MISC_CNTL__DP_MSE_OUTPUT_DPDBG_DATA__SHIFT 0x10
+#define DP_MSE_SAT0_STATUS__DP_MSE_SAT_SRC0_STATUS_MASK 0x7
+#define DP_MSE_SAT0_STATUS__DP_MSE_SAT_SRC0_STATUS__SHIFT 0x0
+#define DP_MSE_SAT0_STATUS__DP_MSE_SAT_SLOT_COUNT0_STATUS_MASK 0x3f00
+#define DP_MSE_SAT0_STATUS__DP_MSE_SAT_SLOT_COUNT0_STATUS__SHIFT 0x8
+#define DP_MSE_SAT0_STATUS__DP_MSE_SAT_SRC1_STATUS_MASK 0x70000
+#define DP_MSE_SAT0_STATUS__DP_MSE_SAT_SRC1_STATUS__SHIFT 0x10
+#define DP_MSE_SAT0_STATUS__DP_MSE_SAT_SLOT_COUNT1_STATUS_MASK 0x3f000000
+#define DP_MSE_SAT0_STATUS__DP_MSE_SAT_SLOT_COUNT1_STATUS__SHIFT 0x18
+#define DP_MSE_SAT1_STATUS__DP_MSE_SAT_SRC2_STATUS_MASK 0x7
+#define DP_MSE_SAT1_STATUS__DP_MSE_SAT_SRC2_STATUS__SHIFT 0x0
+#define DP_MSE_SAT1_STATUS__DP_MSE_SAT_SLOT_COUNT2_STATUS_MASK 0x3f00
+#define DP_MSE_SAT1_STATUS__DP_MSE_SAT_SLOT_COUNT2_STATUS__SHIFT 0x8
+#define DP_MSE_SAT1_STATUS__DP_MSE_SAT_SRC3_STATUS_MASK 0x70000
+#define DP_MSE_SAT1_STATUS__DP_MSE_SAT_SRC3_STATUS__SHIFT 0x10
+#define DP_MSE_SAT1_STATUS__DP_MSE_SAT_SLOT_COUNT3_STATUS_MASK 0x3f000000
+#define DP_MSE_SAT1_STATUS__DP_MSE_SAT_SLOT_COUNT3_STATUS__SHIFT 0x18
+#define DP_MSE_SAT2_STATUS__DP_MSE_SAT_SRC4_STATUS_MASK 0x7
+#define DP_MSE_SAT2_STATUS__DP_MSE_SAT_SRC4_STATUS__SHIFT 0x0
+#define DP_MSE_SAT2_STATUS__DP_MSE_SAT_SLOT_COUNT4_STATUS_MASK 0x3f00
+#define DP_MSE_SAT2_STATUS__DP_MSE_SAT_SLOT_COUNT4_STATUS__SHIFT 0x8
+#define DP_MSE_SAT2_STATUS__DP_MSE_SAT_SRC5_STATUS_MASK 0x70000
+#define DP_MSE_SAT2_STATUS__DP_MSE_SAT_SRC5_STATUS__SHIFT 0x10
+#define DP_MSE_SAT2_STATUS__DP_MSE_SAT_SLOT_COUNT5_STATUS_MASK 0x3f000000
+#define DP_MSE_SAT2_STATUS__DP_MSE_SAT_SLOT_COUNT5_STATUS__SHIFT 0x18
+#define DP_TEST_DEBUG_INDEX__DP_TEST_DEBUG_INDEX_MASK 0xff
+#define DP_TEST_DEBUG_INDEX__DP_TEST_DEBUG_INDEX__SHIFT 0x0
+#define DP_TEST_DEBUG_INDEX__DP_TEST_DEBUG_WRITE_EN_MASK 0x100
+#define DP_TEST_DEBUG_INDEX__DP_TEST_DEBUG_WRITE_EN__SHIFT 0x8
+#define DP_TEST_DEBUG_DATA__DP_TEST_DEBUG_DATA_MASK 0xffffffff
+#define DP_TEST_DEBUG_DATA__DP_TEST_DEBUG_DATA__SHIFT 0x0
+#define DP_FE_TEST_DEBUG_INDEX__DP_FE_TEST_DEBUG_INDEX_MASK 0xff
+#define DP_FE_TEST_DEBUG_INDEX__DP_FE_TEST_DEBUG_INDEX__SHIFT 0x0
+#define DP_FE_TEST_DEBUG_INDEX__DP_FE_TEST_DEBUG_WRITE_EN_MASK 0x100
+#define DP_FE_TEST_DEBUG_INDEX__DP_FE_TEST_DEBUG_WRITE_EN__SHIFT 0x8
+#define DP_FE_TEST_DEBUG_DATA__DP_FE_TEST_DEBUG_DATA_MASK 0xffffffff
+#define DP_FE_TEST_DEBUG_DATA__DP_FE_TEST_DEBUG_DATA__SHIFT 0x0
+#define AUX_CONTROL__AUX_EN_MASK 0x1
+#define AUX_CONTROL__AUX_EN__SHIFT 0x0
+#define AUX_CONTROL__AUX_RESET_MASK 0x10
+#define AUX_CONTROL__AUX_RESET__SHIFT 0x4
+#define AUX_CONTROL__AUX_RESET_DONE_MASK 0x20
+#define AUX_CONTROL__AUX_RESET_DONE__SHIFT 0x5
+#define AUX_CONTROL__AUX_LS_READ_EN_MASK 0x100
+#define AUX_CONTROL__AUX_LS_READ_EN__SHIFT 0x8
+#define AUX_CONTROL__AUX_LS_UPDATE_DISABLE_MASK 0x1000
+#define AUX_CONTROL__AUX_LS_UPDATE_DISABLE__SHIFT 0xc
+#define AUX_CONTROL__AUX_IGNORE_HPD_DISCON_MASK 0x10000
+#define AUX_CONTROL__AUX_IGNORE_HPD_DISCON__SHIFT 0x10
+#define AUX_CONTROL__AUX_MODE_DET_EN_MASK 0x40000
+#define AUX_CONTROL__AUX_MODE_DET_EN__SHIFT 0x12
+#define AUX_CONTROL__AUX_HPD_SEL_MASK 0x700000
+#define AUX_CONTROL__AUX_HPD_SEL__SHIFT 0x14
+#define AUX_CONTROL__AUX_IMPCAL_REQ_EN_MASK 0x1000000
+#define AUX_CONTROL__AUX_IMPCAL_REQ_EN__SHIFT 0x18
+#define AUX_CONTROL__AUX_TEST_MODE_MASK 0x10000000
+#define AUX_CONTROL__AUX_TEST_MODE__SHIFT 0x1c
+#define AUX_CONTROL__AUX_DEGLITCH_EN_MASK 0x20000000
+#define AUX_CONTROL__AUX_DEGLITCH_EN__SHIFT 0x1d
+#define AUX_CONTROL__SPARE_0_MASK 0x40000000
+#define AUX_CONTROL__SPARE_0__SHIFT 0x1e
+#define AUX_CONTROL__SPARE_1_MASK 0x80000000
+#define AUX_CONTROL__SPARE_1__SHIFT 0x1f
+#define AUX_SW_CONTROL__AUX_SW_GO_MASK 0x1
+#define AUX_SW_CONTROL__AUX_SW_GO__SHIFT 0x0
+#define AUX_SW_CONTROL__AUX_LS_READ_TRIG_MASK 0x4
+#define AUX_SW_CONTROL__AUX_LS_READ_TRIG__SHIFT 0x2
+#define AUX_SW_CONTROL__AUX_SW_START_DELAY_MASK 0xf0
+#define AUX_SW_CONTROL__AUX_SW_START_DELAY__SHIFT 0x4
+#define AUX_SW_CONTROL__AUX_SW_WR_BYTES_MASK 0x1f0000
+#define AUX_SW_CONTROL__AUX_SW_WR_BYTES__SHIFT 0x10
+#define AUX_ARB_CONTROL__AUX_ARB_PRIORITY_MASK 0x3
+#define AUX_ARB_CONTROL__AUX_ARB_PRIORITY__SHIFT 0x0
+#define AUX_ARB_CONTROL__AUX_REG_RW_CNTL_STATUS_MASK 0xc
+#define AUX_ARB_CONTROL__AUX_REG_RW_CNTL_STATUS__SHIFT 0x2
+#define AUX_ARB_CONTROL__AUX_NO_QUEUED_SW_GO_MASK 0x100
+#define AUX_ARB_CONTROL__AUX_NO_QUEUED_SW_GO__SHIFT 0x8
+#define AUX_ARB_CONTROL__AUX_NO_QUEUED_LS_GO_MASK 0x400
+#define AUX_ARB_CONTROL__AUX_NO_QUEUED_LS_GO__SHIFT 0xa
+#define AUX_ARB_CONTROL__AUX_SW_USE_AUX_REG_REQ_MASK 0x10000
+#define AUX_ARB_CONTROL__AUX_SW_USE_AUX_REG_REQ__SHIFT 0x10
+#define AUX_ARB_CONTROL__AUX_SW_PENDING_USE_AUX_REG_REQ_MASK 0x10000
+#define AUX_ARB_CONTROL__AUX_SW_PENDING_USE_AUX_REG_REQ__SHIFT 0x10
+#define AUX_ARB_CONTROL__AUX_SW_DONE_USING_AUX_REG_MASK 0x20000
+#define AUX_ARB_CONTROL__AUX_SW_DONE_USING_AUX_REG__SHIFT 0x11
+#define AUX_ARB_CONTROL__AUX_DMCU_USE_AUX_REG_REQ_MASK 0x1000000
+#define AUX_ARB_CONTROL__AUX_DMCU_USE_AUX_REG_REQ__SHIFT 0x18
+#define AUX_ARB_CONTROL__AUX_DMCU_PENDING_USE_AUX_REG_REQ_MASK 0x1000000
+#define AUX_ARB_CONTROL__AUX_DMCU_PENDING_USE_AUX_REG_REQ__SHIFT 0x18
+#define AUX_ARB_CONTROL__AUX_DMCU_DONE_USING_AUX_REG_MASK 0x2000000
+#define AUX_ARB_CONTROL__AUX_DMCU_DONE_USING_AUX_REG__SHIFT 0x19
+#define AUX_INTERRUPT_CONTROL__AUX_SW_DONE_INT_MASK 0x1
+#define AUX_INTERRUPT_CONTROL__AUX_SW_DONE_INT__SHIFT 0x0
+#define AUX_INTERRUPT_CONTROL__AUX_SW_DONE_ACK_MASK 0x2
+#define AUX_INTERRUPT_CONTROL__AUX_SW_DONE_ACK__SHIFT 0x1
+#define AUX_INTERRUPT_CONTROL__AUX_SW_DONE_MASK_MASK 0x4
+#define AUX_INTERRUPT_CONTROL__AUX_SW_DONE_MASK__SHIFT 0x2
+#define AUX_INTERRUPT_CONTROL__AUX_LS_DONE_INT_MASK 0x10
+#define AUX_INTERRUPT_CONTROL__AUX_LS_DONE_INT__SHIFT 0x4
+#define AUX_INTERRUPT_CONTROL__AUX_LS_DONE_ACK_MASK 0x20
+#define AUX_INTERRUPT_CONTROL__AUX_LS_DONE_ACK__SHIFT 0x5
+#define AUX_INTERRUPT_CONTROL__AUX_LS_DONE_MASK_MASK 0x40
+#define AUX_INTERRUPT_CONTROL__AUX_LS_DONE_MASK__SHIFT 0x6
+#define AUX_INTERRUPT_CONTROL__AUX_GTC_SYNC_LOCK_DONE_INT_MASK 0x100
+#define AUX_INTERRUPT_CONTROL__AUX_GTC_SYNC_LOCK_DONE_INT__SHIFT 0x8
+#define AUX_INTERRUPT_CONTROL__AUX_GTC_SYNC_LOCK_DONE_ACK_MASK 0x200
+#define AUX_INTERRUPT_CONTROL__AUX_GTC_SYNC_LOCK_DONE_ACK__SHIFT 0x9
+#define AUX_INTERRUPT_CONTROL__AUX_GTC_SYNC_LOCK_DONE_INT_MASK_MASK 0x400
+#define AUX_INTERRUPT_CONTROL__AUX_GTC_SYNC_LOCK_DONE_INT_MASK__SHIFT 0xa
+#define AUX_INTERRUPT_CONTROL__AUX_GTC_SYNC_ERROR_INT_MASK 0x1000
+#define AUX_INTERRUPT_CONTROL__AUX_GTC_SYNC_ERROR_INT__SHIFT 0xc
+#define AUX_INTERRUPT_CONTROL__AUX_GTC_SYNC_ERROR_ACK_MASK 0x2000
+#define AUX_INTERRUPT_CONTROL__AUX_GTC_SYNC_ERROR_ACK__SHIFT 0xd
+#define AUX_INTERRUPT_CONTROL__AUX_GTC_SYNC_ERROR_INT_MASK_MASK 0x4000
+#define AUX_INTERRUPT_CONTROL__AUX_GTC_SYNC_ERROR_INT_MASK__SHIFT 0xe
+#define AUX_SW_STATUS__AUX_SW_DONE_MASK 0x1
+#define AUX_SW_STATUS__AUX_SW_DONE__SHIFT 0x0
+#define AUX_SW_STATUS__AUX_SW_REQ_MASK 0x2
+#define AUX_SW_STATUS__AUX_SW_REQ__SHIFT 0x1
+#define AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_STATE_MASK 0x70
+#define AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_STATE__SHIFT 0x4
+#define AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_MASK 0x80
+#define AUX_SW_STATUS__AUX_SW_RX_TIMEOUT__SHIFT 0x7
+#define AUX_SW_STATUS__AUX_SW_RX_OVERFLOW_MASK 0x100
+#define AUX_SW_STATUS__AUX_SW_RX_OVERFLOW__SHIFT 0x8
+#define AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK 0x200
+#define AUX_SW_STATUS__AUX_SW_HPD_DISCON__SHIFT 0x9
+#define AUX_SW_STATUS__AUX_SW_RX_PARTIAL_BYTE_MASK 0x400
+#define AUX_SW_STATUS__AUX_SW_RX_PARTIAL_BYTE__SHIFT 0xa
+#define AUX_SW_STATUS__AUX_SW_NON_AUX_MODE_MASK 0x800
+#define AUX_SW_STATUS__AUX_SW_NON_AUX_MODE__SHIFT 0xb
+#define AUX_SW_STATUS__AUX_SW_RX_MIN_COUNT_VIOL_MASK 0x1000
+#define AUX_SW_STATUS__AUX_SW_RX_MIN_COUNT_VIOL__SHIFT 0xc
+#define AUX_SW_STATUS__AUX_SW_RX_INVALID_STOP_MASK 0x4000
+#define AUX_SW_STATUS__AUX_SW_RX_INVALID_STOP__SHIFT 0xe
+#define AUX_SW_STATUS__AUX_SW_RX_SYNC_INVALID_L_MASK 0x20000
+#define AUX_SW_STATUS__AUX_SW_RX_SYNC_INVALID_L__SHIFT 0x11
+#define AUX_SW_STATUS__AUX_SW_RX_SYNC_INVALID_H_MASK 0x40000
+#define AUX_SW_STATUS__AUX_SW_RX_SYNC_INVALID_H__SHIFT 0x12
+#define AUX_SW_STATUS__AUX_SW_RX_INVALID_START_MASK 0x80000
+#define AUX_SW_STATUS__AUX_SW_RX_INVALID_START__SHIFT 0x13
+#define AUX_SW_STATUS__AUX_SW_RX_RECV_NO_DET_MASK 0x100000
+#define AUX_SW_STATUS__AUX_SW_RX_RECV_NO_DET__SHIFT 0x14
+#define AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_H_MASK 0x400000
+#define AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_H__SHIFT 0x16
+#define AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_L_MASK 0x800000
+#define AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_L__SHIFT 0x17
+#define AUX_SW_STATUS__AUX_SW_REPLY_BYTE_COUNT_MASK 0x1f000000
+#define AUX_SW_STATUS__AUX_SW_REPLY_BYTE_COUNT__SHIFT 0x18
+#define AUX_SW_STATUS__AUX_ARB_STATUS_MASK 0xc0000000
+#define AUX_SW_STATUS__AUX_ARB_STATUS__SHIFT 0x1e
+#define AUX_LS_STATUS__AUX_LS_DONE_MASK 0x1
+#define AUX_LS_STATUS__AUX_LS_DONE__SHIFT 0x0
+#define AUX_LS_STATUS__AUX_LS_REQ_MASK 0x2
+#define AUX_LS_STATUS__AUX_LS_REQ__SHIFT 0x1
+#define AUX_LS_STATUS__AUX_LS_RX_TIMEOUT_STATE_MASK 0x70
+#define AUX_LS_STATUS__AUX_LS_RX_TIMEOUT_STATE__SHIFT 0x4
+#define AUX_LS_STATUS__AUX_LS_RX_TIMEOUT_MASK 0x80
+#define AUX_LS_STATUS__AUX_LS_RX_TIMEOUT__SHIFT 0x7
+#define AUX_LS_STATUS__AUX_LS_RX_OVERFLOW_MASK 0x100
+#define AUX_LS_STATUS__AUX_LS_RX_OVERFLOW__SHIFT 0x8
+#define AUX_LS_STATUS__AUX_LS_HPD_DISCON_MASK 0x200
+#define AUX_LS_STATUS__AUX_LS_HPD_DISCON__SHIFT 0x9
+#define AUX_LS_STATUS__AUX_LS_RX_PARTIAL_BYTE_MASK 0x400
+#define AUX_LS_STATUS__AUX_LS_RX_PARTIAL_BYTE__SHIFT 0xa
+#define AUX_LS_STATUS__AUX_LS_NON_AUX_MODE_MASK 0x800
+#define AUX_LS_STATUS__AUX_LS_NON_AUX_MODE__SHIFT 0xb
+#define AUX_LS_STATUS__AUX_LS_RX_MIN_COUNT_VIOL_MASK 0x1000
+#define AUX_LS_STATUS__AUX_LS_RX_MIN_COUNT_VIOL__SHIFT 0xc
+#define AUX_LS_STATUS__AUX_LS_RX_INVALID_STOP_MASK 0x4000
+#define AUX_LS_STATUS__AUX_LS_RX_INVALID_STOP__SHIFT 0xe
+#define AUX_LS_STATUS__AUX_LS_RX_SYNC_INVALID_L_MASK 0x20000
+#define AUX_LS_STATUS__AUX_LS_RX_SYNC_INVALID_L__SHIFT 0x11
+#define AUX_LS_STATUS__AUX_LS_RX_SYNC_INVALID_H_MASK 0x40000
+#define AUX_LS_STATUS__AUX_LS_RX_SYNC_INVALID_H__SHIFT 0x12
+#define AUX_LS_STATUS__AUX_LS_RX_INVALID_START_MASK 0x80000
+#define AUX_LS_STATUS__AUX_LS_RX_INVALID_START__SHIFT 0x13
+#define AUX_LS_STATUS__AUX_LS_RX_RECV_NO_DET_MASK 0x100000
+#define AUX_LS_STATUS__AUX_LS_RX_RECV_NO_DET__SHIFT 0x14
+#define AUX_LS_STATUS__AUX_LS_RX_RECV_INVALID_H_MASK 0x400000
+#define AUX_LS_STATUS__AUX_LS_RX_RECV_INVALID_H__SHIFT 0x16
+#define AUX_LS_STATUS__AUX_LS_RX_RECV_INVALID_L_MASK 0x800000
+#define AUX_LS_STATUS__AUX_LS_RX_RECV_INVALID_L__SHIFT 0x17
+#define AUX_LS_STATUS__AUX_LS_REPLY_BYTE_COUNT_MASK 0x1f000000
+#define AUX_LS_STATUS__AUX_LS_REPLY_BYTE_COUNT__SHIFT 0x18
+#define AUX_LS_STATUS__AUX_LS_CP_IRQ_MASK 0x20000000
+#define AUX_LS_STATUS__AUX_LS_CP_IRQ__SHIFT 0x1d
+#define AUX_LS_STATUS__AUX_LS_UPDATED_MASK 0x40000000
+#define AUX_LS_STATUS__AUX_LS_UPDATED__SHIFT 0x1e
+#define AUX_LS_STATUS__AUX_LS_UPDATED_ACK_MASK 0x80000000
+#define AUX_LS_STATUS__AUX_LS_UPDATED_ACK__SHIFT 0x1f
+#define AUX_SW_DATA__AUX_SW_DATA_RW_MASK 0x1
+#define AUX_SW_DATA__AUX_SW_DATA_RW__SHIFT 0x0
+#define AUX_SW_DATA__AUX_SW_DATA_MASK 0xff00
+#define AUX_SW_DATA__AUX_SW_DATA__SHIFT 0x8
+#define AUX_SW_DATA__AUX_SW_INDEX_MASK 0x1f0000
+#define AUX_SW_DATA__AUX_SW_INDEX__SHIFT 0x10
+#define AUX_SW_DATA__AUX_SW_AUTOINCREMENT_DISABLE_MASK 0x80000000
+#define AUX_SW_DATA__AUX_SW_AUTOINCREMENT_DISABLE__SHIFT 0x1f
+#define AUX_LS_DATA__AUX_LS_DATA_MASK 0xff00
+#define AUX_LS_DATA__AUX_LS_DATA__SHIFT 0x8
+#define AUX_LS_DATA__AUX_LS_INDEX_MASK 0x1f0000
+#define AUX_LS_DATA__AUX_LS_INDEX__SHIFT 0x10
+#define AUX_DPHY_TX_REF_CONTROL__AUX_TX_REF_SEL_MASK 0x1
+#define AUX_DPHY_TX_REF_CONTROL__AUX_TX_REF_SEL__SHIFT 0x0
+#define AUX_DPHY_TX_REF_CONTROL__AUX_TX_RATE_MASK 0x30
+#define AUX_DPHY_TX_REF_CONTROL__AUX_TX_RATE__SHIFT 0x4
+#define AUX_DPHY_TX_REF_CONTROL__AUX_TX_REF_DIV_MASK 0x1ff0000
+#define AUX_DPHY_TX_REF_CONTROL__AUX_TX_REF_DIV__SHIFT 0x10
+#define AUX_DPHY_TX_CONTROL__AUX_TX_PRECHARGE_LEN_MASK 0x7
+#define AUX_DPHY_TX_CONTROL__AUX_TX_PRECHARGE_LEN__SHIFT 0x0
+#define AUX_DPHY_TX_CONTROL__AUX_TX_PRECHARGE_SYMBOLS_MASK 0x3f00
+#define AUX_DPHY_TX_CONTROL__AUX_TX_PRECHARGE_SYMBOLS__SHIFT 0x8
+#define AUX_DPHY_TX_CONTROL__AUX_MODE_DET_CHECK_DELAY_MASK 0x70000
+#define AUX_DPHY_TX_CONTROL__AUX_MODE_DET_CHECK_DELAY__SHIFT 0x10
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_START_WINDOW_MASK 0x70
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_START_WINDOW__SHIFT 0x4
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_RECEIVE_WINDOW_MASK 0x700
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_RECEIVE_WINDOW__SHIFT 0x8
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_HALF_SYM_DETECT_LEN_MASK 0x3000
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_HALF_SYM_DETECT_LEN__SHIFT 0xc
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_TRANSITION_FILTER_EN_MASK 0x10000
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_TRANSITION_FILTER_EN__SHIFT 0x10
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT_MASK 0x20000
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT__SHIFT 0x11
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_ALLOW_BELOW_THRESHOLD_START_MASK 0x40000
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_ALLOW_BELOW_THRESHOLD_START__SHIFT 0x12
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_ALLOW_BELOW_THRESHOLD_STOP_MASK 0x80000
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_ALLOW_BELOW_THRESHOLD_STOP__SHIFT 0x13
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_PHASE_DETECT_LEN_MASK 0x300000
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_PHASE_DETECT_LEN__SHIFT 0x14
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_TIMEOUT_LEN_MASK 0x7000000
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_TIMEOUT_LEN__SHIFT 0x18
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_DETECTION_THRESHOLD_MASK 0x70000000
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_DETECTION_THRESHOLD__SHIFT 0x1c
+#define AUX_DPHY_RX_CONTROL1__AUX_RX_PRECHARGE_SKIP_MASK 0xff
+#define AUX_DPHY_RX_CONTROL1__AUX_RX_PRECHARGE_SKIP__SHIFT 0x0
+#define AUX_DPHY_TX_STATUS__AUX_TX_ACTIVE_MASK 0x1
+#define AUX_DPHY_TX_STATUS__AUX_TX_ACTIVE__SHIFT 0x0
+#define AUX_DPHY_TX_STATUS__AUX_TX_STATE_MASK 0x70
+#define AUX_DPHY_TX_STATUS__AUX_TX_STATE__SHIFT 0x4
+#define AUX_DPHY_TX_STATUS__AUX_TX_HALF_SYM_PERIOD_MASK 0x1ff0000
+#define AUX_DPHY_TX_STATUS__AUX_TX_HALF_SYM_PERIOD__SHIFT 0x10
+#define AUX_DPHY_RX_STATUS__AUX_RX_STATE_MASK 0x7
+#define AUX_DPHY_RX_STATUS__AUX_RX_STATE__SHIFT 0x0
+#define AUX_DPHY_RX_STATUS__AUX_RX_SYNC_VALID_COUNT_MASK 0x1f00
+#define AUX_DPHY_RX_STATUS__AUX_RX_SYNC_VALID_COUNT__SHIFT 0x8
+#define AUX_DPHY_RX_STATUS__AUX_RX_HALF_SYM_PERIOD_FRACT_MASK 0x1f0000
+#define AUX_DPHY_RX_STATUS__AUX_RX_HALF_SYM_PERIOD_FRACT__SHIFT 0x10
+#define AUX_DPHY_RX_STATUS__AUX_RX_HALF_SYM_PERIOD_MASK 0x3fe00000
+#define AUX_DPHY_RX_STATUS__AUX_RX_HALF_SYM_PERIOD__SHIFT 0x15
+#define AUX_GTC_SYNC_ERROR_CONTROL__AUX_GTC_POTENTIAL_ERROR_THRESHOLD_MASK 0x1f
+#define AUX_GTC_SYNC_ERROR_CONTROL__AUX_GTC_POTENTIAL_ERROR_THRESHOLD__SHIFT 0x0
+#define AUX_GTC_SYNC_ERROR_CONTROL__AUX_GTC_DEFINITE_ERROR_THRESHOLD_MASK 0x1f00
+#define AUX_GTC_SYNC_ERROR_CONTROL__AUX_GTC_DEFINITE_ERROR_THRESHOLD__SHIFT 0x8
+#define AUX_GTC_SYNC_ERROR_CONTROL__AUX_GTC_SYNC_LOCK_ACQ_TIMEOUT_LEN_MASK 0x30000
+#define AUX_GTC_SYNC_ERROR_CONTROL__AUX_GTC_SYNC_LOCK_ACQ_TIMEOUT_LEN__SHIFT 0x10
+#define AUX_GTC_SYNC_ERROR_CONTROL__AUX_GTC_SYNC_NUM_RETRY_FOR_LOCK_MAINT_MASK 0x300000
+#define AUX_GTC_SYNC_ERROR_CONTROL__AUX_GTC_SYNC_NUM_RETRY_FOR_LOCK_MAINT__SHIFT 0x14
+#define AUX_GTC_SYNC_CONTROLLER_STATUS__AUX_GTC_SYNC_LOCK_ACQ_COMPLETE_MASK 0x1
+#define AUX_GTC_SYNC_CONTROLLER_STATUS__AUX_GTC_SYNC_LOCK_ACQ_COMPLETE__SHIFT 0x0
+#define AUX_GTC_SYNC_CONTROLLER_STATUS__AUX_GTC_SYNC_LOCK_LOST_MASK 0x10
+#define AUX_GTC_SYNC_CONTROLLER_STATUS__AUX_GTC_SYNC_LOCK_LOST__SHIFT 0x4
+#define AUX_GTC_SYNC_CONTROLLER_STATUS__AUX_GTC_SYNC_LOCK_ACQ_TIMEOUT_OCCURRED_MASK 0x100
+#define AUX_GTC_SYNC_CONTROLLER_STATUS__AUX_GTC_SYNC_LOCK_ACQ_TIMEOUT_OCCURRED__SHIFT 0x8
+#define AUX_GTC_SYNC_CONTROLLER_STATUS__AUX_GTC_SYNC_LOCK_ACQ_TIMEOUT_STATE_MASK 0x1e00
+#define AUX_GTC_SYNC_CONTROLLER_STATUS__AUX_GTC_SYNC_LOCK_ACQ_TIMEOUT_STATE__SHIFT 0x9
+#define AUX_GTC_SYNC_CONTROLLER_STATUS__AUX_GTC_SYNC_PHASE_ADJUST_TIME_VIOL_MASK 0x10000
+#define AUX_GTC_SYNC_CONTROLLER_STATUS__AUX_GTC_SYNC_PHASE_ADJUST_TIME_VIOL__SHIFT 0x10
+#define AUX_GTC_SYNC_CONTROLLER_STATUS__AUX_GTC_SYNC_CRITICAL_ERR_OCCURRED_MASK 0x100000
+#define AUX_GTC_SYNC_CONTROLLER_STATUS__AUX_GTC_SYNC_CRITICAL_ERR_OCCURRED__SHIFT 0x14
+#define AUX_GTC_SYNC_CONTROLLER_STATUS__AUX_GTC_SYNC_CRITICAL_ERR_OCCURRED_ACK_MASK 0x200000
+#define AUX_GTC_SYNC_CONTROLLER_STATUS__AUX_GTC_SYNC_CRITICAL_ERR_OCCURRED_ACK__SHIFT 0x15
+#define AUX_GTC_SYNC_CONTROLLER_STATUS__AUX_GTC_SYNC_MAX_POTENTIAL_ERR_REACHED_MASK 0x400000
+#define AUX_GTC_SYNC_CONTROLLER_STATUS__AUX_GTC_SYNC_MAX_POTENTIAL_ERR_REACHED__SHIFT 0x16
+#define AUX_GTC_SYNC_CONTROLLER_STATUS__AUX_GTC_SYNC_MAX_POTENTIAL_ERR_REACHED_ACK_MASK 0x800000
+#define AUX_GTC_SYNC_CONTROLLER_STATUS__AUX_GTC_SYNC_MAX_POTENTIAL_ERR_REACHED_ACK__SHIFT 0x17
+#define AUX_GTC_SYNC_CONTROLLER_STATUS__AUX_GTC_SYNC_MAX_DEFINITE_ERR_REACHED_MASK 0x1000000
+#define AUX_GTC_SYNC_CONTROLLER_STATUS__AUX_GTC_SYNC_MAX_DEFINITE_ERR_REACHED__SHIFT 0x18
+#define AUX_GTC_SYNC_CONTROLLER_STATUS__AUX_GTC_SYNC_MAX_DEFINITE_ERR_REACHED_ACK_MASK 0x2000000
+#define AUX_GTC_SYNC_CONTROLLER_STATUS__AUX_GTC_SYNC_MAX_DEFINITE_ERR_REACHED_ACK__SHIFT 0x19
+#define AUX_GTC_SYNC_CONTROLLER_STATUS__AUX_GTC_SYNC_CTRL_STATE_MASK 0xf0000000
+#define AUX_GTC_SYNC_CONTROLLER_STATUS__AUX_GTC_SYNC_CTRL_STATE__SHIFT 0x1c
+#define AUX_GTC_SYNC_STATUS__AUX_GTC_SYNC_DONE_MASK 0x1
+#define AUX_GTC_SYNC_STATUS__AUX_GTC_SYNC_DONE__SHIFT 0x0
+#define AUX_GTC_SYNC_STATUS__AUX_GTC_SYNC_REQ_MASK 0x2
+#define AUX_GTC_SYNC_STATUS__AUX_GTC_SYNC_REQ__SHIFT 0x1
+#define AUX_GTC_SYNC_STATUS__AUX_GTC_SYNC_RX_TIMEOUT_STATE_MASK 0x70
+#define AUX_GTC_SYNC_STATUS__AUX_GTC_SYNC_RX_TIMEOUT_STATE__SHIFT 0x4
+#define AUX_GTC_SYNC_STATUS__AUX_GTC_SYNC_TIMEOUT_MASK 0x80
+#define AUX_GTC_SYNC_STATUS__AUX_GTC_SYNC_TIMEOUT__SHIFT 0x7
+#define AUX_GTC_SYNC_STATUS__AUX_GTC_SYNC_RX_OVERFLOW_MASK 0x100
+#define AUX_GTC_SYNC_STATUS__AUX_GTC_SYNC_RX_OVERFLOW__SHIFT 0x8
+#define AUX_GTC_SYNC_STATUS__AUX_GTC_SYNC_HPD_DISCON_MASK 0x200
+#define AUX_GTC_SYNC_STATUS__AUX_GTC_SYNC_HPD_DISCON__SHIFT 0x9
+#define AUX_GTC_SYNC_STATUS__AUX_GTC_SYNC_RX_PARTIAL_BYTE_MASK 0x400
+#define AUX_GTC_SYNC_STATUS__AUX_GTC_SYNC_RX_PARTIAL_BYTE__SHIFT 0xa
+#define AUX_GTC_SYNC_STATUS__AUX_GTC_SYNC_NON_AUX_MODE_MASK 0x800
+#define AUX_GTC_SYNC_STATUS__AUX_GTC_SYNC_NON_AUX_MODE__SHIFT 0xb
+#define AUX_GTC_SYNC_STATUS__AUX_GTC_SYNC_RX_MIN_COUNT_VIOL_MASK 0x1000
+#define AUX_GTC_SYNC_STATUS__AUX_GTC_SYNC_RX_MIN_COUNT_VIOL__SHIFT 0xc
+#define AUX_GTC_SYNC_STATUS__AUX_GTC_SYNC_RX_INVALID_STOP_MASK 0x4000
+#define AUX_GTC_SYNC_STATUS__AUX_GTC_SYNC_RX_INVALID_STOP__SHIFT 0xe
+#define AUX_GTC_SYNC_STATUS__AUX_GTC_SYNC_RX_SYNC_INVALID_L_MASK 0x20000
+#define AUX_GTC_SYNC_STATUS__AUX_GTC_SYNC_RX_SYNC_INVALID_L__SHIFT 0x11
+#define AUX_GTC_SYNC_STATUS__AUX_GTC_SYNC_RX_SYNC_INVALID_H_MASK 0x40000
+#define AUX_GTC_SYNC_STATUS__AUX_GTC_SYNC_RX_SYNC_INVALID_H__SHIFT 0x12
+#define AUX_GTC_SYNC_STATUS__AUX_GTC_SYNC_RX_INVALID_START_MASK 0x80000
+#define AUX_GTC_SYNC_STATUS__AUX_GTC_SYNC_RX_INVALID_START__SHIFT 0x13
+#define AUX_GTC_SYNC_STATUS__AUX_GTC_SYNC_RX_RECV_NO_DET_MASK 0x100000
+#define AUX_GTC_SYNC_STATUS__AUX_GTC_SYNC_RX_RECV_NO_DET__SHIFT 0x14
+#define AUX_GTC_SYNC_STATUS__AUX_GTC_SYNC_RX_RECV_INVALID_H_MASK 0x400000
+#define AUX_GTC_SYNC_STATUS__AUX_GTC_SYNC_RX_RECV_INVALID_H__SHIFT 0x16
+#define AUX_GTC_SYNC_STATUS__AUX_GTC_SYNC_RX_RECV_INVALID_L_MASK 0x800000
+#define AUX_GTC_SYNC_STATUS__AUX_GTC_SYNC_RX_RECV_INVALID_L__SHIFT 0x17
+#define AUX_GTC_SYNC_STATUS__AUX_GTC_SYNC_REPLY_BYTE_COUNT_MASK 0x1f000000
+#define AUX_GTC_SYNC_STATUS__AUX_GTC_SYNC_REPLY_BYTE_COUNT__SHIFT 0x18
+#define AUX_GTC_SYNC_STATUS__AUX_GTC_SYNC_NACKED_MASK 0x20000000
+#define AUX_GTC_SYNC_STATUS__AUX_GTC_SYNC_NACKED__SHIFT 0x1d
+#define AUX_GTC_SYNC_STATUS__AUX_GTC_MASTER_REQ_BY_RX_MASK 0x40000000
+#define AUX_GTC_SYNC_STATUS__AUX_GTC_MASTER_REQ_BY_RX__SHIFT 0x1e
+#define AUX_TEST_DEBUG_INDEX__AUX_TEST_DEBUG_INDEX_MASK 0xff
+#define AUX_TEST_DEBUG_INDEX__AUX_TEST_DEBUG_INDEX__SHIFT 0x0
+#define AUX_TEST_DEBUG_INDEX__AUX_TEST_DEBUG_WRITE_EN_MASK 0x100
+#define AUX_TEST_DEBUG_INDEX__AUX_TEST_DEBUG_WRITE_EN__SHIFT 0x8
+#define AUX_TEST_DEBUG_DATA__AUX_TEST_DEBUG_DATA_MASK 0xffffffff
+#define AUX_TEST_DEBUG_DATA__AUX_TEST_DEBUG_DATA__SHIFT 0x0
+#define DP_AUX_DEBUG_A__DP_AUX_DEBUG_A_MASK 0xffffffff
+#define DP_AUX_DEBUG_A__DP_AUX_DEBUG_A__SHIFT 0x0
+#define DP_AUX_DEBUG_B__DP_AUX_DEBUG_B_MASK 0xffffffff
+#define DP_AUX_DEBUG_B__DP_AUX_DEBUG_B__SHIFT 0x0
+#define DP_AUX_DEBUG_C__DP_AUX_DEBUG_C_MASK 0xffffffff
+#define DP_AUX_DEBUG_C__DP_AUX_DEBUG_C__SHIFT 0x0
+#define DP_AUX_DEBUG_D__DP_AUX_DEBUG_D_MASK 0xffffffff
+#define DP_AUX_DEBUG_D__DP_AUX_DEBUG_D__SHIFT 0x0
+#define DP_AUX_DEBUG_E__DP_AUX_DEBUG_E_MASK 0xffffffff
+#define DP_AUX_DEBUG_E__DP_AUX_DEBUG_E__SHIFT 0x0
+#define DP_AUX_DEBUG_F__DP_AUX_DEBUG_F_MASK 0xffffffff
+#define DP_AUX_DEBUG_F__DP_AUX_DEBUG_F__SHIFT 0x0
+#define DP_AUX_DEBUG_G__DP_AUX_DEBUG_G_MASK 0xffffffff
+#define DP_AUX_DEBUG_G__DP_AUX_DEBUG_G__SHIFT 0x0
+#define DP_AUX_DEBUG_H__DP_AUX_DEBUG_H_MASK 0xffffffff
+#define DP_AUX_DEBUG_H__DP_AUX_DEBUG_H__SHIFT 0x0
+#define DP_AUX_DEBUG_I__DP_AUX_DEBUG_I_MASK 0xffffffff
+#define DP_AUX_DEBUG_I__DP_AUX_DEBUG_I__SHIFT 0x0
+#define DP_AUX_DEBUG_J__DP_AUX_DEBUG_J_MASK 0xffffffff
+#define DP_AUX_DEBUG_J__DP_AUX_DEBUG_J__SHIFT 0x0
+#define DP_AUX_DEBUG_K__DP_AUX_DEBUG_K_MASK 0xffffffff
+#define DP_AUX_DEBUG_K__DP_AUX_DEBUG_K__SHIFT 0x0
+#define DP_AUX_DEBUG_L__DP_AUX_DEBUG_L_MASK 0xffffffff
+#define DP_AUX_DEBUG_L__DP_AUX_DEBUG_L__SHIFT 0x0
+#define DP_AUX_DEBUG_M__DP_AUX_DEBUG_M_MASK 0xffffffff
+#define DP_AUX_DEBUG_M__DP_AUX_DEBUG_M__SHIFT 0x0
+#define DP_AUX_DEBUG_N__DP_AUX_DEBUG_N_MASK 0xffffffff
+#define DP_AUX_DEBUG_N__DP_AUX_DEBUG_N__SHIFT 0x0
+#define DP_AUX_DEBUG_O__DP_AUX_DEBUG_O_MASK 0xffffffff
+#define DP_AUX_DEBUG_O__DP_AUX_DEBUG_O__SHIFT 0x0
+#define DP_AUX_DEBUG_P__DP_AUX_DEBUG_P_MASK 0xffffffff
+#define DP_AUX_DEBUG_P__DP_AUX_DEBUG_P__SHIFT 0x0
+#define DP_AUX_DEBUG_Q__DP_AUX_DEBUG_Q_MASK 0xffffffff
+#define DP_AUX_DEBUG_Q__DP_AUX_DEBUG_Q__SHIFT 0x0
+#define DVO_ENABLE__DVO_ENABLE_MASK 0x1
+#define DVO_ENABLE__DVO_ENABLE__SHIFT 0x0
+#define DVO_ENABLE__DVO_PIXEL_WIDTH_MASK 0x30
+#define DVO_ENABLE__DVO_PIXEL_WIDTH__SHIFT 0x4
+#define DVO_SOURCE_SELECT__DVO_SOURCE_SELECT_MASK 0x7
+#define DVO_SOURCE_SELECT__DVO_SOURCE_SELECT__SHIFT 0x0
+#define DVO_SOURCE_SELECT__DVO_STEREOSYNC_SELECT_MASK 0x70000
+#define DVO_SOURCE_SELECT__DVO_STEREOSYNC_SELECT__SHIFT 0x10
+#define DVO_OUTPUT__DVO_OUTPUT_ENABLE_MODE_MASK 0x3
+#define DVO_OUTPUT__DVO_OUTPUT_ENABLE_MODE__SHIFT 0x0
+#define DVO_OUTPUT__DVO_CLOCK_MODE_MASK 0x100
+#define DVO_OUTPUT__DVO_CLOCK_MODE__SHIFT 0x8
+#define DVO_CONTROL__DVO_RATE_SELECT_MASK 0x1
+#define DVO_CONTROL__DVO_RATE_SELECT__SHIFT 0x0
+#define DVO_CONTROL__DVO_SDRCLK_SEL_MASK 0x2
+#define DVO_CONTROL__DVO_SDRCLK_SEL__SHIFT 0x1
+#define DVO_CONTROL__DVO_DVPDATA_WIDTH_MASK 0x30
+#define DVO_CONTROL__DVO_DVPDATA_WIDTH__SHIFT 0x4
+#define DVO_CONTROL__DVO_DUAL_CHANNEL_EN_MASK 0x100
+#define DVO_CONTROL__DVO_DUAL_CHANNEL_EN__SHIFT 0x8
+#define DVO_CONTROL__DVO_RESET_FIFO_MASK 0x10000
+#define DVO_CONTROL__DVO_RESET_FIFO__SHIFT 0x10
+#define DVO_CONTROL__DVO_SYNC_PHASE_MASK 0x20000
+#define DVO_CONTROL__DVO_SYNC_PHASE__SHIFT 0x11
+#define DVO_CONTROL__DVO_INVERT_DVOCLK_MASK 0x40000
+#define DVO_CONTROL__DVO_INVERT_DVOCLK__SHIFT 0x12
+#define DVO_CONTROL__DVO_HSYNC_POLARITY_MASK 0x100000
+#define DVO_CONTROL__DVO_HSYNC_POLARITY__SHIFT 0x14
+#define DVO_CONTROL__DVO_VSYNC_POLARITY_MASK 0x200000
+#define DVO_CONTROL__DVO_VSYNC_POLARITY__SHIFT 0x15
+#define DVO_CONTROL__DVO_DE_POLARITY_MASK 0x400000
+#define DVO_CONTROL__DVO_DE_POLARITY__SHIFT 0x16
+#define DVO_CONTROL__DVO_COLOR_FORMAT_MASK 0x3000000
+#define DVO_CONTROL__DVO_COLOR_FORMAT__SHIFT 0x18
+#define DVO_CONTROL__DVO_CTL3_MASK 0x80000000
+#define DVO_CONTROL__DVO_CTL3__SHIFT 0x1f
+#define DVO_CRC_EN__DVO_CRC2_EN_MASK 0x10000
+#define DVO_CRC_EN__DVO_CRC2_EN__SHIFT 0x10
+#define DVO_CRC2_SIG_MASK__DVO_CRC2_SIG_MASK_MASK 0x7ffffff
+#define DVO_CRC2_SIG_MASK__DVO_CRC2_SIG_MASK__SHIFT 0x0
+#define DVO_CRC2_SIG_RESULT__DVO_CRC2_SIG_RESULT_MASK 0x7ffffff
+#define DVO_CRC2_SIG_RESULT__DVO_CRC2_SIG_RESULT__SHIFT 0x0
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_LEVEL_ERROR_MASK 0x1
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_LEVEL_ERROR__SHIFT 0x0
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_USE_OVERWRITE_LEVEL_MASK 0x2
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_USE_OVERWRITE_LEVEL__SHIFT 0x1
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_OVERWRITE_LEVEL_MASK 0xfc
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_OVERWRITE_LEVEL__SHIFT 0x2
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_ERROR_ACK_MASK 0x100
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_ERROR_ACK__SHIFT 0x8
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_CAL_AVERAGE_LEVEL_MASK 0xfc00
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_CAL_AVERAGE_LEVEL__SHIFT 0xa
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_MAXIMUM_LEVEL_MASK 0xf0000
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_MAXIMUM_LEVEL__SHIFT 0x10
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_MINIMUM_LEVEL_MASK 0x3c00000
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_MINIMUM_LEVEL__SHIFT 0x16
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_CALIBRATED_MASK 0x20000000
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_CALIBRATED__SHIFT 0x1d
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_FORCE_RECAL_AVERAGE_MASK 0x40000000
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_FORCE_RECAL_AVERAGE__SHIFT 0x1e
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_FORCE_RECOMP_MINMAX_MASK 0x80000000
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_FORCE_RECOMP_MINMAX__SHIFT 0x1f
+#define DVO_TEST_DEBUG_INDEX__DVO_TEST_DEBUG_INDEX_MASK 0xff
+#define DVO_TEST_DEBUG_INDEX__DVO_TEST_DEBUG_INDEX__SHIFT 0x0
+#define DVO_TEST_DEBUG_INDEX__DVO_TEST_DEBUG_WRITE_EN_MASK 0x100
+#define DVO_TEST_DEBUG_INDEX__DVO_TEST_DEBUG_WRITE_EN__SHIFT 0x8
+#define DVO_TEST_DEBUG_DATA__DVO_TEST_DEBUG_DATA_MASK 0xffffffff
+#define DVO_TEST_DEBUG_DATA__DVO_TEST_DEBUG_DATA__SHIFT 0x0
+#define FBC_CNTL__FBC_GRPH_COMP_EN_MASK 0x1
+#define FBC_CNTL__FBC_GRPH_COMP_EN__SHIFT 0x0
+#define FBC_CNTL__FBC_SRC_SEL_MASK 0xe
+#define FBC_CNTL__FBC_SRC_SEL__SHIFT 0x1
+#define FBC_CNTL__FBC_COMP_CLK_GATE_EN_MASK 0x100
+#define FBC_CNTL__FBC_COMP_CLK_GATE_EN__SHIFT 0x8
+#define FBC_CNTL__FBC_DECOMP_CLK_GATE_EN_MASK 0x400
+#define FBC_CNTL__FBC_DECOMP_CLK_GATE_EN__SHIFT 0xa
+#define FBC_CNTL__FBC_COHERENCY_MODE_MASK 0x30000
+#define FBC_CNTL__FBC_COHERENCY_MODE__SHIFT 0x10
+#define FBC_CNTL__FBC_SOFT_COMPRESS_EN_MASK 0x2000000
+#define FBC_CNTL__FBC_SOFT_COMPRESS_EN__SHIFT 0x19
+#define FBC_CNTL__FBC_EN_MASK 0x80000000
+#define FBC_CNTL__FBC_EN__SHIFT 0x1f
+#define FBC_IDLE_FORCE_CLEAR_MASK__FBC_IDLE_FORCE_CLEAR_MASK_MASK 0xffffffff
+#define FBC_IDLE_FORCE_CLEAR_MASK__FBC_IDLE_FORCE_CLEAR_MASK__SHIFT 0x0
+#define FBC_START_STOP_DELAY__FBC_DECOMP_START_DELAY_MASK 0x1f
+#define FBC_START_STOP_DELAY__FBC_DECOMP_START_DELAY__SHIFT 0x0
+#define FBC_START_STOP_DELAY__FBC_DECOMP_STOP_DELAY_MASK 0x80
+#define FBC_START_STOP_DELAY__FBC_DECOMP_STOP_DELAY__SHIFT 0x7
+#define FBC_START_STOP_DELAY__FBC_COMP_START_DELAY_MASK 0x1f00
+#define FBC_START_STOP_DELAY__FBC_COMP_START_DELAY__SHIFT 0x8
+#define FBC_COMP_CNTL__FBC_MIN_COMPRESSION_MASK 0xf
+#define FBC_COMP_CNTL__FBC_MIN_COMPRESSION__SHIFT 0x0
+#define FBC_COMP_CNTL__FBC_DEPTH_MONO08_EN_MASK 0x10000
+#define FBC_COMP_CNTL__FBC_DEPTH_MONO08_EN__SHIFT 0x10
+#define FBC_COMP_CNTL__FBC_DEPTH_MONO16_EN_MASK 0x20000
+#define FBC_COMP_CNTL__FBC_DEPTH_MONO16_EN__SHIFT 0x11
+#define FBC_COMP_CNTL__FBC_DEPTH_RGB04_EN_MASK 0x40000
+#define FBC_COMP_CNTL__FBC_DEPTH_RGB04_EN__SHIFT 0x12
+#define FBC_COMP_CNTL__FBC_DEPTH_RGB08_EN_MASK 0x80000
+#define FBC_COMP_CNTL__FBC_DEPTH_RGB08_EN__SHIFT 0x13
+#define FBC_COMP_CNTL__FBC_DEPTH_RGB16_EN_MASK 0x100000
+#define FBC_COMP_CNTL__FBC_DEPTH_RGB16_EN__SHIFT 0x14
+#define FBC_COMP_MODE__FBC_RLE_EN_MASK 0x1
+#define FBC_COMP_MODE__FBC_RLE_EN__SHIFT 0x0
+#define FBC_COMP_MODE__FBC_DPCM4_RGB_EN_MASK 0x100
+#define FBC_COMP_MODE__FBC_DPCM4_RGB_EN__SHIFT 0x8
+#define FBC_COMP_MODE__FBC_DPCM8_RGB_EN_MASK 0x200
+#define FBC_COMP_MODE__FBC_DPCM8_RGB_EN__SHIFT 0x9
+#define FBC_COMP_MODE__FBC_DPCM4_YUV_EN_MASK 0x400
+#define FBC_COMP_MODE__FBC_DPCM4_YUV_EN__SHIFT 0xa
+#define FBC_COMP_MODE__FBC_DPCM8_YUV_EN_MASK 0x800
+#define FBC_COMP_MODE__FBC_DPCM8_YUV_EN__SHIFT 0xb
+#define FBC_COMP_MODE__FBC_IND_EN_MASK 0x10000
+#define FBC_COMP_MODE__FBC_IND_EN__SHIFT 0x10
+#define FBC_DEBUG0__FBC_PERF_MUX0_MASK 0xff
+#define FBC_DEBUG0__FBC_PERF_MUX0__SHIFT 0x0
+#define FBC_DEBUG0__FBC_PERF_MUX1_MASK 0xff00
+#define FBC_DEBUG0__FBC_PERF_MUX1__SHIFT 0x8
+#define FBC_DEBUG0__FBC_COMP_WAKE_DIS_MASK 0x10000
+#define FBC_DEBUG0__FBC_COMP_WAKE_DIS__SHIFT 0x10
+#define FBC_DEBUG0__FBC_DEBUG0_MASK 0xfe0000
+#define FBC_DEBUG0__FBC_DEBUG0__SHIFT 0x11
+#define FBC_DEBUG0__FBC_DEBUG_MUX_MASK 0xff000000
+#define FBC_DEBUG0__FBC_DEBUG_MUX__SHIFT 0x18
+#define FBC_DEBUG1__FBC_DEBUG1_MASK 0xffffffff
+#define FBC_DEBUG1__FBC_DEBUG1__SHIFT 0x0
+#define FBC_DEBUG2__FBC_DEBUG2_MASK 0xffffffff
+#define FBC_DEBUG2__FBC_DEBUG2__SHIFT 0x0
+#define FBC_IND_LUT0__FBC_IND_LUT0_MASK 0xffffffff
+#define FBC_IND_LUT0__FBC_IND_LUT0__SHIFT 0x0
+#define FBC_IND_LUT1__FBC_IND_LUT1_MASK 0xffffffff
+#define FBC_IND_LUT1__FBC_IND_LUT1__SHIFT 0x0
+#define FBC_IND_LUT2__FBC_IND_LUT2_MASK 0xffffffff
+#define FBC_IND_LUT2__FBC_IND_LUT2__SHIFT 0x0
+#define FBC_IND_LUT3__FBC_IND_LUT3_MASK 0xffffffff
+#define FBC_IND_LUT3__FBC_IND_LUT3__SHIFT 0x0
+#define FBC_IND_LUT4__FBC_IND_LUT4_MASK 0xffffffff
+#define FBC_IND_LUT4__FBC_IND_LUT4__SHIFT 0x0
+#define FBC_IND_LUT5__FBC_IND_LUT5_MASK 0xffffffff
+#define FBC_IND_LUT5__FBC_IND_LUT5__SHIFT 0x0
+#define FBC_IND_LUT6__FBC_IND_LUT6_MASK 0xffffffff
+#define FBC_IND_LUT6__FBC_IND_LUT6__SHIFT 0x0
+#define FBC_IND_LUT7__FBC_IND_LUT7_MASK 0xffffffff
+#define FBC_IND_LUT7__FBC_IND_LUT7__SHIFT 0x0
+#define FBC_IND_LUT8__FBC_IND_LUT8_MASK 0xffffffff
+#define FBC_IND_LUT8__FBC_IND_LUT8__SHIFT 0x0
+#define FBC_IND_LUT9__FBC_IND_LUT9_MASK 0xffffffff
+#define FBC_IND_LUT9__FBC_IND_LUT9__SHIFT 0x0
+#define FBC_IND_LUT10__FBC_IND_LUT10_MASK 0xffffffff
+#define FBC_IND_LUT10__FBC_IND_LUT10__SHIFT 0x0
+#define FBC_IND_LUT11__FBC_IND_LUT11_MASK 0xffffffff
+#define FBC_IND_LUT11__FBC_IND_LUT11__SHIFT 0x0
+#define FBC_IND_LUT12__FBC_IND_LUT12_MASK 0xffffffff
+#define FBC_IND_LUT12__FBC_IND_LUT12__SHIFT 0x0
+#define FBC_IND_LUT13__FBC_IND_LUT13_MASK 0xffffffff
+#define FBC_IND_LUT13__FBC_IND_LUT13__SHIFT 0x0
+#define FBC_IND_LUT14__FBC_IND_LUT14_MASK 0xffffffff
+#define FBC_IND_LUT14__FBC_IND_LUT14__SHIFT 0x0
+#define FBC_IND_LUT15__FBC_IND_LUT15_MASK 0xffffffff
+#define FBC_IND_LUT15__FBC_IND_LUT15__SHIFT 0x0
+#define FBC_CSM_REGION_OFFSET_01__FBC_CSM_REGION_OFFSET_0_MASK 0xfff
+#define FBC_CSM_REGION_OFFSET_01__FBC_CSM_REGION_OFFSET_0__SHIFT 0x0
+#define FBC_CSM_REGION_OFFSET_01__FBC_CSM_REGION_OFFSET_1_MASK 0xfff0000
+#define FBC_CSM_REGION_OFFSET_01__FBC_CSM_REGION_OFFSET_1__SHIFT 0x10
+#define FBC_CSM_REGION_OFFSET_23__FBC_CSM_REGION_OFFSET_2_MASK 0xfff
+#define FBC_CSM_REGION_OFFSET_23__FBC_CSM_REGION_OFFSET_2__SHIFT 0x0
+#define FBC_CSM_REGION_OFFSET_23__FBC_CSM_REGION_OFFSET_3_MASK 0xfff0000
+#define FBC_CSM_REGION_OFFSET_23__FBC_CSM_REGION_OFFSET_3__SHIFT 0x10
+#define FBC_CLIENT_REGION_MASK__FBC_MEMORY_REGION_MASK_MASK 0xf0000
+#define FBC_CLIENT_REGION_MASK__FBC_MEMORY_REGION_MASK__SHIFT 0x10
+#define FBC_DEBUG_COMP__FBC_COMP_SWAP_MASK 0x3
+#define FBC_DEBUG_COMP__FBC_COMP_SWAP__SHIFT 0x0
+#define FBC_DEBUG_COMP__FBC_COMP_RSIZE_MASK 0x8
+#define FBC_DEBUG_COMP__FBC_COMP_RSIZE__SHIFT 0x3
+#define FBC_DEBUG_COMP__FBC_COMP_BUSY_HYSTERESIS_MASK 0xf0
+#define FBC_DEBUG_COMP__FBC_COMP_BUSY_HYSTERESIS__SHIFT 0x4
+#define FBC_DEBUG_COMP__FBC_COMP_CLK_CNTL_MASK 0x300
+#define FBC_DEBUG_COMP__FBC_COMP_CLK_CNTL__SHIFT 0x8
+#define FBC_DEBUG_COMP__FBC_COMP_PRIVILEGED_ACCESS_ENABLE_MASK 0x400
+#define FBC_DEBUG_COMP__FBC_COMP_PRIVILEGED_ACCESS_ENABLE__SHIFT 0xa
+#define FBC_DEBUG_COMP__FBC_COMP_ADDRESS_TRANSLATION_ENABLE_MASK 0x800
+#define FBC_DEBUG_COMP__FBC_COMP_ADDRESS_TRANSLATION_ENABLE__SHIFT 0xb
+#define FBC_DEBUG_CSR__FBC_DEBUG_CSR_ADDR_MASK 0xfff
+#define FBC_DEBUG_CSR__FBC_DEBUG_CSR_ADDR__SHIFT 0x0
+#define FBC_DEBUG_CSR__FBC_DEBUG_CSR_WR_DATA_MASK 0x10000
+#define FBC_DEBUG_CSR__FBC_DEBUG_CSR_WR_DATA__SHIFT 0x10
+#define FBC_DEBUG_CSR__FBC_DEBUG_CSR_RD_DATA_MASK 0x20000
+#define FBC_DEBUG_CSR__FBC_DEBUG_CSR_RD_DATA__SHIFT 0x11
+#define FBC_DEBUG_CSR__FBC_DEBUG_CSR_EN_MASK 0x80000000
+#define FBC_DEBUG_CSR__FBC_DEBUG_CSR_EN__SHIFT 0x1f
+#define FBC_DEBUG_CSR_RDATA__FBC_DEBUG_CSR_RDATA_MASK 0xffffffff
+#define FBC_DEBUG_CSR_RDATA__FBC_DEBUG_CSR_RDATA__SHIFT 0x0
+#define FBC_DEBUG_CSR_WDATA__FBC_DEBUG_CSR_WDATA_MASK 0xffffffff
+#define FBC_DEBUG_CSR_WDATA__FBC_DEBUG_CSR_WDATA__SHIFT 0x0
+#define FBC_DEBUG_CSR_RDATA_HI__FBC_DEBUG_CSR_RDATA_HI_MASK 0xff
+#define FBC_DEBUG_CSR_RDATA_HI__FBC_DEBUG_CSR_RDATA_HI__SHIFT 0x0
+#define FBC_DEBUG_CSR_WDATA_HI__FBC_DEBUG_CSR_WDATA_HI_MASK 0xff
+#define FBC_DEBUG_CSR_WDATA_HI__FBC_DEBUG_CSR_WDATA_HI__SHIFT 0x0
+#define FBC_MISC__FBC_DECOMPRESS_ERROR_MASK 0x3
+#define FBC_MISC__FBC_DECOMPRESS_ERROR__SHIFT 0x0
+#define FBC_MISC__FBC_STOP_ON_ERROR_MASK 0x4
+#define FBC_MISC__FBC_STOP_ON_ERROR__SHIFT 0x2
+#define FBC_MISC__FBC_INVALIDATE_ON_ERROR_MASK 0x8
+#define FBC_MISC__FBC_INVALIDATE_ON_ERROR__SHIFT 0x3
+#define FBC_MISC__FBC_ERROR_PIXEL_MASK 0xf0
+#define FBC_MISC__FBC_ERROR_PIXEL__SHIFT 0x4
+#define FBC_MISC__FBC_DIVIDE_X_MASK 0x300
+#define FBC_MISC__FBC_DIVIDE_X__SHIFT 0x8
+#define FBC_MISC__FBC_DIVIDE_Y_MASK 0x400
+#define FBC_MISC__FBC_DIVIDE_Y__SHIFT 0xa
+#define FBC_MISC__FBC_RSM_WRITE_VALUE_MASK 0x800
+#define FBC_MISC__FBC_RSM_WRITE_VALUE__SHIFT 0xb
+#define FBC_MISC__FBC_RSM_UNCOMP_DATA_IMMEDIATELY_MASK 0x1000
+#define FBC_MISC__FBC_RSM_UNCOMP_DATA_IMMEDIATELY__SHIFT 0xc
+#define FBC_MISC__FBC_STOP_ON_HFLIP_EVENT_MASK 0x2000
+#define FBC_MISC__FBC_STOP_ON_HFLIP_EVENT__SHIFT 0xd
+#define FBC_MISC__FBC_DECOMPRESS_ERROR_CLEAR_MASK 0x10000
+#define FBC_MISC__FBC_DECOMPRESS_ERROR_CLEAR__SHIFT 0x10
+#define FBC_MISC__FBC_RESET_AT_ENABLE_MASK 0x100000
+#define FBC_MISC__FBC_RESET_AT_ENABLE__SHIFT 0x14
+#define FBC_MISC__FBC_RESET_AT_DISABLE_MASK 0x200000
+#define FBC_MISC__FBC_RESET_AT_DISABLE__SHIFT 0x15
+#define FBC_MISC__FBC_SLOW_REQ_INTERVAL_MASK 0x1f000000
+#define FBC_MISC__FBC_SLOW_REQ_INTERVAL__SHIFT 0x18
+#define FBC_MISC__FBC_FORCE_DECOMPRESSOR_EN_MASK 0x80000000
+#define FBC_MISC__FBC_FORCE_DECOMPRESSOR_EN__SHIFT 0x1f
+#define FBC_STATUS__FBC_ENABLE_STATUS_MASK 0x1
+#define FBC_STATUS__FBC_ENABLE_STATUS__SHIFT 0x0
+#define FBC_ALPHA_CNTL__FBC_ALPHA_COMP_EN_MASK 0x1
+#define FBC_ALPHA_CNTL__FBC_ALPHA_COMP_EN__SHIFT 0x0
+#define FBC_ALPHA_CNTL__FBC_FORCE_COPY_TO_COMP_BUF_MASK 0x10
+#define FBC_ALPHA_CNTL__FBC_FORCE_COPY_TO_COMP_BUF__SHIFT 0x4
+#define FBC_ALPHA_CNTL__FBC_ZERO_ALPHA_CHUNK_SKIP_EN_MASK 0x100
+#define FBC_ALPHA_CNTL__FBC_ZERO_ALPHA_CHUNK_SKIP_EN__SHIFT 0x8
+#define FBC_ALPHA_RGB_OVERRIDE__FBC_ZERO_ALPHA_R_VAL_MASK 0xff
+#define FBC_ALPHA_RGB_OVERRIDE__FBC_ZERO_ALPHA_R_VAL__SHIFT 0x0
+#define FBC_ALPHA_RGB_OVERRIDE__FBC_ZERO_ALPHA_G_VAL_MASK 0xff000
+#define FBC_ALPHA_RGB_OVERRIDE__FBC_ZERO_ALPHA_G_VAL__SHIFT 0xc
+#define FBC_ALPHA_RGB_OVERRIDE__FBC_ZERO_ALPHA_B_VAL_MASK 0xff000000
+#define FBC_ALPHA_RGB_OVERRIDE__FBC_ZERO_ALPHA_B_VAL__SHIFT 0x18
+#define FBC_TEST_DEBUG_INDEX__FBC_TEST_DEBUG_INDEX_MASK 0xff
+#define FBC_TEST_DEBUG_INDEX__FBC_TEST_DEBUG_INDEX__SHIFT 0x0
+#define FBC_TEST_DEBUG_INDEX__FBC_TEST_DEBUG_WRITE_EN_MASK 0x100
+#define FBC_TEST_DEBUG_INDEX__FBC_TEST_DEBUG_WRITE_EN__SHIFT 0x8
+#define FBC_TEST_DEBUG_DATA__FBC_TEST_DEBUG_DATA_MASK 0xffffffff
+#define FBC_TEST_DEBUG_DATA__FBC_TEST_DEBUG_DATA__SHIFT 0x0
+#define FMT_CLAMP_COMPONENT_R__FMT_CLAMP_LOWER_R_MASK 0xffff
+#define FMT_CLAMP_COMPONENT_R__FMT_CLAMP_LOWER_R__SHIFT 0x0
+#define FMT_CLAMP_COMPONENT_R__FMT_CLAMP_UPPER_R_MASK 0xffff0000
+#define FMT_CLAMP_COMPONENT_R__FMT_CLAMP_UPPER_R__SHIFT 0x10
+#define FMT_CLAMP_COMPONENT_G__FMT_CLAMP_LOWER_G_MASK 0xffff
+#define FMT_CLAMP_COMPONENT_G__FMT_CLAMP_LOWER_G__SHIFT 0x0
+#define FMT_CLAMP_COMPONENT_G__FMT_CLAMP_UPPER_G_MASK 0xffff0000
+#define FMT_CLAMP_COMPONENT_G__FMT_CLAMP_UPPER_G__SHIFT 0x10
+#define FMT_CLAMP_COMPONENT_B__FMT_CLAMP_LOWER_B_MASK 0xffff
+#define FMT_CLAMP_COMPONENT_B__FMT_CLAMP_LOWER_B__SHIFT 0x0
+#define FMT_CLAMP_COMPONENT_B__FMT_CLAMP_UPPER_B_MASK 0xffff0000
+#define FMT_CLAMP_COMPONENT_B__FMT_CLAMP_UPPER_B__SHIFT 0x10
+#define FMT_DYNAMIC_EXP_CNTL__FMT_DYNAMIC_EXP_EN_MASK 0x1
+#define FMT_DYNAMIC_EXP_CNTL__FMT_DYNAMIC_EXP_EN__SHIFT 0x0
+#define FMT_DYNAMIC_EXP_CNTL__FMT_DYNAMIC_EXP_MODE_MASK 0x10
+#define FMT_DYNAMIC_EXP_CNTL__FMT_DYNAMIC_EXP_MODE__SHIFT 0x4
+#define FMT_CONTROL__FMT_STEREOSYNC_OVERRIDE_MASK 0x1
+#define FMT_CONTROL__FMT_STEREOSYNC_OVERRIDE__SHIFT 0x0
+#define FMT_CONTROL__FMT_STEREOSYNC_OVR_POL_MASK 0x10
+#define FMT_CONTROL__FMT_STEREOSYNC_OVR_POL__SHIFT 0x4
+#define FMT_CONTROL__FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX_MASK 0xf00
+#define FMT_CONTROL__FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX__SHIFT 0x8
+#define FMT_CONTROL__FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP_MASK 0x3000
+#define FMT_CONTROL__FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP__SHIFT 0xc
+#define FMT_CONTROL__FMT_PIXEL_ENCODING_MASK 0x30000
+#define FMT_CONTROL__FMT_PIXEL_ENCODING__SHIFT 0x10
+#define FMT_CONTROL__FMT_SUBSAMPLING_MODE_MASK 0xc0000
+#define FMT_CONTROL__FMT_SUBSAMPLING_MODE__SHIFT 0x12
+#define FMT_CONTROL__FMT_SUBSAMPLING_ORDER_MASK 0x100000
+#define FMT_CONTROL__FMT_SUBSAMPLING_ORDER__SHIFT 0x14
+#define FMT_CONTROL__FMT_CBCR_BIT_REDUCTION_BYPASS_MASK 0x200000
+#define FMT_CONTROL__FMT_CBCR_BIT_REDUCTION_BYPASS__SHIFT 0x15
+#define FMT_CONTROL__FMT_SRC_SELECT_MASK 0x7000000
+#define FMT_CONTROL__FMT_SRC_SELECT__SHIFT 0x18
+#define FMT_CONTROL__FMT_420_PIXEL_PHASE_LOCKED_MASK 0x40000000
+#define FMT_CONTROL__FMT_420_PIXEL_PHASE_LOCKED__SHIFT 0x1e
+#define FMT_CONTROL__FMT_420_PIXEL_PHASE_LOCKED_CLEAR_MASK 0x80000000
+#define FMT_CONTROL__FMT_420_PIXEL_PHASE_LOCKED_CLEAR__SHIFT 0x1f
+#define FMT_BIT_DEPTH_CONTROL__FMT_TRUNCATE_EN_MASK 0x1
+#define FMT_BIT_DEPTH_CONTROL__FMT_TRUNCATE_EN__SHIFT 0x0
+#define FMT_BIT_DEPTH_CONTROL__FMT_TRUNCATE_MODE_MASK 0x2
+#define FMT_BIT_DEPTH_CONTROL__FMT_TRUNCATE_MODE__SHIFT 0x1
+#define FMT_BIT_DEPTH_CONTROL__FMT_TRUNCATE_DEPTH_MASK 0x30
+#define FMT_BIT_DEPTH_CONTROL__FMT_TRUNCATE_DEPTH__SHIFT 0x4
+#define FMT_BIT_DEPTH_CONTROL__FMT_SPATIAL_DITHER_EN_MASK 0x100
+#define FMT_BIT_DEPTH_CONTROL__FMT_SPATIAL_DITHER_EN__SHIFT 0x8
+#define FMT_BIT_DEPTH_CONTROL__FMT_SPATIAL_DITHER_MODE_MASK 0x600
+#define FMT_BIT_DEPTH_CONTROL__FMT_SPATIAL_DITHER_MODE__SHIFT 0x9
+#define FMT_BIT_DEPTH_CONTROL__FMT_SPATIAL_DITHER_DEPTH_MASK 0x1800
+#define FMT_BIT_DEPTH_CONTROL__FMT_SPATIAL_DITHER_DEPTH__SHIFT 0xb
+#define FMT_BIT_DEPTH_CONTROL__FMT_FRAME_RANDOM_ENABLE_MASK 0x2000
+#define FMT_BIT_DEPTH_CONTROL__FMT_FRAME_RANDOM_ENABLE__SHIFT 0xd
+#define FMT_BIT_DEPTH_CONTROL__FMT_RGB_RANDOM_ENABLE_MASK 0x4000
+#define FMT_BIT_DEPTH_CONTROL__FMT_RGB_RANDOM_ENABLE__SHIFT 0xe
+#define FMT_BIT_DEPTH_CONTROL__FMT_HIGHPASS_RANDOM_ENABLE_MASK 0x8000
+#define FMT_BIT_DEPTH_CONTROL__FMT_HIGHPASS_RANDOM_ENABLE__SHIFT 0xf
+#define FMT_BIT_DEPTH_CONTROL__FMT_TEMPORAL_DITHER_EN_MASK 0x10000
+#define FMT_BIT_DEPTH_CONTROL__FMT_TEMPORAL_DITHER_EN__SHIFT 0x10
+#define FMT_BIT_DEPTH_CONTROL__FMT_TEMPORAL_DITHER_DEPTH_MASK 0x60000
+#define FMT_BIT_DEPTH_CONTROL__FMT_TEMPORAL_DITHER_DEPTH__SHIFT 0x11
+#define FMT_BIT_DEPTH_CONTROL__FMT_TEMPORAL_DITHER_OFFSET_MASK 0x600000
+#define FMT_BIT_DEPTH_CONTROL__FMT_TEMPORAL_DITHER_OFFSET__SHIFT 0x15
+#define FMT_BIT_DEPTH_CONTROL__FMT_TEMPORAL_LEVEL_MASK 0x1000000
+#define FMT_BIT_DEPTH_CONTROL__FMT_TEMPORAL_LEVEL__SHIFT 0x18
+#define FMT_BIT_DEPTH_CONTROL__FMT_TEMPORAL_DITHER_RESET_MASK 0x2000000
+#define FMT_BIT_DEPTH_CONTROL__FMT_TEMPORAL_DITHER_RESET__SHIFT 0x19
+#define FMT_BIT_DEPTH_CONTROL__FMT_25FRC_SEL_MASK 0xc000000
+#define FMT_BIT_DEPTH_CONTROL__FMT_25FRC_SEL__SHIFT 0x1a
+#define FMT_BIT_DEPTH_CONTROL__FMT_50FRC_SEL_MASK 0x30000000
+#define FMT_BIT_DEPTH_CONTROL__FMT_50FRC_SEL__SHIFT 0x1c
+#define FMT_BIT_DEPTH_CONTROL__FMT_75FRC_SEL_MASK 0xc0000000
+#define FMT_BIT_DEPTH_CONTROL__FMT_75FRC_SEL__SHIFT 0x1e
+#define FMT_DITHER_RAND_R_SEED__FMT_RAND_R_SEED_MASK 0xff
+#define FMT_DITHER_RAND_R_SEED__FMT_RAND_R_SEED__SHIFT 0x0
+#define FMT_DITHER_RAND_R_SEED__FMT_OFFSET_R_CR_MASK 0xffff0000
+#define FMT_DITHER_RAND_R_SEED__FMT_OFFSET_R_CR__SHIFT 0x10
+#define FMT_DITHER_RAND_G_SEED__FMT_RAND_G_SEED_MASK 0xff
+#define FMT_DITHER_RAND_G_SEED__FMT_RAND_G_SEED__SHIFT 0x0
+#define FMT_DITHER_RAND_G_SEED__FMT_OFFSET_G_Y_MASK 0xffff0000
+#define FMT_DITHER_RAND_G_SEED__FMT_OFFSET_G_Y__SHIFT 0x10
+#define FMT_DITHER_RAND_B_SEED__FMT_RAND_B_SEED_MASK 0xff
+#define FMT_DITHER_RAND_B_SEED__FMT_RAND_B_SEED__SHIFT 0x0
+#define FMT_DITHER_RAND_B_SEED__FMT_OFFSET_B_CB_MASK 0xffff0000
+#define FMT_DITHER_RAND_B_SEED__FMT_OFFSET_B_CB__SHIFT 0x10
+#define FMT_CLAMP_CNTL__FMT_CLAMP_DATA_EN_MASK 0x1
+#define FMT_CLAMP_CNTL__FMT_CLAMP_DATA_EN__SHIFT 0x0
+#define FMT_CLAMP_CNTL__FMT_CLAMP_COLOR_FORMAT_MASK 0x70000
+#define FMT_CLAMP_CNTL__FMT_CLAMP_COLOR_FORMAT__SHIFT 0x10
+#define FMT_CRC_CNTL__FMT_CRC_EN_MASK 0x1
+#define FMT_CRC_CNTL__FMT_CRC_EN__SHIFT 0x0
+#define FMT_CRC_CNTL__FMT_DTMTEST_CRC_EN_MASK 0x2
+#define FMT_CRC_CNTL__FMT_DTMTEST_CRC_EN__SHIFT 0x1
+#define FMT_CRC_CNTL__FMT_CRC_CONT_EN_MASK 0x10
+#define FMT_CRC_CNTL__FMT_CRC_CONT_EN__SHIFT 0x4
+#define FMT_CRC_CNTL__FMT_ONE_SHOT_CRC_PENDING_MASK 0x20
+#define FMT_CRC_CNTL__FMT_ONE_SHOT_CRC_PENDING__SHIFT 0x5
+#define FMT_CRC_CNTL__FMT_CRC_INCLUDE_OVERSCAN_MASK 0x40
+#define FMT_CRC_CNTL__FMT_CRC_INCLUDE_OVERSCAN__SHIFT 0x6
+#define FMT_CRC_CNTL__FMT_CRC_ONLY_BLANKB_MASK 0x100
+#define FMT_CRC_CNTL__FMT_CRC_ONLY_BLANKB__SHIFT 0x8
+#define FMT_CRC_CNTL__FMT_CRC_PSR_MODE_ENABLE_MASK 0x200
+#define FMT_CRC_CNTL__FMT_CRC_PSR_MODE_ENABLE__SHIFT 0x9
+#define FMT_CRC_CNTL__FMT_CRC_INTERLACE_MODE_MASK 0x3000
+#define FMT_CRC_CNTL__FMT_CRC_INTERLACE_MODE__SHIFT 0xc
+#define FMT_CRC_CNTL__FMT_CRC_USE_NEW_AND_REPEATED_PIXELS_MASK 0x10000
+#define FMT_CRC_CNTL__FMT_CRC_USE_NEW_AND_REPEATED_PIXELS__SHIFT 0x10
+#define FMT_CRC_CNTL__FMT_CRC_EVEN_ODD_PIX_ENABLE_MASK 0x100000
+#define FMT_CRC_CNTL__FMT_CRC_EVEN_ODD_PIX_ENABLE__SHIFT 0x14
+#define FMT_CRC_CNTL__FMT_CRC_EVEN_ODD_PIX_SELECT_MASK 0x1000000
+#define FMT_CRC_CNTL__FMT_CRC_EVEN_ODD_PIX_SELECT__SHIFT 0x18
+#define FMT_CRC_SIG_RED_GREEN_MASK__FMT_CRC_SIG_RED_MASK_MASK 0xffff
+#define FMT_CRC_SIG_RED_GREEN_MASK__FMT_CRC_SIG_RED_MASK__SHIFT 0x0
+#define FMT_CRC_SIG_RED_GREEN_MASK__FMT_CRC_SIG_GREEN_MASK_MASK 0xffff0000
+#define FMT_CRC_SIG_RED_GREEN_MASK__FMT_CRC_SIG_GREEN_MASK__SHIFT 0x10
+#define FMT_CRC_SIG_BLUE_CONTROL_MASK__FMT_CRC_SIG_BLUE_MASK_MASK 0xffff
+#define FMT_CRC_SIG_BLUE_CONTROL_MASK__FMT_CRC_SIG_BLUE_MASK__SHIFT 0x0
+#define FMT_CRC_SIG_BLUE_CONTROL_MASK__FMT_CRC_SIG_CONTROL_MASK_MASK 0xffff0000
+#define FMT_CRC_SIG_BLUE_CONTROL_MASK__FMT_CRC_SIG_CONTROL_MASK__SHIFT 0x10
+#define FMT_CRC_SIG_RED_GREEN__FMT_CRC_SIG_RED_MASK 0xffff
+#define FMT_CRC_SIG_RED_GREEN__FMT_CRC_SIG_RED__SHIFT 0x0
+#define FMT_CRC_SIG_RED_GREEN__FMT_CRC_SIG_GREEN_MASK 0xffff0000
+#define FMT_CRC_SIG_RED_GREEN__FMT_CRC_SIG_GREEN__SHIFT 0x10
+#define FMT_CRC_SIG_BLUE_CONTROL__FMT_CRC_SIG_BLUE_MASK 0xffff
+#define FMT_CRC_SIG_BLUE_CONTROL__FMT_CRC_SIG_BLUE__SHIFT 0x0
+#define FMT_CRC_SIG_BLUE_CONTROL__FMT_CRC_SIG_CONTROL_MASK 0xffff0000
+#define FMT_CRC_SIG_BLUE_CONTROL__FMT_CRC_SIG_CONTROL__SHIFT 0x10
+#define FMT_DEBUG_CNTL__FMT_DEBUG_COLOR_SELECT_MASK 0x3
+#define FMT_DEBUG_CNTL__FMT_DEBUG_COLOR_SELECT__SHIFT 0x0
+#define FMT_SIDE_BY_SIDE_STEREO_CONTROL__FMT_SIDE_BY_SIDE_STEREO_ACTIVE_WIDTH_MASK 0x1fff
+#define FMT_SIDE_BY_SIDE_STEREO_CONTROL__FMT_SIDE_BY_SIDE_STEREO_ACTIVE_WIDTH__SHIFT 0x0
+#define FMT_420_HBLANK_EARLY_START__FMT_420_HBLANK_EARLY_START_MASK 0xfff
+#define FMT_420_HBLANK_EARLY_START__FMT_420_HBLANK_EARLY_START__SHIFT 0x0
+#define FMT_TEST_DEBUG_INDEX__FMT_TEST_DEBUG_INDEX_MASK 0xff
+#define FMT_TEST_DEBUG_INDEX__FMT_TEST_DEBUG_INDEX__SHIFT 0x0
+#define FMT_TEST_DEBUG_INDEX__FMT_TEST_DEBUG_WRITE_EN_MASK 0x100
+#define FMT_TEST_DEBUG_INDEX__FMT_TEST_DEBUG_WRITE_EN__SHIFT 0x8
+#define FMT_TEST_DEBUG_DATA__FMT_TEST_DEBUG_DATA_MASK 0xffffffff
+#define FMT_TEST_DEBUG_DATA__FMT_TEST_DEBUG_DATA__SHIFT 0x0
+#define FMT_DEBUG0__FMT_DEBUG0_MASK 0xffffffff
+#define FMT_DEBUG0__FMT_DEBUG0__SHIFT 0x0
+#define FMT_DEBUG1__FMT_DEBUG1_MASK 0xffffffff
+#define FMT_DEBUG1__FMT_DEBUG1__SHIFT 0x0
+#define FMT_DEBUG2__FMT_DEBUG2_MASK 0xffffffff
+#define FMT_DEBUG2__FMT_DEBUG2__SHIFT 0x0
+#define FMT_DEBUG3__FMT_DEBUG3_MASK 0xffffffff
+#define FMT_DEBUG3__FMT_DEBUG3__SHIFT 0x0
+#define FMT_DEBUG_ID__FMT_DEBUG_ID_MASK 0xffffffff
+#define FMT_DEBUG_ID__FMT_DEBUG_ID__SHIFT 0x0
+#define LB_DATA_FORMAT__PIXEL_DEPTH_MASK 0x3
+#define LB_DATA_FORMAT__PIXEL_DEPTH__SHIFT 0x0
+#define LB_DATA_FORMAT__PIXEL_EXPAN_MODE_MASK 0x4
+#define LB_DATA_FORMAT__PIXEL_EXPAN_MODE__SHIFT 0x2
+#define LB_DATA_FORMAT__INTERLEAVE_EN_MASK 0x8
+#define LB_DATA_FORMAT__INTERLEAVE_EN__SHIFT 0x3
+#define LB_DATA_FORMAT__PIXEL_REDUCE_MODE_MASK 0x10
+#define LB_DATA_FORMAT__PIXEL_REDUCE_MODE__SHIFT 0x4
+#define LB_DATA_FORMAT__DYNAMIC_PIXEL_DEPTH_MASK 0x20
+#define LB_DATA_FORMAT__DYNAMIC_PIXEL_DEPTH__SHIFT 0x5
+#define LB_DATA_FORMAT__PREFILL_EN_MASK 0x100
+#define LB_DATA_FORMAT__PREFILL_EN__SHIFT 0x8
+#define LB_DATA_FORMAT__PREFETCH_MASK 0x1000
+#define LB_DATA_FORMAT__PREFETCH__SHIFT 0xc
+#define LB_DATA_FORMAT__REQUEST_MODE_MASK 0x1000000
+#define LB_DATA_FORMAT__REQUEST_MODE__SHIFT 0x18
+#define LB_DATA_FORMAT__ALPHA_EN_MASK 0x80000000
+#define LB_DATA_FORMAT__ALPHA_EN__SHIFT 0x1f
+#define LB_MEMORY_CTRL__LB_MEMORY_SIZE_MASK 0x1fff
+#define LB_MEMORY_CTRL__LB_MEMORY_SIZE__SHIFT 0x0
+#define LB_MEMORY_CTRL__LB_NUM_PARTITIONS_MASK 0xf0000
+#define LB_MEMORY_CTRL__LB_NUM_PARTITIONS__SHIFT 0x10
+#define LB_MEMORY_CTRL__LB_MEMORY_CONFIG_MASK 0x300000
+#define LB_MEMORY_CTRL__LB_MEMORY_CONFIG__SHIFT 0x14
+#define LB_MEMORY_SIZE_STATUS__LB_MEMORY_SIZE_STATUS_MASK 0x1fff
+#define LB_MEMORY_SIZE_STATUS__LB_MEMORY_SIZE_STATUS__SHIFT 0x0
+#define LB_DESKTOP_HEIGHT__DESKTOP_HEIGHT_MASK 0x7fff
+#define LB_DESKTOP_HEIGHT__DESKTOP_HEIGHT__SHIFT 0x0
+#define LB_VLINE_START_END__VLINE_START_MASK 0x3fff
+#define LB_VLINE_START_END__VLINE_START__SHIFT 0x0
+#define LB_VLINE_START_END__VLINE_END_MASK 0x7fff0000
+#define LB_VLINE_START_END__VLINE_END__SHIFT 0x10
+#define LB_VLINE_START_END__VLINE_INV_MASK 0x80000000
+#define LB_VLINE_START_END__VLINE_INV__SHIFT 0x1f
+#define LB_VLINE2_START_END__VLINE2_START_MASK 0x3fff
+#define LB_VLINE2_START_END__VLINE2_START__SHIFT 0x0
+#define LB_VLINE2_START_END__VLINE2_END_MASK 0x7fff0000
+#define LB_VLINE2_START_END__VLINE2_END__SHIFT 0x10
+#define LB_VLINE2_START_END__VLINE2_INV_MASK 0x80000000
+#define LB_VLINE2_START_END__VLINE2_INV__SHIFT 0x1f
+#define LB_V_COUNTER__V_COUNTER_MASK 0x7fff
+#define LB_V_COUNTER__V_COUNTER__SHIFT 0x0
+#define LB_SNAPSHOT_V_COUNTER__SNAPSHOT_V_COUNTER_MASK 0x7fff
+#define LB_SNAPSHOT_V_COUNTER__SNAPSHOT_V_COUNTER__SHIFT 0x0
+#define LB_INTERRUPT_MASK__VBLANK_INTERRUPT_MASK_MASK 0x1
+#define LB_INTERRUPT_MASK__VBLANK_INTERRUPT_MASK__SHIFT 0x0
+#define LB_INTERRUPT_MASK__VLINE_INTERRUPT_MASK_MASK 0x10
+#define LB_INTERRUPT_MASK__VLINE_INTERRUPT_MASK__SHIFT 0x4
+#define LB_INTERRUPT_MASK__VLINE2_INTERRUPT_MASK_MASK 0x100
+#define LB_INTERRUPT_MASK__VLINE2_INTERRUPT_MASK__SHIFT 0x8
+#define LB_VLINE_STATUS__VLINE_OCCURRED_MASK 0x1
+#define LB_VLINE_STATUS__VLINE_OCCURRED__SHIFT 0x0
+#define LB_VLINE_STATUS__VLINE_ACK_MASK 0x10
+#define LB_VLINE_STATUS__VLINE_ACK__SHIFT 0x4
+#define LB_VLINE_STATUS__VLINE_STAT_MASK 0x1000
+#define LB_VLINE_STATUS__VLINE_STAT__SHIFT 0xc
+#define LB_VLINE_STATUS__VLINE_INTERRUPT_MASK 0x10000
+#define LB_VLINE_STATUS__VLINE_INTERRUPT__SHIFT 0x10
+#define LB_VLINE_STATUS__VLINE_INTERRUPT_TYPE_MASK 0x20000
+#define LB_VLINE_STATUS__VLINE_INTERRUPT_TYPE__SHIFT 0x11
+#define LB_VLINE2_STATUS__VLINE2_OCCURRED_MASK 0x1
+#define LB_VLINE2_STATUS__VLINE2_OCCURRED__SHIFT 0x0
+#define LB_VLINE2_STATUS__VLINE2_ACK_MASK 0x10
+#define LB_VLINE2_STATUS__VLINE2_ACK__SHIFT 0x4
+#define LB_VLINE2_STATUS__VLINE2_STAT_MASK 0x1000
+#define LB_VLINE2_STATUS__VLINE2_STAT__SHIFT 0xc
+#define LB_VLINE2_STATUS__VLINE2_INTERRUPT_MASK 0x10000
+#define LB_VLINE2_STATUS__VLINE2_INTERRUPT__SHIFT 0x10
+#define LB_VLINE2_STATUS__VLINE2_INTERRUPT_TYPE_MASK 0x20000
+#define LB_VLINE2_STATUS__VLINE2_INTERRUPT_TYPE__SHIFT 0x11
+#define LB_VBLANK_STATUS__VBLANK_OCCURRED_MASK 0x1
+#define LB_VBLANK_STATUS__VBLANK_OCCURRED__SHIFT 0x0
+#define LB_VBLANK_STATUS__VBLANK_ACK_MASK 0x10
+#define LB_VBLANK_STATUS__VBLANK_ACK__SHIFT 0x4
+#define LB_VBLANK_STATUS__VBLANK_STAT_MASK 0x1000
+#define LB_VBLANK_STATUS__VBLANK_STAT__SHIFT 0xc
+#define LB_VBLANK_STATUS__VBLANK_INTERRUPT_MASK 0x10000
+#define LB_VBLANK_STATUS__VBLANK_INTERRUPT__SHIFT 0x10
+#define LB_VBLANK_STATUS__VBLANK_INTERRUPT_TYPE_MASK 0x20000
+#define LB_VBLANK_STATUS__VBLANK_INTERRUPT_TYPE__SHIFT 0x11
+#define LB_SYNC_RESET_SEL__LB_SYNC_RESET_SEL_MASK 0x3
+#define LB_SYNC_RESET_SEL__LB_SYNC_RESET_SEL__SHIFT 0x0
+#define LB_SYNC_RESET_SEL__LB_SYNC_RESET_SEL2_MASK 0x10
+#define LB_SYNC_RESET_SEL__LB_SYNC_RESET_SEL2__SHIFT 0x4
+#define LB_SYNC_RESET_SEL__LB_SYNC_RESET_DELAY_MASK 0xff00
+#define LB_SYNC_RESET_SEL__LB_SYNC_RESET_DELAY__SHIFT 0x8
+#define LB_SYNC_RESET_SEL__LB_SYNC_DURATION_MASK 0xc00000
+#define LB_SYNC_RESET_SEL__LB_SYNC_DURATION__SHIFT 0x16
+#define LB_BLACK_KEYER_R_CR__LB_BLACK_KEYER_R_CR_MASK 0xfff0
+#define LB_BLACK_KEYER_R_CR__LB_BLACK_KEYER_R_CR__SHIFT 0x4
+#define LB_BLACK_KEYER_G_Y__LB_BLACK_KEYER_G_Y_MASK 0xfff0
+#define LB_BLACK_KEYER_G_Y__LB_BLACK_KEYER_G_Y__SHIFT 0x4
+#define LB_BLACK_KEYER_B_CB__LB_BLACK_KEYER_B_CB_MASK 0xfff0
+#define LB_BLACK_KEYER_B_CB__LB_BLACK_KEYER_B_CB__SHIFT 0x4
+#define LB_KEYER_COLOR_CTRL__LB_KEYER_COLOR_EN_MASK 0x1
+#define LB_KEYER_COLOR_CTRL__LB_KEYER_COLOR_EN__SHIFT 0x0
+#define LB_KEYER_COLOR_CTRL__LB_KEYER_COLOR_REP_EN_MASK 0x100
+#define LB_KEYER_COLOR_CTRL__LB_KEYER_COLOR_REP_EN__SHIFT 0x8
+#define LB_KEYER_COLOR_R_CR__LB_KEYER_COLOR_R_CR_MASK 0xfff0
+#define LB_KEYER_COLOR_R_CR__LB_KEYER_COLOR_R_CR__SHIFT 0x4
+#define LB_KEYER_COLOR_G_Y__LB_KEYER_COLOR_G_Y_MASK 0xfff0
+#define LB_KEYER_COLOR_G_Y__LB_KEYER_COLOR_G_Y__SHIFT 0x4
+#define LB_KEYER_COLOR_B_CB__LB_KEYER_COLOR_B_CB_MASK 0xfff0
+#define LB_KEYER_COLOR_B_CB__LB_KEYER_COLOR_B_CB__SHIFT 0x4
+#define LB_KEYER_COLOR_REP_R_CR__LB_KEYER_COLOR_REP_R_CR_MASK 0xfff0
+#define LB_KEYER_COLOR_REP_R_CR__LB_KEYER_COLOR_REP_R_CR__SHIFT 0x4
+#define LB_KEYER_COLOR_REP_G_Y__LB_KEYER_COLOR_REP_G_Y_MASK 0xfff0
+#define LB_KEYER_COLOR_REP_G_Y__LB_KEYER_COLOR_REP_G_Y__SHIFT 0x4
+#define LB_KEYER_COLOR_REP_B_CB__LB_KEYER_COLOR_REP_B_CB_MASK 0xfff0
+#define LB_KEYER_COLOR_REP_B_CB__LB_KEYER_COLOR_REP_B_CB__SHIFT 0x4
+#define LB_BUFFER_LEVEL_STATUS__REQ_FIFO_LEVEL_MASK 0x3f
+#define LB_BUFFER_LEVEL_STATUS__REQ_FIFO_LEVEL__SHIFT 0x0
+#define LB_BUFFER_LEVEL_STATUS__REQ_FIFO_FULL_CNTL_MASK 0xfc00
+#define LB_BUFFER_LEVEL_STATUS__REQ_FIFO_FULL_CNTL__SHIFT 0xa
+#define LB_BUFFER_LEVEL_STATUS__DATA_BUFFER_LEVEL_MASK 0xfff0000
+#define LB_BUFFER_LEVEL_STATUS__DATA_BUFFER_LEVEL__SHIFT 0x10
+#define LB_BUFFER_LEVEL_STATUS__DATA_FIFO_FULL_CNTL_MASK 0xf0000000
+#define LB_BUFFER_LEVEL_STATUS__DATA_FIFO_FULL_CNTL__SHIFT 0x1c
+#define LB_BUFFER_URGENCY_CTRL__LB_BUFFER_URGENCY_MARK_ON_MASK 0xfff
+#define LB_BUFFER_URGENCY_CTRL__LB_BUFFER_URGENCY_MARK_ON__SHIFT 0x0
+#define LB_BUFFER_URGENCY_CTRL__LB_BUFFER_URGENCY_MARK_OFF_MASK 0xfff0000
+#define LB_BUFFER_URGENCY_CTRL__LB_BUFFER_URGENCY_MARK_OFF__SHIFT 0x10
+#define LB_BUFFER_URGENCY_STATUS__LB_BUFFER_URGENCY_LEVEL_MASK 0xfff
+#define LB_BUFFER_URGENCY_STATUS__LB_BUFFER_URGENCY_LEVEL__SHIFT 0x0
+#define LB_BUFFER_URGENCY_STATUS__LB_BUFFER_URGENCY_STAT_MASK 0x10000
+#define LB_BUFFER_URGENCY_STATUS__LB_BUFFER_URGENCY_STAT__SHIFT 0x10
+#define LB_BUFFER_STATUS__LB_BUFFER_EMPTY_MARGIN_MASK 0xf
+#define LB_BUFFER_STATUS__LB_BUFFER_EMPTY_MARGIN__SHIFT 0x0
+#define LB_BUFFER_STATUS__LB_BUFFER_EMPTY_STAT_MASK 0x10
+#define LB_BUFFER_STATUS__LB_BUFFER_EMPTY_STAT__SHIFT 0x4
+#define LB_BUFFER_STATUS__LB_BUFFER_EMPTY_OCCURRED_MASK 0x100
+#define LB_BUFFER_STATUS__LB_BUFFER_EMPTY_OCCURRED__SHIFT 0x8
+#define LB_BUFFER_STATUS__LB_BUFFER_EMPTY_ACK_MASK 0x1000
+#define LB_BUFFER_STATUS__LB_BUFFER_EMPTY_ACK__SHIFT 0xc
+#define LB_BUFFER_STATUS__LB_BUFFER_FULL_STAT_MASK 0x10000
+#define LB_BUFFER_STATUS__LB_BUFFER_FULL_STAT__SHIFT 0x10
+#define LB_BUFFER_STATUS__LB_BUFFER_FULL_OCCURRED_MASK 0x100000
+#define LB_BUFFER_STATUS__LB_BUFFER_FULL_OCCURRED__SHIFT 0x14
+#define LB_BUFFER_STATUS__LB_BUFFER_FULL_ACK_MASK 0x1000000
+#define LB_BUFFER_STATUS__LB_BUFFER_FULL_ACK__SHIFT 0x18
+#define LB_NO_OUTSTANDING_REQ_STATUS__LB_NO_OUTSTANDING_REQ_STAT_MASK 0x1
+#define LB_NO_OUTSTANDING_REQ_STATUS__LB_NO_OUTSTANDING_REQ_STAT__SHIFT 0x0
+#define MVP_AFR_FLIP_MODE__MVP_AFR_FLIP_MODE_MASK 0x3
+#define MVP_AFR_FLIP_MODE__MVP_AFR_FLIP_MODE__SHIFT 0x0
+#define MVP_AFR_FLIP_FIFO_CNTL__MVP_AFR_FLIP_FIFO_NUM_ENTRIES_MASK 0xf
+#define MVP_AFR_FLIP_FIFO_CNTL__MVP_AFR_FLIP_FIFO_NUM_ENTRIES__SHIFT 0x0
+#define MVP_AFR_FLIP_FIFO_CNTL__MVP_AFR_FLIP_FIFO_RESET_MASK 0x10
+#define MVP_AFR_FLIP_FIFO_CNTL__MVP_AFR_FLIP_FIFO_RESET__SHIFT 0x4
+#define MVP_AFR_FLIP_FIFO_CNTL__MVP_AFR_FLIP_FIFO_RESET_FLAG_MASK 0x100
+#define MVP_AFR_FLIP_FIFO_CNTL__MVP_AFR_FLIP_FIFO_RESET_FLAG__SHIFT 0x8
+#define MVP_AFR_FLIP_FIFO_CNTL__MVP_AFR_FLIP_FIFO_RESET_ACK_MASK 0x1000
+#define MVP_AFR_FLIP_FIFO_CNTL__MVP_AFR_FLIP_FIFO_RESET_ACK__SHIFT 0xc
+#define MVP_FLIP_LINE_NUM_INSERT__MVP_FLIP_LINE_NUM_INSERT_MODE_MASK 0x3
+#define MVP_FLIP_LINE_NUM_INSERT__MVP_FLIP_LINE_NUM_INSERT_MODE__SHIFT 0x0
+#define MVP_FLIP_LINE_NUM_INSERT__MVP_FLIP_LINE_NUM_INSERT_MASK 0x7fff00
+#define MVP_FLIP_LINE_NUM_INSERT__MVP_FLIP_LINE_NUM_INSERT__SHIFT 0x8
+#define MVP_FLIP_LINE_NUM_INSERT__MVP_FLIP_LINE_NUM_OFFSET_MASK 0x3f000000
+#define MVP_FLIP_LINE_NUM_INSERT__MVP_FLIP_LINE_NUM_OFFSET__SHIFT 0x18
+#define MVP_FLIP_LINE_NUM_INSERT__MVP_FLIP_AUTO_ENABLE_MASK 0x40000000
+#define MVP_FLIP_LINE_NUM_INSERT__MVP_FLIP_AUTO_ENABLE__SHIFT 0x1e
+#define DC_MVP_LB_CONTROL__MVP_SWAP_LOCK_IN_MODE_MASK 0x3
+#define DC_MVP_LB_CONTROL__MVP_SWAP_LOCK_IN_MODE__SHIFT 0x0
+#define DC_MVP_LB_CONTROL__DC_MVP_SWAP_LOCK_OUT_SEL_MASK 0x100
+#define DC_MVP_LB_CONTROL__DC_MVP_SWAP_LOCK_OUT_SEL__SHIFT 0x8
+#define DC_MVP_LB_CONTROL__DC_MVP_SWAP_LOCK_OUT_FORCE_ONE_MASK 0x1000
+#define DC_MVP_LB_CONTROL__DC_MVP_SWAP_LOCK_OUT_FORCE_ONE__SHIFT 0xc
+#define DC_MVP_LB_CONTROL__DC_MVP_SWAP_LOCK_OUT_FORCE_ZERO_MASK 0x10000
+#define DC_MVP_LB_CONTROL__DC_MVP_SWAP_LOCK_OUT_FORCE_ZERO__SHIFT 0x10
+#define DC_MVP_LB_CONTROL__DC_MVP_SWAP_LOCK_STATUS_MASK 0x100000
+#define DC_MVP_LB_CONTROL__DC_MVP_SWAP_LOCK_STATUS__SHIFT 0x14
+#define DC_MVP_LB_CONTROL__DC_MVP_SWAP_LOCK_IN_CAP_MASK 0x10000000
+#define DC_MVP_LB_CONTROL__DC_MVP_SWAP_LOCK_IN_CAP__SHIFT 0x1c
+#define DC_MVP_LB_CONTROL__DC_MVP_SPARE_FLOPS_MASK 0x80000000
+#define DC_MVP_LB_CONTROL__DC_MVP_SPARE_FLOPS__SHIFT 0x1f
+#define LB_DEBUG__LB_DEBUG_MASK 0xffffffff
+#define LB_DEBUG__LB_DEBUG__SHIFT 0x0
+#define LB_DEBUG2__LB_DEBUG2_MASK 0xffffffff
+#define LB_DEBUG2__LB_DEBUG2__SHIFT 0x0
+#define LB_DEBUG3__LB_DEBUG3_MASK 0xffffffff
+#define LB_DEBUG3__LB_DEBUG3__SHIFT 0x0
+#define LB_TEST_DEBUG_INDEX__LB_TEST_DEBUG_INDEX_MASK 0xff
+#define LB_TEST_DEBUG_INDEX__LB_TEST_DEBUG_INDEX__SHIFT 0x0
+#define LB_TEST_DEBUG_INDEX__LB_TEST_DEBUG_WRITE_EN_MASK 0x100
+#define LB_TEST_DEBUG_INDEX__LB_TEST_DEBUG_WRITE_EN__SHIFT 0x8
+#define LB_TEST_DEBUG_DATA__LB_TEST_DEBUG_DATA_MASK 0xffffffff
+#define LB_TEST_DEBUG_DATA__LB_TEST_DEBUG_DATA__SHIFT 0x0
+#define LBV_DATA_FORMAT__PIXEL_DEPTH_MASK 0x3
+#define LBV_DATA_FORMAT__PIXEL_DEPTH__SHIFT 0x0
+#define LBV_DATA_FORMAT__PIXEL_EXPAN_MODE_MASK 0x4
+#define LBV_DATA_FORMAT__PIXEL_EXPAN_MODE__SHIFT 0x2
+#define LBV_DATA_FORMAT__INTERLEAVE_EN_MASK 0x8
+#define LBV_DATA_FORMAT__INTERLEAVE_EN__SHIFT 0x3
+#define LBV_DATA_FORMAT__PIXEL_REDUCE_MODE_MASK 0x10
+#define LBV_DATA_FORMAT__PIXEL_REDUCE_MODE__SHIFT 0x4
+#define LBV_DATA_FORMAT__DYNAMIC_PIXEL_DEPTH_MASK 0x20
+#define LBV_DATA_FORMAT__DYNAMIC_PIXEL_DEPTH__SHIFT 0x5
+#define LBV_DATA_FORMAT__DITHER_EN_MASK 0x40
+#define LBV_DATA_FORMAT__DITHER_EN__SHIFT 0x6
+#define LBV_DATA_FORMAT__DOWNSCALE_PREFETCH_EN_MASK 0x80
+#define LBV_DATA_FORMAT__DOWNSCALE_PREFETCH_EN__SHIFT 0x7
+#define LBV_DATA_FORMAT__PREFETCH_MASK 0x1000
+#define LBV_DATA_FORMAT__PREFETCH__SHIFT 0xc
+#define LBV_DATA_FORMAT__REQUEST_MODE_MASK 0x1000000
+#define LBV_DATA_FORMAT__REQUEST_MODE__SHIFT 0x18
+#define LBV_DATA_FORMAT__ALPHA_EN_MASK 0x80000000
+#define LBV_DATA_FORMAT__ALPHA_EN__SHIFT 0x1f
+#define LBV_MEMORY_CTRL__LB_MEMORY_SIZE_MASK 0xfff
+#define LBV_MEMORY_CTRL__LB_MEMORY_SIZE__SHIFT 0x0
+#define LBV_MEMORY_CTRL__LB_NUM_PARTITIONS_MASK 0xf0000
+#define LBV_MEMORY_CTRL__LB_NUM_PARTITIONS__SHIFT 0x10
+#define LBV_MEMORY_CTRL__LB_MEMORY_CONFIG_MASK 0x300000
+#define LBV_MEMORY_CTRL__LB_MEMORY_CONFIG__SHIFT 0x14
+#define LBV_MEMORY_SIZE_STATUS__LB_MEMORY_SIZE_STATUS_MASK 0xfff
+#define LBV_MEMORY_SIZE_STATUS__LB_MEMORY_SIZE_STATUS__SHIFT 0x0
+#define LBV_DESKTOP_HEIGHT__DESKTOP_HEIGHT_MASK 0x7fff
+#define LBV_DESKTOP_HEIGHT__DESKTOP_HEIGHT__SHIFT 0x0
+#define LBV_VLINE_START_END__VLINE_START_MASK 0x3fff
+#define LBV_VLINE_START_END__VLINE_START__SHIFT 0x0
+#define LBV_VLINE_START_END__VLINE_END_MASK 0x7fff0000
+#define LBV_VLINE_START_END__VLINE_END__SHIFT 0x10
+#define LBV_VLINE_START_END__VLINE_INV_MASK 0x80000000
+#define LBV_VLINE_START_END__VLINE_INV__SHIFT 0x1f
+#define LBV_VLINE2_START_END__VLINE2_START_MASK 0x3fff
+#define LBV_VLINE2_START_END__VLINE2_START__SHIFT 0x0
+#define LBV_VLINE2_START_END__VLINE2_END_MASK 0x7fff0000
+#define LBV_VLINE2_START_END__VLINE2_END__SHIFT 0x10
+#define LBV_VLINE2_START_END__VLINE2_INV_MASK 0x80000000
+#define LBV_VLINE2_START_END__VLINE2_INV__SHIFT 0x1f
+#define LBV_V_COUNTER__V_COUNTER_MASK 0x7fff
+#define LBV_V_COUNTER__V_COUNTER__SHIFT 0x0
+#define LBV_SNAPSHOT_V_COUNTER__SNAPSHOT_V_COUNTER_MASK 0x7fff
+#define LBV_SNAPSHOT_V_COUNTER__SNAPSHOT_V_COUNTER__SHIFT 0x0
+#define LBV_V_COUNTER_CHROMA__V_COUNTER_CHROMA_MASK 0x7fff
+#define LBV_V_COUNTER_CHROMA__V_COUNTER_CHROMA__SHIFT 0x0
+#define LBV_SNAPSHOT_V_COUNTER_CHROMA__SNAPSHOT_V_COUNTER_CHROMA_MASK 0x7fff
+#define LBV_SNAPSHOT_V_COUNTER_CHROMA__SNAPSHOT_V_COUNTER_CHROMA__SHIFT 0x0
+#define LBV_INTERRUPT_MASK__VBLANK_INTERRUPT_MASK_MASK 0x1
+#define LBV_INTERRUPT_MASK__VBLANK_INTERRUPT_MASK__SHIFT 0x0
+#define LBV_INTERRUPT_MASK__VLINE_INTERRUPT_MASK_MASK 0x10
+#define LBV_INTERRUPT_MASK__VLINE_INTERRUPT_MASK__SHIFT 0x4
+#define LBV_INTERRUPT_MASK__VLINE2_INTERRUPT_MASK_MASK 0x100
+#define LBV_INTERRUPT_MASK__VLINE2_INTERRUPT_MASK__SHIFT 0x8
+#define LBV_VLINE_STATUS__VLINE_OCCURRED_MASK 0x1
+#define LBV_VLINE_STATUS__VLINE_OCCURRED__SHIFT 0x0
+#define LBV_VLINE_STATUS__VLINE_ACK_MASK 0x10
+#define LBV_VLINE_STATUS__VLINE_ACK__SHIFT 0x4
+#define LBV_VLINE_STATUS__VLINE_STAT_MASK 0x1000
+#define LBV_VLINE_STATUS__VLINE_STAT__SHIFT 0xc
+#define LBV_VLINE_STATUS__VLINE_INTERRUPT_MASK 0x10000
+#define LBV_VLINE_STATUS__VLINE_INTERRUPT__SHIFT 0x10
+#define LBV_VLINE_STATUS__VLINE_INTERRUPT_TYPE_MASK 0x20000
+#define LBV_VLINE_STATUS__VLINE_INTERRUPT_TYPE__SHIFT 0x11
+#define LBV_VLINE2_STATUS__VLINE2_OCCURRED_MASK 0x1
+#define LBV_VLINE2_STATUS__VLINE2_OCCURRED__SHIFT 0x0
+#define LBV_VLINE2_STATUS__VLINE2_ACK_MASK 0x10
+#define LBV_VLINE2_STATUS__VLINE2_ACK__SHIFT 0x4
+#define LBV_VLINE2_STATUS__VLINE2_STAT_MASK 0x1000
+#define LBV_VLINE2_STATUS__VLINE2_STAT__SHIFT 0xc
+#define LBV_VLINE2_STATUS__VLINE2_INTERRUPT_MASK 0x10000
+#define LBV_VLINE2_STATUS__VLINE2_INTERRUPT__SHIFT 0x10
+#define LBV_VLINE2_STATUS__VLINE2_INTERRUPT_TYPE_MASK 0x20000
+#define LBV_VLINE2_STATUS__VLINE2_INTERRUPT_TYPE__SHIFT 0x11
+#define LBV_VBLANK_STATUS__VBLANK_OCCURRED_MASK 0x1
+#define LBV_VBLANK_STATUS__VBLANK_OCCURRED__SHIFT 0x0
+#define LBV_VBLANK_STATUS__VBLANK_ACK_MASK 0x10
+#define LBV_VBLANK_STATUS__VBLANK_ACK__SHIFT 0x4
+#define LBV_VBLANK_STATUS__VBLANK_STAT_MASK 0x1000
+#define LBV_VBLANK_STATUS__VBLANK_STAT__SHIFT 0xc
+#define LBV_VBLANK_STATUS__VBLANK_INTERRUPT_MASK 0x10000
+#define LBV_VBLANK_STATUS__VBLANK_INTERRUPT__SHIFT 0x10
+#define LBV_VBLANK_STATUS__VBLANK_INTERRUPT_TYPE_MASK 0x20000
+#define LBV_VBLANK_STATUS__VBLANK_INTERRUPT_TYPE__SHIFT 0x11
+#define LBV_SYNC_RESET_SEL__LB_SYNC_RESET_SEL_MASK 0x3
+#define LBV_SYNC_RESET_SEL__LB_SYNC_RESET_SEL__SHIFT 0x0
+#define LBV_SYNC_RESET_SEL__LB_SYNC_RESET_SEL2_MASK 0x10
+#define LBV_SYNC_RESET_SEL__LB_SYNC_RESET_SEL2__SHIFT 0x4
+#define LBV_SYNC_RESET_SEL__LB_SYNC_RESET_DELAY_MASK 0xff00
+#define LBV_SYNC_RESET_SEL__LB_SYNC_RESET_DELAY__SHIFT 0x8
+#define LBV_SYNC_RESET_SEL__LB_SYNC_DURATION_MASK 0xc00000
+#define LBV_SYNC_RESET_SEL__LB_SYNC_DURATION__SHIFT 0x16
+#define LBV_BLACK_KEYER_R_CR__LB_BLACK_KEYER_R_CR_MASK 0xfff0
+#define LBV_BLACK_KEYER_R_CR__LB_BLACK_KEYER_R_CR__SHIFT 0x4
+#define LBV_BLACK_KEYER_G_Y__LB_BLACK_KEYER_G_Y_MASK 0xfff0
+#define LBV_BLACK_KEYER_G_Y__LB_BLACK_KEYER_G_Y__SHIFT 0x4
+#define LBV_BLACK_KEYER_B_CB__LB_BLACK_KEYER_B_CB_MASK 0xfff0
+#define LBV_BLACK_KEYER_B_CB__LB_BLACK_KEYER_B_CB__SHIFT 0x4
+#define LBV_KEYER_COLOR_CTRL__LB_KEYER_COLOR_EN_MASK 0x1
+#define LBV_KEYER_COLOR_CTRL__LB_KEYER_COLOR_EN__SHIFT 0x0
+#define LBV_KEYER_COLOR_CTRL__LB_KEYER_COLOR_REP_EN_MASK 0x100
+#define LBV_KEYER_COLOR_CTRL__LB_KEYER_COLOR_REP_EN__SHIFT 0x8
+#define LBV_KEYER_COLOR_R_CR__LB_KEYER_COLOR_R_CR_MASK 0xfff0
+#define LBV_KEYER_COLOR_R_CR__LB_KEYER_COLOR_R_CR__SHIFT 0x4
+#define LBV_KEYER_COLOR_G_Y__LB_KEYER_COLOR_G_Y_MASK 0xfff0
+#define LBV_KEYER_COLOR_G_Y__LB_KEYER_COLOR_G_Y__SHIFT 0x4
+#define LBV_KEYER_COLOR_B_CB__LB_KEYER_COLOR_B_CB_MASK 0xfff0
+#define LBV_KEYER_COLOR_B_CB__LB_KEYER_COLOR_B_CB__SHIFT 0x4
+#define LBV_KEYER_COLOR_REP_R_CR__LB_KEYER_COLOR_REP_R_CR_MASK 0xfff0
+#define LBV_KEYER_COLOR_REP_R_CR__LB_KEYER_COLOR_REP_R_CR__SHIFT 0x4
+#define LBV_KEYER_COLOR_REP_G_Y__LB_KEYER_COLOR_REP_G_Y_MASK 0xfff0
+#define LBV_KEYER_COLOR_REP_G_Y__LB_KEYER_COLOR_REP_G_Y__SHIFT 0x4
+#define LBV_KEYER_COLOR_REP_B_CB__LB_KEYER_COLOR_REP_B_CB_MASK 0xfff0
+#define LBV_KEYER_COLOR_REP_B_CB__LB_KEYER_COLOR_REP_B_CB__SHIFT 0x4
+#define LBV_BUFFER_LEVEL_STATUS__REQ_FIFO_LEVEL_MASK 0x3f
+#define LBV_BUFFER_LEVEL_STATUS__REQ_FIFO_LEVEL__SHIFT 0x0
+#define LBV_BUFFER_LEVEL_STATUS__REQ_FIFO_FULL_CNTL_MASK 0xfc00
+#define LBV_BUFFER_LEVEL_STATUS__REQ_FIFO_FULL_CNTL__SHIFT 0xa
+#define LBV_BUFFER_LEVEL_STATUS__DATA_BUFFER_LEVEL_MASK 0xfff0000
+#define LBV_BUFFER_LEVEL_STATUS__DATA_BUFFER_LEVEL__SHIFT 0x10
+#define LBV_BUFFER_LEVEL_STATUS__DATA_FIFO_FULL_CNTL_MASK 0xf0000000
+#define LBV_BUFFER_LEVEL_STATUS__DATA_FIFO_FULL_CNTL__SHIFT 0x1c
+#define LBV_BUFFER_URGENCY_CTRL__LB_BUFFER_URGENCY_MARK_ON_MASK 0xfff
+#define LBV_BUFFER_URGENCY_CTRL__LB_BUFFER_URGENCY_MARK_ON__SHIFT 0x0
+#define LBV_BUFFER_URGENCY_CTRL__LB_BUFFER_URGENCY_MARK_OFF_MASK 0xfff0000
+#define LBV_BUFFER_URGENCY_CTRL__LB_BUFFER_URGENCY_MARK_OFF__SHIFT 0x10
+#define LBV_BUFFER_URGENCY_STATUS__LB_BUFFER_URGENCY_LEVEL_MASK 0xfff
+#define LBV_BUFFER_URGENCY_STATUS__LB_BUFFER_URGENCY_LEVEL__SHIFT 0x0
+#define LBV_BUFFER_URGENCY_STATUS__LB_BUFFER_URGENCY_STAT_MASK 0x10000
+#define LBV_BUFFER_URGENCY_STATUS__LB_BUFFER_URGENCY_STAT__SHIFT 0x10
+#define LBV_BUFFER_STATUS__LB_BUFFER_EMPTY_MARGIN_MASK 0xf
+#define LBV_BUFFER_STATUS__LB_BUFFER_EMPTY_MARGIN__SHIFT 0x0
+#define LBV_BUFFER_STATUS__LB_BUFFER_EMPTY_STAT_MASK 0x10
+#define LBV_BUFFER_STATUS__LB_BUFFER_EMPTY_STAT__SHIFT 0x4
+#define LBV_BUFFER_STATUS__LB_BUFFER_EMPTY_OCCURRED_MASK 0x100
+#define LBV_BUFFER_STATUS__LB_BUFFER_EMPTY_OCCURRED__SHIFT 0x8
+#define LBV_BUFFER_STATUS__LB_BUFFER_EMPTY_ACK_MASK 0x1000
+#define LBV_BUFFER_STATUS__LB_BUFFER_EMPTY_ACK__SHIFT 0xc
+#define LBV_BUFFER_STATUS__LB_BUFFER_FULL_STAT_MASK 0x10000
+#define LBV_BUFFER_STATUS__LB_BUFFER_FULL_STAT__SHIFT 0x10
+#define LBV_BUFFER_STATUS__LB_BUFFER_FULL_OCCURRED_MASK 0x100000
+#define LBV_BUFFER_STATUS__LB_BUFFER_FULL_OCCURRED__SHIFT 0x14
+#define LBV_BUFFER_STATUS__LB_BUFFER_FULL_ACK_MASK 0x1000000
+#define LBV_BUFFER_STATUS__LB_BUFFER_FULL_ACK__SHIFT 0x18
+#define LBV_BUFFER_STATUS__LB_ENABLE_HIGH_THROUGHPUT_MASK 0x2000000
+#define LBV_BUFFER_STATUS__LB_ENABLE_HIGH_THROUGHPUT__SHIFT 0x19
+#define LBV_BUFFER_STATUS__LB_HIGH_THROUGHPUT_CNTL_MASK 0x1c000000
+#define LBV_BUFFER_STATUS__LB_HIGH_THROUGHPUT_CNTL__SHIFT 0x1a
+#define LBV_NO_OUTSTANDING_REQ_STATUS__LB_NO_OUTSTANDING_REQ_STAT_MASK 0x1
+#define LBV_NO_OUTSTANDING_REQ_STATUS__LB_NO_OUTSTANDING_REQ_STAT__SHIFT 0x0
+#define LBV_DEBUG__LB_DEBUG_MASK 0xffffffff
+#define LBV_DEBUG__LB_DEBUG__SHIFT 0x0
+#define LBV_DEBUG2__LB_DEBUG2_MASK 0xffffffff
+#define LBV_DEBUG2__LB_DEBUG2__SHIFT 0x0
+#define LBV_DEBUG3__LB_DEBUG3_MASK 0xffffffff
+#define LBV_DEBUG3__LB_DEBUG3__SHIFT 0x0
+#define LBV_TEST_DEBUG_INDEX__LB_TEST_DEBUG_INDEX_MASK 0xff
+#define LBV_TEST_DEBUG_INDEX__LB_TEST_DEBUG_INDEX__SHIFT 0x0
+#define LBV_TEST_DEBUG_INDEX__LB_TEST_DEBUG_WRITE_EN_MASK 0x100
+#define LBV_TEST_DEBUG_INDEX__LB_TEST_DEBUG_WRITE_EN__SHIFT 0x8
+#define LBV_TEST_DEBUG_DATA__LB_TEST_DEBUG_DATA_MASK 0xffffffff
+#define LBV_TEST_DEBUG_DATA__LB_TEST_DEBUG_DATA__SHIFT 0x0
+#define MVP_CONTROL1__MVP_EN_MASK 0x1
+#define MVP_CONTROL1__MVP_EN__SHIFT 0x0
+#define MVP_CONTROL1__MVP_MIXER_MODE_MASK 0x70
+#define MVP_CONTROL1__MVP_MIXER_MODE__SHIFT 0x4
+#define MVP_CONTROL1__MVP_MIXER_SLAVE_SEL_MASK 0x100
+#define MVP_CONTROL1__MVP_MIXER_SLAVE_SEL__SHIFT 0x8
+#define MVP_CONTROL1__MVP_MIXER_SLAVE_SEL_DELAY_UNTIL_END_OF_BLANK_MASK 0x200
+#define MVP_CONTROL1__MVP_MIXER_SLAVE_SEL_DELAY_UNTIL_END_OF_BLANK__SHIFT 0x9
+#define MVP_CONTROL1__MVP_ARBITRATION_MODE_FOR_AFR_MANUAL_SWITCH_MODE_MASK 0x400
+#define MVP_CONTROL1__MVP_ARBITRATION_MODE_FOR_AFR_MANUAL_SWITCH_MODE__SHIFT 0xa
+#define MVP_CONTROL1__MVP_RATE_CONTROL_MASK 0x1000
+#define MVP_CONTROL1__MVP_RATE_CONTROL__SHIFT 0xc
+#define MVP_CONTROL1__MVP_CHANNEL_CONTROL_MASK 0x10000
+#define MVP_CONTROL1__MVP_CHANNEL_CONTROL__SHIFT 0x10
+#define MVP_CONTROL1__MVP_GPU_CHAIN_LOCATION_MASK 0x300000
+#define MVP_CONTROL1__MVP_GPU_CHAIN_LOCATION__SHIFT 0x14
+#define MVP_CONTROL1__MVP_DISABLE_MSB_EXPAND_MASK 0x1000000
+#define MVP_CONTROL1__MVP_DISABLE_MSB_EXPAND__SHIFT 0x18
+#define MVP_CONTROL1__MVP_30BPP_EN_MASK 0x10000000
+#define MVP_CONTROL1__MVP_30BPP_EN__SHIFT 0x1c
+#define MVP_CONTROL1__MVP_TERMINATION_CNTL_A_MASK 0x40000000
+#define MVP_CONTROL1__MVP_TERMINATION_CNTL_A__SHIFT 0x1e
+#define MVP_CONTROL1__MVP_TERMINATION_CNTL_B_MASK 0x80000000
+#define MVP_CONTROL1__MVP_TERMINATION_CNTL_B__SHIFT 0x1f
+#define MVP_CONTROL2__MVP_MUX_DE_DVOCNTL0_SEL_MASK 0x1
+#define MVP_CONTROL2__MVP_MUX_DE_DVOCNTL0_SEL__SHIFT 0x0
+#define MVP_CONTROL2__MVP_MUX_DE_DVOCNTL2_SEL_MASK 0x10
+#define MVP_CONTROL2__MVP_MUX_DE_DVOCNTL2_SEL__SHIFT 0x4
+#define MVP_CONTROL2__MVP_MUXA_CLK_SEL_MASK 0x100
+#define MVP_CONTROL2__MVP_MUXA_CLK_SEL__SHIFT 0x8
+#define MVP_CONTROL2__MVP_MUXB_CLK_SEL_MASK 0x1000
+#define MVP_CONTROL2__MVP_MUXB_CLK_SEL__SHIFT 0xc
+#define MVP_CONTROL2__MVP_DVOCNTL_MUX_MASK 0x10000
+#define MVP_CONTROL2__MVP_DVOCNTL_MUX__SHIFT 0x10
+#define MVP_CONTROL2__MVP_FLOW_CONTROL_OUT_EN_MASK 0x100000
+#define MVP_CONTROL2__MVP_FLOW_CONTROL_OUT_EN__SHIFT 0x14
+#define MVP_CONTROL2__MVP_SWAP_LOCK_OUT_EN_MASK 0x1000000
+#define MVP_CONTROL2__MVP_SWAP_LOCK_OUT_EN__SHIFT 0x18
+#define MVP_CONTROL2__MVP_SWAP_AB_IN_DC_DDR_MASK 0x10000000
+#define MVP_CONTROL2__MVP_SWAP_AB_IN_DC_DDR__SHIFT 0x1c
+#define MVP_FIFO_CONTROL__MVP_STOP_SLAVE_WM_MASK 0xff
+#define MVP_FIFO_CONTROL__MVP_STOP_SLAVE_WM__SHIFT 0x0
+#define MVP_FIFO_CONTROL__MVP_PAUSE_SLAVE_WM_MASK 0xff00
+#define MVP_FIFO_CONTROL__MVP_PAUSE_SLAVE_WM__SHIFT 0x8
+#define MVP_FIFO_CONTROL__MVP_PAUSE_SLAVE_CNT_MASK 0xff0000
+#define MVP_FIFO_CONTROL__MVP_PAUSE_SLAVE_CNT__SHIFT 0x10
+#define MVP_FIFO_STATUS__MVP_FIFO_LEVEL_MASK 0xff
+#define MVP_FIFO_STATUS__MVP_FIFO_LEVEL__SHIFT 0x0
+#define MVP_FIFO_STATUS__MVP_FIFO_OVERFLOW_MASK 0x100
+#define MVP_FIFO_STATUS__MVP_FIFO_OVERFLOW__SHIFT 0x8
+#define MVP_FIFO_STATUS__MVP_FIFO_OVERFLOW_OCCURRED_MASK 0x1000
+#define MVP_FIFO_STATUS__MVP_FIFO_OVERFLOW_OCCURRED__SHIFT 0xc
+#define MVP_FIFO_STATUS__MVP_FIFO_OVERFLOW_ACK_MASK 0x10000
+#define MVP_FIFO_STATUS__MVP_FIFO_OVERFLOW_ACK__SHIFT 0x10
+#define MVP_FIFO_STATUS__MVP_FIFO_UNDERFLOW_MASK 0x100000
+#define MVP_FIFO_STATUS__MVP_FIFO_UNDERFLOW__SHIFT 0x14
+#define MVP_FIFO_STATUS__MVP_FIFO_UNDERFLOW_OCCURRED_MASK 0x1000000
+#define MVP_FIFO_STATUS__MVP_FIFO_UNDERFLOW_OCCURRED__SHIFT 0x18
+#define MVP_FIFO_STATUS__MVP_FIFO_UNDERFLOW_ACK_MASK 0x10000000
+#define MVP_FIFO_STATUS__MVP_FIFO_UNDERFLOW_ACK__SHIFT 0x1c
+#define MVP_FIFO_STATUS__MVP_FIFO_ERROR_MASK_MASK 0x40000000
+#define MVP_FIFO_STATUS__MVP_FIFO_ERROR_MASK__SHIFT 0x1e
+#define MVP_FIFO_STATUS__MVP_FIFO_ERROR_INT_STATUS_MASK 0x80000000
+#define MVP_FIFO_STATUS__MVP_FIFO_ERROR_INT_STATUS__SHIFT 0x1f
+#define MVP_SLAVE_STATUS__MVP_SLAVE_PIXELS_PER_LINE_RCVED_MASK 0x1fff
+#define MVP_SLAVE_STATUS__MVP_SLAVE_PIXELS_PER_LINE_RCVED__SHIFT 0x0
+#define MVP_SLAVE_STATUS__MVP_SLAVE_LINES_PER_FRAME_RCVED_MASK 0x1fff0000
+#define MVP_SLAVE_STATUS__MVP_SLAVE_LINES_PER_FRAME_RCVED__SHIFT 0x10
+#define MVP_INBAND_CNTL_CAP__MVP_IGNOR_INBAND_CNTL_MASK 0x1
+#define MVP_INBAND_CNTL_CAP__MVP_IGNOR_INBAND_CNTL__SHIFT 0x0
+#define MVP_INBAND_CNTL_CAP__MVP_PASSING_INBAND_CNTL_EN_MASK 0x10
+#define MVP_INBAND_CNTL_CAP__MVP_PASSING_INBAND_CNTL_EN__SHIFT 0x4
+#define MVP_INBAND_CNTL_CAP__MVP_INBAND_CNTL_CHAR_CAP_MASK 0xffffff00
+#define MVP_INBAND_CNTL_CAP__MVP_INBAND_CNTL_CHAR_CAP__SHIFT 0x8
+#define MVP_BLACK_KEYER__MVP_BLACK_KEYER_R_MASK 0x3ff
+#define MVP_BLACK_KEYER__MVP_BLACK_KEYER_R__SHIFT 0x0
+#define MVP_BLACK_KEYER__MVP_BLACK_KEYER_G_MASK 0xffc00
+#define MVP_BLACK_KEYER__MVP_BLACK_KEYER_G__SHIFT 0xa
+#define MVP_BLACK_KEYER__MVP_BLACK_KEYER_B_MASK 0x3ff00000
+#define MVP_BLACK_KEYER__MVP_BLACK_KEYER_B__SHIFT 0x14
+#define MVP_CRC_CNTL__MVP_CRC_BLUE_MASK_MASK 0xff
+#define MVP_CRC_CNTL__MVP_CRC_BLUE_MASK__SHIFT 0x0
+#define MVP_CRC_CNTL__MVP_CRC_GREEN_MASK_MASK 0xff00
+#define MVP_CRC_CNTL__MVP_CRC_GREEN_MASK__SHIFT 0x8
+#define MVP_CRC_CNTL__MVP_CRC_RED_MASK_MASK 0xff0000
+#define MVP_CRC_CNTL__MVP_CRC_RED_MASK__SHIFT 0x10
+#define MVP_CRC_CNTL__MVP_CRC_EN_MASK 0x10000000
+#define MVP_CRC_CNTL__MVP_CRC_EN__SHIFT 0x1c
+#define MVP_CRC_CNTL__MVP_CRC_CONT_EN_MASK 0x20000000
+#define MVP_CRC_CNTL__MVP_CRC_CONT_EN__SHIFT 0x1d
+#define MVP_CRC_CNTL__MVP_DC_DDR_CRC_EVEN_ODD_PIX_SEL_MASK 0x40000000
+#define MVP_CRC_CNTL__MVP_DC_DDR_CRC_EVEN_ODD_PIX_SEL__SHIFT 0x1e
+#define MVP_CRC_RESULT_BLUE_GREEN__MVP_CRC_BLUE_RESULT_MASK 0xffff
+#define MVP_CRC_RESULT_BLUE_GREEN__MVP_CRC_BLUE_RESULT__SHIFT 0x0
+#define MVP_CRC_RESULT_BLUE_GREEN__MVP_CRC_GREEN_RESULT_MASK 0xffff0000
+#define MVP_CRC_RESULT_BLUE_GREEN__MVP_CRC_GREEN_RESULT__SHIFT 0x10
+#define MVP_CRC_RESULT_RED__MVP_CRC_RED_RESULT_MASK 0xffff
+#define MVP_CRC_RESULT_RED__MVP_CRC_RED_RESULT__SHIFT 0x0
+#define MVP_CONTROL3__MVP_RESET_IN_BETWEEN_FRAMES_MASK 0x1
+#define MVP_CONTROL3__MVP_RESET_IN_BETWEEN_FRAMES__SHIFT 0x0
+#define MVP_CONTROL3__MVP_DDR_SC_AB_SEL_MASK 0x10
+#define MVP_CONTROL3__MVP_DDR_SC_AB_SEL__SHIFT 0x4
+#define MVP_CONTROL3__MVP_DDR_SC_B_START_MODE_MASK 0x100
+#define MVP_CONTROL3__MVP_DDR_SC_B_START_MODE__SHIFT 0x8
+#define MVP_CONTROL3__MVP_FLOW_CONTROL_OUT_FORCE_ONE_MASK 0x1000
+#define MVP_CONTROL3__MVP_FLOW_CONTROL_OUT_FORCE_ONE__SHIFT 0xc
+#define MVP_CONTROL3__MVP_FLOW_CONTROL_OUT_FORCE_ZERO_MASK 0x10000
+#define MVP_CONTROL3__MVP_FLOW_CONTROL_OUT_FORCE_ZERO__SHIFT 0x10
+#define MVP_CONTROL3__MVP_FLOW_CONTROL_CASCADE_EN_MASK 0x100000
+#define MVP_CONTROL3__MVP_FLOW_CONTROL_CASCADE_EN__SHIFT 0x14
+#define MVP_CONTROL3__MVP_SWAP_48BIT_EN_MASK 0x1000000
+#define MVP_CONTROL3__MVP_SWAP_48BIT_EN__SHIFT 0x18
+#define MVP_CONTROL3__MVP_FLOW_CONTROL_IN_CAP_MASK 0x10000000
+#define MVP_CONTROL3__MVP_FLOW_CONTROL_IN_CAP__SHIFT 0x1c
+#define MVP_RECEIVE_CNT_CNTL1__MVP_SLAVE_PIXEL_ERROR_CNT_MASK 0x1fff
+#define MVP_RECEIVE_CNT_CNTL1__MVP_SLAVE_PIXEL_ERROR_CNT__SHIFT 0x0
+#define MVP_RECEIVE_CNT_CNTL1__MVP_SLAVE_LINE_ERROR_CNT_MASK 0x1fff0000
+#define MVP_RECEIVE_CNT_CNTL1__MVP_SLAVE_LINE_ERROR_CNT__SHIFT 0x10
+#define MVP_RECEIVE_CNT_CNTL1__MVP_SLAVE_DATA_CHK_EN_MASK 0x80000000
+#define MVP_RECEIVE_CNT_CNTL1__MVP_SLAVE_DATA_CHK_EN__SHIFT 0x1f
+#define MVP_RECEIVE_CNT_CNTL2__MVP_SLAVE_FRAME_ERROR_CNT_MASK 0x1fff
+#define MVP_RECEIVE_CNT_CNTL2__MVP_SLAVE_FRAME_ERROR_CNT__SHIFT 0x0
+#define MVP_RECEIVE_CNT_CNTL2__MVP_SLAVE_FRAME_ERROR_CNT_RESET_MASK 0x80000000
+#define MVP_RECEIVE_CNT_CNTL2__MVP_SLAVE_FRAME_ERROR_CNT_RESET__SHIFT 0x1f
+#define MVP_DEBUG__MVP_SWAP_LOCK_IN_EN_MASK 0x1
+#define MVP_DEBUG__MVP_SWAP_LOCK_IN_EN__SHIFT 0x0
+#define MVP_DEBUG__MVP_FLOW_CONTROL_IN_EN_MASK 0x2
+#define MVP_DEBUG__MVP_FLOW_CONTROL_IN_EN__SHIFT 0x1
+#define MVP_DEBUG__MVP_SWAP_LOCK_IN_SEL_MASK 0x4
+#define MVP_DEBUG__MVP_SWAP_LOCK_IN_SEL__SHIFT 0x2
+#define MVP_DEBUG__MVP_FLOW_CONTROL_IN_SEL_MASK 0x8
+#define MVP_DEBUG__MVP_FLOW_CONTROL_IN_SEL__SHIFT 0x3
+#define MVP_DEBUG__MVP_DIS_FIX_AFR_MANUAL_HSYNC_FLIP_MASK 0x10
+#define MVP_DEBUG__MVP_DIS_FIX_AFR_MANUAL_HSYNC_FLIP__SHIFT 0x4
+#define MVP_DEBUG__MVP_DIS_FIX_AFR_AUTO_VSYNC_FLIP_MASK 0x20
+#define MVP_DEBUG__MVP_DIS_FIX_AFR_AUTO_VSYNC_FLIP__SHIFT 0x5
+#define MVP_DEBUG__MVP_EN_FIX_AFR_MANUAL_SWITCH_IN_SFR_MASK 0x40
+#define MVP_DEBUG__MVP_EN_FIX_AFR_MANUAL_SWITCH_IN_SFR__SHIFT 0x6
+#define MVP_DEBUG__MVP_DIS_READ_POINTER_RESET_DELAY_MASK 0x80
+#define MVP_DEBUG__MVP_DIS_READ_POINTER_RESET_DELAY__SHIFT 0x7
+#define MVP_DEBUG__MVP_DEBUG_BITS_MASK 0xffffff00
+#define MVP_DEBUG__MVP_DEBUG_BITS__SHIFT 0x8
+#define MVP_TEST_DEBUG_INDEX__MVP_TEST_DEBUG_INDEX_MASK 0xff
+#define MVP_TEST_DEBUG_INDEX__MVP_TEST_DEBUG_INDEX__SHIFT 0x0
+#define MVP_TEST_DEBUG_INDEX__MVP_TEST_DEBUG_WRITE_EN_MASK 0x100
+#define MVP_TEST_DEBUG_INDEX__MVP_TEST_DEBUG_WRITE_EN__SHIFT 0x8
+#define MVP_TEST_DEBUG_DATA__MVP_TEST_DEBUG_DATA_MASK 0xffffffff
+#define MVP_TEST_DEBUG_DATA__MVP_TEST_DEBUG_DATA__SHIFT 0x0
+#define MVP_DEBUG_12__IDEC_MVP_DATA_A_H_MASK 0x1
+#define MVP_DEBUG_12__IDEC_MVP_DATA_A_H__SHIFT 0x0
+#define MVP_DEBUG_12__IDEC_MVP_DATA_A_MASK 0x1fffffe
+#define MVP_DEBUG_12__IDEC_MVP_DATA_A__SHIFT 0x1
+#define MVP_DEBUG_13__IDED_MVP_DATA_B_H_MASK 0x1
+#define MVP_DEBUG_13__IDED_MVP_DATA_B_H__SHIFT 0x0
+#define MVP_DEBUG_13__IDED_MVP_DATA_B_MASK 0x1fffffe
+#define MVP_DEBUG_13__IDED_MVP_DATA_B__SHIFT 0x1
+#define MVP_DEBUG_13__IDED_START_READ_B_MASK 0x2000000
+#define MVP_DEBUG_13__IDED_START_READ_B__SHIFT 0x19
+#define MVP_DEBUG_13__IDED_READ_FIFO_ENTRY_DE_B_MASK 0x4000000
+#define MVP_DEBUG_13__IDED_READ_FIFO_ENTRY_DE_B__SHIFT 0x1a
+#define MVP_DEBUG_13__IDED_WRITE_ADD_B_MASK 0x38000000
+#define MVP_DEBUG_13__IDED_WRITE_ADD_B__SHIFT 0x1b
+#define MVP_DEBUG_14__IDEE_READ_ADD_MASK 0x7
+#define MVP_DEBUG_14__IDEE_READ_ADD__SHIFT 0x0
+#define MVP_DEBUG_14__IDEE_WRITE_ADD_A_MASK 0x38
+#define MVP_DEBUG_14__IDEE_WRITE_ADD_A__SHIFT 0x3
+#define MVP_DEBUG_14__IDEE_WRITE_ADD_B_MASK 0x1c0
+#define MVP_DEBUG_14__IDEE_WRITE_ADD_B__SHIFT 0x6
+#define MVP_DEBUG_14__IDEE_START_READ_MASK 0x200
+#define MVP_DEBUG_14__IDEE_START_READ__SHIFT 0x9
+#define MVP_DEBUG_14__IDEE_START_READ_B_MASK 0x400
+#define MVP_DEBUG_14__IDEE_START_READ_B__SHIFT 0xa
+#define MVP_DEBUG_14__IDEE_START_INCR_WR_A_MASK 0x800
+#define MVP_DEBUG_14__IDEE_START_INCR_WR_A__SHIFT 0xb
+#define MVP_DEBUG_14__IDEE_START_INCR_WR_B_MASK 0x1000
+#define MVP_DEBUG_14__IDEE_START_INCR_WR_B__SHIFT 0xc
+#define MVP_DEBUG_14__IDEE_WRITE2FIFO_MASK 0x2000
+#define MVP_DEBUG_14__IDEE_WRITE2FIFO__SHIFT 0xd
+#define MVP_DEBUG_14__IDEE_READ_FIFO_ENTRY_DE_MASK 0x4000
+#define MVP_DEBUG_14__IDEE_READ_FIFO_ENTRY_DE__SHIFT 0xe
+#define MVP_DEBUG_14__IDEE_READ_FIFO_ENTRY_DE_B_MASK 0x8000
+#define MVP_DEBUG_14__IDEE_READ_FIFO_ENTRY_DE_B__SHIFT 0xf
+#define MVP_DEBUG_14__IDEE_READ_FIFO_DE_MASK 0x10000
+#define MVP_DEBUG_14__IDEE_READ_FIFO_DE__SHIFT 0x10
+#define MVP_DEBUG_14__IDEE_READ_FIFO_DE_B_MASK 0x20000
+#define MVP_DEBUG_14__IDEE_READ_FIFO_DE_B__SHIFT 0x11
+#define MVP_DEBUG_14__IDEE_READ_FIFO_ENABLE_MASK 0x40000
+#define MVP_DEBUG_14__IDEE_READ_FIFO_ENABLE__SHIFT 0x12
+#define MVP_DEBUG_14__IDEE_CRTC1_CNTL_CAPTURE_START_A_MASK 0x80000
+#define MVP_DEBUG_14__IDEE_CRTC1_CNTL_CAPTURE_START_A__SHIFT 0x13
+#define MVP_DEBUG_14__IDEE_CRC_PHASE_MASK 0x100000
+#define MVP_DEBUG_14__IDEE_CRC_PHASE__SHIFT 0x14
+#define MVP_DEBUG_15__IDEF_MVP_ASYNC_FIFO_WEN_MASK 0x1
+#define MVP_DEBUG_15__IDEF_MVP_ASYNC_FIFO_WEN__SHIFT 0x0
+#define MVP_DEBUG_15__IDEF_MVP_ASYNC_FIFO_WDATA_MASK 0xfffffff0
+#define MVP_DEBUG_15__IDEF_MVP_ASYNC_FIFO_WDATA__SHIFT 0x4
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_FIFO_READ_MASK 0x1
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_FIFO_READ__SHIFT 0x0
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_FIFO_EXCEED_STOP_LEVEL_MASK 0x2
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_FIFO_EXCEED_STOP_LEVEL__SHIFT 0x1
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_FIFO_EXCEED_PAUSE_LEVEL_MASK 0x4
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_FIFO_EXCEED_PAUSE_LEVEL__SHIFT 0x2
+#define MVP_DEBUG_16__IDCC_FLOW_CONTROL_OUT_MASK 0x8
+#define MVP_DEBUG_16__IDCC_FLOW_CONTROL_OUT__SHIFT 0x3
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_FIFO_NUM_ENTRIES_MASK 0xff0
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_FIFO_NUM_ENTRIES__SHIFT 0x4
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_FIFO_OVERFLOW_MASK 0x1000
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_FIFO_OVERFLOW__SHIFT 0xc
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_FIFO_UNDERFLOW_MASK 0x2000
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_FIFO_UNDERFLOW__SHIFT 0xd
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_READ_ADDR_MASK 0xff0000
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_READ_ADDR__SHIFT 0x10
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_WRITE_ADDR_MASK 0xff000000
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_WRITE_ADDR__SHIFT 0x18
+#define MVP_DEBUG_17__IDCD_MVP_ASYNC_FIFO_READ_MASK 0x1
+#define MVP_DEBUG_17__IDCD_MVP_ASYNC_FIFO_READ__SHIFT 0x0
+#define MVP_DEBUG_17__IDCD_MVP_ASYNC_FIFO_PHASE_MASK 0x2
+#define MVP_DEBUG_17__IDCD_MVP_ASYNC_FIFO_PHASE__SHIFT 0x1
+#define MVP_DEBUG_17__IDCD_MVP_ASYNC_FIFO_READ_DATA_MASK 0xfffffffc
+#define MVP_DEBUG_17__IDCD_MVP_ASYNC_FIFO_READ_DATA__SHIFT 0x2
+#define SCL_COEF_RAM_SELECT__SCL_C_RAM_TAP_PAIR_IDX_MASK 0xf
+#define SCL_COEF_RAM_SELECT__SCL_C_RAM_TAP_PAIR_IDX__SHIFT 0x0
+#define SCL_COEF_RAM_SELECT__SCL_C_RAM_PHASE_MASK 0xf00
+#define SCL_COEF_RAM_SELECT__SCL_C_RAM_PHASE__SHIFT 0x8
+#define SCL_COEF_RAM_SELECT__SCL_C_RAM_FILTER_TYPE_MASK 0x70000
+#define SCL_COEF_RAM_SELECT__SCL_C_RAM_FILTER_TYPE__SHIFT 0x10
+#define SCL_COEF_RAM_TAP_DATA__SCL_C_RAM_EVEN_TAP_COEF_MASK 0x3fff
+#define SCL_COEF_RAM_TAP_DATA__SCL_C_RAM_EVEN_TAP_COEF__SHIFT 0x0
+#define SCL_COEF_RAM_TAP_DATA__SCL_C_RAM_EVEN_TAP_COEF_EN_MASK 0x8000
+#define SCL_COEF_RAM_TAP_DATA__SCL_C_RAM_EVEN_TAP_COEF_EN__SHIFT 0xf
+#define SCL_COEF_RAM_TAP_DATA__SCL_C_RAM_ODD_TAP_COEF_MASK 0x3fff0000
+#define SCL_COEF_RAM_TAP_DATA__SCL_C_RAM_ODD_TAP_COEF__SHIFT 0x10
+#define SCL_COEF_RAM_TAP_DATA__SCL_C_RAM_ODD_TAP_COEF_EN_MASK 0x80000000
+#define SCL_COEF_RAM_TAP_DATA__SCL_C_RAM_ODD_TAP_COEF_EN__SHIFT 0x1f
+#define SCL_MODE__SCL_MODE_MASK 0x3
+#define SCL_MODE__SCL_MODE__SHIFT 0x0
+#define SCL_MODE__SCL_PSCL_EN_MASK 0x10
+#define SCL_MODE__SCL_PSCL_EN__SHIFT 0x4
+#define SCL_TAP_CONTROL__SCL_V_NUM_OF_TAPS_MASK 0x7
+#define SCL_TAP_CONTROL__SCL_V_NUM_OF_TAPS__SHIFT 0x0
+#define SCL_TAP_CONTROL__SCL_H_NUM_OF_TAPS_MASK 0xf00
+#define SCL_TAP_CONTROL__SCL_H_NUM_OF_TAPS__SHIFT 0x8
+#define SCL_CONTROL__SCL_BOUNDARY_MODE_MASK 0x1
+#define SCL_CONTROL__SCL_BOUNDARY_MODE__SHIFT 0x0
+#define SCL_CONTROL__SCL_EARLY_EOL_MODE_MASK 0x10
+#define SCL_CONTROL__SCL_EARLY_EOL_MODE__SHIFT 0x4
+#define SCL_BYPASS_CONTROL__SCL_BYPASS_MODE_MASK 0x3
+#define SCL_BYPASS_CONTROL__SCL_BYPASS_MODE__SHIFT 0x0
+#define SCL_MANUAL_REPLICATE_CONTROL__SCL_V_MANUAL_REPLICATE_FACTOR_MASK 0xf
+#define SCL_MANUAL_REPLICATE_CONTROL__SCL_V_MANUAL_REPLICATE_FACTOR__SHIFT 0x0
+#define SCL_MANUAL_REPLICATE_CONTROL__SCL_H_MANUAL_REPLICATE_FACTOR_MASK 0xf00
+#define SCL_MANUAL_REPLICATE_CONTROL__SCL_H_MANUAL_REPLICATE_FACTOR__SHIFT 0x8
+#define SCL_AUTOMATIC_MODE_CONTROL__SCL_V_CALC_AUTO_RATIO_EN_MASK 0x1
+#define SCL_AUTOMATIC_MODE_CONTROL__SCL_V_CALC_AUTO_RATIO_EN__SHIFT 0x0
+#define SCL_AUTOMATIC_MODE_CONTROL__SCL_H_CALC_AUTO_RATIO_EN_MASK 0x10000
+#define SCL_AUTOMATIC_MODE_CONTROL__SCL_H_CALC_AUTO_RATIO_EN__SHIFT 0x10
+#define SCL_HORZ_FILTER_CONTROL__SCL_H_FILTER_PICK_NEAREST_MASK 0x1
+#define SCL_HORZ_FILTER_CONTROL__SCL_H_FILTER_PICK_NEAREST__SHIFT 0x0
+#define SCL_HORZ_FILTER_CONTROL__SCL_H_2TAP_HARDCODE_COEF_EN_MASK 0x100
+#define SCL_HORZ_FILTER_CONTROL__SCL_H_2TAP_HARDCODE_COEF_EN__SHIFT 0x8
+#define SCL_HORZ_FILTER_SCALE_RATIO__SCL_H_SCALE_RATIO_MASK 0x3ffffff
+#define SCL_HORZ_FILTER_SCALE_RATIO__SCL_H_SCALE_RATIO__SHIFT 0x0
+#define SCL_HORZ_FILTER_INIT__SCL_H_INIT_FRAC_MASK 0xffffff
+#define SCL_HORZ_FILTER_INIT__SCL_H_INIT_FRAC__SHIFT 0x0
+#define SCL_HORZ_FILTER_INIT__SCL_H_INIT_INT_MASK 0xf000000
+#define SCL_HORZ_FILTER_INIT__SCL_H_INIT_INT__SHIFT 0x18
+#define SCL_VERT_FILTER_CONTROL__SCL_V_FILTER_PICK_NEAREST_MASK 0x1
+#define SCL_VERT_FILTER_CONTROL__SCL_V_FILTER_PICK_NEAREST__SHIFT 0x0
+#define SCL_VERT_FILTER_CONTROL__SCL_V_2TAP_HARDCODE_COEF_EN_MASK 0x100
+#define SCL_VERT_FILTER_CONTROL__SCL_V_2TAP_HARDCODE_COEF_EN__SHIFT 0x8
+#define SCL_VERT_FILTER_SCALE_RATIO__SCL_V_SCALE_RATIO_MASK 0x3ffffff
+#define SCL_VERT_FILTER_SCALE_RATIO__SCL_V_SCALE_RATIO__SHIFT 0x0
+#define SCL_VERT_FILTER_INIT__SCL_V_INIT_FRAC_MASK 0xffffff
+#define SCL_VERT_FILTER_INIT__SCL_V_INIT_FRAC__SHIFT 0x0
+#define SCL_VERT_FILTER_INIT__SCL_V_INIT_INT_MASK 0x7000000
+#define SCL_VERT_FILTER_INIT__SCL_V_INIT_INT__SHIFT 0x18
+#define SCL_VERT_FILTER_INIT_BOT__SCL_V_INIT_FRAC_BOT_MASK 0xffffff
+#define SCL_VERT_FILTER_INIT_BOT__SCL_V_INIT_FRAC_BOT__SHIFT 0x0
+#define SCL_VERT_FILTER_INIT_BOT__SCL_V_INIT_INT_BOT_MASK 0x7000000
+#define SCL_VERT_FILTER_INIT_BOT__SCL_V_INIT_INT_BOT__SHIFT 0x18
+#define SCL_ROUND_OFFSET__SCL_ROUND_OFFSET_RGB_Y_MASK 0xffff
+#define SCL_ROUND_OFFSET__SCL_ROUND_OFFSET_RGB_Y__SHIFT 0x0
+#define SCL_ROUND_OFFSET__SCL_ROUND_OFFSET_CBCR_MASK 0xffff0000
+#define SCL_ROUND_OFFSET__SCL_ROUND_OFFSET_CBCR__SHIFT 0x10
+#define SCL_UPDATE__SCL_UPDATE_PENDING_MASK 0x1
+#define SCL_UPDATE__SCL_UPDATE_PENDING__SHIFT 0x0
+#define SCL_UPDATE__SCL_UPDATE_TAKEN_MASK 0x100
+#define SCL_UPDATE__SCL_UPDATE_TAKEN__SHIFT 0x8
+#define SCL_UPDATE__SCL_UPDATE_LOCK_MASK 0x10000
+#define SCL_UPDATE__SCL_UPDATE_LOCK__SHIFT 0x10
+#define SCL_UPDATE__SCL_COEF_UPDATE_COMPLETE_MASK 0x1000000
+#define SCL_UPDATE__SCL_COEF_UPDATE_COMPLETE__SHIFT 0x18
+#define SCL_F_SHARP_CONTROL__SCL_HF_SHARP_SCALE_FACTOR_MASK 0x7
+#define SCL_F_SHARP_CONTROL__SCL_HF_SHARP_SCALE_FACTOR__SHIFT 0x0
+#define SCL_F_SHARP_CONTROL__SCL_HF_SHARP_EN_MASK 0x10
+#define SCL_F_SHARP_CONTROL__SCL_HF_SHARP_EN__SHIFT 0x4
+#define SCL_F_SHARP_CONTROL__SCL_VF_SHARP_SCALE_FACTOR_MASK 0x700
+#define SCL_F_SHARP_CONTROL__SCL_VF_SHARP_SCALE_FACTOR__SHIFT 0x8
+#define SCL_F_SHARP_CONTROL__SCL_VF_SHARP_EN_MASK 0x1000
+#define SCL_F_SHARP_CONTROL__SCL_VF_SHARP_EN__SHIFT 0xc
+#define SCL_ALU_CONTROL__SCL_ALU_DISABLE_MASK 0x1
+#define SCL_ALU_CONTROL__SCL_ALU_DISABLE__SHIFT 0x0
+#define SCL_COEF_RAM_CONFLICT_STATUS__SCL_HOST_CONFLICT_FLAG_MASK 0x1
+#define SCL_COEF_RAM_CONFLICT_STATUS__SCL_HOST_CONFLICT_FLAG__SHIFT 0x0
+#define SCL_COEF_RAM_CONFLICT_STATUS__SCL_HOST_CONFLICT_ACK_MASK 0x100
+#define SCL_COEF_RAM_CONFLICT_STATUS__SCL_HOST_CONFLICT_ACK__SHIFT 0x8
+#define SCL_COEF_RAM_CONFLICT_STATUS__SCL_HOST_CONFLICT_MASK_MASK 0x1000
+#define SCL_COEF_RAM_CONFLICT_STATUS__SCL_HOST_CONFLICT_MASK__SHIFT 0xc
+#define SCL_COEF_RAM_CONFLICT_STATUS__SCL_HOST_CONFLICT_INT_STATUS_MASK 0x10000
+#define SCL_COEF_RAM_CONFLICT_STATUS__SCL_HOST_CONFLICT_INT_STATUS__SHIFT 0x10
+#define VIEWPORT_START_SECONDARY__VIEWPORT_Y_START_SECONDARY_MASK 0x3fff
+#define VIEWPORT_START_SECONDARY__VIEWPORT_Y_START_SECONDARY__SHIFT 0x0
+#define VIEWPORT_START_SECONDARY__VIEWPORT_X_START_SECONDARY_MASK 0x3fff0000
+#define VIEWPORT_START_SECONDARY__VIEWPORT_X_START_SECONDARY__SHIFT 0x10
+#define VIEWPORT_START__VIEWPORT_Y_START_MASK 0x3fff
+#define VIEWPORT_START__VIEWPORT_Y_START__SHIFT 0x0
+#define VIEWPORT_START__VIEWPORT_X_START_MASK 0x3fff0000
+#define VIEWPORT_START__VIEWPORT_X_START__SHIFT 0x10
+#define VIEWPORT_SIZE__VIEWPORT_HEIGHT_MASK 0x3fff
+#define VIEWPORT_SIZE__VIEWPORT_HEIGHT__SHIFT 0x0
+#define VIEWPORT_SIZE__VIEWPORT_WIDTH_MASK 0x3fff0000
+#define VIEWPORT_SIZE__VIEWPORT_WIDTH__SHIFT 0x10
+#define EXT_OVERSCAN_LEFT_RIGHT__EXT_OVERSCAN_RIGHT_MASK 0x1fff
+#define EXT_OVERSCAN_LEFT_RIGHT__EXT_OVERSCAN_RIGHT__SHIFT 0x0
+#define EXT_OVERSCAN_LEFT_RIGHT__EXT_OVERSCAN_LEFT_MASK 0x1fff0000
+#define EXT_OVERSCAN_LEFT_RIGHT__EXT_OVERSCAN_LEFT__SHIFT 0x10
+#define EXT_OVERSCAN_TOP_BOTTOM__EXT_OVERSCAN_BOTTOM_MASK 0x1fff
+#define EXT_OVERSCAN_TOP_BOTTOM__EXT_OVERSCAN_BOTTOM__SHIFT 0x0
+#define EXT_OVERSCAN_TOP_BOTTOM__EXT_OVERSCAN_TOP_MASK 0x1fff0000
+#define EXT_OVERSCAN_TOP_BOTTOM__EXT_OVERSCAN_TOP__SHIFT 0x10
+#define SCL_MODE_CHANGE_DET1__SCL_MODE_CHANGE_MASK 0x1
+#define SCL_MODE_CHANGE_DET1__SCL_MODE_CHANGE__SHIFT 0x0
+#define SCL_MODE_CHANGE_DET1__SCL_MODE_CHANGE_ACK_MASK 0x10
+#define SCL_MODE_CHANGE_DET1__SCL_MODE_CHANGE_ACK__SHIFT 0x4
+#define SCL_MODE_CHANGE_DET1__SCL_ALU_H_SCALE_RATIO_MASK 0xfffff80
+#define SCL_MODE_CHANGE_DET1__SCL_ALU_H_SCALE_RATIO__SHIFT 0x7
+#define SCL_MODE_CHANGE_DET2__SCL_ALU_V_SCALE_RATIO_MASK 0x1fffff
+#define SCL_MODE_CHANGE_DET2__SCL_ALU_V_SCALE_RATIO__SHIFT 0x0
+#define SCL_MODE_CHANGE_DET3__SCL_ALU_SOURCE_HEIGHT_MASK 0x3fff
+#define SCL_MODE_CHANGE_DET3__SCL_ALU_SOURCE_HEIGHT__SHIFT 0x0
+#define SCL_MODE_CHANGE_DET3__SCL_ALU_SOURCE_WIDTH_MASK 0x3fff0000
+#define SCL_MODE_CHANGE_DET3__SCL_ALU_SOURCE_WIDTH__SHIFT 0x10
+#define SCL_MODE_CHANGE_MASK__SCL_MODE_CHANGE_MASK_MASK 0x1
+#define SCL_MODE_CHANGE_MASK__SCL_MODE_CHANGE_MASK__SHIFT 0x0
+#define SCL_DEBUG2__SCL_DEBUG_REQ_MODE_MASK 0x1
+#define SCL_DEBUG2__SCL_DEBUG_REQ_MODE__SHIFT 0x0
+#define SCL_DEBUG2__SCL_DEBUG_EOF_MODE_MASK 0x6
+#define SCL_DEBUG2__SCL_DEBUG_EOF_MODE__SHIFT 0x1
+#define SCL_DEBUG2__SCL_DEBUG2_MASK 0xfffffff8
+#define SCL_DEBUG2__SCL_DEBUG2__SHIFT 0x3
+#define SCL_DEBUG__SCL_DEBUG_MASK 0xffffffff
+#define SCL_DEBUG__SCL_DEBUG__SHIFT 0x0
+#define SCL_TEST_DEBUG_INDEX__SCL_TEST_DEBUG_INDEX_MASK 0xff
+#define SCL_TEST_DEBUG_INDEX__SCL_TEST_DEBUG_INDEX__SHIFT 0x0
+#define SCL_TEST_DEBUG_INDEX__SCL_TEST_DEBUG_WRITE_EN_MASK 0x100
+#define SCL_TEST_DEBUG_INDEX__SCL_TEST_DEBUG_WRITE_EN__SHIFT 0x8
+#define SCL_TEST_DEBUG_DATA__SCL_TEST_DEBUG_DATA_MASK 0xffffffff
+#define SCL_TEST_DEBUG_DATA__SCL_TEST_DEBUG_DATA__SHIFT 0x0
+#define SCLV_COEF_RAM_SELECT__SCL_C_RAM_TAP_PAIR_IDX_MASK 0x3
+#define SCLV_COEF_RAM_SELECT__SCL_C_RAM_TAP_PAIR_IDX__SHIFT 0x0
+#define SCLV_COEF_RAM_SELECT__SCL_C_RAM_PHASE_MASK 0x7f00
+#define SCLV_COEF_RAM_SELECT__SCL_C_RAM_PHASE__SHIFT 0x8
+#define SCLV_COEF_RAM_SELECT__SCL_C_RAM_FILTER_TYPE_MASK 0x30000
+#define SCLV_COEF_RAM_SELECT__SCL_C_RAM_FILTER_TYPE__SHIFT 0x10
+#define SCLV_COEF_RAM_TAP_DATA__SCL_C_RAM_EVEN_TAP_COEF_MASK 0x3fff
+#define SCLV_COEF_RAM_TAP_DATA__SCL_C_RAM_EVEN_TAP_COEF__SHIFT 0x0
+#define SCLV_COEF_RAM_TAP_DATA__SCL_C_RAM_EVEN_TAP_COEF_EN_MASK 0x8000
+#define SCLV_COEF_RAM_TAP_DATA__SCL_C_RAM_EVEN_TAP_COEF_EN__SHIFT 0xf
+#define SCLV_COEF_RAM_TAP_DATA__SCL_C_RAM_ODD_TAP_COEF_MASK 0x3fff0000
+#define SCLV_COEF_RAM_TAP_DATA__SCL_C_RAM_ODD_TAP_COEF__SHIFT 0x10
+#define SCLV_COEF_RAM_TAP_DATA__SCL_C_RAM_ODD_TAP_COEF_EN_MASK 0x80000000
+#define SCLV_COEF_RAM_TAP_DATA__SCL_C_RAM_ODD_TAP_COEF_EN__SHIFT 0x1f
+#define SCLV_MODE__SCL_MODE_MASK 0x3
+#define SCLV_MODE__SCL_MODE__SHIFT 0x0
+#define SCLV_MODE__SCL_MODE_C_MASK 0xc
+#define SCLV_MODE__SCL_MODE_C__SHIFT 0x2
+#define SCLV_MODE__SCL_PSCL_EN_MASK 0x10
+#define SCLV_MODE__SCL_PSCL_EN__SHIFT 0x4
+#define SCLV_MODE__SCL_PSCL_EN_C_MASK 0x20
+#define SCLV_MODE__SCL_PSCL_EN_C__SHIFT 0x5
+#define SCLV_MODE__SCL_INTERLACE_SOURCE_MASK 0x300
+#define SCLV_MODE__SCL_INTERLACE_SOURCE__SHIFT 0x8
+#define SCLV_TAP_CONTROL__SCL_V_NUM_OF_TAPS_MASK 0x7
+#define SCLV_TAP_CONTROL__SCL_V_NUM_OF_TAPS__SHIFT 0x0
+#define SCLV_TAP_CONTROL__SCL_H_NUM_OF_TAPS_MASK 0x70
+#define SCLV_TAP_CONTROL__SCL_H_NUM_OF_TAPS__SHIFT 0x4
+#define SCLV_TAP_CONTROL__SCL_V_NUM_OF_TAPS_C_MASK 0x700
+#define SCLV_TAP_CONTROL__SCL_V_NUM_OF_TAPS_C__SHIFT 0x8
+#define SCLV_TAP_CONTROL__SCL_H_NUM_OF_TAPS_C_MASK 0x7000
+#define SCLV_TAP_CONTROL__SCL_H_NUM_OF_TAPS_C__SHIFT 0xc
+#define SCLV_CONTROL__SCL_BOUNDARY_MODE_MASK 0x1
+#define SCLV_CONTROL__SCL_BOUNDARY_MODE__SHIFT 0x0
+#define SCLV_CONTROL__SCL_EARLY_EOL_MODE_MASK 0x10
+#define SCLV_CONTROL__SCL_EARLY_EOL_MODE__SHIFT 0x4
+#define SCLV_CONTROL__SCL_TOTAL_PHASE_MASK 0x100
+#define SCLV_CONTROL__SCL_TOTAL_PHASE__SHIFT 0x8
+#define SCLV_MANUAL_REPLICATE_CONTROL__SCL_V_MANUAL_REPLICATE_FACTOR_MASK 0xf
+#define SCLV_MANUAL_REPLICATE_CONTROL__SCL_V_MANUAL_REPLICATE_FACTOR__SHIFT 0x0
+#define SCLV_MANUAL_REPLICATE_CONTROL__SCL_H_MANUAL_REPLICATE_FACTOR_MASK 0xf00
+#define SCLV_MANUAL_REPLICATE_CONTROL__SCL_H_MANUAL_REPLICATE_FACTOR__SHIFT 0x8
+#define SCLV_AUTOMATIC_MODE_CONTROL__SCL_V_CALC_AUTO_RATIO_EN_MASK 0x1
+#define SCLV_AUTOMATIC_MODE_CONTROL__SCL_V_CALC_AUTO_RATIO_EN__SHIFT 0x0
+#define SCLV_AUTOMATIC_MODE_CONTROL__SCL_H_CALC_AUTO_RATIO_EN_MASK 0x10000
+#define SCLV_AUTOMATIC_MODE_CONTROL__SCL_H_CALC_AUTO_RATIO_EN__SHIFT 0x10
+#define SCLV_HORZ_FILTER_CONTROL__SCL_H_2TAP_HARDCODE_COEF_EN_MASK 0x100
+#define SCLV_HORZ_FILTER_CONTROL__SCL_H_2TAP_HARDCODE_COEF_EN__SHIFT 0x8
+#define SCLV_HORZ_FILTER_SCALE_RATIO__SCL_H_SCALE_RATIO_MASK 0x3ffffff
+#define SCLV_HORZ_FILTER_SCALE_RATIO__SCL_H_SCALE_RATIO__SHIFT 0x0
+#define SCLV_HORZ_FILTER_INIT__SCL_H_INIT_FRAC_MASK 0xffffff
+#define SCLV_HORZ_FILTER_INIT__SCL_H_INIT_FRAC__SHIFT 0x0
+#define SCLV_HORZ_FILTER_INIT__SCL_H_INIT_INT_MASK 0xf000000
+#define SCLV_HORZ_FILTER_INIT__SCL_H_INIT_INT__SHIFT 0x18
+#define SCLV_HORZ_FILTER_SCALE_RATIO_C__SCL_H_SCALE_RATIO_C_MASK 0x3ffffff
+#define SCLV_HORZ_FILTER_SCALE_RATIO_C__SCL_H_SCALE_RATIO_C__SHIFT 0x0
+#define SCLV_HORZ_FILTER_INIT_C__SCL_H_INIT_FRAC_C_MASK 0xffffff
+#define SCLV_HORZ_FILTER_INIT_C__SCL_H_INIT_FRAC_C__SHIFT 0x0
+#define SCLV_HORZ_FILTER_INIT_C__SCL_H_INIT_INT_C_MASK 0xf000000
+#define SCLV_HORZ_FILTER_INIT_C__SCL_H_INIT_INT_C__SHIFT 0x18
+#define SCLV_VERT_FILTER_CONTROL__SCL_V_2TAP_HARDCODE_COEF_EN_MASK 0x100
+#define SCLV_VERT_FILTER_CONTROL__SCL_V_2TAP_HARDCODE_COEF_EN__SHIFT 0x8
+#define SCLV_VERT_FILTER_SCALE_RATIO__SCL_V_SCALE_RATIO_MASK 0x3ffffff
+#define SCLV_VERT_FILTER_SCALE_RATIO__SCL_V_SCALE_RATIO__SHIFT 0x0
+#define SCLV_VERT_FILTER_INIT__SCL_V_INIT_FRAC_MASK 0xffffff
+#define SCLV_VERT_FILTER_INIT__SCL_V_INIT_FRAC__SHIFT 0x0
+#define SCLV_VERT_FILTER_INIT__SCL_V_INIT_INT_MASK 0x7000000
+#define SCLV_VERT_FILTER_INIT__SCL_V_INIT_INT__SHIFT 0x18
+#define SCLV_VERT_FILTER_INIT_BOT__SCL_V_INIT_FRAC_BOT_MASK 0xffffff
+#define SCLV_VERT_FILTER_INIT_BOT__SCL_V_INIT_FRAC_BOT__SHIFT 0x0
+#define SCLV_VERT_FILTER_INIT_BOT__SCL_V_INIT_INT_BOT_MASK 0x7000000
+#define SCLV_VERT_FILTER_INIT_BOT__SCL_V_INIT_INT_BOT__SHIFT 0x18
+#define SCLV_VERT_FILTER_SCALE_RATIO_C__SCL_V_SCALE_RATIO_C_MASK 0x3ffffff
+#define SCLV_VERT_FILTER_SCALE_RATIO_C__SCL_V_SCALE_RATIO_C__SHIFT 0x0
+#define SCLV_VERT_FILTER_INIT_C__SCL_V_INIT_FRAC_C_MASK 0xffffff
+#define SCLV_VERT_FILTER_INIT_C__SCL_V_INIT_FRAC_C__SHIFT 0x0
+#define SCLV_VERT_FILTER_INIT_C__SCL_V_INIT_INT_C_MASK 0x7000000
+#define SCLV_VERT_FILTER_INIT_C__SCL_V_INIT_INT_C__SHIFT 0x18
+#define SCLV_VERT_FILTER_INIT_BOT_C__SCL_V_INIT_FRAC_BOT_C_MASK 0xffffff
+#define SCLV_VERT_FILTER_INIT_BOT_C__SCL_V_INIT_FRAC_BOT_C__SHIFT 0x0
+#define SCLV_VERT_FILTER_INIT_BOT_C__SCL_V_INIT_INT_BOT_C_MASK 0x7000000
+#define SCLV_VERT_FILTER_INIT_BOT_C__SCL_V_INIT_INT_BOT_C__SHIFT 0x18
+#define SCLV_ROUND_OFFSET__SCL_ROUND_OFFSET_RGB_Y_MASK 0xffff
+#define SCLV_ROUND_OFFSET__SCL_ROUND_OFFSET_RGB_Y__SHIFT 0x0
+#define SCLV_ROUND_OFFSET__SCL_ROUND_OFFSET_CBCR_MASK 0xffff0000
+#define SCLV_ROUND_OFFSET__SCL_ROUND_OFFSET_CBCR__SHIFT 0x10
+#define SCLV_UPDATE__SCL_UPDATE_PENDING_MASK 0x1
+#define SCLV_UPDATE__SCL_UPDATE_PENDING__SHIFT 0x0
+#define SCLV_UPDATE__SCL_UPDATE_TAKEN_MASK 0x100
+#define SCLV_UPDATE__SCL_UPDATE_TAKEN__SHIFT 0x8
+#define SCLV_UPDATE__SCL_UPDATE_LOCK_MASK 0x10000
+#define SCLV_UPDATE__SCL_UPDATE_LOCK__SHIFT 0x10
+#define SCLV_UPDATE__SCL_COEF_UPDATE_COMPLETE_MASK 0x1000000
+#define SCLV_UPDATE__SCL_COEF_UPDATE_COMPLETE__SHIFT 0x18
+#define SCLV_ALU_CONTROL__SCL_ALU_DISABLE_MASK 0x1
+#define SCLV_ALU_CONTROL__SCL_ALU_DISABLE__SHIFT 0x0
+#define SCLV_VIEWPORT_START__VIEWPORT_Y_START_MASK 0x3fff
+#define SCLV_VIEWPORT_START__VIEWPORT_Y_START__SHIFT 0x0
+#define SCLV_VIEWPORT_START__VIEWPORT_X_START_MASK 0x3fff0000
+#define SCLV_VIEWPORT_START__VIEWPORT_X_START__SHIFT 0x10
+#define SCLV_VIEWPORT_START_SECONDARY__VIEWPORT_Y_START_SECONDARY_MASK 0x3fff
+#define SCLV_VIEWPORT_START_SECONDARY__VIEWPORT_Y_START_SECONDARY__SHIFT 0x0
+#define SCLV_VIEWPORT_START_SECONDARY__VIEWPORT_X_START_SECONDARY_MASK 0x3fff0000
+#define SCLV_VIEWPORT_START_SECONDARY__VIEWPORT_X_START_SECONDARY__SHIFT 0x10
+#define SCLV_VIEWPORT_SIZE__VIEWPORT_HEIGHT_MASK 0x1fff
+#define SCLV_VIEWPORT_SIZE__VIEWPORT_HEIGHT__SHIFT 0x0
+#define SCLV_VIEWPORT_SIZE__VIEWPORT_WIDTH_MASK 0x1fff0000
+#define SCLV_VIEWPORT_SIZE__VIEWPORT_WIDTH__SHIFT 0x10
+#define SCLV_VIEWPORT_START_C__VIEWPORT_Y_START_C_MASK 0x3fff
+#define SCLV_VIEWPORT_START_C__VIEWPORT_Y_START_C__SHIFT 0x0
+#define SCLV_VIEWPORT_START_C__VIEWPORT_X_START_C_MASK 0x3fff0000
+#define SCLV_VIEWPORT_START_C__VIEWPORT_X_START_C__SHIFT 0x10
+#define SCLV_VIEWPORT_START_SECONDARY_C__VIEWPORT_Y_START_SECONDARY_C_MASK 0x3fff
+#define SCLV_VIEWPORT_START_SECONDARY_C__VIEWPORT_Y_START_SECONDARY_C__SHIFT 0x0
+#define SCLV_VIEWPORT_START_SECONDARY_C__VIEWPORT_X_START_SECONDARY_C_MASK 0x3fff0000
+#define SCLV_VIEWPORT_START_SECONDARY_C__VIEWPORT_X_START_SECONDARY_C__SHIFT 0x10
+#define SCLV_VIEWPORT_SIZE_C__VIEWPORT_HEIGHT_C_MASK 0x1fff
+#define SCLV_VIEWPORT_SIZE_C__VIEWPORT_HEIGHT_C__SHIFT 0x0
+#define SCLV_VIEWPORT_SIZE_C__VIEWPORT_WIDTH_C_MASK 0x1fff0000
+#define SCLV_VIEWPORT_SIZE_C__VIEWPORT_WIDTH_C__SHIFT 0x10
+#define SCLV_EXT_OVERSCAN_LEFT_RIGHT__EXT_OVERSCAN_RIGHT_MASK 0x1fff
+#define SCLV_EXT_OVERSCAN_LEFT_RIGHT__EXT_OVERSCAN_RIGHT__SHIFT 0x0
+#define SCLV_EXT_OVERSCAN_LEFT_RIGHT__EXT_OVERSCAN_LEFT_MASK 0x1fff0000
+#define SCLV_EXT_OVERSCAN_LEFT_RIGHT__EXT_OVERSCAN_LEFT__SHIFT 0x10
+#define SCLV_EXT_OVERSCAN_TOP_BOTTOM__EXT_OVERSCAN_BOTTOM_MASK 0x1fff
+#define SCLV_EXT_OVERSCAN_TOP_BOTTOM__EXT_OVERSCAN_BOTTOM__SHIFT 0x0
+#define SCLV_EXT_OVERSCAN_TOP_BOTTOM__EXT_OVERSCAN_TOP_MASK 0x1fff0000
+#define SCLV_EXT_OVERSCAN_TOP_BOTTOM__EXT_OVERSCAN_TOP__SHIFT 0x10
+#define SCLV_MODE_CHANGE_DET1__SCL_MODE_CHANGE_MASK 0x1
+#define SCLV_MODE_CHANGE_DET1__SCL_MODE_CHANGE__SHIFT 0x0
+#define SCLV_MODE_CHANGE_DET1__SCL_MODE_CHANGE_ACK_MASK 0x10
+#define SCLV_MODE_CHANGE_DET1__SCL_MODE_CHANGE_ACK__SHIFT 0x4
+#define SCLV_MODE_CHANGE_DET1__SCL_ALU_H_SCALE_RATIO_MASK 0xfffff80
+#define SCLV_MODE_CHANGE_DET1__SCL_ALU_H_SCALE_RATIO__SHIFT 0x7
+#define SCLV_MODE_CHANGE_DET2__SCL_ALU_V_SCALE_RATIO_MASK 0x1fffff
+#define SCLV_MODE_CHANGE_DET2__SCL_ALU_V_SCALE_RATIO__SHIFT 0x0
+#define SCLV_MODE_CHANGE_DET3__SCL_ALU_SOURCE_HEIGHT_MASK 0x3fff
+#define SCLV_MODE_CHANGE_DET3__SCL_ALU_SOURCE_HEIGHT__SHIFT 0x0
+#define SCLV_MODE_CHANGE_DET3__SCL_ALU_SOURCE_WIDTH_MASK 0x3fff0000
+#define SCLV_MODE_CHANGE_DET3__SCL_ALU_SOURCE_WIDTH__SHIFT 0x10
+#define SCLV_MODE_CHANGE_MASK__SCL_MODE_CHANGE_MASK_MASK 0x1
+#define SCLV_MODE_CHANGE_MASK__SCL_MODE_CHANGE_MASK__SHIFT 0x0
+#define SCLV_HORZ_FILTER_INIT_BOT__SCL_H_INIT_FRAC_BOT_MASK 0xffffff
+#define SCLV_HORZ_FILTER_INIT_BOT__SCL_H_INIT_FRAC_BOT__SHIFT 0x0
+#define SCLV_HORZ_FILTER_INIT_BOT__SCL_H_INIT_INT_BOT_MASK 0xf000000
+#define SCLV_HORZ_FILTER_INIT_BOT__SCL_H_INIT_INT_BOT__SHIFT 0x18
+#define SCLV_HORZ_FILTER_INIT_BOT_C__SCL_H_INIT_FRAC_BOT_C_MASK 0xffffff
+#define SCLV_HORZ_FILTER_INIT_BOT_C__SCL_H_INIT_FRAC_BOT_C__SHIFT 0x0
+#define SCLV_HORZ_FILTER_INIT_BOT_C__SCL_H_INIT_INT_BOT_C_MASK 0xf000000
+#define SCLV_HORZ_FILTER_INIT_BOT_C__SCL_H_INIT_INT_BOT_C__SHIFT 0x18
+#define SCLV_DEBUG2__SCL_DEBUG_REQ_MODE_MASK 0x1
+#define SCLV_DEBUG2__SCL_DEBUG_REQ_MODE__SHIFT 0x0
+#define SCLV_DEBUG2__SCL_DEBUG_EOF_MODE_MASK 0x6
+#define SCLV_DEBUG2__SCL_DEBUG_EOF_MODE__SHIFT 0x1
+#define SCLV_DEBUG2__SCL_DEBUG2_MASK 0xfffffff8
+#define SCLV_DEBUG2__SCL_DEBUG2__SHIFT 0x3
+#define SCLV_DEBUG__SCL_DEBUG_MASK 0xffffffff
+#define SCLV_DEBUG__SCL_DEBUG__SHIFT 0x0
+#define SCLV_TEST_DEBUG_INDEX__SCL_TEST_DEBUG_INDEX_MASK 0xff
+#define SCLV_TEST_DEBUG_INDEX__SCL_TEST_DEBUG_INDEX__SHIFT 0x0
+#define SCLV_TEST_DEBUG_INDEX__SCL_TEST_DEBUG_WRITE_EN_MASK 0x100
+#define SCLV_TEST_DEBUG_INDEX__SCL_TEST_DEBUG_WRITE_EN__SHIFT 0x8
+#define SCLV_TEST_DEBUG_DATA__SCL_TEST_DEBUG_DATA_MASK 0xffffffff
+#define SCLV_TEST_DEBUG_DATA__SCL_TEST_DEBUG_DATA__SHIFT 0x0
+#define COL_MAN_UPDATE__COL_MAN_UPDATE_PENDING_MASK 0x1
+#define COL_MAN_UPDATE__COL_MAN_UPDATE_PENDING__SHIFT 0x0
+#define COL_MAN_UPDATE__COL_MAN_UPDATE_TAKEN_MASK 0x2
+#define COL_MAN_UPDATE__COL_MAN_UPDATE_TAKEN__SHIFT 0x1
+#define COL_MAN_UPDATE__COL_MAN_UPDATE_LOCK_MASK 0x10000
+#define COL_MAN_UPDATE__COL_MAN_UPDATE_LOCK__SHIFT 0x10
+#define COL_MAN_UPDATE__COL_MAN_DISABLE_MULTIPLE_UPDATE_MASK 0x1000000
+#define COL_MAN_UPDATE__COL_MAN_DISABLE_MULTIPLE_UPDATE__SHIFT 0x18
+#define COL_MAN_INPUT_CSC_CONTROL__INPUT_CSC_MODE_MASK 0x3
+#define COL_MAN_INPUT_CSC_CONTROL__INPUT_CSC_MODE__SHIFT 0x0
+#define COL_MAN_INPUT_CSC_CONTROL__INPUT_CSC_INPUT_TYPE_MASK 0x300
+#define COL_MAN_INPUT_CSC_CONTROL__INPUT_CSC_INPUT_TYPE__SHIFT 0x8
+#define COL_MAN_INPUT_CSC_CONTROL__INPUT_CSC_CONVERSION_MODE_MASK 0x10000
+#define COL_MAN_INPUT_CSC_CONTROL__INPUT_CSC_CONVERSION_MODE__SHIFT 0x10
+#define INPUT_CSC_C11_C12_A__INPUT_CSC_C11_A_MASK 0xffff
+#define INPUT_CSC_C11_C12_A__INPUT_CSC_C11_A__SHIFT 0x0
+#define INPUT_CSC_C11_C12_A__INPUT_CSC_C12_A_MASK 0xffff0000
+#define INPUT_CSC_C11_C12_A__INPUT_CSC_C12_A__SHIFT 0x10
+#define INPUT_CSC_C13_C14_A__INPUT_CSC_C13_A_MASK 0xffff
+#define INPUT_CSC_C13_C14_A__INPUT_CSC_C13_A__SHIFT 0x0
+#define INPUT_CSC_C13_C14_A__INPUT_CSC_C14_A_MASK 0xffff0000
+#define INPUT_CSC_C13_C14_A__INPUT_CSC_C14_A__SHIFT 0x10
+#define INPUT_CSC_C21_C22_A__INPUT_CSC_C21_A_MASK 0xffff
+#define INPUT_CSC_C21_C22_A__INPUT_CSC_C21_A__SHIFT 0x0
+#define INPUT_CSC_C21_C22_A__INPUT_CSC_C22_A_MASK 0xffff0000
+#define INPUT_CSC_C21_C22_A__INPUT_CSC_C22_A__SHIFT 0x10
+#define INPUT_CSC_C23_C24_A__INPUT_CSC_C23_A_MASK 0xffff
+#define INPUT_CSC_C23_C24_A__INPUT_CSC_C23_A__SHIFT 0x0
+#define INPUT_CSC_C23_C24_A__INPUT_CSC_C24_A_MASK 0xffff0000
+#define INPUT_CSC_C23_C24_A__INPUT_CSC_C24_A__SHIFT 0x10
+#define INPUT_CSC_C31_C32_A__INPUT_CSC_C31_A_MASK 0xffff
+#define INPUT_CSC_C31_C32_A__INPUT_CSC_C31_A__SHIFT 0x0
+#define INPUT_CSC_C31_C32_A__INPUT_CSC_C32_A_MASK 0xffff0000
+#define INPUT_CSC_C31_C32_A__INPUT_CSC_C32_A__SHIFT 0x10
+#define INPUT_CSC_C33_C34_A__INPUT_CSC_C33_A_MASK 0xffff
+#define INPUT_CSC_C33_C34_A__INPUT_CSC_C33_A__SHIFT 0x0
+#define INPUT_CSC_C33_C34_A__INPUT_CSC_C34_A_MASK 0xffff0000
+#define INPUT_CSC_C33_C34_A__INPUT_CSC_C34_A__SHIFT 0x10
+#define INPUT_CSC_C11_C12_B__INPUT_CSC_C11_B_MASK 0xffff
+#define INPUT_CSC_C11_C12_B__INPUT_CSC_C11_B__SHIFT 0x0
+#define INPUT_CSC_C11_C12_B__INPUT_CSC_C12_B_MASK 0xffff0000
+#define INPUT_CSC_C11_C12_B__INPUT_CSC_C12_B__SHIFT 0x10
+#define INPUT_CSC_C13_C14_B__INPUT_CSC_C13_B_MASK 0xffff
+#define INPUT_CSC_C13_C14_B__INPUT_CSC_C13_B__SHIFT 0x0
+#define INPUT_CSC_C13_C14_B__INPUT_CSC_C14_B_MASK 0xffff0000
+#define INPUT_CSC_C13_C14_B__INPUT_CSC_C14_B__SHIFT 0x10
+#define INPUT_CSC_C21_C22_B__INPUT_CSC_C21_B_MASK 0xffff
+#define INPUT_CSC_C21_C22_B__INPUT_CSC_C21_B__SHIFT 0x0
+#define INPUT_CSC_C21_C22_B__INPUT_CSC_C22_B_MASK 0xffff0000
+#define INPUT_CSC_C21_C22_B__INPUT_CSC_C22_B__SHIFT 0x10
+#define INPUT_CSC_C23_C24_B__INPUT_CSC_C23_B_MASK 0xffff
+#define INPUT_CSC_C23_C24_B__INPUT_CSC_C23_B__SHIFT 0x0
+#define INPUT_CSC_C23_C24_B__INPUT_CSC_C24_B_MASK 0xffff0000
+#define INPUT_CSC_C23_C24_B__INPUT_CSC_C24_B__SHIFT 0x10
+#define INPUT_CSC_C31_C32_B__INPUT_CSC_C31_B_MASK 0xffff
+#define INPUT_CSC_C31_C32_B__INPUT_CSC_C31_B__SHIFT 0x0
+#define INPUT_CSC_C31_C32_B__INPUT_CSC_C32_B_MASK 0xffff0000
+#define INPUT_CSC_C31_C32_B__INPUT_CSC_C32_B__SHIFT 0x10
+#define INPUT_CSC_C33_C34_B__INPUT_CSC_C33_B_MASK 0xffff
+#define INPUT_CSC_C33_C34_B__INPUT_CSC_C33_B__SHIFT 0x0
+#define INPUT_CSC_C33_C34_B__INPUT_CSC_C34_B_MASK 0xffff0000
+#define INPUT_CSC_C33_C34_B__INPUT_CSC_C34_B__SHIFT 0x10
+#define PRESCALE_CONTROL__PRESCALE_MODE_MASK 0x3
+#define PRESCALE_CONTROL__PRESCALE_MODE__SHIFT 0x0
+#define PRESCALE_VALUES_R__PRESCALE_BIAS_R_MASK 0xffff
+#define PRESCALE_VALUES_R__PRESCALE_BIAS_R__SHIFT 0x0
+#define PRESCALE_VALUES_R__PRESCALE_SCALE_R_MASK 0xffff0000
+#define PRESCALE_VALUES_R__PRESCALE_SCALE_R__SHIFT 0x10
+#define PRESCALE_VALUES_G__PRESCALE_BIAS_G_MASK 0xffff
+#define PRESCALE_VALUES_G__PRESCALE_BIAS_G__SHIFT 0x0
+#define PRESCALE_VALUES_G__PRESCALE_SCALE_G_MASK 0xffff0000
+#define PRESCALE_VALUES_G__PRESCALE_SCALE_G__SHIFT 0x10
+#define PRESCALE_VALUES_B__PRESCALE_BIAS_B_MASK 0xffff
+#define PRESCALE_VALUES_B__PRESCALE_BIAS_B__SHIFT 0x0
+#define PRESCALE_VALUES_B__PRESCALE_SCALE_B_MASK 0xffff0000
+#define PRESCALE_VALUES_B__PRESCALE_SCALE_B__SHIFT 0x10
+#define COL_MAN_OUTPUT_CSC_CONTROL__OUTPUT_CSC_MODE_MASK 0x7
+#define COL_MAN_OUTPUT_CSC_CONTROL__OUTPUT_CSC_MODE__SHIFT 0x0
+#define OUTPUT_CSC_C11_C12_A__OUTPUT_CSC_C11_A_MASK 0xffff
+#define OUTPUT_CSC_C11_C12_A__OUTPUT_CSC_C11_A__SHIFT 0x0
+#define OUTPUT_CSC_C11_C12_A__OUTPUT_CSC_C12_A_MASK 0xffff0000
+#define OUTPUT_CSC_C11_C12_A__OUTPUT_CSC_C12_A__SHIFT 0x10
+#define OUTPUT_CSC_C13_C14_A__OUTPUT_CSC_C13_A_MASK 0xffff
+#define OUTPUT_CSC_C13_C14_A__OUTPUT_CSC_C13_A__SHIFT 0x0
+#define OUTPUT_CSC_C13_C14_A__OUTPUT_CSC_C14_A_MASK 0xffff0000
+#define OUTPUT_CSC_C13_C14_A__OUTPUT_CSC_C14_A__SHIFT 0x10
+#define OUTPUT_CSC_C21_C22_A__OUTPUT_CSC_C21_A_MASK 0xffff
+#define OUTPUT_CSC_C21_C22_A__OUTPUT_CSC_C21_A__SHIFT 0x0
+#define OUTPUT_CSC_C21_C22_A__OUTPUT_CSC_C22_A_MASK 0xffff0000
+#define OUTPUT_CSC_C21_C22_A__OUTPUT_CSC_C22_A__SHIFT 0x10
+#define OUTPUT_CSC_C23_C24_A__OUTPUT_CSC_C23_A_MASK 0xffff
+#define OUTPUT_CSC_C23_C24_A__OUTPUT_CSC_C23_A__SHIFT 0x0
+#define OUTPUT_CSC_C23_C24_A__OUTPUT_CSC_C24_A_MASK 0xffff0000
+#define OUTPUT_CSC_C23_C24_A__OUTPUT_CSC_C24_A__SHIFT 0x10
+#define OUTPUT_CSC_C31_C32_A__OUTPUT_CSC_C31_A_MASK 0xffff
+#define OUTPUT_CSC_C31_C32_A__OUTPUT_CSC_C31_A__SHIFT 0x0
+#define OUTPUT_CSC_C31_C32_A__OUTPUT_CSC_C32_A_MASK 0xffff0000
+#define OUTPUT_CSC_C31_C32_A__OUTPUT_CSC_C32_A__SHIFT 0x10
+#define OUTPUT_CSC_C33_C34_A__OUTPUT_CSC_C33_A_MASK 0xffff
+#define OUTPUT_CSC_C33_C34_A__OUTPUT_CSC_C33_A__SHIFT 0x0
+#define OUTPUT_CSC_C33_C34_A__OUTPUT_CSC_C34_A_MASK 0xffff0000
+#define OUTPUT_CSC_C33_C34_A__OUTPUT_CSC_C34_A__SHIFT 0x10
+#define OUTPUT_CSC_C11_C12_B__OUTPUT_CSC_C11_B_MASK 0xffff
+#define OUTPUT_CSC_C11_C12_B__OUTPUT_CSC_C11_B__SHIFT 0x0
+#define OUTPUT_CSC_C11_C12_B__OUTPUT_CSC_C12_B_MASK 0xffff0000
+#define OUTPUT_CSC_C11_C12_B__OUTPUT_CSC_C12_B__SHIFT 0x10
+#define OUTPUT_CSC_C13_C14_B__OUTPUT_CSC_C13_B_MASK 0xffff
+#define OUTPUT_CSC_C13_C14_B__OUTPUT_CSC_C13_B__SHIFT 0x0
+#define OUTPUT_CSC_C13_C14_B__OUTPUT_CSC_C14_B_MASK 0xffff0000
+#define OUTPUT_CSC_C13_C14_B__OUTPUT_CSC_C14_B__SHIFT 0x10
+#define OUTPUT_CSC_C21_C22_B__OUTPUT_CSC_C21_B_MASK 0xffff
+#define OUTPUT_CSC_C21_C22_B__OUTPUT_CSC_C21_B__SHIFT 0x0
+#define OUTPUT_CSC_C21_C22_B__OUTPUT_CSC_C22_B_MASK 0xffff0000
+#define OUTPUT_CSC_C21_C22_B__OUTPUT_CSC_C22_B__SHIFT 0x10
+#define OUTPUT_CSC_C23_C24_B__OUTPUT_CSC_C23_B_MASK 0xffff
+#define OUTPUT_CSC_C23_C24_B__OUTPUT_CSC_C23_B__SHIFT 0x0
+#define OUTPUT_CSC_C23_C24_B__OUTPUT_CSC_C24_B_MASK 0xffff0000
+#define OUTPUT_CSC_C23_C24_B__OUTPUT_CSC_C24_B__SHIFT 0x10
+#define OUTPUT_CSC_C31_C32_B__OUTPUT_CSC_C31_B_MASK 0xffff
+#define OUTPUT_CSC_C31_C32_B__OUTPUT_CSC_C31_B__SHIFT 0x0
+#define OUTPUT_CSC_C31_C32_B__OUTPUT_CSC_C32_B_MASK 0xffff0000
+#define OUTPUT_CSC_C31_C32_B__OUTPUT_CSC_C32_B__SHIFT 0x10
+#define OUTPUT_CSC_C33_C34_B__OUTPUT_CSC_C33_B_MASK 0xffff
+#define OUTPUT_CSC_C33_C34_B__OUTPUT_CSC_C33_B__SHIFT 0x0
+#define OUTPUT_CSC_C33_C34_B__OUTPUT_CSC_C34_B_MASK 0xffff0000
+#define OUTPUT_CSC_C33_C34_B__OUTPUT_CSC_C34_B__SHIFT 0x10
+#define DENORM_CLAMP_CONTROL__DENORM_MODE_MASK 0x3
+#define DENORM_CLAMP_CONTROL__DENORM_MODE__SHIFT 0x0
+#define DENORM_CLAMP_CONTROL__DENORM_10BIT_OUT_MASK 0x100
+#define DENORM_CLAMP_CONTROL__DENORM_10BIT_OUT__SHIFT 0x8
+#define DENORM_CLAMP_RANGE_R_CR__RANGE_CLAMP_MAX_R_CR_MASK 0xfff
+#define DENORM_CLAMP_RANGE_R_CR__RANGE_CLAMP_MAX_R_CR__SHIFT 0x0
+#define DENORM_CLAMP_RANGE_R_CR__RANGE_CLAMP_MIN_R_CR_MASK 0xfff000
+#define DENORM_CLAMP_RANGE_R_CR__RANGE_CLAMP_MIN_R_CR__SHIFT 0xc
+#define DENORM_CLAMP_RANGE_G_Y__RANGE_CLAMP_MAX_G_Y_MASK 0xfff
+#define DENORM_CLAMP_RANGE_G_Y__RANGE_CLAMP_MAX_G_Y__SHIFT 0x0
+#define DENORM_CLAMP_RANGE_G_Y__RANGE_CLAMP_MIN_G_Y_MASK 0xfff000
+#define DENORM_CLAMP_RANGE_G_Y__RANGE_CLAMP_MIN_G_Y__SHIFT 0xc
+#define DENORM_CLAMP_RANGE_B_CB__RANGE_CLAMP_MAX_B_CB_MASK 0xfff
+#define DENORM_CLAMP_RANGE_B_CB__RANGE_CLAMP_MAX_B_CB__SHIFT 0x0
+#define DENORM_CLAMP_RANGE_B_CB__RANGE_CLAMP_MIN_B_CB_MASK 0xfff000
+#define DENORM_CLAMP_RANGE_B_CB__RANGE_CLAMP_MIN_B_CB__SHIFT 0xc
+#define COL_MAN_FP_CONVERTED_FIELD__COL_MAN_FP_CONVERTED_FIELD_DATA_MASK 0x3ffff
+#define COL_MAN_FP_CONVERTED_FIELD__COL_MAN_FP_CONVERTED_FIELD_DATA__SHIFT 0x0
+#define COL_MAN_FP_CONVERTED_FIELD__COL_MAN_FP_CONVERTED_FIELD_INDEX_MASK 0x3f00000
+#define COL_MAN_FP_CONVERTED_FIELD__COL_MAN_FP_CONVERTED_FIELD_INDEX__SHIFT 0x14
+#define GAMMA_CORR_CONTROL__GAMMA_CORR_MODE_MASK 0x3
+#define GAMMA_CORR_CONTROL__GAMMA_CORR_MODE__SHIFT 0x0
+#define GAMMA_CORR_LUT_INDEX__GAMMA_CORR_LUT_INDEX_MASK 0xff
+#define GAMMA_CORR_LUT_INDEX__GAMMA_CORR_LUT_INDEX__SHIFT 0x0
+#define GAMMA_CORR_LUT_DATA__GAMMA_CORR_LUT_DATA_MASK 0x7ffff
+#define GAMMA_CORR_LUT_DATA__GAMMA_CORR_LUT_DATA__SHIFT 0x0
+#define GAMMA_CORR_LUT_WRITE_EN_MASK__GAMMA_CORR_LUT_WRITE_EN_MASK_MASK 0x7
+#define GAMMA_CORR_LUT_WRITE_EN_MASK__GAMMA_CORR_LUT_WRITE_EN_MASK__SHIFT 0x0
+#define GAMMA_CORR_CNTLA_START_CNTL__GAMMA_CORR_CNTLA_EXP_REGION_START_MASK 0x3ffff
+#define GAMMA_CORR_CNTLA_START_CNTL__GAMMA_CORR_CNTLA_EXP_REGION_START__SHIFT 0x0
+#define GAMMA_CORR_CNTLA_START_CNTL__GAMMA_CORR_CNTLA_EXP_REGION_START_SEGMENT_MASK 0x7f00000
+#define GAMMA_CORR_CNTLA_START_CNTL__GAMMA_CORR_CNTLA_EXP_REGION_START_SEGMENT__SHIFT 0x14
+#define GAMMA_CORR_CNTLA_SLOPE_CNTL__GAMMA_CORR_CNTLA_EXP_REGION_LINEAR_SLOPE_MASK 0x3ffff
+#define GAMMA_CORR_CNTLA_SLOPE_CNTL__GAMMA_CORR_CNTLA_EXP_REGION_LINEAR_SLOPE__SHIFT 0x0
+#define GAMMA_CORR_CNTLA_END_CNTL1__GAMMA_CORR_CNTLA_EXP_REGION_END_MASK 0xffff
+#define GAMMA_CORR_CNTLA_END_CNTL1__GAMMA_CORR_CNTLA_EXP_REGION_END__SHIFT 0x0
+#define GAMMA_CORR_CNTLA_END_CNTL2__GAMMA_CORR_CNTLA_EXP_REGION_END_SLOPE_MASK 0xffff
+#define GAMMA_CORR_CNTLA_END_CNTL2__GAMMA_CORR_CNTLA_EXP_REGION_END_SLOPE__SHIFT 0x0
+#define GAMMA_CORR_CNTLA_END_CNTL2__GAMMA_CORR_CNTLA_EXP_REGION_END_BASE_MASK 0xffff0000
+#define GAMMA_CORR_CNTLA_END_CNTL2__GAMMA_CORR_CNTLA_EXP_REGION_END_BASE__SHIFT 0x10
+#define GAMMA_CORR_CNTLA_REGION_0_1__GAMMA_CORR_CNTLA_EXP_REGION0_LUT_OFFSET_MASK 0xff
+#define GAMMA_CORR_CNTLA_REGION_0_1__GAMMA_CORR_CNTLA_EXP_REGION0_LUT_OFFSET__SHIFT 0x0
+#define GAMMA_CORR_CNTLA_REGION_0_1__GAMMA_CORR_CNTLA_EXP_REGION0_NUM_SEGMENTS_MASK 0x3800
+#define GAMMA_CORR_CNTLA_REGION_0_1__GAMMA_CORR_CNTLA_EXP_REGION0_NUM_SEGMENTS__SHIFT 0xb
+#define GAMMA_CORR_CNTLA_REGION_0_1__GAMMA_CORR_CNTLA_EXP_REGION1_LUT_OFFSET_MASK 0x7f8000
+#define GAMMA_CORR_CNTLA_REGION_0_1__GAMMA_CORR_CNTLA_EXP_REGION1_LUT_OFFSET__SHIFT 0xf
+#define GAMMA_CORR_CNTLA_REGION_0_1__GAMMA_CORR_CNTLA_EXP_REGION1_NUM_SEGMENTS_MASK 0x38000000
+#define GAMMA_CORR_CNTLA_REGION_0_1__GAMMA_CORR_CNTLA_EXP_REGION1_NUM_SEGMENTS__SHIFT 0x1b
+#define GAMMA_CORR_CNTLA_REGION_2_3__GAMMA_CORR_CNTLA_EXP_REGION2_LUT_OFFSET_MASK 0xff
+#define GAMMA_CORR_CNTLA_REGION_2_3__GAMMA_CORR_CNTLA_EXP_REGION2_LUT_OFFSET__SHIFT 0x0
+#define GAMMA_CORR_CNTLA_REGION_2_3__GAMMA_CORR_CNTLA_EXP_REGION2_NUM_SEGMENTS_MASK 0x3800
+#define GAMMA_CORR_CNTLA_REGION_2_3__GAMMA_CORR_CNTLA_EXP_REGION2_NUM_SEGMENTS__SHIFT 0xb
+#define GAMMA_CORR_CNTLA_REGION_2_3__GAMMA_CORR_CNTLA_EXP_REGION3_LUT_OFFSET_MASK 0x7f8000
+#define GAMMA_CORR_CNTLA_REGION_2_3__GAMMA_CORR_CNTLA_EXP_REGION3_LUT_OFFSET__SHIFT 0xf
+#define GAMMA_CORR_CNTLA_REGION_2_3__GAMMA_CORR_CNTLA_EXP_REGION3_NUM_SEGMENTS_MASK 0x38000000
+#define GAMMA_CORR_CNTLA_REGION_2_3__GAMMA_CORR_CNTLA_EXP_REGION3_NUM_SEGMENTS__SHIFT 0x1b
+#define GAMMA_CORR_CNTLA_REGION_4_5__GAMMA_CORR_CNTLA_EXP_REGION4_LUT_OFFSET_MASK 0xff
+#define GAMMA_CORR_CNTLA_REGION_4_5__GAMMA_CORR_CNTLA_EXP_REGION4_LUT_OFFSET__SHIFT 0x0
+#define GAMMA_CORR_CNTLA_REGION_4_5__GAMMA_CORR_CNTLA_EXP_REGION4_NUM_SEGMENTS_MASK 0x3800
+#define GAMMA_CORR_CNTLA_REGION_4_5__GAMMA_CORR_CNTLA_EXP_REGION4_NUM_SEGMENTS__SHIFT 0xb
+#define GAMMA_CORR_CNTLA_REGION_4_5__GAMMA_CORR_CNTLA_EXP_REGION5_LUT_OFFSET_MASK 0x7f8000
+#define GAMMA_CORR_CNTLA_REGION_4_5__GAMMA_CORR_CNTLA_EXP_REGION5_LUT_OFFSET__SHIFT 0xf
+#define GAMMA_CORR_CNTLA_REGION_4_5__GAMMA_CORR_CNTLA_EXP_REGION5_NUM_SEGMENTS_MASK 0x38000000
+#define GAMMA_CORR_CNTLA_REGION_4_5__GAMMA_CORR_CNTLA_EXP_REGION5_NUM_SEGMENTS__SHIFT 0x1b
+#define GAMMA_CORR_CNTLA_REGION_6_7__GAMMA_CORR_CNTLA_EXP_REGION6_LUT_OFFSET_MASK 0xff
+#define GAMMA_CORR_CNTLA_REGION_6_7__GAMMA_CORR_CNTLA_EXP_REGION6_LUT_OFFSET__SHIFT 0x0
+#define GAMMA_CORR_CNTLA_REGION_6_7__GAMMA_CORR_CNTLA_EXP_REGION6_NUM_SEGMENTS_MASK 0x3800
+#define GAMMA_CORR_CNTLA_REGION_6_7__GAMMA_CORR_CNTLA_EXP_REGION6_NUM_SEGMENTS__SHIFT 0xb
+#define GAMMA_CORR_CNTLA_REGION_6_7__GAMMA_CORR_CNTLA_EXP_REGION7_LUT_OFFSET_MASK 0x7f8000
+#define GAMMA_CORR_CNTLA_REGION_6_7__GAMMA_CORR_CNTLA_EXP_REGION7_LUT_OFFSET__SHIFT 0xf
+#define GAMMA_CORR_CNTLA_REGION_6_7__GAMMA_CORR_CNTLA_EXP_REGION7_NUM_SEGMENTS_MASK 0x38000000
+#define GAMMA_CORR_CNTLA_REGION_6_7__GAMMA_CORR_CNTLA_EXP_REGION7_NUM_SEGMENTS__SHIFT 0x1b
+#define GAMMA_CORR_CNTLA_REGION_8_9__GAMMA_CORR_CNTLA_EXP_REGION8_LUT_OFFSET_MASK 0xff
+#define GAMMA_CORR_CNTLA_REGION_8_9__GAMMA_CORR_CNTLA_EXP_REGION8_LUT_OFFSET__SHIFT 0x0
+#define GAMMA_CORR_CNTLA_REGION_8_9__GAMMA_CORR_CNTLA_EXP_REGION8_NUM_SEGMENTS_MASK 0x3800
+#define GAMMA_CORR_CNTLA_REGION_8_9__GAMMA_CORR_CNTLA_EXP_REGION8_NUM_SEGMENTS__SHIFT 0xb
+#define GAMMA_CORR_CNTLA_REGION_8_9__GAMMA_CORR_CNTLA_EXP_REGION9_LUT_OFFSET_MASK 0x7f8000
+#define GAMMA_CORR_CNTLA_REGION_8_9__GAMMA_CORR_CNTLA_EXP_REGION9_LUT_OFFSET__SHIFT 0xf
+#define GAMMA_CORR_CNTLA_REGION_8_9__GAMMA_CORR_CNTLA_EXP_REGION9_NUM_SEGMENTS_MASK 0x38000000
+#define GAMMA_CORR_CNTLA_REGION_8_9__GAMMA_CORR_CNTLA_EXP_REGION9_NUM_SEGMENTS__SHIFT 0x1b
+#define GAMMA_CORR_CNTLA_REGION_10_11__GAMMA_CORR_CNTLA_EXP_REGION10_LUT_OFFSET_MASK 0xff
+#define GAMMA_CORR_CNTLA_REGION_10_11__GAMMA_CORR_CNTLA_EXP_REGION10_LUT_OFFSET__SHIFT 0x0
+#define GAMMA_CORR_CNTLA_REGION_10_11__GAMMA_CORR_CNTLA_EXP_REGION10_NUM_SEGMENTS_MASK 0x3800
+#define GAMMA_CORR_CNTLA_REGION_10_11__GAMMA_CORR_CNTLA_EXP_REGION10_NUM_SEGMENTS__SHIFT 0xb
+#define GAMMA_CORR_CNTLA_REGION_10_11__GAMMA_CORR_CNTLA_EXP_REGION11_LUT_OFFSET_MASK 0x7f8000
+#define GAMMA_CORR_CNTLA_REGION_10_11__GAMMA_CORR_CNTLA_EXP_REGION11_LUT_OFFSET__SHIFT 0xf
+#define GAMMA_CORR_CNTLA_REGION_10_11__GAMMA_CORR_CNTLA_EXP_REGION11_NUM_SEGMENTS_MASK 0x38000000
+#define GAMMA_CORR_CNTLA_REGION_10_11__GAMMA_CORR_CNTLA_EXP_REGION11_NUM_SEGMENTS__SHIFT 0x1b
+#define GAMMA_CORR_CNTLA_REGION_12_13__GAMMA_CORR_CNTLA_EXP_REGION12_LUT_OFFSET_MASK 0xff
+#define GAMMA_CORR_CNTLA_REGION_12_13__GAMMA_CORR_CNTLA_EXP_REGION12_LUT_OFFSET__SHIFT 0x0
+#define GAMMA_CORR_CNTLA_REGION_12_13__GAMMA_CORR_CNTLA_EXP_REGION12_NUM_SEGMENTS_MASK 0x3800
+#define GAMMA_CORR_CNTLA_REGION_12_13__GAMMA_CORR_CNTLA_EXP_REGION12_NUM_SEGMENTS__SHIFT 0xb
+#define GAMMA_CORR_CNTLA_REGION_12_13__GAMMA_CORR_CNTLA_EXP_REGION13_LUT_OFFSET_MASK 0x7f8000
+#define GAMMA_CORR_CNTLA_REGION_12_13__GAMMA_CORR_CNTLA_EXP_REGION13_LUT_OFFSET__SHIFT 0xf
+#define GAMMA_CORR_CNTLA_REGION_12_13__GAMMA_CORR_CNTLA_EXP_REGION13_NUM_SEGMENTS_MASK 0x38000000
+#define GAMMA_CORR_CNTLA_REGION_12_13__GAMMA_CORR_CNTLA_EXP_REGION13_NUM_SEGMENTS__SHIFT 0x1b
+#define GAMMA_CORR_CNTLA_REGION_14_15__GAMMA_CORR_CNTLA_EXP_REGION14_LUT_OFFSET_MASK 0xff
+#define GAMMA_CORR_CNTLA_REGION_14_15__GAMMA_CORR_CNTLA_EXP_REGION14_LUT_OFFSET__SHIFT 0x0
+#define GAMMA_CORR_CNTLA_REGION_14_15__GAMMA_CORR_CNTLA_EXP_REGION14_NUM_SEGMENTS_MASK 0x3800
+#define GAMMA_CORR_CNTLA_REGION_14_15__GAMMA_CORR_CNTLA_EXP_REGION14_NUM_SEGMENTS__SHIFT 0xb
+#define GAMMA_CORR_CNTLA_REGION_14_15__GAMMA_CORR_CNTLA_EXP_REGION15_LUT_OFFSET_MASK 0x7f8000
+#define GAMMA_CORR_CNTLA_REGION_14_15__GAMMA_CORR_CNTLA_EXP_REGION15_LUT_OFFSET__SHIFT 0xf
+#define GAMMA_CORR_CNTLA_REGION_14_15__GAMMA_CORR_CNTLA_EXP_REGION15_NUM_SEGMENTS_MASK 0x38000000
+#define GAMMA_CORR_CNTLA_REGION_14_15__GAMMA_CORR_CNTLA_EXP_REGION15_NUM_SEGMENTS__SHIFT 0x1b
+#define GAMMA_CORR_CNTLB_START_CNTL__GAMMA_CORR_CNTLB_EXP_REGION_START_MASK 0x3ffff
+#define GAMMA_CORR_CNTLB_START_CNTL__GAMMA_CORR_CNTLB_EXP_REGION_START__SHIFT 0x0
+#define GAMMA_CORR_CNTLB_START_CNTL__GAMMA_CORR_CNTLB_EXP_REGION_START_SEGMENT_MASK 0x7f00000
+#define GAMMA_CORR_CNTLB_START_CNTL__GAMMA_CORR_CNTLB_EXP_REGION_START_SEGMENT__SHIFT 0x14
+#define GAMMA_CORR_CNTLB_SLOPE_CNTL__GAMMA_CORR_CNTLB_EXP_REGION_LINEAR_SLOPE_MASK 0x3ffff
+#define GAMMA_CORR_CNTLB_SLOPE_CNTL__GAMMA_CORR_CNTLB_EXP_REGION_LINEAR_SLOPE__SHIFT 0x0
+#define GAMMA_CORR_CNTLB_END_CNTL1__GAMMA_CORR_CNTLB_EXP_REGION_END_MASK 0xffff
+#define GAMMA_CORR_CNTLB_END_CNTL1__GAMMA_CORR_CNTLB_EXP_REGION_END__SHIFT 0x0
+#define GAMMA_CORR_CNTLB_END_CNTL2__GAMMA_CORR_CNTLB_EXP_REGION_END_SLOPE_MASK 0xffff
+#define GAMMA_CORR_CNTLB_END_CNTL2__GAMMA_CORR_CNTLB_EXP_REGION_END_SLOPE__SHIFT 0x0
+#define GAMMA_CORR_CNTLB_END_CNTL2__GAMMA_CORR_CNTLB_EXP_REGION_END_BASE_MASK 0xffff0000
+#define GAMMA_CORR_CNTLB_END_CNTL2__GAMMA_CORR_CNTLB_EXP_REGION_END_BASE__SHIFT 0x10
+#define GAMMA_CORR_CNTLB_REGION_0_1__GAMMA_CORR_CNTLB_EXP_REGION0_LUT_OFFSET_MASK 0xff
+#define GAMMA_CORR_CNTLB_REGION_0_1__GAMMA_CORR_CNTLB_EXP_REGION0_LUT_OFFSET__SHIFT 0x0
+#define GAMMA_CORR_CNTLB_REGION_0_1__GAMMA_CORR_CNTLB_EXP_REGION0_NUM_SEGMENTS_MASK 0x3800
+#define GAMMA_CORR_CNTLB_REGION_0_1__GAMMA_CORR_CNTLB_EXP_REGION0_NUM_SEGMENTS__SHIFT 0xb
+#define GAMMA_CORR_CNTLB_REGION_0_1__GAMMA_CORR_CNTLB_EXP_REGION1_LUT_OFFSET_MASK 0x7f8000
+#define GAMMA_CORR_CNTLB_REGION_0_1__GAMMA_CORR_CNTLB_EXP_REGION1_LUT_OFFSET__SHIFT 0xf
+#define GAMMA_CORR_CNTLB_REGION_0_1__GAMMA_CORR_CNTLB_EXP_REGION1_NUM_SEGMENTS_MASK 0x38000000
+#define GAMMA_CORR_CNTLB_REGION_0_1__GAMMA_CORR_CNTLB_EXP_REGION1_NUM_SEGMENTS__SHIFT 0x1b
+#define GAMMA_CORR_CNTLB_REGION_2_3__GAMMA_CORR_CNTLB_EXP_REGION2_LUT_OFFSET_MASK 0xff
+#define GAMMA_CORR_CNTLB_REGION_2_3__GAMMA_CORR_CNTLB_EXP_REGION2_LUT_OFFSET__SHIFT 0x0
+#define GAMMA_CORR_CNTLB_REGION_2_3__GAMMA_CORR_CNTLB_EXP_REGION2_NUM_SEGMENTS_MASK 0x3800
+#define GAMMA_CORR_CNTLB_REGION_2_3__GAMMA_CORR_CNTLB_EXP_REGION2_NUM_SEGMENTS__SHIFT 0xb
+#define GAMMA_CORR_CNTLB_REGION_2_3__GAMMA_CORR_CNTLB_EXP_REGION3_LUT_OFFSET_MASK 0x7f8000
+#define GAMMA_CORR_CNTLB_REGION_2_3__GAMMA_CORR_CNTLB_EXP_REGION3_LUT_OFFSET__SHIFT 0xf
+#define GAMMA_CORR_CNTLB_REGION_2_3__GAMMA_CORR_CNTLB_EXP_REGION3_NUM_SEGMENTS_MASK 0x38000000
+#define GAMMA_CORR_CNTLB_REGION_2_3__GAMMA_CORR_CNTLB_EXP_REGION3_NUM_SEGMENTS__SHIFT 0x1b
+#define GAMMA_CORR_CNTLB_REGION_4_5__GAMMA_CORR_CNTLB_EXP_REGION4_LUT_OFFSET_MASK 0xff
+#define GAMMA_CORR_CNTLB_REGION_4_5__GAMMA_CORR_CNTLB_EXP_REGION4_LUT_OFFSET__SHIFT 0x0
+#define GAMMA_CORR_CNTLB_REGION_4_5__GAMMA_CORR_CNTLB_EXP_REGION4_NUM_SEGMENTS_MASK 0x3800
+#define GAMMA_CORR_CNTLB_REGION_4_5__GAMMA_CORR_CNTLB_EXP_REGION4_NUM_SEGMENTS__SHIFT 0xb
+#define GAMMA_CORR_CNTLB_REGION_4_5__GAMMA_CORR_CNTLB_EXP_REGION5_LUT_OFFSET_MASK 0x7f8000
+#define GAMMA_CORR_CNTLB_REGION_4_5__GAMMA_CORR_CNTLB_EXP_REGION5_LUT_OFFSET__SHIFT 0xf
+#define GAMMA_CORR_CNTLB_REGION_4_5__GAMMA_CORR_CNTLB_EXP_REGION5_NUM_SEGMENTS_MASK 0x38000000
+#define GAMMA_CORR_CNTLB_REGION_4_5__GAMMA_CORR_CNTLB_EXP_REGION5_NUM_SEGMENTS__SHIFT 0x1b
+#define GAMMA_CORR_CNTLB_REGION_6_7__GAMMA_CORR_CNTLB_EXP_REGION6_LUT_OFFSET_MASK 0xff
+#define GAMMA_CORR_CNTLB_REGION_6_7__GAMMA_CORR_CNTLB_EXP_REGION6_LUT_OFFSET__SHIFT 0x0
+#define GAMMA_CORR_CNTLB_REGION_6_7__GAMMA_CORR_CNTLB_EXP_REGION6_NUM_SEGMENTS_MASK 0x3800
+#define GAMMA_CORR_CNTLB_REGION_6_7__GAMMA_CORR_CNTLB_EXP_REGION6_NUM_SEGMENTS__SHIFT 0xb
+#define GAMMA_CORR_CNTLB_REGION_6_7__GAMMA_CORR_CNTLB_EXP_REGION7_LUT_OFFSET_MASK 0x7f8000
+#define GAMMA_CORR_CNTLB_REGION_6_7__GAMMA_CORR_CNTLB_EXP_REGION7_LUT_OFFSET__SHIFT 0xf
+#define GAMMA_CORR_CNTLB_REGION_6_7__GAMMA_CORR_CNTLB_EXP_REGION7_NUM_SEGMENTS_MASK 0x38000000
+#define GAMMA_CORR_CNTLB_REGION_6_7__GAMMA_CORR_CNTLB_EXP_REGION7_NUM_SEGMENTS__SHIFT 0x1b
+#define GAMMA_CORR_CNTLB_REGION_8_9__GAMMA_CORR_CNTLB_EXP_REGION8_LUT_OFFSET_MASK 0xff
+#define GAMMA_CORR_CNTLB_REGION_8_9__GAMMA_CORR_CNTLB_EXP_REGION8_LUT_OFFSET__SHIFT 0x0
+#define GAMMA_CORR_CNTLB_REGION_8_9__GAMMA_CORR_CNTLB_EXP_REGION8_NUM_SEGMENTS_MASK 0x3800
+#define GAMMA_CORR_CNTLB_REGION_8_9__GAMMA_CORR_CNTLB_EXP_REGION8_NUM_SEGMENTS__SHIFT 0xb
+#define GAMMA_CORR_CNTLB_REGION_8_9__GAMMA_CORR_CNTLB_EXP_REGION9_LUT_OFFSET_MASK 0x7f8000
+#define GAMMA_CORR_CNTLB_REGION_8_9__GAMMA_CORR_CNTLB_EXP_REGION9_LUT_OFFSET__SHIFT 0xf
+#define GAMMA_CORR_CNTLB_REGION_8_9__GAMMA_CORR_CNTLB_EXP_REGION9_NUM_SEGMENTS_MASK 0x38000000
+#define GAMMA_CORR_CNTLB_REGION_8_9__GAMMA_CORR_CNTLB_EXP_REGION9_NUM_SEGMENTS__SHIFT 0x1b
+#define GAMMA_CORR_CNTLB_REGION_10_11__GAMMA_CORR_CNTLB_EXP_REGION10_LUT_OFFSET_MASK 0xff
+#define GAMMA_CORR_CNTLB_REGION_10_11__GAMMA_CORR_CNTLB_EXP_REGION10_LUT_OFFSET__SHIFT 0x0
+#define GAMMA_CORR_CNTLB_REGION_10_11__GAMMA_CORR_CNTLB_EXP_REGION10_NUM_SEGMENTS_MASK 0x3800
+#define GAMMA_CORR_CNTLB_REGION_10_11__GAMMA_CORR_CNTLB_EXP_REGION10_NUM_SEGMENTS__SHIFT 0xb
+#define GAMMA_CORR_CNTLB_REGION_10_11__GAMMA_CORR_CNTLB_EXP_REGION11_LUT_OFFSET_MASK 0x7f8000
+#define GAMMA_CORR_CNTLB_REGION_10_11__GAMMA_CORR_CNTLB_EXP_REGION11_LUT_OFFSET__SHIFT 0xf
+#define GAMMA_CORR_CNTLB_REGION_10_11__GAMMA_CORR_CNTLB_EXP_REGION11_NUM_SEGMENTS_MASK 0x38000000
+#define GAMMA_CORR_CNTLB_REGION_10_11__GAMMA_CORR_CNTLB_EXP_REGION11_NUM_SEGMENTS__SHIFT 0x1b
+#define GAMMA_CORR_CNTLB_REGION_12_13__GAMMA_CORR_CNTLB_EXP_REGION12_LUT_OFFSET_MASK 0xff
+#define GAMMA_CORR_CNTLB_REGION_12_13__GAMMA_CORR_CNTLB_EXP_REGION12_LUT_OFFSET__SHIFT 0x0
+#define GAMMA_CORR_CNTLB_REGION_12_13__GAMMA_CORR_CNTLB_EXP_REGION12_NUM_SEGMENTS_MASK 0x3800
+#define GAMMA_CORR_CNTLB_REGION_12_13__GAMMA_CORR_CNTLB_EXP_REGION12_NUM_SEGMENTS__SHIFT 0xb
+#define GAMMA_CORR_CNTLB_REGION_12_13__GAMMA_CORR_CNTLB_EXP_REGION13_LUT_OFFSET_MASK 0x7f8000
+#define GAMMA_CORR_CNTLB_REGION_12_13__GAMMA_CORR_CNTLB_EXP_REGION13_LUT_OFFSET__SHIFT 0xf
+#define GAMMA_CORR_CNTLB_REGION_12_13__GAMMA_CORR_CNTLB_EXP_REGION13_NUM_SEGMENTS_MASK 0x38000000
+#define GAMMA_CORR_CNTLB_REGION_12_13__GAMMA_CORR_CNTLB_EXP_REGION13_NUM_SEGMENTS__SHIFT 0x1b
+#define GAMMA_CORR_CNTLB_REGION_14_15__GAMMA_CORR_CNTLB_EXP_REGION14_LUT_OFFSET_MASK 0xff
+#define GAMMA_CORR_CNTLB_REGION_14_15__GAMMA_CORR_CNTLB_EXP_REGION14_LUT_OFFSET__SHIFT 0x0
+#define GAMMA_CORR_CNTLB_REGION_14_15__GAMMA_CORR_CNTLB_EXP_REGION14_NUM_SEGMENTS_MASK 0x3800
+#define GAMMA_CORR_CNTLB_REGION_14_15__GAMMA_CORR_CNTLB_EXP_REGION14_NUM_SEGMENTS__SHIFT 0xb
+#define GAMMA_CORR_CNTLB_REGION_14_15__GAMMA_CORR_CNTLB_EXP_REGION15_LUT_OFFSET_MASK 0x7f8000
+#define GAMMA_CORR_CNTLB_REGION_14_15__GAMMA_CORR_CNTLB_EXP_REGION15_LUT_OFFSET__SHIFT 0xf
+#define GAMMA_CORR_CNTLB_REGION_14_15__GAMMA_CORR_CNTLB_EXP_REGION15_NUM_SEGMENTS_MASK 0x38000000
+#define GAMMA_CORR_CNTLB_REGION_14_15__GAMMA_CORR_CNTLB_EXP_REGION15_NUM_SEGMENTS__SHIFT 0x1b
+#define PACK_FIFO_ERROR__PACK_FIFO_L_UNDERFLOW_OCCURED_MASK 0x1
+#define PACK_FIFO_ERROR__PACK_FIFO_L_UNDERFLOW_OCCURED__SHIFT 0x0
+#define PACK_FIFO_ERROR__PACK_FIFO_L_UNDERFLOW_ACK_MASK 0x2
+#define PACK_FIFO_ERROR__PACK_FIFO_L_UNDERFLOW_ACK__SHIFT 0x1
+#define PACK_FIFO_ERROR__PACK_FIFO_C_UNDERFLOW_OCCURED_MASK 0x100
+#define PACK_FIFO_ERROR__PACK_FIFO_C_UNDERFLOW_OCCURED__SHIFT 0x8
+#define PACK_FIFO_ERROR__PACK_FIFO_C_UNDERFLOW_ACK_MASK 0x200
+#define PACK_FIFO_ERROR__PACK_FIFO_C_UNDERFLOW_ACK__SHIFT 0x9
+#define PACK_FIFO_ERROR__PACK_FIFO_L_OVERFLOW_OCCURED_MASK 0x10000
+#define PACK_FIFO_ERROR__PACK_FIFO_L_OVERFLOW_OCCURED__SHIFT 0x10
+#define PACK_FIFO_ERROR__PACK_FIFO_L_OVERFLOW_ACK_MASK 0x20000
+#define PACK_FIFO_ERROR__PACK_FIFO_L_OVERFLOW_ACK__SHIFT 0x11
+#define PACK_FIFO_ERROR__PACK_FIFO_C_OVERFLOW_OCCURED_MASK 0x1000000
+#define PACK_FIFO_ERROR__PACK_FIFO_C_OVERFLOW_OCCURED__SHIFT 0x18
+#define PACK_FIFO_ERROR__PACK_FIFO_C_OVERFLOW_ACK_MASK 0x2000000
+#define PACK_FIFO_ERROR__PACK_FIFO_C_OVERFLOW_ACK__SHIFT 0x19
+#define OUTPUT_FIFO_ERROR__OUTPUT_FIFO_UNDERFLOW_OCCURED_MASK 0x1
+#define OUTPUT_FIFO_ERROR__OUTPUT_FIFO_UNDERFLOW_OCCURED__SHIFT 0x0
+#define OUTPUT_FIFO_ERROR__OUTPUT_FIFO_UNDERFLOW_ACK_MASK 0x2
+#define OUTPUT_FIFO_ERROR__OUTPUT_FIFO_UNDERFLOW_ACK__SHIFT 0x1
+#define OUTPUT_FIFO_ERROR__OUTPUT_FIFO_OVERFLOW_OCCURED_MASK 0x100
+#define OUTPUT_FIFO_ERROR__OUTPUT_FIFO_OVERFLOW_OCCURED__SHIFT 0x8
+#define OUTPUT_FIFO_ERROR__OUTPUT_FIFO_OVERFLOW_ACK_MASK 0x200
+#define OUTPUT_FIFO_ERROR__OUTPUT_FIFO_OVERFLOW_ACK__SHIFT 0x9
+#define INPUT_GAMMA_LUT_AUTOFILL__INPUT_GAMMA_LUT_AUTOFILL_MASK 0x1
+#define INPUT_GAMMA_LUT_AUTOFILL__INPUT_GAMMA_LUT_AUTOFILL__SHIFT 0x0
+#define INPUT_GAMMA_LUT_AUTOFILL__INPUT_GAMMA_LUT_AUTOFILL_DONE_MASK 0x2
+#define INPUT_GAMMA_LUT_AUTOFILL__INPUT_GAMMA_LUT_AUTOFILL_DONE__SHIFT 0x1
+#define INPUT_GAMMA_LUT_RW_INDEX__INPUT_GAMMA_LUT_RW_INDEX_MASK 0xff
+#define INPUT_GAMMA_LUT_RW_INDEX__INPUT_GAMMA_LUT_RW_INDEX__SHIFT 0x0
+#define INPUT_GAMMA_LUT_SEQ_COLOR__INPUT_GAMMA_LUT_SEQ_COLOR_MASK 0xffff
+#define INPUT_GAMMA_LUT_SEQ_COLOR__INPUT_GAMMA_LUT_SEQ_COLOR__SHIFT 0x0
+#define INPUT_GAMMA_LUT_PWL_DATA__INPUT_GAMMA_LUT_BASE_MASK 0xffff
+#define INPUT_GAMMA_LUT_PWL_DATA__INPUT_GAMMA_LUT_BASE__SHIFT 0x0
+#define INPUT_GAMMA_LUT_PWL_DATA__INPUT_GAMMA_LUT_DELTA_MASK 0xffff0000
+#define INPUT_GAMMA_LUT_PWL_DATA__INPUT_GAMMA_LUT_DELTA__SHIFT 0x10
+#define INPUT_GAMMA_LUT_30_COLOR__INPUT_GAMMA_LUT_COLOR_10_BLUE_MASK 0x3ff
+#define INPUT_GAMMA_LUT_30_COLOR__INPUT_GAMMA_LUT_COLOR_10_BLUE__SHIFT 0x0
+#define INPUT_GAMMA_LUT_30_COLOR__INPUT_GAMMA_LUT_COLOR_10_GREEN_MASK 0xffc00
+#define INPUT_GAMMA_LUT_30_COLOR__INPUT_GAMMA_LUT_COLOR_10_GREEN__SHIFT 0xa
+#define INPUT_GAMMA_LUT_30_COLOR__INPUT_GAMMA_LUT_COLOR_10_RED_MASK 0x3ff00000
+#define INPUT_GAMMA_LUT_30_COLOR__INPUT_GAMMA_LUT_COLOR_10_RED__SHIFT 0x14
+#define COL_MAN_INPUT_GAMMA_CONTROL1__INPUT_GAMMA_MODE_MASK 0x3
+#define COL_MAN_INPUT_GAMMA_CONTROL1__INPUT_GAMMA_MODE__SHIFT 0x0
+#define COL_MAN_INPUT_GAMMA_CONTROL1__INPUT_GAMMA_LUT_10BIT_BYPASS_EN_MASK 0x4000000
+#define COL_MAN_INPUT_GAMMA_CONTROL1__INPUT_GAMMA_LUT_10BIT_BYPASS_EN__SHIFT 0x1a
+#define COL_MAN_INPUT_GAMMA_CONTROL2__INPUT_GAMMA_INC_B_MASK 0x1e
+#define COL_MAN_INPUT_GAMMA_CONTROL2__INPUT_GAMMA_INC_B__SHIFT 0x1
+#define COL_MAN_INPUT_GAMMA_CONTROL2__INPUT_GAMMA_DATA_B_SIGNED_EN_MASK 0x20
+#define COL_MAN_INPUT_GAMMA_CONTROL2__INPUT_GAMMA_DATA_B_SIGNED_EN__SHIFT 0x5
+#define COL_MAN_INPUT_GAMMA_CONTROL2__INPUT_GAMMA_DATA_B_FORMAT_MASK 0xc0
+#define COL_MAN_INPUT_GAMMA_CONTROL2__INPUT_GAMMA_DATA_B_FORMAT__SHIFT 0x6
+#define COL_MAN_INPUT_GAMMA_CONTROL2__INPUT_GAMMA_INC_G_MASK 0xf00
+#define COL_MAN_INPUT_GAMMA_CONTROL2__INPUT_GAMMA_INC_G__SHIFT 0x8
+#define COL_MAN_INPUT_GAMMA_CONTROL2__INPUT_GAMMA_DATA_G_SIGNED_EN_MASK 0x1000
+#define COL_MAN_INPUT_GAMMA_CONTROL2__INPUT_GAMMA_DATA_G_SIGNED_EN__SHIFT 0xc
+#define COL_MAN_INPUT_GAMMA_CONTROL2__INPUT_GAMMA_DATA_G_FORMAT_MASK 0x6000
+#define COL_MAN_INPUT_GAMMA_CONTROL2__INPUT_GAMMA_DATA_G_FORMAT__SHIFT 0xd
+#define COL_MAN_INPUT_GAMMA_CONTROL2__INPUT_GAMMA_INC_R_MASK 0x78000
+#define COL_MAN_INPUT_GAMMA_CONTROL2__INPUT_GAMMA_INC_R__SHIFT 0xf
+#define COL_MAN_INPUT_GAMMA_CONTROL2__INPUT_GAMMA_DATA_R_SIGNED_EN_MASK 0x80000
+#define COL_MAN_INPUT_GAMMA_CONTROL2__INPUT_GAMMA_DATA_R_SIGNED_EN__SHIFT 0x13
+#define COL_MAN_INPUT_GAMMA_CONTROL2__INPUT_GAMMA_DATA_R_FORMAT_MASK 0x300000
+#define COL_MAN_INPUT_GAMMA_CONTROL2__INPUT_GAMMA_DATA_R_FORMAT__SHIFT 0x14
+#define COL_MAN_INPUT_GAMMA_CONTROL2__INPUT_GAMMA_LUT_RW_MODE_MASK 0x400000
+#define COL_MAN_INPUT_GAMMA_CONTROL2__INPUT_GAMMA_LUT_RW_MODE__SHIFT 0x16
+#define COL_MAN_INPUT_GAMMA_CONTROL2__INPUT_GAMMA_LUT_WRITE_EN_MASK_MASK 0x3800000
+#define COL_MAN_INPUT_GAMMA_CONTROL2__INPUT_GAMMA_LUT_WRITE_EN_MASK__SHIFT 0x17
+#define COL_MAN_INPUT_GAMMA_CONTROL2__INPUT_GAMMA_LUT_VGA_ACCESS_ENABLE_MASK 0x4000000
+#define COL_MAN_INPUT_GAMMA_CONTROL2__INPUT_GAMMA_LUT_VGA_ACCESS_ENABLE__SHIFT 0x1a
+#define COL_MAN_INPUT_GAMMA_CONTROL2__INPUT_GAMMA_LUT_10BIT_BYPASS_DBL_BUF_EN_MASK 0x8000000
+#define COL_MAN_INPUT_GAMMA_CONTROL2__INPUT_GAMMA_LUT_10BIT_BYPASS_DBL_BUF_EN__SHIFT 0x1b
+#define INPUT_GAMMA_BW_OFFSETS_B__INPUT_GAMMA_BLACK_OFFSET_B_MASK 0xffff
+#define INPUT_GAMMA_BW_OFFSETS_B__INPUT_GAMMA_BLACK_OFFSET_B__SHIFT 0x0
+#define INPUT_GAMMA_BW_OFFSETS_B__INPUT_GAMMA_WHITE_OFFSET_B_MASK 0xffff0000
+#define INPUT_GAMMA_BW_OFFSETS_B__INPUT_GAMMA_WHITE_OFFSET_B__SHIFT 0x10
+#define INPUT_GAMMA_BW_OFFSETS_G__INPUT_GAMMA_BLACK_OFFSET_G_MASK 0xffff
+#define INPUT_GAMMA_BW_OFFSETS_G__INPUT_GAMMA_BLACK_OFFSET_G__SHIFT 0x0
+#define INPUT_GAMMA_BW_OFFSETS_G__INPUT_GAMMA_WHITE_OFFSET_G_MASK 0xffff0000
+#define INPUT_GAMMA_BW_OFFSETS_G__INPUT_GAMMA_WHITE_OFFSET_G__SHIFT 0x10
+#define INPUT_GAMMA_BW_OFFSETS_R__INPUT_GAMMA_BLACK_OFFSET_R_MASK 0xffff
+#define INPUT_GAMMA_BW_OFFSETS_R__INPUT_GAMMA_BLACK_OFFSET_R__SHIFT 0x0
+#define INPUT_GAMMA_BW_OFFSETS_R__INPUT_GAMMA_WHITE_OFFSET_R_MASK 0xffff0000
+#define INPUT_GAMMA_BW_OFFSETS_R__INPUT_GAMMA_WHITE_OFFSET_R__SHIFT 0x10
+#define COL_MAN_DEBUG_CONTROL__COL_MAN_GLOBAL_PASSTHROUGH_ENABLE_MASK 0x1
+#define COL_MAN_DEBUG_CONTROL__COL_MAN_GLOBAL_PASSTHROUGH_ENABLE__SHIFT 0x0
+#define COL_MAN_TEST_DEBUG_INDEX__COL_MAN_TEST_DEBUG_INDEX_MASK 0xff
+#define COL_MAN_TEST_DEBUG_INDEX__COL_MAN_TEST_DEBUG_INDEX__SHIFT 0x0
+#define COL_MAN_TEST_DEBUG_INDEX__COL_MAN_TEST_DEBUG_WRITE_EN_MASK 0x100
+#define COL_MAN_TEST_DEBUG_INDEX__COL_MAN_TEST_DEBUG_WRITE_EN__SHIFT 0x8
+#define COL_MAN_TEST_DEBUG_DATA__COL_MAN_TEST_DEBUG_DATA_MASK 0xffffffff
+#define COL_MAN_TEST_DEBUG_DATA__COL_MAN_TEST_DEBUG_DATA__SHIFT 0x0
+#define UNP_GRPH_ENABLE__GRPH_ENABLE_MASK 0x1
+#define UNP_GRPH_ENABLE__GRPH_ENABLE__SHIFT 0x0
+#define UNP_GRPH_CONTROL__GRPH_DEPTH_MASK 0x3
+#define UNP_GRPH_CONTROL__GRPH_DEPTH__SHIFT 0x0
+#define UNP_GRPH_CONTROL__GRPH_NUM_BANKS_MASK 0xc
+#define UNP_GRPH_CONTROL__GRPH_NUM_BANKS__SHIFT 0x2
+#define UNP_GRPH_CONTROL__GRPH_Z_MASK 0x30
+#define UNP_GRPH_CONTROL__GRPH_Z__SHIFT 0x4
+#define UNP_GRPH_CONTROL__GRPH_BANK_WIDTH_L_MASK 0xc0
+#define UNP_GRPH_CONTROL__GRPH_BANK_WIDTH_L__SHIFT 0x6
+#define UNP_GRPH_CONTROL__GRPH_FORMAT_MASK 0x700
+#define UNP_GRPH_CONTROL__GRPH_FORMAT__SHIFT 0x8
+#define UNP_GRPH_CONTROL__GRPH_BANK_HEIGHT_L_MASK 0x1800
+#define UNP_GRPH_CONTROL__GRPH_BANK_HEIGHT_L__SHIFT 0xb
+#define UNP_GRPH_CONTROL__GRPH_TILE_SPLIT_L_MASK 0xe000
+#define UNP_GRPH_CONTROL__GRPH_TILE_SPLIT_L__SHIFT 0xd
+#define UNP_GRPH_CONTROL__GRPH_ADDRESS_TRANSLATION_ENABLE_MASK 0x10000
+#define UNP_GRPH_CONTROL__GRPH_ADDRESS_TRANSLATION_ENABLE__SHIFT 0x10
+#define UNP_GRPH_CONTROL__GRPH_PRIVILEGED_ACCESS_ENABLE_MASK 0x20000
+#define UNP_GRPH_CONTROL__GRPH_PRIVILEGED_ACCESS_ENABLE__SHIFT 0x11
+#define UNP_GRPH_CONTROL__GRPH_MACRO_TILE_ASPECT_L_MASK 0xc0000
+#define UNP_GRPH_CONTROL__GRPH_MACRO_TILE_ASPECT_L__SHIFT 0x12
+#define UNP_GRPH_CONTROL__GRPH_ARRAY_MODE_MASK 0xf00000
+#define UNP_GRPH_CONTROL__GRPH_ARRAY_MODE__SHIFT 0x14
+#define UNP_GRPH_CONTROL__GRPH_PIPE_CONFIG_MASK 0x1f000000
+#define UNP_GRPH_CONTROL__GRPH_PIPE_CONFIG__SHIFT 0x18
+#define UNP_GRPH_CONTROL__GRPH_MICRO_TILE_MODE_L_MASK 0x60000000
+#define UNP_GRPH_CONTROL__GRPH_MICRO_TILE_MODE_L__SHIFT 0x1d
+#define UNP_GRPH_CONTROL__GRPH_COLOR_EXPANSION_MODE_MASK 0x80000000
+#define UNP_GRPH_CONTROL__GRPH_COLOR_EXPANSION_MODE__SHIFT 0x1f
+#define UNP_GRPH_CONTROL_C__GRPH_BANK_WIDTH_C_MASK 0xc0
+#define UNP_GRPH_CONTROL_C__GRPH_BANK_WIDTH_C__SHIFT 0x6
+#define UNP_GRPH_CONTROL_C__GRPH_BANK_HEIGHT_C_MASK 0x1800
+#define UNP_GRPH_CONTROL_C__GRPH_BANK_HEIGHT_C__SHIFT 0xb
+#define UNP_GRPH_CONTROL_C__GRPH_TILE_SPLIT_C_MASK 0xe000
+#define UNP_GRPH_CONTROL_C__GRPH_TILE_SPLIT_C__SHIFT 0xd
+#define UNP_GRPH_CONTROL_C__GRPH_MACRO_TILE_ASPECT_C_MASK 0xc0000
+#define UNP_GRPH_CONTROL_C__GRPH_MACRO_TILE_ASPECT_C__SHIFT 0x12
+#define UNP_GRPH_CONTROL_C__GRPH_MICRO_TILE_MODE_C_MASK 0x60000000
+#define UNP_GRPH_CONTROL_C__GRPH_MICRO_TILE_MODE_C__SHIFT 0x1d
+#define UNP_GRPH_CONTROL_EXP__VIDEO_FORMAT_MASK 0x7
+#define UNP_GRPH_CONTROL_EXP__VIDEO_FORMAT__SHIFT 0x0
+#define UNP_GRPH_SWAP_CNTL__GRPH_ENDIAN_SWAP_MASK 0x3
+#define UNP_GRPH_SWAP_CNTL__GRPH_ENDIAN_SWAP__SHIFT 0x0
+#define UNP_GRPH_SWAP_CNTL__GRPH_RED_CROSSBAR_MASK 0x30
+#define UNP_GRPH_SWAP_CNTL__GRPH_RED_CROSSBAR__SHIFT 0x4
+#define UNP_GRPH_SWAP_CNTL__GRPH_GREEN_CROSSBAR_MASK 0xc0
+#define UNP_GRPH_SWAP_CNTL__GRPH_GREEN_CROSSBAR__SHIFT 0x6
+#define UNP_GRPH_SWAP_CNTL__GRPH_BLUE_CROSSBAR_MASK 0x300
+#define UNP_GRPH_SWAP_CNTL__GRPH_BLUE_CROSSBAR__SHIFT 0x8
+#define UNP_GRPH_PRIMARY_SURFACE_ADDRESS_L__GRPH_PRIMARY_SURFACE_ADDRESS_L_MASK 0xffffff00
+#define UNP_GRPH_PRIMARY_SURFACE_ADDRESS_L__GRPH_PRIMARY_SURFACE_ADDRESS_L__SHIFT 0x8
+#define UNP_GRPH_PRIMARY_SURFACE_ADDRESS_C__GRPH_PRIMARY_SURFACE_ADDRESS_C_MASK 0xffffff00
+#define UNP_GRPH_PRIMARY_SURFACE_ADDRESS_C__GRPH_PRIMARY_SURFACE_ADDRESS_C__SHIFT 0x8
+#define UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L_MASK 0xff
+#define UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L__SHIFT 0x0
+#define UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C_MASK 0xff
+#define UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_C__SHIFT 0x0
+#define UNP_GRPH_PRIMARY_BOTTOM_SURFACE_ADDRESS_L__GRPH_PRIMARY_BOTTOM_SURFACE_ADDRESS_L_MASK 0xffffff00
+#define UNP_GRPH_PRIMARY_BOTTOM_SURFACE_ADDRESS_L__GRPH_PRIMARY_BOTTOM_SURFACE_ADDRESS_L__SHIFT 0x8
+#define UNP_GRPH_PRIMARY_BOTTOM_SURFACE_ADDRESS_C__GRPH_PRIMARY_BOTTOM_SURFACE_ADDRESS_C_MASK 0xffffff00
+#define UNP_GRPH_PRIMARY_BOTTOM_SURFACE_ADDRESS_C__GRPH_PRIMARY_BOTTOM_SURFACE_ADDRESS_C__SHIFT 0x8
+#define UNP_GRPH_PRIMARY_BOTTOM_SURFACE_ADDRESS_HIGH_L__GRPH_PRIMARY_BOTTOM_SURFACE_ADDRESS_HIGH_L_MASK 0xff
+#define UNP_GRPH_PRIMARY_BOTTOM_SURFACE_ADDRESS_HIGH_L__GRPH_PRIMARY_BOTTOM_SURFACE_ADDRESS_HIGH_L__SHIFT 0x0
+#define UNP_GRPH_PRIMARY_BOTTOM_SURFACE_ADDRESS_HIGH_C__GRPH_PRIMARY_BOTTOM_SURFACE_ADDRESS_HIGH_C_MASK 0xff
+#define UNP_GRPH_PRIMARY_BOTTOM_SURFACE_ADDRESS_HIGH_C__GRPH_PRIMARY_BOTTOM_SURFACE_ADDRESS_HIGH_C__SHIFT 0x0
+#define UNP_GRPH_SECONDARY_SURFACE_ADDRESS_L__GRPH_SECONDARY_SURFACE_ADDRESS_L_MASK 0xffffff00
+#define UNP_GRPH_SECONDARY_SURFACE_ADDRESS_L__GRPH_SECONDARY_SURFACE_ADDRESS_L__SHIFT 0x8
+#define UNP_GRPH_SECONDARY_SURFACE_ADDRESS_C__GRPH_SECONDARY_SURFACE_ADDRESS_C_MASK 0xffffff00
+#define UNP_GRPH_SECONDARY_SURFACE_ADDRESS_C__GRPH_SECONDARY_SURFACE_ADDRESS_C__SHIFT 0x8
+#define UNP_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH_L__GRPH_SECONDARY_SURFACE_ADDRESS_HIGH_L_MASK 0xff
+#define UNP_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH_L__GRPH_SECONDARY_SURFACE_ADDRESS_HIGH_L__SHIFT 0x0
+#define UNP_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH_C__GRPH_SECONDARY_SURFACE_ADDRESS_HIGH_C_MASK 0xff
+#define UNP_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH_C__GRPH_SECONDARY_SURFACE_ADDRESS_HIGH_C__SHIFT 0x0
+#define UNP_GRPH_SECONDARY_BOTTOM_SURFACE_ADDRESS_L__GRPH_SECONDARY_BOTTOM_SURFACE_ADDRESS_L_MASK 0xffffff00
+#define UNP_GRPH_SECONDARY_BOTTOM_SURFACE_ADDRESS_L__GRPH_SECONDARY_BOTTOM_SURFACE_ADDRESS_L__SHIFT 0x8
+#define UNP_GRPH_SECONDARY_BOTTOM_SURFACE_ADDRESS_C__GRPH_SECONDARY_BOTTOM_SURFACE_ADDRESS_C_MASK 0xffffff00
+#define UNP_GRPH_SECONDARY_BOTTOM_SURFACE_ADDRESS_C__GRPH_SECONDARY_BOTTOM_SURFACE_ADDRESS_C__SHIFT 0x8
+#define UNP_GRPH_SECONDARY_BOTTOM_SURFACE_ADDRESS_HIGH_L__GRPH_SECONDARY_BOTTOM_SURFACE_ADDRESS_HIGH_L_MASK 0xff
+#define UNP_GRPH_SECONDARY_BOTTOM_SURFACE_ADDRESS_HIGH_L__GRPH_SECONDARY_BOTTOM_SURFACE_ADDRESS_HIGH_L__SHIFT 0x0
+#define UNP_GRPH_SECONDARY_BOTTOM_SURFACE_ADDRESS_HIGH_C__GRPH_SECONDARY_BOTTOM_SURFACE_ADDRESS_HIGH_C_MASK 0xff
+#define UNP_GRPH_SECONDARY_BOTTOM_SURFACE_ADDRESS_HIGH_C__GRPH_SECONDARY_BOTTOM_SURFACE_ADDRESS_HIGH_C__SHIFT 0x0
+#define UNP_GRPH_PITCH_L__GRPH_PITCH_L_MASK 0x7fff
+#define UNP_GRPH_PITCH_L__GRPH_PITCH_L__SHIFT 0x0
+#define UNP_GRPH_PITCH_C__GRPH_PITCH_C_MASK 0x7fff
+#define UNP_GRPH_PITCH_C__GRPH_PITCH_C__SHIFT 0x0
+#define UNP_GRPH_SURFACE_OFFSET_X_L__GRPH_SURFACE_OFFSET_X_L_MASK 0x3fff
+#define UNP_GRPH_SURFACE_OFFSET_X_L__GRPH_SURFACE_OFFSET_X_L__SHIFT 0x0
+#define UNP_GRPH_SURFACE_OFFSET_X_C__GRPH_SURFACE_OFFSET_X_C_MASK 0x3fff
+#define UNP_GRPH_SURFACE_OFFSET_X_C__GRPH_SURFACE_OFFSET_X_C__SHIFT 0x0
+#define UNP_GRPH_SURFACE_OFFSET_Y_L__GRPH_SURFACE_OFFSET_Y_L_MASK 0x3fff
+#define UNP_GRPH_SURFACE_OFFSET_Y_L__GRPH_SURFACE_OFFSET_Y_L__SHIFT 0x0
+#define UNP_GRPH_SURFACE_OFFSET_Y_C__GRPH_SURFACE_OFFSET_Y_C_MASK 0x3fff
+#define UNP_GRPH_SURFACE_OFFSET_Y_C__GRPH_SURFACE_OFFSET_Y_C__SHIFT 0x0
+#define UNP_GRPH_X_START_L__GRPH_X_START_L_MASK 0x3fff
+#define UNP_GRPH_X_START_L__GRPH_X_START_L__SHIFT 0x0
+#define UNP_GRPH_X_START_C__GRPH_X_START_C_MASK 0x3fff
+#define UNP_GRPH_X_START_C__GRPH_X_START_C__SHIFT 0x0
+#define UNP_GRPH_Y_START_L__GRPH_Y_START_L_MASK 0x3fff
+#define UNP_GRPH_Y_START_L__GRPH_Y_START_L__SHIFT 0x0
+#define UNP_GRPH_Y_START_C__GRPH_Y_START_C_MASK 0x3fff
+#define UNP_GRPH_Y_START_C__GRPH_Y_START_C__SHIFT 0x0
+#define UNP_GRPH_X_END_L__GRPH_X_END_L_MASK 0x7fff
+#define UNP_GRPH_X_END_L__GRPH_X_END_L__SHIFT 0x0
+#define UNP_GRPH_X_END_C__GRPH_X_END_C_MASK 0x7fff
+#define UNP_GRPH_X_END_C__GRPH_X_END_C__SHIFT 0x0
+#define UNP_GRPH_Y_END_L__GRPH_Y_END_L_MASK 0x7fff
+#define UNP_GRPH_Y_END_L__GRPH_Y_END_L__SHIFT 0x0
+#define UNP_GRPH_Y_END_C__GRPH_Y_END_C_MASK 0x7fff
+#define UNP_GRPH_Y_END_C__GRPH_Y_END_C__SHIFT 0x0
+#define UNP_GRPH_UPDATE__GRPH_MODE_UPDATE_PENDING_MASK 0x1
+#define UNP_GRPH_UPDATE__GRPH_MODE_UPDATE_PENDING__SHIFT 0x0
+#define UNP_GRPH_UPDATE__GRPH_MODE_UPDATE_TAKEN_MASK 0x2
+#define UNP_GRPH_UPDATE__GRPH_MODE_UPDATE_TAKEN__SHIFT 0x1
+#define UNP_GRPH_UPDATE__GRPH_SURFACE_UPDATE_PENDING_MASK 0x4
+#define UNP_GRPH_UPDATE__GRPH_SURFACE_UPDATE_PENDING__SHIFT 0x2
+#define UNP_GRPH_UPDATE__GRPH_SURFACE_UPDATE_TAKEN_MASK 0x8
+#define UNP_GRPH_UPDATE__GRPH_SURFACE_UPDATE_TAKEN__SHIFT 0x3
+#define UNP_GRPH_UPDATE__GRPH_UPDATE_LOCK_MASK 0x10000
+#define UNP_GRPH_UPDATE__GRPH_UPDATE_LOCK__SHIFT 0x10
+#define UNP_GRPH_UPDATE__GRPH_SURFACE_IGNORE_UPDATE_LOCK_MASK 0x100000
+#define UNP_GRPH_UPDATE__GRPH_SURFACE_IGNORE_UPDATE_LOCK__SHIFT 0x14
+#define UNP_GRPH_UPDATE__GRPH_MODE_DISABLE_MULTIPLE_UPDATE_MASK 0x1000000
+#define UNP_GRPH_UPDATE__GRPH_MODE_DISABLE_MULTIPLE_UPDATE__SHIFT 0x18
+#define UNP_GRPH_UPDATE__GRPH_SURFACE_DISABLE_MULTIPLE_UPDATE_MASK 0x10000000
+#define UNP_GRPH_UPDATE__GRPH_SURFACE_DISABLE_MULTIPLE_UPDATE__SHIFT 0x1c
+#define UNP_PIPE_OUTSTANDING_REQUEST_LIMIT__UNP_PIPE_OUTSTANDING_REQUEST_LIMIT_L_MASK 0xff
+#define UNP_PIPE_OUTSTANDING_REQUEST_LIMIT__UNP_PIPE_OUTSTANDING_REQUEST_LIMIT_L__SHIFT 0x0
+#define UNP_PIPE_OUTSTANDING_REQUEST_LIMIT__UNP_PIPE_OUTSTANDING_REQUEST_LIMIT_C_MASK 0xff00
+#define UNP_PIPE_OUTSTANDING_REQUEST_LIMIT__UNP_PIPE_OUTSTANDING_REQUEST_LIMIT_C__SHIFT 0x8
+#define UNP_GRPH_SURFACE_ADDRESS_INUSE_L__GRPH_SURFACE_ADDRESS_INUSE_L_MASK 0xffffff00
+#define UNP_GRPH_SURFACE_ADDRESS_INUSE_L__GRPH_SURFACE_ADDRESS_INUSE_L__SHIFT 0x8
+#define UNP_GRPH_SURFACE_ADDRESS_INUSE_C__GRPH_SURFACE_ADDRESS_INUSE_C_MASK 0xffffff00
+#define UNP_GRPH_SURFACE_ADDRESS_INUSE_C__GRPH_SURFACE_ADDRESS_INUSE_C__SHIFT 0x8
+#define UNP_GRPH_SURFACE_ADDRESS_HIGH_INUSE_L__GRPH_SURFACE_ADDRESS_HIGH_INUSE_L_MASK 0xff
+#define UNP_GRPH_SURFACE_ADDRESS_HIGH_INUSE_L__GRPH_SURFACE_ADDRESS_HIGH_INUSE_L__SHIFT 0x0
+#define UNP_GRPH_SURFACE_ADDRESS_HIGH_INUSE_C__GRPH_SURFACE_ADDRESS_HIGH_INUSE_C_MASK 0xff
+#define UNP_GRPH_SURFACE_ADDRESS_HIGH_INUSE_C__GRPH_SURFACE_ADDRESS_HIGH_INUSE_C__SHIFT 0x0
+#define UNP_DVMM_PTE_CONTROL__DVMM_USE_SINGLE_PTE_MASK 0x1
+#define UNP_DVMM_PTE_CONTROL__DVMM_USE_SINGLE_PTE__SHIFT 0x0
+#define UNP_DVMM_PTE_CONTROL__DVMM_PAGE_WIDTH_MASK 0x1e
+#define UNP_DVMM_PTE_CONTROL__DVMM_PAGE_WIDTH__SHIFT 0x1
+#define UNP_DVMM_PTE_CONTROL__DVMM_PAGE_HEIGHT_MASK 0x1e0
+#define UNP_DVMM_PTE_CONTROL__DVMM_PAGE_HEIGHT__SHIFT 0x5
+#define UNP_DVMM_PTE_CONTROL__DVMM_MIN_PTE_BEFORE_FLIP_MASK 0x7fe00
+#define UNP_DVMM_PTE_CONTROL__DVMM_MIN_PTE_BEFORE_FLIP__SHIFT 0x9
+#define UNP_DVMM_PTE_CONTROL__DVMM_PTE_BUFFER_MODE0_MASK 0x100000
+#define UNP_DVMM_PTE_CONTROL__DVMM_PTE_BUFFER_MODE0__SHIFT 0x14
+#define UNP_DVMM_PTE_CONTROL__DVMM_PTE_BUFFER_MODE1_MASK 0x200000
+#define UNP_DVMM_PTE_CONTROL__DVMM_PTE_BUFFER_MODE1__SHIFT 0x15
+#define UNP_GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_OCCURRED_MASK 0x1
+#define UNP_GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_OCCURRED__SHIFT 0x0
+#define UNP_GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK 0x100
+#define UNP_GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR__SHIFT 0x8
+#define UNP_GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK 0x1
+#define UNP_GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK__SHIFT 0x0
+#define UNP_GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_TYPE_MASK 0x100
+#define UNP_GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_TYPE__SHIFT 0x8
+#define UNP_GRPH_STEREOSYNC_FLIP__GRPH_STEREOSYNC_FLIP_EN_MASK 0x1
+#define UNP_GRPH_STEREOSYNC_FLIP__GRPH_STEREOSYNC_FLIP_EN__SHIFT 0x0
+#define UNP_GRPH_STEREOSYNC_FLIP__GRPH_STEREOSYNC_FLIP_MODE_MASK 0x30
+#define UNP_GRPH_STEREOSYNC_FLIP__GRPH_STEREOSYNC_FLIP_MODE__SHIFT 0x4
+#define UNP_GRPH_STEREOSYNC_FLIP__GRPH_STACK_INTERLACE_FLIP_EN_MASK 0x100
+#define UNP_GRPH_STEREOSYNC_FLIP__GRPH_STACK_INTERLACE_FLIP_EN__SHIFT 0x8
+#define UNP_GRPH_STEREOSYNC_FLIP__GRPH_STACK_INTERLACE_FLIP_MODE_MASK 0x3000
+#define UNP_GRPH_STEREOSYNC_FLIP__GRPH_STACK_INTERLACE_FLIP_MODE__SHIFT 0xc
+#define UNP_GRPH_STEREOSYNC_FLIP__GRPH_PRIMARY_SURFACE_PENDING_MASK 0x10000
+#define UNP_GRPH_STEREOSYNC_FLIP__GRPH_PRIMARY_SURFACE_PENDING__SHIFT 0x10
+#define UNP_GRPH_STEREOSYNC_FLIP__GRPH_SECONDARY_SURFACE_PENDING_MASK 0x20000
+#define UNP_GRPH_STEREOSYNC_FLIP__GRPH_SECONDARY_SURFACE_PENDING__SHIFT 0x11
+#define UNP_GRPH_STEREOSYNC_FLIP__GRPH_PRIMARY_BOTTOM_SURFACE_PENDING_MASK 0x40000
+#define UNP_GRPH_STEREOSYNC_FLIP__GRPH_PRIMARY_BOTTOM_SURFACE_PENDING__SHIFT 0x12
+#define UNP_GRPH_STEREOSYNC_FLIP__GRPH_SECONDARY_BOTTOM_SURFACE_PENDING_MASK 0x80000
+#define UNP_GRPH_STEREOSYNC_FLIP__GRPH_SECONDARY_BOTTOM_SURFACE_PENDING__SHIFT 0x13
+#define UNP_GRPH_STEREOSYNC_FLIP__GRPH_STEREOSYNC_SELECT_DISABLE_MASK 0x10000000
+#define UNP_GRPH_STEREOSYNC_FLIP__GRPH_STEREOSYNC_SELECT_DISABLE__SHIFT 0x1c
+#define UNP_FLIP_CONTROL__GRPH_SURFACE_UPDATE_PENDING_MODE_MASK 0x1
+#define UNP_FLIP_CONTROL__GRPH_SURFACE_UPDATE_PENDING_MODE__SHIFT 0x0
+#define UNP_FLIP_CONTROL__UNP_DEBUG_SG_MASK 0xfffffffc
+#define UNP_FLIP_CONTROL__UNP_DEBUG_SG__SHIFT 0x2
+#define UNP_CRC_CONTROL__UNP_CRC_ENABLE_MASK 0x1
+#define UNP_CRC_CONTROL__UNP_CRC_ENABLE__SHIFT 0x0
+#define UNP_CRC_CONTROL__UNP_CRC_SOURCE_SEL_MASK 0x1c
+#define UNP_CRC_CONTROL__UNP_CRC_SOURCE_SEL__SHIFT 0x2
+#define UNP_CRC_CONTROL__UNP_CRC_LINE_SEL_MASK 0x300
+#define UNP_CRC_CONTROL__UNP_CRC_LINE_SEL__SHIFT 0x8
+#define UNP_CRC_MASK__UNP_CRC_MASK_MASK 0xffffffff
+#define UNP_CRC_MASK__UNP_CRC_MASK__SHIFT 0x0
+#define UNP_CRC_CURRENT__UNP_CRC_CURRENT_MASK 0xffffffff
+#define UNP_CRC_CURRENT__UNP_CRC_CURRENT__SHIFT 0x0
+#define UNP_CRC_LAST__UNP_CRC_LAST_MASK 0xffffffff
+#define UNP_CRC_LAST__UNP_CRC_LAST__SHIFT 0x0
+#define UNP_LB_DATA_GAP_BETWEEN_CHUNK__UNP_LB_GAP_BETWEEN_CHUNK_MASK 0x1f0
+#define UNP_LB_DATA_GAP_BETWEEN_CHUNK__UNP_LB_GAP_BETWEEN_CHUNK__SHIFT 0x4
+#define UNP_HW_ROTATION__ROTATION_ANGLE_MASK 0x7
+#define UNP_HW_ROTATION__ROTATION_ANGLE__SHIFT 0x0
+#define UNP_HW_ROTATION__PIXEL_DROP_MASK 0x10
+#define UNP_HW_ROTATION__PIXEL_DROP__SHIFT 0x4
+#define UNP_HW_ROTATION__BUFFER_MODE_MASK 0x100
+#define UNP_HW_ROTATION__BUFFER_MODE__SHIFT 0x8
+#define UNP_DEBUG__UNP_DEBUG_MASK 0xffffffff
+#define UNP_DEBUG__UNP_DEBUG__SHIFT 0x0
+#define UNP_DEBUG2__UNP_DEBUG2_MASK 0xffffffff
+#define UNP_DEBUG2__UNP_DEBUG2__SHIFT 0x0
+#define UNP_DVMM_DEBUG__UNP_L_DVMM_DEBUG_MASK 0xffff
+#define UNP_DVMM_DEBUG__UNP_L_DVMM_DEBUG__SHIFT 0x0
+#define UNP_DVMM_DEBUG__UNP_C_DVMM_DEBUG_MASK 0xffff0000
+#define UNP_DVMM_DEBUG__UNP_C_DVMM_DEBUG__SHIFT 0x10
+#define UNP_TEST_DEBUG_INDEX__UNP_TEST_DEBUG_INDEX_MASK 0xff
+#define UNP_TEST_DEBUG_INDEX__UNP_TEST_DEBUG_INDEX__SHIFT 0x0
+#define UNP_TEST_DEBUG_INDEX__UNP_TEST_DEBUG_WRITE_EN_MASK 0x100
+#define UNP_TEST_DEBUG_INDEX__UNP_TEST_DEBUG_WRITE_EN__SHIFT 0x8
+#define UNP_TEST_DEBUG_DATA__UNP_TEST_DEBUG_DATA_MASK 0xffffffff
+#define UNP_TEST_DEBUG_DATA__UNP_TEST_DEBUG_DATA__SHIFT 0x0
+#define GENMO_WT__GENMO_MONO_ADDRESS_B_MASK 0x1
+#define GENMO_WT__GENMO_MONO_ADDRESS_B__SHIFT 0x0
+#define GENMO_WT__VGA_RAM_EN_MASK 0x2
+#define GENMO_WT__VGA_RAM_EN__SHIFT 0x1
+#define GENMO_WT__VGA_CKSEL_MASK 0xc
+#define GENMO_WT__VGA_CKSEL__SHIFT 0x2
+#define GENMO_WT__ODD_EVEN_MD_PGSEL_MASK 0x20
+#define GENMO_WT__ODD_EVEN_MD_PGSEL__SHIFT 0x5
+#define GENMO_WT__VGA_HSYNC_POL_MASK 0x40
+#define GENMO_WT__VGA_HSYNC_POL__SHIFT 0x6
+#define GENMO_WT__VGA_VSYNC_POL_MASK 0x80
+#define GENMO_WT__VGA_VSYNC_POL__SHIFT 0x7
+#define GENMO_RD__GENMO_MONO_ADDRESS_B_MASK 0x1
+#define GENMO_RD__GENMO_MONO_ADDRESS_B__SHIFT 0x0
+#define GENMO_RD__VGA_RAM_EN_MASK 0x2
+#define GENMO_RD__VGA_RAM_EN__SHIFT 0x1
+#define GENMO_RD__VGA_CKSEL_MASK 0xc
+#define GENMO_RD__VGA_CKSEL__SHIFT 0x2
+#define GENMO_RD__ODD_EVEN_MD_PGSEL_MASK 0x20
+#define GENMO_RD__ODD_EVEN_MD_PGSEL__SHIFT 0x5
+#define GENMO_RD__VGA_HSYNC_POL_MASK 0x40
+#define GENMO_RD__VGA_HSYNC_POL__SHIFT 0x6
+#define GENMO_RD__VGA_VSYNC_POL_MASK 0x80
+#define GENMO_RD__VGA_VSYNC_POL__SHIFT 0x7
+#define GENENB__BLK_IO_BASE_MASK 0xff
+#define GENENB__BLK_IO_BASE__SHIFT 0x0
+#define GENFC_WT__VSYNC_SEL_W_MASK 0x8
+#define GENFC_WT__VSYNC_SEL_W__SHIFT 0x3
+#define GENFC_RD__VSYNC_SEL_R_MASK 0x8
+#define GENFC_RD__VSYNC_SEL_R__SHIFT 0x3
+#define GENS0__SENSE_SWITCH_MASK 0x10
+#define GENS0__SENSE_SWITCH__SHIFT 0x4
+#define GENS0__CRT_INTR_MASK 0x80
+#define GENS0__CRT_INTR__SHIFT 0x7
+#define GENS1__NO_DISPLAY_MASK 0x1
+#define GENS1__NO_DISPLAY__SHIFT 0x0
+#define GENS1__VGA_VSTATUS_MASK 0x8
+#define GENS1__VGA_VSTATUS__SHIFT 0x3
+#define GENS1__PIXEL_READ_BACK_MASK 0x30
+#define GENS1__PIXEL_READ_BACK__SHIFT 0x4
+#define DAC_DATA__DAC_DATA_MASK 0x3f
+#define DAC_DATA__DAC_DATA__SHIFT 0x0
+#define DAC_MASK__DAC_MASK_MASK 0xff
+#define DAC_MASK__DAC_MASK__SHIFT 0x0
+#define DAC_R_INDEX__DAC_R_INDEX_MASK 0xff
+#define DAC_R_INDEX__DAC_R_INDEX__SHIFT 0x0
+#define DAC_W_INDEX__DAC_W_INDEX_MASK 0xff
+#define DAC_W_INDEX__DAC_W_INDEX__SHIFT 0x0
+#define SEQ8_IDX__SEQ_IDX_MASK 0x7
+#define SEQ8_IDX__SEQ_IDX__SHIFT 0x0
+#define SEQ8_DATA__SEQ_DATA_MASK 0xff
+#define SEQ8_DATA__SEQ_DATA__SHIFT 0x0
+#define SEQ00__SEQ_RST0B_MASK 0x1
+#define SEQ00__SEQ_RST0B__SHIFT 0x0
+#define SEQ00__SEQ_RST1B_MASK 0x2
+#define SEQ00__SEQ_RST1B__SHIFT 0x1
+#define SEQ01__SEQ_DOT8_MASK 0x1
+#define SEQ01__SEQ_DOT8__SHIFT 0x0
+#define SEQ01__SEQ_SHIFT2_MASK 0x4
+#define SEQ01__SEQ_SHIFT2__SHIFT 0x2
+#define SEQ01__SEQ_PCLKBY2_MASK 0x8
+#define SEQ01__SEQ_PCLKBY2__SHIFT 0x3
+#define SEQ01__SEQ_SHIFT4_MASK 0x10
+#define SEQ01__SEQ_SHIFT4__SHIFT 0x4
+#define SEQ01__SEQ_MAXBW_MASK 0x20
+#define SEQ01__SEQ_MAXBW__SHIFT 0x5
+#define SEQ02__SEQ_MAP0_EN_MASK 0x1
+#define SEQ02__SEQ_MAP0_EN__SHIFT 0x0
+#define SEQ02__SEQ_MAP1_EN_MASK 0x2
+#define SEQ02__SEQ_MAP1_EN__SHIFT 0x1
+#define SEQ02__SEQ_MAP2_EN_MASK 0x4
+#define SEQ02__SEQ_MAP2_EN__SHIFT 0x2
+#define SEQ02__SEQ_MAP3_EN_MASK 0x8
+#define SEQ02__SEQ_MAP3_EN__SHIFT 0x3
+#define SEQ03__SEQ_FONT_B1_MASK 0x1
+#define SEQ03__SEQ_FONT_B1__SHIFT 0x0
+#define SEQ03__SEQ_FONT_B2_MASK 0x2
+#define SEQ03__SEQ_FONT_B2__SHIFT 0x1
+#define SEQ03__SEQ_FONT_A1_MASK 0x4
+#define SEQ03__SEQ_FONT_A1__SHIFT 0x2
+#define SEQ03__SEQ_FONT_A2_MASK 0x8
+#define SEQ03__SEQ_FONT_A2__SHIFT 0x3
+#define SEQ03__SEQ_FONT_B0_MASK 0x10
+#define SEQ03__SEQ_FONT_B0__SHIFT 0x4
+#define SEQ03__SEQ_FONT_A0_MASK 0x20
+#define SEQ03__SEQ_FONT_A0__SHIFT 0x5
+#define SEQ04__SEQ_256K_MASK 0x2
+#define SEQ04__SEQ_256K__SHIFT 0x1
+#define SEQ04__SEQ_ODDEVEN_MASK 0x4
+#define SEQ04__SEQ_ODDEVEN__SHIFT 0x2
+#define SEQ04__SEQ_CHAIN_MASK 0x8
+#define SEQ04__SEQ_CHAIN__SHIFT 0x3
+#define CRTC8_IDX__VCRTC_IDX_MASK 0x3f
+#define CRTC8_IDX__VCRTC_IDX__SHIFT 0x0
+#define CRTC8_DATA__VCRTC_DATA_MASK 0xff
+#define CRTC8_DATA__VCRTC_DATA__SHIFT 0x0
+#define CRT00__H_TOTAL_MASK 0xff
+#define CRT00__H_TOTAL__SHIFT 0x0
+#define CRT01__H_DISP_END_MASK 0xff
+#define CRT01__H_DISP_END__SHIFT 0x0
+#define CRT02__H_BLANK_START_MASK 0xff
+#define CRT02__H_BLANK_START__SHIFT 0x0
+#define CRT03__H_BLANK_END_MASK 0x1f
+#define CRT03__H_BLANK_END__SHIFT 0x0
+#define CRT03__H_DE_SKEW_MASK 0x60
+#define CRT03__H_DE_SKEW__SHIFT 0x5
+#define CRT03__CR10CR11_R_DIS_B_MASK 0x80
+#define CRT03__CR10CR11_R_DIS_B__SHIFT 0x7
+#define CRT04__H_SYNC_START_MASK 0xff
+#define CRT04__H_SYNC_START__SHIFT 0x0
+#define CRT05__H_SYNC_END_MASK 0x1f
+#define CRT05__H_SYNC_END__SHIFT 0x0
+#define CRT05__H_SYNC_SKEW_MASK 0x60
+#define CRT05__H_SYNC_SKEW__SHIFT 0x5
+#define CRT05__H_BLANK_END_B5_MASK 0x80
+#define CRT05__H_BLANK_END_B5__SHIFT 0x7
+#define CRT06__V_TOTAL_MASK 0xff
+#define CRT06__V_TOTAL__SHIFT 0x0
+#define CRT07__V_TOTAL_B8_MASK 0x1
+#define CRT07__V_TOTAL_B8__SHIFT 0x0
+#define CRT07__V_DISP_END_B8_MASK 0x2
+#define CRT07__V_DISP_END_B8__SHIFT 0x1
+#define CRT07__V_SYNC_START_B8_MASK 0x4
+#define CRT07__V_SYNC_START_B8__SHIFT 0x2
+#define CRT07__V_BLANK_START_B8_MASK 0x8
+#define CRT07__V_BLANK_START_B8__SHIFT 0x3
+#define CRT07__LINE_CMP_B8_MASK 0x10
+#define CRT07__LINE_CMP_B8__SHIFT 0x4
+#define CRT07__V_TOTAL_B9_MASK 0x20
+#define CRT07__V_TOTAL_B9__SHIFT 0x5
+#define CRT07__V_DISP_END_B9_MASK 0x40
+#define CRT07__V_DISP_END_B9__SHIFT 0x6
+#define CRT07__V_SYNC_START_B9_MASK 0x80
+#define CRT07__V_SYNC_START_B9__SHIFT 0x7
+#define CRT08__ROW_SCAN_START_MASK 0x1f
+#define CRT08__ROW_SCAN_START__SHIFT 0x0
+#define CRT08__BYTE_PAN_MASK 0x60
+#define CRT08__BYTE_PAN__SHIFT 0x5
+#define CRT09__MAX_ROW_SCAN_MASK 0x1f
+#define CRT09__MAX_ROW_SCAN__SHIFT 0x0
+#define CRT09__V_BLANK_START_B9_MASK 0x20
+#define CRT09__V_BLANK_START_B9__SHIFT 0x5
+#define CRT09__LINE_CMP_B9_MASK 0x40
+#define CRT09__LINE_CMP_B9__SHIFT 0x6
+#define CRT09__DOUBLE_CHAR_HEIGHT_MASK 0x80
+#define CRT09__DOUBLE_CHAR_HEIGHT__SHIFT 0x7
+#define CRT0A__CURSOR_START_MASK 0x1f
+#define CRT0A__CURSOR_START__SHIFT 0x0
+#define CRT0A__CURSOR_DISABLE_MASK 0x20
+#define CRT0A__CURSOR_DISABLE__SHIFT 0x5
+#define CRT0B__CURSOR_END_MASK 0x1f
+#define CRT0B__CURSOR_END__SHIFT 0x0
+#define CRT0B__CURSOR_SKEW_MASK 0x60
+#define CRT0B__CURSOR_SKEW__SHIFT 0x5
+#define CRT0C__DISP_START_MASK 0xff
+#define CRT0C__DISP_START__SHIFT 0x0
+#define CRT0D__DISP_START_MASK 0xff
+#define CRT0D__DISP_START__SHIFT 0x0
+#define CRT0E__CURSOR_LOC_HI_MASK 0xff
+#define CRT0E__CURSOR_LOC_HI__SHIFT 0x0
+#define CRT0F__CURSOR_LOC_LO_MASK 0xff
+#define CRT0F__CURSOR_LOC_LO__SHIFT 0x0
+#define CRT10__V_SYNC_START_MASK 0xff
+#define CRT10__V_SYNC_START__SHIFT 0x0
+#define CRT11__V_SYNC_END_MASK 0xf
+#define CRT11__V_SYNC_END__SHIFT 0x0
+#define CRT11__V_INTR_CLR_MASK 0x10
+#define CRT11__V_INTR_CLR__SHIFT 0x4
+#define CRT11__V_INTR_EN_MASK 0x20
+#define CRT11__V_INTR_EN__SHIFT 0x5
+#define CRT11__SEL5_REFRESH_CYC_MASK 0x40
+#define CRT11__SEL5_REFRESH_CYC__SHIFT 0x6
+#define CRT11__C0T7_WR_ONLY_MASK 0x80
+#define CRT11__C0T7_WR_ONLY__SHIFT 0x7
+#define CRT12__V_DISP_END_MASK 0xff
+#define CRT12__V_DISP_END__SHIFT 0x0
+#define CRT13__DISP_PITCH_MASK 0xff
+#define CRT13__DISP_PITCH__SHIFT 0x0
+#define CRT14__UNDRLN_LOC_MASK 0x1f
+#define CRT14__UNDRLN_LOC__SHIFT 0x0
+#define CRT14__ADDR_CNT_BY4_MASK 0x20
+#define CRT14__ADDR_CNT_BY4__SHIFT 0x5
+#define CRT14__DOUBLE_WORD_MASK 0x40
+#define CRT14__DOUBLE_WORD__SHIFT 0x6
+#define CRT15__V_BLANK_START_MASK 0xff
+#define CRT15__V_BLANK_START__SHIFT 0x0
+#define CRT16__V_BLANK_END_MASK 0xff
+#define CRT16__V_BLANK_END__SHIFT 0x0
+#define CRT17__RA0_AS_A13B_MASK 0x1
+#define CRT17__RA0_AS_A13B__SHIFT 0x0
+#define CRT17__RA1_AS_A14B_MASK 0x2
+#define CRT17__RA1_AS_A14B__SHIFT 0x1
+#define CRT17__VCOUNT_BY2_MASK 0x4
+#define CRT17__VCOUNT_BY2__SHIFT 0x2
+#define CRT17__ADDR_CNT_BY2_MASK 0x8
+#define CRT17__ADDR_CNT_BY2__SHIFT 0x3
+#define CRT17__WRAP_A15TOA0_MASK 0x20
+#define CRT17__WRAP_A15TOA0__SHIFT 0x5
+#define CRT17__BYTE_MODE_MASK 0x40
+#define CRT17__BYTE_MODE__SHIFT 0x6
+#define CRT17__CRTC_SYNC_EN_MASK 0x80
+#define CRT17__CRTC_SYNC_EN__SHIFT 0x7
+#define CRT18__LINE_CMP_MASK 0xff
+#define CRT18__LINE_CMP__SHIFT 0x0
+#define CRT1E__GRPH_DEC_RD1_MASK 0x2
+#define CRT1E__GRPH_DEC_RD1__SHIFT 0x1
+#define CRT1F__GRPH_DEC_RD0_MASK 0xff
+#define CRT1F__GRPH_DEC_RD0__SHIFT 0x0
+#define CRT22__GRPH_LATCH_DATA_MASK 0xff
+#define CRT22__GRPH_LATCH_DATA__SHIFT 0x0
+#define GRPH8_IDX__GRPH_IDX_MASK 0xf
+#define GRPH8_IDX__GRPH_IDX__SHIFT 0x0
+#define GRPH8_DATA__GRPH_DATA_MASK 0xff
+#define GRPH8_DATA__GRPH_DATA__SHIFT 0x0
+#define GRA00__GRPH_SET_RESET0_MASK 0x1
+#define GRA00__GRPH_SET_RESET0__SHIFT 0x0
+#define GRA00__GRPH_SET_RESET1_MASK 0x2
+#define GRA00__GRPH_SET_RESET1__SHIFT 0x1
+#define GRA00__GRPH_SET_RESET2_MASK 0x4
+#define GRA00__GRPH_SET_RESET2__SHIFT 0x2
+#define GRA00__GRPH_SET_RESET3_MASK 0x8
+#define GRA00__GRPH_SET_RESET3__SHIFT 0x3
+#define GRA01__GRPH_SET_RESET_ENA0_MASK 0x1
+#define GRA01__GRPH_SET_RESET_ENA0__SHIFT 0x0
+#define GRA01__GRPH_SET_RESET_ENA1_MASK 0x2
+#define GRA01__GRPH_SET_RESET_ENA1__SHIFT 0x1
+#define GRA01__GRPH_SET_RESET_ENA2_MASK 0x4
+#define GRA01__GRPH_SET_RESET_ENA2__SHIFT 0x2
+#define GRA01__GRPH_SET_RESET_ENA3_MASK 0x8
+#define GRA01__GRPH_SET_RESET_ENA3__SHIFT 0x3
+#define GRA02__GRPH_CCOMP_MASK 0xf
+#define GRA02__GRPH_CCOMP__SHIFT 0x0
+#define GRA03__GRPH_ROTATE_MASK 0x7
+#define GRA03__GRPH_ROTATE__SHIFT 0x0
+#define GRA03__GRPH_FN_SEL_MASK 0x18
+#define GRA03__GRPH_FN_SEL__SHIFT 0x3
+#define GRA04__GRPH_RMAP_MASK 0x3
+#define GRA04__GRPH_RMAP__SHIFT 0x0
+#define GRA05__GRPH_WRITE_MODE_MASK 0x3
+#define GRA05__GRPH_WRITE_MODE__SHIFT 0x0
+#define GRA05__GRPH_READ1_MASK 0x8
+#define GRA05__GRPH_READ1__SHIFT 0x3
+#define GRA05__CGA_ODDEVEN_MASK 0x10
+#define GRA05__CGA_ODDEVEN__SHIFT 0x4
+#define GRA05__GRPH_OES_MASK 0x20
+#define GRA05__GRPH_OES__SHIFT 0x5
+#define GRA05__GRPH_PACK_MASK 0x40
+#define GRA05__GRPH_PACK__SHIFT 0x6
+#define GRA06__GRPH_GRAPHICS_MASK 0x1
+#define GRA06__GRPH_GRAPHICS__SHIFT 0x0
+#define GRA06__GRPH_ODDEVEN_MASK 0x2
+#define GRA06__GRPH_ODDEVEN__SHIFT 0x1
+#define GRA06__GRPH_ADRSEL_MASK 0xc
+#define GRA06__GRPH_ADRSEL__SHIFT 0x2
+#define GRA07__GRPH_XCARE0_MASK 0x1
+#define GRA07__GRPH_XCARE0__SHIFT 0x0
+#define GRA07__GRPH_XCARE1_MASK 0x2
+#define GRA07__GRPH_XCARE1__SHIFT 0x1
+#define GRA07__GRPH_XCARE2_MASK 0x4
+#define GRA07__GRPH_XCARE2__SHIFT 0x2
+#define GRA07__GRPH_XCARE3_MASK 0x8
+#define GRA07__GRPH_XCARE3__SHIFT 0x3
+#define GRA08__GRPH_BMSK_MASK 0xff
+#define GRA08__GRPH_BMSK__SHIFT 0x0
+#define ATTRX__ATTR_IDX_MASK 0x1f
+#define ATTRX__ATTR_IDX__SHIFT 0x0
+#define ATTRX__ATTR_PAL_RW_ENB_MASK 0x20
+#define ATTRX__ATTR_PAL_RW_ENB__SHIFT 0x5
+#define ATTRDW__ATTR_DATA_MASK 0xff
+#define ATTRDW__ATTR_DATA__SHIFT 0x0
+#define ATTRDR__ATTR_DATA_MASK 0xff
+#define ATTRDR__ATTR_DATA__SHIFT 0x0
+#define ATTR00__ATTR_PAL_MASK 0x3f
+#define ATTR00__ATTR_PAL__SHIFT 0x0
+#define ATTR01__ATTR_PAL_MASK 0x3f
+#define ATTR01__ATTR_PAL__SHIFT 0x0
+#define ATTR02__ATTR_PAL_MASK 0x3f
+#define ATTR02__ATTR_PAL__SHIFT 0x0
+#define ATTR03__ATTR_PAL_MASK 0x3f
+#define ATTR03__ATTR_PAL__SHIFT 0x0
+#define ATTR04__ATTR_PAL_MASK 0x3f
+#define ATTR04__ATTR_PAL__SHIFT 0x0
+#define ATTR05__ATTR_PAL_MASK 0x3f
+#define ATTR05__ATTR_PAL__SHIFT 0x0
+#define ATTR06__ATTR_PAL_MASK 0x3f
+#define ATTR06__ATTR_PAL__SHIFT 0x0
+#define ATTR07__ATTR_PAL_MASK 0x3f
+#define ATTR07__ATTR_PAL__SHIFT 0x0
+#define ATTR08__ATTR_PAL_MASK 0x3f
+#define ATTR08__ATTR_PAL__SHIFT 0x0
+#define ATTR09__ATTR_PAL_MASK 0x3f
+#define ATTR09__ATTR_PAL__SHIFT 0x0
+#define ATTR0A__ATTR_PAL_MASK 0x3f
+#define ATTR0A__ATTR_PAL__SHIFT 0x0
+#define ATTR0B__ATTR_PAL_MASK 0x3f
+#define ATTR0B__ATTR_PAL__SHIFT 0x0
+#define ATTR0C__ATTR_PAL_MASK 0x3f
+#define ATTR0C__ATTR_PAL__SHIFT 0x0
+#define ATTR0D__ATTR_PAL_MASK 0x3f
+#define ATTR0D__ATTR_PAL__SHIFT 0x0
+#define ATTR0E__ATTR_PAL_MASK 0x3f
+#define ATTR0E__ATTR_PAL__SHIFT 0x0
+#define ATTR0F__ATTR_PAL_MASK 0x3f
+#define ATTR0F__ATTR_PAL__SHIFT 0x0
+#define ATTR10__ATTR_GRPH_MODE_MASK 0x1
+#define ATTR10__ATTR_GRPH_MODE__SHIFT 0x0
+#define ATTR10__ATTR_MONO_EN_MASK 0x2
+#define ATTR10__ATTR_MONO_EN__SHIFT 0x1
+#define ATTR10__ATTR_LGRPH_EN_MASK 0x4
+#define ATTR10__ATTR_LGRPH_EN__SHIFT 0x2
+#define ATTR10__ATTR_BLINK_EN_MASK 0x8
+#define ATTR10__ATTR_BLINK_EN__SHIFT 0x3
+#define ATTR10__ATTR_PANTOPONLY_MASK 0x20
+#define ATTR10__ATTR_PANTOPONLY__SHIFT 0x5
+#define ATTR10__ATTR_PCLKBY2_MASK 0x40
+#define ATTR10__ATTR_PCLKBY2__SHIFT 0x6
+#define ATTR10__ATTR_CSEL_EN_MASK 0x80
+#define ATTR10__ATTR_CSEL_EN__SHIFT 0x7
+#define ATTR11__ATTR_OVSC_MASK 0xff
+#define ATTR11__ATTR_OVSC__SHIFT 0x0
+#define ATTR12__ATTR_MAP_EN_MASK 0xf
+#define ATTR12__ATTR_MAP_EN__SHIFT 0x0
+#define ATTR12__ATTR_VSMUX_MASK 0x30
+#define ATTR12__ATTR_VSMUX__SHIFT 0x4
+#define ATTR13__ATTR_PPAN_MASK 0xf
+#define ATTR13__ATTR_PPAN__SHIFT 0x0
+#define ATTR14__ATTR_CSEL1_MASK 0x3
+#define ATTR14__ATTR_CSEL1__SHIFT 0x0
+#define ATTR14__ATTR_CSEL2_MASK 0xc
+#define ATTR14__ATTR_CSEL2__SHIFT 0x2
+#define VGA_RENDER_CONTROL__VGA_BLINK_RATE_MASK 0x1f
+#define VGA_RENDER_CONTROL__VGA_BLINK_RATE__SHIFT 0x0
+#define VGA_RENDER_CONTROL__VGA_BLINK_MODE_MASK 0x60
+#define VGA_RENDER_CONTROL__VGA_BLINK_MODE__SHIFT 0x5
+#define VGA_RENDER_CONTROL__VGA_CURSOR_BLINK_INVERT_MASK 0x80
+#define VGA_RENDER_CONTROL__VGA_CURSOR_BLINK_INVERT__SHIFT 0x7
+#define VGA_RENDER_CONTROL__VGA_EXTD_ADDR_COUNT_ENABLE_MASK 0x100
+#define VGA_RENDER_CONTROL__VGA_EXTD_ADDR_COUNT_ENABLE__SHIFT 0x8
+#define VGA_RENDER_CONTROL__VGA_VSTATUS_CNTL_MASK 0x30000
+#define VGA_RENDER_CONTROL__VGA_VSTATUS_CNTL__SHIFT 0x10
+#define VGA_RENDER_CONTROL__VGA_LOCK_8DOT_MASK 0x1000000
+#define VGA_RENDER_CONTROL__VGA_LOCK_8DOT__SHIFT 0x18
+#define VGA_RENDER_CONTROL__VGAREG_LINECMP_COMPATIBILITY_SEL_MASK 0x2000000
+#define VGA_RENDER_CONTROL__VGAREG_LINECMP_COMPATIBILITY_SEL__SHIFT 0x19
+#define VGA_SOURCE_SELECT__VGA_SOURCE_SEL_A_MASK 0x7
+#define VGA_SOURCE_SELECT__VGA_SOURCE_SEL_A__SHIFT 0x0
+#define VGA_SOURCE_SELECT__VGA_SOURCE_SEL_B_MASK 0x700
+#define VGA_SOURCE_SELECT__VGA_SOURCE_SEL_B__SHIFT 0x8
+#define VGA_SEQUENCER_RESET_CONTROL__D1_BLANK_DISPLAY_WHEN_SEQUENCER_RESET_MASK 0x1
+#define VGA_SEQUENCER_RESET_CONTROL__D1_BLANK_DISPLAY_WHEN_SEQUENCER_RESET__SHIFT 0x0
+#define VGA_SEQUENCER_RESET_CONTROL__D2_BLANK_DISPLAY_WHEN_SEQUENCER_RESET_MASK 0x2
+#define VGA_SEQUENCER_RESET_CONTROL__D2_BLANK_DISPLAY_WHEN_SEQUENCER_RESET__SHIFT 0x1
+#define VGA_SEQUENCER_RESET_CONTROL__D3_BLANK_DISPLAY_WHEN_SEQUENCER_RESET_MASK 0x4
+#define VGA_SEQUENCER_RESET_CONTROL__D3_BLANK_DISPLAY_WHEN_SEQUENCER_RESET__SHIFT 0x2
+#define VGA_SEQUENCER_RESET_CONTROL__D4_BLANK_DISPLAY_WHEN_SEQUENCER_RESET_MASK 0x8
+#define VGA_SEQUENCER_RESET_CONTROL__D4_BLANK_DISPLAY_WHEN_SEQUENCER_RESET__SHIFT 0x3
+#define VGA_SEQUENCER_RESET_CONTROL__D5_BLANK_DISPLAY_WHEN_SEQUENCER_RESET_MASK 0x10
+#define VGA_SEQUENCER_RESET_CONTROL__D5_BLANK_DISPLAY_WHEN_SEQUENCER_RESET__SHIFT 0x4
+#define VGA_SEQUENCER_RESET_CONTROL__D6_BLANK_DISPLAY_WHEN_SEQUENCER_RESET_MASK 0x20
+#define VGA_SEQUENCER_RESET_CONTROL__D6_BLANK_DISPLAY_WHEN_SEQUENCER_RESET__SHIFT 0x5
+#define VGA_SEQUENCER_RESET_CONTROL__D1_DISABLE_SYNCS_AND_DE_WHEN_SEQUENCER_RESET_MASK 0x100
+#define VGA_SEQUENCER_RESET_CONTROL__D1_DISABLE_SYNCS_AND_DE_WHEN_SEQUENCER_RESET__SHIFT 0x8
+#define VGA_SEQUENCER_RESET_CONTROL__D2_DISABLE_SYNCS_AND_DE_WHEN_SEQUENCER_RESET_MASK 0x200
+#define VGA_SEQUENCER_RESET_CONTROL__D2_DISABLE_SYNCS_AND_DE_WHEN_SEQUENCER_RESET__SHIFT 0x9
+#define VGA_SEQUENCER_RESET_CONTROL__D3_DISABLE_SYNCS_AND_DE_WHEN_SEQUENCER_RESET_MASK 0x400
+#define VGA_SEQUENCER_RESET_CONTROL__D3_DISABLE_SYNCS_AND_DE_WHEN_SEQUENCER_RESET__SHIFT 0xa
+#define VGA_SEQUENCER_RESET_CONTROL__D4_DISABLE_SYNCS_AND_DE_WHEN_SEQUENCER_RESET_MASK 0x800
+#define VGA_SEQUENCER_RESET_CONTROL__D4_DISABLE_SYNCS_AND_DE_WHEN_SEQUENCER_RESET__SHIFT 0xb
+#define VGA_SEQUENCER_RESET_CONTROL__D5_DISABLE_SYNCS_AND_DE_WHEN_SEQUENCER_RESET_MASK 0x1000
+#define VGA_SEQUENCER_RESET_CONTROL__D5_DISABLE_SYNCS_AND_DE_WHEN_SEQUENCER_RESET__SHIFT 0xc
+#define VGA_SEQUENCER_RESET_CONTROL__D6_DISABLE_SYNCS_AND_DE_WHEN_SEQUENCER_RESET_MASK 0x2000
+#define VGA_SEQUENCER_RESET_CONTROL__D6_DISABLE_SYNCS_AND_DE_WHEN_SEQUENCER_RESET__SHIFT 0xd
+#define VGA_SEQUENCER_RESET_CONTROL__VGA_MODE_AUTO_TRIGGER_ENABLE_MASK 0x10000
+#define VGA_SEQUENCER_RESET_CONTROL__VGA_MODE_AUTO_TRIGGER_ENABLE__SHIFT 0x10
+#define VGA_SEQUENCER_RESET_CONTROL__VGA_MODE_AUTO_TRIGGER_REGISTER_SELECT_MASK 0x20000
+#define VGA_SEQUENCER_RESET_CONTROL__VGA_MODE_AUTO_TRIGGER_REGISTER_SELECT__SHIFT 0x11
+#define VGA_SEQUENCER_RESET_CONTROL__VGA_MODE_AUTO_TRIGGER_INDEX_SELECT_MASK 0xfc0000
+#define VGA_SEQUENCER_RESET_CONTROL__VGA_MODE_AUTO_TRIGGER_INDEX_SELECT__SHIFT 0x12
+#define VGA_MODE_CONTROL__VGA_ATI_LINEAR_MASK 0x1
+#define VGA_MODE_CONTROL__VGA_ATI_LINEAR__SHIFT 0x0
+#define VGA_MODE_CONTROL__VGA_LUT_PALETTE_UPDATE_MODE_MASK 0x30
+#define VGA_MODE_CONTROL__VGA_LUT_PALETTE_UPDATE_MODE__SHIFT 0x4
+#define VGA_MODE_CONTROL__VGA_128K_APERTURE_PAGING_MASK 0x100
+#define VGA_MODE_CONTROL__VGA_128K_APERTURE_PAGING__SHIFT 0x8
+#define VGA_MODE_CONTROL__VGA_TEXT_132_COLUMNS_EN_MASK 0x10000
+#define VGA_MODE_CONTROL__VGA_TEXT_132_COLUMNS_EN__SHIFT 0x10
+#define VGA_SURFACE_PITCH_SELECT__VGA_SURFACE_PITCH_SELECT_MASK 0x3
+#define VGA_SURFACE_PITCH_SELECT__VGA_SURFACE_PITCH_SELECT__SHIFT 0x0
+#define VGA_SURFACE_PITCH_SELECT__VGA_SURFACE_HEIGHT_SELECT_MASK 0x300
+#define VGA_SURFACE_PITCH_SELECT__VGA_SURFACE_HEIGHT_SELECT__SHIFT 0x8
+#define VGA_MEMORY_BASE_ADDRESS__VGA_MEMORY_BASE_ADDRESS_MASK 0xffffffff
+#define VGA_MEMORY_BASE_ADDRESS__VGA_MEMORY_BASE_ADDRESS__SHIFT 0x0
+#define VGA_MEMORY_BASE_ADDRESS_HIGH__VGA_MEMORY_BASE_ADDRESS_HIGH_MASK 0xff
+#define VGA_MEMORY_BASE_ADDRESS_HIGH__VGA_MEMORY_BASE_ADDRESS_HIGH__SHIFT 0x0
+#define VGA_DISPBUF1_SURFACE_ADDR__VGA_DISPBUF1_SURFACE_ADDR_MASK 0x1ffffff
+#define VGA_DISPBUF1_SURFACE_ADDR__VGA_DISPBUF1_SURFACE_ADDR__SHIFT 0x0
+#define VGA_DISPBUF2_SURFACE_ADDR__VGA_DISPBUF2_SURFACE_ADDR_MASK 0x1ffffff
+#define VGA_DISPBUF2_SURFACE_ADDR__VGA_DISPBUF2_SURFACE_ADDR__SHIFT 0x0
+#define VGA_HDP_CONTROL__VGA_MEM_PAGE_SELECT_EN_MASK 0x1
+#define VGA_HDP_CONTROL__VGA_MEM_PAGE_SELECT_EN__SHIFT 0x0
+#define VGA_HDP_CONTROL__VGA_MEMORY_DISABLE_MASK 0x10
+#define VGA_HDP_CONTROL__VGA_MEMORY_DISABLE__SHIFT 0x4
+#define VGA_HDP_CONTROL__VGA_RBBM_LOCK_DISABLE_MASK 0x100
+#define VGA_HDP_CONTROL__VGA_RBBM_LOCK_DISABLE__SHIFT 0x8
+#define VGA_HDP_CONTROL__VGA_SOFT_RESET_MASK 0x10000
+#define VGA_HDP_CONTROL__VGA_SOFT_RESET__SHIFT 0x10
+#define VGA_HDP_CONTROL__VGA_TEST_RESET_CONTROL_MASK 0x1000000
+#define VGA_HDP_CONTROL__VGA_TEST_RESET_CONTROL__SHIFT 0x18
+#define VGA_CACHE_CONTROL__VGA_WRITE_THROUGH_CACHE_DIS_MASK 0x1
+#define VGA_CACHE_CONTROL__VGA_WRITE_THROUGH_CACHE_DIS__SHIFT 0x0
+#define VGA_CACHE_CONTROL__VGA_READ_CACHE_DISABLE_MASK 0x100
+#define VGA_CACHE_CONTROL__VGA_READ_CACHE_DISABLE__SHIFT 0x8
+#define VGA_CACHE_CONTROL__VGA_READ_BUFFER_INVALIDATE_MASK 0x10000
+#define VGA_CACHE_CONTROL__VGA_READ_BUFFER_INVALIDATE__SHIFT 0x10
+#define VGA_CACHE_CONTROL__VGA_DCCIF_W256ONLY_MASK 0x100000
+#define VGA_CACHE_CONTROL__VGA_DCCIF_W256ONLY__SHIFT 0x14
+#define VGA_CACHE_CONTROL__VGA_DCCIF_WC_TIMEOUT_MASK 0x3f000000
+#define VGA_CACHE_CONTROL__VGA_DCCIF_WC_TIMEOUT__SHIFT 0x18
+#define D1VGA_CONTROL__D1VGA_MODE_ENABLE_MASK 0x1
+#define D1VGA_CONTROL__D1VGA_MODE_ENABLE__SHIFT 0x0
+#define D1VGA_CONTROL__D1VGA_TIMING_SELECT_MASK 0x100
+#define D1VGA_CONTROL__D1VGA_TIMING_SELECT__SHIFT 0x8
+#define D1VGA_CONTROL__D1VGA_SYNC_POLARITY_SELECT_MASK 0x200
+#define D1VGA_CONTROL__D1VGA_SYNC_POLARITY_SELECT__SHIFT 0x9
+#define D1VGA_CONTROL__D1VGA_OVERSCAN_COLOR_EN_MASK 0x10000
+#define D1VGA_CONTROL__D1VGA_OVERSCAN_COLOR_EN__SHIFT 0x10
+#define D1VGA_CONTROL__D1VGA_ROTATE_MASK 0x3000000
+#define D1VGA_CONTROL__D1VGA_ROTATE__SHIFT 0x18
+#define D2VGA_CONTROL__D2VGA_MODE_ENABLE_MASK 0x1
+#define D2VGA_CONTROL__D2VGA_MODE_ENABLE__SHIFT 0x0
+#define D2VGA_CONTROL__D2VGA_TIMING_SELECT_MASK 0x100
+#define D2VGA_CONTROL__D2VGA_TIMING_SELECT__SHIFT 0x8
+#define D2VGA_CONTROL__D2VGA_SYNC_POLARITY_SELECT_MASK 0x200
+#define D2VGA_CONTROL__D2VGA_SYNC_POLARITY_SELECT__SHIFT 0x9
+#define D2VGA_CONTROL__D2VGA_OVERSCAN_COLOR_EN_MASK 0x10000
+#define D2VGA_CONTROL__D2VGA_OVERSCAN_COLOR_EN__SHIFT 0x10
+#define D2VGA_CONTROL__D2VGA_ROTATE_MASK 0x3000000
+#define D2VGA_CONTROL__D2VGA_ROTATE__SHIFT 0x18
+#define D3VGA_CONTROL__D3VGA_MODE_ENABLE_MASK 0x1
+#define D3VGA_CONTROL__D3VGA_MODE_ENABLE__SHIFT 0x0
+#define D3VGA_CONTROL__D3VGA_TIMING_SELECT_MASK 0x100
+#define D3VGA_CONTROL__D3VGA_TIMING_SELECT__SHIFT 0x8
+#define D3VGA_CONTROL__D3VGA_SYNC_POLARITY_SELECT_MASK 0x200
+#define D3VGA_CONTROL__D3VGA_SYNC_POLARITY_SELECT__SHIFT 0x9
+#define D3VGA_CONTROL__D3VGA_OVERSCAN_COLOR_EN_MASK 0x10000
+#define D3VGA_CONTROL__D3VGA_OVERSCAN_COLOR_EN__SHIFT 0x10
+#define D3VGA_CONTROL__D3VGA_ROTATE_MASK 0x3000000
+#define D3VGA_CONTROL__D3VGA_ROTATE__SHIFT 0x18
+#define D4VGA_CONTROL__D4VGA_MODE_ENABLE_MASK 0x1
+#define D4VGA_CONTROL__D4VGA_MODE_ENABLE__SHIFT 0x0
+#define D4VGA_CONTROL__D4VGA_TIMING_SELECT_MASK 0x100
+#define D4VGA_CONTROL__D4VGA_TIMING_SELECT__SHIFT 0x8
+#define D4VGA_CONTROL__D4VGA_SYNC_POLARITY_SELECT_MASK 0x200
+#define D4VGA_CONTROL__D4VGA_SYNC_POLARITY_SELECT__SHIFT 0x9
+#define D4VGA_CONTROL__D4VGA_OVERSCAN_COLOR_EN_MASK 0x10000
+#define D4VGA_CONTROL__D4VGA_OVERSCAN_COLOR_EN__SHIFT 0x10
+#define D4VGA_CONTROL__D4VGA_ROTATE_MASK 0x3000000
+#define D4VGA_CONTROL__D4VGA_ROTATE__SHIFT 0x18
+#define D5VGA_CONTROL__D5VGA_MODE_ENABLE_MASK 0x1
+#define D5VGA_CONTROL__D5VGA_MODE_ENABLE__SHIFT 0x0
+#define D5VGA_CONTROL__D5VGA_TIMING_SELECT_MASK 0x100
+#define D5VGA_CONTROL__D5VGA_TIMING_SELECT__SHIFT 0x8
+#define D5VGA_CONTROL__D5VGA_SYNC_POLARITY_SELECT_MASK 0x200
+#define D5VGA_CONTROL__D5VGA_SYNC_POLARITY_SELECT__SHIFT 0x9
+#define D5VGA_CONTROL__D5VGA_OVERSCAN_COLOR_EN_MASK 0x10000
+#define D5VGA_CONTROL__D5VGA_OVERSCAN_COLOR_EN__SHIFT 0x10
+#define D5VGA_CONTROL__D5VGA_ROTATE_MASK 0x3000000
+#define D5VGA_CONTROL__D5VGA_ROTATE__SHIFT 0x18
+#define D6VGA_CONTROL__D6VGA_MODE_ENABLE_MASK 0x1
+#define D6VGA_CONTROL__D6VGA_MODE_ENABLE__SHIFT 0x0
+#define D6VGA_CONTROL__D6VGA_TIMING_SELECT_MASK 0x100
+#define D6VGA_CONTROL__D6VGA_TIMING_SELECT__SHIFT 0x8
+#define D6VGA_CONTROL__D6VGA_SYNC_POLARITY_SELECT_MASK 0x200
+#define D6VGA_CONTROL__D6VGA_SYNC_POLARITY_SELECT__SHIFT 0x9
+#define D6VGA_CONTROL__D6VGA_OVERSCAN_COLOR_EN_MASK 0x10000
+#define D6VGA_CONTROL__D6VGA_OVERSCAN_COLOR_EN__SHIFT 0x10
+#define D6VGA_CONTROL__D6VGA_ROTATE_MASK 0x3000000
+#define D6VGA_CONTROL__D6VGA_ROTATE__SHIFT 0x18
+#define VGA_HW_DEBUG__VGA_HW_DEBUG_MASK 0xffffffff
+#define VGA_HW_DEBUG__VGA_HW_DEBUG__SHIFT 0x0
+#define VGA_STATUS__VGA_MEM_ACCESS_STATUS_MASK 0x1
+#define VGA_STATUS__VGA_MEM_ACCESS_STATUS__SHIFT 0x0
+#define VGA_STATUS__VGA_REG_ACCESS_STATUS_MASK 0x2
+#define VGA_STATUS__VGA_REG_ACCESS_STATUS__SHIFT 0x1
+#define VGA_STATUS__VGA_DISPLAY_SWITCH_STATUS_MASK 0x4
+#define VGA_STATUS__VGA_DISPLAY_SWITCH_STATUS__SHIFT 0x2
+#define VGA_STATUS__VGA_MODE_AUTO_TRIGGER_STATUS_MASK 0x8
+#define VGA_STATUS__VGA_MODE_AUTO_TRIGGER_STATUS__SHIFT 0x3
+#define VGA_INTERRUPT_CONTROL__VGA_MEM_ACCESS_INT_MASK_MASK 0x1
+#define VGA_INTERRUPT_CONTROL__VGA_MEM_ACCESS_INT_MASK__SHIFT 0x0
+#define VGA_INTERRUPT_CONTROL__VGA_REG_ACCESS_INT_MASK_MASK 0x100
+#define VGA_INTERRUPT_CONTROL__VGA_REG_ACCESS_INT_MASK__SHIFT 0x8
+#define VGA_INTERRUPT_CONTROL__VGA_DISPLAY_SWITCH_INT_MASK_MASK 0x10000
+#define VGA_INTERRUPT_CONTROL__VGA_DISPLAY_SWITCH_INT_MASK__SHIFT 0x10
+#define VGA_INTERRUPT_CONTROL__VGA_MODE_AUTO_TRIGGER_INT_MASK_MASK 0x1000000
+#define VGA_INTERRUPT_CONTROL__VGA_MODE_AUTO_TRIGGER_INT_MASK__SHIFT 0x18
+#define VGA_STATUS_CLEAR__VGA_MEM_ACCESS_INT_CLEAR_MASK 0x1
+#define VGA_STATUS_CLEAR__VGA_MEM_ACCESS_INT_CLEAR__SHIFT 0x0
+#define VGA_STATUS_CLEAR__VGA_REG_ACCESS_INT_CLEAR_MASK 0x100
+#define VGA_STATUS_CLEAR__VGA_REG_ACCESS_INT_CLEAR__SHIFT 0x8
+#define VGA_STATUS_CLEAR__VGA_DISPLAY_SWITCH_INT_CLEAR_MASK 0x10000
+#define VGA_STATUS_CLEAR__VGA_DISPLAY_SWITCH_INT_CLEAR__SHIFT 0x10
+#define VGA_STATUS_CLEAR__VGA_MODE_AUTO_TRIGGER_INT_CLEAR_MASK 0x1000000
+#define VGA_STATUS_CLEAR__VGA_MODE_AUTO_TRIGGER_INT_CLEAR__SHIFT 0x18
+#define VGA_INTERRUPT_STATUS__VGA_MEM_ACCESS_INT_STATUS_MASK 0x1
+#define VGA_INTERRUPT_STATUS__VGA_MEM_ACCESS_INT_STATUS__SHIFT 0x0
+#define VGA_INTERRUPT_STATUS__VGA_REG_ACCESS_INT_STATUS_MASK 0x2
+#define VGA_INTERRUPT_STATUS__VGA_REG_ACCESS_INT_STATUS__SHIFT 0x1
+#define VGA_INTERRUPT_STATUS__VGA_DISPLAY_SWITCH_INT_STATUS_MASK 0x4
+#define VGA_INTERRUPT_STATUS__VGA_DISPLAY_SWITCH_INT_STATUS__SHIFT 0x2
+#define VGA_INTERRUPT_STATUS__VGA_MODE_AUTO_TRIGGER_INT_STATUS_MASK 0x8
+#define VGA_INTERRUPT_STATUS__VGA_MODE_AUTO_TRIGGER_INT_STATUS__SHIFT 0x3
+#define VGA_MAIN_CONTROL__VGA_CRTC_TIMEOUT_MASK 0x3
+#define VGA_MAIN_CONTROL__VGA_CRTC_TIMEOUT__SHIFT 0x0
+#define VGA_MAIN_CONTROL__VGA_RENDER_TIMEOUT_COUNT_MASK 0x18
+#define VGA_MAIN_CONTROL__VGA_RENDER_TIMEOUT_COUNT__SHIFT 0x3
+#define VGA_MAIN_CONTROL__VGA_VIRTUAL_VERTICAL_RETRACE_DURATION_MASK 0xe0
+#define VGA_MAIN_CONTROL__VGA_VIRTUAL_VERTICAL_RETRACE_DURATION__SHIFT 0x5
+#define VGA_MAIN_CONTROL__VGA_READBACK_VGA_VSTATUS_SOURCE_SELECT_MASK 0x300
+#define VGA_MAIN_CONTROL__VGA_READBACK_VGA_VSTATUS_SOURCE_SELECT__SHIFT 0x8
+#define VGA_MAIN_CONTROL__VGA_MC_WRITE_CLEAN_WAIT_DELAY_MASK 0xf000
+#define VGA_MAIN_CONTROL__VGA_MC_WRITE_CLEAN_WAIT_DELAY__SHIFT 0xc
+#define VGA_MAIN_CONTROL__VGA_READBACK_NO_DISPLAY_SOURCE_SELECT_MASK 0x30000
+#define VGA_MAIN_CONTROL__VGA_READBACK_NO_DISPLAY_SOURCE_SELECT__SHIFT 0x10
+#define VGA_MAIN_CONTROL__VGA_READBACK_CRT_INTR_SOURCE_SELECT_MASK 0x3000000
+#define VGA_MAIN_CONTROL__VGA_READBACK_CRT_INTR_SOURCE_SELECT__SHIFT 0x18
+#define VGA_MAIN_CONTROL__VGA_READBACK_SENSE_SWITCH_SELECT_MASK 0x4000000
+#define VGA_MAIN_CONTROL__VGA_READBACK_SENSE_SWITCH_SELECT__SHIFT 0x1a
+#define VGA_MAIN_CONTROL__VGA_READ_URGENT_ENABLE_MASK 0x8000000
+#define VGA_MAIN_CONTROL__VGA_READ_URGENT_ENABLE__SHIFT 0x1b
+#define VGA_MAIN_CONTROL__VGA_WRITES_URGENT_ENABLE_MASK 0x10000000
+#define VGA_MAIN_CONTROL__VGA_WRITES_URGENT_ENABLE__SHIFT 0x1c
+#define VGA_MAIN_CONTROL__VGA_EXTERNAL_DAC_SENSE_MASK 0x20000000
+#define VGA_MAIN_CONTROL__VGA_EXTERNAL_DAC_SENSE__SHIFT 0x1d
+#define VGA_MAIN_CONTROL__VGA_MAIN_TEST_VSTATUS_NO_DISPLAY_CRTC_TIMEOUT_MASK 0x80000000
+#define VGA_MAIN_CONTROL__VGA_MAIN_TEST_VSTATUS_NO_DISPLAY_CRTC_TIMEOUT__SHIFT 0x1f
+#define VGA_TEST_CONTROL__VGA_TEST_ENABLE_MASK 0x1
+#define VGA_TEST_CONTROL__VGA_TEST_ENABLE__SHIFT 0x0
+#define VGA_TEST_CONTROL__VGA_TEST_RENDER_START_MASK 0x100
+#define VGA_TEST_CONTROL__VGA_TEST_RENDER_START__SHIFT 0x8
+#define VGA_TEST_CONTROL__VGA_TEST_RENDER_DONE_MASK 0x10000
+#define VGA_TEST_CONTROL__VGA_TEST_RENDER_DONE__SHIFT 0x10
+#define VGA_TEST_CONTROL__VGA_TEST_RENDER_DISPBUF_SELECT_MASK 0x1000000
+#define VGA_TEST_CONTROL__VGA_TEST_RENDER_DISPBUF_SELECT__SHIFT 0x18
+#define VGA_DEBUG_READBACK_INDEX__VGA_DEBUG_READBACK_INDEX_MASK 0xff
+#define VGA_DEBUG_READBACK_INDEX__VGA_DEBUG_READBACK_INDEX__SHIFT 0x0
+#define VGA_DEBUG_READBACK_DATA__VGA_DEBUG_READBACK_DATA_MASK 0xffffffff
+#define VGA_DEBUG_READBACK_DATA__VGA_DEBUG_READBACK_DATA__SHIFT 0x0
+#define VGA_MEM_WRITE_PAGE_ADDR__VGA_MEM_WRITE_PAGE0_ADDR_MASK 0x3ff
+#define VGA_MEM_WRITE_PAGE_ADDR__VGA_MEM_WRITE_PAGE0_ADDR__SHIFT 0x0
+#define VGA_MEM_WRITE_PAGE_ADDR__VGA_MEM_WRITE_PAGE1_ADDR_MASK 0x3ff0000
+#define VGA_MEM_WRITE_PAGE_ADDR__VGA_MEM_WRITE_PAGE1_ADDR__SHIFT 0x10
+#define VGA_MEM_READ_PAGE_ADDR__VGA_MEM_READ_PAGE0_ADDR_MASK 0x3ff
+#define VGA_MEM_READ_PAGE_ADDR__VGA_MEM_READ_PAGE0_ADDR__SHIFT 0x0
+#define VGA_MEM_READ_PAGE_ADDR__VGA_MEM_READ_PAGE1_ADDR_MASK 0x3ff0000
+#define VGA_MEM_READ_PAGE_ADDR__VGA_MEM_READ_PAGE1_ADDR__SHIFT 0x10
+#define VGA_TEST_DEBUG_INDEX__VGA_TEST_DEBUG_INDEX_MASK 0xff
+#define VGA_TEST_DEBUG_INDEX__VGA_TEST_DEBUG_INDEX__SHIFT 0x0
+#define VGA_TEST_DEBUG_INDEX__VGA_TEST_DEBUG_WRITE_EN_MASK 0x100
+#define VGA_TEST_DEBUG_INDEX__VGA_TEST_DEBUG_WRITE_EN__SHIFT 0x8
+#define VGA_TEST_DEBUG_DATA__VGA_TEST_DEBUG_DATA_MASK 0xffffffff
+#define VGA_TEST_DEBUG_DATA__VGA_TEST_DEBUG_DATA__SHIFT 0x0
+#define VGADCC_DBG_DCCIF_C__DBG_DCCIF_C_MASK 0xffffffff
+#define VGADCC_DBG_DCCIF_C__DBG_DCCIF_C__SHIFT 0x0
+#define BPHYC_DAC_MACRO_CNTL__BPHYC_DAC_WHITE_LEVEL_MASK 0x3
+#define BPHYC_DAC_MACRO_CNTL__BPHYC_DAC_WHITE_LEVEL__SHIFT 0x0
+#define BPHYC_DAC_MACRO_CNTL__BPHYC_DAC_WHITE_FINE_CONTROL_MASK 0x3f00
+#define BPHYC_DAC_MACRO_CNTL__BPHYC_DAC_WHITE_FINE_CONTROL__SHIFT 0x8
+#define BPHYC_DAC_MACRO_CNTL__BPHYC_DAC_BANDGAP_ADJUSTMENT_MASK 0x3f0000
+#define BPHYC_DAC_MACRO_CNTL__BPHYC_DAC_BANDGAP_ADJUSTMENT__SHIFT 0x10
+#define BPHYC_DAC_MACRO_CNTL__BPHYC_DAC_ANALOG_MONITOR_MASK 0xf000000
+#define BPHYC_DAC_MACRO_CNTL__BPHYC_DAC_ANALOG_MONITOR__SHIFT 0x18
+#define BPHYC_DAC_MACRO_CNTL__BPHYC_DAC_COREMON_MASK 0x10000000
+#define BPHYC_DAC_MACRO_CNTL__BPHYC_DAC_COREMON__SHIFT 0x1c
+#define BPHYC_DAC_AUTO_CALIB_CONTROL__BPHYC_DAC_CAL_INITB_MASK 0x1
+#define BPHYC_DAC_AUTO_CALIB_CONTROL__BPHYC_DAC_CAL_INITB__SHIFT 0x0
+#define BPHYC_DAC_AUTO_CALIB_CONTROL__BPHYC_DAC_CAL_EN_MASK 0x2
+#define BPHYC_DAC_AUTO_CALIB_CONTROL__BPHYC_DAC_CAL_EN__SHIFT 0x1
+#define BPHYC_DAC_AUTO_CALIB_CONTROL__BPHYC_DAC_CAL_DACADJ_EN_MASK 0x4
+#define BPHYC_DAC_AUTO_CALIB_CONTROL__BPHYC_DAC_CAL_DACADJ_EN__SHIFT 0x2
+#define BPHYC_DAC_AUTO_CALIB_CONTROL__BPHYC_DAC_CAL_WAIT_ADJUST_MASK 0x3ff0
+#define BPHYC_DAC_AUTO_CALIB_CONTROL__BPHYC_DAC_CAL_WAIT_ADJUST__SHIFT 0x4
+#define BPHYC_DAC_AUTO_CALIB_CONTROL__BPHYC_DAC_CAL_MASK_MASK 0x700000
+#define BPHYC_DAC_AUTO_CALIB_CONTROL__BPHYC_DAC_CAL_MASK__SHIFT 0x14
+#define BPHYC_DAC_AUTO_CALIB_CONTROL__BPHYC_DAC_CAL_COMPLETE_MASK 0x10000000
+#define BPHYC_DAC_AUTO_CALIB_CONTROL__BPHYC_DAC_CAL_COMPLETE__SHIFT 0x1c
+#define DPG_PIPE_ARBITRATION_CONTROL1__PIXEL_DURATION_MASK 0xffff
+#define DPG_PIPE_ARBITRATION_CONTROL1__PIXEL_DURATION__SHIFT 0x0
+#define DPG_PIPE_ARBITRATION_CONTROL1__BASE_WEIGHT_MASK 0xffff0000
+#define DPG_PIPE_ARBITRATION_CONTROL1__BASE_WEIGHT__SHIFT 0x10
+#define DPG_PIPE_ARBITRATION_CONTROL2__TIME_WEIGHT_MASK 0xffff
+#define DPG_PIPE_ARBITRATION_CONTROL2__TIME_WEIGHT__SHIFT 0x0
+#define DPG_PIPE_ARBITRATION_CONTROL2__URGENCY_WEIGHT_MASK 0xffff0000
+#define DPG_PIPE_ARBITRATION_CONTROL2__URGENCY_WEIGHT__SHIFT 0x10
+#define DPG_WATERMARK_MASK_CONTROL__STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK_MASK 0x7
+#define DPG_WATERMARK_MASK_CONTROL__STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK__SHIFT 0x0
+#define DPG_WATERMARK_MASK_CONTROL__URGENCY_WATERMARK_MASK_MASK 0x700
+#define DPG_WATERMARK_MASK_CONTROL__URGENCY_WATERMARK_MASK__SHIFT 0x8
+#define DPG_WATERMARK_MASK_CONTROL__NB_PSTATE_CHANGE_WATERMARK_MASK_MASK 0x70000
+#define DPG_WATERMARK_MASK_CONTROL__NB_PSTATE_CHANGE_WATERMARK_MASK__SHIFT 0x10
+#define DPG_WATERMARK_MASK_CONTROL__DISABLE_FLIP_URGENT_MASK 0x1000000
+#define DPG_WATERMARK_MASK_CONTROL__DISABLE_FLIP_URGENT__SHIFT 0x18
+#define DPG_PIPE_URGENCY_CONTROL__URGENCY_LOW_WATERMARK_MASK 0xffff
+#define DPG_PIPE_URGENCY_CONTROL__URGENCY_LOW_WATERMARK__SHIFT 0x0
+#define DPG_PIPE_URGENCY_CONTROL__URGENCY_HIGH_WATERMARK_MASK 0xffff0000
+#define DPG_PIPE_URGENCY_CONTROL__URGENCY_HIGH_WATERMARK__SHIFT 0x10
+#define DPG_PIPE_DPM_CONTROL__DPM_ENABLE_MASK 0x1
+#define DPG_PIPE_DPM_CONTROL__DPM_ENABLE__SHIFT 0x0
+#define DPG_PIPE_DPM_CONTROL__MCLK_CHANGE_ENABLE_MASK 0x10
+#define DPG_PIPE_DPM_CONTROL__MCLK_CHANGE_ENABLE__SHIFT 0x4
+#define DPG_PIPE_DPM_CONTROL__MCLK_CHANGE_FORCE_ON_MASK 0x100
+#define DPG_PIPE_DPM_CONTROL__MCLK_CHANGE_FORCE_ON__SHIFT 0x8
+#define DPG_PIPE_DPM_CONTROL__MCLK_CHANGE_WATERMARK_MASK_MASK 0x3000
+#define DPG_PIPE_DPM_CONTROL__MCLK_CHANGE_WATERMARK_MASK__SHIFT 0xc
+#define DPG_PIPE_DPM_CONTROL__MCLK_CHANGE_WATERMARK_MASK 0xffff0000
+#define DPG_PIPE_DPM_CONTROL__MCLK_CHANGE_WATERMARK__SHIFT 0x10
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_ENABLE_MASK 0x1
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_ENABLE__SHIFT 0x0
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_CURSOR_MASK 0x10
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_CURSOR__SHIFT 0x4
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_ICON_MASK 0x20
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_ICON__SHIFT 0x5
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_VGA_MASK 0x40
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_VGA__SHIFT 0x6
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_FBC_MASK 0x80
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_FBC__SHIFT 0x7
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_WM_HIGH_FORCE_ON_MASK 0x100
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_WM_HIGH_FORCE_ON__SHIFT 0x8
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_WM_HIGH_EXCLUDES_VBLANK_MASK 0x200
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_WM_HIGH_EXCLUDES_VBLANK__SHIFT 0x9
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_URGENT_IN_NOT_SELF_REFRESH_MASK 0x400
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_URGENT_IN_NOT_SELF_REFRESH__SHIFT 0xa
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_SELF_REFRESH_FORCE_ON_MASK 0x800
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_SELF_REFRESH_FORCE_ON__SHIFT 0xb
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK 0xffff0000
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_EXIT_SELF_REFRESH_WATERMARK__SHIFT 0x10
+#define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_ENABLE_MASK 0x1
+#define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_ENABLE__SHIFT 0x0
+#define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_URGENT_DURING_REQUEST_MASK 0x10
+#define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_URGENT_DURING_REQUEST__SHIFT 0x4
+#define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST_MASK 0x100
+#define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST__SHIFT 0x8
+#define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_FORCE_ON_MASK 0x200
+#define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_FORCE_ON__SHIFT 0x9
+#define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_ALLOW_FOR_URGENT_MASK 0x400
+#define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_ALLOW_FOR_URGENT__SHIFT 0xa
+#define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_WATERMARK_MASK 0xffff8000
+#define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_WATERMARK__SHIFT 0xf
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_ENABLE_NONLPTCH_MASK 0x1
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_ENABLE_NONLPTCH__SHIFT 0x0
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_CURSOR_NONLPTCH_MASK 0x10
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_CURSOR_NONLPTCH__SHIFT 0x4
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_ICON_NONLPTCH_MASK 0x20
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_ICON_NONLPTCH__SHIFT 0x5
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_VGA_NONLPTCH_MASK 0x40
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_VGA_NONLPTCH__SHIFT 0x6
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_FBC_NONLPTCH_MASK 0x80
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_FBC_NONLPTCH__SHIFT 0x7
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_WM_HIGH_FORCE_ON_NONLPTCH_MASK 0x100
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_WM_HIGH_FORCE_ON_NONLPTCH__SHIFT 0x8
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_WM_HIGH_EXCLUDES_VBLANK_NONLPTCH_MASK 0x200
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_WM_HIGH_EXCLUDES_VBLANK_NONLPTCH__SHIFT 0x9
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_URGENT_IN_NOT_SELF_REFRESH_NONLPTCH_MASK 0x400
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_URGENT_IN_NOT_SELF_REFRESH_NONLPTCH__SHIFT 0xa
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_SELF_REFRESH_FORCE_ON_NONLPTCH_MASK 0x800
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_SELF_REFRESH_FORCE_ON_NONLPTCH__SHIFT 0xb
+#define DPG_REPEATER_PROGRAM__REG_DPG_DMIFRC_REPEATER_MASK 0x7
+#define DPG_REPEATER_PROGRAM__REG_DPG_DMIFRC_REPEATER__SHIFT 0x0
+#define DPG_REPEATER_PROGRAM__REG_DMIFRC_DPG_REPEATER_MASK 0x70
+#define DPG_REPEATER_PROGRAM__REG_DMIFRC_DPG_REPEATER__SHIFT 0x4
+#define DPG_HW_DEBUG_A__DPG_HW_DEBUG_A_MASK 0xffffffff
+#define DPG_HW_DEBUG_A__DPG_HW_DEBUG_A__SHIFT 0x0
+#define DPG_HW_DEBUG_B__DPG_HW_DEBUG_B_MASK 0xffffffff
+#define DPG_HW_DEBUG_B__DPG_HW_DEBUG_B__SHIFT 0x0
+#define DPG_HW_DEBUG_11__DPG_HW_DEBUG_11_MASK 0x1
+#define DPG_HW_DEBUG_11__DPG_HW_DEBUG_11__SHIFT 0x0
+#define DPG_CHK_PRE_PROC_CNTL__DPG_DISABLE_DMIF_BUF_CHK_MASK 0x1
+#define DPG_CHK_PRE_PROC_CNTL__DPG_DISABLE_DMIF_BUF_CHK__SHIFT 0x0
+#define DPG_DVMM_STATUS__DPG_DVMM_FORCED_FLIP_TO_UNMAPPED_MASK 0x1
+#define DPG_DVMM_STATUS__DPG_DVMM_FORCED_FLIP_TO_UNMAPPED__SHIFT 0x0
+#define DPG_DVMM_STATUS__DPG_DVMM_FORCED_FLIP_TO_MAPPED_MASK 0x2
+#define DPG_DVMM_STATUS__DPG_DVMM_FORCED_FLIP_TO_MAPPED__SHIFT 0x1
+#define DPG_DVMM_STATUS__DPG_DVMM_FORCED_FLIP_TO_UNMAPPED_CLR_MASK 0x10
+#define DPG_DVMM_STATUS__DPG_DVMM_FORCED_FLIP_TO_UNMAPPED_CLR__SHIFT 0x4
+#define DPG_DVMM_STATUS__DPG_DVMM_FORCED_FLIP_TO_MAPPED_CLR_MASK 0x20
+#define DPG_DVMM_STATUS__DPG_DVMM_FORCED_FLIP_TO_MAPPED_CLR__SHIFT 0x5
+#define DPG_TEST_DEBUG_INDEX__DPG_TEST_DEBUG_INDEX_MASK 0xff
+#define DPG_TEST_DEBUG_INDEX__DPG_TEST_DEBUG_INDEX__SHIFT 0x0
+#define DPG_TEST_DEBUG_INDEX__DPG_TEST_DEBUG_WRITE_EN_MASK 0x100
+#define DPG_TEST_DEBUG_INDEX__DPG_TEST_DEBUG_WRITE_EN__SHIFT 0x8
+#define DPG_TEST_DEBUG_DATA__DPG_TEST_DEBUG_DATA_MASK 0xffffffff
+#define DPG_TEST_DEBUG_DATA__DPG_TEST_DEBUG_DATA__SHIFT 0x0
+#define DPGV0_PIPE_ARBITRATION_CONTROL1__PIXEL_DURATION_MASK 0xffff
+#define DPGV0_PIPE_ARBITRATION_CONTROL1__PIXEL_DURATION__SHIFT 0x0
+#define DPGV0_PIPE_ARBITRATION_CONTROL1__BASE_WEIGHT_MASK 0xffff0000
+#define DPGV0_PIPE_ARBITRATION_CONTROL1__BASE_WEIGHT__SHIFT 0x10
+#define DPGV1_PIPE_ARBITRATION_CONTROL1__PIXEL_DURATION_MASK 0xffff
+#define DPGV1_PIPE_ARBITRATION_CONTROL1__PIXEL_DURATION__SHIFT 0x0
+#define DPGV1_PIPE_ARBITRATION_CONTROL1__BASE_WEIGHT_MASK 0xffff0000
+#define DPGV1_PIPE_ARBITRATION_CONTROL1__BASE_WEIGHT__SHIFT 0x10
+#define DPGV0_PIPE_ARBITRATION_CONTROL2__TIME_WEIGHT_MASK 0xffff
+#define DPGV0_PIPE_ARBITRATION_CONTROL2__TIME_WEIGHT__SHIFT 0x0
+#define DPGV0_PIPE_ARBITRATION_CONTROL2__URGENCY_WEIGHT_MASK 0xffff0000
+#define DPGV0_PIPE_ARBITRATION_CONTROL2__URGENCY_WEIGHT__SHIFT 0x10
+#define DPGV1_PIPE_ARBITRATION_CONTROL2__TIME_WEIGHT_MASK 0xffff
+#define DPGV1_PIPE_ARBITRATION_CONTROL2__TIME_WEIGHT__SHIFT 0x0
+#define DPGV1_PIPE_ARBITRATION_CONTROL2__URGENCY_WEIGHT_MASK 0xffff0000
+#define DPGV1_PIPE_ARBITRATION_CONTROL2__URGENCY_WEIGHT__SHIFT 0x10
+#define DPGV0_WATERMARK_MASK_CONTROL__STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK_MASK 0x3
+#define DPGV0_WATERMARK_MASK_CONTROL__STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK__SHIFT 0x0
+#define DPGV0_WATERMARK_MASK_CONTROL__URGENCY_WATERMARK_MASK_MASK 0x300
+#define DPGV0_WATERMARK_MASK_CONTROL__URGENCY_WATERMARK_MASK__SHIFT 0x8
+#define DPGV0_WATERMARK_MASK_CONTROL__NB_PSTATE_CHANGE_WATERMARK_MASK_MASK 0x30000
+#define DPGV0_WATERMARK_MASK_CONTROL__NB_PSTATE_CHANGE_WATERMARK_MASK__SHIFT 0x10
+#define DPGV0_WATERMARK_MASK_CONTROL__DISABLE_FLIP_URGENT_MASK 0x1000000
+#define DPGV0_WATERMARK_MASK_CONTROL__DISABLE_FLIP_URGENT__SHIFT 0x18
+#define DPGV1_WATERMARK_MASK_CONTROL__STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK_MASK 0x3
+#define DPGV1_WATERMARK_MASK_CONTROL__STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK__SHIFT 0x0
+#define DPGV1_WATERMARK_MASK_CONTROL__URGENCY_WATERMARK_MASK_MASK 0x300
+#define DPGV1_WATERMARK_MASK_CONTROL__URGENCY_WATERMARK_MASK__SHIFT 0x8
+#define DPGV1_WATERMARK_MASK_CONTROL__NB_PSTATE_CHANGE_WATERMARK_MASK_MASK 0x30000
+#define DPGV1_WATERMARK_MASK_CONTROL__NB_PSTATE_CHANGE_WATERMARK_MASK__SHIFT 0x10
+#define DPGV1_WATERMARK_MASK_CONTROL__DISABLE_FLIP_URGENT_MASK 0x1000000
+#define DPGV1_WATERMARK_MASK_CONTROL__DISABLE_FLIP_URGENT__SHIFT 0x18
+#define DPGV0_PIPE_URGENCY_CONTROL__URGENCY_LOW_WATERMARK_MASK 0xffff
+#define DPGV0_PIPE_URGENCY_CONTROL__URGENCY_LOW_WATERMARK__SHIFT 0x0
+#define DPGV0_PIPE_URGENCY_CONTROL__URGENCY_HIGH_WATERMARK_MASK 0xffff0000
+#define DPGV0_PIPE_URGENCY_CONTROL__URGENCY_HIGH_WATERMARK__SHIFT 0x10
+#define DPGV1_PIPE_URGENCY_CONTROL__URGENCY_LOW_WATERMARK_MASK 0xffff
+#define DPGV1_PIPE_URGENCY_CONTROL__URGENCY_LOW_WATERMARK__SHIFT 0x0
+#define DPGV1_PIPE_URGENCY_CONTROL__URGENCY_HIGH_WATERMARK_MASK 0xffff0000
+#define DPGV1_PIPE_URGENCY_CONTROL__URGENCY_HIGH_WATERMARK__SHIFT 0x10
+#define DPGV0_PIPE_DPM_CONTROL__DPM_ENABLE_MASK 0x1
+#define DPGV0_PIPE_DPM_CONTROL__DPM_ENABLE__SHIFT 0x0
+#define DPGV0_PIPE_DPM_CONTROL__MCLK_CHANGE_ENABLE_MASK 0x10
+#define DPGV0_PIPE_DPM_CONTROL__MCLK_CHANGE_ENABLE__SHIFT 0x4
+#define DPGV0_PIPE_DPM_CONTROL__MCLK_CHANGE_FORCE_ON_MASK 0x100
+#define DPGV0_PIPE_DPM_CONTROL__MCLK_CHANGE_FORCE_ON__SHIFT 0x8
+#define DPGV0_PIPE_DPM_CONTROL__MCLK_CHANGE_WATERMARK_MASK_MASK 0x3000
+#define DPGV0_PIPE_DPM_CONTROL__MCLK_CHANGE_WATERMARK_MASK__SHIFT 0xc
+#define DPGV0_PIPE_DPM_CONTROL__MCLK_CHANGE_WATERMARK_MASK 0xffff0000
+#define DPGV0_PIPE_DPM_CONTROL__MCLK_CHANGE_WATERMARK__SHIFT 0x10
+#define DPGV1_PIPE_DPM_CONTROL__DPM_ENABLE_MASK 0x1
+#define DPGV1_PIPE_DPM_CONTROL__DPM_ENABLE__SHIFT 0x0
+#define DPGV1_PIPE_DPM_CONTROL__MCLK_CHANGE_ENABLE_MASK 0x10
+#define DPGV1_PIPE_DPM_CONTROL__MCLK_CHANGE_ENABLE__SHIFT 0x4
+#define DPGV1_PIPE_DPM_CONTROL__MCLK_CHANGE_FORCE_ON_MASK 0x100
+#define DPGV1_PIPE_DPM_CONTROL__MCLK_CHANGE_FORCE_ON__SHIFT 0x8
+#define DPGV1_PIPE_DPM_CONTROL__MCLK_CHANGE_WATERMARK_MASK_MASK 0x3000
+#define DPGV1_PIPE_DPM_CONTROL__MCLK_CHANGE_WATERMARK_MASK__SHIFT 0xc
+#define DPGV1_PIPE_DPM_CONTROL__MCLK_CHANGE_WATERMARK_MASK 0xffff0000
+#define DPGV1_PIPE_DPM_CONTROL__MCLK_CHANGE_WATERMARK__SHIFT 0x10
+#define DPGV0_PIPE_STUTTER_CONTROL__STUTTER_ENABLE_MASK 0x1
+#define DPGV0_PIPE_STUTTER_CONTROL__STUTTER_ENABLE__SHIFT 0x0
+#define DPGV0_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_CURSOR_MASK 0x10
+#define DPGV0_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_CURSOR__SHIFT 0x4
+#define DPGV0_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_ICON_MASK 0x20
+#define DPGV0_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_ICON__SHIFT 0x5
+#define DPGV0_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_VGA_MASK 0x40
+#define DPGV0_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_VGA__SHIFT 0x6
+#define DPGV0_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_FBC_MASK 0x80
+#define DPGV0_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_FBC__SHIFT 0x7
+#define DPGV0_PIPE_STUTTER_CONTROL__STUTTER_WM_HIGH_FORCE_ON_MASK 0x100
+#define DPGV0_PIPE_STUTTER_CONTROL__STUTTER_WM_HIGH_FORCE_ON__SHIFT 0x8
+#define DPGV0_PIPE_STUTTER_CONTROL__STUTTER_WM_HIGH_EXCLUDES_VBLANK_MASK 0x200
+#define DPGV0_PIPE_STUTTER_CONTROL__STUTTER_WM_HIGH_EXCLUDES_VBLANK__SHIFT 0x9
+#define DPGV0_PIPE_STUTTER_CONTROL__STUTTER_URGENT_IN_NOT_SELF_REFRESH_MASK 0x400
+#define DPGV0_PIPE_STUTTER_CONTROL__STUTTER_URGENT_IN_NOT_SELF_REFRESH__SHIFT 0xa
+#define DPGV0_PIPE_STUTTER_CONTROL__STUTTER_SELF_REFRESH_FORCE_ON_MASK 0x800
+#define DPGV0_PIPE_STUTTER_CONTROL__STUTTER_SELF_REFRESH_FORCE_ON__SHIFT 0xb
+#define DPGV0_PIPE_STUTTER_CONTROL__STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK 0xffff0000
+#define DPGV0_PIPE_STUTTER_CONTROL__STUTTER_EXIT_SELF_REFRESH_WATERMARK__SHIFT 0x10
+#define DPGV1_PIPE_STUTTER_CONTROL__STUTTER_ENABLE_MASK 0x1
+#define DPGV1_PIPE_STUTTER_CONTROL__STUTTER_ENABLE__SHIFT 0x0
+#define DPGV1_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_CURSOR_MASK 0x10
+#define DPGV1_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_CURSOR__SHIFT 0x4
+#define DPGV1_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_ICON_MASK 0x20
+#define DPGV1_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_ICON__SHIFT 0x5
+#define DPGV1_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_VGA_MASK 0x40
+#define DPGV1_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_VGA__SHIFT 0x6
+#define DPGV1_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_FBC_MASK 0x80
+#define DPGV1_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_FBC__SHIFT 0x7
+#define DPGV1_PIPE_STUTTER_CONTROL__STUTTER_WM_HIGH_FORCE_ON_MASK 0x100
+#define DPGV1_PIPE_STUTTER_CONTROL__STUTTER_WM_HIGH_FORCE_ON__SHIFT 0x8
+#define DPGV1_PIPE_STUTTER_CONTROL__STUTTER_WM_HIGH_EXCLUDES_VBLANK_MASK 0x200
+#define DPGV1_PIPE_STUTTER_CONTROL__STUTTER_WM_HIGH_EXCLUDES_VBLANK__SHIFT 0x9
+#define DPGV1_PIPE_STUTTER_CONTROL__STUTTER_URGENT_IN_NOT_SELF_REFRESH_MASK 0x400
+#define DPGV1_PIPE_STUTTER_CONTROL__STUTTER_URGENT_IN_NOT_SELF_REFRESH__SHIFT 0xa
+#define DPGV1_PIPE_STUTTER_CONTROL__STUTTER_SELF_REFRESH_FORCE_ON_MASK 0x800
+#define DPGV1_PIPE_STUTTER_CONTROL__STUTTER_SELF_REFRESH_FORCE_ON__SHIFT 0xb
+#define DPGV1_PIPE_STUTTER_CONTROL__STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK 0xffff0000
+#define DPGV1_PIPE_STUTTER_CONTROL__STUTTER_EXIT_SELF_REFRESH_WATERMARK__SHIFT 0x10
+#define DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_ENABLE_MASK 0x1
+#define DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_ENABLE__SHIFT 0x0
+#define DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_URGENT_DURING_REQUEST_MASK 0x10
+#define DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_URGENT_DURING_REQUEST__SHIFT 0x4
+#define DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST_MASK 0x100
+#define DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST__SHIFT 0x8
+#define DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_FORCE_ON_MASK 0x200
+#define DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_FORCE_ON__SHIFT 0x9
+#define DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_ALLOW_FOR_URGENT_MASK 0x400
+#define DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_ALLOW_FOR_URGENT__SHIFT 0xa
+#define DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_WATERMARK_MASK 0xffff0000
+#define DPGV0_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_WATERMARK__SHIFT 0x10
+#define DPGV1_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_ENABLE_MASK 0x1
+#define DPGV1_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_ENABLE__SHIFT 0x0
+#define DPGV1_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_URGENT_DURING_REQUEST_MASK 0x10
+#define DPGV1_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_URGENT_DURING_REQUEST__SHIFT 0x4
+#define DPGV1_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST_MASK 0x100
+#define DPGV1_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST__SHIFT 0x8
+#define DPGV1_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_FORCE_ON_MASK 0x200
+#define DPGV1_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_FORCE_ON__SHIFT 0x9
+#define DPGV1_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_ALLOW_FOR_URGENT_MASK 0x400
+#define DPGV1_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_ALLOW_FOR_URGENT__SHIFT 0xa
+#define DPGV1_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_WATERMARK_MASK 0xffff0000
+#define DPGV1_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_WATERMARK__SHIFT 0x10
+#define DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_ENABLE_NONLPTCH_MASK 0x1
+#define DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_ENABLE_NONLPTCH__SHIFT 0x0
+#define DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_CURSOR_NONLPTCH_MASK 0x10
+#define DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_CURSOR_NONLPTCH__SHIFT 0x4
+#define DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_ICON_NONLPTCH_MASK 0x20
+#define DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_ICON_NONLPTCH__SHIFT 0x5
+#define DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_VGA_NONLPTCH_MASK 0x40
+#define DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_VGA_NONLPTCH__SHIFT 0x6
+#define DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_FBC_NONLPTCH_MASK 0x80
+#define DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_FBC_NONLPTCH__SHIFT 0x7
+#define DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_WM_HIGH_FORCE_ON_NONLPTCH_MASK 0x100
+#define DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_WM_HIGH_FORCE_ON_NONLPTCH__SHIFT 0x8
+#define DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_WM_HIGH_EXCLUDES_VBLANK_NONLPTCH_MASK 0x200
+#define DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_WM_HIGH_EXCLUDES_VBLANK_NONLPTCH__SHIFT 0x9
+#define DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_URGENT_IN_NOT_SELF_REFRESH_NONLPTCH_MASK 0x400
+#define DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_URGENT_IN_NOT_SELF_REFRESH_NONLPTCH__SHIFT 0xa
+#define DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_SELF_REFRESH_FORCE_ON_NONLPTCH_MASK 0x800
+#define DPGV0_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_SELF_REFRESH_FORCE_ON_NONLPTCH__SHIFT 0xb
+#define DPGV1_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_ENABLE_NONLPTCH_MASK 0x1
+#define DPGV1_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_ENABLE_NONLPTCH__SHIFT 0x0
+#define DPGV1_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_CURSOR_NONLPTCH_MASK 0x10
+#define DPGV1_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_CURSOR_NONLPTCH__SHIFT 0x4
+#define DPGV1_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_ICON_NONLPTCH_MASK 0x20
+#define DPGV1_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_ICON_NONLPTCH__SHIFT 0x5
+#define DPGV1_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_VGA_NONLPTCH_MASK 0x40
+#define DPGV1_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_VGA_NONLPTCH__SHIFT 0x6
+#define DPGV1_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_FBC_NONLPTCH_MASK 0x80
+#define DPGV1_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_FBC_NONLPTCH__SHIFT 0x7
+#define DPGV1_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_WM_HIGH_FORCE_ON_NONLPTCH_MASK 0x100
+#define DPGV1_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_WM_HIGH_FORCE_ON_NONLPTCH__SHIFT 0x8
+#define DPGV1_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_WM_HIGH_EXCLUDES_VBLANK_NONLPTCH_MASK 0x200
+#define DPGV1_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_WM_HIGH_EXCLUDES_VBLANK_NONLPTCH__SHIFT 0x9
+#define DPGV1_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_URGENT_IN_NOT_SELF_REFRESH_NONLPTCH_MASK 0x400
+#define DPGV1_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_URGENT_IN_NOT_SELF_REFRESH_NONLPTCH__SHIFT 0xa
+#define DPGV1_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_SELF_REFRESH_FORCE_ON_NONLPTCH_MASK 0x800
+#define DPGV1_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_SELF_REFRESH_FORCE_ON_NONLPTCH__SHIFT 0xb
+#define DPGV0_REPEATER_PROGRAM__REG_DPG_DMIFRC_REPEATER_MASK 0x7
+#define DPGV0_REPEATER_PROGRAM__REG_DPG_DMIFRC_REPEATER__SHIFT 0x0
+#define DPGV0_REPEATER_PROGRAM__REG_DMIFRC_DPG_REPEATER_MASK 0x70
+#define DPGV0_REPEATER_PROGRAM__REG_DMIFRC_DPG_REPEATER__SHIFT 0x4
+#define DPGV1_REPEATER_PROGRAM__REG_DPG_DMIFRC_REPEATER_MASK 0x7
+#define DPGV1_REPEATER_PROGRAM__REG_DPG_DMIFRC_REPEATER__SHIFT 0x0
+#define DPGV1_REPEATER_PROGRAM__REG_DMIFRC_DPG_REPEATER_MASK 0x70
+#define DPGV1_REPEATER_PROGRAM__REG_DMIFRC_DPG_REPEATER__SHIFT 0x4
+#define DPGV0_HW_DEBUG_A__DPG_HW_DEBUG_A_MASK 0xffffffff
+#define DPGV0_HW_DEBUG_A__DPG_HW_DEBUG_A__SHIFT 0x0
+#define DPGV1_HW_DEBUG_A__DPG_HW_DEBUG_A_MASK 0xffffffff
+#define DPGV1_HW_DEBUG_A__DPG_HW_DEBUG_A__SHIFT 0x0
+#define DPGV0_HW_DEBUG_B__DPG_HW_DEBUG_B_MASK 0xffffffff
+#define DPGV0_HW_DEBUG_B__DPG_HW_DEBUG_B__SHIFT 0x0
+#define DPGV1_HW_DEBUG_B__DPG_HW_DEBUG_B_MASK 0xffffffff
+#define DPGV1_HW_DEBUG_B__DPG_HW_DEBUG_B__SHIFT 0x0
+#define DPGV0_HW_DEBUG_11__DPG_HW_DEBUG_11_MASK 0x1
+#define DPGV0_HW_DEBUG_11__DPG_HW_DEBUG_11__SHIFT 0x0
+#define DPGV1_HW_DEBUG_11__DPG_HW_DEBUG_11_MASK 0x1
+#define DPGV1_HW_DEBUG_11__DPG_HW_DEBUG_11__SHIFT 0x0
+#define DPGV0_CHK_PRE_PROC_CNTL__DPG_DISABLE_DMIF_BUF_CHK_MASK 0x1
+#define DPGV0_CHK_PRE_PROC_CNTL__DPG_DISABLE_DMIF_BUF_CHK__SHIFT 0x0
+#define DPGV1_CHK_PRE_PROC_CNTL__DPG_DISABLE_DMIF_BUF_CHK_MASK 0x1
+#define DPGV1_CHK_PRE_PROC_CNTL__DPG_DISABLE_DMIF_BUF_CHK__SHIFT 0x0
+#define DPGV_TEST_DEBUG_INDEX__DPG_TEST_DEBUG_INDEX_MASK 0xff
+#define DPGV_TEST_DEBUG_INDEX__DPG_TEST_DEBUG_INDEX__SHIFT 0x0
+#define DPGV_TEST_DEBUG_INDEX__DPG_TEST_DEBUG_WRITE_EN_MASK 0x100
+#define DPGV_TEST_DEBUG_INDEX__DPG_TEST_DEBUG_WRITE_EN__SHIFT 0x8
+#define DPGV_TEST_DEBUG_DATA__DPG_TEST_DEBUG_DATA_MASK 0xffffffff
+#define DPGV_TEST_DEBUG_DATA__DPG_TEST_DEBUG_DATA__SHIFT 0x0
+#define AZROOT_IMMEDIATE_COMMAND_OUTPUT_INTERFACE_INDEX__IMMEDIATE_COMMAND_WRITE_MASK 0x1ffff
+#define AZROOT_IMMEDIATE_COMMAND_OUTPUT_INTERFACE_INDEX__IMMEDIATE_COMMAND_WRITE__SHIFT 0x0
+#define AZROOT_IMMEDIATE_COMMAND_OUTPUT_INTERFACE_DATA__IMMEDIATE_COMMAND_WRITE_MASK 0xffffffff
+#define AZROOT_IMMEDIATE_COMMAND_OUTPUT_INTERFACE_DATA__IMMEDIATE_COMMAND_WRITE__SHIFT 0x0
+#define AZALIA_F2_CODEC_ROOT_PARAMETER_VENDOR_AND_DEVICE_ID__AZALIA_CODEC_ROOT_PARAMETER_VENDOR_AND_DEVICE_ID_MASK 0xffffffff
+#define AZALIA_F2_CODEC_ROOT_PARAMETER_VENDOR_AND_DEVICE_ID__AZALIA_CODEC_ROOT_PARAMETER_VENDOR_AND_DEVICE_ID__SHIFT 0x0
+#define AZALIA_F2_CODEC_ROOT_PARAMETER_REVISION_ID__AZALIA_CODEC_ROOT_PARAMETER_REVISION_ID_MASK 0xffffffff
+#define AZALIA_F2_CODEC_ROOT_PARAMETER_REVISION_ID__AZALIA_CODEC_ROOT_PARAMETER_REVISION_ID__SHIFT 0x0
+#define AZALIA_F2_CODEC_ROOT_PARAMETER_SUBORDINATE_NODE_COUNT__AZALIA_CODEC_ROOT_PARAMETER_SUBORDINATE_NODE_COUNT_MASK 0xffffffff
+#define AZALIA_F2_CODEC_ROOT_PARAMETER_SUBORDINATE_NODE_COUNT__AZALIA_CODEC_ROOT_PARAMETER_SUBORDINATE_NODE_COUNT__SHIFT 0x0
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_SUBORDINATE_NODE_COUNT__AZALIA_CODEC_FUNCTION_PARAMETER_SUBORDINATE_NODE_COUNT_MASK 0xffffffff
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_SUBORDINATE_NODE_COUNT__AZALIA_CODEC_FUNCTION_PARAMETER_SUBORDINATE_NODE_COUNT__SHIFT 0x0
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_GROUP_TYPE__AZALIA_CODEC_FUNCTION_PARAMETER_GROUP_TYPE_MASK 0xffffffff
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_GROUP_TYPE__AZALIA_CODEC_FUNCTION_PARAMETER_GROUP_TYPE__SHIFT 0x0
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_RATE_CAPABILITIES_MASK 0xfff
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_RATE_CAPABILITIES__SHIFT 0x0
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_BIT_CAPABILITIES_MASK 0x1f0000
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_BIT_CAPABILITIES__SHIFT 0x10
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS__AZALIA_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS_MASK 0xffffffff
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS__AZALIA_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS__SHIFT 0x0
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_POWER_STATES__AZALIA_CODEC_FUNCTION_PARAMETER_POWER_STATES_MASK 0x3fffffff
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_POWER_STATES__AZALIA_CODEC_FUNCTION_PARAMETER_POWER_STATES__SHIFT 0x0
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_POWER_STATES__CLKSTOP_MASK 0x40000000
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_POWER_STATES__CLKSTOP__SHIFT 0x1e
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_POWER_STATES__EPSS_MASK 0x80000000
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_POWER_STATES__EPSS__SHIFT 0x1f
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_POWER_STATE__POWER_STATE_SET_MASK 0xf
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_POWER_STATE__POWER_STATE_SET__SHIFT 0x0
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_POWER_STATE__POWER_STATE_ACT_MASK 0xf0
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_POWER_STATE__POWER_STATE_ACT__SHIFT 0x4
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_POWER_STATE__CLKSTOPOK_MASK 0x200
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_POWER_STATE__CLKSTOPOK__SHIFT 0x9
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_POWER_STATE__POWER_STATE_SETTINGS_RESET_MASK 0x400
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_POWER_STATE__POWER_STATE_SETTINGS_RESET__SHIFT 0xa
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESET__CODEC_RESET_MASK 0x1
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESET__CODEC_RESET__SHIFT 0x0
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE0_MASK 0xff
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE0__SHIFT 0x0
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE1_MASK 0xff00
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE1__SHIFT 0x8
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE2_MASK 0xff0000
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE2__SHIFT 0x10
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE3_MASK 0xff000000
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE3__SHIFT 0x18
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID_2__SUBSYSTEM_ID_BYTE1_MASK 0xff
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID_2__SUBSYSTEM_ID_BYTE1__SHIFT 0x0
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID_3__SUBSYSTEM_ID_BYTE2_MASK 0xff
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID_3__SUBSYSTEM_ID_BYTE2__SHIFT 0x0
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID_4__SUBSYSTEM_ID_BYTE3_MASK 0xff
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID_4__SUBSYSTEM_ID_BYTE3__SHIFT 0x0
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_CONVERTER_SYNCHRONIZATION__CONVERTER_SYNCHRONIZATION_MASK 0x7f
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_CONVERTER_SYNCHRONIZATION__CONVERTER_SYNCHRONIZATION__SHIFT 0x0
+#define AZALIA_F0_CODEC_ROOT_PARAMETER_VENDOR_AND_DEVICE_ID__AZALIA_CODEC_ROOT_PARAMETER_VENDOR_AND_DEVICE_ID_MASK 0xffffffff
+#define AZALIA_F0_CODEC_ROOT_PARAMETER_VENDOR_AND_DEVICE_ID__AZALIA_CODEC_ROOT_PARAMETER_VENDOR_AND_DEVICE_ID__SHIFT 0x0
+#define AZALIA_F0_CODEC_ROOT_PARAMETER_REVISION_ID__AZALIA_CODEC_ROOT_PARAMETER_REVISION_ID_MASK 0xffffffff
+#define AZALIA_F0_CODEC_ROOT_PARAMETER_REVISION_ID__AZALIA_CODEC_ROOT_PARAMETER_REVISION_ID__SHIFT 0x0
+#define AZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL__HBR_CHANNEL_COUNT_MASK 0x7
+#define AZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL__HBR_CHANNEL_COUNT__SHIFT 0x0
+#define AZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL__COMPRESSED_CHANNEL_COUNT_MASK 0x70
+#define AZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL__COMPRESSED_CHANNEL_COUNT__SHIFT 0x4
+#define AZALIA_F0_CODEC_RESYNC_FIFO_CONTROL__RESYNC_FIFO_STARTUP_KEEPOUT_WINDOW_MASK 0x3f
+#define AZALIA_F0_CODEC_RESYNC_FIFO_CONTROL__RESYNC_FIFO_STARTUP_KEEPOUT_WINDOW__SHIFT 0x0
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_GROUP_TYPE__AZALIA_CODEC_FUNCTION_PARAMETER_GROUP_TYPE_MASK 0xffffffff
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_GROUP_TYPE__AZALIA_CODEC_FUNCTION_PARAMETER_GROUP_TYPE__SHIFT 0x0
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_RATE_CAPABILITIES_MASK 0xfff
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_RATE_CAPABILITIES__SHIFT 0x0
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_BIT_CAPABILITIES_MASK 0x1f0000
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_BIT_CAPABILITIES__SHIFT 0x10
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS__AZALIA_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS_MASK 0xffffffff
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS__AZALIA_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS__SHIFT 0x0
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES__AZALIA_CODEC_FUNCTION_PARAMETER_POWER_STATES_MASK 0x3fffffff
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES__AZALIA_CODEC_FUNCTION_PARAMETER_POWER_STATES__SHIFT 0x0
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES__CLKSTOP_MASK 0x40000000
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES__CLKSTOP__SHIFT 0x1e
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES__EPSS_MASK 0x80000000
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES__EPSS__SHIFT 0x1f
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_POWER_STATE__POWER_STATE_SET_MASK 0xf
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_POWER_STATE__POWER_STATE_SET__SHIFT 0x0
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_POWER_STATE__POWER_STATE_ACT_MASK 0xf0
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_POWER_STATE__POWER_STATE_ACT__SHIFT 0x4
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_POWER_STATE__CLKSTOPOK_MASK 0x200
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_POWER_STATE__CLKSTOPOK__SHIFT 0x9
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_POWER_STATE__POWER_STATE_SETTINGS_RESET_MASK 0x400
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_POWER_STATE__POWER_STATE_SETTINGS_RESET__SHIFT 0xa
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_RESET__CODEC_RESET_MASK 0x1
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_RESET__CODEC_RESET__SHIFT 0x0
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE0_MASK 0xff
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE0__SHIFT 0x0
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE1_MASK 0xff00
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE1__SHIFT 0x8
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE2_MASK 0xff0000
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE2__SHIFT 0x10
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE3_MASK 0xff000000
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE3__SHIFT 0x18
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_CONVERTER_SYNCHRONIZATION__CONVERTER_SYNCHRONIZATION_MASK 0x7f
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_CONVERTER_SYNCHRONIZATION__CONVERTER_SYNCHRONIZATION__SHIFT 0x0
+#define CC_RCU_DC_AUDIO_PORT_CONNECTIVITY__PORT_CONNECTIVITY_MASK 0x7
+#define CC_RCU_DC_AUDIO_PORT_CONNECTIVITY__PORT_CONNECTIVITY__SHIFT 0x0
+#define CC_RCU_DC_AUDIO_PORT_CONNECTIVITY__PORT_CONNECTIVITY_OVERRIDE_ENABLE_MASK 0x10
+#define CC_RCU_DC_AUDIO_PORT_CONNECTIVITY__PORT_CONNECTIVITY_OVERRIDE_ENABLE__SHIFT 0x4
+#define CC_RCU_DC_AUDIO_INPUT_PORT_CONNECTIVITY__INPUT_PORT_CONNECTIVITY_MASK 0x7
+#define CC_RCU_DC_AUDIO_INPUT_PORT_CONNECTIVITY__INPUT_PORT_CONNECTIVITY__SHIFT 0x0
+#define CC_RCU_DC_AUDIO_INPUT_PORT_CONNECTIVITY__INPUT_PORT_CONNECTIVITY_OVERRIDE_ENABLE_MASK 0x10
+#define CC_RCU_DC_AUDIO_INPUT_PORT_CONNECTIVITY__INPUT_PORT_CONNECTIVITY_OVERRIDE_ENABLE__SHIFT 0x4
+#define AZALIA_F0_CODEC_DEBUG__DISABLE_FORMAT_COMPARISON_MASK 0x3f
+#define AZALIA_F0_CODEC_DEBUG__DISABLE_FORMAT_COMPARISON__SHIFT 0x0
+#define AZALIA_F0_CODEC_DEBUG__CODEC_DEBUG_MASK 0xffffffc0
+#define AZALIA_F0_CODEC_DEBUG__CODEC_DEBUG__SHIFT 0x6
+#define AZALIA_F0_GTC_GROUP_OFFSET0__GTC_GROUP_OFFSET0_MASK 0xffffffff
+#define AZALIA_F0_GTC_GROUP_OFFSET0__GTC_GROUP_OFFSET0__SHIFT 0x0
+#define AZALIA_F0_GTC_GROUP_OFFSET1__GTC_GROUP_OFFSET1_MASK 0xffffffff
+#define AZALIA_F0_GTC_GROUP_OFFSET1__GTC_GROUP_OFFSET1__SHIFT 0x0
+#define AZALIA_F0_GTC_GROUP_OFFSET2__GTC_GROUP_OFFSET2_MASK 0xffffffff
+#define AZALIA_F0_GTC_GROUP_OFFSET2__GTC_GROUP_OFFSET2__SHIFT 0x0
+#define AZALIA_F0_GTC_GROUP_OFFSET3__GTC_GROUP_OFFSET3_MASK 0xffffffff
+#define AZALIA_F0_GTC_GROUP_OFFSET3__GTC_GROUP_OFFSET3__SHIFT 0x0
+#define AZALIA_F0_GTC_GROUP_OFFSET4__GTC_GROUP_OFFSET4_MASK 0xffffffff
+#define AZALIA_F0_GTC_GROUP_OFFSET4__GTC_GROUP_OFFSET4__SHIFT 0x0
+#define AZALIA_F0_GTC_GROUP_OFFSET5__GTC_GROUP_OFFSET5_MASK 0xffffffff
+#define AZALIA_F0_GTC_GROUP_OFFSET5__GTC_GROUP_OFFSET5__SHIFT 0x0
+#define AZALIA_F0_GTC_GROUP_OFFSET6__GTC_GROUP_OFFSET6_MASK 0xffffffff
+#define AZALIA_F0_GTC_GROUP_OFFSET6__GTC_GROUP_OFFSET6__SHIFT 0x0
+#define GLOBAL_CAPABILITIES__SIXTY_FOUR_BIT_ADDRESS_SUPPORTED_MASK 0x1
+#define GLOBAL_CAPABILITIES__SIXTY_FOUR_BIT_ADDRESS_SUPPORTED__SHIFT 0x0
+#define GLOBAL_CAPABILITIES__NUMBER_OF_SERIAL_DATA_OUTPUT_SIGNALS_MASK 0x6
+#define GLOBAL_CAPABILITIES__NUMBER_OF_SERIAL_DATA_OUTPUT_SIGNALS__SHIFT 0x1
+#define GLOBAL_CAPABILITIES__NUMBER_OF_BIDIRECTIONAL_STREAMS_SUPPORTED_MASK 0xf8
+#define GLOBAL_CAPABILITIES__NUMBER_OF_BIDIRECTIONAL_STREAMS_SUPPORTED__SHIFT 0x3
+#define GLOBAL_CAPABILITIES__NUMBER_OF_INPUT_STREAMS_SUPPORTED_MASK 0xf00
+#define GLOBAL_CAPABILITIES__NUMBER_OF_INPUT_STREAMS_SUPPORTED__SHIFT 0x8
+#define GLOBAL_CAPABILITIES__NUMBER_OF_OUTPUT_STREAMS_SUPPORTED_MASK 0xf000
+#define GLOBAL_CAPABILITIES__NUMBER_OF_OUTPUT_STREAMS_SUPPORTED__SHIFT 0xc
+#define MINOR_VERSION__MINOR_VERSION_MASK 0xff
+#define MINOR_VERSION__MINOR_VERSION__SHIFT 0x0
+#define MAJOR_VERSION__MAJOR_VERSION_MASK 0xff
+#define MAJOR_VERSION__MAJOR_VERSION__SHIFT 0x0
+#define OUTPUT_PAYLOAD_CAPABILITY__OUTPUT_PAYLOAD_CAPABILITY_MASK 0xffff
+#define OUTPUT_PAYLOAD_CAPABILITY__OUTPUT_PAYLOAD_CAPABILITY__SHIFT 0x0
+#define INPUT_PAYLOAD_CAPABILITY__INPUT_PAYLOAD_CAPABILITY_MASK 0xffff
+#define INPUT_PAYLOAD_CAPABILITY__INPUT_PAYLOAD_CAPABILITY__SHIFT 0x0
+#define GLOBAL_CONTROL__CONTROLLER_RESET_MASK 0x1
+#define GLOBAL_CONTROL__CONTROLLER_RESET__SHIFT 0x0
+#define GLOBAL_CONTROL__FLUSH_CONTROL_MASK 0x2
+#define GLOBAL_CONTROL__FLUSH_CONTROL__SHIFT 0x1
+#define GLOBAL_CONTROL__ACCEPT_UNSOLICITED_RESPONSE_ENABLE_MASK 0x100
+#define GLOBAL_CONTROL__ACCEPT_UNSOLICITED_RESPONSE_ENABLE__SHIFT 0x8
+#define WAKE_ENABLE__SDIN_WAKE_ENABLE_FLAG_MASK 0x1
+#define WAKE_ENABLE__SDIN_WAKE_ENABLE_FLAG__SHIFT 0x0
+#define STATE_CHANGE_STATUS__STATE_CHANGE_STATUS_MASK 0x1
+#define STATE_CHANGE_STATUS__STATE_CHANGE_STATUS__SHIFT 0x0
+#define GLOBAL_STATUS__FLUSH_STATUS_MASK 0x2
+#define GLOBAL_STATUS__FLUSH_STATUS__SHIFT 0x1
+#define OUTPUT_STREAM_PAYLOAD_CAPABILITY__OUTSTRMPAY_MASK 0xffff
+#define OUTPUT_STREAM_PAYLOAD_CAPABILITY__OUTSTRMPAY__SHIFT 0x0
+#define INPUT_STREAM_PAYLOAD_CAPABILITY__INSTRMPAY_MASK 0xffff
+#define INPUT_STREAM_PAYLOAD_CAPABILITY__INSTRMPAY__SHIFT 0x0
+#define INTERRUPT_CONTROL__STREAM_0_INTERRUPT_ENABLE_MASK 0x1
+#define INTERRUPT_CONTROL__STREAM_0_INTERRUPT_ENABLE__SHIFT 0x0
+#define INTERRUPT_CONTROL__STREAM_1_INTERRUPT_ENABLE_MASK 0x2
+#define INTERRUPT_CONTROL__STREAM_1_INTERRUPT_ENABLE__SHIFT 0x1
+#define INTERRUPT_CONTROL__STREAM_2_INTERRUPT_ENABLE_MASK 0x4
+#define INTERRUPT_CONTROL__STREAM_2_INTERRUPT_ENABLE__SHIFT 0x2
+#define INTERRUPT_CONTROL__STREAM_3_INTERRUPT_ENABLE_MASK 0x8
+#define INTERRUPT_CONTROL__STREAM_3_INTERRUPT_ENABLE__SHIFT 0x3
+#define INTERRUPT_CONTROL__STREAM_4_INTERRUPT_ENABLE_MASK 0x10
+#define INTERRUPT_CONTROL__STREAM_4_INTERRUPT_ENABLE__SHIFT 0x4
+#define INTERRUPT_CONTROL__STREAM_5_INTERRUPT_ENABLE_MASK 0x20
+#define INTERRUPT_CONTROL__STREAM_5_INTERRUPT_ENABLE__SHIFT 0x5
+#define INTERRUPT_CONTROL__STREAM_6_INTERRUPT_ENABLE_MASK 0x40
+#define INTERRUPT_CONTROL__STREAM_6_INTERRUPT_ENABLE__SHIFT 0x6
+#define INTERRUPT_CONTROL__STREAM_7_INTERRUPT_ENABLE_MASK 0x80
+#define INTERRUPT_CONTROL__STREAM_7_INTERRUPT_ENABLE__SHIFT 0x7
+#define INTERRUPT_CONTROL__STREAM_8_INTERRUPT_ENABLE_MASK 0x100
+#define INTERRUPT_CONTROL__STREAM_8_INTERRUPT_ENABLE__SHIFT 0x8
+#define INTERRUPT_CONTROL__STREAM_9_INTERRUPT_ENABLE_MASK 0x200
+#define INTERRUPT_CONTROL__STREAM_9_INTERRUPT_ENABLE__SHIFT 0x9
+#define INTERRUPT_CONTROL__STREAM_10_INTERRUPT_ENABLE_MASK 0x400
+#define INTERRUPT_CONTROL__STREAM_10_INTERRUPT_ENABLE__SHIFT 0xa
+#define INTERRUPT_CONTROL__STREAM_11_INTERRUPT_ENABLE_MASK 0x800
+#define INTERRUPT_CONTROL__STREAM_11_INTERRUPT_ENABLE__SHIFT 0xb
+#define INTERRUPT_CONTROL__STREAM_12_INTERRUPT_ENABLE_MASK 0x1000
+#define INTERRUPT_CONTROL__STREAM_12_INTERRUPT_ENABLE__SHIFT 0xc
+#define INTERRUPT_CONTROL__STREAM_13_INTERRUPT_ENABLE_MASK 0x2000
+#define INTERRUPT_CONTROL__STREAM_13_INTERRUPT_ENABLE__SHIFT 0xd
+#define INTERRUPT_CONTROL__STREAM_14_INTERRUPT_ENABLE_MASK 0x4000
+#define INTERRUPT_CONTROL__STREAM_14_INTERRUPT_ENABLE__SHIFT 0xe
+#define INTERRUPT_CONTROL__STREAM_15_INTERRUPT_ENABLE_MASK 0x8000
+#define INTERRUPT_CONTROL__STREAM_15_INTERRUPT_ENABLE__SHIFT 0xf
+#define INTERRUPT_CONTROL__CONTROLLER_INTERRUPT_ENABLE_MASK 0x40000000
+#define INTERRUPT_CONTROL__CONTROLLER_INTERRUPT_ENABLE__SHIFT 0x1e
+#define INTERRUPT_CONTROL__GLOBAL_INTERRUPT_ENABLE_MASK 0x80000000
+#define INTERRUPT_CONTROL__GLOBAL_INTERRUPT_ENABLE__SHIFT 0x1f
+#define INTERRUPT_STATUS__STREAM_0_INTERRUPT_STATUS_MASK 0x1
+#define INTERRUPT_STATUS__STREAM_0_INTERRUPT_STATUS__SHIFT 0x0
+#define INTERRUPT_STATUS__STREAM_1_INTERRUPT_STATUS_MASK 0x2
+#define INTERRUPT_STATUS__STREAM_1_INTERRUPT_STATUS__SHIFT 0x1
+#define INTERRUPT_STATUS__STREAM_2_INTERRUPT_STATUS_MASK 0x4
+#define INTERRUPT_STATUS__STREAM_2_INTERRUPT_STATUS__SHIFT 0x2
+#define INTERRUPT_STATUS__STREAM_3_INTERRUPT_STATUS_MASK 0x8
+#define INTERRUPT_STATUS__STREAM_3_INTERRUPT_STATUS__SHIFT 0x3
+#define INTERRUPT_STATUS__STREAM_4_INTERRUPT_STATUS_MASK 0x10
+#define INTERRUPT_STATUS__STREAM_4_INTERRUPT_STATUS__SHIFT 0x4
+#define INTERRUPT_STATUS__STREAM_5_INTERRUPT_STATUS_MASK 0x20
+#define INTERRUPT_STATUS__STREAM_5_INTERRUPT_STATUS__SHIFT 0x5
+#define INTERRUPT_STATUS__STREAM_6_INTERRUPT_STATUS_MASK 0x40
+#define INTERRUPT_STATUS__STREAM_6_INTERRUPT_STATUS__SHIFT 0x6
+#define INTERRUPT_STATUS__STREAM_7_INTERRUPT_STATUS_MASK 0x80
+#define INTERRUPT_STATUS__STREAM_7_INTERRUPT_STATUS__SHIFT 0x7
+#define INTERRUPT_STATUS__STREAM_8_INTERRUPT_STATUS_MASK 0x100
+#define INTERRUPT_STATUS__STREAM_8_INTERRUPT_STATUS__SHIFT 0x8
+#define INTERRUPT_STATUS__STREAM_9_INTERRUPT_STATUS_MASK 0x200
+#define INTERRUPT_STATUS__STREAM_9_INTERRUPT_STATUS__SHIFT 0x9
+#define INTERRUPT_STATUS__STREAM_10_INTERRUPT_STATUS_MASK 0x400
+#define INTERRUPT_STATUS__STREAM_10_INTERRUPT_STATUS__SHIFT 0xa
+#define INTERRUPT_STATUS__STREAM_11_INTERRUPT_STATUS_MASK 0x800
+#define INTERRUPT_STATUS__STREAM_11_INTERRUPT_STATUS__SHIFT 0xb
+#define INTERRUPT_STATUS__STREAM_12_INTERRUPT_STATUS_MASK 0x1000
+#define INTERRUPT_STATUS__STREAM_12_INTERRUPT_STATUS__SHIFT 0xc
+#define INTERRUPT_STATUS__STREAM_13_INTERRUPT_STATUS_MASK 0x2000
+#define INTERRUPT_STATUS__STREAM_13_INTERRUPT_STATUS__SHIFT 0xd
+#define INTERRUPT_STATUS__STREAM_14_INTERRUPT_STATUS_MASK 0x4000
+#define INTERRUPT_STATUS__STREAM_14_INTERRUPT_STATUS__SHIFT 0xe
+#define INTERRUPT_STATUS__STREAM_15_INTERRUPT_STATUS_MASK 0x8000
+#define INTERRUPT_STATUS__STREAM_15_INTERRUPT_STATUS__SHIFT 0xf
+#define INTERRUPT_STATUS__CONTROLLER_INTERRUPT_STATUS_MASK 0x40000000
+#define INTERRUPT_STATUS__CONTROLLER_INTERRUPT_STATUS__SHIFT 0x1e
+#define INTERRUPT_STATUS__GLOBAL_INTERRUPT_STATUS_MASK 0x80000000
+#define INTERRUPT_STATUS__GLOBAL_INTERRUPT_STATUS__SHIFT 0x1f
+#define WALL_CLOCK_COUNTER__WALL_CLOCK_COUNTER_MASK 0xffffffff
+#define WALL_CLOCK_COUNTER__WALL_CLOCK_COUNTER__SHIFT 0x0
+#define STREAM_SYNCHRONIZATION__STREAM_0_SYNCHRONIZATION_MASK 0x1
+#define STREAM_SYNCHRONIZATION__STREAM_0_SYNCHRONIZATION__SHIFT 0x0
+#define STREAM_SYNCHRONIZATION__STREAM_1_SYNCHRONIZATION_MASK 0x2
+#define STREAM_SYNCHRONIZATION__STREAM_1_SYNCHRONIZATION__SHIFT 0x1
+#define STREAM_SYNCHRONIZATION__STREAM_2_SYNCHRONIZATION_MASK 0x4
+#define STREAM_SYNCHRONIZATION__STREAM_2_SYNCHRONIZATION__SHIFT 0x2
+#define STREAM_SYNCHRONIZATION__STREAM_3_SYNCHRONIZATION_MASK 0x8
+#define STREAM_SYNCHRONIZATION__STREAM_3_SYNCHRONIZATION__SHIFT 0x3
+#define STREAM_SYNCHRONIZATION__STREAM_4_SYNCHRONIZATION_MASK 0x10
+#define STREAM_SYNCHRONIZATION__STREAM_4_SYNCHRONIZATION__SHIFT 0x4
+#define STREAM_SYNCHRONIZATION__STREAM_5_SYNCHRONIZATION_MASK 0x20
+#define STREAM_SYNCHRONIZATION__STREAM_5_SYNCHRONIZATION__SHIFT 0x5
+#define STREAM_SYNCHRONIZATION__STREAM_6_SYNCHRONIZATION_MASK 0x40
+#define STREAM_SYNCHRONIZATION__STREAM_6_SYNCHRONIZATION__SHIFT 0x6
+#define STREAM_SYNCHRONIZATION__STREAM_7_SYNCHRONIZATION_MASK 0x80
+#define STREAM_SYNCHRONIZATION__STREAM_7_SYNCHRONIZATION__SHIFT 0x7
+#define STREAM_SYNCHRONIZATION__STREAM_8_SYNCHRONIZATION_MASK 0x100
+#define STREAM_SYNCHRONIZATION__STREAM_8_SYNCHRONIZATION__SHIFT 0x8
+#define STREAM_SYNCHRONIZATION__STREAM_9_SYNCHRONIZATION_MASK 0x200
+#define STREAM_SYNCHRONIZATION__STREAM_9_SYNCHRONIZATION__SHIFT 0x9
+#define STREAM_SYNCHRONIZATION__STREAM_10_SYNCHRONIZATION_MASK 0x400
+#define STREAM_SYNCHRONIZATION__STREAM_10_SYNCHRONIZATION__SHIFT 0xa
+#define STREAM_SYNCHRONIZATION__STREAM_11_SYNCHRONIZATION_MASK 0x800
+#define STREAM_SYNCHRONIZATION__STREAM_11_SYNCHRONIZATION__SHIFT 0xb
+#define STREAM_SYNCHRONIZATION__STREAM_12_SYNCHRONIZATION_MASK 0x1000
+#define STREAM_SYNCHRONIZATION__STREAM_12_SYNCHRONIZATION__SHIFT 0xc
+#define STREAM_SYNCHRONIZATION__STREAM_13_SYNCHRONIZATION_MASK 0x2000
+#define STREAM_SYNCHRONIZATION__STREAM_13_SYNCHRONIZATION__SHIFT 0xd
+#define STREAM_SYNCHRONIZATION__STREAM_14_SYNCHRONIZATION_MASK 0x4000
+#define STREAM_SYNCHRONIZATION__STREAM_14_SYNCHRONIZATION__SHIFT 0xe
+#define STREAM_SYNCHRONIZATION__STREAM_15_SYNCHRONIZATION_MASK 0x8000
+#define STREAM_SYNCHRONIZATION__STREAM_15_SYNCHRONIZATION__SHIFT 0xf
+#define CORB_LOWER_BASE_ADDRESS__CORB_LOWER_BASE_UNIMPLEMENTED_BITS_MASK 0x7f
+#define CORB_LOWER_BASE_ADDRESS__CORB_LOWER_BASE_UNIMPLEMENTED_BITS__SHIFT 0x0
+#define CORB_LOWER_BASE_ADDRESS__CORB_LOWER_BASE_ADDRESS_MASK 0xffffff80
+#define CORB_LOWER_BASE_ADDRESS__CORB_LOWER_BASE_ADDRESS__SHIFT 0x7
+#define CORB_UPPER_BASE_ADDRESS__CORB_UPPER_BASE_ADDRESS_MASK 0xffffffff
+#define CORB_UPPER_BASE_ADDRESS__CORB_UPPER_BASE_ADDRESS__SHIFT 0x0
+#define CORB_WRITE_POINTER__CORB_WRITE_POINTER_MASK 0xff
+#define CORB_WRITE_POINTER__CORB_WRITE_POINTER__SHIFT 0x0
+#define CORB_READ_POINTER__CORB_READ_POINTER_MASK 0xff
+#define CORB_READ_POINTER__CORB_READ_POINTER__SHIFT 0x0
+#define CORB_READ_POINTER__CORB_READ_POINTER_RESET_MASK 0x8000
+#define CORB_READ_POINTER__CORB_READ_POINTER_RESET__SHIFT 0xf
+#define CORB_CONTROL__CORB_MEMORY_ERROR_INTERRUPT_ENABLE_MASK 0x1
+#define CORB_CONTROL__CORB_MEMORY_ERROR_INTERRUPT_ENABLE__SHIFT 0x0
+#define CORB_CONTROL__ENABLE_CORB_DMA_ENGINE_MASK 0x2
+#define CORB_CONTROL__ENABLE_CORB_DMA_ENGINE__SHIFT 0x1
+#define CORB_STATUS__CORB_MEMORY_ERROR_INDICATION_MASK 0x1
+#define CORB_STATUS__CORB_MEMORY_ERROR_INDICATION__SHIFT 0x0
+#define CORB_SIZE__CORB_SIZE_MASK 0x3
+#define CORB_SIZE__CORB_SIZE__SHIFT 0x0
+#define CORB_SIZE__CORB_SIZE_CAPABILITY_MASK 0xf0
+#define CORB_SIZE__CORB_SIZE_CAPABILITY__SHIFT 0x4
+#define RIRB_LOWER_BASE_ADDRESS__RIRB_LOWER_BASE_UNIMPLEMENTED_BITS_MASK 0x7f
+#define RIRB_LOWER_BASE_ADDRESS__RIRB_LOWER_BASE_UNIMPLEMENTED_BITS__SHIFT 0x0
+#define RIRB_LOWER_BASE_ADDRESS__RIRB_LOWER_BASE_ADDRESS_MASK 0xffffff80
+#define RIRB_LOWER_BASE_ADDRESS__RIRB_LOWER_BASE_ADDRESS__SHIFT 0x7
+#define RIRB_UPPER_BASE_ADDRESS__RIRB_UPPER_BASE_ADDRESS_MASK 0xffffffff
+#define RIRB_UPPER_BASE_ADDRESS__RIRB_UPPER_BASE_ADDRESS__SHIFT 0x0
+#define RIRB_WRITE_POINTER__RIRB_WRITE_POINTER_MASK 0xff
+#define RIRB_WRITE_POINTER__RIRB_WRITE_POINTER__SHIFT 0x0
+#define RIRB_WRITE_POINTER__RIRB_WRITE_POINTER_RESET_MASK 0x8000
+#define RIRB_WRITE_POINTER__RIRB_WRITE_POINTER_RESET__SHIFT 0xf
+#define RESPONSE_INTERRUPT_COUNT__N_RESPONSE_INTERRUPT_COUNT_MASK 0xff
+#define RESPONSE_INTERRUPT_COUNT__N_RESPONSE_INTERRUPT_COUNT__SHIFT 0x0
+#define RIRB_CONTROL__RESPONSE_INTERRUPT_CONTROL_MASK 0x1
+#define RIRB_CONTROL__RESPONSE_INTERRUPT_CONTROL__SHIFT 0x0
+#define RIRB_CONTROL__RIRB_DMA_ENABLE_MASK 0x2
+#define RIRB_CONTROL__RIRB_DMA_ENABLE__SHIFT 0x1
+#define RIRB_CONTROL__RESPONSE_OVERRUN_INTERRUPT_CONTROL_MASK 0x4
+#define RIRB_CONTROL__RESPONSE_OVERRUN_INTERRUPT_CONTROL__SHIFT 0x2
+#define RIRB_STATUS__RESPONSE_INTERRUPT_MASK 0x1
+#define RIRB_STATUS__RESPONSE_INTERRUPT__SHIFT 0x0
+#define RIRB_STATUS__RESPONSE_OVERRUN_INTERRUPT_STATUS_MASK 0x4
+#define RIRB_STATUS__RESPONSE_OVERRUN_INTERRUPT_STATUS__SHIFT 0x2
+#define RIRB_SIZE__RIRB_SIZE_MASK 0x3
+#define RIRB_SIZE__RIRB_SIZE__SHIFT 0x0
+#define RIRB_SIZE__RIRB_SIZE_CAPABILITY_MASK 0xf0
+#define RIRB_SIZE__RIRB_SIZE_CAPABILITY__SHIFT 0x4
+#define IMMEDIATE_COMMAND_OUTPUT_INTERFACE__IMMEDIATE_COMMAND_WRITE_VERB_AND_PAYLOAD_MASK 0xfffffff
+#define IMMEDIATE_COMMAND_OUTPUT_INTERFACE__IMMEDIATE_COMMAND_WRITE_VERB_AND_PAYLOAD__SHIFT 0x0
+#define IMMEDIATE_COMMAND_OUTPUT_INTERFACE__IMMEDIATE_COMMAND_WRITE_CODEC_ADDRESS_MASK 0xf0000000
+#define IMMEDIATE_COMMAND_OUTPUT_INTERFACE__IMMEDIATE_COMMAND_WRITE_CODEC_ADDRESS__SHIFT 0x1c
+#define IMMEDIATE_COMMAND_OUTPUT_INTERFACE_INDEX__IMMEDIATE_COMMAND_WRITE_MASK 0xffff
+#define IMMEDIATE_COMMAND_OUTPUT_INTERFACE_INDEX__IMMEDIATE_COMMAND_WRITE__SHIFT 0x0
+#define IMMEDIATE_COMMAND_OUTPUT_INTERFACE_DATA__IMMEDIATE_COMMAND_WRITE_MASK 0xffffffff
+#define IMMEDIATE_COMMAND_OUTPUT_INTERFACE_DATA__IMMEDIATE_COMMAND_WRITE__SHIFT 0x0
+#define IMMEDIATE_RESPONSE_INPUT_INTERFACE__IMMEDIATE_RESPONSE_READ_MASK 0xffffffff
+#define IMMEDIATE_RESPONSE_INPUT_INTERFACE__IMMEDIATE_RESPONSE_READ__SHIFT 0x0
+#define IMMEDIATE_COMMAND_STATUS__IMMEDIATE_COMMAND_BUSY_MASK 0x1
+#define IMMEDIATE_COMMAND_STATUS__IMMEDIATE_COMMAND_BUSY__SHIFT 0x0
+#define IMMEDIATE_COMMAND_STATUS__IMMEDIATE_RESULT_VALID_MASK 0x2
+#define IMMEDIATE_COMMAND_STATUS__IMMEDIATE_RESULT_VALID__SHIFT 0x1
+#define DMA_POSITION_LOWER_BASE_ADDRESS__DMA_POSITION_BUFFER_ENABLE_MASK 0x1
+#define DMA_POSITION_LOWER_BASE_ADDRESS__DMA_POSITION_BUFFER_ENABLE__SHIFT 0x0
+#define DMA_POSITION_LOWER_BASE_ADDRESS__DMA_POSITION_LOWER_BASE_UNIMPLEMENTED_BITS_MASK 0x7e
+#define DMA_POSITION_LOWER_BASE_ADDRESS__DMA_POSITION_LOWER_BASE_UNIMPLEMENTED_BITS__SHIFT 0x1
+#define DMA_POSITION_LOWER_BASE_ADDRESS__DMA_POSITION_LOWER_BASE_ADDRESS_MASK 0xffffff80
+#define DMA_POSITION_LOWER_BASE_ADDRESS__DMA_POSITION_LOWER_BASE_ADDRESS__SHIFT 0x7
+#define DMA_POSITION_UPPER_BASE_ADDRESS__DMA_POSITION_UPPER_BASE_ADDRESS_MASK 0xffffffff
+#define DMA_POSITION_UPPER_BASE_ADDRESS__DMA_POSITION_UPPER_BASE_ADDRESS__SHIFT 0x0
+#define WALL_CLOCK_COUNTER_ALIAS__WALL_CLOCK_COUNTER_ALIAS_MASK 0xffffffff
+#define WALL_CLOCK_COUNTER_ALIAS__WALL_CLOCK_COUNTER_ALIAS__SHIFT 0x0
+#define OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS__STREAM_RESET_MASK 0x1
+#define OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS__STREAM_RESET__SHIFT 0x0
+#define OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS__STREAM_RUN_MASK 0x2
+#define OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS__STREAM_RUN__SHIFT 0x1
+#define OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS__INTERRUPT_ON_COMPLETION_ENABLE_MASK 0x4
+#define OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS__INTERRUPT_ON_COMPLETION_ENABLE__SHIFT 0x2
+#define OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS__FIFO_ERROR_INTERRUPT_ENABLE_MASK 0x8
+#define OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS__FIFO_ERROR_INTERRUPT_ENABLE__SHIFT 0x3
+#define OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS__DESCRIPTOR_ERROR_INTERRUPT_ENABLE_MASK 0x10
+#define OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS__DESCRIPTOR_ERROR_INTERRUPT_ENABLE__SHIFT 0x4
+#define OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS__STRIPE_CONTROL_MASK 0x30000
+#define OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS__STRIPE_CONTROL__SHIFT 0x10
+#define OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS__TRAFFIC_PRIORITY_MASK 0x40000
+#define OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS__TRAFFIC_PRIORITY__SHIFT 0x12
+#define OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS__STREAM_NUMBER_MASK 0xf00000
+#define OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS__STREAM_NUMBER__SHIFT 0x14
+#define OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS__BUFFER_COMPLETION_INTERRUPT_STATUS_MASK 0x4000000
+#define OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS__BUFFER_COMPLETION_INTERRUPT_STATUS__SHIFT 0x1a
+#define OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS__FIFO_ERROR_MASK 0x8000000
+#define OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS__FIFO_ERROR__SHIFT 0x1b
+#define OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS__DESCRIPTOR_ERROR_MASK 0x10000000
+#define OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS__DESCRIPTOR_ERROR__SHIFT 0x1c
+#define OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS__FIFO_READY_MASK 0x20000000
+#define OUTPUT_STREAM_DESCRIPTOR_CONTROL_AND_STATUS__FIFO_READY__SHIFT 0x1d
+#define OUTPUT_STREAM_DESCRIPTOR_LINK_POSITION_IN_CURRENT_BUFFER__LINK_POSITION_IN_BUFFER_MASK 0xffffffff
+#define OUTPUT_STREAM_DESCRIPTOR_LINK_POSITION_IN_CURRENT_BUFFER__LINK_POSITION_IN_BUFFER__SHIFT 0x0
+#define OUTPUT_STREAM_DESCRIPTOR_CYCLIC_BUFFER_LENGTH__CYCLIC_BUFFER_LENGTH_MASK 0xffffffff
+#define OUTPUT_STREAM_DESCRIPTOR_CYCLIC_BUFFER_LENGTH__CYCLIC_BUFFER_LENGTH__SHIFT 0x0
+#define OUTPUT_STREAM_DESCRIPTOR_LAST_VALID_INDEX__LAST_VALID_INDEX_MASK 0xff
+#define OUTPUT_STREAM_DESCRIPTOR_LAST_VALID_INDEX__LAST_VALID_INDEX__SHIFT 0x0
+#define OUTPUT_STREAM_DESCRIPTOR_FIFO_SIZE__FIFO_SIZE_MASK 0xffff
+#define OUTPUT_STREAM_DESCRIPTOR_FIFO_SIZE__FIFO_SIZE__SHIFT 0x0
+#define OUTPUT_STREAM_DESCRIPTOR_FORMAT__NUMBER_OF_CHANNELS_MASK 0xf
+#define OUTPUT_STREAM_DESCRIPTOR_FORMAT__NUMBER_OF_CHANNELS__SHIFT 0x0
+#define OUTPUT_STREAM_DESCRIPTOR_FORMAT__BITS_PER_SAMPLE_MASK 0x70
+#define OUTPUT_STREAM_DESCRIPTOR_FORMAT__BITS_PER_SAMPLE__SHIFT 0x4
+#define OUTPUT_STREAM_DESCRIPTOR_FORMAT__SAMPLE_BASE_DIVISOR_MASK 0x700
+#define OUTPUT_STREAM_DESCRIPTOR_FORMAT__SAMPLE_BASE_DIVISOR__SHIFT 0x8
+#define OUTPUT_STREAM_DESCRIPTOR_FORMAT__SAMPLE_BASE_MULTIPLE_MASK 0x3800
+#define OUTPUT_STREAM_DESCRIPTOR_FORMAT__SAMPLE_BASE_MULTIPLE__SHIFT 0xb
+#define OUTPUT_STREAM_DESCRIPTOR_FORMAT__SAMPLE_BASE_RATE_MASK 0x4000
+#define OUTPUT_STREAM_DESCRIPTOR_FORMAT__SAMPLE_BASE_RATE__SHIFT 0xe
+#define OUTPUT_STREAM_DESCRIPTOR_BDL_POINTER_LOWER_BASE_ADDRESS__BUFFER_DESCRIPTOR_LIST_LOWER_BASE_ADDRESS_UNIMPLEMENTED_BITS_MASK 0x7f
+#define OUTPUT_STREAM_DESCRIPTOR_BDL_POINTER_LOWER_BASE_ADDRESS__BUFFER_DESCRIPTOR_LIST_LOWER_BASE_ADDRESS_UNIMPLEMENTED_BITS__SHIFT 0x0
+#define OUTPUT_STREAM_DESCRIPTOR_BDL_POINTER_LOWER_BASE_ADDRESS__BUFFER_DESCRIPTOR_LIST_LOWER_BASE_ADDRESS_MASK 0xffffff80
+#define OUTPUT_STREAM_DESCRIPTOR_BDL_POINTER_LOWER_BASE_ADDRESS__BUFFER_DESCRIPTOR_LIST_LOWER_BASE_ADDRESS__SHIFT 0x7
+#define OUTPUT_STREAM_DESCRIPTOR_BDL_POINTER_UPPER_BASE_ADDRESS__BUFFER_DESCRIPTOR_LIST_UPPER_BASE_ADDRESS_MASK 0xffffffff
+#define OUTPUT_STREAM_DESCRIPTOR_BDL_POINTER_UPPER_BASE_ADDRESS__BUFFER_DESCRIPTOR_LIST_UPPER_BASE_ADDRESS__SHIFT 0x0
+#define OUTPUT_STREAM_DESCRIPTOR_LINK_POSITION_IN_CURRENT_BUFFER_ALIAS__LINK_POSITION_IN_BUFFER_ALIAS_MASK 0xffffffff
+#define OUTPUT_STREAM_DESCRIPTOR_LINK_POSITION_IN_CURRENT_BUFFER_ALIAS__LINK_POSITION_IN_BUFFER_ALIAS__SHIFT 0x0
+#define AZENDPOINT_IMMEDIATE_COMMAND_OUTPUT_INTERFACE_INDEX__IMMEDIATE_COMMAND_WRITE_MASK 0x1ffff
+#define AZENDPOINT_IMMEDIATE_COMMAND_OUTPUT_INTERFACE_INDEX__IMMEDIATE_COMMAND_WRITE__SHIFT 0x0
+#define AZENDPOINT_IMMEDIATE_COMMAND_OUTPUT_INTERFACE_DATA__IMMEDIATE_COMMAND_WRITE_MASK 0xffffffff
+#define AZENDPOINT_IMMEDIATE_COMMAND_OUTPUT_INTERFACE_DATA__IMMEDIATE_COMMAND_WRITE__SHIFT 0x0
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_CHANNEL_CAPABILITIES_MASK 0x1
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_CHANNEL_CAPABILITIES__SHIFT 0x0
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__INPUT_AMPLIFIER_PRESENT_MASK 0x2
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__INPUT_AMPLIFIER_PRESENT__SHIFT 0x1
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__OUTPUT_AMPLIFIER_PRESENT_MASK 0x4
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__OUTPUT_AMPLIFIER_PRESENT__SHIFT 0x2
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AMPLIFIER_PARAMETER_OVERRIDE_MASK 0x8
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AMPLIFIER_PARAMETER_OVERRIDE__SHIFT 0x3
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__FORMAT_OVERRIDE_MASK 0x10
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__FORMAT_OVERRIDE__SHIFT 0x4
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__STRIPE_MASK 0x20
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__STRIPE__SHIFT 0x5
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__PROCESSING_WIDGET_MASK 0x40
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__PROCESSING_WIDGET__SHIFT 0x6
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__UNSOLICITED_RESPONSE_CAPABILITY_MASK 0x80
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__UNSOLICITED_RESPONSE_CAPABILITY__SHIFT 0x7
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__CONNECTION_LIST_MASK 0x100
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__CONNECTION_LIST__SHIFT 0x8
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__DIGITAL_MASK 0x200
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__DIGITAL__SHIFT 0x9
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__POWER_CONTROL_MASK 0x400
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__POWER_CONTROL__SHIFT 0xa
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__LR_SWAP_MASK 0x800
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__LR_SWAP__SHIFT 0xb
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_WIDGET_CAPABILITIES_DELAY_MASK 0xf0000
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_WIDGET_CAPABILITIES_DELAY__SHIFT 0x10
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__TYPE_MASK 0xf00000
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__TYPE__SHIFT 0x14
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_RATE_CAPABILITIES_MASK 0xfff
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_RATE_CAPABILITIES__SHIFT 0x0
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_BIT_CAPABILITIES_MASK 0x1f0000
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_BIT_CAPABILITIES__SHIFT 0x10
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_STREAM_FORMATS__STREAM_FORMATS_MASK 0xffffffff
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_STREAM_FORMATS__STREAM_FORMATS__SHIFT 0x0
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__NUMBER_OF_CHANNELS_MASK 0xf
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__NUMBER_OF_CHANNELS__SHIFT 0x0
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__BITS_PER_SAMPLE_MASK 0x70
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__BITS_PER_SAMPLE__SHIFT 0x4
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_DIVISOR_MASK 0x700
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_DIVISOR__SHIFT 0x8
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_MULTIPLE_MASK 0x3800
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_MULTIPLE__SHIFT 0xb
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_RATE_MASK 0x4000
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_RATE__SHIFT 0xe
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__STREAM_TYPE_MASK 0x8000
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__STREAM_TYPE__SHIFT 0xf
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__STREAM_TYPE_R_MASK 0x8000
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__STREAM_TYPE_R__SHIFT 0xf
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CHANNEL_STREAM_ID__CHANNEL_ID_MASK 0xf
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CHANNEL_STREAM_ID__CHANNEL_ID__SHIFT 0x0
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CHANNEL_STREAM_ID__STREAM_ID_MASK 0xf0
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CHANNEL_STREAM_ID__STREAM_ID__SHIFT 0x4
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__DIGEN_MASK 0x1
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__DIGEN__SHIFT 0x0
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__V_MASK 0x2
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__V__SHIFT 0x1
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__VCFG_MASK 0x4
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__VCFG__SHIFT 0x2
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__PRE_MASK 0x8
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__PRE__SHIFT 0x3
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__COPY_MASK 0x10
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__COPY__SHIFT 0x4
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__NON_AUDIO_MASK 0x20
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__NON_AUDIO__SHIFT 0x5
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__PRO_MASK 0x40
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__PRO__SHIFT 0x6
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__L_MASK 0x80
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__L__SHIFT 0x7
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__CC_MASK 0x7f00
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__CC__SHIFT 0x8
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__KEEPALIVE_MASK 0x800000
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__KEEPALIVE__SHIFT 0x17
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_2__CC_MASK 0x7f
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_2__CC__SHIFT 0x0
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_3__KEEPALIVE_MASK 0x80
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_3__KEEPALIVE__SHIFT 0x7
+#define AZALIA_F2_CODEC_CONVERTER_STRIPE_CONTROL__STRIPE_CONTROL_MASK 0x3
+#define AZALIA_F2_CODEC_CONVERTER_STRIPE_CONTROL__STRIPE_CONTROL__SHIFT 0x0
+#define AZALIA_F2_CODEC_CONVERTER_STRIPE_CONTROL__STRIPE_CAPABILITY_MASK 0x700000
+#define AZALIA_F2_CODEC_CONVERTER_STRIPE_CONTROL__STRIPE_CAPABILITY__SHIFT 0x14
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_RAMP_RATE__RAMP_RATE_MASK 0xff
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_RAMP_RATE__RAMP_RATE__SHIFT 0x0
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING__PRESENTATION_TIME_EMBEDDING_ENABLE_MASK 0x1
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING__PRESENTATION_TIME_EMBEDDING_ENABLE__SHIFT 0x0
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING__PRESENTATION_TIME_OFFSET_CHANGED_MASK 0x2
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING__PRESENTATION_TIME_OFFSET_CHANGED__SHIFT 0x1
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING__PRESENTATION_TIME_EMBEDDING_GROUP_MASK 0x70
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING__PRESENTATION_TIME_EMBEDDING_GROUP__SHIFT 0x4
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_CHANNEL_CAPABILITIES_MASK 0x1
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_CHANNEL_CAPABILITIES__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__INPUT_AMPLIFIER_PRESENT_MASK 0x2
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__INPUT_AMPLIFIER_PRESENT__SHIFT 0x1
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__OUTPUT_AMPLIFIER_PRESENT_MASK 0x4
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__OUTPUT_AMPLIFIER_PRESENT__SHIFT 0x2
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AMPLIFIER_PARAMETER_OVERRIDE_MASK 0x8
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AMPLIFIER_PARAMETER_OVERRIDE__SHIFT 0x3
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__STRIPE_MASK 0x20
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__STRIPE__SHIFT 0x5
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__PROCESSING_WIDGET_MASK 0x40
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__PROCESSING_WIDGET__SHIFT 0x6
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__UNSOLICITED_RESPONSE_CAPABILITY_MASK 0x80
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__UNSOLICITED_RESPONSE_CAPABILITY__SHIFT 0x7
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__CONNECTION_LIST_MASK 0x100
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__CONNECTION_LIST__SHIFT 0x8
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__DIGITAL_MASK 0x200
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__DIGITAL__SHIFT 0x9
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__POWER_CONTROL_MASK 0x400
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__POWER_CONTROL__SHIFT 0xa
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__LR_SWAP_MASK 0x800
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__LR_SWAP__SHIFT 0xb
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_WIDGET_CAPABILITIES_DELAY_MASK 0xf0000
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_WIDGET_CAPABILITIES_DELAY__SHIFT 0x10
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__TYPE_MASK 0xf00000
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__TYPE__SHIFT 0x14
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__IMPEDANCE_SENSE_CAPABLE_MASK 0x1
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__IMPEDANCE_SENSE_CAPABLE__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__TRIGGER_REQUIRED_MASK 0x2
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__TRIGGER_REQUIRED__SHIFT 0x1
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__JACK_DETECTION_CAPABILITY_MASK 0x4
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__JACK_DETECTION_CAPABILITY__SHIFT 0x2
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__HEADPHONE_DRIVE_CAPABLE_MASK 0x8
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__HEADPHONE_DRIVE_CAPABLE__SHIFT 0x3
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__OUTPUT_CAPABLE_MASK 0x10
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__OUTPUT_CAPABLE__SHIFT 0x4
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__INPUT_CAPABLE_MASK 0x20
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__INPUT_CAPABLE__SHIFT 0x5
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__BALANCED_I_O_PINS_MASK 0x40
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__BALANCED_I_O_PINS__SHIFT 0x6
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__HDMI_MASK 0x80
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__HDMI__SHIFT 0x7
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__VREF_CONTROL_MASK 0xff00
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__VREF_CONTROL__SHIFT 0x8
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__EAPD_CAPABLE_MASK 0x10000
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__EAPD_CAPABLE__SHIFT 0x10
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__DP_MASK 0x1000000
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__DP__SHIFT 0x18
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CONNECTION_LIST_LENGTH__CONNECTION_LIST_LENGTH_MASK 0xffffffff
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CONNECTION_LIST_LENGTH__CONNECTION_LIST_LENGTH__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONNECTION_LIST_ENTRY__CONNECTION_LIST_ENTRY_MASK 0xffffffff
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONNECTION_LIST_ENTRY__CONNECTION_LIST_ENTRY__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_CONTROL_WIDGET_CONTROL__OUT_ENABLE_MASK 0x40
+#define AZALIA_F2_CODEC_PIN_CONTROL_WIDGET_CONTROL__OUT_ENABLE__SHIFT 0x6
+#define AZALIA_F2_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE__TAG_MASK 0x3f
+#define AZALIA_F2_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE__TAG__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE__ENABLE_MASK 0x80
+#define AZALIA_F2_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE__ENABLE__SHIFT 0x7
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_PIN_SENSE__IMPEDANCE_SENSE_MASK 0x7fffffff
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_PIN_SENSE__IMPEDANCE_SENSE__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_PIN_SENSE__PRESENCE_DETECT_MASK 0x80000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_PIN_SENSE__PRESENCE_DETECT__SHIFT 0x1f
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__SEQUENCE_MASK 0xf
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__SEQUENCE__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__DEFAULT_ASSOCIATION_MASK 0xf0
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__DEFAULT_ASSOCIATION__SHIFT 0x4
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__MISC_MASK 0xf00
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__MISC__SHIFT 0x8
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__COLOR_MASK 0xf000
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__COLOR__SHIFT 0xc
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__CONNECTION_TYPE_MASK 0xf0000
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__CONNECTION_TYPE__SHIFT 0x10
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__DEFAULT_DEVICE_MASK 0xf00000
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__DEFAULT_DEVICE__SHIFT 0x14
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__LOCATION_MASK 0x3f000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__LOCATION__SHIFT 0x18
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__PORT_CONNECTIVITY_MASK 0xc0000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__PORT_CONNECTIVITY__SHIFT 0x1e
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_2__MISC_MASK 0xf
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_2__MISC__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_2__COLOR_MASK 0xf0
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_2__COLOR__SHIFT 0x4
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_3__CONNECTION_TYPE_MASK 0xf
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_3__CONNECTION_TYPE__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_3__DEFAULT_DEVICE_MASK 0xf0
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_3__DEFAULT_DEVICE__SHIFT 0x4
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_4__LOCATION_MASK 0x3f
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_4__LOCATION__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_4__PORT_CONNECTIVITY_MASK 0xc0
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_4__PORT_CONNECTIVITY__SHIFT 0x6
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_SPEAKER_ALLOCATION__SPEAKER_ALLOCATION_MASK 0x7f
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_SPEAKER_ALLOCATION__SPEAKER_ALLOCATION__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_SPEAKER_ALLOCATION__HDMI_CONNECTION_MASK 0x100
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_SPEAKER_ALLOCATION__HDMI_CONNECTION__SHIFT 0x8
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_SPEAKER_ALLOCATION__DP_CONNECTION_MASK 0x200
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_SPEAKER_ALLOCATION__DP_CONNECTION__SHIFT 0x9
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_SPEAKER_ALLOCATION__EXTRA_CONNECTION_INFO_MASK 0xfc00
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_SPEAKER_ALLOCATION__EXTRA_CONNECTION_INFO__SHIFT 0xa
+#define AZALIA_F2_CODEC_PIN_CONTROL_CHANNEL_ALLOCATION__CHANNEL_ALLOCATION_MASK 0xff
+#define AZALIA_F2_CODEC_PIN_CONTROL_CHANNEL_ALLOCATION__CHANNEL_ALLOCATION__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_CONTROL_DOWN_MIX_INFO__LFE_PLAYBACK_LEVEL_MASK 0x3
+#define AZALIA_F2_CODEC_PIN_CONTROL_DOWN_MIX_INFO__LFE_PLAYBACK_LEVEL__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_CONTROL_DOWN_MIX_INFO__LEVEL_SHIFT_MASK 0x78
+#define AZALIA_F2_CODEC_PIN_CONTROL_DOWN_MIX_INFO__LEVEL_SHIFT__SHIFT 0x3
+#define AZALIA_F2_CODEC_PIN_CONTROL_DOWN_MIX_INFO__DOWN_MIX_INHIBIT_MASK 0x80
+#define AZALIA_F2_CODEC_PIN_CONTROL_DOWN_MIX_INFO__DOWN_MIX_INHIBIT__SHIFT 0x7
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR__MAX_CHANNELS_MASK 0x7
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR__MAX_CHANNELS__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR__FORMAT_CODE_MASK 0x78
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR__FORMAT_CODE__SHIFT 0x3
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR__SUPPORTED_FREQUENCIES_MASK 0xff00
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR__SUPPORTED_FREQUENCIES__SHIFT 0x8
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR__DESCRIPTOR_BYTE_2_MASK 0xff0000
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR__DESCRIPTOR_BYTE_2__SHIFT 0x10
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x18
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR_DATA__DESCRIPTOR_MASK 0xffffffff
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR_DATA__DESCRIPTOR__SHIFT 0x0
+#define AUDIO_DESCRIPTOR0__MAX_CHANNELS_MASK 0x7
+#define AUDIO_DESCRIPTOR0__MAX_CHANNELS__SHIFT 0x0
+#define AUDIO_DESCRIPTOR0__SUPPORTED_FREQUENCIES_MASK 0xff00
+#define AUDIO_DESCRIPTOR0__SUPPORTED_FREQUENCIES__SHIFT 0x8
+#define AUDIO_DESCRIPTOR0__DESCRIPTOR_BYTE_2_MASK 0xff0000
+#define AUDIO_DESCRIPTOR0__DESCRIPTOR_BYTE_2__SHIFT 0x10
+#define AUDIO_DESCRIPTOR0__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000
+#define AUDIO_DESCRIPTOR0__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x18
+#define AUDIO_DESCRIPTOR1__MAX_CHANNELS_MASK 0x7
+#define AUDIO_DESCRIPTOR1__MAX_CHANNELS__SHIFT 0x0
+#define AUDIO_DESCRIPTOR1__SUPPORTED_FREQUENCIES_MASK 0xff00
+#define AUDIO_DESCRIPTOR1__SUPPORTED_FREQUENCIES__SHIFT 0x8
+#define AUDIO_DESCRIPTOR1__DESCRIPTOR_BYTE_2_MASK 0xff0000
+#define AUDIO_DESCRIPTOR1__DESCRIPTOR_BYTE_2__SHIFT 0x10
+#define AUDIO_DESCRIPTOR1__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000
+#define AUDIO_DESCRIPTOR1__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x18
+#define AUDIO_DESCRIPTOR2__MAX_CHANNELS_MASK 0x7
+#define AUDIO_DESCRIPTOR2__MAX_CHANNELS__SHIFT 0x0
+#define AUDIO_DESCRIPTOR2__SUPPORTED_FREQUENCIES_MASK 0xff00
+#define AUDIO_DESCRIPTOR2__SUPPORTED_FREQUENCIES__SHIFT 0x8
+#define AUDIO_DESCRIPTOR2__DESCRIPTOR_BYTE_2_MASK 0xff0000
+#define AUDIO_DESCRIPTOR2__DESCRIPTOR_BYTE_2__SHIFT 0x10
+#define AUDIO_DESCRIPTOR2__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000
+#define AUDIO_DESCRIPTOR2__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x18
+#define AUDIO_DESCRIPTOR3__MAX_CHANNELS_MASK 0x7
+#define AUDIO_DESCRIPTOR3__MAX_CHANNELS__SHIFT 0x0
+#define AUDIO_DESCRIPTOR3__SUPPORTED_FREQUENCIES_MASK 0xff00
+#define AUDIO_DESCRIPTOR3__SUPPORTED_FREQUENCIES__SHIFT 0x8
+#define AUDIO_DESCRIPTOR3__DESCRIPTOR_BYTE_2_MASK 0xff0000
+#define AUDIO_DESCRIPTOR3__DESCRIPTOR_BYTE_2__SHIFT 0x10
+#define AUDIO_DESCRIPTOR3__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000
+#define AUDIO_DESCRIPTOR3__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x18
+#define AUDIO_DESCRIPTOR4__MAX_CHANNELS_MASK 0x7
+#define AUDIO_DESCRIPTOR4__MAX_CHANNELS__SHIFT 0x0
+#define AUDIO_DESCRIPTOR4__SUPPORTED_FREQUENCIES_MASK 0xff00
+#define AUDIO_DESCRIPTOR4__SUPPORTED_FREQUENCIES__SHIFT 0x8
+#define AUDIO_DESCRIPTOR4__DESCRIPTOR_BYTE_2_MASK 0xff0000
+#define AUDIO_DESCRIPTOR4__DESCRIPTOR_BYTE_2__SHIFT 0x10
+#define AUDIO_DESCRIPTOR4__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000
+#define AUDIO_DESCRIPTOR4__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x18
+#define AUDIO_DESCRIPTOR5__MAX_CHANNELS_MASK 0x7
+#define AUDIO_DESCRIPTOR5__MAX_CHANNELS__SHIFT 0x0
+#define AUDIO_DESCRIPTOR5__SUPPORTED_FREQUENCIES_MASK 0xff00
+#define AUDIO_DESCRIPTOR5__SUPPORTED_FREQUENCIES__SHIFT 0x8
+#define AUDIO_DESCRIPTOR5__DESCRIPTOR_BYTE_2_MASK 0xff0000
+#define AUDIO_DESCRIPTOR5__DESCRIPTOR_BYTE_2__SHIFT 0x10
+#define AUDIO_DESCRIPTOR5__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000
+#define AUDIO_DESCRIPTOR5__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x18
+#define AUDIO_DESCRIPTOR6__MAX_CHANNELS_MASK 0x7
+#define AUDIO_DESCRIPTOR6__MAX_CHANNELS__SHIFT 0x0
+#define AUDIO_DESCRIPTOR6__SUPPORTED_FREQUENCIES_MASK 0xff00
+#define AUDIO_DESCRIPTOR6__SUPPORTED_FREQUENCIES__SHIFT 0x8
+#define AUDIO_DESCRIPTOR6__DESCRIPTOR_BYTE_2_MASK 0xff0000
+#define AUDIO_DESCRIPTOR6__DESCRIPTOR_BYTE_2__SHIFT 0x10
+#define AUDIO_DESCRIPTOR6__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000
+#define AUDIO_DESCRIPTOR6__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x18
+#define AUDIO_DESCRIPTOR7__MAX_CHANNELS_MASK 0x7
+#define AUDIO_DESCRIPTOR7__MAX_CHANNELS__SHIFT 0x0
+#define AUDIO_DESCRIPTOR7__SUPPORTED_FREQUENCIES_MASK 0xff00
+#define AUDIO_DESCRIPTOR7__SUPPORTED_FREQUENCIES__SHIFT 0x8
+#define AUDIO_DESCRIPTOR7__DESCRIPTOR_BYTE_2_MASK 0xff0000
+#define AUDIO_DESCRIPTOR7__DESCRIPTOR_BYTE_2__SHIFT 0x10
+#define AUDIO_DESCRIPTOR7__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000
+#define AUDIO_DESCRIPTOR7__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x18
+#define AUDIO_DESCRIPTOR8__MAX_CHANNELS_MASK 0x7
+#define AUDIO_DESCRIPTOR8__MAX_CHANNELS__SHIFT 0x0
+#define AUDIO_DESCRIPTOR8__SUPPORTED_FREQUENCIES_MASK 0xff00
+#define AUDIO_DESCRIPTOR8__SUPPORTED_FREQUENCIES__SHIFT 0x8
+#define AUDIO_DESCRIPTOR8__DESCRIPTOR_BYTE_2_MASK 0xff0000
+#define AUDIO_DESCRIPTOR8__DESCRIPTOR_BYTE_2__SHIFT 0x10
+#define AUDIO_DESCRIPTOR8__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000
+#define AUDIO_DESCRIPTOR8__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x18
+#define AUDIO_DESCRIPTOR9__MAX_CHANNELS_MASK 0x7
+#define AUDIO_DESCRIPTOR9__MAX_CHANNELS__SHIFT 0x0
+#define AUDIO_DESCRIPTOR9__SUPPORTED_FREQUENCIES_MASK 0xff00
+#define AUDIO_DESCRIPTOR9__SUPPORTED_FREQUENCIES__SHIFT 0x8
+#define AUDIO_DESCRIPTOR9__DESCRIPTOR_BYTE_2_MASK 0xff0000
+#define AUDIO_DESCRIPTOR9__DESCRIPTOR_BYTE_2__SHIFT 0x10
+#define AUDIO_DESCRIPTOR9__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000
+#define AUDIO_DESCRIPTOR9__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x18
+#define AUDIO_DESCRIPTOR10__MAX_CHANNELS_MASK 0x7
+#define AUDIO_DESCRIPTOR10__MAX_CHANNELS__SHIFT 0x0
+#define AUDIO_DESCRIPTOR10__SUPPORTED_FREQUENCIES_MASK 0xff00
+#define AUDIO_DESCRIPTOR10__SUPPORTED_FREQUENCIES__SHIFT 0x8
+#define AUDIO_DESCRIPTOR10__DESCRIPTOR_BYTE_2_MASK 0xff0000
+#define AUDIO_DESCRIPTOR10__DESCRIPTOR_BYTE_2__SHIFT 0x10
+#define AUDIO_DESCRIPTOR10__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000
+#define AUDIO_DESCRIPTOR10__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x18
+#define AUDIO_DESCRIPTOR11__MAX_CHANNELS_MASK 0x7
+#define AUDIO_DESCRIPTOR11__MAX_CHANNELS__SHIFT 0x0
+#define AUDIO_DESCRIPTOR11__SUPPORTED_FREQUENCIES_MASK 0xff00
+#define AUDIO_DESCRIPTOR11__SUPPORTED_FREQUENCIES__SHIFT 0x8
+#define AUDIO_DESCRIPTOR11__DESCRIPTOR_BYTE_2_MASK 0xff0000
+#define AUDIO_DESCRIPTOR11__DESCRIPTOR_BYTE_2__SHIFT 0x10
+#define AUDIO_DESCRIPTOR11__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000
+#define AUDIO_DESCRIPTOR11__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x18
+#define AUDIO_DESCRIPTOR12__MAX_CHANNELS_MASK 0x7
+#define AUDIO_DESCRIPTOR12__MAX_CHANNELS__SHIFT 0x0
+#define AUDIO_DESCRIPTOR12__SUPPORTED_FREQUENCIES_MASK 0xff00
+#define AUDIO_DESCRIPTOR12__SUPPORTED_FREQUENCIES__SHIFT 0x8
+#define AUDIO_DESCRIPTOR12__DESCRIPTOR_BYTE_2_MASK 0xff0000
+#define AUDIO_DESCRIPTOR12__DESCRIPTOR_BYTE_2__SHIFT 0x10
+#define AUDIO_DESCRIPTOR12__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000
+#define AUDIO_DESCRIPTOR12__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x18
+#define AUDIO_DESCRIPTOR13__MAX_CHANNELS_MASK 0x7
+#define AUDIO_DESCRIPTOR13__MAX_CHANNELS__SHIFT 0x0
+#define AUDIO_DESCRIPTOR13__SUPPORTED_FREQUENCIES_MASK 0xff00
+#define AUDIO_DESCRIPTOR13__SUPPORTED_FREQUENCIES__SHIFT 0x8
+#define AUDIO_DESCRIPTOR13__DESCRIPTOR_BYTE_2_MASK 0xff0000
+#define AUDIO_DESCRIPTOR13__DESCRIPTOR_BYTE_2__SHIFT 0x10
+#define AUDIO_DESCRIPTOR13__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000
+#define AUDIO_DESCRIPTOR13__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x18
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL01_ENABLE__MULTICHANNEL01_ENABLE_MASK 0x1
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL01_ENABLE__MULTICHANNEL01_ENABLE__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL01_ENABLE__MULTICHANNEL01_MUTE_MASK 0x2
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL01_ENABLE__MULTICHANNEL01_MUTE__SHIFT 0x1
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL01_ENABLE__MULTICHANNEL01_CHANNEL_ID_MASK 0xf0
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL01_ENABLE__MULTICHANNEL01_CHANNEL_ID__SHIFT 0x4
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL23_ENABLE__MULTICHANNEL23_ENABLE_MASK 0x1
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL23_ENABLE__MULTICHANNEL23_ENABLE__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL23_ENABLE__MULTICHANNEL23_MUTE_MASK 0x2
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL23_ENABLE__MULTICHANNEL23_MUTE__SHIFT 0x1
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL23_ENABLE__MULTICHANNEL23_CHANNEL_ID_MASK 0xf0
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL23_ENABLE__MULTICHANNEL23_CHANNEL_ID__SHIFT 0x4
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL45_ENABLE__MULTICHANNEL45_ENABLE_MASK 0x1
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL45_ENABLE__MULTICHANNEL45_ENABLE__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL45_ENABLE__MULTICHANNEL45_MUTE_MASK 0x2
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL45_ENABLE__MULTICHANNEL45_MUTE__SHIFT 0x1
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL45_ENABLE__MULTICHANNEL45_CHANNEL_ID_MASK 0xf0
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL45_ENABLE__MULTICHANNEL45_CHANNEL_ID__SHIFT 0x4
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL67_ENABLE__MULTICHANNEL67_ENABLE_MASK 0x1
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL67_ENABLE__MULTICHANNEL67_ENABLE__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL67_ENABLE__MULTICHANNEL67_MUTE_MASK 0x2
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL67_ENABLE__MULTICHANNEL67_MUTE__SHIFT 0x1
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL67_ENABLE__MULTICHANNEL67_CHANNEL_ID_MASK 0xf0
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL67_ENABLE__MULTICHANNEL67_CHANNEL_ID__SHIFT 0x4
+#define AZALIA_F2_CODEC_PIN_CONTROL_LIPSYNC__VIDEO_LIPSYNC_MASK 0xff
+#define AZALIA_F2_CODEC_PIN_CONTROL_LIPSYNC__VIDEO_LIPSYNC__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_CONTROL_LIPSYNC__AUDIO_LIPSYNC_MASK 0xff00
+#define AZALIA_F2_CODEC_PIN_CONTROL_LIPSYNC__AUDIO_LIPSYNC__SHIFT 0x8
+#define AZALIA_F2_CODEC_PIN_CONTROL_HBR__HBR_CAPABLE_MASK 0x1
+#define AZALIA_F2_CODEC_PIN_CONTROL_HBR__HBR_CAPABLE__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_CONTROL_HBR__HBR_ENABLE_MASK 0x10
+#define AZALIA_F2_CODEC_PIN_CONTROL_HBR__HBR_ENABLE__SHIFT 0x4
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_SINK_INFO_INDEX__SINK_INFO_INDEX_MASK 0xff
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_SINK_INFO_INDEX__SINK_INFO_INDEX__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_SINK_INFO_DATA__SINK_DATA_MASK 0xffffffff
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_SINK_INFO_DATA__SINK_DATA__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_CONTROL_MANUFACTURER_ID__MANUFACTURER_ID_MASK 0xffff
+#define AZALIA_F2_CODEC_PIN_CONTROL_MANUFACTURER_ID__MANUFACTURER_ID__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_CONTROL_PRODUCT_ID__PRODUCT_ID_MASK 0xffff
+#define AZALIA_F2_CODEC_PIN_CONTROL_PRODUCT_ID__PRODUCT_ID__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_CONTROL_SINK_DESCRIPTION_LEN__SINK_DESCRIPTION_LEN_MASK 0xff
+#define AZALIA_F2_CODEC_PIN_CONTROL_SINK_DESCRIPTION_LEN__SINK_DESCRIPTION_LEN__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_CONTROL_PORTID0__PORTID_MASK 0xffffffff
+#define AZALIA_F2_CODEC_PIN_CONTROL_PORTID0__PORTID__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_CONTROL_PORTID1__PORTID_MASK 0xffffffff
+#define AZALIA_F2_CODEC_PIN_CONTROL_PORTID1__PORTID__SHIFT 0x0
+#define SINK_DESCRIPTION0__DESCRIPTION_MASK 0xff
+#define SINK_DESCRIPTION0__DESCRIPTION__SHIFT 0x0
+#define SINK_DESCRIPTION1__DESCRIPTION_MASK 0xff
+#define SINK_DESCRIPTION1__DESCRIPTION__SHIFT 0x0
+#define SINK_DESCRIPTION2__DESCRIPTION_MASK 0xff
+#define SINK_DESCRIPTION2__DESCRIPTION__SHIFT 0x0
+#define SINK_DESCRIPTION3__DESCRIPTION_MASK 0xff
+#define SINK_DESCRIPTION3__DESCRIPTION__SHIFT 0x0
+#define SINK_DESCRIPTION4__DESCRIPTION_MASK 0xff
+#define SINK_DESCRIPTION4__DESCRIPTION__SHIFT 0x0
+#define SINK_DESCRIPTION5__DESCRIPTION_MASK 0xff
+#define SINK_DESCRIPTION5__DESCRIPTION__SHIFT 0x0
+#define SINK_DESCRIPTION6__DESCRIPTION_MASK 0xff
+#define SINK_DESCRIPTION6__DESCRIPTION__SHIFT 0x0
+#define SINK_DESCRIPTION7__DESCRIPTION_MASK 0xff
+#define SINK_DESCRIPTION7__DESCRIPTION__SHIFT 0x0
+#define SINK_DESCRIPTION8__DESCRIPTION_MASK 0xff
+#define SINK_DESCRIPTION8__DESCRIPTION__SHIFT 0x0
+#define SINK_DESCRIPTION9__DESCRIPTION_MASK 0xff
+#define SINK_DESCRIPTION9__DESCRIPTION__SHIFT 0x0
+#define SINK_DESCRIPTION10__DESCRIPTION_MASK 0xff
+#define SINK_DESCRIPTION10__DESCRIPTION__SHIFT 0x0
+#define SINK_DESCRIPTION11__DESCRIPTION_MASK 0xff
+#define SINK_DESCRIPTION11__DESCRIPTION__SHIFT 0x0
+#define SINK_DESCRIPTION12__DESCRIPTION_MASK 0xff
+#define SINK_DESCRIPTION12__DESCRIPTION__SHIFT 0x0
+#define SINK_DESCRIPTION13__DESCRIPTION_MASK 0xff
+#define SINK_DESCRIPTION13__DESCRIPTION__SHIFT 0x0
+#define SINK_DESCRIPTION14__DESCRIPTION_MASK 0xff
+#define SINK_DESCRIPTION14__DESCRIPTION__SHIFT 0x0
+#define SINK_DESCRIPTION15__DESCRIPTION_MASK 0xff
+#define SINK_DESCRIPTION15__DESCRIPTION__SHIFT 0x0
+#define SINK_DESCRIPTION16__DESCRIPTION_MASK 0xff
+#define SINK_DESCRIPTION16__DESCRIPTION__SHIFT 0x0
+#define SINK_DESCRIPTION17__DESCRIPTION_MASK 0xff
+#define SINK_DESCRIPTION17__DESCRIPTION__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL1_ENABLE__MULTICHANNEL1_ENABLE_MASK 0x1
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL1_ENABLE__MULTICHANNEL1_ENABLE__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL1_ENABLE__MULTICHANNEL1_MUTE_MASK 0x2
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL1_ENABLE__MULTICHANNEL1_MUTE__SHIFT 0x1
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL1_ENABLE__MULTICHANNEL1_CHANNEL_ID_MASK 0xf0
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL1_ENABLE__MULTICHANNEL1_CHANNEL_ID__SHIFT 0x4
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL3_ENABLE__MULTICHANNEL3_ENABLE_MASK 0x1
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL3_ENABLE__MULTICHANNEL3_ENABLE__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL3_ENABLE__MULTICHANNEL3_MUTE_MASK 0x2
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL3_ENABLE__MULTICHANNEL3_MUTE__SHIFT 0x1
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL3_ENABLE__MULTICHANNEL3_CHANNEL_ID_MASK 0xf0
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL3_ENABLE__MULTICHANNEL3_CHANNEL_ID__SHIFT 0x4
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL5_ENABLE__MULTICHANNEL5_ENABLE_MASK 0x1
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL5_ENABLE__MULTICHANNEL5_ENABLE__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL5_ENABLE__MULTICHANNEL5_MUTE_MASK 0x2
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL5_ENABLE__MULTICHANNEL5_MUTE__SHIFT 0x1
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL5_ENABLE__MULTICHANNEL5_CHANNEL_ID_MASK 0xf0
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL5_ENABLE__MULTICHANNEL5_CHANNEL_ID__SHIFT 0x4
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL7_ENABLE__MULTICHANNEL7_ENABLE_MASK 0x1
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL7_ENABLE__MULTICHANNEL7_ENABLE__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL7_ENABLE__MULTICHANNEL7_MUTE_MASK 0x2
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL7_ENABLE__MULTICHANNEL7_MUTE__SHIFT 0x1
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL7_ENABLE__MULTICHANNEL7_CHANNEL_ID_MASK 0xf0
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL7_ENABLE__MULTICHANNEL7_CHANNEL_ID__SHIFT 0x4
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL_MODE__MULTICHANNEL_MODE_MASK 0x1
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL_MODE__MULTICHANNEL_MODE__SHIFT 0x0
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_0__IEC_60958_CS_MODE_MASK 0x3
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_0__IEC_60958_CS_MODE__SHIFT 0x0
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_0__IEC_60958_CS_SOURCE_NUMBER_MASK 0x3c
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_0__IEC_60958_CS_SOURCE_NUMBER__SHIFT 0x2
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_CLOCK_ACCURACY_MASK 0x3
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_CLOCK_ACCURACY__SHIFT 0x0
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_CLOCK_ACCURACY_OVRRD_EN_MASK 0x4
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_CLOCK_ACCURACY_OVRRD_EN__SHIFT 0x2
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_WORD_LENGTH_MASK 0x78
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_WORD_LENGTH__SHIFT 0x3
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_WORD_LENGTH_OVRRD_EN_MASK 0x80
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_WORD_LENGTH_OVRRD_EN__SHIFT 0x7
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_2__IEC_60958_CS_SAMPLING_FREQUENCY_MASK 0x3f
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_2__IEC_60958_CS_SAMPLING_FREQUENCY__SHIFT 0x0
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_2__IEC_60958_CS_SAMPLING_FREQUENCY_OVRRD_EN_MASK 0x40
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_2__IEC_60958_CS_SAMPLING_FREQUENCY_OVRRD_EN__SHIFT 0x6
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_3__IEC_60958_CS_ORIGINAL_SAMPLING_FREQUENCY_MASK 0xf
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_3__IEC_60958_CS_ORIGINAL_SAMPLING_FREQUENCY__SHIFT 0x0
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_3__IEC_60958_CS_ORIGINAL_SAMPLING_FREQUENCY_OVRRD_EN_MASK 0x10
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_3__IEC_60958_CS_ORIGINAL_SAMPLING_FREQUENCY_OVRRD_EN__SHIFT 0x4
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_SAMPLING_FREQUENCY_COEFF_MASK 0xf
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_SAMPLING_FREQUENCY_COEFF__SHIFT 0x0
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_MPEG_SURROUND_INFO_MASK 0x10
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_MPEG_SURROUND_INFO__SHIFT 0x4
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_CGMS_A_MASK 0x60
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_CGMS_A__SHIFT 0x5
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_CGMS_A_VALID_MASK 0x80
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_CGMS_A_VALID__SHIFT 0x7
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_5__IEC_60958_CS_CHANNEL_NUMBER_L_MASK 0xf
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_5__IEC_60958_CS_CHANNEL_NUMBER_L__SHIFT 0x0
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_5__IEC_60958_CS_CHANNEL_NUMBER_R_MASK 0xf0
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_5__IEC_60958_CS_CHANNEL_NUMBER_R__SHIFT 0x4
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_6__IEC_60958_CS_CHANNEL_NUMBER_2_MASK 0xf
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_6__IEC_60958_CS_CHANNEL_NUMBER_2__SHIFT 0x0
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_6__IEC_60958_CS_CHANNEL_NUMBER_3_MASK 0xf0
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_6__IEC_60958_CS_CHANNEL_NUMBER_3__SHIFT 0x4
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_7__IEC_60958_CS_CHANNEL_NUMBER_4_MASK 0xf
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_7__IEC_60958_CS_CHANNEL_NUMBER_4__SHIFT 0x0
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_7__IEC_60958_CS_CHANNEL_NUMBER_5_MASK 0xf0
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_7__IEC_60958_CS_CHANNEL_NUMBER_5__SHIFT 0x4
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_8__IEC_60958_CS_CHANNEL_NUMBER_6_MASK 0xf
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_8__IEC_60958_CS_CHANNEL_NUMBER_6__SHIFT 0x0
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_8__IEC_60958_CS_CHANNEL_NUMBER_7_MASK 0xf0
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_8__IEC_60958_CS_CHANNEL_NUMBER_7__SHIFT 0x4
+#define AZALIA_F2_CODEC_PIN_ASSOCIATION_INFO__ASSOCIATION_INFO_MASK 0xffffffff
+#define AZALIA_F2_CODEC_PIN_ASSOCIATION_INFO__ASSOCIATION_INFO__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_CONTROL_DIGITAL_OUTPUT_STATUS__OUTPUT_ACTIVE_MASK 0x1
+#define AZALIA_F2_CODEC_PIN_CONTROL_DIGITAL_OUTPUT_STATUS__OUTPUT_ACTIVE__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_CONTROL_LPIB_SNAPSHOT_CONTROL__LPIB_SNAPSHOT_LOCK_MASK 0x1
+#define AZALIA_F2_CODEC_PIN_CONTROL_LPIB_SNAPSHOT_CONTROL__LPIB_SNAPSHOT_LOCK__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_CONTROL_LPIB_SNAPSHOT_CONTROL__CYCLIC_BUFFER_WRAP_COUNT_MASK 0xff00
+#define AZALIA_F2_CODEC_PIN_CONTROL_LPIB_SNAPSHOT_CONTROL__CYCLIC_BUFFER_WRAP_COUNT__SHIFT 0x8
+#define AZALIA_F2_CODEC_PIN_CONTROL_LPIB__LPIB_MASK 0xffffffff
+#define AZALIA_F2_CODEC_PIN_CONTROL_LPIB__LPIB__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_CONTROL_LPIB_TIMER_SNAPSHOT__LPIB_TIMER_SNAPSHOT_MASK 0xffffffff
+#define AZALIA_F2_CODEC_PIN_CONTROL_LPIB_TIMER_SNAPSHOT__LPIB_TIMER_SNAPSHOT__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_CONTROL_CODING_TYPE__CODING_TYPE_MASK 0xff
+#define AZALIA_F2_CODEC_PIN_CONTROL_CODING_TYPE__CODING_TYPE__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_CONTROL_FORMAT_CHANGED__FORMAT_CHANGED_MASK 0x1
+#define AZALIA_F2_CODEC_PIN_CONTROL_FORMAT_CHANGED__FORMAT_CHANGED__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_CONTROL_FORMAT_CHANGED__FORMAT_CHANGED_ACK_UR_ENABLE_MASK 0x2
+#define AZALIA_F2_CODEC_PIN_CONTROL_FORMAT_CHANGED__FORMAT_CHANGED_ACK_UR_ENABLE__SHIFT 0x1
+#define AZALIA_F2_CODEC_PIN_CONTROL_FORMAT_CHANGED__FORMAT_CHANGE_REASON_MASK 0xff00
+#define AZALIA_F2_CODEC_PIN_CONTROL_FORMAT_CHANGED__FORMAT_CHANGE_REASON__SHIFT 0x8
+#define AZALIA_F2_CODEC_PIN_CONTROL_FORMAT_CHANGED__FORMAT_CHANGE_RESPONSE_MASK 0xff0000
+#define AZALIA_F2_CODEC_PIN_CONTROL_FORMAT_CHANGED__FORMAT_CHANGE_RESPONSE__SHIFT 0x10
+#define AZALIA_F2_CODEC_PIN_CONTROL_WIRELESS_DISPLAY_IDENTIFICATION__WIRELESS_DISPLAY_IDENTIFICATION_MASK 0x3
+#define AZALIA_F2_CODEC_PIN_CONTROL_WIRELESS_DISPLAY_IDENTIFICATION__WIRELESS_DISPLAY_IDENTIFICATION__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_CONTROL_REMOTE_KEEPALIVE__REMOTE_KEEP_ALIVE_ENABLE_MASK 0x1
+#define AZALIA_F2_CODEC_PIN_CONTROL_REMOTE_KEEPALIVE__REMOTE_KEEP_ALIVE_ENABLE__SHIFT 0x0
+#define AZALIA_F2_CODEC_PIN_CONTROL_REMOTE_KEEPALIVE__REMOTE_KEEP_ALIVE_CAPABILITY_MASK 0x10
+#define AZALIA_F2_CODEC_PIN_CONTROL_REMOTE_KEEPALIVE__REMOTE_KEEP_ALIVE_CAPABILITY__SHIFT 0x4
+#define AZALIA_CONTROLLER_CLOCK_GATING__ENABLE_CLOCK_GATING_MASK 0x1
+#define AZALIA_CONTROLLER_CLOCK_GATING__ENABLE_CLOCK_GATING__SHIFT 0x0
+#define AZALIA_CONTROLLER_CLOCK_GATING__CLOCK_ON_STATE_MASK 0x10
+#define AZALIA_CONTROLLER_CLOCK_GATING__CLOCK_ON_STATE__SHIFT 0x4
+#define AZALIA_AUDIO_DTO__AZALIA_AUDIO_DTO_PHASE_MASK 0xffff
+#define AZALIA_AUDIO_DTO__AZALIA_AUDIO_DTO_PHASE__SHIFT 0x0
+#define AZALIA_AUDIO_DTO__AZALIA_AUDIO_DTO_MODULE_MASK 0xffff0000
+#define AZALIA_AUDIO_DTO__AZALIA_AUDIO_DTO_MODULE__SHIFT 0x10
+#define AZALIA_AUDIO_DTO_CONTROL__AZALIA_AUDIO_FORCE_DTO_MASK 0x300
+#define AZALIA_AUDIO_DTO_CONTROL__AZALIA_AUDIO_FORCE_DTO__SHIFT 0x8
+#define AZALIA_SCLK_CONTROL__AUDIO_SCLK_CONTROL_MASK 0x30
+#define AZALIA_SCLK_CONTROL__AUDIO_SCLK_CONTROL__SHIFT 0x4
+#define AZALIA_UNDERFLOW_FILLER_SAMPLE__AZALIA_UNDERFLOW_FILLER_SAMPLE_MASK 0xffffffff
+#define AZALIA_UNDERFLOW_FILLER_SAMPLE__AZALIA_UNDERFLOW_FILLER_SAMPLE__SHIFT 0x0
+#define AZALIA_DATA_DMA_CONTROL__DATA_DMA_NON_SNOOP_MASK 0x3
+#define AZALIA_DATA_DMA_CONTROL__DATA_DMA_NON_SNOOP__SHIFT 0x0
+#define AZALIA_DATA_DMA_CONTROL__INPUT_DATA_DMA_NON_SNOOP_MASK 0xc
+#define AZALIA_DATA_DMA_CONTROL__INPUT_DATA_DMA_NON_SNOOP__SHIFT 0x2
+#define AZALIA_DATA_DMA_CONTROL__DATA_DMA_ISOCHRONOUS_MASK 0x30
+#define AZALIA_DATA_DMA_CONTROL__DATA_DMA_ISOCHRONOUS__SHIFT 0x4
+#define AZALIA_DATA_DMA_CONTROL__INPUT_DATA_DMA_ISOCHRONOUS_MASK 0xc0
+#define AZALIA_DATA_DMA_CONTROL__INPUT_DATA_DMA_ISOCHRONOUS__SHIFT 0x6
+#define AZALIA_DATA_DMA_CONTROL__AZALIA_IOC_GENERATION_METHOD_MASK 0x10000
+#define AZALIA_DATA_DMA_CONTROL__AZALIA_IOC_GENERATION_METHOD__SHIFT 0x10
+#define AZALIA_DATA_DMA_CONTROL__AZALIA_UNDERFLOW_CONTROL_MASK 0x20000
+#define AZALIA_DATA_DMA_CONTROL__AZALIA_UNDERFLOW_CONTROL__SHIFT 0x11
+#define AZALIA_BDL_DMA_CONTROL__BDL_DMA_NON_SNOOP_MASK 0x3
+#define AZALIA_BDL_DMA_CONTROL__BDL_DMA_NON_SNOOP__SHIFT 0x0
+#define AZALIA_BDL_DMA_CONTROL__INPUT_BDL_DMA_NON_SNOOP_MASK 0xc
+#define AZALIA_BDL_DMA_CONTROL__INPUT_BDL_DMA_NON_SNOOP__SHIFT 0x2
+#define AZALIA_BDL_DMA_CONTROL__BDL_DMA_ISOCHRONOUS_MASK 0x30
+#define AZALIA_BDL_DMA_CONTROL__BDL_DMA_ISOCHRONOUS__SHIFT 0x4
+#define AZALIA_BDL_DMA_CONTROL__INPUT_BDL_DMA_ISOCHRONOUS_MASK 0xc0
+#define AZALIA_BDL_DMA_CONTROL__INPUT_BDL_DMA_ISOCHRONOUS__SHIFT 0x6
+#define AZALIA_RIRB_AND_DP_CONTROL__RIRB_NON_SNOOP_MASK 0x1
+#define AZALIA_RIRB_AND_DP_CONTROL__RIRB_NON_SNOOP__SHIFT 0x0
+#define AZALIA_RIRB_AND_DP_CONTROL__DP_DMA_NON_SNOOP_MASK 0x10
+#define AZALIA_RIRB_AND_DP_CONTROL__DP_DMA_NON_SNOOP__SHIFT 0x4
+#define AZALIA_RIRB_AND_DP_CONTROL__DP_UPDATE_FREQ_DIVIDER_MASK 0x1e0
+#define AZALIA_RIRB_AND_DP_CONTROL__DP_UPDATE_FREQ_DIVIDER__SHIFT 0x5
+#define AZALIA_CORB_DMA_CONTROL__CORB_DMA_NON_SNOOP_MASK 0x1
+#define AZALIA_CORB_DMA_CONTROL__CORB_DMA_NON_SNOOP__SHIFT 0x0
+#define AZALIA_CORB_DMA_CONTROL__CORB_DMA_ISOCHRONOUS_MASK 0x10
+#define AZALIA_CORB_DMA_CONTROL__CORB_DMA_ISOCHRONOUS__SHIFT 0x4
+#define AZALIA_APPLICATION_POSITION_IN_CYCLIC_BUFFER__APPLICATION_POSITION_IN_CYCLIC_BUFFER_MASK 0xffffffff
+#define AZALIA_APPLICATION_POSITION_IN_CYCLIC_BUFFER__APPLICATION_POSITION_IN_CYCLIC_BUFFER__SHIFT 0x0
+#define AZALIA_CYCLIC_BUFFER_SYNC__CYCLIC_BUFFER_SYNC_ENABLE_MASK 0x1
+#define AZALIA_CYCLIC_BUFFER_SYNC__CYCLIC_BUFFER_SYNC_ENABLE__SHIFT 0x0
+#define AZALIA_GLOBAL_CAPABILITIES__NUMBER_OF_SERIAL_DATA_OUTPUT_SIGNALS_MASK 0x6
+#define AZALIA_GLOBAL_CAPABILITIES__NUMBER_OF_SERIAL_DATA_OUTPUT_SIGNALS__SHIFT 0x1
+#define AZALIA_OUTPUT_PAYLOAD_CAPABILITY__OUTPUT_PAYLOAD_CAPABILITY_MASK 0xffff
+#define AZALIA_OUTPUT_PAYLOAD_CAPABILITY__OUTPUT_PAYLOAD_CAPABILITY__SHIFT 0x0
+#define AZALIA_OUTPUT_PAYLOAD_CAPABILITY__OUTSTRMPAY_MASK 0xffff0000
+#define AZALIA_OUTPUT_PAYLOAD_CAPABILITY__OUTSTRMPAY__SHIFT 0x10
+#define AZALIA_OUTPUT_STREAM_ARBITER_CONTROL__LATENCY_HIDING_LEVEL_MASK 0xff
+#define AZALIA_OUTPUT_STREAM_ARBITER_CONTROL__LATENCY_HIDING_LEVEL__SHIFT 0x0
+#define AZALIA_OUTPUT_STREAM_ARBITER_CONTROL__SYS_MEM_ACTIVE_ENABLE_MASK 0x100
+#define AZALIA_OUTPUT_STREAM_ARBITER_CONTROL__SYS_MEM_ACTIVE_ENABLE__SHIFT 0x8
+#define AZALIA_OUTPUT_STREAM_ARBITER_CONTROL__INPUT_LATENCY_HIDING_LEVEL_MASK 0xff0000
+#define AZALIA_OUTPUT_STREAM_ARBITER_CONTROL__INPUT_LATENCY_HIDING_LEVEL__SHIFT 0x10
+#define AZALIA_INPUT_PAYLOAD_CAPABILITY__INPUT_PAYLOAD_CAPABILITY_MASK 0xffff
+#define AZALIA_INPUT_PAYLOAD_CAPABILITY__INPUT_PAYLOAD_CAPABILITY__SHIFT 0x0
+#define AZALIA_INPUT_PAYLOAD_CAPABILITY__INSTRMPAY_MASK 0xffff0000
+#define AZALIA_INPUT_PAYLOAD_CAPABILITY__INSTRMPAY__SHIFT 0x10
+#define AZALIA_CONTROLLER_DEBUG__CONTROLLER_DEBUG_MASK 0xffffffff
+#define AZALIA_CONTROLLER_DEBUG__CONTROLLER_DEBUG__SHIFT 0x0
+#define AZALIA_MEM_PWR_CTRL__AZ_MEM_PWR_FORCE_MASK 0x3
+#define AZALIA_MEM_PWR_CTRL__AZ_MEM_PWR_FORCE__SHIFT 0x0
+#define AZALIA_MEM_PWR_CTRL__AZ_MEM_PWR_DIS_MASK 0x4
+#define AZALIA_MEM_PWR_CTRL__AZ_MEM_PWR_DIS__SHIFT 0x2
+#define AZALIA_MEM_PWR_CTRL__AZ_INPUT_STREAM0_MEM_PWR_FORCE_MASK 0x18
+#define AZALIA_MEM_PWR_CTRL__AZ_INPUT_STREAM0_MEM_PWR_FORCE__SHIFT 0x3
+#define AZALIA_MEM_PWR_CTRL__AZ_INPUT_STREAM0_MEM_PWR_DIS_MASK 0x20
+#define AZALIA_MEM_PWR_CTRL__AZ_INPUT_STREAM0_MEM_PWR_DIS__SHIFT 0x5
+#define AZALIA_MEM_PWR_CTRL__AZ_INPUT_STREAM1_MEM_PWR_FORCE_MASK 0xc0
+#define AZALIA_MEM_PWR_CTRL__AZ_INPUT_STREAM1_MEM_PWR_FORCE__SHIFT 0x6
+#define AZALIA_MEM_PWR_CTRL__AZ_INPUT_STREAM1_MEM_PWR_DIS_MASK 0x100
+#define AZALIA_MEM_PWR_CTRL__AZ_INPUT_STREAM1_MEM_PWR_DIS__SHIFT 0x8
+#define AZALIA_MEM_PWR_CTRL__AZ_INPUT_STREAM2_MEM_PWR_FORCE_MASK 0x600
+#define AZALIA_MEM_PWR_CTRL__AZ_INPUT_STREAM2_MEM_PWR_FORCE__SHIFT 0x9
+#define AZALIA_MEM_PWR_CTRL__AZ_INPUT_STREAM2_MEM_PWR_DIS_MASK 0x800
+#define AZALIA_MEM_PWR_CTRL__AZ_INPUT_STREAM2_MEM_PWR_DIS__SHIFT 0xb
+#define AZALIA_MEM_PWR_CTRL__AZ_INPUT_STREAM3_MEM_PWR_FORCE_MASK 0x3000
+#define AZALIA_MEM_PWR_CTRL__AZ_INPUT_STREAM3_MEM_PWR_FORCE__SHIFT 0xc
+#define AZALIA_MEM_PWR_CTRL__AZ_INPUT_STREAM3_MEM_PWR_DIS_MASK 0x4000
+#define AZALIA_MEM_PWR_CTRL__AZ_INPUT_STREAM3_MEM_PWR_DIS__SHIFT 0xe
+#define AZALIA_MEM_PWR_CTRL__AZ_INPUT_STREAM4_MEM_PWR_FORCE_MASK 0x18000
+#define AZALIA_MEM_PWR_CTRL__AZ_INPUT_STREAM4_MEM_PWR_FORCE__SHIFT 0xf
+#define AZALIA_MEM_PWR_CTRL__AZ_INPUT_STREAM4_MEM_PWR_DIS_MASK 0x20000
+#define AZALIA_MEM_PWR_CTRL__AZ_INPUT_STREAM4_MEM_PWR_DIS__SHIFT 0x11
+#define AZALIA_MEM_PWR_CTRL__AZ_INPUT_STREAM5_MEM_PWR_FORCE_MASK 0xc0000
+#define AZALIA_MEM_PWR_CTRL__AZ_INPUT_STREAM5_MEM_PWR_FORCE__SHIFT 0x12
+#define AZALIA_MEM_PWR_CTRL__AZ_INPUT_STREAM5_MEM_PWR_DIS_MASK 0x100000
+#define AZALIA_MEM_PWR_CTRL__AZ_INPUT_STREAM5_MEM_PWR_DIS__SHIFT 0x14
+#define AZALIA_MEM_PWR_CTRL__AZ_MEM_PWR_MODE_SEL_MASK 0x30000000
+#define AZALIA_MEM_PWR_CTRL__AZ_MEM_PWR_MODE_SEL__SHIFT 0x1c
+#define AZALIA_MEM_PWR_STATUS__AZ_MEM_PWR_STATE_MASK 0x3
+#define AZALIA_MEM_PWR_STATUS__AZ_MEM_PWR_STATE__SHIFT 0x0
+#define AZALIA_MEM_PWR_STATUS__AZ_INPUT_STREAM0_MEM_PWR_STATE_MASK 0xc
+#define AZALIA_MEM_PWR_STATUS__AZ_INPUT_STREAM0_MEM_PWR_STATE__SHIFT 0x2
+#define AZALIA_MEM_PWR_STATUS__AZ_INPUT_STREAM1_MEM_PWR_STATE_MASK 0x30
+#define AZALIA_MEM_PWR_STATUS__AZ_INPUT_STREAM1_MEM_PWR_STATE__SHIFT 0x4
+#define AZALIA_MEM_PWR_STATUS__AZ_INPUT_STREAM2_MEM_PWR_STATE_MASK 0xc0
+#define AZALIA_MEM_PWR_STATUS__AZ_INPUT_STREAM2_MEM_PWR_STATE__SHIFT 0x6
+#define AZALIA_MEM_PWR_STATUS__AZ_INPUT_STREAM3_MEM_PWR_STATE_MASK 0x300
+#define AZALIA_MEM_PWR_STATUS__AZ_INPUT_STREAM3_MEM_PWR_STATE__SHIFT 0x8
+#define AZALIA_MEM_PWR_STATUS__AZ_INPUT_STREAM4_MEM_PWR_STATE_MASK 0xc00
+#define AZALIA_MEM_PWR_STATUS__AZ_INPUT_STREAM4_MEM_PWR_STATE__SHIFT 0xa
+#define AZALIA_MEM_PWR_STATUS__AZ_INPUT_STREAM5_MEM_PWR_STATE_MASK 0x3000
+#define AZALIA_MEM_PWR_STATUS__AZ_INPUT_STREAM5_MEM_PWR_STATE__SHIFT 0xc
+#define DCI_PG_DEBUG_CONFIG__DCI_PG_DBG_EN_MASK 0x1
+#define DCI_PG_DEBUG_CONFIG__DCI_PG_DBG_EN__SHIFT 0x0
+#define AZALIA_INPUT_CRC0_CONTROL0__INPUT_CRC_EN_MASK 0x1
+#define AZALIA_INPUT_CRC0_CONTROL0__INPUT_CRC_EN__SHIFT 0x0
+#define AZALIA_INPUT_CRC0_CONTROL0__INPUT_CRC_BLOCK_MODE_MASK 0x10
+#define AZALIA_INPUT_CRC0_CONTROL0__INPUT_CRC_BLOCK_MODE__SHIFT 0x4
+#define AZALIA_INPUT_CRC0_CONTROL0__INPUT_CRC_INSTANCE_SEL_MASK 0x700
+#define AZALIA_INPUT_CRC0_CONTROL0__INPUT_CRC_INSTANCE_SEL__SHIFT 0x8
+#define AZALIA_INPUT_CRC0_CONTROL1__INPUT_CRC_BLOCK_SIZE_MASK 0xffffffff
+#define AZALIA_INPUT_CRC0_CONTROL1__INPUT_CRC_BLOCK_SIZE__SHIFT 0x0
+#define AZALIA_INPUT_CRC0_CONTROL2__INPUT_CRC_BLOCK_ITERATION_MASK 0xffff
+#define AZALIA_INPUT_CRC0_CONTROL2__INPUT_CRC_BLOCK_ITERATION__SHIFT 0x0
+#define AZALIA_INPUT_CRC0_CONTROL3__INPUT_CRC_COMPLETE_MASK 0x1
+#define AZALIA_INPUT_CRC0_CONTROL3__INPUT_CRC_COMPLETE__SHIFT 0x0
+#define AZALIA_INPUT_CRC0_CONTROL3__INPUT_CRC_BLOCK_COMPLETE_PHASE_MASK 0x10
+#define AZALIA_INPUT_CRC0_CONTROL3__INPUT_CRC_BLOCK_COMPLETE_PHASE__SHIFT 0x4
+#define AZALIA_INPUT_CRC0_CONTROL3__INPUT_CRC_CHANNEL_RESULT_SEL_MASK 0x700
+#define AZALIA_INPUT_CRC0_CONTROL3__INPUT_CRC_CHANNEL_RESULT_SEL__SHIFT 0x8
+#define AZALIA_INPUT_CRC0_RESULT__INPUT_CRC_RESULT_MASK 0xffffffff
+#define AZALIA_INPUT_CRC0_RESULT__INPUT_CRC_RESULT__SHIFT 0x0
+#define AZALIA_INPUT_CRC0_CHANNEL0__INPUT_CRC_CHANNEL0_MASK 0xffffffff
+#define AZALIA_INPUT_CRC0_CHANNEL0__INPUT_CRC_CHANNEL0__SHIFT 0x0
+#define AZALIA_INPUT_CRC0_CHANNEL1__INPUT_CRC_CHANNEL1_MASK 0xffffffff
+#define AZALIA_INPUT_CRC0_CHANNEL1__INPUT_CRC_CHANNEL1__SHIFT 0x0
+#define AZALIA_INPUT_CRC0_CHANNEL2__INPUT_CRC_CHANNEL2_MASK 0xffffffff
+#define AZALIA_INPUT_CRC0_CHANNEL2__INPUT_CRC_CHANNEL2__SHIFT 0x0
+#define AZALIA_INPUT_CRC0_CHANNEL3__INPUT_CRC_CHANNEL3_MASK 0xffffffff
+#define AZALIA_INPUT_CRC0_CHANNEL3__INPUT_CRC_CHANNEL3__SHIFT 0x0
+#define AZALIA_INPUT_CRC0_CHANNEL4__INPUT_CRC_CHANNEL4_MASK 0xffffffff
+#define AZALIA_INPUT_CRC0_CHANNEL4__INPUT_CRC_CHANNEL4__SHIFT 0x0
+#define AZALIA_INPUT_CRC0_CHANNEL5__INPUT_CRC_CHANNEL5_MASK 0xffffffff
+#define AZALIA_INPUT_CRC0_CHANNEL5__INPUT_CRC_CHANNEL5__SHIFT 0x0
+#define AZALIA_INPUT_CRC0_CHANNEL6__INPUT_CRC_CHANNEL6_MASK 0xffffffff
+#define AZALIA_INPUT_CRC0_CHANNEL6__INPUT_CRC_CHANNEL6__SHIFT 0x0
+#define AZALIA_INPUT_CRC0_CHANNEL7__INPUT_CRC_CHANNEL7_MASK 0xffffffff
+#define AZALIA_INPUT_CRC0_CHANNEL7__INPUT_CRC_CHANNEL7__SHIFT 0x0
+#define AZALIA_INPUT_CRC1_CONTROL0__INPUT_CRC_EN_MASK 0x1
+#define AZALIA_INPUT_CRC1_CONTROL0__INPUT_CRC_EN__SHIFT 0x0
+#define AZALIA_INPUT_CRC1_CONTROL0__INPUT_CRC_BLOCK_MODE_MASK 0x10
+#define AZALIA_INPUT_CRC1_CONTROL0__INPUT_CRC_BLOCK_MODE__SHIFT 0x4
+#define AZALIA_INPUT_CRC1_CONTROL0__INPUT_CRC_INSTANCE_SEL_MASK 0x700
+#define AZALIA_INPUT_CRC1_CONTROL0__INPUT_CRC_INSTANCE_SEL__SHIFT 0x8
+#define AZALIA_INPUT_CRC1_CONTROL1__INPUT_CRC_BLOCK_SIZE_MASK 0xffffffff
+#define AZALIA_INPUT_CRC1_CONTROL1__INPUT_CRC_BLOCK_SIZE__SHIFT 0x0
+#define AZALIA_INPUT_CRC1_CONTROL2__INPUT_CRC_BLOCK_ITERATION_MASK 0xffff
+#define AZALIA_INPUT_CRC1_CONTROL2__INPUT_CRC_BLOCK_ITERATION__SHIFT 0x0
+#define AZALIA_INPUT_CRC1_CONTROL3__INPUT_CRC_COMPLETE_MASK 0x1
+#define AZALIA_INPUT_CRC1_CONTROL3__INPUT_CRC_COMPLETE__SHIFT 0x0
+#define AZALIA_INPUT_CRC1_CONTROL3__INPUT_CRC_BLOCK_COMPLETE_PHASE_MASK 0x10
+#define AZALIA_INPUT_CRC1_CONTROL3__INPUT_CRC_BLOCK_COMPLETE_PHASE__SHIFT 0x4
+#define AZALIA_INPUT_CRC1_CONTROL3__INPUT_CRC_CHANNEL_RESULT_SEL_MASK 0x700
+#define AZALIA_INPUT_CRC1_CONTROL3__INPUT_CRC_CHANNEL_RESULT_SEL__SHIFT 0x8
+#define AZALIA_INPUT_CRC1_RESULT__INPUT_CRC_RESULT_MASK 0xffffffff
+#define AZALIA_INPUT_CRC1_RESULT__INPUT_CRC_RESULT__SHIFT 0x0
+#define AZALIA_INPUT_CRC1_CHANNEL0__INPUT_CRC_CHANNEL0_MASK 0xffffffff
+#define AZALIA_INPUT_CRC1_CHANNEL0__INPUT_CRC_CHANNEL0__SHIFT 0x0
+#define AZALIA_INPUT_CRC1_CHANNEL1__INPUT_CRC_CHANNEL1_MASK 0xffffffff
+#define AZALIA_INPUT_CRC1_CHANNEL1__INPUT_CRC_CHANNEL1__SHIFT 0x0
+#define AZALIA_INPUT_CRC1_CHANNEL2__INPUT_CRC_CHANNEL2_MASK 0xffffffff
+#define AZALIA_INPUT_CRC1_CHANNEL2__INPUT_CRC_CHANNEL2__SHIFT 0x0
+#define AZALIA_INPUT_CRC1_CHANNEL3__INPUT_CRC_CHANNEL3_MASK 0xffffffff
+#define AZALIA_INPUT_CRC1_CHANNEL3__INPUT_CRC_CHANNEL3__SHIFT 0x0
+#define AZALIA_INPUT_CRC1_CHANNEL4__INPUT_CRC_CHANNEL4_MASK 0xffffffff
+#define AZALIA_INPUT_CRC1_CHANNEL4__INPUT_CRC_CHANNEL4__SHIFT 0x0
+#define AZALIA_INPUT_CRC1_CHANNEL5__INPUT_CRC_CHANNEL5_MASK 0xffffffff
+#define AZALIA_INPUT_CRC1_CHANNEL5__INPUT_CRC_CHANNEL5__SHIFT 0x0
+#define AZALIA_INPUT_CRC1_CHANNEL6__INPUT_CRC_CHANNEL6_MASK 0xffffffff
+#define AZALIA_INPUT_CRC1_CHANNEL6__INPUT_CRC_CHANNEL6__SHIFT 0x0
+#define AZALIA_INPUT_CRC1_CHANNEL7__INPUT_CRC_CHANNEL7_MASK 0xffffffff
+#define AZALIA_INPUT_CRC1_CHANNEL7__INPUT_CRC_CHANNEL7__SHIFT 0x0
+#define AZALIA_CRC0_CONTROL0__CRC_EN_MASK 0x1
+#define AZALIA_CRC0_CONTROL0__CRC_EN__SHIFT 0x0
+#define AZALIA_CRC0_CONTROL0__CRC_BLOCK_MODE_MASK 0x10
+#define AZALIA_CRC0_CONTROL0__CRC_BLOCK_MODE__SHIFT 0x4
+#define AZALIA_CRC0_CONTROL0__CRC_INSTANCE_SEL_MASK 0x700
+#define AZALIA_CRC0_CONTROL0__CRC_INSTANCE_SEL__SHIFT 0x8
+#define AZALIA_CRC0_CONTROL0__CRC_SOURCE_SEL_MASK 0x1000
+#define AZALIA_CRC0_CONTROL0__CRC_SOURCE_SEL__SHIFT 0xc
+#define AZALIA_CRC0_CONTROL1__CRC_BLOCK_SIZE_MASK 0xffffffff
+#define AZALIA_CRC0_CONTROL1__CRC_BLOCK_SIZE__SHIFT 0x0
+#define AZALIA_CRC0_CONTROL2__CRC_BLOCK_ITERATION_MASK 0xffff
+#define AZALIA_CRC0_CONTROL2__CRC_BLOCK_ITERATION__SHIFT 0x0
+#define AZALIA_CRC0_CONTROL3__CRC_COMPLETE_MASK 0x1
+#define AZALIA_CRC0_CONTROL3__CRC_COMPLETE__SHIFT 0x0
+#define AZALIA_CRC0_CONTROL3__CRC_BLOCK_COMPLETE_PHASE_MASK 0x10
+#define AZALIA_CRC0_CONTROL3__CRC_BLOCK_COMPLETE_PHASE__SHIFT 0x4
+#define AZALIA_CRC0_CONTROL3__CRC_CHANNEL_RESULT_SEL_MASK 0x700
+#define AZALIA_CRC0_CONTROL3__CRC_CHANNEL_RESULT_SEL__SHIFT 0x8
+#define AZALIA_CRC0_RESULT__CRC_RESULT_MASK 0xffffffff
+#define AZALIA_CRC0_RESULT__CRC_RESULT__SHIFT 0x0
+#define AZALIA_CRC0_CHANNEL0__CRC_CHANNEL0_MASK 0xffffffff
+#define AZALIA_CRC0_CHANNEL0__CRC_CHANNEL0__SHIFT 0x0
+#define AZALIA_CRC0_CHANNEL1__CRC_CHANNEL1_MASK 0xffffffff
+#define AZALIA_CRC0_CHANNEL1__CRC_CHANNEL1__SHIFT 0x0
+#define AZALIA_CRC0_CHANNEL2__CRC_CHANNEL2_MASK 0xffffffff
+#define AZALIA_CRC0_CHANNEL2__CRC_CHANNEL2__SHIFT 0x0
+#define AZALIA_CRC0_CHANNEL3__CRC_CHANNEL3_MASK 0xffffffff
+#define AZALIA_CRC0_CHANNEL3__CRC_CHANNEL3__SHIFT 0x0
+#define AZALIA_CRC0_CHANNEL4__CRC_CHANNEL4_MASK 0xffffffff
+#define AZALIA_CRC0_CHANNEL4__CRC_CHANNEL4__SHIFT 0x0
+#define AZALIA_CRC0_CHANNEL5__CRC_CHANNEL5_MASK 0xffffffff
+#define AZALIA_CRC0_CHANNEL5__CRC_CHANNEL5__SHIFT 0x0
+#define AZALIA_CRC0_CHANNEL6__CRC_CHANNEL6_MASK 0xffffffff
+#define AZALIA_CRC0_CHANNEL6__CRC_CHANNEL6__SHIFT 0x0
+#define AZALIA_CRC0_CHANNEL7__CRC_CHANNEL7_MASK 0xffffffff
+#define AZALIA_CRC0_CHANNEL7__CRC_CHANNEL7__SHIFT 0x0
+#define AZALIA_CRC1_CONTROL0__CRC_EN_MASK 0x1
+#define AZALIA_CRC1_CONTROL0__CRC_EN__SHIFT 0x0
+#define AZALIA_CRC1_CONTROL0__CRC_BLOCK_MODE_MASK 0x10
+#define AZALIA_CRC1_CONTROL0__CRC_BLOCK_MODE__SHIFT 0x4
+#define AZALIA_CRC1_CONTROL0__CRC_INSTANCE_SEL_MASK 0x700
+#define AZALIA_CRC1_CONTROL0__CRC_INSTANCE_SEL__SHIFT 0x8
+#define AZALIA_CRC1_CONTROL0__CRC_SOURCE_SEL_MASK 0x1000
+#define AZALIA_CRC1_CONTROL0__CRC_SOURCE_SEL__SHIFT 0xc
+#define AZALIA_CRC1_CONTROL1__CRC_BLOCK_SIZE_MASK 0xffffffff
+#define AZALIA_CRC1_CONTROL1__CRC_BLOCK_SIZE__SHIFT 0x0
+#define AZALIA_CRC1_CONTROL2__CRC_BLOCK_ITERATION_MASK 0xffff
+#define AZALIA_CRC1_CONTROL2__CRC_BLOCK_ITERATION__SHIFT 0x0
+#define AZALIA_CRC1_CONTROL3__CRC_COMPLETE_MASK 0x1
+#define AZALIA_CRC1_CONTROL3__CRC_COMPLETE__SHIFT 0x0
+#define AZALIA_CRC1_CONTROL3__CRC_BLOCK_COMPLETE_PHASE_MASK 0x10
+#define AZALIA_CRC1_CONTROL3__CRC_BLOCK_COMPLETE_PHASE__SHIFT 0x4
+#define AZALIA_CRC1_CONTROL3__CRC_CHANNEL_RESULT_SEL_MASK 0x700
+#define AZALIA_CRC1_CONTROL3__CRC_CHANNEL_RESULT_SEL__SHIFT 0x8
+#define AZALIA_CRC1_RESULT__CRC_RESULT_MASK 0xffffffff
+#define AZALIA_CRC1_RESULT__CRC_RESULT__SHIFT 0x0
+#define AZALIA_CRC1_CHANNEL0__CRC_CHANNEL0_MASK 0xffffffff
+#define AZALIA_CRC1_CHANNEL0__CRC_CHANNEL0__SHIFT 0x0
+#define AZALIA_CRC1_CHANNEL1__CRC_CHANNEL1_MASK 0xffffffff
+#define AZALIA_CRC1_CHANNEL1__CRC_CHANNEL1__SHIFT 0x0
+#define AZALIA_CRC1_CHANNEL2__CRC_CHANNEL2_MASK 0xffffffff
+#define AZALIA_CRC1_CHANNEL2__CRC_CHANNEL2__SHIFT 0x0
+#define AZALIA_CRC1_CHANNEL3__CRC_CHANNEL3_MASK 0xffffffff
+#define AZALIA_CRC1_CHANNEL3__CRC_CHANNEL3__SHIFT 0x0
+#define AZALIA_CRC1_CHANNEL4__CRC_CHANNEL4_MASK 0xffffffff
+#define AZALIA_CRC1_CHANNEL4__CRC_CHANNEL4__SHIFT 0x0
+#define AZALIA_CRC1_CHANNEL5__CRC_CHANNEL5_MASK 0xffffffff
+#define AZALIA_CRC1_CHANNEL5__CRC_CHANNEL5__SHIFT 0x0
+#define AZALIA_CRC1_CHANNEL6__CRC_CHANNEL6_MASK 0xffffffff
+#define AZALIA_CRC1_CHANNEL6__CRC_CHANNEL6__SHIFT 0x0
+#define AZALIA_CRC1_CHANNEL7__CRC_CHANNEL7_MASK 0xffffffff
+#define AZALIA_CRC1_CHANNEL7__CRC_CHANNEL7__SHIFT 0x0
+#define AZ_TEST_DEBUG_INDEX__AZ_TEST_DEBUG_INDEX_MASK 0xff
+#define AZ_TEST_DEBUG_INDEX__AZ_TEST_DEBUG_INDEX__SHIFT 0x0
+#define AZ_TEST_DEBUG_INDEX__AZ_TEST_DEBUG_WRITE_EN_MASK 0x100
+#define AZ_TEST_DEBUG_INDEX__AZ_TEST_DEBUG_WRITE_EN__SHIFT 0x8
+#define AZ_TEST_DEBUG_DATA__AZ_TEST_DEBUG_DATA_MASK 0xffffffff
+#define AZ_TEST_DEBUG_DATA__AZ_TEST_DEBUG_DATA__SHIFT 0x0
+#define AZALIA_STREAM_INDEX__AZALIA_STREAM_REG_INDEX_MASK 0xff
+#define AZALIA_STREAM_INDEX__AZALIA_STREAM_REG_INDEX__SHIFT 0x0
+#define AZALIA_STREAM_INDEX__AZALIA_STREAM_REG_WRITE_EN_MASK 0x100
+#define AZALIA_STREAM_INDEX__AZALIA_STREAM_REG_WRITE_EN__SHIFT 0x8
+#define AZALIA_STREAM_DATA__AZALIA_STREAM_REG_DATA_MASK 0xffffffff
+#define AZALIA_STREAM_DATA__AZALIA_STREAM_REG_DATA__SHIFT 0x0
+#define AZALIA_FIFO_SIZE_CONTROL__MIN_FIFO_SIZE_MASK 0x7f
+#define AZALIA_FIFO_SIZE_CONTROL__MIN_FIFO_SIZE__SHIFT 0x0
+#define AZALIA_FIFO_SIZE_CONTROL__MAX_FIFO_SIZE_MASK 0x7f00
+#define AZALIA_FIFO_SIZE_CONTROL__MAX_FIFO_SIZE__SHIFT 0x8
+#define AZALIA_FIFO_SIZE_CONTROL__MAX_LATENCY_SUPPORT_MASK 0xff0000
+#define AZALIA_FIFO_SIZE_CONTROL__MAX_LATENCY_SUPPORT__SHIFT 0x10
+#define AZALIA_LATENCY_COUNTER_CONTROL__AZALIA_LATENCY_COUNTER_RESET_MASK 0x1
+#define AZALIA_LATENCY_COUNTER_CONTROL__AZALIA_LATENCY_COUNTER_RESET__SHIFT 0x0
+#define AZALIA_WORSTCASE_LATENCY_COUNT__AZALIA_WORSTCASE_LATENCY_COUNT_MASK 0xffffffff
+#define AZALIA_WORSTCASE_LATENCY_COUNT__AZALIA_WORSTCASE_LATENCY_COUNT__SHIFT 0x0
+#define AZALIA_CUMULATIVE_LATENCY_COUNT__AZALIA_CUMULATIVE_LATENCY_COUNT_MASK 0xffffffff
+#define AZALIA_CUMULATIVE_LATENCY_COUNT__AZALIA_CUMULATIVE_LATENCY_COUNT__SHIFT 0x0
+#define AZALIA_CUMULATIVE_REQUEST_COUNT__AZALIA_CUMULATIVE_REQUEST_COUNT_MASK 0xffffffff
+#define AZALIA_CUMULATIVE_REQUEST_COUNT__AZALIA_CUMULATIVE_REQUEST_COUNT__SHIFT 0x0
+#define AZALIA_STREAM_DEBUG__STREAM_DEBUG_DATA_MASK 0xffffffff
+#define AZALIA_STREAM_DEBUG__STREAM_DEBUG_DATA__SHIFT 0x0
+#define AZALIA_F0_CODEC_ENDPOINT_INDEX__AZALIA_ENDPOINT_REG_INDEX_MASK 0x3fff
+#define AZALIA_F0_CODEC_ENDPOINT_INDEX__AZALIA_ENDPOINT_REG_INDEX__SHIFT 0x0
+#define AZALIA_F0_CODEC_ENDPOINT_DATA__AZALIA_ENDPOINT_REG_DATA_MASK 0xffffffff
+#define AZALIA_F0_CODEC_ENDPOINT_DATA__AZALIA_ENDPOINT_REG_DATA__SHIFT 0x0
+#define AZALIA_F0_CODEC_CONVERTER_PIN_DEBUG__AZALIA_DEBUG__SHIFT 0x0
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_CHANNEL_CAPABILITIES_MASK 0x1
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_CHANNEL_CAPABILITIES__SHIFT 0x0
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__INPUT_AMPLIFIER_PRESENT_MASK 0x2
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__INPUT_AMPLIFIER_PRESENT__SHIFT 0x1
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__OUTPUT_AMPLIFIER_PRESENT_MASK 0x4
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__OUTPUT_AMPLIFIER_PRESENT__SHIFT 0x2
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AMPLIFIER_PARAMETER_OVERRIDE_MASK 0x8
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AMPLIFIER_PARAMETER_OVERRIDE__SHIFT 0x3
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__FORMAT_OVERRIDE_MASK 0x10
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__FORMAT_OVERRIDE__SHIFT 0x4
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__STRIPE_MASK 0x20
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__STRIPE__SHIFT 0x5
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__PROCESSING_WIDGET_MASK 0x40
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__PROCESSING_WIDGET__SHIFT 0x6
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__UNSOLICITED_RESPONSE_CAPABILITY_MASK 0x80
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__UNSOLICITED_RESPONSE_CAPABILITY__SHIFT 0x7
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__CONNECTION_LIST_MASK 0x100
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__CONNECTION_LIST__SHIFT 0x8
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__DIGITAL_MASK 0x200
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__DIGITAL__SHIFT 0x9
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__POWER_CONTROL_MASK 0x400
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__POWER_CONTROL__SHIFT 0xa
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__LR_SWAP_MASK 0x800
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__LR_SWAP__SHIFT 0xb
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_WIDGET_CAPABILITIES_DELAY_MASK 0xf0000
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_WIDGET_CAPABILITIES_DELAY__SHIFT 0x10
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__TYPE_MASK 0xf00000
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__TYPE__SHIFT 0x14
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__NUMBER_OF_CHANNELS_MASK 0xf
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__NUMBER_OF_CHANNELS__SHIFT 0x0
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__BITS_PER_SAMPLE_MASK 0x70
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__BITS_PER_SAMPLE__SHIFT 0x4
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_DIVISOR_MASK 0x700
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_DIVISOR__SHIFT 0x8
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_MULTIPLE_MASK 0x3800
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_MULTIPLE__SHIFT 0xb
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_RATE_MASK 0x4000
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_RATE__SHIFT 0xe
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__STREAM_TYPE_MASK 0x8000
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__STREAM_TYPE__SHIFT 0xf
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CHANNEL_STREAM_ID__CHANNEL_ID_MASK 0xf
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CHANNEL_STREAM_ID__CHANNEL_ID__SHIFT 0x0
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CHANNEL_STREAM_ID__STREAM_ID_MASK 0xf0
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CHANNEL_STREAM_ID__STREAM_ID__SHIFT 0x4
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__DIGEN_MASK 0x1
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__DIGEN__SHIFT 0x0
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__V_MASK 0x2
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__V__SHIFT 0x1
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__VCFG_MASK 0x4
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__VCFG__SHIFT 0x2
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__PRE_MASK 0x8
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__PRE__SHIFT 0x3
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__COPY_MASK 0x10
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__COPY__SHIFT 0x4
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__NON_AUDIO_MASK 0x20
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__NON_AUDIO__SHIFT 0x5
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__PRO_MASK 0x40
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__PRO__SHIFT 0x6
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__L_MASK 0x80
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__L__SHIFT 0x7
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__CC_MASK 0x7f00
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__CC__SHIFT 0x8
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__KEEPALIVE_MASK 0x800000
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__KEEPALIVE__SHIFT 0x17
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_STREAM_FORMATS__STREAM_FORMATS_MASK 0xffffffff
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_STREAM_FORMATS__STREAM_FORMATS__SHIFT 0x0
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_RATE_CAPABILITIES_MASK 0xfff
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_RATE_CAPABILITIES__SHIFT 0x0
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_BIT_CAPABILITIES_MASK 0x1f0000
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_BIT_CAPABILITIES__SHIFT 0x10
+#define AZALIA_F0_CODEC_CONVERTER_STRIPE_CONTROL__STRIPE_CONTROL_MASK 0x3
+#define AZALIA_F0_CODEC_CONVERTER_STRIPE_CONTROL__STRIPE_CONTROL__SHIFT 0x0
+#define AZALIA_F0_CODEC_CONVERTER_STRIPE_CONTROL__STRIPE_CAPABILITY_MASK 0x700000
+#define AZALIA_F0_CODEC_CONVERTER_STRIPE_CONTROL__STRIPE_CAPABILITY__SHIFT 0x14
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_RAMP_RATE__RAMP_RATE_MASK 0xff
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_RAMP_RATE__RAMP_RATE__SHIFT 0x0
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING__PRESENTATION_TIME_EMBEDDING_ENABLE_MASK 0x1
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING__PRESENTATION_TIME_EMBEDDING_ENABLE__SHIFT 0x0
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING__PRESENTATION_TIME_OFFSET_CHANGED_MASK 0x2
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING__PRESENTATION_TIME_OFFSET_CHANGED__SHIFT 0x1
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING__CLEAR_GTC_COUNTER_MIN_MAX_DELTA_MASK 0x4
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING__CLEAR_GTC_COUNTER_MIN_MAX_DELTA__SHIFT 0x2
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING__PRESENTATION_TIME_EMBEDDING_GROUP_MASK 0x70
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING__PRESENTATION_TIME_EMBEDDING_GROUP__SHIFT 0x4
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_OFFSET_DEBUG__PRESENTATION_TIME_OFFSET_DEBUG_MASK 0xffffffff
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_OFFSET_DEBUG__PRESENTATION_TIME_OFFSET_DEBUG__SHIFT 0x0
+#define AZALIA_F0_CODEC_CONVERTER_GTC_COUNTER_DELTA__GTC_COUNTER_DELTA_MASK 0xffffffff
+#define AZALIA_F0_CODEC_CONVERTER_GTC_COUNTER_DELTA__GTC_COUNTER_DELTA__SHIFT 0x0
+#define AZALIA_F0_CODEC_CONVERTER_GTC_COUNTER_DELTA_MIN__GTC_COUNTER_DELTA_MIN_MASK 0xffffffff
+#define AZALIA_F0_CODEC_CONVERTER_GTC_COUNTER_DELTA_MIN__GTC_COUNTER_DELTA_MIN__SHIFT 0x0
+#define AZALIA_F0_CODEC_CONVERTER_GTC_COUNTER_DELTA_MAX__GTC_COUNTER_DELTA_MAX_MASK 0xffffffff
+#define AZALIA_F0_CODEC_CONVERTER_GTC_COUNTER_DELTA_MAX__GTC_COUNTER_DELTA_MAX__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_CHANNEL_CAPABILITIES_MASK 0x1
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_CHANNEL_CAPABILITIES__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__INPUT_AMPLIFIER_PRESENT_MASK 0x2
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__INPUT_AMPLIFIER_PRESENT__SHIFT 0x1
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__OUTPUT_AMPLIFIER_PRESENT_MASK 0x4
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__OUTPUT_AMPLIFIER_PRESENT__SHIFT 0x2
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AMPLIFIER_PARAMETER_OVERRIDE_MASK 0x8
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AMPLIFIER_PARAMETER_OVERRIDE__SHIFT 0x3
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__STRIPE_MASK 0x20
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__STRIPE__SHIFT 0x5
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__PROCESSING_WIDGET_MASK 0x40
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__PROCESSING_WIDGET__SHIFT 0x6
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__UNSOLICITED_RESPONSE_CAPABILITY_MASK 0x80
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__UNSOLICITED_RESPONSE_CAPABILITY__SHIFT 0x7
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__CONNECTION_LIST_MASK 0x100
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__CONNECTION_LIST__SHIFT 0x8
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__DIGITAL_MASK 0x200
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__DIGITAL__SHIFT 0x9
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__POWER_CONTROL_MASK 0x400
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__POWER_CONTROL__SHIFT 0xa
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__LR_SWAP_MASK 0x800
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__LR_SWAP__SHIFT 0xb
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_WIDGET_CAPABILITIES_DELAY_MASK 0xf0000
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_WIDGET_CAPABILITIES_DELAY__SHIFT 0x10
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__TYPE_MASK 0xf00000
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__TYPE__SHIFT 0x14
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__IMPEDANCE_SENSE_CAPABLE_MASK 0x1
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__IMPEDANCE_SENSE_CAPABLE__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__TRIGGER_REQUIRED_MASK 0x2
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__TRIGGER_REQUIRED__SHIFT 0x1
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__JACK_DETECTION_CAPABILITY_MASK 0x4
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__JACK_DETECTION_CAPABILITY__SHIFT 0x2
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__HEADPHONE_DRIVE_CAPABLE_MASK 0x8
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__HEADPHONE_DRIVE_CAPABLE__SHIFT 0x3
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__OUTPUT_CAPABLE_MASK 0x10
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__OUTPUT_CAPABLE__SHIFT 0x4
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__INPUT_CAPABLE_MASK 0x20
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__INPUT_CAPABLE__SHIFT 0x5
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__BALANCED_I_O_PINS_MASK 0x40
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__BALANCED_I_O_PINS__SHIFT 0x6
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__HDMI_MASK 0x80
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__HDMI__SHIFT 0x7
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__VREF_CONTROL_MASK 0xff00
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__VREF_CONTROL__SHIFT 0x8
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__EAPD_CAPABLE_MASK 0x10000
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__EAPD_CAPABLE__SHIFT 0x10
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__DP_MASK 0x1000000
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__DP__SHIFT 0x18
+#define AZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE__TAG_MASK 0x3f
+#define AZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE__TAG__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE__ENABLE_MASK 0x80
+#define AZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE__ENABLE__SHIFT 0x7
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_PIN_SENSE__IMPEDANCE_SENSE_MASK 0x7fffffff
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_PIN_SENSE__IMPEDANCE_SENSE__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_WIDGET_CONTROL__OUT_ENABLE_MASK 0x40
+#define AZALIA_F0_CODEC_PIN_CONTROL_WIDGET_CONTROL__OUT_ENABLE__SHIFT 0x6
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__SPEAKER_ALLOCATION_MASK 0x7f
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__SPEAKER_ALLOCATION__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__CHANNEL_ALLOCATION_MASK 0xff00
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__CHANNEL_ALLOCATION__SHIFT 0x8
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__HDMI_CONNECTION_MASK 0x10000
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__HDMI_CONNECTION__SHIFT 0x10
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__DP_CONNECTION_MASK 0x20000
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__DP_CONNECTION__SHIFT 0x11
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__EXTRA_CONNECTION_INFO_MASK 0xfc0000
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__EXTRA_CONNECTION_INFO__SHIFT 0x12
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__LFE_PLAYBACK_LEVEL_MASK 0x3000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__LFE_PLAYBACK_LEVEL__SHIFT 0x18
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__LEVEL_SHIFT_MASK 0x78000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__LEVEL_SHIFT__SHIFT 0x1b
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__DOWN_MIX_INHIBIT_MASK 0x80000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__DOWN_MIX_INHIBIT__SHIFT 0x1f
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0__MAX_CHANNELS_MASK 0x7
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0__MAX_CHANNELS__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0__SUPPORTED_FREQUENCIES_MASK 0xff00
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0__SUPPORTED_FREQUENCIES__SHIFT 0x8
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0__DESCRIPTOR_BYTE_2_MASK 0xff0000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0__DESCRIPTOR_BYTE_2__SHIFT 0x10
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x18
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR1__MAX_CHANNELS_MASK 0x7
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR1__MAX_CHANNELS__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR1__SUPPORTED_FREQUENCIES_MASK 0xff00
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR1__SUPPORTED_FREQUENCIES__SHIFT 0x8
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR1__DESCRIPTOR_BYTE_2_MASK 0xff0000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR1__DESCRIPTOR_BYTE_2__SHIFT 0x10
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR2__MAX_CHANNELS_MASK 0x7
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR2__MAX_CHANNELS__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR2__SUPPORTED_FREQUENCIES_MASK 0xff00
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR2__SUPPORTED_FREQUENCIES__SHIFT 0x8
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR2__DESCRIPTOR_BYTE_2_MASK 0xff0000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR2__DESCRIPTOR_BYTE_2__SHIFT 0x10
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR3__MAX_CHANNELS_MASK 0x7
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR3__MAX_CHANNELS__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR3__SUPPORTED_FREQUENCIES_MASK 0xff00
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR3__SUPPORTED_FREQUENCIES__SHIFT 0x8
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR3__DESCRIPTOR_BYTE_2_MASK 0xff0000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR3__DESCRIPTOR_BYTE_2__SHIFT 0x10
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR4__MAX_CHANNELS_MASK 0x7
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR4__MAX_CHANNELS__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR4__SUPPORTED_FREQUENCIES_MASK 0xff00
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR4__SUPPORTED_FREQUENCIES__SHIFT 0x8
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR4__DESCRIPTOR_BYTE_2_MASK 0xff0000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR4__DESCRIPTOR_BYTE_2__SHIFT 0x10
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR5__MAX_CHANNELS_MASK 0x7
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR5__MAX_CHANNELS__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR5__SUPPORTED_FREQUENCIES_MASK 0xff00
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR5__SUPPORTED_FREQUENCIES__SHIFT 0x8
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR5__DESCRIPTOR_BYTE_2_MASK 0xff0000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR5__DESCRIPTOR_BYTE_2__SHIFT 0x10
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR6__MAX_CHANNELS_MASK 0x7
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR6__MAX_CHANNELS__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR6__SUPPORTED_FREQUENCIES_MASK 0xff00
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR6__SUPPORTED_FREQUENCIES__SHIFT 0x8
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR6__DESCRIPTOR_BYTE_2_MASK 0xff0000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR6__DESCRIPTOR_BYTE_2__SHIFT 0x10
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR7__MAX_CHANNELS_MASK 0x7
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR7__MAX_CHANNELS__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR7__SUPPORTED_FREQUENCIES_MASK 0xff00
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR7__SUPPORTED_FREQUENCIES__SHIFT 0x8
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR7__DESCRIPTOR_BYTE_2_MASK 0xff0000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR7__DESCRIPTOR_BYTE_2__SHIFT 0x10
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR8__MAX_CHANNELS_MASK 0x7
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR8__MAX_CHANNELS__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR8__SUPPORTED_FREQUENCIES_MASK 0xff00
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR8__SUPPORTED_FREQUENCIES__SHIFT 0x8
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR8__DESCRIPTOR_BYTE_2_MASK 0xff0000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR8__DESCRIPTOR_BYTE_2__SHIFT 0x10
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR9__MAX_CHANNELS_MASK 0x7
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR9__MAX_CHANNELS__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR9__SUPPORTED_FREQUENCIES_MASK 0xff00
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR9__SUPPORTED_FREQUENCIES__SHIFT 0x8
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR9__DESCRIPTOR_BYTE_2_MASK 0xff0000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR9__DESCRIPTOR_BYTE_2__SHIFT 0x10
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR10__MAX_CHANNELS_MASK 0x7
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR10__MAX_CHANNELS__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR10__SUPPORTED_FREQUENCIES_MASK 0xff00
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR10__SUPPORTED_FREQUENCIES__SHIFT 0x8
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR10__DESCRIPTOR_BYTE_2_MASK 0xff0000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR10__DESCRIPTOR_BYTE_2__SHIFT 0x10
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR11__MAX_CHANNELS_MASK 0x7
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR11__MAX_CHANNELS__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR11__SUPPORTED_FREQUENCIES_MASK 0xff00
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR11__SUPPORTED_FREQUENCIES__SHIFT 0x8
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR11__DESCRIPTOR_BYTE_2_MASK 0xff0000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR11__DESCRIPTOR_BYTE_2__SHIFT 0x10
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR12__MAX_CHANNELS_MASK 0x7
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR12__MAX_CHANNELS__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR12__SUPPORTED_FREQUENCIES_MASK 0xff00
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR12__SUPPORTED_FREQUENCIES__SHIFT 0x8
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR12__DESCRIPTOR_BYTE_2_MASK 0xff0000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR12__DESCRIPTOR_BYTE_2__SHIFT 0x10
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR13__MAX_CHANNELS_MASK 0x7
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR13__MAX_CHANNELS__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR13__SUPPORTED_FREQUENCIES_MASK 0xff00
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR13__SUPPORTED_FREQUENCIES__SHIFT 0x8
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR13__DESCRIPTOR_BYTE_2_MASK 0xff0000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR13__DESCRIPTOR_BYTE_2__SHIFT 0x10
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL01_ENABLE_MASK 0x1
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL01_ENABLE__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL01_MUTE_MASK 0x2
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL01_MUTE__SHIFT 0x1
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL01_CHANNEL_ID_MASK 0xf0
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL01_CHANNEL_ID__SHIFT 0x4
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL23_ENABLE_MASK 0x100
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL23_ENABLE__SHIFT 0x8
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL23_MUTE_MASK 0x200
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL23_MUTE__SHIFT 0x9
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL23_CHANNEL_ID_MASK 0xf000
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL23_CHANNEL_ID__SHIFT 0xc
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL45_ENABLE_MASK 0x10000
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL45_ENABLE__SHIFT 0x10
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL45_MUTE_MASK 0x20000
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL45_MUTE__SHIFT 0x11
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL45_CHANNEL_ID_MASK 0xf00000
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL45_CHANNEL_ID__SHIFT 0x14
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL67_ENABLE_MASK 0x1000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL67_ENABLE__SHIFT 0x18
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL67_MUTE_MASK 0x2000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL67_MUTE__SHIFT 0x19
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL67_CHANNEL_ID_MASK 0xf0000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL67_CHANNEL_ID__SHIFT 0x1c
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL1_ENABLE_MASK 0x1
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL1_ENABLE__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL1_MUTE_MASK 0x2
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL1_MUTE__SHIFT 0x1
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL1_CHANNEL_ID_MASK 0xf0
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL1_CHANNEL_ID__SHIFT 0x4
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL3_ENABLE_MASK 0x100
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL3_ENABLE__SHIFT 0x8
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL3_MUTE_MASK 0x200
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL3_MUTE__SHIFT 0x9
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL3_CHANNEL_ID_MASK 0xf000
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL3_CHANNEL_ID__SHIFT 0xc
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL5_ENABLE_MASK 0x10000
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL5_ENABLE__SHIFT 0x10
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL5_MUTE_MASK 0x20000
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL5_MUTE__SHIFT 0x11
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL5_CHANNEL_ID_MASK 0xf00000
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL5_CHANNEL_ID__SHIFT 0x14
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL7_ENABLE_MASK 0x1000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL7_ENABLE__SHIFT 0x18
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL7_MUTE_MASK 0x2000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL7_MUTE__SHIFT 0x19
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL7_CHANNEL_ID_MASK 0xf0000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL7_CHANNEL_ID__SHIFT 0x1c
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_MODE__MULTICHANNEL_MODE_MASK 0x1
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_MODE__MULTICHANNEL_MODE__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC__VIDEO_LIPSYNC_MASK 0xff
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC__VIDEO_LIPSYNC__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC__AUDIO_LIPSYNC_MASK 0xff00
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC__AUDIO_LIPSYNC__SHIFT 0x8
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR__HBR_CAPABLE_MASK 0x1
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR__HBR_CAPABLE__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR__HBR_ENABLE_MASK 0x10
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR__HBR_ENABLE__SHIFT 0x4
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0__MANUFACTURER_ID_MASK 0xffff
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0__MANUFACTURER_ID__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0__PRODUCT_ID_MASK 0xffff0000
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0__PRODUCT_ID__SHIFT 0x10
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO1__SINK_DESCRIPTION_LEN_MASK 0xff
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO1__SINK_DESCRIPTION_LEN__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO2__PORT_ID0_MASK 0xffffffff
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO2__PORT_ID0__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO3__PORT_ID1_MASK 0xffffffff
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO3__PORT_ID1__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4__DESCRIPTION0_MASK 0xff
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4__DESCRIPTION0__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4__DESCRIPTION1_MASK 0xff00
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4__DESCRIPTION1__SHIFT 0x8
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4__DESCRIPTION2_MASK 0xff0000
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4__DESCRIPTION2__SHIFT 0x10
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4__DESCRIPTION3_MASK 0xff000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4__DESCRIPTION3__SHIFT 0x18
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5__DESCRIPTION4_MASK 0xff
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5__DESCRIPTION4__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5__DESCRIPTION5_MASK 0xff00
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5__DESCRIPTION5__SHIFT 0x8
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5__DESCRIPTION6_MASK 0xff0000
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5__DESCRIPTION6__SHIFT 0x10
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5__DESCRIPTION7_MASK 0xff000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5__DESCRIPTION7__SHIFT 0x18
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6__DESCRIPTION8_MASK 0xff
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6__DESCRIPTION8__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6__DESCRIPTION9_MASK 0xff00
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6__DESCRIPTION9__SHIFT 0x8
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6__DESCRIPTION10_MASK 0xff0000
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6__DESCRIPTION10__SHIFT 0x10
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6__DESCRIPTION11_MASK 0xff000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6__DESCRIPTION11__SHIFT 0x18
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7__DESCRIPTION12_MASK 0xff
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7__DESCRIPTION12__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7__DESCRIPTION13_MASK 0xff00
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7__DESCRIPTION13__SHIFT 0x8
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7__DESCRIPTION14_MASK 0xff0000
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7__DESCRIPTION14__SHIFT 0x10
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7__DESCRIPTION15_MASK 0xff000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7__DESCRIPTION15__SHIFT 0x18
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8__DESCRIPTION16_MASK 0xff
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8__DESCRIPTION16__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8__DESCRIPTION17_MASK 0xff00
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8__DESCRIPTION17__SHIFT 0x8
+#define AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL__CLOCK_GATING_DISABLE_MASK 0x1
+#define AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL__CLOCK_GATING_DISABLE__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL__CLOCK_ON_STATE_MASK 0x10
+#define AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL__CLOCK_ON_STATE__SHIFT 0x4
+#define AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL__AUDIO_ENABLED_MASK 0x80000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL__AUDIO_ENABLED__SHIFT 0x1f
+#define AZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE__UNSOLICITED_RESPONSE_PAYLOAD_MASK 0x3ffffff
+#define AZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE__UNSOLICITED_RESPONSE_PAYLOAD__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE__UNSOLICITED_RESPONSE_FORCE_MASK 0x10000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE__UNSOLICITED_RESPONSE_FORCE__SHIFT 0x1c
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__SEQUENCE_MASK 0xf
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__SEQUENCE__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__DEFAULT_ASSOCIATION_MASK 0xf0
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__DEFAULT_ASSOCIATION__SHIFT 0x4
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__MISC_MASK 0xf00
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__MISC__SHIFT 0x8
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__COLOR_MASK 0xf000
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__COLOR__SHIFT 0xc
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__CONNECTION_TYPE_MASK 0xf0000
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__CONNECTION_TYPE__SHIFT 0x10
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__DEFAULT_DEVICE_MASK 0xf00000
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__DEFAULT_DEVICE__SHIFT 0x14
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__LOCATION_MASK 0x3f000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__LOCATION__SHIFT 0x18
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__PORT_CONNECTIVITY_MASK 0xc0000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__PORT_CONNECTIVITY__SHIFT 0x1e
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_0__IEC_60958_CS_MODE_MASK 0x3
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_0__IEC_60958_CS_MODE__SHIFT 0x0
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_0__IEC_60958_CS_SOURCE_NUMBER_MASK 0x3c
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_0__IEC_60958_CS_SOURCE_NUMBER__SHIFT 0x2
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_CLOCK_ACCURACY_MASK 0x3
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_CLOCK_ACCURACY__SHIFT 0x0
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_CLOCK_ACCURACY_OVRRD_EN_MASK 0x4
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_CLOCK_ACCURACY_OVRRD_EN__SHIFT 0x2
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_WORD_LENGTH_MASK 0x78
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_WORD_LENGTH__SHIFT 0x3
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_WORD_LENGTH_OVRRD_EN_MASK 0x80
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_WORD_LENGTH_OVRRD_EN__SHIFT 0x7
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_2__IEC_60958_CS_SAMPLING_FREQUENCY_MASK 0x3f
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_2__IEC_60958_CS_SAMPLING_FREQUENCY__SHIFT 0x0
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_2__IEC_60958_CS_SAMPLING_FREQUENCY_OVRRD_EN_MASK 0x40
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_2__IEC_60958_CS_SAMPLING_FREQUENCY_OVRRD_EN__SHIFT 0x6
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_3__IEC_60958_CS_ORIGINAL_SAMPLING_FREQUENCY_MASK 0xf
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_3__IEC_60958_CS_ORIGINAL_SAMPLING_FREQUENCY__SHIFT 0x0
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_3__IEC_60958_CS_ORIGINAL_SAMPLING_FREQUENCY_OVRRD_EN_MASK 0x10
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_3__IEC_60958_CS_ORIGINAL_SAMPLING_FREQUENCY_OVRRD_EN__SHIFT 0x4
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_SAMPLING_FREQUENCY_COEFF_MASK 0xf
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_SAMPLING_FREQUENCY_COEFF__SHIFT 0x0
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_MPEG_SURROUND_INFO_MASK 0x10
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_MPEG_SURROUND_INFO__SHIFT 0x4
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_CGMS_A_MASK 0x60
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_CGMS_A__SHIFT 0x5
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_CGMS_A_VALID_MASK 0x80
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_CGMS_A_VALID__SHIFT 0x7
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_5__IEC_60958_CS_CHANNEL_NUMBER_L_MASK 0xf
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_5__IEC_60958_CS_CHANNEL_NUMBER_L__SHIFT 0x0
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_5__IEC_60958_CS_CHANNEL_NUMBER_R_MASK 0xf0
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_5__IEC_60958_CS_CHANNEL_NUMBER_R__SHIFT 0x4
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_6__IEC_60958_CS_CHANNEL_NUMBER_2_MASK 0xf
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_6__IEC_60958_CS_CHANNEL_NUMBER_2__SHIFT 0x0
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_6__IEC_60958_CS_CHANNEL_NUMBER_3_MASK 0xf0
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_6__IEC_60958_CS_CHANNEL_NUMBER_3__SHIFT 0x4
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_7__IEC_60958_CS_CHANNEL_NUMBER_4_MASK 0xf
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_7__IEC_60958_CS_CHANNEL_NUMBER_4__SHIFT 0x0
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_7__IEC_60958_CS_CHANNEL_NUMBER_5_MASK 0xf0
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_7__IEC_60958_CS_CHANNEL_NUMBER_5__SHIFT 0x4
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_8__IEC_60958_CS_CHANNEL_NUMBER_6_MASK 0xf
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_8__IEC_60958_CS_CHANNEL_NUMBER_6__SHIFT 0x0
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_8__IEC_60958_CS_CHANNEL_NUMBER_7_MASK 0xf0
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_8__IEC_60958_CS_CHANNEL_NUMBER_7__SHIFT 0x4
+#define AZALIA_F0_CODEC_PIN_ASSOCIATION_INFO__ASSOCIATION_INFO_MASK 0xffffffff
+#define AZALIA_F0_CODEC_PIN_ASSOCIATION_INFO__ASSOCIATION_INFO__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_DIGITAL_OUTPUT_STATUS__OUTPUT_ACTIVE_MASK 0x1
+#define AZALIA_F0_CODEC_PIN_CONTROL_DIGITAL_OUTPUT_STATUS__OUTPUT_ACTIVE__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_LPIB_SNAPSHOT_CONTROL__LPIB_SNAPSHOT_LOCK_MASK 0x1
+#define AZALIA_F0_CODEC_PIN_CONTROL_LPIB_SNAPSHOT_CONTROL__LPIB_SNAPSHOT_LOCK__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_LPIB_SNAPSHOT_CONTROL__CYCLIC_BUFFER_WRAP_COUNT_MASK 0xff00
+#define AZALIA_F0_CODEC_PIN_CONTROL_LPIB_SNAPSHOT_CONTROL__CYCLIC_BUFFER_WRAP_COUNT__SHIFT 0x8
+#define AZALIA_F0_CODEC_PIN_CONTROL_LPIB__LPIB_MASK 0xffffffff
+#define AZALIA_F0_CODEC_PIN_CONTROL_LPIB__LPIB__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_LPIB_TIMER_SNAPSHOT__LPIB_TIMER_SNAPSHOT_MASK 0xffffffff
+#define AZALIA_F0_CODEC_PIN_CONTROL_LPIB_TIMER_SNAPSHOT__LPIB_TIMER_SNAPSHOT__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_CODING_TYPE__CODING_TYPE_MASK 0xff
+#define AZALIA_F0_CODEC_PIN_CONTROL_CODING_TYPE__CODING_TYPE__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_FORMAT_CHANGED__FORMAT_CHANGED_MASK 0x1
+#define AZALIA_F0_CODEC_PIN_CONTROL_FORMAT_CHANGED__FORMAT_CHANGED__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_FORMAT_CHANGED__FORMAT_CHANGED_ACK_UR_ENABLE_MASK 0x2
+#define AZALIA_F0_CODEC_PIN_CONTROL_FORMAT_CHANGED__FORMAT_CHANGED_ACK_UR_ENABLE__SHIFT 0x1
+#define AZALIA_F0_CODEC_PIN_CONTROL_FORMAT_CHANGED__FORMAT_CHANGE_REASON_MASK 0xff00
+#define AZALIA_F0_CODEC_PIN_CONTROL_FORMAT_CHANGED__FORMAT_CHANGE_REASON__SHIFT 0x8
+#define AZALIA_F0_CODEC_PIN_CONTROL_FORMAT_CHANGED__FORMAT_CHANGE_RESPONSE_MASK 0xff0000
+#define AZALIA_F0_CODEC_PIN_CONTROL_FORMAT_CHANGED__FORMAT_CHANGE_RESPONSE__SHIFT 0x10
+#define AZALIA_F0_CODEC_PIN_CONTROL_WIRELESS_DISPLAY_IDENTIFICATION__WIRELESS_DISPLAY_IDENTIFICATION_MASK 0x3
+#define AZALIA_F0_CODEC_PIN_CONTROL_WIRELESS_DISPLAY_IDENTIFICATION__WIRELESS_DISPLAY_IDENTIFICATION__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_REMOTE_KEEPALIVE__REMOTE_KEEP_ALIVE_ENABLE_MASK 0x1
+#define AZALIA_F0_CODEC_PIN_CONTROL_REMOTE_KEEPALIVE__REMOTE_KEEP_ALIVE_ENABLE__SHIFT 0x0
+#define AZALIA_F0_CODEC_PIN_CONTROL_REMOTE_KEEPALIVE__REMOTE_KEEP_ALIVE_CAPABILITY_MASK 0x10
+#define AZALIA_F0_CODEC_PIN_CONTROL_REMOTE_KEEPALIVE__REMOTE_KEEP_ALIVE_CAPABILITY__SHIFT 0x4
+#define AZALIA_F0_AUDIO_ENABLE_STATUS__AUDIO_ENABLE_STATUS_MASK 0x1
+#define AZALIA_F0_AUDIO_ENABLE_STATUS__AUDIO_ENABLE_STATUS__SHIFT 0x0
+#define AZALIA_F0_AUDIO_ENABLED_INT_STATUS__AUDIO_ENABLED_FLAG_MASK 0x1
+#define AZALIA_F0_AUDIO_ENABLED_INT_STATUS__AUDIO_ENABLED_FLAG__SHIFT 0x0
+#define AZALIA_F0_AUDIO_ENABLED_INT_STATUS__AUDIO_ENABLED_MASK_MASK 0x10
+#define AZALIA_F0_AUDIO_ENABLED_INT_STATUS__AUDIO_ENABLED_MASK__SHIFT 0x4
+#define AZALIA_F0_AUDIO_ENABLED_INT_STATUS__AUDIO_ENABLED_TYPE_MASK 0x100
+#define AZALIA_F0_AUDIO_ENABLED_INT_STATUS__AUDIO_ENABLED_TYPE__SHIFT 0x8
+#define AZALIA_F0_AUDIO_DISABLED_INT_STATUS__AUDIO_DISABLED_FLAG_MASK 0x1
+#define AZALIA_F0_AUDIO_DISABLED_INT_STATUS__AUDIO_DISABLED_FLAG__SHIFT 0x0
+#define AZALIA_F0_AUDIO_DISABLED_INT_STATUS__AUDIO_DISABLED_MASK_MASK 0x10
+#define AZALIA_F0_AUDIO_DISABLED_INT_STATUS__AUDIO_DISABLED_MASK__SHIFT 0x4
+#define AZALIA_F0_AUDIO_DISABLED_INT_STATUS__AUDIO_DISABLED_TYPE_MASK 0x100
+#define AZALIA_F0_AUDIO_DISABLED_INT_STATUS__AUDIO_DISABLED_TYPE__SHIFT 0x8
+#define AZALIA_F0_AUDIO_FORMAT_CHANGED_INT_STATUS__AUDIO_FORMAT_CHANGED_FLAG_MASK 0x1
+#define AZALIA_F0_AUDIO_FORMAT_CHANGED_INT_STATUS__AUDIO_FORMAT_CHANGED_FLAG__SHIFT 0x0
+#define AZALIA_F0_AUDIO_FORMAT_CHANGED_INT_STATUS__AUDIO_FORMAT_CHANGED_MASK_MASK 0x10
+#define AZALIA_F0_AUDIO_FORMAT_CHANGED_INT_STATUS__AUDIO_FORMAT_CHANGED_MASK__SHIFT 0x4
+#define AZALIA_F0_AUDIO_FORMAT_CHANGED_INT_STATUS__AUDIO_FORMAT_CHANGED_TYPE_MASK 0x100
+#define AZALIA_F0_AUDIO_FORMAT_CHANGED_INT_STATUS__AUDIO_FORMAT_CHANGED_TYPE__SHIFT 0x8
+#define AZALIA_F0_CODEC_INPUT_ENDPOINT_INDEX__AZALIA_INPUT_ENDPOINT_REG_INDEX_MASK 0x3fff
+#define AZALIA_F0_CODEC_INPUT_ENDPOINT_INDEX__AZALIA_INPUT_ENDPOINT_REG_INDEX__SHIFT 0x0
+#define AZALIA_F0_CODEC_INPUT_ENDPOINT_DATA__AZALIA_INPUT_ENDPOINT_REG_DATA_MASK 0xffffffff
+#define AZALIA_F0_CODEC_INPUT_ENDPOINT_DATA__AZALIA_INPUT_ENDPOINT_REG_DATA__SHIFT 0x0
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_PIN_DEBUG__AZALIA_INPUT_DEBUG_MASK 0xffffffff
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_PIN_DEBUG__AZALIA_INPUT_DEBUG__SHIFT 0x0
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_CHANNEL_CAPABILITIES_MASK 0x1
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_CHANNEL_CAPABILITIES__SHIFT 0x0
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__INPUT_AMPLIFIER_PRESENT_MASK 0x2
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__INPUT_AMPLIFIER_PRESENT__SHIFT 0x1
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__OUTPUT_AMPLIFIER_PRESENT_MASK 0x4
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__OUTPUT_AMPLIFIER_PRESENT__SHIFT 0x2
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AMPLIFIER_PARAMETER_OVERRIDE_MASK 0x8
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AMPLIFIER_PARAMETER_OVERRIDE__SHIFT 0x3
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__FORMAT_OVERRIDE_MASK 0x10
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__FORMAT_OVERRIDE__SHIFT 0x4
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__STRIPE_MASK 0x20
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__STRIPE__SHIFT 0x5
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__PROCESSING_WIDGET_MASK 0x40
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__PROCESSING_WIDGET__SHIFT 0x6
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__UNSOLICITED_RESPONSE_CAPABILITY_MASK 0x80
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__UNSOLICITED_RESPONSE_CAPABILITY__SHIFT 0x7
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__CONNECTION_LIST_MASK 0x100
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__CONNECTION_LIST__SHIFT 0x8
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__DIGITAL_MASK 0x200
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__DIGITAL__SHIFT 0x9
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__POWER_CONTROL_MASK 0x400
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__POWER_CONTROL__SHIFT 0xa
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__LR_SWAP_MASK 0x800
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__LR_SWAP__SHIFT 0xb
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_WIDGET_CAPABILITIES_DELAY_MASK 0xf0000
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_WIDGET_CAPABILITIES_DELAY__SHIFT 0x10
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__TYPE_MASK 0xf00000
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__TYPE__SHIFT 0x14
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT__NUMBER_OF_CHANNELS_MASK 0xf
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT__NUMBER_OF_CHANNELS__SHIFT 0x0
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT__BITS_PER_SAMPLE_MASK 0x70
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT__BITS_PER_SAMPLE__SHIFT 0x4
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_DIVISOR_MASK 0x700
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_DIVISOR__SHIFT 0x8
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_MULTIPLE_MASK 0x3800
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_MULTIPLE__SHIFT 0xb
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_RATE_MASK 0x4000
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_RATE__SHIFT 0xe
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT__STREAM_TYPE_MASK 0x8000
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT__STREAM_TYPE__SHIFT 0xf
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_CHANNEL_STREAM_ID__CHANNEL_ID_MASK 0xf
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_CHANNEL_STREAM_ID__CHANNEL_ID__SHIFT 0x0
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_CHANNEL_STREAM_ID__STREAM_ID_MASK 0xf0
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_CHANNEL_STREAM_ID__STREAM_ID__SHIFT 0x4
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__DIGEN_MASK 0x1
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__DIGEN__SHIFT 0x0
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__V_MASK 0x2
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__V__SHIFT 0x1
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__VCFG_MASK 0x4
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__VCFG__SHIFT 0x2
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__PRE_MASK 0x8
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__PRE__SHIFT 0x3
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__COPY_MASK 0x10
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__COPY__SHIFT 0x4
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__NON_AUDIO_MASK 0x20
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__NON_AUDIO__SHIFT 0x5
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__PRO_MASK 0x40
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__PRO__SHIFT 0x6
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__L_MASK 0x80
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__L__SHIFT 0x7
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__CC_MASK 0x7f00
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__CC__SHIFT 0x8
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__KEEPALIVE_MASK 0x800000
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__KEEPALIVE__SHIFT 0x17
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_STREAM_FORMATS__STREAM_FORMATS_MASK 0xffffffff
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_STREAM_FORMATS__STREAM_FORMATS__SHIFT 0x0
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_RATE_CAPABILITIES_MASK 0xfff
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_RATE_CAPABILITIES__SHIFT 0x0
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_BIT_CAPABILITIES_MASK 0x1f0000
+#define AZALIA_F0_CODEC_INPUT_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_BIT_CAPABILITIES__SHIFT 0x10
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_CHANNEL_CAPABILITIES_MASK 0x1
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_CHANNEL_CAPABILITIES__SHIFT 0x0
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__INPUT_AMPLIFIER_PRESENT_MASK 0x2
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__INPUT_AMPLIFIER_PRESENT__SHIFT 0x1
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__OUTPUT_AMPLIFIER_PRESENT_MASK 0x4
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__OUTPUT_AMPLIFIER_PRESENT__SHIFT 0x2
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AMPLIFIER_PARAMETER_OVERRIDE_MASK 0x8
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AMPLIFIER_PARAMETER_OVERRIDE__SHIFT 0x3
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__STRIPE_MASK 0x20
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__STRIPE__SHIFT 0x5
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__PROCESSING_WIDGET_MASK 0x40
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__PROCESSING_WIDGET__SHIFT 0x6
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__UNSOLICITED_RESPONSE_CAPABILITY_MASK 0x80
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__UNSOLICITED_RESPONSE_CAPABILITY__SHIFT 0x7
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__CONNECTION_LIST_MASK 0x100
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__CONNECTION_LIST__SHIFT 0x8
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__DIGITAL_MASK 0x200
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__DIGITAL__SHIFT 0x9
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__POWER_CONTROL_MASK 0x400
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__POWER_CONTROL__SHIFT 0xa
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__LR_SWAP_MASK 0x800
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__LR_SWAP__SHIFT 0xb
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_WIDGET_CAPABILITIES_DELAY_MASK 0xf0000
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_WIDGET_CAPABILITIES_DELAY__SHIFT 0x10
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__TYPE_MASK 0xf00000
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__TYPE__SHIFT 0x14
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__IMPEDANCE_SENSE_CAPABLE_MASK 0x1
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__IMPEDANCE_SENSE_CAPABLE__SHIFT 0x0
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__TRIGGER_REQUIRED_MASK 0x2
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__TRIGGER_REQUIRED__SHIFT 0x1
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__JACK_DETECTION_CAPABILITY_MASK 0x4
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__JACK_DETECTION_CAPABILITY__SHIFT 0x2
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__HEADPHONE_DRIVE_CAPABLE_MASK 0x8
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__HEADPHONE_DRIVE_CAPABLE__SHIFT 0x3
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__OUTPUT_CAPABLE_MASK 0x10
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__OUTPUT_CAPABLE__SHIFT 0x4
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__INPUT_CAPABLE_MASK 0x20
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__INPUT_CAPABLE__SHIFT 0x5
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__BALANCED_I_O_PINS_MASK 0x40
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__BALANCED_I_O_PINS__SHIFT 0x6
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__HDMI_MASK 0x80
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__HDMI__SHIFT 0x7
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__VREF_CONTROL_MASK 0xff00
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__VREF_CONTROL__SHIFT 0x8
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__EAPD_CAPABLE_MASK 0x10000
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__EAPD_CAPABLE__SHIFT 0x10
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__DP_MASK 0x1000000
+#define AZALIA_F0_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__DP__SHIFT 0x18
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_UNSOLICITED_RESPONSE__TAG_MASK 0x3f
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_UNSOLICITED_RESPONSE__TAG__SHIFT 0x0
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_UNSOLICITED_RESPONSE__ENABLE_MASK 0x80
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_UNSOLICITED_RESPONSE__ENABLE__SHIFT 0x7
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_RESPONSE_INPUT_PIN_SENSE__IMPEDANCE_SENSE_MASK 0x7fffffff
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_RESPONSE_INPUT_PIN_SENSE__IMPEDANCE_SENSE__SHIFT 0x0
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_RESPONSE_INPUT_PIN_SENSE__PRESENCE_DETECT_MASK 0x80000000
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_RESPONSE_INPUT_PIN_SENSE__PRESENCE_DETECT__SHIFT 0x1f
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_WIDGET_CONTROL__IN_ENABLE_MASK 0x20
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_WIDGET_CONTROL__IN_ENABLE__SHIFT 0x5
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL0_ENABLE_MASK 0x1
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL0_ENABLE__SHIFT 0x0
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL0_MUTE_MASK 0x2
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL0_MUTE__SHIFT 0x1
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL0_CHANNEL_ID_MASK 0xf0
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL0_CHANNEL_ID__SHIFT 0x4
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL1_ENABLE_MASK 0x100
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL1_ENABLE__SHIFT 0x8
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL1_MUTE_MASK 0x200
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL1_MUTE__SHIFT 0x9
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL1_CHANNEL_ID_MASK 0xf000
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL1_CHANNEL_ID__SHIFT 0xc
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL2_ENABLE_MASK 0x10000
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL2_ENABLE__SHIFT 0x10
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL2_MUTE_MASK 0x20000
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL2_MUTE__SHIFT 0x11
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL2_CHANNEL_ID_MASK 0xf00000
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL2_CHANNEL_ID__SHIFT 0x14
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL3_ENABLE_MASK 0x1000000
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL3_ENABLE__SHIFT 0x18
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL3_MUTE_MASK 0x2000000
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL3_MUTE__SHIFT 0x19
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL3_CHANNEL_ID_MASK 0xf0000000
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL3_CHANNEL_ID__SHIFT 0x1c
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL4_ENABLE_MASK 0x1
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL4_ENABLE__SHIFT 0x0
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL4_MUTE_MASK 0x2
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL4_MUTE__SHIFT 0x1
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL4_CHANNEL_ID_MASK 0xf0
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL4_CHANNEL_ID__SHIFT 0x4
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL5_ENABLE_MASK 0x100
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL5_ENABLE__SHIFT 0x8
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL5_MUTE_MASK 0x200
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL5_MUTE__SHIFT 0x9
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL5_CHANNEL_ID_MASK 0xf000
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL5_CHANNEL_ID__SHIFT 0xc
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL6_ENABLE_MASK 0x10000
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL6_ENABLE__SHIFT 0x10
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL6_MUTE_MASK 0x20000
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL6_MUTE__SHIFT 0x11
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL6_CHANNEL_ID_MASK 0xf00000
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL6_CHANNEL_ID__SHIFT 0x14
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL7_ENABLE_MASK 0x1000000
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL7_ENABLE__SHIFT 0x18
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL7_MUTE_MASK 0x2000000
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL7_MUTE__SHIFT 0x19
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL7_CHANNEL_ID_MASK 0xf0000000
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL7_CHANNEL_ID__SHIFT 0x1c
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_RESPONSE_HBR__HBR_CAPABLE_MASK 0x1
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_RESPONSE_HBR__HBR_CAPABLE__SHIFT 0x0
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_RESPONSE_HBR__HBR_ENABLE_MASK 0x10
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_RESPONSE_HBR__HBR_ENABLE__SHIFT 0x4
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_CHANNEL_ALLOCATION__CHANNEL_ALLOCATION_MASK 0xff
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_CHANNEL_ALLOCATION__CHANNEL_ALLOCATION__SHIFT 0x0
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_HOT_PLUG_CONTROL__CLOCK_GATING_DISABLE_MASK 0x1
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_HOT_PLUG_CONTROL__CLOCK_GATING_DISABLE__SHIFT 0x0
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_HOT_PLUG_CONTROL__CLOCK_ON_STATE_MASK 0x10
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_HOT_PLUG_CONTROL__CLOCK_ON_STATE__SHIFT 0x4
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_HOT_PLUG_CONTROL__AUDIO_ENABLED_MASK 0x80000000
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_HOT_PLUG_CONTROL__AUDIO_ENABLED__SHIFT 0x1f
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE__UNSOLICITED_RESPONSE_PAYLOAD_MASK 0x3ffffff
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE__UNSOLICITED_RESPONSE_PAYLOAD__SHIFT 0x0
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE__UNSOLICITED_RESPONSE_FORCE_MASK 0x10000000
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE__UNSOLICITED_RESPONSE_FORCE__SHIFT 0x1c
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__SEQUENCE_MASK 0xf
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__SEQUENCE__SHIFT 0x0
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__DEFAULT_ASSOCIATION_MASK 0xf0
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__DEFAULT_ASSOCIATION__SHIFT 0x4
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__MISC_MASK 0xf00
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__MISC__SHIFT 0x8
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__COLOR_MASK 0xf000
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__COLOR__SHIFT 0xc
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__CONNECTION_TYPE_MASK 0xf0000
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__CONNECTION_TYPE__SHIFT 0x10
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__DEFAULT_DEVICE_MASK 0xf00000
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__DEFAULT_DEVICE__SHIFT 0x14
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__LOCATION_MASK 0x3f000000
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__LOCATION__SHIFT 0x18
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__PORT_CONNECTIVITY_MASK 0xc0000000
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__PORT_CONNECTIVITY__SHIFT 0x1e
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_INPUT_STATUS_CONTROL__INPUT_ACTIVITY_MASK 0x1
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_INPUT_STATUS_CONTROL__INPUT_ACTIVITY__SHIFT 0x0
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_INPUT_STATUS_CONTROL__CHANNEL_LAYOUT_MASK 0x6
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_INPUT_STATUS_CONTROL__CHANNEL_LAYOUT__SHIFT 0x1
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_INPUT_STATUS_CONTROL__INPUT_ACTIVITY_UR_ENABLE_MASK 0x10
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_INPUT_STATUS_CONTROL__INPUT_ACTIVITY_UR_ENABLE__SHIFT 0x4
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_INPUT_STATUS_CONTROL__INPUT_CL_CS_INFOFRAME_CHANGE_UR_ENABLE_MASK 0x20
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_INPUT_STATUS_CONTROL__INPUT_CL_CS_INFOFRAME_CHANGE_UR_ENABLE__SHIFT 0x5
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_INFOFRAME__CHANNEL_COUNT_MASK 0x7
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_INFOFRAME__CHANNEL_COUNT__SHIFT 0x0
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_INFOFRAME__CHANNEL_ALLOCATION_MASK 0xff00
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_INFOFRAME__CHANNEL_ALLOCATION__SHIFT 0x8
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_INFOFRAME__INFOFRAME_BYTE_5_MASK 0xff0000
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_INFOFRAME__INFOFRAME_BYTE_5__SHIFT 0x10
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_INFOFRAME__INFOFRAME_VALID_MASK 0x80000000
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_INFOFRAME__INFOFRAME_VALID__SHIFT 0x1f
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_LPIB_SNAPSHOT_CONTROL__LPIB_SNAPSHOT_LOCK_MASK 0x1
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_LPIB_SNAPSHOT_CONTROL__LPIB_SNAPSHOT_LOCK__SHIFT 0x0
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_LPIB_SNAPSHOT_CONTROL__CYCLIC_BUFFER_WRAP_COUNT_MASK 0xff00
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_LPIB_SNAPSHOT_CONTROL__CYCLIC_BUFFER_WRAP_COUNT__SHIFT 0x8
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_LPIB__LPIB_MASK 0xffffffff
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_LPIB__LPIB__SHIFT 0x0
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_LPIB_TIMER_SNAPSHOT__LPIB_TIMER_SNAPSHOT_MASK 0xffffffff
+#define AZALIA_F0_CODEC_INPUT_PIN_CONTROL_LPIB_TIMER_SNAPSHOT__LPIB_TIMER_SNAPSHOT__SHIFT 0x0
+#define AZENDPOINT_IMMEDIATE_COMMAND_INPUT_INTERFACE_INDEX__IMMEDIATE_COMMAND_WRITE_MASK 0x1ffff
+#define AZENDPOINT_IMMEDIATE_COMMAND_INPUT_INTERFACE_INDEX__IMMEDIATE_COMMAND_WRITE__SHIFT 0x0
+#define AZENDPOINT_IMMEDIATE_COMMAND_INPUT_INTERFACE_DATA__IMMEDIATE_COMMAND_WRITE_MASK 0xffffffff
+#define AZENDPOINT_IMMEDIATE_COMMAND_INPUT_INTERFACE_DATA__IMMEDIATE_COMMAND_WRITE__SHIFT 0x0
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_CHANNEL_CAPABILITIES_MASK 0x1
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_CHANNEL_CAPABILITIES__SHIFT 0x0
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__INPUT_AMPLIFIER_PRESENT_MASK 0x2
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__INPUT_AMPLIFIER_PRESENT__SHIFT 0x1
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__OUTPUT_AMPLIFIER_PRESENT_MASK 0x4
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__OUTPUT_AMPLIFIER_PRESENT__SHIFT 0x2
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AMPLIFIER_PARAMETER_OVERRIDE_MASK 0x8
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AMPLIFIER_PARAMETER_OVERRIDE__SHIFT 0x3
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__FORMAT_OVERRIDE_MASK 0x10
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__FORMAT_OVERRIDE__SHIFT 0x4
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__STRIPE_MASK 0x20
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__STRIPE__SHIFT 0x5
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__PROCESSING_WIDGET_MASK 0x40
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__PROCESSING_WIDGET__SHIFT 0x6
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__UNSOLICITED_RESPONSE_CAPABILITY_MASK 0x80
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__UNSOLICITED_RESPONSE_CAPABILITY__SHIFT 0x7
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__CONNECTION_LIST_MASK 0x100
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__CONNECTION_LIST__SHIFT 0x8
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__DIGITAL_MASK 0x200
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__DIGITAL__SHIFT 0x9
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__POWER_CONTROL_MASK 0x400
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__POWER_CONTROL__SHIFT 0xa
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__LR_SWAP_MASK 0x800
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__LR_SWAP__SHIFT 0xb
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_WIDGET_CAPABILITIES_DELAY_MASK 0xf0000
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_WIDGET_CAPABILITIES_DELAY__SHIFT 0x10
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__TYPE_MASK 0xf00000
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__TYPE__SHIFT 0x14
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_RATE_CAPABILITIES_MASK 0xfff
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_RATE_CAPABILITIES__SHIFT 0x0
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_BIT_CAPABILITIES_MASK 0x1f0000
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_BIT_CAPABILITIES__SHIFT 0x10
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_PARAMETER_STREAM_FORMATS__STREAM_FORMATS_MASK 0xffffffff
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_PARAMETER_STREAM_FORMATS__STREAM_FORMATS__SHIFT 0x0
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT__NUMBER_OF_CHANNELS_MASK 0xf
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT__NUMBER_OF_CHANNELS__SHIFT 0x0
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT__BITS_PER_SAMPLE_MASK 0x70
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT__BITS_PER_SAMPLE__SHIFT 0x4
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_DIVISOR_MASK 0x700
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_DIVISOR__SHIFT 0x8
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_MULTIPLE_MASK 0x3800
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_MULTIPLE__SHIFT 0xb
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_RATE_MASK 0x4000
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_RATE__SHIFT 0xe
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT__STREAM_TYPE_MASK 0x8000
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CONVERTER_FORMAT__STREAM_TYPE__SHIFT 0xf
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CHANNEL_STREAM_ID__CHANNEL_ID_MASK 0xf
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CHANNEL_STREAM_ID__CHANNEL_ID__SHIFT 0x0
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CHANNEL_STREAM_ID__STREAM_ID_MASK 0xf0
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_CHANNEL_STREAM_ID__STREAM_ID__SHIFT 0x4
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__DIGEN_MASK 0x1
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__DIGEN__SHIFT 0x0
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__V_MASK 0x2
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__V__SHIFT 0x1
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__VCFG_MASK 0x4
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__VCFG__SHIFT 0x2
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__PRE_MASK 0x8
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__PRE__SHIFT 0x3
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__COPY_MASK 0x10
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__COPY__SHIFT 0x4
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__NON_AUDIO_MASK 0x20
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__NON_AUDIO__SHIFT 0x5
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__PRO_MASK 0x40
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__PRO__SHIFT 0x6
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__L_MASK 0x80
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__L__SHIFT 0x7
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__CC_MASK 0x7f00
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__CC__SHIFT 0x8
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__KEEPALIVE_MASK 0x800000
+#define AZALIA_F2_CODEC_INPUT_CONVERTER_CONTROL_DIGITAL_CONVERTER__KEEPALIVE__SHIFT 0x17
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_CHANNEL_CAPABILITIES_MASK 0x1
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_CHANNEL_CAPABILITIES__SHIFT 0x0
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__INPUT_AMPLIFIER_PRESENT_MASK 0x2
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__INPUT_AMPLIFIER_PRESENT__SHIFT 0x1
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__OUTPUT_AMPLIFIER_PRESENT_MASK 0x4
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__OUTPUT_AMPLIFIER_PRESENT__SHIFT 0x2
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AMPLIFIER_PARAMETER_OVERRIDE_MASK 0x8
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AMPLIFIER_PARAMETER_OVERRIDE__SHIFT 0x3
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__STRIPE_MASK 0x20
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__STRIPE__SHIFT 0x5
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__PROCESSING_WIDGET_MASK 0x40
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__PROCESSING_WIDGET__SHIFT 0x6
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__UNSOLICITED_RESPONSE_CAPABILITY_MASK 0x80
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__UNSOLICITED_RESPONSE_CAPABILITY__SHIFT 0x7
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__CONNECTION_LIST_MASK 0x100
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__CONNECTION_LIST__SHIFT 0x8
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__DIGITAL_MASK 0x200
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__DIGITAL__SHIFT 0x9
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__POWER_CONTROL_MASK 0x400
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__POWER_CONTROL__SHIFT 0xa
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__LR_SWAP_MASK 0x800
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__LR_SWAP__SHIFT 0xb
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_WIDGET_CAPABILITIES_DELAY_MASK 0xf0000
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_WIDGET_CAPABILITIES_DELAY__SHIFT 0x10
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__TYPE_MASK 0xf00000
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__TYPE__SHIFT 0x14
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__IMPEDANCE_SENSE_CAPABLE_MASK 0x1
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__IMPEDANCE_SENSE_CAPABLE__SHIFT 0x0
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__TRIGGER_REQUIRED_MASK 0x2
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__TRIGGER_REQUIRED__SHIFT 0x1
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__JACK_DETECTION_CAPABILITY_MASK 0x4
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__JACK_DETECTION_CAPABILITY__SHIFT 0x2
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__HEADPHONE_DRIVE_CAPABLE_MASK 0x8
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__HEADPHONE_DRIVE_CAPABLE__SHIFT 0x3
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__OUTPUT_CAPABLE_MASK 0x10
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__OUTPUT_CAPABLE__SHIFT 0x4
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__INPUT_CAPABLE_MASK 0x20
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__INPUT_CAPABLE__SHIFT 0x5
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__BALANCED_I_O_PINS_MASK 0x40
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__BALANCED_I_O_PINS__SHIFT 0x6
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__HDMI_MASK 0x80
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__HDMI__SHIFT 0x7
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__VREF_CONTROL_MASK 0xff00
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__VREF_CONTROL__SHIFT 0x8
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__EAPD_CAPABLE_MASK 0x10000
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__EAPD_CAPABLE__SHIFT 0x10
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__DP_MASK 0x1000000
+#define AZALIA_F2_CODEC_INPUT_PIN_PARAMETER_CAPABILITIES__DP__SHIFT 0x18
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_WIDGET_CONTROL__IN_ENABLE_MASK 0x20
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_WIDGET_CONTROL__IN_ENABLE__SHIFT 0x5
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_UNSOLICITED_RESPONSE__TAG_MASK 0x3f
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_UNSOLICITED_RESPONSE__TAG__SHIFT 0x0
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_UNSOLICITED_RESPONSE__ENABLE_MASK 0x80
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_UNSOLICITED_RESPONSE__ENABLE__SHIFT 0x7
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_RESPONSE_PIN_SENSE__IMPEDANCE_SENSE_MASK 0x7fffffff
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_RESPONSE_PIN_SENSE__IMPEDANCE_SENSE__SHIFT 0x0
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_RESPONSE_PIN_SENSE__PRESENCE_DETECT_MASK 0x80000000
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_RESPONSE_PIN_SENSE__PRESENCE_DETECT__SHIFT 0x1f
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__SEQUENCE_MASK 0xf
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__SEQUENCE__SHIFT 0x0
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__DEFAULT_ASSOCIATION_MASK 0xf0
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__DEFAULT_ASSOCIATION__SHIFT 0x4
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__MISC_MASK 0xf00
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__MISC__SHIFT 0x8
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__COLOR_MASK 0xf000
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__COLOR__SHIFT 0xc
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__CONNECTION_TYPE_MASK 0xf0000
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__CONNECTION_TYPE__SHIFT 0x10
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__DEFAULT_DEVICE_MASK 0xf00000
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__DEFAULT_DEVICE__SHIFT 0x14
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__LOCATION_MASK 0x3f000000
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__LOCATION__SHIFT 0x18
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__PORT_CONNECTIVITY_MASK 0xc0000000
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__PORT_CONNECTIVITY__SHIFT 0x1e
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_2__MISC_MASK 0xf
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_2__MISC__SHIFT 0x0
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_2__COLOR_MASK 0xf0
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_2__COLOR__SHIFT 0x4
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_3__CONNECTION_TYPE_MASK 0xf
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_3__CONNECTION_TYPE__SHIFT 0x0
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_3__DEFAULT_DEVICE_MASK 0xf0
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_3__DEFAULT_DEVICE__SHIFT 0x4
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_4__LOCATION_MASK 0x3f
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_4__LOCATION__SHIFT 0x0
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_4__PORT_CONNECTIVITY_MASK 0xc0
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_4__PORT_CONNECTIVITY__SHIFT 0x6
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL0_ENABLE__MULTICHANNEL0_ENABLE_MASK 0x1
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL0_ENABLE__MULTICHANNEL0_ENABLE__SHIFT 0x0
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL0_ENABLE__MULTICHANNEL0_MUTE_MASK 0x2
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL0_ENABLE__MULTICHANNEL0_MUTE__SHIFT 0x1
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL0_ENABLE__MULTICHANNEL0_CHANNEL_ID_MASK 0xf0
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL0_ENABLE__MULTICHANNEL0_CHANNEL_ID__SHIFT 0x4
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL1_ENABLE__MULTICHANNEL1_ENABLE_MASK 0x1
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL1_ENABLE__MULTICHANNEL1_ENABLE__SHIFT 0x0
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL1_ENABLE__MULTICHANNEL1_MUTE_MASK 0x2
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL1_ENABLE__MULTICHANNEL1_MUTE__SHIFT 0x1
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL1_ENABLE__MULTICHANNEL1_CHANNEL_ID_MASK 0xf0
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL1_ENABLE__MULTICHANNEL1_CHANNEL_ID__SHIFT 0x4
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL2_ENABLE__MULTICHANNEL2_ENABLE_MASK 0x1
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL2_ENABLE__MULTICHANNEL2_ENABLE__SHIFT 0x0
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL2_ENABLE__MULTICHANNEL2_MUTE_MASK 0x2
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL2_ENABLE__MULTICHANNEL2_MUTE__SHIFT 0x1
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL2_ENABLE__MULTICHANNEL2_CHANNEL_ID_MASK 0xf0
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL2_ENABLE__MULTICHANNEL2_CHANNEL_ID__SHIFT 0x4
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL3_ENABLE__MULTICHANNEL3_ENABLE_MASK 0x1
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL3_ENABLE__MULTICHANNEL3_ENABLE__SHIFT 0x0
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL3_ENABLE__MULTICHANNEL3_MUTE_MASK 0x2
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL3_ENABLE__MULTICHANNEL3_MUTE__SHIFT 0x1
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL3_ENABLE__MULTICHANNEL3_CHANNEL_ID_MASK 0xf0
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL3_ENABLE__MULTICHANNEL3_CHANNEL_ID__SHIFT 0x4
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_HBR__HBR_CAPABLE_MASK 0x1
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_HBR__HBR_CAPABLE__SHIFT 0x0
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_HBR__HBR_ENABLE_MASK 0x10
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_HBR__HBR_ENABLE__SHIFT 0x4
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL4_ENABLE__MULTICHANNEL4_ENABLE_MASK 0x1
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL4_ENABLE__MULTICHANNEL4_ENABLE__SHIFT 0x0
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL4_ENABLE__MULTICHANNEL4_MUTE_MASK 0x2
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL4_ENABLE__MULTICHANNEL4_MUTE__SHIFT 0x1
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL4_ENABLE__MULTICHANNEL4_CHANNEL_ID_MASK 0xf0
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL4_ENABLE__MULTICHANNEL4_CHANNEL_ID__SHIFT 0x4
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL5_ENABLE__MULTICHANNEL5_ENABLE_MASK 0x1
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL5_ENABLE__MULTICHANNEL5_ENABLE__SHIFT 0x0
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL5_ENABLE__MULTICHANNEL5_MUTE_MASK 0x2
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL5_ENABLE__MULTICHANNEL5_MUTE__SHIFT 0x1
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL5_ENABLE__MULTICHANNEL5_CHANNEL_ID_MASK 0xf0
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL5_ENABLE__MULTICHANNEL5_CHANNEL_ID__SHIFT 0x4
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL6_ENABLE__MULTICHANNEL6_ENABLE_MASK 0x1
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL6_ENABLE__MULTICHANNEL6_ENABLE__SHIFT 0x0
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL6_ENABLE__MULTICHANNEL6_MUTE_MASK 0x2
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL6_ENABLE__MULTICHANNEL6_MUTE__SHIFT 0x1
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL6_ENABLE__MULTICHANNEL6_CHANNEL_ID_MASK 0xf0
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL6_ENABLE__MULTICHANNEL6_CHANNEL_ID__SHIFT 0x4
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL7_ENABLE__MULTICHANNEL7_ENABLE_MASK 0x1
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL7_ENABLE__MULTICHANNEL7_ENABLE__SHIFT 0x0
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL7_ENABLE__MULTICHANNEL7_MUTE_MASK 0x2
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL7_ENABLE__MULTICHANNEL7_MUTE__SHIFT 0x1
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL7_ENABLE__MULTICHANNEL7_CHANNEL_ID_MASK 0xf0
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_MULTICHANNEL7_ENABLE__MULTICHANNEL7_CHANNEL_ID__SHIFT 0x4
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_CHANNEL_ALLOCATION__CHANNEL_ALLOCATION_MASK 0xff
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_CHANNEL_ALLOCATION__CHANNEL_ALLOCATION__SHIFT 0x0
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_INPUT_STATUS_CONTROL__INPUT_ACTIVITY_MASK 0x1
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_INPUT_STATUS_CONTROL__INPUT_ACTIVITY__SHIFT 0x0
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_INPUT_STATUS_CONTROL__CHANNEL_LAYOUT_MASK 0x6
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_INPUT_STATUS_CONTROL__CHANNEL_LAYOUT__SHIFT 0x1
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_INPUT_STATUS_CONTROL__INPUT_ACTIVITY_UR_ENABLE_MASK 0x10
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_INPUT_STATUS_CONTROL__INPUT_ACTIVITY_UR_ENABLE__SHIFT 0x4
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_INPUT_STATUS_CONTROL__INPUT_CL_CS_INFOFRAME_CHANGE_UR_ENABLE_MASK 0x20
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_INPUT_STATUS_CONTROL__INPUT_CL_CS_INFOFRAME_CHANGE_UR_ENABLE__SHIFT 0x5
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_INFOFRAME__CHANNEL_COUNT_MASK 0x7
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_INFOFRAME__CHANNEL_COUNT__SHIFT 0x0
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_INFOFRAME__CHANNEL_ALLOCATION_MASK 0xff00
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_INFOFRAME__CHANNEL_ALLOCATION__SHIFT 0x8
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_INFOFRAME__INFOFRAME_BYTE_5_MASK 0xff0000
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_INFOFRAME__INFOFRAME_BYTE_5__SHIFT 0x10
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_INFOFRAME__INFOFRAME_VALID_MASK 0x80000000
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_INFOFRAME__INFOFRAME_VALID__SHIFT 0x1f
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_CHANNEL_STATUS_L__CHANNEL_STATUS_L_MASK 0xffffffff
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_CHANNEL_STATUS_L__CHANNEL_STATUS_L__SHIFT 0x0
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_CHANNEL_STATUS_H__CHANNEL_STATUS_H_MASK 0xffffffff
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_CHANNEL_STATUS_H__CHANNEL_STATUS_H__SHIFT 0x0
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_LPIB_SNAPSHOT_CONTROL__LPIB_SNAPSHOT_LOCK_MASK 0x1
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_LPIB_SNAPSHOT_CONTROL__LPIB_SNAPSHOT_LOCK__SHIFT 0x0
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_LPIB_SNAPSHOT_CONTROL__CYCLIC_BUFFER_WRAP_COUNT_MASK 0xff00
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_LPIB_SNAPSHOT_CONTROL__CYCLIC_BUFFER_WRAP_COUNT__SHIFT 0x8
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_LPIB__LPIB_MASK 0xffffffff
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_LPIB__LPIB__SHIFT 0x0
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_LPIB_TIMER_SNAPSHOT__LPIB_TIMER_SNAPSHOT_MASK 0xffffffff
+#define AZALIA_F2_CODEC_INPUT_PIN_CONTROL_LPIB_TIMER_SNAPSHOT__LPIB_TIMER_SNAPSHOT__SHIFT 0x0
+#define BLND_CONTROL__BLND_GLOBAL_GAIN_MASK 0xff
+#define BLND_CONTROL__BLND_GLOBAL_GAIN__SHIFT 0x0
+#define BLND_CONTROL__BLND_MODE_MASK 0x300
+#define BLND_CONTROL__BLND_MODE__SHIFT 0x8
+#define BLND_CONTROL__BLND_STEREO_TYPE_MASK 0xc00
+#define BLND_CONTROL__BLND_STEREO_TYPE__SHIFT 0xa
+#define BLND_CONTROL__BLND_STEREO_POLARITY_MASK 0x1000
+#define BLND_CONTROL__BLND_STEREO_POLARITY__SHIFT 0xc
+#define BLND_CONTROL__BLND_FEEDTHROUGH_EN_MASK 0x2000
+#define BLND_CONTROL__BLND_FEEDTHROUGH_EN__SHIFT 0xd
+#define BLND_CONTROL__BLND_ALPHA_MODE_MASK 0x30000
+#define BLND_CONTROL__BLND_ALPHA_MODE__SHIFT 0x10
+#define BLND_CONTROL__BLND_ACTIVE_OVERLAP_ONLY_MASK 0x40000
+#define BLND_CONTROL__BLND_ACTIVE_OVERLAP_ONLY__SHIFT 0x12
+#define BLND_CONTROL__BLND_MULTIPLIED_MODE_MASK 0x100000
+#define BLND_CONTROL__BLND_MULTIPLIED_MODE__SHIFT 0x14
+#define BLND_CONTROL__BLND_GLOBAL_ALPHA_MASK 0xff000000
+#define BLND_CONTROL__BLND_GLOBAL_ALPHA__SHIFT 0x18
+#define BLND_SM_CONTROL2__SM_MODE_MASK 0x7
+#define BLND_SM_CONTROL2__SM_MODE__SHIFT 0x0
+#define BLND_SM_CONTROL2__SM_FRAME_ALTERNATE_MASK 0x10
+#define BLND_SM_CONTROL2__SM_FRAME_ALTERNATE__SHIFT 0x4
+#define BLND_SM_CONTROL2__SM_FIELD_ALTERNATE_MASK 0x20
+#define BLND_SM_CONTROL2__SM_FIELD_ALTERNATE__SHIFT 0x5
+#define BLND_SM_CONTROL2__SM_FORCE_NEXT_FRAME_POL_MASK 0x300
+#define BLND_SM_CONTROL2__SM_FORCE_NEXT_FRAME_POL__SHIFT 0x8
+#define BLND_SM_CONTROL2__SM_FORCE_NEXT_TOP_POL_MASK 0x30000
+#define BLND_SM_CONTROL2__SM_FORCE_NEXT_TOP_POL__SHIFT 0x10
+#define BLND_SM_CONTROL2__SM_CURRENT_FRAME_POL_MASK 0x1000000
+#define BLND_SM_CONTROL2__SM_CURRENT_FRAME_POL__SHIFT 0x18
+#define BLND_CONTROL2__PTI_ENABLE_MASK 0x1
+#define BLND_CONTROL2__PTI_ENABLE__SHIFT 0x0
+#define BLND_CONTROL2__PTI_NEW_PIXEL_GAP_MASK 0x30
+#define BLND_CONTROL2__PTI_NEW_PIXEL_GAP__SHIFT 0x4
+#define BLND_CONTROL2__BLND_NEW_PIXEL_MODE_MASK 0x40
+#define BLND_CONTROL2__BLND_NEW_PIXEL_MODE__SHIFT 0x6
+#define BLND_CONTROL2__BLND_SUPERAA_DEGAMMA_EN_MASK 0x80
+#define BLND_CONTROL2__BLND_SUPERAA_DEGAMMA_EN__SHIFT 0x7
+#define BLND_CONTROL2__BLND_SUPERAA_REGAMMA_EN_MASK 0x100
+#define BLND_CONTROL2__BLND_SUPERAA_REGAMMA_EN__SHIFT 0x8
+#define BLND_UPDATE__BLND_UPDATE_PENDING_MASK 0x1
+#define BLND_UPDATE__BLND_UPDATE_PENDING__SHIFT 0x0
+#define BLND_UPDATE__BLND_UPDATE_TAKEN_MASK 0x100
+#define BLND_UPDATE__BLND_UPDATE_TAKEN__SHIFT 0x8
+#define BLND_UPDATE__BLND_UPDATE_LOCK_MASK 0x10000
+#define BLND_UPDATE__BLND_UPDATE_LOCK__SHIFT 0x10
+#define BLND_UNDERFLOW_INTERRUPT__BLND_UNDERFLOW_INT_OCCURED_MASK 0x1
+#define BLND_UNDERFLOW_INTERRUPT__BLND_UNDERFLOW_INT_OCCURED__SHIFT 0x0
+#define BLND_UNDERFLOW_INTERRUPT__BLND_UNDERFLOW_INT_ACK_MASK 0x100
+#define BLND_UNDERFLOW_INTERRUPT__BLND_UNDERFLOW_INT_ACK__SHIFT 0x8
+#define BLND_UNDERFLOW_INTERRUPT__BLND_UNDERFLOW_INT_MASK_MASK 0x1000
+#define BLND_UNDERFLOW_INTERRUPT__BLND_UNDERFLOW_INT_MASK__SHIFT 0xc
+#define BLND_UNDERFLOW_INTERRUPT__BLND_UNDERFLOW_INT_PIPE_INDEX_MASK 0x30000
+#define BLND_UNDERFLOW_INTERRUPT__BLND_UNDERFLOW_INT_PIPE_INDEX__SHIFT 0x10
+#define BLND_V_UPDATE_LOCK__BLND_DCP_GRPH_V_UPDATE_LOCK_MASK 0x1
+#define BLND_V_UPDATE_LOCK__BLND_DCP_GRPH_V_UPDATE_LOCK__SHIFT 0x0
+#define BLND_V_UPDATE_LOCK__BLND_DCP_GRPH_SURF_V_UPDATE_LOCK_MASK 0x2
+#define BLND_V_UPDATE_LOCK__BLND_DCP_GRPH_SURF_V_UPDATE_LOCK__SHIFT 0x1
+#define BLND_V_UPDATE_LOCK__BLND_DCP_CUR_V_UPDATE_LOCK_MASK 0x10000
+#define BLND_V_UPDATE_LOCK__BLND_DCP_CUR_V_UPDATE_LOCK__SHIFT 0x10
+#define BLND_V_UPDATE_LOCK__BLND_DCP_CUR2_V_UPDATE_LOCK_MASK 0x1000000
+#define BLND_V_UPDATE_LOCK__BLND_DCP_CUR2_V_UPDATE_LOCK__SHIFT 0x18
+#define BLND_V_UPDATE_LOCK__BLND_SCL_V_UPDATE_LOCK_MASK 0x10000000
+#define BLND_V_UPDATE_LOCK__BLND_SCL_V_UPDATE_LOCK__SHIFT 0x1c
+#define BLND_V_UPDATE_LOCK__BLND_BLND_V_UPDATE_LOCK_MASK 0x20000000
+#define BLND_V_UPDATE_LOCK__BLND_BLND_V_UPDATE_LOCK__SHIFT 0x1d
+#define BLND_V_UPDATE_LOCK__BLND_V_UPDATE_LOCK_MODE_MASK 0x80000000
+#define BLND_V_UPDATE_LOCK__BLND_V_UPDATE_LOCK_MODE__SHIFT 0x1f
+#define BLND_REG_UPDATE_STATUS__DCP_BLNDC_GRPH_UPDATE_PENDING_MASK 0x1
+#define BLND_REG_UPDATE_STATUS__DCP_BLNDC_GRPH_UPDATE_PENDING__SHIFT 0x0
+#define BLND_REG_UPDATE_STATUS__DCP_BLNDO_GRPH_UPDATE_PENDING_MASK 0x2
+#define BLND_REG_UPDATE_STATUS__DCP_BLNDO_GRPH_UPDATE_PENDING__SHIFT 0x1
+#define BLND_REG_UPDATE_STATUS__DCP_BLNDC_GRPH_SURF_UPDATE_PENDING_MASK 0x4
+#define BLND_REG_UPDATE_STATUS__DCP_BLNDC_GRPH_SURF_UPDATE_PENDING__SHIFT 0x2
+#define BLND_REG_UPDATE_STATUS__DCP_BLNDO_GRPH_SURF_UPDATE_PENDING_MASK 0x8
+#define BLND_REG_UPDATE_STATUS__DCP_BLNDO_GRPH_SURF_UPDATE_PENDING__SHIFT 0x3
+#define BLND_REG_UPDATE_STATUS__DCP_BLNDC_CUR_UPDATE_PENDING_MASK 0x40
+#define BLND_REG_UPDATE_STATUS__DCP_BLNDC_CUR_UPDATE_PENDING__SHIFT 0x6
+#define BLND_REG_UPDATE_STATUS__DCP_BLNDO_CUR_UPDATE_PENDING_MASK 0x80
+#define BLND_REG_UPDATE_STATUS__DCP_BLNDO_CUR_UPDATE_PENDING__SHIFT 0x7
+#define BLND_REG_UPDATE_STATUS__SCL_BLNDC_UPDATE_PENDING_MASK 0x100
+#define BLND_REG_UPDATE_STATUS__SCL_BLNDC_UPDATE_PENDING__SHIFT 0x8
+#define BLND_REG_UPDATE_STATUS__SCL_BLNDO_UPDATE_PENDING_MASK 0x200
+#define BLND_REG_UPDATE_STATUS__SCL_BLNDO_UPDATE_PENDING__SHIFT 0x9
+#define BLND_REG_UPDATE_STATUS__BLND_BLNDC_UPDATE_PENDING_MASK 0x400
+#define BLND_REG_UPDATE_STATUS__BLND_BLNDC_UPDATE_PENDING__SHIFT 0xa
+#define BLND_REG_UPDATE_STATUS__BLND_BLNDO_UPDATE_PENDING_MASK 0x800
+#define BLND_REG_UPDATE_STATUS__BLND_BLNDO_UPDATE_PENDING__SHIFT 0xb
+#define BLND_DEBUG__BLND_CNV_MUX_SELECT_MASK 0x1
+#define BLND_DEBUG__BLND_CNV_MUX_SELECT__SHIFT 0x0
+#define BLND_DEBUG__BLND_DEBUG_MASK 0xfffffffe
+#define BLND_DEBUG__BLND_DEBUG__SHIFT 0x1
+#define BLND_TEST_DEBUG_INDEX__BLND_TEST_DEBUG_INDEX_MASK 0xff
+#define BLND_TEST_DEBUG_INDEX__BLND_TEST_DEBUG_INDEX__SHIFT 0x0
+#define BLND_TEST_DEBUG_INDEX__BLND_TEST_DEBUG_WRITE_EN_MASK 0x100
+#define BLND_TEST_DEBUG_INDEX__BLND_TEST_DEBUG_WRITE_EN__SHIFT 0x8
+#define BLND_TEST_DEBUG_DATA__BLND_TEST_DEBUG_DATA_MASK 0xffffffff
+#define BLND_TEST_DEBUG_DATA__BLND_TEST_DEBUG_DATA__SHIFT 0x0
+#define WB_ENABLE__WB_ENABLE_MASK 0x1
+#define WB_ENABLE__WB_ENABLE__SHIFT 0x0
+#define WB_EC_CONFIG__DISPCLK_R_WB_GATE_DIS_MASK 0x1
+#define WB_EC_CONFIG__DISPCLK_R_WB_GATE_DIS__SHIFT 0x0
+#define WB_EC_CONFIG__DISPCLK_G_WB_GATE_DIS_MASK 0x2
+#define WB_EC_CONFIG__DISPCLK_G_WB_GATE_DIS__SHIFT 0x1
+#define WB_EC_CONFIG__DISPCLK_G_WBSCL_GATE_DIS_MASK 0x4
+#define WB_EC_CONFIG__DISPCLK_G_WBSCL_GATE_DIS__SHIFT 0x2
+#define WB_EC_CONFIG__WB_TEST_CLK_SEL_MASK 0x78
+#define WB_EC_CONFIG__WB_TEST_CLK_SEL__SHIFT 0x3
+#define WB_EC_CONFIG__WB_LB_LS_DIS_MASK 0x80
+#define WB_EC_CONFIG__WB_LB_LS_DIS__SHIFT 0x7
+#define WB_EC_CONFIG__WB_LB_SD_DIS_MASK 0x100
+#define WB_EC_CONFIG__WB_LB_SD_DIS__SHIFT 0x8
+#define WB_EC_CONFIG__WB_LUT_LS_DIS_MASK 0x200
+#define WB_EC_CONFIG__WB_LUT_LS_DIS__SHIFT 0x9
+#define WB_EC_CONFIG__WBSCL_LB_MEM_PWR_MODE_SEL_MASK 0x3000
+#define WB_EC_CONFIG__WBSCL_LB_MEM_PWR_MODE_SEL__SHIFT 0xc
+#define WB_EC_CONFIG__WBSCL_LB_MEM_PWR_DIS_MASK 0x4000
+#define WB_EC_CONFIG__WBSCL_LB_MEM_PWR_DIS__SHIFT 0xe
+#define WB_EC_CONFIG__WBSCL_LB_MEM_PWR_FORCE_MASK 0x18000
+#define WB_EC_CONFIG__WBSCL_LB_MEM_PWR_FORCE__SHIFT 0xf
+#define WB_EC_CONFIG__WBSCL_LB_MEM_PWR_STATE_SM_MASK 0x60000
+#define WB_EC_CONFIG__WBSCL_LB_MEM_PWR_STATE_SM__SHIFT 0x11
+#define WB_EC_CONFIG__WBSCL_LB_MEM_PWR_STATE_BG_MASK 0x180000
+#define WB_EC_CONFIG__WBSCL_LB_MEM_PWR_STATE_BG__SHIFT 0x13
+#define WB_EC_CONFIG__WBSCL_LB_MEM_PWR_STATE_MASK 0x600000
+#define WB_EC_CONFIG__WBSCL_LB_MEM_PWR_STATE__SHIFT 0x15
+#define WB_EC_CONFIG__WB_RAM_PW_SAVE_MODE_MASK 0x800000
+#define WB_EC_CONFIG__WB_RAM_PW_SAVE_MODE__SHIFT 0x17
+#define WB_EC_CONFIG__LB_MEM_PWR_STATE_SM_MASK 0x3000000
+#define WB_EC_CONFIG__LB_MEM_PWR_STATE_SM__SHIFT 0x18
+#define WB_EC_CONFIG__LB_MEM_PWR_STATE_BG_MASK 0xc000000
+#define WB_EC_CONFIG__LB_MEM_PWR_STATE_BG__SHIFT 0x1a
+#define WB_EC_CONFIG__LB_MEM_PWR_STATE_MASK 0x30000000
+#define WB_EC_CONFIG__LB_MEM_PWR_STATE__SHIFT 0x1c
+#define WB_EC_CONFIG__LUT_MEM_PWR_STATE_MASK 0xc0000000
+#define WB_EC_CONFIG__LUT_MEM_PWR_STATE__SHIFT 0x1e
+#define CNV_MODE__CNV_FRAME_CAPTURE_RATE_MASK 0x300
+#define CNV_MODE__CNV_FRAME_CAPTURE_RATE__SHIFT 0x8
+#define CNV_MODE__CNV_WINDOW_CROP_EN_MASK 0x1000
+#define CNV_MODE__CNV_WINDOW_CROP_EN__SHIFT 0xc
+#define CNV_MODE__CNV_STEREO_TYPE_MASK 0x6000
+#define CNV_MODE__CNV_STEREO_TYPE__SHIFT 0xd
+#define CNV_MODE__CNV_INTERLACED_MODE_MASK 0x8000
+#define CNV_MODE__CNV_INTERLACED_MODE__SHIFT 0xf
+#define CNV_MODE__CNV_EYE_SELECTION_MASK 0x30000
+#define CNV_MODE__CNV_EYE_SELECTION__SHIFT 0x10
+#define CNV_MODE__CNV_STEREO_POLARITY_MASK 0x40000
+#define CNV_MODE__CNV_STEREO_POLARITY__SHIFT 0x12
+#define CNV_MODE__CNV_INTERLACED_FIELD_ORDER_MASK 0x80000
+#define CNV_MODE__CNV_INTERLACED_FIELD_ORDER__SHIFT 0x13
+#define CNV_MODE__CNV_STEREO_SPLIT_MASK 0x100000
+#define CNV_MODE__CNV_STEREO_SPLIT__SHIFT 0x14
+#define CNV_MODE__CNV_NEW_CONTENT_MASK 0x1000000
+#define CNV_MODE__CNV_NEW_CONTENT__SHIFT 0x18
+#define CNV_MODE__CNV_FRAME_CAPTURE_EN_MASK 0x80000000
+#define CNV_MODE__CNV_FRAME_CAPTURE_EN__SHIFT 0x1f
+#define CNV_WINDOW_START__CNV_WINDOW_START_X_MASK 0xfff
+#define CNV_WINDOW_START__CNV_WINDOW_START_X__SHIFT 0x0
+#define CNV_WINDOW_START__CNV_WINDOW_START_Y_MASK 0xfff0000
+#define CNV_WINDOW_START__CNV_WINDOW_START_Y__SHIFT 0x10
+#define CNV_WINDOW_SIZE__CNV_WINDOW_WIDTH_MASK 0xfff
+#define CNV_WINDOW_SIZE__CNV_WINDOW_WIDTH__SHIFT 0x0
+#define CNV_WINDOW_SIZE__CNV_WINDOW_HEIGHT_MASK 0xfff0000
+#define CNV_WINDOW_SIZE__CNV_WINDOW_HEIGHT__SHIFT 0x10
+#define CNV_UPDATE__CNV_UPDATE_PENDING_MASK 0x1
+#define CNV_UPDATE__CNV_UPDATE_PENDING__SHIFT 0x0
+#define CNV_UPDATE__CNV_UPDATE_TAKEN_MASK 0x100
+#define CNV_UPDATE__CNV_UPDATE_TAKEN__SHIFT 0x8
+#define CNV_UPDATE__CNV_UPDATE_LOCK_MASK 0x10000
+#define CNV_UPDATE__CNV_UPDATE_LOCK__SHIFT 0x10
+#define CNV_SOURCE_SIZE__CNV_SOURCE_WIDTH_MASK 0x7fff
+#define CNV_SOURCE_SIZE__CNV_SOURCE_WIDTH__SHIFT 0x0
+#define CNV_SOURCE_SIZE__CNV_SOURCE_HEIGHT_MASK 0x7fff0000
+#define CNV_SOURCE_SIZE__CNV_SOURCE_HEIGHT__SHIFT 0x10
+#define CNV_CSC_CONTROL__CNV_CSC_BYPASS_MASK 0x1
+#define CNV_CSC_CONTROL__CNV_CSC_BYPASS__SHIFT 0x0
+#define CNV_CSC_C11_C12__CNV_CSC_C11_MASK 0x1fff
+#define CNV_CSC_C11_C12__CNV_CSC_C11__SHIFT 0x0
+#define CNV_CSC_C11_C12__CNV_CSC_C12_MASK 0x1fff0000
+#define CNV_CSC_C11_C12__CNV_CSC_C12__SHIFT 0x10
+#define CNV_CSC_C13_C14__CNV_CSC_C13_MASK 0x1fff
+#define CNV_CSC_C13_C14__CNV_CSC_C13__SHIFT 0x0
+#define CNV_CSC_C13_C14__CNV_CSC_C14_MASK 0x7fff0000
+#define CNV_CSC_C13_C14__CNV_CSC_C14__SHIFT 0x10
+#define CNV_CSC_C21_C22__CNV_CSC_C21_MASK 0x1fff
+#define CNV_CSC_C21_C22__CNV_CSC_C21__SHIFT 0x0
+#define CNV_CSC_C21_C22__CNV_CSC_C22_MASK 0x1fff0000
+#define CNV_CSC_C21_C22__CNV_CSC_C22__SHIFT 0x10
+#define CNV_CSC_C23_C24__CNV_CSC_C23_MASK 0x1fff
+#define CNV_CSC_C23_C24__CNV_CSC_C23__SHIFT 0x0
+#define CNV_CSC_C23_C24__CNV_CSC_C24_MASK 0x7fff0000
+#define CNV_CSC_C23_C24__CNV_CSC_C24__SHIFT 0x10
+#define CNV_CSC_C31_C32__CNV_CSC_C31_MASK 0x1fff
+#define CNV_CSC_C31_C32__CNV_CSC_C31__SHIFT 0x0
+#define CNV_CSC_C31_C32__CNV_CSC_C32_MASK 0x1fff0000
+#define CNV_CSC_C31_C32__CNV_CSC_C32__SHIFT 0x10
+#define CNV_CSC_C33_C34__CNV_CSC_C33_MASK 0x1fff
+#define CNV_CSC_C33_C34__CNV_CSC_C33__SHIFT 0x0
+#define CNV_CSC_C33_C34__CNV_CSC_C34_MASK 0x7fff0000
+#define CNV_CSC_C33_C34__CNV_CSC_C34__SHIFT 0x10
+#define CNV_CSC_ROUND_OFFSET_R__CNV_CSC_ROUND_OFFSET_R_MASK 0xffff
+#define CNV_CSC_ROUND_OFFSET_R__CNV_CSC_ROUND_OFFSET_R__SHIFT 0x0
+#define CNV_CSC_ROUND_OFFSET_G__CNV_CSC_ROUND_OFFSET_G_MASK 0xffff
+#define CNV_CSC_ROUND_OFFSET_G__CNV_CSC_ROUND_OFFSET_G__SHIFT 0x0
+#define CNV_CSC_ROUND_OFFSET_B__CNV_CSC_ROUND_OFFSET_B_MASK 0xffff
+#define CNV_CSC_ROUND_OFFSET_B__CNV_CSC_ROUND_OFFSET_B__SHIFT 0x0
+#define CNV_CSC_CLAMP_R__CNV_CSC_CLAMP_UPPER_R_MASK 0xffff
+#define CNV_CSC_CLAMP_R__CNV_CSC_CLAMP_UPPER_R__SHIFT 0x0
+#define CNV_CSC_CLAMP_R__CNV_CSC_CLAMP_LOWER_R_MASK 0xffff0000
+#define CNV_CSC_CLAMP_R__CNV_CSC_CLAMP_LOWER_R__SHIFT 0x10
+#define CNV_CSC_CLAMP_G__CNV_CSC_CLAMP_UPPER_G_MASK 0xffff
+#define CNV_CSC_CLAMP_G__CNV_CSC_CLAMP_UPPER_G__SHIFT 0x0
+#define CNV_CSC_CLAMP_G__CNV_CSC_CLAMP_LOWER_G_MASK 0xffff0000
+#define CNV_CSC_CLAMP_G__CNV_CSC_CLAMP_LOWER_G__SHIFT 0x10
+#define CNV_CSC_CLAMP_B__CNV_CSC_CLAMP_UPPER_B_MASK 0xffff
+#define CNV_CSC_CLAMP_B__CNV_CSC_CLAMP_UPPER_B__SHIFT 0x0
+#define CNV_CSC_CLAMP_B__CNV_CSC_CLAMP_LOWER_B_MASK 0xffff0000
+#define CNV_CSC_CLAMP_B__CNV_CSC_CLAMP_LOWER_B__SHIFT 0x10
+#define CNV_TEST_CNTL__CNV_TEST_CRC_EN_MASK 0x10
+#define CNV_TEST_CNTL__CNV_TEST_CRC_EN__SHIFT 0x4
+#define CNV_TEST_CNTL__CNV_TEST_CRC_CONT_EN_MASK 0x100
+#define CNV_TEST_CNTL__CNV_TEST_CRC_CONT_EN__SHIFT 0x8
+#define CNV_TEST_CNTL__CNV_TEST_CRC_DE_ONLY_MASK 0x10000
+#define CNV_TEST_CNTL__CNV_TEST_CRC_DE_ONLY__SHIFT 0x10
+#define CNV_TEST_CRC_RED__CNV_TEST_CRC_RED_MASK_MASK 0xfff0
+#define CNV_TEST_CRC_RED__CNV_TEST_CRC_RED_MASK__SHIFT 0x4
+#define CNV_TEST_CRC_RED__CNV_TEST_CRC_SIG_RED_MASK 0xffff0000
+#define CNV_TEST_CRC_RED__CNV_TEST_CRC_SIG_RED__SHIFT 0x10
+#define CNV_TEST_CRC_GREEN__CNV_TEST_CRC_GREEN_MASK_MASK 0xfff0
+#define CNV_TEST_CRC_GREEN__CNV_TEST_CRC_GREEN_MASK__SHIFT 0x4
+#define CNV_TEST_CRC_GREEN__CNV_TEST_CRC_SIG_GREEN_MASK 0xffff0000
+#define CNV_TEST_CRC_GREEN__CNV_TEST_CRC_SIG_GREEN__SHIFT 0x10
+#define CNV_TEST_CRC_BLUE__CNV_TEST_CRC_BLUE_MASK_MASK 0xfff0
+#define CNV_TEST_CRC_BLUE__CNV_TEST_CRC_BLUE_MASK__SHIFT 0x4
+#define CNV_TEST_CRC_BLUE__CNV_TEST_CRC_SIG_BLUE_MASK 0xffff0000
+#define CNV_TEST_CRC_BLUE__CNV_TEST_CRC_SIG_BLUE__SHIFT 0x10
+#define WB_DEBUG_CTRL__WB_DEBUG_EN_MASK 0x1
+#define WB_DEBUG_CTRL__WB_DEBUG_EN__SHIFT 0x0
+#define WB_DEBUG_CTRL__WB_DEBUG_SEL_MASK 0xc0
+#define WB_DEBUG_CTRL__WB_DEBUG_SEL__SHIFT 0x6
+#define WB_DBG_MODE__WB_DBG_MODE_EN_MASK 0x1
+#define WB_DBG_MODE__WB_DBG_MODE_EN__SHIFT 0x0
+#define WB_DBG_MODE__WB_DBG_DIN_FMT_MASK 0x2
+#define WB_DBG_MODE__WB_DBG_DIN_FMT__SHIFT 0x1
+#define WB_DBG_MODE__WB_DBG_36MODE_MASK 0x4
+#define WB_DBG_MODE__WB_DBG_36MODE__SHIFT 0x2
+#define WB_DBG_MODE__WB_DBG_CMAP_MASK 0x8
+#define WB_DBG_MODE__WB_DBG_CMAP__SHIFT 0x3
+#define WB_DBG_MODE__WB_DBG_PXLRATE_ERROR_MASK 0x100
+#define WB_DBG_MODE__WB_DBG_PXLRATE_ERROR__SHIFT 0x8
+#define WB_DBG_MODE__WB_DBG_SOURCE_WIDTH_MASK 0x7fff0000
+#define WB_DBG_MODE__WB_DBG_SOURCE_WIDTH__SHIFT 0x10
+#define WB_HW_DEBUG__WB_HW_DEBUG_MASK 0xffffffff
+#define WB_HW_DEBUG__WB_HW_DEBUG__SHIFT 0x0
+#define CNV_INPUT_SELECT__CNV_INPUT_SRC_SELECT_MASK 0x3
+#define CNV_INPUT_SELECT__CNV_INPUT_SRC_SELECT__SHIFT 0x0
+#define CNV_INPUT_SELECT__CNV_INPUT_PIPE_SELECT_MASK 0x1c
+#define CNV_INPUT_SELECT__CNV_INPUT_PIPE_SELECT__SHIFT 0x2
+#define WB_SOFT_RESET__WB_SOFT_RESET_MASK 0x1
+#define WB_SOFT_RESET__WB_SOFT_RESET__SHIFT 0x0
+#define WB_WARM_UP_MODE_CTL1__WIDTH_WARMUP_MASK 0x7fff
+#define WB_WARM_UP_MODE_CTL1__WIDTH_WARMUP__SHIFT 0x0
+#define WB_WARM_UP_MODE_CTL1__HEIGHT_WARMUP_MASK 0x7fff0000
+#define WB_WARM_UP_MODE_CTL1__HEIGHT_WARMUP__SHIFT 0x10
+#define WB_WARM_UP_MODE_CTL1__GMC_WARM_UP_ENABLE_MASK 0x80000000
+#define WB_WARM_UP_MODE_CTL1__GMC_WARM_UP_ENABLE__SHIFT 0x1f
+#define WB_WARM_UP_MODE_CTL2__DATA_VALUE_WARMUP_MASK 0xff
+#define WB_WARM_UP_MODE_CTL2__DATA_VALUE_WARMUP__SHIFT 0x0
+#define WB_WARM_UP_MODE_CTL2__MODE_WARMUP_MASK 0x100
+#define WB_WARM_UP_MODE_CTL2__MODE_WARMUP__SHIFT 0x8
+#define CNV_TEST_DEBUG_INDEX__CNV_TEST_DEBUG_INDEX_MASK 0xff
+#define CNV_TEST_DEBUG_INDEX__CNV_TEST_DEBUG_INDEX__SHIFT 0x0
+#define CNV_TEST_DEBUG_INDEX__CNV_TEST_DEBUG_WRITE_EN_MASK 0x100
+#define CNV_TEST_DEBUG_INDEX__CNV_TEST_DEBUG_WRITE_EN__SHIFT 0x8
+#define CNV_TEST_DEBUG_DATA__CNV_TEST_DEBUG_DATA_MASK 0xffffffff
+#define CNV_TEST_DEBUG_DATA__CNV_TEST_DEBUG_DATA__SHIFT 0x0
+#define DCFE_CLOCK_CONTROL__DISPCLK_R_DCFE_GATE_DISABLE_MASK 0x10
+#define DCFE_CLOCK_CONTROL__DISPCLK_R_DCFE_GATE_DISABLE__SHIFT 0x4
+#define DCFE_CLOCK_CONTROL__DISPCLK_G_DCP_GATE_DISABLE_MASK 0x100
+#define DCFE_CLOCK_CONTROL__DISPCLK_G_DCP_GATE_DISABLE__SHIFT 0x8
+#define DCFE_CLOCK_CONTROL__DISPCLK_G_SCL_GATE_DISABLE_MASK 0x1000
+#define DCFE_CLOCK_CONTROL__DISPCLK_G_SCL_GATE_DISABLE__SHIFT 0xc
+#define DCFE_CLOCK_CONTROL__DISPCLK_G_PSCL_GATE_DISABLE_MASK 0x8000
+#define DCFE_CLOCK_CONTROL__DISPCLK_G_PSCL_GATE_DISABLE__SHIFT 0xf
+#define DCFE_CLOCK_CONTROL__DISPCLK_G_PIPE_REQUEST_DIS_GATE_DISABLE_MASK 0x20000
+#define DCFE_CLOCK_CONTROL__DISPCLK_G_PIPE_REQUEST_DIS_GATE_DISABLE__SHIFT 0x11
+#define DCFE_CLOCK_CONTROL__DCFE_TEST_CLK_SEL_MASK 0x1f000000
+#define DCFE_CLOCK_CONTROL__DCFE_TEST_CLK_SEL__SHIFT 0x18
+#define DCFE_CLOCK_CONTROL__DCFE_CLOCK_ENABLE_MASK 0x80000000
+#define DCFE_CLOCK_CONTROL__DCFE_CLOCK_ENABLE__SHIFT 0x1f
+#define DCFE_SOFT_RESET__DCP_PIXPIPE_SOFT_RESET_MASK 0x1
+#define DCFE_SOFT_RESET__DCP_PIXPIPE_SOFT_RESET__SHIFT 0x0
+#define DCFE_SOFT_RESET__DCP_REQ_SOFT_RESET_MASK 0x2
+#define DCFE_SOFT_RESET__DCP_REQ_SOFT_RESET__SHIFT 0x1
+#define DCFE_SOFT_RESET__SCL_ALU_SOFT_RESET_MASK 0x4
+#define DCFE_SOFT_RESET__SCL_ALU_SOFT_RESET__SHIFT 0x2
+#define DCFE_SOFT_RESET__SCL_SOFT_RESET_MASK 0x8
+#define DCFE_SOFT_RESET__SCL_SOFT_RESET__SHIFT 0x3
+#define DCFE_SOFT_RESET__CRTC_SOFT_RESET_MASK 0x10
+#define DCFE_SOFT_RESET__CRTC_SOFT_RESET__SHIFT 0x4
+#define DCFE_SOFT_RESET__PSCL_SOFT_RESET_MASK 0x20
+#define DCFE_SOFT_RESET__PSCL_SOFT_RESET__SHIFT 0x5
+#define DCFE_DBG_CONFIG__DCFE_DBG_EN_MASK 0x1
+#define DCFE_DBG_CONFIG__DCFE_DBG_EN__SHIFT 0x0
+#define DCFE_DBG_CONFIG__DCFE_DBG_SEL_MASK 0xf0
+#define DCFE_DBG_CONFIG__DCFE_DBG_SEL__SHIFT 0x4
+#define DCFE_MEM_PWR_CTRL__DCP_LUT_MEM_PWR_FORCE_MASK 0x3
+#define DCFE_MEM_PWR_CTRL__DCP_LUT_MEM_PWR_FORCE__SHIFT 0x0
+#define DCFE_MEM_PWR_CTRL__DCP_LUT_MEM_PWR_DIS_MASK 0x4
+#define DCFE_MEM_PWR_CTRL__DCP_LUT_MEM_PWR_DIS__SHIFT 0x2
+#define DCFE_MEM_PWR_CTRL__DCP_REGAMMA_MEM_PWR_FORCE_MASK 0x18
+#define DCFE_MEM_PWR_CTRL__DCP_REGAMMA_MEM_PWR_FORCE__SHIFT 0x3
+#define DCFE_MEM_PWR_CTRL__DCP_REGAMMA_MEM_PWR_DIS_MASK 0x20
+#define DCFE_MEM_PWR_CTRL__DCP_REGAMMA_MEM_PWR_DIS__SHIFT 0x5
+#define DCFE_MEM_PWR_CTRL__SCL_COEFF_MEM_PWR_FORCE_MASK 0xc0
+#define DCFE_MEM_PWR_CTRL__SCL_COEFF_MEM_PWR_FORCE__SHIFT 0x6
+#define DCFE_MEM_PWR_CTRL__SCL_COEFF_MEM_PWR_DIS_MASK 0x100
+#define DCFE_MEM_PWR_CTRL__SCL_COEFF_MEM_PWR_DIS__SHIFT 0x8
+#define DCFE_MEM_PWR_CTRL__DCP_CURSOR_MEM_PWR_FORCE_MASK 0x600
+#define DCFE_MEM_PWR_CTRL__DCP_CURSOR_MEM_PWR_FORCE__SHIFT 0x9
+#define DCFE_MEM_PWR_CTRL__DCP_CURSOR_MEM_PWR_DIS_MASK 0x800
+#define DCFE_MEM_PWR_CTRL__DCP_CURSOR_MEM_PWR_DIS__SHIFT 0xb
+#define DCFE_MEM_PWR_CTRL__LB0_ALPHA_MEM_PWR_FORCE_MASK 0x3000
+#define DCFE_MEM_PWR_CTRL__LB0_ALPHA_MEM_PWR_FORCE__SHIFT 0xc
+#define DCFE_MEM_PWR_CTRL__LB0_ALPHA_MEM_PWR_DIS_MASK 0x4000
+#define DCFE_MEM_PWR_CTRL__LB0_ALPHA_MEM_PWR_DIS__SHIFT 0xe
+#define DCFE_MEM_PWR_CTRL__LB1_ALPHA_MEM_PWR_FORCE_MASK 0x18000
+#define DCFE_MEM_PWR_CTRL__LB1_ALPHA_MEM_PWR_FORCE__SHIFT 0xf
+#define DCFE_MEM_PWR_CTRL__LB1_ALPHA_MEM_PWR_DIS_MASK 0x20000
+#define DCFE_MEM_PWR_CTRL__LB1_ALPHA_MEM_PWR_DIS__SHIFT 0x11
+#define DCFE_MEM_PWR_CTRL__LB2_ALPHA_MEM_PWR_FORCE_MASK 0xc0000
+#define DCFE_MEM_PWR_CTRL__LB2_ALPHA_MEM_PWR_FORCE__SHIFT 0x12
+#define DCFE_MEM_PWR_CTRL__LB2_ALPHA_MEM_PWR_DIS_MASK 0x100000
+#define DCFE_MEM_PWR_CTRL__LB2_ALPHA_MEM_PWR_DIS__SHIFT 0x14
+#define DCFE_MEM_PWR_CTRL__LB0_MEM_PWR_FORCE_MASK 0x600000
+#define DCFE_MEM_PWR_CTRL__LB0_MEM_PWR_FORCE__SHIFT 0x15
+#define DCFE_MEM_PWR_CTRL__LB0_MEM_PWR_DIS_MASK 0x800000
+#define DCFE_MEM_PWR_CTRL__LB0_MEM_PWR_DIS__SHIFT 0x17
+#define DCFE_MEM_PWR_CTRL__LB1_MEM_PWR_FORCE_MASK 0x3000000
+#define DCFE_MEM_PWR_CTRL__LB1_MEM_PWR_FORCE__SHIFT 0x18
+#define DCFE_MEM_PWR_CTRL__LB1_MEM_PWR_DIS_MASK 0x4000000
+#define DCFE_MEM_PWR_CTRL__LB1_MEM_PWR_DIS__SHIFT 0x1a
+#define DCFE_MEM_PWR_CTRL__LB2_MEM_PWR_FORCE_MASK 0x18000000
+#define DCFE_MEM_PWR_CTRL__LB2_MEM_PWR_FORCE__SHIFT 0x1b
+#define DCFE_MEM_PWR_CTRL__LB2_MEM_PWR_DIS_MASK 0x20000000
+#define DCFE_MEM_PWR_CTRL__LB2_MEM_PWR_DIS__SHIFT 0x1d
+#define DCFE_MEM_PWR_CTRL2__DCP_LUT_MEM_PWR_MODE_SEL_MASK 0x3
+#define DCFE_MEM_PWR_CTRL2__DCP_LUT_MEM_PWR_MODE_SEL__SHIFT 0x0
+#define DCFE_MEM_PWR_CTRL2__DCP_REGAMMA_MEM_PWR_MODE_SEL_MASK 0xc
+#define DCFE_MEM_PWR_CTRL2__DCP_REGAMMA_MEM_PWR_MODE_SEL__SHIFT 0x2
+#define DCFE_MEM_PWR_CTRL2__SCL_COEFF_MEM_PWR_MODE_SEL_MASK 0x30
+#define DCFE_MEM_PWR_CTRL2__SCL_COEFF_MEM_PWR_MODE_SEL__SHIFT 0x4
+#define DCFE_MEM_PWR_CTRL2__DCP_CURSOR_MEM_PWR_MODE_SEL_MASK 0xc0
+#define DCFE_MEM_PWR_CTRL2__DCP_CURSOR_MEM_PWR_MODE_SEL__SHIFT 0x6
+#define DCFE_MEM_PWR_CTRL2__LB_ALPHA_MEM_PWR_MODE_SEL_MASK 0x300
+#define DCFE_MEM_PWR_CTRL2__LB_ALPHA_MEM_PWR_MODE_SEL__SHIFT 0x8
+#define DCFE_MEM_PWR_CTRL2__LB_MEM_PWR_MODE_SEL_MASK 0xc00
+#define DCFE_MEM_PWR_CTRL2__LB_MEM_PWR_MODE_SEL__SHIFT 0xa
+#define DCFE_MEM_PWR_CTRL2__DCP_CURSOR2_MEM_PWR_MODE_SEL_MASK 0x3000
+#define DCFE_MEM_PWR_CTRL2__DCP_CURSOR2_MEM_PWR_MODE_SEL__SHIFT 0xc
+#define DCFE_MEM_PWR_CTRL2__BLND_MEM_PWR_MODE_SEL_MASK 0xc000
+#define DCFE_MEM_PWR_CTRL2__BLND_MEM_PWR_MODE_SEL__SHIFT 0xe
+#define DCFE_MEM_PWR_CTRL2__BLND_MEM_PWR_FORCE_MASK 0x30000
+#define DCFE_MEM_PWR_CTRL2__BLND_MEM_PWR_FORCE__SHIFT 0x10
+#define DCFE_MEM_PWR_CTRL2__BLND_MEM_PWR_DIS_MASK 0x40000
+#define DCFE_MEM_PWR_CTRL2__BLND_MEM_PWR_DIS__SHIFT 0x12
+#define DCFE_MEM_PWR_CTRL2__DCP_CURSOR2_MEM_PWR_FORCE_MASK 0x600000
+#define DCFE_MEM_PWR_CTRL2__DCP_CURSOR2_MEM_PWR_FORCE__SHIFT 0x15
+#define DCFE_MEM_PWR_CTRL2__DCP_CURSOR2_MEM_PWR_DIS_MASK 0x800000
+#define DCFE_MEM_PWR_CTRL2__DCP_CURSOR2_MEM_PWR_DIS__SHIFT 0x17
+#define DCFE_MEM_PWR_STATUS__DCP_LUT_MEM_PWR_STATE_MASK 0x3
+#define DCFE_MEM_PWR_STATUS__DCP_LUT_MEM_PWR_STATE__SHIFT 0x0
+#define DCFE_MEM_PWR_STATUS__DCP_REGAMMA_MEM_PWR_STATE_MASK 0xc
+#define DCFE_MEM_PWR_STATUS__DCP_REGAMMA_MEM_PWR_STATE__SHIFT 0x2
+#define DCFE_MEM_PWR_STATUS__SCL_COEFF_MEM_PWR_STATE_MASK 0x30
+#define DCFE_MEM_PWR_STATUS__SCL_COEFF_MEM_PWR_STATE__SHIFT 0x4
+#define DCFE_MEM_PWR_STATUS__DCP_CURSOR_MEM_PWR_STATE_MASK 0xc0
+#define DCFE_MEM_PWR_STATUS__DCP_CURSOR_MEM_PWR_STATE__SHIFT 0x6
+#define DCFE_MEM_PWR_STATUS__DCP_CURSOR2_MEM_PWR_STATE_MASK 0x300
+#define DCFE_MEM_PWR_STATUS__DCP_CURSOR2_MEM_PWR_STATE__SHIFT 0x8
+#define DCFE_MEM_PWR_STATUS__LB0_ALPHA_MEM_PWR_STATE_MASK 0xc00
+#define DCFE_MEM_PWR_STATUS__LB0_ALPHA_MEM_PWR_STATE__SHIFT 0xa
+#define DCFE_MEM_PWR_STATUS__LB1_ALPHA_MEM_PWR_STATE_MASK 0x3000
+#define DCFE_MEM_PWR_STATUS__LB1_ALPHA_MEM_PWR_STATE__SHIFT 0xc
+#define DCFE_MEM_PWR_STATUS__LB2_ALPHA_MEM_PWR_STATE_MASK 0xc000
+#define DCFE_MEM_PWR_STATUS__LB2_ALPHA_MEM_PWR_STATE__SHIFT 0xe
+#define DCFE_MEM_PWR_STATUS__LB0_MEM_PWR_STATE_MASK 0x30000
+#define DCFE_MEM_PWR_STATUS__LB0_MEM_PWR_STATE__SHIFT 0x10
+#define DCFE_MEM_PWR_STATUS__LB1_MEM_PWR_STATE_MASK 0xc0000
+#define DCFE_MEM_PWR_STATUS__LB1_MEM_PWR_STATE__SHIFT 0x12
+#define DCFE_MEM_PWR_STATUS__LB2_MEM_PWR_STATE_MASK 0x300000
+#define DCFE_MEM_PWR_STATUS__LB2_MEM_PWR_STATE__SHIFT 0x14
+#define DCFE_MEM_PWR_STATUS__BLND_MEM_PWR_STATE_MASK 0xc00000
+#define DCFE_MEM_PWR_STATUS__BLND_MEM_PWR_STATE__SHIFT 0x16
+#define DCFE_MISC__DCFE_DPG_ALLOW_SR_ECO_EN_MASK 0x1
+#define DCFE_MISC__DCFE_DPG_ALLOW_SR_ECO_EN__SHIFT 0x0
+#define DCFE_FLUSH__FLUSH_OCCURED_MASK 0x1
+#define DCFE_FLUSH__FLUSH_OCCURED__SHIFT 0x0
+#define DCFE_FLUSH__CLEAR_FLUSH_OCCURED_MASK 0x2
+#define DCFE_FLUSH__CLEAR_FLUSH_OCCURED__SHIFT 0x1
+#define DCFE_FLUSH__FLUSH_DEEP_MASK 0x4
+#define DCFE_FLUSH__FLUSH_DEEP__SHIFT 0x2
+#define DCFE_FLUSH__CLEAR_FLUSH_DEEP_MASK 0x8
+#define DCFE_FLUSH__CLEAR_FLUSH_DEEP__SHIFT 0x3
+#define DCFE_FLUSH__ALL_MC_REQ_RET_MASK 0x10
+#define DCFE_FLUSH__ALL_MC_REQ_RET__SHIFT 0x4
+#define DCFEV_CLOCK_CONTROL__DISPCLK_R_DCFEV_GATE_DISABLE_MASK 0x8
+#define DCFEV_CLOCK_CONTROL__DISPCLK_R_DCFEV_GATE_DISABLE__SHIFT 0x3
+#define DCFEV_CLOCK_CONTROL__DISPCLK_G_UNP_GATE_DISABLE_MASK 0x80
+#define DCFEV_CLOCK_CONTROL__DISPCLK_G_UNP_GATE_DISABLE__SHIFT 0x7
+#define DCFEV_CLOCK_CONTROL__DISPCLK_G_SCLV_GATE_DISABLE_MASK 0x200
+#define DCFEV_CLOCK_CONTROL__DISPCLK_G_SCLV_GATE_DISABLE__SHIFT 0x9
+#define DCFEV_CLOCK_CONTROL__DISPCLK_G_COL_MAN_GATE_DISABLE_MASK 0x800
+#define DCFEV_CLOCK_CONTROL__DISPCLK_G_COL_MAN_GATE_DISABLE__SHIFT 0xb
+#define DCFEV_CLOCK_CONTROL__DISPCLK_G_PSCLV_GATE_DISABLE_MASK 0x2000
+#define DCFEV_CLOCK_CONTROL__DISPCLK_G_PSCLV_GATE_DISABLE__SHIFT 0xd
+#define DCFEV_CLOCK_CONTROL__DISPCLK_G_CRTC_GATE_DISABLE_MASK 0x8000
+#define DCFEV_CLOCK_CONTROL__DISPCLK_G_CRTC_GATE_DISABLE__SHIFT 0xf
+#define DCFEV_CLOCK_CONTROL__DCFEV_TEST_CLK_SEL_MASK 0x1f000000
+#define DCFEV_CLOCK_CONTROL__DCFEV_TEST_CLK_SEL__SHIFT 0x18
+#define DCFEV_CLOCK_CONTROL__DCFEV_CLOCK_ENABLE_MASK 0x80000000
+#define DCFEV_CLOCK_CONTROL__DCFEV_CLOCK_ENABLE__SHIFT 0x1f
+#define DCFEV_SOFT_RESET__UNP_PIXPIPE_SOFT_RESET_MASK 0x1
+#define DCFEV_SOFT_RESET__UNP_PIXPIPE_SOFT_RESET__SHIFT 0x0
+#define DCFEV_SOFT_RESET__UNP_REQ_SOFT_RESET_MASK 0x2
+#define DCFEV_SOFT_RESET__UNP_REQ_SOFT_RESET__SHIFT 0x1
+#define DCFEV_SOFT_RESET__SCLV_ALU_SOFT_RESET_MASK 0x4
+#define DCFEV_SOFT_RESET__SCLV_ALU_SOFT_RESET__SHIFT 0x2
+#define DCFEV_SOFT_RESET__SCLV_SOFT_RESET_MASK 0x8
+#define DCFEV_SOFT_RESET__SCLV_SOFT_RESET__SHIFT 0x3
+#define DCFEV_SOFT_RESET__CRTC_SOFT_RESET_MASK 0x10
+#define DCFEV_SOFT_RESET__CRTC_SOFT_RESET__SHIFT 0x4
+#define DCFEV_SOFT_RESET__PSCLV_SOFT_RESET_MASK 0x20
+#define DCFEV_SOFT_RESET__PSCLV_SOFT_RESET__SHIFT 0x5
+#define DCFEV_SOFT_RESET__COL_MAN_SOFT_RESET_MASK 0x40
+#define DCFEV_SOFT_RESET__COL_MAN_SOFT_RESET__SHIFT 0x6
+#define DCFEV_DMIFV_CLOCK_CONTROL__DMIFV_SCLK_G_DMIFTRK_GATE_DIS_MASK 0x8
+#define DCFEV_DMIFV_CLOCK_CONTROL__DMIFV_SCLK_G_DMIFTRK_GATE_DIS__SHIFT 0x3
+#define DCFEV_DMIFV_CLOCK_CONTROL__DMIFV_DISPCLK_G_DMIFVL_GATE_DIS_MASK 0x10
+#define DCFEV_DMIFV_CLOCK_CONTROL__DMIFV_DISPCLK_G_DMIFVL_GATE_DIS__SHIFT 0x4
+#define DCFEV_DMIFV_CLOCK_CONTROL__DMIFV_DISPCLK_G_DMIFVC_GATE_DIS_MASK 0x20
+#define DCFEV_DMIFV_CLOCK_CONTROL__DMIFV_DISPCLK_G_DMIFVC_GATE_DIS__SHIFT 0x5
+#define DCFEV_DMIFV_CLOCK_CONTROL__DMIFV_SOFT_RESET_MASK 0x40
+#define DCFEV_DMIFV_CLOCK_CONTROL__DMIFV_SOFT_RESET__SHIFT 0x6
+#define DCFEV_DMIFV_CLOCK_CONTROL__DMIFV_TEST_CLK_SEL_MASK 0x1f000000
+#define DCFEV_DMIFV_CLOCK_CONTROL__DMIFV_TEST_CLK_SEL__SHIFT 0x18
+#define DCFEV_DMIFV_CLOCK_CONTROL__DMIFV_BUFFER_MODE_MASK 0x80000000
+#define DCFEV_DMIFV_CLOCK_CONTROL__DMIFV_BUFFER_MODE__SHIFT 0x1f
+#define DCFEV_DBG_CONFIG__DCFEV_DBG_EN_MASK 0x1
+#define DCFEV_DBG_CONFIG__DCFEV_DBG_EN__SHIFT 0x0
+#define DCFEV_DBG_CONFIG__DCFEV_DBG_SEL_MASK 0xf0
+#define DCFEV_DBG_CONFIG__DCFEV_DBG_SEL__SHIFT 0x4
+#define DCFEV_DMIFV_MEM_PWR_CTRL__DMIFV_MEM_PWR_SEL_MASK 0x3
+#define DCFEV_DMIFV_MEM_PWR_CTRL__DMIFV_MEM_PWR_SEL__SHIFT 0x0
+#define DCFEV_DMIFV_MEM_PWR_CTRL__DMIFV_MEM_PWR_LUMA_0_FORCE_MASK 0x4
+#define DCFEV_DMIFV_MEM_PWR_CTRL__DMIFV_MEM_PWR_LUMA_0_FORCE__SHIFT 0x2
+#define DCFEV_DMIFV_MEM_PWR_CTRL__DMIFV_MEM_PWR_LUMA_1_FORCE_MASK 0x8
+#define DCFEV_DMIFV_MEM_PWR_CTRL__DMIFV_MEM_PWR_LUMA_1_FORCE__SHIFT 0x3
+#define DCFEV_DMIFV_MEM_PWR_CTRL__DMIFV_MEM_PWR_LUMA_2_FORCE_MASK 0x10
+#define DCFEV_DMIFV_MEM_PWR_CTRL__DMIFV_MEM_PWR_LUMA_2_FORCE__SHIFT 0x4
+#define DCFEV_DMIFV_MEM_PWR_CTRL__DMIFV_MEM_PWR_LUMA_3_FORCE_MASK 0x20
+#define DCFEV_DMIFV_MEM_PWR_CTRL__DMIFV_MEM_PWR_LUMA_3_FORCE__SHIFT 0x5
+#define DCFEV_DMIFV_MEM_PWR_CTRL__DMIFV_MEM_PWR_LUMA_4_FORCE_MASK 0x40
+#define DCFEV_DMIFV_MEM_PWR_CTRL__DMIFV_MEM_PWR_LUMA_4_FORCE__SHIFT 0x6
+#define DCFEV_DMIFV_MEM_PWR_CTRL__DMIFV_MEM_PWR_CHROMA_0_FORCE_MASK 0x80
+#define DCFEV_DMIFV_MEM_PWR_CTRL__DMIFV_MEM_PWR_CHROMA_0_FORCE__SHIFT 0x7
+#define DCFEV_DMIFV_MEM_PWR_CTRL__DMIFV_MEM_PWR_CHROMA_1_FORCE_MASK 0x100
+#define DCFEV_DMIFV_MEM_PWR_CTRL__DMIFV_MEM_PWR_CHROMA_1_FORCE__SHIFT 0x8
+#define DCFEV_DMIFV_MEM_PWR_CTRL__DMIFV_MEM_PWR_CHROMA_2_FORCE_MASK 0x200
+#define DCFEV_DMIFV_MEM_PWR_CTRL__DMIFV_MEM_PWR_CHROMA_2_FORCE__SHIFT 0x9
+#define DCFEV_DMIFV_MEM_PWR_CTRL__DMIFV_MEM_PWR_CHROMA_3_FORCE_MASK 0x400
+#define DCFEV_DMIFV_MEM_PWR_CTRL__DMIFV_MEM_PWR_CHROMA_3_FORCE__SHIFT 0xa
+#define DCFEV_DMIFV_MEM_PWR_CTRL__DMIFV_MEM_PWR_CHROMA_4_FORCE_MASK 0x800
+#define DCFEV_DMIFV_MEM_PWR_CTRL__DMIFV_MEM_PWR_CHROMA_4_FORCE__SHIFT 0xb
+#define DCFEV_DMIFV_MEM_PWR_STATUS__DMIFV_MEM_PWR_LUMA_0_STATE_MASK 0x3
+#define DCFEV_DMIFV_MEM_PWR_STATUS__DMIFV_MEM_PWR_LUMA_0_STATE__SHIFT 0x0
+#define DCFEV_DMIFV_MEM_PWR_STATUS__DMIFV_MEM_PWR_LUMA_1_STATE_MASK 0xc
+#define DCFEV_DMIFV_MEM_PWR_STATUS__DMIFV_MEM_PWR_LUMA_1_STATE__SHIFT 0x2
+#define DCFEV_DMIFV_MEM_PWR_STATUS__DMIFV_MEM_PWR_LUMA_2_STATE_MASK 0x30
+#define DCFEV_DMIFV_MEM_PWR_STATUS__DMIFV_MEM_PWR_LUMA_2_STATE__SHIFT 0x4
+#define DCFEV_DMIFV_MEM_PWR_STATUS__DMIFV_MEM_PWR_LUMA_3_STATE_MASK 0xc0
+#define DCFEV_DMIFV_MEM_PWR_STATUS__DMIFV_MEM_PWR_LUMA_3_STATE__SHIFT 0x6
+#define DCFEV_DMIFV_MEM_PWR_STATUS__DMIFV_MEM_PWR_LUMA_4_STATE_MASK 0x300
+#define DCFEV_DMIFV_MEM_PWR_STATUS__DMIFV_MEM_PWR_LUMA_4_STATE__SHIFT 0x8
+#define DCFEV_DMIFV_MEM_PWR_STATUS__DMIFV_MEM_PWR_CHROMA_0_STATE_MASK 0xc00
+#define DCFEV_DMIFV_MEM_PWR_STATUS__DMIFV_MEM_PWR_CHROMA_0_STATE__SHIFT 0xa
+#define DCFEV_DMIFV_MEM_PWR_STATUS__DMIFV_MEM_PWR_CHROMA_1_STATE_MASK 0x3000
+#define DCFEV_DMIFV_MEM_PWR_STATUS__DMIFV_MEM_PWR_CHROMA_1_STATE__SHIFT 0xc
+#define DCFEV_DMIFV_MEM_PWR_STATUS__DMIFV_MEM_PWR_CHROMA_2_STATE_MASK 0xc000
+#define DCFEV_DMIFV_MEM_PWR_STATUS__DMIFV_MEM_PWR_CHROMA_2_STATE__SHIFT 0xe
+#define DCFEV_DMIFV_MEM_PWR_STATUS__DMIFV_MEM_PWR_CHROMA_3_STATE_MASK 0x30000
+#define DCFEV_DMIFV_MEM_PWR_STATUS__DMIFV_MEM_PWR_CHROMA_3_STATE__SHIFT 0x10
+#define DCFEV_DMIFV_MEM_PWR_STATUS__DMIFV_MEM_PWR_CHROMA_4_STATE_MASK 0xc0000
+#define DCFEV_DMIFV_MEM_PWR_STATUS__DMIFV_MEM_PWR_CHROMA_4_STATE__SHIFT 0x12
+#define DCFEV_MEM_PWR_CTRL__COL_MAN_GAMMA_CORR_MEM_PWR_FORCE_MASK 0x3
+#define DCFEV_MEM_PWR_CTRL__COL_MAN_GAMMA_CORR_MEM_PWR_FORCE__SHIFT 0x0
+#define DCFEV_MEM_PWR_CTRL__COL_MAN_GAMMA_CORR_MEM_PWR_DIS_MASK 0x4
+#define DCFEV_MEM_PWR_CTRL__COL_MAN_GAMMA_CORR_MEM_PWR_DIS__SHIFT 0x2
+#define DCFEV_MEM_PWR_CTRL__COL_MAN_INPUT_GAMMA_MEM_PWR_FORCE_MASK 0x18
+#define DCFEV_MEM_PWR_CTRL__COL_MAN_INPUT_GAMMA_MEM_PWR_FORCE__SHIFT 0x3
+#define DCFEV_MEM_PWR_CTRL__COL_MAN_INPUT_GAMMA_MEM_PWR_DIS_MASK 0x20
+#define DCFEV_MEM_PWR_CTRL__COL_MAN_INPUT_GAMMA_MEM_PWR_DIS__SHIFT 0x5
+#define DCFEV_MEM_PWR_CTRL__SCLV_COEFF_MEM_PWR_FORCE_MASK 0xc0
+#define DCFEV_MEM_PWR_CTRL__SCLV_COEFF_MEM_PWR_FORCE__SHIFT 0x6
+#define DCFEV_MEM_PWR_CTRL__SCLV_COEFF_MEM_PWR_DIS_MASK 0x100
+#define DCFEV_MEM_PWR_CTRL__SCLV_COEFF_MEM_PWR_DIS__SHIFT 0x8
+#define DCFEV_MEM_PWR_CTRL__LBV0_MEM_PWR_FORCE_MASK 0x600
+#define DCFEV_MEM_PWR_CTRL__LBV0_MEM_PWR_FORCE__SHIFT 0x9
+#define DCFEV_MEM_PWR_CTRL__LBV0_MEM_PWR_DIS_MASK 0x800
+#define DCFEV_MEM_PWR_CTRL__LBV0_MEM_PWR_DIS__SHIFT 0xb
+#define DCFEV_MEM_PWR_CTRL__LBV1_MEM_PWR_FORCE_MASK 0x3000
+#define DCFEV_MEM_PWR_CTRL__LBV1_MEM_PWR_FORCE__SHIFT 0xc
+#define DCFEV_MEM_PWR_CTRL__LBV1_MEM_PWR_DIS_MASK 0x4000
+#define DCFEV_MEM_PWR_CTRL__LBV1_MEM_PWR_DIS__SHIFT 0xe
+#define DCFEV_MEM_PWR_CTRL__LBV2_MEM_PWR_FORCE_MASK 0x18000
+#define DCFEV_MEM_PWR_CTRL__LBV2_MEM_PWR_FORCE__SHIFT 0xf
+#define DCFEV_MEM_PWR_CTRL__LBV2_MEM_PWR_DIS_MASK 0x20000
+#define DCFEV_MEM_PWR_CTRL__LBV2_MEM_PWR_DIS__SHIFT 0x11
+#define DCFEV_MEM_PWR_CTRL2__COL_MAN_GAMMA_CORR_MEM_PWR_MODE_SEL_MASK 0x3
+#define DCFEV_MEM_PWR_CTRL2__COL_MAN_GAMMA_CORR_MEM_PWR_MODE_SEL__SHIFT 0x0
+#define DCFEV_MEM_PWR_CTRL2__COL_MAN_INPUT_GAMMA_MEM_PWR_MODE_SEL_MASK 0xc
+#define DCFEV_MEM_PWR_CTRL2__COL_MAN_INPUT_GAMMA_MEM_PWR_MODE_SEL__SHIFT 0x2
+#define DCFEV_MEM_PWR_CTRL2__SCLV_COEFF_MEM_PWR_MODE_SEL_MASK 0x30
+#define DCFEV_MEM_PWR_CTRL2__SCLV_COEFF_MEM_PWR_MODE_SEL__SHIFT 0x4
+#define DCFEV_MEM_PWR_CTRL2__LBV_MEM_PWR_MODE_SEL_MASK 0xc0
+#define DCFEV_MEM_PWR_CTRL2__LBV_MEM_PWR_MODE_SEL__SHIFT 0x6
+#define DCFEV_MEM_PWR_STATUS__COL_MAN_GAMMA_CORR_MEM_PWR_STATE_MASK 0x3
+#define DCFEV_MEM_PWR_STATUS__COL_MAN_GAMMA_CORR_MEM_PWR_STATE__SHIFT 0x0
+#define DCFEV_MEM_PWR_STATUS__COL_MAN_INPUT_GAMMA_MEM_PWR_STATE_MASK 0xc
+#define DCFEV_MEM_PWR_STATUS__COL_MAN_INPUT_GAMMA_MEM_PWR_STATE__SHIFT 0x2
+#define DCFEV_MEM_PWR_STATUS__SCLV_COEFF_MEM_PWR_STATE_MASK 0x30
+#define DCFEV_MEM_PWR_STATUS__SCLV_COEFF_MEM_PWR_STATE__SHIFT 0x4
+#define DCFEV_MEM_PWR_STATUS__LBV0_MEM_PWR_STATE_MASK 0xc0
+#define DCFEV_MEM_PWR_STATUS__LBV0_MEM_PWR_STATE__SHIFT 0x6
+#define DCFEV_MEM_PWR_STATUS__LBV1_MEM_PWR_STATE_MASK 0x300
+#define DCFEV_MEM_PWR_STATUS__LBV1_MEM_PWR_STATE__SHIFT 0x8
+#define DCFEV_MEM_PWR_STATUS__LBV2_MEM_PWR_STATE_MASK 0xc00
+#define DCFEV_MEM_PWR_STATUS__LBV2_MEM_PWR_STATE__SHIFT 0xa
+#define DCFEV_MEM_PWR_STATUS__LBV3_MEM_PWR_STATE_MASK 0x3000
+#define DCFEV_MEM_PWR_STATUS__LBV3_MEM_PWR_STATE__SHIFT 0xc
+#define DCFEV_L_FLUSH__FLUSH_OCCURED_MASK 0x1
+#define DCFEV_L_FLUSH__FLUSH_OCCURED__SHIFT 0x0
+#define DCFEV_L_FLUSH__CLEAR_FLUSH_OCCURED_MASK 0x2
+#define DCFEV_L_FLUSH__CLEAR_FLUSH_OCCURED__SHIFT 0x1
+#define DCFEV_L_FLUSH__FLUSH_DEEP_MASK 0x4
+#define DCFEV_L_FLUSH__FLUSH_DEEP__SHIFT 0x2
+#define DCFEV_L_FLUSH__CLEAR_FLUSH_DEEP_MASK 0x8
+#define DCFEV_L_FLUSH__CLEAR_FLUSH_DEEP__SHIFT 0x3
+#define DCFEV_L_FLUSH__ALL_MC_REQ_RET_MASK 0x10
+#define DCFEV_L_FLUSH__ALL_MC_REQ_RET__SHIFT 0x4
+#define DCFEV_C_FLUSH__FLUSH_OCCURED_MASK 0x1
+#define DCFEV_C_FLUSH__FLUSH_OCCURED__SHIFT 0x0
+#define DCFEV_C_FLUSH__CLEAR_FLUSH_OCCURED_MASK 0x2
+#define DCFEV_C_FLUSH__CLEAR_FLUSH_OCCURED__SHIFT 0x1
+#define DCFEV_C_FLUSH__FLUSH_DEEP_MASK 0x4
+#define DCFEV_C_FLUSH__FLUSH_DEEP__SHIFT 0x2
+#define DCFEV_C_FLUSH__CLEAR_FLUSH_DEEP_MASK 0x8
+#define DCFEV_C_FLUSH__CLEAR_FLUSH_DEEP__SHIFT 0x3
+#define DCFEV_C_FLUSH__ALL_MC_REQ_RET_MASK 0x10
+#define DCFEV_C_FLUSH__ALL_MC_REQ_RET__SHIFT 0x4
+#define DCFEV_DMIFV_DEBUG__DMIFV_DEBUG_BUS_SEL_MASK 0xf
+#define DCFEV_DMIFV_DEBUG__DMIFV_DEBUG_BUS_SEL__SHIFT 0x0
+#define DCFEV_DMIFV_DEBUG__DMIFV_DEBUG_LUMA_VS_CHROMA_MASK 0x10
+#define DCFEV_DMIFV_DEBUG__DMIFV_DEBUG_LUMA_VS_CHROMA__SHIFT 0x4
+#define DCFEV_DMIFV_DEBUG__DMIFV_DEBUG_LOWER_UPPER_MASK 0x20
+#define DCFEV_DMIFV_DEBUG__DMIFV_DEBUG_LOWER_UPPER__SHIFT 0x5
+#define DCFEV_MISC__DCFEV_DPG_ALLOW_SR_ECO_EN_MASK 0x1
+#define DCFEV_MISC__DCFEV_DPG_ALLOW_SR_ECO_EN__SHIFT 0x0
+#define DC_HPD_INT_STATUS__DC_HPD_INT_STATUS_MASK 0x1
+#define DC_HPD_INT_STATUS__DC_HPD_INT_STATUS__SHIFT 0x0
+#define DC_HPD_INT_STATUS__DC_HPD_SENSE_MASK 0x2
+#define DC_HPD_INT_STATUS__DC_HPD_SENSE__SHIFT 0x1
+#define DC_HPD_INT_STATUS__DC_HPD_SENSE_DELAYED_MASK 0x10
+#define DC_HPD_INT_STATUS__DC_HPD_SENSE_DELAYED__SHIFT 0x4
+#define DC_HPD_INT_STATUS__DC_HPD_RX_INT_STATUS_MASK 0x100
+#define DC_HPD_INT_STATUS__DC_HPD_RX_INT_STATUS__SHIFT 0x8
+#define DC_HPD_INT_STATUS__DC_HPD_TOGGLE_FILT_CON_TIMER_VAL_MASK 0xff000
+#define DC_HPD_INT_STATUS__DC_HPD_TOGGLE_FILT_CON_TIMER_VAL__SHIFT 0xc
+#define DC_HPD_INT_STATUS__DC_HPD_TOGGLE_FILT_DISCON_TIMER_VAL_MASK 0xff000000
+#define DC_HPD_INT_STATUS__DC_HPD_TOGGLE_FILT_DISCON_TIMER_VAL__SHIFT 0x18
+#define DC_HPD_INT_CONTROL__DC_HPD_INT_ACK_MASK 0x1
+#define DC_HPD_INT_CONTROL__DC_HPD_INT_ACK__SHIFT 0x0
+#define DC_HPD_INT_CONTROL__DC_HPD_INT_POLARITY_MASK 0x100
+#define DC_HPD_INT_CONTROL__DC_HPD_INT_POLARITY__SHIFT 0x8
+#define DC_HPD_INT_CONTROL__DC_HPD_INT_EN_MASK 0x10000
+#define DC_HPD_INT_CONTROL__DC_HPD_INT_EN__SHIFT 0x10
+#define DC_HPD_INT_CONTROL__DC_HPD_RX_INT_ACK_MASK 0x100000
+#define DC_HPD_INT_CONTROL__DC_HPD_RX_INT_ACK__SHIFT 0x14
+#define DC_HPD_INT_CONTROL__DC_HPD_RX_INT_EN_MASK 0x1000000
+#define DC_HPD_INT_CONTROL__DC_HPD_RX_INT_EN__SHIFT 0x18
+#define DC_HPD_CONTROL__DC_HPD_CONNECTION_TIMER_MASK 0x1fff
+#define DC_HPD_CONTROL__DC_HPD_CONNECTION_TIMER__SHIFT 0x0
+#define DC_HPD_CONTROL__DC_HPD_RX_INT_TIMER_MASK 0x3ff0000
+#define DC_HPD_CONTROL__DC_HPD_RX_INT_TIMER__SHIFT 0x10
+#define DC_HPD_CONTROL__DC_HPD_EN_MASK 0x10000000
+#define DC_HPD_CONTROL__DC_HPD_EN__SHIFT 0x1c
+#define DC_HPD_FAST_TRAIN_CNTL__DC_HPD_CONNECT_AUX_TX_DELAY_MASK 0xff
+#define DC_HPD_FAST_TRAIN_CNTL__DC_HPD_CONNECT_AUX_TX_DELAY__SHIFT 0x0
+#define DC_HPD_FAST_TRAIN_CNTL__DC_HPD_CONNECT_FAST_TRAIN_DELAY_MASK 0xff000
+#define DC_HPD_FAST_TRAIN_CNTL__DC_HPD_CONNECT_FAST_TRAIN_DELAY__SHIFT 0xc
+#define DC_HPD_FAST_TRAIN_CNTL__DC_HPD_CONNECT_AUX_TX_EN_MASK 0x1000000
+#define DC_HPD_FAST_TRAIN_CNTL__DC_HPD_CONNECT_AUX_TX_EN__SHIFT 0x18
+#define DC_HPD_FAST_TRAIN_CNTL__DC_HPD_CONNECT_FAST_TRAIN_EN_MASK 0x10000000
+#define DC_HPD_FAST_TRAIN_CNTL__DC_HPD_CONNECT_FAST_TRAIN_EN__SHIFT 0x1c
+#define DC_HPD_TOGGLE_FILT_CNTL__DC_HPD_CONNECT_INT_DELAY_MASK 0xff
+#define DC_HPD_TOGGLE_FILT_CNTL__DC_HPD_CONNECT_INT_DELAY__SHIFT 0x0
+#define DC_HPD_TOGGLE_FILT_CNTL__DC_HPD_DISCONNECT_INT_DELAY_MASK 0xff00000
+#define DC_HPD_TOGGLE_FILT_CNTL__DC_HPD_DISCONNECT_INT_DELAY__SHIFT 0x14
+#define DCO_SCRATCH0__DCO_SCRATCH0_MASK 0xffffffff
+#define DCO_SCRATCH0__DCO_SCRATCH0__SHIFT 0x0
+#define DCO_SCRATCH1__DCO_SCRATCH1_MASK 0xffffffff
+#define DCO_SCRATCH1__DCO_SCRATCH1__SHIFT 0x0
+#define DCO_SCRATCH2__DCO_SCRATCH2_MASK 0xffffffff
+#define DCO_SCRATCH2__DCO_SCRATCH2__SHIFT 0x0
+#define DCO_SCRATCH3__DCO_SCRATCH3_MASK 0xffffffff
+#define DCO_SCRATCH3__DCO_SCRATCH3__SHIFT 0x0
+#define DCO_SCRATCH4__DCO_SCRATCH4_MASK 0xffffffff
+#define DCO_SCRATCH4__DCO_SCRATCH4__SHIFT 0x0
+#define DCO_SCRATCH5__DCO_SCRATCH5_MASK 0xffffffff
+#define DCO_SCRATCH5__DCO_SCRATCH5__SHIFT 0x0
+#define DCO_SCRATCH6__DCO_SCRATCH6_MASK 0xffffffff
+#define DCO_SCRATCH6__DCO_SCRATCH6__SHIFT 0x0
+#define DCO_SCRATCH7__DCO_SCRATCH7_MASK 0xffffffff
+#define DCO_SCRATCH7__DCO_SCRATCH7__SHIFT 0x0
+#define DCE_VCE_CONTROL__DC_VCE_VIDEO_PIPE_SELECT_MASK 0x7
+#define DCE_VCE_CONTROL__DC_VCE_VIDEO_PIPE_SELECT__SHIFT 0x0
+#define DCE_VCE_CONTROL__DC_VCE_AUDIO_STREAM_SELECT_MASK 0x70
+#define DCE_VCE_CONTROL__DC_VCE_AUDIO_STREAM_SELECT__SHIFT 0x4
+#define DISP_INTERRUPT_STATUS__SCL_DISP1_MODE_CHANGE_INTERRUPT_MASK 0x1
+#define DISP_INTERRUPT_STATUS__SCL_DISP1_MODE_CHANGE_INTERRUPT__SHIFT 0x0
+#define DISP_INTERRUPT_STATUS__D1BLND_DATA_UNDERFLOW_INTERRUPT_MASK 0x2
+#define DISP_INTERRUPT_STATUS__D1BLND_DATA_UNDERFLOW_INTERRUPT__SHIFT 0x1
+#define DISP_INTERRUPT_STATUS__LB_D1_VLINE_INTERRUPT_MASK 0x4
+#define DISP_INTERRUPT_STATUS__LB_D1_VLINE_INTERRUPT__SHIFT 0x2
+#define DISP_INTERRUPT_STATUS__LB_D1_VBLANK_INTERRUPT_MASK 0x8
+#define DISP_INTERRUPT_STATUS__LB_D1_VBLANK_INTERRUPT__SHIFT 0x3
+#define DISP_INTERRUPT_STATUS__CRTC1_SNAPSHOT_INTERRUPT_MASK 0x10
+#define DISP_INTERRUPT_STATUS__CRTC1_SNAPSHOT_INTERRUPT__SHIFT 0x4
+#define DISP_INTERRUPT_STATUS__CRTC1_FORCE_VSYNC_NEXT_LINE_INTERRUPT_MASK 0x20
+#define DISP_INTERRUPT_STATUS__CRTC1_FORCE_VSYNC_NEXT_LINE_INTERRUPT__SHIFT 0x5
+#define DISP_INTERRUPT_STATUS__CRTC1_FORCE_COUNT_NOW_INTERRUPT_MASK 0x40
+#define DISP_INTERRUPT_STATUS__CRTC1_FORCE_COUNT_NOW_INTERRUPT__SHIFT 0x6
+#define DISP_INTERRUPT_STATUS__CRTC1_TRIGA_INTERRUPT_MASK 0x80
+#define DISP_INTERRUPT_STATUS__CRTC1_TRIGA_INTERRUPT__SHIFT 0x7
+#define DISP_INTERRUPT_STATUS__CRTC1_TRIGB_INTERRUPT_MASK 0x100
+#define DISP_INTERRUPT_STATUS__CRTC1_TRIGB_INTERRUPT__SHIFT 0x8
+#define DISP_INTERRUPT_STATUS__CRTC1_VSYNC_NOM_INTERRUPT_MASK 0x200
+#define DISP_INTERRUPT_STATUS__CRTC1_VSYNC_NOM_INTERRUPT__SHIFT 0x9
+#define DISP_INTERRUPT_STATUS__CRTC1_SET_V_TOTAL_MIN_EVENT_OCCURED_INT_MASK 0x400
+#define DISP_INTERRUPT_STATUS__CRTC1_SET_V_TOTAL_MIN_EVENT_OCCURED_INT__SHIFT 0xa
+#define DISP_INTERRUPT_STATUS__DIGA_DP_FAST_TRAINING_COMPLETE_INTERRUPT_MASK 0x8000
+#define DISP_INTERRUPT_STATUS__DIGA_DP_FAST_TRAINING_COMPLETE_INTERRUPT__SHIFT 0xf
+#define DISP_INTERRUPT_STATUS__DIGA_DP_VID_STREAM_DISABLE_INTERRUPT_MASK 0x10000
+#define DISP_INTERRUPT_STATUS__DIGA_DP_VID_STREAM_DISABLE_INTERRUPT__SHIFT 0x10
+#define DISP_INTERRUPT_STATUS__DC_HPD1_INTERRUPT_MASK 0x20000
+#define DISP_INTERRUPT_STATUS__DC_HPD1_INTERRUPT__SHIFT 0x11
+#define DISP_INTERRUPT_STATUS__DC_HPD1_RX_INTERRUPT_MASK 0x40000
+#define DISP_INTERRUPT_STATUS__DC_HPD1_RX_INTERRUPT__SHIFT 0x12
+#define DISP_INTERRUPT_STATUS__AUX1_SW_DONE_INTERRUPT_MASK 0x80000
+#define DISP_INTERRUPT_STATUS__AUX1_SW_DONE_INTERRUPT__SHIFT 0x13
+#define DISP_INTERRUPT_STATUS__AUX1_LS_DONE_INTERRUPT_MASK 0x100000
+#define DISP_INTERRUPT_STATUS__AUX1_LS_DONE_INTERRUPT__SHIFT 0x14
+#define DISP_INTERRUPT_STATUS__DIGA_DISPCLK_SWITCH_ALLOWED_INTERRUPT_MASK 0x200000
+#define DISP_INTERRUPT_STATUS__DIGA_DISPCLK_SWITCH_ALLOWED_INTERRUPT__SHIFT 0x15
+#define DISP_INTERRUPT_STATUS__DACA_AUTODETECT_INTERRUPT_MASK 0x400000
+#define DISP_INTERRUPT_STATUS__DACA_AUTODETECT_INTERRUPT__SHIFT 0x16
+#define DISP_INTERRUPT_STATUS__DACB_AUTODETECT_INTERRUPT_MASK 0x800000
+#define DISP_INTERRUPT_STATUS__DACB_AUTODETECT_INTERRUPT__SHIFT 0x17
+#define DISP_INTERRUPT_STATUS__DC_I2C_SW_DONE_INTERRUPT_MASK 0x1000000
+#define DISP_INTERRUPT_STATUS__DC_I2C_SW_DONE_INTERRUPT__SHIFT 0x18
+#define DISP_INTERRUPT_STATUS__DC_I2C_HW_DONE_INTERRUPT_MASK 0x2000000
+#define DISP_INTERRUPT_STATUS__DC_I2C_HW_DONE_INTERRUPT__SHIFT 0x19
+#define DISP_INTERRUPT_STATUS__DMCU_UC_INTERNAL_INT_MASK 0x4000000
+#define DISP_INTERRUPT_STATUS__DMCU_UC_INTERNAL_INT__SHIFT 0x1a
+#define DISP_INTERRUPT_STATUS__DMCU_SCP_INT_MASK 0x8000000
+#define DISP_INTERRUPT_STATUS__DMCU_SCP_INT__SHIFT 0x1b
+#define DISP_INTERRUPT_STATUS__ABM1_HG_READY_INT_MASK 0x10000000
+#define DISP_INTERRUPT_STATUS__ABM1_HG_READY_INT__SHIFT 0x1c
+#define DISP_INTERRUPT_STATUS__ABM1_LS_READY_INT_MASK 0x20000000
+#define DISP_INTERRUPT_STATUS__ABM1_LS_READY_INT__SHIFT 0x1d
+#define DISP_INTERRUPT_STATUS__ABM1_BL_UPDATE_INT_MASK 0x40000000
+#define DISP_INTERRUPT_STATUS__ABM1_BL_UPDATE_INT__SHIFT 0x1e
+#define DISP_INTERRUPT_STATUS__DISP_INTERRUPT_STATUS_CONTINUE_MASK 0x80000000
+#define DISP_INTERRUPT_STATUS__DISP_INTERRUPT_STATUS_CONTINUE__SHIFT 0x1f
+#define DISP_INTERRUPT_STATUS_CONTINUE__SCL_DISP2_MODE_CHANGE_INTERRUPT_MASK 0x1
+#define DISP_INTERRUPT_STATUS_CONTINUE__SCL_DISP2_MODE_CHANGE_INTERRUPT__SHIFT 0x0
+#define DISP_INTERRUPT_STATUS_CONTINUE__D2BLND_DATA_UNDERFLOW_INTERRUPT_MASK 0x2
+#define DISP_INTERRUPT_STATUS_CONTINUE__D2BLND_DATA_UNDERFLOW_INTERRUPT__SHIFT 0x1
+#define DISP_INTERRUPT_STATUS_CONTINUE__LB_D2_VLINE_INTERRUPT_MASK 0x4
+#define DISP_INTERRUPT_STATUS_CONTINUE__LB_D2_VLINE_INTERRUPT__SHIFT 0x2
+#define DISP_INTERRUPT_STATUS_CONTINUE__LB_D2_VBLANK_INTERRUPT_MASK 0x8
+#define DISP_INTERRUPT_STATUS_CONTINUE__LB_D2_VBLANK_INTERRUPT__SHIFT 0x3
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_SNAPSHOT_INTERRUPT_MASK 0x10
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_SNAPSHOT_INTERRUPT__SHIFT 0x4
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_FORCE_VSYNC_NEXT_LINE_INTERRUPT_MASK 0x20
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_FORCE_VSYNC_NEXT_LINE_INTERRUPT__SHIFT 0x5
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_FORCE_COUNT_NOW_INTERRUPT_MASK 0x40
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_FORCE_COUNT_NOW_INTERRUPT__SHIFT 0x6
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_TRIGA_INTERRUPT_MASK 0x80
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_TRIGA_INTERRUPT__SHIFT 0x7
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_TRIGB_INTERRUPT_MASK 0x100
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_TRIGB_INTERRUPT__SHIFT 0x8
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_VSYNC_NOM_INTERRUPT_MASK 0x200
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_VSYNC_NOM_INTERRUPT__SHIFT 0x9
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_SET_V_TOTAL_MIN_EVENT_OCCURED_INT_MASK 0x400
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_SET_V_TOTAL_MIN_EVENT_OCCURED_INT__SHIFT 0xa
+#define DISP_INTERRUPT_STATUS_CONTINUE__DIGB_DP_FAST_TRAINING_COMPLETE_INTERRUPT_MASK 0x8000
+#define DISP_INTERRUPT_STATUS_CONTINUE__DIGB_DP_FAST_TRAINING_COMPLETE_INTERRUPT__SHIFT 0xf
+#define DISP_INTERRUPT_STATUS_CONTINUE__DIGB_DP_VID_STREAM_DISABLE_INTERRUPT_MASK 0x10000
+#define DISP_INTERRUPT_STATUS_CONTINUE__DIGB_DP_VID_STREAM_DISABLE_INTERRUPT__SHIFT 0x10
+#define DISP_INTERRUPT_STATUS_CONTINUE__DC_HPD2_INTERRUPT_MASK 0x20000
+#define DISP_INTERRUPT_STATUS_CONTINUE__DC_HPD2_INTERRUPT__SHIFT 0x11
+#define DISP_INTERRUPT_STATUS_CONTINUE__DC_HPD2_RX_INTERRUPT_MASK 0x40000
+#define DISP_INTERRUPT_STATUS_CONTINUE__DC_HPD2_RX_INTERRUPT__SHIFT 0x12
+#define DISP_INTERRUPT_STATUS_CONTINUE__AUX2_SW_DONE_INTERRUPT_MASK 0x80000
+#define DISP_INTERRUPT_STATUS_CONTINUE__AUX2_SW_DONE_INTERRUPT__SHIFT 0x13
+#define DISP_INTERRUPT_STATUS_CONTINUE__AUX2_LS_DONE_INTERRUPT_MASK 0x100000
+#define DISP_INTERRUPT_STATUS_CONTINUE__AUX2_LS_DONE_INTERRUPT__SHIFT 0x14
+#define DISP_INTERRUPT_STATUS_CONTINUE__LB_D1_VLINE2_INTERRUPT_MASK 0x200000
+#define DISP_INTERRUPT_STATUS_CONTINUE__LB_D1_VLINE2_INTERRUPT__SHIFT 0x15
+#define DISP_INTERRUPT_STATUS_CONTINUE__LB_D2_VLINE2_INTERRUPT_MASK 0x400000
+#define DISP_INTERRUPT_STATUS_CONTINUE__LB_D2_VLINE2_INTERRUPT__SHIFT 0x16
+#define DISP_INTERRUPT_STATUS_CONTINUE__LB_D3_VLINE2_INTERRUPT_MASK 0x800000
+#define DISP_INTERRUPT_STATUS_CONTINUE__LB_D3_VLINE2_INTERRUPT__SHIFT 0x17
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC1_EXT_TIMING_SYNC_LOSS_INTERRUPT_MASK 0x2000000
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC1_EXT_TIMING_SYNC_LOSS_INTERRUPT__SHIFT 0x19
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC1_EXT_TIMING_SYNC_INTERRUPT_MASK 0x4000000
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC1_EXT_TIMING_SYNC_INTERRUPT__SHIFT 0x1a
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC1_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_MASK 0x8000000
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC1_EXT_TIMING_SYNC_SIGNAL_INTERRUPT__SHIFT 0x1b
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC1_VERTICAL_INTERRUPT0_MASK 0x10000000
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC1_VERTICAL_INTERRUPT0__SHIFT 0x1c
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC1_VERTICAL_INTERRUPT1_MASK 0x20000000
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC1_VERTICAL_INTERRUPT1__SHIFT 0x1d
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC1_VERTICAL_INTERRUPT2_MASK 0x40000000
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC1_VERTICAL_INTERRUPT2__SHIFT 0x1e
+#define DISP_INTERRUPT_STATUS_CONTINUE__DISP_INTERRUPT_STATUS_CONTINUE2_MASK 0x80000000
+#define DISP_INTERRUPT_STATUS_CONTINUE__DISP_INTERRUPT_STATUS_CONTINUE2__SHIFT 0x1f
+#define DISP_INTERRUPT_STATUS_CONTINUE2__SCL_DISP3_MODE_CHANGE_INTERRUPT_MASK 0x1
+#define DISP_INTERRUPT_STATUS_CONTINUE2__SCL_DISP3_MODE_CHANGE_INTERRUPT__SHIFT 0x0
+#define DISP_INTERRUPT_STATUS_CONTINUE2__D3BLND_DATA_UNDERFLOW_INTERRUPT_MASK 0x2
+#define DISP_INTERRUPT_STATUS_CONTINUE2__D3BLND_DATA_UNDERFLOW_INTERRUPT__SHIFT 0x1
+#define DISP_INTERRUPT_STATUS_CONTINUE2__LB_D3_VLINE_INTERRUPT_MASK 0x4
+#define DISP_INTERRUPT_STATUS_CONTINUE2__LB_D3_VLINE_INTERRUPT__SHIFT 0x2
+#define DISP_INTERRUPT_STATUS_CONTINUE2__LB_D3_VBLANK_INTERRUPT_MASK 0x8
+#define DISP_INTERRUPT_STATUS_CONTINUE2__LB_D3_VBLANK_INTERRUPT__SHIFT 0x3
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_SNAPSHOT_INTERRUPT_MASK 0x10
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_SNAPSHOT_INTERRUPT__SHIFT 0x4
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_FORCE_VSYNC_NEXT_LINE_INTERRUPT_MASK 0x20
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_FORCE_VSYNC_NEXT_LINE_INTERRUPT__SHIFT 0x5
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_FORCE_COUNT_NOW_INTERRUPT_MASK 0x40
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_FORCE_COUNT_NOW_INTERRUPT__SHIFT 0x6
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_TRIGA_INTERRUPT_MASK 0x80
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_TRIGA_INTERRUPT__SHIFT 0x7
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_TRIGB_INTERRUPT_MASK 0x100
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_TRIGB_INTERRUPT__SHIFT 0x8
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_VSYNC_NOM_INTERRUPT_MASK 0x200
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_VSYNC_NOM_INTERRUPT__SHIFT 0x9
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_SET_V_TOTAL_MIN_EVENT_OCCURED_INT_MASK 0x400
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_SET_V_TOTAL_MIN_EVENT_OCCURED_INT__SHIFT 0xa
+#define DISP_INTERRUPT_STATUS_CONTINUE2__DIGC_DP_FAST_TRAINING_COMPLETE_INTERRUPT_MASK 0x8000
+#define DISP_INTERRUPT_STATUS_CONTINUE2__DIGC_DP_FAST_TRAINING_COMPLETE_INTERRUPT__SHIFT 0xf
+#define DISP_INTERRUPT_STATUS_CONTINUE2__DIGC_DP_VID_STREAM_DISABLE_INTERRUPT_MASK 0x10000
+#define DISP_INTERRUPT_STATUS_CONTINUE2__DIGC_DP_VID_STREAM_DISABLE_INTERRUPT__SHIFT 0x10
+#define DISP_INTERRUPT_STATUS_CONTINUE2__DC_HPD3_INTERRUPT_MASK 0x20000
+#define DISP_INTERRUPT_STATUS_CONTINUE2__DC_HPD3_INTERRUPT__SHIFT 0x11
+#define DISP_INTERRUPT_STATUS_CONTINUE2__DC_HPD3_RX_INTERRUPT_MASK 0x40000
+#define DISP_INTERRUPT_STATUS_CONTINUE2__DC_HPD3_RX_INTERRUPT__SHIFT 0x12
+#define DISP_INTERRUPT_STATUS_CONTINUE2__AUX3_SW_DONE_INTERRUPT_MASK 0x80000
+#define DISP_INTERRUPT_STATUS_CONTINUE2__AUX3_SW_DONE_INTERRUPT__SHIFT 0x13
+#define DISP_INTERRUPT_STATUS_CONTINUE2__AUX3_LS_DONE_INTERRUPT_MASK 0x100000
+#define DISP_INTERRUPT_STATUS_CONTINUE2__AUX3_LS_DONE_INTERRUPT__SHIFT 0x14
+#define DISP_INTERRUPT_STATUS_CONTINUE2__LB_D4_VLINE2_INTERRUPT_MASK 0x200000
+#define DISP_INTERRUPT_STATUS_CONTINUE2__LB_D4_VLINE2_INTERRUPT__SHIFT 0x15
+#define DISP_INTERRUPT_STATUS_CONTINUE2__LB_D5_VLINE2_INTERRUPT_MASK 0x400000
+#define DISP_INTERRUPT_STATUS_CONTINUE2__LB_D5_VLINE2_INTERRUPT__SHIFT 0x16
+#define DISP_INTERRUPT_STATUS_CONTINUE2__LB_D6_VLINE2_INTERRUPT_MASK 0x800000
+#define DISP_INTERRUPT_STATUS_CONTINUE2__LB_D6_VLINE2_INTERRUPT__SHIFT 0x17
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC2_EXT_TIMING_SYNC_LOSS_INTERRUPT_MASK 0x2000000
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC2_EXT_TIMING_SYNC_LOSS_INTERRUPT__SHIFT 0x19
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC2_EXT_TIMING_SYNC_INTERRUPT_MASK 0x4000000
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC2_EXT_TIMING_SYNC_INTERRUPT__SHIFT 0x1a
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC2_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_MASK 0x8000000
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC2_EXT_TIMING_SYNC_SIGNAL_INTERRUPT__SHIFT 0x1b
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC2_VERTICAL_INTERRUPT0_MASK 0x10000000
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC2_VERTICAL_INTERRUPT0__SHIFT 0x1c
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC2_VERTICAL_INTERRUPT1_MASK 0x20000000
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC2_VERTICAL_INTERRUPT1__SHIFT 0x1d
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC2_VERTICAL_INTERRUPT2_MASK 0x40000000
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC2_VERTICAL_INTERRUPT2__SHIFT 0x1e
+#define DISP_INTERRUPT_STATUS_CONTINUE2__DISP_INTERRUPT_STATUS_CONTINUE3_MASK 0x80000000
+#define DISP_INTERRUPT_STATUS_CONTINUE2__DISP_INTERRUPT_STATUS_CONTINUE3__SHIFT 0x1f
+#define DISP_INTERRUPT_STATUS_CONTINUE3__SCL_DISP4_MODE_CHANGE_INTERRUPT_MASK 0x1
+#define DISP_INTERRUPT_STATUS_CONTINUE3__SCL_DISP4_MODE_CHANGE_INTERRUPT__SHIFT 0x0
+#define DISP_INTERRUPT_STATUS_CONTINUE3__D4BLND_DATA_UNDERFLOW_INTERRUPT_MASK 0x2
+#define DISP_INTERRUPT_STATUS_CONTINUE3__D4BLND_DATA_UNDERFLOW_INTERRUPT__SHIFT 0x1
+#define DISP_INTERRUPT_STATUS_CONTINUE3__LB_D4_VLINE_INTERRUPT_MASK 0x4
+#define DISP_INTERRUPT_STATUS_CONTINUE3__LB_D4_VLINE_INTERRUPT__SHIFT 0x2
+#define DISP_INTERRUPT_STATUS_CONTINUE3__LB_D4_VBLANK_INTERRUPT_MASK 0x8
+#define DISP_INTERRUPT_STATUS_CONTINUE3__LB_D4_VBLANK_INTERRUPT__SHIFT 0x3
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_SNAPSHOT_INTERRUPT_MASK 0x10
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_SNAPSHOT_INTERRUPT__SHIFT 0x4
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_FORCE_VSYNC_NEXT_LINE_INTERRUPT_MASK 0x20
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_FORCE_VSYNC_NEXT_LINE_INTERRUPT__SHIFT 0x5
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_FORCE_COUNT_NOW_INTERRUPT_MASK 0x40
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_FORCE_COUNT_NOW_INTERRUPT__SHIFT 0x6
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_TRIGA_INTERRUPT_MASK 0x80
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_TRIGA_INTERRUPT__SHIFT 0x7
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_TRIGB_INTERRUPT_MASK 0x100
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_TRIGB_INTERRUPT__SHIFT 0x8
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_VSYNC_NOM_INTERRUPT_MASK 0x200
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_VSYNC_NOM_INTERRUPT__SHIFT 0x9
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_SET_V_TOTAL_MIN_EVENT_OCCURED_INT_MASK 0x400
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_SET_V_TOTAL_MIN_EVENT_OCCURED_INT__SHIFT 0xa
+#define DISP_INTERRUPT_STATUS_CONTINUE3__DIGD_DP_FAST_TRAINING_COMPLETE_INTERRUPT_MASK 0x8000
+#define DISP_INTERRUPT_STATUS_CONTINUE3__DIGD_DP_FAST_TRAINING_COMPLETE_INTERRUPT__SHIFT 0xf
+#define DISP_INTERRUPT_STATUS_CONTINUE3__DIGD_DP_VID_STREAM_DISABLE_INTERRUPT_MASK 0x10000
+#define DISP_INTERRUPT_STATUS_CONTINUE3__DIGD_DP_VID_STREAM_DISABLE_INTERRUPT__SHIFT 0x10
+#define DISP_INTERRUPT_STATUS_CONTINUE3__DC_HPD4_INTERRUPT_MASK 0x20000
+#define DISP_INTERRUPT_STATUS_CONTINUE3__DC_HPD4_INTERRUPT__SHIFT 0x11
+#define DISP_INTERRUPT_STATUS_CONTINUE3__DC_HPD4_RX_INTERRUPT_MASK 0x40000
+#define DISP_INTERRUPT_STATUS_CONTINUE3__DC_HPD4_RX_INTERRUPT__SHIFT 0x12
+#define DISP_INTERRUPT_STATUS_CONTINUE3__AUX4_SW_DONE_INTERRUPT_MASK 0x80000
+#define DISP_INTERRUPT_STATUS_CONTINUE3__AUX4_SW_DONE_INTERRUPT__SHIFT 0x13
+#define DISP_INTERRUPT_STATUS_CONTINUE3__AUX4_LS_DONE_INTERRUPT_MASK 0x100000
+#define DISP_INTERRUPT_STATUS_CONTINUE3__AUX4_LS_DONE_INTERRUPT__SHIFT 0x14
+#define DISP_INTERRUPT_STATUS_CONTINUE3__BUFMGR_IHIF_INTERRUPT_MASK 0x200000
+#define DISP_INTERRUPT_STATUS_CONTINUE3__BUFMGR_IHIF_INTERRUPT__SHIFT 0x15
+#define DISP_INTERRUPT_STATUS_CONTINUE3__WBSCL_HOST_CONFLICT_INTERRUPT_MASK 0x400000
+#define DISP_INTERRUPT_STATUS_CONTINUE3__WBSCL_HOST_CONFLICT_INTERRUPT__SHIFT 0x16
+#define DISP_INTERRUPT_STATUS_CONTINUE3__WBSCL_DATA_OVERFLOW_INTERRUPT_MASK 0x800000
+#define DISP_INTERRUPT_STATUS_CONTINUE3__WBSCL_DATA_OVERFLOW_INTERRUPT__SHIFT 0x17
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC3_EXT_TIMING_SYNC_LOSS_INTERRUPT_MASK 0x2000000
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC3_EXT_TIMING_SYNC_LOSS_INTERRUPT__SHIFT 0x19
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC3_EXT_TIMING_SYNC_INTERRUPT_MASK 0x4000000
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC3_EXT_TIMING_SYNC_INTERRUPT__SHIFT 0x1a
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC3_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_MASK 0x8000000
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC3_EXT_TIMING_SYNC_SIGNAL_INTERRUPT__SHIFT 0x1b
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC3_VERTICAL_INTERRUPT0_MASK 0x10000000
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC3_VERTICAL_INTERRUPT0__SHIFT 0x1c
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC3_VERTICAL_INTERRUPT1_MASK 0x20000000
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC3_VERTICAL_INTERRUPT1__SHIFT 0x1d
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC3_VERTICAL_INTERRUPT2_MASK 0x40000000
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC3_VERTICAL_INTERRUPT2__SHIFT 0x1e
+#define DISP_INTERRUPT_STATUS_CONTINUE3__DISP_INTERRUPT_STATUS_CONTINUE4_MASK 0x80000000
+#define DISP_INTERRUPT_STATUS_CONTINUE3__DISP_INTERRUPT_STATUS_CONTINUE4__SHIFT 0x1f
+#define DISP_INTERRUPT_STATUS_CONTINUE4__SCL_DISP5_MODE_CHANGE_INTERRUPT_MASK 0x1
+#define DISP_INTERRUPT_STATUS_CONTINUE4__SCL_DISP5_MODE_CHANGE_INTERRUPT__SHIFT 0x0
+#define DISP_INTERRUPT_STATUS_CONTINUE4__D5BLND_DATA_UNDERFLOW_INTERRUPT_MASK 0x2
+#define DISP_INTERRUPT_STATUS_CONTINUE4__D5BLND_DATA_UNDERFLOW_INTERRUPT__SHIFT 0x1
+#define DISP_INTERRUPT_STATUS_CONTINUE4__LB_D5_VLINE_INTERRUPT_MASK 0x4
+#define DISP_INTERRUPT_STATUS_CONTINUE4__LB_D5_VLINE_INTERRUPT__SHIFT 0x2
+#define DISP_INTERRUPT_STATUS_CONTINUE4__LB_D5_VBLANK_INTERRUPT_MASK 0x8
+#define DISP_INTERRUPT_STATUS_CONTINUE4__LB_D5_VBLANK_INTERRUPT__SHIFT 0x3
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_SNAPSHOT_INTERRUPT_MASK 0x10
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_SNAPSHOT_INTERRUPT__SHIFT 0x4
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_FORCE_VSYNC_NEXT_LINE_INTERRUPT_MASK 0x20
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_FORCE_VSYNC_NEXT_LINE_INTERRUPT__SHIFT 0x5
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_FORCE_COUNT_NOW_INTERRUPT_MASK 0x40
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_FORCE_COUNT_NOW_INTERRUPT__SHIFT 0x6
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_TRIGA_INTERRUPT_MASK 0x80
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_TRIGA_INTERRUPT__SHIFT 0x7
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_TRIGB_INTERRUPT_MASK 0x100
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_TRIGB_INTERRUPT__SHIFT 0x8
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_VSYNC_NOM_INTERRUPT_MASK 0x200
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_VSYNC_NOM_INTERRUPT__SHIFT 0x9
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_SET_V_TOTAL_MIN_EVENT_OCCURED_INT_MASK 0x400
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_SET_V_TOTAL_MIN_EVENT_OCCURED_INT__SHIFT 0xa
+#define DISP_INTERRUPT_STATUS_CONTINUE4__DIGE_DP_FAST_TRAINING_COMPLETE_INTERRUPT_MASK 0x8000
+#define DISP_INTERRUPT_STATUS_CONTINUE4__DIGE_DP_FAST_TRAINING_COMPLETE_INTERRUPT__SHIFT 0xf
+#define DISP_INTERRUPT_STATUS_CONTINUE4__DIGE_DP_VID_STREAM_DISABLE_INTERRUPT_MASK 0x10000
+#define DISP_INTERRUPT_STATUS_CONTINUE4__DIGE_DP_VID_STREAM_DISABLE_INTERRUPT__SHIFT 0x10
+#define DISP_INTERRUPT_STATUS_CONTINUE4__DC_HPD5_INTERRUPT_MASK 0x20000
+#define DISP_INTERRUPT_STATUS_CONTINUE4__DC_HPD5_INTERRUPT__SHIFT 0x11
+#define DISP_INTERRUPT_STATUS_CONTINUE4__DC_HPD5_RX_INTERRUPT_MASK 0x40000
+#define DISP_INTERRUPT_STATUS_CONTINUE4__DC_HPD5_RX_INTERRUPT__SHIFT 0x12
+#define DISP_INTERRUPT_STATUS_CONTINUE4__AUX5_SW_DONE_INTERRUPT_MASK 0x80000
+#define DISP_INTERRUPT_STATUS_CONTINUE4__AUX5_SW_DONE_INTERRUPT__SHIFT 0x13
+#define DISP_INTERRUPT_STATUS_CONTINUE4__AUX5_LS_DONE_INTERRUPT_MASK 0x100000
+#define DISP_INTERRUPT_STATUS_CONTINUE4__AUX5_LS_DONE_INTERRUPT__SHIFT 0x14
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC4_EXT_TIMING_SYNC_LOSS_INTERRUPT_MASK 0x400000
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC4_EXT_TIMING_SYNC_LOSS_INTERRUPT__SHIFT 0x16
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC4_EXT_TIMING_SYNC_INTERRUPT_MASK 0x800000
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC4_EXT_TIMING_SYNC_INTERRUPT__SHIFT 0x17
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC4_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_MASK 0x1000000
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC4_EXT_TIMING_SYNC_SIGNAL_INTERRUPT__SHIFT 0x18
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_EXT_TIMING_SYNC_LOSS_INTERRUPT_MASK 0x2000000
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_EXT_TIMING_SYNC_LOSS_INTERRUPT__SHIFT 0x19
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_EXT_TIMING_SYNC_INTERRUPT_MASK 0x4000000
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_EXT_TIMING_SYNC_INTERRUPT__SHIFT 0x1a
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_MASK 0x8000000
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_EXT_TIMING_SYNC_SIGNAL_INTERRUPT__SHIFT 0x1b
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC4_VERTICAL_INTERRUPT0_MASK 0x10000000
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC4_VERTICAL_INTERRUPT0__SHIFT 0x1c
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC4_VERTICAL_INTERRUPT1_MASK 0x20000000
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC4_VERTICAL_INTERRUPT1__SHIFT 0x1d
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC4_VERTICAL_INTERRUPT2_MASK 0x40000000
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC4_VERTICAL_INTERRUPT2__SHIFT 0x1e
+#define DISP_INTERRUPT_STATUS_CONTINUE4__DISP_INTERRUPT_STATUS_CONTINUE5_MASK 0x80000000
+#define DISP_INTERRUPT_STATUS_CONTINUE4__DISP_INTERRUPT_STATUS_CONTINUE5__SHIFT 0x1f
+#define DISP_INTERRUPT_STATUS_CONTINUE5__SCL_DISP6_MODE_CHANGE_INTERRUPT_MASK 0x1
+#define DISP_INTERRUPT_STATUS_CONTINUE5__SCL_DISP6_MODE_CHANGE_INTERRUPT__SHIFT 0x0
+#define DISP_INTERRUPT_STATUS_CONTINUE5__D6BLND_DATA_UNDERFLOW_INTERRUPT_MASK 0x2
+#define DISP_INTERRUPT_STATUS_CONTINUE5__D6BLND_DATA_UNDERFLOW_INTERRUPT__SHIFT 0x1
+#define DISP_INTERRUPT_STATUS_CONTINUE5__LB_D6_VLINE_INTERRUPT_MASK 0x4
+#define DISP_INTERRUPT_STATUS_CONTINUE5__LB_D6_VLINE_INTERRUPT__SHIFT 0x2
+#define DISP_INTERRUPT_STATUS_CONTINUE5__LB_D6_VBLANK_INTERRUPT_MASK 0x8
+#define DISP_INTERRUPT_STATUS_CONTINUE5__LB_D6_VBLANK_INTERRUPT__SHIFT 0x3
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_SNAPSHOT_INTERRUPT_MASK 0x10
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_SNAPSHOT_INTERRUPT__SHIFT 0x4
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_FORCE_VSYNC_NEXT_LINE_INTERRUPT_MASK 0x20
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_FORCE_VSYNC_NEXT_LINE_INTERRUPT__SHIFT 0x5
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_FORCE_COUNT_NOW_INTERRUPT_MASK 0x40
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_FORCE_COUNT_NOW_INTERRUPT__SHIFT 0x6
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_TRIGA_INTERRUPT_MASK 0x80
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_TRIGA_INTERRUPT__SHIFT 0x7
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_TRIGB_INTERRUPT_MASK 0x100
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_TRIGB_INTERRUPT__SHIFT 0x8
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_VSYNC_NOM_INTERRUPT_MASK 0x200
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_VSYNC_NOM_INTERRUPT__SHIFT 0x9
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_SET_V_TOTAL_MIN_EVENT_OCCURED_INT_MASK 0x400
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_SET_V_TOTAL_MIN_EVENT_OCCURED_INT__SHIFT 0xa
+#define DISP_INTERRUPT_STATUS_CONTINUE5__DIGF_DP_FAST_TRAINING_COMPLETE_INTERRUPT_MASK 0x8000
+#define DISP_INTERRUPT_STATUS_CONTINUE5__DIGF_DP_FAST_TRAINING_COMPLETE_INTERRUPT__SHIFT 0xf
+#define DISP_INTERRUPT_STATUS_CONTINUE5__DIGF_DP_VID_STREAM_DISABLE_INTERRUPT_MASK 0x10000
+#define DISP_INTERRUPT_STATUS_CONTINUE5__DIGF_DP_VID_STREAM_DISABLE_INTERRUPT__SHIFT 0x10
+#define DISP_INTERRUPT_STATUS_CONTINUE5__DC_HPD6_INTERRUPT_MASK 0x20000
+#define DISP_INTERRUPT_STATUS_CONTINUE5__DC_HPD6_INTERRUPT__SHIFT 0x11
+#define DISP_INTERRUPT_STATUS_CONTINUE5__DC_HPD6_RX_INTERRUPT_MASK 0x40000
+#define DISP_INTERRUPT_STATUS_CONTINUE5__DC_HPD6_RX_INTERRUPT__SHIFT 0x12
+#define DISP_INTERRUPT_STATUS_CONTINUE5__AUX6_SW_DONE_INTERRUPT_MASK 0x80000
+#define DISP_INTERRUPT_STATUS_CONTINUE5__AUX6_SW_DONE_INTERRUPT__SHIFT 0x13
+#define DISP_INTERRUPT_STATUS_CONTINUE5__AUX6_LS_DONE_INTERRUPT_MASK 0x100000
+#define DISP_INTERRUPT_STATUS_CONTINUE5__AUX6_LS_DONE_INTERRUPT__SHIFT 0x14
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_EXT_TIMING_SYNC_LOSS_INTERRUPT_MASK 0x400000
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_EXT_TIMING_SYNC_LOSS_INTERRUPT__SHIFT 0x16
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_EXT_TIMING_SYNC_INTERRUPT_MASK 0x800000
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_EXT_TIMING_SYNC_INTERRUPT__SHIFT 0x17
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_EXT_TIMING_SYNC_SIGNAL_INTERRUPT_MASK 0x1000000
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_EXT_TIMING_SYNC_SIGNAL_INTERRUPT__SHIFT 0x18
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC5_VERTICAL_INTERRUPT0_MASK 0x2000000
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC5_VERTICAL_INTERRUPT0__SHIFT 0x19
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC5_VERTICAL_INTERRUPT1_MASK 0x4000000
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC5_VERTICAL_INTERRUPT1__SHIFT 0x1a
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC5_VERTICAL_INTERRUPT2_MASK 0x8000000
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC5_VERTICAL_INTERRUPT2__SHIFT 0x1b
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_VERTICAL_INTERRUPT0_MASK 0x10000000
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_VERTICAL_INTERRUPT0__SHIFT 0x1c
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_VERTICAL_INTERRUPT1_MASK 0x20000000
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_VERTICAL_INTERRUPT1__SHIFT 0x1d
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_VERTICAL_INTERRUPT2_MASK 0x40000000
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_VERTICAL_INTERRUPT2__SHIFT 0x1e
+#define DISP_INTERRUPT_STATUS_CONTINUE5__DISP_INTERRUPT_STATUS_CONTINUE6_MASK 0x80000000
+#define DISP_INTERRUPT_STATUS_CONTINUE5__DISP_INTERRUPT_STATUS_CONTINUE6__SHIFT 0x1f
+#define DISP_INTERRUPT_STATUS_CONTINUE6__DCRX_PERFMON_COUNTER0_INTERRUPT_MASK 0x1
+#define DISP_INTERRUPT_STATUS_CONTINUE6__DCRX_PERFMON_COUNTER0_INTERRUPT__SHIFT 0x0
+#define DISP_INTERRUPT_STATUS_CONTINUE6__DCRX_PERFMON_COUNTER1_INTERRUPT_MASK 0x2
+#define DISP_INTERRUPT_STATUS_CONTINUE6__DCRX_PERFMON_COUNTER1_INTERRUPT__SHIFT 0x1
+#define DISP_INTERRUPT_STATUS_CONTINUE6__DCRX_PERFMON_COUNTER2_INTERRUPT_MASK 0x4
+#define DISP_INTERRUPT_STATUS_CONTINUE6__DCRX_PERFMON_COUNTER2_INTERRUPT__SHIFT 0x2
+#define DISP_INTERRUPT_STATUS_CONTINUE6__DCRX_PERFMON_COUNTER3_INTERRUPT_MASK 0x8
+#define DISP_INTERRUPT_STATUS_CONTINUE6__DCRX_PERFMON_COUNTER3_INTERRUPT__SHIFT 0x3
+#define DISP_INTERRUPT_STATUS_CONTINUE6__DCRX_PERFMON_COUNTER4_INTERRUPT_MASK 0x10
+#define DISP_INTERRUPT_STATUS_CONTINUE6__DCRX_PERFMON_COUNTER4_INTERRUPT__SHIFT 0x4
+#define DISP_INTERRUPT_STATUS_CONTINUE6__DCRX_PERFMON_COUNTER5_INTERRUPT_MASK 0x20
+#define DISP_INTERRUPT_STATUS_CONTINUE6__DCRX_PERFMON_COUNTER5_INTERRUPT__SHIFT 0x5
+#define DISP_INTERRUPT_STATUS_CONTINUE6__DCRX_PERFMON_COUNTER6_INTERRUPT_MASK 0x40
+#define DISP_INTERRUPT_STATUS_CONTINUE6__DCRX_PERFMON_COUNTER6_INTERRUPT__SHIFT 0x6
+#define DISP_INTERRUPT_STATUS_CONTINUE6__DCRX_PERFMON_COUNTER7_INTERRUPT_MASK 0x80
+#define DISP_INTERRUPT_STATUS_CONTINUE6__DCRX_PERFMON_COUNTER7_INTERRUPT__SHIFT 0x7
+#define DISP_INTERRUPT_STATUS_CONTINUE6__DCRX_PERFMON_COUNTER_OFF_INTERRUPT_MASK 0x100
+#define DISP_INTERRUPT_STATUS_CONTINUE6__DCRX_PERFMON_COUNTER_OFF_INTERRUPT__SHIFT 0x8
+#define DISP_INTERRUPT_STATUS_CONTINUE6__BUFMGR_CWB0_IHIF_INTERRUPT_MASK 0x200
+#define DISP_INTERRUPT_STATUS_CONTINUE6__BUFMGR_CWB0_IHIF_INTERRUPT__SHIFT 0x9
+#define DISP_INTERRUPT_STATUS_CONTINUE6__BUFMGR_CWB1_IHIF_INTERRUPT_MASK 0x400
+#define DISP_INTERRUPT_STATUS_CONTINUE6__BUFMGR_CWB1_IHIF_INTERRUPT__SHIFT 0xa
+#define DISP_INTERRUPT_STATUS_CONTINUE6__DIGG_DP_FAST_TRAINING_COMPLETE_INTERRUPT_MASK 0x8000
+#define DISP_INTERRUPT_STATUS_CONTINUE6__DIGG_DP_FAST_TRAINING_COMPLETE_INTERRUPT__SHIFT 0xf
+#define DISP_INTERRUPT_STATUS_CONTINUE6__DIGG_DP_VID_STREAM_DISABLE_INTERRUPT_MASK 0x10000
+#define DISP_INTERRUPT_STATUS_CONTINUE6__DIGG_DP_VID_STREAM_DISABLE_INTERRUPT__SHIFT 0x10
+#define DISP_INTERRUPT_STATUS_CONTINUE6__AUX1_GTC_SYNC_LOCK_DONE_INTERRUPT_MASK 0x20000
+#define DISP_INTERRUPT_STATUS_CONTINUE6__AUX1_GTC_SYNC_LOCK_DONE_INTERRUPT__SHIFT 0x11
+#define DISP_INTERRUPT_STATUS_CONTINUE6__AUX1_GTC_SYNC_ERROR_INTERRUPT_MASK 0x40000
+#define DISP_INTERRUPT_STATUS_CONTINUE6__AUX1_GTC_SYNC_ERROR_INTERRUPT__SHIFT 0x12
+#define DISP_INTERRUPT_STATUS_CONTINUE6__AUX2_GTC_SYNC_LOCK_DONE_INTERRUPT_MASK 0x80000
+#define DISP_INTERRUPT_STATUS_CONTINUE6__AUX2_GTC_SYNC_LOCK_DONE_INTERRUPT__SHIFT 0x13
+#define DISP_INTERRUPT_STATUS_CONTINUE6__AUX2_GTC_SYNC_ERROR_INTERRUPT_MASK 0x100000
+#define DISP_INTERRUPT_STATUS_CONTINUE6__AUX2_GTC_SYNC_ERROR_INTERRUPT__SHIFT 0x14
+#define DISP_INTERRUPT_STATUS_CONTINUE6__AUX3_GTC_SYNC_LOCK_DONE_INTERRUPT_MASK 0x200000
+#define DISP_INTERRUPT_STATUS_CONTINUE6__AUX3_GTC_SYNC_LOCK_DONE_INTERRUPT__SHIFT 0x15
+#define DISP_INTERRUPT_STATUS_CONTINUE6__AUX3_GTC_SYNC_ERROR_INTERRUPT_MASK 0x400000
+#define DISP_INTERRUPT_STATUS_CONTINUE6__AUX3_GTC_SYNC_ERROR_INTERRUPT__SHIFT 0x16
+#define DISP_INTERRUPT_STATUS_CONTINUE6__AUX4_GTC_SYNC_LOCK_DONE_INTERRUPT_MASK 0x800000
+#define DISP_INTERRUPT_STATUS_CONTINUE6__AUX4_GTC_SYNC_LOCK_DONE_INTERRUPT__SHIFT 0x17
+#define DISP_INTERRUPT_STATUS_CONTINUE6__AUX4_GTC_SYNC_ERROR_INTERRUPT_MASK 0x1000000
+#define DISP_INTERRUPT_STATUS_CONTINUE6__AUX4_GTC_SYNC_ERROR_INTERRUPT__SHIFT 0x18
+#define DISP_INTERRUPT_STATUS_CONTINUE6__AUX5_GTC_SYNC_LOCK_DONE_INTERRUPT_MASK 0x2000000
+#define DISP_INTERRUPT_STATUS_CONTINUE6__AUX5_GTC_SYNC_LOCK_DONE_INTERRUPT__SHIFT 0x19
+#define DISP_INTERRUPT_STATUS_CONTINUE6__AUX5_GTC_SYNC_ERROR_INTERRUPT_MASK 0x4000000
+#define DISP_INTERRUPT_STATUS_CONTINUE6__AUX5_GTC_SYNC_ERROR_INTERRUPT__SHIFT 0x1a
+#define DISP_INTERRUPT_STATUS_CONTINUE6__AUX6_GTC_SYNC_LOCK_DONE_INTERRUPT_MASK 0x8000000
+#define DISP_INTERRUPT_STATUS_CONTINUE6__AUX6_GTC_SYNC_LOCK_DONE_INTERRUPT__SHIFT 0x1b
+#define DISP_INTERRUPT_STATUS_CONTINUE6__AUX6_GTC_SYNC_ERROR_INTERRUPT_MASK 0x10000000
+#define DISP_INTERRUPT_STATUS_CONTINUE6__AUX6_GTC_SYNC_ERROR_INTERRUPT__SHIFT 0x1c
+#define DISP_INTERRUPT_STATUS_CONTINUE6__DISP_INTERRUPT_STATUS_CONTINUE7_MASK 0x80000000
+#define DISP_INTERRUPT_STATUS_CONTINUE6__DISP_INTERRUPT_STATUS_CONTINUE7__SHIFT 0x1f
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCCG_PERFMON_COUNTER0_INTERRUPT_MASK 0x1
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCCG_PERFMON_COUNTER0_INTERRUPT__SHIFT 0x0
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCCG_PERFMON_COUNTER1_INTERRUPT_MASK 0x2
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCCG_PERFMON_COUNTER1_INTERRUPT__SHIFT 0x1
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCCG_PERFMON_COUNTER2_INTERRUPT_MASK 0x4
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCCG_PERFMON_COUNTER2_INTERRUPT__SHIFT 0x2
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCCG_PERFMON_COUNTER3_INTERRUPT_MASK 0x8
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCCG_PERFMON_COUNTER3_INTERRUPT__SHIFT 0x3
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCCG_PERFMON_COUNTER4_INTERRUPT_MASK 0x10
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCCG_PERFMON_COUNTER4_INTERRUPT__SHIFT 0x4
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCCG_PERFMON_COUNTER5_INTERRUPT_MASK 0x20
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCCG_PERFMON_COUNTER5_INTERRUPT__SHIFT 0x5
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCCG_PERFMON_COUNTER6_INTERRUPT_MASK 0x40
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCCG_PERFMON_COUNTER6_INTERRUPT__SHIFT 0x6
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCCG_PERFMON_COUNTER7_INTERRUPT_MASK 0x80
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCCG_PERFMON_COUNTER7_INTERRUPT__SHIFT 0x7
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCCG_PERFMON_COUNTER_OFF_INTERRUPT_MASK 0x100
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCCG_PERFMON_COUNTER_OFF_INTERRUPT__SHIFT 0x8
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCI_PERFMON_COUNTER0_INTERRUPT_MASK 0x200
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCI_PERFMON_COUNTER0_INTERRUPT__SHIFT 0x9
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCI_PERFMON_COUNTER1_INTERRUPT_MASK 0x400
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCI_PERFMON_COUNTER1_INTERRUPT__SHIFT 0xa
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCI_PERFMON_COUNTER2_INTERRUPT_MASK 0x800
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCI_PERFMON_COUNTER2_INTERRUPT__SHIFT 0xb
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCI_PERFMON_COUNTER3_INTERRUPT_MASK 0x1000
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCI_PERFMON_COUNTER3_INTERRUPT__SHIFT 0xc
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCI_PERFMON_COUNTER4_INTERRUPT_MASK 0x2000
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCI_PERFMON_COUNTER4_INTERRUPT__SHIFT 0xd
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCI_PERFMON_COUNTER5_INTERRUPT_MASK 0x4000
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCI_PERFMON_COUNTER5_INTERRUPT__SHIFT 0xe
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCI_PERFMON_COUNTER6_INTERRUPT_MASK 0x8000
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCI_PERFMON_COUNTER6_INTERRUPT__SHIFT 0xf
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCI_PERFMON_COUNTER7_INTERRUPT_MASK 0x10000
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCI_PERFMON_COUNTER7_INTERRUPT__SHIFT 0x10
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCI_PERFMON_COUNTER_OFF_INTERRUPT_MASK 0x20000
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCI_PERFMON_COUNTER_OFF_INTERRUPT__SHIFT 0x11
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCO_PERFMON_COUNTER0_INTERRUPT_MASK 0x40000
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCO_PERFMON_COUNTER0_INTERRUPT__SHIFT 0x12
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCO_PERFMON_COUNTER1_INTERRUPT_MASK 0x80000
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCO_PERFMON_COUNTER1_INTERRUPT__SHIFT 0x13
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCO_PERFMON_COUNTER2_INTERRUPT_MASK 0x100000
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCO_PERFMON_COUNTER2_INTERRUPT__SHIFT 0x14
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCO_PERFMON_COUNTER3_INTERRUPT_MASK 0x200000
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCO_PERFMON_COUNTER3_INTERRUPT__SHIFT 0x15
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCO_PERFMON_COUNTER4_INTERRUPT_MASK 0x400000
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCO_PERFMON_COUNTER4_INTERRUPT__SHIFT 0x16
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCO_PERFMON_COUNTER5_INTERRUPT_MASK 0x800000
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCO_PERFMON_COUNTER5_INTERRUPT__SHIFT 0x17
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCO_PERFMON_COUNTER6_INTERRUPT_MASK 0x1000000
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCO_PERFMON_COUNTER6_INTERRUPT__SHIFT 0x18
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCO_PERFMON_COUNTER7_INTERRUPT_MASK 0x2000000
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCO_PERFMON_COUNTER7_INTERRUPT__SHIFT 0x19
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCO_PERFMON_COUNTER_OFF_INTERRUPT_MASK 0x4000000
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DCO_PERFMON_COUNTER_OFF_INTERRUPT__SHIFT 0x1a
+#define DISP_INTERRUPT_STATUS_CONTINUE7__WB_PERFMON_COUNTER0_INTERRUPT_MASK 0x8000000
+#define DISP_INTERRUPT_STATUS_CONTINUE7__WB_PERFMON_COUNTER0_INTERRUPT__SHIFT 0x1b
+#define DISP_INTERRUPT_STATUS_CONTINUE7__WB_PERFMON_COUNTER1_INTERRUPT_MASK 0x10000000
+#define DISP_INTERRUPT_STATUS_CONTINUE7__WB_PERFMON_COUNTER1_INTERRUPT__SHIFT 0x1c
+#define DISP_INTERRUPT_STATUS_CONTINUE7__WB_PERFMON_COUNTER2_INTERRUPT_MASK 0x20000000
+#define DISP_INTERRUPT_STATUS_CONTINUE7__WB_PERFMON_COUNTER2_INTERRUPT__SHIFT 0x1d
+#define DISP_INTERRUPT_STATUS_CONTINUE7__WB_PERFMON_COUNTER3_INTERRUPT_MASK 0x40000000
+#define DISP_INTERRUPT_STATUS_CONTINUE7__WB_PERFMON_COUNTER3_INTERRUPT__SHIFT 0x1e
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DISP_INTERRUPT_STATUS_CONTINUE8_MASK 0x80000000
+#define DISP_INTERRUPT_STATUS_CONTINUE7__DISP_INTERRUPT_STATUS_CONTINUE8__SHIFT 0x1f
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE0_PERFMON_COUNTER0_INTERRUPT_MASK 0x1
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE0_PERFMON_COUNTER0_INTERRUPT__SHIFT 0x0
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE0_PERFMON_COUNTER1_INTERRUPT_MASK 0x2
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE0_PERFMON_COUNTER1_INTERRUPT__SHIFT 0x1
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE0_PERFMON_COUNTER2_INTERRUPT_MASK 0x4
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE0_PERFMON_COUNTER2_INTERRUPT__SHIFT 0x2
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE0_PERFMON_COUNTER3_INTERRUPT_MASK 0x8
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE0_PERFMON_COUNTER3_INTERRUPT__SHIFT 0x3
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE0_PERFMON_COUNTER4_INTERRUPT_MASK 0x10
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE0_PERFMON_COUNTER4_INTERRUPT__SHIFT 0x4
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE0_PERFMON_COUNTER5_INTERRUPT_MASK 0x20
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE0_PERFMON_COUNTER5_INTERRUPT__SHIFT 0x5
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE0_PERFMON_COUNTER6_INTERRUPT_MASK 0x40
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE0_PERFMON_COUNTER6_INTERRUPT__SHIFT 0x6
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE0_PERFMON_COUNTER7_INTERRUPT_MASK 0x80
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE0_PERFMON_COUNTER7_INTERRUPT__SHIFT 0x7
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE0_PERFMON_COUNTER_OFF_INTERRUPT_MASK 0x100
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE0_PERFMON_COUNTER_OFF_INTERRUPT__SHIFT 0x8
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE1_PERFMON_COUNTER0_INTERRUPT_MASK 0x200
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE1_PERFMON_COUNTER0_INTERRUPT__SHIFT 0x9
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE1_PERFMON_COUNTER1_INTERRUPT_MASK 0x400
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE1_PERFMON_COUNTER1_INTERRUPT__SHIFT 0xa
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE1_PERFMON_COUNTER2_INTERRUPT_MASK 0x800
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE1_PERFMON_COUNTER2_INTERRUPT__SHIFT 0xb
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE1_PERFMON_COUNTER3_INTERRUPT_MASK 0x1000
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE1_PERFMON_COUNTER3_INTERRUPT__SHIFT 0xc
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE1_PERFMON_COUNTER4_INTERRUPT_MASK 0x2000
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE1_PERFMON_COUNTER4_INTERRUPT__SHIFT 0xd
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE1_PERFMON_COUNTER5_INTERRUPT_MASK 0x4000
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE1_PERFMON_COUNTER5_INTERRUPT__SHIFT 0xe
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE1_PERFMON_COUNTER6_INTERRUPT_MASK 0x8000
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE1_PERFMON_COUNTER6_INTERRUPT__SHIFT 0xf
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE1_PERFMON_COUNTER7_INTERRUPT_MASK 0x10000
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE1_PERFMON_COUNTER7_INTERRUPT__SHIFT 0x10
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE1_PERFMON_COUNTER_OFF_INTERRUPT_MASK 0x20000
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE1_PERFMON_COUNTER_OFF_INTERRUPT__SHIFT 0x11
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE2_PERFMON_COUNTER0_INTERRUPT_MASK 0x40000
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE2_PERFMON_COUNTER0_INTERRUPT__SHIFT 0x12
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE2_PERFMON_COUNTER1_INTERRUPT_MASK 0x80000
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE2_PERFMON_COUNTER1_INTERRUPT__SHIFT 0x13
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE2_PERFMON_COUNTER2_INTERRUPT_MASK 0x100000
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE2_PERFMON_COUNTER2_INTERRUPT__SHIFT 0x14
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE2_PERFMON_COUNTER3_INTERRUPT_MASK 0x200000
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE2_PERFMON_COUNTER3_INTERRUPT__SHIFT 0x15
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE2_PERFMON_COUNTER4_INTERRUPT_MASK 0x400000
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE2_PERFMON_COUNTER4_INTERRUPT__SHIFT 0x16
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE2_PERFMON_COUNTER5_INTERRUPT_MASK 0x800000
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE2_PERFMON_COUNTER5_INTERRUPT__SHIFT 0x17
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE2_PERFMON_COUNTER6_INTERRUPT_MASK 0x1000000
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE2_PERFMON_COUNTER6_INTERRUPT__SHIFT 0x18
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE2_PERFMON_COUNTER7_INTERRUPT_MASK 0x2000000
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE2_PERFMON_COUNTER7_INTERRUPT__SHIFT 0x19
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE2_PERFMON_COUNTER_OFF_INTERRUPT_MASK 0x4000000
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DCFE2_PERFMON_COUNTER_OFF_INTERRUPT__SHIFT 0x1a
+#define DISP_INTERRUPT_STATUS_CONTINUE8__WB_PERFMON_COUNTER4_INTERRUPT_MASK 0x8000000
+#define DISP_INTERRUPT_STATUS_CONTINUE8__WB_PERFMON_COUNTER4_INTERRUPT__SHIFT 0x1b
+#define DISP_INTERRUPT_STATUS_CONTINUE8__WB_PERFMON_COUNTER5_INTERRUPT_MASK 0x10000000
+#define DISP_INTERRUPT_STATUS_CONTINUE8__WB_PERFMON_COUNTER5_INTERRUPT__SHIFT 0x1c
+#define DISP_INTERRUPT_STATUS_CONTINUE8__WB_PERFMON_COUNTER6_INTERRUPT_MASK 0x20000000
+#define DISP_INTERRUPT_STATUS_CONTINUE8__WB_PERFMON_COUNTER6_INTERRUPT__SHIFT 0x1d
+#define DISP_INTERRUPT_STATUS_CONTINUE8__WB_PERFMON_COUNTER7_INTERRUPT_MASK 0x40000000
+#define DISP_INTERRUPT_STATUS_CONTINUE8__WB_PERFMON_COUNTER7_INTERRUPT__SHIFT 0x1e
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DISP_INTERRUPT_STATUS_CONTINUE9_MASK 0x80000000
+#define DISP_INTERRUPT_STATUS_CONTINUE8__DISP_INTERRUPT_STATUS_CONTINUE9__SHIFT 0x1f
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE3_PERFMON_COUNTER0_INTERRUPT_MASK 0x1
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE3_PERFMON_COUNTER0_INTERRUPT__SHIFT 0x0
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE3_PERFMON_COUNTER1_INTERRUPT_MASK 0x2
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE3_PERFMON_COUNTER1_INTERRUPT__SHIFT 0x1
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE3_PERFMON_COUNTER2_INTERRUPT_MASK 0x4
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE3_PERFMON_COUNTER2_INTERRUPT__SHIFT 0x2
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE3_PERFMON_COUNTER3_INTERRUPT_MASK 0x8
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE3_PERFMON_COUNTER3_INTERRUPT__SHIFT 0x3
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE3_PERFMON_COUNTER4_INTERRUPT_MASK 0x10
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE3_PERFMON_COUNTER4_INTERRUPT__SHIFT 0x4
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE3_PERFMON_COUNTER5_INTERRUPT_MASK 0x20
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE3_PERFMON_COUNTER5_INTERRUPT__SHIFT 0x5
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE3_PERFMON_COUNTER6_INTERRUPT_MASK 0x40
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE3_PERFMON_COUNTER6_INTERRUPT__SHIFT 0x6
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE3_PERFMON_COUNTER7_INTERRUPT_MASK 0x80
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE3_PERFMON_COUNTER7_INTERRUPT__SHIFT 0x7
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE3_PERFMON_COUNTER_OFF_INTERRUPT_MASK 0x100
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE3_PERFMON_COUNTER_OFF_INTERRUPT__SHIFT 0x8
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE4_PERFMON_COUNTER0_INTERRUPT_MASK 0x200
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE4_PERFMON_COUNTER0_INTERRUPT__SHIFT 0x9
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE4_PERFMON_COUNTER1_INTERRUPT_MASK 0x400
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE4_PERFMON_COUNTER1_INTERRUPT__SHIFT 0xa
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE4_PERFMON_COUNTER2_INTERRUPT_MASK 0x800
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE4_PERFMON_COUNTER2_INTERRUPT__SHIFT 0xb
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE4_PERFMON_COUNTER3_INTERRUPT_MASK 0x1000
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE4_PERFMON_COUNTER3_INTERRUPT__SHIFT 0xc
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE4_PERFMON_COUNTER4_INTERRUPT_MASK 0x2000
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE4_PERFMON_COUNTER4_INTERRUPT__SHIFT 0xd
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE4_PERFMON_COUNTER5_INTERRUPT_MASK 0x4000
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE4_PERFMON_COUNTER5_INTERRUPT__SHIFT 0xe
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE4_PERFMON_COUNTER6_INTERRUPT_MASK 0x8000
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE4_PERFMON_COUNTER6_INTERRUPT__SHIFT 0xf
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE4_PERFMON_COUNTER7_INTERRUPT_MASK 0x10000
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE4_PERFMON_COUNTER7_INTERRUPT__SHIFT 0x10
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE4_PERFMON_COUNTER_OFF_INTERRUPT_MASK 0x20000
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE4_PERFMON_COUNTER_OFF_INTERRUPT__SHIFT 0x11
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE5_PERFMON_COUNTER0_INTERRUPT_MASK 0x40000
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE5_PERFMON_COUNTER0_INTERRUPT__SHIFT 0x12
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE5_PERFMON_COUNTER1_INTERRUPT_MASK 0x80000
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE5_PERFMON_COUNTER1_INTERRUPT__SHIFT 0x13
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE5_PERFMON_COUNTER2_INTERRUPT_MASK 0x100000
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE5_PERFMON_COUNTER2_INTERRUPT__SHIFT 0x14
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE5_PERFMON_COUNTER3_INTERRUPT_MASK 0x200000
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE5_PERFMON_COUNTER3_INTERRUPT__SHIFT 0x15
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE5_PERFMON_COUNTER4_INTERRUPT_MASK 0x400000
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE5_PERFMON_COUNTER4_INTERRUPT__SHIFT 0x16
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE5_PERFMON_COUNTER5_INTERRUPT_MASK 0x800000
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE5_PERFMON_COUNTER5_INTERRUPT__SHIFT 0x17
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE5_PERFMON_COUNTER6_INTERRUPT_MASK 0x1000000
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE5_PERFMON_COUNTER6_INTERRUPT__SHIFT 0x18
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE5_PERFMON_COUNTER7_INTERRUPT_MASK 0x2000000
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE5_PERFMON_COUNTER7_INTERRUPT__SHIFT 0x19
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE5_PERFMON_COUNTER_OFF_INTERRUPT_MASK 0x4000000
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DCFE5_PERFMON_COUNTER_OFF_INTERRUPT__SHIFT 0x1a
+#define DISP_INTERRUPT_STATUS_CONTINUE9__WB_PERFMON_COUNTER_OFF_INTERRUPT_MASK 0x8000000
+#define DISP_INTERRUPT_STATUS_CONTINUE9__WB_PERFMON_COUNTER_OFF_INTERRUPT__SHIFT 0x1b
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DISP_INTERRUPT_STATUS_CONTINUE10_MASK 0x80000000
+#define DISP_INTERRUPT_STATUS_CONTINUE9__DISP_INTERRUPT_STATUS_CONTINUE10__SHIFT 0x1f
+#define DISP_INTERRUPT_STATUS_CONTINUE10__DIGLPA_DP_FAST_TRAINING_COMPLETE_INTERRUPT_MASK 0x10
+#define DISP_INTERRUPT_STATUS_CONTINUE10__DIGLPA_DP_FAST_TRAINING_COMPLETE_INTERRUPT__SHIFT 0x4
+#define DISP_INTERRUPT_STATUS_CONTINUE10__DIGLPA_DP_VID_STREAM_DISABLE_INTERRUPT_MASK 0x20
+#define DISP_INTERRUPT_STATUS_CONTINUE10__DIGLPA_DP_VID_STREAM_DISABLE_INTERRUPT__SHIFT 0x5
+#define DISP_INTERRUPT_STATUS_CONTINUE10__DIGLPB_DP_FAST_TRAINING_COMPLETE_INTERRUPT_MASK 0x400
+#define DISP_INTERRUPT_STATUS_CONTINUE10__DIGLPB_DP_FAST_TRAINING_COMPLETE_INTERRUPT__SHIFT 0xa
+#define DISP_INTERRUPT_STATUS_CONTINUE10__DIGLPB_DP_VID_STREAM_DISABLE_INTERRUPT_MASK 0x800
+#define DISP_INTERRUPT_STATUS_CONTINUE10__DIGLPB_DP_VID_STREAM_DISABLE_INTERRUPT__SHIFT 0xb
+#define DISP_INTERRUPT_STATUS_CONTINUE10__DCCG_PERFMON2_COUNTER0_INTERRUPT_MASK 0x1000
+#define DISP_INTERRUPT_STATUS_CONTINUE10__DCCG_PERFMON2_COUNTER0_INTERRUPT__SHIFT 0xc
+#define DISP_INTERRUPT_STATUS_CONTINUE10__DCCG_PERFMON2_COUNTER1_INTERRUPT_MASK 0x2000
+#define DISP_INTERRUPT_STATUS_CONTINUE10__DCCG_PERFMON2_COUNTER1_INTERRUPT__SHIFT 0xd
+#define DISP_INTERRUPT_STATUS_CONTINUE10__DCCG_PERFMON2_COUNTER2_INTERRUPT_MASK 0x4000
+#define DISP_INTERRUPT_STATUS_CONTINUE10__DCCG_PERFMON2_COUNTER2_INTERRUPT__SHIFT 0xe
+#define DISP_INTERRUPT_STATUS_CONTINUE10__DCCG_PERFMON2_COUNTER3_INTERRUPT_MASK 0x8000
+#define DISP_INTERRUPT_STATUS_CONTINUE10__DCCG_PERFMON2_COUNTER3_INTERRUPT__SHIFT 0xf
+#define DISP_INTERRUPT_STATUS_CONTINUE10__DCCG_PERFMON2_COUNTER4_INTERRUPT_MASK 0x10000
+#define DISP_INTERRUPT_STATUS_CONTINUE10__DCCG_PERFMON2_COUNTER4_INTERRUPT__SHIFT 0x10
+#define DISP_INTERRUPT_STATUS_CONTINUE10__DCCG_PERFMON2_COUNTER5_INTERRUPT_MASK 0x20000
+#define DISP_INTERRUPT_STATUS_CONTINUE10__DCCG_PERFMON2_COUNTER5_INTERRUPT__SHIFT 0x11
+#define DISP_INTERRUPT_STATUS_CONTINUE10__DCCG_PERFMON2_COUNTER6_INTERRUPT_MASK 0x40000
+#define DISP_INTERRUPT_STATUS_CONTINUE10__DCCG_PERFMON2_COUNTER6_INTERRUPT__SHIFT 0x12
+#define DISP_INTERRUPT_STATUS_CONTINUE10__DCCG_PERFMON2_COUNTER7_INTERRUPT_MASK 0x80000
+#define DISP_INTERRUPT_STATUS_CONTINUE10__DCCG_PERFMON2_COUNTER7_INTERRUPT__SHIFT 0x13
+#define DISP_INTERRUPT_STATUS_CONTINUE10__DCCG_PERFMON2_COUNTER_OFF_INTERRUPT_MASK 0x100000
+#define DISP_INTERRUPT_STATUS_CONTINUE10__DCCG_PERFMON2_COUNTER_OFF_INTERRUPT__SHIFT 0x14
+#define DCO_MEM_PWR_STATUS__I2C_MEM_PWR_STATE_MASK 0x1
+#define DCO_MEM_PWR_STATUS__I2C_MEM_PWR_STATE__SHIFT 0x0
+#define DCO_MEM_PWR_STATUS__MVP_MEM_PWR_STATE_MASK 0x4
+#define DCO_MEM_PWR_STATUS__MVP_MEM_PWR_STATE__SHIFT 0x2
+#define DCO_MEM_PWR_STATUS__DPA_MEM_PWR_STATE_MASK 0x8
+#define DCO_MEM_PWR_STATUS__DPA_MEM_PWR_STATE__SHIFT 0x3
+#define DCO_MEM_PWR_STATUS__DPB_MEM_PWR_STATE_MASK 0x10
+#define DCO_MEM_PWR_STATUS__DPB_MEM_PWR_STATE__SHIFT 0x4
+#define DCO_MEM_PWR_STATUS__DPC_MEM_PWR_STATE_MASK 0x20
+#define DCO_MEM_PWR_STATUS__DPC_MEM_PWR_STATE__SHIFT 0x5
+#define DCO_MEM_PWR_STATUS__DPD_MEM_PWR_STATE_MASK 0x40
+#define DCO_MEM_PWR_STATUS__DPD_MEM_PWR_STATE__SHIFT 0x6
+#define DCO_MEM_PWR_STATUS__DPE_MEM_PWR_STATE_MASK 0x80
+#define DCO_MEM_PWR_STATUS__DPE_MEM_PWR_STATE__SHIFT 0x7
+#define DCO_MEM_PWR_STATUS__DPF_MEM_PWR_STATE_MASK 0x100
+#define DCO_MEM_PWR_STATUS__DPF_MEM_PWR_STATE__SHIFT 0x8
+#define DCO_MEM_PWR_STATUS__DPG_MEM_PWR_STATE_MASK 0x200
+#define DCO_MEM_PWR_STATUS__DPG_MEM_PWR_STATE__SHIFT 0x9
+#define DCO_MEM_PWR_STATUS__HDMI0_MEM_PWR_STATE_MASK 0xc00
+#define DCO_MEM_PWR_STATUS__HDMI0_MEM_PWR_STATE__SHIFT 0xa
+#define DCO_MEM_PWR_STATUS__HDMI1_MEM_PWR_STATE_MASK 0x3000
+#define DCO_MEM_PWR_STATUS__HDMI1_MEM_PWR_STATE__SHIFT 0xc
+#define DCO_MEM_PWR_STATUS__HDMI2_MEM_PWR_STATE_MASK 0xc000
+#define DCO_MEM_PWR_STATUS__HDMI2_MEM_PWR_STATE__SHIFT 0xe
+#define DCO_MEM_PWR_STATUS__HDMI3_MEM_PWR_STATE_MASK 0x30000
+#define DCO_MEM_PWR_STATUS__HDMI3_MEM_PWR_STATE__SHIFT 0x10
+#define DCO_MEM_PWR_STATUS__HDMI4_MEM_PWR_STATE_MASK 0xc0000
+#define DCO_MEM_PWR_STATUS__HDMI4_MEM_PWR_STATE__SHIFT 0x12
+#define DCO_MEM_PWR_STATUS__HDMI5_MEM_PWR_STATE_MASK 0x300000
+#define DCO_MEM_PWR_STATUS__HDMI5_MEM_PWR_STATE__SHIFT 0x14
+#define DCO_MEM_PWR_STATUS__HDMI6_MEM_PWR_STATE_MASK 0xc00000
+#define DCO_MEM_PWR_STATUS__HDMI6_MEM_PWR_STATE__SHIFT 0x16
+#define DCO_MEM_PWR_STATUS1__DPLPA_MEM_PWR_STATE_MASK 0x1
+#define DCO_MEM_PWR_STATUS1__DPLPA_MEM_PWR_STATE__SHIFT 0x0
+#define DCO_MEM_PWR_STATUS1__DPLPB_MEM_PWR_STATE_MASK 0x2
+#define DCO_MEM_PWR_STATUS1__DPLPB_MEM_PWR_STATE__SHIFT 0x1
+#define DCO_MEM_PWR_STATUS1__HDMILP0_MEM_PWR_STATE_MASK 0xc00
+#define DCO_MEM_PWR_STATUS1__HDMILP0_MEM_PWR_STATE__SHIFT 0xa
+#define DCO_MEM_PWR_STATUS1__HDMILP1_MEM_PWR_STATE_MASK 0x3000
+#define DCO_MEM_PWR_STATUS1__HDMILP1_MEM_PWR_STATE__SHIFT 0xc
+#define DCO_MEM_PWR_CTRL__I2C_LIGHT_SLEEP_FORCE_MASK 0x1
+#define DCO_MEM_PWR_CTRL__I2C_LIGHT_SLEEP_FORCE__SHIFT 0x0
+#define DCO_MEM_PWR_CTRL__I2C_LIGHT_SLEEP_DIS_MASK 0x2
+#define DCO_MEM_PWR_CTRL__I2C_LIGHT_SLEEP_DIS__SHIFT 0x1
+#define DCO_MEM_PWR_CTRL__MVP_LIGHT_SLEEP_DIS_MASK 0x8
+#define DCO_MEM_PWR_CTRL__MVP_LIGHT_SLEEP_DIS__SHIFT 0x3
+#define DCO_MEM_PWR_CTRL__DPA_LIGHT_SLEEP_DIS_MASK 0x10
+#define DCO_MEM_PWR_CTRL__DPA_LIGHT_SLEEP_DIS__SHIFT 0x4
+#define DCO_MEM_PWR_CTRL__DPB_LIGHT_SLEEP_DIS_MASK 0x20
+#define DCO_MEM_PWR_CTRL__DPB_LIGHT_SLEEP_DIS__SHIFT 0x5
+#define DCO_MEM_PWR_CTRL__DPC_LIGHT_SLEEP_DIS_MASK 0x40
+#define DCO_MEM_PWR_CTRL__DPC_LIGHT_SLEEP_DIS__SHIFT 0x6
+#define DCO_MEM_PWR_CTRL__DPD_LIGHT_SLEEP_DIS_MASK 0x80
+#define DCO_MEM_PWR_CTRL__DPD_LIGHT_SLEEP_DIS__SHIFT 0x7
+#define DCO_MEM_PWR_CTRL__DPE_LIGHT_SLEEP_DIS_MASK 0x100
+#define DCO_MEM_PWR_CTRL__DPE_LIGHT_SLEEP_DIS__SHIFT 0x8
+#define DCO_MEM_PWR_CTRL__DPF_LIGHT_SLEEP_DIS_MASK 0x200
+#define DCO_MEM_PWR_CTRL__DPF_LIGHT_SLEEP_DIS__SHIFT 0x9
+#define DCO_MEM_PWR_CTRL__DPG_LIGHT_SLEEP_DIS_MASK 0x400
+#define DCO_MEM_PWR_CTRL__DPG_LIGHT_SLEEP_DIS__SHIFT 0xa
+#define DCO_MEM_PWR_CTRL__HDMI0_MEM_PWR_FORCE_MASK 0x1800
+#define DCO_MEM_PWR_CTRL__HDMI0_MEM_PWR_FORCE__SHIFT 0xb
+#define DCO_MEM_PWR_CTRL__HDMI0_MEM_PWR_DIS_MASK 0x2000
+#define DCO_MEM_PWR_CTRL__HDMI0_MEM_PWR_DIS__SHIFT 0xd
+#define DCO_MEM_PWR_CTRL__HDMI1_MEM_PWR_FORCE_MASK 0xc000
+#define DCO_MEM_PWR_CTRL__HDMI1_MEM_PWR_FORCE__SHIFT 0xe
+#define DCO_MEM_PWR_CTRL__HDMI1_MEM_PWR_DIS_MASK 0x10000
+#define DCO_MEM_PWR_CTRL__HDMI1_MEM_PWR_DIS__SHIFT 0x10
+#define DCO_MEM_PWR_CTRL__HDMI2_MEM_PWR_FORCE_MASK 0x60000
+#define DCO_MEM_PWR_CTRL__HDMI2_MEM_PWR_FORCE__SHIFT 0x11
+#define DCO_MEM_PWR_CTRL__HDMI2_MEM_PWR_DIS_MASK 0x80000
+#define DCO_MEM_PWR_CTRL__HDMI2_MEM_PWR_DIS__SHIFT 0x13
+#define DCO_MEM_PWR_CTRL__HDMI3_MEM_PWR_FORCE_MASK 0x300000
+#define DCO_MEM_PWR_CTRL__HDMI3_MEM_PWR_FORCE__SHIFT 0x14
+#define DCO_MEM_PWR_CTRL__HDMI3_MEM_PWR_DIS_MASK 0x400000
+#define DCO_MEM_PWR_CTRL__HDMI3_MEM_PWR_DIS__SHIFT 0x16
+#define DCO_MEM_PWR_CTRL__HDMI4_MEM_PWR_FORCE_MASK 0x1800000
+#define DCO_MEM_PWR_CTRL__HDMI4_MEM_PWR_FORCE__SHIFT 0x17
+#define DCO_MEM_PWR_CTRL__HDMI4_MEM_PWR_DIS_MASK 0x2000000
+#define DCO_MEM_PWR_CTRL__HDMI4_MEM_PWR_DIS__SHIFT 0x19
+#define DCO_MEM_PWR_CTRL__HDMI5_MEM_PWR_FORCE_MASK 0xc000000
+#define DCO_MEM_PWR_CTRL__HDMI5_MEM_PWR_FORCE__SHIFT 0x1a
+#define DCO_MEM_PWR_CTRL__HDMI5_MEM_PWR_DIS_MASK 0x10000000
+#define DCO_MEM_PWR_CTRL__HDMI5_MEM_PWR_DIS__SHIFT 0x1c
+#define DCO_MEM_PWR_CTRL__HDMI6_MEM_PWR_FORCE_MASK 0x60000000
+#define DCO_MEM_PWR_CTRL__HDMI6_MEM_PWR_FORCE__SHIFT 0x1d
+#define DCO_MEM_PWR_CTRL__HDMI6_MEM_PWR_DIS_MASK 0x80000000
+#define DCO_MEM_PWR_CTRL__HDMI6_MEM_PWR_DIS__SHIFT 0x1f
+#define DCO_MEM_PWR_CTRL2__HDMI_MEM_PWR_MODE_SEL_MASK 0x3
+#define DCO_MEM_PWR_CTRL2__HDMI_MEM_PWR_MODE_SEL__SHIFT 0x0
+#define DCO_MEM_PWR_CTRL2__DPLPA_LIGHT_SLEEP_DIS_MASK 0x4
+#define DCO_MEM_PWR_CTRL2__DPLPA_LIGHT_SLEEP_DIS__SHIFT 0x2
+#define DCO_MEM_PWR_CTRL2__DPLPB_LIGHT_SLEEP_DIS_MASK 0x8
+#define DCO_MEM_PWR_CTRL2__DPLPB_LIGHT_SLEEP_DIS__SHIFT 0x3
+#define DCO_MEM_PWR_CTRL2__HDMILP0_MEM_PWR_FORCE_MASK 0x30000
+#define DCO_MEM_PWR_CTRL2__HDMILP0_MEM_PWR_FORCE__SHIFT 0x10
+#define DCO_MEM_PWR_CTRL2__HDMILP0_MEM_PWR_DIS_MASK 0x40000
+#define DCO_MEM_PWR_CTRL2__HDMILP0_MEM_PWR_DIS__SHIFT 0x12
+#define DCO_MEM_PWR_CTRL2__HDMILP1_MEM_PWR_FORCE_MASK 0x180000
+#define DCO_MEM_PWR_CTRL2__HDMILP1_MEM_PWR_FORCE__SHIFT 0x13
+#define DCO_MEM_PWR_CTRL2__HDMILP1_MEM_PWR_DIS_MASK 0x200000
+#define DCO_MEM_PWR_CTRL2__HDMILP1_MEM_PWR_DIS__SHIFT 0x15
+#define FMT_MEMORY0_CONTROL__FMT420_MEM0_SOURCE_SEL_MASK 0x7
+#define FMT_MEMORY0_CONTROL__FMT420_MEM0_SOURCE_SEL__SHIFT 0x0
+#define FMT_MEMORY0_CONTROL__FMT420_MEM0_PWR_FORCE_MASK 0x30
+#define FMT_MEMORY0_CONTROL__FMT420_MEM0_PWR_FORCE__SHIFT 0x4
+#define FMT_MEMORY0_CONTROL__FMT420_MEM0_PWR_DIS_MASK 0x100
+#define FMT_MEMORY0_CONTROL__FMT420_MEM0_PWR_DIS__SHIFT 0x8
+#define FMT_MEMORY0_CONTROL__FMT420_MEM0_PWR_STATE_MASK 0x3000
+#define FMT_MEMORY0_CONTROL__FMT420_MEM0_PWR_STATE__SHIFT 0xc
+#define FMT_MEMORY1_CONTROL__FMT420_MEM1_SOURCE_SEL_MASK 0x7
+#define FMT_MEMORY1_CONTROL__FMT420_MEM1_SOURCE_SEL__SHIFT 0x0
+#define FMT_MEMORY1_CONTROL__FMT420_MEM1_PWR_FORCE_MASK 0x30
+#define FMT_MEMORY1_CONTROL__FMT420_MEM1_PWR_FORCE__SHIFT 0x4
+#define FMT_MEMORY1_CONTROL__FMT420_MEM1_PWR_DIS_MASK 0x100
+#define FMT_MEMORY1_CONTROL__FMT420_MEM1_PWR_DIS__SHIFT 0x8
+#define FMT_MEMORY1_CONTROL__FMT420_MEM1_PWR_STATE_MASK 0x3000
+#define FMT_MEMORY1_CONTROL__FMT420_MEM1_PWR_STATE__SHIFT 0xc
+#define FMT_MEMORY2_CONTROL__FMT420_MEM2_SOURCE_SEL_MASK 0x7
+#define FMT_MEMORY2_CONTROL__FMT420_MEM2_SOURCE_SEL__SHIFT 0x0
+#define FMT_MEMORY2_CONTROL__FMT420_MEM2_PWR_FORCE_MASK 0x30
+#define FMT_MEMORY2_CONTROL__FMT420_MEM2_PWR_FORCE__SHIFT 0x4
+#define FMT_MEMORY2_CONTROL__FMT420_MEM2_PWR_DIS_MASK 0x100
+#define FMT_MEMORY2_CONTROL__FMT420_MEM2_PWR_DIS__SHIFT 0x8
+#define FMT_MEMORY2_CONTROL__FMT420_MEM2_PWR_STATE_MASK 0x3000
+#define FMT_MEMORY2_CONTROL__FMT420_MEM2_PWR_STATE__SHIFT 0xc
+#define FMT_MEMORY3_CONTROL__FMT420_MEM3_SOURCE_SEL_MASK 0x7
+#define FMT_MEMORY3_CONTROL__FMT420_MEM3_SOURCE_SEL__SHIFT 0x0
+#define FMT_MEMORY3_CONTROL__FMT420_MEM3_PWR_FORCE_MASK 0x30
+#define FMT_MEMORY3_CONTROL__FMT420_MEM3_PWR_FORCE__SHIFT 0x4
+#define FMT_MEMORY3_CONTROL__FMT420_MEM3_PWR_DIS_MASK 0x100
+#define FMT_MEMORY3_CONTROL__FMT420_MEM3_PWR_DIS__SHIFT 0x8
+#define FMT_MEMORY3_CONTROL__FMT420_MEM3_PWR_STATE_MASK 0x3000
+#define FMT_MEMORY3_CONTROL__FMT420_MEM3_PWR_STATE__SHIFT 0xc
+#define FMT_MEMORY4_CONTROL__FMT420_MEM4_SOURCE_SEL_MASK 0x7
+#define FMT_MEMORY4_CONTROL__FMT420_MEM4_SOURCE_SEL__SHIFT 0x0
+#define FMT_MEMORY4_CONTROL__FMT420_MEM4_PWR_FORCE_MASK 0x30
+#define FMT_MEMORY4_CONTROL__FMT420_MEM4_PWR_FORCE__SHIFT 0x4
+#define FMT_MEMORY4_CONTROL__FMT420_MEM4_PWR_DIS_MASK 0x100
+#define FMT_MEMORY4_CONTROL__FMT420_MEM4_PWR_DIS__SHIFT 0x8
+#define FMT_MEMORY4_CONTROL__FMT420_MEM4_PWR_STATE_MASK 0x3000
+#define FMT_MEMORY4_CONTROL__FMT420_MEM4_PWR_STATE__SHIFT 0xc
+#define FMT_MEMORY5_CONTROL__FMT420_MEM5_SOURCE_SEL_MASK 0x7
+#define FMT_MEMORY5_CONTROL__FMT420_MEM5_SOURCE_SEL__SHIFT 0x0
+#define FMT_MEMORY5_CONTROL__FMT420_MEM5_PWR_FORCE_MASK 0x30
+#define FMT_MEMORY5_CONTROL__FMT420_MEM5_PWR_FORCE__SHIFT 0x4
+#define FMT_MEMORY5_CONTROL__FMT420_MEM5_PWR_DIS_MASK 0x100
+#define FMT_MEMORY5_CONTROL__FMT420_MEM5_PWR_DIS__SHIFT 0x8
+#define FMT_MEMORY5_CONTROL__FMT420_MEM5_PWR_STATE_MASK 0x3000
+#define FMT_MEMORY5_CONTROL__FMT420_MEM5_PWR_STATE__SHIFT 0xc
+#define DCO_CLK_CNTL__DISPCLK_R_DCO_GATE_DIS_MASK 0x20
+#define DCO_CLK_CNTL__DISPCLK_R_DCO_GATE_DIS__SHIFT 0x5
+#define DCO_CLK_CNTL__DISPCLK_G_ABM_GATE_DIS_MASK 0x40
+#define DCO_CLK_CNTL__DISPCLK_G_ABM_GATE_DIS__SHIFT 0x6
+#define DCO_CLK_CNTL__DISPCLK_G_DVO_GATE_DIS_MASK 0x80
+#define DCO_CLK_CNTL__DISPCLK_G_DVO_GATE_DIS__SHIFT 0x7
+#define DCO_CLK_CNTL__DISPCLK_G_DACA_GATE_DIS_MASK 0x100
+#define DCO_CLK_CNTL__DISPCLK_G_DACA_GATE_DIS__SHIFT 0x8
+#define DCO_CLK_CNTL__DISPCLK_G_DACB_GATE_DIS_MASK 0x200
+#define DCO_CLK_CNTL__DISPCLK_G_DACB_GATE_DIS__SHIFT 0x9
+#define DCO_CLK_CNTL__REFCLK_R_DCO_GATE_DIS_MASK 0x400
+#define DCO_CLK_CNTL__REFCLK_R_DCO_GATE_DIS__SHIFT 0xa
+#define DCO_CLK_CNTL__DISPCLK_G_FMT0_GATE_DIS_MASK 0x10000
+#define DCO_CLK_CNTL__DISPCLK_G_FMT0_GATE_DIS__SHIFT 0x10
+#define DCO_CLK_CNTL__DISPCLK_G_FMT1_GATE_DIS_MASK 0x20000
+#define DCO_CLK_CNTL__DISPCLK_G_FMT1_GATE_DIS__SHIFT 0x11
+#define DCO_CLK_CNTL__DISPCLK_G_FMT2_GATE_DIS_MASK 0x40000
+#define DCO_CLK_CNTL__DISPCLK_G_FMT2_GATE_DIS__SHIFT 0x12
+#define DCO_CLK_CNTL__DISPCLK_G_FMT3_GATE_DIS_MASK 0x80000
+#define DCO_CLK_CNTL__DISPCLK_G_FMT3_GATE_DIS__SHIFT 0x13
+#define DCO_CLK_CNTL__DISPCLK_G_FMT4_GATE_DIS_MASK 0x100000
+#define DCO_CLK_CNTL__DISPCLK_G_FMT4_GATE_DIS__SHIFT 0x14
+#define DCO_CLK_CNTL__DISPCLK_G_FMT5_GATE_DIS_MASK 0x200000
+#define DCO_CLK_CNTL__DISPCLK_G_FMT5_GATE_DIS__SHIFT 0x15
+#define DCO_CLK_CNTL__DISPCLK_G_DIGLPA_GATE_DIS_MASK 0x400000
+#define DCO_CLK_CNTL__DISPCLK_G_DIGLPA_GATE_DIS__SHIFT 0x16
+#define DCO_CLK_CNTL__DISPCLK_G_DIGLPB_GATE_DIS_MASK 0x800000
+#define DCO_CLK_CNTL__DISPCLK_G_DIGLPB_GATE_DIS__SHIFT 0x17
+#define DCO_CLK_CNTL__DISPCLK_G_DIGA_GATE_DIS_MASK 0x1000000
+#define DCO_CLK_CNTL__DISPCLK_G_DIGA_GATE_DIS__SHIFT 0x18
+#define DCO_CLK_CNTL__DISPCLK_G_DIGB_GATE_DIS_MASK 0x2000000
+#define DCO_CLK_CNTL__DISPCLK_G_DIGB_GATE_DIS__SHIFT 0x19
+#define DCO_CLK_CNTL__DISPCLK_G_DIGC_GATE_DIS_MASK 0x4000000
+#define DCO_CLK_CNTL__DISPCLK_G_DIGC_GATE_DIS__SHIFT 0x1a
+#define DCO_CLK_CNTL__DISPCLK_G_DIGD_GATE_DIS_MASK 0x8000000
+#define DCO_CLK_CNTL__DISPCLK_G_DIGD_GATE_DIS__SHIFT 0x1b
+#define DCO_CLK_CNTL__DISPCLK_G_DIGE_GATE_DIS_MASK 0x10000000
+#define DCO_CLK_CNTL__DISPCLK_G_DIGE_GATE_DIS__SHIFT 0x1c
+#define DCO_CLK_CNTL__DISPCLK_G_DIGF_GATE_DIS_MASK 0x20000000
+#define DCO_CLK_CNTL__DISPCLK_G_DIGF_GATE_DIS__SHIFT 0x1d
+#define DCO_CLK_CNTL__DISPCLK_G_DIGG_GATE_DIS_MASK 0x40000000
+#define DCO_CLK_CNTL__DISPCLK_G_DIGG_GATE_DIS__SHIFT 0x1e
+#define DCO_CLK_CNTL2__DCO_TEST_CLK_SEL_MASK 0x7f
+#define DCO_CLK_CNTL2__DCO_TEST_CLK_SEL__SHIFT 0x0
+#define DCO_CLK_CNTL2__SCLK_G_AFMTA_GATE_DIS_MASK 0x80
+#define DCO_CLK_CNTL2__SCLK_G_AFMTA_GATE_DIS__SHIFT 0x7
+#define DCO_CLK_CNTL2__SCLK_G_AFMTB_GATE_DIS_MASK 0x100
+#define DCO_CLK_CNTL2__SCLK_G_AFMTB_GATE_DIS__SHIFT 0x8
+#define DCO_CLK_CNTL2__SCLK_G_AFMTC_GATE_DIS_MASK 0x200
+#define DCO_CLK_CNTL2__SCLK_G_AFMTC_GATE_DIS__SHIFT 0x9
+#define DCO_CLK_CNTL2__SCLK_G_AFMTD_GATE_DIS_MASK 0x400
+#define DCO_CLK_CNTL2__SCLK_G_AFMTD_GATE_DIS__SHIFT 0xa
+#define DCO_CLK_CNTL2__SCLK_G_AFMTE_GATE_DIS_MASK 0x800
+#define DCO_CLK_CNTL2__SCLK_G_AFMTE_GATE_DIS__SHIFT 0xb
+#define DCO_CLK_CNTL2__SCLK_G_AFMTF_GATE_DIS_MASK 0x1000
+#define DCO_CLK_CNTL2__SCLK_G_AFMTF_GATE_DIS__SHIFT 0xc
+#define DCO_CLK_CNTL2__SCLK_G_AFMTG_GATE_DIS_MASK 0x2000
+#define DCO_CLK_CNTL2__SCLK_G_AFMTG_GATE_DIS__SHIFT 0xd
+#define DCO_CLK_CNTL2__SCLK_G_AFMTLPA_GATE_DIS_MASK 0x8000
+#define DCO_CLK_CNTL2__SCLK_G_AFMTLPA_GATE_DIS__SHIFT 0xf
+#define DCO_CLK_CNTL2__SCLK_G_AFMTLPB_GATE_DIS_MASK 0x10000
+#define DCO_CLK_CNTL2__SCLK_G_AFMTLPB_GATE_DIS__SHIFT 0x10
+#define DCO_CLK_CNTL2__SYMCLKA_FE_G_AFMT_GATE_DIS_MASK 0x20000
+#define DCO_CLK_CNTL2__SYMCLKA_FE_G_AFMT_GATE_DIS__SHIFT 0x11
+#define DCO_CLK_CNTL2__SYMCLKB_FE_G_AFMT_GATE_DIS_MASK 0x40000
+#define DCO_CLK_CNTL2__SYMCLKB_FE_G_AFMT_GATE_DIS__SHIFT 0x12
+#define DCO_CLK_CNTL2__SYMCLKC_FE_G_AFMT_GATE_DIS_MASK 0x80000
+#define DCO_CLK_CNTL2__SYMCLKC_FE_G_AFMT_GATE_DIS__SHIFT 0x13
+#define DCO_CLK_CNTL2__SYMCLKD_FE_G_AFMT_GATE_DIS_MASK 0x100000
+#define DCO_CLK_CNTL2__SYMCLKD_FE_G_AFMT_GATE_DIS__SHIFT 0x14
+#define DCO_CLK_CNTL2__SYMCLKE_FE_G_AFMT_GATE_DIS_MASK 0x200000
+#define DCO_CLK_CNTL2__SYMCLKE_FE_G_AFMT_GATE_DIS__SHIFT 0x15
+#define DCO_CLK_CNTL2__SYMCLKF_FE_G_AFMT_GATE_DIS_MASK 0x400000
+#define DCO_CLK_CNTL2__SYMCLKF_FE_G_AFMT_GATE_DIS__SHIFT 0x16
+#define DCO_CLK_CNTL2__SYMCLKG_FE_G_AFMT_GATE_DIS_MASK 0x800000
+#define DCO_CLK_CNTL2__SYMCLKG_FE_G_AFMT_GATE_DIS__SHIFT 0x17
+#define DCO_CLK_CNTL2__SYMCLKLPA_FE_G_AFMT_GATE_DIS_MASK 0x2000000
+#define DCO_CLK_CNTL2__SYMCLKLPA_FE_G_AFMT_GATE_DIS__SHIFT 0x19
+#define DCO_CLK_CNTL2__SYMCLKLPB_FE_G_AFMT_GATE_DIS_MASK 0x4000000
+#define DCO_CLK_CNTL2__SYMCLKLPB_FE_G_AFMT_GATE_DIS__SHIFT 0x1a
+#define DCO_CLK_CNTL3__SYMCLKA_FE_G_TMDS_GATE_DIS_MASK 0x1
+#define DCO_CLK_CNTL3__SYMCLKA_FE_G_TMDS_GATE_DIS__SHIFT 0x0
+#define DCO_CLK_CNTL3__SYMCLKB_FE_G_TMDS_GATE_DIS_MASK 0x2
+#define DCO_CLK_CNTL3__SYMCLKB_FE_G_TMDS_GATE_DIS__SHIFT 0x1
+#define DCO_CLK_CNTL3__SYMCLKC_FE_G_TMDS_GATE_DIS_MASK 0x4
+#define DCO_CLK_CNTL3__SYMCLKC_FE_G_TMDS_GATE_DIS__SHIFT 0x2
+#define DCO_CLK_CNTL3__SYMCLKD_FE_G_TMDS_GATE_DIS_MASK 0x8
+#define DCO_CLK_CNTL3__SYMCLKD_FE_G_TMDS_GATE_DIS__SHIFT 0x3
+#define DCO_CLK_CNTL3__SYMCLKE_FE_G_TMDS_GATE_DIS_MASK 0x10
+#define DCO_CLK_CNTL3__SYMCLKE_FE_G_TMDS_GATE_DIS__SHIFT 0x4
+#define DCO_CLK_CNTL3__SYMCLKF_FE_G_TMDS_GATE_DIS_MASK 0x20
+#define DCO_CLK_CNTL3__SYMCLKF_FE_G_TMDS_GATE_DIS__SHIFT 0x5
+#define DCO_CLK_CNTL3__SYMCLKG_FE_G_TMDS_GATE_DIS_MASK 0x40
+#define DCO_CLK_CNTL3__SYMCLKG_FE_G_TMDS_GATE_DIS__SHIFT 0x6
+#define DCO_CLK_CNTL3__SYMCLKLPA_FE_G_TMDS_GATE_DIS_MASK 0x100
+#define DCO_CLK_CNTL3__SYMCLKLPA_FE_G_TMDS_GATE_DIS__SHIFT 0x8
+#define DCO_CLK_CNTL3__SYMCLKLPB_FE_G_TMDS_GATE_DIS_MASK 0x200
+#define DCO_CLK_CNTL3__SYMCLKLPB_FE_G_TMDS_GATE_DIS__SHIFT 0x9
+#define DCO_CLK_CNTL3__SYMCLKA_G_TMDS_GATE_DIS_MASK 0x400
+#define DCO_CLK_CNTL3__SYMCLKA_G_TMDS_GATE_DIS__SHIFT 0xa
+#define DCO_CLK_CNTL3__SYMCLKB_G_TMDS_GATE_DIS_MASK 0x800
+#define DCO_CLK_CNTL3__SYMCLKB_G_TMDS_GATE_DIS__SHIFT 0xb
+#define DCO_CLK_CNTL3__SYMCLKC_G_TMDS_GATE_DIS_MASK 0x1000
+#define DCO_CLK_CNTL3__SYMCLKC_G_TMDS_GATE_DIS__SHIFT 0xc
+#define DCO_CLK_CNTL3__SYMCLKD_G_TMDS_GATE_DIS_MASK 0x2000
+#define DCO_CLK_CNTL3__SYMCLKD_G_TMDS_GATE_DIS__SHIFT 0xd
+#define DCO_CLK_CNTL3__SYMCLKE_G_TMDS_GATE_DIS_MASK 0x4000
+#define DCO_CLK_CNTL3__SYMCLKE_G_TMDS_GATE_DIS__SHIFT 0xe
+#define DCO_CLK_CNTL3__SYMCLKF_G_TMDS_GATE_DIS_MASK 0x8000
+#define DCO_CLK_CNTL3__SYMCLKF_G_TMDS_GATE_DIS__SHIFT 0xf
+#define DCO_CLK_CNTL3__SYMCLKG_G_TMDS_GATE_DIS_MASK 0x10000
+#define DCO_CLK_CNTL3__SYMCLKG_G_TMDS_GATE_DIS__SHIFT 0x10
+#define DCO_CLK_CNTL3__SYMCLKLPA_G_TMDS_GATE_DIS_MASK 0x40000
+#define DCO_CLK_CNTL3__SYMCLKLPA_G_TMDS_GATE_DIS__SHIFT 0x12
+#define DCO_CLK_CNTL3__SYMCLKLPB_G_TMDS_GATE_DIS_MASK 0x80000
+#define DCO_CLK_CNTL3__SYMCLKLPB_G_TMDS_GATE_DIS__SHIFT 0x13
+#define DPDBG_CNTL__DPDBG_ENABLE_MASK 0x1
+#define DPDBG_CNTL__DPDBG_ENABLE__SHIFT 0x0
+#define DPDBG_CNTL__DPDBG_INPUT_ENABLE_MASK 0x2
+#define DPDBG_CNTL__DPDBG_INPUT_ENABLE__SHIFT 0x1
+#define DPDBG_CNTL__DPDBG_SYMCLK_ON_MASK 0x10
+#define DPDBG_CNTL__DPDBG_SYMCLK_ON__SHIFT 0x4
+#define DPDBG_CNTL__DPDBG_ERROR_DETECTION_MODE_MASK 0x100
+#define DPDBG_CNTL__DPDBG_ERROR_DETECTION_MODE__SHIFT 0x8
+#define DPDBG_CNTL__DPDBG_LINE_LENGTH_MASK 0xffff0000
+#define DPDBG_CNTL__DPDBG_LINE_LENGTH__SHIFT 0x10
+#define DPDBG_INTERRUPT__DPDBG_FIFO_OVERFLOW_INT_MASK_MASK 0x1
+#define DPDBG_INTERRUPT__DPDBG_FIFO_OVERFLOW_INT_MASK__SHIFT 0x0
+#define DPDBG_INTERRUPT__DPDBG_FIFO_OVERFLOW_INT_TYPE_MASK 0x2
+#define DPDBG_INTERRUPT__DPDBG_FIFO_OVERFLOW_INT_TYPE__SHIFT 0x1
+#define DPDBG_INTERRUPT__DPDBG_FIFO_OVERFLOW_INT_ACK_MASK 0x100
+#define DPDBG_INTERRUPT__DPDBG_FIFO_OVERFLOW_INT_ACK__SHIFT 0x8
+#define DPDBG_INTERRUPT__DPDBG_FIFO_OVERFLOW_OCCURRED_MASK 0x10000
+#define DPDBG_INTERRUPT__DPDBG_FIFO_OVERFLOW_OCCURRED__SHIFT 0x10
+#define DPDBG_INTERRUPT__DPDBG_FIFO_OVERFLOW_INT_STATUS_MASK 0x1000000
+#define DPDBG_INTERRUPT__DPDBG_FIFO_OVERFLOW_INT_STATUS__SHIFT 0x18
+#define DCO_POWER_MANAGEMENT_CNTL__PM_ASSERT_RESET_MASK 0x1
+#define DCO_POWER_MANAGEMENT_CNTL__PM_ASSERT_RESET__SHIFT 0x0
+#define DCO_POWER_MANAGEMENT_CNTL__PM_ALL_BUSY_OFF_MASK 0x100
+#define DCO_POWER_MANAGEMENT_CNTL__PM_ALL_BUSY_OFF__SHIFT 0x8
+#define DCO_SOFT_RESET__DACA_SOFT_RESET_MASK 0x1
+#define DCO_SOFT_RESET__DACA_SOFT_RESET__SHIFT 0x0
+#define DCO_SOFT_RESET__I2S0_SPDIF0_SOFT_RESET_MASK 0x10
+#define DCO_SOFT_RESET__I2S0_SPDIF0_SOFT_RESET__SHIFT 0x4
+#define DCO_SOFT_RESET__I2S1_SOFT_RESET_MASK 0x20
+#define DCO_SOFT_RESET__I2S1_SOFT_RESET__SHIFT 0x5
+#define DCO_SOFT_RESET__SPDIF1_SOFT_RESET_MASK 0x40
+#define DCO_SOFT_RESET__SPDIF1_SOFT_RESET__SHIFT 0x6
+#define DCO_SOFT_RESET__DB_CLK_SOFT_RESET_MASK 0x1000
+#define DCO_SOFT_RESET__DB_CLK_SOFT_RESET__SHIFT 0xc
+#define DCO_SOFT_RESET__FMT0_SOFT_RESET_MASK 0x10000
+#define DCO_SOFT_RESET__FMT0_SOFT_RESET__SHIFT 0x10
+#define DCO_SOFT_RESET__FMT1_SOFT_RESET_MASK 0x20000
+#define DCO_SOFT_RESET__FMT1_SOFT_RESET__SHIFT 0x11
+#define DCO_SOFT_RESET__FMT2_SOFT_RESET_MASK 0x40000
+#define DCO_SOFT_RESET__FMT2_SOFT_RESET__SHIFT 0x12
+#define DCO_SOFT_RESET__FMT3_SOFT_RESET_MASK 0x80000
+#define DCO_SOFT_RESET__FMT3_SOFT_RESET__SHIFT 0x13
+#define DCO_SOFT_RESET__FMT4_SOFT_RESET_MASK 0x100000
+#define DCO_SOFT_RESET__FMT4_SOFT_RESET__SHIFT 0x14
+#define DCO_SOFT_RESET__FMT5_SOFT_RESET_MASK 0x200000
+#define DCO_SOFT_RESET__FMT5_SOFT_RESET__SHIFT 0x15
+#define DCO_SOFT_RESET__MVP_SOFT_RESET_MASK 0x1000000
+#define DCO_SOFT_RESET__MVP_SOFT_RESET__SHIFT 0x18
+#define DCO_SOFT_RESET__ABM_SOFT_RESET_MASK 0x2000000
+#define DCO_SOFT_RESET__ABM_SOFT_RESET__SHIFT 0x19
+#define DCO_SOFT_RESET__DVO_SOFT_RESET_MASK 0x8000000
+#define DCO_SOFT_RESET__DVO_SOFT_RESET__SHIFT 0x1b
+#define DIG_SOFT_RESET__DIGA_FE_SOFT_RESET_MASK 0x1
+#define DIG_SOFT_RESET__DIGA_FE_SOFT_RESET__SHIFT 0x0
+#define DIG_SOFT_RESET__DIGA_BE_SOFT_RESET_MASK 0x2
+#define DIG_SOFT_RESET__DIGA_BE_SOFT_RESET__SHIFT 0x1
+#define DIG_SOFT_RESET__DIGB_FE_SOFT_RESET_MASK 0x10
+#define DIG_SOFT_RESET__DIGB_FE_SOFT_RESET__SHIFT 0x4
+#define DIG_SOFT_RESET__DIGB_BE_SOFT_RESET_MASK 0x20
+#define DIG_SOFT_RESET__DIGB_BE_SOFT_RESET__SHIFT 0x5
+#define DIG_SOFT_RESET__DIGC_FE_SOFT_RESET_MASK 0x100
+#define DIG_SOFT_RESET__DIGC_FE_SOFT_RESET__SHIFT 0x8
+#define DIG_SOFT_RESET__DIGC_BE_SOFT_RESET_MASK 0x200
+#define DIG_SOFT_RESET__DIGC_BE_SOFT_RESET__SHIFT 0x9
+#define DIG_SOFT_RESET__DIGD_FE_SOFT_RESET_MASK 0x1000
+#define DIG_SOFT_RESET__DIGD_FE_SOFT_RESET__SHIFT 0xc
+#define DIG_SOFT_RESET__DIGD_BE_SOFT_RESET_MASK 0x2000
+#define DIG_SOFT_RESET__DIGD_BE_SOFT_RESET__SHIFT 0xd
+#define DIG_SOFT_RESET__DIGE_FE_SOFT_RESET_MASK 0x10000
+#define DIG_SOFT_RESET__DIGE_FE_SOFT_RESET__SHIFT 0x10
+#define DIG_SOFT_RESET__DIGE_BE_SOFT_RESET_MASK 0x20000
+#define DIG_SOFT_RESET__DIGE_BE_SOFT_RESET__SHIFT 0x11
+#define DIG_SOFT_RESET__DIGF_FE_SOFT_RESET_MASK 0x100000
+#define DIG_SOFT_RESET__DIGF_FE_SOFT_RESET__SHIFT 0x14
+#define DIG_SOFT_RESET__DIGF_BE_SOFT_RESET_MASK 0x200000
+#define DIG_SOFT_RESET__DIGF_BE_SOFT_RESET__SHIFT 0x15
+#define DIG_SOFT_RESET__DIGG_FE_SOFT_RESET_MASK 0x1000000
+#define DIG_SOFT_RESET__DIGG_FE_SOFT_RESET__SHIFT 0x18
+#define DIG_SOFT_RESET__DIGG_BE_SOFT_RESET_MASK 0x2000000
+#define DIG_SOFT_RESET__DIGG_BE_SOFT_RESET__SHIFT 0x19
+#define DIG_SOFT_RESET__DPDBG_SOFT_RESET_MASK 0x80000000
+#define DIG_SOFT_RESET__DPDBG_SOFT_RESET__SHIFT 0x1f
+#define DIG_SOFT_RESET_2__DIGLPA_FE_SOFT_RESET_MASK 0x1
+#define DIG_SOFT_RESET_2__DIGLPA_FE_SOFT_RESET__SHIFT 0x0
+#define DIG_SOFT_RESET_2__DIGLPA_BE_SOFT_RESET_MASK 0x2
+#define DIG_SOFT_RESET_2__DIGLPA_BE_SOFT_RESET__SHIFT 0x1
+#define DIG_SOFT_RESET_2__DIGLPB_FE_SOFT_RESET_MASK 0x10
+#define DIG_SOFT_RESET_2__DIGLPB_FE_SOFT_RESET__SHIFT 0x4
+#define DIG_SOFT_RESET_2__DIGLPB_BE_SOFT_RESET_MASK 0x20
+#define DIG_SOFT_RESET_2__DIGLPB_BE_SOFT_RESET__SHIFT 0x5
+#define DCO_STEREOSYNC_SEL__GENERICA_STEREOSYNC_SEL_MASK 0x7
+#define DCO_STEREOSYNC_SEL__GENERICA_STEREOSYNC_SEL__SHIFT 0x0
+#define DCO_STEREOSYNC_SEL__GENERICB_STEREOSYNC_SEL_MASK 0x70000
+#define DCO_STEREOSYNC_SEL__GENERICB_STEREOSYNC_SEL__SHIFT 0x10
+#define DCO_HDMI_RXSTATUS_TIMER_CONTROL__DCO_HDMI_RXSTATUS_TIMER_ENABLE_MASK 0x1
+#define DCO_HDMI_RXSTATUS_TIMER_CONTROL__DCO_HDMI_RXSTATUS_TIMER_ENABLE__SHIFT 0x0
+#define DCO_HDMI_RXSTATUS_TIMER_CONTROL__DCO_HDMI_RXSTATUS_TIMER_TYPE_MASK 0x10
+#define DCO_HDMI_RXSTATUS_TIMER_CONTROL__DCO_HDMI_RXSTATUS_TIMER_TYPE__SHIFT 0x4
+#define DCO_HDMI_RXSTATUS_TIMER_CONTROL__DCO_HDMI_RXSTATUS_TIMER_STATUS_MASK 0x100
+#define DCO_HDMI_RXSTATUS_TIMER_CONTROL__DCO_HDMI_RXSTATUS_TIMER_STATUS__SHIFT 0x8
+#define DCO_HDMI_RXSTATUS_TIMER_CONTROL__DCO_HDMI_RXSTATUS_TIMER_MASK_MASK 0x1000
+#define DCO_HDMI_RXSTATUS_TIMER_CONTROL__DCO_HDMI_RXSTATUS_TIMER_MASK__SHIFT 0xc
+#define DCO_HDMI_RXSTATUS_TIMER_CONTROL__DCO_HDMI_RXSTATUS_TIMER_INTERVAL_MASK 0xfff0000
+#define DCO_HDMI_RXSTATUS_TIMER_CONTROL__DCO_HDMI_RXSTATUS_TIMER_INTERVAL__SHIFT 0x10
+#define DCO_PSP_INTERRUPT_STATUS__DCO_PSP_INTERRUPT_STATUS_MASK 0x1
+#define DCO_PSP_INTERRUPT_STATUS__DCO_PSP_INTERRUPT_STATUS__SHIFT 0x0
+#define DCO_PSP_INTERRUPT_STATUS__DCO_PSP_INTERRUPT_MESSAGE_MASK 0xfffffffe
+#define DCO_PSP_INTERRUPT_STATUS__DCO_PSP_INTERRUPT_MESSAGE__SHIFT 0x1
+#define DCO_PSP_INTERRUPT_CLEAR__DCO_PSP_INTERRUPT_CLEAR_MASK 0x1
+#define DCO_PSP_INTERRUPT_CLEAR__DCO_PSP_INTERRUPT_CLEAR__SHIFT 0x0
+#define DCO_GENERIC_INTERRUPT_MESSAGE__DCO_GENERIC_INTERRUPT_STATUS_MASK 0x1
+#define DCO_GENERIC_INTERRUPT_MESSAGE__DCO_GENERIC_INTERRUPT_STATUS__SHIFT 0x0
+#define DCO_GENERIC_INTERRUPT_MESSAGE__DCO_GENERIC_INTERRUPT_MESSAGE_MASK 0xfffffffe
+#define DCO_GENERIC_INTERRUPT_MESSAGE__DCO_GENERIC_INTERRUPT_MESSAGE__SHIFT 0x1
+#define DCO_GENERIC_INTERRUPT_CLEAR__DCO_GENERIC_INTERRUPT_CLEAR_MASK 0x1
+#define DCO_GENERIC_INTERRUPT_CLEAR__DCO_GENERIC_INTERRUPT_CLEAR__SHIFT 0x0
+#define DCO_TEST_DEBUG_INDEX__DCO_TEST_DEBUG_INDEX_MASK 0xff
+#define DCO_TEST_DEBUG_INDEX__DCO_TEST_DEBUG_INDEX__SHIFT 0x0
+#define DCO_TEST_DEBUG_INDEX__DCO_TEST_DEBUG_WRITE_EN_MASK 0x100
+#define DCO_TEST_DEBUG_INDEX__DCO_TEST_DEBUG_WRITE_EN__SHIFT 0x8
+#define DCO_TEST_DEBUG_DATA__DCO_TEST_DEBUG_DATA_MASK 0xffffffff
+#define DCO_TEST_DEBUG_DATA__DCO_TEST_DEBUG_DATA__SHIFT 0x0
+#define DC_I2C_CONTROL__DC_I2C_GO_MASK 0x1
+#define DC_I2C_CONTROL__DC_I2C_GO__SHIFT 0x0
+#define DC_I2C_CONTROL__DC_I2C_SOFT_RESET_MASK 0x2
+#define DC_I2C_CONTROL__DC_I2C_SOFT_RESET__SHIFT 0x1
+#define DC_I2C_CONTROL__DC_I2C_SEND_RESET_MASK 0x4
+#define DC_I2C_CONTROL__DC_I2C_SEND_RESET__SHIFT 0x2
+#define DC_I2C_CONTROL__DC_I2C_SW_STATUS_RESET_MASK 0x8
+#define DC_I2C_CONTROL__DC_I2C_SW_STATUS_RESET__SHIFT 0x3
+#define DC_I2C_CONTROL__DC_I2C_DDC_SELECT_MASK 0x700
+#define DC_I2C_CONTROL__DC_I2C_DDC_SELECT__SHIFT 0x8
+#define DC_I2C_CONTROL__DC_I2C_TRANSACTION_COUNT_MASK 0x300000
+#define DC_I2C_CONTROL__DC_I2C_TRANSACTION_COUNT__SHIFT 0x14
+#define DC_I2C_CONTROL__DC_I2C_DBG_REF_SEL_MASK 0x80000000
+#define DC_I2C_CONTROL__DC_I2C_DBG_REF_SEL__SHIFT 0x1f
+#define DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_MASK 0x3
+#define DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY__SHIFT 0x0
+#define DC_I2C_ARBITRATION__DC_I2C_REG_RW_CNTL_STATUS_MASK 0xc
+#define DC_I2C_ARBITRATION__DC_I2C_REG_RW_CNTL_STATUS__SHIFT 0x2
+#define DC_I2C_ARBITRATION__DC_I2C_NO_QUEUED_SW_GO_MASK 0x10
+#define DC_I2C_ARBITRATION__DC_I2C_NO_QUEUED_SW_GO__SHIFT 0x4
+#define DC_I2C_ARBITRATION__DC_I2C_ABORT_HW_XFER_MASK 0x100
+#define DC_I2C_ARBITRATION__DC_I2C_ABORT_HW_XFER__SHIFT 0x8
+#define DC_I2C_ARBITRATION__DC_I2C_ABORT_SW_XFER_MASK 0x1000
+#define DC_I2C_ARBITRATION__DC_I2C_ABORT_SW_XFER__SHIFT 0xc
+#define DC_I2C_ARBITRATION__DC_I2C_SW_USE_I2C_REG_REQ_MASK 0x100000
+#define DC_I2C_ARBITRATION__DC_I2C_SW_USE_I2C_REG_REQ__SHIFT 0x14
+#define DC_I2C_ARBITRATION__DC_I2C_SW_DONE_USING_I2C_REG_MASK 0x200000
+#define DC_I2C_ARBITRATION__DC_I2C_SW_DONE_USING_I2C_REG__SHIFT 0x15
+#define DC_I2C_ARBITRATION__DC_I2C_DMCU_USE_I2C_REG_REQ_MASK 0x1000000
+#define DC_I2C_ARBITRATION__DC_I2C_DMCU_USE_I2C_REG_REQ__SHIFT 0x18
+#define DC_I2C_ARBITRATION__DC_I2C_DMCU_DONE_USING_I2C_REG_MASK 0x2000000
+#define DC_I2C_ARBITRATION__DC_I2C_DMCU_DONE_USING_I2C_REG__SHIFT 0x19
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_SW_DONE_INT_MASK 0x1
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_SW_DONE_INT__SHIFT 0x0
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_SW_DONE_ACK_MASK 0x2
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_SW_DONE_ACK__SHIFT 0x1
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_SW_DONE_MASK_MASK 0x4
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_SW_DONE_MASK__SHIFT 0x2
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC1_HW_DONE_INT_MASK 0x10
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC1_HW_DONE_INT__SHIFT 0x4
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC1_HW_DONE_ACK_MASK 0x20
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC1_HW_DONE_ACK__SHIFT 0x5
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC1_HW_DONE_MASK_MASK 0x40
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC1_HW_DONE_MASK__SHIFT 0x6
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC2_HW_DONE_INT_MASK 0x100
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC2_HW_DONE_INT__SHIFT 0x8
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC2_HW_DONE_ACK_MASK 0x200
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC2_HW_DONE_ACK__SHIFT 0x9
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC2_HW_DONE_MASK_MASK 0x400
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC2_HW_DONE_MASK__SHIFT 0xa
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC3_HW_DONE_INT_MASK 0x1000
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC3_HW_DONE_INT__SHIFT 0xc
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC3_HW_DONE_ACK_MASK 0x2000
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC3_HW_DONE_ACK__SHIFT 0xd
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC3_HW_DONE_MASK_MASK 0x4000
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC3_HW_DONE_MASK__SHIFT 0xe
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC4_HW_DONE_INT_MASK 0x10000
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC4_HW_DONE_INT__SHIFT 0x10
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC4_HW_DONE_ACK_MASK 0x20000
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC4_HW_DONE_ACK__SHIFT 0x11
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC4_HW_DONE_MASK_MASK 0x40000
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC4_HW_DONE_MASK__SHIFT 0x12
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC5_HW_DONE_INT_MASK 0x100000
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC5_HW_DONE_INT__SHIFT 0x14
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC5_HW_DONE_ACK_MASK 0x200000
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC5_HW_DONE_ACK__SHIFT 0x15
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC5_HW_DONE_MASK_MASK 0x400000
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC5_HW_DONE_MASK__SHIFT 0x16
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC6_HW_DONE_INT_MASK 0x1000000
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC6_HW_DONE_INT__SHIFT 0x18
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC6_HW_DONE_ACK_MASK 0x2000000
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC6_HW_DONE_ACK__SHIFT 0x19
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC6_HW_DONE_MASK_MASK 0x4000000
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC6_HW_DONE_MASK__SHIFT 0x1a
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDCVGA_HW_DONE_INT_MASK 0x8000000
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDCVGA_HW_DONE_INT__SHIFT 0x1b
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDCVGA_HW_DONE_ACK_MASK 0x10000000
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDCVGA_HW_DONE_ACK__SHIFT 0x1c
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDCVGA_HW_DONE_MASK_MASK 0x20000000
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDCVGA_HW_DONE_MASK__SHIFT 0x1d
+#define DC_I2C_SW_STATUS__DC_I2C_SW_STATUS_MASK 0x3
+#define DC_I2C_SW_STATUS__DC_I2C_SW_STATUS__SHIFT 0x0
+#define DC_I2C_SW_STATUS__DC_I2C_SW_DONE_MASK 0x4
+#define DC_I2C_SW_STATUS__DC_I2C_SW_DONE__SHIFT 0x2
+#define DC_I2C_SW_STATUS__DC_I2C_SW_ABORTED_MASK 0x10
+#define DC_I2C_SW_STATUS__DC_I2C_SW_ABORTED__SHIFT 0x4
+#define DC_I2C_SW_STATUS__DC_I2C_SW_TIMEOUT_MASK 0x20
+#define DC_I2C_SW_STATUS__DC_I2C_SW_TIMEOUT__SHIFT 0x5
+#define DC_I2C_SW_STATUS__DC_I2C_SW_INTERRUPTED_MASK 0x40
+#define DC_I2C_SW_STATUS__DC_I2C_SW_INTERRUPTED__SHIFT 0x6
+#define DC_I2C_SW_STATUS__DC_I2C_SW_BUFFER_OVERFLOW_MASK 0x80
+#define DC_I2C_SW_STATUS__DC_I2C_SW_BUFFER_OVERFLOW__SHIFT 0x7
+#define DC_I2C_SW_STATUS__DC_I2C_SW_STOPPED_ON_NACK_MASK 0x100
+#define DC_I2C_SW_STATUS__DC_I2C_SW_STOPPED_ON_NACK__SHIFT 0x8
+#define DC_I2C_SW_STATUS__DC_I2C_SW_NACK0_MASK 0x1000
+#define DC_I2C_SW_STATUS__DC_I2C_SW_NACK0__SHIFT 0xc
+#define DC_I2C_SW_STATUS__DC_I2C_SW_NACK1_MASK 0x2000
+#define DC_I2C_SW_STATUS__DC_I2C_SW_NACK1__SHIFT 0xd
+#define DC_I2C_SW_STATUS__DC_I2C_SW_NACK2_MASK 0x4000
+#define DC_I2C_SW_STATUS__DC_I2C_SW_NACK2__SHIFT 0xe
+#define DC_I2C_SW_STATUS__DC_I2C_SW_NACK3_MASK 0x8000
+#define DC_I2C_SW_STATUS__DC_I2C_SW_NACK3__SHIFT 0xf
+#define DC_I2C_SW_STATUS__DC_I2C_SW_REQ_MASK 0x40000
+#define DC_I2C_SW_STATUS__DC_I2C_SW_REQ__SHIFT 0x12
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_HW_STATUS_MASK 0x3
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_HW_STATUS__SHIFT 0x0
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_HW_DONE_MASK 0x8
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_HW_DONE__SHIFT 0x3
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_HW_REQ_MASK 0x10000
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_HW_REQ__SHIFT 0x10
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_HW_URG_MASK 0x20000
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_HW_URG__SHIFT 0x11
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_EDID_DETECT_STATUS_MASK 0x100000
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_EDID_DETECT_STATUS__SHIFT 0x14
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_EDID_DETECT_NUM_VALID_TRIES_MASK 0xf000000
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_EDID_DETECT_NUM_VALID_TRIES__SHIFT 0x18
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_EDID_DETECT_STATE_MASK 0x70000000
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_EDID_DETECT_STATE__SHIFT 0x1c
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_HW_STATUS_MASK 0x3
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_HW_STATUS__SHIFT 0x0
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_HW_DONE_MASK 0x8
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_HW_DONE__SHIFT 0x3
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_HW_REQ_MASK 0x10000
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_HW_REQ__SHIFT 0x10
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_HW_URG_MASK 0x20000
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_HW_URG__SHIFT 0x11
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_EDID_DETECT_STATUS_MASK 0x100000
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_EDID_DETECT_STATUS__SHIFT 0x14
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_EDID_DETECT_NUM_VALID_TRIES_MASK 0xf000000
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_EDID_DETECT_NUM_VALID_TRIES__SHIFT 0x18
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_EDID_DETECT_STATE_MASK 0x70000000
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_EDID_DETECT_STATE__SHIFT 0x1c
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_HW_STATUS_MASK 0x3
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_HW_STATUS__SHIFT 0x0
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_HW_DONE_MASK 0x8
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_HW_DONE__SHIFT 0x3
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_HW_REQ_MASK 0x10000
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_HW_REQ__SHIFT 0x10
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_HW_URG_MASK 0x20000
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_HW_URG__SHIFT 0x11
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_EDID_DETECT_STATUS_MASK 0x100000
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_EDID_DETECT_STATUS__SHIFT 0x14
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_EDID_DETECT_NUM_VALID_TRIES_MASK 0xf000000
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_EDID_DETECT_NUM_VALID_TRIES__SHIFT 0x18
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_EDID_DETECT_STATE_MASK 0x70000000
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_EDID_DETECT_STATE__SHIFT 0x1c
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_HW_STATUS_MASK 0x3
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_HW_STATUS__SHIFT 0x0
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_HW_DONE_MASK 0x8
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_HW_DONE__SHIFT 0x3
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_HW_REQ_MASK 0x10000
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_HW_REQ__SHIFT 0x10
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_HW_URG_MASK 0x20000
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_HW_URG__SHIFT 0x11
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_EDID_DETECT_STATUS_MASK 0x100000
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_EDID_DETECT_STATUS__SHIFT 0x14
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_EDID_DETECT_NUM_VALID_TRIES_MASK 0xf000000
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_EDID_DETECT_NUM_VALID_TRIES__SHIFT 0x18
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_EDID_DETECT_STATE_MASK 0x70000000
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_EDID_DETECT_STATE__SHIFT 0x1c
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_HW_STATUS_MASK 0x3
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_HW_STATUS__SHIFT 0x0
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_HW_DONE_MASK 0x8
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_HW_DONE__SHIFT 0x3
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_HW_REQ_MASK 0x10000
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_HW_REQ__SHIFT 0x10
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_HW_URG_MASK 0x20000
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_HW_URG__SHIFT 0x11
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_EDID_DETECT_STATUS_MASK 0x100000
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_EDID_DETECT_STATUS__SHIFT 0x14
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_EDID_DETECT_NUM_VALID_TRIES_MASK 0xf000000
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_EDID_DETECT_NUM_VALID_TRIES__SHIFT 0x18
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_EDID_DETECT_STATE_MASK 0x70000000
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_EDID_DETECT_STATE__SHIFT 0x1c
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_HW_STATUS_MASK 0x3
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_HW_STATUS__SHIFT 0x0
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_HW_DONE_MASK 0x8
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_HW_DONE__SHIFT 0x3
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_HW_REQ_MASK 0x10000
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_HW_REQ__SHIFT 0x10
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_HW_URG_MASK 0x20000
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_HW_URG__SHIFT 0x11
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_EDID_DETECT_STATUS_MASK 0x100000
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_EDID_DETECT_STATUS__SHIFT 0x14
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_EDID_DETECT_NUM_VALID_TRIES_MASK 0xf000000
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_EDID_DETECT_NUM_VALID_TRIES__SHIFT 0x18
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_EDID_DETECT_STATE_MASK 0x70000000
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_EDID_DETECT_STATE__SHIFT 0x1c
+#define DC_I2C_DDC1_SPEED__DC_I2C_DDC1_THRESHOLD_MASK 0x3
+#define DC_I2C_DDC1_SPEED__DC_I2C_DDC1_THRESHOLD__SHIFT 0x0
+#define DC_I2C_DDC1_SPEED__DC_I2C_DDC1_DISABLE_FILTER_DURING_STALL_MASK 0x10
+#define DC_I2C_DDC1_SPEED__DC_I2C_DDC1_DISABLE_FILTER_DURING_STALL__SHIFT 0x4
+#define DC_I2C_DDC1_SPEED__DC_I2C_DDC1_START_STOP_TIMING_CNTL_MASK 0x300
+#define DC_I2C_DDC1_SPEED__DC_I2C_DDC1_START_STOP_TIMING_CNTL__SHIFT 0x8
+#define DC_I2C_DDC1_SPEED__DC_I2C_DDC1_PRESCALE_MASK 0xffff0000
+#define DC_I2C_DDC1_SPEED__DC_I2C_DDC1_PRESCALE__SHIFT 0x10
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_DATA_DRIVE_EN_MASK 0x1
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_DATA_DRIVE_EN__SHIFT 0x0
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_DATA_DRIVE_SEL_MASK 0x2
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_DATA_DRIVE_SEL__SHIFT 0x1
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_EDID_DETECT_ENABLE_MASK 0x10
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_EDID_DETECT_ENABLE__SHIFT 0x4
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_EDID_DETECT_MODE_MASK 0x20
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_EDID_DETECT_MODE__SHIFT 0x5
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_ENABLE_MASK 0x40
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_ENABLE__SHIFT 0x6
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_CLK_DRIVE_EN_MASK 0x80
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_CLK_DRIVE_EN__SHIFT 0x7
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_INTRA_BYTE_DELAY_MASK 0xff00
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_INTRA_BYTE_DELAY__SHIFT 0x8
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_INTRA_TRANSACTION_DELAY_MASK 0xff0000
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_INTRA_TRANSACTION_DELAY__SHIFT 0x10
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_TIME_LIMIT_MASK 0xff000000
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_TIME_LIMIT__SHIFT 0x18
+#define DC_I2C_DDC2_SPEED__DC_I2C_DDC2_THRESHOLD_MASK 0x3
+#define DC_I2C_DDC2_SPEED__DC_I2C_DDC2_THRESHOLD__SHIFT 0x0
+#define DC_I2C_DDC2_SPEED__DC_I2C_DDC2_DISABLE_FILTER_DURING_STALL_MASK 0x10
+#define DC_I2C_DDC2_SPEED__DC_I2C_DDC2_DISABLE_FILTER_DURING_STALL__SHIFT 0x4
+#define DC_I2C_DDC2_SPEED__DC_I2C_DDC2_START_STOP_TIMING_CNTL_MASK 0x300
+#define DC_I2C_DDC2_SPEED__DC_I2C_DDC2_START_STOP_TIMING_CNTL__SHIFT 0x8
+#define DC_I2C_DDC2_SPEED__DC_I2C_DDC2_PRESCALE_MASK 0xffff0000
+#define DC_I2C_DDC2_SPEED__DC_I2C_DDC2_PRESCALE__SHIFT 0x10
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_DATA_DRIVE_EN_MASK 0x1
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_DATA_DRIVE_EN__SHIFT 0x0
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_DATA_DRIVE_SEL_MASK 0x2
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_DATA_DRIVE_SEL__SHIFT 0x1
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_EDID_DETECT_ENABLE_MASK 0x10
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_EDID_DETECT_ENABLE__SHIFT 0x4
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_EDID_DETECT_MODE_MASK 0x20
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_EDID_DETECT_MODE__SHIFT 0x5
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_ENABLE_MASK 0x40
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_ENABLE__SHIFT 0x6
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_CLK_DRIVE_EN_MASK 0x80
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_CLK_DRIVE_EN__SHIFT 0x7
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_INTRA_BYTE_DELAY_MASK 0xff00
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_INTRA_BYTE_DELAY__SHIFT 0x8
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_INTRA_TRANSACTION_DELAY_MASK 0xff0000
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_INTRA_TRANSACTION_DELAY__SHIFT 0x10
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_TIME_LIMIT_MASK 0xff000000
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_TIME_LIMIT__SHIFT 0x18
+#define DC_I2C_DDC3_SPEED__DC_I2C_DDC3_THRESHOLD_MASK 0x3
+#define DC_I2C_DDC3_SPEED__DC_I2C_DDC3_THRESHOLD__SHIFT 0x0
+#define DC_I2C_DDC3_SPEED__DC_I2C_DDC3_DISABLE_FILTER_DURING_STALL_MASK 0x10
+#define DC_I2C_DDC3_SPEED__DC_I2C_DDC3_DISABLE_FILTER_DURING_STALL__SHIFT 0x4
+#define DC_I2C_DDC3_SPEED__DC_I2C_DDC3_START_STOP_TIMING_CNTL_MASK 0x300
+#define DC_I2C_DDC3_SPEED__DC_I2C_DDC3_START_STOP_TIMING_CNTL__SHIFT 0x8
+#define DC_I2C_DDC3_SPEED__DC_I2C_DDC3_PRESCALE_MASK 0xffff0000
+#define DC_I2C_DDC3_SPEED__DC_I2C_DDC3_PRESCALE__SHIFT 0x10
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_DATA_DRIVE_EN_MASK 0x1
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_DATA_DRIVE_EN__SHIFT 0x0
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_DATA_DRIVE_SEL_MASK 0x2
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_DATA_DRIVE_SEL__SHIFT 0x1
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_EDID_DETECT_ENABLE_MASK 0x10
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_EDID_DETECT_ENABLE__SHIFT 0x4
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_EDID_DETECT_MODE_MASK 0x20
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_EDID_DETECT_MODE__SHIFT 0x5
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_ENABLE_MASK 0x40
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_ENABLE__SHIFT 0x6
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_CLK_DRIVE_EN_MASK 0x80
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_CLK_DRIVE_EN__SHIFT 0x7
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_INTRA_BYTE_DELAY_MASK 0xff00
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_INTRA_BYTE_DELAY__SHIFT 0x8
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_INTRA_TRANSACTION_DELAY_MASK 0xff0000
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_INTRA_TRANSACTION_DELAY__SHIFT 0x10
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_TIME_LIMIT_MASK 0xff000000
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_TIME_LIMIT__SHIFT 0x18
+#define DC_I2C_DDC4_SPEED__DC_I2C_DDC4_THRESHOLD_MASK 0x3
+#define DC_I2C_DDC4_SPEED__DC_I2C_DDC4_THRESHOLD__SHIFT 0x0
+#define DC_I2C_DDC4_SPEED__DC_I2C_DDC4_DISABLE_FILTER_DURING_STALL_MASK 0x10
+#define DC_I2C_DDC4_SPEED__DC_I2C_DDC4_DISABLE_FILTER_DURING_STALL__SHIFT 0x4
+#define DC_I2C_DDC4_SPEED__DC_I2C_DDC4_START_STOP_TIMING_CNTL_MASK 0x300
+#define DC_I2C_DDC4_SPEED__DC_I2C_DDC4_START_STOP_TIMING_CNTL__SHIFT 0x8
+#define DC_I2C_DDC4_SPEED__DC_I2C_DDC4_PRESCALE_MASK 0xffff0000
+#define DC_I2C_DDC4_SPEED__DC_I2C_DDC4_PRESCALE__SHIFT 0x10
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_DATA_DRIVE_EN_MASK 0x1
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_DATA_DRIVE_EN__SHIFT 0x0
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_DATA_DRIVE_SEL_MASK 0x2
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_DATA_DRIVE_SEL__SHIFT 0x1
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_EDID_DETECT_ENABLE_MASK 0x10
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_EDID_DETECT_ENABLE__SHIFT 0x4
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_EDID_DETECT_MODE_MASK 0x20
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_EDID_DETECT_MODE__SHIFT 0x5
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_ENABLE_MASK 0x40
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_ENABLE__SHIFT 0x6
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_CLK_DRIVE_EN_MASK 0x80
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_CLK_DRIVE_EN__SHIFT 0x7
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_INTRA_BYTE_DELAY_MASK 0xff00
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_INTRA_BYTE_DELAY__SHIFT 0x8
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_INTRA_TRANSACTION_DELAY_MASK 0xff0000
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_INTRA_TRANSACTION_DELAY__SHIFT 0x10
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_TIME_LIMIT_MASK 0xff000000
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_TIME_LIMIT__SHIFT 0x18
+#define DC_I2C_DDC5_SPEED__DC_I2C_DDC5_THRESHOLD_MASK 0x3
+#define DC_I2C_DDC5_SPEED__DC_I2C_DDC5_THRESHOLD__SHIFT 0x0
+#define DC_I2C_DDC5_SPEED__DC_I2C_DDC5_DISABLE_FILTER_DURING_STALL_MASK 0x10
+#define DC_I2C_DDC5_SPEED__DC_I2C_DDC5_DISABLE_FILTER_DURING_STALL__SHIFT 0x4
+#define DC_I2C_DDC5_SPEED__DC_I2C_DDC5_START_STOP_TIMING_CNTL_MASK 0x300
+#define DC_I2C_DDC5_SPEED__DC_I2C_DDC5_START_STOP_TIMING_CNTL__SHIFT 0x8
+#define DC_I2C_DDC5_SPEED__DC_I2C_DDC5_PRESCALE_MASK 0xffff0000
+#define DC_I2C_DDC5_SPEED__DC_I2C_DDC5_PRESCALE__SHIFT 0x10
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_DATA_DRIVE_EN_MASK 0x1
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_DATA_DRIVE_EN__SHIFT 0x0
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_DATA_DRIVE_SEL_MASK 0x2
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_DATA_DRIVE_SEL__SHIFT 0x1
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_EDID_DETECT_ENABLE_MASK 0x10
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_EDID_DETECT_ENABLE__SHIFT 0x4
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_EDID_DETECT_MODE_MASK 0x20
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_EDID_DETECT_MODE__SHIFT 0x5
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_ENABLE_MASK 0x40
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_ENABLE__SHIFT 0x6
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_CLK_DRIVE_EN_MASK 0x80
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_CLK_DRIVE_EN__SHIFT 0x7
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_INTRA_BYTE_DELAY_MASK 0xff00
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_INTRA_BYTE_DELAY__SHIFT 0x8
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_INTRA_TRANSACTION_DELAY_MASK 0xff0000
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_INTRA_TRANSACTION_DELAY__SHIFT 0x10
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_TIME_LIMIT_MASK 0xff000000
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_TIME_LIMIT__SHIFT 0x18
+#define DC_I2C_DDC6_SPEED__DC_I2C_DDC6_THRESHOLD_MASK 0x3
+#define DC_I2C_DDC6_SPEED__DC_I2C_DDC6_THRESHOLD__SHIFT 0x0
+#define DC_I2C_DDC6_SPEED__DC_I2C_DDC6_DISABLE_FILTER_DURING_STALL_MASK 0x10
+#define DC_I2C_DDC6_SPEED__DC_I2C_DDC6_DISABLE_FILTER_DURING_STALL__SHIFT 0x4
+#define DC_I2C_DDC6_SPEED__DC_I2C_DDC6_START_STOP_TIMING_CNTL_MASK 0x300
+#define DC_I2C_DDC6_SPEED__DC_I2C_DDC6_START_STOP_TIMING_CNTL__SHIFT 0x8
+#define DC_I2C_DDC6_SPEED__DC_I2C_DDC6_PRESCALE_MASK 0xffff0000
+#define DC_I2C_DDC6_SPEED__DC_I2C_DDC6_PRESCALE__SHIFT 0x10
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_DATA_DRIVE_EN_MASK 0x1
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_DATA_DRIVE_EN__SHIFT 0x0
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_DATA_DRIVE_SEL_MASK 0x2
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_DATA_DRIVE_SEL__SHIFT 0x1
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_EDID_DETECT_ENABLE_MASK 0x10
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_EDID_DETECT_ENABLE__SHIFT 0x4
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_EDID_DETECT_MODE_MASK 0x20
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_EDID_DETECT_MODE__SHIFT 0x5
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_ENABLE_MASK 0x40
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_ENABLE__SHIFT 0x6
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_CLK_DRIVE_EN_MASK 0x80
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_CLK_DRIVE_EN__SHIFT 0x7
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_INTRA_BYTE_DELAY_MASK 0xff00
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_INTRA_BYTE_DELAY__SHIFT 0x8
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_INTRA_TRANSACTION_DELAY_MASK 0xff0000
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_INTRA_TRANSACTION_DELAY__SHIFT 0x10
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_TIME_LIMIT_MASK 0xff000000
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_TIME_LIMIT__SHIFT 0x18
+#define DC_I2C_TRANSACTION0__DC_I2C_RW0_MASK 0x1
+#define DC_I2C_TRANSACTION0__DC_I2C_RW0__SHIFT 0x0
+#define DC_I2C_TRANSACTION0__DC_I2C_STOP_ON_NACK0_MASK 0x100
+#define DC_I2C_TRANSACTION0__DC_I2C_STOP_ON_NACK0__SHIFT 0x8
+#define DC_I2C_TRANSACTION0__DC_I2C_START0_MASK 0x1000
+#define DC_I2C_TRANSACTION0__DC_I2C_START0__SHIFT 0xc
+#define DC_I2C_TRANSACTION0__DC_I2C_STOP0_MASK 0x2000
+#define DC_I2C_TRANSACTION0__DC_I2C_STOP0__SHIFT 0xd
+#define DC_I2C_TRANSACTION0__DC_I2C_COUNT0_MASK 0x3ff0000
+#define DC_I2C_TRANSACTION0__DC_I2C_COUNT0__SHIFT 0x10
+#define DC_I2C_TRANSACTION1__DC_I2C_RW1_MASK 0x1
+#define DC_I2C_TRANSACTION1__DC_I2C_RW1__SHIFT 0x0
+#define DC_I2C_TRANSACTION1__DC_I2C_STOP_ON_NACK1_MASK 0x100
+#define DC_I2C_TRANSACTION1__DC_I2C_STOP_ON_NACK1__SHIFT 0x8
+#define DC_I2C_TRANSACTION1__DC_I2C_START1_MASK 0x1000
+#define DC_I2C_TRANSACTION1__DC_I2C_START1__SHIFT 0xc
+#define DC_I2C_TRANSACTION1__DC_I2C_STOP1_MASK 0x2000
+#define DC_I2C_TRANSACTION1__DC_I2C_STOP1__SHIFT 0xd
+#define DC_I2C_TRANSACTION1__DC_I2C_COUNT1_MASK 0x3ff0000
+#define DC_I2C_TRANSACTION1__DC_I2C_COUNT1__SHIFT 0x10
+#define DC_I2C_TRANSACTION2__DC_I2C_RW2_MASK 0x1
+#define DC_I2C_TRANSACTION2__DC_I2C_RW2__SHIFT 0x0
+#define DC_I2C_TRANSACTION2__DC_I2C_STOP_ON_NACK2_MASK 0x100
+#define DC_I2C_TRANSACTION2__DC_I2C_STOP_ON_NACK2__SHIFT 0x8
+#define DC_I2C_TRANSACTION2__DC_I2C_START2_MASK 0x1000
+#define DC_I2C_TRANSACTION2__DC_I2C_START2__SHIFT 0xc
+#define DC_I2C_TRANSACTION2__DC_I2C_STOP2_MASK 0x2000
+#define DC_I2C_TRANSACTION2__DC_I2C_STOP2__SHIFT 0xd
+#define DC_I2C_TRANSACTION2__DC_I2C_COUNT2_MASK 0x3ff0000
+#define DC_I2C_TRANSACTION2__DC_I2C_COUNT2__SHIFT 0x10
+#define DC_I2C_TRANSACTION3__DC_I2C_RW3_MASK 0x1
+#define DC_I2C_TRANSACTION3__DC_I2C_RW3__SHIFT 0x0
+#define DC_I2C_TRANSACTION3__DC_I2C_STOP_ON_NACK3_MASK 0x100
+#define DC_I2C_TRANSACTION3__DC_I2C_STOP_ON_NACK3__SHIFT 0x8
+#define DC_I2C_TRANSACTION3__DC_I2C_START3_MASK 0x1000
+#define DC_I2C_TRANSACTION3__DC_I2C_START3__SHIFT 0xc
+#define DC_I2C_TRANSACTION3__DC_I2C_STOP3_MASK 0x2000
+#define DC_I2C_TRANSACTION3__DC_I2C_STOP3__SHIFT 0xd
+#define DC_I2C_TRANSACTION3__DC_I2C_COUNT3_MASK 0x3ff0000
+#define DC_I2C_TRANSACTION3__DC_I2C_COUNT3__SHIFT 0x10
+#define DC_I2C_DATA__DC_I2C_DATA_RW_MASK 0x1
+#define DC_I2C_DATA__DC_I2C_DATA_RW__SHIFT 0x0
+#define DC_I2C_DATA__DC_I2C_DATA_MASK 0xff00
+#define DC_I2C_DATA__DC_I2C_DATA__SHIFT 0x8
+#define DC_I2C_DATA__DC_I2C_INDEX_MASK 0x3ff0000
+#define DC_I2C_DATA__DC_I2C_INDEX__SHIFT 0x10
+#define DC_I2C_DATA__DC_I2C_INDEX_WRITE_MASK 0x80000000
+#define DC_I2C_DATA__DC_I2C_INDEX_WRITE__SHIFT 0x1f
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_HW_STATUS_MASK 0x3
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_HW_STATUS__SHIFT 0x0
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_HW_DONE_MASK 0x8
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_HW_DONE__SHIFT 0x3
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_HW_REQ_MASK 0x10000
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_HW_REQ__SHIFT 0x10
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_HW_URG_MASK 0x20000
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_HW_URG__SHIFT 0x11
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_EDID_DETECT_STATUS_MASK 0x100000
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_EDID_DETECT_STATUS__SHIFT 0x14
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_EDID_DETECT_NUM_VALID_TRIES_MASK 0xf000000
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_EDID_DETECT_NUM_VALID_TRIES__SHIFT 0x18
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_EDID_DETECT_STATE_MASK 0x70000000
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_EDID_DETECT_STATE__SHIFT 0x1c
+#define DC_I2C_DDCVGA_SPEED__DC_I2C_DDCVGA_THRESHOLD_MASK 0x3
+#define DC_I2C_DDCVGA_SPEED__DC_I2C_DDCVGA_THRESHOLD__SHIFT 0x0
+#define DC_I2C_DDCVGA_SPEED__DC_I2C_DDCVGA_DISABLE_FILTER_DURING_STALL_MASK 0x10
+#define DC_I2C_DDCVGA_SPEED__DC_I2C_DDCVGA_DISABLE_FILTER_DURING_STALL__SHIFT 0x4
+#define DC_I2C_DDCVGA_SPEED__DC_I2C_DDCVGA_START_STOP_TIMING_CNTL_MASK 0x300
+#define DC_I2C_DDCVGA_SPEED__DC_I2C_DDCVGA_START_STOP_TIMING_CNTL__SHIFT 0x8
+#define DC_I2C_DDCVGA_SPEED__DC_I2C_DDCVGA_PRESCALE_MASK 0xffff0000
+#define DC_I2C_DDCVGA_SPEED__DC_I2C_DDCVGA_PRESCALE__SHIFT 0x10
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_DATA_DRIVE_EN_MASK 0x1
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_DATA_DRIVE_EN__SHIFT 0x0
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_DATA_DRIVE_SEL_MASK 0x2
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_DATA_DRIVE_SEL__SHIFT 0x1
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_EDID_DETECT_ENABLE_MASK 0x10
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_EDID_DETECT_ENABLE__SHIFT 0x4
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_EDID_DETECT_MODE_MASK 0x20
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_EDID_DETECT_MODE__SHIFT 0x5
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_ENABLE_MASK 0x40
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_ENABLE__SHIFT 0x6
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_CLK_DRIVE_EN_MASK 0x80
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_CLK_DRIVE_EN__SHIFT 0x7
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_INTRA_BYTE_DELAY_MASK 0xff00
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_INTRA_BYTE_DELAY__SHIFT 0x8
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_INTRA_TRANSACTION_DELAY_MASK 0xff0000
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_INTRA_TRANSACTION_DELAY__SHIFT 0x10
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_TIME_LIMIT_MASK 0xff000000
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_TIME_LIMIT__SHIFT 0x18
+#define DC_I2C_EDID_DETECT_CTRL__DC_I2C_EDID_DETECT_WAIT_TIME_MASK 0xffff
+#define DC_I2C_EDID_DETECT_CTRL__DC_I2C_EDID_DETECT_WAIT_TIME__SHIFT 0x0
+#define DC_I2C_EDID_DETECT_CTRL__DC_I2C_EDID_DETECT_NUM_TRIES_UNTIL_VALID_MASK 0xf00000
+#define DC_I2C_EDID_DETECT_CTRL__DC_I2C_EDID_DETECT_NUM_TRIES_UNTIL_VALID__SHIFT 0x14
+#define DC_I2C_EDID_DETECT_CTRL__DC_I2C_EDID_DETECT_SEND_RESET_MASK 0x10000000
+#define DC_I2C_EDID_DETECT_CTRL__DC_I2C_EDID_DETECT_SEND_RESET__SHIFT 0x1c
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC1_READ_REQUEST_OCCURRED_MASK 0x1
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC1_READ_REQUEST_OCCURRED__SHIFT 0x0
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC1_READ_REQUEST_INT_MASK 0x2
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC1_READ_REQUEST_INT__SHIFT 0x1
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC1_READ_REQUEST_ACK_MASK 0x4
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC1_READ_REQUEST_ACK__SHIFT 0x2
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC1_READ_REQUEST_MASK_MASK 0x8
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC1_READ_REQUEST_MASK__SHIFT 0x3
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC2_READ_REQUEST_OCCURRED_MASK 0x10
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC2_READ_REQUEST_OCCURRED__SHIFT 0x4
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC2_READ_REQUEST_INT_MASK 0x20
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC2_READ_REQUEST_INT__SHIFT 0x5
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC2_READ_REQUEST_ACK_MASK 0x40
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC2_READ_REQUEST_ACK__SHIFT 0x6
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC2_READ_REQUEST_MASK_MASK 0x80
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC2_READ_REQUEST_MASK__SHIFT 0x7
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC3_READ_REQUEST_OCCURRED_MASK 0x100
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC3_READ_REQUEST_OCCURRED__SHIFT 0x8
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC3_READ_REQUEST_INT_MASK 0x200
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC3_READ_REQUEST_INT__SHIFT 0x9
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC3_READ_REQUEST_ACK_MASK 0x400
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC3_READ_REQUEST_ACK__SHIFT 0xa
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC3_READ_REQUEST_MASK_MASK 0x800
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC3_READ_REQUEST_MASK__SHIFT 0xb
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC4_READ_REQUEST_OCCURRED_MASK 0x1000
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC4_READ_REQUEST_OCCURRED__SHIFT 0xc
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC4_READ_REQUEST_INT_MASK 0x2000
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC4_READ_REQUEST_INT__SHIFT 0xd
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC4_READ_REQUEST_ACK_MASK 0x4000
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC4_READ_REQUEST_ACK__SHIFT 0xe
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC4_READ_REQUEST_MASK_MASK 0x8000
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC4_READ_REQUEST_MASK__SHIFT 0xf
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC5_READ_REQUEST_OCCURRED_MASK 0x10000
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC5_READ_REQUEST_OCCURRED__SHIFT 0x10
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC5_READ_REQUEST_INT_MASK 0x20000
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC5_READ_REQUEST_INT__SHIFT 0x11
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC5_READ_REQUEST_ACK_MASK 0x40000
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC5_READ_REQUEST_ACK__SHIFT 0x12
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC5_READ_REQUEST_MASK_MASK 0x80000
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC5_READ_REQUEST_MASK__SHIFT 0x13
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC6_READ_REQUEST_OCCURRED_MASK 0x100000
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC6_READ_REQUEST_OCCURRED__SHIFT 0x14
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC6_READ_REQUEST_INT_MASK 0x200000
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC6_READ_REQUEST_INT__SHIFT 0x15
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC6_READ_REQUEST_ACK_MASK 0x400000
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC6_READ_REQUEST_ACK__SHIFT 0x16
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC6_READ_REQUEST_MASK_MASK 0x800000
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC6_READ_REQUEST_MASK__SHIFT 0x17
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDCVGA_READ_REQUEST_OCCURRED_MASK 0x1000000
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDCVGA_READ_REQUEST_OCCURRED__SHIFT 0x18
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDCVGA_READ_REQUEST_INT_MASK 0x2000000
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDCVGA_READ_REQUEST_INT__SHIFT 0x19
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDCVGA_READ_REQUEST_ACK_MASK 0x4000000
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDCVGA_READ_REQUEST_ACK__SHIFT 0x1a
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDCVGA_READ_REQUEST_MASK_MASK 0x8000000
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDCVGA_READ_REQUEST_MASK__SHIFT 0x1b
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC_READ_REQUEST_ACK_ENABLE_MASK 0x40000000
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC_READ_REQUEST_ACK_ENABLE__SHIFT 0x1e
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC_READ_REQUEST_INT_TYPE_MASK 0x80000000
+#define DC_I2C_READ_REQUEST_INTERRUPT__DC_I2C_DDC_READ_REQUEST_INT_TYPE__SHIFT 0x1f
+#define GENERIC_I2C_CONTROL__GENERIC_I2C_GO_MASK 0x1
+#define GENERIC_I2C_CONTROL__GENERIC_I2C_GO__SHIFT 0x0
+#define GENERIC_I2C_CONTROL__GENERIC_I2C_SOFT_RESET_MASK 0x2
+#define GENERIC_I2C_CONTROL__GENERIC_I2C_SOFT_RESET__SHIFT 0x1
+#define GENERIC_I2C_CONTROL__GENERIC_I2C_SEND_RESET_MASK 0x4
+#define GENERIC_I2C_CONTROL__GENERIC_I2C_SEND_RESET__SHIFT 0x2
+#define GENERIC_I2C_CONTROL__GENERIC_I2C_ENABLE_MASK 0x8
+#define GENERIC_I2C_CONTROL__GENERIC_I2C_ENABLE__SHIFT 0x3
+#define GENERIC_I2C_CONTROL__GENERIC_I2C_DBG_REF_SEL_MASK 0x80000000
+#define GENERIC_I2C_CONTROL__GENERIC_I2C_DBG_REF_SEL__SHIFT 0x1f
+#define GENERIC_I2C_INTERRUPT_CONTROL__GENERIC_I2C_DONE_INT_MASK 0x1
+#define GENERIC_I2C_INTERRUPT_CONTROL__GENERIC_I2C_DONE_INT__SHIFT 0x0
+#define GENERIC_I2C_INTERRUPT_CONTROL__GENERIC_I2C_DONE_ACK_MASK 0x2
+#define GENERIC_I2C_INTERRUPT_CONTROL__GENERIC_I2C_DONE_ACK__SHIFT 0x1
+#define GENERIC_I2C_INTERRUPT_CONTROL__GENERIC_I2C_DONE_MASK_MASK 0x4
+#define GENERIC_I2C_INTERRUPT_CONTROL__GENERIC_I2C_DONE_MASK__SHIFT 0x2
+#define GENERIC_I2C_INTERRUPT_CONTROL__GENERIC_I2C_DDC_READ_REQUEST_OCCURRED_MASK 0x100
+#define GENERIC_I2C_INTERRUPT_CONTROL__GENERIC_I2C_DDC_READ_REQUEST_OCCURRED__SHIFT 0x8
+#define GENERIC_I2C_INTERRUPT_CONTROL__GENERIC_I2C_DDC_READ_REQUEST_INT_MASK 0x200
+#define GENERIC_I2C_INTERRUPT_CONTROL__GENERIC_I2C_DDC_READ_REQUEST_INT__SHIFT 0x9
+#define GENERIC_I2C_INTERRUPT_CONTROL__GENERIC_I2C_DDC_READ_REQUEST_ACK_MASK 0x400
+#define GENERIC_I2C_INTERRUPT_CONTROL__GENERIC_I2C_DDC_READ_REQUEST_ACK__SHIFT 0xa
+#define GENERIC_I2C_INTERRUPT_CONTROL__GENERIC_I2C_DDC_READ_REQUEST_MASK_MASK 0x800
+#define GENERIC_I2C_INTERRUPT_CONTROL__GENERIC_I2C_DDC_READ_REQUEST_MASK__SHIFT 0xb
+#define GENERIC_I2C_INTERRUPT_CONTROL__GENERIC_I2C_DDC_READ_REQUEST_INT_TYPE_MASK 0x1000
+#define GENERIC_I2C_INTERRUPT_CONTROL__GENERIC_I2C_DDC_READ_REQUEST_INT_TYPE__SHIFT 0xc
+#define GENERIC_I2C_STATUS__GENERIC_I2C_STATUS_MASK 0xf
+#define GENERIC_I2C_STATUS__GENERIC_I2C_STATUS__SHIFT 0x0
+#define GENERIC_I2C_STATUS__GENERIC_I2C_DONE_MASK 0x10
+#define GENERIC_I2C_STATUS__GENERIC_I2C_DONE__SHIFT 0x4
+#define GENERIC_I2C_STATUS__GENERIC_I2C_ABORTED_MASK 0x20
+#define GENERIC_I2C_STATUS__GENERIC_I2C_ABORTED__SHIFT 0x5
+#define GENERIC_I2C_STATUS__GENERIC_I2C_TIMEOUT_MASK 0x40
+#define GENERIC_I2C_STATUS__GENERIC_I2C_TIMEOUT__SHIFT 0x6
+#define GENERIC_I2C_STATUS__GENERIC_I2C_STOPPED_ON_NACK_MASK 0x200
+#define GENERIC_I2C_STATUS__GENERIC_I2C_STOPPED_ON_NACK__SHIFT 0x9
+#define GENERIC_I2C_STATUS__GENERIC_I2C_NACK_MASK 0x400
+#define GENERIC_I2C_STATUS__GENERIC_I2C_NACK__SHIFT 0xa
+#define GENERIC_I2C_SPEED__GENERIC_I2C_THRESHOLD_MASK 0x3
+#define GENERIC_I2C_SPEED__GENERIC_I2C_THRESHOLD__SHIFT 0x0
+#define GENERIC_I2C_SPEED__GENERIC_I2C_DISABLE_FILTER_DURING_STALL_MASK 0x10
+#define GENERIC_I2C_SPEED__GENERIC_I2C_DISABLE_FILTER_DURING_STALL__SHIFT 0x4
+#define GENERIC_I2C_SPEED__GENERIC_I2C_START_STOP_TIMING_CNTL_MASK 0x300
+#define GENERIC_I2C_SPEED__GENERIC_I2C_START_STOP_TIMING_CNTL__SHIFT 0x8
+#define GENERIC_I2C_SPEED__GENERIC_I2C_PRESCALE_MASK 0xffff0000
+#define GENERIC_I2C_SPEED__GENERIC_I2C_PRESCALE__SHIFT 0x10
+#define GENERIC_I2C_SETUP__GENERIC_I2C_DATA_DRIVE_EN_MASK 0x1
+#define GENERIC_I2C_SETUP__GENERIC_I2C_DATA_DRIVE_EN__SHIFT 0x0
+#define GENERIC_I2C_SETUP__GENERIC_I2C_DATA_DRIVE_SEL_MASK 0x2
+#define GENERIC_I2C_SETUP__GENERIC_I2C_DATA_DRIVE_SEL__SHIFT 0x1
+#define GENERIC_I2C_SETUP__GENERIC_I2C_CLK_DRIVE_EN_MASK 0x80
+#define GENERIC_I2C_SETUP__GENERIC_I2C_CLK_DRIVE_EN__SHIFT 0x7
+#define GENERIC_I2C_SETUP__GENERIC_I2C_INTRA_BYTE_DELAY_MASK 0xff00
+#define GENERIC_I2C_SETUP__GENERIC_I2C_INTRA_BYTE_DELAY__SHIFT 0x8
+#define GENERIC_I2C_SETUP__GENERIC_I2C_TIME_LIMIT_MASK 0xff000000
+#define GENERIC_I2C_SETUP__GENERIC_I2C_TIME_LIMIT__SHIFT 0x18
+#define GENERIC_I2C_TRANSACTION__GENERIC_I2C_RW_MASK 0x1
+#define GENERIC_I2C_TRANSACTION__GENERIC_I2C_RW__SHIFT 0x0
+#define GENERIC_I2C_TRANSACTION__GENERIC_I2C_STOP_ON_NACK_MASK 0x100
+#define GENERIC_I2C_TRANSACTION__GENERIC_I2C_STOP_ON_NACK__SHIFT 0x8
+#define GENERIC_I2C_TRANSACTION__GENERIC_I2C_ACK_ON_READ_MASK 0x200
+#define GENERIC_I2C_TRANSACTION__GENERIC_I2C_ACK_ON_READ__SHIFT 0x9
+#define GENERIC_I2C_TRANSACTION__GENERIC_I2C_START_MASK 0x1000
+#define GENERIC_I2C_TRANSACTION__GENERIC_I2C_START__SHIFT 0xc
+#define GENERIC_I2C_TRANSACTION__GENERIC_I2C_STOP_MASK 0x2000
+#define GENERIC_I2C_TRANSACTION__GENERIC_I2C_STOP__SHIFT 0xd
+#define GENERIC_I2C_TRANSACTION__GENERIC_I2C_COUNT_MASK 0xf0000
+#define GENERIC_I2C_TRANSACTION__GENERIC_I2C_COUNT__SHIFT 0x10
+#define GENERIC_I2C_DATA__GENERIC_I2C_DATA_RW_MASK 0x1
+#define GENERIC_I2C_DATA__GENERIC_I2C_DATA_RW__SHIFT 0x0
+#define GENERIC_I2C_DATA__GENERIC_I2C_DATA_MASK 0xff00
+#define GENERIC_I2C_DATA__GENERIC_I2C_DATA__SHIFT 0x8
+#define GENERIC_I2C_DATA__GENERIC_I2C_INDEX_MASK 0xf0000
+#define GENERIC_I2C_DATA__GENERIC_I2C_INDEX__SHIFT 0x10
+#define GENERIC_I2C_DATA__GENERIC_I2C_INDEX_WRITE_MASK 0x80000000
+#define GENERIC_I2C_DATA__GENERIC_I2C_INDEX_WRITE__SHIFT 0x1f
+#define GENERIC_I2C_PIN_SELECTION__GENERIC_I2C_SCL_PIN_SEL_MASK 0x7f
+#define GENERIC_I2C_PIN_SELECTION__GENERIC_I2C_SCL_PIN_SEL__SHIFT 0x0
+#define GENERIC_I2C_PIN_SELECTION__GENERIC_I2C_SDA_PIN_SEL_MASK 0x7f00
+#define GENERIC_I2C_PIN_SELECTION__GENERIC_I2C_SDA_PIN_SEL__SHIFT 0x8
+#define GENERIC_I2C_PIN_DEBUG__GENERIC_I2C_SCL_OUTPUT_MASK 0x1
+#define GENERIC_I2C_PIN_DEBUG__GENERIC_I2C_SCL_OUTPUT__SHIFT 0x0
+#define GENERIC_I2C_PIN_DEBUG__GENERIC_I2C_SCL_INPUT_MASK 0x2
+#define GENERIC_I2C_PIN_DEBUG__GENERIC_I2C_SCL_INPUT__SHIFT 0x1
+#define GENERIC_I2C_PIN_DEBUG__GENERIC_I2C_SCL_EN_MASK 0x4
+#define GENERIC_I2C_PIN_DEBUG__GENERIC_I2C_SCL_EN__SHIFT 0x2
+#define GENERIC_I2C_PIN_DEBUG__GENERIC_I2C_SDA_OUTPUT_MASK 0x10
+#define GENERIC_I2C_PIN_DEBUG__GENERIC_I2C_SDA_OUTPUT__SHIFT 0x4
+#define GENERIC_I2C_PIN_DEBUG__GENERIC_I2C_SDA_INPUT_MASK 0x20
+#define GENERIC_I2C_PIN_DEBUG__GENERIC_I2C_SDA_INPUT__SHIFT 0x5
+#define GENERIC_I2C_PIN_DEBUG__GENERIC_I2C_SDA_EN_MASK 0x40
+#define GENERIC_I2C_PIN_DEBUG__GENERIC_I2C_SDA_EN__SHIFT 0x6
+#define BLNDV_CONTROL__BLND_GLOBAL_GAIN_MASK 0xff
+#define BLNDV_CONTROL__BLND_GLOBAL_GAIN__SHIFT 0x0
+#define BLNDV_CONTROL__BLND_MODE_MASK 0x300
+#define BLNDV_CONTROL__BLND_MODE__SHIFT 0x8
+#define BLNDV_CONTROL__BLND_STEREO_TYPE_MASK 0xc00
+#define BLNDV_CONTROL__BLND_STEREO_TYPE__SHIFT 0xa
+#define BLNDV_CONTROL__BLND_STEREO_POLARITY_MASK 0x1000
+#define BLNDV_CONTROL__BLND_STEREO_POLARITY__SHIFT 0xc
+#define BLNDV_CONTROL__BLND_FEEDTHROUGH_EN_MASK 0x2000
+#define BLNDV_CONTROL__BLND_FEEDTHROUGH_EN__SHIFT 0xd
+#define BLNDV_CONTROL__BLND_ALPHA_MODE_MASK 0x30000
+#define BLNDV_CONTROL__BLND_ALPHA_MODE__SHIFT 0x10
+#define BLNDV_CONTROL__BLND_ACTIVE_OVERLAP_ONLY_MASK 0x40000
+#define BLNDV_CONTROL__BLND_ACTIVE_OVERLAP_ONLY__SHIFT 0x12
+#define BLNDV_CONTROL__BLND_MULTIPLIED_MODE_MASK 0x100000
+#define BLNDV_CONTROL__BLND_MULTIPLIED_MODE__SHIFT 0x14
+#define BLNDV_CONTROL__BLND_GLOBAL_ALPHA_MASK 0xff000000
+#define BLNDV_CONTROL__BLND_GLOBAL_ALPHA__SHIFT 0x18
+#define BLNDV_SM_CONTROL2__SM_MODE_MASK 0x7
+#define BLNDV_SM_CONTROL2__SM_MODE__SHIFT 0x0
+#define BLNDV_SM_CONTROL2__SM_FRAME_ALTERNATE_MASK 0x10
+#define BLNDV_SM_CONTROL2__SM_FRAME_ALTERNATE__SHIFT 0x4
+#define BLNDV_SM_CONTROL2__SM_FIELD_ALTERNATE_MASK 0x20
+#define BLNDV_SM_CONTROL2__SM_FIELD_ALTERNATE__SHIFT 0x5
+#define BLNDV_SM_CONTROL2__SM_FORCE_NEXT_FRAME_POL_MASK 0x300
+#define BLNDV_SM_CONTROL2__SM_FORCE_NEXT_FRAME_POL__SHIFT 0x8
+#define BLNDV_SM_CONTROL2__SM_FORCE_NEXT_TOP_POL_MASK 0x30000
+#define BLNDV_SM_CONTROL2__SM_FORCE_NEXT_TOP_POL__SHIFT 0x10
+#define BLNDV_SM_CONTROL2__SM_CURRENT_FRAME_POL_MASK 0x1000000
+#define BLNDV_SM_CONTROL2__SM_CURRENT_FRAME_POL__SHIFT 0x18
+#define BLNDV_CONTROL2__PTI_ENABLE_MASK 0x1
+#define BLNDV_CONTROL2__PTI_ENABLE__SHIFT 0x0
+#define BLNDV_CONTROL2__PTI_NEW_PIXEL_GAP_MASK 0x30
+#define BLNDV_CONTROL2__PTI_NEW_PIXEL_GAP__SHIFT 0x4
+#define BLNDV_CONTROL2__BLND_NEW_PIXEL_MODE_MASK 0x40
+#define BLNDV_CONTROL2__BLND_NEW_PIXEL_MODE__SHIFT 0x6
+#define BLNDV_CONTROL2__BLND_SUPERAA_DEGAMMA_EN_MASK 0x80
+#define BLNDV_CONTROL2__BLND_SUPERAA_DEGAMMA_EN__SHIFT 0x7
+#define BLNDV_CONTROL2__BLND_SUPERAA_REGAMMA_EN_MASK 0x100
+#define BLNDV_CONTROL2__BLND_SUPERAA_REGAMMA_EN__SHIFT 0x8
+#define BLNDV_UPDATE__BLND_UPDATE_PENDING_MASK 0x1
+#define BLNDV_UPDATE__BLND_UPDATE_PENDING__SHIFT 0x0
+#define BLNDV_UPDATE__BLND_UPDATE_TAKEN_MASK 0x100
+#define BLNDV_UPDATE__BLND_UPDATE_TAKEN__SHIFT 0x8
+#define BLNDV_UPDATE__BLND_UPDATE_LOCK_MASK 0x10000
+#define BLNDV_UPDATE__BLND_UPDATE_LOCK__SHIFT 0x10
+#define BLNDV_UNDERFLOW_INTERRUPT__BLND_UNDERFLOW_INT_OCCURED_MASK 0x1
+#define BLNDV_UNDERFLOW_INTERRUPT__BLND_UNDERFLOW_INT_OCCURED__SHIFT 0x0
+#define BLNDV_UNDERFLOW_INTERRUPT__BLND_UNDERFLOW_INT_ACK_MASK 0x100
+#define BLNDV_UNDERFLOW_INTERRUPT__BLND_UNDERFLOW_INT_ACK__SHIFT 0x8
+#define BLNDV_UNDERFLOW_INTERRUPT__BLND_UNDERFLOW_INT_MASK_MASK 0x1000
+#define BLNDV_UNDERFLOW_INTERRUPT__BLND_UNDERFLOW_INT_MASK__SHIFT 0xc
+#define BLNDV_UNDERFLOW_INTERRUPT__BLND_UNDERFLOW_INT_PIPE_INDEX_MASK 0x30000
+#define BLNDV_UNDERFLOW_INTERRUPT__BLND_UNDERFLOW_INT_PIPE_INDEX__SHIFT 0x10
+#define BLNDV_V_UPDATE_LOCK__BLND_DCP_GRPH_V_UPDATE_LOCK_MASK 0x1
+#define BLNDV_V_UPDATE_LOCK__BLND_DCP_GRPH_V_UPDATE_LOCK__SHIFT 0x0
+#define BLNDV_V_UPDATE_LOCK__BLND_DCP_GRPH_SURF_V_UPDATE_LOCK_MASK 0x2
+#define BLNDV_V_UPDATE_LOCK__BLND_DCP_GRPH_SURF_V_UPDATE_LOCK__SHIFT 0x1
+#define BLNDV_V_UPDATE_LOCK__BLND_DCP_CUR_V_UPDATE_LOCK_MASK 0x10000
+#define BLNDV_V_UPDATE_LOCK__BLND_DCP_CUR_V_UPDATE_LOCK__SHIFT 0x10
+#define BLNDV_V_UPDATE_LOCK__BLND_DCP_CUR2_V_UPDATE_LOCK_MASK 0x1000000
+#define BLNDV_V_UPDATE_LOCK__BLND_DCP_CUR2_V_UPDATE_LOCK__SHIFT 0x18
+#define BLNDV_V_UPDATE_LOCK__BLND_SCL_V_UPDATE_LOCK_MASK 0x10000000
+#define BLNDV_V_UPDATE_LOCK__BLND_SCL_V_UPDATE_LOCK__SHIFT 0x1c
+#define BLNDV_V_UPDATE_LOCK__BLND_BLND_V_UPDATE_LOCK_MASK 0x20000000
+#define BLNDV_V_UPDATE_LOCK__BLND_BLND_V_UPDATE_LOCK__SHIFT 0x1d
+#define BLNDV_V_UPDATE_LOCK__BLND_V_UPDATE_LOCK_MODE_MASK 0x80000000
+#define BLNDV_V_UPDATE_LOCK__BLND_V_UPDATE_LOCK_MODE__SHIFT 0x1f
+#define BLNDV_REG_UPDATE_STATUS__DCP_BLNDC_GRPH_UPDATE_PENDING_MASK 0x1
+#define BLNDV_REG_UPDATE_STATUS__DCP_BLNDC_GRPH_UPDATE_PENDING__SHIFT 0x0
+#define BLNDV_REG_UPDATE_STATUS__DCP_BLNDO_GRPH_UPDATE_PENDING_MASK 0x2
+#define BLNDV_REG_UPDATE_STATUS__DCP_BLNDO_GRPH_UPDATE_PENDING__SHIFT 0x1
+#define BLNDV_REG_UPDATE_STATUS__DCP_BLNDC_GRPH_SURF_UPDATE_PENDING_MASK 0x4
+#define BLNDV_REG_UPDATE_STATUS__DCP_BLNDC_GRPH_SURF_UPDATE_PENDING__SHIFT 0x2
+#define BLNDV_REG_UPDATE_STATUS__DCP_BLNDO_GRPH_SURF_UPDATE_PENDING_MASK 0x8
+#define BLNDV_REG_UPDATE_STATUS__DCP_BLNDO_GRPH_SURF_UPDATE_PENDING__SHIFT 0x3
+#define BLNDV_REG_UPDATE_STATUS__DCP_BLNDC_CUR_UPDATE_PENDING_MASK 0x40
+#define BLNDV_REG_UPDATE_STATUS__DCP_BLNDC_CUR_UPDATE_PENDING__SHIFT 0x6
+#define BLNDV_REG_UPDATE_STATUS__DCP_BLNDO_CUR_UPDATE_PENDING_MASK 0x80
+#define BLNDV_REG_UPDATE_STATUS__DCP_BLNDO_CUR_UPDATE_PENDING__SHIFT 0x7
+#define BLNDV_REG_UPDATE_STATUS__SCL_BLNDC_UPDATE_PENDING_MASK 0x100
+#define BLNDV_REG_UPDATE_STATUS__SCL_BLNDC_UPDATE_PENDING__SHIFT 0x8
+#define BLNDV_REG_UPDATE_STATUS__SCL_BLNDO_UPDATE_PENDING_MASK 0x200
+#define BLNDV_REG_UPDATE_STATUS__SCL_BLNDO_UPDATE_PENDING__SHIFT 0x9
+#define BLNDV_REG_UPDATE_STATUS__BLND_BLNDC_UPDATE_PENDING_MASK 0x400
+#define BLNDV_REG_UPDATE_STATUS__BLND_BLNDC_UPDATE_PENDING__SHIFT 0xa
+#define BLNDV_REG_UPDATE_STATUS__BLND_BLNDO_UPDATE_PENDING_MASK 0x800
+#define BLNDV_REG_UPDATE_STATUS__BLND_BLNDO_UPDATE_PENDING__SHIFT 0xb
+#define BLNDV_DEBUG__BLND_CNV_MUX_SELECT_MASK 0x1
+#define BLNDV_DEBUG__BLND_CNV_MUX_SELECT__SHIFT 0x0
+#define BLNDV_DEBUG__BLND_DEBUG_MASK 0xfffffffe
+#define BLNDV_DEBUG__BLND_DEBUG__SHIFT 0x1
+#define BLNDV_TEST_DEBUG_INDEX__BLND_TEST_DEBUG_INDEX_MASK 0xff
+#define BLNDV_TEST_DEBUG_INDEX__BLND_TEST_DEBUG_INDEX__SHIFT 0x0
+#define BLNDV_TEST_DEBUG_INDEX__BLND_TEST_DEBUG_WRITE_EN_MASK 0x100
+#define BLNDV_TEST_DEBUG_INDEX__BLND_TEST_DEBUG_WRITE_EN__SHIFT 0x8
+#define BLNDV_TEST_DEBUG_DATA__BLND_TEST_DEBUG_DATA_MASK 0xffffffff
+#define BLNDV_TEST_DEBUG_DATA__BLND_TEST_DEBUG_DATA__SHIFT 0x0
+#define CRTCV_H_TOTAL__CRTC_H_TOTAL_MASK 0x3fff
+#define CRTCV_H_TOTAL__CRTC_H_TOTAL__SHIFT 0x0
+#define CRTCV_H_BLANK_START_END__CRTC_H_BLANK_START_MASK 0x3fff
+#define CRTCV_H_BLANK_START_END__CRTC_H_BLANK_START__SHIFT 0x0
+#define CRTCV_H_BLANK_START_END__CRTC_H_BLANK_END_MASK 0x3fff0000
+#define CRTCV_H_BLANK_START_END__CRTC_H_BLANK_END__SHIFT 0x10
+#define CRTCV_H_SYNC_A__CRTC_H_SYNC_A_START_MASK 0x3fff
+#define CRTCV_H_SYNC_A__CRTC_H_SYNC_A_START__SHIFT 0x0
+#define CRTCV_H_SYNC_A__CRTC_H_SYNC_A_END_MASK 0x3fff0000
+#define CRTCV_H_SYNC_A__CRTC_H_SYNC_A_END__SHIFT 0x10
+#define CRTCV_V_TOTAL__CRTC_V_TOTAL_MASK 0x3fff
+#define CRTCV_V_TOTAL__CRTC_V_TOTAL__SHIFT 0x0
+#define CRTCV_V_BLANK_START_END__CRTC_V_BLANK_START_MASK 0x3fff
+#define CRTCV_V_BLANK_START_END__CRTC_V_BLANK_START__SHIFT 0x0
+#define CRTCV_V_BLANK_START_END__CRTC_V_BLANK_END_MASK 0x3fff0000
+#define CRTCV_V_BLANK_START_END__CRTC_V_BLANK_END__SHIFT 0x10
+#define CRTCV_V_SYNC_A__CRTC_V_SYNC_A_START_MASK 0x3fff
+#define CRTCV_V_SYNC_A__CRTC_V_SYNC_A_START__SHIFT 0x0
+#define CRTCV_V_SYNC_A__CRTC_V_SYNC_A_END_MASK 0x3fff0000
+#define CRTCV_V_SYNC_A__CRTC_V_SYNC_A_END__SHIFT 0x10
+#define CRTCV_CONTROL__CRTC_MASTER_EN_MASK 0x1
+#define CRTCV_CONTROL__CRTC_MASTER_EN__SHIFT 0x0
+#define CRTCV_CONTROL__CRTC_SYNC_RESET_SEL_MASK 0x10
+#define CRTCV_CONTROL__CRTC_SYNC_RESET_SEL__SHIFT 0x4
+#define CRTCV_CONTROL__CRTC_DISABLE_POINT_CNTL_MASK 0x300
+#define CRTCV_CONTROL__CRTC_DISABLE_POINT_CNTL__SHIFT 0x8
+#define CRTCV_CONTROL__CRTC_START_POINT_CNTL_MASK 0x1000
+#define CRTCV_CONTROL__CRTC_START_POINT_CNTL__SHIFT 0xc
+#define CRTCV_CONTROL__CRTC_FIELD_NUMBER_CNTL_MASK 0x2000
+#define CRTCV_CONTROL__CRTC_FIELD_NUMBER_CNTL__SHIFT 0xd
+#define CRTCV_CONTROL__CRTC_FIELD_NUMBER_POLARITY_MASK 0x4000
+#define CRTCV_CONTROL__CRTC_FIELD_NUMBER_POLARITY__SHIFT 0xe
+#define CRTCV_CONTROL__CRTC_CURRENT_MASTER_EN_STATE_MASK 0x10000
+#define CRTCV_CONTROL__CRTC_CURRENT_MASTER_EN_STATE__SHIFT 0x10
+#define CRTCV_CONTROL__CRTC_HBLANK_EARLY_CONTROL_MASK 0x700000
+#define CRTCV_CONTROL__CRTC_HBLANK_EARLY_CONTROL__SHIFT 0x14
+#define CRTCV_CONTROL__CRTC_DISP_READ_REQUEST_DISABLE_MASK 0x1000000
+#define CRTCV_CONTROL__CRTC_DISP_READ_REQUEST_DISABLE__SHIFT 0x18
+#define CRTCV_CONTROL__CRTC_SOF_PULL_EN_MASK 0x20000000
+#define CRTCV_CONTROL__CRTC_SOF_PULL_EN__SHIFT 0x1d
+#define CRTCV_CONTROL__CRTC_AVSYNC_LOCK_SNAPSHOT_MASK 0x40000000
+#define CRTCV_CONTROL__CRTC_AVSYNC_LOCK_SNAPSHOT__SHIFT 0x1e
+#define CRTCV_CONTROL__CRTC_AVSYNC_VSYNC_N_HSYNC_MODE_MASK 0x80000000
+#define CRTCV_CONTROL__CRTC_AVSYNC_VSYNC_N_HSYNC_MODE__SHIFT 0x1f
+#define CRTCV_START_LINE_CONTROL__CRTC_PROGRESSIVE_START_LINE_EARLY_MASK 0x1
+#define CRTCV_START_LINE_CONTROL__CRTC_PROGRESSIVE_START_LINE_EARLY__SHIFT 0x0
+#define CRTCV_START_LINE_CONTROL__CRTC_INTERLACE_START_LINE_EARLY_MASK 0x2
+#define CRTCV_START_LINE_CONTROL__CRTC_INTERLACE_START_LINE_EARLY__SHIFT 0x1
+#define CRTCV_START_LINE_CONTROL__CRTC_PREFETCH_EN_MASK 0x4
+#define CRTCV_START_LINE_CONTROL__CRTC_PREFETCH_EN__SHIFT 0x2
+#define CRTCV_START_LINE_CONTROL__CRTC_LEGACY_REQUESTOR_EN_MASK 0x100
+#define CRTCV_START_LINE_CONTROL__CRTC_LEGACY_REQUESTOR_EN__SHIFT 0x8
+#define CRTCV_START_LINE_CONTROL__CRTC_ADVANCED_START_LINE_POSITION_MASK 0xff000
+#define CRTCV_START_LINE_CONTROL__CRTC_ADVANCED_START_LINE_POSITION__SHIFT 0xc
+#define CRTCV_OVERSCAN_COLOR__CRTC_OVERSCAN_COLOR_BLUE_MASK 0x3ff
+#define CRTCV_OVERSCAN_COLOR__CRTC_OVERSCAN_COLOR_BLUE__SHIFT 0x0
+#define CRTCV_OVERSCAN_COLOR__CRTC_OVERSCAN_COLOR_GREEN_MASK 0xffc00
+#define CRTCV_OVERSCAN_COLOR__CRTC_OVERSCAN_COLOR_GREEN__SHIFT 0xa
+#define CRTCV_OVERSCAN_COLOR__CRTC_OVERSCAN_COLOR_RED_MASK 0x3ff00000
+#define CRTCV_OVERSCAN_COLOR__CRTC_OVERSCAN_COLOR_RED__SHIFT 0x14
+#define CRTCV_OVERSCAN_COLOR_EXT__CRTC_OVERSCAN_COLOR_BLUE_EXT_MASK 0x3
+#define CRTCV_OVERSCAN_COLOR_EXT__CRTC_OVERSCAN_COLOR_BLUE_EXT__SHIFT 0x0
+#define CRTCV_OVERSCAN_COLOR_EXT__CRTC_OVERSCAN_COLOR_GREEN_EXT_MASK 0x300
+#define CRTCV_OVERSCAN_COLOR_EXT__CRTC_OVERSCAN_COLOR_GREEN_EXT__SHIFT 0x8
+#define CRTCV_OVERSCAN_COLOR_EXT__CRTC_OVERSCAN_COLOR_RED_EXT_MASK 0x30000
+#define CRTCV_OVERSCAN_COLOR_EXT__CRTC_OVERSCAN_COLOR_RED_EXT__SHIFT 0x10
+#define CRTCV_BLACK_COLOR__CRTC_BLACK_COLOR_B_CB_MASK 0x3ff
+#define CRTCV_BLACK_COLOR__CRTC_BLACK_COLOR_B_CB__SHIFT 0x0
+#define CRTCV_BLACK_COLOR__CRTC_BLACK_COLOR_G_Y_MASK 0xffc00
+#define CRTCV_BLACK_COLOR__CRTC_BLACK_COLOR_G_Y__SHIFT 0xa
+#define CRTCV_BLACK_COLOR__CRTC_BLACK_COLOR_R_CR_MASK 0x3ff00000
+#define CRTCV_BLACK_COLOR__CRTC_BLACK_COLOR_R_CR__SHIFT 0x14
+#define CRTCV_BLACK_COLOR_EXT__CRTC_BLACK_COLOR_B_CB_EXT_MASK 0x3
+#define CRTCV_BLACK_COLOR_EXT__CRTC_BLACK_COLOR_B_CB_EXT__SHIFT 0x0
+#define CRTCV_BLACK_COLOR_EXT__CRTC_BLACK_COLOR_G_Y_EXT_MASK 0x300
+#define CRTCV_BLACK_COLOR_EXT__CRTC_BLACK_COLOR_G_Y_EXT__SHIFT 0x8
+#define CRTCV_BLACK_COLOR_EXT__CRTC_BLACK_COLOR_R_CR_EXT_MASK 0x30000
+#define CRTCV_BLACK_COLOR_EXT__CRTC_BLACK_COLOR_R_CR_EXT__SHIFT 0x10
+#define CRTCV_CRC_CNTL__CRTC_CRC_EN_MASK 0x1
+#define CRTCV_CRC_CNTL__CRTC_CRC_EN__SHIFT 0x0
+#define CRTCV_CRC_CNTL__CRTC_CRC_CONT_EN_MASK 0x10
+#define CRTCV_CRC_CNTL__CRTC_CRC_CONT_EN__SHIFT 0x4
+#define CRTCV_CRC_CNTL__CRTC_CRC_STEREO_MODE_MASK 0x300
+#define CRTCV_CRC_CNTL__CRTC_CRC_STEREO_MODE__SHIFT 0x8
+#define CRTCV_CRC_CNTL__CRTC_CRC_INTERLACE_MODE_MASK 0x3000
+#define CRTCV_CRC_CNTL__CRTC_CRC_INTERLACE_MODE__SHIFT 0xc
+#define CRTCV_CRC_CNTL__CRTC_CRC_USE_NEW_AND_REPEATED_PIXELS_MASK 0x10000
+#define CRTCV_CRC_CNTL__CRTC_CRC_USE_NEW_AND_REPEATED_PIXELS__SHIFT 0x10
+#define CRTCV_CRC_CNTL__CRTC_CRC0_SELECT_MASK 0x700000
+#define CRTCV_CRC_CNTL__CRTC_CRC0_SELECT__SHIFT 0x14
+#define CRTCV_CRC_CNTL__CRTC_CRC1_SELECT_MASK 0x7000000
+#define CRTCV_CRC_CNTL__CRTC_CRC1_SELECT__SHIFT 0x18
+#define CRTCV_CRC0_WINDOWA_X_CONTROL__CRTC_CRC0_WINDOWA_X_START_MASK 0x3fff
+#define CRTCV_CRC0_WINDOWA_X_CONTROL__CRTC_CRC0_WINDOWA_X_START__SHIFT 0x0
+#define CRTCV_CRC0_WINDOWA_X_CONTROL__CRTC_CRC0_WINDOWA_X_END_MASK 0x3fff0000
+#define CRTCV_CRC0_WINDOWA_X_CONTROL__CRTC_CRC0_WINDOWA_X_END__SHIFT 0x10
+#define CRTCV_CRC0_WINDOWA_Y_CONTROL__CRTC_CRC0_WINDOWA_Y_START_MASK 0x3fff
+#define CRTCV_CRC0_WINDOWA_Y_CONTROL__CRTC_CRC0_WINDOWA_Y_START__SHIFT 0x0
+#define CRTCV_CRC0_WINDOWA_Y_CONTROL__CRTC_CRC0_WINDOWA_Y_END_MASK 0x3fff0000
+#define CRTCV_CRC0_WINDOWA_Y_CONTROL__CRTC_CRC0_WINDOWA_Y_END__SHIFT 0x10
+#define CRTCV_CRC0_WINDOWB_X_CONTROL__CRTC_CRC0_WINDOWB_X_START_MASK 0x3fff
+#define CRTCV_CRC0_WINDOWB_X_CONTROL__CRTC_CRC0_WINDOWB_X_START__SHIFT 0x0
+#define CRTCV_CRC0_WINDOWB_X_CONTROL__CRTC_CRC0_WINDOWB_X_END_MASK 0x3fff0000
+#define CRTCV_CRC0_WINDOWB_X_CONTROL__CRTC_CRC0_WINDOWB_X_END__SHIFT 0x10
+#define CRTCV_CRC0_WINDOWB_Y_CONTROL__CRTC_CRC0_WINDOWB_Y_START_MASK 0x3fff
+#define CRTCV_CRC0_WINDOWB_Y_CONTROL__CRTC_CRC0_WINDOWB_Y_START__SHIFT 0x0
+#define CRTCV_CRC0_WINDOWB_Y_CONTROL__CRTC_CRC0_WINDOWB_Y_END_MASK 0x3fff0000
+#define CRTCV_CRC0_WINDOWB_Y_CONTROL__CRTC_CRC0_WINDOWB_Y_END__SHIFT 0x10
+#define CRTCV_CRC0_DATA_RG__CRC0_R_CR_MASK 0xffff
+#define CRTCV_CRC0_DATA_RG__CRC0_R_CR__SHIFT 0x0
+#define CRTCV_CRC0_DATA_RG__CRC0_G_Y_MASK 0xffff0000
+#define CRTCV_CRC0_DATA_RG__CRC0_G_Y__SHIFT 0x10
+#define CRTCV_CRC0_DATA_B__CRC0_B_CB_MASK 0xffff
+#define CRTCV_CRC0_DATA_B__CRC0_B_CB__SHIFT 0x0
+#define CRTCV_CRC1_WINDOWA_X_CONTROL__CRTC_CRC1_WINDOWA_X_START_MASK 0x3fff
+#define CRTCV_CRC1_WINDOWA_X_CONTROL__CRTC_CRC1_WINDOWA_X_START__SHIFT 0x0
+#define CRTCV_CRC1_WINDOWA_X_CONTROL__CRTC_CRC1_WINDOWA_X_END_MASK 0x3fff0000
+#define CRTCV_CRC1_WINDOWA_X_CONTROL__CRTC_CRC1_WINDOWA_X_END__SHIFT 0x10
+#define CRTCV_CRC1_WINDOWA_Y_CONTROL__CRTC_CRC1_WINDOWA_Y_START_MASK 0x3fff
+#define CRTCV_CRC1_WINDOWA_Y_CONTROL__CRTC_CRC1_WINDOWA_Y_START__SHIFT 0x0
+#define CRTCV_CRC1_WINDOWA_Y_CONTROL__CRTC_CRC1_WINDOWA_Y_END_MASK 0x3fff0000
+#define CRTCV_CRC1_WINDOWA_Y_CONTROL__CRTC_CRC1_WINDOWA_Y_END__SHIFT 0x10
+#define CRTCV_CRC1_WINDOWB_X_CONTROL__CRTC_CRC1_WINDOWB_X_START_MASK 0x3fff
+#define CRTCV_CRC1_WINDOWB_X_CONTROL__CRTC_CRC1_WINDOWB_X_START__SHIFT 0x0
+#define CRTCV_CRC1_WINDOWB_X_CONTROL__CRTC_CRC1_WINDOWB_X_END_MASK 0x3fff0000
+#define CRTCV_CRC1_WINDOWB_X_CONTROL__CRTC_CRC1_WINDOWB_X_END__SHIFT 0x10
+#define CRTCV_CRC1_WINDOWB_Y_CONTROL__CRTC_CRC1_WINDOWB_Y_START_MASK 0x3fff
+#define CRTCV_CRC1_WINDOWB_Y_CONTROL__CRTC_CRC1_WINDOWB_Y_START__SHIFT 0x0
+#define CRTCV_CRC1_WINDOWB_Y_CONTROL__CRTC_CRC1_WINDOWB_Y_END_MASK 0x3fff0000
+#define CRTCV_CRC1_WINDOWB_Y_CONTROL__CRTC_CRC1_WINDOWB_Y_END__SHIFT 0x10
+#define CRTCV_CRC1_DATA_RG__CRC1_R_CR_MASK 0xffff
+#define CRTCV_CRC1_DATA_RG__CRC1_R_CR__SHIFT 0x0
+#define CRTCV_CRC1_DATA_RG__CRC1_G_Y_MASK 0xffff0000
+#define CRTCV_CRC1_DATA_RG__CRC1_G_Y__SHIFT 0x10
+#define CRTCV_CRC1_DATA_B__CRC1_B_CB_MASK 0xffff
+#define CRTCV_CRC1_DATA_B__CRC1_B_CB__SHIFT 0x0
+#define CRTCV_TEST_DEBUG_INDEX__CRTC_TEST_DEBUG_INDEX_MASK 0xff
+#define CRTCV_TEST_DEBUG_INDEX__CRTC_TEST_DEBUG_INDEX__SHIFT 0x0
+#define CRTCV_TEST_DEBUG_INDEX__CRTC_TEST_DEBUG_WRITE_EN_MASK 0x100
+#define CRTCV_TEST_DEBUG_INDEX__CRTC_TEST_DEBUG_WRITE_EN__SHIFT 0x8
+#define CRTCV_TEST_DEBUG_DATA__CRTC_TEST_DEBUG_DATA_MASK 0xffffffff
+#define CRTCV_TEST_DEBUG_DATA__CRTC_TEST_DEBUG_DATA__SHIFT 0x0
+#define XDMA_MC_PCIE_CLIENT_CONFIG__XDMA_MC_PCIE_SWAP_MASK 0x300
+#define XDMA_MC_PCIE_CLIENT_CONFIG__XDMA_MC_PCIE_SWAP__SHIFT 0x8
+#define XDMA_MC_PCIE_CLIENT_CONFIG__XDMA_MC_PCIE_VMID_MASK 0xf000
+#define XDMA_MC_PCIE_CLIENT_CONFIG__XDMA_MC_PCIE_VMID__SHIFT 0xc
+#define XDMA_MC_PCIE_CLIENT_CONFIG__XDMA_MC_PCIE_PRIV_MASK 0x10000
+#define XDMA_MC_PCIE_CLIENT_CONFIG__XDMA_MC_PCIE_PRIV__SHIFT 0x10
+#define XDMA_LOCAL_SURFACE_TILING1__XDMA_LOCAL_ARRAY_MODE_MASK 0xf
+#define XDMA_LOCAL_SURFACE_TILING1__XDMA_LOCAL_ARRAY_MODE__SHIFT 0x0
+#define XDMA_LOCAL_SURFACE_TILING1__XDMA_LOCAL_TILE_SPLIT_MASK 0x70
+#define XDMA_LOCAL_SURFACE_TILING1__XDMA_LOCAL_TILE_SPLIT__SHIFT 0x4
+#define XDMA_LOCAL_SURFACE_TILING1__XDMA_LOCAL_BANK_WIDTH_MASK 0x300
+#define XDMA_LOCAL_SURFACE_TILING1__XDMA_LOCAL_BANK_WIDTH__SHIFT 0x8
+#define XDMA_LOCAL_SURFACE_TILING1__XDMA_LOCAL_BANK_HEIGHT_MASK 0xc00
+#define XDMA_LOCAL_SURFACE_TILING1__XDMA_LOCAL_BANK_HEIGHT__SHIFT 0xa
+#define XDMA_LOCAL_SURFACE_TILING1__XDMA_LOCAL_MACRO_TILE_ASPECT_MASK 0x3000
+#define XDMA_LOCAL_SURFACE_TILING1__XDMA_LOCAL_MACRO_TILE_ASPECT__SHIFT 0xc
+#define XDMA_LOCAL_SURFACE_TILING1__XDMA_LOCAL_NUM_BANKS_MASK 0x300000
+#define XDMA_LOCAL_SURFACE_TILING1__XDMA_LOCAL_NUM_BANKS__SHIFT 0x14
+#define XDMA_LOCAL_SURFACE_TILING2__XDMA_LOCAL_PIPE_INTERLEAVE_SIZE_MASK 0x7
+#define XDMA_LOCAL_SURFACE_TILING2__XDMA_LOCAL_PIPE_INTERLEAVE_SIZE__SHIFT 0x0
+#define XDMA_LOCAL_SURFACE_TILING2__XDMA_LOCAL_MICRO_TILE_MODE_MASK 0x700000
+#define XDMA_LOCAL_SURFACE_TILING2__XDMA_LOCAL_MICRO_TILE_MODE__SHIFT 0x14
+#define XDMA_LOCAL_SURFACE_TILING2__XDMA_LOCAL_PIPE_CONFIG_MASK 0xf8000000
+#define XDMA_LOCAL_SURFACE_TILING2__XDMA_LOCAL_PIPE_CONFIG__SHIFT 0x1b
+#define XDMA_INTERRUPT__XDMA_MSTR_MEM_URGENT_STAT_MASK 0x100
+#define XDMA_INTERRUPT__XDMA_MSTR_MEM_URGENT_STAT__SHIFT 0x8
+#define XDMA_INTERRUPT__XDMA_MSTR_MEM_URGENT_MASK_MASK 0x200
+#define XDMA_INTERRUPT__XDMA_MSTR_MEM_URGENT_MASK__SHIFT 0x9
+#define XDMA_INTERRUPT__XDMA_MSTR_MEM_URGENT_ACK_MASK 0x400
+#define XDMA_INTERRUPT__XDMA_MSTR_MEM_URGENT_ACK__SHIFT 0xa
+#define XDMA_INTERRUPT__XDMA_SLV_READ_URGENT_STAT_MASK 0x10000
+#define XDMA_INTERRUPT__XDMA_SLV_READ_URGENT_STAT__SHIFT 0x10
+#define XDMA_INTERRUPT__XDMA_SLV_READ_URGENT_MASK_MASK 0x20000
+#define XDMA_INTERRUPT__XDMA_SLV_READ_URGENT_MASK__SHIFT 0x11
+#define XDMA_INTERRUPT__XDMA_SLV_READ_URGENT_ACK_MASK 0x40000
+#define XDMA_INTERRUPT__XDMA_SLV_READ_URGENT_ACK__SHIFT 0x12
+#define XDMA_INTERRUPT__XDMA_PERF_MEAS_STAT_MASK 0x100000
+#define XDMA_INTERRUPT__XDMA_PERF_MEAS_STAT__SHIFT 0x14
+#define XDMA_INTERRUPT__XDMA_PERF_MEAS_MASK_MASK 0x200000
+#define XDMA_INTERRUPT__XDMA_PERF_MEAS_MASK__SHIFT 0x15
+#define XDMA_INTERRUPT__XDMA_PERF_MEAS_ACK_MASK 0x400000
+#define XDMA_INTERRUPT__XDMA_PERF_MEAS_ACK__SHIFT 0x16
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_TURN_ON_DELAY_MASK 0xf
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_TURN_ON_DELAY__SHIFT 0x0
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_TURN_OFF_DELAY_MASK 0xff0
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_TURN_OFF_DELAY__SHIFT 0x4
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_GATE_DIS_MASK 0x8000
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_GATE_DIS__SHIFT 0xf
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_REG_GATE_DIS_MASK 0x10000
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_REG_GATE_DIS__SHIFT 0x10
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_G_MDYN_GATE_DIS_PIPE_0_MASK 0x20000
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_G_MDYN_GATE_DIS_PIPE_0__SHIFT 0x11
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_G_MDYN_GATE_DIS_PIPE_1_MASK 0x40000
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_G_MDYN_GATE_DIS_PIPE_1__SHIFT 0x12
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_G_MDYN_GATE_DIS_PIPE_2_MASK 0x80000
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_G_MDYN_GATE_DIS_PIPE_2__SHIFT 0x13
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_G_MDYN_GATE_DIS_PIPE_3_MASK 0x100000
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_G_MDYN_GATE_DIS_PIPE_3__SHIFT 0x14
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_G_MDYN_GATE_DIS_PIPE_4_MASK 0x200000
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_G_MDYN_GATE_DIS_PIPE_4__SHIFT 0x15
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_G_MDYN_GATE_DIS_PIPE_5_MASK 0x400000
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_G_MDYN_GATE_DIS_PIPE_5__SHIFT 0x16
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_G_SDYN_GATE_DIS_MASK 0x800000
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_G_SDYN_GATE_DIS__SHIFT 0x17
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_G_MSTAT_GATE_DIS_MASK 0x1000000
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_G_MSTAT_GATE_DIS__SHIFT 0x18
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_G_SSTAT_GATE_DIS_MASK 0x2000000
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_G_SSTAT_GATE_DIS__SHIFT 0x19
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_CORE_IDLE_STATE_MASK 0x3
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_CORE_IDLE_STATE__SHIFT 0x0
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_IF_IDLE_STATE_MASK 0xc
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_IF_IDLE_STATE__SHIFT 0x2
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_IF_PCIE_STATE_MASK 0x180000
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_IF_PCIE_STATE__SHIFT 0x13
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_IF_PCIE_TRANS_MASK 0x200000
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_IF_PCIE_TRANS__SHIFT 0x15
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_IF_RD_STATE_MASK 0xc00000
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_IF_RD_STATE__SHIFT 0x16
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_IF_RD_TRANS_MASK 0x2000000
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_IF_RD_TRANS__SHIFT 0x19
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_IF_WR_STATE_MASK 0xc000000
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_IF_WR_STATE__SHIFT 0x1a
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_IF_WR_TRANS_MASK 0x10000000
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_IF_WR_TRANS__SHIFT 0x1c
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_IF_BIF_STATE_MASK 0x60000000
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_IF_BIF_STATE__SHIFT 0x1d
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_IF_BIF_TRANS_MASK 0x80000000
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_IF_BIF_TRANS__SHIFT 0x1f
+#define XDMA_IF_BIF_STATUS__XDMA_IF_BIF_ERROR_STATUS_MASK 0xf
+#define XDMA_IF_BIF_STATUS__XDMA_IF_BIF_ERROR_STATUS__SHIFT 0x0
+#define XDMA_IF_BIF_STATUS__XDMA_IF_BIF_ERROR_CLEAR_MASK 0x100
+#define XDMA_IF_BIF_STATUS__XDMA_IF_BIF_ERROR_CLEAR__SHIFT 0x8
+#define XDMA_PERF_MEAS_STATUS__XDMA_PERF_MEAS_STATUS_MASK 0xff
+#define XDMA_PERF_MEAS_STATUS__XDMA_PERF_MEAS_STATUS__SHIFT 0x0
+#define XDMA_IF_STATUS__XDMA_MC_PCIEWR_BUSY_MASK 0x1
+#define XDMA_IF_STATUS__XDMA_MC_PCIEWR_BUSY__SHIFT 0x0
+#define XDMA_TEST_DEBUG_INDEX__XDMA_TEST_DEBUG_INDEX_MASK 0xff
+#define XDMA_TEST_DEBUG_INDEX__XDMA_TEST_DEBUG_INDEX__SHIFT 0x0
+#define XDMA_TEST_DEBUG_INDEX__XDMA_TEST_DEBUG_WRITE_EN_MASK 0x100
+#define XDMA_TEST_DEBUG_INDEX__XDMA_TEST_DEBUG_WRITE_EN__SHIFT 0x8
+#define XDMA_TEST_DEBUG_DATA__XDMA_TEST_DEBUG_DATA_MASK 0xffffffff
+#define XDMA_TEST_DEBUG_DATA__XDMA_TEST_DEBUG_DATA__SHIFT 0x0
+#define XDMA_RBBMIF_RDWR_CNTL__XDMA_RBBMIF_RDWR_DELAY_MASK 0x7
+#define XDMA_RBBMIF_RDWR_CNTL__XDMA_RBBMIF_RDWR_DELAY__SHIFT 0x0
+#define XDMA_RBBMIF_RDWR_CNTL__XDMA_RBBMIF_RDWR_TIMEOUT_DIS_MASK 0x8
+#define XDMA_RBBMIF_RDWR_CNTL__XDMA_RBBMIF_RDWR_TIMEOUT_DIS__SHIFT 0x3
+#define XDMA_RBBMIF_RDWR_CNTL__XDMA_RBBMIF_TIMEOUT_DELAY_MASK 0xffff8000
+#define XDMA_RBBMIF_RDWR_CNTL__XDMA_RBBMIF_TIMEOUT_DELAY__SHIFT 0xf
+#define XDMA_PG_CONTROL__XDMA_PG_CONTROL_MASK 0xffffffff
+#define XDMA_PG_CONTROL__XDMA_PG_CONTROL__SHIFT 0x0
+#define XDMA_PG_WDATA__XDMA_PG_WDATA_MASK 0xffffffff
+#define XDMA_PG_WDATA__XDMA_PG_WDATA__SHIFT 0x0
+#define XDMA_PG_STATUS__XDMA_SERDES_RDATA_MASK 0xffffff
+#define XDMA_PG_STATUS__XDMA_SERDES_RDATA__SHIFT 0x0
+#define XDMA_PG_STATUS__XDMA_PGFSM_READ_READY_MASK 0x1000000
+#define XDMA_PG_STATUS__XDMA_PGFSM_READ_READY__SHIFT 0x18
+#define XDMA_PG_STATUS__XDMA_SERDES_BUSY_MASK 0x2000000
+#define XDMA_PG_STATUS__XDMA_SERDES_BUSY__SHIFT 0x19
+#define XDMA_PG_STATUS__XDMA_SERDES_SMU_POWER_STATUS_MASK 0x4000000
+#define XDMA_PG_STATUS__XDMA_SERDES_SMU_POWER_STATUS__SHIFT 0x1a
+#define XDMA_AON_TEST_DEBUG_INDEX__XDMA_AON_TEST_DEBUG_INDEX_MASK 0xff
+#define XDMA_AON_TEST_DEBUG_INDEX__XDMA_AON_TEST_DEBUG_INDEX__SHIFT 0x0
+#define XDMA_AON_TEST_DEBUG_INDEX__XDMA_AON_TEST_DEBUG_WRITE_EN_MASK 0x100
+#define XDMA_AON_TEST_DEBUG_INDEX__XDMA_AON_TEST_DEBUG_WRITE_EN__SHIFT 0x8
+#define XDMA_AON_TEST_DEBUG_INDEX__XDMA_DEBUG_SEL_MASK 0x200
+#define XDMA_AON_TEST_DEBUG_INDEX__XDMA_DEBUG_SEL__SHIFT 0x9
+#define XDMA_AON_TEST_DEBUG_INDEX__XDMA_DEBUG_OUT_EN_MASK 0x400
+#define XDMA_AON_TEST_DEBUG_INDEX__XDMA_DEBUG_OUT_EN__SHIFT 0xa
+#define XDMA_AON_TEST_DEBUG_DATA__XDMA_AON_TEST_DEBUG_DATA_MASK 0xffffffff
+#define XDMA_AON_TEST_DEBUG_DATA__XDMA_AON_TEST_DEBUG_DATA__SHIFT 0x0
+#define XDMA_MSTR_CNTL__XDMA_MSTR_ALPHA_POSITION_MASK 0x3000
+#define XDMA_MSTR_CNTL__XDMA_MSTR_ALPHA_POSITION__SHIFT 0xc
+#define XDMA_MSTR_CNTL__XDMA_MSTR_MEM_READY_MASK 0x4000
+#define XDMA_MSTR_CNTL__XDMA_MSTR_MEM_READY__SHIFT 0xe
+#define XDMA_MSTR_CNTL__XDMA_MSTR_ENABLE_MASK 0x10000
+#define XDMA_MSTR_CNTL__XDMA_MSTR_ENABLE__SHIFT 0x10
+#define XDMA_MSTR_CNTL__XDMA_MSTR_DEBUG_MODE_MASK 0x40000
+#define XDMA_MSTR_CNTL__XDMA_MSTR_DEBUG_MODE__SHIFT 0x12
+#define XDMA_MSTR_CNTL__XDMA_MSTR_SOFT_RESET_MASK 0x100000
+#define XDMA_MSTR_CNTL__XDMA_MSTR_SOFT_RESET__SHIFT 0x14
+#define XDMA_MSTR_CNTL__XDMA_MSTR_BIF_STALL_EN_MASK 0x200000
+#define XDMA_MSTR_CNTL__XDMA_MSTR_BIF_STALL_EN__SHIFT 0x15
+#define XDMA_MSTR_STATUS__XDMA_MSTR_VCOUNT_CURRENT_MASK 0x3fff
+#define XDMA_MSTR_STATUS__XDMA_MSTR_VCOUNT_CURRENT__SHIFT 0x0
+#define XDMA_MSTR_STATUS__XDMA_MSTR_WRITE_LINE_CURRENT_MASK 0xfff0000
+#define XDMA_MSTR_STATUS__XDMA_MSTR_WRITE_LINE_CURRENT__SHIFT 0x10
+#define XDMA_MSTR_STATUS__XDMA_MSTR_STATUS_SELECT_MASK 0x70000000
+#define XDMA_MSTR_STATUS__XDMA_MSTR_STATUS_SELECT__SHIFT 0x1c
+#define XDMA_MSTR_MEM_CLIENT_CONFIG__XDMA_MSTR_MEM_CLIENT_SWAP_MASK 0x300
+#define XDMA_MSTR_MEM_CLIENT_CONFIG__XDMA_MSTR_MEM_CLIENT_SWAP__SHIFT 0x8
+#define XDMA_MSTR_MEM_CLIENT_CONFIG__XDMA_MSTR_MEM_CLIENT_VMID_MASK 0xf000
+#define XDMA_MSTR_MEM_CLIENT_CONFIG__XDMA_MSTR_MEM_CLIENT_VMID__SHIFT 0xc
+#define XDMA_MSTR_MEM_CLIENT_CONFIG__XDMA_MSTR_MEM_CLIENT_PRIV_MASK 0x10000
+#define XDMA_MSTR_MEM_CLIENT_CONFIG__XDMA_MSTR_MEM_CLIENT_PRIV__SHIFT 0x10
+#define XDMA_MSTR_LOCAL_SURFACE_BASE_ADDR__XDMA_MSTR_LOCAL_SURFACE_BASE_ADDR_MASK 0xffffffff
+#define XDMA_MSTR_LOCAL_SURFACE_BASE_ADDR__XDMA_MSTR_LOCAL_SURFACE_BASE_ADDR__SHIFT 0x0
+#define XDMA_MSTR_LOCAL_SURFACE_BASE_ADDR_HIGH__XDMA_MSTR_LOCAL_SURFACE_BASE_ADDR_HIGH_MASK 0xff
+#define XDMA_MSTR_LOCAL_SURFACE_BASE_ADDR_HIGH__XDMA_MSTR_LOCAL_SURFACE_BASE_ADDR_HIGH__SHIFT 0x0
+#define XDMA_MSTR_LOCAL_SURFACE_PITCH__XDMA_MSTR_LOCAL_SURFACE_PITCH_MASK 0x3fff
+#define XDMA_MSTR_LOCAL_SURFACE_PITCH__XDMA_MSTR_LOCAL_SURFACE_PITCH__SHIFT 0x0
+#define XDMA_MSTR_CMD_URGENT_CNTL__XDMA_MSTR_CMD_CLIENT_STALL_MASK 0x1
+#define XDMA_MSTR_CMD_URGENT_CNTL__XDMA_MSTR_CMD_CLIENT_STALL__SHIFT 0x0
+#define XDMA_MSTR_CMD_URGENT_CNTL__XDMA_MSTR_CMD_URGENT_LEVEL_MASK 0xf00
+#define XDMA_MSTR_CMD_URGENT_CNTL__XDMA_MSTR_CMD_URGENT_LEVEL__SHIFT 0x8
+#define XDMA_MSTR_CMD_URGENT_CNTL__XDMA_MSTR_CMD_STALL_DELAY_MASK 0xf000
+#define XDMA_MSTR_CMD_URGENT_CNTL__XDMA_MSTR_CMD_STALL_DELAY__SHIFT 0xc
+#define XDMA_MSTR_MEM_URGENT_CNTL__XDMA_MSTR_MEM_CLIENT_STALL_MASK 0x1
+#define XDMA_MSTR_MEM_URGENT_CNTL__XDMA_MSTR_MEM_CLIENT_STALL__SHIFT 0x0
+#define XDMA_MSTR_MEM_URGENT_CNTL__XDMA_MSTR_MEM_URGENT_LIMIT_MASK 0xf0
+#define XDMA_MSTR_MEM_URGENT_CNTL__XDMA_MSTR_MEM_URGENT_LIMIT__SHIFT 0x4
+#define XDMA_MSTR_MEM_URGENT_CNTL__XDMA_MSTR_MEM_URGENT_LEVEL_MASK 0xf00
+#define XDMA_MSTR_MEM_URGENT_CNTL__XDMA_MSTR_MEM_URGENT_LEVEL__SHIFT 0x8
+#define XDMA_MSTR_MEM_URGENT_CNTL__XDMA_MSTR_MEM_STALL_DELAY_MASK 0xf000
+#define XDMA_MSTR_MEM_URGENT_CNTL__XDMA_MSTR_MEM_STALL_DELAY__SHIFT 0xc
+#define XDMA_MSTR_MEM_URGENT_CNTL__XDMA_MSTR_MEM_URGENT_TIMER_MASK 0xffff0000
+#define XDMA_MSTR_MEM_URGENT_CNTL__XDMA_MSTR_MEM_URGENT_TIMER__SHIFT 0x10
+#define XDMA_MSTR_PCIE_NACK_STATUS__XDMA_MSTR_PCIE_NACK_TAG_MASK 0x3ff
+#define XDMA_MSTR_PCIE_NACK_STATUS__XDMA_MSTR_PCIE_NACK_TAG__SHIFT 0x0
+#define XDMA_MSTR_PCIE_NACK_STATUS__XDMA_MSTR_PCIE_NACK_MASK 0x3000
+#define XDMA_MSTR_PCIE_NACK_STATUS__XDMA_MSTR_PCIE_NACK__SHIFT 0xc
+#define XDMA_MSTR_PCIE_NACK_STATUS__XDMA_MSTR_PCIE_NACK_CLR_MASK 0x10000
+#define XDMA_MSTR_PCIE_NACK_STATUS__XDMA_MSTR_PCIE_NACK_CLR__SHIFT 0x10
+#define XDMA_MSTR_MEM_NACK_STATUS__XDMA_MSTR_MEM_NACK_TAG_MASK 0x3ff
+#define XDMA_MSTR_MEM_NACK_STATUS__XDMA_MSTR_MEM_NACK_TAG__SHIFT 0x0
+#define XDMA_MSTR_MEM_NACK_STATUS__XDMA_MSTR_MEM_NACK_MASK 0x3000
+#define XDMA_MSTR_MEM_NACK_STATUS__XDMA_MSTR_MEM_NACK__SHIFT 0xc
+#define XDMA_MSTR_MEM_NACK_STATUS__XDMA_MSTR_MEM_NACK_CLR_MASK 0x10000
+#define XDMA_MSTR_MEM_NACK_STATUS__XDMA_MSTR_MEM_NACK_CLR__SHIFT 0x10
+#define XDMA_MSTR_VSYNC_GSL_CHECK__XDMA_MSTR_VSYNC_GSL_CHECK_SEL_MASK 0x7
+#define XDMA_MSTR_VSYNC_GSL_CHECK__XDMA_MSTR_VSYNC_GSL_CHECK_SEL__SHIFT 0x0
+#define XDMA_MSTR_VSYNC_GSL_CHECK__XDMA_MSTR_VSYNC_GSL_CHECK_V_COUNT_MASK 0x3fff00
+#define XDMA_MSTR_VSYNC_GSL_CHECK__XDMA_MSTR_VSYNC_GSL_CHECK_V_COUNT__SHIFT 0x8
+#define XDMA_MSTR_PIPE_CNTL__XDMA_MSTR_CACHE_LINES_MASK 0xff
+#define XDMA_MSTR_PIPE_CNTL__XDMA_MSTR_CACHE_LINES__SHIFT 0x0
+#define XDMA_MSTR_PIPE_CNTL__XDMA_MSTR_READ_REQUEST_MASK 0x100
+#define XDMA_MSTR_PIPE_CNTL__XDMA_MSTR_READ_REQUEST__SHIFT 0x8
+#define XDMA_MSTR_PIPE_CNTL__XDMA_MSTR_PIPE_FRAME_MODE_MASK 0x200
+#define XDMA_MSTR_PIPE_CNTL__XDMA_MSTR_PIPE_FRAME_MODE__SHIFT 0x9
+#define XDMA_MSTR_PIPE_CNTL__XDMA_MSTR_PIPE_SOFT_RESET_MASK 0x400
+#define XDMA_MSTR_PIPE_CNTL__XDMA_MSTR_PIPE_SOFT_RESET__SHIFT 0xa
+#define XDMA_MSTR_PIPE_CNTL__XDMA_MSTR_CACHE_INVALIDATE_MASK 0x800
+#define XDMA_MSTR_PIPE_CNTL__XDMA_MSTR_CACHE_INVALIDATE__SHIFT 0xb
+#define XDMA_MSTR_PIPE_CNTL__XDMA_MSTR_REQUEST_CHANNEL_ID_MASK 0x7000
+#define XDMA_MSTR_PIPE_CNTL__XDMA_MSTR_REQUEST_CHANNEL_ID__SHIFT 0xc
+#define XDMA_MSTR_PIPE_CNTL__XDMA_MSTR_FLIP_MODE_MASK 0x8000
+#define XDMA_MSTR_PIPE_CNTL__XDMA_MSTR_FLIP_MODE__SHIFT 0xf
+#define XDMA_MSTR_PIPE_CNTL__XDMA_MSTR_REQUEST_MIN_MASK 0xff0000
+#define XDMA_MSTR_PIPE_CNTL__XDMA_MSTR_REQUEST_MIN__SHIFT 0x10
+#define XDMA_MSTR_PIPE_CNTL__XDMA_MSTR_PIPE_ACTIVE_MASK 0x1000000
+#define XDMA_MSTR_PIPE_CNTL__XDMA_MSTR_PIPE_ACTIVE__SHIFT 0x18
+#define XDMA_MSTR_PIPE_CNTL__XDMA_MSTR_PIPE_FLUSHING_MASK 0x2000000
+#define XDMA_MSTR_PIPE_CNTL__XDMA_MSTR_PIPE_FLUSHING__SHIFT 0x19
+#define XDMA_MSTR_PIPE_CNTL__XDMA_MSTR_PIPE_FLIP_PENDING_MASK 0x4000000
+#define XDMA_MSTR_PIPE_CNTL__XDMA_MSTR_PIPE_FLIP_PENDING__SHIFT 0x1a
+#define XDMA_MSTR_PIPE_CNTL__XDMA_MSTR_VSYNC_GSL_ENABLE_MASK 0x8000000
+#define XDMA_MSTR_PIPE_CNTL__XDMA_MSTR_VSYNC_GSL_ENABLE__SHIFT 0x1b
+#define XDMA_MSTR_PIPE_CNTL__XDMA_MSTR_SUPERAA_ENABLE_MASK 0x10000000
+#define XDMA_MSTR_PIPE_CNTL__XDMA_MSTR_SUPERAA_ENABLE__SHIFT 0x1c
+#define XDMA_MSTR_PIPE_CNTL__XDMA_MSTR_HSYNC_GSL_GROUP_MASK 0x60000000
+#define XDMA_MSTR_PIPE_CNTL__XDMA_MSTR_HSYNC_GSL_GROUP__SHIFT 0x1d
+#define XDMA_MSTR_PIPE_CNTL__XDMA_MSTR_GSL_GROUP_MASTER_MASK 0x80000000
+#define XDMA_MSTR_PIPE_CNTL__XDMA_MSTR_GSL_GROUP_MASTER__SHIFT 0x1f
+#define XDMA_MSTR_READ_COMMAND__XDMA_MSTR_REQUEST_SIZE_MASK 0x3fff
+#define XDMA_MSTR_READ_COMMAND__XDMA_MSTR_REQUEST_SIZE__SHIFT 0x0
+#define XDMA_MSTR_READ_COMMAND__XDMA_MSTR_REQUEST_PREFETCH_MASK 0x3fff0000
+#define XDMA_MSTR_READ_COMMAND__XDMA_MSTR_REQUEST_PREFETCH__SHIFT 0x10
+#define XDMA_MSTR_CHANNEL_DIM__XDMA_MSTR_CHANNEL_WIDTH_MASK 0x3fff
+#define XDMA_MSTR_CHANNEL_DIM__XDMA_MSTR_CHANNEL_WIDTH__SHIFT 0x0
+#define XDMA_MSTR_CHANNEL_DIM__XDMA_MSTR_CHANNEL_HEIGHT_MASK 0x3fff0000
+#define XDMA_MSTR_CHANNEL_DIM__XDMA_MSTR_CHANNEL_HEIGHT__SHIFT 0x10
+#define XDMA_MSTR_HEIGHT__XDMA_MSTR_ACTIVE_HEIGHT_MASK 0x3fff
+#define XDMA_MSTR_HEIGHT__XDMA_MSTR_ACTIVE_HEIGHT__SHIFT 0x0
+#define XDMA_MSTR_HEIGHT__XDMA_MSTR_FRAME_HEIGHT_MASK 0x3fff0000
+#define XDMA_MSTR_HEIGHT__XDMA_MSTR_FRAME_HEIGHT__SHIFT 0x10
+#define XDMA_MSTR_REMOTE_SURFACE_BASE__XDMA_MSTR_REMOTE_SURFACE_BASE_MASK 0xffffffff
+#define XDMA_MSTR_REMOTE_SURFACE_BASE__XDMA_MSTR_REMOTE_SURFACE_BASE__SHIFT 0x0
+#define XDMA_MSTR_REMOTE_SURFACE_BASE_HIGH__XDMA_MSTR_REMOTE_SURFACE_BASE_HIGH_MASK 0xff
+#define XDMA_MSTR_REMOTE_SURFACE_BASE_HIGH__XDMA_MSTR_REMOTE_SURFACE_BASE_HIGH__SHIFT 0x0
+#define XDMA_MSTR_REMOTE_GPU_ADDRESS__XDMA_MSTR_REMOTE_GPU_ADDRESS_MASK 0xffffffff
+#define XDMA_MSTR_REMOTE_GPU_ADDRESS__XDMA_MSTR_REMOTE_GPU_ADDRESS__SHIFT 0x0
+#define XDMA_MSTR_REMOTE_GPU_ADDRESS_HIGH__XDMA_MSTR_REMOTE_GPU_ADDRESS_HIGH_MASK 0xff
+#define XDMA_MSTR_REMOTE_GPU_ADDRESS_HIGH__XDMA_MSTR_REMOTE_GPU_ADDRESS_HIGH__SHIFT 0x0
+#define XDMA_MSTR_CACHE_BASE_ADDR__XDMA_MSTR_CACHE_BASE_ADDR_MASK 0xffffffff
+#define XDMA_MSTR_CACHE_BASE_ADDR__XDMA_MSTR_CACHE_BASE_ADDR__SHIFT 0x0
+#define XDMA_MSTR_CACHE_BASE_ADDR_HIGH__XDMA_MSTR_CACHE_BASE_ADDR_HIGH_MASK 0xff
+#define XDMA_MSTR_CACHE_BASE_ADDR_HIGH__XDMA_MSTR_CACHE_BASE_ADDR_HIGH__SHIFT 0x0
+#define XDMA_MSTR_CACHE__XDMA_MSTR_CACHE_PITCH_MASK 0x3fff
+#define XDMA_MSTR_CACHE__XDMA_MSTR_CACHE_PITCH__SHIFT 0x0
+#define XDMA_MSTR_CACHE__XDMA_MSTR_CACHE_TLB_PG_STATE_MASK 0x60000000
+#define XDMA_MSTR_CACHE__XDMA_MSTR_CACHE_TLB_PG_STATE__SHIFT 0x1d
+#define XDMA_MSTR_CACHE__XDMA_MSTR_CACHE_TLB_PG_TRANS_MASK 0x80000000
+#define XDMA_MSTR_CACHE__XDMA_MSTR_CACHE_TLB_PG_TRANS__SHIFT 0x1f
+#define XDMA_MSTR_CHANNEL_START__XDMA_MSTR_CHANNEL_START_X_MASK 0x3fff
+#define XDMA_MSTR_CHANNEL_START__XDMA_MSTR_CHANNEL_START_X__SHIFT 0x0
+#define XDMA_MSTR_CHANNEL_START__XDMA_MSTR_CHANNEL_START_Y_MASK 0x3fff0000
+#define XDMA_MSTR_CHANNEL_START__XDMA_MSTR_CHANNEL_START_Y__SHIFT 0x10
+#define XDMA_MSTR_PERFMEAS_STATUS__XDMA_MSTR_PERFMEAS_DATA_MASK 0xffffff
+#define XDMA_MSTR_PERFMEAS_STATUS__XDMA_MSTR_PERFMEAS_DATA__SHIFT 0x0
+#define XDMA_MSTR_PERFMEAS_STATUS__XDMA_MSTR_PERFMEAS_INDEX_MASK 0x7000000
+#define XDMA_MSTR_PERFMEAS_STATUS__XDMA_MSTR_PERFMEAS_INDEX__SHIFT 0x18
+#define XDMA_MSTR_PERFMEAS_STATUS__XDMA_MSTR_PERFMEAS_INDEX_MODE_MASK 0xc0000000
+#define XDMA_MSTR_PERFMEAS_STATUS__XDMA_MSTR_PERFMEAS_INDEX_MODE__SHIFT 0x1e
+#define XDMA_MSTR_PERFMEAS_CNTL__XDMA_MSTR_CACHE_BW_MEAS_ITER_MASK 0xfff
+#define XDMA_MSTR_PERFMEAS_CNTL__XDMA_MSTR_CACHE_BW_MEAS_ITER__SHIFT 0x0
+#define XDMA_MSTR_PERFMEAS_CNTL__XDMA_MSTR_CACHE_BW_SEGID_SEL_MASK 0x1f000
+#define XDMA_MSTR_PERFMEAS_CNTL__XDMA_MSTR_CACHE_BW_SEGID_SEL__SHIFT 0xc
+#define XDMA_MSTR_PERFMEAS_CNTL__XDMA_MSTR_CACHE_BW_COUNTER_RST_MASK 0x20000
+#define XDMA_MSTR_PERFMEAS_CNTL__XDMA_MSTR_CACHE_BW_COUNTER_RST__SHIFT 0x11
+#define XDMA_MSTR_PERFMEAS_CNTL__XDMA_MSTR_LT_MEAS_ITER_MASK 0x7ff80000
+#define XDMA_MSTR_PERFMEAS_CNTL__XDMA_MSTR_LT_MEAS_ITER__SHIFT 0x13
+#define XDMA_MSTR_PERFMEAS_CNTL__XDMA_MSTR_LT_COUNTER_RST_MASK 0x80000000
+#define XDMA_MSTR_PERFMEAS_CNTL__XDMA_MSTR_LT_COUNTER_RST__SHIFT 0x1f
+#define XDMA_SLV_CNTL__XDMA_SLV_READ_LINES_MASK 0x1
+#define XDMA_SLV_CNTL__XDMA_SLV_READ_LINES__SHIFT 0x0
+#define XDMA_SLV_CNTL__XDMA_SLV_MEM_READY_MASK 0x200
+#define XDMA_SLV_CNTL__XDMA_SLV_MEM_READY__SHIFT 0x9
+#define XDMA_SLV_CNTL__XDMA_SLV_ACTIVE_MASK 0x400
+#define XDMA_SLV_CNTL__XDMA_SLV_ACTIVE__SHIFT 0xa
+#define XDMA_SLV_CNTL__XDMA_SLV_ALPHA_POSITION_MASK 0x3000
+#define XDMA_SLV_CNTL__XDMA_SLV_ALPHA_POSITION__SHIFT 0xc
+#define XDMA_SLV_CNTL__XDMA_SLV_ENABLE_MASK 0x10000
+#define XDMA_SLV_CNTL__XDMA_SLV_ENABLE__SHIFT 0x10
+#define XDMA_SLV_CNTL__XDMA_SLV_READ_LAT_TEST_EN_MASK 0x80000
+#define XDMA_SLV_CNTL__XDMA_SLV_READ_LAT_TEST_EN__SHIFT 0x13
+#define XDMA_SLV_CNTL__XDMA_SLV_SOFT_RESET_MASK 0x100000
+#define XDMA_SLV_CNTL__XDMA_SLV_SOFT_RESET__SHIFT 0x14
+#define XDMA_SLV_CNTL__XDMA_SLV_REQ_MAXED_OUT_MASK 0x1000000
+#define XDMA_SLV_CNTL__XDMA_SLV_REQ_MAXED_OUT__SHIFT 0x18
+#define XDMA_SLV_CNTL__XDMA_SLV_WB_BURST_RESET_MASK 0x2000000
+#define XDMA_SLV_CNTL__XDMA_SLV_WB_BURST_RESET__SHIFT 0x19
+#define XDMA_SLV_MEM_CLIENT_CONFIG__XDMA_SLV_MEM_CLIENT_SWAP_MASK 0x300
+#define XDMA_SLV_MEM_CLIENT_CONFIG__XDMA_SLV_MEM_CLIENT_SWAP__SHIFT 0x8
+#define XDMA_SLV_MEM_CLIENT_CONFIG__XDMA_SLV_MEM_CLIENT_VMID_MASK 0xf000
+#define XDMA_SLV_MEM_CLIENT_CONFIG__XDMA_SLV_MEM_CLIENT_VMID__SHIFT 0xc
+#define XDMA_SLV_MEM_CLIENT_CONFIG__XDMA_SLV_MEM_CLIENT_PRIV_MASK 0x10000
+#define XDMA_SLV_MEM_CLIENT_CONFIG__XDMA_SLV_MEM_CLIENT_PRIV__SHIFT 0x10
+#define XDMA_SLV_SLS_PITCH__XDMA_SLV_SLS_PITCH_MASK 0x3fff
+#define XDMA_SLV_SLS_PITCH__XDMA_SLV_SLS_PITCH__SHIFT 0x0
+#define XDMA_SLV_SLS_PITCH__XDMA_SLV_SLS_WIDTH_MASK 0x3fff0000
+#define XDMA_SLV_SLS_PITCH__XDMA_SLV_SLS_WIDTH__SHIFT 0x10
+#define XDMA_SLV_READ_URGENT_CNTL__XDMA_SLV_READ_CLIENT_STALL_MASK 0x1
+#define XDMA_SLV_READ_URGENT_CNTL__XDMA_SLV_READ_CLIENT_STALL__SHIFT 0x0
+#define XDMA_SLV_READ_URGENT_CNTL__XDMA_SLV_READ_URGENT_LIMIT_MASK 0xf0
+#define XDMA_SLV_READ_URGENT_CNTL__XDMA_SLV_READ_URGENT_LIMIT__SHIFT 0x4
+#define XDMA_SLV_READ_URGENT_CNTL__XDMA_SLV_READ_URGENT_LEVEL_MASK 0xf00
+#define XDMA_SLV_READ_URGENT_CNTL__XDMA_SLV_READ_URGENT_LEVEL__SHIFT 0x8
+#define XDMA_SLV_READ_URGENT_CNTL__XDMA_SLV_READ_STALL_DELAY_MASK 0xf000
+#define XDMA_SLV_READ_URGENT_CNTL__XDMA_SLV_READ_STALL_DELAY__SHIFT 0xc
+#define XDMA_SLV_READ_URGENT_CNTL__XDMA_SLV_READ_URGENT_TIMER_MASK 0xffff0000
+#define XDMA_SLV_READ_URGENT_CNTL__XDMA_SLV_READ_URGENT_TIMER__SHIFT 0x10
+#define XDMA_SLV_WRITE_URGENT_CNTL__XDMA_SLV_WRITE_STALL_MASK 0x1
+#define XDMA_SLV_WRITE_URGENT_CNTL__XDMA_SLV_WRITE_STALL__SHIFT 0x0
+#define XDMA_SLV_WRITE_URGENT_CNTL__XDMA_SLV_WRITE_URGENT_LEVEL_MASK 0xf00
+#define XDMA_SLV_WRITE_URGENT_CNTL__XDMA_SLV_WRITE_URGENT_LEVEL__SHIFT 0x8
+#define XDMA_SLV_WRITE_URGENT_CNTL__XDMA_SLV_WRITE_STALL_DELAY_MASK 0xf000
+#define XDMA_SLV_WRITE_URGENT_CNTL__XDMA_SLV_WRITE_STALL_DELAY__SHIFT 0xc
+#define XDMA_SLV_WB_RATE_CNTL__XDMA_SLV_WB_BURST_SIZE_MASK 0x1ff
+#define XDMA_SLV_WB_RATE_CNTL__XDMA_SLV_WB_BURST_SIZE__SHIFT 0x0
+#define XDMA_SLV_WB_RATE_CNTL__XDMA_SLV_WB_BURST_PERIOD_MASK 0xffff0000
+#define XDMA_SLV_WB_RATE_CNTL__XDMA_SLV_WB_BURST_PERIOD__SHIFT 0x10
+#define XDMA_SLV_READ_LATENCY_MINMAX__XDMA_SLV_READ_LATENCY_MIN_MASK 0xffff
+#define XDMA_SLV_READ_LATENCY_MINMAX__XDMA_SLV_READ_LATENCY_MIN__SHIFT 0x0
+#define XDMA_SLV_READ_LATENCY_MINMAX__XDMA_SLV_READ_LATENCY_MAX_MASK 0xffff0000
+#define XDMA_SLV_READ_LATENCY_MINMAX__XDMA_SLV_READ_LATENCY_MAX__SHIFT 0x10
+#define XDMA_SLV_READ_LATENCY_AVE__XDMA_SLV_READ_LATENCY_ACC_MASK 0xfffff
+#define XDMA_SLV_READ_LATENCY_AVE__XDMA_SLV_READ_LATENCY_ACC__SHIFT 0x0
+#define XDMA_SLV_READ_LATENCY_AVE__XDMA_SLV_READ_LATENCY_COUNT_MASK 0xfff00000
+#define XDMA_SLV_READ_LATENCY_AVE__XDMA_SLV_READ_LATENCY_COUNT__SHIFT 0x14
+#define XDMA_SLV_PCIE_NACK_STATUS__XDMA_SLV_PCIE_NACK_TAG_MASK 0x3ff
+#define XDMA_SLV_PCIE_NACK_STATUS__XDMA_SLV_PCIE_NACK_TAG__SHIFT 0x0
+#define XDMA_SLV_PCIE_NACK_STATUS__XDMA_SLV_PCIE_NACK_MASK 0x3000
+#define XDMA_SLV_PCIE_NACK_STATUS__XDMA_SLV_PCIE_NACK__SHIFT 0xc
+#define XDMA_SLV_PCIE_NACK_STATUS__XDMA_SLV_PCIE_NACK_CLR_MASK 0x10000
+#define XDMA_SLV_PCIE_NACK_STATUS__XDMA_SLV_PCIE_NACK_CLR__SHIFT 0x10
+#define XDMA_SLV_MEM_NACK_STATUS__XDMA_SLV_MEM_NACK_TAG_MASK 0xffff
+#define XDMA_SLV_MEM_NACK_STATUS__XDMA_SLV_MEM_NACK_TAG__SHIFT 0x0
+#define XDMA_SLV_MEM_NACK_STATUS__XDMA_SLV_MEM_NACK_MASK 0x30000
+#define XDMA_SLV_MEM_NACK_STATUS__XDMA_SLV_MEM_NACK__SHIFT 0x10
+#define XDMA_SLV_MEM_NACK_STATUS__XDMA_SLV_MEM_NACK_CLR_MASK 0x80000000
+#define XDMA_SLV_MEM_NACK_STATUS__XDMA_SLV_MEM_NACK_CLR__SHIFT 0x1f
+#define XDMA_SLV_RDRET_BUF_STATUS__XDMA_SLV_RDRET_FREE_ENTRIES_MASK 0x3ff
+#define XDMA_SLV_RDRET_BUF_STATUS__XDMA_SLV_RDRET_FREE_ENTRIES__SHIFT 0x0
+#define XDMA_SLV_RDRET_BUF_STATUS__XDMA_SLV_RDRET_BUF_SIZE_MASK 0x3ff000
+#define XDMA_SLV_RDRET_BUF_STATUS__XDMA_SLV_RDRET_BUF_SIZE__SHIFT 0xc
+#define XDMA_SLV_RDRET_BUF_STATUS__XDMA_SLV_RDRET_PG_STATE_MASK 0xc00000
+#define XDMA_SLV_RDRET_BUF_STATUS__XDMA_SLV_RDRET_PG_STATE__SHIFT 0x16
+#define XDMA_SLV_RDRET_BUF_STATUS__XDMA_SLV_RDRET_PG_TRANS_MASK 0x1000000
+#define XDMA_SLV_RDRET_BUF_STATUS__XDMA_SLV_RDRET_PG_TRANS__SHIFT 0x18
+#define XDMA_SLV_READ_LATENCY_TIMER__XDMA_SLV_READ_LATENCY_TIMER_MASK 0xffff
+#define XDMA_SLV_READ_LATENCY_TIMER__XDMA_SLV_READ_LATENCY_TIMER__SHIFT 0x0
+#define XDMA_SLV_FLIP_PENDING__XDMA_SLV_FLIP_PENDING_MASK 0x1
+#define XDMA_SLV_FLIP_PENDING__XDMA_SLV_FLIP_PENDING__SHIFT 0x0
+#define XDMA_SLV_CHANNEL_CNTL__XDMA_SLV_CHANNEL_WEIGHT_MASK 0x1ff
+#define XDMA_SLV_CHANNEL_CNTL__XDMA_SLV_CHANNEL_WEIGHT__SHIFT 0x0
+#define XDMA_SLV_CHANNEL_CNTL__XDMA_SLV_STOP_TRANSFER_MASK 0x10000
+#define XDMA_SLV_CHANNEL_CNTL__XDMA_SLV_STOP_TRANSFER__SHIFT 0x10
+#define XDMA_SLV_CHANNEL_CNTL__XDMA_SLV_CHANNEL_SOFT_RESET_MASK 0x20000
+#define XDMA_SLV_CHANNEL_CNTL__XDMA_SLV_CHANNEL_SOFT_RESET__SHIFT 0x11
+#define XDMA_SLV_CHANNEL_CNTL__XDMA_SLV_CHANNEL_ACTIVE_MASK 0x1000000
+#define XDMA_SLV_CHANNEL_CNTL__XDMA_SLV_CHANNEL_ACTIVE__SHIFT 0x18
+#define XDMA_SLV_REMOTE_GPU_ADDRESS__XDMA_SLV_REMOTE_GPU_ADDRESS_MASK 0xffffffff
+#define XDMA_SLV_REMOTE_GPU_ADDRESS__XDMA_SLV_REMOTE_GPU_ADDRESS__SHIFT 0x0
+#define XDMA_SLV_REMOTE_GPU_ADDRESS_HIGH__XDMA_SLV_REMOTE_GPU_ADDRESS_HIGH_MASK 0xff
+#define XDMA_SLV_REMOTE_GPU_ADDRESS_HIGH__XDMA_SLV_REMOTE_GPU_ADDRESS_HIGH__SHIFT 0x0
+#define CMD_BUS_TX_CONTROL_LANE0__tx_pwr_MASK 0x7
+#define CMD_BUS_TX_CONTROL_LANE0__tx_pwr__SHIFT 0x0
+#define CMD_BUS_TX_CONTROL_LANE0__tx_pg_en_MASK 0x18
+#define CMD_BUS_TX_CONTROL_LANE0__tx_pg_en__SHIFT 0x3
+#define CMD_BUS_TX_CONTROL_LANE0__tx_rdy_MASK 0x100
+#define CMD_BUS_TX_CONTROL_LANE0__tx_rdy__SHIFT 0x8
+#define CMD_BUS_TX_CONTROL_LANE1__tx_pwr_MASK 0x7
+#define CMD_BUS_TX_CONTROL_LANE1__tx_pwr__SHIFT 0x0
+#define CMD_BUS_TX_CONTROL_LANE1__tx_pg_en_MASK 0x18
+#define CMD_BUS_TX_CONTROL_LANE1__tx_pg_en__SHIFT 0x3
+#define CMD_BUS_TX_CONTROL_LANE1__tx_rdy_MASK 0x100
+#define CMD_BUS_TX_CONTROL_LANE1__tx_rdy__SHIFT 0x8
+#define CMD_BUS_TX_CONTROL_LANE2__tx_pwr_MASK 0x7
+#define CMD_BUS_TX_CONTROL_LANE2__tx_pwr__SHIFT 0x0
+#define CMD_BUS_TX_CONTROL_LANE2__tx_pg_en_MASK 0x18
+#define CMD_BUS_TX_CONTROL_LANE2__tx_pg_en__SHIFT 0x3
+#define CMD_BUS_TX_CONTROL_LANE2__tx_rdy_MASK 0x100
+#define CMD_BUS_TX_CONTROL_LANE2__tx_rdy__SHIFT 0x8
+#define CMD_BUS_TX_CONTROL_LANE3__tx_pwr_MASK 0x7
+#define CMD_BUS_TX_CONTROL_LANE3__tx_pwr__SHIFT 0x0
+#define CMD_BUS_TX_CONTROL_LANE3__tx_pg_en_MASK 0x18
+#define CMD_BUS_TX_CONTROL_LANE3__tx_pg_en__SHIFT 0x3
+#define CMD_BUS_TX_CONTROL_LANE3__tx_rdy_MASK 0x100
+#define CMD_BUS_TX_CONTROL_LANE3__tx_rdy__SHIFT 0x8
+#define MARGIN_DEEMPH_LANE0__txmarg_sel_MASK 0x7
+#define MARGIN_DEEMPH_LANE0__txmarg_sel__SHIFT 0x0
+#define MARGIN_DEEMPH_LANE0__deemph_sel_MASK 0x18
+#define MARGIN_DEEMPH_LANE0__deemph_sel__SHIFT 0x3
+#define MARGIN_DEEMPH_LANE0__tx_margin_en_MASK 0x20
+#define MARGIN_DEEMPH_LANE0__tx_margin_en__SHIFT 0x5
+#define MARGIN_DEEMPH_LANE1__txmarg_sel_MASK 0x7
+#define MARGIN_DEEMPH_LANE1__txmarg_sel__SHIFT 0x0
+#define MARGIN_DEEMPH_LANE1__deemph_sel_MASK 0x18
+#define MARGIN_DEEMPH_LANE1__deemph_sel__SHIFT 0x3
+#define MARGIN_DEEMPH_LANE1__tx_margin_en_MASK 0x20
+#define MARGIN_DEEMPH_LANE1__tx_margin_en__SHIFT 0x5
+#define MARGIN_DEEMPH_LANE2__txmarg_sel_MASK 0x7
+#define MARGIN_DEEMPH_LANE2__txmarg_sel__SHIFT 0x0
+#define MARGIN_DEEMPH_LANE2__deemph_sel_MASK 0x18
+#define MARGIN_DEEMPH_LANE2__deemph_sel__SHIFT 0x3
+#define MARGIN_DEEMPH_LANE2__tx_margin_en_MASK 0x20
+#define MARGIN_DEEMPH_LANE2__tx_margin_en__SHIFT 0x5
+#define MARGIN_DEEMPH_LANE3__txmarg_sel_MASK 0x7
+#define MARGIN_DEEMPH_LANE3__txmarg_sel__SHIFT 0x0
+#define MARGIN_DEEMPH_LANE3__deemph_sel_MASK 0x18
+#define MARGIN_DEEMPH_LANE3__deemph_sel__SHIFT 0x3
+#define MARGIN_DEEMPH_LANE3__tx_margin_en_MASK 0x20
+#define MARGIN_DEEMPH_LANE3__tx_margin_en__SHIFT 0x5
+#define CMD_BUS_GLOBAL_FOR_TX_LANE0__twosym_en_MASK 0x6
+#define CMD_BUS_GLOBAL_FOR_TX_LANE0__twosym_en__SHIFT 0x1
+#define CMD_BUS_GLOBAL_FOR_TX_LANE0__link_speed_MASK 0x18
+#define CMD_BUS_GLOBAL_FOR_TX_LANE0__link_speed__SHIFT 0x3
+#define CMD_BUS_GLOBAL_FOR_TX_LANE0__gang_mode_MASK 0xe0
+#define CMD_BUS_GLOBAL_FOR_TX_LANE0__gang_mode__SHIFT 0x5
+#define CMD_BUS_GLOBAL_FOR_TX_LANE0__max_linkrate_MASK 0x300
+#define CMD_BUS_GLOBAL_FOR_TX_LANE0__max_linkrate__SHIFT 0x8
+#define CMD_BUS_GLOBAL_FOR_TX_LANE0__pcs_freq_MASK 0xc00
+#define CMD_BUS_GLOBAL_FOR_TX_LANE0__pcs_freq__SHIFT 0xa
+#define CMD_BUS_GLOBAL_FOR_TX_LANE0__pcs_clken_MASK 0x1000
+#define CMD_BUS_GLOBAL_FOR_TX_LANE0__pcs_clken__SHIFT 0xc
+#define CMD_BUS_GLOBAL_FOR_TX_LANE0__pcs_clkdone_MASK 0x2000
+#define CMD_BUS_GLOBAL_FOR_TX_LANE0__pcs_clkdone__SHIFT 0xd
+#define CMD_BUS_GLOBAL_FOR_TX_LANE0__pll1_always_on_MASK 0x4000
+#define CMD_BUS_GLOBAL_FOR_TX_LANE0__pll1_always_on__SHIFT 0xe
+#define CMD_BUS_GLOBAL_FOR_TX_LANE0__rdclk_div2_en_MASK 0x8000
+#define CMD_BUS_GLOBAL_FOR_TX_LANE0__rdclk_div2_en__SHIFT 0xf
+#define CMD_BUS_GLOBAL_FOR_TX_LANE0__tx_boost_adj_MASK 0xf0000
+#define CMD_BUS_GLOBAL_FOR_TX_LANE0__tx_boost_adj__SHIFT 0x10
+#define CMD_BUS_GLOBAL_FOR_TX_LANE0__tx_boost_en_MASK 0x100000
+#define CMD_BUS_GLOBAL_FOR_TX_LANE0__tx_boost_en__SHIFT 0x14
+#define CMD_BUS_GLOBAL_FOR_TX_LANE0__tx_binary_ron_code_offset_MASK 0xc00000
+#define CMD_BUS_GLOBAL_FOR_TX_LANE0__tx_binary_ron_code_offset__SHIFT 0x16
+#define CMD_BUS_GLOBAL_FOR_TX_LANE1__twosym_en_MASK 0x6
+#define CMD_BUS_GLOBAL_FOR_TX_LANE1__twosym_en__SHIFT 0x1
+#define CMD_BUS_GLOBAL_FOR_TX_LANE1__link_speed_MASK 0x18
+#define CMD_BUS_GLOBAL_FOR_TX_LANE1__link_speed__SHIFT 0x3
+#define CMD_BUS_GLOBAL_FOR_TX_LANE1__gang_mode_MASK 0xe0
+#define CMD_BUS_GLOBAL_FOR_TX_LANE1__gang_mode__SHIFT 0x5
+#define CMD_BUS_GLOBAL_FOR_TX_LANE1__max_linkrate_MASK 0x300
+#define CMD_BUS_GLOBAL_FOR_TX_LANE1__max_linkrate__SHIFT 0x8
+#define CMD_BUS_GLOBAL_FOR_TX_LANE1__pcs_freq_MASK 0xc00
+#define CMD_BUS_GLOBAL_FOR_TX_LANE1__pcs_freq__SHIFT 0xa
+#define CMD_BUS_GLOBAL_FOR_TX_LANE1__pcs_clken_MASK 0x1000
+#define CMD_BUS_GLOBAL_FOR_TX_LANE1__pcs_clken__SHIFT 0xc
+#define CMD_BUS_GLOBAL_FOR_TX_LANE1__pcs_clkdone_MASK 0x2000
+#define CMD_BUS_GLOBAL_FOR_TX_LANE1__pcs_clkdone__SHIFT 0xd
+#define CMD_BUS_GLOBAL_FOR_TX_LANE1__pll1_always_on_MASK 0x4000
+#define CMD_BUS_GLOBAL_FOR_TX_LANE1__pll1_always_on__SHIFT 0xe
+#define CMD_BUS_GLOBAL_FOR_TX_LANE1__rdclk_div2_en_MASK 0x8000
+#define CMD_BUS_GLOBAL_FOR_TX_LANE1__rdclk_div2_en__SHIFT 0xf
+#define CMD_BUS_GLOBAL_FOR_TX_LANE1__tx_boost_adj_MASK 0xf0000
+#define CMD_BUS_GLOBAL_FOR_TX_LANE1__tx_boost_adj__SHIFT 0x10
+#define CMD_BUS_GLOBAL_FOR_TX_LANE1__tx_boost_en_MASK 0x100000
+#define CMD_BUS_GLOBAL_FOR_TX_LANE1__tx_boost_en__SHIFT 0x14
+#define CMD_BUS_GLOBAL_FOR_TX_LANE1__tx_binary_ron_code_offset_MASK 0xc00000
+#define CMD_BUS_GLOBAL_FOR_TX_LANE1__tx_binary_ron_code_offset__SHIFT 0x16
+#define CMD_BUS_GLOBAL_FOR_TX_LANE2__twosym_en_MASK 0x6
+#define CMD_BUS_GLOBAL_FOR_TX_LANE2__twosym_en__SHIFT 0x1
+#define CMD_BUS_GLOBAL_FOR_TX_LANE2__link_speed_MASK 0x18
+#define CMD_BUS_GLOBAL_FOR_TX_LANE2__link_speed__SHIFT 0x3
+#define CMD_BUS_GLOBAL_FOR_TX_LANE2__gang_mode_MASK 0xe0
+#define CMD_BUS_GLOBAL_FOR_TX_LANE2__gang_mode__SHIFT 0x5
+#define CMD_BUS_GLOBAL_FOR_TX_LANE2__max_linkrate_MASK 0x300
+#define CMD_BUS_GLOBAL_FOR_TX_LANE2__max_linkrate__SHIFT 0x8
+#define CMD_BUS_GLOBAL_FOR_TX_LANE2__pcs_freq_MASK 0xc00
+#define CMD_BUS_GLOBAL_FOR_TX_LANE2__pcs_freq__SHIFT 0xa
+#define CMD_BUS_GLOBAL_FOR_TX_LANE2__pcs_clken_MASK 0x1000
+#define CMD_BUS_GLOBAL_FOR_TX_LANE2__pcs_clken__SHIFT 0xc
+#define CMD_BUS_GLOBAL_FOR_TX_LANE2__pcs_clkdone_MASK 0x2000
+#define CMD_BUS_GLOBAL_FOR_TX_LANE2__pcs_clkdone__SHIFT 0xd
+#define CMD_BUS_GLOBAL_FOR_TX_LANE2__pll1_always_on_MASK 0x4000
+#define CMD_BUS_GLOBAL_FOR_TX_LANE2__pll1_always_on__SHIFT 0xe
+#define CMD_BUS_GLOBAL_FOR_TX_LANE2__rdclk_div2_en_MASK 0x8000
+#define CMD_BUS_GLOBAL_FOR_TX_LANE2__rdclk_div2_en__SHIFT 0xf
+#define CMD_BUS_GLOBAL_FOR_TX_LANE2__tx_boost_adj_MASK 0xf0000
+#define CMD_BUS_GLOBAL_FOR_TX_LANE2__tx_boost_adj__SHIFT 0x10
+#define CMD_BUS_GLOBAL_FOR_TX_LANE2__tx_boost_en_MASK 0x100000
+#define CMD_BUS_GLOBAL_FOR_TX_LANE2__tx_boost_en__SHIFT 0x14
+#define CMD_BUS_GLOBAL_FOR_TX_LANE2__tx_binary_ron_code_offset_MASK 0xc00000
+#define CMD_BUS_GLOBAL_FOR_TX_LANE2__tx_binary_ron_code_offset__SHIFT 0x16
+#define CMD_BUS_GLOBAL_FOR_TX_LANE3__twosym_en_MASK 0x6
+#define CMD_BUS_GLOBAL_FOR_TX_LANE3__twosym_en__SHIFT 0x1
+#define CMD_BUS_GLOBAL_FOR_TX_LANE3__link_speed_MASK 0x18
+#define CMD_BUS_GLOBAL_FOR_TX_LANE3__link_speed__SHIFT 0x3
+#define CMD_BUS_GLOBAL_FOR_TX_LANE3__gang_mode_MASK 0xe0
+#define CMD_BUS_GLOBAL_FOR_TX_LANE3__gang_mode__SHIFT 0x5
+#define CMD_BUS_GLOBAL_FOR_TX_LANE3__max_linkrate_MASK 0x300
+#define CMD_BUS_GLOBAL_FOR_TX_LANE3__max_linkrate__SHIFT 0x8
+#define CMD_BUS_GLOBAL_FOR_TX_LANE3__pcs_freq_MASK 0xc00
+#define CMD_BUS_GLOBAL_FOR_TX_LANE3__pcs_freq__SHIFT 0xa
+#define CMD_BUS_GLOBAL_FOR_TX_LANE3__pcs_clken_MASK 0x1000
+#define CMD_BUS_GLOBAL_FOR_TX_LANE3__pcs_clken__SHIFT 0xc
+#define CMD_BUS_GLOBAL_FOR_TX_LANE3__pcs_clkdone_MASK 0x2000
+#define CMD_BUS_GLOBAL_FOR_TX_LANE3__pcs_clkdone__SHIFT 0xd
+#define CMD_BUS_GLOBAL_FOR_TX_LANE3__pll1_always_on_MASK 0x4000
+#define CMD_BUS_GLOBAL_FOR_TX_LANE3__pll1_always_on__SHIFT 0xe
+#define CMD_BUS_GLOBAL_FOR_TX_LANE3__rdclk_div2_en_MASK 0x8000
+#define CMD_BUS_GLOBAL_FOR_TX_LANE3__rdclk_div2_en__SHIFT 0xf
+#define CMD_BUS_GLOBAL_FOR_TX_LANE3__tx_boost_adj_MASK 0xf0000
+#define CMD_BUS_GLOBAL_FOR_TX_LANE3__tx_boost_adj__SHIFT 0x10
+#define CMD_BUS_GLOBAL_FOR_TX_LANE3__tx_boost_en_MASK 0x100000
+#define CMD_BUS_GLOBAL_FOR_TX_LANE3__tx_boost_en__SHIFT 0x14
+#define CMD_BUS_GLOBAL_FOR_TX_LANE3__tx_binary_ron_code_offset_MASK 0xc00000
+#define CMD_BUS_GLOBAL_FOR_TX_LANE3__tx_binary_ron_code_offset__SHIFT 0x16
+#define TX_DISP_RFU0_LANE0__rfu_value0_MASK 0xffffffff
+#define TX_DISP_RFU0_LANE0__rfu_value0__SHIFT 0x0
+#define TX_DISP_RFU0_LANE1__rfu_value0_MASK 0xffffffff
+#define TX_DISP_RFU0_LANE1__rfu_value0__SHIFT 0x0
+#define TX_DISP_RFU0_LANE2__rfu_value0_MASK 0xffffffff
+#define TX_DISP_RFU0_LANE2__rfu_value0__SHIFT 0x0
+#define TX_DISP_RFU0_LANE3__rfu_value0_MASK 0xffffffff
+#define TX_DISP_RFU0_LANE3__rfu_value0__SHIFT 0x0
+#define TX_DISP_RFU1_LANE0__rfu_value1_MASK 0xffffffff
+#define TX_DISP_RFU1_LANE0__rfu_value1__SHIFT 0x0
+#define TX_DISP_RFU1_LANE1__rfu_value1_MASK 0xffffffff
+#define TX_DISP_RFU1_LANE1__rfu_value1__SHIFT 0x0
+#define TX_DISP_RFU1_LANE2__rfu_value1_MASK 0xffffffff
+#define TX_DISP_RFU1_LANE2__rfu_value1__SHIFT 0x0
+#define TX_DISP_RFU1_LANE3__rfu_value1_MASK 0xffffffff
+#define TX_DISP_RFU1_LANE3__rfu_value1__SHIFT 0x0
+#define TX_DISP_RFU2_LANE0__rfu_value2_MASK 0xffffffff
+#define TX_DISP_RFU2_LANE0__rfu_value2__SHIFT 0x0
+#define TX_DISP_RFU2_LANE1__rfu_value2_MASK 0xffffffff
+#define TX_DISP_RFU2_LANE1__rfu_value2__SHIFT 0x0
+#define TX_DISP_RFU2_LANE2__rfu_value2_MASK 0xffffffff
+#define TX_DISP_RFU2_LANE2__rfu_value2__SHIFT 0x0
+#define TX_DISP_RFU2_LANE3__rfu_value2_MASK 0xffffffff
+#define TX_DISP_RFU2_LANE3__rfu_value2__SHIFT 0x0
+#define TX_DISP_RFU3_LANE0__rfu_value3_MASK 0xffffffff
+#define TX_DISP_RFU3_LANE0__rfu_value3__SHIFT 0x0
+#define TX_DISP_RFU3_LANE1__rfu_value3_MASK 0xffffffff
+#define TX_DISP_RFU3_LANE1__rfu_value3__SHIFT 0x0
+#define TX_DISP_RFU3_LANE2__rfu_value3_MASK 0xffffffff
+#define TX_DISP_RFU3_LANE2__rfu_value3__SHIFT 0x0
+#define TX_DISP_RFU3_LANE3__rfu_value3_MASK 0xffffffff
+#define TX_DISP_RFU3_LANE3__rfu_value3__SHIFT 0x0
+#define TX_DISP_RFU4_LANE0__rfu_value4_MASK 0xffffffff
+#define TX_DISP_RFU4_LANE0__rfu_value4__SHIFT 0x0
+#define TX_DISP_RFU4_LANE1__rfu_value4_MASK 0xffffffff
+#define TX_DISP_RFU4_LANE1__rfu_value4__SHIFT 0x0
+#define TX_DISP_RFU4_LANE2__rfu_value4_MASK 0xffffffff
+#define TX_DISP_RFU4_LANE2__rfu_value4__SHIFT 0x0
+#define TX_DISP_RFU4_LANE3__rfu_value4_MASK 0xffffffff
+#define TX_DISP_RFU4_LANE3__rfu_value4__SHIFT 0x0
+#define TX_DISP_RFU5_LANE0__rfu_value5_MASK 0xffffffff
+#define TX_DISP_RFU5_LANE0__rfu_value5__SHIFT 0x0
+#define TX_DISP_RFU5_LANE1__rfu_value5_MASK 0xffffffff
+#define TX_DISP_RFU5_LANE1__rfu_value5__SHIFT 0x0
+#define TX_DISP_RFU5_LANE2__rfu_value5_MASK 0xffffffff
+#define TX_DISP_RFU5_LANE2__rfu_value5__SHIFT 0x0
+#define TX_DISP_RFU5_LANE3__rfu_value5_MASK 0xffffffff
+#define TX_DISP_RFU5_LANE3__rfu_value5__SHIFT 0x0
+#define TX_DISP_RFU6_LANE0__rfu_value6_MASK 0xffffffff
+#define TX_DISP_RFU6_LANE0__rfu_value6__SHIFT 0x0
+#define TX_DISP_RFU6_LANE1__rfu_value6_MASK 0xffffffff
+#define TX_DISP_RFU6_LANE1__rfu_value6__SHIFT 0x0
+#define TX_DISP_RFU6_LANE2__rfu_value6_MASK 0xffffffff
+#define TX_DISP_RFU6_LANE2__rfu_value6__SHIFT 0x0
+#define TX_DISP_RFU6_LANE3__rfu_value6_MASK 0xffffffff
+#define TX_DISP_RFU6_LANE3__rfu_value6__SHIFT 0x0
+#define TX_DISP_RFU7_LANE0__rfu_value7_MASK 0xffffffff
+#define TX_DISP_RFU7_LANE0__rfu_value7__SHIFT 0x0
+#define TX_DISP_RFU7_LANE1__rfu_value7_MASK 0xffffffff
+#define TX_DISP_RFU7_LANE1__rfu_value7__SHIFT 0x0
+#define TX_DISP_RFU7_LANE2__rfu_value7_MASK 0xffffffff
+#define TX_DISP_RFU7_LANE2__rfu_value7__SHIFT 0x0
+#define TX_DISP_RFU7_LANE3__rfu_value7_MASK 0xffffffff
+#define TX_DISP_RFU7_LANE3__rfu_value7__SHIFT 0x0
+#define TX_DISP_RFU8_LANE0__rfu_value8_MASK 0xffffffff
+#define TX_DISP_RFU8_LANE0__rfu_value8__SHIFT 0x0
+#define TX_DISP_RFU8_LANE1__rfu_value8_MASK 0xffffffff
+#define TX_DISP_RFU8_LANE1__rfu_value8__SHIFT 0x0
+#define TX_DISP_RFU8_LANE2__rfu_value8_MASK 0xffffffff
+#define TX_DISP_RFU8_LANE2__rfu_value8__SHIFT 0x0
+#define TX_DISP_RFU8_LANE3__rfu_value8_MASK 0xffffffff
+#define TX_DISP_RFU8_LANE3__rfu_value8__SHIFT 0x0
+#define TX_DISP_RFU9_LANE0__rfu_value9_MASK 0xffffffff
+#define TX_DISP_RFU9_LANE0__rfu_value9__SHIFT 0x0
+#define TX_DISP_RFU9_LANE1__rfu_value9_MASK 0xffffffff
+#define TX_DISP_RFU9_LANE1__rfu_value9__SHIFT 0x0
+#define TX_DISP_RFU9_LANE2__rfu_value9_MASK 0xffffffff
+#define TX_DISP_RFU9_LANE2__rfu_value9__SHIFT 0x0
+#define TX_DISP_RFU9_LANE3__rfu_value9_MASK 0xffffffff
+#define TX_DISP_RFU9_LANE3__rfu_value9__SHIFT 0x0
+#define TX_DISP_RFU10_LANE0__rfu_value10_MASK 0xffffffff
+#define TX_DISP_RFU10_LANE0__rfu_value10__SHIFT 0x0
+#define TX_DISP_RFU10_LANE1__rfu_value10_MASK 0xffffffff
+#define TX_DISP_RFU10_LANE1__rfu_value10__SHIFT 0x0
+#define TX_DISP_RFU10_LANE2__rfu_value10_MASK 0xffffffff
+#define TX_DISP_RFU10_LANE2__rfu_value10__SHIFT 0x0
+#define TX_DISP_RFU10_LANE3__rfu_value10_MASK 0xffffffff
+#define TX_DISP_RFU10_LANE3__rfu_value10__SHIFT 0x0
+#define TX_DISP_RFU11_LANE0__rfu_value11_MASK 0xffffffff
+#define TX_DISP_RFU11_LANE0__rfu_value11__SHIFT 0x0
+#define TX_DISP_RFU11_LANE1__rfu_value11_MASK 0xffffffff
+#define TX_DISP_RFU11_LANE1__rfu_value11__SHIFT 0x0
+#define TX_DISP_RFU11_LANE2__rfu_value11_MASK 0xffffffff
+#define TX_DISP_RFU11_LANE2__rfu_value11__SHIFT 0x0
+#define TX_DISP_RFU11_LANE3__rfu_value11_MASK 0xffffffff
+#define TX_DISP_RFU11_LANE3__rfu_value11__SHIFT 0x0
+#define TX_DISP_RFU12_LANE0__rfu_value12_MASK 0xffffffff
+#define TX_DISP_RFU12_LANE0__rfu_value12__SHIFT 0x0
+#define TX_DISP_RFU12_LANE1__rfu_value12_MASK 0xffffffff
+#define TX_DISP_RFU12_LANE1__rfu_value12__SHIFT 0x0
+#define TX_DISP_RFU12_LANE2__rfu_value12_MASK 0xffffffff
+#define TX_DISP_RFU12_LANE2__rfu_value12__SHIFT 0x0
+#define TX_DISP_RFU12_LANE3__rfu_value12_MASK 0xffffffff
+#define TX_DISP_RFU12_LANE3__rfu_value12__SHIFT 0x0
+#define COMMON_MAR_DEEMPH_NOM__tx_margin_nom_MASK 0xff
+#define COMMON_MAR_DEEMPH_NOM__tx_margin_nom__SHIFT 0x0
+#define COMMON_MAR_DEEMPH_NOM__deemph_gen1_nom_MASK 0xff00
+#define COMMON_MAR_DEEMPH_NOM__deemph_gen1_nom__SHIFT 0x8
+#define COMMON_MAR_DEEMPH_NOM__deemph35_gen2_nom_MASK 0xff0000
+#define COMMON_MAR_DEEMPH_NOM__deemph35_gen2_nom__SHIFT 0x10
+#define COMMON_MAR_DEEMPH_NOM__deemph60_gen2_nom_MASK 0xff000000
+#define COMMON_MAR_DEEMPH_NOM__deemph60_gen2_nom__SHIFT 0x18
+#define COMMON_LANE_PWRMGMT__pgdelay_MASK 0xf
+#define COMMON_LANE_PWRMGMT__pgdelay__SHIFT 0x0
+#define COMMON_LANE_PWRMGMT__pgmask_MASK 0x3f0
+#define COMMON_LANE_PWRMGMT__pgmask__SHIFT 0x4
+#define COMMON_LANE_PWRMGMT__vprot_en_MASK 0x800
+#define COMMON_LANE_PWRMGMT__vprot_en__SHIFT 0xb
+#define COMMON_TXCNTRL__rdptr_rst_val_gen3_MASK 0x1f
+#define COMMON_TXCNTRL__rdptr_rst_val_gen3__SHIFT 0x0
+#define COMMON_TXCNTRL__clkgate_dis_MASK 0x20
+#define COMMON_TXCNTRL__clkgate_dis__SHIFT 0x5
+#define COMMON_TXCNTRL__slew_rate_ctl_gen1_MASK 0x1c0
+#define COMMON_TXCNTRL__slew_rate_ctl_gen1__SHIFT 0x6
+#define COMMON_TXCNTRL__slew_rate_ctl_gen2_MASK 0xe00
+#define COMMON_TXCNTRL__slew_rate_ctl_gen2__SHIFT 0x9
+#define COMMON_TXCNTRL__slew_rate_ctl_gen3_MASK 0x7000
+#define COMMON_TXCNTRL__slew_rate_ctl_gen3__SHIFT 0xc
+#define COMMON_TXCNTRL__dual_dvi_mstr_en_MASK 0x8000
+#define COMMON_TXCNTRL__dual_dvi_mstr_en__SHIFT 0xf
+#define COMMON_TXCNTRL__dual_dvi_en_MASK 0x10000
+#define COMMON_TXCNTRL__dual_dvi_en__SHIFT 0x10
+#define COMMON_TMDP__tmdp_spare_MASK 0xffffffff
+#define COMMON_TMDP__tmdp_spare__SHIFT 0x0
+#define COMMON_LANE_RESETS__lane_0_reset_l_MASK 0x1
+#define COMMON_LANE_RESETS__lane_0_reset_l__SHIFT 0x0
+#define COMMON_LANE_RESETS__lane_1_reset_l_MASK 0x2
+#define COMMON_LANE_RESETS__lane_1_reset_l__SHIFT 0x1
+#define COMMON_LANE_RESETS__lane_2_reset_l_MASK 0x4
+#define COMMON_LANE_RESETS__lane_2_reset_l__SHIFT 0x2
+#define COMMON_LANE_RESETS__lane_3_reset_l_MASK 0x8
+#define COMMON_LANE_RESETS__lane_3_reset_l__SHIFT 0x3
+#define COMMON_LANE_RESETS__lane_4_reset_l_MASK 0x10
+#define COMMON_LANE_RESETS__lane_4_reset_l__SHIFT 0x4
+#define COMMON_LANE_RESETS__lane_5_reset_l_MASK 0x20
+#define COMMON_LANE_RESETS__lane_5_reset_l__SHIFT 0x5
+#define COMMON_LANE_RESETS__lane_6_reset_l_MASK 0x40
+#define COMMON_LANE_RESETS__lane_6_reset_l__SHIFT 0x6
+#define COMMON_LANE_RESETS__lane_7_reset_l_MASK 0x80
+#define COMMON_LANE_RESETS__lane_7_reset_l__SHIFT 0x7
+#define COMMON_ZCALCODE_CTRL__zcalcode_override_MASK 0x1
+#define COMMON_ZCALCODE_CTRL__zcalcode_override__SHIFT 0x0
+#define COMMON_ZCALCODE_CTRL__tx_binary_code_override_val_MASK 0x3e
+#define COMMON_ZCALCODE_CTRL__tx_binary_code_override_val__SHIFT 0x1
+#define COMMON_ZCALCODE_CTRL__tx_driver_fifty_ohms_MASK 0x200000
+#define COMMON_ZCALCODE_CTRL__tx_driver_fifty_ohms__SHIFT 0x15
+#define COMMON_DISP_RFU1__rfu_value1_MASK 0xffffffff
+#define COMMON_DISP_RFU1__rfu_value1__SHIFT 0x0
+#define COMMON_DISP_RFU2__rfu_value2_MASK 0xffffffff
+#define COMMON_DISP_RFU2__rfu_value2__SHIFT 0x0
+#define COMMON_DISP_RFU3__rfu_value3_MASK 0xffffffff
+#define COMMON_DISP_RFU3__rfu_value3__SHIFT 0x0
+#define COMMON_DISP_RFU4__rfu_value4_MASK 0xffffffff
+#define COMMON_DISP_RFU4__rfu_value4__SHIFT 0x0
+#define COMMON_DISP_RFU5__rfu_value5_MASK 0xffffffff
+#define COMMON_DISP_RFU5__rfu_value5__SHIFT 0x0
+#define COMMON_DISP_RFU6__rfu_value6_MASK 0xffffffff
+#define COMMON_DISP_RFU6__rfu_value6__SHIFT 0x0
+#define COMMON_DISP_RFU7__rfu_value7_MASK 0xffffffff
+#define COMMON_DISP_RFU7__rfu_value7__SHIFT 0x0
+#define FREQ_CTRL0__fcw0_frac_MASK 0xffff
+#define FREQ_CTRL0__fcw0_frac__SHIFT 0x0
+#define FREQ_CTRL0__fcw0_int_MASK 0x1ff0000
+#define FREQ_CTRL0__fcw0_int__SHIFT 0x10
+#define FREQ_CTRL1__fcw1_frac_MASK 0xffff
+#define FREQ_CTRL1__fcw1_frac__SHIFT 0x0
+#define FREQ_CTRL1__fcw1_int_MASK 0x1ff0000
+#define FREQ_CTRL1__fcw1_int__SHIFT 0x10
+#define FREQ_CTRL2__fcw_denom_MASK 0xffff
+#define FREQ_CTRL2__fcw_denom__SHIFT 0x0
+#define FREQ_CTRL2__fcw_slew_frac_MASK 0xffff0000
+#define FREQ_CTRL2__fcw_slew_frac__SHIFT 0x10
+#define FREQ_CTRL3__refclk_div_MASK 0x3
+#define FREQ_CTRL3__refclk_div__SHIFT 0x0
+#define FREQ_CTRL3__vco_pre_div_MASK 0x18
+#define FREQ_CTRL3__vco_pre_div__SHIFT 0x3
+#define FREQ_CTRL3__fracn_en_MASK 0x40
+#define FREQ_CTRL3__fracn_en__SHIFT 0x6
+#define FREQ_CTRL3__ssc_en_MASK 0x100
+#define FREQ_CTRL3__ssc_en__SHIFT 0x8
+#define FREQ_CTRL3__fcw_sel_MASK 0x400
+#define FREQ_CTRL3__fcw_sel__SHIFT 0xa
+#define FREQ_CTRL3__freq_jump_en_MASK 0x1000
+#define FREQ_CTRL3__freq_jump_en__SHIFT 0xc
+#define FREQ_CTRL3__tdc_resolution_MASK 0xff0000
+#define FREQ_CTRL3__tdc_resolution__SHIFT 0x10
+#define FREQ_CTRL3__dpll_cfg_1_MASK 0xff000000
+#define FREQ_CTRL3__dpll_cfg_1__SHIFT 0x18
+#define BW_CTRL_COARSE__gi_coarse_mant_MASK 0x3
+#define BW_CTRL_COARSE__gi_coarse_mant__SHIFT 0x0
+#define BW_CTRL_COARSE__gi_coarse_exp_MASK 0x3c
+#define BW_CTRL_COARSE__gi_coarse_exp__SHIFT 0x2
+#define BW_CTRL_COARSE__gp_coarse_mant_MASK 0x780
+#define BW_CTRL_COARSE__gp_coarse_mant__SHIFT 0x7
+#define BW_CTRL_COARSE__gp_coarse_exp_MASK 0xf000
+#define BW_CTRL_COARSE__gp_coarse_exp__SHIFT 0xc
+#define BW_CTRL_COARSE__nctl_coarse_res_MASK 0x7e0000
+#define BW_CTRL_COARSE__nctl_coarse_res__SHIFT 0x11
+#define BW_CTRL_COARSE__nctl_coarse_frac_res_MASK 0x3000000
+#define BW_CTRL_COARSE__nctl_coarse_frac_res__SHIFT 0x18
+#define BW_CTRL_FINE__dpll_cfg_3_MASK 0x3ff
+#define BW_CTRL_FINE__dpll_cfg_3__SHIFT 0x0
+#define CAL_CTRL__bypass_freq_lock_MASK 0x1
+#define CAL_CTRL__bypass_freq_lock__SHIFT 0x0
+#define CAL_CTRL__tdc_cal_en_MASK 0x2
+#define CAL_CTRL__tdc_cal_en__SHIFT 0x1
+#define CAL_CTRL__tdc_cal_ctrl_MASK 0x1f8
+#define CAL_CTRL__tdc_cal_ctrl__SHIFT 0x3
+#define CAL_CTRL__meas_win_sel_MASK 0x600
+#define CAL_CTRL__meas_win_sel__SHIFT 0x9
+#define CAL_CTRL__kdco_cal_dis_MASK 0x800
+#define CAL_CTRL__kdco_cal_dis__SHIFT 0xb
+#define CAL_CTRL__kdco_ratio_MASK 0x1fe000
+#define CAL_CTRL__kdco_ratio__SHIFT 0xd
+#define CAL_CTRL__kdco_incr_cal_dis_MASK 0x400000
+#define CAL_CTRL__kdco_incr_cal_dis__SHIFT 0x16
+#define CAL_CTRL__nctl_adj_dis_MASK 0x800000
+#define CAL_CTRL__nctl_adj_dis__SHIFT 0x17
+#define CAL_CTRL__refclk_rate_MASK 0xff000000
+#define CAL_CTRL__refclk_rate__SHIFT 0x18
+#define LOOP_CTRL__fbdiv_mask_en_MASK 0x1
+#define LOOP_CTRL__fbdiv_mask_en__SHIFT 0x0
+#define LOOP_CTRL__fb_slip_dis_MASK 0x4
+#define LOOP_CTRL__fb_slip_dis__SHIFT 0x2
+#define LOOP_CTRL__clk_tdc_sel_MASK 0x30
+#define LOOP_CTRL__clk_tdc_sel__SHIFT 0x4
+#define LOOP_CTRL__clk_nctl_sel_MASK 0x180
+#define LOOP_CTRL__clk_nctl_sel__SHIFT 0x7
+#define LOOP_CTRL__sig_del_patt_sel_MASK 0x400
+#define LOOP_CTRL__sig_del_patt_sel__SHIFT 0xa
+#define LOOP_CTRL__nctl_sig_del_dis_MASK 0x1000
+#define LOOP_CTRL__nctl_sig_del_dis__SHIFT 0xc
+#define LOOP_CTRL__fbclk_track_refclk_MASK 0x4000
+#define LOOP_CTRL__fbclk_track_refclk__SHIFT 0xe
+#define LOOP_CTRL__prbs_en_MASK 0x10000
+#define LOOP_CTRL__prbs_en__SHIFT 0x10
+#define LOOP_CTRL__tdc_clk_gate_en_MASK 0x40000
+#define LOOP_CTRL__tdc_clk_gate_en__SHIFT 0x12
+#define LOOP_CTRL__phase_offset_MASK 0x7f00000
+#define LOOP_CTRL__phase_offset__SHIFT 0x14
+#define VREG_CFG__bleeder_ac_MASK 0x1
+#define VREG_CFG__bleeder_ac__SHIFT 0x0
+#define VREG_CFG__bleeder_en_MASK 0x2
+#define VREG_CFG__bleeder_en__SHIFT 0x1
+#define VREG_CFG__is_1p2_MASK 0x4
+#define VREG_CFG__is_1p2__SHIFT 0x2
+#define VREG_CFG__reg_obs_sel_MASK 0x18
+#define VREG_CFG__reg_obs_sel__SHIFT 0x3
+#define VREG_CFG__reg_on_mode_MASK 0x60
+#define VREG_CFG__reg_on_mode__SHIFT 0x5
+#define VREG_CFG__rlad_tap_sel_MASK 0x780
+#define VREG_CFG__rlad_tap_sel__SHIFT 0x7
+#define VREG_CFG__reg_off_hi_MASK 0x800
+#define VREG_CFG__reg_off_hi__SHIFT 0xb
+#define VREG_CFG__reg_off_lo_MASK 0x1000
+#define VREG_CFG__reg_off_lo__SHIFT 0xc
+#define VREG_CFG__scale_driver_MASK 0x6000
+#define VREG_CFG__scale_driver__SHIFT 0xd
+#define VREG_CFG__sel_bump_MASK 0x8000
+#define VREG_CFG__sel_bump__SHIFT 0xf
+#define VREG_CFG__sel_rladder_x_MASK 0x10000
+#define VREG_CFG__sel_rladder_x__SHIFT 0x10
+#define VREG_CFG__short_rc_filt_x_MASK 0x20000
+#define VREG_CFG__short_rc_filt_x__SHIFT 0x11
+#define VREG_CFG__vref_pwr_on_MASK 0x40000
+#define VREG_CFG__vref_pwr_on__SHIFT 0x12
+#define VREG_CFG__dpll_cfg_2_MASK 0xff00000
+#define VREG_CFG__dpll_cfg_2__SHIFT 0x14
+#define OBSERVE0__lock_det_tdc_steps_MASK 0x1f
+#define OBSERVE0__lock_det_tdc_steps__SHIFT 0x0
+#define OBSERVE0__clear_sticky_lock_MASK 0x40
+#define OBSERVE0__clear_sticky_lock__SHIFT 0x6
+#define OBSERVE0__lock_det_dis_MASK 0x100
+#define OBSERVE0__lock_det_dis__SHIFT 0x8
+#define OBSERVE0__dco_cfg_MASK 0x3fc00
+#define OBSERVE0__dco_cfg__SHIFT 0xa
+#define OBSERVE0__anaobs_sel_MASK 0xe00000
+#define OBSERVE0__anaobs_sel__SHIFT 0x15
+#define OBSERVE1__digobs_sel_MASK 0xf
+#define OBSERVE1__digobs_sel__SHIFT 0x0
+#define OBSERVE1__digobs_trig_sel_MASK 0x1e0
+#define OBSERVE1__digobs_trig_sel__SHIFT 0x5
+#define OBSERVE1__digobs_div_MASK 0xc00
+#define OBSERVE1__digobs_div__SHIFT 0xa
+#define OBSERVE1__digobs_trig_div_MASK 0x6000
+#define OBSERVE1__digobs_trig_div__SHIFT 0xd
+#define OBSERVE1__lock_timer_MASK 0x3fff0000
+#define OBSERVE1__lock_timer__SHIFT 0x10
+#define DFT_OUT__dft_data_MASK 0xffffffff
+#define DFT_OUT__dft_data__SHIFT 0x0
+#define PLL_WRAP_CNTRL1__wrap_cfg_sel_clk_MASK 0x3
+#define PLL_WRAP_CNTRL1__wrap_cfg_sel_clk__SHIFT 0x0
+#define PLL_WRAP_CNTRL__wrap_cfg_pll_freq_programming_ovveride_MASK 0x1
+#define PLL_WRAP_CNTRL__wrap_cfg_pll_freq_programming_ovveride__SHIFT 0x0
+#define PLL_WRAP_CNTRL__wrap_cfg_pll_pwr_state_ovrride_MASK 0x2
+#define PLL_WRAP_CNTRL__wrap_cfg_pll_pwr_state_ovrride__SHIFT 0x1
+#define PLL_WRAP_CNTRL__wrap_cfg_pll_pwr_state_MASK 0xc
+#define PLL_WRAP_CNTRL__wrap_cfg_pll_pwr_state__SHIFT 0x2
+#define PLL_WRAP_CNTRL__wrap_cfg_tx_pdiv_val_MASK 0xe0
+#define PLL_WRAP_CNTRL__wrap_cfg_tx_pdiv_val__SHIFT 0x5
+#define PLL_WRAP_CNTRL__wrap_cfg_tx_pixdiv_val_MASK 0x100
+#define PLL_WRAP_CNTRL__wrap_cfg_tx_pixdiv_val__SHIFT 0x8
+#define PLL_WRAP_CNTRL__wrap_cfg_cml_cmos_sel_MASK 0x400
+#define PLL_WRAP_CNTRL__wrap_cfg_cml_cmos_sel__SHIFT 0xa
+#define PLL_WRAP_CNTRL__wrap_cfg_pll_rdy_MASK 0x2000
+#define PLL_WRAP_CNTRL__wrap_cfg_pll_rdy__SHIFT 0xd
+#define PLL_WRAP_CNTRL__wrap_cfg_pll_update_MASK 0x4000
+#define PLL_WRAP_CNTRL__wrap_cfg_pll_update__SHIFT 0xe
+#define PLL_WRAP_CNTRL__wrap_cfg_ref_values_chg_MASK 0x8000
+#define PLL_WRAP_CNTRL__wrap_cfg_ref_values_chg__SHIFT 0xf
+#define PLL_WRAP_CNTRL__wrap_cfg_clk_gate_w_rdy_MASK 0x10000
+#define PLL_WRAP_CNTRL__wrap_cfg_clk_gate_w_rdy__SHIFT 0x10
+#define PLL_WRAP_CNTRL__wrap_cfg_pll_dsm_sel_MASK 0xe0000
+#define PLL_WRAP_CNTRL__wrap_cfg_pll_dsm_sel__SHIFT 0x11
+#define PPLL_VREG_CFG__pw_pc_bleeder_ac_MASK 0x1
+#define PPLL_VREG_CFG__pw_pc_bleeder_ac__SHIFT 0x0
+#define PPLL_VREG_CFG__pw_pc_bleeder_en_MASK 0x2
+#define PPLL_VREG_CFG__pw_pc_bleeder_en__SHIFT 0x1
+#define PPLL_VREG_CFG__pw_pc_is_1p2_MASK 0x4
+#define PPLL_VREG_CFG__pw_pc_is_1p2__SHIFT 0x2
+#define PPLL_VREG_CFG__pw_pc_reg_obs_sel_MASK 0x18
+#define PPLL_VREG_CFG__pw_pc_reg_obs_sel__SHIFT 0x3
+#define PPLL_VREG_CFG__pw_pc_reg_on_mode_MASK 0x60
+#define PPLL_VREG_CFG__pw_pc_reg_on_mode__SHIFT 0x5
+#define PPLL_VREG_CFG__pw_pc_rlad_tap_sel_MASK 0x780
+#define PPLL_VREG_CFG__pw_pc_rlad_tap_sel__SHIFT 0x7
+#define PPLL_VREG_CFG__pw_pc_reg_off_hi_MASK 0x800
+#define PPLL_VREG_CFG__pw_pc_reg_off_hi__SHIFT 0xb
+#define PPLL_VREG_CFG__pw_pc_reg_off_lo_MASK 0x1000
+#define PPLL_VREG_CFG__pw_pc_reg_off_lo__SHIFT 0xc
+#define PPLL_VREG_CFG__pw_pc_scale_driver_MASK 0x6000
+#define PPLL_VREG_CFG__pw_pc_scale_driver__SHIFT 0xd
+#define PPLL_VREG_CFG__pw_pc_sel_bump_MASK 0x8000
+#define PPLL_VREG_CFG__pw_pc_sel_bump__SHIFT 0xf
+#define PPLL_VREG_CFG__pw_pc_sel_rladder_x_MASK 0x10000
+#define PPLL_VREG_CFG__pw_pc_sel_rladder_x__SHIFT 0x10
+#define PPLL_VREG_CFG__pw_pc_short_rc_filt_x_MASK 0x20000
+#define PPLL_VREG_CFG__pw_pc_short_rc_filt_x__SHIFT 0x11
+#define PPLL_VREG_CFG__pw_pc_vref_pwr_on_MASK 0x40000
+#define PPLL_VREG_CFG__pw_pc_vref_pwr_on__SHIFT 0x12
+#define PPLL_VREG_CFG__pw_pc_dpll_cfg_2_MASK 0xff00000
+#define PPLL_VREG_CFG__pw_pc_dpll_cfg_2__SHIFT 0x14
+#define PPLL_MODE_CNTL__pw_pc_refclk_gate_dis_MASK 0x1
+#define PPLL_MODE_CNTL__pw_pc_refclk_gate_dis__SHIFT 0x0
+#define PPLL_MODE_CNTL__pw_pc_multi_phase_en_MASK 0xf00
+#define PPLL_MODE_CNTL__pw_pc_multi_phase_en__SHIFT 0x8
+#define PPLL_MODE_CNTL__reg_tmg_pwr_state_MASK 0x30000
+#define PPLL_MODE_CNTL__reg_tmg_pwr_state__SHIFT 0x10
+#define PPLL_FREQ_CTRL0__reg_tmg_fcw0_frac_MASK 0xffff
+#define PPLL_FREQ_CTRL0__reg_tmg_fcw0_frac__SHIFT 0x0
+#define PPLL_FREQ_CTRL0__reg_tmg_fcw0_int_MASK 0x1ff0000
+#define PPLL_FREQ_CTRL0__reg_tmg_fcw0_int__SHIFT 0x10
+#define PPLL_FREQ_CTRL1__reg_tmg_fcw1_frac_MASK 0xffff
+#define PPLL_FREQ_CTRL1__reg_tmg_fcw1_frac__SHIFT 0x0
+#define PPLL_FREQ_CTRL1__reg_tmg_fcw1_int_MASK 0x1ff0000
+#define PPLL_FREQ_CTRL1__reg_tmg_fcw1_int__SHIFT 0x10
+#define PPLL_FREQ_CTRL2__reg_tmg_fcw_denom_MASK 0xffff
+#define PPLL_FREQ_CTRL2__reg_tmg_fcw_denom__SHIFT 0x0
+#define PPLL_FREQ_CTRL2__reg_tmg_fcw_slew_frac_MASK 0xffff0000
+#define PPLL_FREQ_CTRL2__reg_tmg_fcw_slew_frac__SHIFT 0x10
+#define PPLL_FREQ_CTRL3__reg_tmg_refclk_div_MASK 0x3
+#define PPLL_FREQ_CTRL3__reg_tmg_refclk_div__SHIFT 0x0
+#define PPLL_FREQ_CTRL3__reg_tmg_vco_pre_div_MASK 0x18
+#define PPLL_FREQ_CTRL3__reg_tmg_vco_pre_div__SHIFT 0x3
+#define PPLL_FREQ_CTRL3__reg_tmg_fracn_en_MASK 0x40
+#define PPLL_FREQ_CTRL3__reg_tmg_fracn_en__SHIFT 0x6
+#define PPLL_FREQ_CTRL3__reg_tmg_ssc_en_MASK 0x100
+#define PPLL_FREQ_CTRL3__reg_tmg_ssc_en__SHIFT 0x8
+#define PPLL_FREQ_CTRL3__reg_tmg_fcw_sel_MASK 0x400
+#define PPLL_FREQ_CTRL3__reg_tmg_fcw_sel__SHIFT 0xa
+#define PPLL_FREQ_CTRL3__reg_tmg_freq_jump_en_MASK 0x1000
+#define PPLL_FREQ_CTRL3__reg_tmg_freq_jump_en__SHIFT 0xc
+#define PPLL_FREQ_CTRL3__reg_tmg_tdc_resol_MASK 0xff0000
+#define PPLL_FREQ_CTRL3__reg_tmg_tdc_resol__SHIFT 0x10
+#define PPLL_FREQ_CTRL3__pw_pc_dpll_cfg_1_MASK 0xff000000
+#define PPLL_FREQ_CTRL3__pw_pc_dpll_cfg_1__SHIFT 0x18
+#define PPLL_BW_CTRL_COARSE__reg_tmg_gi_crse_mant_MASK 0x3
+#define PPLL_BW_CTRL_COARSE__reg_tmg_gi_crse_mant__SHIFT 0x0
+#define PPLL_BW_CTRL_COARSE__reg_tmg_gi_crse_exp_MASK 0x3c
+#define PPLL_BW_CTRL_COARSE__reg_tmg_gi_crse_exp__SHIFT 0x2
+#define PPLL_BW_CTRL_COARSE__reg_tmg_gp_crse_mant_MASK 0x780
+#define PPLL_BW_CTRL_COARSE__reg_tmg_gp_crse_mant__SHIFT 0x7
+#define PPLL_BW_CTRL_COARSE__reg_tmg_gp_crse_exp_MASK 0xf000
+#define PPLL_BW_CTRL_COARSE__reg_tmg_gp_crse_exp__SHIFT 0xc
+#define PPLL_BW_CTRL_COARSE__reg_tmg_nctl_crse_res_MASK 0x7e0000
+#define PPLL_BW_CTRL_COARSE__reg_tmg_nctl_crse_res__SHIFT 0x11
+#define PPLL_BW_CTRL_COARSE__reg_tmg_nctl_crse_frac_res_MASK 0x3000000
+#define PPLL_BW_CTRL_COARSE__reg_tmg_nctl_crse_frac_res__SHIFT 0x18
+#define PPLL_BW_CTRL_FINE__pw_pc_dpll_cfg_3_MASK 0x3ff
+#define PPLL_BW_CTRL_FINE__pw_pc_dpll_cfg_3__SHIFT 0x0
+#define PPLL_CAL_CTRL__pw_pc_bypass_freq_lock_MASK 0x1
+#define PPLL_CAL_CTRL__pw_pc_bypass_freq_lock__SHIFT 0x0
+#define PPLL_CAL_CTRL__pw_pc_tdc_cal_en_MASK 0x2
+#define PPLL_CAL_CTRL__pw_pc_tdc_cal_en__SHIFT 0x1
+#define PPLL_CAL_CTRL__pw_pc_tdc_cal_ctrl_MASK 0x1f8
+#define PPLL_CAL_CTRL__pw_pc_tdc_cal_ctrl__SHIFT 0x3
+#define PPLL_CAL_CTRL__pw_pc_meas_win_sel_MASK 0x600
+#define PPLL_CAL_CTRL__pw_pc_meas_win_sel__SHIFT 0x9
+#define PPLL_CAL_CTRL__pw_pc_kdco_cal_dis_MASK 0x800
+#define PPLL_CAL_CTRL__pw_pc_kdco_cal_dis__SHIFT 0xb
+#define PPLL_CAL_CTRL__pw_pc_kdco_ratio_MASK 0x1fe000
+#define PPLL_CAL_CTRL__pw_pc_kdco_ratio__SHIFT 0xd
+#define PPLL_CAL_CTRL__pw_pc_kdco_incr_cal_dis_MASK 0x400000
+#define PPLL_CAL_CTRL__pw_pc_kdco_incr_cal_dis__SHIFT 0x16
+#define PPLL_CAL_CTRL__pw_pc_nctl_adj_dis_MASK 0x800000
+#define PPLL_CAL_CTRL__pw_pc_nctl_adj_dis__SHIFT 0x17
+#define PPLL_CAL_CTRL__pw_pc_refclk_rate_MASK 0xff000000
+#define PPLL_CAL_CTRL__pw_pc_refclk_rate__SHIFT 0x18
+#define PPLL_LOOP_CTRL__pw_pc_fbdiv_mask_en_MASK 0x1
+#define PPLL_LOOP_CTRL__pw_pc_fbdiv_mask_en__SHIFT 0x0
+#define PPLL_LOOP_CTRL__pw_pc_fb_slip_dis_MASK 0x4
+#define PPLL_LOOP_CTRL__pw_pc_fb_slip_dis__SHIFT 0x2
+#define PPLL_LOOP_CTRL__pw_pc_clk_tdc_sel_MASK 0x30
+#define PPLL_LOOP_CTRL__pw_pc_clk_tdc_sel__SHIFT 0x4
+#define PPLL_LOOP_CTRL__pw_pc_clk_nctl_sel_MASK 0x180
+#define PPLL_LOOP_CTRL__pw_pc_clk_nctl_sel__SHIFT 0x7
+#define PPLL_LOOP_CTRL__pw_pc_sig_del_patt_sel_MASK 0x400
+#define PPLL_LOOP_CTRL__pw_pc_sig_del_patt_sel__SHIFT 0xa
+#define PPLL_LOOP_CTRL__pw_pc_nctl_sig_del_dis_MASK 0x1000
+#define PPLL_LOOP_CTRL__pw_pc_nctl_sig_del_dis__SHIFT 0xc
+#define PPLL_LOOP_CTRL__pw_pc_fbclk_track_refclk_MASK 0x4000
+#define PPLL_LOOP_CTRL__pw_pc_fbclk_track_refclk__SHIFT 0xe
+#define PPLL_LOOP_CTRL__pw_pc_prbs_en_MASK 0x10000
+#define PPLL_LOOP_CTRL__pw_pc_prbs_en__SHIFT 0x10
+#define PPLL_LOOP_CTRL__pw_pc_tdc_clk_gate_en_MASK 0x40000
+#define PPLL_LOOP_CTRL__pw_pc_tdc_clk_gate_en__SHIFT 0x12
+#define PPLL_LOOP_CTRL__pw_pc_phase_offset_MASK 0x7f00000
+#define PPLL_LOOP_CTRL__pw_pc_phase_offset__SHIFT 0x14
+#define PPLL_REFCLK_CNTL__regs_pw_refclk0_recv_en_MASK 0x1
+#define PPLL_REFCLK_CNTL__regs_pw_refclk0_recv_en__SHIFT 0x0
+#define PPLL_REFCLK_CNTL__regs_pw_refclk1_recv_en_MASK 0x2
+#define PPLL_REFCLK_CNTL__regs_pw_refclk1_recv_en__SHIFT 0x1
+#define PPLL_REFCLK_CNTL__regs_pw_refclk2_recv_en_MASK 0x4
+#define PPLL_REFCLK_CNTL__regs_pw_refclk2_recv_en__SHIFT 0x2
+#define PPLL_REFCLK_CNTL__regs_pw_refclk3_recv_en_MASK 0x8
+#define PPLL_REFCLK_CNTL__regs_pw_refclk3_recv_en__SHIFT 0x3
+#define PPLL_REFCLK_CNTL__regs_pw_refclk0_recv_sel_MASK 0x100
+#define PPLL_REFCLK_CNTL__regs_pw_refclk0_recv_sel__SHIFT 0x8
+#define PPLL_REFCLK_CNTL__regs_pw_refclk1_recv_sel_MASK 0x200
+#define PPLL_REFCLK_CNTL__regs_pw_refclk1_recv_sel__SHIFT 0x9
+#define PPLL_REFCLK_CNTL__regs_pw_refclk2_recv_sel_MASK 0x400
+#define PPLL_REFCLK_CNTL__regs_pw_refclk2_recv_sel__SHIFT 0xa
+#define PPLL_REFCLK_CNTL__regs_pw_refclk3_recv_sel_MASK 0x800
+#define PPLL_REFCLK_CNTL__regs_pw_refclk3_recv_sel__SHIFT 0xb
+#define PPLL_REFCLK_CNTL__regs_pw_refdivsrc_MASK 0xc000
+#define PPLL_REFCLK_CNTL__regs_pw_refdivsrc__SHIFT 0xe
+#define PPLL_REFCLK_CNTL__regs_pw_ref2core_sel_MASK 0x10000
+#define PPLL_REFCLK_CNTL__regs_pw_ref2core_sel__SHIFT 0x10
+#define PPLL_CLKOUT_CNTL__regs_pw_pixclk_pre_pdivsel_MASK 0x100
+#define PPLL_CLKOUT_CNTL__regs_pw_pixclk_pre_pdivsel__SHIFT 0x8
+#define PPLL_CLKOUT_CNTL__regs_pw_pixclk_pdivsel_MASK 0x200
+#define PPLL_CLKOUT_CNTL__regs_pw_pixclk_pdivsel__SHIFT 0x9
+#define PPLL_CLKOUT_CNTL__regs_pw_dvoclk_pre_pdivsel_MASK 0x400
+#define PPLL_CLKOUT_CNTL__regs_pw_dvoclk_pre_pdivsel__SHIFT 0xa
+#define PPLL_CLKOUT_CNTL__regs_pw_dvoclk_pdivsel_MASK 0x800
+#define PPLL_CLKOUT_CNTL__regs_pw_dvoclk_pdivsel__SHIFT 0xb
+#define PPLL_CLKOUT_CNTL__regs_pw_idclk_en_MASK 0x1000
+#define PPLL_CLKOUT_CNTL__regs_pw_idclk_en__SHIFT 0xc
+#define PPLL_CLKOUT_CNTL__regs_pw_idclk_pre_pdivsel_MASK 0x2000
+#define PPLL_CLKOUT_CNTL__regs_pw_idclk_pre_pdivsel__SHIFT 0xd
+#define PPLL_CLKOUT_CNTL__regs_pw_idclk_pdivsel_MASK 0x4000
+#define PPLL_CLKOUT_CNTL__regs_pw_idclk_pdivsel__SHIFT 0xe
+#define PPLL_CLKOUT_CNTL__regs_pw_idclk_obs_sel_MASK 0x8000
+#define PPLL_CLKOUT_CNTL__regs_pw_idclk_obs_sel__SHIFT 0xf
+#define PPLL_CLKOUT_CNTL__regs_pw_refclk_sel_MASK 0x30000
+#define PPLL_CLKOUT_CNTL__regs_pw_refclk_sel__SHIFT 0x10
+#define PPLL_CLKOUT_CNTL__regs_cc_resetb_MASK 0x100000
+#define PPLL_CLKOUT_CNTL__regs_cc_resetb__SHIFT 0x14
+#define PPLL_DFT_CNTL__regs_pw_obs_en_MASK 0x1
+#define PPLL_DFT_CNTL__regs_pw_obs_en__SHIFT 0x0
+#define PPLL_DFT_CNTL__regs_pw_obs_div_sel_1_MASK 0x6
+#define PPLL_DFT_CNTL__regs_pw_obs_div_sel_1__SHIFT 0x1
+#define PPLL_DFT_CNTL__regs_pw_obs_clk_sel_1_MASK 0xf0
+#define PPLL_DFT_CNTL__regs_pw_obs_clk_sel_1__SHIFT 0x4
+#define PPLL_DFT_CNTL__regs_pw_obs_clk_sel_2_MASK 0xf00
+#define PPLL_DFT_CNTL__regs_pw_obs_clk_sel_2__SHIFT 0x8
+#define PPLL_DFT_CNTL__regs_pw_obs_sel_MASK 0x3000
+#define PPLL_DFT_CNTL__regs_pw_obs_sel__SHIFT 0xc
+#define PPLL_ANALOG_CNTL__regs_pw_spare_MASK 0xff
+#define PPLL_ANALOG_CNTL__regs_pw_spare__SHIFT 0x0
+#define PPLL_POSTDIV__reg_tmg_postdiv_MASK 0xf00
+#define PPLL_POSTDIV__reg_tmg_postdiv__SHIFT 0x8
+#define PPLL_POSTDIV__reg_tmg_pixclk_pdiv2_MASK 0x1000
+#define PPLL_POSTDIV__reg_tmg_pixclk_pdiv2__SHIFT 0xc
+#define PPLL_DEBUG0__pw_pc_phase_jump_trig_MASK 0x2
+#define PPLL_DEBUG0__pw_pc_phase_jump_trig__SHIFT 0x1
+#define PPLL_DEBUG0__pw_pc_fine_tdc_dis_MASK 0x4
+#define PPLL_DEBUG0__pw_pc_fine_tdc_dis__SHIFT 0x2
+#define PPLL_DEBUG0__pw_pc_coarse_tdc_dis_MASK 0x8
+#define PPLL_DEBUG0__pw_pc_coarse_tdc_dis__SHIFT 0x3
+#define PPLL_DEBUG0__pw_pc_alt_nctl_en_MASK 0x10
+#define PPLL_DEBUG0__pw_pc_alt_nctl_en__SHIFT 0x4
+#define PPLL_DEBUG0__pw_pc_alt_nctl_MASK 0x1ffffe0
+#define PPLL_DEBUG0__pw_pc_alt_nctl__SHIFT 0x5
+#define PPLL_DEBUG0__pw_pc_nctl_coarse_step_dis_MASK 0x2000000
+#define PPLL_DEBUG0__pw_pc_nctl_coarse_step_dis__SHIFT 0x19
+#define PPLL_DEBUG0__pw_pc_trig_coarse_step_MASK 0x4000000
+#define PPLL_DEBUG0__pw_pc_trig_coarse_step__SHIFT 0x1a
+#define PPLL_DEBUG0__pw_pc_dft_sel_MASK 0x38000000
+#define PPLL_DEBUG0__pw_pc_dft_sel__SHIFT 0x1b
+#define PPLL_DEBUG0__pw_pc_dft_capture_MASK 0x40000000
+#define PPLL_DEBUG0__pw_pc_dft_capture__SHIFT 0x1e
+#define PPLL_OBSERVE0__pw_pc_lock_det_tdc_steps_MASK 0x1f
+#define PPLL_OBSERVE0__pw_pc_lock_det_tdc_steps__SHIFT 0x0
+#define PPLL_OBSERVE0__pw_pc_clear_sticky_lock_MASK 0x40
+#define PPLL_OBSERVE0__pw_pc_clear_sticky_lock__SHIFT 0x6
+#define PPLL_OBSERVE0__pw_pc_lock_det_dis_MASK 0x100
+#define PPLL_OBSERVE0__pw_pc_lock_det_dis__SHIFT 0x8
+#define PPLL_OBSERVE0__pw_pc_dco_cfg_MASK 0x3fc00
+#define PPLL_OBSERVE0__pw_pc_dco_cfg__SHIFT 0xa
+#define PPLL_OBSERVE0__pw_pc_anaobs_sel_MASK 0xe00000
+#define PPLL_OBSERVE0__pw_pc_anaobs_sel__SHIFT 0x15
+#define PPLL_OBSERVE1__pw_pc_digobs_sel_MASK 0xf
+#define PPLL_OBSERVE1__pw_pc_digobs_sel__SHIFT 0x0
+#define PPLL_OBSERVE1__pw_pc_digobs_trig_sel_MASK 0x1e0
+#define PPLL_OBSERVE1__pw_pc_digobs_trig_sel__SHIFT 0x5
+#define PPLL_OBSERVE1__pw_pc_digobs_div_MASK 0xc00
+#define PPLL_OBSERVE1__pw_pc_digobs_div__SHIFT 0xa
+#define PPLL_OBSERVE1__pw_pc_digobs_trig_div_MASK 0x3000
+#define PPLL_OBSERVE1__pw_pc_digobs_trig_div__SHIFT 0xc
+#define PPLL_OBSERVE1__reg_tmg_lock_timer_MASK 0x3fff0000
+#define PPLL_OBSERVE1__reg_tmg_lock_timer__SHIFT 0x10
+#define PPLL_UPDATE_CNTL__reg_tmg_PLL_UPDATE_LOCK_MASK 0x4
+#define PPLL_UPDATE_CNTL__reg_tmg_PLL_UPDATE_LOCK__SHIFT 0x2
+#define PPLL_UPDATE_CNTL__reg_tmg_PLL_UPDATE_POINT_MASK 0x8
+#define PPLL_UPDATE_CNTL__reg_tmg_PLL_UPDATE_POINT__SHIFT 0x3
+#define PPLL_UPDATE_CNTL__tmg_reg_UPDATE_PENDING_MASK 0x100
+#define PPLL_UPDATE_CNTL__tmg_reg_UPDATE_PENDING__SHIFT 0x8
+#define PPLL_UPDATE_CNTL__pc_pw_pll_rdy_MASK 0x200
+#define PPLL_UPDATE_CNTL__pc_pw_pll_rdy__SHIFT 0x9
+#define PPLL_UPDATE_CNTL__TieLow1_MASK 0x10000
+#define PPLL_UPDATE_CNTL__TieLow1__SHIFT 0x10
+#define PPLL_OBSERVE0_OUT__disppll_core_obsout_MASK 0xffffffff
+#define PPLL_OBSERVE0_OUT__disppll_core_obsout__SHIFT 0x0
+#define PPLL_STATUS_DEBUG1__dbg_pll_rdy_MASK 0x1
+#define PPLL_STATUS_DEBUG1__dbg_pll_rdy__SHIFT 0x0
+#define PPLL_STATUS_DEBUG1__core_disppll_pwr_ok_vddp_MASK 0x2
+#define PPLL_STATUS_DEBUG1__core_disppll_pwr_ok_vddp__SHIFT 0x1
+#define PPLL_STATUS_DEBUG1__core_disppll_rcu_dc_resetb_vddp_MASK 0x4
+#define PPLL_STATUS_DEBUG1__core_disppll_rcu_dc_resetb_vddp__SHIFT 0x2
+#define PPLL_DEBUG_MUX_CNTL__DEBUG_BUS_MUX_SEL_MASK 0x1f
+#define PPLL_DEBUG_MUX_CNTL__DEBUG_BUS_MUX_SEL__SHIFT 0x0
+#define PPLL_DIV_UPDATE_DEBUG__TieLow2_MASK 0x1
+#define PPLL_DIV_UPDATE_DEBUG__TieLow2__SHIFT 0x0
+#define PPLL_DIV_UPDATE_DEBUG__tmg_reg_FB_DIV_CHANGED_MASK 0x2
+#define PPLL_DIV_UPDATE_DEBUG__tmg_reg_FB_DIV_CHANGED__SHIFT 0x1
+#define PPLL_DIV_UPDATE_DEBUG__dbg_UPDATE_PENDING_MASK 0x4
+#define PPLL_DIV_UPDATE_DEBUG__dbg_UPDATE_PENDING__SHIFT 0x2
+#define PPLL_DIV_UPDATE_DEBUG__tmg_reg_CURRENT_STATE_MASK 0x18
+#define PPLL_DIV_UPDATE_DEBUG__tmg_reg_CURRENT_STATE__SHIFT 0x3
+#define PPLL_DIV_UPDATE_DEBUG__tmg_reg_UPDATE_ENABLE_MASK 0x20
+#define PPLL_DIV_UPDATE_DEBUG__tmg_reg_UPDATE_ENABLE__SHIFT 0x5
+#define PPLL_DIV_UPDATE_DEBUG__tmg_reg_UPDATE_REQ_MASK 0x40
+#define PPLL_DIV_UPDATE_DEBUG__tmg_reg_UPDATE_REQ__SHIFT 0x6
+#define PPLL_DIV_UPDATE_DEBUG__tmg_reg_UPDATE_ACK_MASK 0x80
+#define PPLL_DIV_UPDATE_DEBUG__tmg_reg_UPDATE_ACK__SHIFT 0x7
+#define PPLL_STATUS_DEBUG0__obsout_MASK 0xffffffff
+#define PPLL_STATUS_DEBUG0__obsout__SHIFT 0x0
+#define COMP_EN_CTL__comp_en_MASK 0x1
+#define COMP_EN_CTL__comp_en__SHIFT 0x0
+#define COMP_EN_CTL__comp_en_override_MASK 0x4
+#define COMP_EN_CTL__comp_en_override__SHIFT 0x2
+#define COMP_EN_CTL__comp_done_MASK 0x10
+#define COMP_EN_CTL__comp_done__SHIFT 0x4
+#define COMP_EN_CTL__zcal_code_override_MASK 0x40
+#define COMP_EN_CTL__zcal_code_override__SHIFT 0x6
+#define COMP_EN_CTL__zcal_cal_rtt_MASK 0x80
+#define COMP_EN_CTL__zcal_cal_rtt__SHIFT 0x7
+#define COMP_EN_CTL__zcal_base_en_MASK 0x100
+#define COMP_EN_CTL__zcal_base_en__SHIFT 0x8
+#define COMP_EN_CTL__zcal_ht_rtt_sel_MASK 0x200
+#define COMP_EN_CTL__zcal_ht_rtt_sel__SHIFT 0x9
+#define COMP_EN_CTL__zcal_code_MASK 0x7c00
+#define COMP_EN_CTL__zcal_code__SHIFT 0xa
+#define COMP_EN_CTL__zcal_ron_cal_mode_MASK 0x10000
+#define COMP_EN_CTL__zcal_ron_cal_mode__SHIFT 0x10
+#define COMP_EN_CTL__zcal_ana_dbg_sel_MASK 0x60000
+#define COMP_EN_CTL__zcal_ana_dbg_sel__SHIFT 0x11
+#define COMP_EN_CTL__cfg_cml_cmos_sel_MASK 0x80000
+#define COMP_EN_CTL__cfg_cml_cmos_sel__SHIFT 0x13
+#define COMP_EN_CTL__dsm_sel_MASK 0xf00000
+#define COMP_EN_CTL__dsm_sel__SHIFT 0x14
+#define DPCSTX_PHY_CNTL__DPCS_PHY_RESET_MASK 0x1
+#define DPCSTX_PHY_CNTL__DPCS_PHY_RESET__SHIFT 0x0
+#define DPCSTX_TX_CLOCK_CNTL__DPCS_SYMCLK_GATE_DIS_MASK 0x1
+#define DPCSTX_TX_CLOCK_CNTL__DPCS_SYMCLK_GATE_DIS__SHIFT 0x0
+#define DPCSTX_TX_CLOCK_CNTL__DPCS_SYMCLK_EN_MASK 0x2
+#define DPCSTX_TX_CLOCK_CNTL__DPCS_SYMCLK_EN__SHIFT 0x1
+#define DPCSTX_TX_CLOCK_CNTL__DPCS_SYMCLK_CLOCK_ON_MASK 0x4
+#define DPCSTX_TX_CLOCK_CNTL__DPCS_SYMCLK_CLOCK_ON__SHIFT 0x2
+#define DPCSTX_TX_CLOCK_CNTL__DPCS_SYMCLK_DIV2_CLOCK_ON_MASK 0x8
+#define DPCSTX_TX_CLOCK_CNTL__DPCS_SYMCLK_DIV2_CLOCK_ON__SHIFT 0x3
+#define DPCSTX_TX_CLOCK_CNTL__DPCS_SYMCLK_DIV2_TX0_EN_MASK 0x10
+#define DPCSTX_TX_CLOCK_CNTL__DPCS_SYMCLK_DIV2_TX0_EN__SHIFT 0x4
+#define DPCSTX_TX_CLOCK_CNTL__DPCS_SYMCLK_DIV2_TX1_EN_MASK 0x20
+#define DPCSTX_TX_CLOCK_CNTL__DPCS_SYMCLK_DIV2_TX1_EN__SHIFT 0x5
+#define DPCSTX_TX_CLOCK_CNTL__DPCS_SYMCLK_DIV2_TX2_EN_MASK 0x40
+#define DPCSTX_TX_CLOCK_CNTL__DPCS_SYMCLK_DIV2_TX2_EN__SHIFT 0x6
+#define DPCSTX_TX_CLOCK_CNTL__DPCS_SYMCLK_DIV2_TX3_EN_MASK 0x80
+#define DPCSTX_TX_CLOCK_CNTL__DPCS_SYMCLK_DIV2_TX3_EN__SHIFT 0x7
+#define DPCSTX_TX_CNTL__DPCS_TX_RESYNC_MASK 0x1
+#define DPCSTX_TX_CNTL__DPCS_TX_RESYNC__SHIFT 0x0
+#define DPCSTX_TX_CNTL__DPCS_TX_STAGGERING_EN_MASK 0x2
+#define DPCSTX_TX_CNTL__DPCS_TX_STAGGERING_EN__SHIFT 0x1
+#define DPCSTX_TX_CNTL__DPCS_TX_HIGH_IMP_IDLE_OVERRIDE_EN_MASK 0x4
+#define DPCSTX_TX_CNTL__DPCS_TX_HIGH_IMP_IDLE_OVERRIDE_EN__SHIFT 0x2
+#define DPCSTX_TX_CNTL__DPCS_TX_HIGH_IMP_IDLE_MASK 0xf0
+#define DPCSTX_TX_CNTL__DPCS_TX_HIGH_IMP_IDLE__SHIFT 0x4
+#define DPCSTX_TX_CNTL__DPCS_TX_STAGGERING_DELAY_MASK 0x700
+#define DPCSTX_TX_CNTL__DPCS_TX_STAGGERING_DELAY__SHIFT 0x8
+#define DPCSTX_TX_CNTL__DPCS_TX_PLL_UPDATE_REQ_MASK 0x1000
+#define DPCSTX_TX_CNTL__DPCS_TX_PLL_UPDATE_REQ__SHIFT 0xc
+#define DPCSTX_TX_CNTL__DPCS_TX_PLL_UPDATE_PENDING_MASK 0x2000
+#define DPCSTX_TX_CNTL__DPCS_TX_PLL_UPDATE_PENDING__SHIFT 0xd
+#define DPCSTX_TX_CNTL__DPCS_TX_DATA_SWAP_MASK 0x4000
+#define DPCSTX_TX_CNTL__DPCS_TX_DATA_SWAP__SHIFT 0xe
+#define DPCSTX_TX_CNTL__DPCS_TX_FIFO_EN_MASK 0x10000
+#define DPCSTX_TX_CNTL__DPCS_TX_FIFO_EN__SHIFT 0x10
+#define DPCSTX_TX_CNTL__DPCS_TX_FIFO_START_MASK 0x20000
+#define DPCSTX_TX_CNTL__DPCS_TX_FIFO_START__SHIFT 0x11
+#define DPCSTX_TX_CNTL__DPCS_TX_FIFO_WR_START_DELAY_MASK 0xf00000
+#define DPCSTX_TX_CNTL__DPCS_TX_FIFO_WR_START_DELAY__SHIFT 0x14
+#define DPCSTX_TX_CNTL__DPCS_TX_DVI_LINK_MODE_MASK 0x3000000
+#define DPCSTX_TX_CNTL__DPCS_TX_DVI_LINK_MODE__SHIFT 0x18
+#define DPCSTX_TX_CNTL__DPCS_TX_SOFT_RESET_MASK 0x80000000
+#define DPCSTX_TX_CNTL__DPCS_TX_SOFT_RESET__SHIFT 0x1f
+#define DPCSTX_CBUS_CNTL__DPCS_CBUS_WR_CMD_DELAY_MASK 0xf
+#define DPCSTX_CBUS_CNTL__DPCS_CBUS_WR_CMD_DELAY__SHIFT 0x0
+#define DPCSTX_CBUS_CNTL__DPCS_PHY_MASTER_REQ_DELAY_MASK 0xff00
+#define DPCSTX_CBUS_CNTL__DPCS_PHY_MASTER_REQ_DELAY__SHIFT 0x8
+#define DPCSTX_CBUS_CNTL__DPCS_CBUS_SOFT_RESET_MASK 0x80000000
+#define DPCSTX_CBUS_CNTL__DPCS_CBUS_SOFT_RESET__SHIFT 0x1f
+#define DPCSTX_REG_ERROR_STATUS__DPCS_REG_FIFO_OVERFLOW_MASK 0x1
+#define DPCSTX_REG_ERROR_STATUS__DPCS_REG_FIFO_OVERFLOW__SHIFT 0x0
+#define DPCSTX_REG_ERROR_STATUS__DPCS_REG_ERROR_CLR_MASK 0x2
+#define DPCSTX_REG_ERROR_STATUS__DPCS_REG_ERROR_CLR__SHIFT 0x1
+#define DPCSTX_REG_ERROR_STATUS__DPCS_REG_FIFO_ERROR_MASK_MASK 0x10
+#define DPCSTX_REG_ERROR_STATUS__DPCS_REG_FIFO_ERROR_MASK__SHIFT 0x4
+#define DPCSTX_TX_ERROR_STATUS__DPCS_TX0_FIFO_ERROR_MASK 0x1
+#define DPCSTX_TX_ERROR_STATUS__DPCS_TX0_FIFO_ERROR__SHIFT 0x0
+#define DPCSTX_TX_ERROR_STATUS__DPCS_TX1_FIFO_ERROR_MASK 0x2
+#define DPCSTX_TX_ERROR_STATUS__DPCS_TX1_FIFO_ERROR__SHIFT 0x1
+#define DPCSTX_TX_ERROR_STATUS__DPCS_TX2_FIFO_ERROR_MASK 0x4
+#define DPCSTX_TX_ERROR_STATUS__DPCS_TX2_FIFO_ERROR__SHIFT 0x2
+#define DPCSTX_TX_ERROR_STATUS__DPCS_TX3_FIFO_ERROR_MASK 0x8
+#define DPCSTX_TX_ERROR_STATUS__DPCS_TX3_FIFO_ERROR__SHIFT 0x3
+#define DPCSTX_TX_ERROR_STATUS__DPCS_TX_ERROR_CLR_MASK 0x100
+#define DPCSTX_TX_ERROR_STATUS__DPCS_TX_ERROR_CLR__SHIFT 0x8
+#define DPCSTX_TX_ERROR_STATUS__DPCS_TX_FIFO_ERROR_MASK_MASK 0x1000
+#define DPCSTX_TX_ERROR_STATUS__DPCS_TX_FIFO_ERROR_MASK__SHIFT 0xc
+#define DPCSTX_PLL_UPDATE_ADDR__DPCS_PLL_UPDATE_ADDR_MASK 0x3ffff
+#define DPCSTX_PLL_UPDATE_ADDR__DPCS_PLL_UPDATE_ADDR__SHIFT 0x0
+#define DPCSTX_PLL_UPDATE_DATA__DPCS_PLL_UPDATE_DATA_MASK 0xffffffff
+#define DPCSTX_PLL_UPDATE_DATA__DPCS_PLL_UPDATE_DATA__SHIFT 0x0
+#define DPCSTX_INDEX_MODE_ADDR__DPCS_INDEX_MODE_ADDR_MASK 0x3ffff
+#define DPCSTX_INDEX_MODE_ADDR__DPCS_INDEX_MODE_ADDR__SHIFT 0x0
+#define DPCSTX_INDEX_MODE_DATA__DPCS_INDEX_MODE_DATA_MASK 0xffffffff
+#define DPCSTX_INDEX_MODE_DATA__DPCS_INDEX_MODE_DATA__SHIFT 0x0
+#define DPCSTX_DEBUG_CONFIG__DPCS_DBG_EN_MASK 0x1
+#define DPCSTX_DEBUG_CONFIG__DPCS_DBG_EN__SHIFT 0x0
+#define DPCSTX_DEBUG_CONFIG__DPCS_DBG_CFGCLK_SEL_MASK 0x6
+#define DPCSTX_DEBUG_CONFIG__DPCS_DBG_CFGCLK_SEL__SHIFT 0x1
+#define DPCSTX_DEBUG_CONFIG__DPCS_DBG_TX_SYMCLK_SEL_MASK 0x38
+#define DPCSTX_DEBUG_CONFIG__DPCS_DBG_TX_SYMCLK_SEL__SHIFT 0x3
+#define DPCSTX_DEBUG_CONFIG__DPCS_DBG_CLOCK_SEL_MASK 0x700
+#define DPCSTX_DEBUG_CONFIG__DPCS_DBG_CLOCK_SEL__SHIFT 0x8
+#define DPCSTX_DEBUG_CONFIG__DPCS_DBG_BLOCK_SEL_MASK 0x3800
+#define DPCSTX_DEBUG_CONFIG__DPCS_DBG_BLOCK_SEL__SHIFT 0xb
+#define DPCSTX_DEBUG_CONFIG__DPCS_DBG_CBUS_DIS_MASK 0x4000
+#define DPCSTX_DEBUG_CONFIG__DPCS_DBG_CBUS_DIS__SHIFT 0xe
+#define DPCSTX_DEBUG_CONFIG__DPCS_TEST_DEBUG_WRITE_EN_MASK 0x10000
+#define DPCSTX_DEBUG_CONFIG__DPCS_TEST_DEBUG_WRITE_EN__SHIFT 0x10
+#define DPCSTX_DEBUG_CONFIG__DPCS_DBG_TX_SYMCLK_DIV2_SEL_MASK 0xe0000
+#define DPCSTX_DEBUG_CONFIG__DPCS_DBG_TX_SYMCLK_DIV2_SEL__SHIFT 0x11
+#define DPCSTX_DEBUG_CONFIG__DPCS_TEST_DEBUG_INDEX_MASK 0xff000000
+#define DPCSTX_DEBUG_CONFIG__DPCS_TEST_DEBUG_INDEX__SHIFT 0x18
+#define DPCSTX_TEST_DEBUG_DATA__DPCS_TEST_DEBUG_DATA_MASK 0xffffffff
+#define DPCSTX_TEST_DEBUG_DATA__DPCS_TEST_DEBUG_DATA__SHIFT 0x0
+
+#endif /* DCE_11_2_SH_MASK_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_8_0_d.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_8_0_d.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_8_0_d.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_8_0_d.h	2016-07-24 15:23:50.000000000 -0400
@@ -1391,6 +1391,8 @@
 #define mmRLC_CGTT_MGCG_OVERRIDE                                                0xec48
 #define mmRLC_CGCG_CGLS_CTRL                                                    0xec49
 #define mmRLC_CGCG_RAMP_CTRL                                                    0xec4a
+#define mmRLC_CGCG_CGLS_CTRL_3D                                                 0xec9d
+#define mmRLC_CGCG_RAMP_CTRL_3D                                                 0xec9e
 #define mmRLC_DYN_PG_STATUS                                                     0xec4b
 #define mmRLC_DYN_PG_REQUEST                                                    0xec4c
 #define mmRLC_PG_DELAY                                                          0xec4d
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/include/asic_reg/uvd/uvd_6_0_d.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/include/asic_reg/uvd/uvd_6_0_d.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/include/asic_reg/uvd/uvd_6_0_d.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/include/asic_reg/uvd/uvd_6_0_d.h	2016-07-24 15:23:50.000000000 -0400
@@ -111,5 +111,6 @@
 #define mmUVD_MIF_RECON1_ADDR_CONFIG                                            0x39c5
 #define ixUVD_MIF_SCLR_ADDR_CONFIG                                              0x4
 #define mmUVD_JPEG_ADDR_CONFIG                                                  0x3a1f
+#define mmUVD_GP_SCRATCH4                                                       0x3d38
 
 #endif /* UVD_6_0_D_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/include/atombios.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/include/atombios.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/include/atombios.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/include/atombios.h	2016-07-24 15:23:50.000000000 -0400
@@ -79,9 +79,23 @@
 #define ATOM_PPLL0            2
 #define ATOM_PPLL3            3
 
+#define ATOM_PHY_PLL0         4
+#define ATOM_PHY_PLL1         5
+
 #define ATOM_EXT_PLL1         8
+#define ATOM_GCK_DFS          8
 #define ATOM_EXT_PLL2         9
+#define ATOM_FCH_CLK          9
 #define ATOM_EXT_CLOCK        10
+#define ATOM_DP_DTO           11
+
+#define ATOM_COMBOPHY_PLL0    20
+#define ATOM_COMBOPHY_PLL1    21
+#define ATOM_COMBOPHY_PLL2    22
+#define ATOM_COMBOPHY_PLL3    23
+#define ATOM_COMBOPHY_PLL4    24
+#define ATOM_COMBOPHY_PLL5    25
+
 #define ATOM_PPLL_INVALID     0xFF
 
 #define ENCODER_REFCLK_SRC_P1PLL       0
@@ -224,6 +238,31 @@ typedef struct _ATOM_ROM_HEADER
   UCHAR  ucReserved;
 }ATOM_ROM_HEADER;
 
+
+typedef struct _ATOM_ROM_HEADER_V2_1
+{
+  ATOM_COMMON_TABLE_HEADER      sHeader;
+  UCHAR  uaFirmWareSignature[4];    //Signature to distinguish between Atombios and non-atombios,
+                                    //atombios should init it as "ATOM", don't change the position
+  USHORT usBiosRuntimeSegmentAddress;
+  USHORT usProtectedModeInfoOffset;
+  USHORT usConfigFilenameOffset;
+  USHORT usCRC_BlockOffset;
+  USHORT usBIOS_BootupMessageOffset;
+  USHORT usInt10Offset;
+  USHORT usPciBusDevInitCode;
+  USHORT usIoBaseAddress;
+  USHORT usSubsystemVendorID;
+  USHORT usSubsystemID;
+  USHORT usPCI_InfoOffset;
+  USHORT usMasterCommandTableOffset;//Offest for SW to get all command table offsets, Don't change the position
+  USHORT usMasterDataTableOffset;   //Offest for SW to get all data table offsets, Don't change the position
+  UCHAR  ucExtendedFunctionCode;
+  UCHAR  ucReserved;
+  ULONG  ulPSPDirTableOffset;
+}ATOM_ROM_HEADER_V2_1;
+
+
 //==============================Command Table Portion====================================
 
 
@@ -272,12 +311,12 @@ typedef struct _ATOM_MASTER_LIST_OF_COMM
   USHORT GetSCLKOverMCLKRatio;                   //Atomic Table,  only used by Bios
   USHORT SetCRTC_Timing;                         //Atomic Table,  directly used by various SW components,latest version 1.1
   USHORT SetCRTC_OverScan;                       //Atomic Table,  used by various SW components,latest version 1.1
-  USHORT SetCRTC_Replication;                    //Atomic Table,  used only by Bios
+  USHORT GetSMUClockInfo;                         //Atomic Table,  used only by Bios
   USHORT SelectCRTC_Source;                      //Atomic Table,  directly used by various SW components,latest version 1.1
   USHORT EnableGraphSurfaces;                    //Atomic Table,  used only by Bios
   USHORT UpdateCRTC_DoubleBufferRegisters;       //Atomic Table,  used only by Bios
   USHORT LUT_AutoFill;                           //Atomic Table,  only used by Bios
-  USHORT EnableHW_IconCursor;                    //Atomic Table,  only used by Bios
+  USHORT SetDCEClock;                            //Atomic Table,  start from DCE11.1, shared by driver and VBIOS, change DISPCLK and DPREFCLK
   USHORT GetMemoryClock;                         //Atomic Table,  directly used by various SW components,latest version 1.1
   USHORT GetEngineClock;                         //Atomic Table,  directly used by various SW components,latest version 1.1
   USHORT SetCRTC_UsingDTDTiming;                 //Atomic Table,  directly used by various SW components,latest version 1.1
@@ -292,7 +331,7 @@ typedef struct _ATOM_MASTER_LIST_OF_COMM
   USHORT PowerConnectorDetection;                //Atomic Table,  directly used by various SW components,latest version 1.1
   USHORT MC_Synchronization;                     //Atomic Table,  indirectly used by various SW components,called from SetMemoryClock
   USHORT ComputeMemoryEnginePLL;                 //Atomic Table,  indirectly used by various SW components,called from SetMemory/EngineClock
-  USHORT MemoryRefreshConversion;                //Atomic Table,  indirectly used by various SW components,called from SetMemory or SetEngineClock
+  USHORT Gfx_Init;                               //Atomic Table,  indirectly used by various SW components,called from SetMemory or SetEngineClock
   USHORT VRAM_GetCurrentInfoBlock;               //Atomic Table,  used only by Bios
   USHORT DynamicMemorySettings;                  //Atomic Table,  indirectly used by various SW components,called from SetMemoryClock
   USHORT MemoryTraining;                         //Atomic Table,  used only by Bios
@@ -333,6 +372,10 @@ typedef struct _ATOM_MASTER_LIST_OF_COMM
 #define LCD1OutputControl                        HW_Misc_Operation
 #define TV1OutputControl                         Gfx_Harvesting
 #define TVEncoderControl                         SMC_Init
+#define EnableHW_IconCursor                      SetDCEClock
+#define SetCRTC_Replication                      GetSMUClockInfo
+
+#define MemoryRefreshConversion                  Gfx_Init
 
 typedef struct _ATOM_MASTER_COMMAND_TABLE
 {
@@ -425,6 +468,9 @@ typedef struct _COMPUTE_MEMORY_ENGINE_PL
 #define b3FIRST_TIME_CHANGE_CLOCK                 0x08       //Applicable to both memory and engine clock change,when set, it means this is 1st time to change clock after ASIC bootup
 #define b3SKIP_SW_PROGRAM_PLL                     0x10       //Applicable to both memory and engine clock change, when set, it means the table will not program SPLL/MPLL
 #define b3DRAM_SELF_REFRESH_EXIT                  0x20       //Applicable to DRAM self refresh exit only. when set, it means it will go to program DRAM self refresh exit path
+#define b3SRIOV_INIT_BOOT                         0x40       //Use by HV GPU driver only, to load uCode. for ASIC_InitTable SCLK parameter only
+#define b3SRIOV_LOAD_UCODE                        0x40       //Use by HV GPU driver only, to load uCode. for ASIC_InitTable SCLK parameter only
+#define b3SRIOV_SKIP_ASIC_INIT                    0x02       //Use by HV GPU driver only, skip ASIC_Init for primary adapter boot. for ASIC_InitTable SCLK parameter only
 
 typedef struct _ATOM_COMPUTE_CLOCK_FREQ
 {
@@ -518,6 +564,33 @@ typedef struct _COMPUTE_GPU_CLOCK_OUTPUT
 //ucPllCntlFlag
 #define SPLL_CNTL_FLAG_VCO_MODE_MASK            0x03
 
+typedef struct _COMPUTE_GPU_CLOCK_INPUT_PARAMETERS_V1_7
+{
+  ATOM_COMPUTE_CLOCK_FREQ  ulClock;         //Input Parameter
+  ULONG   ulReserved[5];
+}COMPUTE_GPU_CLOCK_INPUT_PARAMETERS_V1_7;
+
+//ATOM_COMPUTE_CLOCK_FREQ.ulComputeClockFlag
+#define COMPUTE_GPUCLK_INPUT_FLAG_CLK_TYPE_MASK            0x0f
+#define COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK           0x00
+#define COMPUTE_GPUCLK_INPUT_FLAG_SCLK                     0x01
+
+typedef struct _COMPUTE_GPU_CLOCK_OUTPUT_PARAMETERS_V1_7
+{
+  COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V4  ulClock;         //Output Parameter: ucPostDiv=DFS divider
+  USHORT  usSclk_fcw_frac;                  //fractional divider of fcw = usSclk_fcw_frac/65536
+  USHORT  usSclk_fcw_int;                   //integer divider of fcwc
+  UCHAR   ucSclkPostDiv;                    //PLL post divider = 2^ucSclkPostDiv
+  UCHAR   ucSclkVcoMode;                    //0: 4G~8Ghz, 1:3G~6Ghz,3: 2G~4Ghz, 2:Reserved
+  UCHAR   ucSclkPllRange;                   //GreenTable SCLK PLL range entry index ( 0~7 )
+  UCHAR   ucSscEnable;
+  USHORT  usSsc_fcw1_frac;                  //fcw1_frac when SSC enable
+  USHORT  usSsc_fcw1_int;                   //fcw1_int when SSC enable
+  USHORT  usReserved;
+  USHORT  usPcc_fcw_int;
+  USHORT  usSsc_fcw_slew_frac;              //fcw_slew_frac when SSC enable
+  USHORT  usPcc_fcw_slew_frac;
+}COMPUTE_GPU_CLOCK_OUTPUT_PARAMETERS_V1_7;
 
 // ucInputFlag
 #define ATOM_PLL_INPUT_FLAG_PLL_STROBE_MODE_EN  1   // 1-StrobeMode, 0-PerformanceMode
@@ -557,12 +630,16 @@ typedef struct _COMPUTE_MEMORY_CLOCK_PAR
   ULONG ulReserved;
 }COMPUTE_MEMORY_CLOCK_PARAM_PARAMETERS_V2_2;
 
+//Input parameter of DynamicMemorySettingsTable
+//when ATOM_COMPUTE_CLOCK_FREQ.ulComputeClockFlag = COMPUTE_MEMORY_PLL_PARAM
 typedef struct _DYNAMICE_MEMORY_SETTINGS_PARAMETER
 {
   ATOM_COMPUTE_CLOCK_FREQ ulClock;
   ULONG ulReserved[2];
 }DYNAMICE_MEMORY_SETTINGS_PARAMETER;
 
+//Input parameter of DynamicMemorySettingsTable
+//when ATOM_COMPUTE_CLOCK_FREQ.ulComputeClockFlag == COMPUTE_ENGINE_PLL_PARAM
 typedef struct _DYNAMICE_ENGINE_SETTINGS_PARAMETER
 {
   ATOM_COMPUTE_CLOCK_FREQ ulClock;
@@ -570,6 +647,29 @@ typedef struct _DYNAMICE_ENGINE_SETTINGS
   ULONG ulReserved;
 }DYNAMICE_ENGINE_SETTINGS_PARAMETER;
 
+//Input parameter of DynamicMemorySettingsTable ver2.1 and above
+//when ATOM_COMPUTE_CLOCK_FREQ.ulComputeClockFlag == ADJUST_MC_SETTING_PARAM
+typedef struct _DYNAMICE_MC_DPM_SETTINGS_PARAMETER
+{
+  ATOM_COMPUTE_CLOCK_FREQ ulClock;
+  UCHAR ucMclkDPMState;
+  UCHAR ucReserved[3];
+  ULONG ulReserved;
+}DYNAMICE_MC_DPM_SETTINGS_PARAMETER;
+
+//ucMclkDPMState
+#define DYNAMIC_MC_DPM_SETTING_LOW_DPM_STATE       0
+#define DYNAMIC_MC_DPM_SETTING_MEDIUM_DPM_STATE    1
+#define DYNAMIC_MC_DPM_SETTING_HIGH_DPM_STATE      2
+
+typedef union _DYNAMICE_MEMORY_SETTINGS_PARAMETER_V2_1
+{
+  DYNAMICE_MEMORY_SETTINGS_PARAMETER asMCReg;
+  DYNAMICE_ENGINE_SETTINGS_PARAMETER asMCArbReg;
+  DYNAMICE_MC_DPM_SETTINGS_PARAMETER asDPMMCReg;
+}DYNAMICE_MEMORY_SETTINGS_PARAMETER_V2_1;
+
+
 /****************************************************************************/
 // Structures used by SetEngineClockTable
 /****************************************************************************/
@@ -584,6 +684,13 @@ typedef struct _SET_ENGINE_CLOCK_PS_ALLO
   COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_PS_ALLOCATION sReserved;
 }SET_ENGINE_CLOCK_PS_ALLOCATION;
 
+typedef struct _SET_ENGINE_CLOCK_PS_ALLOCATION_V1_2
+{
+  ULONG ulTargetEngineClock;          //In 10Khz unit
+  COMPUTE_GPU_CLOCK_INPUT_PARAMETERS_V1_7 sReserved;
+}SET_ENGINE_CLOCK_PS_ALLOCATION_V1_2;
+
+
 /****************************************************************************/
 // Structures used by SetMemoryClockTable
 /****************************************************************************/
@@ -827,6 +934,12 @@ typedef struct _DIG_ENCODER_CONTROL_PARA
 #define ATOM_ENCODER_CMD_SETUP                        0x0f
 #define ATOM_ENCODER_CMD_SETUP_PANEL_MODE            0x10
 
+// New Command for DIGxEncoderControlTable v1.5
+#define ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN4    0x14
+#define ATOM_ENCODER_CMD_STREAM_SETUP                 0x0F      //change name ATOM_ENCODER_CMD_SETUP
+#define ATOM_ENCODER_CMD_LINK_SETUP                   0x11      //internal use, called by other Command Table
+#define ATOM_ENCODER_CMD_ENCODER_BLANK                0x12      //internal use, called by other Command Table
+
 // ucStatus
 #define ATOM_ENCODER_STATUS_LINK_TRAINING_COMPLETE    0x10
 #define ATOM_ENCODER_STATUS_LINK_TRAINING_INCOMPLETE  0x00
@@ -955,6 +1068,69 @@ typedef struct _DIG_ENCODER_CONTROL_PARA
 #define DP_PANEL_MODE_INTERNAL_DP2_MODE                  0x01
 #define DP_PANEL_MODE_INTERNAL_DP1_MODE                  0x11
 
+
+typedef struct _ENCODER_STREAM_SETUP_PARAMETERS_V5
+{
+  UCHAR ucDigId;           // 0~6 map to DIG0~DIG6
+  UCHAR ucAction;          // =  ATOM_ENOCODER_CMD_STREAM_SETUP
+  UCHAR ucDigMode;         // ATOM_ENCODER_MODE_DP/ATOM_ENCODER_MODE_DVI/ATOM_ENCODER_MODE_HDMI
+  UCHAR ucLaneNum;         // Lane number
+  ULONG ulPixelClock;      // Pixel Clock in 10Khz
+  UCHAR ucBitPerColor;
+  UCHAR ucLinkRateIn270Mhz;//= DP link rate/270Mhz, =6: 1.62G  = 10: 2.7G, =20: 5.4Ghz, =30: 8.1Ghz etc
+  UCHAR ucReserved[2];
+}ENCODER_STREAM_SETUP_PARAMETERS_V5;
+
+typedef struct _ENCODER_LINK_SETUP_PARAMETERS_V5
+{
+  UCHAR ucDigId;           // 0~6 map to DIG0~DIG6
+  UCHAR ucAction;          // =  ATOM_ENOCODER_CMD_LINK_SETUP
+  UCHAR ucDigMode;         // ATOM_ENCODER_MODE_DP/ATOM_ENCODER_MODE_DVI/ATOM_ENCODER_MODE_HDMI
+  UCHAR ucLaneNum;         // Lane number
+  ULONG ulSymClock;        // Symbol Clock in 10Khz
+  UCHAR ucHPDSel;
+  UCHAR ucDigEncoderSel;   // DIG stream( front-end ) selection, bit0 means DIG0 FE is enable,
+  UCHAR ucReserved[2];
+}ENCODER_LINK_SETUP_PARAMETERS_V5;
+
+typedef struct _DP_PANEL_MODE_SETUP_PARAMETERS_V5
+{
+  UCHAR ucDigId;           // 0~6 map to DIG0~DIG6
+  UCHAR ucAction;          // = ATOM_ENCODER_CMD_DPLINK_SETUP
+  UCHAR ucPanelMode;       // =0:     external DP
+                           // =0x1:   internal DP2
+                           // =0x11:  internal DP1 NutMeg/Travis DP Translator
+  UCHAR ucReserved;
+  ULONG ulReserved[2];
+}DP_PANEL_MODE_SETUP_PARAMETERS_V5;
+
+typedef struct _ENCODER_GENERIC_CMD_PARAMETERS_V5
+{
+  UCHAR ucDigId;           // 0~6 map to DIG0~DIG6
+  UCHAR ucAction;          // = rest of generic encoder command which does not carry any parameters
+  UCHAR ucReserved[2];
+  ULONG ulReserved[2];
+}ENCODER_GENERIC_CMD_PARAMETERS_V5;
+
+//ucDigId
+#define ATOM_ENCODER_CONFIG_V5_DIG0_ENCODER                 0x00
+#define ATOM_ENCODER_CONFIG_V5_DIG1_ENCODER                 0x01
+#define ATOM_ENCODER_CONFIG_V5_DIG2_ENCODER                 0x02
+#define ATOM_ENCODER_CONFIG_V5_DIG3_ENCODER                 0x03
+#define ATOM_ENCODER_CONFIG_V5_DIG4_ENCODER                 0x04
+#define ATOM_ENCODER_CONFIG_V5_DIG5_ENCODER                 0x05
+#define ATOM_ENCODER_CONFIG_V5_DIG6_ENCODER                 0x06
+
+
+typedef union _DIG_ENCODER_CONTROL_PARAMETERS_V5
+{
+  ENCODER_GENERIC_CMD_PARAMETERS_V5  asCmdParam;
+  ENCODER_STREAM_SETUP_PARAMETERS_V5 asStreamParam;
+  ENCODER_LINK_SETUP_PARAMETERS_V5  asLinkParam;
+  DP_PANEL_MODE_SETUP_PARAMETERS_V5 asDPPanelModeParam;
+}DIG_ENCODER_CONTROL_PARAMETERS_V5;
+
+
 /****************************************************************************/
 // Structures used by UNIPHYTransmitterControlTable
 //                    LVTMATransmitterControlTable
@@ -1371,6 +1547,49 @@ typedef struct _DIG_TRANSMITTER_CONTROL_
 
 #define DIG_TRANSMITTER_CONTROL_PS_ALLOCATION_V1_5            DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_5
 
+typedef struct _DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_6
+{
+  UCHAR ucPhyId;           // 0=UNIPHYA, 1=UNIPHYB, 2=UNIPHYC, 3=UNIPHYD, 4= UNIPHYE 5=UNIPHYF
+  UCHAR ucAction;          // define as ATOM_TRANSMITER_ACTION_xxx
+  union
+  {
+    UCHAR ucDigMode;       // ATOM_ENCODER_MODE_DP/ATOM_ENCODER_MODE_DVI/ATOM_ENCODER_MODE_HDMI
+    UCHAR ucDPLaneSet;     // DP voltage swing and pre-emphasis value defined in DPCD DP_LANE_SET, "DP_LANE_SET__xDB_y_zV"
+  };
+  UCHAR ucLaneNum;         // Lane number
+  ULONG ulSymClock;        // Symbol Clock in 10Khz
+  UCHAR ucHPDSel;          // =1: HPD1, =2: HPD2, .... =6: HPD6, =0: HPD is not assigned
+  UCHAR ucDigEncoderSel;   // DIG stream( front-end ) selection, bit0 means DIG0 FE is enable,
+  UCHAR ucConnObjId;       // Connector Object Id defined in ObjectId.h
+  UCHAR ucReserved;
+  ULONG ulReserved;
+}DIG_TRANSMITTER_CONTROL_PARAMETERS_V1_6;
+
+
+// ucDigEncoderSel
+#define ATOM_TRANMSITTER_V6__DIGA_SEL                       0x01
+#define ATOM_TRANMSITTER_V6__DIGB_SEL                       0x02
+#define ATOM_TRANMSITTER_V6__DIGC_SEL                       0x04
+#define ATOM_TRANMSITTER_V6__DIGD_SEL                       0x08
+#define ATOM_TRANMSITTER_V6__DIGE_SEL                       0x10
+#define ATOM_TRANMSITTER_V6__DIGF_SEL                       0x20
+#define ATOM_TRANMSITTER_V6__DIGG_SEL                       0x40
+
+// ucDigMode
+#define ATOM_TRANSMITTER_DIGMODE_V6_DP                      0
+#define ATOM_TRANSMITTER_DIGMODE_V6_DVI                     2
+#define ATOM_TRANSMITTER_DIGMODE_V6_HDMI                    3
+#define ATOM_TRANSMITTER_DIGMODE_V6_DP_MST                  5
+
+//ucHPDSel
+#define ATOM_TRANSMITTER_V6_NO_HPD_SEL                      0x00
+#define ATOM_TRANSMITTER_V6_HPD1_SEL                        0x01
+#define ATOM_TRANSMITTER_V6_HPD2_SEL                        0x02
+#define ATOM_TRANSMITTER_V6_HPD3_SEL                        0x03
+#define ATOM_TRANSMITTER_V6_HPD4_SEL                        0x04
+#define ATOM_TRANSMITTER_V6_HPD5_SEL                        0x05
+#define ATOM_TRANSMITTER_V6_HPD6_SEL                        0x06
+
 
 /****************************************************************************/
 // Structures used by ExternalEncoderControlTable V1.3
@@ -1784,6 +2003,101 @@ typedef struct _GET_DISP_PLL_STATUS_INPU
   PIXEL_CLOCK_PARAMETERS_V5 sDispClkInput;
 }GET_DISP_PLL_STATUS_INPUT_PARAMETERS_V3;
 
+typedef struct _PIXEL_CLOCK_PARAMETERS_V7
+{
+    ULONG  ulPixelClock;               // target the pixel clock to drive the CRTC timing in unit of 100Hz.
+
+    UCHAR  ucPpll;                     // ATOM_PHY_PLL0/ATOM_PHY_PLL1/ATOM_PPLL0
+    UCHAR  ucTransmitterID;            // ASIC encoder id defined in objectId.h,
+                                       // indicate which graphic encoder will be used.
+    UCHAR  ucEncoderMode;              // Encoder mode:
+    UCHAR  ucMiscInfo;                 // bit[0]= Force program PLL for pixclk
+                                       // bit[1]= Force program PHY PLL only ( internally used by VBIOS only in DP case which PHYPLL is programmed for SYMCLK, not Pixclk )
+                                       // bit[5:4]= RefClock source for PPLL.
+                                       //          =0: XTLAIN( default mode )
+                                       //          =1: pcie
+                                       //          =2: GENLK
+    UCHAR  ucCRTC;                     // ATOM_CRTC1~6, indicate the CRTC controller to
+    UCHAR  ucDeepColorRatio;           // HDMI panel bit depth: =0: 24bpp =1:30bpp, =2:36bpp
+    UCHAR  ucReserved[2];
+    ULONG  ulReserved;
+}PIXEL_CLOCK_PARAMETERS_V7;
+
+//ucMiscInfo
+#define PIXEL_CLOCK_V7_MISC_FORCE_PROG_PPLL         0x01
+#define PIXEL_CLOCK_V7_MISC_PROG_PHYPLL             0x02
+#define PIXEL_CLOCK_V7_MISC_YUV420_MODE             0x04
+#define PIXEL_CLOCK_V7_MISC_DVI_DUALLINK_EN         0x08
+#define PIXEL_CLOCK_V7_MISC_REF_DIV_SRC             0x30
+#define PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_XTALIN      0x00
+#define PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_PCIE        0x10
+#define PIXEL_CLOCK_V7_MISC_REF_DIV_SRC_GENLK       0x20
+
+//ucDeepColorRatio
+#define PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_DIS          0x00      //00 - DCCG_DEEP_COLOR_DTO_DISABLE: Disable Deep Color DTO
+#define PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_5_4          0x01      //01 - DCCG_DEEP_COLOR_DTO_5_4_RATIO: Set Deep Color DTO to 5:4
+#define PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_3_2          0x02      //02 - DCCG_DEEP_COLOR_DTO_3_2_RATIO: Set Deep Color DTO to 3:2
+#define PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_2_1          0x03      //03 - DCCG_DEEP_COLOR_DTO_2_1_RATIO: Set Deep Color DTO to 2:1
+
+// SetDCEClockTable input parameter for DCE11.1
+typedef struct _SET_DCE_CLOCK_PARAMETERS_V1_1
+{
+  ULONG  ulDISPClkFreq;       // target DISPCLK frquency in unit of 10kHz, return real DISPCLK frequency. when ucFlag[1]=1, in unit of 100Hz.
+  UCHAR  ucFlag;              // bit0=1: DPREFCLK bypass DFS bit0=0: DPREFCLK not bypass DFS
+  UCHAR  ucCrtc;              // use when enable DCCG pixel clock ucFlag[1]=1
+  UCHAR  ucPpllId;            // use when enable DCCG pixel clock ucFlag[1]=1
+  UCHAR  ucDeepColorRatio;    // use when enable DCCG pixel clock ucFlag[1]=1
+}SET_DCE_CLOCK_PARAMETERS_V1_1;
+
+
+typedef struct _SET_DCE_CLOCK_PS_ALLOCATION_V1_1
+{
+  SET_DCE_CLOCK_PARAMETERS_V1_1 asParam;
+  ULONG ulReserved[2];
+}SET_DCE_CLOCK_PS_ALLOCATION_V1_1;
+
+//SET_DCE_CLOCK_PARAMETERS_V1_1.ucFlag
+#define SET_DCE_CLOCK_FLAG_GEN_DPREFCLK            0x01
+#define SET_DCE_CLOCK_FLAG_DPREFCLK_BYPASS         0x01
+#define SET_DCE_CLOCK_FLAG_ENABLE_PIXCLK           0x02
+
+// SetDCEClockTable input parameter for DCE11.2( POLARIS10 and POLARIS11 ) and above
+typedef struct _SET_DCE_CLOCK_PARAMETERS_V2_1
+{
+  ULONG  ulDCEClkFreq;                               // target DCE frequency in unit of 10KHZ, return real DISPCLK/DPREFCLK frequency.
+  UCHAR  ucDCEClkType;                               // =0: DISPCLK  =1: DPREFCLK  =2: PIXCLK
+  UCHAR  ucDCEClkSrc;                                // ATOM_PLL0 or ATOM_GCK_DFS or ATOM_FCH_CLK or ATOM_COMBOPHY_PLLx
+  UCHAR  ucDCEClkFlag;                               // Bit [1:0] = PPLL ref clock source ( when ucDCEClkSrc= ATOM_PPLL0 )
+  UCHAR  ucCRTC;                                     // ucDisp Pipe Id, ATOM_CRTC0/1/2/..., use only when ucDCEClkType = PIXCLK
+}SET_DCE_CLOCK_PARAMETERS_V2_1;
+
+//ucDCEClkType
+#define DCE_CLOCK_TYPE_DISPCLK                        0
+#define DCE_CLOCK_TYPE_DPREFCLK                       1
+#define DCE_CLOCK_TYPE_PIXELCLK                       2        // used by VBIOS internally, called by SetPixelClockTable
+
+//ucDCEClkFlag when ucDCEClkType == DPREFCLK
+#define DCE_CLOCK_FLAG_PLL_REFCLK_SRC_MASK            0x03
+#define DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENERICA        0x00
+#define DCE_CLOCK_FLAG_PLL_REFCLK_SRC_GENLK           0x01
+#define DCE_CLOCK_FLAG_PLL_REFCLK_SRC_PCIE            0x02
+#define DCE_CLOCK_FLAG_PLL_REFCLK_SRC_XTALIN          0x03
+
+//ucDCEClkFlag when ucDCEClkType == PIXCLK
+#define DCE_CLOCK_FLAG_PCLK_DEEPCOLOR_RATIO_MASK      0x03
+#define DCE_CLOCK_FLAG_PCLK_DEEPCOLOR_RATIO_DIS       0x00      //00 - DCCG_DEEP_COLOR_DTO_DISABLE: Disable Deep Color DTO
+#define DCE_CLOCK_FLAG_PCLK_DEEPCOLOR_RATIO_5_4       0x01      //01 - DCCG_DEEP_COLOR_DTO_5_4_RATIO: Set Deep Color DTO to 5:4
+#define DCE_CLOCK_FLAG_PCLK_DEEPCOLOR_RATIO_3_2       0x02      //02 - DCCG_DEEP_COLOR_DTO_3_2_RATIO: Set Deep Color DTO to 3:2
+#define DCE_CLOCK_FLAG_PCLK_DEEPCOLOR_RATIO_2_1       0x03      //03 - DCCG_DEEP_COLOR_DTO_2_1_RATIO: Set Deep Color DTO to 2:1
+#define DCE_CLOCK_FLAG_PIXCLK_YUV420_MODE             0x04
+
+typedef struct _SET_DCE_CLOCK_PS_ALLOCATION_V2_1
+{
+  SET_DCE_CLOCK_PARAMETERS_V2_1 asParam;
+  ULONG ulReserved[2];
+}SET_DCE_CLOCK_PS_ALLOCATION_V2_1;
+
+
 
 /****************************************************************************/
 // Structures used by AdjustDisplayPllTable
@@ -2300,6 +2614,11 @@ typedef struct   _SET_VOLTAGE_PARAMETERS
 #define VOLTAGE_TYPE_VDDCI                   4
 #define VOLTAGE_TYPE_VDDGFX                  5
 #define VOLTAGE_TYPE_PCC                     6
+#define VOLTAGE_TYPE_MVPP                    7
+#define VOLTAGE_TYPE_LEDDPM                  8
+#define VOLTAGE_TYPE_PCC_MVDD                9
+#define VOLTAGE_TYPE_PCIE_VDDC               10
+#define VOLTAGE_TYPE_PCIE_VDDR               11
 
 #define VOLTAGE_TYPE_GENERIC_I2C_1           0x11
 #define VOLTAGE_TYPE_GENERIC_I2C_2           0x12
@@ -2396,6 +2715,39 @@ typedef struct  _GET_EVV_VOLTAGE_INFO_OU
   USHORT   usTDP_Power;                                  // TDP_Current in unit  of 0.1W
 }GET_EVV_VOLTAGE_INFO_OUTPUT_PARAMETER_V1_2;
 
+
+// New Added from CI Hawaii for GetVoltageInfoTable, input parameter structure
+typedef struct  _GET_VOLTAGE_INFO_INPUT_PARAMETER_V1_3
+{
+  UCHAR    ucVoltageType;               // Input: To tell which voltage to set up, VDDC/MVDDC/MVDDQ/VDDCI
+  UCHAR    ucVoltageMode;               // Input: Indicate action: Get voltage info
+  USHORT   usVoltageLevel;              // Input: real voltage level in unit of mv or Voltage Phase (0, 1, 2, .. ) or Leakage Id
+  ULONG    ulSCLKFreq;                  // Input: when ucVoltageMode= ATOM_GET_VOLTAGE_EVV_VOLTAGE, DPM state SCLK frequency, Define in PPTable SCLK/Voltage dependence table
+  ULONG    ulReserved[3];
+}GET_VOLTAGE_INFO_INPUT_PARAMETER_V1_3;
+
+// New Added from CI Hawaii for EVV feature
+typedef struct  _GET_EVV_VOLTAGE_INFO_OUTPUT_PARAMETER_V1_3
+{
+  ULONG    ulVoltageLevel;                               // real voltage level in unit of 0.01mv
+  ULONG    ulReserved[4];
+}GET_EVV_VOLTAGE_INFO_OUTPUT_PARAMETER_V1_3;
+
+
+/****************************************************************************/
+// Structures used by GetSMUClockInfo
+/****************************************************************************/
+typedef struct  _GET_SMU_CLOCK_INFO_INPUT_PARAMETER_V2_1
+{
+  ULONG ulDfsPllOutputFreq:24;
+  ULONG ucDfsDivider:8;
+}GET_SMU_CLOCK_INFO_INPUT_PARAMETER_V2_1;
+
+typedef struct  _GET_SMU_CLOCK_INFO_OUTPUT_PARAMETER_V2_1
+{
+  ULONG ulDfsOutputFreq;
+}GET_SMU_CLOCK_INFO_OUTPUT_PARAMETER_V2_1;
+
 /****************************************************************************/
 // Structures used by TVEncoderControlTable
 /****************************************************************************/
@@ -2429,13 +2781,13 @@ typedef struct _ATOM_MASTER_LIST_OF_DATA
   USHORT        PaletteData;              // Only used by BIOS
   USHORT        LCD_Info;                 // Shared by various SW components,latest version 1.3, was called LVDS_Info
   USHORT        DIGTransmitterInfo;       // Internal used by VBIOS only version 3.1
-  USHORT        AnalogTV_Info;            // Shared by various SW components,latest version 1.1
+  USHORT        SMU_Info;                 // Shared by various SW components,latest version 1.1
   USHORT        SupportedDevicesInfo;     // Will be obsolete from R600
   USHORT        GPIO_I2C_Info;            // Shared by various SW components,latest version 1.2 will be used from R600
   USHORT        VRAM_UsageByFirmware;     // Shared by various SW components,latest version 1.3 will be used from R600
   USHORT        GPIO_Pin_LUT;             // Shared by various SW components,latest version 1.1
   USHORT        VESA_ToInternalModeLUT;   // Only used by Bios
-  USHORT        ComponentVideoInfo;       // Shared by various SW components,latest version 2.1 will be used from R600
+  USHORT        GFX_Info;                 // Shared by various SW components,latest version 2.1 will be used from R600
   USHORT        PowerPlayInfo;            // Shared by various SW components,latest version 2.1,new design from R600
   USHORT        GPUVirtualizationInfo;    // Will be obsolete from R600
   USHORT        SaveRestoreInfo;          // Only used by Bios
@@ -2455,7 +2807,7 @@ typedef struct _ATOM_MASTER_LIST_OF_DATA
   USHORT        ASIC_ProfilingInfo;       // New table name from R600, used to be called "ASIC_VDDCI_Info" for pre-R600
   USHORT        VoltageObjectInfo;        // Shared by various SW components, latest version 1.1
   USHORT        PowerSourceInfo;          // Shared by various SW components, latest versoin 1.1
-  USHORT	      ServiceInfo;
+  USHORT        ServiceInfo;
 }ATOM_MASTER_LIST_OF_DATA_TABLES;
 
 typedef struct _ATOM_MASTER_DATA_TABLE
@@ -2469,6 +2821,8 @@ typedef struct _ATOM_MASTER_DATA_TABLE
 #define DAC_Info                 PaletteData
 #define TMDS_Info                DIGTransmitterInfo
 #define CompassionateData        GPUVirtualizationInfo
+#define AnalogTV_Info            SMU_Info
+#define ComponentVideoInfo       GFX_Info
 
 /****************************************************************************/
 // Structure used in MultimediaCapabilityInfoTable
@@ -4278,10 +4632,15 @@ typedef struct _EXT_DISPLAY_PATH
 #define MAX_NUMBER_OF_EXT_DISPLAY_PATH    7
 
 //usCaps
-#define  EXT_DISPLAY_PATH_CAPS__HBR2_DISABLE               0x01
-#define  EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN             0x02
-#define  EXT_DISPLAY_PATH_CAPS__HDMI20_PI3EQX1204          0x04
-#define  EXT_DISPLAY_PATH_CAPS__HDMI20_TISN65DP159RSBT     0x08
+#define  EXT_DISPLAY_PATH_CAPS__HBR2_DISABLE               0x0001
+#define  EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN             0x0002
+#define  EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK              0x007C
+#define  EXT_DISPLAY_PATH_CAPS__HDMI20_PI3EQX1204          (0x01 << 2 )     //PI redriver chip
+#define  EXT_DISPLAY_PATH_CAPS__HDMI20_TISN65DP159RSBT     (0x02 << 2 )     //TI retimer chip
+#define  EXT_DISPLAY_PATH_CAPS__HDMI20_PARADE_PS175        (0x03 << 2 )     //Parade DP->HDMI recoverter chip
+
+
+
 
 typedef  struct _ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO
 {
@@ -4325,10 +4684,10 @@ typedef struct _ATOM_COMMON_RECORD_HEADE
 #define ATOM_CONNECTOR_REMOTE_CAP_RECORD_TYPE          19
 #define ATOM_ENCODER_CAP_RECORD_TYPE                   20
 #define ATOM_BRACKET_LAYOUT_RECORD_TYPE                21
-
+#define ATOM_CONNECTOR_FORCED_TMDS_CAP_RECORD_TYPE     22
 
 //Must be updated when new record type is added,equal to that record definition!
-#define ATOM_MAX_OBJECT_RECORD_NUMBER             ATOM_ENCODER_CAP_RECORD_TYPE
+#define ATOM_MAX_OBJECT_RECORD_NUMBER                  ATOM_CONNECTOR_FORCED_TMDS_CAP_RECORD_TYPE
 
 typedef struct  _ATOM_I2C_RECORD
 {
@@ -4458,10 +4817,12 @@ typedef struct  _ATOM_ENCODER_DVO_CF_REC
   UCHAR                       ucPadding[2];
 }ATOM_ENCODER_DVO_CF_RECORD;
 
-// Bit maps for ATOM_ENCODER_CAP_RECORD.ucEncoderCap
-#define ATOM_ENCODER_CAP_RECORD_HBR2                  0x01         // DP1.2 HBR2 is supported by HW encoder
+// Bit maps for ATOM_ENCODER_CAP_RECORD.usEncoderCap
+#define ATOM_ENCODER_CAP_RECORD_HBR2                  0x01         // DP1.2 HBR2 is supported by HW encoder, it is retired in NI. the real meaning from SI is MST_EN
+#define ATOM_ENCODER_CAP_RECORD_MST_EN                0x01         // from SI, this bit means DP MST is enable or not.
 #define ATOM_ENCODER_CAP_RECORD_HBR2_EN               0x02         // DP1.2 HBR2 setting is qualified and HBR2 can be enabled
 #define ATOM_ENCODER_CAP_RECORD_HDMI6Gbps_EN          0x04         // HDMI2.0 6Gbps enable or not.
+#define ATOM_ENCODER_CAP_RECORD_HBR3_EN               0x08         // DP1.3 HBR3 is supported by board.
 
 typedef struct  _ATOM_ENCODER_CAP_RECORD
 {
@@ -4482,6 +4843,31 @@ typedef struct  _ATOM_ENCODER_CAP_RECORD
   };
 }ATOM_ENCODER_CAP_RECORD;
 
+// Used after SI
+typedef struct  _ATOM_ENCODER_CAP_RECORD_V2
+{
+  ATOM_COMMON_RECORD_HEADER   sheader;
+  union {
+    USHORT                    usEncoderCap;
+    struct {
+#if ATOM_BIG_ENDIAN
+      USHORT                  usReserved:12;        // Bit4-15 may be defined for other capability in future
+      USHORT                  usHBR3En:1;           // bit3 is for DP1.3 HBR3 enable
+      USHORT                  usHDMI6GEn:1;         // Bit2 is for HDMI6Gbps enable, this bit is used starting from CZ( APU) Ellemere (dGPU)
+      USHORT                  usHBR2En:1;           // Bit1 is for DP1.2 HBR2 enable
+      USHORT                  usMSTEn:1;            // Bit0 is for DP1.2 MST enable
+#else
+      USHORT                  usMSTEn:1;            // Bit0 is for DP1.2 MST enable
+      USHORT                  usHBR2En:1;           // Bit1 is for DP1.2 HBR2 enable
+      USHORT                  usHDMI6GEn:1;         // Bit2 is for HDMI6Gbps enable, this bit is used starting from CZ( APU) Ellemere (dGPU)
+      USHORT                  usHBR3En:1;           // bit3 is for DP1.3 HBR3 enable
+      USHORT                  usReserved:12;        // Bit4-15 may be defined for other capability in future
+#endif
+    };
+  };
+}ATOM_ENCODER_CAP_RECORD_V2;
+
+
 // value for ATOM_CONNECTOR_CF_RECORD.ucConnectedDvoBundle
 #define ATOM_CONNECTOR_CF_RECORD_CONNECTED_UPPER12BITBUNDLEA   1
 #define ATOM_CONNECTOR_CF_RECORD_CONNECTED_LOWER12BITBUNDLEB   2
@@ -4554,6 +4940,16 @@ typedef struct _ATOM_CONNECTOR_REMOTE_CA
   USHORT                      usReserved;
 }ATOM_CONNECTOR_REMOTE_CAP_RECORD;
 
+
+typedef struct  _ATOM_CONNECTOR_FORCED_TMDS_CAP_RECORD
+{
+  ATOM_COMMON_RECORD_HEADER   sheader;
+  // override TMDS capability on this connector when it operate in TMDS mode.  usMaxTmdsClkRate = max TMDS Clock in Mhz/2.5
+  UCHAR                       ucMaxTmdsClkRateIn2_5Mhz;
+  UCHAR                       ucReserved;
+} ATOM_CONNECTOR_FORCED_TMDS_CAP_RECORD;
+
+
 typedef struct  _ATOM_CONNECTOR_LAYOUT_INFO
 {
    USHORT usConnectorObjectId;
@@ -4657,12 +5053,12 @@ typedef struct _ATOM_VOLTAGE_CONTROL
 #define VOLTAGE_CONTROL_ID_UP1801             0x0C
 #define VOLTAGE_CONTROL_ID_ST6788A            0x0D
 #define VOLTAGE_CONTROL_ID_CHLIR3564SVI2      0x0E
-#define VOLTAGE_CONTROL_ID_AD527x      	      0x0F
-#define VOLTAGE_CONTROL_ID_NCP81022    	      0x10
-#define VOLTAGE_CONTROL_ID_LTC2635			  0x11
-#define VOLTAGE_CONTROL_ID_NCP4208	          0x12
+#define VOLTAGE_CONTROL_ID_AD527x             0x0F
+#define VOLTAGE_CONTROL_ID_NCP81022           0x10
+#define VOLTAGE_CONTROL_ID_LTC2635            0x11
+#define VOLTAGE_CONTROL_ID_NCP4208            0x12
 #define VOLTAGE_CONTROL_ID_IR35xx             0x13
-#define VOLTAGE_CONTROL_ID_RT9403	          0x14
+#define VOLTAGE_CONTROL_ID_RT9403             0x14
 
 #define VOLTAGE_CONTROL_ID_GENERIC_I2C        0x40
 
@@ -4784,11 +5180,38 @@ typedef struct  _ATOM_SVID2_VOLTAGE_OBJE
    ULONG    ulReserved;
 }ATOM_SVID2_VOLTAGE_OBJECT_V3;
 
+
+
+typedef struct  _ATOM_MERGED_VOLTAGE_OBJECT_V3
+{
+   ATOM_VOLTAGE_OBJECT_HEADER_V3 sHeader;    // voltage mode = VOLTAGE_OBJ_MERGED_POWER
+   UCHAR    ucMergedVType;                   // VDDC/VDCCI/....
+   UCHAR    ucReserved[3];
+}ATOM_MERGED_VOLTAGE_OBJECT_V3;
+
+
+typedef struct _ATOM_EVV_DPM_INFO
+{
+  ULONG ulDPMSclk;            // DPM state SCLK
+  USHORT usVAdjOffset;        // Adjust Voltage offset in unit of mv
+  UCHAR ucDPMTblVIndex;       // Voltage Index in SMC_DPM_Table structure VddcTable/VddGfxTable
+  UCHAR ucDPMState;           // DPMState0~7
+} ATOM_EVV_DPM_INFO;
+
+// ucVoltageMode = VOLTAGE_OBJ_EVV
+typedef struct  _ATOM_EVV_VOLTAGE_OBJECT_V3
+{
+  ATOM_VOLTAGE_OBJECT_HEADER_V3 sHeader;    // voltage mode = VOLTAGE_OBJ_SVID2
+  ATOM_EVV_DPM_INFO asEvvDpmList[8];
+}ATOM_EVV_VOLTAGE_OBJECT_V3;
+
+
 typedef union _ATOM_VOLTAGE_OBJECT_V3{
   ATOM_GPIO_VOLTAGE_OBJECT_V3 asGpioVoltageObj;
   ATOM_I2C_VOLTAGE_OBJECT_V3 asI2cVoltageObj;
   ATOM_LEAKAGE_VOLTAGE_OBJECT_V3 asLeakageObj;
   ATOM_SVID2_VOLTAGE_OBJECT_V3 asSVID2Obj;
+  ATOM_EVV_VOLTAGE_OBJECT_V3 asEvvObj;
 }ATOM_VOLTAGE_OBJECT_V3;
 
 typedef struct  _ATOM_VOLTAGE_OBJECT_INFO_V3_1
@@ -4963,7 +5386,11 @@ typedef struct  _ATOM_ASIC_PROFILING_INF
   ULONG  ulLkgEncodeMax;
   ULONG  ulLkgEncodeMin;
   ULONG  ulEfuseLogisticAlpha;
+
+  union{
   USHORT usPowerDpm0;
+  USHORT usParamNegFlag;          //bit0 =1 :indicate ulRoBeta is Negative, bit1=1 indicate Kv_m  max is postive
+  };
   USHORT usPowerDpm1;
   USHORT usPowerDpm2;
   USHORT usPowerDpm3;
@@ -5067,6 +5494,158 @@ typedef struct  _ATOM_ASIC_PROFILING_INF
   ULONG ulReserved[8];            // Reserved for future ASIC
 }ATOM_ASIC_PROFILING_INFO_V3_4;
 
+// for  Polaris10/Polaris11 speed EVV algorithm
+typedef struct  _ATOM_ASIC_PROFILING_INFO_V3_5
+{
+  ATOM_COMMON_TABLE_HEADER         asHeader;
+  ULONG  ulMaxVddc;               //Maximum voltage for all parts, in unit of 0.01mv
+  ULONG  ulMinVddc;               //Minimum voltage for all parts, in unit of 0.01mv
+  USHORT usLkgEuseIndex;          //Efuse Lkg_FT address ( BYTE address )
+  UCHAR  ucLkgEfuseBitLSB;        //Efuse Lkg_FT bit shift in 32bit DWORD
+  UCHAR  ucLkgEfuseLength;        //Efuse Lkg_FT length
+  ULONG  ulLkgEncodeLn_MaxDivMin; //value of ln(Max_Lkg_Ft/Min_Lkg_Ft ) in unit of 0.00001 ( unit=100000 )
+  ULONG  ulLkgEncodeMax;          //Maximum Lkg_Ft measured value ( or efuse decode value ), in unit of 0.00001 ( unit=100000 )
+  ULONG  ulLkgEncodeMin;          //Minimum Lkg_Ft measured value ( or efuse decode value ), in unit of 0.00001 ( unit=100000 )
+  EFUSE_LINEAR_FUNC_PARAM sRoFuse;//Efuse RO info: DWORD address, bit shift, length, max/min measure value. in unit of 1.
+  ULONG  ulEvvDefaultVddc;        //def="EVV_DEFAULT_VDDC" descr="return default VDDC(v) when Efuse not cut" unit="100000"/>
+  ULONG  ulEvvNoCalcVddc;         //def="EVV_NOCALC_VDDC" descr="return VDDC(v) when Calculation is bad" unit="100000"/>
+  ULONG  ulSpeed_Model;           //def="EVV_SPEED_MODEL" descr="0 = Greek model, 1 = multivariate model" unit="1"/>
+  ULONG  ulSM_A0;                 //def="EVV_SM_A0" descr="Leakage coeff(Multivariant Mode)." unit="100000"/>
+  ULONG  ulSM_A1;                 //def="EVV_SM_A1" descr="Leakage/SCLK coeff(Multivariant Mode)." unit="1000000"/>
+  ULONG  ulSM_A2;                 //def="EVV_SM_A2" descr="Alpha( Greek Mode ) or VDDC/SCLK coeff(Multivariant Mode)." unit="100000"/>
+  ULONG  ulSM_A3;                 //def="EVV_SM_A3" descr="Beta( Greek Mode ) or SCLK coeff(Multivariant Mode)." unit="100000"/>
+  ULONG  ulSM_A4;                 //def="EVV_SM_A4" descr="VDDC^2/SCLK coeff(Multivariant Mode)." unit="100000"/>
+  ULONG  ulSM_A5;                 //def="EVV_SM_A5" descr="VDDC^2 coeff(Multivariant Mode)." unit="100000"/>
+  ULONG  ulSM_A6;                 //def="EVV_SM_A6" descr="Gamma( Greek Mode ) or VDDC coeff(Multivariant Mode)." unit="100000"/>
+  ULONG  ulSM_A7;                 //def="EVV_SM_A7" descr="Epsilon( Greek Mode ) or constant(Multivariant Mode)." unit="100000"/>
+  UCHAR  ucSM_A0_sign;            //def="EVV_SM_A0_SIGN" descr="=0 SM_A0 is postive. =1: SM_A0 is negative" unit="1"/>
+  UCHAR  ucSM_A1_sign;            //def="EVV_SM_A1_SIGN" descr="=0 SM_A1 is postive. =1: SM_A1 is negative" unit="1"/>
+  UCHAR  ucSM_A2_sign;            //def="EVV_SM_A2_SIGN" descr="=0 SM_A2 is postive. =1: SM_A2 is negative" unit="1"/>
+  UCHAR  ucSM_A3_sign;            //def="EVV_SM_A3_SIGN" descr="=0 SM_A3 is postive. =1: SM_A3 is negative" unit="1"/>
+  UCHAR  ucSM_A4_sign;            //def="EVV_SM_A4_SIGN" descr="=0 SM_A4 is postive. =1: SM_A4 is negative" unit="1"/>
+  UCHAR  ucSM_A5_sign;            //def="EVV_SM_A5_SIGN" descr="=0 SM_A5 is postive. =1: SM_A5 is negative" unit="1"/>
+  UCHAR  ucSM_A6_sign;            //def="EVV_SM_A6_SIGN" descr="=0 SM_A6 is postive. =1: SM_A6 is negative" unit="1"/>
+  UCHAR  ucSM_A7_sign;            //def="EVV_SM_A7_SIGN" descr="=0 SM_A7 is postive. =1: SM_A7 is negative" unit="1"/>
+  ULONG  ulMargin_RO_a;           //def="EVV_MARGIN_RO_A" descr="A Term to represent RO equation in Ax2+Bx+C, unit=1"
+  ULONG  ulMargin_RO_b;           //def="EVV_MARGIN_RO_B" descr="B Term to represent RO equation in Ax2+Bx+C, unit=1"
+  ULONG  ulMargin_RO_c;           //def="EVV_MARGIN_RO_C" descr="C Term to represent RO equation in Ax2+Bx+C, unit=1"
+  ULONG  ulMargin_fixed;          //def="EVV_MARGIN_FIXED" descr="Fixed MHz to add to SCLK margin, unit=1" unit="1"/>
+  ULONG  ulMargin_Fmax_mean;      //def="EVV_MARGIN_FMAX_MEAN" descr="Percentage to add for Fmas mean margin unit=10000" unit="10000"/>
+  ULONG  ulMargin_plat_mean;      //def="EVV_MARGIN_PLAT_MEAN" descr="Percentage to add for platform mean margin unit=10000" unit="10000"/>
+  ULONG  ulMargin_Fmax_sigma;     //def="EVV_MARGIN_FMAX_SIGMA" descr="Percentage to add for Fmax sigma margin unit=10000" unit="10000"/>
+  ULONG  ulMargin_plat_sigma;     //def="EVV_MARGIN_PLAT_SIGMA" descr="Percentage to add for platform sigma margin unit=10000" unit="10000"/>
+  ULONG  ulMargin_DC_sigma;       //def="EVV_MARGIN_DC_SIGMA" descr="Regulator DC tolerance margin (mV) unit=100" unit="100"/>
+  ULONG  ulReserved[12];
+}ATOM_ASIC_PROFILING_INFO_V3_5;
+
+/* for Polars10/11 AVFS parameters */
+typedef struct  _ATOM_ASIC_PROFILING_INFO_V3_6
+{
+  ATOM_COMMON_TABLE_HEADER         asHeader;
+  ULONG  ulMaxVddc;
+  ULONG  ulMinVddc;
+  USHORT usLkgEuseIndex;
+  UCHAR  ucLkgEfuseBitLSB;
+  UCHAR  ucLkgEfuseLength;
+  ULONG  ulLkgEncodeLn_MaxDivMin;
+  ULONG  ulLkgEncodeMax;
+  ULONG  ulLkgEncodeMin;
+  EFUSE_LINEAR_FUNC_PARAM sRoFuse;
+  ULONG  ulEvvDefaultVddc;
+  ULONG  ulEvvNoCalcVddc;
+  ULONG  ulSpeed_Model;
+  ULONG  ulSM_A0;
+  ULONG  ulSM_A1;
+  ULONG  ulSM_A2;
+  ULONG  ulSM_A3;
+  ULONG  ulSM_A4;
+  ULONG  ulSM_A5;
+  ULONG  ulSM_A6;
+  ULONG  ulSM_A7;
+  UCHAR  ucSM_A0_sign;
+  UCHAR  ucSM_A1_sign;
+  UCHAR  ucSM_A2_sign;
+  UCHAR  ucSM_A3_sign;
+  UCHAR  ucSM_A4_sign;
+  UCHAR  ucSM_A5_sign;
+  UCHAR  ucSM_A6_sign;
+  UCHAR  ucSM_A7_sign;
+  ULONG  ulMargin_RO_a;
+  ULONG  ulMargin_RO_b;
+  ULONG  ulMargin_RO_c;
+  ULONG  ulMargin_fixed;
+  ULONG  ulMargin_Fmax_mean;
+  ULONG  ulMargin_plat_mean;
+  ULONG  ulMargin_Fmax_sigma;
+  ULONG  ulMargin_plat_sigma;
+  ULONG  ulMargin_DC_sigma;
+  ULONG  ulLoadLineSlop;
+  ULONG  ulaTDClimitPerDPM[8];
+  ULONG  ulaNoCalcVddcPerDPM[8];
+  ULONG  ulAVFS_meanNsigma_Acontant0;
+  ULONG  ulAVFS_meanNsigma_Acontant1;
+  ULONG  ulAVFS_meanNsigma_Acontant2;
+  USHORT usAVFS_meanNsigma_DC_tol_sigma;
+  USHORT usAVFS_meanNsigma_Platform_mean;
+  USHORT usAVFS_meanNsigma_Platform_sigma;
+  ULONG  ulGB_VDROOP_TABLE_CKSOFF_a0;
+  ULONG  ulGB_VDROOP_TABLE_CKSOFF_a1;
+  ULONG  ulGB_VDROOP_TABLE_CKSOFF_a2;
+  ULONG  ulGB_VDROOP_TABLE_CKSON_a0;
+  ULONG  ulGB_VDROOP_TABLE_CKSON_a1;
+  ULONG  ulGB_VDROOP_TABLE_CKSON_a2;
+  ULONG  ulAVFSGB_FUSE_TABLE_CKSOFF_m1;
+  USHORT usAVFSGB_FUSE_TABLE_CKSOFF_m2;
+  ULONG  ulAVFSGB_FUSE_TABLE_CKSOFF_b;
+  ULONG  ulAVFSGB_FUSE_TABLE_CKSON_m1;
+  USHORT usAVFSGB_FUSE_TABLE_CKSON_m2;
+  ULONG  ulAVFSGB_FUSE_TABLE_CKSON_b;
+  USHORT usMaxVoltage_0_25mv;
+  UCHAR  ucEnableGB_VDROOP_TABLE_CKSOFF;
+  UCHAR  ucEnableGB_VDROOP_TABLE_CKSON;
+  UCHAR  ucEnableGB_FUSE_TABLE_CKSOFF;
+  UCHAR  ucEnableGB_FUSE_TABLE_CKSON;
+  USHORT usPSM_Age_ComFactor;
+  UCHAR  ucEnableApplyAVFS_CKS_OFF_Voltage;
+  UCHAR  ucReserved;
+}ATOM_ASIC_PROFILING_INFO_V3_6;
+
+
+typedef struct _ATOM_SCLK_FCW_RANGE_ENTRY_V1{
+  ULONG  ulMaxSclkFreq;
+  UCHAR  ucVco_setting;      // 1: 3-6GHz, 3: 2-4GHz
+  UCHAR  ucPostdiv;          // divide by 2^n
+  USHORT ucFcw_pcc;
+  USHORT ucFcw_trans_upper;
+  USHORT ucRcw_trans_lower;
+}ATOM_SCLK_FCW_RANGE_ENTRY_V1;
+
+
+// SMU_InfoTable for  Polaris10/Polaris11
+typedef struct  _ATOM_SMU_INFO_V2_1
+{
+  ATOM_COMMON_TABLE_HEADER         asHeader;
+  UCHAR ucSclkEntryNum;            // for potential future extend, indicate the number of ATOM_SCLK_FCW_RANGE_ENTRY_V1
+  UCHAR ucReserved[3];
+  ATOM_SCLK_FCW_RANGE_ENTRY_V1     asSclkFcwRangeEntry[8];
+}ATOM_SMU_INFO_V2_1;
+
+
+// GFX_InfoTable for Polaris10/Polaris11
+typedef struct  _ATOM_GFX_INFO_V2_1
+{
+  ATOM_COMMON_TABLE_HEADER asHeader;
+  UCHAR GfxIpMinVer;
+  UCHAR GfxIpMajVer;
+  UCHAR max_shader_engines;
+  UCHAR max_tile_pipes;
+  UCHAR max_cu_per_sh;
+  UCHAR max_sh_per_se;
+  UCHAR max_backends_per_se;
+  UCHAR max_texture_channel_caches;
+}ATOM_GFX_INFO_V2_1;
+
+
 typedef struct _ATOM_POWER_SOURCE_OBJECT
 {
    UCHAR  ucPwrSrcId;                                   // Power source
@@ -5765,14 +6344,6 @@ sExtDispConnInfo:                 Displa
 
 **********************************************************************************************************************/
 
-// this Table is used for Kaveri/Kabini APU
-typedef struct _ATOM_FUSION_SYSTEM_INFO_V2
-{
-  ATOM_INTEGRATED_SYSTEM_INFO_V1_8    sIntegratedSysInfo;       // refer to ATOM_INTEGRATED_SYSTEM_INFO_V1_8 definition
-  ULONG                               ulPowerplayTable[128];    // Update comments here to link new powerplay table definition structure
-}ATOM_FUSION_SYSTEM_INFO_V2;
-
-
 typedef struct _ATOM_I2C_REG_INFO
 {
   UCHAR ucI2cRegIndex;
@@ -5859,7 +6430,50 @@ typedef struct _ATOM_INTEGRATED_SYSTEM_I
 #define EDP_VS_VARIABLE_PREM_MODE           5
 
 
-// this IntegrateSystemInfoTable is used for Carrizo
+// ulGPUCapInfo
+#define SYS_INFO_V1_9_GPUCAPSINFO_DISABLE_AUX_MODE_DETECT                         0x08
+#define SYS_INFO_V1_9_GPUCAPSINFO_ENABEL_DFS_BYPASS                               0x10
+//ulGPUCapInfo[16]=1 indicate SMC firmware is able to support GNB fast resume function, so that driver can call SMC to program most of GNB register during resuming, from ML
+#define SYS_INFO_V1_9_GPUCAPSINFO_GNB_FAST_RESUME_CAPABLE                         0x00010000
+//ulGPUCapInfo[18]=1 indicate the IOMMU is not available
+#define SYS_INFO_V1_9_GPUCAPINFO_IOMMU_DISABLE                                    0x00040000
+//ulGPUCapInfo[19]=1 indicate the MARC Aperture is opened.
+#define SYS_INFO_V1_9_GPUCAPINFO_MARC_APERTURE_ENABLE                             0x00080000
+
+
+typedef struct _DPHY_TIMING_PARA
+{
+    UCHAR  ucProfileID;       // SENSOR_PROFILES
+    ULONG  ucPara;
+} DPHY_TIMING_PARA;
+
+typedef struct _DPHY_ELEC_PARA
+{
+    USHORT  usPara[3];
+} DPHY_ELEC_PARA;
+
+typedef struct _CAMERA_MODULE_INFO
+{
+    UCHAR    ucID;                    // 0: Rear, 1: Front right of user, 2: Front left of user
+    UCHAR    strModuleName[8];
+    DPHY_TIMING_PARA asTimingPara[6]; // Exact number is under estimation and confirmation from sensor vendor
+} CAMERA_MODULE_INFO;
+
+typedef struct _FLASHLIGHT_INFO
+{
+    UCHAR    ucID;         // 0: Rear, 1: Front
+    UCHAR    strName[8];
+} FLASHLIGHT_INFO;
+
+typedef struct _CAMERA_DATA
+{
+    ULONG                   ulVersionCode;
+    CAMERA_MODULE_INFO      asCameraInfo[3];     // Assuming 3 camera sensors max
+    FLASHLIGHT_INFO         asFlashInfo;      // Assuming 1 flashlight max
+    DPHY_ELEC_PARA          asDphyElecPara;
+    ULONG                   ulCrcVal;         // CRC
+}CAMERA_DATA;
+
 typedef struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_10
 {
   ATOM_COMMON_TABLE_HEADER   sHeader;
@@ -5883,7 +6497,7 @@ typedef struct _ATOM_INTEGRATED_SYSTEM_I
   USHORT usPanelRefreshRateRange;
   UCHAR  ucMemoryType;
   UCHAR  ucUMAChannelNumber;
-  UCHAR  strVBIOSMsg[40];
+  ULONG  ulMsgReserved[10];
   ATOM_TDP_CONFIG  asTdpConfig;
   ULONG  ulReserved[7];
   ATOM_CLK_VOLT_CAPABILITY_V2   sDispClkVoltageMapping[8];
@@ -5925,8 +6539,27 @@ typedef struct _ATOM_INTEGRATED_SYSTEM_I
   UCHAR  ucEDPv1_4VSMode;
   UCHAR  ucReserved2;
   ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO sExtDispConnInfo;
+  CAMERA_DATA asCameraInfo;
+  ULONG  ulReserved8[29];
 }ATOM_INTEGRATED_SYSTEM_INFO_V1_10;
 
+
+// this Table is used for Kaveri/Kabini APU
+typedef struct _ATOM_FUSION_SYSTEM_INFO_V2
+{
+  ATOM_INTEGRATED_SYSTEM_INFO_V1_8    sIntegratedSysInfo;       // refer to ATOM_INTEGRATED_SYSTEM_INFO_V1_8 definition
+  ULONG                               ulPowerplayTable[128];    // Update comments here to link new powerplay table definition structure
+}ATOM_FUSION_SYSTEM_INFO_V2;
+
+
+typedef struct _ATOM_FUSION_SYSTEM_INFO_V3
+{
+  ATOM_INTEGRATED_SYSTEM_INFO_V1_10   sIntegratedSysInfo;           // refer to ATOM_INTEGRATED_SYSTEM_INFO_V1_8 definition
+  ULONG                               ulPowerplayTable[192];        // Reserve 768 bytes space for PowerPlayInfoTable
+}ATOM_FUSION_SYSTEM_INFO_V3;
+
+#define FUSION_V3_OFFSET_FROM_TOP_OF_FB 0x800
+
 /**************************************************************************/
 // This portion is only used when ext thermal chip or engine/memory clock SS chip is populated on a design
 //Memory SS Info Table
@@ -6193,12 +6826,12 @@ typedef struct _ATOM_ASIC_INTERNAL_SS_IN
 #define ATOM_S3_DFP1_ACTIVE             0x00000008L
 #define ATOM_S3_CRT2_ACTIVE             0x00000010L
 #define ATOM_S3_LCD2_ACTIVE             0x00000020L
-#define ATOM_S3_DFP6_ACTIVE                     0x00000040L
+#define ATOM_S3_DFP6_ACTIVE             0x00000040L
 #define ATOM_S3_DFP2_ACTIVE             0x00000080L
 #define ATOM_S3_CV_ACTIVE               0x00000100L
-#define ATOM_S3_DFP3_ACTIVE                     0x00000200L
-#define ATOM_S3_DFP4_ACTIVE                     0x00000400L
-#define ATOM_S3_DFP5_ACTIVE                     0x00000800L
+#define ATOM_S3_DFP3_ACTIVE             0x00000200L
+#define ATOM_S3_DFP4_ACTIVE             0x00000400L
+#define ATOM_S3_DFP5_ACTIVE             0x00000800L
 
 
 #define ATOM_S3_DEVICE_ACTIVE_MASK      0x00000FFFL
@@ -6215,9 +6848,9 @@ typedef struct _ATOM_ASIC_INTERNAL_SS_IN
 #define ATOM_S3_DFP6_CRTC_ACTIVE        0x00400000L
 #define ATOM_S3_DFP2_CRTC_ACTIVE        0x00800000L
 #define ATOM_S3_CV_CRTC_ACTIVE          0x01000000L
-#define ATOM_S3_DFP3_CRTC_ACTIVE            0x02000000L
-#define ATOM_S3_DFP4_CRTC_ACTIVE            0x04000000L
-#define ATOM_S3_DFP5_CRTC_ACTIVE            0x08000000L
+#define ATOM_S3_DFP3_CRTC_ACTIVE        0x02000000L
+#define ATOM_S3_DFP4_CRTC_ACTIVE        0x04000000L
+#define ATOM_S3_DFP5_CRTC_ACTIVE        0x08000000L
 
 
 #define ATOM_S3_DEVICE_CRTC_ACTIVE_MASK 0x0FFF0000L
@@ -6238,9 +6871,9 @@ typedef struct _ATOM_ASIC_INTERNAL_SS_IN
 #define ATOM_S3_DFP6_ACTIVEb0           0x40
 #define ATOM_S3_DFP2_ACTIVEb0           0x80
 #define ATOM_S3_CV_ACTIVEb1             0x01
-#define ATOM_S3_DFP3_ACTIVEb1                  0x02
-#define ATOM_S3_DFP4_ACTIVEb1                  0x04
-#define ATOM_S3_DFP5_ACTIVEb1                  0x08
+#define ATOM_S3_DFP3_ACTIVEb1           0x02
+#define ATOM_S3_DFP4_ACTIVEb1           0x04
+#define ATOM_S3_DFP5_ACTIVEb1           0x08
 
 
 #define ATOM_S3_ACTIVE_CRTC1w0          0xFFF
@@ -6254,9 +6887,9 @@ typedef struct _ATOM_ASIC_INTERNAL_SS_IN
 #define ATOM_S3_DFP6_CRTC_ACTIVEb2      0x40
 #define ATOM_S3_DFP2_CRTC_ACTIVEb2      0x80
 #define ATOM_S3_CV_CRTC_ACTIVEb3        0x01
-#define ATOM_S3_DFP3_CRTC_ACTIVEb3         0x02
-#define ATOM_S3_DFP4_CRTC_ACTIVEb3         0x04
-#define ATOM_S3_DFP5_CRTC_ACTIVEb3         0x08
+#define ATOM_S3_DFP3_CRTC_ACTIVEb3      0x02
+#define ATOM_S3_DFP4_CRTC_ACTIVEb3      0x04
+#define ATOM_S3_DFP5_CRTC_ACTIVEb3      0x08
 
 
 #define ATOM_S3_ACTIVE_CRTC2w1          0xFFF
@@ -6878,15 +7511,18 @@ typedef struct _ATOM_MC_INIT_PARAM_TABLE
 #define _32Mx16             0x32
 #define _32Mx32             0x33
 #define _32Mx128            0x35
-#define _64Mx32             0x43
 #define _64Mx8              0x41
 #define _64Mx16             0x42
+#define _64Mx32             0x43
+#define _64Mx128            0x45
 #define _128Mx8             0x51
 #define _128Mx16            0x52
 #define _128Mx32            0x53
 #define _256Mx8             0x61
 #define _256Mx16            0x62
+#define _256Mx32            0x63
 #define _512Mx8             0x71
+#define _512Mx16            0x72
 
 
 #define SAMSUNG             0x1
@@ -7407,6 +8043,17 @@ typedef struct _ATOM_MEMORY_TRAINING_INF
 }ATOM_MEMORY_TRAINING_INFO;
 
 
+typedef struct _ATOM_MEMORY_TRAINING_INFO_V3_1
+{
+   ATOM_COMMON_TABLE_HEADER   sHeader;
+   ULONG                      ulMCUcodeVersion;
+   USHORT                     usMCIOInitLen;         //len of ATOM_REG_INIT_SETTING array
+   USHORT                     usMCUcodeLen;          //len of ATOM_MC_UCODE_DATA array
+   USHORT                     usMCIORegInitOffset;   //point of offset of ATOM_REG_INIT_SETTING array
+   USHORT                     usMCUcodeOffset;       //point of offset of MC uCode ULONG array.
+}ATOM_MEMORY_TRAINING_INFO_V3_1;
+
+
 typedef struct SW_I2C_CNTL_DATA_PARAMETERS
 {
   UCHAR    ucControl;
@@ -7623,7 +8270,7 @@ typedef struct _ASIC_TRANSMITTER_INFO
 {
    USHORT usTransmitterObjId;
    USHORT usSupportDevice;
-  UCHAR  ucTransmitterCmdTblId;
+   UCHAR  ucTransmitterCmdTblId;
    UCHAR  ucConfig;
    UCHAR  ucEncoderID;                //available 1st encoder ( default )
    UCHAR  ucOptionEncoderID;    //available 2nd encoder ( optional )
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/include/cgs_common.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/include/cgs_common.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/include/cgs_common.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/include/cgs_common.h	2016-07-24 15:23:50.000000000 -0400
@@ -26,6 +26,8 @@
 
 #include "amd_shared.h"
 
+struct cgs_device;
+
 /**
  * enum cgs_gpu_mem_type - GPU memory types
  */
@@ -92,6 +94,7 @@ enum cgs_voltage_planes {
  */
 enum cgs_ucode_id {
 	CGS_UCODE_ID_SMU = 0,
+	CGS_UCODE_ID_SMU_SK,
 	CGS_UCODE_ID_SDMA0,
 	CGS_UCODE_ID_SDMA1,
 	CGS_UCODE_ID_CP_CE,
@@ -111,6 +114,7 @@ enum cgs_system_info_id {
 	CGS_SYSTEM_INFO_PCIE_MLW,
 	CGS_SYSTEM_INFO_CG_FLAGS,
 	CGS_SYSTEM_INFO_PG_FLAGS,
+	CGS_SYSTEM_INFO_GFX_CU_INFO,
 	CGS_SYSTEM_INFO_ID_MAXIMUM,
 };
 
@@ -223,7 +227,7 @@ struct cgs_acpi_method_info {
  *
  * Return:  0 on success, -errno otherwise
  */
-typedef int (*cgs_gpu_mem_info_t)(void *cgs_device, enum cgs_gpu_mem_type type,
+typedef int (*cgs_gpu_mem_info_t)(struct cgs_device *cgs_device, enum cgs_gpu_mem_type type,
 				  uint64_t *mc_start, uint64_t *mc_size,
 				  uint64_t *mem_size);
 
@@ -239,7 +243,7 @@ typedef int (*cgs_gpu_mem_info_t)(void *
  *
  * Return:  0 on success, -errno otherwise
  */
-typedef int (*cgs_gmap_kmem_t)(void *cgs_device, void *kmem, uint64_t size,
+typedef int (*cgs_gmap_kmem_t)(struct cgs_device *cgs_device, void *kmem, uint64_t size,
 			       uint64_t min_offset, uint64_t max_offset,
 			       cgs_handle_t *kmem_handle, uint64_t *mcaddr);
 
@@ -250,7 +254,7 @@ typedef int (*cgs_gmap_kmem_t)(void *cgs
  *
  * Return:  0 on success, -errno otherwise
  */
-typedef int (*cgs_gunmap_kmem_t)(void *cgs_device, cgs_handle_t kmem_handle);
+typedef int (*cgs_gunmap_kmem_t)(struct cgs_device *cgs_device, cgs_handle_t kmem_handle);
 
 /**
  * cgs_alloc_gpu_mem() - Allocate GPU memory
@@ -279,7 +283,7 @@ typedef int (*cgs_gunmap_kmem_t)(void *c
  *
  * Return:  0 on success, -errno otherwise
  */
-typedef int (*cgs_alloc_gpu_mem_t)(void *cgs_device, enum cgs_gpu_mem_type type,
+typedef int (*cgs_alloc_gpu_mem_t)(struct cgs_device *cgs_device, enum cgs_gpu_mem_type type,
 				   uint64_t size, uint64_t align,
 				   uint64_t min_offset, uint64_t max_offset,
 				   cgs_handle_t *handle);
@@ -291,7 +295,7 @@ typedef int (*cgs_alloc_gpu_mem_t)(void
  *
  * Return:  0 on success, -errno otherwise
  */
-typedef int (*cgs_free_gpu_mem_t)(void *cgs_device, cgs_handle_t handle);
+typedef int (*cgs_free_gpu_mem_t)(struct cgs_device *cgs_device, cgs_handle_t handle);
 
 /**
  * cgs_gmap_gpu_mem() - GPU-map GPU memory
@@ -303,7 +307,7 @@ typedef int (*cgs_free_gpu_mem_t)(void *
  *
  * Return:  0 on success, -errno otherwise
  */
-typedef int (*cgs_gmap_gpu_mem_t)(void *cgs_device, cgs_handle_t handle,
+typedef int (*cgs_gmap_gpu_mem_t)(struct cgs_device *cgs_device, cgs_handle_t handle,
 				  uint64_t *mcaddr);
 
 /**
@@ -315,7 +319,7 @@ typedef int (*cgs_gmap_gpu_mem_t)(void *
  *
  * Return:  0 on success, -errno otherwise
  */
-typedef int (*cgs_gunmap_gpu_mem_t)(void *cgs_device, cgs_handle_t handle);
+typedef int (*cgs_gunmap_gpu_mem_t)(struct cgs_device *cgs_device, cgs_handle_t handle);
 
 /**
  * cgs_kmap_gpu_mem() - Kernel-map GPU memory
@@ -326,7 +330,7 @@ typedef int (*cgs_gunmap_gpu_mem_t)(void
  *
  * Return:  0 on success, -errno otherwise
  */
-typedef int (*cgs_kmap_gpu_mem_t)(void *cgs_device, cgs_handle_t handle,
+typedef int (*cgs_kmap_gpu_mem_t)(struct cgs_device *cgs_device, cgs_handle_t handle,
 				  void **map);
 
 /**
@@ -336,7 +340,7 @@ typedef int (*cgs_kmap_gpu_mem_t)(void *
  *
  * Return:  0 on success, -errno otherwise
  */
-typedef int (*cgs_kunmap_gpu_mem_t)(void *cgs_device, cgs_handle_t handle);
+typedef int (*cgs_kunmap_gpu_mem_t)(struct cgs_device *cgs_device, cgs_handle_t handle);
 
 /**
  * cgs_read_register() - Read an MMIO register
@@ -345,7 +349,7 @@ typedef int (*cgs_kunmap_gpu_mem_t)(void
  *
  * Return:  register value
  */
-typedef uint32_t (*cgs_read_register_t)(void *cgs_device, unsigned offset);
+typedef uint32_t (*cgs_read_register_t)(struct cgs_device *cgs_device, unsigned offset);
 
 /**
  * cgs_write_register() - Write an MMIO register
@@ -353,7 +357,7 @@ typedef uint32_t (*cgs_read_register_t)(
  * @offset:	register offset
  * @value:	register value
  */
-typedef void (*cgs_write_register_t)(void *cgs_device, unsigned offset,
+typedef void (*cgs_write_register_t)(struct cgs_device *cgs_device, unsigned offset,
 				     uint32_t value);
 
 /**
@@ -363,7 +367,7 @@ typedef void (*cgs_write_register_t)(voi
  *
  * Return:  register value
  */
-typedef uint32_t (*cgs_read_ind_register_t)(void *cgs_device, enum cgs_ind_reg space,
+typedef uint32_t (*cgs_read_ind_register_t)(struct cgs_device *cgs_device, enum cgs_ind_reg space,
 					    unsigned index);
 
 /**
@@ -372,7 +376,7 @@ typedef uint32_t (*cgs_read_ind_register
  * @offset:	register offset
  * @value:	register value
  */
-typedef void (*cgs_write_ind_register_t)(void *cgs_device, enum cgs_ind_reg space,
+typedef void (*cgs_write_ind_register_t)(struct cgs_device *cgs_device, enum cgs_ind_reg space,
 					 unsigned index, uint32_t value);
 
 /**
@@ -382,7 +386,7 @@ typedef void (*cgs_write_ind_register_t)
  *
  * Return:  Value read
  */
-typedef uint8_t (*cgs_read_pci_config_byte_t)(void *cgs_device, unsigned addr);
+typedef uint8_t (*cgs_read_pci_config_byte_t)(struct cgs_device *cgs_device, unsigned addr);
 
 /**
  * cgs_read_pci_config_word() - Read word from PCI configuration space
@@ -391,7 +395,7 @@ typedef uint8_t (*cgs_read_pci_config_by
  *
  * Return:  Value read
  */
-typedef uint16_t (*cgs_read_pci_config_word_t)(void *cgs_device, unsigned addr);
+typedef uint16_t (*cgs_read_pci_config_word_t)(struct cgs_device *cgs_device, unsigned addr);
 
 /**
  * cgs_read_pci_config_dword() - Read dword from PCI configuration space
@@ -400,7 +404,7 @@ typedef uint16_t (*cgs_read_pci_config_w
  *
  * Return:  Value read
  */
-typedef uint32_t (*cgs_read_pci_config_dword_t)(void *cgs_device,
+typedef uint32_t (*cgs_read_pci_config_dword_t)(struct cgs_device *cgs_device,
 						unsigned addr);
 
 /**
@@ -409,7 +413,7 @@ typedef uint32_t (*cgs_read_pci_config_d
  * @addr:	address
  * @value:	value to write
  */
-typedef void (*cgs_write_pci_config_byte_t)(void *cgs_device, unsigned addr,
+typedef void (*cgs_write_pci_config_byte_t)(struct cgs_device *cgs_device, unsigned addr,
 					    uint8_t value);
 
 /**
@@ -418,7 +422,7 @@ typedef void (*cgs_write_pci_config_byte
  * @addr:	address, must be word-aligned
  * @value:	value to write
  */
-typedef void (*cgs_write_pci_config_word_t)(void *cgs_device, unsigned addr,
+typedef void (*cgs_write_pci_config_word_t)(struct cgs_device *cgs_device, unsigned addr,
 					    uint16_t value);
 
 /**
@@ -427,7 +431,7 @@ typedef void (*cgs_write_pci_config_word
  * @addr:	address, must be dword-aligned
  * @value:	value to write
  */
-typedef void (*cgs_write_pci_config_dword_t)(void *cgs_device, unsigned addr,
+typedef void (*cgs_write_pci_config_dword_t)(struct cgs_device *cgs_device, unsigned addr,
 					     uint32_t value);
 
 
@@ -441,7 +445,7 @@ typedef void (*cgs_write_pci_config_dwor
  *
  * Return: 0 on success, -errno otherwise
  */
-typedef int (*cgs_get_pci_resource_t)(void *cgs_device,
+typedef int (*cgs_get_pci_resource_t)(struct cgs_device *cgs_device,
 				      enum cgs_resource_type resource_type,
 				      uint64_t size,
 				      uint64_t offset,
@@ -458,7 +462,7 @@ typedef int (*cgs_get_pci_resource_t)(vo
  * Return: Pointer to start of the table, or NULL on failure
  */
 typedef const void *(*cgs_atom_get_data_table_t)(
-	void *cgs_device, unsigned table,
+	struct cgs_device *cgs_device, unsigned table,
 	uint16_t *size, uint8_t *frev, uint8_t *crev);
 
 /**
@@ -470,7 +474,7 @@ typedef const void *(*cgs_atom_get_data_
  *
  * Return: 0 on success, -errno otherwise
  */
-typedef int (*cgs_atom_get_cmd_table_revs_t)(void *cgs_device, unsigned table,
+typedef int (*cgs_atom_get_cmd_table_revs_t)(struct cgs_device *cgs_device, unsigned table,
 					     uint8_t *frev, uint8_t *crev);
 
 /**
@@ -481,7 +485,7 @@ typedef int (*cgs_atom_get_cmd_table_rev
  *
  * Return: 0 on success, -errno otherwise
  */
-typedef int (*cgs_atom_exec_cmd_table_t)(void *cgs_device,
+typedef int (*cgs_atom_exec_cmd_table_t)(struct cgs_device *cgs_device,
 					 unsigned table, void *args);
 
 /**
@@ -491,7 +495,7 @@ typedef int (*cgs_atom_exec_cmd_table_t)
  *
  * Return:  0 on success, -errno otherwise
  */
-typedef int (*cgs_create_pm_request_t)(void *cgs_device, cgs_handle_t *request);
+typedef int (*cgs_create_pm_request_t)(struct cgs_device *cgs_device, cgs_handle_t *request);
 
 /**
  * cgs_destroy_pm_request() - Destroy a power management request
@@ -500,7 +504,7 @@ typedef int (*cgs_create_pm_request_t)(v
  *
  * Return:  0 on success, -errno otherwise
  */
-typedef int (*cgs_destroy_pm_request_t)(void *cgs_device, cgs_handle_t request);
+typedef int (*cgs_destroy_pm_request_t)(struct cgs_device *cgs_device, cgs_handle_t request);
 
 /**
  * cgs_set_pm_request() - Activate or deactiveate a PM request
@@ -516,7 +520,7 @@ typedef int (*cgs_destroy_pm_request_t)(
  *
  * Return:  0 on success, -errno otherwise
  */
-typedef int (*cgs_set_pm_request_t)(void *cgs_device, cgs_handle_t request,
+typedef int (*cgs_set_pm_request_t)(struct cgs_device *cgs_device, cgs_handle_t request,
 				    int active);
 
 /**
@@ -528,7 +532,7 @@ typedef int (*cgs_set_pm_request_t)(void
  *
  * Return:  0 on success, -errno otherwise
  */
-typedef int (*cgs_pm_request_clock_t)(void *cgs_device, cgs_handle_t request,
+typedef int (*cgs_pm_request_clock_t)(struct cgs_device *cgs_device, cgs_handle_t request,
 				      enum cgs_clock clock, unsigned freq);
 
 /**
@@ -540,7 +544,7 @@ typedef int (*cgs_pm_request_clock_t)(vo
  *
  * Return:  0 on success, -errno otherwise
  */
-typedef int (*cgs_pm_request_engine_t)(void *cgs_device, cgs_handle_t request,
+typedef int (*cgs_pm_request_engine_t)(struct cgs_device *cgs_device, cgs_handle_t request,
 				       enum cgs_engine engine, int powered);
 
 /**
@@ -551,7 +555,7 @@ typedef int (*cgs_pm_request_engine_t)(v
  *
  * Return:  0 on success, -errno otherwise
  */
-typedef int (*cgs_pm_query_clock_limits_t)(void *cgs_device,
+typedef int (*cgs_pm_query_clock_limits_t)(struct cgs_device *cgs_device,
 					   enum cgs_clock clock,
 					   struct cgs_clock_limits *limits);
 
@@ -563,7 +567,7 @@ typedef int (*cgs_pm_query_clock_limits_
  *
  * Return: 0 on success, -errno otherwise
  */
-typedef int (*cgs_set_camera_voltages_t)(void *cgs_device, uint32_t mask,
+typedef int (*cgs_set_camera_voltages_t)(struct cgs_device *cgs_device, uint32_t mask,
 					 const uint32_t *voltages);
 /**
  * cgs_get_firmware_info - Get the firmware information from core driver
@@ -573,25 +577,28 @@ typedef int (*cgs_set_camera_voltages_t)
  *
  * Return: 0 on success, -errno otherwise
  */
-typedef int (*cgs_get_firmware_info)(void *cgs_device,
+typedef int (*cgs_get_firmware_info)(struct cgs_device *cgs_device,
 				     enum cgs_ucode_id type,
 				     struct cgs_firmware_info *info);
 
-typedef int(*cgs_set_powergating_state)(void *cgs_device,
+typedef int (*cgs_rel_firmware)(struct cgs_device *cgs_device,
+					 enum cgs_ucode_id type);
+
+typedef int(*cgs_set_powergating_state)(struct cgs_device *cgs_device,
 				  enum amd_ip_block_type block_type,
 				  enum amd_powergating_state state);
 
-typedef int(*cgs_set_clockgating_state)(void *cgs_device,
+typedef int(*cgs_set_clockgating_state)(struct cgs_device *cgs_device,
 				  enum amd_ip_block_type block_type,
 				  enum amd_clockgating_state state);
 
 typedef int(*cgs_get_active_displays_info)(
-					void *cgs_device,
+					struct cgs_device *cgs_device,
 					struct cgs_display_info *info);
 
-typedef int (*cgs_notify_dpm_enabled)(void *cgs_device, bool enabled);
+typedef int (*cgs_notify_dpm_enabled)(struct cgs_device *cgs_device, bool enabled);
 
-typedef int (*cgs_call_acpi_method)(void *cgs_device,
+typedef int (*cgs_call_acpi_method)(struct cgs_device *cgs_device,
 					uint32_t acpi_method,
 					uint32_t acpi_function,
 					void *pinput, void *poutput,
@@ -599,7 +606,7 @@ typedef int (*cgs_call_acpi_method)(void
 					uint32_t input_size,
 					uint32_t output_size);
 
-typedef int (*cgs_query_system_info)(void *cgs_device,
+typedef int (*cgs_query_system_info)(struct cgs_device *cgs_device,
 				struct cgs_system_info *sys_info);
 
 struct cgs_ops {
@@ -641,6 +648,7 @@ struct cgs_ops {
 	cgs_set_camera_voltages_t set_camera_voltages;
 	/* Firmware Info */
 	cgs_get_firmware_info get_firmware_info;
+	cgs_rel_firmware rel_firmware;
 	/* cg pg interface*/
 	cgs_set_powergating_state set_powergating_state;
 	cgs_set_clockgating_state set_clockgating_state;
@@ -734,6 +742,8 @@ struct cgs_device
 	CGS_CALL(set_camera_voltages,dev,mask,voltages)
 #define cgs_get_firmware_info(dev, type, info)	\
 	CGS_CALL(get_firmware_info, dev, type, info)
+#define cgs_rel_firmware(dev, type)	\
+	CGS_CALL(rel_firmware, dev, type)
 #define cgs_set_powergating_state(dev, block_type, state)	\
 	CGS_CALL(set_powergating_state, dev, block_type, state)
 #define cgs_set_clockgating_state(dev, block_type, state)	\
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/include/cgs_linux.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/include/cgs_linux.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/include/cgs_linux.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/include/cgs_linux.h	2016-07-24 15:23:50.000000000 -0400
@@ -66,7 +66,7 @@ typedef int (*cgs_irq_handler_func_t)(vo
  *
  * Return:  0 on success, -errno otherwise
  */
-typedef int (*cgs_add_irq_source_t)(void *cgs_device, unsigned src_id,
+typedef int (*cgs_add_irq_source_t)(struct cgs_device *cgs_device, unsigned src_id,
 				    unsigned num_types,
 				    cgs_irq_source_set_func_t set,
 				    cgs_irq_handler_func_t handler,
@@ -83,7 +83,7 @@ typedef int (*cgs_add_irq_source_t)(void
  *
  * Return:  0 on success, -errno otherwise
  */
-typedef int (*cgs_irq_get_t)(void *cgs_device, unsigned src_id, unsigned type);
+typedef int (*cgs_irq_get_t)(struct cgs_device *cgs_device, unsigned src_id, unsigned type);
 
 /**
  * cgs_irq_put() - Indicate IRQ source is no longer needed
@@ -98,7 +98,7 @@ typedef int (*cgs_irq_get_t)(void *cgs_d
  *
  * Return:  0 on success, -errno otherwise
  */
-typedef int (*cgs_irq_put_t)(void *cgs_device, unsigned src_id, unsigned type);
+typedef int (*cgs_irq_put_t)(struct cgs_device *cgs_device, unsigned src_id, unsigned type);
 
 struct cgs_os_ops {
 	/* IRQ handling */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/amd_powerplay.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/amd_powerplay.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/amd_powerplay.c	2016-07-24 15:23:50.000000000 -0400
@@ -37,6 +37,12 @@
 			return -EINVAL;					\
 	} while (0)
 
+#define PP_CHECK_HW(hwmgr)						\
+	do {								\
+		if ((hwmgr) == NULL || (hwmgr)->hwmgr_func == NULL)	\
+			return -EINVAL;					\
+	} while (0)
+
 static int pp_early_init(void *handle)
 {
 	return 0;
@@ -54,22 +60,29 @@ static int pp_sw_init(void *handle)
 	pp_handle = (struct pp_instance *)handle;
 	hwmgr = pp_handle->hwmgr;
 
-	if (hwmgr == NULL || hwmgr->pptable_func == NULL ||
-	    hwmgr->hwmgr_func == NULL ||
+	PP_CHECK_HW(hwmgr);
+
+	if (hwmgr->pptable_func == NULL ||
 	    hwmgr->pptable_func->pptable_init == NULL ||
 	    hwmgr->hwmgr_func->backend_init == NULL)
 		return -EINVAL;
 
 	ret = hwmgr->pptable_func->pptable_init(hwmgr);
+	if (ret)
+		goto err;
 
-	if (ret == 0)
-		ret = hwmgr->hwmgr_func->backend_init(hwmgr);
-
+	ret = hwmgr->hwmgr_func->backend_init(hwmgr);
 	if (ret)
-		printk("amdgpu: powerplay initialization failed\n");
-	else
-		printk("amdgpu: powerplay initialized\n");
+		goto err1;
+
+	pr_info("amdgpu: powerplay initialized\n");
 
+	return 0;
+err1:
+	if (hwmgr->pptable_func->pptable_fini)
+		hwmgr->pptable_func->pptable_fini(hwmgr);
+err:
+	pr_err("amdgpu: powerplay initialization failed\n");
 	return ret;
 }
 
@@ -85,10 +98,14 @@ static int pp_sw_fini(void *handle)
 	pp_handle = (struct pp_instance *)handle;
 	hwmgr = pp_handle->hwmgr;
 
-	if (hwmgr != NULL || hwmgr->hwmgr_func != NULL ||
-	    hwmgr->hwmgr_func->backend_fini != NULL)
+	PP_CHECK_HW(hwmgr);
+
+	if (hwmgr->hwmgr_func->backend_fini != NULL)
 		ret = hwmgr->hwmgr_func->backend_fini(hwmgr);
 
+	if (hwmgr->pptable_func->pptable_fini)
+		hwmgr->pptable_func->pptable_fini(hwmgr);
+
 	return ret;
 }
 
@@ -172,21 +189,117 @@ static int pp_sw_reset(void *handle)
 	return 0;
 }
 
-static void pp_print_status(void *handle)
-{
-
-}
 
 static int pp_set_clockgating_state(void *handle,
 				    enum amd_clockgating_state state)
 {
+	struct pp_hwmgr  *hwmgr;
+	uint32_t msg_id, pp_state;
+
+	if (handle == NULL)
+		return -EINVAL;
+
+	hwmgr = ((struct pp_instance *)handle)->hwmgr;
+
+	PP_CHECK_HW(hwmgr);
+
+	if (hwmgr->hwmgr_func->update_clock_gatings == NULL) {
+		printk(KERN_INFO "%s was not implemented.\n", __func__);
+		return 0;
+	}
+
+	if (state == AMD_CG_STATE_UNGATE)
+		pp_state = 0;
+	else
+		pp_state = PP_STATE_CG | PP_STATE_LS;
+
+	/* Enable/disable GFX blocks clock gating through SMU */
+	msg_id = PP_CG_MSG_ID(PP_GROUP_GFX,
+			PP_BLOCK_GFX_CG,
+			PP_STATE_SUPPORT_CG | PP_STATE_SUPPORT_LS,
+			pp_state);
+	hwmgr->hwmgr_func->update_clock_gatings(hwmgr, &msg_id);
+	msg_id = PP_CG_MSG_ID(PP_GROUP_GFX,
+			PP_BLOCK_GFX_3D,
+			PP_STATE_SUPPORT_CG | PP_STATE_SUPPORT_LS,
+			pp_state);
+	hwmgr->hwmgr_func->update_clock_gatings(hwmgr, &msg_id);
+	msg_id = PP_CG_MSG_ID(PP_GROUP_GFX,
+			PP_BLOCK_GFX_RLC,
+			PP_STATE_SUPPORT_CG | PP_STATE_SUPPORT_LS,
+			pp_state);
+	hwmgr->hwmgr_func->update_clock_gatings(hwmgr, &msg_id);
+	msg_id = PP_CG_MSG_ID(PP_GROUP_GFX,
+			PP_BLOCK_GFX_CP,
+			PP_STATE_SUPPORT_CG | PP_STATE_SUPPORT_LS,
+			pp_state);
+	hwmgr->hwmgr_func->update_clock_gatings(hwmgr, &msg_id);
+	msg_id = PP_CG_MSG_ID(PP_GROUP_GFX,
+			PP_BLOCK_GFX_MG,
+			PP_STATE_SUPPORT_CG | PP_STATE_SUPPORT_LS,
+			pp_state);
+	hwmgr->hwmgr_func->update_clock_gatings(hwmgr, &msg_id);
+
+	/* Enable/disable System blocks clock gating through SMU */
+	msg_id = PP_CG_MSG_ID(PP_GROUP_SYS,
+			PP_BLOCK_SYS_BIF,
+			PP_STATE_SUPPORT_CG | PP_STATE_SUPPORT_LS,
+			pp_state);
+	hwmgr->hwmgr_func->update_clock_gatings(hwmgr, &msg_id);
+	msg_id = PP_CG_MSG_ID(PP_GROUP_SYS,
+			PP_BLOCK_SYS_BIF,
+			PP_STATE_SUPPORT_CG | PP_STATE_SUPPORT_LS,
+			pp_state);
+	hwmgr->hwmgr_func->update_clock_gatings(hwmgr, &msg_id);
+	msg_id = PP_CG_MSG_ID(PP_GROUP_SYS,
+			PP_BLOCK_SYS_MC,
+			PP_STATE_SUPPORT_CG | PP_STATE_SUPPORT_LS,
+			pp_state);
+	hwmgr->hwmgr_func->update_clock_gatings(hwmgr, &msg_id);
+	msg_id = PP_CG_MSG_ID(PP_GROUP_SYS,
+			PP_BLOCK_SYS_ROM,
+			PP_STATE_SUPPORT_CG | PP_STATE_SUPPORT_LS,
+			pp_state);
+	hwmgr->hwmgr_func->update_clock_gatings(hwmgr, &msg_id);
+	msg_id = PP_CG_MSG_ID(PP_GROUP_SYS,
+			PP_BLOCK_SYS_DRM,
+			PP_STATE_SUPPORT_CG | PP_STATE_SUPPORT_LS,
+			pp_state);
+	hwmgr->hwmgr_func->update_clock_gatings(hwmgr, &msg_id);
+	msg_id = PP_CG_MSG_ID(PP_GROUP_SYS,
+			PP_BLOCK_SYS_HDP,
+			PP_STATE_SUPPORT_CG | PP_STATE_SUPPORT_LS,
+			pp_state);
+	hwmgr->hwmgr_func->update_clock_gatings(hwmgr, &msg_id);
+	msg_id = PP_CG_MSG_ID(PP_GROUP_SYS,
+			PP_BLOCK_SYS_SDMA,
+			PP_STATE_SUPPORT_CG | PP_STATE_SUPPORT_LS,
+			pp_state);
+	hwmgr->hwmgr_func->update_clock_gatings(hwmgr, &msg_id);
+
 	return 0;
 }
 
 static int pp_set_powergating_state(void *handle,
 				    enum amd_powergating_state state)
 {
-	return 0;
+	struct pp_hwmgr  *hwmgr;
+
+	if (handle == NULL)
+		return -EINVAL;
+
+	hwmgr = ((struct pp_instance *)handle)->hwmgr;
+
+	PP_CHECK_HW(hwmgr);
+
+	if (hwmgr->hwmgr_func->enable_per_cu_power_gating == NULL) {
+		printk(KERN_INFO "%s was not implemented.\n", __func__);
+		return 0;
+	}
+
+	/* Enable/disable GFX per cu powergating through SMU */
+	return hwmgr->hwmgr_func->enable_per_cu_power_gating(hwmgr,
+			state == AMD_PG_STATE_GATE ? true : false);
 }
 
 static int pp_suspend(void *handle)
@@ -236,6 +349,7 @@ static int pp_resume(void *handle)
 }
 
 const struct amd_ip_funcs pp_ip_funcs = {
+	.name = "powerplay",
 	.early_init = pp_early_init,
 	.late_init = NULL,
 	.sw_init = pp_sw_init,
@@ -247,7 +361,6 @@ const struct amd_ip_funcs pp_ip_funcs =
 	.is_idle = pp_is_idle,
 	.wait_for_idle = pp_wait_for_idle,
 	.soft_reset = pp_sw_reset,
-	.print_status = pp_print_status,
 	.set_clockgating_state = pp_set_clockgating_state,
 	.set_powergating_state = pp_set_powergating_state,
 };
@@ -275,9 +388,12 @@ static int pp_dpm_force_performance_leve
 
 	hwmgr = pp_handle->hwmgr;
 
-	if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
-	    hwmgr->hwmgr_func->force_dpm_level == NULL)
-		return -EINVAL;
+	PP_CHECK_HW(hwmgr);
+
+	if (hwmgr->hwmgr_func->force_dpm_level == NULL) {
+		printk(KERN_INFO "%s was not implemented.\n", __func__);
+		return 0;
+	}
 
 	hwmgr->hwmgr_func->force_dpm_level(hwmgr, level);
 
@@ -309,9 +425,12 @@ static int pp_dpm_get_sclk(void *handle,
 
 	hwmgr = ((struct pp_instance *)handle)->hwmgr;
 
-	if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
-	    hwmgr->hwmgr_func->get_sclk == NULL)
-		return -EINVAL;
+	PP_CHECK_HW(hwmgr);
+
+	if (hwmgr->hwmgr_func->get_sclk == NULL) {
+		printk(KERN_INFO "%s was not implemented.\n", __func__);
+		return 0;
+	}
 
 	return hwmgr->hwmgr_func->get_sclk(hwmgr, low);
 }
@@ -325,9 +444,12 @@ static int pp_dpm_get_mclk(void *handle,
 
 	hwmgr = ((struct pp_instance *)handle)->hwmgr;
 
-	if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
-	    hwmgr->hwmgr_func->get_mclk == NULL)
-		return -EINVAL;
+	PP_CHECK_HW(hwmgr);
+
+	if (hwmgr->hwmgr_func->get_mclk == NULL) {
+		printk(KERN_INFO "%s was not implemented.\n", __func__);
+		return 0;
+	}
 
 	return hwmgr->hwmgr_func->get_mclk(hwmgr, low);
 }
@@ -341,9 +463,12 @@ static int pp_dpm_powergate_vce(void *ha
 
 	hwmgr = ((struct pp_instance *)handle)->hwmgr;
 
-	if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
-	    hwmgr->hwmgr_func->powergate_vce == NULL)
-		return -EINVAL;
+	PP_CHECK_HW(hwmgr);
+
+	if (hwmgr->hwmgr_func->powergate_vce == NULL) {
+		printk(KERN_INFO "%s was not implemented.\n", __func__);
+		return 0;
+	}
 
 	return hwmgr->hwmgr_func->powergate_vce(hwmgr, gate);
 }
@@ -357,9 +482,12 @@ static int pp_dpm_powergate_uvd(void *ha
 
 	hwmgr = ((struct pp_instance *)handle)->hwmgr;
 
-	if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
-	    hwmgr->hwmgr_func->powergate_uvd == NULL)
-		return -EINVAL;
+	PP_CHECK_HW(hwmgr);
+
+	if (hwmgr->hwmgr_func->powergate_uvd == NULL) {
+		printk(KERN_INFO "%s was not implemented.\n", __func__);
+		return 0;
+	}
 
 	return hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate);
 }
@@ -455,10 +583,14 @@ pp_debugfs_print_current_performance_lev
 
 	hwmgr = ((struct pp_instance *)handle)->hwmgr;
 
-	if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
-	  hwmgr->hwmgr_func->print_current_perforce_level == NULL)
+	if (hwmgr == NULL || hwmgr->hwmgr_func == NULL)
 		return;
 
+	if (hwmgr->hwmgr_func->print_current_perforce_level == NULL) {
+		printk(KERN_INFO "%s was not implemented.\n", __func__);
+		return;
+	}
+
 	hwmgr->hwmgr_func->print_current_perforce_level(hwmgr, m);
 }
 
@@ -471,9 +603,12 @@ static int pp_dpm_set_fan_control_mode(v
 
 	hwmgr = ((struct pp_instance *)handle)->hwmgr;
 
-	if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
-	  hwmgr->hwmgr_func->set_fan_control_mode == NULL)
-		return -EINVAL;
+	PP_CHECK_HW(hwmgr);
+
+	if (hwmgr->hwmgr_func->set_fan_control_mode == NULL) {
+		printk(KERN_INFO "%s was not implemented.\n", __func__);
+		return 0;
+	}
 
 	return hwmgr->hwmgr_func->set_fan_control_mode(hwmgr, mode);
 }
@@ -487,9 +622,12 @@ static int pp_dpm_get_fan_control_mode(v
 
 	hwmgr = ((struct pp_instance *)handle)->hwmgr;
 
-	if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
-	  hwmgr->hwmgr_func->get_fan_control_mode == NULL)
-		return -EINVAL;
+	PP_CHECK_HW(hwmgr);
+
+	if (hwmgr->hwmgr_func->get_fan_control_mode == NULL) {
+		printk(KERN_INFO "%s was not implemented.\n", __func__);
+		return 0;
+	}
 
 	return hwmgr->hwmgr_func->get_fan_control_mode(hwmgr);
 }
@@ -503,9 +641,12 @@ static int pp_dpm_set_fan_speed_percent(
 
 	hwmgr = ((struct pp_instance *)handle)->hwmgr;
 
-	if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
-	  hwmgr->hwmgr_func->set_fan_speed_percent == NULL)
-		return -EINVAL;
+	PP_CHECK_HW(hwmgr);
+
+	if (hwmgr->hwmgr_func->set_fan_speed_percent == NULL) {
+		printk(KERN_INFO "%s was not implemented.\n", __func__);
+		return 0;
+	}
 
 	return hwmgr->hwmgr_func->set_fan_speed_percent(hwmgr, percent);
 }
@@ -519,9 +660,12 @@ static int pp_dpm_get_fan_speed_percent(
 
 	hwmgr = ((struct pp_instance *)handle)->hwmgr;
 
-	if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
-	  hwmgr->hwmgr_func->get_fan_speed_percent == NULL)
-		return -EINVAL;
+	PP_CHECK_HW(hwmgr);
+
+	if (hwmgr->hwmgr_func->get_fan_speed_percent == NULL) {
+		printk(KERN_INFO "%s was not implemented.\n", __func__);
+		return 0;
+	}
 
 	return hwmgr->hwmgr_func->get_fan_speed_percent(hwmgr, speed);
 }
@@ -535,9 +679,12 @@ static int pp_dpm_get_temperature(void *
 
 	hwmgr = ((struct pp_instance *)handle)->hwmgr;
 
-	if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
-	  hwmgr->hwmgr_func->get_temperature == NULL)
-		return -EINVAL;
+	PP_CHECK_HW(hwmgr);
+
+	if (hwmgr->hwmgr_func->get_temperature == NULL) {
+		printk(KERN_INFO "%s was not implemented.\n", __func__);
+		return 0;
+	}
 
 	return hwmgr->hwmgr_func->get_temperature(hwmgr);
 }
@@ -591,9 +738,12 @@ static int pp_dpm_get_pp_table(void *han
 
 	hwmgr = ((struct pp_instance *)handle)->hwmgr;
 
-	if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
-		hwmgr->hwmgr_func->get_pp_table == NULL)
-		return -EINVAL;
+	PP_CHECK_HW(hwmgr);
+
+	if (hwmgr->hwmgr_func->get_pp_table == NULL) {
+		printk(KERN_INFO "%s was not implemented.\n", __func__);
+		return 0;
+	}
 
 	return hwmgr->hwmgr_func->get_pp_table(hwmgr, table);
 }
@@ -607,15 +757,18 @@ static int pp_dpm_set_pp_table(void *han
 
 	hwmgr = ((struct pp_instance *)handle)->hwmgr;
 
-	if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
-		hwmgr->hwmgr_func->set_pp_table == NULL)
-		return -EINVAL;
+	PP_CHECK_HW(hwmgr);
+
+	if (hwmgr->hwmgr_func->set_pp_table == NULL) {
+		printk(KERN_INFO "%s was not implemented.\n", __func__);
+		return 0;
+	}
 
 	return hwmgr->hwmgr_func->set_pp_table(hwmgr, buf, size);
 }
 
 static int pp_dpm_force_clock_level(void *handle,
-		enum pp_clock_type type, int level)
+		enum pp_clock_type type, uint32_t mask)
 {
 	struct pp_hwmgr *hwmgr;
 
@@ -624,11 +777,14 @@ static int pp_dpm_force_clock_level(void
 
 	hwmgr = ((struct pp_instance *)handle)->hwmgr;
 
-	if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
-			hwmgr->hwmgr_func->force_clock_level == NULL)
-		return -EINVAL;
+	PP_CHECK_HW(hwmgr);
 
-	return hwmgr->hwmgr_func->force_clock_level(hwmgr, type, level);
+	if (hwmgr->hwmgr_func->force_clock_level == NULL) {
+		printk(KERN_INFO "%s was not implemented.\n", __func__);
+		return 0;
+	}
+
+	return hwmgr->hwmgr_func->force_clock_level(hwmgr, type, mask);
 }
 
 static int pp_dpm_print_clock_levels(void *handle,
@@ -641,10 +797,12 @@ static int pp_dpm_print_clock_levels(voi
 
 	hwmgr = ((struct pp_instance *)handle)->hwmgr;
 
-	if (hwmgr == NULL || hwmgr->hwmgr_func == NULL ||
-			hwmgr->hwmgr_func->print_clock_levels == NULL)
-		return -EINVAL;
+	PP_CHECK_HW(hwmgr);
 
+	if (hwmgr->hwmgr_func->print_clock_levels == NULL) {
+		printk(KERN_INFO "%s was not implemented.\n", __func__);
+		return 0;
+	}
 	return hwmgr->hwmgr_func->print_clock_levels(hwmgr, type, buf);
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/eventmgr/eventactionchains.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/eventmgr/eventactionchains.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/eventmgr/eventactionchains.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/eventmgr/eventactionchains.c	2016-07-24 15:23:50.000000000 -0400
@@ -24,7 +24,7 @@
 #include "eventactionchains.h"
 #include "eventsubchains.h"
 
-static const pem_event_action *initialize_event[] = {
+static const pem_event_action * const initialize_event[] = {
 	block_adjust_power_state_tasks,
 	power_budget_tasks,
 	system_config_tasks,
@@ -45,7 +45,7 @@ const struct action_chain initialize_act
 	initialize_event
 };
 
-static const pem_event_action *uninitialize_event[] = {
+static const pem_event_action * const uninitialize_event[] = {
 	ungate_all_display_phys_tasks,
 	uninitialize_display_phy_access_tasks,
 	disable_gfx_voltage_island_power_gating_tasks,
@@ -64,7 +64,7 @@ const struct action_chain uninitialize_a
 	uninitialize_event
 };
 
-static const pem_event_action *power_source_change_event_pp_enabled[] = {
+static const pem_event_action * const power_source_change_event_pp_enabled[] = {
 	set_power_source_tasks,
 	set_power_saving_state_tasks,
 	adjust_power_state_tasks,
@@ -79,7 +79,7 @@ const struct action_chain power_source_c
 	power_source_change_event_pp_enabled
 };
 
-static const pem_event_action *power_source_change_event_pp_disabled[] = {
+static const pem_event_action * const power_source_change_event_pp_disabled[] = {
 	set_power_source_tasks,
 	set_nbmcu_state_tasks,
 	NULL
@@ -90,7 +90,7 @@ const struct action_chain power_source_c
 	power_source_change_event_pp_disabled
 };
 
-static const pem_event_action *power_source_change_event_hardware_dc[] = {
+static const pem_event_action * const power_source_change_event_hardware_dc[] = {
 	set_power_source_tasks,
 	set_power_saving_state_tasks,
 	adjust_power_state_tasks,
@@ -106,7 +106,7 @@ const struct action_chain power_source_c
 	power_source_change_event_hardware_dc
 };
 
-static const pem_event_action *suspend_event[] = {
+static const pem_event_action * const suspend_event[] = {
 	reset_display_phy_access_tasks,
 	unregister_interrupt_tasks,
 	disable_gfx_voltage_island_power_gating_tasks,
@@ -130,7 +130,7 @@ const struct action_chain suspend_action
 	suspend_event
 };
 
-static const pem_event_action *resume_event[] = {
+static const pem_event_action * const resume_event[] = {
 	unblock_hw_access_tasks,
 	resume_connected_standby_tasks,
 	notify_smu_resume_tasks,
@@ -164,7 +164,7 @@ const struct action_chain resume_action_
 	resume_event
 };
 
-static const pem_event_action *complete_init_event[] = {
+static const pem_event_action * const complete_init_event[] = {
 	unblock_adjust_power_state_tasks,
 	adjust_power_state_tasks,
 	enable_gfx_clock_gating_tasks,
@@ -178,7 +178,7 @@ const struct action_chain complete_init_
 	complete_init_event
 };
 
-static const pem_event_action *enable_gfx_clock_gating_event[] = {
+static const pem_event_action * const enable_gfx_clock_gating_event[] = {
 	enable_gfx_clock_gating_tasks,
 	NULL
 };
@@ -188,7 +188,7 @@ const struct action_chain enable_gfx_clo
 	enable_gfx_clock_gating_event
 };
 
-static const pem_event_action *disable_gfx_clock_gating_event[] = {
+static const pem_event_action * const disable_gfx_clock_gating_event[] = {
 	disable_gfx_clock_gating_tasks,
 	NULL
 };
@@ -198,7 +198,7 @@ const struct action_chain disable_gfx_cl
 	disable_gfx_clock_gating_event
 };
 
-static const pem_event_action *enable_cgpg_event[] = {
+static const pem_event_action * const enable_cgpg_event[] = {
 	enable_cgpg_tasks,
 	NULL
 };
@@ -208,7 +208,7 @@ const struct action_chain enable_cgpg_ac
 	enable_cgpg_event
 };
 
-static const pem_event_action *disable_cgpg_event[] = {
+static const pem_event_action * const disable_cgpg_event[] = {
 	disable_cgpg_tasks,
 	NULL
 };
@@ -221,7 +221,7 @@ const struct action_chain disable_cgpg_a
 
 /* Enable user _2d performance and activate */
 
-static const pem_event_action *enable_user_state_event[] = {
+static const pem_event_action * const enable_user_state_event[] = {
 	create_new_user_performance_state_tasks,
 	adjust_power_state_tasks,
 	NULL
@@ -232,7 +232,7 @@ const struct action_chain enable_user_st
 	enable_user_state_event
 };
 
-static const pem_event_action *enable_user_2d_performance_event[] = {
+static const pem_event_action * const enable_user_2d_performance_event[] = {
 	enable_user_2d_performance_tasks,
 	add_user_2d_performance_state_tasks,
 	set_performance_state_tasks,
@@ -247,7 +247,7 @@ const struct action_chain enable_user_2d
 };
 
 
-static const pem_event_action *disable_user_2d_performance_event[] = {
+static const pem_event_action * const disable_user_2d_performance_event[] = {
 	disable_user_2d_performance_tasks,
 	delete_user_2d_performance_state_tasks,
 	NULL
@@ -259,7 +259,7 @@ const struct action_chain disable_user_2
 };
 
 
-static const pem_event_action *display_config_change_event[] = {
+static const pem_event_action * const display_config_change_event[] = {
 	/* countDisplayConfigurationChangeEventTasks, */
 	unblock_adjust_power_state_tasks,
 	set_cpu_power_state,
@@ -278,7 +278,7 @@ const struct action_chain display_config
 	display_config_change_event
 };
 
-static const pem_event_action *readjust_power_state_event[] = {
+static const pem_event_action * const readjust_power_state_event[] = {
 	adjust_power_state_tasks,
 	NULL
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/eventmgr/eventmanagement.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/eventmgr/eventmanagement.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/eventmgr/eventmanagement.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/eventmgr/eventmanagement.c	2016-07-24 15:23:50.000000000 -0400
@@ -62,7 +62,7 @@ int pem_init_event_action_chains(struct
 
 int pem_excute_event_chain(struct pp_eventmgr *eventmgr, const struct action_chain *event_chain, struct pem_event_data *event_data)
 {
-	const pem_event_action **paction_chain;
+	const pem_event_action * const *paction_chain;
 	const pem_event_action *psub_chain;
 	int tmp_result = 0;
 	int result = 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/eventmgr/eventmgr.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/eventmgr/eventmgr.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/eventmgr/eventmgr.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/eventmgr/eventmgr.c	2016-07-24 15:23:50.000000000 -0400
@@ -58,9 +58,6 @@ static void pem_fini(struct pp_eventmgr
 	pem_unregister_interrupts(eventmgr);
 
 	pem_handle_event(eventmgr, AMD_PP_EVENT_UNINITIALIZE, &event_data);
-
-	if (eventmgr != NULL)
-		kfree(eventmgr);
 }
 
 int eventmgr_init(struct pp_instance *handle)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c	2016-07-24 15:23:50.000000000 -0400
@@ -237,7 +237,7 @@ int cz_dpm_powergate_vce(struct pp_hwmgr
 }
 
 
-static struct phm_master_table_item cz_enable_clock_power_gatings_list[] = {
+static const struct phm_master_table_item cz_enable_clock_power_gatings_list[] = {
 	/*we don't need an exit table here, because there is only D3 cold on Kv*/
 	{ phm_cf_want_uvd_power_gating, cz_tf_uvd_power_gating_initialize },
 	{ phm_cf_want_vce_power_gating, cz_tf_vce_power_gating_initialize },
@@ -245,7 +245,7 @@ static struct phm_master_table_item cz_e
 	{ NULL, NULL }
 };
 
-struct phm_master_table_header cz_phm_enable_clock_power_gatings_master = {
+const struct phm_master_table_header cz_phm_enable_clock_power_gatings_master = {
 	0,
 	PHM_MasterTableFlag_None,
 	cz_enable_clock_power_gatings_list
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.h	2016-07-24 15:23:50.000000000 -0400
@@ -28,8 +28,7 @@
 #include "pp_asicblocks.h"
 
 extern int cz_phm_set_asic_block_gating(struct pp_hwmgr *hwmgr, enum PHM_AsicBlock block, enum PHM_ClockGateSetting gating);
-extern struct phm_master_table_header cz_phm_enable_clock_power_gatings_master;
-extern struct phm_master_table_header cz_phm_disable_clock_power_gatings_master;
+extern const struct phm_master_table_header cz_phm_enable_clock_power_gatings_master;
 extern int cz_dpm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate);
 extern int cz_dpm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate);
 extern int cz_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c	2016-07-24 15:23:50.000000000 -0400
@@ -915,7 +915,7 @@ static int cz_tf_update_low_mem_pstate(s
 	return 0;
 }
 
-static struct phm_master_table_item cz_set_power_state_list[] = {
+static const struct phm_master_table_item cz_set_power_state_list[] = {
 	{NULL, cz_tf_update_sclk_limit},
 	{NULL, cz_tf_set_deep_sleep_sclk_threshold},
 	{NULL, cz_tf_set_watermark_threshold},
@@ -925,13 +925,13 @@ static struct phm_master_table_item cz_s
 	{NULL, NULL}
 };
 
-static struct phm_master_table_header cz_set_power_state_master = {
+static const struct phm_master_table_header cz_set_power_state_master = {
 	0,
 	PHM_MasterTableFlag_None,
 	cz_set_power_state_list
 };
 
-static struct phm_master_table_item cz_setup_asic_list[] = {
+static const struct phm_master_table_item cz_setup_asic_list[] = {
 	{NULL, cz_tf_reset_active_process_mask},
 	{NULL, cz_tf_upload_pptable_to_smu},
 	{NULL, cz_tf_init_sclk_limit},
@@ -943,7 +943,7 @@ static struct phm_master_table_item cz_s
 	{NULL, NULL}
 };
 
-static struct phm_master_table_header cz_setup_asic_master = {
+static const struct phm_master_table_header cz_setup_asic_master = {
 	0,
 	PHM_MasterTableFlag_None,
 	cz_setup_asic_list
@@ -984,14 +984,14 @@ static int cz_tf_reset_cc6_data(struct p
 	return 0;
 }
 
-static struct phm_master_table_item cz_power_down_asic_list[] = {
+static const struct phm_master_table_item cz_power_down_asic_list[] = {
 	{NULL, cz_tf_power_up_display_clock_sys_pll},
 	{NULL, cz_tf_clear_nb_dpm_flag},
 	{NULL, cz_tf_reset_cc6_data},
 	{NULL, NULL}
 };
 
-static struct phm_master_table_header cz_power_down_asic_master = {
+static const struct phm_master_table_header cz_power_down_asic_master = {
 	0,
 	PHM_MasterTableFlag_None,
 	cz_power_down_asic_list
@@ -1095,19 +1095,19 @@ static int cz_tf_check_for_dpm_enabled(s
 	return 0;
 }
 
-static struct phm_master_table_item cz_disable_dpm_list[] = {
+static const struct phm_master_table_item cz_disable_dpm_list[] = {
 	{ NULL, cz_tf_check_for_dpm_enabled},
 	{NULL, NULL},
 };
 
 
-static struct phm_master_table_header cz_disable_dpm_master = {
+static const struct phm_master_table_header cz_disable_dpm_master = {
 	0,
 	PHM_MasterTableFlag_None,
 	cz_disable_dpm_list
 };
 
-static struct phm_master_table_item cz_enable_dpm_list[] = {
+static const struct phm_master_table_item cz_enable_dpm_list[] = {
 	{ NULL, cz_tf_check_for_dpm_disabled },
 	{ NULL, cz_tf_program_voting_clients },
 	{ NULL, cz_tf_start_dpm},
@@ -1117,7 +1117,7 @@ static struct phm_master_table_item cz_e
 	{NULL, NULL},
 };
 
-static struct phm_master_table_header cz_enable_dpm_master = {
+static const struct phm_master_table_header cz_enable_dpm_master = {
 	0,
 	PHM_MasterTableFlag_None,
 	cz_enable_dpm_list
@@ -1729,7 +1729,7 @@ static int cz_get_dal_power_level(struct
 }
 
 static int cz_force_clock_level(struct pp_hwmgr *hwmgr,
-		enum pp_clock_type type, int level)
+		enum pp_clock_type type, uint32_t mask)
 {
 	if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL)
 		return -EINVAL;
@@ -1738,10 +1738,10 @@ static int cz_force_clock_level(struct p
 	case PP_SCLK:
 		smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
 				PPSMC_MSG_SetSclkSoftMin,
-				(1 << level));
+				mask);
 		smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
 				PPSMC_MSG_SetSclkSoftMax,
-				(1 << level));
+				mask);
 		break;
 	default:
 		break;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_clockpowergating.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_clockpowergating.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_clockpowergating.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_clockpowergating.c	2016-07-24 15:23:50.000000000 -0400
@@ -47,10 +47,17 @@ int fiji_phm_powergate_uvd(struct pp_hwm
 
 	data->uvd_power_gated = bgate;
 
-	if (bgate)
+	if (bgate) {
+		cgs_set_clockgating_state(hwmgr->device,
+					  AMD_IP_BLOCK_TYPE_UVD,
+					  AMD_CG_STATE_GATE);
 		fiji_update_uvd_dpm(hwmgr, true);
-	else
+	} else {
 		fiji_update_uvd_dpm(hwmgr, false);
+		cgs_set_clockgating_state(hwmgr->device,
+					  AMD_IP_BLOCK_TYPE_UVD,
+					  AMD_PG_STATE_UNGATE);
+	}
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c	2016-07-24 15:23:50.000000000 -0400
@@ -95,23 +95,23 @@ enum DPM_EVENT_SRC {
 /* [2.5%,~2.5%] Clock stretched is multiple of 2.5% vs
  * not and [Fmin, Fmax, LDO_REFSEL, USE_FOR_LOW_FREQ]
  */
-uint16_t fiji_clock_stretcher_lookup_table[2][4] = { {600, 1050, 3, 0},
-                                                {600, 1050, 6, 1} };
+static const uint16_t fiji_clock_stretcher_lookup_table[2][4] =
+{ {600, 1050, 3, 0}, {600, 1050, 6, 1} };
 
 /* [FF, SS] type, [] 4 voltage ranges, and
  * [Floor Freq, Boundary Freq, VID min , VID max]
  */
-uint32_t fiji_clock_stretcher_ddt_table[2][4][4] =
+static const uint32_t fiji_clock_stretcher_ddt_table[2][4][4] =
 { { {265, 529, 120, 128}, {325, 650, 96, 119}, {430, 860, 32, 95}, {0, 0, 0, 31} },
   { {275, 550, 104, 112}, {319, 638, 96, 103}, {360, 720, 64, 95}, {384, 768, 32, 63} } };
 
 /* [Use_For_Low_freq] value, [0%, 5%, 10%, 7.14%, 14.28%, 20%]
  * (coming from PWR_CKS_CNTL.stretch_amount reg spec)
  */
-uint8_t fiji_clock_stretch_amount_conversion[2][6] = { {0, 1, 3, 2, 4, 5},
-                                                  {0, 2, 4, 5, 6, 5} };
+static const uint8_t fiji_clock_stretch_amount_conversion[2][6] =
+{ {0, 1, 3, 2, 4, 5}, {0, 2, 4, 5, 6, 5} };
 
-const unsigned long PhwFiji_Magic = (unsigned long)(PHM_VIslands_Magic);
+static const unsigned long PhwFiji_Magic = (unsigned long)(PHM_VIslands_Magic);
 
 struct fiji_power_state *cast_phw_fiji_power_state(
 				  struct pp_hw_power_state *hw_ps)
@@ -465,14 +465,14 @@ static int fiji_set_private_data_based_o
 			table_info->vdd_dep_on_mclk;
 
 	PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table != NULL,
-		"VDD dependency on SCLK table is missing. 	\
+		"VDD dependency on SCLK table is missing.	\
 		This table is mandatory", return -EINVAL);
 	PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table->count >= 1,
-		"VDD dependency on SCLK table has to have is missing. 	\
+		"VDD dependency on SCLK table has to have is missing.	\
 		This table is mandatory", return -EINVAL);
 
 	PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table != NULL,
-		"VDD dependency on MCLK table is missing. 	\
+		"VDD dependency on MCLK table is missing.	\
 		This table is mandatory", return -EINVAL);
 	PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table->count >= 1,
 		"VDD dependency on MCLK table has to have is missing.	 \
@@ -579,6 +579,18 @@ static int fiji_patch_boot_state(struct
 	return 0;
 }
 
+static int fiji_hwmgr_backend_fini(struct pp_hwmgr *hwmgr)
+{
+	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
+
+	if (data->soft_pp_table) {
+		kfree(data->soft_pp_table);
+		data->soft_pp_table = NULL;
+	}
+
+	return phm_hwmgr_backend_fini(hwmgr);
+}
+
 static int fiji_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
 {
 	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
@@ -621,6 +633,8 @@ static int fiji_hwmgr_backend_init(struc
 	data->vddci_control = FIJI_VOLTAGE_CONTROL_NONE;
 	data->mvdd_control = FIJI_VOLTAGE_CONTROL_NONE;
 
+	data->force_pcie_gen = PP_PCIEGenInvalid;
+
 	if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr,
 			VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2))
 		data->voltage_control = FIJI_VOLTAGE_CONTROL_BY_SVID2;
@@ -734,7 +748,7 @@ static int fiji_hwmgr_backend_init(struc
 			data->pcie_lane_cap = (uint32_t)sys_info.value;
 	} else {
 		/* Ignore return value in here, we are cleaning up a mess. */
-		tonga_hwmgr_backend_fini(hwmgr);
+		fiji_hwmgr_backend_fini(hwmgr);
 	}
 
 	return 0;
@@ -1818,7 +1832,7 @@ static uint16_t fiji_find_closest_vddci(
 
 	PP_ASSERT_WITH_CODE(false,
 			"VDDCI is larger than max VDDCI in VDDCI Voltage Table!",
-			return vddci_table->entries[i].value);
+			return vddci_table->entries[i-1].value);
 }
 
 static int fiji_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr,
@@ -1885,6 +1899,23 @@ static int fiji_get_dependency_volt_by_c
 
 	return 0;
 }
+
+static uint8_t fiji_get_sleep_divider_id_from_clock(uint32_t clock,
+		uint32_t clock_insr)
+{
+	uint8_t i;
+	uint32_t temp;
+	uint32_t min = max(clock_insr, (uint32_t)FIJI_MINIMUM_ENGINE_CLOCK);
+
+	PP_ASSERT_WITH_CODE((clock >= min), "Engine clock can't satisfy stutter requirement!", return 0);
+	for (i = FIJI_MAX_DEEPSLEEP_DIVIDER_ID;  ; i--) {
+		temp = clock >> i;
+
+		if (temp >= min || i == 0)
+			break;
+	}
+	return i;
+}
 /**
 * Populates single SMC SCLK structure using the provided engine clock
 *
@@ -1928,17 +1959,13 @@ static int fiji_populate_single_graphic_
 
 	threshold = clock * data->fast_watermark_threshold / 100;
 
-	/*
-	* TODO: get minimum clocks from dal configaration
-	* PECI_GetMinClockSettings(hwmgr->pPECI, &minClocks);
-	*/
-	/* data->DisplayTiming.minClockInSR = minClocks.engineClockInSR; */
 
-	/* get level->DeepSleepDivId
-	if (phm_cap_enabled(hwmgr->platformDescriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep))
-	{
-	level->DeepSleepDivId = PhwFiji_GetSleepDividerIdFromClock(hwmgr, clock, minClocks.engineClockInSR);
-	} */
+	data->display_timing.min_clock_in_sr = hwmgr->display_config.min_core_set_clock_in_sr;
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep))
+		level->DeepSleepDivId = fiji_get_sleep_divider_id_from_clock(clock,
+								hwmgr->display_config.min_core_set_clock_in_sr);
+
 
 	/* Default to slow, highest DPM level will be
 	 * set to PPSMC_DISPLAY_WATERMARK_LOW later.
@@ -3364,7 +3391,7 @@ static void fiji_set_dpm_event_sources(s
 				DPM_EVENT_SRC, src);
 		PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT,
 				THERMAL_PROTECTION_DIS,
-				phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+				!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
 						PHM_PlatformCaps_ThermalController));
 	} else
 		PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT,
@@ -3548,46 +3575,11 @@ static int fiji_force_dpm_highest(struct
 	return 0;
 }
 
-static void fiji_apply_dal_min_voltage_request(struct pp_hwmgr *hwmgr)
-{
-	struct phm_ppt_v1_information *table_info =
-			(struct phm_ppt_v1_information *)hwmgr->pptable;
-	struct phm_clock_voltage_dependency_table *table =
-				table_info->vddc_dep_on_dal_pwrl;
-	struct phm_ppt_v1_clock_voltage_dependency_table *vddc_table;
-	enum PP_DAL_POWERLEVEL dal_power_level = hwmgr->dal_power_level;
-	uint32_t req_vddc = 0, req_volt, i;
-
-	if (!table && !(dal_power_level >= PP_DAL_POWERLEVEL_ULTRALOW &&
-			dal_power_level <= PP_DAL_POWERLEVEL_PERFORMANCE))
-		return;
-
-	for (i= 0; i < table->count; i++) {
-		if (dal_power_level == table->entries[i].clk) {
-			req_vddc = table->entries[i].v;
-			break;
-		}
-	}
-
-	vddc_table = table_info->vdd_dep_on_sclk;
-	for (i= 0; i < vddc_table->count; i++) {
-		if (req_vddc <= vddc_table->entries[i].vddc) {
-			req_volt = (((uint32_t)vddc_table->entries[i].vddc) * VOLTAGE_SCALE)
-					<< VDDC_SHIFT;
-			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
-					PPSMC_MSG_VddC_Request, req_volt);
-			return;
-		}
-	}
-	printk(KERN_ERR "DAL requested level can not"
-			" found a available voltage in VDDC DPM Table \n");
-}
-
 static int fiji_upload_dpmlevel_enable_mask(struct pp_hwmgr *hwmgr)
 {
 	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
 
-	fiji_apply_dal_min_voltage_request(hwmgr);
+	phm_apply_dal_min_voltage_request(hwmgr);
 
 	if (!data->sclk_dpm_key_disabled) {
 		if (data->dpm_level_enable_mask.sclk_dpm_enable_mask)
@@ -4066,7 +4058,6 @@ static int fiji_find_dpm_states_clocks_i
 	struct fiji_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table);
 	uint32_t mclk = fiji_ps->performance_levels
 			[fiji_ps->performance_level_count - 1].memory_clock;
-	struct PP_Clocks min_clocks = {0};
 	uint32_t i;
 	struct cgs_display_info info = {0};
 
@@ -4080,10 +4071,8 @@ static int fiji_find_dpm_states_clocks_i
 	if (i >= sclk_table->count)
 		data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_SCLK;
 	else {
-	/* TODO: Check SCLK in DAL's minimum clocks
-	 * in case DeepSleep divider update is required.
-	 */
-		if(data->display_timing.min_clock_in_sr != min_clocks.engineClockInSR)
+		if(data->display_timing.min_clock_in_sr !=
+			hwmgr->display_config.min_core_set_clock_in_sr)
 			data->need_update_smu7_dpm_table |= DPMTABLE_UPDATE_SCLK;
 	}
 
@@ -4327,7 +4316,7 @@ static int fiji_populate_and_upload_sclk
 
 	if (data->need_update_smu7_dpm_table &
 			(DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK)) {
-		result = fiji_populate_all_memory_levels(hwmgr);
+		result = fiji_populate_all_graphic_levels(hwmgr);
 		PP_ASSERT_WITH_CODE((0 == result),
 				"Failed to populate SCLK during PopulateNewDPMClocksStates Function!",
 				return result);
@@ -5086,24 +5075,40 @@ static int fiji_get_pp_table(struct pp_h
 {
 	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
 
-	*table = (char *)&data->smc_state_table;
+	if (!data->soft_pp_table) {
+		data->soft_pp_table = kmemdup(hwmgr->soft_pp_table,
+					      hwmgr->soft_pp_table_size,
+					      GFP_KERNEL);
+		if (!data->soft_pp_table)
+			return -ENOMEM;
+	}
 
-	return sizeof(struct SMU73_Discrete_DpmTable);
+	*table = (char *)&data->soft_pp_table;
+
+	return hwmgr->soft_pp_table_size;
 }
 
 static int fiji_set_pp_table(struct pp_hwmgr *hwmgr, const char *buf, size_t size)
 {
 	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
 
-	void *table = (void *)&data->smc_state_table;
+	if (!data->soft_pp_table) {
+		data->soft_pp_table = kzalloc(hwmgr->soft_pp_table_size, GFP_KERNEL);
+		if (!data->soft_pp_table)
+			return -ENOMEM;
+	}
 
-	memcpy(table, buf, size);
+	memcpy(data->soft_pp_table, buf, size);
+
+	hwmgr->soft_pp_table = data->soft_pp_table;
+
+	/* TODO: re-init powerplay to implement modified pptable */
 
 	return 0;
 }
 
 static int fiji_force_clock_level(struct pp_hwmgr *hwmgr,
-		enum pp_clock_type type, int level)
+		enum pp_clock_type type, uint32_t mask)
 {
 	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
 
@@ -5115,20 +5120,30 @@ static int fiji_force_clock_level(struct
 		if (!data->sclk_dpm_key_disabled)
 			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
 					PPSMC_MSG_SCLKDPM_SetEnabledMask,
-					(1 << level));
+					data->dpm_level_enable_mask.sclk_dpm_enable_mask & mask);
 		break;
+
 	case PP_MCLK:
 		if (!data->mclk_dpm_key_disabled)
 			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
 					PPSMC_MSG_MCLKDPM_SetEnabledMask,
-					(1 << level));
+					data->dpm_level_enable_mask.mclk_dpm_enable_mask & mask);
 		break;
+
 	case PP_PCIE:
+	{
+		uint32_t tmp = mask & data->dpm_level_enable_mask.pcie_dpm_enable_mask;
+		uint32_t level = 0;
+
+		while (tmp >>= 1)
+			level++;
+
 		if (!data->pcie_dpm_key_disabled)
 			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
 					PPSMC_MSG_PCIeDPM_ForceLevel,
-					(1 << level));
+					level);
 		break;
+	}
 	default:
 		break;
 	}
@@ -5252,19 +5267,19 @@ bool fiji_check_smc_update_required_for_
 
 	if (data->display_timing.num_existing_displays != info.display_count)
 		is_update_required = true;
-/* TO DO NEED TO GET DEEP SLEEP CLOCK FROM DAL
-	if (phm_cap_enabled(hwmgr->hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) {
-		cgs_get_min_clock_settings(hwmgr->device, &min_clocks);
-		if(min_clocks.engineClockInSR != data->display_timing.minClockInSR)
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) {
+		if(hwmgr->display_config.min_core_set_clock_in_sr != data->display_timing.min_clock_in_sr)
 			is_update_required = true;
-*/
+	}
+
 	return is_update_required;
 }
 
 
 static const struct pp_hwmgr_func fiji_hwmgr_funcs = {
 	.backend_init = &fiji_hwmgr_backend_init,
-	.backend_fini = &tonga_hwmgr_backend_fini,
+	.backend_fini = &fiji_hwmgr_backend_fini,
 	.asic_setup = &fiji_setup_asic_task,
 	.dynamic_state_management_enable = &fiji_enable_dpm_tasks,
 	.force_dpm_level = &fiji_dpm_force_dpm_level,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.h	2016-07-24 15:23:50.000000000 -0400
@@ -263,7 +263,7 @@ struct fiji_hwmgr {
 	bool                           enable_tdc_limit_feature;
 	bool                           enable_pkg_pwr_tracking_feature;
 	bool                           disable_uvd_power_tune_feature;
-	struct fiji_pt_defaults       *power_tune_defaults;
+	const struct fiji_pt_defaults  *power_tune_defaults;
 	struct SMU73_Discrete_PmFuses  power_tune_table;
 	uint32_t                       dte_tj_offset;
 	uint32_t                       fast_watermark_threshold;
@@ -302,6 +302,9 @@ struct fiji_hwmgr {
 	bool                           pg_acp_init;
 	bool                           frtc_enabled;
 	bool                           frtc_status_changed;
+
+	/* soft pptable for re-uploading into smu */
+	void *soft_pp_table;
 };
 
 /* To convert to Q8.8 format for firmware */
@@ -338,7 +341,6 @@ enum Fiji_I2CLineID {
 #define FIJI_UNUSED_GPIO_PIN       0x7F
 
 extern int tonga_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr *hwmgr);
-extern int tonga_hwmgr_backend_fini(struct pp_hwmgr *hwmgr);
 extern int tonga_get_mc_microcode_version (struct pp_hwmgr *hwmgr);
 extern int tonga_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr);
 extern int tonga_notify_smc_display_change(struct pp_hwmgr *hwmgr, bool has_display);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_powertune.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_powertune.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_powertune.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_powertune.c	2016-07-24 15:23:50.000000000 -0400
@@ -32,7 +32,7 @@
 #define VOLTAGE_SCALE  4
 #define POWERTUNE_DEFAULT_SET_MAX    1
 
-struct fiji_pt_defaults fiji_power_tune_data_set_array[POWERTUNE_DEFAULT_SET_MAX] = {
+const struct fiji_pt_defaults fiji_power_tune_data_set_array[POWERTUNE_DEFAULT_SET_MAX] = {
 		/*sviLoadLIneEn,  SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc */
 		{1,               0xF,             0xFD,
 		/* TDC_MAWt, TdcWaterfallCtl, DTEAmbientTempBase */
@@ -143,7 +143,7 @@ static void get_scl_sda_value(uint8_t li
 int fiji_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr)
 {
 	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
-	struct fiji_pt_defaults *defaults = data->power_tune_defaults;
+	const struct fiji_pt_defaults *defaults = data->power_tune_defaults;
 	SMU73_Discrete_DpmTable  *dpm_table = &(data->smc_state_table);
 	struct phm_ppt_v1_information *table_info =
 			(struct phm_ppt_v1_information *)(hwmgr->pptable);
@@ -222,7 +222,7 @@ int fiji_populate_bapm_parameters_in_dpm
 static int fiji_populate_svi_load_line(struct pp_hwmgr *hwmgr)
 {
     struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
-    struct fiji_pt_defaults *defaults = data->power_tune_defaults;
+    const struct fiji_pt_defaults *defaults = data->power_tune_defaults;
 
     data->power_tune_table.SviLoadLineEn = defaults->SviLoadLineEn;
     data->power_tune_table.SviLoadLineVddC = defaults->SviLoadLineVddC;
@@ -238,7 +238,7 @@ static int fiji_populate_tdc_limit(struc
 	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
 	struct phm_ppt_v1_information *table_info =
 			(struct phm_ppt_v1_information *)(hwmgr->pptable);
-	struct  fiji_pt_defaults *defaults = data->power_tune_defaults;
+	const struct fiji_pt_defaults *defaults = data->power_tune_defaults;
 
 	/* TDC number of fraction bits are changed from 8 to 7
 	 * for Fiji as requested by SMC team
@@ -256,7 +256,7 @@ static int fiji_populate_tdc_limit(struc
 static int fiji_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset)
 {
 	struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend);
-	struct  fiji_pt_defaults *defaults = data->power_tune_defaults;
+	const struct fiji_pt_defaults *defaults = data->power_tune_defaults;
 	uint32_t temp;
 
 	if (fiji_read_smc_sram_dword(hwmgr->smumgr,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_thermal.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_thermal.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_thermal.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_thermal.c	2016-07-24 15:23:50.000000000 -0400
@@ -221,8 +221,8 @@ int fiji_fan_ctrl_set_fan_speed_percent(
 	if (duty100 == 0)
 		return -EINVAL;
 
-	tmp64 = (uint64_t)speed * 100;
-	do_div(tmp64, duty100);
+	tmp64 = (uint64_t)speed * duty100;
+	do_div(tmp64, 100);
 	duty = (uint32_t)tmp64;
 
 	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
@@ -615,7 +615,7 @@ static int tf_fiji_thermal_disable_alert
 	return fiji_thermal_disable_alert(hwmgr);
 }
 
-static struct phm_master_table_item
+static const struct phm_master_table_item
 fiji_thermal_start_thermal_controller_master_list[] = {
 	{NULL, tf_fiji_thermal_initialize},
 	{NULL, tf_fiji_thermal_set_temperature_range},
@@ -630,14 +630,14 @@ fiji_thermal_start_thermal_controller_ma
 	{NULL, NULL}
 };
 
-static struct phm_master_table_header
+static const struct phm_master_table_header
 fiji_thermal_start_thermal_controller_master = {
 	0,
 	PHM_MasterTableFlag_None,
 	fiji_thermal_start_thermal_controller_master_list
 };
 
-static struct phm_master_table_item
+static const struct phm_master_table_item
 fiji_thermal_set_temperature_range_master_list[] = {
 	{NULL, tf_fiji_thermal_disable_alert},
 	{NULL, tf_fiji_thermal_set_temperature_range},
@@ -645,7 +645,7 @@ fiji_thermal_set_temperature_range_maste
 	{NULL, NULL}
 };
 
-struct phm_master_table_header
+static const struct phm_master_table_header
 fiji_thermal_set_temperature_range_master = {
 	0,
 	PHM_MasterTableFlag_None,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/functiontables.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/functiontables.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/functiontables.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/functiontables.c	2016-07-24 15:23:50.000000000 -0400
@@ -84,7 +84,7 @@ int phm_dispatch_table(struct pp_hwmgr *
 }
 
 int phm_construct_table(struct pp_hwmgr *hwmgr,
-			struct phm_master_table_header *master_table,
+			const struct phm_master_table_header *master_table,
 			struct phm_runtime_table_header *rt_table)
 {
 	uint32_t function_count = 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c	2016-07-24 15:23:50.000000000 -0400
@@ -306,10 +306,14 @@ int phm_store_dal_configuration_data(str
 {
 	PHM_FUNC_CHECK(hwmgr);
 
-	if (hwmgr->hwmgr_func->store_cc6_data == NULL)
+	if (display_config == NULL)
 		return -EINVAL;
 
 	hwmgr->display_config = *display_config;
+
+	if (hwmgr->hwmgr_func->store_cc6_data == NULL)
+		return -EINVAL;
+
 	/* to do pass other display configuration in furture */
 
 	if (hwmgr->hwmgr_func->store_cc6_data)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c	2016-07-24 15:23:50.000000000 -0400
@@ -30,10 +30,14 @@
 #include "pppcielanes.h"
 #include "pp_debug.h"
 #include "ppatomctrl.h"
+#include "ppsmc.h"
+
+#define VOLTAGE_SCALE               4
 
 extern int cz_hwmgr_init(struct pp_hwmgr *hwmgr);
 extern int tonga_hwmgr_init(struct pp_hwmgr *hwmgr);
 extern int fiji_hwmgr_init(struct pp_hwmgr *hwmgr);
+extern int polaris10_hwmgr_init(struct pp_hwmgr *hwmgr);
 
 int hwmgr_init(struct amd_pp_init *pp_init, struct pp_instance *handle)
 {
@@ -67,6 +71,10 @@ int hwmgr_init(struct amd_pp_init *pp_in
 		case CHIP_FIJI:
 			fiji_hwmgr_init(hwmgr);
 			break;
+		case CHIP_POLARIS11:
+		case CHIP_POLARIS10:
+			polaris10_hwmgr_init(hwmgr);
+			break;
 		default:
 			return -EINVAL;
 		}
@@ -85,6 +93,13 @@ int hwmgr_fini(struct pp_hwmgr *hwmgr)
 	if (hwmgr == NULL || hwmgr->ps == NULL)
 		return -EINVAL;
 
+	/* do hwmgr finish*/
+	kfree(hwmgr->backend);
+
+	kfree(hwmgr->start_thermal_controller.function_list);
+
+	kfree(hwmgr->set_temperature_range.function_list);
+
 	kfree(hwmgr->ps);
 	kfree(hwmgr);
 	return 0;
@@ -454,7 +469,7 @@ uint16_t phm_find_closest_vddci(struct p
 
 	PP_ASSERT_WITH_CODE(false,
 			"VDDCI is larger than max VDDCI in VDDCI Voltage Table!",
-			return vddci_table->entries[i].value);
+			return vddci_table->entries[i-1].value);
 }
 
 int phm_find_boot_level(void *table,
@@ -561,3 +576,38 @@ uint32_t phm_get_lowest_enabled_level(st
 
 	return level;
 }
+
+void phm_apply_dal_min_voltage_request(struct pp_hwmgr *hwmgr)
+{
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)hwmgr->pptable;
+	struct phm_clock_voltage_dependency_table *table =
+				table_info->vddc_dep_on_dal_pwrl;
+	struct phm_ppt_v1_clock_voltage_dependency_table *vddc_table;
+	enum PP_DAL_POWERLEVEL dal_power_level = hwmgr->dal_power_level;
+	uint32_t req_vddc = 0, req_volt, i;
+
+	if (!table || table->count <= 0
+		|| dal_power_level < PP_DAL_POWERLEVEL_ULTRALOW
+		|| dal_power_level > PP_DAL_POWERLEVEL_PERFORMANCE)
+		return;
+
+	for (i = 0; i < table->count; i++) {
+		if (dal_power_level == table->entries[i].clk) {
+			req_vddc = table->entries[i].v;
+			break;
+		}
+	}
+
+	vddc_table = table_info->vdd_dep_on_sclk;
+	for (i = 0; i < vddc_table->count; i++) {
+		if (req_vddc <= vddc_table->entries[i].vddc) {
+			req_volt = (((uint32_t)vddc_table->entries[i].vddc) * VOLTAGE_SCALE);
+			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+					PPSMC_MSG_VddC_Request, req_volt);
+			return;
+		}
+	}
+	printk(KERN_ERR "DAL requested level can not"
+			" found a available voltage in VDDC DPM Table \n");
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr_ppt.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr_ppt.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr_ppt.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr_ppt.h	2016-07-24 15:23:50.000000000 -0400
@@ -39,6 +39,7 @@ struct phm_ppt_v1_clock_voltage_dependen
 	uint8_t phases;
 	uint8_t cks_enable;
 	uint8_t cks_voffset;
+	uint32_t sclk_offset;
 };
 
 typedef struct phm_ppt_v1_clock_voltage_dependency_record phm_ppt_v1_clock_voltage_dependency_record;
@@ -92,6 +93,8 @@ typedef struct phm_ppt_v1_voltage_lookup
 struct phm_ppt_v1_pcie_record {
 	uint8_t gen_speed;
 	uint8_t lane_width;
+	uint16_t usreserved;
+	uint32_t pcie_sclk;
 };
 typedef struct phm_ppt_v1_pcie_record phm_ppt_v1_pcie_record;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/Makefile linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/Makefile
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -8,7 +8,9 @@ HARDWARE_MGR = hwmgr.o processpptables.o
 	       tonga_processpptables.o ppatomctrl.o \
                tonga_hwmgr.o pppcielanes.o  tonga_thermal.o\
                fiji_powertune.o fiji_hwmgr.o tonga_clockpowergating.o \
-               fiji_clockpowergating.o fiji_thermal.o
+               fiji_clockpowergating.o fiji_thermal.o \
+	       polaris10_hwmgr.o polaris10_powertune.o polaris10_thermal.o \
+	       polaris10_clockpowergating.o
 
 AMD_PP_HWMGR = $(addprefix $(AMD_PP_PATH)/hwmgr/,$(HARDWARE_MGR))
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_clockpowergating.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_clockpowergating.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_clockpowergating.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_clockpowergating.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,430 @@
+/*
+ * Copyright 2016 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "polaris10_clockpowergating.h"
+
+int polaris10_phm_powerdown_uvd(struct pp_hwmgr *hwmgr)
+{
+	if (phm_cf_want_uvd_power_gating(hwmgr))
+		return smum_send_msg_to_smc(hwmgr->smumgr,
+				PPSMC_MSG_UVDPowerOFF);
+	return 0;
+}
+
+int polaris10_phm_powerup_uvd(struct pp_hwmgr *hwmgr)
+{
+	if (phm_cf_want_uvd_power_gating(hwmgr)) {
+		if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+				  PHM_PlatformCaps_UVDDynamicPowerGating)) {
+			return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+					PPSMC_MSG_UVDPowerON, 1);
+		} else {
+			return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+					PPSMC_MSG_UVDPowerON, 0);
+		}
+	}
+
+	return 0;
+}
+
+int polaris10_phm_powerdown_vce(struct pp_hwmgr *hwmgr)
+{
+	if (phm_cf_want_vce_power_gating(hwmgr))
+		return smum_send_msg_to_smc(hwmgr->smumgr,
+				PPSMC_MSG_VCEPowerOFF);
+	return 0;
+}
+
+int polaris10_phm_powerup_vce(struct pp_hwmgr *hwmgr)
+{
+	if (phm_cf_want_vce_power_gating(hwmgr))
+		return smum_send_msg_to_smc(hwmgr->smumgr,
+				PPSMC_MSG_VCEPowerON);
+	return 0;
+}
+
+int polaris10_phm_powerdown_samu(struct pp_hwmgr *hwmgr)
+{
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_SamuPowerGating))
+		return smum_send_msg_to_smc(hwmgr->smumgr,
+				PPSMC_MSG_SAMPowerOFF);
+	return 0;
+}
+
+int polaris10_phm_powerup_samu(struct pp_hwmgr *hwmgr)
+{
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_SamuPowerGating))
+		return smum_send_msg_to_smc(hwmgr->smumgr,
+				PPSMC_MSG_SAMPowerON);
+	return 0;
+}
+
+int polaris10_phm_disable_clock_power_gating(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+
+	data->uvd_power_gated = false;
+	data->vce_power_gated = false;
+	data->samu_power_gated = false;
+
+	polaris10_phm_powerup_uvd(hwmgr);
+	polaris10_phm_powerup_vce(hwmgr);
+	polaris10_phm_powerup_samu(hwmgr);
+
+	return 0;
+}
+
+int polaris10_phm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+
+	if (data->uvd_power_gated == bgate)
+		return 0;
+
+	data->uvd_power_gated = bgate;
+
+	if (bgate) {
+		polaris10_update_uvd_dpm(hwmgr, true);
+		polaris10_phm_powerdown_uvd(hwmgr);
+	} else {
+		polaris10_phm_powerup_uvd(hwmgr);
+		polaris10_update_uvd_dpm(hwmgr, false);
+	}
+
+	return 0;
+}
+
+int polaris10_phm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+
+	if (data->vce_power_gated == bgate)
+		return 0;
+
+	data->vce_power_gated = bgate;
+
+	if (bgate)
+		polaris10_phm_powerdown_vce(hwmgr);
+	else
+		polaris10_phm_powerup_vce(hwmgr);
+
+	return 0;
+}
+
+int polaris10_phm_powergate_samu(struct pp_hwmgr *hwmgr, bool bgate)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+
+	if (data->samu_power_gated == bgate)
+		return 0;
+
+	data->samu_power_gated = bgate;
+
+	if (bgate) {
+		polaris10_update_samu_dpm(hwmgr, true);
+		polaris10_phm_powerdown_samu(hwmgr);
+	} else {
+		polaris10_phm_powerup_samu(hwmgr);
+		polaris10_update_samu_dpm(hwmgr, false);
+	}
+
+	return 0;
+}
+
+int polaris10_phm_update_clock_gatings(struct pp_hwmgr *hwmgr,
+					const uint32_t *msg_id)
+{
+	PPSMC_Msg msg;
+	uint32_t value;
+
+	switch ((*msg_id & PP_GROUP_MASK) >> PP_GROUP_SHIFT) {
+	case PP_GROUP_GFX:
+		switch ((*msg_id & PP_BLOCK_MASK) >> PP_BLOCK_SHIFT) {
+		case PP_BLOCK_GFX_CG:
+			if (PP_STATE_SUPPORT_CG & *msg_id) {
+				msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
+						PPSMC_MSG_EnableClockGatingFeature :
+						PPSMC_MSG_DisableClockGatingFeature;
+				value = CG_GFX_CGCG_MASK;
+
+				if (smum_send_msg_to_smc_with_parameter(
+						hwmgr->smumgr, msg, value))
+					return -1;
+			}
+			if (PP_STATE_SUPPORT_LS & *msg_id) {
+				msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS
+					? PPSMC_MSG_EnableClockGatingFeature
+					: PPSMC_MSG_DisableClockGatingFeature;
+				value = CG_GFX_CGLS_MASK;
+
+				if (smum_send_msg_to_smc_with_parameter(
+						hwmgr->smumgr, msg, value))
+					return -1;
+			}
+			break;
+
+		case PP_BLOCK_GFX_3D:
+			if (PP_STATE_SUPPORT_CG & *msg_id) {
+				msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
+						PPSMC_MSG_EnableClockGatingFeature :
+						PPSMC_MSG_DisableClockGatingFeature;
+				value = CG_GFX_3DCG_MASK;
+
+				if (smum_send_msg_to_smc_with_parameter(
+						hwmgr->smumgr, msg, value))
+					return -1;
+			}
+
+			if  (PP_STATE_SUPPORT_LS & *msg_id) {
+				msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
+						PPSMC_MSG_EnableClockGatingFeature :
+						PPSMC_MSG_DisableClockGatingFeature;
+				value = CG_GFX_3DLS_MASK;
+
+				if (smum_send_msg_to_smc_with_parameter(
+						hwmgr->smumgr, msg, value))
+					return -1;
+			}
+			break;
+
+		case PP_BLOCK_GFX_RLC:
+			if (PP_STATE_SUPPORT_LS & *msg_id) {
+				msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
+						PPSMC_MSG_EnableClockGatingFeature :
+						PPSMC_MSG_DisableClockGatingFeature;
+				value = CG_GFX_RLC_LS_MASK;
+
+				if (smum_send_msg_to_smc_with_parameter(
+						hwmgr->smumgr, msg, value))
+					return -1;
+			}
+			break;
+
+		case PP_BLOCK_GFX_CP:
+			if (PP_STATE_SUPPORT_LS & *msg_id) {
+				msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
+						PPSMC_MSG_EnableClockGatingFeature :
+						PPSMC_MSG_DisableClockGatingFeature;
+				value = CG_GFX_CP_LS_MASK;
+
+				if (smum_send_msg_to_smc_with_parameter(
+						hwmgr->smumgr, msg, value))
+					return -1;
+			}
+			break;
+
+		case PP_BLOCK_GFX_MG:
+			if (PP_STATE_SUPPORT_CG & *msg_id) {
+				msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG)	?
+						PPSMC_MSG_EnableClockGatingFeature :
+						PPSMC_MSG_DisableClockGatingFeature;
+				value = (CG_CPF_MGCG_MASK | CG_RLC_MGCG_MASK |
+						CG_GFX_OTHERS_MGCG_MASK);
+
+				if (smum_send_msg_to_smc_with_parameter(
+						hwmgr->smumgr, msg, value))
+					return -1;
+			}
+			break;
+
+		default:
+			return -1;
+		}
+		break;
+
+	case PP_GROUP_SYS:
+		switch ((*msg_id & PP_BLOCK_MASK) >> PP_BLOCK_SHIFT) {
+		case PP_BLOCK_SYS_BIF:
+			if (PP_STATE_SUPPORT_CG & *msg_id) {
+				msg = (*msg_id & PP_STATE_MASK) & PP_STATE_CG ?
+						PPSMC_MSG_EnableClockGatingFeature :
+						PPSMC_MSG_DisableClockGatingFeature;
+				value = CG_SYS_BIF_MGCG_MASK;
+
+				if (smum_send_msg_to_smc_with_parameter(
+						hwmgr->smumgr, msg, value))
+					return -1;
+			}
+			if  (PP_STATE_SUPPORT_LS & *msg_id) {
+				msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
+						PPSMC_MSG_EnableClockGatingFeature :
+						PPSMC_MSG_DisableClockGatingFeature;
+				value = CG_SYS_BIF_MGLS_MASK;
+
+				if (smum_send_msg_to_smc_with_parameter(
+						hwmgr->smumgr, msg, value))
+					return -1;
+			}
+			break;
+
+		case PP_BLOCK_SYS_MC:
+			if (PP_STATE_SUPPORT_CG & *msg_id) {
+				msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG)	?
+						PPSMC_MSG_EnableClockGatingFeature :
+						PPSMC_MSG_DisableClockGatingFeature;
+				value = CG_SYS_MC_MGCG_MASK;
+
+				if (smum_send_msg_to_smc_with_parameter(
+						hwmgr->smumgr, msg, value))
+					return -1;
+			}
+
+			if (PP_STATE_SUPPORT_LS & *msg_id) {
+				msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
+						PPSMC_MSG_EnableClockGatingFeature :
+						PPSMC_MSG_DisableClockGatingFeature;
+				value = CG_SYS_MC_MGLS_MASK;
+
+				if (smum_send_msg_to_smc_with_parameter(
+						hwmgr->smumgr, msg, value))
+					return -1;
+			}
+			break;
+
+		case PP_BLOCK_SYS_DRM:
+			if (PP_STATE_SUPPORT_CG & *msg_id) {
+				msg = (*msg_id & PP_STATE_MASK) & PP_STATE_CG ?
+						PPSMC_MSG_EnableClockGatingFeature :
+						PPSMC_MSG_DisableClockGatingFeature;
+				value = CG_SYS_DRM_MGCG_MASK;
+
+				if (smum_send_msg_to_smc_with_parameter(
+						hwmgr->smumgr, msg, value))
+					return -1;
+			}
+			if (PP_STATE_SUPPORT_LS & *msg_id) {
+				msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
+						PPSMC_MSG_EnableClockGatingFeature :
+						PPSMC_MSG_DisableClockGatingFeature;
+				value = CG_SYS_DRM_MGLS_MASK;
+
+				if (smum_send_msg_to_smc_with_parameter(
+						hwmgr->smumgr, msg, value))
+					return -1;
+			}
+			break;
+
+		case PP_BLOCK_SYS_HDP:
+			if (PP_STATE_SUPPORT_CG & *msg_id) {
+				msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
+						PPSMC_MSG_EnableClockGatingFeature :
+						PPSMC_MSG_DisableClockGatingFeature;
+				value = CG_SYS_HDP_MGCG_MASK;
+
+				if (smum_send_msg_to_smc_with_parameter(
+						hwmgr->smumgr, msg, value))
+					return -1;
+			}
+
+			if (PP_STATE_SUPPORT_LS & *msg_id) {
+				msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
+						PPSMC_MSG_EnableClockGatingFeature :
+						PPSMC_MSG_DisableClockGatingFeature;
+				value = CG_SYS_HDP_MGLS_MASK;
+
+				if (smum_send_msg_to_smc_with_parameter(
+						hwmgr->smumgr, msg, value))
+					return -1;
+			}
+			break;
+
+		case PP_BLOCK_SYS_SDMA:
+			if (PP_STATE_SUPPORT_CG & *msg_id) {
+				msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG)	?
+						PPSMC_MSG_EnableClockGatingFeature :
+						PPSMC_MSG_DisableClockGatingFeature;
+				value = CG_SYS_SDMA_MGCG_MASK;
+
+				if (smum_send_msg_to_smc_with_parameter(
+						hwmgr->smumgr, msg, value))
+					return -1;
+			}
+
+			if (PP_STATE_SUPPORT_LS & *msg_id) {
+				msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
+						PPSMC_MSG_EnableClockGatingFeature :
+						PPSMC_MSG_DisableClockGatingFeature;
+				value = CG_SYS_SDMA_MGLS_MASK;
+
+				if (smum_send_msg_to_smc_with_parameter(
+						hwmgr->smumgr, msg, value))
+					return -1;
+			}
+			break;
+
+		case PP_BLOCK_SYS_ROM:
+			if (PP_STATE_SUPPORT_CG & *msg_id) {
+				msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
+						PPSMC_MSG_EnableClockGatingFeature :
+						PPSMC_MSG_DisableClockGatingFeature;
+				value = CG_SYS_ROM_MASK;
+
+				if (smum_send_msg_to_smc_with_parameter(
+						hwmgr->smumgr, msg, value))
+					return -1;
+			}
+			break;
+
+		default:
+			return -1;
+
+		}
+		break;
+
+	default:
+		return -1;
+
+	}
+
+	return 0;
+}
+
+/* This function is for Polaris11 only for now,
+ * Powerplay will only control the static per CU Power Gating.
+ * Dynamic per CU Power Gating will be done in gfx.
+ */
+int polaris10_phm_enable_per_cu_power_gating(struct pp_hwmgr *hwmgr, bool enable)
+{
+	struct cgs_system_info sys_info = {0};
+	uint32_t active_cus;
+	int result;
+
+	sys_info.size = sizeof(struct cgs_system_info);
+	sys_info.info_id = CGS_SYSTEM_INFO_GFX_CU_INFO;
+
+	result = cgs_query_system_info(hwmgr->device, &sys_info);
+
+	if (result)
+		return -EINVAL;
+	else
+		active_cus = sys_info.value;
+
+	if (enable)
+		return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+				PPSMC_MSG_GFX_CU_PG_ENABLE, active_cus);
+	else
+		return smum_send_msg_to_smc(hwmgr->smumgr,
+				PPSMC_MSG_GFX_CU_PG_DISABLE);
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_clockpowergating.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_clockpowergating.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_clockpowergating.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_clockpowergating.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2016 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef _POLARIS10_CLOCK_POWER_GATING_H_
+#define _POLARIS10_CLOCK_POWER_GATING_H_
+
+#include "polaris10_hwmgr.h"
+#include "pp_asicblocks.h"
+
+int polaris10_phm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate);
+int polaris10_phm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate);
+int polaris10_phm_powerdown_uvd(struct pp_hwmgr *hwmgr);
+int polaris10_phm_powergate_samu(struct pp_hwmgr *hwmgr, bool bgate);
+int polaris10_phm_powergate_acp(struct pp_hwmgr *hwmgr, bool bgate);
+int polaris10_phm_disable_clock_power_gating(struct pp_hwmgr *hwmgr);
+int polaris10_phm_update_clock_gatings(struct pp_hwmgr *hwmgr,
+					const uint32_t *msg_id);
+int polaris10_phm_enable_per_cu_power_gating(struct pp_hwmgr *hwmgr, bool enable);
+
+#endif /* _POLARIS10_CLOCK_POWER_GATING_H_ */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_dyn_defaults.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_dyn_defaults.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_dyn_defaults.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_dyn_defaults.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef POLARIS10_DYN_DEFAULTS_H
+#define POLARIS10_DYN_DEFAULTS_H
+
+
+enum Polaris10dpm_TrendDetection {
+	Polaris10Adpm_TrendDetection_AUTO,
+	Polaris10Adpm_TrendDetection_UP,
+	Polaris10Adpm_TrendDetection_DOWN
+};
+typedef enum Polaris10dpm_TrendDetection Polaris10dpm_TrendDetection;
+
+/*  We need to fill in the default values */
+
+
+#define PPPOLARIS10_VOTINGRIGHTSCLIENTS_DFLT0              0x3FFFC102
+#define PPPOLARIS10_VOTINGRIGHTSCLIENTS_DFLT1              0x000400
+#define PPPOLARIS10_VOTINGRIGHTSCLIENTS_DFLT2              0xC00080
+#define PPPOLARIS10_VOTINGRIGHTSCLIENTS_DFLT3              0xC00200
+#define PPPOLARIS10_VOTINGRIGHTSCLIENTS_DFLT4              0xC01680
+#define PPPOLARIS10_VOTINGRIGHTSCLIENTS_DFLT5              0xC00033
+#define PPPOLARIS10_VOTINGRIGHTSCLIENTS_DFLT6              0xC00033
+#define PPPOLARIS10_VOTINGRIGHTSCLIENTS_DFLT7              0x3FFFC000
+
+
+#define PPPOLARIS10_THERMALPROTECTCOUNTER_DFLT            0x200
+#define PPPOLARIS10_STATICSCREENTHRESHOLDUNIT_DFLT        0
+#define PPPOLARIS10_STATICSCREENTHRESHOLD_DFLT            0x00C8
+#define PPPOLARIS10_GFXIDLECLOCKSTOPTHRESHOLD_DFLT        0x200
+#define PPPOLARIS10_REFERENCEDIVIDER_DFLT                  4
+
+#define PPPOLARIS10_ULVVOLTAGECHANGEDELAY_DFLT             1687
+
+#define PPPOLARIS10_CGULVPARAMETER_DFLT                    0x00040035
+#define PPPOLARIS10_CGULVCONTROL_DFLT                      0x00007450
+#define PPPOLARIS10_TARGETACTIVITY_DFLT                     50
+#define PPPOLARIS10_MCLK_TARGETACTIVITY_DFLT                10
+
+#endif
+
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,5060 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/fb.h>
+#include <asm/div64.h>
+#include "linux/delay.h"
+#include "pp_acpi.h"
+#include "hwmgr.h"
+#include "polaris10_hwmgr.h"
+#include "polaris10_powertune.h"
+#include "polaris10_dyn_defaults.h"
+#include "polaris10_smumgr.h"
+#include "pp_debug.h"
+#include "ppatomctrl.h"
+#include "atombios.h"
+#include "tonga_pptable.h"
+#include "pppcielanes.h"
+#include "amd_pcie_helpers.h"
+#include "hardwaremanager.h"
+#include "tonga_processpptables.h"
+#include "cgs_common.h"
+#include "smu74.h"
+#include "smu_ucode_xfer_vi.h"
+#include "smu74_discrete.h"
+#include "smu/smu_7_1_3_d.h"
+#include "smu/smu_7_1_3_sh_mask.h"
+#include "gmc/gmc_8_1_d.h"
+#include "gmc/gmc_8_1_sh_mask.h"
+#include "oss/oss_3_0_d.h"
+#include "gca/gfx_8_0_d.h"
+#include "bif/bif_5_0_d.h"
+#include "bif/bif_5_0_sh_mask.h"
+#include "gmc/gmc_8_1_d.h"
+#include "gmc/gmc_8_1_sh_mask.h"
+#include "bif/bif_5_0_d.h"
+#include "bif/bif_5_0_sh_mask.h"
+#include "dce/dce_10_0_d.h"
+#include "dce/dce_10_0_sh_mask.h"
+
+#include "polaris10_thermal.h"
+#include "polaris10_clockpowergating.h"
+
+#define MC_CG_ARB_FREQ_F0           0x0a
+#define MC_CG_ARB_FREQ_F1           0x0b
+#define MC_CG_ARB_FREQ_F2           0x0c
+#define MC_CG_ARB_FREQ_F3           0x0d
+
+#define MC_CG_SEQ_DRAMCONF_S0       0x05
+#define MC_CG_SEQ_DRAMCONF_S1       0x06
+#define MC_CG_SEQ_YCLK_SUSPEND      0x04
+#define MC_CG_SEQ_YCLK_RESUME       0x0a
+
+
+#define SMC_RAM_END 0x40000
+
+#define SMC_CG_IND_START            0xc0030000
+#define SMC_CG_IND_END              0xc0040000
+
+#define VOLTAGE_SCALE               4
+#define VOLTAGE_VID_OFFSET_SCALE1   625
+#define VOLTAGE_VID_OFFSET_SCALE2   100
+
+#define VDDC_VDDCI_DELTA            200
+
+#define MEM_FREQ_LOW_LATENCY        25000
+#define MEM_FREQ_HIGH_LATENCY       80000
+
+#define MEM_LATENCY_HIGH            45
+#define MEM_LATENCY_LOW             35
+#define MEM_LATENCY_ERR             0xFFFF
+
+#define MC_SEQ_MISC0_GDDR5_SHIFT 28
+#define MC_SEQ_MISC0_GDDR5_MASK  0xf0000000
+#define MC_SEQ_MISC0_GDDR5_VALUE 5
+
+
+#define PCIE_BUS_CLK                10000
+#define TCLK                        (PCIE_BUS_CLK / 10)
+
+
+static const uint16_t polaris10_clock_stretcher_lookup_table[2][4] =
+{ {600, 1050, 3, 0}, {600, 1050, 6, 1} };
+
+/*  [FF, SS] type, [] 4 voltage ranges, and [Floor Freq, Boundary Freq, VID min , VID max] */
+static const uint32_t polaris10_clock_stretcher_ddt_table[2][4][4] =
+{ { {265, 529, 120, 128}, {325, 650, 96, 119}, {430, 860, 32, 95}, {0, 0, 0, 31} },
+  { {275, 550, 104, 112}, {319, 638, 96, 103}, {360, 720, 64, 95}, {384, 768, 32, 63} } };
+
+/*  [Use_For_Low_freq] value, [0%, 5%, 10%, 7.14%, 14.28%, 20%] (coming from PWR_CKS_CNTL.stretch_amount reg spec) */
+static const uint8_t polaris10_clock_stretch_amount_conversion[2][6] =
+{ {0, 1, 3, 2, 4, 5}, {0, 2, 4, 5, 6, 5} };
+
+/** Values for the CG_THERMAL_CTRL::DPM_EVENT_SRC field. */
+enum DPM_EVENT_SRC {
+	DPM_EVENT_SRC_ANALOG = 0,
+	DPM_EVENT_SRC_EXTERNAL = 1,
+	DPM_EVENT_SRC_DIGITAL = 2,
+	DPM_EVENT_SRC_ANALOG_OR_EXTERNAL = 3,
+	DPM_EVENT_SRC_DIGITAL_OR_EXTERNAL = 4
+};
+
+static const unsigned long PhwPolaris10_Magic = (unsigned long)(PHM_VIslands_Magic);
+
+struct polaris10_power_state *cast_phw_polaris10_power_state(
+				  struct pp_hw_power_state *hw_ps)
+{
+	PP_ASSERT_WITH_CODE((PhwPolaris10_Magic == hw_ps->magic),
+				"Invalid Powerstate Type!",
+				 return NULL);
+
+	return (struct polaris10_power_state *)hw_ps;
+}
+
+const struct polaris10_power_state *cast_const_phw_polaris10_power_state(
+				 const struct pp_hw_power_state *hw_ps)
+{
+	PP_ASSERT_WITH_CODE((PhwPolaris10_Magic == hw_ps->magic),
+				"Invalid Powerstate Type!",
+				 return NULL);
+
+	return (const struct polaris10_power_state *)hw_ps;
+}
+
+static bool polaris10_is_dpm_running(struct pp_hwmgr *hwmgr)
+{
+	return (1 == PHM_READ_INDIRECT_FIELD(hwmgr->device,
+			CGS_IND_REG__SMC, FEATURE_STATUS, VOLTAGE_CONTROLLER_ON))
+			? true : false;
+}
+
+/**
+ * Find the MC microcode version and store it in the HwMgr struct
+ *
+ * @param    hwmgr  the address of the powerplay hardware manager.
+ * @return   always 0
+ */
+int phm_get_mc_microcode_version (struct pp_hwmgr *hwmgr)
+{
+	cgs_write_register(hwmgr->device, mmMC_SEQ_IO_DEBUG_INDEX, 0x9F);
+
+	hwmgr->microcode_version_info.MC = cgs_read_register(hwmgr->device, mmMC_SEQ_IO_DEBUG_DATA);
+
+	return 0;
+}
+
+uint16_t phm_get_current_pcie_speed(struct pp_hwmgr *hwmgr)
+{
+	uint32_t speedCntl = 0;
+
+	/* mmPCIE_PORT_INDEX rename as mmPCIE_INDEX */
+	speedCntl = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__PCIE,
+			ixPCIE_LC_SPEED_CNTL);
+	return((uint16_t)PHM_GET_FIELD(speedCntl,
+			PCIE_LC_SPEED_CNTL, LC_CURRENT_DATA_RATE));
+}
+
+int phm_get_current_pcie_lane_number(struct pp_hwmgr *hwmgr)
+{
+	uint32_t link_width;
+
+	/* mmPCIE_PORT_INDEX rename as mmPCIE_INDEX */
+	link_width = PHM_READ_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__PCIE,
+			PCIE_LC_LINK_WIDTH_CNTL, LC_LINK_WIDTH_RD);
+
+	PP_ASSERT_WITH_CODE((7 >= link_width),
+			"Invalid PCIe lane width!", return 0);
+
+	return decode_pcie_lane_width(link_width);
+}
+
+/**
+* Enable voltage control
+*
+* @param    pHwMgr  the address of the powerplay hardware manager.
+* @return   always PP_Result_OK
+*/
+int polaris10_enable_smc_voltage_controller(struct pp_hwmgr *hwmgr)
+{
+	PP_ASSERT_WITH_CODE(
+		(hwmgr->smumgr->smumgr_funcs->send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_Voltage_Cntl_Enable) == 0),
+		"Failed to enable voltage DPM during DPM Start Function!",
+		return 1;
+	);
+
+	return 0;
+}
+
+/**
+* Checks if we want to support voltage control
+*
+* @param    hwmgr  the address of the powerplay hardware manager.
+*/
+static bool polaris10_voltage_control(const struct pp_hwmgr *hwmgr)
+{
+	const struct polaris10_hwmgr *data =
+			(const struct polaris10_hwmgr *)(hwmgr->backend);
+
+	return (POLARIS10_VOLTAGE_CONTROL_NONE != data->voltage_control);
+}
+
+/**
+* Enable voltage control
+*
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @return   always 0
+*/
+static int polaris10_enable_voltage_control(struct pp_hwmgr *hwmgr)
+{
+	/* enable voltage control */
+	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			GENERAL_PWRMGT, VOLT_PWRMGT_EN, 1);
+
+	return 0;
+}
+
+/**
+* Create Voltage Tables.
+*
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @return   always 0
+*/
+static int polaris10_construct_voltage_tables(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)hwmgr->pptable;
+	int result;
+
+	if (POLARIS10_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) {
+		result = atomctrl_get_voltage_table_v3(hwmgr,
+				VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_GPIO_LUT,
+				&(data->mvdd_voltage_table));
+		PP_ASSERT_WITH_CODE((0 == result),
+				"Failed to retrieve MVDD table.",
+				return result);
+	} else if (POLARIS10_VOLTAGE_CONTROL_BY_SVID2 == data->mvdd_control) {
+		result = phm_get_svi2_mvdd_voltage_table(&(data->mvdd_voltage_table),
+				table_info->vdd_dep_on_mclk);
+		PP_ASSERT_WITH_CODE((0 == result),
+				"Failed to retrieve SVI2 MVDD table from dependancy table.",
+				return result;);
+	}
+
+	if (POLARIS10_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) {
+		result = atomctrl_get_voltage_table_v3(hwmgr,
+				VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_GPIO_LUT,
+				&(data->vddci_voltage_table));
+		PP_ASSERT_WITH_CODE((0 == result),
+				"Failed to retrieve VDDCI table.",
+				return result);
+	} else if (POLARIS10_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) {
+		result = phm_get_svi2_vddci_voltage_table(&(data->vddci_voltage_table),
+				table_info->vdd_dep_on_mclk);
+		PP_ASSERT_WITH_CODE((0 == result),
+				"Failed to retrieve SVI2 VDDCI table from dependancy table.",
+				return result);
+	}
+
+	if (POLARIS10_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) {
+		result = phm_get_svi2_vdd_voltage_table(&(data->vddc_voltage_table),
+				table_info->vddc_lookup_table);
+		PP_ASSERT_WITH_CODE((0 == result),
+				"Failed to retrieve SVI2 VDDC table from lookup table.",
+				return result);
+	}
+
+	PP_ASSERT_WITH_CODE(
+			(data->vddc_voltage_table.count <= (SMU74_MAX_LEVELS_VDDC)),
+			"Too many voltage values for VDDC. Trimming to fit state table.",
+			phm_trim_voltage_table_to_fit_state_table(SMU74_MAX_LEVELS_VDDC,
+								&(data->vddc_voltage_table)));
+
+	PP_ASSERT_WITH_CODE(
+			(data->vddci_voltage_table.count <= (SMU74_MAX_LEVELS_VDDCI)),
+			"Too many voltage values for VDDCI. Trimming to fit state table.",
+			phm_trim_voltage_table_to_fit_state_table(SMU74_MAX_LEVELS_VDDCI,
+					&(data->vddci_voltage_table)));
+
+	PP_ASSERT_WITH_CODE(
+			(data->mvdd_voltage_table.count <= (SMU74_MAX_LEVELS_MVDD)),
+			"Too many voltage values for MVDD. Trimming to fit state table.",
+			phm_trim_voltage_table_to_fit_state_table(SMU74_MAX_LEVELS_MVDD,
+							   &(data->mvdd_voltage_table)));
+
+	return 0;
+}
+
+/**
+* Programs static screed detection parameters
+*
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @return   always 0
+*/
+static int polaris10_program_static_screen_threshold_parameters(
+							struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+
+	/* Set static screen threshold unit */
+	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			CG_STATIC_SCREEN_PARAMETER, STATIC_SCREEN_THRESHOLD_UNIT,
+			data->static_screen_threshold_unit);
+	/* Set static screen threshold */
+	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			CG_STATIC_SCREEN_PARAMETER, STATIC_SCREEN_THRESHOLD,
+			data->static_screen_threshold);
+
+	return 0;
+}
+
+/**
+* Setup display gap for glitch free memory clock switching.
+*
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @return   always  0
+*/
+static int polaris10_enable_display_gap(struct pp_hwmgr *hwmgr)
+{
+	uint32_t display_gap =
+			cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+					ixCG_DISPLAY_GAP_CNTL);
+
+	display_gap = PHM_SET_FIELD(display_gap, CG_DISPLAY_GAP_CNTL,
+			DISP_GAP, DISPLAY_GAP_IGNORE);
+
+	display_gap = PHM_SET_FIELD(display_gap, CG_DISPLAY_GAP_CNTL,
+			DISP_GAP_MCHG, DISPLAY_GAP_VBLANK);
+
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+			ixCG_DISPLAY_GAP_CNTL, display_gap);
+
+	return 0;
+}
+
+/**
+* Programs activity state transition voting clients
+*
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @return   always  0
+*/
+static int polaris10_program_voting_clients(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+
+	/* Clear reset for voting clients before enabling DPM */
+	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			SCLK_PWRMGT_CNTL, RESET_SCLK_CNT, 0);
+	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			SCLK_PWRMGT_CNTL, RESET_BUSY_CNT, 0);
+
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+			ixCG_FREQ_TRAN_VOTING_0, data->voting_rights_clients0);
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+			ixCG_FREQ_TRAN_VOTING_1, data->voting_rights_clients1);
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+			ixCG_FREQ_TRAN_VOTING_2, data->voting_rights_clients2);
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+			ixCG_FREQ_TRAN_VOTING_3, data->voting_rights_clients3);
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+			ixCG_FREQ_TRAN_VOTING_4, data->voting_rights_clients4);
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+			ixCG_FREQ_TRAN_VOTING_5, data->voting_rights_clients5);
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+			ixCG_FREQ_TRAN_VOTING_6, data->voting_rights_clients6);
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+			ixCG_FREQ_TRAN_VOTING_7, data->voting_rights_clients7);
+
+	return 0;
+}
+
+/**
+* Get the location of various tables inside the FW image.
+*
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @return   always  0
+*/
+static int polaris10_process_firmware_header(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
+	uint32_t tmp;
+	int result;
+	bool error = false;
+
+	result = polaris10_read_smc_sram_dword(hwmgr->smumgr,
+			SMU7_FIRMWARE_HEADER_LOCATION +
+			offsetof(SMU74_Firmware_Header, DpmTable),
+			&tmp, data->sram_end);
+
+	if (0 == result)
+		data->dpm_table_start = tmp;
+
+	error |= (0 != result);
+
+	result = polaris10_read_smc_sram_dword(hwmgr->smumgr,
+			SMU7_FIRMWARE_HEADER_LOCATION +
+			offsetof(SMU74_Firmware_Header, SoftRegisters),
+			&tmp, data->sram_end);
+
+	if (!result) {
+		data->soft_regs_start = tmp;
+		smu_data->soft_regs_start = tmp;
+	}
+
+	error |= (0 != result);
+
+	result = polaris10_read_smc_sram_dword(hwmgr->smumgr,
+			SMU7_FIRMWARE_HEADER_LOCATION +
+			offsetof(SMU74_Firmware_Header, mcRegisterTable),
+			&tmp, data->sram_end);
+
+	if (!result)
+		data->mc_reg_table_start = tmp;
+
+	result = polaris10_read_smc_sram_dword(hwmgr->smumgr,
+			SMU7_FIRMWARE_HEADER_LOCATION +
+			offsetof(SMU74_Firmware_Header, FanTable),
+			&tmp, data->sram_end);
+
+	if (!result)
+		data->fan_table_start = tmp;
+
+	error |= (0 != result);
+
+	result = polaris10_read_smc_sram_dword(hwmgr->smumgr,
+			SMU7_FIRMWARE_HEADER_LOCATION +
+			offsetof(SMU74_Firmware_Header, mcArbDramTimingTable),
+			&tmp, data->sram_end);
+
+	if (!result)
+		data->arb_table_start = tmp;
+
+	error |= (0 != result);
+
+	result = polaris10_read_smc_sram_dword(hwmgr->smumgr,
+			SMU7_FIRMWARE_HEADER_LOCATION +
+			offsetof(SMU74_Firmware_Header, Version),
+			&tmp, data->sram_end);
+
+	if (!result)
+		hwmgr->microcode_version_info.SMC = tmp;
+
+	error |= (0 != result);
+
+	return error ? -1 : 0;
+}
+
+/* Copy one arb setting to another and then switch the active set.
+ * arb_src and arb_dest is one of the MC_CG_ARB_FREQ_Fx constants.
+ */
+static int polaris10_copy_and_switch_arb_sets(struct pp_hwmgr *hwmgr,
+		uint32_t arb_src, uint32_t arb_dest)
+{
+	uint32_t mc_arb_dram_timing;
+	uint32_t mc_arb_dram_timing2;
+	uint32_t burst_time;
+	uint32_t mc_cg_config;
+
+	switch (arb_src) {
+	case MC_CG_ARB_FREQ_F0:
+		mc_arb_dram_timing  = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING);
+		mc_arb_dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2);
+		burst_time = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0);
+		break;
+	case MC_CG_ARB_FREQ_F1:
+		mc_arb_dram_timing  = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING_1);
+		mc_arb_dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2_1);
+		burst_time = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE1);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (arb_dest) {
+	case MC_CG_ARB_FREQ_F0:
+		cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING, mc_arb_dram_timing);
+		cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2, mc_arb_dram_timing2);
+		PHM_WRITE_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0, burst_time);
+		break;
+	case MC_CG_ARB_FREQ_F1:
+		cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING_1, mc_arb_dram_timing);
+		cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2_1, mc_arb_dram_timing2);
+		PHM_WRITE_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE1, burst_time);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	mc_cg_config = cgs_read_register(hwmgr->device, mmMC_CG_CONFIG);
+	mc_cg_config |= 0x0000000F;
+	cgs_write_register(hwmgr->device, mmMC_CG_CONFIG, mc_cg_config);
+	PHM_WRITE_FIELD(hwmgr->device, MC_ARB_CG, CG_ARB_REQ, arb_dest);
+
+	return 0;
+}
+
+/**
+* Initial switch from ARB F0->F1
+*
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @return   always 0
+* This function is to be called from the SetPowerState table.
+*/
+static int polaris10_initial_switch_from_arbf0_to_f1(struct pp_hwmgr *hwmgr)
+{
+	return polaris10_copy_and_switch_arb_sets(hwmgr,
+			MC_CG_ARB_FREQ_F0, MC_CG_ARB_FREQ_F1);
+}
+
+static int polaris10_setup_default_pcie_table(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	struct phm_ppt_v1_pcie_table *pcie_table = table_info->pcie_table;
+	uint32_t i, max_entry;
+
+	PP_ASSERT_WITH_CODE((data->use_pcie_performance_levels ||
+			data->use_pcie_power_saving_levels), "No pcie performance levels!",
+			return -EINVAL);
+
+	if (data->use_pcie_performance_levels &&
+			!data->use_pcie_power_saving_levels) {
+		data->pcie_gen_power_saving = data->pcie_gen_performance;
+		data->pcie_lane_power_saving = data->pcie_lane_performance;
+	} else if (!data->use_pcie_performance_levels &&
+			data->use_pcie_power_saving_levels) {
+		data->pcie_gen_performance = data->pcie_gen_power_saving;
+		data->pcie_lane_performance = data->pcie_lane_power_saving;
+	}
+
+	phm_reset_single_dpm_table(&data->dpm_table.pcie_speed_table,
+					SMU74_MAX_LEVELS_LINK,
+					MAX_REGULAR_DPM_NUMBER);
+
+	if (pcie_table != NULL) {
+		/* max_entry is used to make sure we reserve one PCIE level
+		 * for boot level (fix for A+A PSPP issue).
+		 * If PCIE table from PPTable have ULV entry + 8 entries,
+		 * then ignore the last entry.*/
+		max_entry = (SMU74_MAX_LEVELS_LINK < pcie_table->count) ?
+				SMU74_MAX_LEVELS_LINK : pcie_table->count;
+		for (i = 1; i < max_entry; i++) {
+			phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, i - 1,
+					get_pcie_gen_support(data->pcie_gen_cap,
+							pcie_table->entries[i].gen_speed),
+					get_pcie_lane_support(data->pcie_lane_cap,
+							pcie_table->entries[i].lane_width));
+		}
+		data->dpm_table.pcie_speed_table.count = max_entry - 1;
+
+		/* Setup BIF_SCLK levels */
+		for (i = 0; i < max_entry; i++)
+			data->bif_sclk_table[i] = pcie_table->entries[i].pcie_sclk;
+	} else {
+		/* Hardcode Pcie Table */
+		phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 0,
+				get_pcie_gen_support(data->pcie_gen_cap,
+						PP_Min_PCIEGen),
+				get_pcie_lane_support(data->pcie_lane_cap,
+						PP_Max_PCIELane));
+		phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 1,
+				get_pcie_gen_support(data->pcie_gen_cap,
+						PP_Min_PCIEGen),
+				get_pcie_lane_support(data->pcie_lane_cap,
+						PP_Max_PCIELane));
+		phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 2,
+				get_pcie_gen_support(data->pcie_gen_cap,
+						PP_Max_PCIEGen),
+				get_pcie_lane_support(data->pcie_lane_cap,
+						PP_Max_PCIELane));
+		phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 3,
+				get_pcie_gen_support(data->pcie_gen_cap,
+						PP_Max_PCIEGen),
+				get_pcie_lane_support(data->pcie_lane_cap,
+						PP_Max_PCIELane));
+		phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 4,
+				get_pcie_gen_support(data->pcie_gen_cap,
+						PP_Max_PCIEGen),
+				get_pcie_lane_support(data->pcie_lane_cap,
+						PP_Max_PCIELane));
+		phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 5,
+				get_pcie_gen_support(data->pcie_gen_cap,
+						PP_Max_PCIEGen),
+				get_pcie_lane_support(data->pcie_lane_cap,
+						PP_Max_PCIELane));
+
+		data->dpm_table.pcie_speed_table.count = 6;
+	}
+	/* Populate last level for boot PCIE level, but do not increment count. */
+	phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table,
+			data->dpm_table.pcie_speed_table.count,
+			get_pcie_gen_support(data->pcie_gen_cap,
+					PP_Min_PCIEGen),
+			get_pcie_lane_support(data->pcie_lane_cap,
+					PP_Max_PCIELane));
+
+	return 0;
+}
+
+/*
+ * This function is to initalize all DPM state tables
+ * for SMU7 based on the dependency table.
+ * Dynamic state patching function will then trim these
+ * state tables to the allowed range based
+ * on the power policy or external client requests,
+ * such as UVD request, etc.
+ */
+int polaris10_setup_default_dpm_tables(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	uint32_t i;
+
+	struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table =
+			table_info->vdd_dep_on_sclk;
+	struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table =
+			table_info->vdd_dep_on_mclk;
+
+	PP_ASSERT_WITH_CODE(dep_sclk_table != NULL,
+			"SCLK dependency table is missing. This table is mandatory",
+			return -EINVAL);
+	PP_ASSERT_WITH_CODE(dep_sclk_table->count >= 1,
+			"SCLK dependency table has to have is missing."
+			"This table is mandatory",
+			return -EINVAL);
+
+	PP_ASSERT_WITH_CODE(dep_mclk_table != NULL,
+			"MCLK dependency table is missing. This table is mandatory",
+			return -EINVAL);
+	PP_ASSERT_WITH_CODE(dep_mclk_table->count >= 1,
+			"MCLK dependency table has to have is missing."
+			"This table is mandatory",
+			return -EINVAL);
+
+	/* clear the state table to reset everything to default */
+	phm_reset_single_dpm_table(
+			&data->dpm_table.sclk_table, SMU74_MAX_LEVELS_GRAPHICS, MAX_REGULAR_DPM_NUMBER);
+	phm_reset_single_dpm_table(
+			&data->dpm_table.mclk_table, SMU74_MAX_LEVELS_MEMORY, MAX_REGULAR_DPM_NUMBER);
+
+
+	/* Initialize Sclk DPM table based on allow Sclk values */
+	data->dpm_table.sclk_table.count = 0;
+	for (i = 0; i < dep_sclk_table->count; i++) {
+		if (i == 0 || data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count - 1].value !=
+						dep_sclk_table->entries[i].clk) {
+
+			data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].value =
+					dep_sclk_table->entries[i].clk;
+
+			data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].enabled =
+					(i == 0) ? true : false;
+			data->dpm_table.sclk_table.count++;
+		}
+	}
+
+	/* Initialize Mclk DPM table based on allow Mclk values */
+	data->dpm_table.mclk_table.count = 0;
+	for (i = 0; i < dep_mclk_table->count; i++) {
+		if (i == 0 || data->dpm_table.mclk_table.dpm_levels
+				[data->dpm_table.mclk_table.count - 1].value !=
+						dep_mclk_table->entries[i].clk) {
+			data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count].value =
+							dep_mclk_table->entries[i].clk;
+			data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count].enabled =
+							(i == 0) ? true : false;
+			data->dpm_table.mclk_table.count++;
+		}
+	}
+
+	/* setup PCIE gen speed levels */
+	polaris10_setup_default_pcie_table(hwmgr);
+
+	/* save a copy of the default DPM table */
+	memcpy(&(data->golden_dpm_table), &(data->dpm_table),
+			sizeof(struct polaris10_dpm_table));
+
+	return 0;
+}
+
+uint8_t convert_to_vid(uint16_t vddc)
+{
+	return (uint8_t) ((6200 - (vddc * VOLTAGE_SCALE)) / 25);
+}
+
+/**
+ * Mvdd table preparation for SMC.
+ *
+ * @param    *hwmgr The address of the hardware manager.
+ * @param    *table The SMC DPM table structure to be populated.
+ * @return   0
+ */
+static int polaris10_populate_smc_mvdd_table(struct pp_hwmgr *hwmgr,
+			SMU74_Discrete_DpmTable *table)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	uint32_t count, level;
+
+	if (POLARIS10_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) {
+		count = data->mvdd_voltage_table.count;
+		if (count > SMU_MAX_SMIO_LEVELS)
+			count = SMU_MAX_SMIO_LEVELS;
+		for (level = 0; level < count; level++) {
+			table->SmioTable2.Pattern[level].Voltage =
+				PP_HOST_TO_SMC_US(data->mvdd_voltage_table.entries[count].value * VOLTAGE_SCALE);
+			/* Index into DpmTable.Smio. Drive bits from Smio entry to get this voltage level.*/
+			table->SmioTable2.Pattern[level].Smio =
+				(uint8_t) level;
+			table->Smio[level] |=
+				data->mvdd_voltage_table.entries[level].smio_low;
+		}
+		table->SmioMask2 = data->mvdd_voltage_table.mask_low;
+
+		table->MvddLevelCount = (uint32_t) PP_HOST_TO_SMC_UL(count);
+	}
+
+	return 0;
+}
+
+static int polaris10_populate_smc_vddci_table(struct pp_hwmgr *hwmgr,
+					struct SMU74_Discrete_DpmTable *table)
+{
+	uint32_t count, level;
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+
+	count = data->vddci_voltage_table.count;
+
+	if (POLARIS10_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) {
+		if (count > SMU_MAX_SMIO_LEVELS)
+			count = SMU_MAX_SMIO_LEVELS;
+		for (level = 0; level < count; ++level) {
+			table->SmioTable1.Pattern[level].Voltage =
+				PP_HOST_TO_SMC_US(data->vddci_voltage_table.entries[level].value * VOLTAGE_SCALE);
+			table->SmioTable1.Pattern[level].Smio = (uint8_t) level;
+
+			table->Smio[level] |= data->vddci_voltage_table.entries[level].smio_low;
+		}
+	}
+
+	table->SmioMask1 = data->vddci_voltage_table.mask_low;
+
+	return 0;
+}
+
+/**
+* Preparation of vddc and vddgfx CAC tables for SMC.
+*
+* @param    hwmgr  the address of the hardware manager
+* @param    table  the SMC DPM table structure to be populated
+* @return   always 0
+*/
+static int polaris10_populate_cac_table(struct pp_hwmgr *hwmgr,
+		struct SMU74_Discrete_DpmTable *table)
+{
+	uint32_t count;
+	uint8_t index;
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	struct phm_ppt_v1_voltage_lookup_table *lookup_table =
+			table_info->vddc_lookup_table;
+	/* tables is already swapped, so in order to use the value from it,
+	 * we need to swap it back.
+	 * We are populating vddc CAC data to BapmVddc table
+	 * in split and merged mode
+	 */
+	for (count = 0; count < lookup_table->count; count++) {
+		index = phm_get_voltage_index(lookup_table,
+				data->vddc_voltage_table.entries[count].value);
+		table->BapmVddcVidLoSidd[count] = convert_to_vid(lookup_table->entries[index].us_cac_low);
+		table->BapmVddcVidHiSidd[count] = convert_to_vid(lookup_table->entries[index].us_cac_mid);
+		table->BapmVddcVidHiSidd2[count] = convert_to_vid(lookup_table->entries[index].us_cac_high);
+	}
+
+	return 0;
+}
+
+/**
+* Preparation of voltage tables for SMC.
+*
+* @param    hwmgr   the address of the hardware manager
+* @param    table   the SMC DPM table structure to be populated
+* @return   always  0
+*/
+
+int polaris10_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr,
+		struct SMU74_Discrete_DpmTable *table)
+{
+	polaris10_populate_smc_vddci_table(hwmgr, table);
+	polaris10_populate_smc_mvdd_table(hwmgr, table);
+	polaris10_populate_cac_table(hwmgr, table);
+
+	return 0;
+}
+
+static int polaris10_populate_ulv_level(struct pp_hwmgr *hwmgr,
+		struct SMU74_Discrete_Ulv *state)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+
+	state->CcPwrDynRm = 0;
+	state->CcPwrDynRm1 = 0;
+
+	state->VddcOffset = (uint16_t) table_info->us_ulv_voltage_offset;
+	state->VddcOffsetVid = (uint8_t)(table_info->us_ulv_voltage_offset *
+			VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1);
+
+	state->VddcPhase = (data->vddc_phase_shed_control) ? 0 : 1;
+
+	CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm);
+	CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm1);
+	CONVERT_FROM_HOST_TO_SMC_US(state->VddcOffset);
+
+	return 0;
+}
+
+static int polaris10_populate_ulv_state(struct pp_hwmgr *hwmgr,
+		struct SMU74_Discrete_DpmTable *table)
+{
+	return polaris10_populate_ulv_level(hwmgr, &table->Ulv);
+}
+
+static int polaris10_populate_smc_link_level(struct pp_hwmgr *hwmgr,
+		struct SMU74_Discrete_DpmTable *table)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	struct polaris10_dpm_table *dpm_table = &data->dpm_table;
+	int i;
+
+	/* Index (dpm_table->pcie_speed_table.count)
+	 * is reserved for PCIE boot level. */
+	for (i = 0; i <= dpm_table->pcie_speed_table.count; i++) {
+		table->LinkLevel[i].PcieGenSpeed  =
+				(uint8_t)dpm_table->pcie_speed_table.dpm_levels[i].value;
+		table->LinkLevel[i].PcieLaneCount = (uint8_t)encode_pcie_lane_width(
+				dpm_table->pcie_speed_table.dpm_levels[i].param1);
+		table->LinkLevel[i].EnabledForActivity = 1;
+		table->LinkLevel[i].SPC = (uint8_t)(data->pcie_spc_cap & 0xff);
+		table->LinkLevel[i].DownThreshold = PP_HOST_TO_SMC_UL(5);
+		table->LinkLevel[i].UpThreshold = PP_HOST_TO_SMC_UL(30);
+	}
+
+	data->smc_state_table.LinkLevelCount =
+			(uint8_t)dpm_table->pcie_speed_table.count;
+	data->dpm_level_enable_mask.pcie_dpm_enable_mask =
+			phm_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table);
+
+	return 0;
+}
+
+static uint32_t polaris10_get_xclk(struct pp_hwmgr *hwmgr)
+{
+	uint32_t reference_clock, tmp;
+	struct cgs_display_info info = {0};
+	struct cgs_mode_info mode_info;
+
+	info.mode_info = &mode_info;
+
+	tmp = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_CLKPIN_CNTL_2, MUX_TCLK_TO_XCLK);
+
+	if (tmp)
+		return TCLK;
+
+	cgs_get_active_displays_info(hwmgr->device, &info);
+	reference_clock = mode_info.ref_clock;
+
+	tmp = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_CLKPIN_CNTL, XTALIN_DIVIDE);
+
+	if (0 != tmp)
+		return reference_clock / 4;
+
+	return reference_clock;
+}
+
+/**
+* Calculates the SCLK dividers using the provided engine clock
+*
+* @param    hwmgr  the address of the hardware manager
+* @param    clock  the engine clock to use to populate the structure
+* @param    sclk   the SMC SCLK structure to be populated
+*/
+static int polaris10_calculate_sclk_params(struct pp_hwmgr *hwmgr,
+		uint32_t clock, SMU_SclkSetting *sclk_setting)
+{
+	const struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	const SMU74_Discrete_DpmTable *table = &(data->smc_state_table);
+	struct pp_atomctrl_clock_dividers_ai dividers;
+
+	uint32_t ref_clock;
+	uint32_t pcc_target_percent, pcc_target_freq, ss_target_percent, ss_target_freq;
+	uint8_t i;
+	int result;
+	uint64_t temp;
+
+	sclk_setting->SclkFrequency = clock;
+	/* get the engine clock dividers for this clock value */
+	result = atomctrl_get_engine_pll_dividers_ai(hwmgr, clock,  &dividers);
+	if (result == 0) {
+		sclk_setting->Fcw_int = dividers.usSclk_fcw_int;
+		sclk_setting->Fcw_frac = dividers.usSclk_fcw_frac;
+		sclk_setting->Pcc_fcw_int = dividers.usPcc_fcw_int;
+		sclk_setting->PllRange = dividers.ucSclkPllRange;
+		sclk_setting->Sclk_slew_rate = 0x400;
+		sclk_setting->Pcc_up_slew_rate = dividers.usPcc_fcw_slew_frac;
+		sclk_setting->Pcc_down_slew_rate = 0xffff;
+		sclk_setting->SSc_En = dividers.ucSscEnable;
+		sclk_setting->Fcw1_int = dividers.usSsc_fcw1_int;
+		sclk_setting->Fcw1_frac = dividers.usSsc_fcw1_frac;
+		sclk_setting->Sclk_ss_slew_rate = dividers.usSsc_fcw_slew_frac;
+		return result;
+	}
+
+	ref_clock = polaris10_get_xclk(hwmgr);
+
+	for (i = 0; i < NUM_SCLK_RANGE; i++) {
+		if (clock > data->range_table[i].trans_lower_frequency
+		&& clock <= data->range_table[i].trans_upper_frequency) {
+			sclk_setting->PllRange = i;
+			break;
+		}
+	}
+
+	sclk_setting->Fcw_int = (uint16_t)((clock << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv) / ref_clock);
+	temp = clock << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv;
+	temp <<= 0x10;
+	do_div(temp, ref_clock);
+	sclk_setting->Fcw_frac = temp & 0xffff;
+
+	pcc_target_percent = 10; /*  Hardcode 10% for now. */
+	pcc_target_freq = clock - (clock * pcc_target_percent / 100);
+	sclk_setting->Pcc_fcw_int = (uint16_t)((pcc_target_freq << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv) / ref_clock);
+
+	ss_target_percent = 2; /*  Hardcode 2% for now. */
+	sclk_setting->SSc_En = 0;
+	if (ss_target_percent) {
+		sclk_setting->SSc_En = 1;
+		ss_target_freq = clock - (clock * ss_target_percent / 100);
+		sclk_setting->Fcw1_int = (uint16_t)((ss_target_freq << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv) / ref_clock);
+		temp = ss_target_freq << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv;
+		temp <<= 0x10;
+		do_div(temp, ref_clock);
+		sclk_setting->Fcw1_frac = temp & 0xffff;
+	}
+
+	return 0;
+}
+
+static int polaris10_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr,
+		struct phm_ppt_v1_clock_voltage_dependency_table *dep_table,
+		uint32_t clock, SMU_VoltageLevel *voltage, uint32_t *mvdd)
+{
+	uint32_t i;
+	uint16_t vddci;
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+
+	*voltage = *mvdd = 0;
+
+	/* clock - voltage dependency table is empty table */
+	if (dep_table->count == 0)
+		return -EINVAL;
+
+	for (i = 0; i < dep_table->count; i++) {
+		/* find first sclk bigger than request */
+		if (dep_table->entries[i].clk >= clock) {
+			*voltage |= (dep_table->entries[i].vddc *
+					VOLTAGE_SCALE) << VDDC_SHIFT;
+			if (POLARIS10_VOLTAGE_CONTROL_NONE == data->vddci_control)
+				*voltage |= (data->vbios_boot_state.vddci_bootup_value *
+						VOLTAGE_SCALE) << VDDCI_SHIFT;
+			else if (dep_table->entries[i].vddci)
+				*voltage |= (dep_table->entries[i].vddci *
+						VOLTAGE_SCALE) << VDDCI_SHIFT;
+			else {
+				vddci = phm_find_closest_vddci(&(data->vddci_voltage_table),
+						(dep_table->entries[i].vddc -
+								(uint16_t)data->vddc_vddci_delta));
+				*voltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT;
+			}
+
+			if (POLARIS10_VOLTAGE_CONTROL_NONE == data->mvdd_control)
+				*mvdd = data->vbios_boot_state.mvdd_bootup_value *
+					VOLTAGE_SCALE;
+			else if (dep_table->entries[i].mvdd)
+				*mvdd = (uint32_t) dep_table->entries[i].mvdd *
+					VOLTAGE_SCALE;
+
+			*voltage |= 1 << PHASES_SHIFT;
+			return 0;
+		}
+	}
+
+	/* sclk is bigger than max sclk in the dependence table */
+	*voltage |= (dep_table->entries[i - 1].vddc * VOLTAGE_SCALE) << VDDC_SHIFT;
+
+	if (POLARIS10_VOLTAGE_CONTROL_NONE == data->vddci_control)
+		*voltage |= (data->vbios_boot_state.vddci_bootup_value *
+				VOLTAGE_SCALE) << VDDCI_SHIFT;
+	else if (dep_table->entries[i-1].vddci) {
+		vddci = phm_find_closest_vddci(&(data->vddci_voltage_table),
+				(dep_table->entries[i].vddc -
+						(uint16_t)data->vddc_vddci_delta));
+		*voltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT;
+	}
+
+	if (POLARIS10_VOLTAGE_CONTROL_NONE == data->mvdd_control)
+		*mvdd = data->vbios_boot_state.mvdd_bootup_value * VOLTAGE_SCALE;
+	else if (dep_table->entries[i].mvdd)
+		*mvdd = (uint32_t) dep_table->entries[i - 1].mvdd * VOLTAGE_SCALE;
+
+	return 0;
+}
+
+static const sclkFcwRange_t Range_Table[NUM_SCLK_RANGE] =
+{ {VCO_2_4, POSTDIV_DIV_BY_16,  75, 160, 112},
+  {VCO_3_6, POSTDIV_DIV_BY_16, 112, 224, 160},
+  {VCO_2_4, POSTDIV_DIV_BY_8,   75, 160, 112},
+  {VCO_3_6, POSTDIV_DIV_BY_8,  112, 224, 160},
+  {VCO_2_4, POSTDIV_DIV_BY_4,   75, 160, 112},
+  {VCO_3_6, POSTDIV_DIV_BY_4,  112, 216, 160},
+  {VCO_2_4, POSTDIV_DIV_BY_2,   75, 160, 108},
+  {VCO_3_6, POSTDIV_DIV_BY_2,  112, 216, 160} };
+
+static void polaris10_get_sclk_range_table(struct pp_hwmgr *hwmgr)
+{
+	uint32_t i, ref_clk;
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	SMU74_Discrete_DpmTable  *table = &(data->smc_state_table);
+	struct pp_atom_ctrl_sclk_range_table range_table_from_vbios = { { {0} } };
+
+	ref_clk = polaris10_get_xclk(hwmgr);
+
+	if (0 == atomctrl_get_smc_sclk_range_table(hwmgr, &range_table_from_vbios)) {
+		for (i = 0; i < NUM_SCLK_RANGE; i++) {
+			table->SclkFcwRangeTable[i].vco_setting = range_table_from_vbios.entry[i].ucVco_setting;
+			table->SclkFcwRangeTable[i].postdiv = range_table_from_vbios.entry[i].ucPostdiv;
+			table->SclkFcwRangeTable[i].fcw_pcc = range_table_from_vbios.entry[i].usFcw_pcc;
+
+			table->SclkFcwRangeTable[i].fcw_trans_upper = range_table_from_vbios.entry[i].usFcw_trans_upper;
+			table->SclkFcwRangeTable[i].fcw_trans_lower = range_table_from_vbios.entry[i].usRcw_trans_lower;
+
+			CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_pcc);
+			CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_trans_upper);
+			CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_trans_lower);
+		}
+		return;
+	}
+
+	for (i = 0; i < NUM_SCLK_RANGE; i++) {
+
+		data->range_table[i].trans_lower_frequency = (ref_clk * Range_Table[i].fcw_trans_lower) >> Range_Table[i].postdiv;
+		data->range_table[i].trans_upper_frequency = (ref_clk * Range_Table[i].fcw_trans_upper) >> Range_Table[i].postdiv;
+
+		table->SclkFcwRangeTable[i].vco_setting = Range_Table[i].vco_setting;
+		table->SclkFcwRangeTable[i].postdiv = Range_Table[i].postdiv;
+		table->SclkFcwRangeTable[i].fcw_pcc = Range_Table[i].fcw_pcc;
+
+		table->SclkFcwRangeTable[i].fcw_trans_upper = Range_Table[i].fcw_trans_upper;
+		table->SclkFcwRangeTable[i].fcw_trans_lower = Range_Table[i].fcw_trans_lower;
+
+		CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_pcc);
+		CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_trans_upper);
+		CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_trans_lower);
+	}
+}
+
+/**
+* Populates single SMC SCLK structure using the provided engine clock
+*
+* @param    hwmgr      the address of the hardware manager
+* @param    clock the engine clock to use to populate the structure
+* @param    sclk        the SMC SCLK structure to be populated
+*/
+
+static int polaris10_populate_single_graphic_level(struct pp_hwmgr *hwmgr,
+		uint32_t clock, uint16_t sclk_al_threshold,
+		struct SMU74_Discrete_GraphicsLevel *level)
+{
+	int result, i, temp;
+	/* PP_Clocks minClocks; */
+	uint32_t mvdd;
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	SMU_SclkSetting curr_sclk_setting = { 0 };
+
+	result = polaris10_calculate_sclk_params(hwmgr, clock, &curr_sclk_setting);
+
+	/* populate graphics levels */
+	result = polaris10_get_dependency_volt_by_clk(hwmgr,
+			table_info->vdd_dep_on_sclk, clock,
+			&level->MinVoltage, &mvdd);
+
+	PP_ASSERT_WITH_CODE((0 == result),
+			"can not find VDDC voltage value for "
+			"VDDC engine clock dependency table",
+			return result);
+	level->ActivityLevel = sclk_al_threshold;
+
+	level->CcPwrDynRm = 0;
+	level->CcPwrDynRm1 = 0;
+	level->EnabledForActivity = 0;
+	level->EnabledForThrottle = 1;
+	level->UpHyst = 10;
+	level->DownHyst = 0;
+	level->VoltageDownHyst = 0;
+	level->PowerThrottle = 0;
+
+	/*
+	* TODO: get minimum clocks from dal configaration
+	* PECI_GetMinClockSettings(hwmgr->pPECI, &minClocks);
+	*/
+	/* data->DisplayTiming.minClockInSR = minClocks.engineClockInSR; */
+
+	/* get level->DeepSleepDivId
+	if (phm_cap_enabled(hwmgr->platformDescriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep))
+		level->DeepSleepDivId = PhwFiji_GetSleepDividerIdFromClock(hwmgr, clock, minClocks.engineClockInSR);
+	*/
+	PP_ASSERT_WITH_CODE((clock >= POLARIS10_MINIMUM_ENGINE_CLOCK), "Engine clock can't satisfy stutter requirement!", return 0);
+	for (i = POLARIS10_MAX_DEEPSLEEP_DIVIDER_ID;  ; i--) {
+		temp = clock >> i;
+
+		if (temp >= POLARIS10_MINIMUM_ENGINE_CLOCK || i == 0)
+			break;
+	}
+
+	level->DeepSleepDivId = i;
+
+	/* Default to slow, highest DPM level will be
+	 * set to PPSMC_DISPLAY_WATERMARK_LOW later.
+	 */
+	if (data->update_up_hyst)
+		level->UpHyst = (uint8_t)data->up_hyst;
+	if (data->update_down_hyst)
+		level->DownHyst = (uint8_t)data->down_hyst;
+
+	level->SclkSetting = curr_sclk_setting;
+
+	CONVERT_FROM_HOST_TO_SMC_UL(level->MinVoltage);
+	CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm);
+	CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm1);
+	CONVERT_FROM_HOST_TO_SMC_US(level->ActivityLevel);
+	CONVERT_FROM_HOST_TO_SMC_UL(level->SclkSetting.SclkFrequency);
+	CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw_int);
+	CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw_frac);
+	CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Pcc_fcw_int);
+	CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Sclk_slew_rate);
+	CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Pcc_up_slew_rate);
+	CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Pcc_down_slew_rate);
+	CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw1_int);
+	CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw1_frac);
+	CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Sclk_ss_slew_rate);
+	return 0;
+}
+
+/**
+* Populates all SMC SCLK levels' structure based on the trimmed allowed dpm engine clock states
+*
+* @param    hwmgr      the address of the hardware manager
+*/
+static int polaris10_populate_all_graphic_levels(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	struct polaris10_dpm_table *dpm_table = &data->dpm_table;
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	struct phm_ppt_v1_pcie_table *pcie_table = table_info->pcie_table;
+	uint8_t pcie_entry_cnt = (uint8_t) data->dpm_table.pcie_speed_table.count;
+	int result = 0;
+	uint32_t array = data->dpm_table_start +
+			offsetof(SMU74_Discrete_DpmTable, GraphicsLevel);
+	uint32_t array_size = sizeof(struct SMU74_Discrete_GraphicsLevel) *
+			SMU74_MAX_LEVELS_GRAPHICS;
+	struct SMU74_Discrete_GraphicsLevel *levels =
+			data->smc_state_table.GraphicsLevel;
+	uint32_t i, max_entry;
+	uint8_t hightest_pcie_level_enabled = 0,
+		lowest_pcie_level_enabled = 0,
+		mid_pcie_level_enabled = 0,
+		count = 0;
+
+	polaris10_get_sclk_range_table(hwmgr);
+
+	for (i = 0; i < dpm_table->sclk_table.count; i++) {
+
+		result = polaris10_populate_single_graphic_level(hwmgr,
+				dpm_table->sclk_table.dpm_levels[i].value,
+				(uint16_t)data->activity_target[i],
+				&(data->smc_state_table.GraphicsLevel[i]));
+		if (result)
+			return result;
+
+		/* Making sure only DPM level 0-1 have Deep Sleep Div ID populated. */
+		if (i > 1)
+			levels[i].DeepSleepDivId = 0;
+	}
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+					PHM_PlatformCaps_SPLLShutdownSupport))
+		data->smc_state_table.GraphicsLevel[0].SclkSetting.SSc_En = 0;
+
+	data->smc_state_table.GraphicsLevel[0].EnabledForActivity = 1;
+	data->smc_state_table.GraphicsDpmLevelCount =
+			(uint8_t)dpm_table->sclk_table.count;
+	data->dpm_level_enable_mask.sclk_dpm_enable_mask =
+			phm_get_dpm_level_enable_mask_value(&dpm_table->sclk_table);
+
+
+	if (pcie_table != NULL) {
+		PP_ASSERT_WITH_CODE((1 <= pcie_entry_cnt),
+				"There must be 1 or more PCIE levels defined in PPTable.",
+				return -EINVAL);
+		max_entry = pcie_entry_cnt - 1;
+		for (i = 0; i < dpm_table->sclk_table.count; i++)
+			levels[i].pcieDpmLevel =
+					(uint8_t) ((i < max_entry) ? i : max_entry);
+	} else {
+		while (data->dpm_level_enable_mask.pcie_dpm_enable_mask &&
+				((data->dpm_level_enable_mask.pcie_dpm_enable_mask &
+						(1 << (hightest_pcie_level_enabled + 1))) != 0))
+			hightest_pcie_level_enabled++;
+
+		while (data->dpm_level_enable_mask.pcie_dpm_enable_mask &&
+				((data->dpm_level_enable_mask.pcie_dpm_enable_mask &
+						(1 << lowest_pcie_level_enabled)) == 0))
+			lowest_pcie_level_enabled++;
+
+		while ((count < hightest_pcie_level_enabled) &&
+				((data->dpm_level_enable_mask.pcie_dpm_enable_mask &
+						(1 << (lowest_pcie_level_enabled + 1 + count))) == 0))
+			count++;
+
+		mid_pcie_level_enabled = (lowest_pcie_level_enabled + 1 + count) <
+				hightest_pcie_level_enabled ?
+						(lowest_pcie_level_enabled + 1 + count) :
+						hightest_pcie_level_enabled;
+
+		/* set pcieDpmLevel to hightest_pcie_level_enabled */
+		for (i = 2; i < dpm_table->sclk_table.count; i++)
+			levels[i].pcieDpmLevel = hightest_pcie_level_enabled;
+
+		/* set pcieDpmLevel to lowest_pcie_level_enabled */
+		levels[0].pcieDpmLevel = lowest_pcie_level_enabled;
+
+		/* set pcieDpmLevel to mid_pcie_level_enabled */
+		levels[1].pcieDpmLevel = mid_pcie_level_enabled;
+	}
+	/* level count will send to smc once at init smc table and never change */
+	result = polaris10_copy_bytes_to_smc(hwmgr->smumgr, array, (uint8_t *)levels,
+			(uint32_t)array_size, data->sram_end);
+
+	return result;
+}
+
+static int polaris10_populate_single_memory_level(struct pp_hwmgr *hwmgr,
+		uint32_t clock, struct SMU74_Discrete_MemoryLevel *mem_level)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	int result = 0;
+	struct cgs_display_info info = {0, 0, NULL};
+
+	cgs_get_active_displays_info(hwmgr->device, &info);
+
+	if (table_info->vdd_dep_on_mclk) {
+		result = polaris10_get_dependency_volt_by_clk(hwmgr,
+				table_info->vdd_dep_on_mclk, clock,
+				&mem_level->MinVoltage, &mem_level->MinMvdd);
+		PP_ASSERT_WITH_CODE((0 == result),
+				"can not find MinVddc voltage value from memory "
+				"VDDC voltage dependency table", return result);
+	}
+
+	mem_level->MclkFrequency = clock;
+	mem_level->EnabledForThrottle = 1;
+	mem_level->EnabledForActivity = 0;
+	mem_level->UpHyst = 0;
+	mem_level->DownHyst = 100;
+	mem_level->VoltageDownHyst = 0;
+	mem_level->ActivityLevel = (uint16_t)data->mclk_activity_target;
+	mem_level->StutterEnable = false;
+	mem_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
+
+	data->display_timing.num_existing_displays = info.display_count;
+
+	if ((data->mclk_stutter_mode_threshold) &&
+		(clock <= data->mclk_stutter_mode_threshold) &&
+		(PHM_READ_FIELD(hwmgr->device, DPG_PIPE_STUTTER_CONTROL,
+				STUTTER_ENABLE) & 0x1))
+		mem_level->StutterEnable = true;
+
+	if (!result) {
+		CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MinMvdd);
+		CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MclkFrequency);
+		CONVERT_FROM_HOST_TO_SMC_US(mem_level->ActivityLevel);
+		CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MinVoltage);
+	}
+	return result;
+}
+
+/**
+* Populates all SMC MCLK levels' structure based on the trimmed allowed dpm memory clock states
+*
+* @param    hwmgr      the address of the hardware manager
+*/
+static int polaris10_populate_all_memory_levels(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	struct polaris10_dpm_table *dpm_table = &data->dpm_table;
+	int result;
+	/* populate MCLK dpm table to SMU7 */
+	uint32_t array = data->dpm_table_start +
+			offsetof(SMU74_Discrete_DpmTable, MemoryLevel);
+	uint32_t array_size = sizeof(SMU74_Discrete_MemoryLevel) *
+			SMU74_MAX_LEVELS_MEMORY;
+	struct SMU74_Discrete_MemoryLevel *levels =
+			data->smc_state_table.MemoryLevel;
+	uint32_t i;
+
+	for (i = 0; i < dpm_table->mclk_table.count; i++) {
+		PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value),
+				"can not populate memory level as memory clock is zero",
+				return -EINVAL);
+		result = polaris10_populate_single_memory_level(hwmgr,
+				dpm_table->mclk_table.dpm_levels[i].value,
+				&levels[i]);
+		if (i == dpm_table->mclk_table.count - 1) {
+			levels[i].DisplayWatermark = PPSMC_DISPLAY_WATERMARK_HIGH;
+			levels[i].EnabledForActivity = 1;
+		}
+		if (result)
+			return result;
+	}
+
+	/* in order to prevent MC activity from stutter mode to push DPM up.
+	 * the UVD change complements this by putting the MCLK in
+	 * a higher state by default such that we are not effected by
+	 * up threshold or and MCLK DPM latency.
+	 */
+	levels[0].ActivityLevel = 0x1f;
+	CONVERT_FROM_HOST_TO_SMC_US(levels[0].ActivityLevel);
+
+	data->smc_state_table.MemoryDpmLevelCount =
+			(uint8_t)dpm_table->mclk_table.count;
+	data->dpm_level_enable_mask.mclk_dpm_enable_mask =
+			phm_get_dpm_level_enable_mask_value(&dpm_table->mclk_table);
+
+	/* level count will send to smc once at init smc table and never change */
+	result = polaris10_copy_bytes_to_smc(hwmgr->smumgr, array, (uint8_t *)levels,
+			(uint32_t)array_size, data->sram_end);
+
+	return result;
+}
+
+/**
+* Populates the SMC MVDD structure using the provided memory clock.
+*
+* @param    hwmgr      the address of the hardware manager
+* @param    mclk        the MCLK value to be used in the decision if MVDD should be high or low.
+* @param    voltage     the SMC VOLTAGE structure to be populated
+*/
+int polaris10_populate_mvdd_value(struct pp_hwmgr *hwmgr,
+		uint32_t mclk, SMIO_Pattern *smio_pat)
+{
+	const struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	uint32_t i = 0;
+
+	if (POLARIS10_VOLTAGE_CONTROL_NONE != data->mvdd_control) {
+		/* find mvdd value which clock is more than request */
+		for (i = 0; i < table_info->vdd_dep_on_mclk->count; i++) {
+			if (mclk <= table_info->vdd_dep_on_mclk->entries[i].clk) {
+				smio_pat->Voltage = data->mvdd_voltage_table.entries[i].value;
+				break;
+			}
+		}
+		PP_ASSERT_WITH_CODE(i < table_info->vdd_dep_on_mclk->count,
+				"MVDD Voltage is outside the supported range.",
+				return -EINVAL);
+	} else
+		return -EINVAL;
+
+	return 0;
+}
+
+static int polaris10_populate_smc_acpi_level(struct pp_hwmgr *hwmgr,
+		SMU74_Discrete_DpmTable *table)
+{
+	int result = 0;
+	uint32_t sclk_frequency;
+	const struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	SMIO_Pattern vol_level;
+	uint32_t mvdd;
+	uint16_t us_mvdd;
+
+	table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC;
+
+
+	/* Get MinVoltage and Frequency from DPM0,
+	 * already converted to SMC_UL */
+	sclk_frequency = data->dpm_table.sclk_table.dpm_levels[0].value;
+	result = polaris10_get_dependency_volt_by_clk(hwmgr,
+			table_info->vdd_dep_on_sclk,
+			sclk_frequency,
+			&table->ACPILevel.MinVoltage, &mvdd);
+	PP_ASSERT_WITH_CODE((0 == result),
+			"Cannot find ACPI VDDC voltage value "
+			"in Clock Dependency Table",
+			);
+
+
+	result = polaris10_calculate_sclk_params(hwmgr, sclk_frequency,  &(table->ACPILevel.SclkSetting));
+	PP_ASSERT_WITH_CODE(result == 0, "Error retrieving Engine Clock dividers from VBIOS.", return result);
+
+	table->ACPILevel.DeepSleepDivId = 0;
+	table->ACPILevel.CcPwrDynRm = 0;
+	table->ACPILevel.CcPwrDynRm1 = 0;
+
+	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.Flags);
+	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.MinVoltage);
+	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm);
+	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm1);
+
+	CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SclkSetting.SclkFrequency);
+	CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw_int);
+	CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw_frac);
+	CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Pcc_fcw_int);
+	CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Sclk_slew_rate);
+	CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Pcc_up_slew_rate);
+	CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Pcc_down_slew_rate);
+	CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw1_int);
+	CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw1_frac);
+	CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Sclk_ss_slew_rate);
+
+
+	/* Get MinVoltage and Frequency from DPM0, already converted to SMC_UL */
+	table->MemoryACPILevel.MclkFrequency =
+			data->dpm_table.mclk_table.dpm_levels[0].value;
+	result = polaris10_get_dependency_volt_by_clk(hwmgr,
+			table_info->vdd_dep_on_mclk,
+			table->MemoryACPILevel.MclkFrequency,
+			&table->MemoryACPILevel.MinVoltage, &mvdd);
+	PP_ASSERT_WITH_CODE((0 == result),
+			"Cannot find ACPI VDDCI voltage value "
+			"in Clock Dependency Table",
+			);
+
+	us_mvdd = 0;
+	if ((POLARIS10_VOLTAGE_CONTROL_NONE == data->mvdd_control) ||
+			(data->mclk_dpm_key_disabled))
+		us_mvdd = data->vbios_boot_state.mvdd_bootup_value;
+	else {
+		if (!polaris10_populate_mvdd_value(hwmgr,
+				data->dpm_table.mclk_table.dpm_levels[0].value,
+				&vol_level))
+			us_mvdd = vol_level.Voltage;
+	}
+
+	if (0 == polaris10_populate_mvdd_value(hwmgr, 0, &vol_level))
+		table->MemoryACPILevel.MinMvdd = PP_HOST_TO_SMC_UL(vol_level.Voltage);
+	else
+		table->MemoryACPILevel.MinMvdd = 0;
+
+	table->MemoryACPILevel.StutterEnable = false;
+
+	table->MemoryACPILevel.EnabledForThrottle = 0;
+	table->MemoryACPILevel.EnabledForActivity = 0;
+	table->MemoryACPILevel.UpHyst = 0;
+	table->MemoryACPILevel.DownHyst = 100;
+	table->MemoryACPILevel.VoltageDownHyst = 0;
+	table->MemoryACPILevel.ActivityLevel =
+			PP_HOST_TO_SMC_US((uint16_t)data->mclk_activity_target);
+
+	CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MclkFrequency);
+	CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MinVoltage);
+
+	return result;
+}
+
+static int polaris10_populate_smc_vce_level(struct pp_hwmgr *hwmgr,
+		SMU74_Discrete_DpmTable *table)
+{
+	int result = -EINVAL;
+	uint8_t count;
+	struct pp_atomctrl_clock_dividers_vi dividers;
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table =
+			table_info->mm_dep_table;
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	uint32_t vddci;
+
+	table->VceLevelCount = (uint8_t)(mm_table->count);
+	table->VceBootLevel = 0;
+
+	for (count = 0; count < table->VceLevelCount; count++) {
+		table->VceLevel[count].Frequency = mm_table->entries[count].eclk;
+		table->VceLevel[count].MinVoltage = 0;
+		table->VceLevel[count].MinVoltage |=
+				(mm_table->entries[count].vddc * VOLTAGE_SCALE) << VDDC_SHIFT;
+
+		if (POLARIS10_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control)
+			vddci = (uint32_t)phm_find_closest_vddci(&(data->vddci_voltage_table),
+						mm_table->entries[count].vddc - VDDC_VDDCI_DELTA);
+		else if (POLARIS10_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control)
+			vddci = mm_table->entries[count].vddc - VDDC_VDDCI_DELTA;
+		else
+			vddci = (data->vbios_boot_state.vddci_bootup_value * VOLTAGE_SCALE) << VDDCI_SHIFT;
+
+
+		table->VceLevel[count].MinVoltage |=
+				(vddci * VOLTAGE_SCALE) << VDDCI_SHIFT;
+		table->VceLevel[count].MinVoltage |= 1 << PHASES_SHIFT;
+
+		/*retrieve divider value for VBIOS */
+		result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
+				table->VceLevel[count].Frequency, &dividers);
+		PP_ASSERT_WITH_CODE((0 == result),
+				"can not find divide id for VCE engine clock",
+				return result);
+
+		table->VceLevel[count].Divider = (uint8_t)dividers.pll_post_divider;
+
+		CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].Frequency);
+		CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].MinVoltage);
+	}
+	return result;
+}
+
+static int polaris10_populate_smc_samu_level(struct pp_hwmgr *hwmgr,
+		SMU74_Discrete_DpmTable *table)
+{
+	int result = -EINVAL;
+	uint8_t count;
+	struct pp_atomctrl_clock_dividers_vi dividers;
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table =
+			table_info->mm_dep_table;
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	uint32_t vddci;
+
+	table->SamuBootLevel = 0;
+	table->SamuLevelCount = (uint8_t)(mm_table->count);
+
+	for (count = 0; count < table->SamuLevelCount; count++) {
+		/* not sure whether we need evclk or not */
+		table->SamuLevel[count].MinVoltage = 0;
+		table->SamuLevel[count].Frequency = mm_table->entries[count].samclock;
+		table->SamuLevel[count].MinVoltage |= (mm_table->entries[count].vddc *
+				VOLTAGE_SCALE) << VDDC_SHIFT;
+
+		if (POLARIS10_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control)
+			vddci = (uint32_t)phm_find_closest_vddci(&(data->vddci_voltage_table),
+						mm_table->entries[count].vddc - VDDC_VDDCI_DELTA);
+		else if (POLARIS10_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control)
+			vddci = mm_table->entries[count].vddc - VDDC_VDDCI_DELTA;
+		else
+			vddci = (data->vbios_boot_state.vddci_bootup_value * VOLTAGE_SCALE) << VDDCI_SHIFT;
+
+		table->SamuLevel[count].MinVoltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT;
+		table->SamuLevel[count].MinVoltage |= 1 << PHASES_SHIFT;
+
+		/* retrieve divider value for VBIOS */
+		result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
+				table->SamuLevel[count].Frequency, &dividers);
+		PP_ASSERT_WITH_CODE((0 == result),
+				"can not find divide id for samu clock", return result);
+
+		table->SamuLevel[count].Divider = (uint8_t)dividers.pll_post_divider;
+
+		CONVERT_FROM_HOST_TO_SMC_UL(table->SamuLevel[count].Frequency);
+		CONVERT_FROM_HOST_TO_SMC_UL(table->SamuLevel[count].MinVoltage);
+	}
+	return result;
+}
+
+static int polaris10_populate_memory_timing_parameters(struct pp_hwmgr *hwmgr,
+		int32_t eng_clock, int32_t mem_clock,
+		SMU74_Discrete_MCArbDramTimingTableEntry *arb_regs)
+{
+	uint32_t dram_timing;
+	uint32_t dram_timing2;
+	uint32_t burst_time;
+	int result;
+
+	result = atomctrl_set_engine_dram_timings_rv770(hwmgr,
+			eng_clock, mem_clock);
+	PP_ASSERT_WITH_CODE(result == 0,
+			"Error calling VBIOS to set DRAM_TIMING.", return result);
+
+	dram_timing = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING);
+	dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2);
+	burst_time = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0);
+
+
+	arb_regs->McArbDramTiming  = PP_HOST_TO_SMC_UL(dram_timing);
+	arb_regs->McArbDramTiming2 = PP_HOST_TO_SMC_UL(dram_timing2);
+	arb_regs->McArbBurstTime   = (uint8_t)burst_time;
+
+	return 0;
+}
+
+static int polaris10_program_memory_timing_parameters(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	struct SMU74_Discrete_MCArbDramTimingTable arb_regs;
+	uint32_t i, j;
+	int result = 0;
+
+	for (i = 0; i < data->dpm_table.sclk_table.count; i++) {
+		for (j = 0; j < data->dpm_table.mclk_table.count; j++) {
+			result = polaris10_populate_memory_timing_parameters(hwmgr,
+					data->dpm_table.sclk_table.dpm_levels[i].value,
+					data->dpm_table.mclk_table.dpm_levels[j].value,
+					&arb_regs.entries[i][j]);
+			if (result == 0)
+				result = atomctrl_set_ac_timing_ai(hwmgr, data->dpm_table.mclk_table.dpm_levels[j].value, j);
+			if (result != 0)
+				return result;
+		}
+	}
+
+	result = polaris10_copy_bytes_to_smc(
+			hwmgr->smumgr,
+			data->arb_table_start,
+			(uint8_t *)&arb_regs,
+			sizeof(SMU74_Discrete_MCArbDramTimingTable),
+			data->sram_end);
+	return result;
+}
+
+static int polaris10_populate_smc_uvd_level(struct pp_hwmgr *hwmgr,
+		struct SMU74_Discrete_DpmTable *table)
+{
+	int result = -EINVAL;
+	uint8_t count;
+	struct pp_atomctrl_clock_dividers_vi dividers;
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table =
+			table_info->mm_dep_table;
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	uint32_t vddci;
+
+	table->UvdLevelCount = (uint8_t)(mm_table->count);
+	table->UvdBootLevel = 0;
+
+	for (count = 0; count < table->UvdLevelCount; count++) {
+		table->UvdLevel[count].MinVoltage = 0;
+		table->UvdLevel[count].VclkFrequency = mm_table->entries[count].vclk;
+		table->UvdLevel[count].DclkFrequency = mm_table->entries[count].dclk;
+		table->UvdLevel[count].MinVoltage |= (mm_table->entries[count].vddc *
+				VOLTAGE_SCALE) << VDDC_SHIFT;
+
+		if (POLARIS10_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control)
+			vddci = (uint32_t)phm_find_closest_vddci(&(data->vddci_voltage_table),
+						mm_table->entries[count].vddc - VDDC_VDDCI_DELTA);
+		else if (POLARIS10_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control)
+			vddci = mm_table->entries[count].vddc - VDDC_VDDCI_DELTA;
+		else
+			vddci = (data->vbios_boot_state.vddci_bootup_value * VOLTAGE_SCALE) << VDDCI_SHIFT;
+
+		table->UvdLevel[count].MinVoltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT;
+		table->UvdLevel[count].MinVoltage |= 1 << PHASES_SHIFT;
+
+		/* retrieve divider value for VBIOS */
+		result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
+				table->UvdLevel[count].VclkFrequency, &dividers);
+		PP_ASSERT_WITH_CODE((0 == result),
+				"can not find divide id for Vclk clock", return result);
+
+		table->UvdLevel[count].VclkDivider = (uint8_t)dividers.pll_post_divider;
+
+		result = atomctrl_get_dfs_pll_dividers_vi(hwmgr,
+				table->UvdLevel[count].DclkFrequency, &dividers);
+		PP_ASSERT_WITH_CODE((0 == result),
+				"can not find divide id for Dclk clock", return result);
+
+		table->UvdLevel[count].DclkDivider = (uint8_t)dividers.pll_post_divider;
+
+		CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].VclkFrequency);
+		CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].DclkFrequency);
+		CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].MinVoltage);
+	}
+
+	return result;
+}
+
+static int polaris10_populate_smc_boot_level(struct pp_hwmgr *hwmgr,
+		struct SMU74_Discrete_DpmTable *table)
+{
+	int result = 0;
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+
+	table->GraphicsBootLevel = 0;
+	table->MemoryBootLevel = 0;
+
+	/* find boot level from dpm table */
+	result = phm_find_boot_level(&(data->dpm_table.sclk_table),
+			data->vbios_boot_state.sclk_bootup_value,
+			(uint32_t *)&(table->GraphicsBootLevel));
+
+	result = phm_find_boot_level(&(data->dpm_table.mclk_table),
+			data->vbios_boot_state.mclk_bootup_value,
+			(uint32_t *)&(table->MemoryBootLevel));
+
+	table->BootVddc  = data->vbios_boot_state.vddc_bootup_value *
+			VOLTAGE_SCALE;
+	table->BootVddci = data->vbios_boot_state.vddci_bootup_value *
+			VOLTAGE_SCALE;
+	table->BootMVdd  = data->vbios_boot_state.mvdd_bootup_value *
+			VOLTAGE_SCALE;
+
+	CONVERT_FROM_HOST_TO_SMC_US(table->BootVddc);
+	CONVERT_FROM_HOST_TO_SMC_US(table->BootVddci);
+	CONVERT_FROM_HOST_TO_SMC_US(table->BootMVdd);
+
+	return 0;
+}
+
+
+static int polaris10_populate_smc_initailial_state(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	uint8_t count, level;
+
+	count = (uint8_t)(table_info->vdd_dep_on_sclk->count);
+
+	for (level = 0; level < count; level++) {
+		if (table_info->vdd_dep_on_sclk->entries[level].clk >=
+				data->vbios_boot_state.sclk_bootup_value) {
+			data->smc_state_table.GraphicsBootLevel = level;
+			break;
+		}
+	}
+
+	count = (uint8_t)(table_info->vdd_dep_on_mclk->count);
+	for (level = 0; level < count; level++) {
+		if (table_info->vdd_dep_on_mclk->entries[level].clk >=
+				data->vbios_boot_state.mclk_bootup_value) {
+			data->smc_state_table.MemoryBootLevel = level;
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static int polaris10_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr)
+{
+	uint32_t ro, efuse, volt_without_cks, volt_with_cks, value, max, min;
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	uint8_t i, stretch_amount, stretch_amount2, volt_offset = 0;
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table =
+			table_info->vdd_dep_on_sclk;
+
+	stretch_amount = (uint8_t)table_info->cac_dtp_table->usClockStretchAmount;
+
+	/* Read SMU_Eefuse to read and calculate RO and determine
+	 * if the part is SS or FF. if RO >= 1660MHz, part is FF.
+	 */
+	efuse = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+			ixSMU_EFUSE_0 + (67 * 4));
+	efuse &= 0xFF000000;
+	efuse = efuse >> 24;
+
+	if (hwmgr->chip_id == CHIP_POLARIS10) {
+		min = 1000;
+		max = 2300;
+	} else {
+		min = 1100;
+		max = 2100;
+	}
+
+	ro = efuse * (max -min)/255 + min;
+
+	/* Populate Sclk_CKS_masterEn0_7 and Sclk_voltageOffset */
+	for (i = 0; i < sclk_table->count; i++) {
+		data->smc_state_table.Sclk_CKS_masterEn0_7 |=
+				sclk_table->entries[i].cks_enable << i;
+		if (hwmgr->chip_id == CHIP_POLARIS10) {
+			volt_without_cks = (uint32_t)((2753594000U + (sclk_table->entries[i].clk/100) * 136418 -(ro - 70) * 1000000) / \
+						(2424180 - (sclk_table->entries[i].clk/100) * 1132925/1000));
+			volt_with_cks = (uint32_t)((2797202000U + sclk_table->entries[i].clk/100 * 3232 - (ro - 65) * 1000000) / \
+					(2522480 - sclk_table->entries[i].clk/100 * 115764/100));
+		} else {
+			volt_without_cks = (uint32_t)((2416794800U + (sclk_table->entries[i].clk/100) * 1476925/10 -(ro - 50) * 1000000) / \
+						(2625416 - (sclk_table->entries[i].clk/100) * (12586807/10000)));
+			volt_with_cks = (uint32_t)((2999656000U - sclk_table->entries[i].clk/100 * 392803 - (ro - 44) * 1000000) / \
+					(3422454 - sclk_table->entries[i].clk/100 * (18886376/10000)));
+		}
+
+		if (volt_without_cks >= volt_with_cks)
+			volt_offset = (uint8_t)(((volt_without_cks - volt_with_cks +
+					sclk_table->entries[i].cks_voffset) * 100 + 624) / 625);
+
+		data->smc_state_table.Sclk_voltageOffset[i] = volt_offset;
+	}
+
+	data->smc_state_table.LdoRefSel = (table_info->cac_dtp_table->ucCKS_LDO_REFSEL != 0) ? table_info->cac_dtp_table->ucCKS_LDO_REFSEL : 6;
+	/* Populate CKS Lookup Table */
+	if (stretch_amount == 1 || stretch_amount == 2 || stretch_amount == 5)
+		stretch_amount2 = 0;
+	else if (stretch_amount == 3 || stretch_amount == 4)
+		stretch_amount2 = 1;
+	else {
+		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_ClockStretcher);
+		PP_ASSERT_WITH_CODE(false,
+				"Stretch Amount in PPTable not supported\n",
+				return -EINVAL);
+	}
+
+	value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL);
+	value &= 0xFFFFFFFE;
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL, value);
+
+	return 0;
+}
+
+/**
+* Populates the SMC VRConfig field in DPM table.
+*
+* @param    hwmgr   the address of the hardware manager
+* @param    table   the SMC DPM table structure to be populated
+* @return   always 0
+*/
+static int polaris10_populate_vr_config(struct pp_hwmgr *hwmgr,
+		struct SMU74_Discrete_DpmTable *table)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	uint16_t config;
+
+	config = VR_MERGED_WITH_VDDC;
+	table->VRConfig |= (config << VRCONF_VDDGFX_SHIFT);
+
+	/* Set Vddc Voltage Controller */
+	if (POLARIS10_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) {
+		config = VR_SVI2_PLANE_1;
+		table->VRConfig |= config;
+	} else {
+		PP_ASSERT_WITH_CODE(false,
+				"VDDC should be on SVI2 control in merged mode!",
+				);
+	}
+	/* Set Vddci Voltage Controller */
+	if (POLARIS10_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) {
+		config = VR_SVI2_PLANE_2;  /* only in merged mode */
+		table->VRConfig |= (config << VRCONF_VDDCI_SHIFT);
+	} else if (POLARIS10_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) {
+		config = VR_SMIO_PATTERN_1;
+		table->VRConfig |= (config << VRCONF_VDDCI_SHIFT);
+	} else {
+		config = VR_STATIC_VOLTAGE;
+		table->VRConfig |= (config << VRCONF_VDDCI_SHIFT);
+	}
+	/* Set Mvdd Voltage Controller */
+	if (POLARIS10_VOLTAGE_CONTROL_BY_SVID2 == data->mvdd_control) {
+		config = VR_SVI2_PLANE_2;
+		table->VRConfig |= (config << VRCONF_MVDD_SHIFT);
+	} else if (POLARIS10_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) {
+		config = VR_SMIO_PATTERN_2;
+		table->VRConfig |= (config << VRCONF_MVDD_SHIFT);
+	} else {
+		config = VR_STATIC_VOLTAGE;
+		table->VRConfig |= (config << VRCONF_MVDD_SHIFT);
+	}
+
+	return 0;
+}
+
+
+int polaris10_populate_avfs_parameters(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	SMU74_Discrete_DpmTable  *table = &(data->smc_state_table);
+	int result = 0;
+	struct pp_atom_ctrl__avfs_parameters avfs_params = {0};
+	AVFS_meanNsigma_t AVFS_meanNsigma = { {0} };
+	AVFS_Sclk_Offset_t AVFS_SclkOffset = { {0} };
+	uint32_t tmp, i;
+	struct pp_smumgr *smumgr = hwmgr->smumgr;
+	struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend);
+
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)hwmgr->pptable;
+	struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table =
+			table_info->vdd_dep_on_sclk;
+
+
+	if (smu_data->avfs.avfs_btc_status == AVFS_BTC_NOTSUPPORTED)
+		return result;
+
+	result = atomctrl_get_avfs_information(hwmgr, &avfs_params);
+
+	if (0 == result) {
+		table->BTCGB_VDROOP_TABLE[0].a0  = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSON_a0);
+		table->BTCGB_VDROOP_TABLE[0].a1  = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSON_a1);
+		table->BTCGB_VDROOP_TABLE[0].a2  = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSON_a2);
+		table->BTCGB_VDROOP_TABLE[1].a0  = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a0);
+		table->BTCGB_VDROOP_TABLE[1].a1  = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a1);
+		table->BTCGB_VDROOP_TABLE[1].a2  = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a2);
+		table->AVFSGB_VDROOP_TABLE[0].m1 = PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSON_m1);
+		table->AVFSGB_VDROOP_TABLE[0].m2 = PP_HOST_TO_SMC_US(avfs_params.usAVFSGB_FUSE_TABLE_CKSON_m2);
+		table->AVFSGB_VDROOP_TABLE[0].b  = PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSON_b);
+		table->AVFSGB_VDROOP_TABLE[0].m1_shift = 24;
+		table->AVFSGB_VDROOP_TABLE[0].m2_shift  = 12;
+		table->AVFSGB_VDROOP_TABLE[1].m1 = PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_m1);
+		table->AVFSGB_VDROOP_TABLE[1].m2 = PP_HOST_TO_SMC_US(avfs_params.usAVFSGB_FUSE_TABLE_CKSOFF_m2);
+		table->AVFSGB_VDROOP_TABLE[1].b  = PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_b);
+		table->AVFSGB_VDROOP_TABLE[1].m1_shift = 24;
+		table->AVFSGB_VDROOP_TABLE[1].m2_shift  = 12;
+		table->MaxVoltage                = PP_HOST_TO_SMC_US(avfs_params.usMaxVoltage_0_25mv);
+		AVFS_meanNsigma.Aconstant[0]      = PP_HOST_TO_SMC_UL(avfs_params.ulAVFS_meanNsigma_Acontant0);
+		AVFS_meanNsigma.Aconstant[1]      = PP_HOST_TO_SMC_UL(avfs_params.ulAVFS_meanNsigma_Acontant1);
+		AVFS_meanNsigma.Aconstant[2]      = PP_HOST_TO_SMC_UL(avfs_params.ulAVFS_meanNsigma_Acontant2);
+		AVFS_meanNsigma.DC_tol_sigma      = PP_HOST_TO_SMC_US(avfs_params.usAVFS_meanNsigma_DC_tol_sigma);
+		AVFS_meanNsigma.Platform_mean     = PP_HOST_TO_SMC_US(avfs_params.usAVFS_meanNsigma_Platform_mean);
+		AVFS_meanNsigma.PSM_Age_CompFactor = PP_HOST_TO_SMC_US(avfs_params.usPSM_Age_ComFactor);
+		AVFS_meanNsigma.Platform_sigma     = PP_HOST_TO_SMC_US(avfs_params.usAVFS_meanNsigma_Platform_sigma);
+
+		for (i = 0; i < NUM_VFT_COLUMNS; i++) {
+			AVFS_meanNsigma.Static_Voltage_Offset[i] = (uint8_t)(sclk_table->entries[i].cks_voffset * 100 / 625);
+			AVFS_SclkOffset.Sclk_Offset[i] = PP_HOST_TO_SMC_US((uint16_t)(sclk_table->entries[i].sclk_offset) / 100);
+		}
+
+		result = polaris10_read_smc_sram_dword(smumgr,
+				SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU74_Firmware_Header, AvfsMeanNSigma),
+				&tmp, data->sram_end);
+
+		polaris10_copy_bytes_to_smc(smumgr,
+					tmp,
+					(uint8_t *)&AVFS_meanNsigma,
+					sizeof(AVFS_meanNsigma_t),
+					data->sram_end);
+
+		result = polaris10_read_smc_sram_dword(smumgr,
+				SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU74_Firmware_Header, AvfsSclkOffsetTable),
+				&tmp, data->sram_end);
+		polaris10_copy_bytes_to_smc(smumgr,
+					tmp,
+					(uint8_t *)&AVFS_SclkOffset,
+					sizeof(AVFS_Sclk_Offset_t),
+					data->sram_end);
+
+		data->avfs_vdroop_override_setting = (avfs_params.ucEnableGB_VDROOP_TABLE_CKSON << BTCGB0_Vdroop_Enable_SHIFT) |
+						(avfs_params.ucEnableGB_VDROOP_TABLE_CKSOFF << BTCGB1_Vdroop_Enable_SHIFT) |
+						(avfs_params.ucEnableGB_FUSE_TABLE_CKSON << AVFSGB0_Vdroop_Enable_SHIFT) |
+						(avfs_params.ucEnableGB_FUSE_TABLE_CKSOFF << AVFSGB1_Vdroop_Enable_SHIFT);
+		data->apply_avfs_cks_off_voltage = (avfs_params.ucEnableApplyAVFS_CKS_OFF_Voltage == 1) ? true : false;
+	}
+	return result;
+}
+
+
+/**
+* Initializes the SMC table and uploads it
+*
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @return   always 0
+*/
+static int polaris10_init_smc_table(struct pp_hwmgr *hwmgr)
+{
+	int result;
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	struct SMU74_Discrete_DpmTable *table = &(data->smc_state_table);
+	const struct polaris10_ulv_parm *ulv = &(data->ulv);
+	uint8_t i;
+	struct pp_atomctrl_gpio_pin_assignment gpio_pin;
+	pp_atomctrl_clock_dividers_vi dividers;
+
+	result = polaris10_setup_default_dpm_tables(hwmgr);
+	PP_ASSERT_WITH_CODE(0 == result,
+			"Failed to setup default DPM tables!", return result);
+
+	if (POLARIS10_VOLTAGE_CONTROL_NONE != data->voltage_control)
+		polaris10_populate_smc_voltage_tables(hwmgr, table);
+
+	table->SystemFlags = 0;
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_AutomaticDCTransition))
+		table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC;
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_StepVddc))
+		table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC;
+
+	if (data->is_memory_gddr5)
+		table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5;
+
+	if (ulv->ulv_supported && table_info->us_ulv_voltage_offset) {
+		result = polaris10_populate_ulv_state(hwmgr, table);
+		PP_ASSERT_WITH_CODE(0 == result,
+				"Failed to initialize ULV state!", return result);
+		cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+				ixCG_ULV_PARAMETER, PPPOLARIS10_CGULVPARAMETER_DFLT);
+	}
+
+	result = polaris10_populate_smc_link_level(hwmgr, table);
+	PP_ASSERT_WITH_CODE(0 == result,
+			"Failed to initialize Link Level!", return result);
+
+	result = polaris10_populate_all_graphic_levels(hwmgr);
+	PP_ASSERT_WITH_CODE(0 == result,
+			"Failed to initialize Graphics Level!", return result);
+
+	result = polaris10_populate_all_memory_levels(hwmgr);
+	PP_ASSERT_WITH_CODE(0 == result,
+			"Failed to initialize Memory Level!", return result);
+
+	result = polaris10_populate_smc_acpi_level(hwmgr, table);
+	PP_ASSERT_WITH_CODE(0 == result,
+			"Failed to initialize ACPI Level!", return result);
+
+	result = polaris10_populate_smc_vce_level(hwmgr, table);
+	PP_ASSERT_WITH_CODE(0 == result,
+			"Failed to initialize VCE Level!", return result);
+
+	result = polaris10_populate_smc_samu_level(hwmgr, table);
+	PP_ASSERT_WITH_CODE(0 == result,
+			"Failed to initialize SAMU Level!", return result);
+
+	/* Since only the initial state is completely set up at this point
+	 * (the other states are just copies of the boot state) we only
+	 * need to populate the  ARB settings for the initial state.
+	 */
+	result = polaris10_program_memory_timing_parameters(hwmgr);
+	PP_ASSERT_WITH_CODE(0 == result,
+			"Failed to Write ARB settings for the initial state.", return result);
+
+	result = polaris10_populate_smc_uvd_level(hwmgr, table);
+	PP_ASSERT_WITH_CODE(0 == result,
+			"Failed to initialize UVD Level!", return result);
+
+	result = polaris10_populate_smc_boot_level(hwmgr, table);
+	PP_ASSERT_WITH_CODE(0 == result,
+			"Failed to initialize Boot Level!", return result);
+
+	result = polaris10_populate_smc_initailial_state(hwmgr);
+	PP_ASSERT_WITH_CODE(0 == result,
+			"Failed to initialize Boot State!", return result);
+
+	result = polaris10_populate_bapm_parameters_in_dpm_table(hwmgr);
+	PP_ASSERT_WITH_CODE(0 == result,
+			"Failed to populate BAPM Parameters!", return result);
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_ClockStretcher)) {
+		result = polaris10_populate_clock_stretcher_data_table(hwmgr);
+		PP_ASSERT_WITH_CODE(0 == result,
+				"Failed to populate Clock Stretcher Data Table!",
+				return result);
+	}
+
+	result = polaris10_populate_avfs_parameters(hwmgr);
+	PP_ASSERT_WITH_CODE(0 == result, "Failed to populate AVFS Parameters!", return result;);
+
+	table->CurrSclkPllRange = 0xff;
+	table->GraphicsVoltageChangeEnable  = 1;
+	table->GraphicsThermThrottleEnable  = 1;
+	table->GraphicsInterval = 1;
+	table->VoltageInterval  = 1;
+	table->ThermalInterval  = 1;
+	table->TemperatureLimitHigh =
+			table_info->cac_dtp_table->usTargetOperatingTemp *
+			POLARIS10_Q88_FORMAT_CONVERSION_UNIT;
+	table->TemperatureLimitLow  =
+			(table_info->cac_dtp_table->usTargetOperatingTemp - 1) *
+			POLARIS10_Q88_FORMAT_CONVERSION_UNIT;
+	table->MemoryVoltageChangeEnable = 1;
+	table->MemoryInterval = 1;
+	table->VoltageResponseTime = 0;
+	table->PhaseResponseTime = 0;
+	table->MemoryThermThrottleEnable = 1;
+	table->PCIeBootLinkLevel = 0;
+	table->PCIeGenInterval = 1;
+	table->VRConfig = 0;
+
+	result = polaris10_populate_vr_config(hwmgr, table);
+	PP_ASSERT_WITH_CODE(0 == result,
+			"Failed to populate VRConfig setting!", return result);
+
+	table->ThermGpio = 17;
+	table->SclkStepSize = 0x4000;
+
+	if (atomctrl_get_pp_assign_pin(hwmgr, VDDC_VRHOT_GPIO_PINID, &gpio_pin)) {
+		table->VRHotGpio = gpio_pin.uc_gpio_pin_bit_shift;
+	} else {
+		table->VRHotGpio = POLARIS10_UNUSED_GPIO_PIN;
+		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_RegulatorHot);
+	}
+
+	if (atomctrl_get_pp_assign_pin(hwmgr, PP_AC_DC_SWITCH_GPIO_PINID,
+			&gpio_pin)) {
+		table->AcDcGpio = gpio_pin.uc_gpio_pin_bit_shift;
+		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_AutomaticDCTransition);
+	} else {
+		table->AcDcGpio = POLARIS10_UNUSED_GPIO_PIN;
+		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_AutomaticDCTransition);
+	}
+
+	/* Thermal Output GPIO */
+	if (atomctrl_get_pp_assign_pin(hwmgr, THERMAL_INT_OUTPUT_GPIO_PINID,
+			&gpio_pin)) {
+		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_ThermalOutGPIO);
+
+		table->ThermOutGpio = gpio_pin.uc_gpio_pin_bit_shift;
+
+		/* For porlarity read GPIOPAD_A with assigned Gpio pin
+		 * since VBIOS will program this register to set 'inactive state',
+		 * driver can then determine 'active state' from this and
+		 * program SMU with correct polarity
+		 */
+		table->ThermOutPolarity = (0 == (cgs_read_register(hwmgr->device, mmGPIOPAD_A)
+					& (1 << gpio_pin.uc_gpio_pin_bit_shift))) ? 1:0;
+		table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_ONLY;
+
+		/* if required, combine VRHot/PCC with thermal out GPIO */
+		if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_RegulatorHot)
+		&& phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_CombinePCCWithThermalSignal))
+			table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_VRHOT;
+	} else {
+		table->ThermOutGpio = 17;
+		table->ThermOutPolarity = 1;
+		table->ThermOutMode = SMU7_THERM_OUT_MODE_DISABLE;
+	}
+
+	/* Populate BIF_SCLK levels into SMC DPM table */
+	for (i = 0; i <= data->dpm_table.pcie_speed_table.count; i++) {
+		result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, data->bif_sclk_table[i], &dividers);
+		PP_ASSERT_WITH_CODE((result == 0), "Can not find DFS divide id for Sclk", return result);
+
+		if (i == 0)
+			table->Ulv.BifSclkDfs = PP_HOST_TO_SMC_US((USHORT)(dividers.pll_post_divider));
+		else
+			table->LinkLevel[i-1].BifSclkDfs = PP_HOST_TO_SMC_US((USHORT)(dividers.pll_post_divider));
+	}
+
+	for (i = 0; i < SMU74_MAX_ENTRIES_SMIO; i++)
+		table->Smio[i] = PP_HOST_TO_SMC_UL(table->Smio[i]);
+
+	CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags);
+	CONVERT_FROM_HOST_TO_SMC_UL(table->VRConfig);
+	CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask1);
+	CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask2);
+	CONVERT_FROM_HOST_TO_SMC_UL(table->SclkStepSize);
+	CONVERT_FROM_HOST_TO_SMC_UL(table->CurrSclkPllRange);
+	CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitHigh);
+	CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitLow);
+	CONVERT_FROM_HOST_TO_SMC_US(table->VoltageResponseTime);
+	CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime);
+
+	/* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */
+	result = polaris10_copy_bytes_to_smc(hwmgr->smumgr,
+			data->dpm_table_start +
+			offsetof(SMU74_Discrete_DpmTable, SystemFlags),
+			(uint8_t *)&(table->SystemFlags),
+			sizeof(SMU74_Discrete_DpmTable) - 3 * sizeof(SMU74_PIDController),
+			data->sram_end);
+	PP_ASSERT_WITH_CODE(0 == result,
+			"Failed to upload dpm data to SMC memory!", return result);
+
+	return 0;
+}
+
+/**
+* Initialize the ARB DRAM timing table's index field.
+*
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @return   always 0
+*/
+static int polaris10_init_arb_table_index(struct pp_hwmgr *hwmgr)
+{
+	const struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	uint32_t tmp;
+	int result;
+
+	/* This is a read-modify-write on the first byte of the ARB table.
+	 * The first byte in the SMU73_Discrete_MCArbDramTimingTable structure
+	 * is the field 'current'.
+	 * This solution is ugly, but we never write the whole table only
+	 * individual fields in it.
+	 * In reality this field should not be in that structure
+	 * but in a soft register.
+	 */
+	result = polaris10_read_smc_sram_dword(hwmgr->smumgr,
+			data->arb_table_start, &tmp, data->sram_end);
+
+	if (result)
+		return result;
+
+	tmp &= 0x00FFFFFF;
+	tmp |= ((uint32_t)MC_CG_ARB_FREQ_F1) << 24;
+
+	return polaris10_write_smc_sram_dword(hwmgr->smumgr,
+			data->arb_table_start, tmp, data->sram_end);
+}
+
+static int polaris10_enable_vrhot_gpio_interrupt(struct pp_hwmgr *hwmgr)
+{
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_RegulatorHot))
+		return smum_send_msg_to_smc(hwmgr->smumgr,
+				PPSMC_MSG_EnableVRHotGPIOInterrupt);
+
+	return 0;
+}
+
+static int polaris10_enable_sclk_control(struct pp_hwmgr *hwmgr)
+{
+	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SCLK_PWRMGT_CNTL,
+			SCLK_PWRMGT_OFF, 0);
+	return 0;
+}
+
+static int polaris10_enable_ulv(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	struct polaris10_ulv_parm *ulv = &(data->ulv);
+
+	if (ulv->ulv_supported)
+		return smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_EnableULV);
+
+	return 0;
+}
+
+static int polaris10_enable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr)
+{
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_SclkDeepSleep)) {
+		if (smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_MASTER_DeepSleep_ON))
+			PP_ASSERT_WITH_CODE(false,
+					"Attempt to enable Master Deep Sleep switch failed!",
+					return -1);
+	} else {
+		if (smum_send_msg_to_smc(hwmgr->smumgr,
+				PPSMC_MSG_MASTER_DeepSleep_OFF)) {
+			PP_ASSERT_WITH_CODE(false,
+					"Attempt to disable Master Deep Sleep switch failed!",
+					return -1);
+		}
+	}
+
+	return 0;
+}
+
+static int polaris10_enable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	uint32_t soft_register_value = 0;
+	uint32_t handshake_disables_offset = data->soft_regs_start
+				+ offsetof(SMU74_SoftRegisters, HandshakeDisables);
+
+	/* enable SCLK dpm */
+	if (!data->sclk_dpm_key_disabled)
+		PP_ASSERT_WITH_CODE(
+		(0 == smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_DPM_Enable)),
+		"Failed to enable SCLK DPM during DPM Start Function!",
+		return -1);
+
+	/* enable MCLK dpm */
+	if (0 == data->mclk_dpm_key_disabled) {
+/* Disable UVD - SMU handshake for MCLK. */
+		soft_register_value = cgs_read_ind_register(hwmgr->device,
+					CGS_IND_REG__SMC, handshake_disables_offset);
+		soft_register_value |= SMU7_UVD_MCLK_HANDSHAKE_DISABLE;
+		cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+				handshake_disables_offset, soft_register_value);
+
+		PP_ASSERT_WITH_CODE(
+				(0 == smum_send_msg_to_smc(hwmgr->smumgr,
+						PPSMC_MSG_MCLKDPM_Enable)),
+				"Failed to enable MCLK DPM during DPM Start Function!",
+				return -1);
+
+		PHM_WRITE_FIELD(hwmgr->device, MC_SEQ_CNTL_3, CAC_EN, 0x1);
+
+		cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC0_CNTL, 0x5);
+		cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC1_CNTL, 0x5);
+		cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_CPL_CNTL, 0x100005);
+		udelay(10);
+		cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC0_CNTL, 0x400005);
+		cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC1_CNTL, 0x400005);
+		cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_CPL_CNTL, 0x500005);
+	}
+
+	return 0;
+}
+
+static int polaris10_start_dpm(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+
+	/*enable general power management */
+
+	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT,
+			GLOBAL_PWRMGT_EN, 1);
+
+	/* enable sclk deep sleep */
+
+	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SCLK_PWRMGT_CNTL,
+			DYNAMIC_PM_EN, 1);
+
+	/* prepare for PCIE DPM */
+
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
+			data->soft_regs_start + offsetof(SMU74_SoftRegisters,
+					VoltageChangeTimeout), 0x1000);
+	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__PCIE,
+			SWRST_COMMAND_1, RESETLC, 0x0);
+/*
+	PP_ASSERT_WITH_CODE(
+			(0 == smum_send_msg_to_smc(hwmgr->smumgr,
+					PPSMC_MSG_Voltage_Cntl_Enable)),
+			"Failed to enable voltage DPM during DPM Start Function!",
+			return -1);
+*/
+
+	if (polaris10_enable_sclk_mclk_dpm(hwmgr)) {
+		printk(KERN_ERR "Failed to enable Sclk DPM and Mclk DPM!");
+		return -1;
+	}
+
+	/* enable PCIE dpm */
+	if (0 == data->pcie_dpm_key_disabled) {
+		PP_ASSERT_WITH_CODE(
+				(0 == smum_send_msg_to_smc(hwmgr->smumgr,
+						PPSMC_MSG_PCIeDPM_Enable)),
+				"Failed to enable pcie DPM during DPM Start Function!",
+				return -1);
+	}
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_Falcon_QuickTransition)) {
+		PP_ASSERT_WITH_CODE((0 == smum_send_msg_to_smc(hwmgr->smumgr,
+				PPSMC_MSG_EnableACDCGPIOInterrupt)),
+				"Failed to enable AC DC GPIO Interrupt!",
+				);
+	}
+
+	return 0;
+}
+
+static void polaris10_set_dpm_event_sources(struct pp_hwmgr *hwmgr, uint32_t sources)
+{
+	bool protection;
+	enum DPM_EVENT_SRC src;
+
+	switch (sources) {
+	default:
+		printk(KERN_ERR "Unknown throttling event sources.");
+		/* fall through */
+	case 0:
+		protection = false;
+		/* src is unused */
+		break;
+	case (1 << PHM_AutoThrottleSource_Thermal):
+		protection = true;
+		src = DPM_EVENT_SRC_DIGITAL;
+		break;
+	case (1 << PHM_AutoThrottleSource_External):
+		protection = true;
+		src = DPM_EVENT_SRC_EXTERNAL;
+		break;
+	case (1 << PHM_AutoThrottleSource_External) |
+			(1 << PHM_AutoThrottleSource_Thermal):
+		protection = true;
+		src = DPM_EVENT_SRC_DIGITAL_OR_EXTERNAL;
+		break;
+	}
+	/* Order matters - don't enable thermal protection for the wrong source. */
+	if (protection) {
+		PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_THERMAL_CTRL,
+				DPM_EVENT_SRC, src);
+		PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT,
+				THERMAL_PROTECTION_DIS,
+				!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+						PHM_PlatformCaps_ThermalController));
+	} else
+		PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT,
+				THERMAL_PROTECTION_DIS, 1);
+}
+
+static int polaris10_enable_auto_throttle_source(struct pp_hwmgr *hwmgr,
+		PHM_AutoThrottleSource source)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+
+	if (!(data->active_auto_throttle_sources & (1 << source))) {
+		data->active_auto_throttle_sources |= 1 << source;
+		polaris10_set_dpm_event_sources(hwmgr, data->active_auto_throttle_sources);
+	}
+	return 0;
+}
+
+static int polaris10_enable_thermal_auto_throttle(struct pp_hwmgr *hwmgr)
+{
+	return polaris10_enable_auto_throttle_source(hwmgr, PHM_AutoThrottleSource_Thermal);
+}
+
+int polaris10_pcie_performance_request(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	data->pcie_performance_request = true;
+
+	return 0;
+}
+
+int polaris10_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
+{
+	int tmp_result, result = 0;
+	tmp_result = (!polaris10_is_dpm_running(hwmgr)) ? 0 : -1;
+	PP_ASSERT_WITH_CODE(result == 0,
+			"DPM is already running right now, no need to enable DPM!",
+			return 0);
+
+	if (polaris10_voltage_control(hwmgr)) {
+		tmp_result = polaris10_enable_voltage_control(hwmgr);
+		PP_ASSERT_WITH_CODE(tmp_result == 0,
+				"Failed to enable voltage control!",
+				result = tmp_result);
+
+		tmp_result = polaris10_construct_voltage_tables(hwmgr);
+		PP_ASSERT_WITH_CODE((0 == tmp_result),
+				"Failed to contruct voltage tables!",
+				result = tmp_result);
+	}
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_EngineSpreadSpectrumSupport))
+		PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+				GENERAL_PWRMGT, DYN_SPREAD_SPECTRUM_EN, 1);
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_ThermalController))
+		PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+				GENERAL_PWRMGT, THERMAL_PROTECTION_DIS, 0);
+
+	tmp_result = polaris10_program_static_screen_threshold_parameters(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to program static screen threshold parameters!",
+			result = tmp_result);
+
+	tmp_result = polaris10_enable_display_gap(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to enable display gap!", result = tmp_result);
+
+	tmp_result = polaris10_program_voting_clients(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to program voting clients!", result = tmp_result);
+
+	tmp_result = polaris10_process_firmware_header(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to process firmware header!", result = tmp_result);
+
+	tmp_result = polaris10_initial_switch_from_arbf0_to_f1(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to initialize switch from ArbF0 to F1!",
+			result = tmp_result);
+
+	tmp_result = polaris10_init_smc_table(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to initialize SMC table!", result = tmp_result);
+
+	tmp_result = polaris10_init_arb_table_index(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to initialize ARB table index!", result = tmp_result);
+
+	tmp_result = polaris10_populate_pm_fuses(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to populate PM fuses!", result = tmp_result);
+
+	tmp_result = polaris10_enable_vrhot_gpio_interrupt(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to enable VR hot GPIO interrupt!", result = tmp_result);
+
+	smum_send_msg_to_smc(hwmgr->smumgr, (PPSMC_Msg)PPSMC_HasDisplay);
+
+	tmp_result = polaris10_enable_sclk_control(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to enable SCLK control!", result = tmp_result);
+
+	tmp_result = polaris10_enable_smc_voltage_controller(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to enable voltage control!", result = tmp_result);
+
+	tmp_result = polaris10_enable_ulv(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to enable ULV!", result = tmp_result);
+
+	tmp_result = polaris10_enable_deep_sleep_master_switch(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to enable deep sleep master switch!", result = tmp_result);
+
+	tmp_result = polaris10_start_dpm(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to start DPM!", result = tmp_result);
+
+	tmp_result = polaris10_enable_smc_cac(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to enable SMC CAC!", result = tmp_result);
+
+	tmp_result = polaris10_enable_power_containment(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to enable power containment!", result = tmp_result);
+
+	tmp_result = polaris10_power_control_set_level(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to power control set level!", result = tmp_result);
+
+	tmp_result = polaris10_enable_thermal_auto_throttle(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to enable thermal auto throttle!", result = tmp_result);
+
+	tmp_result = polaris10_pcie_performance_request(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"pcie performance request failed!", result = tmp_result);
+
+	return result;
+}
+
+int polaris10_disable_dpm_tasks(struct pp_hwmgr *hwmgr)
+{
+
+	return 0;
+}
+
+int polaris10_reset_asic_tasks(struct pp_hwmgr *hwmgr)
+{
+
+	return 0;
+}
+
+int polaris10_hwmgr_backend_fini(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+
+	if (data->soft_pp_table) {
+		kfree(data->soft_pp_table);
+		data->soft_pp_table = NULL;
+	}
+
+	return phm_hwmgr_backend_fini(hwmgr);
+}
+
+int polaris10_set_features_platform_caps(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+
+	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_SclkDeepSleep);
+
+	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+		PHM_PlatformCaps_DynamicPatchPowerState);
+
+	if (data->mvdd_control == POLARIS10_VOLTAGE_CONTROL_NONE)
+		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_EnableMVDDControl);
+
+	if (data->vddci_control == POLARIS10_VOLTAGE_CONTROL_NONE)
+		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_ControlVDDCI);
+
+	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+			 PHM_PlatformCaps_TablelessHardwareInterface);
+
+	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_EnableSMU7ThermalManagement);
+
+	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_DynamicPowerManagement);
+
+	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_UnTabledHardwareInterface);
+
+	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_TablelessHardwareInterface);
+
+	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+					PHM_PlatformCaps_SMC);
+
+	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+					PHM_PlatformCaps_NonABMSupportInPPLib);
+
+	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+					PHM_PlatformCaps_DynamicUVDState);
+
+	/* power tune caps Assume disabled */
+	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+						PHM_PlatformCaps_SQRamping);
+	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+						PHM_PlatformCaps_DBRamping);
+	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+						PHM_PlatformCaps_TDRamping);
+	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+						PHM_PlatformCaps_TCPRamping);
+
+	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+					PHM_PlatformCaps_PowerContainment);
+	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+							PHM_PlatformCaps_CAC);
+
+	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+						PHM_PlatformCaps_RegulatorHot);
+
+	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+						PHM_PlatformCaps_AutomaticDCTransition);
+
+	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+						PHM_PlatformCaps_ODFuzzyFanControlSupport);
+
+	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+						PHM_PlatformCaps_FanSpeedInTableIsRPM);
+
+	if (hwmgr->chip_id == CHIP_POLARIS11)
+		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+					PHM_PlatformCaps_SPLLShutdownSupport);
+	return 0;
+}
+
+static void polaris10_init_dpm_defaults(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+
+	polaris10_initialize_power_tune_defaults(hwmgr);
+
+	data->pcie_gen_performance.max = PP_PCIEGen1;
+	data->pcie_gen_performance.min = PP_PCIEGen3;
+	data->pcie_gen_power_saving.max = PP_PCIEGen1;
+	data->pcie_gen_power_saving.min = PP_PCIEGen3;
+	data->pcie_lane_performance.max = 0;
+	data->pcie_lane_performance.min = 16;
+	data->pcie_lane_power_saving.max = 0;
+	data->pcie_lane_power_saving.min = 16;
+}
+
+/**
+* Get Leakage VDDC based on leakage ID.
+*
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @return   always 0
+*/
+static int polaris10_get_evv_voltages(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	uint16_t vv_id;
+	uint32_t vddc = 0;
+	uint16_t i, j;
+	uint32_t sclk = 0;
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)hwmgr->pptable;
+	struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table =
+			table_info->vdd_dep_on_sclk;
+	int result;
+
+	for (i = 0; i < POLARIS10_MAX_LEAKAGE_COUNT; i++) {
+		vv_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i;
+		if (!phm_get_sclk_for_voltage_evv(hwmgr,
+				table_info->vddc_lookup_table, vv_id, &sclk)) {
+			if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+					PHM_PlatformCaps_ClockStretcher)) {
+				for (j = 1; j < sclk_table->count; j++) {
+					if (sclk_table->entries[j].clk == sclk &&
+							sclk_table->entries[j].cks_enable == 0) {
+						sclk += 5000;
+						break;
+					}
+				}
+			}
+
+
+			PP_ASSERT_WITH_CODE(0 == atomctrl_get_voltage_evv_on_sclk_ai(hwmgr,
+							VOLTAGE_TYPE_VDDC, sclk, vv_id, &vddc),
+						"Error retrieving EVV voltage value!",
+						continue);
+
+
+			/* need to make sure vddc is less than 2v or else, it could burn the ASIC.
+			 * real voltage level in unit of 0.01mv */
+			PP_ASSERT_WITH_CODE((vddc < 200000 && vddc != 0),
+					"Invalid VDDC value", result = -EINVAL;);
+
+			/* the voltage should not be zero nor equal to leakage ID */
+			if (vddc != 0 && vddc != vv_id) {
+				data->vddc_leakage.actual_voltage[data->vddc_leakage.count] = (uint16_t)(vddc/100);
+				data->vddc_leakage.leakage_id[data->vddc_leakage.count] = vv_id;
+				data->vddc_leakage.count++;
+			}
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * Change virtual leakage voltage to actual value.
+ *
+ * @param     hwmgr  the address of the powerplay hardware manager.
+ * @param     pointer to changing voltage
+ * @param     pointer to leakage table
+ */
+static void polaris10_patch_with_vdd_leakage(struct pp_hwmgr *hwmgr,
+		uint16_t *voltage, struct polaris10_leakage_voltage *leakage_table)
+{
+	uint32_t index;
+
+	/* search for leakage voltage ID 0xff01 ~ 0xff08 */
+	for (index = 0; index < leakage_table->count; index++) {
+		/* if this voltage matches a leakage voltage ID */
+		/* patch with actual leakage voltage */
+		if (leakage_table->leakage_id[index] == *voltage) {
+			*voltage = leakage_table->actual_voltage[index];
+			break;
+		}
+	}
+
+	if (*voltage > ATOM_VIRTUAL_VOLTAGE_ID0)
+		printk(KERN_ERR "Voltage value looks like a Leakage ID but it's not patched \n");
+}
+
+/**
+* Patch voltage lookup table by EVV leakages.
+*
+* @param     hwmgr  the address of the powerplay hardware manager.
+* @param     pointer to voltage lookup table
+* @param     pointer to leakage table
+* @return     always 0
+*/
+static int polaris10_patch_lookup_table_with_leakage(struct pp_hwmgr *hwmgr,
+		phm_ppt_v1_voltage_lookup_table *lookup_table,
+		struct polaris10_leakage_voltage *leakage_table)
+{
+	uint32_t i;
+
+	for (i = 0; i < lookup_table->count; i++)
+		polaris10_patch_with_vdd_leakage(hwmgr,
+				&lookup_table->entries[i].us_vdd, leakage_table);
+
+	return 0;
+}
+
+static int polaris10_patch_clock_voltage_limits_with_vddc_leakage(
+		struct pp_hwmgr *hwmgr, struct polaris10_leakage_voltage *leakage_table,
+		uint16_t *vddc)
+{
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	polaris10_patch_with_vdd_leakage(hwmgr, (uint16_t *)vddc, leakage_table);
+	hwmgr->dyn_state.max_clock_voltage_on_dc.vddc =
+			table_info->max_clock_voltage_on_dc.vddc;
+	return 0;
+}
+
+static int polaris10_patch_voltage_dependency_tables_with_lookup_table(
+		struct pp_hwmgr *hwmgr)
+{
+	uint8_t entryId;
+	uint8_t voltageId;
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+
+	struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table =
+			table_info->vdd_dep_on_sclk;
+	struct phm_ppt_v1_clock_voltage_dependency_table *mclk_table =
+			table_info->vdd_dep_on_mclk;
+	struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table =
+			table_info->mm_dep_table;
+
+	for (entryId = 0; entryId < sclk_table->count; ++entryId) {
+		voltageId = sclk_table->entries[entryId].vddInd;
+		sclk_table->entries[entryId].vddc =
+				table_info->vddc_lookup_table->entries[voltageId].us_vdd;
+	}
+
+	for (entryId = 0; entryId < mclk_table->count; ++entryId) {
+		voltageId = mclk_table->entries[entryId].vddInd;
+		mclk_table->entries[entryId].vddc =
+			table_info->vddc_lookup_table->entries[voltageId].us_vdd;
+	}
+
+	for (entryId = 0; entryId < mm_table->count; ++entryId) {
+		voltageId = mm_table->entries[entryId].vddcInd;
+		mm_table->entries[entryId].vddc =
+			table_info->vddc_lookup_table->entries[voltageId].us_vdd;
+	}
+
+	return 0;
+
+}
+
+static int polaris10_calc_voltage_dependency_tables(struct pp_hwmgr *hwmgr)
+{
+	/* Need to determine if we need calculated voltage. */
+	return 0;
+}
+
+static int polaris10_calc_mm_voltage_dependency_table(struct pp_hwmgr *hwmgr)
+{
+	/* Need to determine if we need calculated voltage from mm table. */
+	return 0;
+}
+
+static int polaris10_sort_lookup_table(struct pp_hwmgr *hwmgr,
+		struct phm_ppt_v1_voltage_lookup_table *lookup_table)
+{
+	uint32_t table_size, i, j;
+	struct phm_ppt_v1_voltage_lookup_record tmp_voltage_lookup_record;
+	table_size = lookup_table->count;
+
+	PP_ASSERT_WITH_CODE(0 != lookup_table->count,
+		"Lookup table is empty", return -EINVAL);
+
+	/* Sorting voltages */
+	for (i = 0; i < table_size - 1; i++) {
+		for (j = i + 1; j > 0; j--) {
+			if (lookup_table->entries[j].us_vdd <
+					lookup_table->entries[j - 1].us_vdd) {
+				tmp_voltage_lookup_record = lookup_table->entries[j - 1];
+				lookup_table->entries[j - 1] = lookup_table->entries[j];
+				lookup_table->entries[j] = tmp_voltage_lookup_record;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static int polaris10_complete_dependency_tables(struct pp_hwmgr *hwmgr)
+{
+	int result = 0;
+	int tmp_result;
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+
+	tmp_result = polaris10_patch_lookup_table_with_leakage(hwmgr,
+			table_info->vddc_lookup_table, &(data->vddc_leakage));
+	if (tmp_result)
+		result = tmp_result;
+
+	tmp_result = polaris10_patch_clock_voltage_limits_with_vddc_leakage(hwmgr,
+			&(data->vddc_leakage), &table_info->max_clock_voltage_on_dc.vddc);
+	if (tmp_result)
+		result = tmp_result;
+
+	tmp_result = polaris10_patch_voltage_dependency_tables_with_lookup_table(hwmgr);
+	if (tmp_result)
+		result = tmp_result;
+
+	tmp_result = polaris10_calc_voltage_dependency_tables(hwmgr);
+	if (tmp_result)
+		result = tmp_result;
+
+	tmp_result = polaris10_calc_mm_voltage_dependency_table(hwmgr);
+	if (tmp_result)
+		result = tmp_result;
+
+	tmp_result = polaris10_sort_lookup_table(hwmgr, table_info->vddc_lookup_table);
+	if (tmp_result)
+		result = tmp_result;
+
+	return result;
+}
+
+static int polaris10_set_private_data_based_on_pptable(struct pp_hwmgr *hwmgr)
+{
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+
+	struct phm_ppt_v1_clock_voltage_dependency_table *allowed_sclk_vdd_table =
+						table_info->vdd_dep_on_sclk;
+	struct phm_ppt_v1_clock_voltage_dependency_table *allowed_mclk_vdd_table =
+						table_info->vdd_dep_on_mclk;
+
+	PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table != NULL,
+		"VDD dependency on SCLK table is missing.	\
+		This table is mandatory", return -EINVAL);
+	PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table->count >= 1,
+		"VDD dependency on SCLK table has to have is missing.	\
+		This table is mandatory", return -EINVAL);
+
+	PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table != NULL,
+		"VDD dependency on MCLK table is missing.	\
+		This table is mandatory", return -EINVAL);
+	PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table->count >= 1,
+		"VDD dependency on MCLK table has to have is missing.	 \
+		This table is mandatory", return -EINVAL);
+
+	table_info->max_clock_voltage_on_ac.sclk =
+		allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].clk;
+	table_info->max_clock_voltage_on_ac.mclk =
+		allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].clk;
+	table_info->max_clock_voltage_on_ac.vddc =
+		allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].vddc;
+	table_info->max_clock_voltage_on_ac.vddci =
+		allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].vddci;
+
+	hwmgr->dyn_state.max_clock_voltage_on_ac.sclk = table_info->max_clock_voltage_on_ac.sclk;
+	hwmgr->dyn_state.max_clock_voltage_on_ac.mclk = table_info->max_clock_voltage_on_ac.mclk;
+	hwmgr->dyn_state.max_clock_voltage_on_ac.vddc = table_info->max_clock_voltage_on_ac.vddc;
+	hwmgr->dyn_state.max_clock_voltage_on_ac.vddci =table_info->max_clock_voltage_on_ac.vddci;
+
+	return 0;
+}
+
+int polaris10_patch_voltage_workaround(struct pp_hwmgr *hwmgr)
+{
+	struct phm_ppt_v1_information *table_info =
+		       (struct phm_ppt_v1_information *)(hwmgr->pptable);
+	struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table =
+			table_info->vdd_dep_on_mclk;
+	struct phm_ppt_v1_voltage_lookup_table *lookup_table =
+			table_info->vddc_lookup_table;
+	uint32_t i;
+
+	if (hwmgr->chip_id == CHIP_POLARIS10 && hwmgr->hw_revision == 0xC7) {
+		if (lookup_table->entries[dep_mclk_table->entries[dep_mclk_table->count-1].vddInd].us_vdd >= 1000)
+			return 0;
+
+		for (i = 0; i < lookup_table->count; i++) {
+			if (lookup_table->entries[i].us_vdd < 0xff01 && lookup_table->entries[i].us_vdd >= 1000) {
+				dep_mclk_table->entries[dep_mclk_table->count-1].vddInd = (uint8_t) i;
+				return 0;
+			}
+		}
+	}
+	return 0;
+}
+
+
+int polaris10_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	struct pp_atomctrl_gpio_pin_assignment gpio_pin_assignment;
+	uint32_t temp_reg;
+	int result;
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+
+	data->dll_default_on = false;
+	data->sram_end = SMC_RAM_END;
+	data->mclk_dpm0_activity_target = 0xa;
+	data->disable_dpm_mask = 0xFF;
+	data->static_screen_threshold = PPPOLARIS10_STATICSCREENTHRESHOLD_DFLT;
+	data->static_screen_threshold_unit = PPPOLARIS10_STATICSCREENTHRESHOLD_DFLT;
+	data->activity_target[0] = PPPOLARIS10_TARGETACTIVITY_DFLT;
+	data->activity_target[1] = PPPOLARIS10_TARGETACTIVITY_DFLT;
+	data->activity_target[2] = PPPOLARIS10_TARGETACTIVITY_DFLT;
+	data->activity_target[3] = PPPOLARIS10_TARGETACTIVITY_DFLT;
+	data->activity_target[4] = PPPOLARIS10_TARGETACTIVITY_DFLT;
+	data->activity_target[5] = PPPOLARIS10_TARGETACTIVITY_DFLT;
+	data->activity_target[6] = PPPOLARIS10_TARGETACTIVITY_DFLT;
+	data->activity_target[7] = PPPOLARIS10_TARGETACTIVITY_DFLT;
+
+	data->voting_rights_clients0 = PPPOLARIS10_VOTINGRIGHTSCLIENTS_DFLT0;
+	data->voting_rights_clients1 = PPPOLARIS10_VOTINGRIGHTSCLIENTS_DFLT1;
+	data->voting_rights_clients2 = PPPOLARIS10_VOTINGRIGHTSCLIENTS_DFLT2;
+	data->voting_rights_clients3 = PPPOLARIS10_VOTINGRIGHTSCLIENTS_DFLT3;
+	data->voting_rights_clients4 = PPPOLARIS10_VOTINGRIGHTSCLIENTS_DFLT4;
+	data->voting_rights_clients5 = PPPOLARIS10_VOTINGRIGHTSCLIENTS_DFLT5;
+	data->voting_rights_clients6 = PPPOLARIS10_VOTINGRIGHTSCLIENTS_DFLT6;
+	data->voting_rights_clients7 = PPPOLARIS10_VOTINGRIGHTSCLIENTS_DFLT7;
+
+	data->vddc_vddci_delta = VDDC_VDDCI_DELTA;
+
+	data->mclk_activity_target = PPPOLARIS10_MCLK_TARGETACTIVITY_DFLT;
+
+	/* need to set voltage control types before EVV patching */
+	data->voltage_control = POLARIS10_VOLTAGE_CONTROL_NONE;
+	data->vddci_control = POLARIS10_VOLTAGE_CONTROL_NONE;
+	data->mvdd_control = POLARIS10_VOLTAGE_CONTROL_NONE;
+
+	data->enable_tdc_limit_feature = true;
+	data->enable_pkg_pwr_tracking_feature = true;
+	data->force_pcie_gen = PP_PCIEGenInvalid;
+	data->mclk_stutter_mode_threshold = 40000;
+
+	if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr,
+			VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2))
+		data->voltage_control = POLARIS10_VOLTAGE_CONTROL_BY_SVID2;
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_EnableMVDDControl)) {
+		if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr,
+				VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_GPIO_LUT))
+			data->mvdd_control = POLARIS10_VOLTAGE_CONTROL_BY_GPIO;
+		else if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr,
+				VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_SVID2))
+			data->mvdd_control = POLARIS10_VOLTAGE_CONTROL_BY_SVID2;
+	}
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_ControlVDDCI)) {
+		if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr,
+				VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_GPIO_LUT))
+			data->vddci_control = POLARIS10_VOLTAGE_CONTROL_BY_GPIO;
+		else if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr,
+				VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_SVID2))
+			data->vddci_control = POLARIS10_VOLTAGE_CONTROL_BY_SVID2;
+	}
+
+	if (table_info->cac_dtp_table->usClockStretchAmount != 0)
+		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+					PHM_PlatformCaps_ClockStretcher);
+
+	polaris10_set_features_platform_caps(hwmgr);
+
+	polaris10_patch_voltage_workaround(hwmgr);
+	polaris10_init_dpm_defaults(hwmgr);
+
+	/* Get leakage voltage based on leakage ID. */
+	result = polaris10_get_evv_voltages(hwmgr);
+
+	if (result) {
+		printk("Get EVV Voltage Failed.  Abort Driver loading!\n");
+		return -1;
+	}
+
+	polaris10_complete_dependency_tables(hwmgr);
+	polaris10_set_private_data_based_on_pptable(hwmgr);
+
+	/* Initalize Dynamic State Adjustment Rule Settings */
+	result = phm_initializa_dynamic_state_adjustment_rule_settings(hwmgr);
+
+	if (0 == result) {
+		struct cgs_system_info sys_info = {0};
+
+		data->is_tlu_enabled = 0;
+
+		hwmgr->platform_descriptor.hardwareActivityPerformanceLevels =
+							POLARIS10_MAX_HARDWARE_POWERLEVELS;
+		hwmgr->platform_descriptor.hardwarePerformanceLevels = 2;
+		hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50;
+
+
+		if (atomctrl_get_pp_assign_pin(hwmgr, VDDC_PCC_GPIO_PINID, &gpio_pin_assignment)) {
+			temp_reg = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCNB_PWRMGT_CNTL);
+			switch (gpio_pin_assignment.uc_gpio_pin_bit_shift) {
+			case 0:
+				temp_reg = PHM_SET_FIELD(temp_reg, CNB_PWRMGT_CNTL, GNB_SLOW_MODE, 0x1);
+				break;
+			case 1:
+				temp_reg = PHM_SET_FIELD(temp_reg, CNB_PWRMGT_CNTL, GNB_SLOW_MODE, 0x2);
+				break;
+			case 2:
+				temp_reg = PHM_SET_FIELD(temp_reg, CNB_PWRMGT_CNTL, GNB_SLOW, 0x1);
+				break;
+			case 3:
+				temp_reg = PHM_SET_FIELD(temp_reg, CNB_PWRMGT_CNTL, FORCE_NB_PS1, 0x1);
+				break;
+			case 4:
+				temp_reg = PHM_SET_FIELD(temp_reg, CNB_PWRMGT_CNTL, DPM_ENABLED, 0x1);
+				break;
+			default:
+				PP_ASSERT_WITH_CODE(0,
+				"Failed to setup PCC HW register! Wrong GPIO assigned for VDDC_PCC_GPIO_PINID!",
+				);
+				break;
+			}
+			cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCNB_PWRMGT_CNTL, temp_reg);
+		}
+
+		if (table_info->cac_dtp_table->usDefaultTargetOperatingTemp != 0 &&
+			hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode) {
+			hwmgr->thermal_controller.advanceFanControlParameters.usFanPWMMinLimit =
+				(uint16_t)hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit;
+
+			hwmgr->thermal_controller.advanceFanControlParameters.usFanPWMMaxLimit =
+				(uint16_t)hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM;
+
+			hwmgr->thermal_controller.advanceFanControlParameters.usFanPWMStep = 1;
+
+			hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMMaxLimit = 100;
+
+			hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMMinLimit =
+				(uint16_t)hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit;
+
+			hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMStep = 1;
+
+			table_info->cac_dtp_table->usDefaultTargetOperatingTemp = (table_info->cac_dtp_table->usDefaultTargetOperatingTemp >= 50) ?
+									(table_info->cac_dtp_table->usDefaultTargetOperatingTemp -50) : 0;
+
+			table_info->cac_dtp_table->usOperatingTempMaxLimit = table_info->cac_dtp_table->usDefaultTargetOperatingTemp;
+			table_info->cac_dtp_table->usOperatingTempStep = 1;
+			table_info->cac_dtp_table->usOperatingTempHyst = 1;
+
+			hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanPWM =
+				       hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM;
+
+			hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM =
+				       hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM;
+
+			hwmgr->dyn_state.cac_dtp_table->usOperatingTempMinLimit =
+				       table_info->cac_dtp_table->usOperatingTempMinLimit;
+
+			hwmgr->dyn_state.cac_dtp_table->usOperatingTempMaxLimit =
+				       table_info->cac_dtp_table->usOperatingTempMaxLimit;
+
+			hwmgr->dyn_state.cac_dtp_table->usDefaultTargetOperatingTemp =
+				       table_info->cac_dtp_table->usDefaultTargetOperatingTemp;
+
+			hwmgr->dyn_state.cac_dtp_table->usOperatingTempStep =
+				       table_info->cac_dtp_table->usOperatingTempStep;
+
+			hwmgr->dyn_state.cac_dtp_table->usTargetOperatingTemp =
+				       table_info->cac_dtp_table->usTargetOperatingTemp;
+		}
+
+		sys_info.size = sizeof(struct cgs_system_info);
+		sys_info.info_id = CGS_SYSTEM_INFO_PCIE_GEN_INFO;
+		result = cgs_query_system_info(hwmgr->device, &sys_info);
+		if (result)
+			data->pcie_gen_cap = 0x30007;
+		else
+			data->pcie_gen_cap = (uint32_t)sys_info.value;
+		if (data->pcie_gen_cap & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)
+			data->pcie_spc_cap = 20;
+		sys_info.size = sizeof(struct cgs_system_info);
+		sys_info.info_id = CGS_SYSTEM_INFO_PCIE_MLW;
+		result = cgs_query_system_info(hwmgr->device, &sys_info);
+		if (result)
+			data->pcie_lane_cap = 0x2f0000;
+		else
+			data->pcie_lane_cap = (uint32_t)sys_info.value;
+
+		hwmgr->platform_descriptor.vbiosInterruptId = 0x20000400; /* IRQ_SOURCE1_SW_INT */
+/* The true clock step depends on the frequency, typically 4.5 or 9 MHz. Here we use 5. */
+		hwmgr->platform_descriptor.clockStep.engineClock = 500;
+		hwmgr->platform_descriptor.clockStep.memoryClock = 500;
+	} else {
+		/* Ignore return value in here, we are cleaning up a mess. */
+		polaris10_hwmgr_backend_fini(hwmgr);
+	}
+
+	return 0;
+}
+
+static int polaris10_force_dpm_highest(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	uint32_t level, tmp;
+
+	if (!data->pcie_dpm_key_disabled) {
+		if (data->dpm_level_enable_mask.pcie_dpm_enable_mask) {
+			level = 0;
+			tmp = data->dpm_level_enable_mask.pcie_dpm_enable_mask;
+			while (tmp >>= 1)
+				level++;
+
+			if (level)
+				smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+						PPSMC_MSG_PCIeDPM_ForceLevel, level);
+		}
+	}
+
+	if (!data->sclk_dpm_key_disabled) {
+		if (data->dpm_level_enable_mask.sclk_dpm_enable_mask) {
+			level = 0;
+			tmp = data->dpm_level_enable_mask.sclk_dpm_enable_mask;
+			while (tmp >>= 1)
+				level++;
+
+			if (level)
+				smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+						PPSMC_MSG_SCLKDPM_SetEnabledMask,
+						(1 << level));
+		}
+	}
+
+	if (!data->mclk_dpm_key_disabled) {
+		if (data->dpm_level_enable_mask.mclk_dpm_enable_mask) {
+			level = 0;
+			tmp = data->dpm_level_enable_mask.mclk_dpm_enable_mask;
+			while (tmp >>= 1)
+				level++;
+
+			if (level)
+				smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+						PPSMC_MSG_MCLKDPM_SetEnabledMask,
+						(1 << level));
+		}
+	}
+
+	return 0;
+}
+
+static int polaris10_upload_dpm_level_enable_mask(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+
+	phm_apply_dal_min_voltage_request(hwmgr);
+
+	if (!data->sclk_dpm_key_disabled) {
+		if (data->dpm_level_enable_mask.sclk_dpm_enable_mask)
+			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+					PPSMC_MSG_SCLKDPM_SetEnabledMask,
+					data->dpm_level_enable_mask.sclk_dpm_enable_mask);
+	}
+
+	if (!data->mclk_dpm_key_disabled) {
+		if (data->dpm_level_enable_mask.mclk_dpm_enable_mask)
+			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+					PPSMC_MSG_MCLKDPM_SetEnabledMask,
+					data->dpm_level_enable_mask.mclk_dpm_enable_mask);
+	}
+
+	return 0;
+}
+
+static int polaris10_unforce_dpm_levels(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+
+	if (!polaris10_is_dpm_running(hwmgr))
+		return -EINVAL;
+
+	if (!data->pcie_dpm_key_disabled) {
+		smum_send_msg_to_smc(hwmgr->smumgr,
+				PPSMC_MSG_PCIeDPM_UnForceLevel);
+	}
+
+	return polaris10_upload_dpm_level_enable_mask(hwmgr);
+}
+
+static int polaris10_force_dpm_lowest(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data =
+			(struct polaris10_hwmgr *)(hwmgr->backend);
+	uint32_t level;
+
+	if (!data->sclk_dpm_key_disabled)
+		if (data->dpm_level_enable_mask.sclk_dpm_enable_mask) {
+			level = phm_get_lowest_enabled_level(hwmgr,
+							      data->dpm_level_enable_mask.sclk_dpm_enable_mask);
+			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+							    PPSMC_MSG_SCLKDPM_SetEnabledMask,
+							    (1 << level));
+
+	}
+
+	if (!data->mclk_dpm_key_disabled) {
+		if (data->dpm_level_enable_mask.mclk_dpm_enable_mask) {
+			level = phm_get_lowest_enabled_level(hwmgr,
+							      data->dpm_level_enable_mask.mclk_dpm_enable_mask);
+			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+							    PPSMC_MSG_MCLKDPM_SetEnabledMask,
+							    (1 << level));
+		}
+	}
+
+	if (!data->pcie_dpm_key_disabled) {
+		if (data->dpm_level_enable_mask.pcie_dpm_enable_mask) {
+			level = phm_get_lowest_enabled_level(hwmgr,
+							      data->dpm_level_enable_mask.pcie_dpm_enable_mask);
+			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+							    PPSMC_MSG_PCIeDPM_ForceLevel,
+							    (level));
+		}
+	}
+
+	return 0;
+
+}
+static int polaris10_force_dpm_level(struct pp_hwmgr *hwmgr,
+				enum amd_dpm_forced_level level)
+{
+	int ret = 0;
+
+	switch (level) {
+	case AMD_DPM_FORCED_LEVEL_HIGH:
+		ret = polaris10_force_dpm_highest(hwmgr);
+		if (ret)
+			return ret;
+		break;
+	case AMD_DPM_FORCED_LEVEL_LOW:
+		ret = polaris10_force_dpm_lowest(hwmgr);
+		if (ret)
+			return ret;
+		break;
+	case AMD_DPM_FORCED_LEVEL_AUTO:
+		ret = polaris10_unforce_dpm_levels(hwmgr);
+		if (ret)
+			return ret;
+		break;
+	default:
+		break;
+	}
+
+	hwmgr->dpm_level = level;
+
+	return ret;
+}
+
+static int polaris10_get_power_state_size(struct pp_hwmgr *hwmgr)
+{
+	return sizeof(struct polaris10_power_state);
+}
+
+
+static int polaris10_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
+				struct pp_power_state *request_ps,
+			const struct pp_power_state *current_ps)
+{
+
+	struct polaris10_power_state *polaris10_ps =
+				cast_phw_polaris10_power_state(&request_ps->hardware);
+	uint32_t sclk;
+	uint32_t mclk;
+	struct PP_Clocks minimum_clocks = {0};
+	bool disable_mclk_switching;
+	bool disable_mclk_switching_for_frame_lock;
+	struct cgs_display_info info = {0};
+	const struct phm_clock_and_voltage_limits *max_limits;
+	uint32_t i;
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	int32_t count;
+	int32_t stable_pstate_sclk = 0, stable_pstate_mclk = 0;
+
+	data->battery_state = (PP_StateUILabel_Battery ==
+			request_ps->classification.ui_label);
+
+	PP_ASSERT_WITH_CODE(polaris10_ps->performance_level_count == 2,
+				 "VI should always have 2 performance levels",
+				);
+
+	max_limits = (PP_PowerSource_AC == hwmgr->power_source) ?
+			&(hwmgr->dyn_state.max_clock_voltage_on_ac) :
+			&(hwmgr->dyn_state.max_clock_voltage_on_dc);
+
+	/* Cap clock DPM tables at DC MAX if it is in DC. */
+	if (PP_PowerSource_DC == hwmgr->power_source) {
+		for (i = 0; i < polaris10_ps->performance_level_count; i++) {
+			if (polaris10_ps->performance_levels[i].memory_clock > max_limits->mclk)
+				polaris10_ps->performance_levels[i].memory_clock = max_limits->mclk;
+			if (polaris10_ps->performance_levels[i].engine_clock > max_limits->sclk)
+				polaris10_ps->performance_levels[i].engine_clock = max_limits->sclk;
+		}
+	}
+
+	polaris10_ps->vce_clks.evclk = hwmgr->vce_arbiter.evclk;
+	polaris10_ps->vce_clks.ecclk = hwmgr->vce_arbiter.ecclk;
+
+	cgs_get_active_displays_info(hwmgr->device, &info);
+
+	/*TO DO result = PHM_CheckVBlankTime(hwmgr, &vblankTooShort);*/
+
+	/* TO DO GetMinClockSettings(hwmgr->pPECI, &minimum_clocks); */
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_StablePState)) {
+		max_limits = &(hwmgr->dyn_state.max_clock_voltage_on_ac);
+		stable_pstate_sclk = (max_limits->sclk * 75) / 100;
+
+		for (count = table_info->vdd_dep_on_sclk->count - 1;
+				count >= 0; count--) {
+			if (stable_pstate_sclk >=
+					table_info->vdd_dep_on_sclk->entries[count].clk) {
+				stable_pstate_sclk =
+						table_info->vdd_dep_on_sclk->entries[count].clk;
+				break;
+			}
+		}
+
+		if (count < 0)
+			stable_pstate_sclk = table_info->vdd_dep_on_sclk->entries[0].clk;
+
+		stable_pstate_mclk = max_limits->mclk;
+
+		minimum_clocks.engineClock = stable_pstate_sclk;
+		minimum_clocks.memoryClock = stable_pstate_mclk;
+	}
+
+	if (minimum_clocks.engineClock < hwmgr->gfx_arbiter.sclk)
+		minimum_clocks.engineClock = hwmgr->gfx_arbiter.sclk;
+
+	if (minimum_clocks.memoryClock < hwmgr->gfx_arbiter.mclk)
+		minimum_clocks.memoryClock = hwmgr->gfx_arbiter.mclk;
+
+	polaris10_ps->sclk_threshold = hwmgr->gfx_arbiter.sclk_threshold;
+
+	if (0 != hwmgr->gfx_arbiter.sclk_over_drive) {
+		PP_ASSERT_WITH_CODE((hwmgr->gfx_arbiter.sclk_over_drive <=
+				hwmgr->platform_descriptor.overdriveLimit.engineClock),
+				"Overdrive sclk exceeds limit",
+				hwmgr->gfx_arbiter.sclk_over_drive =
+						hwmgr->platform_descriptor.overdriveLimit.engineClock);
+
+		if (hwmgr->gfx_arbiter.sclk_over_drive >= hwmgr->gfx_arbiter.sclk)
+			polaris10_ps->performance_levels[1].engine_clock =
+					hwmgr->gfx_arbiter.sclk_over_drive;
+	}
+
+	if (0 != hwmgr->gfx_arbiter.mclk_over_drive) {
+		PP_ASSERT_WITH_CODE((hwmgr->gfx_arbiter.mclk_over_drive <=
+				hwmgr->platform_descriptor.overdriveLimit.memoryClock),
+				"Overdrive mclk exceeds limit",
+				hwmgr->gfx_arbiter.mclk_over_drive =
+						hwmgr->platform_descriptor.overdriveLimit.memoryClock);
+
+		if (hwmgr->gfx_arbiter.mclk_over_drive >= hwmgr->gfx_arbiter.mclk)
+			polaris10_ps->performance_levels[1].memory_clock =
+					hwmgr->gfx_arbiter.mclk_over_drive;
+	}
+
+	disable_mclk_switching_for_frame_lock = phm_cap_enabled(
+				    hwmgr->platform_descriptor.platformCaps,
+				    PHM_PlatformCaps_DisableMclkSwitchingForFrameLock);
+
+	disable_mclk_switching = (1 < info.display_count) ||
+				    disable_mclk_switching_for_frame_lock;
+
+	sclk = polaris10_ps->performance_levels[0].engine_clock;
+	mclk = polaris10_ps->performance_levels[0].memory_clock;
+
+	if (disable_mclk_switching)
+		mclk = polaris10_ps->performance_levels
+		[polaris10_ps->performance_level_count - 1].memory_clock;
+
+	if (sclk < minimum_clocks.engineClock)
+		sclk = (minimum_clocks.engineClock > max_limits->sclk) ?
+				max_limits->sclk : minimum_clocks.engineClock;
+
+	if (mclk < minimum_clocks.memoryClock)
+		mclk = (minimum_clocks.memoryClock > max_limits->mclk) ?
+				max_limits->mclk : minimum_clocks.memoryClock;
+
+	polaris10_ps->performance_levels[0].engine_clock = sclk;
+	polaris10_ps->performance_levels[0].memory_clock = mclk;
+
+	polaris10_ps->performance_levels[1].engine_clock =
+		(polaris10_ps->performance_levels[1].engine_clock >=
+				polaris10_ps->performance_levels[0].engine_clock) ?
+						polaris10_ps->performance_levels[1].engine_clock :
+						polaris10_ps->performance_levels[0].engine_clock;
+
+	if (disable_mclk_switching) {
+		if (mclk < polaris10_ps->performance_levels[1].memory_clock)
+			mclk = polaris10_ps->performance_levels[1].memory_clock;
+
+		polaris10_ps->performance_levels[0].memory_clock = mclk;
+		polaris10_ps->performance_levels[1].memory_clock = mclk;
+	} else {
+		if (polaris10_ps->performance_levels[1].memory_clock <
+				polaris10_ps->performance_levels[0].memory_clock)
+			polaris10_ps->performance_levels[1].memory_clock =
+					polaris10_ps->performance_levels[0].memory_clock;
+	}
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_StablePState)) {
+		for (i = 0; i < polaris10_ps->performance_level_count; i++) {
+			polaris10_ps->performance_levels[i].engine_clock = stable_pstate_sclk;
+			polaris10_ps->performance_levels[i].memory_clock = stable_pstate_mclk;
+			polaris10_ps->performance_levels[i].pcie_gen = data->pcie_gen_performance.max;
+			polaris10_ps->performance_levels[i].pcie_lane = data->pcie_gen_performance.max;
+		}
+	}
+	return 0;
+}
+
+
+static int polaris10_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low)
+{
+	struct pp_power_state  *ps;
+	struct polaris10_power_state  *polaris10_ps;
+
+	if (hwmgr == NULL)
+		return -EINVAL;
+
+	ps = hwmgr->request_ps;
+
+	if (ps == NULL)
+		return -EINVAL;
+
+	polaris10_ps = cast_phw_polaris10_power_state(&ps->hardware);
+
+	if (low)
+		return polaris10_ps->performance_levels[0].memory_clock;
+	else
+		return polaris10_ps->performance_levels
+				[polaris10_ps->performance_level_count-1].memory_clock;
+}
+
+static int polaris10_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low)
+{
+	struct pp_power_state  *ps;
+	struct polaris10_power_state  *polaris10_ps;
+
+	if (hwmgr == NULL)
+		return -EINVAL;
+
+	ps = hwmgr->request_ps;
+
+	if (ps == NULL)
+		return -EINVAL;
+
+	polaris10_ps = cast_phw_polaris10_power_state(&ps->hardware);
+
+	if (low)
+		return polaris10_ps->performance_levels[0].engine_clock;
+	else
+		return polaris10_ps->performance_levels
+				[polaris10_ps->performance_level_count-1].engine_clock;
+}
+
+static int polaris10_dpm_patch_boot_state(struct pp_hwmgr *hwmgr,
+					struct pp_hw_power_state *hw_ps)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	struct polaris10_power_state *ps = (struct polaris10_power_state *)hw_ps;
+	ATOM_FIRMWARE_INFO_V2_2 *fw_info;
+	uint16_t size;
+	uint8_t frev, crev;
+	int index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
+
+	/* First retrieve the Boot clocks and VDDC from the firmware info table.
+	 * We assume here that fw_info is unchanged if this call fails.
+	 */
+	fw_info = (ATOM_FIRMWARE_INFO_V2_2 *)cgs_atom_get_data_table(
+			hwmgr->device, index,
+			&size, &frev, &crev);
+	if (!fw_info)
+		/* During a test, there is no firmware info table. */
+		return 0;
+
+	/* Patch the state. */
+	data->vbios_boot_state.sclk_bootup_value =
+			le32_to_cpu(fw_info->ulDefaultEngineClock);
+	data->vbios_boot_state.mclk_bootup_value =
+			le32_to_cpu(fw_info->ulDefaultMemoryClock);
+	data->vbios_boot_state.mvdd_bootup_value =
+			le16_to_cpu(fw_info->usBootUpMVDDCVoltage);
+	data->vbios_boot_state.vddc_bootup_value =
+			le16_to_cpu(fw_info->usBootUpVDDCVoltage);
+	data->vbios_boot_state.vddci_bootup_value =
+			le16_to_cpu(fw_info->usBootUpVDDCIVoltage);
+	data->vbios_boot_state.pcie_gen_bootup_value =
+			phm_get_current_pcie_speed(hwmgr);
+
+	data->vbios_boot_state.pcie_lane_bootup_value =
+			(uint16_t)phm_get_current_pcie_lane_number(hwmgr);
+
+	/* set boot power state */
+	ps->performance_levels[0].memory_clock = data->vbios_boot_state.mclk_bootup_value;
+	ps->performance_levels[0].engine_clock = data->vbios_boot_state.sclk_bootup_value;
+	ps->performance_levels[0].pcie_gen = data->vbios_boot_state.pcie_gen_bootup_value;
+	ps->performance_levels[0].pcie_lane = data->vbios_boot_state.pcie_lane_bootup_value;
+
+	return 0;
+}
+
+static int polaris10_get_pp_table_entry_callback_func(struct pp_hwmgr *hwmgr,
+		void *state, struct pp_power_state *power_state,
+		void *pp_table, uint32_t classification_flag)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	struct polaris10_power_state  *polaris10_power_state =
+			(struct polaris10_power_state *)(&(power_state->hardware));
+	struct polaris10_performance_level *performance_level;
+	ATOM_Tonga_State *state_entry = (ATOM_Tonga_State *)state;
+	ATOM_Tonga_POWERPLAYTABLE *powerplay_table =
+			(ATOM_Tonga_POWERPLAYTABLE *)pp_table;
+	PPTable_Generic_SubTable_Header *sclk_dep_table =
+			(PPTable_Generic_SubTable_Header *)
+			(((unsigned long)powerplay_table) +
+				le16_to_cpu(powerplay_table->usSclkDependencyTableOffset));
+
+	ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table =
+			(ATOM_Tonga_MCLK_Dependency_Table *)
+			(((unsigned long)powerplay_table) +
+				le16_to_cpu(powerplay_table->usMclkDependencyTableOffset));
+
+	/* The following fields are not initialized here: id orderedList allStatesList */
+	power_state->classification.ui_label =
+			(le16_to_cpu(state_entry->usClassification) &
+			ATOM_PPLIB_CLASSIFICATION_UI_MASK) >>
+			ATOM_PPLIB_CLASSIFICATION_UI_SHIFT;
+	power_state->classification.flags = classification_flag;
+	/* NOTE: There is a classification2 flag in BIOS that is not being used right now */
+
+	power_state->classification.temporary_state = false;
+	power_state->classification.to_be_deleted = false;
+
+	power_state->validation.disallowOnDC =
+			(0 != (le32_to_cpu(state_entry->ulCapsAndSettings) &
+					ATOM_Tonga_DISALLOW_ON_DC));
+
+	power_state->pcie.lanes = 0;
+
+	power_state->display.disableFrameModulation = false;
+	power_state->display.limitRefreshrate = false;
+	power_state->display.enableVariBright =
+			(0 != (le32_to_cpu(state_entry->ulCapsAndSettings) &
+					ATOM_Tonga_ENABLE_VARIBRIGHT));
+
+	power_state->validation.supportedPowerLevels = 0;
+	power_state->uvd_clocks.VCLK = 0;
+	power_state->uvd_clocks.DCLK = 0;
+	power_state->temperatures.min = 0;
+	power_state->temperatures.max = 0;
+
+	performance_level = &(polaris10_power_state->performance_levels
+			[polaris10_power_state->performance_level_count++]);
+
+	PP_ASSERT_WITH_CODE(
+			(polaris10_power_state->performance_level_count < SMU74_MAX_LEVELS_GRAPHICS),
+			"Performance levels exceeds SMC limit!",
+			return -1);
+
+	PP_ASSERT_WITH_CODE(
+			(polaris10_power_state->performance_level_count <=
+					hwmgr->platform_descriptor.hardwareActivityPerformanceLevels),
+			"Performance levels exceeds Driver limit!",
+			return -1);
+
+	/* Performance levels are arranged from low to high. */
+	performance_level->memory_clock = mclk_dep_table->entries
+			[state_entry->ucMemoryClockIndexLow].ulMclk;
+	if (sclk_dep_table->ucRevId == 0)
+		performance_level->engine_clock = ((ATOM_Tonga_SCLK_Dependency_Table *)sclk_dep_table)->entries
+			[state_entry->ucEngineClockIndexLow].ulSclk;
+	else if (sclk_dep_table->ucRevId == 1)
+		performance_level->engine_clock = ((ATOM_Polaris_SCLK_Dependency_Table *)sclk_dep_table)->entries
+			[state_entry->ucEngineClockIndexLow].ulSclk;
+	performance_level->pcie_gen = get_pcie_gen_support(data->pcie_gen_cap,
+			state_entry->ucPCIEGenLow);
+	performance_level->pcie_lane = get_pcie_lane_support(data->pcie_lane_cap,
+			state_entry->ucPCIELaneHigh);
+
+	performance_level = &(polaris10_power_state->performance_levels
+			[polaris10_power_state->performance_level_count++]);
+	performance_level->memory_clock = mclk_dep_table->entries
+			[state_entry->ucMemoryClockIndexHigh].ulMclk;
+
+	if (sclk_dep_table->ucRevId == 0)
+		performance_level->engine_clock = ((ATOM_Tonga_SCLK_Dependency_Table *)sclk_dep_table)->entries
+			[state_entry->ucEngineClockIndexHigh].ulSclk;
+	else if (sclk_dep_table->ucRevId == 1)
+		performance_level->engine_clock = ((ATOM_Polaris_SCLK_Dependency_Table *)sclk_dep_table)->entries
+			[state_entry->ucEngineClockIndexHigh].ulSclk;
+
+	performance_level->pcie_gen = get_pcie_gen_support(data->pcie_gen_cap,
+			state_entry->ucPCIEGenHigh);
+	performance_level->pcie_lane = get_pcie_lane_support(data->pcie_lane_cap,
+			state_entry->ucPCIELaneHigh);
+
+	return 0;
+}
+
+static int polaris10_get_pp_table_entry(struct pp_hwmgr *hwmgr,
+		unsigned long entry_index, struct pp_power_state *state)
+{
+	int result;
+	struct polaris10_power_state *ps;
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table =
+			table_info->vdd_dep_on_mclk;
+
+	state->hardware.magic = PHM_VIslands_Magic;
+
+	ps = (struct polaris10_power_state *)(&state->hardware);
+
+	result = tonga_get_powerplay_table_entry(hwmgr, entry_index, state,
+			polaris10_get_pp_table_entry_callback_func);
+
+	/* This is the earliest time we have all the dependency table and the VBIOS boot state
+	 * as PP_Tables_GetPowerPlayTableEntry retrieves the VBIOS boot state
+	 * if there is only one VDDCI/MCLK level, check if it's the same as VBIOS boot state
+	 */
+	if (dep_mclk_table != NULL && dep_mclk_table->count == 1) {
+		if (dep_mclk_table->entries[0].clk !=
+				data->vbios_boot_state.mclk_bootup_value)
+			printk(KERN_ERR "Single MCLK entry VDDCI/MCLK dependency table "
+					"does not match VBIOS boot MCLK level");
+		if (dep_mclk_table->entries[0].vddci !=
+				data->vbios_boot_state.vddci_bootup_value)
+			printk(KERN_ERR "Single VDDCI entry VDDCI/MCLK dependency table "
+					"does not match VBIOS boot VDDCI level");
+	}
+
+	/* set DC compatible flag if this state supports DC */
+	if (!state->validation.disallowOnDC)
+		ps->dc_compatible = true;
+
+	if (state->classification.flags & PP_StateClassificationFlag_ACPI)
+		data->acpi_pcie_gen = ps->performance_levels[0].pcie_gen;
+
+	ps->uvd_clks.vclk = state->uvd_clocks.VCLK;
+	ps->uvd_clks.dclk = state->uvd_clocks.DCLK;
+
+	if (!result) {
+		uint32_t i;
+
+		switch (state->classification.ui_label) {
+		case PP_StateUILabel_Performance:
+			data->use_pcie_performance_levels = true;
+			for (i = 0; i < ps->performance_level_count; i++) {
+				if (data->pcie_gen_performance.max <
+						ps->performance_levels[i].pcie_gen)
+					data->pcie_gen_performance.max =
+							ps->performance_levels[i].pcie_gen;
+
+				if (data->pcie_gen_performance.min >
+						ps->performance_levels[i].pcie_gen)
+					data->pcie_gen_performance.min =
+							ps->performance_levels[i].pcie_gen;
+
+				if (data->pcie_lane_performance.max <
+						ps->performance_levels[i].pcie_lane)
+					data->pcie_lane_performance.max =
+							ps->performance_levels[i].pcie_lane;
+				if (data->pcie_lane_performance.min >
+						ps->performance_levels[i].pcie_lane)
+					data->pcie_lane_performance.min =
+							ps->performance_levels[i].pcie_lane;
+			}
+			break;
+		case PP_StateUILabel_Battery:
+			data->use_pcie_power_saving_levels = true;
+
+			for (i = 0; i < ps->performance_level_count; i++) {
+				if (data->pcie_gen_power_saving.max <
+						ps->performance_levels[i].pcie_gen)
+					data->pcie_gen_power_saving.max =
+							ps->performance_levels[i].pcie_gen;
+
+				if (data->pcie_gen_power_saving.min >
+						ps->performance_levels[i].pcie_gen)
+					data->pcie_gen_power_saving.min =
+							ps->performance_levels[i].pcie_gen;
+
+				if (data->pcie_lane_power_saving.max <
+						ps->performance_levels[i].pcie_lane)
+					data->pcie_lane_power_saving.max =
+							ps->performance_levels[i].pcie_lane;
+
+				if (data->pcie_lane_power_saving.min >
+						ps->performance_levels[i].pcie_lane)
+					data->pcie_lane_power_saving.min =
+							ps->performance_levels[i].pcie_lane;
+			}
+			break;
+		default:
+			break;
+		}
+	}
+	return 0;
+}
+
+static void
+polaris10_print_current_perforce_level(struct pp_hwmgr *hwmgr, struct seq_file *m)
+{
+	uint32_t sclk, mclk, activity_percent;
+	uint32_t offset;
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+
+	smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_API_GetSclkFrequency);
+
+	sclk = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0);
+
+	smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_API_GetMclkFrequency);
+
+	mclk = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0);
+	seq_printf(m, "\n [  mclk  ]: %u MHz\n\n [  sclk  ]: %u MHz\n",
+			mclk / 100, sclk / 100);
+
+	offset = data->soft_regs_start + offsetof(SMU74_SoftRegisters, AverageGraphicsActivity);
+	activity_percent = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset);
+	activity_percent += 0x80;
+	activity_percent >>= 8;
+
+	seq_printf(m, "\n [GPU load]: %u%%\n\n", activity_percent > 100 ? 100 : activity_percent);
+
+	seq_printf(m, "uvd    %sabled\n", data->uvd_power_gated ? "dis" : "en");
+
+	seq_printf(m, "vce    %sabled\n", data->vce_power_gated ? "dis" : "en");
+}
+
+static int polaris10_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, const void *input)
+{
+	const struct phm_set_power_state_input *states =
+			(const struct phm_set_power_state_input *)input;
+	const struct polaris10_power_state *polaris10_ps =
+			cast_const_phw_polaris10_power_state(states->pnew_state);
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	struct polaris10_single_dpm_table *sclk_table = &(data->dpm_table.sclk_table);
+	uint32_t sclk = polaris10_ps->performance_levels
+			[polaris10_ps->performance_level_count - 1].engine_clock;
+	struct polaris10_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table);
+	uint32_t mclk = polaris10_ps->performance_levels
+			[polaris10_ps->performance_level_count - 1].memory_clock;
+	struct PP_Clocks min_clocks = {0};
+	uint32_t i;
+	struct cgs_display_info info = {0};
+
+	data->need_update_smu7_dpm_table = 0;
+
+	for (i = 0; i < sclk_table->count; i++) {
+		if (sclk == sclk_table->dpm_levels[i].value)
+			break;
+	}
+
+	if (i >= sclk_table->count)
+		data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_SCLK;
+	else {
+	/* TODO: Check SCLK in DAL's minimum clocks
+	 * in case DeepSleep divider update is required.
+	 */
+		if (data->display_timing.min_clock_in_sr != min_clocks.engineClockInSR &&
+			(min_clocks.engineClockInSR >= POLARIS10_MINIMUM_ENGINE_CLOCK ||
+				data->display_timing.min_clock_in_sr >= POLARIS10_MINIMUM_ENGINE_CLOCK))
+			data->need_update_smu7_dpm_table |= DPMTABLE_UPDATE_SCLK;
+	}
+
+	for (i = 0; i < mclk_table->count; i++) {
+		if (mclk == mclk_table->dpm_levels[i].value)
+			break;
+	}
+
+	if (i >= mclk_table->count)
+		data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_MCLK;
+
+	cgs_get_active_displays_info(hwmgr->device, &info);
+
+	if (data->display_timing.num_existing_displays != info.display_count)
+		data->need_update_smu7_dpm_table |= DPMTABLE_UPDATE_MCLK;
+
+	return 0;
+}
+
+static uint16_t polaris10_get_maximum_link_speed(struct pp_hwmgr *hwmgr,
+		const struct polaris10_power_state *polaris10_ps)
+{
+	uint32_t i;
+	uint32_t sclk, max_sclk = 0;
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	struct polaris10_dpm_table *dpm_table = &data->dpm_table;
+
+	for (i = 0; i < polaris10_ps->performance_level_count; i++) {
+		sclk = polaris10_ps->performance_levels[i].engine_clock;
+		if (max_sclk < sclk)
+			max_sclk = sclk;
+	}
+
+	for (i = 0; i < dpm_table->sclk_table.count; i++) {
+		if (dpm_table->sclk_table.dpm_levels[i].value == max_sclk)
+			return (uint16_t) ((i >= dpm_table->pcie_speed_table.count) ?
+					dpm_table->pcie_speed_table.dpm_levels
+					[dpm_table->pcie_speed_table.count - 1].value :
+					dpm_table->pcie_speed_table.dpm_levels[i].value);
+	}
+
+	return 0;
+}
+
+static int polaris10_request_link_speed_change_before_state_change(
+		struct pp_hwmgr *hwmgr, const void *input)
+{
+	const struct phm_set_power_state_input *states =
+			(const struct phm_set_power_state_input *)input;
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	const struct polaris10_power_state *polaris10_nps =
+			cast_const_phw_polaris10_power_state(states->pnew_state);
+	const struct polaris10_power_state *polaris10_cps =
+			cast_const_phw_polaris10_power_state(states->pcurrent_state);
+
+	uint16_t target_link_speed = polaris10_get_maximum_link_speed(hwmgr, polaris10_nps);
+	uint16_t current_link_speed;
+
+	if (data->force_pcie_gen == PP_PCIEGenInvalid)
+		current_link_speed = polaris10_get_maximum_link_speed(hwmgr, polaris10_cps);
+	else
+		current_link_speed = data->force_pcie_gen;
+
+	data->force_pcie_gen = PP_PCIEGenInvalid;
+	data->pspp_notify_required = false;
+
+	if (target_link_speed > current_link_speed) {
+		switch (target_link_speed) {
+		case PP_PCIEGen3:
+			if (0 == acpi_pcie_perf_request(hwmgr->device, PCIE_PERF_REQ_GEN3, false))
+				break;
+			data->force_pcie_gen = PP_PCIEGen2;
+			if (current_link_speed == PP_PCIEGen2)
+				break;
+		case PP_PCIEGen2:
+			if (0 == acpi_pcie_perf_request(hwmgr->device, PCIE_PERF_REQ_GEN2, false))
+				break;
+		default:
+			data->force_pcie_gen = phm_get_current_pcie_speed(hwmgr);
+			break;
+		}
+	} else {
+		if (target_link_speed < current_link_speed)
+			data->pspp_notify_required = true;
+	}
+
+	return 0;
+}
+
+static int polaris10_freeze_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+
+	if (0 == data->need_update_smu7_dpm_table)
+		return 0;
+
+	if ((0 == data->sclk_dpm_key_disabled) &&
+		(data->need_update_smu7_dpm_table &
+			(DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK))) {
+		PP_ASSERT_WITH_CODE(true == polaris10_is_dpm_running(hwmgr),
+				"Trying to freeze SCLK DPM when DPM is disabled",
+				);
+		PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr->smumgr,
+				PPSMC_MSG_SCLKDPM_FreezeLevel),
+				"Failed to freeze SCLK DPM during FreezeSclkMclkDPM Function!",
+				return -1);
+	}
+
+	if ((0 == data->mclk_dpm_key_disabled) &&
+		(data->need_update_smu7_dpm_table &
+		 DPMTABLE_OD_UPDATE_MCLK)) {
+		PP_ASSERT_WITH_CODE(true == polaris10_is_dpm_running(hwmgr),
+				"Trying to freeze MCLK DPM when DPM is disabled",
+				);
+		PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr->smumgr,
+				PPSMC_MSG_MCLKDPM_FreezeLevel),
+				"Failed to freeze MCLK DPM during FreezeSclkMclkDPM Function!",
+				return -1);
+	}
+
+	return 0;
+}
+
+static int polaris10_populate_and_upload_sclk_mclk_dpm_levels(
+		struct pp_hwmgr *hwmgr, const void *input)
+{
+	int result = 0;
+	const struct phm_set_power_state_input *states =
+			(const struct phm_set_power_state_input *)input;
+	const struct polaris10_power_state *polaris10_ps =
+			cast_const_phw_polaris10_power_state(states->pnew_state);
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	uint32_t sclk = polaris10_ps->performance_levels
+			[polaris10_ps->performance_level_count - 1].engine_clock;
+	uint32_t mclk = polaris10_ps->performance_levels
+			[polaris10_ps->performance_level_count - 1].memory_clock;
+	struct polaris10_dpm_table *dpm_table = &data->dpm_table;
+
+	struct polaris10_dpm_table *golden_dpm_table = &data->golden_dpm_table;
+	uint32_t dpm_count, clock_percent;
+	uint32_t i;
+
+	if (0 == data->need_update_smu7_dpm_table)
+		return 0;
+
+	if (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_SCLK) {
+		dpm_table->sclk_table.dpm_levels
+		[dpm_table->sclk_table.count - 1].value = sclk;
+
+		if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_OD6PlusinACSupport) ||
+		    phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_OD6PlusinDCSupport)) {
+		/* Need to do calculation based on the golden DPM table
+		 * as the Heatmap GPU Clock axis is also based on the default values
+		 */
+			PP_ASSERT_WITH_CODE(
+				(golden_dpm_table->sclk_table.dpm_levels
+						[golden_dpm_table->sclk_table.count - 1].value != 0),
+				"Divide by 0!",
+				return -1);
+			dpm_count = dpm_table->sclk_table.count < 2 ? 0 : dpm_table->sclk_table.count - 2;
+
+			for (i = dpm_count; i > 1; i--) {
+				if (sclk > golden_dpm_table->sclk_table.dpm_levels[golden_dpm_table->sclk_table.count-1].value) {
+					clock_percent =
+					      ((sclk
+						- golden_dpm_table->sclk_table.dpm_levels[golden_dpm_table->sclk_table.count-1].value
+						) * 100)
+						/ golden_dpm_table->sclk_table.dpm_levels[golden_dpm_table->sclk_table.count-1].value;
+
+					dpm_table->sclk_table.dpm_levels[i].value =
+							golden_dpm_table->sclk_table.dpm_levels[i].value +
+							(golden_dpm_table->sclk_table.dpm_levels[i].value *
+								clock_percent)/100;
+
+				} else if (golden_dpm_table->sclk_table.dpm_levels[dpm_table->sclk_table.count-1].value > sclk) {
+					clock_percent =
+						((golden_dpm_table->sclk_table.dpm_levels[golden_dpm_table->sclk_table.count - 1].value
+						- sclk) * 100)
+						/ golden_dpm_table->sclk_table.dpm_levels[golden_dpm_table->sclk_table.count-1].value;
+
+					dpm_table->sclk_table.dpm_levels[i].value =
+							golden_dpm_table->sclk_table.dpm_levels[i].value -
+							(golden_dpm_table->sclk_table.dpm_levels[i].value *
+									clock_percent) / 100;
+				} else
+					dpm_table->sclk_table.dpm_levels[i].value =
+							golden_dpm_table->sclk_table.dpm_levels[i].value;
+			}
+		}
+	}
+
+	if (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK) {
+		dpm_table->mclk_table.dpm_levels
+			[dpm_table->mclk_table.count - 1].value = mclk;
+
+		if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_OD6PlusinACSupport) ||
+		    phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_OD6PlusinDCSupport)) {
+
+			PP_ASSERT_WITH_CODE(
+					(golden_dpm_table->mclk_table.dpm_levels
+						[golden_dpm_table->mclk_table.count-1].value != 0),
+					"Divide by 0!",
+					return -1);
+			dpm_count = dpm_table->mclk_table.count < 2 ? 0 : dpm_table->mclk_table.count - 2;
+			for (i = dpm_count; i > 1; i--) {
+				if (golden_dpm_table->mclk_table.dpm_levels[golden_dpm_table->mclk_table.count-1].value < mclk) {
+					clock_percent = ((mclk -
+					golden_dpm_table->mclk_table.dpm_levels[golden_dpm_table->mclk_table.count-1].value) * 100)
+					/ golden_dpm_table->mclk_table.dpm_levels[golden_dpm_table->mclk_table.count-1].value;
+
+					dpm_table->mclk_table.dpm_levels[i].value =
+							golden_dpm_table->mclk_table.dpm_levels[i].value +
+							(golden_dpm_table->mclk_table.dpm_levels[i].value *
+							clock_percent) / 100;
+
+				} else if (golden_dpm_table->mclk_table.dpm_levels[dpm_table->mclk_table.count-1].value > mclk) {
+					clock_percent = (
+					 (golden_dpm_table->mclk_table.dpm_levels[golden_dpm_table->mclk_table.count-1].value - mclk)
+					* 100)
+					/ golden_dpm_table->mclk_table.dpm_levels[golden_dpm_table->mclk_table.count-1].value;
+
+					dpm_table->mclk_table.dpm_levels[i].value =
+							golden_dpm_table->mclk_table.dpm_levels[i].value -
+							(golden_dpm_table->mclk_table.dpm_levels[i].value *
+									clock_percent) / 100;
+				} else
+					dpm_table->mclk_table.dpm_levels[i].value =
+							golden_dpm_table->mclk_table.dpm_levels[i].value;
+			}
+		}
+	}
+
+	if (data->need_update_smu7_dpm_table &
+			(DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK)) {
+		result = polaris10_populate_all_graphic_levels(hwmgr);
+		PP_ASSERT_WITH_CODE((0 == result),
+				"Failed to populate SCLK during PopulateNewDPMClocksStates Function!",
+				return result);
+	}
+
+	if (data->need_update_smu7_dpm_table &
+			(DPMTABLE_OD_UPDATE_MCLK + DPMTABLE_UPDATE_MCLK)) {
+		/*populate MCLK dpm table to SMU7 */
+		result = polaris10_populate_all_memory_levels(hwmgr);
+		PP_ASSERT_WITH_CODE((0 == result),
+				"Failed to populate MCLK during PopulateNewDPMClocksStates Function!",
+				return result);
+	}
+
+	return result;
+}
+
+static int polaris10_trim_single_dpm_states(struct pp_hwmgr *hwmgr,
+			  struct polaris10_single_dpm_table *dpm_table,
+			uint32_t low_limit, uint32_t high_limit)
+{
+	uint32_t i;
+
+	for (i = 0; i < dpm_table->count; i++) {
+		if ((dpm_table->dpm_levels[i].value < low_limit)
+		|| (dpm_table->dpm_levels[i].value > high_limit))
+			dpm_table->dpm_levels[i].enabled = false;
+		else
+			dpm_table->dpm_levels[i].enabled = true;
+	}
+
+	return 0;
+}
+
+static int polaris10_trim_dpm_states(struct pp_hwmgr *hwmgr,
+		const struct polaris10_power_state *polaris10_ps)
+{
+	int result = 0;
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	uint32_t high_limit_count;
+
+	PP_ASSERT_WITH_CODE((polaris10_ps->performance_level_count >= 1),
+			"power state did not have any performance level",
+			return -1);
+
+	high_limit_count = (1 == polaris10_ps->performance_level_count) ? 0 : 1;
+
+	polaris10_trim_single_dpm_states(hwmgr,
+			&(data->dpm_table.sclk_table),
+			polaris10_ps->performance_levels[0].engine_clock,
+			polaris10_ps->performance_levels[high_limit_count].engine_clock);
+
+	polaris10_trim_single_dpm_states(hwmgr,
+			&(data->dpm_table.mclk_table),
+			polaris10_ps->performance_levels[0].memory_clock,
+			polaris10_ps->performance_levels[high_limit_count].memory_clock);
+
+	return result;
+}
+
+static int polaris10_generate_dpm_level_enable_mask(
+		struct pp_hwmgr *hwmgr, const void *input)
+{
+	int result;
+	const struct phm_set_power_state_input *states =
+			(const struct phm_set_power_state_input *)input;
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	const struct polaris10_power_state *polaris10_ps =
+			cast_const_phw_polaris10_power_state(states->pnew_state);
+
+	result = polaris10_trim_dpm_states(hwmgr, polaris10_ps);
+	if (result)
+		return result;
+
+	data->dpm_level_enable_mask.sclk_dpm_enable_mask =
+			phm_get_dpm_level_enable_mask_value(&data->dpm_table.sclk_table);
+	data->dpm_level_enable_mask.mclk_dpm_enable_mask =
+			phm_get_dpm_level_enable_mask_value(&data->dpm_table.mclk_table);
+	data->dpm_level_enable_mask.pcie_dpm_enable_mask =
+			phm_get_dpm_level_enable_mask_value(&data->dpm_table.pcie_speed_table);
+
+	return 0;
+}
+
+int polaris10_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable)
+{
+	return smum_send_msg_to_smc(hwmgr->smumgr, enable ?
+			PPSMC_MSG_UVDDPM_Enable :
+			PPSMC_MSG_UVDDPM_Disable);
+}
+
+int polaris10_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable)
+{
+	return smum_send_msg_to_smc(hwmgr->smumgr, enable?
+			PPSMC_MSG_VCEDPM_Enable :
+			PPSMC_MSG_VCEDPM_Disable);
+}
+
+int polaris10_enable_disable_samu_dpm(struct pp_hwmgr *hwmgr, bool enable)
+{
+	return smum_send_msg_to_smc(hwmgr->smumgr, enable?
+			PPSMC_MSG_SAMUDPM_Enable :
+			PPSMC_MSG_SAMUDPM_Disable);
+}
+
+int polaris10_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	uint32_t mm_boot_level_offset, mm_boot_level_value;
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+
+	if (!bgate) {
+		data->smc_state_table.UvdBootLevel = 0;
+		if (table_info->mm_dep_table->count > 0)
+			data->smc_state_table.UvdBootLevel =
+					(uint8_t) (table_info->mm_dep_table->count - 1);
+		mm_boot_level_offset = data->dpm_table_start +
+				offsetof(SMU74_Discrete_DpmTable, UvdBootLevel);
+		mm_boot_level_offset /= 4;
+		mm_boot_level_offset *= 4;
+		mm_boot_level_value = cgs_read_ind_register(hwmgr->device,
+				CGS_IND_REG__SMC, mm_boot_level_offset);
+		mm_boot_level_value &= 0x00FFFFFF;
+		mm_boot_level_value |= data->smc_state_table.UvdBootLevel << 24;
+		cgs_write_ind_register(hwmgr->device,
+				CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value);
+
+		if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_UVDDPM) ||
+			phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_StablePState))
+			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+					PPSMC_MSG_UVDDPM_SetEnabledMask,
+					(uint32_t)(1 << data->smc_state_table.UvdBootLevel));
+	}
+
+	return polaris10_enable_disable_uvd_dpm(hwmgr, !bgate);
+}
+
+static int polaris10_update_vce_dpm(struct pp_hwmgr *hwmgr, const void *input)
+{
+	const struct phm_set_power_state_input *states =
+			(const struct phm_set_power_state_input *)input;
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	const struct polaris10_power_state *polaris10_nps =
+			cast_const_phw_polaris10_power_state(states->pnew_state);
+	const struct polaris10_power_state *polaris10_cps =
+			cast_const_phw_polaris10_power_state(states->pcurrent_state);
+
+	uint32_t mm_boot_level_offset, mm_boot_level_value;
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+
+	if (polaris10_nps->vce_clks.evclk > 0 &&
+	(polaris10_cps == NULL || polaris10_cps->vce_clks.evclk == 0)) {
+
+		data->smc_state_table.VceBootLevel =
+				(uint8_t) (table_info->mm_dep_table->count - 1);
+
+		mm_boot_level_offset = data->dpm_table_start +
+				offsetof(SMU74_Discrete_DpmTable, VceBootLevel);
+		mm_boot_level_offset /= 4;
+		mm_boot_level_offset *= 4;
+		mm_boot_level_value = cgs_read_ind_register(hwmgr->device,
+				CGS_IND_REG__SMC, mm_boot_level_offset);
+		mm_boot_level_value &= 0xFF00FFFF;
+		mm_boot_level_value |= data->smc_state_table.VceBootLevel << 16;
+		cgs_write_ind_register(hwmgr->device,
+				CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value);
+
+		if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState)) {
+			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+					PPSMC_MSG_VCEDPM_SetEnabledMask,
+					(uint32_t)1 << data->smc_state_table.VceBootLevel);
+
+			polaris10_enable_disable_vce_dpm(hwmgr, true);
+		} else if (polaris10_nps->vce_clks.evclk == 0 &&
+				polaris10_cps != NULL &&
+				polaris10_cps->vce_clks.evclk > 0)
+			polaris10_enable_disable_vce_dpm(hwmgr, false);
+	}
+
+	return 0;
+}
+
+int polaris10_update_samu_dpm(struct pp_hwmgr *hwmgr, bool bgate)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	uint32_t mm_boot_level_offset, mm_boot_level_value;
+
+	if (!bgate) {
+		data->smc_state_table.SamuBootLevel = 0;
+		mm_boot_level_offset = data->dpm_table_start +
+				offsetof(SMU74_Discrete_DpmTable, SamuBootLevel);
+		mm_boot_level_offset /= 4;
+		mm_boot_level_offset *= 4;
+		mm_boot_level_value = cgs_read_ind_register(hwmgr->device,
+				CGS_IND_REG__SMC, mm_boot_level_offset);
+		mm_boot_level_value &= 0xFFFFFF00;
+		mm_boot_level_value |= data->smc_state_table.SamuBootLevel << 0;
+		cgs_write_ind_register(hwmgr->device,
+				CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value);
+
+		if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_StablePState))
+			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+					PPSMC_MSG_SAMUDPM_SetEnabledMask,
+					(uint32_t)(1 << data->smc_state_table.SamuBootLevel));
+	}
+
+	return polaris10_enable_disable_samu_dpm(hwmgr, !bgate);
+}
+
+static int polaris10_update_sclk_threshold(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+
+	int result = 0;
+	uint32_t low_sclk_interrupt_threshold = 0;
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_SclkThrottleLowNotification)
+		&& (hwmgr->gfx_arbiter.sclk_threshold !=
+				data->low_sclk_interrupt_threshold)) {
+		data->low_sclk_interrupt_threshold =
+				hwmgr->gfx_arbiter.sclk_threshold;
+		low_sclk_interrupt_threshold =
+				data->low_sclk_interrupt_threshold;
+
+		CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold);
+
+		result = polaris10_copy_bytes_to_smc(
+				hwmgr->smumgr,
+				data->dpm_table_start +
+				offsetof(SMU74_Discrete_DpmTable,
+					LowSclkInterruptThreshold),
+				(uint8_t *)&low_sclk_interrupt_threshold,
+				sizeof(uint32_t),
+				data->sram_end);
+	}
+
+	return result;
+}
+
+static int polaris10_program_mem_timing_parameters(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+
+	if (data->need_update_smu7_dpm_table &
+		(DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_OD_UPDATE_MCLK))
+		return polaris10_program_memory_timing_parameters(hwmgr);
+
+	return 0;
+}
+
+static int polaris10_unfreeze_sclk_mclk_dpm(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+
+	if (0 == data->need_update_smu7_dpm_table)
+		return 0;
+
+	if ((0 == data->sclk_dpm_key_disabled) &&
+		(data->need_update_smu7_dpm_table &
+		(DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK))) {
+
+		PP_ASSERT_WITH_CODE(true == polaris10_is_dpm_running(hwmgr),
+				"Trying to Unfreeze SCLK DPM when DPM is disabled",
+				);
+		PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr->smumgr,
+				PPSMC_MSG_SCLKDPM_UnfreezeLevel),
+			"Failed to unfreeze SCLK DPM during UnFreezeSclkMclkDPM Function!",
+			return -1);
+	}
+
+	if ((0 == data->mclk_dpm_key_disabled) &&
+		(data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK)) {
+
+		PP_ASSERT_WITH_CODE(true == polaris10_is_dpm_running(hwmgr),
+				"Trying to Unfreeze MCLK DPM when DPM is disabled",
+				);
+		PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr->smumgr,
+				PPSMC_MSG_SCLKDPM_UnfreezeLevel),
+		    "Failed to unfreeze MCLK DPM during UnFreezeSclkMclkDPM Function!",
+		    return -1);
+	}
+
+	data->need_update_smu7_dpm_table = 0;
+
+	return 0;
+}
+
+static int polaris10_notify_link_speed_change_after_state_change(
+		struct pp_hwmgr *hwmgr, const void *input)
+{
+	const struct phm_set_power_state_input *states =
+			(const struct phm_set_power_state_input *)input;
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	const struct polaris10_power_state *polaris10_ps =
+			cast_const_phw_polaris10_power_state(states->pnew_state);
+	uint16_t target_link_speed = polaris10_get_maximum_link_speed(hwmgr, polaris10_ps);
+	uint8_t  request;
+
+	if (data->pspp_notify_required) {
+		if (target_link_speed == PP_PCIEGen3)
+			request = PCIE_PERF_REQ_GEN3;
+		else if (target_link_speed == PP_PCIEGen2)
+			request = PCIE_PERF_REQ_GEN2;
+		else
+			request = PCIE_PERF_REQ_GEN1;
+
+		if (request == PCIE_PERF_REQ_GEN1 &&
+				phm_get_current_pcie_speed(hwmgr) > 0)
+			return 0;
+
+		if (acpi_pcie_perf_request(hwmgr->device, request, false)) {
+			if (PP_PCIEGen2 == target_link_speed)
+				printk("PSPP request to switch to Gen2 from Gen3 Failed!");
+			else
+				printk("PSPP request to switch to Gen1 from Gen2 Failed!");
+		}
+	}
+
+	return 0;
+}
+
+static int polaris10_notify_smc_display(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+
+	smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+		(PPSMC_Msg)PPSMC_MSG_SetVBITimeout, data->frame_time_x2);
+	return (smum_send_msg_to_smc(hwmgr->smumgr, (PPSMC_Msg)PPSMC_HasDisplay) == 0) ?  0 : -EINVAL;
+}
+
+static int polaris10_set_power_state_tasks(struct pp_hwmgr *hwmgr, const void *input)
+{
+	int tmp_result, result = 0;
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+
+	tmp_result = polaris10_find_dpm_states_clocks_in_dpm_table(hwmgr, input);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to find DPM states clocks in DPM table!",
+			result = tmp_result);
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_PCIEPerformanceRequest)) {
+		tmp_result =
+			polaris10_request_link_speed_change_before_state_change(hwmgr, input);
+		PP_ASSERT_WITH_CODE((0 == tmp_result),
+				"Failed to request link speed change before state change!",
+				result = tmp_result);
+	}
+
+	tmp_result = polaris10_freeze_sclk_mclk_dpm(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to freeze SCLK MCLK DPM!", result = tmp_result);
+
+	tmp_result = polaris10_populate_and_upload_sclk_mclk_dpm_levels(hwmgr, input);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to populate and upload SCLK MCLK DPM levels!",
+			result = tmp_result);
+
+	tmp_result = polaris10_generate_dpm_level_enable_mask(hwmgr, input);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to generate DPM level enabled mask!",
+			result = tmp_result);
+
+	tmp_result = polaris10_update_vce_dpm(hwmgr, input);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to update VCE DPM!",
+			result = tmp_result);
+
+	tmp_result = polaris10_update_sclk_threshold(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to update SCLK threshold!",
+			result = tmp_result);
+
+	tmp_result = polaris10_program_mem_timing_parameters(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to program memory timing parameters!",
+			result = tmp_result);
+
+	tmp_result = polaris10_notify_smc_display(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to notify smc display settings!",
+			result = tmp_result);
+
+	tmp_result = polaris10_unfreeze_sclk_mclk_dpm(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to unfreeze SCLK MCLK DPM!",
+			result = tmp_result);
+
+	tmp_result = polaris10_upload_dpm_level_enable_mask(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to upload DPM level enabled mask!",
+			result = tmp_result);
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_PCIEPerformanceRequest)) {
+		tmp_result =
+			polaris10_notify_link_speed_change_after_state_change(hwmgr, input);
+		PP_ASSERT_WITH_CODE((0 == tmp_result),
+				"Failed to notify link speed change after state change!",
+				result = tmp_result);
+	}
+	data->apply_optimized_settings = false;
+	return result;
+}
+
+static int polaris10_set_max_fan_pwm_output(struct pp_hwmgr *hwmgr, uint16_t us_max_fan_pwm)
+{
+	hwmgr->thermal_controller.
+	advanceFanControlParameters.usMaxFanPWM = us_max_fan_pwm;
+
+	if (phm_is_hw_access_blocked(hwmgr))
+		return 0;
+
+	return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+			PPSMC_MSG_SetFanPwmMax, us_max_fan_pwm);
+}
+
+
+int polaris10_notify_smc_display_change(struct pp_hwmgr *hwmgr, bool has_display)
+{
+	PPSMC_Msg msg = has_display ? (PPSMC_Msg)PPSMC_HasDisplay : (PPSMC_Msg)PPSMC_NoDisplay;
+
+	return (smum_send_msg_to_smc(hwmgr->smumgr, msg) == 0) ?  0 : -1;
+}
+
+int polaris10_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr)
+{
+	uint32_t num_active_displays = 0;
+	struct cgs_display_info info = {0};
+	info.mode_info = NULL;
+
+	cgs_get_active_displays_info(hwmgr->device, &info);
+
+	num_active_displays = info.display_count;
+
+	if (num_active_displays > 1)  /* to do && (pHwMgr->pPECI->displayConfiguration.bMultiMonitorInSync != TRUE)) */
+		polaris10_notify_smc_display_change(hwmgr, false);
+
+	return 0;
+}
+
+/**
+* Programs the display gap
+*
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @return   always OK
+*/
+int polaris10_program_display_gap(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	uint32_t num_active_displays = 0;
+	uint32_t display_gap = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_DISPLAY_GAP_CNTL);
+	uint32_t display_gap2;
+	uint32_t pre_vbi_time_in_us;
+	uint32_t frame_time_in_us;
+	uint32_t ref_clock;
+	uint32_t refresh_rate = 0;
+	struct cgs_display_info info = {0};
+	struct cgs_mode_info mode_info;
+
+	info.mode_info = &mode_info;
+
+	cgs_get_active_displays_info(hwmgr->device, &info);
+	num_active_displays = info.display_count;
+
+	display_gap = PHM_SET_FIELD(display_gap, CG_DISPLAY_GAP_CNTL, DISP_GAP, (num_active_displays > 0) ? DISPLAY_GAP_VBLANK_OR_WM : DISPLAY_GAP_IGNORE);
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_DISPLAY_GAP_CNTL, display_gap);
+
+	ref_clock = mode_info.ref_clock;
+	refresh_rate = mode_info.refresh_rate;
+
+	if (0 == refresh_rate)
+		refresh_rate = 60;
+
+	frame_time_in_us = 1000000 / refresh_rate;
+
+	pre_vbi_time_in_us = frame_time_in_us - 200 - mode_info.vblank_time_us;
+	data->frame_time_x2 = frame_time_in_us * 2 / 100;
+
+	display_gap2 = pre_vbi_time_in_us * (ref_clock / 100);
+
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_DISPLAY_GAP_CNTL2, display_gap2);
+
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, data->soft_regs_start + offsetof(SMU74_SoftRegisters, PreVBlankGap), 0x64);
+
+	cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, data->soft_regs_start + offsetof(SMU74_SoftRegisters, VBlankTimeout), (frame_time_in_us - pre_vbi_time_in_us));
+
+	return 0;
+}
+
+
+int polaris10_display_configuration_changed_task(struct pp_hwmgr *hwmgr)
+{
+	return polaris10_program_display_gap(hwmgr);
+}
+
+/**
+*  Set maximum target operating fan output RPM
+*
+* @param    hwmgr:  the address of the powerplay hardware manager.
+* @param    usMaxFanRpm:  max operating fan RPM value.
+* @return   The response that came from the SMC.
+*/
+static int polaris10_set_max_fan_rpm_output(struct pp_hwmgr *hwmgr, uint16_t us_max_fan_rpm)
+{
+	hwmgr->thermal_controller.
+	advanceFanControlParameters.usMaxFanRPM = us_max_fan_rpm;
+
+	if (phm_is_hw_access_blocked(hwmgr))
+		return 0;
+
+	return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+			PPSMC_MSG_SetFanRpmMax, us_max_fan_rpm);
+}
+
+int polaris10_register_internal_thermal_interrupt(struct pp_hwmgr *hwmgr,
+					const void *thermal_interrupt_info)
+{
+	return 0;
+}
+
+bool polaris10_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	bool is_update_required = false;
+	struct cgs_display_info info = {0, 0, NULL};
+
+	cgs_get_active_displays_info(hwmgr->device, &info);
+
+	if (data->display_timing.num_existing_displays != info.display_count)
+		is_update_required = true;
+/* TO DO NEED TO GET DEEP SLEEP CLOCK FROM DAL
+	if (phm_cap_enabled(hwmgr->hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) {
+		cgs_get_min_clock_settings(hwmgr->device, &min_clocks);
+		if (min_clocks.engineClockInSR != data->display_timing.minClockInSR &&
+			(min_clocks.engineClockInSR >= POLARIS10_MINIMUM_ENGINE_CLOCK ||
+				data->display_timing.minClockInSR >= POLARIS10_MINIMUM_ENGINE_CLOCK))
+			is_update_required = true;
+*/
+	return is_update_required;
+}
+
+static inline bool polaris10_are_power_levels_equal(const struct polaris10_performance_level *pl1,
+							   const struct polaris10_performance_level *pl2)
+{
+	return ((pl1->memory_clock == pl2->memory_clock) &&
+		  (pl1->engine_clock == pl2->engine_clock) &&
+		  (pl1->pcie_gen == pl2->pcie_gen) &&
+		  (pl1->pcie_lane == pl2->pcie_lane));
+}
+
+int polaris10_check_states_equal(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *pstate1, const struct pp_hw_power_state *pstate2, bool *equal)
+{
+	const struct polaris10_power_state *psa = cast_const_phw_polaris10_power_state(pstate1);
+	const struct polaris10_power_state *psb = cast_const_phw_polaris10_power_state(pstate2);
+	int i;
+
+	if (pstate1 == NULL || pstate2 == NULL || equal == NULL)
+		return -EINVAL;
+
+	/* If the two states don't even have the same number of performance levels they cannot be the same state. */
+	if (psa->performance_level_count != psb->performance_level_count) {
+		*equal = false;
+		return 0;
+	}
+
+	for (i = 0; i < psa->performance_level_count; i++) {
+		if (!polaris10_are_power_levels_equal(&(psa->performance_levels[i]), &(psb->performance_levels[i]))) {
+			/* If we have found even one performance level pair that is different the states are different. */
+			*equal = false;
+			return 0;
+		}
+	}
+
+	/* If all performance levels are the same try to use the UVD clocks to break the tie.*/
+	*equal = ((psa->uvd_clks.vclk == psb->uvd_clks.vclk) && (psa->uvd_clks.dclk == psb->uvd_clks.dclk));
+	*equal &= ((psa->vce_clks.evclk == psb->vce_clks.evclk) && (psa->vce_clks.ecclk == psb->vce_clks.ecclk));
+	*equal &= (psa->sclk_threshold == psb->sclk_threshold);
+
+	return 0;
+}
+
+int polaris10_upload_mc_firmware(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+
+	uint32_t vbios_version;
+
+	/*  Read MC indirect register offset 0x9F bits [3:0] to see if VBIOS has already loaded a full version of MC ucode or not.*/
+
+	phm_get_mc_microcode_version(hwmgr);
+	vbios_version = hwmgr->microcode_version_info.MC & 0xf;
+	/*  Full version of MC ucode has already been loaded. */
+	if (vbios_version == 0) {
+		data->need_long_memory_training = false;
+		return 0;
+	}
+
+	data->need_long_memory_training = false;
+
+/*
+ *	PPMCME_FirmwareDescriptorEntry *pfd = NULL;
+	pfd = &tonga_mcmeFirmware;
+	if (0 == PHM_READ_FIELD(hwmgr->device, MC_SEQ_SUP_CNTL, RUN))
+		polaris10_load_mc_microcode(hwmgr, pfd->dpmThreshold,
+					pfd->cfgArray, pfd->cfgSize, pfd->ioDebugArray,
+					pfd->ioDebugSize, pfd->ucodeArray, pfd->ucodeSize);
+*/
+	return 0;
+}
+
+/**
+ * Read clock related registers.
+ *
+ * @param    hwmgr  the address of the powerplay hardware manager.
+ * @return   always 0
+ */
+static int polaris10_read_clock_registers(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+
+	data->clock_registers.vCG_SPLL_FUNC_CNTL = cgs_read_ind_register(hwmgr->device,
+						CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL)
+						& CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN_MASK;
+
+	data->clock_registers.vCG_SPLL_FUNC_CNTL_2 = cgs_read_ind_register(hwmgr->device,
+						CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL_2)
+						& CG_SPLL_FUNC_CNTL_2__SCLK_MUX_SEL_MASK;
+
+	data->clock_registers.vCG_SPLL_FUNC_CNTL_4 = cgs_read_ind_register(hwmgr->device,
+						CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL_4)
+						& CG_SPLL_FUNC_CNTL_4__SPLL_SPARE_MASK;
+
+	return 0;
+}
+
+/**
+ * Find out if memory is GDDR5.
+ *
+ * @param    hwmgr  the address of the powerplay hardware manager.
+ * @return   always 0
+ */
+static int polaris10_get_memory_type(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	uint32_t temp;
+
+	temp = cgs_read_register(hwmgr->device, mmMC_SEQ_MISC0);
+
+	data->is_memory_gddr5 = (MC_SEQ_MISC0_GDDR5_VALUE ==
+			((temp & MC_SEQ_MISC0_GDDR5_MASK) >>
+			 MC_SEQ_MISC0_GDDR5_SHIFT));
+
+	return 0;
+}
+
+/**
+ * Enables Dynamic Power Management by SMC
+ *
+ * @param    hwmgr  the address of the powerplay hardware manager.
+ * @return   always 0
+ */
+static int polaris10_enable_acpi_power_management(struct pp_hwmgr *hwmgr)
+{
+	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			GENERAL_PWRMGT, STATIC_PM_EN, 1);
+
+	return 0;
+}
+
+/**
+ * Initialize PowerGating States for different engines
+ *
+ * @param    hwmgr  the address of the powerplay hardware manager.
+ * @return   always 0
+ */
+static int polaris10_init_power_gate_state(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+
+	data->uvd_power_gated = false;
+	data->vce_power_gated = false;
+	data->samu_power_gated = false;
+
+	return 0;
+}
+
+static int polaris10_init_sclk_threshold(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	data->low_sclk_interrupt_threshold = 0;
+
+	return 0;
+}
+
+int polaris10_setup_asic_task(struct pp_hwmgr *hwmgr)
+{
+	int tmp_result, result = 0;
+
+	polaris10_upload_mc_firmware(hwmgr);
+
+	tmp_result = polaris10_read_clock_registers(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to read clock registers!", result = tmp_result);
+
+	tmp_result = polaris10_get_memory_type(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to get memory type!", result = tmp_result);
+
+	tmp_result = polaris10_enable_acpi_power_management(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to enable ACPI power management!", result = tmp_result);
+
+	tmp_result = polaris10_init_power_gate_state(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to init power gate state!", result = tmp_result);
+
+	tmp_result = phm_get_mc_microcode_version(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to get MC microcode version!", result = tmp_result);
+
+	tmp_result = polaris10_init_sclk_threshold(hwmgr);
+	PP_ASSERT_WITH_CODE((0 == tmp_result),
+			"Failed to init sclk threshold!", result = tmp_result);
+
+	return result;
+}
+
+static int polaris10_get_pp_table(struct pp_hwmgr *hwmgr, char **table)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+
+	if (!data->soft_pp_table) {
+		data->soft_pp_table = kmemdup(hwmgr->soft_pp_table,
+					      hwmgr->soft_pp_table_size,
+					      GFP_KERNEL);
+		if (!data->soft_pp_table)
+			return -ENOMEM;
+	}
+
+	*table = (char *)&data->soft_pp_table;
+
+	return hwmgr->soft_pp_table_size;
+}
+
+static int polaris10_set_pp_table(struct pp_hwmgr *hwmgr, const char *buf, size_t size)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+
+	if (!data->soft_pp_table) {
+		data->soft_pp_table = kzalloc(hwmgr->soft_pp_table_size, GFP_KERNEL);
+		if (!data->soft_pp_table)
+			return -ENOMEM;
+	}
+
+	memcpy(data->soft_pp_table, buf, size);
+
+	hwmgr->soft_pp_table = data->soft_pp_table;
+
+	/* TODO: re-init powerplay to implement modified pptable */
+
+	return 0;
+}
+
+static int polaris10_force_clock_level(struct pp_hwmgr *hwmgr,
+		enum pp_clock_type type, uint32_t mask)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+
+	if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL)
+		return -EINVAL;
+
+	switch (type) {
+	case PP_SCLK:
+		if (!data->sclk_dpm_key_disabled)
+			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+					PPSMC_MSG_SCLKDPM_SetEnabledMask,
+					data->dpm_level_enable_mask.sclk_dpm_enable_mask & mask);
+		break;
+	case PP_MCLK:
+		if (!data->mclk_dpm_key_disabled)
+			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+					PPSMC_MSG_MCLKDPM_SetEnabledMask,
+					data->dpm_level_enable_mask.mclk_dpm_enable_mask & mask);
+		break;
+	case PP_PCIE:
+	{
+		uint32_t tmp = mask & data->dpm_level_enable_mask.pcie_dpm_enable_mask;
+		uint32_t level = 0;
+
+		while (tmp >>= 1)
+			level++;
+
+		if (!data->pcie_dpm_key_disabled)
+			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+					PPSMC_MSG_PCIeDPM_ForceLevel,
+					level);
+		break;
+	}
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static uint16_t polaris10_get_current_pcie_speed(struct pp_hwmgr *hwmgr)
+{
+	uint32_t speedCntl = 0;
+
+	/* mmPCIE_PORT_INDEX rename as mmPCIE_INDEX */
+	speedCntl = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__PCIE,
+			ixPCIE_LC_SPEED_CNTL);
+	return((uint16_t)PHM_GET_FIELD(speedCntl,
+			PCIE_LC_SPEED_CNTL, LC_CURRENT_DATA_RATE));
+}
+
+static int polaris10_print_clock_levels(struct pp_hwmgr *hwmgr,
+		enum pp_clock_type type, char *buf)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	struct polaris10_single_dpm_table *sclk_table = &(data->dpm_table.sclk_table);
+	struct polaris10_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table);
+	struct polaris10_single_dpm_table *pcie_table = &(data->dpm_table.pcie_speed_table);
+	int i, now, size = 0;
+	uint32_t clock, pcie_speed;
+
+	switch (type) {
+	case PP_SCLK:
+		smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_API_GetSclkFrequency);
+		clock = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0);
+
+		for (i = 0; i < sclk_table->count; i++) {
+			if (clock > sclk_table->dpm_levels[i].value)
+				continue;
+			break;
+		}
+		now = i;
+
+		for (i = 0; i < sclk_table->count; i++)
+			size += sprintf(buf + size, "%d: %uMhz %s\n",
+					i, sclk_table->dpm_levels[i].value / 100,
+					(i == now) ? "*" : "");
+		break;
+	case PP_MCLK:
+		smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_API_GetMclkFrequency);
+		clock = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0);
+
+		for (i = 0; i < mclk_table->count; i++) {
+			if (clock > mclk_table->dpm_levels[i].value)
+				continue;
+			break;
+		}
+		now = i;
+
+		for (i = 0; i < mclk_table->count; i++)
+			size += sprintf(buf + size, "%d: %uMhz %s\n",
+					i, mclk_table->dpm_levels[i].value / 100,
+					(i == now) ? "*" : "");
+		break;
+	case PP_PCIE:
+		pcie_speed = polaris10_get_current_pcie_speed(hwmgr);
+		for (i = 0; i < pcie_table->count; i++) {
+			if (pcie_speed != pcie_table->dpm_levels[i].value)
+				continue;
+			break;
+		}
+		now = i;
+
+		for (i = 0; i < pcie_table->count; i++)
+			size += sprintf(buf + size, "%d: %s %s\n", i,
+					(pcie_table->dpm_levels[i].value == 0) ? "2.5GB, x8" :
+					(pcie_table->dpm_levels[i].value == 1) ? "5.0GB, x16" :
+					(pcie_table->dpm_levels[i].value == 2) ? "8.0GB, x16" : "",
+					(i == now) ? "*" : "");
+		break;
+	default:
+		break;
+	}
+	return size;
+}
+
+static int polaris10_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode)
+{
+	if (mode) {
+		/* stop auto-manage */
+		if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_MicrocodeFanControl))
+			polaris10_fan_ctrl_stop_smc_fan_control(hwmgr);
+		polaris10_fan_ctrl_set_static_mode(hwmgr, mode);
+	} else
+		/* restart auto-manage */
+		polaris10_fan_ctrl_reset_fan_speed_to_default(hwmgr);
+
+	return 0;
+}
+
+static int polaris10_get_fan_control_mode(struct pp_hwmgr *hwmgr)
+{
+	if (hwmgr->fan_ctrl_is_in_default_mode)
+		return hwmgr->fan_ctrl_default_mode;
+	else
+		return PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+				CG_FDO_CTRL2, FDO_PWM_MODE);
+}
+
+static const struct pp_hwmgr_func polaris10_hwmgr_funcs = {
+	.backend_init = &polaris10_hwmgr_backend_init,
+	.backend_fini = &polaris10_hwmgr_backend_fini,
+	.asic_setup = &polaris10_setup_asic_task,
+	.dynamic_state_management_enable = &polaris10_enable_dpm_tasks,
+	.apply_state_adjust_rules = polaris10_apply_state_adjust_rules,
+	.force_dpm_level = &polaris10_force_dpm_level,
+	.power_state_set = polaris10_set_power_state_tasks,
+	.get_power_state_size = polaris10_get_power_state_size,
+	.get_mclk = polaris10_dpm_get_mclk,
+	.get_sclk = polaris10_dpm_get_sclk,
+	.patch_boot_state = polaris10_dpm_patch_boot_state,
+	.get_pp_table_entry = polaris10_get_pp_table_entry,
+	.get_num_of_pp_table_entries = tonga_get_number_of_powerplay_table_entries,
+	.print_current_perforce_level = polaris10_print_current_perforce_level,
+	.powerdown_uvd = polaris10_phm_powerdown_uvd,
+	.powergate_uvd = polaris10_phm_powergate_uvd,
+	.powergate_vce = polaris10_phm_powergate_vce,
+	.disable_clock_power_gating = polaris10_phm_disable_clock_power_gating,
+	.update_clock_gatings = polaris10_phm_update_clock_gatings,
+	.notify_smc_display_config_after_ps_adjustment = polaris10_notify_smc_display_config_after_ps_adjustment,
+	.display_config_changed = polaris10_display_configuration_changed_task,
+	.set_max_fan_pwm_output = polaris10_set_max_fan_pwm_output,
+	.set_max_fan_rpm_output = polaris10_set_max_fan_rpm_output,
+	.get_temperature = polaris10_thermal_get_temperature,
+	.stop_thermal_controller = polaris10_thermal_stop_thermal_controller,
+	.get_fan_speed_info = polaris10_fan_ctrl_get_fan_speed_info,
+	.get_fan_speed_percent = polaris10_fan_ctrl_get_fan_speed_percent,
+	.set_fan_speed_percent = polaris10_fan_ctrl_set_fan_speed_percent,
+	.reset_fan_speed_to_default = polaris10_fan_ctrl_reset_fan_speed_to_default,
+	.get_fan_speed_rpm = polaris10_fan_ctrl_get_fan_speed_rpm,
+	.set_fan_speed_rpm = polaris10_fan_ctrl_set_fan_speed_rpm,
+	.uninitialize_thermal_controller = polaris10_thermal_ctrl_uninitialize_thermal_controller,
+	.register_internal_thermal_interrupt = polaris10_register_internal_thermal_interrupt,
+	.check_smc_update_required_for_display_configuration = polaris10_check_smc_update_required_for_display_configuration,
+	.check_states_equal = polaris10_check_states_equal,
+	.set_fan_control_mode = polaris10_set_fan_control_mode,
+	.get_fan_control_mode = polaris10_get_fan_control_mode,
+	.get_pp_table = polaris10_get_pp_table,
+	.set_pp_table = polaris10_set_pp_table,
+	.force_clock_level = polaris10_force_clock_level,
+	.print_clock_levels = polaris10_print_clock_levels,
+	.enable_per_cu_power_gating = polaris10_phm_enable_per_cu_power_gating,
+};
+
+int polaris10_hwmgr_init(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr  *data;
+
+	data = kzalloc (sizeof(struct polaris10_hwmgr), GFP_KERNEL);
+	if (data == NULL)
+		return -ENOMEM;
+
+	hwmgr->backend = data;
+	hwmgr->hwmgr_func = &polaris10_hwmgr_funcs;
+	hwmgr->pptable_func = &tonga_pptable_funcs;
+	pp_polaris10_thermal_initialize(hwmgr);
+
+	return 0;
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,361 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef POLARIS10_HWMGR_H
+#define POLARIS10_HWMGR_H
+
+#include "hwmgr.h"
+#include "smu74.h"
+#include "smu74_discrete.h"
+#include "ppatomctrl.h"
+#include "polaris10_ppsmc.h"
+#include "polaris10_powertune.h"
+
+#define POLARIS10_MAX_HARDWARE_POWERLEVELS	2
+
+#define POLARIS10_VOLTAGE_CONTROL_NONE                   0x0
+#define POLARIS10_VOLTAGE_CONTROL_BY_GPIO                0x1
+#define POLARIS10_VOLTAGE_CONTROL_BY_SVID2               0x2
+#define POLARIS10_VOLTAGE_CONTROL_MERGED                 0x3
+
+#define DPMTABLE_OD_UPDATE_SCLK     0x00000001
+#define DPMTABLE_OD_UPDATE_MCLK     0x00000002
+#define DPMTABLE_UPDATE_SCLK        0x00000004
+#define DPMTABLE_UPDATE_MCLK        0x00000008
+
+struct polaris10_performance_level {
+	uint32_t  memory_clock;
+	uint32_t  engine_clock;
+	uint16_t  pcie_gen;
+	uint16_t  pcie_lane;
+};
+
+struct polaris10_uvd_clocks {
+	uint32_t  vclk;
+	uint32_t  dclk;
+};
+
+struct polaris10_vce_clocks {
+	uint32_t  evclk;
+	uint32_t  ecclk;
+};
+
+struct polaris10_power_state {
+	uint32_t                  magic;
+	struct polaris10_uvd_clocks    uvd_clks;
+	struct polaris10_vce_clocks    vce_clks;
+	uint32_t                  sam_clk;
+	uint16_t                  performance_level_count;
+	bool                      dc_compatible;
+	uint32_t                  sclk_threshold;
+	struct polaris10_performance_level  performance_levels[POLARIS10_MAX_HARDWARE_POWERLEVELS];
+};
+
+struct polaris10_dpm_level {
+	bool	enabled;
+	uint32_t	value;
+	uint32_t	param1;
+};
+
+#define POLARIS10_MAX_DEEPSLEEP_DIVIDER_ID 5
+#define MAX_REGULAR_DPM_NUMBER 8
+#define POLARIS10_MINIMUM_ENGINE_CLOCK 2500
+
+struct polaris10_single_dpm_table {
+	uint32_t		count;
+	struct polaris10_dpm_level	dpm_levels[MAX_REGULAR_DPM_NUMBER];
+};
+
+struct polaris10_dpm_table {
+	struct polaris10_single_dpm_table  sclk_table;
+	struct polaris10_single_dpm_table  mclk_table;
+	struct polaris10_single_dpm_table  pcie_speed_table;
+	struct polaris10_single_dpm_table  vddc_table;
+	struct polaris10_single_dpm_table  vddci_table;
+	struct polaris10_single_dpm_table  mvdd_table;
+};
+
+struct polaris10_clock_registers {
+	uint32_t  vCG_SPLL_FUNC_CNTL;
+	uint32_t  vCG_SPLL_FUNC_CNTL_2;
+	uint32_t  vCG_SPLL_FUNC_CNTL_3;
+	uint32_t  vCG_SPLL_FUNC_CNTL_4;
+	uint32_t  vCG_SPLL_SPREAD_SPECTRUM;
+	uint32_t  vCG_SPLL_SPREAD_SPECTRUM_2;
+	uint32_t  vDLL_CNTL;
+	uint32_t  vMCLK_PWRMGT_CNTL;
+	uint32_t  vMPLL_AD_FUNC_CNTL;
+	uint32_t  vMPLL_DQ_FUNC_CNTL;
+	uint32_t  vMPLL_FUNC_CNTL;
+	uint32_t  vMPLL_FUNC_CNTL_1;
+	uint32_t  vMPLL_FUNC_CNTL_2;
+	uint32_t  vMPLL_SS1;
+	uint32_t  vMPLL_SS2;
+};
+
+#define DISABLE_MC_LOADMICROCODE   1
+#define DISABLE_MC_CFGPROGRAMMING  2
+
+struct polaris10_voltage_smio_registers {
+	uint32_t vS0_VID_LOWER_SMIO_CNTL;
+};
+
+#define POLARIS10_MAX_LEAKAGE_COUNT  8
+
+struct polaris10_leakage_voltage {
+	uint16_t  count;
+	uint16_t  leakage_id[POLARIS10_MAX_LEAKAGE_COUNT];
+	uint16_t  actual_voltage[POLARIS10_MAX_LEAKAGE_COUNT];
+};
+
+struct polaris10_vbios_boot_state {
+	uint16_t    mvdd_bootup_value;
+	uint16_t    vddc_bootup_value;
+	uint16_t    vddci_bootup_value;
+	uint32_t    sclk_bootup_value;
+	uint32_t    mclk_bootup_value;
+	uint16_t    pcie_gen_bootup_value;
+	uint16_t    pcie_lane_bootup_value;
+};
+
+/* Ultra Low Voltage parameter structure */
+struct polaris10_ulv_parm {
+	bool                           ulv_supported;
+	uint32_t                       cg_ulv_parameter;
+	uint32_t                       ulv_volt_change_delay;
+	struct polaris10_performance_level  ulv_power_level;
+};
+
+struct polaris10_display_timing {
+	uint32_t  min_clock_in_sr;
+	uint32_t  num_existing_displays;
+};
+
+struct polaris10_dpmlevel_enable_mask {
+	uint32_t  uvd_dpm_enable_mask;
+	uint32_t  vce_dpm_enable_mask;
+	uint32_t  acp_dpm_enable_mask;
+	uint32_t  samu_dpm_enable_mask;
+	uint32_t  sclk_dpm_enable_mask;
+	uint32_t  mclk_dpm_enable_mask;
+	uint32_t  pcie_dpm_enable_mask;
+};
+
+struct polaris10_pcie_perf_range {
+	uint16_t  max;
+	uint16_t  min;
+};
+struct polaris10_range_table {
+	uint32_t trans_lower_frequency; /* in 10khz */
+	uint32_t trans_upper_frequency;
+};
+
+struct polaris10_hwmgr {
+	struct polaris10_dpm_table			dpm_table;
+	struct polaris10_dpm_table			golden_dpm_table;
+	SMU74_Discrete_DpmTable				smc_state_table;
+	struct SMU74_Discrete_Ulv            ulv_setting;
+
+	struct polaris10_range_table                range_table[NUM_SCLK_RANGE];
+	uint32_t						voting_rights_clients0;
+	uint32_t						voting_rights_clients1;
+	uint32_t						voting_rights_clients2;
+	uint32_t						voting_rights_clients3;
+	uint32_t						voting_rights_clients4;
+	uint32_t						voting_rights_clients5;
+	uint32_t						voting_rights_clients6;
+	uint32_t						voting_rights_clients7;
+	uint32_t						static_screen_threshold_unit;
+	uint32_t						static_screen_threshold;
+	uint32_t						voltage_control;
+	uint32_t						vddc_vddci_delta;
+
+	uint32_t						active_auto_throttle_sources;
+
+	struct polaris10_clock_registers            clock_registers;
+	struct polaris10_voltage_smio_registers      voltage_smio_registers;
+
+	bool                           is_memory_gddr5;
+	uint16_t                       acpi_vddc;
+	bool                           pspp_notify_required;
+	uint16_t                       force_pcie_gen;
+	uint16_t                       acpi_pcie_gen;
+	uint32_t                       pcie_gen_cap;
+	uint32_t                       pcie_lane_cap;
+	uint32_t                       pcie_spc_cap;
+	struct polaris10_leakage_voltage          vddc_leakage;
+	struct polaris10_leakage_voltage          Vddci_leakage;
+
+	uint32_t                             mvdd_control;
+	uint32_t                             vddc_mask_low;
+	uint32_t                             mvdd_mask_low;
+	uint16_t                            max_vddc_in_pptable;
+	uint16_t                            min_vddc_in_pptable;
+	uint16_t                            max_vddci_in_pptable;
+	uint16_t                            min_vddci_in_pptable;
+	uint32_t                             mclk_strobe_mode_threshold;
+	uint32_t                             mclk_stutter_mode_threshold;
+	uint32_t                             mclk_edc_enable_threshold;
+	uint32_t                             mclk_edcwr_enable_threshold;
+	bool                                is_uvd_enabled;
+	struct polaris10_vbios_boot_state        vbios_boot_state;
+
+	bool                           pcie_performance_request;
+	bool                           battery_state;
+	bool                           is_tlu_enabled;
+
+	/* ---- SMC SRAM Address of firmware header tables ---- */
+	uint32_t                             sram_end;
+	uint32_t                             dpm_table_start;
+	uint32_t                             soft_regs_start;
+	uint32_t                             mc_reg_table_start;
+	uint32_t                             fan_table_start;
+	uint32_t                             arb_table_start;
+
+	/* ---- Stuff originally coming from Evergreen ---- */
+	uint32_t                             vddci_control;
+	struct pp_atomctrl_voltage_table     vddc_voltage_table;
+	struct pp_atomctrl_voltage_table     vddci_voltage_table;
+	struct pp_atomctrl_voltage_table     mvdd_voltage_table;
+
+	uint32_t                             mgcg_cgtt_local2;
+	uint32_t                             mgcg_cgtt_local3;
+	uint32_t                             gpio_debug;
+	uint32_t                             mc_micro_code_feature;
+	uint32_t                             highest_mclk;
+	uint16_t                             acpi_vddci;
+	uint8_t                              mvdd_high_index;
+	uint8_t                              mvdd_low_index;
+	bool                                 dll_default_on;
+	bool                                 performance_request_registered;
+
+	/* ---- Low Power Features ---- */
+	struct polaris10_ulv_parm                 ulv;
+
+	/* ---- CAC Stuff ---- */
+	uint32_t                       cac_table_start;
+	bool                           cac_configuration_required;
+	bool                           driver_calculate_cac_leakage;
+	bool                           cac_enabled;
+
+	/* ---- DPM2 Parameters ---- */
+	uint32_t                       power_containment_features;
+	bool                           enable_dte_feature;
+	bool                           enable_tdc_limit_feature;
+	bool                           enable_pkg_pwr_tracking_feature;
+	bool                           disable_uvd_power_tune_feature;
+	const struct polaris10_pt_defaults       *power_tune_defaults;
+	struct SMU74_Discrete_PmFuses  power_tune_table;
+	uint32_t                       dte_tj_offset;
+	uint32_t                       fast_watermark_threshold;
+
+	/* ---- Phase Shedding ---- */
+	bool                           vddc_phase_shed_control;
+
+	/* ---- DI/DT ---- */
+	struct polaris10_display_timing        display_timing;
+	uint32_t                      bif_sclk_table[SMU74_MAX_LEVELS_LINK];
+
+	/* ---- Thermal Temperature Setting ---- */
+	struct polaris10_dpmlevel_enable_mask     dpm_level_enable_mask;
+	uint32_t                                  need_update_smu7_dpm_table;
+	uint32_t                                  sclk_dpm_key_disabled;
+	uint32_t                                  mclk_dpm_key_disabled;
+	uint32_t                                  pcie_dpm_key_disabled;
+	uint32_t                                  min_engine_clocks;
+	struct polaris10_pcie_perf_range          pcie_gen_performance;
+	struct polaris10_pcie_perf_range          pcie_lane_performance;
+	struct polaris10_pcie_perf_range          pcie_gen_power_saving;
+	struct polaris10_pcie_perf_range          pcie_lane_power_saving;
+	bool                                      use_pcie_performance_levels;
+	bool                                      use_pcie_power_saving_levels;
+	uint32_t                                  activity_target[SMU74_MAX_LEVELS_GRAPHICS];
+	uint32_t                                  mclk_activity_target;
+	uint32_t                                  mclk_dpm0_activity_target;
+	uint32_t                                  low_sclk_interrupt_threshold;
+	uint32_t                                  last_mclk_dpm_enable_mask;
+	bool                                      uvd_enabled;
+
+	/* ---- Power Gating States ---- */
+	bool                           uvd_power_gated;
+	bool                           vce_power_gated;
+	bool                           samu_power_gated;
+	bool                           need_long_memory_training;
+
+	/* Application power optimization parameters */
+	bool                               update_up_hyst;
+	bool                               update_down_hyst;
+	uint32_t                           down_hyst;
+	uint32_t                           up_hyst;
+	uint32_t disable_dpm_mask;
+	bool apply_optimized_settings;
+
+	/* soft pptable for re-uploading into smu */
+	void *soft_pp_table;
+
+	uint32_t                              avfs_vdroop_override_setting;
+	bool                                  apply_avfs_cks_off_voltage;
+	uint32_t                              frame_time_x2;
+};
+
+/* To convert to Q8.8 format for firmware */
+#define POLARIS10_Q88_FORMAT_CONVERSION_UNIT             256
+
+enum Polaris10_I2CLineID {
+	Polaris10_I2CLineID_DDC1 = 0x90,
+	Polaris10_I2CLineID_DDC2 = 0x91,
+	Polaris10_I2CLineID_DDC3 = 0x92,
+	Polaris10_I2CLineID_DDC4 = 0x93,
+	Polaris10_I2CLineID_DDC5 = 0x94,
+	Polaris10_I2CLineID_DDC6 = 0x95,
+	Polaris10_I2CLineID_SCLSDA = 0x96,
+	Polaris10_I2CLineID_DDCVGA = 0x97
+};
+
+#define POLARIS10_I2C_DDC1DATA          0
+#define POLARIS10_I2C_DDC1CLK           1
+#define POLARIS10_I2C_DDC2DATA          2
+#define POLARIS10_I2C_DDC2CLK           3
+#define POLARIS10_I2C_DDC3DATA          4
+#define POLARIS10_I2C_DDC3CLK           5
+#define POLARIS10_I2C_SDA               40
+#define POLARIS10_I2C_SCL               41
+#define POLARIS10_I2C_DDC4DATA          65
+#define POLARIS10_I2C_DDC4CLK           66
+#define POLARIS10_I2C_DDC5DATA          0x48
+#define POLARIS10_I2C_DDC5CLK           0x49
+#define POLARIS10_I2C_DDC6DATA          0x4a
+#define POLARIS10_I2C_DDC6CLK           0x4b
+#define POLARIS10_I2C_DDCVGADATA        0x4c
+#define POLARIS10_I2C_DDCVGACLK         0x4d
+
+#define POLARIS10_UNUSED_GPIO_PIN       0x7F
+
+int polaris10_hwmgr_init(struct pp_hwmgr *hwmgr);
+
+int polaris10_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate);
+int polaris10_update_samu_dpm(struct pp_hwmgr *hwmgr, bool bgate);
+int polaris10_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable);
+
+#endif
+
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_powertune.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_powertune.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_powertune.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_powertune.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,398 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "hwmgr.h"
+#include "smumgr.h"
+#include "polaris10_hwmgr.h"
+#include "polaris10_powertune.h"
+#include "polaris10_smumgr.h"
+#include "smu74_discrete.h"
+#include "pp_debug.h"
+
+#define VOLTAGE_SCALE  4
+#define POWERTUNE_DEFAULT_SET_MAX    1
+
+static const struct polaris10_pt_defaults polaris10_power_tune_data_set_array[POWERTUNE_DEFAULT_SET_MAX] = {
+	/* sviLoadLIneEn, SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc, TDC_MAWt,
+	 * TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac, BAPM_TEMP_GRADIENT */
+	{ 1, 0xF, 0xFD, 0x19, 5, 45, 0, 0xB0000,
+	{ 0x79, 0x253, 0x25D, 0xAE, 0x72, 0x80, 0x83, 0x86, 0x6F, 0xC8, 0xC9, 0xC9, 0x2F, 0x4D, 0x61},
+	{ 0x17C, 0x172, 0x180, 0x1BC, 0x1B3, 0x1BD, 0x206, 0x200, 0x203, 0x25D, 0x25A, 0x255, 0x2C3, 0x2C5, 0x2B4 } },
+};
+
+void polaris10_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *polaris10_hwmgr = (struct polaris10_hwmgr *)(hwmgr->backend);
+	struct  phm_ppt_v1_information *table_info =
+			(struct  phm_ppt_v1_information *)(hwmgr->pptable);
+
+	if (table_info &&
+			table_info->cac_dtp_table->usPowerTuneDataSetID <= POWERTUNE_DEFAULT_SET_MAX &&
+			table_info->cac_dtp_table->usPowerTuneDataSetID)
+		polaris10_hwmgr->power_tune_defaults =
+				&polaris10_power_tune_data_set_array
+				[table_info->cac_dtp_table->usPowerTuneDataSetID - 1];
+	else
+		polaris10_hwmgr->power_tune_defaults = &polaris10_power_tune_data_set_array[0];
+
+}
+
+static uint16_t scale_fan_gain_settings(uint16_t raw_setting)
+{
+	uint32_t tmp;
+	tmp = raw_setting * 4096 / 100;
+	return (uint16_t)tmp;
+}
+
+int polaris10_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	const struct polaris10_pt_defaults *defaults = data->power_tune_defaults;
+	SMU74_Discrete_DpmTable  *dpm_table = &(data->smc_state_table);
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	struct phm_cac_tdp_table *cac_dtp_table = table_info->cac_dtp_table;
+	struct pp_advance_fan_control_parameters *fan_table=
+			&hwmgr->thermal_controller.advanceFanControlParameters;
+	int i, j, k;
+	const uint16_t *pdef1;
+	const uint16_t *pdef2;
+
+	dpm_table->DefaultTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usTDP * 128));
+	dpm_table->TargetTdp  = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usTDP * 128));
+
+	PP_ASSERT_WITH_CODE(cac_dtp_table->usTargetOperatingTemp <= 255,
+				"Target Operating Temp is out of Range!",
+				);
+
+	dpm_table->TemperatureLimitEdge = PP_HOST_TO_SMC_US(
+			cac_dtp_table->usTargetOperatingTemp * 256);
+	dpm_table->TemperatureLimitHotspot = PP_HOST_TO_SMC_US(
+			cac_dtp_table->usTemperatureLimitHotspot * 256);
+	dpm_table->FanGainEdge = PP_HOST_TO_SMC_US(
+			scale_fan_gain_settings(fan_table->usFanGainEdge));
+	dpm_table->FanGainHotspot = PP_HOST_TO_SMC_US(
+			scale_fan_gain_settings(fan_table->usFanGainHotspot));
+
+	pdef1 = defaults->BAPMTI_R;
+	pdef2 = defaults->BAPMTI_RC;
+
+	for (i = 0; i < SMU74_DTE_ITERATIONS; i++) {
+		for (j = 0; j < SMU74_DTE_SOURCES; j++) {
+			for (k = 0; k < SMU74_DTE_SINKS; k++) {
+				dpm_table->BAPMTI_R[i][j][k] = PP_HOST_TO_SMC_US(*pdef1);
+				dpm_table->BAPMTI_RC[i][j][k] = PP_HOST_TO_SMC_US(*pdef2);
+				pdef1++;
+				pdef2++;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static int polaris10_populate_svi_load_line(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	const struct polaris10_pt_defaults *defaults = data->power_tune_defaults;
+
+	data->power_tune_table.SviLoadLineEn = defaults->SviLoadLineEn;
+	data->power_tune_table.SviLoadLineVddC = defaults->SviLoadLineVddC;
+	data->power_tune_table.SviLoadLineTrimVddC = 3;
+	data->power_tune_table.SviLoadLineOffsetVddC = 0;
+
+	return 0;
+}
+
+static int polaris10_populate_tdc_limit(struct pp_hwmgr *hwmgr)
+{
+	uint16_t tdc_limit;
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	const struct polaris10_pt_defaults *defaults = data->power_tune_defaults;
+
+	tdc_limit = (uint16_t)(table_info->cac_dtp_table->usTDC * 128);
+	data->power_tune_table.TDC_VDDC_PkgLimit =
+			CONVERT_FROM_HOST_TO_SMC_US(tdc_limit);
+	data->power_tune_table.TDC_VDDC_ThrottleReleaseLimitPerc =
+			defaults->TDC_VDDC_ThrottleReleaseLimitPerc;
+	data->power_tune_table.TDC_MAWt = defaults->TDC_MAWt;
+
+	return 0;
+}
+
+static int polaris10_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	const struct polaris10_pt_defaults *defaults = data->power_tune_defaults;
+	uint32_t temp;
+
+	if (polaris10_read_smc_sram_dword(hwmgr->smumgr,
+			fuse_table_offset +
+			offsetof(SMU74_Discrete_PmFuses, TdcWaterfallCtl),
+			(uint32_t *)&temp, data->sram_end))
+		PP_ASSERT_WITH_CODE(false,
+				"Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!",
+				return -EINVAL);
+	else {
+		data->power_tune_table.TdcWaterfallCtl = defaults->TdcWaterfallCtl;
+		data->power_tune_table.LPMLTemperatureMin =
+				(uint8_t)((temp >> 16) & 0xff);
+		data->power_tune_table.LPMLTemperatureMax =
+				(uint8_t)((temp >> 8) & 0xff);
+		data->power_tune_table.Reserved = (uint8_t)(temp & 0xff);
+	}
+	return 0;
+}
+
+static int polaris10_populate_temperature_scaler(struct pp_hwmgr *hwmgr)
+{
+	int i;
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+
+	/* Currently not used. Set all to zero. */
+	for (i = 0; i < 16; i++)
+		data->power_tune_table.LPMLTemperatureScaler[i] = 0;
+
+	return 0;
+}
+
+static int polaris10_populate_fuzzy_fan(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+
+	if ((hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity & (1 << 15))
+		|| 0 == hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity)
+		hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity =
+			hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity;
+
+	data->power_tune_table.FuzzyFan_PwmSetDelta = PP_HOST_TO_SMC_US(
+				hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity);
+	return 0;
+}
+
+static int polaris10_populate_gnb_lpml(struct pp_hwmgr *hwmgr)
+{
+	int i;
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+
+	/* Currently not used. Set all to zero. */
+	for (i = 0; i < 16; i++)
+		data->power_tune_table.GnbLPML[i] = 0;
+
+	return 0;
+}
+
+static int polaris10_min_max_vgnb_lpml_id_from_bapm_vddc(struct pp_hwmgr *hwmgr)
+{
+	return 0;
+}
+
+static int polaris10_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	uint16_t hi_sidd = data->power_tune_table.BapmVddCBaseLeakageHiSidd;
+	uint16_t lo_sidd = data->power_tune_table.BapmVddCBaseLeakageLoSidd;
+	struct phm_cac_tdp_table *cac_table = table_info->cac_dtp_table;
+
+	hi_sidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256);
+	lo_sidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256);
+
+	data->power_tune_table.BapmVddCBaseLeakageHiSidd =
+			CONVERT_FROM_HOST_TO_SMC_US(hi_sidd);
+	data->power_tune_table.BapmVddCBaseLeakageLoSidd =
+			CONVERT_FROM_HOST_TO_SMC_US(lo_sidd);
+
+	return 0;
+}
+
+int polaris10_populate_pm_fuses(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	uint32_t pm_fuse_table_offset;
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_PowerContainment)) {
+		if (polaris10_read_smc_sram_dword(hwmgr->smumgr,
+				SMU7_FIRMWARE_HEADER_LOCATION +
+				offsetof(SMU74_Firmware_Header, PmFuseTable),
+				&pm_fuse_table_offset, data->sram_end))
+			PP_ASSERT_WITH_CODE(false,
+					"Attempt to get pm_fuse_table_offset Failed!",
+					return -EINVAL);
+
+		if (polaris10_populate_svi_load_line(hwmgr))
+			PP_ASSERT_WITH_CODE(false,
+					"Attempt to populate SviLoadLine Failed!",
+					return -EINVAL);
+
+		if (polaris10_populate_tdc_limit(hwmgr))
+			PP_ASSERT_WITH_CODE(false,
+					"Attempt to populate TDCLimit Failed!", return -EINVAL);
+
+		if (polaris10_populate_dw8(hwmgr, pm_fuse_table_offset))
+			PP_ASSERT_WITH_CODE(false,
+					"Attempt to populate TdcWaterfallCtl, "
+					"LPMLTemperature Min and Max Failed!",
+					return -EINVAL);
+
+		if (0 != polaris10_populate_temperature_scaler(hwmgr))
+			PP_ASSERT_WITH_CODE(false,
+					"Attempt to populate LPMLTemperatureScaler Failed!",
+					return -EINVAL);
+
+		if (polaris10_populate_fuzzy_fan(hwmgr))
+			PP_ASSERT_WITH_CODE(false,
+					"Attempt to populate Fuzzy Fan Control parameters Failed!",
+					return -EINVAL);
+
+		if (polaris10_populate_gnb_lpml(hwmgr))
+			PP_ASSERT_WITH_CODE(false,
+					"Attempt to populate GnbLPML Failed!",
+					return -EINVAL);
+
+		if (polaris10_min_max_vgnb_lpml_id_from_bapm_vddc(hwmgr))
+			PP_ASSERT_WITH_CODE(false,
+					"Attempt to populate GnbLPML Min and Max Vid Failed!",
+					return -EINVAL);
+
+		if (polaris10_populate_bapm_vddc_base_leakage_sidd(hwmgr))
+			PP_ASSERT_WITH_CODE(false,
+					"Attempt to populate BapmVddCBaseLeakage Hi and Lo "
+					"Sidd Failed!", return -EINVAL);
+
+		if (polaris10_copy_bytes_to_smc(hwmgr->smumgr, pm_fuse_table_offset,
+				(uint8_t *)&data->power_tune_table,
+				(sizeof(struct SMU74_Discrete_PmFuses) - 92), data->sram_end))
+			PP_ASSERT_WITH_CODE(false,
+					"Attempt to download PmFuseTable Failed!",
+					return -EINVAL);
+	}
+	return 0;
+}
+
+int polaris10_enable_smc_cac(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	int result = 0;
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_CAC)) {
+		int smc_result;
+		smc_result = smum_send_msg_to_smc(hwmgr->smumgr,
+				(uint16_t)(PPSMC_MSG_EnableCac));
+		PP_ASSERT_WITH_CODE((0 == smc_result),
+				"Failed to enable CAC in SMC.", result = -1);
+
+		data->cac_enabled = (0 == smc_result) ? true : false;
+	}
+	return result;
+}
+
+int polaris10_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+
+	if (data->power_containment_features &
+			POWERCONTAINMENT_FEATURE_PkgPwrLimit)
+		return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+				PPSMC_MSG_PkgPwrSetLimit, n);
+	return 0;
+}
+
+static int polaris10_set_overdriver_target_tdp(struct pp_hwmgr *pHwMgr, uint32_t target_tdp)
+{
+	return smum_send_msg_to_smc_with_parameter(pHwMgr->smumgr,
+			PPSMC_MSG_OverDriveSetTargetTdp, target_tdp);
+}
+
+int polaris10_enable_power_containment(struct pp_hwmgr *hwmgr)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	int smc_result;
+	int result = 0;
+
+	data->power_containment_features = 0;
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_PowerContainment)) {
+
+		if (data->enable_tdc_limit_feature) {
+			smc_result = smum_send_msg_to_smc(hwmgr->smumgr,
+					(uint16_t)(PPSMC_MSG_TDCLimitEnable));
+			PP_ASSERT_WITH_CODE((0 == smc_result),
+					"Failed to enable TDCLimit in SMC.", result = -1;);
+			if (0 == smc_result)
+				data->power_containment_features |=
+						POWERCONTAINMENT_FEATURE_TDCLimit;
+		}
+
+		if (data->enable_pkg_pwr_tracking_feature) {
+			smc_result = smum_send_msg_to_smc(hwmgr->smumgr,
+					(uint16_t)(PPSMC_MSG_PkgPwrLimitEnable));
+			PP_ASSERT_WITH_CODE((0 == smc_result),
+					"Failed to enable PkgPwrTracking in SMC.", result = -1;);
+			if (0 == smc_result) {
+				struct phm_cac_tdp_table *cac_table =
+						table_info->cac_dtp_table;
+				uint32_t default_limit =
+					(uint32_t)(cac_table->usMaximumPowerDeliveryLimit * 256);
+
+				data->power_containment_features |=
+						POWERCONTAINMENT_FEATURE_PkgPwrLimit;
+
+				if (polaris10_set_power_limit(hwmgr, default_limit))
+					printk(KERN_ERR "Failed to set Default Power Limit in SMC!");
+			}
+		}
+	}
+	return result;
+}
+
+int polaris10_power_control_set_level(struct pp_hwmgr *hwmgr)
+{
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	struct phm_cac_tdp_table *cac_table = table_info->cac_dtp_table;
+	int adjust_percent, target_tdp;
+	int result = 0;
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_PowerContainment)) {
+		/* adjustment percentage has already been validated */
+		adjust_percent = hwmgr->platform_descriptor.TDPAdjustmentPolarity ?
+				hwmgr->platform_descriptor.TDPAdjustment :
+				(-1 * hwmgr->platform_descriptor.TDPAdjustment);
+		/* SMC requested that target_tdp to be 7 bit fraction in DPM table
+		 * but message to be 8 bit fraction for messages
+		 */
+		target_tdp = ((100 + adjust_percent) * (int)(cac_table->usTDP * 256)) / 100;
+		result = polaris10_set_overdriver_target_tdp(hwmgr, (uint32_t)target_tdp);
+	}
+
+	return result;
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_powertune.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_powertune.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_powertune.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_powertune.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#ifndef POLARIS10_POWERTUNE_H
+#define POLARIS10_POWERTUNE_H
+
+enum polaris10_pt_config_reg_type {
+	POLARIS10_CONFIGREG_MMR = 0,
+	POLARIS10_CONFIGREG_SMC_IND,
+	POLARIS10_CONFIGREG_DIDT_IND,
+	POLARIS10_CONFIGREG_CACHE,
+	POLARIS10_CONFIGREG_MAX
+};
+
+/* PowerContainment Features */
+#define POWERCONTAINMENT_FEATURE_DTE             0x00000001
+#define POWERCONTAINMENT_FEATURE_TDCLimit        0x00000002
+#define POWERCONTAINMENT_FEATURE_PkgPwrLimit     0x00000004
+
+struct polaris10_pt_config_reg {
+	uint32_t                           offset;
+	uint32_t                           mask;
+	uint32_t                           shift;
+	uint32_t                           value;
+	enum polaris10_pt_config_reg_type       type;
+};
+
+struct polaris10_pt_defaults {
+	uint8_t   SviLoadLineEn;
+	uint8_t   SviLoadLineVddC;
+	uint8_t   TDC_VDDC_ThrottleReleaseLimitPerc;
+	uint8_t   TDC_MAWt;
+	uint8_t   TdcWaterfallCtl;
+	uint8_t   DTEAmbientTempBase;
+
+	uint32_t  DisplayCac;
+	uint32_t  BAPM_TEMP_GRADIENT;
+	uint16_t  BAPMTI_R[SMU74_DTE_ITERATIONS * SMU74_DTE_SOURCES * SMU74_DTE_SINKS];
+	uint16_t  BAPMTI_RC[SMU74_DTE_ITERATIONS * SMU74_DTE_SOURCES * SMU74_DTE_SINKS];
+};
+
+void polaris10_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr);
+int polaris10_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr);
+int polaris10_populate_pm_fuses(struct pp_hwmgr *hwmgr);
+int polaris10_enable_smc_cac(struct pp_hwmgr *hwmgr);
+int polaris10_enable_power_containment(struct pp_hwmgr *hwmgr);
+int polaris10_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n);
+int polaris10_power_control_set_level(struct pp_hwmgr *hwmgr);
+
+#endif  /* POLARIS10_POWERTUNE_H */
+
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_thermal.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_thermal.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_thermal.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_thermal.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,716 @@
+/*
+ * Copyright 2016 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include <asm/div64.h>
+#include "polaris10_thermal.h"
+#include "polaris10_hwmgr.h"
+#include "polaris10_smumgr.h"
+#include "polaris10_ppsmc.h"
+#include "smu/smu_7_1_3_d.h"
+#include "smu/smu_7_1_3_sh_mask.h"
+
+int polaris10_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr,
+		struct phm_fan_speed_info *fan_speed_info)
+{
+	if (hwmgr->thermal_controller.fanInfo.bNoFan)
+		return 0;
+
+	fan_speed_info->supports_percent_read = true;
+	fan_speed_info->supports_percent_write = true;
+	fan_speed_info->min_percent = 0;
+	fan_speed_info->max_percent = 100;
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_FanSpeedInTableIsRPM) &&
+		hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution) {
+		fan_speed_info->supports_rpm_read = true;
+		fan_speed_info->supports_rpm_write = true;
+		fan_speed_info->min_rpm = hwmgr->thermal_controller.fanInfo.ulMinRPM;
+		fan_speed_info->max_rpm = hwmgr->thermal_controller.fanInfo.ulMaxRPM;
+	} else {
+		fan_speed_info->min_rpm = 0;
+		fan_speed_info->max_rpm = 0;
+	}
+
+	return 0;
+}
+
+int polaris10_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr,
+		uint32_t *speed)
+{
+	uint32_t duty100;
+	uint32_t duty;
+	uint64_t tmp64;
+
+	if (hwmgr->thermal_controller.fanInfo.bNoFan)
+		return 0;
+
+	duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			CG_FDO_CTRL1, FMAX_DUTY100);
+	duty = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			CG_THERMAL_STATUS, FDO_PWM_DUTY);
+
+	if (duty100 == 0)
+		return -EINVAL;
+
+
+	tmp64 = (uint64_t)duty * 100;
+	do_div(tmp64, duty100);
+	*speed = (uint32_t)tmp64;
+
+	if (*speed > 100)
+		*speed = 100;
+
+	return 0;
+}
+
+int polaris10_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed)
+{
+	uint32_t tach_period;
+	uint32_t crystal_clock_freq;
+
+	if (hwmgr->thermal_controller.fanInfo.bNoFan ||
+			(hwmgr->thermal_controller.fanInfo.
+				ucTachometerPulsesPerRevolution == 0))
+		return 0;
+
+	tach_period = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			CG_TACH_STATUS, TACH_PERIOD);
+
+	if (tach_period == 0)
+		return -EINVAL;
+
+	crystal_clock_freq = tonga_get_xclk(hwmgr);
+
+	*speed = 60 * crystal_clock_freq * 10000 / tach_period;
+
+	return 0;
+}
+
+/**
+* Set Fan Speed Control to static mode, so that the user can decide what speed to use.
+* @param    hwmgr  the address of the powerplay hardware manager.
+*           mode    the fan control mode, 0 default, 1 by percent, 5, by RPM
+* @exception Should always succeed.
+*/
+int polaris10_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode)
+{
+
+	if (hwmgr->fan_ctrl_is_in_default_mode) {
+		hwmgr->fan_ctrl_default_mode =
+				PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device,	CGS_IND_REG__SMC,
+						CG_FDO_CTRL2, FDO_PWM_MODE);
+		hwmgr->tmin =
+				PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+						CG_FDO_CTRL2, TMIN);
+		hwmgr->fan_ctrl_is_in_default_mode = false;
+	}
+
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			CG_FDO_CTRL2, TMIN, 0);
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			CG_FDO_CTRL2, FDO_PWM_MODE, mode);
+
+	return 0;
+}
+
+/**
+* Reset Fan Speed Control to default mode.
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @exception Should always succeed.
+*/
+int polaris10_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr)
+{
+	if (!hwmgr->fan_ctrl_is_in_default_mode) {
+		PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+				CG_FDO_CTRL2, FDO_PWM_MODE, hwmgr->fan_ctrl_default_mode);
+		PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+				CG_FDO_CTRL2, TMIN, hwmgr->tmin);
+		hwmgr->fan_ctrl_is_in_default_mode = true;
+	}
+
+	return 0;
+}
+
+int polaris10_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr)
+{
+	int result;
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_ODFuzzyFanControlSupport)) {
+		cgs_write_register(hwmgr->device, mmSMC_MSG_ARG_0, FAN_CONTROL_FUZZY);
+		result = smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_StartFanControl);
+
+		if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_FanSpeedInTableIsRPM))
+			hwmgr->hwmgr_func->set_max_fan_rpm_output(hwmgr,
+					hwmgr->thermal_controller.
+					advanceFanControlParameters.usMaxFanRPM);
+		else
+			hwmgr->hwmgr_func->set_max_fan_pwm_output(hwmgr,
+					hwmgr->thermal_controller.
+					advanceFanControlParameters.usMaxFanPWM);
+
+	} else {
+		cgs_write_register(hwmgr->device, mmSMC_MSG_ARG_0, FAN_CONTROL_TABLE);
+		result = smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_StartFanControl);
+	}
+
+	if (!result && hwmgr->thermal_controller.
+			advanceFanControlParameters.ucTargetTemperature)
+		result = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+				PPSMC_MSG_SetFanTemperatureTarget,
+				hwmgr->thermal_controller.
+				advanceFanControlParameters.ucTargetTemperature);
+
+	return result;
+}
+
+
+int polaris10_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr)
+{
+	return smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_StopFanControl);
+}
+
+/**
+* Set Fan Speed in percent.
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @param    speed is the percentage value (0% - 100%) to be set.
+* @exception Fails is the 100% setting appears to be 0.
+*/
+int polaris10_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr,
+		uint32_t speed)
+{
+	uint32_t duty100;
+	uint32_t duty;
+	uint64_t tmp64;
+
+	if (hwmgr->thermal_controller.fanInfo.bNoFan)
+		return 0;
+
+	if (speed > 100)
+		speed = 100;
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_MicrocodeFanControl))
+		polaris10_fan_ctrl_stop_smc_fan_control(hwmgr);
+
+	duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			CG_FDO_CTRL1, FMAX_DUTY100);
+
+	if (duty100 == 0)
+		return -EINVAL;
+
+	tmp64 = (uint64_t)speed * duty100;
+	do_div(tmp64, 100);
+	duty = (uint32_t)tmp64;
+
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			CG_FDO_CTRL0, FDO_STATIC_DUTY, duty);
+
+	return polaris10_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC);
+}
+
+/**
+* Reset Fan Speed to default.
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @exception Always succeeds.
+*/
+int polaris10_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr)
+{
+	int result;
+
+	if (hwmgr->thermal_controller.fanInfo.bNoFan)
+		return 0;
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_MicrocodeFanControl)) {
+		result = polaris10_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC);
+		if (!result)
+			result = polaris10_fan_ctrl_start_smc_fan_control(hwmgr);
+	} else
+		result = polaris10_fan_ctrl_set_default_mode(hwmgr);
+
+	return result;
+}
+
+/**
+* Set Fan Speed in RPM.
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @param    speed is the percentage value (min - max) to be set.
+* @exception Fails is the speed not lie between min and max.
+*/
+int polaris10_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed)
+{
+	uint32_t tach_period;
+	uint32_t crystal_clock_freq;
+
+	if (hwmgr->thermal_controller.fanInfo.bNoFan ||
+			(hwmgr->thermal_controller.fanInfo.
+			ucTachometerPulsesPerRevolution == 0) ||
+			(speed < hwmgr->thermal_controller.fanInfo.ulMinRPM) ||
+			(speed > hwmgr->thermal_controller.fanInfo.ulMaxRPM))
+		return 0;
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_MicrocodeFanControl))
+		polaris10_fan_ctrl_stop_smc_fan_control(hwmgr);
+
+	crystal_clock_freq = tonga_get_xclk(hwmgr);
+
+	tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed);
+
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+				CG_TACH_STATUS, TACH_PERIOD, tach_period);
+
+	return polaris10_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC);
+}
+
+/**
+* Reads the remote temperature from the SIslands thermal controller.
+*
+* @param    hwmgr The address of the hardware manager.
+*/
+int polaris10_thermal_get_temperature(struct pp_hwmgr *hwmgr)
+{
+	int temp;
+
+	temp = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			CG_MULT_THERMAL_STATUS, CTF_TEMP);
+
+	/* Bit 9 means the reading is lower than the lowest usable value. */
+	if (temp & 0x200)
+		temp = POLARIS10_THERMAL_MAXIMUM_TEMP_READING;
+	else
+		temp = temp & 0x1ff;
+
+	temp *= PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
+
+	return temp;
+}
+
+/**
+* Set the requested temperature range for high and low alert signals
+*
+* @param    hwmgr The address of the hardware manager.
+* @param    range Temperature range to be programmed for high and low alert signals
+* @exception PP_Result_BadInput if the input data is not valid.
+*/
+static int polaris10_thermal_set_temperature_range(struct pp_hwmgr *hwmgr,
+		uint32_t low_temp, uint32_t high_temp)
+{
+	uint32_t low = POLARIS10_THERMAL_MINIMUM_ALERT_TEMP *
+			PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
+	uint32_t high = POLARIS10_THERMAL_MAXIMUM_ALERT_TEMP *
+			PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
+
+	if (low < low_temp)
+		low = low_temp;
+	if (high > high_temp)
+		high = high_temp;
+
+	if (low > high)
+		return -EINVAL;
+
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			CG_THERMAL_INT, DIG_THERM_INTH,
+			(high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES));
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			CG_THERMAL_INT, DIG_THERM_INTL,
+			(low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES));
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			CG_THERMAL_CTRL, DIG_THERM_DPM,
+			(high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES));
+
+	return 0;
+}
+
+/**
+* Programs thermal controller one-time setting registers
+*
+* @param    hwmgr The address of the hardware manager.
+*/
+static int polaris10_thermal_initialize(struct pp_hwmgr *hwmgr)
+{
+	if (hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution)
+		PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+				CG_TACH_CTRL, EDGE_PER_REV,
+				hwmgr->thermal_controller.fanInfo.
+				ucTachometerPulsesPerRevolution - 1);
+
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			CG_FDO_CTRL2, TACH_PWM_RESP_RATE, 0x28);
+
+	return 0;
+}
+
+/**
+* Enable thermal alerts on the RV770 thermal controller.
+*
+* @param    hwmgr The address of the hardware manager.
+*/
+static int polaris10_thermal_enable_alert(struct pp_hwmgr *hwmgr)
+{
+	uint32_t alert;
+
+	alert = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			CG_THERMAL_INT, THERM_INT_MASK);
+	alert &= ~(POLARIS10_THERMAL_HIGH_ALERT_MASK | POLARIS10_THERMAL_LOW_ALERT_MASK);
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			CG_THERMAL_INT, THERM_INT_MASK, alert);
+
+	/* send message to SMU to enable internal thermal interrupts */
+	return smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_Thermal_Cntl_Enable);
+}
+
+/**
+* Disable thermal alerts on the RV770 thermal controller.
+* @param    hwmgr The address of the hardware manager.
+*/
+static int polaris10_thermal_disable_alert(struct pp_hwmgr *hwmgr)
+{
+	uint32_t alert;
+
+	alert = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			CG_THERMAL_INT, THERM_INT_MASK);
+	alert |= (POLARIS10_THERMAL_HIGH_ALERT_MASK | POLARIS10_THERMAL_LOW_ALERT_MASK);
+	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			CG_THERMAL_INT, THERM_INT_MASK, alert);
+
+	/* send message to SMU to disable internal thermal interrupts */
+	return smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_Thermal_Cntl_Disable);
+}
+
+/**
+* Uninitialize the thermal controller.
+* Currently just disables alerts.
+* @param    hwmgr The address of the hardware manager.
+*/
+int polaris10_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr)
+{
+	int result = polaris10_thermal_disable_alert(hwmgr);
+
+	if (!hwmgr->thermal_controller.fanInfo.bNoFan)
+		polaris10_fan_ctrl_set_default_mode(hwmgr);
+
+	return result;
+}
+
+/**
+* Set up the fan table to control the fan using the SMC.
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @param    pInput the pointer to input data
+* @param    pOutput the pointer to output data
+* @param    pStorage the pointer to temporary storage
+* @param    Result the last failure code
+* @return   result from set temperature range routine
+*/
+int tf_polaris10_thermal_setup_fan_table(struct pp_hwmgr *hwmgr,
+		void *input, void *output, void *storage, int result)
+{
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+	SMU74_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE };
+	uint32_t duty100;
+	uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2;
+	uint16_t fdo_min, slope1, slope2;
+	uint32_t reference_clock;
+	int res;
+	uint64_t tmp64;
+
+	if (data->fan_table_start == 0) {
+		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_MicrocodeFanControl);
+		return 0;
+	}
+
+	duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+			CG_FDO_CTRL1, FMAX_DUTY100);
+
+	if (duty100 == 0) {
+		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_MicrocodeFanControl);
+		return 0;
+	}
+
+	tmp64 = hwmgr->thermal_controller.advanceFanControlParameters.
+			usPWMMin * duty100;
+	do_div(tmp64, 10000);
+	fdo_min = (uint16_t)tmp64;
+
+	t_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usTMed -
+			hwmgr->thermal_controller.advanceFanControlParameters.usTMin;
+	t_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usTHigh -
+			hwmgr->thermal_controller.advanceFanControlParameters.usTMed;
+
+	pwm_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed -
+			hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin;
+	pwm_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh -
+			hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed;
+
+	slope1 = (uint16_t)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100);
+	slope2 = (uint16_t)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100);
+
+	fan_table.TempMin = cpu_to_be16((50 + hwmgr->
+			thermal_controller.advanceFanControlParameters.usTMin) / 100);
+	fan_table.TempMed = cpu_to_be16((50 + hwmgr->
+			thermal_controller.advanceFanControlParameters.usTMed) / 100);
+	fan_table.TempMax = cpu_to_be16((50 + hwmgr->
+			thermal_controller.advanceFanControlParameters.usTMax) / 100);
+
+	fan_table.Slope1 = cpu_to_be16(slope1);
+	fan_table.Slope2 = cpu_to_be16(slope2);
+
+	fan_table.FdoMin = cpu_to_be16(fdo_min);
+
+	fan_table.HystDown = cpu_to_be16(hwmgr->
+			thermal_controller.advanceFanControlParameters.ucTHyst);
+
+	fan_table.HystUp = cpu_to_be16(1);
+
+	fan_table.HystSlope = cpu_to_be16(1);
+
+	fan_table.TempRespLim = cpu_to_be16(5);
+
+	reference_clock = tonga_get_xclk(hwmgr);
+
+	fan_table.RefreshPeriod = cpu_to_be32((hwmgr->
+			thermal_controller.advanceFanControlParameters.ulCycleDelay *
+			reference_clock) / 1600);
+
+	fan_table.FdoMax = cpu_to_be16((uint16_t)duty100);
+
+	fan_table.TempSrc = (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD(
+			hwmgr->device, CGS_IND_REG__SMC,
+			CG_MULT_THERMAL_CTRL, TEMP_SEL);
+
+	res = polaris10_copy_bytes_to_smc(hwmgr->smumgr, data->fan_table_start,
+			(uint8_t *)&fan_table, (uint32_t)sizeof(fan_table),
+			data->sram_end);
+
+	if (!res && hwmgr->thermal_controller.
+			advanceFanControlParameters.ucMinimumPWMLimit)
+		res = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+				PPSMC_MSG_SetFanMinPwm,
+				hwmgr->thermal_controller.
+				advanceFanControlParameters.ucMinimumPWMLimit);
+
+	if (!res && hwmgr->thermal_controller.
+			advanceFanControlParameters.ulMinFanSCLKAcousticLimit)
+		res = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+				PPSMC_MSG_SetFanSclkTarget,
+				hwmgr->thermal_controller.
+				advanceFanControlParameters.ulMinFanSCLKAcousticLimit);
+
+	if (res)
+		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+				PHM_PlatformCaps_MicrocodeFanControl);
+
+	return 0;
+}
+
+/**
+* Start the fan control on the SMC.
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @param    pInput the pointer to input data
+* @param    pOutput the pointer to output data
+* @param    pStorage the pointer to temporary storage
+* @param    Result the last failure code
+* @return   result from set temperature range routine
+*/
+int tf_polaris10_thermal_start_smc_fan_control(struct pp_hwmgr *hwmgr,
+		void *input, void *output, void *storage, int result)
+{
+/* If the fantable setup has failed we could have disabled
+ * PHM_PlatformCaps_MicrocodeFanControl even after
+ * this function was included in the table.
+ * Make sure that we still think controlling the fan is OK.
+*/
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_MicrocodeFanControl)) {
+		polaris10_fan_ctrl_start_smc_fan_control(hwmgr);
+		polaris10_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC);
+	}
+
+	return 0;
+}
+
+/**
+* Set temperature range for high and low alerts
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @param    pInput the pointer to input data
+* @param    pOutput the pointer to output data
+* @param    pStorage the pointer to temporary storage
+* @param    Result the last failure code
+* @return   result from set temperature range routine
+*/
+int tf_polaris10_thermal_set_temperature_range(struct pp_hwmgr *hwmgr,
+		void *input, void *output, void *storage, int result)
+{
+	struct PP_TemperatureRange *range = (struct PP_TemperatureRange *)input;
+
+	if (range == NULL)
+		return -EINVAL;
+
+	return polaris10_thermal_set_temperature_range(hwmgr, range->min, range->max);
+}
+
+/**
+* Programs one-time setting registers
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @param    pInput the pointer to input data
+* @param    pOutput the pointer to output data
+* @param    pStorage the pointer to temporary storage
+* @param    Result the last failure code
+* @return   result from initialize thermal controller routine
+*/
+int tf_polaris10_thermal_initialize(struct pp_hwmgr *hwmgr,
+		void *input, void *output, void *storage, int result)
+{
+    return polaris10_thermal_initialize(hwmgr);
+}
+
+/**
+* Enable high and low alerts
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @param    pInput the pointer to input data
+* @param    pOutput the pointer to output data
+* @param    pStorage the pointer to temporary storage
+* @param    Result the last failure code
+* @return   result from enable alert routine
+*/
+int tf_polaris10_thermal_enable_alert(struct pp_hwmgr *hwmgr,
+		void *input, void *output, void *storage, int result)
+{
+	return polaris10_thermal_enable_alert(hwmgr);
+}
+
+/**
+* Disable high and low alerts
+* @param    hwmgr  the address of the powerplay hardware manager.
+* @param    pInput the pointer to input data
+* @param    pOutput the pointer to output data
+* @param    pStorage the pointer to temporary storage
+* @param    Result the last failure code
+* @return   result from disable alert routine
+*/
+static int tf_polaris10_thermal_disable_alert(struct pp_hwmgr *hwmgr,
+		void *input, void *output, void *storage, int result)
+{
+	return polaris10_thermal_disable_alert(hwmgr);
+}
+
+static int tf_polaris10_thermal_avfs_enable(struct pp_hwmgr *hwmgr,
+		void *input, void *output, void *storage, int result)
+{
+	int ret;
+	struct pp_smumgr *smumgr = (struct pp_smumgr *)(hwmgr->smumgr);
+	struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend);
+	struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend);
+
+	if (smu_data->avfs.avfs_btc_status == AVFS_BTC_NOTSUPPORTED)
+		return 0;
+
+	ret = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+			PPSMC_MSG_SetGBDroopSettings, data->avfs_vdroop_override_setting);
+
+	ret = (smum_send_msg_to_smc(smumgr, PPSMC_MSG_EnableAvfs) == 0) ?
+			0 : -1;
+
+	if (!ret)
+		/* If this param is not changed, this function could fire unnecessarily */
+		smu_data->avfs.avfs_btc_status = AVFS_BTC_COMPLETED_PREVIOUSLY;
+
+	return ret;
+}
+
+static const struct phm_master_table_item
+polaris10_thermal_start_thermal_controller_master_list[] = {
+	{NULL, tf_polaris10_thermal_initialize},
+	{NULL, tf_polaris10_thermal_set_temperature_range},
+	{NULL, tf_polaris10_thermal_enable_alert},
+	{NULL, tf_polaris10_thermal_avfs_enable},
+/* We should restrict performance levels to low before we halt the SMC.
+ * On the other hand we are still in boot state when we do this
+ * so it would be pointless.
+ * If this assumption changes we have to revisit this table.
+ */
+	{NULL, tf_polaris10_thermal_setup_fan_table},
+	{NULL, tf_polaris10_thermal_start_smc_fan_control},
+	{NULL, NULL}
+};
+
+static const struct phm_master_table_header
+polaris10_thermal_start_thermal_controller_master = {
+	0,
+	PHM_MasterTableFlag_None,
+	polaris10_thermal_start_thermal_controller_master_list
+};
+
+static const struct phm_master_table_item
+polaris10_thermal_set_temperature_range_master_list[] = {
+	{NULL, tf_polaris10_thermal_disable_alert},
+	{NULL, tf_polaris10_thermal_set_temperature_range},
+	{NULL, tf_polaris10_thermal_enable_alert},
+	{NULL, NULL}
+};
+
+static const struct phm_master_table_header
+polaris10_thermal_set_temperature_range_master = {
+	0,
+	PHM_MasterTableFlag_None,
+	polaris10_thermal_set_temperature_range_master_list
+};
+
+int polaris10_thermal_ctrl_uninitialize_thermal_controller(struct pp_hwmgr *hwmgr)
+{
+	if (!hwmgr->thermal_controller.fanInfo.bNoFan)
+		polaris10_fan_ctrl_set_default_mode(hwmgr);
+	return 0;
+}
+
+/**
+* Initializes the thermal controller related functions in the Hardware Manager structure.
+* @param    hwmgr The address of the hardware manager.
+* @exception Any error code from the low-level communication.
+*/
+int pp_polaris10_thermal_initialize(struct pp_hwmgr *hwmgr)
+{
+	int result;
+
+	result = phm_construct_table(hwmgr,
+			&polaris10_thermal_set_temperature_range_master,
+			&(hwmgr->set_temperature_range));
+
+	if (!result) {
+		result = phm_construct_table(hwmgr,
+				&polaris10_thermal_start_thermal_controller_master,
+				&(hwmgr->start_thermal_controller));
+		if (result)
+			phm_destroy_table(hwmgr, &(hwmgr->set_temperature_range));
+	}
+
+	if (!result)
+		hwmgr->fan_ctrl_is_in_default_mode = true;
+	return result;
+}
+
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_thermal.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_thermal.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_thermal.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_thermal.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2016 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef _POLARIS10_THERMAL_H_
+#define _POLARIS10_THERMAL_H_
+
+#include "hwmgr.h"
+
+#define POLARIS10_THERMAL_HIGH_ALERT_MASK         0x1
+#define POLARIS10_THERMAL_LOW_ALERT_MASK          0x2
+
+#define POLARIS10_THERMAL_MINIMUM_TEMP_READING    -256
+#define POLARIS10_THERMAL_MAXIMUM_TEMP_READING    255
+
+#define POLARIS10_THERMAL_MINIMUM_ALERT_TEMP      0
+#define POLARIS10_THERMAL_MAXIMUM_ALERT_TEMP      255
+
+#define FDO_PWM_MODE_STATIC  1
+#define FDO_PWM_MODE_STATIC_RPM 5
+
+
+extern int tf_polaris10_thermal_initialize(struct pp_hwmgr *hwmgr, void *input, void *output, void *storage, int result);
+extern int tf_polaris10_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, void *input, void *output, void *storage, int result);
+extern int tf_polaris10_thermal_enable_alert(struct pp_hwmgr *hwmgr, void *input, void *output, void *storage, int result);
+
+extern int polaris10_thermal_get_temperature(struct pp_hwmgr *hwmgr);
+extern int polaris10_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr);
+extern int polaris10_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr, struct phm_fan_speed_info *fan_speed_info);
+extern int polaris10_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr, uint32_t *speed);
+extern int polaris10_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr);
+extern int polaris10_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode);
+extern int polaris10_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr, uint32_t speed);
+extern int polaris10_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr);
+extern int pp_polaris10_thermal_initialize(struct pp_hwmgr *hwmgr);
+extern int polaris10_thermal_ctrl_uninitialize_thermal_controller(struct pp_hwmgr *hwmgr);
+extern int polaris10_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed);
+extern int polaris10_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed);
+extern int polaris10_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr);
+extern uint32_t tonga_get_xclk(struct pp_hwmgr *hwmgr);
+
+#endif
+
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/pp_acpi.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/pp_acpi.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/pp_acpi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/pp_acpi.c	2016-07-24 15:23:50.000000000 -0400
@@ -1,3 +1,26 @@
+/*
+ * Copyright 2016 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
 #include <linux/errno.h>
 #include "linux/delay.h"
 #include "hwmgr.h"
@@ -21,6 +44,20 @@ bool acpi_atcs_functions_supported(void
 	return result == 0 ? (output_buf.function_bits & (1 << (index - 1))) != 0 : false;
 }
 
+bool acpi_atcs_notify_pcie_device_ready(void *device)
+{
+	int32_t temp_buffer = 1;
+
+	return cgs_call_acpi_method(device, CGS_ACPI_METHOD_ATCS,
+				ATCS_FUNCTION_PCIE_DEVICE_READY_NOTIFICATION,
+						&temp_buffer,
+						NULL,
+						0,
+						sizeof(temp_buffer),
+						0);
+}
+
+
 int acpi_pcie_perf_request(void *device, uint8_t perf_req, bool advertise)
 {
 	struct atcs_pref_req_input atcs_input;
@@ -29,7 +66,7 @@ int acpi_pcie_perf_request(void *device,
 	int result;
 	struct cgs_system_info info = {0};
 
-	if (!acpi_atcs_functions_supported(device, ATCS_FUNCTION_PCIE_PERFORMANCE_REQUEST))
+	if( 0 != acpi_atcs_notify_pcie_device_ready(device))
 		return -EINVAL;
 
 	info.size = sizeof(struct cgs_system_info);
@@ -54,7 +91,7 @@ int acpi_pcie_perf_request(void *device,
 						ATCS_FUNCTION_PCIE_PERFORMANCE_REQUEST,
 						&atcs_input,
 						&atcs_output,
-						0,
+						1,
 						sizeof(atcs_input),
 						sizeof(atcs_output));
 		if (result != 0)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.c	2016-07-24 15:23:50.000000000 -0400
@@ -373,6 +373,37 @@ int atomctrl_get_engine_pll_dividers_vi(
 	return result;
 }
 
+int atomctrl_get_engine_pll_dividers_ai(struct pp_hwmgr *hwmgr,
+		uint32_t clock_value,
+		pp_atomctrl_clock_dividers_ai *dividers)
+{
+	COMPUTE_GPU_CLOCK_OUTPUT_PARAMETERS_V1_7 pll_patameters;
+	int result;
+
+	pll_patameters.ulClock.ulClock = clock_value;
+	pll_patameters.ulClock.ucPostDiv = COMPUTE_GPUCLK_INPUT_FLAG_SCLK;
+
+	result = cgs_atom_exec_cmd_table
+		(hwmgr->device,
+		 GetIndexIntoMasterTable(COMMAND, ComputeMemoryEnginePLL),
+		 &pll_patameters);
+
+	if (0 == result) {
+		dividers->usSclk_fcw_frac     = le16_to_cpu(pll_patameters.usSclk_fcw_frac);
+		dividers->usSclk_fcw_int      = le16_to_cpu(pll_patameters.usSclk_fcw_int);
+		dividers->ucSclkPostDiv       = pll_patameters.ucSclkPostDiv;
+		dividers->ucSclkVcoMode       = pll_patameters.ucSclkVcoMode;
+		dividers->ucSclkPllRange      = pll_patameters.ucSclkPllRange;
+		dividers->ucSscEnable         = pll_patameters.ucSscEnable;
+		dividers->usSsc_fcw1_frac     = le16_to_cpu(pll_patameters.usSsc_fcw1_frac);
+		dividers->usSsc_fcw1_int      = le16_to_cpu(pll_patameters.usSsc_fcw1_int);
+		dividers->usPcc_fcw_int       = le16_to_cpu(pll_patameters.usPcc_fcw_int);
+		dividers->usSsc_fcw_slew_frac = le16_to_cpu(pll_patameters.usSsc_fcw_slew_frac);
+		dividers->usPcc_fcw_slew_frac = le16_to_cpu(pll_patameters.usPcc_fcw_slew_frac);
+	}
+	return result;
+}
+
 int atomctrl_get_dfs_pll_dividers_vi(
 		struct pp_hwmgr *hwmgr,
 		uint32_t clock_value,
@@ -618,7 +649,7 @@ int atomctrl_calculate_voltage_evv_on_sc
 	if (!getASICProfilingInfo)
 		return -1;
 
-	if(getASICProfilingInfo->asHeader.ucTableFormatRevision < 3 ||
+	if (getASICProfilingInfo->asHeader.ucTableFormatRevision < 3 ||
 			(getASICProfilingInfo->asHeader.ucTableFormatRevision == 3 &&
 			getASICProfilingInfo->asHeader.ucTableContentRevision < 4))
 		return -1;
@@ -891,18 +922,18 @@ int atomctrl_calculate_voltage_evv_on_sc
 	 *-----------------------
 	 */
 
-	fA_Term = fAdd(fMargin_RO_a, fAdd(fMultiply(fSM_A4,fSclk), fSM_A5));
+	fA_Term = fAdd(fMargin_RO_a, fAdd(fMultiply(fSM_A4, fSclk), fSM_A5));
 	fB_Term = fAdd(fAdd(fMultiply(fSM_A2, fSclk), fSM_A6), fMargin_RO_b);
 	fC_Term = fAdd(fMargin_RO_c,
 			fAdd(fMultiply(fSM_A0,fLkg_FT),
-			fAdd(fMultiply(fSM_A1, fMultiply(fLkg_FT,fSclk)),
+			fAdd(fMultiply(fSM_A1, fMultiply(fLkg_FT, fSclk)),
 			fAdd(fMultiply(fSM_A3, fSclk),
-			fSubtract(fSM_A7,fRO_fused)))));
+			fSubtract(fSM_A7, fRO_fused)))));
 
 	fVDDC_base = fSubtract(fRO_fused,
 			fSubtract(fMargin_RO_c,
 					fSubtract(fSM_A3, fMultiply(fSM_A1, fSclk))));
-	fVDDC_base = fDivide(fVDDC_base, fAdd(fMultiply(fSM_A0,fSclk), fSM_A2));
+	fVDDC_base = fDivide(fVDDC_base, fAdd(fMultiply(fSM_A0, fSclk), fSM_A2));
 
 	repeat = fSubtract(fVDDC_base,
 			fDivide(fMargin_DC_sigma, ConvertToFraction(1000)));
@@ -916,7 +947,7 @@ int atomctrl_calculate_voltage_evv_on_sc
 			fSubtract(fRO_DC_margin,
 			fSubtract(fSM_A3,
 			fMultiply(fSM_A2, repeat))));
-	fDC_SCLK = fDivide(fDC_SCLK, fAdd(fMultiply(fSM_A0,repeat), fSM_A1));
+	fDC_SCLK = fDivide(fDC_SCLK, fAdd(fMultiply(fSM_A0, repeat), fSM_A1));
 
 	fSigma_DC = fSubtract(fSclk, fDC_SCLK);
 
@@ -996,7 +1027,7 @@ int atomctrl_calculate_voltage_evv_on_sc
 		fV_NL = fRoundUpByStepSize(fV_NL, fStepSize, 0);
 
 		if (GreaterThan(fV_max, fV_NL) &&
-			(GreaterThan(fV_NL,fEVV_V) ||
+			(GreaterThan(fV_NL, fEVV_V) ||
 			Equal(fV_NL, fEVV_V))) {
 			fV_NL = fMultiply(fV_NL, ConvertToFraction(1000));
 
@@ -1010,10 +1041,10 @@ int atomctrl_calculate_voltage_evv_on_sc
 }
 
 /** atomctrl_get_voltage_evv_on_sclk gets voltage via call to ATOM COMMAND table.
- * @param hwmgr               	input: pointer to hwManager
+ * @param hwmgr	input: pointer to hwManager
  * @param voltage_type            input: type of EVV voltage VDDC or VDDGFX
  * @param sclk                        input: in 10Khz unit. DPM state SCLK frequency
- *                                   		which is define in PPTable SCLK/VDDC dependence
+ *		which is define in PPTable SCLK/VDDC dependence
  *				table associated with this virtual_voltage_Id
  * @param virtual_voltage_Id      input: voltage id which match per voltage DPM state: 0xff01, 0xff02.. 0xff08
  * @param voltage		       output: real voltage level in unit of mv
@@ -1205,3 +1236,112 @@ int atomctrl_read_efuse(void *device, ui
 
 	return result;
 }
+
+int atomctrl_set_ac_timing_ai(struct pp_hwmgr *hwmgr, uint32_t memory_clock,
+								uint8_t level)
+{
+	DYNAMICE_MEMORY_SETTINGS_PARAMETER_V2_1 memory_clock_parameters;
+	int result;
+
+	memory_clock_parameters.asDPMMCReg.ulClock.ulClockFreq = memory_clock & SET_CLOCK_FREQ_MASK;
+	memory_clock_parameters.asDPMMCReg.ulClock.ulComputeClockFlag = ADJUST_MC_SETTING_PARAM;
+	memory_clock_parameters.asDPMMCReg.ucMclkDPMState = level;
+
+	result = cgs_atom_exec_cmd_table
+		(hwmgr->device,
+		 GetIndexIntoMasterTable(COMMAND, DynamicMemorySettings),
+		 &memory_clock_parameters);
+
+	return result;
+}
+
+int atomctrl_get_voltage_evv_on_sclk_ai(struct pp_hwmgr *hwmgr, uint8_t voltage_type,
+				uint32_t sclk, uint16_t virtual_voltage_Id, uint32_t *voltage)
+{
+
+	int result;
+	GET_VOLTAGE_INFO_INPUT_PARAMETER_V1_3 get_voltage_info_param_space;
+
+	get_voltage_info_param_space.ucVoltageType = voltage_type;
+	get_voltage_info_param_space.ucVoltageMode = ATOM_GET_VOLTAGE_EVV_VOLTAGE;
+	get_voltage_info_param_space.usVoltageLevel = virtual_voltage_Id;
+	get_voltage_info_param_space.ulSCLKFreq = sclk;
+
+	result = cgs_atom_exec_cmd_table(hwmgr->device,
+			GetIndexIntoMasterTable(COMMAND, GetVoltageInfo),
+			&get_voltage_info_param_space);
+
+	if (0 != result)
+		return result;
+
+	*voltage = ((GET_EVV_VOLTAGE_INFO_OUTPUT_PARAMETER_V1_3 *)(&get_voltage_info_param_space))->ulVoltageLevel;
+
+	return result;
+}
+
+int atomctrl_get_smc_sclk_range_table(struct pp_hwmgr *hwmgr, struct pp_atom_ctrl_sclk_range_table *table)
+{
+
+	int i;
+	u8 frev, crev;
+	u16 size;
+
+	ATOM_SMU_INFO_V2_1 *psmu_info =
+		(ATOM_SMU_INFO_V2_1 *)cgs_atom_get_data_table(hwmgr->device,
+			GetIndexIntoMasterTable(DATA, SMU_Info),
+			&size, &frev, &crev);
+
+
+	for (i = 0; i < psmu_info->ucSclkEntryNum; i++) {
+		table->entry[i].ucVco_setting = psmu_info->asSclkFcwRangeEntry[i].ucVco_setting;
+		table->entry[i].ucPostdiv = psmu_info->asSclkFcwRangeEntry[i].ucPostdiv;
+		table->entry[i].usFcw_pcc = psmu_info->asSclkFcwRangeEntry[i].ucFcw_pcc;
+		table->entry[i].usFcw_trans_upper = psmu_info->asSclkFcwRangeEntry[i].ucFcw_trans_upper;
+		table->entry[i].usRcw_trans_lower = psmu_info->asSclkFcwRangeEntry[i].ucRcw_trans_lower;
+	}
+
+	return 0;
+}
+
+int atomctrl_get_avfs_information(struct pp_hwmgr *hwmgr, struct pp_atom_ctrl__avfs_parameters *param)
+{
+	ATOM_ASIC_PROFILING_INFO_V3_6 *profile = NULL;
+
+	if (param == NULL)
+		return -EINVAL;
+
+	profile = (ATOM_ASIC_PROFILING_INFO_V3_6 *)
+			cgs_atom_get_data_table(hwmgr->device,
+					GetIndexIntoMasterTable(DATA, ASIC_ProfilingInfo),
+					NULL, NULL, NULL);
+	if (!profile)
+		return -1;
+
+	param->ulAVFS_meanNsigma_Acontant0 = profile->ulAVFS_meanNsigma_Acontant0;
+	param->ulAVFS_meanNsigma_Acontant1 = profile->ulAVFS_meanNsigma_Acontant1;
+	param->ulAVFS_meanNsigma_Acontant2 = profile->ulAVFS_meanNsigma_Acontant2;
+	param->usAVFS_meanNsigma_DC_tol_sigma = profile->usAVFS_meanNsigma_DC_tol_sigma;
+	param->usAVFS_meanNsigma_Platform_mean = profile->usAVFS_meanNsigma_Platform_mean;
+	param->usAVFS_meanNsigma_Platform_sigma = profile->usAVFS_meanNsigma_Platform_sigma;
+	param->ulGB_VDROOP_TABLE_CKSOFF_a0 = profile->ulGB_VDROOP_TABLE_CKSOFF_a0;
+	param->ulGB_VDROOP_TABLE_CKSOFF_a1 = profile->ulGB_VDROOP_TABLE_CKSOFF_a1;
+	param->ulGB_VDROOP_TABLE_CKSOFF_a2 = profile->ulGB_VDROOP_TABLE_CKSOFF_a2;
+	param->ulGB_VDROOP_TABLE_CKSON_a0 = profile->ulGB_VDROOP_TABLE_CKSON_a0;
+	param->ulGB_VDROOP_TABLE_CKSON_a1 = profile->ulGB_VDROOP_TABLE_CKSON_a1;
+	param->ulGB_VDROOP_TABLE_CKSON_a2 = profile->ulGB_VDROOP_TABLE_CKSON_a2;
+	param->ulAVFSGB_FUSE_TABLE_CKSOFF_m1 = profile->ulAVFSGB_FUSE_TABLE_CKSOFF_m1;
+	param->usAVFSGB_FUSE_TABLE_CKSOFF_m2 = profile->usAVFSGB_FUSE_TABLE_CKSOFF_m2;
+	param->ulAVFSGB_FUSE_TABLE_CKSOFF_b = profile->ulAVFSGB_FUSE_TABLE_CKSOFF_b;
+	param->ulAVFSGB_FUSE_TABLE_CKSON_m1 = profile->ulAVFSGB_FUSE_TABLE_CKSON_m1;
+	param->usAVFSGB_FUSE_TABLE_CKSON_m2 = profile->usAVFSGB_FUSE_TABLE_CKSON_m2;
+	param->ulAVFSGB_FUSE_TABLE_CKSON_b = profile->ulAVFSGB_FUSE_TABLE_CKSON_b;
+	param->usMaxVoltage_0_25mv = profile->usMaxVoltage_0_25mv;
+	param->ucEnableGB_VDROOP_TABLE_CKSOFF = profile->ucEnableGB_VDROOP_TABLE_CKSOFF;
+	param->ucEnableGB_VDROOP_TABLE_CKSON = profile->ucEnableGB_VDROOP_TABLE_CKSON;
+	param->ucEnableGB_FUSE_TABLE_CKSOFF = profile->ucEnableGB_FUSE_TABLE_CKSOFF;
+	param->ucEnableGB_FUSE_TABLE_CKSON = profile->ucEnableGB_FUSE_TABLE_CKSON;
+	param->usPSM_Age_ComFactor = profile->usPSM_Age_ComFactor;
+	param->ucEnableApplyAVFS_CKS_OFF_Voltage = profile->ucEnableApplyAVFS_CKS_OFF_Voltage;
+
+	return 0;
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.h	2016-07-24 15:23:50.000000000 -0400
@@ -101,6 +101,23 @@ struct pp_atomctrl_clock_dividers_vi {
 };
 typedef struct pp_atomctrl_clock_dividers_vi pp_atomctrl_clock_dividers_vi;
 
+struct pp_atomctrl_clock_dividers_ai {
+	u16 usSclk_fcw_frac;
+	u16  usSclk_fcw_int;
+	u8   ucSclkPostDiv;
+	u8   ucSclkVcoMode;
+	u8   ucSclkPllRange;
+	u8   ucSscEnable;
+	u16  usSsc_fcw1_frac;
+	u16  usSsc_fcw1_int;
+	u16  usReserved;
+	u16  usPcc_fcw_int;
+	u16  usSsc_fcw_slew_frac;
+	u16  usPcc_fcw_slew_frac;
+};
+typedef struct pp_atomctrl_clock_dividers_ai pp_atomctrl_clock_dividers_ai;
+
+
 union pp_atomctrl_s_mpll_fb_divider {
 	struct {
 		uint32_t cl_kf : 12;
@@ -204,6 +221,21 @@ struct pp_atomctrl_mc_register_address {
 
 typedef struct pp_atomctrl_mc_register_address pp_atomctrl_mc_register_address;
 
+#define MAX_SCLK_RANGE 8
+
+struct pp_atom_ctrl_sclk_range_table_entry{
+	uint8_t  ucVco_setting;
+	uint8_t  ucPostdiv;
+	uint16_t usFcw_pcc;
+	uint16_t usFcw_trans_upper;
+	uint16_t usRcw_trans_lower;
+};
+
+
+struct pp_atom_ctrl_sclk_range_table{
+	struct pp_atom_ctrl_sclk_range_table_entry entry[MAX_SCLK_RANGE];
+};
+
 struct pp_atomctrl_mc_reg_table {
 	uint8_t                         last;                    /* number of registers */
 	uint8_t                         num_entries;             /* number of AC timing entries */
@@ -218,6 +250,35 @@ struct pp_atomctrl_gpio_pin_assignment {
 };
 typedef struct pp_atomctrl_gpio_pin_assignment pp_atomctrl_gpio_pin_assignment;
 
+struct pp_atom_ctrl__avfs_parameters {
+	uint32_t  ulAVFS_meanNsigma_Acontant0;
+	uint32_t  ulAVFS_meanNsigma_Acontant1;
+	uint32_t  ulAVFS_meanNsigma_Acontant2;
+	uint16_t usAVFS_meanNsigma_DC_tol_sigma;
+	uint16_t usAVFS_meanNsigma_Platform_mean;
+	uint16_t usAVFS_meanNsigma_Platform_sigma;
+	uint32_t  ulGB_VDROOP_TABLE_CKSOFF_a0;
+	uint32_t  ulGB_VDROOP_TABLE_CKSOFF_a1;
+	uint32_t  ulGB_VDROOP_TABLE_CKSOFF_a2;
+	uint32_t  ulGB_VDROOP_TABLE_CKSON_a0;
+	uint32_t  ulGB_VDROOP_TABLE_CKSON_a1;
+	uint32_t  ulGB_VDROOP_TABLE_CKSON_a2;
+	uint32_t  ulAVFSGB_FUSE_TABLE_CKSOFF_m1;
+	uint16_t  usAVFSGB_FUSE_TABLE_CKSOFF_m2;
+	uint32_t  ulAVFSGB_FUSE_TABLE_CKSOFF_b;
+	uint32_t  ulAVFSGB_FUSE_TABLE_CKSON_m1;
+	uint16_t  usAVFSGB_FUSE_TABLE_CKSON_m2;
+	uint32_t  ulAVFSGB_FUSE_TABLE_CKSON_b;
+	uint16_t  usMaxVoltage_0_25mv;
+	uint8_t  ucEnableGB_VDROOP_TABLE_CKSOFF;
+	uint8_t  ucEnableGB_VDROOP_TABLE_CKSON;
+	uint8_t  ucEnableGB_FUSE_TABLE_CKSOFF;
+	uint8_t  ucEnableGB_FUSE_TABLE_CKSON;
+	uint16_t usPSM_Age_ComFactor;
+	uint8_t  ucEnableApplyAVFS_CKS_OFF_Voltage;
+	uint8_t  ucReserved;
+};
+
 extern bool atomctrl_get_pp_assign_pin(struct pp_hwmgr *hwmgr, const uint32_t pinId, pp_atomctrl_gpio_pin_assignment *gpio_pin_assignment);
 extern int atomctrl_get_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type, uint32_t sclk, uint16_t virtual_voltage_Id, uint16_t *voltage);
 extern uint32_t atomctrl_get_mpll_reference_clock(struct pp_hwmgr *hwmgr);
@@ -240,7 +301,14 @@ extern int atomctrl_read_efuse(void *dev
 		uint16_t end_index, uint32_t mask, uint32_t *efuse);
 extern int atomctrl_calculate_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type,
 		uint32_t sclk, uint16_t virtual_voltage_Id, uint16_t *voltage, uint16_t dpm_level, bool debug);
+extern int atomctrl_get_engine_pll_dividers_ai(struct pp_hwmgr *hwmgr, uint32_t clock_value, pp_atomctrl_clock_dividers_ai *dividers);
+extern int atomctrl_set_ac_timing_ai(struct pp_hwmgr *hwmgr, uint32_t memory_clock,
+								uint8_t level);
+extern int atomctrl_get_voltage_evv_on_sclk_ai(struct pp_hwmgr *hwmgr, uint8_t voltage_type,
+				uint32_t sclk, uint16_t virtual_voltage_Id, uint32_t *voltage);
+extern int atomctrl_get_smc_sclk_range_table(struct pp_hwmgr *hwmgr, struct pp_atom_ctrl_sclk_range_table *table);
 
+extern int atomctrl_get_avfs_information(struct pp_hwmgr *hwmgr, struct pp_atom_ctrl__avfs_parameters *param);
 
 #endif
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/ppevvmath.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/ppevvmath.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/ppevvmath.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/ppevvmath.h	2016-07-24 15:23:50.000000000 -0400
@@ -127,8 +127,8 @@ fInt fExponential(fInt exponent)
 	fInt solution = fPositiveOne; /*Starting off with baseline of 1 */
 	fInt error_term;
 
-	uint32_t k_array[11] = {55452, 27726, 13863, 6931, 4055, 2231, 1178, 606, 308, 155, 78};
-	uint32_t expk_array[11] = {2560000, 160000, 40000, 20000, 15000, 12500, 11250, 10625, 10313, 10156, 10078};
+	static const uint32_t k_array[11] = {55452, 27726, 13863, 6931, 4055, 2231, 1178, 606, 308, 155, 78};
+	static const uint32_t expk_array[11] = {2560000, 160000, 40000, 20000, 15000, 12500, 11250, 10625, 10313, 10156, 10078};
 
 	if (GreaterThan(fZERO, exponent)) {
 		exponent = fNegate(exponent);
@@ -162,8 +162,8 @@ fInt fNaturalLog(fInt value)
 	fInt solution = ConvertToFraction(0); /*Starting off with baseline of 0 */
 	fInt error_term;
 
-	uint32_t k_array[10] = {160000, 40000, 20000, 15000, 12500, 11250, 10625, 10313, 10156, 10078};
-	uint32_t logk_array[10] = {27726, 13863, 6931, 4055, 2231, 1178, 606, 308, 155, 78};
+	static const uint32_t k_array[10] = {160000, 40000, 20000, 15000, 12500, 11250, 10625, 10313, 10156, 10078};
+	static const uint32_t logk_array[10] = {27726, 13863, 6931, 4055, 2231, 1178, 606, 308, 155, 78};
 
 	while (GreaterThan(fAdd(value, fNegativeOne), upper_bound)) {
 		for (i = 0; i < 10; i++) {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c	2016-07-24 15:23:50.000000000 -0400
@@ -51,6 +51,9 @@
 #include "bif/bif_5_0_d.h"
 #include "bif/bif_5_0_sh_mask.h"
 
+#include "dce/dce_10_0_d.h"
+#include "dce/dce_10_0_sh_mask.h"
+
 #include "cgs_linux.h"
 #include "eventmgr.h"
 #include "amd_pcie_helpers.h"
@@ -86,17 +89,17 @@
 typedef uint32_t PECI_RegistryValue;
 
 /* [2.5%,~2.5%] Clock stretched is multiple of 2.5% vs not and [Fmin, Fmax, LDO_REFSEL, USE_FOR_LOW_FREQ] */
-uint16_t PP_ClockStretcherLookupTable[2][4] = {
+static const uint16_t PP_ClockStretcherLookupTable[2][4] = {
 	{600, 1050, 3, 0},
 	{600, 1050, 6, 1} };
 
 /* [FF, SS] type, [] 4 voltage ranges, and [Floor Freq, Boundary Freq, VID min , VID max] */
-uint32_t PP_ClockStretcherDDTTable[2][4][4] = {
+static const uint32_t PP_ClockStretcherDDTTable[2][4][4] = {
 	{ {265, 529, 120, 128}, {325, 650, 96, 119}, {430, 860, 32, 95}, {0, 0, 0, 31} },
 	{ {275, 550, 104, 112}, {319, 638, 96, 103}, {360, 720, 64, 95}, {384, 768, 32, 63} } };
 
 /* [Use_For_Low_freq] value, [0%, 5%, 10%, 7.14%, 14.28%, 20%] (coming from PWR_CKS_CNTL.stretch_amount reg spec) */
-uint8_t PP_ClockStretchAmountConversion[2][6] = {
+static const uint8_t PP_ClockStretchAmountConversion[2][6] = {
 	{0, 1, 3, 2, 4, 5},
 	{0, 2, 4, 5, 6, 5} };
 
@@ -110,7 +113,7 @@ enum DPM_EVENT_SRC {
 };
 typedef enum DPM_EVENT_SRC DPM_EVENT_SRC;
 
-const unsigned long PhwTonga_Magic = (unsigned long)(PHM_VIslands_Magic);
+static const unsigned long PhwTonga_Magic = (unsigned long)(PHM_VIslands_Magic);
 
 struct tonga_power_state *cast_phw_tonga_power_state(
 				  struct pp_hw_power_state *hw_ps)
@@ -429,19 +432,20 @@ int tonga_get_evv_voltage(struct pp_hwmg
 						}
 					}
 				}
-				PP_ASSERT_WITH_CODE(0 == atomctrl_get_voltage_evv_on_sclk
-						(hwmgr, VOLTAGE_TYPE_VDDGFX, sclk,
-						 virtual_voltage_id, &vddgfx),
-						"Error retrieving EVV voltage value!", continue);
-
-				/* need to make sure vddgfx is less than 2v or else, it could burn the ASIC. */
-				PP_ASSERT_WITH_CODE((vddgfx < 2000 && vddgfx != 0), "Invalid VDDGFX value!", return -1);
+				if (0 == atomctrl_get_voltage_evv_on_sclk
+				    (hwmgr, VOLTAGE_TYPE_VDDGFX, sclk,
+				     virtual_voltage_id, &vddgfx)) {
+					/* need to make sure vddgfx is less than 2v or else, it could burn the ASIC. */
+					PP_ASSERT_WITH_CODE((vddgfx < 2000 && vddgfx != 0), "Invalid VDDGFX value!", return -1);
 
-				/* the voltage should not be zero nor equal to leakage ID */
-				if (vddgfx != 0 && vddgfx != virtual_voltage_id) {
-					data->vddcgfx_leakage.actual_voltage[data->vddcgfx_leakage.count] = vddgfx;
-					data->vddcgfx_leakage.leakage_id[data->vddcgfx_leakage.count] = virtual_voltage_id;
-					data->vddcgfx_leakage.count++;
+					/* the voltage should not be zero nor equal to leakage ID */
+					if (vddgfx != 0 && vddgfx != virtual_voltage_id) {
+						data->vddcgfx_leakage.actual_voltage[data->vddcgfx_leakage.count] = vddgfx;
+						data->vddcgfx_leakage.leakage_id[data->vddcgfx_leakage.count] = virtual_voltage_id;
+						data->vddcgfx_leakage.count++;
+					}
+				} else {
+					printk("Error retrieving EVV voltage value!\n");
 				}
 			}
 		} else {
@@ -449,20 +453,20 @@ int tonga_get_evv_voltage(struct pp_hwmg
 			if (0 == tonga_get_sclk_for_voltage_evv(hwmgr,
 						pptable_info->vddc_lookup_table,
 						virtual_voltage_id, &sclk)) {
-				PP_ASSERT_WITH_CODE(0 == atomctrl_get_voltage_evv_on_sclk
-						(hwmgr, VOLTAGE_TYPE_VDDC, sclk,
-						 virtual_voltage_id, &vddc),
-						"Error retrieving EVV voltage value!", continue);
-
-				/* need to make sure vddc is less than 2v or else, it could burn the ASIC. */
-				if (vddc > 2000)
-					printk(KERN_ERR "[ powerplay ] Invalid VDDC value! \n");
+				if (0 == atomctrl_get_voltage_evv_on_sclk
+				    (hwmgr, VOLTAGE_TYPE_VDDC, sclk,
+				     virtual_voltage_id, &vddc)) {
+					/* need to make sure vddc is less than 2v or else, it could burn the ASIC. */
+					PP_ASSERT_WITH_CODE(vddc < 2000, "Invalid VDDC value!", return -1);
 
-				/* the voltage should not be zero nor equal to leakage ID */
-				if (vddc != 0 && vddc != virtual_voltage_id) {
-					data->vddc_leakage.actual_voltage[data->vddc_leakage.count] = vddc;
-					data->vddc_leakage.leakage_id[data->vddc_leakage.count] = virtual_voltage_id;
-					data->vddc_leakage.count++;
+					/* the voltage should not be zero nor equal to leakage ID */
+					if (vddc != 0 && vddc != virtual_voltage_id) {
+						data->vddc_leakage.actual_voltage[data->vddc_leakage.count] = vddc;
+						data->vddc_leakage.leakage_id[data->vddc_leakage.count] = virtual_voltage_id;
+						data->vddc_leakage.count++;
+					}
+				} else {
+					printk("Error retrieving EVV voltage value!\n");
 				}
 			}
 		}
@@ -1298,7 +1302,7 @@ static int tonga_populate_smc_mvdd_table
 			table->Smio[count] |=
 				data->mvdd_voltage_table.entries[count].smio_low;
 		}
-		table->SmioMask2 = data->vddci_voltage_table.mask_low;
+		table->SmioMask2 = data->mvdd_voltage_table.mask_low;
 
 		CONVERT_FROM_HOST_TO_SMC_UL(table->MvddLevelCount);
 	}
@@ -2037,14 +2041,11 @@ static int tonga_populate_single_memory_
 	data->display_timing.num_existing_displays = info.display_count;
 
 	if ((data->mclk_stutter_mode_threshold != 0) &&
-			(memory_clock <= data->mclk_stutter_mode_threshold) &&
-			(data->is_uvd_enabled == 0)
-#if defined(LINUX)
-			&& (PHM_READ_FIELD(hwmgr->device, DPG_PIPE_STUTTER_CONTROL, STUTTER_ENABLE) & 0x1)
-			&& (data->display_timing.num_existing_displays <= 2)
-			&& (data->display_timing.num_existing_displays != 0)
-#endif
-	)
+	    (memory_clock <= data->mclk_stutter_mode_threshold) &&
+	    (data->is_uvd_enabled == 0)
+	    && (PHM_READ_FIELD(hwmgr->device, DPG_PIPE_STUTTER_CONTROL, STUTTER_ENABLE) & 0x1)
+	    && (data->display_timing.num_existing_displays <= 2)
+	    && (data->display_timing.num_existing_displays != 0))
 		memory_level->StutterEnable = 1;
 
 	/* decide strobe mode*/
@@ -2415,6 +2416,24 @@ int tonga_calculate_sclk_params(struct p
 	return 0;
 }
 
+static uint8_t tonga_get_sleep_divider_id_from_clock(uint32_t engine_clock,
+		uint32_t min_engine_clock_in_sr)
+{
+	uint32_t i, temp;
+	uint32_t min = max(min_engine_clock_in_sr, (uint32_t)TONGA_MINIMUM_ENGINE_CLOCK);
+
+	PP_ASSERT_WITH_CODE((engine_clock >= min),
+			"Engine clock can't satisfy stutter requirement!", return 0);
+
+	for (i = TONGA_MAX_DEEPSLEEP_DIVIDER_ID;; i--) {
+		temp = engine_clock >> i;
+
+		if(temp >= min || i == 0)
+			break;
+	}
+	return (uint8_t)i;
+}
+
 /**
  * Populates single SMC SCLK structure using the provided engine clock
  *
@@ -2463,12 +2482,12 @@ static int tonga_populate_single_graphic
 	*get the DAL clock. do it in funture.
 	PECI_GetMinClockSettings(hwmgr->peci, &minClocks);
 	data->display_timing.min_clock_insr = minClocks.engineClockInSR;
-
-	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep))
-	{
-		graphic_level->DeepSleepDivId = PhwTonga_GetSleepDividerIdFromClock(hwmgr, engine_clock, minClocks.engineClockInSR);
-	}
 */
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_SclkDeepSleep))
+		graphic_level->DeepSleepDivId =
+				tonga_get_sleep_divider_id_from_clock(engine_clock,
+						data->display_timing.min_clock_insr);
 
 	/* Default to slow, highest DPM level will be set to PPSMC_DISPLAY_WATERMARK_LOW later.*/
 	graphic_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
@@ -2663,7 +2682,7 @@ static int tonga_populate_all_memory_lev
 struct TONGA_DLL_SPEED_SETTING {
 	uint16_t            Min;                          /* Minimum Data Rate*/
 	uint16_t            Max;                          /* Maximum Data Rate*/
-	uint32_t 			dll_speed;                     /* The desired DLL_SPEED setting*/
+	uint32_t			dll_speed;                     /* The desired DLL_SPEED setting*/
 };
 
 static int tonga_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr)
@@ -2828,27 +2847,6 @@ static int tonga_setup_default_dpm_table
 		}
 	}
 
-	/* Initialize Vddc DPM table based on allow Vddc values.  And populate corresponding std values. */
-	for (i = 0; i < allowed_vdd_sclk_table->count; i++) {
-		data->dpm_table.vddc_table.dpm_levels[i].value = allowed_vdd_mclk_table->entries[i].vddc;
-		/* tonga_hwmgr->dpm_table.VddcTable.dpm_levels[i].param1 = stdVoltageTable->entries[i].Leakage; */
-		/* param1 is for corresponding std voltage */
-		data->dpm_table.vddc_table.dpm_levels[i].enabled = 1;
-	}
-	data->dpm_table.vddc_table.count = allowed_vdd_sclk_table->count;
-
-	if (NULL != allowed_vdd_mclk_table) {
-		/* Initialize Vddci DPM table based on allow Mclk values */
-		for (i = 0; i < allowed_vdd_mclk_table->count; i++) {
-			data->dpm_table.vdd_ci_table.dpm_levels[i].value = allowed_vdd_mclk_table->entries[i].vddci;
-			data->dpm_table.vdd_ci_table.dpm_levels[i].enabled = 1;
-			data->dpm_table.mvdd_table.dpm_levels[i].value = allowed_vdd_mclk_table->entries[i].mvdd;
-			data->dpm_table.mvdd_table.dpm_levels[i].enabled = 1;
-		}
-		data->dpm_table.vdd_ci_table.count = allowed_vdd_mclk_table->count;
-		data->dpm_table.mvdd_table.count = allowed_vdd_mclk_table->count;
-	}
-
 	/* setup PCIE gen speed levels*/
 	tonga_setup_default_pcie_tables(hwmgr);
 
@@ -3296,14 +3294,14 @@ static int tonga_set_private_var_based_o
 		pptable_info->vdd_dep_on_mclk;
 
 	PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table != NULL,
-		"VDD dependency on SCLK table is missing. 	\
+		"VDD dependency on SCLK table is missing.	\
 		This table is mandatory", return -1);
 	PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table->count >= 1,
-		"VDD dependency on SCLK table has to have is missing. 	\
+		"VDD dependency on SCLK table has to have is missing.	\
 		This table is mandatory", return -1);
 
 	PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table != NULL,
-		"VDD dependency on MCLK table is missing. 	\
+		"VDD dependency on MCLK table is missing.	\
 		This table is mandatory", return -1);
 	PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table->count >= 1,
 		"VDD dependency on MCLK table has to have is missing.	 \
@@ -4424,17 +4422,14 @@ int tonga_reset_asic_tasks(struct pp_hwm
 
 int tonga_hwmgr_backend_fini(struct pp_hwmgr *hwmgr)
 {
-	if (NULL != hwmgr->dyn_state.vddc_dep_on_dal_pwrl) {
-		kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl);
-		hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL;
-	}
+	struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
 
-	if (NULL != hwmgr->backend) {
-		kfree(hwmgr->backend);
-		hwmgr->backend = NULL;
+	if (data->soft_pp_table) {
+		kfree(data->soft_pp_table);
+		data->soft_pp_table = NULL;
 	}
 
-	return 0;
+	return phm_hwmgr_backend_fini(hwmgr);
 }
 
 /**
@@ -4494,6 +4489,7 @@ int tonga_hwmgr_backend_init(struct pp_h
 	data->vdd_ci_control = TONGA_VOLTAGE_CONTROL_NONE;
 	data->vdd_gfx_control = TONGA_VOLTAGE_CONTROL_NONE;
 	data->mvdd_control = TONGA_VOLTAGE_CONTROL_NONE;
+	data->force_pcie_gen = PP_PCIEGenInvalid;
 
 	if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr,
 				VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2)) {
@@ -5315,7 +5311,7 @@ static int tonga_freeze_sclk_mclk_dpm(st
 		(data->need_update_smu7_dpm_table &
 		(DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK))) {
 		PP_ASSERT_WITH_CODE(
-			true == tonga_is_dpm_running(hwmgr),
+			0 == tonga_is_dpm_running(hwmgr),
 			"Trying to freeze SCLK DPM when DPM is disabled",
 			);
 		PP_ASSERT_WITH_CODE(
@@ -5328,7 +5324,7 @@ static int tonga_freeze_sclk_mclk_dpm(st
 	if ((0 == data->mclk_dpm_key_disabled) &&
 		(data->need_update_smu7_dpm_table &
 		 DPMTABLE_OD_UPDATE_MCLK)) {
-		PP_ASSERT_WITH_CODE(true == tonga_is_dpm_running(hwmgr),
+		PP_ASSERT_WITH_CODE(0 == tonga_is_dpm_running(hwmgr),
 			"Trying to freeze MCLK DPM when DPM is disabled",
 			);
 		PP_ASSERT_WITH_CODE(
@@ -5429,7 +5425,7 @@ static int tonga_populate_and_upload_scl
 	}
 
 	if (data->need_update_smu7_dpm_table & (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK)) {
-		result = tonga_populate_all_memory_levels(hwmgr);
+		result = tonga_populate_all_graphic_levels(hwmgr);
 		PP_ASSERT_WITH_CODE((0 == result),
 			"Failed to populate SCLK during PopulateNewDPMClocksStates Function!",
 			return result);
@@ -5631,7 +5627,7 @@ static int tonga_unfreeze_sclk_mclk_dpm(
 		(data->need_update_smu7_dpm_table &
 		(DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK))) {
 
-		PP_ASSERT_WITH_CODE(true == tonga_is_dpm_running(hwmgr),
+		PP_ASSERT_WITH_CODE(0 == tonga_is_dpm_running(hwmgr),
 			"Trying to Unfreeze SCLK DPM when DPM is disabled",
 			);
 		PP_ASSERT_WITH_CODE(
@@ -5645,7 +5641,7 @@ static int tonga_unfreeze_sclk_mclk_dpm(
 		(data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK)) {
 
 		PP_ASSERT_WITH_CODE(
-				true == tonga_is_dpm_running(hwmgr),
+				0 == tonga_is_dpm_running(hwmgr),
 				"Trying to Unfreeze MCLK DPM when DPM is disabled",
 				);
 		PP_ASSERT_WITH_CODE(
@@ -5874,7 +5870,7 @@ uint32_t tonga_get_xclk(struct pp_hwmgr
 	if (!fw_info)
 		return 0;
 
-	reference_clock = le16_to_cpu(fw_info->usMinPixelClockPLL_Output);
+	reference_clock = le16_to_cpu(fw_info->usReferenceClock);
 
 	divide = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_CLKPIN_CNTL, XTALIN_DIVIDE);
 
@@ -6039,24 +6035,40 @@ static int tonga_get_pp_table(struct pp_
 {
 	struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
 
-	*table = (char *)&data->smc_state_table;
+	if (!data->soft_pp_table) {
+		data->soft_pp_table = kmemdup(hwmgr->soft_pp_table,
+					      hwmgr->soft_pp_table_size,
+					      GFP_KERNEL);
+		if (!data->soft_pp_table)
+			return -ENOMEM;
+	}
 
-	return sizeof(struct SMU72_Discrete_DpmTable);
+	*table = (char *)&data->soft_pp_table;
+
+	return hwmgr->soft_pp_table_size;
 }
 
 static int tonga_set_pp_table(struct pp_hwmgr *hwmgr, const char *buf, size_t size)
 {
 	struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
 
-	void *table = (void *)&data->smc_state_table;
+	if (!data->soft_pp_table) {
+		data->soft_pp_table = kzalloc(hwmgr->soft_pp_table_size, GFP_KERNEL);
+		if (!data->soft_pp_table)
+			return -ENOMEM;
+	}
 
-	memcpy(table, buf, size);
+	memcpy(data->soft_pp_table, buf, size);
+
+	hwmgr->soft_pp_table = data->soft_pp_table;
+
+	/* TODO: re-init powerplay to implement modified pptable */
 
 	return 0;
 }
 
 static int tonga_force_clock_level(struct pp_hwmgr *hwmgr,
-		enum pp_clock_type type, int level)
+		enum pp_clock_type type, uint32_t mask)
 {
 	struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
 
@@ -6068,20 +6080,28 @@ static int tonga_force_clock_level(struc
 		if (!data->sclk_dpm_key_disabled)
 			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
 					PPSMC_MSG_SCLKDPM_SetEnabledMask,
-					(1 << level));
+					data->dpm_level_enable_mask.sclk_dpm_enable_mask & mask);
 		break;
 	case PP_MCLK:
 		if (!data->mclk_dpm_key_disabled)
 			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
 					PPSMC_MSG_MCLKDPM_SetEnabledMask,
-					(1 << level));
+					data->dpm_level_enable_mask.mclk_dpm_enable_mask & mask);
 		break;
 	case PP_PCIE:
+	{
+		uint32_t tmp = mask & data->dpm_level_enable_mask.pcie_dpm_enable_mask;
+		uint32_t level = 0;
+
+		while (tmp >>= 1)
+			level++;
+
 		if (!data->pcie_dpm_key_disabled)
 			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
 					PPSMC_MSG_PCIeDPM_ForceLevel,
-					(1 << level));
+					level);
 		break;
+	}
 	default:
 		break;
 	}
@@ -6173,6 +6193,7 @@ static const struct pp_hwmgr_func tonga_
 	.powergate_uvd = tonga_phm_powergate_uvd,
 	.powergate_vce = tonga_phm_powergate_vce,
 	.disable_clock_power_gating = tonga_phm_disable_clock_power_gating,
+	.update_clock_gatings = tonga_phm_update_clock_gatings,
 	.notify_smc_display_config_after_ps_adjustment = tonga_notify_smc_display_config_after_ps_adjustment,
 	.display_config_changed = tonga_display_configuration_changed_task,
 	.set_max_fan_pwm_output = tonga_set_max_fan_pwm_output,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.h	2016-07-24 15:23:50.000000000 -0400
@@ -74,7 +74,7 @@ struct tonga_power_state {
 };
 
 struct _phw_tonga_dpm_level {
-	bool  		enabled;
+	bool		enabled;
 	uint32_t    value;
 	uint32_t    param1;
 };
@@ -237,20 +237,20 @@ struct tonga_hwmgr {
 	irq_handler_func_t             ctf_callback;
 	void                             *ctf_context;
 
-	phw_tonga_clock_registers      	  clock_registers;
+	phw_tonga_clock_registers	  clock_registers;
 	phw_tonga_voltage_smio_registers  voltage_smio_registers;
 
-	bool                         	is_memory_GDDR5;
+	bool	is_memory_GDDR5;
 	uint16_t                          acpi_vddc;
-	bool                         	pspp_notify_required;        /* Flag to indicate if PSPP notification to SBIOS is required */
+	bool	pspp_notify_required;        /* Flag to indicate if PSPP notification to SBIOS is required */
 	uint16_t                          force_pcie_gen;            /* The forced PCI-E speed if not 0xffff */
 	uint16_t                          acpi_pcie_gen;             /* The PCI-E speed at ACPI time */
 	uint32_t                           pcie_gen_cap;             /* The PCI-E speed capabilities bitmap from CAIL */
 	uint32_t                           pcie_lane_cap;            /* The PCI-E lane capabilities bitmap from CAIL */
 	uint32_t                           pcie_spc_cap;             /* Symbol Per Clock Capabilities from registry */
-	phw_tonga_leakage_voltage       	vddc_leakage;            /* The Leakage VDDC supported (based on leakage ID).*/
-	phw_tonga_leakage_voltage       	vddcgfx_leakage;         /* The Leakage VDDC supported (based on leakage ID). */
-	phw_tonga_leakage_voltage       	vddci_leakage;           /* The Leakage VDDCI supported (based on leakage ID). */
+	phw_tonga_leakage_voltage	vddc_leakage;            /* The Leakage VDDC supported (based on leakage ID).*/
+	phw_tonga_leakage_voltage	vddcgfx_leakage;         /* The Leakage VDDC supported (based on leakage ID). */
+	phw_tonga_leakage_voltage	vddci_leakage;           /* The Leakage VDDCI supported (based on leakage ID). */
 
 	uint32_t                           mvdd_control;
 	uint32_t                           vddc_mask_low;
@@ -263,8 +263,8 @@ struct tonga_hwmgr {
 	uint32_t                           mclk_stutter_mode_threshold;
 	uint32_t                           mclk_edc_enable_threshold;
 	uint32_t                           mclk_edc_wr_enable_threshold;
-	bool                         	is_uvd_enabled;
-	bool                         	is_xdma_enabled;
+	bool	is_uvd_enabled;
+	bool	is_xdma_enabled;
 	phw_tonga_vbios_boot_state      vbios_boot_state;
 
 	bool                         battery_state;
@@ -353,6 +353,8 @@ struct tonga_hwmgr {
 	bool                           acp_power_gated;  /* 1: gated, 0:not gated */
 	bool                           pg_acp_init;
 
+	/* soft pptable for re-uploading into smu */
+	void *soft_pp_table;
 };
 
 typedef struct tonga_hwmgr tonga_hwmgr;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_pptable.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_pptable.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_pptable.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_pptable.h	2016-07-24 15:23:50.000000000 -0400
@@ -197,6 +197,22 @@ typedef struct _ATOM_Tonga_SCLK_Dependen
 	ATOM_Tonga_SCLK_Dependency_Record entries[1];				 /* Dynamically allocate entries. */
 } ATOM_Tonga_SCLK_Dependency_Table;
 
+typedef struct _ATOM_Polaris_SCLK_Dependency_Record {
+	UCHAR  ucVddInd;											/* Base voltage */
+	USHORT usVddcOffset;										/* Offset relative to base voltage */
+	ULONG ulSclk;
+	USHORT usEdcCurrent;
+	UCHAR  ucReliabilityTemperature;
+	UCHAR  ucCKSVOffsetandDisable;			/* Bits 0~6: Voltage offset for CKS, Bit 7: Disable/enable for the SCLK level. */
+	ULONG  ulSclkOffset;
+} ATOM_Polaris_SCLK_Dependency_Record;
+
+typedef struct _ATOM_Polaris_SCLK_Dependency_Table {
+	UCHAR ucRevId;
+	UCHAR ucNumEntries;							/* Number of entries. */
+	ATOM_Polaris_SCLK_Dependency_Record entries[1];				 /* Dynamically allocate entries. */
+} ATOM_Polaris_SCLK_Dependency_Table;
+
 typedef struct _ATOM_Tonga_PCIE_Record {
 	UCHAR ucPCIEGenSpeed;
 	UCHAR usPCIELaneWidth;
@@ -209,6 +225,20 @@ typedef struct _ATOM_Tonga_PCIE_Table {
 	ATOM_Tonga_PCIE_Record entries[1];							/* Dynamically allocate entries. */
 } ATOM_Tonga_PCIE_Table;
 
+typedef struct _ATOM_Polaris10_PCIE_Record {
+	UCHAR ucPCIEGenSpeed;
+	UCHAR usPCIELaneWidth;
+	UCHAR ucReserved[2];
+	ULONG ulPCIE_Sclk;
+} ATOM_Polaris10_PCIE_Record;
+
+typedef struct _ATOM_Polaris10_PCIE_Table {
+	UCHAR ucRevId;
+	UCHAR ucNumEntries;                                         /* Number of entries. */
+	ATOM_Polaris10_PCIE_Record entries[1];                      /* Dynamically allocate entries. */
+} ATOM_Polaris10_PCIE_Table;
+
+
 typedef struct _ATOM_Tonga_MM_Dependency_Record {
 	UCHAR   ucVddcInd;											 /* VDDC voltage */
 	USHORT  usVddgfxOffset;									  /* Offset relative to VDDC voltage */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.c	2016-07-24 15:23:50.000000000 -0400
@@ -138,12 +138,15 @@ const void *get_powerplay_table(struct p
 
 	u16 size;
 	u8 frev, crev;
-	void *table_address;
-
-	table_address = (ATOM_Tonga_POWERPLAYTABLE *)
-		cgs_atom_get_data_table(hwmgr->device, index, &size, &frev, &crev);
+	void *table_address = (void *)hwmgr->soft_pp_table;
 
-	hwmgr->soft_pp_table = table_address;	/*Cache the result in RAM.*/
+	if (!table_address) {
+		table_address = (ATOM_Tonga_POWERPLAYTABLE *)
+				cgs_atom_get_data_table(hwmgr->device,
+						index, &size, &frev, &crev);
+		hwmgr->soft_pp_table = table_address;	/*Cache the result in RAM.*/
+		hwmgr->soft_pp_table_size = size;
+	}
 
 	return table_address;
 }
@@ -299,7 +302,7 @@ static int init_dpm_2_parameters(
 			(((unsigned long)powerplay_table) + le16_to_cpu(powerplay_table->usPPMTableOffset));
 
 		if (0 != powerplay_table->usPPMTableOffset) {
-			if (1 == get_platform_power_management_table(hwmgr, atom_ppm_table)) {
+			if (get_platform_power_management_table(hwmgr, atom_ppm_table) == 0) {
 				phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 					PHM_PlatformCaps_EnablePlatformPowerManagement);
 			}
@@ -405,41 +408,78 @@ static int get_mclk_voltage_dependency_t
 static int get_sclk_voltage_dependency_table(
 		struct pp_hwmgr *hwmgr,
 		phm_ppt_v1_clock_voltage_dependency_table **pp_tonga_sclk_dep_table,
-		const ATOM_Tonga_SCLK_Dependency_Table * sclk_dep_table
+		const PPTable_Generic_SubTable_Header *sclk_dep_table
 		)
 {
 	uint32_t table_size, i;
 	phm_ppt_v1_clock_voltage_dependency_table *sclk_table;
 
-	PP_ASSERT_WITH_CODE((0 != sclk_dep_table->ucNumEntries),
-		"Invalid PowerPlay Table!", return -1);
+	if (sclk_dep_table->ucRevId < 1) {
+		const ATOM_Tonga_SCLK_Dependency_Table *tonga_table =
+			    (ATOM_Tonga_SCLK_Dependency_Table *)sclk_dep_table;
 
-	table_size = sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record)
-		* sclk_dep_table->ucNumEntries;
+		PP_ASSERT_WITH_CODE((0 != tonga_table->ucNumEntries),
+			"Invalid PowerPlay Table!", return -1);
 
-	sclk_table = (phm_ppt_v1_clock_voltage_dependency_table *)
-		kzalloc(table_size, GFP_KERNEL);
+		table_size = sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record)
+			* tonga_table->ucNumEntries;
 
-	if (NULL == sclk_table)
-		return -ENOMEM;
+		sclk_table = (phm_ppt_v1_clock_voltage_dependency_table *)
+			kzalloc(table_size, GFP_KERNEL);
 
-	memset(sclk_table, 0x00, table_size);
+		if (NULL == sclk_table)
+			return -ENOMEM;
 
-	sclk_table->count = (uint32_t)sclk_dep_table->ucNumEntries;
+		memset(sclk_table, 0x00, table_size);
 
-	for (i = 0; i < sclk_dep_table->ucNumEntries; i++) {
-		sclk_table->entries[i].vddInd =
-			sclk_dep_table->entries[i].ucVddInd;
-		sclk_table->entries[i].vdd_offset =
-			sclk_dep_table->entries[i].usVddcOffset;
-		sclk_table->entries[i].clk =
-			sclk_dep_table->entries[i].ulSclk;
-		sclk_table->entries[i].cks_enable =
-			(((sclk_dep_table->entries[i].ucCKSVOffsetandDisable & 0x80) >> 7) == 0) ? 1 : 0;
-		sclk_table->entries[i].cks_voffset =
-			(sclk_dep_table->entries[i].ucCKSVOffsetandDisable & 0x7F);
-	}
+		sclk_table->count = (uint32_t)tonga_table->ucNumEntries;
 
+		for (i = 0; i < tonga_table->ucNumEntries; i++) {
+			sclk_table->entries[i].vddInd =
+				tonga_table->entries[i].ucVddInd;
+			sclk_table->entries[i].vdd_offset =
+				tonga_table->entries[i].usVddcOffset;
+			sclk_table->entries[i].clk =
+				tonga_table->entries[i].ulSclk;
+			sclk_table->entries[i].cks_enable =
+				(((tonga_table->entries[i].ucCKSVOffsetandDisable & 0x80) >> 7) == 0) ? 1 : 0;
+			sclk_table->entries[i].cks_voffset =
+				(tonga_table->entries[i].ucCKSVOffsetandDisable & 0x7F);
+		}
+	} else {
+		const ATOM_Polaris_SCLK_Dependency_Table *polaris_table =
+			    (ATOM_Polaris_SCLK_Dependency_Table *)sclk_dep_table;
+
+		PP_ASSERT_WITH_CODE((0 != polaris_table->ucNumEntries),
+			"Invalid PowerPlay Table!", return -1);
+
+		table_size = sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record)
+			* polaris_table->ucNumEntries;
+
+		sclk_table = (phm_ppt_v1_clock_voltage_dependency_table *)
+			kzalloc(table_size, GFP_KERNEL);
+
+		if (NULL == sclk_table)
+			return -ENOMEM;
+
+		memset(sclk_table, 0x00, table_size);
+
+		sclk_table->count = (uint32_t)polaris_table->ucNumEntries;
+
+		for (i = 0; i < polaris_table->ucNumEntries; i++) {
+			sclk_table->entries[i].vddInd =
+				polaris_table->entries[i].ucVddInd;
+			sclk_table->entries[i].vdd_offset =
+				polaris_table->entries[i].usVddcOffset;
+			sclk_table->entries[i].clk =
+				polaris_table->entries[i].ulSclk;
+			sclk_table->entries[i].cks_enable =
+				(((polaris_table->entries[i].ucCKSVOffsetandDisable & 0x80) >> 7) == 0) ? 1 : 0;
+			sclk_table->entries[i].cks_voffset =
+				(polaris_table->entries[i].ucCKSVOffsetandDisable & 0x7F);
+			sclk_table->entries[i].sclk_offset = polaris_table->entries[i].ulSclkOffset;
+		}
+	}
 	*pp_tonga_sclk_dep_table = sclk_table;
 
 	return 0;
@@ -448,47 +488,90 @@ static int get_sclk_voltage_dependency_t
 static int get_pcie_table(
 		struct pp_hwmgr *hwmgr,
 		phm_ppt_v1_pcie_table **pp_tonga_pcie_table,
-		const ATOM_Tonga_PCIE_Table * atom_pcie_table
+		const PPTable_Generic_SubTable_Header * pTable
 		)
 {
 	uint32_t table_size, i, pcie_count;
 	phm_ppt_v1_pcie_table *pcie_table;
 	struct phm_ppt_v1_information *pp_table_information =
 		(struct phm_ppt_v1_information *)(hwmgr->pptable);
-	PP_ASSERT_WITH_CODE((0 != atom_pcie_table->ucNumEntries),
-		"Invalid PowerPlay Table!", return -1);
 
-	table_size = sizeof(uint32_t) +
-		sizeof(phm_ppt_v1_pcie_record) * atom_pcie_table->ucNumEntries;
+	if (pTable->ucRevId < 1) {
+		const ATOM_Tonga_PCIE_Table *atom_pcie_table = (ATOM_Tonga_PCIE_Table *)pTable;
+		PP_ASSERT_WITH_CODE((atom_pcie_table->ucNumEntries != 0),
+			"Invalid PowerPlay Table!", return -1);
 
-	pcie_table = (phm_ppt_v1_pcie_table *)kzalloc(table_size, GFP_KERNEL);
+		table_size = sizeof(uint32_t) +
+			sizeof(phm_ppt_v1_pcie_record) * atom_pcie_table->ucNumEntries;
 
-	if (NULL == pcie_table)
-		return -ENOMEM;
+		pcie_table = (phm_ppt_v1_pcie_table *)kzalloc(table_size, GFP_KERNEL);
 
-	memset(pcie_table, 0x00, table_size);
+		if (pcie_table == NULL)
+			return -ENOMEM;
 
-	/*
-	* Make sure the number of pcie entries are less than or equal to sclk dpm levels.
-	* Since first PCIE entry is for ULV, #pcie has to be <= SclkLevel + 1.
-	*/
-	pcie_count = (pp_table_information->vdd_dep_on_sclk->count) + 1;
-	if ((uint32_t)atom_pcie_table->ucNumEntries <= pcie_count)
-		pcie_count = (uint32_t)atom_pcie_table->ucNumEntries;
-	else
-		printk(KERN_ERR "[ powerplay ] Number of Pcie Entries exceed the number of SCLK Dpm Levels! \
-		Disregarding the excess entries... \n");
+		memset(pcie_table, 0x00, table_size);
 
-	pcie_table->count = pcie_count;
+		/*
+		* Make sure the number of pcie entries are less than or equal to sclk dpm levels.
+		* Since first PCIE entry is for ULV, #pcie has to be <= SclkLevel + 1.
+		*/
+		pcie_count = (pp_table_information->vdd_dep_on_sclk->count) + 1;
+		if ((uint32_t)atom_pcie_table->ucNumEntries <= pcie_count)
+			pcie_count = (uint32_t)atom_pcie_table->ucNumEntries;
+		else
+			printk(KERN_ERR "[ powerplay ] Number of Pcie Entries exceed the number of SCLK Dpm Levels! \
+			Disregarding the excess entries... \n");
 
-	for (i = 0; i < pcie_count; i++) {
-		pcie_table->entries[i].gen_speed =
-			atom_pcie_table->entries[i].ucPCIEGenSpeed;
-		pcie_table->entries[i].lane_width =
-			atom_pcie_table->entries[i].usPCIELaneWidth;
-	}
+		pcie_table->count = pcie_count;
 
-	*pp_tonga_pcie_table = pcie_table;
+		for (i = 0; i < pcie_count; i++) {
+			pcie_table->entries[i].gen_speed =
+				atom_pcie_table->entries[i].ucPCIEGenSpeed;
+			pcie_table->entries[i].lane_width =
+				atom_pcie_table->entries[i].usPCIELaneWidth;
+		}
+
+		*pp_tonga_pcie_table = pcie_table;
+	} else {
+		/* Polaris10/Polaris11 and newer. */
+		const ATOM_Polaris10_PCIE_Table *atom_pcie_table = (ATOM_Polaris10_PCIE_Table *)pTable;
+		PP_ASSERT_WITH_CODE((atom_pcie_table->ucNumEntries != 0),
+			"Invalid PowerPlay Table!", return -1);
+
+		table_size = sizeof(uint32_t) +
+			sizeof(phm_ppt_v1_pcie_record) * atom_pcie_table->ucNumEntries;
+
+		pcie_table = (phm_ppt_v1_pcie_table *)kzalloc(table_size, GFP_KERNEL);
+
+		if (pcie_table == NULL)
+			return -ENOMEM;
+
+		memset(pcie_table, 0x00, table_size);
+
+		/*
+		* Make sure the number of pcie entries are less than or equal to sclk dpm levels.
+		* Since first PCIE entry is for ULV, #pcie has to be <= SclkLevel + 1.
+		*/
+		pcie_count = (pp_table_information->vdd_dep_on_sclk->count) + 1;
+		if ((uint32_t)atom_pcie_table->ucNumEntries <= pcie_count)
+			pcie_count = (uint32_t)atom_pcie_table->ucNumEntries;
+		else
+			printk(KERN_ERR "[ powerplay ] Number of Pcie Entries exceed the number of SCLK Dpm Levels! \
+			Disregarding the excess entries... \n");
+
+		pcie_table->count = pcie_count;
+
+		for (i = 0; i < pcie_count; i++) {
+			pcie_table->entries[i].gen_speed =
+				atom_pcie_table->entries[i].ucPCIEGenSpeed;
+			pcie_table->entries[i].lane_width =
+				atom_pcie_table->entries[i].usPCIELaneWidth;
+			pcie_table->entries[i].pcie_sclk =
+				atom_pcie_table->entries[i].ulPCIE_Sclk;
+		}
+
+		*pp_tonga_pcie_table = pcie_table;
+	}
 
 	return 0;
 }
@@ -662,14 +745,14 @@ static int init_clock_voltage_dependency
 	const ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table =
 		(const ATOM_Tonga_MCLK_Dependency_Table *)(((unsigned long) powerplay_table) +
 		le16_to_cpu(powerplay_table->usMclkDependencyTableOffset));
-	const ATOM_Tonga_SCLK_Dependency_Table *sclk_dep_table =
-		(const ATOM_Tonga_SCLK_Dependency_Table *)(((unsigned long) powerplay_table) +
+	const PPTable_Generic_SubTable_Header *sclk_dep_table =
+		(const PPTable_Generic_SubTable_Header *)(((unsigned long) powerplay_table) +
 		le16_to_cpu(powerplay_table->usSclkDependencyTableOffset));
 	const ATOM_Tonga_Hard_Limit_Table *pHardLimits =
 		(const ATOM_Tonga_Hard_Limit_Table *)(((unsigned long) powerplay_table) +
 		le16_to_cpu(powerplay_table->usHardLimitTableOffset));
-	const ATOM_Tonga_PCIE_Table *pcie_table =
-		(const ATOM_Tonga_PCIE_Table *)(((unsigned long) powerplay_table) +
+	const PPTable_Generic_SubTable_Header *pcie_table =
+		(const PPTable_Generic_SubTable_Header *)(((unsigned long) powerplay_table) +
 		le16_to_cpu(powerplay_table->usPCIETableOffset));
 
 	pp_table_information->vdd_dep_on_sclk = NULL;
@@ -994,48 +1077,44 @@ int tonga_pp_tables_uninitialize(struct
 	struct phm_ppt_v1_information *pp_table_information =
 		(struct phm_ppt_v1_information *)(hwmgr->pptable);
 
-	if (NULL != hwmgr->soft_pp_table) {
-		kfree(hwmgr->soft_pp_table);
+	if (NULL != hwmgr->soft_pp_table)
 		hwmgr->soft_pp_table = NULL;
-	}
 
-	if (NULL != pp_table_information->vdd_dep_on_sclk)
-		pp_table_information->vdd_dep_on_sclk = NULL;
+	kfree(pp_table_information->vdd_dep_on_sclk);
+	pp_table_information->vdd_dep_on_sclk = NULL;
 
-	if (NULL != pp_table_information->vdd_dep_on_mclk)
-		pp_table_information->vdd_dep_on_mclk = NULL;
+	kfree(pp_table_information->vdd_dep_on_mclk);
+	pp_table_information->vdd_dep_on_mclk = NULL;
 
-	if (NULL != pp_table_information->valid_mclk_values)
-		pp_table_information->valid_mclk_values = NULL;
+	kfree(pp_table_information->valid_mclk_values);
+	pp_table_information->valid_mclk_values = NULL;
 
-	if (NULL != pp_table_information->valid_sclk_values)
-		pp_table_information->valid_sclk_values = NULL;
+	kfree(pp_table_information->valid_sclk_values);
+	pp_table_information->valid_sclk_values = NULL;
 
-	if (NULL != pp_table_information->vddc_lookup_table)
-		pp_table_information->vddc_lookup_table = NULL;
+	kfree(pp_table_information->vddc_lookup_table);
+	pp_table_information->vddc_lookup_table = NULL;
 
-	if (NULL != pp_table_information->vddgfx_lookup_table)
-		pp_table_information->vddgfx_lookup_table = NULL;
+	kfree(pp_table_information->vddgfx_lookup_table);
+	pp_table_information->vddgfx_lookup_table = NULL;
 
-	if (NULL != pp_table_information->mm_dep_table)
-		pp_table_information->mm_dep_table = NULL;
+	kfree(pp_table_information->mm_dep_table);
+	pp_table_information->mm_dep_table = NULL;
 
-	if (NULL != pp_table_information->cac_dtp_table)
-		pp_table_information->cac_dtp_table = NULL;
+	kfree(pp_table_information->cac_dtp_table);
+	pp_table_information->cac_dtp_table = NULL;
 
-	if (NULL != hwmgr->dyn_state.cac_dtp_table)
-		hwmgr->dyn_state.cac_dtp_table = NULL;
+	kfree(hwmgr->dyn_state.cac_dtp_table);
+	hwmgr->dyn_state.cac_dtp_table = NULL;
 
-	if (NULL != pp_table_information->ppm_parameter_table)
-		pp_table_information->ppm_parameter_table = NULL;
+	kfree(pp_table_information->ppm_parameter_table);
+	pp_table_information->ppm_parameter_table = NULL;
 
-	if (NULL != pp_table_information->pcie_table)
-		pp_table_information->pcie_table = NULL;
+	kfree(pp_table_information->pcie_table);
+	pp_table_information->pcie_table = NULL;
 
-	if (NULL != hwmgr->pptable) {
-		kfree(hwmgr->pptable);
-		hwmgr->pptable = NULL;
-	}
+	kfree(hwmgr->pptable);
+	hwmgr->pptable = NULL;
 
 	return result;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_thermal.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_thermal.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_thermal.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_thermal.c	2016-07-24 15:23:50.000000000 -0400
@@ -195,8 +195,8 @@ int tonga_fan_ctrl_set_fan_speed_percent
 	if (0 == duty100)
 		return -EINVAL;
 
-	tmp64 = (uint64_t)speed * 100;
-	do_div(tmp64, duty100);
+	tmp64 = (uint64_t)speed * duty100;
+	do_div(tmp64, 100);
 	duty = (uint32_t)tmp64;
 
 	PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL0, FDO_STATIC_DUTY, duty);
@@ -525,7 +525,7 @@ static int tf_tonga_thermal_disable_aler
 	return tonga_thermal_disable_alert(hwmgr);
 }
 
-static struct phm_master_table_item tonga_thermal_start_thermal_controller_master_list[] = {
+static const struct phm_master_table_item tonga_thermal_start_thermal_controller_master_list[] = {
 	{ NULL, tf_tonga_thermal_initialize },
 	{ NULL, tf_tonga_thermal_set_temperature_range },
 	{ NULL, tf_tonga_thermal_enable_alert },
@@ -538,20 +538,20 @@ static struct phm_master_table_item tong
 	{ NULL, NULL }
 };
 
-static struct phm_master_table_header tonga_thermal_start_thermal_controller_master = {
+static const struct phm_master_table_header tonga_thermal_start_thermal_controller_master = {
 	0,
 	PHM_MasterTableFlag_None,
 	tonga_thermal_start_thermal_controller_master_list
 };
 
-static struct phm_master_table_item tonga_thermal_set_temperature_range_master_list[] = {
+static const struct phm_master_table_item tonga_thermal_set_temperature_range_master_list[] = {
 	{ NULL, tf_tonga_thermal_disable_alert},
 	{ NULL, tf_tonga_thermal_set_temperature_range},
 	{ NULL, tf_tonga_thermal_enable_alert},
 	{ NULL, NULL }
 };
 
-struct phm_master_table_header tonga_thermal_set_temperature_range_master = {
+static const struct phm_master_table_header tonga_thermal_set_temperature_range_master = {
 	0,
 	PHM_MasterTableFlag_None,
 	tonga_thermal_set_temperature_range_master_list
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h	2016-07-24 15:23:50.000000000 -0400
@@ -289,6 +289,9 @@ struct pp_states_info {
 
 #define PP_BLOCK_GFX_CG         0x01
 #define PP_BLOCK_GFX_MG         0x02
+#define PP_BLOCK_GFX_3D         0x04
+#define PP_BLOCK_GFX_RLC        0x08
+#define PP_BLOCK_GFX_CP         0x10
 #define PP_BLOCK_SYS_BIF        0x01
 #define PP_BLOCK_SYS_MC         0x02
 #define PP_BLOCK_SYS_ROM        0x04
@@ -337,7 +340,7 @@ struct amd_powerplay_funcs {
 	int (*get_pp_num_states)(void *handle, struct pp_states_info *data);
 	int (*get_pp_table)(void *handle, char **table);
 	int (*set_pp_table)(void *handle, const char *buf, size_t size);
-	int (*force_clock_level)(void *handle, enum pp_clock_type type, int level);
+	int (*force_clock_level)(void *handle, enum pp_clock_type type, uint32_t mask);
 	int (*print_clock_levels)(void *handle, enum pp_clock_type type, char *buf);
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/inc/eventmgr.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/inc/eventmgr.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/inc/eventmgr.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/inc/eventmgr.h	2016-07-24 15:23:50.000000000 -0400
@@ -37,7 +37,7 @@ typedef int (*pem_event_action)(struct p
 
 struct action_chain {
 	const char *description;  /* action chain description for debugging purpose */
-	const pem_event_action **action_chain; /* pointer to chain of event actions */
+	const pem_event_action * const *action_chain; /* pointer to chain of event actions */
 };
 
 struct pem_power_source_ui_state_info {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/inc/fiji_pwrvirus.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/inc/fiji_pwrvirus.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/inc/fiji_pwrvirus.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/inc/fiji_pwrvirus.h	2016-07-24 15:23:50.000000000 -0400
@@ -46,7 +46,7 @@ struct PWR_Command_Table
 typedef struct PWR_Command_Table PWR_Command_Table;
 
 #define PWR_VIRUS_TABLE_SIZE  10243
-static PWR_Command_Table PwrVirusTable[PWR_VIRUS_TABLE_SIZE] =
+static const PWR_Command_Table PwrVirusTable[PWR_VIRUS_TABLE_SIZE] =
 {
     { PwrCmdWrite, 0x100100b6, mmPCIE_INDEX                               },
     { PwrCmdWrite, 0x00000000, mmPCIE_DATA                                },
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h	2016-07-24 15:23:50.000000000 -0400
@@ -211,6 +211,7 @@ enum phm_platform_caps {
 	PHM_PlatformCaps_ClockStretcher,
 	PHM_PlatformCaps_TablelessHardwareInterface,
 	PHM_PlatformCaps_EnableDriverEVV,
+	PHM_PlatformCaps_SPLLShutdownSupport,
 	PHM_PlatformCaps_Max
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h	2016-07-24 15:23:50.000000000 -0400
@@ -141,7 +141,7 @@ enum phm_master_table_flag {
 struct phm_master_table_header {
 	uint32_t storage_size;
 	uint32_t flags;
-	struct phm_master_table_item *master_list;
+	const struct phm_master_table_item *master_list;
 };
 
 struct phm_runtime_table_header {
@@ -199,7 +199,7 @@ extern int phm_dispatch_table(struct pp_
 			      void *input, void *output);
 
 extern int phm_construct_table(struct pp_hwmgr *hwmgr,
-			       struct phm_master_table_header *master_table,
+			       const struct phm_master_table_header *master_table,
 			       struct phm_runtime_table_header *rt_table);
 
 extern int phm_destroy_table(struct pp_hwmgr *hwmgr,
@@ -335,8 +335,9 @@ struct pp_hwmgr_func {
 	int (*power_off_asic)(struct pp_hwmgr *hwmgr);
 	int (*get_pp_table)(struct pp_hwmgr *hwmgr, char **table);
 	int (*set_pp_table)(struct pp_hwmgr *hwmgr, const char *buf, size_t size);
-	int (*force_clock_level)(struct pp_hwmgr *hwmgr, enum pp_clock_type type, int level);
+	int (*force_clock_level)(struct pp_hwmgr *hwmgr, enum pp_clock_type type, uint32_t mask);
 	int (*print_clock_levels)(struct pp_hwmgr *hwmgr, enum pp_clock_type type, char *buf);
+	int (*enable_per_cu_power_gating)(struct pp_hwmgr *hwmgr, bool enable);
 };
 
 struct pp_table_func {
@@ -410,6 +411,8 @@ struct phm_cac_tdp_table {
 	uint8_t  ucVr_I2C_Line;
 	uint8_t  ucPlx_I2C_address;
 	uint8_t  ucPlx_I2C_Line;
+	uint32_t usBoostPowerLimit;
+	uint8_t  ucCKS_LDO_REFSEL;
 };
 
 struct phm_ppm_table {
@@ -499,7 +502,7 @@ struct phm_dynamic_state_info {
 	struct phm_ppm_table                          *ppm_parameter_table;
 	struct phm_cac_tdp_table                      *cac_dtp_table;
 	struct phm_clock_voltage_dependency_table	  *vdd_gfx_dependency_on_sclk;
-	struct phm_vq_budgeting_table		  		  *vq_budgeting_table;
+	struct phm_vq_budgeting_table				  *vq_budgeting_table;
 };
 
 struct pp_fan_info {
@@ -576,6 +579,7 @@ struct pp_hwmgr {
 	void *device;
 	struct pp_smumgr *smumgr;
 	const void *soft_pp_table;
+	uint32_t soft_pp_table_size;
 	bool need_pp_table_upload;
 	enum amd_dpm_forced_level dpm_level;
 	bool block_hw_access;
@@ -671,7 +675,7 @@ extern int phm_get_sclk_for_voltage_evv(
 extern int phm_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr *hwmgr);
 extern int phm_hwmgr_backend_fini(struct pp_hwmgr *hwmgr);
 extern uint32_t phm_get_lowest_enabled_level(struct pp_hwmgr *hwmgr, uint32_t mask);
-
+extern void phm_apply_dal_min_voltage_request(struct pp_hwmgr *hwmgr);
 
 #define PHM_ENTIRE_REGISTER_MASK 0xFFFFFFFFU
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/inc/polaris10_ppsmc.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/inc/polaris10_ppsmc.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/inc/polaris10_ppsmc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/inc/polaris10_ppsmc.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,412 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef POLARIS10_PP_SMC_H
+#define POLARIS10_PP_SMC_H
+
+
+#pragma pack(push, 1)
+
+#define PPSMC_MSG_SetGBDroopSettings          ((uint16_t) 0x305)
+
+#define PPSMC_SWSTATE_FLAG_DC                           0x01
+#define PPSMC_SWSTATE_FLAG_UVD                          0x02
+#define PPSMC_SWSTATE_FLAG_VCE                          0x04
+
+#define PPSMC_THERMAL_PROTECT_TYPE_INTERNAL             0x00
+#define PPSMC_THERMAL_PROTECT_TYPE_EXTERNAL             0x01
+#define PPSMC_THERMAL_PROTECT_TYPE_NONE                 0xff
+
+#define PPSMC_SYSTEMFLAG_GPIO_DC                        0x01
+#define PPSMC_SYSTEMFLAG_STEPVDDC                       0x02
+#define PPSMC_SYSTEMFLAG_GDDR5                          0x04
+
+#define PPSMC_SYSTEMFLAG_DISABLE_BABYSTEP               0x08
+
+#define PPSMC_SYSTEMFLAG_REGULATOR_HOT                  0x10
+#define PPSMC_SYSTEMFLAG_REGULATOR_HOT_ANALOG           0x20
+
+#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_MASK              0x07
+#define PPSMC_EXTRAFLAGS_AC2DC_DONT_WAIT_FOR_VBLANK     0x08
+
+#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTODPMLOWSTATE   0x00
+#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTOINITIALSTATE  0x01
+
+
+#define PPSMC_DPM2FLAGS_TDPCLMP                         0x01
+#define PPSMC_DPM2FLAGS_PWRSHFT                         0x02
+#define PPSMC_DPM2FLAGS_OCP                             0x04
+
+
+#define PPSMC_DISPLAY_WATERMARK_LOW                     0
+#define PPSMC_DISPLAY_WATERMARK_HIGH                    1
+
+
+#define PPSMC_STATEFLAG_AUTO_PULSE_SKIP    0x01
+#define PPSMC_STATEFLAG_POWERBOOST         0x02
+#define PPSMC_STATEFLAG_PSKIP_ON_TDP_FAULT 0x04
+#define PPSMC_STATEFLAG_POWERSHIFT         0x08
+#define PPSMC_STATEFLAG_SLOW_READ_MARGIN   0x10
+#define PPSMC_STATEFLAG_DEEPSLEEP_THROTTLE 0x20
+#define PPSMC_STATEFLAG_DEEPSLEEP_BYPASS   0x40
+
+
+#define FDO_MODE_HARDWARE 0
+#define FDO_MODE_PIECE_WISE_LINEAR 1
+
+enum FAN_CONTROL {
+	FAN_CONTROL_FUZZY,
+	FAN_CONTROL_TABLE
+};
+
+
+#define PPSMC_Result_OK             ((uint16_t)0x01)
+#define PPSMC_Result_NoMore         ((uint16_t)0x02)
+
+#define PPSMC_Result_NotNow         ((uint16_t)0x03)
+#define PPSMC_Result_Failed         ((uint16_t)0xFF)
+#define PPSMC_Result_UnknownCmd     ((uint16_t)0xFE)
+#define PPSMC_Result_UnknownVT      ((uint16_t)0xFD)
+
+typedef uint16_t PPSMC_Result;
+
+#define PPSMC_isERROR(x) ((uint16_t)0x80 & (x))
+
+
+#define PPSMC_MSG_Halt                      ((uint16_t)0x10)
+#define PPSMC_MSG_Resume                    ((uint16_t)0x11)
+#define PPSMC_MSG_EnableDPMLevel            ((uint16_t)0x12)
+#define PPSMC_MSG_ZeroLevelsDisabled        ((uint16_t)0x13)
+#define PPSMC_MSG_OneLevelsDisabled         ((uint16_t)0x14)
+#define PPSMC_MSG_TwoLevelsDisabled         ((uint16_t)0x15)
+#define PPSMC_MSG_EnableThermalInterrupt    ((uint16_t)0x16)
+#define PPSMC_MSG_RunningOnAC               ((uint16_t)0x17)
+#define PPSMC_MSG_LevelUp                   ((uint16_t)0x18)
+#define PPSMC_MSG_LevelDown                 ((uint16_t)0x19)
+#define PPSMC_MSG_ResetDPMCounters          ((uint16_t)0x1a)
+#define PPSMC_MSG_SwitchToSwState           ((uint16_t)0x20)
+#define PPSMC_MSG_SwitchToSwStateLast       ((uint16_t)0x3f)
+#define PPSMC_MSG_SwitchToInitialState      ((uint16_t)0x40)
+#define PPSMC_MSG_NoForcedLevel             ((uint16_t)0x41)
+#define PPSMC_MSG_ForceHigh                 ((uint16_t)0x42)
+#define PPSMC_MSG_ForceMediumOrHigh         ((uint16_t)0x43)
+#define PPSMC_MSG_SwitchToMinimumPower      ((uint16_t)0x51)
+#define PPSMC_MSG_ResumeFromMinimumPower    ((uint16_t)0x52)
+#define PPSMC_MSG_EnableCac                 ((uint16_t)0x53)
+#define PPSMC_MSG_DisableCac                ((uint16_t)0x54)
+#define PPSMC_DPMStateHistoryStart          ((uint16_t)0x55)
+#define PPSMC_DPMStateHistoryStop           ((uint16_t)0x56)
+#define PPSMC_CACHistoryStart               ((uint16_t)0x57)
+#define PPSMC_CACHistoryStop                ((uint16_t)0x58)
+#define PPSMC_TDPClampingActive             ((uint16_t)0x59)
+#define PPSMC_TDPClampingInactive           ((uint16_t)0x5A)
+#define PPSMC_StartFanControl               ((uint16_t)0x5B)
+#define PPSMC_StopFanControl                ((uint16_t)0x5C)
+#define PPSMC_NoDisplay                     ((uint16_t)0x5D)
+#define PPSMC_HasDisplay                    ((uint16_t)0x5E)
+#define PPSMC_MSG_UVDPowerOFF               ((uint16_t)0x60)
+#define PPSMC_MSG_UVDPowerON                ((uint16_t)0x61)
+#define PPSMC_MSG_EnableULV                 ((uint16_t)0x62)
+#define PPSMC_MSG_DisableULV                ((uint16_t)0x63)
+#define PPSMC_MSG_EnterULV                  ((uint16_t)0x64)
+#define PPSMC_MSG_ExitULV                   ((uint16_t)0x65)
+#define PPSMC_PowerShiftActive              ((uint16_t)0x6A)
+#define PPSMC_PowerShiftInactive            ((uint16_t)0x6B)
+#define PPSMC_OCPActive                     ((uint16_t)0x6C)
+#define PPSMC_OCPInactive                   ((uint16_t)0x6D)
+#define PPSMC_CACLongTermAvgEnable          ((uint16_t)0x6E)
+#define PPSMC_CACLongTermAvgDisable         ((uint16_t)0x6F)
+#define PPSMC_MSG_InferredStateSweep_Start  ((uint16_t)0x70)
+#define PPSMC_MSG_InferredStateSweep_Stop   ((uint16_t)0x71)
+#define PPSMC_MSG_SwitchToLowestInfState    ((uint16_t)0x72)
+#define PPSMC_MSG_SwitchToNonInfState       ((uint16_t)0x73)
+#define PPSMC_MSG_AllStateSweep_Start       ((uint16_t)0x74)
+#define PPSMC_MSG_AllStateSweep_Stop        ((uint16_t)0x75)
+#define PPSMC_MSG_SwitchNextLowerInfState   ((uint16_t)0x76)
+#define PPSMC_MSG_SwitchNextHigherInfState  ((uint16_t)0x77)
+#define PPSMC_MSG_MclkRetrainingTest        ((uint16_t)0x78)
+#define PPSMC_MSG_ForceTDPClamping          ((uint16_t)0x79)
+#define PPSMC_MSG_CollectCAC_PowerCorreln   ((uint16_t)0x7A)
+#define PPSMC_MSG_CollectCAC_WeightCalib    ((uint16_t)0x7B)
+#define PPSMC_MSG_CollectCAC_SQonly         ((uint16_t)0x7C)
+#define PPSMC_MSG_CollectCAC_TemperaturePwr ((uint16_t)0x7D)
+
+#define PPSMC_MSG_ExtremitiesTest_Start     ((uint16_t)0x7E)
+#define PPSMC_MSG_ExtremitiesTest_Stop      ((uint16_t)0x7F)
+#define PPSMC_FlushDataCache                ((uint16_t)0x80)
+#define PPSMC_FlushInstrCache               ((uint16_t)0x81)
+
+#define PPSMC_MSG_SetEnabledLevels          ((uint16_t)0x82)
+#define PPSMC_MSG_SetForcedLevels           ((uint16_t)0x83)
+
+#define PPSMC_MSG_ResetToDefaults           ((uint16_t)0x84)
+
+#define PPSMC_MSG_SetForcedLevelsAndJump      ((uint16_t)0x85)
+#define PPSMC_MSG_SetCACHistoryMode           ((uint16_t)0x86)
+#define PPSMC_MSG_EnableDTE                   ((uint16_t)0x87)
+#define PPSMC_MSG_DisableDTE                  ((uint16_t)0x88)
+
+#define PPSMC_MSG_SmcSpaceSetAddress          ((uint16_t)0x89)
+#define PPSM_MSG_SmcSpaceWriteDWordInc        ((uint16_t)0x8A)
+#define PPSM_MSG_SmcSpaceWriteWordInc         ((uint16_t)0x8B)
+#define PPSM_MSG_SmcSpaceWriteByteInc         ((uint16_t)0x8C)
+
+#define PPSMC_MSG_BREAK                       ((uint16_t)0xF8)
+
+#define PPSMC_MSG_Test                        ((uint16_t) 0x100)
+#define PPSMC_MSG_DPM_Voltage_Pwrmgt          ((uint16_t) 0x101)
+#define PPSMC_MSG_DPM_Config                  ((uint16_t) 0x102)
+#define PPSMC_MSG_PM_Controller_Start         ((uint16_t) 0x103)
+#define PPSMC_MSG_DPM_ForceState              ((uint16_t) 0x104)
+#define PPSMC_MSG_PG_PowerDownSIMD            ((uint16_t) 0x105)
+#define PPSMC_MSG_PG_PowerUpSIMD              ((uint16_t) 0x106)
+#define PPSMC_MSG_PM_Controller_Stop          ((uint16_t) 0x107)
+#define PPSMC_MSG_PG_SIMD_Config              ((uint16_t) 0x108)
+#define PPSMC_MSG_Voltage_Cntl_Enable         ((uint16_t) 0x109)
+#define PPSMC_MSG_Thermal_Cntl_Enable         ((uint16_t) 0x10a)
+#define PPSMC_MSG_Reset_Service               ((uint16_t) 0x10b)
+#define PPSMC_MSG_VCEPowerOFF                 ((uint16_t) 0x10e)
+#define PPSMC_MSG_VCEPowerON                  ((uint16_t) 0x10f)
+#define PPSMC_MSG_DPM_Disable_VCE_HS          ((uint16_t) 0x110)
+#define PPSMC_MSG_DPM_Enable_VCE_HS           ((uint16_t) 0x111)
+#define PPSMC_MSG_DPM_N_LevelsDisabled        ((uint16_t) 0x112)
+#define PPSMC_MSG_DCEPowerOFF                 ((uint16_t) 0x113)
+#define PPSMC_MSG_DCEPowerON                  ((uint16_t) 0x114)
+#define PPSMC_MSG_PCIE_DDIPowerDown           ((uint16_t) 0x117)
+#define PPSMC_MSG_PCIE_DDIPowerUp             ((uint16_t) 0x118)
+#define PPSMC_MSG_PCIE_CascadePLLPowerDown    ((uint16_t) 0x119)
+#define PPSMC_MSG_PCIE_CascadePLLPowerUp      ((uint16_t) 0x11a)
+#define PPSMC_MSG_SYSPLLPowerOff              ((uint16_t) 0x11b)
+#define PPSMC_MSG_SYSPLLPowerOn               ((uint16_t) 0x11c)
+#define PPSMC_MSG_DCE_RemoveVoltageAdjustment ((uint16_t) 0x11d)
+#define PPSMC_MSG_DCE_AllowVoltageAdjustment  ((uint16_t) 0x11e)
+#define PPSMC_MSG_DISPLAYPHYStatusNotify      ((uint16_t) 0x11f)
+#define PPSMC_MSG_EnableBAPM                  ((uint16_t) 0x120)
+#define PPSMC_MSG_DisableBAPM                 ((uint16_t) 0x121)
+#define PPSMC_MSG_Spmi_Enable                 ((uint16_t) 0x122)
+#define PPSMC_MSG_Spmi_Timer                  ((uint16_t) 0x123)
+#define PPSMC_MSG_LCLK_DPM_Config             ((uint16_t) 0x124)
+#define PPSMC_MSG_VddNB_Request               ((uint16_t) 0x125)
+#define PPSMC_MSG_PCIE_DDIPhyPowerDown        ((uint32_t) 0x126)
+#define PPSMC_MSG_PCIE_DDIPhyPowerUp          ((uint32_t) 0x127)
+#define PPSMC_MSG_MCLKDPM_Config              ((uint16_t) 0x128)
+
+#define PPSMC_MSG_UVDDPM_Config               ((uint16_t) 0x129)
+#define PPSMC_MSG_VCEDPM_Config               ((uint16_t) 0x12A)
+#define PPSMC_MSG_ACPDPM_Config               ((uint16_t) 0x12B)
+#define PPSMC_MSG_SAMUDPM_Config              ((uint16_t) 0x12C)
+#define PPSMC_MSG_UVDDPM_SetEnabledMask       ((uint16_t) 0x12D)
+#define PPSMC_MSG_VCEDPM_SetEnabledMask       ((uint16_t) 0x12E)
+#define PPSMC_MSG_ACPDPM_SetEnabledMask       ((uint16_t) 0x12F)
+#define PPSMC_MSG_SAMUDPM_SetEnabledMask      ((uint16_t) 0x130)
+#define PPSMC_MSG_MCLKDPM_ForceState          ((uint16_t) 0x131)
+#define PPSMC_MSG_MCLKDPM_NoForcedLevel       ((uint16_t) 0x132)
+#define PPSMC_MSG_Thermal_Cntl_Disable        ((uint16_t) 0x133)
+#define PPSMC_MSG_SetTDPLimit                 ((uint16_t) 0x134)
+#define PPSMC_MSG_Voltage_Cntl_Disable        ((uint16_t) 0x135)
+#define PPSMC_MSG_PCIeDPM_Enable              ((uint16_t) 0x136)
+#define PPSMC_MSG_ACPPowerOFF                 ((uint16_t) 0x137)
+#define PPSMC_MSG_ACPPowerON                  ((uint16_t) 0x138)
+#define PPSMC_MSG_SAMPowerOFF                 ((uint16_t) 0x139)
+#define PPSMC_MSG_SAMPowerON                  ((uint16_t) 0x13a)
+#define PPSMC_MSG_SDMAPowerOFF                ((uint16_t) 0x13b)
+#define PPSMC_MSG_SDMAPowerON                 ((uint16_t) 0x13c)
+#define PPSMC_MSG_PCIeDPM_Disable             ((uint16_t) 0x13d)
+#define PPSMC_MSG_IOMMUPowerOFF               ((uint16_t) 0x13e)
+#define PPSMC_MSG_IOMMUPowerON                ((uint16_t) 0x13f)
+#define PPSMC_MSG_NBDPM_Enable                ((uint16_t) 0x140)
+#define PPSMC_MSG_NBDPM_Disable               ((uint16_t) 0x141)
+#define PPSMC_MSG_NBDPM_ForceNominal          ((uint16_t) 0x142)
+#define PPSMC_MSG_NBDPM_ForcePerformance      ((uint16_t) 0x143)
+#define PPSMC_MSG_NBDPM_UnForce               ((uint16_t) 0x144)
+#define PPSMC_MSG_SCLKDPM_SetEnabledMask      ((uint16_t) 0x145)
+#define PPSMC_MSG_MCLKDPM_SetEnabledMask      ((uint16_t) 0x146)
+#define PPSMC_MSG_PCIeDPM_ForceLevel          ((uint16_t) 0x147)
+#define PPSMC_MSG_PCIeDPM_UnForceLevel        ((uint16_t) 0x148)
+#define PPSMC_MSG_EnableACDCGPIOInterrupt     ((uint16_t) 0x149)
+#define PPSMC_MSG_EnableVRHotGPIOInterrupt    ((uint16_t) 0x14a)
+#define PPSMC_MSG_SwitchToAC                  ((uint16_t) 0x14b)
+#define PPSMC_MSG_XDMAPowerOFF                ((uint16_t) 0x14c)
+#define PPSMC_MSG_XDMAPowerON                 ((uint16_t) 0x14d)
+
+#define PPSMC_MSG_DPM_Enable                  ((uint16_t) 0x14e)
+#define PPSMC_MSG_DPM_Disable                 ((uint16_t) 0x14f)
+#define PPSMC_MSG_MCLKDPM_Enable              ((uint16_t) 0x150)
+#define PPSMC_MSG_MCLKDPM_Disable             ((uint16_t) 0x151)
+#define PPSMC_MSG_LCLKDPM_Enable              ((uint16_t) 0x152)
+#define PPSMC_MSG_LCLKDPM_Disable             ((uint16_t) 0x153)
+#define PPSMC_MSG_UVDDPM_Enable               ((uint16_t) 0x154)
+#define PPSMC_MSG_UVDDPM_Disable              ((uint16_t) 0x155)
+#define PPSMC_MSG_SAMUDPM_Enable              ((uint16_t) 0x156)
+#define PPSMC_MSG_SAMUDPM_Disable             ((uint16_t) 0x157)
+#define PPSMC_MSG_ACPDPM_Enable               ((uint16_t) 0x158)
+#define PPSMC_MSG_ACPDPM_Disable              ((uint16_t) 0x159)
+#define PPSMC_MSG_VCEDPM_Enable               ((uint16_t) 0x15a)
+#define PPSMC_MSG_VCEDPM_Disable              ((uint16_t) 0x15b)
+#define PPSMC_MSG_LCLKDPM_SetEnabledMask      ((uint16_t) 0x15c)
+#define PPSMC_MSG_DPM_FPS_Mode                ((uint16_t) 0x15d)
+#define PPSMC_MSG_DPM_Activity_Mode           ((uint16_t) 0x15e)
+#define PPSMC_MSG_VddC_Request                ((uint16_t) 0x15f)
+#define PPSMC_MSG_MCLKDPM_GetEnabledMask      ((uint16_t) 0x160)
+#define PPSMC_MSG_LCLKDPM_GetEnabledMask      ((uint16_t) 0x161)
+#define PPSMC_MSG_SCLKDPM_GetEnabledMask      ((uint16_t) 0x162)
+#define PPSMC_MSG_UVDDPM_GetEnabledMask       ((uint16_t) 0x163)
+#define PPSMC_MSG_SAMUDPM_GetEnabledMask      ((uint16_t) 0x164)
+#define PPSMC_MSG_ACPDPM_GetEnabledMask       ((uint16_t) 0x165)
+#define PPSMC_MSG_VCEDPM_GetEnabledMask       ((uint16_t) 0x166)
+#define PPSMC_MSG_PCIeDPM_SetEnabledMask      ((uint16_t) 0x167)
+#define PPSMC_MSG_PCIeDPM_GetEnabledMask      ((uint16_t) 0x168)
+#define PPSMC_MSG_TDCLimitEnable              ((uint16_t) 0x169)
+#define PPSMC_MSG_TDCLimitDisable             ((uint16_t) 0x16a)
+#define PPSMC_MSG_DPM_AutoRotate_Mode         ((uint16_t) 0x16b)
+#define PPSMC_MSG_DISPCLK_FROM_FCH            ((uint16_t) 0x16c)
+#define PPSMC_MSG_DISPCLK_FROM_DFS            ((uint16_t) 0x16d)
+#define PPSMC_MSG_DPREFCLK_FROM_FCH           ((uint16_t) 0x16e)
+#define PPSMC_MSG_DPREFCLK_FROM_DFS           ((uint16_t) 0x16f)
+#define PPSMC_MSG_PmStatusLogStart            ((uint16_t) 0x170)
+#define PPSMC_MSG_PmStatusLogSample           ((uint16_t) 0x171)
+#define PPSMC_MSG_SCLK_AutoDPM_ON             ((uint16_t) 0x172)
+#define PPSMC_MSG_MCLK_AutoDPM_ON             ((uint16_t) 0x173)
+#define PPSMC_MSG_LCLK_AutoDPM_ON             ((uint16_t) 0x174)
+#define PPSMC_MSG_UVD_AutoDPM_ON              ((uint16_t) 0x175)
+#define PPSMC_MSG_SAMU_AutoDPM_ON             ((uint16_t) 0x176)
+#define PPSMC_MSG_ACP_AutoDPM_ON              ((uint16_t) 0x177)
+#define PPSMC_MSG_VCE_AutoDPM_ON              ((uint16_t) 0x178)
+#define PPSMC_MSG_PCIe_AutoDPM_ON             ((uint16_t) 0x179)
+#define PPSMC_MSG_MASTER_AutoDPM_ON           ((uint16_t) 0x17a)
+#define PPSMC_MSG_MASTER_AutoDPM_OFF          ((uint16_t) 0x17b)
+#define PPSMC_MSG_DYNAMICDISPPHYPOWER         ((uint16_t) 0x17c)
+#define PPSMC_MSG_CAC_COLLECTION_ON           ((uint16_t) 0x17d)
+#define PPSMC_MSG_CAC_COLLECTION_OFF          ((uint16_t) 0x17e)
+#define PPSMC_MSG_CAC_CORRELATION_ON          ((uint16_t) 0x17f)
+#define PPSMC_MSG_CAC_CORRELATION_OFF         ((uint16_t) 0x180)
+#define PPSMC_MSG_PM_STATUS_TO_DRAM_ON        ((uint16_t) 0x181)
+#define PPSMC_MSG_PM_STATUS_TO_DRAM_OFF       ((uint16_t) 0x182)
+#define PPSMC_MSG_ALLOW_LOWSCLK_INTERRUPT     ((uint16_t) 0x184)
+#define PPSMC_MSG_PkgPwrLimitEnable           ((uint16_t) 0x185)
+#define PPSMC_MSG_PkgPwrLimitDisable          ((uint16_t) 0x186)
+#define PPSMC_MSG_PkgPwrSetLimit              ((uint16_t) 0x187)
+#define PPSMC_MSG_OverDriveSetTargetTdp       ((uint16_t) 0x188)
+#define PPSMC_MSG_SCLKDPM_FreezeLevel         ((uint16_t) 0x189)
+#define PPSMC_MSG_SCLKDPM_UnfreezeLevel       ((uint16_t) 0x18A)
+#define PPSMC_MSG_MCLKDPM_FreezeLevel         ((uint16_t) 0x18B)
+#define PPSMC_MSG_MCLKDPM_UnfreezeLevel       ((uint16_t) 0x18C)
+#define PPSMC_MSG_START_DRAM_LOGGING          ((uint16_t) 0x18D)
+#define PPSMC_MSG_STOP_DRAM_LOGGING           ((uint16_t) 0x18E)
+#define PPSMC_MSG_MASTER_DeepSleep_ON         ((uint16_t) 0x18F)
+#define PPSMC_MSG_MASTER_DeepSleep_OFF        ((uint16_t) 0x190)
+#define PPSMC_MSG_Remove_DC_Clamp             ((uint16_t) 0x191)
+#define PPSMC_MSG_DisableACDCGPIOInterrupt    ((uint16_t) 0x192)
+#define PPSMC_MSG_OverrideVoltageControl_SetVddc       ((uint16_t) 0x193)
+#define PPSMC_MSG_OverrideVoltageControl_SetVddci      ((uint16_t) 0x194)
+#define PPSMC_MSG_SetVidOffset_1              ((uint16_t) 0x195)
+#define PPSMC_MSG_SetVidOffset_2              ((uint16_t) 0x207)
+#define PPSMC_MSG_GetVidOffset_1              ((uint16_t) 0x196)
+#define PPSMC_MSG_GetVidOffset_2              ((uint16_t) 0x208)
+#define PPSMC_MSG_THERMAL_OVERDRIVE_Enable    ((uint16_t) 0x197)
+#define PPSMC_MSG_THERMAL_OVERDRIVE_Disable   ((uint16_t) 0x198)
+#define PPSMC_MSG_SetTjMax                    ((uint16_t) 0x199)
+#define PPSMC_MSG_SetFanPwmMax                ((uint16_t) 0x19A)
+#define PPSMC_MSG_WaitForMclkSwitchFinish     ((uint16_t) 0x19B)
+#define PPSMC_MSG_ENABLE_THERMAL_DPM          ((uint16_t) 0x19C)
+#define PPSMC_MSG_DISABLE_THERMAL_DPM         ((uint16_t) 0x19D)
+
+#define PPSMC_MSG_API_GetSclkFrequency        ((uint16_t) 0x200)
+#define PPSMC_MSG_API_GetMclkFrequency        ((uint16_t) 0x201)
+#define PPSMC_MSG_API_GetSclkBusy             ((uint16_t) 0x202)
+#define PPSMC_MSG_API_GetMclkBusy             ((uint16_t) 0x203)
+#define PPSMC_MSG_API_GetAsicPower            ((uint16_t) 0x204)
+#define PPSMC_MSG_SetFanRpmMax                ((uint16_t) 0x205)
+#define PPSMC_MSG_SetFanSclkTarget            ((uint16_t) 0x206)
+#define PPSMC_MSG_SetFanMinPwm                ((uint16_t) 0x209)
+#define PPSMC_MSG_SetFanTemperatureTarget     ((uint16_t) 0x20A)
+
+#define PPSMC_MSG_BACO_StartMonitor           ((uint16_t) 0x240)
+#define PPSMC_MSG_BACO_Cancel                 ((uint16_t) 0x241)
+#define PPSMC_MSG_EnableVddGfx                ((uint16_t) 0x242)
+#define PPSMC_MSG_DisableVddGfx               ((uint16_t) 0x243)
+#define PPSMC_MSG_UcodeAddressLow             ((uint16_t) 0x244)
+#define PPSMC_MSG_UcodeAddressHigh            ((uint16_t) 0x245)
+#define PPSMC_MSG_UcodeLoadStatus             ((uint16_t) 0x246)
+
+#define PPSMC_MSG_DRV_DRAM_ADDR_HI            ((uint16_t) 0x250)
+#define PPSMC_MSG_DRV_DRAM_ADDR_LO            ((uint16_t) 0x251)
+#define PPSMC_MSG_SMU_DRAM_ADDR_HI            ((uint16_t) 0x252)
+#define PPSMC_MSG_SMU_DRAM_ADDR_LO            ((uint16_t) 0x253)
+#define PPSMC_MSG_LoadUcodes                  ((uint16_t) 0x254)
+#define PPSMC_MSG_PowerStateNotify            ((uint16_t) 0x255)
+#define PPSMC_MSG_COND_EXEC_DRAM_ADDR_HI      ((uint16_t) 0x256)
+#define PPSMC_MSG_COND_EXEC_DRAM_ADDR_LO      ((uint16_t) 0x257)
+#define PPSMC_MSG_VBIOS_DRAM_ADDR_HI          ((uint16_t) 0x258)
+#define PPSMC_MSG_VBIOS_DRAM_ADDR_LO          ((uint16_t) 0x259)
+#define PPSMC_MSG_LoadVBios                   ((uint16_t) 0x25A)
+#define PPSMC_MSG_GetUcodeVersion             ((uint16_t) 0x25B)
+#define DMCUSMC_MSG_PSREntry                  ((uint16_t) 0x25C)
+#define DMCUSMC_MSG_PSRExit                   ((uint16_t) 0x25D)
+#define PPSMC_MSG_EnableClockGatingFeature    ((uint16_t) 0x260)
+#define PPSMC_MSG_DisableClockGatingFeature   ((uint16_t) 0x261)
+#define PPSMC_MSG_IsDeviceRunning             ((uint16_t) 0x262)
+#define PPSMC_MSG_LoadMetaData                ((uint16_t) 0x263)
+#define PPSMC_MSG_TMON_AutoCaliberate_Enable  ((uint16_t) 0x264)
+#define PPSMC_MSG_TMON_AutoCaliberate_Disable ((uint16_t) 0x265)
+#define PPSMC_MSG_GetTelemetry1Slope          ((uint16_t) 0x266)
+#define PPSMC_MSG_GetTelemetry1Offset         ((uint16_t) 0x267)
+#define PPSMC_MSG_GetTelemetry2Slope          ((uint16_t) 0x268)
+#define PPSMC_MSG_GetTelemetry2Offset         ((uint16_t) 0x269)
+#define PPSMC_MSG_EnableAvfs                  ((uint16_t) 0x26A)
+#define PPSMC_MSG_DisableAvfs                 ((uint16_t) 0x26B)
+
+#define PPSMC_MSG_PerformBtc                  ((uint16_t) 0x26C)
+#define PPSMC_MSG_VftTableIsValid             ((uint16_t) 0x275)
+#define PPSMC_MSG_UseNewGPIOScheme            ((uint16_t) 0x277)
+#define PPSMC_MSG_GetEnabledPsm               ((uint16_t) 0x400)
+#define PPSMC_MSG_AgmStartPsm                 ((uint16_t) 0x401)
+#define PPSMC_MSG_AgmReadPsm                  ((uint16_t) 0x402)
+#define PPSMC_MSG_AgmResetPsm                 ((uint16_t) 0x403)
+#define PPSMC_MSG_ReadVftCell                 ((uint16_t) 0x404)
+
+#define PPSMC_MSG_GFX_CU_PG_ENABLE            ((uint16_t) 0x280)
+#define PPSMC_MSG_GFX_CU_PG_DISABLE           ((uint16_t) 0x281)
+#define PPSMC_MSG_GetCurrPkgPwr               ((uint16_t) 0x282)
+
+#define PPSMC_MSG_SetGpuPllDfsForSclk         ((uint16_t) 0x300)
+#define PPSMC_MSG_Didt_Block_Function		  ((uint16_t) 0x301)
+
+#define PPSMC_MSG_SetVBITimeout               ((uint16_t) 0x306)
+
+#define PPSMC_MSG_SecureSRBMWrite             ((uint16_t) 0x600)
+#define PPSMC_MSG_SecureSRBMRead              ((uint16_t) 0x601)
+#define PPSMC_MSG_SetAddress                  ((uint16_t) 0x800)
+#define PPSMC_MSG_GetData                     ((uint16_t) 0x801)
+#define PPSMC_MSG_SetData                     ((uint16_t) 0x802)
+
+typedef uint16_t PPSMC_Msg;
+
+#define PPSMC_EVENT_STATUS_THERMAL          0x00000001
+#define PPSMC_EVENT_STATUS_REGULATORHOT     0x00000002
+#define PPSMC_EVENT_STATUS_DC               0x00000004
+
+#pragma pack(pop)
+
+#endif
+
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/inc/polaris10_pwrvirus.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/inc/polaris10_pwrvirus.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/inc/polaris10_pwrvirus.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/inc/polaris10_pwrvirus.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,10088 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#ifndef _POLARIS10_PWRVIRUS_H
+#define _POLARIS10_PWRVIRUS_H
+
+#define mmSMC_IND_INDEX_11                              0x01AC
+#define mmSMC_IND_DATA_11                               0x01AD
+#define mmCP_HYP_MEC1_UCODE_ADDR	0xf81a
+#define mmCP_HYP_MEC1_UCODE_DATA	0xf81b
+#define mmCP_HYP_MEC2_UCODE_ADDR	0xf81c
+#define mmCP_HYP_MEC2_UCODE_DATA	0xf81d
+
+enum PWR_Command {
+	PwrCmdNull = 0,
+	PwrCmdWrite,
+	PwrCmdEnd,
+	PwrCmdMax
+};
+
+typedef enum PWR_Command PWR_Command;
+
+struct PWR_Command_Table {
+	PWR_Command        command;
+	uint32_t              data;
+	uint32_t reg;
+};
+
+typedef struct PWR_Command_Table PWR_Command_Table;
+
+
+#define PWR_VIRUS_TABLE_SIZE  10031
+
+static const PWR_Command_Table pwr_virus_table[PWR_VIRUS_TABLE_SIZE] = {
+	{ PwrCmdWrite, 0x00000000, mmRLC_CNTL                                 },
+	{ PwrCmdWrite, 0x00000002, mmRLC_SRM_CNTL                             },
+	{ PwrCmdWrite, 0x15000000, mmCP_ME_CNTL                               },
+	{ PwrCmdWrite, 0x50000000, mmCP_MEC_CNTL                              },
+	{ PwrCmdWrite, 0x80000004, mmCP_DFY_CNTL                              },
+	{ PwrCmdWrite, 0x0840800a, mmCP_RB0_CNTL                              },
+	{ PwrCmdWrite, 0xf30fff0f, mmTCC_CTRL                                 },
+	{ PwrCmdWrite, 0x00000002, mmTCC_EXE_DISABLE                          },
+	{ PwrCmdWrite, 0x000000ff, mmTCP_ADDR_CONFIG                          },
+	{ PwrCmdWrite, 0x540ff000, mmCP_CPC_IC_BASE_LO                        },
+	{ PwrCmdWrite, 0x000000b4, mmCP_CPC_IC_BASE_HI                        },
+	{ PwrCmdWrite, 0x00010000, mmCP_HYP_MEC1_UCODE_ADDR                   },
+	{ PwrCmdWrite, 0x00041b75, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000710e8, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000910dd, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000a1081, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000b016f, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000c0e3c, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000d10ec, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000e0188, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00101b5d, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00150a6c, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00170c5e, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x001d0c8c, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x001e0cfe, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00221408, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00370d7b, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00390dcb, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x003c142f, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x003f0b27, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00400e63, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00500f62, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00460fa7, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00490fa7, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x005811d4, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00680ad6, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00760b00, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00780b0c, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00790af7, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x007d1aba, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x007e1abe, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00591260, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x005a12fb, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00861ac7, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x008c1b01, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x008d1b34, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00a014b9, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00a1152e, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00a216fb, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00a41890, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00a31906, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00a50b14, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00621387, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x005c0b27, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00160a75, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00010000, mmCP_HYP_MEC2_UCODE_ADDR                   },
+	{ PwrCmdWrite, 0x00041b75, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000710e8, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000910dd, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000a1081, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000b016f, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000c0e3c, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000d10ec, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000e0188, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00101b5d, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00150a6c, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00170c5e, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x001d0c8c, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x001e0cfe, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00221408, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00370d7b, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00390dcb, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x003c142f, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x003f0b27, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00400e63, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00500f62, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00460fa7, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00490fa7, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x005811d4, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00680ad6, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00760b00, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00780b0c, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00790af7, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x007d1aba, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x007e1abe, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00591260, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x005a12fb, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00861ac7, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x008c1b01, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x008d1b34, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00a014b9, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00a1152e, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00a216fb, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00a41890, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00a31906, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00a50b14, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00621387, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x005c0b27, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x00160a75, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA                   },
+	{ PwrCmdWrite, 0x80000004, mmCP_DFY_CNTL                              },
+	{ PwrCmdWrite, 0x000000b4, mmCP_DFY_ADDR_HI                           },
+	{ PwrCmdWrite, 0x540fe800, mmCP_DFY_ADDR_LO                           },
+	{ PwrCmdWrite, 0x7e000200, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e020201, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e040204, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e060205, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xbf810000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x54106f00, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x000400b4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00004000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00804fac, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000004, mmCP_DFY_CNTL                              },
+	{ PwrCmdWrite, 0x000000b4, mmCP_DFY_ADDR_HI                           },
+	{ PwrCmdWrite, 0x540fef00, mmCP_DFY_ADDR_LO                           },
+	{ PwrCmdWrite, 0xc0031502, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00001e00, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000004, mmCP_DFY_CNTL                              },
+	{ PwrCmdWrite, 0x000000b4, mmCP_DFY_ADDR_HI                           },
+	{ PwrCmdWrite, 0x540ff000, mmCP_DFY_ADDR_LO                           },
+	{ PwrCmdWrite, 0xc424000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000145, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94800001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94c00001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95400001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95800001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdc810000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdcc10000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdd010000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdd410000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdd810000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4080061, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x24ccffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x3cd08000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9500fffd, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1cd0ffcf, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d018001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4140004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x050c0019, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x84c00000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000023, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000067, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000006a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000006d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000079, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000084, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000008f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000099, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800000a0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800000af, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400053, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4080007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x388c0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x08880002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04100003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94c00005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x98800003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000002d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04100005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c000043, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28cc0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00050, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c000055, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28080001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc000004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d808001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdc180000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdc140000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdc100000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdc0c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc800005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdc080000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd013278, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4113278, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x24cc0700, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4113255, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd01324f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4113254, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1d10ffdf, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd013254, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x10cc0014, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1d10c017, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d0d000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd0130b7, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x14cc0010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd9c00036, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000005d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc00c4000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc130b5, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x14d00011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9500fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdc030000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd800000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd800000d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94c01b10, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc00e0080, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc130b5, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000013b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc00e0800, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc130b5, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000013b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400053, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04100006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c000043, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28cc0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00050, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c000055, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x280c0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00052, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28180039, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000034, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400053, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04100007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c000043, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28cc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00050, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c000055, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x280c0010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00052, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28180039, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000034, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400053, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04100008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c000043, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28cc0003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00050, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c000055, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x280c0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00052, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28180039, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000034, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdc030000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000069, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28080001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc428000d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ca88004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc800079, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04280001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc00006f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000013b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000034, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04100010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c000043, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00078, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c000055, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28180080, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000034, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04100001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd013278, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4113278, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc00c4000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4113254, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1d10c017, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc130b5, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd0130b7, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000013b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c00001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96400001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96800001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96c00001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97400001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97800001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97c00001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdc810000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd4c0380, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdcc0388, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x55dc0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdcc038c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce0c0390, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x56200020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce0c0394, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce4c0398, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x56640020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce4c039c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce8c03a0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x56a80020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce8c03a4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcecc03a8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x56ec0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcecc03ac, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf0c03b0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x57300020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf0c03b4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf4c03b8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x57740020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf4c03bc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf8c03c0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x57b80020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf8c03c4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfcc03c8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x57fc0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfcc03cc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd9000033, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41c0009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25dc0010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c0fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41c000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x05dc002f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc12009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41d200a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc012009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd9000034, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25e01c00, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12200013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25e40300, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12640008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25e800c0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12a80002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25ec003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e25c00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7eae400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7de5c00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xddc10000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc02ee000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec1c200, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c005f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x24d000ff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x31100006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9500007b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c000190, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdc1c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc1c200, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4df0388, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4d7038c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d5dc01a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4e30390, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4d70394, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d62001a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4e70398, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4d7039c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d66401a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4eb03a0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4d703a4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d6a801a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4ef03a8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4d703ac, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d6ec01a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4f303b0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4d703b4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d73001a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4f703b8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4d703bc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d77401a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4fb03c0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4d703c4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d7b801a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4ff03c8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4d703cc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d7fc01a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdc080000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4d70380, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4080001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1c88001c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c0083, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94c00010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdc0e0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94c0000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c0082, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x24d00001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9900000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18cc01e3, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x3cd00004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95000008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c0085, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18cc006a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x98c00005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c0082, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18cc01e3, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x3cd00004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9900fffa, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdc180000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdc140000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdc100000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdc0c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc800004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdc080000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4080001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1c88001c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdc180000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdc140000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdc100000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdc0c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc800004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdc080000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400051, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc428000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04180018, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a80001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a40001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4293265, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x040c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1aac0027, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2aa80080, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce813265, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac00017, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd80002f1, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04080002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x08880001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8080250, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8080258, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8080230, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8080238, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8080240, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8080248, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8080268, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8080270, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8080228, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000367, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9880fff3, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04080010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x08880001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd80c0309, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd80c0319, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04cc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9880fffc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc00e0100, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc130b5, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000016e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4180032, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95800001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18d0003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x24d4001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x24d80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x155c0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x05e80180, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9900000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x202c003d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd800010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec1325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42d325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96c00001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000aa7, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000bfc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800012e9, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4200007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a200001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce000010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c000190, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc410001b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000032, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000031, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9900091a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x24d000ff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x05280196, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18d4fe04, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x29540008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800001b4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000032b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000350, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000352, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000035f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000701, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000047c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000019f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000800, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc419325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1d98001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd81325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4140004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04100002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c000043, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28cc0002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00050, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43c0044, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27fc0003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9bc00002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97c00006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc00c4000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc130b5, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c000055, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d40c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400028, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd9400036, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4193256, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41d3254, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x15540008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd40005b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd40005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd40005d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd840006d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc421325a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42d3249, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x11540015, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x19a4003c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1998003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1af0007d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x11dc000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1264001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x15dc000d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d65400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13300018, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1a38003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7dd5c00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7df1c00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd800045, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc00100, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc411326a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc415326b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc419326c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41d326d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc425326e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4293279, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce800077, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd000056, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400057, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd800058, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc00059, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4193265, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x259c8000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99c00004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce40005a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x29988000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd813265, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4113248, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2510000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd000073, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc418000d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc411326f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x17300019, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25140fff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95400007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd800003a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001b6d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4153279, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400077, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd00005f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000075, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26f00001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x15100010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d190004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd000035, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000035, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1af07fe8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf00000d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf00000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001427, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04340022, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x07740001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04300010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdf430000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd4412e01, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0434001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdf430000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdf030000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd4412e40, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc41c030, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc41c031, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43dc031, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04343000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4113246, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf413267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51100020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7dd1c01a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4353267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x45dc0160, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc810001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b4c0057, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b700213, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b740199, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f4f400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x55180020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2198003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1c00025, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd000026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd800026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9bc00001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x248dfffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc12e00, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00142b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1af4007d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x33740003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26d80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1ae8003e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9680000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4253277, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26680001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96800009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2a640002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce413277, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4253348, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce413348, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4253348, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96400001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b400003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x958000d8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000315, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4253277, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04303000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26680001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf013267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4193246, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96800041, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b342010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1714000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25540800, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b30c012, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x459801b0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d77400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2b300000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf00001c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04240010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x199c01e2, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e5e4002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x3e5c0004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x3e540002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c00006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc80c0011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8140011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x54d00020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x55580020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000282, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95400015, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc80c0011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a640002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x041c0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x45980008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x54d00020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96400004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8140011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x041c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf00001c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99c00003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8180011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000282, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8140011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x55580020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000282, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc80c0011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf00001c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8100011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8140011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x55580020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc1334e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd01334f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd413350, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd813351, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd881334d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4193273, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41d3275, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40d3271, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4113270, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4153274, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x50cc0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7cd0c01a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7cdcc011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x05900008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd00006a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc0006b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41d3272, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d594002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x54d00020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc12e23, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd012e24, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc12e25, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4193246, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x15540002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc81c001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b340057, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b280213, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b300199, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x45980198, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f2b000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x55e40020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf000024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1800025, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd40000d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd40000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40d3249, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x20cc003c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc13249, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4113274, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdd430000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc01e0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x29dc0002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000036, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc400078, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc400078, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2d540002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95400022, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x078c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x07d40000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00120d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001239, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001232, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04f80000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x057c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc414000d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41c0019, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7dd5c005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25dc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd840007c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400074, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400069, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94c018a6, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd4412e22, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd800007c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94c018a2, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c00007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c0019, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7cd4c005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x24cc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94c00008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9680fffc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800002e3, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c0057, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7cd0c002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94c00003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9680fffd, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800002e3, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000069, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd013273, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd013275, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000074, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc414005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9540188f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40d3249, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc013cfff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7cd0c009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc13249, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9680000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c0077, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x38d00001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99000006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04cc0002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdcc30000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94c01882, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd800000d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000304, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd840002f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41c0015, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c0ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400030, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41c0016, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c0ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000030, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41c0016, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99c0ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd800002f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41c0015, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99c0ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc81c001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x49980198, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x55e40020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x459801a0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf000024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1800025, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04302000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf013267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96800004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000036, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000329, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc812e00, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04302000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf013267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4193256, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42d3249, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x16ec001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000028, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd800002b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1998003e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec00031, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000036, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97800004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce00000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1a18003e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd800008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04100000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d43c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4093249, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1888003e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94800015, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400074, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c000671, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a400006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc419324c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x259c0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1598001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c0000d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9580000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99000003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400036, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04100001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x14d80011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x24dc00ff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x31e00002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x31dc0003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9580fff0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a000003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99c00002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd9c00036, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94800004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000074, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc418005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95801827, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8800036, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8c00036, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc424000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a400004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4180014, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9580ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd840002f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x14dc0011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c0fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c000190, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd800006d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41d3246, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4193245, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51dc0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400028, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc420000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x32200002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a0000ad, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04200032, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xde030000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400033, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04080000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43c0009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27fc0002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97c0fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42c0015, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96c0ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd800002e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42d3249, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1af4003e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9740004d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc428000d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4080060, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ca88005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x24880001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f4b4009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97400046, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4313274, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4100057, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d33400c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97400009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28240100, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e6a4004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce400079, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1eecffdd, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec13249, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf013273, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf013275, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800003c3, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc429326f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1aa80030, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96800006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28240001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc428000d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06a80008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e6a8004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce800035, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41d3272, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25cc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x10cc0004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x19e80042, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25dc0006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x11dc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e8e800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7de9c00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40d3271, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4293270, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x50cc0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ce8c01a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7cd30011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x11e80007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2aa80000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce80001c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd300001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4300011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b30003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x33300000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4240059, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1660001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e320009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc0328000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e72400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0430000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a000002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04300008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc02ac000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d310002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x17300002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2aa87600, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7cd0c011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc00024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd0c00025, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce800026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04280222, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce800026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96000002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4280058, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x22ec003d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec13249, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd013273, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce813275, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd800007b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8380018, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x57b00020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04343108, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc429325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x040c3000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13740008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2374007e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x32a80003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc13267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40d3267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18ec0057, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18e40213, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18cc0199, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7cecc00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ce4c00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94800003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800003e7, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04200022, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xde030000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1800025, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd4400026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04200010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xde030000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x45980104, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1800025, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd4400026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf800026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf000026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x49980104, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a80000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc81c001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x45980168, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x55e00020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1800025, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800003f2, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c000448, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x040c2000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc13267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40d3267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94c00001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40d3249, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18cc003e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400030, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42c0016, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96c0ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000030, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42c0016, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd800002f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42c0015, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400034, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4300025, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4340024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4380081, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf813279, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf41326e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf01326d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94c0000d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x254c0700, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc424001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x10cc0010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1a641fe8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28cc0726, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2a640200, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc1237b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2264003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8813260, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce41325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4240033, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4280034, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd9000036, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001427, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96400006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xde430000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce40000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94c01755, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9680000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce80000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06a80002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xde830000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce80000d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94c0174c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00142b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4393265, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2bb80040, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400032, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf813265, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4200012, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a00ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4100044, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x19180024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8100072, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x551c003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99c00003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95800010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000043d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc00c8000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd840006c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28200000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000043f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc00c4000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x282000f0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4113255, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd01324f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc130b5, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce000053, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x195c00e8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2555fff0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc0360001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x042c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x29540001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04240000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04280004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc420000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x32200002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a000009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec1c200, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc5e124dc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0aa80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ef6c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e624001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a80fff9, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc02ee000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2555fff0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec1c200, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x29540008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc81c001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x55e00020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42d3255, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4353259, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8013260, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x45980158, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1800025, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x49980158, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x45980170, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4200012, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x16200010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a00fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1800025, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc429324f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce800026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec00026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd000008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40d325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d43c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x195400e8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1154000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18dc00e8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x05e80488, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18d0006c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18f807f0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18e40077, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18ec0199, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e6e400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000048e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000494, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800004de, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000685, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000686, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800006ac, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1ccc001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc1325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4293254, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1264000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4300004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d79400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e7a400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x52a8001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x15180001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d69401a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x202c007d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec1325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95000008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95800028, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42d3267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4193246, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1aec0028, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40d325c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800004cc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42d3256, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc419324e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26e8003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1aec003e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12f4000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41d324d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40d324f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d75401a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04100002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d290004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f8f4001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f52800f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x50e00002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51980008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a800002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800004d1, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d0dc002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x6665fc00, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e5e401a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7da1c011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd140000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1c00002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2a644000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce400002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f534002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x6665fc00, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e76401a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1800002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce400002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800004d7, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42d325a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4193258, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1aec003e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41d3257, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4213259, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12f4000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d75401a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x52200002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7da1c011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd140000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1c00002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2a644000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce400002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x202c003d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf000008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec1325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42d325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96c00001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4193260, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x259c0007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x15980004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x05e804e3, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800004e7, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800004f0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000505, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc435325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd801325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x277401ef, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf41325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c000671, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9640fff4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x17e00008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc418000d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce000009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd84131db, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd800009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc430001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42d325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b301ff8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2b300400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2330003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26edf000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ef2c00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8413260, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec1325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x05a80507, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000050c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000528, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000057d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800005c2, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800005f3, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c000671, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a400012, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1bd400e8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42c004a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd40005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41c004d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec0005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99c0000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4100019, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d150005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25100001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99000008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00063b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4113277, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2511fffd, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd013277, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd801326f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000624, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04240012, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1be00fe4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce413260, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce000066, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400068, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c000671, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1bd400e8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42c004a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd40005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41c004d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec0005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99c0000d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4100019, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d150005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25100001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99000009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400067, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00063b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4113277, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2511fffd, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd013277, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd801326f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000624, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1bd400e8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42c0060, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ed6c005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26ec0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4113271, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4153270, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4193272, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41d3273, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04280022, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51100020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d51401a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4113274, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4213275, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4253276, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4313248, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1400061, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2730000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13300010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7db1800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd800060, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96c00002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x05dc0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc00062, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x042c3000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd000063, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce000064, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce400065, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42d3246, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4313245, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4353267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce813260, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc820001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b700057, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b680213, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b740199, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x46ec0188, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x56240020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd2c00025, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x042c2000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc418000d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x17e00008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce000009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42d3267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26e01000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a00fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd9c131fc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd800009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96c00001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4113277, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41c000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc420000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x11dc0002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7de1c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x11dc0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x29dc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25140001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x191807e4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x192007ec, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95400004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc1334a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9580000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x09980001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x041c0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95800005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x09980001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51dc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x69dc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9980fffd, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7de20014, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x561c0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce013344, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc13345, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95400022, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x042c3000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42d3246, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4313245, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4353267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc425334d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26640001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9640fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc419334e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41d334f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4213350, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4253351, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b680057, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b700213, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b740199, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x46ec01b0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd2c00025, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd800026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x042c2000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42d3267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96c00001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04280032, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce813260, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8800068, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2010007d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd01325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc411325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1910003e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9500fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04100040, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd00001b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc410000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9900ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04100060, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd00001b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc410000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9900ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2010003d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd01325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4113277, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25140001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x191807e4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9540000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2511fffd, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd013277, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41c000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc420000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x11dc0002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7de1c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x11dc0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc1334a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95800005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8013344, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8013345, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4180050, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41c0052, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04280042, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd813273, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc13275, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce813260, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd9000068, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400067, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x07d40000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00120d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00124f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001232, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x057c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x042c3000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42d3246, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4313245, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4353267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b680057, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b700213, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b740199, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc820001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x46ec0190, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x56240020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd2c00025, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x042c2000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4153249, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2154003d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41c0019, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1bd800e8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7dd9c005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25dc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42c004a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd80005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc420004d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec0005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x11dc0010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e1e000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd413249, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce01326f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28340001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x05980008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f598004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd800035, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1be800e8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42c004a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce80005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd801327a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd800005f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000075, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd800007f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc424004c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce41326e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec0005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28240100, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e6a4004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce400079, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc435325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x277401ef, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04240020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce41325e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd801325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8013260, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf41325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xda000068, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4113277, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41c000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc420000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x11dc0002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7de1c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x11dc0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x29dc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25140001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9540002d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc1334a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x042c3000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42d3246, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4313245, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4353267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc425334d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26640001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9640fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc419334e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41d334f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4213350, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4253351, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b680057, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b700213, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b740199, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x46ec01b0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd2c00025, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd800026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x042c2000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42d3267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96c00001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41c000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc420000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x11dc0002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7de1c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x11dc0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc1334a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc430000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04240000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b000010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1be000e8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x042c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc0360001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04280004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec1c200, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc63124dc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0aa80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ef6c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e724001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a80fff9, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc02ee000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec1c200, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4253260, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7fc14001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40d3249, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18cc003e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x98c00005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x194c1c03, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc0003b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c002d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000697, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc420004a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x194c00e8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc0005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c004c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc431326d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27301fff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce00005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7cf0c00d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x98c00003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c0007e0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c00008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc430001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b301ff8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2b300400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2330003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd801325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25100007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x31100005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9900008e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000075e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x202c007d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec1325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4293265, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4353254, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26a9feff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1374000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c000d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1774000d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41d30b8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c00008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd801325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce813265, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400100, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc00ac006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc00e0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28880700, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28cc0014, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c0006de, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x14cc0010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x30d4000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04cc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x10cc0010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28cc0014, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99400009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41530b8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4193265, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x19980028, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99400003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99800002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800006c8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd801325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x15600008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce000009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8380023, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4180081, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x11a00002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7fa38011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4100026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x05980008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d1a0002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x282c2002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x3e280008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4300027, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x042c0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd3800025, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf000024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x202400d0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ca48001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc800026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28240006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a640001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a800004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x32280000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a800002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x24d8003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd840003c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec0003a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd81a2a4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41d325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25dc0007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40d3249, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18cc003e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94c0000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc420004a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x194c00e8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc0005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c004c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc431326d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27301fff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce00005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7cf0c00d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000712, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x194c1c03, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc0003b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c002d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x05e80714, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000071c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000720, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000747, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000071d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800007c4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000732, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000745, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000744, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x98c00006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000072e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x98c00003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c0007e0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c0000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4253265, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2a64008c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce413265, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc430001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b301fe8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2b300400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2330003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8013260, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04240000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000075e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x98c0fff1, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c0007e0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c00002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000723, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41f02f1, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c00004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8013247, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd801325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000743, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8813247, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd801325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd000008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04100001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x98c0ffde, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000072e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x98c00003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c0007e0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c00012, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x15600008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc418000d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce000009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd84131db, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd800009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc430001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b301ff8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2b300400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2330003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8413260, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04240000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x041c3000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc13267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41d3267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41d3265, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25dc8000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c00007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41c004a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x195800e8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd80005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc418004c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd81326e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc0005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41d3265, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25dd7fff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc13265, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41d3246, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4193245, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42d3267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51e00020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e1a001a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x46200200, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04283247, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04300033, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1af80057, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1af40213, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x042c000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f7b400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f6f400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd2000025, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd800026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc6990000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x329c325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99c00008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x329c3269, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99c00006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x329c3267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c00005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc01defff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d9d8009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000078a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25980000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0b300001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd800026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b00fff2, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43c0012, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9bc0ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd801325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc431325a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc03e7ff0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f3f0009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf01325a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4313249, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1f30001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf013249, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc03e4000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc13254, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8013254, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd801324f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8013255, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8013247, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd801325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b300028, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00120d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001219, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001232, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9900000d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9700000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43d30b5, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1bf0003a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b000b80, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x203c003a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc430000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27300700, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13300014, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2b300001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf0130b7, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc130b5, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x46200008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd2000025, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x043c2000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc13267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43d3267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9bc00001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4080007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4193260, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x259c0003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x31dc0003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c00014, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x040c3000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc13267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40d3267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18ec0057, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18e40213, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18cc0199, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7cecc00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ce4c00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4193246, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c000448, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x040c2000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc13267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40d3267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94c00001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc800010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd801325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc418000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x31980002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x041c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9980001c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x19580066, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x15600008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x040c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc0120001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x11980003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04240004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7da18001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4200007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc1c200, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41d24db, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7cd0c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a640001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7dd9c005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25dc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99c00002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a40fff8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc418005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9580137b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc00ee000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc1c200, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce000010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd840004f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4113269, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x19080070, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x190c00e8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2510003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2518000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd813268, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x05a80809, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000080e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000080f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000898, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000946, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800009e1, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04a80811, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000815, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000834, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000085e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000085e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04341001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42d3045, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec1c091, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x31300021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9700000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd84002f1, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43130b8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27300001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4293059, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x56a8001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f2b000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b000241, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000084a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43130b6, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b000003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc02f0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec130b6, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4252087, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x5668001a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26a80005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a80fffd, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd80130b6, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000084a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04341001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc431ecaa, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27300080, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b000010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc02e0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec130b6, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd80130b6, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x31300021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9700000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd84002f1, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43130b8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27300001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4293059, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x56a8001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f2b000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b00021d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdd410000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x040c0005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd84802e9, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001a41, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43b02f1, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b800006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec80278, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x56f00020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf080280, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001608, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdc140000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8813247, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd80802e9, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000085e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x31100011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x950001fa, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc02e0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2aec0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc01c0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc0180001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc00c0007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x11a40006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7de6000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x10e40008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e26000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e2e000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce000013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4113254, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1d10ffdf, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2110003e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd013254, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd801324f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8013255, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1d10ff9e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd013254, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8013247, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd801325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd801325e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc0245301, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce413249, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd801325f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc425326c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc0121fff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x29108eff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e524009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce41326c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc425325a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc0127ff0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e524009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce41325a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc425325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc0131fff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e524009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce41325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd801326d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd801326e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8013279, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94c00003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x08cc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000866, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc00c0007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95800003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x09980001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000866, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc0100010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7dd2400c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a400004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc0180003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7dd1c002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000866, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04a8089a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000089e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800008fa, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000945, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000945, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x31300022, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43130b8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27300001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04183000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4113246, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4193245, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51100020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d91801a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x459801e0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2738000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b342010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x172c000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26ec0800, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b30c012, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ef7400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2b300000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf00001c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42c000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8300011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000036, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x45980008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42c000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8340011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9740002f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43c0004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13b80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc79d3300, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc7a13301, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8393300, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc0260001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce793301, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x964012a4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c028009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9740001c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27580001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99800004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x57740001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06a80400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800008d2, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4180006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x29640001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce40001a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x242c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06ec0400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x57740001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27580001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9980fffd, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc02620c0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce41c078, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce81c080, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01c081, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf01c082, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x57240020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce41c083, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc0260400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e6e400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce41c084, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7eae8001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f2f0011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800008d2, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4180006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdf93300, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce393301, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43c0004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04182000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000903, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x31240022, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04100001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43130b8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27300001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4af0280, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4b30278, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ec30011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x32f80000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b800011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x043c0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x67180001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0bfc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x57300001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95800006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a400003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd981325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000915, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd9c1325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9bc0fff6, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f818001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001606, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d838001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94800010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41d3259, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc421325a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x16240014, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12640014, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1a2801f0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12a80010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2620ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e2a000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7de1c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e5e400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b800002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2264003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce41325a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8013259, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00075e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4af0228, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x043c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x66d80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95800010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04300002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1330000d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13f40014, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04380040, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf80001b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04380060, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf80001b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x07fc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x56ec0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x33e80010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9680ffec, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04a80948, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000094c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000099b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800009e0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800009e0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43c0004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04183000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4113246, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4193245, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51100020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d91801a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x459801e0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2738000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b342010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x172c000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26ec0800, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b30c012, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ef7400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2b300000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf00001c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42c000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8300011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000033, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x45980008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42c000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8340011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9740002c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13b80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc79d3300, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc7a13301, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8393300, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc0260001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce793301, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x964011fe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c028009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9740001c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27580001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99800004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x57740001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06a80400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000978, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4180006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x29640001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce40001a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x242c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06ec0400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x57740001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27580001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9980fffd, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc0260010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce41c078, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf01c080, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x57240020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce41c081, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce81c082, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01c083, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc0260800, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e6e400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce41c084, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7eae8001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f2f0011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000978, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4180006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdf93300, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce393301, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04182000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4193246, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7dda801a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d41c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e838011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd84802e9, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001802, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x469c0390, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04183000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b342010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x172c000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26ec0800, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b30c012, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ef7400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2b300000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf00001c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x45dc0004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1c0001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4200011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x45dc0004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1c0001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4240011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x45dc0004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1c0001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4280011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x45dc0004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1c0001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42c0011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x45dc0004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1c0001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4300011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x45dc0004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1c0001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4340011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x45dc0004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1c0001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4380011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04182000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x043c0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c0014df, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x31280014, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce8802ef, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a800062, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x31280034, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a800060, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04a809e8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800009ec, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000a45, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000a59, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000a59, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4113246, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4193245, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51100020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d91801a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x45980400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4b30258, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4a70250, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x53300020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e72401a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b342010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x172c000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26ec0800, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b30c012, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ef7400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2b300000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf00001c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x042c0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x66740001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97400041, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04383000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf813267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4393267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b800001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4300011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b38007e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x33b40003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b400003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x4598001c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9740002f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c0011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4100011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4340011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf4002eb, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4340011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf4002ec, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4340011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf4002ed, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4340011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf4002ee, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04382000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf813267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd84802e9, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001715, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04382000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf813267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x56640001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0aec0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac0ffbc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04341001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94800005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc431ecaa, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27300080, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000a55, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43130b6, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x233c0032, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc130b6, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf0130b6, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc49302ef, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99000003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8413247, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04180001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x5198001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd813268, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4193269, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2598000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9980fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd80002f1, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8013268, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd800004f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04380001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x53b8001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7db9801a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd813268, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000a5e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94c01106, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc412e01, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc412e02, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc412e03, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc412e00, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000aa7, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94c010fd, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x50640020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ce4c01a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd0c00072, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc80c0072, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x58e801fc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12a80009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2aa80000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd0c0001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce80001c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc424000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a40ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04240010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18dc01e2, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e5e4002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x3e5c0003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x3e540002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c00006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8180011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8100011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8100011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x55140020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000aa2, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9540000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8180011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x44cc0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x55900020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd0c0001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc424000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a40ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4140011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000aa2, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x44cc0004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4180011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd0c0001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc424000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a40ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8100011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x55140020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd812e01, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd012e02, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd412e03, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc412e00, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4253249, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2264003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce413249, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4253249, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96400001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc410001a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4140028, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95000005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1e64001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce413249, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x14d00010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4180030, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41c0007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99000004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99400009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9980000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000ab1, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c000190, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc420001c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000032, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a0010ac, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000aa7, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd880003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c00002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8c0003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001082, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8800040, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c00002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8c00040, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800010de, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc010ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18d403f7, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d0cc009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41b0367, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d958004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d85800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdc1e0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc424000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18d001fc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x05280adc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000af1, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000adf, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000ae7, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c000ace, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8c00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96400002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd8d2000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99c00010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18d803f7, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc010ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d0cc009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04140000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x11940014, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x29544001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a400002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x29544003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000af4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8c00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96400002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd44d2000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc424000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8c00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96400002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd44dc000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18d0003c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95000006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c000ace, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd8d2c00, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99c00003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000b0a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd44d2c00, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28148004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x24d800ff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00019, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd4593240, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94c0105e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x50540020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2198003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x199c0034, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c00028, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42d324f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4313255, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ef3400c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x14e80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a8000af, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x041c0002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x042c01c8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c000d61, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94c01043, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x50540020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18a01fe8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x3620005c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a00000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2464003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc6290ce7, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x16ac001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96c00004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26ac003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ee6c00d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96c00005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06200001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2620000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a00fff8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce000367, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9640102e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x199c0037, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x19a00035, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c0005d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42d3256, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc431325a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2330003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x16f8001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9780000d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4253248, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc035f0ff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e764009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x19b401f8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13740008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e76400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce413248, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf01325a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc431325a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d15001a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1000072, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8100072, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x55140020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x199c0034, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b800004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1ae4003e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000b7c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4353254, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x16a80008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1aec003c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x19a4003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12a80015, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12ec001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1374000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7eae800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc02e4000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1774000d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7eae800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c00005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43d3248, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1bfc01e8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13fc0018, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7dbd800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1d98ff15, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x592c00fc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd80000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12e00016, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7da1800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x592c007e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12e00015, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7da1800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd800001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x11a0000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1264001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1620000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e26000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e32000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12e4001b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e26000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x5924007e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12640017, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e26000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x19a4003c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12640018, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e26000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce01325a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd013257, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd413258, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc429325a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94c00fdb, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96800001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c00003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9780f5ca, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400100, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00120d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001219, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001232, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001b6d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42d324e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc431324d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc435324f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4293256, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x52ec0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x07740003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04240002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x269c003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e5e4004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f67000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f674002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0b740001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x53740002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ef6c011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1ab42010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1ab8c006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x16a8000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26a80800, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2b740000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f7b400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf40001c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd2c0001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4180011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a000003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c000bec, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000b47, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42c001d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4313256, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b34060b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b300077, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13300017, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04340100, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26ec00ff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc03a8004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ef6c00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f3b000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ef2c00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec1325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c0032, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc410001d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc415325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18580037, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x251000ff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc421325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x262001ef, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce01325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99800004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d15400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd41325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1d54001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd41325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc428000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42c000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12a80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26a80004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7eae800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4340028, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x14f00010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4380030, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd280200, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd680208, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcda80210, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b00000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b400014, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b800017, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc428000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42c000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12a80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26a80004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7eae800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc6930200, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc6970208, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc69b0210, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x17300001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b000005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c000190, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000032, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000028, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd800002b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd900003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd940003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001082, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd9000040, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd9400040, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800010de, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x14fc0011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x24f800ff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x33b80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97c0fffc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b800007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c000190, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000032, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000028, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd800002b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04100000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04140000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d83c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4093249, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1888003e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94800020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400074, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c000671, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a400009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc419324c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x259c0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1598001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c00016, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95800015, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99000003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400036, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04100001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x14d80011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x24e000ff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x321c0002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x32200001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9580ffee, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99c00014, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96000004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04140001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000c30, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9480000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000074, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc418005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95800f29, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94800004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000074, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc418005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95800f23, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd9c00036, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99400002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94800004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000074, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc418005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95800f1a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8800036, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x041c0003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x042c01c8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c000d61, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4200007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c0077, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94c00001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9600f502, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a200001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x98c0f500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce000010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a000f05, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc431325a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42d3256, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1f30001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x16e4001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf01325a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc431325a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9640f4f4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc434000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x33740002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b40f4f1, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4353254, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x16a80008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1aec003c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12a80015, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12ec001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1374000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7eae800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc02e4000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1774000d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7eae800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400100, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12780001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2bb80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc00ac005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc00e0002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28cc8000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28884900, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28cc0014, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000ff3, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x17fc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9bc00004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96400ee1, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc41c40a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc41c40c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc41c40d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x24d0007f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x15580010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x255400ff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd01c411, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd81c40f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd41c40e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc41c410, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04200000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18e80033, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18ec0034, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc41c414, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc41c415, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd81c413, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd41c412, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18dc0032, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c030011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c038011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c00027, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96c00002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc431c417, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc435c416, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96800004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96c00002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc439c419, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43dc418, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41c000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x29dc0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf413261, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96c00002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf013262, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96800004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc13263, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96c00002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf813264, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18dc0030, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c00017, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x17fc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac00005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d77000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9bc00015, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9700000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000cd6, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51b80020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x53300020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f97801a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f37001a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f3b000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9bc0000d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97800002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000cd6, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a000018, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28200001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000ca7, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18dc0031, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c00003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc435c40b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9740fffd, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4280032, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40d325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800012c2, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc438001d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1bb81ff0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f8cc00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc1325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc438001d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13f4000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9bc00006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43d3256, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1bf0060b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1bfc0077, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ff3c00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000cf4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43d325a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1bfc0677, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13fc0017, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04300100, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1bb81fe8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc032800b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7fb7800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ff3c00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ffbc00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc1325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18d42011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x17fc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18d001e8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x24cc007f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7cd4c00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9bc00004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc428005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96800e6c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x50580020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d59401a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1400072, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8140072, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x596001fc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12200009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ce0c00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x505c0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x50600020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7de1c01a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc0001b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd140001d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd180001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1c00020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95000010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04300000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8240010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e5e800c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9bc00015, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a80000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b000024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28300001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x122c0004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06ec0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0aec0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000d1f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8240010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x566c0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce413261, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec13262, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4340032, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2b740008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40d325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96800005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x566c0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce413261, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec13262, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800012c2, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc438001d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1bb81fe8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f8cc00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc1325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc438001d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13f4000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9bc00006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43d3256, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1bf0060b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1bfc0077, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ff3c00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000d57, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43d325a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1bfc0677, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13fc0017, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04300100, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1bb81fe8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc0328009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7fb7800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ff3c00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ffbc00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc1325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4253246, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4113245, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04143000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd413267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x52640020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e51001a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4153267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d2d0011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x19640057, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x19580213, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x19600199, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7da6400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e26400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1000025, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce400024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04142000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd413267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4153267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99400001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18d001e8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18d40030, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18d80034, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x05280d83, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c424001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000d8a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000d95, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000db1, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000d95, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000dbc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x11540010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e010001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00187c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d75400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd4610000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9580f3d8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc439c040, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97800001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000016, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x526c0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18e80058, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e2ec01a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd2c00072, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc82c0072, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x5ae0073a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ea2800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9940000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce800024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd2c00025, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd4400026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9580f3c6, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4380012, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdc3a0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0bb80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce800024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd2c00025, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc400026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b80fffb, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9980fff5, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc02a0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2aa80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x16200002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce01c405, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd441c406, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9580f3b1, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc439c409, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97800001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc424000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a40000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x11540010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x29540002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd4610000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9580f3a5, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc439c040, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97800001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94c00da7, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x50500020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7cd0c01a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd0c00072, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8280072, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x5aac007e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12d80017, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d9d800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x56a00020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2620ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7da1800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e82400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e58c01a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x19d4003d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28182002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99400030, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00104f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc430000d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4340035, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8140023, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4180081, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13300005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc011000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4240004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x11a00002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c908009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12640004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d614011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4100026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x05980008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ca4800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d1a0002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7cb0800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x3e280008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x20880188, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x54ec0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7cb4800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4300027, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04380008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1400025, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf000024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x20240090, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ca48001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc800026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec00026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec00026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28240004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a640001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a800005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x32280000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a800002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c018001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000016, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf80003a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd901a2a4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001037, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc421326c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1624001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd841325f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8800033, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43c0009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27fc0004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97c0fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000039, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd0c00038, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43c0022, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9bc0ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8800034, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc429325f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26ac0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac0fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26ac0002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96c00003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc430001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8800033, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13f4000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b301ff0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2b300300, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2330003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9680000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43c0009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27fc0004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97c0fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400039, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd0c00038, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43c0022, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9bc0ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8800034, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8800034, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c0001a2, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc80003b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x24b00008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1330000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18ac0024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2b304000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18a800e5, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1d980008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12a80008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7da9800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4113249, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1910003e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99000002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd840003d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51100020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf01326c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7cd0c01a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc421326c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12a80014, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2220003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e2a000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce01326c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8800033, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43c0009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27fc0004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97c0fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000039, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd0c00038, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43c0022, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9bc0ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8800034, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18dc003d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c00004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x041c0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x042c01c8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c000d61, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18d40030, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18d001e8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18fc0034, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x24e8000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06a80e71, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000edd, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000e91, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000e91, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000ea1, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000eaa, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000e7c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000e7f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000e7f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000e87, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000e8f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51dc0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d9e001a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000ee6, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc420000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2a200008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce000013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4213262, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4253261, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x52200020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e26001a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000ee6, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc420000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2a200008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce000013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4213264, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4253263, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x52200020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e26001a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000ee6, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc820001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000ee6, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18e82005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51e00020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2aa80000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7da1801a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1800072, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8180072, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x59a001fc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12200009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ea2800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce80001c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8200011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000ee6, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x15980002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd81c400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc421c401, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95400041, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc425c401, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x52640020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e26001a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000ee6, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x31ac2580, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac00011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x31ac260c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac0000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x31ac0800, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac0000d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x31ac0828, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac0000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x31ac2440, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac00009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x31ac2390, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac00007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x31ac0093, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac00005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x31ac31dc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x31ac31e6, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96c00004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000ede, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x39ac7c06, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x3db07c00, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000ebc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x39acc337, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x3db0c330, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000ebc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x39acc335, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x3db0c336, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000ebc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x39ac9002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x3db09001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000ebc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x39ac9012, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x3db09011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000ebc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x39acec70, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x3db0ec6f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000ebc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc5a10000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95400005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x05980001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc5a50000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x52640020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e26001a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x05280eea, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000ef1, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000efe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000f11, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000f2e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000efe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000f1f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce190000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95400005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x05980001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x56200020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce190000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97c0f26f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc439c040, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97800001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51ec0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18e80058, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7daec01a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd2c00072, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc82c0072, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x5af8073a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7eba800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd2c00025, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce800024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95400003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x56240020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97c0f25c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4380012, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc02a0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2aa80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x15980002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd81c405, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce01c406, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95400003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x56240020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce41c406, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97c0f24e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc439c409, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97800001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc424000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a40f247, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce190000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95400004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x05980001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x56200020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce190000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97c0f240, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc439c040, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97800001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x31ac2580, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac00011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x31ac260c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac0000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x31ac0800, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac0000d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x31ac0828, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac0000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x31ac2440, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac00009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x31ac2390, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac00007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x31ac0093, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac00005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x31ac31dc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x31ac31e6, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96c00004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000ef2, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x39ac7c06, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x3db07c00, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000f40, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x39acc337, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x3db0c330, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000f40, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x39acc335, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x3db0c336, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000f40, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x39acec70, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x3db0ec6f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000f40, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x39ac9002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x3db09002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000f40, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x39ac9012, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x3db09012, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000f40, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000ef1, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c0006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x98c0ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c43c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c00001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc434000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2b740008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2b780001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8c1325e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf80001a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c034001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c038001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18e0007d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x32240003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a400006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x32240000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a400004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd01c080, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd41c081, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000f88, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51640020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e52401a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd2400072, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8280072, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce81c080, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x56ac0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26f0ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf01c081, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1af000fc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1334000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x24e02000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f63400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18e00074, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x32240003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a400006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x32240000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a400004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd81c082, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc1c083, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000f9d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51e40020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e5a401a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd2400072, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8280072, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce81c082, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x56ac0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26f0ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf01c083, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1af000fc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13380016, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18e00039, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12200019, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7fa3800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7fb7800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18e0007d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1220001d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7fa3800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18e00074, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12200014, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7fa3800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf81c078, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc1c084, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18dc003d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c00004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x041c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x042c01c8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c000d61, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18d001e8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x31140005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99400003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x31140006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95400002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00104f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x05280fb7, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28140002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000fbe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000fbe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000fc2, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000fbe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000fd1, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000ff2, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000ff2, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x24cc003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc1a2a4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18e80039, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x52a8003b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x50580020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x24cc003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d59401a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1400072, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8140072, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d69401a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41c0017, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99c0ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd140004b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc1a2a4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc414000d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04180001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x24cc003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d958004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd800035, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc1a2a4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43d3249, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1bfc003e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400074, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4100019, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d150005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25100001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9500000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97c0fffc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4180021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x159c0011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x259800ff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x31a00003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x31a40001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e25800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c0fff5, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9580fff4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000fef, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc411326f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1d100010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd01326f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000074, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04380000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc430000d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8140023, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4180081, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13300005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc011000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4240004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x33b40003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97400003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc0340008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000ffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4340035, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x11a00002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c908009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12640004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d614011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4100026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x05980008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ca4800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d1a0002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7cb0800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x282c2002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x208801a8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x3e280008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7cb4800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4300027, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x042c0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1400025, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf000024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x20240030, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ca48001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc800026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc400026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28340000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x507c0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d7d401a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1400072, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8140072, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x557c0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28342002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd4400026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a80000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x32280000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a80000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000102f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a800005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x32280000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a800002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c018001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1cccfe08, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec0003a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc1a2a4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43d3249, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1bfc003e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9bc00007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x16a80008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce800009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42c005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96c00b33, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd840003c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4200025, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7da2400f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7da28002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e1ac002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0aec0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96400002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d2ac002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x3ef40010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b40f11d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04380030, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf81325e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xde410000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdcc10000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdd010000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdd410000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdd810000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xddc10000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xde010000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c024001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8100086, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x5510003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40d3249, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18cc003e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x98c00003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99000011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001075, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9900000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c0026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4100081, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4140025, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d15800f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d15c002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d520002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a200001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95800002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7cde0002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x3e20001a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a000009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x040c0030, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc1325e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001071, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd9c00036, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94c00b01, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04240001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdc200000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdc1c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdc180000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdc140000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdc100000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdc0c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96400004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdc240000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdc0c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdc240000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc40003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8c00010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4080029, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc80003b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18a800e5, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1d980008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12a80008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7da9800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18a400e5, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12500009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x248c0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94c00006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x200c006d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7cd0c00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc1326c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc421326c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x200c0228, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7cd0c00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc1326c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc421326c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c002a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc410002b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18881fe8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18d4072c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18cc00d1, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7cd4c00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x3094000d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x38d80000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x311c0003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99400006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x30940007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1620001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9940001d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a000023, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800010c4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9580001a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99c00019, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00041, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25140001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc418002c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9940000d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x259c007f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x19a00030, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc0001b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400022, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc430000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x17300001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a000012, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400023, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800010cb, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x199c0fe8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc0001b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400023, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc430000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x17300001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800010cb, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8c00010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000022, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000023, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc430005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000aac, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc434002e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2020002c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce01326c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x17780001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27740001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x07a810d8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc421326c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000aa7, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000bfc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800012e9, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000104c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc400040, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8800010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4180032, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x200c007d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc1325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc411325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28240007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xde430000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc80003b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x24b00008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1330000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18a800e5, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1d980008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12a80008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7da9800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40d3249, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18cc003e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x98c00002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd840003d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2b304000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf01326c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc431326c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x192400fd, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x50580020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d59401a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06681110, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc400078, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18ac0024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x19180070, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x19100078, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18f40058, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x5978073a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f7b400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001117, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001118, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001122, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000112d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001130, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001133, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000117b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x24ec0f00, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x32ec0600, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96c00003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4300006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b00ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1400025, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000117b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x24ec0f00, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x32ec0600, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96c00003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4300006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b00ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1400025, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000117b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc81c001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x55e00020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001122, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc81c0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x55e00020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001122, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00116b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc02a0200, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e8e8009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x22a8003d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x22a80074, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2774001c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13740014, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7eb6800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25ecffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x55700020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x15f40010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13740002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x275c001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c00027, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c018001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f41c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x15dc0002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x39e00008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25dc0007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7dc1c01e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x05dc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96000004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x05e40008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00116e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001168, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7dc2001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06200001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x05e40008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e62000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a000004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7da58001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00116e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001165, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7dc2001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06200001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e1a0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x05cc0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e0d000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95000007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e02401e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06640001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06640008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x05d80008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00116e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001168, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7dc2401e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06640001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7da58001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00116e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x05e00008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7da2000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9600ffe6, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x17640002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00116e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4200006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a00ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00116b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc420000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2a200001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce00001a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce81c078, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec1c080, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01c081, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd41c082, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf01c083, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12640002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x22640435, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce41c084, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0528117e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x312c0003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001185, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001182, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001182, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4300012, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b00ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac0000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc03a0400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x15980008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1198001c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d81c00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc130b7, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf8130b5, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04240008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41c0049, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x19a000e8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x29a80008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7de2c00c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc421325e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26200010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc415326d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a000006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc420007d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96000004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96c00003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce40003e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800011a3, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d654001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd41326d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c020001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96000005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4100026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4240081, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4140025, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800011b6, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4253279, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc415326d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc431326c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2730003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x3b380006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97800004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x3f38000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b800004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800011b4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04300006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800011b4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0430000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04380002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7fb10004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e57000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e578002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d67c002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0be40001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d3a4002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x202c002c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc421325e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04280020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec1326c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26200010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x3e640010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96000003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96400002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce81325e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4300028, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc434002e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x17780001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27740001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x07a811cf, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b00feb8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc414005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x954009a7, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000aa7, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000bfc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800012e9, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00120d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc1c07c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc41c07d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc41c08c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc41c079, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd01c07e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18f0012f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18f40612, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18cc00c1, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7cf7400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x39600004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a000002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc0140004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x11600001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18fc003e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9740001c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400041, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc425c07f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97c00003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x166c001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800011ee, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1a6c003e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96c00006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04200002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a200001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a00ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800011e8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc428002c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96800010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26ac007f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec0001b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1ab00030, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1aac0fe8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc434000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b40ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec0001b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc434000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b40ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001205, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a200001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a00ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc425c07f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x166c001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x11600001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac0fffa, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001232, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000033, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc438000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43c0009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27fc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97c0fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd841c07f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43dc07f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1bfc0078, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ffbc00c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97c0fffd, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc03a2800, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf81c07c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01c07d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01c08c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01c079, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01c07e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04380040, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf80001b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04380060, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf80001b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04380002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0bb80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43dc07f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x17fc001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04380010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9bc0fffa, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd801c07f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43dc07f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00078, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000034, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc03ae000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf81c200, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc03a0800, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf81c07c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01c07d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01c08c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01c079, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01c07e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04380040, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf80001b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04380002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0bb80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43dc07f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x17fc001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04380010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9bc0fffa, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc03ae000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf81c200, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc03a4000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf81c07c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01c07d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01c08c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01c079, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01c07e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04380002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0bb80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43dc07f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x17fc001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04380010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9bc0fffa, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x30d00002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99000052, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9640090f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1514001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x19180038, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99400030, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x30dc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99c0000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42d324e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc431324d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc435324f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4293256, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1ab0c006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x52ec0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000127f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42d3258, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4313257, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4353259, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc429325a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1ab0c012, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x07740001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04240002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26a0003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e624004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f67800f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97800002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04340000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x53740002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ef6c011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1ab42010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x16a8000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26a80800, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2b740000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf40001c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd2c0001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4100011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1514001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99400006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9980000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c0012e1, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04100000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x964008d7, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd9800036, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42c001d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c00005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc431325a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b300677, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x11dc000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800012aa, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4313256, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b34060b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b300077, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13300017, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04340100, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26ec00ff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc03a8002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ef6c00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7edec00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f3b000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ef2c00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec1325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4140032, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc410001d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x29540008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40d325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1858003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x251000ff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99800007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d0cc00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc1325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18d0006c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18d407f0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9900000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04100002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4193256, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41d324f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2598003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d190004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d5d4001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d52000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a000003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd41324f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800012d8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d514002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd41324f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800012d8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4193259, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41d325a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d958001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7dd5c002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd813259, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc1325a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1ccc001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc1325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40d325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94c00001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4340028, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x14f00010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4380030, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b000004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b40000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b80000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x17300001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b000005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c000190, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000032, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000028, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd800002b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd980003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd9c0003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001082, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd9800040, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd9c00040, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800010de, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x33f80003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97800051, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc80003b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x24b00008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1330000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18a800e5, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1d980008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12a80008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7da9800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4353249, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b74003e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b400002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd840003d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2b304000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf01326c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc431326c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b4c00f8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x50700020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04e81324, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18ac0024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x50600020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc400078, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x30e40004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a400007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d71401a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x596401fc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12640009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b74008d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e76400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2a640000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000132c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000133b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001344, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42530b5, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1a68003a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a80fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2024003a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25980700, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x11980014, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d19000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd0130b7, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce4130b5, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce40001c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd140001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4240011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7de6800f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a80ffea, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce40001c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd140001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8240011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7de1c01a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7de6800f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a80ffe0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00104f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28182002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc430000d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4340035, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8140023, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4180081, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13300005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4240004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x11a00002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12640004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d614011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4100026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x05980008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ca4800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d1a0002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7cb0800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x3e280008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7cb4800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4300027, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x042c0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1400025, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf000024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x20240030, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ca48001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc800026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b4c00f8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc400026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28340000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x507c0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x30e40004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a400005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d7d401a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1400072, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8140072, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x557c0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28342002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd4400026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a800005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x32280000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a800002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c018001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04380028, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec0003a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf81a2a4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001037, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94c007eb, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x50500020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d0d001a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1000072, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8100072, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x591c01fc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x11dc0009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x45140210, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x595801fc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x11980009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x29dc0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc0001c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd140001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4200011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1624001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96400069, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce013249, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1a307fe8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf00000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x23304076, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41d3254, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4253256, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18cc00e8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x10cc0015, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x4514020c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd140001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4200011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce013248, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1a2001e8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12200014, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2a204001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce000013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1a64003c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1264001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x11dc0009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x15dc000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7dcdc00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e5dc00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc00100, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf00000d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf00000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001427, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04340022, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x07740001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04300010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdf430000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd4412e01, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0434001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdf430000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdf030000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd4412e40, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc41c030, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc41c031, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x248dfffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc12e00, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc812e00, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00142b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x45140248, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd140001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8200011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce013257, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x56200020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce013258, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0434000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdb000024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1400025, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x45540008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd140001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8200011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce013259, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x56200020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc0337fff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f220009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce01325a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x55300020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d01c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x042c01d0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c000d61, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06ec0004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f01c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c000d61, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x041c0002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x042c01c8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c000d61, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4380012, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000aa7, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x50500020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001427, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7cd0c01a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4200007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd0c00072, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8240072, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd240001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x19682011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x5a6c01fc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12ec0009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7eeac00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2aec0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec0001c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc430000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b00ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4180011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c438001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99800007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdf830000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfa0000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00142b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00142b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000012, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43c0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9bc0ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400012, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43c0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97c0ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4380007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x17b80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18d40038, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b800004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc414005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9540073d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18c80066, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x30880001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94800008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00187c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42c0004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd910000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d410001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x043c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04240001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06200001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x4220000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a640001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc000078, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x24e80007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x24ec0010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac00006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42c0004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc5310000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001465, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d15001a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1000072, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc82c0072, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd2c0001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18f02011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x5aec01fc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12ec0009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ef2c00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2aec0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec0001c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42c000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4300011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96800012, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12a80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0aa80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06a8146a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f1f0009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f1b400f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001478, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f1b400e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001478, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f1b400c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000147a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f1b400d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000147a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f1b400f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000147a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f1b400e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000147a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f334002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97400014, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000147b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b400012, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b800005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9bc0001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e024001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x043c0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000144a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c0032, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc438001d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43d325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1bb81ff0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7fbfc00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc1325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94800007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00187c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42c0004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd910000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b800003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c0032, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40d325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800012c2, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc438001d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13f4000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9bc00006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43d3256, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1bf0060b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1bfc0077, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ff3c00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800014a9, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43d325a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1bfc0677, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04300100, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1bb81ff0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc0328007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7fb7800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13fc0017, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ff3c00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ffbc00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc1325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc03a0002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf8130b5, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x043c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc414000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x29540008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4193246, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7dd9c01a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x45dc0390, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04183000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b380057, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b340213, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b300199, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f7b400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1c00025, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc800026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c424001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c428001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce800026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c42c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec00026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c430001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf000026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c438001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf800026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04182000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd840004f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1a0800fd, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x109c000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4193265, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7dd9c00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc13265, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2620ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce080228, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9880000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce480250, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce880258, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8080230, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8080238, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8080240, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8080248, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8080268, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8080270, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd800004f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97c0ec75, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x040c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x041c0010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26180001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x09dc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x16200001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95800002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04cc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99c0fffb, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc80230, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8080238, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8080240, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8080248, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x040c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce480250, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce880258, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x52a80020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e6a401a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x041c0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x66580001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x09dc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x56640001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95800002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04cc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99c0fffb, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc80260, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8080268, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8080270, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x040c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec80288, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf080290, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec80298, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf0802a0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x040c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x041c0010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf4802a8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27580001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x09dc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x17740001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95800002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04cc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99c0fffb, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc802b0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd80802b8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x178c000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27b8003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7cf8c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf8802c0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc802c8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf8802d0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf8802d8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd800004f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43d3265, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1bc800ea, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25b8ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4930240, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc48f0238, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04cc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x24cc000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7cd2800c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a80000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc5230309, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2620ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e3a400c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a400004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x05100001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2510000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001539, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd08034b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc48f0230, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4930240, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x98c00004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd880353, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00163f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc49b0353, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4930238, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc48f0228, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x05100001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2510000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7cd14005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25540001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99400004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x05100001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2510000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000154f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc48f0230, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd080238, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd08034b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x08cc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2598ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x3d200008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc80230, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd900309, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8100319, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04340801, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2198003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd910ce7, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4190ce6, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d918005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25980001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9580fffd, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d918004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd810ce6, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a000003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdd1054f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000156e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x090c0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdcd050e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x040c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x110c0014, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28cc4001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc41230a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc41230b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc41230c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc41230d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc480329, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc48032a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc4802e0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000055, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc48f02e0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x24d8003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x09940001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x44100001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9580002c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95400005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51100001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x69100001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000157f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x24cc003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4970290, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc49b0288, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d59401a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc49b02a0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc49f0298, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x041c0040, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04200000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7dcdc002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d924019, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d26400c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x09dc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51100001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06200001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99c0fffa, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc48f0230, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4930240, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00163f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001579, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d010021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d914019, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4930238, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x55580020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd480298, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd8802a0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x10d40010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12180016, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc51f0309, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d95800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d62000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7dd9c00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdd00309, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce113320, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc48f02e0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc49b02b0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18dc01e8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7dd9400e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc48f0230, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4930240, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c0001d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95400003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00163f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800015aa, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc48f0238, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4a302b8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12240004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e5e400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4ab02a8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04100000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce4c0319, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d9d8002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ea14005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25540001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99400004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06200001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2620000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800015bc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x09dc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04240001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e624004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06200001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d25000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2620000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99c0fff4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd0d3330, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce0802b8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd8802b0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4ab02e0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1aa807f0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc48f02d0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc49702d8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc49b02c8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc49f02c0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96800028, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d4e000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9600000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d964002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e6a000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96000003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d694001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800015e9, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7cde4002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e6a000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96000008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7de94001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800015e9, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7cd64002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e6a000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96000003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d694001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800015e9, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc48f0230, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4930240, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00163f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800015cd, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4930238, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d698002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd4802d8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x129c0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc50f0319, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x11a0000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x11140001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e1e000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1198000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd953300, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e0e000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12a8000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce953301, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce100319, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4b70280, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4b30278, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f73800a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x536c0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9780eb68, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001608, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x043c0003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001609, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x043c0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x30b40000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b400011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4b70258, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4b30250, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x53780020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7fb3801a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7faf8019, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04300020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x67b40001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0b300001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x57b80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97400002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b00fffb, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4bb0260, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7fab8001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf880260, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04300020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x66f40001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0b300001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x56ec0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97400005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4353247, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f7f4009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b40fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b00fff7, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x269c0007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x11dc0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x29dc0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26a00018, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12200003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7de1c00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26a00060, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06200020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x16200001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7de1c00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x269c0018, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26a00007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26a40060, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x11dc0006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12200006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x16640001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x29dc0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7de1c00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7de5c00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4b70228, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x05100001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04cc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2510000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc80230, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f514005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25540001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99400004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x05100001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2510000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001644, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4b30248, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd080240, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f130005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27300001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b000002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001688, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00120d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001219, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001232, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04300001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04340801, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f130004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf01051e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42d051f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ed2c005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26ec0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96c0fffd, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf01051f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000055, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc5170309, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x195c07f0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x196007f6, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04340000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c00008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x09dc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04340001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c00005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x09dc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x53740001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x6b740001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001665, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4a702a0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4ab0298, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x52640020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e6a401a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f634014, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e76401a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4300004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x56680020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8113320, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce480298, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce8802a0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc5170319, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4b702b0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x255c000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f5f4001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8113330, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf4802b0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x11340001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x195c07e8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x196007ee, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8353300, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e1e4001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8353301, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce4802d0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8100309, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8100319, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf000008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4970258, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc48f0250, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7cd4c01a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4af0280, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4b30278, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04140020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x64d80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x54cc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95800060, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4193247, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25980001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9580005c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7dc24001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41d3248, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25dc000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7dd2000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96000057, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41d3255, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc435324f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7df5c00c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99c00004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4193265, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25980040, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9580fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1bb0003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000049, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1bb000e8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x33380003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b800046, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9700000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4393260, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1bb000e4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x33300004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000040, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800016f1, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc033ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2f3000ff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f3b0009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27b800ff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b80fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8c00033, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4300009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27300008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9700fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1a7003e6, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27380003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13b80004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27300003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13300003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1a7000e8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13300001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x07b80002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1a700064, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x17b00005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x07300003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0b300003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800016df, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x17b00005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13300005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7fb30002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4392083, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7fb38005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27b80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b80ffdf, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8c00034, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27b000ff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b00ffca, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd841325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2030007b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800016f2, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd841325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04300001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f2b0014, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9940ff9c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001608, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd840004f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc414000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x29540008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43d3265, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1bc800ea, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd80802e9, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18fc0064, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9bc00042, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4193246, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7dd9801a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x45980400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x043c3000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc13267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43d3267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9bc00001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b380057, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b340213, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b300199, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f7b400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x14f4001d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4bf02e9, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9bc0001c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x192807fa, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4bf0258, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4a70250, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x53fc0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e7e401a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x042c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04300000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x667c0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x56640001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06ec0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97c0fffd, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x07300001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0aec0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7eebc00c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06ec0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97c0fff8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0b300001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x43300007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x53300002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7db30011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd3000025, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc03ec005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2bfca200, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd000026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x192807fa, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc01f007f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d1d0009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2110007d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x203c003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc13256, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c0017f5, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd013254, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18fc01e8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc13248, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00185b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8413247, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0b740001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b40ffd5, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd800004f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4bf02e9, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97c0ea24, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x14d4001d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4930260, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d52400e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc49f0258, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4a30250, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51dc0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7de1801a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96400017, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d534002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4af0270, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7dae4005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26640001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x32e0001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a400006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06ec0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96000002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x042c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec80270, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000174f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0b740001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00178a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x05100001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b40fff3, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4af0280, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4b30278, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001608, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4ab0268, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7daa4005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26640001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x32a0001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a400005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96000002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x24280000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001765, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc01f007f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d1d0009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2110007d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8013256, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c0017f2, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd013254, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4113248, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x15100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x11100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4b3034b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f13000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf013248, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4930260, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001855, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x32a4001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8413247, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd800004f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x09100001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96400002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x24280000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd080260, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce880268, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9940ffc0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ec28001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x32e0001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4253247, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26640001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9640005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4293265, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4253255, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc431324f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e72400c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26a80040, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a400002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9680fff7, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc429325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1aa4003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96400049, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1aa400e8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x32680003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a800046, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9640000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4293260, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1aa400e4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x32640004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96400040, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc425325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26640010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800017e2, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc027ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2e6400ff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc429325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e6a4009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce41325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc429325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26a800ff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a80fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8c00033, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4240009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26640008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9640fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x19e403e6, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26680003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12a80004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26640003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12640003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ea68001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x19e400e8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ea68001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12640001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ea68001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06a80002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x19e40064, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96400009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x16a40005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06640003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce412082, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a640003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800017d0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x16a40005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce412082, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12640005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ea64002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4292083, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ea68005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26a80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a80ffdf, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8c00034, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc425325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26640010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc429325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26a400ff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a40ffca, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd841325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2024007b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce41325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800017e3, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd841325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4a70280, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4ab0278, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x52640020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e6a401a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04280001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7eae8014, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e6a401a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x56680020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce480278, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce880280, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06ec0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96000002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x042c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec80270, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c438001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800017fe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4bf02e9, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9bc00006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c438001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf800026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800017fe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43b02eb, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42302ec, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf813245, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce013246, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x52200020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7fa3801a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x47b8020c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x15e00008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1220000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2a206032, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x513c001e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e3e001a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4bf02e9, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9bc00005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000180f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b3c0077, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b300199, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ff3000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1330000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2b300032, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x043c3000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc13267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43d3267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd200000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4200007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd3800002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf000002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000040, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96000002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400040, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400018, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x043c2000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc13267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000018, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8800010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7dc30001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdc1e0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04380032, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf80000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001427, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc413248, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43d3269, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27fc000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x33fc0003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97c00011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x043c001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdfc30000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd4413249, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c43c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c43c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x043c0024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0bfc0021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdfc30000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd441326a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x173c0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b300303, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f3f0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x043c0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ff3c004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc13084, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001842, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x043c0024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdfc30000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd4413249, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c43c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x23fc003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc1326d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0bb80026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdf830000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd441326e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c438001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c438001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4393265, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1fb8ffc6, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xddc30000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf813265, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a000003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc0000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001852, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc0000d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce000010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c00142b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc13252, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce013253, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001878, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc49f02e9, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99c00018, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc13252, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce013253, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x043c3000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc13267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43d3267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97c0ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41c0012, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99c0ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x043c2000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc13267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001878, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41f02ed, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42302ee, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc13252, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce013253, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04200001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e2a0004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce013084, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28340001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x313c0bcc, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9bc00010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x393c051f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9bc00004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x3d3c050e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9bc0000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97c0000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x393c0560, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9bc00004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x3d3c054f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9bc00007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97c00007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x393c1538, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9bc00005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x3d3c1537, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9bc00002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2b740800, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43d3265, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1bc800ea, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18e8007c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c42c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06a8189a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000189e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800018c5, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800018f2, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18d0007e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x50580020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x09200001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d59401a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1400072, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc8140072, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x09240002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99000011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc42130b5, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1a24002c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2020002c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc418000d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1198001c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x10cc0004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x14cc0004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7cd8c00a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc130b7, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce0130b5, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd1400025, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x5978073a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2bb80002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf800024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd800026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9600e8a8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4300012, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b00ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9640e8a5, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800018a9, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04140000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc55b0309, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x3d5c0010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x05540001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2598ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x09780001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7dad800c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99c0ffd2, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9580fff9, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4970258, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4930250, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d15001a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04140020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x442c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x65180001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x55100001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9580000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41d3248, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04300001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f2b0014, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25dc000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7df9c00c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c00004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8c13260, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd901325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9940fff1, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04140020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x66d80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x56ec0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95800005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc421325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26240007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9940fff7, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000189e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04140020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41d3254, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc023007f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x19e4003e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7de1c009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7dee000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96400008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96000007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8c13260, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd901325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc421325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x261c0007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99c0fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000189e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9940fff0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000189e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43d3265, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1bc800ea, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18e00064, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06281911, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x14f4001d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x24cc0003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001915, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x800019af, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001a2b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc48032b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc480333, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc48033b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc480343, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x98800011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4213246, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4253245, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x52200020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e26401a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x46640400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04203000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce013267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4213267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b3c0057, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b200213, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b300199, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e3e000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e32000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce000024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4970258, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4930250, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d15001a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4af0280, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4b30278, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04180000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04140020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f438001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41d3247, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25dc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c00068, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4213254, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1a1c003e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c00065, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc01f007f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e1e0009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97800062, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0bb80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x43bc0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7fcbc001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc7df032b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e1fc00c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97c0fffa, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x043c0101, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94c00002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x043c0102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1bb0003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000049, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1bb000e8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x33380003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b800046, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4393260, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1bb000e4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x33300004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000040, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001994, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc033ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2f3000ff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f3b0009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27b800ff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b80fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8c00033, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4300009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27300008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9700fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x19f003e6, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27380003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13b80004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27300003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13300003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x19f000e8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13300001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x07b80002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x19f00064, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x17b00005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x07300003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0b300003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001982, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x17b00005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13300005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7fb30002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4392083, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7fb38005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27b80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b80ffdf, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8c00034, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27b000ff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b00ffcb, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc1325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2030007b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001995, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc1325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04300001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f2b0014, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x98800009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x41bc0007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x53fc0002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e7fc011, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd3c00025, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43c0012, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9bc0ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x653c0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7dbd8001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x55100001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9940ff8f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x043c2000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcfc13267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04140000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc55b0309, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x3d5c0010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2598ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x05540001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d91800c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c00003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9580fff8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x09780001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4970258, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4930250, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d15001a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4af0280, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4b30278, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04140020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x65180001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x55100001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9580005d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4253247, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26640001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04200101, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96400058, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7dc24001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41d3248, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25dc000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7df9c00c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95c00053, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94c00002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04200102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e41c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc425325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1a70003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000049, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1a7000e8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x33240003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a400046, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9700000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4253260, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1a7000e4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x33300004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000040, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001a21, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc033ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2f3000ff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc425325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f270009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc425325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x266400ff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8c00033, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4300009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27300008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9700fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x19f003e6, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27240003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12640004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27300003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13300003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e724001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x19f000e8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e724001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13300001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e724001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06640002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x19f00064, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x16700005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x07300003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0b300003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001a0f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x16700005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13300005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e730002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4252083, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e724005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x26640001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a40ffdf, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8c00034, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc425325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x267000ff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b00ffca, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce01325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2030007b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001a22, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce01325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04300001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f2b0014, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9940ff9f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001a31, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4213246, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4253245, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x52200020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e26401a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x46640400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04203000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce013267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4213267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b180057, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b200213, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1b300199, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e1a000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e32000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce000024, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4970258, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4930250, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d15001a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4af0280, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4b30278, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04140020, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x65180001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95800060, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4193247, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x25980001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04200101, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94c00005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x30f00005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04200005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b000002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04200102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95800056, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1bb0003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000049, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1bb000e8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x33380003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b800046, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9700000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4393260, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1bb000e4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x33300004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000040, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001aa2, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc033ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2f3000ff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f3b0009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27b800ff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b80fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8c00033, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4300009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27300008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9700fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x19f003e6, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27380003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13b80004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27300003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13300003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x19f000e8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13300001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x07b80002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x19f00064, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x17b00005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x07300003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0b300003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001a90, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x17b00005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x13300005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7fb30002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4392083, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7fb38005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27b80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b80ffdf, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8c00034, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27b000ff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b00ffca, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce01325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2030007b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf00325b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001aa3, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce01325d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04300001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7f2b0014, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc49b02e9, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99800005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd2400025, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x4664001c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000026, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x55100001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9940ff9c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc49b02e9, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99800008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc430000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2b300008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf000013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04302000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcf013267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x244c00ff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc4c0200, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc44f0200, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc410000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc414000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d158010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x059cc000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccdd0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c0037, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94c0ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc000049, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c003a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94c0ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x24d00001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9500e69a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18d0003b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18d40021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99400006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd840004a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c003c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94c0ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x14cc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94c00028, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000033, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc438000b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43c0009, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x27fc0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97c0fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd841c07f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43dc07f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1bfc0078, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7ffbc00c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x97c0fffd, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x99000004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc0120840, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x282c0040, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001ae8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc0121841, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x282c001a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd01c07c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01c07d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01c08c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01c079, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01c07e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04200004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcec0001b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a200001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9a00ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc425c07f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x166c001f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04200004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9ac0fffb, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc434000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9b40ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd801c07f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc425c07f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce400078, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8000034, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9940e66b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd800004a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c0036, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x24d00001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9900fffe, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18cc0021, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc00047, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc000046, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c0039, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94c0ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c003d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x98c0ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x24d003ff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18d47fea, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x18d87ff4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd00004c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd40004e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd80004d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd41c405, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc02a0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2aa80001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd01c406, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01c406, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01c406, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c0006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x98c0ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc414000e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x29540008, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x295c0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8c1325e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcdc0001a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x11980002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x4110000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc0160800, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7d15000a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc0164010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd41c078, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01c080, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01c081, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd81c082, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc01c083, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd01c084, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c0006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x98c0ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400048, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c003b, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x94c0ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd801c40a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd901c40d, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd801c410, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd801c40e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd801c40f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc40c0040, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04140001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9940ffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04140096, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc1c400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc411c401, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9500fffa, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc424003e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04d00001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x11100002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd01c40c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc0180034, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd81c411, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd841c414, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0a540001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcd41c412, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x2468000f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc419c416, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x41980003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc41c003f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7dda0001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x12200002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x10cc0002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xccc1c40c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd901c411, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce41c412, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xce292e40, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc412e01, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc412e02, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc412e03, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc412e00, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000aa7, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdc120000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x31144000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x95400005, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xdc030000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xcc3c000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x33f80003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x9780e601, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x188cfff0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x04e40002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96400006, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x96400003, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80001b74, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xbf810000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000004, mmCP_DFY_CNTL                              },
+	{ PwrCmdWrite, 0x000000b4, mmCP_DFY_ADDR_HI                           },
+	{ PwrCmdWrite, 0x54106500, mmCP_DFY_ADDR_LO                           },
+	{ PwrCmdWrite, 0x7e000200, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e020204, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc00a0505, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xbf8c007f, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xb8900904, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xb8911a04, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xb8920304, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xb8930b44, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x921c0d0c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x921c1c13, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x921d0c12, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x811c1d1c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x811c111c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x921cff1c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000400, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x921dff10, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000100, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x81181d1c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e040218, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0701000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0701000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0701000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0701000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0701000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0701000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050102, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xbf810000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000004, mmCP_DFY_CNTL                              },
+	{ PwrCmdWrite, 0x000000b4, mmCP_DFY_ADDR_HI                           },
+	{ PwrCmdWrite, 0x54106900, mmCP_DFY_ADDR_LO                           },
+	{ PwrCmdWrite, 0x7e080200, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x7e100204, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xbefc00ff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00010000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x24200087, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x262200ff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x000001f0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x20222282, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x28182111, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xbf810000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x80000004, mmCP_DFY_CNTL                              },
+	{ PwrCmdWrite, 0x000000b4, mmCP_DFY_ADDR_HI                           },
+	{ PwrCmdWrite, 0x54116f00, mmCP_DFY_ADDR_LO                           },
+	{ PwrCmdWrite, 0xc0310800, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000040, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xb4540fe8, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000041, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0000000c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x07808000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x540fee40, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x54116f00, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00005301, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xb4540fef, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x540fee20, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x08000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc0310800, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000040, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xb454105e, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x000000c0, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x07808000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x540fee40, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x54117300, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00005301, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xb4540fef, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x540fee20, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x08000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc0310800, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000040, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xb4541065, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000500, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0000001c, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x07808000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x540fee40, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x54117700, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00005301, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xb4540fef, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x540fee20, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x08000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xc0310800, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000040, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xb4541069, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000444, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x0000008a, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x07808000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000002, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x540fee40, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000010, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000004, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x54117b00, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00005301, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0xb4540fef, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x540fee20, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x08000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_MEC_CNTL                              },
+	{ PwrCmdWrite, 0x00000000, mmCP_MEC_CNTL                              },
+	{ PwrCmdWrite, 0x00000004, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x54116f00, mmCP_MQD_BASE_ADDR                         },
+	{ PwrCmdWrite, 0x000000b4, mmCP_MQD_BASE_ADDR_HI                      },
+	{ PwrCmdWrite, 0xb4540fef, mmCP_HQD_PQ_BASE                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_BASE_HI                        },
+	{ PwrCmdWrite, 0x540fee20, mmCP_HQD_PQ_WPTR_POLL_ADDR                 },
+	{ PwrCmdWrite, 0x000000b4, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI              },
+	{ PwrCmdWrite, 0x00005301, mmCP_HQD_PERSISTENT_STATE                  },
+	{ PwrCmdWrite, 0x00010000, mmCP_HQD_VMID                              },
+	{ PwrCmdWrite, 0xc8318509, mmCP_HQD_PQ_CONTROL                        },
+	{ PwrCmdWrite, 0x00000005, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x54117300, mmCP_MQD_BASE_ADDR                         },
+	{ PwrCmdWrite, 0x000000b4, mmCP_MQD_BASE_ADDR_HI                      },
+	{ PwrCmdWrite, 0xb4540fef, mmCP_HQD_PQ_BASE                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_BASE_HI                        },
+	{ PwrCmdWrite, 0x540fee20, mmCP_HQD_PQ_WPTR_POLL_ADDR                 },
+	{ PwrCmdWrite, 0x000000b4, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI              },
+	{ PwrCmdWrite, 0x00005301, mmCP_HQD_PERSISTENT_STATE                  },
+	{ PwrCmdWrite, 0x00010000, mmCP_HQD_VMID                              },
+	{ PwrCmdWrite, 0xc8318509, mmCP_HQD_PQ_CONTROL                        },
+	{ PwrCmdWrite, 0x00000006, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x54117700, mmCP_MQD_BASE_ADDR                         },
+	{ PwrCmdWrite, 0x000000b4, mmCP_MQD_BASE_ADDR_HI                      },
+	{ PwrCmdWrite, 0xb4540fef, mmCP_HQD_PQ_BASE                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_BASE_HI                        },
+	{ PwrCmdWrite, 0x540fee20, mmCP_HQD_PQ_WPTR_POLL_ADDR                 },
+	{ PwrCmdWrite, 0x000000b4, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI              },
+	{ PwrCmdWrite, 0x00005301, mmCP_HQD_PERSISTENT_STATE                  },
+	{ PwrCmdWrite, 0x00010000, mmCP_HQD_VMID                              },
+	{ PwrCmdWrite, 0xc8318509, mmCP_HQD_PQ_CONTROL                        },
+	{ PwrCmdWrite, 0x00000007, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x54117b00, mmCP_MQD_BASE_ADDR                         },
+	{ PwrCmdWrite, 0x000000b4, mmCP_MQD_BASE_ADDR_HI                      },
+	{ PwrCmdWrite, 0xb4540fef, mmCP_HQD_PQ_BASE                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_BASE_HI                        },
+	{ PwrCmdWrite, 0x540fee20, mmCP_HQD_PQ_WPTR_POLL_ADDR                 },
+	{ PwrCmdWrite, 0x000000b4, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI              },
+	{ PwrCmdWrite, 0x00005301, mmCP_HQD_PERSISTENT_STATE                  },
+	{ PwrCmdWrite, 0x00010000, mmCP_HQD_VMID                              },
+	{ PwrCmdWrite, 0xc8318509, mmCP_HQD_PQ_CONTROL                        },
+	{ PwrCmdWrite, 0x00000004, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000104, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000204, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000304, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000404, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000504, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000604, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000704, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000005, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000105, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000205, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000305, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000405, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000505, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000605, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000705, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000006, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000106, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000206, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000306, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000406, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000506, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000606, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000706, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000007, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000107, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000207, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000307, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000407, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000507, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000607, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000707, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000008, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000108, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000208, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000308, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000408, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000508, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000608, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000708, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000009, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000109, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000209, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000309, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000409, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000509, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000609, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000709, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR                           },
+	{ PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR                           },
+	{ PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE                            },
+	{ PwrCmdWrite, 0x00000004, mmSRBM_GFX_CNTL                            },
+	{ PwrCmdWrite, 0x01010101, mmCP_PQ_WPTR_POLL_CNTL1                    },
+	{ PwrCmdWrite, 0x00000000, mmGRBM_STATUS                              },
+	{ PwrCmdWrite, 0x00000000, mmGRBM_STATUS                              },
+	{ PwrCmdWrite, 0x00000000, mmGRBM_STATUS                              },
+	{ PwrCmdEnd,   0x00000000, 0x00000000                                 },
+};
+
+
+#endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/inc/pp_acpi.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/inc/pp_acpi.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/inc/pp_acpi.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/inc/pp_acpi.h	2016-07-24 15:23:50.000000000 -0400
@@ -26,3 +26,4 @@ extern bool acpi_atcs_functions_supporte
 extern int acpi_pcie_perf_request(void *device,
 						uint8_t perf_req,
 						bool advertise);
+extern bool acpi_atcs_notify_pcie_device_ready(void *device);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/inc/smu74_discrete.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/inc/smu74_discrete.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/inc/smu74_discrete.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/inc/smu74_discrete.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,849 @@
+/*
+ * Copyright 2014 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef SMU74_DISCRETE_H
+#define SMU74_DISCRETE_H
+
+#include "smu74.h"
+
+#pragma pack(push, 1)
+
+
+#define NUM_SCLK_RANGE 8
+
+#define VCO_3_6 1
+#define VCO_2_4 3
+
+#define POSTDIV_DIV_BY_1  0
+#define POSTDIV_DIV_BY_2  1
+#define POSTDIV_DIV_BY_4  2
+#define POSTDIV_DIV_BY_8  3
+#define POSTDIV_DIV_BY_16 4
+
+struct sclkFcwRange_t {
+	uint8_t  vco_setting;
+	uint8_t  postdiv;
+	uint16_t fcw_pcc;
+
+	uint16_t fcw_trans_upper;
+	uint16_t fcw_trans_lower;
+};
+typedef struct sclkFcwRange_t sclkFcwRange_t;
+
+struct SMIO_Pattern {
+	uint16_t Voltage;
+	uint8_t  Smio;
+	uint8_t  padding;
+};
+
+typedef struct SMIO_Pattern SMIO_Pattern;
+
+struct SMIO_Table {
+	SMIO_Pattern Pattern[SMU_MAX_SMIO_LEVELS];
+};
+
+typedef struct SMIO_Table SMIO_Table;
+
+struct SMU_SclkSetting {
+	uint32_t    SclkFrequency;
+	uint16_t    Fcw_int;
+	uint16_t    Fcw_frac;
+	uint16_t    Pcc_fcw_int;
+	uint8_t     PllRange;
+	uint8_t     SSc_En;
+	uint16_t    Sclk_slew_rate;
+	uint16_t    Pcc_up_slew_rate;
+	uint16_t    Pcc_down_slew_rate;
+	uint16_t    Fcw1_int;
+	uint16_t    Fcw1_frac;
+	uint16_t    Sclk_ss_slew_rate;
+};
+typedef struct SMU_SclkSetting SMU_SclkSetting;
+
+struct SMU74_Discrete_GraphicsLevel {
+	SMU_VoltageLevel MinVoltage;
+	uint8_t     pcieDpmLevel;
+	uint8_t     DeepSleepDivId;
+	uint16_t    ActivityLevel;
+	uint32_t    CgSpllFuncCntl3;
+	uint32_t    CgSpllFuncCntl4;
+	uint32_t    CcPwrDynRm;
+	uint32_t    CcPwrDynRm1;
+	uint8_t     SclkDid;
+	uint8_t     padding;
+	uint8_t     EnabledForActivity;
+	uint8_t     EnabledForThrottle;
+	uint8_t     UpHyst;
+	uint8_t     DownHyst;
+	uint8_t     VoltageDownHyst;
+	uint8_t     PowerThrottle;
+	SMU_SclkSetting SclkSetting;
+};
+
+typedef struct SMU74_Discrete_GraphicsLevel SMU74_Discrete_GraphicsLevel;
+
+struct SMU74_Discrete_ACPILevel {
+	uint32_t    Flags;
+	SMU_VoltageLevel MinVoltage;
+	uint32_t    SclkFrequency;
+	uint8_t     SclkDid;
+	uint8_t     DisplayWatermark;
+	uint8_t     DeepSleepDivId;
+	uint8_t     padding;
+	uint32_t    CcPwrDynRm;
+	uint32_t    CcPwrDynRm1;
+
+	SMU_SclkSetting SclkSetting;
+};
+
+typedef struct SMU74_Discrete_ACPILevel SMU74_Discrete_ACPILevel;
+
+struct SMU74_Discrete_Ulv {
+	uint32_t    CcPwrDynRm;
+	uint32_t    CcPwrDynRm1;
+	uint16_t    VddcOffset;
+	uint8_t     VddcOffsetVid;
+	uint8_t     VddcPhase;
+	uint16_t    BifSclkDfs;
+	uint16_t    Reserved;
+};
+
+typedef struct SMU74_Discrete_Ulv SMU74_Discrete_Ulv;
+
+struct SMU74_Discrete_MemoryLevel {
+	SMU_VoltageLevel MinVoltage;
+	uint32_t    MinMvdd;
+
+	uint32_t    MclkFrequency;
+
+	uint8_t     StutterEnable;
+	uint8_t     EnabledForThrottle;
+	uint8_t     EnabledForActivity;
+	uint8_t     padding_0;
+
+	uint8_t     UpHyst;
+	uint8_t     DownHyst;
+	uint8_t     VoltageDownHyst;
+	uint8_t     padding_1;
+
+	uint16_t    ActivityLevel;
+	uint8_t     DisplayWatermark;
+	uint8_t     Reserved;
+};
+
+typedef struct SMU74_Discrete_MemoryLevel SMU74_Discrete_MemoryLevel;
+
+struct SMU74_Discrete_LinkLevel {
+	uint8_t     PcieGenSpeed;
+	uint8_t     PcieLaneCount;
+	uint8_t     EnabledForActivity;
+	uint8_t     SPC;
+	uint32_t    DownThreshold;
+	uint32_t    UpThreshold;
+	uint16_t    BifSclkDfs;
+	uint16_t    Reserved;
+};
+
+typedef struct SMU74_Discrete_LinkLevel SMU74_Discrete_LinkLevel;
+
+struct SMU74_Discrete_MCArbDramTimingTableEntry {
+	uint32_t McArbDramTiming;
+	uint32_t McArbDramTiming2;
+	uint8_t  McArbBurstTime;
+	uint8_t  padding[3];
+};
+
+typedef struct SMU74_Discrete_MCArbDramTimingTableEntry SMU74_Discrete_MCArbDramTimingTableEntry;
+
+struct SMU74_Discrete_MCArbDramTimingTable {
+	SMU74_Discrete_MCArbDramTimingTableEntry entries[SMU__NUM_SCLK_DPM_STATE][SMU__NUM_MCLK_DPM_LEVELS];
+};
+
+typedef struct SMU74_Discrete_MCArbDramTimingTable SMU74_Discrete_MCArbDramTimingTable;
+
+struct SMU74_Discrete_UvdLevel {
+	uint32_t VclkFrequency;
+	uint32_t DclkFrequency;
+	SMU_VoltageLevel MinVoltage;
+	uint8_t  VclkDivider;
+	uint8_t  DclkDivider;
+	uint8_t  padding[2];
+};
+
+typedef struct SMU74_Discrete_UvdLevel SMU74_Discrete_UvdLevel;
+
+struct SMU74_Discrete_ExtClkLevel {
+	uint32_t Frequency;
+	SMU_VoltageLevel MinVoltage;
+	uint8_t  Divider;
+	uint8_t  padding[3];
+};
+
+typedef struct SMU74_Discrete_ExtClkLevel SMU74_Discrete_ExtClkLevel;
+
+struct SMU74_Discrete_StateInfo {
+	uint32_t SclkFrequency;
+	uint32_t MclkFrequency;
+	uint32_t VclkFrequency;
+	uint32_t DclkFrequency;
+	uint32_t SamclkFrequency;
+	uint32_t AclkFrequency;
+	uint32_t EclkFrequency;
+	uint16_t MvddVoltage;
+	uint16_t padding16;
+	uint8_t  DisplayWatermark;
+	uint8_t  McArbIndex;
+	uint8_t  McRegIndex;
+	uint8_t  SeqIndex;
+	uint8_t  SclkDid;
+	int8_t   SclkIndex;
+	int8_t   MclkIndex;
+	uint8_t  PCIeGen;
+};
+
+typedef struct SMU74_Discrete_StateInfo SMU74_Discrete_StateInfo;
+
+struct SMU_QuadraticCoeffs {
+	int32_t m1;
+	uint32_t b;
+
+	int16_t m2;
+	uint8_t m1_shift;
+	uint8_t m2_shift;
+};
+typedef struct SMU_QuadraticCoeffs SMU_QuadraticCoeffs;
+
+struct SMU74_Discrete_DpmTable {
+
+	SMU74_PIDController                  GraphicsPIDController;
+	SMU74_PIDController                  MemoryPIDController;
+	SMU74_PIDController                  LinkPIDController;
+
+	uint32_t                            SystemFlags;
+
+	uint32_t                            VRConfig;
+	uint32_t                            SmioMask1;
+	uint32_t                            SmioMask2;
+	SMIO_Table                          SmioTable1;
+	SMIO_Table                          SmioTable2;
+
+	uint32_t                            MvddLevelCount;
+
+
+	uint8_t                             BapmVddcVidHiSidd[SMU74_MAX_LEVELS_VDDC];
+	uint8_t                             BapmVddcVidLoSidd[SMU74_MAX_LEVELS_VDDC];
+	uint8_t                             BapmVddcVidHiSidd2[SMU74_MAX_LEVELS_VDDC];
+
+	uint8_t                             GraphicsDpmLevelCount;
+	uint8_t                             MemoryDpmLevelCount;
+	uint8_t                             LinkLevelCount;
+	uint8_t                             MasterDeepSleepControl;
+
+	uint8_t                             UvdLevelCount;
+	uint8_t                             VceLevelCount;
+	uint8_t                             AcpLevelCount;
+	uint8_t                             SamuLevelCount;
+
+	uint8_t                             ThermOutGpio;
+	uint8_t                             ThermOutPolarity;
+	uint8_t                             ThermOutMode;
+	uint8_t                             BootPhases;
+
+	uint8_t                             VRHotLevel;
+	uint8_t                             LdoRefSel;
+	uint8_t                             Reserved1[2];
+	uint16_t                            FanStartTemperature;
+	uint16_t                            FanStopTemperature;
+	uint16_t                            MaxVoltage;
+	uint16_t                            Reserved2;
+	uint32_t                            Reserved[1];
+
+	SMU74_Discrete_GraphicsLevel        GraphicsLevel[SMU74_MAX_LEVELS_GRAPHICS];
+	SMU74_Discrete_MemoryLevel          MemoryACPILevel;
+	SMU74_Discrete_MemoryLevel          MemoryLevel[SMU74_MAX_LEVELS_MEMORY];
+	SMU74_Discrete_LinkLevel            LinkLevel[SMU74_MAX_LEVELS_LINK];
+	SMU74_Discrete_ACPILevel            ACPILevel;
+	SMU74_Discrete_UvdLevel             UvdLevel[SMU74_MAX_LEVELS_UVD];
+	SMU74_Discrete_ExtClkLevel          VceLevel[SMU74_MAX_LEVELS_VCE];
+	SMU74_Discrete_ExtClkLevel          AcpLevel[SMU74_MAX_LEVELS_ACP];
+	SMU74_Discrete_ExtClkLevel          SamuLevel[SMU74_MAX_LEVELS_SAMU];
+	SMU74_Discrete_Ulv                  Ulv;
+
+	uint8_t                             DisplayWatermark[SMU74_MAX_LEVELS_MEMORY][SMU74_MAX_LEVELS_GRAPHICS];
+
+	uint32_t                            SclkStepSize;
+	uint32_t                            Smio[SMU74_MAX_ENTRIES_SMIO];
+
+	uint8_t                             UvdBootLevel;
+	uint8_t                             VceBootLevel;
+	uint8_t                             AcpBootLevel;
+	uint8_t                             SamuBootLevel;
+
+	uint8_t                             GraphicsBootLevel;
+	uint8_t                             GraphicsVoltageChangeEnable;
+	uint8_t                             GraphicsThermThrottleEnable;
+	uint8_t                             GraphicsInterval;
+
+	uint8_t                             VoltageInterval;
+	uint8_t                             ThermalInterval;
+	uint16_t                            TemperatureLimitHigh;
+
+	uint16_t                            TemperatureLimitLow;
+	uint8_t                             MemoryBootLevel;
+	uint8_t                             MemoryVoltageChangeEnable;
+
+	uint16_t                            BootMVdd;
+	uint8_t                             MemoryInterval;
+	uint8_t                             MemoryThermThrottleEnable;
+
+	uint16_t                            VoltageResponseTime;
+	uint16_t                            PhaseResponseTime;
+
+	uint8_t                             PCIeBootLinkLevel;
+	uint8_t                             PCIeGenInterval;
+	uint8_t                             DTEInterval;
+	uint8_t                             DTEMode;
+
+	uint8_t                             SVI2Enable;
+	uint8_t                             VRHotGpio;
+	uint8_t                             AcDcGpio;
+	uint8_t                             ThermGpio;
+
+	uint16_t                            PPM_PkgPwrLimit;
+	uint16_t                            PPM_TemperatureLimit;
+
+	uint16_t                            DefaultTdp;
+	uint16_t                            TargetTdp;
+
+	uint16_t                            FpsHighThreshold;
+	uint16_t                            FpsLowThreshold;
+
+	uint16_t                            BAPMTI_R[SMU74_DTE_ITERATIONS][SMU74_DTE_SOURCES][SMU74_DTE_SINKS];
+	uint16_t                            BAPMTI_RC[SMU74_DTE_ITERATIONS][SMU74_DTE_SOURCES][SMU74_DTE_SINKS];
+
+	uint16_t                            TemperatureLimitEdge;
+	uint16_t                            TemperatureLimitHotspot;
+
+	uint16_t                            BootVddc;
+	uint16_t                            BootVddci;
+
+	uint16_t                            FanGainEdge;
+	uint16_t                            FanGainHotspot;
+
+	uint32_t                            LowSclkInterruptThreshold;
+	uint32_t                            VddGfxReChkWait;
+
+	uint8_t                             ClockStretcherAmount;
+	uint8_t                             Sclk_CKS_masterEn0_7;
+	uint8_t                             Sclk_CKS_masterEn8_15;
+	uint8_t                             DPMFreezeAndForced;
+
+	uint8_t                             Sclk_voltageOffset[8];
+
+	SMU_ClockStretcherDataTable         ClockStretcherDataTable;
+	SMU_CKS_LOOKUPTable                 CKS_LOOKUPTable;
+
+	uint32_t                            CurrSclkPllRange;
+	sclkFcwRange_t                      SclkFcwRangeTable[NUM_SCLK_RANGE];
+	GB_VDROOP_TABLE_t                   BTCGB_VDROOP_TABLE[BTCGB_VDROOP_TABLE_MAX_ENTRIES];
+	SMU_QuadraticCoeffs                 AVFSGB_VDROOP_TABLE[AVFSGB_VDROOP_TABLE_MAX_ENTRIES];
+};
+
+typedef struct SMU74_Discrete_DpmTable SMU74_Discrete_DpmTable;
+
+
+struct SMU74_Discrete_FanTable {
+	uint16_t FdoMode;
+	int16_t  TempMin;
+	int16_t  TempMed;
+	int16_t  TempMax;
+	int16_t  Slope1;
+	int16_t  Slope2;
+	int16_t  FdoMin;
+	int16_t  HystUp;
+	int16_t  HystDown;
+	int16_t  HystSlope;
+	int16_t  TempRespLim;
+	int16_t  TempCurr;
+	int16_t  SlopeCurr;
+	int16_t  PwmCurr;
+	uint32_t RefreshPeriod;
+	int16_t  FdoMax;
+	uint8_t  TempSrc;
+	int8_t   Padding;
+};
+
+typedef struct SMU74_Discrete_FanTable SMU74_Discrete_FanTable;
+
+#define SMU7_DISCRETE_GPIO_SCLK_DEBUG             4
+#define SMU7_DISCRETE_GPIO_SCLK_DEBUG_BIT         (0x1 << SMU7_DISCRETE_GPIO_SCLK_DEBUG)
+
+
+struct SMU7_MclkDpmScoreboard {
+	uint32_t PercentageBusy;
+
+	int32_t  PIDError;
+	int32_t  PIDIntegral;
+	int32_t  PIDOutput;
+
+	uint32_t SigmaDeltaAccum;
+	uint32_t SigmaDeltaOutput;
+	uint32_t SigmaDeltaLevel;
+
+	uint32_t UtilizationSetpoint;
+
+	uint8_t  TdpClampMode;
+	uint8_t  TdcClampMode;
+	uint8_t  ThermClampMode;
+	uint8_t  VoltageBusy;
+
+	int8_t   CurrLevel;
+	int8_t   TargLevel;
+	uint8_t  LevelChangeInProgress;
+	uint8_t  UpHyst;
+
+	uint8_t  DownHyst;
+	uint8_t  VoltageDownHyst;
+	uint8_t  DpmEnable;
+	uint8_t  DpmRunning;
+
+	uint8_t  DpmForce;
+	uint8_t  DpmForceLevel;
+	uint8_t  padding2;
+	uint8_t  McArbIndex;
+
+	uint32_t MinimumPerfMclk;
+
+	uint8_t  AcpiReq;
+	uint8_t  AcpiAck;
+	uint8_t  MclkSwitchInProgress;
+	uint8_t  MclkSwitchCritical;
+
+	uint8_t  IgnoreVBlank;
+	uint8_t  TargetMclkIndex;
+	uint16_t VbiFailureCount;
+	uint8_t  VbiWaitCounter;
+	uint8_t  EnabledLevelsChange;
+
+	uint16_t LevelResidencyCounters[SMU74_MAX_LEVELS_MEMORY];
+	uint16_t LevelSwitchCounters[SMU74_MAX_LEVELS_MEMORY];
+
+	void     (*TargetStateCalculator)(uint8_t);
+	void     (*SavedTargetStateCalculator)(uint8_t);
+
+	uint16_t AutoDpmInterval;
+	uint16_t AutoDpmRange;
+
+	uint16_t VbiTimeoutCount;
+	uint16_t MclkSwitchingTime;
+
+	uint8_t  fastSwitch;
+	uint8_t  Save_PIC_VDDGFX_EXIT;
+	uint8_t  Save_PIC_VDDGFX_ENTER;
+	uint8_t  padding;
+};
+
+typedef struct SMU7_MclkDpmScoreboard SMU7_MclkDpmScoreboard;
+
+struct SMU7_UlvScoreboard {
+	uint8_t     EnterUlv;
+	uint8_t     ExitUlv;
+	uint8_t     UlvActive;
+	uint8_t     WaitingForUlv;
+	uint8_t     UlvEnable;
+	uint8_t     UlvRunning;
+	uint8_t     UlvMasterEnable;
+	uint8_t     padding;
+	uint32_t    UlvAbortedCount;
+	uint32_t    UlvTimeStamp;
+};
+
+typedef struct SMU7_UlvScoreboard SMU7_UlvScoreboard;
+
+struct VddgfxSavedRegisters {
+	uint32_t GPU_DBG[3];
+	uint32_t MEC_BaseAddress_Hi;
+	uint32_t MEC_BaseAddress_Lo;
+	uint32_t THM_TMON0_CTRL2__RDIR_PRESENT;
+	uint32_t THM_TMON1_CTRL2__RDIR_PRESENT;
+	uint32_t CP_INT_CNTL;
+};
+
+typedef struct VddgfxSavedRegisters VddgfxSavedRegisters;
+
+struct SMU7_VddGfxScoreboard {
+	uint8_t     VddGfxEnable;
+	uint8_t     VddGfxActive;
+	uint8_t     VPUResetOccured;
+	uint8_t     padding;
+
+	uint32_t    VddGfxEnteredCount;
+	uint32_t    VddGfxAbortedCount;
+
+	uint32_t    VddGfxVid;
+
+	VddgfxSavedRegisters SavedRegisters;
+};
+
+typedef struct SMU7_VddGfxScoreboard SMU7_VddGfxScoreboard;
+
+struct SMU7_TdcLimitScoreboard {
+	uint8_t  Enable;
+	uint8_t  Running;
+	uint16_t Alpha;
+	uint32_t FilteredIddc;
+	uint32_t IddcLimit;
+	uint32_t IddcHyst;
+	SMU7_HystController_Data HystControllerData;
+};
+
+typedef struct SMU7_TdcLimitScoreboard SMU7_TdcLimitScoreboard;
+
+struct SMU7_PkgPwrLimitScoreboard {
+	uint8_t  Enable;
+	uint8_t  Running;
+	uint16_t Alpha;
+	uint32_t FilteredPkgPwr;
+	uint32_t Limit;
+	uint32_t Hyst;
+	uint32_t LimitFromDriver;
+	SMU7_HystController_Data HystControllerData;
+};
+
+typedef struct SMU7_PkgPwrLimitScoreboard SMU7_PkgPwrLimitScoreboard;
+
+struct SMU7_BapmScoreboard {
+	uint32_t source_powers[SMU74_DTE_SOURCES];
+	uint32_t source_powers_last[SMU74_DTE_SOURCES];
+	int32_t entity_temperatures[SMU74_NUM_GPU_TES];
+	int32_t initial_entity_temperatures[SMU74_NUM_GPU_TES];
+	int32_t Limit;
+	int32_t Hyst;
+	int32_t therm_influence_coeff_table[SMU74_DTE_ITERATIONS * SMU74_DTE_SOURCES * SMU74_DTE_SINKS * 2];
+	int32_t therm_node_table[SMU74_DTE_ITERATIONS * SMU74_DTE_SOURCES * SMU74_DTE_SINKS];
+	uint16_t ConfigTDPPowerScalar;
+	uint16_t FanSpeedPowerScalar;
+	uint16_t OverDrivePowerScalar;
+	uint16_t OverDriveLimitScalar;
+	uint16_t FinalPowerScalar;
+	uint8_t VariantID;
+	uint8_t spare997;
+
+	SMU7_HystController_Data HystControllerData;
+
+	int32_t temperature_gradient_slope;
+	int32_t temperature_gradient;
+	uint32_t measured_temperature;
+};
+
+
+typedef struct SMU7_BapmScoreboard SMU7_BapmScoreboard;
+
+struct SMU7_AcpiScoreboard {
+	uint32_t SavedInterruptMask[2];
+	uint8_t LastACPIRequest;
+	uint8_t CgBifResp;
+	uint8_t RequestType;
+	uint8_t Padding;
+	SMU74_Discrete_ACPILevel D0Level;
+};
+
+typedef struct SMU7_AcpiScoreboard SMU7_AcpiScoreboard;
+
+struct SMU74_Discrete_PmFuses {
+	uint8_t BapmVddCVidHiSidd[8];
+	uint8_t BapmVddCVidLoSidd[8];
+	uint8_t VddCVid[8];
+	uint8_t SviLoadLineEn;
+	uint8_t SviLoadLineVddC;
+	uint8_t SviLoadLineTrimVddC;
+	uint8_t SviLoadLineOffsetVddC;
+	uint16_t TDC_VDDC_PkgLimit;
+	uint8_t TDC_VDDC_ThrottleReleaseLimitPerc;
+	uint8_t TDC_MAWt;
+	uint8_t TdcWaterfallCtl;
+	uint8_t LPMLTemperatureMin;
+	uint8_t LPMLTemperatureMax;
+	uint8_t Reserved;
+
+	uint8_t LPMLTemperatureScaler[16];
+
+	int16_t FuzzyFan_ErrorSetDelta;
+	int16_t FuzzyFan_ErrorRateSetDelta;
+	int16_t FuzzyFan_PwmSetDelta;
+	uint16_t Reserved6;
+
+	uint8_t GnbLPML[16];
+
+	uint8_t GnbLPMLMaxVid;
+	uint8_t GnbLPMLMinVid;
+	uint8_t Reserved1[2];
+
+	uint16_t BapmVddCBaseLeakageHiSidd;
+	uint16_t BapmVddCBaseLeakageLoSidd;
+
+	uint16_t  VFT_Temp[3];
+	uint16_t  padding;
+
+	SMU_QuadraticCoeffs VFT_ATE[3];
+
+	SMU_QuadraticCoeffs AVFS_GB;
+	SMU_QuadraticCoeffs ATE_ACBTC_GB;
+
+	SMU_QuadraticCoeffs P2V;
+
+	uint32_t PsmCharzFreq;
+
+	uint16_t InversionVoltage;
+	uint16_t PsmCharzTemp;
+
+	uint32_t EnabledAvfsModules;
+};
+
+typedef struct SMU74_Discrete_PmFuses SMU74_Discrete_PmFuses;
+
+struct SMU7_Discrete_Log_Header_Table {
+	uint32_t    version;
+	uint32_t    asic_id;
+	uint16_t    flags;
+	uint16_t    entry_size;
+	uint32_t    total_size;
+	uint32_t    num_of_entries;
+	uint8_t     type;
+	uint8_t     mode;
+	uint8_t     filler_0[2];
+	uint32_t    filler_1[2];
+};
+
+typedef struct SMU7_Discrete_Log_Header_Table SMU7_Discrete_Log_Header_Table;
+
+struct SMU7_Discrete_Log_Cntl {
+	uint8_t             Enabled;
+	uint8_t             Type;
+	uint8_t             padding[2];
+	uint32_t            BufferSize;
+	uint32_t            SamplesLogged;
+	uint32_t            SampleSize;
+	uint32_t            AddrL;
+	uint32_t            AddrH;
+};
+
+typedef struct SMU7_Discrete_Log_Cntl SMU7_Discrete_Log_Cntl;
+
+#if defined SMU__DGPU_ONLY
+#define CAC_ACC_NW_NUM_OF_SIGNALS 87
+#endif
+
+
+struct SMU7_Discrete_Cac_Collection_Table {
+	uint32_t temperature;
+	uint32_t cac_acc_nw[CAC_ACC_NW_NUM_OF_SIGNALS];
+};
+
+typedef struct SMU7_Discrete_Cac_Collection_Table SMU7_Discrete_Cac_Collection_Table;
+
+struct SMU7_Discrete_Cac_Verification_Table {
+	uint32_t VddcTotalPower;
+	uint32_t VddcLeakagePower;
+	uint32_t VddcConstantPower;
+	uint32_t VddcGfxDynamicPower;
+	uint32_t VddcUvdDynamicPower;
+	uint32_t VddcVceDynamicPower;
+	uint32_t VddcAcpDynamicPower;
+	uint32_t VddcPcieDynamicPower;
+	uint32_t VddcDceDynamicPower;
+	uint32_t VddcCurrent;
+	uint32_t VddcVoltage;
+	uint32_t VddciTotalPower;
+	uint32_t VddciLeakagePower;
+	uint32_t VddciConstantPower;
+	uint32_t VddciDynamicPower;
+	uint32_t Vddr1TotalPower;
+	uint32_t Vddr1LeakagePower;
+	uint32_t Vddr1ConstantPower;
+	uint32_t Vddr1DynamicPower;
+	uint32_t spare[4];
+	uint32_t temperature;
+};
+
+typedef struct SMU7_Discrete_Cac_Verification_Table SMU7_Discrete_Cac_Verification_Table;
+
+struct SMU7_Discrete_Pm_Status_Table {
+	int32_t T_meas_max;
+	int32_t T_meas_acc;
+	int32_t T_calc_max;
+	int32_t T_calc_acc;
+	uint32_t P_scalar_acc;
+	uint32_t P_calc_max;
+	uint32_t P_calc_acc;
+
+	uint32_t I_calc_max;
+	uint32_t I_calc_acc;
+	uint32_t I_calc_acc_vddci;
+	uint32_t V_calc_noload_acc;
+	uint32_t V_calc_load_acc;
+	uint32_t V_calc_noload_acc_vddci;
+	uint32_t P_meas_acc;
+	uint32_t V_meas_noload_acc;
+	uint32_t V_meas_load_acc;
+	uint32_t I_meas_acc;
+	uint32_t P_meas_acc_vddci;
+	uint32_t V_meas_noload_acc_vddci;
+	uint32_t V_meas_load_acc_vddci;
+	uint32_t I_meas_acc_vddci;
+
+	uint16_t Sclk_dpm_residency[8];
+	uint16_t Uvd_dpm_residency[8];
+	uint16_t Vce_dpm_residency[8];
+	uint16_t Mclk_dpm_residency[4];
+
+	uint32_t P_vddci_acc;
+	uint32_t P_vddr1_acc;
+	uint32_t P_nte1_acc;
+	uint32_t PkgPwr_max;
+	uint32_t PkgPwr_acc;
+	uint32_t MclkSwitchingTime_max;
+	uint32_t MclkSwitchingTime_acc;
+	uint32_t FanPwm_acc;
+	uint32_t FanRpm_acc;
+
+	uint32_t AccCnt;
+};
+
+typedef struct SMU7_Discrete_Pm_Status_Table SMU7_Discrete_Pm_Status_Table;
+
+#define SMU7_MAX_GFX_CU_COUNT 16
+
+struct SMU7_GfxCuPgScoreboard {
+	uint8_t Enabled;
+	uint8_t WaterfallUp;
+	uint8_t WaterfallDown;
+	uint8_t WaterfallLimit;
+	uint8_t CurrMaxCu;
+	uint8_t TargMaxCu;
+	uint8_t ClampMode;
+	uint8_t Active;
+	uint8_t MaxSupportedCu;
+	uint8_t MinSupportedCu;
+	uint8_t PendingGfxCuHostInterrupt;
+	uint8_t LastFilteredMaxCuInteger;
+	uint16_t FilteredMaxCu;
+	uint16_t FilteredMaxCuAlpha;
+	uint16_t FilterResetCount;
+	uint16_t FilterResetCountLimit;
+	uint8_t ForceCu;
+	uint8_t ForceCuCount;
+	uint8_t spare[2];
+};
+
+typedef struct SMU7_GfxCuPgScoreboard SMU7_GfxCuPgScoreboard;
+
+#define SMU7_SCLK_CAC 0x561
+#define SMU7_MCLK_CAC 0xF9
+#define SMU7_VCLK_CAC 0x2DE
+#define SMU7_DCLK_CAC 0x2DE
+#define SMU7_ECLK_CAC 0x25E
+#define SMU7_ACLK_CAC 0x25E
+#define SMU7_SAMCLK_CAC 0x25E
+#define SMU7_DISPCLK_CAC 0x100
+#define SMU7_CAC_CONSTANT 0x2EE3430
+#define SMU7_CAC_CONSTANT_SHIFT 18
+
+#define SMU7_VDDCI_MCLK_CONST        1765
+#define SMU7_VDDCI_MCLK_CONST_SHIFT  16
+#define SMU7_VDDCI_VDDCI_CONST       50958
+#define SMU7_VDDCI_VDDCI_CONST_SHIFT 14
+#define SMU7_VDDCI_CONST             11781
+#define SMU7_VDDCI_STROBE_PWR        1331
+
+#define SMU7_VDDR1_CONST            693
+#define SMU7_VDDR1_CAC_WEIGHT       20
+#define SMU7_VDDR1_CAC_WEIGHT_SHIFT 19
+#define SMU7_VDDR1_STROBE_PWR       512
+
+#define SMU7_AREA_COEFF_UVD 0xA78
+#define SMU7_AREA_COEFF_VCE 0x190A
+#define SMU7_AREA_COEFF_ACP 0x22D1
+#define SMU7_AREA_COEFF_SAMU 0x534
+
+#define SMU7_THERM_OUT_MODE_DISABLE       0x0
+#define SMU7_THERM_OUT_MODE_THERM_ONLY    0x1
+#define SMU7_THERM_OUT_MODE_THERM_VRHOT   0x2
+
+// DIDT Defines
+#define SQ_Enable_MASK 0x1
+#define SQ_IR_MASK 0x2
+#define SQ_PCC_MASK 0x4
+#define SQ_EDC_MASK 0x8
+
+#define TCP_Enable_MASK 0x100
+#define TCP_IR_MASK 0x200
+#define TCP_PCC_MASK 0x400
+#define TCP_EDC_MASK 0x800
+
+#define TD_Enable_MASK 0x10000
+#define TD_IR_MASK 0x20000
+#define TD_PCC_MASK 0x40000
+#define TD_EDC_MASK 0x80000
+
+#define DB_Enable_MASK 0x1000000
+#define DB_IR_MASK 0x2000000
+#define DB_PCC_MASK 0x4000000 
+#define DB_EDC_MASK 0x8000000
+
+#define SQ_Enable_SHIFT 0
+#define SQ_IR_SHIFT 1
+#define SQ_PCC_SHIFT 2
+#define SQ_EDC_SHIFT 3
+
+#define TCP_Enable_SHIFT 8
+#define TCP_IR_SHIFT 9
+#define TCP_PCC_SHIFT 10
+#define TCP_EDC_SHIFT 11
+
+#define TD_Enable_SHIFT 16
+#define TD_IR_SHIFT 17
+#define TD_PCC_SHIFT 18
+#define TD_EDC_SHIFT 19
+
+#define DB_Enable_SHIFT 24
+#define DB_IR_SHIFT 25
+#define DB_PCC_SHIFT 26 
+#define DB_EDC_SHIFT 27
+
+#define BTCGB0_Vdroop_Enable_MASK  0x1
+#define BTCGB1_Vdroop_Enable_MASK  0x2
+#define AVFSGB0_Vdroop_Enable_MASK 0x4
+#define AVFSGB1_Vdroop_Enable_MASK 0x8
+
+#define BTCGB0_Vdroop_Enable_SHIFT  0
+#define BTCGB1_Vdroop_Enable_SHIFT  1
+#define AVFSGB0_Vdroop_Enable_SHIFT 2
+#define AVFSGB1_Vdroop_Enable_SHIFT 3
+
+
+#pragma pack(pop)
+
+
+#endif
+
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/inc/smu74.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/inc/smu74.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/inc/smu74.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/inc/smu74.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,833 @@
+/*
+ * Copyright 2014 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+
+#ifndef SMU74_H
+#define SMU74_H
+
+#pragma pack(push, 1)
+
+#define SMU__DGPU_ONLY
+
+#define SMU__NUM_SCLK_DPM_STATE  8
+#define SMU__NUM_MCLK_DPM_LEVELS 4
+#define SMU__NUM_LCLK_DPM_LEVELS 8
+#define SMU__NUM_PCIE_DPM_LEVELS 8
+
+#define EXP_M1  35
+#define EXP_M2  92821
+#define EXP_B   66629747
+
+#define EXP_M1_1  365
+#define EXP_M2_1  658700
+#define EXP_B_1   305506134
+
+#define EXP_M1_2  189
+#define EXP_M2_2  379692
+#define EXP_B_2   194609469
+
+#define EXP_M1_3  99
+#define EXP_M2_3  217915
+#define EXP_B_3   122255994
+
+#define EXP_M1_4  51
+#define EXP_M2_4  122643
+#define EXP_B_4   74893384
+
+#define EXP_M1_5  423
+#define EXP_M2_5  1103326
+#define EXP_B_5   728122621
+
+enum SID_OPTION {
+	SID_OPTION_HI,
+	SID_OPTION_LO,
+	SID_OPTION_COUNT
+};
+
+enum Poly3rdOrderCoeff {
+	LEAKAGE_TEMPERATURE_SCALAR,
+	LEAKAGE_VOLTAGE_SCALAR,
+	DYNAMIC_VOLTAGE_SCALAR,
+	POLY_3RD_ORDER_COUNT
+};
+
+struct SMU7_Poly3rdOrder_Data {
+	int32_t a;
+	int32_t b;
+	int32_t c;
+	int32_t d;
+	uint8_t a_shift;
+	uint8_t b_shift;
+	uint8_t c_shift;
+	uint8_t x_shift;
+};
+
+typedef struct SMU7_Poly3rdOrder_Data SMU7_Poly3rdOrder_Data;
+
+struct Power_Calculator_Data {
+	uint16_t NoLoadVoltage;
+	uint16_t LoadVoltage;
+	uint16_t Resistance;
+	uint16_t Temperature;
+	uint16_t BaseLeakage;
+	uint16_t LkgTempScalar;
+	uint16_t LkgVoltScalar;
+	uint16_t LkgAreaScalar;
+	uint16_t LkgPower;
+	uint16_t DynVoltScalar;
+	uint32_t Cac;
+	uint32_t DynPower;
+	uint32_t TotalCurrent;
+	uint32_t TotalPower;
+};
+
+typedef struct Power_Calculator_Data PowerCalculatorData_t;
+
+struct Gc_Cac_Weight_Data {
+	uint8_t index;
+	uint32_t value;
+};
+
+typedef struct Gc_Cac_Weight_Data GcCacWeight_Data;
+
+
+typedef struct {
+	uint32_t high;
+	uint32_t low;
+} data_64_t;
+
+typedef struct {
+	data_64_t high;
+	data_64_t low;
+} data_128_t;
+
+#define SMU7_CONTEXT_ID_SMC        1
+#define SMU7_CONTEXT_ID_VBIOS      2
+
+#define SMU74_MAX_LEVELS_VDDC            16
+#define SMU74_MAX_LEVELS_VDDGFX          16
+#define SMU74_MAX_LEVELS_VDDCI           8
+#define SMU74_MAX_LEVELS_MVDD            4
+
+#define SMU_MAX_SMIO_LEVELS              4
+
+#define SMU74_MAX_LEVELS_GRAPHICS        SMU__NUM_SCLK_DPM_STATE   /* SCLK + SQ DPM + ULV */
+#define SMU74_MAX_LEVELS_MEMORY          SMU__NUM_MCLK_DPM_LEVELS   /* MCLK Levels DPM */
+#define SMU74_MAX_LEVELS_GIO             SMU__NUM_LCLK_DPM_LEVELS  /* LCLK Levels */
+#define SMU74_MAX_LEVELS_LINK            SMU__NUM_PCIE_DPM_LEVELS  /* PCIe speed and number of lanes */
+#define SMU74_MAX_LEVELS_UVD             8   /* VCLK/DCLK levels for UVD */
+#define SMU74_MAX_LEVELS_VCE             8   /* ECLK levels for VCE */
+#define SMU74_MAX_LEVELS_ACP             8   /* ACLK levels for ACP */
+#define SMU74_MAX_LEVELS_SAMU            8   /* SAMCLK levels for SAMU */
+#define SMU74_MAX_ENTRIES_SMIO           32  /* Number of entries in SMIO table */
+
+#define DPM_NO_LIMIT 0
+#define DPM_NO_UP 1
+#define DPM_GO_DOWN 2
+#define DPM_GO_UP 3
+
+#define SMU7_FIRST_DPM_GRAPHICS_LEVEL    0
+#define SMU7_FIRST_DPM_MEMORY_LEVEL      0
+
+#define GPIO_CLAMP_MODE_VRHOT      1
+#define GPIO_CLAMP_MODE_THERM      2
+#define GPIO_CLAMP_MODE_DC         4
+
+#define SCRATCH_B_TARG_PCIE_INDEX_SHIFT 0
+#define SCRATCH_B_TARG_PCIE_INDEX_MASK  (0x7<<SCRATCH_B_TARG_PCIE_INDEX_SHIFT)
+#define SCRATCH_B_CURR_PCIE_INDEX_SHIFT 3
+#define SCRATCH_B_CURR_PCIE_INDEX_MASK  (0x7<<SCRATCH_B_CURR_PCIE_INDEX_SHIFT)
+#define SCRATCH_B_TARG_UVD_INDEX_SHIFT  6
+#define SCRATCH_B_TARG_UVD_INDEX_MASK   (0x7<<SCRATCH_B_TARG_UVD_INDEX_SHIFT)
+#define SCRATCH_B_CURR_UVD_INDEX_SHIFT  9
+#define SCRATCH_B_CURR_UVD_INDEX_MASK   (0x7<<SCRATCH_B_CURR_UVD_INDEX_SHIFT)
+#define SCRATCH_B_TARG_VCE_INDEX_SHIFT  12
+#define SCRATCH_B_TARG_VCE_INDEX_MASK   (0x7<<SCRATCH_B_TARG_VCE_INDEX_SHIFT)
+#define SCRATCH_B_CURR_VCE_INDEX_SHIFT  15
+#define SCRATCH_B_CURR_VCE_INDEX_MASK   (0x7<<SCRATCH_B_CURR_VCE_INDEX_SHIFT)
+#define SCRATCH_B_TARG_ACP_INDEX_SHIFT  18
+#define SCRATCH_B_TARG_ACP_INDEX_MASK   (0x7<<SCRATCH_B_TARG_ACP_INDEX_SHIFT)
+#define SCRATCH_B_CURR_ACP_INDEX_SHIFT  21
+#define SCRATCH_B_CURR_ACP_INDEX_MASK   (0x7<<SCRATCH_B_CURR_ACP_INDEX_SHIFT)
+#define SCRATCH_B_TARG_SAMU_INDEX_SHIFT 24
+#define SCRATCH_B_TARG_SAMU_INDEX_MASK  (0x7<<SCRATCH_B_TARG_SAMU_INDEX_SHIFT)
+#define SCRATCH_B_CURR_SAMU_INDEX_SHIFT 27
+#define SCRATCH_B_CURR_SAMU_INDEX_MASK  (0x7<<SCRATCH_B_CURR_SAMU_INDEX_SHIFT)
+
+/* Virtualization Defines */
+#define CG_XDMA_MASK  0x1
+#define CG_XDMA_SHIFT 0
+#define CG_UVD_MASK   0x2
+#define CG_UVD_SHIFT  1
+#define CG_VCE_MASK   0x4
+#define CG_VCE_SHIFT  2
+#define CG_SAMU_MASK  0x8
+#define CG_SAMU_SHIFT 3
+#define CG_GFX_MASK   0x10
+#define CG_GFX_SHIFT  4
+#define CG_SDMA_MASK  0x20
+#define CG_SDMA_SHIFT 5
+#define CG_HDP_MASK   0x40
+#define CG_HDP_SHIFT  6
+#define CG_MC_MASK    0x80
+#define CG_MC_SHIFT   7
+#define CG_DRM_MASK   0x100
+#define CG_DRM_SHIFT  8
+#define CG_ROM_MASK   0x200
+#define CG_ROM_SHIFT  9
+#define CG_BIF_MASK   0x400
+#define CG_BIF_SHIFT  10
+
+
+#define SMU74_DTE_ITERATIONS 5
+#define SMU74_DTE_SOURCES 3
+#define SMU74_DTE_SINKS 1
+#define SMU74_NUM_CPU_TES 0
+#define SMU74_NUM_GPU_TES 1
+#define SMU74_NUM_NON_TES 2
+#define SMU74_DTE_FAN_SCALAR_MIN 0x100
+#define SMU74_DTE_FAN_SCALAR_MAX 0x166
+#define SMU74_DTE_FAN_TEMP_MAX 93
+#define SMU74_DTE_FAN_TEMP_MIN 83
+
+
+#if defined SMU__FUSION_ONLY
+#define SMU7_DTE_ITERATIONS 5
+#define SMU7_DTE_SOURCES 5
+#define SMU7_DTE_SINKS 3
+#define SMU7_NUM_CPU_TES 2
+#define SMU7_NUM_GPU_TES 1
+#define SMU7_NUM_NON_TES 2
+#endif
+
+struct SMU7_HystController_Data {
+	uint8_t waterfall_up;
+	uint8_t waterfall_down;
+	uint8_t waterfall_limit;
+	uint8_t spare;
+	uint16_t release_cnt;
+	uint16_t release_limit;
+};
+
+typedef struct SMU7_HystController_Data SMU7_HystController_Data;
+
+struct SMU74_PIDController {
+	uint32_t Ki;
+	int32_t LFWindupUpperLim;
+	int32_t LFWindupLowerLim;
+	uint32_t StatePrecision;
+	uint32_t LfPrecision;
+	uint32_t LfOffset;
+	uint32_t MaxState;
+	uint32_t MaxLfFraction;
+	uint32_t StateShift;
+};
+
+typedef struct SMU74_PIDController SMU74_PIDController;
+
+struct SMU7_LocalDpmScoreboard {
+	uint32_t PercentageBusy;
+
+	int32_t  PIDError;
+	int32_t  PIDIntegral;
+	int32_t  PIDOutput;
+
+	uint32_t SigmaDeltaAccum;
+	uint32_t SigmaDeltaOutput;
+	uint32_t SigmaDeltaLevel;
+
+	uint32_t UtilizationSetpoint;
+
+	uint8_t  TdpClampMode;
+	uint8_t  TdcClampMode;
+	uint8_t  ThermClampMode;
+	uint8_t  VoltageBusy;
+
+	int8_t   CurrLevel;
+	int8_t   TargLevel;
+	uint8_t  LevelChangeInProgress;
+	uint8_t  UpHyst;
+
+	uint8_t  DownHyst;
+	uint8_t  VoltageDownHyst;
+	uint8_t  DpmEnable;
+	uint8_t  DpmRunning;
+
+	uint8_t  DpmForce;
+	uint8_t  DpmForceLevel;
+	uint8_t  DisplayWatermark;
+	uint8_t  McArbIndex;
+
+	uint32_t MinimumPerfSclk;
+
+	uint8_t  AcpiReq;
+	uint8_t  AcpiAck;
+	uint8_t  GfxClkSlow;
+	uint8_t  GpioClampMode;
+
+	uint8_t  spare2;
+	uint8_t  EnabledLevelsChange;
+	uint8_t  DteClampMode;
+	uint8_t  FpsClampMode;
+
+	uint16_t LevelResidencyCounters[SMU74_MAX_LEVELS_GRAPHICS];
+	uint16_t LevelSwitchCounters[SMU74_MAX_LEVELS_GRAPHICS];
+
+	void     (*TargetStateCalculator)(uint8_t);
+	void     (*SavedTargetStateCalculator)(uint8_t);
+
+	uint16_t AutoDpmInterval;
+	uint16_t AutoDpmRange;
+
+	uint8_t  FpsEnabled;
+	uint8_t  MaxPerfLevel;
+	uint8_t  AllowLowClkInterruptToHost;
+	uint8_t  FpsRunning;
+
+	uint32_t MaxAllowedFrequency;
+
+	uint32_t FilteredSclkFrequency;
+	uint32_t LastSclkFrequency;
+	uint32_t FilteredSclkFrequencyCnt;
+
+	uint8_t MinPerfLevel;
+	uint8_t padding[3];
+
+	uint16_t FpsAlpha;
+	uint16_t DeltaTime;
+	uint32_t CurrentFps;
+	uint32_t FilteredFps;
+	uint32_t FrameCount;
+	uint32_t FrameCountLast;
+	uint16_t FpsTargetScalar;
+	uint16_t FpsWaterfallLimitScalar;
+	uint16_t FpsAlphaScalar;
+	uint16_t spare8;
+	SMU7_HystController_Data HystControllerData;
+};
+
+typedef struct SMU7_LocalDpmScoreboard SMU7_LocalDpmScoreboard;
+
+#define SMU7_MAX_VOLTAGE_CLIENTS 12
+
+typedef uint8_t (*VoltageChangeHandler_t)(uint16_t, uint8_t);
+
+#define VDDC_MASK    0x00007FFF
+#define VDDC_SHIFT   0
+#define VDDCI_MASK   0x3FFF8000
+#define VDDCI_SHIFT  15
+#define PHASES_MASK  0xC0000000
+#define PHASES_SHIFT 30
+
+typedef uint32_t SMU_VoltageLevel;
+
+struct SMU7_VoltageScoreboard {
+
+	SMU_VoltageLevel TargetVoltage;
+	uint16_t MaxVid;
+	uint8_t  HighestVidOffset;
+	uint8_t  CurrentVidOffset;
+
+	uint16_t CurrentVddc;
+	uint16_t CurrentVddci;
+
+
+	uint8_t  ControllerBusy;
+	uint8_t  CurrentVid;
+	uint8_t  CurrentVddciVid;
+	uint8_t  padding;
+
+	SMU_VoltageLevel RequestedVoltage[SMU7_MAX_VOLTAGE_CLIENTS];
+	SMU_VoltageLevel TargetVoltageState;
+	uint8_t  EnabledRequest[SMU7_MAX_VOLTAGE_CLIENTS];
+
+	uint8_t  padding2;
+	uint8_t  padding3;
+	uint8_t  ControllerEnable;
+	uint8_t  ControllerRunning;
+	uint16_t CurrentStdVoltageHiSidd;
+	uint16_t CurrentStdVoltageLoSidd;
+	uint8_t  OverrideVoltage;
+	uint8_t  padding4;
+	uint8_t  padding5;
+	uint8_t  CurrentPhases;
+
+	VoltageChangeHandler_t ChangeVddc;
+
+	VoltageChangeHandler_t ChangeVddci;
+	VoltageChangeHandler_t ChangePhase;
+	VoltageChangeHandler_t ChangeMvdd;
+
+	VoltageChangeHandler_t functionLinks[6];
+
+	uint16_t *VddcFollower1;
+
+	int16_t  Driver_OD_RequestedVidOffset1;
+	int16_t  Driver_OD_RequestedVidOffset2;
+};
+
+typedef struct SMU7_VoltageScoreboard SMU7_VoltageScoreboard;
+
+#define SMU7_MAX_PCIE_LINK_SPEEDS 3 /* 0:Gen1 1:Gen2 2:Gen3 */
+
+struct SMU7_PCIeLinkSpeedScoreboard {
+	uint8_t     DpmEnable;
+	uint8_t     DpmRunning;
+	uint8_t     DpmForce;
+	uint8_t     DpmForceLevel;
+
+	uint8_t     CurrentLinkSpeed;
+	uint8_t     EnabledLevelsChange;
+	uint16_t    AutoDpmInterval;
+
+	uint16_t    AutoDpmRange;
+	uint16_t    AutoDpmCount;
+
+	uint8_t     DpmMode;
+	uint8_t     AcpiReq;
+	uint8_t     AcpiAck;
+	uint8_t     CurrentLinkLevel;
+
+};
+
+typedef struct SMU7_PCIeLinkSpeedScoreboard SMU7_PCIeLinkSpeedScoreboard;
+
+#define SMU7_LKGE_LUT_NUM_OF_TEMP_ENTRIES 16
+#define SMU7_LKGE_LUT_NUM_OF_VOLT_ENTRIES 16
+
+#define SMU7_SCALE_I  7
+#define SMU7_SCALE_R 12
+
+struct SMU7_PowerScoreboard {
+	PowerCalculatorData_t VddcPowerData[SID_OPTION_COUNT];
+
+	uint32_t TotalGpuPower;
+	uint32_t TdcCurrent;
+
+	uint16_t   VddciTotalPower;
+	uint16_t   sparesasfsdfd;
+	uint16_t   Vddr1Power;
+	uint16_t   RocPower;
+
+	uint16_t   CalcMeasPowerBlend;
+	uint8_t    SidOptionPower;
+	uint8_t    SidOptionCurrent;
+
+	uint32_t   WinTime;
+
+	uint16_t Telemetry_1_slope;
+	uint16_t Telemetry_2_slope;
+	int32_t Telemetry_1_offset;
+	int32_t Telemetry_2_offset;
+
+	uint32_t VddcCurrentTelemetry;
+	uint32_t VddGfxCurrentTelemetry;
+	uint32_t VddcPowerTelemetry;
+	uint32_t VddGfxPowerTelemetry;
+	uint32_t VddciPowerTelemetry;
+
+	uint32_t VddcPower;
+	uint32_t VddGfxPower;
+	uint32_t VddciPower;
+
+	uint32_t TelemetryCurrent[2];
+	uint32_t TelemetryVoltage[2];
+	uint32_t TelemetryPower[2];
+};
+
+typedef struct SMU7_PowerScoreboard SMU7_PowerScoreboard;
+
+struct SMU7_ThermalScoreboard {
+	int16_t  GpuLimit;
+	int16_t  GpuHyst;
+	uint16_t CurrGnbTemp;
+	uint16_t FilteredGnbTemp;
+
+	uint8_t  ControllerEnable;
+	uint8_t  ControllerRunning;
+	uint8_t  AutoTmonCalInterval;
+	uint8_t  AutoTmonCalEnable;
+
+	uint8_t  ThermalDpmEnabled;
+	uint8_t  SclkEnabledMask;
+	uint8_t  spare[2];
+	int32_t  temperature_gradient;
+
+	SMU7_HystController_Data HystControllerData;
+	int32_t  WeightedSensorTemperature;
+	uint16_t TemperatureLimit[SMU74_MAX_LEVELS_GRAPHICS];
+	uint32_t Alpha;
+};
+
+typedef struct SMU7_ThermalScoreboard SMU7_ThermalScoreboard;
+
+#define SMU7_SCLK_DPM_CONFIG_MASK                        0x01
+#define SMU7_VOLTAGE_CONTROLLER_CONFIG_MASK              0x02
+#define SMU7_THERMAL_CONTROLLER_CONFIG_MASK              0x04
+#define SMU7_MCLK_DPM_CONFIG_MASK                        0x08
+#define SMU7_UVD_DPM_CONFIG_MASK                         0x10
+#define SMU7_VCE_DPM_CONFIG_MASK                         0x20
+#define SMU7_ACP_DPM_CONFIG_MASK                         0x40
+#define SMU7_SAMU_DPM_CONFIG_MASK                        0x80
+#define SMU7_PCIEGEN_DPM_CONFIG_MASK                    0x100
+
+#define SMU7_ACP_MCLK_HANDSHAKE_DISABLE                  0x00000001
+#define SMU7_ACP_SCLK_HANDSHAKE_DISABLE                  0x00000002
+#define SMU7_UVD_MCLK_HANDSHAKE_DISABLE                  0x00000100
+#define SMU7_UVD_SCLK_HANDSHAKE_DISABLE                  0x00000200
+#define SMU7_VCE_MCLK_HANDSHAKE_DISABLE                  0x00010000
+#define SMU7_VCE_SCLK_HANDSHAKE_DISABLE                  0x00020000
+
+/* All 'soft registers' should be uint32_t. */
+struct SMU74_SoftRegisters {
+	uint32_t        RefClockFrequency;
+	uint32_t        PmTimerPeriod;
+	uint32_t        FeatureEnables;
+
+	uint32_t        PreVBlankGap;
+	uint32_t        VBlankTimeout;
+	uint32_t        TrainTimeGap;
+
+	uint32_t        MvddSwitchTime;
+	uint32_t        LongestAcpiTrainTime;
+	uint32_t        AcpiDelay;
+	uint32_t        G5TrainTime;
+	uint32_t        DelayMpllPwron;
+	uint32_t        VoltageChangeTimeout;
+
+	uint32_t        HandshakeDisables;
+
+	uint8_t         DisplayPhy1Config;
+	uint8_t         DisplayPhy2Config;
+	uint8_t         DisplayPhy3Config;
+	uint8_t         DisplayPhy4Config;
+
+	uint8_t         DisplayPhy5Config;
+	uint8_t         DisplayPhy6Config;
+	uint8_t         DisplayPhy7Config;
+	uint8_t         DisplayPhy8Config;
+
+	uint32_t        AverageGraphicsActivity;
+	uint32_t        AverageMemoryActivity;
+	uint32_t        AverageGioActivity;
+
+	uint8_t         SClkDpmEnabledLevels;
+	uint8_t         MClkDpmEnabledLevels;
+	uint8_t         LClkDpmEnabledLevels;
+	uint8_t         PCIeDpmEnabledLevels;
+
+	uint8_t         UVDDpmEnabledLevels;
+	uint8_t         SAMUDpmEnabledLevels;
+	uint8_t         ACPDpmEnabledLevels;
+	uint8_t         VCEDpmEnabledLevels;
+
+	uint32_t        DRAM_LOG_ADDR_H;
+	uint32_t        DRAM_LOG_ADDR_L;
+	uint32_t        DRAM_LOG_PHY_ADDR_H;
+	uint32_t        DRAM_LOG_PHY_ADDR_L;
+	uint32_t        DRAM_LOG_BUFF_SIZE;
+	uint32_t        UlvEnterCount;
+	uint32_t        UlvTime;
+	uint32_t        UcodeLoadStatus;
+	uint32_t        AllowMvddSwitch;
+	uint8_t         Activity_Weight;
+	uint8_t         Reserved8[3];
+};
+
+typedef struct SMU74_SoftRegisters SMU74_SoftRegisters;
+
+struct SMU74_Firmware_Header {
+	uint32_t Digest[5];
+	uint32_t Version;
+	uint32_t HeaderSize;
+	uint32_t Flags;
+	uint32_t EntryPoint;
+	uint32_t CodeSize;
+	uint32_t ImageSize;
+
+	uint32_t Rtos;
+	uint32_t SoftRegisters;
+	uint32_t DpmTable;
+	uint32_t FanTable;
+	uint32_t CacConfigTable;
+	uint32_t CacStatusTable;
+
+	uint32_t mcRegisterTable;
+
+	uint32_t mcArbDramTimingTable;
+
+	uint32_t PmFuseTable;
+	uint32_t Globals;
+	uint32_t ClockStretcherTable;
+	uint32_t VftTable;
+	uint32_t Reserved1;
+	uint32_t AvfsTable;
+	uint32_t AvfsCksOffGbvTable;
+	uint32_t AvfsMeanNSigma;
+	uint32_t AvfsSclkOffsetTable;
+	uint32_t Reserved[16];
+	uint32_t Signature;
+};
+
+typedef struct SMU74_Firmware_Header SMU74_Firmware_Header;
+
+#define SMU7_FIRMWARE_HEADER_LOCATION 0x20000
+
+enum  DisplayConfig {
+	PowerDown = 1,
+	DP54x4,
+	DP54x2,
+	DP54x1,
+	DP27x4,
+	DP27x2,
+	DP27x1,
+	HDMI297,
+	HDMI162,
+	LVDS,
+	DP324x4,
+	DP324x2,
+	DP324x1
+};
+
+
+#define MC_BLOCK_COUNT 1
+#define CPL_BLOCK_COUNT 5
+#define SE_BLOCK_COUNT 15
+#define GC_BLOCK_COUNT 24
+
+struct SMU7_Local_Cac {
+	uint8_t BlockId;
+	uint8_t SignalId;
+	uint8_t Threshold;
+	uint8_t Padding;
+};
+
+typedef struct SMU7_Local_Cac SMU7_Local_Cac;
+
+struct SMU7_Local_Cac_Table {
+
+	SMU7_Local_Cac CplLocalCac[CPL_BLOCK_COUNT];
+	SMU7_Local_Cac McLocalCac[MC_BLOCK_COUNT];
+	SMU7_Local_Cac SeLocalCac[SE_BLOCK_COUNT];
+	SMU7_Local_Cac GcLocalCac[GC_BLOCK_COUNT];
+};
+
+typedef struct SMU7_Local_Cac_Table SMU7_Local_Cac_Table;
+
+#pragma pack(pop)
+
+/* Description of Clock Gating bitmask for Tonga:
+ * System Clock Gating
+ */
+#define CG_SYS_BITMASK_FIRST_BIT      0  /* First bit of Sys CG bitmask */
+#define CG_SYS_BITMASK_LAST_BIT       9  /* Last bit of Sys CG bitmask */
+#define CG_SYS_BIF_MGLS_SHIFT         0
+#define CG_SYS_ROM_SHIFT              1
+#define CG_SYS_MC_MGCG_SHIFT          2
+#define CG_SYS_MC_MGLS_SHIFT          3
+#define CG_SYS_SDMA_MGCG_SHIFT        4
+#define CG_SYS_SDMA_MGLS_SHIFT        5
+#define CG_SYS_DRM_MGCG_SHIFT         6
+#define CG_SYS_HDP_MGCG_SHIFT         7
+#define CG_SYS_HDP_MGLS_SHIFT         8
+#define CG_SYS_DRM_MGLS_SHIFT         9
+#define CG_SYS_BIF_MGCG_SHIFT         10
+
+#define CG_SYS_BIF_MGLS_MASK          0x1
+#define CG_SYS_ROM_MASK               0x2
+#define CG_SYS_MC_MGCG_MASK           0x4
+#define CG_SYS_MC_MGLS_MASK           0x8
+#define CG_SYS_SDMA_MGCG_MASK         0x10
+#define CG_SYS_SDMA_MGLS_MASK         0x20
+#define CG_SYS_DRM_MGCG_MASK          0x40
+#define CG_SYS_HDP_MGCG_MASK          0x80
+#define CG_SYS_HDP_MGLS_MASK          0x100
+#define CG_SYS_DRM_MGLS_MASK          0x200
+#define CG_SYS_BIF_MGCG_MASK          0x400
+
+/* Graphics Clock Gating */
+#define CG_GFX_BITMASK_FIRST_BIT      16 /* First bit of Gfx CG bitmask */
+#define CG_GFX_BITMASK_LAST_BIT       24 /* Last bit of Gfx CG bitmask */
+
+#define CG_GFX_CGCG_SHIFT             16
+#define CG_GFX_CGLS_SHIFT             17
+#define CG_CPF_MGCG_SHIFT             18
+#define CG_RLC_MGCG_SHIFT             19
+#define CG_GFX_OTHERS_MGCG_SHIFT      20
+#define CG_GFX_3DCG_SHIFT             21
+#define CG_GFX_3DLS_SHIFT             22
+#define CG_GFX_RLC_LS_SHIFT           23
+#define CG_GFX_CP_LS_SHIFT            24
+
+#define CG_GFX_CGCG_MASK              0x00010000
+#define CG_GFX_CGLS_MASK              0x00020000
+#define CG_CPF_MGCG_MASK              0x00040000
+#define CG_RLC_MGCG_MASK              0x00080000
+#define CG_GFX_OTHERS_MGCG_MASK       0x00100000
+#define CG_GFX_3DCG_MASK              0x00200000
+#define CG_GFX_3DLS_MASK              0x00400000
+#define CG_GFX_RLC_LS_MASK            0x00800000
+#define CG_GFX_CP_LS_MASK             0x01000000
+
+
+/* Voltage Regulator Configuration
+VR Config info is contained in dpmTable.VRConfig */
+
+#define VRCONF_VDDC_MASK         0x000000FF
+#define VRCONF_VDDC_SHIFT        0
+#define VRCONF_VDDGFX_MASK       0x0000FF00
+#define VRCONF_VDDGFX_SHIFT      8
+#define VRCONF_VDDCI_MASK        0x00FF0000
+#define VRCONF_VDDCI_SHIFT       16
+#define VRCONF_MVDD_MASK         0xFF000000
+#define VRCONF_MVDD_SHIFT        24
+
+#define VR_MERGED_WITH_VDDC      0
+#define VR_SVI2_PLANE_1          1
+#define VR_SVI2_PLANE_2          2
+#define VR_SMIO_PATTERN_1        3
+#define VR_SMIO_PATTERN_2        4
+#define VR_STATIC_VOLTAGE        5
+
+/* Clock Stretcher Configuration */
+
+#define CLOCK_STRETCHER_MAX_ENTRIES 0x4
+#define CKS_LOOKUPTable_MAX_ENTRIES 0x4
+
+/* The 'settings' field is subdivided in the following way: */
+#define CLOCK_STRETCHER_SETTING_DDT_MASK             0x01
+#define CLOCK_STRETCHER_SETTING_DDT_SHIFT            0x0
+#define CLOCK_STRETCHER_SETTING_STRETCH_AMOUNT_MASK  0x1E
+#define CLOCK_STRETCHER_SETTING_STRETCH_AMOUNT_SHIFT 0x1
+#define CLOCK_STRETCHER_SETTING_ENABLE_MASK          0x80
+#define CLOCK_STRETCHER_SETTING_ENABLE_SHIFT         0x7
+
+struct SMU_ClockStretcherDataTableEntry {
+	uint8_t minVID;
+	uint8_t maxVID;
+	uint16_t setting;
+};
+typedef struct SMU_ClockStretcherDataTableEntry SMU_ClockStretcherDataTableEntry;
+
+struct SMU_ClockStretcherDataTable {
+	SMU_ClockStretcherDataTableEntry ClockStretcherDataTableEntry[CLOCK_STRETCHER_MAX_ENTRIES];
+};
+typedef struct SMU_ClockStretcherDataTable SMU_ClockStretcherDataTable;
+
+struct SMU_CKS_LOOKUPTableEntry {
+	uint16_t minFreq;
+	uint16_t maxFreq;
+
+	uint8_t setting;
+	uint8_t padding[3];
+};
+typedef struct SMU_CKS_LOOKUPTableEntry SMU_CKS_LOOKUPTableEntry;
+
+struct SMU_CKS_LOOKUPTable {
+	SMU_CKS_LOOKUPTableEntry CKS_LOOKUPTableEntry[CKS_LOOKUPTable_MAX_ENTRIES];
+};
+typedef struct SMU_CKS_LOOKUPTable SMU_CKS_LOOKUPTable;
+
+struct AgmAvfsData_t {
+	uint16_t avgPsmCount[28];
+	uint16_t minPsmCount[28];
+};
+
+typedef struct AgmAvfsData_t AgmAvfsData_t;
+
+enum VFT_COLUMNS {
+	SCLK0,
+	SCLK1,
+	SCLK2,
+	SCLK3,
+	SCLK4,
+	SCLK5,
+	SCLK6,
+	SCLK7,
+
+	NUM_VFT_COLUMNS
+};
+
+#define VFT_TABLE_DEFINED
+
+#define TEMP_RANGE_MAXSTEPS 12
+
+struct VFT_CELL_t {
+	uint16_t Voltage;
+};
+
+typedef struct VFT_CELL_t VFT_CELL_t;
+
+struct VFT_TABLE_t {
+	VFT_CELL_t    Cell[TEMP_RANGE_MAXSTEPS][NUM_VFT_COLUMNS];
+	uint16_t      AvfsGbv[NUM_VFT_COLUMNS];
+	uint16_t      BtcGbv[NUM_VFT_COLUMNS];
+	uint16_t      Temperature[TEMP_RANGE_MAXSTEPS];
+
+	uint8_t       NumTemperatureSteps;
+	uint8_t       padding[3];
+};
+
+typedef struct VFT_TABLE_t VFT_TABLE_t;
+
+
+/* Total margin, root mean square of Fmax + DC + Platform */
+struct AVFS_Margin_t {
+	VFT_CELL_t Cell[NUM_VFT_COLUMNS];
+};
+typedef struct AVFS_Margin_t AVFS_Margin_t;
+
+#define BTCGB_VDROOP_TABLE_MAX_ENTRIES 2
+#define AVFSGB_VDROOP_TABLE_MAX_ENTRIES 2
+
+struct GB_VDROOP_TABLE_t {
+	int32_t a0;
+	int32_t a1;
+	int32_t a2;
+	uint32_t spare;
+};
+typedef struct GB_VDROOP_TABLE_t GB_VDROOP_TABLE_t;
+
+struct AVFS_CksOff_Gbv_t {
+	VFT_CELL_t Cell[NUM_VFT_COLUMNS];
+};
+typedef struct AVFS_CksOff_Gbv_t AVFS_CksOff_Gbv_t;
+
+struct AVFS_meanNsigma_t {
+	uint32_t Aconstant[3];
+	uint16_t DC_tol_sigma;
+	uint16_t Platform_mean;
+	uint16_t Platform_sigma;
+	uint16_t PSM_Age_CompFactor;
+	uint8_t  Static_Voltage_Offset[NUM_VFT_COLUMNS];
+};
+typedef struct AVFS_meanNsigma_t AVFS_meanNsigma_t;
+
+struct AVFS_Sclk_Offset_t {
+	uint16_t Sclk_Offset[8];
+};
+typedef struct AVFS_Sclk_Offset_t AVFS_Sclk_Offset_t;
+
+#endif
+
+
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/inc/smu_ucode_xfer_cz.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/inc/smu_ucode_xfer_cz.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/inc/smu_ucode_xfer_cz.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/inc/smu_ucode_xfer_cz.h	2016-07-24 15:23:50.000000000 -0400
@@ -1,3 +1,25 @@
+/*
+ * Copyright 2016 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
 // CZ Ucode Loading Definitions
 #ifndef SMU_UCODE_XFER_CZ_H
 #define SMU_UCODE_XFER_CZ_H
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/inc/smu_ucode_xfer_vi.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/inc/smu_ucode_xfer_vi.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/inc/smu_ucode_xfer_vi.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/inc/smu_ucode_xfer_vi.h	2016-07-24 15:23:50.000000000 -0400
@@ -44,6 +44,7 @@
 #define UCODE_ID_IH_REG_RESTORE   11
 #define UCODE_ID_VBIOS            12
 #define UCODE_ID_MISC_METADATA    13
+#define UCODE_ID_SMU_SK		      14
 #define UCODE_ID_RLC_SCRATCH      32
 #define UCODE_ID_RLC_SRM_ARAM     33
 #define UCODE_ID_RLC_SRM_DRAM     34
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c	2016-07-24 15:23:50.000000000 -0400
@@ -39,7 +39,7 @@
 
 #define SIZE_ALIGN_32(x)    (((x) + 31) / 32 * 32)
 
-static enum cz_scratch_entry firmware_list[] = {
+static const enum cz_scratch_entry firmware_list[] = {
 	CZ_SCRATCH_ENTRY_UCODE_ID_SDMA0,
 	CZ_SCRATCH_ENTRY_UCODE_ID_SDMA1,
 	CZ_SCRATCH_ENTRY_UCODE_ID_CP_CE,
@@ -639,7 +639,7 @@ static int cz_smu_populate_firmware_entr
 
 	cz_smu->driver_buffer_length = 0;
 
-	for (i = 0; i < sizeof(firmware_list)/sizeof(*firmware_list); i++) {
+	for (i = 0; i < ARRAY_SIZE(firmware_list); i++) {
 
 		firmware_type = cz_translate_firmware_enum_to_arg(smumgr,
 					firmware_list[i]);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c	2016-07-24 15:23:50.000000000 -0400
@@ -44,7 +44,7 @@
 
 #define FIJI_SMC_SIZE 0x20000
 
-struct SMU73_Discrete_GraphicsLevel avfs_graphics_level[8] = {
+static const struct SMU73_Discrete_GraphicsLevel avfs_graphics_level[8] = {
 		/*  Min        Sclk       pcie     DeepSleep Activity  CgSpll      CgSpll    spllSpread  SpllSpread   CcPwr  CcPwr  Sclk   Display     Enabled     Enabled                       Voltage    Power */
 		/* Voltage,  Frequency,  DpmLevel,  DivId,    Level,  FuncCntl3,  FuncCntl4,  Spectrum,   Spectrum2,  DynRm, DynRm1  Did, Watermark, ForActivity, ForThrottle, UpHyst, DownHyst, DownHyst, Throttle */
 		{ 0x3c0fd047, 0x30750000,   0x00,     0x03,   0x1e00, 0x00200410, 0x87020000, 0x21680000, 0x0c000000,   0,      0,   0x16,   0x00,       0x01,        0x01,      0x00,   0x00,      0x00,     0x00 },
@@ -189,7 +189,7 @@ int fiji_copy_bytes_to_smc(struct pp_smu
 
 int fiji_program_jump_on_start(struct pp_smumgr *smumgr)
 {
-	static unsigned char data[] = { 0xE0, 0x00, 0x80, 0x40 };
+	static const unsigned char data[] = { 0xE0, 0x00, 0x80, 0x40 };
 
 	fiji_copy_bytes_to_smc(smumgr, 0x0, data, 4, sizeof(data) + 1);
 
@@ -665,7 +665,7 @@ int fiji_setup_pwr_virus(struct pp_smumg
 {
 	int i, result = -1;
 	uint32_t reg, data;
-	PWR_Command_Table *virus = PwrVirusTable;
+	const PWR_Command_Table *virus = PwrVirusTable;
 	struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend);
 
 	priv->avfs.AvfsBtcStatus = AVFS_LOAD_VIRUS;
@@ -1006,10 +1006,16 @@ static int fiji_smu_init(struct pp_smumg
 
 static int fiji_smu_fini(struct pp_smumgr *smumgr)
 {
+	struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend);
+
+	smu_free_memory(smumgr->device, (void *)priv->header_buffer.handle);
+
 	if (smumgr->backend) {
 		kfree(smumgr->backend);
 		smumgr->backend = NULL;
 	}
+
+	cgs_rel_firmware(smumgr->device, CGS_UCODE_ID_SMU);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/smumgr/Makefile linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/smumgr/Makefile
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/smumgr/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/smumgr/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -2,7 +2,7 @@
 # Makefile for the 'smu manager' sub-component of powerplay.
 # It provides the smu management services for the driver.
 
-SMU_MGR = smumgr.o cz_smumgr.o tonga_smumgr.o fiji_smumgr.o
+SMU_MGR = smumgr.o cz_smumgr.o tonga_smumgr.o fiji_smumgr.o polaris10_smumgr.o
 
 AMD_PP_SMUMGR = $(addprefix $(AMD_PP_PATH)/smumgr/,$(SMU_MGR))
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,1007 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "smumgr.h"
+#include "smu74.h"
+#include "smu_ucode_xfer_vi.h"
+#include "polaris10_smumgr.h"
+#include "smu74_discrete.h"
+#include "smu/smu_7_1_3_d.h"
+#include "smu/smu_7_1_3_sh_mask.h"
+#include "gmc/gmc_8_1_d.h"
+#include "gmc/gmc_8_1_sh_mask.h"
+#include "oss/oss_3_0_d.h"
+#include "gca/gfx_8_0_d.h"
+#include "bif/bif_5_0_d.h"
+#include "bif/bif_5_0_sh_mask.h"
+#include "polaris10_pwrvirus.h"
+#include "ppatomctrl.h"
+#include "pp_debug.h"
+#include "cgs_common.h"
+
+#define POLARIS10_SMC_SIZE 0x20000
+#define VOLTAGE_SCALE 4
+
+/* Microcode file is stored in this buffer */
+#define BUFFER_SIZE                 80000
+#define MAX_STRING_SIZE             15
+#define BUFFER_SIZETWO              131072  /* 128 *1024 */
+
+#define SMC_RAM_END 0x40000
+
+static const SMU74_Discrete_GraphicsLevel avfs_graphics_level_polaris10[8] = {
+	/*  Min      pcie   DeepSleep Activity  CgSpll      CgSpll    CcPwr  CcPwr  Sclk         Enabled      Enabled                       Voltage    Power */
+	/* Voltage, DpmLevel, DivId,  Level,  FuncCntl3,  FuncCntl4,  DynRm, DynRm1 Did, Padding,ForActivity, ForThrottle, UpHyst, DownHyst, DownHyst, Throttle */
+	{ 0x100ea446, 0x00, 0x03, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0x30750000, 0x3000, 0, 0x2600, 0, 0, 0x0004, 0x8f02, 0xffff, 0x2f00, 0x300e, 0x2700 } },
+	{ 0x400ea446, 0x01, 0x04, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0x409c0000, 0x2000, 0, 0x1e00, 1, 1, 0x0004, 0x8300, 0xffff, 0x1f00, 0xcb5e, 0x1a00 } },
+	{ 0x740ea446, 0x01, 0x00, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0x50c30000, 0x2800, 0, 0x2000, 1, 1, 0x0004, 0x0c02, 0xffff, 0x2700, 0x6433, 0x2100 } },
+	{ 0xa40ea446, 0x01, 0x00, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0x60ea0000, 0x3000, 0, 0x2600, 1, 1, 0x0004, 0x8f02, 0xffff, 0x2f00, 0x300e, 0x2700 } },
+	{ 0xd80ea446, 0x01, 0x00, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0x70110100, 0x3800, 0, 0x2c00, 1, 1, 0x0004, 0x1203, 0xffff, 0x3600, 0xc9e2, 0x2e00 } },
+	{ 0x3c0fa446, 0x01, 0x00, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0x80380100, 0x2000, 0, 0x1e00, 2, 1, 0x0004, 0x8300, 0xffff, 0x1f00, 0xcb5e, 0x1a00 } },
+	{ 0x6c0fa446, 0x01, 0x00, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0x905f0100, 0x2400, 0, 0x1e00, 2, 1, 0x0004, 0x8901, 0xffff, 0x2300, 0x314c, 0x1d00 } },
+	{ 0xa00fa446, 0x01, 0x00, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0xa0860100, 0x2800, 0, 0x2000, 2, 1, 0x0004, 0x0c02, 0xffff, 0x2700, 0x6433, 0x2100 } }
+};
+
+static const SMU74_Discrete_MemoryLevel avfs_memory_level_polaris10 =
+	{0x100ea446, 0, 0x30750000, 0x01, 0x01, 0x01, 0x00, 0x00, 0x64, 0x00, 0x00, 0x1f00, 0x00, 0x00};
+
+/**
+* Set the address for reading/writing the SMC SRAM space.
+* @param    smumgr  the address of the powerplay hardware manager.
+* @param    smcAddress the address in the SMC RAM to access.
+*/
+static int polaris10_set_smc_sram_address(struct pp_smumgr *smumgr, uint32_t smc_addr, uint32_t limit)
+{
+	PP_ASSERT_WITH_CODE((0 == (3 & smc_addr)), "SMC address must be 4 byte aligned.", return -EINVAL);
+	PP_ASSERT_WITH_CODE((limit > (smc_addr + 3)), "SMC addr is beyond the SMC RAM area.", return -EINVAL);
+
+	cgs_write_register(smumgr->device, mmSMC_IND_INDEX_11, smc_addr);
+	SMUM_WRITE_FIELD(smumgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_11, 0);
+
+	return 0;
+}
+
+/**
+* Copy bytes from SMC RAM space into driver memory.
+*
+* @param    smumgr  the address of the powerplay SMU manager.
+* @param    smc_start_address the start address in the SMC RAM to copy bytes from
+* @param    src the byte array to copy the bytes to.
+* @param    byte_count the number of bytes to copy.
+*/
+int polaris10_copy_bytes_from_smc(struct pp_smumgr *smumgr, uint32_t smc_start_address, uint32_t *dest, uint32_t byte_count, uint32_t limit)
+{
+	uint32_t data;
+	uint32_t addr;
+	uint8_t *dest_byte;
+	uint8_t i, data_byte[4] = {0};
+	uint32_t *pdata = (uint32_t *)&data_byte;
+
+	PP_ASSERT_WITH_CODE((0 == (3 & smc_start_address)), "SMC address must be 4 byte aligned.", return -1;);
+	PP_ASSERT_WITH_CODE((limit > (smc_start_address + byte_count)), "SMC address is beyond the SMC RAM area.", return -1);
+
+	addr = smc_start_address;
+
+	while (byte_count >= 4) {
+		polaris10_read_smc_sram_dword(smumgr, addr, &data, limit);
+
+		*dest = PP_SMC_TO_HOST_UL(data);
+
+		dest += 1;
+		byte_count -= 4;
+		addr += 4;
+	}
+
+	if (byte_count) {
+		polaris10_read_smc_sram_dword(smumgr, addr, &data, limit);
+		*pdata = PP_SMC_TO_HOST_UL(data);
+	/* Cast dest into byte type in dest_byte.  This way, we don't overflow if the allocated memory is not 4-byte aligned. */
+		dest_byte = (uint8_t *)dest;
+		for (i = 0; i < byte_count; i++)
+			dest_byte[i] = data_byte[i];
+	}
+
+	return 0;
+}
+
+/**
+* Copy bytes from an array into the SMC RAM space.
+*
+* @param    pSmuMgr  the address of the powerplay SMU manager.
+* @param    smc_start_address the start address in the SMC RAM to copy bytes to.
+* @param    src the byte array to copy the bytes from.
+* @param    byte_count the number of bytes to copy.
+*/
+int polaris10_copy_bytes_to_smc(struct pp_smumgr *smumgr, uint32_t smc_start_address,
+				const uint8_t *src, uint32_t byte_count, uint32_t limit)
+{
+	int result;
+	uint32_t data = 0;
+	uint32_t original_data;
+	uint32_t addr = 0;
+	uint32_t extra_shift;
+
+	PP_ASSERT_WITH_CODE((0 == (3 & smc_start_address)), "SMC address must be 4 byte aligned.", return -1);
+	PP_ASSERT_WITH_CODE((limit > (smc_start_address + byte_count)), "SMC address is beyond the SMC RAM area.", return -1);
+
+	addr = smc_start_address;
+
+	while (byte_count >= 4) {
+	/* Bytes are written into the SMC addres space with the MSB first. */
+		data = src[0] * 0x1000000 + src[1] * 0x10000 + src[2] * 0x100 + src[3];
+
+		result = polaris10_set_smc_sram_address(smumgr, addr, limit);
+
+		if (0 != result)
+			return result;
+
+		cgs_write_register(smumgr->device, mmSMC_IND_DATA_11, data);
+
+		src += 4;
+		byte_count -= 4;
+		addr += 4;
+	}
+
+	if (0 != byte_count) {
+
+		data = 0;
+
+		result = polaris10_set_smc_sram_address(smumgr, addr, limit);
+
+		if (0 != result)
+			return result;
+
+
+		original_data = cgs_read_register(smumgr->device, mmSMC_IND_DATA_11);
+
+		extra_shift = 8 * (4 - byte_count);
+
+		while (byte_count > 0) {
+			/* Bytes are written into the SMC addres space with the MSB first. */
+			data = (0x100 * data) + *src++;
+			byte_count--;
+		}
+
+		data <<= extra_shift;
+
+		data |= (original_data & ~((~0UL) << extra_shift));
+
+		result = polaris10_set_smc_sram_address(smumgr, addr, limit);
+
+		if (0 != result)
+			return result;
+
+		cgs_write_register(smumgr->device, mmSMC_IND_DATA_11, data);
+	}
+
+	return 0;
+}
+
+
+static int polaris10_program_jump_on_start(struct pp_smumgr *smumgr)
+{
+	static const unsigned char data[4] = { 0xE0, 0x00, 0x80, 0x40 };
+
+	polaris10_copy_bytes_to_smc(smumgr, 0x0, data, 4, sizeof(data)+1);
+
+	return 0;
+}
+
+/**
+* Return if the SMC is currently running.
+*
+* @param    smumgr  the address of the powerplay hardware manager.
+*/
+bool polaris10_is_smc_ram_running(struct pp_smumgr *smumgr)
+{
+	return ((0 == SMUM_READ_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, SMC_SYSCON_CLOCK_CNTL_0, ck_disable))
+	&& (0x20100 <= cgs_read_ind_register(smumgr->device, CGS_IND_REG__SMC, ixSMC_PC_C)));
+}
+
+static bool polaris10_is_hw_avfs_present(struct pp_smumgr *smumgr)
+{
+	uint32_t efuse;
+
+	efuse = cgs_read_ind_register(smumgr->device, CGS_IND_REG__SMC, ixSMU_EFUSE_0 + (49*4));
+	efuse &= 0x00000001;
+	if (efuse)
+		return true;
+
+	return false;
+}
+
+/**
+* Send a message to the SMC, and wait for its response.
+*
+* @param    smumgr  the address of the powerplay hardware manager.
+* @param    msg the message to send.
+* @return   The response that came from the SMC.
+*/
+int polaris10_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg)
+{
+	int ret;
+
+	if (!polaris10_is_smc_ram_running(smumgr))
+		return -1;
+
+
+	SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0);
+
+	ret = SMUM_READ_FIELD(smumgr->device, SMC_RESP_0, SMC_RESP);
+
+	if (ret != 1)
+		printk("\n failed to send pre message %x ret is %d \n",  msg, ret);
+
+	cgs_write_register(smumgr->device, mmSMC_MESSAGE_0, msg);
+
+	SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0);
+
+	ret = SMUM_READ_FIELD(smumgr->device, SMC_RESP_0, SMC_RESP);
+
+	if (ret != 1)
+		printk("\n failed to send message %x ret is %d \n",  msg, ret);
+
+	return 0;
+}
+
+
+/**
+* Send a message to the SMC, and do not wait for its response.
+*
+* @param    smumgr  the address of the powerplay hardware manager.
+* @param    msg the message to send.
+* @return   Always return 0.
+*/
+int polaris10_send_msg_to_smc_without_waiting(struct pp_smumgr *smumgr, uint16_t msg)
+{
+	cgs_write_register(smumgr->device, mmSMC_MESSAGE_0, msg);
+
+	return 0;
+}
+
+/**
+* Send a message to the SMC with parameter
+*
+* @param    smumgr:  the address of the powerplay hardware manager.
+* @param    msg: the message to send.
+* @param    parameter: the parameter to send
+* @return   The response that came from the SMC.
+*/
+int polaris10_send_msg_to_smc_with_parameter(struct pp_smumgr *smumgr, uint16_t msg, uint32_t parameter)
+{
+	if (!polaris10_is_smc_ram_running(smumgr)) {
+		return -1;
+	}
+
+	SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0);
+
+	cgs_write_register(smumgr->device, mmSMC_MSG_ARG_0, parameter);
+
+	return polaris10_send_msg_to_smc(smumgr, msg);
+}
+
+
+/**
+* Send a message to the SMC with parameter, do not wait for response
+*
+* @param    smumgr:  the address of the powerplay hardware manager.
+* @param    msg: the message to send.
+* @param    parameter: the parameter to send
+* @return   The response that came from the SMC.
+*/
+int polaris10_send_msg_to_smc_with_parameter_without_waiting(struct pp_smumgr *smumgr, uint16_t msg, uint32_t parameter)
+{
+	cgs_write_register(smumgr->device, mmSMC_MSG_ARG_0, parameter);
+
+	return polaris10_send_msg_to_smc_without_waiting(smumgr, msg);
+}
+
+int polaris10_send_msg_to_smc_offset(struct pp_smumgr *smumgr)
+{
+	cgs_write_register(smumgr->device, mmSMC_MSG_ARG_0, 0x20000);
+
+	cgs_write_register(smumgr->device, mmSMC_MESSAGE_0, PPSMC_MSG_Test);
+
+	SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0);
+
+	if (1 != SMUM_READ_FIELD(smumgr->device, SMC_RESP_0, SMC_RESP))
+		printk("Failed to send Message.\n");
+
+	return 0;
+}
+
+/**
+* Wait until the SMC is doing nithing. Doing nothing means that the SMC is either turned off or it is sitting on the STOP instruction.
+*
+* @param    smumgr  the address of the powerplay hardware manager.
+* @param    msg the message to send.
+* @return   The response that came from the SMC.
+*/
+int polaris10_wait_for_smc_inactive(struct pp_smumgr *smumgr)
+{
+	/* If the SMC is not even on it qualifies as inactive. */
+	if (!polaris10_is_smc_ram_running(smumgr))
+		return -1;
+
+	SMUM_WAIT_VFPF_INDIRECT_FIELD(smumgr, SMC_IND, SMC_SYSCON_CLOCK_CNTL_0, cken, 0);
+	return 0;
+}
+
+
+/**
+* Upload the SMC firmware to the SMC microcontroller.
+*
+* @param    smumgr  the address of the powerplay hardware manager.
+* @param    pFirmware the data structure containing the various sections of the firmware.
+*/
+static int polaris10_upload_smc_firmware_data(struct pp_smumgr *smumgr, uint32_t length, uint32_t *src, uint32_t limit)
+{
+	uint32_t byte_count = length;
+
+	PP_ASSERT_WITH_CODE((limit >= byte_count), "SMC address is beyond the SMC RAM area.", return -1);
+
+	cgs_write_register(smumgr->device, mmSMC_IND_INDEX_11, 0x20000);
+	SMUM_WRITE_FIELD(smumgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_11, 1);
+
+	for (; byte_count >= 4; byte_count -= 4)
+		cgs_write_register(smumgr->device, mmSMC_IND_DATA_11, *src++);
+
+	SMUM_WRITE_FIELD(smumgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_11, 0);
+
+	PP_ASSERT_WITH_CODE((0 == byte_count), "SMC size must be dividable by 4.", return -1);
+
+	return 0;
+}
+
+static enum cgs_ucode_id polaris10_convert_fw_type_to_cgs(uint32_t fw_type)
+{
+	enum cgs_ucode_id result = CGS_UCODE_ID_MAXIMUM;
+
+	switch (fw_type) {
+	case UCODE_ID_SMU:
+		result = CGS_UCODE_ID_SMU;
+		break;
+	case UCODE_ID_SMU_SK:
+		result = CGS_UCODE_ID_SMU_SK;
+		break;
+	case UCODE_ID_SDMA0:
+		result = CGS_UCODE_ID_SDMA0;
+		break;
+	case UCODE_ID_SDMA1:
+		result = CGS_UCODE_ID_SDMA1;
+		break;
+	case UCODE_ID_CP_CE:
+		result = CGS_UCODE_ID_CP_CE;
+		break;
+	case UCODE_ID_CP_PFP:
+		result = CGS_UCODE_ID_CP_PFP;
+		break;
+	case UCODE_ID_CP_ME:
+		result = CGS_UCODE_ID_CP_ME;
+		break;
+	case UCODE_ID_CP_MEC:
+		result = CGS_UCODE_ID_CP_MEC;
+		break;
+	case UCODE_ID_CP_MEC_JT1:
+		result = CGS_UCODE_ID_CP_MEC_JT1;
+		break;
+	case UCODE_ID_CP_MEC_JT2:
+		result = CGS_UCODE_ID_CP_MEC_JT2;
+		break;
+	case UCODE_ID_RLC_G:
+		result = CGS_UCODE_ID_RLC_G;
+		break;
+	default:
+		break;
+	}
+
+	return result;
+}
+
+static int polaris10_upload_smu_firmware_image(struct pp_smumgr *smumgr)
+{
+	int result = 0;
+	struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend);
+
+	struct cgs_firmware_info info = {0};
+
+	if (smu_data->security_hard_key == 1)
+		cgs_get_firmware_info(smumgr->device,
+			polaris10_convert_fw_type_to_cgs(UCODE_ID_SMU), &info);
+	else
+		cgs_get_firmware_info(smumgr->device,
+			polaris10_convert_fw_type_to_cgs(UCODE_ID_SMU_SK), &info);
+
+	/* TO DO cgs_init_samu_load_smu(smumgr->device, (uint32_t *)info.kptr, info.image_size, smu_data->post_initial_boot);*/
+	result = polaris10_upload_smc_firmware_data(smumgr, info.image_size, (uint32_t *)info.kptr, POLARIS10_SMC_SIZE);
+
+	return result;
+}
+
+/**
+* Read a 32bit value from the SMC SRAM space.
+* ALL PARAMETERS ARE IN HOST BYTE ORDER.
+* @param    smumgr  the address of the powerplay hardware manager.
+* @param    smcAddress the address in the SMC RAM to access.
+* @param    value and output parameter for the data read from the SMC SRAM.
+*/
+int polaris10_read_smc_sram_dword(struct pp_smumgr *smumgr, uint32_t smc_addr, uint32_t *value, uint32_t limit)
+{
+	int result;
+
+	result = polaris10_set_smc_sram_address(smumgr, smc_addr, limit);
+
+	if (result)
+		return result;
+
+	*value = cgs_read_register(smumgr->device, mmSMC_IND_DATA_11);
+	return 0;
+}
+
+/**
+* Write a 32bit value to the SMC SRAM space.
+* ALL PARAMETERS ARE IN HOST BYTE ORDER.
+* @param    smumgr  the address of the powerplay hardware manager.
+* @param    smc_addr the address in the SMC RAM to access.
+* @param    value to write to the SMC SRAM.
+*/
+int polaris10_write_smc_sram_dword(struct pp_smumgr *smumgr, uint32_t smc_addr, uint32_t value, uint32_t limit)
+{
+	int result;
+
+	result = polaris10_set_smc_sram_address(smumgr, smc_addr, limit);
+
+	if (result)
+		return result;
+
+	cgs_write_register(smumgr->device, mmSMC_IND_DATA_11, value);
+
+	return 0;
+}
+
+
+int polaris10_smu_fini(struct pp_smumgr *smumgr)
+{
+	if (smumgr->backend) {
+		kfree(smumgr->backend);
+		smumgr->backend = NULL;
+	}
+	cgs_rel_firmware(smumgr->device, CGS_UCODE_ID_SMU);
+	return 0;
+}
+
+/* Convert the firmware type to SMU type mask. For MEC, we need to check all MEC related type */
+static uint32_t polaris10_get_mask_for_firmware_type(uint32_t fw_type)
+{
+	uint32_t result = 0;
+
+	switch (fw_type) {
+	case UCODE_ID_SDMA0:
+		result = UCODE_ID_SDMA0_MASK;
+		break;
+	case UCODE_ID_SDMA1:
+		result = UCODE_ID_SDMA1_MASK;
+		break;
+	case UCODE_ID_CP_CE:
+		result = UCODE_ID_CP_CE_MASK;
+		break;
+	case UCODE_ID_CP_PFP:
+		result = UCODE_ID_CP_PFP_MASK;
+		break;
+	case UCODE_ID_CP_ME:
+		result = UCODE_ID_CP_ME_MASK;
+		break;
+	case UCODE_ID_CP_MEC_JT1:
+	case UCODE_ID_CP_MEC_JT2:
+		result = UCODE_ID_CP_MEC_MASK;
+		break;
+	case UCODE_ID_RLC_G:
+		result = UCODE_ID_RLC_G_MASK;
+		break;
+	default:
+		printk("UCode type is out of range! \n");
+		result = 0;
+	}
+
+	return result;
+}
+
+/* Populate one firmware image to the data structure */
+
+static int polaris10_populate_single_firmware_entry(struct pp_smumgr *smumgr,
+						uint32_t fw_type,
+						struct SMU_Entry *entry)
+{
+	int result = 0;
+	struct cgs_firmware_info info = {0};
+
+	result = cgs_get_firmware_info(smumgr->device,
+				polaris10_convert_fw_type_to_cgs(fw_type),
+				&info);
+
+	if (!result) {
+		entry->version = info.version;
+		entry->id = (uint16_t)fw_type;
+		entry->image_addr_high = smu_upper_32_bits(info.mc_addr);
+		entry->image_addr_low = smu_lower_32_bits(info.mc_addr);
+		entry->meta_data_addr_high = 0;
+		entry->meta_data_addr_low = 0;
+		entry->data_size_byte = info.image_size;
+		entry->num_register_entries = 0;
+	}
+
+	if (fw_type == UCODE_ID_RLC_G)
+		entry->flags = 1;
+	else
+		entry->flags = 0;
+
+	return 0;
+}
+
+static int polaris10_request_smu_load_fw(struct pp_smumgr *smumgr)
+{
+	struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend);
+	uint32_t fw_to_load;
+
+	int result = 0;
+	struct SMU_DRAMData_TOC *toc;
+
+	if (!smumgr->reload_fw) {
+		printk(KERN_INFO "[ powerplay ] skip reloading...\n");
+		return 0;
+	}
+
+	if (smu_data->soft_regs_start)
+		cgs_write_ind_register(smumgr->device, CGS_IND_REG__SMC,
+					smu_data->soft_regs_start + offsetof(SMU74_SoftRegisters, UcodeLoadStatus),
+					0x0);
+
+	polaris10_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_SMU_DRAM_ADDR_HI, smu_data->smu_buffer.mc_addr_high);
+	polaris10_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_SMU_DRAM_ADDR_LO, smu_data->smu_buffer.mc_addr_low);
+
+	toc = (struct SMU_DRAMData_TOC *)smu_data->header;
+	toc->num_entries = 0;
+	toc->structure_version = 1;
+
+	PP_ASSERT_WITH_CODE(0 == polaris10_populate_single_firmware_entry(smumgr, UCODE_ID_RLC_G, &toc->entry[toc->num_entries++]), "Failed to Get Firmware Entry.", return -1);
+	PP_ASSERT_WITH_CODE(0 == polaris10_populate_single_firmware_entry(smumgr, UCODE_ID_CP_CE, &toc->entry[toc->num_entries++]), "Failed to Get Firmware Entry.", return -1);
+	PP_ASSERT_WITH_CODE(0 == polaris10_populate_single_firmware_entry(smumgr, UCODE_ID_CP_PFP, &toc->entry[toc->num_entries++]), "Failed to Get Firmware Entry.", return -1);
+	PP_ASSERT_WITH_CODE(0 == polaris10_populate_single_firmware_entry(smumgr, UCODE_ID_CP_ME, &toc->entry[toc->num_entries++]), "Failed to Get Firmware Entry.", return -1);
+	PP_ASSERT_WITH_CODE(0 == polaris10_populate_single_firmware_entry(smumgr, UCODE_ID_CP_MEC, &toc->entry[toc->num_entries++]), "Failed to Get Firmware Entry.", return -1);
+	PP_ASSERT_WITH_CODE(0 == polaris10_populate_single_firmware_entry(smumgr, UCODE_ID_CP_MEC_JT1, &toc->entry[toc->num_entries++]), "Failed to Get Firmware Entry.", return -1);
+	PP_ASSERT_WITH_CODE(0 == polaris10_populate_single_firmware_entry(smumgr, UCODE_ID_CP_MEC_JT2, &toc->entry[toc->num_entries++]), "Failed to Get Firmware Entry.", return -1);
+	PP_ASSERT_WITH_CODE(0 == polaris10_populate_single_firmware_entry(smumgr, UCODE_ID_SDMA0, &toc->entry[toc->num_entries++]), "Failed to Get Firmware Entry.", return -1);
+	PP_ASSERT_WITH_CODE(0 == polaris10_populate_single_firmware_entry(smumgr, UCODE_ID_SDMA1, &toc->entry[toc->num_entries++]), "Failed to Get Firmware Entry.", return -1);
+
+	polaris10_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_DRV_DRAM_ADDR_HI, smu_data->header_buffer.mc_addr_high);
+	polaris10_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_DRV_DRAM_ADDR_LO, smu_data->header_buffer.mc_addr_low);
+
+	fw_to_load = UCODE_ID_RLC_G_MASK
+		   + UCODE_ID_SDMA0_MASK
+		   + UCODE_ID_SDMA1_MASK
+		   + UCODE_ID_CP_CE_MASK
+		   + UCODE_ID_CP_ME_MASK
+		   + UCODE_ID_CP_PFP_MASK
+		   + UCODE_ID_CP_MEC_MASK;
+
+	if (polaris10_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_LoadUcodes, fw_to_load))
+		printk(KERN_ERR "Fail to Request SMU Load uCode");
+
+	return result;
+}
+
+/* Check if the FW has been loaded, SMU will not return if loading has not finished. */
+static int polaris10_check_fw_load_finish(struct pp_smumgr *smumgr, uint32_t fw_type)
+{
+	struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend);
+	uint32_t fw_mask = polaris10_get_mask_for_firmware_type(fw_type);
+	uint32_t ret;
+	/* Check SOFT_REGISTERS_TABLE_28.UcodeLoadStatus */
+	ret = smum_wait_on_indirect_register(smumgr, mmSMC_IND_INDEX_11,
+					smu_data->soft_regs_start + offsetof(SMU74_SoftRegisters, UcodeLoadStatus),
+					fw_mask, fw_mask);
+
+	return ret;
+}
+
+static int polaris10_reload_firmware(struct pp_smumgr *smumgr)
+{
+	return smumgr->smumgr_funcs->start_smu(smumgr);
+}
+
+static int polaris10_setup_pwr_virus(struct pp_smumgr *smumgr)
+{
+	int i;
+	int result = -1;
+	uint32_t reg, data;
+
+	const PWR_Command_Table *pvirus = pwr_virus_table;
+	struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend);
+
+
+	for (i = 0; i < PWR_VIRUS_TABLE_SIZE; i++) {
+		switch (pvirus->command) {
+		case PwrCmdWrite:
+			reg  = pvirus->reg;
+			data = pvirus->data;
+			cgs_write_register(smumgr->device, reg, data);
+			break;
+
+		case PwrCmdEnd:
+			result = 0;
+			break;
+
+		default:
+			printk("Table Exit with Invalid Command!");
+			smu_data->avfs.avfs_btc_status = AVFS_BTC_VIRUS_FAIL;
+			result = -1;
+			break;
+		}
+		pvirus++;
+	}
+
+	return result;
+}
+
+static int polaris10_perform_btc(struct pp_smumgr *smumgr)
+{
+	int result = 0;
+	struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend);
+
+	if (0 != smu_data->avfs.avfs_btc_param) {
+		if (0 != polaris10_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_PerformBtc, smu_data->avfs.avfs_btc_param)) {
+			printk("[AVFS][SmuPolaris10_PerformBtc] PerformBTC SMU msg failed");
+			result = -1;
+		}
+	}
+	if (smu_data->avfs.avfs_btc_param > 1) {
+		/* Soft-Reset to reset the engine before loading uCode */
+		/* halt */
+		cgs_write_register(smumgr->device, mmCP_MEC_CNTL, 0x50000000);
+		/* reset everything */
+		cgs_write_register(smumgr->device, mmGRBM_SOFT_RESET, 0xffffffff);
+		cgs_write_register(smumgr->device, mmGRBM_SOFT_RESET, 0);
+	}
+	return result;
+}
+
+
+int polaris10_setup_graphics_level_structure(struct pp_smumgr *smumgr)
+{
+	uint32_t vr_config;
+	uint32_t dpm_table_start;
+
+	uint16_t u16_boot_mvdd;
+	uint32_t graphics_level_address, vr_config_address, graphics_level_size;
+
+	graphics_level_size = sizeof(avfs_graphics_level_polaris10);
+	u16_boot_mvdd = PP_HOST_TO_SMC_US(1300 * VOLTAGE_SCALE);
+
+	PP_ASSERT_WITH_CODE(0 == polaris10_read_smc_sram_dword(smumgr,
+				SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU74_Firmware_Header, DpmTable),
+				&dpm_table_start, 0x40000),
+			"[AVFS][Polaris10_SetupGfxLvlStruct] SMU could not communicate starting address of DPM table",
+			return -1);
+
+	/*  Default value for VRConfig = VR_MERGED_WITH_VDDC + VR_STATIC_VOLTAGE(VDDCI) */
+	vr_config = 0x01000500; /* Real value:0x50001 */
+
+	vr_config_address = dpm_table_start + offsetof(SMU74_Discrete_DpmTable, VRConfig);
+
+	PP_ASSERT_WITH_CODE(0 == polaris10_copy_bytes_to_smc(smumgr, vr_config_address,
+				(uint8_t *)&vr_config, sizeof(uint32_t), 0x40000),
+			"[AVFS][Polaris10_SetupGfxLvlStruct] Problems copying VRConfig value over to SMC",
+			return -1);
+
+	graphics_level_address = dpm_table_start + offsetof(SMU74_Discrete_DpmTable, GraphicsLevel);
+
+	PP_ASSERT_WITH_CODE(0 == polaris10_copy_bytes_to_smc(smumgr, graphics_level_address,
+				(uint8_t *)(&avfs_graphics_level_polaris10),
+				graphics_level_size, 0x40000),
+			"[AVFS][Polaris10_SetupGfxLvlStruct] Copying of SCLK DPM table failed!",
+			return -1);
+
+	graphics_level_address = dpm_table_start + offsetof(SMU74_Discrete_DpmTable, MemoryLevel);
+
+	PP_ASSERT_WITH_CODE(0 == polaris10_copy_bytes_to_smc(smumgr, graphics_level_address,
+				(uint8_t *)(&avfs_memory_level_polaris10), sizeof(avfs_memory_level_polaris10), 0x40000),
+				"[AVFS][Polaris10_SetupGfxLvlStruct] Copying of MCLK DPM table failed!",
+			return -1);
+
+	/* MVDD Boot value - neccessary for getting rid of the hang that occurs during Mclk DPM enablement */
+
+	graphics_level_address = dpm_table_start + offsetof(SMU74_Discrete_DpmTable, BootMVdd);
+
+	PP_ASSERT_WITH_CODE(0 == polaris10_copy_bytes_to_smc(smumgr, graphics_level_address,
+			(uint8_t *)(&u16_boot_mvdd), sizeof(u16_boot_mvdd), 0x40000),
+			"[AVFS][Polaris10_SetupGfxLvlStruct] Copying of DPM table failed!",
+			return -1);
+
+	return 0;
+}
+
+int polaris10_avfs_event_mgr(struct pp_smumgr *smumgr, bool SMU_VFT_INTACT)
+{
+	struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend);
+
+	switch (smu_data->avfs.avfs_btc_status) {
+	case AVFS_BTC_COMPLETED_PREVIOUSLY:
+		break;
+
+	case AVFS_BTC_BOOT: /* Cold Boot State - Post SMU Start */
+
+		smu_data->avfs.avfs_btc_status = AVFS_BTC_DPMTABLESETUP_FAILED;
+		PP_ASSERT_WITH_CODE(0 == polaris10_setup_graphics_level_structure(smumgr),
+		"[AVFS][Polaris10_AVFSEventMgr] Could not Copy Graphics Level table over to SMU",
+		return -1);
+
+		if (smu_data->avfs.avfs_btc_param > 1) {
+			printk("[AVFS][Polaris10_AVFSEventMgr] AC BTC has not been successfully verified on Fiji. There may be in this setting.");
+			smu_data->avfs.avfs_btc_status = AVFS_BTC_VIRUS_FAIL;
+			PP_ASSERT_WITH_CODE(-1 == polaris10_setup_pwr_virus(smumgr),
+			"[AVFS][Polaris10_AVFSEventMgr] Could not setup Pwr Virus for AVFS ",
+			return -1);
+		}
+
+		smu_data->avfs.avfs_btc_status = AVFS_BTC_FAILED;
+		PP_ASSERT_WITH_CODE(0 == polaris10_perform_btc(smumgr),
+					"[AVFS][Polaris10_AVFSEventMgr] Failure at SmuPolaris10_PerformBTC. AVFS Disabled",
+				 return -1);
+
+		break;
+
+	case AVFS_BTC_DISABLED:
+	case AVFS_BTC_NOTSUPPORTED:
+		break;
+
+	default:
+		printk("[AVFS] Something is broken. See log!");
+		break;
+	}
+
+	return 0;
+}
+
+static int polaris10_start_smu_in_protection_mode(struct pp_smumgr *smumgr)
+{
+	int result = 0;
+
+	/* Wait for smc boot up */
+	/* SMUM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(smumgr, SMC_IND, RCU_UC_EVENTS, boot_seq_done, 0) */
+
+	/* Assert reset */
+	SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC,
+					SMC_SYSCON_RESET_CNTL, rst_reg, 1);
+
+	result = polaris10_upload_smu_firmware_image(smumgr);
+	if (result != 0)
+		return result;
+
+	/* Clear status */
+	cgs_write_ind_register(smumgr->device, CGS_IND_REG__SMC, ixSMU_STATUS, 0);
+
+	SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC,
+					SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0);
+
+	/* De-assert reset */
+	SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC,
+					SMC_SYSCON_RESET_CNTL, rst_reg, 0);
+
+
+	SMUM_WAIT_VFPF_INDIRECT_FIELD(smumgr, SMC_IND, RCU_UC_EVENTS, INTERRUPTS_ENABLED, 1);
+
+
+	/* Call Test SMU message with 0x20000 offset to trigger SMU start */
+	polaris10_send_msg_to_smc_offset(smumgr);
+
+	/* Wait done bit to be set */
+	/* Check pass/failed indicator */
+
+	SMUM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(smumgr, SMC_IND, SMU_STATUS, SMU_DONE, 0);
+
+	if (1 != SMUM_READ_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC,
+						SMU_STATUS, SMU_PASS))
+		PP_ASSERT_WITH_CODE(false, "SMU Firmware start failed!", return -1);
+
+	cgs_write_ind_register(smumgr->device, CGS_IND_REG__SMC, ixFIRMWARE_FLAGS, 0);
+
+	SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC,
+					SMC_SYSCON_RESET_CNTL, rst_reg, 1);
+
+	SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC,
+					SMC_SYSCON_RESET_CNTL, rst_reg, 0);
+
+	/* Wait for firmware to initialize */
+	SMUM_WAIT_VFPF_INDIRECT_FIELD(smumgr, SMC_IND, FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1);
+
+	return result;
+}
+
+static int polaris10_start_smu_in_non_protection_mode(struct pp_smumgr *smumgr)
+{
+	int result = 0;
+
+	/* wait for smc boot up */
+	SMUM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(smumgr, SMC_IND, RCU_UC_EVENTS, boot_seq_done, 0);
+
+	/* Clear firmware interrupt enable flag */
+	/* SMUM_WRITE_VFPF_INDIRECT_FIELD(pSmuMgr, SMC_IND, SMC_SYSCON_MISC_CNTL, pre_fetcher_en, 1); */
+	cgs_write_ind_register(smumgr->device, CGS_IND_REG__SMC,
+				ixFIRMWARE_FLAGS, 0);
+
+	SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC,
+					SMC_SYSCON_RESET_CNTL,
+					rst_reg, 1);
+
+	result = polaris10_upload_smu_firmware_image(smumgr);
+	if (result != 0)
+		return result;
+
+	/* Set smc instruct start point at 0x0 */
+	polaris10_program_jump_on_start(smumgr);
+
+	SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC,
+					SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0);
+
+	SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC,
+					SMC_SYSCON_RESET_CNTL, rst_reg, 0);
+
+	/* Wait for firmware to initialize */
+
+	SMUM_WAIT_VFPF_INDIRECT_FIELD(smumgr, SMC_IND,
+					FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1);
+
+	return result;
+}
+
+static int polaris10_start_smu(struct pp_smumgr *smumgr)
+{
+	int result = 0;
+	struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend);
+	bool SMU_VFT_INTACT;
+
+	/* Only start SMC if SMC RAM is not running */
+	if (!polaris10_is_smc_ram_running(smumgr)) {
+		SMU_VFT_INTACT = false;
+		smu_data->protected_mode = (uint8_t) (SMUM_READ_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, SMU_FIRMWARE, SMU_MODE));
+		smu_data->security_hard_key = (uint8_t) (SMUM_READ_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, SMU_FIRMWARE, SMU_SEL));
+
+		/* Check if SMU is running in protected mode */
+		if (smu_data->protected_mode == 0) {
+			result = polaris10_start_smu_in_non_protection_mode(smumgr);
+		} else {
+			result = polaris10_start_smu_in_protection_mode(smumgr);
+
+			/* If failed, try with different security Key. */
+			if (result != 0) {
+				smu_data->security_hard_key ^= 1;
+				result = polaris10_start_smu_in_protection_mode(smumgr);
+			}
+		}
+
+		if (result != 0)
+			PP_ASSERT_WITH_CODE(0, "Failed to load SMU ucode.", return result);
+
+		polaris10_avfs_event_mgr(smumgr, true);
+	} else
+		SMU_VFT_INTACT = true; /*Driver went offline but SMU was still alive and contains the VFT table */
+
+	smu_data->post_initial_boot = true;
+	polaris10_avfs_event_mgr(smumgr, SMU_VFT_INTACT);
+	/* Setup SoftRegsStart here for register lookup in case DummyBackEnd is used and ProcessFirmwareHeader is not executed */
+	polaris10_read_smc_sram_dword(smumgr, SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU74_Firmware_Header, SoftRegisters),
+					&(smu_data->soft_regs_start), 0x40000);
+
+	result = polaris10_request_smu_load_fw(smumgr);
+
+	return result;
+}
+
+static int polaris10_smu_init(struct pp_smumgr *smumgr)
+{
+	struct polaris10_smumgr *smu_data;
+	uint8_t *internal_buf;
+	uint64_t mc_addr = 0;
+	/* Allocate memory for backend private data */
+	smu_data = (struct polaris10_smumgr *)(smumgr->backend);
+	smu_data->header_buffer.data_size =
+		((sizeof(struct SMU_DRAMData_TOC) / 4096) + 1) * 4096;
+	smu_data->smu_buffer.data_size = 200*4096;
+	smu_data->avfs.avfs_btc_status = AVFS_BTC_NOTSUPPORTED;
+/* Allocate FW image data structure and header buffer and
+ * send the header buffer address to SMU */
+	smu_allocate_memory(smumgr->device,
+		smu_data->header_buffer.data_size,
+		CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB,
+		PAGE_SIZE,
+		&mc_addr,
+		&smu_data->header_buffer.kaddr,
+		&smu_data->header_buffer.handle);
+
+	smu_data->header = smu_data->header_buffer.kaddr;
+	smu_data->header_buffer.mc_addr_high = smu_upper_32_bits(mc_addr);
+	smu_data->header_buffer.mc_addr_low = smu_lower_32_bits(mc_addr);
+
+	PP_ASSERT_WITH_CODE((NULL != smu_data->header),
+		"Out of memory.",
+		kfree(smumgr->backend);
+		cgs_free_gpu_mem(smumgr->device,
+		(cgs_handle_t)smu_data->header_buffer.handle);
+		return -1);
+
+/* Allocate buffer for SMU internal buffer and send the address to SMU.
+ * Iceland SMU does not need internal buffer.*/
+	smu_allocate_memory(smumgr->device,
+		smu_data->smu_buffer.data_size,
+		CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB,
+		PAGE_SIZE,
+		&mc_addr,
+		&smu_data->smu_buffer.kaddr,
+		&smu_data->smu_buffer.handle);
+
+	internal_buf = smu_data->smu_buffer.kaddr;
+	smu_data->smu_buffer.mc_addr_high = smu_upper_32_bits(mc_addr);
+	smu_data->smu_buffer.mc_addr_low = smu_lower_32_bits(mc_addr);
+
+	PP_ASSERT_WITH_CODE((NULL != internal_buf),
+		"Out of memory.",
+		kfree(smumgr->backend);
+		cgs_free_gpu_mem(smumgr->device,
+		(cgs_handle_t)smu_data->smu_buffer.handle);
+		return -1;);
+
+	if (polaris10_is_hw_avfs_present(smumgr))
+		smu_data->avfs.avfs_btc_status = AVFS_BTC_BOOT;
+	else
+		smu_data->avfs.avfs_btc_status = AVFS_BTC_NOTSUPPORTED;
+
+	return 0;
+}
+
+static const struct pp_smumgr_func ellsemere_smu_funcs = {
+	.smu_init = polaris10_smu_init,
+	.smu_fini = polaris10_smu_fini,
+	.start_smu = polaris10_start_smu,
+	.check_fw_load_finish = polaris10_check_fw_load_finish,
+	.request_smu_load_fw = polaris10_reload_firmware,
+	.request_smu_load_specific_fw = NULL,
+	.send_msg_to_smc = polaris10_send_msg_to_smc,
+	.send_msg_to_smc_with_parameter = polaris10_send_msg_to_smc_with_parameter,
+	.download_pptable_settings = NULL,
+	.upload_pptable_settings = NULL,
+};
+
+int polaris10_smum_init(struct pp_smumgr *smumgr)
+{
+	struct polaris10_smumgr *polaris10_smu = NULL;
+
+	polaris10_smu = kzalloc(sizeof(struct polaris10_smumgr), GFP_KERNEL);
+
+	if (polaris10_smu == NULL)
+		return -1;
+
+	smumgr->backend = polaris10_smu;
+	smumgr->smumgr_funcs = &ellsemere_smu_funcs;
+
+	return 0;
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2015 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef _POLARIS10_SMUMANAGER_H
+#define _POLARIS10_SMUMANAGER_H
+
+#include <polaris10_ppsmc.h>
+#include <pp_endian.h>
+
+struct polaris10_avfs {
+	enum AVFS_BTC_STATUS avfs_btc_status;
+	uint32_t           avfs_btc_param;
+};
+
+struct polaris10_buffer_entry {
+	uint32_t data_size;
+	uint32_t mc_addr_low;
+	uint32_t mc_addr_high;
+	void *kaddr;
+	unsigned long  handle;
+};
+
+struct polaris10_smumgr {
+	uint8_t *header;
+	uint8_t *mec_image;
+	struct polaris10_buffer_entry smu_buffer;
+	struct polaris10_buffer_entry header_buffer;
+	uint32_t soft_regs_start;
+	uint8_t *read_rrm_straps;
+	uint32_t read_drm_straps_mc_address_high;
+	uint32_t read_drm_straps_mc_address_low;
+	uint32_t acpi_optimization;
+	bool post_initial_boot;
+	uint8_t protected_mode;
+	uint8_t security_hard_key;
+	struct polaris10_avfs  avfs;
+};
+
+
+int polaris10_smum_init(struct pp_smumgr *smumgr);
+
+int polaris10_read_smc_sram_dword(struct pp_smumgr *smumgr, uint32_t smc_addr, uint32_t *value, uint32_t limit);
+int polaris10_write_smc_sram_dword(struct pp_smumgr *smumgr, uint32_t smc_addr, uint32_t value, uint32_t limit);
+int polaris10_copy_bytes_to_smc(struct pp_smumgr *smumgr, uint32_t smc_start_address,
+				const uint8_t *src, uint32_t byte_count, uint32_t limit);
+
+#endif
+
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c	2016-07-24 15:23:50.000000000 -0400
@@ -30,6 +30,7 @@
 #include "cz_smumgr.h"
 #include "tonga_smumgr.h"
 #include "fiji_smumgr.h"
+#include "polaris10_smumgr.h"
 
 int smum_init(struct amd_pp_init *pp_init, struct pp_instance *handle)
 {
@@ -62,6 +63,10 @@ int smum_init(struct amd_pp_init *pp_ini
 		case CHIP_FIJI:
 			fiji_smum_init(smumgr);
 			break;
+		case CHIP_POLARIS11:
+		case CHIP_POLARIS10:
+			polaris10_smum_init(smumgr);
+			break;
 		default:
 			return -EINVAL;
 		}
@@ -76,6 +81,7 @@ int smum_init(struct amd_pp_init *pp_ini
 
 int smum_fini(struct pp_smumgr *smumgr)
 {
+	kfree(smumgr->device);
 	kfree(smumgr);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c	2016-07-24 15:23:50.000000000 -0400
@@ -145,7 +145,7 @@ out:
 
 int tonga_program_jump_on_start(struct pp_smumgr *smumgr)
 {
-	static unsigned char pData[] = { 0xE0, 0x00, 0x80, 0x40 };
+	static const unsigned char pData[] = { 0xE0, 0x00, 0x80, 0x40 };
 
 	tonga_copy_bytes_to_smc(smumgr, 0x0, pData, 4, sizeof(pData)+1);
 
@@ -328,10 +328,17 @@ int tonga_write_smc_sram_dword(struct pp
 
 static int tonga_smu_fini(struct pp_smumgr *smumgr)
 {
+	struct tonga_smumgr *priv = (struct tonga_smumgr *)(smumgr->backend);
+
+	smu_free_memory(smumgr->device, (void *)priv->smu_buffer.handle);
+	smu_free_memory(smumgr->device, (void *)priv->header_buffer.handle);
+
 	if (smumgr->backend != NULL) {
 		kfree(smumgr->backend);
 		smumgr->backend = NULL;
 	}
+
+	cgs_rel_firmware(smumgr->device, CGS_UCODE_ID_SMU);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c	2016-07-24 15:23:50.000000000 -0400
@@ -319,6 +319,48 @@ static bool amd_sched_entity_in(struct a
 	return added;
 }
 
+static void amd_sched_free_job(struct fence *f, struct fence_cb *cb) {
+	struct amd_sched_job *job = container_of(cb, struct amd_sched_job, cb_free_job);
+	schedule_work(&job->work_free_job);
+}
+
+/* job_finish is called after hw fence signaled, and
+ * the job had already been deleted from ring_mirror_list
+ */
+void amd_sched_job_finish(struct amd_sched_job *s_job)
+{
+	struct amd_sched_job *next;
+	struct amd_gpu_scheduler *sched = s_job->sched;
+
+	if (sched->timeout != MAX_SCHEDULE_TIMEOUT) {
+		if (cancel_delayed_work(&s_job->work_tdr))
+			amd_sched_job_put(s_job);
+
+		/* queue TDR for next job */
+		next = list_first_entry_or_null(&sched->ring_mirror_list,
+						struct amd_sched_job, node);
+
+		if (next) {
+			INIT_DELAYED_WORK(&next->work_tdr, s_job->timeout_callback);
+			amd_sched_job_get(next);
+			schedule_delayed_work(&next->work_tdr, sched->timeout);
+		}
+	}
+}
+
+void amd_sched_job_begin(struct amd_sched_job *s_job)
+{
+	struct amd_gpu_scheduler *sched = s_job->sched;
+
+	if (sched->timeout != MAX_SCHEDULE_TIMEOUT &&
+		list_first_entry_or_null(&sched->ring_mirror_list, struct amd_sched_job, node) == s_job)
+	{
+		INIT_DELAYED_WORK(&s_job->work_tdr, s_job->timeout_callback);
+		amd_sched_job_get(s_job);
+		schedule_delayed_work(&s_job->work_tdr, sched->timeout);
+	}
+}
+
 /**
  * Submit a job to the job queue
  *
@@ -330,11 +372,39 @@ void amd_sched_entity_push_job(struct am
 {
 	struct amd_sched_entity *entity = sched_job->s_entity;
 
+	sched_job->use_sched = 1;
+	fence_add_callback(&sched_job->s_fence->base,
+					&sched_job->cb_free_job, amd_sched_free_job);
 	trace_amd_sched_job(sched_job);
 	wait_event(entity->sched->job_scheduled,
 		   amd_sched_entity_in(sched_job));
 }
 
+/* init a sched_job with basic field */
+int amd_sched_job_init(struct amd_sched_job *job,
+						struct amd_gpu_scheduler *sched,
+						struct amd_sched_entity *entity,
+						void (*timeout_cb)(struct work_struct *work),
+						void (*free_cb)(struct kref *refcount),
+						void *owner, struct fence **fence)
+{
+	INIT_LIST_HEAD(&job->node);
+	kref_init(&job->refcount);
+	job->sched = sched;
+	job->s_entity = entity;
+	job->s_fence = amd_sched_fence_create(entity, owner);
+	if (!job->s_fence)
+		return -ENOMEM;
+
+	job->s_fence->s_job = job;
+	job->timeout_callback = timeout_cb;
+	job->free_callback = free_cb;
+
+	if (fence)
+		*fence = &job->s_fence->base;
+	return 0;
+}
+
 /**
  * Return ture if we can push more jobs to the hw.
  */
@@ -383,47 +453,26 @@ static void amd_sched_process_job(struct
 	unsigned long flags;
 
 	atomic_dec(&sched->hw_rq_count);
+
+	/* remove job from ring_mirror_list */
+	spin_lock_irqsave(&sched->job_list_lock, flags);
+	list_del_init(&s_fence->s_job->node);
+	sched->ops->finish_job(s_fence->s_job);
+	spin_unlock_irqrestore(&sched->job_list_lock, flags);
+
 	amd_sched_fence_signal(s_fence);
-	if (sched->timeout != MAX_SCHEDULE_TIMEOUT) {
-		cancel_delayed_work(&s_fence->dwork);
-		spin_lock_irqsave(&sched->fence_list_lock, flags);
-		list_del_init(&s_fence->list);
-		spin_unlock_irqrestore(&sched->fence_list_lock, flags);
-	}
+
 	trace_amd_sched_process_job(s_fence);
 	fence_put(&s_fence->base);
 	wake_up_interruptible(&sched->wake_up_worker);
 }
 
-static void amd_sched_fence_work_func(struct work_struct *work)
-{
-	struct amd_sched_fence *s_fence =
-		container_of(work, struct amd_sched_fence, dwork.work);
-	struct amd_gpu_scheduler *sched = s_fence->sched;
-	struct amd_sched_fence *entity, *tmp;
-	unsigned long flags;
-
-	DRM_ERROR("[%s] scheduler is timeout!\n", sched->name);
-
-	/* Clean all pending fences */
-	spin_lock_irqsave(&sched->fence_list_lock, flags);
-	list_for_each_entry_safe(entity, tmp, &sched->fence_list, list) {
-		DRM_ERROR("  fence no %d\n", entity->base.seqno);
-		cancel_delayed_work(&entity->dwork);
-		list_del_init(&entity->list);
-		fence_put(&entity->base);
-	}
-	spin_unlock_irqrestore(&sched->fence_list_lock, flags);
-}
-
 static int amd_sched_main(void *param)
 {
 	struct sched_param sparam = {.sched_priority = 1};
 	struct amd_gpu_scheduler *sched = (struct amd_gpu_scheduler *)param;
 	int r, count;
 
-	spin_lock_init(&sched->fence_list_lock);
-	INIT_LIST_HEAD(&sched->fence_list);
 	sched_setscheduler(current, SCHED_FIFO, &sparam);
 
 	while (!kthread_should_stop()) {
@@ -431,7 +480,6 @@ static int amd_sched_main(void *param)
 		struct amd_sched_fence *s_fence;
 		struct amd_sched_job *sched_job;
 		struct fence *fence;
-		unsigned long flags;
 
 		wait_event_interruptible(sched->wake_up_worker,
 			(entity = amd_sched_select_entity(sched)) ||
@@ -446,15 +494,8 @@ static int amd_sched_main(void *param)
 
 		s_fence = sched_job->s_fence;
 
-		if (sched->timeout != MAX_SCHEDULE_TIMEOUT) {
-			INIT_DELAYED_WORK(&s_fence->dwork, amd_sched_fence_work_func);
-			schedule_delayed_work(&s_fence->dwork, sched->timeout);
-			spin_lock_irqsave(&sched->fence_list_lock, flags);
-			list_add_tail(&s_fence->list, &sched->fence_list);
-			spin_unlock_irqrestore(&sched->fence_list_lock, flags);
-		}
-
 		atomic_inc(&sched->hw_rq_count);
+		amd_sched_job_pre_schedule(sched, sched_job);
 		fence = sched->ops->run_job(sched_job);
 		amd_sched_fence_scheduled(s_fence);
 		if (fence) {
@@ -489,7 +530,7 @@ static int amd_sched_main(void *param)
  * Return 0 on success, otherwise error code.
 */
 int amd_sched_init(struct amd_gpu_scheduler *sched,
-		   struct amd_sched_backend_ops *ops,
+		   const struct amd_sched_backend_ops *ops,
 		   unsigned hw_submission, long timeout, const char *name)
 {
 	int i;
@@ -502,6 +543,8 @@ int amd_sched_init(struct amd_gpu_schedu
 
 	init_waitqueue_head(&sched->wake_up_worker);
 	init_waitqueue_head(&sched->job_scheduled);
+	INIT_LIST_HEAD(&sched->ring_mirror_list);
+	spin_lock_init(&sched->job_list_lock);
 	atomic_set(&sched->hw_rq_count, 0);
 	if (atomic_inc_return(&sched_fence_slab_ref) == 1) {
 		sched_fence_slab = kmem_cache_create(
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h linux-libre-4.7-gnu/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h	2016-07-24 15:23:50.000000000 -0400
@@ -37,7 +37,7 @@ extern atomic_t sched_fence_slab_ref;
 
 /**
  * A scheduler entity is a wrapper around a job queue or a group
- * of other entities. Entities take turns emitting jobs from their 
+ * of other entities. Entities take turns emitting jobs from their
  * job queues to corresponding hardware ring based on scheduling
  * policy.
 */
@@ -74,14 +74,21 @@ struct amd_sched_fence {
 	struct amd_gpu_scheduler	*sched;
 	spinlock_t			lock;
 	void                            *owner;
-	struct delayed_work		dwork;
-	struct list_head		list;
+	struct amd_sched_job	*s_job;
 };
 
 struct amd_sched_job {
+	struct kref refcount;
 	struct amd_gpu_scheduler        *sched;
 	struct amd_sched_entity         *s_entity;
 	struct amd_sched_fence          *s_fence;
+	bool	use_sched;	/* true if the job goes to scheduler */
+	struct fence_cb                cb_free_job;
+	struct work_struct             work_free_job;
+	struct list_head			   node;
+	struct delayed_work work_tdr;
+	void (*timeout_callback) (struct work_struct *work);
+	void (*free_callback)(struct kref *refcount);
 };
 
 extern const struct fence_ops amd_sched_fence_ops;
@@ -102,6 +109,8 @@ static inline struct amd_sched_fence *to
 struct amd_sched_backend_ops {
 	struct fence *(*dependency)(struct amd_sched_job *sched_job);
 	struct fence *(*run_job)(struct amd_sched_job *sched_job);
+	void (*begin_job)(struct amd_sched_job *sched_job);
+	void (*finish_job)(struct amd_sched_job *sched_job);
 };
 
 enum amd_sched_priority {
@@ -114,7 +123,7 @@ enum amd_sched_priority {
  * One scheduler is implemented for each hardware ring
 */
 struct amd_gpu_scheduler {
-	struct amd_sched_backend_ops	*ops;
+	const struct amd_sched_backend_ops	*ops;
 	uint32_t			hw_submission_limit;
 	long				timeout;
 	const char			*name;
@@ -122,13 +131,13 @@ struct amd_gpu_scheduler {
 	wait_queue_head_t		wake_up_worker;
 	wait_queue_head_t		job_scheduled;
 	atomic_t			hw_rq_count;
-	struct list_head		fence_list;
-	spinlock_t			fence_list_lock;
 	struct task_struct		*thread;
+	struct list_head	ring_mirror_list;
+	spinlock_t			job_list_lock;
 };
 
 int amd_sched_init(struct amd_gpu_scheduler *sched,
-		   struct amd_sched_backend_ops *ops,
+		   const struct amd_sched_backend_ops *ops,
 		   uint32_t hw_submission, long timeout, const char *name);
 void amd_sched_fini(struct amd_gpu_scheduler *sched);
 
@@ -144,5 +153,24 @@ struct amd_sched_fence *amd_sched_fence_
 	struct amd_sched_entity *s_entity, void *owner);
 void amd_sched_fence_scheduled(struct amd_sched_fence *fence);
 void amd_sched_fence_signal(struct amd_sched_fence *fence);
+int amd_sched_job_init(struct amd_sched_job *job,
+					struct amd_gpu_scheduler *sched,
+					struct amd_sched_entity *entity,
+					void (*timeout_cb)(struct work_struct *work),
+					void (*free_cb)(struct kref* refcount),
+					void *owner, struct fence **fence);
+void amd_sched_job_pre_schedule(struct amd_gpu_scheduler *sched ,
+								struct amd_sched_job *s_job);
+void amd_sched_job_finish(struct amd_sched_job *s_job);
+void amd_sched_job_begin(struct amd_sched_job *s_job);
+static inline void amd_sched_job_get(struct amd_sched_job *job) {
+	if (job)
+		kref_get(&job->refcount);
+}
+
+static inline void amd_sched_job_put(struct amd_sched_job *job) {
+	if (job)
+		kref_put(&job->refcount, job->free_callback);
+}
 
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/amd/scheduler/sched_fence.c linux-libre-4.7-gnu/drivers/gpu/drm/amd/scheduler/sched_fence.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/amd/scheduler/sched_fence.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/amd/scheduler/sched_fence.c	2016-07-24 15:23:50.000000000 -0400
@@ -57,6 +57,16 @@ void amd_sched_fence_signal(struct amd_s
 		FENCE_TRACE(&fence->base, "was already signaled\n");
 }
 
+void amd_sched_job_pre_schedule(struct amd_gpu_scheduler *sched ,
+				struct amd_sched_job *s_job)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&sched->job_list_lock, flags);
+	list_add_tail(&s_job->node, &sched->ring_mirror_list);
+	sched->ops->begin_job(s_job);
+	spin_unlock_irqrestore(&sched->job_list_lock, flags);
+}
+
 void amd_sched_fence_scheduled(struct amd_sched_fence *s_fence)
 {
 	struct fence_cb *cur, *tmp;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/arc/arcpgu_crtc.c linux-libre-4.7-gnu/drivers/gpu/drm/arc/arcpgu_crtc.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/arc/arcpgu_crtc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/arc/arcpgu_crtc.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,257 @@
+/*
+ * ARC PGU DRM driver.
+ *
+ * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ */
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_plane_helper.h>
+#include <linux/clk.h>
+#include <linux/platform_data/simplefb.h>
+
+#include "arcpgu.h"
+#include "arcpgu_regs.h"
+
+#define ENCODE_PGU_XY(x, y)	((((x) - 1) << 16) | ((y) - 1))
+
+static struct simplefb_format supported_formats[] = {
+	{ "r5g6b5", 16, {11, 5}, {5, 6}, {0, 5}, {0, 0}, DRM_FORMAT_RGB565 },
+	{ "r8g8b8", 24, {16, 8}, {8, 8}, {0, 8}, {0, 0}, DRM_FORMAT_RGB888 },
+};
+
+static void arc_pgu_set_pxl_fmt(struct drm_crtc *crtc)
+{
+	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
+	uint32_t pixel_format = crtc->primary->state->fb->pixel_format;
+	struct simplefb_format *format = NULL;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(supported_formats); i++) {
+		if (supported_formats[i].fourcc == pixel_format)
+			format = &supported_formats[i];
+	}
+
+	if (WARN_ON(!format))
+		return;
+
+	if (format->fourcc == DRM_FORMAT_RGB888)
+		arc_pgu_write(arcpgu, ARCPGU_REG_CTRL,
+			      arc_pgu_read(arcpgu, ARCPGU_REG_CTRL) |
+					   ARCPGU_MODE_RGB888_MASK);
+
+}
+
+static const struct drm_crtc_funcs arc_pgu_crtc_funcs = {
+	.destroy = drm_crtc_cleanup,
+	.set_config = drm_atomic_helper_set_config,
+	.page_flip = drm_atomic_helper_page_flip,
+	.reset = drm_atomic_helper_crtc_reset,
+	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+};
+
+static void arc_pgu_crtc_mode_set_nofb(struct drm_crtc *crtc)
+{
+	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
+	struct drm_display_mode *m = &crtc->state->adjusted_mode;
+	u32 val;
+
+	arc_pgu_write(arcpgu, ARCPGU_REG_FMT,
+		      ENCODE_PGU_XY(m->crtc_htotal, m->crtc_vtotal));
+
+	arc_pgu_write(arcpgu, ARCPGU_REG_HSYNC,
+		      ENCODE_PGU_XY(m->crtc_hsync_start - m->crtc_hdisplay,
+				    m->crtc_hsync_end - m->crtc_hdisplay));
+
+	arc_pgu_write(arcpgu, ARCPGU_REG_VSYNC,
+		      ENCODE_PGU_XY(m->crtc_vsync_start - m->crtc_vdisplay,
+				    m->crtc_vsync_end - m->crtc_vdisplay));
+
+	arc_pgu_write(arcpgu, ARCPGU_REG_ACTIVE,
+		      ENCODE_PGU_XY(m->crtc_hblank_end - m->crtc_hblank_start,
+				    m->crtc_vblank_end - m->crtc_vblank_start));
+
+	val = arc_pgu_read(arcpgu, ARCPGU_REG_CTRL);
+
+	if (m->flags & DRM_MODE_FLAG_PVSYNC)
+		val |= ARCPGU_CTRL_VS_POL_MASK << ARCPGU_CTRL_VS_POL_OFST;
+	else
+		val &= ~(ARCPGU_CTRL_VS_POL_MASK << ARCPGU_CTRL_VS_POL_OFST);
+
+	if (m->flags & DRM_MODE_FLAG_PHSYNC)
+		val |= ARCPGU_CTRL_HS_POL_MASK << ARCPGU_CTRL_HS_POL_OFST;
+	else
+		val &= ~(ARCPGU_CTRL_HS_POL_MASK << ARCPGU_CTRL_HS_POL_OFST);
+
+	arc_pgu_write(arcpgu, ARCPGU_REG_CTRL, val);
+	arc_pgu_write(arcpgu, ARCPGU_REG_STRIDE, 0);
+	arc_pgu_write(arcpgu, ARCPGU_REG_START_SET, 1);
+
+	arc_pgu_set_pxl_fmt(crtc);
+
+	clk_set_rate(arcpgu->clk, m->crtc_clock * 1000);
+}
+
+static void arc_pgu_crtc_enable(struct drm_crtc *crtc)
+{
+	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
+
+	clk_prepare_enable(arcpgu->clk);
+	arc_pgu_write(arcpgu, ARCPGU_REG_CTRL,
+		      arc_pgu_read(arcpgu, ARCPGU_REG_CTRL) |
+		      ARCPGU_CTRL_ENABLE_MASK);
+}
+
+static void arc_pgu_crtc_disable(struct drm_crtc *crtc)
+{
+	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
+
+	if (!crtc->primary->fb)
+		return;
+
+	clk_disable_unprepare(arcpgu->clk);
+	arc_pgu_write(arcpgu, ARCPGU_REG_CTRL,
+			      arc_pgu_read(arcpgu, ARCPGU_REG_CTRL) &
+			      ~ARCPGU_CTRL_ENABLE_MASK);
+}
+
+static int arc_pgu_crtc_atomic_check(struct drm_crtc *crtc,
+				     struct drm_crtc_state *state)
+{
+	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
+	struct drm_display_mode *mode = &state->adjusted_mode;
+	long rate, clk_rate = mode->clock * 1000;
+
+	rate = clk_round_rate(arcpgu->clk, clk_rate);
+	if (rate != clk_rate)
+		return -EINVAL;
+
+	return 0;
+}
+
+static void arc_pgu_crtc_atomic_begin(struct drm_crtc *crtc,
+				      struct drm_crtc_state *state)
+{
+	struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc);
+	unsigned long flags;
+
+	if (crtc->state->event) {
+		struct drm_pending_vblank_event *event = crtc->state->event;
+
+		crtc->state->event = NULL;
+		event->pipe = drm_crtc_index(crtc);
+
+		WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+
+		spin_lock_irqsave(&crtc->dev->event_lock, flags);
+		list_add_tail(&event->base.link, &arcpgu->event_list);
+		spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+	}
+}
+
+static const struct drm_crtc_helper_funcs arc_pgu_crtc_helper_funcs = {
+	.mode_set	= drm_helper_crtc_mode_set,
+	.mode_set_base	= drm_helper_crtc_mode_set_base,
+	.mode_set_nofb	= arc_pgu_crtc_mode_set_nofb,
+	.enable		= arc_pgu_crtc_enable,
+	.disable	= arc_pgu_crtc_disable,
+	.prepare	= arc_pgu_crtc_disable,
+	.commit		= arc_pgu_crtc_enable,
+	.atomic_check	= arc_pgu_crtc_atomic_check,
+	.atomic_begin	= arc_pgu_crtc_atomic_begin,
+};
+
+static void arc_pgu_plane_atomic_update(struct drm_plane *plane,
+					struct drm_plane_state *state)
+{
+	struct arcpgu_drm_private *arcpgu;
+	struct drm_gem_cma_object *gem;
+
+	if (!plane->state->crtc || !plane->state->fb)
+		return;
+
+	arcpgu = crtc_to_arcpgu_priv(plane->state->crtc);
+	gem = drm_fb_cma_get_gem_obj(plane->state->fb, 0);
+	arc_pgu_write(arcpgu, ARCPGU_REG_BUF0_ADDR, gem->paddr);
+}
+
+static const struct drm_plane_helper_funcs arc_pgu_plane_helper_funcs = {
+	.prepare_fb = NULL,
+	.cleanup_fb = NULL,
+	.atomic_update = arc_pgu_plane_atomic_update,
+};
+
+static void arc_pgu_plane_destroy(struct drm_plane *plane)
+{
+	drm_plane_helper_disable(plane);
+	drm_plane_cleanup(plane);
+}
+
+static const struct drm_plane_funcs arc_pgu_plane_funcs = {
+	.update_plane		= drm_atomic_helper_update_plane,
+	.disable_plane		= drm_atomic_helper_disable_plane,
+	.destroy		= arc_pgu_plane_destroy,
+	.reset			= drm_atomic_helper_plane_reset,
+	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+	.atomic_destroy_state	= drm_atomic_helper_plane_destroy_state,
+};
+
+static struct drm_plane *arc_pgu_plane_init(struct drm_device *drm)
+{
+	struct arcpgu_drm_private *arcpgu = drm->dev_private;
+	struct drm_plane *plane = NULL;
+	u32 formats[ARRAY_SIZE(supported_formats)], i;
+	int ret;
+
+	plane = devm_kzalloc(drm->dev, sizeof(*plane), GFP_KERNEL);
+	if (!plane)
+		return ERR_PTR(-ENOMEM);
+
+	for (i = 0; i < ARRAY_SIZE(supported_formats); i++)
+		formats[i] = supported_formats[i].fourcc;
+
+	ret = drm_universal_plane_init(drm, plane, 0xff, &arc_pgu_plane_funcs,
+				       formats, ARRAY_SIZE(formats),
+				       DRM_PLANE_TYPE_PRIMARY, NULL);
+	if (ret)
+		return ERR_PTR(ret);
+
+	drm_plane_helper_add(plane, &arc_pgu_plane_helper_funcs);
+	arcpgu->plane = plane;
+
+	return plane;
+}
+
+int arc_pgu_setup_crtc(struct drm_device *drm)
+{
+	struct arcpgu_drm_private *arcpgu = drm->dev_private;
+	struct drm_plane *primary;
+	int ret;
+
+	primary = arc_pgu_plane_init(drm);
+	if (IS_ERR(primary))
+		return PTR_ERR(primary);
+
+	ret = drm_crtc_init_with_planes(drm, &arcpgu->crtc, primary, NULL,
+					&arc_pgu_crtc_funcs, NULL);
+	if (ret) {
+		arc_pgu_plane_destroy(primary);
+		return ret;
+	}
+
+	drm_crtc_helper_add(&arcpgu->crtc, &arc_pgu_crtc_helper_funcs);
+	return 0;
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/arc/arcpgu_drv.c linux-libre-4.7-gnu/drivers/gpu/drm/arc/arcpgu_drv.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/arc/arcpgu_drv.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/arc/arcpgu_drv.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,288 @@
+/*
+ * ARC PGU DRM driver.
+ *
+ * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/clk.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_atomic_helper.h>
+#include <linux/of_reserved_mem.h>
+
+#include "arcpgu.h"
+#include "arcpgu_regs.h"
+
+static void arcpgu_fb_output_poll_changed(struct drm_device *dev)
+{
+	struct arcpgu_drm_private *arcpgu = dev->dev_private;
+
+	if (arcpgu->fbdev)
+		drm_fbdev_cma_hotplug_event(arcpgu->fbdev);
+}
+
+static int arcpgu_atomic_commit(struct drm_device *dev,
+				    struct drm_atomic_state *state, bool async)
+{
+	return drm_atomic_helper_commit(dev, state, false);
+}
+
+static struct drm_mode_config_funcs arcpgu_drm_modecfg_funcs = {
+	.fb_create  = drm_fb_cma_create,
+	.output_poll_changed = arcpgu_fb_output_poll_changed,
+	.atomic_check = drm_atomic_helper_check,
+	.atomic_commit = arcpgu_atomic_commit,
+};
+
+static void arcpgu_setup_mode_config(struct drm_device *drm)
+{
+	drm_mode_config_init(drm);
+	drm->mode_config.min_width = 0;
+	drm->mode_config.min_height = 0;
+	drm->mode_config.max_width = 1920;
+	drm->mode_config.max_height = 1080;
+	drm->mode_config.funcs = &arcpgu_drm_modecfg_funcs;
+}
+
+int arcpgu_gem_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+	int ret;
+
+	ret = drm_gem_mmap(filp, vma);
+	if (ret)
+		return ret;
+
+	vma->vm_page_prot = pgprot_noncached(vm_get_page_prot(vma->vm_flags));
+	return 0;
+}
+
+static const struct file_operations arcpgu_drm_ops = {
+	.owner = THIS_MODULE,
+	.open = drm_open,
+	.release = drm_release,
+	.unlocked_ioctl = drm_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = drm_compat_ioctl,
+#endif
+	.poll = drm_poll,
+	.read = drm_read,
+	.llseek = no_llseek,
+	.mmap = arcpgu_gem_mmap,
+};
+
+static void arcpgu_preclose(struct drm_device *drm, struct drm_file *file)
+{
+	struct arcpgu_drm_private *arcpgu = drm->dev_private;
+	struct drm_pending_vblank_event *e, *t;
+	unsigned long flags;
+
+	spin_lock_irqsave(&drm->event_lock, flags);
+	list_for_each_entry_safe(e, t, &arcpgu->event_list, base.link) {
+		if (e->base.file_priv != file)
+			continue;
+		list_del(&e->base.link);
+		e->base.destroy(&e->base);
+	}
+	spin_unlock_irqrestore(&drm->event_lock, flags);
+}
+
+static void arcpgu_lastclose(struct drm_device *drm)
+{
+	struct arcpgu_drm_private *arcpgu = drm->dev_private;
+
+	drm_fbdev_cma_restore_mode(arcpgu->fbdev);
+}
+
+static int arcpgu_load(struct drm_device *drm)
+{
+	struct platform_device *pdev = to_platform_device(drm->dev);
+	struct arcpgu_drm_private *arcpgu;
+	struct device_node *encoder_node;
+	struct resource *res;
+	int ret;
+
+	arcpgu = devm_kzalloc(&pdev->dev, sizeof(*arcpgu), GFP_KERNEL);
+	if (arcpgu == NULL)
+		return -ENOMEM;
+
+	drm->dev_private = arcpgu;
+
+	arcpgu->clk = devm_clk_get(drm->dev, "pxlclk");
+	if (IS_ERR(arcpgu->clk))
+		return PTR_ERR(arcpgu->clk);
+
+	INIT_LIST_HEAD(&arcpgu->event_list);
+
+	arcpgu_setup_mode_config(drm);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	arcpgu->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(arcpgu->regs)) {
+		dev_err(drm->dev, "Could not remap IO mem\n");
+		return PTR_ERR(arcpgu->regs);
+	}
+
+	dev_info(drm->dev, "arc_pgu ID: 0x%x\n",
+		 arc_pgu_read(arcpgu, ARCPGU_REG_ID));
+
+	/* Get the optional framebuffer memory resource */
+	ret = of_reserved_mem_device_init(drm->dev);
+	if (ret && ret != -ENODEV)
+		return ret;
+
+	if (dma_set_mask_and_coherent(drm->dev, DMA_BIT_MASK(32)))
+		return -ENODEV;
+
+	if (arc_pgu_setup_crtc(drm) < 0)
+		return -ENODEV;
+
+	/* find the encoder node and initialize it */
+	encoder_node = of_parse_phandle(drm->dev->of_node, "encoder-slave", 0);
+	if (!encoder_node) {
+		dev_err(drm->dev, "failed to get an encoder slave node\n");
+		return -ENODEV;
+	}
+
+	ret = arcpgu_drm_hdmi_init(drm, encoder_node);
+	if (ret < 0)
+		return ret;
+
+	drm_mode_config_reset(drm);
+	drm_kms_helper_poll_init(drm);
+
+	arcpgu->fbdev = drm_fbdev_cma_init(drm, 16,
+					      drm->mode_config.num_crtc,
+					      drm->mode_config.num_connector);
+	if (IS_ERR(arcpgu->fbdev)) {
+		ret = PTR_ERR(arcpgu->fbdev);
+		arcpgu->fbdev = NULL;
+		return -ENODEV;
+	}
+
+	platform_set_drvdata(pdev, arcpgu);
+	return 0;
+}
+
+int arcpgu_unload(struct drm_device *drm)
+{
+	struct arcpgu_drm_private *arcpgu = drm->dev_private;
+
+	if (arcpgu->fbdev) {
+		drm_fbdev_cma_fini(arcpgu->fbdev);
+		arcpgu->fbdev = NULL;
+	}
+	drm_kms_helper_poll_fini(drm);
+	drm_vblank_cleanup(drm);
+	drm_mode_config_cleanup(drm);
+
+	return 0;
+}
+
+static struct drm_driver arcpgu_drm_driver = {
+	.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
+			   DRIVER_ATOMIC,
+	.preclose = arcpgu_preclose,
+	.lastclose = arcpgu_lastclose,
+	.name = "drm-arcpgu",
+	.desc = "ARC PGU Controller",
+	.date = "20160219",
+	.major = 1,
+	.minor = 0,
+	.patchlevel = 0,
+	.fops = &arcpgu_drm_ops,
+	.dumb_create = drm_gem_cma_dumb_create,
+	.dumb_map_offset = drm_gem_cma_dumb_map_offset,
+	.dumb_destroy = drm_gem_dumb_destroy,
+	.get_vblank_counter = drm_vblank_no_hw_counter,
+	.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
+	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
+	.gem_free_object = drm_gem_cma_free_object,
+	.gem_vm_ops = &drm_gem_cma_vm_ops,
+	.gem_prime_export = drm_gem_prime_export,
+	.gem_prime_import = drm_gem_prime_import,
+	.gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
+	.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
+	.gem_prime_vmap = drm_gem_cma_prime_vmap,
+	.gem_prime_vunmap = drm_gem_cma_prime_vunmap,
+	.gem_prime_mmap = drm_gem_cma_prime_mmap,
+};
+
+static int arcpgu_probe(struct platform_device *pdev)
+{
+	struct drm_device *drm;
+	int ret;
+
+	drm = drm_dev_alloc(&arcpgu_drm_driver, &pdev->dev);
+	if (!drm)
+		return -ENOMEM;
+
+	ret = arcpgu_load(drm);
+	if (ret)
+		goto err_unref;
+
+	ret = drm_dev_register(drm, 0);
+	if (ret)
+		goto err_unload;
+
+	ret = drm_connector_register_all(drm);
+	if (ret)
+		goto err_unregister;
+
+	return 0;
+
+err_unregister:
+	drm_dev_unregister(drm);
+
+err_unload:
+	arcpgu_unload(drm);
+
+err_unref:
+	drm_dev_unref(drm);
+
+	return ret;
+}
+
+static int arcpgu_remove(struct platform_device *pdev)
+{
+	struct drm_device *drm = platform_get_drvdata(pdev);
+
+	drm_connector_unregister_all(drm);
+	drm_dev_unregister(drm);
+	arcpgu_unload(drm);
+	drm_dev_unref(drm);
+
+	return 0;
+}
+
+static const struct of_device_id arcpgu_of_table[] = {
+	{.compatible = "snps,arcpgu"},
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, arcpgu_of_table);
+
+static struct platform_driver arcpgu_platform_driver = {
+	.probe = arcpgu_probe,
+	.remove = arcpgu_remove,
+	.driver = {
+		   .name = "arcpgu",
+		   .of_match_table = arcpgu_of_table,
+		   },
+};
+
+module_platform_driver(arcpgu_platform_driver);
+
+MODULE_AUTHOR("Carlos Palminha <palminha@synopsys.com>");
+MODULE_DESCRIPTION("ARC PGU DRM driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/arc/arcpgu.h linux-libre-4.7-gnu/drivers/gpu/drm/arc/arcpgu.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/arc/arcpgu.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/arc/arcpgu.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,50 @@
+/*
+ * ARC PGU DRM driver.
+ *
+ * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ */
+
+#ifndef _ARCPGU_H_
+#define _ARCPGU_H_
+
+struct arcpgu_drm_private {
+	void __iomem		*regs;
+	struct clk		*clk;
+	struct drm_fbdev_cma	*fbdev;
+	struct drm_framebuffer	*fb;
+	struct list_head	event_list;
+	struct drm_crtc		crtc;
+	struct drm_plane	*plane;
+};
+
+#define crtc_to_arcpgu_priv(x) container_of(x, struct arcpgu_drm_private, crtc)
+
+static inline void arc_pgu_write(struct arcpgu_drm_private *arcpgu,
+				 unsigned int reg, u32 value)
+{
+	iowrite32(value, arcpgu->regs + reg);
+}
+
+static inline u32 arc_pgu_read(struct arcpgu_drm_private *arcpgu,
+			       unsigned int reg)
+{
+	return ioread32(arcpgu->regs + reg);
+}
+
+int arc_pgu_setup_crtc(struct drm_device *dev);
+int arcpgu_drm_hdmi_init(struct drm_device *drm, struct device_node *np);
+struct drm_fbdev_cma *arcpgu_fbdev_cma_init(struct drm_device *dev,
+	unsigned int preferred_bpp, unsigned int num_crtc,
+	unsigned int max_conn_count);
+
+#endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/arc/arcpgu_hdmi.c linux-libre-4.7-gnu/drivers/gpu/drm/arc/arcpgu_hdmi.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/arc/arcpgu_hdmi.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/arc/arcpgu_hdmi.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,201 @@
+/*
+ * ARC PGU DRM driver.
+ *
+ * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ */
+
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_encoder_slave.h>
+#include <drm/drm_atomic_helper.h>
+
+#include "arcpgu.h"
+
+struct arcpgu_drm_connector {
+	struct drm_connector connector;
+	struct drm_encoder_slave *encoder_slave;
+};
+
+static int arcpgu_drm_connector_get_modes(struct drm_connector *connector)
+{
+	const struct drm_encoder_slave_funcs *sfuncs;
+	struct drm_encoder_slave *slave;
+	struct arcpgu_drm_connector *con =
+		container_of(connector, struct arcpgu_drm_connector, connector);
+
+	slave = con->encoder_slave;
+	if (slave == NULL) {
+		dev_err(connector->dev->dev,
+			"connector_get_modes: cannot find slave encoder for connector\n");
+		return 0;
+	}
+
+	sfuncs = slave->slave_funcs;
+	if (sfuncs->get_modes == NULL)
+		return 0;
+
+	return sfuncs->get_modes(&slave->base, connector);
+}
+
+struct drm_encoder *
+arcpgu_drm_connector_best_encoder(struct drm_connector *connector)
+{
+	struct drm_encoder_slave *slave;
+	struct arcpgu_drm_connector *con =
+		container_of(connector, struct arcpgu_drm_connector, connector);
+
+	slave = con->encoder_slave;
+	if (slave == NULL) {
+		dev_err(connector->dev->dev,
+			"connector_best_encoder: cannot find slave encoder for connector\n");
+		return NULL;
+	}
+
+	return &slave->base;
+}
+
+static enum drm_connector_status
+arcpgu_drm_connector_detect(struct drm_connector *connector, bool force)
+{
+	enum drm_connector_status status = connector_status_unknown;
+	const struct drm_encoder_slave_funcs *sfuncs;
+	struct drm_encoder_slave *slave;
+
+	struct arcpgu_drm_connector *con =
+		container_of(connector, struct arcpgu_drm_connector, connector);
+
+	slave = con->encoder_slave;
+	if (slave == NULL) {
+		dev_err(connector->dev->dev,
+			"connector_detect: cannot find slave encoder for connector\n");
+		return status;
+	}
+
+	sfuncs = slave->slave_funcs;
+	if (sfuncs && sfuncs->detect)
+		return sfuncs->detect(&slave->base, connector);
+
+	dev_err(connector->dev->dev, "connector_detect: could not detect slave funcs\n");
+	return status;
+}
+
+static void arcpgu_drm_connector_destroy(struct drm_connector *connector)
+{
+	drm_connector_unregister(connector);
+	drm_connector_cleanup(connector);
+}
+
+static const struct drm_connector_helper_funcs
+arcpgu_drm_connector_helper_funcs = {
+	.get_modes = arcpgu_drm_connector_get_modes,
+	.best_encoder = arcpgu_drm_connector_best_encoder,
+};
+
+static const struct drm_connector_funcs arcpgu_drm_connector_funcs = {
+	.dpms = drm_helper_connector_dpms,
+	.reset = drm_atomic_helper_connector_reset,
+	.detect = arcpgu_drm_connector_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = arcpgu_drm_connector_destroy,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static struct drm_encoder_helper_funcs arcpgu_drm_encoder_helper_funcs = {
+	.dpms = drm_i2c_encoder_dpms,
+	.mode_fixup = drm_i2c_encoder_mode_fixup,
+	.mode_set = drm_i2c_encoder_mode_set,
+	.prepare = drm_i2c_encoder_prepare,
+	.commit = drm_i2c_encoder_commit,
+	.detect = drm_i2c_encoder_detect,
+};
+
+static struct drm_encoder_funcs arcpgu_drm_encoder_funcs = {
+	.destroy = drm_encoder_cleanup,
+};
+
+int arcpgu_drm_hdmi_init(struct drm_device *drm, struct device_node *np)
+{
+	struct arcpgu_drm_connector *arcpgu_connector;
+	struct drm_i2c_encoder_driver *driver;
+	struct drm_encoder_slave *encoder;
+	struct drm_connector *connector;
+	struct i2c_client *i2c_slave;
+	int ret;
+
+	encoder = devm_kzalloc(drm->dev, sizeof(*encoder), GFP_KERNEL);
+	if (encoder == NULL)
+		return -ENOMEM;
+
+	i2c_slave = of_find_i2c_device_by_node(np);
+	if (!i2c_slave || !i2c_get_clientdata(i2c_slave)) {
+		dev_err(drm->dev, "failed to find i2c slave encoder\n");
+		return -EPROBE_DEFER;
+	}
+
+	if (i2c_slave->dev.driver == NULL) {
+		dev_err(drm->dev, "failed to find i2c slave driver\n");
+		return -EPROBE_DEFER;
+	}
+
+	driver =
+	    to_drm_i2c_encoder_driver(to_i2c_driver(i2c_slave->dev.driver));
+	ret = driver->encoder_init(i2c_slave, drm, encoder);
+	if (ret) {
+		dev_err(drm->dev, "failed to initialize i2c encoder slave\n");
+		return ret;
+	}
+
+	encoder->base.possible_crtcs = 1;
+	encoder->base.possible_clones = 0;
+	ret = drm_encoder_init(drm, &encoder->base, &arcpgu_drm_encoder_funcs,
+			       DRM_MODE_ENCODER_TMDS, NULL);
+	if (ret)
+		return ret;
+
+	drm_encoder_helper_add(&encoder->base,
+			       &arcpgu_drm_encoder_helper_funcs);
+
+	arcpgu_connector = devm_kzalloc(drm->dev, sizeof(*arcpgu_connector),
+					GFP_KERNEL);
+	if (!arcpgu_connector) {
+		ret = -ENOMEM;
+		goto error_encoder_cleanup;
+	}
+
+	connector = &arcpgu_connector->connector;
+	drm_connector_helper_add(connector, &arcpgu_drm_connector_helper_funcs);
+	ret = drm_connector_init(drm, connector, &arcpgu_drm_connector_funcs,
+			DRM_MODE_CONNECTOR_HDMIA);
+	if (ret < 0) {
+		dev_err(drm->dev, "failed to initialize drm connector\n");
+		goto error_encoder_cleanup;
+	}
+
+	ret = drm_mode_connector_attach_encoder(connector, &encoder->base);
+	if (ret < 0) {
+		dev_err(drm->dev, "could not attach connector to encoder\n");
+		drm_connector_unregister(connector);
+		goto error_connector_cleanup;
+	}
+
+	arcpgu_connector->encoder_slave = encoder;
+
+	return 0;
+
+error_connector_cleanup:
+	drm_connector_cleanup(connector);
+
+error_encoder_cleanup:
+	drm_encoder_cleanup(&encoder->base);
+	return ret;
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/arc/arcpgu_regs.h linux-libre-4.7-gnu/drivers/gpu/drm/arc/arcpgu_regs.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/arc/arcpgu_regs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/arc/arcpgu_regs.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,40 @@
+/*
+ * ARC PGU DRM driver.
+ *
+ * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ */
+
+#ifndef _ARC_PGU_REGS_H_
+#define _ARC_PGU_REGS_H_
+
+#define ARCPGU_REG_CTRL		0x00
+#define ARCPGU_REG_STAT		0x04
+#define ARCPGU_REG_FMT		0x10
+#define ARCPGU_REG_HSYNC	0x14
+#define ARCPGU_REG_VSYNC	0x18
+#define ARCPGU_REG_ACTIVE	0x1c
+#define ARCPGU_REG_BUF0_ADDR	0x40
+#define ARCPGU_REG_STRIDE	0x50
+#define ARCPGU_REG_START_SET	0x84
+
+#define ARCPGU_REG_ID		0x3FC
+
+#define ARCPGU_CTRL_ENABLE_MASK	0x02
+#define ARCPGU_CTRL_VS_POL_MASK	0x1
+#define ARCPGU_CTRL_VS_POL_OFST	0x3
+#define ARCPGU_CTRL_HS_POL_MASK	0x1
+#define ARCPGU_CTRL_HS_POL_OFST	0x4
+#define ARCPGU_MODE_RGB888_MASK	0x04
+#define ARCPGU_STAT_BUSY_MASK	0x02
+
+#endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/arc/Kconfig linux-libre-4.7-gnu/drivers/gpu/drm/arc/Kconfig
--- linux-libre-4.6-gnu/drivers/gpu/drm/arc/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/arc/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,10 @@
+config DRM_ARCPGU
+	tristate "ARC PGU"
+	depends on DRM && OF
+	select DRM_KMS_CMA_HELPER
+	select DRM_KMS_FB_HELPER
+	select DRM_KMS_HELPER
+	help
+	  Choose this option if you have an ARC PGU controller.
+
+	  If M is selected the module will be called arcpgu.
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/arc/Makefile linux-libre-4.7-gnu/drivers/gpu/drm/arc/Makefile
--- linux-libre-4.6-gnu/drivers/gpu/drm/arc/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/arc/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,2 @@
+arcpgu-y := arcpgu_crtc.o arcpgu_hdmi.o arcpgu_drv.o
+obj-$(CONFIG_DRM_ARCPGU) += arcpgu.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/arm/hdlcd_crtc.c linux-libre-4.7-gnu/drivers/gpu/drm/arm/hdlcd_crtc.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/arm/hdlcd_crtc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/arm/hdlcd_crtc.c	2016-07-24 15:23:50.000000000 -0400
@@ -33,8 +33,17 @@
  *
  */
 
+static void hdlcd_crtc_cleanup(struct drm_crtc *crtc)
+{
+	struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
+
+	/* stop the controller on cleanup */
+	hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 0);
+	drm_crtc_cleanup(crtc);
+}
+
 static const struct drm_crtc_funcs hdlcd_crtc_funcs = {
-	.destroy = drm_crtc_cleanup,
+	.destroy = hdlcd_crtc_cleanup,
 	.set_config = drm_atomic_helper_set_config,
 	.page_flip = drm_atomic_helper_page_flip,
 	.reset = drm_atomic_helper_crtc_reset,
@@ -97,7 +106,7 @@ static void hdlcd_crtc_mode_set_nofb(str
 	struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
 	struct drm_display_mode *m = &crtc->state->adjusted_mode;
 	struct videomode vm;
-	unsigned int polarities, line_length, err;
+	unsigned int polarities, err;
 
 	vm.vfront_porch = m->crtc_vsync_start - m->crtc_vdisplay;
 	vm.vback_porch = m->crtc_vtotal - m->crtc_vsync_end;
@@ -113,23 +122,18 @@ static void hdlcd_crtc_mode_set_nofb(str
 	if (m->flags & DRM_MODE_FLAG_PVSYNC)
 		polarities |= HDLCD_POLARITY_VSYNC;
 
-	line_length = crtc->primary->state->fb->pitches[0];
-
 	/* Allow max number of outstanding requests and largest burst size */
 	hdlcd_write(hdlcd, HDLCD_REG_BUS_OPTIONS,
 		    HDLCD_BUS_MAX_OUTSTAND | HDLCD_BUS_BURST_16);
 
-	hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, line_length);
-	hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_PITCH, line_length);
-	hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_COUNT, m->crtc_vdisplay - 1);
 	hdlcd_write(hdlcd, HDLCD_REG_V_DATA, m->crtc_vdisplay - 1);
 	hdlcd_write(hdlcd, HDLCD_REG_V_BACK_PORCH, vm.vback_porch - 1);
 	hdlcd_write(hdlcd, HDLCD_REG_V_FRONT_PORCH, vm.vfront_porch - 1);
 	hdlcd_write(hdlcd, HDLCD_REG_V_SYNC, vm.vsync_len - 1);
+	hdlcd_write(hdlcd, HDLCD_REG_H_DATA, m->crtc_hdisplay - 1);
 	hdlcd_write(hdlcd, HDLCD_REG_H_BACK_PORCH, vm.hback_porch - 1);
 	hdlcd_write(hdlcd, HDLCD_REG_H_FRONT_PORCH, vm.hfront_porch - 1);
 	hdlcd_write(hdlcd, HDLCD_REG_H_SYNC, vm.hsync_len - 1);
-	hdlcd_write(hdlcd, HDLCD_REG_H_DATA, m->crtc_hdisplay - 1);
 	hdlcd_write(hdlcd, HDLCD_REG_POLARITIES, polarities);
 
 	err = hdlcd_set_pxl_fmt(crtc);
@@ -144,20 +148,19 @@ static void hdlcd_crtc_enable(struct drm
 	struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
 
 	clk_prepare_enable(hdlcd->clk);
+	hdlcd_crtc_mode_set_nofb(crtc);
 	hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 1);
-	drm_crtc_vblank_on(crtc);
 }
 
 static void hdlcd_crtc_disable(struct drm_crtc *crtc)
 {
 	struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
 
-	if (!crtc->primary->fb)
+	if (!crtc->state->active)
 		return;
 
-	clk_disable_unprepare(hdlcd->clk);
 	hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 0);
-	drm_crtc_vblank_off(crtc);
+	clk_disable_unprepare(hdlcd->clk);
 }
 
 static int hdlcd_crtc_atomic_check(struct drm_crtc *crtc,
@@ -179,20 +182,17 @@ static int hdlcd_crtc_atomic_check(struc
 static void hdlcd_crtc_atomic_begin(struct drm_crtc *crtc,
 				    struct drm_crtc_state *state)
 {
-	struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc);
-	unsigned long flags;
-
-	if (crtc->state->event) {
-		struct drm_pending_vblank_event *event = crtc->state->event;
+	struct drm_pending_vblank_event *event = crtc->state->event;
 
+	if (event) {
 		crtc->state->event = NULL;
-		event->pipe = drm_crtc_index(crtc);
 
-		WARN_ON(drm_crtc_vblank_get(crtc) != 0);
-
-		spin_lock_irqsave(&crtc->dev->event_lock, flags);
-		list_add_tail(&event->base.link, &hdlcd->event_list);
-		spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+		spin_lock_irq(&crtc->dev->event_lock);
+		if (drm_crtc_vblank_get(crtc) == 0)
+			drm_crtc_arm_vblank_event(crtc, event);
+		else
+			drm_crtc_send_vblank_event(crtc, event);
+		spin_unlock_irq(&crtc->dev->event_lock);
 	}
 }
 
@@ -225,6 +225,15 @@ static const struct drm_crtc_helper_func
 static int hdlcd_plane_atomic_check(struct drm_plane *plane,
 				    struct drm_plane_state *state)
 {
+	u32 src_w, src_h;
+
+	src_w = state->src_w >> 16;
+	src_h = state->src_h >> 16;
+
+	/* we can't do any scaling of the plane source */
+	if ((src_w != state->crtc_w) || (src_h != state->crtc_h))
+		return -EINVAL;
+
 	return 0;
 }
 
@@ -233,20 +242,31 @@ static void hdlcd_plane_atomic_update(st
 {
 	struct hdlcd_drm_private *hdlcd;
 	struct drm_gem_cma_object *gem;
+	unsigned int depth, bpp;
+	u32 src_w, src_h, dest_w, dest_h;
 	dma_addr_t scanout_start;
 
-	if (!plane->state->crtc || !plane->state->fb)
+	if (!plane->state->fb)
 		return;
 
-	hdlcd = crtc_to_hdlcd_priv(plane->state->crtc);
+	drm_fb_get_bpp_depth(plane->state->fb->pixel_format, &depth, &bpp);
+	src_w = plane->state->src_w >> 16;
+	src_h = plane->state->src_h >> 16;
+	dest_w = plane->state->crtc_w;
+	dest_h = plane->state->crtc_h;
 	gem = drm_fb_cma_get_gem_obj(plane->state->fb, 0);
-	scanout_start = gem->paddr;
+	scanout_start = gem->paddr + plane->state->fb->offsets[0] +
+		plane->state->crtc_y * plane->state->fb->pitches[0] +
+		plane->state->crtc_x * bpp / 8;
+
+	hdlcd = plane->dev->dev_private;
+	hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, plane->state->fb->pitches[0]);
+	hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_PITCH, plane->state->fb->pitches[0]);
+	hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_COUNT, dest_h - 1);
 	hdlcd_write(hdlcd, HDLCD_REG_FB_BASE, scanout_start);
 }
 
 static const struct drm_plane_helper_funcs hdlcd_plane_helper_funcs = {
-	.prepare_fb = NULL,
-	.cleanup_fb = NULL,
 	.atomic_check = hdlcd_plane_atomic_check,
 	.atomic_update = hdlcd_plane_atomic_update,
 };
@@ -294,16 +314,6 @@ static struct drm_plane *hdlcd_plane_ini
 	return plane;
 }
 
-void hdlcd_crtc_suspend(struct drm_crtc *crtc)
-{
-	hdlcd_crtc_disable(crtc);
-}
-
-void hdlcd_crtc_resume(struct drm_crtc *crtc)
-{
-	hdlcd_crtc_enable(crtc);
-}
-
 int hdlcd_setup_crtc(struct drm_device *drm)
 {
 	struct hdlcd_drm_private *hdlcd = drm->dev_private;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/arm/hdlcd_drv.c linux-libre-4.7-gnu/drivers/gpu/drm/arm/hdlcd_drv.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/arm/hdlcd_drv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/arm/hdlcd_drv.c	2016-07-24 15:23:50.000000000 -0400
@@ -49,8 +49,6 @@ static int hdlcd_load(struct drm_device
 	atomic_set(&hdlcd->dma_end_count, 0);
 #endif
 
-	INIT_LIST_HEAD(&hdlcd->event_list);
-
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	hdlcd->mmio = devm_ioremap_resource(drm->dev, res);
 	if (IS_ERR(hdlcd->mmio)) {
@@ -84,11 +82,7 @@ static int hdlcd_load(struct drm_device
 		goto setup_fail;
 	}
 
-	pm_runtime_enable(drm->dev);
-
-	pm_runtime_get_sync(drm->dev);
 	ret = drm_irq_install(drm, platform_get_irq(pdev, 0));
-	pm_runtime_put_sync(drm->dev);
 	if (ret < 0) {
 		DRM_ERROR("failed to install IRQ handler\n");
 		goto irq_fail;
@@ -113,7 +107,7 @@ static void hdlcd_fb_output_poll_changed
 }
 
 static int hdlcd_atomic_commit(struct drm_device *dev,
-			       struct drm_atomic_state *state, bool async)
+			       struct drm_atomic_state *state, bool nonblock)
 {
 	return drm_atomic_helper_commit(dev, state, false);
 }
@@ -164,24 +158,9 @@ static irqreturn_t hdlcd_irq(int irq, vo
 		atomic_inc(&hdlcd->vsync_count);
 
 #endif
-	if (irq_status & HDLCD_INTERRUPT_VSYNC) {
-		bool events_sent = false;
-		unsigned long flags;
-		struct drm_pending_vblank_event	*e, *t;
-
+	if (irq_status & HDLCD_INTERRUPT_VSYNC)
 		drm_crtc_handle_vblank(&hdlcd->crtc);
 
-		spin_lock_irqsave(&drm->event_lock, flags);
-		list_for_each_entry_safe(e, t, &hdlcd->event_list, base.link) {
-			list_del(&e->base.link);
-			drm_crtc_send_vblank_event(&hdlcd->crtc, e);
-			events_sent = true;
-		}
-		if (events_sent)
-			drm_crtc_vblank_put(&hdlcd->crtc);
-		spin_unlock_irqrestore(&drm->event_lock, flags);
-	}
-
 	/* acknowledge interrupt(s) */
 	hdlcd_write(hdlcd, HDLCD_REG_INT_CLEAR, irq_status);
 
@@ -275,6 +254,7 @@ static int hdlcd_show_pxlclock(struct se
 static struct drm_info_list hdlcd_debugfs_list[] = {
 	{ "interrupt_count", hdlcd_show_underrun_count, 0 },
 	{ "clocks", hdlcd_show_pxlclock, 0 },
+	{ "fb", drm_fb_cma_debugfs_show, 0 },
 };
 
 static int hdlcd_debugfs_init(struct drm_minor *minor)
@@ -357,6 +337,8 @@ static int hdlcd_drm_bind(struct device
 		return -ENOMEM;
 
 	drm->dev_private = hdlcd;
+	dev_set_drvdata(dev, drm);
+
 	hdlcd_setup_mode_config(drm);
 	ret = hdlcd_load(drm, 0);
 	if (ret)
@@ -366,20 +348,23 @@ static int hdlcd_drm_bind(struct device
 	if (ret)
 		goto err_unload;
 
-	dev_set_drvdata(dev, drm);
-
 	ret = component_bind_all(dev, drm);
 	if (ret) {
 		DRM_ERROR("Failed to bind all components\n");
 		goto err_unregister;
 	}
 
+	ret = pm_runtime_set_active(dev);
+	if (ret)
+		goto err_pm_active;
+
+	pm_runtime_enable(dev);
+
 	ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
 	if (ret < 0) {
 		DRM_ERROR("failed to initialise vblank\n");
 		goto err_vblank;
 	}
-	drm->vblank_disable_allowed = true;
 
 	drm_mode_config_reset(drm);
 	drm_kms_helper_poll_init(drm);
@@ -400,16 +385,16 @@ err_fbdev:
 	drm_mode_config_cleanup(drm);
 	drm_vblank_cleanup(drm);
 err_vblank:
+	pm_runtime_disable(drm->dev);
+err_pm_active:
 	component_unbind_all(dev, drm);
 err_unregister:
 	drm_dev_unregister(drm);
 err_unload:
-	pm_runtime_get_sync(drm->dev);
 	drm_irq_uninstall(drm);
-	pm_runtime_put_sync(drm->dev);
-	pm_runtime_disable(drm->dev);
 	of_reserved_mem_device_release(drm->dev);
 err_free:
+	dev_set_drvdata(dev, NULL);
 	drm_dev_unref(drm);
 
 	return ret;
@@ -496,30 +481,34 @@ MODULE_DEVICE_TABLE(of, hdlcd_of_match);
 static int __maybe_unused hdlcd_pm_suspend(struct device *dev)
 {
 	struct drm_device *drm = dev_get_drvdata(dev);
-	struct drm_crtc *crtc;
+	struct hdlcd_drm_private *hdlcd = drm ? drm->dev_private : NULL;
 
-	if (pm_runtime_suspended(dev))
+	if (!hdlcd)
 		return 0;
 
-	drm_modeset_lock_all(drm);
-	list_for_each_entry(crtc, &drm->mode_config.crtc_list, head)
-		hdlcd_crtc_suspend(crtc);
-	drm_modeset_unlock_all(drm);
+	drm_kms_helper_poll_disable(drm);
+
+	hdlcd->state = drm_atomic_helper_suspend(drm);
+	if (IS_ERR(hdlcd->state)) {
+		drm_kms_helper_poll_enable(drm);
+		return PTR_ERR(hdlcd->state);
+	}
+
 	return 0;
 }
 
 static int __maybe_unused hdlcd_pm_resume(struct device *dev)
 {
 	struct drm_device *drm = dev_get_drvdata(dev);
-	struct drm_crtc *crtc;
+	struct hdlcd_drm_private *hdlcd = drm ? drm->dev_private : NULL;
 
-	if (!pm_runtime_suspended(dev))
+	if (!hdlcd)
 		return 0;
 
-	drm_modeset_lock_all(drm);
-	list_for_each_entry(crtc, &drm->mode_config.crtc_list, head)
-		hdlcd_crtc_resume(crtc);
-	drm_modeset_unlock_all(drm);
+	drm_atomic_helper_resume(drm, hdlcd->state);
+	drm_kms_helper_poll_enable(drm);
+	pm_runtime_set_active(dev);
+
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/arm/hdlcd_drv.h linux-libre-4.7-gnu/drivers/gpu/drm/arm/hdlcd_drv.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/arm/hdlcd_drv.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/arm/hdlcd_drv.h	2016-07-24 15:23:50.000000000 -0400
@@ -9,10 +9,9 @@ struct hdlcd_drm_private {
 	void __iomem			*mmio;
 	struct clk			*clk;
 	struct drm_fbdev_cma		*fbdev;
-	struct drm_framebuffer		*fb;
-	struct list_head		event_list;
 	struct drm_crtc			crtc;
 	struct drm_plane		*plane;
+	struct drm_atomic_state		*state;
 #ifdef CONFIG_DEBUG_FS
 	atomic_t buffer_underrun_count;
 	atomic_t bus_error_count;
@@ -36,7 +35,5 @@ static inline u32 hdlcd_read(struct hdlc
 
 int hdlcd_setup_crtc(struct drm_device *dev);
 void hdlcd_set_scanout(struct hdlcd_drm_private *hdlcd);
-void hdlcd_crtc_suspend(struct drm_crtc *crtc);
-void hdlcd_crtc_resume(struct drm_crtc *crtc);
 
 #endif /* __HDLCD_DRV_H__ */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/armada/armada_crtc.c linux-libre-4.7-gnu/drivers/gpu/drm/armada/armada_crtc.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/armada/armada_crtc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/armada/armada_crtc.c	2016-07-24 15:23:50.000000000 -0400
@@ -897,7 +897,6 @@ static void cursor_update(void *data)
 static int armada_drm_crtc_cursor_set(struct drm_crtc *crtc,
 	struct drm_file *file, uint32_t handle, uint32_t w, uint32_t h)
 {
-	struct drm_device *dev = crtc->dev;
 	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
 	struct armada_gem_object *obj = NULL;
 	int ret;
@@ -911,7 +910,7 @@ static int armada_drm_crtc_cursor_set(st
 		if (w > 64 || h > 64 || (w > 32 && h > 32))
 			return -ENOMEM;
 
-		obj = armada_gem_object_lookup(dev, file, handle);
+		obj = armada_gem_object_lookup(file, handle);
 		if (!obj)
 			return -ENOENT;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/armada/armada_drv.c linux-libre-4.7-gnu/drivers/gpu/drm/armada/armada_drv.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/armada/armada_drv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/armada/armada_drv.c	2016-07-24 15:23:50.000000000 -0400
@@ -113,7 +113,6 @@ static int armada_drm_load(struct drm_de
 		goto err_comp;
 
 	dev->irq_enabled = true;
-	dev->vblank_disable_allowed = 1;
 
 	ret = armada_fbdev_init(dev);
 	if (ret)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/armada/armada_fb.c linux-libre-4.7-gnu/drivers/gpu/drm/armada/armada_fb.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/armada/armada_fb.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/armada/armada_fb.c	2016-07-24 15:23:50.000000000 -0400
@@ -120,7 +120,7 @@ static struct drm_framebuffer *armada_fb
 		goto err;
 	}
 
-	obj = armada_gem_object_lookup(dev, dfile, mode->handles[0]);
+	obj = armada_gem_object_lookup(dfile, mode->handles[0]);
 	if (!obj) {
 		ret = -ENOENT;
 		goto err;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/armada/armada_gem.c linux-libre-4.7-gnu/drivers/gpu/drm/armada/armada_gem.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/armada/armada_gem.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/armada/armada_gem.c	2016-07-24 15:23:50.000000000 -0400
@@ -278,7 +278,7 @@ int armada_gem_dumb_map_offset(struct dr
 	struct armada_gem_object *obj;
 	int ret = 0;
 
-	obj = armada_gem_object_lookup(dev, file, handle);
+	obj = armada_gem_object_lookup(file, handle);
 	if (!obj) {
 		DRM_ERROR("failed to lookup gem object\n");
 		return -EINVAL;
@@ -348,7 +348,7 @@ int armada_gem_mmap_ioctl(struct drm_dev
 	struct armada_gem_object *dobj;
 	unsigned long addr;
 
-	dobj = armada_gem_object_lookup(dev, file, args->handle);
+	dobj = armada_gem_object_lookup(file, args->handle);
 	if (dobj == NULL)
 		return -ENOENT;
 
@@ -391,7 +391,7 @@ int armada_gem_pwrite_ioctl(struct drm_d
 	if (ret)
 		return ret;
 
-	dobj = armada_gem_object_lookup(dev, file, args->handle);
+	dobj = armada_gem_object_lookup(file, args->handle);
 	if (dobj == NULL)
 		return -ENOENT;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/armada/armada_gem.h linux-libre-4.7-gnu/drivers/gpu/drm/armada/armada_gem.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/armada/armada_gem.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/armada/armada_gem.h	2016-07-24 15:23:50.000000000 -0400
@@ -45,9 +45,9 @@ struct drm_gem_object *armada_gem_prime_
 int armada_gem_map_import(struct armada_gem_object *);
 
 static inline struct armada_gem_object *armada_gem_object_lookup(
-	struct drm_device *dev, struct drm_file *dfile, unsigned handle)
+	struct drm_file *dfile, unsigned handle)
 {
-	struct drm_gem_object *obj = drm_gem_object_lookup(dev, dfile, handle);
+	struct drm_gem_object *obj = drm_gem_object_lookup(dfile, handle);
 
 	return obj ? drm_to_armada_gem(obj) : NULL;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/ast/ast_drv.c linux-libre-4.7-gnu/drivers/gpu/drm/ast/ast_drv.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/ast/ast_drv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/ast/ast_drv.c	2016-07-24 15:23:50.000000000 -0400
@@ -218,10 +218,8 @@ static struct drm_driver driver = {
 
 static int __init ast_init(void)
 {
-#ifdef CONFIG_VGA_CONSOLE
 	if (vgacon_text_force() && ast_modeset == -1)
 		return -EINVAL;
-#endif
 
 	if (ast_modeset == 0)
 		return -EINVAL;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/ast/ast_drv.h linux-libre-4.7-gnu/drivers/gpu/drm/ast/ast_drv.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/ast/ast_drv.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/ast/ast_drv.h	2016-07-24 15:23:50.000000000 -0400
@@ -367,7 +367,7 @@ static inline int ast_bo_reserve(struct
 {
 	int ret;
 
-	ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, NULL);
+	ret = ttm_bo_reserve(&bo->bo, true, no_wait, NULL);
 	if (ret) {
 		if (ret != -ERESTARTSYS && ret != -EBUSY)
 			DRM_ERROR("reserve failed %p\n", bo);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/ast/ast_main.c linux-libre-4.7-gnu/drivers/gpu/drm/ast/ast_main.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/ast/ast_main.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/ast/ast_main.c	2016-07-24 15:23:50.000000000 -0400
@@ -333,7 +333,7 @@ ast_user_framebuffer_create(struct drm_d
 	struct ast_framebuffer *ast_fb;
 	int ret;
 
-	obj = drm_gem_object_lookup(dev, filp, mode_cmd->handles[0]);
+	obj = drm_gem_object_lookup(filp, mode_cmd->handles[0]);
 	if (obj == NULL)
 		return ERR_PTR(-ENOENT);
 
@@ -574,7 +574,7 @@ ast_dumb_mmap_offset(struct drm_file *fi
 	struct drm_gem_object *obj;
 	struct ast_bo *bo;
 
-	obj = drm_gem_object_lookup(dev, file, handle);
+	obj = drm_gem_object_lookup(file, handle);
 	if (obj == NULL)
 		return -ENOENT;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/ast/ast_mode.c linux-libre-4.7-gnu/drivers/gpu/drm/ast/ast_mode.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/ast/ast_mode.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/ast/ast_mode.c	2016-07-24 15:23:50.000000000 -0400
@@ -1141,7 +1141,7 @@ static int ast_cursor_set(struct drm_crt
 	if (width > AST_MAX_HWC_WIDTH || height > AST_MAX_HWC_HEIGHT)
 		return -EINVAL;
 
-	obj = drm_gem_object_lookup(crtc->dev, file_priv, handle);
+	obj = drm_gem_object_lookup(file_priv, handle);
 	if (!obj) {
 		DRM_ERROR("Cannot find cursor object %x for crtc\n", handle);
 		return -ENOENT;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/ast/ast_ttm.c linux-libre-4.7-gnu/drivers/gpu/drm/ast/ast_ttm.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/ast/ast_ttm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/ast/ast_ttm.c	2016-07-24 15:23:50.000000000 -0400
@@ -245,6 +245,8 @@ struct ttm_bo_driver ast_bo_driver = {
 	.verify_access = ast_bo_verify_access,
 	.io_mem_reserve = &ast_ttm_io_mem_reserve,
 	.io_mem_free = &ast_ttm_io_mem_free,
+	.lru_tail = &ttm_bo_default_lru_tail,
+	.swap_lru_tail = &ttm_bo_default_swap_lru_tail,
 };
 
 int ast_mm_init(struct ast_private *ast)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c linux-libre-4.7-gnu/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c	2016-07-24 15:23:50.000000000 -0400
@@ -32,6 +32,23 @@
 #include "atmel_hlcdc_dc.h"
 
 /**
+ * Atmel HLCDC CRTC state structure
+ *
+ * @base: base CRTC state
+ * @output_mode: RGBXXX output mode
+ */
+struct atmel_hlcdc_crtc_state {
+	struct drm_crtc_state base;
+	unsigned int output_mode;
+};
+
+static inline struct atmel_hlcdc_crtc_state *
+drm_crtc_state_to_atmel_hlcdc_crtc_state(struct drm_crtc_state *state)
+{
+	return container_of(state, struct atmel_hlcdc_crtc_state, base);
+}
+
+/**
  * Atmel HLCDC CRTC structure
  *
  * @base: base DRM CRTC structure
@@ -59,6 +76,7 @@ static void atmel_hlcdc_crtc_mode_set_no
 	struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c);
 	struct regmap *regmap = crtc->dc->hlcdc->regmap;
 	struct drm_display_mode *adj = &c->state->adjusted_mode;
+	struct atmel_hlcdc_crtc_state *state;
 	unsigned long mode_rate;
 	struct videomode vm;
 	unsigned long prate;
@@ -112,15 +130,27 @@ static void atmel_hlcdc_crtc_mode_set_no
 	if (adj->flags & DRM_MODE_FLAG_NHSYNC)
 		cfg |= ATMEL_HLCDC_HSPOL;
 
+	state = drm_crtc_state_to_atmel_hlcdc_crtc_state(c->state);
+	cfg |= state->output_mode << 8;
+
 	regmap_update_bits(regmap, ATMEL_HLCDC_CFG(5),
 			   ATMEL_HLCDC_HSPOL | ATMEL_HLCDC_VSPOL |
 			   ATMEL_HLCDC_VSPDLYS | ATMEL_HLCDC_VSPDLYE |
 			   ATMEL_HLCDC_DISPPOL | ATMEL_HLCDC_DISPDLY |
 			   ATMEL_HLCDC_VSPSU | ATMEL_HLCDC_VSPHO |
-			   ATMEL_HLCDC_GUARDTIME_MASK,
+			   ATMEL_HLCDC_GUARDTIME_MASK | ATMEL_HLCDC_MODE_MASK,
 			   cfg);
 }
 
+static bool atmel_hlcdc_crtc_mode_fixup(struct drm_crtc *c,
+					const struct drm_display_mode *mode,
+					struct drm_display_mode *adjusted_mode)
+{
+	struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c);
+
+	return atmel_hlcdc_dc_mode_valid(crtc->dc, adjusted_mode) == MODE_OK;
+}
+
 static void atmel_hlcdc_crtc_disable(struct drm_crtc *c)
 {
 	struct drm_device *dev = c->dev;
@@ -221,15 +251,79 @@ void atmel_hlcdc_crtc_resume(struct drm_
 	}
 }
 
+#define ATMEL_HLCDC_RGB444_OUTPUT	BIT(0)
+#define ATMEL_HLCDC_RGB565_OUTPUT	BIT(1)
+#define ATMEL_HLCDC_RGB666_OUTPUT	BIT(2)
+#define ATMEL_HLCDC_RGB888_OUTPUT	BIT(3)
+#define ATMEL_HLCDC_OUTPUT_MODE_MASK	GENMASK(3, 0)
+
+static int atmel_hlcdc_crtc_select_output_mode(struct drm_crtc_state *state)
+{
+	unsigned int output_fmts = ATMEL_HLCDC_OUTPUT_MODE_MASK;
+	struct atmel_hlcdc_crtc_state *hstate;
+	struct drm_connector_state *cstate;
+	struct drm_connector *connector;
+	struct atmel_hlcdc_crtc *crtc;
+	int i;
+
+	crtc = drm_crtc_to_atmel_hlcdc_crtc(state->crtc);
+
+	for_each_connector_in_state(state->state, connector, cstate, i) {
+		struct drm_display_info *info = &connector->display_info;
+		unsigned int supported_fmts = 0;
+		int j;
+
+		if (!cstate->crtc)
+			continue;
+
+		for (j = 0; j < info->num_bus_formats; j++) {
+			switch (info->bus_formats[j]) {
+			case MEDIA_BUS_FMT_RGB444_1X12:
+				supported_fmts |= ATMEL_HLCDC_RGB444_OUTPUT;
+				break;
+			case MEDIA_BUS_FMT_RGB565_1X16:
+				supported_fmts |= ATMEL_HLCDC_RGB565_OUTPUT;
+				break;
+			case MEDIA_BUS_FMT_RGB666_1X18:
+				supported_fmts |= ATMEL_HLCDC_RGB666_OUTPUT;
+				break;
+			case MEDIA_BUS_FMT_RGB888_1X24:
+				supported_fmts |= ATMEL_HLCDC_RGB888_OUTPUT;
+				break;
+			default:
+				break;
+			}
+		}
+
+		if (crtc->dc->desc->conflicting_output_formats)
+			output_fmts &= supported_fmts;
+		else
+			output_fmts |= supported_fmts;
+	}
+
+	if (!output_fmts)
+		return -EINVAL;
+
+	hstate = drm_crtc_state_to_atmel_hlcdc_crtc_state(state);
+	hstate->output_mode = fls(output_fmts) - 1;
+
+	return 0;
+}
+
 static int atmel_hlcdc_crtc_atomic_check(struct drm_crtc *c,
 					 struct drm_crtc_state *s)
 {
-	struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c);
+	int ret;
 
-	if (atmel_hlcdc_dc_mode_valid(crtc->dc, &s->adjusted_mode) != MODE_OK)
-		return -EINVAL;
+	ret = atmel_hlcdc_crtc_select_output_mode(s);
+	if (ret)
+		return ret;
 
-	return atmel_hlcdc_plane_prepare_disc_area(s);
+	ret = atmel_hlcdc_plane_prepare_disc_area(s);
+	if (ret)
+		return ret;
+
+	return atmel_hlcdc_plane_prepare_ahb_routing(s);
 }
 
 static void atmel_hlcdc_crtc_atomic_begin(struct drm_crtc *c,
@@ -254,6 +348,7 @@ static void atmel_hlcdc_crtc_atomic_flus
 }
 
 static const struct drm_crtc_helper_funcs lcdc_crtc_helper_funcs = {
+	.mode_fixup = atmel_hlcdc_crtc_mode_fixup,
 	.mode_set = drm_helper_crtc_mode_set,
 	.mode_set_nofb = atmel_hlcdc_crtc_mode_set_nofb,
 	.mode_set_base = drm_helper_crtc_mode_set_base,
@@ -292,13 +387,60 @@ void atmel_hlcdc_crtc_irq(struct drm_crt
 	atmel_hlcdc_crtc_finish_page_flip(drm_crtc_to_atmel_hlcdc_crtc(c));
 }
 
+void atmel_hlcdc_crtc_reset(struct drm_crtc *crtc)
+{
+	struct atmel_hlcdc_crtc_state *state;
+
+	if (crtc->state) {
+		__drm_atomic_helper_crtc_destroy_state(crtc->state);
+		state = drm_crtc_state_to_atmel_hlcdc_crtc_state(crtc->state);
+		kfree(state);
+		crtc->state = NULL;
+	}
+
+	state = kzalloc(sizeof(*state), GFP_KERNEL);
+	if (state) {
+		crtc->state = &state->base;
+		crtc->state->crtc = crtc;
+	}
+}
+
+static struct drm_crtc_state *
+atmel_hlcdc_crtc_duplicate_state(struct drm_crtc *crtc)
+{
+	struct atmel_hlcdc_crtc_state *state, *cur;
+
+	if (WARN_ON(!crtc->state))
+		return NULL;
+
+	state = kmalloc(sizeof(*state), GFP_KERNEL);
+	if (!state)
+		return NULL;
+	__drm_atomic_helper_crtc_duplicate_state(crtc, &state->base);
+
+	cur = drm_crtc_state_to_atmel_hlcdc_crtc_state(crtc->state);
+	state->output_mode = cur->output_mode;
+
+	return &state->base;
+}
+
+static void atmel_hlcdc_crtc_destroy_state(struct drm_crtc *crtc,
+					   struct drm_crtc_state *s)
+{
+	struct atmel_hlcdc_crtc_state *state;
+
+	state = drm_crtc_state_to_atmel_hlcdc_crtc_state(s);
+	__drm_atomic_helper_crtc_destroy_state(s);
+	kfree(state);
+}
+
 static const struct drm_crtc_funcs atmel_hlcdc_crtc_funcs = {
 	.page_flip = drm_atomic_helper_page_flip,
 	.set_config = drm_atomic_helper_set_config,
 	.destroy = atmel_hlcdc_crtc_destroy,
-	.reset = drm_atomic_helper_crtc_reset,
-	.atomic_duplicate_state =  drm_atomic_helper_crtc_duplicate_state,
-	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+	.reset = atmel_hlcdc_crtc_reset,
+	.atomic_duplicate_state =  atmel_hlcdc_crtc_duplicate_state,
+	.atomic_destroy_state = atmel_hlcdc_crtc_destroy_state,
 };
 
 int atmel_hlcdc_crtc_create(struct drm_device *dev)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c linux-libre-4.7-gnu/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c	2016-07-24 15:23:50.000000000 -0400
@@ -50,6 +50,10 @@ static const struct atmel_hlcdc_dc_desc
 	.min_height = 0,
 	.max_width = 1280,
 	.max_height = 860,
+	.max_spw = 0x3f,
+	.max_vpw = 0x3f,
+	.max_hpw = 0xff,
+	.conflicting_output_formats = true,
 	.nlayers = ARRAY_SIZE(atmel_hlcdc_at91sam9n12_layers),
 	.layers = atmel_hlcdc_at91sam9n12_layers,
 };
@@ -134,6 +138,10 @@ static const struct atmel_hlcdc_dc_desc
 	.min_height = 0,
 	.max_width = 800,
 	.max_height = 600,
+	.max_spw = 0x3f,
+	.max_vpw = 0x3f,
+	.max_hpw = 0xff,
+	.conflicting_output_formats = true,
 	.nlayers = ARRAY_SIZE(atmel_hlcdc_at91sam9x5_layers),
 	.layers = atmel_hlcdc_at91sam9x5_layers,
 };
@@ -237,6 +245,10 @@ static const struct atmel_hlcdc_dc_desc
 	.min_height = 0,
 	.max_width = 2048,
 	.max_height = 2048,
+	.max_spw = 0x3f,
+	.max_vpw = 0x3f,
+	.max_hpw = 0x1ff,
+	.conflicting_output_formats = true,
 	.nlayers = ARRAY_SIZE(atmel_hlcdc_sama5d3_layers),
 	.layers = atmel_hlcdc_sama5d3_layers,
 };
@@ -320,6 +332,9 @@ static const struct atmel_hlcdc_dc_desc
 	.min_height = 0,
 	.max_width = 2048,
 	.max_height = 2048,
+	.max_spw = 0xff,
+	.max_vpw = 0xff,
+	.max_hpw = 0x3ff,
 	.nlayers = ARRAY_SIZE(atmel_hlcdc_sama5d4_layers),
 	.layers = atmel_hlcdc_sama5d4_layers,
 };
@@ -358,19 +373,19 @@ int atmel_hlcdc_dc_mode_valid(struct atm
 	int hback_porch = mode->htotal - mode->hsync_end;
 	int hsync_len = mode->hsync_end - mode->hsync_start;
 
-	if (hsync_len > 0x40 || hsync_len < 1)
+	if (hsync_len > dc->desc->max_spw + 1 || hsync_len < 1)
 		return MODE_HSYNC;
 
-	if (vsync_len > 0x40 || vsync_len < 1)
+	if (vsync_len > dc->desc->max_spw + 1 || vsync_len < 1)
 		return MODE_VSYNC;
 
-	if (hfront_porch > 0x200 || hfront_porch < 1 ||
-	    hback_porch > 0x200 || hback_porch < 1 ||
+	if (hfront_porch > dc->desc->max_hpw + 1 || hfront_porch < 1 ||
+	    hback_porch > dc->desc->max_hpw + 1 || hback_porch < 1 ||
 	    mode->hdisplay < 1)
 		return MODE_H_ILLEGAL;
 
-	if (vfront_porch > 0x40 || vfront_porch < 1 ||
-	    vback_porch > 0x40 || vback_porch < 0 ||
+	if (vfront_porch > dc->desc->max_vpw + 1 || vfront_porch < 1 ||
+	    vback_porch > dc->desc->max_vpw || vback_porch < 0 ||
 	    mode->vdisplay < 1)
 		return MODE_V_ILLEGAL;
 
@@ -427,11 +442,102 @@ static void atmel_hlcdc_fb_output_poll_c
 	}
 }
 
+struct atmel_hlcdc_dc_commit {
+	struct work_struct work;
+	struct drm_device *dev;
+	struct drm_atomic_state *state;
+};
+
+static void
+atmel_hlcdc_dc_atomic_complete(struct atmel_hlcdc_dc_commit *commit)
+{
+	struct drm_device *dev = commit->dev;
+	struct atmel_hlcdc_dc *dc = dev->dev_private;
+	struct drm_atomic_state *old_state = commit->state;
+
+	/* Apply the atomic update. */
+	drm_atomic_helper_commit_modeset_disables(dev, old_state);
+	drm_atomic_helper_commit_planes(dev, old_state, false);
+	drm_atomic_helper_commit_modeset_enables(dev, old_state);
+
+	drm_atomic_helper_wait_for_vblanks(dev, old_state);
+
+	drm_atomic_helper_cleanup_planes(dev, old_state);
+
+	drm_atomic_state_free(old_state);
+
+	/* Complete the commit, wake up any waiter. */
+	spin_lock(&dc->commit.wait.lock);
+	dc->commit.pending = false;
+	wake_up_all_locked(&dc->commit.wait);
+	spin_unlock(&dc->commit.wait.lock);
+
+	kfree(commit);
+}
+
+static void atmel_hlcdc_dc_atomic_work(struct work_struct *work)
+{
+	struct atmel_hlcdc_dc_commit *commit =
+		container_of(work, struct atmel_hlcdc_dc_commit, work);
+
+	atmel_hlcdc_dc_atomic_complete(commit);
+}
+
+static int atmel_hlcdc_dc_atomic_commit(struct drm_device *dev,
+					struct drm_atomic_state *state,
+					bool async)
+{
+	struct atmel_hlcdc_dc *dc = dev->dev_private;
+	struct atmel_hlcdc_dc_commit *commit;
+	int ret;
+
+	ret = drm_atomic_helper_prepare_planes(dev, state);
+	if (ret)
+		return ret;
+
+	/* Allocate the commit object. */
+	commit = kzalloc(sizeof(*commit), GFP_KERNEL);
+	if (!commit) {
+		ret = -ENOMEM;
+		goto error;
+	}
+
+	INIT_WORK(&commit->work, atmel_hlcdc_dc_atomic_work);
+	commit->dev = dev;
+	commit->state = state;
+
+	spin_lock(&dc->commit.wait.lock);
+	ret = wait_event_interruptible_locked(dc->commit.wait,
+					      !dc->commit.pending);
+	if (ret == 0)
+		dc->commit.pending = true;
+	spin_unlock(&dc->commit.wait.lock);
+
+	if (ret) {
+		kfree(commit);
+		goto error;
+	}
+
+	/* Swap the state, this is the point of no return. */
+	drm_atomic_helper_swap_state(dev, state);
+
+	if (async)
+		queue_work(dc->wq, &commit->work);
+	else
+		atmel_hlcdc_dc_atomic_complete(commit);
+
+	return 0;
+
+error:
+	drm_atomic_helper_cleanup_planes(dev, state);
+	return ret;
+}
+
 static const struct drm_mode_config_funcs mode_config_funcs = {
 	.fb_create = atmel_hlcdc_fb_create,
 	.output_poll_changed = atmel_hlcdc_fb_output_poll_changed,
 	.atomic_check = drm_atomic_helper_check,
-	.atomic_commit = drm_atomic_helper_commit,
+	.atomic_commit = atmel_hlcdc_dc_atomic_commit,
 };
 
 static int atmel_hlcdc_dc_modeset_init(struct drm_device *dev)
@@ -445,7 +551,7 @@ static int atmel_hlcdc_dc_modeset_init(s
 
 	ret = atmel_hlcdc_create_outputs(dev);
 	if (ret) {
-		dev_err(dev->dev, "failed to create panel: %d\n", ret);
+		dev_err(dev->dev, "failed to create HLCDC outputs: %d\n", ret);
 		return ret;
 	}
 
@@ -509,6 +615,7 @@ static int atmel_hlcdc_dc_load(struct dr
 	if (!dc->wq)
 		return -ENOMEM;
 
+	init_waitqueue_head(&dc->commit.wait);
 	dc->desc = match->data;
 	dc->hlcdc = dev_get_drvdata(dev->dev->parent);
 	dev->dev_private = dc;
@@ -584,38 +691,10 @@ static void atmel_hlcdc_dc_unload(struct
 	destroy_workqueue(dc->wq);
 }
 
-static int atmel_hlcdc_dc_connector_plug_all(struct drm_device *dev)
-{
-	struct drm_connector *connector, *failed;
-	int ret;
-
-	mutex_lock(&dev->mode_config.mutex);
-	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-		ret = drm_connector_register(connector);
-		if (ret) {
-			failed = connector;
-			goto err;
-		}
-	}
-	mutex_unlock(&dev->mode_config.mutex);
-	return 0;
-
-err:
-	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-		if (failed == connector)
-			break;
-
-		drm_connector_unregister(connector);
-	}
-	mutex_unlock(&dev->mode_config.mutex);
-
-	return ret;
-}
-
 static void atmel_hlcdc_dc_connector_unplug_all(struct drm_device *dev)
 {
 	mutex_lock(&dev->mode_config.mutex);
-	drm_connector_unplug_all(dev);
+	drm_connector_unregister_all(dev);
 	mutex_unlock(&dev->mode_config.mutex);
 }
 
@@ -736,7 +815,7 @@ static int atmel_hlcdc_dc_drm_probe(stru
 	if (ret)
 		goto err_unload;
 
-	ret = atmel_hlcdc_dc_connector_plug_all(ddev);
+	ret = drm_connector_register_all(ddev);
 	if (ret)
 		goto err_unregister;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h linux-libre-4.7-gnu/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h	2016-07-24 15:23:50.000000000 -0400
@@ -50,6 +50,11 @@
  * @min_height: minimum height supported by the Display Controller
  * @max_width: maximum width supported by the Display Controller
  * @max_height: maximum height supported by the Display Controller
+ * @max_spw: maximum vertical/horizontal pulse width
+ * @max_vpw: maximum vertical back/front porch width
+ * @max_hpw: maximum horizontal back/front porch width
+ * @conflicting_output_formats: true if RGBXXX output formats conflict with
+ *				each other.
  * @layers: a layer description table describing available layers
  * @nlayers: layer description table size
  */
@@ -58,6 +63,10 @@ struct atmel_hlcdc_dc_desc {
 	int min_height;
 	int max_width;
 	int max_height;
+	int max_spw;
+	int max_vpw;
+	int max_hpw;
+	bool conflicting_output_formats;
 	const struct atmel_hlcdc_layer_desc *layers;
 	int nlayers;
 };
@@ -128,6 +137,7 @@ struct atmel_hlcdc_planes {
  * @planes: instantiated planes
  * @layers: active HLCDC layer
  * @wq: display controller workqueue
+ * @commit: used for async commit handling
  */
 struct atmel_hlcdc_dc {
 	const struct atmel_hlcdc_dc_desc *desc;
@@ -137,6 +147,10 @@ struct atmel_hlcdc_dc {
 	struct atmel_hlcdc_planes *planes;
 	struct atmel_hlcdc_layer *layers[ATMEL_HLCDC_MAX_LAYERS];
 	struct workqueue_struct *wq;
+	struct {
+		wait_queue_head_t wait;
+		bool pending;
+	} commit;
 };
 
 extern struct atmel_hlcdc_formats atmel_hlcdc_plane_rgb_formats;
@@ -149,6 +163,7 @@ struct atmel_hlcdc_planes *
 atmel_hlcdc_create_planes(struct drm_device *dev);
 
 int atmel_hlcdc_plane_prepare_disc_area(struct drm_crtc_state *c_state);
+int atmel_hlcdc_plane_prepare_ahb_routing(struct drm_crtc_state *c_state);
 
 void atmel_hlcdc_crtc_irq(struct drm_crtc *c);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c linux-libre-4.7-gnu/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c	2016-07-24 15:23:50.000000000 -0400
@@ -27,16 +27,6 @@
 #include "atmel_hlcdc_dc.h"
 
 /**
- * Atmel HLCDC RGB output mode
- */
-enum atmel_hlcdc_connector_rgb_mode {
-	ATMEL_HLCDC_CONNECTOR_RGB444,
-	ATMEL_HLCDC_CONNECTOR_RGB565,
-	ATMEL_HLCDC_CONNECTOR_RGB666,
-	ATMEL_HLCDC_CONNECTOR_RGB888,
-};
-
-/**
  * Atmel HLCDC RGB connector structure
  *
  * This structure stores RGB slave device information.
@@ -44,13 +34,13 @@ enum atmel_hlcdc_connector_rgb_mode {
  * @connector: DRM connector
  * @encoder: DRM encoder
  * @dc: pointer to the atmel_hlcdc_dc structure
- * @dpms: current DPMS mode
+ * @panel: panel connected on the RGB output
  */
 struct atmel_hlcdc_rgb_output {
 	struct drm_connector connector;
 	struct drm_encoder encoder;
 	struct atmel_hlcdc_dc *dc;
-	int dpms;
+	struct drm_panel *panel;
 };
 
 static inline struct atmel_hlcdc_rgb_output *
@@ -66,91 +56,31 @@ drm_encoder_to_atmel_hlcdc_rgb_output(st
 	return container_of(encoder, struct atmel_hlcdc_rgb_output, encoder);
 }
 
-/**
- * Atmel HLCDC Panel device structure
- *
- * This structure is specialization of the slave device structure to
- * interface with drm panels.
- *
- * @base: base slave device fields
- * @panel: drm panel attached to this slave device
- */
-struct atmel_hlcdc_panel {
-	struct atmel_hlcdc_rgb_output base;
-	struct drm_panel *panel;
-};
-
-static inline struct atmel_hlcdc_panel *
-atmel_hlcdc_rgb_output_to_panel(struct atmel_hlcdc_rgb_output *output)
-{
-	return container_of(output, struct atmel_hlcdc_panel, base);
-}
-
-static void atmel_hlcdc_panel_encoder_enable(struct drm_encoder *encoder)
-{
-	struct atmel_hlcdc_rgb_output *rgb =
-			drm_encoder_to_atmel_hlcdc_rgb_output(encoder);
-	struct atmel_hlcdc_panel *panel = atmel_hlcdc_rgb_output_to_panel(rgb);
-
-	drm_panel_enable(panel->panel);
-}
-
-static void atmel_hlcdc_panel_encoder_disable(struct drm_encoder *encoder)
+static void atmel_hlcdc_rgb_encoder_enable(struct drm_encoder *encoder)
 {
 	struct atmel_hlcdc_rgb_output *rgb =
 			drm_encoder_to_atmel_hlcdc_rgb_output(encoder);
-	struct atmel_hlcdc_panel *panel = atmel_hlcdc_rgb_output_to_panel(rgb);
 
-	drm_panel_disable(panel->panel);
-}
-
-static bool
-atmel_hlcdc_panel_encoder_mode_fixup(struct drm_encoder *encoder,
-				     const struct drm_display_mode *mode,
-				     struct drm_display_mode *adjusted)
-{
-	return true;
+	if (rgb->panel) {
+		drm_panel_prepare(rgb->panel);
+		drm_panel_enable(rgb->panel);
+	}
 }
 
-static void
-atmel_hlcdc_rgb_encoder_mode_set(struct drm_encoder *encoder,
-				 struct drm_display_mode *mode,
-				 struct drm_display_mode *adjusted)
+static void atmel_hlcdc_rgb_encoder_disable(struct drm_encoder *encoder)
 {
 	struct atmel_hlcdc_rgb_output *rgb =
 			drm_encoder_to_atmel_hlcdc_rgb_output(encoder);
-	struct drm_display_info *info = &rgb->connector.display_info;
-	unsigned int cfg;
-
-	cfg = 0;
 
-	if (info->num_bus_formats) {
-		switch (info->bus_formats[0]) {
-		case MEDIA_BUS_FMT_RGB565_1X16:
-			cfg |= ATMEL_HLCDC_CONNECTOR_RGB565 << 8;
-			break;
-		case MEDIA_BUS_FMT_RGB666_1X18:
-			cfg |= ATMEL_HLCDC_CONNECTOR_RGB666 << 8;
-			break;
-		case MEDIA_BUS_FMT_RGB888_1X24:
-			cfg |= ATMEL_HLCDC_CONNECTOR_RGB888 << 8;
-			break;
-		case MEDIA_BUS_FMT_RGB444_1X12:
-		default:
-			break;
-		}
+	if (rgb->panel) {
+		drm_panel_disable(rgb->panel);
+		drm_panel_unprepare(rgb->panel);
 	}
-
-	regmap_update_bits(rgb->dc->hlcdc->regmap, ATMEL_HLCDC_CFG(5),
-			   ATMEL_HLCDC_MODE_MASK,
-			   cfg);
 }
 
 static const struct drm_encoder_helper_funcs atmel_hlcdc_panel_encoder_helper_funcs = {
-	.mode_fixup = atmel_hlcdc_panel_encoder_mode_fixup,
-	.mode_set = atmel_hlcdc_rgb_encoder_mode_set,
-	.disable = atmel_hlcdc_panel_encoder_disable,
-	.enable = atmel_hlcdc_panel_encoder_enable,
+	.disable = atmel_hlcdc_rgb_encoder_disable,
+	.enable = atmel_hlcdc_rgb_encoder_enable,
 };
 
 static void atmel_hlcdc_rgb_encoder_destroy(struct drm_encoder *encoder)
@@ -167,9 +97,11 @@ static int atmel_hlcdc_panel_get_modes(s
 {
 	struct atmel_hlcdc_rgb_output *rgb =
 			drm_connector_to_atmel_hlcdc_rgb_output(connector);
-	struct atmel_hlcdc_panel *panel = atmel_hlcdc_rgb_output_to_panel(rgb);
 
-	return panel->panel->funcs->get_modes(panel->panel);
+	if (rgb->panel)
+		return rgb->panel->funcs->get_modes(rgb->panel);
+
+	return 0;
 }
 
 static int atmel_hlcdc_rgb_mode_valid(struct drm_connector *connector,
@@ -201,7 +133,13 @@ static const struct drm_connector_helper
 static enum drm_connector_status
 atmel_hlcdc_panel_connector_detect(struct drm_connector *connector, bool force)
 {
-	return connector_status_connected;
+	struct atmel_hlcdc_rgb_output *rgb =
+			drm_connector_to_atmel_hlcdc_rgb_output(connector);
+
+	if (rgb->panel)
+		return connector_status_connected;
+
+	return connector_status_disconnected;
 }
 
 static void
@@ -209,9 +147,10 @@ atmel_hlcdc_panel_connector_destroy(stru
 {
 	struct atmel_hlcdc_rgb_output *rgb =
 			drm_connector_to_atmel_hlcdc_rgb_output(connector);
-	struct atmel_hlcdc_panel *panel = atmel_hlcdc_rgb_output_to_panel(rgb);
 
-	drm_panel_detach(panel->panel);
+	if (rgb->panel)
+		drm_panel_detach(rgb->panel);
+
 	drm_connector_cleanup(connector);
 }
 
@@ -225,88 +164,124 @@ static const struct drm_connector_funcs
 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };
 
-static int atmel_hlcdc_create_panel_output(struct drm_device *dev,
-					   struct of_endpoint *ep)
+static int atmel_hlcdc_check_endpoint(struct drm_device *dev,
+				      const struct of_endpoint *ep)
 {
-	struct atmel_hlcdc_dc *dc = dev->dev_private;
 	struct device_node *np;
-	struct drm_panel *p = NULL;
-	struct atmel_hlcdc_panel *panel;
-	int ret;
+	void *obj;
 
 	np = of_graph_get_remote_port_parent(ep->local_node);
-	if (!np)
-		return -EINVAL;
 
-	p = of_drm_find_panel(np);
+	obj = of_drm_find_panel(np);
+	if (!obj)
+		obj = of_drm_find_bridge(np);
+
 	of_node_put(np);
 
-	if (!p)
-		return -EPROBE_DEFER;
+	return obj ? 0 : -EPROBE_DEFER;
+}
 
-	panel = devm_kzalloc(dev->dev, sizeof(*panel), GFP_KERNEL);
-	if (!panel)
-		return -EINVAL;
+static int atmel_hlcdc_attach_endpoint(struct drm_device *dev,
+				       const struct of_endpoint *ep)
+{
+	struct atmel_hlcdc_dc *dc = dev->dev_private;
+	struct atmel_hlcdc_rgb_output *output;
+	struct device_node *np;
+	struct drm_panel *panel;
+	struct drm_bridge *bridge;
+	int ret;
 
-	panel->base.dpms = DRM_MODE_DPMS_OFF;
+	output = devm_kzalloc(dev->dev, sizeof(*output), GFP_KERNEL);
+	if (!output)
+		return -EINVAL;
 
-	panel->base.dc = dc;
+	output->dc = dc;
 
-	drm_encoder_helper_add(&panel->base.encoder,
+	drm_encoder_helper_add(&output->encoder,
 			       &atmel_hlcdc_panel_encoder_helper_funcs);
-	ret = drm_encoder_init(dev, &panel->base.encoder,
+	ret = drm_encoder_init(dev, &output->encoder,
 			       &atmel_hlcdc_panel_encoder_funcs,
-			       DRM_MODE_ENCODER_LVDS, NULL);
+			       DRM_MODE_ENCODER_NONE, NULL);
 	if (ret)
 		return ret;
 
-	panel->base.connector.dpms = DRM_MODE_DPMS_OFF;
-	panel->base.connector.polled = DRM_CONNECTOR_POLL_CONNECT;
-	drm_connector_helper_add(&panel->base.connector,
-				 &atmel_hlcdc_panel_connector_helper_funcs);
-	ret = drm_connector_init(dev, &panel->base.connector,
-				 &atmel_hlcdc_panel_connector_funcs,
-				 DRM_MODE_CONNECTOR_LVDS);
-	if (ret)
-		goto err_encoder_cleanup;
+	output->encoder.possible_crtcs = 0x1;
 
-	drm_mode_connector_attach_encoder(&panel->base.connector,
-					  &panel->base.encoder);
-	panel->base.encoder.possible_crtcs = 0x1;
+	np = of_graph_get_remote_port_parent(ep->local_node);
 
-	drm_panel_attach(p, &panel->base.connector);
-	panel->panel = p;
+	ret = -EPROBE_DEFER;
 
-	return 0;
+	panel = of_drm_find_panel(np);
+	if (panel) {
+		of_node_put(np);
+		output->connector.dpms = DRM_MODE_DPMS_OFF;
+		output->connector.polled = DRM_CONNECTOR_POLL_CONNECT;
+		drm_connector_helper_add(&output->connector,
+				&atmel_hlcdc_panel_connector_helper_funcs);
+		ret = drm_connector_init(dev, &output->connector,
+					 &atmel_hlcdc_panel_connector_funcs,
+					 DRM_MODE_CONNECTOR_Unknown);
+		if (ret)
+			goto err_encoder_cleanup;
+
+		drm_mode_connector_attach_encoder(&output->connector,
+						  &output->encoder);
+
+		ret = drm_panel_attach(panel, &output->connector);
+		if (ret) {
+			drm_connector_cleanup(&output->connector);
+			goto err_encoder_cleanup;
+		}
+
+		output->panel = panel;
+
+		return 0;
+	}
+
+	bridge = of_drm_find_bridge(np);
+	of_node_put(np);
+
+	if (bridge) {
+		output->encoder.bridge = bridge;
+		bridge->encoder = &output->encoder;
+		ret = drm_bridge_attach(dev, bridge);
+		if (!ret)
+			return 0;
+	}
 
 err_encoder_cleanup:
-	drm_encoder_cleanup(&panel->base.encoder);
+	drm_encoder_cleanup(&output->encoder);
 
 	return ret;
 }
 
 int atmel_hlcdc_create_outputs(struct drm_device *dev)
 {
-	struct device_node *port_np, *np;
+	struct device_node *ep_np = NULL;
 	struct of_endpoint ep;
 	int ret;
 
-	port_np = of_get_child_by_name(dev->dev->of_node, "port");
-	if (!port_np)
-		return -EINVAL;
-
-	np = of_get_child_by_name(port_np, "endpoint");
-	of_node_put(port_np);
+	for_each_endpoint_of_node(dev->dev->of_node, ep_np) {
+		ret = of_graph_parse_endpoint(ep_np, &ep);
+		if (!ret)
+			ret = atmel_hlcdc_check_endpoint(dev, &ep);
 
-	if (!np)
-		return -EINVAL;
+		if (ret) {
+			of_node_put(ep_np);
+			return ret;
+		}
+	}
 
-	ret = of_graph_parse_endpoint(np, &ep);
-	of_node_put(port_np);
+	for_each_endpoint_of_node(dev->dev->of_node, ep_np) {
+		ret = of_graph_parse_endpoint(ep_np, &ep);
+		if (!ret)
+			ret = atmel_hlcdc_attach_endpoint(dev, &ep);
 
-	if (ret)
-		return ret;
+		if (ret) {
+			of_node_put(ep_np);
+			return ret;
+		}
+	}
 
-	/* We currently only support panel output */
-	return atmel_hlcdc_create_panel_output(dev, &ep);
+	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c linux-libre-4.7-gnu/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c	2016-07-24 15:23:50.000000000 -0400
@@ -37,6 +37,7 @@
  * @xstride: value to add to the pixel pointer between each line
  * @pstride: value to add to the pixel pointer between each pixel
  * @nplanes: number of planes (deduced from pixel_format)
+ * @prepared: plane update has been prepared
  */
 struct atmel_hlcdc_plane_state {
 	struct drm_plane_state base;
@@ -58,12 +59,15 @@ struct atmel_hlcdc_plane_state {
 	int disc_w;
 	int disc_h;
 
+	int ahb_id;
+
 	/* These fields are private and should not be touched */
 	int bpp[ATMEL_HLCDC_MAX_PLANES];
 	unsigned int offsets[ATMEL_HLCDC_MAX_PLANES];
 	int xstride[ATMEL_HLCDC_MAX_PLANES];
 	int pstride[ATMEL_HLCDC_MAX_PLANES];
 	int nplanes;
+	bool prepared;
 };
 
 static inline struct atmel_hlcdc_plane_state *
@@ -335,6 +339,8 @@ atmel_hlcdc_plane_update_pos_and_size(st
 
 		atmel_hlcdc_layer_update_cfg(&plane->layer, 13, 0xffffffff,
 					     factor_reg);
+	} else {
+		atmel_hlcdc_layer_update_cfg(&plane->layer, 13, 0xffffffff, 0);
 	}
 }
 
@@ -359,8 +365,10 @@ atmel_hlcdc_plane_update_general_setting
 
 	atmel_hlcdc_layer_update_cfg(&plane->layer,
 				     ATMEL_HLCDC_LAYER_DMA_CFG_ID,
-				     ATMEL_HLCDC_LAYER_DMA_BLEN_MASK,
-				     ATMEL_HLCDC_LAYER_DMA_BLEN_INCR16);
+				     ATMEL_HLCDC_LAYER_DMA_BLEN_MASK |
+				     ATMEL_HLCDC_LAYER_DMA_SIF,
+				     ATMEL_HLCDC_LAYER_DMA_BLEN_INCR16 |
+				     state->ahb_id);
 
 	atmel_hlcdc_layer_update_cfg(&plane->layer, layout->general_config,
 				     ATMEL_HLCDC_LAYER_ITER2BL |
@@ -435,6 +443,41 @@ static void atmel_hlcdc_plane_update_buf
 	}
 }
 
+int atmel_hlcdc_plane_prepare_ahb_routing(struct drm_crtc_state *c_state)
+{
+	unsigned int ahb_load[2] = { };
+	struct drm_plane *plane;
+
+	drm_atomic_crtc_state_for_each_plane(plane, c_state) {
+		struct atmel_hlcdc_plane_state *plane_state;
+		struct drm_plane_state *plane_s;
+		unsigned int pixels, load = 0;
+		int i;
+
+		plane_s = drm_atomic_get_plane_state(c_state->state, plane);
+		if (IS_ERR(plane_s))
+			return PTR_ERR(plane_s);
+
+		plane_state =
+			drm_plane_state_to_atmel_hlcdc_plane_state(plane_s);
+
+		pixels = (plane_state->src_w * plane_state->src_h) -
+			 (plane_state->disc_w * plane_state->disc_h);
+
+		for (i = 0; i < plane_state->nplanes; i++)
+			load += pixels * plane_state->bpp[i];
+
+		if (ahb_load[0] <= ahb_load[1])
+			plane_state->ahb_id = 0;
+		else
+			plane_state->ahb_id = 1;
+
+		ahb_load[plane_state->ahb_id] += load;
+	}
+
+	return 0;
+}
+
 int
 atmel_hlcdc_plane_prepare_disc_area(struct drm_crtc_state *c_state)
 {
@@ -714,12 +757,54 @@ static int atmel_hlcdc_plane_atomic_chec
 static int atmel_hlcdc_plane_prepare_fb(struct drm_plane *p,
 					const struct drm_plane_state *new_state)
 {
+	/*
+	 * FIXME: we should avoid this const -> non-const cast but it's
+	 * currently the only solution we have to modify the ->prepared
+	 * state and rollback the update request.
+	 * Ideally, we should rework the code to attach all the resources
+	 * to atmel_hlcdc_plane_state (including the DMA desc allocation),
+	 * but this require a complete rework of the atmel_hlcdc_layer
+	 * code.
+	 */
+	struct drm_plane_state *s = (struct drm_plane_state *)new_state;
 	struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
+	struct atmel_hlcdc_plane_state *state =
+			drm_plane_state_to_atmel_hlcdc_plane_state(s);
+	int ret;
 
-	if (!new_state->fb)
-		return 0;
+	ret = atmel_hlcdc_layer_update_start(&plane->layer);
+	if (!ret)
+		state->prepared = true;
 
-	return atmel_hlcdc_layer_update_start(&plane->layer);
+	return ret;
+}
+
+static void atmel_hlcdc_plane_cleanup_fb(struct drm_plane *p,
+				const struct drm_plane_state *old_state)
+{
+	/*
+	 * FIXME: we should avoid this const -> non-const cast but it's
+	 * currently the only solution we have to modify the ->prepared
+	 * state and rollback the update request.
+	 * Ideally, we should rework the code to attach all the resources
+	 * to atmel_hlcdc_plane_state (including the DMA desc allocation),
+	 * but this require a complete rework of the atmel_hlcdc_layer
+	 * code.
+	 */
+	struct drm_plane_state *s = (struct drm_plane_state *)old_state;
+	struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
+	struct atmel_hlcdc_plane_state *state =
+			drm_plane_state_to_atmel_hlcdc_plane_state(s);
+
+	/*
+	 * The Request has already been applied or cancelled, nothing to do
+	 * here.
+	 */
+	if (!state->prepared)
+		return;
+
+	atmel_hlcdc_layer_update_rollback(&plane->layer);
+	state->prepared = false;
 }
 
 static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p,
@@ -844,6 +929,7 @@ static void atmel_hlcdc_plane_init_prope
 
 static struct drm_plane_helper_funcs atmel_hlcdc_layer_plane_helper_funcs = {
 	.prepare_fb = atmel_hlcdc_plane_prepare_fb,
+	.cleanup_fb = atmel_hlcdc_plane_cleanup_fb,
 	.atomic_check = atmel_hlcdc_plane_atomic_check,
 	.atomic_update = atmel_hlcdc_plane_atomic_update,
 	.atomic_disable = atmel_hlcdc_plane_atomic_disable,
@@ -883,6 +969,7 @@ atmel_hlcdc_plane_atomic_duplicate_state
 		return NULL;
 
 	copy->disc_updated = false;
+	copy->prepared = false;
 
 	if (copy->base.fb)
 		drm_framebuffer_reference(copy->base.fb);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/bochs/bochs_fbdev.c linux-libre-4.7-gnu/drivers/gpu/drm/bochs/bochs_fbdev.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/bochs/bochs_fbdev.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/bochs/bochs_fbdev.c	2016-07-24 15:23:50.000000000 -0400
@@ -82,7 +82,7 @@ static int bochsfb_create(struct drm_fb_
 
 	bo = gem_to_bochs_bo(gobj);
 
-	ret = ttm_bo_reserve(&bo->bo, true, false, false, NULL);
+	ret = ttm_bo_reserve(&bo->bo, true, false, NULL);
 	if (ret)
 		return ret;
 
@@ -162,22 +162,7 @@ static int bochs_fbdev_destroy(struct bo
 	return 0;
 }
 
-void bochs_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
-			u16 blue, int regno)
-{
-}
-
-void bochs_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
-			u16 *blue, int regno)
-{
-	*red   = regno;
-	*green = regno;
-	*blue  = regno;
-}
-
 static const struct drm_fb_helper_funcs bochs_fb_helper_funcs = {
-	.gamma_set = bochs_fb_gamma_set,
-	.gamma_get = bochs_fb_gamma_get,
 	.fb_probe = bochsfb_create,
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/bochs/bochs_kms.c linux-libre-4.7-gnu/drivers/gpu/drm/bochs/bochs_kms.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/bochs/bochs_kms.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/bochs/bochs_kms.c	2016-07-24 15:23:50.000000000 -0400
@@ -43,7 +43,7 @@ static int bochs_crtc_mode_set_base(stru
 	if (old_fb) {
 		bochs_fb = to_bochs_framebuffer(old_fb);
 		bo = gem_to_bochs_bo(bochs_fb->obj);
-		ret = ttm_bo_reserve(&bo->bo, true, false, false, NULL);
+		ret = ttm_bo_reserve(&bo->bo, true, false, NULL);
 		if (ret) {
 			DRM_ERROR("failed to reserve old_fb bo\n");
 		} else {
@@ -57,7 +57,7 @@ static int bochs_crtc_mode_set_base(stru
 
 	bochs_fb = to_bochs_framebuffer(crtc->primary->fb);
 	bo = gem_to_bochs_bo(bochs_fb->obj);
-	ret = ttm_bo_reserve(&bo->bo, true, false, false, NULL);
+	ret = ttm_bo_reserve(&bo->bo, true, false, NULL);
 	if (ret)
 		return ret;
 
@@ -93,11 +93,6 @@ static void bochs_crtc_commit(struct drm
 {
 }
 
-static void bochs_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
-				 u16 *blue, uint32_t start, uint32_t size)
-{
-}
-
 static int bochs_crtc_page_flip(struct drm_crtc *crtc,
 				struct drm_framebuffer *fb,
 				struct drm_pending_vblank_event *event,
@@ -120,7 +115,6 @@ static int bochs_crtc_page_flip(struct d
 
 /* These provide the minimum set of functions required to handle a CRTC */
 static const struct drm_crtc_funcs bochs_crtc_funcs = {
-	.gamma_set = bochs_crtc_gamma_set,
 	.set_config = drm_crtc_helper_set_config,
 	.destroy = drm_crtc_cleanup,
 	.page_flip = bochs_crtc_page_flip,
@@ -140,7 +134,6 @@ static void bochs_crtc_init(struct drm_d
 	struct drm_crtc *crtc = &bochs->crtc;
 
 	drm_crtc_init(dev, crtc, &bochs_crtc_funcs);
-	drm_mode_crtc_set_gamma_size(crtc, 256);
 	drm_crtc_helper_add(crtc, &bochs_helper_funcs);
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/bochs/bochs_mm.c linux-libre-4.7-gnu/drivers/gpu/drm/bochs/bochs_mm.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/bochs/bochs_mm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/bochs/bochs_mm.c	2016-07-24 15:23:50.000000000 -0400
@@ -212,6 +212,8 @@ struct ttm_bo_driver bochs_bo_driver = {
 	.verify_access = bochs_bo_verify_access,
 	.io_mem_reserve = &bochs_ttm_io_mem_reserve,
 	.io_mem_free = &bochs_ttm_io_mem_free,
+	.lru_tail = &ttm_bo_default_lru_tail,
+	.swap_lru_tail = &ttm_bo_default_swap_lru_tail,
 };
 
 int bochs_mm_init(struct bochs_device *bochs)
@@ -456,7 +458,7 @@ int bochs_dumb_mmap_offset(struct drm_fi
 	struct drm_gem_object *obj;
 	struct bochs_bo *bo;
 
-	obj = drm_gem_object_lookup(dev, file, handle);
+	obj = drm_gem_object_lookup(file, handle);
 	if (obj == NULL)
 		return -ENOENT;
 
@@ -518,7 +520,7 @@ bochs_user_framebuffer_create(struct drm
 	if (mode_cmd->pixel_format != DRM_FORMAT_XRGB8888)
 		return ERR_PTR(-ENOENT);
 
-	obj = drm_gem_object_lookup(dev, filp, mode_cmd->handles[0]);
+	obj = drm_gem_object_lookup(filp, mode_cmd->handles[0]);
 	if (obj == NULL)
 		return ERR_PTR(-ENOENT);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c linux-libre-4.7-gnu/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,1430 @@
+/*
+* Analogix DP (Display Port) core interface driver.
+*
+* Copyright (C) 2012 Samsung Electronics Co., Ltd.
+* Author: Jingoo Han <jg1.han@samsung.com>
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 2 of the License, or (at your
+* option) any later version.
+*/
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/gpio.h>
+#include <linux/component.h>
+#include <linux/phy/phy.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_panel.h>
+
+#include <drm/bridge/analogix_dp.h>
+
+#include "analogix_dp_core.h"
+
+#define to_dp(nm)	container_of(nm, struct analogix_dp_device, nm)
+
+struct bridge_init {
+	struct i2c_client *client;
+	struct device_node *node;
+};
+
+static void analogix_dp_init_dp(struct analogix_dp_device *dp)
+{
+	analogix_dp_reset(dp);
+
+	analogix_dp_swreset(dp);
+
+	analogix_dp_init_analog_param(dp);
+	analogix_dp_init_interrupt(dp);
+
+	/* SW defined function Normal operation */
+	analogix_dp_enable_sw_function(dp);
+
+	analogix_dp_config_interrupt(dp);
+	analogix_dp_init_analog_func(dp);
+
+	analogix_dp_init_hpd(dp);
+	analogix_dp_init_aux(dp);
+}
+
+static int analogix_dp_detect_hpd(struct analogix_dp_device *dp)
+{
+	int timeout_loop = 0;
+
+	while (timeout_loop < DP_TIMEOUT_LOOP_COUNT) {
+		if (analogix_dp_get_plug_in_status(dp) == 0)
+			return 0;
+
+		timeout_loop++;
+		usleep_range(10, 11);
+	}
+
+	/*
+	 * Some edp screen do not have hpd signal, so we can't just
+	 * return failed when hpd plug in detect failed, DT property
+	 * "force-hpd" would indicate whether driver need this.
+	 */
+	if (!dp->force_hpd)
+		return -ETIMEDOUT;
+
+	/*
+	 * The eDP TRM indicate that if HPD_STATUS(RO) is 0, AUX CH
+	 * will not work, so we need to give a force hpd action to
+	 * set HPD_STATUS manually.
+	 */
+	dev_dbg(dp->dev, "failed to get hpd plug status, try to force hpd\n");
+
+	analogix_dp_force_hpd(dp);
+
+	if (analogix_dp_get_plug_in_status(dp) != 0) {
+		dev_err(dp->dev, "failed to get hpd plug in status\n");
+		return -EINVAL;
+	}
+
+	dev_dbg(dp->dev, "success to get plug in status after force hpd\n");
+
+	return 0;
+}
+
+static unsigned char analogix_dp_calc_edid_check_sum(unsigned char *edid_data)
+{
+	int i;
+	unsigned char sum = 0;
+
+	for (i = 0; i < EDID_BLOCK_LENGTH; i++)
+		sum = sum + edid_data[i];
+
+	return sum;
+}
+
+static int analogix_dp_read_edid(struct analogix_dp_device *dp)
+{
+	unsigned char *edid = dp->edid;
+	unsigned int extend_block = 0;
+	unsigned char sum;
+	unsigned char test_vector;
+	int retval;
+
+	/*
+	 * EDID device address is 0x50.
+	 * However, if necessary, you must have set upper address
+	 * into E-EDID in I2C device, 0x30.
+	 */
+
+	/* Read Extension Flag, Number of 128-byte EDID extension blocks */
+	retval = analogix_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
+						EDID_EXTENSION_FLAG,
+						&extend_block);
+	if (retval)
+		return retval;
+
+	if (extend_block > 0) {
+		dev_dbg(dp->dev, "EDID data includes a single extension!\n");
+
+		/* Read EDID data */
+		retval = analogix_dp_read_bytes_from_i2c(dp,
+						I2C_EDID_DEVICE_ADDR,
+						EDID_HEADER_PATTERN,
+						EDID_BLOCK_LENGTH,
+						&edid[EDID_HEADER_PATTERN]);
+		if (retval != 0) {
+			dev_err(dp->dev, "EDID Read failed!\n");
+			return -EIO;
+		}
+		sum = analogix_dp_calc_edid_check_sum(edid);
+		if (sum != 0) {
+			dev_err(dp->dev, "EDID bad checksum!\n");
+			return -EIO;
+		}
+
+		/* Read additional EDID data */
+		retval = analogix_dp_read_bytes_from_i2c(dp,
+				I2C_EDID_DEVICE_ADDR,
+				EDID_BLOCK_LENGTH,
+				EDID_BLOCK_LENGTH,
+				&edid[EDID_BLOCK_LENGTH]);
+		if (retval != 0) {
+			dev_err(dp->dev, "EDID Read failed!\n");
+			return -EIO;
+		}
+		sum = analogix_dp_calc_edid_check_sum(&edid[EDID_BLOCK_LENGTH]);
+		if (sum != 0) {
+			dev_err(dp->dev, "EDID bad checksum!\n");
+			return -EIO;
+		}
+
+		analogix_dp_read_byte_from_dpcd(dp, DP_TEST_REQUEST,
+						&test_vector);
+		if (test_vector & DP_TEST_LINK_EDID_READ) {
+			analogix_dp_write_byte_to_dpcd(dp,
+				DP_TEST_EDID_CHECKSUM,
+				edid[EDID_BLOCK_LENGTH + EDID_CHECKSUM]);
+			analogix_dp_write_byte_to_dpcd(dp,
+				DP_TEST_RESPONSE,
+				DP_TEST_EDID_CHECKSUM_WRITE);
+		}
+	} else {
+		dev_info(dp->dev, "EDID data does not include any extensions.\n");
+
+		/* Read EDID data */
+		retval = analogix_dp_read_bytes_from_i2c(dp,
+				I2C_EDID_DEVICE_ADDR, EDID_HEADER_PATTERN,
+				EDID_BLOCK_LENGTH, &edid[EDID_HEADER_PATTERN]);
+		if (retval != 0) {
+			dev_err(dp->dev, "EDID Read failed!\n");
+			return -EIO;
+		}
+		sum = analogix_dp_calc_edid_check_sum(edid);
+		if (sum != 0) {
+			dev_err(dp->dev, "EDID bad checksum!\n");
+			return -EIO;
+		}
+
+		analogix_dp_read_byte_from_dpcd(dp, DP_TEST_REQUEST,
+						&test_vector);
+		if (test_vector & DP_TEST_LINK_EDID_READ) {
+			analogix_dp_write_byte_to_dpcd(dp,
+				DP_TEST_EDID_CHECKSUM, edid[EDID_CHECKSUM]);
+			analogix_dp_write_byte_to_dpcd(dp,
+				DP_TEST_RESPONSE, DP_TEST_EDID_CHECKSUM_WRITE);
+		}
+	}
+
+	dev_dbg(dp->dev, "EDID Read success!\n");
+	return 0;
+}
+
+static int analogix_dp_handle_edid(struct analogix_dp_device *dp)
+{
+	u8 buf[12];
+	int i;
+	int retval;
+
+	/* Read DPCD DP_DPCD_REV~RECEIVE_PORT1_CAP_1 */
+	retval = analogix_dp_read_bytes_from_dpcd(dp, DP_DPCD_REV, 12, buf);
+	if (retval)
+		return retval;
+
+	/* Read EDID */
+	for (i = 0; i < 3; i++) {
+		retval = analogix_dp_read_edid(dp);
+		if (!retval)
+			break;
+	}
+
+	return retval;
+}
+
+static void
+analogix_dp_enable_rx_to_enhanced_mode(struct analogix_dp_device *dp,
+				       bool enable)
+{
+	u8 data;
+
+	analogix_dp_read_byte_from_dpcd(dp, DP_LANE_COUNT_SET, &data);
+
+	if (enable)
+		analogix_dp_write_byte_to_dpcd(dp, DP_LANE_COUNT_SET,
+					       DP_LANE_COUNT_ENHANCED_FRAME_EN |
+					       DPCD_LANE_COUNT_SET(data));
+	else
+		analogix_dp_write_byte_to_dpcd(dp, DP_LANE_COUNT_SET,
+					       DPCD_LANE_COUNT_SET(data));
+}
+
+static int analogix_dp_is_enhanced_mode_available(struct analogix_dp_device *dp)
+{
+	u8 data;
+	int retval;
+
+	analogix_dp_read_byte_from_dpcd(dp, DP_MAX_LANE_COUNT, &data);
+	retval = DPCD_ENHANCED_FRAME_CAP(data);
+
+	return retval;
+}
+
+static void analogix_dp_set_enhanced_mode(struct analogix_dp_device *dp)
+{
+	u8 data;
+
+	data = analogix_dp_is_enhanced_mode_available(dp);
+	analogix_dp_enable_rx_to_enhanced_mode(dp, data);
+	analogix_dp_enable_enhanced_mode(dp, data);
+}
+
+static void analogix_dp_training_pattern_dis(struct analogix_dp_device *dp)
+{
+	analogix_dp_set_training_pattern(dp, DP_NONE);
+
+	analogix_dp_write_byte_to_dpcd(dp, DP_TRAINING_PATTERN_SET,
+				       DP_TRAINING_PATTERN_DISABLE);
+}
+
+static void
+analogix_dp_set_lane_lane_pre_emphasis(struct analogix_dp_device *dp,
+				       int pre_emphasis, int lane)
+{
+	switch (lane) {
+	case 0:
+		analogix_dp_set_lane0_pre_emphasis(dp, pre_emphasis);
+		break;
+	case 1:
+		analogix_dp_set_lane1_pre_emphasis(dp, pre_emphasis);
+		break;
+
+	case 2:
+		analogix_dp_set_lane2_pre_emphasis(dp, pre_emphasis);
+		break;
+
+	case 3:
+		analogix_dp_set_lane3_pre_emphasis(dp, pre_emphasis);
+		break;
+	}
+}
+
+static int analogix_dp_link_start(struct analogix_dp_device *dp)
+{
+	u8 buf[4];
+	int lane, lane_count, pll_tries, retval;
+
+	lane_count = dp->link_train.lane_count;
+
+	dp->link_train.lt_state = CLOCK_RECOVERY;
+	dp->link_train.eq_loop = 0;
+
+	for (lane = 0; lane < lane_count; lane++)
+		dp->link_train.cr_loop[lane] = 0;
+
+	/* Set link rate and count as you want to establish*/
+	analogix_dp_set_link_bandwidth(dp, dp->link_train.link_rate);
+	analogix_dp_set_lane_count(dp, dp->link_train.lane_count);
+
+	/* Setup RX configuration */
+	buf[0] = dp->link_train.link_rate;
+	buf[1] = dp->link_train.lane_count;
+	retval = analogix_dp_write_bytes_to_dpcd(dp, DP_LINK_BW_SET, 2, buf);
+	if (retval)
+		return retval;
+
+	/* Set TX pre-emphasis to minimum */
+	for (lane = 0; lane < lane_count; lane++)
+		analogix_dp_set_lane_lane_pre_emphasis(dp,
+			PRE_EMPHASIS_LEVEL_0, lane);
+
+	/* Wait for PLL lock */
+	pll_tries = 0;
+	while (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
+		if (pll_tries == DP_TIMEOUT_LOOP_COUNT) {
+			dev_err(dp->dev, "Wait for PLL lock timed out\n");
+			return -ETIMEDOUT;
+		}
+
+		pll_tries++;
+		usleep_range(90, 120);
+	}
+
+	/* Set training pattern 1 */
+	analogix_dp_set_training_pattern(dp, TRAINING_PTN1);
+
+	/* Set RX training pattern */
+	retval = analogix_dp_write_byte_to_dpcd(dp,
+			DP_TRAINING_PATTERN_SET,
+			DP_LINK_SCRAMBLING_DISABLE | DP_TRAINING_PATTERN_1);
+	if (retval)
+		return retval;
+
+	for (lane = 0; lane < lane_count; lane++)
+		buf[lane] = DP_TRAIN_PRE_EMPH_LEVEL_0 |
+			    DP_TRAIN_VOLTAGE_SWING_LEVEL_0;
+
+	retval = analogix_dp_write_bytes_to_dpcd(dp, DP_TRAINING_LANE0_SET,
+						 lane_count, buf);
+
+	return retval;
+}
+
+static unsigned char analogix_dp_get_lane_status(u8 link_status[2], int lane)
+{
+	int shift = (lane & 1) * 4;
+	u8 link_value = link_status[lane >> 1];
+
+	return (link_value >> shift) & 0xf;
+}
+
+static int analogix_dp_clock_recovery_ok(u8 link_status[2], int lane_count)
+{
+	int lane;
+	u8 lane_status;
+
+	for (lane = 0; lane < lane_count; lane++) {
+		lane_status = analogix_dp_get_lane_status(link_status, lane);
+		if ((lane_status & DP_LANE_CR_DONE) == 0)
+			return -EINVAL;
+	}
+	return 0;
+}
+
+static int analogix_dp_channel_eq_ok(u8 link_status[2], u8 link_align,
+				     int lane_count)
+{
+	int lane;
+	u8 lane_status;
+
+	if ((link_align & DP_INTERLANE_ALIGN_DONE) == 0)
+		return -EINVAL;
+
+	for (lane = 0; lane < lane_count; lane++) {
+		lane_status = analogix_dp_get_lane_status(link_status, lane);
+		lane_status &= DP_CHANNEL_EQ_BITS;
+		if (lane_status != DP_CHANNEL_EQ_BITS)
+			return -EINVAL;
+	}
+
+	return 0;
+}
+
+static unsigned char
+analogix_dp_get_adjust_request_voltage(u8 adjust_request[2], int lane)
+{
+	int shift = (lane & 1) * 4;
+	u8 link_value = adjust_request[lane >> 1];
+
+	return (link_value >> shift) & 0x3;
+}
+
+static unsigned char analogix_dp_get_adjust_request_pre_emphasis(
+					u8 adjust_request[2],
+					int lane)
+{
+	int shift = (lane & 1) * 4;
+	u8 link_value = adjust_request[lane >> 1];
+
+	return ((link_value >> shift) & 0xc) >> 2;
+}
+
+static void analogix_dp_set_lane_link_training(struct analogix_dp_device *dp,
+					       u8 training_lane_set, int lane)
+{
+	switch (lane) {
+	case 0:
+		analogix_dp_set_lane0_link_training(dp, training_lane_set);
+		break;
+	case 1:
+		analogix_dp_set_lane1_link_training(dp, training_lane_set);
+		break;
+
+	case 2:
+		analogix_dp_set_lane2_link_training(dp, training_lane_set);
+		break;
+
+	case 3:
+		analogix_dp_set_lane3_link_training(dp, training_lane_set);
+		break;
+	}
+}
+
+static unsigned int
+analogix_dp_get_lane_link_training(struct analogix_dp_device *dp,
+				   int lane)
+{
+	u32 reg;
+
+	switch (lane) {
+	case 0:
+		reg = analogix_dp_get_lane0_link_training(dp);
+		break;
+	case 1:
+		reg = analogix_dp_get_lane1_link_training(dp);
+		break;
+	case 2:
+		reg = analogix_dp_get_lane2_link_training(dp);
+		break;
+	case 3:
+		reg = analogix_dp_get_lane3_link_training(dp);
+		break;
+	default:
+		WARN_ON(1);
+		return 0;
+	}
+
+	return reg;
+}
+
+static void analogix_dp_reduce_link_rate(struct analogix_dp_device *dp)
+{
+	analogix_dp_training_pattern_dis(dp);
+	analogix_dp_set_enhanced_mode(dp);
+
+	dp->link_train.lt_state = FAILED;
+}
+
+static void analogix_dp_get_adjust_training_lane(struct analogix_dp_device *dp,
+						 u8 adjust_request[2])
+{
+	int lane, lane_count;
+	u8 voltage_swing, pre_emphasis, training_lane;
+
+	lane_count = dp->link_train.lane_count;
+	for (lane = 0; lane < lane_count; lane++) {
+		voltage_swing = analogix_dp_get_adjust_request_voltage(
+						adjust_request, lane);
+		pre_emphasis = analogix_dp_get_adjust_request_pre_emphasis(
+						adjust_request, lane);
+		training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
+				DPCD_PRE_EMPHASIS_SET(pre_emphasis);
+
+		if (voltage_swing == VOLTAGE_LEVEL_3)
+			training_lane |= DP_TRAIN_MAX_SWING_REACHED;
+		if (pre_emphasis == PRE_EMPHASIS_LEVEL_3)
+			training_lane |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
+
+		dp->link_train.training_lane[lane] = training_lane;
+	}
+}
+
+static int analogix_dp_process_clock_recovery(struct analogix_dp_device *dp)
+{
+	int lane, lane_count, retval;
+	u8 voltage_swing, pre_emphasis, training_lane;
+	u8 link_status[2], adjust_request[2];
+
+	usleep_range(100, 101);
+
+	lane_count = dp->link_train.lane_count;
+
+	retval =  analogix_dp_read_bytes_from_dpcd(dp,
+			DP_LANE0_1_STATUS, 2, link_status);
+	if (retval)
+		return retval;
+
+	retval =  analogix_dp_read_bytes_from_dpcd(dp,
+			DP_ADJUST_REQUEST_LANE0_1, 2, adjust_request);
+	if (retval)
+		return retval;
+
+	if (analogix_dp_clock_recovery_ok(link_status, lane_count) == 0) {
+		/* set training pattern 2 for EQ */
+		analogix_dp_set_training_pattern(dp, TRAINING_PTN2);
+
+		retval = analogix_dp_write_byte_to_dpcd(dp,
+				DP_TRAINING_PATTERN_SET,
+				DP_LINK_SCRAMBLING_DISABLE |
+				DP_TRAINING_PATTERN_2);
+		if (retval)
+			return retval;
+
+		dev_info(dp->dev, "Link Training Clock Recovery success\n");
+		dp->link_train.lt_state = EQUALIZER_TRAINING;
+	} else {
+		for (lane = 0; lane < lane_count; lane++) {
+			training_lane = analogix_dp_get_lane_link_training(
+							dp, lane);
+			voltage_swing = analogix_dp_get_adjust_request_voltage(
+							adjust_request, lane);
+			pre_emphasis = analogix_dp_get_adjust_request_pre_emphasis(
+							adjust_request, lane);
+
+			if (DPCD_VOLTAGE_SWING_GET(training_lane) ==
+					voltage_swing &&
+			    DPCD_PRE_EMPHASIS_GET(training_lane) ==
+					pre_emphasis)
+				dp->link_train.cr_loop[lane]++;
+
+			if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP ||
+			    voltage_swing == VOLTAGE_LEVEL_3 ||
+			    pre_emphasis == PRE_EMPHASIS_LEVEL_3) {
+				dev_err(dp->dev, "CR Max reached (%d,%d,%d)\n",
+					dp->link_train.cr_loop[lane],
+					voltage_swing, pre_emphasis);
+				analogix_dp_reduce_link_rate(dp);
+				return -EIO;
+			}
+		}
+	}
+
+	analogix_dp_get_adjust_training_lane(dp, adjust_request);
+
+	for (lane = 0; lane < lane_count; lane++)
+		analogix_dp_set_lane_link_training(dp,
+			dp->link_train.training_lane[lane], lane);
+
+	retval = analogix_dp_write_bytes_to_dpcd(dp,
+			DP_TRAINING_LANE0_SET, lane_count,
+			dp->link_train.training_lane);
+	if (retval)
+		return retval;
+
+	return retval;
+}
+
+static int analogix_dp_process_equalizer_training(struct analogix_dp_device *dp)
+{
+	int lane, lane_count, retval;
+	u32 reg;
+	u8 link_align, link_status[2], adjust_request[2];
+
+	usleep_range(400, 401);
+
+	lane_count = dp->link_train.lane_count;
+
+	retval = analogix_dp_read_bytes_from_dpcd(dp,
+			DP_LANE0_1_STATUS, 2, link_status);
+	if (retval)
+		return retval;
+
+	if (analogix_dp_clock_recovery_ok(link_status, lane_count)) {
+		analogix_dp_reduce_link_rate(dp);
+		return -EIO;
+	}
+
+	retval = analogix_dp_read_bytes_from_dpcd(dp,
+			DP_ADJUST_REQUEST_LANE0_1, 2, adjust_request);
+	if (retval)
+		return retval;
+
+	retval = analogix_dp_read_byte_from_dpcd(dp,
+			DP_LANE_ALIGN_STATUS_UPDATED, &link_align);
+	if (retval)
+		return retval;
+
+	analogix_dp_get_adjust_training_lane(dp, adjust_request);
+
+	if (!analogix_dp_channel_eq_ok(link_status, link_align, lane_count)) {
+		/* traing pattern Set to Normal */
+		analogix_dp_training_pattern_dis(dp);
+
+		dev_info(dp->dev, "Link Training success!\n");
+
+		analogix_dp_get_link_bandwidth(dp, &reg);
+		dp->link_train.link_rate = reg;
+		dev_dbg(dp->dev, "final bandwidth = %.2x\n",
+			dp->link_train.link_rate);
+
+		analogix_dp_get_lane_count(dp, &reg);
+		dp->link_train.lane_count = reg;
+		dev_dbg(dp->dev, "final lane count = %.2x\n",
+			dp->link_train.lane_count);
+
+		/* set enhanced mode if available */
+		analogix_dp_set_enhanced_mode(dp);
+		dp->link_train.lt_state = FINISHED;
+
+		return 0;
+	}
+
+	/* not all locked */
+	dp->link_train.eq_loop++;
+
+	if (dp->link_train.eq_loop > MAX_EQ_LOOP) {
+		dev_err(dp->dev, "EQ Max loop\n");
+		analogix_dp_reduce_link_rate(dp);
+		return -EIO;
+	}
+
+	for (lane = 0; lane < lane_count; lane++)
+		analogix_dp_set_lane_link_training(dp,
+			dp->link_train.training_lane[lane], lane);
+
+	retval = analogix_dp_write_bytes_to_dpcd(dp, DP_TRAINING_LANE0_SET,
+			lane_count, dp->link_train.training_lane);
+
+	return retval;
+}
+
+static void analogix_dp_get_max_rx_bandwidth(struct analogix_dp_device *dp,
+					     u8 *bandwidth)
+{
+	u8 data;
+
+	/*
+	 * For DP rev.1.1, Maximum link rate of Main Link lanes
+	 * 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps
+	 * For DP rev.1.2, Maximum link rate of Main Link lanes
+	 * 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps, 0x14 = 5.4Gbps
+	 */
+	analogix_dp_read_byte_from_dpcd(dp, DP_MAX_LINK_RATE, &data);
+	*bandwidth = data;
+}
+
+static void analogix_dp_get_max_rx_lane_count(struct analogix_dp_device *dp,
+					      u8 *lane_count)
+{
+	u8 data;
+
+	/*
+	 * For DP rev.1.1, Maximum number of Main Link lanes
+	 * 0x01 = 1 lane, 0x02 = 2 lanes, 0x04 = 4 lanes
+	 */
+	analogix_dp_read_byte_from_dpcd(dp, DP_MAX_LANE_COUNT, &data);
+	*lane_count = DPCD_MAX_LANE_COUNT(data);
+}
+
+static void analogix_dp_init_training(struct analogix_dp_device *dp,
+				      enum link_lane_count_type max_lane,
+				      int max_rate)
+{
+	/*
+	 * MACRO_RST must be applied after the PLL_LOCK to avoid
+	 * the DP inter pair skew issue for at least 10 us
+	 */
+	analogix_dp_reset_macro(dp);
+
+	/* Initialize by reading RX's DPCD */
+	analogix_dp_get_max_rx_bandwidth(dp, &dp->link_train.link_rate);
+	analogix_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count);
+
+	if ((dp->link_train.link_rate != DP_LINK_BW_1_62) &&
+	    (dp->link_train.link_rate != DP_LINK_BW_2_7) &&
+	    (dp->link_train.link_rate != DP_LINK_BW_5_4)) {
+		dev_err(dp->dev, "Rx Max Link Rate is abnormal :%x !\n",
+			dp->link_train.link_rate);
+		dp->link_train.link_rate = DP_LINK_BW_1_62;
+	}
+
+	if (dp->link_train.lane_count == 0) {
+		dev_err(dp->dev, "Rx Max Lane count is abnormal :%x !\n",
+			dp->link_train.lane_count);
+		dp->link_train.lane_count = (u8)LANE_COUNT1;
+	}
+
+	/* Setup TX lane count & rate */
+	if (dp->link_train.lane_count > max_lane)
+		dp->link_train.lane_count = max_lane;
+	if (dp->link_train.link_rate > max_rate)
+		dp->link_train.link_rate = max_rate;
+
+	/* All DP analog module power up */
+	analogix_dp_set_analog_power_down(dp, POWER_ALL, 0);
+}
+
+static int analogix_dp_sw_link_training(struct analogix_dp_device *dp)
+{
+	int retval = 0, training_finished = 0;
+
+	dp->link_train.lt_state = START;
+
+	/* Process here */
+	while (!retval && !training_finished) {
+		switch (dp->link_train.lt_state) {
+		case START:
+			retval = analogix_dp_link_start(dp);
+			if (retval)
+				dev_err(dp->dev, "LT link start failed!\n");
+			break;
+		case CLOCK_RECOVERY:
+			retval = analogix_dp_process_clock_recovery(dp);
+			if (retval)
+				dev_err(dp->dev, "LT CR failed!\n");
+			break;
+		case EQUALIZER_TRAINING:
+			retval = analogix_dp_process_equalizer_training(dp);
+			if (retval)
+				dev_err(dp->dev, "LT EQ failed!\n");
+			break;
+		case FINISHED:
+			training_finished = 1;
+			break;
+		case FAILED:
+			return -EREMOTEIO;
+		}
+	}
+	if (retval)
+		dev_err(dp->dev, "eDP link training failed (%d)\n", retval);
+
+	return retval;
+}
+
+static int analogix_dp_set_link_train(struct analogix_dp_device *dp,
+				      u32 count, u32 bwtype)
+{
+	int i;
+	int retval;
+
+	for (i = 0; i < DP_TIMEOUT_LOOP_COUNT; i++) {
+		analogix_dp_init_training(dp, count, bwtype);
+		retval = analogix_dp_sw_link_training(dp);
+		if (retval == 0)
+			break;
+
+		usleep_range(100, 110);
+	}
+
+	return retval;
+}
+
+static int analogix_dp_config_video(struct analogix_dp_device *dp)
+{
+	int retval = 0;
+	int timeout_loop = 0;
+	int done_count = 0;
+
+	analogix_dp_config_video_slave_mode(dp);
+
+	analogix_dp_set_video_color_format(dp);
+
+	if (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
+		dev_err(dp->dev, "PLL is not locked yet.\n");
+		return -EINVAL;
+	}
+
+	for (;;) {
+		timeout_loop++;
+		if (analogix_dp_is_slave_video_stream_clock_on(dp) == 0)
+			break;
+		if (timeout_loop > DP_TIMEOUT_LOOP_COUNT) {
+			dev_err(dp->dev, "Timeout of video streamclk ok\n");
+			return -ETIMEDOUT;
+		}
+
+		usleep_range(1, 2);
+	}
+
+	/* Set to use the register calculated M/N video */
+	analogix_dp_set_video_cr_mn(dp, CALCULATED_M, 0, 0);
+
+	/* For video bist, Video timing must be generated by register */
+	analogix_dp_set_video_timing_mode(dp, VIDEO_TIMING_FROM_CAPTURE);
+
+	/* Disable video mute */
+	analogix_dp_enable_video_mute(dp, 0);
+
+	/* Configure video slave mode */
+	analogix_dp_enable_video_master(dp, 0);
+
+	timeout_loop = 0;
+
+	for (;;) {
+		timeout_loop++;
+		if (analogix_dp_is_video_stream_on(dp) == 0) {
+			done_count++;
+			if (done_count > 10)
+				break;
+		} else if (done_count) {
+			done_count = 0;
+		}
+		if (timeout_loop > DP_TIMEOUT_LOOP_COUNT) {
+			dev_err(dp->dev, "Timeout of video streamclk ok\n");
+			return -ETIMEDOUT;
+		}
+
+		usleep_range(1000, 1001);
+	}
+
+	if (retval != 0)
+		dev_err(dp->dev, "Video stream is not detected!\n");
+
+	return retval;
+}
+
+static void analogix_dp_enable_scramble(struct analogix_dp_device *dp,
+					bool enable)
+{
+	u8 data;
+
+	if (enable) {
+		analogix_dp_enable_scrambling(dp);
+
+		analogix_dp_read_byte_from_dpcd(dp, DP_TRAINING_PATTERN_SET,
+						&data);
+		analogix_dp_write_byte_to_dpcd(dp,
+			DP_TRAINING_PATTERN_SET,
+			(u8)(data & ~DP_LINK_SCRAMBLING_DISABLE));
+	} else {
+		analogix_dp_disable_scrambling(dp);
+
+		analogix_dp_read_byte_from_dpcd(dp, DP_TRAINING_PATTERN_SET,
+						&data);
+		analogix_dp_write_byte_to_dpcd(dp,
+			DP_TRAINING_PATTERN_SET,
+			(u8)(data | DP_LINK_SCRAMBLING_DISABLE));
+	}
+}
+
+static irqreturn_t analogix_dp_hardirq(int irq, void *arg)
+{
+	struct analogix_dp_device *dp = arg;
+	irqreturn_t ret = IRQ_NONE;
+	enum dp_irq_type irq_type;
+
+	irq_type = analogix_dp_get_irq_type(dp);
+	if (irq_type != DP_IRQ_TYPE_UNKNOWN) {
+		analogix_dp_mute_hpd_interrupt(dp);
+		ret = IRQ_WAKE_THREAD;
+	}
+
+	return ret;
+}
+
+static irqreturn_t analogix_dp_irq_thread(int irq, void *arg)
+{
+	struct analogix_dp_device *dp = arg;
+	enum dp_irq_type irq_type;
+
+	irq_type = analogix_dp_get_irq_type(dp);
+	if (irq_type & DP_IRQ_TYPE_HP_CABLE_IN ||
+	    irq_type & DP_IRQ_TYPE_HP_CABLE_OUT) {
+		dev_dbg(dp->dev, "Detected cable status changed!\n");
+		if (dp->drm_dev)
+			drm_helper_hpd_irq_event(dp->drm_dev);
+	}
+
+	if (irq_type != DP_IRQ_TYPE_UNKNOWN) {
+		analogix_dp_clear_hotplug_interrupts(dp);
+		analogix_dp_unmute_hpd_interrupt(dp);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static void analogix_dp_commit(struct analogix_dp_device *dp)
+{
+	int ret;
+
+	/* Keep the panel disabled while we configure video */
+	if (dp->plat_data->panel) {
+		if (drm_panel_disable(dp->plat_data->panel))
+			DRM_ERROR("failed to disable the panel\n");
+	}
+
+	ret = analogix_dp_set_link_train(dp, dp->video_info.max_lane_count,
+					 dp->video_info.max_link_rate);
+	if (ret) {
+		dev_err(dp->dev, "unable to do link train\n");
+		return;
+	}
+
+	analogix_dp_enable_scramble(dp, 1);
+	analogix_dp_enable_rx_to_enhanced_mode(dp, 1);
+	analogix_dp_enable_enhanced_mode(dp, 1);
+
+	analogix_dp_init_video(dp);
+	ret = analogix_dp_config_video(dp);
+	if (ret)
+		dev_err(dp->dev, "unable to config video\n");
+
+	/* Safe to enable the panel now */
+	if (dp->plat_data->panel) {
+		if (drm_panel_enable(dp->plat_data->panel))
+			DRM_ERROR("failed to enable the panel\n");
+	}
+
+	/* Enable video */
+	analogix_dp_start_video(dp);
+}
+
+int analogix_dp_get_modes(struct drm_connector *connector)
+{
+	struct analogix_dp_device *dp = to_dp(connector);
+	struct edid *edid = (struct edid *)dp->edid;
+	int num_modes = 0;
+
+	if (analogix_dp_handle_edid(dp) == 0) {
+		drm_mode_connector_update_edid_property(&dp->connector, edid);
+		num_modes += drm_add_edid_modes(&dp->connector, edid);
+	}
+
+	if (dp->plat_data->panel)
+		num_modes += drm_panel_get_modes(dp->plat_data->panel);
+
+	if (dp->plat_data->get_modes)
+		num_modes += dp->plat_data->get_modes(dp->plat_data);
+
+	return num_modes;
+}
+
+static struct drm_encoder *
+analogix_dp_best_encoder(struct drm_connector *connector)
+{
+	struct analogix_dp_device *dp = to_dp(connector);
+
+	return dp->encoder;
+}
+
+static const struct drm_connector_helper_funcs analogix_dp_connector_helper_funcs = {
+	.get_modes = analogix_dp_get_modes,
+	.best_encoder = analogix_dp_best_encoder,
+};
+
+enum drm_connector_status
+analogix_dp_detect(struct drm_connector *connector, bool force)
+{
+	struct analogix_dp_device *dp = to_dp(connector);
+
+	if (analogix_dp_detect_hpd(dp))
+		return connector_status_disconnected;
+
+	return connector_status_connected;
+}
+
+static void analogix_dp_connector_destroy(struct drm_connector *connector)
+{
+	drm_connector_unregister(connector);
+	drm_connector_cleanup(connector);
+
+}
+
+static const struct drm_connector_funcs analogix_dp_connector_funcs = {
+	.dpms = drm_atomic_helper_connector_dpms,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.detect = analogix_dp_detect,
+	.destroy = analogix_dp_connector_destroy,
+	.reset = drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static int analogix_dp_bridge_attach(struct drm_bridge *bridge)
+{
+	struct analogix_dp_device *dp = bridge->driver_private;
+	struct drm_encoder *encoder = dp->encoder;
+	struct drm_connector *connector = &dp->connector;
+	int ret;
+
+	if (!bridge->encoder) {
+		DRM_ERROR("Parent encoder object not found");
+		return -ENODEV;
+	}
+
+	connector->polled = DRM_CONNECTOR_POLL_HPD;
+
+	ret = drm_connector_init(dp->drm_dev, connector,
+				 &analogix_dp_connector_funcs,
+				 DRM_MODE_CONNECTOR_eDP);
+	if (ret) {
+		DRM_ERROR("Failed to initialize connector with drm\n");
+		return ret;
+	}
+
+	drm_connector_helper_add(connector,
+				 &analogix_dp_connector_helper_funcs);
+	drm_mode_connector_attach_encoder(connector, encoder);
+
+	/*
+	 * NOTE: the connector registration is implemented in analogix
+	 * platform driver, that to say connector would be exist after
+	 * plat_data->attch return, that's why we record the connector
+	 * point after plat attached.
+	 */
+	 if (dp->plat_data->attach) {
+		 ret = dp->plat_data->attach(dp->plat_data, bridge, connector);
+		 if (ret) {
+			 DRM_ERROR("Failed at platform attch func\n");
+			 return ret;
+		 }
+	}
+
+	if (dp->plat_data->panel) {
+		ret = drm_panel_attach(dp->plat_data->panel, &dp->connector);
+		if (ret) {
+			DRM_ERROR("Failed to attach panel\n");
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static void analogix_dp_bridge_enable(struct drm_bridge *bridge)
+{
+	struct analogix_dp_device *dp = bridge->driver_private;
+
+	if (dp->dpms_mode == DRM_MODE_DPMS_ON)
+		return;
+
+	pm_runtime_get_sync(dp->dev);
+
+	if (dp->plat_data->power_on)
+		dp->plat_data->power_on(dp->plat_data);
+
+	phy_power_on(dp->phy);
+	analogix_dp_init_dp(dp);
+	enable_irq(dp->irq);
+	analogix_dp_commit(dp);
+
+	dp->dpms_mode = DRM_MODE_DPMS_ON;
+}
+
+static void analogix_dp_bridge_disable(struct drm_bridge *bridge)
+{
+	struct analogix_dp_device *dp = bridge->driver_private;
+
+	if (dp->dpms_mode != DRM_MODE_DPMS_ON)
+		return;
+
+	if (dp->plat_data->panel) {
+		if (drm_panel_disable(dp->plat_data->panel)) {
+			DRM_ERROR("failed to disable the panel\n");
+			return;
+		}
+	}
+
+	disable_irq(dp->irq);
+	phy_power_off(dp->phy);
+
+	if (dp->plat_data->power_off)
+		dp->plat_data->power_off(dp->plat_data);
+
+	pm_runtime_put_sync(dp->dev);
+
+	dp->dpms_mode = DRM_MODE_DPMS_OFF;
+}
+
+static void analogix_dp_bridge_mode_set(struct drm_bridge *bridge,
+					struct drm_display_mode *orig_mode,
+					struct drm_display_mode *mode)
+{
+	struct analogix_dp_device *dp = bridge->driver_private;
+	struct drm_display_info *display_info = &dp->connector.display_info;
+	struct video_info *video = &dp->video_info;
+	struct device_node *dp_node = dp->dev->of_node;
+	int vic;
+
+	/* Input video interlaces & hsync pol & vsync pol */
+	video->interlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
+	video->v_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NVSYNC);
+	video->h_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NHSYNC);
+
+	/* Input video dynamic_range & colorimetry */
+	vic = drm_match_cea_mode(mode);
+	if ((vic == 6) || (vic == 7) || (vic == 21) || (vic == 22) ||
+	    (vic == 2) || (vic == 3) || (vic == 17) || (vic == 18)) {
+		video->dynamic_range = CEA;
+		video->ycbcr_coeff = COLOR_YCBCR601;
+	} else if (vic) {
+		video->dynamic_range = CEA;
+		video->ycbcr_coeff = COLOR_YCBCR709;
+	} else {
+		video->dynamic_range = VESA;
+		video->ycbcr_coeff = COLOR_YCBCR709;
+	}
+
+	/* Input vide bpc and color_formats */
+	switch (display_info->bpc) {
+	case 12:
+		video->color_depth = COLOR_12;
+		break;
+	case 10:
+		video->color_depth = COLOR_10;
+		break;
+	case 8:
+		video->color_depth = COLOR_8;
+		break;
+	case 6:
+		video->color_depth = COLOR_6;
+		break;
+	default:
+		video->color_depth = COLOR_8;
+		break;
+	}
+	if (display_info->color_formats & DRM_COLOR_FORMAT_YCRCB444)
+		video->color_space = COLOR_YCBCR444;
+	else if (display_info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
+		video->color_space = COLOR_YCBCR422;
+	else if (display_info->color_formats & DRM_COLOR_FORMAT_RGB444)
+		video->color_space = COLOR_RGB;
+	else
+		video->color_space = COLOR_RGB;
+
+	/*
+	 * NOTE: those property parsing code is used for providing backward
+	 * compatibility for samsung platform.
+	 * Due to we used the "of_property_read_u32" interfaces, when this
+	 * property isn't present, the "video_info" can keep the original
+	 * values and wouldn't be modified.
+	 */
+	of_property_read_u32(dp_node, "samsung,color-space",
+			     &video->color_space);
+	of_property_read_u32(dp_node, "samsung,dynamic-range",
+			     &video->dynamic_range);
+	of_property_read_u32(dp_node, "samsung,ycbcr-coeff",
+			     &video->ycbcr_coeff);
+	of_property_read_u32(dp_node, "samsung,color-depth",
+			     &video->color_depth);
+	if (of_property_read_bool(dp_node, "hsync-active-high"))
+		video->h_sync_polarity = true;
+	if (of_property_read_bool(dp_node, "vsync-active-high"))
+		video->v_sync_polarity = true;
+	if (of_property_read_bool(dp_node, "interlaced"))
+		video->interlaced = true;
+}
+
+static void analogix_dp_bridge_nop(struct drm_bridge *bridge)
+{
+	/* do nothing */
+}
+
+static const struct drm_bridge_funcs analogix_dp_bridge_funcs = {
+	.enable = analogix_dp_bridge_enable,
+	.disable = analogix_dp_bridge_disable,
+	.pre_enable = analogix_dp_bridge_nop,
+	.post_disable = analogix_dp_bridge_nop,
+	.mode_set = analogix_dp_bridge_mode_set,
+	.attach = analogix_dp_bridge_attach,
+};
+
+static int analogix_dp_create_bridge(struct drm_device *drm_dev,
+				     struct analogix_dp_device *dp)
+{
+	struct drm_bridge *bridge;
+	int ret;
+
+	bridge = devm_kzalloc(drm_dev->dev, sizeof(*bridge), GFP_KERNEL);
+	if (!bridge) {
+		DRM_ERROR("failed to allocate for drm bridge\n");
+		return -ENOMEM;
+	}
+
+	dp->bridge = bridge;
+
+	dp->encoder->bridge = bridge;
+	bridge->driver_private = dp;
+	bridge->encoder = dp->encoder;
+	bridge->funcs = &analogix_dp_bridge_funcs;
+
+	ret = drm_bridge_attach(drm_dev, bridge);
+	if (ret) {
+		DRM_ERROR("failed to attach drm bridge\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int analogix_dp_dt_parse_pdata(struct analogix_dp_device *dp)
+{
+	struct device_node *dp_node = dp->dev->of_node;
+	struct video_info *video_info = &dp->video_info;
+
+	switch (dp->plat_data->dev_type) {
+	case RK3288_DP:
+		/*
+		 * Like Rk3288 DisplayPort TRM indicate that "Main link
+		 * containing 4 physical lanes of 2.7/1.62 Gbps/lane".
+		 */
+		video_info->max_link_rate = 0x0A;
+		video_info->max_lane_count = 0x04;
+		break;
+	case EXYNOS_DP:
+		/*
+		 * NOTE: those property parseing code is used for
+		 * providing backward compatibility for samsung platform.
+		 */
+		of_property_read_u32(dp_node, "samsung,link-rate",
+				     &video_info->max_link_rate);
+		of_property_read_u32(dp_node, "samsung,lane-count",
+				     &video_info->max_lane_count);
+		break;
+	}
+
+	return 0;
+}
+
+int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
+		     struct analogix_dp_plat_data *plat_data)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct analogix_dp_device *dp;
+	struct resource *res;
+	unsigned int irq_flags;
+	int ret;
+
+	if (!plat_data) {
+		dev_err(dev, "Invalided input plat_data\n");
+		return -EINVAL;
+	}
+
+	dp = devm_kzalloc(dev, sizeof(struct analogix_dp_device), GFP_KERNEL);
+	if (!dp)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, dp);
+
+	dp->dev = &pdev->dev;
+	dp->dpms_mode = DRM_MODE_DPMS_OFF;
+
+	/*
+	 * platform dp driver need containor_of the plat_data to get
+	 * the driver private data, so we need to store the point of
+	 * plat_data, not the context of plat_data.
+	 */
+	dp->plat_data = plat_data;
+
+	ret = analogix_dp_dt_parse_pdata(dp);
+	if (ret)
+		return ret;
+
+	dp->phy = devm_phy_get(dp->dev, "dp");
+	if (IS_ERR(dp->phy)) {
+		dev_err(dp->dev, "no DP phy configured\n");
+		ret = PTR_ERR(dp->phy);
+		if (ret) {
+			/*
+			 * phy itself is not enabled, so we can move forward
+			 * assigning NULL to phy pointer.
+			 */
+			if (ret == -ENOSYS || ret == -ENODEV)
+				dp->phy = NULL;
+			else
+				return ret;
+		}
+	}
+
+	dp->clock = devm_clk_get(&pdev->dev, "dp");
+	if (IS_ERR(dp->clock)) {
+		dev_err(&pdev->dev, "failed to get clock\n");
+		return PTR_ERR(dp->clock);
+	}
+
+	clk_prepare_enable(dp->clock);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	dp->reg_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(dp->reg_base))
+		return PTR_ERR(dp->reg_base);
+
+	dp->force_hpd = of_property_read_bool(dev->of_node, "force-hpd");
+
+	dp->hpd_gpio = of_get_named_gpio(dev->of_node, "hpd-gpios", 0);
+	if (!gpio_is_valid(dp->hpd_gpio))
+		dp->hpd_gpio = of_get_named_gpio(dev->of_node,
+						 "samsung,hpd-gpio", 0);
+
+	if (gpio_is_valid(dp->hpd_gpio)) {
+		/*
+		 * Set up the hotplug GPIO from the device tree as an interrupt.
+		 * Simply specifying a different interrupt in the device tree
+		 * doesn't work since we handle hotplug rather differently when
+		 * using a GPIO.  We also need the actual GPIO specifier so
+		 * that we can get the current state of the GPIO.
+		 */
+		ret = devm_gpio_request_one(&pdev->dev, dp->hpd_gpio, GPIOF_IN,
+					    "hpd_gpio");
+		if (ret) {
+			dev_err(&pdev->dev, "failed to get hpd gpio\n");
+			return ret;
+		}
+		dp->irq = gpio_to_irq(dp->hpd_gpio);
+		irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
+	} else {
+		dp->hpd_gpio = -ENODEV;
+		dp->irq = platform_get_irq(pdev, 0);
+		irq_flags = 0;
+	}
+
+	if (dp->irq == -ENXIO) {
+		dev_err(&pdev->dev, "failed to get irq\n");
+		return -ENODEV;
+	}
+
+	pm_runtime_enable(dev);
+
+	phy_power_on(dp->phy);
+
+	if (dp->plat_data->panel) {
+		if (drm_panel_prepare(dp->plat_data->panel)) {
+			DRM_ERROR("failed to setup the panel\n");
+			return -EBUSY;
+		}
+	}
+
+	analogix_dp_init_dp(dp);
+
+	ret = devm_request_threaded_irq(&pdev->dev, dp->irq,
+					analogix_dp_hardirq,
+					analogix_dp_irq_thread,
+					irq_flags, "analogix-dp", dp);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to request irq\n");
+		goto err_disable_pm_runtime;
+	}
+	disable_irq(dp->irq);
+
+	dp->drm_dev = drm_dev;
+	dp->encoder = dp->plat_data->encoder;
+
+	ret = analogix_dp_create_bridge(drm_dev, dp);
+	if (ret) {
+		DRM_ERROR("failed to create bridge (%d)\n", ret);
+		drm_encoder_cleanup(dp->encoder);
+		goto err_disable_pm_runtime;
+	}
+
+	return 0;
+
+err_disable_pm_runtime:
+	pm_runtime_disable(dev);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(analogix_dp_bind);
+
+void analogix_dp_unbind(struct device *dev, struct device *master,
+			void *data)
+{
+	struct analogix_dp_device *dp = dev_get_drvdata(dev);
+
+	analogix_dp_bridge_disable(dp->bridge);
+
+	if (dp->plat_data->panel) {
+		if (drm_panel_unprepare(dp->plat_data->panel))
+			DRM_ERROR("failed to turnoff the panel\n");
+	}
+
+	pm_runtime_disable(dev);
+}
+EXPORT_SYMBOL_GPL(analogix_dp_unbind);
+
+#ifdef CONFIG_PM
+int analogix_dp_suspend(struct device *dev)
+{
+	struct analogix_dp_device *dp = dev_get_drvdata(dev);
+
+	clk_disable_unprepare(dp->clock);
+
+	if (dp->plat_data->panel) {
+		if (drm_panel_unprepare(dp->plat_data->panel))
+			DRM_ERROR("failed to turnoff the panel\n");
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(analogix_dp_suspend);
+
+int analogix_dp_resume(struct device *dev)
+{
+	struct analogix_dp_device *dp = dev_get_drvdata(dev);
+	int ret;
+
+	ret = clk_prepare_enable(dp->clock);
+	if (ret < 0) {
+		DRM_ERROR("Failed to prepare_enable the clock clk [%d]\n", ret);
+		return ret;
+	}
+
+	if (dp->plat_data->panel) {
+		if (drm_panel_prepare(dp->plat_data->panel)) {
+			DRM_ERROR("failed to setup the panel\n");
+			return -EBUSY;
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(analogix_dp_resume);
+#endif
+
+MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
+MODULE_DESCRIPTION("Analogix DP Core Driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h linux-libre-4.7-gnu/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,281 @@
+/*
+ * Header file for Analogix DP (Display Port) core interface driver.
+ *
+ * Copyright (C) 2012 Samsung Electronics Co., Ltd.
+ * Author: Jingoo Han <jg1.han@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef _ANALOGIX_DP_CORE_H
+#define _ANALOGIX_DP_CORE_H
+
+#include <drm/drm_crtc.h>
+#include <drm/drm_dp_helper.h>
+
+#define DP_TIMEOUT_LOOP_COUNT 100
+#define MAX_CR_LOOP 5
+#define MAX_EQ_LOOP 5
+
+/* I2C EDID Chip ID, Slave Address */
+#define I2C_EDID_DEVICE_ADDR			0x50
+#define I2C_E_EDID_DEVICE_ADDR			0x30
+
+#define EDID_BLOCK_LENGTH			0x80
+#define EDID_HEADER_PATTERN			0x00
+#define EDID_EXTENSION_FLAG			0x7e
+#define EDID_CHECKSUM				0x7f
+
+/* DP_MAX_LANE_COUNT */
+#define DPCD_ENHANCED_FRAME_CAP(x)		(((x) >> 7) & 0x1)
+#define DPCD_MAX_LANE_COUNT(x)			((x) & 0x1f)
+
+/* DP_LANE_COUNT_SET */
+#define DPCD_LANE_COUNT_SET(x)			((x) & 0x1f)
+
+/* DP_TRAINING_LANE0_SET */
+#define DPCD_PRE_EMPHASIS_SET(x)		(((x) & 0x3) << 3)
+#define DPCD_PRE_EMPHASIS_GET(x)		(((x) >> 3) & 0x3)
+#define DPCD_VOLTAGE_SWING_SET(x)		(((x) & 0x3) << 0)
+#define DPCD_VOLTAGE_SWING_GET(x)		(((x) >> 0) & 0x3)
+
+enum link_lane_count_type {
+	LANE_COUNT1 = 1,
+	LANE_COUNT2 = 2,
+	LANE_COUNT4 = 4
+};
+
+enum link_training_state {
+	START,
+	CLOCK_RECOVERY,
+	EQUALIZER_TRAINING,
+	FINISHED,
+	FAILED
+};
+
+enum voltage_swing_level {
+	VOLTAGE_LEVEL_0,
+	VOLTAGE_LEVEL_1,
+	VOLTAGE_LEVEL_2,
+	VOLTAGE_LEVEL_3,
+};
+
+enum pre_emphasis_level {
+	PRE_EMPHASIS_LEVEL_0,
+	PRE_EMPHASIS_LEVEL_1,
+	PRE_EMPHASIS_LEVEL_2,
+	PRE_EMPHASIS_LEVEL_3,
+};
+
+enum pattern_set {
+	PRBS7,
+	D10_2,
+	TRAINING_PTN1,
+	TRAINING_PTN2,
+	DP_NONE
+};
+
+enum color_space {
+	COLOR_RGB,
+	COLOR_YCBCR422,
+	COLOR_YCBCR444
+};
+
+enum color_depth {
+	COLOR_6,
+	COLOR_8,
+	COLOR_10,
+	COLOR_12
+};
+
+enum color_coefficient {
+	COLOR_YCBCR601,
+	COLOR_YCBCR709
+};
+
+enum dynamic_range {
+	VESA,
+	CEA
+};
+
+enum pll_status {
+	PLL_UNLOCKED,
+	PLL_LOCKED
+};
+
+enum clock_recovery_m_value_type {
+	CALCULATED_M,
+	REGISTER_M
+};
+
+enum video_timing_recognition_type {
+	VIDEO_TIMING_FROM_CAPTURE,
+	VIDEO_TIMING_FROM_REGISTER
+};
+
+enum analog_power_block {
+	AUX_BLOCK,
+	CH0_BLOCK,
+	CH1_BLOCK,
+	CH2_BLOCK,
+	CH3_BLOCK,
+	ANALOG_TOTAL,
+	POWER_ALL
+};
+
+enum dp_irq_type {
+	DP_IRQ_TYPE_HP_CABLE_IN,
+	DP_IRQ_TYPE_HP_CABLE_OUT,
+	DP_IRQ_TYPE_HP_CHANGE,
+	DP_IRQ_TYPE_UNKNOWN,
+};
+
+struct video_info {
+	char *name;
+
+	bool h_sync_polarity;
+	bool v_sync_polarity;
+	bool interlaced;
+
+	enum color_space color_space;
+	enum dynamic_range dynamic_range;
+	enum color_coefficient ycbcr_coeff;
+	enum color_depth color_depth;
+
+	int max_link_rate;
+	enum link_lane_count_type max_lane_count;
+};
+
+struct link_train {
+	int eq_loop;
+	int cr_loop[4];
+
+	u8 link_rate;
+	u8 lane_count;
+	u8 training_lane[4];
+
+	enum link_training_state lt_state;
+};
+
+struct analogix_dp_device {
+	struct drm_encoder	*encoder;
+	struct device		*dev;
+	struct drm_device	*drm_dev;
+	struct drm_connector	connector;
+	struct drm_bridge	*bridge;
+	struct clk		*clock;
+	unsigned int		irq;
+	void __iomem		*reg_base;
+
+	struct video_info	video_info;
+	struct link_train	link_train;
+	struct phy		*phy;
+	int			dpms_mode;
+	int			hpd_gpio;
+	bool                    force_hpd;
+	unsigned char           edid[EDID_BLOCK_LENGTH * 2];
+
+	struct analogix_dp_plat_data *plat_data;
+};
+
+/* analogix_dp_reg.c */
+void analogix_dp_enable_video_mute(struct analogix_dp_device *dp, bool enable);
+void analogix_dp_stop_video(struct analogix_dp_device *dp);
+void analogix_dp_lane_swap(struct analogix_dp_device *dp, bool enable);
+void analogix_dp_init_analog_param(struct analogix_dp_device *dp);
+void analogix_dp_init_interrupt(struct analogix_dp_device *dp);
+void analogix_dp_reset(struct analogix_dp_device *dp);
+void analogix_dp_swreset(struct analogix_dp_device *dp);
+void analogix_dp_config_interrupt(struct analogix_dp_device *dp);
+void analogix_dp_mute_hpd_interrupt(struct analogix_dp_device *dp);
+void analogix_dp_unmute_hpd_interrupt(struct analogix_dp_device *dp);
+enum pll_status analogix_dp_get_pll_lock_status(struct analogix_dp_device *dp);
+void analogix_dp_set_pll_power_down(struct analogix_dp_device *dp, bool enable);
+void analogix_dp_set_analog_power_down(struct analogix_dp_device *dp,
+				       enum analog_power_block block,
+				       bool enable);
+void analogix_dp_init_analog_func(struct analogix_dp_device *dp);
+void analogix_dp_init_hpd(struct analogix_dp_device *dp);
+void analogix_dp_force_hpd(struct analogix_dp_device *dp);
+enum dp_irq_type analogix_dp_get_irq_type(struct analogix_dp_device *dp);
+void analogix_dp_clear_hotplug_interrupts(struct analogix_dp_device *dp);
+void analogix_dp_reset_aux(struct analogix_dp_device *dp);
+void analogix_dp_init_aux(struct analogix_dp_device *dp);
+int analogix_dp_get_plug_in_status(struct analogix_dp_device *dp);
+void analogix_dp_enable_sw_function(struct analogix_dp_device *dp);
+int analogix_dp_start_aux_transaction(struct analogix_dp_device *dp);
+int analogix_dp_write_byte_to_dpcd(struct analogix_dp_device *dp,
+				   unsigned int reg_addr,
+				   unsigned char data);
+int analogix_dp_read_byte_from_dpcd(struct analogix_dp_device *dp,
+				    unsigned int reg_addr,
+				    unsigned char *data);
+int analogix_dp_write_bytes_to_dpcd(struct analogix_dp_device *dp,
+				    unsigned int reg_addr,
+				    unsigned int count,
+				    unsigned char data[]);
+int analogix_dp_read_bytes_from_dpcd(struct analogix_dp_device *dp,
+				     unsigned int reg_addr,
+				     unsigned int count,
+				     unsigned char data[]);
+int analogix_dp_select_i2c_device(struct analogix_dp_device *dp,
+				  unsigned int device_addr,
+				  unsigned int reg_addr);
+int analogix_dp_read_byte_from_i2c(struct analogix_dp_device *dp,
+				   unsigned int device_addr,
+				   unsigned int reg_addr,
+				   unsigned int *data);
+int analogix_dp_read_bytes_from_i2c(struct analogix_dp_device *dp,
+				    unsigned int device_addr,
+				    unsigned int reg_addr,
+				    unsigned int count,
+				    unsigned char edid[]);
+void analogix_dp_set_link_bandwidth(struct analogix_dp_device *dp, u32 bwtype);
+void analogix_dp_get_link_bandwidth(struct analogix_dp_device *dp, u32 *bwtype);
+void analogix_dp_set_lane_count(struct analogix_dp_device *dp, u32 count);
+void analogix_dp_get_lane_count(struct analogix_dp_device *dp, u32 *count);
+void analogix_dp_enable_enhanced_mode(struct analogix_dp_device *dp,
+				      bool enable);
+void analogix_dp_set_training_pattern(struct analogix_dp_device *dp,
+				      enum pattern_set pattern);
+void analogix_dp_set_lane0_pre_emphasis(struct analogix_dp_device *dp,
+					u32 level);
+void analogix_dp_set_lane1_pre_emphasis(struct analogix_dp_device *dp,
+					u32 level);
+void analogix_dp_set_lane2_pre_emphasis(struct analogix_dp_device *dp,
+					u32 level);
+void analogix_dp_set_lane3_pre_emphasis(struct analogix_dp_device *dp,
+					u32 level);
+void analogix_dp_set_lane0_link_training(struct analogix_dp_device *dp,
+					 u32 training_lane);
+void analogix_dp_set_lane1_link_training(struct analogix_dp_device *dp,
+					 u32 training_lane);
+void analogix_dp_set_lane2_link_training(struct analogix_dp_device *dp,
+					 u32 training_lane);
+void analogix_dp_set_lane3_link_training(struct analogix_dp_device *dp,
+					 u32 training_lane);
+u32 analogix_dp_get_lane0_link_training(struct analogix_dp_device *dp);
+u32 analogix_dp_get_lane1_link_training(struct analogix_dp_device *dp);
+u32 analogix_dp_get_lane2_link_training(struct analogix_dp_device *dp);
+u32 analogix_dp_get_lane3_link_training(struct analogix_dp_device *dp);
+void analogix_dp_reset_macro(struct analogix_dp_device *dp);
+void analogix_dp_init_video(struct analogix_dp_device *dp);
+
+void analogix_dp_set_video_color_format(struct analogix_dp_device *dp);
+int analogix_dp_is_slave_video_stream_clock_on(struct analogix_dp_device *dp);
+void analogix_dp_set_video_cr_mn(struct analogix_dp_device *dp,
+				 enum clock_recovery_m_value_type type,
+				 u32 m_value,
+				 u32 n_value);
+void analogix_dp_set_video_timing_mode(struct analogix_dp_device *dp, u32 type);
+void analogix_dp_enable_video_master(struct analogix_dp_device *dp,
+				     bool enable);
+void analogix_dp_start_video(struct analogix_dp_device *dp);
+int analogix_dp_is_video_stream_on(struct analogix_dp_device *dp);
+void analogix_dp_config_video_slave_mode(struct analogix_dp_device *dp);
+void analogix_dp_enable_scrambling(struct analogix_dp_device *dp);
+void analogix_dp_disable_scrambling(struct analogix_dp_device *dp);
+#endif /* _ANALOGIX_DP_CORE_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c linux-libre-4.7-gnu/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,1320 @@
+/*
+ * Analogix DP (Display port) core register interface driver.
+ *
+ * Copyright (C) 2012 Samsung Electronics Co., Ltd.
+ * Author: Jingoo Han <jg1.han@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+
+#include <drm/bridge/analogix_dp.h>
+
+#include "analogix_dp_core.h"
+#include "analogix_dp_reg.h"
+
+#define COMMON_INT_MASK_1	0
+#define COMMON_INT_MASK_2	0
+#define COMMON_INT_MASK_3	0
+#define COMMON_INT_MASK_4	(HOTPLUG_CHG | HPD_LOST | PLUG)
+#define INT_STA_MASK		INT_HPD
+
+void analogix_dp_enable_video_mute(struct analogix_dp_device *dp, bool enable)
+{
+	u32 reg;
+
+	if (enable) {
+		reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1);
+		reg |= HDCP_VIDEO_MUTE;
+		writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1);
+	} else {
+		reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1);
+		reg &= ~HDCP_VIDEO_MUTE;
+		writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1);
+	}
+}
+
+void analogix_dp_stop_video(struct analogix_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1);
+	reg &= ~VIDEO_EN;
+	writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1);
+}
+
+void analogix_dp_lane_swap(struct analogix_dp_device *dp, bool enable)
+{
+	u32 reg;
+
+	if (enable)
+		reg = LANE3_MAP_LOGIC_LANE_0 | LANE2_MAP_LOGIC_LANE_1 |
+		      LANE1_MAP_LOGIC_LANE_2 | LANE0_MAP_LOGIC_LANE_3;
+	else
+		reg = LANE3_MAP_LOGIC_LANE_3 | LANE2_MAP_LOGIC_LANE_2 |
+		      LANE1_MAP_LOGIC_LANE_1 | LANE0_MAP_LOGIC_LANE_0;
+
+	writel(reg, dp->reg_base + ANALOGIX_DP_LANE_MAP);
+}
+
+void analogix_dp_init_analog_param(struct analogix_dp_device *dp)
+{
+	u32 reg;
+
+	reg = TX_TERMINAL_CTRL_50_OHM;
+	writel(reg, dp->reg_base + ANALOGIX_DP_ANALOG_CTL_1);
+
+	reg = SEL_24M | TX_DVDD_BIT_1_0625V;
+	writel(reg, dp->reg_base + ANALOGIX_DP_ANALOG_CTL_2);
+
+	if (dp->plat_data && (dp->plat_data->dev_type == RK3288_DP)) {
+		writel(REF_CLK_24M, dp->reg_base + ANALOGIX_DP_PLL_REG_1);
+		writel(0x95, dp->reg_base + ANALOGIX_DP_PLL_REG_2);
+		writel(0x40, dp->reg_base + ANALOGIX_DP_PLL_REG_3);
+		writel(0x58, dp->reg_base + ANALOGIX_DP_PLL_REG_4);
+		writel(0x22, dp->reg_base + ANALOGIX_DP_PLL_REG_5);
+	}
+
+	reg = DRIVE_DVDD_BIT_1_0625V | VCO_BIT_600_MICRO;
+	writel(reg, dp->reg_base + ANALOGIX_DP_ANALOG_CTL_3);
+
+	reg = PD_RING_OSC | AUX_TERMINAL_CTRL_50_OHM |
+		TX_CUR1_2X | TX_CUR_16_MA;
+	writel(reg, dp->reg_base + ANALOGIX_DP_PLL_FILTER_CTL_1);
+
+	reg = CH3_AMP_400_MV | CH2_AMP_400_MV |
+		CH1_AMP_400_MV | CH0_AMP_400_MV;
+	writel(reg, dp->reg_base + ANALOGIX_DP_TX_AMP_TUNING_CTL);
+}
+
+void analogix_dp_init_interrupt(struct analogix_dp_device *dp)
+{
+	/* Set interrupt pin assertion polarity as high */
+	writel(INT_POL1 | INT_POL0, dp->reg_base + ANALOGIX_DP_INT_CTL);
+
+	/* Clear pending regisers */
+	writel(0xff, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_1);
+	writel(0x4f, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_2);
+	writel(0xe0, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_3);
+	writel(0xe7, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_4);
+	writel(0x63, dp->reg_base + ANALOGIX_DP_INT_STA);
+
+	/* 0:mask,1: unmask */
+	writel(0x00, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_1);
+	writel(0x00, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_2);
+	writel(0x00, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_3);
+	writel(0x00, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_4);
+	writel(0x00, dp->reg_base + ANALOGIX_DP_INT_STA_MASK);
+}
+
+void analogix_dp_reset(struct analogix_dp_device *dp)
+{
+	u32 reg;
+
+	analogix_dp_stop_video(dp);
+	analogix_dp_enable_video_mute(dp, 0);
+
+	reg = MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N |
+		AUD_FIFO_FUNC_EN_N | AUD_FUNC_EN_N |
+		HDCP_FUNC_EN_N | SW_FUNC_EN_N;
+	writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_1);
+
+	reg = SSC_FUNC_EN_N | AUX_FUNC_EN_N |
+		SERDES_FIFO_FUNC_EN_N |
+		LS_CLK_DOMAIN_FUNC_EN_N;
+	writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_2);
+
+	usleep_range(20, 30);
+
+	analogix_dp_lane_swap(dp, 0);
+
+	writel(0x0, dp->reg_base + ANALOGIX_DP_SYS_CTL_1);
+	writel(0x40, dp->reg_base + ANALOGIX_DP_SYS_CTL_2);
+	writel(0x0, dp->reg_base + ANALOGIX_DP_SYS_CTL_3);
+	writel(0x0, dp->reg_base + ANALOGIX_DP_SYS_CTL_4);
+
+	writel(0x0, dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL);
+	writel(0x0, dp->reg_base + ANALOGIX_DP_HDCP_CTL);
+
+	writel(0x5e, dp->reg_base + ANALOGIX_DP_HPD_DEGLITCH_L);
+	writel(0x1a, dp->reg_base + ANALOGIX_DP_HPD_DEGLITCH_H);
+
+	writel(0x10, dp->reg_base + ANALOGIX_DP_LINK_DEBUG_CTL);
+
+	writel(0x0, dp->reg_base + ANALOGIX_DP_PHY_TEST);
+
+	writel(0x0, dp->reg_base + ANALOGIX_DP_VIDEO_FIFO_THRD);
+	writel(0x20, dp->reg_base + ANALOGIX_DP_AUDIO_MARGIN);
+
+	writel(0x4, dp->reg_base + ANALOGIX_DP_M_VID_GEN_FILTER_TH);
+	writel(0x2, dp->reg_base + ANALOGIX_DP_M_AUD_GEN_FILTER_TH);
+
+	writel(0x00000101, dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL);
+}
+
+void analogix_dp_swreset(struct analogix_dp_device *dp)
+{
+	writel(RESET_DP_TX, dp->reg_base + ANALOGIX_DP_TX_SW_RESET);
+}
+
+void analogix_dp_config_interrupt(struct analogix_dp_device *dp)
+{
+	u32 reg;
+
+	/* 0: mask, 1: unmask */
+	reg = COMMON_INT_MASK_1;
+	writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_1);
+
+	reg = COMMON_INT_MASK_2;
+	writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_2);
+
+	reg = COMMON_INT_MASK_3;
+	writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_3);
+
+	reg = COMMON_INT_MASK_4;
+	writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_4);
+
+	reg = INT_STA_MASK;
+	writel(reg, dp->reg_base + ANALOGIX_DP_INT_STA_MASK);
+}
+
+void analogix_dp_mute_hpd_interrupt(struct analogix_dp_device *dp)
+{
+	u32 reg;
+
+	/* 0: mask, 1: unmask */
+	reg = readl(dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_4);
+	reg &= ~COMMON_INT_MASK_4;
+	writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_4);
+
+	reg = readl(dp->reg_base + ANALOGIX_DP_INT_STA_MASK);
+	reg &= ~INT_STA_MASK;
+	writel(reg, dp->reg_base + ANALOGIX_DP_INT_STA_MASK);
+}
+
+void analogix_dp_unmute_hpd_interrupt(struct analogix_dp_device *dp)
+{
+	u32 reg;
+
+	/* 0: mask, 1: unmask */
+	reg = COMMON_INT_MASK_4;
+	writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_4);
+
+	reg = INT_STA_MASK;
+	writel(reg, dp->reg_base + ANALOGIX_DP_INT_STA_MASK);
+}
+
+enum pll_status analogix_dp_get_pll_lock_status(struct analogix_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + ANALOGIX_DP_DEBUG_CTL);
+	if (reg & PLL_LOCK)
+		return PLL_LOCKED;
+	else
+		return PLL_UNLOCKED;
+}
+
+void analogix_dp_set_pll_power_down(struct analogix_dp_device *dp, bool enable)
+{
+	u32 reg;
+
+	if (enable) {
+		reg = readl(dp->reg_base + ANALOGIX_DP_PLL_CTL);
+		reg |= DP_PLL_PD;
+		writel(reg, dp->reg_base + ANALOGIX_DP_PLL_CTL);
+	} else {
+		reg = readl(dp->reg_base + ANALOGIX_DP_PLL_CTL);
+		reg &= ~DP_PLL_PD;
+		writel(reg, dp->reg_base + ANALOGIX_DP_PLL_CTL);
+	}
+}
+
+void analogix_dp_set_analog_power_down(struct analogix_dp_device *dp,
+				       enum analog_power_block block,
+				       bool enable)
+{
+	u32 reg;
+	u32 phy_pd_addr = ANALOGIX_DP_PHY_PD;
+
+	if (dp->plat_data && (dp->plat_data->dev_type == RK3288_DP))
+		phy_pd_addr = ANALOGIX_DP_PD;
+
+	switch (block) {
+	case AUX_BLOCK:
+		if (enable) {
+			reg = readl(dp->reg_base + phy_pd_addr);
+			reg |= AUX_PD;
+			writel(reg, dp->reg_base + phy_pd_addr);
+		} else {
+			reg = readl(dp->reg_base + phy_pd_addr);
+			reg &= ~AUX_PD;
+			writel(reg, dp->reg_base + phy_pd_addr);
+		}
+		break;
+	case CH0_BLOCK:
+		if (enable) {
+			reg = readl(dp->reg_base + phy_pd_addr);
+			reg |= CH0_PD;
+			writel(reg, dp->reg_base + phy_pd_addr);
+		} else {
+			reg = readl(dp->reg_base + phy_pd_addr);
+			reg &= ~CH0_PD;
+			writel(reg, dp->reg_base + phy_pd_addr);
+		}
+		break;
+	case CH1_BLOCK:
+		if (enable) {
+			reg = readl(dp->reg_base + phy_pd_addr);
+			reg |= CH1_PD;
+			writel(reg, dp->reg_base + phy_pd_addr);
+		} else {
+			reg = readl(dp->reg_base + phy_pd_addr);
+			reg &= ~CH1_PD;
+			writel(reg, dp->reg_base + phy_pd_addr);
+		}
+		break;
+	case CH2_BLOCK:
+		if (enable) {
+			reg = readl(dp->reg_base + phy_pd_addr);
+			reg |= CH2_PD;
+			writel(reg, dp->reg_base + phy_pd_addr);
+		} else {
+			reg = readl(dp->reg_base + phy_pd_addr);
+			reg &= ~CH2_PD;
+			writel(reg, dp->reg_base + phy_pd_addr);
+		}
+		break;
+	case CH3_BLOCK:
+		if (enable) {
+			reg = readl(dp->reg_base + phy_pd_addr);
+			reg |= CH3_PD;
+			writel(reg, dp->reg_base + phy_pd_addr);
+		} else {
+			reg = readl(dp->reg_base + phy_pd_addr);
+			reg &= ~CH3_PD;
+			writel(reg, dp->reg_base + phy_pd_addr);
+		}
+		break;
+	case ANALOG_TOTAL:
+		if (enable) {
+			reg = readl(dp->reg_base + phy_pd_addr);
+			reg |= DP_PHY_PD;
+			writel(reg, dp->reg_base + phy_pd_addr);
+		} else {
+			reg = readl(dp->reg_base + phy_pd_addr);
+			reg &= ~DP_PHY_PD;
+			writel(reg, dp->reg_base + phy_pd_addr);
+		}
+		break;
+	case POWER_ALL:
+		if (enable) {
+			reg = DP_PHY_PD | AUX_PD | CH3_PD | CH2_PD |
+				CH1_PD | CH0_PD;
+			writel(reg, dp->reg_base + phy_pd_addr);
+		} else {
+			writel(0x00, dp->reg_base + phy_pd_addr);
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+void analogix_dp_init_analog_func(struct analogix_dp_device *dp)
+{
+	u32 reg;
+	int timeout_loop = 0;
+
+	analogix_dp_set_analog_power_down(dp, POWER_ALL, 0);
+
+	reg = PLL_LOCK_CHG;
+	writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_1);
+
+	reg = readl(dp->reg_base + ANALOGIX_DP_DEBUG_CTL);
+	reg &= ~(F_PLL_LOCK | PLL_LOCK_CTRL);
+	writel(reg, dp->reg_base + ANALOGIX_DP_DEBUG_CTL);
+
+	/* Power up PLL */
+	if (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
+		analogix_dp_set_pll_power_down(dp, 0);
+
+		while (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
+			timeout_loop++;
+			if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
+				dev_err(dp->dev, "failed to get pll lock status\n");
+				return;
+			}
+			usleep_range(10, 20);
+		}
+	}
+
+	/* Enable Serdes FIFO function and Link symbol clock domain module */
+	reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_2);
+	reg &= ~(SERDES_FIFO_FUNC_EN_N | LS_CLK_DOMAIN_FUNC_EN_N
+		| AUX_FUNC_EN_N);
+	writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_2);
+}
+
+void analogix_dp_clear_hotplug_interrupts(struct analogix_dp_device *dp)
+{
+	u32 reg;
+
+	if (gpio_is_valid(dp->hpd_gpio))
+		return;
+
+	reg = HOTPLUG_CHG | HPD_LOST | PLUG;
+	writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_4);
+
+	reg = INT_HPD;
+	writel(reg, dp->reg_base + ANALOGIX_DP_INT_STA);
+}
+
+void analogix_dp_init_hpd(struct analogix_dp_device *dp)
+{
+	u32 reg;
+
+	if (gpio_is_valid(dp->hpd_gpio))
+		return;
+
+	analogix_dp_clear_hotplug_interrupts(dp);
+
+	reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_3);
+	reg &= ~(F_HPD | HPD_CTRL);
+	writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_3);
+}
+
+void analogix_dp_force_hpd(struct analogix_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_3);
+	reg = (F_HPD | HPD_CTRL);
+	writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_3);
+}
+
+enum dp_irq_type analogix_dp_get_irq_type(struct analogix_dp_device *dp)
+{
+	u32 reg;
+
+	if (gpio_is_valid(dp->hpd_gpio)) {
+		reg = gpio_get_value(dp->hpd_gpio);
+		if (reg)
+			return DP_IRQ_TYPE_HP_CABLE_IN;
+		else
+			return DP_IRQ_TYPE_HP_CABLE_OUT;
+	} else {
+		/* Parse hotplug interrupt status register */
+		reg = readl(dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_4);
+
+		if (reg & PLUG)
+			return DP_IRQ_TYPE_HP_CABLE_IN;
+
+		if (reg & HPD_LOST)
+			return DP_IRQ_TYPE_HP_CABLE_OUT;
+
+		if (reg & HOTPLUG_CHG)
+			return DP_IRQ_TYPE_HP_CHANGE;
+
+		return DP_IRQ_TYPE_UNKNOWN;
+	}
+}
+
+void analogix_dp_reset_aux(struct analogix_dp_device *dp)
+{
+	u32 reg;
+
+	/* Disable AUX channel module */
+	reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_2);
+	reg |= AUX_FUNC_EN_N;
+	writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_2);
+}
+
+void analogix_dp_init_aux(struct analogix_dp_device *dp)
+{
+	u32 reg;
+
+	/* Clear inerrupts related to AUX channel */
+	reg = RPLY_RECEIV | AUX_ERR;
+	writel(reg, dp->reg_base + ANALOGIX_DP_INT_STA);
+
+	analogix_dp_reset_aux(dp);
+
+	/* Disable AUX transaction H/W retry */
+	if (dp->plat_data && (dp->plat_data->dev_type == RK3288_DP))
+		reg = AUX_BIT_PERIOD_EXPECTED_DELAY(0) |
+		      AUX_HW_RETRY_COUNT_SEL(3) |
+		      AUX_HW_RETRY_INTERVAL_600_MICROSECONDS;
+	else
+		reg = AUX_BIT_PERIOD_EXPECTED_DELAY(3) |
+		      AUX_HW_RETRY_COUNT_SEL(0) |
+		      AUX_HW_RETRY_INTERVAL_600_MICROSECONDS;
+	writel(reg, dp->reg_base + ANALOGIX_DP_AUX_HW_RETRY_CTL);
+
+	/* Receive AUX Channel DEFER commands equal to DEFFER_COUNT*64 */
+	reg = DEFER_CTRL_EN | DEFER_COUNT(1);
+	writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_DEFER_CTL);
+
+	/* Enable AUX channel module */
+	reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_2);
+	reg &= ~AUX_FUNC_EN_N;
+	writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_2);
+}
+
+int analogix_dp_get_plug_in_status(struct analogix_dp_device *dp)
+{
+	u32 reg;
+
+	if (gpio_is_valid(dp->hpd_gpio)) {
+		if (gpio_get_value(dp->hpd_gpio))
+			return 0;
+	} else {
+		reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_3);
+		if (reg & HPD_STATUS)
+			return 0;
+	}
+
+	return -EINVAL;
+}
+
+void analogix_dp_enable_sw_function(struct analogix_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_1);
+	reg &= ~SW_FUNC_EN_N;
+	writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_1);
+}
+
+int analogix_dp_start_aux_transaction(struct analogix_dp_device *dp)
+{
+	int reg;
+	int retval = 0;
+	int timeout_loop = 0;
+
+	/* Enable AUX CH operation */
+	reg = readl(dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_2);
+	reg |= AUX_EN;
+	writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_2);
+
+	/* Is AUX CH command reply received? */
+	reg = readl(dp->reg_base + ANALOGIX_DP_INT_STA);
+	while (!(reg & RPLY_RECEIV)) {
+		timeout_loop++;
+		if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
+			dev_err(dp->dev, "AUX CH command reply failed!\n");
+			return -ETIMEDOUT;
+		}
+		reg = readl(dp->reg_base + ANALOGIX_DP_INT_STA);
+		usleep_range(10, 11);
+	}
+
+	/* Clear interrupt source for AUX CH command reply */
+	writel(RPLY_RECEIV, dp->reg_base + ANALOGIX_DP_INT_STA);
+
+	/* Clear interrupt source for AUX CH access error */
+	reg = readl(dp->reg_base + ANALOGIX_DP_INT_STA);
+	if (reg & AUX_ERR) {
+		writel(AUX_ERR, dp->reg_base + ANALOGIX_DP_INT_STA);
+		return -EREMOTEIO;
+	}
+
+	/* Check AUX CH error access status */
+	reg = readl(dp->reg_base + ANALOGIX_DP_AUX_CH_STA);
+	if ((reg & AUX_STATUS_MASK) != 0) {
+		dev_err(dp->dev, "AUX CH error happens: %d\n\n",
+			reg & AUX_STATUS_MASK);
+		return -EREMOTEIO;
+	}
+
+	return retval;
+}
+
+int analogix_dp_write_byte_to_dpcd(struct analogix_dp_device *dp,
+				   unsigned int reg_addr,
+				   unsigned char data)
+{
+	u32 reg;
+	int i;
+	int retval;
+
+	for (i = 0; i < 3; i++) {
+		/* Clear AUX CH data buffer */
+		reg = BUF_CLR;
+		writel(reg, dp->reg_base + ANALOGIX_DP_BUFFER_DATA_CTL);
+
+		/* Select DPCD device address */
+		reg = AUX_ADDR_7_0(reg_addr);
+		writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_7_0);
+		reg = AUX_ADDR_15_8(reg_addr);
+		writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_15_8);
+		reg = AUX_ADDR_19_16(reg_addr);
+		writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_19_16);
+
+		/* Write data buffer */
+		reg = (unsigned int)data;
+		writel(reg, dp->reg_base + ANALOGIX_DP_BUF_DATA_0);
+
+		/*
+		 * Set DisplayPort transaction and write 1 byte
+		 * If bit 3 is 1, DisplayPort transaction.
+		 * If Bit 3 is 0, I2C transaction.
+		 */
+		reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE;
+		writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_1);
+
+		/* Start AUX transaction */
+		retval = analogix_dp_start_aux_transaction(dp);
+		if (retval == 0)
+			break;
+
+		dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__);
+	}
+
+	return retval;
+}
+
+int analogix_dp_read_byte_from_dpcd(struct analogix_dp_device *dp,
+				    unsigned int reg_addr,
+				    unsigned char *data)
+{
+	u32 reg;
+	int i;
+	int retval;
+
+	for (i = 0; i < 3; i++) {
+		/* Clear AUX CH data buffer */
+		reg = BUF_CLR;
+		writel(reg, dp->reg_base + ANALOGIX_DP_BUFFER_DATA_CTL);
+
+		/* Select DPCD device address */
+		reg = AUX_ADDR_7_0(reg_addr);
+		writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_7_0);
+		reg = AUX_ADDR_15_8(reg_addr);
+		writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_15_8);
+		reg = AUX_ADDR_19_16(reg_addr);
+		writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_19_16);
+
+		/*
+		 * Set DisplayPort transaction and read 1 byte
+		 * If bit 3 is 1, DisplayPort transaction.
+		 * If Bit 3 is 0, I2C transaction.
+		 */
+		reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ;
+		writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_1);
+
+		/* Start AUX transaction */
+		retval = analogix_dp_start_aux_transaction(dp);
+		if (retval == 0)
+			break;
+
+		dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__);
+	}
+
+	/* Read data buffer */
+	reg = readl(dp->reg_base + ANALOGIX_DP_BUF_DATA_0);
+	*data = (unsigned char)(reg & 0xff);
+
+	return retval;
+}
+
+int analogix_dp_write_bytes_to_dpcd(struct analogix_dp_device *dp,
+				    unsigned int reg_addr,
+				    unsigned int count,
+				    unsigned char data[])
+{
+	u32 reg;
+	unsigned int start_offset;
+	unsigned int cur_data_count;
+	unsigned int cur_data_idx;
+	int i;
+	int retval = 0;
+
+	/* Clear AUX CH data buffer */
+	reg = BUF_CLR;
+	writel(reg, dp->reg_base + ANALOGIX_DP_BUFFER_DATA_CTL);
+
+	start_offset = 0;
+	while (start_offset < count) {
+		/* Buffer size of AUX CH is 16 * 4bytes */
+		if ((count - start_offset) > 16)
+			cur_data_count = 16;
+		else
+			cur_data_count = count - start_offset;
+
+		for (i = 0; i < 3; i++) {
+			/* Select DPCD device address */
+			reg = AUX_ADDR_7_0(reg_addr + start_offset);
+			writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_7_0);
+			reg = AUX_ADDR_15_8(reg_addr + start_offset);
+			writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_15_8);
+			reg = AUX_ADDR_19_16(reg_addr + start_offset);
+			writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_19_16);
+
+			for (cur_data_idx = 0; cur_data_idx < cur_data_count;
+			     cur_data_idx++) {
+				reg = data[start_offset + cur_data_idx];
+				writel(reg, dp->reg_base +
+				       ANALOGIX_DP_BUF_DATA_0 +
+				       4 * cur_data_idx);
+			}
+
+			/*
+			 * Set DisplayPort transaction and write
+			 * If bit 3 is 1, DisplayPort transaction.
+			 * If Bit 3 is 0, I2C transaction.
+			 */
+			reg = AUX_LENGTH(cur_data_count) |
+				AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE;
+			writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_1);
+
+			/* Start AUX transaction */
+			retval = analogix_dp_start_aux_transaction(dp);
+			if (retval == 0)
+				break;
+
+			dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
+				__func__);
+		}
+
+		start_offset += cur_data_count;
+	}
+
+	return retval;
+}
+
+int analogix_dp_read_bytes_from_dpcd(struct analogix_dp_device *dp,
+				     unsigned int reg_addr,
+				     unsigned int count,
+				     unsigned char data[])
+{
+	u32 reg;
+	unsigned int start_offset;
+	unsigned int cur_data_count;
+	unsigned int cur_data_idx;
+	int i;
+	int retval = 0;
+
+	/* Clear AUX CH data buffer */
+	reg = BUF_CLR;
+	writel(reg, dp->reg_base + ANALOGIX_DP_BUFFER_DATA_CTL);
+
+	start_offset = 0;
+	while (start_offset < count) {
+		/* Buffer size of AUX CH is 16 * 4bytes */
+		if ((count - start_offset) > 16)
+			cur_data_count = 16;
+		else
+			cur_data_count = count - start_offset;
+
+		/* AUX CH Request Transaction process */
+		for (i = 0; i < 3; i++) {
+			/* Select DPCD device address */
+			reg = AUX_ADDR_7_0(reg_addr + start_offset);
+			writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_7_0);
+			reg = AUX_ADDR_15_8(reg_addr + start_offset);
+			writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_15_8);
+			reg = AUX_ADDR_19_16(reg_addr + start_offset);
+			writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_19_16);
+
+			/*
+			 * Set DisplayPort transaction and read
+			 * If bit 3 is 1, DisplayPort transaction.
+			 * If Bit 3 is 0, I2C transaction.
+			 */
+			reg = AUX_LENGTH(cur_data_count) |
+				AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ;
+			writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_1);
+
+			/* Start AUX transaction */
+			retval = analogix_dp_start_aux_transaction(dp);
+			if (retval == 0)
+				break;
+
+			dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
+				__func__);
+		}
+
+		for (cur_data_idx = 0; cur_data_idx < cur_data_count;
+		    cur_data_idx++) {
+			reg = readl(dp->reg_base + ANALOGIX_DP_BUF_DATA_0
+						 + 4 * cur_data_idx);
+			data[start_offset + cur_data_idx] =
+				(unsigned char)reg;
+		}
+
+		start_offset += cur_data_count;
+	}
+
+	return retval;
+}
+
+int analogix_dp_select_i2c_device(struct analogix_dp_device *dp,
+				  unsigned int device_addr,
+				  unsigned int reg_addr)
+{
+	u32 reg;
+	int retval;
+
+	/* Set EDID device address */
+	reg = device_addr;
+	writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_7_0);
+	writel(0x0, dp->reg_base + ANALOGIX_DP_AUX_ADDR_15_8);
+	writel(0x0, dp->reg_base + ANALOGIX_DP_AUX_ADDR_19_16);
+
+	/* Set offset from base address of EDID device */
+	writel(reg_addr, dp->reg_base + ANALOGIX_DP_BUF_DATA_0);
+
+	/*
+	 * Set I2C transaction and write address
+	 * If bit 3 is 1, DisplayPort transaction.
+	 * If Bit 3 is 0, I2C transaction.
+	 */
+	reg = AUX_TX_COMM_I2C_TRANSACTION | AUX_TX_COMM_MOT |
+		AUX_TX_COMM_WRITE;
+	writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_1);
+
+	/* Start AUX transaction */
+	retval = analogix_dp_start_aux_transaction(dp);
+	if (retval != 0)
+		dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__);
+
+	return retval;
+}
+
+int analogix_dp_read_byte_from_i2c(struct analogix_dp_device *dp,
+				   unsigned int device_addr,
+				   unsigned int reg_addr,
+				   unsigned int *data)
+{
+	u32 reg;
+	int i;
+	int retval;
+
+	for (i = 0; i < 3; i++) {
+		/* Clear AUX CH data buffer */
+		reg = BUF_CLR;
+		writel(reg, dp->reg_base + ANALOGIX_DP_BUFFER_DATA_CTL);
+
+		/* Select EDID device */
+		retval = analogix_dp_select_i2c_device(dp, device_addr,
+						       reg_addr);
+		if (retval != 0)
+			continue;
+
+		/*
+		 * Set I2C transaction and read data
+		 * If bit 3 is 1, DisplayPort transaction.
+		 * If Bit 3 is 0, I2C transaction.
+		 */
+		reg = AUX_TX_COMM_I2C_TRANSACTION |
+			AUX_TX_COMM_READ;
+		writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_1);
+
+		/* Start AUX transaction */
+		retval = analogix_dp_start_aux_transaction(dp);
+		if (retval == 0)
+			break;
+
+		dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__);
+	}
+
+	/* Read data */
+	if (retval == 0)
+		*data = readl(dp->reg_base + ANALOGIX_DP_BUF_DATA_0);
+
+	return retval;
+}
+
+int analogix_dp_read_bytes_from_i2c(struct analogix_dp_device *dp,
+				    unsigned int device_addr,
+				    unsigned int reg_addr,
+				    unsigned int count,
+				    unsigned char edid[])
+{
+	u32 reg;
+	unsigned int i, j;
+	unsigned int cur_data_idx;
+	unsigned int defer = 0;
+	int retval = 0;
+
+	for (i = 0; i < count; i += 16) {
+		for (j = 0; j < 3; j++) {
+			/* Clear AUX CH data buffer */
+			reg = BUF_CLR;
+			writel(reg, dp->reg_base + ANALOGIX_DP_BUFFER_DATA_CTL);
+
+			/* Set normal AUX CH command */
+			reg = readl(dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_2);
+			reg &= ~ADDR_ONLY;
+			writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_2);
+
+			/*
+			 * If Rx sends defer, Tx sends only reads
+			 * request without sending address
+			 */
+			if (!defer)
+				retval = analogix_dp_select_i2c_device(dp,
+						device_addr, reg_addr + i);
+			else
+				defer = 0;
+
+			if (retval == 0) {
+				/*
+				 * Set I2C transaction and write data
+				 * If bit 3 is 1, DisplayPort transaction.
+				 * If Bit 3 is 0, I2C transaction.
+				 */
+				reg = AUX_LENGTH(16) |
+					AUX_TX_COMM_I2C_TRANSACTION |
+					AUX_TX_COMM_READ;
+				writel(reg, dp->reg_base +
+					ANALOGIX_DP_AUX_CH_CTL_1);
+
+				/* Start AUX transaction */
+				retval = analogix_dp_start_aux_transaction(dp);
+				if (retval == 0)
+					break;
+
+				dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
+					__func__);
+			}
+			/* Check if Rx sends defer */
+			reg = readl(dp->reg_base + ANALOGIX_DP_AUX_RX_COMM);
+			if (reg == AUX_RX_COMM_AUX_DEFER ||
+			    reg == AUX_RX_COMM_I2C_DEFER) {
+				dev_err(dp->dev, "Defer: %d\n\n", reg);
+				defer = 1;
+			}
+		}
+
+		for (cur_data_idx = 0; cur_data_idx < 16; cur_data_idx++) {
+			reg = readl(dp->reg_base + ANALOGIX_DP_BUF_DATA_0
+						 + 4 * cur_data_idx);
+			edid[i + cur_data_idx] = (unsigned char)reg;
+		}
+	}
+
+	return retval;
+}
+
+void analogix_dp_set_link_bandwidth(struct analogix_dp_device *dp, u32 bwtype)
+{
+	u32 reg;
+
+	reg = bwtype;
+	if ((bwtype == DP_LINK_BW_2_7) || (bwtype == DP_LINK_BW_1_62))
+		writel(reg, dp->reg_base + ANALOGIX_DP_LINK_BW_SET);
+}
+
+void analogix_dp_get_link_bandwidth(struct analogix_dp_device *dp, u32 *bwtype)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + ANALOGIX_DP_LINK_BW_SET);
+	*bwtype = reg;
+}
+
+void analogix_dp_set_lane_count(struct analogix_dp_device *dp, u32 count)
+{
+	u32 reg;
+
+	reg = count;
+	writel(reg, dp->reg_base + ANALOGIX_DP_LANE_COUNT_SET);
+}
+
+void analogix_dp_get_lane_count(struct analogix_dp_device *dp, u32 *count)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + ANALOGIX_DP_LANE_COUNT_SET);
+	*count = reg;
+}
+
+void analogix_dp_enable_enhanced_mode(struct analogix_dp_device *dp,
+				      bool enable)
+{
+	u32 reg;
+
+	if (enable) {
+		reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_4);
+		reg |= ENHANCED;
+		writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_4);
+	} else {
+		reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_4);
+		reg &= ~ENHANCED;
+		writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_4);
+	}
+}
+
+void analogix_dp_set_training_pattern(struct analogix_dp_device *dp,
+				      enum pattern_set pattern)
+{
+	u32 reg;
+
+	switch (pattern) {
+	case PRBS7:
+		reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_PRBS7;
+		writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET);
+		break;
+	case D10_2:
+		reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_D10_2;
+		writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET);
+		break;
+	case TRAINING_PTN1:
+		reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN1;
+		writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET);
+		break;
+	case TRAINING_PTN2:
+		reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN2;
+		writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET);
+		break;
+	case DP_NONE:
+		reg = SCRAMBLING_ENABLE |
+			LINK_QUAL_PATTERN_SET_DISABLE |
+			SW_TRAINING_PATTERN_SET_NORMAL;
+		writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET);
+		break;
+	default:
+		break;
+	}
+}
+
+void analogix_dp_set_lane0_pre_emphasis(struct analogix_dp_device *dp,
+					u32 level)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL);
+	reg &= ~PRE_EMPHASIS_SET_MASK;
+	reg |= level << PRE_EMPHASIS_SET_SHIFT;
+	writel(reg, dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL);
+}
+
+void analogix_dp_set_lane1_pre_emphasis(struct analogix_dp_device *dp,
+					u32 level)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + ANALOGIX_DP_LN1_LINK_TRAINING_CTL);
+	reg &= ~PRE_EMPHASIS_SET_MASK;
+	reg |= level << PRE_EMPHASIS_SET_SHIFT;
+	writel(reg, dp->reg_base + ANALOGIX_DP_LN1_LINK_TRAINING_CTL);
+}
+
+void analogix_dp_set_lane2_pre_emphasis(struct analogix_dp_device *dp,
+					u32 level)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + ANALOGIX_DP_LN2_LINK_TRAINING_CTL);
+	reg &= ~PRE_EMPHASIS_SET_MASK;
+	reg |= level << PRE_EMPHASIS_SET_SHIFT;
+	writel(reg, dp->reg_base + ANALOGIX_DP_LN2_LINK_TRAINING_CTL);
+}
+
+void analogix_dp_set_lane3_pre_emphasis(struct analogix_dp_device *dp,
+					u32 level)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + ANALOGIX_DP_LN3_LINK_TRAINING_CTL);
+	reg &= ~PRE_EMPHASIS_SET_MASK;
+	reg |= level << PRE_EMPHASIS_SET_SHIFT;
+	writel(reg, dp->reg_base + ANALOGIX_DP_LN3_LINK_TRAINING_CTL);
+}
+
+void analogix_dp_set_lane0_link_training(struct analogix_dp_device *dp,
+					 u32 training_lane)
+{
+	u32 reg;
+
+	reg = training_lane;
+	writel(reg, dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL);
+}
+
+void analogix_dp_set_lane1_link_training(struct analogix_dp_device *dp,
+					 u32 training_lane)
+{
+	u32 reg;
+
+	reg = training_lane;
+	writel(reg, dp->reg_base + ANALOGIX_DP_LN1_LINK_TRAINING_CTL);
+}
+
+void analogix_dp_set_lane2_link_training(struct analogix_dp_device *dp,
+					 u32 training_lane)
+{
+	u32 reg;
+
+	reg = training_lane;
+	writel(reg, dp->reg_base + ANALOGIX_DP_LN2_LINK_TRAINING_CTL);
+}
+
+void analogix_dp_set_lane3_link_training(struct analogix_dp_device *dp,
+					 u32 training_lane)
+{
+	u32 reg;
+
+	reg = training_lane;
+	writel(reg, dp->reg_base + ANALOGIX_DP_LN3_LINK_TRAINING_CTL);
+}
+
+u32 analogix_dp_get_lane0_link_training(struct analogix_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL);
+	return reg;
+}
+
+u32 analogix_dp_get_lane1_link_training(struct analogix_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + ANALOGIX_DP_LN1_LINK_TRAINING_CTL);
+	return reg;
+}
+
+u32 analogix_dp_get_lane2_link_training(struct analogix_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + ANALOGIX_DP_LN2_LINK_TRAINING_CTL);
+	return reg;
+}
+
+u32 analogix_dp_get_lane3_link_training(struct analogix_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + ANALOGIX_DP_LN3_LINK_TRAINING_CTL);
+	return reg;
+}
+
+void analogix_dp_reset_macro(struct analogix_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + ANALOGIX_DP_PHY_TEST);
+	reg |= MACRO_RST;
+	writel(reg, dp->reg_base + ANALOGIX_DP_PHY_TEST);
+
+	/* 10 us is the minimum reset time. */
+	usleep_range(10, 20);
+
+	reg &= ~MACRO_RST;
+	writel(reg, dp->reg_base + ANALOGIX_DP_PHY_TEST);
+}
+
+void analogix_dp_init_video(struct analogix_dp_device *dp)
+{
+	u32 reg;
+
+	reg = VSYNC_DET | VID_FORMAT_CHG | VID_CLK_CHG;
+	writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_1);
+
+	reg = 0x0;
+	writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_1);
+
+	reg = CHA_CRI(4) | CHA_CTRL;
+	writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_2);
+
+	reg = 0x0;
+	writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_3);
+
+	reg = VID_HRES_TH(2) | VID_VRES_TH(0);
+	writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_8);
+}
+
+void analogix_dp_set_video_color_format(struct analogix_dp_device *dp)
+{
+	u32 reg;
+
+	/* Configure the input color depth, color space, dynamic range */
+	reg = (dp->video_info.dynamic_range << IN_D_RANGE_SHIFT) |
+		(dp->video_info.color_depth << IN_BPC_SHIFT) |
+		(dp->video_info.color_space << IN_COLOR_F_SHIFT);
+	writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_2);
+
+	/* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */
+	reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_3);
+	reg &= ~IN_YC_COEFFI_MASK;
+	if (dp->video_info.ycbcr_coeff)
+		reg |= IN_YC_COEFFI_ITU709;
+	else
+		reg |= IN_YC_COEFFI_ITU601;
+	writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_3);
+}
+
+int analogix_dp_is_slave_video_stream_clock_on(struct analogix_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_1);
+	writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_1);
+
+	reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_1);
+
+	if (!(reg & DET_STA)) {
+		dev_dbg(dp->dev, "Input stream clock not detected.\n");
+		return -EINVAL;
+	}
+
+	reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_2);
+	writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_2);
+
+	reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_2);
+	dev_dbg(dp->dev, "wait SYS_CTL_2.\n");
+
+	if (reg & CHA_STA) {
+		dev_dbg(dp->dev, "Input stream clk is changing\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+void analogix_dp_set_video_cr_mn(struct analogix_dp_device *dp,
+				 enum clock_recovery_m_value_type type,
+				 u32 m_value, u32 n_value)
+{
+	u32 reg;
+
+	if (type == REGISTER_M) {
+		reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_4);
+		reg |= FIX_M_VID;
+		writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_4);
+		reg = m_value & 0xff;
+		writel(reg, dp->reg_base + ANALOGIX_DP_M_VID_0);
+		reg = (m_value >> 8) & 0xff;
+		writel(reg, dp->reg_base + ANALOGIX_DP_M_VID_1);
+		reg = (m_value >> 16) & 0xff;
+		writel(reg, dp->reg_base + ANALOGIX_DP_M_VID_2);
+
+		reg = n_value & 0xff;
+		writel(reg, dp->reg_base + ANALOGIX_DP_N_VID_0);
+		reg = (n_value >> 8) & 0xff;
+		writel(reg, dp->reg_base + ANALOGIX_DP_N_VID_1);
+		reg = (n_value >> 16) & 0xff;
+		writel(reg, dp->reg_base + ANALOGIX_DP_N_VID_2);
+	} else  {
+		reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_4);
+		reg &= ~FIX_M_VID;
+		writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_4);
+
+		writel(0x00, dp->reg_base + ANALOGIX_DP_N_VID_0);
+		writel(0x80, dp->reg_base + ANALOGIX_DP_N_VID_1);
+		writel(0x00, dp->reg_base + ANALOGIX_DP_N_VID_2);
+	}
+}
+
+void analogix_dp_set_video_timing_mode(struct analogix_dp_device *dp, u32 type)
+{
+	u32 reg;
+
+	if (type == VIDEO_TIMING_FROM_CAPTURE) {
+		reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10);
+		reg &= ~FORMAT_SEL;
+		writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10);
+	} else {
+		reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10);
+		reg |= FORMAT_SEL;
+		writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10);
+	}
+}
+
+void analogix_dp_enable_video_master(struct analogix_dp_device *dp, bool enable)
+{
+	u32 reg;
+
+	if (enable) {
+		reg = readl(dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL);
+		reg &= ~VIDEO_MODE_MASK;
+		reg |= VIDEO_MASTER_MODE_EN | VIDEO_MODE_MASTER_MODE;
+		writel(reg, dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL);
+	} else {
+		reg = readl(dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL);
+		reg &= ~VIDEO_MODE_MASK;
+		reg |= VIDEO_MODE_SLAVE_MODE;
+		writel(reg, dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL);
+	}
+}
+
+void analogix_dp_start_video(struct analogix_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1);
+	reg |= VIDEO_EN;
+	writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1);
+}
+
+int analogix_dp_is_video_stream_on(struct analogix_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_3);
+	writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_3);
+
+	reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_3);
+	if (!(reg & STRM_VALID)) {
+		dev_dbg(dp->dev, "Input video stream is not detected.\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+void analogix_dp_config_video_slave_mode(struct analogix_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_1);
+	reg &= ~(MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N);
+	reg |= MASTER_VID_FUNC_EN_N;
+	writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_1);
+
+	reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10);
+	reg &= ~INTERACE_SCAN_CFG;
+	reg |= (dp->video_info.interlaced << 2);
+	writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10);
+
+	reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10);
+	reg &= ~VSYNC_POLARITY_CFG;
+	reg |= (dp->video_info.v_sync_polarity << 1);
+	writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10);
+
+	reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10);
+	reg &= ~HSYNC_POLARITY_CFG;
+	reg |= (dp->video_info.h_sync_polarity << 0);
+	writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10);
+
+	reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE;
+	writel(reg, dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL);
+}
+
+void analogix_dp_enable_scrambling(struct analogix_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET);
+	reg &= ~SCRAMBLING_DISABLE;
+	writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET);
+}
+
+void analogix_dp_disable_scrambling(struct analogix_dp_device *dp)
+{
+	u32 reg;
+
+	reg = readl(dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET);
+	reg |= SCRAMBLING_DISABLE;
+	writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET);
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h linux-libre-4.7-gnu/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,378 @@
+/*
+ * Register definition file for Analogix DP core driver
+ *
+ * Copyright (C) 2012 Samsung Electronics Co., Ltd.
+ * Author: Jingoo Han <jg1.han@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _ANALOGIX_DP_REG_H
+#define _ANALOGIX_DP_REG_H
+
+#define ANALOGIX_DP_TX_SW_RESET			0x14
+#define ANALOGIX_DP_FUNC_EN_1			0x18
+#define ANALOGIX_DP_FUNC_EN_2			0x1C
+#define ANALOGIX_DP_VIDEO_CTL_1			0x20
+#define ANALOGIX_DP_VIDEO_CTL_2			0x24
+#define ANALOGIX_DP_VIDEO_CTL_3			0x28
+
+#define ANALOGIX_DP_VIDEO_CTL_8			0x3C
+#define ANALOGIX_DP_VIDEO_CTL_10		0x44
+
+#define ANALOGIX_DP_PLL_REG_1			0xfc
+#define ANALOGIX_DP_PLL_REG_2			0x9e4
+#define ANALOGIX_DP_PLL_REG_3			0x9e8
+#define ANALOGIX_DP_PLL_REG_4			0x9ec
+#define ANALOGIX_DP_PLL_REG_5			0xa00
+
+#define ANALOGIX_DP_PD				0x12c
+
+#define ANALOGIX_DP_LANE_MAP			0x35C
+
+#define ANALOGIX_DP_ANALOG_CTL_1		0x370
+#define ANALOGIX_DP_ANALOG_CTL_2		0x374
+#define ANALOGIX_DP_ANALOG_CTL_3		0x378
+#define ANALOGIX_DP_PLL_FILTER_CTL_1		0x37C
+#define ANALOGIX_DP_TX_AMP_TUNING_CTL		0x380
+
+#define ANALOGIX_DP_AUX_HW_RETRY_CTL		0x390
+
+#define ANALOGIX_DP_COMMON_INT_STA_1		0x3C4
+#define ANALOGIX_DP_COMMON_INT_STA_2		0x3C8
+#define ANALOGIX_DP_COMMON_INT_STA_3		0x3CC
+#define ANALOGIX_DP_COMMON_INT_STA_4		0x3D0
+#define ANALOGIX_DP_INT_STA			0x3DC
+#define ANALOGIX_DP_COMMON_INT_MASK_1		0x3E0
+#define ANALOGIX_DP_COMMON_INT_MASK_2		0x3E4
+#define ANALOGIX_DP_COMMON_INT_MASK_3		0x3E8
+#define ANALOGIX_DP_COMMON_INT_MASK_4		0x3EC
+#define ANALOGIX_DP_INT_STA_MASK		0x3F8
+#define ANALOGIX_DP_INT_CTL			0x3FC
+
+#define ANALOGIX_DP_SYS_CTL_1			0x600
+#define ANALOGIX_DP_SYS_CTL_2			0x604
+#define ANALOGIX_DP_SYS_CTL_3			0x608
+#define ANALOGIX_DP_SYS_CTL_4			0x60C
+
+#define ANALOGIX_DP_PKT_SEND_CTL		0x640
+#define ANALOGIX_DP_HDCP_CTL			0x648
+
+#define ANALOGIX_DP_LINK_BW_SET			0x680
+#define ANALOGIX_DP_LANE_COUNT_SET		0x684
+#define ANALOGIX_DP_TRAINING_PTN_SET		0x688
+#define ANALOGIX_DP_LN0_LINK_TRAINING_CTL	0x68C
+#define ANALOGIX_DP_LN1_LINK_TRAINING_CTL	0x690
+#define ANALOGIX_DP_LN2_LINK_TRAINING_CTL	0x694
+#define ANALOGIX_DP_LN3_LINK_TRAINING_CTL	0x698
+
+#define ANALOGIX_DP_DEBUG_CTL			0x6C0
+#define ANALOGIX_DP_HPD_DEGLITCH_L		0x6C4
+#define ANALOGIX_DP_HPD_DEGLITCH_H		0x6C8
+#define ANALOGIX_DP_LINK_DEBUG_CTL		0x6E0
+
+#define ANALOGIX_DP_M_VID_0			0x700
+#define ANALOGIX_DP_M_VID_1			0x704
+#define ANALOGIX_DP_M_VID_2			0x708
+#define ANALOGIX_DP_N_VID_0			0x70C
+#define ANALOGIX_DP_N_VID_1			0x710
+#define ANALOGIX_DP_N_VID_2			0x714
+
+#define ANALOGIX_DP_PLL_CTL			0x71C
+#define ANALOGIX_DP_PHY_PD			0x720
+#define ANALOGIX_DP_PHY_TEST			0x724
+
+#define ANALOGIX_DP_VIDEO_FIFO_THRD		0x730
+#define ANALOGIX_DP_AUDIO_MARGIN		0x73C
+
+#define ANALOGIX_DP_M_VID_GEN_FILTER_TH		0x764
+#define ANALOGIX_DP_M_AUD_GEN_FILTER_TH		0x778
+#define ANALOGIX_DP_AUX_CH_STA			0x780
+#define ANALOGIX_DP_AUX_CH_DEFER_CTL		0x788
+#define ANALOGIX_DP_AUX_RX_COMM			0x78C
+#define ANALOGIX_DP_BUFFER_DATA_CTL		0x790
+#define ANALOGIX_DP_AUX_CH_CTL_1		0x794
+#define ANALOGIX_DP_AUX_ADDR_7_0		0x798
+#define ANALOGIX_DP_AUX_ADDR_15_8		0x79C
+#define ANALOGIX_DP_AUX_ADDR_19_16		0x7A0
+#define ANALOGIX_DP_AUX_CH_CTL_2		0x7A4
+
+#define ANALOGIX_DP_BUF_DATA_0			0x7C0
+
+#define ANALOGIX_DP_SOC_GENERAL_CTL		0x800
+
+/* ANALOGIX_DP_TX_SW_RESET */
+#define RESET_DP_TX				(0x1 << 0)
+
+/* ANALOGIX_DP_FUNC_EN_1 */
+#define MASTER_VID_FUNC_EN_N			(0x1 << 7)
+#define SLAVE_VID_FUNC_EN_N			(0x1 << 5)
+#define AUD_FIFO_FUNC_EN_N			(0x1 << 4)
+#define AUD_FUNC_EN_N				(0x1 << 3)
+#define HDCP_FUNC_EN_N				(0x1 << 2)
+#define CRC_FUNC_EN_N				(0x1 << 1)
+#define SW_FUNC_EN_N				(0x1 << 0)
+
+/* ANALOGIX_DP_FUNC_EN_2 */
+#define SSC_FUNC_EN_N				(0x1 << 7)
+#define AUX_FUNC_EN_N				(0x1 << 2)
+#define SERDES_FIFO_FUNC_EN_N			(0x1 << 1)
+#define LS_CLK_DOMAIN_FUNC_EN_N			(0x1 << 0)
+
+/* ANALOGIX_DP_VIDEO_CTL_1 */
+#define VIDEO_EN				(0x1 << 7)
+#define HDCP_VIDEO_MUTE				(0x1 << 6)
+
+/* ANALOGIX_DP_VIDEO_CTL_1 */
+#define IN_D_RANGE_MASK				(0x1 << 7)
+#define IN_D_RANGE_SHIFT			(7)
+#define IN_D_RANGE_CEA				(0x1 << 7)
+#define IN_D_RANGE_VESA				(0x0 << 7)
+#define IN_BPC_MASK				(0x7 << 4)
+#define IN_BPC_SHIFT				(4)
+#define IN_BPC_12_BITS				(0x3 << 4)
+#define IN_BPC_10_BITS				(0x2 << 4)
+#define IN_BPC_8_BITS				(0x1 << 4)
+#define IN_BPC_6_BITS				(0x0 << 4)
+#define IN_COLOR_F_MASK				(0x3 << 0)
+#define IN_COLOR_F_SHIFT			(0)
+#define IN_COLOR_F_YCBCR444			(0x2 << 0)
+#define IN_COLOR_F_YCBCR422			(0x1 << 0)
+#define IN_COLOR_F_RGB				(0x0 << 0)
+
+/* ANALOGIX_DP_VIDEO_CTL_3 */
+#define IN_YC_COEFFI_MASK			(0x1 << 7)
+#define IN_YC_COEFFI_SHIFT			(7)
+#define IN_YC_COEFFI_ITU709			(0x1 << 7)
+#define IN_YC_COEFFI_ITU601			(0x0 << 7)
+#define VID_CHK_UPDATE_TYPE_MASK		(0x1 << 4)
+#define VID_CHK_UPDATE_TYPE_SHIFT		(4)
+#define VID_CHK_UPDATE_TYPE_1			(0x1 << 4)
+#define VID_CHK_UPDATE_TYPE_0			(0x0 << 4)
+
+/* ANALOGIX_DP_VIDEO_CTL_8 */
+#define VID_HRES_TH(x)				(((x) & 0xf) << 4)
+#define VID_VRES_TH(x)				(((x) & 0xf) << 0)
+
+/* ANALOGIX_DP_VIDEO_CTL_10 */
+#define FORMAT_SEL				(0x1 << 4)
+#define INTERACE_SCAN_CFG			(0x1 << 2)
+#define VSYNC_POLARITY_CFG			(0x1 << 1)
+#define HSYNC_POLARITY_CFG			(0x1 << 0)
+
+/* ANALOGIX_DP_PLL_REG_1 */
+#define REF_CLK_24M				(0x1 << 1)
+#define REF_CLK_27M				(0x0 << 1)
+
+/* ANALOGIX_DP_LANE_MAP */
+#define LANE3_MAP_LOGIC_LANE_0			(0x0 << 6)
+#define LANE3_MAP_LOGIC_LANE_1			(0x1 << 6)
+#define LANE3_MAP_LOGIC_LANE_2			(0x2 << 6)
+#define LANE3_MAP_LOGIC_LANE_3			(0x3 << 6)
+#define LANE2_MAP_LOGIC_LANE_0			(0x0 << 4)
+#define LANE2_MAP_LOGIC_LANE_1			(0x1 << 4)
+#define LANE2_MAP_LOGIC_LANE_2			(0x2 << 4)
+#define LANE2_MAP_LOGIC_LANE_3			(0x3 << 4)
+#define LANE1_MAP_LOGIC_LANE_0			(0x0 << 2)
+#define LANE1_MAP_LOGIC_LANE_1			(0x1 << 2)
+#define LANE1_MAP_LOGIC_LANE_2			(0x2 << 2)
+#define LANE1_MAP_LOGIC_LANE_3			(0x3 << 2)
+#define LANE0_MAP_LOGIC_LANE_0			(0x0 << 0)
+#define LANE0_MAP_LOGIC_LANE_1			(0x1 << 0)
+#define LANE0_MAP_LOGIC_LANE_2			(0x2 << 0)
+#define LANE0_MAP_LOGIC_LANE_3			(0x3 << 0)
+
+/* ANALOGIX_DP_ANALOG_CTL_1 */
+#define TX_TERMINAL_CTRL_50_OHM			(0x1 << 4)
+
+/* ANALOGIX_DP_ANALOG_CTL_2 */
+#define SEL_24M					(0x1 << 3)
+#define TX_DVDD_BIT_1_0625V			(0x4 << 0)
+
+/* ANALOGIX_DP_ANALOG_CTL_3 */
+#define DRIVE_DVDD_BIT_1_0625V			(0x4 << 5)
+#define VCO_BIT_600_MICRO			(0x5 << 0)
+
+/* ANALOGIX_DP_PLL_FILTER_CTL_1 */
+#define PD_RING_OSC				(0x1 << 6)
+#define AUX_TERMINAL_CTRL_50_OHM		(0x2 << 4)
+#define TX_CUR1_2X				(0x1 << 2)
+#define TX_CUR_16_MA				(0x3 << 0)
+
+/* ANALOGIX_DP_TX_AMP_TUNING_CTL */
+#define CH3_AMP_400_MV				(0x0 << 24)
+#define CH2_AMP_400_MV				(0x0 << 16)
+#define CH1_AMP_400_MV				(0x0 << 8)
+#define CH0_AMP_400_MV				(0x0 << 0)
+
+/* ANALOGIX_DP_AUX_HW_RETRY_CTL */
+#define AUX_BIT_PERIOD_EXPECTED_DELAY(x)	(((x) & 0x7) << 8)
+#define AUX_HW_RETRY_INTERVAL_MASK		(0x3 << 3)
+#define AUX_HW_RETRY_INTERVAL_600_MICROSECONDS	(0x0 << 3)
+#define AUX_HW_RETRY_INTERVAL_800_MICROSECONDS	(0x1 << 3)
+#define AUX_HW_RETRY_INTERVAL_1000_MICROSECONDS	(0x2 << 3)
+#define AUX_HW_RETRY_INTERVAL_1800_MICROSECONDS	(0x3 << 3)
+#define AUX_HW_RETRY_COUNT_SEL(x)		(((x) & 0x7) << 0)
+
+/* ANALOGIX_DP_COMMON_INT_STA_1 */
+#define VSYNC_DET				(0x1 << 7)
+#define PLL_LOCK_CHG				(0x1 << 6)
+#define SPDIF_ERR				(0x1 << 5)
+#define SPDIF_UNSTBL				(0x1 << 4)
+#define VID_FORMAT_CHG				(0x1 << 3)
+#define AUD_CLK_CHG				(0x1 << 2)
+#define VID_CLK_CHG				(0x1 << 1)
+#define SW_INT					(0x1 << 0)
+
+/* ANALOGIX_DP_COMMON_INT_STA_2 */
+#define ENC_EN_CHG				(0x1 << 6)
+#define HW_BKSV_RDY				(0x1 << 3)
+#define HW_SHA_DONE				(0x1 << 2)
+#define HW_AUTH_STATE_CHG			(0x1 << 1)
+#define HW_AUTH_DONE				(0x1 << 0)
+
+/* ANALOGIX_DP_COMMON_INT_STA_3 */
+#define AFIFO_UNDER				(0x1 << 7)
+#define AFIFO_OVER				(0x1 << 6)
+#define R0_CHK_FLAG				(0x1 << 5)
+
+/* ANALOGIX_DP_COMMON_INT_STA_4 */
+#define PSR_ACTIVE				(0x1 << 7)
+#define PSR_INACTIVE				(0x1 << 6)
+#define SPDIF_BI_PHASE_ERR			(0x1 << 5)
+#define HOTPLUG_CHG				(0x1 << 2)
+#define HPD_LOST				(0x1 << 1)
+#define PLUG					(0x1 << 0)
+
+/* ANALOGIX_DP_INT_STA */
+#define INT_HPD					(0x1 << 6)
+#define HW_TRAINING_FINISH			(0x1 << 5)
+#define RPLY_RECEIV				(0x1 << 1)
+#define AUX_ERR					(0x1 << 0)
+
+/* ANALOGIX_DP_INT_CTL */
+#define SOFT_INT_CTRL				(0x1 << 2)
+#define INT_POL1				(0x1 << 1)
+#define INT_POL0				(0x1 << 0)
+
+/* ANALOGIX_DP_SYS_CTL_1 */
+#define DET_STA					(0x1 << 2)
+#define FORCE_DET				(0x1 << 1)
+#define DET_CTRL				(0x1 << 0)
+
+/* ANALOGIX_DP_SYS_CTL_2 */
+#define CHA_CRI(x)				(((x) & 0xf) << 4)
+#define CHA_STA					(0x1 << 2)
+#define FORCE_CHA				(0x1 << 1)
+#define CHA_CTRL				(0x1 << 0)
+
+/* ANALOGIX_DP_SYS_CTL_3 */
+#define HPD_STATUS				(0x1 << 6)
+#define F_HPD					(0x1 << 5)
+#define HPD_CTRL				(0x1 << 4)
+#define HDCP_RDY				(0x1 << 3)
+#define STRM_VALID				(0x1 << 2)
+#define F_VALID					(0x1 << 1)
+#define VALID_CTRL				(0x1 << 0)
+
+/* ANALOGIX_DP_SYS_CTL_4 */
+#define FIX_M_AUD				(0x1 << 4)
+#define ENHANCED				(0x1 << 3)
+#define FIX_M_VID				(0x1 << 2)
+#define M_VID_UPDATE_CTRL			(0x3 << 0)
+
+/* ANALOGIX_DP_TRAINING_PTN_SET */
+#define SCRAMBLER_TYPE				(0x1 << 9)
+#define HW_LINK_TRAINING_PATTERN		(0x1 << 8)
+#define SCRAMBLING_DISABLE			(0x1 << 5)
+#define SCRAMBLING_ENABLE			(0x0 << 5)
+#define LINK_QUAL_PATTERN_SET_MASK		(0x3 << 2)
+#define LINK_QUAL_PATTERN_SET_PRBS7		(0x3 << 2)
+#define LINK_QUAL_PATTERN_SET_D10_2		(0x1 << 2)
+#define LINK_QUAL_PATTERN_SET_DISABLE		(0x0 << 2)
+#define SW_TRAINING_PATTERN_SET_MASK		(0x3 << 0)
+#define SW_TRAINING_PATTERN_SET_PTN2		(0x2 << 0)
+#define SW_TRAINING_PATTERN_SET_PTN1		(0x1 << 0)
+#define SW_TRAINING_PATTERN_SET_NORMAL		(0x0 << 0)
+
+/* ANALOGIX_DP_LN0_LINK_TRAINING_CTL */
+#define PRE_EMPHASIS_SET_MASK			(0x3 << 3)
+#define PRE_EMPHASIS_SET_SHIFT			(3)
+
+/* ANALOGIX_DP_DEBUG_CTL */
+#define PLL_LOCK				(0x1 << 4)
+#define F_PLL_LOCK				(0x1 << 3)
+#define PLL_LOCK_CTRL				(0x1 << 2)
+#define PN_INV					(0x1 << 0)
+
+/* ANALOGIX_DP_PLL_CTL */
+#define DP_PLL_PD				(0x1 << 7)
+#define DP_PLL_RESET				(0x1 << 6)
+#define DP_PLL_LOOP_BIT_DEFAULT			(0x1 << 4)
+#define DP_PLL_REF_BIT_1_1250V			(0x5 << 0)
+#define DP_PLL_REF_BIT_1_2500V			(0x7 << 0)
+
+/* ANALOGIX_DP_PHY_PD */
+#define DP_PHY_PD				(0x1 << 5)
+#define AUX_PD					(0x1 << 4)
+#define CH3_PD					(0x1 << 3)
+#define CH2_PD					(0x1 << 2)
+#define CH1_PD					(0x1 << 1)
+#define CH0_PD					(0x1 << 0)
+
+/* ANALOGIX_DP_PHY_TEST */
+#define MACRO_RST				(0x1 << 5)
+#define CH1_TEST				(0x1 << 1)
+#define CH0_TEST				(0x1 << 0)
+
+/* ANALOGIX_DP_AUX_CH_STA */
+#define AUX_BUSY				(0x1 << 4)
+#define AUX_STATUS_MASK				(0xf << 0)
+
+/* ANALOGIX_DP_AUX_CH_DEFER_CTL */
+#define DEFER_CTRL_EN				(0x1 << 7)
+#define DEFER_COUNT(x)				(((x) & 0x7f) << 0)
+
+/* ANALOGIX_DP_AUX_RX_COMM */
+#define AUX_RX_COMM_I2C_DEFER			(0x2 << 2)
+#define AUX_RX_COMM_AUX_DEFER			(0x2 << 0)
+
+/* ANALOGIX_DP_BUFFER_DATA_CTL */
+#define BUF_CLR					(0x1 << 7)
+#define BUF_DATA_COUNT(x)			(((x) & 0x1f) << 0)
+
+/* ANALOGIX_DP_AUX_CH_CTL_1 */
+#define AUX_LENGTH(x)				(((x - 1) & 0xf) << 4)
+#define AUX_TX_COMM_MASK			(0xf << 0)
+#define AUX_TX_COMM_DP_TRANSACTION		(0x1 << 3)
+#define AUX_TX_COMM_I2C_TRANSACTION		(0x0 << 3)
+#define AUX_TX_COMM_MOT				(0x1 << 2)
+#define AUX_TX_COMM_WRITE			(0x0 << 0)
+#define AUX_TX_COMM_READ			(0x1 << 0)
+
+/* ANALOGIX_DP_AUX_ADDR_7_0 */
+#define AUX_ADDR_7_0(x)				(((x) >> 0) & 0xff)
+
+/* ANALOGIX_DP_AUX_ADDR_15_8 */
+#define AUX_ADDR_15_8(x)			(((x) >> 8) & 0xff)
+
+/* ANALOGIX_DP_AUX_ADDR_19_16 */
+#define AUX_ADDR_19_16(x)			(((x) >> 16) & 0x0f)
+
+/* ANALOGIX_DP_AUX_CH_CTL_2 */
+#define ADDR_ONLY				(0x1 << 1)
+#define AUX_EN					(0x1 << 0)
+
+/* ANALOGIX_DP_SOC_GENERAL_CTL */
+#define AUDIO_MODE_SPDIF_MODE			(0x1 << 8)
+#define AUDIO_MODE_MASTER_MODE			(0x0 << 8)
+#define MASTER_VIDEO_INTERLACE_EN		(0x1 << 4)
+#define VIDEO_MASTER_CLK_SEL			(0x1 << 2)
+#define VIDEO_MASTER_MODE_EN			(0x1 << 1)
+#define VIDEO_MODE_MASK				(0x1 << 0)
+#define VIDEO_MODE_SLAVE_MODE			(0x1 << 0)
+#define VIDEO_MODE_MASTER_MODE			(0x0 << 0)
+
+#endif /* _ANALOGIX_DP_REG_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/bridge/analogix/Kconfig linux-libre-4.7-gnu/drivers/gpu/drm/bridge/analogix/Kconfig
--- linux-libre-4.6-gnu/drivers/gpu/drm/bridge/analogix/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/bridge/analogix/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,3 @@
+config DRM_ANALOGIX_DP
+	tristate
+	depends on DRM
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/bridge/analogix/Makefile linux-libre-4.7-gnu/drivers/gpu/drm/bridge/analogix/Makefile
--- linux-libre-4.6-gnu/drivers/gpu/drm/bridge/analogix/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/bridge/analogix/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,2 @@
+analogix_dp-objs := analogix_dp_core.o analogix_dp_reg.o
+obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix_dp.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/bridge/analogix-anx78xx.c linux-libre-4.7-gnu/drivers/gpu/drm/bridge/analogix-anx78xx.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/bridge/analogix-anx78xx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/bridge/analogix-anx78xx.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,1514 @@
+/*
+ * Copyright(c) 2016, Analogix Semiconductor.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 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.
+ *
+ * Based on anx7808 driver obtained from chromeos with copyright:
+ * Copyright(c) 2013, Google Inc.
+ *
+ */
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/regmap.h>
+#include <linux/types.h>
+#include <linux/gpio/consumer.h>
+#include <linux/regulator/consumer.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_dp_helper.h>
+#include <drm/drm_edid.h>
+
+#include "analogix-anx78xx.h"
+
+#define I2C_NUM_ADDRESSES	5
+#define I2C_IDX_TX_P0		0
+#define I2C_IDX_TX_P1		1
+#define I2C_IDX_TX_P2		2
+#define I2C_IDX_RX_P0		3
+#define I2C_IDX_RX_P1		4
+
+#define XTAL_CLK		270 /* 27M */
+#define AUX_CH_BUFFER_SIZE	16
+#define AUX_WAIT_TIMEOUT_MS	15
+
+static const u8 anx78xx_i2c_addresses[] = {
+	[I2C_IDX_TX_P0] = TX_P0,
+	[I2C_IDX_TX_P1] = TX_P1,
+	[I2C_IDX_TX_P2] = TX_P2,
+	[I2C_IDX_RX_P0] = RX_P0,
+	[I2C_IDX_RX_P1] = RX_P1,
+};
+
+struct anx78xx_platform_data {
+	struct regulator *dvdd10;
+	struct gpio_desc *gpiod_hpd;
+	struct gpio_desc *gpiod_pd;
+	struct gpio_desc *gpiod_reset;
+
+	int hpd_irq;
+	int intp_irq;
+};
+
+struct anx78xx {
+	struct drm_dp_aux aux;
+	struct drm_bridge bridge;
+	struct i2c_client *client;
+	struct edid *edid;
+	struct drm_connector connector;
+	struct drm_dp_link link;
+	struct anx78xx_platform_data pdata;
+	struct mutex lock;
+
+	/*
+	 * I2C Slave addresses of ANX7814 are mapped as TX_P0, TX_P1, TX_P2,
+	 * RX_P0 and RX_P1.
+	 */
+	struct i2c_client *i2c_dummy[I2C_NUM_ADDRESSES];
+	struct regmap *map[I2C_NUM_ADDRESSES];
+
+	u16 chipid;
+	u8 dpcd[DP_RECEIVER_CAP_SIZE];
+
+	bool powered;
+};
+
+static inline struct anx78xx *connector_to_anx78xx(struct drm_connector *c)
+{
+	return container_of(c, struct anx78xx, connector);
+}
+
+static inline struct anx78xx *bridge_to_anx78xx(struct drm_bridge *bridge)
+{
+	return container_of(bridge, struct anx78xx, bridge);
+}
+
+static int anx78xx_set_bits(struct regmap *map, u8 reg, u8 mask)
+{
+	return regmap_update_bits(map, reg, mask, mask);
+}
+
+static int anx78xx_clear_bits(struct regmap *map, u8 reg, u8 mask)
+{
+	return regmap_update_bits(map, reg, mask, 0);
+}
+
+static bool anx78xx_aux_op_finished(struct anx78xx *anx78xx)
+{
+	unsigned int value;
+	int err;
+
+	err = regmap_read(anx78xx->map[I2C_IDX_TX_P0], SP_DP_AUX_CH_CTRL2_REG,
+			  &value);
+	if (err < 0)
+		return false;
+
+	return (value & SP_AUX_EN) == 0;
+}
+
+static int anx78xx_aux_wait(struct anx78xx *anx78xx)
+{
+	unsigned long timeout;
+	unsigned int status;
+	int err;
+
+	timeout = jiffies + msecs_to_jiffies(AUX_WAIT_TIMEOUT_MS) + 1;
+
+	while (!anx78xx_aux_op_finished(anx78xx)) {
+		if (time_after(jiffies, timeout)) {
+			if (!anx78xx_aux_op_finished(anx78xx)) {
+				DRM_ERROR("Timed out waiting AUX to finish\n");
+				return -ETIMEDOUT;
+			}
+
+			break;
+		}
+
+		usleep_range(1000, 2000);
+	}
+
+	/* Read the AUX channel access status */
+	err = regmap_read(anx78xx->map[I2C_IDX_TX_P0], SP_AUX_CH_STATUS_REG,
+			  &status);
+	if (err < 0) {
+		DRM_ERROR("Failed to read from AUX channel: %d\n", err);
+		return err;
+	}
+
+	if (status & SP_AUX_STATUS) {
+		DRM_ERROR("Failed to wait for AUX channel (status: %02x)\n",
+			  status);
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+static int anx78xx_aux_address(struct anx78xx *anx78xx, unsigned int addr)
+{
+	int err;
+
+	err = regmap_write(anx78xx->map[I2C_IDX_TX_P0], SP_AUX_ADDR_7_0_REG,
+			   addr & 0xff);
+	if (err)
+		return err;
+
+	err = regmap_write(anx78xx->map[I2C_IDX_TX_P0], SP_AUX_ADDR_15_8_REG,
+			   (addr & 0xff00) >> 8);
+	if (err)
+		return err;
+
+	/*
+	 * DP AUX CH Address Register #2, only update bits[3:0]
+	 * [7:4] RESERVED
+	 * [3:0] AUX_ADDR[19:16], Register control AUX CH address.
+	 */
+	err = regmap_update_bits(anx78xx->map[I2C_IDX_TX_P0],
+				 SP_AUX_ADDR_19_16_REG,
+				 SP_AUX_ADDR_19_16_MASK,
+				 (addr & 0xf0000) >> 16);
+
+	if (err)
+		return err;
+
+	return 0;
+}
+
+static ssize_t anx78xx_aux_transfer(struct drm_dp_aux *aux,
+				    struct drm_dp_aux_msg *msg)
+{
+	struct anx78xx *anx78xx = container_of(aux, struct anx78xx, aux);
+	u8 ctrl1 = msg->request;
+	u8 ctrl2 = SP_AUX_EN;
+	u8 *buffer = msg->buffer;
+	int err;
+
+	/* The DP AUX transmit and receive buffer has 16 bytes. */
+	if (WARN_ON(msg->size > AUX_CH_BUFFER_SIZE))
+		return -E2BIG;
+
+	/* Zero-sized messages specify address-only transactions. */
+	if (msg->size < 1)
+		ctrl2 |= SP_ADDR_ONLY;
+	else	/* For non-zero-sized set the length field. */
+		ctrl1 |= (msg->size - 1) << SP_AUX_LENGTH_SHIFT;
+
+	if ((msg->request & DP_AUX_I2C_READ) == 0) {
+		/* When WRITE | MOT write values to data buffer */
+		err = regmap_bulk_write(anx78xx->map[I2C_IDX_TX_P0],
+					SP_DP_BUF_DATA0_REG, buffer,
+					msg->size);
+		if (err)
+			return err;
+	}
+
+	/* Write address and request */
+	err = anx78xx_aux_address(anx78xx, msg->address);
+	if (err)
+		return err;
+
+	err = regmap_write(anx78xx->map[I2C_IDX_TX_P0], SP_DP_AUX_CH_CTRL1_REG,
+			   ctrl1);
+	if (err)
+		return err;
+
+	/* Start transaction */
+	err = regmap_update_bits(anx78xx->map[I2C_IDX_TX_P0],
+				 SP_DP_AUX_CH_CTRL2_REG, SP_ADDR_ONLY |
+				 SP_AUX_EN, ctrl2);
+	if (err)
+		return err;
+
+	err = anx78xx_aux_wait(anx78xx);
+	if (err)
+		return err;
+
+	msg->reply = DP_AUX_I2C_REPLY_ACK;
+
+	if ((msg->size > 0) && (msg->request & DP_AUX_I2C_READ)) {
+		/* Read values from data buffer */
+		err = regmap_bulk_read(anx78xx->map[I2C_IDX_TX_P0],
+				       SP_DP_BUF_DATA0_REG, buffer,
+				       msg->size);
+		if (err)
+			return err;
+	}
+
+	err = anx78xx_clear_bits(anx78xx->map[I2C_IDX_TX_P0],
+				 SP_DP_AUX_CH_CTRL2_REG, SP_ADDR_ONLY);
+	if (err)
+		return err;
+
+	return msg->size;
+}
+
+static int anx78xx_set_hpd(struct anx78xx *anx78xx)
+{
+	int err;
+
+	err = anx78xx_clear_bits(anx78xx->map[I2C_IDX_RX_P0],
+				 SP_TMDS_CTRL_BASE + 7, SP_PD_RT);
+	if (err)
+		return err;
+
+	err = anx78xx_set_bits(anx78xx->map[I2C_IDX_TX_P2], SP_VID_CTRL3_REG,
+			       SP_HPD_OUT);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+static int anx78xx_clear_hpd(struct anx78xx *anx78xx)
+{
+	int err;
+
+	err = anx78xx_clear_bits(anx78xx->map[I2C_IDX_TX_P2], SP_VID_CTRL3_REG,
+				 SP_HPD_OUT);
+	if (err)
+		return err;
+
+	err = anx78xx_set_bits(anx78xx->map[I2C_IDX_RX_P0],
+			       SP_TMDS_CTRL_BASE + 7, SP_PD_RT);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+static const struct reg_sequence tmds_phy_initialization[] = {
+	{ SP_TMDS_CTRL_BASE +  1, 0x90 },
+	{ SP_TMDS_CTRL_BASE +  2, 0xa9 },
+	{ SP_TMDS_CTRL_BASE +  6, 0x92 },
+	{ SP_TMDS_CTRL_BASE +  7, 0x80 },
+	{ SP_TMDS_CTRL_BASE + 20, 0xf2 },
+	{ SP_TMDS_CTRL_BASE + 22, 0xc4 },
+	{ SP_TMDS_CTRL_BASE + 23, 0x18 },
+};
+
+static int anx78xx_rx_initialization(struct anx78xx *anx78xx)
+{
+	int err;
+
+	err = regmap_write(anx78xx->map[I2C_IDX_RX_P0], SP_HDMI_MUTE_CTRL_REG,
+			   SP_AUD_MUTE | SP_VID_MUTE);
+	if (err)
+		return err;
+
+	err = anx78xx_set_bits(anx78xx->map[I2C_IDX_RX_P0], SP_CHIP_CTRL_REG,
+			       SP_MAN_HDMI5V_DET | SP_PLLLOCK_CKDT_EN |
+			       SP_DIGITAL_CKDT_EN);
+	if (err)
+		return err;
+
+	err = anx78xx_set_bits(anx78xx->map[I2C_IDX_RX_P0],
+			       SP_SOFTWARE_RESET1_REG, SP_HDCP_MAN_RST |
+			       SP_SW_MAN_RST | SP_TMDS_RST | SP_VIDEO_RST);
+	if (err)
+		return err;
+
+	err = anx78xx_clear_bits(anx78xx->map[I2C_IDX_RX_P0],
+				 SP_SOFTWARE_RESET1_REG, SP_HDCP_MAN_RST |
+				 SP_SW_MAN_RST | SP_TMDS_RST | SP_VIDEO_RST);
+	if (err)
+		return err;
+
+	/* Sync detect change, GP set mute */
+	err = anx78xx_set_bits(anx78xx->map[I2C_IDX_RX_P0],
+			       SP_AUD_EXCEPTION_ENABLE_BASE + 1, BIT(5) |
+			       BIT(6));
+	if (err)
+		return err;
+
+	err = anx78xx_set_bits(anx78xx->map[I2C_IDX_RX_P0],
+			       SP_AUD_EXCEPTION_ENABLE_BASE + 3,
+			       SP_AEC_EN21);
+	if (err)
+		return err;
+
+	err = anx78xx_set_bits(anx78xx->map[I2C_IDX_RX_P0], SP_AUDVID_CTRL_REG,
+			       SP_AVC_EN | SP_AAC_OE | SP_AAC_EN);
+	if (err)
+		return err;
+
+	err = anx78xx_clear_bits(anx78xx->map[I2C_IDX_RX_P0],
+				 SP_SYSTEM_POWER_DOWN1_REG, SP_PWDN_CTRL);
+	if (err)
+		return err;
+
+	err = anx78xx_set_bits(anx78xx->map[I2C_IDX_RX_P0],
+			       SP_VID_DATA_RANGE_CTRL_REG, SP_R2Y_INPUT_LIMIT);
+	if (err)
+		return err;
+
+	/* Enable DDC stretch */
+	err = regmap_write(anx78xx->map[I2C_IDX_TX_P0],
+			   SP_DP_EXTRA_I2C_DEV_ADDR_REG, SP_I2C_EXTRA_ADDR);
+	if (err)
+		return err;
+
+	/* TMDS phy initialization */
+	err = regmap_multi_reg_write(anx78xx->map[I2C_IDX_RX_P0],
+				     tmds_phy_initialization,
+				     ARRAY_SIZE(tmds_phy_initialization));
+	if (err)
+		return err;
+
+	err = anx78xx_clear_hpd(anx78xx);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+static const u8 dp_tx_output_precise_tune_bits[20] = {
+	0x01, 0x03, 0x07, 0x7f, 0x71, 0x6b, 0x7f,
+	0x73, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00,
+	0x0c, 0x42, 0x1e, 0x3e, 0x72, 0x7e,
+};
+
+static int anx78xx_link_phy_initialization(struct anx78xx *anx78xx)
+{
+	int err;
+
+	/*
+	 * REVISIT : It is writing to a RESERVED bits in Analog Control 0
+	 * register.
+	 */
+	err = regmap_write(anx78xx->map[I2C_IDX_TX_P2], SP_ANALOG_CTRL0_REG,
+			   0x02);
+	if (err)
+		return err;
+
+	/*
+	 * Write DP TX output emphasis precise tune bits.
+	 */
+	err = regmap_bulk_write(anx78xx->map[I2C_IDX_TX_P1],
+				SP_DP_TX_LT_CTRL0_REG,
+				dp_tx_output_precise_tune_bits,
+				ARRAY_SIZE(dp_tx_output_precise_tune_bits));
+
+	if (err)
+		return err;
+
+	return 0;
+}
+
+static int anx78xx_xtal_clk_sel(struct anx78xx *anx78xx)
+{
+	unsigned int value;
+	int err;
+
+	err = regmap_update_bits(anx78xx->map[I2C_IDX_TX_P2],
+				 SP_ANALOG_DEBUG2_REG,
+				 SP_XTAL_FRQ | SP_FORCE_SW_OFF_BYPASS,
+				 SP_XTAL_FRQ_27M);
+	if (err)
+		return err;
+
+	err = regmap_write(anx78xx->map[I2C_IDX_TX_P0], SP_DP_AUX_CH_CTRL3_REG,
+			   XTAL_CLK & SP_WAIT_COUNTER_7_0_MASK);
+	if (err)
+		return err;
+
+	err = regmap_write(anx78xx->map[I2C_IDX_TX_P0], SP_DP_AUX_CH_CTRL4_REG,
+			   ((XTAL_CLK & 0xff00) >> 2) | (XTAL_CLK / 10));
+	if (err)
+		return err;
+
+	err = regmap_write(anx78xx->map[I2C_IDX_TX_P0],
+			   SP_I2C_GEN_10US_TIMER0_REG, XTAL_CLK & 0xff);
+	if (err)
+		return err;
+
+	err = regmap_write(anx78xx->map[I2C_IDX_TX_P0],
+			   SP_I2C_GEN_10US_TIMER1_REG,
+			   (XTAL_CLK & 0xff00) >> 8);
+	if (err)
+		return err;
+
+	err = regmap_write(anx78xx->map[I2C_IDX_TX_P0], SP_AUX_MISC_CTRL_REG,
+			   XTAL_CLK / 10 - 1);
+	if (err)
+		return err;
+
+	err = regmap_read(anx78xx->map[I2C_IDX_RX_P0],
+			  SP_HDMI_US_TIMER_CTRL_REG,
+			  &value);
+	if (err)
+		return err;
+
+	err = regmap_write(anx78xx->map[I2C_IDX_RX_P0],
+			   SP_HDMI_US_TIMER_CTRL_REG,
+			   (value & SP_MS_TIMER_MARGIN_10_8_MASK) |
+			   ((((XTAL_CLK / 10) >> 1) - 2) << 3));
+	if (err)
+		return err;
+
+	return 0;
+}
+
+static const struct reg_sequence otp_key_protect[] = {
+	{ SP_OTP_KEY_PROTECT1_REG, SP_OTP_PSW1 },
+	{ SP_OTP_KEY_PROTECT2_REG, SP_OTP_PSW2 },
+	{ SP_OTP_KEY_PROTECT3_REG, SP_OTP_PSW3 },
+};
+
+static int anx78xx_tx_initialization(struct anx78xx *anx78xx)
+{
+	int err;
+
+	/* Set terminal resistor to 50 ohm */
+	err = regmap_write(anx78xx->map[I2C_IDX_TX_P0], SP_DP_AUX_CH_CTRL2_REG,
+			   0x30);
+	if (err)
+		return err;
+
+	/* Enable aux double diff output */
+	err = anx78xx_set_bits(anx78xx->map[I2C_IDX_TX_P0],
+			       SP_DP_AUX_CH_CTRL2_REG, 0x08);
+	if (err)
+		return err;
+
+	err = anx78xx_clear_bits(anx78xx->map[I2C_IDX_TX_P0],
+				 SP_DP_HDCP_CTRL_REG, SP_AUTO_EN |
+				 SP_AUTO_START);
+	if (err)
+		return err;
+
+	err = regmap_multi_reg_write(anx78xx->map[I2C_IDX_TX_P0],
+				     otp_key_protect,
+				     ARRAY_SIZE(otp_key_protect));
+	if (err)
+		return err;
+
+	err = anx78xx_set_bits(anx78xx->map[I2C_IDX_TX_P0],
+			       SP_HDCP_KEY_COMMAND_REG, SP_DISABLE_SYNC_HDCP);
+	if (err)
+		return err;
+
+	err = regmap_write(anx78xx->map[I2C_IDX_TX_P2], SP_VID_CTRL8_REG,
+			   SP_VID_VRES_TH);
+	if (err)
+		return err;
+
+	/*
+	 * DP HDCP auto authentication wait timer (when downstream starts to
+	 * auth, DP side will wait for this period then do auth automatically)
+	 */
+	err = regmap_write(anx78xx->map[I2C_IDX_TX_P0], SP_HDCP_AUTO_TIMER_REG,
+			   0x00);
+	if (err)
+		return err;
+
+	err = anx78xx_set_bits(anx78xx->map[I2C_IDX_TX_P0],
+			       SP_DP_HDCP_CTRL_REG, SP_LINK_POLLING);
+	if (err)
+		return err;
+
+	err = anx78xx_set_bits(anx78xx->map[I2C_IDX_TX_P0],
+			       SP_DP_LINK_DEBUG_CTRL_REG, SP_M_VID_DEBUG);
+	if (err)
+		return err;
+
+	err = anx78xx_set_bits(anx78xx->map[I2C_IDX_TX_P2],
+			       SP_ANALOG_DEBUG2_REG, SP_POWERON_TIME_1P5MS);
+	if (err)
+		return err;
+
+	err = anx78xx_xtal_clk_sel(anx78xx);
+	if (err)
+		return err;
+
+	err = regmap_write(anx78xx->map[I2C_IDX_TX_P0], SP_AUX_DEFER_CTRL_REG,
+			   SP_DEFER_CTRL_EN | 0x0c);
+	if (err)
+		return err;
+
+	err = anx78xx_set_bits(anx78xx->map[I2C_IDX_TX_P0],
+			       SP_DP_POLLING_CTRL_REG,
+			       SP_AUTO_POLLING_DISABLE);
+	if (err)
+		return err;
+
+	/*
+	 * Short the link integrity check timer to speed up bstatus
+	 * polling for HDCP CTS item 1A-07
+	 */
+	err = regmap_write(anx78xx->map[I2C_IDX_TX_P0],
+			   SP_HDCP_LINK_CHECK_TIMER_REG, 0x1d);
+	if (err)
+		return err;
+
+	err = anx78xx_set_bits(anx78xx->map[I2C_IDX_TX_P0],
+			       SP_DP_MISC_CTRL_REG, SP_EQ_TRAINING_LOOP);
+	if (err)
+		return err;
+
+	/* Power down the main link by default */
+	err = anx78xx_set_bits(anx78xx->map[I2C_IDX_TX_P0],
+			       SP_DP_ANALOG_POWER_DOWN_REG, SP_CH0_PD);
+	if (err)
+		return err;
+
+	err = anx78xx_link_phy_initialization(anx78xx);
+	if (err)
+		return err;
+
+	/* Gen m_clk with downspreading */
+	err = anx78xx_set_bits(anx78xx->map[I2C_IDX_TX_P0],
+			       SP_DP_M_CALCULATION_CTRL_REG, SP_M_GEN_CLK_SEL);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+static int anx78xx_enable_interrupts(struct anx78xx *anx78xx)
+{
+	int err;
+
+	/*
+	 * BIT0: INT pin assertion polarity: 1 = assert high
+	 * BIT1: INT pin output type: 0 = push/pull
+	 */
+	err = regmap_write(anx78xx->map[I2C_IDX_TX_P2], SP_INT_CTRL_REG, 0x01);
+	if (err)
+		return err;
+
+	err = regmap_write(anx78xx->map[I2C_IDX_TX_P2],
+			   SP_COMMON_INT_MASK4_REG, SP_HPD_LOST | SP_HPD_PLUG);
+	if (err)
+		return err;
+
+	err = regmap_write(anx78xx->map[I2C_IDX_TX_P2], SP_DP_INT_MASK1_REG,
+			   SP_TRAINING_FINISH);
+	if (err)
+		return err;
+
+	err = regmap_write(anx78xx->map[I2C_IDX_RX_P0], SP_INT_MASK1_REG,
+			   SP_CKDT_CHG | SP_SCDT_CHG);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+static void anx78xx_poweron(struct anx78xx *anx78xx)
+{
+	struct anx78xx_platform_data *pdata = &anx78xx->pdata;
+	int err;
+
+	if (WARN_ON(anx78xx->powered))
+		return;
+
+	if (pdata->dvdd10) {
+		err = regulator_enable(pdata->dvdd10);
+		if (err) {
+			DRM_ERROR("Failed to enable DVDD10 regulator: %d\n",
+				  err);
+			return;
+		}
+
+		usleep_range(1000, 2000);
+	}
+
+	gpiod_set_value_cansleep(pdata->gpiod_reset, 1);
+	usleep_range(1000, 2000);
+
+	gpiod_set_value_cansleep(pdata->gpiod_pd, 0);
+	usleep_range(1000, 2000);
+
+	gpiod_set_value_cansleep(pdata->gpiod_reset, 0);
+
+	/* Power on registers module */
+	anx78xx_set_bits(anx78xx->map[I2C_IDX_TX_P2], SP_POWERDOWN_CTRL_REG,
+			 SP_HDCP_PD | SP_AUDIO_PD | SP_VIDEO_PD | SP_LINK_PD);
+	anx78xx_clear_bits(anx78xx->map[I2C_IDX_TX_P2], SP_POWERDOWN_CTRL_REG,
+			   SP_REGISTER_PD | SP_TOTAL_PD);
+
+	anx78xx->powered = true;
+}
+
+static void anx78xx_poweroff(struct anx78xx *anx78xx)
+{
+	struct anx78xx_platform_data *pdata = &anx78xx->pdata;
+	int err;
+
+	if (WARN_ON(!anx78xx->powered))
+		return;
+
+	gpiod_set_value_cansleep(pdata->gpiod_reset, 1);
+	usleep_range(1000, 2000);
+
+	gpiod_set_value_cansleep(pdata->gpiod_pd, 1);
+	usleep_range(1000, 2000);
+
+	if (pdata->dvdd10) {
+		err = regulator_disable(pdata->dvdd10);
+		if (err) {
+			DRM_ERROR("Failed to disable DVDD10 regulator: %d\n",
+				  err);
+			return;
+		}
+
+		usleep_range(1000, 2000);
+	}
+
+	anx78xx->powered = false;
+}
+
+static int anx78xx_start(struct anx78xx *anx78xx)
+{
+	int err;
+
+	/* Power on all modules */
+	err = anx78xx_clear_bits(anx78xx->map[I2C_IDX_TX_P2],
+				 SP_POWERDOWN_CTRL_REG,
+				 SP_HDCP_PD | SP_AUDIO_PD | SP_VIDEO_PD |
+				 SP_LINK_PD);
+
+	err = anx78xx_enable_interrupts(anx78xx);
+	if (err) {
+		DRM_ERROR("Failed to enable interrupts: %d\n", err);
+		goto err_poweroff;
+	}
+
+	err = anx78xx_rx_initialization(anx78xx);
+	if (err) {
+		DRM_ERROR("Failed receiver initialization: %d\n", err);
+		goto err_poweroff;
+	}
+
+	err = anx78xx_tx_initialization(anx78xx);
+	if (err) {
+		DRM_ERROR("Failed transmitter initialization: %d\n", err);
+		goto err_poweroff;
+	}
+
+	/*
+	 * This delay seems to help keep the hardware in a good state. Without
+	 * it, there are times where it fails silently.
+	 */
+	usleep_range(10000, 15000);
+
+	return 0;
+
+err_poweroff:
+	DRM_ERROR("Failed SlimPort transmitter initialization: %d\n", err);
+	anx78xx_poweroff(anx78xx);
+
+	return err;
+}
+
+static int anx78xx_init_pdata(struct anx78xx *anx78xx)
+{
+	struct anx78xx_platform_data *pdata = &anx78xx->pdata;
+	struct device *dev = &anx78xx->client->dev;
+
+	/* 1.0V digital core power regulator  */
+	pdata->dvdd10 = devm_regulator_get(dev, "dvdd10");
+	if (IS_ERR(pdata->dvdd10)) {
+		DRM_ERROR("DVDD10 regulator not found\n");
+		return PTR_ERR(pdata->dvdd10);
+	}
+
+	/* GPIO for HPD */
+	pdata->gpiod_hpd = devm_gpiod_get(dev, "hpd", GPIOD_IN);
+	if (IS_ERR(pdata->gpiod_hpd))
+		return PTR_ERR(pdata->gpiod_hpd);
+
+	/* GPIO for chip power down */
+	pdata->gpiod_pd = devm_gpiod_get(dev, "pd", GPIOD_OUT_HIGH);
+	if (IS_ERR(pdata->gpiod_pd))
+		return PTR_ERR(pdata->gpiod_pd);
+
+	/* GPIO for chip reset */
+	pdata->gpiod_reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
+
+	return PTR_ERR_OR_ZERO(pdata->gpiod_reset);
+}
+
+static int anx78xx_dp_link_training(struct anx78xx *anx78xx)
+{
+	u8 dp_bw, value;
+	int err;
+
+	err = regmap_write(anx78xx->map[I2C_IDX_RX_P0], SP_HDMI_MUTE_CTRL_REG,
+			   0x0);
+	if (err)
+		return err;
+
+	err = anx78xx_clear_bits(anx78xx->map[I2C_IDX_TX_P2],
+				 SP_POWERDOWN_CTRL_REG,
+				 SP_TOTAL_PD);
+	if (err)
+		return err;
+
+	err = drm_dp_dpcd_readb(&anx78xx->aux, DP_MAX_LINK_RATE, &dp_bw);
+	if (err < 0)
+		return err;
+
+	switch (dp_bw) {
+	case DP_LINK_BW_1_62:
+	case DP_LINK_BW_2_7:
+	case DP_LINK_BW_5_4:
+		break;
+
+	default:
+		DRM_DEBUG_KMS("DP bandwidth (%#02x) not supported\n", dp_bw);
+		return -EINVAL;
+	}
+
+	err = anx78xx_set_bits(anx78xx->map[I2C_IDX_TX_P2], SP_VID_CTRL1_REG,
+			       SP_VIDEO_MUTE);
+	if (err)
+		return err;
+
+	err = anx78xx_clear_bits(anx78xx->map[I2C_IDX_TX_P2],
+				 SP_VID_CTRL1_REG, SP_VIDEO_EN);
+	if (err)
+		return err;
+
+	/* Get DPCD info */
+	err = drm_dp_dpcd_read(&anx78xx->aux, DP_DPCD_REV,
+			       &anx78xx->dpcd, DP_RECEIVER_CAP_SIZE);
+	if (err < 0) {
+		DRM_ERROR("Failed to read DPCD: %d\n", err);
+		return err;
+	}
+
+	/* Clear channel x SERDES power down */
+	err = anx78xx_clear_bits(anx78xx->map[I2C_IDX_TX_P0],
+				 SP_DP_ANALOG_POWER_DOWN_REG, SP_CH0_PD);
+	if (err)
+		return err;
+
+	/* Check link capabilities */
+	err = drm_dp_link_probe(&anx78xx->aux, &anx78xx->link);
+	if (err < 0) {
+		DRM_ERROR("Failed to probe link capabilities: %d\n", err);
+		return err;
+	}
+
+	/* Power up the sink */
+	err = drm_dp_link_power_up(&anx78xx->aux, &anx78xx->link);
+	if (err < 0) {
+		DRM_ERROR("Failed to power up DisplayPort link: %d\n", err);
+		return err;
+	}
+
+	/* Possibly enable downspread on the sink */
+	err = regmap_write(anx78xx->map[I2C_IDX_TX_P0],
+			   SP_DP_DOWNSPREAD_CTRL1_REG, 0);
+	if (err)
+		return err;
+
+	if (anx78xx->dpcd[DP_MAX_DOWNSPREAD] & DP_MAX_DOWNSPREAD_0_5) {
+		DRM_DEBUG("Enable downspread on the sink\n");
+		/* 4000PPM */
+		err = regmap_write(anx78xx->map[I2C_IDX_TX_P0],
+				   SP_DP_DOWNSPREAD_CTRL1_REG, 8);
+		if (err)
+			return err;
+
+		err = drm_dp_dpcd_writeb(&anx78xx->aux, DP_DOWNSPREAD_CTRL,
+					 DP_SPREAD_AMP_0_5);
+		if (err < 0)
+			return err;
+	} else {
+		err = drm_dp_dpcd_writeb(&anx78xx->aux, DP_DOWNSPREAD_CTRL, 0);
+		if (err < 0)
+			return err;
+	}
+
+	/* Set the lane count and the link rate on the sink */
+	if (drm_dp_enhanced_frame_cap(anx78xx->dpcd))
+		err = anx78xx_set_bits(anx78xx->map[I2C_IDX_TX_P0],
+				       SP_DP_SYSTEM_CTRL_BASE + 4,
+				       SP_ENHANCED_MODE);
+	else
+		err = anx78xx_clear_bits(anx78xx->map[I2C_IDX_TX_P0],
+					 SP_DP_SYSTEM_CTRL_BASE + 4,
+					 SP_ENHANCED_MODE);
+	if (err)
+		return err;
+
+	value = drm_dp_link_rate_to_bw_code(anx78xx->link.rate);
+	err = regmap_write(anx78xx->map[I2C_IDX_TX_P0],
+			   SP_DP_MAIN_LINK_BW_SET_REG, value);
+	if (err)
+		return err;
+
+	err = drm_dp_link_configure(&anx78xx->aux, &anx78xx->link);
+	if (err < 0) {
+		DRM_ERROR("Failed to configure DisplayPort link: %d\n", err);
+		return err;
+	}
+
+	/* Start training on the source */
+	err = regmap_write(anx78xx->map[I2C_IDX_TX_P0], SP_DP_LT_CTRL_REG,
+			   SP_LT_EN);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+static int anx78xx_config_dp_output(struct anx78xx *anx78xx)
+{
+	int err;
+
+	err = anx78xx_clear_bits(anx78xx->map[I2C_IDX_TX_P2], SP_VID_CTRL1_REG,
+				 SP_VIDEO_MUTE);
+	if (err)
+		return err;
+
+	/* Enable DP output */
+	err = anx78xx_set_bits(anx78xx->map[I2C_IDX_TX_P2], SP_VID_CTRL1_REG,
+			       SP_VIDEO_EN);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+static int anx78xx_send_video_infoframe(struct anx78xx *anx78xx,
+					struct hdmi_avi_infoframe *frame)
+{
+	u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE];
+	int err;
+
+	err = hdmi_avi_infoframe_pack(frame, buffer, sizeof(buffer));
+	if (err < 0) {
+		DRM_ERROR("Failed to pack AVI infoframe: %d\n", err);
+		return err;
+	}
+
+	err = anx78xx_clear_bits(anx78xx->map[I2C_IDX_TX_P0],
+				 SP_PACKET_SEND_CTRL_REG, SP_AVI_IF_EN);
+	if (err)
+		return err;
+
+	err = regmap_bulk_write(anx78xx->map[I2C_IDX_TX_P2],
+				SP_INFOFRAME_AVI_DB1_REG, buffer,
+				frame->length);
+	if (err)
+		return err;
+
+	err = anx78xx_set_bits(anx78xx->map[I2C_IDX_TX_P0],
+			       SP_PACKET_SEND_CTRL_REG, SP_AVI_IF_UD);
+	if (err)
+		return err;
+
+	err = anx78xx_set_bits(anx78xx->map[I2C_IDX_TX_P0],
+			       SP_PACKET_SEND_CTRL_REG, SP_AVI_IF_EN);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+static int anx78xx_get_downstream_info(struct anx78xx *anx78xx)
+{
+	u8 value;
+	int err;
+
+	err = drm_dp_dpcd_readb(&anx78xx->aux, DP_SINK_COUNT, &value);
+	if (err < 0) {
+		DRM_ERROR("Get sink count failed %d\n", err);
+		return err;
+	}
+
+	if (!DP_GET_SINK_COUNT(value)) {
+		DRM_ERROR("Downstream disconnected\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int anx78xx_get_modes(struct drm_connector *connector)
+{
+	struct anx78xx *anx78xx = connector_to_anx78xx(connector);
+	int err, num_modes = 0;
+
+	if (WARN_ON(!anx78xx->powered))
+		return 0;
+
+	if (anx78xx->edid)
+		return drm_add_edid_modes(connector, anx78xx->edid);
+
+	mutex_lock(&anx78xx->lock);
+
+	err = anx78xx_get_downstream_info(anx78xx);
+	if (err) {
+		DRM_ERROR("Failed to get downstream info: %d\n", err);
+		goto unlock;
+	}
+
+	anx78xx->edid = drm_get_edid(connector, &anx78xx->aux.ddc);
+	if (!anx78xx->edid) {
+		DRM_ERROR("Failed to read EDID\n");
+		goto unlock;
+	}
+
+	err = drm_mode_connector_update_edid_property(connector,
+						      anx78xx->edid);
+	if (err) {
+		DRM_ERROR("Failed to update EDID property: %d\n", err);
+		goto unlock;
+	}
+
+	num_modes = drm_add_edid_modes(connector, anx78xx->edid);
+	/* Store the ELD */
+	drm_edid_to_eld(connector, anx78xx->edid);
+
+unlock:
+	mutex_unlock(&anx78xx->lock);
+
+	return num_modes;
+}
+
+static struct drm_encoder *anx78xx_best_encoder(struct drm_connector *connector)
+{
+	struct anx78xx *anx78xx = connector_to_anx78xx(connector);
+
+	return anx78xx->bridge.encoder;
+}
+
+static const struct drm_connector_helper_funcs anx78xx_connector_helper_funcs = {
+	.get_modes = anx78xx_get_modes,
+	.best_encoder = anx78xx_best_encoder,
+};
+
+static enum drm_connector_status anx78xx_detect(struct drm_connector *connector,
+						bool force)
+{
+	struct anx78xx *anx78xx = connector_to_anx78xx(connector);
+
+	if (!gpiod_get_value(anx78xx->pdata.gpiod_hpd))
+		return connector_status_disconnected;
+
+	return connector_status_connected;
+}
+
+static void anx78xx_connector_destroy(struct drm_connector *connector)
+{
+	drm_connector_cleanup(connector);
+}
+
+static const struct drm_connector_funcs anx78xx_connector_funcs = {
+	.dpms = drm_atomic_helper_connector_dpms,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.detect = anx78xx_detect,
+	.destroy = anx78xx_connector_destroy,
+	.reset = drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static int anx78xx_bridge_attach(struct drm_bridge *bridge)
+{
+	struct anx78xx *anx78xx = bridge_to_anx78xx(bridge);
+	int err;
+
+	if (!bridge->encoder) {
+		DRM_ERROR("Parent encoder object not found");
+		return -ENODEV;
+	}
+
+	/* Register aux channel */
+	anx78xx->aux.name = "DP-AUX";
+	anx78xx->aux.dev = &anx78xx->client->dev;
+	anx78xx->aux.transfer = anx78xx_aux_transfer;
+
+	err = drm_dp_aux_register(&anx78xx->aux);
+	if (err < 0) {
+		DRM_ERROR("Failed to register aux channel: %d\n", err);
+		return err;
+	}
+
+	err = drm_connector_init(bridge->dev, &anx78xx->connector,
+				 &anx78xx_connector_funcs,
+				 DRM_MODE_CONNECTOR_DisplayPort);
+	if (err) {
+		DRM_ERROR("Failed to initialize connector: %d\n", err);
+		return err;
+	}
+
+	drm_connector_helper_add(&anx78xx->connector,
+				 &anx78xx_connector_helper_funcs);
+
+	err = drm_connector_register(&anx78xx->connector);
+	if (err) {
+		DRM_ERROR("Failed to register connector: %d\n", err);
+		return err;
+	}
+
+	anx78xx->connector.polled = DRM_CONNECTOR_POLL_HPD;
+
+	err = drm_mode_connector_attach_encoder(&anx78xx->connector,
+						bridge->encoder);
+	if (err) {
+		DRM_ERROR("Failed to link up connector to encoder: %d\n", err);
+		return err;
+	}
+
+	return 0;
+}
+
+static bool anx78xx_bridge_mode_fixup(struct drm_bridge *bridge,
+				      const struct drm_display_mode *mode,
+				      struct drm_display_mode *adjusted_mode)
+{
+	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+		return false;
+
+	/* Max 1200p at 5.4 Ghz, one lane */
+	if (mode->clock > 154000)
+		return false;
+
+	return true;
+}
+
+static void anx78xx_bridge_disable(struct drm_bridge *bridge)
+{
+	struct anx78xx *anx78xx = bridge_to_anx78xx(bridge);
+
+	/* Power off all modules except configuration registers access */
+	anx78xx_set_bits(anx78xx->map[I2C_IDX_TX_P2], SP_POWERDOWN_CTRL_REG,
+			 SP_HDCP_PD | SP_AUDIO_PD | SP_VIDEO_PD | SP_LINK_PD);
+}
+
+static void anx78xx_bridge_mode_set(struct drm_bridge *bridge,
+				    struct drm_display_mode *mode,
+				    struct drm_display_mode *adjusted_mode)
+{
+	struct anx78xx *anx78xx = bridge_to_anx78xx(bridge);
+	struct hdmi_avi_infoframe frame;
+	int err;
+
+	if (WARN_ON(!anx78xx->powered))
+		return;
+
+	mutex_lock(&anx78xx->lock);
+
+	err = drm_hdmi_avi_infoframe_from_display_mode(&frame, adjusted_mode);
+	if (err) {
+		DRM_ERROR("Failed to setup AVI infoframe: %d\n", err);
+		goto unlock;
+	}
+
+	err = anx78xx_send_video_infoframe(anx78xx, &frame);
+	if (err)
+		DRM_ERROR("Failed to send AVI infoframe: %d\n", err);
+
+unlock:
+	mutex_unlock(&anx78xx->lock);
+}
+
+static void anx78xx_bridge_enable(struct drm_bridge *bridge)
+{
+	struct anx78xx *anx78xx = bridge_to_anx78xx(bridge);
+	int err;
+
+	err = anx78xx_start(anx78xx);
+	if (err) {
+		DRM_ERROR("Failed to initialize: %d\n", err);
+		return;
+	}
+
+	err = anx78xx_set_hpd(anx78xx);
+	if (err)
+		DRM_ERROR("Failed to set HPD: %d\n", err);
+}
+
+static const struct drm_bridge_funcs anx78xx_bridge_funcs = {
+	.attach = anx78xx_bridge_attach,
+	.mode_fixup = anx78xx_bridge_mode_fixup,
+	.disable = anx78xx_bridge_disable,
+	.mode_set = anx78xx_bridge_mode_set,
+	.enable = anx78xx_bridge_enable,
+};
+
+static irqreturn_t anx78xx_hpd_threaded_handler(int irq, void *data)
+{
+	struct anx78xx *anx78xx = data;
+	int err;
+
+	if (anx78xx->powered)
+		return IRQ_HANDLED;
+
+	mutex_lock(&anx78xx->lock);
+
+	/* Cable is pulled, power on the chip */
+	anx78xx_poweron(anx78xx);
+
+	err = anx78xx_enable_interrupts(anx78xx);
+	if (err)
+		DRM_ERROR("Failed to enable interrupts: %d\n", err);
+
+	mutex_unlock(&anx78xx->lock);
+
+	return IRQ_HANDLED;
+}
+
+static int anx78xx_handle_dp_int_1(struct anx78xx *anx78xx, u8 irq)
+{
+	int err;
+
+	DRM_DEBUG_KMS("Handle DP interrupt 1: %02x\n", irq);
+
+	err = regmap_write(anx78xx->map[I2C_IDX_TX_P2], SP_DP_INT_STATUS1_REG,
+			   irq);
+	if (err)
+		return err;
+
+	if (irq & SP_TRAINING_FINISH) {
+		DRM_DEBUG_KMS("IRQ: hardware link training finished\n");
+		err = anx78xx_config_dp_output(anx78xx);
+	}
+
+	return err;
+}
+
+static bool anx78xx_handle_common_int_4(struct anx78xx *anx78xx, u8 irq)
+{
+	bool event = false;
+	int err;
+
+	DRM_DEBUG_KMS("Handle common interrupt 4: %02x\n", irq);
+
+	err = regmap_write(anx78xx->map[I2C_IDX_TX_P2],
+			   SP_COMMON_INT_STATUS4_REG, irq);
+	if (err) {
+		DRM_ERROR("Failed to write SP_COMMON_INT_STATUS4 %d\n", err);
+		return event;
+	}
+
+	if (irq & SP_HPD_LOST) {
+		DRM_DEBUG_KMS("IRQ: Hot plug detect - cable is pulled out\n");
+		event = true;
+		anx78xx_poweroff(anx78xx);
+		/* Free cached EDID */
+		kfree(anx78xx->edid);
+		anx78xx->edid = NULL;
+	} else if (irq & SP_HPD_PLUG) {
+		DRM_DEBUG_KMS("IRQ: Hot plug detect - cable plug\n");
+		event = true;
+	}
+
+	return event;
+}
+
+static void anx78xx_handle_hdmi_int_1(struct anx78xx *anx78xx, u8 irq)
+{
+	unsigned int value;
+	int err;
+
+	DRM_DEBUG_KMS("Handle HDMI interrupt 1: %02x\n", irq);
+
+	err = regmap_write(anx78xx->map[I2C_IDX_RX_P0], SP_INT_STATUS1_REG,
+			   irq);
+	if (err) {
+		DRM_ERROR("Write HDMI int 1 failed: %d\n", err);
+		return;
+	}
+
+	if ((irq & SP_CKDT_CHG) || (irq & SP_SCDT_CHG)) {
+		DRM_DEBUG_KMS("IRQ: HDMI input detected\n");
+
+		err = regmap_read(anx78xx->map[I2C_IDX_RX_P0],
+				  SP_SYSTEM_STATUS_REG, &value);
+		if (err) {
+			DRM_ERROR("Read system status reg failed: %d\n", err);
+			return;
+		}
+
+		if (!(value & SP_TMDS_CLOCK_DET)) {
+			DRM_DEBUG_KMS("IRQ: *** Waiting for HDMI clock ***\n");
+			return;
+		}
+
+		if (!(value & SP_TMDS_DE_DET)) {
+			DRM_DEBUG_KMS("IRQ: *** Waiting for HDMI signal ***\n");
+			return;
+		}
+
+		err = anx78xx_dp_link_training(anx78xx);
+		if (err)
+			DRM_ERROR("Failed to start link training: %d\n", err);
+	}
+}
+
+static irqreturn_t anx78xx_intp_threaded_handler(int unused, void *data)
+{
+	struct anx78xx *anx78xx = data;
+	bool event = false;
+	unsigned int irq;
+	int err;
+
+	mutex_lock(&anx78xx->lock);
+
+	err = regmap_read(anx78xx->map[I2C_IDX_TX_P2], SP_DP_INT_STATUS1_REG,
+			  &irq);
+	if (err) {
+		DRM_ERROR("Failed to read DP interrupt 1 status: %d\n", err);
+		goto unlock;
+	}
+
+	if (irq)
+		anx78xx_handle_dp_int_1(anx78xx, irq);
+
+	err = regmap_read(anx78xx->map[I2C_IDX_TX_P2],
+			  SP_COMMON_INT_STATUS4_REG, &irq);
+	if (err) {
+		DRM_ERROR("Failed to read common interrupt 4 status: %d\n",
+			  err);
+		goto unlock;
+	}
+
+	if (irq)
+		event = anx78xx_handle_common_int_4(anx78xx, irq);
+
+	/* Make sure we are still powered after handle HPD events */
+	if (!anx78xx->powered)
+		goto unlock;
+
+	err = regmap_read(anx78xx->map[I2C_IDX_RX_P0], SP_INT_STATUS1_REG,
+			  &irq);
+	if (err) {
+		DRM_ERROR("Failed to read HDMI int 1 status: %d\n", err);
+		goto unlock;
+	}
+
+	if (irq)
+		anx78xx_handle_hdmi_int_1(anx78xx, irq);
+
+unlock:
+	mutex_unlock(&anx78xx->lock);
+
+	if (event)
+		drm_helper_hpd_irq_event(anx78xx->connector.dev);
+
+	return IRQ_HANDLED;
+}
+
+static void unregister_i2c_dummy_clients(struct anx78xx *anx78xx)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(anx78xx->i2c_dummy); i++)
+		if (anx78xx->i2c_dummy[i])
+			i2c_unregister_device(anx78xx->i2c_dummy[i]);
+}
+
+static const struct regmap_config anx78xx_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+};
+
+static const u16 anx78xx_chipid_list[] = {
+	0x7812,
+	0x7814,
+	0x7818,
+};
+
+static int anx78xx_i2c_probe(struct i2c_client *client,
+			     const struct i2c_device_id *id)
+{
+	struct anx78xx *anx78xx;
+	struct anx78xx_platform_data *pdata;
+	unsigned int i, idl, idh, version;
+	bool found = false;
+	int err;
+
+	anx78xx = devm_kzalloc(&client->dev, sizeof(*anx78xx), GFP_KERNEL);
+	if (!anx78xx)
+		return -ENOMEM;
+
+	pdata = &anx78xx->pdata;
+
+	mutex_init(&anx78xx->lock);
+
+#if IS_ENABLED(CONFIG_OF)
+	anx78xx->bridge.of_node = client->dev.of_node;
+#endif
+
+	anx78xx->client = client;
+	i2c_set_clientdata(client, anx78xx);
+
+	err = anx78xx_init_pdata(anx78xx);
+	if (err) {
+		DRM_ERROR("Failed to initialize pdata: %d\n", err);
+		return err;
+	}
+
+	pdata->hpd_irq = gpiod_to_irq(pdata->gpiod_hpd);
+	if (pdata->hpd_irq < 0) {
+		DRM_ERROR("Failed to get HPD IRQ: %d\n", pdata->hpd_irq);
+		return -ENODEV;
+	}
+
+	pdata->intp_irq = client->irq;
+	if (!pdata->intp_irq) {
+		DRM_ERROR("Failed to get CABLE_DET and INTP IRQ\n");
+		return -ENODEV;
+	}
+
+	/* Map slave addresses of ANX7814 */
+	for (i = 0; i < I2C_NUM_ADDRESSES; i++) {
+		anx78xx->i2c_dummy[i] = i2c_new_dummy(client->adapter,
+						anx78xx_i2c_addresses[i] >> 1);
+		if (!anx78xx->i2c_dummy[i]) {
+			err = -ENOMEM;
+			DRM_ERROR("Failed to reserve I2C bus %02x\n",
+				  anx78xx_i2c_addresses[i]);
+			goto err_unregister_i2c;
+		}
+
+		anx78xx->map[i] = devm_regmap_init_i2c(anx78xx->i2c_dummy[i],
+						       &anx78xx_regmap_config);
+		if (IS_ERR(anx78xx->map[i])) {
+			err = PTR_ERR(anx78xx->map[i]);
+			DRM_ERROR("Failed regmap initialization %02x\n",
+				  anx78xx_i2c_addresses[i]);
+			goto err_unregister_i2c;
+		}
+	}
+
+	/* Look for supported chip ID */
+	anx78xx_poweron(anx78xx);
+
+	err = regmap_read(anx78xx->map[I2C_IDX_TX_P2], SP_DEVICE_IDL_REG,
+			  &idl);
+	if (err)
+		goto err_poweroff;
+
+	err = regmap_read(anx78xx->map[I2C_IDX_TX_P2], SP_DEVICE_IDH_REG,
+			  &idh);
+	if (err)
+		goto err_poweroff;
+
+	anx78xx->chipid = (u8)idl | ((u8)idh << 8);
+
+	err = regmap_read(anx78xx->map[I2C_IDX_TX_P2], SP_DEVICE_VERSION_REG,
+			  &version);
+	if (err)
+		goto err_poweroff;
+
+	for (i = 0; i < ARRAY_SIZE(anx78xx_chipid_list); i++) {
+		if (anx78xx->chipid == anx78xx_chipid_list[i]) {
+			DRM_INFO("Found ANX%x (ver. %d) SlimPort Transmitter\n",
+				 anx78xx->chipid, version);
+			found = true;
+			break;
+		}
+	}
+
+	if (!found) {
+		DRM_ERROR("ANX%x (ver. %d) not supported by this driver\n",
+			  anx78xx->chipid, version);
+		err = -ENODEV;
+		goto err_poweroff;
+	}
+
+	err = devm_request_threaded_irq(&client->dev, pdata->hpd_irq, NULL,
+					anx78xx_hpd_threaded_handler,
+					IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+					"anx78xx-hpd", anx78xx);
+	if (err) {
+		DRM_ERROR("Failed to request CABLE_DET threaded IRQ: %d\n",
+			  err);
+		goto err_poweroff;
+	}
+
+	err = devm_request_threaded_irq(&client->dev, pdata->intp_irq, NULL,
+					anx78xx_intp_threaded_handler,
+					IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+					"anx78xx-intp", anx78xx);
+	if (err) {
+		DRM_ERROR("Failed to request INTP threaded IRQ: %d\n", err);
+		goto err_poweroff;
+	}
+
+	anx78xx->bridge.funcs = &anx78xx_bridge_funcs;
+
+	err = drm_bridge_add(&anx78xx->bridge);
+	if (err < 0) {
+		DRM_ERROR("Failed to add drm bridge: %d\n", err);
+		goto err_poweroff;
+	}
+
+	/* If cable is pulled out, just poweroff and wait for HPD event */
+	if (!gpiod_get_value(anx78xx->pdata.gpiod_hpd))
+		anx78xx_poweroff(anx78xx);
+
+	return 0;
+
+err_poweroff:
+	anx78xx_poweroff(anx78xx);
+
+err_unregister_i2c:
+	unregister_i2c_dummy_clients(anx78xx);
+	return err;
+}
+
+static int anx78xx_i2c_remove(struct i2c_client *client)
+{
+	struct anx78xx *anx78xx = i2c_get_clientdata(client);
+
+	drm_bridge_remove(&anx78xx->bridge);
+
+	unregister_i2c_dummy_clients(anx78xx);
+
+	kfree(anx78xx->edid);
+
+	return 0;
+}
+
+static const struct i2c_device_id anx78xx_id[] = {
+	{ "anx7814", 0 },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(i2c, anx78xx_id);
+
+#if IS_ENABLED(CONFIG_OF)
+static const struct of_device_id anx78xx_match_table[] = {
+	{ .compatible = "analogix,anx7814", },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, anx78xx_match_table);
+#endif
+
+static struct i2c_driver anx78xx_driver = {
+	.driver = {
+		   .name = "anx7814",
+		   .of_match_table = of_match_ptr(anx78xx_match_table),
+		  },
+	.probe = anx78xx_i2c_probe,
+	.remove = anx78xx_i2c_remove,
+	.id_table = anx78xx_id,
+};
+module_i2c_driver(anx78xx_driver);
+
+MODULE_DESCRIPTION("ANX78xx SlimPort Transmitter driver");
+MODULE_AUTHOR("Enric Balletbo i Serra <enric.balletbo@collabora.com>");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/bridge/analogix-anx78xx.h linux-libre-4.7-gnu/drivers/gpu/drm/bridge/analogix-anx78xx.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/bridge/analogix-anx78xx.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/bridge/analogix-anx78xx.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,719 @@
+/*
+ * Copyright(c) 2016, Analogix Semiconductor. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 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.
+ *
+ */
+
+#ifndef __ANX78xx_H
+#define __ANX78xx_H
+
+#define TX_P0				0x70
+#define TX_P1				0x7a
+#define TX_P2				0x72
+
+#define RX_P0				0x7e
+#define RX_P1				0x80
+
+/***************************************************************/
+/* Register definition of device address 0x7e                  */
+/***************************************************************/
+
+/*
+ * System Control and Status
+ */
+
+/* Software Reset Register 1 */
+#define SP_SOFTWARE_RESET1_REG		0x11
+#define SP_VIDEO_RST			BIT(4)
+#define SP_HDCP_MAN_RST			BIT(2)
+#define SP_TMDS_RST			BIT(1)
+#define SP_SW_MAN_RST			BIT(0)
+
+/* System Status Register */
+#define SP_SYSTEM_STATUS_REG		0x14
+#define SP_TMDS_CLOCK_DET		BIT(1)
+#define SP_TMDS_DE_DET			BIT(0)
+
+/* HDMI Status Register */
+#define SP_HDMI_STATUS_REG		0x15
+#define SP_HDMI_AUD_LAYOUT		BIT(3)
+#define SP_HDMI_DET			BIT(0)
+#  define SP_DVI_MODE			0
+#  define SP_HDMI_MODE			1
+
+/* HDMI Mute Control Register */
+#define SP_HDMI_MUTE_CTRL_REG		0x16
+#define SP_AUD_MUTE			BIT(1)
+#define SP_VID_MUTE			BIT(0)
+
+/* System Power Down Register 1 */
+#define SP_SYSTEM_POWER_DOWN1_REG	0x18
+#define SP_PWDN_CTRL			BIT(0)
+
+/*
+ * Audio and Video Auto Control
+ */
+
+/* Auto Audio and Video Control register */
+#define SP_AUDVID_CTRL_REG		0x20
+#define SP_AVC_OE			BIT(7)
+#define SP_AAC_OE			BIT(6)
+#define SP_AVC_EN			BIT(1)
+#define SP_AAC_EN			BIT(0)
+
+/* Audio Exception Enable Registers */
+#define SP_AUD_EXCEPTION_ENABLE_BASE	(0x24 - 1)
+/* Bits for Audio Exception Enable Register 3 */
+#define SP_AEC_EN21			BIT(5)
+
+/*
+ * Interrupt
+ */
+
+/* Interrupt Status Register 1 */
+#define SP_INT_STATUS1_REG		0x31
+/* Bits for Interrupt Status Register 1 */
+#define SP_HDMI_DVI			BIT(7)
+#define SP_CKDT_CHG			BIT(6)
+#define SP_SCDT_CHG			BIT(5)
+#define SP_PCLK_CHG			BIT(4)
+#define SP_PLL_UNLOCK			BIT(3)
+#define SP_CABLE_PLUG_CHG		BIT(2)
+#define SP_SET_MUTE			BIT(1)
+#define SP_SW_INTR			BIT(0)
+/* Bits for Interrupt Status Register 2 */
+#define SP_HDCP_ERR			BIT(5)
+#define SP_AUDIO_SAMPLE_CHG		BIT(0)	/* undocumented */
+/* Bits for Interrupt Status Register 3 */
+#define SP_AUD_MODE_CHG			BIT(0)
+/* Bits for Interrupt Status Register 5 */
+#define SP_AUDIO_RCV			BIT(0)
+/* Bits for Interrupt Status Register 6 */
+#define SP_INT_STATUS6_REG		0x36
+#define SP_CTS_RCV			BIT(7)
+#define SP_NEW_AUD_PKT			BIT(4)
+#define SP_NEW_AVI_PKT			BIT(1)
+#define SP_NEW_CP_PKT			BIT(0)
+/* Bits for Interrupt Status Register 7 */
+#define SP_NO_VSI			BIT(7)
+#define SP_NEW_VS			BIT(4)
+
+/* Interrupt Mask 1 Status Registers */
+#define SP_INT_MASK1_REG		0x41
+
+/* HDMI US TIMER Control Register */
+#define SP_HDMI_US_TIMER_CTRL_REG	0x49
+#define SP_MS_TIMER_MARGIN_10_8_MASK	0x07
+
+/*
+ * TMDS Control
+ */
+
+/* TMDS Control Registers */
+#define SP_TMDS_CTRL_BASE		(0x50 - 1)
+/* Bits for TMDS Control Register 7 */
+#define SP_PD_RT			BIT(0)
+
+/*
+ * Video Control
+ */
+
+/* Video Status Register */
+#define SP_VIDEO_STATUS_REG		0x70
+#define SP_COLOR_DEPTH_MASK		0xf0
+#define SP_COLOR_DEPTH_SHIFT		4
+#  define SP_COLOR_DEPTH_MODE_LEGACY	0x00
+#  define SP_COLOR_DEPTH_MODE_24BIT	0x04
+#  define SP_COLOR_DEPTH_MODE_30BIT	0x05
+#  define SP_COLOR_DEPTH_MODE_36BIT	0x06
+#  define SP_COLOR_DEPTH_MODE_48BIT	0x07
+
+/* Video Data Range Control Register */
+#define SP_VID_DATA_RANGE_CTRL_REG	0x83
+#define SP_R2Y_INPUT_LIMIT		BIT(1)
+
+/* Pixel Clock High Resolution Counter Registers */
+#define SP_PCLK_HIGHRES_CNT_BASE	(0x8c - 1)
+
+/*
+ * Audio Control
+ */
+
+/* Number of Audio Channels Status Registers */
+#define SP_AUD_CH_STATUS_REG_NUM	6
+
+/* Audio IN S/PDIF Channel Status Registers */
+#define SP_AUD_SPDIF_CH_STATUS_BASE	0xc7
+
+/* Audio IN S/PDIF Channel Status Register 4 */
+#define SP_FS_FREQ_MASK			0x0f
+#  define SP_FS_FREQ_44100HZ		0x00
+#  define SP_FS_FREQ_48000HZ		0x02
+#  define SP_FS_FREQ_32000HZ		0x03
+#  define SP_FS_FREQ_88200HZ		0x08
+#  define SP_FS_FREQ_96000HZ		0x0a
+#  define SP_FS_FREQ_176400HZ		0x0c
+#  define SP_FS_FREQ_192000HZ		0x0e
+
+/*
+ * Micellaneous Control Block
+ */
+
+/* CHIP Control Register */
+#define SP_CHIP_CTRL_REG		0xe3
+#define SP_MAN_HDMI5V_DET		BIT(3)
+#define SP_PLLLOCK_CKDT_EN		BIT(2)
+#define SP_ANALOG_CKDT_EN		BIT(1)
+#define SP_DIGITAL_CKDT_EN		BIT(0)
+
+/* Packet Receiving Status Register */
+#define SP_PACKET_RECEIVING_STATUS_REG	0xf3
+#define SP_AVI_RCVD			BIT(5)
+#define SP_VSI_RCVD			BIT(1)
+
+/***************************************************************/
+/* Register definition of device address 0x80                  */
+/***************************************************************/
+
+/* HDCP BCAPS Shadow Register */
+#define SP_HDCP_BCAPS_SHADOW_REG	0x2a
+#define SP_BCAPS_REPEATER		BIT(5)
+
+/* HDCP Status Register */
+#define SP_RX_HDCP_STATUS_REG		0x3f
+#define SP_AUTH_EN			BIT(4)
+
+/*
+ * InfoFrame and Control Packet Registers
+ */
+
+/* AVI InfoFrame packet checksum */
+#define SP_AVI_INFOFRAME_CHECKSUM	0xa3
+
+/* AVI InfoFrame Registers */
+#define SP_AVI_INFOFRAME_DATA_BASE	0xa4
+
+#define SP_AVI_COLOR_F_MASK		0x60
+#define SP_AVI_COLOR_F_SHIFT		5
+
+/* Audio InfoFrame Registers */
+#define SP_AUD_INFOFRAME_DATA_BASE	0xc4
+#define SP_AUD_INFOFRAME_LAYOUT_MASK	0x0f
+
+/* MPEG/HDMI Vendor Specific InfoFrame Packet type code */
+#define SP_MPEG_VS_INFOFRAME_TYPE_REG	0xe0
+
+/* MPEG/HDMI Vendor Specific InfoFrame Packet length */
+#define SP_MPEG_VS_INFOFRAME_LEN_REG	0xe2
+
+/* MPEG/HDMI Vendor Specific InfoFrame Packet version number */
+#define SP_MPEG_VS_INFOFRAME_VER_REG	0xe1
+
+/* MPEG/HDMI Vendor Specific InfoFrame Packet content */
+#define SP_MPEG_VS_INFOFRAME_DATA_BASE	0xe4
+
+/* General Control Packet Register */
+#define SP_GENERAL_CTRL_PACKET_REG	0x9f
+#define SP_CLEAR_AVMUTE			BIT(4)
+#define SP_SET_AVMUTE			BIT(0)
+
+/***************************************************************/
+/* Register definition of device address 0x70                  */
+/***************************************************************/
+
+/* HDCP Status Register */
+#define SP_TX_HDCP_STATUS_REG		0x00
+#define SP_AUTH_FAIL			BIT(5)
+#define SP_AUTHEN_PASS			BIT(1)
+
+/* HDCP Control Register 0 */
+#define SP_HDCP_CTRL0_REG		0x01
+#define SP_RX_REPEATER			BIT(6)
+#define SP_RE_AUTH			BIT(5)
+#define SP_SW_AUTH_OK			BIT(4)
+#define SP_HARD_AUTH_EN			BIT(3)
+#define SP_HDCP_ENC_EN			BIT(2)
+#define SP_BKSV_SRM_PASS		BIT(1)
+#define SP_KSVLIST_VLD			BIT(0)
+/* HDCP Function Enabled */
+#define SP_HDCP_FUNCTION_ENABLED	(BIT(0) | BIT(1) | BIT(2) | BIT(3))
+
+/* HDCP Receiver BSTATUS Register 0 */
+#define	SP_HDCP_RX_BSTATUS0_REG		0x1b
+/* HDCP Receiver BSTATUS Register 1 */
+#define	SP_HDCP_RX_BSTATUS1_REG		0x1c
+
+/* HDCP Embedded "Blue Screen" Content Registers */
+#define SP_HDCP_VID0_BLUE_SCREEN_REG	0x2c
+#define SP_HDCP_VID1_BLUE_SCREEN_REG	0x2d
+#define SP_HDCP_VID2_BLUE_SCREEN_REG	0x2e
+
+/* HDCP Wait R0 Timing Register */
+#define SP_HDCP_WAIT_R0_TIME_REG	0x40
+
+/* HDCP Link Integrity Check Timer Register */
+#define SP_HDCP_LINK_CHECK_TIMER_REG	0x41
+
+/* HDCP Repeater Ready Wait Timer Register */
+#define SP_HDCP_RPTR_RDY_WAIT_TIME_REG	0x42
+
+/* HDCP Auto Timer Register */
+#define SP_HDCP_AUTO_TIMER_REG		0x51
+
+/* HDCP Key Status Register */
+#define SP_HDCP_KEY_STATUS_REG		0x5e
+
+/* HDCP Key Command Register */
+#define SP_HDCP_KEY_COMMAND_REG		0x5f
+#define SP_DISABLE_SYNC_HDCP		BIT(2)
+
+/* OTP Memory Key Protection Registers */
+#define SP_OTP_KEY_PROTECT1_REG		0x60
+#define SP_OTP_KEY_PROTECT2_REG		0x61
+#define SP_OTP_KEY_PROTECT3_REG		0x62
+#define SP_OTP_PSW1			0xa2
+#define SP_OTP_PSW2			0x7e
+#define SP_OTP_PSW3			0xc6
+
+/* DP System Control Registers */
+#define SP_DP_SYSTEM_CTRL_BASE		(0x80 - 1)
+/* Bits for DP System Control Register 2 */
+#define SP_CHA_STA			BIT(2)
+/* Bits for DP System Control Register 3 */
+#define SP_HPD_STATUS			BIT(6)
+#define SP_STRM_VALID			BIT(2)
+/* Bits for DP System Control Register 4 */
+#define SP_ENHANCED_MODE		BIT(3)
+
+/* DP Video Control Register */
+#define SP_DP_VIDEO_CTRL_REG		0x84
+#define SP_COLOR_F_MASK			0x06
+#define SP_COLOR_F_SHIFT		1
+#define SP_BPC_MASK			0xe0
+#define SP_BPC_SHIFT			5
+#  define SP_BPC_6BITS			0x00
+#  define SP_BPC_8BITS			0x01
+#  define SP_BPC_10BITS			0x02
+#  define SP_BPC_12BITS			0x03
+
+/* DP Audio Control Register */
+#define SP_DP_AUDIO_CTRL_REG		0x87
+#define SP_AUD_EN			BIT(0)
+
+/* 10us Pulse Generate Timer Registers */
+#define SP_I2C_GEN_10US_TIMER0_REG	0x88
+#define SP_I2C_GEN_10US_TIMER1_REG	0x89
+
+/* Packet Send Control Register */
+#define SP_PACKET_SEND_CTRL_REG		0x90
+#define SP_AUD_IF_UP			BIT(7)
+#define SP_AVI_IF_UD			BIT(6)
+#define SP_MPEG_IF_UD			BIT(5)
+#define SP_SPD_IF_UD			BIT(4)
+#define SP_AUD_IF_EN			BIT(3)
+#define SP_AVI_IF_EN			BIT(2)
+#define SP_MPEG_IF_EN			BIT(1)
+#define SP_SPD_IF_EN			BIT(0)
+
+/* DP HDCP Control Register */
+#define SP_DP_HDCP_CTRL_REG		0x92
+#define SP_AUTO_EN			BIT(7)
+#define SP_AUTO_START			BIT(5)
+#define SP_LINK_POLLING			BIT(1)
+
+/* DP Main Link Bandwidth Setting Register */
+#define SP_DP_MAIN_LINK_BW_SET_REG	0xa0
+#define SP_LINK_BW_SET_MASK		0x1f
+#define SP_INITIAL_SLIM_M_AUD_SEL	BIT(5)
+
+/* DP Training Pattern Set Register */
+#define SP_DP_TRAINING_PATTERN_SET_REG	0xa2
+
+/* DP Lane 0 Link Training Control Register */
+#define SP_DP_LANE0_LT_CTRL_REG		0xa3
+#define SP_TX_SW_SET_MASK		0x1b
+#define SP_MAX_PRE_REACH		BIT(5)
+#define SP_MAX_DRIVE_REACH		BIT(4)
+#define SP_PRE_EMP_LEVEL1		BIT(3)
+#define SP_DRVIE_CURRENT_LEVEL1		BIT(0)
+
+/* DP Link Training Control Register */
+#define SP_DP_LT_CTRL_REG		0xa8
+#define SP_LT_ERROR_TYPE_MASK		0x70
+#  define SP_LT_NO_ERROR		0x00
+#  define SP_LT_AUX_WRITE_ERROR		0x01
+#  define SP_LT_MAX_DRIVE_REACHED	0x02
+#  define SP_LT_WRONG_LANE_COUNT_SET	0x03
+#  define SP_LT_LOOP_SAME_5_TIME	0x04
+#  define SP_LT_CR_FAIL_IN_EQ		0x05
+#  define SP_LT_EQ_LOOP_5_TIME		0x06
+#define SP_LT_EN			BIT(0)
+
+/* DP CEP Training Control Registers */
+#define SP_DP_CEP_TRAINING_CTRL0_REG	0xa9
+#define SP_DP_CEP_TRAINING_CTRL1_REG	0xaa
+
+/* DP Debug Register 1 */
+#define SP_DP_DEBUG1_REG		0xb0
+#define SP_DEBUG_PLL_LOCK		BIT(4)
+#define SP_POLLING_EN			BIT(1)
+
+/* DP Polling Control Register */
+#define SP_DP_POLLING_CTRL_REG		0xb4
+#define SP_AUTO_POLLING_DISABLE		BIT(0)
+
+/* DP Link Debug Control Register */
+#define SP_DP_LINK_DEBUG_CTRL_REG	0xb8
+#define SP_M_VID_DEBUG			BIT(5)
+#define SP_NEW_PRBS7			BIT(4)
+#define SP_INSERT_ER			BIT(1)
+#define SP_PRBS31_EN			BIT(0)
+
+/* AUX Misc control Register */
+#define SP_AUX_MISC_CTRL_REG		0xbf
+
+/* DP PLL control Register */
+#define SP_DP_PLL_CTRL_REG		0xc7
+#define SP_PLL_RST			BIT(6)
+
+/* DP Analog Power Down Register */
+#define SP_DP_ANALOG_POWER_DOWN_REG	0xc8
+#define SP_CH0_PD			BIT(0)
+
+/* DP Misc Control Register */
+#define SP_DP_MISC_CTRL_REG		0xcd
+#define SP_EQ_TRAINING_LOOP		BIT(6)
+
+/* DP Extra I2C Device Address Register */
+#define SP_DP_EXTRA_I2C_DEV_ADDR_REG	0xce
+#define SP_I2C_STRETCH_DISABLE		BIT(7)
+
+#define SP_I2C_EXTRA_ADDR		0x50
+
+/* DP Downspread Control Register 1 */
+#define SP_DP_DOWNSPREAD_CTRL1_REG	0xd0
+
+/* DP M Value Calculation Control Register */
+#define SP_DP_M_CALCULATION_CTRL_REG	0xd9
+#define SP_M_GEN_CLK_SEL		BIT(0)
+
+/* AUX Channel Access Status Register */
+#define SP_AUX_CH_STATUS_REG		0xe0
+#define SP_AUX_STATUS			0x0f
+
+/* AUX Channel DEFER Control Register */
+#define SP_AUX_DEFER_CTRL_REG		0xe2
+#define SP_DEFER_CTRL_EN		BIT(7)
+
+/* DP Buffer Data Count Register */
+#define SP_BUF_DATA_COUNT_REG		0xe4
+#define SP_BUF_DATA_COUNT_MASK		0x1f
+#define SP_BUF_CLR			BIT(7)
+
+/* DP AUX Channel Control Register 1 */
+#define SP_DP_AUX_CH_CTRL1_REG		0xe5
+#define SP_AUX_TX_COMM_MASK		0x0f
+#define SP_AUX_LENGTH_MASK		0xf0
+#define SP_AUX_LENGTH_SHIFT		4
+
+/* DP AUX CH Address Register 0 */
+#define SP_AUX_ADDR_7_0_REG		0xe6
+
+/* DP AUX CH Address Register 1 */
+#define SP_AUX_ADDR_15_8_REG		0xe7
+
+/* DP AUX CH Address Register 2 */
+#define SP_AUX_ADDR_19_16_REG		0xe8
+#define SP_AUX_ADDR_19_16_MASK		0x0f
+
+/* DP AUX Channel Control Register 2 */
+#define SP_DP_AUX_CH_CTRL2_REG		0xe9
+#define SP_AUX_SEL_RXCM			BIT(6)
+#define SP_AUX_CHSEL			BIT(3)
+#define SP_AUX_PN_INV			BIT(2)
+#define SP_ADDR_ONLY			BIT(1)
+#define SP_AUX_EN			BIT(0)
+
+/* DP Video Stream Control InfoFrame Register */
+#define SP_DP_3D_VSC_CTRL_REG		0xea
+#define SP_INFO_FRAME_VSC_EN		BIT(0)
+
+/* DP Video Stream Data Byte 1 Register */
+#define SP_DP_VSC_DB1_REG		0xeb
+
+/* DP AUX Channel Control Register 3 */
+#define SP_DP_AUX_CH_CTRL3_REG		0xec
+#define SP_WAIT_COUNTER_7_0_MASK	0xff
+
+/* DP AUX Channel Control Register 4 */
+#define SP_DP_AUX_CH_CTRL4_REG		0xed
+
+/* DP AUX Buffer Data Registers */
+#define SP_DP_BUF_DATA0_REG		0xf0
+
+/***************************************************************/
+/* Register definition of device address 0x72                  */
+/***************************************************************/
+
+/*
+ * Core Register Definitions
+ */
+
+/* Device ID Low Byte Register */
+#define SP_DEVICE_IDL_REG		0x02
+
+/* Device ID High Byte Register */
+#define SP_DEVICE_IDH_REG		0x03
+
+/* Device version register */
+#define SP_DEVICE_VERSION_REG		0x04
+
+/* Power Down Control Register */
+#define SP_POWERDOWN_CTRL_REG		0x05
+#define SP_REGISTER_PD			BIT(7)
+#define SP_HDCP_PD			BIT(5)
+#define SP_AUDIO_PD			BIT(4)
+#define SP_VIDEO_PD			BIT(3)
+#define SP_LINK_PD			BIT(2)
+#define SP_TOTAL_PD			BIT(1)
+
+/* Reset Control Register 1 */
+#define SP_RESET_CTRL1_REG		0x06
+#define SP_MISC_RST			BIT(7)
+#define SP_VIDCAP_RST			BIT(6)
+#define SP_VIDFIF_RST			BIT(5)
+#define SP_AUDFIF_RST			BIT(4)
+#define SP_AUDCAP_RST			BIT(3)
+#define SP_HDCP_RST			BIT(2)
+#define SP_SW_RST			BIT(1)
+#define SP_HW_RST			BIT(0)
+
+/* Reset Control Register 2 */
+#define SP_RESET_CTRL2_REG		0x07
+#define SP_AUX_RST			BIT(2)
+#define SP_SERDES_FIFO_RST		BIT(1)
+#define SP_I2C_REG_RST			BIT(0)
+
+/* Video Control Register 1 */
+#define SP_VID_CTRL1_REG		0x08
+#define SP_VIDEO_EN			BIT(7)
+#define SP_VIDEO_MUTE			BIT(2)
+#define SP_DE_GEN			BIT(1)
+#define SP_DEMUX			BIT(0)
+
+/* Video Control Register 2 */
+#define SP_VID_CTRL2_REG		0x09
+#define SP_IN_COLOR_F_MASK		0x03
+#define SP_IN_YC_BIT_SEL		BIT(2)
+#define SP_IN_BPC_MASK			0x70
+#define SP_IN_BPC_SHIFT			4
+#  define SP_IN_BPC_12BIT		0x03
+#  define SP_IN_BPC_10BIT		0x02
+#  define SP_IN_BPC_8BIT		0x01
+#  define SP_IN_BPC_6BIT		0x00
+#define SP_IN_D_RANGE			BIT(7)
+
+/* Video Control Register 3 */
+#define SP_VID_CTRL3_REG		0x0a
+#define SP_HPD_OUT			BIT(6)
+
+/* Video Control Register 5 */
+#define SP_VID_CTRL5_REG		0x0c
+#define SP_CSC_STD_SEL			BIT(7)
+#define SP_XVYCC_RNG_LMT		BIT(6)
+#define SP_RANGE_Y2R			BIT(5)
+#define SP_CSPACE_Y2R			BIT(4)
+#define SP_RGB_RNG_LMT			BIT(3)
+#define SP_Y_RNG_LMT			BIT(2)
+#define SP_RANGE_R2Y			BIT(1)
+#define SP_CSPACE_R2Y			BIT(0)
+
+/* Video Control Register 6 */
+#define SP_VID_CTRL6_REG		0x0d
+#define SP_TEST_PATTERN_EN		BIT(7)
+#define SP_VIDEO_PROCESS_EN		BIT(6)
+#define SP_VID_US_MODE			BIT(3)
+#define SP_VID_DS_MODE			BIT(2)
+#define SP_UP_SAMPLE			BIT(1)
+#define SP_DOWN_SAMPLE			BIT(0)
+
+/* Video Control Register 8 */
+#define SP_VID_CTRL8_REG		0x0f
+#define SP_VID_VRES_TH			BIT(0)
+
+/* Total Line Status Low Byte Register */
+#define SP_TOTAL_LINE_STAL_REG		0x24
+
+/* Total Line Status High Byte Register */
+#define SP_TOTAL_LINE_STAH_REG		0x25
+
+/* Active Line Status Low Byte Register */
+#define SP_ACT_LINE_STAL_REG		0x26
+
+/* Active Line Status High Byte Register */
+#define SP_ACT_LINE_STAH_REG		0x27
+
+/* Vertical Front Porch Status Register */
+#define SP_V_F_PORCH_STA_REG		0x28
+
+/* Vertical SYNC Width Status Register */
+#define SP_V_SYNC_STA_REG		0x29
+
+/* Vertical Back Porch Status Register */
+#define SP_V_B_PORCH_STA_REG		0x2a
+
+/* Total Pixel Status Low Byte Register */
+#define SP_TOTAL_PIXEL_STAL_REG		0x2b
+
+/* Total Pixel Status High Byte Register */
+#define SP_TOTAL_PIXEL_STAH_REG		0x2c
+
+/* Active Pixel Status Low Byte Register */
+#define SP_ACT_PIXEL_STAL_REG		0x2d
+
+/* Active Pixel Status High Byte Register */
+#define SP_ACT_PIXEL_STAH_REG		0x2e
+
+/* Horizontal Front Porch Status Low Byte Register */
+#define SP_H_F_PORCH_STAL_REG		0x2f
+
+/* Horizontal Front Porch Statys High Byte Register */
+#define SP_H_F_PORCH_STAH_REG		0x30
+
+/* Horizontal SYNC Width Status Low Byte Register */
+#define SP_H_SYNC_STAL_REG		0x31
+
+/* Horizontal SYNC Width Status High Byte Register */
+#define SP_H_SYNC_STAH_REG		0x32
+
+/* Horizontal Back Porch Status Low Byte Register */
+#define SP_H_B_PORCH_STAL_REG		0x33
+
+/* Horizontal Back Porch Status High Byte Register */
+#define SP_H_B_PORCH_STAH_REG		0x34
+
+/* InfoFrame AVI Packet DB1 Register */
+#define SP_INFOFRAME_AVI_DB1_REG	0x70
+
+/* Bit Control Specific Register */
+#define SP_BIT_CTRL_SPECIFIC_REG	0x80
+#define SP_BIT_CTRL_SELECT_SHIFT	1
+#define SP_ENABLE_BIT_CTRL		BIT(0)
+
+/* InfoFrame Audio Packet DB1 Register */
+#define SP_INFOFRAME_AUD_DB1_REG	0x83
+
+/* InfoFrame MPEG Packet DB1 Register */
+#define SP_INFOFRAME_MPEG_DB1_REG	0xb0
+
+/* Audio Channel Status Registers */
+#define SP_AUD_CH_STATUS_BASE		0xd0
+
+/* Audio Channel Num Register 5 */
+#define SP_I2S_CHANNEL_NUM_MASK		0xe0
+#  define SP_I2S_CH_NUM_1		(0x00 << 5)
+#  define SP_I2S_CH_NUM_2		(0x01 << 5)
+#  define SP_I2S_CH_NUM_3		(0x02 << 5)
+#  define SP_I2S_CH_NUM_4		(0x03 << 5)
+#  define SP_I2S_CH_NUM_5		(0x04 << 5)
+#  define SP_I2S_CH_NUM_6		(0x05 << 5)
+#  define SP_I2S_CH_NUM_7		(0x06 << 5)
+#  define SP_I2S_CH_NUM_8		(0x07 << 5)
+#define SP_EXT_VUCP			BIT(2)
+#define SP_VBIT				BIT(1)
+#define SP_AUDIO_LAYOUT			BIT(0)
+
+/* Analog Debug Register 2 */
+#define SP_ANALOG_DEBUG2_REG		0xdd
+#define SP_FORCE_SW_OFF_BYPASS		0x20
+#define SP_XTAL_FRQ			0x1c
+#  define SP_XTAL_FRQ_19M2		(0x00 << 2)
+#  define SP_XTAL_FRQ_24M		(0x01 << 2)
+#  define SP_XTAL_FRQ_25M		(0x02 << 2)
+#  define SP_XTAL_FRQ_26M		(0x03 << 2)
+#  define SP_XTAL_FRQ_27M		(0x04 << 2)
+#  define SP_XTAL_FRQ_38M4		(0x05 << 2)
+#  define SP_XTAL_FRQ_52M		(0x06 << 2)
+#define SP_POWERON_TIME_1P5MS		0x03
+
+/* Analog Control 0 Register */
+#define SP_ANALOG_CTRL0_REG		0xe1
+
+/* Common Interrupt Status Register 1 */
+#define SP_COMMON_INT_STATUS_BASE	(0xf1 - 1)
+#define SP_PLL_LOCK_CHG			0x40
+
+/* Common Interrupt Status Register 2 */
+#define SP_COMMON_INT_STATUS2		0xf2
+#define SP_HDCP_AUTH_CHG		BIT(1)
+#define SP_HDCP_AUTH_DONE		BIT(0)
+
+#define SP_HDCP_LINK_CHECK_FAIL		BIT(0)
+
+/* Common Interrupt Status Register 4 */
+#define SP_COMMON_INT_STATUS4_REG	0xf4
+#define SP_HPD_IRQ			BIT(6)
+#define SP_HPD_ESYNC_ERR		BIT(4)
+#define SP_HPD_CHG			BIT(2)
+#define SP_HPD_LOST			BIT(1)
+#define SP_HPD_PLUG			BIT(0)
+
+/* DP Interrupt Status Register */
+#define SP_DP_INT_STATUS1_REG		0xf7
+#define SP_TRAINING_FINISH		BIT(5)
+#define SP_POLLING_ERR			BIT(4)
+
+/* Common Interrupt Mask Register */
+#define SP_COMMON_INT_MASK_BASE		(0xf8 - 1)
+
+#define SP_COMMON_INT_MASK4_REG		0xfb
+
+/* DP Interrupts Mask Register */
+#define SP_DP_INT_MASK1_REG		0xfe
+
+/* Interrupt Control Register */
+#define SP_INT_CTRL_REG			0xff
+
+/***************************************************************/
+/* Register definition of device address 0x7a                  */
+/***************************************************************/
+
+/* DP TX Link Training Control Register */
+#define SP_DP_TX_LT_CTRL0_REG		0x30
+
+/* PD 1.2 Lint Training 80bit Pattern Register */
+#define SP_DP_LT_80BIT_PATTERN0_REG	0x80
+#define SP_DP_LT_80BIT_PATTERN_REG_NUM	10
+
+/* Audio Interface Control Register 0 */
+#define SP_AUD_INTERFACE_CTRL0_REG	0x5f
+#define SP_AUD_INTERFACE_DISABLE	0x80
+
+/* Audio Interface Control Register 2 */
+#define SP_AUD_INTERFACE_CTRL2_REG	0x60
+#define SP_M_AUD_ADJUST_ST		0x04
+
+/* Audio Interface Control Register 3 */
+#define SP_AUD_INTERFACE_CTRL3_REG	0x62
+
+/* Audio Interface Control Register 4 */
+#define SP_AUD_INTERFACE_CTRL4_REG	0x67
+
+/* Audio Interface Control Register 5 */
+#define SP_AUD_INTERFACE_CTRL5_REG	0x68
+
+/* Audio Interface Control Register 6 */
+#define SP_AUD_INTERFACE_CTRL6_REG	0x69
+
+/* Firmware Version Register */
+#define SP_FW_VER_REG			0xb7
+
+#endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/bridge/dw-hdmi.c linux-libre-4.7-gnu/drivers/gpu/drm/bridge/dw-hdmi.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/bridge/dw-hdmi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/bridge/dw-hdmi.c	2016-07-24 15:23:50.000000000 -0400
@@ -1413,11 +1413,6 @@ static void dw_hdmi_bridge_enable(struct
 	mutex_unlock(&hdmi->mutex);
 }
 
-static void dw_hdmi_bridge_nop(struct drm_bridge *bridge)
-{
-	/* do nothing */
-}
-
 static enum drm_connector_status
 dw_hdmi_connector_detect(struct drm_connector *connector, bool force)
 {
@@ -1536,8 +1531,6 @@ static const struct drm_connector_helper
 static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = {
 	.enable = dw_hdmi_bridge_enable,
 	.disable = dw_hdmi_bridge_disable,
-	.pre_enable = dw_hdmi_bridge_nop,
-	.post_disable = dw_hdmi_bridge_nop,
 	.mode_set = dw_hdmi_bridge_mode_set,
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/bridge/Kconfig linux-libre-4.7-gnu/drivers/gpu/drm/bridge/Kconfig
--- linux-libre-4.6-gnu/drivers/gpu/drm/bridge/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/bridge/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -7,6 +7,16 @@ config DRM_BRIDGE
 menu "Display Interface Bridges"
 	depends on DRM && DRM_BRIDGE
 
+config DRM_ANALOGIX_ANX78XX
+	tristate "Analogix ANX78XX bridge"
+	select DRM_KMS_HELPER
+	select REGMAP_I2C
+	---help---
+	  ANX78XX is an ultra-low Full-HD SlimPort transmitter
+	  designed for portable devices. The ANX78XX transforms
+	  the HDMI output of an application processor to MyDP
+	  or DisplayPort.
+
 config DRM_DW_HDMI
 	tristate
 	select DRM_KMS_HELPER
@@ -40,4 +50,6 @@ config DRM_PARADE_PS8622
 	---help---
 	  Parade eDP-LVDS bridge chip driver.
 
+source "drivers/gpu/drm/bridge/analogix/Kconfig"
+
 endmenu
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/bridge/Makefile linux-libre-4.7-gnu/drivers/gpu/drm/bridge/Makefile
--- linux-libre-4.6-gnu/drivers/gpu/drm/bridge/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/bridge/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -1,6 +1,8 @@
 ccflags-y := -Iinclude/drm
 
+obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += analogix-anx78xx.o
 obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o
 obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
 obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
 obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o
+obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix/
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/cirrus/cirrus_drv.c linux-libre-4.7-gnu/drivers/gpu/drm/cirrus/cirrus_drv.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/cirrus/cirrus_drv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/cirrus/cirrus_drv.c	2016-07-24 15:23:50.000000000 -0400
@@ -163,10 +163,8 @@ static struct pci_driver cirrus_pci_driv
 
 static int __init cirrus_init(void)
 {
-#ifdef CONFIG_VGA_CONSOLE
 	if (vgacon_text_force() && cirrus_modeset == -1)
 		return -EINVAL;
-#endif
 
 	if (cirrus_modeset == 0)
 		return -EINVAL;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/cirrus/cirrus_drv.h linux-libre-4.7-gnu/drivers/gpu/drm/cirrus/cirrus_drv.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/cirrus/cirrus_drv.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/cirrus/cirrus_drv.h	2016-07-24 15:23:50.000000000 -0400
@@ -245,7 +245,7 @@ static inline int cirrus_bo_reserve(stru
 {
 	int ret;
 
-	ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, NULL);
+	ret = ttm_bo_reserve(&bo->bo, true, no_wait, NULL);
 	if (ret) {
 		if (ret != -ERESTARTSYS && ret != -EBUSY)
 			DRM_ERROR("reserve failed %p\n", bo);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/cirrus/cirrus_main.c linux-libre-4.7-gnu/drivers/gpu/drm/cirrus/cirrus_main.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/cirrus/cirrus_main.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/cirrus/cirrus_main.c	2016-07-24 15:23:50.000000000 -0400
@@ -61,7 +61,7 @@ cirrus_user_framebuffer_create(struct dr
 				      bpp, mode_cmd->pitches[0]))
 		return ERR_PTR(-EINVAL);
 
-	obj = drm_gem_object_lookup(dev, filp, mode_cmd->handles[0]);
+	obj = drm_gem_object_lookup(filp, mode_cmd->handles[0]);
 	if (obj == NULL)
 		return ERR_PTR(-ENOENT);
 
@@ -295,7 +295,7 @@ cirrus_dumb_mmap_offset(struct drm_file
 	struct drm_gem_object *obj;
 	struct cirrus_bo *bo;
 
-	obj = drm_gem_object_lookup(dev, file, handle);
+	obj = drm_gem_object_lookup(file, handle);
 	if (obj == NULL)
 		return -ENOENT;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/cirrus/cirrus_ttm.c linux-libre-4.7-gnu/drivers/gpu/drm/cirrus/cirrus_ttm.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/cirrus/cirrus_ttm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/cirrus/cirrus_ttm.c	2016-07-24 15:23:50.000000000 -0400
@@ -245,6 +245,8 @@ struct ttm_bo_driver cirrus_bo_driver =
 	.verify_access = cirrus_bo_verify_access,
 	.io_mem_reserve = &cirrus_ttm_io_mem_reserve,
 	.io_mem_free = &cirrus_ttm_io_mem_free,
+	.lru_tail = &ttm_bo_default_lru_tail,
+	.swap_lru_tail = &ttm_bo_default_swap_lru_tail,
 };
 
 int cirrus_mm_init(struct cirrus_device *cirrus)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/drm_agpsupport.c linux-libre-4.7-gnu/drivers/gpu/drm/drm_agpsupport.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/drm_agpsupport.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/drm_agpsupport.c	2016-07-24 15:23:50.000000000 -0400
@@ -423,7 +423,7 @@ struct drm_agp_head *drm_agp_init(struct
 }
 
 /**
- * drm_agp_clear - Clear AGP resource list
+ * drm_legacy_agp_clear - Clear AGP resource list
  * @dev: DRM device
  *
  * Iterate over all AGP resources and remove them. But keep the AGP head
@@ -434,7 +434,7 @@ struct drm_agp_head *drm_agp_init(struct
  * resources from getting destroyed. Drivers are responsible of cleaning them up
  * during device shutdown.
  */
-void drm_agp_clear(struct drm_device *dev)
+void drm_legacy_agp_clear(struct drm_device *dev)
 {
 	struct drm_agp_mem *entry, *tempe;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/drm_atomic.c linux-libre-4.7-gnu/drivers/gpu/drm/drm_atomic.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/drm_atomic.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/drm_atomic.c	2016-07-24 15:23:50.000000000 -0400
@@ -31,6 +31,8 @@
 #include <drm/drm_mode.h>
 #include <drm/drm_plane_helper.h>
 
+#include "drm_crtc_internal.h"
+
 /**
  * drm_atomic_state_default_release -
  * release memory initialized by drm_atomic_state_init
@@ -142,18 +144,11 @@ void drm_atomic_state_default_clear(stru
 		if (!connector)
 			continue;
 
-		/*
-		 * FIXME: Async commits can race with connector unplugging and
-		 * there's currently nothing that prevents cleanup up state for
-		 * deleted connectors. As long as the callback doesn't look at
-		 * the connector we'll be fine though, so make sure that's the
-		 * case by setting all connector pointers to NULL.
-		 */
-		state->connector_states[i]->connector = NULL;
-		connector->funcs->atomic_destroy_state(NULL,
+		connector->funcs->atomic_destroy_state(connector,
 						       state->connector_states[i]);
 		state->connectors[i] = NULL;
 		state->connector_states[i] = NULL;
+		drm_connector_unreference(connector);
 	}
 
 	for (i = 0; i < config->num_crtc; i++) {
@@ -261,6 +256,8 @@ drm_atomic_get_crtc_state(struct drm_ato
 	int ret, index = drm_crtc_index(crtc);
 	struct drm_crtc_state *crtc_state;
 
+	WARN_ON(!state->acquire_ctx);
+
 	crtc_state = drm_atomic_get_existing_crtc_state(state, crtc);
 	if (crtc_state)
 		return crtc_state;
@@ -354,6 +351,8 @@ int drm_atomic_set_mode_prop_for_crtc(st
 	drm_property_unreference_blob(state->mode_blob);
 	state->mode_blob = NULL;
 
+	memset(&state->mode, 0, sizeof(state->mode));
+
 	if (blob) {
 		if (blob->length != sizeof(struct drm_mode_modeinfo) ||
 		    drm_mode_convert_umode(&state->mode,
@@ -366,7 +365,6 @@ int drm_atomic_set_mode_prop_for_crtc(st
 		DRM_DEBUG_ATOMIC("Set [MODE:%s] for CRTC state %p\n",
 				 state->mode.name, state);
 	} else {
-		memset(&state->mode, 0, sizeof(state->mode));
 		state->enable = false;
 		DRM_DEBUG_ATOMIC("Set [NOMODE] for CRTC state %p\n",
 				 state);
@@ -620,6 +618,8 @@ drm_atomic_get_plane_state(struct drm_at
 	int ret, index = drm_plane_index(plane);
 	struct drm_plane_state *plane_state;
 
+	WARN_ON(!state->acquire_ctx);
+
 	plane_state = drm_atomic_get_existing_plane_state(state, plane);
 	if (plane_state)
 		return plane_state;
@@ -888,6 +888,8 @@ drm_atomic_get_connector_state(struct dr
 	struct drm_mode_config *config = &connector->dev->mode_config;
 	struct drm_connector_state *connector_state;
 
+	WARN_ON(!state->acquire_ctx);
+
 	ret = drm_modeset_lock(&config->connection_mutex, state->acquire_ctx);
 	if (ret)
 		return ERR_PTR(ret);
@@ -924,6 +926,7 @@ drm_atomic_get_connector_state(struct dr
 	if (!connector_state)
 		return ERR_PTR(-ENOMEM);
 
+	drm_connector_reference(connector);
 	state->connector_states[index] = connector_state;
 	state->connectors[index] = connector;
 	connector_state->state = state;
@@ -1158,12 +1161,18 @@ drm_atomic_set_crtc_for_connector(struct
 {
 	struct drm_crtc_state *crtc_state;
 
-	if (conn_state->crtc && conn_state->crtc != crtc) {
+	if (conn_state->crtc == crtc)
+		return 0;
+
+	if (conn_state->crtc) {
 		crtc_state = drm_atomic_get_existing_crtc_state(conn_state->state,
 								conn_state->crtc);
 
 		crtc_state->connector_mask &=
 			~(1 << drm_connector_index(conn_state->connector));
+
+		drm_connector_unreference(conn_state->connector);
+		conn_state->crtc = NULL;
 	}
 
 	if (crtc) {
@@ -1173,16 +1182,16 @@ drm_atomic_set_crtc_for_connector(struct
 
 		crtc_state->connector_mask |=
 			1 << drm_connector_index(conn_state->connector);
-	}
 
-	conn_state->crtc = crtc;
+		drm_connector_reference(conn_state->connector);
+		conn_state->crtc = crtc;
 
-	if (crtc)
 		DRM_DEBUG_ATOMIC("Link connector state %p to [CRTC:%d:%s]\n",
 				 conn_state, crtc->base.id, crtc->name);
-	else
+	} else {
 		DRM_DEBUG_ATOMIC("Link connector state %p to [NOCRTC]\n",
 				 conn_state);
+	}
 
 	return 0;
 }
@@ -1287,14 +1296,39 @@ EXPORT_SYMBOL(drm_atomic_add_affected_pl
  */
 void drm_atomic_legacy_backoff(struct drm_atomic_state *state)
 {
+	struct drm_device *dev = state->dev;
+	unsigned crtc_mask = 0;
+	struct drm_crtc *crtc;
 	int ret;
+	bool global = false;
+
+	drm_for_each_crtc(crtc, dev) {
+		if (crtc->acquire_ctx != state->acquire_ctx)
+			continue;
+
+		crtc_mask |= drm_crtc_mask(crtc);
+		crtc->acquire_ctx = NULL;
+	}
+
+	if (WARN_ON(dev->mode_config.acquire_ctx == state->acquire_ctx)) {
+		global = true;
+
+		dev->mode_config.acquire_ctx = NULL;
+	}
 
 retry:
 	drm_modeset_backoff(state->acquire_ctx);
 
-	ret = drm_modeset_lock_all_ctx(state->dev, state->acquire_ctx);
+	ret = drm_modeset_lock_all_ctx(dev, state->acquire_ctx);
 	if (ret)
 		goto retry;
+
+	drm_for_each_crtc(crtc, dev)
+		if (drm_crtc_mask(crtc) & crtc_mask)
+			crtc->acquire_ctx = state->acquire_ctx;
+
+	if (global)
+		dev->mode_config.acquire_ctx = state->acquire_ctx;
 }
 EXPORT_SYMBOL(drm_atomic_legacy_backoff);
 
@@ -1388,7 +1422,7 @@ int drm_atomic_commit(struct drm_atomic_
 EXPORT_SYMBOL(drm_atomic_commit);
 
 /**
- * drm_atomic_async_commit - atomic&async configuration commit
+ * drm_atomic_nonblocking_commit - atomic&nonblocking configuration commit
  * @state: atomic configuration to check
  *
  * Note that this function can return -EDEADLK if the driver needed to acquire
@@ -1403,7 +1437,7 @@ EXPORT_SYMBOL(drm_atomic_commit);
  * Returns:
  * 0 on success, negative error code on failure.
  */
-int drm_atomic_async_commit(struct drm_atomic_state *state)
+int drm_atomic_nonblocking_commit(struct drm_atomic_state *state)
 {
 	struct drm_mode_config *config = &state->dev->mode_config;
 	int ret;
@@ -1412,11 +1446,11 @@ int drm_atomic_async_commit(struct drm_a
 	if (ret)
 		return ret;
 
-	DRM_DEBUG_ATOMIC("commiting %p asynchronously\n", state);
+	DRM_DEBUG_ATOMIC("commiting %p nonblocking\n", state);
 
 	return config->funcs->atomic_commit(state->dev, state, true);
 }
-EXPORT_SYMBOL(drm_atomic_async_commit);
+EXPORT_SYMBOL(drm_atomic_nonblocking_commit);
 
 /*
  * The big monstor ioctl
@@ -1614,12 +1648,19 @@ retry:
 		}
 
 		obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_ANY);
-		if (!obj || !obj->properties) {
+		if (!obj) {
+			ret = -ENOENT;
+			goto out;
+		}
+
+		if (!obj->properties) {
+			drm_mode_object_unreference(obj);
 			ret = -ENOENT;
 			goto out;
 		}
 
 		if (get_user(count_props, count_props_ptr + copied_objs)) {
+			drm_mode_object_unreference(obj);
 			ret = -EFAULT;
 			goto out;
 		}
@@ -1632,12 +1673,14 @@ retry:
 			struct drm_property *prop;
 
 			if (get_user(prop_id, props_ptr + copied_props)) {
+				drm_mode_object_unreference(obj);
 				ret = -EFAULT;
 				goto out;
 			}
 
 			prop = drm_property_find(dev, prop_id);
 			if (!prop) {
+				drm_mode_object_unreference(obj);
 				ret = -ENOENT;
 				goto out;
 			}
@@ -1645,13 +1688,16 @@ retry:
 			if (copy_from_user(&prop_value,
 					   prop_values_ptr + copied_props,
 					   sizeof(prop_value))) {
+				drm_mode_object_unreference(obj);
 				ret = -EFAULT;
 				goto out;
 			}
 
 			ret = atomic_set_prop(state, obj, prop, prop_value);
-			if (ret)
+			if (ret) {
+				drm_mode_object_unreference(obj);
 				goto out;
+			}
 
 			copied_props++;
 		}
@@ -1662,6 +1708,7 @@ retry:
 			plane_mask |= (1 << drm_plane_index(plane));
 			plane->old_fb = plane->fb;
 		}
+		drm_mode_object_unreference(obj);
 	}
 
 	if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
@@ -1685,7 +1732,7 @@ retry:
 		 */
 		ret = drm_atomic_check_only(state);
 	} else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) {
-		ret = drm_atomic_async_commit(state);
+		ret = drm_atomic_nonblocking_commit(state);
 	} else {
 		ret = drm_atomic_commit(state);
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/drm_atomic_helper.c linux-libre-4.7-gnu/drivers/gpu/drm/drm_atomic_helper.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/drm_atomic_helper.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/drm_atomic_helper.c	2016-07-24 15:23:50.000000000 -0400
@@ -384,8 +384,6 @@ mode_fixup(struct drm_atomic_state *stat
 		 */
 		encoder = conn_state->best_encoder;
 		funcs = encoder->helper_private;
-		if (!funcs)
-			continue;
 
 		ret = drm_bridge_mode_fixup(encoder->bridge, &crtc_state->mode,
 				&crtc_state->adjusted_mode);
@@ -394,7 +392,7 @@ mode_fixup(struct drm_atomic_state *stat
 			return -EINVAL;
 		}
 
-		if (funcs->atomic_check) {
+		if (funcs && funcs->atomic_check) {
 			ret = funcs->atomic_check(encoder, crtc_state,
 						  conn_state);
 			if (ret) {
@@ -402,7 +400,7 @@ mode_fixup(struct drm_atomic_state *stat
 						 encoder->base.id, encoder->name);
 				return ret;
 			}
-		} else if (funcs->mode_fixup) {
+		} else if (funcs && funcs->mode_fixup) {
 			ret = funcs->mode_fixup(encoder, &crtc_state->mode,
 						&crtc_state->adjusted_mode);
 			if (!ret) {
@@ -707,12 +705,14 @@ disable_outputs(struct drm_device *dev,
 		drm_bridge_disable(encoder->bridge);
 
 		/* Right function depends upon target state. */
-		if (connector->state->crtc && funcs->prepare)
-			funcs->prepare(encoder);
-		else if (funcs->disable)
-			funcs->disable(encoder);
-		else
-			funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
+		if (funcs) {
+			if (connector->state->crtc && funcs->prepare)
+				funcs->prepare(encoder);
+			else if (funcs->disable)
+				funcs->disable(encoder);
+			else if (funcs->dpms)
+				funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
+		}
 
 		drm_bridge_post_disable(encoder->bridge);
 	}
@@ -873,7 +873,7 @@ crtc_set_mode(struct drm_device *dev, st
 		 * Each encoder has at most one connector (since we always steal
 		 * it away), so we won't call mode_set hooks twice.
 		 */
-		if (funcs->mode_set)
+		if (funcs && funcs->mode_set)
 			funcs->mode_set(encoder, mode, adjusted_mode);
 
 		drm_bridge_mode_set(encoder->bridge, mode, adjusted_mode);
@@ -974,17 +974,29 @@ void drm_atomic_helper_commit_modeset_en
 		 */
 		drm_bridge_pre_enable(encoder->bridge);
 
-		if (funcs->enable)
-			funcs->enable(encoder);
-		else
-			funcs->commit(encoder);
+		if (funcs) {
+			if (funcs->enable)
+				funcs->enable(encoder);
+			else if (funcs->commit)
+				funcs->commit(encoder);
+		}
 
 		drm_bridge_enable(encoder->bridge);
 	}
 }
 EXPORT_SYMBOL(drm_atomic_helper_commit_modeset_enables);
 
-static void wait_for_fences(struct drm_device *dev,
+/**
+ * drm_atomic_helper_wait_for_fences - wait for fences stashed in plane state
+ * @dev: DRM device
+ * @state: atomic state object with old state structures
+ *
+ * For implicit sync, driver should fish the exclusive fence out from the
+ * incoming fb's and stash it in the drm_plane_state.  This is called after
+ * drm_atomic_helper_swap_state() so it uses the current plane state (and
+ * just uses the atomic state to find the changed planes)
+ */
+void drm_atomic_helper_wait_for_fences(struct drm_device *dev,
 			    struct drm_atomic_state *state)
 {
 	struct drm_plane *plane;
@@ -1002,6 +1014,7 @@ static void wait_for_fences(struct drm_d
 		plane->state->fence = NULL;
 	}
 }
+EXPORT_SYMBOL(drm_atomic_helper_wait_for_fences);
 
 /**
  * drm_atomic_helper_framebuffer_changed - check if framebuffer has changed
@@ -1092,6 +1105,8 @@ drm_atomic_helper_wait_for_vblanks(struc
 					drm_crtc_vblank_count(crtc),
 				msecs_to_jiffies(50));
 
+		WARN(!ret, "[CRTC:%d] vblank wait timed out\n", crtc->base.id);
+
 		drm_crtc_vblank_put(crtc);
 	}
 }
@@ -1101,13 +1116,13 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for
  * drm_atomic_helper_commit - commit validated state object
  * @dev: DRM device
  * @state: the driver state object
- * @async: asynchronous commit
+ * @nonblocking: whether nonblocking behavior is requested.
  *
  * This function commits a with drm_atomic_helper_check() pre-validated state
  * object. This can still fail when e.g. the framebuffer reservation fails. For
- * now this doesn't implement asynchronous commits.
+ * now this doesn't implement nonblocking commits.
  *
- * Note that right now this function does not support async commits, and hence
+ * Note that right now this function does not support nonblocking commits, hence
  * driver writers must implement their own version for now. Also note that the
  * default ordering of how the various stages are called is to match the legacy
  * modeset helper library closest. One peculiarity of that is that it doesn't
@@ -1128,11 +1143,11 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for
  */
 int drm_atomic_helper_commit(struct drm_device *dev,
 			     struct drm_atomic_state *state,
-			     bool async)
+			     bool nonblock)
 {
 	int ret;
 
-	if (async)
+	if (nonblock)
 		return -EBUSY;
 
 	ret = drm_atomic_helper_prepare_planes(dev, state);
@@ -1163,7 +1178,7 @@ int drm_atomic_helper_commit(struct drm_
 	 * current layout.
 	 */
 
-	wait_for_fences(dev, state);
+	drm_atomic_helper_wait_for_fences(dev, state);
 
 	drm_atomic_helper_commit_modeset_disables(dev, state);
 
@@ -1182,20 +1197,20 @@ int drm_atomic_helper_commit(struct drm_
 EXPORT_SYMBOL(drm_atomic_helper_commit);
 
 /**
- * DOC: implementing async commit
+ * DOC: implementing nonblocking commit
  *
- * For now the atomic helpers don't support async commit directly. If there is
- * real need it could be added though, using the dma-buf fence infrastructure
- * for generic synchronization with outstanding rendering.
+ * For now the atomic helpers don't support nonblocking commit directly. If
+ * there is real need it could be added though, using the dma-buf fence
+ * infrastructure for generic synchronization with outstanding rendering.
  *
- * For now drivers have to implement async commit themselves, with the following
- * sequence being the recommended one:
+ * For now drivers have to implement nonblocking commit themselves, with the
+ * following sequence being the recommended one:
  *
  * 1. Run drm_atomic_helper_prepare_planes() first. This is the only function
  * which commit needs to call which can fail, so we want to run it first and
  * synchronously.
  *
- * 2. Synchronize with any outstanding asynchronous commit worker threads which
+ * 2. Synchronize with any outstanding nonblocking commit worker threads which
  * might be affected the new state update. This can be done by either cancelling
  * or flushing the work items, depending upon whether the driver can deal with
  * cancelled updates. Note that it is important to ensure that the framebuffer
@@ -1209,9 +1224,9 @@ EXPORT_SYMBOL(drm_atomic_helper_commit);
  * 3. The software state is updated synchronously with
  * drm_atomic_helper_swap_state(). Doing this under the protection of all modeset
  * locks means concurrent callers never see inconsistent state. And doing this
- * while it's guaranteed that no relevant async worker runs means that async
- * workers do not need grab any locks. Actually they must not grab locks, for
- * otherwise the work flushing will deadlock.
+ * while it's guaranteed that no relevant nonblocking worker runs means that
+ * nonblocking workers do not need grab any locks. Actually they must not grab
+ * locks, for otherwise the work flushing will deadlock.
  *
  * 4. Schedule a work item to do all subsequent steps, using the split-out
  * commit helpers: a) pre-plane commit b) plane commit c) post-plane commit and
@@ -2358,11 +2373,11 @@ retry:
 		goto fail;
 	}
 
-	ret = drm_atomic_async_commit(state);
+	ret = drm_atomic_nonblocking_commit(state);
 	if (ret != 0)
 		goto fail;
 
-	/* Driver takes ownership of state on successful async commit. */
+	/* Driver takes ownership of state on successful commit. */
 	return 0;
 fail:
 	if (ret == -EDEADLK)
@@ -2468,6 +2483,23 @@ backoff:
 EXPORT_SYMBOL(drm_atomic_helper_connector_dpms);
 
 /**
+ * drm_atomic_helper_best_encoder - Helper for &drm_connector_helper_funcs
+ *                                  ->best_encoder callback
+ * @connector: Connector control structure
+ *
+ * This is a &drm_connector_helper_funcs ->best_encoder callback helper for
+ * connectors that support exactly 1 encoder, statically determined at driver
+ * init time.
+ */
+struct drm_encoder *
+drm_atomic_helper_best_encoder(struct drm_connector *connector)
+{
+	WARN_ON(connector->encoder_ids[1]);
+	return drm_encoder_find(connector->dev, connector->encoder_ids[0]);
+}
+EXPORT_SYMBOL(drm_atomic_helper_best_encoder);
+
+/**
  * DOC: atomic state reset and initialization
  *
  * Both the drm core and the atomic helpers assume that there is always the full
@@ -2497,12 +2529,9 @@ EXPORT_SYMBOL(drm_atomic_helper_connecto
  */
 void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc)
 {
-	if (crtc->state) {
-		drm_property_unreference_blob(crtc->state->mode_blob);
-		drm_property_unreference_blob(crtc->state->degamma_lut);
-		drm_property_unreference_blob(crtc->state->ctm);
-		drm_property_unreference_blob(crtc->state->gamma_lut);
-	}
+	if (crtc->state)
+		__drm_atomic_helper_crtc_destroy_state(crtc->state);
+
 	kfree(crtc->state);
 	crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL);
 
@@ -2566,15 +2595,13 @@ EXPORT_SYMBOL(drm_atomic_helper_crtc_dup
 
 /**
  * __drm_atomic_helper_crtc_destroy_state - release CRTC state
- * @crtc: CRTC object
  * @state: CRTC state object to release
  *
  * Releases all resources stored in the CRTC state without actually freeing
  * the memory of the CRTC state. This is useful for drivers that subclass the
  * CRTC state.
  */
-void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc,
-					    struct drm_crtc_state *state)
+void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc_state *state)
 {
 	drm_property_unreference_blob(state->mode_blob);
 	drm_property_unreference_blob(state->degamma_lut);
@@ -2594,7 +2621,7 @@ EXPORT_SYMBOL(__drm_atomic_helper_crtc_d
 void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc,
 					  struct drm_crtc_state *state)
 {
-	__drm_atomic_helper_crtc_destroy_state(crtc, state);
+	__drm_atomic_helper_crtc_destroy_state(state);
 	kfree(state);
 }
 EXPORT_SYMBOL(drm_atomic_helper_crtc_destroy_state);
@@ -2608,8 +2635,8 @@ EXPORT_SYMBOL(drm_atomic_helper_crtc_des
  */
 void drm_atomic_helper_plane_reset(struct drm_plane *plane)
 {
-	if (plane->state && plane->state->fb)
-		drm_framebuffer_unreference(plane->state->fb);
+	if (plane->state)
+		__drm_atomic_helper_plane_destroy_state(plane->state);
 
 	kfree(plane->state);
 	plane->state = kzalloc(sizeof(*plane->state), GFP_KERNEL);
@@ -2664,15 +2691,13 @@ EXPORT_SYMBOL(drm_atomic_helper_plane_du
 
 /**
  * __drm_atomic_helper_plane_destroy_state - release plane state
- * @plane: plane object
  * @state: plane state object to release
  *
  * Releases all resources stored in the plane state without actually freeing
  * the memory of the plane state. This is useful for drivers that subclass the
  * plane state.
  */
-void __drm_atomic_helper_plane_destroy_state(struct drm_plane *plane,
-					     struct drm_plane_state *state)
+void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state)
 {
 	if (state->fb)
 		drm_framebuffer_unreference(state->fb);
@@ -2690,7 +2715,7 @@ EXPORT_SYMBOL(__drm_atomic_helper_plane_
 void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane,
 					   struct drm_plane_state *state)
 {
-	__drm_atomic_helper_plane_destroy_state(plane, state);
+	__drm_atomic_helper_plane_destroy_state(state);
 	kfree(state);
 }
 EXPORT_SYMBOL(drm_atomic_helper_plane_destroy_state);
@@ -2730,6 +2755,9 @@ void drm_atomic_helper_connector_reset(s
 	struct drm_connector_state *conn_state =
 		kzalloc(sizeof(*conn_state), GFP_KERNEL);
 
+	if (connector->state)
+		__drm_atomic_helper_connector_destroy_state(connector->state);
+
 	kfree(connector->state);
 	__drm_atomic_helper_connector_reset(connector, conn_state);
 }
@@ -2748,6 +2776,8 @@ __drm_atomic_helper_connector_duplicate_
 					    struct drm_connector_state *state)
 {
 	memcpy(state, connector->state, sizeof(*state));
+	if (state->crtc)
+		drm_connector_reference(connector);
 }
 EXPORT_SYMBOL(__drm_atomic_helper_connector_duplicate_state);
 
@@ -2859,7 +2889,6 @@ EXPORT_SYMBOL(drm_atomic_helper_duplicat
 
 /**
  * __drm_atomic_helper_connector_destroy_state - release connector state
- * @connector: connector object
  * @state: connector state object to release
  *
  * Releases all resources stored in the connector state without actually
@@ -2867,14 +2896,15 @@ EXPORT_SYMBOL(drm_atomic_helper_duplicat
  * subclass the connector state.
  */
 void
-__drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
-					    struct drm_connector_state *state)
+__drm_atomic_helper_connector_destroy_state(struct drm_connector_state *state)
 {
 	/*
 	 * This is currently a placeholder so that drivers that subclass the
 	 * state will automatically do the right thing if code is ever added
 	 * to this function.
 	 */
+	if (state->crtc)
+		drm_connector_unreference(state->connector);
 }
 EXPORT_SYMBOL(__drm_atomic_helper_connector_destroy_state);
 
@@ -2889,7 +2919,7 @@ EXPORT_SYMBOL(__drm_atomic_helper_connec
 void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
 					  struct drm_connector_state *state)
 {
-	__drm_atomic_helper_connector_destroy_state(connector, state);
+	__drm_atomic_helper_connector_destroy_state(state);
 	kfree(state);
 }
 EXPORT_SYMBOL(drm_atomic_helper_connector_destroy_state);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/drm_bufs.c linux-libre-4.7-gnu/drivers/gpu/drm/drm_bufs.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/drm_bufs.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/drm_bufs.c	2016-07-24 15:23:50.000000000 -0400
@@ -396,6 +396,10 @@ int drm_legacy_addmap_ioctl(struct drm_d
 	if (!(capable(CAP_SYS_ADMIN) || map->type == _DRM_AGP || map->type == _DRM_SHM))
 		return -EPERM;
 
+	if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
+	    drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
 	err = drm_addmap_core(dev, map->offset, map->size, map->type,
 			      map->flags, &maplist);
 
@@ -416,6 +420,62 @@ int drm_legacy_addmap_ioctl(struct drm_d
 	return 0;
 }
 
+/*
+ * Get a mapping information.
+ *
+ * \param inode device inode.
+ * \param file_priv DRM file private.
+ * \param cmd command.
+ * \param arg user argument, pointing to a drm_map structure.
+ *
+ * \return zero on success or a negative number on failure.
+ *
+ * Searches for the mapping with the specified offset and copies its information
+ * into userspace
+ */
+int drm_legacy_getmap_ioctl(struct drm_device *dev, void *data,
+			    struct drm_file *file_priv)
+{
+	struct drm_map *map = data;
+	struct drm_map_list *r_list = NULL;
+	struct list_head *list;
+	int idx;
+	int i;
+
+	if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
+	    drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
+	idx = map->offset;
+	if (idx < 0)
+		return -EINVAL;
+
+	i = 0;
+	mutex_lock(&dev->struct_mutex);
+	list_for_each(list, &dev->maplist) {
+		if (i == idx) {
+			r_list = list_entry(list, struct drm_map_list, head);
+			break;
+		}
+		i++;
+	}
+	if (!r_list || !r_list->map) {
+		mutex_unlock(&dev->struct_mutex);
+		return -EINVAL;
+	}
+
+	map->offset = r_list->map->offset;
+	map->size = r_list->map->size;
+	map->type = r_list->map->type;
+	map->flags = r_list->map->flags;
+	map->handle = (void *)(unsigned long) r_list->user_token;
+	map->mtrr = arch_phys_wc_index(r_list->map->mtrr);
+
+	mutex_unlock(&dev->struct_mutex);
+
+	return 0;
+}
+
 /**
  * Remove a map private from list and deallocate resources if the mapping
  * isn't in use.
@@ -482,18 +542,35 @@ int drm_legacy_rmmap_locked(struct drm_d
 }
 EXPORT_SYMBOL(drm_legacy_rmmap_locked);
 
-int drm_legacy_rmmap(struct drm_device *dev, struct drm_local_map *map)
+void drm_legacy_rmmap(struct drm_device *dev, struct drm_local_map *map)
 {
-	int ret;
+	if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
+	    drm_core_check_feature(dev, DRIVER_MODESET))
+		return;
 
 	mutex_lock(&dev->struct_mutex);
-	ret = drm_legacy_rmmap_locked(dev, map);
+	drm_legacy_rmmap_locked(dev, map);
 	mutex_unlock(&dev->struct_mutex);
-
-	return ret;
 }
 EXPORT_SYMBOL(drm_legacy_rmmap);
 
+void drm_legacy_master_rmmaps(struct drm_device *dev, struct drm_master *master)
+{
+	struct drm_map_list *r_list, *list_temp;
+
+	if (drm_core_check_feature(dev, DRIVER_MODESET))
+		return;
+
+	mutex_lock(&dev->struct_mutex);
+	list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head) {
+		if (r_list->master == master) {
+			drm_legacy_rmmap_locked(dev, r_list->map);
+			r_list = NULL;
+		}
+	}
+	mutex_unlock(&dev->struct_mutex);
+}
+
 /* The rmmap ioctl appears to be unnecessary.  All mappings are torn down on
  * the last close of the device, and this is necessary for cleanup when things
  * exit uncleanly.  Therefore, having userland manually remove mappings seems
@@ -517,6 +594,10 @@ int drm_legacy_rmmap_ioctl(struct drm_de
 	struct drm_map_list *r_list;
 	int ret;
 
+	if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) &&
+	    drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
 	mutex_lock(&dev->struct_mutex);
 	list_for_each_entry(r_list, &dev->maplist, head) {
 		if (r_list->map &&
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/drm_cache.c linux-libre-4.7-gnu/drivers/gpu/drm/drm_cache.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/drm_cache.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/drm_cache.c	2016-07-24 15:23:50.000000000 -0400
@@ -72,7 +72,7 @@ drm_clflush_pages(struct page *pages[],
 {
 
 #if defined(CONFIG_X86)
-	if (cpu_has_clflush) {
+	if (static_cpu_has(X86_FEATURE_CLFLUSH)) {
 		drm_cache_flush_clflush(pages, num_pages);
 		return;
 	}
@@ -105,7 +105,7 @@ void
 drm_clflush_sg(struct sg_table *st)
 {
 #if defined(CONFIG_X86)
-	if (cpu_has_clflush) {
+	if (static_cpu_has(X86_FEATURE_CLFLUSH)) {
 		struct sg_page_iter sg_iter;
 
 		mb();
@@ -129,7 +129,7 @@ void
 drm_clflush_virt_range(void *addr, unsigned long length)
 {
 #if defined(CONFIG_X86)
-	if (cpu_has_clflush) {
+	if (static_cpu_has(X86_FEATURE_CLFLUSH)) {
 		const int size = boot_cpu_data.x86_clflush_size;
 		void *end = addr + length;
 		addr = (void *)(((unsigned long)addr) & -size);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/drm_crtc.c linux-libre-4.7-gnu/drivers/gpu/drm/drm_crtc.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/drm_crtc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/drm_crtc.c	2016-07-24 15:23:50.000000000 -0400
@@ -168,6 +168,7 @@ static struct drm_conn_prop_enum_list dr
 	{ DRM_MODE_CONNECTOR_eDP, "eDP" },
 	{ DRM_MODE_CONNECTOR_VIRTUAL, "Virtual" },
 	{ DRM_MODE_CONNECTOR_DSI, "DSI" },
+	{ DRM_MODE_CONNECTOR_DPI, "DPI" },
 };
 
 static const struct drm_prop_enum_list drm_encoder_enum_list[] = {
@@ -179,6 +180,7 @@ static const struct drm_prop_enum_list d
 	{ DRM_MODE_ENCODER_VIRTUAL, "Virtual" },
 	{ DRM_MODE_ENCODER_DSI, "DSI" },
 	{ DRM_MODE_ENCODER_DPMST, "DP MST" },
+	{ DRM_MODE_ENCODER_DPI, "DPI" },
 };
 
 static const struct drm_prop_enum_list drm_subpixel_enum_list[] = {
@@ -275,7 +277,8 @@ EXPORT_SYMBOL(drm_get_format_name);
 static int drm_mode_object_get_reg(struct drm_device *dev,
 				   struct drm_mode_object *obj,
 				   uint32_t obj_type,
-				   bool register_obj)
+				   bool register_obj,
+				   void (*obj_free_cb)(struct kref *kref))
 {
 	int ret;
 
@@ -288,6 +291,10 @@ static int drm_mode_object_get_reg(struc
 		 */
 		obj->id = ret;
 		obj->type = obj_type;
+		if (obj_free_cb) {
+			obj->free_cb = obj_free_cb;
+			kref_init(&obj->refcount);
+		}
 	}
 	mutex_unlock(&dev->mode_config.idr_mutex);
 
@@ -311,7 +318,7 @@ static int drm_mode_object_get_reg(struc
 int drm_mode_object_get(struct drm_device *dev,
 			struct drm_mode_object *obj, uint32_t obj_type)
 {
-	return drm_mode_object_get_reg(dev, obj, obj_type, true);
+	return drm_mode_object_get_reg(dev, obj, obj_type, true, NULL);
 }
 
 static void drm_mode_object_register(struct drm_device *dev,
@@ -323,19 +330,24 @@ static void drm_mode_object_register(str
 }
 
 /**
- * drm_mode_object_put - free a modeset identifer
+ * drm_mode_object_unregister - free a modeset identifer
  * @dev: DRM device
  * @object: object to free
  *
- * Free @id from @dev's unique identifier pool. Note that despite the _get
- * postfix modeset identifiers are _not_ reference counted. Hence don't use this
+ * Free @id from @dev's unique identifier pool.
+ * This function can be called multiple times, and guards against
+ * multiple removals.
+ * These modeset identifiers are _not_ reference counted. Hence don't use this
  * for reference counted modeset objects like framebuffers.
  */
-void drm_mode_object_put(struct drm_device *dev,
+void drm_mode_object_unregister(struct drm_device *dev,
 			 struct drm_mode_object *object)
 {
 	mutex_lock(&dev->mode_config.idr_mutex);
-	idr_remove(&dev->mode_config.crtc_idr, object->id);
+	if (object->id) {
+		idr_remove(&dev->mode_config.crtc_idr, object->id);
+		object->id = 0;
+	}
 	mutex_unlock(&dev->mode_config.idr_mutex);
 }
 
@@ -350,11 +362,11 @@ static struct drm_mode_object *_object_f
 		obj = NULL;
 	if (obj && obj->id != id)
 		obj = NULL;
-	/* don't leak out unref'd fb's */
-	if (obj &&
-	    (obj->type == DRM_MODE_OBJECT_FB ||
-	     obj->type == DRM_MODE_OBJECT_BLOB))
-		obj = NULL;
+
+	if (obj && obj->free_cb) {
+		if (!kref_get_unless_zero(&obj->refcount))
+			obj = NULL;
+	}
 	mutex_unlock(&dev->mode_config.idr_mutex);
 
 	return obj;
@@ -366,25 +378,70 @@ static struct drm_mode_object *_object_f
  * @id: id of the mode object
  * @type: type of the mode object
  *
- * Note that framebuffers cannot be looked up with this functions - since those
- * are reference counted, they need special treatment.  Even with
- * DRM_MODE_OBJECT_ANY (although that will simply return NULL
- * rather than WARN_ON()).
+ * This function is used to look up a modeset object. It will acquire a
+ * reference for reference counted objects. This reference must be dropped again
+ * by callind drm_mode_object_unreference().
  */
 struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
 		uint32_t id, uint32_t type)
 {
 	struct drm_mode_object *obj = NULL;
 
-	/* Framebuffers are reference counted and need their own lookup
-	 * function.*/
-	WARN_ON(type == DRM_MODE_OBJECT_FB || type == DRM_MODE_OBJECT_BLOB);
 	obj = _object_find(dev, id, type);
 	return obj;
 }
 EXPORT_SYMBOL(drm_mode_object_find);
 
 /**
+ * drm_mode_object_unreference - decr the object refcnt
+ * @obj: mode_object
+ *
+ * This functions decrements the object's refcount if it is a refcounted modeset
+ * object. It is a no-op on any other object. This is used to drop references
+ * acquired with drm_mode_object_reference().
+ */
+void drm_mode_object_unreference(struct drm_mode_object *obj)
+{
+	if (obj->free_cb) {
+		DRM_DEBUG("OBJ ID: %d (%d)\n", obj->id, atomic_read(&obj->refcount.refcount));
+		kref_put(&obj->refcount, obj->free_cb);
+	}
+}
+EXPORT_SYMBOL(drm_mode_object_unreference);
+
+/**
+ * drm_mode_object_reference - incr the object refcnt
+ * @obj: mode_object
+ *
+ * This functions increments the object's refcount if it is a refcounted modeset
+ * object. It is a no-op on any other object. References should be dropped again
+ * by calling drm_mode_object_unreference().
+ */
+void drm_mode_object_reference(struct drm_mode_object *obj)
+{
+	if (obj->free_cb) {
+		DRM_DEBUG("OBJ ID: %d (%d)\n", obj->id, atomic_read(&obj->refcount.refcount));
+		kref_get(&obj->refcount);
+	}
+}
+EXPORT_SYMBOL(drm_mode_object_reference);
+
+static void drm_framebuffer_free(struct kref *kref)
+{
+	struct drm_framebuffer *fb =
+			container_of(kref, struct drm_framebuffer, base.refcount);
+	struct drm_device *dev = fb->dev;
+
+	/*
+	 * The lookup idr holds a weak reference, which has not necessarily been
+	 * removed at this point. Check for that.
+	 */
+	drm_mode_object_unregister(dev, &fb->base);
+
+	fb->funcs->destroy(fb);
+}
+
+/**
  * drm_framebuffer_init - initialize a framebuffer
  * @dev: DRM device
  * @fb: framebuffer to be initialized
@@ -407,71 +464,26 @@ int drm_framebuffer_init(struct drm_devi
 {
 	int ret;
 
-	mutex_lock(&dev->mode_config.fb_lock);
-	kref_init(&fb->refcount);
 	INIT_LIST_HEAD(&fb->filp_head);
 	fb->dev = dev;
 	fb->funcs = funcs;
 
-	ret = drm_mode_object_get(dev, &fb->base, DRM_MODE_OBJECT_FB);
+	ret = drm_mode_object_get_reg(dev, &fb->base, DRM_MODE_OBJECT_FB,
+				      false, drm_framebuffer_free);
 	if (ret)
 		goto out;
 
+	mutex_lock(&dev->mode_config.fb_lock);
 	dev->mode_config.num_fb++;
 	list_add(&fb->head, &dev->mode_config.fb_list);
-out:
 	mutex_unlock(&dev->mode_config.fb_lock);
 
+	drm_mode_object_register(dev, &fb->base);
+out:
 	return ret;
 }
 EXPORT_SYMBOL(drm_framebuffer_init);
 
-/* dev->mode_config.fb_lock must be held! */
-static void __drm_framebuffer_unregister(struct drm_device *dev,
-					 struct drm_framebuffer *fb)
-{
-	drm_mode_object_put(dev, &fb->base);
-
-	fb->base.id = 0;
-}
-
-static void drm_framebuffer_free(struct kref *kref)
-{
-	struct drm_framebuffer *fb =
-			container_of(kref, struct drm_framebuffer, refcount);
-	struct drm_device *dev = fb->dev;
-
-	/*
-	 * The lookup idr holds a weak reference, which has not necessarily been
-	 * removed at this point. Check for that.
-	 */
-	mutex_lock(&dev->mode_config.fb_lock);
-	if (fb->base.id) {
-		/* Mark fb as reaped and drop idr ref. */
-		__drm_framebuffer_unregister(dev, fb);
-	}
-	mutex_unlock(&dev->mode_config.fb_lock);
-
-	fb->funcs->destroy(fb);
-}
-
-static struct drm_framebuffer *__drm_framebuffer_lookup(struct drm_device *dev,
-							uint32_t id)
-{
-	struct drm_mode_object *obj = NULL;
-	struct drm_framebuffer *fb;
-
-	mutex_lock(&dev->mode_config.idr_mutex);
-	obj = idr_find(&dev->mode_config.crtc_idr, id);
-	if (!obj || (obj->type != DRM_MODE_OBJECT_FB) || (obj->id != id))
-		fb = NULL;
-	else
-		fb = obj_to_fb(obj);
-	mutex_unlock(&dev->mode_config.idr_mutex);
-
-	return fb;
-}
-
 /**
  * drm_framebuffer_lookup - look up a drm framebuffer and grab a reference
  * @dev: drm device
@@ -484,47 +496,17 @@ static struct drm_framebuffer *__drm_fra
 struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev,
 					       uint32_t id)
 {
-	struct drm_framebuffer *fb;
-
-	mutex_lock(&dev->mode_config.fb_lock);
-	fb = __drm_framebuffer_lookup(dev, id);
-	if (fb) {
-		if (!kref_get_unless_zero(&fb->refcount))
-			fb = NULL;
-	}
-	mutex_unlock(&dev->mode_config.fb_lock);
+	struct drm_mode_object *obj;
+	struct drm_framebuffer *fb = NULL;
 
+	obj = _object_find(dev, id, DRM_MODE_OBJECT_FB);
+	if (obj)
+		fb = obj_to_fb(obj);
 	return fb;
 }
 EXPORT_SYMBOL(drm_framebuffer_lookup);
 
 /**
- * drm_framebuffer_unreference - unref a framebuffer
- * @fb: framebuffer to unref
- *
- * This functions decrements the fb's refcount and frees it if it drops to zero.
- */
-void drm_framebuffer_unreference(struct drm_framebuffer *fb)
-{
-	DRM_DEBUG("%p: FB ID: %d (%d)\n", fb, fb->base.id, atomic_read(&fb->refcount.refcount));
-	kref_put(&fb->refcount, drm_framebuffer_free);
-}
-EXPORT_SYMBOL(drm_framebuffer_unreference);
-
-/**
- * drm_framebuffer_reference - incr the fb refcnt
- * @fb: framebuffer
- *
- * This functions increments the fb's refcount.
- */
-void drm_framebuffer_reference(struct drm_framebuffer *fb)
-{
-	DRM_DEBUG("%p: FB ID: %d (%d)\n", fb, fb->base.id, atomic_read(&fb->refcount.refcount));
-	kref_get(&fb->refcount);
-}
-EXPORT_SYMBOL(drm_framebuffer_reference);
-
-/**
  * drm_framebuffer_unregister_private - unregister a private fb from the lookup idr
  * @fb: fb to unregister
  *
@@ -542,10 +524,8 @@ void drm_framebuffer_unregister_private(
 
 	dev = fb->dev;
 
-	mutex_lock(&dev->mode_config.fb_lock);
 	/* Mark fb as reaped and drop idr ref. */
-	__drm_framebuffer_unregister(dev, fb);
-	mutex_unlock(&dev->mode_config.fb_lock);
+	drm_mode_object_unregister(dev, &fb->base);
 }
 EXPORT_SYMBOL(drm_framebuffer_unregister_private);
 
@@ -619,7 +599,7 @@ void drm_framebuffer_remove(struct drm_f
 	 * in-use fb with fb-id == 0. Userspace is allowed to shoot its own foot
 	 * in this manner.
 	 */
-	if (atomic_read(&fb->refcount.refcount) > 1) {
+	if (drm_framebuffer_read_refcount(fb) > 1) {
 		drm_modeset_lock_all(dev);
 		/* remove from any CRTC */
 		drm_for_each_crtc(crtc, dev) {
@@ -705,7 +685,7 @@ int drm_crtc_init_with_planes(struct drm
 				       drm_num_crtcs(dev));
 	}
 	if (!crtc->name) {
-		drm_mode_object_put(dev, &crtc->base);
+		drm_mode_object_unregister(dev, &crtc->base);
 		return -ENOMEM;
 	}
 
@@ -747,7 +727,7 @@ void drm_crtc_cleanup(struct drm_crtc *c
 
 	drm_modeset_lock_fini(&crtc->mutex);
 
-	drm_mode_object_put(dev, &crtc->base);
+	drm_mode_object_unregister(dev, &crtc->base);
 	list_del(&crtc->head);
 	dev->mode_config.num_crtc--;
 
@@ -884,6 +864,16 @@ static void drm_connector_get_cmdline_mo
 		      mode->interlace ?  " interlaced" : "");
 }
 
+static void drm_connector_free(struct kref *kref)
+{
+	struct drm_connector *connector =
+		container_of(kref, struct drm_connector, base.refcount);
+	struct drm_device *dev = connector->dev;
+
+	drm_mode_object_unregister(dev, &connector->base);
+	connector->funcs->destroy(connector);
+}
+
 /**
  * drm_connector_init - Init a preallocated connector
  * @dev: DRM device
@@ -909,7 +899,9 @@ int drm_connector_init(struct drm_device
 
 	drm_modeset_lock_all(dev);
 
-	ret = drm_mode_object_get_reg(dev, &connector->base, DRM_MODE_OBJECT_CONNECTOR, false);
+	ret = drm_mode_object_get_reg(dev, &connector->base,
+				      DRM_MODE_OBJECT_CONNECTOR,
+				      false, drm_connector_free);
 	if (ret)
 		goto out_unlock;
 
@@ -972,7 +964,7 @@ out_put_id:
 		ida_remove(&config->connector_ida, connector->connector_id);
 out_put:
 	if (ret)
-		drm_mode_object_put(dev, &connector->base);
+		drm_mode_object_unregister(dev, &connector->base);
 
 out_unlock:
 	drm_modeset_unlock_all(dev);
@@ -1010,7 +1002,7 @@ void drm_connector_cleanup(struct drm_co
 		   connector->connector_id);
 
 	kfree(connector->display_info.bus_formats);
-	drm_mode_object_put(dev, &connector->base);
+	drm_mode_object_unregister(dev, &connector->base);
 	kfree(connector->name);
 	connector->name = NULL;
 	list_del(&connector->head);
@@ -1038,8 +1030,6 @@ int drm_connector_register(struct drm_co
 {
 	int ret;
 
-	drm_mode_object_register(connector->dev, &connector->base);
-
 	ret = drm_sysfs_connector_add(connector);
 	if (ret)
 		return ret;
@@ -1050,6 +1040,8 @@ int drm_connector_register(struct drm_co
 		return ret;
 	}
 
+	drm_mode_object_register(connector->dev, &connector->base);
+
 	return 0;
 }
 EXPORT_SYMBOL(drm_connector_register);
@@ -1067,25 +1059,65 @@ void drm_connector_unregister(struct drm
 }
 EXPORT_SYMBOL(drm_connector_unregister);
 
+/**
+ * drm_connector_register_all - register all connectors
+ * @dev: drm device
+ *
+ * This function registers all connectors in sysfs and other places so that
+ * userspace can start to access them. Drivers can call it after calling
+ * drm_dev_register() to complete the device registration, if they don't call
+ * drm_connector_register() on each connector individually.
+ *
+ * When a device is unplugged and should be removed from userspace access,
+ * call drm_connector_unregister_all(), which is the inverse of this
+ * function.
+ *
+ * Returns:
+ * Zero on success, error code on failure.
+ */
+int drm_connector_register_all(struct drm_device *dev)
+{
+	struct drm_connector *connector;
+	int ret;
+
+	mutex_lock(&dev->mode_config.mutex);
+
+	drm_for_each_connector(connector, dev) {
+		ret = drm_connector_register(connector);
+		if (ret)
+			goto err;
+	}
+
+	mutex_unlock(&dev->mode_config.mutex);
+
+	return 0;
+
+err:
+	mutex_unlock(&dev->mode_config.mutex);
+	drm_connector_unregister_all(dev);
+	return ret;
+}
+EXPORT_SYMBOL(drm_connector_register_all);
 
 /**
- * drm_connector_unplug_all - unregister connector userspace interfaces
+ * drm_connector_unregister_all - unregister connector userspace interfaces
  * @dev: drm device
  *
- * This function unregisters all connector userspace interfaces in sysfs. Should
- * be call when the device is disconnected, e.g. from an usb driver's
- * ->disconnect callback.
+ * This functions unregisters all connectors from sysfs and other places so
+ * that userspace can no longer access them. Drivers should call this as the
+ * first step tearing down the device instace, or when the underlying
+ * physical device disappeared (e.g. USB unplug), right before calling
+ * drm_dev_unregister().
  */
-void drm_connector_unplug_all(struct drm_device *dev)
+void drm_connector_unregister_all(struct drm_device *dev)
 {
 	struct drm_connector *connector;
 
 	/* FIXME: taking the mode config mutex ends up in a clash with sysfs */
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
 		drm_connector_unregister(connector);
-
 }
-EXPORT_SYMBOL(drm_connector_unplug_all);
+EXPORT_SYMBOL(drm_connector_unregister_all);
 
 /**
  * drm_encoder_init - Init a preallocated encoder
@@ -1138,7 +1170,7 @@ int drm_encoder_init(struct drm_device *
 
 out_put:
 	if (ret)
-		drm_mode_object_put(dev, &encoder->base);
+		drm_mode_object_unregister(dev, &encoder->base);
 
 out_unlock:
 	drm_modeset_unlock_all(dev);
@@ -1181,7 +1213,7 @@ void drm_encoder_cleanup(struct drm_enco
 	struct drm_device *dev = encoder->dev;
 
 	drm_modeset_lock_all(dev);
-	drm_mode_object_put(dev, &encoder->base);
+	drm_mode_object_unregister(dev, &encoder->base);
 	kfree(encoder->name);
 	list_del(&encoder->head);
 	dev->mode_config.num_encoder--;
@@ -1242,7 +1274,7 @@ int drm_universal_plane_init(struct drm_
 					    GFP_KERNEL);
 	if (!plane->format_types) {
 		DRM_DEBUG_KMS("out of memory when allocating plane\n");
-		drm_mode_object_put(dev, &plane->base);
+		drm_mode_object_unregister(dev, &plane->base);
 		return -ENOMEM;
 	}
 
@@ -1258,7 +1290,7 @@ int drm_universal_plane_init(struct drm_
 	}
 	if (!plane->name) {
 		kfree(plane->format_types);
-		drm_mode_object_put(dev, &plane->base);
+		drm_mode_object_unregister(dev, &plane->base);
 		return -ENOMEM;
 	}
 
@@ -1338,7 +1370,7 @@ void drm_plane_cleanup(struct drm_plane
 
 	drm_modeset_lock_all(dev);
 	kfree(plane->format_types);
-	drm_mode_object_put(dev, &plane->base);
+	drm_mode_object_unregister(dev, &plane->base);
 
 	BUG_ON(list_empty(&plane->head));
 
@@ -1918,8 +1950,6 @@ int drm_mode_getresources(struct drm_dev
 		copied = 0;
 		crtc_id = (uint32_t __user *)(unsigned long)card_res->crtc_id_ptr;
 		drm_for_each_crtc(crtc, dev) {
-			DRM_DEBUG_KMS("[CRTC:%d:%s]\n",
-				      crtc->base.id, crtc->name);
 			if (put_user(crtc->base.id, crtc_id + copied)) {
 				ret = -EFAULT;
 				goto out;
@@ -1934,8 +1964,6 @@ int drm_mode_getresources(struct drm_dev
 		copied = 0;
 		encoder_id = (uint32_t __user *)(unsigned long)card_res->encoder_id_ptr;
 		drm_for_each_encoder(encoder, dev) {
-			DRM_DEBUG_KMS("[ENCODER:%d:%s]\n", encoder->base.id,
-					encoder->name);
 			if (put_user(encoder->base.id, encoder_id +
 				     copied)) {
 				ret = -EFAULT;
@@ -1951,9 +1979,6 @@ int drm_mode_getresources(struct drm_dev
 		copied = 0;
 		connector_id = (uint32_t __user *)(unsigned long)card_res->connector_id_ptr;
 		drm_for_each_connector(connector, dev) {
-			DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
-				connector->base.id,
-				connector->name);
 			if (put_user(connector->base.id,
 				     connector_id + copied)) {
 				ret = -EFAULT;
@@ -1964,9 +1989,6 @@ int drm_mode_getresources(struct drm_dev
 	}
 	card_res->count_connectors = connector_count;
 
-	DRM_DEBUG_KMS("CRTC[%d] CONNECTORS[%d] ENCODERS[%d]\n", card_res->count_crtcs,
-		  card_res->count_connectors, card_res->count_encoders);
-
 out:
 	mutex_unlock(&dev->mode_config.mutex);
 	return ret;
@@ -2125,11 +2147,9 @@ int drm_mode_getconnector(struct drm_dev
 
 	memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo));
 
-	DRM_DEBUG_KMS("[CONNECTOR:%d:?]\n", out_resp->connector_id);
-
 	mutex_lock(&dev->mode_config.mutex);
 
-	connector = drm_connector_find(dev, out_resp->connector_id);
+	connector = drm_connector_lookup(dev, out_resp->connector_id);
 	if (!connector) {
 		ret = -ENOENT;
 		goto out_unlock;
@@ -2213,6 +2233,7 @@ int drm_mode_getconnector(struct drm_dev
 out:
 	drm_modeset_unlock(&dev->mode_config.connection_mutex);
 
+	drm_connector_unreference(connector);
 out_unlock:
 	mutex_unlock(&dev->mode_config.mutex);
 
@@ -2800,8 +2821,6 @@ int drm_mode_setcrtc(struct drm_device *
 			goto out;
 		}
 
-		drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
-
 		/*
 		 * Check whether the primary plane supports the fb pixel format.
 		 * Drivers not implementing the universal planes API use a
@@ -2857,13 +2876,14 @@ int drm_mode_setcrtc(struct drm_device *
 		}
 
 		for (i = 0; i < crtc_req->count_connectors; i++) {
+			connector_set[i] = NULL;
 			set_connectors_ptr = (uint32_t __user *)(unsigned long)crtc_req->set_connectors_ptr;
 			if (get_user(out_id, &set_connectors_ptr[i])) {
 				ret = -EFAULT;
 				goto out;
 			}
 
-			connector = drm_connector_find(dev, out_id);
+			connector = drm_connector_lookup(dev, out_id);
 			if (!connector) {
 				DRM_DEBUG_KMS("Connector id %d unknown\n",
 						out_id);
@@ -2891,6 +2911,12 @@ out:
 	if (fb)
 		drm_framebuffer_unreference(fb);
 
+	if (connector_set) {
+		for (i = 0; i < crtc_req->count_connectors; i++) {
+			if (connector_set[i])
+				drm_connector_unreference(connector_set[i]);
+		}
+	}
 	kfree(connector_set);
 	drm_mode_destroy(dev, mode);
 	drm_modeset_unlock_all(dev);
@@ -3423,17 +3449,35 @@ int drm_mode_addfb2(struct drm_device *d
 	if (IS_ERR(fb))
 		return PTR_ERR(fb);
 
-	/* Transfer ownership to the filp for reaping on close */
-
 	DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
-	mutex_lock(&file_priv->fbs_lock);
 	r->fb_id = fb->base.id;
+
+	/* Transfer ownership to the filp for reaping on close */
+	mutex_lock(&file_priv->fbs_lock);
 	list_add(&fb->filp_head, &file_priv->fbs);
 	mutex_unlock(&file_priv->fbs_lock);
 
 	return 0;
 }
 
+struct drm_mode_rmfb_work {
+	struct work_struct work;
+	struct list_head fbs;
+};
+
+static void drm_mode_rmfb_work_fn(struct work_struct *w)
+{
+	struct drm_mode_rmfb_work *arg = container_of(w, typeof(*arg), work);
+
+	while (!list_empty(&arg->fbs)) {
+		struct drm_framebuffer *fb =
+			list_first_entry(&arg->fbs, typeof(*fb), filp_head);
+
+		list_del_init(&fb->filp_head);
+		drm_framebuffer_remove(fb);
+	}
+}
+
 /**
  * drm_mode_rmfb - remove an FB from the configuration
  * @dev: drm device for the ioctl
@@ -3458,30 +3502,49 @@ int drm_mode_rmfb(struct drm_device *dev
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 		return -EINVAL;
 
-	mutex_lock(&file_priv->fbs_lock);
-	mutex_lock(&dev->mode_config.fb_lock);
-	fb = __drm_framebuffer_lookup(dev, *id);
+	fb = drm_framebuffer_lookup(dev, *id);
 	if (!fb)
-		goto fail_lookup;
+		return -ENOENT;
 
+	mutex_lock(&file_priv->fbs_lock);
 	list_for_each_entry(fbl, &file_priv->fbs, filp_head)
 		if (fb == fbl)
 			found = 1;
-	if (!found)
-		goto fail_lookup;
+	if (!found) {
+		mutex_unlock(&file_priv->fbs_lock);
+		goto fail_unref;
+	}
 
 	list_del_init(&fb->filp_head);
-	mutex_unlock(&dev->mode_config.fb_lock);
 	mutex_unlock(&file_priv->fbs_lock);
 
+	/* drop the reference we picked up in framebuffer lookup */
 	drm_framebuffer_unreference(fb);
 
-	return 0;
+	/*
+	 * we now own the reference that was stored in the fbs list
+	 *
+	 * drm_framebuffer_remove may fail with -EINTR on pending signals,
+	 * so run this in a separate stack as there's no way to correctly
+	 * handle this after the fb is already removed from the lookup table.
+	 */
+	if (drm_framebuffer_read_refcount(fb) > 1) {
+		struct drm_mode_rmfb_work arg;
 
-fail_lookup:
-	mutex_unlock(&dev->mode_config.fb_lock);
-	mutex_unlock(&file_priv->fbs_lock);
+		INIT_WORK_ONSTACK(&arg.work, drm_mode_rmfb_work_fn);
+		INIT_LIST_HEAD(&arg.fbs);
+		list_add_tail(&fb->filp_head, &arg.fbs);
+
+		schedule_work(&arg.work);
+		flush_work(&arg.work);
+		destroy_work_on_stack(&arg.work);
+	} else
+		drm_framebuffer_unreference(fb);
 
+	return 0;
+
+fail_unref:
+	drm_framebuffer_unreference(fb);
 	return -ENOENT;
 }
 
@@ -3627,7 +3690,6 @@ out_err1:
 	return ret;
 }
 
-
 /**
  * drm_fb_release - remove and free the FBs on this file
  * @priv: drm file for the ioctl
@@ -3642,6 +3704,9 @@ out_err1:
 void drm_fb_release(struct drm_file *priv)
 {
 	struct drm_framebuffer *fb, *tfb;
+	struct drm_mode_rmfb_work arg;
+
+	INIT_LIST_HEAD(&arg.fbs);
 
 	/*
 	 * When the file gets released that means no one else can access the fb
@@ -3654,10 +3719,22 @@ void drm_fb_release(struct drm_file *pri
 	 * at it any more.
 	 */
 	list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) {
-		list_del_init(&fb->filp_head);
+		if (drm_framebuffer_read_refcount(fb) > 1) {
+			list_move_tail(&fb->filp_head, &arg.fbs);
+		} else {
+			list_del_init(&fb->filp_head);
 
-		/* This drops the fpriv->fbs reference. */
-		drm_framebuffer_unreference(fb);
+			/* This drops the fpriv->fbs reference. */
+			drm_framebuffer_unreference(fb);
+		}
+	}
+
+	if (!list_empty(&arg.fbs)) {
+		INIT_WORK_ONSTACK(&arg.work, drm_mode_rmfb_work_fn);
+
+		schedule_work(&arg.work);
+		flush_work(&arg.work);
+		destroy_work_on_stack(&arg.work);
 	}
 }
 
@@ -4029,7 +4106,7 @@ void drm_property_destroy(struct drm_dev
 
 	if (property->num_values)
 		kfree(property->values);
-	drm_mode_object_put(dev, &property->base);
+	drm_mode_object_unregister(dev, &property->base);
 	list_del(&property->head);
 	kfree(property);
 }
@@ -4234,6 +4311,20 @@ done:
 	return ret;
 }
 
+static void drm_property_free_blob(struct kref *kref)
+{
+	struct drm_property_blob *blob =
+		container_of(kref, struct drm_property_blob, base.refcount);
+
+	mutex_lock(&blob->dev->mode_config.blob_lock);
+	list_del(&blob->head_global);
+	mutex_unlock(&blob->dev->mode_config.blob_lock);
+
+	drm_mode_object_unregister(blob->dev, &blob->base);
+
+	kfree(blob);
+}
+
 /**
  * drm_property_create_blob - Create new blob property
  *
@@ -4271,20 +4362,16 @@ drm_property_create_blob(struct drm_devi
 	if (data)
 		memcpy(blob->data, data, length);
 
-	mutex_lock(&dev->mode_config.blob_lock);
-
-	ret = drm_mode_object_get(dev, &blob->base, DRM_MODE_OBJECT_BLOB);
+	ret = drm_mode_object_get_reg(dev, &blob->base, DRM_MODE_OBJECT_BLOB,
+				      true, drm_property_free_blob);
 	if (ret) {
 		kfree(blob);
-		mutex_unlock(&dev->mode_config.blob_lock);
 		return ERR_PTR(-EINVAL);
 	}
 
-	kref_init(&blob->refcount);
-
+	mutex_lock(&dev->mode_config.blob_lock);
 	list_add_tail(&blob->head_global,
 	              &dev->mode_config.property_blob_list);
-
 	mutex_unlock(&dev->mode_config.blob_lock);
 
 	return blob;
@@ -4292,27 +4379,6 @@ drm_property_create_blob(struct drm_devi
 EXPORT_SYMBOL(drm_property_create_blob);
 
 /**
- * drm_property_free_blob - Blob property destructor
- *
- * Internal free function for blob properties; must not be used directly.
- *
- * @kref: Reference
- */
-static void drm_property_free_blob(struct kref *kref)
-{
-	struct drm_property_blob *blob =
-		container_of(kref, struct drm_property_blob, refcount);
-
-	WARN_ON(!mutex_is_locked(&blob->dev->mode_config.blob_lock));
-
-	list_del(&blob->head_global);
-	list_del(&blob->head_file);
-	drm_mode_object_put(blob->dev, &blob->base);
-
-	kfree(blob);
-}
-
-/**
  * drm_property_unreference_blob - Unreference a blob property
  *
  * Drop a reference on a blob property. May free the object.
@@ -4321,42 +4387,14 @@ static void drm_property_free_blob(struc
  */
 void drm_property_unreference_blob(struct drm_property_blob *blob)
 {
-	struct drm_device *dev;
-
 	if (!blob)
 		return;
 
-	dev = blob->dev;
-
-	DRM_DEBUG("%p: blob ID: %d (%d)\n", blob, blob->base.id, atomic_read(&blob->refcount.refcount));
-
-	if (kref_put_mutex(&blob->refcount, drm_property_free_blob,
-			   &dev->mode_config.blob_lock))
-		mutex_unlock(&dev->mode_config.blob_lock);
-	else
-		might_lock(&dev->mode_config.blob_lock);
+	drm_mode_object_unreference(&blob->base);
 }
 EXPORT_SYMBOL(drm_property_unreference_blob);
 
 /**
- * drm_property_unreference_blob_locked - Unreference a blob property with blob_lock held
- *
- * Drop a reference on a blob property. May free the object. This must be
- * called with blob_lock held.
- *
- * @blob: Pointer to blob property
- */
-static void drm_property_unreference_blob_locked(struct drm_property_blob *blob)
-{
-	if (!blob)
-		return;
-
-	DRM_DEBUG("%p: blob ID: %d (%d)\n", blob, blob->base.id, atomic_read(&blob->refcount.refcount));
-
-	kref_put(&blob->refcount, drm_property_free_blob);
-}
-
-/**
  * drm_property_destroy_user_blobs - destroy all blobs created by this client
  * @dev:       DRM device
  * @file_priv: destroy all blobs owned by this file handle
@@ -4366,14 +4404,14 @@ void drm_property_destroy_user_blobs(str
 {
 	struct drm_property_blob *blob, *bt;
 
-	mutex_lock(&dev->mode_config.blob_lock);
-
+	/*
+	 * When the file gets released that means no one else can access the
+	 * blob list any more, so no need to grab dev->blob_lock.
+	 */
 	list_for_each_entry_safe(blob, bt, &file_priv->blobs, head_file) {
 		list_del_init(&blob->head_file);
-		drm_property_unreference_blob_locked(blob);
+		drm_property_unreference_blob(blob);
 	}
-
-	mutex_unlock(&dev->mode_config.blob_lock);
 }
 
 /**
@@ -4385,35 +4423,11 @@ void drm_property_destroy_user_blobs(str
  */
 struct drm_property_blob *drm_property_reference_blob(struct drm_property_blob *blob)
 {
-	DRM_DEBUG("%p: blob ID: %d (%d)\n", blob, blob->base.id, atomic_read(&blob->refcount.refcount));
-	kref_get(&blob->refcount);
+	drm_mode_object_reference(&blob->base);
 	return blob;
 }
 EXPORT_SYMBOL(drm_property_reference_blob);
 
-/*
- * Like drm_property_lookup_blob, but does not return an additional reference.
- * Must be called with blob_lock held.
- */
-static struct drm_property_blob *__drm_property_lookup_blob(struct drm_device *dev,
-							    uint32_t id)
-{
-	struct drm_mode_object *obj = NULL;
-	struct drm_property_blob *blob;
-
-	WARN_ON(!mutex_is_locked(&dev->mode_config.blob_lock));
-
-	mutex_lock(&dev->mode_config.idr_mutex);
-	obj = idr_find(&dev->mode_config.crtc_idr, id);
-	if (!obj || (obj->type != DRM_MODE_OBJECT_BLOB) || (obj->id != id))
-		blob = NULL;
-	else
-		blob = obj_to_blob(obj);
-	mutex_unlock(&dev->mode_config.idr_mutex);
-
-	return blob;
-}
-
 /**
  * drm_property_lookup_blob - look up a blob property and take a reference
  * @dev: drm device
@@ -4426,16 +4440,12 @@ static struct drm_property_blob *__drm_p
 struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev,
 					           uint32_t id)
 {
-	struct drm_property_blob *blob;
-
-	mutex_lock(&dev->mode_config.blob_lock);
-	blob = __drm_property_lookup_blob(dev, id);
-	if (blob) {
-		if (!kref_get_unless_zero(&blob->refcount))
-			blob = NULL;
-	}
-	mutex_unlock(&dev->mode_config.blob_lock);
+	struct drm_mode_object *obj;
+	struct drm_property_blob *blob = NULL;
 
+	obj = _object_find(dev, id, DRM_MODE_OBJECT_BLOB);
+	if (obj)
+		blob = obj_to_blob(obj);
 	return blob;
 }
 EXPORT_SYMBOL(drm_property_lookup_blob);
@@ -4540,26 +4550,21 @@ int drm_mode_getblob_ioctl(struct drm_de
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 		return -EINVAL;
 
-	drm_modeset_lock_all(dev);
-	mutex_lock(&dev->mode_config.blob_lock);
-	blob = __drm_property_lookup_blob(dev, out_resp->blob_id);
-	if (!blob) {
-		ret = -ENOENT;
-		goto done;
-	}
+	blob = drm_property_lookup_blob(dev, out_resp->blob_id);
+	if (!blob)
+		return -ENOENT;
 
 	if (out_resp->length == blob->length) {
 		blob_ptr = (void __user *)(unsigned long)out_resp->data;
 		if (copy_to_user(blob_ptr, blob->data, blob->length)) {
 			ret = -EFAULT;
-			goto done;
+			goto unref;
 		}
 	}
 	out_resp->length = blob->length;
+unref:
+	drm_property_unreference_blob(blob);
 
-done:
-	mutex_unlock(&dev->mode_config.blob_lock);
-	drm_modeset_unlock_all(dev);
 	return ret;
 }
 
@@ -4638,13 +4643,11 @@ int drm_mode_destroyblob_ioctl(struct dr
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 		return -EINVAL;
 
-	mutex_lock(&dev->mode_config.blob_lock);
-	blob = __drm_property_lookup_blob(dev, out_resp->blob_id);
-	if (!blob) {
-		ret = -ENOENT;
-		goto err;
-	}
+	blob = drm_property_lookup_blob(dev, out_resp->blob_id);
+	if (!blob)
+		return -ENOENT;
 
+	mutex_lock(&dev->mode_config.blob_lock);
 	/* Ensure the property was actually created by this user. */
 	list_for_each_entry(bt, &file_priv->blobs, head_file) {
 		if (bt == blob) {
@@ -4661,13 +4664,18 @@ int drm_mode_destroyblob_ioctl(struct dr
 	/* We must drop head_file here, because we may not be the last
 	 * reference on the blob. */
 	list_del_init(&blob->head_file);
-	drm_property_unreference_blob_locked(blob);
 	mutex_unlock(&dev->mode_config.blob_lock);
 
+	/* One reference from lookup, and one from the filp. */
+	drm_property_unreference_blob(blob);
+	drm_property_unreference_blob(blob);
+
 	return 0;
 
 err:
 	mutex_unlock(&dev->mode_config.blob_lock);
+	drm_property_unreference_blob(blob);
+
 	return ret;
 }
 
@@ -4831,19 +4839,8 @@ bool drm_property_change_valid_get(struc
 		if (value == 0)
 			return true;
 
-		/* handle refcnt'd objects specially: */
-		if (property->values[0] == DRM_MODE_OBJECT_FB) {
-			struct drm_framebuffer *fb;
-			fb = drm_framebuffer_lookup(property->dev, value);
-			if (fb) {
-				*ref = &fb->base;
-				return true;
-			} else {
-				return false;
-			}
-		} else {
-			return _object_find(property->dev, value, property->values[0]) != NULL;
-		}
+		*ref = _object_find(property->dev, value, property->values[0]);
+		return *ref != NULL;
 	}
 
 	for (i = 0; i < property->num_values; i++)
@@ -4859,8 +4856,7 @@ void drm_property_change_valid_put(struc
 		return;
 
 	if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
-		if (property->values[0] == DRM_MODE_OBJECT_FB)
-			drm_framebuffer_unreference(obj_to_fb(ref));
+		drm_mode_object_unreference(ref);
 	} else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB))
 		drm_property_unreference_blob(obj_to_blob(ref));
 }
@@ -4991,7 +4987,7 @@ int drm_mode_obj_get_properties_ioctl(st
 	}
 	if (!obj->properties) {
 		ret = -EINVAL;
-		goto out;
+		goto out_unref;
 	}
 
 	ret = get_properties(obj, file_priv->atomic,
@@ -4999,6 +4995,8 @@ int drm_mode_obj_get_properties_ioctl(st
 			(uint64_t __user *)(unsigned long)(arg->prop_values_ptr),
 			&arg->count_props);
 
+out_unref:
+	drm_mode_object_unreference(obj);
 out:
 	drm_modeset_unlock_all(dev);
 	return ret;
@@ -5041,25 +5039,25 @@ int drm_mode_obj_set_property_ioctl(stru
 		goto out;
 	}
 	if (!arg_obj->properties)
-		goto out;
+		goto out_unref;
 
 	for (i = 0; i < arg_obj->properties->count; i++)
 		if (arg_obj->properties->properties[i]->base.id == arg->prop_id)
 			break;
 
 	if (i == arg_obj->properties->count)
-		goto out;
+		goto out_unref;
 
 	prop_obj = drm_mode_object_find(dev, arg->prop_id,
 					DRM_MODE_OBJECT_PROPERTY);
 	if (!prop_obj) {
 		ret = -ENOENT;
-		goto out;
+		goto out_unref;
 	}
 	property = obj_to_property(prop_obj);
 
 	if (!drm_property_change_valid_get(property, arg->value, &ref))
-		goto out;
+		goto out_unref;
 
 	switch (arg_obj->type) {
 	case DRM_MODE_OBJECT_CONNECTOR:
@@ -5077,6 +5075,8 @@ int drm_mode_obj_set_property_ioctl(stru
 
 	drm_property_change_valid_put(property, ref);
 
+out_unref:
+	drm_mode_object_unreference(arg_obj);
 out:
 	drm_modeset_unlock_all(dev);
 	return ret;
@@ -5914,6 +5914,15 @@ void drm_mode_config_cleanup(struct drm_
 		drm_property_destroy(dev, property);
 	}
 
+	list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list,
+				 head) {
+		plane->funcs->destroy(plane);
+	}
+
+	list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) {
+		crtc->funcs->destroy(crtc);
+	}
+
 	list_for_each_entry_safe(blob, bt, &dev->mode_config.property_blob_list,
 				 head_global) {
 		drm_property_unreference_blob(blob);
@@ -5929,16 +5938,7 @@ void drm_mode_config_cleanup(struct drm_
 	 */
 	WARN_ON(!list_empty(&dev->mode_config.fb_list));
 	list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) {
-		drm_framebuffer_free(&fb->refcount);
-	}
-
-	list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list,
-				 head) {
-		plane->funcs->destroy(plane);
-	}
-
-	list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) {
-		crtc->funcs->destroy(crtc);
+		drm_framebuffer_free(&fb->base.refcount);
 	}
 
 	ida_destroy(&dev->mode_config.connector_ida);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/drm_crtc_helper.c linux-libre-4.7-gnu/drivers/gpu/drm/drm_crtc_helper.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/drm_crtc_helper.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/drm_crtc_helper.c	2016-07-24 15:23:50.000000000 -0400
@@ -170,11 +170,14 @@ drm_encoder_disable(struct drm_encoder *
 {
 	const struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
 
+	if (!encoder_funcs)
+		return;
+
 	drm_bridge_disable(encoder->bridge);
 
 	if (encoder_funcs->disable)
 		(*encoder_funcs->disable)(encoder);
-	else
+	else if (encoder_funcs->dpms)
 		(*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
 
 	drm_bridge_post_disable(encoder->bridge);
@@ -248,6 +251,9 @@ drm_crtc_prepare_encoders(struct drm_dev
 
 	drm_for_each_encoder(encoder, dev) {
 		encoder_funcs = encoder->helper_private;
+		if (!encoder_funcs)
+			continue;
+
 		/* Disable unused encoders */
 		if (encoder->crtc == NULL)
 			drm_encoder_disable(encoder);
@@ -326,6 +332,10 @@ bool drm_crtc_helper_set_mode(struct drm
 		if (encoder->crtc != crtc)
 			continue;
 
+		encoder_funcs = encoder->helper_private;
+		if (!encoder_funcs)
+			continue;
+
 		ret = drm_bridge_mode_fixup(encoder->bridge,
 			mode, adjusted_mode);
 		if (!ret) {
@@ -360,11 +370,15 @@ bool drm_crtc_helper_set_mode(struct drm
 		if (encoder->crtc != crtc)
 			continue;
 
+		encoder_funcs = encoder->helper_private;
+		if (!encoder_funcs)
+			continue;
+
 		drm_bridge_disable(encoder->bridge);
 
-		encoder_funcs = encoder->helper_private;
 		/* Disable the encoders as the first thing we do. */
-		encoder_funcs->prepare(encoder);
+		if (encoder_funcs->prepare)
+			encoder_funcs->prepare(encoder);
 
 		drm_bridge_post_disable(encoder->bridge);
 	}
@@ -385,11 +399,15 @@ bool drm_crtc_helper_set_mode(struct drm
 		if (encoder->crtc != crtc)
 			continue;
 
+		encoder_funcs = encoder->helper_private;
+		if (!encoder_funcs)
+			continue;
+
 		DRM_DEBUG_KMS("[ENCODER:%d:%s] set [MODE:%d:%s]\n",
 			encoder->base.id, encoder->name,
 			mode->base.id, mode->name);
-		encoder_funcs = encoder->helper_private;
-		encoder_funcs->mode_set(encoder, mode, adjusted_mode);
+		if (encoder_funcs->mode_set)
+			encoder_funcs->mode_set(encoder, mode, adjusted_mode);
 
 		drm_bridge_mode_set(encoder->bridge, mode, adjusted_mode);
 	}
@@ -402,10 +420,14 @@ bool drm_crtc_helper_set_mode(struct drm
 		if (encoder->crtc != crtc)
 			continue;
 
+		encoder_funcs = encoder->helper_private;
+		if (!encoder_funcs)
+			continue;
+
 		drm_bridge_pre_enable(encoder->bridge);
 
-		encoder_funcs = encoder->helper_private;
-		encoder_funcs->commit(encoder);
+		if (encoder_funcs->commit)
+			encoder_funcs->commit(encoder);
 
 		drm_bridge_enable(encoder->bridge);
 	}
@@ -456,6 +478,9 @@ drm_crtc_helper_disable(struct drm_crtc
 			 * between them is henceforth no longer available.
 			 */
 			connector->dpms = DRM_MODE_DPMS_OFF;
+
+			/* we keep a reference while the encoder is bound */
+			drm_connector_unreference(connector);
 		}
 	}
 
@@ -503,11 +528,11 @@ drm_crtc_helper_disable(struct drm_crtc
 int drm_crtc_helper_set_config(struct drm_mode_set *set)
 {
 	struct drm_device *dev;
-	struct drm_crtc *new_crtc;
-	struct drm_encoder *save_encoders, *new_encoder, *encoder;
+	struct drm_crtc **save_encoder_crtcs, *new_crtc;
+	struct drm_encoder **save_connector_encoders, *new_encoder, *encoder;
 	bool mode_changed = false; /* if true do a full mode set */
 	bool fb_changed = false; /* if true and !mode_changed just do a flip */
-	struct drm_connector *save_connectors, *connector;
+	struct drm_connector *connector;
 	int count = 0, ro, fail = 0;
 	const struct drm_crtc_helper_funcs *crtc_funcs;
 	struct drm_mode_set save_set;
@@ -549,15 +574,15 @@ int drm_crtc_helper_set_config(struct dr
 	 * Allocate space for the backup of all (non-pointer) encoder and
 	 * connector data.
 	 */
-	save_encoders = kzalloc(dev->mode_config.num_encoder *
-				sizeof(struct drm_encoder), GFP_KERNEL);
-	if (!save_encoders)
+	save_encoder_crtcs = kzalloc(dev->mode_config.num_encoder *
+				sizeof(struct drm_crtc *), GFP_KERNEL);
+	if (!save_encoder_crtcs)
 		return -ENOMEM;
 
-	save_connectors = kzalloc(dev->mode_config.num_connector *
-				sizeof(struct drm_connector), GFP_KERNEL);
-	if (!save_connectors) {
-		kfree(save_encoders);
+	save_connector_encoders = kzalloc(dev->mode_config.num_connector *
+				sizeof(struct drm_encoder *), GFP_KERNEL);
+	if (!save_connector_encoders) {
+		kfree(save_encoder_crtcs);
 		return -ENOMEM;
 	}
 
@@ -568,12 +593,12 @@ int drm_crtc_helper_set_config(struct dr
 	 */
 	count = 0;
 	drm_for_each_encoder(encoder, dev) {
-		save_encoders[count++] = *encoder;
+		save_encoder_crtcs[count++] = encoder->crtc;
 	}
 
 	count = 0;
 	drm_for_each_connector(connector, dev) {
-		save_connectors[count++] = *connector;
+		save_connector_encoders[count++] = connector->encoder;
 	}
 
 	save_set.crtc = set->crtc;
@@ -606,6 +631,15 @@ int drm_crtc_helper_set_config(struct dr
 		mode_changed = true;
 	}
 
+	/* take a reference on all unbound connectors in set, reuse the
+	 * already taken reference for bound connectors
+	 */
+	for (ro = 0; ro < set->num_connectors; ro++) {
+		if (set->connectors[ro]->encoder)
+			continue;
+		drm_connector_reference(set->connectors[ro]);
+	}
+
 	/* a) traverse passed in connector list and get encoders for them */
 	count = 0;
 	drm_for_each_connector(connector, dev) {
@@ -724,20 +758,29 @@ int drm_crtc_helper_set_config(struct dr
 		}
 	}
 
-	kfree(save_connectors);
-	kfree(save_encoders);
+	kfree(save_connector_encoders);
+	kfree(save_encoder_crtcs);
 	return 0;
 
 fail:
 	/* Restore all previous data. */
 	count = 0;
 	drm_for_each_encoder(encoder, dev) {
-		*encoder = save_encoders[count++];
+		encoder->crtc = save_encoder_crtcs[count++];
 	}
 
 	count = 0;
 	drm_for_each_connector(connector, dev) {
-		*connector = save_connectors[count++];
+		connector->encoder = save_connector_encoders[count++];
+	}
+
+	/* after fail drop reference on all unbound connectors in set, let
+	 * bound connectors keep their reference
+	 */
+	for (ro = 0; ro < set->num_connectors; ro++) {
+		if (set->connectors[ro]->encoder)
+			continue;
+		drm_connector_unreference(set->connectors[ro]);
 	}
 
 	/* Try to restore the config */
@@ -746,8 +789,8 @@ fail:
 				      save_set.y, save_set.fb))
 		DRM_ERROR("failed to restore config after modeset failure\n");
 
-	kfree(save_connectors);
-	kfree(save_encoders);
+	kfree(save_connector_encoders);
+	kfree(save_encoder_crtcs);
 	return ret;
 }
 EXPORT_SYMBOL(drm_crtc_helper_set_config);
@@ -771,12 +814,15 @@ static void drm_helper_encoder_dpms(stru
 	struct drm_bridge *bridge = encoder->bridge;
 	const struct drm_encoder_helper_funcs *encoder_funcs;
 
+	encoder_funcs = encoder->helper_private;
+	if (!encoder_funcs)
+		return;
+
 	if (mode == DRM_MODE_DPMS_ON)
 		drm_bridge_pre_enable(bridge);
 	else
 		drm_bridge_disable(bridge);
 
-	encoder_funcs = encoder->helper_private;
 	if (encoder_funcs->dpms)
 		encoder_funcs->dpms(encoder, mode);
 
@@ -1053,10 +1099,12 @@ int drm_helper_crtc_mode_set_base(struct
 
 	if (plane->funcs->atomic_duplicate_state)
 		plane_state = plane->funcs->atomic_duplicate_state(plane);
-	else if (plane->state)
+	else {
+		if (!plane->state)
+			drm_atomic_helper_plane_reset(plane);
+
 		plane_state = drm_atomic_helper_plane_duplicate_state(plane);
-	else
-		plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL);
+	}
 	if (!plane_state)
 		return -ENOMEM;
 	plane_state->plane = plane;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/drm_crtc_internal.h linux-libre-4.7-gnu/drivers/gpu/drm/drm_crtc_internal.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/drm_crtc_internal.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/drm_crtc_internal.h	2016-07-24 15:23:50.000000000 -0400
@@ -33,8 +33,8 @@
 
 int drm_mode_object_get(struct drm_device *dev,
 			struct drm_mode_object *obj, uint32_t obj_type);
-void drm_mode_object_put(struct drm_device *dev,
-			 struct drm_mode_object *object);
+void drm_mode_object_unregister(struct drm_device *dev,
+				struct drm_mode_object *object);
 
 /* drm_atomic.c */
 int drm_atomic_get_property(struct drm_mode_object *obj,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/drm_dp_aux_dev.c linux-libre-4.7-gnu/drivers/gpu/drm/drm_dp_aux_dev.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/drm_dp_aux_dev.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/drm_dp_aux_dev.c	2016-07-24 15:23:50.000000000 -0400
@@ -159,6 +159,12 @@ static ssize_t auxdev_read(struct file *
 		uint8_t localbuf[DP_AUX_MAX_PAYLOAD_BYTES];
 		ssize_t todo = min_t(size_t, bytes_pending, sizeof(localbuf));
 
+		if (signal_pending(current)) {
+			res = num_bytes_processed ?
+				num_bytes_processed : -ERESTARTSYS;
+			goto out;
+		}
+
 		res = drm_dp_dpcd_read(aux_dev->aux, *offset, localbuf, todo);
 		if (res <= 0) {
 			res = num_bytes_processed ? num_bytes_processed : res;
@@ -202,6 +208,12 @@ static ssize_t auxdev_write(struct file
 		uint8_t localbuf[DP_AUX_MAX_PAYLOAD_BYTES];
 		ssize_t todo = min_t(size_t, bytes_pending, sizeof(localbuf));
 
+		if (signal_pending(current)) {
+			res = num_bytes_processed ?
+				num_bytes_processed : -ERESTARTSYS;
+			goto out;
+		}
+
 		if (__copy_from_user(localbuf,
 				     buf + num_bytes_processed, todo)) {
 			res = num_bytes_processed ?
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/drm_dp_dual_mode_helper.c linux-libre-4.7-gnu/drivers/gpu/drm/drm_dp_dual_mode_helper.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/drm_dp_dual_mode_helper.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/drm_dp_dual_mode_helper.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,366 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <linux/errno.h>
+#include <linux/export.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <drm/drm_dp_dual_mode_helper.h>
+#include <drm/drmP.h>
+
+/**
+ * DOC: dp dual mode helpers
+ *
+ * Helper functions to deal with DP dual mode (aka. DP++) adaptors.
+ *
+ * Type 1:
+ * Adaptor registers (if any) and the sink DDC bus may be accessed via I2C.
+ *
+ * Type 2:
+ * Adaptor registers and sink DDC bus can be accessed either via I2C or
+ * I2C-over-AUX. Source devices may choose to implement either of these
+ * access methods.
+ */
+
+#define DP_DUAL_MODE_SLAVE_ADDRESS 0x40
+
+/**
+ * drm_dp_dual_mode_read - Read from the DP dual mode adaptor register(s)
+ * @adapter: I2C adapter for the DDC bus
+ * @offset: register offset
+ * @buffer: buffer for return data
+ * @size: sizo of the buffer
+ *
+ * Reads @size bytes from the DP dual mode adaptor registers
+ * starting at @offset.
+ *
+ * Returns:
+ * 0 on success, negative error code on failure
+ */
+ssize_t drm_dp_dual_mode_read(struct i2c_adapter *adapter,
+			      u8 offset, void *buffer, size_t size)
+{
+	struct i2c_msg msgs[] = {
+		{
+			.addr = DP_DUAL_MODE_SLAVE_ADDRESS,
+			.flags = 0,
+			.len = 1,
+			.buf = &offset,
+		},
+		{
+			.addr = DP_DUAL_MODE_SLAVE_ADDRESS,
+			.flags = I2C_M_RD,
+			.len = size,
+			.buf = buffer,
+		},
+	};
+	int ret;
+
+	ret = i2c_transfer(adapter, msgs, ARRAY_SIZE(msgs));
+	if (ret < 0)
+		return ret;
+	if (ret != ARRAY_SIZE(msgs))
+		return -EPROTO;
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_dp_dual_mode_read);
+
+/**
+ * drm_dp_dual_mode_write - Write to the DP dual mode adaptor register(s)
+ * @adapter: I2C adapter for the DDC bus
+ * @offset: register offset
+ * @buffer: buffer for write data
+ * @size: sizo of the buffer
+ *
+ * Writes @size bytes to the DP dual mode adaptor registers
+ * starting at @offset.
+ *
+ * Returns:
+ * 0 on success, negative error code on failure
+ */
+ssize_t drm_dp_dual_mode_write(struct i2c_adapter *adapter,
+			       u8 offset, const void *buffer, size_t size)
+{
+	struct i2c_msg msg = {
+		.addr = DP_DUAL_MODE_SLAVE_ADDRESS,
+		.flags = 0,
+		.len = 1 + size,
+		.buf = NULL,
+	};
+	void *data;
+	int ret;
+
+	data = kmalloc(msg.len, GFP_TEMPORARY);
+	if (!data)
+		return -ENOMEM;
+
+	msg.buf = data;
+
+	memcpy(data, &offset, 1);
+	memcpy(data + 1, buffer, size);
+
+	ret = i2c_transfer(adapter, &msg, 1);
+
+	kfree(data);
+
+	if (ret < 0)
+		return ret;
+	if (ret != 1)
+		return -EPROTO;
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_dp_dual_mode_write);
+
+static bool is_hdmi_adaptor(const char hdmi_id[DP_DUAL_MODE_HDMI_ID_LEN])
+{
+	static const char dp_dual_mode_hdmi_id[DP_DUAL_MODE_HDMI_ID_LEN] =
+		"DP-HDMI ADAPTOR\x04";
+
+	return memcmp(hdmi_id, dp_dual_mode_hdmi_id,
+		      sizeof(dp_dual_mode_hdmi_id)) == 0;
+}
+
+static bool is_type2_adaptor(uint8_t adaptor_id)
+{
+	return adaptor_id == (DP_DUAL_MODE_TYPE_TYPE2 |
+			      DP_DUAL_MODE_REV_TYPE2);
+}
+
+/**
+ * drm_dp_dual_mode_detect - Identify the DP dual mode adaptor
+ * @adapter: I2C adapter for the DDC bus
+ *
+ * Attempt to identify the type of the DP dual mode adaptor used.
+ *
+ * Note that when the answer is @DRM_DP_DUAL_MODE_UNKNOWN it's not
+ * certain whether we're dealing with a native HDMI port or
+ * a type 1 DVI dual mode adaptor. The driver will have to use
+ * some other hardware/driver specific mechanism to make that
+ * distinction.
+ *
+ * Returns:
+ * The type of the DP dual mode adaptor used
+ */
+enum drm_dp_dual_mode_type drm_dp_dual_mode_detect(struct i2c_adapter *adapter)
+{
+	char hdmi_id[DP_DUAL_MODE_HDMI_ID_LEN] = {};
+	uint8_t adaptor_id = 0x00;
+	ssize_t ret;
+
+	/*
+	 * Let's see if the adaptor is there the by reading the
+	 * HDMI ID registers.
+	 *
+	 * Note that type 1 DVI adaptors are not required to implemnt
+	 * any registers, and that presents a problem for detection.
+	 * If the i2c transfer is nacked, we may or may not be dealing
+	 * with a type 1 DVI adaptor. Some other mechanism of detecting
+	 * the presence of the adaptor is required. One way would be
+	 * to check the state of the CONFIG1 pin, Another method would
+	 * simply require the driver to know whether the port is a DP++
+	 * port or a native HDMI port. Both of these methods are entirely
+	 * hardware/driver specific so we can't deal with them here.
+	 */
+	ret = drm_dp_dual_mode_read(adapter, DP_DUAL_MODE_HDMI_ID,
+				    hdmi_id, sizeof(hdmi_id));
+	if (ret)
+		return DRM_DP_DUAL_MODE_UNKNOWN;
+
+	/*
+	 * Sigh. Some (maybe all?) type 1 adaptors are broken and ack
+	 * the offset but ignore it, and instead they just always return
+	 * data from the start of the HDMI ID buffer. So for a broken
+	 * type 1 HDMI adaptor a single byte read will always give us
+	 * 0x44, and for a type 1 DVI adaptor it should give 0x00
+	 * (assuming it implements any registers). Fortunately neither
+	 * of those values will match the type 2 signature of the
+	 * DP_DUAL_MODE_ADAPTOR_ID register so we can proceed with
+	 * the type 2 adaptor detection safely even in the presence
+	 * of broken type 1 adaptors.
+	 */
+	ret = drm_dp_dual_mode_read(adapter, DP_DUAL_MODE_ADAPTOR_ID,
+				    &adaptor_id, sizeof(adaptor_id));
+	if (ret == 0) {
+		if (is_type2_adaptor(adaptor_id)) {
+			if (is_hdmi_adaptor(hdmi_id))
+				return DRM_DP_DUAL_MODE_TYPE2_HDMI;
+			else
+				return DRM_DP_DUAL_MODE_TYPE2_DVI;
+		}
+	}
+
+	if (is_hdmi_adaptor(hdmi_id))
+		return DRM_DP_DUAL_MODE_TYPE1_HDMI;
+	else
+		return DRM_DP_DUAL_MODE_TYPE1_DVI;
+}
+EXPORT_SYMBOL(drm_dp_dual_mode_detect);
+
+/**
+ * drm_dp_dual_mode_max_tmds_clock - Max TMDS clock for DP dual mode adaptor
+ * @type: DP dual mode adaptor type
+ * @adapter: I2C adapter for the DDC bus
+ *
+ * Determine the max TMDS clock the adaptor supports based on the
+ * type of the dual mode adaptor and the DP_DUAL_MODE_MAX_TMDS_CLOCK
+ * register (on type2 adaptors). As some type 1 adaptors have
+ * problems with registers (see comments in drm_dp_dual_mode_detect())
+ * we don't read the register on those, instead we simply assume
+ * a 165 MHz limit based on the specification.
+ *
+ * Returns:
+ * Maximum supported TMDS clock rate for the DP dual mode adaptor in kHz.
+ */
+int drm_dp_dual_mode_max_tmds_clock(enum drm_dp_dual_mode_type type,
+				    struct i2c_adapter *adapter)
+{
+	uint8_t max_tmds_clock;
+	ssize_t ret;
+
+	/* native HDMI so no limit */
+	if (type == DRM_DP_DUAL_MODE_NONE)
+		return 0;
+
+	/*
+	 * Type 1 adaptors are limited to 165MHz
+	 * Type 2 adaptors can tells us their limit
+	 */
+	if (type < DRM_DP_DUAL_MODE_TYPE2_DVI)
+		return 165000;
+
+	ret = drm_dp_dual_mode_read(adapter, DP_DUAL_MODE_MAX_TMDS_CLOCK,
+				    &max_tmds_clock, sizeof(max_tmds_clock));
+	if (ret || max_tmds_clock == 0x00 || max_tmds_clock == 0xff) {
+		DRM_DEBUG_KMS("Failed to query max TMDS clock\n");
+		return 165000;
+	}
+
+	return max_tmds_clock * 5000 / 2;
+}
+EXPORT_SYMBOL(drm_dp_dual_mode_max_tmds_clock);
+
+/**
+ * drm_dp_dual_mode_get_tmds_output - Get the state of the TMDS output buffers in the DP dual mode adaptor
+ * @type: DP dual mode adaptor type
+ * @adapter: I2C adapter for the DDC bus
+ * @enabled: current state of the TMDS output buffers
+ *
+ * Get the state of the TMDS output buffers in the adaptor. For
+ * type2 adaptors this is queried from the DP_DUAL_MODE_TMDS_OEN
+ * register. As some type 1 adaptors have problems with registers
+ * (see comments in drm_dp_dual_mode_detect()) we don't read the
+ * register on those, instead we simply assume that the buffers
+ * are always enabled.
+ *
+ * Returns:
+ * 0 on success, negative error code on failure
+ */
+int drm_dp_dual_mode_get_tmds_output(enum drm_dp_dual_mode_type type,
+				     struct i2c_adapter *adapter,
+				     bool *enabled)
+{
+	uint8_t tmds_oen;
+	ssize_t ret;
+
+	if (type < DRM_DP_DUAL_MODE_TYPE2_DVI) {
+		*enabled = true;
+		return 0;
+	}
+
+	ret = drm_dp_dual_mode_read(adapter, DP_DUAL_MODE_TMDS_OEN,
+				    &tmds_oen, sizeof(tmds_oen));
+	if (ret) {
+		DRM_DEBUG_KMS("Failed to query state of TMDS output buffers\n");
+		return ret;
+	}
+
+	*enabled = !(tmds_oen & DP_DUAL_MODE_TMDS_DISABLE);
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_dp_dual_mode_get_tmds_output);
+
+/**
+ * drm_dp_dual_mode_set_tmds_output - Enable/disable TMDS output buffers in the DP dual mode adaptor
+ * @type: DP dual mode adaptor type
+ * @adapter: I2C adapter for the DDC bus
+ * @enable: enable (as opposed to disable) the TMDS output buffers
+ *
+ * Set the state of the TMDS output buffers in the adaptor. For
+ * type2 this is set via the DP_DUAL_MODE_TMDS_OEN register. As
+ * some type 1 adaptors have problems with registers (see comments
+ * in drm_dp_dual_mode_detect()) we avoid touching the register,
+ * making this function a no-op on type 1 adaptors.
+ *
+ * Returns:
+ * 0 on success, negative error code on failure
+ */
+int drm_dp_dual_mode_set_tmds_output(enum drm_dp_dual_mode_type type,
+				     struct i2c_adapter *adapter, bool enable)
+{
+	uint8_t tmds_oen = enable ? 0 : DP_DUAL_MODE_TMDS_DISABLE;
+	ssize_t ret;
+
+	if (type < DRM_DP_DUAL_MODE_TYPE2_DVI)
+		return 0;
+
+	ret = drm_dp_dual_mode_write(adapter, DP_DUAL_MODE_TMDS_OEN,
+				     &tmds_oen, sizeof(tmds_oen));
+	if (ret) {
+		DRM_DEBUG_KMS("Failed to %s TMDS output buffers\n",
+			      enable ? "enable" : "disable");
+		return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_dp_dual_mode_set_tmds_output);
+
+/**
+ * drm_dp_get_dual_mode_type_name - Get the name of the DP dual mode adaptor type as a string
+ * @type: DP dual mode adaptor type
+ *
+ * Returns:
+ * String representation of the DP dual mode adaptor type
+ */
+const char *drm_dp_get_dual_mode_type_name(enum drm_dp_dual_mode_type type)
+{
+	switch (type) {
+	case DRM_DP_DUAL_MODE_NONE:
+		return "none";
+	case DRM_DP_DUAL_MODE_TYPE1_DVI:
+		return "type 1 DVI";
+	case DRM_DP_DUAL_MODE_TYPE1_HDMI:
+		return "type 1 HDMI";
+	case DRM_DP_DUAL_MODE_TYPE2_DVI:
+		return "type 2 DVI";
+	case DRM_DP_DUAL_MODE_TYPE2_HDMI:
+		return "type 2 HDMI";
+	default:
+		WARN_ON(type != DRM_DP_DUAL_MODE_UNKNOWN);
+		return "unknown";
+	}
+}
+EXPORT_SYMBOL(drm_dp_get_dual_mode_type_name);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/drm_dp_helper.c linux-libre-4.7-gnu/drivers/gpu/drm/drm_dp_helper.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/drm_dp_helper.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/drm_dp_helper.c	2016-07-24 15:23:50.000000000 -0400
@@ -178,8 +178,8 @@ static int drm_dp_dpcd_access(struct drm
 			      unsigned int offset, void *buffer, size_t size)
 {
 	struct drm_dp_aux_msg msg;
-	unsigned int retry;
-	int err = 0;
+	unsigned int retry, native_reply;
+	int err = 0, ret = 0;
 
 	memset(&msg, 0, sizeof(msg));
 	msg.address = offset;
@@ -196,38 +196,39 @@ static int drm_dp_dpcd_access(struct drm
 	 * sufficient, bump to 32 which makes Dell 4k monitors happier.
 	 */
 	for (retry = 0; retry < 32; retry++) {
-
-		err = aux->transfer(aux, &msg);
-		if (err < 0) {
-			if (err == -EBUSY)
-				continue;
-
-			goto unlock;
+		if (ret != 0 && ret != -ETIMEDOUT) {
+			usleep_range(AUX_RETRY_INTERVAL,
+				     AUX_RETRY_INTERVAL + 100);
 		}
 
+		ret = aux->transfer(aux, &msg);
 
-		switch (msg.reply & DP_AUX_NATIVE_REPLY_MASK) {
-		case DP_AUX_NATIVE_REPLY_ACK:
-			if (err < size)
-				err = -EPROTO;
-			goto unlock;
-
-		case DP_AUX_NATIVE_REPLY_NACK:
-			err = -EIO;
-			goto unlock;
+		if (ret > 0) {
+			native_reply = msg.reply & DP_AUX_NATIVE_REPLY_MASK;
+			if (native_reply == DP_AUX_NATIVE_REPLY_ACK) {
+				if (ret == size)
+					goto unlock;
 
-		case DP_AUX_NATIVE_REPLY_DEFER:
-			usleep_range(AUX_RETRY_INTERVAL, AUX_RETRY_INTERVAL + 100);
-			break;
+				ret = -EPROTO;
+			} else
+				ret = -EIO;
 		}
+
+		/*
+		 * We want the error we return to be the error we received on
+		 * the first transaction, since we may get a different error the
+		 * next time we retry
+		 */
+		if (!err)
+			err = ret;
 	}
 
 	DRM_DEBUG_KMS("too many retries, giving up\n");
-	err = -EIO;
+	ret = err;
 
 unlock:
 	mutex_unlock(&aux->hw_mutex);
-	return err;
+	return ret;
 }
 
 /**
@@ -247,6 +248,25 @@ unlock:
 ssize_t drm_dp_dpcd_read(struct drm_dp_aux *aux, unsigned int offset,
 			 void *buffer, size_t size)
 {
+	int ret;
+
+	/*
+	 * HP ZR24w corrupts the first DPCD access after entering power save
+	 * mode. Eg. on a read, the entire buffer will be filled with the same
+	 * byte. Do a throw away read to avoid corrupting anything we care
+	 * about. Afterwards things will work correctly until the monitor
+	 * gets woken up and subsequently re-enters power save mode.
+	 *
+	 * The user pressing any button on the monitor is enough to wake it
+	 * up, so there is no particularly good place to do the workaround.
+	 * We just have to do it before any DPCD access and hope that the
+	 * monitor doesn't power down exactly after the throw away read.
+	 */
+	ret = drm_dp_dpcd_access(aux, DP_AUX_NATIVE_READ, DP_DPCD_REV, buffer,
+				 1);
+	if (ret != 1)
+		return ret;
+
 	return drm_dp_dpcd_access(aux, DP_AUX_NATIVE_READ, offset, buffer,
 				  size);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/drm_dp_mst_topology.c linux-libre-4.7-gnu/drivers/gpu/drm/drm_dp_mst_topology.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/drm_dp_mst_topology.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/drm_dp_mst_topology.c	2016-07-24 15:23:50.000000000 -0400
@@ -2756,7 +2756,7 @@ static void drm_dp_mst_dump_mstb(struct
 
 	seq_printf(m, "%smst: %p, %d\n", prefix, mstb, mstb->num_ports);
 	list_for_each_entry(port, &mstb->ports, next) {
-		seq_printf(m, "%sport: %d: ddps: %d ldps: %d, sdp: %d/%d, %p, conn: %p\n", prefix, port->port_num, port->ddps, port->ldps, port->num_sdp_streams, port->num_sdp_stream_sinks, port, port->connector);
+		seq_printf(m, "%sport: %d: input: %d: pdt: %d, ddps: %d ldps: %d, sdp: %d/%d, %p, conn: %p\n", prefix, port->port_num, port->input, port->pdt, port->ddps, port->ldps, port->num_sdp_streams, port->num_sdp_stream_sinks, port, port->connector);
 		if (port->mstb)
 			drm_dp_mst_dump_mstb(m, port->mstb);
 	}
@@ -2777,6 +2777,16 @@ static bool dump_dp_payload_table(struct
 	return false;
 }
 
+static void fetch_monitor_name(struct drm_dp_mst_topology_mgr *mgr,
+			       struct drm_dp_mst_port *port, char *name,
+			       int namelen)
+{
+	struct edid *mst_edid;
+
+	mst_edid = drm_dp_mst_get_edid(port->connector, mgr, port);
+	drm_edid_get_monitor_name(mst_edid, name, namelen);
+}
+
 /**
  * drm_dp_mst_dump_topology(): dump topology to seq file.
  * @m: seq_file to dump output to
@@ -2789,6 +2799,7 @@ void drm_dp_mst_dump_topology(struct seq
 {
 	int i;
 	struct drm_dp_mst_port *port;
+
 	mutex_lock(&mgr->lock);
 	if (mgr->mst_primary)
 		drm_dp_mst_dump_mstb(m, mgr->mst_primary);
@@ -2797,14 +2808,21 @@ void drm_dp_mst_dump_topology(struct seq
 	mutex_unlock(&mgr->lock);
 
 	mutex_lock(&mgr->payload_lock);
-	seq_printf(m, "vcpi: %lx %lx\n", mgr->payload_mask, mgr->vcpi_mask);
+	seq_printf(m, "vcpi: %lx %lx %d\n", mgr->payload_mask, mgr->vcpi_mask,
+		mgr->max_payloads);
 
 	for (i = 0; i < mgr->max_payloads; i++) {
 		if (mgr->proposed_vcpis[i]) {
+			char name[14];
+
 			port = container_of(mgr->proposed_vcpis[i], struct drm_dp_mst_port, vcpi);
-			seq_printf(m, "vcpi %d: %d %d %d\n", i, port->port_num, port->vcpi.vcpi, port->vcpi.num_slots);
+			fetch_monitor_name(mgr, port, name, sizeof(name));
+			seq_printf(m, "vcpi %d: %d %d %d sink name: %s\n", i,
+				   port->port_num, port->vcpi.vcpi,
+				   port->vcpi.num_slots,
+				   (*name != 0) ? name :  "Unknown");
 		} else
-			seq_printf(m, "vcpi %d:unsed\n", i);
+			seq_printf(m, "vcpi %d:unused\n", i);
 	}
 	for (i = 0; i < mgr->max_payloads; i++) {
 		seq_printf(m, "payload %d: %d, %d, %d\n",
@@ -2844,8 +2862,9 @@ void drm_dp_mst_dump_topology(struct seq
 		for (i = 0; i < 0x3; i++)
 			seq_printf(m, "%02x", buf[i]);
 		seq_printf(m, " devid: ");
-		for (i = 0x3; i < 0x8; i++)
+		for (i = 0x3; i < 0x8 && buf[i]; i++)
 			seq_printf(m, "%c", buf[i]);
+
 		seq_printf(m, " revision: hw: %x.%x sw: %x.%x", buf[0x9] >> 4, buf[0x9] & 0xf, buf[0xa], buf[0xb]);
 		seq_printf(m, "\n");
 		bret = dump_dp_payload_table(mgr, buf);
@@ -2908,11 +2927,9 @@ static void drm_dp_destroy_connector_wor
 		drm_dp_port_teardown_pdt(port, port->pdt);
 
 		if (!port->input && port->vcpi.vcpi > 0) {
-			if (mgr->mst_state) {
-				drm_dp_mst_reset_vcpi_slots(mgr, port);
-				drm_dp_update_payload_part1(mgr);
-				drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi);
-			}
+			drm_dp_mst_reset_vcpi_slots(mgr, port);
+			drm_dp_update_payload_part1(mgr);
+			drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi);
 		}
 
 		kref_put(&port->kref, drm_dp_free_mst_port);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/drm_drv.c linux-libre-4.7-gnu/drivers/gpu/drm/drm_drv.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/drm_drv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/drm_drv.c	2016-07-24 15:23:50.000000000 -0400
@@ -37,13 +37,23 @@
 #include "drm_legacy.h"
 #include "drm_internal.h"
 
-unsigned int drm_debug = 0;	/* bitmask of DRM_UT_x */
+/*
+ * drm_debug: Enable debug output.
+ * Bitmask of DRM_UT_x. See include/drm/drmP.h for details.
+ */
+unsigned int drm_debug = 0;
 EXPORT_SYMBOL(drm_debug);
 
 MODULE_AUTHOR(CORE_AUTHOR);
 MODULE_DESCRIPTION(CORE_DESC);
 MODULE_LICENSE("GPL and additional rights");
-MODULE_PARM_DESC(debug, "Enable debug output");
+MODULE_PARM_DESC(debug, "Enable debug output, where each bit enables a debug category.\n"
+"\t\tBit 0 (0x01) will enable CORE messages (drm core code)\n"
+"\t\tBit 1 (0x02) will enable DRIVER messages (drm controller code)\n"
+"\t\tBit 2 (0x04) will enable KMS messages (modesetting code)\n"
+"\t\tBit 3 (0x08) will enable PRIME messages (prime code)\n"
+"\t\tBit 4 (0x10) will enable ATOMIC messages (atomic code)\n"
+"\t\tBit 5 (0x20) will enable VBL messages (vblank code)");
 module_param_named(debug, drm_debug, int, 0600);
 
 static DEFINE_SPINLOCK(drm_minor_lock);
@@ -111,19 +121,11 @@ static void drm_master_destroy(struct kr
 {
 	struct drm_master *master = container_of(kref, struct drm_master, refcount);
 	struct drm_device *dev = master->minor->dev;
-	struct drm_map_list *r_list, *list_temp;
 
-	mutex_lock(&dev->struct_mutex);
 	if (dev->driver->master_destroy)
 		dev->driver->master_destroy(dev, master);
 
-	list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head) {
-		if (r_list->master == master) {
-			drm_legacy_rmmap_locked(dev, r_list->map);
-			r_list = NULL;
-		}
-	}
-	mutex_unlock(&dev->struct_mutex);
+	drm_legacy_master_rmmaps(dev, master);
 
 	idr_destroy(&master->magic_map);
 	kfree(master->unique);
@@ -588,6 +590,7 @@ struct drm_device *drm_dev_alloc(struct
 	spin_lock_init(&dev->buf_lock);
 	spin_lock_init(&dev->event_lock);
 	mutex_init(&dev->struct_mutex);
+	mutex_init(&dev->filelist_mutex);
 	mutex_init(&dev->ctxlist_mutex);
 	mutex_init(&dev->master_mutex);
 
@@ -715,7 +718,11 @@ EXPORT_SYMBOL(drm_dev_unref);
  *
  * Register the DRM device @dev with the system, advertise device to user-space
  * and start normal device operation. @dev must be allocated via drm_dev_alloc()
- * previously.
+ * previously. Right after drm_dev_register() the driver should call
+ * drm_connector_register_all() to register all connectors in sysfs. This is
+ * a separate call for backward compatibility with drivers still using
+ * the deprecated ->load() callback, where connectors are registered from within
+ * the ->load() callback.
  *
  * Never call this twice on any device!
  *
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/drm_edid.c linux-libre-4.7-gnu/drivers/gpu/drm/drm_edid.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/drm_edid.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/drm_edid.c	2016-07-24 15:23:50.000000000 -0400
@@ -3293,6 +3293,46 @@ monitor_name(struct detailed_timing *t,
 		*(u8 **)data = t->data.other_data.data.str.str;
 }
 
+static int get_monitor_name(struct edid *edid, char name[13])
+{
+	char *edid_name = NULL;
+	int mnl;
+
+	if (!edid || !name)
+		return 0;
+
+	drm_for_each_detailed_block((u8 *)edid, monitor_name, &edid_name);
+	for (mnl = 0; edid_name && mnl < 13; mnl++) {
+		if (edid_name[mnl] == 0x0a)
+			break;
+
+		name[mnl] = edid_name[mnl];
+	}
+
+	return mnl;
+}
+
+/**
+ * drm_edid_get_monitor_name - fetch the monitor name from the edid
+ * @edid: monitor EDID information
+ * @name: pointer to a character array to hold the name of the monitor
+ * @bufsize: The size of the name buffer (should be at least 14 chars.)
+ *
+ */
+void drm_edid_get_monitor_name(struct edid *edid, char *name, int bufsize)
+{
+	int name_length;
+	char buf[13];
+	
+	if (bufsize <= 0)
+		return;
+
+	name_length = min(get_monitor_name(edid, buf), bufsize - 1);
+	memcpy(name, buf, name_length);
+	name[name_length] = '\0';
+}
+EXPORT_SYMBOL(drm_edid_get_monitor_name);
+
 /**
  * drm_edid_to_eld - build ELD from EDID
  * @connector: connector corresponding to the HDMI/DP sink
@@ -3306,7 +3346,6 @@ void drm_edid_to_eld(struct drm_connecto
 {
 	uint8_t *eld = connector->eld;
 	u8 *cea;
-	u8 *name;
 	u8 *db;
 	int total_sad_count = 0;
 	int mnl;
@@ -3320,14 +3359,8 @@ void drm_edid_to_eld(struct drm_connecto
 		return;
 	}
 
-	name = NULL;
-	drm_for_each_detailed_block((u8 *)edid, monitor_name, &name);
-	/* max: 13 bytes EDID, 16 bytes ELD */
-	for (mnl = 0; name && mnl < 13; mnl++) {
-		if (name[mnl] == 0x0a)
-			break;
-		eld[20 + mnl] = name[mnl];
-	}
+	mnl = get_monitor_name(edid, eld + 20);
+
 	eld[4] = (cea[1] << 5) | mnl;
 	DRM_DEBUG_KMS("ELD monitor %s\n", eld + 20);
 
@@ -3868,6 +3901,133 @@ static void drm_add_display_info(struct
 		info->color_formats |= DRM_COLOR_FORMAT_YCRCB422;
 }
 
+static int validate_displayid(u8 *displayid, int length, int idx)
+{
+	int i;
+	u8 csum = 0;
+	struct displayid_hdr *base;
+
+	base = (struct displayid_hdr *)&displayid[idx];
+
+	DRM_DEBUG_KMS("base revision 0x%x, length %d, %d %d\n",
+		      base->rev, base->bytes, base->prod_id, base->ext_count);
+
+	if (base->bytes + 5 > length - idx)
+		return -EINVAL;
+	for (i = idx; i <= base->bytes + 5; i++) {
+		csum += displayid[i];
+	}
+	if (csum) {
+		DRM_ERROR("DisplayID checksum invalid, remainder is %d\n", csum);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static struct drm_display_mode *drm_mode_displayid_detailed(struct drm_device *dev,
+							    struct displayid_detailed_timings_1 *timings)
+{
+	struct drm_display_mode *mode;
+	unsigned pixel_clock = (timings->pixel_clock[0] |
+				(timings->pixel_clock[1] << 8) |
+				(timings->pixel_clock[2] << 16));
+	unsigned hactive = (timings->hactive[0] | timings->hactive[1] << 8) + 1;
+	unsigned hblank = (timings->hblank[0] | timings->hblank[1] << 8) + 1;
+	unsigned hsync = (timings->hsync[0] | (timings->hsync[1] & 0x7f) << 8) + 1;
+	unsigned hsync_width = (timings->hsw[0] | timings->hsw[1] << 8) + 1;
+	unsigned vactive = (timings->vactive[0] | timings->vactive[1] << 8) + 1;
+	unsigned vblank = (timings->vblank[0] | timings->vblank[1] << 8) + 1;
+	unsigned vsync = (timings->vsync[0] | (timings->vsync[1] & 0x7f) << 8) + 1;
+	unsigned vsync_width = (timings->vsw[0] | timings->vsw[1] << 8) + 1;
+	bool hsync_positive = (timings->hsync[1] >> 7) & 0x1;
+	bool vsync_positive = (timings->vsync[1] >> 7) & 0x1;
+	mode = drm_mode_create(dev);
+	if (!mode)
+		return NULL;
+
+	mode->clock = pixel_clock * 10;
+	mode->hdisplay = hactive;
+	mode->hsync_start = mode->hdisplay + hsync;
+	mode->hsync_end = mode->hsync_start + hsync_width;
+	mode->htotal = mode->hdisplay + hblank;
+
+	mode->vdisplay = vactive;
+	mode->vsync_start = mode->vdisplay + vsync;
+	mode->vsync_end = mode->vsync_start + vsync_width;
+	mode->vtotal = mode->vdisplay + vblank;
+
+	mode->flags = 0;
+	mode->flags |= hsync_positive ? DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
+	mode->flags |= vsync_positive ? DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
+	mode->type = DRM_MODE_TYPE_DRIVER;
+
+	if (timings->flags & 0x80)
+		mode->type |= DRM_MODE_TYPE_PREFERRED;
+	mode->vrefresh = drm_mode_vrefresh(mode);
+	drm_mode_set_name(mode);
+
+	return mode;
+}
+
+static int add_displayid_detailed_1_modes(struct drm_connector *connector,
+					  struct displayid_block *block)
+{
+	struct displayid_detailed_timing_block *det = (struct displayid_detailed_timing_block *)block;
+	int i;
+	int num_timings;
+	struct drm_display_mode *newmode;
+	int num_modes = 0;
+	/* blocks must be multiple of 20 bytes length */
+	if (block->num_bytes % 20)
+		return 0;
+
+	num_timings = block->num_bytes / 20;
+	for (i = 0; i < num_timings; i++) {
+		struct displayid_detailed_timings_1 *timings = &det->timings[i];
+
+		newmode = drm_mode_displayid_detailed(connector->dev, timings);
+		if (!newmode)
+			continue;
+
+		drm_mode_probed_add(connector, newmode);
+		num_modes++;
+	}
+	return num_modes;
+}
+
+static int add_displayid_detailed_modes(struct drm_connector *connector,
+					struct edid *edid)
+{
+	u8 *displayid;
+	int ret;
+	int idx = 1;
+	int length = EDID_LENGTH;
+	struct displayid_block *block;
+	int num_modes = 0;
+
+	displayid = drm_find_displayid_extension(edid);
+	if (!displayid)
+		return 0;
+
+	ret = validate_displayid(displayid, length, idx);
+	if (ret)
+		return 0;
+
+	idx += sizeof(struct displayid_hdr);
+	while (block = (struct displayid_block *)&displayid[idx],
+	       idx + sizeof(struct displayid_block) <= length &&
+	       idx + sizeof(struct displayid_block) + block->num_bytes <= length &&
+	       block->num_bytes > 0) {
+		idx += block->num_bytes + sizeof(struct displayid_block);
+		switch (block->tag) {
+		case DATA_BLOCK_TYPE_1_DETAILED_TIMING:
+			num_modes += add_displayid_detailed_1_modes(connector, block);
+			break;
+		}
+	}
+	return num_modes;
+}
+
 /**
  * drm_add_edid_modes - add modes from EDID data, if available
  * @connector: connector we're probing
@@ -3913,6 +4073,7 @@ int drm_add_edid_modes(struct drm_connec
 	num_modes += add_established_modes(connector, edid);
 	num_modes += add_cea_modes(connector, edid);
 	num_modes += add_alternate_cea_modes(connector, edid);
+	num_modes += add_displayid_detailed_modes(connector, edid);
 	if (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF)
 		num_modes += add_inferred_modes(connector, edid);
 
@@ -4119,96 +4280,98 @@ drm_hdmi_vendor_infoframe_from_display_m
 }
 EXPORT_SYMBOL(drm_hdmi_vendor_infoframe_from_display_mode);
 
-static int drm_parse_display_id(struct drm_connector *connector,
-				u8 *displayid, int length,
-				bool is_edid_extension)
+static int drm_parse_tiled_block(struct drm_connector *connector,
+				 struct displayid_block *block)
 {
-	/* if this is an EDID extension the first byte will be 0x70 */
-	int idx = 0;
-	struct displayid_hdr *base;
-	struct displayid_block *block;
-	u8 csum = 0;
-	int i;
-
-	if (is_edid_extension)
-		idx = 1;
-
-	base = (struct displayid_hdr *)&displayid[idx];
+	struct displayid_tiled_block *tile = (struct displayid_tiled_block *)block;
+	u16 w, h;
+	u8 tile_v_loc, tile_h_loc;
+	u8 num_v_tile, num_h_tile;
+	struct drm_tile_group *tg;
 
-	DRM_DEBUG_KMS("base revision 0x%x, length %d, %d %d\n",
-		      base->rev, base->bytes, base->prod_id, base->ext_count);
+	w = tile->tile_size[0] | tile->tile_size[1] << 8;
+	h = tile->tile_size[2] | tile->tile_size[3] << 8;
 
-	if (base->bytes + 5 > length - idx)
-		return -EINVAL;
+	num_v_tile = (tile->topo[0] & 0xf) | (tile->topo[2] & 0x30);
+	num_h_tile = (tile->topo[0] >> 4) | ((tile->topo[2] >> 2) & 0x30);
+	tile_v_loc = (tile->topo[1] & 0xf) | ((tile->topo[2] & 0x3) << 4);
+	tile_h_loc = (tile->topo[1] >> 4) | (((tile->topo[2] >> 2) & 0x3) << 4);
 
-	for (i = idx; i <= base->bytes + 5; i++) {
-		csum += displayid[i];
-	}
-	if (csum) {
-		DRM_ERROR("DisplayID checksum invalid, remainder is %d\n", csum);
-		return -EINVAL;
-	}
+	connector->has_tile = true;
+	if (tile->tile_cap & 0x80)
+		connector->tile_is_single_monitor = true;
 
-	block = (struct displayid_block *)&displayid[idx + 4];
-	DRM_DEBUG_KMS("block id %d, rev %d, len %d\n",
-		      block->tag, block->rev, block->num_bytes);
+	connector->num_h_tile = num_h_tile + 1;
+	connector->num_v_tile = num_v_tile + 1;
+	connector->tile_h_loc = tile_h_loc;
+	connector->tile_v_loc = tile_v_loc;
+	connector->tile_h_size = w + 1;
+	connector->tile_v_size = h + 1;
 
-	switch (block->tag) {
-	case DATA_BLOCK_TILED_DISPLAY: {
-		struct displayid_tiled_block *tile = (struct displayid_tiled_block *)block;
+	DRM_DEBUG_KMS("tile cap 0x%x\n", tile->tile_cap);
+	DRM_DEBUG_KMS("tile_size %d x %d\n", w + 1, h + 1);
+	DRM_DEBUG_KMS("topo num tiles %dx%d, location %dx%d\n",
+		      num_h_tile + 1, num_v_tile + 1, tile_h_loc, tile_v_loc);
+	DRM_DEBUG_KMS("vend %c%c%c\n", tile->topology_id[0], tile->topology_id[1], tile->topology_id[2]);
 
-		u16 w, h;
-		u8 tile_v_loc, tile_h_loc;
-		u8 num_v_tile, num_h_tile;
-		struct drm_tile_group *tg;
+	tg = drm_mode_get_tile_group(connector->dev, tile->topology_id);
+	if (!tg) {
+		tg = drm_mode_create_tile_group(connector->dev, tile->topology_id);
+	}
+	if (!tg)
+		return -ENOMEM;
 
-		w = tile->tile_size[0] | tile->tile_size[1] << 8;
-		h = tile->tile_size[2] | tile->tile_size[3] << 8;
+	if (connector->tile_group != tg) {
+		/* if we haven't got a pointer,
+		   take the reference, drop ref to old tile group */
+		if (connector->tile_group) {
+			drm_mode_put_tile_group(connector->dev, connector->tile_group);
+		}
+		connector->tile_group = tg;
+	} else
+		/* if same tile group, then release the ref we just took. */
+		drm_mode_put_tile_group(connector->dev, tg);
+	return 0;
+}
 
-		num_v_tile = (tile->topo[0] & 0xf) | (tile->topo[2] & 0x30);
-		num_h_tile = (tile->topo[0] >> 4) | ((tile->topo[2] >> 2) & 0x30);
-		tile_v_loc = (tile->topo[1] & 0xf) | ((tile->topo[2] & 0x3) << 4);
-		tile_h_loc = (tile->topo[1] >> 4) | (((tile->topo[2] >> 2) & 0x3) << 4);
+static int drm_parse_display_id(struct drm_connector *connector,
+				u8 *displayid, int length,
+				bool is_edid_extension)
+{
+	/* if this is an EDID extension the first byte will be 0x70 */
+	int idx = 0;
+	struct displayid_block *block;
+	int ret;
 
-		connector->has_tile = true;
-		if (tile->tile_cap & 0x80)
-			connector->tile_is_single_monitor = true;
+	if (is_edid_extension)
+		idx = 1;
 
-		connector->num_h_tile = num_h_tile + 1;
-		connector->num_v_tile = num_v_tile + 1;
-		connector->tile_h_loc = tile_h_loc;
-		connector->tile_v_loc = tile_v_loc;
-		connector->tile_h_size = w + 1;
-		connector->tile_v_size = h + 1;
+	ret = validate_displayid(displayid, length, idx);
+	if (ret)
+		return ret;
 
-		DRM_DEBUG_KMS("tile cap 0x%x\n", tile->tile_cap);
-		DRM_DEBUG_KMS("tile_size %d x %d\n", w + 1, h + 1);
-		DRM_DEBUG_KMS("topo num tiles %dx%d, location %dx%d\n",
-		       num_h_tile + 1, num_v_tile + 1, tile_h_loc, tile_v_loc);
-		DRM_DEBUG_KMS("vend %c%c%c\n", tile->topology_id[0], tile->topology_id[1], tile->topology_id[2]);
+	idx += sizeof(struct displayid_hdr);
+	while (block = (struct displayid_block *)&displayid[idx],
+	       idx + sizeof(struct displayid_block) <= length &&
+	       idx + sizeof(struct displayid_block) + block->num_bytes <= length &&
+	       block->num_bytes > 0) {
+		idx += block->num_bytes + sizeof(struct displayid_block);
+		DRM_DEBUG_KMS("block id 0x%x, rev %d, len %d\n",
+			      block->tag, block->rev, block->num_bytes);
 
-		tg = drm_mode_get_tile_group(connector->dev, tile->topology_id);
-		if (!tg) {
-			tg = drm_mode_create_tile_group(connector->dev, tile->topology_id);
+		switch (block->tag) {
+		case DATA_BLOCK_TILED_DISPLAY:
+			ret = drm_parse_tiled_block(connector, block);
+			if (ret)
+				return ret;
+			break;
+		case DATA_BLOCK_TYPE_1_DETAILED_TIMING:
+			/* handled in mode gathering code. */
+			break;
+		default:
+			DRM_DEBUG_KMS("found DisplayID tag 0x%x, unhandled\n", block->tag);
+			break;
 		}
-		if (!tg)
-			return -ENOMEM;
-
-		if (connector->tile_group != tg) {
-			/* if we haven't got a pointer,
-			   take the reference, drop ref to old tile group */
-			if (connector->tile_group) {
-				drm_mode_put_tile_group(connector->dev, connector->tile_group);
-			}
-			connector->tile_group = tg;
-		} else
-			/* if same tile group, then release the ref we just took. */
-			drm_mode_put_tile_group(connector->dev, tg);
-	}
-		break;
-	default:
-		printk("unknown displayid tag %d\n", block->tag);
-		break;
 	}
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/drm_fb_cma_helper.c linux-libre-4.7-gnu/drivers/gpu/drm/drm_fb_cma_helper.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/drm_fb_cma_helper.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/drm_fb_cma_helper.c	2016-07-24 15:23:50.000000000 -0400
@@ -25,6 +25,8 @@
 #include <drm/drm_fb_cma_helper.h>
 #include <linux/module.h>
 
+#define DEFAULT_FBDEFIO_DELAY_MS 50
+
 struct drm_fb_cma {
 	struct drm_framebuffer		fb;
 	struct drm_gem_cma_object	*obj[4];
@@ -35,6 +37,59 @@ struct drm_fbdev_cma {
 	struct drm_fb_cma	*fb;
 };
 
+/**
+ * DOC: framebuffer cma helper functions
+ *
+ * Provides helper functions for creating a cma (contiguous memory allocator)
+ * backed framebuffer.
+ *
+ * drm_fb_cma_create() is used in the &drm_mode_config_funcs ->fb_create
+ * callback function to create a cma backed framebuffer.
+ *
+ * An fbdev framebuffer backed by cma is also available by calling
+ * drm_fbdev_cma_init(). drm_fbdev_cma_fini() tears it down.
+ * If the &drm_framebuffer_funcs ->dirty callback is set, fb_deferred_io
+ * will be set up automatically. dirty() is called by
+ * drm_fb_helper_deferred_io() in process context (struct delayed_work).
+ *
+ * Example fbdev deferred io code:
+ *
+ *     static int driver_fbdev_fb_dirty(struct drm_framebuffer *fb,
+ *                                      struct drm_file *file_priv,
+ *                                      unsigned flags, unsigned color,
+ *                                      struct drm_clip_rect *clips,
+ *                                      unsigned num_clips)
+ *     {
+ *         struct drm_gem_cma_object *cma = drm_fb_cma_get_gem_obj(fb, 0);
+ *         ... push changes ...
+ *         return 0;
+ *     }
+ *
+ *     static struct drm_framebuffer_funcs driver_fbdev_fb_funcs = {
+ *         .destroy       = drm_fb_cma_destroy,
+ *         .create_handle = drm_fb_cma_create_handle,
+ *         .dirty         = driver_fbdev_fb_dirty,
+ *     };
+ *
+ *     static int driver_fbdev_create(struct drm_fb_helper *helper,
+ *             struct drm_fb_helper_surface_size *sizes)
+ *     {
+ *         return drm_fbdev_cma_create_with_funcs(helper, sizes,
+ *                                                &driver_fbdev_fb_funcs);
+ *     }
+ *
+ *     static const struct drm_fb_helper_funcs driver_fb_helper_funcs = {
+ *         .fb_probe = driver_fbdev_create,
+ *     };
+ *
+ *     Initialize:
+ *     fbdev = drm_fbdev_cma_init_with_funcs(dev, 16,
+ *                                           dev->mode_config.num_crtc,
+ *                                           dev->mode_config.num_connector,
+ *                                           &driver_fb_helper_funcs);
+ *
+ */
+
 static inline struct drm_fbdev_cma *to_fbdev_cma(struct drm_fb_helper *helper)
 {
 	return container_of(helper, struct drm_fbdev_cma, fb_helper);
@@ -45,7 +100,7 @@ static inline struct drm_fb_cma *to_fb_c
 	return container_of(fb, struct drm_fb_cma, fb);
 }
 
-static void drm_fb_cma_destroy(struct drm_framebuffer *fb)
+void drm_fb_cma_destroy(struct drm_framebuffer *fb)
 {
 	struct drm_fb_cma *fb_cma = to_fb_cma(fb);
 	int i;
@@ -58,8 +113,9 @@ static void drm_fb_cma_destroy(struct dr
 	drm_framebuffer_cleanup(fb);
 	kfree(fb_cma);
 }
+EXPORT_SYMBOL(drm_fb_cma_destroy);
 
-static int drm_fb_cma_create_handle(struct drm_framebuffer *fb,
+int drm_fb_cma_create_handle(struct drm_framebuffer *fb,
 	struct drm_file *file_priv, unsigned int *handle)
 {
 	struct drm_fb_cma *fb_cma = to_fb_cma(fb);
@@ -67,6 +123,7 @@ static int drm_fb_cma_create_handle(stru
 	return drm_gem_handle_create(file_priv,
 			&fb_cma->obj[0]->base, handle);
 }
+EXPORT_SYMBOL(drm_fb_cma_create_handle);
 
 static struct drm_framebuffer_funcs drm_fb_cma_funcs = {
 	.destroy	= drm_fb_cma_destroy,
@@ -76,7 +133,7 @@ static struct drm_framebuffer_funcs drm_
 static struct drm_fb_cma *drm_fb_cma_alloc(struct drm_device *dev,
 	const struct drm_mode_fb_cmd2 *mode_cmd,
 	struct drm_gem_cma_object **obj,
-	unsigned int num_planes)
+	unsigned int num_planes, const struct drm_framebuffer_funcs *funcs)
 {
 	struct drm_fb_cma *fb_cma;
 	int ret;
@@ -91,7 +148,7 @@ static struct drm_fb_cma *drm_fb_cma_all
 	for (i = 0; i < num_planes; i++)
 		fb_cma->obj[i] = obj[i];
 
-	ret = drm_framebuffer_init(dev, &fb_cma->fb, &drm_fb_cma_funcs);
+	ret = drm_framebuffer_init(dev, &fb_cma->fb, funcs);
 	if (ret) {
 		dev_err(dev->dev, "Failed to initialize framebuffer: %d\n", ret);
 		kfree(fb_cma);
@@ -102,13 +159,17 @@ static struct drm_fb_cma *drm_fb_cma_all
 }
 
 /**
- * drm_fb_cma_create() - (struct drm_mode_config_funcs *)->fb_create callback function
+ * drm_fb_cma_create_with_funcs() - helper function for the
+ *                                  &drm_mode_config_funcs ->fb_create
+ *                                  callback function
  *
- * If your hardware has special alignment or pitch requirements these should be
- * checked before calling this function.
+ * This can be used to set &drm_framebuffer_funcs for drivers that need the
+ * dirty() callback. Use drm_fb_cma_create() if you don't need to change
+ * &drm_framebuffer_funcs.
  */
-struct drm_framebuffer *drm_fb_cma_create(struct drm_device *dev,
-	struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd)
+struct drm_framebuffer *drm_fb_cma_create_with_funcs(struct drm_device *dev,
+	struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd,
+	const struct drm_framebuffer_funcs *funcs)
 {
 	struct drm_fb_cma *fb_cma;
 	struct drm_gem_cma_object *objs[4];
@@ -126,7 +187,7 @@ struct drm_framebuffer *drm_fb_cma_creat
 		unsigned int height = mode_cmd->height / (i ? vsub : 1);
 		unsigned int min_size;
 
-		obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[i]);
+		obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[i]);
 		if (!obj) {
 			dev_err(dev->dev, "Failed to lookup GEM object\n");
 			ret = -ENXIO;
@@ -145,7 +206,7 @@ struct drm_framebuffer *drm_fb_cma_creat
 		objs[i] = to_drm_gem_cma_obj(obj);
 	}
 
-	fb_cma = drm_fb_cma_alloc(dev, mode_cmd, objs, i);
+	fb_cma = drm_fb_cma_alloc(dev, mode_cmd, objs, i, funcs);
 	if (IS_ERR(fb_cma)) {
 		ret = PTR_ERR(fb_cma);
 		goto err_gem_object_unreference;
@@ -158,6 +219,21 @@ err_gem_object_unreference:
 		drm_gem_object_unreference_unlocked(&objs[i]->base);
 	return ERR_PTR(ret);
 }
+EXPORT_SYMBOL_GPL(drm_fb_cma_create_with_funcs);
+
+/**
+ * drm_fb_cma_create() - &drm_mode_config_funcs ->fb_create callback function
+ *
+ * If your hardware has special alignment or pitch requirements these should be
+ * checked before calling this function. Use drm_fb_cma_create_with_funcs() if
+ * you need to set &drm_framebuffer_funcs ->dirty.
+ */
+struct drm_framebuffer *drm_fb_cma_create(struct drm_device *dev,
+	struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd)
+{
+	return drm_fb_cma_create_with_funcs(dev, file_priv, mode_cmd,
+					    &drm_fb_cma_funcs);
+}
 EXPORT_SYMBOL_GPL(drm_fb_cma_create);
 
 /**
@@ -233,8 +309,67 @@ static struct fb_ops drm_fbdev_cma_ops =
 	.fb_setcmap	= drm_fb_helper_setcmap,
 };
 
-static int drm_fbdev_cma_create(struct drm_fb_helper *helper,
-	struct drm_fb_helper_surface_size *sizes)
+static int drm_fbdev_cma_deferred_io_mmap(struct fb_info *info,
+					  struct vm_area_struct *vma)
+{
+	fb_deferred_io_mmap(info, vma);
+	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+
+	return 0;
+}
+
+static int drm_fbdev_cma_defio_init(struct fb_info *fbi,
+				    struct drm_gem_cma_object *cma_obj)
+{
+	struct fb_deferred_io *fbdefio;
+	struct fb_ops *fbops;
+
+	/*
+	 * Per device structures are needed because:
+	 * fbops: fb_deferred_io_cleanup() clears fbops.fb_mmap
+	 * fbdefio: individual delays
+	 */
+	fbdefio = kzalloc(sizeof(*fbdefio), GFP_KERNEL);
+	fbops = kzalloc(sizeof(*fbops), GFP_KERNEL);
+	if (!fbdefio || !fbops) {
+		kfree(fbdefio);
+		return -ENOMEM;
+	}
+
+	/* can't be offset from vaddr since dirty() uses cma_obj */
+	fbi->screen_buffer = cma_obj->vaddr;
+	/* fb_deferred_io_fault() needs a physical address */
+	fbi->fix.smem_start = page_to_phys(virt_to_page(fbi->screen_buffer));
+
+	*fbops = *fbi->fbops;
+	fbi->fbops = fbops;
+
+	fbdefio->delay = msecs_to_jiffies(DEFAULT_FBDEFIO_DELAY_MS);
+	fbdefio->deferred_io = drm_fb_helper_deferred_io;
+	fbi->fbdefio = fbdefio;
+	fb_deferred_io_init(fbi);
+	fbi->fbops->fb_mmap = drm_fbdev_cma_deferred_io_mmap;
+
+	return 0;
+}
+
+static void drm_fbdev_cma_defio_fini(struct fb_info *fbi)
+{
+	if (!fbi->fbdefio)
+		return;
+
+	fb_deferred_io_cleanup(fbi);
+	kfree(fbi->fbdefio);
+	kfree(fbi->fbops);
+}
+
+/*
+ * For use in a (struct drm_fb_helper_funcs *)->fb_probe callback function that
+ * needs custom struct drm_framebuffer_funcs, like dirty() for deferred_io use.
+ */
+int drm_fbdev_cma_create_with_funcs(struct drm_fb_helper *helper,
+	struct drm_fb_helper_surface_size *sizes,
+	const struct drm_framebuffer_funcs *funcs)
 {
 	struct drm_fbdev_cma *fbdev_cma = to_fbdev_cma(helper);
 	struct drm_mode_fb_cmd2 mode_cmd = { 0 };
@@ -270,7 +405,7 @@ static int drm_fbdev_cma_create(struct d
 		goto err_gem_free_object;
 	}
 
-	fbdev_cma->fb = drm_fb_cma_alloc(dev, &mode_cmd, &obj, 1);
+	fbdev_cma->fb = drm_fb_cma_alloc(dev, &mode_cmd, &obj, 1, funcs);
 	if (IS_ERR(fbdev_cma->fb)) {
 		dev_err(dev->dev, "Failed to allocate DRM framebuffer.\n");
 		ret = PTR_ERR(fbdev_cma->fb);
@@ -296,31 +431,48 @@ static int drm_fbdev_cma_create(struct d
 	fbi->screen_size = size;
 	fbi->fix.smem_len = size;
 
+	if (funcs->dirty) {
+		ret = drm_fbdev_cma_defio_init(fbi, obj);
+		if (ret)
+			goto err_cma_destroy;
+	}
+
 	return 0;
 
+err_cma_destroy:
+	drm_framebuffer_unregister_private(&fbdev_cma->fb->fb);
+	drm_fb_cma_destroy(&fbdev_cma->fb->fb);
 err_fb_info_destroy:
 	drm_fb_helper_release_fbi(helper);
 err_gem_free_object:
-	dev->driver->gem_free_object(&obj->base);
+	drm_gem_object_unreference_unlocked(&obj->base);
 	return ret;
 }
+EXPORT_SYMBOL(drm_fbdev_cma_create_with_funcs);
+
+static int drm_fbdev_cma_create(struct drm_fb_helper *helper,
+	struct drm_fb_helper_surface_size *sizes)
+{
+	return drm_fbdev_cma_create_with_funcs(helper, sizes, &drm_fb_cma_funcs);
+}
 
 static const struct drm_fb_helper_funcs drm_fb_cma_helper_funcs = {
 	.fb_probe = drm_fbdev_cma_create,
 };
 
 /**
- * drm_fbdev_cma_init() - Allocate and initializes a drm_fbdev_cma struct
+ * drm_fbdev_cma_init_with_funcs() - Allocate and initializes a drm_fbdev_cma struct
  * @dev: DRM device
  * @preferred_bpp: Preferred bits per pixel for the device
  * @num_crtc: Number of CRTCs
  * @max_conn_count: Maximum number of connectors
+ * @funcs: fb helper functions, in particular fb_probe()
  *
  * Returns a newly allocated drm_fbdev_cma struct or a ERR_PTR.
  */
-struct drm_fbdev_cma *drm_fbdev_cma_init(struct drm_device *dev,
+struct drm_fbdev_cma *drm_fbdev_cma_init_with_funcs(struct drm_device *dev,
 	unsigned int preferred_bpp, unsigned int num_crtc,
-	unsigned int max_conn_count)
+	unsigned int max_conn_count, const struct drm_fb_helper_funcs *funcs)
 {
 	struct drm_fbdev_cma *fbdev_cma;
 	struct drm_fb_helper *helper;
@@ -334,7 +486,7 @@ struct drm_fbdev_cma *drm_fbdev_cma_init
 
 	helper = &fbdev_cma->fb_helper;
 
-	drm_fb_helper_prepare(dev, helper, &drm_fb_cma_helper_funcs);
+	drm_fb_helper_prepare(dev, helper, funcs);
 
 	ret = drm_fb_helper_init(dev, helper, num_crtc, max_conn_count);
 	if (ret < 0) {
@@ -364,6 +516,24 @@ err_free:
 
 	return ERR_PTR(ret);
 }
+EXPORT_SYMBOL_GPL(drm_fbdev_cma_init_with_funcs);
+
+/**
+ * drm_fbdev_cma_init() - Allocate and initializes a drm_fbdev_cma struct
+ * @dev: DRM device
+ * @preferred_bpp: Preferred bits per pixel for the device
+ * @num_crtc: Number of CRTCs
+ * @max_conn_count: Maximum number of connectors
+ *
+ * Returns a newly allocated drm_fbdev_cma struct or a ERR_PTR.
+ */
+struct drm_fbdev_cma *drm_fbdev_cma_init(struct drm_device *dev,
+	unsigned int preferred_bpp, unsigned int num_crtc,
+	unsigned int max_conn_count)
+{
+	return drm_fbdev_cma_init_with_funcs(dev, preferred_bpp, num_crtc,
+				max_conn_count, &drm_fb_cma_helper_funcs);
+}
 EXPORT_SYMBOL_GPL(drm_fbdev_cma_init);
 
 /**
@@ -373,6 +543,7 @@ EXPORT_SYMBOL_GPL(drm_fbdev_cma_init);
 void drm_fbdev_cma_fini(struct drm_fbdev_cma *fbdev_cma)
 {
 	drm_fb_helper_unregister_fbi(&fbdev_cma->fb_helper);
+	drm_fbdev_cma_defio_fini(fbdev_cma->fb_helper.fbdev);
 	drm_fb_helper_release_fbi(&fbdev_cma->fb_helper);
 
 	if (fbdev_cma->fb) {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/drm_fb_helper.c linux-libre-4.7-gnu/drivers/gpu/drm/drm_fb_helper.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/drm_fb_helper.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/drm_fb_helper.c	2016-07-24 15:23:50.000000000 -0400
@@ -84,6 +84,15 @@ static LIST_HEAD(kernel_fb_helper_list);
  * and set up an initial configuration using the detected hardware, drivers
  * should call drm_fb_helper_single_add_all_connectors() followed by
  * drm_fb_helper_initial_config().
+ *
+ * If &drm_framebuffer_funcs ->dirty is set, the
+ * drm_fb_helper_{cfb,sys}_{write,fillrect,copyarea,imageblit} functions will
+ * accumulate changes and schedule &drm_fb_helper ->dirty_work to run right
+ * away. This worker then calls the dirty() function ensuring that it will
+ * always run in process context since the fb_*() function could be running in
+ * atomic context. If drm_fb_helper_deferred_io() is used as the deferred_io
+ * callback it will also schedule dirty_work with the damage collected from the
+ * mmap page writes.
  */
 
 /**
@@ -153,40 +162,13 @@ int drm_fb_helper_add_one_connector(stru
 	if (!fb_helper_connector)
 		return -ENOMEM;
 
+	drm_connector_reference(connector);
 	fb_helper_connector->connector = connector;
 	fb_helper->connector_info[fb_helper->connector_count++] = fb_helper_connector;
 	return 0;
 }
 EXPORT_SYMBOL(drm_fb_helper_add_one_connector);
 
-static void remove_from_modeset(struct drm_mode_set *set,
-		struct drm_connector *connector)
-{
-	int i, j;
-
-	for (i = 0; i < set->num_connectors; i++) {
-		if (set->connectors[i] == connector)
-			break;
-	}
-
-	if (i == set->num_connectors)
-		return;
-
-	for (j = i + 1; j < set->num_connectors; j++) {
-		set->connectors[j - 1] = set->connectors[j];
-	}
-	set->num_connectors--;
-
-	/*
-	 * TODO maybe need to makes sure we set it back to !=NULL somewhere?
-	 */
-	if (set->num_connectors == 0) {
-		set->fb = NULL;
-		drm_mode_destroy(connector->dev, set->mode);
-		set->mode = NULL;
-	}
-}
-
 int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
 				       struct drm_connector *connector)
 {
@@ -206,6 +188,7 @@ int drm_fb_helper_remove_one_connector(s
 	if (i == fb_helper->connector_count)
 		return -EINVAL;
 	fb_helper_connector = fb_helper->connector_info[i];
+	drm_connector_unreference(fb_helper_connector->connector);
 
 	for (j = i + 1; j < fb_helper->connector_count; j++) {
 		fb_helper->connector_info[j - 1] = fb_helper->connector_info[j];
@@ -213,10 +196,6 @@ int drm_fb_helper_remove_one_connector(s
 	fb_helper->connector_count--;
 	kfree(fb_helper_connector);
 
-	/* also cleanup dangling references to the connector: */
-	for (i = 0; i < fb_helper->crtc_count; i++)
-		remove_from_modeset(&fb_helper->crtc_info[i].mode_set, connector);
-
 	return 0;
 }
 EXPORT_SYMBOL(drm_fb_helper_remove_one_connector);
@@ -626,8 +605,10 @@ static void drm_fb_helper_crtc_free(stru
 {
 	int i;
 
-	for (i = 0; i < helper->connector_count; i++)
+	for (i = 0; i < helper->connector_count; i++) {
+		drm_connector_unreference(helper->connector_info[i]->connector);
 		kfree(helper->connector_info[i]);
+	}
 	kfree(helper->connector_info);
 	for (i = 0; i < helper->crtc_count; i++) {
 		kfree(helper->crtc_info[i].mode_set.connectors);
@@ -637,6 +618,23 @@ static void drm_fb_helper_crtc_free(stru
 	kfree(helper->crtc_info);
 }
 
+static void drm_fb_helper_dirty_work(struct work_struct *work)
+{
+	struct drm_fb_helper *helper = container_of(work, struct drm_fb_helper,
+						    dirty_work);
+	struct drm_clip_rect *clip = &helper->dirty_clip;
+	struct drm_clip_rect clip_copy;
+	unsigned long flags;
+
+	spin_lock_irqsave(&helper->dirty_lock, flags);
+	clip_copy = *clip;
+	clip->x1 = clip->y1 = ~0;
+	clip->x2 = clip->y2 = 0;
+	spin_unlock_irqrestore(&helper->dirty_lock, flags);
+
+	helper->fb->funcs->dirty(helper->fb, NULL, 0, 0, &clip_copy, 1);
+}
+
 /**
  * drm_fb_helper_prepare - setup a drm_fb_helper structure
  * @dev: DRM device
@@ -650,6 +648,9 @@ void drm_fb_helper_prepare(struct drm_de
 			   const struct drm_fb_helper_funcs *funcs)
 {
 	INIT_LIST_HEAD(&helper->kernel_fb_list);
+	spin_lock_init(&helper->dirty_lock);
+	INIT_WORK(&helper->dirty_work, drm_fb_helper_dirty_work);
+	helper->dirty_clip.x1 = helper->dirty_clip.y1 = ~0;
 	helper->funcs = funcs;
 	helper->dev = dev;
 }
@@ -834,6 +835,59 @@ void drm_fb_helper_unlink_fbi(struct drm
 }
 EXPORT_SYMBOL(drm_fb_helper_unlink_fbi);
 
+static void drm_fb_helper_dirty(struct fb_info *info, u32 x, u32 y,
+				u32 width, u32 height)
+{
+	struct drm_fb_helper *helper = info->par;
+	struct drm_clip_rect *clip = &helper->dirty_clip;
+	unsigned long flags;
+
+	if (!helper->fb->funcs->dirty)
+		return;
+
+	spin_lock_irqsave(&helper->dirty_lock, flags);
+	clip->x1 = min_t(u32, clip->x1, x);
+	clip->y1 = min_t(u32, clip->y1, y);
+	clip->x2 = max_t(u32, clip->x2, x + width);
+	clip->y2 = max_t(u32, clip->y2, y + height);
+	spin_unlock_irqrestore(&helper->dirty_lock, flags);
+
+	schedule_work(&helper->dirty_work);
+}
+
+/**
+ * drm_fb_helper_deferred_io() - fbdev deferred_io callback function
+ * @info: fb_info struct pointer
+ * @pagelist: list of dirty mmap framebuffer pages
+ *
+ * This function is used as the &fb_deferred_io ->deferred_io
+ * callback function for flushing the fbdev mmap writes.
+ */
+void drm_fb_helper_deferred_io(struct fb_info *info,
+			       struct list_head *pagelist)
+{
+	unsigned long start, end, min, max;
+	struct page *page;
+	u32 y1, y2;
+
+	min = ULONG_MAX;
+	max = 0;
+	list_for_each_entry(page, pagelist, lru) {
+		start = page->index << PAGE_SHIFT;
+		end = start + PAGE_SIZE - 1;
+		min = min(min, start);
+		max = max(max, end);
+	}
+
+	if (min < max) {
+		y1 = min / info->fix.line_length;
+		y2 = min_t(u32, DIV_ROUND_UP(max, info->fix.line_length),
+			   info->var.yres);
+		drm_fb_helper_dirty(info, 0, y1, info->var.xres, y2 - y1);
+	}
+}
+EXPORT_SYMBOL(drm_fb_helper_deferred_io);
+
 /**
  * drm_fb_helper_sys_read - wrapper around fb_sys_read
  * @info: fb_info struct pointer
@@ -862,7 +916,14 @@ EXPORT_SYMBOL(drm_fb_helper_sys_read);
 ssize_t drm_fb_helper_sys_write(struct fb_info *info, const char __user *buf,
 				size_t count, loff_t *ppos)
 {
-	return fb_sys_write(info, buf, count, ppos);
+	ssize_t ret;
+
+	ret = fb_sys_write(info, buf, count, ppos);
+	if (ret > 0)
+		drm_fb_helper_dirty(info, 0, 0, info->var.xres,
+				    info->var.yres);
+
+	return ret;
 }
 EXPORT_SYMBOL(drm_fb_helper_sys_write);
 
@@ -877,6 +938,8 @@ void drm_fb_helper_sys_fillrect(struct f
 				const struct fb_fillrect *rect)
 {
 	sys_fillrect(info, rect);
+	drm_fb_helper_dirty(info, rect->dx, rect->dy,
+			    rect->width, rect->height);
 }
 EXPORT_SYMBOL(drm_fb_helper_sys_fillrect);
 
@@ -891,6 +954,8 @@ void drm_fb_helper_sys_copyarea(struct f
 				const struct fb_copyarea *area)
 {
 	sys_copyarea(info, area);
+	drm_fb_helper_dirty(info, area->dx, area->dy,
+			    area->width, area->height);
 }
 EXPORT_SYMBOL(drm_fb_helper_sys_copyarea);
 
@@ -905,6 +970,8 @@ void drm_fb_helper_sys_imageblit(struct
 				 const struct fb_image *image)
 {
 	sys_imageblit(info, image);
+	drm_fb_helper_dirty(info, image->dx, image->dy,
+			    image->width, image->height);
 }
 EXPORT_SYMBOL(drm_fb_helper_sys_imageblit);
 
@@ -919,6 +986,8 @@ void drm_fb_helper_cfb_fillrect(struct f
 				const struct fb_fillrect *rect)
 {
 	cfb_fillrect(info, rect);
+	drm_fb_helper_dirty(info, rect->dx, rect->dy,
+			    rect->width, rect->height);
 }
 EXPORT_SYMBOL(drm_fb_helper_cfb_fillrect);
 
@@ -933,6 +1002,8 @@ void drm_fb_helper_cfb_copyarea(struct f
 				const struct fb_copyarea *area)
 {
 	cfb_copyarea(info, area);
+	drm_fb_helper_dirty(info, area->dx, area->dy,
+			    area->width, area->height);
 }
 EXPORT_SYMBOL(drm_fb_helper_cfb_copyarea);
 
@@ -947,6 +1018,8 @@ void drm_fb_helper_cfb_imageblit(struct
 				 const struct fb_image *image)
 {
 	cfb_imageblit(info, image);
+	drm_fb_helper_dirty(info, image->dx, image->dy,
+			    image->width, image->height);
 }
 EXPORT_SYMBOL(drm_fb_helper_cfb_imageblit);
 
@@ -1895,7 +1968,6 @@ static int drm_pick_crtcs(struct drm_fb_
 			  int n, int width, int height)
 {
 	int c, o;
-	struct drm_device *dev = fb_helper->dev;
 	struct drm_connector *connector;
 	const struct drm_connector_helper_funcs *connector_funcs;
 	struct drm_encoder *encoder;
@@ -1914,7 +1986,7 @@ static int drm_pick_crtcs(struct drm_fb_
 	if (modes[n] == NULL)
 		return best_score;
 
-	crtcs = kzalloc(dev->mode_config.num_connector *
+	crtcs = kzalloc(fb_helper->connector_count *
 			sizeof(struct drm_fb_helper_crtc *), GFP_KERNEL);
 	if (!crtcs)
 		return best_score;
@@ -1960,7 +2032,7 @@ static int drm_pick_crtcs(struct drm_fb_
 		if (score > best_score) {
 			best_score = score;
 			memcpy(best_crtcs, crtcs,
-			       dev->mode_config.num_connector *
+			       fb_helper->connector_count *
 			       sizeof(struct drm_fb_helper_crtc *));
 		}
 	}
@@ -2104,8 +2176,8 @@ out:
  * cmdline option.
  *
  * The other option is to just disable fbdev emulation since very likely the
- * first modest from userspace will crash in the same way, and is even easier to
- * debug. This can be done by setting the drm_kms_helper.fbdev_emulation=0
+ * first modeset from userspace will crash in the same way, and is even easier
+ * to debug. This can be done by setting the drm_kms_helper.fbdev_emulation=0
  * kernel cmdline option.
  *
  * RETURNS:
@@ -2150,7 +2222,7 @@ EXPORT_SYMBOL(drm_fb_helper_initial_conf
  * hotplug interrupt).
  *
  * Note that drivers may call this even before calling
- * drm_fb_helper_initial_config but only aftert drm_fb_helper_init. This allows
+ * drm_fb_helper_initial_config but only after drm_fb_helper_init. This allows
  * for a race-free fbcon setup and will make sure that the fbdev emulation will
  * not miss any hotplug events.
  *
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/drm_fops.c linux-libre-4.7-gnu/drivers/gpu/drm/drm_fops.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/drm_fops.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/drm_fops.c	2016-07-24 15:23:50.000000000 -0400
@@ -297,9 +297,9 @@ static int drm_open_helper(struct file *
 	}
 	mutex_unlock(&dev->master_mutex);
 
-	mutex_lock(&dev->struct_mutex);
+	mutex_lock(&dev->filelist_mutex);
 	list_add(&priv->lhead, &dev->filelist);
-	mutex_unlock(&dev->struct_mutex);
+	mutex_unlock(&dev->filelist_mutex);
 
 #ifdef __alpha__
 	/*
@@ -381,14 +381,26 @@ static void drm_events_release(struct dr
  */
 static void drm_legacy_dev_reinit(struct drm_device *dev)
 {
-	if (drm_core_check_feature(dev, DRIVER_MODESET))
-		return;
+	if (dev->irq_enabled)
+		drm_irq_uninstall(dev);
+
+	mutex_lock(&dev->struct_mutex);
+
+	drm_legacy_agp_clear(dev);
+
+	drm_legacy_sg_cleanup(dev);
+	drm_legacy_vma_flush(dev);
+	drm_legacy_dma_takedown(dev);
+
+	mutex_unlock(&dev->struct_mutex);
 
 	dev->sigdata.lock = NULL;
 
 	dev->context_flag = 0;
 	dev->last_context = 0;
 	dev->if_version = 0;
+
+	DRM_DEBUG("lastclose completed\n");
 }
 
 /*
@@ -400,7 +412,7 @@ static void drm_legacy_dev_reinit(struct
  *
  * \sa drm_device
  */
-int drm_lastclose(struct drm_device * dev)
+void drm_lastclose(struct drm_device * dev)
 {
 	DRM_DEBUG("\n");
 
@@ -408,23 +420,8 @@ int drm_lastclose(struct drm_device * de
 		dev->driver->lastclose(dev);
 	DRM_DEBUG("driver lastclose completed\n");
 
-	if (dev->irq_enabled && !drm_core_check_feature(dev, DRIVER_MODESET))
-		drm_irq_uninstall(dev);
-
-	mutex_lock(&dev->struct_mutex);
-
-	drm_agp_clear(dev);
-
-	drm_legacy_sg_cleanup(dev);
-	drm_legacy_vma_flush(dev);
-	drm_legacy_dma_takedown(dev);
-
-	mutex_unlock(&dev->struct_mutex);
-
-	drm_legacy_dev_reinit(dev);
-
-	DRM_DEBUG("lastclose completed\n");
-	return 0;
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		drm_legacy_dev_reinit(dev);
 }
 
 /**
@@ -445,14 +442,16 @@ int drm_release(struct inode *inode, str
 	struct drm_file *file_priv = filp->private_data;
 	struct drm_minor *minor = file_priv->minor;
 	struct drm_device *dev = minor->dev;
-	int retcode = 0;
 
 	mutex_lock(&drm_global_mutex);
 
 	DRM_DEBUG("open_count = %d\n", dev->open_count);
 
-	mutex_lock(&dev->struct_mutex);
+	mutex_lock(&dev->filelist_mutex);
 	list_del(&file_priv->lhead);
+	mutex_unlock(&dev->filelist_mutex);
+
+	mutex_lock(&dev->struct_mutex);
 	if (file_priv->magic)
 		idr_remove(&file_priv->master->magic_map, file_priv->magic);
 	mutex_unlock(&dev->struct_mutex);
@@ -538,7 +537,7 @@ int drm_release(struct inode *inode, str
 	 */
 
 	if (!--dev->open_count) {
-		retcode = drm_lastclose(dev);
+		drm_lastclose(dev);
 		if (drm_device_is_unplugged(dev))
 			drm_put_dev(dev);
 	}
@@ -546,7 +545,7 @@ int drm_release(struct inode *inode, str
 
 	drm_minor_release(minor);
 
-	return retcode;
+	return 0;
 }
 EXPORT_SYMBOL(drm_release);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/drm_gem.c linux-libre-4.7-gnu/drivers/gpu/drm/drm_gem.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/drm_gem.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/drm_gem.c	2016-07-24 15:23:50.000000000 -0400
@@ -279,7 +279,6 @@ drm_gem_object_release_handle(int id, vo
 int
 drm_gem_handle_delete(struct drm_file *filp, u32 handle)
 {
-	struct drm_device *dev;
 	struct drm_gem_object *obj;
 
 	/* This is gross. The idr system doesn't let us try a delete and
@@ -294,18 +293,19 @@ drm_gem_handle_delete(struct drm_file *f
 	spin_lock(&filp->table_lock);
 
 	/* Check if we currently have a reference on the object */
-	obj = idr_find(&filp->object_idr, handle);
-	if (obj == NULL) {
-		spin_unlock(&filp->table_lock);
+	obj = idr_replace(&filp->object_idr, NULL, handle);
+	spin_unlock(&filp->table_lock);
+	if (IS_ERR_OR_NULL(obj))
 		return -EINVAL;
-	}
-	dev = obj->dev;
 
-	/* Release reference and decrement refcount. */
+	/* Release driver's reference and decrement refcount. */
+	drm_gem_object_release_handle(handle, obj, filp);
+
+	/* And finally make the handle available for future allocations. */
+	spin_lock(&filp->table_lock);
 	idr_remove(&filp->object_idr, handle);
 	spin_unlock(&filp->table_lock);
 
-	drm_gem_object_release_handle(handle, obj, filp);
 	return 0;
 }
 EXPORT_SYMBOL(drm_gem_handle_delete);
@@ -422,6 +422,10 @@ EXPORT_SYMBOL(drm_gem_handle_create);
  * @obj: obj in question
  *
  * This routine frees fake offsets allocated by drm_gem_create_mmap_offset().
+ *
+ * Note that drm_gem_object_release() already calls this function, so drivers
+ * don't have to take care of releasing the mmap offset themselves when freeing
+ * the GEM object.
  */
 void
 drm_gem_free_mmap_offset(struct drm_gem_object *obj)
@@ -445,6 +449,9 @@ EXPORT_SYMBOL(drm_gem_free_mmap_offset);
  * This routine allocates and attaches a fake offset for @obj, in cases where
  * the virtual size differs from the physical size (ie. obj->size).  Otherwise
  * just use drm_gem_create_mmap_offset().
+ *
+ * This function is idempotent and handles an already allocated mmap offset
+ * transparently. Drivers do not need to check for this case.
  */
 int
 drm_gem_create_mmap_offset_size(struct drm_gem_object *obj, size_t size)
@@ -466,6 +473,9 @@ EXPORT_SYMBOL(drm_gem_create_mmap_offset
  * structures.
  *
  * This routine allocates and attaches a fake offset for @obj.
+ *
+ * Drivers can call drm_gem_free_mmap_offset() before freeing @obj to release
+ * the fake offset again.
  */
 int drm_gem_create_mmap_offset(struct drm_gem_object *obj)
 {
@@ -578,7 +588,6 @@ EXPORT_SYMBOL(drm_gem_put_pages);
 
 /**
  * drm_gem_object_lookup - look up a GEM object from it's handle
- * @dev: DRM device
  * @filp: DRM file private date
  * @handle: userspace handle
  *
@@ -588,8 +597,7 @@ EXPORT_SYMBOL(drm_gem_put_pages);
  * otherwise.
  */
 struct drm_gem_object *
-drm_gem_object_lookup(struct drm_device *dev, struct drm_file *filp,
-		      u32 handle)
+drm_gem_object_lookup(struct drm_file *filp, u32 handle)
 {
 	struct drm_gem_object *obj;
 
@@ -597,12 +605,8 @@ drm_gem_object_lookup(struct drm_device
 
 	/* Check if we currently have a reference on the object */
 	obj = idr_find(&filp->object_idr, handle);
-	if (obj == NULL) {
-		spin_unlock(&filp->table_lock);
-		return NULL;
-	}
-
-	drm_gem_object_reference(obj);
+	if (obj)
+		drm_gem_object_reference(obj);
 
 	spin_unlock(&filp->table_lock);
 
@@ -655,7 +659,7 @@ drm_gem_flink_ioctl(struct drm_device *d
 	if (!drm_core_check_feature(dev, DRIVER_GEM))
 		return -ENODEV;
 
-	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+	obj = drm_gem_object_lookup(file_priv, args->handle);
 	if (obj == NULL)
 		return -ENOENT;
 
@@ -759,6 +763,13 @@ drm_gem_release(struct drm_device *dev,
 	idr_destroy(&file_private->object_idr);
 }
 
+/**
+ * drm_gem_object_release - release GEM buffer object resources
+ * @obj: GEM buffer object
+ *
+ * This releases any structures and resources used by @obj and is the invers of
+ * drm_gem_object_init().
+ */
 void
 drm_gem_object_release(struct drm_gem_object *obj)
 {
@@ -787,14 +798,67 @@ drm_gem_object_free(struct kref *kref)
 		container_of(kref, struct drm_gem_object, refcount);
 	struct drm_device *dev = obj->dev;
 
-	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+	if (dev->driver->gem_free_object_unlocked) {
+		dev->driver->gem_free_object_unlocked(obj);
+	} else if (dev->driver->gem_free_object) {
+		WARN_ON(!mutex_is_locked(&dev->struct_mutex));
 
-	if (dev->driver->gem_free_object != NULL)
 		dev->driver->gem_free_object(obj);
+	}
 }
 EXPORT_SYMBOL(drm_gem_object_free);
 
 /**
+ * drm_gem_object_unreference_unlocked - release a GEM BO reference
+ * @obj: GEM buffer object
+ *
+ * This releases a reference to @obj. Callers must not hold the
+ * dev->struct_mutex lock when calling this function.
+ *
+ * See also __drm_gem_object_unreference().
+ */
+void
+drm_gem_object_unreference_unlocked(struct drm_gem_object *obj)
+{
+	struct drm_device *dev;
+
+	if (!obj)
+		return;
+
+	dev = obj->dev;
+	might_lock(&dev->struct_mutex);
+
+	if (dev->driver->gem_free_object_unlocked)
+		kref_put(&obj->refcount, drm_gem_object_free);
+	else if (kref_put_mutex(&obj->refcount, drm_gem_object_free,
+				&dev->struct_mutex))
+		mutex_unlock(&dev->struct_mutex);
+}
+EXPORT_SYMBOL(drm_gem_object_unreference_unlocked);
+
+/**
+ * drm_gem_object_unreference - release a GEM BO reference
+ * @obj: GEM buffer object
+ *
+ * This releases a reference to @obj. Callers must hold the dev->struct_mutex
+ * lock when calling this function, even when the driver doesn't use
+ * dev->struct_mutex for anything.
+ *
+ * For drivers not encumbered with legacy locking use
+ * drm_gem_object_unreference_unlocked() instead.
+ */
+void
+drm_gem_object_unreference(struct drm_gem_object *obj)
+{
+	if (obj) {
+		WARN_ON(!mutex_is_locked(&obj->dev->struct_mutex));
+
+		kref_put(&obj->refcount, drm_gem_object_free);
+	}
+}
+EXPORT_SYMBOL(drm_gem_object_unreference);
+
+/**
  * drm_gem_vm_open - vma->ops->open implementation for GEM
  * @vma: VM area structure
  *
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/drm_gem_cma_helper.c linux-libre-4.7-gnu/drivers/gpu/drm/drm_gem_cma_helper.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/drm_gem_cma_helper.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/drm_gem_cma_helper.c	2016-07-24 15:23:50.000000000 -0400
@@ -121,7 +121,7 @@ struct drm_gem_cma_object *drm_gem_cma_c
 	return cma_obj;
 
 error:
-	drm->driver->gem_free_object(&cma_obj->base);
+	drm_gem_object_unreference_unlocked(&cma_obj->base);
 	return ERR_PTR(ret);
 }
 EXPORT_SYMBOL_GPL(drm_gem_cma_create);
@@ -162,18 +162,12 @@ drm_gem_cma_create_with_handle(struct dr
 	 * and handle has the id what user can see.
 	 */
 	ret = drm_gem_handle_create(file_priv, gem_obj, handle);
-	if (ret)
-		goto err_handle_create;
-
 	/* drop reference from allocate - handle holds it now. */
 	drm_gem_object_unreference_unlocked(gem_obj);
+	if (ret)
+		return ERR_PTR(ret);
 
 	return cma_obj;
-
-err_handle_create:
-	drm->driver->gem_free_object(gem_obj);
-
-	return ERR_PTR(ret);
 }
 
 /**
@@ -291,7 +285,7 @@ int drm_gem_cma_dumb_map_offset(struct d
 {
 	struct drm_gem_object *gem_obj;
 
-	gem_obj = drm_gem_object_lookup(drm, file_priv, handle);
+	gem_obj = drm_gem_object_lookup(file_priv, handle);
 	if (!gem_obj) {
 		dev_err(drm->dev, "failed to lookup GEM object\n");
 		return -EINVAL;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/drm_info.c linux-libre-4.7-gnu/drivers/gpu/drm/drm_info.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/drm_info.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/drm_info.c	2016-07-24 15:23:50.000000000 -0400
@@ -174,7 +174,7 @@ int drm_clients_info(struct seq_file *m,
 	/* dev->filelist is sorted youngest first, but we want to present
 	 * oldest first (i.e. kernel, servers, clients), so walk backwardss.
 	 */
-	mutex_lock(&dev->struct_mutex);
+	mutex_lock(&dev->filelist_mutex);
 	list_for_each_entry_reverse(priv, &dev->filelist, lhead) {
 		struct task_struct *task;
 
@@ -190,7 +190,7 @@ int drm_clients_info(struct seq_file *m,
 			   priv->magic);
 		rcu_read_unlock();
 	}
-	mutex_unlock(&dev->struct_mutex);
+	mutex_unlock(&dev->filelist_mutex);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/drm_internal.h linux-libre-4.7-gnu/drivers/gpu/drm/drm_internal.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/drm_internal.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/drm_internal.h	2016-07-24 15:23:50.000000000 -0400
@@ -26,7 +26,7 @@ extern unsigned int drm_timestamp_monoto
 
 /* drm_fops.c */
 extern struct mutex drm_global_mutex;
-int drm_lastclose(struct drm_device *dev);
+void drm_lastclose(struct drm_device *dev);
 
 /* drm_pci.c */
 int drm_pci_set_unique(struct drm_device *dev,
@@ -37,8 +37,6 @@ int drm_irq_by_busid(struct drm_device *
 
 /* drm_vm.c */
 int drm_vma_info(struct seq_file *m, void *data);
-void drm_vm_open_locked(struct drm_device *dev, struct vm_area_struct *vma);
-void drm_vm_close_locked(struct drm_device *dev, struct vm_area_struct *vma);
 
 /* drm_prime.c */
 int drm_prime_handle_to_fd_ioctl(struct drm_device *dev, void *data,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/drm_ioctl.c linux-libre-4.7-gnu/drivers/gpu/drm/drm_ioctl.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/drm_ioctl.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/drm_ioctl.c	2016-07-24 15:23:50.000000000 -0400
@@ -150,58 +150,6 @@ static int drm_set_busid(struct drm_devi
 }
 
 /*
- * Get a mapping information.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument, pointing to a drm_map structure.
- *
- * \return zero on success or a negative number on failure.
- *
- * Searches for the mapping with the specified offset and copies its information
- * into userspace
- */
-static int drm_getmap(struct drm_device *dev, void *data,
-	       struct drm_file *file_priv)
-{
-	struct drm_map *map = data;
-	struct drm_map_list *r_list = NULL;
-	struct list_head *list;
-	int idx;
-	int i;
-
-	idx = map->offset;
-	if (idx < 0)
-		return -EINVAL;
-
-	i = 0;
-	mutex_lock(&dev->struct_mutex);
-	list_for_each(list, &dev->maplist) {
-		if (i == idx) {
-			r_list = list_entry(list, struct drm_map_list, head);
-			break;
-		}
-		i++;
-	}
-	if (!r_list || !r_list->map) {
-		mutex_unlock(&dev->struct_mutex);
-		return -EINVAL;
-	}
-
-	map->offset = r_list->map->offset;
-	map->size = r_list->map->size;
-	map->type = r_list->map->type;
-	map->flags = r_list->map->flags;
-	map->handle = (void *)(unsigned long) r_list->user_token;
-	map->mtrr = arch_phys_wc_index(r_list->map->mtrr);
-
-	mutex_unlock(&dev->struct_mutex);
-
-	return 0;
-}
-
-/*
  * Get client information.
  *
  * \param inode device inode.
@@ -558,7 +506,7 @@ static const struct drm_ioctl_desc drm_i
 	DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0),
 	DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0),
 	DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_legacy_getmap_ioctl, DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, DRM_UNLOCKED|DRM_RENDER_ALLOW),
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/drm_irq.c linux-libre-4.7-gnu/drivers/gpu/drm/drm_irq.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/drm_irq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/drm_irq.c	2016-07-24 15:23:50.000000000 -0400
@@ -348,9 +348,6 @@ static void vblank_disable_fn(unsigned l
 	unsigned int pipe = vblank->pipe;
 	unsigned long irqflags;
 
-	if (!dev->vblank_disable_allowed)
-		return;
-
 	spin_lock_irqsave(&dev->vbl_lock, irqflags);
 	if (atomic_read(&vblank->refcount) == 0 && vblank->enabled) {
 		DRM_DEBUG("disabling vblank on crtc %u\n", pipe);
@@ -437,8 +434,6 @@ int drm_vblank_init(struct drm_device *d
 			 "get_vblank_timestamp == NULL\n");
 	}
 
-	dev->vblank_disable_allowed = false;
-
 	return 0;
 
 err:
@@ -863,10 +858,7 @@ int drm_calc_vbltimestamp_from_scanoutpo
 	/* Subtract time delta from raw timestamp to get final
 	 * vblank_time timestamp for end of vblank.
 	 */
-	if (delta_ns < 0)
-		etime = ktime_add_ns(etime, -delta_ns);
-	else
-		etime = ktime_sub_ns(etime, delta_ns);
+	etime = ktime_sub_ns(etime, delta_ns);
 	*vblank_time = ktime_to_timeval(etime);
 
 	DRM_DEBUG_VBL("crtc %u : v 0x%x p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d rep]\n",
@@ -1588,7 +1580,6 @@ void drm_vblank_post_modeset(struct drm_
 
 	if (vblank->inmodeset) {
 		spin_lock_irqsave(&dev->vbl_lock, irqflags);
-		dev->vblank_disable_allowed = true;
 		drm_reset_vblank_timestamp(dev, pipe);
 		spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/drm_legacy.h linux-libre-4.7-gnu/drivers/gpu/drm/drm_legacy.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/drm_legacy.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/drm_legacy.h	2016-07-24 15:23:50.000000000 -0400
@@ -63,6 +63,8 @@ int drm_legacy_getsareactx(struct drm_de
 
 #define DRM_MAP_HASH_OFFSET 0x10000000
 
+int drm_legacy_getmap_ioctl(struct drm_device *dev, void *data,
+			    struct drm_file *file_priv);
 int drm_legacy_addmap_ioctl(struct drm_device *d, void *v, struct drm_file *f);
 int drm_legacy_rmmap_ioctl(struct drm_device *d, void *v, struct drm_file *f);
 int drm_legacy_addbufs(struct drm_device *d, void *v, struct drm_file *f);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/drm_modes.c linux-libre-4.7-gnu/drivers/gpu/drm/drm_modes.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/drm_modes.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/drm_modes.c	2016-07-24 15:23:50.000000000 -0400
@@ -98,7 +98,7 @@ void drm_mode_destroy(struct drm_device
 	if (!mode)
 		return;
 
-	drm_mode_object_put(dev, &mode->base);
+	drm_mode_object_unregister(dev, &mode->base);
 
 	kfree(mode);
 }
@@ -1518,6 +1518,8 @@ int drm_mode_convert_umode(struct drm_di
 	if (out->status != MODE_OK)
 		goto out;
 
+	drm_mode_set_crtcinfo(out, CRTC_INTERLACE_HALVE_V);
+
 	ret = 0;
 
 out:
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/drm_panel.c linux-libre-4.7-gnu/drivers/gpu/drm/drm_panel.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/drm_panel.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/drm_panel.c	2016-07-24 15:23:50.000000000 -0400
@@ -30,12 +30,36 @@
 static DEFINE_MUTEX(panel_lock);
 static LIST_HEAD(panel_list);
 
+/**
+ * DOC: drm panel
+ *
+ * The DRM panel helpers allow drivers to register panel objects with a
+ * central registry and provide functions to retrieve those panels in display
+ * drivers.
+ */
+
+/**
+ * drm_panel_init - initialize a panel
+ * @panel: DRM panel
+ *
+ * Sets up internal fields of the panel so that it can subsequently be added
+ * to the registry.
+ */
 void drm_panel_init(struct drm_panel *panel)
 {
 	INIT_LIST_HEAD(&panel->list);
 }
 EXPORT_SYMBOL(drm_panel_init);
 
+/**
+ * drm_panel_add - add a panel to the global registry
+ * @panel: panel to add
+ *
+ * Add a panel to the global registry so that it can be looked up by display
+ * drivers.
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
 int drm_panel_add(struct drm_panel *panel)
 {
 	mutex_lock(&panel_lock);
@@ -46,6 +70,12 @@ int drm_panel_add(struct drm_panel *pane
 }
 EXPORT_SYMBOL(drm_panel_add);
 
+/**
+ * drm_panel_remove - remove a panel from the global registry
+ * @panel: DRM panel
+ *
+ * Removes a panel from the global registry.
+ */
 void drm_panel_remove(struct drm_panel *panel)
 {
 	mutex_lock(&panel_lock);
@@ -54,6 +84,18 @@ void drm_panel_remove(struct drm_panel *
 }
 EXPORT_SYMBOL(drm_panel_remove);
 
+/**
+ * drm_panel_attach - attach a panel to a connector
+ * @panel: DRM panel
+ * @connector: DRM connector
+ *
+ * After obtaining a pointer to a DRM panel a display driver calls this
+ * function to attach a panel to a connector.
+ *
+ * An error is returned if the panel is already attached to another connector.
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
 int drm_panel_attach(struct drm_panel *panel, struct drm_connector *connector)
 {
 	if (panel->connector)
@@ -66,6 +108,15 @@ int drm_panel_attach(struct drm_panel *p
 }
 EXPORT_SYMBOL(drm_panel_attach);
 
+/**
+ * drm_panel_detach - detach a panel from a connector
+ * @panel: DRM panel
+ *
+ * Detaches a panel from the connector it is attached to. If a panel is not
+ * attached to any connector this is effectively a no-op.
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
 int drm_panel_detach(struct drm_panel *panel)
 {
 	panel->connector = NULL;
@@ -76,6 +127,16 @@ int drm_panel_detach(struct drm_panel *p
 EXPORT_SYMBOL(drm_panel_detach);
 
 #ifdef CONFIG_OF
+/**
+ * of_drm_find_panel - look up a panel using a device tree node
+ * @np: device tree node of the panel
+ *
+ * Searches the set of registered panels for one that matches the given device
+ * tree node. If a matching panel is found, return a pointer to it.
+ *
+ * Return: A pointer to the panel registered for the specified device tree
+ * node or NULL if no panel matching the device tree node can be found.
+ */
 struct drm_panel *of_drm_find_panel(struct device_node *np)
 {
 	struct drm_panel *panel;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/drm_pci.c linux-libre-4.7-gnu/drivers/gpu/drm/drm_pci.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/drm_pci.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/drm_pci.c	2016-07-24 15:23:50.000000000 -0400
@@ -250,7 +250,7 @@ void drm_pci_agp_destroy(struct drm_devi
 {
 	if (dev->agp) {
 		arch_phys_wc_del(dev->agp->agp_mtrr);
-		drm_agp_clear(dev);
+		drm_legacy_agp_clear(dev);
 		kfree(dev->agp);
 		dev->agp = NULL;
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/drm_prime.c linux-libre-4.7-gnu/drivers/gpu/drm/drm_prime.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/drm_prime.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/drm_prime.c	2016-07-24 15:23:50.000000000 -0400
@@ -407,7 +407,7 @@ int drm_gem_prime_handle_to_fd(struct dr
 	struct dma_buf *dmabuf;
 
 	mutex_lock(&file_priv->prime.lock);
-	obj = drm_gem_object_lookup(dev, file_priv, handle);
+	obj = drm_gem_object_lookup(file_priv, handle);
 	if (!obj)  {
 		ret = -ENOENT;
 		goto out_unlock;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/drm_probe_helper.c linux-libre-4.7-gnu/drivers/gpu/drm/drm_probe_helper.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/drm_probe_helper.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/drm_probe_helper.c	2016-07-24 15:23:50.000000000 -0400
@@ -264,10 +264,8 @@ int drm_helper_probe_single_connector_mo
 		count = drm_add_edid_modes(connector, edid);
 		drm_edid_to_eld(connector, edid);
 	} else {
-#ifdef CONFIG_DRM_LOAD_EDID_FIRMWARE
 		count = drm_load_edid_firmware(connector);
 		if (count == 0)
-#endif
 			count = (*connector_funcs->get_modes)(connector);
 	}
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/drm_sysfs.c linux-libre-4.7-gnu/drivers/gpu/drm/drm_sysfs.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/drm_sysfs.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/drm_sysfs.c	2016-07-24 15:23:50.000000000 -0400
@@ -208,9 +208,12 @@ static ssize_t status_show(struct device
 			   char *buf)
 {
 	struct drm_connector *connector = to_drm_connector(device);
+	enum drm_connector_status status;
+
+	status = READ_ONCE(connector->status);
 
 	return snprintf(buf, PAGE_SIZE, "%s\n",
-			drm_get_connector_status_name(connector->status));
+			drm_get_connector_status_name(status));
 }
 
 static ssize_t dpms_show(struct device *device,
@@ -231,9 +234,11 @@ static ssize_t enabled_show(struct devic
 			   char *buf)
 {
 	struct drm_connector *connector = to_drm_connector(device);
+	bool enabled;
 
-	return snprintf(buf, PAGE_SIZE, "%s\n", connector->encoder ? "enabled" :
-			"disabled");
+	enabled = READ_ONCE(connector->encoder);
+
+	return snprintf(buf, PAGE_SIZE, enabled ? "enabled\n" : "disabled\n");
 }
 
 static ssize_t edid_show(struct file *filp, struct kobject *kobj,
@@ -287,102 +292,6 @@ static ssize_t modes_show(struct device
 	return written;
 }
 
-static ssize_t tv_subconnector_show(struct device *device,
-				    struct device_attribute *attr,
-				    char *buf)
-{
-	struct drm_connector *connector = to_drm_connector(device);
-	struct drm_device *dev = connector->dev;
-	struct drm_property *prop;
-	uint64_t subconnector;
-	int ret;
-
-	prop = dev->mode_config.tv_subconnector_property;
-	if (!prop) {
-		DRM_ERROR("Unable to find subconnector property\n");
-		return 0;
-	}
-
-	ret = drm_object_property_get_value(&connector->base, prop, &subconnector);
-	if (ret)
-		return 0;
-
-	return snprintf(buf, PAGE_SIZE, "%s",
-			drm_get_tv_subconnector_name((int)subconnector));
-}
-
-static ssize_t tv_select_subconnector_show(struct device *device,
-					   struct device_attribute *attr,
-					   char *buf)
-{
-	struct drm_connector *connector = to_drm_connector(device);
-	struct drm_device *dev = connector->dev;
-	struct drm_property *prop;
-	uint64_t subconnector;
-	int ret;
-
-	prop = dev->mode_config.tv_select_subconnector_property;
-	if (!prop) {
-		DRM_ERROR("Unable to find select subconnector property\n");
-		return 0;
-	}
-
-	ret = drm_object_property_get_value(&connector->base, prop, &subconnector);
-	if (ret)
-		return 0;
-
-	return snprintf(buf, PAGE_SIZE, "%s",
-			drm_get_tv_select_name((int)subconnector));
-}
-
-static ssize_t dvii_subconnector_show(struct device *device,
-				      struct device_attribute *attr,
-				      char *buf)
-{
-	struct drm_connector *connector = to_drm_connector(device);
-	struct drm_device *dev = connector->dev;
-	struct drm_property *prop;
-	uint64_t subconnector;
-	int ret;
-
-	prop = dev->mode_config.dvi_i_subconnector_property;
-	if (!prop) {
-		DRM_ERROR("Unable to find subconnector property\n");
-		return 0;
-	}
-
-	ret = drm_object_property_get_value(&connector->base, prop, &subconnector);
-	if (ret)
-		return 0;
-
-	return snprintf(buf, PAGE_SIZE, "%s",
-			drm_get_dvi_i_subconnector_name((int)subconnector));
-}
-
-static ssize_t dvii_select_subconnector_show(struct device *device,
-					     struct device_attribute *attr,
-					     char *buf)
-{
-	struct drm_connector *connector = to_drm_connector(device);
-	struct drm_device *dev = connector->dev;
-	struct drm_property *prop;
-	uint64_t subconnector;
-	int ret;
-
-	prop = dev->mode_config.dvi_i_select_subconnector_property;
-	if (!prop) {
-		DRM_ERROR("Unable to find select subconnector property\n");
-		return 0;
-	}
-
-	ret = drm_object_property_get_value(&connector->base, prop, &subconnector);
-	if (ret)
-		return 0;
-
-	return snprintf(buf, PAGE_SIZE, "%s",
-			drm_get_dvi_i_select_name((int)subconnector));
-}
-
 static DEVICE_ATTR_RW(status);
 static DEVICE_ATTR_RO(enabled);
 static DEVICE_ATTR_RO(dpms);
@@ -396,54 +305,6 @@ static struct attribute *connector_dev_a
 	NULL
 };
 
-static DEVICE_ATTR_RO(tv_subconnector);
-static DEVICE_ATTR_RO(tv_select_subconnector);
-
-static struct attribute *connector_tv_dev_attrs[] = {
-	&dev_attr_tv_subconnector.attr,
-	&dev_attr_tv_select_subconnector.attr,
-	NULL
-};
-
-static DEVICE_ATTR_RO(dvii_subconnector);
-static DEVICE_ATTR_RO(dvii_select_subconnector);
-
-static struct attribute *connector_dvii_dev_attrs[] = {
-	&dev_attr_dvii_subconnector.attr,
-	&dev_attr_dvii_select_subconnector.attr,
-	NULL
-};
-
-/* Connector type related helpers */
-static int kobj_connector_type(struct kobject *kobj)
-{
-	struct device *dev = kobj_to_dev(kobj);
-	struct drm_connector *connector = to_drm_connector(dev);
-
-	return connector->connector_type;
-}
-
-static umode_t connector_is_dvii(struct kobject *kobj,
-				 struct attribute *attr, int idx)
-{
-	return kobj_connector_type(kobj) == DRM_MODE_CONNECTOR_DVII ?
-		attr->mode : 0;
-}
-
-static umode_t connector_is_tv(struct kobject *kobj,
-			       struct attribute *attr, int idx)
-{
-	switch (kobj_connector_type(kobj)) {
-	case DRM_MODE_CONNECTOR_Composite:
-	case DRM_MODE_CONNECTOR_SVIDEO:
-	case DRM_MODE_CONNECTOR_Component:
-	case DRM_MODE_CONNECTOR_TV:
-		return attr->mode;
-	}
-
-	return 0;
-}
-
 static struct bin_attribute edid_attr = {
 	.attr.name = "edid",
 	.attr.mode = 0444,
@@ -461,20 +322,8 @@ static const struct attribute_group conn
 	.bin_attrs = connector_bin_attrs,
 };
 
-static const struct attribute_group connector_tv_dev_group = {
-	.attrs = connector_tv_dev_attrs,
-	.is_visible = connector_is_tv,
-};
-
-static const struct attribute_group connector_dvii_dev_group = {
-	.attrs = connector_dvii_dev_attrs,
-	.is_visible = connector_is_dvii,
-};
-
 static const struct attribute_group *connector_dev_groups[] = {
 	&connector_dev_group,
-	&connector_tv_dev_group,
-	&connector_dvii_dev_group,
 	NULL
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/drm_vm.c linux-libre-4.7-gnu/drivers/gpu/drm/drm_vm.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/drm_vm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/drm_vm.c	2016-07-24 15:23:50.000000000 -0400
@@ -395,16 +395,8 @@ static const struct vm_operations_struct
 	.close = drm_vm_close,
 };
 
-/**
- * \c open method for shared virtual memory.
- *
- * \param vma virtual memory area.
- *
- * Create a new drm_vma_entry structure as the \p vma private data entry and
- * add it to drm_device::vmalist.
- */
-void drm_vm_open_locked(struct drm_device *dev,
-		struct vm_area_struct *vma)
+static void drm_vm_open_locked(struct drm_device *dev,
+			       struct vm_area_struct *vma)
 {
 	struct drm_vma_entry *vma_entry;
 
@@ -429,8 +421,8 @@ static void drm_vm_open(struct vm_area_s
 	mutex_unlock(&dev->struct_mutex);
 }
 
-void drm_vm_close_locked(struct drm_device *dev,
-		struct vm_area_struct *vma)
+static void drm_vm_close_locked(struct drm_device *dev,
+				struct vm_area_struct *vma)
 {
 	struct drm_vma_entry *pt, *temp;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/etnaviv/etnaviv_drv.c linux-libre-4.7-gnu/drivers/gpu/drm/etnaviv/etnaviv_drv.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/etnaviv/etnaviv_drv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/etnaviv/etnaviv_drv.c	2016-07-24 15:23:50.000000000 -0400
@@ -314,7 +314,7 @@ static int etnaviv_ioctl_gem_cpu_prep(st
 	if (args->op & ~(ETNA_PREP_READ | ETNA_PREP_WRITE | ETNA_PREP_NOSYNC))
 		return -EINVAL;
 
-	obj = drm_gem_object_lookup(dev, file, args->handle);
+	obj = drm_gem_object_lookup(file, args->handle);
 	if (!obj)
 		return -ENOENT;
 
@@ -335,7 +335,7 @@ static int etnaviv_ioctl_gem_cpu_fini(st
 	if (args->flags)
 		return -EINVAL;
 
-	obj = drm_gem_object_lookup(dev, file, args->handle);
+	obj = drm_gem_object_lookup(file, args->handle);
 	if (!obj)
 		return -ENOENT;
 
@@ -356,7 +356,7 @@ static int etnaviv_ioctl_gem_info(struct
 	if (args->pad)
 		return -EINVAL;
 
-	obj = drm_gem_object_lookup(dev, file, args->handle);
+	obj = drm_gem_object_lookup(file, args->handle);
 	if (!obj)
 		return -ENOENT;
 
@@ -441,7 +441,7 @@ static int etnaviv_ioctl_gem_wait(struct
 	if (!gpu)
 		return -ENXIO;
 
-	obj = drm_gem_object_lookup(dev, file, args->handle);
+	obj = drm_gem_object_lookup(file, args->handle);
 	if (!obj)
 		return -ENOENT;
 
@@ -497,7 +497,7 @@ static struct drm_driver etnaviv_drm_dri
 	.open               = etnaviv_open,
 	.preclose           = etnaviv_preclose,
 	.set_busid          = drm_platform_set_busid,
-	.gem_free_object    = etnaviv_gem_free_object,
+	.gem_free_object_unlocked = etnaviv_gem_free_object,
 	.gem_vm_ops         = &vm_ops,
 	.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
 	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/etnaviv/etnaviv_gem.c linux-libre-4.7-gnu/drivers/gpu/drm/etnaviv/etnaviv_gem.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/etnaviv/etnaviv_gem.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/etnaviv/etnaviv_gem.c	2016-07-24 15:23:50.000000000 -0400
@@ -129,10 +129,9 @@ void etnaviv_gem_put_pages(struct etnavi
 	/* when we start tracking the pin count, then do something here */
 }
 
-static int etnaviv_gem_mmap_obj(struct drm_gem_object *obj,
+static int etnaviv_gem_mmap_obj(struct etnaviv_gem_object *etnaviv_obj,
 		struct vm_area_struct *vma)
 {
-	struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
 	pgprot_t vm_page_prot;
 
 	vma->vm_flags &= ~VM_PFNMAP;
@@ -151,9 +150,9 @@ static int etnaviv_gem_mmap_obj(struct d
 		 * in particular in the case of mmap'd dmabufs)
 		 */
 		fput(vma->vm_file);
-		get_file(obj->filp);
+		get_file(etnaviv_obj->base.filp);
 		vma->vm_pgoff = 0;
-		vma->vm_file  = obj->filp;
+		vma->vm_file  = etnaviv_obj->base.filp;
 
 		vma->vm_page_prot = vm_page_prot;
 	}
@@ -173,7 +172,7 @@ int etnaviv_gem_mmap(struct file *filp,
 	}
 
 	obj = to_etnaviv_bo(vma->vm_private_data);
-	return etnaviv_gem_mmap_obj(vma->vm_private_data, vma);
+	return obj->ops->mmap(obj, vma);
 }
 
 int etnaviv_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
@@ -545,6 +544,7 @@ static const struct etnaviv_gem_ops etna
 	.get_pages = etnaviv_gem_shmem_get_pages,
 	.release = etnaviv_gem_shmem_release,
 	.vmap = etnaviv_gem_vmap_impl,
+	.mmap = etnaviv_gem_mmap_obj,
 };
 
 void etnaviv_gem_free_object(struct drm_gem_object *obj)
@@ -886,10 +886,17 @@ static void etnaviv_gem_userptr_release(
 	put_task_struct(etnaviv_obj->userptr.task);
 }
 
+static int etnaviv_gem_userptr_mmap_obj(struct etnaviv_gem_object *etnaviv_obj,
+		struct vm_area_struct *vma)
+{
+	return -EINVAL;
+}
+
 static const struct etnaviv_gem_ops etnaviv_gem_userptr_ops = {
 	.get_pages = etnaviv_gem_userptr_get_pages,
 	.release = etnaviv_gem_userptr_release,
 	.vmap = etnaviv_gem_vmap_impl,
+	.mmap = etnaviv_gem_userptr_mmap_obj,
 };
 
 int etnaviv_gem_new_userptr(struct drm_device *dev, struct drm_file *file,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/etnaviv/etnaviv_gem.h linux-libre-4.7-gnu/drivers/gpu/drm/etnaviv/etnaviv_gem.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/etnaviv/etnaviv_gem.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/etnaviv/etnaviv_gem.h	2016-07-24 15:23:50.000000000 -0400
@@ -79,6 +79,7 @@ struct etnaviv_gem_ops {
 	int (*get_pages)(struct etnaviv_gem_object *);
 	void (*release)(struct etnaviv_gem_object *);
 	void *(*vmap)(struct etnaviv_gem_object *);
+	int (*mmap)(struct etnaviv_gem_object *, struct vm_area_struct *);
 };
 
 static inline bool is_active(struct etnaviv_gem_object *etnaviv_obj)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c linux-libre-4.7-gnu/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c	2016-07-24 15:23:50.000000000 -0400
@@ -84,10 +84,17 @@ static void *etnaviv_gem_prime_vmap_impl
 	return dma_buf_vmap(etnaviv_obj->base.import_attach->dmabuf);
 }
 
+static int etnaviv_gem_prime_mmap_obj(struct etnaviv_gem_object *etnaviv_obj,
+		struct vm_area_struct *vma)
+{
+	return dma_buf_mmap(etnaviv_obj->base.dma_buf, vma, 0);
+}
+
 static const struct etnaviv_gem_ops etnaviv_gem_prime_ops = {
 	/* .get_pages should never be called */
 	.release = etnaviv_gem_prime_release,
 	.vmap = etnaviv_gem_prime_vmap_impl,
+	.mmap = etnaviv_gem_prime_mmap_obj,
 };
 
 struct drm_gem_object *etnaviv_gem_prime_import_sg_table(struct drm_device *dev,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c linux-libre-4.7-gnu/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c	2016-07-24 15:23:50.000000000 -0400
@@ -28,11 +28,6 @@
 #define BO_LOCKED   0x4000
 #define BO_PINNED   0x2000
 
-static inline void __user *to_user_ptr(u64 address)
-{
-	return (void __user *)(uintptr_t)address;
-}
-
 static struct etnaviv_gem_submit *submit_create(struct drm_device *dev,
 		struct etnaviv_gpu *gpu, size_t nr)
 {
@@ -347,21 +342,21 @@ int etnaviv_ioctl_gem_submit(struct drm_
 	cmdbuf->exec_state = args->exec_state;
 	cmdbuf->ctx = file->driver_priv;
 
-	ret = copy_from_user(bos, to_user_ptr(args->bos),
+	ret = copy_from_user(bos, u64_to_user_ptr(args->bos),
 			     args->nr_bos * sizeof(*bos));
 	if (ret) {
 		ret = -EFAULT;
 		goto err_submit_cmds;
 	}
 
-	ret = copy_from_user(relocs, to_user_ptr(args->relocs),
+	ret = copy_from_user(relocs, u64_to_user_ptr(args->relocs),
 			     args->nr_relocs * sizeof(*relocs));
 	if (ret) {
 		ret = -EFAULT;
 		goto err_submit_cmds;
 	}
 
-	ret = copy_from_user(stream, to_user_ptr(args->stream),
+	ret = copy_from_user(stream, u64_to_user_ptr(args->stream),
 			     args->stream_size);
 	if (ret) {
 		ret = -EFAULT;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/etnaviv/etnaviv_gpu.c linux-libre-4.7-gnu/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/etnaviv/etnaviv_gpu.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/etnaviv/etnaviv_gpu.c	2016-07-24 15:23:50.000000000 -0400
@@ -796,9 +796,9 @@ int etnaviv_gpu_debugfs(struct etnaviv_g
 	    debug.state[0] == debug.state[1]) {
 		seq_puts(m, "seems to be stuck\n");
 	} else if (debug.address[0] == debug.address[1]) {
-		seq_puts(m, "adress is constant\n");
+		seq_puts(m, "address is constant\n");
 	} else {
-		seq_puts(m, "is runing\n");
+		seq_puts(m, "is running\n");
 	}
 
 	seq_printf(m, "\t address 0: 0x%08x\n", debug.address[0]);
@@ -1528,8 +1528,8 @@ static int etnaviv_gpu_bind(struct devic
 	INIT_WORK(&gpu->recover_work, recover_worker);
 	init_waitqueue_head(&gpu->fence_event);
 
-	setup_timer(&gpu->hangcheck_timer, hangcheck_handler,
-			(unsigned long)gpu);
+	setup_deferrable_timer(&gpu->hangcheck_timer, hangcheck_handler,
+			       (unsigned long)gpu);
 
 	priv->gpu[priv->num_gpus++] = gpu;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/etnaviv/etnaviv_iommu.c linux-libre-4.7-gnu/drivers/gpu/drm/etnaviv/etnaviv_iommu.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/etnaviv/etnaviv_iommu.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/etnaviv/etnaviv_iommu.c	2016-07-24 15:23:50.000000000 -0400
@@ -225,6 +225,7 @@ struct iommu_domain *etnaviv_iommu_domai
 
 	etnaviv_domain->domain.type = __IOMMU_DOMAIN_PAGING;
 	etnaviv_domain->domain.ops = &etnaviv_iommu_ops.ops;
+	etnaviv_domain->domain.pgsize_bitmap = SZ_4K;
 	etnaviv_domain->domain.geometry.aperture_start = GPU_MEM_START;
 	etnaviv_domain->domain.geometry.aperture_end = GPU_MEM_START + PT_ENTRIES * SZ_4K - 1;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos5433_drm_decon.c linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos5433_drm_decon.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos5433_drm_decon.c	2016-07-24 15:23:50.000000000 -0400
@@ -28,6 +28,10 @@
 #define WINDOWS_NR	3
 #define MIN_FB_WIDTH_FOR_16WORD_BURST	128
 
+#define IFTYPE_I80	(1 << 0)
+#define I80_HW_TRG	(1 << 1)
+#define IFTYPE_HDMI	(1 << 2)
+
 static const char * const decon_clks_name[] = {
 	"pclk",
 	"aclk_decon",
@@ -38,12 +42,6 @@ static const char * const decon_clks_nam
 	"sclk_decon_eclk",
 };
 
-enum decon_iftype {
-	IFTYPE_RGB,
-	IFTYPE_I80,
-	IFTYPE_HDMI
-};
-
 enum decon_flag_bits {
 	BIT_CLKS_ENABLED,
 	BIT_IRQS_ENABLED,
@@ -61,7 +59,7 @@ struct decon_context {
 	struct clk			*clks[ARRAY_SIZE(decon_clks_name)];
 	int				pipe;
 	unsigned long			flags;
-	enum decon_iftype		out_type;
+	unsigned long			out_type;
 	int				first_win;
 };
 
@@ -95,7 +93,7 @@ static int decon_enable_vblank(struct ex
 
 	if (!test_and_set_bit(BIT_IRQS_ENABLED, &ctx->flags)) {
 		val = VIDINTCON0_INTEN;
-		if (ctx->out_type == IFTYPE_I80)
+		if (ctx->out_type & IFTYPE_I80)
 			val |= VIDINTCON0_FRAMEDONE;
 		else
 			val |= VIDINTCON0_INTFRMEN;
@@ -119,11 +117,11 @@ static void decon_disable_vblank(struct
 
 static void decon_setup_trigger(struct decon_context *ctx)
 {
-	u32 val = (ctx->out_type != IFTYPE_HDMI)
+	u32 val = !(ctx->out_type & I80_HW_TRG)
 		? TRIGCON_TRIGEN_PER_F | TRIGCON_TRIGEN_F |
 		  TRIGCON_TE_AUTO_MASK | TRIGCON_SWTRIGEN
 		: TRIGCON_TRIGEN_PER_F | TRIGCON_TRIGEN_F |
-		  TRIGCON_HWTRIGMASK_I80_RGB | TRIGCON_HWTRIGEN_I80_RGB;
+		  TRIGCON_HWTRIGMASK | TRIGCON_HWTRIGEN;
 	writel(val, ctx->addr + DECON_TRIGCON);
 }
 
@@ -136,7 +134,7 @@ static void decon_commit(struct exynos_d
 	if (test_bit(BIT_SUSPENDED, &ctx->flags))
 		return;
 
-	if (ctx->out_type == IFTYPE_HDMI) {
+	if (ctx->out_type & IFTYPE_HDMI) {
 		m->crtc_hsync_start = m->crtc_hdisplay + 10;
 		m->crtc_hsync_end = m->crtc_htotal - 92;
 		m->crtc_vsync_start = m->crtc_vdisplay + 1;
@@ -149,19 +147,24 @@ static void decon_commit(struct exynos_d
 	val = CMU_CLKGAGE_MODE_SFR_F | CMU_CLKGAGE_MODE_MEM_F;
 	writel(val, ctx->addr + DECON_CMU);
 
+	if (ctx->out_type & (IFTYPE_I80 | I80_HW_TRG))
+		decon_setup_trigger(ctx);
+
 	/* lcd on and use command if */
 	val = VIDOUT_LCD_ON;
-	if (ctx->out_type == IFTYPE_I80)
+	if (ctx->out_type & IFTYPE_I80) {
 		val |= VIDOUT_COMMAND_IF;
-	else
+	} else {
 		val |= VIDOUT_RGB_IF;
+	}
+
 	writel(val, ctx->addr + DECON_VIDOUTCON0);
 
 	val = VIDTCON2_LINEVAL(m->vdisplay - 1) |
 		VIDTCON2_HOZVAL(m->hdisplay - 1);
 	writel(val, ctx->addr + DECON_VIDTCON2);
 
-	if (ctx->out_type != IFTYPE_I80) {
+	if (!(ctx->out_type & IFTYPE_I80)) {
 		val = VIDTCON00_VBPD_F(
 				m->crtc_vtotal - m->crtc_vsync_end - 1) |
 			VIDTCON00_VFPD_F(
@@ -183,10 +186,10 @@ static void decon_commit(struct exynos_d
 		writel(val, ctx->addr + DECON_VIDTCON11);
 	}
 
-	decon_setup_trigger(ctx);
-
 	/* enable output and display signal */
 	decon_set_bits(ctx, DECON_VIDCON0, VIDCON0_ENVID | VIDCON0_ENVID_F, ~0);
+
+	decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0);
 }
 
 static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win,
@@ -300,7 +303,7 @@ static void decon_update_plane(struct ex
 	val = dma_addr + pitch * state->src.h;
 	writel(val, ctx->addr + DECON_VIDW0xADD1B0(win));
 
-	if (ctx->out_type != IFTYPE_HDMI)
+	if (!(ctx->out_type & IFTYPE_HDMI))
 		val = BIT_VAL(pitch - state->crtc.w * bpp, 27, 14)
 			| BIT_VAL(state->crtc.w * bpp, 13, 0);
 	else
@@ -312,9 +315,6 @@ static void decon_update_plane(struct ex
 
 	/* window enable */
 	decon_set_bits(ctx, DECON_WINCONx(win), WINCONx_ENWIN_F, ~0);
-
-	/* standalone update */
-	decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0);
 }
 
 static void decon_disable_plane(struct exynos_drm_crtc *crtc,
@@ -326,15 +326,7 @@ static void decon_disable_plane(struct e
 	if (test_bit(BIT_SUSPENDED, &ctx->flags))
 		return;
 
-	decon_shadow_protect_win(ctx, win, true);
-
-	/* window disable */
 	decon_set_bits(ctx, DECON_WINCONx(win), WINCONx_ENWIN_F, 0);
-
-	decon_shadow_protect_win(ctx, win, false);
-
-	/* standalone update */
-	decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0);
 }
 
 static void decon_atomic_flush(struct exynos_drm_crtc *crtc)
@@ -348,7 +340,10 @@ static void decon_atomic_flush(struct ex
 	for (i = ctx->first_win; i < WINDOWS_NR; i++)
 		decon_shadow_protect_win(ctx, i, false);
 
-	if (ctx->out_type == IFTYPE_I80)
+	/* standalone update */
+	decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0);
+
+	if (ctx->out_type & IFTYPE_I80)
 		set_bit(BIT_WIN_UPDATED, &ctx->flags);
 }
 
@@ -374,7 +369,7 @@ static void decon_swreset(struct decon_c
 
 	WARN(tries == 0, "failed to software reset DECON\n");
 
-	if (ctx->out_type != IFTYPE_HDMI)
+	if (!(ctx->out_type & IFTYPE_HDMI))
 		return;
 
 	writel(VIDCON0_CLKVALUP | VIDCON0_VLCKFREE, ctx->addr + DECON_VIDCON0);
@@ -383,7 +378,6 @@ static void decon_swreset(struct decon_c
 	writel(VIDCON1_VCLK_RUN_VDEN_DISABLE, ctx->addr + DECON_VIDCON1);
 	writel(CRCCTRL_CRCEN | CRCCTRL_CRCSTART_F | CRCCTRL_CRCCLKEN,
 	       ctx->addr + DECON_CRCCTRL);
-	decon_setup_trigger(ctx);
 }
 
 static void decon_enable(struct exynos_drm_crtc *crtc)
@@ -395,8 +389,12 @@ static void decon_enable(struct exynos_d
 
 	pm_runtime_get_sync(ctx->dev);
 
+	exynos_drm_pipe_clk_enable(crtc, true);
+
 	set_bit(BIT_CLKS_ENABLED, &ctx->flags);
 
+	decon_swreset(ctx);
+
 	/* if vblank was enabled status, enable it again. */
 	if (test_and_clear_bit(BIT_IRQS_ENABLED, &ctx->flags))
 		decon_enable_vblank(ctx->crtc);
@@ -424,6 +422,8 @@ static void decon_disable(struct exynos_
 
 	clear_bit(BIT_CLKS_ENABLED, &ctx->flags);
 
+	exynos_drm_pipe_clk_enable(crtc, false);
+
 	pm_runtime_put_sync(ctx->dev);
 
 	set_bit(BIT_SUSPENDED, &ctx->flags);
@@ -433,13 +433,12 @@ static void decon_te_irq_handler(struct
 {
 	struct decon_context *ctx = crtc->ctx;
 
-	if (!test_bit(BIT_CLKS_ENABLED, &ctx->flags))
+	if (!test_bit(BIT_CLKS_ENABLED, &ctx->flags) ||
+	    (ctx->out_type & I80_HW_TRG))
 		return;
 
 	if (test_and_clear_bit(BIT_WIN_UPDATED, &ctx->flags))
 		decon_set_bits(ctx, DECON_TRIGCON, TRIGCON_SWTRIGCMD, ~0);
-
-	drm_crtc_handle_vblank(&ctx->crtc->base);
 }
 
 static void decon_clear_channels(struct exynos_drm_crtc *crtc)
@@ -459,8 +458,10 @@ static void decon_clear_channels(struct
 		decon_shadow_protect_win(ctx, win, true);
 		decon_set_bits(ctx, DECON_WINCONx(win), WINCONx_ENWIN_F, 0);
 		decon_shadow_protect_win(ctx, win, false);
-		decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0);
 	}
+
+	decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0);
+
 	/* TODO: wait for possible vsync */
 	msleep(50);
 
@@ -509,7 +510,7 @@ static int decon_bind(struct device *dev
 	}
 
 	exynos_plane = &ctx->planes[ctx->first_win];
-	out_type = (ctx->out_type == IFTYPE_HDMI) ? EXYNOS_DISPLAY_TYPE_HDMI
+	out_type = (ctx->out_type & IFTYPE_HDMI) ? EXYNOS_DISPLAY_TYPE_HDMI
 						  : EXYNOS_DISPLAY_TYPE_LCD;
 	ctx->crtc = exynos_drm_crtc_create(drm_dev, &exynos_plane->base,
 					ctx->pipe, out_type,
@@ -570,6 +571,7 @@ static irqreturn_t decon_irq_handler(int
 
 		/* clear */
 		writel(val, ctx->addr + DECON_VIDINTCON1);
+		drm_crtc_handle_vblank(&ctx->crtc->base);
 	}
 
 out:
@@ -617,11 +619,11 @@ static const struct dev_pm_ops exynos543
 static const struct of_device_id exynos5433_decon_driver_dt_match[] = {
 	{
 		.compatible = "samsung,exynos5433-decon",
-		.data = (void *)IFTYPE_RGB
+		.data = (void *)I80_HW_TRG
 	},
 	{
 		.compatible = "samsung,exynos5433-decon-tv",
-		.data = (void *)IFTYPE_HDMI
+		.data = (void *)(I80_HW_TRG | IFTYPE_HDMI)
 	},
 	{},
 };
@@ -629,7 +631,6 @@ MODULE_DEVICE_TABLE(of, exynos5433_decon
 
 static int exynos5433_decon_probe(struct platform_device *pdev)
 {
-	const struct of_device_id *of_id;
 	struct device *dev = &pdev->dev;
 	struct decon_context *ctx;
 	struct resource *res;
@@ -642,14 +643,13 @@ static int exynos5433_decon_probe(struct
 
 	__set_bit(BIT_SUSPENDED, &ctx->flags);
 	ctx->dev = dev;
+	ctx->out_type = (unsigned long)of_device_get_match_data(dev);
 
-	of_id = of_match_device(exynos5433_decon_driver_dt_match, &pdev->dev);
-	ctx->out_type = (enum decon_iftype)of_id->data;
-
-	if (ctx->out_type == IFTYPE_HDMI)
+	if (ctx->out_type & IFTYPE_HDMI) {
 		ctx->first_win = 1;
-	else if (of_get_child_by_name(dev->of_node, "i80-if-timings"))
-		ctx->out_type = IFTYPE_I80;
+	} else if (of_get_child_by_name(dev->of_node, "i80-if-timings")) {
+		ctx->out_type |= IFTYPE_I80;
+	}
 
 	for (i = 0; i < ARRAY_SIZE(decon_clks_name); i++) {
 		struct clk *clk;
@@ -674,7 +674,7 @@ static int exynos5433_decon_probe(struct
 	}
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
-			(ctx->out_type == IFTYPE_I80) ? "lcd_sys" : "vsync");
+			(ctx->out_type & IFTYPE_I80) ? "lcd_sys" : "vsync");
 	if (!res) {
 		dev_err(dev, "cannot find IRQ resource\n");
 		return -ENXIO;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos7_drm_decon.c linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos7_drm_decon.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos7_drm_decon.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos7_drm_decon.c	2016-07-24 15:23:50.000000000 -0400
@@ -31,7 +31,6 @@
 #include "exynos_drm_plane.h"
 #include "exynos_drm_drv.h"
 #include "exynos_drm_fb.h"
-#include "exynos_drm_fbdev.h"
 #include "exynos_drm_iommu.h"
 
 /*
@@ -593,7 +592,6 @@ static const struct exynos_drm_crtc_ops
 	.commit = decon_commit,
 	.enable_vblank = decon_enable_vblank,
 	.disable_vblank = decon_disable_vblank,
-	.wait_for_vblank = decon_wait_for_vblank,
 	.atomic_begin = decon_atomic_begin,
 	.update_plane = decon_update_plane,
 	.disable_plane = decon_disable_plane,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_dp.c linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_dp.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_dp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_dp.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,312 @@
+/*
+ * Samsung SoC DP (Display Port) interface driver.
+ *
+ * Copyright (C) 2012 Samsung Electronics Co., Ltd.
+ * Author: Jingoo Han <jg1.han@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/of_graph.h>
+#include <linux/component.h>
+#include <video/of_display_timing.h>
+#include <video/of_videomode.h>
+#include <video/videomode.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_panel.h>
+
+#include <drm/bridge/analogix_dp.h>
+#include <drm/exynos_drm.h>
+
+#include "exynos_drm_crtc.h"
+
+#define to_dp(nm)	container_of(nm, struct exynos_dp_device, nm)
+
+struct exynos_dp_device {
+	struct drm_encoder         encoder;
+	struct drm_connector       *connector;
+	struct drm_bridge          *ptn_bridge;
+	struct drm_device          *drm_dev;
+	struct device              *dev;
+
+	struct videomode           vm;
+	struct analogix_dp_plat_data plat_data;
+};
+
+int exynos_dp_crtc_clock_enable(struct analogix_dp_plat_data *plat_data,
+				bool enable)
+{
+	struct exynos_dp_device *dp = to_dp(plat_data);
+	struct drm_encoder *encoder = &dp->encoder;
+
+	if (!encoder->crtc)
+		return -EPERM;
+
+	exynos_drm_pipe_clk_enable(to_exynos_crtc(encoder->crtc), enable);
+
+	return 0;
+}
+
+static int exynos_dp_poweron(struct analogix_dp_plat_data *plat_data)
+{
+	return exynos_dp_crtc_clock_enable(plat_data, true);
+}
+
+static int exynos_dp_poweroff(struct analogix_dp_plat_data *plat_data)
+{
+	return exynos_dp_crtc_clock_enable(plat_data, false);
+}
+
+static int exynos_dp_get_modes(struct analogix_dp_plat_data *plat_data)
+{
+	struct exynos_dp_device *dp = to_dp(plat_data);
+	struct drm_connector *connector = dp->connector;
+	struct drm_display_mode *mode;
+	int num_modes = 0;
+
+	if (dp->plat_data.panel)
+		return num_modes;
+
+	mode = drm_mode_create(connector->dev);
+	if (!mode) {
+		DRM_ERROR("failed to create a new display mode.\n");
+		return num_modes;
+	}
+
+	drm_display_mode_from_videomode(&dp->vm, mode);
+	connector->display_info.width_mm = mode->width_mm;
+	connector->display_info.height_mm = mode->height_mm;
+
+	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+	drm_mode_set_name(mode);
+	drm_mode_probed_add(connector, mode);
+
+	return num_modes + 1;
+}
+
+static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data,
+				   struct drm_bridge *bridge,
+				   struct drm_connector *connector)
+{
+	struct exynos_dp_device *dp = to_dp(plat_data);
+	struct drm_encoder *encoder = &dp->encoder;
+	int ret;
+
+	drm_connector_register(connector);
+	dp->connector = connector;
+
+	/* Pre-empt DP connector creation if there's a bridge */
+	if (dp->ptn_bridge) {
+		bridge->next = dp->ptn_bridge;
+		dp->ptn_bridge->encoder = encoder;
+		ret = drm_bridge_attach(encoder->dev, dp->ptn_bridge);
+		if (ret) {
+			DRM_ERROR("Failed to attach bridge to drm\n");
+			bridge->next = NULL;
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static void exynos_dp_mode_set(struct drm_encoder *encoder,
+			       struct drm_display_mode *mode,
+			       struct drm_display_mode *adjusted_mode)
+{
+}
+
+static void exynos_dp_nop(struct drm_encoder *encoder)
+{
+	/* do nothing */
+}
+
+static const struct drm_encoder_helper_funcs exynos_dp_encoder_helper_funcs = {
+	.mode_set = exynos_dp_mode_set,
+	.enable = exynos_dp_nop,
+	.disable = exynos_dp_nop,
+};
+
+static const struct drm_encoder_funcs exynos_dp_encoder_funcs = {
+	.destroy = drm_encoder_cleanup,
+};
+
+static int exynos_dp_dt_parse_panel(struct exynos_dp_device *dp)
+{
+	int ret;
+
+	ret = of_get_videomode(dp->dev->of_node, &dp->vm, OF_USE_NATIVE_MODE);
+	if (ret) {
+		DRM_ERROR("failed: of_get_videomode() : %d\n", ret);
+		return ret;
+	}
+	return 0;
+}
+
+static int exynos_dp_bind(struct device *dev, struct device *master, void *data)
+{
+	struct exynos_dp_device *dp = dev_get_drvdata(dev);
+	struct drm_encoder *encoder = &dp->encoder;
+	struct drm_device *drm_dev = data;
+	int pipe, ret;
+
+	/*
+	 * Just like the probe function said, we don't need the
+	 * device drvrate anymore, we should leave the charge to
+	 * analogix dp driver, set the device drvdata to NULL.
+	 */
+	dev_set_drvdata(dev, NULL);
+
+	dp->dev = dev;
+	dp->drm_dev = drm_dev;
+
+	dp->plat_data.dev_type = EXYNOS_DP;
+	dp->plat_data.power_on = exynos_dp_poweron;
+	dp->plat_data.power_off = exynos_dp_poweroff;
+	dp->plat_data.attach = exynos_dp_bridge_attach;
+	dp->plat_data.get_modes = exynos_dp_get_modes;
+
+	if (!dp->plat_data.panel && !dp->ptn_bridge) {
+		ret = exynos_dp_dt_parse_panel(dp);
+		if (ret)
+			return ret;
+	}
+
+	pipe = exynos_drm_crtc_get_pipe_from_type(drm_dev,
+						  EXYNOS_DISPLAY_TYPE_LCD);
+	if (pipe < 0)
+		return pipe;
+
+	encoder->possible_crtcs = 1 << pipe;
+
+	DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
+
+	drm_encoder_init(drm_dev, encoder, &exynos_dp_encoder_funcs,
+			 DRM_MODE_ENCODER_TMDS, NULL);
+
+	drm_encoder_helper_add(encoder, &exynos_dp_encoder_helper_funcs);
+
+	dp->plat_data.encoder = encoder;
+
+	return analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data);
+}
+
+static void exynos_dp_unbind(struct device *dev, struct device *master,
+			     void *data)
+{
+	return analogix_dp_unbind(dev, master, data);
+}
+
+static const struct component_ops exynos_dp_ops = {
+	.bind	= exynos_dp_bind,
+	.unbind	= exynos_dp_unbind,
+};
+
+static int exynos_dp_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = NULL, *endpoint = NULL;
+	struct exynos_dp_device *dp;
+
+	dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device),
+			  GFP_KERNEL);
+	if (!dp)
+		return -ENOMEM;
+
+	/*
+	 * We just use the drvdata until driver run into component
+	 * add function, and then we would set drvdata to null, so
+	 * that analogix dp driver would take charge of the drvdata.
+	 */
+	platform_set_drvdata(pdev, dp);
+
+	/* This is for the backward compatibility. */
+	np = of_parse_phandle(dev->of_node, "panel", 0);
+	if (np) {
+		dp->plat_data.panel = of_drm_find_panel(np);
+		of_node_put(np);
+		if (!dp->plat_data.panel)
+			return -EPROBE_DEFER;
+		goto out;
+	}
+
+	endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
+	if (endpoint) {
+		np = of_graph_get_remote_port_parent(endpoint);
+		if (np) {
+			/* The remote port can be either a panel or a bridge */
+			dp->plat_data.panel = of_drm_find_panel(np);
+			if (!dp->plat_data.panel) {
+				dp->ptn_bridge = of_drm_find_bridge(np);
+				if (!dp->ptn_bridge) {
+					of_node_put(np);
+					return -EPROBE_DEFER;
+				}
+			}
+			of_node_put(np);
+		} else {
+			DRM_ERROR("no remote endpoint device node found.\n");
+			return -EINVAL;
+		}
+	} else {
+		DRM_ERROR("no port endpoint subnode found.\n");
+		return -EINVAL;
+	}
+
+out:
+	return component_add(&pdev->dev, &exynos_dp_ops);
+}
+
+static int exynos_dp_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &exynos_dp_ops);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int exynos_dp_suspend(struct device *dev)
+{
+	return analogix_dp_suspend(dev);
+}
+
+static int exynos_dp_resume(struct device *dev)
+{
+	return analogix_dp_resume(dev);
+}
+#endif
+
+static const struct dev_pm_ops exynos_dp_pm_ops = {
+	SET_RUNTIME_PM_OPS(exynos_dp_suspend, exynos_dp_resume, NULL)
+};
+
+static const struct of_device_id exynos_dp_match[] = {
+	{ .compatible = "samsung,exynos5-dp" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, exynos_dp_match);
+
+struct platform_driver dp_driver = {
+	.probe		= exynos_dp_probe,
+	.remove		= exynos_dp_remove,
+	.driver		= {
+		.name	= "exynos-dp",
+		.owner	= THIS_MODULE,
+		.pm	= &exynos_dp_pm_ops,
+		.of_match_table = exynos_dp_match,
+	},
+};
+
+MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
+MODULE_DESCRIPTION("Samsung Specific Analogix-DP Driver Extension");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_dp_core.c linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_dp_core.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_dp_core.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_dp_core.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1499 +0,0 @@
-/*
- * Samsung SoC DP (Display Port) interface driver.
- *
- * Copyright (C) 2012 Samsung Electronics Co., Ltd.
- * Author: Jingoo Han <jg1.han@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/of.h>
-#include <linux/of_gpio.h>
-#include <linux/of_graph.h>
-#include <linux/gpio.h>
-#include <linux/component.h>
-#include <linux/phy/phy.h>
-#include <video/of_display_timing.h>
-#include <video/of_videomode.h>
-
-#include <drm/drmP.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_crtc_helper.h>
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_panel.h>
-
-#include "exynos_dp_core.h"
-#include "exynos_drm_crtc.h"
-
-#define ctx_from_connector(c)	container_of(c, struct exynos_dp_device, \
-					connector)
-
-static inline struct exynos_drm_crtc *dp_to_crtc(struct exynos_dp_device *dp)
-{
-	return to_exynos_crtc(dp->encoder.crtc);
-}
-
-static inline struct exynos_dp_device *encoder_to_dp(
-						struct drm_encoder *e)
-{
-	return container_of(e, struct exynos_dp_device, encoder);
-}
-
-struct bridge_init {
-	struct i2c_client *client;
-	struct device_node *node;
-};
-
-static void exynos_dp_init_dp(struct exynos_dp_device *dp)
-{
-	exynos_dp_reset(dp);
-
-	exynos_dp_swreset(dp);
-
-	exynos_dp_init_analog_param(dp);
-	exynos_dp_init_interrupt(dp);
-
-	/* SW defined function Normal operation */
-	exynos_dp_enable_sw_function(dp);
-
-	exynos_dp_config_interrupt(dp);
-	exynos_dp_init_analog_func(dp);
-
-	exynos_dp_init_hpd(dp);
-	exynos_dp_init_aux(dp);
-}
-
-static int exynos_dp_detect_hpd(struct exynos_dp_device *dp)
-{
-	int timeout_loop = 0;
-
-	while (exynos_dp_get_plug_in_status(dp) != 0) {
-		timeout_loop++;
-		if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
-			dev_err(dp->dev, "failed to get hpd plug status\n");
-			return -ETIMEDOUT;
-		}
-		usleep_range(10, 11);
-	}
-
-	return 0;
-}
-
-static unsigned char exynos_dp_calc_edid_check_sum(unsigned char *edid_data)
-{
-	int i;
-	unsigned char sum = 0;
-
-	for (i = 0; i < EDID_BLOCK_LENGTH; i++)
-		sum = sum + edid_data[i];
-
-	return sum;
-}
-
-static int exynos_dp_read_edid(struct exynos_dp_device *dp)
-{
-	unsigned char edid[EDID_BLOCK_LENGTH * 2];
-	unsigned int extend_block = 0;
-	unsigned char sum;
-	unsigned char test_vector;
-	int retval;
-
-	/*
-	 * EDID device address is 0x50.
-	 * However, if necessary, you must have set upper address
-	 * into E-EDID in I2C device, 0x30.
-	 */
-
-	/* Read Extension Flag, Number of 128-byte EDID extension blocks */
-	retval = exynos_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
-				EDID_EXTENSION_FLAG,
-				&extend_block);
-	if (retval)
-		return retval;
-
-	if (extend_block > 0) {
-		dev_dbg(dp->dev, "EDID data includes a single extension!\n");
-
-		/* Read EDID data */
-		retval = exynos_dp_read_bytes_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
-						EDID_HEADER_PATTERN,
-						EDID_BLOCK_LENGTH,
-						&edid[EDID_HEADER_PATTERN]);
-		if (retval != 0) {
-			dev_err(dp->dev, "EDID Read failed!\n");
-			return -EIO;
-		}
-		sum = exynos_dp_calc_edid_check_sum(edid);
-		if (sum != 0) {
-			dev_err(dp->dev, "EDID bad checksum!\n");
-			return -EIO;
-		}
-
-		/* Read additional EDID data */
-		retval = exynos_dp_read_bytes_from_i2c(dp,
-				I2C_EDID_DEVICE_ADDR,
-				EDID_BLOCK_LENGTH,
-				EDID_BLOCK_LENGTH,
-				&edid[EDID_BLOCK_LENGTH]);
-		if (retval != 0) {
-			dev_err(dp->dev, "EDID Read failed!\n");
-			return -EIO;
-		}
-		sum = exynos_dp_calc_edid_check_sum(&edid[EDID_BLOCK_LENGTH]);
-		if (sum != 0) {
-			dev_err(dp->dev, "EDID bad checksum!\n");
-			return -EIO;
-		}
-
-		exynos_dp_read_byte_from_dpcd(dp, DP_TEST_REQUEST,
-					&test_vector);
-		if (test_vector & DP_TEST_LINK_EDID_READ) {
-			exynos_dp_write_byte_to_dpcd(dp,
-				DP_TEST_EDID_CHECKSUM,
-				edid[EDID_BLOCK_LENGTH + EDID_CHECKSUM]);
-			exynos_dp_write_byte_to_dpcd(dp,
-				DP_TEST_RESPONSE,
-				DP_TEST_EDID_CHECKSUM_WRITE);
-		}
-	} else {
-		dev_info(dp->dev, "EDID data does not include any extensions.\n");
-
-		/* Read EDID data */
-		retval = exynos_dp_read_bytes_from_i2c(dp,
-				I2C_EDID_DEVICE_ADDR,
-				EDID_HEADER_PATTERN,
-				EDID_BLOCK_LENGTH,
-				&edid[EDID_HEADER_PATTERN]);
-		if (retval != 0) {
-			dev_err(dp->dev, "EDID Read failed!\n");
-			return -EIO;
-		}
-		sum = exynos_dp_calc_edid_check_sum(edid);
-		if (sum != 0) {
-			dev_err(dp->dev, "EDID bad checksum!\n");
-			return -EIO;
-		}
-
-		exynos_dp_read_byte_from_dpcd(dp,
-			DP_TEST_REQUEST,
-			&test_vector);
-		if (test_vector & DP_TEST_LINK_EDID_READ) {
-			exynos_dp_write_byte_to_dpcd(dp,
-				DP_TEST_EDID_CHECKSUM,
-				edid[EDID_CHECKSUM]);
-			exynos_dp_write_byte_to_dpcd(dp,
-				DP_TEST_RESPONSE,
-				DP_TEST_EDID_CHECKSUM_WRITE);
-		}
-	}
-
-	dev_dbg(dp->dev, "EDID Read success!\n");
-	return 0;
-}
-
-static int exynos_dp_handle_edid(struct exynos_dp_device *dp)
-{
-	u8 buf[12];
-	int i;
-	int retval;
-
-	/* Read DPCD DP_DPCD_REV~RECEIVE_PORT1_CAP_1 */
-	retval = exynos_dp_read_bytes_from_dpcd(dp, DP_DPCD_REV,
-				12, buf);
-	if (retval)
-		return retval;
-
-	/* Read EDID */
-	for (i = 0; i < 3; i++) {
-		retval = exynos_dp_read_edid(dp);
-		if (!retval)
-			break;
-	}
-
-	return retval;
-}
-
-static void exynos_dp_enable_rx_to_enhanced_mode(struct exynos_dp_device *dp,
-						bool enable)
-{
-	u8 data;
-
-	exynos_dp_read_byte_from_dpcd(dp, DP_LANE_COUNT_SET, &data);
-
-	if (enable)
-		exynos_dp_write_byte_to_dpcd(dp, DP_LANE_COUNT_SET,
-			DP_LANE_COUNT_ENHANCED_FRAME_EN |
-			DPCD_LANE_COUNT_SET(data));
-	else
-		exynos_dp_write_byte_to_dpcd(dp, DP_LANE_COUNT_SET,
-			DPCD_LANE_COUNT_SET(data));
-}
-
-static int exynos_dp_is_enhanced_mode_available(struct exynos_dp_device *dp)
-{
-	u8 data;
-	int retval;
-
-	exynos_dp_read_byte_from_dpcd(dp, DP_MAX_LANE_COUNT, &data);
-	retval = DPCD_ENHANCED_FRAME_CAP(data);
-
-	return retval;
-}
-
-static void exynos_dp_set_enhanced_mode(struct exynos_dp_device *dp)
-{
-	u8 data;
-
-	data = exynos_dp_is_enhanced_mode_available(dp);
-	exynos_dp_enable_rx_to_enhanced_mode(dp, data);
-	exynos_dp_enable_enhanced_mode(dp, data);
-}
-
-static void exynos_dp_training_pattern_dis(struct exynos_dp_device *dp)
-{
-	exynos_dp_set_training_pattern(dp, DP_NONE);
-
-	exynos_dp_write_byte_to_dpcd(dp,
-		DP_TRAINING_PATTERN_SET,
-		DP_TRAINING_PATTERN_DISABLE);
-}
-
-static void exynos_dp_set_lane_lane_pre_emphasis(struct exynos_dp_device *dp,
-					int pre_emphasis, int lane)
-{
-	switch (lane) {
-	case 0:
-		exynos_dp_set_lane0_pre_emphasis(dp, pre_emphasis);
-		break;
-	case 1:
-		exynos_dp_set_lane1_pre_emphasis(dp, pre_emphasis);
-		break;
-
-	case 2:
-		exynos_dp_set_lane2_pre_emphasis(dp, pre_emphasis);
-		break;
-
-	case 3:
-		exynos_dp_set_lane3_pre_emphasis(dp, pre_emphasis);
-		break;
-	}
-}
-
-static int exynos_dp_link_start(struct exynos_dp_device *dp)
-{
-	u8 buf[4];
-	int lane, lane_count, pll_tries, retval;
-
-	lane_count = dp->link_train.lane_count;
-
-	dp->link_train.lt_state = CLOCK_RECOVERY;
-	dp->link_train.eq_loop = 0;
-
-	for (lane = 0; lane < lane_count; lane++)
-		dp->link_train.cr_loop[lane] = 0;
-
-	/* Set link rate and count as you want to establish*/
-	exynos_dp_set_link_bandwidth(dp, dp->link_train.link_rate);
-	exynos_dp_set_lane_count(dp, dp->link_train.lane_count);
-
-	/* Setup RX configuration */
-	buf[0] = dp->link_train.link_rate;
-	buf[1] = dp->link_train.lane_count;
-	retval = exynos_dp_write_bytes_to_dpcd(dp, DP_LINK_BW_SET,
-				2, buf);
-	if (retval)
-		return retval;
-
-	/* Set TX pre-emphasis to minimum */
-	for (lane = 0; lane < lane_count; lane++)
-		exynos_dp_set_lane_lane_pre_emphasis(dp,
-			PRE_EMPHASIS_LEVEL_0, lane);
-
-	/* Wait for PLL lock */
-	pll_tries = 0;
-	while (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
-		if (pll_tries == DP_TIMEOUT_LOOP_COUNT) {
-			dev_err(dp->dev, "Wait for PLL lock timed out\n");
-			return -ETIMEDOUT;
-		}
-
-		pll_tries++;
-		usleep_range(90, 120);
-	}
-
-	/* Set training pattern 1 */
-	exynos_dp_set_training_pattern(dp, TRAINING_PTN1);
-
-	/* Set RX training pattern */
-	retval = exynos_dp_write_byte_to_dpcd(dp,
-			DP_TRAINING_PATTERN_SET,
-			DP_LINK_SCRAMBLING_DISABLE | DP_TRAINING_PATTERN_1);
-	if (retval)
-		return retval;
-
-	for (lane = 0; lane < lane_count; lane++)
-		buf[lane] = DP_TRAIN_PRE_EMPH_LEVEL_0 |
-			    DP_TRAIN_VOLTAGE_SWING_LEVEL_0;
-
-	retval = exynos_dp_write_bytes_to_dpcd(dp, DP_TRAINING_LANE0_SET,
-			lane_count, buf);
-
-	return retval;
-}
-
-static unsigned char exynos_dp_get_lane_status(u8 link_status[2], int lane)
-{
-	int shift = (lane & 1) * 4;
-	u8 link_value = link_status[lane>>1];
-
-	return (link_value >> shift) & 0xf;
-}
-
-static int exynos_dp_clock_recovery_ok(u8 link_status[2], int lane_count)
-{
-	int lane;
-	u8 lane_status;
-
-	for (lane = 0; lane < lane_count; lane++) {
-		lane_status = exynos_dp_get_lane_status(link_status, lane);
-		if ((lane_status & DP_LANE_CR_DONE) == 0)
-			return -EINVAL;
-	}
-	return 0;
-}
-
-static int exynos_dp_channel_eq_ok(u8 link_status[2], u8 link_align,
-				int lane_count)
-{
-	int lane;
-	u8 lane_status;
-
-	if ((link_align & DP_INTERLANE_ALIGN_DONE) == 0)
-		return -EINVAL;
-
-	for (lane = 0; lane < lane_count; lane++) {
-		lane_status = exynos_dp_get_lane_status(link_status, lane);
-		lane_status &= DP_CHANNEL_EQ_BITS;
-		if (lane_status != DP_CHANNEL_EQ_BITS)
-			return -EINVAL;
-	}
-
-	return 0;
-}
-
-static unsigned char exynos_dp_get_adjust_request_voltage(u8 adjust_request[2],
-							int lane)
-{
-	int shift = (lane & 1) * 4;
-	u8 link_value = adjust_request[lane>>1];
-
-	return (link_value >> shift) & 0x3;
-}
-
-static unsigned char exynos_dp_get_adjust_request_pre_emphasis(
-					u8 adjust_request[2],
-					int lane)
-{
-	int shift = (lane & 1) * 4;
-	u8 link_value = adjust_request[lane>>1];
-
-	return ((link_value >> shift) & 0xc) >> 2;
-}
-
-static void exynos_dp_set_lane_link_training(struct exynos_dp_device *dp,
-					u8 training_lane_set, int lane)
-{
-	switch (lane) {
-	case 0:
-		exynos_dp_set_lane0_link_training(dp, training_lane_set);
-		break;
-	case 1:
-		exynos_dp_set_lane1_link_training(dp, training_lane_set);
-		break;
-
-	case 2:
-		exynos_dp_set_lane2_link_training(dp, training_lane_set);
-		break;
-
-	case 3:
-		exynos_dp_set_lane3_link_training(dp, training_lane_set);
-		break;
-	}
-}
-
-static unsigned int exynos_dp_get_lane_link_training(
-				struct exynos_dp_device *dp,
-				int lane)
-{
-	u32 reg;
-
-	switch (lane) {
-	case 0:
-		reg = exynos_dp_get_lane0_link_training(dp);
-		break;
-	case 1:
-		reg = exynos_dp_get_lane1_link_training(dp);
-		break;
-	case 2:
-		reg = exynos_dp_get_lane2_link_training(dp);
-		break;
-	case 3:
-		reg = exynos_dp_get_lane3_link_training(dp);
-		break;
-	default:
-		WARN_ON(1);
-		return 0;
-	}
-
-	return reg;
-}
-
-static void exynos_dp_reduce_link_rate(struct exynos_dp_device *dp)
-{
-	exynos_dp_training_pattern_dis(dp);
-	exynos_dp_set_enhanced_mode(dp);
-
-	dp->link_train.lt_state = FAILED;
-}
-
-static void exynos_dp_get_adjust_training_lane(struct exynos_dp_device *dp,
-					u8 adjust_request[2])
-{
-	int lane, lane_count;
-	u8 voltage_swing, pre_emphasis, training_lane;
-
-	lane_count = dp->link_train.lane_count;
-	for (lane = 0; lane < lane_count; lane++) {
-		voltage_swing = exynos_dp_get_adjust_request_voltage(
-						adjust_request, lane);
-		pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
-						adjust_request, lane);
-		training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
-				DPCD_PRE_EMPHASIS_SET(pre_emphasis);
-
-		if (voltage_swing == VOLTAGE_LEVEL_3)
-			training_lane |= DP_TRAIN_MAX_SWING_REACHED;
-		if (pre_emphasis == PRE_EMPHASIS_LEVEL_3)
-			training_lane |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
-
-		dp->link_train.training_lane[lane] = training_lane;
-	}
-}
-
-static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
-{
-	int lane, lane_count, retval;
-	u8 voltage_swing, pre_emphasis, training_lane;
-	u8 link_status[2], adjust_request[2];
-
-	usleep_range(100, 101);
-
-	lane_count = dp->link_train.lane_count;
-
-	retval =  exynos_dp_read_bytes_from_dpcd(dp,
-			DP_LANE0_1_STATUS, 2, link_status);
-	if (retval)
-		return retval;
-
-	retval =  exynos_dp_read_bytes_from_dpcd(dp,
-			DP_ADJUST_REQUEST_LANE0_1, 2, adjust_request);
-	if (retval)
-		return retval;
-
-	if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) {
-		/* set training pattern 2 for EQ */
-		exynos_dp_set_training_pattern(dp, TRAINING_PTN2);
-
-		retval = exynos_dp_write_byte_to_dpcd(dp,
-				DP_TRAINING_PATTERN_SET,
-				DP_LINK_SCRAMBLING_DISABLE |
-				DP_TRAINING_PATTERN_2);
-		if (retval)
-			return retval;
-
-		dev_info(dp->dev, "Link Training Clock Recovery success\n");
-		dp->link_train.lt_state = EQUALIZER_TRAINING;
-	} else {
-		for (lane = 0; lane < lane_count; lane++) {
-			training_lane = exynos_dp_get_lane_link_training(
-							dp, lane);
-			voltage_swing = exynos_dp_get_adjust_request_voltage(
-							adjust_request, lane);
-			pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
-							adjust_request, lane);
-
-			if (DPCD_VOLTAGE_SWING_GET(training_lane) ==
-					voltage_swing &&
-			    DPCD_PRE_EMPHASIS_GET(training_lane) ==
-					pre_emphasis)
-				dp->link_train.cr_loop[lane]++;
-
-			if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP ||
-			    voltage_swing == VOLTAGE_LEVEL_3 ||
-			    pre_emphasis == PRE_EMPHASIS_LEVEL_3) {
-				dev_err(dp->dev, "CR Max reached (%d,%d,%d)\n",
-					dp->link_train.cr_loop[lane],
-					voltage_swing, pre_emphasis);
-				exynos_dp_reduce_link_rate(dp);
-				return -EIO;
-			}
-		}
-	}
-
-	exynos_dp_get_adjust_training_lane(dp, adjust_request);
-
-	for (lane = 0; lane < lane_count; lane++)
-		exynos_dp_set_lane_link_training(dp,
-			dp->link_train.training_lane[lane], lane);
-
-	retval = exynos_dp_write_bytes_to_dpcd(dp,
-			DP_TRAINING_LANE0_SET, lane_count,
-			dp->link_train.training_lane);
-	if (retval)
-		return retval;
-
-	return retval;
-}
-
-static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp)
-{
-	int lane, lane_count, retval;
-	u32 reg;
-	u8 link_align, link_status[2], adjust_request[2];
-
-	usleep_range(400, 401);
-
-	lane_count = dp->link_train.lane_count;
-
-	retval = exynos_dp_read_bytes_from_dpcd(dp,
-			DP_LANE0_1_STATUS, 2, link_status);
-	if (retval)
-		return retval;
-
-	if (exynos_dp_clock_recovery_ok(link_status, lane_count)) {
-		exynos_dp_reduce_link_rate(dp);
-		return -EIO;
-	}
-
-	retval = exynos_dp_read_bytes_from_dpcd(dp,
-			DP_ADJUST_REQUEST_LANE0_1, 2, adjust_request);
-	if (retval)
-		return retval;
-
-	retval = exynos_dp_read_byte_from_dpcd(dp,
-			DP_LANE_ALIGN_STATUS_UPDATED, &link_align);
-	if (retval)
-		return retval;
-
-	exynos_dp_get_adjust_training_lane(dp, adjust_request);
-
-	if (!exynos_dp_channel_eq_ok(link_status, link_align, lane_count)) {
-		/* traing pattern Set to Normal */
-		exynos_dp_training_pattern_dis(dp);
-
-		dev_info(dp->dev, "Link Training success!\n");
-
-		exynos_dp_get_link_bandwidth(dp, &reg);
-		dp->link_train.link_rate = reg;
-		dev_dbg(dp->dev, "final bandwidth = %.2x\n",
-			dp->link_train.link_rate);
-
-		exynos_dp_get_lane_count(dp, &reg);
-		dp->link_train.lane_count = reg;
-		dev_dbg(dp->dev, "final lane count = %.2x\n",
-			dp->link_train.lane_count);
-
-		/* set enhanced mode if available */
-		exynos_dp_set_enhanced_mode(dp);
-		dp->link_train.lt_state = FINISHED;
-
-		return 0;
-	}
-
-	/* not all locked */
-	dp->link_train.eq_loop++;
-
-	if (dp->link_train.eq_loop > MAX_EQ_LOOP) {
-		dev_err(dp->dev, "EQ Max loop\n");
-		exynos_dp_reduce_link_rate(dp);
-		return -EIO;
-	}
-
-	for (lane = 0; lane < lane_count; lane++)
-		exynos_dp_set_lane_link_training(dp,
-			dp->link_train.training_lane[lane], lane);
-
-	retval = exynos_dp_write_bytes_to_dpcd(dp, DP_TRAINING_LANE0_SET,
-			lane_count, dp->link_train.training_lane);
-
-	return retval;
-}
-
-static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp,
-					u8 *bandwidth)
-{
-	u8 data;
-
-	/*
-	 * For DP rev.1.1, Maximum link rate of Main Link lanes
-	 * 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps
-	 */
-	exynos_dp_read_byte_from_dpcd(dp, DP_MAX_LINK_RATE, &data);
-	*bandwidth = data;
-}
-
-static void exynos_dp_get_max_rx_lane_count(struct exynos_dp_device *dp,
-					u8 *lane_count)
-{
-	u8 data;
-
-	/*
-	 * For DP rev.1.1, Maximum number of Main Link lanes
-	 * 0x01 = 1 lane, 0x02 = 2 lanes, 0x04 = 4 lanes
-	 */
-	exynos_dp_read_byte_from_dpcd(dp, DP_MAX_LANE_COUNT, &data);
-	*lane_count = DPCD_MAX_LANE_COUNT(data);
-}
-
-static void exynos_dp_init_training(struct exynos_dp_device *dp,
-			enum link_lane_count_type max_lane,
-			enum link_rate_type max_rate)
-{
-	/*
-	 * MACRO_RST must be applied after the PLL_LOCK to avoid
-	 * the DP inter pair skew issue for at least 10 us
-	 */
-	exynos_dp_reset_macro(dp);
-
-	/* Initialize by reading RX's DPCD */
-	exynos_dp_get_max_rx_bandwidth(dp, &dp->link_train.link_rate);
-	exynos_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count);
-
-	if ((dp->link_train.link_rate != LINK_RATE_1_62GBPS) &&
-	   (dp->link_train.link_rate != LINK_RATE_2_70GBPS)) {
-		dev_err(dp->dev, "Rx Max Link Rate is abnormal :%x !\n",
-			dp->link_train.link_rate);
-		dp->link_train.link_rate = LINK_RATE_1_62GBPS;
-	}
-
-	if (dp->link_train.lane_count == 0) {
-		dev_err(dp->dev, "Rx Max Lane count is abnormal :%x !\n",
-			dp->link_train.lane_count);
-		dp->link_train.lane_count = (u8)LANE_COUNT1;
-	}
-
-	/* Setup TX lane count & rate */
-	if (dp->link_train.lane_count > max_lane)
-		dp->link_train.lane_count = max_lane;
-	if (dp->link_train.link_rate > max_rate)
-		dp->link_train.link_rate = max_rate;
-
-	/* All DP analog module power up */
-	exynos_dp_set_analog_power_down(dp, POWER_ALL, 0);
-}
-
-static int exynos_dp_sw_link_training(struct exynos_dp_device *dp)
-{
-	int retval = 0, training_finished = 0;
-
-	dp->link_train.lt_state = START;
-
-	/* Process here */
-	while (!retval && !training_finished) {
-		switch (dp->link_train.lt_state) {
-		case START:
-			retval = exynos_dp_link_start(dp);
-			if (retval)
-				dev_err(dp->dev, "LT link start failed!\n");
-			break;
-		case CLOCK_RECOVERY:
-			retval = exynos_dp_process_clock_recovery(dp);
-			if (retval)
-				dev_err(dp->dev, "LT CR failed!\n");
-			break;
-		case EQUALIZER_TRAINING:
-			retval = exynos_dp_process_equalizer_training(dp);
-			if (retval)
-				dev_err(dp->dev, "LT EQ failed!\n");
-			break;
-		case FINISHED:
-			training_finished = 1;
-			break;
-		case FAILED:
-			return -EREMOTEIO;
-		}
-	}
-	if (retval)
-		dev_err(dp->dev, "eDP link training failed (%d)\n", retval);
-
-	return retval;
-}
-
-static int exynos_dp_set_link_train(struct exynos_dp_device *dp,
-				u32 count,
-				u32 bwtype)
-{
-	int i;
-	int retval;
-
-	for (i = 0; i < DP_TIMEOUT_LOOP_COUNT; i++) {
-		exynos_dp_init_training(dp, count, bwtype);
-		retval = exynos_dp_sw_link_training(dp);
-		if (retval == 0)
-			break;
-
-		usleep_range(100, 110);
-	}
-
-	return retval;
-}
-
-static int exynos_dp_config_video(struct exynos_dp_device *dp)
-{
-	int retval = 0;
-	int timeout_loop = 0;
-	int done_count = 0;
-
-	exynos_dp_config_video_slave_mode(dp);
-
-	exynos_dp_set_video_color_format(dp);
-
-	if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
-		dev_err(dp->dev, "PLL is not locked yet.\n");
-		return -EINVAL;
-	}
-
-	for (;;) {
-		timeout_loop++;
-		if (exynos_dp_is_slave_video_stream_clock_on(dp) == 0)
-			break;
-		if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
-			dev_err(dp->dev, "Timeout of video streamclk ok\n");
-			return -ETIMEDOUT;
-		}
-
-		usleep_range(1, 2);
-	}
-
-	/* Set to use the register calculated M/N video */
-	exynos_dp_set_video_cr_mn(dp, CALCULATED_M, 0, 0);
-
-	/* For video bist, Video timing must be generated by register */
-	exynos_dp_set_video_timing_mode(dp, VIDEO_TIMING_FROM_CAPTURE);
-
-	/* Disable video mute */
-	exynos_dp_enable_video_mute(dp, 0);
-
-	/* Configure video slave mode */
-	exynos_dp_enable_video_master(dp, 0);
-
-	timeout_loop = 0;
-
-	for (;;) {
-		timeout_loop++;
-		if (exynos_dp_is_video_stream_on(dp) == 0) {
-			done_count++;
-			if (done_count > 10)
-				break;
-		} else if (done_count) {
-			done_count = 0;
-		}
-		if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
-			dev_err(dp->dev, "Timeout of video streamclk ok\n");
-			return -ETIMEDOUT;
-		}
-
-		usleep_range(1000, 1001);
-	}
-
-	if (retval != 0)
-		dev_err(dp->dev, "Video stream is not detected!\n");
-
-	return retval;
-}
-
-static void exynos_dp_enable_scramble(struct exynos_dp_device *dp, bool enable)
-{
-	u8 data;
-
-	if (enable) {
-		exynos_dp_enable_scrambling(dp);
-
-		exynos_dp_read_byte_from_dpcd(dp,
-			DP_TRAINING_PATTERN_SET,
-			&data);
-		exynos_dp_write_byte_to_dpcd(dp,
-			DP_TRAINING_PATTERN_SET,
-			(u8)(data & ~DP_LINK_SCRAMBLING_DISABLE));
-	} else {
-		exynos_dp_disable_scrambling(dp);
-
-		exynos_dp_read_byte_from_dpcd(dp,
-			DP_TRAINING_PATTERN_SET,
-			&data);
-		exynos_dp_write_byte_to_dpcd(dp,
-			DP_TRAINING_PATTERN_SET,
-			(u8)(data | DP_LINK_SCRAMBLING_DISABLE));
-	}
-}
-
-static irqreturn_t exynos_dp_irq_handler(int irq, void *arg)
-{
-	struct exynos_dp_device *dp = arg;
-
-	enum dp_irq_type irq_type;
-
-	irq_type = exynos_dp_get_irq_type(dp);
-	switch (irq_type) {
-	case DP_IRQ_TYPE_HP_CABLE_IN:
-		dev_dbg(dp->dev, "Received irq - cable in\n");
-		schedule_work(&dp->hotplug_work);
-		exynos_dp_clear_hotplug_interrupts(dp);
-		break;
-	case DP_IRQ_TYPE_HP_CABLE_OUT:
-		dev_dbg(dp->dev, "Received irq - cable out\n");
-		exynos_dp_clear_hotplug_interrupts(dp);
-		break;
-	case DP_IRQ_TYPE_HP_CHANGE:
-		/*
-		 * We get these change notifications once in a while, but there
-		 * is nothing we can do with them. Just ignore it for now and
-		 * only handle cable changes.
-		 */
-		dev_dbg(dp->dev, "Received irq - hotplug change; ignoring.\n");
-		exynos_dp_clear_hotplug_interrupts(dp);
-		break;
-	default:
-		dev_err(dp->dev, "Received irq - unknown type!\n");
-		break;
-	}
-	return IRQ_HANDLED;
-}
-
-static void exynos_dp_hotplug(struct work_struct *work)
-{
-	struct exynos_dp_device *dp;
-
-	dp = container_of(work, struct exynos_dp_device, hotplug_work);
-
-	if (dp->drm_dev)
-		drm_helper_hpd_irq_event(dp->drm_dev);
-}
-
-static void exynos_dp_commit(struct drm_encoder *encoder)
-{
-	struct exynos_dp_device *dp = encoder_to_dp(encoder);
-	int ret;
-
-	/* Keep the panel disabled while we configure video */
-	if (dp->panel) {
-		if (drm_panel_disable(dp->panel))
-			DRM_ERROR("failed to disable the panel\n");
-	}
-
-	ret = exynos_dp_detect_hpd(dp);
-	if (ret) {
-		/* Cable has been disconnected, we're done */
-		return;
-	}
-
-	ret = exynos_dp_handle_edid(dp);
-	if (ret) {
-		dev_err(dp->dev, "unable to handle edid\n");
-		return;
-	}
-
-	ret = exynos_dp_set_link_train(dp, dp->video_info->lane_count,
-					dp->video_info->link_rate);
-	if (ret) {
-		dev_err(dp->dev, "unable to do link train\n");
-		return;
-	}
-
-	exynos_dp_enable_scramble(dp, 1);
-	exynos_dp_enable_rx_to_enhanced_mode(dp, 1);
-	exynos_dp_enable_enhanced_mode(dp, 1);
-
-	exynos_dp_set_lane_count(dp, dp->video_info->lane_count);
-	exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate);
-
-	exynos_dp_init_video(dp);
-	ret = exynos_dp_config_video(dp);
-	if (ret)
-		dev_err(dp->dev, "unable to config video\n");
-
-	/* Safe to enable the panel now */
-	if (dp->panel) {
-		if (drm_panel_enable(dp->panel))
-			DRM_ERROR("failed to enable the panel\n");
-	}
-
-	/* Enable video */
-	exynos_dp_start_video(dp);
-}
-
-static enum drm_connector_status exynos_dp_detect(
-				struct drm_connector *connector, bool force)
-{
-	return connector_status_connected;
-}
-
-static void exynos_dp_connector_destroy(struct drm_connector *connector)
-{
-	drm_connector_unregister(connector);
-	drm_connector_cleanup(connector);
-}
-
-static const struct drm_connector_funcs exynos_dp_connector_funcs = {
-	.dpms = drm_atomic_helper_connector_dpms,
-	.fill_modes = drm_helper_probe_single_connector_modes,
-	.detect = exynos_dp_detect,
-	.destroy = exynos_dp_connector_destroy,
-	.reset = drm_atomic_helper_connector_reset,
-	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
-	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
-};
-
-static int exynos_dp_get_modes(struct drm_connector *connector)
-{
-	struct exynos_dp_device *dp = ctx_from_connector(connector);
-	struct drm_display_mode *mode;
-
-	if (dp->panel)
-		return drm_panel_get_modes(dp->panel);
-
-	mode = drm_mode_create(connector->dev);
-	if (!mode) {
-		DRM_ERROR("failed to create a new display mode.\n");
-		return 0;
-	}
-
-	drm_display_mode_from_videomode(&dp->vm, mode);
-	connector->display_info.width_mm = mode->width_mm;
-	connector->display_info.height_mm = mode->height_mm;
-
-	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
-	drm_mode_set_name(mode);
-	drm_mode_probed_add(connector, mode);
-
-	return 1;
-}
-
-static struct drm_encoder *exynos_dp_best_encoder(
-			struct drm_connector *connector)
-{
-	struct exynos_dp_device *dp = ctx_from_connector(connector);
-
-	return &dp->encoder;
-}
-
-static const struct drm_connector_helper_funcs exynos_dp_connector_helper_funcs = {
-	.get_modes = exynos_dp_get_modes,
-	.best_encoder = exynos_dp_best_encoder,
-};
-
-/* returns the number of bridges attached */
-static int exynos_drm_attach_lcd_bridge(struct exynos_dp_device *dp,
-		struct drm_encoder *encoder)
-{
-	int ret;
-
-	encoder->bridge->next = dp->ptn_bridge;
-	dp->ptn_bridge->encoder = encoder;
-	ret = drm_bridge_attach(encoder->dev, dp->ptn_bridge);
-	if (ret) {
-		DRM_ERROR("Failed to attach bridge to drm\n");
-		return ret;
-	}
-
-	return 0;
-}
-
-static int exynos_dp_bridge_attach(struct drm_bridge *bridge)
-{
-	struct exynos_dp_device *dp = bridge->driver_private;
-	struct drm_encoder *encoder = &dp->encoder;
-	struct drm_connector *connector = &dp->connector;
-	int ret;
-
-	/* Pre-empt DP connector creation if there's a bridge */
-	if (dp->ptn_bridge) {
-		ret = exynos_drm_attach_lcd_bridge(dp, encoder);
-		if (!ret)
-			return 0;
-	}
-
-	connector->polled = DRM_CONNECTOR_POLL_HPD;
-
-	ret = drm_connector_init(dp->drm_dev, connector,
-			&exynos_dp_connector_funcs, DRM_MODE_CONNECTOR_eDP);
-	if (ret) {
-		DRM_ERROR("Failed to initialize connector with drm\n");
-		return ret;
-	}
-
-	drm_connector_helper_add(connector, &exynos_dp_connector_helper_funcs);
-	drm_connector_register(connector);
-	drm_mode_connector_attach_encoder(connector, encoder);
-
-	if (dp->panel)
-		ret = drm_panel_attach(dp->panel, &dp->connector);
-
-	return ret;
-}
-
-static void exynos_dp_bridge_enable(struct drm_bridge *bridge)
-{
-	struct exynos_dp_device *dp = bridge->driver_private;
-	struct exynos_drm_crtc *crtc = dp_to_crtc(dp);
-
-	if (dp->dpms_mode == DRM_MODE_DPMS_ON)
-		return;
-
-	pm_runtime_get_sync(dp->dev);
-
-	if (dp->panel) {
-		if (drm_panel_prepare(dp->panel)) {
-			DRM_ERROR("failed to setup the panel\n");
-			return;
-		}
-	}
-
-	if (crtc->ops->clock_enable)
-		crtc->ops->clock_enable(dp_to_crtc(dp), true);
-
-	phy_power_on(dp->phy);
-	exynos_dp_init_dp(dp);
-	enable_irq(dp->irq);
-	exynos_dp_commit(&dp->encoder);
-
-	dp->dpms_mode = DRM_MODE_DPMS_ON;
-}
-
-static void exynos_dp_bridge_disable(struct drm_bridge *bridge)
-{
-	struct exynos_dp_device *dp = bridge->driver_private;
-	struct exynos_drm_crtc *crtc = dp_to_crtc(dp);
-
-	if (dp->dpms_mode != DRM_MODE_DPMS_ON)
-		return;
-
-	if (dp->panel) {
-		if (drm_panel_disable(dp->panel)) {
-			DRM_ERROR("failed to disable the panel\n");
-			return;
-		}
-	}
-
-	disable_irq(dp->irq);
-	flush_work(&dp->hotplug_work);
-	phy_power_off(dp->phy);
-
-	if (crtc->ops->clock_enable)
-		crtc->ops->clock_enable(dp_to_crtc(dp), false);
-
-	if (dp->panel) {
-		if (drm_panel_unprepare(dp->panel))
-			DRM_ERROR("failed to turnoff the panel\n");
-	}
-
-	pm_runtime_put_sync(dp->dev);
-
-	dp->dpms_mode = DRM_MODE_DPMS_OFF;
-}
-
-static void exynos_dp_bridge_nop(struct drm_bridge *bridge)
-{
-	/* do nothing */
-}
-
-static const struct drm_bridge_funcs exynos_dp_bridge_funcs = {
-	.enable = exynos_dp_bridge_enable,
-	.disable = exynos_dp_bridge_disable,
-	.pre_enable = exynos_dp_bridge_nop,
-	.post_disable = exynos_dp_bridge_nop,
-	.attach = exynos_dp_bridge_attach,
-};
-
-static int exynos_dp_create_connector(struct drm_encoder *encoder)
-{
-	struct exynos_dp_device *dp = encoder_to_dp(encoder);
-	struct drm_device *drm_dev = dp->drm_dev;
-	struct drm_bridge *bridge;
-	int ret;
-
-	bridge = devm_kzalloc(drm_dev->dev, sizeof(*bridge), GFP_KERNEL);
-	if (!bridge) {
-		DRM_ERROR("failed to allocate for drm bridge\n");
-		return -ENOMEM;
-	}
-
-	dp->bridge = bridge;
-
-	encoder->bridge = bridge;
-	bridge->driver_private = dp;
-	bridge->encoder = encoder;
-	bridge->funcs = &exynos_dp_bridge_funcs;
-
-	ret = drm_bridge_attach(drm_dev, bridge);
-	if (ret) {
-		DRM_ERROR("failed to attach drm bridge\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static void exynos_dp_mode_set(struct drm_encoder *encoder,
-			       struct drm_display_mode *mode,
-			       struct drm_display_mode *adjusted_mode)
-{
-}
-
-static void exynos_dp_enable(struct drm_encoder *encoder)
-{
-}
-
-static void exynos_dp_disable(struct drm_encoder *encoder)
-{
-}
-
-static const struct drm_encoder_helper_funcs exynos_dp_encoder_helper_funcs = {
-	.mode_set = exynos_dp_mode_set,
-	.enable = exynos_dp_enable,
-	.disable = exynos_dp_disable,
-};
-
-static const struct drm_encoder_funcs exynos_dp_encoder_funcs = {
-	.destroy = drm_encoder_cleanup,
-};
-
-static struct video_info *exynos_dp_dt_parse_pdata(struct device *dev)
-{
-	struct device_node *dp_node = dev->of_node;
-	struct video_info *dp_video_config;
-
-	dp_video_config = devm_kzalloc(dev,
-				sizeof(*dp_video_config), GFP_KERNEL);
-	if (!dp_video_config)
-		return ERR_PTR(-ENOMEM);
-
-	dp_video_config->h_sync_polarity =
-		of_property_read_bool(dp_node, "hsync-active-high");
-
-	dp_video_config->v_sync_polarity =
-		of_property_read_bool(dp_node, "vsync-active-high");
-
-	dp_video_config->interlaced =
-		of_property_read_bool(dp_node, "interlaced");
-
-	if (of_property_read_u32(dp_node, "samsung,color-space",
-				&dp_video_config->color_space)) {
-		dev_err(dev, "failed to get color-space\n");
-		return ERR_PTR(-EINVAL);
-	}
-
-	if (of_property_read_u32(dp_node, "samsung,dynamic-range",
-				&dp_video_config->dynamic_range)) {
-		dev_err(dev, "failed to get dynamic-range\n");
-		return ERR_PTR(-EINVAL);
-	}
-
-	if (of_property_read_u32(dp_node, "samsung,ycbcr-coeff",
-				&dp_video_config->ycbcr_coeff)) {
-		dev_err(dev, "failed to get ycbcr-coeff\n");
-		return ERR_PTR(-EINVAL);
-	}
-
-	if (of_property_read_u32(dp_node, "samsung,color-depth",
-				&dp_video_config->color_depth)) {
-		dev_err(dev, "failed to get color-depth\n");
-		return ERR_PTR(-EINVAL);
-	}
-
-	if (of_property_read_u32(dp_node, "samsung,link-rate",
-				&dp_video_config->link_rate)) {
-		dev_err(dev, "failed to get link-rate\n");
-		return ERR_PTR(-EINVAL);
-	}
-
-	if (of_property_read_u32(dp_node, "samsung,lane-count",
-				&dp_video_config->lane_count)) {
-		dev_err(dev, "failed to get lane-count\n");
-		return ERR_PTR(-EINVAL);
-	}
-
-	return dp_video_config;
-}
-
-static int exynos_dp_dt_parse_panel(struct exynos_dp_device *dp)
-{
-	int ret;
-
-	ret = of_get_videomode(dp->dev->of_node, &dp->vm, OF_USE_NATIVE_MODE);
-	if (ret) {
-		DRM_ERROR("failed: of_get_videomode() : %d\n", ret);
-		return ret;
-	}
-	return 0;
-}
-
-static int exynos_dp_bind(struct device *dev, struct device *master, void *data)
-{
-	struct exynos_dp_device *dp = dev_get_drvdata(dev);
-	struct platform_device *pdev = to_platform_device(dev);
-	struct drm_device *drm_dev = data;
-	struct drm_encoder *encoder = &dp->encoder;
-	struct resource *res;
-	unsigned int irq_flags;
-	int pipe, ret = 0;
-
-	dp->dev = &pdev->dev;
-	dp->dpms_mode = DRM_MODE_DPMS_OFF;
-
-	dp->video_info = exynos_dp_dt_parse_pdata(&pdev->dev);
-	if (IS_ERR(dp->video_info))
-		return PTR_ERR(dp->video_info);
-
-	dp->phy = devm_phy_get(dp->dev, "dp");
-	if (IS_ERR(dp->phy)) {
-		dev_err(dp->dev, "no DP phy configured\n");
-		ret = PTR_ERR(dp->phy);
-		if (ret) {
-			/*
-			 * phy itself is not enabled, so we can move forward
-			 * assigning NULL to phy pointer.
-			 */
-			if (ret == -ENOSYS || ret == -ENODEV)
-				dp->phy = NULL;
-			else
-				return ret;
-		}
-	}
-
-	if (!dp->panel && !dp->ptn_bridge) {
-		ret = exynos_dp_dt_parse_panel(dp);
-		if (ret)
-			return ret;
-	}
-
-	dp->clock = devm_clk_get(&pdev->dev, "dp");
-	if (IS_ERR(dp->clock)) {
-		dev_err(&pdev->dev, "failed to get clock\n");
-		return PTR_ERR(dp->clock);
-	}
-
-	clk_prepare_enable(dp->clock);
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
-	dp->reg_base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(dp->reg_base))
-		return PTR_ERR(dp->reg_base);
-
-	dp->hpd_gpio = of_get_named_gpio(dev->of_node, "samsung,hpd-gpio", 0);
-
-	if (gpio_is_valid(dp->hpd_gpio)) {
-		/*
-		 * Set up the hotplug GPIO from the device tree as an interrupt.
-		 * Simply specifying a different interrupt in the device tree
-		 * doesn't work since we handle hotplug rather differently when
-		 * using a GPIO.  We also need the actual GPIO specifier so
-		 * that we can get the current state of the GPIO.
-		 */
-		ret = devm_gpio_request_one(&pdev->dev, dp->hpd_gpio, GPIOF_IN,
-					    "hpd_gpio");
-		if (ret) {
-			dev_err(&pdev->dev, "failed to get hpd gpio\n");
-			return ret;
-		}
-		dp->irq = gpio_to_irq(dp->hpd_gpio);
-		irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
-	} else {
-		dp->hpd_gpio = -ENODEV;
-		dp->irq = platform_get_irq(pdev, 0);
-		irq_flags = 0;
-	}
-
-	if (dp->irq == -ENXIO) {
-		dev_err(&pdev->dev, "failed to get irq\n");
-		return -ENODEV;
-	}
-
-	INIT_WORK(&dp->hotplug_work, exynos_dp_hotplug);
-
-	ret = devm_request_irq(&pdev->dev, dp->irq, exynos_dp_irq_handler,
-			irq_flags, "exynos-dp", dp);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to request irq\n");
-		return ret;
-	}
-	disable_irq(dp->irq);
-
-	dp->drm_dev = drm_dev;
-
-	pipe = exynos_drm_crtc_get_pipe_from_type(drm_dev,
-						  EXYNOS_DISPLAY_TYPE_LCD);
-	if (pipe < 0)
-		return pipe;
-
-	encoder->possible_crtcs = 1 << pipe;
-
-	DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
-
-	drm_encoder_init(drm_dev, encoder, &exynos_dp_encoder_funcs,
-			 DRM_MODE_ENCODER_TMDS, NULL);
-
-	drm_encoder_helper_add(encoder, &exynos_dp_encoder_helper_funcs);
-
-	ret = exynos_dp_create_connector(encoder);
-	if (ret) {
-		DRM_ERROR("failed to create connector ret = %d\n", ret);
-		drm_encoder_cleanup(encoder);
-		return ret;
-	}
-
-	return 0;
-}
-
-static void exynos_dp_unbind(struct device *dev, struct device *master,
-				void *data)
-{
-	struct exynos_dp_device *dp = dev_get_drvdata(dev);
-
-	exynos_dp_disable(&dp->encoder);
-}
-
-static const struct component_ops exynos_dp_ops = {
-	.bind	= exynos_dp_bind,
-	.unbind	= exynos_dp_unbind,
-};
-
-static int exynos_dp_probe(struct platform_device *pdev)
-{
-	struct device *dev = &pdev->dev;
-	struct device_node *np = NULL, *endpoint = NULL;
-	struct exynos_dp_device *dp;
-	int ret;
-
-	dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device),
-				GFP_KERNEL);
-	if (!dp)
-		return -ENOMEM;
-
-	platform_set_drvdata(pdev, dp);
-
-	/* This is for the backward compatibility. */
-	np = of_parse_phandle(dev->of_node, "panel", 0);
-	if (np) {
-		dp->panel = of_drm_find_panel(np);
-		of_node_put(np);
-		if (!dp->panel)
-			return -EPROBE_DEFER;
-		goto out;
-	}
-
-	endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
-	if (endpoint) {
-		np = of_graph_get_remote_port_parent(endpoint);
-		if (np) {
-			/* The remote port can be either a panel or a bridge */
-			dp->panel = of_drm_find_panel(np);
-			if (!dp->panel) {
-				dp->ptn_bridge = of_drm_find_bridge(np);
-				if (!dp->ptn_bridge) {
-					of_node_put(np);
-					return -EPROBE_DEFER;
-				}
-			}
-			of_node_put(np);
-		} else {
-			DRM_ERROR("no remote endpoint device node found.\n");
-			return -EINVAL;
-		}
-	} else {
-		DRM_ERROR("no port endpoint subnode found.\n");
-		return -EINVAL;
-	}
-
-out:
-	pm_runtime_enable(dev);
-
-	ret = component_add(&pdev->dev, &exynos_dp_ops);
-	if (ret)
-		goto err_disable_pm_runtime;
-
-	return ret;
-
-err_disable_pm_runtime:
-	pm_runtime_disable(dev);
-
-	return ret;
-}
-
-static int exynos_dp_remove(struct platform_device *pdev)
-{
-	pm_runtime_disable(&pdev->dev);
-	component_del(&pdev->dev, &exynos_dp_ops);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int exynos_dp_suspend(struct device *dev)
-{
-	struct exynos_dp_device *dp = dev_get_drvdata(dev);
-
-	clk_disable_unprepare(dp->clock);
-
-	return 0;
-}
-
-static int exynos_dp_resume(struct device *dev)
-{
-	struct exynos_dp_device *dp = dev_get_drvdata(dev);
-	int ret;
-
-	ret = clk_prepare_enable(dp->clock);
-	if (ret < 0) {
-		DRM_ERROR("Failed to prepare_enable the clock clk [%d]\n", ret);
-		return ret;
-	}
-
-	return 0;
-}
-#endif
-
-static const struct dev_pm_ops exynos_dp_pm_ops = {
-	SET_RUNTIME_PM_OPS(exynos_dp_suspend, exynos_dp_resume, NULL)
-};
-
-static const struct of_device_id exynos_dp_match[] = {
-	{ .compatible = "samsung,exynos5-dp" },
-	{},
-};
-MODULE_DEVICE_TABLE(of, exynos_dp_match);
-
-struct platform_driver dp_driver = {
-	.probe		= exynos_dp_probe,
-	.remove		= exynos_dp_remove,
-	.driver		= {
-		.name	= "exynos-dp",
-		.owner	= THIS_MODULE,
-		.pm	= &exynos_dp_pm_ops,
-		.of_match_table = exynos_dp_match,
-	},
-};
-
-MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
-MODULE_DESCRIPTION("Samsung SoC DP Driver");
-MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_dp_core.h linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_dp_core.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_dp_core.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_dp_core.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,282 +0,0 @@
-/*
- * Header file for Samsung DP (Display Port) interface driver.
- *
- * Copyright (C) 2012 Samsung Electronics Co., Ltd.
- * Author: Jingoo Han <jg1.han@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#ifndef _EXYNOS_DP_CORE_H
-#define _EXYNOS_DP_CORE_H
-
-#include <drm/drm_crtc.h>
-#include <drm/drm_dp_helper.h>
-#include <drm/exynos_drm.h>
-#include <video/videomode.h>
-
-#include "exynos_drm_drv.h"
-
-#define DP_TIMEOUT_LOOP_COUNT 100
-#define MAX_CR_LOOP 5
-#define MAX_EQ_LOOP 5
-
-enum link_rate_type {
-	LINK_RATE_1_62GBPS = 0x06,
-	LINK_RATE_2_70GBPS = 0x0a
-};
-
-enum link_lane_count_type {
-	LANE_COUNT1 = 1,
-	LANE_COUNT2 = 2,
-	LANE_COUNT4 = 4
-};
-
-enum link_training_state {
-	START,
-	CLOCK_RECOVERY,
-	EQUALIZER_TRAINING,
-	FINISHED,
-	FAILED
-};
-
-enum voltage_swing_level {
-	VOLTAGE_LEVEL_0,
-	VOLTAGE_LEVEL_1,
-	VOLTAGE_LEVEL_2,
-	VOLTAGE_LEVEL_3,
-};
-
-enum pre_emphasis_level {
-	PRE_EMPHASIS_LEVEL_0,
-	PRE_EMPHASIS_LEVEL_1,
-	PRE_EMPHASIS_LEVEL_2,
-	PRE_EMPHASIS_LEVEL_3,
-};
-
-enum pattern_set {
-	PRBS7,
-	D10_2,
-	TRAINING_PTN1,
-	TRAINING_PTN2,
-	DP_NONE
-};
-
-enum color_space {
-	COLOR_RGB,
-	COLOR_YCBCR422,
-	COLOR_YCBCR444
-};
-
-enum color_depth {
-	COLOR_6,
-	COLOR_8,
-	COLOR_10,
-	COLOR_12
-};
-
-enum color_coefficient {
-	COLOR_YCBCR601,
-	COLOR_YCBCR709
-};
-
-enum dynamic_range {
-	VESA,
-	CEA
-};
-
-enum pll_status {
-	PLL_UNLOCKED,
-	PLL_LOCKED
-};
-
-enum clock_recovery_m_value_type {
-	CALCULATED_M,
-	REGISTER_M
-};
-
-enum video_timing_recognition_type {
-	VIDEO_TIMING_FROM_CAPTURE,
-	VIDEO_TIMING_FROM_REGISTER
-};
-
-enum analog_power_block {
-	AUX_BLOCK,
-	CH0_BLOCK,
-	CH1_BLOCK,
-	CH2_BLOCK,
-	CH3_BLOCK,
-	ANALOG_TOTAL,
-	POWER_ALL
-};
-
-enum dp_irq_type {
-	DP_IRQ_TYPE_HP_CABLE_IN,
-	DP_IRQ_TYPE_HP_CABLE_OUT,
-	DP_IRQ_TYPE_HP_CHANGE,
-	DP_IRQ_TYPE_UNKNOWN,
-};
-
-struct video_info {
-	char *name;
-
-	bool h_sync_polarity;
-	bool v_sync_polarity;
-	bool interlaced;
-
-	enum color_space color_space;
-	enum dynamic_range dynamic_range;
-	enum color_coefficient ycbcr_coeff;
-	enum color_depth color_depth;
-
-	enum link_rate_type link_rate;
-	enum link_lane_count_type lane_count;
-};
-
-struct link_train {
-	int eq_loop;
-	int cr_loop[4];
-
-	u8 link_rate;
-	u8 lane_count;
-	u8 training_lane[4];
-
-	enum link_training_state lt_state;
-};
-
-struct exynos_dp_device {
-	struct drm_encoder	encoder;
-	struct device		*dev;
-	struct drm_device	*drm_dev;
-	struct drm_connector	connector;
-	struct drm_panel	*panel;
-	struct drm_bridge	*bridge;
-	struct drm_bridge	*ptn_bridge;
-	struct clk		*clock;
-	unsigned int		irq;
-	void __iomem		*reg_base;
-
-	struct video_info	*video_info;
-	struct link_train	link_train;
-	struct work_struct	hotplug_work;
-	struct phy		*phy;
-	int			dpms_mode;
-	int			hpd_gpio;
-	struct videomode	vm;
-};
-
-/* exynos_dp_reg.c */
-void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable);
-void exynos_dp_stop_video(struct exynos_dp_device *dp);
-void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable);
-void exynos_dp_init_analog_param(struct exynos_dp_device *dp);
-void exynos_dp_init_interrupt(struct exynos_dp_device *dp);
-void exynos_dp_reset(struct exynos_dp_device *dp);
-void exynos_dp_swreset(struct exynos_dp_device *dp);
-void exynos_dp_config_interrupt(struct exynos_dp_device *dp);
-enum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp);
-void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable);
-void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
-				enum analog_power_block block,
-				bool enable);
-void exynos_dp_init_analog_func(struct exynos_dp_device *dp);
-void exynos_dp_init_hpd(struct exynos_dp_device *dp);
-enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp);
-void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp);
-void exynos_dp_reset_aux(struct exynos_dp_device *dp);
-void exynos_dp_init_aux(struct exynos_dp_device *dp);
-int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp);
-void exynos_dp_enable_sw_function(struct exynos_dp_device *dp);
-int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp);
-int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp,
-				unsigned int reg_addr,
-				unsigned char data);
-int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp,
-				unsigned int reg_addr,
-				unsigned char *data);
-int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp,
-				unsigned int reg_addr,
-				unsigned int count,
-				unsigned char data[]);
-int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp,
-				unsigned int reg_addr,
-				unsigned int count,
-				unsigned char data[]);
-int exynos_dp_select_i2c_device(struct exynos_dp_device *dp,
-				unsigned int device_addr,
-				unsigned int reg_addr);
-int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp,
-				unsigned int device_addr,
-				unsigned int reg_addr,
-				unsigned int *data);
-int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp,
-				unsigned int device_addr,
-				unsigned int reg_addr,
-				unsigned int count,
-				unsigned char edid[]);
-void exynos_dp_set_link_bandwidth(struct exynos_dp_device *dp, u32 bwtype);
-void exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32 *bwtype);
-void exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count);
-void exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count);
-void exynos_dp_enable_enhanced_mode(struct exynos_dp_device *dp, bool enable);
-void exynos_dp_set_training_pattern(struct exynos_dp_device *dp,
-				 enum pattern_set pattern);
-void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32 level);
-void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32 level);
-void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32 level);
-void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32 level);
-void exynos_dp_set_lane0_link_training(struct exynos_dp_device *dp,
-				u32 training_lane);
-void exynos_dp_set_lane1_link_training(struct exynos_dp_device *dp,
-				u32 training_lane);
-void exynos_dp_set_lane2_link_training(struct exynos_dp_device *dp,
-				u32 training_lane);
-void exynos_dp_set_lane3_link_training(struct exynos_dp_device *dp,
-				u32 training_lane);
-u32 exynos_dp_get_lane0_link_training(struct exynos_dp_device *dp);
-u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp);
-u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp);
-u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp);
-void exynos_dp_reset_macro(struct exynos_dp_device *dp);
-void exynos_dp_init_video(struct exynos_dp_device *dp);
-
-void exynos_dp_set_video_color_format(struct exynos_dp_device *dp);
-int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp);
-void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp,
-			enum clock_recovery_m_value_type type,
-			u32 m_value,
-			u32 n_value);
-void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32 type);
-void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool enable);
-void exynos_dp_start_video(struct exynos_dp_device *dp);
-int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp);
-void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp);
-void exynos_dp_enable_scrambling(struct exynos_dp_device *dp);
-void exynos_dp_disable_scrambling(struct exynos_dp_device *dp);
-
-/* I2C EDID Chip ID, Slave Address */
-#define I2C_EDID_DEVICE_ADDR			0x50
-#define I2C_E_EDID_DEVICE_ADDR			0x30
-
-#define EDID_BLOCK_LENGTH			0x80
-#define EDID_HEADER_PATTERN			0x00
-#define EDID_EXTENSION_FLAG			0x7e
-#define EDID_CHECKSUM				0x7f
-
-/* DP_MAX_LANE_COUNT */
-#define DPCD_ENHANCED_FRAME_CAP(x)		(((x) >> 7) & 0x1)
-#define DPCD_MAX_LANE_COUNT(x)			((x) & 0x1f)
-
-/* DP_LANE_COUNT_SET */
-#define DPCD_LANE_COUNT_SET(x)			((x) & 0x1f)
-
-/* DP_TRAINING_LANE0_SET */
-#define DPCD_PRE_EMPHASIS_SET(x)		(((x) & 0x3) << 3)
-#define DPCD_PRE_EMPHASIS_GET(x)		(((x) >> 3) & 0x3)
-#define DPCD_VOLTAGE_SWING_SET(x)		(((x) & 0x3) << 0)
-#define DPCD_VOLTAGE_SWING_GET(x)		(((x) >> 0) & 0x3)
-
-#endif /* _EXYNOS_DP_CORE_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_dp_reg.c linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_dp_reg.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_dp_reg.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_dp_reg.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1263 +0,0 @@
-/*
- * Samsung DP (Display port) register interface driver.
- *
- * Copyright (C) 2012 Samsung Electronics Co., Ltd.
- * Author: Jingoo Han <jg1.han@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#include <linux/device.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/gpio.h>
-
-#include "exynos_dp_core.h"
-#include "exynos_dp_reg.h"
-
-#define COMMON_INT_MASK_1	0
-#define COMMON_INT_MASK_2	0
-#define COMMON_INT_MASK_3	0
-#define COMMON_INT_MASK_4	(HOTPLUG_CHG | HPD_LOST | PLUG)
-#define INT_STA_MASK		INT_HPD
-
-void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable)
-{
-	u32 reg;
-
-	if (enable) {
-		reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
-		reg |= HDCP_VIDEO_MUTE;
-		writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
-	} else {
-		reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
-		reg &= ~HDCP_VIDEO_MUTE;
-		writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
-	}
-}
-
-void exynos_dp_stop_video(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
-	reg &= ~VIDEO_EN;
-	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
-}
-
-void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable)
-{
-	u32 reg;
-
-	if (enable)
-		reg = LANE3_MAP_LOGIC_LANE_0 | LANE2_MAP_LOGIC_LANE_1 |
-			LANE1_MAP_LOGIC_LANE_2 | LANE0_MAP_LOGIC_LANE_3;
-	else
-		reg = LANE3_MAP_LOGIC_LANE_3 | LANE2_MAP_LOGIC_LANE_2 |
-			LANE1_MAP_LOGIC_LANE_1 | LANE0_MAP_LOGIC_LANE_0;
-
-	writel(reg, dp->reg_base + EXYNOS_DP_LANE_MAP);
-}
-
-void exynos_dp_init_analog_param(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = TX_TERMINAL_CTRL_50_OHM;
-	writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_1);
-
-	reg = SEL_24M | TX_DVDD_BIT_1_0625V;
-	writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_2);
-
-	reg = DRIVE_DVDD_BIT_1_0625V | VCO_BIT_600_MICRO;
-	writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_3);
-
-	reg = PD_RING_OSC | AUX_TERMINAL_CTRL_50_OHM |
-		TX_CUR1_2X | TX_CUR_16_MA;
-	writel(reg, dp->reg_base + EXYNOS_DP_PLL_FILTER_CTL_1);
-
-	reg = CH3_AMP_400_MV | CH2_AMP_400_MV |
-		CH1_AMP_400_MV | CH0_AMP_400_MV;
-	writel(reg, dp->reg_base + EXYNOS_DP_TX_AMP_TUNING_CTL);
-}
-
-void exynos_dp_init_interrupt(struct exynos_dp_device *dp)
-{
-	/* Set interrupt pin assertion polarity as high */
-	writel(INT_POL1 | INT_POL0, dp->reg_base + EXYNOS_DP_INT_CTL);
-
-	/* Clear pending regisers */
-	writel(0xff, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
-	writel(0x4f, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_2);
-	writel(0xe0, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_3);
-	writel(0xe7, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
-	writel(0x63, dp->reg_base + EXYNOS_DP_INT_STA);
-
-	/* 0:mask,1: unmask */
-	writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_1);
-	writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_2);
-	writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_3);
-	writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_4);
-	writel(0x00, dp->reg_base + EXYNOS_DP_INT_STA_MASK);
-}
-
-void exynos_dp_reset(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	exynos_dp_stop_video(dp);
-	exynos_dp_enable_video_mute(dp, 0);
-
-	reg = MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N |
-		AUD_FIFO_FUNC_EN_N | AUD_FUNC_EN_N |
-		HDCP_FUNC_EN_N | SW_FUNC_EN_N;
-	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
-
-	reg = SSC_FUNC_EN_N | AUX_FUNC_EN_N |
-		SERDES_FIFO_FUNC_EN_N |
-		LS_CLK_DOMAIN_FUNC_EN_N;
-	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
-
-	usleep_range(20, 30);
-
-	exynos_dp_lane_swap(dp, 0);
-
-	writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
-	writel(0x40, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
-	writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
-	writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
-
-	writel(0x0, dp->reg_base + EXYNOS_DP_PKT_SEND_CTL);
-	writel(0x0, dp->reg_base + EXYNOS_DP_HDCP_CTL);
-
-	writel(0x5e, dp->reg_base + EXYNOS_DP_HPD_DEGLITCH_L);
-	writel(0x1a, dp->reg_base + EXYNOS_DP_HPD_DEGLITCH_H);
-
-	writel(0x10, dp->reg_base + EXYNOS_DP_LINK_DEBUG_CTL);
-
-	writel(0x0, dp->reg_base + EXYNOS_DP_PHY_TEST);
-
-	writel(0x0, dp->reg_base + EXYNOS_DP_VIDEO_FIFO_THRD);
-	writel(0x20, dp->reg_base + EXYNOS_DP_AUDIO_MARGIN);
-
-	writel(0x4, dp->reg_base + EXYNOS_DP_M_VID_GEN_FILTER_TH);
-	writel(0x2, dp->reg_base + EXYNOS_DP_M_AUD_GEN_FILTER_TH);
-
-	writel(0x00000101, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
-}
-
-void exynos_dp_swreset(struct exynos_dp_device *dp)
-{
-	writel(RESET_DP_TX, dp->reg_base + EXYNOS_DP_TX_SW_RESET);
-}
-
-void exynos_dp_config_interrupt(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	/* 0: mask, 1: unmask */
-	reg = COMMON_INT_MASK_1;
-	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_1);
-
-	reg = COMMON_INT_MASK_2;
-	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_2);
-
-	reg = COMMON_INT_MASK_3;
-	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_3);
-
-	reg = COMMON_INT_MASK_4;
-	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_4);
-
-	reg = INT_STA_MASK;
-	writel(reg, dp->reg_base + EXYNOS_DP_INT_STA_MASK);
-}
-
-enum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_DEBUG_CTL);
-	if (reg & PLL_LOCK)
-		return PLL_LOCKED;
-	else
-		return PLL_UNLOCKED;
-}
-
-void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable)
-{
-	u32 reg;
-
-	if (enable) {
-		reg = readl(dp->reg_base + EXYNOS_DP_PLL_CTL);
-		reg |= DP_PLL_PD;
-		writel(reg, dp->reg_base + EXYNOS_DP_PLL_CTL);
-	} else {
-		reg = readl(dp->reg_base + EXYNOS_DP_PLL_CTL);
-		reg &= ~DP_PLL_PD;
-		writel(reg, dp->reg_base + EXYNOS_DP_PLL_CTL);
-	}
-}
-
-void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
-				enum analog_power_block block,
-				bool enable)
-{
-	u32 reg;
-
-	switch (block) {
-	case AUX_BLOCK:
-		if (enable) {
-			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-			reg |= AUX_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		} else {
-			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-			reg &= ~AUX_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		}
-		break;
-	case CH0_BLOCK:
-		if (enable) {
-			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-			reg |= CH0_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		} else {
-			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-			reg &= ~CH0_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		}
-		break;
-	case CH1_BLOCK:
-		if (enable) {
-			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-			reg |= CH1_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		} else {
-			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-			reg &= ~CH1_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		}
-		break;
-	case CH2_BLOCK:
-		if (enable) {
-			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-			reg |= CH2_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		} else {
-			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-			reg &= ~CH2_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		}
-		break;
-	case CH3_BLOCK:
-		if (enable) {
-			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-			reg |= CH3_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		} else {
-			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-			reg &= ~CH3_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		}
-		break;
-	case ANALOG_TOTAL:
-		if (enable) {
-			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-			reg |= DP_PHY_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		} else {
-			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
-			reg &= ~DP_PHY_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		}
-		break;
-	case POWER_ALL:
-		if (enable) {
-			reg = DP_PHY_PD | AUX_PD | CH3_PD | CH2_PD |
-				CH1_PD | CH0_PD;
-			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
-		} else {
-			writel(0x00, dp->reg_base + EXYNOS_DP_PHY_PD);
-		}
-		break;
-	default:
-		break;
-	}
-}
-
-void exynos_dp_init_analog_func(struct exynos_dp_device *dp)
-{
-	u32 reg;
-	int timeout_loop = 0;
-
-	exynos_dp_set_analog_power_down(dp, POWER_ALL, 0);
-
-	reg = PLL_LOCK_CHG;
-	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
-
-	reg = readl(dp->reg_base + EXYNOS_DP_DEBUG_CTL);
-	reg &= ~(F_PLL_LOCK | PLL_LOCK_CTRL);
-	writel(reg, dp->reg_base + EXYNOS_DP_DEBUG_CTL);
-
-	/* Power up PLL */
-	if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
-		exynos_dp_set_pll_power_down(dp, 0);
-
-		while (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
-			timeout_loop++;
-			if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
-				dev_err(dp->dev, "failed to get pll lock status\n");
-				return;
-			}
-			usleep_range(10, 20);
-		}
-	}
-
-	/* Enable Serdes FIFO function and Link symbol clock domain module */
-	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
-	reg &= ~(SERDES_FIFO_FUNC_EN_N | LS_CLK_DOMAIN_FUNC_EN_N
-		| AUX_FUNC_EN_N);
-	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
-}
-
-void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	if (gpio_is_valid(dp->hpd_gpio))
-		return;
-
-	reg = HOTPLUG_CHG | HPD_LOST | PLUG;
-	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
-
-	reg = INT_HPD;
-	writel(reg, dp->reg_base + EXYNOS_DP_INT_STA);
-}
-
-void exynos_dp_init_hpd(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	if (gpio_is_valid(dp->hpd_gpio))
-		return;
-
-	exynos_dp_clear_hotplug_interrupts(dp);
-
-	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
-	reg &= ~(F_HPD | HPD_CTRL);
-	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
-}
-
-enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	if (gpio_is_valid(dp->hpd_gpio)) {
-		reg = gpio_get_value(dp->hpd_gpio);
-		if (reg)
-			return DP_IRQ_TYPE_HP_CABLE_IN;
-		else
-			return DP_IRQ_TYPE_HP_CABLE_OUT;
-	} else {
-		/* Parse hotplug interrupt status register */
-		reg = readl(dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
-
-		if (reg & PLUG)
-			return DP_IRQ_TYPE_HP_CABLE_IN;
-
-		if (reg & HPD_LOST)
-			return DP_IRQ_TYPE_HP_CABLE_OUT;
-
-		if (reg & HOTPLUG_CHG)
-			return DP_IRQ_TYPE_HP_CHANGE;
-
-		return DP_IRQ_TYPE_UNKNOWN;
-	}
-}
-
-void exynos_dp_reset_aux(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	/* Disable AUX channel module */
-	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
-	reg |= AUX_FUNC_EN_N;
-	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
-}
-
-void exynos_dp_init_aux(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	/* Clear inerrupts related to AUX channel */
-	reg = RPLY_RECEIV | AUX_ERR;
-	writel(reg, dp->reg_base + EXYNOS_DP_INT_STA);
-
-	exynos_dp_reset_aux(dp);
-
-	/* Disable AUX transaction H/W retry */
-	reg = AUX_BIT_PERIOD_EXPECTED_DELAY(3) | AUX_HW_RETRY_COUNT_SEL(0)|
-		AUX_HW_RETRY_INTERVAL_600_MICROSECONDS;
-	writel(reg, dp->reg_base + EXYNOS_DP_AUX_HW_RETRY_CTL);
-
-	/* Receive AUX Channel DEFER commands equal to DEFFER_COUNT*64 */
-	reg = DEFER_CTRL_EN | DEFER_COUNT(1);
-	writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_DEFER_CTL);
-
-	/* Enable AUX channel module */
-	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
-	reg &= ~AUX_FUNC_EN_N;
-	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
-}
-
-int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	if (gpio_is_valid(dp->hpd_gpio)) {
-		if (gpio_get_value(dp->hpd_gpio))
-			return 0;
-	} else {
-		reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
-		if (reg & HPD_STATUS)
-			return 0;
-	}
-
-	return -EINVAL;
-}
-
-void exynos_dp_enable_sw_function(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_1);
-	reg &= ~SW_FUNC_EN_N;
-	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
-}
-
-int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp)
-{
-	int reg;
-	int retval = 0;
-	int timeout_loop = 0;
-
-	/* Enable AUX CH operation */
-	reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
-	reg |= AUX_EN;
-	writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
-
-	/* Is AUX CH command reply received? */
-	reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
-	while (!(reg & RPLY_RECEIV)) {
-		timeout_loop++;
-		if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
-			dev_err(dp->dev, "AUX CH command reply failed!\n");
-			return -ETIMEDOUT;
-		}
-		reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
-		usleep_range(10, 11);
-	}
-
-	/* Clear interrupt source for AUX CH command reply */
-	writel(RPLY_RECEIV, dp->reg_base + EXYNOS_DP_INT_STA);
-
-	/* Clear interrupt source for AUX CH access error */
-	reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
-	if (reg & AUX_ERR) {
-		writel(AUX_ERR, dp->reg_base + EXYNOS_DP_INT_STA);
-		return -EREMOTEIO;
-	}
-
-	/* Check AUX CH error access status */
-	reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_STA);
-	if ((reg & AUX_STATUS_MASK) != 0) {
-		dev_err(dp->dev, "AUX CH error happens: %d\n\n",
-			reg & AUX_STATUS_MASK);
-		return -EREMOTEIO;
-	}
-
-	return retval;
-}
-
-int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp,
-				unsigned int reg_addr,
-				unsigned char data)
-{
-	u32 reg;
-	int i;
-	int retval;
-
-	for (i = 0; i < 3; i++) {
-		/* Clear AUX CH data buffer */
-		reg = BUF_CLR;
-		writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
-
-		/* Select DPCD device address */
-		reg = AUX_ADDR_7_0(reg_addr);
-		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
-		reg = AUX_ADDR_15_8(reg_addr);
-		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
-		reg = AUX_ADDR_19_16(reg_addr);
-		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
-
-		/* Write data buffer */
-		reg = (unsigned int)data;
-		writel(reg, dp->reg_base + EXYNOS_DP_BUF_DATA_0);
-
-		/*
-		 * Set DisplayPort transaction and write 1 byte
-		 * If bit 3 is 1, DisplayPort transaction.
-		 * If Bit 3 is 0, I2C transaction.
-		 */
-		reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE;
-		writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
-
-		/* Start AUX transaction */
-		retval = exynos_dp_start_aux_transaction(dp);
-		if (retval == 0)
-			break;
-		else
-			dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
-				__func__);
-	}
-
-	return retval;
-}
-
-int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp,
-				unsigned int reg_addr,
-				unsigned char *data)
-{
-	u32 reg;
-	int i;
-	int retval;
-
-	for (i = 0; i < 3; i++) {
-		/* Clear AUX CH data buffer */
-		reg = BUF_CLR;
-		writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
-
-		/* Select DPCD device address */
-		reg = AUX_ADDR_7_0(reg_addr);
-		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
-		reg = AUX_ADDR_15_8(reg_addr);
-		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
-		reg = AUX_ADDR_19_16(reg_addr);
-		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
-
-		/*
-		 * Set DisplayPort transaction and read 1 byte
-		 * If bit 3 is 1, DisplayPort transaction.
-		 * If Bit 3 is 0, I2C transaction.
-		 */
-		reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ;
-		writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
-
-		/* Start AUX transaction */
-		retval = exynos_dp_start_aux_transaction(dp);
-		if (retval == 0)
-			break;
-		else
-			dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
-				__func__);
-	}
-
-	/* Read data buffer */
-	reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0);
-	*data = (unsigned char)(reg & 0xff);
-
-	return retval;
-}
-
-int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp,
-				unsigned int reg_addr,
-				unsigned int count,
-				unsigned char data[])
-{
-	u32 reg;
-	unsigned int start_offset;
-	unsigned int cur_data_count;
-	unsigned int cur_data_idx;
-	int i;
-	int retval = 0;
-
-	/* Clear AUX CH data buffer */
-	reg = BUF_CLR;
-	writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
-
-	start_offset = 0;
-	while (start_offset < count) {
-		/* Buffer size of AUX CH is 16 * 4bytes */
-		if ((count - start_offset) > 16)
-			cur_data_count = 16;
-		else
-			cur_data_count = count - start_offset;
-
-		for (i = 0; i < 3; i++) {
-			/* Select DPCD device address */
-			reg = AUX_ADDR_7_0(reg_addr + start_offset);
-			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
-			reg = AUX_ADDR_15_8(reg_addr + start_offset);
-			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
-			reg = AUX_ADDR_19_16(reg_addr + start_offset);
-			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
-
-			for (cur_data_idx = 0; cur_data_idx < cur_data_count;
-			     cur_data_idx++) {
-				reg = data[start_offset + cur_data_idx];
-				writel(reg, dp->reg_base + EXYNOS_DP_BUF_DATA_0
-							  + 4 * cur_data_idx);
-			}
-
-			/*
-			 * Set DisplayPort transaction and write
-			 * If bit 3 is 1, DisplayPort transaction.
-			 * If Bit 3 is 0, I2C transaction.
-			 */
-			reg = AUX_LENGTH(cur_data_count) |
-				AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE;
-			writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
-
-			/* Start AUX transaction */
-			retval = exynos_dp_start_aux_transaction(dp);
-			if (retval == 0)
-				break;
-			else
-				dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
-					__func__);
-		}
-
-		start_offset += cur_data_count;
-	}
-
-	return retval;
-}
-
-int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp,
-				unsigned int reg_addr,
-				unsigned int count,
-				unsigned char data[])
-{
-	u32 reg;
-	unsigned int start_offset;
-	unsigned int cur_data_count;
-	unsigned int cur_data_idx;
-	int i;
-	int retval = 0;
-
-	/* Clear AUX CH data buffer */
-	reg = BUF_CLR;
-	writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
-
-	start_offset = 0;
-	while (start_offset < count) {
-		/* Buffer size of AUX CH is 16 * 4bytes */
-		if ((count - start_offset) > 16)
-			cur_data_count = 16;
-		else
-			cur_data_count = count - start_offset;
-
-		/* AUX CH Request Transaction process */
-		for (i = 0; i < 3; i++) {
-			/* Select DPCD device address */
-			reg = AUX_ADDR_7_0(reg_addr + start_offset);
-			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
-			reg = AUX_ADDR_15_8(reg_addr + start_offset);
-			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
-			reg = AUX_ADDR_19_16(reg_addr + start_offset);
-			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
-
-			/*
-			 * Set DisplayPort transaction and read
-			 * If bit 3 is 1, DisplayPort transaction.
-			 * If Bit 3 is 0, I2C transaction.
-			 */
-			reg = AUX_LENGTH(cur_data_count) |
-				AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ;
-			writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
-
-			/* Start AUX transaction */
-			retval = exynos_dp_start_aux_transaction(dp);
-			if (retval == 0)
-				break;
-			else
-				dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
-					__func__);
-		}
-
-		for (cur_data_idx = 0; cur_data_idx < cur_data_count;
-		    cur_data_idx++) {
-			reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0
-						 + 4 * cur_data_idx);
-			data[start_offset + cur_data_idx] =
-				(unsigned char)reg;
-		}
-
-		start_offset += cur_data_count;
-	}
-
-	return retval;
-}
-
-int exynos_dp_select_i2c_device(struct exynos_dp_device *dp,
-				unsigned int device_addr,
-				unsigned int reg_addr)
-{
-	u32 reg;
-	int retval;
-
-	/* Set EDID device address */
-	reg = device_addr;
-	writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
-	writel(0x0, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
-	writel(0x0, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
-
-	/* Set offset from base address of EDID device */
-	writel(reg_addr, dp->reg_base + EXYNOS_DP_BUF_DATA_0);
-
-	/*
-	 * Set I2C transaction and write address
-	 * If bit 3 is 1, DisplayPort transaction.
-	 * If Bit 3 is 0, I2C transaction.
-	 */
-	reg = AUX_TX_COMM_I2C_TRANSACTION | AUX_TX_COMM_MOT |
-		AUX_TX_COMM_WRITE;
-	writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
-
-	/* Start AUX transaction */
-	retval = exynos_dp_start_aux_transaction(dp);
-	if (retval != 0)
-		dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__);
-
-	return retval;
-}
-
-int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp,
-				unsigned int device_addr,
-				unsigned int reg_addr,
-				unsigned int *data)
-{
-	u32 reg;
-	int i;
-	int retval;
-
-	for (i = 0; i < 3; i++) {
-		/* Clear AUX CH data buffer */
-		reg = BUF_CLR;
-		writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
-
-		/* Select EDID device */
-		retval = exynos_dp_select_i2c_device(dp, device_addr, reg_addr);
-		if (retval != 0)
-			continue;
-
-		/*
-		 * Set I2C transaction and read data
-		 * If bit 3 is 1, DisplayPort transaction.
-		 * If Bit 3 is 0, I2C transaction.
-		 */
-		reg = AUX_TX_COMM_I2C_TRANSACTION |
-			AUX_TX_COMM_READ;
-		writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
-
-		/* Start AUX transaction */
-		retval = exynos_dp_start_aux_transaction(dp);
-		if (retval == 0)
-			break;
-		else
-			dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
-				__func__);
-	}
-
-	/* Read data */
-	if (retval == 0)
-		*data = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0);
-
-	return retval;
-}
-
-int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp,
-				unsigned int device_addr,
-				unsigned int reg_addr,
-				unsigned int count,
-				unsigned char edid[])
-{
-	u32 reg;
-	unsigned int i, j;
-	unsigned int cur_data_idx;
-	unsigned int defer = 0;
-	int retval = 0;
-
-	for (i = 0; i < count; i += 16) {
-		for (j = 0; j < 3; j++) {
-			/* Clear AUX CH data buffer */
-			reg = BUF_CLR;
-			writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
-
-			/* Set normal AUX CH command */
-			reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
-			reg &= ~ADDR_ONLY;
-			writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
-
-			/*
-			 * If Rx sends defer, Tx sends only reads
-			 * request without sending address
-			 */
-			if (!defer)
-				retval = exynos_dp_select_i2c_device(dp,
-						device_addr, reg_addr + i);
-			else
-				defer = 0;
-
-			if (retval == 0) {
-				/*
-				 * Set I2C transaction and write data
-				 * If bit 3 is 1, DisplayPort transaction.
-				 * If Bit 3 is 0, I2C transaction.
-				 */
-				reg = AUX_LENGTH(16) |
-					AUX_TX_COMM_I2C_TRANSACTION |
-					AUX_TX_COMM_READ;
-				writel(reg, dp->reg_base +
-					EXYNOS_DP_AUX_CH_CTL_1);
-
-				/* Start AUX transaction */
-				retval = exynos_dp_start_aux_transaction(dp);
-				if (retval == 0)
-					break;
-				else
-					dev_dbg(dp->dev,
-						"%s: Aux Transaction fail!\n",
-						__func__);
-			}
-			/* Check if Rx sends defer */
-			reg = readl(dp->reg_base + EXYNOS_DP_AUX_RX_COMM);
-			if (reg == AUX_RX_COMM_AUX_DEFER ||
-				reg == AUX_RX_COMM_I2C_DEFER) {
-				dev_err(dp->dev, "Defer: %d\n\n", reg);
-				defer = 1;
-			}
-		}
-
-		for (cur_data_idx = 0; cur_data_idx < 16; cur_data_idx++) {
-			reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0
-						 + 4 * cur_data_idx);
-			edid[i + cur_data_idx] = (unsigned char)reg;
-		}
-	}
-
-	return retval;
-}
-
-void exynos_dp_set_link_bandwidth(struct exynos_dp_device *dp, u32 bwtype)
-{
-	u32 reg;
-
-	reg = bwtype;
-	if ((bwtype == LINK_RATE_2_70GBPS) || (bwtype == LINK_RATE_1_62GBPS))
-		writel(reg, dp->reg_base + EXYNOS_DP_LINK_BW_SET);
-}
-
-void exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32 *bwtype)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_LINK_BW_SET);
-	*bwtype = reg;
-}
-
-void exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count)
-{
-	u32 reg;
-
-	reg = count;
-	writel(reg, dp->reg_base + EXYNOS_DP_LANE_COUNT_SET);
-}
-
-void exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_LANE_COUNT_SET);
-	*count = reg;
-}
-
-void exynos_dp_enable_enhanced_mode(struct exynos_dp_device *dp, bool enable)
-{
-	u32 reg;
-
-	if (enable) {
-		reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
-		reg |= ENHANCED;
-		writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
-	} else {
-		reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
-		reg &= ~ENHANCED;
-		writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
-	}
-}
-
-void exynos_dp_set_training_pattern(struct exynos_dp_device *dp,
-				 enum pattern_set pattern)
-{
-	u32 reg;
-
-	switch (pattern) {
-	case PRBS7:
-		reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_PRBS7;
-		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
-		break;
-	case D10_2:
-		reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_D10_2;
-		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
-		break;
-	case TRAINING_PTN1:
-		reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN1;
-		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
-		break;
-	case TRAINING_PTN2:
-		reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN2;
-		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
-		break;
-	case DP_NONE:
-		reg = SCRAMBLING_ENABLE |
-			LINK_QUAL_PATTERN_SET_DISABLE |
-			SW_TRAINING_PATTERN_SET_NORMAL;
-		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
-		break;
-	default:
-		break;
-	}
-}
-
-void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32 level)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
-	reg &= ~PRE_EMPHASIS_SET_MASK;
-	reg |= level << PRE_EMPHASIS_SET_SHIFT;
-	writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
-}
-
-void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32 level)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
-	reg &= ~PRE_EMPHASIS_SET_MASK;
-	reg |= level << PRE_EMPHASIS_SET_SHIFT;
-	writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
-}
-
-void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32 level)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
-	reg &= ~PRE_EMPHASIS_SET_MASK;
-	reg |= level << PRE_EMPHASIS_SET_SHIFT;
-	writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
-}
-
-void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32 level)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
-	reg &= ~PRE_EMPHASIS_SET_MASK;
-	reg |= level << PRE_EMPHASIS_SET_SHIFT;
-	writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
-}
-
-void exynos_dp_set_lane0_link_training(struct exynos_dp_device *dp,
-					u32 training_lane)
-{
-	u32 reg;
-
-	reg = training_lane;
-	writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
-}
-
-void exynos_dp_set_lane1_link_training(struct exynos_dp_device *dp,
-					u32 training_lane)
-{
-	u32 reg;
-
-	reg = training_lane;
-	writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
-}
-
-void exynos_dp_set_lane2_link_training(struct exynos_dp_device *dp,
-					u32 training_lane)
-{
-	u32 reg;
-
-	reg = training_lane;
-	writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
-}
-
-void exynos_dp_set_lane3_link_training(struct exynos_dp_device *dp,
-					u32 training_lane)
-{
-	u32 reg;
-
-	reg = training_lane;
-	writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
-}
-
-u32 exynos_dp_get_lane0_link_training(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
-	return reg;
-}
-
-u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
-	return reg;
-}
-
-u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
-	return reg;
-}
-
-u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
-	return reg;
-}
-
-void exynos_dp_reset_macro(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_PHY_TEST);
-	reg |= MACRO_RST;
-	writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST);
-
-	/* 10 us is the minimum reset time. */
-	usleep_range(10, 20);
-
-	reg &= ~MACRO_RST;
-	writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST);
-}
-
-void exynos_dp_init_video(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = VSYNC_DET | VID_FORMAT_CHG | VID_CLK_CHG;
-	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
-
-	reg = 0x0;
-	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
-
-	reg = CHA_CRI(4) | CHA_CTRL;
-	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
-
-	reg = 0x0;
-	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
-
-	reg = VID_HRES_TH(2) | VID_VRES_TH(0);
-	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_8);
-}
-
-void exynos_dp_set_video_color_format(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	/* Configure the input color depth, color space, dynamic range */
-	reg = (dp->video_info->dynamic_range << IN_D_RANGE_SHIFT) |
-		(dp->video_info->color_depth << IN_BPC_SHIFT) |
-		(dp->video_info->color_space << IN_COLOR_F_SHIFT);
-	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_2);
-
-	/* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */
-	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_3);
-	reg &= ~IN_YC_COEFFI_MASK;
-	if (dp->video_info->ycbcr_coeff)
-		reg |= IN_YC_COEFFI_ITU709;
-	else
-		reg |= IN_YC_COEFFI_ITU601;
-	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_3);
-}
-
-int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_1);
-	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
-
-	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_1);
-
-	if (!(reg & DET_STA)) {
-		dev_dbg(dp->dev, "Input stream clock not detected.\n");
-		return -EINVAL;
-	}
-
-	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_2);
-	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
-
-	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_2);
-	dev_dbg(dp->dev, "wait SYS_CTL_2.\n");
-
-	if (reg & CHA_STA) {
-		dev_dbg(dp->dev, "Input stream clk is changing\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp,
-		enum clock_recovery_m_value_type type,
-		u32 m_value,
-		u32 n_value)
-{
-	u32 reg;
-
-	if (type == REGISTER_M) {
-		reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
-		reg |= FIX_M_VID;
-		writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
-		reg = m_value & 0xff;
-		writel(reg, dp->reg_base + EXYNOS_DP_M_VID_0);
-		reg = (m_value >> 8) & 0xff;
-		writel(reg, dp->reg_base + EXYNOS_DP_M_VID_1);
-		reg = (m_value >> 16) & 0xff;
-		writel(reg, dp->reg_base + EXYNOS_DP_M_VID_2);
-
-		reg = n_value & 0xff;
-		writel(reg, dp->reg_base + EXYNOS_DP_N_VID_0);
-		reg = (n_value >> 8) & 0xff;
-		writel(reg, dp->reg_base + EXYNOS_DP_N_VID_1);
-		reg = (n_value >> 16) & 0xff;
-		writel(reg, dp->reg_base + EXYNOS_DP_N_VID_2);
-	} else  {
-		reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
-		reg &= ~FIX_M_VID;
-		writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
-
-		writel(0x00, dp->reg_base + EXYNOS_DP_N_VID_0);
-		writel(0x80, dp->reg_base + EXYNOS_DP_N_VID_1);
-		writel(0x00, dp->reg_base + EXYNOS_DP_N_VID_2);
-	}
-}
-
-void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32 type)
-{
-	u32 reg;
-
-	if (type == VIDEO_TIMING_FROM_CAPTURE) {
-		reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-		reg &= ~FORMAT_SEL;
-		writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-	} else {
-		reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-		reg |= FORMAT_SEL;
-		writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-	}
-}
-
-void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool enable)
-{
-	u32 reg;
-
-	if (enable) {
-		reg = readl(dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
-		reg &= ~VIDEO_MODE_MASK;
-		reg |= VIDEO_MASTER_MODE_EN | VIDEO_MODE_MASTER_MODE;
-		writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
-	} else {
-		reg = readl(dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
-		reg &= ~VIDEO_MODE_MASK;
-		reg |= VIDEO_MODE_SLAVE_MODE;
-		writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
-	}
-}
-
-void exynos_dp_start_video(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
-	reg |= VIDEO_EN;
-	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
-}
-
-int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
-	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
-
-	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
-	if (!(reg & STRM_VALID)) {
-		dev_dbg(dp->dev, "Input video stream is not detected.\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_1);
-	reg &= ~(MASTER_VID_FUNC_EN_N|SLAVE_VID_FUNC_EN_N);
-	reg |= MASTER_VID_FUNC_EN_N;
-	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
-
-	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-	reg &= ~INTERACE_SCAN_CFG;
-	reg |= (dp->video_info->interlaced << 2);
-	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-
-	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-	reg &= ~VSYNC_POLARITY_CFG;
-	reg |= (dp->video_info->v_sync_polarity << 1);
-	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-
-	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-	reg &= ~HSYNC_POLARITY_CFG;
-	reg |= (dp->video_info->h_sync_polarity << 0);
-	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
-
-	reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE;
-	writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
-}
-
-void exynos_dp_enable_scrambling(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
-	reg &= ~SCRAMBLING_DISABLE;
-	writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
-}
-
-void exynos_dp_disable_scrambling(struct exynos_dp_device *dp)
-{
-	u32 reg;
-
-	reg = readl(dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
-	reg |= SCRAMBLING_DISABLE;
-	writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
-}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_dp_reg.h linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_dp_reg.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_dp_reg.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_dp_reg.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,366 +0,0 @@
-/*
- * Register definition file for Samsung DP driver
- *
- * Copyright (C) 2012 Samsung Electronics Co., Ltd.
- * Author: Jingoo Han <jg1.han@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef _EXYNOS_DP_REG_H
-#define _EXYNOS_DP_REG_H
-
-#define EXYNOS_DP_TX_SW_RESET			0x14
-#define EXYNOS_DP_FUNC_EN_1			0x18
-#define EXYNOS_DP_FUNC_EN_2			0x1C
-#define EXYNOS_DP_VIDEO_CTL_1			0x20
-#define EXYNOS_DP_VIDEO_CTL_2			0x24
-#define EXYNOS_DP_VIDEO_CTL_3			0x28
-
-#define EXYNOS_DP_VIDEO_CTL_8			0x3C
-#define EXYNOS_DP_VIDEO_CTL_10			0x44
-
-#define EXYNOS_DP_LANE_MAP			0x35C
-
-#define EXYNOS_DP_ANALOG_CTL_1			0x370
-#define EXYNOS_DP_ANALOG_CTL_2			0x374
-#define EXYNOS_DP_ANALOG_CTL_3			0x378
-#define EXYNOS_DP_PLL_FILTER_CTL_1		0x37C
-#define EXYNOS_DP_TX_AMP_TUNING_CTL		0x380
-
-#define EXYNOS_DP_AUX_HW_RETRY_CTL		0x390
-
-#define EXYNOS_DP_COMMON_INT_STA_1		0x3C4
-#define EXYNOS_DP_COMMON_INT_STA_2		0x3C8
-#define EXYNOS_DP_COMMON_INT_STA_3		0x3CC
-#define EXYNOS_DP_COMMON_INT_STA_4		0x3D0
-#define EXYNOS_DP_INT_STA			0x3DC
-#define EXYNOS_DP_COMMON_INT_MASK_1		0x3E0
-#define EXYNOS_DP_COMMON_INT_MASK_2		0x3E4
-#define EXYNOS_DP_COMMON_INT_MASK_3		0x3E8
-#define EXYNOS_DP_COMMON_INT_MASK_4		0x3EC
-#define EXYNOS_DP_INT_STA_MASK			0x3F8
-#define EXYNOS_DP_INT_CTL			0x3FC
-
-#define EXYNOS_DP_SYS_CTL_1			0x600
-#define EXYNOS_DP_SYS_CTL_2			0x604
-#define EXYNOS_DP_SYS_CTL_3			0x608
-#define EXYNOS_DP_SYS_CTL_4			0x60C
-
-#define EXYNOS_DP_PKT_SEND_CTL			0x640
-#define EXYNOS_DP_HDCP_CTL			0x648
-
-#define EXYNOS_DP_LINK_BW_SET			0x680
-#define EXYNOS_DP_LANE_COUNT_SET		0x684
-#define EXYNOS_DP_TRAINING_PTN_SET		0x688
-#define EXYNOS_DP_LN0_LINK_TRAINING_CTL		0x68C
-#define EXYNOS_DP_LN1_LINK_TRAINING_CTL		0x690
-#define EXYNOS_DP_LN2_LINK_TRAINING_CTL		0x694
-#define EXYNOS_DP_LN3_LINK_TRAINING_CTL		0x698
-
-#define EXYNOS_DP_DEBUG_CTL			0x6C0
-#define EXYNOS_DP_HPD_DEGLITCH_L		0x6C4
-#define EXYNOS_DP_HPD_DEGLITCH_H		0x6C8
-#define EXYNOS_DP_LINK_DEBUG_CTL		0x6E0
-
-#define EXYNOS_DP_M_VID_0			0x700
-#define EXYNOS_DP_M_VID_1			0x704
-#define EXYNOS_DP_M_VID_2			0x708
-#define EXYNOS_DP_N_VID_0			0x70C
-#define EXYNOS_DP_N_VID_1			0x710
-#define EXYNOS_DP_N_VID_2			0x714
-
-#define EXYNOS_DP_PLL_CTL			0x71C
-#define EXYNOS_DP_PHY_PD			0x720
-#define EXYNOS_DP_PHY_TEST			0x724
-
-#define EXYNOS_DP_VIDEO_FIFO_THRD		0x730
-#define EXYNOS_DP_AUDIO_MARGIN			0x73C
-
-#define EXYNOS_DP_M_VID_GEN_FILTER_TH		0x764
-#define EXYNOS_DP_M_AUD_GEN_FILTER_TH		0x778
-#define EXYNOS_DP_AUX_CH_STA			0x780
-#define EXYNOS_DP_AUX_CH_DEFER_CTL		0x788
-#define EXYNOS_DP_AUX_RX_COMM			0x78C
-#define EXYNOS_DP_BUFFER_DATA_CTL		0x790
-#define EXYNOS_DP_AUX_CH_CTL_1			0x794
-#define EXYNOS_DP_AUX_ADDR_7_0			0x798
-#define EXYNOS_DP_AUX_ADDR_15_8			0x79C
-#define EXYNOS_DP_AUX_ADDR_19_16		0x7A0
-#define EXYNOS_DP_AUX_CH_CTL_2			0x7A4
-
-#define EXYNOS_DP_BUF_DATA_0			0x7C0
-
-#define EXYNOS_DP_SOC_GENERAL_CTL		0x800
-
-/* EXYNOS_DP_TX_SW_RESET */
-#define RESET_DP_TX				(0x1 << 0)
-
-/* EXYNOS_DP_FUNC_EN_1 */
-#define MASTER_VID_FUNC_EN_N			(0x1 << 7)
-#define SLAVE_VID_FUNC_EN_N			(0x1 << 5)
-#define AUD_FIFO_FUNC_EN_N			(0x1 << 4)
-#define AUD_FUNC_EN_N				(0x1 << 3)
-#define HDCP_FUNC_EN_N				(0x1 << 2)
-#define CRC_FUNC_EN_N				(0x1 << 1)
-#define SW_FUNC_EN_N				(0x1 << 0)
-
-/* EXYNOS_DP_FUNC_EN_2 */
-#define SSC_FUNC_EN_N				(0x1 << 7)
-#define AUX_FUNC_EN_N				(0x1 << 2)
-#define SERDES_FIFO_FUNC_EN_N			(0x1 << 1)
-#define LS_CLK_DOMAIN_FUNC_EN_N			(0x1 << 0)
-
-/* EXYNOS_DP_VIDEO_CTL_1 */
-#define VIDEO_EN				(0x1 << 7)
-#define HDCP_VIDEO_MUTE				(0x1 << 6)
-
-/* EXYNOS_DP_VIDEO_CTL_1 */
-#define IN_D_RANGE_MASK				(0x1 << 7)
-#define IN_D_RANGE_SHIFT			(7)
-#define IN_D_RANGE_CEA				(0x1 << 7)
-#define IN_D_RANGE_VESA				(0x0 << 7)
-#define IN_BPC_MASK				(0x7 << 4)
-#define IN_BPC_SHIFT				(4)
-#define IN_BPC_12_BITS				(0x3 << 4)
-#define IN_BPC_10_BITS				(0x2 << 4)
-#define IN_BPC_8_BITS				(0x1 << 4)
-#define IN_BPC_6_BITS				(0x0 << 4)
-#define IN_COLOR_F_MASK				(0x3 << 0)
-#define IN_COLOR_F_SHIFT			(0)
-#define IN_COLOR_F_YCBCR444			(0x2 << 0)
-#define IN_COLOR_F_YCBCR422			(0x1 << 0)
-#define IN_COLOR_F_RGB				(0x0 << 0)
-
-/* EXYNOS_DP_VIDEO_CTL_3 */
-#define IN_YC_COEFFI_MASK			(0x1 << 7)
-#define IN_YC_COEFFI_SHIFT			(7)
-#define IN_YC_COEFFI_ITU709			(0x1 << 7)
-#define IN_YC_COEFFI_ITU601			(0x0 << 7)
-#define VID_CHK_UPDATE_TYPE_MASK		(0x1 << 4)
-#define VID_CHK_UPDATE_TYPE_SHIFT		(4)
-#define VID_CHK_UPDATE_TYPE_1			(0x1 << 4)
-#define VID_CHK_UPDATE_TYPE_0			(0x0 << 4)
-
-/* EXYNOS_DP_VIDEO_CTL_8 */
-#define VID_HRES_TH(x)				(((x) & 0xf) << 4)
-#define VID_VRES_TH(x)				(((x) & 0xf) << 0)
-
-/* EXYNOS_DP_VIDEO_CTL_10 */
-#define FORMAT_SEL				(0x1 << 4)
-#define INTERACE_SCAN_CFG			(0x1 << 2)
-#define VSYNC_POLARITY_CFG			(0x1 << 1)
-#define HSYNC_POLARITY_CFG			(0x1 << 0)
-
-/* EXYNOS_DP_LANE_MAP */
-#define LANE3_MAP_LOGIC_LANE_0			(0x0 << 6)
-#define LANE3_MAP_LOGIC_LANE_1			(0x1 << 6)
-#define LANE3_MAP_LOGIC_LANE_2			(0x2 << 6)
-#define LANE3_MAP_LOGIC_LANE_3			(0x3 << 6)
-#define LANE2_MAP_LOGIC_LANE_0			(0x0 << 4)
-#define LANE2_MAP_LOGIC_LANE_1			(0x1 << 4)
-#define LANE2_MAP_LOGIC_LANE_2			(0x2 << 4)
-#define LANE2_MAP_LOGIC_LANE_3			(0x3 << 4)
-#define LANE1_MAP_LOGIC_LANE_0			(0x0 << 2)
-#define LANE1_MAP_LOGIC_LANE_1			(0x1 << 2)
-#define LANE1_MAP_LOGIC_LANE_2			(0x2 << 2)
-#define LANE1_MAP_LOGIC_LANE_3			(0x3 << 2)
-#define LANE0_MAP_LOGIC_LANE_0			(0x0 << 0)
-#define LANE0_MAP_LOGIC_LANE_1			(0x1 << 0)
-#define LANE0_MAP_LOGIC_LANE_2			(0x2 << 0)
-#define LANE0_MAP_LOGIC_LANE_3			(0x3 << 0)
-
-/* EXYNOS_DP_ANALOG_CTL_1 */
-#define TX_TERMINAL_CTRL_50_OHM			(0x1 << 4)
-
-/* EXYNOS_DP_ANALOG_CTL_2 */
-#define SEL_24M					(0x1 << 3)
-#define TX_DVDD_BIT_1_0625V			(0x4 << 0)
-
-/* EXYNOS_DP_ANALOG_CTL_3 */
-#define DRIVE_DVDD_BIT_1_0625V			(0x4 << 5)
-#define VCO_BIT_600_MICRO			(0x5 << 0)
-
-/* EXYNOS_DP_PLL_FILTER_CTL_1 */
-#define PD_RING_OSC				(0x1 << 6)
-#define AUX_TERMINAL_CTRL_50_OHM		(0x2 << 4)
-#define TX_CUR1_2X				(0x1 << 2)
-#define TX_CUR_16_MA				(0x3 << 0)
-
-/* EXYNOS_DP_TX_AMP_TUNING_CTL */
-#define CH3_AMP_400_MV				(0x0 << 24)
-#define CH2_AMP_400_MV				(0x0 << 16)
-#define CH1_AMP_400_MV				(0x0 << 8)
-#define CH0_AMP_400_MV				(0x0 << 0)
-
-/* EXYNOS_DP_AUX_HW_RETRY_CTL */
-#define AUX_BIT_PERIOD_EXPECTED_DELAY(x)	(((x) & 0x7) << 8)
-#define AUX_HW_RETRY_INTERVAL_MASK		(0x3 << 3)
-#define AUX_HW_RETRY_INTERVAL_600_MICROSECONDS	(0x0 << 3)
-#define AUX_HW_RETRY_INTERVAL_800_MICROSECONDS	(0x1 << 3)
-#define AUX_HW_RETRY_INTERVAL_1000_MICROSECONDS	(0x2 << 3)
-#define AUX_HW_RETRY_INTERVAL_1800_MICROSECONDS	(0x3 << 3)
-#define AUX_HW_RETRY_COUNT_SEL(x)		(((x) & 0x7) << 0)
-
-/* EXYNOS_DP_COMMON_INT_STA_1 */
-#define VSYNC_DET				(0x1 << 7)
-#define PLL_LOCK_CHG				(0x1 << 6)
-#define SPDIF_ERR				(0x1 << 5)
-#define SPDIF_UNSTBL				(0x1 << 4)
-#define VID_FORMAT_CHG				(0x1 << 3)
-#define AUD_CLK_CHG				(0x1 << 2)
-#define VID_CLK_CHG				(0x1 << 1)
-#define SW_INT					(0x1 << 0)
-
-/* EXYNOS_DP_COMMON_INT_STA_2 */
-#define ENC_EN_CHG				(0x1 << 6)
-#define HW_BKSV_RDY				(0x1 << 3)
-#define HW_SHA_DONE				(0x1 << 2)
-#define HW_AUTH_STATE_CHG			(0x1 << 1)
-#define HW_AUTH_DONE				(0x1 << 0)
-
-/* EXYNOS_DP_COMMON_INT_STA_3 */
-#define AFIFO_UNDER				(0x1 << 7)
-#define AFIFO_OVER				(0x1 << 6)
-#define R0_CHK_FLAG				(0x1 << 5)
-
-/* EXYNOS_DP_COMMON_INT_STA_4 */
-#define PSR_ACTIVE				(0x1 << 7)
-#define PSR_INACTIVE				(0x1 << 6)
-#define SPDIF_BI_PHASE_ERR			(0x1 << 5)
-#define HOTPLUG_CHG				(0x1 << 2)
-#define HPD_LOST				(0x1 << 1)
-#define PLUG					(0x1 << 0)
-
-/* EXYNOS_DP_INT_STA */
-#define INT_HPD					(0x1 << 6)
-#define HW_TRAINING_FINISH			(0x1 << 5)
-#define RPLY_RECEIV				(0x1 << 1)
-#define AUX_ERR					(0x1 << 0)
-
-/* EXYNOS_DP_INT_CTL */
-#define SOFT_INT_CTRL				(0x1 << 2)
-#define INT_POL1				(0x1 << 1)
-#define INT_POL0				(0x1 << 0)
-
-/* EXYNOS_DP_SYS_CTL_1 */
-#define DET_STA					(0x1 << 2)
-#define FORCE_DET				(0x1 << 1)
-#define DET_CTRL				(0x1 << 0)
-
-/* EXYNOS_DP_SYS_CTL_2 */
-#define CHA_CRI(x)				(((x) & 0xf) << 4)
-#define CHA_STA					(0x1 << 2)
-#define FORCE_CHA				(0x1 << 1)
-#define CHA_CTRL				(0x1 << 0)
-
-/* EXYNOS_DP_SYS_CTL_3 */
-#define HPD_STATUS				(0x1 << 6)
-#define F_HPD					(0x1 << 5)
-#define HPD_CTRL				(0x1 << 4)
-#define HDCP_RDY				(0x1 << 3)
-#define STRM_VALID				(0x1 << 2)
-#define F_VALID					(0x1 << 1)
-#define VALID_CTRL				(0x1 << 0)
-
-/* EXYNOS_DP_SYS_CTL_4 */
-#define FIX_M_AUD				(0x1 << 4)
-#define ENHANCED				(0x1 << 3)
-#define FIX_M_VID				(0x1 << 2)
-#define M_VID_UPDATE_CTRL			(0x3 << 0)
-
-/* EXYNOS_DP_TRAINING_PTN_SET */
-#define SCRAMBLER_TYPE				(0x1 << 9)
-#define HW_LINK_TRAINING_PATTERN		(0x1 << 8)
-#define SCRAMBLING_DISABLE			(0x1 << 5)
-#define SCRAMBLING_ENABLE			(0x0 << 5)
-#define LINK_QUAL_PATTERN_SET_MASK		(0x3 << 2)
-#define LINK_QUAL_PATTERN_SET_PRBS7		(0x3 << 2)
-#define LINK_QUAL_PATTERN_SET_D10_2		(0x1 << 2)
-#define LINK_QUAL_PATTERN_SET_DISABLE		(0x0 << 2)
-#define SW_TRAINING_PATTERN_SET_MASK		(0x3 << 0)
-#define SW_TRAINING_PATTERN_SET_PTN2		(0x2 << 0)
-#define SW_TRAINING_PATTERN_SET_PTN1		(0x1 << 0)
-#define SW_TRAINING_PATTERN_SET_NORMAL		(0x0 << 0)
-
-/* EXYNOS_DP_LN0_LINK_TRAINING_CTL */
-#define PRE_EMPHASIS_SET_MASK			(0x3 << 3)
-#define PRE_EMPHASIS_SET_SHIFT			(3)
-
-/* EXYNOS_DP_DEBUG_CTL */
-#define PLL_LOCK				(0x1 << 4)
-#define F_PLL_LOCK				(0x1 << 3)
-#define PLL_LOCK_CTRL				(0x1 << 2)
-#define PN_INV					(0x1 << 0)
-
-/* EXYNOS_DP_PLL_CTL */
-#define DP_PLL_PD				(0x1 << 7)
-#define DP_PLL_RESET				(0x1 << 6)
-#define DP_PLL_LOOP_BIT_DEFAULT			(0x1 << 4)
-#define DP_PLL_REF_BIT_1_1250V			(0x5 << 0)
-#define DP_PLL_REF_BIT_1_2500V			(0x7 << 0)
-
-/* EXYNOS_DP_PHY_PD */
-#define DP_PHY_PD				(0x1 << 5)
-#define AUX_PD					(0x1 << 4)
-#define CH3_PD					(0x1 << 3)
-#define CH2_PD					(0x1 << 2)
-#define CH1_PD					(0x1 << 1)
-#define CH0_PD					(0x1 << 0)
-
-/* EXYNOS_DP_PHY_TEST */
-#define MACRO_RST				(0x1 << 5)
-#define CH1_TEST				(0x1 << 1)
-#define CH0_TEST				(0x1 << 0)
-
-/* EXYNOS_DP_AUX_CH_STA */
-#define AUX_BUSY				(0x1 << 4)
-#define AUX_STATUS_MASK				(0xf << 0)
-
-/* EXYNOS_DP_AUX_CH_DEFER_CTL */
-#define DEFER_CTRL_EN				(0x1 << 7)
-#define DEFER_COUNT(x)				(((x) & 0x7f) << 0)
-
-/* EXYNOS_DP_AUX_RX_COMM */
-#define AUX_RX_COMM_I2C_DEFER			(0x2 << 2)
-#define AUX_RX_COMM_AUX_DEFER			(0x2 << 0)
-
-/* EXYNOS_DP_BUFFER_DATA_CTL */
-#define BUF_CLR					(0x1 << 7)
-#define BUF_DATA_COUNT(x)			(((x) & 0x1f) << 0)
-
-/* EXYNOS_DP_AUX_CH_CTL_1 */
-#define AUX_LENGTH(x)				(((x - 1) & 0xf) << 4)
-#define AUX_TX_COMM_MASK			(0xf << 0)
-#define AUX_TX_COMM_DP_TRANSACTION		(0x1 << 3)
-#define AUX_TX_COMM_I2C_TRANSACTION		(0x0 << 3)
-#define AUX_TX_COMM_MOT				(0x1 << 2)
-#define AUX_TX_COMM_WRITE			(0x0 << 0)
-#define AUX_TX_COMM_READ			(0x1 << 0)
-
-/* EXYNOS_DP_AUX_ADDR_7_0 */
-#define AUX_ADDR_7_0(x)				(((x) >> 0) & 0xff)
-
-/* EXYNOS_DP_AUX_ADDR_15_8 */
-#define AUX_ADDR_15_8(x)			(((x) >> 8) & 0xff)
-
-/* EXYNOS_DP_AUX_ADDR_19_16 */
-#define AUX_ADDR_19_16(x)			(((x) >> 16) & 0x0f)
-
-/* EXYNOS_DP_AUX_CH_CTL_2 */
-#define ADDR_ONLY				(0x1 << 1)
-#define AUX_EN					(0x1 << 0)
-
-/* EXYNOS_DP_SOC_GENERAL_CTL */
-#define AUDIO_MODE_SPDIF_MODE			(0x1 << 8)
-#define AUDIO_MODE_MASTER_MODE			(0x0 << 8)
-#define MASTER_VIDEO_INTERLACE_EN		(0x1 << 4)
-#define VIDEO_MASTER_CLK_SEL			(0x1 << 2)
-#define VIDEO_MASTER_MODE_EN			(0x1 << 1)
-#define VIDEO_MODE_MASK				(0x1 << 0)
-#define VIDEO_MODE_SLAVE_MODE			(0x1 << 0)
-#define VIDEO_MODE_MASTER_MODE			(0x0 << 0)
-
-#endif /* _EXYNOS_DP_REG_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_drm_core.c linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_drm_core.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_drm_core.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_drm_core.c	2016-07-24 15:23:50.000000000 -0400
@@ -15,7 +15,6 @@
 #include <drm/drmP.h>
 #include "exynos_drm_drv.h"
 #include "exynos_drm_crtc.h"
-#include "exynos_drm_fbdev.h"
 
 static LIST_HEAD(exynos_drm_subdrv_list);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_drm_crtc.c linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_drm_crtc.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_drm_crtc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_drm_crtc.c	2016-07-24 15:23:50.000000000 -0400
@@ -157,9 +157,8 @@ err_crtc:
 
 int exynos_drm_crtc_enable_vblank(struct drm_device *dev, unsigned int pipe)
 {
-	struct exynos_drm_private *private = dev->dev_private;
-	struct exynos_drm_crtc *exynos_crtc =
-		to_exynos_crtc(private->crtc[pipe]);
+	struct exynos_drm_crtc *exynos_crtc = exynos_drm_crtc_from_pipe(dev,
+									pipe);
 
 	if (exynos_crtc->ops->enable_vblank)
 		return exynos_crtc->ops->enable_vblank(exynos_crtc);
@@ -169,9 +168,8 @@ int exynos_drm_crtc_enable_vblank(struct
 
 void exynos_drm_crtc_disable_vblank(struct drm_device *dev, unsigned int pipe)
 {
-	struct exynos_drm_private *private = dev->dev_private;
-	struct exynos_drm_crtc *exynos_crtc =
-		to_exynos_crtc(private->crtc[pipe]);
+	struct exynos_drm_crtc *exynos_crtc = exynos_drm_crtc_from_pipe(dev,
+									pipe);
 
 	if (exynos_crtc->ops->disable_vblank)
 		exynos_crtc->ops->disable_vblank(exynos_crtc);
@@ -235,20 +233,15 @@ void exynos_drm_crtc_cancel_page_flip(st
 	unsigned long flags;
 
 	spin_lock_irqsave(&crtc->dev->event_lock, flags);
+
 	e = exynos_crtc->event;
 	if (e && e->base.file_priv == file) {
 		exynos_crtc->event = NULL;
-		/*
-		 * event will be destroyed by core part
-		 * so below line should be removed later with core changes
-		 */
-		e->base.destroy(&e->base);
-		/*
-		 * event_space will be increased by core part
-		 * so below line should be removed later with core changes.
-		 */
-		file->event_space += sizeof(e->event);
 		atomic_dec(&exynos_crtc->pending_update);
 	}
+
 	spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+
+	if (e && e->base.file_priv == file)
+		drm_event_cancel_free(crtc->dev, &e->base);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_drm_dpi.c linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_drm_dpi.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_drm_dpi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_drm_dpi.c	2016-07-24 15:23:50.000000000 -0400
@@ -15,6 +15,7 @@
 #include <drm/drm_panel.h>
 #include <drm/drm_atomic_helper.h>
 
+#include <linux/of_graph.h>
 #include <linux/regulator/consumer.h>
 
 #include <video/of_videomode.h>
@@ -164,67 +165,6 @@ static const struct drm_encoder_funcs ex
 	.destroy = drm_encoder_cleanup,
 };
 
-/* of_* functions will be removed after merge of of_graph patches */
-static struct device_node *
-of_get_child_by_name_reg(struct device_node *parent, const char *name, u32 reg)
-{
-	struct device_node *np;
-
-	for_each_child_of_node(parent, np) {
-		u32 r;
-
-		if (!np->name || of_node_cmp(np->name, name))
-			continue;
-
-		if (of_property_read_u32(np, "reg", &r) < 0)
-			r = 0;
-
-		if (reg == r)
-			break;
-	}
-
-	return np;
-}
-
-static struct device_node *of_graph_get_port_by_reg(struct device_node *parent,
-						    u32 reg)
-{
-	struct device_node *ports, *port;
-
-	ports = of_get_child_by_name(parent, "ports");
-	if (ports)
-		parent = ports;
-
-	port = of_get_child_by_name_reg(parent, "port", reg);
-
-	of_node_put(ports);
-
-	return port;
-}
-
-static struct device_node *
-of_graph_get_endpoint_by_reg(struct device_node *port, u32 reg)
-{
-	return of_get_child_by_name_reg(port, "endpoint", reg);
-}
-
-static struct device_node *
-of_graph_get_remote_port_parent(const struct device_node *node)
-{
-	struct device_node *np;
-	unsigned int depth;
-
-	np = of_parse_phandle(node, "remote-endpoint", 0);
-
-	/* Walk 3 levels up only if there is 'ports' node. */
-	for (depth = 3; depth && np; depth--) {
-		np = of_get_next_parent(np);
-		if (depth == 2 && of_node_cmp(np->name, "ports"))
-			break;
-	}
-	return np;
-}
-
 enum {
 	FIMD_PORT_IN0,
 	FIMD_PORT_IN1,
@@ -237,12 +177,7 @@ static struct device_node *exynos_dpi_of
 {
 	struct device_node *np, *ep;
 
-	np = of_graph_get_port_by_reg(dev->of_node, FIMD_PORT_RGB);
-	if (!np)
-		return NULL;
-
-	ep = of_graph_get_endpoint_by_reg(np, 0);
-	of_node_put(np);
+	ep = of_graph_get_endpoint_by_regs(dev->of_node, FIMD_PORT_RGB, 0);
 	if (!ep)
 		return NULL;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_drm_drv.c linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_drm_drv.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_drm_drv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_drm_drv.c	2016-07-24 15:23:50.000000000 -0400
@@ -212,13 +212,6 @@ static int exynos_drm_load(struct drm_de
 	 */
 	dev->irq_enabled = true;
 
-	/*
-	 * with vblank_disable_allowed = true, vblank interrupt will be disabled
-	 * by drm timer once a current process gives up ownership of
-	 * vblank event.(after drm_vblank_put function is called)
-	 */
-	dev->vblank_disable_allowed = true;
-
 	/* init kms poll for handling hpd */
 	drm_kms_helper_poll_init(dev);
 
@@ -270,7 +263,7 @@ static int commit_is_pending(struct exyn
 }
 
 int exynos_atomic_commit(struct drm_device *dev, struct drm_atomic_state *state,
-			 bool async)
+			 bool nonblock)
 {
 	struct exynos_drm_private *priv = dev->dev_private;
 	struct exynos_atomic_commit *commit;
@@ -308,7 +301,7 @@ int exynos_atomic_commit(struct drm_devi
 
 	drm_atomic_helper_swap_state(dev, state);
 
-	if (async)
+	if (nonblock)
 		schedule_work(&commit->work);
 	else
 		exynos_atomic_commit_complete(commit);
@@ -418,7 +411,7 @@ static struct drm_driver exynos_drm_driv
 	.get_vblank_counter	= drm_vblank_no_hw_counter,
 	.enable_vblank		= exynos_drm_crtc_enable_vblank,
 	.disable_vblank		= exynos_drm_crtc_disable_vblank,
-	.gem_free_object	= exynos_drm_gem_free_object,
+	.gem_free_object_unlocked = exynos_drm_gem_free_object,
 	.gem_vm_ops		= &exynos_drm_gem_vm_ops,
 	.dumb_create		= exynos_drm_gem_dumb_create,
 	.dumb_map_offset	= exynos_drm_gem_dumb_map_offset,
@@ -431,6 +424,7 @@ static struct drm_driver exynos_drm_driv
 	.gem_prime_import_sg_table	= exynos_drm_gem_prime_import_sg_table,
 	.gem_prime_vmap		= exynos_drm_gem_prime_vmap,
 	.gem_prime_vunmap	= exynos_drm_gem_prime_vunmap,
+	.gem_prime_mmap		= exynos_drm_gem_prime_mmap,
 	.ioctls			= exynos_ioctls,
 	.num_ioctls		= ARRAY_SIZE(exynos_ioctls),
 	.fops			= &exynos_drm_driver_fops,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_drm_drv.h linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_drm_drv.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_drm_drv.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_drm_drv.h	2016-07-24 15:23:50.000000000 -0400
@@ -120,8 +120,6 @@ struct exynos_drm_plane_config {
  * @commit: set current hw specific display mode to hw.
  * @enable_vblank: specific driver callback for enabling vblank interrupt.
  * @disable_vblank: specific driver callback for disabling vblank interrupt.
- * @wait_for_vblank: wait for vblank interrupt to make sure that
- *	hardware overlay is updated.
  * @atomic_check: validate state
  * @atomic_begin: prepare device to receive an update
  * @atomic_flush: mark the end of device update
@@ -129,10 +127,6 @@ struct exynos_drm_plane_config {
  * @disable_plane: disable hardware specific overlay.
  * @te_handler: trigger to transfer video image at the tearing effect
  *	synchronization signal if there is a page flip request.
- * @clock_enable: optional function enabling/disabling display domain clock,
- *	called from exynos-dp driver before powering up (with
- *	'enable' argument as true) and after powering down (with
- *	'enable' as false).
  */
 struct exynos_drm_crtc;
 struct exynos_drm_crtc_ops {
@@ -141,7 +135,6 @@ struct exynos_drm_crtc_ops {
 	void (*commit)(struct exynos_drm_crtc *crtc);
 	int (*enable_vblank)(struct exynos_drm_crtc *crtc);
 	void (*disable_vblank)(struct exynos_drm_crtc *crtc);
-	void (*wait_for_vblank)(struct exynos_drm_crtc *crtc);
 	int (*atomic_check)(struct exynos_drm_crtc *crtc,
 			    struct drm_crtc_state *state);
 	void (*atomic_begin)(struct exynos_drm_crtc *crtc);
@@ -151,7 +144,10 @@ struct exynos_drm_crtc_ops {
 			      struct exynos_drm_plane *plane);
 	void (*atomic_flush)(struct exynos_drm_crtc *crtc);
 	void (*te_handler)(struct exynos_drm_crtc *crtc);
-	void (*clock_enable)(struct exynos_drm_crtc *crtc, bool enable);
+};
+
+struct exynos_drm_clk {
+	void (*enable)(struct exynos_drm_clk *clk, bool enable);
 };
 
 /*
@@ -182,8 +178,16 @@ struct exynos_drm_crtc {
 	atomic_t			pending_update;
 	const struct exynos_drm_crtc_ops	*ops;
 	void				*ctx;
+	struct exynos_drm_clk		*pipe_clk;
 };
 
+static inline void exynos_drm_pipe_clk_enable(struct exynos_drm_crtc *crtc,
+					      bool enable)
+{
+	if (crtc->pipe_clk)
+		crtc->pipe_clk->enable(crtc->pipe_clk, enable);
+}
+
 struct exynos_drm_g2d_private {
 	struct device		*dev;
 	struct list_head	inuse_cmdlist;
@@ -232,6 +236,14 @@ struct exynos_drm_private {
 	wait_queue_head_t	wait;
 };
 
+static inline struct exynos_drm_crtc *
+exynos_drm_crtc_from_pipe(struct drm_device *dev, int pipe)
+{
+	struct exynos_drm_private *private = dev->dev_private;
+
+	return to_exynos_crtc(private->crtc[pipe]);
+}
+
 static inline struct device *to_dma_dev(struct drm_device *dev)
 {
 	struct exynos_drm_private *priv = dev->dev_private;
@@ -296,7 +308,7 @@ static inline int exynos_dpi_bind(struct
 #endif
 
 int exynos_atomic_commit(struct drm_device *dev, struct drm_atomic_state *state,
-			 bool async);
+			 bool nonblock);
 
 
 extern struct platform_driver fimd_driver;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_drm_dsi.c linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_drm_dsi.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_drm_dsi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_drm_dsi.c	2016-07-24 15:23:50.000000000 -0400
@@ -280,7 +280,7 @@ struct exynos_dsi {
 	spinlock_t transfer_lock; /* protects transfer_list */
 	struct list_head transfer_list;
 
-	struct exynos_dsi_driver_data *driver_data;
+	const struct exynos_dsi_driver_data *driver_data;
 	struct device_node *bridge_node;
 };
 
@@ -532,15 +532,6 @@ static const struct of_device_id exynos_
 	{ }
 };
 
-static inline struct exynos_dsi_driver_data *exynos_dsi_get_driver_data(
-						struct platform_device *pdev)
-{
-	const struct of_device_id *of_id =
-			of_match_device(exynos_dsi_of_match, &pdev->dev);
-
-	return (struct exynos_dsi_driver_data *)of_id->data;
-}
-
 static void exynos_dsi_wait_for_reset(struct exynos_dsi *dsi)
 {
 	if (wait_for_completion_timeout(&dsi->completed, msecs_to_jiffies(300)))
@@ -564,7 +555,7 @@ static void exynos_dsi_reset(struct exyn
 static unsigned long exynos_dsi_pll_find_pms(struct exynos_dsi *dsi,
 		unsigned long fin, unsigned long fout, u8 *p, u16 *m, u8 *s)
 {
-	struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
+	const struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
 	unsigned long best_freq = 0;
 	u32 min_delta = 0xffffffff;
 	u8 p_min, p_max;
@@ -618,7 +609,7 @@ static unsigned long exynos_dsi_pll_find
 static unsigned long exynos_dsi_set_pll(struct exynos_dsi *dsi,
 					unsigned long freq)
 {
-	struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
+	const struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
 	unsigned long fin, fout;
 	int timeout;
 	u8 p, s;
@@ -712,7 +703,7 @@ static int exynos_dsi_enable_clock(struc
 
 static void exynos_dsi_set_phy_ctrl(struct exynos_dsi *dsi)
 {
-	struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
+	const struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
 	const unsigned int *reg_values = driver_data->reg_values;
 	u32 reg;
 
@@ -790,7 +781,7 @@ static void exynos_dsi_enable_lane(struc
 
 static int exynos_dsi_init_link(struct exynos_dsi *dsi)
 {
-	struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
+	const struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
 	int timeout;
 	u32 reg;
 	u32 lanes_mask;
@@ -1334,7 +1325,7 @@ static void exynos_dsi_disable_irq(struc
 
 static int exynos_dsi_init(struct exynos_dsi *dsi)
 {
-	struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
+	const struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
 
 	exynos_dsi_reset(dsi);
 	exynos_dsi_enable_irq(dsi);
@@ -1641,50 +1632,6 @@ static const struct drm_encoder_funcs ex
 
 MODULE_DEVICE_TABLE(of, exynos_dsi_of_match);
 
-/* of_* functions will be removed after merge of of_graph patches */
-static struct device_node *
-of_get_child_by_name_reg(struct device_node *parent, const char *name, u32 reg)
-{
-	struct device_node *np;
-
-	for_each_child_of_node(parent, np) {
-		u32 r;
-
-		if (!np->name || of_node_cmp(np->name, name))
-			continue;
-
-		if (of_property_read_u32(np, "reg", &r) < 0)
-			r = 0;
-
-		if (reg == r)
-			break;
-	}
-
-	return np;
-}
-
-static struct device_node *of_graph_get_port_by_reg(struct device_node *parent,
-						    u32 reg)
-{
-	struct device_node *ports, *port;
-
-	ports = of_get_child_by_name(parent, "ports");
-	if (ports)
-		parent = ports;
-
-	port = of_get_child_by_name_reg(parent, "port", reg);
-
-	of_node_put(ports);
-
-	return port;
-}
-
-static struct device_node *
-of_graph_get_endpoint_by_reg(struct device_node *port, u32 reg)
-{
-	return of_get_child_by_name_reg(port, "endpoint", reg);
-}
-
 static int exynos_dsi_of_read_u32(const struct device_node *np,
 				  const char *propname, u32 *out_value)
 {
@@ -1706,7 +1653,7 @@ static int exynos_dsi_parse_dt(struct ex
 {
 	struct device *dev = dsi->dev;
 	struct device_node *node = dev->of_node;
-	struct device_node *port, *ep;
+	struct device_node *ep;
 	int ret;
 
 	ret = exynos_dsi_of_read_u32(node, "samsung,pll-clock-frequency",
@@ -1714,16 +1661,9 @@ static int exynos_dsi_parse_dt(struct ex
 	if (ret < 0)
 		return ret;
 
-	port = of_graph_get_port_by_reg(node, DSI_PORT_OUT);
-	if (!port) {
-		dev_err(dev, "no output port specified\n");
-		return -EINVAL;
-	}
-
-	ep = of_graph_get_endpoint_by_reg(port, 0);
-	of_node_put(port);
+	ep = of_graph_get_endpoint_by_regs(node, DSI_PORT_OUT, 0);
 	if (!ep) {
-		dev_err(dev, "no endpoint specified in output port\n");
+		dev_err(dev, "no output port with endpoint specified\n");
 		return -EINVAL;
 	}
 
@@ -1833,7 +1773,7 @@ static int exynos_dsi_probe(struct platf
 	dsi->dsi_host.dev = dev;
 
 	dsi->dev = dev;
-	dsi->driver_data = exynos_dsi_get_driver_data(pdev);
+	dsi->driver_data = of_device_get_match_data(dev);
 
 	ret = exynos_dsi_parse_dt(dsi);
 	if (ret)
@@ -1917,7 +1857,7 @@ static int __maybe_unused exynos_dsi_sus
 {
 	struct drm_encoder *encoder = dev_get_drvdata(dev);
 	struct exynos_dsi *dsi = encoder_to_dsi(encoder);
-	struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
+	const struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
 	int ret, i;
 
 	usleep_range(10000, 20000);
@@ -1948,7 +1888,7 @@ static int __maybe_unused exynos_dsi_res
 {
 	struct drm_encoder *encoder = dev_get_drvdata(dev);
 	struct exynos_dsi *dsi = encoder_to_dsi(encoder);
-	struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
+	const struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
 	int ret, i;
 
 	ret = regulator_bulk_enable(ARRAY_SIZE(dsi->supplies), dsi->supplies);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_drm_fb.c linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_drm_fb.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_drm_fb.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_drm_fb.c	2016-07-24 15:23:50.000000000 -0400
@@ -97,20 +97,9 @@ static int exynos_drm_fb_create_handle(s
 				     &exynos_fb->exynos_gem[0]->base, handle);
 }
 
-static int exynos_drm_fb_dirty(struct drm_framebuffer *fb,
-				struct drm_file *file_priv, unsigned flags,
-				unsigned color, struct drm_clip_rect *clips,
-				unsigned num_clips)
-{
-	/* TODO */
-
-	return 0;
-}
-
 static const struct drm_framebuffer_funcs exynos_drm_fb_funcs = {
 	.destroy	= exynos_drm_fb_destroy,
 	.create_handle	= exynos_drm_fb_create_handle,
-	.dirty		= exynos_drm_fb_dirty,
 };
 
 struct drm_framebuffer *
@@ -163,8 +152,7 @@ exynos_user_fb_create(struct drm_device
 	int ret;
 
 	for (i = 0; i < drm_format_num_planes(mode_cmd->pixel_format); i++) {
-		obj = drm_gem_object_lookup(dev, file_priv,
-					    mode_cmd->handles[i]);
+		obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[i]);
 		if (!obj) {
 			DRM_ERROR("failed to lookup gem object\n");
 			ret = -ENOENT;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_drm_fbdev.c linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_drm_fbdev.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_drm_fbdev.c	2016-07-24 15:23:50.000000000 -0400
@@ -138,8 +138,6 @@ static int exynos_drm_fbdev_create(struc
 	mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
 							  sizes->surface_depth);
 
-	mutex_lock(&dev->struct_mutex);
-
 	size = mode_cmd.pitches[0] * mode_cmd.height;
 
 	exynos_gem = exynos_drm_gem_create(dev, EXYNOS_BO_CONTIG, size);
@@ -154,10 +152,8 @@ static int exynos_drm_fbdev_create(struc
 						   size);
 	}
 
-	if (IS_ERR(exynos_gem)) {
-		ret = PTR_ERR(exynos_gem);
-		goto out;
-	}
+	if (IS_ERR(exynos_gem))
+		return PTR_ERR(exynos_gem);
 
 	exynos_fbdev->exynos_gem = exynos_gem;
 
@@ -173,7 +169,6 @@ static int exynos_drm_fbdev_create(struc
 	if (ret < 0)
 		goto err_destroy_framebuffer;
 
-	mutex_unlock(&dev->struct_mutex);
 	return ret;
 
 err_destroy_framebuffer:
@@ -181,13 +176,12 @@ err_destroy_framebuffer:
 err_destroy_gem:
 	exynos_drm_gem_destroy(exynos_gem);
 
-/*
- * if failed, all resources allocated above would be released by
- * drm_mode_config_cleanup() when drm_load() had been called prior
- * to any specific driver such as fimd or hdmi driver.
- */
-out:
-	mutex_unlock(&dev->struct_mutex);
+	/*
+	 * if failed, all resources allocated above would be released by
+	 * drm_mode_config_cleanup() when drm_load() had been called prior
+	 * to any specific driver such as fimd or hdmi driver.
+	 */
+
 	return ret;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_drm_fimd.c linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_drm_fimd.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_drm_fimd.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_drm_fimd.c	2016-07-24 15:23:50.000000000 -0400
@@ -30,7 +30,6 @@
 
 #include "exynos_drm_drv.h"
 #include "exynos_drm_fb.h"
-#include "exynos_drm_fbdev.h"
 #include "exynos_drm_crtc.h"
 #include "exynos_drm_plane.h"
 #include "exynos_drm_iommu.h"
@@ -68,10 +67,15 @@
 /* color key value register for hardware window 1 ~ 4. */
 #define WKEYCON1_BASE(x)		((WKEYCON1 + 0x140) + ((x - 1) * 8))
 
-/* I80 / RGB trigger control register */
+/* I80 trigger control register */
 #define TRIGCON				0x1A4
-#define TRGMODE_I80_RGB_ENABLE_I80	(1 << 0)
-#define SWTRGCMD_I80_RGB_ENABLE		(1 << 1)
+#define TRGMODE_ENABLE			(1 << 0)
+#define SWTRGCMD_ENABLE			(1 << 1)
+/* Exynos3250, 3472, 4415, 5260 5410, 5420 and 5422 only supported. */
+#define HWTRGEN_ENABLE			(1 << 3)
+#define HWTRGMASK_ENABLE		(1 << 4)
+/* Exynos3250, 3472, 4415, 5260, 5420 and 5422 only supported. */
+#define HWTRIGEN_PER_ENABLE		(1 << 31)
 
 /* display mode change control register except exynos4 */
 #define VIDOUT_CON			0x000
@@ -89,12 +93,16 @@
 /* FIMD has totally five hardware windows. */
 #define WINDOWS_NR	5
 
+/* HW trigger flag on i80 panel. */
+#define I80_HW_TRG     (1 << 1)
+
 struct fimd_driver_data {
 	unsigned int timing_base;
 	unsigned int lcdblk_offset;
 	unsigned int lcdblk_vt_shift;
 	unsigned int lcdblk_bypass_shift;
 	unsigned int lcdblk_mic_bypass_shift;
+	unsigned int trg_type;
 
 	unsigned int has_shadowcon:1;
 	unsigned int has_clksel:1;
@@ -102,6 +110,9 @@ struct fimd_driver_data {
 	unsigned int has_vidoutcon:1;
 	unsigned int has_vtsel:1;
 	unsigned int has_mic_bypass:1;
+	unsigned int has_dp_clk:1;
+	unsigned int has_hw_trigger:1;
+	unsigned int has_trigger_per_te:1;
 };
 
 static struct fimd_driver_data s3c64xx_fimd_driver_data = {
@@ -114,8 +125,10 @@ static struct fimd_driver_data exynos3_f
 	.timing_base = 0x20000,
 	.lcdblk_offset = 0x210,
 	.lcdblk_bypass_shift = 1,
+	.trg_type = I80_HW_TRG,
 	.has_shadowcon = 1,
 	.has_vidoutcon = 1,
+	.has_trigger_per_te = 1,
 };
 
 static struct fimd_driver_data exynos4_fimd_driver_data = {
@@ -132,9 +145,11 @@ static struct fimd_driver_data exynos441
 	.lcdblk_offset = 0x210,
 	.lcdblk_vt_shift = 10,
 	.lcdblk_bypass_shift = 1,
+	.trg_type = I80_HW_TRG,
 	.has_shadowcon = 1,
 	.has_vidoutcon = 1,
 	.has_vtsel = 1,
+	.has_trigger_per_te = 1,
 };
 
 static struct fimd_driver_data exynos5_fimd_driver_data = {
@@ -145,6 +160,7 @@ static struct fimd_driver_data exynos5_f
 	.has_shadowcon = 1,
 	.has_vidoutcon = 1,
 	.has_vtsel = 1,
+	.has_dp_clk = 1,
 };
 
 static struct fimd_driver_data exynos5420_fimd_driver_data = {
@@ -157,6 +173,7 @@ static struct fimd_driver_data exynos542
 	.has_vidoutcon = 1,
 	.has_vtsel = 1,
 	.has_mic_bypass = 1,
+	.has_dp_clk = 1,
 };
 
 struct fimd_context {
@@ -182,8 +199,9 @@ struct fimd_context {
 	atomic_t			win_updated;
 	atomic_t			triggering;
 
-	struct fimd_driver_data *driver_data;
+	const struct fimd_driver_data *driver_data;
 	struct drm_encoder *encoder;
+	struct exynos_drm_clk		dp_clk;
 };
 
 static const struct of_device_id fimd_driver_dt_match[] = {
@@ -219,15 +237,6 @@ static const uint32_t fimd_formats[] = {
 	DRM_FORMAT_ARGB8888,
 };
 
-static inline struct fimd_driver_data *drm_fimd_get_driver_data(
-	struct platform_device *pdev)
-{
-	const struct of_device_id *of_id =
-			of_match_device(fimd_driver_dt_match, &pdev->dev);
-
-	return (struct fimd_driver_data *)of_id->data;
-}
-
 static int fimd_enable_vblank(struct exynos_drm_crtc *crtc)
 {
 	struct fimd_context *ctx = crtc->ctx;
@@ -383,9 +392,16 @@ static void fimd_clear_channels(struct e
 static u32 fimd_calc_clkdiv(struct fimd_context *ctx,
 		const struct drm_display_mode *mode)
 {
-	unsigned long ideal_clk = mode->htotal * mode->vtotal * mode->vrefresh;
+	unsigned long ideal_clk;
 	u32 clkdiv;
 
+	if (mode->clock == 0) {
+		DRM_ERROR("Mode has zero clock value.\n");
+		return 0xff;
+	}
+
+	ideal_clk = mode->clock * 1000;
+
 	if (ctx->i80_if) {
 		/*
 		 * The frame done interrupt should be occurred prior to the
@@ -400,11 +416,31 @@ static u32 fimd_calc_clkdiv(struct fimd_
 	return (clkdiv < 0x100) ? clkdiv : 0xff;
 }
 
+static void fimd_setup_trigger(struct fimd_context *ctx)
+{
+	void __iomem *timing_base = ctx->regs + ctx->driver_data->timing_base;
+	u32 trg_type = ctx->driver_data->trg_type;
+	u32 val = readl(timing_base + TRIGCON);
+
+	val &= ~(TRGMODE_ENABLE);
+
+	if (trg_type == I80_HW_TRG) {
+		if (ctx->driver_data->has_hw_trigger)
+			val |= HWTRGEN_ENABLE | HWTRGMASK_ENABLE;
+		if (ctx->driver_data->has_trigger_per_te)
+			val |= HWTRIGEN_PER_ENABLE;
+	} else {
+		val |= TRGMODE_ENABLE;
+	}
+
+	writel(val, timing_base + TRIGCON);
+}
+
 static void fimd_commit(struct exynos_drm_crtc *crtc)
 {
 	struct fimd_context *ctx = crtc->ctx;
 	struct drm_display_mode *mode = &crtc->base.state->adjusted_mode;
-	struct fimd_driver_data *driver_data = ctx->driver_data;
+	const struct fimd_driver_data *driver_data = ctx->driver_data;
 	void *timing_base = ctx->regs + driver_data->timing_base;
 	u32 val, clkdiv;
 
@@ -495,6 +531,8 @@ static void fimd_commit(struct exynos_dr
 	       VIDTCON2_HOZVAL_E(mode->hdisplay - 1);
 	writel(val, ctx->regs + driver_data->timing_base + VIDTCON2);
 
+	fimd_setup_trigger(ctx);
+
 	/*
 	 * fields of register with prefix '_F' would be updated
 	 * at vsync(same as dma start)
@@ -827,7 +865,7 @@ static void fimd_disable(struct exynos_d
 static void fimd_trigger(struct device *dev)
 {
 	struct fimd_context *ctx = dev_get_drvdata(dev);
-	struct fimd_driver_data *driver_data = ctx->driver_data;
+	const struct fimd_driver_data *driver_data = ctx->driver_data;
 	void *timing_base = ctx->regs + driver_data->timing_base;
 	u32 reg;
 
@@ -842,7 +880,7 @@ static void fimd_trigger(struct device *
 	atomic_set(&ctx->triggering, 1);
 
 	reg = readl(timing_base + TRIGCON);
-	reg |= (TRGMODE_I80_RGB_ENABLE_I80 | SWTRGCMD_I80_RGB_ENABLE);
+	reg |= (TRGMODE_ENABLE | SWTRGCMD_ENABLE);
 	writel(reg, timing_base + TRIGCON);
 
 	/*
@@ -856,11 +894,15 @@ static void fimd_trigger(struct device *
 static void fimd_te_handler(struct exynos_drm_crtc *crtc)
 {
 	struct fimd_context *ctx = crtc->ctx;
+	u32 trg_type = ctx->driver_data->trg_type;
 
 	/* Checks the crtc is detached already from encoder */
 	if (ctx->pipe < 0 || !ctx->drm_dev)
 		return;
 
+	if (trg_type == I80_HW_TRG)
+		goto out;
+
 	/*
 	 * If there is a page flip request, triggers and handles the page flip
 	 * event so that current fb can be updated into panel GRAM.
@@ -868,6 +910,7 @@ static void fimd_te_handler(struct exyno
 	if (atomic_add_unless(&ctx->win_updated, -1, 0))
 		fimd_trigger(ctx->dev);
 
+out:
 	/* Wakes up vsync event queue */
 	if (atomic_read(&ctx->wait_vsync_event)) {
 		atomic_set(&ctx->wait_vsync_event, 0);
@@ -878,21 +921,11 @@ static void fimd_te_handler(struct exyno
 		drm_crtc_handle_vblank(&ctx->crtc->base);
 }
 
-static void fimd_dp_clock_enable(struct exynos_drm_crtc *crtc, bool enable)
+static void fimd_dp_clock_enable(struct exynos_drm_clk *clk, bool enable)
 {
-	struct fimd_context *ctx = crtc->ctx;
-	u32 val;
-
-	/*
-	 * Only Exynos 5250, 5260, 5410 and 542x requires enabling DP/MIE
-	 * clock. On these SoCs the bootloader may enable it but any
-	 * power domain off/on will reset it to disable state.
-	 */
-	if (ctx->driver_data != &exynos5_fimd_driver_data &&
-	    ctx->driver_data != &exynos5420_fimd_driver_data)
-		return;
-
-	val = enable ? DP_MIE_CLK_DP_ENABLE : DP_MIE_CLK_DISABLE;
+	struct fimd_context *ctx = container_of(clk, struct fimd_context,
+						dp_clk);
+	u32 val = enable ? DP_MIE_CLK_DP_ENABLE : DP_MIE_CLK_DISABLE;
 	writel(val, ctx->regs + DP_MIE_CLKCON);
 }
 
@@ -902,13 +935,11 @@ static const struct exynos_drm_crtc_ops
 	.commit = fimd_commit,
 	.enable_vblank = fimd_enable_vblank,
 	.disable_vblank = fimd_disable_vblank,
-	.wait_for_vblank = fimd_wait_for_vblank,
 	.atomic_begin = fimd_atomic_begin,
 	.update_plane = fimd_update_plane,
 	.disable_plane = fimd_disable_plane,
 	.atomic_flush = fimd_atomic_flush,
 	.te_handler = fimd_te_handler,
-	.clock_enable = fimd_dp_clock_enable,
 };
 
 static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
@@ -987,6 +1018,11 @@ static int fimd_bind(struct device *dev,
 	if (IS_ERR(ctx->crtc))
 		return PTR_ERR(ctx->crtc);
 
+	if (ctx->driver_data->has_dp_clk) {
+		ctx->dp_clk.enable = fimd_dp_clock_enable;
+		ctx->crtc->pipe_clk = &ctx->dp_clk;
+	}
+
 	if (ctx->encoder)
 		exynos_dpi_bind(drm_dev, ctx->encoder);
 
@@ -1035,7 +1071,7 @@ static int fimd_probe(struct platform_de
 
 	ctx->dev = dev;
 	ctx->suspended = true;
-	ctx->driver_data = drm_fimd_get_driver_data(pdev);
+	ctx->driver_data = of_device_get_match_data(dev);
 
 	if (of_property_read_bool(dev->of_node, "samsung,invert-vden"))
 		ctx->vidcon1 |= VIDCON1_INV_VDEN;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_drm_g2d.c linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_drm_g2d.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_drm_g2d.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_drm_g2d.c	2016-07-24 15:23:50.000000000 -0400
@@ -48,13 +48,13 @@
 
 /* registers for base address */
 #define G2D_SRC_BASE_ADDR		0x0304
-#define G2D_SRC_STRIDE_REG		0x0308
+#define G2D_SRC_STRIDE			0x0308
 #define G2D_SRC_COLOR_MODE		0x030C
 #define G2D_SRC_LEFT_TOP		0x0310
 #define G2D_SRC_RIGHT_BOTTOM		0x0314
 #define G2D_SRC_PLANE2_BASE_ADDR	0x0318
 #define G2D_DST_BASE_ADDR		0x0404
-#define G2D_DST_STRIDE_REG		0x0408
+#define G2D_DST_STRIDE			0x0408
 #define G2D_DST_COLOR_MODE		0x040C
 #define G2D_DST_LEFT_TOP		0x0410
 #define G2D_DST_RIGHT_BOTTOM		0x0414
@@ -383,8 +383,8 @@ static void g2d_userptr_put_dma_addr(str
 		return;
 
 out:
-	exynos_gem_unmap_sgt_from_dma(drm_dev, g2d_userptr->sgt,
-					DMA_BIDIRECTIONAL);
+	dma_unmap_sg(to_dma_dev(drm_dev), g2d_userptr->sgt->sgl,
+			g2d_userptr->sgt->nents, DMA_BIDIRECTIONAL);
 
 	pages = frame_vector_pages(g2d_userptr->vec);
 	if (!IS_ERR(pages)) {
@@ -501,10 +501,10 @@ static dma_addr_t *g2d_userptr_get_dma_a
 
 	g2d_userptr->sgt = sgt;
 
-	ret = exynos_gem_map_sgt_with_dma(drm_dev, g2d_userptr->sgt,
-						DMA_BIDIRECTIONAL);
-	if (ret < 0) {
+	if (!dma_map_sg(to_dma_dev(drm_dev), sgt->sgl, sgt->nents,
+				DMA_BIDIRECTIONAL)) {
 		DRM_ERROR("failed to map sgt with dma region.\n");
+		ret = -ENOMEM;
 		goto err_sg_free_table;
 	}
 
@@ -563,7 +563,7 @@ static enum g2d_reg_type g2d_get_reg_typ
 
 	switch (reg_offset) {
 	case G2D_SRC_BASE_ADDR:
-	case G2D_SRC_STRIDE_REG:
+	case G2D_SRC_STRIDE:
 	case G2D_SRC_COLOR_MODE:
 	case G2D_SRC_LEFT_TOP:
 	case G2D_SRC_RIGHT_BOTTOM:
@@ -573,7 +573,7 @@ static enum g2d_reg_type g2d_get_reg_typ
 		reg_type = REG_TYPE_SRC_PLANE2;
 		break;
 	case G2D_DST_BASE_ADDR:
-	case G2D_DST_STRIDE_REG:
+	case G2D_DST_STRIDE:
 	case G2D_DST_COLOR_MODE:
 	case G2D_DST_LEFT_TOP:
 	case G2D_DST_RIGHT_BOTTOM:
@@ -968,8 +968,8 @@ static int g2d_check_reg_offset(struct d
 			} else
 				buf_info->types[reg_type] = BUF_TYPE_GEM;
 			break;
-		case G2D_SRC_STRIDE_REG:
-		case G2D_DST_STRIDE_REG:
+		case G2D_SRC_STRIDE:
+		case G2D_DST_STRIDE:
 			if (for_addr)
 				goto err;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_drm_gem.c linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_drm_gem.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_drm_gem.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_drm_gem.c	2016-07-24 15:23:50.000000000 -0400
@@ -177,7 +177,7 @@ unsigned long exynos_drm_gem_get_size(st
 	struct exynos_drm_gem *exynos_gem;
 	struct drm_gem_object *obj;
 
-	obj = drm_gem_object_lookup(dev, file_priv, gem_handle);
+	obj = drm_gem_object_lookup(file_priv, gem_handle);
 	if (!obj) {
 		DRM_ERROR("failed to lookup gem object.\n");
 		return 0;
@@ -296,7 +296,7 @@ dma_addr_t *exynos_drm_gem_get_dma_addr(
 	struct exynos_drm_gem *exynos_gem;
 	struct drm_gem_object *obj;
 
-	obj = drm_gem_object_lookup(dev, filp, gem_handle);
+	obj = drm_gem_object_lookup(filp, gem_handle);
 	if (!obj) {
 		DRM_ERROR("failed to lookup gem object.\n");
 		return ERR_PTR(-EINVAL);
@@ -313,7 +313,7 @@ void exynos_drm_gem_put_dma_addr(struct
 {
 	struct drm_gem_object *obj;
 
-	obj = drm_gem_object_lookup(dev, filp, gem_handle);
+	obj = drm_gem_object_lookup(filp, gem_handle);
 	if (!obj) {
 		DRM_ERROR("failed to lookup gem object.\n");
 		return;
@@ -362,12 +362,9 @@ int exynos_drm_gem_get_ioctl(struct drm_
 	struct drm_exynos_gem_info *args = data;
 	struct drm_gem_object *obj;
 
-	mutex_lock(&dev->struct_mutex);
-
-	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+	obj = drm_gem_object_lookup(file_priv, args->handle);
 	if (!obj) {
 		DRM_ERROR("failed to lookup gem object.\n");
-		mutex_unlock(&dev->struct_mutex);
 		return -EINVAL;
 	}
 
@@ -376,38 +373,11 @@ int exynos_drm_gem_get_ioctl(struct drm_
 	args->flags = exynos_gem->flags;
 	args->size = exynos_gem->size;
 
-	drm_gem_object_unreference(obj);
-	mutex_unlock(&dev->struct_mutex);
-
-	return 0;
-}
-
-int exynos_gem_map_sgt_with_dma(struct drm_device *drm_dev,
-				struct sg_table *sgt,
-				enum dma_data_direction dir)
-{
-	int nents;
-
-	mutex_lock(&drm_dev->struct_mutex);
-
-	nents = dma_map_sg(to_dma_dev(drm_dev), sgt->sgl, sgt->nents, dir);
-	if (!nents) {
-		DRM_ERROR("failed to map sgl with dma.\n");
-		mutex_unlock(&drm_dev->struct_mutex);
-		return nents;
-	}
+	drm_gem_object_unreference_unlocked(obj);
 
-	mutex_unlock(&drm_dev->struct_mutex);
 	return 0;
 }
 
-void exynos_gem_unmap_sgt_from_dma(struct drm_device *drm_dev,
-				struct sg_table *sgt,
-				enum dma_data_direction dir)
-{
-	dma_unmap_sg(to_dma_dev(drm_dev), sgt->sgl, sgt->nents, dir);
-}
-
 void exynos_drm_gem_free_object(struct drm_gem_object *obj)
 {
 	exynos_drm_gem_destroy(to_exynos_gem(obj));
@@ -458,27 +428,22 @@ int exynos_drm_gem_dumb_map_offset(struc
 	struct drm_gem_object *obj;
 	int ret = 0;
 
-	mutex_lock(&dev->struct_mutex);
-
 	/*
 	 * get offset of memory allocated for drm framebuffer.
 	 * - this callback would be called by user application
 	 *	with DRM_IOCTL_MODE_MAP_DUMB command.
 	 */
 
-	obj = drm_gem_object_lookup(dev, file_priv, handle);
+	obj = drm_gem_object_lookup(file_priv, handle);
 	if (!obj) {
 		DRM_ERROR("failed to lookup gem object.\n");
-		ret = -EINVAL;
-		goto unlock;
+		return -EINVAL;
 	}
 
 	*offset = drm_vma_node_offset_addr(&obj->vma_node);
 	DRM_DEBUG_KMS("offset = 0x%lx\n", (unsigned long)*offset);
 
-	drm_gem_object_unreference(obj);
-unlock:
-	mutex_unlock(&dev->struct_mutex);
+	drm_gem_object_unreference_unlocked(obj);
 	return ret;
 }
 
@@ -516,22 +481,12 @@ out:
 	}
 }
 
-int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
+static int exynos_drm_gem_mmap_obj(struct drm_gem_object *obj,
+				   struct vm_area_struct *vma)
 {
-	struct exynos_drm_gem *exynos_gem;
-	struct drm_gem_object *obj;
+	struct exynos_drm_gem *exynos_gem = to_exynos_gem(obj);
 	int ret;
 
-	/* set vm_area_struct. */
-	ret = drm_gem_mmap(filp, vma);
-	if (ret < 0) {
-		DRM_ERROR("failed to mmap.\n");
-		return ret;
-	}
-
-	obj = vma->vm_private_data;
-	exynos_gem = to_exynos_gem(obj);
-
 	DRM_DEBUG_KMS("flags = 0x%x\n", exynos_gem->flags);
 
 	/* non-cachable as default. */
@@ -556,6 +511,26 @@ err_close_vm:
 	return ret;
 }
 
+int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+	struct drm_gem_object *obj;
+	int ret;
+
+	/* set vm_area_struct. */
+	ret = drm_gem_mmap(filp, vma);
+	if (ret < 0) {
+		DRM_ERROR("failed to mmap.\n");
+		return ret;
+	}
+
+	obj = vma->vm_private_data;
+
+	if (obj->import_attach)
+		return dma_buf_mmap(obj->dma_buf, vma, 0);
+
+	return exynos_drm_gem_mmap_obj(obj, vma);
+}
+
 /* low-level interface prime helpers */
 struct sg_table *exynos_drm_gem_prime_get_sg_table(struct drm_gem_object *obj)
 {
@@ -630,3 +605,15 @@ void exynos_drm_gem_prime_vunmap(struct
 {
 	/* Nothing to do */
 }
+
+int exynos_drm_gem_prime_mmap(struct drm_gem_object *obj,
+			      struct vm_area_struct *vma)
+{
+	int ret;
+
+	ret = drm_gem_mmap_obj(obj, obj->size, vma);
+	if (ret < 0)
+		return ret;
+
+	return exynos_drm_gem_mmap_obj(obj, vma);
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_drm_gem.h linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_drm_gem.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_drm_gem.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_drm_gem.h	2016-07-24 15:23:50.000000000 -0400
@@ -121,16 +121,6 @@ int exynos_drm_gem_fault(struct vm_area_
 /* set vm_flags and we can change the vm attribute to other one at here. */
 int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma);
 
-/* map sgt with dma region. */
-int exynos_gem_map_sgt_with_dma(struct drm_device *drm_dev,
-				struct sg_table *sgt,
-				enum dma_data_direction dir);
-
-/* unmap sgt from dma region. */
-void exynos_gem_unmap_sgt_from_dma(struct drm_device *drm_dev,
-				struct sg_table *sgt,
-				enum dma_data_direction dir);
-
 /* low-level interface prime helpers */
 struct sg_table *exynos_drm_gem_prime_get_sg_table(struct drm_gem_object *obj);
 struct drm_gem_object *
@@ -139,5 +129,7 @@ exynos_drm_gem_prime_import_sg_table(str
 				     struct sg_table *sgt);
 void *exynos_drm_gem_prime_vmap(struct drm_gem_object *obj);
 void exynos_drm_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
+int exynos_drm_gem_prime_mmap(struct drm_gem_object *obj,
+			      struct vm_area_struct *vma);
 
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_drm_plane.c linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_drm_plane.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_drm_plane.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_drm_plane.c	2016-07-24 15:23:50.000000000 -0400
@@ -166,7 +166,7 @@ static void exynos_drm_plane_destroy_sta
 {
 	struct exynos_drm_plane_state *old_exynos_state =
 					to_exynos_plane_state(old_state);
-	__drm_atomic_helper_plane_destroy_state(plane, old_state);
+	__drm_atomic_helper_plane_destroy_state(old_state);
 	kfree(old_exynos_state);
 }
 
@@ -242,7 +242,7 @@ exynos_drm_plane_check_size(const struct
 	    state->v_ratio == (1 << 15))
 		height_ok = true;
 
-	if (width_ok & height_ok)
+	if (width_ok && height_ok)
 		return 0;
 
 	DRM_DEBUG_KMS("scaling mode is not supported");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_drm_rotator.c linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_drm_rotator.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_drm_rotator.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_drm_rotator.c	2016-07-24 15:23:50.000000000 -0400
@@ -15,6 +15,7 @@
 #include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
+#include <linux/of_device.h>
 #include <linux/pm_runtime.h>
 
 #include <drm/drmP.h>
@@ -696,7 +697,6 @@ static int rotator_probe(struct platform
 	struct device *dev = &pdev->dev;
 	struct rot_context *rot;
 	struct exynos_drm_ippdrv *ippdrv;
-	const struct of_device_id *match;
 	int ret;
 
 	if (!dev->of_node) {
@@ -708,13 +708,8 @@ static int rotator_probe(struct platform
 	if (!rot)
 		return -ENOMEM;
 
-	match = of_match_node(exynos_rotator_match, dev->of_node);
-	if (!match) {
-		dev_err(dev, "failed to match node\n");
-		return -ENODEV;
-	}
-	rot->limit_tbl = (struct rot_limit_table *)match->data;
-
+	rot->limit_tbl = (struct rot_limit_table *)
+				of_device_get_match_data(dev);
 	rot->regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	rot->regs = devm_ioremap_resource(dev, rot->regs_res);
 	if (IS_ERR(rot->regs))
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_hdmi.c linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_hdmi.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_hdmi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_hdmi.c	2016-07-24 15:23:50.000000000 -0400
@@ -7,9 +7,9 @@
  *
  * Based on drivers/media/video/s5p-tv/hdmi_drv.c
  *
- * 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
+ * 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.
  *
  */
@@ -49,14 +49,16 @@
 
 /* AVI header and aspect ratio */
 #define HDMI_AVI_VERSION		0x02
-#define HDMI_AVI_LENGTH		0x0D
+#define HDMI_AVI_LENGTH			0x0d
 
 /* AUI header info */
-#define HDMI_AUI_VERSION	0x01
-#define HDMI_AUI_LENGTH	0x0A
-#define AVI_SAME_AS_PIC_ASPECT_RATIO 0x8
-#define AVI_4_3_CENTER_RATIO	0x9
-#define AVI_16_9_CENTER_RATIO	0xa
+#define HDMI_AUI_VERSION		0x01
+#define HDMI_AUI_LENGTH			0x0a
+
+/* AVI active format aspect ratio */
+#define AVI_SAME_AS_PIC_ASPECT_RATIO	0x08
+#define AVI_4_3_CENTER_RATIO		0x09
+#define AVI_16_9_CENTER_RATIO		0x0a
 
 enum hdmi_type {
 	HDMI_TYPE13,
@@ -90,11 +92,34 @@ static const char * const supply[] = {
 	"vdd_pll",
 };
 
+struct hdmiphy_config {
+	int pixel_clock;
+	u8 conf[32];
+};
+
+struct hdmiphy_configs {
+	int count;
+	const struct hdmiphy_config *data;
+};
+
+struct string_array_spec {
+	int count;
+	const char * const *data;
+};
+
+#define INIT_ARRAY_SPEC(a) { .count = ARRAY_SIZE(a), .data = a }
+
 struct hdmi_driver_data {
 	unsigned int type;
-	const struct hdmiphy_config *phy_confs;
-	unsigned int phy_conf_count;
 	unsigned int is_apb_phy:1;
+	unsigned int has_sysreg:1;
+	struct hdmiphy_configs phy_confs;
+	struct string_array_spec clk_gates;
+	/*
+	 * Array of triplets (p_off, p_on, clock), where p_off and p_on are
+	 * required parents of clock when HDMI-PHY is respectively off or on.
+	 */
+	struct string_array_spec clk_muxes;
 };
 
 struct hdmi_context {
@@ -116,13 +141,12 @@ struct hdmi_context {
 	struct gpio_desc		*hpd_gpio;
 	int				irq;
 	struct regmap			*pmureg;
-	struct clk			*hdmi;
-	struct clk			*sclk_hdmi;
-	struct clk			*sclk_pixel;
-	struct clk			*sclk_hdmiphy;
-	struct clk			*mout_hdmi;
+	struct regmap			*sysreg;
+	struct clk			**clk_gates;
+	struct clk			**clk_muxes;
 	struct regulator_bulk_data	regul_bulk[ARRAY_SIZE(supply)];
 	struct regulator		*reg_hdmi_en;
+	struct exynos_drm_clk		phy_clk;
 };
 
 static inline struct hdmi_context *encoder_to_hdmi(struct drm_encoder *e)
@@ -135,12 +159,6 @@ static inline struct hdmi_context *conne
 	return container_of(c, struct hdmi_context, connector);
 }
 
-struct hdmiphy_config {
-	int pixel_clock;
-	u8 conf[32];
-};
-
-/* list of phy config settings */
 static const struct hdmiphy_config hdmiphy_v13_configs[] = {
 	{
 		.pixel_clock = 27000000,
@@ -501,25 +519,136 @@ static const struct hdmiphy_config hdmip
 	},
 };
 
-static struct hdmi_driver_data exynos5420_hdmi_driver_data = {
+static const struct hdmiphy_config hdmiphy_5433_configs[] = {
+	{
+		.pixel_clock = 27000000,
+		.conf = {
+			0x01, 0x51, 0x22, 0x51, 0x08, 0xfc, 0x88, 0x46,
+			0x72, 0x50, 0x24, 0x0c, 0x24, 0x0f, 0x7c, 0xa5,
+			0xd4, 0x2b, 0x87, 0x00, 0x00, 0x04, 0x00, 0x30,
+			0x08, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40,
+		},
+	},
+	{
+		.pixel_clock = 27027000,
+		.conf = {
+			0x01, 0x51, 0x2d, 0x72, 0x64, 0x09, 0x88, 0xc3,
+			0x71, 0x50, 0x24, 0x14, 0x24, 0x0f, 0x7c, 0xa5,
+			0xd4, 0x2b, 0x87, 0x00, 0x00, 0x04, 0x00, 0x30,
+			0x28, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40,
+		},
+	},
+	{
+		.pixel_clock = 40000000,
+		.conf = {
+			0x01, 0x51, 0x32, 0x55, 0x01, 0x00, 0x88, 0x02,
+			0x4d, 0x50, 0x44, 0x8C, 0x27, 0x00, 0x7C, 0xAC,
+			0xD6, 0x2B, 0x67, 0x00, 0x00, 0x04, 0x00, 0x30,
+			0x08, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40,
+		},
+	},
+	{
+		.pixel_clock = 50000000,
+		.conf = {
+			0x01, 0x51, 0x34, 0x40, 0x64, 0x09, 0x88, 0xc3,
+			0x3d, 0x50, 0x44, 0x8C, 0x27, 0x00, 0x7C, 0xAC,
+			0xD6, 0x2B, 0x67, 0x00, 0x00, 0x04, 0x00, 0x30,
+			0x08, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40,
+		},
+	},
+	{
+		.pixel_clock = 65000000,
+		.conf = {
+			0x01, 0x51, 0x36, 0x31, 0x40, 0x10, 0x04, 0xc6,
+			0x2e, 0xe8, 0x44, 0x8C, 0x27, 0x00, 0x7C, 0xAC,
+			0xD6, 0x2B, 0x67, 0x00, 0x00, 0x04, 0x00, 0x30,
+			0x08, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40,
+		},
+	},
+	{
+		.pixel_clock = 74176000,
+		.conf = {
+			0x01, 0x51, 0x3E, 0x35, 0x5B, 0xDE, 0x88, 0x42,
+			0x53, 0x51, 0x44, 0x8C, 0x27, 0x00, 0x7C, 0xAC,
+			0xD6, 0x2B, 0x67, 0x00, 0x00, 0x04, 0x00, 0x30,
+			0x08, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40,
+		},
+	},
+	{
+		.pixel_clock = 74250000,
+		.conf = {
+			0x01, 0x51, 0x3E, 0x35, 0x40, 0xF0, 0x88, 0xC2,
+			0x52, 0x51, 0x44, 0x8C, 0x27, 0x00, 0x7C, 0xAC,
+			0xD6, 0x2B, 0x67, 0x00, 0x00, 0x04, 0x00, 0x30,
+			0x08, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40,
+		},
+	},
+	{
+		.pixel_clock = 108000000,
+		.conf = {
+			0x01, 0x51, 0x2d, 0x15, 0x01, 0x00, 0x88, 0x02,
+			0x72, 0x52, 0x44, 0x8C, 0x27, 0x00, 0x7C, 0xAC,
+			0xD6, 0x2B, 0x67, 0x00, 0x00, 0x04, 0x00, 0x30,
+			0x08, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40,
+		},
+	},
+	{
+		.pixel_clock = 148500000,
+		.conf = {
+			0x01, 0x51, 0x1f, 0x00, 0x40, 0xf8, 0x88, 0xc1,
+			0x52, 0x52, 0x24, 0x0c, 0x24, 0x0f, 0x7c, 0xa5,
+			0xd4, 0x2b, 0x87, 0x00, 0x00, 0x04, 0x00, 0x30,
+			0x08, 0x10, 0x01, 0x01, 0x48, 0x4a, 0x00, 0x40,
+		},
+	},
+};
+
+static const char * const hdmi_clk_gates4[] = {
+	"hdmi", "sclk_hdmi"
+};
+
+static const char * const hdmi_clk_muxes4[] = {
+	"sclk_pixel", "sclk_hdmiphy", "mout_hdmi"
+};
+
+static const char * const hdmi_clk_gates5433[] = {
+	"hdmi_pclk", "hdmi_i_pclk", "i_tmds_clk", "i_pixel_clk", "i_spdif_clk"
+};
+
+static const char * const hdmi_clk_muxes5433[] = {
+	"oscclk", "tmds_clko", "tmds_clko_user",
+	"oscclk", "pixel_clko", "pixel_clko_user"
+};
+
+static const struct hdmi_driver_data exynos4210_hdmi_driver_data = {
+	.type		= HDMI_TYPE13,
+	.phy_confs	= INIT_ARRAY_SPEC(hdmiphy_v13_configs),
+	.clk_gates	= INIT_ARRAY_SPEC(hdmi_clk_gates4),
+	.clk_muxes	= INIT_ARRAY_SPEC(hdmi_clk_muxes4),
+};
+
+static const struct hdmi_driver_data exynos4212_hdmi_driver_data = {
 	.type		= HDMI_TYPE14,
-	.phy_confs	= hdmiphy_5420_configs,
-	.phy_conf_count	= ARRAY_SIZE(hdmiphy_5420_configs),
-	.is_apb_phy	= 1,
+	.phy_confs	= INIT_ARRAY_SPEC(hdmiphy_v14_configs),
+	.clk_gates	= INIT_ARRAY_SPEC(hdmi_clk_gates4),
+	.clk_muxes	= INIT_ARRAY_SPEC(hdmi_clk_muxes4),
 };
 
-static struct hdmi_driver_data exynos4212_hdmi_driver_data = {
+static const struct hdmi_driver_data exynos5420_hdmi_driver_data = {
 	.type		= HDMI_TYPE14,
-	.phy_confs	= hdmiphy_v14_configs,
-	.phy_conf_count	= ARRAY_SIZE(hdmiphy_v14_configs),
-	.is_apb_phy	= 0,
+	.is_apb_phy	= 1,
+	.phy_confs	= INIT_ARRAY_SPEC(hdmiphy_5420_configs),
+	.clk_gates	= INIT_ARRAY_SPEC(hdmi_clk_gates4),
+	.clk_muxes	= INIT_ARRAY_SPEC(hdmi_clk_muxes4),
 };
 
-static struct hdmi_driver_data exynos4210_hdmi_driver_data = {
-	.type		= HDMI_TYPE13,
-	.phy_confs	= hdmiphy_v13_configs,
-	.phy_conf_count	= ARRAY_SIZE(hdmiphy_v13_configs),
-	.is_apb_phy	= 0,
+static const struct hdmi_driver_data exynos5433_hdmi_driver_data = {
+	.type		= HDMI_TYPE14,
+	.is_apb_phy	= 1,
+	.has_sysreg     = 1,
+	.phy_confs	= INIT_ARRAY_SPEC(hdmiphy_5433_configs),
+	.clk_gates	= INIT_ARRAY_SPEC(hdmi_clk_gates5433),
+	.clk_muxes	= INIT_ARRAY_SPEC(hdmi_clk_muxes5433),
 };
 
 static inline u32 hdmi_map_reg(struct hdmi_context *hdata, u32 reg_id)
@@ -585,266 +714,52 @@ static int hdmiphy_reg_write_buf(struct
 	}
 }
 
-static void hdmi_v13_regs_dump(struct hdmi_context *hdata, char *prefix)
+static int hdmi_clk_enable_gates(struct hdmi_context *hdata)
 {
-#define DUMPREG(reg_id) \
-	DRM_DEBUG_KMS("%s:" #reg_id " = %08x\n", prefix, \
-	readl(hdata->regs + reg_id))
-	DRM_DEBUG_KMS("%s: ---- CONTROL REGISTERS ----\n", prefix);
-	DUMPREG(HDMI_INTC_FLAG);
-	DUMPREG(HDMI_INTC_CON);
-	DUMPREG(HDMI_HPD_STATUS);
-	DUMPREG(HDMI_V13_PHY_RSTOUT);
-	DUMPREG(HDMI_V13_PHY_VPLL);
-	DUMPREG(HDMI_V13_PHY_CMU);
-	DUMPREG(HDMI_V13_CORE_RSTOUT);
+	int i, ret;
 
-	DRM_DEBUG_KMS("%s: ---- CORE REGISTERS ----\n", prefix);
-	DUMPREG(HDMI_CON_0);
-	DUMPREG(HDMI_CON_1);
-	DUMPREG(HDMI_CON_2);
-	DUMPREG(HDMI_SYS_STATUS);
-	DUMPREG(HDMI_V13_PHY_STATUS);
-	DUMPREG(HDMI_STATUS_EN);
-	DUMPREG(HDMI_HPD);
-	DUMPREG(HDMI_MODE_SEL);
-	DUMPREG(HDMI_V13_HPD_GEN);
-	DUMPREG(HDMI_V13_DC_CONTROL);
-	DUMPREG(HDMI_V13_VIDEO_PATTERN_GEN);
+	for (i = 0; i < hdata->drv_data->clk_gates.count; ++i) {
+		ret = clk_prepare_enable(hdata->clk_gates[i]);
+		if (!ret)
+			continue;
 
-	DRM_DEBUG_KMS("%s: ---- CORE SYNC REGISTERS ----\n", prefix);
-	DUMPREG(HDMI_H_BLANK_0);
-	DUMPREG(HDMI_H_BLANK_1);
-	DUMPREG(HDMI_V13_V_BLANK_0);
-	DUMPREG(HDMI_V13_V_BLANK_1);
-	DUMPREG(HDMI_V13_V_BLANK_2);
-	DUMPREG(HDMI_V13_H_V_LINE_0);
-	DUMPREG(HDMI_V13_H_V_LINE_1);
-	DUMPREG(HDMI_V13_H_V_LINE_2);
-	DUMPREG(HDMI_VSYNC_POL);
-	DUMPREG(HDMI_INT_PRO_MODE);
-	DUMPREG(HDMI_V13_V_BLANK_F_0);
-	DUMPREG(HDMI_V13_V_BLANK_F_1);
-	DUMPREG(HDMI_V13_V_BLANK_F_2);
-	DUMPREG(HDMI_V13_H_SYNC_GEN_0);
-	DUMPREG(HDMI_V13_H_SYNC_GEN_1);
-	DUMPREG(HDMI_V13_H_SYNC_GEN_2);
-	DUMPREG(HDMI_V13_V_SYNC_GEN_1_0);
-	DUMPREG(HDMI_V13_V_SYNC_GEN_1_1);
-	DUMPREG(HDMI_V13_V_SYNC_GEN_1_2);
-	DUMPREG(HDMI_V13_V_SYNC_GEN_2_0);
-	DUMPREG(HDMI_V13_V_SYNC_GEN_2_1);
-	DUMPREG(HDMI_V13_V_SYNC_GEN_2_2);
-	DUMPREG(HDMI_V13_V_SYNC_GEN_3_0);
-	DUMPREG(HDMI_V13_V_SYNC_GEN_3_1);
-	DUMPREG(HDMI_V13_V_SYNC_GEN_3_2);
+		dev_err(hdata->dev, "Cannot enable clock '%s', %d\n",
+			hdata->drv_data->clk_gates.data[i], ret);
+		while (i--)
+			clk_disable_unprepare(hdata->clk_gates[i]);
+		return ret;
+	}
 
-	DRM_DEBUG_KMS("%s: ---- TG REGISTERS ----\n", prefix);
-	DUMPREG(HDMI_TG_CMD);
-	DUMPREG(HDMI_TG_H_FSZ_L);
-	DUMPREG(HDMI_TG_H_FSZ_H);
-	DUMPREG(HDMI_TG_HACT_ST_L);
-	DUMPREG(HDMI_TG_HACT_ST_H);
-	DUMPREG(HDMI_TG_HACT_SZ_L);
-	DUMPREG(HDMI_TG_HACT_SZ_H);
-	DUMPREG(HDMI_TG_V_FSZ_L);
-	DUMPREG(HDMI_TG_V_FSZ_H);
-	DUMPREG(HDMI_TG_VSYNC_L);
-	DUMPREG(HDMI_TG_VSYNC_H);
-	DUMPREG(HDMI_TG_VSYNC2_L);
-	DUMPREG(HDMI_TG_VSYNC2_H);
-	DUMPREG(HDMI_TG_VACT_ST_L);
-	DUMPREG(HDMI_TG_VACT_ST_H);
-	DUMPREG(HDMI_TG_VACT_SZ_L);
-	DUMPREG(HDMI_TG_VACT_SZ_H);
-	DUMPREG(HDMI_TG_FIELD_CHG_L);
-	DUMPREG(HDMI_TG_FIELD_CHG_H);
-	DUMPREG(HDMI_TG_VACT_ST2_L);
-	DUMPREG(HDMI_TG_VACT_ST2_H);
-	DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_L);
-	DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_H);
-	DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_L);
-	DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_H);
-	DUMPREG(HDMI_TG_FIELD_TOP_HDMI_L);
-	DUMPREG(HDMI_TG_FIELD_TOP_HDMI_H);
-	DUMPREG(HDMI_TG_FIELD_BOT_HDMI_L);
-	DUMPREG(HDMI_TG_FIELD_BOT_HDMI_H);
-#undef DUMPREG
+	return 0;
 }
 
-static void hdmi_v14_regs_dump(struct hdmi_context *hdata, char *prefix)
+static void hdmi_clk_disable_gates(struct hdmi_context *hdata)
 {
-	int i;
-
-#define DUMPREG(reg_id) \
-	DRM_DEBUG_KMS("%s:" #reg_id " = %08x\n", prefix, \
-	readl(hdata->regs + reg_id))
-
-	DRM_DEBUG_KMS("%s: ---- CONTROL REGISTERS ----\n", prefix);
-	DUMPREG(HDMI_INTC_CON);
-	DUMPREG(HDMI_INTC_FLAG);
-	DUMPREG(HDMI_HPD_STATUS);
-	DUMPREG(HDMI_INTC_CON_1);
-	DUMPREG(HDMI_INTC_FLAG_1);
-	DUMPREG(HDMI_PHY_STATUS_0);
-	DUMPREG(HDMI_PHY_STATUS_PLL);
-	DUMPREG(HDMI_PHY_CON_0);
-	DUMPREG(HDMI_V14_PHY_RSTOUT);
-	DUMPREG(HDMI_PHY_VPLL);
-	DUMPREG(HDMI_PHY_CMU);
-	DUMPREG(HDMI_CORE_RSTOUT);
-
-	DRM_DEBUG_KMS("%s: ---- CORE REGISTERS ----\n", prefix);
-	DUMPREG(HDMI_CON_0);
-	DUMPREG(HDMI_CON_1);
-	DUMPREG(HDMI_CON_2);
-	DUMPREG(HDMI_SYS_STATUS);
-	DUMPREG(HDMI_PHY_STATUS_0);
-	DUMPREG(HDMI_STATUS_EN);
-	DUMPREG(HDMI_HPD);
-	DUMPREG(HDMI_MODE_SEL);
-	DUMPREG(HDMI_ENC_EN);
-	DUMPREG(HDMI_DC_CONTROL);
-	DUMPREG(HDMI_VIDEO_PATTERN_GEN);
-
-	DRM_DEBUG_KMS("%s: ---- CORE SYNC REGISTERS ----\n", prefix);
-	DUMPREG(HDMI_H_BLANK_0);
-	DUMPREG(HDMI_H_BLANK_1);
-	DUMPREG(HDMI_V2_BLANK_0);
-	DUMPREG(HDMI_V2_BLANK_1);
-	DUMPREG(HDMI_V1_BLANK_0);
-	DUMPREG(HDMI_V1_BLANK_1);
-	DUMPREG(HDMI_V_LINE_0);
-	DUMPREG(HDMI_V_LINE_1);
-	DUMPREG(HDMI_H_LINE_0);
-	DUMPREG(HDMI_H_LINE_1);
-	DUMPREG(HDMI_HSYNC_POL);
-
-	DUMPREG(HDMI_VSYNC_POL);
-	DUMPREG(HDMI_INT_PRO_MODE);
-	DUMPREG(HDMI_V_BLANK_F0_0);
-	DUMPREG(HDMI_V_BLANK_F0_1);
-	DUMPREG(HDMI_V_BLANK_F1_0);
-	DUMPREG(HDMI_V_BLANK_F1_1);
-
-	DUMPREG(HDMI_H_SYNC_START_0);
-	DUMPREG(HDMI_H_SYNC_START_1);
-	DUMPREG(HDMI_H_SYNC_END_0);
-	DUMPREG(HDMI_H_SYNC_END_1);
-
-	DUMPREG(HDMI_V_SYNC_LINE_BEF_2_0);
-	DUMPREG(HDMI_V_SYNC_LINE_BEF_2_1);
-	DUMPREG(HDMI_V_SYNC_LINE_BEF_1_0);
-	DUMPREG(HDMI_V_SYNC_LINE_BEF_1_1);
-
-	DUMPREG(HDMI_V_SYNC_LINE_AFT_2_0);
-	DUMPREG(HDMI_V_SYNC_LINE_AFT_2_1);
-	DUMPREG(HDMI_V_SYNC_LINE_AFT_1_0);
-	DUMPREG(HDMI_V_SYNC_LINE_AFT_1_1);
-
-	DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_2_0);
-	DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_2_1);
-	DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_1_0);
-	DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_1_1);
-
-	DUMPREG(HDMI_V_BLANK_F2_0);
-	DUMPREG(HDMI_V_BLANK_F2_1);
-	DUMPREG(HDMI_V_BLANK_F3_0);
-	DUMPREG(HDMI_V_BLANK_F3_1);
-	DUMPREG(HDMI_V_BLANK_F4_0);
-	DUMPREG(HDMI_V_BLANK_F4_1);
-	DUMPREG(HDMI_V_BLANK_F5_0);
-	DUMPREG(HDMI_V_BLANK_F5_1);
-
-	DUMPREG(HDMI_V_SYNC_LINE_AFT_3_0);
-	DUMPREG(HDMI_V_SYNC_LINE_AFT_3_1);
-	DUMPREG(HDMI_V_SYNC_LINE_AFT_4_0);
-	DUMPREG(HDMI_V_SYNC_LINE_AFT_4_1);
-	DUMPREG(HDMI_V_SYNC_LINE_AFT_5_0);
-	DUMPREG(HDMI_V_SYNC_LINE_AFT_5_1);
-	DUMPREG(HDMI_V_SYNC_LINE_AFT_6_0);
-	DUMPREG(HDMI_V_SYNC_LINE_AFT_6_1);
+	int i = hdata->drv_data->clk_gates.count;
 
-	DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_3_0);
-	DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_3_1);
-	DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_4_0);
-	DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_4_1);
-	DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_5_0);
-	DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_5_1);
-	DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_6_0);
-	DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_6_1);
+	while (i--)
+		clk_disable_unprepare(hdata->clk_gates[i]);
+}
 
-	DUMPREG(HDMI_VACT_SPACE_1_0);
-	DUMPREG(HDMI_VACT_SPACE_1_1);
-	DUMPREG(HDMI_VACT_SPACE_2_0);
-	DUMPREG(HDMI_VACT_SPACE_2_1);
-	DUMPREG(HDMI_VACT_SPACE_3_0);
-	DUMPREG(HDMI_VACT_SPACE_3_1);
-	DUMPREG(HDMI_VACT_SPACE_4_0);
-	DUMPREG(HDMI_VACT_SPACE_4_1);
-	DUMPREG(HDMI_VACT_SPACE_5_0);
-	DUMPREG(HDMI_VACT_SPACE_5_1);
-	DUMPREG(HDMI_VACT_SPACE_6_0);
-	DUMPREG(HDMI_VACT_SPACE_6_1);
+static int hdmi_clk_set_parents(struct hdmi_context *hdata, bool to_phy)
+{
+	struct device *dev = hdata->dev;
+	int ret = 0;
+	int i;
 
-	DRM_DEBUG_KMS("%s: ---- TG REGISTERS ----\n", prefix);
-	DUMPREG(HDMI_TG_CMD);
-	DUMPREG(HDMI_TG_H_FSZ_L);
-	DUMPREG(HDMI_TG_H_FSZ_H);
-	DUMPREG(HDMI_TG_HACT_ST_L);
-	DUMPREG(HDMI_TG_HACT_ST_H);
-	DUMPREG(HDMI_TG_HACT_SZ_L);
-	DUMPREG(HDMI_TG_HACT_SZ_H);
-	DUMPREG(HDMI_TG_V_FSZ_L);
-	DUMPREG(HDMI_TG_V_FSZ_H);
-	DUMPREG(HDMI_TG_VSYNC_L);
-	DUMPREG(HDMI_TG_VSYNC_H);
-	DUMPREG(HDMI_TG_VSYNC2_L);
-	DUMPREG(HDMI_TG_VSYNC2_H);
-	DUMPREG(HDMI_TG_VACT_ST_L);
-	DUMPREG(HDMI_TG_VACT_ST_H);
-	DUMPREG(HDMI_TG_VACT_SZ_L);
-	DUMPREG(HDMI_TG_VACT_SZ_H);
-	DUMPREG(HDMI_TG_FIELD_CHG_L);
-	DUMPREG(HDMI_TG_FIELD_CHG_H);
-	DUMPREG(HDMI_TG_VACT_ST2_L);
-	DUMPREG(HDMI_TG_VACT_ST2_H);
-	DUMPREG(HDMI_TG_VACT_ST3_L);
-	DUMPREG(HDMI_TG_VACT_ST3_H);
-	DUMPREG(HDMI_TG_VACT_ST4_L);
-	DUMPREG(HDMI_TG_VACT_ST4_H);
-	DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_L);
-	DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_H);
-	DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_L);
-	DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_H);
-	DUMPREG(HDMI_TG_FIELD_TOP_HDMI_L);
-	DUMPREG(HDMI_TG_FIELD_TOP_HDMI_H);
-	DUMPREG(HDMI_TG_FIELD_BOT_HDMI_L);
-	DUMPREG(HDMI_TG_FIELD_BOT_HDMI_H);
-	DUMPREG(HDMI_TG_3D);
+	for (i = 0; i < hdata->drv_data->clk_muxes.count; i += 3) {
+		struct clk **c = &hdata->clk_muxes[i];
 
-	DRM_DEBUG_KMS("%s: ---- PACKET REGISTERS ----\n", prefix);
-	DUMPREG(HDMI_AVI_CON);
-	DUMPREG(HDMI_AVI_HEADER0);
-	DUMPREG(HDMI_AVI_HEADER1);
-	DUMPREG(HDMI_AVI_HEADER2);
-	DUMPREG(HDMI_AVI_CHECK_SUM);
-	DUMPREG(HDMI_VSI_CON);
-	DUMPREG(HDMI_VSI_HEADER0);
-	DUMPREG(HDMI_VSI_HEADER1);
-	DUMPREG(HDMI_VSI_HEADER2);
-	for (i = 0; i < 7; ++i)
-		DUMPREG(HDMI_VSI_DATA(i));
+		ret = clk_set_parent(c[2], c[to_phy]);
+		if (!ret)
+			continue;
 
-#undef DUMPREG
-}
+		dev_err(dev, "Cannot set clock parent of '%s' to '%s', %d\n",
+			hdata->drv_data->clk_muxes.data[i + 2],
+			hdata->drv_data->clk_muxes.data[i + to_phy], ret);
+	}
 
-static void hdmi_regs_dump(struct hdmi_context *hdata, char *prefix)
-{
-	if (hdata->drv_data->type == HDMI_TYPE13)
-		hdmi_v13_regs_dump(hdata, prefix);
-	else
-		hdmi_v14_regs_dump(hdata, prefix);
+	return ret;
 }
 
 static u8 hdmi_chksum(struct hdmi_context *hdata,
@@ -993,10 +908,11 @@ static int hdmi_get_modes(struct drm_con
 
 static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock)
 {
+	const struct hdmiphy_configs *confs = &hdata->drv_data->phy_confs;
 	int i;
 
-	for (i = 0; i < hdata->drv_data->phy_conf_count; i++)
-		if (hdata->drv_data->phy_confs[i].pixel_clock == pixel_clock)
+	for (i = 0; i < confs->count; i++)
+		if (confs->data[i].pixel_clock == pixel_clock)
 			return i;
 
 	DRM_DEBUG_KMS("Could not find phy config for %d\n", pixel_clock);
@@ -1078,13 +994,11 @@ static bool hdmi_mode_fixup(struct drm_e
 
 	mode_ok = hdmi_mode_valid(connector, adjusted_mode);
 
-	/* just return if user desired mode exists. */
 	if (mode_ok == MODE_OK)
 		return true;
 
 	/*
-	 * otherwise, find the most suitable mode among modes and change it
-	 * to adjusted_mode.
+	 * Find the most suitable mode and copy it to adjusted_mode.
 	 */
 	list_for_each_entry(m, &connector->modes, head) {
 		mode_ok = hdmi_mode_valid(connector, m);
@@ -1129,15 +1043,15 @@ static void hdmi_audio_init(struct hdmi_
 	switch (bits_per_sample) {
 	case 20:
 		data_num = 2;
-		bit_ch  = 1;
+		bit_ch = 1;
 		break;
 	case 24:
 		data_num = 3;
-		bit_ch  = 1;
+		bit_ch = 1;
 		break;
 	default:
 		data_num = 1;
-		bit_ch  = 0;
+		bit_ch = 0;
 		break;
 	}
 
@@ -1230,13 +1144,12 @@ static void hdmi_conf_init(struct hdmi_c
 	/* choose HDMI mode */
 	hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
 		HDMI_MODE_HDMI_EN, HDMI_MODE_MASK);
-	/* Apply Video preable and Guard band in HDMI mode only */
+	/* apply video pre-amble and guard band in HDMI mode only */
 	hdmi_reg_writeb(hdata, HDMI_CON_2, 0);
 	/* disable bluescreen */
 	hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_BLUE_SCR_EN);
 
 	if (hdata->dvi_mode) {
-		/* choose DVI mode */
 		hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
 				HDMI_MODE_DVI_EN, HDMI_MODE_MASK);
 		hdmi_reg_writeb(hdata, HDMI_CON_2,
@@ -1308,7 +1221,7 @@ static void hdmi_v13_mode_apply(struct h
 
 	val = (m->hsync_start - m->hdisplay - 2);
 	val |= ((m->hsync_end - m->hdisplay - 2) << 10);
-	val |= ((m->flags & DRM_MODE_FLAG_NHSYNC)  ? 1 : 0)<<20;
+	val |= ((m->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0)<<20;
 	hdmi_reg_writev(hdata, HDMI_V13_H_SYNC_GEN_0, 3, val);
 
 	/*
@@ -1319,7 +1232,6 @@ static void hdmi_v13_mode_apply(struct h
 
 	/* Following values & calculations differ for different type of modes */
 	if (m->flags & DRM_MODE_FLAG_INTERLACE) {
-		/* Interlaced Mode */
 		val = ((m->vsync_end - m->vdisplay) / 2);
 		val |= ((m->vsync_start - m->vdisplay) / 2) << 12;
 		hdmi_reg_writev(hdata, HDMI_V13_V_SYNC_GEN_1_0, 3, val);
@@ -1348,8 +1260,6 @@ static void hdmi_v13_mode_apply(struct h
 
 		hdmi_reg_writev(hdata, HDMI_TG_VACT_ST2_L, 2, 0x249);
 	} else {
-		/* Progressive Mode */
-
 		val = m->vtotal;
 		val |= (m->vtotal - m->vdisplay) << 11;
 		hdmi_reg_writev(hdata, HDMI_V13_V_BLANK_0, 3, val);
@@ -1365,21 +1275,12 @@ static void hdmi_v13_mode_apply(struct h
 		hdmi_reg_writev(hdata, HDMI_TG_VACT_ST_L, 2,
 				m->vtotal - m->vdisplay);
 		hdmi_reg_writev(hdata, HDMI_TG_VACT_SZ_L, 2, m->vdisplay);
-		hdmi_reg_writev(hdata, HDMI_TG_VACT_ST2_L, 2, 0x248);
 	}
 
-	/* Timing generator registers */
 	hdmi_reg_writev(hdata, HDMI_TG_H_FSZ_L, 2, m->htotal);
 	hdmi_reg_writev(hdata, HDMI_TG_HACT_ST_L, 2, m->htotal - m->hdisplay);
 	hdmi_reg_writev(hdata, HDMI_TG_HACT_SZ_L, 2, m->hdisplay);
 	hdmi_reg_writev(hdata, HDMI_TG_V_FSZ_L, 2, m->vtotal);
-	hdmi_reg_writev(hdata, HDMI_TG_VSYNC_L, 2, 0x1);
-	hdmi_reg_writev(hdata, HDMI_TG_VSYNC2_L, 2, 0x233);
-	hdmi_reg_writev(hdata, HDMI_TG_FIELD_CHG_L, 2, 0x233);
-	hdmi_reg_writev(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, 2, 0x1);
-	hdmi_reg_writev(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, 2, 0x233);
-	hdmi_reg_writev(hdata, HDMI_TG_FIELD_TOP_HDMI_L, 2, 0x1);
-	hdmi_reg_writev(hdata, HDMI_TG_FIELD_BOT_HDMI_L, 2, 0x233);
 }
 
 static void hdmi_v14_mode_apply(struct hdmi_context *hdata)
@@ -1390,7 +1291,7 @@ static void hdmi_v14_mode_apply(struct h
 	hdmi_reg_writev(hdata, HDMI_V_LINE_0, 2, m->vtotal);
 	hdmi_reg_writev(hdata, HDMI_H_LINE_0, 2, m->htotal);
 	hdmi_reg_writev(hdata, HDMI_HSYNC_POL, 1,
-			(m->flags & DRM_MODE_FLAG_NHSYNC)  ? 1 : 0);
+			(m->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0);
 	hdmi_reg_writev(hdata, HDMI_VSYNC_POL, 1,
 			(m->flags & DRM_MODE_FLAG_NVSYNC) ? 1 : 0);
 	hdmi_reg_writev(hdata, HDMI_INT_PRO_MODE, 1,
@@ -1404,7 +1305,6 @@ static void hdmi_v14_mode_apply(struct h
 
 	/* Following values & calculations differ for different type of modes */
 	if (m->flags & DRM_MODE_FLAG_INTERLACE) {
-		/* Interlaced Mode */
 		hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_BEF_2_0, 2,
 			(m->vsync_end - m->vdisplay) / 2);
 		hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_BEF_1_0, 2,
@@ -1437,7 +1337,6 @@ static void hdmi_v14_mode_apply(struct h
 		hdmi_reg_writev(hdata, HDMI_TG_VACT_ST3_L, 2, 0x0);
 		hdmi_reg_writev(hdata, HDMI_TG_VACT_ST4_L, 2, 0x0);
 	} else {
-		/* Progressive Mode */
 		hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_BEF_2_0, 2,
 			m->vsync_end - m->vdisplay);
 		hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_BEF_1_0, 2,
@@ -1454,15 +1353,8 @@ static void hdmi_v14_mode_apply(struct h
 		hdmi_reg_writev(hdata, HDMI_TG_VACT_ST_L, 2,
 				m->vtotal - m->vdisplay);
 		hdmi_reg_writev(hdata, HDMI_TG_VACT_SZ_L, 2, m->vdisplay);
-		hdmi_reg_writev(hdata, HDMI_TG_VACT_ST2_L, 2, 0x248);
-		hdmi_reg_writev(hdata, HDMI_TG_VACT_ST3_L, 2, 0x47b);
-		hdmi_reg_writev(hdata, HDMI_TG_VACT_ST4_L, 2, 0x6ae);
-		hdmi_reg_writev(hdata, HDMI_TG_VSYNC2_L, 2, 0x233);
-		hdmi_reg_writev(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, 2, 0x233);
-		hdmi_reg_writev(hdata, HDMI_TG_FIELD_BOT_HDMI_L, 2, 0x233);
 	}
 
-	/* Following values & calculations are same irrespective of mode type */
 	hdmi_reg_writev(hdata, HDMI_H_SYNC_START_0, 2,
 			m->hsync_start - m->hdisplay - 2);
 	hdmi_reg_writev(hdata, HDMI_H_SYNC_END_0, 2,
@@ -1486,16 +1378,12 @@ static void hdmi_v14_mode_apply(struct h
 	hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_0, 2, 0xffff);
 	hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_0, 2, 0xffff);
 
-	/* Timing generator registers */
 	hdmi_reg_writev(hdata, HDMI_TG_H_FSZ_L, 2, m->htotal);
 	hdmi_reg_writev(hdata, HDMI_TG_HACT_ST_L, 2, m->htotal - m->hdisplay);
 	hdmi_reg_writev(hdata, HDMI_TG_HACT_SZ_L, 2, m->hdisplay);
 	hdmi_reg_writev(hdata, HDMI_TG_V_FSZ_L, 2, m->vtotal);
-	hdmi_reg_writev(hdata, HDMI_TG_VSYNC_L, 2, 0x1);
-	hdmi_reg_writev(hdata, HDMI_TG_FIELD_CHG_L, 2, 0x233);
-	hdmi_reg_writev(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, 2, 0x1);
-	hdmi_reg_writev(hdata, HDMI_TG_FIELD_TOP_HDMI_L, 2, 0x1);
-	hdmi_reg_writev(hdata, HDMI_TG_3D, 1, 0x0);
+	if (hdata->drv_data == &exynos5433_hdmi_driver_data)
+		hdmi_reg_writeb(hdata, HDMI_TG_DECON_EN, 1);
 }
 
 static void hdmi_mode_apply(struct hdmi_context *hdata)
@@ -1505,62 +1393,64 @@ static void hdmi_mode_apply(struct hdmi_
 	else
 		hdmi_v14_mode_apply(hdata);
 
-	hdmiphy_wait_for_pll(hdata);
-
-	clk_set_parent(hdata->mout_hdmi, hdata->sclk_hdmiphy);
-
-	/* enable HDMI and timing generator */
 	hdmi_start(hdata, true);
 }
 
 static void hdmiphy_conf_reset(struct hdmi_context *hdata)
 {
-	clk_set_parent(hdata->mout_hdmi, hdata->sclk_pixel);
-
-	/* reset hdmiphy */
+	hdmi_reg_writemask(hdata, HDMI_CORE_RSTOUT, 0, 1);
+	usleep_range(10000, 12000);
+	hdmi_reg_writemask(hdata, HDMI_CORE_RSTOUT, ~0, 1);
+	usleep_range(10000, 12000);
 	hdmi_reg_writemask(hdata, HDMI_PHY_RSTOUT, ~0, HDMI_PHY_SW_RSTOUT);
 	usleep_range(10000, 12000);
-	hdmi_reg_writemask(hdata, HDMI_PHY_RSTOUT,  0, HDMI_PHY_SW_RSTOUT);
+	hdmi_reg_writemask(hdata, HDMI_PHY_RSTOUT, 0, HDMI_PHY_SW_RSTOUT);
 	usleep_range(10000, 12000);
 }
 
+static void hdmiphy_enable_mode_set(struct hdmi_context *hdata, bool enable)
+{
+	u8 v = enable ? HDMI_PHY_ENABLE_MODE_SET : HDMI_PHY_DISABLE_MODE_SET;
+
+	if (hdata->drv_data == &exynos5433_hdmi_driver_data)
+		writel(v, hdata->regs_hdmiphy + HDMIPHY5433_MODE_SET_DONE);
+}
+
 static void hdmiphy_conf_apply(struct hdmi_context *hdata)
 {
 	int ret;
-	int i;
+	const u8 *phy_conf;
 
-	/* pixel clock */
-	i = hdmi_find_phy_conf(hdata, hdata->current_mode.clock * 1000);
-	if (i < 0) {
+	ret = hdmi_find_phy_conf(hdata, hdata->current_mode.clock * 1000);
+	if (ret < 0) {
 		DRM_ERROR("failed to find hdmiphy conf\n");
 		return;
 	}
+	phy_conf = hdata->drv_data->phy_confs.data[ret].conf;
 
-	ret = hdmiphy_reg_write_buf(hdata, 0,
-			hdata->drv_data->phy_confs[i].conf, 32);
+	hdmi_clk_set_parents(hdata, false);
+
+	hdmiphy_conf_reset(hdata);
+
+	hdmiphy_enable_mode_set(hdata, true);
+	ret = hdmiphy_reg_write_buf(hdata, 0, phy_conf, 32);
 	if (ret) {
 		DRM_ERROR("failed to configure hdmiphy\n");
 		return;
 	}
-
+	hdmiphy_enable_mode_set(hdata, false);
+	hdmi_clk_set_parents(hdata, true);
 	usleep_range(10000, 12000);
+	hdmiphy_wait_for_pll(hdata);
 }
 
 static void hdmi_conf_apply(struct hdmi_context *hdata)
 {
-	hdmiphy_conf_reset(hdata);
-	hdmiphy_conf_apply(hdata);
-
 	hdmi_start(hdata, false);
 	hdmi_conf_init(hdata);
-
 	hdmi_audio_init(hdata);
-
-	/* setting core registers */
 	hdmi_mode_apply(hdata);
 	hdmi_audio_control(hdata, true);
-
-	hdmi_regs_dump(hdata, "start");
 }
 
 static void hdmi_mode_set(struct drm_encoder *encoder,
@@ -1579,10 +1469,17 @@ static void hdmi_mode_set(struct drm_enc
 	hdata->cea_video_id = drm_match_cea_mode(mode);
 }
 
-static void hdmi_enable(struct drm_encoder *encoder)
+static void hdmi_set_refclk(struct hdmi_context *hdata, bool on)
 {
-	struct hdmi_context *hdata = encoder_to_hdmi(encoder);
+	if (!hdata->sysreg)
+		return;
+
+	regmap_update_bits(hdata->sysreg, EXYNOS5433_SYSREG_DISP_HDMI_PHY,
+			   SYSREG_HDMI_REFCLK_INT_CLK, on ? ~0 : 0);
+}
 
+static void hdmiphy_enable(struct hdmi_context *hdata)
+{
 	if (hdata->powered)
 		return;
 
@@ -1591,15 +1488,47 @@ static void hdmi_enable(struct drm_encod
 	if (regulator_bulk_enable(ARRAY_SIZE(supply), hdata->regul_bulk))
 		DRM_DEBUG_KMS("failed to enable regulator bulk\n");
 
-	/* set pmu hdmiphy control bit to enable hdmiphy */
 	regmap_update_bits(hdata->pmureg, PMU_HDMI_PHY_CONTROL,
 			PMU_HDMI_PHY_ENABLE_BIT, 1);
 
-	hdmi_conf_apply(hdata);
+	hdmi_set_refclk(hdata, true);
+
+	hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, 0, HDMI_PHY_POWER_OFF_EN);
+
+	hdmiphy_conf_apply(hdata);
 
 	hdata->powered = true;
 }
 
+static void hdmiphy_disable(struct hdmi_context *hdata)
+{
+	if (!hdata->powered)
+		return;
+
+	hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_EN);
+
+	hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, ~0, HDMI_PHY_POWER_OFF_EN);
+
+	hdmi_set_refclk(hdata, false);
+
+	regmap_update_bits(hdata->pmureg, PMU_HDMI_PHY_CONTROL,
+			PMU_HDMI_PHY_ENABLE_BIT, 0);
+
+	regulator_bulk_disable(ARRAY_SIZE(supply), hdata->regul_bulk);
+
+	pm_runtime_put_sync(hdata->dev);
+
+	hdata->powered = false;
+}
+
+static void hdmi_enable(struct drm_encoder *encoder)
+{
+	struct hdmi_context *hdata = encoder_to_hdmi(encoder);
+
+	hdmiphy_enable(hdata);
+	hdmi_conf_apply(hdata);
+}
+
 static void hdmi_disable(struct drm_encoder *encoder)
 {
 	struct hdmi_context *hdata = encoder_to_hdmi(encoder);
@@ -1623,20 +1552,9 @@ static void hdmi_disable(struct drm_enco
 	if (funcs && funcs->disable)
 		(*funcs->disable)(crtc);
 
-	/* HDMI System Disable */
-	hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_EN);
-
 	cancel_delayed_work(&hdata->hotplug_work);
 
-	/* reset pmu hdmiphy control bit to disable hdmiphy */
-	regmap_update_bits(hdata->pmureg, PMU_HDMI_PHY_CONTROL,
-			PMU_HDMI_PHY_ENABLE_BIT, 0);
-
-	regulator_bulk_disable(ARRAY_SIZE(supply), hdata->regul_bulk);
-
-	pm_runtime_put_sync(hdata->dev);
-
-	hdata->powered = false;
+	hdmiphy_disable(hdata);
 }
 
 static const struct drm_encoder_helper_funcs exynos_hdmi_encoder_helper_funcs = {
@@ -1670,6 +1588,68 @@ static irqreturn_t hdmi_irq_thread(int i
 	return IRQ_HANDLED;
 }
 
+static int hdmi_clks_get(struct hdmi_context *hdata,
+			 const struct string_array_spec *names,
+			 struct clk **clks)
+{
+	struct device *dev = hdata->dev;
+	int i;
+
+	for (i = 0; i < names->count; ++i) {
+		struct clk *clk = devm_clk_get(dev, names->data[i]);
+
+		if (IS_ERR(clk)) {
+			int ret = PTR_ERR(clk);
+
+			dev_err(dev, "Cannot get clock %s, %d\n",
+				names->data[i], ret);
+
+			return ret;
+		}
+
+		clks[i] = clk;
+	}
+
+	return 0;
+}
+
+static int hdmi_clk_init(struct hdmi_context *hdata)
+{
+	const struct hdmi_driver_data *drv_data = hdata->drv_data;
+	int count = drv_data->clk_gates.count + drv_data->clk_muxes.count;
+	struct device *dev = hdata->dev;
+	struct clk **clks;
+	int ret;
+
+	if (!count)
+		return 0;
+
+	clks = devm_kzalloc(dev, sizeof(*clks) * count, GFP_KERNEL);
+	if (!clks)
+		return -ENOMEM;
+
+	hdata->clk_gates = clks;
+	hdata->clk_muxes = clks + drv_data->clk_gates.count;
+
+	ret = hdmi_clks_get(hdata, &drv_data->clk_gates, hdata->clk_gates);
+	if (ret)
+		return ret;
+
+	return hdmi_clks_get(hdata, &drv_data->clk_muxes, hdata->clk_muxes);
+}
+
+
+static void hdmiphy_clk_enable(struct exynos_drm_clk *clk, bool enable)
+{
+	struct hdmi_context *hdata = container_of(clk, struct hdmi_context,
+						  phy_clk);
+
+	if (enable)
+		hdmiphy_enable(hdata);
+	else
+		hdmiphy_disable(hdata);
+}
+
 static int hdmi_resources_init(struct hdmi_context *hdata)
 {
 	struct device *dev = hdata->dev;
@@ -1688,39 +1668,14 @@ static int hdmi_resources_init(struct hd
 		DRM_ERROR("failed to get GPIO irq\n");
 		return  hdata->irq;
 	}
-	/* get clocks, power */
-	hdata->hdmi = devm_clk_get(dev, "hdmi");
-	if (IS_ERR(hdata->hdmi)) {
-		DRM_ERROR("failed to get clock 'hdmi'\n");
-		ret = PTR_ERR(hdata->hdmi);
-		goto fail;
-	}
-	hdata->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi");
-	if (IS_ERR(hdata->sclk_hdmi)) {
-		DRM_ERROR("failed to get clock 'sclk_hdmi'\n");
-		ret = PTR_ERR(hdata->sclk_hdmi);
-		goto fail;
-	}
-	hdata->sclk_pixel = devm_clk_get(dev, "sclk_pixel");
-	if (IS_ERR(hdata->sclk_pixel)) {
-		DRM_ERROR("failed to get clock 'sclk_pixel'\n");
-		ret = PTR_ERR(hdata->sclk_pixel);
-		goto fail;
-	}
-	hdata->sclk_hdmiphy = devm_clk_get(dev, "sclk_hdmiphy");
-	if (IS_ERR(hdata->sclk_hdmiphy)) {
-		DRM_ERROR("failed to get clock 'sclk_hdmiphy'\n");
-		ret = PTR_ERR(hdata->sclk_hdmiphy);
-		goto fail;
-	}
-	hdata->mout_hdmi = devm_clk_get(dev, "mout_hdmi");
-	if (IS_ERR(hdata->mout_hdmi)) {
-		DRM_ERROR("failed to get clock 'mout_hdmi'\n");
-		ret = PTR_ERR(hdata->mout_hdmi);
-		goto fail;
-	}
 
-	clk_set_parent(hdata->mout_hdmi, hdata->sclk_pixel);
+	ret = hdmi_clk_init(hdata);
+	if (ret)
+		return ret;
+
+	ret = hdmi_clk_set_parents(hdata, false);
+	if (ret)
+		return ret;
 
 	for (i = 0; i < ARRAY_SIZE(supply); ++i) {
 		hdata->regul_bulk[i].supply = supply[i];
@@ -1728,7 +1683,8 @@ static int hdmi_resources_init(struct hd
 	}
 	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(supply), hdata->regul_bulk);
 	if (ret) {
-		DRM_ERROR("failed to get regulators\n");
+		if (ret != -EPROBE_DEFER)
+			DRM_ERROR("failed to get regulators\n");
 		return ret;
 	}
 
@@ -1745,9 +1701,6 @@ static int hdmi_resources_init(struct hd
 		DRM_ERROR("failed to enable hdmi-en regulator\n");
 
 	return ret;
-fail:
-	DRM_ERROR("HDMI resource init - failed\n");
-	return ret;
 }
 
 static struct of_device_id hdmi_match_types[] = {
@@ -1761,6 +1714,9 @@ static struct of_device_id hdmi_match_ty
 		.compatible = "samsung,exynos5420-hdmi",
 		.data = &exynos5420_hdmi_driver_data,
 	}, {
+		.compatible = "samsung,exynos5433-hdmi",
+		.data = &exynos5433_hdmi_driver_data,
+	}, {
 		/* end node */
 	}
 };
@@ -1780,6 +1736,10 @@ static int hdmi_bind(struct device *dev,
 	if (pipe < 0)
 		return pipe;
 
+	hdata->phy_clk.enable = hdmiphy_clk_enable;
+
+	exynos_drm_crtc_from_pipe(drm_dev, pipe)->pipe_clk = &hdata->phy_clk;
+
 	encoder->possible_crtcs = 1 << pipe;
 
 	DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
@@ -1830,7 +1790,6 @@ static struct device_node *hdmi_legacy_p
 static int hdmi_probe(struct platform_device *pdev)
 {
 	struct device_node *ddc_node, *phy_node;
-	const struct of_device_id *match;
 	struct device *dev = &pdev->dev;
 	struct hdmi_context *hdata;
 	struct resource *res;
@@ -1840,11 +1799,7 @@ static int hdmi_probe(struct platform_de
 	if (!hdata)
 		return -ENOMEM;
 
-	match = of_match_device(hdmi_match_types, dev);
-	if (!match)
-		return -ENODEV;
-
-	hdata->drv_data = match->data;
+	hdata->drv_data = of_device_get_match_data(dev);
 
 	platform_set_drvdata(pdev, hdata);
 
@@ -1852,7 +1807,8 @@ static int hdmi_probe(struct platform_de
 
 	ret = hdmi_resources_init(hdata);
 	if (ret) {
-		DRM_ERROR("hdmi_resources_init failed\n");
+		if (ret != -EPROBE_DEFER)
+			DRM_ERROR("hdmi_resources_init failed\n");
 		return ret;
 	}
 
@@ -1867,7 +1823,6 @@ static int hdmi_probe(struct platform_de
 	if (ddc_node)
 		goto out_get_ddc_adpt;
 
-	/* DDC i2c driver */
 	ddc_node = of_parse_phandle(dev->of_node, "ddc", 0);
 	if (!ddc_node) {
 		DRM_ERROR("Failed to find ddc node in device tree\n");
@@ -1885,7 +1840,6 @@ out_get_ddc_adpt:
 	if (phy_node)
 		goto out_get_phy_port;
 
-	/* hdmiphy i2c driver */
 	phy_node = of_parse_phandle(dev->of_node, "phy", 0);
 	if (!phy_node) {
 		DRM_ERROR("Failed to find hdmiphy node in device tree\n");
@@ -1929,6 +1883,16 @@ out_get_phy_port:
 		goto err_hdmiphy;
 	}
 
+	if (hdata->drv_data->has_sysreg) {
+		hdata->sysreg = syscon_regmap_lookup_by_phandle(dev->of_node,
+				"samsung,sysreg-phandle");
+		if (IS_ERR(hdata->sysreg)) {
+			DRM_ERROR("sysreg regmap lookup failed.\n");
+			ret = -EPROBE_DEFER;
+			goto err_hdmiphy;
+		}
+	}
+
 	pm_runtime_enable(dev);
 
 	ret = component_add(&pdev->dev, &hdmi_component_ops);
@@ -1975,8 +1939,7 @@ static int exynos_hdmi_suspend(struct de
 {
 	struct hdmi_context *hdata = dev_get_drvdata(dev);
 
-	clk_disable_unprepare(hdata->sclk_hdmi);
-	clk_disable_unprepare(hdata->hdmi);
+	hdmi_clk_disable_gates(hdata);
 
 	return 0;
 }
@@ -1986,17 +1949,9 @@ static int exynos_hdmi_resume(struct dev
 	struct hdmi_context *hdata = dev_get_drvdata(dev);
 	int ret;
 
-	ret = clk_prepare_enable(hdata->hdmi);
-	if (ret < 0) {
-		DRM_ERROR("Failed to prepare_enable the hdmi clk [%d]\n", ret);
-		return ret;
-	}
-	ret = clk_prepare_enable(hdata->sclk_hdmi);
-	if (ret < 0) {
-		DRM_ERROR("Failed to prepare_enable the sclk_mixer clk [%d]\n",
-			  ret);
+	ret = hdmi_clk_enable_gates(hdata);
+	if (ret < 0)
 		return ret;
-	}
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_mixer.c linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_mixer.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/exynos/exynos_mixer.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/exynos/exynos_mixer.c	2016-07-24 15:23:50.000000000 -0400
@@ -31,6 +31,7 @@
 #include <linux/clk.h>
 #include <linux/regulator/consumer.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/component.h>
 
 #include <drm/exynos_drm.h>
@@ -103,8 +104,6 @@ struct mixer_context {
 
 	struct mixer_resources	mixer_res;
 	enum mixer_version_id	mxr_ver;
-	wait_queue_head_t	wait_vsync_queue;
-	atomic_t		wait_vsync_event;
 };
 
 struct mixer_drv_data {
@@ -787,12 +786,6 @@ static irqreturn_t mixer_irq_handler(int
 
 			exynos_drm_crtc_finish_update(ctx->crtc, plane);
 		}
-
-		/* set wait vsync event to zero and wake up queue. */
-		if (atomic_read(&ctx->wait_vsync_event)) {
-			atomic_set(&ctx->wait_vsync_event, 0);
-			wake_up(&ctx->wait_vsync_queue);
-		}
 	}
 
 out:
@@ -1027,34 +1020,6 @@ static void mixer_atomic_flush(struct ex
 	mixer_vsync_set_update(mixer_ctx, true);
 }
 
-static void mixer_wait_for_vblank(struct exynos_drm_crtc *crtc)
-{
-	struct mixer_context *mixer_ctx = crtc->ctx;
-	int err;
-
-	if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags))
-		return;
-
-	err = drm_vblank_get(mixer_ctx->drm_dev, mixer_ctx->pipe);
-	if (err < 0) {
-		DRM_DEBUG_KMS("failed to acquire vblank counter\n");
-		return;
-	}
-
-	atomic_set(&mixer_ctx->wait_vsync_event, 1);
-
-	/*
-	 * wait for MIXER to signal VSYNC interrupt or return after
-	 * timeout which is set to 50ms (refresh rate of 20).
-	 */
-	if (!wait_event_timeout(mixer_ctx->wait_vsync_queue,
-				!atomic_read(&mixer_ctx->wait_vsync_event),
-				HZ/20))
-		DRM_DEBUG_KMS("vblank wait timed out.\n");
-
-	drm_vblank_put(mixer_ctx->drm_dev, mixer_ctx->pipe);
-}
-
 static void mixer_enable(struct exynos_drm_crtc *crtc)
 {
 	struct mixer_context *ctx = crtc->ctx;
@@ -1065,6 +1030,8 @@ static void mixer_enable(struct exynos_d
 
 	pm_runtime_get_sync(ctx->dev);
 
+	exynos_drm_pipe_clk_enable(crtc, true);
+
 	mixer_vsync_set_update(ctx, false);
 
 	mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET);
@@ -1094,6 +1061,8 @@ static void mixer_disable(struct exynos_
 	for (i = 0; i < MIXER_WIN_NR; i++)
 		mixer_disable_plane(crtc, &ctx->planes[i]);
 
+	exynos_drm_pipe_clk_enable(crtc, false);
+
 	pm_runtime_put(ctx->dev);
 
 	clear_bit(MXR_BIT_POWERED, &ctx->flags);
@@ -1126,7 +1095,6 @@ static const struct exynos_drm_crtc_ops
 	.disable		= mixer_disable,
 	.enable_vblank		= mixer_enable_vblank,
 	.disable_vblank		= mixer_disable_vblank,
-	.wait_for_vblank	= mixer_wait_for_vblank,
 	.atomic_begin		= mixer_atomic_begin,
 	.update_plane		= mixer_update_plane,
 	.disable_plane		= mixer_disable_plane,
@@ -1155,18 +1123,6 @@ static struct mixer_drv_data exynos4210_
 	.has_sclk = 1,
 };
 
-static const struct platform_device_id mixer_driver_types[] = {
-	{
-		.name		= "s5p-mixer",
-		.driver_data	= (unsigned long)&exynos4210_mxr_drv_data,
-	}, {
-		.name		= "exynos5-mixer",
-		.driver_data	= (unsigned long)&exynos5250_mxr_drv_data,
-	}, {
-		/* end node */
-	}
-};
-
 static struct of_device_id mixer_match_types[] = {
 	{
 		.compatible = "samsung,exynos4210-mixer",
@@ -1243,7 +1199,7 @@ static const struct component_ops mixer_
 static int mixer_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct mixer_drv_data *drv;
+	const struct mixer_drv_data *drv;
 	struct mixer_context *ctx;
 	int ret;
 
@@ -1253,23 +1209,13 @@ static int mixer_probe(struct platform_d
 		return -ENOMEM;
 	}
 
-	if (dev->of_node) {
-		const struct of_device_id *match;
-
-		match = of_match_node(mixer_match_types, dev->of_node);
-		drv = (struct mixer_drv_data *)match->data;
-	} else {
-		drv = (struct mixer_drv_data *)
-			platform_get_device_id(pdev)->driver_data;
-	}
+	drv = of_device_get_match_data(dev);
 
 	ctx->pdev = pdev;
 	ctx->dev = dev;
 	ctx->vp_enabled = drv->is_vp_enabled;
 	ctx->has_sclk = drv->has_sclk;
 	ctx->mxr_ver = drv->version;
-	init_waitqueue_head(&ctx->wait_vsync_queue);
-	atomic_set(&ctx->wait_vsync_event, 0);
 
 	platform_set_drvdata(pdev, ctx);
 
@@ -1355,5 +1301,4 @@ struct platform_driver mixer_driver = {
 	},
 	.probe = mixer_probe,
 	.remove = mixer_remove,
-	.id_table	= mixer_driver_types,
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/exynos/Kconfig linux-libre-4.7-gnu/drivers/gpu/drm/exynos/Kconfig
--- linux-libre-4.6-gnu/drivers/gpu/drm/exynos/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/exynos/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -71,8 +71,9 @@ config DRM_EXYNOS_DSI
 	  This enables support for Exynos MIPI-DSI device.
 
 config DRM_EXYNOS_DP
-	bool "Display Port"
+	bool "EXYNOS specific extensions for Analogix DP driver"
 	depends on DRM_EXYNOS_FIMD || DRM_EXYNOS7_DECON
+	select DRM_ANALOGIX_DP
 	default DRM_EXYNOS
 	select DRM_PANEL
 	help
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/exynos/Makefile linux-libre-4.7-gnu/drivers/gpu/drm/exynos/Makefile
--- linux-libre-4.6-gnu/drivers/gpu/drm/exynos/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/exynos/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -12,7 +12,7 @@ exynosdrm-$(CONFIG_DRM_EXYNOS5433_DECON)
 exynosdrm-$(CONFIG_DRM_EXYNOS7_DECON)	+= exynos7_drm_decon.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_DPI)	+= exynos_drm_dpi.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_DSI)	+= exynos_drm_dsi.o
-exynosdrm-$(CONFIG_DRM_EXYNOS_DP)	+= exynos_dp_core.o exynos_dp_reg.o
+exynosdrm-$(CONFIG_DRM_EXYNOS_DP)	+= exynos_dp.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_MIXER)	+= exynos_mixer.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI)	+= exynos_hdmi.o
 exynosdrm-$(CONFIG_DRM_EXYNOS_VIDI)	+= exynos_drm_vidi.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/exynos/regs-hdmi.h linux-libre-4.7-gnu/drivers/gpu/drm/exynos/regs-hdmi.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/exynos/regs-hdmi.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/exynos/regs-hdmi.h	2016-07-24 15:23:50.000000000 -0400
@@ -586,10 +586,12 @@
 #define HDMI_TG_VACT_ST4_L		HDMI_TG_BASE(0x0070)
 #define HDMI_TG_VACT_ST4_H		HDMI_TG_BASE(0x0074)
 #define HDMI_TG_3D			HDMI_TG_BASE(0x00F0)
+#define HDMI_TG_DECON_EN		HDMI_TG_BASE(0x01e0)
 
 /* HDMI PHY Registers Offsets*/
-#define HDMIPHY_POWER		(0x74 >> 2)
-#define HDMIPHY_MODE_SET_DONE		(0x7c >> 2)
+#define HDMIPHY_POWER			0x74
+#define HDMIPHY_MODE_SET_DONE		0x7c
+#define HDMIPHY5433_MODE_SET_DONE	0x84
 
 /* HDMI PHY Values */
 #define HDMI_PHY_POWER_ON              0x80
@@ -603,4 +605,7 @@
 #define PMU_HDMI_PHY_CONTROL		0x700
 #define PMU_HDMI_PHY_ENABLE_BIT		BIT(0)
 
+#define EXYNOS5433_SYSREG_DISP_HDMI_PHY	0x1008
+#define SYSREG_HDMI_REFCLK_INT_CLK	1
+
 #endif /* SAMSUNG_REGS_HDMI_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c linux-libre-4.7-gnu/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c	2016-07-24 15:23:50.000000000 -0400
@@ -66,13 +66,12 @@ static void fsl_dcu_drm_crtc_mode_set_no
 {
 	struct drm_device *dev = crtc->dev;
 	struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
+	struct drm_connector *con = &fsl_dev->connector.base;
 	struct drm_display_mode *mode = &crtc->state->mode;
-	unsigned int hbp, hfp, hsw, vbp, vfp, vsw, div, index, pol = 0;
-	unsigned long dcuclk;
+	unsigned int hbp, hfp, hsw, vbp, vfp, vsw, index, pol = 0;
 
 	index = drm_crtc_index(crtc);
-	dcuclk = clk_get_rate(fsl_dev->clk);
-	div = dcuclk / mode->clock / 1000;
+	clk_set_rate(fsl_dev->pix_clk, mode->clock * 1000);
 
 	/* Configure timings: */
 	hbp = mode->htotal - mode->hsync_end;
@@ -82,6 +81,10 @@ static void fsl_dcu_drm_crtc_mode_set_no
 	vfp = mode->vsync_start - mode->vdisplay;
 	vsw = mode->vsync_end - mode->vsync_start;
 
+	/* INV_PXCK as default (most display sample data on rising edge) */
+	if (!(con->display_info.bus_flags & DRM_BUS_FLAG_PIXDATA_POSEDGE))
+		pol |= DCU_SYN_POL_INV_PXCK;
+
 	if (mode->flags & DRM_MODE_FLAG_NHSYNC)
 		pol |= DCU_SYN_POL_INV_HS_LOW;
 
@@ -99,7 +102,6 @@ static void fsl_dcu_drm_crtc_mode_set_no
 	regmap_write(fsl_dev->regmap, DCU_DISP_SIZE,
 		     DCU_DISP_SIZE_DELTA_Y(mode->vdisplay) |
 		     DCU_DISP_SIZE_DELTA_X(mode->hdisplay));
-	regmap_write(fsl_dev->regmap, DCU_DIV_RATIO, div);
 	regmap_write(fsl_dev->regmap, DCU_SYN_POL, pol);
 	regmap_write(fsl_dev->regmap, DCU_BGND, DCU_BGND_R(0) |
 		     DCU_BGND_G(0) | DCU_BGND_B(0));
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c linux-libre-4.7-gnu/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c	2016-07-24 15:23:50.000000000 -0400
@@ -23,10 +23,12 @@
 
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_gem_cma_helper.h>
 
 #include "fsl_dcu_drm_crtc.h"
 #include "fsl_dcu_drm_drv.h"
+#include "fsl_tcon.h"
 
 static bool fsl_dcu_drm_is_volatile_reg(struct device *dev, unsigned int reg)
 {
@@ -40,9 +42,10 @@ static const struct regmap_config fsl_dc
 	.reg_bits = 32,
 	.reg_stride = 4,
 	.val_bits = 32,
-	.cache_type = REGCACHE_RBTREE,
+	.cache_type = REGCACHE_FLAT,
 
 	.volatile_reg = fsl_dcu_drm_is_volatile_reg,
+	.max_register = 0x11fc,
 };
 
 static int fsl_dcu_drm_irq_init(struct drm_device *dev)
@@ -62,46 +65,54 @@ static int fsl_dcu_drm_irq_init(struct d
 	return ret;
 }
 
-static int fsl_dcu_load(struct drm_device *drm, unsigned long flags)
+static int fsl_dcu_load(struct drm_device *dev, unsigned long flags)
 {
-	struct device *dev = drm->dev;
-	struct fsl_dcu_drm_device *fsl_dev = drm->dev_private;
+	struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
 	int ret;
 
 	ret = fsl_dcu_drm_modeset_init(fsl_dev);
 	if (ret < 0) {
-		dev_err(dev, "failed to initialize mode setting\n");
+		dev_err(dev->dev, "failed to initialize mode setting\n");
 		return ret;
 	}
 
-	ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
+	ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
 	if (ret < 0) {
-		dev_err(dev, "failed to initialize vblank\n");
+		dev_err(dev->dev, "failed to initialize vblank\n");
 		goto done;
 	}
-	drm->vblank_disable_allowed = true;
 
-	ret = fsl_dcu_drm_irq_init(drm);
+	ret = fsl_dcu_drm_irq_init(dev);
 	if (ret < 0)
 		goto done;
-	drm->irq_enabled = true;
+	dev->irq_enabled = true;
 
-	fsl_dcu_fbdev_init(drm);
+	fsl_dcu_fbdev_init(dev);
 
 	return 0;
 done:
-	if (ret) {
-		drm_mode_config_cleanup(drm);
-		drm_vblank_cleanup(drm);
-		drm_irq_uninstall(drm);
-		drm->dev_private = NULL;
-	}
+	drm_kms_helper_poll_fini(dev);
+
+	if (fsl_dev->fbdev)
+		drm_fbdev_cma_fini(fsl_dev->fbdev);
+
+	drm_mode_config_cleanup(dev);
+	drm_vblank_cleanup(dev);
+	drm_irq_uninstall(dev);
+	dev->dev_private = NULL;
 
 	return ret;
 }
 
 static int fsl_dcu_unload(struct drm_device *dev)
 {
+	struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
+
+	drm_kms_helper_poll_fini(dev);
+
+	if (fsl_dev->fbdev)
+		drm_fbdev_cma_fini(fsl_dev->fbdev);
+
 	drm_mode_config_cleanup(dev);
 	drm_vblank_cleanup(dev);
 	drm_irq_uninstall(dev);
@@ -157,6 +168,13 @@ static void fsl_dcu_drm_disable_vblank(s
 	regmap_write(fsl_dev->regmap, DCU_INT_MASK, value);
 }
 
+static void fsl_dcu_drm_lastclose(struct drm_device *dev)
+{
+	struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
+
+	drm_fbdev_cma_restore_mode(fsl_dev->fbdev);
+}
+
 static const struct file_operations fsl_dcu_drm_fops = {
 	.owner		= THIS_MODULE,
 	.open		= drm_open,
@@ -174,6 +192,7 @@ static const struct file_operations fsl_
 static struct drm_driver fsl_dcu_drm_driver = {
 	.driver_features	= DRIVER_HAVE_IRQ | DRIVER_GEM | DRIVER_MODESET
 				| DRIVER_PRIME | DRIVER_ATOMIC,
+	.lastclose		= fsl_dcu_drm_lastclose,
 	.load			= fsl_dcu_load,
 	.unload			= fsl_dcu_unload,
 	.irq_handler		= fsl_dcu_drm_irq,
@@ -197,9 +216,9 @@ static struct drm_driver fsl_dcu_drm_dri
 	.fops			= &fsl_dcu_drm_fops,
 	.name			= "fsl-dcu-drm",
 	.desc			= "Freescale DCU DRM",
-	.date			= "20150213",
+	.date			= "20160425",
 	.major			= 1,
-	.minor			= 0,
+	.minor			= 1,
 };
 
 #ifdef CONFIG_PM_SLEEP
@@ -283,6 +302,9 @@ static int fsl_dcu_drm_probe(struct plat
 	struct resource *res;
 	void __iomem *base;
 	struct drm_driver *driver = &fsl_dcu_drm_driver;
+	struct clk *pix_clk_in;
+	char pix_clk_name[32];
+	const char *pix_clk_in_name;
 	const struct of_device_id *id;
 	int ret;
 
@@ -290,6 +312,11 @@ static int fsl_dcu_drm_probe(struct plat
 	if (!fsl_dev)
 		return -ENOMEM;
 
+	id = of_match_node(fsl_dcu_of_match, pdev->dev.of_node);
+	if (!id)
+		return -ENODEV;
+	fsl_dev->soc = id->data;
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
 		dev_err(dev, "could not get memory IO resource\n");
@@ -308,39 +335,54 @@ static int fsl_dcu_drm_probe(struct plat
 		return -ENXIO;
 	}
 
+	fsl_dev->regmap = devm_regmap_init_mmio(dev, base,
+			&fsl_dcu_regmap_config);
+	if (IS_ERR(fsl_dev->regmap)) {
+		dev_err(dev, "regmap init failed\n");
+		return PTR_ERR(fsl_dev->regmap);
+	}
+
 	fsl_dev->clk = devm_clk_get(dev, "dcu");
 	if (IS_ERR(fsl_dev->clk)) {
-		ret = PTR_ERR(fsl_dev->clk);
 		dev_err(dev, "failed to get dcu clock\n");
-		return ret;
-	}
-	ret = clk_prepare(fsl_dev->clk);
-	if (ret < 0) {
-		dev_err(dev, "failed to prepare dcu clk\n");
-		return ret;
+		return PTR_ERR(fsl_dev->clk);
 	}
-	ret = clk_enable(fsl_dev->clk);
+	ret = clk_prepare_enable(fsl_dev->clk);
 	if (ret < 0) {
 		dev_err(dev, "failed to enable dcu clk\n");
-		clk_unprepare(fsl_dev->clk);
 		return ret;
 	}
 
-	fsl_dev->regmap = devm_regmap_init_mmio(dev, base,
-			&fsl_dcu_regmap_config);
-	if (IS_ERR(fsl_dev->regmap)) {
-		dev_err(dev, "regmap init failed\n");
-		return PTR_ERR(fsl_dev->regmap);
+	pix_clk_in = devm_clk_get(dev, "pix");
+	if (IS_ERR(pix_clk_in)) {
+		/* legancy binding, use dcu clock as pixel clock input */
+		pix_clk_in = fsl_dev->clk;
 	}
 
-	id = of_match_node(fsl_dcu_of_match, pdev->dev.of_node);
-	if (!id)
-		return -ENODEV;
-	fsl_dev->soc = id->data;
+	pix_clk_in_name = __clk_get_name(pix_clk_in);
+	snprintf(pix_clk_name, sizeof(pix_clk_name), "%s_pix", pix_clk_in_name);
+	fsl_dev->pix_clk = clk_register_divider(dev, pix_clk_name,
+			pix_clk_in_name, 0, base + DCU_DIV_RATIO,
+			0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL);
+	if (IS_ERR(fsl_dev->pix_clk)) {
+		dev_err(dev, "failed to register pix clk\n");
+		ret = PTR_ERR(fsl_dev->pix_clk);
+		goto disable_clk;
+	}
+
+	ret = clk_prepare_enable(fsl_dev->pix_clk);
+	if (ret < 0) {
+		dev_err(dev, "failed to enable pix clk\n");
+		goto unregister_pix_clk;
+	}
+
+	fsl_dev->tcon = fsl_tcon_init(dev);
 
 	drm = drm_dev_alloc(driver, dev);
-	if (!drm)
-		return -ENOMEM;
+	if (!drm) {
+		ret = -ENOMEM;
+		goto disable_pix_clk;
+	}
 
 	fsl_dev->dev = dev;
 	fsl_dev->drm = drm;
@@ -360,6 +402,12 @@ static int fsl_dcu_drm_probe(struct plat
 
 unref:
 	drm_dev_unref(drm);
+disable_pix_clk:
+	clk_disable_unprepare(fsl_dev->pix_clk);
+unregister_pix_clk:
+	clk_unregister(fsl_dev->pix_clk);
+disable_clk:
+	clk_disable_unprepare(fsl_dev->clk);
 	return ret;
 }
 
@@ -367,6 +415,9 @@ static int fsl_dcu_drm_remove(struct pla
 {
 	struct fsl_dcu_drm_device *fsl_dev = platform_get_drvdata(pdev);
 
+	clk_disable_unprepare(fsl_dev->clk);
+	clk_disable_unprepare(fsl_dev->pix_clk);
+	clk_unregister(fsl_dev->pix_clk);
 	drm_put_dev(fsl_dev->drm);
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h linux-libre-4.7-gnu/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h	2016-07-24 15:23:50.000000000 -0400
@@ -47,8 +47,8 @@
 #define DCU_VSYN_PARA_FP(x)		(x)
 
 #define DCU_SYN_POL			0x0024
-#define DCU_SYN_POL_INV_PXCK_FALL	(0 << 6)
-#define DCU_SYN_POL_NEG_REMAIN		(0 << 5)
+#define DCU_SYN_POL_INV_PXCK		BIT(6)
+#define DCU_SYN_POL_NEG			BIT(5)
 #define DCU_SYN_POL_INV_VS_LOW		BIT(1)
 #define DCU_SYN_POL_INV_HS_LOW		BIT(0)
 
@@ -183,6 +183,8 @@ struct fsl_dcu_drm_device {
 	struct regmap *regmap;
 	int irq;
 	struct clk *clk;
+	struct clk *pix_clk;
+	struct fsl_tcon *tcon;
 	/*protects hardware register*/
 	spinlock_t irq_lock;
 	struct drm_device *drm;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c linux-libre-4.7-gnu/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c	2016-07-24 15:23:50.000000000 -0400
@@ -17,6 +17,7 @@
 #include <drm/drm_panel.h>
 
 #include "fsl_dcu_drm_drv.h"
+#include "fsl_tcon.h"
 
 static int
 fsl_dcu_drm_encoder_atomic_check(struct drm_encoder *encoder,
@@ -28,10 +29,20 @@ fsl_dcu_drm_encoder_atomic_check(struct
 
 static void fsl_dcu_drm_encoder_disable(struct drm_encoder *encoder)
 {
+	struct drm_device *dev = encoder->dev;
+	struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
+
+	if (fsl_dev->tcon)
+		fsl_tcon_bypass_disable(fsl_dev->tcon);
 }
 
 static void fsl_dcu_drm_encoder_enable(struct drm_encoder *encoder)
 {
+	struct drm_device *dev = encoder->dev;
+	struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
+
+	if (fsl_dev->tcon)
+		fsl_tcon_bypass_enable(fsl_dev->tcon);
 }
 
 static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
@@ -68,7 +79,10 @@ int fsl_dcu_drm_encoder_create(struct fs
 
 static void fsl_dcu_drm_connector_destroy(struct drm_connector *connector)
 {
+	struct fsl_dcu_drm_connector *fsl_con = to_fsl_dcu_connector(connector);
+
 	drm_connector_unregister(connector);
+	drm_panel_detach(fsl_con->panel);
 	drm_connector_cleanup(connector);
 }
 
@@ -131,7 +145,7 @@ int fsl_dcu_drm_connector_create(struct
 				 struct drm_encoder *encoder)
 {
 	struct drm_connector *connector = &fsl_dev->connector.base;
-	struct drm_mode_config mode_config = fsl_dev->drm->mode_config;
+	struct drm_mode_config *mode_config = &fsl_dev->drm->mode_config;
 	struct device_node *panel_node;
 	int ret;
 
@@ -153,19 +167,23 @@ int fsl_dcu_drm_connector_create(struct
 		goto err_sysfs;
 
 	drm_object_property_set_value(&connector->base,
-				      mode_config.dpms_property,
+				      mode_config->dpms_property,
 				      DRM_MODE_DPMS_OFF);
 
 	panel_node = of_parse_phandle(fsl_dev->np, "fsl,panel", 0);
-	if (panel_node) {
-		fsl_dev->connector.panel = of_drm_find_panel(panel_node);
-		if (!fsl_dev->connector.panel) {
-			ret = -EPROBE_DEFER;
-			goto err_sysfs;
-		}
-	of_node_put(panel_node);
+	if (!panel_node) {
+		dev_err(fsl_dev->dev, "fsl,panel property not found\n");
+		ret = -ENODEV;
+		goto err_sysfs;
 	}
 
+	fsl_dev->connector.panel = of_drm_find_panel(panel_node);
+	if (!fsl_dev->connector.panel) {
+		ret = -EPROBE_DEFER;
+		goto err_panel;
+	}
+	of_node_put(panel_node);
+
 	ret = drm_panel_attach(fsl_dev->connector.panel, connector);
 	if (ret) {
 		dev_err(fsl_dev->dev, "failed to attach panel\n");
@@ -174,6 +192,8 @@ int fsl_dcu_drm_connector_create(struct
 
 	return 0;
 
+err_panel:
+	of_node_put(panel_node);
 err_sysfs:
 	drm_connector_unregister(connector);
 err_cleanup:
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/fsl-dcu/fsl_tcon.c linux-libre-4.7-gnu/drivers/gpu/drm/fsl-dcu/fsl_tcon.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/fsl-dcu/fsl_tcon.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/fsl-dcu/fsl_tcon.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2015 Toradex AG
+ *
+ * Stefan Agner <stefan@agner.ch>
+ *
+ * Freescale TCON device driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include "fsl_tcon.h"
+
+void fsl_tcon_bypass_disable(struct fsl_tcon *tcon)
+{
+	regmap_update_bits(tcon->regs, FSL_TCON_CTRL1,
+			   FSL_TCON_CTRL1_TCON_BYPASS, 0);
+}
+
+void fsl_tcon_bypass_enable(struct fsl_tcon *tcon)
+{
+	regmap_update_bits(tcon->regs, FSL_TCON_CTRL1,
+			   FSL_TCON_CTRL1_TCON_BYPASS,
+			   FSL_TCON_CTRL1_TCON_BYPASS);
+}
+
+static struct regmap_config fsl_tcon_regmap_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+
+	.name = "tcon",
+};
+
+static int fsl_tcon_init_regmap(struct device *dev,
+				struct fsl_tcon *tcon,
+				struct device_node *np)
+{
+	struct resource res;
+	void __iomem *regs;
+
+	if (of_address_to_resource(np, 0, &res))
+		return -EINVAL;
+
+	regs = devm_ioremap_resource(dev, &res);
+	if (IS_ERR(regs))
+		return PTR_ERR(regs);
+
+	tcon->regs = devm_regmap_init_mmio(dev, regs,
+					   &fsl_tcon_regmap_config);
+	if (IS_ERR(tcon->regs))
+		return PTR_ERR(tcon->regs);
+
+	return 0;
+}
+
+struct fsl_tcon *fsl_tcon_init(struct device *dev)
+{
+	struct fsl_tcon *tcon;
+	struct device_node *np;
+	int ret;
+
+	/* TCON node is not mandatory, some devices do not provide TCON */
+	np = of_parse_phandle(dev->of_node, "fsl,tcon", 0);
+	if (!np)
+		return NULL;
+
+	tcon = devm_kzalloc(dev, sizeof(*tcon), GFP_KERNEL);
+	if (!tcon) {
+		ret = -ENOMEM;
+		goto err_node_put;
+	}
+
+	ret = fsl_tcon_init_regmap(dev, tcon, np);
+	if (ret) {
+		dev_err(dev, "Couldn't create the TCON regmap\n");
+		goto err_node_put;
+	}
+
+	tcon->ipg_clk = of_clk_get_by_name(np, "ipg");
+	if (IS_ERR(tcon->ipg_clk)) {
+		dev_err(dev, "Couldn't get the TCON bus clock\n");
+		goto err_node_put;
+	}
+
+	clk_prepare_enable(tcon->ipg_clk);
+
+	dev_info(dev, "Using TCON in bypass mode\n");
+
+	return tcon;
+
+err_node_put:
+	of_node_put(np);
+	return NULL;
+}
+
+void fsl_tcon_free(struct fsl_tcon *tcon)
+{
+	clk_disable_unprepare(tcon->ipg_clk);
+	clk_put(tcon->ipg_clk);
+}
+
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/fsl-dcu/fsl_tcon.h linux-libre-4.7-gnu/drivers/gpu/drm/fsl-dcu/fsl_tcon.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/fsl-dcu/fsl_tcon.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/fsl-dcu/fsl_tcon.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2015 Toradex AG
+ *
+ * Stefan Agner <stefan@agner.ch>
+ *
+ * Freescale TCON device driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __FSL_TCON_H__
+#define __FSL_TCON_H__
+
+#include <linux/bitops.h>
+
+#define FSL_TCON_CTRL1			0x0
+#define FSL_TCON_CTRL1_TCON_BYPASS	BIT(29)
+
+struct fsl_tcon {
+	struct regmap		*regs;
+	struct clk		*ipg_clk;
+};
+
+struct fsl_tcon *fsl_tcon_init(struct device *dev);
+void fsl_tcon_free(struct fsl_tcon *tcon);
+
+void fsl_tcon_bypass_disable(struct fsl_tcon *tcon);
+void fsl_tcon_bypass_enable(struct fsl_tcon *tcon);
+
+#endif /* __FSL_TCON_H__ */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/fsl-dcu/Kconfig linux-libre-4.7-gnu/drivers/gpu/drm/fsl-dcu/Kconfig
--- linux-libre-4.6-gnu/drivers/gpu/drm/fsl-dcu/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/fsl-dcu/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -1,6 +1,6 @@
 config DRM_FSL_DCU
 	tristate "DRM Support for Freescale DCU"
-	depends on DRM && OF && ARM
+	depends on DRM && OF && ARM && COMMON_CLK
 	select BACKLIGHT_CLASS_DEVICE
 	select BACKLIGHT_LCD_SUPPORT
 	select DRM_KMS_HELPER
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/fsl-dcu/Makefile linux-libre-4.7-gnu/drivers/gpu/drm/fsl-dcu/Makefile
--- linux-libre-4.6-gnu/drivers/gpu/drm/fsl-dcu/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/fsl-dcu/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -3,5 +3,6 @@ fsl-dcu-drm-y := fsl_dcu_drm_drv.o \
 		 fsl_dcu_drm_rgb.o \
 		 fsl_dcu_drm_plane.o \
 		 fsl_dcu_drm_crtc.o \
-		 fsl_dcu_drm_fbdev.o
+		 fsl_dcu_drm_fbdev.o \
+		 fsl_tcon.o
 obj-$(CONFIG_DRM_FSL_DCU)	+= fsl-dcu-drm.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/gma500/framebuffer.c linux-libre-4.7-gnu/drivers/gpu/drm/gma500/framebuffer.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/gma500/framebuffer.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/gma500/framebuffer.c	2016-07-24 15:23:50.000000000 -0400
@@ -411,7 +411,7 @@ static int psbfb_create(struct psb_fbdev
 	info = drm_fb_helper_alloc_fbi(&fbdev->psb_fb_helper);
 	if (IS_ERR(info)) {
 		ret = PTR_ERR(info);
-		goto out_err1;
+		goto err_free_range;
 	}
 	info->par = fbdev;
 
@@ -419,7 +419,7 @@ static int psbfb_create(struct psb_fbdev
 
 	ret = psb_framebuffer_init(dev, psbfb, &mode_cmd, backing);
 	if (ret)
-		goto out_unref;
+		goto err_release;
 
 	fb = &psbfb->base;
 	psbfb->fbdev = info;
@@ -464,14 +464,9 @@ static int psbfb_create(struct psb_fbdev
 					psbfb->base.width, psbfb->base.height);
 
 	return 0;
-out_unref:
-	if (backing->stolen)
-		psb_gtt_free_range(dev, backing);
-	else
-		drm_gem_object_unreference_unlocked(&backing->gem);
-
+err_release:
 	drm_fb_helper_release_fbi(&fbdev->psb_fb_helper);
-out_err1:
+err_free_range:
 	psb_gtt_free_range(dev, backing);
 	return ret;
 }
@@ -495,7 +490,7 @@ static struct drm_framebuffer *psb_user_
 	 *	Find the GEM object and thus the gtt range object that is
 	 *	to back this space
 	 */
-	obj = drm_gem_object_lookup(dev, filp, cmd->handles[0]);
+	obj = drm_gem_object_lookup(filp, cmd->handles[0]);
 	if (obj == NULL)
 		return ERR_PTR(-ENOENT);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/gma500/gem.c linux-libre-4.7-gnu/drivers/gpu/drm/gma500/gem.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/gma500/gem.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/gma500/gem.c	2016-07-24 15:23:50.000000000 -0400
@@ -63,7 +63,7 @@ int psb_gem_dumb_map_gtt(struct drm_file
 	struct drm_gem_object *obj;
 
 	/* GEM does all our handle to object mapping */
-	obj = drm_gem_object_lookup(dev, file, handle);
+	obj = drm_gem_object_lookup(file, handle);
 	if (obj == NULL)
 		return -ENOENT;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/gma500/gma_display.c linux-libre-4.7-gnu/drivers/gpu/drm/gma500/gma_display.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/gma500/gma_display.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/gma500/gma_display.c	2016-07-24 15:23:50.000000000 -0400
@@ -372,7 +372,7 @@ int gma_crtc_cursor_set(struct drm_crtc
 		return -EINVAL;
 	}
 
-	obj = drm_gem_object_lookup(dev, file_priv, handle);
+	obj = drm_gem_object_lookup(file_priv, handle);
 	if (!obj) {
 		ret = -ENOENT;
 		goto unlock;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c linux-libre-4.7-gnu/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c	2016-07-24 15:23:50.000000000 -0400
@@ -979,11 +979,7 @@ struct mdfld_dsi_encoder *mdfld_dsi_dpi_
 		return NULL;
 	}
 
-	if (dsi_connector->pipe)
-		dpi_output->panel_on = 0;
-	else
-		dpi_output->panel_on = 0;
-
+	dpi_output->panel_on = 0;
 	dpi_output->dev = dev;
 	if (mdfld_get_panel_type(dev, pipe) != TC35876X)
 		dpi_output->p_funcs = p_funcs;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c linux-libre-4.7-gnu/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c	2016-07-24 15:23:50.000000000 -0400
@@ -72,7 +72,7 @@ static const char *const dsi_errors[] =
 	"RX Prot Violation",
 	"HS Generic Write FIFO Full",
 	"LP Generic Write FIFO Full",
-	"Generic Read Data Avail"
+	"Generic Read Data Avail",
 	"Special Packet Sent",
 	"Tearing Effect",
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/gma500/psb_drv.c linux-libre-4.7-gnu/drivers/gpu/drm/gma500/psb_drv.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/gma500/psb_drv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/gma500/psb_drv.c	2016-07-24 15:23:50.000000000 -0400
@@ -374,7 +374,6 @@ static int psb_driver_load(struct drm_de
 
 	drm_irq_install(dev, dev->pdev->irq);
 
-	dev->vblank_disable_allowed = true;
 	dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
 	dev->driver->get_vblank_counter = psb_get_vblank_counter;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/hisilicon/Kconfig linux-libre-4.7-gnu/drivers/gpu/drm/hisilicon/Kconfig
--- linux-libre-4.6-gnu/drivers/gpu/drm/hisilicon/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/hisilicon/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,5 @@
+#
+# hisilicon drm device configuration.
+# Please keep this list sorted alphabetically
+
+source "drivers/gpu/drm/hisilicon/kirin/Kconfig"
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c linux-libre-4.7-gnu/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,858 @@
+/*
+ * DesignWare MIPI DSI Host Controller v1.02 driver
+ *
+ * Copyright (c) 2016 Linaro Limited.
+ * Copyright (c) 2014-2016 Hisilicon Limited.
+ *
+ * Author:
+ *	Xinliang Liu <z.liuxinliang@hisilicon.com>
+ *	Xinliang Liu <xinliang.liu@linaro.org>
+ *	Xinwei Kong <kong.kongxinwei@hisilicon.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/of_graph.h>
+
+#include <drm/drm_of.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_encoder_slave.h>
+#include <drm/drm_atomic_helper.h>
+
+#include "dw_dsi_reg.h"
+
+#define MAX_TX_ESC_CLK		10
+#define ROUND(x, y)		((x) / (y) + \
+				((x) % (y) * 10 / (y) >= 5 ? 1 : 0))
+#define PHY_REF_CLK_RATE	19200000
+#define PHY_REF_CLK_PERIOD_PS	(1000000000 / (PHY_REF_CLK_RATE / 1000))
+
+#define encoder_to_dsi(encoder) \
+	container_of(encoder, struct dw_dsi, encoder)
+#define host_to_dsi(host) \
+	container_of(host, struct dw_dsi, host)
+
+struct mipi_phy_params {
+	u32 clk_t_lpx;
+	u32 clk_t_hs_prepare;
+	u32 clk_t_hs_zero;
+	u32 clk_t_hs_trial;
+	u32 clk_t_wakeup;
+	u32 data_t_lpx;
+	u32 data_t_hs_prepare;
+	u32 data_t_hs_zero;
+	u32 data_t_hs_trial;
+	u32 data_t_ta_go;
+	u32 data_t_ta_get;
+	u32 data_t_wakeup;
+	u32 hstx_ckg_sel;
+	u32 pll_fbd_div5f;
+	u32 pll_fbd_div1f;
+	u32 pll_fbd_2p;
+	u32 pll_enbwt;
+	u32 pll_fbd_p;
+	u32 pll_fbd_s;
+	u32 pll_pre_div1p;
+	u32 pll_pre_p;
+	u32 pll_vco_750M;
+	u32 pll_lpf_rs;
+	u32 pll_lpf_cs;
+	u32 clklp2hs_time;
+	u32 clkhs2lp_time;
+	u32 lp2hs_time;
+	u32 hs2lp_time;
+	u32 clk_to_data_delay;
+	u32 data_to_clk_delay;
+	u32 lane_byte_clk_kHz;
+	u32 clk_division;
+};
+
+struct dsi_hw_ctx {
+	void __iomem *base;
+	struct clk *pclk;
+};
+
+struct dw_dsi {
+	struct drm_encoder encoder;
+	struct drm_bridge *bridge;
+	struct mipi_dsi_host host;
+	struct drm_display_mode cur_mode;
+	struct dsi_hw_ctx *ctx;
+	struct mipi_phy_params phy;
+
+	u32 lanes;
+	enum mipi_dsi_pixel_format format;
+	unsigned long mode_flags;
+	bool enable;
+};
+
+struct dsi_data {
+	struct dw_dsi dsi;
+	struct dsi_hw_ctx ctx;
+};
+
+struct dsi_phy_range {
+	u32 min_range_kHz;
+	u32 max_range_kHz;
+	u32 pll_vco_750M;
+	u32 hstx_ckg_sel;
+};
+
+static const struct dsi_phy_range dphy_range_info[] = {
+	{   46875,    62500,   1,    7 },
+	{   62500,    93750,   0,    7 },
+	{   93750,   125000,   1,    6 },
+	{  125000,   187500,   0,    6 },
+	{  187500,   250000,   1,    5 },
+	{  250000,   375000,   0,    5 },
+	{  375000,   500000,   1,    4 },
+	{  500000,   750000,   0,    4 },
+	{  750000,  1000000,   1,    0 },
+	{ 1000000,  1500000,   0,    0 }
+};
+
+static u32 dsi_calc_phy_rate(u32 req_kHz, struct mipi_phy_params *phy)
+{
+	u32 ref_clk_ps = PHY_REF_CLK_PERIOD_PS;
+	u32 tmp_kHz = req_kHz;
+	u32 i = 0;
+	u32 q_pll = 1;
+	u32 m_pll = 0;
+	u32 n_pll = 0;
+	u32 r_pll = 1;
+	u32 m_n = 0;
+	u32 m_n_int = 0;
+	u32 f_kHz = 0;
+	u64 temp;
+
+	/*
+	 * Find a rate >= req_kHz.
+	 */
+	do {
+		f_kHz = tmp_kHz;
+
+		for (i = 0; i < ARRAY_SIZE(dphy_range_info); i++)
+			if (f_kHz >= dphy_range_info[i].min_range_kHz &&
+			    f_kHz <= dphy_range_info[i].max_range_kHz)
+				break;
+
+		if (i == ARRAY_SIZE(dphy_range_info)) {
+			DRM_ERROR("%dkHz out of range\n", f_kHz);
+			return 0;
+		}
+
+		phy->pll_vco_750M = dphy_range_info[i].pll_vco_750M;
+		phy->hstx_ckg_sel = dphy_range_info[i].hstx_ckg_sel;
+
+		if (phy->hstx_ckg_sel <= 7 &&
+		    phy->hstx_ckg_sel >= 4)
+			q_pll = 0x10 >> (7 - phy->hstx_ckg_sel);
+
+		temp = f_kHz * (u64)q_pll * (u64)ref_clk_ps;
+		m_n_int = temp / (u64)1000000000;
+		m_n = (temp % (u64)1000000000) / (u64)100000000;
+
+		if (m_n_int % 2 == 0) {
+			if (m_n * 6 >= 50) {
+				n_pll = 2;
+				m_pll = (m_n_int + 1) * n_pll;
+			} else if (m_n * 6 >= 30) {
+				n_pll = 3;
+				m_pll = m_n_int * n_pll + 2;
+			} else {
+				n_pll = 1;
+				m_pll = m_n_int * n_pll;
+			}
+		} else {
+			if (m_n * 6 >= 50) {
+				n_pll = 1;
+				m_pll = (m_n_int + 1) * n_pll;
+			} else if (m_n * 6 >= 30) {
+				n_pll = 1;
+				m_pll = (m_n_int + 1) * n_pll;
+			} else if (m_n * 6 >= 10) {
+				n_pll = 3;
+				m_pll = m_n_int * n_pll + 1;
+			} else {
+				n_pll = 2;
+				m_pll = m_n_int * n_pll;
+			}
+		}
+
+		if (n_pll == 1) {
+			phy->pll_fbd_p = 0;
+			phy->pll_pre_div1p = 1;
+		} else {
+			phy->pll_fbd_p = n_pll;
+			phy->pll_pre_div1p = 0;
+		}
+
+		if (phy->pll_fbd_2p <= 7 && phy->pll_fbd_2p >= 4)
+			r_pll = 0x10 >> (7 - phy->pll_fbd_2p);
+
+		if (m_pll == 2) {
+			phy->pll_pre_p = 0;
+			phy->pll_fbd_s = 0;
+			phy->pll_fbd_div1f = 0;
+			phy->pll_fbd_div5f = 1;
+		} else if (m_pll >= 2 * 2 * r_pll && m_pll <= 2 * 4 * r_pll) {
+			phy->pll_pre_p = m_pll / (2 * r_pll);
+			phy->pll_fbd_s = 0;
+			phy->pll_fbd_div1f = 1;
+			phy->pll_fbd_div5f = 0;
+		} else if (m_pll >= 2 * 5 * r_pll && m_pll <= 2 * 150 * r_pll) {
+			if (((m_pll / (2 * r_pll)) % 2) == 0) {
+				phy->pll_pre_p =
+					(m_pll / (2 * r_pll)) / 2 - 1;
+				phy->pll_fbd_s =
+					(m_pll / (2 * r_pll)) % 2 + 2;
+			} else {
+				phy->pll_pre_p =
+					(m_pll / (2 * r_pll)) / 2;
+				phy->pll_fbd_s =
+					(m_pll / (2 * r_pll)) % 2;
+			}
+			phy->pll_fbd_div1f = 0;
+			phy->pll_fbd_div5f = 0;
+		} else {
+			phy->pll_pre_p = 0;
+			phy->pll_fbd_s = 0;
+			phy->pll_fbd_div1f = 0;
+			phy->pll_fbd_div5f = 1;
+		}
+
+		f_kHz = (u64)1000000000 * (u64)m_pll /
+			((u64)ref_clk_ps * (u64)n_pll * (u64)q_pll);
+
+		if (f_kHz >= req_kHz)
+			break;
+
+		tmp_kHz += 10;
+
+	} while (true);
+
+	return f_kHz;
+}
+
+static void dsi_get_phy_params(u32 phy_req_kHz,
+			       struct mipi_phy_params *phy)
+{
+	u32 ref_clk_ps = PHY_REF_CLK_PERIOD_PS;
+	u32 phy_rate_kHz;
+	u32 ui;
+
+	memset(phy, 0, sizeof(*phy));
+
+	phy_rate_kHz = dsi_calc_phy_rate(phy_req_kHz, phy);
+	if (!phy_rate_kHz)
+		return;
+
+	ui = 1000000 / phy_rate_kHz;
+
+	phy->clk_t_lpx = ROUND(50, 8 * ui);
+	phy->clk_t_hs_prepare = ROUND(133, 16 * ui) - 1;
+
+	phy->clk_t_hs_zero = ROUND(262, 8 * ui);
+	phy->clk_t_hs_trial = 2 * (ROUND(60, 8 * ui) - 1);
+	phy->clk_t_wakeup = ROUND(1000000, (ref_clk_ps / 1000) - 1);
+	if (phy->clk_t_wakeup > 0xff)
+		phy->clk_t_wakeup = 0xff;
+	phy->data_t_wakeup = phy->clk_t_wakeup;
+	phy->data_t_lpx = phy->clk_t_lpx;
+	phy->data_t_hs_prepare = ROUND(125 + 10 * ui, 16 * ui) - 1;
+	phy->data_t_hs_zero = ROUND(105 + 6 * ui, 8 * ui);
+	phy->data_t_hs_trial = 2 * (ROUND(60 + 4 * ui, 8 * ui) - 1);
+	phy->data_t_ta_go = 3;
+	phy->data_t_ta_get = 4;
+
+	phy->pll_enbwt = 1;
+	phy->clklp2hs_time = ROUND(407, 8 * ui) + 12;
+	phy->clkhs2lp_time = ROUND(105 + 12 * ui, 8 * ui);
+	phy->lp2hs_time = ROUND(240 + 12 * ui, 8 * ui) + 1;
+	phy->hs2lp_time = phy->clkhs2lp_time;
+	phy->clk_to_data_delay = 1 + phy->clklp2hs_time;
+	phy->data_to_clk_delay = ROUND(60 + 52 * ui, 8 * ui) +
+				phy->clkhs2lp_time;
+
+	phy->lane_byte_clk_kHz = phy_rate_kHz / 8;
+	phy->clk_division =
+		DIV_ROUND_UP(phy->lane_byte_clk_kHz, MAX_TX_ESC_CLK);
+}
+
+static u32 dsi_get_dpi_color_coding(enum mipi_dsi_pixel_format format)
+{
+	u32 val;
+
+	/*
+	 * TODO: only support RGB888 now, to support more
+	 */
+	switch (format) {
+	case MIPI_DSI_FMT_RGB888:
+		val = DSI_24BITS_1;
+		break;
+	default:
+		val = DSI_24BITS_1;
+		break;
+	}
+
+	return val;
+}
+
+/*
+ * dsi phy reg write function
+ */
+static void dsi_phy_tst_set(void __iomem *base, u32 reg, u32 val)
+{
+	u32 reg_write = 0x10000 + reg;
+
+	/*
+	 * latch reg first
+	 */
+	writel(reg_write, base + PHY_TST_CTRL1);
+	writel(0x02, base + PHY_TST_CTRL0);
+	writel(0x00, base + PHY_TST_CTRL0);
+
+	/*
+	 * then latch value
+	 */
+	writel(val, base + PHY_TST_CTRL1);
+	writel(0x02, base + PHY_TST_CTRL0);
+	writel(0x00, base + PHY_TST_CTRL0);
+}
+
+static void dsi_set_phy_timer(void __iomem *base,
+			      struct mipi_phy_params *phy,
+			      u32 lanes)
+{
+	u32 val;
+
+	/*
+	 * Set lane value and phy stop wait time.
+	 */
+	val = (lanes - 1) | (PHY_STOP_WAIT_TIME << 8);
+	writel(val, base + PHY_IF_CFG);
+
+	/*
+	 * Set phy clk division.
+	 */
+	val = readl(base + CLKMGR_CFG) | phy->clk_division;
+	writel(val, base + CLKMGR_CFG);
+
+	/*
+	 * Set lp and hs switching params.
+	 */
+	dw_update_bits(base + PHY_TMR_CFG, 24, MASK(8), phy->hs2lp_time);
+	dw_update_bits(base + PHY_TMR_CFG, 16, MASK(8), phy->lp2hs_time);
+	dw_update_bits(base + PHY_TMR_LPCLK_CFG, 16, MASK(10),
+		       phy->clkhs2lp_time);
+	dw_update_bits(base + PHY_TMR_LPCLK_CFG, 0, MASK(10),
+		       phy->clklp2hs_time);
+	dw_update_bits(base + CLK_DATA_TMR_CFG, 8, MASK(8),
+		       phy->data_to_clk_delay);
+	dw_update_bits(base + CLK_DATA_TMR_CFG, 0, MASK(8),
+		       phy->clk_to_data_delay);
+}
+
+static void dsi_set_mipi_phy(void __iomem *base,
+			     struct mipi_phy_params *phy,
+			     u32 lanes)
+{
+	u32 delay_count;
+	u32 val;
+	u32 i;
+
+	/* phy timer setting */
+	dsi_set_phy_timer(base, phy, lanes);
+
+	/*
+	 * Reset to clean up phy tst params.
+	 */
+	writel(0, base + PHY_RSTZ);
+	writel(0, base + PHY_TST_CTRL0);
+	writel(1, base + PHY_TST_CTRL0);
+	writel(0, base + PHY_TST_CTRL0);
+
+	/*
+	 * Clock lane timing control setting: TLPX, THS-PREPARE,
+	 * THS-ZERO, THS-TRAIL, TWAKEUP.
+	 */
+	dsi_phy_tst_set(base, CLK_TLPX, phy->clk_t_lpx);
+	dsi_phy_tst_set(base, CLK_THS_PREPARE, phy->clk_t_hs_prepare);
+	dsi_phy_tst_set(base, CLK_THS_ZERO, phy->clk_t_hs_zero);
+	dsi_phy_tst_set(base, CLK_THS_TRAIL, phy->clk_t_hs_trial);
+	dsi_phy_tst_set(base, CLK_TWAKEUP, phy->clk_t_wakeup);
+
+	/*
+	 * Data lane timing control setting: TLPX, THS-PREPARE,
+	 * THS-ZERO, THS-TRAIL, TTA-GO, TTA-GET, TWAKEUP.
+	 */
+	for (i = 0; i < lanes; i++) {
+		dsi_phy_tst_set(base, DATA_TLPX(i), phy->data_t_lpx);
+		dsi_phy_tst_set(base, DATA_THS_PREPARE(i),
+				phy->data_t_hs_prepare);
+		dsi_phy_tst_set(base, DATA_THS_ZERO(i), phy->data_t_hs_zero);
+		dsi_phy_tst_set(base, DATA_THS_TRAIL(i), phy->data_t_hs_trial);
+		dsi_phy_tst_set(base, DATA_TTA_GO(i), phy->data_t_ta_go);
+		dsi_phy_tst_set(base, DATA_TTA_GET(i), phy->data_t_ta_get);
+		dsi_phy_tst_set(base, DATA_TWAKEUP(i), phy->data_t_wakeup);
+	}
+
+	/*
+	 * physical configuration: I, pll I, pll II, pll III,
+	 * pll IV, pll V.
+	 */
+	dsi_phy_tst_set(base, PHY_CFG_I, phy->hstx_ckg_sel);
+	val = (phy->pll_fbd_div5f << 5) + (phy->pll_fbd_div1f << 4) +
+				(phy->pll_fbd_2p << 1) + phy->pll_enbwt;
+	dsi_phy_tst_set(base, PHY_CFG_PLL_I, val);
+	dsi_phy_tst_set(base, PHY_CFG_PLL_II, phy->pll_fbd_p);
+	dsi_phy_tst_set(base, PHY_CFG_PLL_III, phy->pll_fbd_s);
+	val = (phy->pll_pre_div1p << 7) + phy->pll_pre_p;
+	dsi_phy_tst_set(base, PHY_CFG_PLL_IV, val);
+	val = (5 << 5) + (phy->pll_vco_750M << 4) + (phy->pll_lpf_rs << 2) +
+		phy->pll_lpf_cs;
+	dsi_phy_tst_set(base, PHY_CFG_PLL_V, val);
+
+	writel(PHY_ENABLECLK, base + PHY_RSTZ);
+	udelay(1);
+	writel(PHY_ENABLECLK | PHY_UNSHUTDOWNZ, base + PHY_RSTZ);
+	udelay(1);
+	writel(PHY_ENABLECLK | PHY_UNRSTZ | PHY_UNSHUTDOWNZ, base + PHY_RSTZ);
+	usleep_range(1000, 1500);
+
+	/*
+	 * wait for phy's clock ready
+	 */
+	delay_count = 100;
+	while (delay_count) {
+		val = readl(base +  PHY_STATUS);
+		if ((BIT(0) | BIT(2)) & val)
+			break;
+
+		udelay(1);
+		delay_count--;
+	}
+
+	if (!delay_count)
+		DRM_INFO("phylock and phystopstateclklane is not ready.\n");
+}
+
+static void dsi_set_mode_timing(void __iomem *base,
+				u32 lane_byte_clk_kHz,
+				struct drm_display_mode *mode,
+				enum mipi_dsi_pixel_format format)
+{
+	u32 hfp, hbp, hsw, vfp, vbp, vsw;
+	u32 hline_time;
+	u32 hsa_time;
+	u32 hbp_time;
+	u32 pixel_clk_kHz;
+	int htot, vtot;
+	u32 val;
+	u64 tmp;
+
+	val = dsi_get_dpi_color_coding(format);
+	writel(val, base + DPI_COLOR_CODING);
+
+	val = (mode->flags & DRM_MODE_FLAG_NHSYNC ? 1 : 0) << 2;
+	val |= (mode->flags & DRM_MODE_FLAG_NVSYNC ? 1 : 0) << 1;
+	writel(val, base +  DPI_CFG_POL);
+
+	/*
+	 * The DSI IP accepts vertical timing using lines as normal,
+	 * but horizontal timing is a mixture of pixel-clocks for the
+	 * active region and byte-lane clocks for the blanking-related
+	 * timings.  hfp is specified as the total hline_time in byte-
+	 * lane clocks minus hsa, hbp and active.
+	 */
+	pixel_clk_kHz = mode->clock;
+	htot = mode->htotal;
+	vtot = mode->vtotal;
+	hfp = mode->hsync_start - mode->hdisplay;
+	hbp = mode->htotal - mode->hsync_end;
+	hsw = mode->hsync_end - mode->hsync_start;
+	vfp = mode->vsync_start - mode->vdisplay;
+	vbp = mode->vtotal - mode->vsync_end;
+	vsw = mode->vsync_end - mode->vsync_start;
+	if (vsw > 15) {
+		DRM_DEBUG_DRIVER("vsw exceeded 15\n");
+		vsw = 15;
+	}
+
+	hsa_time = (hsw * lane_byte_clk_kHz) / pixel_clk_kHz;
+	hbp_time = (hbp * lane_byte_clk_kHz) / pixel_clk_kHz;
+	tmp = (u64)htot * (u64)lane_byte_clk_kHz;
+	hline_time = DIV_ROUND_UP(tmp, pixel_clk_kHz);
+
+	/* all specified in byte-lane clocks */
+	writel(hsa_time, base + VID_HSA_TIME);
+	writel(hbp_time, base + VID_HBP_TIME);
+	writel(hline_time, base + VID_HLINE_TIME);
+
+	writel(vsw, base + VID_VSA_LINES);
+	writel(vbp, base + VID_VBP_LINES);
+	writel(vfp, base + VID_VFP_LINES);
+	writel(mode->vdisplay, base + VID_VACTIVE_LINES);
+	writel(mode->hdisplay, base + VID_PKT_SIZE);
+
+	DRM_DEBUG_DRIVER("htot=%d, hfp=%d, hbp=%d, hsw=%d\n",
+			 htot, hfp, hbp, hsw);
+	DRM_DEBUG_DRIVER("vtol=%d, vfp=%d, vbp=%d, vsw=%d\n",
+			 vtot, vfp, vbp, vsw);
+	DRM_DEBUG_DRIVER("hsa_time=%d, hbp_time=%d, hline_time=%d\n",
+			 hsa_time, hbp_time, hline_time);
+}
+
+static void dsi_set_video_mode(void __iomem *base, unsigned long flags)
+{
+	u32 val;
+	u32 mode_mask = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
+		MIPI_DSI_MODE_VIDEO_SYNC_PULSE;
+	u32 non_burst_sync_pulse = MIPI_DSI_MODE_VIDEO |
+		MIPI_DSI_MODE_VIDEO_SYNC_PULSE;
+	u32 non_burst_sync_event = MIPI_DSI_MODE_VIDEO;
+
+	/*
+	 * choose video mode type
+	 */
+	if ((flags & mode_mask) == non_burst_sync_pulse)
+		val = DSI_NON_BURST_SYNC_PULSES;
+	else if ((flags & mode_mask) == non_burst_sync_event)
+		val = DSI_NON_BURST_SYNC_EVENTS;
+	else
+		val = DSI_BURST_SYNC_PULSES_1;
+	writel(val, base + VID_MODE_CFG);
+
+	writel(PHY_TXREQUESTCLKHS, base + LPCLK_CTRL);
+	writel(DSI_VIDEO_MODE, base + MODE_CFG);
+}
+
+static void dsi_mipi_init(struct dw_dsi *dsi)
+{
+	struct dsi_hw_ctx *ctx = dsi->ctx;
+	struct mipi_phy_params *phy = &dsi->phy;
+	struct drm_display_mode *mode = &dsi->cur_mode;
+	u32 bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
+	void __iomem *base = ctx->base;
+	u32 dphy_req_kHz;
+
+	/*
+	 * count phy params
+	 */
+	dphy_req_kHz = mode->clock * bpp / dsi->lanes;
+	dsi_get_phy_params(dphy_req_kHz, phy);
+
+	/* reset Core */
+	writel(RESET, base + PWR_UP);
+
+	/* set dsi phy params */
+	dsi_set_mipi_phy(base, phy, dsi->lanes);
+
+	/* set dsi mode timing */
+	dsi_set_mode_timing(base, phy->lane_byte_clk_kHz, mode, dsi->format);
+
+	/* set dsi video mode */
+	dsi_set_video_mode(base, dsi->mode_flags);
+
+	/* dsi wake up */
+	writel(POWERUP, base + PWR_UP);
+
+	DRM_DEBUG_DRIVER("lanes=%d, pixel_clk=%d kHz, bytes_freq=%d kHz\n",
+			 dsi->lanes, mode->clock, phy->lane_byte_clk_kHz);
+}
+
+static void dsi_encoder_disable(struct drm_encoder *encoder)
+{
+	struct dw_dsi *dsi = encoder_to_dsi(encoder);
+	struct dsi_hw_ctx *ctx = dsi->ctx;
+	void __iomem *base = ctx->base;
+
+	if (!dsi->enable)
+		return;
+
+	writel(0, base + PWR_UP);
+	writel(0, base + LPCLK_CTRL);
+	writel(0, base + PHY_RSTZ);
+	clk_disable_unprepare(ctx->pclk);
+
+	dsi->enable = false;
+}
+
+static void dsi_encoder_enable(struct drm_encoder *encoder)
+{
+	struct dw_dsi *dsi = encoder_to_dsi(encoder);
+	struct dsi_hw_ctx *ctx = dsi->ctx;
+	int ret;
+
+	if (dsi->enable)
+		return;
+
+	ret = clk_prepare_enable(ctx->pclk);
+	if (ret) {
+		DRM_ERROR("fail to enable pclk: %d\n", ret);
+		return;
+	}
+
+	dsi_mipi_init(dsi);
+
+	dsi->enable = true;
+}
+
+static void dsi_encoder_mode_set(struct drm_encoder *encoder,
+				 struct drm_display_mode *mode,
+				 struct drm_display_mode *adj_mode)
+{
+	struct dw_dsi *dsi = encoder_to_dsi(encoder);
+
+	drm_mode_copy(&dsi->cur_mode, adj_mode);
+}
+
+static int dsi_encoder_atomic_check(struct drm_encoder *encoder,
+				    struct drm_crtc_state *crtc_state,
+				    struct drm_connector_state *conn_state)
+{
+	/* do nothing */
+	return 0;
+}
+
+static const struct drm_encoder_helper_funcs dw_encoder_helper_funcs = {
+	.atomic_check	= dsi_encoder_atomic_check,
+	.mode_set	= dsi_encoder_mode_set,
+	.enable		= dsi_encoder_enable,
+	.disable	= dsi_encoder_disable
+};
+
+static const struct drm_encoder_funcs dw_encoder_funcs = {
+	.destroy = drm_encoder_cleanup,
+};
+
+static int dw_drm_encoder_init(struct device *dev,
+			       struct drm_device *drm_dev,
+			       struct drm_encoder *encoder)
+{
+	int ret;
+	u32 crtc_mask = drm_of_find_possible_crtcs(drm_dev, dev->of_node);
+
+	if (!crtc_mask) {
+		DRM_ERROR("failed to find crtc mask\n");
+		return -EINVAL;
+	}
+
+	encoder->possible_crtcs = crtc_mask;
+	ret = drm_encoder_init(drm_dev, encoder, &dw_encoder_funcs,
+			       DRM_MODE_ENCODER_DSI, NULL);
+	if (ret) {
+		DRM_ERROR("failed to init dsi encoder\n");
+		return ret;
+	}
+
+	drm_encoder_helper_add(encoder, &dw_encoder_helper_funcs);
+
+	return 0;
+}
+
+static int dsi_host_attach(struct mipi_dsi_host *host,
+			   struct mipi_dsi_device *mdsi)
+{
+	struct dw_dsi *dsi = host_to_dsi(host);
+
+	if (mdsi->lanes < 1 || mdsi->lanes > 4) {
+		DRM_ERROR("dsi device params invalid\n");
+		return -EINVAL;
+	}
+
+	dsi->lanes = mdsi->lanes;
+	dsi->format = mdsi->format;
+	dsi->mode_flags = mdsi->mode_flags;
+
+	return 0;
+}
+
+static int dsi_host_detach(struct mipi_dsi_host *host,
+			   struct mipi_dsi_device *mdsi)
+{
+	/* do nothing */
+	return 0;
+}
+
+static const struct mipi_dsi_host_ops dsi_host_ops = {
+	.attach = dsi_host_attach,
+	.detach = dsi_host_detach,
+};
+
+static int dsi_host_init(struct device *dev, struct dw_dsi *dsi)
+{
+	struct mipi_dsi_host *host = &dsi->host;
+	int ret;
+
+	host->dev = dev;
+	host->ops = &dsi_host_ops;
+	ret = mipi_dsi_host_register(host);
+	if (ret) {
+		DRM_ERROR("failed to register dsi host\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int dsi_bridge_init(struct drm_device *dev, struct dw_dsi *dsi)
+{
+	struct drm_encoder *encoder = &dsi->encoder;
+	struct drm_bridge *bridge = dsi->bridge;
+	int ret;
+
+	/* associate the bridge to dsi encoder */
+	encoder->bridge = bridge;
+	bridge->encoder = encoder;
+
+	ret = drm_bridge_attach(dev, bridge);
+	if (ret) {
+		DRM_ERROR("failed to attach external bridge\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int dsi_bind(struct device *dev, struct device *master, void *data)
+{
+	struct dsi_data *ddata = dev_get_drvdata(dev);
+	struct dw_dsi *dsi = &ddata->dsi;
+	struct drm_device *drm_dev = data;
+	int ret;
+
+	ret = dw_drm_encoder_init(dev, drm_dev, &dsi->encoder);
+	if (ret)
+		return ret;
+
+	ret = dsi_host_init(dev, dsi);
+	if (ret)
+		return ret;
+
+	ret = dsi_bridge_init(drm_dev, dsi);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static void dsi_unbind(struct device *dev, struct device *master, void *data)
+{
+	/* do nothing */
+}
+
+static const struct component_ops dsi_ops = {
+	.bind	= dsi_bind,
+	.unbind	= dsi_unbind,
+};
+
+static int dsi_parse_dt(struct platform_device *pdev, struct dw_dsi *dsi)
+{
+	struct dsi_hw_ctx *ctx = dsi->ctx;
+	struct device_node *np = pdev->dev.of_node;
+	struct device_node *endpoint, *bridge_node;
+	struct drm_bridge *bridge;
+	struct resource *res;
+
+	/*
+	 * Get the endpoint node. In our case, dsi has one output port1
+	 * to which the external HDMI bridge is connected.
+	 */
+	endpoint = of_graph_get_endpoint_by_regs(np, 1, -1);
+	if (!endpoint) {
+		DRM_ERROR("no valid endpoint node\n");
+		return -ENODEV;
+	}
+	of_node_put(endpoint);
+
+	bridge_node = of_graph_get_remote_port_parent(endpoint);
+	if (!bridge_node) {
+		DRM_ERROR("no valid bridge node\n");
+		return -ENODEV;
+	}
+	of_node_put(bridge_node);
+
+	bridge = of_drm_find_bridge(bridge_node);
+	if (!bridge) {
+		DRM_INFO("wait for external HDMI bridge driver.\n");
+		return -EPROBE_DEFER;
+	}
+	dsi->bridge = bridge;
+
+	ctx->pclk = devm_clk_get(&pdev->dev, "pclk");
+	if (IS_ERR(ctx->pclk)) {
+		DRM_ERROR("failed to get pclk clock\n");
+		return PTR_ERR(ctx->pclk);
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	ctx->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(ctx->base)) {
+		DRM_ERROR("failed to remap dsi io region\n");
+		return PTR_ERR(ctx->base);
+	}
+
+	return 0;
+}
+
+static int dsi_probe(struct platform_device *pdev)
+{
+	struct dsi_data *data;
+	struct dw_dsi *dsi;
+	struct dsi_hw_ctx *ctx;
+	int ret;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data) {
+		DRM_ERROR("failed to allocate dsi data.\n");
+		return -ENOMEM;
+	}
+	dsi = &data->dsi;
+	ctx = &data->ctx;
+	dsi->ctx = ctx;
+
+	ret = dsi_parse_dt(pdev, dsi);
+	if (ret)
+		return ret;
+
+	platform_set_drvdata(pdev, data);
+
+	return component_add(&pdev->dev, &dsi_ops);
+}
+
+static int dsi_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &dsi_ops);
+
+	return 0;
+}
+
+static const struct of_device_id dsi_of_match[] = {
+	{.compatible = "hisilicon,hi6220-dsi"},
+	{ }
+};
+MODULE_DEVICE_TABLE(of, dsi_of_match);
+
+static struct platform_driver dsi_driver = {
+	.probe = dsi_probe,
+	.remove = dsi_remove,
+	.driver = {
+		.name = "dw-dsi",
+		.of_match_table = dsi_of_match,
+	},
+};
+
+module_platform_driver(dsi_driver);
+
+MODULE_AUTHOR("Xinliang Liu <xinliang.liu@linaro.org>");
+MODULE_AUTHOR("Xinliang Liu <z.liuxinliang@hisilicon.com>");
+MODULE_AUTHOR("Xinwei Kong <kong.kongxinwei@hisilicon.com>");
+MODULE_DESCRIPTION("DesignWare MIPI DSI Host Controller v1.02 driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/hisilicon/kirin/dw_dsi_reg.h linux-libre-4.7-gnu/drivers/gpu/drm/hisilicon/kirin/dw_dsi_reg.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/hisilicon/kirin/dw_dsi_reg.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/hisilicon/kirin/dw_dsi_reg.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2016 Linaro Limited.
+ * Copyright (c) 2014-2016 Hisilicon Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __DW_DSI_REG_H__
+#define __DW_DSI_REG_H__
+
+#define MASK(x)				(BIT(x) - 1)
+
+/*
+ * regs
+ */
+#define PWR_UP                  0x04  /* Core power-up */
+#define RESET                   0
+#define POWERUP                 BIT(0)
+#define PHY_IF_CFG              0xA4  /* D-PHY interface configuration */
+#define CLKMGR_CFG              0x08  /* the internal clock dividers */
+#define PHY_RSTZ                0xA0  /* D-PHY reset control */
+#define PHY_ENABLECLK           BIT(2)
+#define PHY_UNRSTZ              BIT(1)
+#define PHY_UNSHUTDOWNZ         BIT(0)
+#define PHY_TST_CTRL0           0xB4  /* D-PHY test interface control 0 */
+#define PHY_TST_CTRL1           0xB8  /* D-PHY test interface control 1 */
+#define CLK_TLPX                0x10
+#define CLK_THS_PREPARE         0x11
+#define CLK_THS_ZERO            0x12
+#define CLK_THS_TRAIL           0x13
+#define CLK_TWAKEUP             0x14
+#define DATA_TLPX(x)            (0x20 + ((x) << 4))
+#define DATA_THS_PREPARE(x)     (0x21 + ((x) << 4))
+#define DATA_THS_ZERO(x)        (0x22 + ((x) << 4))
+#define DATA_THS_TRAIL(x)       (0x23 + ((x) << 4))
+#define DATA_TTA_GO(x)          (0x24 + ((x) << 4))
+#define DATA_TTA_GET(x)         (0x25 + ((x) << 4))
+#define DATA_TWAKEUP(x)         (0x26 + ((x) << 4))
+#define PHY_CFG_I               0x60
+#define PHY_CFG_PLL_I           0x63
+#define PHY_CFG_PLL_II          0x64
+#define PHY_CFG_PLL_III         0x65
+#define PHY_CFG_PLL_IV          0x66
+#define PHY_CFG_PLL_V           0x67
+#define DPI_COLOR_CODING        0x10  /* DPI color coding */
+#define DPI_CFG_POL             0x14  /* DPI polarity configuration */
+#define VID_HSA_TIME            0x48  /* Horizontal Sync Active time */
+#define VID_HBP_TIME            0x4C  /* Horizontal Back Porch time */
+#define VID_HLINE_TIME          0x50  /* Line time */
+#define VID_VSA_LINES           0x54  /* Vertical Sync Active period */
+#define VID_VBP_LINES           0x58  /* Vertical Back Porch period */
+#define VID_VFP_LINES           0x5C  /* Vertical Front Porch period */
+#define VID_VACTIVE_LINES       0x60  /* Vertical resolution */
+#define VID_PKT_SIZE            0x3C  /* Video packet size */
+#define VID_MODE_CFG            0x38  /* Video mode configuration */
+#define PHY_TMR_CFG             0x9C  /* Data lanes timing configuration */
+#define BTA_TO_CNT              0x8C  /* Response timeout definition */
+#define PHY_TMR_LPCLK_CFG       0x98  /* clock lane timing configuration */
+#define CLK_DATA_TMR_CFG        0xCC
+#define LPCLK_CTRL              0x94  /* Low-power in clock lane */
+#define PHY_TXREQUESTCLKHS      BIT(0)
+#define MODE_CFG                0x34  /* Video or Command mode selection */
+#define PHY_STATUS              0xB0  /* D-PHY PPI status interface */
+
+#define	PHY_STOP_WAIT_TIME      0x30
+
+/*
+ * regs relevant enum
+ */
+enum dpi_color_coding {
+	DSI_24BITS_1 = 5,
+};
+
+enum dsi_video_mode_type {
+	DSI_NON_BURST_SYNC_PULSES = 0,
+	DSI_NON_BURST_SYNC_EVENTS,
+	DSI_BURST_SYNC_PULSES_1,
+	DSI_BURST_SYNC_PULSES_2
+};
+
+enum dsi_work_mode {
+	DSI_VIDEO_MODE = 0,
+	DSI_COMMAND_MODE
+};
+
+/*
+ * Register Write/Read Helper functions
+ */
+static inline void dw_update_bits(void __iomem *addr, u32 bit_start,
+				  u32 mask, u32 val)
+{
+	u32 tmp, orig;
+
+	orig = readl(addr);
+	tmp = orig & ~(mask << bit_start);
+	tmp |= (val & mask) << bit_start;
+	writel(tmp, addr);
+}
+
+#endif /* __DW_DRM_DSI_H__ */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/hisilicon/kirin/Kconfig linux-libre-4.7-gnu/drivers/gpu/drm/hisilicon/kirin/Kconfig
--- linux-libre-4.6-gnu/drivers/gpu/drm/hisilicon/kirin/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/hisilicon/kirin/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,18 @@
+config DRM_HISI_KIRIN
+	tristate "DRM Support for Hisilicon Kirin series SoCs Platform"
+	depends on DRM && OF && ARM64
+	select DRM_KMS_HELPER
+	select DRM_GEM_CMA_HELPER
+	select DRM_KMS_CMA_HELPER
+	help
+	  Choose this option if you have a hisilicon Kirin chipsets(hi6220).
+	  If M is selected the module will be called kirin-drm.
+
+config HISI_KIRIN_DW_DSI
+	tristate "HiSilicon Kirin specific extensions for Synopsys DW MIPI DSI"
+	depends on DRM_HISI_KIRIN
+	select DRM_MIPI_DSI
+	help
+	 This selects support for HiSilicon Kirin SoC specific extensions for
+	 the Synopsys DesignWare DSI driver. If you want to enable MIPI DSI on
+	 hi6220 based SoC, you should selet this option.
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h linux-libre-4.7-gnu/drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2016 Linaro Limited.
+ * Copyright (c) 2014-2016 Hisilicon Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __KIRIN_ADE_REG_H__
+#define __KIRIN_ADE_REG_H__
+
+/*
+ * ADE Registers
+ */
+#define MASK(x)				(BIT(x) - 1)
+
+#define ADE_CTRL			0x0004
+#define FRM_END_START_OFST		0
+#define FRM_END_START_MASK		MASK(2)
+#define AUTO_CLK_GATE_EN_OFST		0
+#define AUTO_CLK_GATE_EN		BIT(0)
+#define ADE_DISP_SRC_CFG		0x0018
+#define ADE_CTRL1			0x008C
+#define ADE_EN				0x0100
+#define ADE_DISABLE			0
+#define ADE_ENABLE			1
+/* reset and reload regs */
+#define ADE_SOFT_RST_SEL(x)		(0x0078 + (x) * 0x4)
+#define ADE_RELOAD_DIS(x)		(0x00AC + (x) * 0x4)
+#define RDMA_OFST			0
+#define CLIP_OFST			15
+#define SCL_OFST			21
+#define CTRAN_OFST			24
+#define OVLY_OFST			37 /* 32+5 */
+/* channel regs */
+#define RD_CH_CTRL(x)			(0x1004 + (x) * 0x80)
+#define RD_CH_ADDR(x)			(0x1008 + (x) * 0x80)
+#define RD_CH_SIZE(x)			(0x100C + (x) * 0x80)
+#define RD_CH_STRIDE(x)			(0x1010 + (x) * 0x80)
+#define RD_CH_SPACE(x)			(0x1014 + (x) * 0x80)
+#define RD_CH_EN(x)			(0x1020 + (x) * 0x80)
+/* overlay regs */
+#define ADE_OVLY1_TRANS_CFG		0x002C
+#define ADE_OVLY_CTL			0x0098
+#define ADE_OVLY_CH_XY0(x)		(0x2004 + (x) * 4)
+#define ADE_OVLY_CH_XY1(x)		(0x2024 + (x) * 4)
+#define ADE_OVLY_CH_CTL(x)		(0x204C + (x) * 4)
+#define ADE_OVLY_OUTPUT_SIZE(x)		(0x2070 + (x) * 8)
+#define OUTPUT_XSIZE_OFST		16
+#define ADE_OVLYX_CTL(x)		(0x209C + (x) * 4)
+#define CH_OVLY_SEL_OFST(x)		((x) * 4)
+#define CH_OVLY_SEL_MASK		MASK(2)
+#define CH_OVLY_SEL_VAL(x)		((x) + 1)
+#define CH_ALP_MODE_OFST		0
+#define CH_ALP_SEL_OFST			2
+#define CH_UNDER_ALP_SEL_OFST		4
+#define CH_EN_OFST			6
+#define CH_ALP_GBL_OFST			15
+#define CH_SEL_OFST			28
+/* ctran regs */
+#define ADE_CTRAN_DIS(x)		(0x5004 + (x) * 0x100)
+#define CTRAN_BYPASS_ON			1
+#define CTRAN_BYPASS_OFF		0
+#define ADE_CTRAN_IMAGE_SIZE(x)		(0x503C + (x) * 0x100)
+/* clip regs */
+#define ADE_CLIP_DISABLE(x)		(0x6800 + (x) * 0x100)
+#define ADE_CLIP_SIZE0(x)		(0x6804 + (x) * 0x100)
+#define ADE_CLIP_SIZE1(x)		(0x6808 + (x) * 0x100)
+
+/*
+ * LDI Registers
+ */
+#define LDI_HRZ_CTRL0			0x7400
+#define HBP_OFST			20
+#define LDI_HRZ_CTRL1			0x7404
+#define LDI_VRT_CTRL0			0x7408
+#define VBP_OFST			20
+#define LDI_VRT_CTRL1			0x740C
+#define LDI_PLR_CTRL			0x7410
+#define FLAG_NVSYNC			BIT(0)
+#define FLAG_NHSYNC			BIT(1)
+#define FLAG_NPIXCLK			BIT(2)
+#define FLAG_NDE			BIT(3)
+#define LDI_DSP_SIZE			0x7414
+#define VSIZE_OFST			20
+#define LDI_INT_EN			0x741C
+#define FRAME_END_INT_EN_OFST		1
+#define LDI_CTRL			0x7420
+#define BPP_OFST			3
+#define DATA_GATE_EN			BIT(2)
+#define LDI_EN				BIT(0)
+#define LDI_MSK_INT			0x7428
+#define LDI_INT_CLR			0x742C
+#define LDI_WORK_MODE			0x7430
+#define LDI_HDMI_DSI_GT			0x7434
+
+/*
+ * ADE media bus service regs
+ */
+#define ADE0_QOSGENERATOR_MODE		0x010C
+#define QOSGENERATOR_MODE_MASK		MASK(2)
+#define ADE0_QOSGENERATOR_EXTCONTROL	0x0118
+#define SOCKET_QOS_EN			BIT(0)
+#define ADE1_QOSGENERATOR_MODE		0x020C
+#define ADE1_QOSGENERATOR_EXTCONTROL	0x0218
+
+/*
+ * ADE regs relevant enums
+ */
+enum frame_end_start {
+	/* regs take effect in every vsync */
+	REG_EFFECTIVE_IN_VSYNC = 0,
+	/* regs take effect in fist ade en and every frame end */
+	REG_EFFECTIVE_IN_ADEEN_FRMEND,
+	/* regs take effect in ade en immediately */
+	REG_EFFECTIVE_IN_ADEEN,
+	/* regs take effect in first vsync and every frame end */
+	REG_EFFECTIVE_IN_VSYNC_FRMEND
+};
+
+enum ade_fb_format {
+	ADE_RGB_565 = 0,
+	ADE_BGR_565,
+	ADE_XRGB_8888,
+	ADE_XBGR_8888,
+	ADE_ARGB_8888,
+	ADE_ABGR_8888,
+	ADE_RGBA_8888,
+	ADE_BGRA_8888,
+	ADE_RGB_888,
+	ADE_BGR_888 = 9,
+	ADE_FORMAT_UNSUPPORT = 800
+};
+
+enum ade_channel {
+	ADE_CH1 = 0,	/* channel 1 for primary plane */
+	ADE_CH_NUM
+};
+
+enum ade_scale {
+	ADE_SCL1 = 0,
+	ADE_SCL2,
+	ADE_SCL3,
+	ADE_SCL_NUM
+};
+
+enum ade_ctran {
+	ADE_CTRAN1 = 0,
+	ADE_CTRAN2,
+	ADE_CTRAN3,
+	ADE_CTRAN4,
+	ADE_CTRAN5,
+	ADE_CTRAN6,
+	ADE_CTRAN_NUM
+};
+
+enum ade_overlay {
+	ADE_OVLY1 = 0,
+	ADE_OVLY2,
+	ADE_OVLY3,
+	ADE_OVLY_NUM
+};
+
+enum ade_alpha_mode {
+	ADE_ALP_GLOBAL = 0,
+	ADE_ALP_PIXEL,
+	ADE_ALP_PIXEL_AND_GLB
+};
+
+enum ade_alpha_blending_mode {
+	ADE_ALP_MUL_COEFF_0 = 0,	/* alpha */
+	ADE_ALP_MUL_COEFF_1,		/* 1-alpha */
+	ADE_ALP_MUL_COEFF_2,		/* 0 */
+	ADE_ALP_MUL_COEFF_3		/* 1 */
+};
+
+/*
+ * LDI regs relevant enums
+ */
+enum dsi_pclk_en {
+	DSI_PCLK_ON = 0,
+	DSI_PCLK_OFF
+};
+
+enum ldi_output_format {
+	LDI_OUT_RGB_565 = 0,
+	LDI_OUT_RGB_666,
+	LDI_OUT_RGB_888
+};
+
+enum ldi_work_mode {
+	TEST_MODE = 0,
+	NORMAL_MODE
+};
+
+enum ldi_input_source {
+	DISP_SRC_NONE = 0,
+	DISP_SRC_OVLY2,
+	DISP_SRC_DISP,
+	DISP_SRC_ROT,
+	DISP_SRC_SCL2
+};
+
+/*
+ * ADE media bus service relevant enums
+ */
+enum qos_generator_mode {
+	FIXED_MODE = 0,
+	LIMITER_MODE,
+	BYPASS_MODE,
+	REGULATOR_MODE
+};
+
+/*
+ * Register Write/Read Helper functions
+ */
+static inline void ade_update_bits(void __iomem *addr, u32 bit_start,
+				   u32 mask, u32 val)
+{
+	u32 tmp, orig;
+
+	orig = readl(addr);
+	tmp = orig & ~(mask << bit_start);
+	tmp |= (val & mask) << bit_start;
+	writel(tmp, addr);
+}
+
+#endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c linux-libre-4.7-gnu/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,1057 @@
+/*
+ * Hisilicon Hi6220 SoC ADE(Advanced Display Engine)'s crtc&plane driver
+ *
+ * Copyright (c) 2016 Linaro Limited.
+ * Copyright (c) 2014-2016 Hisilicon Limited.
+ *
+ * Author:
+ *	Xinliang Liu <z.liuxinliang@hisilicon.com>
+ *	Xinliang Liu <xinliang.liu@linaro.org>
+ *	Xinwei Kong <kong.kongxinwei@hisilicon.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <video/display_timing.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+
+#include "kirin_drm_drv.h"
+#include "kirin_ade_reg.h"
+
+#define PRIMARY_CH	ADE_CH1 /* primary plane */
+#define OUT_OVLY	ADE_OVLY2 /* output overlay compositor */
+#define ADE_DEBUG	1
+
+#define to_ade_crtc(crtc) \
+	container_of(crtc, struct ade_crtc, base)
+
+#define to_ade_plane(plane) \
+	container_of(plane, struct ade_plane, base)
+
+struct ade_hw_ctx {
+	void __iomem  *base;
+	struct regmap *noc_regmap;
+	struct clk *ade_core_clk;
+	struct clk *media_noc_clk;
+	struct clk *ade_pix_clk;
+	struct reset_control *reset;
+	bool power_on;
+	int irq;
+};
+
+struct ade_crtc {
+	struct drm_crtc base;
+	struct ade_hw_ctx *ctx;
+	bool enable;
+	u32 out_format;
+};
+
+struct ade_plane {
+	struct drm_plane base;
+	void *ctx;
+	u8 ch; /* channel */
+};
+
+struct ade_data {
+	struct ade_crtc acrtc;
+	struct ade_plane aplane[ADE_CH_NUM];
+	struct ade_hw_ctx ctx;
+};
+
+/* ade-format info: */
+struct ade_format {
+	u32 pixel_format;
+	enum ade_fb_format ade_format;
+};
+
+static const struct ade_format ade_formats[] = {
+	/* 16bpp RGB: */
+	{ DRM_FORMAT_RGB565, ADE_RGB_565 },
+	{ DRM_FORMAT_BGR565, ADE_BGR_565 },
+	/* 24bpp RGB: */
+	{ DRM_FORMAT_RGB888, ADE_RGB_888 },
+	{ DRM_FORMAT_BGR888, ADE_BGR_888 },
+	/* 32bpp [A]RGB: */
+	{ DRM_FORMAT_XRGB8888, ADE_XRGB_8888 },
+	{ DRM_FORMAT_XBGR8888, ADE_XBGR_8888 },
+	{ DRM_FORMAT_RGBA8888, ADE_RGBA_8888 },
+	{ DRM_FORMAT_BGRA8888, ADE_BGRA_8888 },
+	{ DRM_FORMAT_ARGB8888, ADE_ARGB_8888 },
+	{ DRM_FORMAT_ABGR8888, ADE_ABGR_8888 },
+};
+
+static const u32 channel_formats1[] = {
+	/* channel 1,2,3,4 */
+	DRM_FORMAT_RGB565, DRM_FORMAT_BGR565, DRM_FORMAT_RGB888,
+	DRM_FORMAT_BGR888, DRM_FORMAT_XRGB8888, DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_RGBA8888, DRM_FORMAT_BGRA8888, DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_ABGR8888
+};
+
+u32 ade_get_channel_formats(u8 ch, const u32 **formats)
+{
+	switch (ch) {
+	case ADE_CH1:
+		*formats = channel_formats1;
+		return ARRAY_SIZE(channel_formats1);
+	default:
+		DRM_ERROR("no this channel %d\n", ch);
+		*formats = NULL;
+		return 0;
+	}
+}
+
+/* convert from fourcc format to ade format */
+static u32 ade_get_format(u32 pixel_format)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ade_formats); i++)
+		if (ade_formats[i].pixel_format == pixel_format)
+			return ade_formats[i].ade_format;
+
+	/* not found */
+	DRM_ERROR("Not found pixel format!!fourcc_format= %d\n",
+		  pixel_format);
+	return ADE_FORMAT_UNSUPPORT;
+}
+
+static void ade_update_reload_bit(void __iomem *base, u32 bit_num, u32 val)
+{
+	u32 bit_ofst, reg_num;
+
+	bit_ofst = bit_num % 32;
+	reg_num = bit_num / 32;
+
+	ade_update_bits(base + ADE_RELOAD_DIS(reg_num), bit_ofst,
+			MASK(1), !!val);
+}
+
+static u32 ade_read_reload_bit(void __iomem *base, u32 bit_num)
+{
+	u32 tmp, bit_ofst, reg_num;
+
+	bit_ofst = bit_num % 32;
+	reg_num = bit_num / 32;
+
+	tmp = readl(base + ADE_RELOAD_DIS(reg_num));
+	return !!(BIT(bit_ofst) & tmp);
+}
+
+static void ade_init(struct ade_hw_ctx *ctx)
+{
+	void __iomem *base = ctx->base;
+
+	/* enable clk gate */
+	ade_update_bits(base + ADE_CTRL1, AUTO_CLK_GATE_EN_OFST,
+			AUTO_CLK_GATE_EN, ADE_ENABLE);
+	/* clear overlay */
+	writel(0, base + ADE_OVLY1_TRANS_CFG);
+	writel(0, base + ADE_OVLY_CTL);
+	writel(0, base + ADE_OVLYX_CTL(OUT_OVLY));
+	/* clear reset and reload regs */
+	writel(MASK(32), base + ADE_SOFT_RST_SEL(0));
+	writel(MASK(32), base + ADE_SOFT_RST_SEL(1));
+	writel(MASK(32), base + ADE_RELOAD_DIS(0));
+	writel(MASK(32), base + ADE_RELOAD_DIS(1));
+	/*
+	 * for video mode, all the ade registers should
+	 * become effective at frame end.
+	 */
+	ade_update_bits(base + ADE_CTRL, FRM_END_START_OFST,
+			FRM_END_START_MASK, REG_EFFECTIVE_IN_ADEEN_FRMEND);
+}
+
+static void ade_set_pix_clk(struct ade_hw_ctx *ctx,
+			    struct drm_display_mode *mode,
+			    struct drm_display_mode *adj_mode)
+{
+	u32 clk_Hz = mode->clock * 1000;
+	int ret;
+
+	/*
+	 * Success should be guaranteed in mode_valid call back,
+	 * so failure shouldn't happen here
+	 */
+	ret = clk_set_rate(ctx->ade_pix_clk, clk_Hz);
+	if (ret)
+		DRM_ERROR("failed to set pixel clk %dHz (%d)\n", clk_Hz, ret);
+	adj_mode->clock = clk_get_rate(ctx->ade_pix_clk) / 1000;
+}
+
+static void ade_ldi_set_mode(struct ade_crtc *acrtc,
+			     struct drm_display_mode *mode,
+			     struct drm_display_mode *adj_mode)
+{
+	struct ade_hw_ctx *ctx = acrtc->ctx;
+	void __iomem *base = ctx->base;
+	u32 width = mode->hdisplay;
+	u32 height = mode->vdisplay;
+	u32 hfp, hbp, hsw, vfp, vbp, vsw;
+	u32 plr_flags;
+
+	plr_flags = (mode->flags & DRM_MODE_FLAG_NVSYNC) ? FLAG_NVSYNC : 0;
+	plr_flags |= (mode->flags & DRM_MODE_FLAG_NHSYNC) ? FLAG_NHSYNC : 0;
+	hfp = mode->hsync_start - mode->hdisplay;
+	hbp = mode->htotal - mode->hsync_end;
+	hsw = mode->hsync_end - mode->hsync_start;
+	vfp = mode->vsync_start - mode->vdisplay;
+	vbp = mode->vtotal - mode->vsync_end;
+	vsw = mode->vsync_end - mode->vsync_start;
+	if (vsw > 15) {
+		DRM_DEBUG_DRIVER("vsw exceeded 15\n");
+		vsw = 15;
+	}
+
+	writel((hbp << HBP_OFST) | hfp, base + LDI_HRZ_CTRL0);
+	 /* the configured value is actual value - 1 */
+	writel(hsw - 1, base + LDI_HRZ_CTRL1);
+	writel((vbp << VBP_OFST) | vfp, base + LDI_VRT_CTRL0);
+	 /* the configured value is actual value - 1 */
+	writel(vsw - 1, base + LDI_VRT_CTRL1);
+	 /* the configured value is actual value - 1 */
+	writel(((height - 1) << VSIZE_OFST) | (width - 1),
+	       base + LDI_DSP_SIZE);
+	writel(plr_flags, base + LDI_PLR_CTRL);
+
+	/* set overlay compositor output size */
+	writel(((width - 1) << OUTPUT_XSIZE_OFST) | (height - 1),
+	       base + ADE_OVLY_OUTPUT_SIZE(OUT_OVLY));
+
+	/* ctran6 setting */
+	writel(CTRAN_BYPASS_ON, base + ADE_CTRAN_DIS(ADE_CTRAN6));
+	 /* the configured value is actual value - 1 */
+	writel(width * height - 1, base + ADE_CTRAN_IMAGE_SIZE(ADE_CTRAN6));
+	ade_update_reload_bit(base, CTRAN_OFST + ADE_CTRAN6, 0);
+
+	ade_set_pix_clk(ctx, mode, adj_mode);
+
+	DRM_DEBUG_DRIVER("set mode: %dx%d\n", width, height);
+}
+
+static int ade_power_up(struct ade_hw_ctx *ctx)
+{
+	int ret;
+
+	ret = clk_prepare_enable(ctx->media_noc_clk);
+	if (ret) {
+		DRM_ERROR("failed to enable media_noc_clk (%d)\n", ret);
+		return ret;
+	}
+
+	ret = reset_control_deassert(ctx->reset);
+	if (ret) {
+		DRM_ERROR("failed to deassert reset\n");
+		return ret;
+	}
+
+	ret = clk_prepare_enable(ctx->ade_core_clk);
+	if (ret) {
+		DRM_ERROR("failed to enable ade_core_clk (%d)\n", ret);
+		return ret;
+	}
+
+	ade_init(ctx);
+	ctx->power_on = true;
+	return 0;
+}
+
+static void ade_power_down(struct ade_hw_ctx *ctx)
+{
+	void __iomem *base = ctx->base;
+
+	writel(ADE_DISABLE, base + LDI_CTRL);
+	/* dsi pixel off */
+	writel(DSI_PCLK_OFF, base + LDI_HDMI_DSI_GT);
+
+	clk_disable_unprepare(ctx->ade_core_clk);
+	reset_control_assert(ctx->reset);
+	clk_disable_unprepare(ctx->media_noc_clk);
+	ctx->power_on = false;
+}
+
+static void ade_set_medianoc_qos(struct ade_crtc *acrtc)
+{
+	struct ade_hw_ctx *ctx = acrtc->ctx;
+	struct regmap *map = ctx->noc_regmap;
+
+	regmap_update_bits(map, ADE0_QOSGENERATOR_MODE,
+			   QOSGENERATOR_MODE_MASK, BYPASS_MODE);
+	regmap_update_bits(map, ADE0_QOSGENERATOR_EXTCONTROL,
+			   SOCKET_QOS_EN, SOCKET_QOS_EN);
+
+	regmap_update_bits(map, ADE1_QOSGENERATOR_MODE,
+			   QOSGENERATOR_MODE_MASK, BYPASS_MODE);
+	regmap_update_bits(map, ADE1_QOSGENERATOR_EXTCONTROL,
+			   SOCKET_QOS_EN, SOCKET_QOS_EN);
+}
+
+static int ade_enable_vblank(struct drm_device *dev, unsigned int pipe)
+{
+	struct kirin_drm_private *priv = dev->dev_private;
+	struct ade_crtc *acrtc = to_ade_crtc(priv->crtc[pipe]);
+	struct ade_hw_ctx *ctx = acrtc->ctx;
+	void __iomem *base = ctx->base;
+
+	if (!ctx->power_on)
+		(void)ade_power_up(ctx);
+
+	ade_update_bits(base + LDI_INT_EN, FRAME_END_INT_EN_OFST,
+			MASK(1), 1);
+
+	return 0;
+}
+
+static void ade_disable_vblank(struct drm_device *dev, unsigned int pipe)
+{
+	struct kirin_drm_private *priv = dev->dev_private;
+	struct ade_crtc *acrtc = to_ade_crtc(priv->crtc[pipe]);
+	struct ade_hw_ctx *ctx = acrtc->ctx;
+	void __iomem *base = ctx->base;
+
+	if (!ctx->power_on) {
+		DRM_ERROR("power is down! vblank disable fail\n");
+		return;
+	}
+
+	ade_update_bits(base + LDI_INT_EN, FRAME_END_INT_EN_OFST,
+			MASK(1), 0);
+}
+
+static irqreturn_t ade_irq_handler(int irq, void *data)
+{
+	struct ade_crtc *acrtc = data;
+	struct ade_hw_ctx *ctx = acrtc->ctx;
+	struct drm_crtc *crtc = &acrtc->base;
+	void __iomem *base = ctx->base;
+	u32 status;
+
+	status = readl(base + LDI_MSK_INT);
+	DRM_DEBUG_VBL("LDI IRQ: status=0x%X\n", status);
+
+	/* vblank irq */
+	if (status & BIT(FRAME_END_INT_EN_OFST)) {
+		ade_update_bits(base + LDI_INT_CLR, FRAME_END_INT_EN_OFST,
+				MASK(1), 1);
+		drm_crtc_handle_vblank(crtc);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static void ade_display_enable(struct ade_crtc *acrtc)
+{
+	struct ade_hw_ctx *ctx = acrtc->ctx;
+	void __iomem *base = ctx->base;
+	u32 out_fmt = acrtc->out_format;
+
+	/* enable output overlay compositor */
+	writel(ADE_ENABLE, base + ADE_OVLYX_CTL(OUT_OVLY));
+	ade_update_reload_bit(base, OVLY_OFST + OUT_OVLY, 0);
+
+	/* display source setting */
+	writel(DISP_SRC_OVLY2, base + ADE_DISP_SRC_CFG);
+
+	/* enable ade */
+	writel(ADE_ENABLE, base + ADE_EN);
+	/* enable ldi */
+	writel(NORMAL_MODE, base + LDI_WORK_MODE);
+	writel((out_fmt << BPP_OFST) | DATA_GATE_EN | LDI_EN,
+	       base + LDI_CTRL);
+	/* dsi pixel on */
+	writel(DSI_PCLK_ON, base + LDI_HDMI_DSI_GT);
+}
+
+#if ADE_DEBUG
+static void ade_rdma_dump_regs(void __iomem *base, u32 ch)
+{
+	u32 reg_ctrl, reg_addr, reg_size, reg_stride, reg_space, reg_en;
+	u32 val;
+
+	reg_ctrl = RD_CH_CTRL(ch);
+	reg_addr = RD_CH_ADDR(ch);
+	reg_size = RD_CH_SIZE(ch);
+	reg_stride = RD_CH_STRIDE(ch);
+	reg_space = RD_CH_SPACE(ch);
+	reg_en = RD_CH_EN(ch);
+
+	val = ade_read_reload_bit(base, RDMA_OFST + ch);
+	DRM_DEBUG_DRIVER("[rdma%d]: reload(%d)\n", ch + 1, val);
+	val = readl(base + reg_ctrl);
+	DRM_DEBUG_DRIVER("[rdma%d]: reg_ctrl(0x%08x)\n", ch + 1, val);
+	val = readl(base + reg_addr);
+	DRM_DEBUG_DRIVER("[rdma%d]: reg_addr(0x%08x)\n", ch + 1, val);
+	val = readl(base + reg_size);
+	DRM_DEBUG_DRIVER("[rdma%d]: reg_size(0x%08x)\n", ch + 1, val);
+	val = readl(base + reg_stride);
+	DRM_DEBUG_DRIVER("[rdma%d]: reg_stride(0x%08x)\n", ch + 1, val);
+	val = readl(base + reg_space);
+	DRM_DEBUG_DRIVER("[rdma%d]: reg_space(0x%08x)\n", ch + 1, val);
+	val = readl(base + reg_en);
+	DRM_DEBUG_DRIVER("[rdma%d]: reg_en(0x%08x)\n", ch + 1, val);
+}
+
+static void ade_clip_dump_regs(void __iomem *base, u32 ch)
+{
+	u32 val;
+
+	val = ade_read_reload_bit(base, CLIP_OFST + ch);
+	DRM_DEBUG_DRIVER("[clip%d]: reload(%d)\n", ch + 1, val);
+	val = readl(base + ADE_CLIP_DISABLE(ch));
+	DRM_DEBUG_DRIVER("[clip%d]: reg_clip_disable(0x%08x)\n", ch + 1, val);
+	val = readl(base + ADE_CLIP_SIZE0(ch));
+	DRM_DEBUG_DRIVER("[clip%d]: reg_clip_size0(0x%08x)\n", ch + 1, val);
+	val = readl(base + ADE_CLIP_SIZE1(ch));
+	DRM_DEBUG_DRIVER("[clip%d]: reg_clip_size1(0x%08x)\n", ch + 1, val);
+}
+
+static void ade_compositor_routing_dump_regs(void __iomem *base, u32 ch)
+{
+	u8 ovly_ch = 0; /* TODO: Only primary plane now */
+	u32 val;
+
+	val = readl(base + ADE_OVLY_CH_XY0(ovly_ch));
+	DRM_DEBUG_DRIVER("[overlay ch%d]: reg_ch_xy0(0x%08x)\n", ovly_ch, val);
+	val = readl(base + ADE_OVLY_CH_XY1(ovly_ch));
+	DRM_DEBUG_DRIVER("[overlay ch%d]: reg_ch_xy1(0x%08x)\n", ovly_ch, val);
+	val = readl(base + ADE_OVLY_CH_CTL(ovly_ch));
+	DRM_DEBUG_DRIVER("[overlay ch%d]: reg_ch_ctl(0x%08x)\n", ovly_ch, val);
+}
+
+static void ade_dump_overlay_compositor_regs(void __iomem *base, u32 comp)
+{
+	u32 val;
+
+	val = ade_read_reload_bit(base, OVLY_OFST + comp);
+	DRM_DEBUG_DRIVER("[overlay%d]: reload(%d)\n", comp + 1, val);
+	writel(ADE_ENABLE, base + ADE_OVLYX_CTL(comp));
+	DRM_DEBUG_DRIVER("[overlay%d]: reg_ctl(0x%08x)\n", comp + 1, val);
+	val = readl(base + ADE_OVLY_CTL);
+	DRM_DEBUG_DRIVER("ovly_ctl(0x%08x)\n", val);
+}
+
+static void ade_dump_regs(void __iomem *base)
+{
+	u32 i;
+
+	/* dump channel regs */
+	for (i = 0; i < ADE_CH_NUM; i++) {
+		/* dump rdma regs */
+		ade_rdma_dump_regs(base, i);
+
+		/* dump clip regs */
+		ade_clip_dump_regs(base, i);
+
+		/* dump compositor routing regs */
+		ade_compositor_routing_dump_regs(base, i);
+	}
+
+	/* dump overlay compositor regs */
+	ade_dump_overlay_compositor_regs(base, OUT_OVLY);
+}
+#else
+static void ade_dump_regs(void __iomem *base) { }
+#endif
+
+static void ade_crtc_enable(struct drm_crtc *crtc)
+{
+	struct ade_crtc *acrtc = to_ade_crtc(crtc);
+	struct ade_hw_ctx *ctx = acrtc->ctx;
+	int ret;
+
+	if (acrtc->enable)
+		return;
+
+	if (!ctx->power_on) {
+		ret = ade_power_up(ctx);
+		if (ret)
+			return;
+	}
+
+	ade_set_medianoc_qos(acrtc);
+	ade_display_enable(acrtc);
+	ade_dump_regs(ctx->base);
+	acrtc->enable = true;
+}
+
+static void ade_crtc_disable(struct drm_crtc *crtc)
+{
+	struct ade_crtc *acrtc = to_ade_crtc(crtc);
+	struct ade_hw_ctx *ctx = acrtc->ctx;
+
+	if (!acrtc->enable)
+		return;
+
+	ade_power_down(ctx);
+	acrtc->enable = false;
+}
+
+static int ade_crtc_atomic_check(struct drm_crtc *crtc,
+				 struct drm_crtc_state *state)
+{
+	/* do nothing */
+	return 0;
+}
+
+static void ade_crtc_mode_set_nofb(struct drm_crtc *crtc)
+{
+	struct ade_crtc *acrtc = to_ade_crtc(crtc);
+	struct ade_hw_ctx *ctx = acrtc->ctx;
+	struct drm_display_mode *mode = &crtc->state->mode;
+	struct drm_display_mode *adj_mode = &crtc->state->adjusted_mode;
+
+	if (!ctx->power_on)
+		(void)ade_power_up(ctx);
+	ade_ldi_set_mode(acrtc, mode, adj_mode);
+}
+
+static void ade_crtc_atomic_begin(struct drm_crtc *crtc,
+				  struct drm_crtc_state *old_state)
+{
+	struct ade_crtc *acrtc = to_ade_crtc(crtc);
+	struct ade_hw_ctx *ctx = acrtc->ctx;
+
+	if (!ctx->power_on)
+		(void)ade_power_up(ctx);
+}
+
+static void ade_crtc_atomic_flush(struct drm_crtc *crtc,
+				  struct drm_crtc_state *old_state)
+
+{
+	struct ade_crtc *acrtc = to_ade_crtc(crtc);
+	struct ade_hw_ctx *ctx = acrtc->ctx;
+	void __iomem *base = ctx->base;
+
+	/* only crtc is enabled regs take effect */
+	if (acrtc->enable) {
+		ade_dump_regs(base);
+		/* flush ade registers */
+		writel(ADE_ENABLE, base + ADE_EN);
+	}
+}
+
+static const struct drm_crtc_helper_funcs ade_crtc_helper_funcs = {
+	.enable		= ade_crtc_enable,
+	.disable	= ade_crtc_disable,
+	.atomic_check	= ade_crtc_atomic_check,
+	.mode_set_nofb	= ade_crtc_mode_set_nofb,
+	.atomic_begin	= ade_crtc_atomic_begin,
+	.atomic_flush	= ade_crtc_atomic_flush,
+};
+
+static const struct drm_crtc_funcs ade_crtc_funcs = {
+	.destroy	= drm_crtc_cleanup,
+	.set_config	= drm_atomic_helper_set_config,
+	.page_flip	= drm_atomic_helper_page_flip,
+	.reset		= drm_atomic_helper_crtc_reset,
+	.set_property = drm_atomic_helper_crtc_set_property,
+	.atomic_duplicate_state	= drm_atomic_helper_crtc_duplicate_state,
+	.atomic_destroy_state	= drm_atomic_helper_crtc_destroy_state,
+};
+
+static int ade_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
+			 struct drm_plane *plane)
+{
+	struct kirin_drm_private *priv = dev->dev_private;
+	struct device_node *port;
+	int ret;
+
+	/* set crtc port so that
+	 * drm_of_find_possible_crtcs call works
+	 */
+	port = of_get_child_by_name(dev->dev->of_node, "port");
+	if (!port) {
+		DRM_ERROR("no port node found in %s\n",
+			  dev->dev->of_node->full_name);
+		return -EINVAL;
+	}
+	of_node_put(port);
+	crtc->port = port;
+
+	ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL,
+					&ade_crtc_funcs, NULL);
+	if (ret) {
+		DRM_ERROR("failed to init crtc.\n");
+		return ret;
+	}
+
+	drm_crtc_helper_add(crtc, &ade_crtc_helper_funcs);
+	priv->crtc[drm_crtc_index(crtc)] = crtc;
+
+	return 0;
+}
+
+static void ade_rdma_set(void __iomem *base, struct drm_framebuffer *fb,
+			 u32 ch, u32 y, u32 in_h, u32 fmt)
+{
+	struct drm_gem_cma_object *obj = drm_fb_cma_get_gem_obj(fb, 0);
+	u32 reg_ctrl, reg_addr, reg_size, reg_stride, reg_space, reg_en;
+	u32 stride = fb->pitches[0];
+	u32 addr = (u32)obj->paddr + y * stride;
+
+	DRM_DEBUG_DRIVER("rdma%d: (y=%d, height=%d), stride=%d, paddr=0x%x\n",
+			 ch + 1, y, in_h, stride, (u32)obj->paddr);
+	DRM_DEBUG_DRIVER("addr=0x%x, fb:%dx%d, pixel_format=%d(%s)\n",
+			 addr, fb->width, fb->height, fmt,
+			 drm_get_format_name(fb->pixel_format));
+
+	/* get reg offset */
+	reg_ctrl = RD_CH_CTRL(ch);
+	reg_addr = RD_CH_ADDR(ch);
+	reg_size = RD_CH_SIZE(ch);
+	reg_stride = RD_CH_STRIDE(ch);
+	reg_space = RD_CH_SPACE(ch);
+	reg_en = RD_CH_EN(ch);
+
+	/*
+	 * TODO: set rotation
+	 */
+	writel((fmt << 16) & 0x1f0000, base + reg_ctrl);
+	writel(addr, base + reg_addr);
+	writel((in_h << 16) | stride, base + reg_size);
+	writel(stride, base + reg_stride);
+	writel(in_h * stride, base + reg_space);
+	writel(ADE_ENABLE, base + reg_en);
+	ade_update_reload_bit(base, RDMA_OFST + ch, 0);
+}
+
+static void ade_rdma_disable(void __iomem *base, u32 ch)
+{
+	u32 reg_en;
+
+	/* get reg offset */
+	reg_en = RD_CH_EN(ch);
+	writel(0, base + reg_en);
+	ade_update_reload_bit(base, RDMA_OFST + ch, 1);
+}
+
+static void ade_clip_set(void __iomem *base, u32 ch, u32 fb_w, u32 x,
+			 u32 in_w, u32 in_h)
+{
+	u32 disable_val;
+	u32 clip_left;
+	u32 clip_right;
+
+	/*
+	 * clip width, no need to clip height
+	 */
+	if (fb_w == in_w) { /* bypass */
+		disable_val = 1;
+		clip_left = 0;
+		clip_right = 0;
+	} else {
+		disable_val = 0;
+		clip_left = x;
+		clip_right = fb_w - (x + in_w) - 1;
+	}
+
+	DRM_DEBUG_DRIVER("clip%d: clip_left=%d, clip_right=%d\n",
+			 ch + 1, clip_left, clip_right);
+
+	writel(disable_val, base + ADE_CLIP_DISABLE(ch));
+	writel((fb_w - 1) << 16 | (in_h - 1), base + ADE_CLIP_SIZE0(ch));
+	writel(clip_left << 16 | clip_right, base + ADE_CLIP_SIZE1(ch));
+	ade_update_reload_bit(base, CLIP_OFST + ch, 0);
+}
+
+static void ade_clip_disable(void __iomem *base, u32 ch)
+{
+	writel(1, base + ADE_CLIP_DISABLE(ch));
+	ade_update_reload_bit(base, CLIP_OFST + ch, 1);
+}
+
+static bool has_Alpha_channel(int format)
+{
+	switch (format) {
+	case ADE_ARGB_8888:
+	case ADE_ABGR_8888:
+	case ADE_RGBA_8888:
+	case ADE_BGRA_8888:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static void ade_get_blending_params(u32 fmt, u8 glb_alpha, u8 *alp_mode,
+				    u8 *alp_sel, u8 *under_alp_sel)
+{
+	bool has_alpha = has_Alpha_channel(fmt);
+
+	/*
+	 * get alp_mode
+	 */
+	if (has_alpha && glb_alpha < 255)
+		*alp_mode = ADE_ALP_PIXEL_AND_GLB;
+	else if (has_alpha)
+		*alp_mode = ADE_ALP_PIXEL;
+	else
+		*alp_mode = ADE_ALP_GLOBAL;
+
+	/*
+	 * get alp sel
+	 */
+	*alp_sel = ADE_ALP_MUL_COEFF_3; /* 1 */
+	*under_alp_sel = ADE_ALP_MUL_COEFF_2; /* 0 */
+}
+
+static void ade_compositor_routing_set(void __iomem *base, u8 ch,
+				       u32 x0, u32 y0,
+				       u32 in_w, u32 in_h, u32 fmt)
+{
+	u8 ovly_ch = 0; /* TODO: This is the zpos, only one plane now */
+	u8 glb_alpha = 255;
+	u32 x1 = x0 + in_w - 1;
+	u32 y1 = y0 + in_h - 1;
+	u32 val;
+	u8 alp_sel;
+	u8 under_alp_sel;
+	u8 alp_mode;
+
+	ade_get_blending_params(fmt, glb_alpha, &alp_mode, &alp_sel,
+				&under_alp_sel);
+
+	/* overlay routing setting
+	 */
+	writel(x0 << 16 | y0, base + ADE_OVLY_CH_XY0(ovly_ch));
+	writel(x1 << 16 | y1, base + ADE_OVLY_CH_XY1(ovly_ch));
+	val = (ch + 1) << CH_SEL_OFST | BIT(CH_EN_OFST) |
+		alp_sel << CH_ALP_SEL_OFST |
+		under_alp_sel << CH_UNDER_ALP_SEL_OFST |
+		glb_alpha << CH_ALP_GBL_OFST |
+		alp_mode << CH_ALP_MODE_OFST;
+	writel(val, base + ADE_OVLY_CH_CTL(ovly_ch));
+	/* connect this plane/channel to overlay2 compositor */
+	ade_update_bits(base + ADE_OVLY_CTL, CH_OVLY_SEL_OFST(ovly_ch),
+			CH_OVLY_SEL_MASK, CH_OVLY_SEL_VAL(OUT_OVLY));
+}
+
+static void ade_compositor_routing_disable(void __iomem *base, u32 ch)
+{
+	u8 ovly_ch = 0; /* TODO: Only primary plane now */
+
+	/* disable this plane/channel */
+	ade_update_bits(base + ADE_OVLY_CH_CTL(ovly_ch), CH_EN_OFST,
+			MASK(1), 0);
+	/* dis-connect this plane/channel of overlay2 compositor */
+	ade_update_bits(base + ADE_OVLY_CTL, CH_OVLY_SEL_OFST(ovly_ch),
+			CH_OVLY_SEL_MASK, 0);
+}
+
+/*
+ * Typicaly, a channel looks like: DMA-->clip-->scale-->ctrans-->compositor
+ */
+static void ade_update_channel(struct ade_plane *aplane,
+			       struct drm_framebuffer *fb, int crtc_x,
+			       int crtc_y, unsigned int crtc_w,
+			       unsigned int crtc_h, u32 src_x,
+			       u32 src_y, u32 src_w, u32 src_h)
+{
+	struct ade_hw_ctx *ctx = aplane->ctx;
+	void __iomem *base = ctx->base;
+	u32 fmt = ade_get_format(fb->pixel_format);
+	u32 ch = aplane->ch;
+	u32 in_w;
+	u32 in_h;
+
+	DRM_DEBUG_DRIVER("channel%d: src:(%d, %d)-%dx%d, crtc:(%d, %d)-%dx%d",
+			 ch + 1, src_x, src_y, src_w, src_h,
+			 crtc_x, crtc_y, crtc_w, crtc_h);
+
+	/* 1) DMA setting */
+	in_w = src_w;
+	in_h = src_h;
+	ade_rdma_set(base, fb, ch, src_y, in_h, fmt);
+
+	/* 2) clip setting */
+	ade_clip_set(base, ch, fb->width, src_x, in_w, in_h);
+
+	/* 3) TODO: scale setting for overlay planes */
+
+	/* 4) TODO: ctran/csc setting for overlay planes */
+
+	/* 5) compositor routing setting */
+	ade_compositor_routing_set(base, ch, crtc_x, crtc_y, in_w, in_h, fmt);
+}
+
+static void ade_disable_channel(struct ade_plane *aplane)
+{
+	struct ade_hw_ctx *ctx = aplane->ctx;
+	void __iomem *base = ctx->base;
+	u32 ch = aplane->ch;
+
+	DRM_DEBUG_DRIVER("disable channel%d\n", ch + 1);
+
+	/* disable read DMA */
+	ade_rdma_disable(base, ch);
+
+	/* disable clip */
+	ade_clip_disable(base, ch);
+
+	/* disable compositor routing */
+	ade_compositor_routing_disable(base, ch);
+}
+
+static int ade_plane_prepare_fb(struct drm_plane *plane,
+				const struct drm_plane_state *new_state)
+{
+	/* do nothing */
+	return 0;
+}
+
+static void ade_plane_cleanup_fb(struct drm_plane *plane,
+				 const struct drm_plane_state *old_state)
+{
+	/* do nothing */
+}
+
+static int ade_plane_atomic_check(struct drm_plane *plane,
+				  struct drm_plane_state *state)
+{
+	struct drm_framebuffer *fb = state->fb;
+	struct drm_crtc *crtc = state->crtc;
+	struct drm_crtc_state *crtc_state;
+	u32 src_x = state->src_x >> 16;
+	u32 src_y = state->src_y >> 16;
+	u32 src_w = state->src_w >> 16;
+	u32 src_h = state->src_h >> 16;
+	int crtc_x = state->crtc_x;
+	int crtc_y = state->crtc_y;
+	u32 crtc_w = state->crtc_w;
+	u32 crtc_h = state->crtc_h;
+	u32 fmt;
+
+	if (!crtc || !fb)
+		return 0;
+
+	fmt = ade_get_format(fb->pixel_format);
+	if (fmt == ADE_FORMAT_UNSUPPORT)
+		return -EINVAL;
+
+	crtc_state = drm_atomic_get_crtc_state(state->state, crtc);
+	if (IS_ERR(crtc_state))
+		return PTR_ERR(crtc_state);
+
+	if (src_w != crtc_w || src_h != crtc_h) {
+		DRM_ERROR("Scale not support!!!\n");
+		return -EINVAL;
+	}
+
+	if (src_x + src_w > fb->width ||
+	    src_y + src_h > fb->height)
+		return -EINVAL;
+
+	if (crtc_x < 0 || crtc_y < 0)
+		return -EINVAL;
+
+	if (crtc_x + crtc_w > crtc_state->adjusted_mode.hdisplay ||
+	    crtc_y + crtc_h > crtc_state->adjusted_mode.vdisplay)
+		return -EINVAL;
+
+	return 0;
+}
+
+static void ade_plane_atomic_update(struct drm_plane *plane,
+				    struct drm_plane_state *old_state)
+{
+	struct drm_plane_state	*state	= plane->state;
+	struct ade_plane *aplane = to_ade_plane(plane);
+
+	ade_update_channel(aplane, state->fb, state->crtc_x, state->crtc_y,
+			   state->crtc_w, state->crtc_h,
+			   state->src_x >> 16, state->src_y >> 16,
+			   state->src_w >> 16, state->src_h >> 16);
+}
+
+static void ade_plane_atomic_disable(struct drm_plane *plane,
+				     struct drm_plane_state *old_state)
+{
+	struct ade_plane *aplane = to_ade_plane(plane);
+
+	ade_disable_channel(aplane);
+}
+
+static const struct drm_plane_helper_funcs ade_plane_helper_funcs = {
+	.prepare_fb = ade_plane_prepare_fb,
+	.cleanup_fb = ade_plane_cleanup_fb,
+	.atomic_check = ade_plane_atomic_check,
+	.atomic_update = ade_plane_atomic_update,
+	.atomic_disable = ade_plane_atomic_disable,
+};
+
+static struct drm_plane_funcs ade_plane_funcs = {
+	.update_plane	= drm_atomic_helper_update_plane,
+	.disable_plane	= drm_atomic_helper_disable_plane,
+	.set_property = drm_atomic_helper_plane_set_property,
+	.destroy = drm_plane_cleanup,
+	.reset = drm_atomic_helper_plane_reset,
+	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+};
+
+static int ade_plane_init(struct drm_device *dev, struct ade_plane *aplane,
+			  enum drm_plane_type type)
+{
+	const u32 *fmts;
+	u32 fmts_cnt;
+	int ret = 0;
+
+	/* get  properties */
+	fmts_cnt = ade_get_channel_formats(aplane->ch, &fmts);
+	if (ret)
+		return ret;
+
+	ret = drm_universal_plane_init(dev, &aplane->base, 1, &ade_plane_funcs,
+				       fmts, fmts_cnt, type, NULL);
+	if (ret) {
+		DRM_ERROR("fail to init plane, ch=%d\n", aplane->ch);
+		return ret;
+	}
+
+	drm_plane_helper_add(&aplane->base, &ade_plane_helper_funcs);
+
+	return 0;
+}
+
+static int ade_dts_parse(struct platform_device *pdev, struct ade_hw_ctx *ctx)
+{
+	struct resource *res;
+	struct device *dev = &pdev->dev;
+	struct device_node *np = pdev->dev.of_node;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	ctx->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(ctx->base)) {
+		DRM_ERROR("failed to remap ade io base\n");
+		return  PTR_ERR(ctx->base);
+	}
+
+	ctx->reset = devm_reset_control_get(dev, NULL);
+	if (IS_ERR(ctx->reset))
+		return PTR_ERR(ctx->reset);
+
+	ctx->noc_regmap =
+		syscon_regmap_lookup_by_phandle(np, "hisilicon,noc-syscon");
+	if (IS_ERR(ctx->noc_regmap)) {
+		DRM_ERROR("failed to get noc regmap\n");
+		return PTR_ERR(ctx->noc_regmap);
+	}
+
+	ctx->irq = platform_get_irq(pdev, 0);
+	if (ctx->irq < 0) {
+		DRM_ERROR("failed to get irq\n");
+		return -ENODEV;
+	}
+
+	ctx->ade_core_clk = devm_clk_get(dev, "clk_ade_core");
+	if (!ctx->ade_core_clk) {
+		DRM_ERROR("failed to parse clk ADE_CORE\n");
+		return -ENODEV;
+	}
+
+	ctx->media_noc_clk = devm_clk_get(dev, "clk_codec_jpeg");
+	if (!ctx->media_noc_clk) {
+		DRM_ERROR("failed to parse clk CODEC_JPEG\n");
+	    return -ENODEV;
+	}
+
+	ctx->ade_pix_clk = devm_clk_get(dev, "clk_ade_pix");
+	if (!ctx->ade_pix_clk) {
+		DRM_ERROR("failed to parse clk ADE_PIX\n");
+	    return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int ade_drm_init(struct drm_device *dev)
+{
+	struct platform_device *pdev = dev->platformdev;
+	struct ade_data *ade;
+	struct ade_hw_ctx *ctx;
+	struct ade_crtc *acrtc;
+	struct ade_plane *aplane;
+	enum drm_plane_type type;
+	int ret;
+	int i;
+
+	ade = devm_kzalloc(dev->dev, sizeof(*ade), GFP_KERNEL);
+	if (!ade) {
+		DRM_ERROR("failed to alloc ade_data\n");
+		return -ENOMEM;
+	}
+	platform_set_drvdata(pdev, ade);
+
+	ctx = &ade->ctx;
+	acrtc = &ade->acrtc;
+	acrtc->ctx = ctx;
+	acrtc->out_format = LDI_OUT_RGB_888;
+
+	ret = ade_dts_parse(pdev, ctx);
+	if (ret)
+		return ret;
+
+	/*
+	 * plane init
+	 * TODO: Now only support primary plane, overlay planes
+	 * need to do.
+	 */
+	for (i = 0; i < ADE_CH_NUM; i++) {
+		aplane = &ade->aplane[i];
+		aplane->ch = i;
+		aplane->ctx = ctx;
+		type = i == PRIMARY_CH ? DRM_PLANE_TYPE_PRIMARY :
+			DRM_PLANE_TYPE_OVERLAY;
+
+		ret = ade_plane_init(dev, aplane, type);
+		if (ret)
+			return ret;
+	}
+
+	/* crtc init */
+	ret = ade_crtc_init(dev, &acrtc->base, &ade->aplane[PRIMARY_CH].base);
+	if (ret)
+		return ret;
+
+	/* vblank irq init */
+	ret = devm_request_irq(dev->dev, ctx->irq, ade_irq_handler,
+			       IRQF_SHARED, dev->driver->name, acrtc);
+	if (ret)
+		return ret;
+	dev->driver->get_vblank_counter = drm_vblank_no_hw_counter;
+	dev->driver->enable_vblank = ade_enable_vblank;
+	dev->driver->disable_vblank = ade_disable_vblank;
+
+	return 0;
+}
+
+static void ade_drm_cleanup(struct drm_device *dev)
+{
+	struct platform_device *pdev = dev->platformdev;
+	struct ade_data *ade = platform_get_drvdata(pdev);
+	struct drm_crtc *crtc = &ade->acrtc.base;
+
+	drm_crtc_cleanup(crtc);
+}
+
+const struct kirin_dc_ops ade_dc_ops = {
+	.init = ade_drm_init,
+	.cleanup = ade_drm_cleanup
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c linux-libre-4.7-gnu/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,343 @@
+/*
+ * Hisilicon Kirin SoCs drm master driver
+ *
+ * Copyright (c) 2016 Linaro Limited.
+ * Copyright (c) 2014-2016 Hisilicon Limited.
+ *
+ * Author:
+ *	Xinliang Liu <z.liuxinliang@hisilicon.com>
+ *	Xinliang Liu <xinliang.liu@linaro.org>
+ *	Xinwei Kong <kong.kongxinwei@hisilicon.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/of_platform.h>
+#include <linux/component.h>
+#include <linux/of_graph.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+
+#include "kirin_drm_drv.h"
+
+static struct kirin_dc_ops *dc_ops;
+
+static int kirin_drm_kms_cleanup(struct drm_device *dev)
+{
+	struct kirin_drm_private *priv = dev->dev_private;
+
+#ifdef CONFIG_DRM_FBDEV_EMULATION
+	if (priv->fbdev) {
+		drm_fbdev_cma_fini(priv->fbdev);
+		priv->fbdev = NULL;
+	}
+#endif
+	drm_kms_helper_poll_fini(dev);
+	drm_vblank_cleanup(dev);
+	dc_ops->cleanup(dev);
+	drm_mode_config_cleanup(dev);
+	devm_kfree(dev->dev, priv);
+	dev->dev_private = NULL;
+
+	return 0;
+}
+
+#ifdef CONFIG_DRM_FBDEV_EMULATION
+static void kirin_fbdev_output_poll_changed(struct drm_device *dev)
+{
+	struct kirin_drm_private *priv = dev->dev_private;
+
+	if (priv->fbdev) {
+		drm_fbdev_cma_hotplug_event(priv->fbdev);
+	} else {
+		priv->fbdev = drm_fbdev_cma_init(dev, 32,
+				dev->mode_config.num_crtc,
+				dev->mode_config.num_connector);
+		if (IS_ERR(priv->fbdev))
+			priv->fbdev = NULL;
+	}
+}
+#endif
+
+static const struct drm_mode_config_funcs kirin_drm_mode_config_funcs = {
+	.fb_create = drm_fb_cma_create,
+#ifdef CONFIG_DRM_FBDEV_EMULATION
+	.output_poll_changed = kirin_fbdev_output_poll_changed,
+#endif
+	.atomic_check = drm_atomic_helper_check,
+	.atomic_commit = drm_atomic_helper_commit,
+};
+
+static void kirin_drm_mode_config_init(struct drm_device *dev)
+{
+	dev->mode_config.min_width = 0;
+	dev->mode_config.min_height = 0;
+
+	dev->mode_config.max_width = 2048;
+	dev->mode_config.max_height = 2048;
+
+	dev->mode_config.funcs = &kirin_drm_mode_config_funcs;
+}
+
+static int kirin_drm_kms_init(struct drm_device *dev)
+{
+	struct kirin_drm_private *priv;
+	int ret;
+
+	priv = devm_kzalloc(dev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	dev->dev_private = priv;
+	dev_set_drvdata(dev->dev, dev);
+
+	/* dev->mode_config initialization */
+	drm_mode_config_init(dev);
+	kirin_drm_mode_config_init(dev);
+
+	/* display controller init */
+	ret = dc_ops->init(dev);
+	if (ret)
+		goto err_mode_config_cleanup;
+
+	/* bind and init sub drivers */
+	ret = component_bind_all(dev->dev, dev);
+	if (ret) {
+		DRM_ERROR("failed to bind all component.\n");
+		goto err_dc_cleanup;
+	}
+
+	/* vblank init */
+	ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
+	if (ret) {
+		DRM_ERROR("failed to initialize vblank.\n");
+		goto err_unbind_all;
+	}
+	/* with irq_enabled = true, we can use the vblank feature. */
+	dev->irq_enabled = true;
+
+	/* reset all the states of crtc/plane/encoder/connector */
+	drm_mode_config_reset(dev);
+
+	/* init kms poll for handling hpd */
+	drm_kms_helper_poll_init(dev);
+
+	/* force detection after connectors init */
+	(void)drm_helper_hpd_irq_event(dev);
+
+	return 0;
+
+err_unbind_all:
+	component_unbind_all(dev->dev, dev);
+err_dc_cleanup:
+	dc_ops->cleanup(dev);
+err_mode_config_cleanup:
+	drm_mode_config_cleanup(dev);
+	devm_kfree(dev->dev, priv);
+	dev->dev_private = NULL;
+
+	return ret;
+}
+
+static const struct file_operations kirin_drm_fops = {
+	.owner		= THIS_MODULE,
+	.open		= drm_open,
+	.release	= drm_release,
+	.unlocked_ioctl	= drm_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= drm_compat_ioctl,
+#endif
+	.poll		= drm_poll,
+	.read		= drm_read,
+	.llseek		= no_llseek,
+	.mmap		= drm_gem_cma_mmap,
+};
+
+static int kirin_gem_cma_dumb_create(struct drm_file *file,
+				     struct drm_device *dev,
+				     struct drm_mode_create_dumb *args)
+{
+	return drm_gem_cma_dumb_create_internal(file, dev, args);
+}
+
+static struct drm_driver kirin_drm_driver = {
+	.driver_features	= DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME |
+				  DRIVER_ATOMIC | DRIVER_HAVE_IRQ,
+	.fops			= &kirin_drm_fops,
+	.set_busid		= drm_platform_set_busid,
+
+	.gem_free_object	= drm_gem_cma_free_object,
+	.gem_vm_ops		= &drm_gem_cma_vm_ops,
+	.dumb_create		= kirin_gem_cma_dumb_create,
+	.dumb_map_offset	= drm_gem_cma_dumb_map_offset,
+	.dumb_destroy		= drm_gem_dumb_destroy,
+
+	.prime_handle_to_fd	= drm_gem_prime_handle_to_fd,
+	.prime_fd_to_handle	= drm_gem_prime_fd_to_handle,
+	.gem_prime_export	= drm_gem_prime_export,
+	.gem_prime_import	= drm_gem_prime_import,
+	.gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
+	.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
+	.gem_prime_vmap		= drm_gem_cma_prime_vmap,
+	.gem_prime_vunmap	= drm_gem_cma_prime_vunmap,
+	.gem_prime_mmap		= drm_gem_cma_prime_mmap,
+
+	.name			= "kirin",
+	.desc			= "Hisilicon Kirin SoCs' DRM Driver",
+	.date			= "20150718",
+	.major			= 1,
+	.minor			= 0,
+};
+
+static int compare_of(struct device *dev, void *data)
+{
+	return dev->of_node == data;
+}
+
+static int kirin_drm_bind(struct device *dev)
+{
+	struct drm_driver *driver = &kirin_drm_driver;
+	struct drm_device *drm_dev;
+	int ret;
+
+	drm_dev = drm_dev_alloc(driver, dev);
+	if (!drm_dev)
+		return -ENOMEM;
+
+	drm_dev->platformdev = to_platform_device(dev);
+
+	ret = kirin_drm_kms_init(drm_dev);
+	if (ret)
+		goto err_drm_dev_unref;
+
+	ret = drm_dev_register(drm_dev, 0);
+	if (ret)
+		goto err_kms_cleanup;
+
+	/* connectors should be registered after drm device register */
+	ret = drm_connector_register_all(drm_dev);
+	if (ret)
+		goto err_drm_dev_unregister;
+
+	DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
+		 driver->name, driver->major, driver->minor, driver->patchlevel,
+		 driver->date, drm_dev->primary->index);
+
+	return 0;
+
+err_drm_dev_unregister:
+	drm_dev_unregister(drm_dev);
+err_kms_cleanup:
+	kirin_drm_kms_cleanup(drm_dev);
+err_drm_dev_unref:
+	drm_dev_unref(drm_dev);
+
+	return ret;
+}
+
+static void kirin_drm_unbind(struct device *dev)
+{
+	struct drm_device *drm_dev = dev_get_drvdata(dev);
+
+	drm_connector_unregister_all(drm_dev);
+	drm_dev_unregister(drm_dev);
+	kirin_drm_kms_cleanup(drm_dev);
+	drm_dev_unref(drm_dev);
+}
+
+static const struct component_master_ops kirin_drm_ops = {
+	.bind = kirin_drm_bind,
+	.unbind = kirin_drm_unbind,
+};
+
+static struct device_node *kirin_get_remote_node(struct device_node *np)
+{
+	struct device_node *endpoint, *remote;
+
+	/* get the first endpoint, in our case only one remote node
+	 * is connected to display controller.
+	 */
+	endpoint = of_graph_get_next_endpoint(np, NULL);
+	if (!endpoint) {
+		DRM_ERROR("no valid endpoint node\n");
+		return ERR_PTR(-ENODEV);
+	}
+	of_node_put(endpoint);
+
+	remote = of_graph_get_remote_port_parent(endpoint);
+	if (!remote) {
+		DRM_ERROR("no valid remote node\n");
+		return ERR_PTR(-ENODEV);
+	}
+	of_node_put(remote);
+
+	if (!of_device_is_available(remote)) {
+		DRM_ERROR("not available for remote node\n");
+		return ERR_PTR(-ENODEV);
+	}
+
+	return remote;
+}
+
+static int kirin_drm_platform_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct component_match *match = NULL;
+	struct device_node *remote;
+
+	dc_ops = (struct kirin_dc_ops *)of_device_get_match_data(dev);
+	if (!dc_ops) {
+		DRM_ERROR("failed to get dt id data\n");
+		return -EINVAL;
+	}
+
+	remote = kirin_get_remote_node(np);
+	if (IS_ERR(remote))
+		return PTR_ERR(remote);
+
+	component_match_add(dev, &match, compare_of, remote);
+
+	return component_master_add_with_match(dev, &kirin_drm_ops, match);
+
+	return 0;
+}
+
+static int kirin_drm_platform_remove(struct platform_device *pdev)
+{
+	component_master_del(&pdev->dev, &kirin_drm_ops);
+	dc_ops = NULL;
+	return 0;
+}
+
+static const struct of_device_id kirin_drm_dt_ids[] = {
+	{ .compatible = "hisilicon,hi6220-ade",
+	  .data = &ade_dc_ops,
+	},
+	{ /* end node */ },
+};
+MODULE_DEVICE_TABLE(of, kirin_drm_dt_ids);
+
+static struct platform_driver kirin_drm_platform_driver = {
+	.probe = kirin_drm_platform_probe,
+	.remove = kirin_drm_platform_remove,
+	.driver = {
+		.name = "kirin-drm",
+		.of_match_table = kirin_drm_dt_ids,
+	},
+};
+
+module_platform_driver(kirin_drm_platform_driver);
+
+MODULE_AUTHOR("Xinliang Liu <xinliang.liu@linaro.org>");
+MODULE_AUTHOR("Xinliang Liu <z.liuxinliang@hisilicon.com>");
+MODULE_AUTHOR("Xinwei Kong <kong.kongxinwei@hisilicon.com>");
+MODULE_DESCRIPTION("hisilicon Kirin SoCs' DRM master driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.h linux-libre-4.7-gnu/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2016 Linaro Limited.
+ * Copyright (c) 2014-2016 Hisilicon Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __KIRIN_DRM_DRV_H__
+#define __KIRIN_DRM_DRV_H__
+
+#define MAX_CRTC	2
+
+/* display controller init/cleanup ops */
+struct kirin_dc_ops {
+	int (*init)(struct drm_device *dev);
+	void (*cleanup)(struct drm_device *dev);
+};
+
+struct kirin_drm_private {
+	struct drm_crtc *crtc[MAX_CRTC];
+#ifdef CONFIG_DRM_FBDEV_EMULATION
+	struct drm_fbdev_cma *fbdev;
+#endif
+};
+
+extern const struct kirin_dc_ops ade_dc_ops;
+
+#endif /* __KIRIN_DRM_DRV_H__ */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/hisilicon/kirin/Makefile linux-libre-4.7-gnu/drivers/gpu/drm/hisilicon/kirin/Makefile
--- linux-libre-4.6-gnu/drivers/gpu/drm/hisilicon/kirin/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/hisilicon/kirin/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,6 @@
+kirin-drm-y := kirin_drm_drv.o \
+	       kirin_drm_ade.o
+
+obj-$(CONFIG_DRM_HISI_KIRIN) += kirin-drm.o
+
+obj-$(CONFIG_HISI_KIRIN_DW_DSI) += dw_drm_dsi.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/hisilicon/Makefile linux-libre-4.7-gnu/drivers/gpu/drm/hisilicon/Makefile
--- linux-libre-4.6-gnu/drivers/gpu/drm/hisilicon/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/hisilicon/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,5 @@
+#
+# Makefile for hisilicon drm drivers.
+# Please keep this list sorted alphabetically
+
+obj-$(CONFIG_DRM_HISI_KIRIN) += kirin/
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_cmd_parser.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_cmd_parser.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_cmd_parser.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_cmd_parser.c	2016-07-24 15:23:50.000000000 -0400
@@ -444,6 +444,7 @@ static const struct drm_i915_reg_descrip
 	REG64(CL_PRIMITIVES_COUNT),
 	REG64(PS_INVOCATION_COUNT),
 	REG64(PS_DEPTH_COUNT),
+	REG64_IDX(RING_TIMESTAMP, RENDER_RING_BASE),
 	REG32(OACONTROL), /* Only allowed for LRI and SRM. See below. */
 	REG64(MI_PREDICATE_SRC0),
 	REG64(MI_PREDICATE_SRC1),
@@ -471,6 +472,25 @@ static const struct drm_i915_reg_descrip
 	REG32(GEN7_L3SQCREG1),
 	REG32(GEN7_L3CNTLREG2),
 	REG32(GEN7_L3CNTLREG3),
+};
+
+static const struct drm_i915_reg_descriptor hsw_render_regs[] = {
+	REG64_IDX(HSW_CS_GPR, 0),
+	REG64_IDX(HSW_CS_GPR, 1),
+	REG64_IDX(HSW_CS_GPR, 2),
+	REG64_IDX(HSW_CS_GPR, 3),
+	REG64_IDX(HSW_CS_GPR, 4),
+	REG64_IDX(HSW_CS_GPR, 5),
+	REG64_IDX(HSW_CS_GPR, 6),
+	REG64_IDX(HSW_CS_GPR, 7),
+	REG64_IDX(HSW_CS_GPR, 8),
+	REG64_IDX(HSW_CS_GPR, 9),
+	REG64_IDX(HSW_CS_GPR, 10),
+	REG64_IDX(HSW_CS_GPR, 11),
+	REG64_IDX(HSW_CS_GPR, 12),
+	REG64_IDX(HSW_CS_GPR, 13),
+	REG64_IDX(HSW_CS_GPR, 14),
+	REG64_IDX(HSW_CS_GPR, 15),
 	REG32(HSW_SCRATCH1,
 	      .mask = ~HSW_SCRATCH1_L3_DATA_ATOMICS_DISABLE,
 	      .value = 0),
@@ -500,6 +520,33 @@ static const struct drm_i915_reg_descrip
 #undef REG64
 #undef REG32
 
+struct drm_i915_reg_table {
+	const struct drm_i915_reg_descriptor *regs;
+	int num_regs;
+	bool master;
+};
+
+static const struct drm_i915_reg_table ivb_render_reg_tables[] = {
+	{ gen7_render_regs, ARRAY_SIZE(gen7_render_regs), false },
+	{ ivb_master_regs, ARRAY_SIZE(ivb_master_regs), true },
+};
+
+static const struct drm_i915_reg_table ivb_blt_reg_tables[] = {
+	{ gen7_blt_regs, ARRAY_SIZE(gen7_blt_regs), false },
+	{ ivb_master_regs, ARRAY_SIZE(ivb_master_regs), true },
+};
+
+static const struct drm_i915_reg_table hsw_render_reg_tables[] = {
+	{ gen7_render_regs, ARRAY_SIZE(gen7_render_regs), false },
+	{ hsw_render_regs, ARRAY_SIZE(hsw_render_regs), false },
+	{ hsw_master_regs, ARRAY_SIZE(hsw_master_regs), true },
+};
+
+static const struct drm_i915_reg_table hsw_blt_reg_tables[] = {
+	{ gen7_blt_regs, ARRAY_SIZE(gen7_blt_regs), false },
+	{ hsw_master_regs, ARRAY_SIZE(hsw_master_regs), true },
+};
+
 static u32 gen7_render_get_cmd_length_mask(u32 cmd_header)
 {
 	u32 client = (cmd_header & INSTR_CLIENT_MASK) >> INSTR_CLIENT_SHIFT;
@@ -555,7 +602,7 @@ static u32 gen7_blt_get_cmd_length_mask(
 	return 0;
 }
 
-static bool validate_cmds_sorted(struct intel_engine_cs *ring,
+static bool validate_cmds_sorted(struct intel_engine_cs *engine,
 				 const struct drm_i915_cmd_table *cmd_tables,
 				 int cmd_table_count)
 {
@@ -577,7 +624,7 @@ static bool validate_cmds_sorted(struct
 
 			if (curr < previous) {
 				DRM_ERROR("CMD: table not sorted ring=%d table=%d entry=%d cmd=0x%08X prev=0x%08X\n",
-					  ring->id, i, j, curr, previous);
+					  engine->id, i, j, curr, previous);
 				ret = false;
 			}
 
@@ -611,11 +658,18 @@ static bool check_sorted(int ring_id,
 	return ret;
 }
 
-static bool validate_regs_sorted(struct intel_engine_cs *ring)
+static bool validate_regs_sorted(struct intel_engine_cs *engine)
 {
-	return check_sorted(ring->id, ring->reg_table, ring->reg_count) &&
-		check_sorted(ring->id, ring->master_reg_table,
-			     ring->master_reg_count);
+	int i;
+	const struct drm_i915_reg_table *table;
+
+	for (i = 0; i < engine->reg_table_count; i++) {
+		table = &engine->reg_tables[i];
+		if (!check_sorted(engine->id, table->regs, table->num_regs))
+			return false;
+	}
+
+	return true;
 }
 
 struct cmd_node {
@@ -639,13 +693,13 @@ struct cmd_node {
  */
 #define CMD_HASH_MASK STD_MI_OPCODE_MASK
 
-static int init_hash_table(struct intel_engine_cs *ring,
+static int init_hash_table(struct intel_engine_cs *engine,
 			   const struct drm_i915_cmd_table *cmd_tables,
 			   int cmd_table_count)
 {
 	int i, j;
 
-	hash_init(ring->cmd_hash);
+	hash_init(engine->cmd_hash);
 
 	for (i = 0; i < cmd_table_count; i++) {
 		const struct drm_i915_cmd_table *table = &cmd_tables[i];
@@ -660,7 +714,7 @@ static int init_hash_table(struct intel_
 				return -ENOMEM;
 
 			desc_node->desc = desc;
-			hash_add(ring->cmd_hash, &desc_node->node,
+			hash_add(engine->cmd_hash, &desc_node->node,
 				 desc->cmd.value & CMD_HASH_MASK);
 		}
 	}
@@ -668,13 +722,13 @@ static int init_hash_table(struct intel_
 	return 0;
 }
 
-static void fini_hash_table(struct intel_engine_cs *ring)
+static void fini_hash_table(struct intel_engine_cs *engine)
 {
 	struct hlist_node *tmp;
 	struct cmd_node *desc_node;
 	int i;
 
-	hash_for_each_safe(ring->cmd_hash, i, tmp, desc_node, node) {
+	hash_for_each_safe(engine->cmd_hash, i, tmp, desc_node, node) {
 		hash_del(&desc_node->node);
 		kfree(desc_node);
 	}
@@ -690,18 +744,18 @@ static void fini_hash_table(struct intel
  *
  * Return: non-zero if initialization fails
  */
-int i915_cmd_parser_init_ring(struct intel_engine_cs *ring)
+int i915_cmd_parser_init_ring(struct intel_engine_cs *engine)
 {
 	const struct drm_i915_cmd_table *cmd_tables;
 	int cmd_table_count;
 	int ret;
 
-	if (!IS_GEN7(ring->dev))
+	if (!IS_GEN7(engine->dev))
 		return 0;
 
-	switch (ring->id) {
+	switch (engine->id) {
 	case RCS:
-		if (IS_HASWELL(ring->dev)) {
+		if (IS_HASWELL(engine->dev)) {
 			cmd_tables = hsw_render_ring_cmds;
 			cmd_table_count =
 				ARRAY_SIZE(hsw_render_ring_cmds);
@@ -710,26 +764,23 @@ int i915_cmd_parser_init_ring(struct int
 			cmd_table_count = ARRAY_SIZE(gen7_render_cmds);
 		}
 
-		ring->reg_table = gen7_render_regs;
-		ring->reg_count = ARRAY_SIZE(gen7_render_regs);
-
-		if (IS_HASWELL(ring->dev)) {
-			ring->master_reg_table = hsw_master_regs;
-			ring->master_reg_count = ARRAY_SIZE(hsw_master_regs);
+		if (IS_HASWELL(engine->dev)) {
+			engine->reg_tables = hsw_render_reg_tables;
+			engine->reg_table_count = ARRAY_SIZE(hsw_render_reg_tables);
 		} else {
-			ring->master_reg_table = ivb_master_regs;
-			ring->master_reg_count = ARRAY_SIZE(ivb_master_regs);
+			engine->reg_tables = ivb_render_reg_tables;
+			engine->reg_table_count = ARRAY_SIZE(ivb_render_reg_tables);
 		}
 
-		ring->get_cmd_length_mask = gen7_render_get_cmd_length_mask;
+		engine->get_cmd_length_mask = gen7_render_get_cmd_length_mask;
 		break;
 	case VCS:
 		cmd_tables = gen7_video_cmds;
 		cmd_table_count = ARRAY_SIZE(gen7_video_cmds);
-		ring->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask;
+		engine->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask;
 		break;
 	case BCS:
-		if (IS_HASWELL(ring->dev)) {
+		if (IS_HASWELL(engine->dev)) {
 			cmd_tables = hsw_blt_ring_cmds;
 			cmd_table_count = ARRAY_SIZE(hsw_blt_ring_cmds);
 		} else {
@@ -737,44 +788,41 @@ int i915_cmd_parser_init_ring(struct int
 			cmd_table_count = ARRAY_SIZE(gen7_blt_cmds);
 		}
 
-		ring->reg_table = gen7_blt_regs;
-		ring->reg_count = ARRAY_SIZE(gen7_blt_regs);
-
-		if (IS_HASWELL(ring->dev)) {
-			ring->master_reg_table = hsw_master_regs;
-			ring->master_reg_count = ARRAY_SIZE(hsw_master_regs);
+		if (IS_HASWELL(engine->dev)) {
+			engine->reg_tables = hsw_blt_reg_tables;
+			engine->reg_table_count = ARRAY_SIZE(hsw_blt_reg_tables);
 		} else {
-			ring->master_reg_table = ivb_master_regs;
-			ring->master_reg_count = ARRAY_SIZE(ivb_master_regs);
+			engine->reg_tables = ivb_blt_reg_tables;
+			engine->reg_table_count = ARRAY_SIZE(ivb_blt_reg_tables);
 		}
 
-		ring->get_cmd_length_mask = gen7_blt_get_cmd_length_mask;
+		engine->get_cmd_length_mask = gen7_blt_get_cmd_length_mask;
 		break;
 	case VECS:
 		cmd_tables = hsw_vebox_cmds;
 		cmd_table_count = ARRAY_SIZE(hsw_vebox_cmds);
 		/* VECS can use the same length_mask function as VCS */
-		ring->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask;
+		engine->get_cmd_length_mask = gen7_bsd_get_cmd_length_mask;
 		break;
 	default:
 		DRM_ERROR("CMD: cmd_parser_init with unknown ring: %d\n",
-			  ring->id);
+			  engine->id);
 		BUG();
 	}
 
-	BUG_ON(!validate_cmds_sorted(ring, cmd_tables, cmd_table_count));
-	BUG_ON(!validate_regs_sorted(ring));
+	BUG_ON(!validate_cmds_sorted(engine, cmd_tables, cmd_table_count));
+	BUG_ON(!validate_regs_sorted(engine));
 
-	WARN_ON(!hash_empty(ring->cmd_hash));
+	WARN_ON(!hash_empty(engine->cmd_hash));
 
-	ret = init_hash_table(ring, cmd_tables, cmd_table_count);
+	ret = init_hash_table(engine, cmd_tables, cmd_table_count);
 	if (ret) {
 		DRM_ERROR("CMD: cmd_parser_init failed!\n");
-		fini_hash_table(ring);
+		fini_hash_table(engine);
 		return ret;
 	}
 
-	ring->needs_cmd_parser = true;
+	engine->needs_cmd_parser = true;
 
 	return 0;
 }
@@ -786,21 +834,21 @@ int i915_cmd_parser_init_ring(struct int
  * Releases any resources related to command parsing that may have been
  * initialized for the specified ring.
  */
-void i915_cmd_parser_fini_ring(struct intel_engine_cs *ring)
+void i915_cmd_parser_fini_ring(struct intel_engine_cs *engine)
 {
-	if (!ring->needs_cmd_parser)
+	if (!engine->needs_cmd_parser)
 		return;
 
-	fini_hash_table(ring);
+	fini_hash_table(engine);
 }
 
 static const struct drm_i915_cmd_descriptor*
-find_cmd_in_table(struct intel_engine_cs *ring,
+find_cmd_in_table(struct intel_engine_cs *engine,
 		  u32 cmd_header)
 {
 	struct cmd_node *desc_node;
 
-	hash_for_each_possible(ring->cmd_hash, desc_node, node,
+	hash_for_each_possible(engine->cmd_hash, desc_node, node,
 			       cmd_header & CMD_HASH_MASK) {
 		const struct drm_i915_cmd_descriptor *desc = desc_node->desc;
 		u32 masked_cmd = desc->cmd.mask & cmd_header;
@@ -822,18 +870,18 @@ find_cmd_in_table(struct intel_engine_cs
  * ring's default length encoding and returns default_desc.
  */
 static const struct drm_i915_cmd_descriptor*
-find_cmd(struct intel_engine_cs *ring,
+find_cmd(struct intel_engine_cs *engine,
 	 u32 cmd_header,
 	 struct drm_i915_cmd_descriptor *default_desc)
 {
 	const struct drm_i915_cmd_descriptor *desc;
 	u32 mask;
 
-	desc = find_cmd_in_table(ring, cmd_header);
+	desc = find_cmd_in_table(engine, cmd_header);
 	if (desc)
 		return desc;
 
-	mask = ring->get_cmd_length_mask(cmd_header);
+	mask = engine->get_cmd_length_mask(cmd_header);
 	if (!mask)
 		return NULL;
 
@@ -848,12 +896,31 @@ static const struct drm_i915_reg_descrip
 find_reg(const struct drm_i915_reg_descriptor *table,
 	 int count, u32 addr)
 {
-	if (table) {
-		int i;
+	int i;
 
-		for (i = 0; i < count; i++) {
-			if (i915_mmio_reg_offset(table[i].addr) == addr)
-				return &table[i];
+	for (i = 0; i < count; i++) {
+		if (i915_mmio_reg_offset(table[i].addr) == addr)
+			return &table[i];
+	}
+
+	return NULL;
+}
+
+static const struct drm_i915_reg_descriptor *
+find_reg_in_tables(const struct drm_i915_reg_table *tables,
+		   int count, bool is_master, u32 addr)
+{
+	int i;
+	const struct drm_i915_reg_table *table;
+	const struct drm_i915_reg_descriptor *reg;
+
+	for (i = 0; i < count; i++) {
+		table = &tables[i];
+		if (!table->master || is_master) {
+			reg = find_reg(table->regs, table->num_regs,
+				       addr);
+			if (reg != NULL)
+				return reg;
 		}
 	}
 
@@ -963,18 +1030,18 @@ unpin_src:
  *
  * Return: true if the ring requires software command parsing
  */
-bool i915_needs_cmd_parser(struct intel_engine_cs *ring)
+bool i915_needs_cmd_parser(struct intel_engine_cs *engine)
 {
-	if (!ring->needs_cmd_parser)
+	if (!engine->needs_cmd_parser)
 		return false;
 
-	if (!USES_PPGTT(ring->dev))
+	if (!USES_PPGTT(engine->dev))
 		return false;
 
 	return (i915.enable_cmd_parser == 1);
 }
 
-static bool check_cmd(const struct intel_engine_cs *ring,
+static bool check_cmd(const struct intel_engine_cs *engine,
 		      const struct drm_i915_cmd_descriptor *desc,
 		      const u32 *cmd, u32 length,
 		      const bool is_master,
@@ -1004,17 +1071,14 @@ static bool check_cmd(const struct intel
 		     offset += step) {
 			const u32 reg_addr = cmd[offset] & desc->reg.mask;
 			const struct drm_i915_reg_descriptor *reg =
-				find_reg(ring->reg_table, ring->reg_count,
-					 reg_addr);
-
-			if (!reg && is_master)
-				reg = find_reg(ring->master_reg_table,
-					       ring->master_reg_count,
-					       reg_addr);
+				find_reg_in_tables(engine->reg_tables,
+						   engine->reg_table_count,
+						   is_master,
+						   reg_addr);
 
 			if (!reg) {
 				DRM_DEBUG_DRIVER("CMD: Rejected register 0x%08X in command: 0x%08X (ring=%d)\n",
-						 reg_addr, *cmd, ring->id);
+						 reg_addr, *cmd, engine->id);
 				return false;
 			}
 
@@ -1087,7 +1151,7 @@ static bool check_cmd(const struct intel
 						 *cmd,
 						 desc->bits[i].mask,
 						 desc->bits[i].expected,
-						 dword, ring->id);
+						 dword, engine->id);
 				return false;
 			}
 		}
@@ -1113,7 +1177,7 @@ static bool check_cmd(const struct intel
  * Return: non-zero if the parser finds violations or otherwise fails; -EACCES
  * if the batch appears legal but should use hardware parsing
  */
-int i915_parse_cmds(struct intel_engine_cs *ring,
+int i915_parse_cmds(struct intel_engine_cs *engine,
 		    struct drm_i915_gem_object *batch_obj,
 		    struct drm_i915_gem_object *shadow_batch_obj,
 		    u32 batch_start_offset,
@@ -1147,7 +1211,7 @@ int i915_parse_cmds(struct intel_engine_
 		if (*cmd == MI_BATCH_BUFFER_END)
 			break;
 
-		desc = find_cmd(ring, *cmd, &default_desc);
+		desc = find_cmd(engine, *cmd, &default_desc);
 		if (!desc) {
 			DRM_DEBUG_DRIVER("CMD: Unrecognized command: 0x%08X\n",
 					 *cmd);
@@ -1179,7 +1243,7 @@ int i915_parse_cmds(struct intel_engine_
 			break;
 		}
 
-		if (!check_cmd(ring, desc, cmd, length, is_master,
+		if (!check_cmd(engine, desc, cmd, length, is_master,
 			       &oacontrol_set)) {
 			ret = -EINVAL;
 			break;
@@ -1223,6 +1287,7 @@ int i915_cmd_parser_get_version(void)
 	 * 3. Allow access to the GPGPU_THREADS_DISPATCHED register.
 	 * 4. L3 atomic chicken bits of HSW_SCRATCH1 and HSW_ROW_CHICKEN3.
 	 * 5. GPGPU dispatch compute indirect registers.
+	 * 6. TIMESTAMP register and Haswell CS GPR registers
 	 */
-	return 5;
+	return 6;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_debugfs.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_debugfs.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_debugfs.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_debugfs.c	2016-07-24 15:23:50.000000000 -0400
@@ -89,27 +89,34 @@ static int i915_capabilities(struct seq_
 	return 0;
 }
 
-static const char *get_pin_flag(struct drm_i915_gem_object *obj)
+static const char get_active_flag(struct drm_i915_gem_object *obj)
 {
-	if (obj->pin_display)
-		return "p";
-	else
-		return " ";
+	return obj->active ? '*' : ' ';
 }
 
-static const char *get_tiling_flag(struct drm_i915_gem_object *obj)
+static const char get_pin_flag(struct drm_i915_gem_object *obj)
+{
+	return obj->pin_display ? 'p' : ' ';
+}
+
+static const char get_tiling_flag(struct drm_i915_gem_object *obj)
 {
 	switch (obj->tiling_mode) {
 	default:
-	case I915_TILING_NONE: return " ";
-	case I915_TILING_X: return "X";
-	case I915_TILING_Y: return "Y";
+	case I915_TILING_NONE: return ' ';
+	case I915_TILING_X: return 'X';
+	case I915_TILING_Y: return 'Y';
 	}
 }
 
-static inline const char *get_global_flag(struct drm_i915_gem_object *obj)
+static inline const char get_global_flag(struct drm_i915_gem_object *obj)
 {
-	return i915_gem_obj_to_ggtt(obj) ? "g" : " ";
+	return i915_gem_obj_to_ggtt(obj) ? 'g' : ' ';
+}
+
+static inline const char get_pin_mapped_flag(struct drm_i915_gem_object *obj)
+{
+	return obj->mapping ? 'M' : ' ';
 }
 
 static u64 i915_gem_obj_total_ggtt_size(struct drm_i915_gem_object *obj)
@@ -129,23 +136,26 @@ static void
 describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
 {
 	struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
-	struct intel_engine_cs *ring;
+	struct intel_engine_cs *engine;
 	struct i915_vma *vma;
 	int pin_count = 0;
-	int i;
+	enum intel_engine_id id;
 
-	seq_printf(m, "%pK: %s%s%s%s %8zdKiB %02x %02x [ ",
+	lockdep_assert_held(&obj->base.dev->struct_mutex);
+
+	seq_printf(m, "%pK: %c%c%c%c%c %8zdKiB %02x %02x [ ",
 		   &obj->base,
-		   obj->active ? "*" : " ",
+		   get_active_flag(obj),
 		   get_pin_flag(obj),
 		   get_tiling_flag(obj),
 		   get_global_flag(obj),
+		   get_pin_mapped_flag(obj),
 		   obj->base.size / 1024,
 		   obj->base.read_domains,
 		   obj->base.write_domain);
-	for_each_ring(ring, dev_priv, i)
+	for_each_engine_id(engine, dev_priv, id)
 		seq_printf(m, "%x ",
-				i915_gem_request_get_seqno(obj->last_read_req[i]));
+				i915_gem_request_get_seqno(obj->last_read_req[id]));
 	seq_printf(m, "] %x %x%s%s%s",
 		   i915_gem_request_get_seqno(obj->last_write_req),
 		   i915_gem_request_get_seqno(obj->last_fenced_req),
@@ -184,7 +194,7 @@ describe_obj(struct seq_file *m, struct
 	}
 	if (obj->last_write_req != NULL)
 		seq_printf(m, " (%s)",
-			   i915_gem_request_get_ring(obj->last_write_req)->name);
+			   i915_gem_request_get_engine(obj->last_write_req)->name);
 	if (obj->frontbuffer_bits)
 		seq_printf(m, " (frontbuffer: 0x%03x)", obj->frontbuffer_bits);
 }
@@ -202,8 +212,8 @@ static int i915_gem_object_list_info(str
 	uintptr_t list = (uintptr_t) node->info_ent->data;
 	struct list_head *head;
 	struct drm_device *dev = node->minor->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct i915_address_space *vm = &dev_priv->gtt.base;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	struct i915_vma *vma;
 	u64 total_obj_size, total_gtt_size;
 	int count, ret;
@@ -216,11 +226,11 @@ static int i915_gem_object_list_info(str
 	switch (list) {
 	case ACTIVE_LIST:
 		seq_puts(m, "Active:\n");
-		head = &vm->active_list;
+		head = &ggtt->base.active_list;
 		break;
 	case INACTIVE_LIST:
 		seq_puts(m, "Inactive:\n");
-		head = &vm->inactive_list;
+		head = &ggtt->base.inactive_list;
 		break;
 	default:
 		mutex_unlock(&dev->struct_mutex);
@@ -397,15 +407,15 @@ static void print_batch_pool_stats(struc
 {
 	struct drm_i915_gem_object *obj;
 	struct file_stats stats;
-	struct intel_engine_cs *ring;
-	int i, j;
+	struct intel_engine_cs *engine;
+	int j;
 
 	memset(&stats, 0, sizeof(stats));
 
-	for_each_ring(ring, dev_priv, i) {
-		for (j = 0; j < ARRAY_SIZE(ring->batch_pool.cache_list); j++) {
+	for_each_engine(engine, dev_priv) {
+		for (j = 0; j < ARRAY_SIZE(engine->batch_pool.cache_list); j++) {
 			list_for_each_entry(obj,
-					    &ring->batch_pool.cache_list[j],
+					    &engine->batch_pool.cache_list[j],
 					    batch_pool_link)
 				per_file_stats(0, obj, &stats);
 		}
@@ -429,11 +439,13 @@ static int i915_gem_object_info(struct s
 {
 	struct drm_info_node *node = m->private;
 	struct drm_device *dev = node->minor->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	u32 count, mappable_count, purgeable_count;
 	u64 size, mappable_size, purgeable_size;
+	unsigned long pin_mapped_count = 0, pin_mapped_purgeable_count = 0;
+	u64 pin_mapped_size = 0, pin_mapped_purgeable_size = 0;
 	struct drm_i915_gem_object *obj;
-	struct i915_address_space *vm = &dev_priv->gtt.base;
 	struct drm_file *file;
 	struct i915_vma *vma;
 	int ret;
@@ -452,12 +464,12 @@ static int i915_gem_object_info(struct s
 		   count, mappable_count, size, mappable_size);
 
 	size = count = mappable_size = mappable_count = 0;
-	count_vmas(&vm->active_list, vm_link);
+	count_vmas(&ggtt->base.active_list, vm_link);
 	seq_printf(m, "  %u [%u] active objects, %llu [%llu] bytes\n",
 		   count, mappable_count, size, mappable_size);
 
 	size = count = mappable_size = mappable_count = 0;
-	count_vmas(&vm->inactive_list, vm_link);
+	count_vmas(&ggtt->base.inactive_list, vm_link);
 	seq_printf(m, "  %u [%u] inactive objects, %llu [%llu] bytes\n",
 		   count, mappable_count, size, mappable_size);
 
@@ -466,6 +478,14 @@ static int i915_gem_object_info(struct s
 		size += obj->base.size, ++count;
 		if (obj->madv == I915_MADV_DONTNEED)
 			purgeable_size += obj->base.size, ++purgeable_count;
+		if (obj->mapping) {
+			pin_mapped_count++;
+			pin_mapped_size += obj->base.size;
+			if (obj->pages_pin_count == 0) {
+				pin_mapped_purgeable_count++;
+				pin_mapped_purgeable_size += obj->base.size;
+			}
+		}
 	}
 	seq_printf(m, "%u unbound objects, %llu bytes\n", count, size);
 
@@ -483,6 +503,14 @@ static int i915_gem_object_info(struct s
 			purgeable_size += obj->base.size;
 			++purgeable_count;
 		}
+		if (obj->mapping) {
+			pin_mapped_count++;
+			pin_mapped_size += obj->base.size;
+			if (obj->pages_pin_count == 0) {
+				pin_mapped_purgeable_count++;
+				pin_mapped_purgeable_size += obj->base.size;
+			}
+		}
 	}
 	seq_printf(m, "%u purgeable objects, %llu bytes\n",
 		   purgeable_count, purgeable_size);
@@ -490,13 +518,20 @@ static int i915_gem_object_info(struct s
 		   mappable_count, mappable_size);
 	seq_printf(m, "%u fault mappable objects, %llu bytes\n",
 		   count, size);
+	seq_printf(m,
+		   "%lu [%lu] pin mapped objects, %llu [%llu] bytes [purgeable]\n",
+		   pin_mapped_count, pin_mapped_purgeable_count,
+		   pin_mapped_size, pin_mapped_purgeable_size);
 
 	seq_printf(m, "%llu [%llu] gtt total\n",
-		   dev_priv->gtt.base.total,
-		   (u64)dev_priv->gtt.mappable_end - dev_priv->gtt.base.start);
+		   ggtt->base.total, ggtt->mappable_end - ggtt->base.start);
 
 	seq_putc(m, '\n');
 	print_batch_pool_stats(m, dev_priv);
+
+	mutex_unlock(&dev->struct_mutex);
+
+	mutex_lock(&dev->filelist_mutex);
 	list_for_each_entry_reverse(file, &dev->filelist, lhead) {
 		struct file_stats stats;
 		struct task_struct *task;
@@ -517,8 +552,7 @@ static int i915_gem_object_info(struct s
 		print_file_stats(m, task ? task->comm : "<unknown>", stats);
 		rcu_read_unlock();
 	}
-
-	mutex_unlock(&dev->struct_mutex);
+	mutex_unlock(&dev->filelist_mutex);
 
 	return 0;
 }
@@ -591,14 +625,13 @@ static int i915_gem_pageflip_info(struct
 					   pipe, plane);
 			}
 			if (work->flip_queued_req) {
-				struct intel_engine_cs *ring =
-					i915_gem_request_get_ring(work->flip_queued_req);
+				struct intel_engine_cs *engine = i915_gem_request_get_engine(work->flip_queued_req);
 
 				seq_printf(m, "Flip queued on %s at seqno %x, next seqno %x [current breadcrumb %x], completed? %d\n",
-					   ring->name,
+					   engine->name,
 					   i915_gem_request_get_seqno(work->flip_queued_req),
 					   dev_priv->next_seqno,
-					   ring->get_seqno(ring, true),
+					   engine->get_seqno(engine),
 					   i915_gem_request_completed(work->flip_queued_req, true));
 			} else
 				seq_printf(m, "Flip not associated with any ring\n");
@@ -637,28 +670,28 @@ static int i915_gem_batch_pool_info(stru
 	struct drm_device *dev = node->minor->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_gem_object *obj;
-	struct intel_engine_cs *ring;
+	struct intel_engine_cs *engine;
 	int total = 0;
-	int ret, i, j;
+	int ret, j;
 
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
 
-	for_each_ring(ring, dev_priv, i) {
-		for (j = 0; j < ARRAY_SIZE(ring->batch_pool.cache_list); j++) {
+	for_each_engine(engine, dev_priv) {
+		for (j = 0; j < ARRAY_SIZE(engine->batch_pool.cache_list); j++) {
 			int count;
 
 			count = 0;
 			list_for_each_entry(obj,
-					    &ring->batch_pool.cache_list[j],
+					    &engine->batch_pool.cache_list[j],
 					    batch_pool_link)
 				count++;
 			seq_printf(m, "%s cache[%d]: %d objects\n",
-				   ring->name, j, count);
+				   engine->name, j, count);
 
 			list_for_each_entry(obj,
-					    &ring->batch_pool.cache_list[j],
+					    &engine->batch_pool.cache_list[j],
 					    batch_pool_link) {
 				seq_puts(m, "   ");
 				describe_obj(m, obj);
@@ -681,26 +714,26 @@ static int i915_gem_request_info(struct
 	struct drm_info_node *node = m->private;
 	struct drm_device *dev = node->minor->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring;
+	struct intel_engine_cs *engine;
 	struct drm_i915_gem_request *req;
-	int ret, any, i;
+	int ret, any;
 
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
 
 	any = 0;
-	for_each_ring(ring, dev_priv, i) {
+	for_each_engine(engine, dev_priv) {
 		int count;
 
 		count = 0;
-		list_for_each_entry(req, &ring->request_list, list)
+		list_for_each_entry(req, &engine->request_list, list)
 			count++;
 		if (count == 0)
 			continue;
 
-		seq_printf(m, "%s requests: %d\n", ring->name, count);
-		list_for_each_entry(req, &ring->request_list, list) {
+		seq_printf(m, "%s requests: %d\n", engine->name, count);
+		list_for_each_entry(req, &engine->request_list, list) {
 			struct task_struct *task;
 
 			rcu_read_lock();
@@ -726,12 +759,12 @@ static int i915_gem_request_info(struct
 }
 
 static void i915_ring_seqno_info(struct seq_file *m,
-				 struct intel_engine_cs *ring)
+				 struct intel_engine_cs *engine)
 {
-	if (ring->get_seqno) {
-		seq_printf(m, "Current sequence (%s): %x\n",
-			   ring->name, ring->get_seqno(ring, false));
-	}
+	seq_printf(m, "Current sequence (%s): %x\n",
+		   engine->name, engine->get_seqno(engine));
+	seq_printf(m, "Current user interrupts (%s): %x\n",
+		   engine->name, READ_ONCE(engine->user_interrupts));
 }
 
 static int i915_gem_seqno_info(struct seq_file *m, void *data)
@@ -739,16 +772,16 @@ static int i915_gem_seqno_info(struct se
 	struct drm_info_node *node = m->private;
 	struct drm_device *dev = node->minor->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring;
-	int ret, i;
+	struct intel_engine_cs *engine;
+	int ret;
 
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
 	intel_runtime_pm_get(dev_priv);
 
-	for_each_ring(ring, dev_priv, i)
-		i915_ring_seqno_info(m, ring);
+	for_each_engine(engine, dev_priv)
+		i915_ring_seqno_info(m, engine);
 
 	intel_runtime_pm_put(dev_priv);
 	mutex_unlock(&dev->struct_mutex);
@@ -762,7 +795,7 @@ static int i915_interrupt_info(struct se
 	struct drm_info_node *node = m->private;
 	struct drm_device *dev = node->minor->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring;
+	struct intel_engine_cs *engine;
 	int ret, i, pipe;
 
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
@@ -934,13 +967,13 @@ static int i915_interrupt_info(struct se
 		seq_printf(m, "Graphics Interrupt mask:		%08x\n",
 			   I915_READ(GTIMR));
 	}
-	for_each_ring(ring, dev_priv, i) {
+	for_each_engine(engine, dev_priv) {
 		if (INTEL_INFO(dev)->gen >= 6) {
 			seq_printf(m,
 				   "Graphics Interrupt mask (%s):	%08x\n",
-				   ring->name, I915_READ_IMR(ring));
+				   engine->name, I915_READ_IMR(engine));
 		}
-		i915_ring_seqno_info(m, ring);
+		i915_ring_seqno_info(m, engine);
 	}
 	intel_runtime_pm_put(dev_priv);
 	mutex_unlock(&dev->struct_mutex);
@@ -981,12 +1014,12 @@ static int i915_hws_info(struct seq_file
 	struct drm_info_node *node = m->private;
 	struct drm_device *dev = node->minor->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring;
+	struct intel_engine_cs *engine;
 	const u32 *hws;
 	int i;
 
-	ring = &dev_priv->ring[(uintptr_t)node->info_ent->data];
-	hws = ring->status_page.page_addr;
+	engine = &dev_priv->engine[(uintptr_t)node->info_ent->data];
+	hws = engine->status_page.page_addr;
 	if (hws == NULL)
 		return 0;
 
@@ -1216,12 +1249,12 @@ static int i915_frequency_info(struct se
 		rpdeclimit = I915_READ(GEN6_RP_DOWN_THRESHOLD);
 
 		rpstat = I915_READ(GEN6_RPSTAT1);
-		rpupei = I915_READ(GEN6_RP_CUR_UP_EI);
-		rpcurup = I915_READ(GEN6_RP_CUR_UP);
-		rpprevup = I915_READ(GEN6_RP_PREV_UP);
-		rpdownei = I915_READ(GEN6_RP_CUR_DOWN_EI);
-		rpcurdown = I915_READ(GEN6_RP_CUR_DOWN);
-		rpprevdown = I915_READ(GEN6_RP_PREV_DOWN);
+		rpupei = I915_READ(GEN6_RP_CUR_UP_EI) & GEN6_CURICONT_MASK;
+		rpcurup = I915_READ(GEN6_RP_CUR_UP) & GEN6_CURBSYTAVG_MASK;
+		rpprevup = I915_READ(GEN6_RP_PREV_UP) & GEN6_CURBSYTAVG_MASK;
+		rpdownei = I915_READ(GEN6_RP_CUR_DOWN_EI) & GEN6_CURIAVG_MASK;
+		rpcurdown = I915_READ(GEN6_RP_CUR_DOWN) & GEN6_CURBSYTAVG_MASK;
+		rpprevdown = I915_READ(GEN6_RP_PREV_DOWN) & GEN6_CURBSYTAVG_MASK;
 		if (IS_GEN9(dev))
 			cagf = (rpstat & GEN9_CAGF_MASK) >> GEN9_CAGF_SHIFT;
 		else if (IS_HASWELL(dev) || IS_BROADWELL(dev))
@@ -1261,21 +1294,21 @@ static int i915_frequency_info(struct se
 		seq_printf(m, "RPDECLIMIT: 0x%08x\n", rpdeclimit);
 		seq_printf(m, "RPNSWREQ: %dMHz\n", reqf);
 		seq_printf(m, "CAGF: %dMHz\n", cagf);
-		seq_printf(m, "RP CUR UP EI: %dus\n", rpupei &
-			   GEN6_CURICONT_MASK);
-		seq_printf(m, "RP CUR UP: %dus\n", rpcurup &
-			   GEN6_CURBSYTAVG_MASK);
-		seq_printf(m, "RP PREV UP: %dus\n", rpprevup &
-			   GEN6_CURBSYTAVG_MASK);
+		seq_printf(m, "RP CUR UP EI: %d (%dus)\n",
+			   rpupei, GT_PM_INTERVAL_TO_US(dev_priv, rpupei));
+		seq_printf(m, "RP CUR UP: %d (%dus)\n",
+			   rpcurup, GT_PM_INTERVAL_TO_US(dev_priv, rpcurup));
+		seq_printf(m, "RP PREV UP: %d (%dus)\n",
+			   rpprevup, GT_PM_INTERVAL_TO_US(dev_priv, rpprevup));
 		seq_printf(m, "Up threshold: %d%%\n",
 			   dev_priv->rps.up_threshold);
 
-		seq_printf(m, "RP CUR DOWN EI: %dus\n", rpdownei &
-			   GEN6_CURIAVG_MASK);
-		seq_printf(m, "RP CUR DOWN: %dus\n", rpcurdown &
-			   GEN6_CURBSYTAVG_MASK);
-		seq_printf(m, "RP PREV DOWN: %dus\n", rpprevdown &
-			   GEN6_CURBSYTAVG_MASK);
+		seq_printf(m, "RP CUR DOWN EI: %d (%dus)\n",
+			   rpdownei, GT_PM_INTERVAL_TO_US(dev_priv, rpdownei));
+		seq_printf(m, "RP CUR DOWN: %d (%dus)\n",
+			   rpcurdown, GT_PM_INTERVAL_TO_US(dev_priv, rpcurdown));
+		seq_printf(m, "RP PREV DOWN: %d (%dus)\n",
+			   rpprevdown, GT_PM_INTERVAL_TO_US(dev_priv, rpprevdown));
 		seq_printf(m, "Down threshold: %d%%\n",
 			   dev_priv->rps.down_threshold);
 
@@ -1331,11 +1364,12 @@ static int i915_hangcheck_info(struct se
 	struct drm_info_node *node = m->private;
 	struct drm_device *dev = node->minor->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring;
-	u64 acthd[I915_NUM_RINGS];
-	u32 seqno[I915_NUM_RINGS];
+	struct intel_engine_cs *engine;
+	u64 acthd[I915_NUM_ENGINES];
+	u32 seqno[I915_NUM_ENGINES];
 	u32 instdone[I915_NUM_INSTDONE_REG];
-	int i, j;
+	enum intel_engine_id id;
+	int j;
 
 	if (!i915.enable_hangcheck) {
 		seq_printf(m, "Hangcheck disabled\n");
@@ -1344,9 +1378,9 @@ static int i915_hangcheck_info(struct se
 
 	intel_runtime_pm_get(dev_priv);
 
-	for_each_ring(ring, dev_priv, i) {
-		seqno[i] = ring->get_seqno(ring, false);
-		acthd[i] = intel_ring_get_active_head(ring);
+	for_each_engine_id(engine, dev_priv, id) {
+		acthd[id] = intel_ring_get_active_head(engine);
+		seqno[id] = engine->get_seqno(engine);
 	}
 
 	i915_get_extra_instdone(dev, instdone);
@@ -1360,19 +1394,22 @@ static int i915_hangcheck_info(struct se
 	} else
 		seq_printf(m, "Hangcheck inactive\n");
 
-	for_each_ring(ring, dev_priv, i) {
-		seq_printf(m, "%s:\n", ring->name);
-		seq_printf(m, "\tseqno = %x [current %x]\n",
-			   ring->hangcheck.seqno, seqno[i]);
+	for_each_engine_id(engine, dev_priv, id) {
+		seq_printf(m, "%s:\n", engine->name);
+		seq_printf(m, "\tseqno = %x [current %x, last %x]\n",
+			   engine->hangcheck.seqno,
+			   seqno[id],
+			   engine->last_submitted_seqno);
+		seq_printf(m, "\tuser interrupts = %x [current %x]\n",
+			   engine->hangcheck.user_interrupts,
+			   READ_ONCE(engine->user_interrupts));
 		seq_printf(m, "\tACTHD = 0x%08llx [current 0x%08llx]\n",
-			   (long long)ring->hangcheck.acthd,
-			   (long long)acthd[i]);
-		seq_printf(m, "\tmax ACTHD = 0x%08llx\n",
-			   (long long)ring->hangcheck.max_acthd);
-		seq_printf(m, "\tscore = %d\n", ring->hangcheck.score);
-		seq_printf(m, "\taction = %d\n", ring->hangcheck.action);
+			   (long long)engine->hangcheck.acthd,
+			   (long long)acthd[id]);
+		seq_printf(m, "\tscore = %d\n", engine->hangcheck.score);
+		seq_printf(m, "\taction = %d\n", engine->hangcheck.action);
 
-		if (ring->id == RCS) {
+		if (engine->id == RCS) {
 			seq_puts(m, "\tinstdone read =");
 
 			for (j = 0; j < I915_NUM_INSTDONE_REG; j++)
@@ -1382,7 +1419,7 @@ static int i915_hangcheck_info(struct se
 
 			for (j = 0; j < I915_NUM_INSTDONE_REG; j++)
 				seq_printf(m, " 0x%08x",
-					   ring->hangcheck.instdone[j]);
+					   engine->hangcheck.instdone[j]);
 
 			seq_puts(m, "\n");
 		}
@@ -1465,12 +1502,11 @@ static int i915_forcewake_domains(struct
 	struct drm_device *dev = node->minor->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_uncore_forcewake_domain *fw_domain;
-	int i;
 
 	spin_lock_irq(&dev_priv->uncore.lock);
-	for_each_fw_domain(fw_domain, dev_priv, i) {
+	for_each_fw_domain(fw_domain, dev_priv) {
 		seq_printf(m, "%s.wake_count = %u\n",
-			   intel_uncore_forcewake_domain_to_str(i),
+			   intel_uncore_forcewake_domain_to_str(fw_domain->id),
 			   fw_domain->wake_count);
 	}
 	spin_unlock_irq(&dev_priv->uncore.lock);
@@ -1897,6 +1933,11 @@ static int i915_gem_framebuffer_info(str
 	struct drm_device *dev = node->minor->dev;
 	struct intel_framebuffer *fbdev_fb = NULL;
 	struct drm_framebuffer *drm_fb;
+	int ret;
+
+	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	if (ret)
+		return ret;
 
 #ifdef CONFIG_DRM_FBDEV_EMULATION
        if (to_i915(dev)->fbdev) {
@@ -1908,7 +1949,7 @@ static int i915_gem_framebuffer_info(str
                          fbdev_fb->base.depth,
                          fbdev_fb->base.bits_per_pixel,
                          fbdev_fb->base.modifier[0],
-                         atomic_read(&fbdev_fb->base.refcount.refcount));
+                         drm_framebuffer_read_refcount(&fbdev_fb->base));
                describe_obj(m, fbdev_fb->obj);
                seq_putc(m, '\n');
        }
@@ -1926,11 +1967,12 @@ static int i915_gem_framebuffer_info(str
 			   fb->base.depth,
 			   fb->base.bits_per_pixel,
 			   fb->base.modifier[0],
-			   atomic_read(&fb->base.refcount.refcount));
+			   drm_framebuffer_read_refcount(&fb->base));
 		describe_obj(m, fb->obj);
 		seq_putc(m, '\n');
 	}
 	mutex_unlock(&dev->mode_config.fb_lock);
+	mutex_unlock(&dev->struct_mutex);
 
 	return 0;
 }
@@ -1948,9 +1990,10 @@ static int i915_context_status(struct se
 	struct drm_info_node *node = m->private;
 	struct drm_device *dev = node->minor->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring;
+	struct intel_engine_cs *engine;
 	struct intel_context *ctx;
-	int ret, i;
+	enum intel_engine_id id;
+	int ret;
 
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
@@ -1968,13 +2011,13 @@ static int i915_context_status(struct se
 
 		if (i915.enable_execlists) {
 			seq_putc(m, '\n');
-			for_each_ring(ring, dev_priv, i) {
+			for_each_engine_id(engine, dev_priv, id) {
 				struct drm_i915_gem_object *ctx_obj =
-					ctx->engine[i].state;
+					ctx->engine[id].state;
 				struct intel_ringbuffer *ringbuf =
-					ctx->engine[i].ringbuf;
+					ctx->engine[id].ringbuf;
 
-				seq_printf(m, "%s: ", ring->name);
+				seq_printf(m, "%s: ", engine->name);
 				if (ctx_obj)
 					describe_obj(m, ctx_obj);
 				if (ringbuf)
@@ -1995,22 +2038,22 @@ static int i915_context_status(struct se
 
 static void i915_dump_lrc_obj(struct seq_file *m,
 			      struct intel_context *ctx,
-			      struct intel_engine_cs *ring)
+			      struct intel_engine_cs *engine)
 {
 	struct page *page;
 	uint32_t *reg_state;
 	int j;
-	struct drm_i915_gem_object *ctx_obj = ctx->engine[ring->id].state;
+	struct drm_i915_gem_object *ctx_obj = ctx->engine[engine->id].state;
 	unsigned long ggtt_offset = 0;
 
 	if (ctx_obj == NULL) {
 		seq_printf(m, "Context on %s with no gem object\n",
-			   ring->name);
+			   engine->name);
 		return;
 	}
 
-	seq_printf(m, "CONTEXT: %s %u\n", ring->name,
-		   intel_execlists_ctx_id(ctx, ring));
+	seq_printf(m, "CONTEXT: %s %u\n", engine->name,
+		   intel_execlists_ctx_id(ctx, engine));
 
 	if (!i915_gem_obj_ggtt_bound(ctx_obj))
 		seq_puts(m, "\tNot bound in GGTT\n");
@@ -2043,9 +2086,9 @@ static int i915_dump_lrc(struct seq_file
 	struct drm_info_node *node = (struct drm_info_node *) m->private;
 	struct drm_device *dev = node->minor->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring;
+	struct intel_engine_cs *engine;
 	struct intel_context *ctx;
-	int ret, i;
+	int ret;
 
 	if (!i915.enable_execlists) {
 		seq_printf(m, "Logical Ring Contexts are disabled\n");
@@ -2058,8 +2101,8 @@ static int i915_dump_lrc(struct seq_file
 
 	list_for_each_entry(ctx, &dev_priv->context_list, link)
 		if (ctx != dev_priv->kernel_context)
-			for_each_ring(ring, dev_priv, i)
-				i915_dump_lrc_obj(m, ctx, ring);
+			for_each_engine(engine, dev_priv)
+				i915_dump_lrc_obj(m, ctx, engine);
 
 	mutex_unlock(&dev->struct_mutex);
 
@@ -2071,15 +2114,14 @@ static int i915_execlists(struct seq_fil
 	struct drm_info_node *node = (struct drm_info_node *)m->private;
 	struct drm_device *dev = node->minor->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring;
+	struct intel_engine_cs *engine;
 	u32 status_pointer;
 	u8 read_pointer;
 	u8 write_pointer;
 	u32 status;
 	u32 ctx_id;
 	struct list_head *cursor;
-	int ring_id, i;
-	int ret;
+	int i, ret;
 
 	if (!i915.enable_execlists) {
 		seq_puts(m, "Logical Ring Contexts are disabled\n");
@@ -2092,22 +2134,21 @@ static int i915_execlists(struct seq_fil
 
 	intel_runtime_pm_get(dev_priv);
 
-	for_each_ring(ring, dev_priv, ring_id) {
+	for_each_engine(engine, dev_priv) {
 		struct drm_i915_gem_request *head_req = NULL;
 		int count = 0;
-		unsigned long flags;
 
-		seq_printf(m, "%s\n", ring->name);
+		seq_printf(m, "%s\n", engine->name);
 
-		status = I915_READ(RING_EXECLIST_STATUS_LO(ring));
-		ctx_id = I915_READ(RING_EXECLIST_STATUS_HI(ring));
+		status = I915_READ(RING_EXECLIST_STATUS_LO(engine));
+		ctx_id = I915_READ(RING_EXECLIST_STATUS_HI(engine));
 		seq_printf(m, "\tExeclist status: 0x%08X, context: %u\n",
 			   status, ctx_id);
 
-		status_pointer = I915_READ(RING_CONTEXT_STATUS_PTR(ring));
+		status_pointer = I915_READ(RING_CONTEXT_STATUS_PTR(engine));
 		seq_printf(m, "\tStatus pointer: 0x%08X\n", status_pointer);
 
-		read_pointer = ring->next_context_status_buffer;
+		read_pointer = engine->next_context_status_buffer;
 		write_pointer = GEN8_CSB_WRITE_PTR(status_pointer);
 		if (read_pointer > write_pointer)
 			write_pointer += GEN8_CSB_ENTRIES;
@@ -2115,24 +2156,25 @@ static int i915_execlists(struct seq_fil
 			   read_pointer, write_pointer);
 
 		for (i = 0; i < GEN8_CSB_ENTRIES; i++) {
-			status = I915_READ(RING_CONTEXT_STATUS_BUF_LO(ring, i));
-			ctx_id = I915_READ(RING_CONTEXT_STATUS_BUF_HI(ring, i));
+			status = I915_READ(RING_CONTEXT_STATUS_BUF_LO(engine, i));
+			ctx_id = I915_READ(RING_CONTEXT_STATUS_BUF_HI(engine, i));
 
 			seq_printf(m, "\tStatus buffer %d: 0x%08X, context: %u\n",
 				   i, status, ctx_id);
 		}
 
-		spin_lock_irqsave(&ring->execlist_lock, flags);
-		list_for_each(cursor, &ring->execlist_queue)
+		spin_lock_bh(&engine->execlist_lock);
+		list_for_each(cursor, &engine->execlist_queue)
 			count++;
-		head_req = list_first_entry_or_null(&ring->execlist_queue,
-				struct drm_i915_gem_request, execlist_link);
-		spin_unlock_irqrestore(&ring->execlist_lock, flags);
+		head_req = list_first_entry_or_null(&engine->execlist_queue,
+						    struct drm_i915_gem_request,
+						    execlist_link);
+		spin_unlock_bh(&engine->execlist_lock);
 
 		seq_printf(m, "\t%d requests in queue\n", count);
 		if (head_req) {
 			seq_printf(m, "\tHead request id: %u\n",
-				   intel_execlists_ctx_id(head_req->ctx, ring));
+				   intel_execlists_ctx_id(head_req->ctx, engine));
 			seq_printf(m, "\tHead request tail: %u\n",
 				   head_req->tail);
 		}
@@ -2248,19 +2290,19 @@ static int per_file_ctx(int id, void *pt
 static void gen8_ppgtt_info(struct seq_file *m, struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring;
+	struct intel_engine_cs *engine;
 	struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
-	int unused, i;
+	int i;
 
 	if (!ppgtt)
 		return;
 
-	for_each_ring(ring, dev_priv, unused) {
-		seq_printf(m, "%s\n", ring->name);
+	for_each_engine(engine, dev_priv) {
+		seq_printf(m, "%s\n", engine->name);
 		for (i = 0; i < 4; i++) {
-			u64 pdp = I915_READ(GEN8_RING_PDP_UDW(ring, i));
+			u64 pdp = I915_READ(GEN8_RING_PDP_UDW(engine, i));
 			pdp <<= 32;
-			pdp |= I915_READ(GEN8_RING_PDP_LDW(ring, i));
+			pdp |= I915_READ(GEN8_RING_PDP_LDW(engine, i));
 			seq_printf(m, "\tPDP%d 0x%016llx\n", i, pdp);
 		}
 	}
@@ -2269,19 +2311,22 @@ static void gen8_ppgtt_info(struct seq_f
 static void gen6_ppgtt_info(struct seq_file *m, struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring;
-	int i;
+	struct intel_engine_cs *engine;
 
 	if (INTEL_INFO(dev)->gen == 6)
 		seq_printf(m, "GFX_MODE: 0x%08x\n", I915_READ(GFX_MODE));
 
-	for_each_ring(ring, dev_priv, i) {
-		seq_printf(m, "%s\n", ring->name);
+	for_each_engine(engine, dev_priv) {
+		seq_printf(m, "%s\n", engine->name);
 		if (INTEL_INFO(dev)->gen == 7)
-			seq_printf(m, "GFX_MODE: 0x%08x\n", I915_READ(RING_MODE_GEN7(ring)));
-		seq_printf(m, "PP_DIR_BASE: 0x%08x\n", I915_READ(RING_PP_DIR_BASE(ring)));
-		seq_printf(m, "PP_DIR_BASE_READ: 0x%08x\n", I915_READ(RING_PP_DIR_BASE_READ(ring)));
-		seq_printf(m, "PP_DIR_DCLV: 0x%08x\n", I915_READ(RING_PP_DIR_DCLV(ring)));
+			seq_printf(m, "GFX_MODE: 0x%08x\n",
+				   I915_READ(RING_MODE_GEN7(engine)));
+		seq_printf(m, "PP_DIR_BASE: 0x%08x\n",
+			   I915_READ(RING_PP_DIR_BASE(engine)));
+		seq_printf(m, "PP_DIR_BASE_READ: 0x%08x\n",
+			   I915_READ(RING_PP_DIR_BASE_READ(engine)));
+		seq_printf(m, "PP_DIR_DCLV: 0x%08x\n",
+			   I915_READ(RING_PP_DIR_DCLV(engine)));
 	}
 	if (dev_priv->mm.aliasing_ppgtt) {
 		struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
@@ -2312,6 +2357,7 @@ static int i915_ppgtt_info(struct seq_fi
 	else if (INTEL_INFO(dev)->gen >= 6)
 		gen6_ppgtt_info(m, dev);
 
+	mutex_lock(&dev->filelist_mutex);
 	list_for_each_entry_reverse(file, &dev->filelist, lhead) {
 		struct drm_i915_file_private *file_priv = file->driver_priv;
 		struct task_struct *task;
@@ -2319,15 +2365,16 @@ static int i915_ppgtt_info(struct seq_fi
 		task = get_pid_task(file->pid, PIDTYPE_PID);
 		if (!task) {
 			ret = -ESRCH;
-			goto out_put;
+			goto out_unlock;
 		}
 		seq_printf(m, "\nproc: %s\n", task->comm);
 		put_task_struct(task);
 		idr_for_each(&file_priv->context_idr, per_file_ctx,
 			     (void *)(unsigned long)m);
 	}
+out_unlock:
+	mutex_unlock(&dev->filelist_mutex);
 
-out_put:
 	intel_runtime_pm_put(dev_priv);
 	mutex_unlock(&dev->struct_mutex);
 
@@ -2336,12 +2383,11 @@ out_put:
 
 static int count_irq_waiters(struct drm_i915_private *i915)
 {
-	struct intel_engine_cs *ring;
+	struct intel_engine_cs *engine;
 	int count = 0;
-	int i;
 
-	for_each_ring(ring, i915, i)
-		count += ring->irq_refcount;
+	for_each_engine(engine, i915)
+		count += engine->irq_refcount;
 
 	return count;
 }
@@ -2362,6 +2408,8 @@ static int i915_rps_boost_info(struct se
 		   intel_gpu_freq(dev_priv, dev_priv->rps.min_freq_softlimit),
 		   intel_gpu_freq(dev_priv, dev_priv->rps.max_freq_softlimit),
 		   intel_gpu_freq(dev_priv, dev_priv->rps.max_freq));
+
+	mutex_lock(&dev->filelist_mutex);
 	spin_lock(&dev_priv->rps.client_lock);
 	list_for_each_entry_reverse(file, &dev->filelist, lhead) {
 		struct drm_i915_file_private *file_priv = file->driver_priv;
@@ -2384,6 +2432,7 @@ static int i915_rps_boost_info(struct se
 		   list_empty(&dev_priv->rps.mmioflips.link) ? "" : ", active");
 	seq_printf(m, "Kernel boosts: %d\n", dev_priv->rps.boosts);
 	spin_unlock(&dev_priv->rps.client_lock);
+	mutex_unlock(&dev->filelist_mutex);
 
 	return 0;
 }
@@ -2393,10 +2442,11 @@ static int i915_llc(struct seq_file *m,
 	struct drm_info_node *node = m->private;
 	struct drm_device *dev = node->minor->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	const bool edram = INTEL_GEN(dev_priv) > 8;
 
-	/* Size calculation for LLC is a bit of a pain. Ignore for now. */
 	seq_printf(m, "LLC: %s\n", yesno(HAS_LLC(dev)));
-	seq_printf(m, "eLLC: %zuMB\n", dev_priv->ellc_size);
+	seq_printf(m, "%s: %lluMB\n", edram ? "eDRAM" : "eLLC",
+		   intel_uncore_edram_size(dev_priv)/1024/1024);
 
 	return 0;
 }
@@ -2408,7 +2458,7 @@ static int i915_guc_load_status_info(str
 	struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
 	u32 tmp, i;
 
-	if (!HAS_GUC_UCODE(dev_priv->dev))
+	if (!HAS_GUC_UCODE(dev_priv))
 		return 0;
 
 	seq_printf(m, "GuC firmware status:\n");
@@ -2449,9 +2499,8 @@ static void i915_guc_client_info(struct
 				 struct drm_i915_private *dev_priv,
 				 struct i915_guc_client *client)
 {
-	struct intel_engine_cs *ring;
+	struct intel_engine_cs *engine;
 	uint64_t tot = 0;
-	uint32_t i;
 
 	seq_printf(m, "\tPriority %d, GuC ctx index: %u, PD offset 0x%x\n",
 		client->priority, client->ctx_index, client->proc_desc_offset);
@@ -2464,11 +2513,11 @@ static void i915_guc_client_info(struct
 	seq_printf(m, "\tFailed doorbell: %u\n", client->b_fail);
 	seq_printf(m, "\tLast submission result: %d\n", client->retcode);
 
-	for_each_ring(ring, dev_priv, i) {
+	for_each_engine(engine, dev_priv) {
 		seq_printf(m, "\tSubmissions: %llu %s\n",
-				client->submissions[ring->guc_id],
-				ring->name);
-		tot += client->submissions[ring->guc_id];
+				client->submissions[engine->guc_id],
+				engine->name);
+		tot += client->submissions[engine->guc_id];
 	}
 	seq_printf(m, "\tTotal: %llu\n", tot);
 }
@@ -2480,11 +2529,10 @@ static int i915_guc_info(struct seq_file
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_guc guc;
 	struct i915_guc_client client = {};
-	struct intel_engine_cs *ring;
-	enum intel_ring_id i;
+	struct intel_engine_cs *engine;
 	u64 total = 0;
 
-	if (!HAS_GUC_SCHED(dev_priv->dev))
+	if (!HAS_GUC_SCHED(dev_priv))
 		return 0;
 
 	if (mutex_lock_interruptible(&dev->struct_mutex))
@@ -2504,11 +2552,11 @@ static int i915_guc_info(struct seq_file
 	seq_printf(m, "GuC last action error code: %d\n", guc.action_err);
 
 	seq_printf(m, "\nGuC submissions:\n");
-	for_each_ring(ring, dev_priv, i) {
+	for_each_engine(engine, dev_priv) {
 		seq_printf(m, "\t%-24s: %10llu, last seqno 0x%08x\n",
-			ring->name, guc.submissions[ring->guc_id],
-			guc.last_seqno[ring->guc_id]);
-		total += guc.submissions[ring->guc_id];
+			engine->name, guc.submissions[engine->guc_id],
+			guc.last_seqno[engine->guc_id]);
+		total += guc.submissions[engine->guc_id];
 	}
 	seq_printf(m, "\t%s: %llu\n", "Total", total);
 
@@ -2688,10 +2736,8 @@ static int i915_runtime_pm_status(struct
 	struct drm_device *dev = node->minor->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	if (!HAS_RUNTIME_PM(dev)) {
-		seq_puts(m, "not supported\n");
-		return 0;
-	}
+	if (!HAS_RUNTIME_PM(dev_priv))
+		seq_puts(m, "Runtime power management not supported\n");
 
 	seq_printf(m, "GPU idle: %s\n", yesno(!dev_priv->mm.busy));
 	seq_printf(m, "IRQs disabled: %s\n",
@@ -2702,6 +2748,9 @@ static int i915_runtime_pm_status(struct
 #else
 	seq_printf(m, "Device Power Management (CONFIG_PM) disabled\n");
 #endif
+	seq_printf(m, "PCI device power state: %s [%d]\n",
+		   pci_power_name(dev_priv->dev->pdev->current_state),
+		   dev_priv->dev->pdev->current_state);
 
 	return 0;
 }
@@ -3114,9 +3163,10 @@ static int i915_semaphore_status(struct
 	struct drm_info_node *node = (struct drm_info_node *) m->private;
 	struct drm_device *dev = node->minor->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring;
+	struct intel_engine_cs *engine;
 	int num_rings = hweight32(INTEL_INFO(dev)->ring_mask);
-	int i, j, ret;
+	enum intel_engine_id id;
+	int j, ret;
 
 	if (!i915_semaphore_is_enabled(dev)) {
 		seq_puts(m, "Semaphores are disabled\n");
@@ -3135,14 +3185,14 @@ static int i915_semaphore_status(struct
 		page = i915_gem_object_get_page(dev_priv->semaphore_obj, 0);
 
 		seqno = (uint64_t *)kmap_atomic(page);
-		for_each_ring(ring, dev_priv, i) {
+		for_each_engine_id(engine, dev_priv, id) {
 			uint64_t offset;
 
-			seq_printf(m, "%s\n", ring->name);
+			seq_printf(m, "%s\n", engine->name);
 
 			seq_puts(m, "  Last signal:");
 			for (j = 0; j < num_rings; j++) {
-				offset = i * I915_NUM_RINGS + j;
+				offset = id * I915_NUM_ENGINES + j;
 				seq_printf(m, "0x%08llx (0x%02llx) ",
 					   seqno[offset], offset * 8);
 			}
@@ -3150,7 +3200,7 @@ static int i915_semaphore_status(struct
 
 			seq_puts(m, "  Last wait:  ");
 			for (j = 0; j < num_rings; j++) {
-				offset = i + (j * I915_NUM_RINGS);
+				offset = id + (j * I915_NUM_ENGINES);
 				seq_printf(m, "0x%08llx (0x%02llx) ",
 					   seqno[offset], offset * 8);
 			}
@@ -3160,18 +3210,18 @@ static int i915_semaphore_status(struct
 		kunmap_atomic(seqno);
 	} else {
 		seq_puts(m, "  Last signal:");
-		for_each_ring(ring, dev_priv, i)
+		for_each_engine(engine, dev_priv)
 			for (j = 0; j < num_rings; j++)
 				seq_printf(m, "0x%08x\n",
-					   I915_READ(ring->semaphore.mbox.signal[j]));
+					   I915_READ(engine->semaphore.mbox.signal[j]));
 		seq_putc(m, '\n');
 	}
 
 	seq_puts(m, "\nSync seqno:\n");
-	for_each_ring(ring, dev_priv, i) {
-		for (j = 0; j < num_rings; j++) {
-			seq_printf(m, "  0x%08x ", ring->semaphore.sync_seqno[j]);
-		}
+	for_each_engine(engine, dev_priv) {
+		for (j = 0; j < num_rings; j++)
+			seq_printf(m, "  0x%08x ",
+				   engine->semaphore.sync_seqno[j]);
 		seq_putc(m, '\n');
 	}
 	seq_putc(m, '\n');
@@ -3193,8 +3243,8 @@ static int i915_shared_dplls_info(struct
 		struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i];
 
 		seq_printf(m, "DPLL%i: %s, id: %i\n", i, pll->name, pll->id);
-		seq_printf(m, " crtc_mask: 0x%08x, active: %d, on: %s\n",
-			   pll->config.crtc_mask, pll->active, yesno(pll->on));
+		seq_printf(m, " crtc_mask: 0x%08x, active: 0x%x, on: %s\n",
+			   pll->config.crtc_mask, pll->active_mask, yesno(pll->on));
 		seq_printf(m, " tracked hardware state:\n");
 		seq_printf(m, " dpll:    0x%08x\n", pll->config.hw_state.dpll);
 		seq_printf(m, " dpll_md: 0x%08x\n",
@@ -3212,11 +3262,12 @@ static int i915_wa_registers(struct seq_
 {
 	int i;
 	int ret;
-	struct intel_engine_cs *ring;
+	struct intel_engine_cs *engine;
 	struct drm_info_node *node = (struct drm_info_node *) m->private;
 	struct drm_device *dev = node->minor->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct i915_workarounds *workarounds = &dev_priv->workarounds;
+	enum intel_engine_id id;
 
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
@@ -3225,9 +3276,9 @@ static int i915_wa_registers(struct seq_
 	intel_runtime_pm_get(dev_priv);
 
 	seq_printf(m, "Workarounds applied: %d\n", workarounds->count);
-	for_each_ring(ring, dev_priv, i)
+	for_each_engine_id(engine, dev_priv, id)
 		seq_printf(m, "HW whitelist count for %s: %d\n",
-			   ring->name, workarounds->hw_whitelist_count[i]);
+			   engine->name, workarounds->hw_whitelist_count[id]);
 	for (i = 0; i < workarounds->count; ++i) {
 		i915_reg_t addr;
 		u32 mask, value, read;
@@ -3417,7 +3468,8 @@ static int i915_dp_mst_info(struct seq_f
 		intel_dig_port = enc_to_dig_port(encoder);
 		if (!intel_dig_port->dp.can_mst)
 			continue;
-
+		seq_printf(m, "MST Source Port %c\n",
+			   port_name(intel_dig_port->port));
 		drm_dp_mst_dump_topology(m, &intel_dig_port->dp.mst_mgr);
 	}
 	drm_modeset_unlock_all(dev);
@@ -4693,7 +4745,7 @@ i915_wedged_get(void *data, u64 *val)
 	struct drm_device *dev = data;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	*val = atomic_read(&dev_priv->gpu_error.reset_counter);
+	*val = i915_terminally_wedged(&dev_priv->gpu_error);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_dma.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_dma.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_dma.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_dma.c	2016-07-24 15:23:50.000000000 -0400
@@ -50,6 +50,66 @@
 #include <linux/pm_runtime.h>
 #include <linux/oom.h>
 
+static unsigned int i915_load_fail_count;
+
+bool __i915_inject_load_failure(const char *func, int line)
+{
+	if (i915_load_fail_count >= i915.inject_load_failure)
+		return false;
+
+	if (++i915_load_fail_count == i915.inject_load_failure) {
+		DRM_INFO("Injecting failure at checkpoint %u [%s:%d]\n",
+			 i915.inject_load_failure, func, line);
+		return true;
+	}
+
+	return false;
+}
+
+#define FDO_BUG_URL "https://bugs.freedesktop.org/enter_bug.cgi?product=DRI"
+#define FDO_BUG_MSG "Please file a bug at " FDO_BUG_URL " against DRM/Intel " \
+		    "providing the dmesg log by booting with drm.debug=0xf"
+
+void
+__i915_printk(struct drm_i915_private *dev_priv, const char *level,
+	      const char *fmt, ...)
+{
+	static bool shown_bug_once;
+	struct device *dev = dev_priv->dev->dev;
+	bool is_error = level[1] <= KERN_ERR[1];
+	bool is_debug = level[1] == KERN_DEBUG[1];
+	struct va_format vaf;
+	va_list args;
+
+	if (is_debug && !(drm_debug & DRM_UT_DRIVER))
+		return;
+
+	va_start(args, fmt);
+
+	vaf.fmt = fmt;
+	vaf.va = &args;
+
+	dev_printk(level, dev, "[" DRM_NAME ":%ps] %pV",
+		   __builtin_return_address(0), &vaf);
+
+	if (is_error && !shown_bug_once) {
+		dev_notice(dev, "%s", FDO_BUG_MSG);
+		shown_bug_once = true;
+	}
+
+	va_end(args);
+}
+
+static bool i915_error_injected(struct drm_i915_private *dev_priv)
+{
+	return i915.inject_load_failure &&
+	       i915_load_fail_count == i915.inject_load_failure;
+}
+
+#define i915_load_error(dev_priv, fmt, ...)				     \
+	__i915_printk(dev_priv,						     \
+		      i915_error_injected(dev_priv) ? KERN_DEBUG : KERN_ERR, \
+		      fmt, ##__VA_ARGS__)
 
 static int i915_getparam(struct drm_device *dev, void *data,
 			 struct drm_file *file_priv)
@@ -87,16 +147,16 @@ static int i915_getparam(struct drm_devi
 		value = 1;
 		break;
 	case I915_PARAM_HAS_BSD:
-		value = intel_ring_initialized(&dev_priv->ring[VCS]);
+		value = intel_engine_initialized(&dev_priv->engine[VCS]);
 		break;
 	case I915_PARAM_HAS_BLT:
-		value = intel_ring_initialized(&dev_priv->ring[BCS]);
+		value = intel_engine_initialized(&dev_priv->engine[BCS]);
 		break;
 	case I915_PARAM_HAS_VEBOX:
-		value = intel_ring_initialized(&dev_priv->ring[VECS]);
+		value = intel_engine_initialized(&dev_priv->engine[VECS]);
 		break;
 	case I915_PARAM_HAS_BSD2:
-		value = intel_ring_initialized(&dev_priv->ring[VCS2]);
+		value = intel_engine_initialized(&dev_priv->engine[VCS2]);
 		break;
 	case I915_PARAM_HAS_RELAXED_FENCING:
 		value = 1;
@@ -197,13 +257,6 @@ static int i915_get_bridge_dev(struct dr
 	return 0;
 }
 
-#define MCHBAR_I915 0x44
-#define MCHBAR_I965 0x48
-#define MCHBAR_SIZE (4*4096)
-
-#define DEVEN_REG 0x54
-#define   DEVEN_MCHBAR_EN (1 << 28)
-
 /* Allocate space for the MCH regs if needed, return nonzero on error */
 static int
 intel_alloc_mchbar_resource(struct drm_device *dev)
@@ -265,7 +318,7 @@ intel_setup_mchbar(struct drm_device *de
 	dev_priv->mchbar_need_disable = false;
 
 	if (IS_I915G(dev) || IS_I915GM(dev)) {
-		pci_read_config_dword(dev_priv->bridge_dev, DEVEN_REG, &temp);
+		pci_read_config_dword(dev_priv->bridge_dev, DEVEN, &temp);
 		enabled = !!(temp & DEVEN_MCHBAR_EN);
 	} else {
 		pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
@@ -283,7 +336,7 @@ intel_setup_mchbar(struct drm_device *de
 
 	/* Space is allocated or reserved, so enable it. */
 	if (IS_I915G(dev) || IS_I915GM(dev)) {
-		pci_write_config_dword(dev_priv->bridge_dev, DEVEN_REG,
+		pci_write_config_dword(dev_priv->bridge_dev, DEVEN,
 				       temp | DEVEN_MCHBAR_EN);
 	} else {
 		pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
@@ -296,17 +349,24 @@ intel_teardown_mchbar(struct drm_device
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int mchbar_reg = INTEL_INFO(dev)->gen >= 4 ? MCHBAR_I965 : MCHBAR_I915;
-	u32 temp;
 
 	if (dev_priv->mchbar_need_disable) {
 		if (IS_I915G(dev) || IS_I915GM(dev)) {
-			pci_read_config_dword(dev_priv->bridge_dev, DEVEN_REG, &temp);
-			temp &= ~DEVEN_MCHBAR_EN;
-			pci_write_config_dword(dev_priv->bridge_dev, DEVEN_REG, temp);
+			u32 deven_val;
+
+			pci_read_config_dword(dev_priv->bridge_dev, DEVEN,
+					      &deven_val);
+			deven_val &= ~DEVEN_MCHBAR_EN;
+			pci_write_config_dword(dev_priv->bridge_dev, DEVEN,
+					       deven_val);
 		} else {
-			pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
-			temp &= ~1;
-			pci_write_config_dword(dev_priv->bridge_dev, mchbar_reg, temp);
+			u32 mchbar_val;
+
+			pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg,
+					      &mchbar_val);
+			mchbar_val &= ~1;
+			pci_write_config_dword(dev_priv->bridge_dev, mchbar_reg,
+					       mchbar_val);
 		}
 	}
 
@@ -370,6 +430,9 @@ static int i915_load_modeset_init(struct
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int ret;
 
+	if (i915_inject_load_failure())
+		return -ENODEV;
+
 	ret = intel_bios_init(dev_priv);
 	if (ret)
 		DRM_INFO("failed to find VBIOS tables\n");
@@ -413,9 +476,6 @@ static int i915_load_modeset_init(struct
 
 	intel_modeset_gem_init(dev);
 
-	/* Always safe in the mode setting case. */
-	/* FIXME: do pre/post-mode set stuff in core KMS code */
-	dev->vblank_disable_allowed = true;
 	if (INTEL_INFO(dev)->num_pipes == 0)
 		return 0;
 
@@ -444,7 +504,7 @@ static int i915_load_modeset_init(struct
 
 cleanup_gem:
 	mutex_lock(&dev->struct_mutex);
-	i915_gem_cleanup_ringbuffer(dev);
+	i915_gem_cleanup_engines(dev);
 	i915_gem_context_fini(dev);
 	mutex_unlock(&dev->struct_mutex);
 cleanup_irq:
@@ -453,6 +513,7 @@ cleanup_irq:
 	intel_teardown_gmbus(dev);
 cleanup_csr:
 	intel_csr_ucode_fini(dev_priv);
+	intel_power_domains_fini(dev_priv);
 	vga_switcheroo_unregister_client(dev->pdev);
 cleanup_vga_client:
 	vga_client_register(dev->pdev, NULL, NULL, NULL);
@@ -465,6 +526,7 @@ static int i915_kick_out_firmware_fb(str
 {
 	struct apertures_struct *ap;
 	struct pci_dev *pdev = dev_priv->dev->pdev;
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	bool primary;
 	int ret;
 
@@ -472,8 +534,8 @@ static int i915_kick_out_firmware_fb(str
 	if (!ap)
 		return -ENOMEM;
 
-	ap->ranges[0].base = dev_priv->gtt.mappable_base;
-	ap->ranges[0].size = dev_priv->gtt.mappable_end;
+	ap->ranges[0].base = ggtt->mappable_base;
+	ap->ranges[0].size = ggtt->mappable_end;
 
 	primary =
 		pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
@@ -853,6 +915,10 @@ static void intel_device_info_runtime_in
 	else if (INTEL_INFO(dev)->gen >= 9)
 		gen9_sseu_info_init(dev);
 
+	/* Snooping is broken on BXT A stepping. */
+	info->has_snoop = !info->has_llc;
+	info->has_snoop &= !IS_BXT_REVID(dev, 0, BXT_REVID_A1);
+
 	DRM_DEBUG_DRIVER("slice total: %u\n", info->slice_total);
 	DRM_DEBUG_DRIVER("subslice total: %u\n", info->subslice_total);
 	DRM_DEBUG_DRIVER("subslice per slice: %u\n", info->subslice_per_slice);
@@ -929,6 +995,84 @@ static void i915_workqueues_cleanup(stru
 	destroy_workqueue(dev_priv->wq);
 }
 
+/**
+ * i915_driver_init_early - setup state not requiring device access
+ * @dev_priv: device private
+ *
+ * Initialize everything that is a "SW-only" state, that is state not
+ * requiring accessing the device or exposing the driver via kernel internal
+ * or userspace interfaces. Example steps belonging here: lock initialization,
+ * system memory allocation, setting up device specific attributes and
+ * function hooks not requiring accessing the device.
+ */
+static int i915_driver_init_early(struct drm_i915_private *dev_priv,
+				  struct drm_device *dev,
+				  struct intel_device_info *info)
+{
+	struct intel_device_info *device_info;
+	int ret = 0;
+
+	if (i915_inject_load_failure())
+		return -ENODEV;
+
+	/* Setup the write-once "constant" device info */
+	device_info = (struct intel_device_info *)&dev_priv->info;
+	memcpy(device_info, info, sizeof(dev_priv->info));
+	device_info->device_id = dev->pdev->device;
+
+	spin_lock_init(&dev_priv->irq_lock);
+	spin_lock_init(&dev_priv->gpu_error.lock);
+	mutex_init(&dev_priv->backlight_lock);
+	spin_lock_init(&dev_priv->uncore.lock);
+	spin_lock_init(&dev_priv->mm.object_stat_lock);
+	spin_lock_init(&dev_priv->mmio_flip_lock);
+	mutex_init(&dev_priv->sb_lock);
+	mutex_init(&dev_priv->modeset_restore_lock);
+	mutex_init(&dev_priv->av_mutex);
+	mutex_init(&dev_priv->wm.wm_mutex);
+	mutex_init(&dev_priv->pps_mutex);
+
+	ret = i915_workqueues_init(dev_priv);
+	if (ret < 0)
+		return ret;
+
+	/* This must be called before any calls to HAS_PCH_* */
+	intel_detect_pch(dev);
+
+	intel_pm_setup(dev);
+	intel_init_dpio(dev_priv);
+	intel_power_domains_init(dev_priv);
+	intel_irq_init(dev_priv);
+	intel_init_display_hooks(dev_priv);
+	intel_init_clock_gating_hooks(dev_priv);
+	intel_init_audio_hooks(dev_priv);
+	i915_gem_load_init(dev);
+
+	intel_display_crc_init(dev);
+
+	i915_dump_device_info(dev_priv);
+
+	/* Not all pre-production machines fall into this category, only the
+	 * very first ones. Almost everything should work, except for maybe
+	 * suspend/resume. And we don't implement workarounds that affect only
+	 * pre-production machines. */
+	if (IS_HSW_EARLY_SDV(dev))
+		DRM_INFO("This is an early pre-production Haswell machine. "
+			 "It may not be fully functional.\n");
+
+	return 0;
+}
+
+/**
+ * i915_driver_cleanup_early - cleanup the setup done in i915_driver_init_early()
+ * @dev_priv: device private
+ */
+static void i915_driver_cleanup_early(struct drm_i915_private *dev_priv)
+{
+	i915_gem_load_cleanup(dev_priv->dev);
+	i915_workqueues_cleanup(dev_priv);
+}
+
 static int i915_mmio_setup(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
@@ -970,97 +1114,93 @@ static void i915_mmio_cleanup(struct drm
 }
 
 /**
- * i915_driver_load - setup chip and create an initial config
- * @dev: DRM device
- * @flags: startup flags
+ * i915_driver_init_mmio - setup device MMIO
+ * @dev_priv: device private
  *
- * The driver load routine has to do several things:
- *   - drive output discovery via intel_modeset_init()
- *   - initialize the memory manager
- *   - allocate initial config memory
- *   - setup the DRM framebuffer with the allocated memory
+ * Setup minimal device state necessary for MMIO accesses later in the
+ * initialization sequence. The setup here should avoid any other device-wide
+ * side effects or exposing the driver via kernel internal or user space
+ * interfaces.
  */
-int i915_driver_load(struct drm_device *dev, unsigned long flags)
+static int i915_driver_init_mmio(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv;
-	struct intel_device_info *info, *device_info;
-	int ret = 0;
-	uint32_t aperture_size;
-
-	info = (struct intel_device_info *) flags;
-
-	dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
-	if (dev_priv == NULL)
-		return -ENOMEM;
-
-	dev->dev_private = dev_priv;
-	dev_priv->dev = dev;
+	struct drm_device *dev = dev_priv->dev;
+	int ret;
 
-	/* Setup the write-once "constant" device info */
-	device_info = (struct intel_device_info *)&dev_priv->info;
-	memcpy(device_info, info, sizeof(dev_priv->info));
-	device_info->device_id = dev->pdev->device;
+	if (i915_inject_load_failure())
+		return -ENODEV;
 
-	spin_lock_init(&dev_priv->irq_lock);
-	spin_lock_init(&dev_priv->gpu_error.lock);
-	mutex_init(&dev_priv->backlight_lock);
-	spin_lock_init(&dev_priv->uncore.lock);
-	spin_lock_init(&dev_priv->mm.object_stat_lock);
-	spin_lock_init(&dev_priv->mmio_flip_lock);
-	mutex_init(&dev_priv->sb_lock);
-	mutex_init(&dev_priv->modeset_restore_lock);
-	mutex_init(&dev_priv->av_mutex);
+	if (i915_get_bridge_dev(dev))
+		return -EIO;
 
-	ret = i915_workqueues_init(dev_priv);
+	ret = i915_mmio_setup(dev);
 	if (ret < 0)
-		goto out_free_priv;
+		goto put_bridge;
 
-	intel_pm_setup(dev);
+	intel_uncore_init(dev);
 
-	intel_runtime_pm_get(dev_priv);
+	return 0;
 
-	intel_display_crc_init(dev);
+put_bridge:
+	pci_dev_put(dev_priv->bridge_dev);
 
-	i915_dump_device_info(dev_priv);
+	return ret;
+}
 
-	/* Not all pre-production machines fall into this category, only the
-	 * very first ones. Almost everything should work, except for maybe
-	 * suspend/resume. And we don't implement workarounds that affect only
-	 * pre-production machines. */
-	if (IS_HSW_EARLY_SDV(dev))
-		DRM_INFO("This is an early pre-production Haswell machine. "
-			 "It may not be fully functional.\n");
+/**
+ * i915_driver_cleanup_mmio - cleanup the setup done in i915_driver_init_mmio()
+ * @dev_priv: device private
+ */
+static void i915_driver_cleanup_mmio(struct drm_i915_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
 
-	if (i915_get_bridge_dev(dev)) {
-		ret = -EIO;
-		goto out_runtime_pm_put;
-	}
+	intel_uncore_fini(dev);
+	i915_mmio_cleanup(dev);
+	pci_dev_put(dev_priv->bridge_dev);
+}
 
-	ret = i915_mmio_setup(dev);
-	if (ret < 0)
-		goto put_bridge;
+/**
+ * i915_driver_init_hw - setup state requiring device access
+ * @dev_priv: device private
+ *
+ * Setup state that requires accessing the device, but doesn't require
+ * exposing the driver via kernel internal or userspace interfaces.
+ */
+static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
+	uint32_t aperture_size;
+	int ret;
 
-	/* This must be called before any calls to HAS_PCH_* */
-	intel_detect_pch(dev);
+	if (i915_inject_load_failure())
+		return -ENODEV;
 
-	intel_uncore_init(dev);
+	intel_device_info_runtime_init(dev);
 
-	ret = i915_gem_gtt_init(dev);
+	ret = i915_ggtt_init_hw(dev);
 	if (ret)
-		goto out_uncore_fini;
+		return ret;
+
+	ret = i915_ggtt_enable_hw(dev);
+	if (ret) {
+		DRM_ERROR("failed to enable GGTT\n");
+		goto out_ggtt;
+	}
 
 	/* WARNING: Apparently we must kick fbdev drivers before vgacon,
 	 * otherwise the vga fbdev driver falls over. */
 	ret = i915_kick_out_firmware_fb(dev_priv);
 	if (ret) {
 		DRM_ERROR("failed to remove conflicting framebuffer drivers\n");
-		goto out_gtt;
+		goto out_ggtt;
 	}
 
 	ret = i915_kick_out_vgacon(dev_priv);
 	if (ret) {
 		DRM_ERROR("failed to remove conflicting VGA console\n");
-		goto out_gtt;
+		goto out_ggtt;
 	}
 
 	pci_set_master(dev->pdev);
@@ -1080,26 +1220,27 @@ int i915_driver_load(struct drm_device *
 	if (IS_BROADWATER(dev) || IS_CRESTLINE(dev))
 		dma_set_coherent_mask(&dev->pdev->dev, DMA_BIT_MASK(32));
 
-	aperture_size = dev_priv->gtt.mappable_end;
+	aperture_size = ggtt->mappable_end;
 
-	dev_priv->gtt.mappable =
-		io_mapping_create_wc(dev_priv->gtt.mappable_base,
+	ggtt->mappable =
+		io_mapping_create_wc(ggtt->mappable_base,
 				     aperture_size);
-	if (dev_priv->gtt.mappable == NULL) {
+	if (!ggtt->mappable) {
 		ret = -EIO;
-		goto out_gtt;
+		goto out_ggtt;
 	}
 
-	dev_priv->gtt.mtrr = arch_phys_wc_add(dev_priv->gtt.mappable_base,
+	ggtt->mtrr = arch_phys_wc_add(ggtt->mappable_base,
 					      aperture_size);
 
-	intel_irq_init(dev_priv);
+	pm_qos_add_request(&dev_priv->pm_qos, PM_QOS_CPU_DMA_LATENCY,
+			   PM_QOS_DEFAULT_VALUE);
+
 	intel_uncore_sanitize(dev);
 
 	intel_opregion_setup(dev);
 
-	i915_gem_load_init(dev);
-	i915_gem_shrinker_init(dev_priv);
+	i915_gem_load_init_fences(dev_priv);
 
 	/* On the 945G/GM, the chipset reports the MSI capability on the
 	 * integrated graphics even though the support isn't actually there
@@ -1117,24 +1258,44 @@ int i915_driver_load(struct drm_device *
 			DRM_DEBUG_DRIVER("can't enable MSI");
 	}
 
-	intel_device_info_runtime_init(dev);
+	return 0;
 
-	intel_init_dpio(dev_priv);
+out_ggtt:
+	i915_ggtt_cleanup_hw(dev);
 
-	if (INTEL_INFO(dev)->num_pipes) {
-		ret = drm_vblank_init(dev, INTEL_INFO(dev)->num_pipes);
-		if (ret)
-			goto out_gem_unload;
-	}
+	return ret;
+}
 
-	intel_power_domains_init(dev_priv);
+/**
+ * i915_driver_cleanup_hw - cleanup the setup done in i915_driver_init_hw()
+ * @dev_priv: device private
+ */
+static void i915_driver_cleanup_hw(struct drm_i915_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 
-	ret = i915_load_modeset_init(dev);
-	if (ret < 0) {
-		DRM_ERROR("failed to init modeset\n");
-		goto out_power_well;
-	}
+	if (dev->pdev->msi_enabled)
+		pci_disable_msi(dev->pdev);
+
+	pm_qos_remove_request(&dev_priv->pm_qos);
+	arch_phys_wc_del(ggtt->mtrr);
+	io_mapping_free(ggtt->mappable);
+	i915_ggtt_cleanup_hw(dev);
+}
+
+/**
+ * i915_driver_register - register the driver with the rest of the system
+ * @dev_priv: device private
+ *
+ * Perform any steps necessary to make the driver available via kernel
+ * internal or userspace interfaces.
+ */
+static void i915_driver_register(struct drm_i915_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
 
+	i915_gem_shrinker_init(dev_priv);
 	/*
 	 * Notify a valid surface after modesetting,
 	 * when running inside a VM.
@@ -1144,48 +1305,107 @@ int i915_driver_load(struct drm_device *
 
 	i915_setup_sysfs(dev);
 
-	if (INTEL_INFO(dev)->num_pipes) {
+	if (INTEL_INFO(dev_priv)->num_pipes) {
 		/* Must be done after probing outputs */
 		intel_opregion_init(dev);
 		acpi_video_register();
 	}
 
-	if (IS_GEN5(dev))
+	if (IS_GEN5(dev_priv))
 		intel_gpu_ips_init(dev_priv);
 
-	intel_runtime_pm_enable(dev_priv);
-
 	i915_audio_component_init(dev_priv);
+}
+
+/**
+ * i915_driver_unregister - cleanup the registration done in i915_driver_regiser()
+ * @dev_priv: device private
+ */
+static void i915_driver_unregister(struct drm_i915_private *dev_priv)
+{
+	i915_audio_component_cleanup(dev_priv);
+	intel_gpu_ips_teardown();
+	acpi_video_unregister();
+	intel_opregion_fini(dev_priv->dev);
+	i915_teardown_sysfs(dev_priv->dev);
+	i915_gem_shrinker_cleanup(dev_priv);
+}
+
+/**
+ * i915_driver_load - setup chip and create an initial config
+ * @dev: DRM device
+ * @flags: startup flags
+ *
+ * The driver load routine has to do several things:
+ *   - drive output discovery via intel_modeset_init()
+ *   - initialize the memory manager
+ *   - allocate initial config memory
+ *   - setup the DRM framebuffer with the allocated memory
+ */
+int i915_driver_load(struct drm_device *dev, unsigned long flags)
+{
+	struct drm_i915_private *dev_priv;
+	int ret = 0;
+
+	dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
+	if (dev_priv == NULL)
+		return -ENOMEM;
+
+	dev->dev_private = dev_priv;
+	/* Must be set before calling __i915_printk */
+	dev_priv->dev = dev;
+
+	ret = i915_driver_init_early(dev_priv, dev,
+				     (struct intel_device_info *)flags);
+
+	if (ret < 0)
+		goto out_free_priv;
+
+	intel_runtime_pm_get(dev_priv);
+
+	ret = i915_driver_init_mmio(dev_priv);
+	if (ret < 0)
+		goto out_runtime_pm_put;
+
+	ret = i915_driver_init_hw(dev_priv);
+	if (ret < 0)
+		goto out_cleanup_mmio;
+
+	/*
+	 * TODO: move the vblank init and parts of modeset init steps into one
+	 * of the i915_driver_init_/i915_driver_register functions according
+	 * to the role/effect of the given init step.
+	 */
+	if (INTEL_INFO(dev)->num_pipes) {
+		ret = drm_vblank_init(dev, INTEL_INFO(dev)->num_pipes);
+		if (ret)
+			goto out_cleanup_hw;
+	}
+
+	ret = i915_load_modeset_init(dev);
+	if (ret < 0)
+		goto out_cleanup_vblank;
+
+	i915_driver_register(dev_priv);
+
+	intel_runtime_pm_enable(dev_priv);
 
 	intel_runtime_pm_put(dev_priv);
 
 	return 0;
 
-out_power_well:
-	intel_power_domains_fini(dev_priv);
+out_cleanup_vblank:
 	drm_vblank_cleanup(dev);
-out_gem_unload:
-	i915_gem_shrinker_cleanup(dev_priv);
-
-	if (dev->pdev->msi_enabled)
-		pci_disable_msi(dev->pdev);
-
-	intel_teardown_mchbar(dev);
-	pm_qos_remove_request(&dev_priv->pm_qos);
-	arch_phys_wc_del(dev_priv->gtt.mtrr);
-	io_mapping_free(dev_priv->gtt.mappable);
-out_gtt:
-	i915_global_gtt_cleanup(dev);
-out_uncore_fini:
-	intel_uncore_fini(dev);
-	i915_mmio_cleanup(dev);
-put_bridge:
-	pci_dev_put(dev_priv->bridge_dev);
-	i915_gem_load_cleanup(dev);
+out_cleanup_hw:
+	i915_driver_cleanup_hw(dev_priv);
+out_cleanup_mmio:
+	i915_driver_cleanup_mmio(dev_priv);
 out_runtime_pm_put:
 	intel_runtime_pm_put(dev_priv);
-	i915_workqueues_cleanup(dev_priv);
+	i915_driver_cleanup_early(dev_priv);
 out_free_priv:
+	i915_load_error(dev_priv, "Device initialization failed (%d)\n", ret);
+
 	kfree(dev_priv);
 
 	return ret;
@@ -1198,26 +1418,15 @@ int i915_driver_unload(struct drm_device
 
 	intel_fbdev_fini(dev);
 
-	i915_audio_component_cleanup(dev_priv);
-
 	ret = i915_gem_suspend(dev);
 	if (ret) {
 		DRM_ERROR("failed to idle hardware: %d\n", ret);
 		return ret;
 	}
 
-	intel_power_domains_fini(dev_priv);
-
-	intel_gpu_ips_teardown();
-
-	i915_teardown_sysfs(dev);
-
-	i915_gem_shrinker_cleanup(dev_priv);
-
-	io_mapping_free(dev_priv->gtt.mappable);
-	arch_phys_wc_del(dev_priv->gtt.mtrr);
+	intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
 
-	acpi_video_unregister();
+	i915_driver_unregister(dev_priv);
 
 	drm_vblank_cleanup(dev);
 
@@ -1246,31 +1455,24 @@ int i915_driver_unload(struct drm_device
 	cancel_delayed_work_sync(&dev_priv->gpu_error.hangcheck_work);
 	i915_destroy_error_state(dev);
 
-	if (dev->pdev->msi_enabled)
-		pci_disable_msi(dev->pdev);
-
-	intel_opregion_fini(dev);
-
 	/* Flush any outstanding unpin_work. */
 	flush_workqueue(dev_priv->wq);
 
 	intel_guc_ucode_fini(dev);
 	mutex_lock(&dev->struct_mutex);
-	i915_gem_cleanup_ringbuffer(dev);
+	i915_gem_cleanup_engines(dev);
 	i915_gem_context_fini(dev);
 	mutex_unlock(&dev->struct_mutex);
 	intel_fbc_cleanup_cfb(dev_priv);
 
-	pm_qos_remove_request(&dev_priv->pm_qos);
+	intel_power_domains_fini(dev_priv);
 
-	i915_global_gtt_cleanup(dev);
+	i915_driver_cleanup_hw(dev_priv);
+	i915_driver_cleanup_mmio(dev_priv);
 
-	intel_uncore_fini(dev);
-	i915_mmio_cleanup(dev);
+	intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
 
-	i915_gem_load_cleanup(dev);
-	pci_dev_put(dev_priv->bridge_dev);
-	i915_workqueues_cleanup(dev_priv);
+	i915_driver_cleanup_early(dev_priv);
 	kfree(dev_priv);
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_drv.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_drv.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_drv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_drv.c	2016-07-24 15:23:50.000000000 -0400
@@ -66,6 +66,11 @@ static struct drm_driver driver;
 #define IVB_CURSOR_OFFSETS \
 	.cursor_offsets = { CURSOR_A_OFFSET, IVB_CURSOR_B_OFFSET, IVB_CURSOR_C_OFFSET }
 
+#define BDW_COLORS \
+	.color = { .degamma_lut_size = 512, .gamma_lut_size = 512 }
+#define CHV_COLORS \
+	.color = { .degamma_lut_size = 65, .gamma_lut_size = 257 }
+
 static const struct intel_device_info intel_i830_info = {
 	.gen = 2, .is_mobile = 1, .cursor_needs_physical = 1, .num_pipes = 2,
 	.has_overlay = 1, .overlay_needs_physical = 1,
@@ -288,24 +293,28 @@ static const struct intel_device_info in
 	.is_mobile = 1,
 };
 
+#define BDW_FEATURES \
+	HSW_FEATURES, \
+	BDW_COLORS
+
 static const struct intel_device_info intel_broadwell_d_info = {
-	HSW_FEATURES,
+	BDW_FEATURES,
 	.gen = 8,
 };
 
 static const struct intel_device_info intel_broadwell_m_info = {
-	HSW_FEATURES,
+	BDW_FEATURES,
 	.gen = 8, .is_mobile = 1,
 };
 
 static const struct intel_device_info intel_broadwell_gt3d_info = {
-	HSW_FEATURES,
+	BDW_FEATURES,
 	.gen = 8,
 	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
 };
 
 static const struct intel_device_info intel_broadwell_gt3m_info = {
-	HSW_FEATURES,
+	BDW_FEATURES,
 	.gen = 8, .is_mobile = 1,
 	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
 };
@@ -318,16 +327,17 @@ static const struct intel_device_info in
 	.display_mmio_offset = VLV_DISPLAY_BASE,
 	GEN_CHV_PIPEOFFSETS,
 	CURSOR_OFFSETS,
+	CHV_COLORS,
 };
 
 static const struct intel_device_info intel_skylake_info = {
-	HSW_FEATURES,
+	BDW_FEATURES,
 	.is_skylake = 1,
 	.gen = 9,
 };
 
 static const struct intel_device_info intel_skylake_gt3_info = {
-	HSW_FEATURES,
+	BDW_FEATURES,
 	.is_skylake = 1,
 	.gen = 9,
 	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
@@ -345,18 +355,17 @@ static const struct intel_device_info in
 	.has_fbc = 1,
 	GEN_DEFAULT_PIPEOFFSETS,
 	IVB_CURSOR_OFFSETS,
+	BDW_COLORS,
 };
 
 static const struct intel_device_info intel_kabylake_info = {
-	HSW_FEATURES,
-	.is_preliminary = 1,
+	BDW_FEATURES,
 	.is_kabylake = 1,
 	.gen = 9,
 };
 
 static const struct intel_device_info intel_kabylake_gt3_info = {
-	HSW_FEATURES,
-	.is_preliminary = 1,
+	BDW_FEATURES,
 	.is_kabylake = 1,
 	.gen = 9,
 	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
@@ -503,7 +512,12 @@ void intel_detect_pch(struct drm_device
 				DRM_DEBUG_KMS("Found SunrisePoint LP PCH\n");
 				WARN_ON(!IS_SKYLAKE(dev) &&
 					!IS_KABYLAKE(dev));
+			} else if (id == INTEL_PCH_KBP_DEVICE_ID_TYPE) {
+				dev_priv->pch_type = PCH_KBP;
+				DRM_DEBUG_KMS("Found KabyPoint PCH\n");
+				WARN_ON(!IS_KABYLAKE(dev));
 			} else if ((id == INTEL_PCH_P2X_DEVICE_ID_TYPE) ||
+				   (id == INTEL_PCH_P3X_DEVICE_ID_TYPE) ||
 				   ((id == INTEL_PCH_QEMU_DEVICE_ID_TYPE) &&
 				    pch->subsystem_vendor == 0x1af4 &&
 				    pch->subsystem_device == 0x1100)) {
@@ -557,10 +571,9 @@ static void intel_suspend_encoders(struc
 	drm_modeset_unlock_all(dev);
 }
 
-static int intel_suspend_complete(struct drm_i915_private *dev_priv);
 static int vlv_resume_prepare(struct drm_i915_private *dev_priv,
 			      bool rpm_resume);
-static int bxt_resume_prepare(struct drm_i915_private *dev_priv);
+static int vlv_suspend_complete(struct drm_i915_private *dev_priv);
 
 static bool suspend_to_idle(struct drm_i915_private *dev_priv)
 {
@@ -630,8 +643,7 @@ static int i915_drm_suspend(struct drm_d
 
 	intel_display_set_init_power(dev_priv, false);
 
-	if (HAS_CSR(dev_priv))
-		flush_work(&dev_priv->csr.work);
+	intel_csr_ucode_suspend(dev_priv);
 
 out:
 	enable_rpm_wakeref_asserts(dev_priv);
@@ -647,7 +659,8 @@ static int i915_drm_suspend_late(struct
 
 	disable_rpm_wakeref_asserts(dev_priv);
 
-	fw_csr = suspend_to_idle(dev_priv) && dev_priv->csr.dmc_payload;
+	fw_csr = !IS_BROXTON(dev_priv) &&
+		suspend_to_idle(dev_priv) && dev_priv->csr.dmc_payload;
 	/*
 	 * In case of firmware assisted context save/restore don't manually
 	 * deinit the power domains. This also means the CSR/DMC firmware will
@@ -658,7 +671,13 @@ static int i915_drm_suspend_late(struct
 	if (!fw_csr)
 		intel_power_domains_suspend(dev_priv);
 
-	ret = intel_suspend_complete(dev_priv);
+	ret = 0;
+	if (IS_BROXTON(dev_priv))
+		bxt_enable_dc9(dev_priv);
+	else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
+		hsw_enable_pc8(dev_priv);
+	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+		ret = vlv_suspend_complete(dev_priv);
 
 	if (ret) {
 		DRM_ERROR("Suspend complete failed: %d\n", ret);
@@ -719,9 +738,16 @@ int i915_suspend_switcheroo(struct drm_d
 static int i915_drm_resume(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	int ret;
 
 	disable_rpm_wakeref_asserts(dev_priv);
 
+	ret = i915_ggtt_enable_hw(dev);
+	if (ret)
+		DRM_ERROR("failed to re-enable GGTT\n");
+
+	intel_csr_ucode_resume(dev_priv);
+
 	mutex_lock(&dev->struct_mutex);
 	i915_gem_restore_gtt_mappings(dev);
 	mutex_unlock(&dev->struct_mutex);
@@ -850,21 +876,25 @@ static int i915_drm_resume_early(struct
 
 	intel_uncore_early_sanitize(dev, true);
 
-	if (IS_BROXTON(dev))
-		ret = bxt_resume_prepare(dev_priv);
-	else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
+	if (IS_BROXTON(dev)) {
+		if (!dev_priv->suspended_to_idle)
+			gen9_sanitize_dc_state(dev_priv);
+		bxt_disable_dc9(dev_priv);
+	} else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
 		hsw_disable_pc8(dev_priv);
+	}
 
 	intel_uncore_sanitize(dev);
 
-	if (!(dev_priv->suspended_to_idle && dev_priv->csr.dmc_payload))
+	if (IS_BROXTON(dev_priv) ||
+	    !(dev_priv->suspended_to_idle && dev_priv->csr.dmc_payload))
 		intel_power_domains_init_hw(dev_priv, true);
 
+	enable_rpm_wakeref_asserts(dev_priv);
+
 out:
 	dev_priv->suspended_to_idle = false;
 
-	enable_rpm_wakeref_asserts(dev_priv);
-
 	return ret;
 }
 
@@ -900,23 +930,32 @@ int i915_resume_switcheroo(struct drm_de
 int i915_reset(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	bool simulated;
+	struct i915_gpu_error *error = &dev_priv->gpu_error;
+	unsigned reset_counter;
 	int ret;
 
 	intel_reset_gt_powersave(dev);
 
 	mutex_lock(&dev->struct_mutex);
 
-	i915_gem_reset(dev);
+	/* Clear any previous failed attempts at recovery. Time to try again. */
+	atomic_andnot(I915_WEDGED, &error->reset_counter);
 
-	simulated = dev_priv->gpu_error.stop_rings != 0;
+	/* Clear the reset-in-progress flag and increment the reset epoch. */
+	reset_counter = atomic_inc_return(&error->reset_counter);
+	if (WARN_ON(__i915_reset_in_progress(reset_counter))) {
+		ret = -EIO;
+		goto error;
+	}
 
-	ret = intel_gpu_reset(dev);
+	i915_gem_reset(dev);
+
+	ret = intel_gpu_reset(dev, ALL_ENGINES);
 
 	/* Also reset the gpu hangman. */
-	if (simulated) {
+	if (error->stop_rings != 0) {
 		DRM_INFO("Simulated gpu hang, resetting stop_rings\n");
-		dev_priv->gpu_error.stop_rings = 0;
+		error->stop_rings = 0;
 		if (ret == -ENODEV) {
 			DRM_INFO("Reset not implemented, but ignoring "
 				 "error for simulated gpu hangs\n");
@@ -928,9 +967,11 @@ int i915_reset(struct drm_device *dev)
 		pr_notice("drm/i915: Resetting chip after gpu hang\n");
 
 	if (ret) {
-		DRM_ERROR("Failed to reset chip: %i\n", ret);
-		mutex_unlock(&dev->struct_mutex);
-		return ret;
+		if (ret != -ENODEV)
+			DRM_ERROR("Failed to reset chip: %i\n", ret);
+		else
+			DRM_DEBUG_DRIVER("GPU reset disabled\n");
+		goto error;
 	}
 
 	intel_overlay_reset(dev_priv);
@@ -949,20 +990,14 @@ int i915_reset(struct drm_device *dev)
 	 * was running at the time of the reset (i.e. we weren't VT
 	 * switched away).
 	 */
-
-	/* Used to prevent gem_check_wedged returning -EAGAIN during gpu reset */
-	dev_priv->gpu_error.reload_in_reset = true;
-
 	ret = i915_gem_init_hw(dev);
-
-	dev_priv->gpu_error.reload_in_reset = false;
-
-	mutex_unlock(&dev->struct_mutex);
 	if (ret) {
 		DRM_ERROR("Failed hw init on reset %d\n", ret);
-		return ret;
+		goto error;
 	}
 
+	mutex_unlock(&dev->struct_mutex);
+
 	/*
 	 * rps/rc6 re-init is necessary to restore state lost after the
 	 * reset and the re-install of gt irqs. Skip for ironlake per
@@ -973,6 +1008,11 @@ int i915_reset(struct drm_device *dev)
 		intel_enable_gt_powersave(dev);
 
 	return 0;
+
+error:
+	atomic_or(I915_WEDGED, &error->reset_counter);
+	mutex_unlock(&dev->struct_mutex);
+	return ret;
 }
 
 static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
@@ -1079,44 +1119,6 @@ static int i915_pm_resume(struct device
 	return i915_drm_resume(drm_dev);
 }
 
-static int hsw_suspend_complete(struct drm_i915_private *dev_priv)
-{
-	hsw_enable_pc8(dev_priv);
-
-	return 0;
-}
-
-static int bxt_suspend_complete(struct drm_i915_private *dev_priv)
-{
-	struct drm_device *dev = dev_priv->dev;
-
-	/* TODO: when DC5 support is added disable DC5 here. */
-
-	broxton_ddi_phy_uninit(dev);
-	broxton_uninit_cdclk(dev);
-	bxt_enable_dc9(dev_priv);
-
-	return 0;
-}
-
-static int bxt_resume_prepare(struct drm_i915_private *dev_priv)
-{
-	struct drm_device *dev = dev_priv->dev;
-
-	/* TODO: when CSR FW support is added make sure the FW is loaded */
-
-	bxt_disable_dc9(dev_priv);
-
-	/*
-	 * TODO: when DC5 support is added enable DC5 here if the CSR FW
-	 * is available.
-	 */
-	broxton_init_cdclk(dev);
-	broxton_ddi_phy_init(dev);
-
-	return 0;
-}
-
 /*
  * Save all Gunit registers that may be lost after a D3 and a subsequent
  * S0i[R123] transition. The list of registers needing a save/restore is
@@ -1420,7 +1422,7 @@ static int vlv_suspend_complete(struct d
 	if (err)
 		goto err2;
 
-	if (!IS_CHERRYVIEW(dev_priv->dev))
+	if (!IS_CHERRYVIEW(dev_priv))
 		vlv_save_gunit_s0ix_state(dev_priv);
 
 	err = vlv_force_gfx_clock(dev_priv, false);
@@ -1452,7 +1454,7 @@ static int vlv_resume_prepare(struct drm
 	 */
 	ret = vlv_force_gfx_clock(dev_priv, true);
 
-	if (!IS_CHERRYVIEW(dev_priv->dev))
+	if (!IS_CHERRYVIEW(dev_priv))
 		vlv_restore_gunit_s0ix_state(dev_priv);
 
 	err = vlv_allow_gt_wake(dev_priv, true);
@@ -1522,7 +1524,16 @@ static int intel_runtime_suspend(struct
 	intel_suspend_gt_powersave(dev);
 	intel_runtime_pm_disable_interrupts(dev_priv);
 
-	ret = intel_suspend_complete(dev_priv);
+	ret = 0;
+	if (IS_BROXTON(dev_priv)) {
+		bxt_display_core_uninit(dev_priv);
+		bxt_enable_dc9(dev_priv);
+	} else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
+		hsw_enable_pc8(dev_priv);
+	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
+		ret = vlv_suspend_complete(dev_priv);
+	}
+
 	if (ret) {
 		DRM_ERROR("Runtime suspend failed, disabling it (%d)\n", ret);
 		intel_runtime_pm_enable_interrupts(dev_priv);
@@ -1596,12 +1607,17 @@ static int intel_runtime_resume(struct d
 	if (IS_GEN6(dev_priv))
 		intel_init_pch_refclk(dev);
 
-	if (IS_BROXTON(dev))
-		ret = bxt_resume_prepare(dev_priv);
-	else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
+	if (IS_BROXTON(dev)) {
+		bxt_disable_dc9(dev_priv);
+		bxt_display_core_init(dev_priv, true);
+		if (dev_priv->csr.dmc_payload &&
+		    (dev_priv->csr.allowed_dc_mask & DC_STATE_EN_UPTO_DC5))
+			gen9_enable_dc5(dev_priv);
+	} else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
 		hsw_disable_pc8(dev_priv);
-	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
 		ret = vlv_resume_prepare(dev_priv, true);
+	}
 
 	/*
 	 * No point of rolling back things in case of an error, as the best
@@ -1632,26 +1648,6 @@ static int intel_runtime_resume(struct d
 	return ret;
 }
 
-/*
- * This function implements common functionality of runtime and system
- * suspend sequence.
- */
-static int intel_suspend_complete(struct drm_i915_private *dev_priv)
-{
-	int ret;
-
-	if (IS_BROXTON(dev_priv))
-		ret = bxt_suspend_complete(dev_priv);
-	else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
-		ret = hsw_suspend_complete(dev_priv);
-	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
-		ret = vlv_suspend_complete(dev_priv);
-	else
-		ret = 0;
-
-	return ret;
-}
-
 static const struct dev_pm_ops i915_pm_ops = {
 	/*
 	 * S0ix (via system suspend) and S3 event handlers [PMSG_SUSPEND,
@@ -1772,10 +1768,8 @@ static int __init i915_init(void)
 	if (i915.modeset == 0)
 		driver.driver_features &= ~DRIVER_MODESET;
 
-#ifdef CONFIG_VGA_CONSOLE
 	if (vgacon_text_force() && i915.modeset == -1)
 		driver.driver_features &= ~DRIVER_MODESET;
-#endif
 
 	if (!(driver.driver_features & DRIVER_MODESET)) {
 		/* Silently fail loading to not upset userspace. */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_drv.h linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_drv.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_drv.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_drv.h	2016-07-24 15:23:50.000000000 -0400
@@ -33,33 +33,40 @@
 #include <uapi/drm/i915_drm.h>
 #include <uapi/drm/drm_fourcc.h>
 
-#include <drm/drmP.h>
-#include "i915_params.h"
-#include "i915_reg.h"
-#include "intel_bios.h"
-#include "intel_ringbuffer.h"
-#include "intel_lrc.h"
-#include "i915_gem_gtt.h"
-#include "i915_gem_render_state.h"
 #include <linux/io-mapping.h>
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
-#include <drm/intel-gtt.h>
-#include <drm/drm_legacy.h> /* for struct drm_dma_handle */
-#include <drm/drm_gem.h>
 #include <linux/backlight.h>
 #include <linux/hashtable.h>
 #include <linux/intel-iommu.h>
 #include <linux/kref.h>
 #include <linux/pm_qos.h>
+#include <linux/shmem_fs.h>
+
+#include <drm/drmP.h>
+#include <drm/intel-gtt.h>
+#include <drm/drm_legacy.h> /* for struct drm_dma_handle */
+#include <drm/drm_gem.h>
+
+#include "i915_params.h"
+#include "i915_reg.h"
+
+#include "intel_bios.h"
+#include "intel_dpll_mgr.h"
 #include "intel_guc.h"
+#include "intel_lrc.h"
+#include "intel_ringbuffer.h"
+
+#include "i915_gem.h"
+#include "i915_gem_gtt.h"
+#include "i915_gem_render_state.h"
 
 /* General customization:
  */
 
 #define DRIVER_NAME		"i915"
 #define DRIVER_DESC		"Intel Graphics"
-#define DRIVER_DATE		"20160229"
+#define DRIVER_DATE		"20160425"
 
 #undef WARN_ON
 /* Many gcc seem to no see through this and fall over :( */
@@ -97,6 +104,10 @@
 #define I915_STATE_WARN_ON(x)						\
 	I915_STATE_WARN((x), "%s", "WARN_ON(" __stringify(x) ")")
 
+bool __i915_inject_load_failure(const char *func, int line);
+#define i915_inject_load_failure() \
+	__i915_inject_load_failure(__func__, __LINE__)
+
 static inline const char *yesno(bool v)
 {
 	return v ? "yes" : "no";
@@ -122,9 +133,35 @@ enum transcoder {
 	TRANSCODER_B,
 	TRANSCODER_C,
 	TRANSCODER_EDP,
+	TRANSCODER_DSI_A,
+	TRANSCODER_DSI_C,
 	I915_MAX_TRANSCODERS
 };
-#define transcoder_name(t) ((t) + 'A')
+
+static inline const char *transcoder_name(enum transcoder transcoder)
+{
+	switch (transcoder) {
+	case TRANSCODER_A:
+		return "A";
+	case TRANSCODER_B:
+		return "B";
+	case TRANSCODER_C:
+		return "C";
+	case TRANSCODER_EDP:
+		return "EDP";
+	case TRANSCODER_DSI_A:
+		return "DSI A";
+	case TRANSCODER_DSI_C:
+		return "DSI C";
+	default:
+		return "<invalid>";
+	}
+}
+
+static inline bool transcoder_is_dsi(enum transcoder transcoder)
+{
+	return transcoder == TRANSCODER_DSI_A || transcoder == TRANSCODER_DSI_C;
+}
 
 /*
  * I915_MAX_PLANES in the enum below is the maximum (across all platforms)
@@ -176,6 +213,8 @@ enum intel_display_power_domain {
 	POWER_DOMAIN_TRANSCODER_B,
 	POWER_DOMAIN_TRANSCODER_C,
 	POWER_DOMAIN_TRANSCODER_EDP,
+	POWER_DOMAIN_TRANSCODER_DSI_A,
+	POWER_DOMAIN_TRANSCODER_DSI_C,
 	POWER_DOMAIN_PORT_DDI_A_LANES,
 	POWER_DOMAIN_PORT_DDI_B_LANES,
 	POWER_DOMAIN_PORT_DDI_C_LANES,
@@ -273,6 +312,10 @@ struct i915_hotplug {
 	     (__s) < INTEL_INFO(__dev_priv)->num_sprites[(__p)];	\
 	     (__s)++)
 
+#define for_each_port_masked(__port, __ports_mask) \
+	for ((__port) = PORT_A; (__port) < I915_MAX_PORTS; (__port)++)	\
+		for_each_if ((__ports_mask) & (1 << (__port)))
+
 #define for_each_crtc(dev, crtc) \
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
 
@@ -340,81 +383,6 @@ struct drm_i915_file_private {
 	unsigned int bsd_ring;
 };
 
-enum intel_dpll_id {
-	DPLL_ID_PRIVATE = -1, /* non-shared dpll in use */
-	/* real shared dpll ids must be >= 0 */
-	DPLL_ID_PCH_PLL_A = 0,
-	DPLL_ID_PCH_PLL_B = 1,
-	/* hsw/bdw */
-	DPLL_ID_WRPLL1 = 0,
-	DPLL_ID_WRPLL2 = 1,
-	DPLL_ID_SPLL = 2,
-
-	/* skl */
-	DPLL_ID_SKL_DPLL1 = 0,
-	DPLL_ID_SKL_DPLL2 = 1,
-	DPLL_ID_SKL_DPLL3 = 2,
-};
-#define I915_NUM_PLLS 3
-
-struct intel_dpll_hw_state {
-	/* i9xx, pch plls */
-	uint32_t dpll;
-	uint32_t dpll_md;
-	uint32_t fp0;
-	uint32_t fp1;
-
-	/* hsw, bdw */
-	uint32_t wrpll;
-	uint32_t spll;
-
-	/* skl */
-	/*
-	 * DPLL_CTRL1 has 6 bits for each each this DPLL. We store those in
-	 * lower part of ctrl1 and they get shifted into position when writing
-	 * the register.  This allows us to easily compare the state to share
-	 * the DPLL.
-	 */
-	uint32_t ctrl1;
-	/* HDMI only, 0 when used for DP */
-	uint32_t cfgcr1, cfgcr2;
-
-	/* bxt */
-	uint32_t ebb0, ebb4, pll0, pll1, pll2, pll3, pll6, pll8, pll9, pll10,
-		 pcsdw12;
-};
-
-struct intel_shared_dpll_config {
-	unsigned crtc_mask; /* mask of CRTCs sharing this PLL */
-	struct intel_dpll_hw_state hw_state;
-};
-
-struct intel_shared_dpll {
-	struct intel_shared_dpll_config config;
-
-	int active; /* count of number of active CRTCs (i.e. DPMS on) */
-	bool on; /* is the PLL actually active? Disabled during modeset */
-	const char *name;
-	/* should match the index in the dev_priv->shared_dplls array */
-	enum intel_dpll_id id;
-	/* The mode_set hook is optional and should be used together with the
-	 * intel_prepare_shared_dpll function. */
-	void (*mode_set)(struct drm_i915_private *dev_priv,
-			 struct intel_shared_dpll *pll);
-	void (*enable)(struct drm_i915_private *dev_priv,
-		       struct intel_shared_dpll *pll);
-	void (*disable)(struct drm_i915_private *dev_priv,
-			struct intel_shared_dpll *pll);
-	bool (*get_hw_state)(struct drm_i915_private *dev_priv,
-			     struct intel_shared_dpll *pll,
-			     struct intel_dpll_hw_state *hw_state);
-};
-
-#define SKL_DPLL0 0
-#define SKL_DPLL1 1
-#define SKL_DPLL2 2
-#define SKL_DPLL3 3
-
 /* Used by dp and fdi links */
 struct intel_link_m_n {
 	uint32_t	tu;
@@ -533,7 +501,8 @@ struct drm_i915_error_state {
 		u32 cpu_ring_head;
 		u32 cpu_ring_tail;
 
-		u32 semaphore_seqno[I915_NUM_RINGS - 1];
+		u32 last_seqno;
+		u32 semaphore_seqno[I915_NUM_ENGINES - 1];
 
 		/* Register state */
 		u32 start;
@@ -553,7 +522,7 @@ struct drm_i915_error_state {
 		u32 fault_reg;
 		u64 faddr;
 		u32 rc_psmi; /* sleep state */
-		u32 semaphore_mboxes[I915_NUM_RINGS - 1];
+		u32 semaphore_mboxes[I915_NUM_ENGINES - 1];
 
 		struct drm_i915_error_object {
 			int page_count;
@@ -561,6 +530,8 @@ struct drm_i915_error_state {
 			u32 *pages[0];
 		} *ringbuffer, *batchbuffer, *wa_batchbuffer, *ctx, *hws_page;
 
+		struct drm_i915_error_object *wa_ctx;
+
 		struct drm_i915_error_request {
 			long jiffies;
 			u32 seqno;
@@ -577,12 +548,12 @@ struct drm_i915_error_state {
 
 		pid_t pid;
 		char comm[TASK_COMM_LEN];
-	} ring[I915_NUM_RINGS];
+	} ring[I915_NUM_ENGINES];
 
 	struct drm_i915_error_buffer {
 		u32 size;
 		u32 name;
-		u32 rseqno[I915_NUM_RINGS], wseqno;
+		u32 rseqno[I915_NUM_ENGINES], wseqno;
 		u64 gtt_offset;
 		u32 read_domains;
 		u32 write_domain;
@@ -611,27 +582,12 @@ struct dpll;
 struct drm_i915_display_funcs {
 	int (*get_display_clock_speed)(struct drm_device *dev);
 	int (*get_fifo_size)(struct drm_device *dev, int plane);
-	/**
-	 * find_dpll() - Find the best values for the PLL
-	 * @limit: limits for the PLL
-	 * @crtc: current CRTC
-	 * @target: target frequency in kHz
-	 * @refclk: reference clock frequency in kHz
-	 * @match_clock: if provided, @best_clock P divider must
-	 *               match the P divider from @match_clock
-	 *               used for LVDS downclocking
-	 * @best_clock: best PLL values found
-	 *
-	 * Returns true on success, false on failure.
-	 */
-	bool (*find_dpll)(const struct intel_limit *limit,
-			  struct intel_crtc_state *crtc_state,
-			  int target, int refclk,
-			  struct dpll *match_clock,
-			  struct dpll *best_clock);
-	int (*compute_pipe_wm)(struct intel_crtc *crtc,
-			       struct drm_atomic_state *state);
-	void (*program_watermarks)(struct intel_crtc_state *cstate);
+	int (*compute_pipe_wm)(struct intel_crtc_state *cstate);
+	int (*compute_intermediate_wm)(struct drm_device *dev,
+				       struct intel_crtc *intel_crtc,
+				       struct intel_crtc_state *newstate);
+	void (*initial_watermarks)(struct intel_crtc_state *cstate);
+	void (*optimize_watermarks)(struct intel_crtc_state *cstate);
 	void (*update_wm)(struct drm_crtc *crtc);
 	int (*modeset_calc_cdclk)(struct drm_atomic_state *state);
 	void (*modeset_commit_cdclk)(struct drm_atomic_state *state);
@@ -662,6 +618,9 @@ struct drm_i915_display_funcs {
 	/* render clock increase/decrease */
 	/* display clock increase/decrease */
 	/* pll clock increase/decrease */
+
+	void (*load_csc_matrix)(struct drm_crtc_state *crtc_state);
+	void (*load_luts)(struct drm_crtc_state *crtc_state);
 };
 
 enum forcewake_domain_id {
@@ -681,6 +640,13 @@ enum forcewake_domains {
 			 FORCEWAKE_MEDIA)
 };
 
+#define FW_REG_READ  (1)
+#define FW_REG_WRITE (2)
+
+enum forcewake_domains
+intel_uncore_forcewake_for_reg(struct drm_i915_private *dev_priv,
+			       i915_reg_t reg, unsigned int op);
+
 struct intel_uncore_funcs {
 	void (*force_wake_get)(struct drm_i915_private *dev_priv,
 							enum forcewake_domains domains);
@@ -713,8 +679,9 @@ struct intel_uncore {
 	struct intel_uncore_forcewake_domain {
 		struct drm_i915_private *i915;
 		enum forcewake_domain_id id;
+		enum forcewake_domains mask;
 		unsigned wake_count;
-		struct timer_list timer;
+		struct hrtimer timer;
 		i915_reg_t reg_set;
 		u32 val_set;
 		u32 val_clear;
@@ -727,14 +694,14 @@ struct intel_uncore {
 };
 
 /* Iterate over initialised fw domains */
-#define for_each_fw_domain_mask(domain__, mask__, dev_priv__, i__) \
-	for ((i__) = 0, (domain__) = &(dev_priv__)->uncore.fw_domain[0]; \
-	     (i__) < FW_DOMAIN_ID_COUNT; \
-	     (i__)++, (domain__) = &(dev_priv__)->uncore.fw_domain[i__]) \
-		for_each_if (((mask__) & (dev_priv__)->uncore.fw_domains) & (1 << (i__)))
+#define for_each_fw_domain_masked(domain__, mask__, dev_priv__) \
+	for ((domain__) = &(dev_priv__)->uncore.fw_domain[0]; \
+	     (domain__) < &(dev_priv__)->uncore.fw_domain[FW_DOMAIN_ID_COUNT]; \
+	     (domain__)++) \
+		for_each_if ((mask__) & (domain__)->mask)
 
-#define for_each_fw_domain(domain__, dev_priv__, i__) \
-	for_each_fw_domain_mask(domain__, FORCEWAKE_ALL, dev_priv__, i__)
+#define for_each_fw_domain(domain__, dev_priv__) \
+	for_each_fw_domain_masked(domain__, FORCEWAKE_ALL, dev_priv__)
 
 #define CSR_VERSION(major, minor)	((major) << 16 | (minor))
 #define CSR_VERSION_MAJOR(version)	((version) >> 16)
@@ -750,6 +717,7 @@ struct intel_csr {
 	i915_reg_t mmioaddr[8];
 	uint32_t mmiodata[8];
 	uint32_t dc_state;
+	uint32_t allowed_dc_mask;
 };
 
 #define DEV_INFO_FOR_EACH_FLAG(func, sep) \
@@ -779,6 +747,7 @@ struct intel_csr {
 	func(overlay_needs_physical) sep \
 	func(supports_tv) sep \
 	func(has_llc) sep \
+	func(has_snoop) sep \
 	func(has_ddi) sep \
 	func(has_fpga_dbg)
 
@@ -810,6 +779,11 @@ struct intel_device_info {
 	u8 has_slice_pg:1;
 	u8 has_subslice_pg:1;
 	u8 has_eu_pg:1;
+
+	struct color_luts {
+		u16 degamma_lut_size;
+		u16 gamma_lut_size;
+	} color;
 };
 
 #undef DEFINE_FLAG
@@ -891,7 +865,7 @@ struct intel_context {
 		struct i915_vma *lrc_vma;
 		u64 lrc_desc;
 		uint32_t *lrc_reg_state;
-	} engine[I915_NUM_RINGS];
+	} engine[I915_NUM_ENGINES];
 
 	struct list_head link;
 };
@@ -1016,6 +990,7 @@ enum intel_pch {
 	PCH_CPT,	/* Cougarpoint PCH */
 	PCH_LPT,	/* Lynxpoint PCH */
 	PCH_SPT,        /* Sunrisepoint PCH */
+	PCH_KBP,        /* Kabypoint PCH */
 	PCH_NOP,
 };
 
@@ -1036,6 +1011,7 @@ struct intel_fbc_work;
 
 struct intel_gmbus {
 	struct i2c_adapter adapter;
+#define GMBUS_FORCE_BIT_RETRY (1U << 31)
 	u32 force_bit;
 	u32 reg0;
 	i915_reg_t gpio_reg;
@@ -1159,6 +1135,7 @@ struct intel_gen6_power_mgmt {
 	u8 efficient_freq;	/* AKA RPe. Pre-determined balanced frequency */
 	u8 rp1_freq;		/* "less than" RP0 power/freqency */
 	u8 rp0_freq;		/* Non-overclocked max frequency. */
+	u16 gpll_ref_freq;	/* vlv/chv GPLL reference frequency */
 
 	u8 up_threshold; /* Current %busy required to uplock */
 	u8 down_threshold; /* Current %busy required to downclock */
@@ -1298,6 +1275,7 @@ struct i915_gem_mm {
 	struct i915_hw_ppgtt *aliasing_ppgtt;
 
 	struct notifier_block oom_notifier;
+	struct notifier_block vmap_notifier;
 	struct shrinker shrinker;
 	bool shrinker_no_lock_stealing;
 
@@ -1423,9 +1401,6 @@ struct i915_gpu_error {
 
 	/* For missed irq/seqno simulation. */
 	unsigned int test_irq_rings;
-
-	/* Used to prevent gem_check_wedged returning -EAGAIN during gpu reset   */
-	bool reload_in_reset;
 };
 
 enum modeset_restore {
@@ -1482,21 +1457,23 @@ struct intel_vbt_data {
 	unsigned int lvds_use_ssc:1;
 	unsigned int display_clock_mode:1;
 	unsigned int fdi_rx_polarity_inverted:1;
-	unsigned int has_mipi:1;
+	unsigned int panel_type:4;
 	int lvds_ssc_freq;
 	unsigned int bios_lvds_val; /* initial [PCH_]LVDS reg val in VBIOS */
 
 	enum drrs_support_type drrs_type;
 
-	/* eDP */
-	int edp_rate;
-	int edp_lanes;
-	int edp_preemphasis;
-	int edp_vswing;
-	bool edp_initialized;
-	bool edp_support;
-	int edp_bpp;
-	struct edp_power_seq edp_pps;
+	struct {
+		int rate;
+		int lanes;
+		int preemphasis;
+		int vswing;
+		bool low_vswing;
+		bool initialized;
+		bool support;
+		int bpp;
+		struct edp_power_seq pps;
+	} edp;
 
 	struct {
 		bool full_link;
@@ -1516,7 +1493,6 @@ struct intel_vbt_data {
 
 	/* MIPI DSI */
 	struct {
-		u16 port;
 		u16 panel_id;
 		struct mipi_config *config;
 		struct mipi_pps_data *pps;
@@ -1532,6 +1508,7 @@ struct intel_vbt_data {
 	union child_device_config *child_dev;
 
 	struct ddi_vbt_port_info ddi_port_info[I915_MAX_PORTS];
+	struct sdvo_device_mapping sdvo_mappings[2];
 };
 
 enum intel_ddb_partitioning {
@@ -1706,7 +1683,7 @@ struct i915_wa_reg {
 struct i915_workarounds {
 	struct i915_wa_reg reg[I915_MAX_WA_REGS];
 	u32 count;
-	u32 hw_whitelist_count[I915_NUM_RINGS];
+	u32 hw_whitelist_count[I915_NUM_ENGINES];
 };
 
 struct i915_virtual_gpu {
@@ -1719,7 +1696,7 @@ struct i915_execbuffer_params {
 	uint32_t                        dispatch_flags;
 	uint32_t                        args_batch_start_offset;
 	uint64_t                        batch_obj_vm_offset;
-	struct intel_engine_cs          *ring;
+	struct intel_engine_cs *engine;
 	struct drm_i915_gem_object      *batch_obj;
 	struct intel_context            *ctx;
 	struct drm_i915_gem_request     *request;
@@ -1771,7 +1748,7 @@ struct drm_i915_private {
 	wait_queue_head_t gmbus_wait_queue;
 
 	struct pci_dev *bridge_dev;
-	struct intel_engine_cs ring[I915_NUM_RINGS];
+	struct intel_engine_cs engine[I915_NUM_ENGINES];
 	struct drm_i915_gem_object *semaphore_obj;
 	uint32_t last_seqno, next_seqno;
 
@@ -1829,6 +1806,7 @@ struct drm_i915_private {
 	unsigned int skl_boot_cdclk;
 	unsigned int cdclk_freq, max_cdclk_freq, atomic_cdclk_freq;
 	unsigned int max_dotclk_freq;
+	unsigned int rawclk_freq;
 	unsigned int hpll_freq;
 	unsigned int czclk_freq;
 
@@ -1855,7 +1833,7 @@ struct drm_i915_private {
 	struct drm_atomic_state *modeset_restore_state;
 
 	struct list_head vm_list; /* Global list of all address spaces */
-	struct i915_gtt gtt; /* VM representing the global address space */
+	struct i915_ggtt ggtt; /* VM representing the global address space */
 
 	struct i915_gem_mm mm;
 	DECLARE_HASHTABLE(mm_structs, 7);
@@ -1863,8 +1841,6 @@ struct drm_i915_private {
 
 	/* Kernel Modesetting */
 
-	struct sdvo_device_mapping sdvo_mappings[2];
-
 	struct drm_crtc *plane_to_crtc_mapping[I915_MAX_PIPES];
 	struct drm_crtc *pipe_to_crtc_mapping[I915_MAX_PIPES];
 	wait_queue_head_t pending_flip_queue;
@@ -1876,6 +1852,14 @@ struct drm_i915_private {
 	/* dpll and cdclk state is protected by connection_mutex */
 	int num_shared_dpll;
 	struct intel_shared_dpll shared_dplls[I915_NUM_PLLS];
+	const struct intel_dpll_mgr *dpll_mgr;
+
+	/*
+	 * dpll_lock serializes intel_{prepare,enable,disable}_shared_dpll.
+	 * Must be global rather than per dpll, because on some platforms
+	 * plls share registers.
+	 */
+	struct mutex dpll_lock;
 
 	unsigned int active_crtcs;
 	unsigned int min_pixclk[I915_MAX_PIPES];
@@ -1884,9 +1868,6 @@ struct drm_i915_private {
 
 	struct i915_workarounds workarounds;
 
-	/* Reclocking support */
-	bool render_reclock_avail;
-
 	struct i915_frontbuffer_tracking fb_tracking;
 
 	u16 orig_clock;
@@ -1896,7 +1877,7 @@ struct drm_i915_private {
 	struct intel_l3_parity l3_parity;
 
 	/* Cannot be determined by PCIID. You must always read a register. */
-	size_t ellc_size;
+	u32 edram_cap;
 
 	/* gen6+ rps state */
 	struct intel_gen6_power_mgmt rps;
@@ -1936,7 +1917,15 @@ struct drm_i915_private {
 
 	u32 fdi_rx_config;
 
+	/* Shadow for DISPLAY_PHY_CONTROL which can't be safely read */
 	u32 chv_phy_control;
+	/*
+	 * Shadows for CHV DPLL_MD regs to keep the state
+	 * checker somewhat working in the presence hardware
+	 * crappiness (can't read out DPLL_MD for pipes B & C).
+	 */
+	u32 chv_dpll_md[I915_MAX_PIPES];
+	u32 bxt_phy_grc;
 
 	u32 suspend_count;
 	bool suspended_to_idle;
@@ -1980,6 +1969,13 @@ struct drm_i915_private {
 		};
 
 		uint8_t max_level;
+
+		/*
+		 * Should be held around atomic WM register writing; also
+		 * protects * intel_crtc->wm.active and
+		 * cstate->wm.need_postvbl_update.
+		 */
+		struct mutex wm_mutex;
 	} wm;
 
 	struct i915_runtime_pm pm;
@@ -1989,15 +1985,13 @@ struct drm_i915_private {
 		int (*execbuf_submit)(struct i915_execbuffer_params *params,
 				      struct drm_i915_gem_execbuffer2 *args,
 				      struct list_head *vmas);
-		int (*init_rings)(struct drm_device *dev);
-		void (*cleanup_ring)(struct intel_engine_cs *ring);
-		void (*stop_ring)(struct intel_engine_cs *ring);
+		int (*init_engines)(struct drm_device *dev);
+		void (*cleanup_engine)(struct intel_engine_cs *engine);
+		void (*stop_engine)(struct intel_engine_cs *engine);
 	} gt;
 
 	struct intel_context *kernel_context;
 
-	bool edp_low_vswing;
-
 	/* perform PHY state sanity checks? */
 	bool chv_phy_assert[2];
 
@@ -2024,10 +2018,28 @@ static inline struct drm_i915_private *g
 	return container_of(guc, struct drm_i915_private, guc);
 }
 
-/* Iterate over initialised rings */
-#define for_each_ring(ring__, dev_priv__, i__) \
-	for ((i__) = 0; (i__) < I915_NUM_RINGS; (i__)++) \
-		for_each_if ((((ring__) = &(dev_priv__)->ring[(i__)]), intel_ring_initialized((ring__))))
+/* Simple iterator over all initialised engines */
+#define for_each_engine(engine__, dev_priv__) \
+	for ((engine__) = &(dev_priv__)->engine[0]; \
+	     (engine__) < &(dev_priv__)->engine[I915_NUM_ENGINES]; \
+	     (engine__)++) \
+		for_each_if (intel_engine_initialized(engine__))
+
+/* Iterator with engine_id */
+#define for_each_engine_id(engine__, dev_priv__, id__) \
+	for ((engine__) = &(dev_priv__)->engine[0], (id__) = 0; \
+	     (engine__) < &(dev_priv__)->engine[I915_NUM_ENGINES]; \
+	     (engine__)++) \
+		for_each_if (((id__) = (engine__)->id, \
+			      intel_engine_initialized(engine__)))
+
+/* Iterator over subset of engines selected by mask */
+#define for_each_engine_masked(engine__, dev_priv__, mask__) \
+	for ((engine__) = &(dev_priv__)->engine[0]; \
+	     (engine__) < &(dev_priv__)->engine[I915_NUM_ENGINES]; \
+	     (engine__)++) \
+		for_each_if (((mask__) & intel_engine_flag(engine__)) && \
+			     intel_engine_initialized(engine__))
 
 enum hdmi_force_audio {
 	HDMI_AUDIO_OFF_DVI = -2,	/* no aux data for HDMI-DVI converter */
@@ -2097,7 +2109,7 @@ struct drm_i915_gem_object {
 	struct drm_mm_node *stolen;
 	struct list_head global_list;
 
-	struct list_head ring_list[I915_NUM_RINGS];
+	struct list_head engine_list[I915_NUM_ENGINES];
 	/** Used in execbuf to temporarily hold a ref */
 	struct list_head obj_exec_link;
 
@@ -2108,7 +2120,7 @@ struct drm_i915_gem_object {
 	 * rendering and so a non-zero seqno), and is not set if it i s on
 	 * inactive (ready to be unbound) list.
 	 */
-	unsigned int active:I915_NUM_RINGS;
+	unsigned int active:I915_NUM_ENGINES;
 
 	/**
 	 * This is set if the object has been written to since last bound
@@ -2172,10 +2184,7 @@ struct drm_i915_gem_object {
 		struct scatterlist *sg;
 		int last;
 	} get_page;
-
-	/* prime dma-buf support */
-	void *dma_buf_vmapping;
-	int vmapping_count;
+	void *mapping;
 
 	/** Breadcrumb of last rendering to the buffer.
 	 * There can only be one writer, but we allow for multiple readers.
@@ -2187,7 +2196,7 @@ struct drm_i915_gem_object {
 	 * read request. This allows for the CPU to read from an active
 	 * buffer by only waiting for the write to complete.
 	 * */
-	struct drm_i915_gem_request *last_read_req[I915_NUM_RINGS];
+	struct drm_i915_gem_request *last_read_req[I915_NUM_ENGINES];
 	struct drm_i915_gem_request *last_write_req;
 	/** Breadcrumb of last fenced GPU access to the buffer. */
 	struct drm_i915_gem_request *last_fenced_req;
@@ -2242,7 +2251,8 @@ struct drm_i915_gem_request {
 
 	/** On Which ring this request was generated */
 	struct drm_i915_private *i915;
-	struct intel_engine_cs *ring;
+	struct intel_engine_cs *engine;
+	unsigned reset_counter;
 
 	 /** GEM sequence number associated with the previous request,
 	  * when the HWS breadcrumb is equal to this the GPU is processing
@@ -2323,7 +2333,6 @@ struct drm_i915_gem_request {
 struct drm_i915_gem_request * __must_check
 i915_gem_request_alloc(struct intel_engine_cs *engine,
 		       struct intel_context *ctx);
-void i915_gem_request_cancel(struct drm_i915_gem_request *req);
 void i915_gem_request_free(struct kref *req_ref);
 int i915_gem_request_add_to_client(struct drm_i915_gem_request *req,
 				   struct drm_file *file);
@@ -2335,9 +2344,9 @@ i915_gem_request_get_seqno(struct drm_i9
 }
 
 static inline struct intel_engine_cs *
-i915_gem_request_get_ring(struct drm_i915_gem_request *req)
+i915_gem_request_get_engine(struct drm_i915_gem_request *req)
 {
-	return req ? req->ring : NULL;
+	return req ? req->engine : NULL;
 }
 
 static inline struct drm_i915_gem_request *
@@ -2351,7 +2360,7 @@ i915_gem_request_reference(struct drm_i9
 static inline void
 i915_gem_request_unreference(struct drm_i915_gem_request *req)
 {
-	WARN_ON(!mutex_is_locked(&req->ring->dev->struct_mutex));
+	WARN_ON(!mutex_is_locked(&req->engine->dev->struct_mutex));
 	kref_put(&req->ref, i915_gem_request_free);
 }
 
@@ -2363,7 +2372,7 @@ i915_gem_request_unreference__unlocked(s
 	if (!req)
 		return;
 
-	dev = req->ring->dev;
+	dev = req->engine->dev;
 	if (kref_put_mutex(&req->ref, i915_gem_request_free, &dev->struct_mutex))
 		mutex_unlock(&dev->struct_mutex);
 }
@@ -2493,6 +2502,7 @@ struct drm_i915_cmd_table {
 	__p; \
 })
 #define INTEL_INFO(p) 	(&__I915__(p)->info)
+#define INTEL_GEN(p)	(INTEL_INFO(p)->gen)
 #define INTEL_DEVID(p)	(INTEL_INFO(p)->device_id)
 #define INTEL_REVID(p)	(__I915__(p)->dev->pdev->revision)
 
@@ -2591,6 +2601,15 @@ struct drm_i915_cmd_table {
 
 #define IS_BXT_REVID(p, since, until) (IS_BROXTON(p) && IS_REVID(p, since, until))
 
+#define KBL_REVID_A0		0x0
+#define KBL_REVID_B0		0x1
+#define KBL_REVID_C0		0x2
+#define KBL_REVID_D0		0x3
+#define KBL_REVID_E0		0x4
+
+#define IS_KBL_REVID(p, since, until) \
+	(IS_KABYLAKE(p) && IS_REVID(p, since, until))
+
 /*
  * The genX designation typically refers to the render engine, so render
  * capability related checks should use IS_GEN, while display and other checks
@@ -2611,13 +2630,17 @@ struct drm_i915_cmd_table {
 #define BLT_RING		(1<<BCS)
 #define VEBOX_RING		(1<<VECS)
 #define BSD2_RING		(1<<VCS2)
+#define ALL_ENGINES		(~0)
+
 #define HAS_BSD(dev)		(INTEL_INFO(dev)->ring_mask & BSD_RING)
 #define HAS_BSD2(dev)		(INTEL_INFO(dev)->ring_mask & BSD2_RING)
 #define HAS_BLT(dev)		(INTEL_INFO(dev)->ring_mask & BLT_RING)
 #define HAS_VEBOX(dev)		(INTEL_INFO(dev)->ring_mask & VEBOX_RING)
 #define HAS_LLC(dev)		(INTEL_INFO(dev)->has_llc)
+#define HAS_SNOOP(dev)		(INTEL_INFO(dev)->has_snoop)
+#define HAS_EDRAM(dev)		(__I915__(dev)->edram_cap & EDRAM_ENABLED)
 #define HAS_WT(dev)		((IS_HASWELL(dev) || IS_BROADWELL(dev)) && \
-				 __I915__(dev)->ellc_size)
+				 HAS_EDRAM(dev))
 #define I915_NEED_GFX_HWS(dev)	(INTEL_INFO(dev)->need_gfx_hws)
 
 #define HAS_HW_CONTEXTS(dev)	(INTEL_INFO(dev)->gen >= 6)
@@ -2671,7 +2694,7 @@ struct drm_i915_cmd_table {
 #define HAS_RUNTIME_PM(dev)	(IS_GEN6(dev) || IS_HASWELL(dev) || \
 				 IS_BROADWELL(dev) || IS_VALLEYVIEW(dev) || \
 				 IS_CHERRYVIEW(dev) || IS_SKYLAKE(dev) || \
-				 IS_KABYLAKE(dev))
+				 IS_KABYLAKE(dev) || IS_BROXTON(dev))
 #define HAS_RC6(dev)		(INTEL_INFO(dev)->gen >= 6)
 #define HAS_RC6p(dev)		(INTEL_INFO(dev)->gen == 6 || IS_IVYBRIDGE(dev))
 
@@ -2695,10 +2718,13 @@ struct drm_i915_cmd_table {
 #define INTEL_PCH_LPT_LP_DEVICE_ID_TYPE		0x9c00
 #define INTEL_PCH_SPT_DEVICE_ID_TYPE		0xA100
 #define INTEL_PCH_SPT_LP_DEVICE_ID_TYPE		0x9D00
+#define INTEL_PCH_KBP_DEVICE_ID_TYPE		0xA200
 #define INTEL_PCH_P2X_DEVICE_ID_TYPE		0x7100
+#define INTEL_PCH_P3X_DEVICE_ID_TYPE		0x7000
 #define INTEL_PCH_QEMU_DEVICE_ID_TYPE		0x2900 /* qemu q35 has 2918 */
 
 #define INTEL_PCH_TYPE(dev) (__I915__(dev)->pch_type)
+#define HAS_PCH_KBP(dev) (INTEL_PCH_TYPE(dev) == PCH_KBP)
 #define HAS_PCH_SPT(dev) (INTEL_PCH_TYPE(dev) == PCH_SPT)
 #define HAS_PCH_LPT(dev) (INTEL_PCH_TYPE(dev) == PCH_LPT)
 #define HAS_PCH_LPT_LP(dev) (__I915__(dev)->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE)
@@ -2727,6 +2753,13 @@ extern int i915_suspend_switcheroo(struc
 extern int i915_resume_switcheroo(struct drm_device *dev);
 
 /* i915_dma.c */
+void __printf(3, 4)
+__i915_printk(struct drm_i915_private *dev_priv, const char *level,
+	      const char *fmt, ...);
+
+#define i915_report_error(dev_priv, fmt, ...)				   \
+	__i915_printk(dev_priv, KERN_ERR, fmt, ##__VA_ARGS__)
+
 extern int i915_driver_load(struct drm_device *, unsigned long flags);
 extern int i915_driver_unload(struct drm_device *);
 extern int i915_driver_open(struct drm_device *dev, struct drm_file *file);
@@ -2739,9 +2772,11 @@ extern void i915_driver_postclose(struct
 extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
 			      unsigned long arg);
 #endif
-extern int intel_gpu_reset(struct drm_device *dev);
+extern int intel_gpu_reset(struct drm_device *dev, u32 engine_mask);
 extern bool intel_has_gpu_reset(struct drm_device *dev);
 extern int i915_reset(struct drm_device *dev);
+extern int intel_guc_reset(struct drm_i915_private *dev_priv);
+extern void intel_engine_init_hangcheck(struct intel_engine_cs *engine);
 extern unsigned long i915_chipset_val(struct drm_i915_private *dev_priv);
 extern unsigned long i915_mch_val(struct drm_i915_private *dev_priv);
 extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv);
@@ -2758,7 +2793,7 @@ bool intel_hpd_pin_to_port(enum hpd_pin
 /* i915_irq.c */
 void i915_queue_hangcheck(struct drm_device *dev);
 __printf(3, 4)
-void i915_handle_error(struct drm_device *dev, bool wedged,
+void i915_handle_error(struct drm_device *dev, u32 engine_mask,
 		       const char *fmt, ...);
 
 extern void intel_irq_init(struct drm_i915_private *dev_priv);
@@ -2785,6 +2820,8 @@ void intel_uncore_forcewake_get__locked(
 					enum forcewake_domains domains);
 void intel_uncore_forcewake_put__locked(struct drm_i915_private *dev_priv,
 					enum forcewake_domains domains);
+u64 intel_uncore_edram_size(struct drm_i915_private *dev_priv);
+
 void assert_forcewakes_inactive(struct drm_i915_private *dev_priv);
 static inline bool intel_vgpu_active(struct drm_device *dev)
 {
@@ -2863,7 +2900,6 @@ int i915_gem_sw_finish_ioctl(struct drm_
 			     struct drm_file *file_priv);
 void i915_gem_execbuffer_move_to_active(struct list_head *vmas,
 					struct drm_i915_gem_request *req);
-void i915_gem_execbuffer_retire_commands(struct i915_execbuffer_params *params);
 int i915_gem_ringbuffer_submission(struct i915_execbuffer_params *params,
 				   struct drm_i915_gem_execbuffer2 *args,
 				   struct list_head *vmas);
@@ -2894,6 +2930,7 @@ int i915_gem_wait_ioctl(struct drm_devic
 			struct drm_file *file_priv);
 void i915_gem_load_init(struct drm_device *dev);
 void i915_gem_load_cleanup(struct drm_device *dev);
+void i915_gem_load_init_fences(struct drm_i915_private *dev_priv);
 void *i915_gem_object_alloc(struct drm_device *dev);
 void i915_gem_object_free(struct drm_i915_gem_object *obj);
 void i915_gem_object_init(struct drm_i915_gem_object *obj,
@@ -2978,12 +3015,46 @@ static inline void i915_gem_object_pin_p
 	BUG_ON(obj->pages == NULL);
 	obj->pages_pin_count++;
 }
+
 static inline void i915_gem_object_unpin_pages(struct drm_i915_gem_object *obj)
 {
 	BUG_ON(obj->pages_pin_count == 0);
 	obj->pages_pin_count--;
 }
 
+/**
+ * i915_gem_object_pin_map - return a contiguous mapping of the entire object
+ * @obj - the object to map into kernel address space
+ *
+ * Calls i915_gem_object_pin_pages() to prevent reaping of the object's
+ * pages and then returns a contiguous mapping of the backing storage into
+ * the kernel address space.
+ *
+ * The caller must hold the struct_mutex, and is responsible for calling
+ * i915_gem_object_unpin_map() when the mapping is no longer required.
+ *
+ * Returns the pointer through which to access the mapped object, or an
+ * ERR_PTR() on error.
+ */
+void *__must_check i915_gem_object_pin_map(struct drm_i915_gem_object *obj);
+
+/**
+ * i915_gem_object_unpin_map - releases an earlier mapping
+ * @obj - the object to unmap
+ *
+ * After pinning the object and mapping its pages, once you are finished
+ * with your access, call i915_gem_object_unpin_map() to release the pin
+ * upon the mapping. Once the pin count reaches zero, that mapping may be
+ * removed.
+ *
+ * The caller must hold the struct_mutex.
+ */
+static inline void i915_gem_object_unpin_map(struct drm_i915_gem_object *obj)
+{
+	lockdep_assert_held(&obj->base.dev->struct_mutex);
+	i915_gem_object_unpin_pages(obj);
+}
+
 int __must_check i915_mutex_lock_interruptible(struct drm_device *dev);
 int i915_gem_object_sync(struct drm_i915_gem_object *obj,
 			 struct intel_engine_cs *to,
@@ -3007,42 +3078,68 @@ i915_seqno_passed(uint32_t seq1, uint32_
 static inline bool i915_gem_request_started(struct drm_i915_gem_request *req,
 					   bool lazy_coherency)
 {
-	u32 seqno = req->ring->get_seqno(req->ring, lazy_coherency);
-	return i915_seqno_passed(seqno, req->previous_seqno);
+	if (!lazy_coherency && req->engine->irq_seqno_barrier)
+		req->engine->irq_seqno_barrier(req->engine);
+	return i915_seqno_passed(req->engine->get_seqno(req->engine),
+				 req->previous_seqno);
 }
 
 static inline bool i915_gem_request_completed(struct drm_i915_gem_request *req,
 					      bool lazy_coherency)
 {
-	u32 seqno = req->ring->get_seqno(req->ring, lazy_coherency);
-	return i915_seqno_passed(seqno, req->seqno);
+	if (!lazy_coherency && req->engine->irq_seqno_barrier)
+		req->engine->irq_seqno_barrier(req->engine);
+	return i915_seqno_passed(req->engine->get_seqno(req->engine),
+				 req->seqno);
 }
 
 int __must_check i915_gem_get_seqno(struct drm_device *dev, u32 *seqno);
 int __must_check i915_gem_set_seqno(struct drm_device *dev, u32 seqno);
 
 struct drm_i915_gem_request *
-i915_gem_find_active_request(struct intel_engine_cs *ring);
+i915_gem_find_active_request(struct intel_engine_cs *engine);
 
 bool i915_gem_retire_requests(struct drm_device *dev);
-void i915_gem_retire_requests_ring(struct intel_engine_cs *ring);
-int __must_check i915_gem_check_wedge(struct i915_gpu_error *error,
-				      bool interruptible);
+void i915_gem_retire_requests_ring(struct intel_engine_cs *engine);
+
+static inline u32 i915_reset_counter(struct i915_gpu_error *error)
+{
+	return atomic_read(&error->reset_counter);
+}
+
+static inline bool __i915_reset_in_progress(u32 reset)
+{
+	return unlikely(reset & I915_RESET_IN_PROGRESS_FLAG);
+}
+
+static inline bool __i915_reset_in_progress_or_wedged(u32 reset)
+{
+	return unlikely(reset & (I915_RESET_IN_PROGRESS_FLAG | I915_WEDGED));
+}
+
+static inline bool __i915_terminally_wedged(u32 reset)
+{
+	return unlikely(reset & I915_WEDGED);
+}
 
 static inline bool i915_reset_in_progress(struct i915_gpu_error *error)
 {
-	return unlikely(atomic_read(&error->reset_counter)
-			& (I915_RESET_IN_PROGRESS_FLAG | I915_WEDGED));
+	return __i915_reset_in_progress(i915_reset_counter(error));
+}
+
+static inline bool i915_reset_in_progress_or_wedged(struct i915_gpu_error *error)
+{
+	return __i915_reset_in_progress_or_wedged(i915_reset_counter(error));
 }
 
 static inline bool i915_terminally_wedged(struct i915_gpu_error *error)
 {
-	return atomic_read(&error->reset_counter) & I915_WEDGED;
+	return __i915_terminally_wedged(i915_reset_counter(error));
 }
 
 static inline u32 i915_reset_count(struct i915_gpu_error *error)
 {
-	return ((atomic_read(&error->reset_counter) & ~I915_WEDGED) + 1) / 2;
+	return ((i915_reset_counter(error) & ~I915_WEDGED) + 1) / 2;
 }
 
 static inline bool i915_stop_ring_allow_ban(struct drm_i915_private *dev_priv)
@@ -3060,11 +3157,11 @@ static inline bool i915_stop_ring_allow_
 void i915_gem_reset(struct drm_device *dev);
 bool i915_gem_clflush_object(struct drm_i915_gem_object *obj, bool force);
 int __must_check i915_gem_init(struct drm_device *dev);
-int i915_gem_init_rings(struct drm_device *dev);
+int i915_gem_init_engines(struct drm_device *dev);
 int __must_check i915_gem_init_hw(struct drm_device *dev);
 int i915_gem_l3_remap(struct drm_i915_gem_request *req, int slice);
 void i915_gem_init_swizzling(struct drm_device *dev);
-void i915_gem_cleanup_ringbuffer(struct drm_device *dev);
+void i915_gem_cleanup_engines(struct drm_device *dev);
 int __must_check i915_gpu_idle(struct drm_device *dev);
 int __must_check i915_gem_suspend(struct drm_device *dev);
 void __i915_add_request(struct drm_i915_gem_request *req,
@@ -3075,7 +3172,6 @@ void __i915_add_request(struct drm_i915_
 #define i915_add_request_no_flush(req) \
 	__i915_add_request(req, NULL, false)
 int __i915_wait_request(struct drm_i915_gem_request *req,
-			unsigned reset_counter,
 			bool interruptible,
 			s64 *timeout,
 			struct intel_rps_client *rps);
@@ -3155,13 +3251,9 @@ i915_gem_obj_to_ggtt(struct drm_i915_gem
 bool i915_gem_obj_is_pinned(struct drm_i915_gem_object *obj);
 
 /* Some GGTT VM helpers */
-#define i915_obj_to_ggtt(obj) \
-	(&((struct drm_i915_private *)(obj)->base.dev->dev_private)->gtt.base)
-
 static inline struct i915_hw_ppgtt *
 i915_vm_to_ppgtt(struct i915_address_space *vm)
 {
-	WARN_ON(i915_is_ggtt(vm));
 	return container_of(vm, struct i915_hw_ppgtt, base);
 }
 
@@ -3174,7 +3266,10 @@ static inline bool i915_gem_obj_ggtt_bou
 static inline unsigned long
 i915_gem_obj_ggtt_size(struct drm_i915_gem_object *obj)
 {
-	return i915_gem_obj_size(obj, i915_obj_to_ggtt(obj));
+	struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
+
+	return i915_gem_obj_size(obj, &ggtt->base);
 }
 
 static inline int __must_check
@@ -3182,7 +3277,10 @@ i915_gem_obj_ggtt_pin(struct drm_i915_ge
 		      uint32_t alignment,
 		      unsigned flags)
 {
-	return i915_gem_object_pin(obj, i915_obj_to_ggtt(obj),
+	struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
+
+	return i915_gem_object_pin(obj, &ggtt->base,
 				   alignment, flags | PIN_GLOBAL);
 }
 
@@ -3297,6 +3395,7 @@ unsigned long i915_gem_shrink(struct drm
 #define I915_SHRINK_UNBOUND 0x2
 #define I915_SHRINK_BOUND 0x4
 #define I915_SHRINK_ACTIVE 0x8
+#define I915_SHRINK_VMAPS 0x10
 unsigned long i915_gem_shrink_all(struct drm_i915_private *dev_priv);
 void i915_gem_shrinker_init(struct drm_i915_private *dev_priv);
 void i915_gem_shrinker_cleanup(struct drm_i915_private *dev_priv);
@@ -3343,7 +3442,7 @@ static inline void i915_error_state_buf_
 {
 	kfree(eb->buf);
 }
-void i915_capture_error_state(struct drm_device *dev, bool wedge,
+void i915_capture_error_state(struct drm_device *dev, u32 engine_mask,
 			      const char *error_msg);
 void i915_error_state_get(struct drm_device *dev,
 			  struct i915_error_state_file_priv *error_priv);
@@ -3355,10 +3454,10 @@ const char *i915_cache_level_str(struct
 
 /* i915_cmd_parser.c */
 int i915_cmd_parser_get_version(void);
-int i915_cmd_parser_init_ring(struct intel_engine_cs *ring);
-void i915_cmd_parser_fini_ring(struct intel_engine_cs *ring);
-bool i915_needs_cmd_parser(struct intel_engine_cs *ring);
-int i915_parse_cmds(struct intel_engine_cs *ring,
+int i915_cmd_parser_init_ring(struct intel_engine_cs *engine);
+void i915_cmd_parser_fini_ring(struct intel_engine_cs *engine);
+bool i915_needs_cmd_parser(struct intel_engine_cs *engine);
+int i915_parse_cmds(struct intel_engine_cs *engine,
 		    struct drm_i915_gem_object *batch_obj,
 		    struct drm_i915_gem_object *shadow_batch_obj,
 		    u32 batch_start_offset,
@@ -3392,6 +3491,14 @@ extern void intel_i2c_reset(struct drm_d
 /* intel_bios.c */
 int intel_bios_init(struct drm_i915_private *dev_priv);
 bool intel_bios_is_valid_vbt(const void *buf, size_t size);
+bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv);
+bool intel_bios_is_lvds_present(struct drm_i915_private *dev_priv, u8 *i2c_pin);
+bool intel_bios_is_port_present(struct drm_i915_private *dev_priv, enum port port);
+bool intel_bios_is_port_edp(struct drm_i915_private *dev_priv, enum port port);
+bool intel_bios_is_port_dp_dual_mode(struct drm_i915_private *dev_priv, enum port port);
+bool intel_bios_is_dsi_present(struct drm_i915_private *dev_priv, enum port *port);
+bool intel_bios_is_port_hpd_inverted(struct drm_i915_private *dev_priv,
+				     enum port port);
 
 /* intel_opregion.c */
 #ifdef CONFIG_ACPI
@@ -3403,6 +3510,7 @@ extern int intel_opregion_notify_encoder
 					 bool enable);
 extern int intel_opregion_notify_adapter(struct drm_device *dev,
 					 pci_power_t state);
+extern int intel_opregion_get_panel_type(struct drm_device *dev);
 #else
 static inline int intel_opregion_setup(struct drm_device *dev) { return 0; }
 static inline void intel_opregion_init(struct drm_device *dev) { return; }
@@ -3418,6 +3526,10 @@ intel_opregion_notify_adapter(struct drm
 {
 	return 0;
 }
+static inline int intel_opregion_get_panel_type(struct drm_device *dev)
+{
+	return -ENODEV;
+}
 #endif
 
 /* intel_acpi.c */
@@ -3577,11 +3689,6 @@ static inline i915_reg_t i915_vgacntrl_r
 		return VGACNTRL;
 }
 
-static inline void __user *to_user_ptr(u64 address)
-{
-	return (void __user *)(uintptr_t)address;
-}
-
 static inline unsigned long msecs_to_jiffies_timeout(const unsigned int m)
 {
 	unsigned long j = msecs_to_jiffies(m);
@@ -3629,11 +3736,11 @@ wait_remaining_ms_from_jiffies(unsigned
 	}
 }
 
-static inline void i915_trace_irq_get(struct intel_engine_cs *ring,
+static inline void i915_trace_irq_get(struct intel_engine_cs *engine,
 				      struct drm_i915_gem_request *req)
 {
-	if (ring->trace_irq_req == NULL && ring->irq_get(ring))
-		i915_gem_request_assign(&ring->trace_irq_req, req);
+	if (engine->trace_irq_req == NULL && engine->irq_get(engine))
+		i915_gem_request_assign(&engine->trace_irq_req, req);
 }
 
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_gem.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_gem.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_gem.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_gem.c	2016-07-24 15:23:50.000000000 -0400
@@ -32,14 +32,13 @@
 #include "i915_vgpu.h"
 #include "i915_trace.h"
 #include "intel_drv.h"
+#include "intel_mocs.h"
 #include <linux/shmem_fs.h>
 #include <linux/slab.h>
 #include <linux/swap.h>
 #include <linux/pci.h>
 #include <linux/dma-buf.h>
 
-#define RQ_BUG_ON(expr)
-
 static void i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *obj);
 static void i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *obj);
 static void
@@ -85,9 +84,7 @@ i915_gem_wait_for_error(struct i915_gpu_
 {
 	int ret;
 
-#define EXIT_COND (!i915_reset_in_progress(error) || \
-		   i915_terminally_wedged(error))
-	if (EXIT_COND)
+	if (!i915_reset_in_progress(error))
 		return 0;
 
 	/*
@@ -96,17 +93,16 @@ i915_gem_wait_for_error(struct i915_gpu_
 	 * we should simply try to bail out and fail as gracefully as possible.
 	 */
 	ret = wait_event_interruptible_timeout(error->reset_queue,
-					       EXIT_COND,
+					       !i915_reset_in_progress(error),
 					       10*HZ);
 	if (ret == 0) {
 		DRM_ERROR("Timed out waiting for the gpu reset to complete\n");
 		return -EIO;
 	} else if (ret < 0) {
 		return ret;
+	} else {
+		return 0;
 	}
-#undef EXIT_COND
-
-	return 0;
 }
 
 int i915_mutex_lock_interruptible(struct drm_device *dev)
@@ -130,9 +126,9 @@ int
 i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
 			    struct drm_file *file)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	struct drm_i915_gem_get_aperture *args = data;
-	struct i915_gtt *ggtt = &dev_priv->gtt;
 	struct i915_vma *vma;
 	size_t pinned;
 
@@ -146,7 +142,7 @@ i915_gem_get_aperture_ioctl(struct drm_d
 			pinned += vma->node.size;
 	mutex_unlock(&dev->struct_mutex);
 
-	args->aper_size = dev_priv->gtt.base.total;
+	args->aper_size = ggtt->base.total;
 	args->aper_available_size = args->aper_size - pinned;
 
 	return 0;
@@ -211,11 +207,10 @@ i915_gem_object_put_pages_phys(struct dr
 	BUG_ON(obj->madv == __I915_MADV_PURGED);
 
 	ret = i915_gem_object_set_to_cpu_domain(obj, true);
-	if (ret) {
+	if (WARN_ON(ret)) {
 		/* In the event of a disaster, abandon all caches and
 		 * hope for the best.
 		 */
-		WARN_ON(ret != -EIO);
 		obj->base.read_domains = obj->base.write_domain = I915_GEM_DOMAIN_CPU;
 	}
 
@@ -324,7 +319,7 @@ i915_gem_phys_pwrite(struct drm_i915_gem
 {
 	struct drm_device *dev = obj->base.dev;
 	void *vaddr = obj->phys_handle->vaddr + args->offset;
-	char __user *user_data = to_user_ptr(args->data_ptr);
+	char __user *user_data = u64_to_user_ptr(args->data_ptr);
 	int ret = 0;
 
 	/* We manually control the domain here and pretend that it
@@ -605,7 +600,7 @@ i915_gem_shmem_pread(struct drm_device *
 	int needs_clflush = 0;
 	struct sg_page_iter sg_iter;
 
-	user_data = to_user_ptr(args->data_ptr);
+	user_data = u64_to_user_ptr(args->data_ptr);
 	remain = args->size;
 
 	obj_do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj);
@@ -692,7 +687,7 @@ i915_gem_pread_ioctl(struct drm_device *
 		return 0;
 
 	if (!access_ok(VERIFY_WRITE,
-		       to_user_ptr(args->data_ptr),
+		       u64_to_user_ptr(args->data_ptr),
 		       args->size))
 		return -EFAULT;
 
@@ -700,7 +695,7 @@ i915_gem_pread_ioctl(struct drm_device *
 	if (ret)
 		return ret;
 
-	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
+	obj = to_intel_bo(drm_gem_object_lookup(file, args->handle));
 	if (&obj->base == NULL) {
 		ret = -ENOENT;
 		goto unlock;
@@ -765,7 +760,8 @@ i915_gem_gtt_pwrite_fast(struct drm_devi
 			 struct drm_i915_gem_pwrite *args,
 			 struct drm_file *file)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	ssize_t remain;
 	loff_t offset, page_base;
 	char __user *user_data;
@@ -783,7 +779,7 @@ i915_gem_gtt_pwrite_fast(struct drm_devi
 	if (ret)
 		goto out_unpin;
 
-	user_data = to_user_ptr(args->data_ptr);
+	user_data = u64_to_user_ptr(args->data_ptr);
 	remain = args->size;
 
 	offset = i915_gem_obj_ggtt_offset(obj) + args->offset;
@@ -807,7 +803,7 @@ i915_gem_gtt_pwrite_fast(struct drm_devi
 		 * source page isn't available.  Return the error and we'll
 		 * retry in the slow path.
 		 */
-		if (fast_user_write(dev_priv->gtt.mappable, page_base,
+		if (fast_user_write(ggtt->mappable, page_base,
 				    page_offset, user_data, page_length)) {
 			ret = -EFAULT;
 			goto out_flush;
@@ -907,7 +903,7 @@ i915_gem_shmem_pwrite(struct drm_device
 	int needs_clflush_before = 0;
 	struct sg_page_iter sg_iter;
 
-	user_data = to_user_ptr(args->data_ptr);
+	user_data = u64_to_user_ptr(args->data_ptr);
 	remain = args->size;
 
 	obj_do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj);
@@ -1036,12 +1032,12 @@ i915_gem_pwrite_ioctl(struct drm_device
 		return 0;
 
 	if (!access_ok(VERIFY_READ,
-		       to_user_ptr(args->data_ptr),
+		       u64_to_user_ptr(args->data_ptr),
 		       args->size))
 		return -EFAULT;
 
 	if (likely(!i915.prefault_disable)) {
-		ret = fault_in_multipages_readable(to_user_ptr(args->data_ptr),
+		ret = fault_in_multipages_readable(u64_to_user_ptr(args->data_ptr),
 						   args->size);
 		if (ret)
 			return -EFAULT;
@@ -1053,7 +1049,7 @@ i915_gem_pwrite_ioctl(struct drm_device
 	if (ret)
 		goto put_rpm;
 
-	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
+	obj = to_intel_bo(drm_gem_object_lookup(file, args->handle));
 	if (&obj->base == NULL) {
 		ret = -ENOENT;
 		goto unlock;
@@ -1109,27 +1105,19 @@ put_rpm:
 	return ret;
 }
 
-int
-i915_gem_check_wedge(struct i915_gpu_error *error,
-		     bool interruptible)
+static int
+i915_gem_check_wedge(unsigned reset_counter, bool interruptible)
 {
-	if (i915_reset_in_progress(error)) {
+	if (__i915_terminally_wedged(reset_counter))
+		return -EIO;
+
+	if (__i915_reset_in_progress(reset_counter)) {
 		/* Non-interruptible callers can't handle -EAGAIN, hence return
 		 * -EIO unconditionally for these. */
 		if (!interruptible)
 			return -EIO;
 
-		/* Recovery complete, but the reset failed ... */
-		if (i915_terminally_wedged(error))
-			return -EIO;
-
-		/*
-		 * Check if GPU Reset is in progress - we need intel_ring_begin
-		 * to work properly to reinit the hw state while the gpu is
-		 * still marked as reset-in-progress. Handle this with a flag.
-		 */
-		if (!error->reload_in_reset)
-			return -EAGAIN;
+		return -EAGAIN;
 	}
 
 	return 0;
@@ -1141,9 +1129,9 @@ static void fake_irq(unsigned long data)
 }
 
 static bool missed_irq(struct drm_i915_private *dev_priv,
-		       struct intel_engine_cs *ring)
+		       struct intel_engine_cs *engine)
 {
-	return test_bit(ring->id, &dev_priv->gpu_error.missed_irq_rings);
+	return test_bit(engine->id, &dev_priv->gpu_error.missed_irq_rings);
 }
 
 static unsigned long local_clock_us(unsigned *cpu)
@@ -1193,7 +1181,7 @@ static int __i915_spin_request(struct dr
 	 * takes to sleep on a request, on the order of a microsecond.
 	 */
 
-	if (req->ring->irq_refcount)
+	if (req->engine->irq_refcount)
 		return -EBUSY;
 
 	/* Only spin if we know the GPU is processing this request */
@@ -1223,7 +1211,6 @@ static int __i915_spin_request(struct dr
 /**
  * __i915_wait_request - wait until execution of request has finished
  * @req: duh!
- * @reset_counter: reset sequence associated with the given request
  * @interruptible: do an interruptible wait (normally yes)
  * @timeout: in - how long to wait (NULL forever); out - how much time remaining
  *
@@ -1238,16 +1225,15 @@ static int __i915_spin_request(struct dr
  * errno with remaining time filled in timeout argument.
  */
 int __i915_wait_request(struct drm_i915_gem_request *req,
-			unsigned reset_counter,
 			bool interruptible,
 			s64 *timeout,
 			struct intel_rps_client *rps)
 {
-	struct intel_engine_cs *ring = i915_gem_request_get_ring(req);
-	struct drm_device *dev = ring->dev;
+	struct intel_engine_cs *engine = i915_gem_request_get_engine(req);
+	struct drm_device *dev = engine->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	const bool irq_test_in_progress =
-		ACCESS_ONCE(dev_priv->gpu_error.test_irq_rings) & intel_ring_flag(ring);
+		ACCESS_ONCE(dev_priv->gpu_error.test_irq_rings) & intel_engine_flag(engine);
 	int state = interruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE;
 	DEFINE_WAIT(wait);
 	unsigned long timeout_expire;
@@ -1288,7 +1274,7 @@ int __i915_wait_request(struct drm_i915_
 	if (ret == 0)
 		goto out;
 
-	if (!irq_test_in_progress && WARN_ON(!ring->irq_get(ring))) {
+	if (!irq_test_in_progress && WARN_ON(!engine->irq_get(engine))) {
 		ret = -ENODEV;
 		goto out;
 	}
@@ -1296,16 +1282,17 @@ int __i915_wait_request(struct drm_i915_
 	for (;;) {
 		struct timer_list timer;
 
-		prepare_to_wait(&ring->irq_queue, &wait, state);
+		prepare_to_wait(&engine->irq_queue, &wait, state);
 
 		/* We need to check whether any gpu reset happened in between
-		 * the caller grabbing the seqno and now ... */
-		if (reset_counter != atomic_read(&dev_priv->gpu_error.reset_counter)) {
-			/* ... but upgrade the -EAGAIN to an -EIO if the gpu
-			 * is truely gone. */
-			ret = i915_gem_check_wedge(&dev_priv->gpu_error, interruptible);
-			if (ret == 0)
-				ret = -EAGAIN;
+		 * the request being submitted and now. If a reset has occurred,
+		 * the request is effectively complete (we either are in the
+		 * process of or have discarded the rendering and completely
+		 * reset the GPU. The results of the request are lost and we
+		 * are free to continue on with the original operation.
+		 */
+		if (req->reset_counter != i915_reset_counter(&dev_priv->gpu_error)) {
+			ret = 0;
 			break;
 		}
 
@@ -1325,11 +1312,11 @@ int __i915_wait_request(struct drm_i915_
 		}
 
 		timer.function = NULL;
-		if (timeout || missed_irq(dev_priv, ring)) {
+		if (timeout || missed_irq(dev_priv, engine)) {
 			unsigned long expire;
 
 			setup_timer_on_stack(&timer, fake_irq, (unsigned long)current);
-			expire = missed_irq(dev_priv, ring) ? jiffies + 1 : timeout_expire;
+			expire = missed_irq(dev_priv, engine) ? jiffies + 1 : timeout_expire;
 			mod_timer(&timer, expire);
 		}
 
@@ -1341,9 +1328,9 @@ int __i915_wait_request(struct drm_i915_
 		}
 	}
 	if (!irq_test_in_progress)
-		ring->irq_put(ring);
+		engine->irq_put(engine);
 
-	finish_wait(&ring->irq_queue, &wait);
+	finish_wait(&engine->irq_queue, &wait);
 
 out:
 	trace_i915_gem_request_wait_end(req);
@@ -1370,7 +1357,6 @@ out:
 int i915_gem_request_add_to_client(struct drm_i915_gem_request *req,
 				   struct drm_file *file)
 {
-	struct drm_i915_private *dev_private;
 	struct drm_i915_file_private *file_priv;
 
 	WARN_ON(!req || !file || req->file_priv);
@@ -1381,7 +1367,6 @@ int i915_gem_request_add_to_client(struc
 	if (req->file_priv)
 		return -EINVAL;
 
-	dev_private = req->ring->dev->dev_private;
 	file_priv = file->driver_priv;
 
 	spin_lock(&file_priv->mm.lock);
@@ -1434,7 +1419,7 @@ static void i915_gem_request_retire(stru
 static void
 __i915_gem_request_retire__upto(struct drm_i915_gem_request *req)
 {
-	struct intel_engine_cs *engine = req->ring;
+	struct intel_engine_cs *engine = req->engine;
 	struct drm_i915_gem_request *tmp;
 
 	lockdep_assert_held(&engine->dev->struct_mutex);
@@ -1459,30 +1444,22 @@ __i915_gem_request_retire__upto(struct d
 int
 i915_wait_request(struct drm_i915_gem_request *req)
 {
-	struct drm_device *dev;
-	struct drm_i915_private *dev_priv;
+	struct drm_i915_private *dev_priv = req->i915;
 	bool interruptible;
 	int ret;
 
-	BUG_ON(req == NULL);
-
-	dev = req->ring->dev;
-	dev_priv = dev->dev_private;
 	interruptible = dev_priv->mm.interruptible;
 
-	BUG_ON(!mutex_is_locked(&dev->struct_mutex));
+	BUG_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
 
-	ret = i915_gem_check_wedge(&dev_priv->gpu_error, interruptible);
+	ret = __i915_wait_request(req, interruptible, NULL, NULL);
 	if (ret)
 		return ret;
 
-	ret = __i915_wait_request(req,
-				  atomic_read(&dev_priv->gpu_error.reset_counter),
-				  interruptible, NULL, NULL);
-	if (ret)
-		return ret;
+	/* If the GPU hung, we want to keep the requests to find the guilty. */
+	if (req->reset_counter == i915_reset_counter(&dev_priv->gpu_error))
+		__i915_gem_request_retire__upto(req);
 
-	__i915_gem_request_retire__upto(req);
 	return 0;
 }
 
@@ -1505,14 +1482,14 @@ i915_gem_object_wait_rendering(struct dr
 			if (ret)
 				return ret;
 
-			i = obj->last_write_req->ring->id;
+			i = obj->last_write_req->engine->id;
 			if (obj->last_read_req[i] == obj->last_write_req)
 				i915_gem_object_retire__read(obj, i);
 			else
 				i915_gem_object_retire__write(obj);
 		}
 	} else {
-		for (i = 0; i < I915_NUM_RINGS; i++) {
+		for (i = 0; i < I915_NUM_ENGINES; i++) {
 			if (obj->last_read_req[i] == NULL)
 				continue;
 
@@ -1522,7 +1499,7 @@ i915_gem_object_wait_rendering(struct dr
 
 			i915_gem_object_retire__read(obj, i);
 		}
-		RQ_BUG_ON(obj->active);
+		GEM_BUG_ON(obj->active);
 	}
 
 	return 0;
@@ -1532,14 +1509,15 @@ static void
 i915_gem_object_retire_request(struct drm_i915_gem_object *obj,
 			       struct drm_i915_gem_request *req)
 {
-	int ring = req->ring->id;
+	int ring = req->engine->id;
 
 	if (obj->last_read_req[ring] == req)
 		i915_gem_object_retire__read(obj, ring);
 	else if (obj->last_write_req == req)
 		i915_gem_object_retire__write(obj);
 
-	__i915_gem_request_retire__upto(req);
+	if (req->reset_counter == i915_reset_counter(&req->i915->gpu_error))
+		__i915_gem_request_retire__upto(req);
 }
 
 /* A nonblocking variant of the above wait. This is a highly dangerous routine
@@ -1552,8 +1530,7 @@ i915_gem_object_wait_rendering__nonblock
 {
 	struct drm_device *dev = obj->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_i915_gem_request *requests[I915_NUM_RINGS];
-	unsigned reset_counter;
+	struct drm_i915_gem_request *requests[I915_NUM_ENGINES];
 	int ret, i, n = 0;
 
 	BUG_ON(!mutex_is_locked(&dev->struct_mutex));
@@ -1562,12 +1539,6 @@ i915_gem_object_wait_rendering__nonblock
 	if (!obj->active)
 		return 0;
 
-	ret = i915_gem_check_wedge(&dev_priv->gpu_error, true);
-	if (ret)
-		return ret;
-
-	reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter);
-
 	if (readonly) {
 		struct drm_i915_gem_request *req;
 
@@ -1577,7 +1548,7 @@ i915_gem_object_wait_rendering__nonblock
 
 		requests[n++] = i915_gem_request_reference(req);
 	} else {
-		for (i = 0; i < I915_NUM_RINGS; i++) {
+		for (i = 0; i < I915_NUM_ENGINES; i++) {
 			struct drm_i915_gem_request *req;
 
 			req = obj->last_read_req[i];
@@ -1589,9 +1560,9 @@ i915_gem_object_wait_rendering__nonblock
 	}
 
 	mutex_unlock(&dev->struct_mutex);
+	ret = 0;
 	for (i = 0; ret == 0 && i < n; i++)
-		ret = __i915_wait_request(requests[i], reset_counter, true,
-					  NULL, rps);
+		ret = __i915_wait_request(requests[i], true, NULL, rps);
 	mutex_lock(&dev->struct_mutex);
 
 	for (i = 0; i < n; i++) {
@@ -1640,7 +1611,7 @@ i915_gem_set_domain_ioctl(struct drm_dev
 	if (ret)
 		return ret;
 
-	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
+	obj = to_intel_bo(drm_gem_object_lookup(file, args->handle));
 	if (&obj->base == NULL) {
 		ret = -ENOENT;
 		goto unlock;
@@ -1688,7 +1659,7 @@ i915_gem_sw_finish_ioctl(struct drm_devi
 	if (ret)
 		return ret;
 
-	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
+	obj = to_intel_bo(drm_gem_object_lookup(file, args->handle));
 	if (&obj->base == NULL) {
 		ret = -ENOENT;
 		goto unlock;
@@ -1732,10 +1703,10 @@ i915_gem_mmap_ioctl(struct drm_device *d
 	if (args->flags & ~(I915_MMAP_WC))
 		return -EINVAL;
 
-	if (args->flags & I915_MMAP_WC && !cpu_has_pat)
+	if (args->flags & I915_MMAP_WC && !boot_cpu_has(X86_FEATURE_PAT))
 		return -ENODEV;
 
-	obj = drm_gem_object_lookup(dev, file, args->handle);
+	obj = drm_gem_object_lookup(file, args->handle);
 	if (obj == NULL)
 		return -ENOENT;
 
@@ -1754,7 +1725,10 @@ i915_gem_mmap_ioctl(struct drm_device *d
 		struct mm_struct *mm = current->mm;
 		struct vm_area_struct *vma;
 
-		down_write(&mm->mmap_sem);
+		if (down_write_killable(&mm->mmap_sem)) {
+			drm_gem_object_unreference_unlocked(obj);
+			return -EINTR;
+		}
 		vma = find_vma(mm, addr);
 		if (vma)
 			vma->vm_page_prot =
@@ -1792,7 +1766,8 @@ int i915_gem_fault(struct vm_area_struct
 {
 	struct drm_i915_gem_object *obj = to_intel_bo(vma->vm_private_data);
 	struct drm_device *dev = obj->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	struct i915_ggtt_view view = i915_ggtt_view_normal;
 	pgoff_t page_offset;
 	unsigned long pfn;
@@ -1827,7 +1802,7 @@ int i915_gem_fault(struct vm_area_struct
 	}
 
 	/* Use a partial view if the object is bigger than the aperture. */
-	if (obj->base.size >= dev_priv->gtt.mappable_end &&
+	if (obj->base.size >= ggtt->mappable_end &&
 	    obj->tiling_mode == I915_TILING_NONE) {
 		static const unsigned int chunk_size = 256; // 1 MiB
 
@@ -1855,7 +1830,7 @@ int i915_gem_fault(struct vm_area_struct
 		goto unpin;
 
 	/* Finally, remap it using the new GTT offset */
-	pfn = dev_priv->gtt.mappable_base +
+	pfn = ggtt->mappable_base +
 		i915_gem_obj_ggtt_offset_view(obj, &view);
 	pfn >>= PAGE_SHIFT;
 
@@ -1964,11 +1939,27 @@ out:
 void
 i915_gem_release_mmap(struct drm_i915_gem_object *obj)
 {
+	/* Serialisation between user GTT access and our code depends upon
+	 * revoking the CPU's PTE whilst the mutex is held. The next user
+	 * pagefault then has to wait until we release the mutex.
+	 */
+	lockdep_assert_held(&obj->base.dev->struct_mutex);
+
 	if (!obj->fault_mappable)
 		return;
 
 	drm_vma_node_unmap(&obj->base.vma_node,
 			   obj->base.dev->anon_inode->i_mapping);
+
+	/* Ensure that the CPU's PTE are revoked and there are not outstanding
+	 * memory transactions from userspace before we return. The TLB
+	 * flushing implied above by changing the PTE above *should* be
+	 * sufficient, an extra barrier here just provides us with a bit
+	 * of paranoid documentation about our requirement to serialise
+	 * memory writes before touching registers / GSM.
+	 */
+	wmb();
+
 	obj->fault_mappable = false;
 }
 
@@ -2033,9 +2024,6 @@ static int i915_gem_object_create_mmap_o
 	struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
 	int ret;
 
-	if (drm_vma_node_has_offset(&obj->base.vma_node))
-		return 0;
-
 	dev_priv->mm.shrinker_no_lock_stealing = true;
 
 	ret = drm_gem_create_mmap_offset(&obj->base);
@@ -2084,7 +2072,7 @@ i915_gem_mmap_gtt(struct drm_file *file,
 	if (ret)
 		return ret;
 
-	obj = to_intel_bo(drm_gem_object_lookup(dev, file, handle));
+	obj = to_intel_bo(drm_gem_object_lookup(file, handle));
 	if (&obj->base == NULL) {
 		ret = -ENOENT;
 		goto unlock;
@@ -2180,11 +2168,10 @@ i915_gem_object_put_pages_gtt(struct drm
 	BUG_ON(obj->madv == __I915_MADV_PURGED);
 
 	ret = i915_gem_object_set_to_cpu_domain(obj, true);
-	if (ret) {
+	if (WARN_ON(ret)) {
 		/* In the event of a disaster, abandon all caches and
 		 * hope for the best.
 		 */
-		WARN_ON(ret != -EIO);
 		i915_gem_clflush_object(obj, true);
 		obj->base.read_domains = obj->base.write_domain = I915_GEM_DOMAIN_CPU;
 	}
@@ -2232,6 +2219,14 @@ i915_gem_object_put_pages(struct drm_i91
 	 * lists early. */
 	list_del(&obj->global_list);
 
+	if (obj->mapping) {
+		if (is_vmalloc_addr(obj->mapping))
+			vunmap(obj->mapping);
+		else
+			kunmap(kmap_to_page(obj->mapping));
+		obj->mapping = NULL;
+	}
+
 	ops->put_pages(obj);
 	obj->pages = NULL;
 
@@ -2400,21 +2395,64 @@ i915_gem_object_get_pages(struct drm_i91
 	return 0;
 }
 
+void *i915_gem_object_pin_map(struct drm_i915_gem_object *obj)
+{
+	int ret;
+
+	lockdep_assert_held(&obj->base.dev->struct_mutex);
+
+	ret = i915_gem_object_get_pages(obj);
+	if (ret)
+		return ERR_PTR(ret);
+
+	i915_gem_object_pin_pages(obj);
+
+	if (obj->mapping == NULL) {
+		struct page **pages;
+
+		pages = NULL;
+		if (obj->base.size == PAGE_SIZE)
+			obj->mapping = kmap(sg_page(obj->pages->sgl));
+		else
+			pages = drm_malloc_gfp(obj->base.size >> PAGE_SHIFT,
+					       sizeof(*pages),
+					       GFP_TEMPORARY);
+		if (pages != NULL) {
+			struct sg_page_iter sg_iter;
+			int n;
+
+			n = 0;
+			for_each_sg_page(obj->pages->sgl, &sg_iter,
+					 obj->pages->nents, 0)
+				pages[n++] = sg_page_iter_page(&sg_iter);
+
+			obj->mapping = vmap(pages, n, 0, PAGE_KERNEL);
+			drm_free_large(pages);
+		}
+		if (obj->mapping == NULL) {
+			i915_gem_object_unpin_pages(obj);
+			return ERR_PTR(-ENOMEM);
+		}
+	}
+
+	return obj->mapping;
+}
+
 void i915_vma_move_to_active(struct i915_vma *vma,
 			     struct drm_i915_gem_request *req)
 {
 	struct drm_i915_gem_object *obj = vma->obj;
-	struct intel_engine_cs *ring;
+	struct intel_engine_cs *engine;
 
-	ring = i915_gem_request_get_ring(req);
+	engine = i915_gem_request_get_engine(req);
 
 	/* Add a reference if we're newly entering the active list. */
 	if (obj->active == 0)
 		drm_gem_object_reference(&obj->base);
-	obj->active |= intel_ring_flag(ring);
+	obj->active |= intel_engine_flag(engine);
 
-	list_move_tail(&obj->ring_list[ring->id], &ring->active_list);
-	i915_gem_request_assign(&obj->last_read_req[ring->id], req);
+	list_move_tail(&obj->engine_list[engine->id], &engine->active_list);
+	i915_gem_request_assign(&obj->last_read_req[engine->id], req);
 
 	list_move_tail(&vma->vm_link, &vma->vm->active_list);
 }
@@ -2422,8 +2460,8 @@ void i915_vma_move_to_active(struct i915
 static void
 i915_gem_object_retire__write(struct drm_i915_gem_object *obj)
 {
-	RQ_BUG_ON(obj->last_write_req == NULL);
-	RQ_BUG_ON(!(obj->active & intel_ring_flag(obj->last_write_req->ring)));
+	GEM_BUG_ON(obj->last_write_req == NULL);
+	GEM_BUG_ON(!(obj->active & intel_engine_flag(obj->last_write_req->engine)));
 
 	i915_gem_request_assign(&obj->last_write_req, NULL);
 	intel_fb_obj_flush(obj, true, ORIGIN_CS);
@@ -2434,13 +2472,13 @@ i915_gem_object_retire__read(struct drm_
 {
 	struct i915_vma *vma;
 
-	RQ_BUG_ON(obj->last_read_req[ring] == NULL);
-	RQ_BUG_ON(!(obj->active & (1 << ring)));
+	GEM_BUG_ON(obj->last_read_req[ring] == NULL);
+	GEM_BUG_ON(!(obj->active & (1 << ring)));
 
-	list_del_init(&obj->ring_list[ring]);
+	list_del_init(&obj->engine_list[ring]);
 	i915_gem_request_assign(&obj->last_read_req[ring], NULL);
 
-	if (obj->last_write_req && obj->last_write_req->ring->id == ring)
+	if (obj->last_write_req && obj->last_write_req->engine->id == ring)
 		i915_gem_object_retire__write(obj);
 
 	obj->active &= ~(1 << ring);
@@ -2467,24 +2505,20 @@ static int
 i915_gem_init_seqno(struct drm_device *dev, u32 seqno)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring;
-	int ret, i, j;
+	struct intel_engine_cs *engine;
+	int ret;
 
 	/* Carefully retire all requests without writing to the rings */
-	for_each_ring(ring, dev_priv, i) {
-		ret = intel_ring_idle(ring);
+	for_each_engine(engine, dev_priv) {
+		ret = intel_engine_idle(engine);
 		if (ret)
 			return ret;
 	}
 	i915_gem_retire_requests(dev);
 
 	/* Finally reset hw state */
-	for_each_ring(ring, dev_priv, i) {
-		intel_ring_init_seqno(ring, seqno);
-
-		for (j = 0; j < ARRAY_SIZE(ring->semaphore.sync_seqno); j++)
-			ring->semaphore.sync_seqno[j] = 0;
-	}
+	for_each_engine(engine, dev_priv)
+		intel_ring_init_seqno(engine, seqno);
 
 	return 0;
 }
@@ -2542,7 +2576,7 @@ void __i915_add_request(struct drm_i915_
 			struct drm_i915_gem_object *obj,
 			bool flush_caches)
 {
-	struct intel_engine_cs *ring;
+	struct intel_engine_cs *engine;
 	struct drm_i915_private *dev_priv;
 	struct intel_ringbuffer *ringbuf;
 	u32 request_start;
@@ -2551,8 +2585,8 @@ void __i915_add_request(struct drm_i915_
 	if (WARN_ON(request == NULL))
 		return;
 
-	ring = request->ring;
-	dev_priv = ring->dev->dev_private;
+	engine = request->engine;
+	dev_priv = request->i915;
 	ringbuf = request->ringbuf;
 
 	/*
@@ -2579,6 +2613,28 @@ void __i915_add_request(struct drm_i915_
 		WARN(ret, "*_ring_flush_all_caches failed: %d!\n", ret);
 	}
 
+	trace_i915_gem_request_add(request);
+
+	request->head = request_start;
+
+	/* Whilst this request exists, batch_obj will be on the
+	 * active_list, and so will hold the active reference. Only when this
+	 * request is retired will the the batch_obj be moved onto the
+	 * inactive_list and lose its active reference. Hence we do not need
+	 * to explicitly hold another reference here.
+	 */
+	request->batch_obj = obj;
+
+	/* Seal the request and mark it as pending execution. Note that
+	 * we may inspect this state, without holding any locks, during
+	 * hangcheck. Hence we apply the barrier to ensure that we do not
+	 * see a more recent value in the hws than we are tracking.
+	 */
+	request->emitted_jiffies = jiffies;
+	request->previous_seqno = engine->last_submitted_seqno;
+	smp_store_mb(engine->last_submitted_seqno, request->seqno);
+	list_add_tail(&request->list, &engine->request_list);
+
 	/* Record the position of the start of the request so that
 	 * should we detect the updated seqno part-way through the
 	 * GPU processing the request, we never over-estimate the
@@ -2587,33 +2643,16 @@ void __i915_add_request(struct drm_i915_
 	request->postfix = intel_ring_get_tail(ringbuf);
 
 	if (i915.enable_execlists)
-		ret = ring->emit_request(request);
+		ret = engine->emit_request(request);
 	else {
-		ret = ring->add_request(request);
+		ret = engine->add_request(request);
 
 		request->tail = intel_ring_get_tail(ringbuf);
 	}
 	/* Not allowed to fail! */
 	WARN(ret, "emit|add_request failed: %d!\n", ret);
 
-	request->head = request_start;
-
-	/* Whilst this request exists, batch_obj will be on the
-	 * active_list, and so will hold the active reference. Only when this
-	 * request is retired will the the batch_obj be moved onto the
-	 * inactive_list and lose its active reference. Hence we do not need
-	 * to explicitly hold another reference here.
-	 */
-	request->batch_obj = obj;
-
-	request->emitted_jiffies = jiffies;
-	request->previous_seqno = ring->last_submitted_seqno;
-	ring->last_submitted_seqno = request->seqno;
-	list_add_tail(&request->list, &ring->request_list);
-
-	trace_i915_gem_request_add(request);
-
-	i915_queue_hangcheck(ring->dev);
+	i915_queue_hangcheck(engine->dev);
 
 	queue_delayed_work(dev_priv->wq,
 			   &dev_priv->mm.retire_work,
@@ -2680,7 +2719,7 @@ void i915_gem_request_free(struct kref *
 
 	if (ctx) {
 		if (i915.enable_execlists && ctx != req->i915->kernel_context)
-			intel_lr_context_unpin(ctx, req->ring);
+			intel_lr_context_unpin(ctx, req->engine);
 
 		i915_gem_context_unreference(ctx);
 	}
@@ -2689,11 +2728,12 @@ void i915_gem_request_free(struct kref *
 }
 
 static inline int
-__i915_gem_request_alloc(struct intel_engine_cs *ring,
+__i915_gem_request_alloc(struct intel_engine_cs *engine,
 			 struct intel_context *ctx,
 			 struct drm_i915_gem_request **req_out)
 {
-	struct drm_i915_private *dev_priv = to_i915(ring->dev);
+	struct drm_i915_private *dev_priv = to_i915(engine->dev);
+	unsigned reset_counter = i915_reset_counter(&dev_priv->gpu_error);
 	struct drm_i915_gem_request *req;
 	int ret;
 
@@ -2702,17 +2742,26 @@ __i915_gem_request_alloc(struct intel_en
 
 	*req_out = NULL;
 
+	/* ABI: Before userspace accesses the GPU (e.g. execbuffer), report
+	 * EIO if the GPU is already wedged, or EAGAIN to drop the struct_mutex
+	 * and restart.
+	 */
+	ret = i915_gem_check_wedge(reset_counter, dev_priv->mm.interruptible);
+	if (ret)
+		return ret;
+
 	req = kmem_cache_zalloc(dev_priv->requests, GFP_KERNEL);
 	if (req == NULL)
 		return -ENOMEM;
 
-	ret = i915_gem_get_seqno(ring->dev, &req->seqno);
+	ret = i915_gem_get_seqno(engine->dev, &req->seqno);
 	if (ret)
 		goto err;
 
 	kref_init(&req->ref);
 	req->i915 = dev_priv;
-	req->ring = ring;
+	req->engine = engine;
+	req->reset_counter = reset_counter;
 	req->ctx  = ctx;
 	i915_gem_context_reference(req->ctx);
 
@@ -2742,7 +2791,8 @@ __i915_gem_request_alloc(struct intel_en
 		 * fully prepared. Thus it can be cleaned up using the proper
 		 * free code.
 		 */
-		i915_gem_request_cancel(req);
+		intel_ring_reserved_space_cancel(req->ringbuf);
+		i915_gem_request_unreference(req);
 		return ret;
 	}
 
@@ -2779,19 +2829,12 @@ i915_gem_request_alloc(struct intel_engi
 	return err ? ERR_PTR(err) : req;
 }
 
-void i915_gem_request_cancel(struct drm_i915_gem_request *req)
-{
-	intel_ring_reserved_space_cancel(req->ringbuf);
-
-	i915_gem_request_unreference(req);
-}
-
 struct drm_i915_gem_request *
-i915_gem_find_active_request(struct intel_engine_cs *ring)
+i915_gem_find_active_request(struct intel_engine_cs *engine)
 {
 	struct drm_i915_gem_request *request;
 
-	list_for_each_entry(request, &ring->request_list, list) {
+	list_for_each_entry(request, &engine->request_list, list) {
 		if (i915_gem_request_completed(request, false))
 			continue;
 
@@ -2801,38 +2844,38 @@ i915_gem_find_active_request(struct inte
 	return NULL;
 }
 
-static void i915_gem_reset_ring_status(struct drm_i915_private *dev_priv,
-				       struct intel_engine_cs *ring)
+static void i915_gem_reset_engine_status(struct drm_i915_private *dev_priv,
+				       struct intel_engine_cs *engine)
 {
 	struct drm_i915_gem_request *request;
 	bool ring_hung;
 
-	request = i915_gem_find_active_request(ring);
+	request = i915_gem_find_active_request(engine);
 
 	if (request == NULL)
 		return;
 
-	ring_hung = ring->hangcheck.score >= HANGCHECK_SCORE_RING_HUNG;
+	ring_hung = engine->hangcheck.score >= HANGCHECK_SCORE_RING_HUNG;
 
 	i915_set_reset_status(dev_priv, request->ctx, ring_hung);
 
-	list_for_each_entry_continue(request, &ring->request_list, list)
+	list_for_each_entry_continue(request, &engine->request_list, list)
 		i915_set_reset_status(dev_priv, request->ctx, false);
 }
 
-static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv,
-					struct intel_engine_cs *ring)
+static void i915_gem_reset_engine_cleanup(struct drm_i915_private *dev_priv,
+					struct intel_engine_cs *engine)
 {
 	struct intel_ringbuffer *buffer;
 
-	while (!list_empty(&ring->active_list)) {
+	while (!list_empty(&engine->active_list)) {
 		struct drm_i915_gem_object *obj;
 
-		obj = list_first_entry(&ring->active_list,
+		obj = list_first_entry(&engine->active_list,
 				       struct drm_i915_gem_object,
-				       ring_list[ring->id]);
+				       engine_list[engine->id]);
 
-		i915_gem_object_retire__read(obj, ring->id);
+		i915_gem_object_retire__read(obj, engine->id);
 	}
 
 	/*
@@ -2842,14 +2885,16 @@ static void i915_gem_reset_ring_cleanup(
 	 */
 
 	if (i915.enable_execlists) {
-		spin_lock_irq(&ring->execlist_lock);
+		/* Ensure irq handler finishes or is cancelled. */
+		tasklet_kill(&engine->irq_tasklet);
 
+		spin_lock_bh(&engine->execlist_lock);
 		/* list_splice_tail_init checks for empty lists */
-		list_splice_tail_init(&ring->execlist_queue,
-				      &ring->execlist_retired_req_list);
+		list_splice_tail_init(&engine->execlist_queue,
+				      &engine->execlist_retired_req_list);
+		spin_unlock_bh(&engine->execlist_lock);
 
-		spin_unlock_irq(&ring->execlist_lock);
-		intel_execlists_retire_requests(ring);
+		intel_execlists_retire_requests(engine);
 	}
 
 	/*
@@ -2859,10 +2904,10 @@ static void i915_gem_reset_ring_cleanup(
 	 * implicit references on things like e.g. ppgtt address spaces through
 	 * the request.
 	 */
-	while (!list_empty(&ring->request_list)) {
+	while (!list_empty(&engine->request_list)) {
 		struct drm_i915_gem_request *request;
 
-		request = list_first_entry(&ring->request_list,
+		request = list_first_entry(&engine->request_list,
 					   struct drm_i915_gem_request,
 					   list);
 
@@ -2876,28 +2921,29 @@ static void i915_gem_reset_ring_cleanup(
 	 * upon reset is less than when we start. Do one more pass over
 	 * all the ringbuffers to reset last_retired_head.
 	 */
-	list_for_each_entry(buffer, &ring->buffers, link) {
+	list_for_each_entry(buffer, &engine->buffers, link) {
 		buffer->last_retired_head = buffer->tail;
 		intel_ring_update_space(buffer);
 	}
+
+	intel_ring_init_seqno(engine, engine->last_submitted_seqno);
 }
 
 void i915_gem_reset(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring;
-	int i;
+	struct intel_engine_cs *engine;
 
 	/*
 	 * Before we free the objects from the requests, we need to inspect
 	 * them for finding the guilty party. As the requests only borrow
 	 * their reference to the objects, the inspection must be done first.
 	 */
-	for_each_ring(ring, dev_priv, i)
-		i915_gem_reset_ring_status(dev_priv, ring);
+	for_each_engine(engine, dev_priv)
+		i915_gem_reset_engine_status(dev_priv, engine);
 
-	for_each_ring(ring, dev_priv, i)
-		i915_gem_reset_ring_cleanup(dev_priv, ring);
+	for_each_engine(engine, dev_priv)
+		i915_gem_reset_engine_cleanup(dev_priv, engine);
 
 	i915_gem_context_reset(dev);
 
@@ -2910,19 +2956,19 @@ void i915_gem_reset(struct drm_device *d
  * This function clears the request list as sequence numbers are passed.
  */
 void
-i915_gem_retire_requests_ring(struct intel_engine_cs *ring)
+i915_gem_retire_requests_ring(struct intel_engine_cs *engine)
 {
-	WARN_ON(i915_verify_lists(ring->dev));
+	WARN_ON(i915_verify_lists(engine->dev));
 
 	/* Retire requests first as we use it above for the early return.
 	 * If we retire requests last, we may use a later seqno and so clear
 	 * the requests lists without clearing the active list, leading to
 	 * confusion.
 	 */
-	while (!list_empty(&ring->request_list)) {
+	while (!list_empty(&engine->request_list)) {
 		struct drm_i915_gem_request *request;
 
-		request = list_first_entry(&ring->request_list,
+		request = list_first_entry(&engine->request_list,
 					   struct drm_i915_gem_request,
 					   list);
 
@@ -2936,45 +2982,44 @@ i915_gem_retire_requests_ring(struct int
 	 * by the ringbuffer to the flushing/inactive lists as appropriate,
 	 * before we free the context associated with the requests.
 	 */
-	while (!list_empty(&ring->active_list)) {
+	while (!list_empty(&engine->active_list)) {
 		struct drm_i915_gem_object *obj;
 
-		obj = list_first_entry(&ring->active_list,
-				      struct drm_i915_gem_object,
-				      ring_list[ring->id]);
+		obj = list_first_entry(&engine->active_list,
+				       struct drm_i915_gem_object,
+				       engine_list[engine->id]);
 
-		if (!list_empty(&obj->last_read_req[ring->id]->list))
+		if (!list_empty(&obj->last_read_req[engine->id]->list))
 			break;
 
-		i915_gem_object_retire__read(obj, ring->id);
+		i915_gem_object_retire__read(obj, engine->id);
 	}
 
-	if (unlikely(ring->trace_irq_req &&
-		     i915_gem_request_completed(ring->trace_irq_req, true))) {
-		ring->irq_put(ring);
-		i915_gem_request_assign(&ring->trace_irq_req, NULL);
+	if (unlikely(engine->trace_irq_req &&
+		     i915_gem_request_completed(engine->trace_irq_req, true))) {
+		engine->irq_put(engine);
+		i915_gem_request_assign(&engine->trace_irq_req, NULL);
 	}
 
-	WARN_ON(i915_verify_lists(ring->dev));
+	WARN_ON(i915_verify_lists(engine->dev));
 }
 
 bool
 i915_gem_retire_requests(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring;
+	struct intel_engine_cs *engine;
 	bool idle = true;
-	int i;
 
-	for_each_ring(ring, dev_priv, i) {
-		i915_gem_retire_requests_ring(ring);
-		idle &= list_empty(&ring->request_list);
+	for_each_engine(engine, dev_priv) {
+		i915_gem_retire_requests_ring(engine);
+		idle &= list_empty(&engine->request_list);
 		if (i915.enable_execlists) {
-			spin_lock_irq(&ring->execlist_lock);
-			idle &= list_empty(&ring->execlist_queue);
-			spin_unlock_irq(&ring->execlist_lock);
+			spin_lock_bh(&engine->execlist_lock);
+			idle &= list_empty(&engine->execlist_queue);
+			spin_unlock_bh(&engine->execlist_lock);
 
-			intel_execlists_retire_requests(ring);
+			intel_execlists_retire_requests(engine);
 		}
 	}
 
@@ -3011,25 +3056,21 @@ i915_gem_idle_work_handler(struct work_s
 	struct drm_i915_private *dev_priv =
 		container_of(work, typeof(*dev_priv), mm.idle_work.work);
 	struct drm_device *dev = dev_priv->dev;
-	struct intel_engine_cs *ring;
-	int i;
+	struct intel_engine_cs *engine;
 
-	for_each_ring(ring, dev_priv, i)
-		if (!list_empty(&ring->request_list))
+	for_each_engine(engine, dev_priv)
+		if (!list_empty(&engine->request_list))
 			return;
 
 	/* we probably should sync with hangcheck here, using cancel_work_sync.
-	 * Also locking seems to be fubar here, ring->request_list is protected
+	 * Also locking seems to be fubar here, engine->request_list is protected
 	 * by dev->struct_mutex. */
 
 	intel_mark_idle(dev);
 
 	if (mutex_trylock(&dev->struct_mutex)) {
-		struct intel_engine_cs *ring;
-		int i;
-
-		for_each_ring(ring, dev_priv, i)
-			i915_gem_batch_pool_fini(&ring->batch_pool);
+		for_each_engine(engine, dev_priv)
+			i915_gem_batch_pool_fini(&engine->batch_pool);
 
 		mutex_unlock(&dev->struct_mutex);
 	}
@@ -3048,7 +3089,7 @@ i915_gem_object_flush_active(struct drm_
 	if (!obj->active)
 		return 0;
 
-	for (i = 0; i < I915_NUM_RINGS; i++) {
+	for (i = 0; i < I915_NUM_ENGINES; i++) {
 		struct drm_i915_gem_request *req;
 
 		req = obj->last_read_req[i];
@@ -3093,11 +3134,9 @@ retire:
 int
 i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_gem_wait *args = data;
 	struct drm_i915_gem_object *obj;
-	struct drm_i915_gem_request *req[I915_NUM_RINGS];
-	unsigned reset_counter;
+	struct drm_i915_gem_request *req[I915_NUM_ENGINES];
 	int i, n = 0;
 	int ret;
 
@@ -3108,7 +3147,7 @@ i915_gem_wait_ioctl(struct drm_device *d
 	if (ret)
 		return ret;
 
-	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->bo_handle));
+	obj = to_intel_bo(drm_gem_object_lookup(file, args->bo_handle));
 	if (&obj->base == NULL) {
 		mutex_unlock(&dev->struct_mutex);
 		return -ENOENT;
@@ -3131,9 +3170,8 @@ i915_gem_wait_ioctl(struct drm_device *d
 	}
 
 	drm_gem_object_unreference(&obj->base);
-	reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter);
 
-	for (i = 0; i < I915_NUM_RINGS; i++) {
+	for (i = 0; i < I915_NUM_ENGINES; i++) {
 		if (obj->last_read_req[i] == NULL)
 			continue;
 
@@ -3144,7 +3182,7 @@ i915_gem_wait_ioctl(struct drm_device *d
 
 	for (i = 0; i < n; i++) {
 		if (ret == 0)
-			ret = __i915_wait_request(req[i], reset_counter, true,
+			ret = __i915_wait_request(req[i], true,
 						  args->timeout_ns > 0 ? &args->timeout_ns : NULL,
 						  to_rps_client(file));
 		i915_gem_request_unreference__unlocked(req[i]);
@@ -3166,7 +3204,7 @@ __i915_gem_object_sync(struct drm_i915_g
 	struct intel_engine_cs *from;
 	int ret;
 
-	from = i915_gem_request_get_ring(from_req);
+	from = i915_gem_request_get_engine(from_req);
 	if (to == from)
 		return 0;
 
@@ -3176,7 +3214,6 @@ __i915_gem_object_sync(struct drm_i915_g
 	if (!i915_semaphore_is_enabled(obj->base.dev)) {
 		struct drm_i915_private *i915 = to_i915(obj->base.dev);
 		ret = __i915_wait_request(from_req,
-					  atomic_read(&i915->gpu_error.reset_counter),
 					  i915->mm.interruptible,
 					  NULL,
 					  &i915->rps.semaphores);
@@ -3260,7 +3297,7 @@ i915_gem_object_sync(struct drm_i915_gem
 		     struct drm_i915_gem_request **to_req)
 {
 	const bool readonly = obj->base.pending_write_domain == 0;
-	struct drm_i915_gem_request *req[I915_NUM_RINGS];
+	struct drm_i915_gem_request *req[I915_NUM_ENGINES];
 	int ret, i, n;
 
 	if (!obj->active)
@@ -3274,7 +3311,7 @@ i915_gem_object_sync(struct drm_i915_gem
 		if (obj->last_write_req)
 			req[n++] = obj->last_write_req;
 	} else {
-		for (i = 0; i < I915_NUM_RINGS; i++)
+		for (i = 0; i < I915_NUM_ENGINES; i++)
 			if (obj->last_read_req[i])
 				req[n++] = obj->last_read_req[i];
 	}
@@ -3297,9 +3334,6 @@ static void i915_gem_object_finish_gtt(s
 	if ((obj->base.read_domains & I915_GEM_DOMAIN_GTT) == 0)
 		return;
 
-	/* Wait for any direct GTT access to complete */
-	mb();
-
 	old_read_domains = obj->base.read_domains;
 	old_write_domain = obj->base.write_domain;
 
@@ -3391,28 +3425,25 @@ int __i915_vma_unbind_no_wait(struct i91
 int i915_gpu_idle(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring;
-	int ret, i;
+	struct intel_engine_cs *engine;
+	int ret;
 
 	/* Flush everything onto the inactive list. */
-	for_each_ring(ring, dev_priv, i) {
+	for_each_engine(engine, dev_priv) {
 		if (!i915.enable_execlists) {
 			struct drm_i915_gem_request *req;
 
-			req = i915_gem_request_alloc(ring, NULL);
+			req = i915_gem_request_alloc(engine, NULL);
 			if (IS_ERR(req))
 				return PTR_ERR(req);
 
 			ret = i915_switch_context(req);
-			if (ret) {
-				i915_gem_request_cancel(req);
-				return ret;
-			}
-
 			i915_add_request_no_flush(req);
+			if (ret)
+				return ret;
 		}
 
-		ret = intel_ring_idle(ring);
+		ret = intel_engine_idle(engine);
 		if (ret)
 			return ret;
 	}
@@ -3466,7 +3497,8 @@ i915_gem_object_bind_to_vm(struct drm_i9
 			   uint64_t flags)
 {
 	struct drm_device *dev = obj->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	u32 fence_alignment, unfenced_alignment;
 	u32 search_flag, alloc_flag;
 	u64 start, end;
@@ -3513,7 +3545,7 @@ i915_gem_object_bind_to_vm(struct drm_i9
 	start = flags & PIN_OFFSET_BIAS ? flags & PIN_OFFSET_MASK : 0;
 	end = vm->total;
 	if (flags & PIN_MAPPABLE)
-		end = min_t(u64, end, dev_priv->gtt.mappable_end);
+		end = min_t(u64, end, ggtt->mappable_end);
 	if (flags & PIN_ZONE_4G)
 		end = min_t(u64, end, (1ULL << 32) - PAGE_SIZE);
 
@@ -3720,6 +3752,9 @@ i915_gem_object_flush_cpu_write_domain(s
 int
 i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
 {
+	struct drm_device *dev = obj->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	uint32_t old_write_domain, old_read_domains;
 	struct i915_vma *vma;
 	int ret;
@@ -3774,7 +3809,7 @@ i915_gem_object_set_to_gtt_domain(struct
 	vma = i915_gem_obj_to_ggtt(obj);
 	if (vma && drm_mm_node_allocated(&vma->node) && !obj->active)
 		list_move_tail(&vma->vm_link,
-			       &to_i915(obj->base.dev)->gtt.base.inactive_list);
+			       &ggtt->base.inactive_list);
 
 	return 0;
 }
@@ -3906,7 +3941,7 @@ int i915_gem_get_caching_ioctl(struct dr
 	struct drm_i915_gem_caching *args = data;
 	struct drm_i915_gem_object *obj;
 
-	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
+	obj = to_intel_bo(drm_gem_object_lookup(file, args->handle));
 	if (&obj->base == NULL)
 		return -ENOENT;
 
@@ -3949,7 +3984,7 @@ int i915_gem_set_caching_ioctl(struct dr
 		 * cacheline, whereas normally such cachelines would get
 		 * invalidated.
 		 */
-		if (IS_BXT_REVID(dev, 0, BXT_REVID_A1))
+		if (!HAS_LLC(dev) && !HAS_SNOOP(dev))
 			return -ENODEV;
 
 		level = I915_CACHE_LLC;
@@ -3967,7 +4002,7 @@ int i915_gem_set_caching_ioctl(struct dr
 	if (ret)
 		goto rpm_put;
 
-	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
+	obj = to_intel_bo(drm_gem_object_lookup(file, args->handle));
 	if (&obj->base == NULL) {
 		ret = -ENOENT;
 		goto unlock;
@@ -4128,16 +4163,15 @@ i915_gem_ring_throttle(struct drm_device
 	struct drm_i915_file_private *file_priv = file->driver_priv;
 	unsigned long recent_enough = jiffies - DRM_I915_THROTTLE_JIFFIES;
 	struct drm_i915_gem_request *request, *target = NULL;
-	unsigned reset_counter;
 	int ret;
 
 	ret = i915_gem_wait_for_error(&dev_priv->gpu_error);
 	if (ret)
 		return ret;
 
-	ret = i915_gem_check_wedge(&dev_priv->gpu_error, false);
-	if (ret)
-		return ret;
+	/* ABI: return -EIO if already wedged */
+	if (i915_terminally_wedged(&dev_priv->gpu_error))
+		return -EIO;
 
 	spin_lock(&file_priv->mm.lock);
 	list_for_each_entry(request, &file_priv->mm.request_list, client_list) {
@@ -4153,7 +4187,6 @@ i915_gem_ring_throttle(struct drm_device
 
 		target = request;
 	}
-	reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter);
 	if (target)
 		i915_gem_request_reference(target);
 	spin_unlock(&file_priv->mm.lock);
@@ -4161,7 +4194,7 @@ i915_gem_ring_throttle(struct drm_device
 	if (target == NULL)
 		return 0;
 
-	ret = __i915_wait_request(target, reset_counter, true, NULL, NULL);
+	ret = __i915_wait_request(target, true, NULL, NULL);
 	if (ret == 0)
 		queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, 0);
 
@@ -4211,7 +4244,7 @@ void __i915_vma_set_map_and_fenceable(st
 		     (vma->node.start & (fence_alignment - 1)) == 0);
 
 	mappable = (vma->node.start + fence_size <=
-		    to_i915(obj->base.dev)->gtt.mappable_end);
+		    to_i915(obj->base.dev)->ggtt.mappable_end);
 
 	obj->map_and_fenceable = mappable && fenceable;
 }
@@ -4243,9 +4276,6 @@ i915_gem_object_do_pin(struct drm_i915_g
 	vma = ggtt_view ? i915_gem_obj_to_ggtt_view(obj, ggtt_view) :
 			  i915_gem_obj_to_vma(obj, vm);
 
-	if (IS_ERR(vma))
-		return PTR_ERR(vma);
-
 	if (vma) {
 		if (WARN_ON(vma->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT))
 			return -EBUSY;
@@ -4308,10 +4338,13 @@ i915_gem_object_ggtt_pin(struct drm_i915
 			 uint32_t alignment,
 			 uint64_t flags)
 {
-	if (WARN_ONCE(!view, "no view specified"))
-		return -EINVAL;
+	struct drm_device *dev = obj->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 
-	return i915_gem_object_do_pin(obj, i915_obj_to_ggtt(obj), view,
+	BUG_ON(!view);
+
+	return i915_gem_object_do_pin(obj, &ggtt->base, view,
 				      alignment, flags | PIN_GLOBAL);
 }
 
@@ -4321,7 +4354,6 @@ i915_gem_object_ggtt_unpin_view(struct d
 {
 	struct i915_vma *vma = i915_gem_obj_to_ggtt_view(obj, view);
 
-	BUG_ON(!vma);
 	WARN_ON(vma->pin_count == 0);
 	WARN_ON(!i915_gem_obj_ggtt_bound_view(obj, view));
 
@@ -4340,7 +4372,7 @@ i915_gem_busy_ioctl(struct drm_device *d
 	if (ret)
 		return ret;
 
-	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
+	obj = to_intel_bo(drm_gem_object_lookup(file, args->handle));
 	if (&obj->base == NULL) {
 		ret = -ENOENT;
 		goto unlock;
@@ -4359,15 +4391,15 @@ i915_gem_busy_ioctl(struct drm_device *d
 	if (obj->active) {
 		int i;
 
-		for (i = 0; i < I915_NUM_RINGS; i++) {
+		for (i = 0; i < I915_NUM_ENGINES; i++) {
 			struct drm_i915_gem_request *req;
 
 			req = obj->last_read_req[i];
 			if (req)
-				args->busy |= 1 << (16 + req->ring->exec_id);
+				args->busy |= 1 << (16 + req->engine->exec_id);
 		}
 		if (obj->last_write_req)
-			args->busy |= obj->last_write_req->ring->exec_id;
+			args->busy |= obj->last_write_req->engine->exec_id;
 	}
 
 unref:
@@ -4405,7 +4437,7 @@ i915_gem_madvise_ioctl(struct drm_device
 	if (ret)
 		return ret;
 
-	obj = to_intel_bo(drm_gem_object_lookup(dev, file_priv, args->handle));
+	obj = to_intel_bo(drm_gem_object_lookup(file_priv, args->handle));
 	if (&obj->base == NULL) {
 		ret = -ENOENT;
 		goto unlock;
@@ -4447,8 +4479,8 @@ void i915_gem_object_init(struct drm_i91
 	int i;
 
 	INIT_LIST_HEAD(&obj->global_list);
-	for (i = 0; i < I915_NUM_RINGS; i++)
-		INIT_LIST_HEAD(&obj->ring_list[i]);
+	for (i = 0; i < I915_NUM_ENGINES; i++)
+		INIT_LIST_HEAD(&obj->engine_list[i]);
 	INIT_LIST_HEAD(&obj->obj_exec_link);
 	INIT_LIST_HEAD(&obj->vma_list);
 	INIT_LIST_HEAD(&obj->batch_pool_link);
@@ -4623,14 +4655,15 @@ struct i915_vma *i915_gem_obj_to_vma(str
 struct i915_vma *i915_gem_obj_to_ggtt_view(struct drm_i915_gem_object *obj,
 					   const struct i915_ggtt_view *view)
 {
-	struct i915_address_space *ggtt = i915_obj_to_ggtt(obj);
+	struct drm_device *dev = obj->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	struct i915_vma *vma;
 
-	if (WARN_ONCE(!view, "no view specified"))
-		return ERR_PTR(-EINVAL);
+	BUG_ON(!view);
 
 	list_for_each_entry(vma, &obj->vma_list, obj_link)
-		if (vma->vm == ggtt &&
+		if (vma->vm == &ggtt->base &&
 		    i915_ggtt_view_equal(&vma->ggtt_view, view))
 			return vma;
 	return NULL;
@@ -4653,14 +4686,13 @@ void i915_gem_vma_destroy(struct i915_vm
 }
 
 static void
-i915_gem_stop_ringbuffers(struct drm_device *dev)
+i915_gem_stop_engines(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring;
-	int i;
+	struct intel_engine_cs *engine;
 
-	for_each_ring(ring, dev_priv, i)
-		dev_priv->gt.stop_ring(ring);
+	for_each_engine(engine, dev_priv)
+		dev_priv->gt.stop_engine(engine);
 }
 
 int
@@ -4676,7 +4708,7 @@ i915_gem_suspend(struct drm_device *dev)
 
 	i915_gem_retire_requests(dev);
 
-	i915_gem_stop_ringbuffers(dev);
+	i915_gem_stop_engines(dev);
 	mutex_unlock(&dev->struct_mutex);
 
 	cancel_delayed_work_sync(&dev_priv->gpu_error.hangcheck_work);
@@ -4697,8 +4729,8 @@ err:
 
 int i915_gem_l3_remap(struct drm_i915_gem_request *req, int slice)
 {
-	struct intel_engine_cs *ring = req->ring;
-	struct drm_device *dev = ring->dev;
+	struct intel_engine_cs *engine = req->engine;
+	struct drm_device *dev = engine->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 *remap_info = dev_priv->l3_parity.remap_info[slice];
 	int i, ret;
@@ -4716,12 +4748,12 @@ int i915_gem_l3_remap(struct drm_i915_ge
 	 * at initialization time.
 	 */
 	for (i = 0; i < GEN7_L3LOG_SIZE / 4; i++) {
-		intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
-		intel_ring_emit_reg(ring, GEN7_L3LOG(slice, i));
-		intel_ring_emit(ring, remap_info[i]);
+		intel_ring_emit(engine, MI_LOAD_REGISTER_IMM(1));
+		intel_ring_emit_reg(engine, GEN7_L3LOG(slice, i));
+		intel_ring_emit(engine, remap_info[i]);
 	}
 
-	intel_ring_advance(ring);
+	intel_ring_advance(engine);
 
 	return ret;
 }
@@ -4778,7 +4810,7 @@ static void init_unused_rings(struct drm
 	}
 }
 
-int i915_gem_init_rings(struct drm_device *dev)
+int i915_gem_init_engines(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int ret;
@@ -4814,13 +4846,13 @@ int i915_gem_init_rings(struct drm_devic
 	return 0;
 
 cleanup_vebox_ring:
-	intel_cleanup_ring_buffer(&dev_priv->ring[VECS]);
+	intel_cleanup_engine(&dev_priv->engine[VECS]);
 cleanup_blt_ring:
-	intel_cleanup_ring_buffer(&dev_priv->ring[BCS]);
+	intel_cleanup_engine(&dev_priv->engine[BCS]);
 cleanup_bsd_ring:
-	intel_cleanup_ring_buffer(&dev_priv->ring[VCS]);
+	intel_cleanup_engine(&dev_priv->engine[VCS]);
 cleanup_render_ring:
-	intel_cleanup_ring_buffer(&dev_priv->ring[RCS]);
+	intel_cleanup_engine(&dev_priv->engine[RCS]);
 
 	return ret;
 }
@@ -4829,16 +4861,13 @@ int
 i915_gem_init_hw(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring;
-	int ret, i, j;
-
-	if (INTEL_INFO(dev)->gen < 6 && !intel_enable_gtt())
-		return -EIO;
+	struct intel_engine_cs *engine;
+	int ret, j;
 
 	/* Double layer security blanket, see i915_gem_init() */
 	intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
 
-	if (dev_priv->ellc_size)
+	if (HAS_EDRAM(dev) && INTEL_GEN(dev_priv) < 9)
 		I915_WRITE(HSW_IDICR, I915_READ(HSW_IDICR) | IDIHASHMSK(0xf));
 
 	if (IS_HASWELL(dev))
@@ -4876,12 +4905,14 @@ i915_gem_init_hw(struct drm_device *dev)
 	}
 
 	/* Need to do basic initialisation of all rings first: */
-	for_each_ring(ring, dev_priv, i) {
-		ret = ring->init_hw(ring);
+	for_each_engine(engine, dev_priv) {
+		ret = engine->init_hw(engine);
 		if (ret)
 			goto out;
 	}
 
+	intel_mocs_init_l3cc_table(dev);
+
 	/* We can't enable contexts until all firmware is loaded */
 	if (HAS_GUC_UCODE(dev)) {
 		ret = intel_guc_ucode_load(dev);
@@ -4901,38 +4932,39 @@ i915_gem_init_hw(struct drm_device *dev)
 		goto out;
 
 	/* Now it is safe to go back round and do everything else: */
-	for_each_ring(ring, dev_priv, i) {
+	for_each_engine(engine, dev_priv) {
 		struct drm_i915_gem_request *req;
 
-		req = i915_gem_request_alloc(ring, NULL);
+		req = i915_gem_request_alloc(engine, NULL);
 		if (IS_ERR(req)) {
 			ret = PTR_ERR(req);
-			i915_gem_cleanup_ringbuffer(dev);
-			goto out;
+			break;
 		}
 
-		if (ring->id == RCS) {
-			for (j = 0; j < NUM_L3_SLICES(dev); j++)
-				i915_gem_l3_remap(req, j);
+		if (engine->id == RCS) {
+			for (j = 0; j < NUM_L3_SLICES(dev); j++) {
+				ret = i915_gem_l3_remap(req, j);
+				if (ret)
+					goto err_request;
+			}
 		}
 
 		ret = i915_ppgtt_init_ring(req);
-		if (ret && ret != -EIO) {
-			DRM_ERROR("PPGTT enable ring #%d failed %d\n", i, ret);
-			i915_gem_request_cancel(req);
-			i915_gem_cleanup_ringbuffer(dev);
-			goto out;
-		}
+		if (ret)
+			goto err_request;
 
 		ret = i915_gem_context_enable(req);
-		if (ret && ret != -EIO) {
-			DRM_ERROR("Context enable ring #%d failed %d\n", i, ret);
-			i915_gem_request_cancel(req);
-			i915_gem_cleanup_ringbuffer(dev);
-			goto out;
-		}
+		if (ret)
+			goto err_request;
 
+err_request:
 		i915_add_request_no_flush(req);
+		if (ret) {
+			DRM_ERROR("Failed to enable %s, error=%d\n",
+				  engine->name, ret);
+			i915_gem_cleanup_engines(dev);
+			break;
+		}
 	}
 
 out:
@@ -4952,14 +4984,14 @@ int i915_gem_init(struct drm_device *dev
 
 	if (!i915.enable_execlists) {
 		dev_priv->gt.execbuf_submit = i915_gem_ringbuffer_submission;
-		dev_priv->gt.init_rings = i915_gem_init_rings;
-		dev_priv->gt.cleanup_ring = intel_cleanup_ring_buffer;
-		dev_priv->gt.stop_ring = intel_stop_ring_buffer;
+		dev_priv->gt.init_engines = i915_gem_init_engines;
+		dev_priv->gt.cleanup_engine = intel_cleanup_engine;
+		dev_priv->gt.stop_engine = intel_stop_engine;
 	} else {
 		dev_priv->gt.execbuf_submit = intel_execlists_submission;
-		dev_priv->gt.init_rings = intel_logical_rings_init;
-		dev_priv->gt.cleanup_ring = intel_logical_ring_cleanup;
-		dev_priv->gt.stop_ring = intel_logical_ring_stop;
+		dev_priv->gt.init_engines = intel_logical_rings_init;
+		dev_priv->gt.cleanup_engine = intel_logical_ring_cleanup;
+		dev_priv->gt.stop_engine = intel_logical_ring_stop;
 	}
 
 	/* This is just a security blanket to placate dragons.
@@ -4974,13 +5006,13 @@ int i915_gem_init(struct drm_device *dev
 	if (ret)
 		goto out_unlock;
 
-	i915_gem_init_global_gtt(dev);
+	i915_gem_init_ggtt(dev);
 
 	ret = i915_gem_context_init(dev);
 	if (ret)
 		goto out_unlock;
 
-	ret = dev_priv->gt.init_rings(dev);
+	ret = dev_priv->gt.init_engines(dev);
 	if (ret)
 		goto out_unlock;
 
@@ -5003,29 +5035,52 @@ out_unlock:
 }
 
 void
-i915_gem_cleanup_ringbuffer(struct drm_device *dev)
+i915_gem_cleanup_engines(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring;
-	int i;
+	struct intel_engine_cs *engine;
 
-	for_each_ring(ring, dev_priv, i)
-		dev_priv->gt.cleanup_ring(ring);
+	for_each_engine(engine, dev_priv)
+		dev_priv->gt.cleanup_engine(engine);
 
-    if (i915.enable_execlists)
-            /*
-             * Neither the BIOS, ourselves or any other kernel
-             * expects the system to be in execlists mode on startup,
-             * so we need to reset the GPU back to legacy mode.
-             */
-            intel_gpu_reset(dev);
+	if (i915.enable_execlists)
+		/*
+		 * Neither the BIOS, ourselves or any other kernel
+		 * expects the system to be in execlists mode on startup,
+		 * so we need to reset the GPU back to legacy mode.
+		 */
+		intel_gpu_reset(dev, ALL_ENGINES);
 }
 
 static void
-init_ring_lists(struct intel_engine_cs *ring)
+init_engine_lists(struct intel_engine_cs *engine)
 {
-	INIT_LIST_HEAD(&ring->active_list);
-	INIT_LIST_HEAD(&ring->request_list);
+	INIT_LIST_HEAD(&engine->active_list);
+	INIT_LIST_HEAD(&engine->request_list);
+}
+
+void
+i915_gem_load_init_fences(struct drm_i915_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+
+	if (INTEL_INFO(dev_priv)->gen >= 7 && !IS_VALLEYVIEW(dev_priv) &&
+	    !IS_CHERRYVIEW(dev_priv))
+		dev_priv->num_fence_regs = 32;
+	else if (INTEL_INFO(dev_priv)->gen >= 4 || IS_I945G(dev_priv) ||
+		 IS_I945GM(dev_priv) || IS_G33(dev_priv))
+		dev_priv->num_fence_regs = 16;
+	else
+		dev_priv->num_fence_regs = 8;
+
+	if (intel_vgpu_active(dev))
+		dev_priv->num_fence_regs =
+				I915_READ(vgtif_reg(avail_rs.fence_num));
+
+	/* Initialize fence registers to zero */
+	i915_gem_restore_fences(dev);
+
+	i915_gem_detect_bit_6_swizzle(dev);
 }
 
 void
@@ -5055,8 +5110,8 @@ i915_gem_load_init(struct drm_device *de
 	INIT_LIST_HEAD(&dev_priv->mm.unbound_list);
 	INIT_LIST_HEAD(&dev_priv->mm.bound_list);
 	INIT_LIST_HEAD(&dev_priv->mm.fence_list);
-	for (i = 0; i < I915_NUM_RINGS; i++)
-		init_ring_lists(&dev_priv->ring[i]);
+	for (i = 0; i < I915_NUM_ENGINES; i++)
+		init_engine_lists(&dev_priv->engine[i]);
 	for (i = 0; i < I915_MAX_NUM_FENCES; i++)
 		INIT_LIST_HEAD(&dev_priv->fence_regs[i].lru_list);
 	INIT_DELAYED_WORK(&dev_priv->mm.retire_work,
@@ -5067,17 +5122,6 @@ i915_gem_load_init(struct drm_device *de
 
 	dev_priv->relative_constants_mode = I915_EXEC_CONSTANTS_REL_GENERAL;
 
-	if (INTEL_INFO(dev)->gen >= 7 && !IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev))
-		dev_priv->num_fence_regs = 32;
-	else if (INTEL_INFO(dev)->gen >= 4 || IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
-		dev_priv->num_fence_regs = 16;
-	else
-		dev_priv->num_fence_regs = 8;
-
-	if (intel_vgpu_active(dev))
-		dev_priv->num_fence_regs =
-				I915_READ(vgtif_reg(avail_rs.fence_num));
-
 	/*
 	 * Set initial sequence number for requests.
 	 * Using this number allows the wraparound to happen early,
@@ -5086,11 +5130,8 @@ i915_gem_load_init(struct drm_device *de
 	dev_priv->next_seqno = ((u32)~0 - 0x1100);
 	dev_priv->last_seqno = ((u32)~0 - 0x1101);
 
-	/* Initialize fence registers to zero */
 	INIT_LIST_HEAD(&dev_priv->mm.fence_list);
-	i915_gem_restore_fences(dev);
 
-	i915_gem_detect_bit_6_swizzle(dev);
 	init_waitqueue_head(&dev_priv->pending_flip_queue);
 
 	dev_priv->mm.interruptible = true;
@@ -5213,11 +5254,12 @@ u64 i915_gem_obj_offset(struct drm_i915_
 u64 i915_gem_obj_ggtt_offset_view(struct drm_i915_gem_object *o,
 				  const struct i915_ggtt_view *view)
 {
-	struct i915_address_space *ggtt = i915_obj_to_ggtt(o);
+	struct drm_i915_private *dev_priv = to_i915(o->base.dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	struct i915_vma *vma;
 
 	list_for_each_entry(vma, &o->vma_list, obj_link)
-		if (vma->vm == ggtt &&
+		if (vma->vm == &ggtt->base &&
 		    i915_ggtt_view_equal(&vma->ggtt_view, view))
 			return vma->node.start;
 
@@ -5244,11 +5286,12 @@ bool i915_gem_obj_bound(struct drm_i915_
 bool i915_gem_obj_ggtt_bound_view(struct drm_i915_gem_object *o,
 				  const struct i915_ggtt_view *view)
 {
-	struct i915_address_space *ggtt = i915_obj_to_ggtt(o);
+	struct drm_i915_private *dev_priv = to_i915(o->base.dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	struct i915_vma *vma;
 
 	list_for_each_entry(vma, &o->vma_list, obj_link)
-		if (vma->vm == ggtt &&
+		if (vma->vm == &ggtt->base &&
 		    i915_ggtt_view_equal(&vma->ggtt_view, view) &&
 		    drm_mm_node_allocated(&vma->node))
 			return true;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_gem_context.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_gem_context.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_gem_context.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_gem_context.c	2016-07-24 15:23:50.000000000 -0400
@@ -342,15 +342,15 @@ void i915_gem_context_reset(struct drm_d
 		struct intel_context *ctx;
 
 		list_for_each_entry(ctx, &dev_priv->context_list, link)
-			intel_lr_context_reset(dev, ctx);
+			intel_lr_context_reset(dev_priv, ctx);
 	}
 
-	for (i = 0; i < I915_NUM_RINGS; i++) {
-		struct intel_engine_cs *ring = &dev_priv->ring[i];
+	for (i = 0; i < I915_NUM_ENGINES; i++) {
+		struct intel_engine_cs *engine = &dev_priv->engine[i];
 
-		if (ring->last_context) {
-			i915_gem_context_unpin(ring->last_context, ring);
-			ring->last_context = NULL;
+		if (engine->last_context) {
+			i915_gem_context_unpin(engine->last_context, engine);
+			engine->last_context = NULL;
 		}
 	}
 
@@ -413,7 +413,7 @@ void i915_gem_context_fini(struct drm_de
 		/* The only known way to stop the gpu from accessing the hw context is
 		 * to reset it. Do this as the very last operation to avoid confusing
 		 * other code, leading to spurious errors. */
-		intel_gpu_reset(dev);
+		intel_gpu_reset(dev, ALL_ENGINES);
 
 		/* When default context is created and switched to, base object refcount
 		 * will be 2 (+1 from object creation and +1 from do_switch()).
@@ -421,17 +421,17 @@ void i915_gem_context_fini(struct drm_de
 		 * to default context. So we need to unreference the base object once
 		 * to offset the do_switch part, so that i915_gem_context_unreference()
 		 * can then free the base object correctly. */
-		WARN_ON(!dev_priv->ring[RCS].last_context);
+		WARN_ON(!dev_priv->engine[RCS].last_context);
 
 		i915_gem_object_ggtt_unpin(dctx->legacy_hw_ctx.rcs_state);
 	}
 
-	for (i = I915_NUM_RINGS; --i >= 0;) {
-		struct intel_engine_cs *ring = &dev_priv->ring[i];
+	for (i = I915_NUM_ENGINES; --i >= 0;) {
+		struct intel_engine_cs *engine = &dev_priv->engine[i];
 
-		if (ring->last_context) {
-			i915_gem_context_unpin(ring->last_context, ring);
-			ring->last_context = NULL;
+		if (engine->last_context) {
+			i915_gem_context_unpin(engine->last_context, engine);
+			engine->last_context = NULL;
 		}
 	}
 
@@ -441,14 +441,14 @@ void i915_gem_context_fini(struct drm_de
 
 int i915_gem_context_enable(struct drm_i915_gem_request *req)
 {
-	struct intel_engine_cs *ring = req->ring;
+	struct intel_engine_cs *engine = req->engine;
 	int ret;
 
 	if (i915.enable_execlists) {
-		if (ring->init_context == NULL)
+		if (engine->init_context == NULL)
 			return 0;
 
-		ret = ring->init_context(req);
+		ret = engine->init_context(req);
 	} else
 		ret = i915_switch_context(req);
 
@@ -510,133 +510,147 @@ i915_gem_context_get(struct drm_i915_fil
 static inline int
 mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags)
 {
-	struct intel_engine_cs *ring = req->ring;
+	struct intel_engine_cs *engine = req->engine;
 	u32 flags = hw_flags | MI_MM_SPACE_GTT;
 	const int num_rings =
 		/* Use an extended w/a on ivb+ if signalling from other rings */
-		i915_semaphore_is_enabled(ring->dev) ?
-		hweight32(INTEL_INFO(ring->dev)->ring_mask) - 1 :
+		i915_semaphore_is_enabled(engine->dev) ?
+		hweight32(INTEL_INFO(engine->dev)->ring_mask) - 1 :
 		0;
-	int len, i, ret;
+	int len, ret;
 
 	/* w/a: If Flush TLB Invalidation Mode is enabled, driver must do a TLB
 	 * invalidation prior to MI_SET_CONTEXT. On GEN6 we don't set the value
 	 * explicitly, so we rely on the value at ring init, stored in
 	 * itlb_before_ctx_switch.
 	 */
-	if (IS_GEN6(ring->dev)) {
-		ret = ring->flush(req, I915_GEM_GPU_DOMAINS, 0);
+	if (IS_GEN6(engine->dev)) {
+		ret = engine->flush(req, I915_GEM_GPU_DOMAINS, 0);
 		if (ret)
 			return ret;
 	}
 
 	/* These flags are for resource streamer on HSW+ */
-	if (IS_HASWELL(ring->dev) || INTEL_INFO(ring->dev)->gen >= 8)
+	if (IS_HASWELL(engine->dev) || INTEL_INFO(engine->dev)->gen >= 8)
 		flags |= (HSW_MI_RS_SAVE_STATE_EN | HSW_MI_RS_RESTORE_STATE_EN);
-	else if (INTEL_INFO(ring->dev)->gen < 8)
+	else if (INTEL_INFO(engine->dev)->gen < 8)
 		flags |= (MI_SAVE_EXT_STATE_EN | MI_RESTORE_EXT_STATE_EN);
 
 
 	len = 4;
-	if (INTEL_INFO(ring->dev)->gen >= 7)
-		len += 2 + (num_rings ? 4*num_rings + 2 : 0);
+	if (INTEL_INFO(engine->dev)->gen >= 7)
+		len += 2 + (num_rings ? 4*num_rings + 6 : 0);
 
 	ret = intel_ring_begin(req, len);
 	if (ret)
 		return ret;
 
 	/* WaProgramMiArbOnOffAroundMiSetContext:ivb,vlv,hsw,bdw,chv */
-	if (INTEL_INFO(ring->dev)->gen >= 7) {
-		intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_DISABLE);
+	if (INTEL_INFO(engine->dev)->gen >= 7) {
+		intel_ring_emit(engine, MI_ARB_ON_OFF | MI_ARB_DISABLE);
 		if (num_rings) {
 			struct intel_engine_cs *signaller;
 
-			intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(num_rings));
-			for_each_ring(signaller, to_i915(ring->dev), i) {
-				if (signaller == ring)
+			intel_ring_emit(engine,
+					MI_LOAD_REGISTER_IMM(num_rings));
+			for_each_engine(signaller, to_i915(engine->dev)) {
+				if (signaller == engine)
 					continue;
 
-				intel_ring_emit_reg(ring, RING_PSMI_CTL(signaller->mmio_base));
-				intel_ring_emit(ring, _MASKED_BIT_ENABLE(GEN6_PSMI_SLEEP_MSG_DISABLE));
+				intel_ring_emit_reg(engine,
+						    RING_PSMI_CTL(signaller->mmio_base));
+				intel_ring_emit(engine,
+						_MASKED_BIT_ENABLE(GEN6_PSMI_SLEEP_MSG_DISABLE));
 			}
 		}
 	}
 
-	intel_ring_emit(ring, MI_NOOP);
-	intel_ring_emit(ring, MI_SET_CONTEXT);
-	intel_ring_emit(ring, i915_gem_obj_ggtt_offset(req->ctx->legacy_hw_ctx.rcs_state) |
+	intel_ring_emit(engine, MI_NOOP);
+	intel_ring_emit(engine, MI_SET_CONTEXT);
+	intel_ring_emit(engine,
+			i915_gem_obj_ggtt_offset(req->ctx->legacy_hw_ctx.rcs_state) |
 			flags);
 	/*
 	 * w/a: MI_SET_CONTEXT must always be followed by MI_NOOP
 	 * WaMiSetContext_Hang:snb,ivb,vlv
 	 */
-	intel_ring_emit(ring, MI_NOOP);
+	intel_ring_emit(engine, MI_NOOP);
 
-	if (INTEL_INFO(ring->dev)->gen >= 7) {
+	if (INTEL_INFO(engine->dev)->gen >= 7) {
 		if (num_rings) {
 			struct intel_engine_cs *signaller;
+			i915_reg_t last_reg = {}; /* keep gcc quiet */
 
-			intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(num_rings));
-			for_each_ring(signaller, to_i915(ring->dev), i) {
-				if (signaller == ring)
+			intel_ring_emit(engine,
+					MI_LOAD_REGISTER_IMM(num_rings));
+			for_each_engine(signaller, to_i915(engine->dev)) {
+				if (signaller == engine)
 					continue;
 
-				intel_ring_emit_reg(ring, RING_PSMI_CTL(signaller->mmio_base));
-				intel_ring_emit(ring, _MASKED_BIT_DISABLE(GEN6_PSMI_SLEEP_MSG_DISABLE));
+				last_reg = RING_PSMI_CTL(signaller->mmio_base);
+				intel_ring_emit_reg(engine, last_reg);
+				intel_ring_emit(engine,
+						_MASKED_BIT_DISABLE(GEN6_PSMI_SLEEP_MSG_DISABLE));
 			}
+
+			/* Insert a delay before the next switch! */
+			intel_ring_emit(engine,
+					MI_STORE_REGISTER_MEM |
+					MI_SRM_LRM_GLOBAL_GTT);
+			intel_ring_emit_reg(engine, last_reg);
+			intel_ring_emit(engine, engine->scratch.gtt_offset);
+			intel_ring_emit(engine, MI_NOOP);
 		}
-		intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_ENABLE);
+		intel_ring_emit(engine, MI_ARB_ON_OFF | MI_ARB_ENABLE);
 	}
 
-	intel_ring_advance(ring);
+	intel_ring_advance(engine);
 
 	return ret;
 }
 
-static inline bool should_skip_switch(struct intel_engine_cs *ring,
-				      struct intel_context *from,
-				      struct intel_context *to)
+static inline bool skip_rcs_switch(struct intel_engine_cs *engine,
+				   struct intel_context *to)
 {
 	if (to->remap_slice)
 		return false;
 
-	if (to->ppgtt && from == to &&
-	    !(intel_ring_flag(ring) & to->ppgtt->pd_dirty_rings))
-		return true;
+	if (!to->legacy_hw_ctx.initialized)
+		return false;
 
-	return false;
+	if (to->ppgtt &&
+	    !(intel_engine_flag(engine) & to->ppgtt->pd_dirty_rings))
+		return false;
+
+	return to == engine->last_context;
 }
 
 static bool
-needs_pd_load_pre(struct intel_engine_cs *ring, struct intel_context *to)
+needs_pd_load_pre(struct intel_engine_cs *engine, struct intel_context *to)
 {
-	struct drm_i915_private *dev_priv = ring->dev->dev_private;
-
 	if (!to->ppgtt)
 		return false;
 
-	if (INTEL_INFO(ring->dev)->gen < 8)
+	if (engine->last_context == to &&
+	    !(intel_engine_flag(engine) & to->ppgtt->pd_dirty_rings))
+		return false;
+
+	if (engine->id != RCS)
 		return true;
 
-	if (ring != &dev_priv->ring[RCS])
+	if (INTEL_INFO(engine->dev)->gen < 8)
 		return true;
 
 	return false;
 }
 
 static bool
-needs_pd_load_post(struct intel_engine_cs *ring, struct intel_context *to,
-		u32 hw_flags)
+needs_pd_load_post(struct intel_context *to, u32 hw_flags)
 {
-	struct drm_i915_private *dev_priv = ring->dev->dev_private;
-
 	if (!to->ppgtt)
 		return false;
 
-	if (!IS_GEN8(ring->dev))
-		return false;
-
-	if (ring != &dev_priv->ring[RCS])
+	if (!IS_GEN8(to->i915))
 		return false;
 
 	if (hw_flags & MI_RESTORE_INHIBIT)
@@ -645,58 +659,32 @@ needs_pd_load_post(struct intel_engine_c
 	return false;
 }
 
-static int do_switch(struct drm_i915_gem_request *req)
+static int do_rcs_switch(struct drm_i915_gem_request *req)
 {
 	struct intel_context *to = req->ctx;
-	struct intel_engine_cs *ring = req->ring;
-	struct drm_i915_private *dev_priv = ring->dev->dev_private;
-	struct intel_context *from = ring->last_context;
-	u32 hw_flags = 0;
-	bool uninitialized = false;
+	struct intel_engine_cs *engine = req->engine;
+	struct intel_context *from;
+	u32 hw_flags;
 	int ret, i;
 
-	if (from != NULL && ring == &dev_priv->ring[RCS]) {
-		BUG_ON(from->legacy_hw_ctx.rcs_state == NULL);
-		BUG_ON(!i915_gem_obj_is_pinned(from->legacy_hw_ctx.rcs_state));
-	}
-
-	if (should_skip_switch(ring, from, to))
+	if (skip_rcs_switch(engine, to))
 		return 0;
 
 	/* Trying to pin first makes error handling easier. */
-	if (ring == &dev_priv->ring[RCS]) {
-		ret = i915_gem_obj_ggtt_pin(to->legacy_hw_ctx.rcs_state,
-					    get_context_alignment(ring->dev), 0);
-		if (ret)
-			return ret;
-	}
+	ret = i915_gem_obj_ggtt_pin(to->legacy_hw_ctx.rcs_state,
+				    get_context_alignment(engine->dev),
+				    0);
+	if (ret)
+		return ret;
 
 	/*
 	 * Pin can switch back to the default context if we end up calling into
 	 * evict_everything - as a last ditch gtt defrag effort that also
 	 * switches to the default context. Hence we need to reload from here.
+	 *
+	 * XXX: Doing so is painfully broken!
 	 */
-	from = ring->last_context;
-
-	if (needs_pd_load_pre(ring, to)) {
-		/* Older GENs and non render rings still want the load first,
-		 * "PP_DCLV followed by PP_DIR_BASE register through Load
-		 * Register Immediate commands in Ring Buffer before submitting
-		 * a context."*/
-		trace_switch_mm(ring, to);
-		ret = to->ppgtt->switch_mm(to->ppgtt, req);
-		if (ret)
-			goto unpin_out;
-
-		/* Doing a PD load always reloads the page dirs */
-		to->ppgtt->pd_dirty_rings &= ~intel_ring_flag(ring);
-	}
-
-	if (ring != &dev_priv->ring[RCS]) {
-		if (from)
-			i915_gem_context_unreference(from);
-		goto done;
-	}
+	from = engine->last_context;
 
 	/*
 	 * Clear this page out of any CPU caches for coherent swap-in/out. Note
@@ -710,53 +698,37 @@ static int do_switch(struct drm_i915_gem
 	if (ret)
 		goto unpin_out;
 
-	if (!to->legacy_hw_ctx.initialized || i915_gem_context_is_default(to)) {
-		hw_flags |= MI_RESTORE_INHIBIT;
+	if (needs_pd_load_pre(engine, to)) {
+		/* Older GENs and non render rings still want the load first,
+		 * "PP_DCLV followed by PP_DIR_BASE register through Load
+		 * Register Immediate commands in Ring Buffer before submitting
+		 * a context."*/
+		trace_switch_mm(engine, to);
+		ret = to->ppgtt->switch_mm(to->ppgtt, req);
+		if (ret)
+			goto unpin_out;
+	}
+
+	if (!to->legacy_hw_ctx.initialized || i915_gem_context_is_default(to))
 		/* NB: If we inhibit the restore, the context is not allowed to
 		 * die because future work may end up depending on valid address
 		 * space. This means we must enforce that a page table load
 		 * occur when this occurs. */
-	} else if (to->ppgtt &&
-		   (intel_ring_flag(ring) & to->ppgtt->pd_dirty_rings)) {
-		hw_flags |= MI_FORCE_RESTORE;
-		to->ppgtt->pd_dirty_rings &= ~intel_ring_flag(ring);
-	}
+		hw_flags = MI_RESTORE_INHIBIT;
+	else if (to->ppgtt &&
+		 intel_engine_flag(engine) & to->ppgtt->pd_dirty_rings)
+		hw_flags = MI_FORCE_RESTORE;
+	else
+		hw_flags = 0;
 
 	/* We should never emit switch_mm more than once */
-	WARN_ON(needs_pd_load_pre(ring, to) &&
-		needs_pd_load_post(ring, to, hw_flags));
-
-	ret = mi_set_context(req, hw_flags);
-	if (ret)
-		goto unpin_out;
-
-	/* GEN8 does *not* require an explicit reload if the PDPs have been
-	 * setup, and we do not wish to move them.
-	 */
-	if (needs_pd_load_post(ring, to, hw_flags)) {
-		trace_switch_mm(ring, to);
-		ret = to->ppgtt->switch_mm(to->ppgtt, req);
-		/* The hardware context switch is emitted, but we haven't
-		 * actually changed the state - so it's probably safe to bail
-		 * here. Still, let the user know something dangerous has
-		 * happened.
-		 */
-		if (ret) {
-			DRM_ERROR("Failed to change address space on context switch\n");
-			goto unpin_out;
-		}
-	}
-
-	for (i = 0; i < MAX_L3_SLICES; i++) {
-		if (!(to->remap_slice & (1<<i)))
-			continue;
+	WARN_ON(needs_pd_load_pre(engine, to) &&
+		needs_pd_load_post(to, hw_flags));
 
-		ret = i915_gem_l3_remap(req, i);
-		/* If it failed, try again next round */
+	if (to != from || (hw_flags & MI_FORCE_RESTORE)) {
+		ret = mi_set_context(req, hw_flags);
 		if (ret)
-			DRM_DEBUG_DRIVER("L3 remapping failed\n");
-		else
-			to->remap_slice &= ~(1<<i);
+			goto unpin_out;
 	}
 
 	/* The backing object for the context is done after switching to the
@@ -781,27 +753,51 @@ static int do_switch(struct drm_i915_gem
 		i915_gem_object_ggtt_unpin(from->legacy_hw_ctx.rcs_state);
 		i915_gem_context_unreference(from);
 	}
+	i915_gem_context_reference(to);
+	engine->last_context = to;
 
-	uninitialized = !to->legacy_hw_ctx.initialized;
-	to->legacy_hw_ctx.initialized = true;
+	/* GEN8 does *not* require an explicit reload if the PDPs have been
+	 * setup, and we do not wish to move them.
+	 */
+	if (needs_pd_load_post(to, hw_flags)) {
+		trace_switch_mm(engine, to);
+		ret = to->ppgtt->switch_mm(to->ppgtt, req);
+		/* The hardware context switch is emitted, but we haven't
+		 * actually changed the state - so it's probably safe to bail
+		 * here. Still, let the user know something dangerous has
+		 * happened.
+		 */
+		if (ret)
+			return ret;
+	}
 
-done:
-	i915_gem_context_reference(to);
-	ring->last_context = to;
+	if (to->ppgtt)
+		to->ppgtt->pd_dirty_rings &= ~intel_engine_flag(engine);
 
-	if (uninitialized) {
-		if (ring->init_context) {
-			ret = ring->init_context(req);
+	for (i = 0; i < MAX_L3_SLICES; i++) {
+		if (!(to->remap_slice & (1<<i)))
+			continue;
+
+		ret = i915_gem_l3_remap(req, i);
+		if (ret)
+			return ret;
+
+		to->remap_slice &= ~(1<<i);
+	}
+
+	if (!to->legacy_hw_ctx.initialized) {
+		if (engine->init_context) {
+			ret = engine->init_context(req);
 			if (ret)
-				DRM_ERROR("ring init context: %d\n", ret);
+				return ret;
 		}
+		to->legacy_hw_ctx.initialized = true;
 	}
 
 	return 0;
 
 unpin_out:
-	if (ring->id == RCS)
-		i915_gem_object_ggtt_unpin(to->legacy_hw_ctx.rcs_state);
+	i915_gem_object_ggtt_unpin(to->legacy_hw_ctx.rcs_state);
 	return ret;
 }
 
@@ -820,23 +816,39 @@ unpin_out:
  */
 int i915_switch_context(struct drm_i915_gem_request *req)
 {
-	struct intel_engine_cs *ring = req->ring;
-	struct drm_i915_private *dev_priv = ring->dev->dev_private;
+	struct intel_engine_cs *engine = req->engine;
+	struct drm_i915_private *dev_priv = req->i915;
 
 	WARN_ON(i915.enable_execlists);
 	WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
 
-	if (req->ctx->legacy_hw_ctx.rcs_state == NULL) { /* We have the fake context */
-		if (req->ctx != ring->last_context) {
-			i915_gem_context_reference(req->ctx);
-			if (ring->last_context)
-				i915_gem_context_unreference(ring->last_context);
-			ring->last_context = req->ctx;
+	if (engine->id != RCS ||
+	    req->ctx->legacy_hw_ctx.rcs_state == NULL) {
+		struct intel_context *to = req->ctx;
+
+		if (needs_pd_load_pre(engine, to)) {
+			int ret;
+
+			trace_switch_mm(engine, to);
+			ret = to->ppgtt->switch_mm(to->ppgtt, req);
+			if (ret)
+				return ret;
+
+			/* Doing a PD load always reloads the page dirs */
+			to->ppgtt->pd_dirty_rings &= ~intel_engine_flag(engine);
 		}
+
+		if (to != engine->last_context) {
+			i915_gem_context_reference(to);
+			if (engine->last_context)
+				i915_gem_context_unreference(engine->last_context);
+			engine->last_context = to;
+		}
+
 		return 0;
 	}
 
-	return do_switch(req);
+	return do_rcs_switch(req);
 }
 
 static bool contexts_enabled(struct drm_device *dev)
@@ -937,7 +949,7 @@ int i915_gem_context_getparam_ioctl(stru
 		else if (to_i915(dev)->mm.aliasing_ppgtt)
 			args->value = to_i915(dev)->mm.aliasing_ppgtt->base.total;
 		else
-			args->value = to_i915(dev)->gtt.base.total;
+			args->value = to_i915(dev)->ggtt.base.total;
 		break;
 	default:
 		ret = -EINVAL;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_gem_debug.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_gem_debug.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_gem_debug.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_gem_debug.c	2016-07-24 15:23:50.000000000 -0400
@@ -36,29 +36,29 @@ i915_verify_lists(struct drm_device *dev
 	static int warned;
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct drm_i915_gem_object *obj;
-	struct intel_engine_cs *ring;
+	struct intel_engine_cs *engine;
 	int err = 0;
-	int i;
 
 	if (warned)
 		return 0;
 
-	for_each_ring(ring, dev_priv, i) {
-		list_for_each_entry(obj, &ring->active_list, ring_list[ring->id]) {
+	for_each_engine(engine, dev_priv) {
+		list_for_each_entry(obj, &engine->active_list,
+				    engine_list[engine->id]) {
 			if (obj->base.dev != dev ||
 			    !atomic_read(&obj->base.refcount.refcount)) {
 				DRM_ERROR("%s: freed active obj %p\n",
-					  ring->name, obj);
+					  engine->name, obj);
 				err++;
 				break;
 			} else if (!obj->active ||
-				   obj->last_read_req[ring->id] == NULL) {
+				   obj->last_read_req[engine->id] == NULL) {
 				DRM_ERROR("%s: invalid active obj %p\n",
-					  ring->name, obj);
+					  engine->name, obj);
 				err++;
 			} else if (obj->base.write_domain) {
 				DRM_ERROR("%s: invalid write obj %p (w %x)\n",
-					  ring->name,
+					  engine->name,
 					  obj, obj->base.write_domain);
 				err++;
 			}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_gem_dmabuf.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_gem_dmabuf.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_gem_dmabuf.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_gem_dmabuf.c	2016-07-24 15:23:50.000000000 -0400
@@ -95,14 +95,12 @@ static void i915_gem_unmap_dma_buf(struc
 {
 	struct drm_i915_gem_object *obj = dma_buf_to_obj(attachment->dmabuf);
 
-	mutex_lock(&obj->base.dev->struct_mutex);
-
 	dma_unmap_sg(attachment->dev, sg->sgl, sg->nents, dir);
 	sg_free_table(sg);
 	kfree(sg);
 
+	mutex_lock(&obj->base.dev->struct_mutex);
 	i915_gem_object_unpin_pages(obj);
-
 	mutex_unlock(&obj->base.dev->struct_mutex);
 }
 
@@ -110,51 +108,17 @@ static void *i915_gem_dmabuf_vmap(struct
 {
 	struct drm_i915_gem_object *obj = dma_buf_to_obj(dma_buf);
 	struct drm_device *dev = obj->base.dev;
-	struct sg_page_iter sg_iter;
-	struct page **pages;
-	int ret, i;
+	void *addr;
+	int ret;
 
 	ret = i915_mutex_lock_interruptible(dev);
 	if (ret)
 		return ERR_PTR(ret);
 
-	if (obj->dma_buf_vmapping) {
-		obj->vmapping_count++;
-		goto out_unlock;
-	}
-
-	ret = i915_gem_object_get_pages(obj);
-	if (ret)
-		goto err;
-
-	i915_gem_object_pin_pages(obj);
-
-	ret = -ENOMEM;
-
-	pages = drm_malloc_ab(obj->base.size >> PAGE_SHIFT, sizeof(*pages));
-	if (pages == NULL)
-		goto err_unpin;
-
-	i = 0;
-	for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0)
-		pages[i++] = sg_page_iter_page(&sg_iter);
-
-	obj->dma_buf_vmapping = vmap(pages, i, 0, PAGE_KERNEL);
-	drm_free_large(pages);
-
-	if (!obj->dma_buf_vmapping)
-		goto err_unpin;
-
-	obj->vmapping_count = 1;
-out_unlock:
+	addr = i915_gem_object_pin_map(obj);
 	mutex_unlock(&dev->struct_mutex);
-	return obj->dma_buf_vmapping;
 
-err_unpin:
-	i915_gem_object_unpin_pages(obj);
-err:
-	mutex_unlock(&dev->struct_mutex);
-	return ERR_PTR(ret);
+	return addr;
 }
 
 static void i915_gem_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr)
@@ -163,12 +127,7 @@ static void i915_gem_dmabuf_vunmap(struc
 	struct drm_device *dev = obj->base.dev;
 
 	mutex_lock(&dev->struct_mutex);
-	if (--obj->vmapping_count == 0) {
-		vunmap(obj->dma_buf_vmapping);
-		obj->dma_buf_vmapping = NULL;
-
-		i915_gem_object_unpin_pages(obj);
-	}
+	i915_gem_object_unpin_map(obj);
 	mutex_unlock(&dev->struct_mutex);
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_gem_execbuffer.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_gem_execbuffer.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_gem_execbuffer.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_gem_execbuffer.c	2016-07-24 15:23:50.000000000 -0400
@@ -313,7 +313,8 @@ relocate_entry_gtt(struct drm_i915_gem_o
 		   uint64_t target_offset)
 {
 	struct drm_device *dev = obj->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	uint64_t delta = relocation_target(reloc, target_offset);
 	uint64_t offset;
 	void __iomem *reloc_page;
@@ -330,7 +331,7 @@ relocate_entry_gtt(struct drm_i915_gem_o
 	/* Map the page containing the relocation we're going to perform.  */
 	offset = i915_gem_obj_ggtt_offset(obj);
 	offset += reloc->offset;
-	reloc_page = io_mapping_map_atomic_wc(dev_priv->gtt.mappable,
+	reloc_page = io_mapping_map_atomic_wc(ggtt->mappable,
 					      offset & PAGE_MASK);
 	iowrite32(lower_32_bits(delta), reloc_page + offset_in_page(offset));
 
@@ -340,7 +341,7 @@ relocate_entry_gtt(struct drm_i915_gem_o
 		if (offset_in_page(offset) == 0) {
 			io_mapping_unmap_atomic(reloc_page);
 			reloc_page =
-				io_mapping_map_atomic_wc(dev_priv->gtt.mappable,
+				io_mapping_map_atomic_wc(ggtt->mappable,
 							 offset);
 		}
 
@@ -488,7 +489,7 @@ i915_gem_execbuffer_relocate_entry(struc
 		ret = relocate_entry_cpu(obj, reloc, target_offset);
 	else if (obj->map_and_fenceable)
 		ret = relocate_entry_gtt(obj, reloc, target_offset);
-	else if (cpu_has_clflush)
+	else if (static_cpu_has(X86_FEATURE_CLFLUSH))
 		ret = relocate_entry_clflush(obj, reloc, target_offset);
 	else {
 		WARN_ONCE(1, "Impossible case in relocation handling\n");
@@ -514,7 +515,7 @@ i915_gem_execbuffer_relocate_vma(struct
 	struct drm_i915_gem_exec_object2 *entry = vma->exec_entry;
 	int remain, ret;
 
-	user_relocs = to_user_ptr(entry->relocs_ptr);
+	user_relocs = u64_to_user_ptr(entry->relocs_ptr);
 
 	remain = entry->relocation_count;
 	while (remain) {
@@ -535,9 +536,7 @@ i915_gem_execbuffer_relocate_vma(struct
 				return ret;
 
 			if (r->presumed_offset != offset &&
-			    __copy_to_user_inatomic(&user_relocs->presumed_offset,
-						    &r->presumed_offset,
-						    sizeof(r->presumed_offset))) {
+			    __put_user(r->presumed_offset, &user_relocs->presumed_offset)) {
 				return -EFAULT;
 			}
 
@@ -599,7 +598,7 @@ static bool only_mappable_for_reloc(unsi
 
 static int
 i915_gem_execbuffer_reserve_vma(struct i915_vma *vma,
-				struct intel_engine_cs *ring,
+				struct intel_engine_cs *engine,
 				bool *need_reloc)
 {
 	struct drm_i915_gem_object *obj = vma->obj;
@@ -713,7 +712,7 @@ eb_vma_misplaced(struct i915_vma *vma)
 }
 
 static int
-i915_gem_execbuffer_reserve(struct intel_engine_cs *ring,
+i915_gem_execbuffer_reserve(struct intel_engine_cs *engine,
 			    struct list_head *vmas,
 			    struct intel_context *ctx,
 			    bool *need_relocs)
@@ -723,10 +722,10 @@ i915_gem_execbuffer_reserve(struct intel
 	struct i915_address_space *vm;
 	struct list_head ordered_vmas;
 	struct list_head pinned_vmas;
-	bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4;
+	bool has_fenced_gpu_access = INTEL_INFO(engine->dev)->gen < 4;
 	int retry;
 
-	i915_gem_retire_requests_ring(ring);
+	i915_gem_retire_requests_ring(engine);
 
 	vm = list_first_entry(vmas, struct i915_vma, exec_list)->vm;
 
@@ -788,7 +787,9 @@ i915_gem_execbuffer_reserve(struct intel
 			if (eb_vma_misplaced(vma))
 				ret = i915_vma_unbind(vma);
 			else
-				ret = i915_gem_execbuffer_reserve_vma(vma, ring, need_relocs);
+				ret = i915_gem_execbuffer_reserve_vma(vma,
+								      engine,
+								      need_relocs);
 			if (ret)
 				goto err;
 		}
@@ -798,7 +799,8 @@ i915_gem_execbuffer_reserve(struct intel
 			if (drm_mm_node_allocated(&vma->node))
 				continue;
 
-			ret = i915_gem_execbuffer_reserve_vma(vma, ring, need_relocs);
+			ret = i915_gem_execbuffer_reserve_vma(vma, engine,
+							      need_relocs);
 			if (ret)
 				goto err;
 		}
@@ -821,7 +823,7 @@ static int
 i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
 				  struct drm_i915_gem_execbuffer2 *args,
 				  struct drm_file *file,
-				  struct intel_engine_cs *ring,
+				  struct intel_engine_cs *engine,
 				  struct eb_vmas *eb,
 				  struct drm_i915_gem_exec_object2 *exec,
 				  struct intel_context *ctx)
@@ -865,7 +867,7 @@ i915_gem_execbuffer_relocate_slow(struct
 		u64 invalid_offset = (u64)-1;
 		int j;
 
-		user_relocs = to_user_ptr(exec[i].relocs_ptr);
+		user_relocs = u64_to_user_ptr(exec[i].relocs_ptr);
 
 		if (copy_from_user(reloc+total, user_relocs,
 				   exec[i].relocation_count * sizeof(*reloc))) {
@@ -910,7 +912,8 @@ i915_gem_execbuffer_relocate_slow(struct
 		goto err;
 
 	need_relocs = (args->flags & I915_EXEC_NO_RELOC) == 0;
-	ret = i915_gem_execbuffer_reserve(ring, &eb->vmas, ctx, &need_relocs);
+	ret = i915_gem_execbuffer_reserve(engine, &eb->vmas, ctx,
+					  &need_relocs);
 	if (ret)
 		goto err;
 
@@ -938,7 +941,7 @@ static int
 i915_gem_execbuffer_move_to_gpu(struct drm_i915_gem_request *req,
 				struct list_head *vmas)
 {
-	const unsigned other_rings = ~intel_ring_flag(req->ring);
+	const unsigned other_rings = ~intel_engine_flag(req->engine);
 	struct i915_vma *vma;
 	uint32_t flush_domains = 0;
 	bool flush_chipset = false;
@@ -948,7 +951,7 @@ i915_gem_execbuffer_move_to_gpu(struct d
 		struct drm_i915_gem_object *obj = vma->obj;
 
 		if (obj->active & other_rings) {
-			ret = i915_gem_object_sync(obj, req->ring, &req);
+			ret = i915_gem_object_sync(obj, req->engine, &req);
 			if (ret)
 				return ret;
 		}
@@ -960,7 +963,7 @@ i915_gem_execbuffer_move_to_gpu(struct d
 	}
 
 	if (flush_chipset)
-		i915_gem_chipset_flush(req->ring->dev);
+		i915_gem_chipset_flush(req->engine->dev);
 
 	if (flush_domains & I915_GEM_DOMAIN_GTT)
 		wmb();
@@ -1009,7 +1012,7 @@ validate_exec_list(struct drm_device *de
 		invalid_flags |= EXEC_OBJECT_NEEDS_GTT;
 
 	for (i = 0; i < count; i++) {
-		char __user *ptr = to_user_ptr(exec[i].relocs_ptr);
+		char __user *ptr = u64_to_user_ptr(exec[i].relocs_ptr);
 		int length; /* limited by fault_in_pages_readable() */
 
 		if (exec[i].flags & invalid_flags)
@@ -1062,12 +1065,12 @@ validate_exec_list(struct drm_device *de
 
 static struct intel_context *
 i915_gem_validate_context(struct drm_device *dev, struct drm_file *file,
-			  struct intel_engine_cs *ring, const u32 ctx_id)
+			  struct intel_engine_cs *engine, const u32 ctx_id)
 {
 	struct intel_context *ctx = NULL;
 	struct i915_ctx_hang_stats *hs;
 
-	if (ring->id != RCS && ctx_id != DEFAULT_CONTEXT_HANDLE)
+	if (engine->id != RCS && ctx_id != DEFAULT_CONTEXT_HANDLE)
 		return ERR_PTR(-EINVAL);
 
 	ctx = i915_gem_context_get(file->driver_priv, ctx_id);
@@ -1080,8 +1083,8 @@ i915_gem_validate_context(struct drm_dev
 		return ERR_PTR(-EIO);
 	}
 
-	if (i915.enable_execlists && !ctx->engine[ring->id].state) {
-		int ret = intel_lr_context_deferred_alloc(ctx, ring);
+	if (i915.enable_execlists && !ctx->engine[engine->id].state) {
+		int ret = intel_lr_context_deferred_alloc(ctx, engine);
 		if (ret) {
 			DRM_DEBUG("Could not create LRC %u: %d\n", ctx_id, ret);
 			return ERR_PTR(ret);
@@ -1095,7 +1098,7 @@ void
 i915_gem_execbuffer_move_to_active(struct list_head *vmas,
 				   struct drm_i915_gem_request *req)
 {
-	struct intel_engine_cs *ring = i915_gem_request_get_ring(req);
+	struct intel_engine_cs *engine = i915_gem_request_get_engine(req);
 	struct i915_vma *vma;
 
 	list_for_each_entry(vma, vmas, exec_list) {
@@ -1122,7 +1125,7 @@ i915_gem_execbuffer_move_to_active(struc
 		if (entry->flags & EXEC_OBJECT_NEEDS_FENCE) {
 			i915_gem_request_assign(&obj->last_fenced_req, req);
 			if (entry->flags & __EXEC_OBJECT_HAS_FENCE) {
-				struct drm_i915_private *dev_priv = to_i915(ring->dev);
+				struct drm_i915_private *dev_priv = to_i915(engine->dev);
 				list_move_tail(&dev_priv->fence_regs[obj->fence_reg].lru_list,
 					       &dev_priv->mm.fence_list);
 			}
@@ -1132,11 +1135,11 @@ i915_gem_execbuffer_move_to_active(struc
 	}
 }
 
-void
+static void
 i915_gem_execbuffer_retire_commands(struct i915_execbuffer_params *params)
 {
 	/* Unconditionally force add_request to emit a full flush. */
-	params->ring->gpu_caches_dirty = true;
+	params->engine->gpu_caches_dirty = true;
 
 	/* Add a breadcrumb for the completion of the batch buffer */
 	__i915_add_request(params->request, params->batch_obj, true);
@@ -1146,11 +1149,11 @@ static int
 i915_reset_gen7_sol_offsets(struct drm_device *dev,
 			    struct drm_i915_gem_request *req)
 {
-	struct intel_engine_cs *ring = req->ring;
+	struct intel_engine_cs *engine = req->engine;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int ret, i;
 
-	if (!IS_GEN7(dev) || ring != &dev_priv->ring[RCS]) {
+	if (!IS_GEN7(dev) || engine != &dev_priv->engine[RCS]) {
 		DRM_DEBUG("sol reset is gen7/rcs only\n");
 		return -EINVAL;
 	}
@@ -1160,18 +1163,18 @@ i915_reset_gen7_sol_offsets(struct drm_d
 		return ret;
 
 	for (i = 0; i < 4; i++) {
-		intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
-		intel_ring_emit_reg(ring, GEN7_SO_WRITE_OFFSET(i));
-		intel_ring_emit(ring, 0);
+		intel_ring_emit(engine, MI_LOAD_REGISTER_IMM(1));
+		intel_ring_emit_reg(engine, GEN7_SO_WRITE_OFFSET(i));
+		intel_ring_emit(engine, 0);
 	}
 
-	intel_ring_advance(ring);
+	intel_ring_advance(engine);
 
 	return 0;
 }
 
 static struct drm_i915_gem_object*
-i915_gem_execbuffer_parse(struct intel_engine_cs *ring,
+i915_gem_execbuffer_parse(struct intel_engine_cs *engine,
 			  struct drm_i915_gem_exec_object2 *shadow_exec_entry,
 			  struct eb_vmas *eb,
 			  struct drm_i915_gem_object *batch_obj,
@@ -1183,12 +1186,12 @@ i915_gem_execbuffer_parse(struct intel_e
 	struct i915_vma *vma;
 	int ret;
 
-	shadow_batch_obj = i915_gem_batch_pool_get(&ring->batch_pool,
+	shadow_batch_obj = i915_gem_batch_pool_get(&engine->batch_pool,
 						   PAGE_ALIGN(batch_len));
 	if (IS_ERR(shadow_batch_obj))
 		return shadow_batch_obj;
 
-	ret = i915_parse_cmds(ring,
+	ret = i915_parse_cmds(engine,
 			      batch_obj,
 			      shadow_batch_obj,
 			      batch_start_offset,
@@ -1229,7 +1232,7 @@ i915_gem_ringbuffer_submission(struct i9
 			       struct list_head *vmas)
 {
 	struct drm_device *dev = params->dev;
-	struct intel_engine_cs *ring = params->ring;
+	struct intel_engine_cs *engine = params->engine;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u64 exec_start, exec_len;
 	int instp_mode;
@@ -1244,8 +1247,8 @@ i915_gem_ringbuffer_submission(struct i9
 	if (ret)
 		return ret;
 
-	WARN(params->ctx->ppgtt && params->ctx->ppgtt->pd_dirty_rings & (1<<ring->id),
-	     "%s didn't clear reload\n", ring->name);
+	WARN(params->ctx->ppgtt && params->ctx->ppgtt->pd_dirty_rings & (1<<engine->id),
+	     "%s didn't clear reload\n", engine->name);
 
 	instp_mode = args->flags & I915_EXEC_CONSTANTS_MASK;
 	instp_mask = I915_EXEC_CONSTANTS_MASK;
@@ -1253,7 +1256,7 @@ i915_gem_ringbuffer_submission(struct i9
 	case I915_EXEC_CONSTANTS_REL_GENERAL:
 	case I915_EXEC_CONSTANTS_ABSOLUTE:
 	case I915_EXEC_CONSTANTS_REL_SURFACE:
-		if (instp_mode != 0 && ring != &dev_priv->ring[RCS]) {
+		if (instp_mode != 0 && engine != &dev_priv->engine[RCS]) {
 			DRM_DEBUG("non-0 rel constants mode on non-RCS\n");
 			return -EINVAL;
 		}
@@ -1280,17 +1283,17 @@ i915_gem_ringbuffer_submission(struct i9
 		return -EINVAL;
 	}
 
-	if (ring == &dev_priv->ring[RCS] &&
+	if (engine == &dev_priv->engine[RCS] &&
 	    instp_mode != dev_priv->relative_constants_mode) {
 		ret = intel_ring_begin(params->request, 4);
 		if (ret)
 			return ret;
 
-		intel_ring_emit(ring, MI_NOOP);
-		intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
-		intel_ring_emit_reg(ring, INSTPM);
-		intel_ring_emit(ring, instp_mask << 16 | instp_mode);
-		intel_ring_advance(ring);
+		intel_ring_emit(engine, MI_NOOP);
+		intel_ring_emit(engine, MI_LOAD_REGISTER_IMM(1));
+		intel_ring_emit_reg(engine, INSTPM);
+		intel_ring_emit(engine, instp_mask << 16 | instp_mode);
+		intel_ring_advance(engine);
 
 		dev_priv->relative_constants_mode = instp_mode;
 	}
@@ -1308,7 +1311,7 @@ i915_gem_ringbuffer_submission(struct i9
 	if (exec_len == 0)
 		exec_len = params->batch_obj->base.size;
 
-	ret = ring->dispatch_execbuffer(params->request,
+	ret = engine->dispatch_execbuffer(params->request,
 					exec_start, exec_len,
 					params->dispatch_flags);
 	if (ret)
@@ -1317,7 +1320,6 @@ i915_gem_ringbuffer_submission(struct i9
 	trace_i915_gem_ring_dispatch(params->request, params->dispatch_flags);
 
 	i915_gem_execbuffer_move_to_active(vmas, params->request);
-	i915_gem_execbuffer_retire_commands(params);
 
 	return 0;
 }
@@ -1365,7 +1367,7 @@ eb_get_batch(struct eb_vmas *eb)
 
 #define I915_USER_RINGS (4)
 
-static const enum intel_ring_id user_ring_map[I915_USER_RINGS + 1] = {
+static const enum intel_engine_id user_ring_map[I915_USER_RINGS + 1] = {
 	[I915_EXEC_DEFAULT]	= RCS,
 	[I915_EXEC_RENDER]	= RCS,
 	[I915_EXEC_BLT]		= BCS,
@@ -1408,12 +1410,12 @@ eb_select_ring(struct drm_i915_private *
 			return -EINVAL;
 		}
 
-		*ring = &dev_priv->ring[_VCS(bsd_idx)];
+		*ring = &dev_priv->engine[_VCS(bsd_idx)];
 	} else {
-		*ring = &dev_priv->ring[user_ring_map[user_ring_id]];
+		*ring = &dev_priv->engine[user_ring_map[user_ring_id]];
 	}
 
-	if (!intel_ring_initialized(*ring)) {
+	if (!intel_engine_initialized(*ring)) {
 		DRM_DEBUG("execbuf with invalid ring: %u\n", user_ring_id);
 		return -EINVAL;
 	}
@@ -1427,12 +1429,13 @@ i915_gem_do_execbuffer(struct drm_device
 		       struct drm_i915_gem_execbuffer2 *args,
 		       struct drm_i915_gem_exec_object2 *exec)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	struct drm_i915_gem_request *req = NULL;
 	struct eb_vmas *eb;
 	struct drm_i915_gem_object *batch_obj;
 	struct drm_i915_gem_exec_object2 shadow_exec_entry;
-	struct intel_engine_cs *ring;
+	struct intel_engine_cs *engine;
 	struct intel_context *ctx;
 	struct i915_address_space *vm;
 	struct i915_execbuffer_params params_master; /* XXX: will be removed later */
@@ -1459,7 +1462,7 @@ i915_gem_do_execbuffer(struct drm_device
 	if (args->flags & I915_EXEC_IS_PINNED)
 		dispatch_flags |= I915_DISPATCH_PINNED;
 
-	ret = eb_select_ring(dev_priv, file, args, &ring);
+	ret = eb_select_ring(dev_priv, file, args, &engine);
 	if (ret)
 		return ret;
 
@@ -1473,9 +1476,9 @@ i915_gem_do_execbuffer(struct drm_device
 			DRM_DEBUG("RS is only allowed for Haswell, Gen8 and above\n");
 			return -EINVAL;
 		}
-		if (ring->id != RCS) {
+		if (engine->id != RCS) {
 			DRM_DEBUG("RS is not available on %s\n",
-				 ring->name);
+				 engine->name);
 			return -EINVAL;
 		}
 
@@ -1488,7 +1491,7 @@ i915_gem_do_execbuffer(struct drm_device
 	if (ret)
 		goto pre_mutex_err;
 
-	ctx = i915_gem_validate_context(dev, file, ring, ctx_id);
+	ctx = i915_gem_validate_context(dev, file, engine, ctx_id);
 	if (IS_ERR(ctx)) {
 		mutex_unlock(&dev->struct_mutex);
 		ret = PTR_ERR(ctx);
@@ -1500,7 +1503,7 @@ i915_gem_do_execbuffer(struct drm_device
 	if (ctx->ppgtt)
 		vm = &ctx->ppgtt->base;
 	else
-		vm = &dev_priv->gtt.base;
+		vm = &ggtt->base;
 
 	memset(&params_master, 0x00, sizeof(params_master));
 
@@ -1522,7 +1525,8 @@ i915_gem_do_execbuffer(struct drm_device
 
 	/* Move the objects en-masse into the GTT, evicting if necessary. */
 	need_relocs = (args->flags & I915_EXEC_NO_RELOC) == 0;
-	ret = i915_gem_execbuffer_reserve(ring, &eb->vmas, ctx, &need_relocs);
+	ret = i915_gem_execbuffer_reserve(engine, &eb->vmas, ctx,
+					  &need_relocs);
 	if (ret)
 		goto err;
 
@@ -1531,7 +1535,8 @@ i915_gem_do_execbuffer(struct drm_device
 		ret = i915_gem_execbuffer_relocate(eb);
 	if (ret) {
 		if (ret == -EFAULT) {
-			ret = i915_gem_execbuffer_relocate_slow(dev, args, file, ring,
+			ret = i915_gem_execbuffer_relocate_slow(dev, args, file,
+								engine,
 								eb, exec, ctx);
 			BUG_ON(!mutex_is_locked(&dev->struct_mutex));
 		}
@@ -1547,16 +1552,16 @@ i915_gem_do_execbuffer(struct drm_device
 	}
 
 	params->args_batch_start_offset = args->batch_start_offset;
-	if (i915_needs_cmd_parser(ring) && args->batch_len) {
+	if (i915_needs_cmd_parser(engine) && args->batch_len) {
 		struct drm_i915_gem_object *parsed_batch_obj;
 
-		parsed_batch_obj = i915_gem_execbuffer_parse(ring,
-						      &shadow_exec_entry,
-						      eb,
-						      batch_obj,
-						      args->batch_start_offset,
-						      args->batch_len,
-						      file->is_master);
+		parsed_batch_obj = i915_gem_execbuffer_parse(engine,
+							     &shadow_exec_entry,
+							     eb,
+							     batch_obj,
+							     args->batch_start_offset,
+							     args->batch_len,
+							     file->is_master);
 		if (IS_ERR(parsed_batch_obj)) {
 			ret = PTR_ERR(parsed_batch_obj);
 			goto err;
@@ -1608,7 +1613,7 @@ i915_gem_do_execbuffer(struct drm_device
 		params->batch_obj_vm_offset = i915_gem_obj_offset(batch_obj, vm);
 
 	/* Allocate a request for this batch buffer nice and early. */
-	req = i915_gem_request_alloc(ring, ctx);
+	req = i915_gem_request_alloc(engine, ctx);
 	if (IS_ERR(req)) {
 		ret = PTR_ERR(req);
 		goto err_batch_unpin;
@@ -1616,7 +1621,7 @@ i915_gem_do_execbuffer(struct drm_device
 
 	ret = i915_gem_request_add_to_client(req, file);
 	if (ret)
-		goto err_batch_unpin;
+		goto err_request;
 
 	/*
 	 * Save assorted stuff away to pass through to *_submission().
@@ -1626,13 +1631,15 @@ i915_gem_do_execbuffer(struct drm_device
 	 */
 	params->dev                     = dev;
 	params->file                    = file;
-	params->ring                    = ring;
+	params->engine                    = engine;
 	params->dispatch_flags          = dispatch_flags;
 	params->batch_obj               = batch_obj;
 	params->ctx                     = ctx;
 	params->request                 = req;
 
 	ret = dev_priv->gt.execbuf_submit(params, args, &eb->vmas);
+err_request:
+	i915_gem_execbuffer_retire_commands(params);
 
 err_batch_unpin:
 	/*
@@ -1649,14 +1656,6 @@ err:
 	i915_gem_context_unreference(ctx);
 	eb_destroy(eb);
 
-	/*
-	 * If the request was created but not successfully submitted then it
-	 * must be freed again. If it was submitted then it is being tracked
-	 * on the active request list and no clean up is required here.
-	 */
-	if (ret && !IS_ERR_OR_NULL(req))
-		i915_gem_request_cancel(req);
-
 	mutex_unlock(&dev->struct_mutex);
 
 pre_mutex_err:
@@ -1696,7 +1695,7 @@ i915_gem_execbuffer(struct drm_device *d
 		return -ENOMEM;
 	}
 	ret = copy_from_user(exec_list,
-			     to_user_ptr(args->buffers_ptr),
+			     u64_to_user_ptr(args->buffers_ptr),
 			     sizeof(*exec_list) * args->buffer_count);
 	if (ret != 0) {
 		DRM_DEBUG("copy %d exec entries failed %d\n",
@@ -1732,7 +1731,7 @@ i915_gem_execbuffer(struct drm_device *d
 	ret = i915_gem_do_execbuffer(dev, data, file, &exec2, exec2_list);
 	if (!ret) {
 		struct drm_i915_gem_exec_object __user *user_exec_list =
-			to_user_ptr(args->buffers_ptr);
+			u64_to_user_ptr(args->buffers_ptr);
 
 		/* Copy the new buffer offsets back to the user's exec list. */
 		for (i = 0; i < args->buffer_count; i++) {
@@ -1775,18 +1774,16 @@ i915_gem_execbuffer2(struct drm_device *
 		return -EINVAL;
 	}
 
-	exec2_list = kmalloc(sizeof(*exec2_list)*args->buffer_count,
-			     GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY);
-	if (exec2_list == NULL)
-		exec2_list = drm_malloc_ab(sizeof(*exec2_list),
-					   args->buffer_count);
+	exec2_list = drm_malloc_gfp(args->buffer_count,
+				    sizeof(*exec2_list),
+				    GFP_TEMPORARY);
 	if (exec2_list == NULL) {
 		DRM_DEBUG("Failed to allocate exec list for %d buffers\n",
 			  args->buffer_count);
 		return -ENOMEM;
 	}
 	ret = copy_from_user(exec2_list,
-			     to_user_ptr(args->buffers_ptr),
+			     u64_to_user_ptr(args->buffers_ptr),
 			     sizeof(*exec2_list) * args->buffer_count);
 	if (ret != 0) {
 		DRM_DEBUG("copy %d exec entries failed %d\n",
@@ -1799,7 +1796,7 @@ i915_gem_execbuffer2(struct drm_device *
 	if (!ret) {
 		/* Copy the new buffer offsets back to the user's exec list. */
 		struct drm_i915_gem_exec_object2 __user *user_exec_list =
-				   to_user_ptr(args->buffers_ptr);
+				   u64_to_user_ptr(args->buffers_ptr);
 		int i;
 
 		for (i = 0; i < args->buffer_count; i++) {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_gem_gtt.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_gem_gtt.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_gem_gtt.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_gem_gtt.c	2016-07-24 15:23:50.000000000 -0400
@@ -658,7 +658,7 @@ static int gen8_write_pdp(struct drm_i91
 			  unsigned entry,
 			  dma_addr_t addr)
 {
-	struct intel_engine_cs *ring = req->ring;
+	struct intel_engine_cs *engine = req->engine;
 	int ret;
 
 	BUG_ON(entry >= 4);
@@ -667,13 +667,13 @@ static int gen8_write_pdp(struct drm_i91
 	if (ret)
 		return ret;
 
-	intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
-	intel_ring_emit_reg(ring, GEN8_RING_PDP_UDW(ring, entry));
-	intel_ring_emit(ring, upper_32_bits(addr));
-	intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
-	intel_ring_emit_reg(ring, GEN8_RING_PDP_LDW(ring, entry));
-	intel_ring_emit(ring, lower_32_bits(addr));
-	intel_ring_advance(ring);
+	intel_ring_emit(engine, MI_LOAD_REGISTER_IMM(1));
+	intel_ring_emit_reg(engine, GEN8_RING_PDP_UDW(engine, entry));
+	intel_ring_emit(engine, upper_32_bits(addr));
+	intel_ring_emit(engine, MI_LOAD_REGISTER_IMM(1));
+	intel_ring_emit_reg(engine, GEN8_RING_PDP_LDW(engine, entry));
+	intel_ring_emit(engine, lower_32_bits(addr));
+	intel_ring_advance(engine);
 
 	return 0;
 }
@@ -706,8 +706,7 @@ static void gen8_ppgtt_clear_pte_range(s
 				       uint64_t length,
 				       gen8_pte_t scratch_pte)
 {
-	struct i915_hw_ppgtt *ppgtt =
-		container_of(vm, struct i915_hw_ppgtt, base);
+	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
 	gen8_pte_t *pt_vaddr;
 	unsigned pdpe = gen8_pdpe_index(start);
 	unsigned pde = gen8_pde_index(start);
@@ -746,7 +745,7 @@ static void gen8_ppgtt_clear_pte_range(s
 			num_entries--;
 		}
 
-		kunmap_px(ppgtt, pt);
+		kunmap_px(ppgtt, pt_vaddr);
 
 		pte = 0;
 		if (++pde == I915_PDES) {
@@ -762,8 +761,7 @@ static void gen8_ppgtt_clear_range(struc
 				   uint64_t length,
 				   bool use_scratch)
 {
-	struct i915_hw_ppgtt *ppgtt =
-		container_of(vm, struct i915_hw_ppgtt, base);
+	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
 	gen8_pte_t scratch_pte = gen8_pte_encode(px_dma(vm->scratch_page),
 						 I915_CACHE_LLC, use_scratch);
 
@@ -788,8 +786,7 @@ gen8_ppgtt_insert_pte_entries(struct i91
 			      uint64_t start,
 			      enum i915_cache_level cache_level)
 {
-	struct i915_hw_ppgtt *ppgtt =
-		container_of(vm, struct i915_hw_ppgtt, base);
+	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
 	gen8_pte_t *pt_vaddr;
 	unsigned pdpe = gen8_pdpe_index(start);
 	unsigned pde = gen8_pde_index(start);
@@ -829,8 +826,7 @@ static void gen8_ppgtt_insert_entries(st
 				      enum i915_cache_level cache_level,
 				      u32 unused)
 {
-	struct i915_hw_ppgtt *ppgtt =
-		container_of(vm, struct i915_hw_ppgtt, base);
+	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
 	struct sg_page_iter sg_iter;
 
 	__sg_page_iter_start(&sg_iter, pages->sgl, sg_nents(pages->sgl), 0);
@@ -909,11 +905,10 @@ static int gen8_init_scratch(struct i915
 static int gen8_ppgtt_notify_vgt(struct i915_hw_ppgtt *ppgtt, bool create)
 {
 	enum vgt_g2v_type msg;
-	struct drm_device *dev = ppgtt->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(ppgtt->base.dev);
 	int i;
 
-	if (USES_FULL_48BIT_PPGTT(dev)) {
+	if (USES_FULL_48BIT_PPGTT(dev_priv)) {
 		u64 daddr = px_dma(&ppgtt->pml4);
 
 		I915_WRITE(vgtif_reg(pdp[0].lo), lower_32_bits(daddr));
@@ -981,8 +976,7 @@ static void gen8_ppgtt_cleanup_4lvl(stru
 
 static void gen8_ppgtt_cleanup(struct i915_address_space *vm)
 {
-	struct i915_hw_ppgtt *ppgtt =
-		container_of(vm, struct i915_hw_ppgtt, base);
+	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
 
 	if (intel_vgpu_active(vm->dev))
 		gen8_ppgtt_notify_vgt(ppgtt, false);
@@ -1216,8 +1210,7 @@ static int gen8_alloc_va_range_3lvl(stru
 				    uint64_t start,
 				    uint64_t length)
 {
-	struct i915_hw_ppgtt *ppgtt =
-		container_of(vm, struct i915_hw_ppgtt, base);
+	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
 	unsigned long *new_page_dirs, *new_page_tables;
 	struct drm_device *dev = vm->dev;
 	struct i915_page_directory *pd;
@@ -1329,8 +1322,7 @@ static int gen8_alloc_va_range_4lvl(stru
 				    uint64_t length)
 {
 	DECLARE_BITMAP(new_pdps, GEN8_PML4ES_PER_PML4);
-	struct i915_hw_ppgtt *ppgtt =
-			container_of(vm, struct i915_hw_ppgtt, base);
+	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
 	struct i915_page_directory_pointer *pdp;
 	uint64_t pml4e;
 	int ret = 0;
@@ -1376,8 +1368,7 @@ err_out:
 static int gen8_alloc_va_range(struct i915_address_space *vm,
 			       uint64_t start, uint64_t length)
 {
-	struct i915_hw_ppgtt *ppgtt =
-		container_of(vm, struct i915_hw_ppgtt, base);
+	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
 
 	if (USES_FULL_48BIT_PPGTT(vm->dev))
 		return gen8_alloc_va_range_4lvl(vm, &ppgtt->pml4, start, length);
@@ -1629,6 +1620,7 @@ static void gen6_write_page_range(struct
 				  struct i915_page_directory *pd,
 				  uint32_t start, uint32_t length)
 {
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	struct i915_page_table *pt;
 	uint32_t pde, temp;
 
@@ -1637,7 +1629,7 @@ static void gen6_write_page_range(struct
 
 	/* Make sure write is complete before other code can use this page
 	 * table. Also require for WC mapped PTEs */
-	readl(dev_priv->gtt.gsm);
+	readl(ggtt->gsm);
 }
 
 static uint32_t get_pd_offset(struct i915_hw_ppgtt *ppgtt)
@@ -1650,11 +1642,11 @@ static uint32_t get_pd_offset(struct i91
 static int hsw_mm_switch(struct i915_hw_ppgtt *ppgtt,
 			 struct drm_i915_gem_request *req)
 {
-	struct intel_engine_cs *ring = req->ring;
+	struct intel_engine_cs *engine = req->engine;
 	int ret;
 
 	/* NB: TLBs must be flushed and invalidated before a switch */
-	ret = ring->flush(req, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
+	ret = engine->flush(req, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
 	if (ret)
 		return ret;
 
@@ -1662,13 +1654,13 @@ static int hsw_mm_switch(struct i915_hw_
 	if (ret)
 		return ret;
 
-	intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(2));
-	intel_ring_emit_reg(ring, RING_PP_DIR_DCLV(ring));
-	intel_ring_emit(ring, PP_DIR_DCLV_2G);
-	intel_ring_emit_reg(ring, RING_PP_DIR_BASE(ring));
-	intel_ring_emit(ring, get_pd_offset(ppgtt));
-	intel_ring_emit(ring, MI_NOOP);
-	intel_ring_advance(ring);
+	intel_ring_emit(engine, MI_LOAD_REGISTER_IMM(2));
+	intel_ring_emit_reg(engine, RING_PP_DIR_DCLV(engine));
+	intel_ring_emit(engine, PP_DIR_DCLV_2G);
+	intel_ring_emit_reg(engine, RING_PP_DIR_BASE(engine));
+	intel_ring_emit(engine, get_pd_offset(ppgtt));
+	intel_ring_emit(engine, MI_NOOP);
+	intel_ring_advance(engine);
 
 	return 0;
 }
@@ -1676,22 +1668,22 @@ static int hsw_mm_switch(struct i915_hw_
 static int vgpu_mm_switch(struct i915_hw_ppgtt *ppgtt,
 			  struct drm_i915_gem_request *req)
 {
-	struct intel_engine_cs *ring = req->ring;
+	struct intel_engine_cs *engine = req->engine;
 	struct drm_i915_private *dev_priv = to_i915(ppgtt->base.dev);
 
-	I915_WRITE(RING_PP_DIR_DCLV(ring), PP_DIR_DCLV_2G);
-	I915_WRITE(RING_PP_DIR_BASE(ring), get_pd_offset(ppgtt));
+	I915_WRITE(RING_PP_DIR_DCLV(engine), PP_DIR_DCLV_2G);
+	I915_WRITE(RING_PP_DIR_BASE(engine), get_pd_offset(ppgtt));
 	return 0;
 }
 
 static int gen7_mm_switch(struct i915_hw_ppgtt *ppgtt,
 			  struct drm_i915_gem_request *req)
 {
-	struct intel_engine_cs *ring = req->ring;
+	struct intel_engine_cs *engine = req->engine;
 	int ret;
 
 	/* NB: TLBs must be flushed and invalidated before a switch */
-	ret = ring->flush(req, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
+	ret = engine->flush(req, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
 	if (ret)
 		return ret;
 
@@ -1699,17 +1691,17 @@ static int gen7_mm_switch(struct i915_hw
 	if (ret)
 		return ret;
 
-	intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(2));
-	intel_ring_emit_reg(ring, RING_PP_DIR_DCLV(ring));
-	intel_ring_emit(ring, PP_DIR_DCLV_2G);
-	intel_ring_emit_reg(ring, RING_PP_DIR_BASE(ring));
-	intel_ring_emit(ring, get_pd_offset(ppgtt));
-	intel_ring_emit(ring, MI_NOOP);
-	intel_ring_advance(ring);
+	intel_ring_emit(engine, MI_LOAD_REGISTER_IMM(2));
+	intel_ring_emit_reg(engine, RING_PP_DIR_DCLV(engine));
+	intel_ring_emit(engine, PP_DIR_DCLV_2G);
+	intel_ring_emit_reg(engine, RING_PP_DIR_BASE(engine));
+	intel_ring_emit(engine, get_pd_offset(ppgtt));
+	intel_ring_emit(engine, MI_NOOP);
+	intel_ring_advance(engine);
 
 	/* XXX: RCS is the only one to auto invalidate the TLBs? */
-	if (ring->id != RCS) {
-		ret = ring->flush(req, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
+	if (engine->id != RCS) {
+		ret = engine->flush(req, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
 		if (ret)
 			return ret;
 	}
@@ -1720,15 +1712,15 @@ static int gen7_mm_switch(struct i915_hw
 static int gen6_mm_switch(struct i915_hw_ppgtt *ppgtt,
 			  struct drm_i915_gem_request *req)
 {
-	struct intel_engine_cs *ring = req->ring;
+	struct intel_engine_cs *engine = req->engine;
 	struct drm_device *dev = ppgtt->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 
-	I915_WRITE(RING_PP_DIR_DCLV(ring), PP_DIR_DCLV_2G);
-	I915_WRITE(RING_PP_DIR_BASE(ring), get_pd_offset(ppgtt));
+	I915_WRITE(RING_PP_DIR_DCLV(engine), PP_DIR_DCLV_2G);
+	I915_WRITE(RING_PP_DIR_BASE(engine), get_pd_offset(ppgtt));
 
-	POSTING_READ(RING_PP_DIR_DCLV(ring));
+	POSTING_READ(RING_PP_DIR_DCLV(engine));
 
 	return 0;
 }
@@ -1736,12 +1728,11 @@ static int gen6_mm_switch(struct i915_hw
 static void gen8_ppgtt_enable(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring;
-	int j;
+	struct intel_engine_cs *engine;
 
-	for_each_ring(ring, dev_priv, j) {
+	for_each_engine(engine, dev_priv) {
 		u32 four_level = USES_FULL_48BIT_PPGTT(dev) ? GEN8_GFX_PPGTT_48B : 0;
-		I915_WRITE(RING_MODE_GEN7(ring),
+		I915_WRITE(RING_MODE_GEN7(engine),
 			   _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE | four_level));
 	}
 }
@@ -1749,9 +1740,8 @@ static void gen8_ppgtt_enable(struct drm
 static void gen7_ppgtt_enable(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring;
+	struct intel_engine_cs *engine;
 	uint32_t ecochk, ecobits;
-	int i;
 
 	ecobits = I915_READ(GAC_ECO_BITS);
 	I915_WRITE(GAC_ECO_BITS, ecobits | ECOBITS_PPGTT_CACHE64B);
@@ -1765,9 +1755,9 @@ static void gen7_ppgtt_enable(struct drm
 	}
 	I915_WRITE(GAM_ECOCHK, ecochk);
 
-	for_each_ring(ring, dev_priv, i) {
+	for_each_engine(engine, dev_priv) {
 		/* GFX_MODE is per-ring on gen7+ */
-		I915_WRITE(RING_MODE_GEN7(ring),
+		I915_WRITE(RING_MODE_GEN7(engine),
 			   _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE));
 	}
 }
@@ -1796,8 +1786,7 @@ static void gen6_ppgtt_clear_range(struc
 				   uint64_t length,
 				   bool use_scratch)
 {
-	struct i915_hw_ppgtt *ppgtt =
-		container_of(vm, struct i915_hw_ppgtt, base);
+	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
 	gen6_pte_t *pt_vaddr, scratch_pte;
 	unsigned first_entry = start >> PAGE_SHIFT;
 	unsigned num_entries = length >> PAGE_SHIFT;
@@ -1831,8 +1820,7 @@ static void gen6_ppgtt_insert_entries(st
 				      uint64_t start,
 				      enum i915_cache_level cache_level, u32 flags)
 {
-	struct i915_hw_ppgtt *ppgtt =
-		container_of(vm, struct i915_hw_ppgtt, base);
+	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
 	gen6_pte_t *pt_vaddr;
 	unsigned first_entry = start >> PAGE_SHIFT;
 	unsigned act_pt = first_entry / GEN6_PTES;
@@ -1864,9 +1852,9 @@ static int gen6_alloc_va_range(struct i9
 {
 	DECLARE_BITMAP(new_page_tables, I915_PDES);
 	struct drm_device *dev = vm->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct i915_hw_ppgtt *ppgtt =
-				container_of(vm, struct i915_hw_ppgtt, base);
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
+	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
 	struct i915_page_table *pt;
 	uint32_t start, length, start_save, length_save;
 	uint32_t pde, temp;
@@ -1932,7 +1920,7 @@ static int gen6_alloc_va_range(struct i9
 
 	/* Make sure write is complete before other code can use this page
 	 * table. Also require for WC mapped PTEs */
-	readl(dev_priv->gtt.gsm);
+	readl(ggtt->gsm);
 
 	mark_tlbs_dirty(ppgtt);
 	return 0;
@@ -1978,8 +1966,7 @@ static void gen6_free_scratch(struct i91
 
 static void gen6_ppgtt_cleanup(struct i915_address_space *vm)
 {
-	struct i915_hw_ppgtt *ppgtt =
-		container_of(vm, struct i915_hw_ppgtt, base);
+	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
 	struct i915_page_table *pt;
 	uint32_t pde;
 
@@ -1997,7 +1984,8 @@ static int gen6_ppgtt_allocate_page_dire
 {
 	struct i915_address_space *vm = &ppgtt->base;
 	struct drm_device *dev = ppgtt->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	bool retried = false;
 	int ret;
 
@@ -2005,23 +1993,23 @@ static int gen6_ppgtt_allocate_page_dire
 	 * allocator works in address space sizes, so it's multiplied by page
 	 * size. We allocate at the top of the GTT to avoid fragmentation.
 	 */
-	BUG_ON(!drm_mm_initialized(&dev_priv->gtt.base.mm));
+	BUG_ON(!drm_mm_initialized(&ggtt->base.mm));
 
 	ret = gen6_init_scratch(vm);
 	if (ret)
 		return ret;
 
 alloc:
-	ret = drm_mm_insert_node_in_range_generic(&dev_priv->gtt.base.mm,
+	ret = drm_mm_insert_node_in_range_generic(&ggtt->base.mm,
 						  &ppgtt->node, GEN6_PD_SIZE,
 						  GEN6_PD_ALIGN, 0,
-						  0, dev_priv->gtt.base.total,
+						  0, ggtt->base.total,
 						  DRM_MM_TOPDOWN);
 	if (ret == -ENOSPC && !retried) {
-		ret = i915_gem_evict_something(dev, &dev_priv->gtt.base,
+		ret = i915_gem_evict_something(dev, &ggtt->base,
 					       GEN6_PD_SIZE, GEN6_PD_ALIGN,
 					       I915_CACHE_NONE,
-					       0, dev_priv->gtt.base.total,
+					       0, ggtt->base.total,
 					       0);
 		if (ret)
 			goto err_out;
@@ -2034,7 +2022,7 @@ alloc:
 		goto err_out;
 
 
-	if (ppgtt->node.start < dev_priv->gtt.mappable_end)
+	if (ppgtt->node.start < ggtt->mappable_end)
 		DRM_DEBUG("Forced to use aperture for PDEs\n");
 
 	return 0;
@@ -2062,10 +2050,11 @@ static void gen6_scratch_va_range(struct
 static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
 {
 	struct drm_device *dev = ppgtt->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	int ret;
 
-	ppgtt->base.pte_encode = dev_priv->gtt.base.pte_encode;
+	ppgtt->base.pte_encode = ggtt->base.pte_encode;
 	if (IS_GEN6(dev)) {
 		ppgtt->switch_mm = gen6_mm_switch;
 	} else if (IS_HASWELL(dev)) {
@@ -2095,7 +2084,7 @@ static int gen6_ppgtt_init(struct i915_h
 	ppgtt->pd.base.ggtt_offset =
 		ppgtt->node.start / PAGE_SIZE * sizeof(gen6_pte_t);
 
-	ppgtt->pd_addr = (gen6_pte_t __iomem *)dev_priv->gtt.gsm +
+	ppgtt->pd_addr = (gen6_pte_t __iomem *)ggtt->gsm +
 		ppgtt->pd.base.ggtt_offset / sizeof(gen6_pte_t);
 
 	gen6_scratch_va_range(ppgtt, 0, ppgtt->base.total);
@@ -2192,7 +2181,7 @@ int i915_ppgtt_init_hw(struct drm_device
 
 int i915_ppgtt_init_ring(struct drm_i915_gem_request *req)
 {
-	struct drm_i915_private *dev_priv = req->ring->dev->dev_private;
+	struct drm_i915_private *dev_priv = req->i915;
 	struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
 
 	if (i915.enable_execlists)
@@ -2263,9 +2252,10 @@ static bool needs_idle_maps(struct drm_d
 
 static bool do_idling(struct drm_i915_private *dev_priv)
 {
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	bool ret = dev_priv->mm.interruptible;
 
-	if (unlikely(dev_priv->gtt.do_idle_maps)) {
+	if (unlikely(ggtt->do_idle_maps)) {
 		dev_priv->mm.interruptible = false;
 		if (i915_gpu_idle(dev_priv->dev)) {
 			DRM_ERROR("Couldn't idle GPU\n");
@@ -2279,22 +2269,23 @@ static bool do_idling(struct drm_i915_pr
 
 static void undo_idling(struct drm_i915_private *dev_priv, bool interruptible)
 {
-	if (unlikely(dev_priv->gtt.do_idle_maps))
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
+
+	if (unlikely(ggtt->do_idle_maps))
 		dev_priv->mm.interruptible = interruptible;
 }
 
 void i915_check_and_clear_faults(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring;
-	int i;
+	struct intel_engine_cs *engine;
 
 	if (INTEL_INFO(dev)->gen < 6)
 		return;
 
-	for_each_ring(ring, dev_priv, i) {
+	for_each_engine(engine, dev_priv) {
 		u32 fault_reg;
-		fault_reg = I915_READ(RING_FAULT_REG(ring));
+		fault_reg = I915_READ(RING_FAULT_REG(engine));
 		if (fault_reg & RING_FAULT_VALID) {
 			DRM_DEBUG_DRIVER("Unexpected fault\n"
 					 "\tAddr: 0x%08lx\n"
@@ -2305,16 +2296,16 @@ void i915_check_and_clear_faults(struct
 					 fault_reg & RING_FAULT_GTTSEL_MASK ? "GGTT" : "PPGTT",
 					 RING_FAULT_SRCID(fault_reg),
 					 RING_FAULT_FAULT_TYPE(fault_reg));
-			I915_WRITE(RING_FAULT_REG(ring),
+			I915_WRITE(RING_FAULT_REG(engine),
 				   fault_reg & ~RING_FAULT_VALID);
 		}
 	}
-	POSTING_READ(RING_FAULT_REG(&dev_priv->ring[RCS]));
+	POSTING_READ(RING_FAULT_REG(&dev_priv->engine[RCS]));
 }
 
 static void i915_ggtt_flush(struct drm_i915_private *dev_priv)
 {
-	if (INTEL_INFO(dev_priv->dev)->gen < 6) {
+	if (INTEL_INFO(dev_priv)->gen < 6) {
 		intel_gtt_chipset_flush();
 	} else {
 		I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
@@ -2324,7 +2315,8 @@ static void i915_ggtt_flush(struct drm_i
 
 void i915_gem_suspend_gtt_mappings(struct drm_device *dev)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 
 	/* Don't bother messing with faults pre GEN6 as we have little
 	 * documentation supporting that it's a good idea.
@@ -2334,10 +2326,8 @@ void i915_gem_suspend_gtt_mappings(struc
 
 	i915_check_and_clear_faults(dev);
 
-	dev_priv->gtt.base.clear_range(&dev_priv->gtt.base,
-				       dev_priv->gtt.base.start,
-				       dev_priv->gtt.base.total,
-				       true);
+	ggtt->base.clear_range(&ggtt->base, ggtt->base.start, ggtt->base.total,
+			     true);
 
 	i915_ggtt_flush(dev_priv);
 }
@@ -2367,10 +2357,11 @@ static void gen8_ggtt_insert_entries(str
 				     uint64_t start,
 				     enum i915_cache_level level, u32 unused)
 {
-	struct drm_i915_private *dev_priv = vm->dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(vm->dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	unsigned first_entry = start >> PAGE_SHIFT;
 	gen8_pte_t __iomem *gtt_entries =
-		(gen8_pte_t __iomem *)dev_priv->gtt.gsm + first_entry;
+		(gen8_pte_t __iomem *)ggtt->gsm + first_entry;
 	int i = 0;
 	struct sg_page_iter sg_iter;
 	dma_addr_t addr = 0; /* shut up gcc */
@@ -2444,10 +2435,11 @@ static void gen6_ggtt_insert_entries(str
 				     uint64_t start,
 				     enum i915_cache_level level, u32 flags)
 {
-	struct drm_i915_private *dev_priv = vm->dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(vm->dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	unsigned first_entry = start >> PAGE_SHIFT;
 	gen6_pte_t __iomem *gtt_entries =
-		(gen6_pte_t __iomem *)dev_priv->gtt.gsm + first_entry;
+		(gen6_pte_t __iomem *)ggtt->gsm + first_entry;
 	int i = 0;
 	struct sg_page_iter sg_iter;
 	dma_addr_t addr = 0;
@@ -2487,12 +2479,13 @@ static void gen8_ggtt_clear_range(struct
 				  uint64_t length,
 				  bool use_scratch)
 {
-	struct drm_i915_private *dev_priv = vm->dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(vm->dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	unsigned first_entry = start >> PAGE_SHIFT;
 	unsigned num_entries = length >> PAGE_SHIFT;
 	gen8_pte_t scratch_pte, __iomem *gtt_base =
-		(gen8_pte_t __iomem *) dev_priv->gtt.gsm + first_entry;
-	const int max_entries = gtt_total_entries(dev_priv->gtt) - first_entry;
+		(gen8_pte_t __iomem *)ggtt->gsm + first_entry;
+	const int max_entries = ggtt_total_entries(ggtt) - first_entry;
 	int i;
 	int rpm_atomic_seq;
 
@@ -2518,12 +2511,13 @@ static void gen6_ggtt_clear_range(struct
 				  uint64_t length,
 				  bool use_scratch)
 {
-	struct drm_i915_private *dev_priv = vm->dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(vm->dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	unsigned first_entry = start >> PAGE_SHIFT;
 	unsigned num_entries = length >> PAGE_SHIFT;
 	gen6_pte_t scratch_pte, __iomem *gtt_base =
-		(gen6_pte_t __iomem *) dev_priv->gtt.gsm + first_entry;
-	const int max_entries = gtt_total_entries(dev_priv->gtt) - first_entry;
+		(gen6_pte_t __iomem *)ggtt->gsm + first_entry;
+	const int max_entries = ggtt_total_entries(ggtt) - first_entry;
 	int i;
 	int rpm_atomic_seq;
 
@@ -2613,32 +2607,31 @@ static int aliasing_gtt_bind_vma(struct
 				 enum i915_cache_level cache_level,
 				 u32 flags)
 {
-	struct drm_device *dev = vma->vm->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_i915_gem_object *obj = vma->obj;
-	struct sg_table *pages = obj->pages;
-	u32 pte_flags = 0;
+	u32 pte_flags;
 	int ret;
 
 	ret = i915_get_ggtt_vma_pages(vma);
 	if (ret)
 		return ret;
-	pages = vma->ggtt_view.pages;
 
 	/* Currently applicable only to VLV */
-	if (obj->gt_ro)
+	pte_flags = 0;
+	if (vma->obj->gt_ro)
 		pte_flags |= PTE_READ_ONLY;
 
 
 	if (flags & GLOBAL_BIND) {
-		vma->vm->insert_entries(vma->vm, pages,
+		vma->vm->insert_entries(vma->vm,
+					vma->ggtt_view.pages,
 					vma->node.start,
 					cache_level, pte_flags);
 	}
 
 	if (flags & LOCAL_BIND) {
-		struct i915_hw_ppgtt *appgtt = dev_priv->mm.aliasing_ppgtt;
-		appgtt->base.insert_entries(&appgtt->base, pages,
+		struct i915_hw_ppgtt *appgtt =
+			to_i915(vma->vm->dev)->mm.aliasing_ppgtt;
+		appgtt->base.insert_entries(&appgtt->base,
+					    vma->ggtt_view.pages,
 					    vma->node.start,
 					    cache_level, pte_flags);
 	}
@@ -2717,8 +2710,8 @@ static int i915_gem_setup_global_gtt(str
 	 * aperture.  One page should be enough to keep any prefetching inside
 	 * of the aperture.
 	 */
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct i915_address_space *ggtt_vm = &dev_priv->gtt.base;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	struct drm_mm_node *entry;
 	struct drm_i915_gem_object *obj;
 	unsigned long hole_start, hole_end;
@@ -2726,13 +2719,13 @@ static int i915_gem_setup_global_gtt(str
 
 	BUG_ON(mappable_end > end);
 
-	ggtt_vm->start = start;
+	ggtt->base.start = start;
 
 	/* Subtract the guard page before address space initialization to
 	 * shrink the range used by drm_mm */
-	ggtt_vm->total = end - start - PAGE_SIZE;
-	i915_address_space_init(ggtt_vm, dev_priv);
-	ggtt_vm->total += PAGE_SIZE;
+	ggtt->base.total = end - start - PAGE_SIZE;
+	i915_address_space_init(&ggtt->base, dev_priv);
+	ggtt->base.total += PAGE_SIZE;
 
 	if (intel_vgpu_active(dev)) {
 		ret = intel_vgt_balloon(dev);
@@ -2741,36 +2734,36 @@ static int i915_gem_setup_global_gtt(str
 	}
 
 	if (!HAS_LLC(dev))
-		ggtt_vm->mm.color_adjust = i915_gtt_color_adjust;
+		ggtt->base.mm.color_adjust = i915_gtt_color_adjust;
 
 	/* Mark any preallocated objects as occupied */
 	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
-		struct i915_vma *vma = i915_gem_obj_to_vma(obj, ggtt_vm);
+		struct i915_vma *vma = i915_gem_obj_to_vma(obj, &ggtt->base);
 
 		DRM_DEBUG_KMS("reserving preallocated space: %llx + %zx\n",
 			      i915_gem_obj_ggtt_offset(obj), obj->base.size);
 
 		WARN_ON(i915_gem_obj_ggtt_bound(obj));
-		ret = drm_mm_reserve_node(&ggtt_vm->mm, &vma->node);
+		ret = drm_mm_reserve_node(&ggtt->base.mm, &vma->node);
 		if (ret) {
 			DRM_DEBUG_KMS("Reservation failed: %i\n", ret);
 			return ret;
 		}
 		vma->bound |= GLOBAL_BIND;
 		__i915_vma_set_map_and_fenceable(vma);
-		list_add_tail(&vma->vm_link, &ggtt_vm->inactive_list);
+		list_add_tail(&vma->vm_link, &ggtt->base.inactive_list);
 	}
 
 	/* Clear any non-preallocated blocks */
-	drm_mm_for_each_hole(entry, &ggtt_vm->mm, hole_start, hole_end) {
+	drm_mm_for_each_hole(entry, &ggtt->base.mm, hole_start, hole_end) {
 		DRM_DEBUG_KMS("clearing unused GTT space: [%lx, %lx]\n",
 			      hole_start, hole_end);
-		ggtt_vm->clear_range(ggtt_vm, hole_start,
+		ggtt->base.clear_range(&ggtt->base, hole_start,
 				     hole_end - hole_start, true);
 	}
 
 	/* And finally clear the reserved guard page */
-	ggtt_vm->clear_range(ggtt_vm, end - PAGE_SIZE, PAGE_SIZE, true);
+	ggtt->base.clear_range(&ggtt->base, end - PAGE_SIZE, PAGE_SIZE, true);
 
 	if (USES_PPGTT(dev) && !USES_FULL_PPGTT(dev)) {
 		struct i915_hw_ppgtt *ppgtt;
@@ -2801,28 +2794,33 @@ static int i915_gem_setup_global_gtt(str
 					true);
 
 		dev_priv->mm.aliasing_ppgtt = ppgtt;
-		WARN_ON(dev_priv->gtt.base.bind_vma != ggtt_bind_vma);
-		dev_priv->gtt.base.bind_vma = aliasing_gtt_bind_vma;
+		WARN_ON(ggtt->base.bind_vma != ggtt_bind_vma);
+		ggtt->base.bind_vma = aliasing_gtt_bind_vma;
 	}
 
 	return 0;
 }
 
-void i915_gem_init_global_gtt(struct drm_device *dev)
+/**
+ * i915_gem_init_ggtt - Initialize GEM for Global GTT
+ * @dev: DRM device
+ */
+void i915_gem_init_ggtt(struct drm_device *dev)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	u64 gtt_size, mappable_size;
-
-	gtt_size = dev_priv->gtt.base.total;
-	mappable_size = dev_priv->gtt.mappable_end;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 
-	i915_gem_setup_global_gtt(dev, 0, mappable_size, gtt_size);
+	i915_gem_setup_global_gtt(dev, 0, ggtt->mappable_end, ggtt->base.total);
 }
 
-void i915_global_gtt_cleanup(struct drm_device *dev)
+/**
+ * i915_ggtt_cleanup_hw - Clean up GGTT hardware initialization
+ * @dev: DRM device
+ */
+void i915_ggtt_cleanup_hw(struct drm_device *dev)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct i915_address_space *vm = &dev_priv->gtt.base;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 
 	if (dev_priv->mm.aliasing_ppgtt) {
 		struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
@@ -2832,15 +2830,15 @@ void i915_global_gtt_cleanup(struct drm_
 
 	i915_gem_cleanup_stolen(dev);
 
-	if (drm_mm_initialized(&vm->mm)) {
+	if (drm_mm_initialized(&ggtt->base.mm)) {
 		if (intel_vgpu_active(dev))
 			intel_vgt_deballoon();
 
-		drm_mm_takedown(&vm->mm);
-		list_del(&vm->global_link);
+		drm_mm_takedown(&ggtt->base.mm);
+		list_del(&ggtt->base.global_link);
 	}
 
-	vm->cleanup(vm);
+	ggtt->base.cleanup(&ggtt->base);
 }
 
 static unsigned int gen6_get_total_gtt_size(u16 snb_gmch_ctl)
@@ -2924,13 +2922,14 @@ static size_t gen9_get_stolen_size(u16 g
 static int ggtt_probe_common(struct drm_device *dev,
 			     size_t gtt_size)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	struct i915_page_scratch *scratch_page;
-	phys_addr_t gtt_phys_addr;
+	phys_addr_t ggtt_phys_addr;
 
 	/* For Modern GENs the PTEs and register space are split in the BAR */
-	gtt_phys_addr = pci_resource_start(dev->pdev, 0) +
-		(pci_resource_len(dev->pdev, 0) / 2);
+	ggtt_phys_addr = pci_resource_start(dev->pdev, 0) +
+			 (pci_resource_len(dev->pdev, 0) / 2);
 
 	/*
 	 * On BXT writes larger than 64 bit to the GTT pagetable range will be
@@ -2940,10 +2939,10 @@ static int ggtt_probe_common(struct drm_
 	 * readback check when writing GTT PTE entries.
 	 */
 	if (IS_BROXTON(dev))
-		dev_priv->gtt.gsm = ioremap_nocache(gtt_phys_addr, gtt_size);
+		ggtt->gsm = ioremap_nocache(ggtt_phys_addr, gtt_size);
 	else
-		dev_priv->gtt.gsm = ioremap_wc(gtt_phys_addr, gtt_size);
-	if (!dev_priv->gtt.gsm) {
+		ggtt->gsm = ioremap_wc(ggtt_phys_addr, gtt_size);
+	if (!ggtt->gsm) {
 		DRM_ERROR("Failed to map the gtt page table\n");
 		return -ENOMEM;
 	}
@@ -2952,11 +2951,11 @@ static int ggtt_probe_common(struct drm_
 	if (IS_ERR(scratch_page)) {
 		DRM_ERROR("Scratch setup failed\n");
 		/* iounmap will also get called at remove, but meh */
-		iounmap(dev_priv->gtt.gsm);
+		iounmap(ggtt->gsm);
 		return PTR_ERR(scratch_page);
 	}
 
-	dev_priv->gtt.base.scratch_page = scratch_page;
+	ggtt->base.scratch_page = scratch_page;
 
 	return 0;
 }
@@ -2977,7 +2976,7 @@ static void bdw_setup_private_ppat(struc
 	      GEN8_PPAT(6, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(2)) |
 	      GEN8_PPAT(7, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(3));
 
-	if (!USES_PPGTT(dev_priv->dev))
+	if (!USES_PPGTT(dev_priv))
 		/* Spec: "For GGTT, there is NO pat_sel[2:0] from the entry,
 		 * so RTL will always use the value corresponding to
 		 * pat_sel = 000".
@@ -3034,20 +3033,16 @@ static void chv_setup_private_ppat(struc
 	I915_WRITE(GEN8_PRIVATE_PAT_HI, pat >> 32);
 }
 
-static int gen8_gmch_probe(struct drm_device *dev,
-			   u64 *gtt_total,
-			   size_t *stolen,
-			   phys_addr_t *mappable_base,
-			   u64 *mappable_end)
+static int gen8_gmch_probe(struct i915_ggtt *ggtt)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	u64 gtt_size;
+	struct drm_device *dev = ggtt->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(dev);
 	u16 snb_gmch_ctl;
 	int ret;
 
 	/* TODO: We're not aware of mappable constraints on gen8 yet */
-	*mappable_base = pci_resource_start(dev->pdev, 2);
-	*mappable_end = pci_resource_len(dev->pdev, 2);
+	ggtt->mappable_base = pci_resource_start(dev->pdev, 2);
+	ggtt->mappable_end = pci_resource_len(dev->pdev, 2);
 
 	if (!pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(39)))
 		pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(39));
@@ -3055,56 +3050,50 @@ static int gen8_gmch_probe(struct drm_de
 	pci_read_config_word(dev->pdev, SNB_GMCH_CTRL, &snb_gmch_ctl);
 
 	if (INTEL_INFO(dev)->gen >= 9) {
-		*stolen = gen9_get_stolen_size(snb_gmch_ctl);
-		gtt_size = gen8_get_total_gtt_size(snb_gmch_ctl);
+		ggtt->stolen_size = gen9_get_stolen_size(snb_gmch_ctl);
+		ggtt->size = gen8_get_total_gtt_size(snb_gmch_ctl);
 	} else if (IS_CHERRYVIEW(dev)) {
-		*stolen = chv_get_stolen_size(snb_gmch_ctl);
-		gtt_size = chv_get_total_gtt_size(snb_gmch_ctl);
+		ggtt->stolen_size = chv_get_stolen_size(snb_gmch_ctl);
+		ggtt->size = chv_get_total_gtt_size(snb_gmch_ctl);
 	} else {
-		*stolen = gen8_get_stolen_size(snb_gmch_ctl);
-		gtt_size = gen8_get_total_gtt_size(snb_gmch_ctl);
+		ggtt->stolen_size = gen8_get_stolen_size(snb_gmch_ctl);
+		ggtt->size = gen8_get_total_gtt_size(snb_gmch_ctl);
 	}
 
-	*gtt_total = (gtt_size / sizeof(gen8_pte_t)) << PAGE_SHIFT;
+	ggtt->base.total = (ggtt->size / sizeof(gen8_pte_t)) << PAGE_SHIFT;
 
 	if (IS_CHERRYVIEW(dev) || IS_BROXTON(dev))
 		chv_setup_private_ppat(dev_priv);
 	else
 		bdw_setup_private_ppat(dev_priv);
 
-	ret = ggtt_probe_common(dev, gtt_size);
-
-	dev_priv->gtt.base.clear_range = gen8_ggtt_clear_range;
-	dev_priv->gtt.base.insert_entries = gen8_ggtt_insert_entries;
-	dev_priv->gtt.base.bind_vma = ggtt_bind_vma;
-	dev_priv->gtt.base.unbind_vma = ggtt_unbind_vma;
+	ret = ggtt_probe_common(dev, ggtt->size);
 
+	ggtt->base.clear_range = gen8_ggtt_clear_range;
 	if (IS_CHERRYVIEW(dev_priv))
-		dev_priv->gtt.base.insert_entries = gen8_ggtt_insert_entries__BKL;
+		ggtt->base.insert_entries = gen8_ggtt_insert_entries__BKL;
+	else
+		ggtt->base.insert_entries = gen8_ggtt_insert_entries;
+	ggtt->base.bind_vma = ggtt_bind_vma;
+	ggtt->base.unbind_vma = ggtt_unbind_vma;
 
 	return ret;
 }
 
-static int gen6_gmch_probe(struct drm_device *dev,
-			   u64 *gtt_total,
-			   size_t *stolen,
-			   phys_addr_t *mappable_base,
-			   u64 *mappable_end)
+static int gen6_gmch_probe(struct i915_ggtt *ggtt)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	unsigned int gtt_size;
+	struct drm_device *dev = ggtt->base.dev;
 	u16 snb_gmch_ctl;
 	int ret;
 
-	*mappable_base = pci_resource_start(dev->pdev, 2);
-	*mappable_end = pci_resource_len(dev->pdev, 2);
+	ggtt->mappable_base = pci_resource_start(dev->pdev, 2);
+	ggtt->mappable_end = pci_resource_len(dev->pdev, 2);
 
 	/* 64/512MB is the current min/max we actually know of, but this is just
 	 * a coarse sanity check.
 	 */
-	if ((*mappable_end < (64<<20) || (*mappable_end > (512<<20)))) {
-		DRM_ERROR("Unknown GMADR size (%llx)\n",
-			  dev_priv->gtt.mappable_end);
+	if ((ggtt->mappable_end < (64<<20) || (ggtt->mappable_end > (512<<20)))) {
+		DRM_ERROR("Unknown GMADR size (%llx)\n", ggtt->mappable_end);
 		return -ENXIO;
 	}
 
@@ -3112,37 +3101,32 @@ static int gen6_gmch_probe(struct drm_de
 		pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(40));
 	pci_read_config_word(dev->pdev, SNB_GMCH_CTRL, &snb_gmch_ctl);
 
-	*stolen = gen6_get_stolen_size(snb_gmch_ctl);
-
-	gtt_size = gen6_get_total_gtt_size(snb_gmch_ctl);
-	*gtt_total = (gtt_size / sizeof(gen6_pte_t)) << PAGE_SHIFT;
+	ggtt->stolen_size = gen6_get_stolen_size(snb_gmch_ctl);
+	ggtt->size = gen6_get_total_gtt_size(snb_gmch_ctl);
+	ggtt->base.total = (ggtt->size / sizeof(gen6_pte_t)) << PAGE_SHIFT;
 
-	ret = ggtt_probe_common(dev, gtt_size);
+	ret = ggtt_probe_common(dev, ggtt->size);
 
-	dev_priv->gtt.base.clear_range = gen6_ggtt_clear_range;
-	dev_priv->gtt.base.insert_entries = gen6_ggtt_insert_entries;
-	dev_priv->gtt.base.bind_vma = ggtt_bind_vma;
-	dev_priv->gtt.base.unbind_vma = ggtt_unbind_vma;
+	ggtt->base.clear_range = gen6_ggtt_clear_range;
+	ggtt->base.insert_entries = gen6_ggtt_insert_entries;
+	ggtt->base.bind_vma = ggtt_bind_vma;
+	ggtt->base.unbind_vma = ggtt_unbind_vma;
 
 	return ret;
 }
 
 static void gen6_gmch_remove(struct i915_address_space *vm)
 {
+	struct i915_ggtt *ggtt = container_of(vm, struct i915_ggtt, base);
 
-	struct i915_gtt *gtt = container_of(vm, struct i915_gtt, base);
-
-	iounmap(gtt->gsm);
+	iounmap(ggtt->gsm);
 	free_scratch_page(vm->dev, vm->scratch_page);
 }
 
-static int i915_gmch_probe(struct drm_device *dev,
-			   u64 *gtt_total,
-			   size_t *stolen,
-			   phys_addr_t *mappable_base,
-			   u64 *mappable_end)
+static int i915_gmch_probe(struct i915_ggtt *ggtt)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_device *dev = ggtt->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(dev);
 	int ret;
 
 	ret = intel_gmch_probe(dev_priv->bridge_dev, dev_priv->dev->pdev, NULL);
@@ -3151,15 +3135,16 @@ static int i915_gmch_probe(struct drm_de
 		return -EIO;
 	}
 
-	intel_gtt_get(gtt_total, stolen, mappable_base, mappable_end);
+	intel_gtt_get(&ggtt->base.total, &ggtt->stolen_size,
+		      &ggtt->mappable_base, &ggtt->mappable_end);
 
-	dev_priv->gtt.do_idle_maps = needs_idle_maps(dev_priv->dev);
-	dev_priv->gtt.base.insert_entries = i915_ggtt_insert_entries;
-	dev_priv->gtt.base.clear_range = i915_ggtt_clear_range;
-	dev_priv->gtt.base.bind_vma = ggtt_bind_vma;
-	dev_priv->gtt.base.unbind_vma = ggtt_unbind_vma;
+	ggtt->do_idle_maps = needs_idle_maps(dev_priv->dev);
+	ggtt->base.insert_entries = i915_ggtt_insert_entries;
+	ggtt->base.clear_range = i915_ggtt_clear_range;
+	ggtt->base.bind_vma = ggtt_bind_vma;
+	ggtt->base.unbind_vma = ggtt_unbind_vma;
 
-	if (unlikely(dev_priv->gtt.do_idle_maps))
+	if (unlikely(ggtt->do_idle_maps))
 		DRM_INFO("applying Ironlake quirks for intel_iommu\n");
 
 	return 0;
@@ -3170,41 +3155,53 @@ static void i915_gmch_remove(struct i915
 	intel_gmch_remove();
 }
 
-int i915_gem_gtt_init(struct drm_device *dev)
+/**
+ * i915_ggtt_init_hw - Initialize GGTT hardware
+ * @dev: DRM device
+ */
+int i915_ggtt_init_hw(struct drm_device *dev)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct i915_gtt *gtt = &dev_priv->gtt;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	int ret;
 
 	if (INTEL_INFO(dev)->gen <= 5) {
-		gtt->gtt_probe = i915_gmch_probe;
-		gtt->base.cleanup = i915_gmch_remove;
+		ggtt->probe = i915_gmch_probe;
+		ggtt->base.cleanup = i915_gmch_remove;
 	} else if (INTEL_INFO(dev)->gen < 8) {
-		gtt->gtt_probe = gen6_gmch_probe;
-		gtt->base.cleanup = gen6_gmch_remove;
-		if (IS_HASWELL(dev) && dev_priv->ellc_size)
-			gtt->base.pte_encode = iris_pte_encode;
+		ggtt->probe = gen6_gmch_probe;
+		ggtt->base.cleanup = gen6_gmch_remove;
+
+		if (HAS_EDRAM(dev))
+			ggtt->base.pte_encode = iris_pte_encode;
 		else if (IS_HASWELL(dev))
-			gtt->base.pte_encode = hsw_pte_encode;
+			ggtt->base.pte_encode = hsw_pte_encode;
 		else if (IS_VALLEYVIEW(dev))
-			gtt->base.pte_encode = byt_pte_encode;
+			ggtt->base.pte_encode = byt_pte_encode;
 		else if (INTEL_INFO(dev)->gen >= 7)
-			gtt->base.pte_encode = ivb_pte_encode;
+			ggtt->base.pte_encode = ivb_pte_encode;
 		else
-			gtt->base.pte_encode = snb_pte_encode;
+			ggtt->base.pte_encode = snb_pte_encode;
 	} else {
-		dev_priv->gtt.gtt_probe = gen8_gmch_probe;
-		dev_priv->gtt.base.cleanup = gen6_gmch_remove;
+		ggtt->probe = gen8_gmch_probe;
+		ggtt->base.cleanup = gen6_gmch_remove;
 	}
 
-	gtt->base.dev = dev;
-	gtt->base.is_ggtt = true;
+	ggtt->base.dev = dev;
+	ggtt->base.is_ggtt = true;
 
-	ret = gtt->gtt_probe(dev, &gtt->base.total, &gtt->stolen_size,
-			     &gtt->mappable_base, &gtt->mappable_end);
+	ret = ggtt->probe(ggtt);
 	if (ret)
 		return ret;
 
+	if ((ggtt->base.total - 1) >> 32) {
+		DRM_ERROR("We never expected a Global GTT with more than 32bits"
+			  "of address space! Found %lldM!\n",
+			  ggtt->base.total >> 20);
+		ggtt->base.total = 1ULL << 32;
+		ggtt->mappable_end = min(ggtt->mappable_end, ggtt->base.total);
+	}
+
 	/*
 	 * Initialise stolen early so that we may reserve preallocated
 	 * objects for the BIOS to KMS transition.
@@ -3215,9 +3212,9 @@ int i915_gem_gtt_init(struct drm_device
 
 	/* GMADR is the PCI mmio aperture into the global GTT. */
 	DRM_INFO("Memory usable by graphics device = %lluM\n",
-		 gtt->base.total >> 20);
-	DRM_DEBUG_DRIVER("GMADR size = %lldM\n", gtt->mappable_end >> 20);
-	DRM_DEBUG_DRIVER("GTT stolen size = %zdM\n", gtt->stolen_size >> 20);
+		 ggtt->base.total >> 20);
+	DRM_DEBUG_DRIVER("GMADR size = %lldM\n", ggtt->mappable_end >> 20);
+	DRM_DEBUG_DRIVER("GTT stolen size = %zdM\n", ggtt->stolen_size >> 20);
 #ifdef CONFIG_INTEL_IOMMU
 	if (intel_iommu_gfx_mapped)
 		DRM_INFO("VT-d active for gfx access\n");
@@ -3234,33 +3231,38 @@ int i915_gem_gtt_init(struct drm_device
 	return 0;
 
 out_gtt_cleanup:
-	gtt->base.cleanup(&dev_priv->gtt.base);
+	ggtt->base.cleanup(&ggtt->base);
 
 	return ret;
 }
 
+int i915_ggtt_enable_hw(struct drm_device *dev)
+{
+	if (INTEL_INFO(dev)->gen < 6 && !intel_enable_gtt())
+		return -EIO;
+
+	return 0;
+}
+
 void i915_gem_restore_gtt_mappings(struct drm_device *dev)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	struct drm_i915_gem_object *obj;
-	struct i915_address_space *vm;
 	struct i915_vma *vma;
 	bool flush;
 
 	i915_check_and_clear_faults(dev);
 
 	/* First fill our portion of the GTT with scratch pages */
-	dev_priv->gtt.base.clear_range(&dev_priv->gtt.base,
-				       dev_priv->gtt.base.start,
-				       dev_priv->gtt.base.total,
-				       true);
+	ggtt->base.clear_range(&ggtt->base, ggtt->base.start, ggtt->base.total,
+			       true);
 
 	/* Cache flush objects bound into GGTT and rebind them. */
-	vm = &dev_priv->gtt.base;
 	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
 		flush = false;
 		list_for_each_entry(vma, &obj->vma_list, obj_link) {
-			if (vma->vm != vm)
+			if (vma->vm != &ggtt->base)
 				continue;
 
 			WARN_ON(i915_vma_bind(vma, obj->cache_level,
@@ -3283,15 +3285,17 @@ void i915_gem_restore_gtt_mappings(struc
 	}
 
 	if (USES_PPGTT(dev)) {
+		struct i915_address_space *vm;
+
 		list_for_each_entry(vm, &dev_priv->vm_list, global_link) {
 			/* TODO: Perhaps it shouldn't be gen6 specific */
 
-			struct i915_hw_ppgtt *ppgtt =
-					container_of(vm, struct i915_hw_ppgtt,
-						     base);
+			struct i915_hw_ppgtt *ppgtt;
 
-			if (i915_is_ggtt(vm))
+			if (vm->is_ggtt)
 				ppgtt = dev_priv->mm.aliasing_ppgtt;
+			else
+				ppgtt = i915_vm_to_ppgtt(vm);
 
 			gen6_write_page_range(dev_priv, &ppgtt->pd,
 					      0, ppgtt->base.total);
@@ -3350,19 +3354,13 @@ struct i915_vma *
 i915_gem_obj_lookup_or_create_ggtt_vma(struct drm_i915_gem_object *obj,
 				       const struct i915_ggtt_view *view)
 {
-	struct i915_address_space *ggtt = i915_obj_to_ggtt(obj);
-	struct i915_vma *vma;
-
-	if (WARN_ON(!view))
-		return ERR_PTR(-EINVAL);
-
-	vma = i915_gem_obj_to_ggtt_view(obj, view);
-
-	if (IS_ERR(vma))
-		return vma;
+	struct drm_device *dev = obj->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
+	struct i915_vma *vma = i915_gem_obj_to_ggtt_view(obj, view);
 
 	if (!vma)
-		vma = __i915_gem_vma_create(obj, ggtt, view);
+		vma = __i915_gem_vma_create(obj, &ggtt->base, view);
 
 	return vma;
 
@@ -3377,11 +3375,6 @@ rotate_pages(const dma_addr_t *in, unsig
 	unsigned int column, row;
 	unsigned int src_idx;
 
-	if (!sg) {
-		st->nents = 0;
-		sg = st->sgl;
-	}
-
 	for (column = 0; column < width; column++) {
 		src_idx = stride * (height - 1) + column;
 		for (row = 0; row < height; row++) {
@@ -3405,7 +3398,7 @@ static struct sg_table *
 intel_rotate_fb_obj_pages(struct intel_rotation_info *rot_info,
 			  struct drm_i915_gem_object *obj)
 {
-	unsigned int size_pages = rot_info->size >> PAGE_SHIFT;
+	unsigned int size_pages = rot_info->plane[0].width * rot_info->plane[0].height;
 	unsigned int size_pages_uv;
 	struct sg_page_iter sg_iter;
 	unsigned long i;
@@ -3416,14 +3409,15 @@ intel_rotate_fb_obj_pages(struct intel_r
 	int ret = -ENOMEM;
 
 	/* Allocate a temporary list of source pages for random access. */
-	page_addr_list = drm_malloc_ab(obj->base.size / PAGE_SIZE,
-				       sizeof(dma_addr_t));
+	page_addr_list = drm_malloc_gfp(obj->base.size / PAGE_SIZE,
+					sizeof(dma_addr_t),
+					GFP_TEMPORARY);
 	if (!page_addr_list)
 		return ERR_PTR(ret);
 
 	/* Account for UV plane with NV12. */
 	if (rot_info->pixel_format == DRM_FORMAT_NV12)
-		size_pages_uv = rot_info->size_uv >> PAGE_SHIFT;
+		size_pages_uv = rot_info->plane[1].width * rot_info->plane[1].height;
 	else
 		size_pages_uv = 0;
 
@@ -3443,11 +3437,14 @@ intel_rotate_fb_obj_pages(struct intel_r
 		i++;
 	}
 
+	st->nents = 0;
+	sg = st->sgl;
+
 	/* Rotate the pages. */
 	sg = rotate_pages(page_addr_list, 0,
-		     rot_info->width_pages, rot_info->height_pages,
-		     rot_info->width_pages,
-		     st, NULL);
+			  rot_info->plane[0].width, rot_info->plane[0].height,
+			  rot_info->plane[0].width,
+			  st, sg);
 
 	/* Append the UV plane if NV12. */
 	if (rot_info->pixel_format == DRM_FORMAT_NV12) {
@@ -3459,18 +3456,15 @@ intel_rotate_fb_obj_pages(struct intel_r
 
 		rot_info->uv_start_page = uv_start_page;
 
-		rotate_pages(page_addr_list, uv_start_page,
-			     rot_info->width_pages_uv,
-			     rot_info->height_pages_uv,
-			     rot_info->width_pages_uv,
-			     st, sg);
+		sg = rotate_pages(page_addr_list, rot_info->uv_start_page,
+				  rot_info->plane[1].width, rot_info->plane[1].height,
+				  rot_info->plane[1].width,
+				  st, sg);
 	}
 
-	DRM_DEBUG_KMS(
-		      "Created rotated page mapping for object size %zu (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %u pages (%u plane 0)).\n",
-		      obj->base.size, rot_info->pitch, rot_info->height,
-		      rot_info->pixel_format, rot_info->width_pages,
-		      rot_info->height_pages, size_pages + size_pages_uv,
+	DRM_DEBUG_KMS("Created rotated page mapping for object size %zu (%ux%u tiles, %u pages (%u plane 0)).\n",
+		      obj->base.size, rot_info->plane[0].width,
+		      rot_info->plane[0].height, size_pages + size_pages_uv,
 		      size_pages);
 
 	drm_free_large(page_addr_list);
@@ -3482,11 +3476,9 @@ err_sg_alloc:
 err_st_alloc:
 	drm_free_large(page_addr_list);
 
-	DRM_DEBUG_KMS(
-		      "Failed to create rotated mapping for object size %zu! (%d) (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %u pages (%u plane 0))\n",
-		      obj->base.size, ret, rot_info->pitch, rot_info->height,
-		      rot_info->pixel_format, rot_info->width_pages,
-		      rot_info->height_pages, size_pages + size_pages_uv,
+	DRM_DEBUG_KMS("Failed to create rotated mapping for object size %zu! (%d) (%ux%u tiles, %u pages (%u plane 0))\n",
+		      obj->base.size, ret, rot_info->plane[0].width,
+		      rot_info->plane[0].height, size_pages + size_pages_uv,
 		      size_pages);
 	return ERR_PTR(ret);
 }
@@ -3634,7 +3626,7 @@ i915_ggtt_view_size(struct drm_i915_gem_
 	if (view->type == I915_GGTT_VIEW_NORMAL) {
 		return obj->base.size;
 	} else if (view->type == I915_GGTT_VIEW_ROTATED) {
-		return view->params.rotated.size;
+		return intel_rotation_info_size(&view->params.rotated) << PAGE_SHIFT;
 	} else if (view->type == I915_GGTT_VIEW_PARTIAL) {
 		return view->params.partial.size << PAGE_SHIFT;
 	} else {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_gem_gtt.h linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_gem_gtt.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_gem_gtt.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_gem_gtt.h	2016-07-24 15:23:50.000000000 -0400
@@ -42,7 +42,7 @@ typedef uint64_t gen8_pde_t;
 typedef uint64_t gen8_ppgtt_pdpe_t;
 typedef uint64_t gen8_ppgtt_pml4e_t;
 
-#define gtt_total_entries(gtt) ((gtt).base.total >> PAGE_SHIFT)
+#define ggtt_total_entries(ggtt) ((ggtt)->base.total >> PAGE_SHIFT)
 
 /* gen6-hsw has bit 11-4 for physical addr bit 39-32 */
 #define GEN6_GTT_ADDR_ENCODE(addr)	((addr) | (((addr) >> 28) & 0xff0))
@@ -135,16 +135,13 @@ enum i915_ggtt_view_type {
 };
 
 struct intel_rotation_info {
-	unsigned int height;
-	unsigned int pitch;
 	unsigned int uv_offset;
 	uint32_t pixel_format;
-	uint64_t fb_modifier;
-	unsigned int width_pages, height_pages;
-	uint64_t size;
-	unsigned int width_pages_uv, height_pages_uv;
-	uint64_t size_uv;
 	unsigned int uv_start_page;
+	struct {
+		/* tiles */
+		unsigned int width, height;
+	} plane[2];
 };
 
 struct i915_ggtt_view {
@@ -342,13 +339,14 @@ struct i915_address_space {
  * and correct (in cases like swizzling). That region is referred to as GMADR in
  * the spec.
  */
-struct i915_gtt {
+struct i915_ggtt {
 	struct i915_address_space base;
 
 	size_t stolen_size;		/* Total size of stolen memory */
 	size_t stolen_usable_size;	/* Total size minus BIOS reserved */
 	size_t stolen_reserved_base;
 	size_t stolen_reserved_size;
+	size_t size;			/* Total size of Global GTT */
 	u64 mappable_end;		/* End offset that we can CPU map */
 	struct io_mapping *mappable;	/* Mapping to our CPU mappable region */
 	phys_addr_t mappable_base;	/* PA of our GMADR */
@@ -360,10 +358,7 @@ struct i915_gtt {
 
 	int mtrr;
 
-	/* global gtt ops */
-	int (*gtt_probe)(struct drm_device *dev, u64 *gtt_total,
-			  size_t *stolen, phys_addr_t *mappable_base,
-			  u64 *mappable_end);
+	int (*probe)(struct i915_ggtt *ggtt);
 };
 
 struct i915_hw_ppgtt {
@@ -518,10 +513,10 @@ i915_page_dir_dma_addr(const struct i915
 		px_dma(ppgtt->base.scratch_pd);
 }
 
-int i915_gem_gtt_init(struct drm_device *dev);
-void i915_gem_init_global_gtt(struct drm_device *dev);
-void i915_global_gtt_cleanup(struct drm_device *dev);
-
+int i915_ggtt_init_hw(struct drm_device *dev);
+int i915_ggtt_enable_hw(struct drm_device *dev);
+void i915_gem_init_ggtt(struct drm_device *dev);
+void i915_ggtt_cleanup_hw(struct drm_device *dev);
 
 int i915_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt);
 int i915_ppgtt_init_hw(struct drm_device *dev);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_gem.h linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_gem.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_gem.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_gem.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,34 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __I915_GEM_H__
+#define __I915_GEM_H__
+
+#ifdef CONFIG_DRM_I915_DEBUG_GEM
+#define GEM_BUG_ON(expr) BUG_ON(expr)
+#else
+#define GEM_BUG_ON(expr)
+#endif
+
+#endif /* __I915_GEM_H__ */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_gem_render_state.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_gem_render_state.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_gem_render_state.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_gem_render_state.c	2016-07-24 15:23:50.000000000 -0400
@@ -169,15 +169,15 @@ void i915_gem_render_state_fini(struct r
 	drm_gem_object_unreference(&so->obj->base);
 }
 
-int i915_gem_render_state_prepare(struct intel_engine_cs *ring,
+int i915_gem_render_state_prepare(struct intel_engine_cs *engine,
 				  struct render_state *so)
 {
 	int ret;
 
-	if (WARN_ON(ring->id != RCS))
+	if (WARN_ON(engine->id != RCS))
 		return -ENOENT;
 
-	ret = render_state_init(so, ring->dev);
+	ret = render_state_init(so, engine->dev);
 	if (ret)
 		return ret;
 
@@ -198,21 +198,21 @@ int i915_gem_render_state_init(struct dr
 	struct render_state so;
 	int ret;
 
-	ret = i915_gem_render_state_prepare(req->ring, &so);
+	ret = i915_gem_render_state_prepare(req->engine, &so);
 	if (ret)
 		return ret;
 
 	if (so.rodata == NULL)
 		return 0;
 
-	ret = req->ring->dispatch_execbuffer(req, so.ggtt_offset,
+	ret = req->engine->dispatch_execbuffer(req, so.ggtt_offset,
 					     so.rodata->batch_items * 4,
 					     I915_DISPATCH_SECURE);
 	if (ret)
 		goto out;
 
 	if (so.aux_batch_size > 8) {
-		ret = req->ring->dispatch_execbuffer(req,
+		ret = req->engine->dispatch_execbuffer(req,
 						     (so.ggtt_offset +
 						      so.aux_batch_offset),
 						     so.aux_batch_size,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_gem_render_state.h linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_gem_render_state.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_gem_render_state.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_gem_render_state.h	2016-07-24 15:23:50.000000000 -0400
@@ -43,7 +43,7 @@ struct render_state {
 
 int i915_gem_render_state_init(struct drm_i915_gem_request *req);
 void i915_gem_render_state_fini(struct render_state *so);
-int i915_gem_render_state_prepare(struct intel_engine_cs *ring,
+int i915_gem_render_state_prepare(struct intel_engine_cs *engine,
 				  struct render_state *so);
 
 #endif /* _I915_GEM_RENDER_STATE_H_ */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_gem_shrinker.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_gem_shrinker.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_gem_shrinker.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_gem_shrinker.c	2016-07-24 15:23:50.000000000 -0400
@@ -28,6 +28,7 @@
 #include <linux/swap.h>
 #include <linux/pci.h>
 #include <linux/dma-buf.h>
+#include <linux/vmalloc.h>
 #include <drm/drmP.h>
 #include <drm/i915_drm.h>
 
@@ -39,7 +40,7 @@ static bool mutex_is_locked_by(struct mu
 	if (!mutex_is_locked(mutex))
 		return false;
 
-#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_MUTEXES)
+#if defined(CONFIG_DEBUG_MUTEXES) || defined(CONFIG_MUTEX_SPIN_ON_OWNER)
 	return mutex->owner == task;
 #else
 	/* Since UP may be pre-empted, we cannot assume that we own the lock */
@@ -69,6 +70,10 @@ static bool swap_available(void)
 
 static bool can_release_pages(struct drm_i915_gem_object *obj)
 {
+	/* Only shmemfs objects are backed by swap */
+	if (!obj->base.filp)
+		return false;
+
 	/* Only report true if by unbinding the object and putting its pages
 	 * we can actually make forward progress towards freeing physical
 	 * pages.
@@ -166,6 +171,10 @@ i915_gem_shrink(struct drm_i915_private
 			    obj->madv != I915_MADV_DONTNEED)
 				continue;
 
+			if (flags & I915_SHRINK_VMAPS &&
+			    !is_vmalloc_addr(obj->mapping))
+				continue;
+
 			if ((flags & I915_SHRINK_ACTIVE) == 0 && obj->active)
 				continue;
 
@@ -246,7 +255,7 @@ i915_gem_shrinker_count(struct shrinker
 
 	count = 0;
 	list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_list)
-		if (obj->pages_pin_count == 0)
+		if (can_release_pages(obj))
 			count += obj->base.size >> PAGE_SHIFT;
 
 	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
@@ -288,67 +297,82 @@ i915_gem_shrinker_scan(struct shrinker *
 	return freed;
 }
 
-static int
-i915_gem_shrinker_oom(struct notifier_block *nb, unsigned long event, void *ptr)
-{
-	struct drm_i915_private *dev_priv =
-		container_of(nb, struct drm_i915_private, mm.oom_notifier);
-	struct drm_device *dev = dev_priv->dev;
-	struct drm_i915_gem_object *obj;
-	unsigned long timeout = msecs_to_jiffies(5000) + 1;
-	unsigned long pinned, bound, unbound, freed_pages;
+struct shrinker_lock_uninterruptible {
 	bool was_interruptible;
 	bool unlock;
+};
 
-	while (!i915_gem_shrinker_lock(dev, &unlock) && --timeout) {
+static bool
+i915_gem_shrinker_lock_uninterruptible(struct drm_i915_private *dev_priv,
+				       struct shrinker_lock_uninterruptible *slu,
+				       int timeout_ms)
+{
+	unsigned long timeout = msecs_to_jiffies(timeout_ms) + 1;
+
+	while (!i915_gem_shrinker_lock(dev_priv->dev, &slu->unlock)) {
 		schedule_timeout_killable(1);
 		if (fatal_signal_pending(current))
-			return NOTIFY_DONE;
-	}
-	if (timeout == 0) {
-		pr_err("Unable to purge GPU memory due lock contention.\n");
-		return NOTIFY_DONE;
+			return false;
+		if (--timeout == 0) {
+			pr_err("Unable to lock GPU to purge memory.\n");
+			return false;
+		}
 	}
 
-	was_interruptible = dev_priv->mm.interruptible;
+	slu->was_interruptible = dev_priv->mm.interruptible;
 	dev_priv->mm.interruptible = false;
+	return true;
+}
 
-	freed_pages = i915_gem_shrink_all(dev_priv);
+static void
+i915_gem_shrinker_unlock_uninterruptible(struct drm_i915_private *dev_priv,
+					 struct shrinker_lock_uninterruptible *slu)
+{
+	dev_priv->mm.interruptible = slu->was_interruptible;
+	if (slu->unlock)
+		mutex_unlock(&dev_priv->dev->struct_mutex);
+}
 
-	dev_priv->mm.interruptible = was_interruptible;
+static int
+i915_gem_shrinker_oom(struct notifier_block *nb, unsigned long event, void *ptr)
+{
+	struct drm_i915_private *dev_priv =
+		container_of(nb, struct drm_i915_private, mm.oom_notifier);
+	struct shrinker_lock_uninterruptible slu;
+	struct drm_i915_gem_object *obj;
+	unsigned long unevictable, bound, unbound, freed_pages;
+
+	if (!i915_gem_shrinker_lock_uninterruptible(dev_priv, &slu, 5000))
+		return NOTIFY_DONE;
+
+	freed_pages = i915_gem_shrink_all(dev_priv);
 
 	/* Because we may be allocating inside our own driver, we cannot
 	 * assert that there are no objects with pinned pages that are not
 	 * being pointed to by hardware.
 	 */
-	unbound = bound = pinned = 0;
+	unbound = bound = unevictable = 0;
 	list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_list) {
-		if (!obj->base.filp) /* not backed by a freeable object */
-			continue;
-
-		if (obj->pages_pin_count)
-			pinned += obj->base.size;
+		if (!can_release_pages(obj))
+			unevictable += obj->base.size >> PAGE_SHIFT;
 		else
-			unbound += obj->base.size;
+			unbound += obj->base.size >> PAGE_SHIFT;
 	}
 	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
-		if (!obj->base.filp)
-			continue;
-
-		if (obj->pages_pin_count)
-			pinned += obj->base.size;
+		if (!can_release_pages(obj))
+			unevictable += obj->base.size >> PAGE_SHIFT;
 		else
-			bound += obj->base.size;
+			bound += obj->base.size >> PAGE_SHIFT;
 	}
 
-	if (unlock)
-		mutex_unlock(&dev->struct_mutex);
+	i915_gem_shrinker_unlock_uninterruptible(dev_priv, &slu);
 
 	if (freed_pages || unbound || bound)
-		pr_info("Purging GPU memory, %lu bytes freed, %lu bytes still pinned.\n",
-			freed_pages << PAGE_SHIFT, pinned);
+		pr_info("Purging GPU memory, %lu pages freed, "
+			"%lu pages still pinned.\n",
+			freed_pages, unevictable);
 	if (unbound || bound)
-		pr_err("%lu and %lu bytes still available in the "
+		pr_err("%lu and %lu pages still available in the "
 		       "bound and unbound GPU page lists.\n",
 		       bound, unbound);
 
@@ -356,6 +380,29 @@ i915_gem_shrinker_oom(struct notifier_bl
 	return NOTIFY_DONE;
 }
 
+static int
+i915_gem_shrinker_vmap(struct notifier_block *nb, unsigned long event, void *ptr)
+{
+	struct drm_i915_private *dev_priv =
+		container_of(nb, struct drm_i915_private, mm.vmap_notifier);
+	struct shrinker_lock_uninterruptible slu;
+	unsigned long freed_pages;
+
+	if (!i915_gem_shrinker_lock_uninterruptible(dev_priv, &slu, 5000))
+		return NOTIFY_DONE;
+
+	freed_pages = i915_gem_shrink(dev_priv, -1UL,
+				      I915_SHRINK_BOUND |
+				      I915_SHRINK_UNBOUND |
+				      I915_SHRINK_ACTIVE |
+				      I915_SHRINK_VMAPS);
+
+	i915_gem_shrinker_unlock_uninterruptible(dev_priv, &slu);
+
+	*(unsigned long *)ptr += freed_pages;
+	return NOTIFY_DONE;
+}
+
 /**
  * i915_gem_shrinker_init - Initialize i915 shrinker
  * @dev_priv: i915 device
@@ -371,6 +418,9 @@ void i915_gem_shrinker_init(struct drm_i
 
 	dev_priv->mm.oom_notifier.notifier_call = i915_gem_shrinker_oom;
 	WARN_ON(register_oom_notifier(&dev_priv->mm.oom_notifier));
+
+	dev_priv->mm.vmap_notifier.notifier_call = i915_gem_shrinker_vmap;
+	WARN_ON(register_vmap_purge_notifier(&dev_priv->mm.vmap_notifier));
 }
 
 /**
@@ -381,6 +431,7 @@ void i915_gem_shrinker_init(struct drm_i
  */
 void i915_gem_shrinker_cleanup(struct drm_i915_private *dev_priv)
 {
+	WARN_ON(unregister_vmap_purge_notifier(&dev_priv->mm.vmap_notifier));
 	WARN_ON(unregister_oom_notifier(&dev_priv->mm.oom_notifier));
 	unregister_shrinker(&dev_priv->mm.shrinker);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_gem_stolen.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_gem_stolen.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_gem_stolen.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_gem_stolen.c	2016-07-24 15:23:50.000000000 -0400
@@ -55,8 +55,10 @@ int i915_gem_stolen_insert_node_in_range
 		return -ENODEV;
 
 	/* See the comment at the drm_mm_init() call for more about this check.
-	 * WaSkipStolenMemoryFirstPage:bdw,chv (incomplete) */
-	if (INTEL_INFO(dev_priv)->gen == 8 && start < 4096)
+	 * WaSkipStolenMemoryFirstPage:bdw,chv,kbl (incomplete)
+	 */
+	if (start < 4096 && (IS_GEN8(dev_priv) ||
+			     IS_KBL_REVID(dev_priv, 0, KBL_REVID_A0)))
 		start = 4096;
 
 	mutex_lock(&dev_priv->mm.stolen_lock);
@@ -72,9 +74,11 @@ int i915_gem_stolen_insert_node(struct d
 				struct drm_mm_node *node, u64 size,
 				unsigned alignment)
 {
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
+
 	return i915_gem_stolen_insert_node_in_range(dev_priv, node, size,
-					alignment, 0,
-					dev_priv->gtt.stolen_usable_size);
+						    alignment, 0,
+						    ggtt->stolen_usable_size);
 }
 
 void i915_gem_stolen_remove_node(struct drm_i915_private *dev_priv,
@@ -87,14 +91,15 @@ void i915_gem_stolen_remove_node(struct
 
 static unsigned long i915_stolen_to_physical(struct drm_device *dev)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	struct resource *r;
 	u32 base;
 
 	/* Almost universally we can find the Graphics Base of Stolen Memory
-	 * at offset 0x5c in the igfx configuration space. On a few (desktop)
-	 * machines this is also mirrored in the bridge device at different
-	 * locations, or in the MCHBAR.
+	 * at register BSM (0x5c) in the igfx configuration space. On a few
+	 * (desktop) machines this is also mirrored in the bridge device at
+	 * different locations, or in the MCHBAR.
 	 *
 	 * On 865 we just check the TOUD register.
 	 *
@@ -104,9 +109,11 @@ static unsigned long i915_stolen_to_phys
 	 */
 	base = 0;
 	if (INTEL_INFO(dev)->gen >= 3) {
-		/* Read Graphics Base of Stolen Memory directly */
-		pci_read_config_dword(dev->pdev, 0x5c, &base);
-		base &= ~((1<<20) - 1);
+		u32 bsm;
+
+		pci_read_config_dword(dev->pdev, BSM, &bsm);
+
+		base = bsm & BSM_MASK;
 	} else if (IS_I865G(dev)) {
 		u16 toud = 0;
 
@@ -134,7 +141,7 @@ static unsigned long i915_stolen_to_phys
 					 I85X_DRB3, &tmp);
 		tom = tmp * MB(32);
 
-		base = tom - tseg_size - dev_priv->gtt.stolen_size;
+		base = tom - tseg_size - ggtt->stolen_size;
 	} else if (IS_845G(dev)) {
 		u32 tseg_size = 0;
 		u32 tom;
@@ -158,7 +165,7 @@ static unsigned long i915_stolen_to_phys
 					 I830_DRB3, &tmp);
 		tom = tmp * MB(32);
 
-		base = tom - tseg_size - dev_priv->gtt.stolen_size;
+		base = tom - tseg_size - ggtt->stolen_size;
 	} else if (IS_I830(dev)) {
 		u32 tseg_size = 0;
 		u32 tom;
@@ -178,7 +185,7 @@ static unsigned long i915_stolen_to_phys
 					 I830_DRB3, &tmp);
 		tom = tmp * MB(32);
 
-		base = tom - tseg_size - dev_priv->gtt.stolen_size;
+		base = tom - tseg_size - ggtt->stolen_size;
 	}
 
 	if (base == 0)
@@ -189,41 +196,41 @@ static unsigned long i915_stolen_to_phys
 		struct {
 			u32 start, end;
 		} stolen[2] = {
-			{ .start = base, .end = base + dev_priv->gtt.stolen_size, },
-			{ .start = base, .end = base + dev_priv->gtt.stolen_size, },
+			{ .start = base, .end = base + ggtt->stolen_size, },
+			{ .start = base, .end = base + ggtt->stolen_size, },
 		};
-		u64 gtt_start, gtt_end;
+		u64 ggtt_start, ggtt_end;
 
-		gtt_start = I915_READ(PGTBL_CTL);
+		ggtt_start = I915_READ(PGTBL_CTL);
 		if (IS_GEN4(dev))
-			gtt_start = (gtt_start & PGTBL_ADDRESS_LO_MASK) |
-				(gtt_start & PGTBL_ADDRESS_HI_MASK) << 28;
+			ggtt_start = (ggtt_start & PGTBL_ADDRESS_LO_MASK) |
+				     (ggtt_start & PGTBL_ADDRESS_HI_MASK) << 28;
 		else
-			gtt_start &= PGTBL_ADDRESS_LO_MASK;
-		gtt_end = gtt_start + gtt_total_entries(dev_priv->gtt) * 4;
+			ggtt_start &= PGTBL_ADDRESS_LO_MASK;
+		ggtt_end = ggtt_start + ggtt_total_entries(ggtt) * 4;
 
-		if (gtt_start >= stolen[0].start && gtt_start < stolen[0].end)
-			stolen[0].end = gtt_start;
-		if (gtt_end > stolen[1].start && gtt_end <= stolen[1].end)
-			stolen[1].start = gtt_end;
+		if (ggtt_start >= stolen[0].start && ggtt_start < stolen[0].end)
+			stolen[0].end = ggtt_start;
+		if (ggtt_end > stolen[1].start && ggtt_end <= stolen[1].end)
+			stolen[1].start = ggtt_end;
 
 		/* pick the larger of the two chunks */
 		if (stolen[0].end - stolen[0].start >
 		    stolen[1].end - stolen[1].start) {
 			base = stolen[0].start;
-			dev_priv->gtt.stolen_size = stolen[0].end - stolen[0].start;
+			ggtt->stolen_size = stolen[0].end - stolen[0].start;
 		} else {
 			base = stolen[1].start;
-			dev_priv->gtt.stolen_size = stolen[1].end - stolen[1].start;
+			ggtt->stolen_size = stolen[1].end - stolen[1].start;
 		}
 
 		if (stolen[0].start != stolen[1].start ||
 		    stolen[0].end != stolen[1].end) {
 			DRM_DEBUG_KMS("GTT within stolen memory at 0x%llx-0x%llx\n",
-				      (unsigned long long) gtt_start,
-				      (unsigned long long) gtt_end - 1);
+				      (unsigned long long)ggtt_start,
+				      (unsigned long long)ggtt_end - 1);
 			DRM_DEBUG_KMS("Stolen memory adjusted to 0x%x-0x%x\n",
-				      base, base + (u32) dev_priv->gtt.stolen_size - 1);
+				      base, base + (u32)ggtt->stolen_size - 1);
 		}
 	}
 
@@ -233,7 +240,7 @@ static unsigned long i915_stolen_to_phys
 	 * kernel. So if the region is already marked as busy, something
 	 * is seriously wrong.
 	 */
-	r = devm_request_mem_region(dev->dev, base, dev_priv->gtt.stolen_size,
+	r = devm_request_mem_region(dev->dev, base, ggtt->stolen_size,
 				    "Graphics Stolen Memory");
 	if (r == NULL) {
 		/*
@@ -245,7 +252,7 @@ static unsigned long i915_stolen_to_phys
 		 * reservation starting from 1 instead of 0.
 		 */
 		r = devm_request_mem_region(dev->dev, base + 1,
-					    dev_priv->gtt.stolen_size - 1,
+					    ggtt->stolen_size - 1,
 					    "Graphics Stolen Memory");
 		/*
 		 * GEN3 firmware likes to smash pci bridges into the stolen
@@ -253,7 +260,7 @@ static unsigned long i915_stolen_to_phys
 		 */
 		if (r == NULL && !IS_GEN3(dev)) {
 			DRM_ERROR("conflict detected with stolen region: [0x%08x - 0x%08x]\n",
-				  base, base + (uint32_t)dev_priv->gtt.stolen_size);
+				  base, base + (uint32_t)ggtt->stolen_size);
 			base = 0;
 		}
 	}
@@ -274,11 +281,12 @@ void i915_gem_cleanup_stolen(struct drm_
 static void g4x_get_stolen_reserved(struct drm_i915_private *dev_priv,
 				    unsigned long *base, unsigned long *size)
 {
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	uint32_t reg_val = I915_READ(IS_GM45(dev_priv) ?
 				     CTG_STOLEN_RESERVED :
 				     ELK_STOLEN_RESERVED);
 	unsigned long stolen_top = dev_priv->mm.stolen_base +
-		dev_priv->gtt.stolen_size;
+				   ggtt->stolen_size;
 
 	*base = (reg_val & G4X_STOLEN_RESERVED_ADDR2_MASK) << 16;
 
@@ -369,10 +377,11 @@ static void gen8_get_stolen_reserved(str
 static void bdw_get_stolen_reserved(struct drm_i915_private *dev_priv,
 				    unsigned long *base, unsigned long *size)
 {
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	uint32_t reg_val = I915_READ(GEN6_STOLEN_RESERVED);
 	unsigned long stolen_top;
 
-	stolen_top = dev_priv->mm.stolen_base + dev_priv->gtt.stolen_size;
+	stolen_top = dev_priv->mm.stolen_base + ggtt->stolen_size;
 
 	*base = reg_val & GEN6_STOLEN_RESERVED_ADDR_MASK;
 
@@ -388,7 +397,8 @@ static void bdw_get_stolen_reserved(stru
 
 int i915_gem_init_stolen(struct drm_device *dev)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	unsigned long reserved_total, reserved_base = 0, reserved_size;
 	unsigned long stolen_top;
 
@@ -401,14 +411,14 @@ int i915_gem_init_stolen(struct drm_devi
 	}
 #endif
 
-	if (dev_priv->gtt.stolen_size == 0)
+	if (ggtt->stolen_size == 0)
 		return 0;
 
 	dev_priv->mm.stolen_base = i915_stolen_to_physical(dev);
 	if (dev_priv->mm.stolen_base == 0)
 		return 0;
 
-	stolen_top = dev_priv->mm.stolen_base + dev_priv->gtt.stolen_size;
+	stolen_top = dev_priv->mm.stolen_base + ggtt->stolen_size;
 
 	switch (INTEL_INFO(dev_priv)->gen) {
 	case 2:
@@ -458,19 +468,18 @@ int i915_gem_init_stolen(struct drm_devi
 		return 0;
 	}
 
-	dev_priv->gtt.stolen_reserved_base = reserved_base;
-	dev_priv->gtt.stolen_reserved_size = reserved_size;
+	ggtt->stolen_reserved_base = reserved_base;
+	ggtt->stolen_reserved_size = reserved_size;
 
 	/* It is possible for the reserved area to end before the end of stolen
 	 * memory, so just consider the start. */
 	reserved_total = stolen_top - reserved_base;
 
 	DRM_DEBUG_KMS("Memory reserved for graphics device: %zuK, usable: %luK\n",
-		      dev_priv->gtt.stolen_size >> 10,
-		      (dev_priv->gtt.stolen_size - reserved_total) >> 10);
+		      ggtt->stolen_size >> 10,
+		      (ggtt->stolen_size - reserved_total) >> 10);
 
-	dev_priv->gtt.stolen_usable_size = dev_priv->gtt.stolen_size -
-					   reserved_total;
+	ggtt->stolen_usable_size = ggtt->stolen_size - reserved_total;
 
 	/*
 	 * Basic memrange allocator for stolen space.
@@ -483,7 +492,7 @@ int i915_gem_init_stolen(struct drm_devi
 	 * i915_gem_stolen_insert_node_in_range(). We may want to fix the fbcon
 	 * problem later.
 	 */
-	drm_mm_init(&dev_priv->mm.stolen, 0, dev_priv->gtt.stolen_usable_size);
+	drm_mm_init(&dev_priv->mm.stolen, 0, ggtt->stolen_usable_size);
 
 	return 0;
 }
@@ -492,12 +501,13 @@ static struct sg_table *
 i915_pages_create_for_stolen(struct drm_device *dev,
 			     u32 offset, u32 size)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	struct sg_table *st;
 	struct scatterlist *sg;
 
 	DRM_DEBUG_DRIVER("offset=0x%x, size=%d\n", offset, size);
-	BUG_ON(offset > dev_priv->gtt.stolen_size - size);
+	BUG_ON(offset > ggtt->stolen_size - size);
 
 	/* We hide that we have no struct page backing our stolen object
 	 * by wrapping the contiguous physical allocation with a fake
@@ -628,8 +638,8 @@ i915_gem_object_create_stolen_for_preall
 					       u32 gtt_offset,
 					       u32 size)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct i915_address_space *ggtt = &dev_priv->gtt.base;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	struct drm_i915_gem_object *obj;
 	struct drm_mm_node *stolen;
 	struct i915_vma *vma;
@@ -675,7 +685,7 @@ i915_gem_object_create_stolen_for_preall
 	if (gtt_offset == I915_GTT_OFFSET_NONE)
 		return obj;
 
-	vma = i915_gem_obj_lookup_or_create_vma(obj, ggtt);
+	vma = i915_gem_obj_lookup_or_create_vma(obj, &ggtt->base);
 	if (IS_ERR(vma)) {
 		ret = PTR_ERR(vma);
 		goto err;
@@ -688,8 +698,8 @@ i915_gem_object_create_stolen_for_preall
 	 */
 	vma->node.start = gtt_offset;
 	vma->node.size = size;
-	if (drm_mm_initialized(&ggtt->mm)) {
-		ret = drm_mm_reserve_node(&ggtt->mm, &vma->node);
+	if (drm_mm_initialized(&ggtt->base.mm)) {
+		ret = drm_mm_reserve_node(&ggtt->base.mm, &vma->node);
 		if (ret) {
 			DRM_DEBUG_KMS("failed to allocate stolen GTT space\n");
 			goto err;
@@ -697,7 +707,7 @@ i915_gem_object_create_stolen_for_preall
 
 		vma->bound |= GLOBAL_BIND;
 		__i915_vma_set_map_and_fenceable(vma);
-		list_add_tail(&vma->vm_link, &ggtt->inactive_list);
+		list_add_tail(&vma->vm_link, &ggtt->base.inactive_list);
 	}
 
 	list_add_tail(&obj->global_list, &dev_priv->mm.bound_list);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_gem_tiling.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_gem_tiling.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_gem_tiling.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_gem_tiling.c	2016-07-24 15:23:50.000000000 -0400
@@ -166,7 +166,7 @@ i915_gem_set_tiling(struct drm_device *d
 	struct drm_i915_gem_object *obj;
 	int ret = 0;
 
-	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
+	obj = to_intel_bo(drm_gem_object_lookup(file, args->handle));
 	if (&obj->base == NULL)
 		return -ENOENT;
 
@@ -297,7 +297,7 @@ i915_gem_get_tiling(struct drm_device *d
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_gem_object *obj;
 
-	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
+	obj = to_intel_bo(drm_gem_object_lookup(file, args->handle));
 	if (&obj->base == NULL)
 		return -ENOENT;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_gem_userptr.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_gem_userptr.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_gem_userptr.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_gem_userptr.c	2016-07-24 15:23:50.000000000 -0400
@@ -34,7 +34,7 @@
 
 struct i915_mm_struct {
 	struct mm_struct *mm;
-	struct drm_device *dev;
+	struct drm_i915_private *i915;
 	struct i915_mmu_notifier *mn;
 	struct hlist_node node;
 	struct kref kref;
@@ -49,6 +49,7 @@ struct i915_mmu_notifier {
 	struct hlist_node node;
 	struct mmu_notifier mn;
 	struct rb_root objects;
+	struct workqueue_struct *wq;
 };
 
 struct i915_mmu_object {
@@ -60,6 +61,37 @@ struct i915_mmu_object {
 	bool attached;
 };
 
+static void wait_rendering(struct drm_i915_gem_object *obj)
+{
+	struct drm_device *dev = obj->base.dev;
+	struct drm_i915_gem_request *requests[I915_NUM_ENGINES];
+	int i, n;
+
+	if (!obj->active)
+		return;
+
+	n = 0;
+	for (i = 0; i < I915_NUM_ENGINES; i++) {
+		struct drm_i915_gem_request *req;
+
+		req = obj->last_read_req[i];
+		if (req == NULL)
+			continue;
+
+		requests[n++] = i915_gem_request_reference(req);
+	}
+
+	mutex_unlock(&dev->struct_mutex);
+
+	for (i = 0; i < n; i++)
+		__i915_wait_request(requests[i], false, NULL, NULL);
+
+	mutex_lock(&dev->struct_mutex);
+
+	for (i = 0; i < n; i++)
+		i915_gem_request_unreference(requests[i]);
+}
+
 static void cancel_userptr(struct work_struct *work)
 {
 	struct i915_mmu_object *mo = container_of(work, typeof(*mo), work);
@@ -75,13 +107,13 @@ static void cancel_userptr(struct work_s
 		struct i915_vma *vma, *tmp;
 		bool was_interruptible;
 
+		wait_rendering(obj);
+
 		was_interruptible = dev_priv->mm.interruptible;
 		dev_priv->mm.interruptible = false;
 
-		list_for_each_entry_safe(vma, tmp, &obj->vma_list, obj_link) {
-			int ret = i915_vma_unbind(vma);
-			WARN_ON(ret && ret != -EIO);
-		}
+		list_for_each_entry_safe(vma, tmp, &obj->vma_list, obj_link)
+			WARN_ON(i915_vma_unbind(vma));
 		WARN_ON(i915_gem_object_put_pages(obj));
 
 		dev_priv->mm.interruptible = was_interruptible;
@@ -140,7 +172,7 @@ static void i915_gem_userptr_mn_invalida
 		 */
 		mo = container_of(it, struct i915_mmu_object, it);
 		if (kref_get_unless_zero(&mo->obj->base.refcount))
-			schedule_work(&mo->work);
+			queue_work(mn->wq, &mo->work);
 
 		list_add(&mo->link, &cancelled);
 		it = interval_tree_iter_next(it, start, end);
@@ -148,6 +180,8 @@ static void i915_gem_userptr_mn_invalida
 	list_for_each_entry(mo, &cancelled, link)
 		del_object(mo);
 	spin_unlock(&mn->lock);
+
+	flush_workqueue(mn->wq);
 }
 
 static const struct mmu_notifier_ops i915_gem_userptr_notifier = {
@@ -167,10 +201,16 @@ i915_mmu_notifier_create(struct mm_struc
 	spin_lock_init(&mn->lock);
 	mn->mn.ops = &i915_gem_userptr_notifier;
 	mn->objects = RB_ROOT;
+	mn->wq = alloc_workqueue("i915-userptr-release", WQ_UNBOUND, 0);
+	if (mn->wq == NULL) {
+		kfree(mn);
+		return ERR_PTR(-ENOMEM);
+	}
 
 	 /* Protected by mmap_sem (write-lock) */
 	ret = __mmu_notifier_register(&mn->mn, mm);
 	if (ret) {
+		destroy_workqueue(mn->wq);
 		kfree(mn);
 		return ERR_PTR(ret);
 	}
@@ -205,13 +245,13 @@ i915_mmu_notifier_find(struct i915_mm_st
 		return mn;
 
 	down_write(&mm->mm->mmap_sem);
-	mutex_lock(&to_i915(mm->dev)->mm_lock);
+	mutex_lock(&mm->i915->mm_lock);
 	if ((mn = mm->mn) == NULL) {
 		mn = i915_mmu_notifier_create(mm->mm);
 		if (!IS_ERR(mn))
 			mm->mn = mn;
 	}
-	mutex_unlock(&to_i915(mm->dev)->mm_lock);
+	mutex_unlock(&mm->i915->mm_lock);
 	up_write(&mm->mm->mmap_sem);
 
 	return mn;
@@ -256,6 +296,7 @@ i915_mmu_notifier_free(struct i915_mmu_n
 		return;
 
 	mmu_notifier_unregister(&mn->mn, mm);
+	destroy_workqueue(mn->wq);
 	kfree(mn);
 }
 
@@ -327,7 +368,7 @@ i915_gem_userptr_init__mm_struct(struct
 		}
 
 		kref_init(&mm->kref);
-		mm->dev = obj->base.dev;
+		mm->i915 = to_i915(obj->base.dev);
 
 		mm->mm = current->mm;
 		atomic_inc(&current->mm->mm_count);
@@ -362,7 +403,7 @@ __i915_mm_struct_free(struct kref *kref)
 
 	/* Protected by dev_priv->mm_lock */
 	hash_del(&mm->node);
-	mutex_unlock(&to_i915(mm->dev)->mm_lock);
+	mutex_unlock(&mm->i915->mm_lock);
 
 	INIT_WORK(&mm->work, __i915_mm_struct_free__worker);
 	schedule_work(&mm->work);
@@ -494,10 +535,7 @@ __i915_gem_userptr_get_pages_worker(stru
 	ret = -ENOMEM;
 	pinned = 0;
 
-	pvec = kmalloc(npages*sizeof(struct page *),
-		       GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY);
-	if (pvec == NULL)
-		pvec = drm_malloc_ab(npages, sizeof(struct page *));
+	pvec = drm_malloc_gfp(npages, sizeof(struct page *), GFP_TEMPORARY);
 	if (pvec != NULL) {
 		struct mm_struct *mm = obj->userptr.mm->mm;
 
@@ -639,14 +677,11 @@ i915_gem_userptr_get_pages(struct drm_i9
 	pvec = NULL;
 	pinned = 0;
 	if (obj->userptr.mm->mm == current->mm) {
-		pvec = kmalloc(num_pages*sizeof(struct page *),
-			       GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY);
+		pvec = drm_malloc_gfp(num_pages, sizeof(struct page *),
+				      GFP_TEMPORARY);
 		if (pvec == NULL) {
-			pvec = drm_malloc_ab(num_pages, sizeof(struct page *));
-			if (pvec == NULL) {
-				__i915_gem_userptr_set_active(obj, false);
-				return -ENOMEM;
-			}
+			__i915_gem_userptr_set_active(obj, false);
+			return -ENOMEM;
 		}
 
 		pinned = __get_user_pages_fast(obj->userptr.ptr, num_pages,
@@ -763,6 +798,13 @@ i915_gem_userptr_ioctl(struct drm_device
 	int ret;
 	u32 handle;
 
+	if (!HAS_LLC(dev) && !HAS_SNOOP(dev)) {
+		/* We cannot support coherent userptr objects on hw without
+		 * LLC and broken snooping.
+		 */
+		return -ENODEV;
+	}
+
 	if (args->flags & ~(I915_USERPTR_READ_ONLY |
 			    I915_USERPTR_UNSYNCHRONIZED))
 		return -EINVAL;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_gpu_error.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_gpu_error.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_gpu_error.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_gpu_error.c	2016-07-24 15:23:50.000000000 -0400
@@ -198,7 +198,7 @@ static void print_error_buffers(struct d
 			   err->size,
 			   err->read_domains,
 			   err->write_domain);
-		for (i = 0; i < I915_NUM_RINGS; i++)
+		for (i = 0; i < I915_NUM_ENGINES; i++)
 			err_printf(m, "%02x ", err->rseqno[i]);
 
 		err_printf(m, "] %02x", err->wseqno);
@@ -230,8 +230,6 @@ static const char *hangcheck_action_to_s
 		return "wait";
 	case HANGCHECK_ACTIVE:
 		return "active";
-	case HANGCHECK_ACTIVE_LOOP:
-		return "active (loop)";
 	case HANGCHECK_KICK:
 		return "kick";
 	case HANGCHECK_HUNG:
@@ -298,6 +296,7 @@ static void i915_ring_error_state(struct
 		}
 	}
 	err_printf(m, "  seqno: 0x%08x\n", ring->seqno);
+	err_printf(m, "  last_seqno: 0x%08x\n", ring->last_seqno);
 	err_printf(m, "  waiting: %s\n", yesno(ring->waiting));
 	err_printf(m, "  ring->head: 0x%08x\n", ring->cpu_ring_head);
 	err_printf(m, "  ring->tail: 0x%08x\n", ring->cpu_ring_tail);
@@ -433,7 +432,7 @@ int i915_error_state_to_str(struct drm_i
 	for (i = 0; i < ARRAY_SIZE(error->ring); i++) {
 		obj = error->ring[i].batchbuffer;
 		if (obj) {
-			err_puts(m, dev_priv->ring[i].name);
+			err_puts(m, dev_priv->engine[i].name);
 			if (error->ring[i].pid != -1)
 				err_printf(m, " (submitted by %s [%d])",
 					   error->ring[i].comm,
@@ -447,14 +446,14 @@ int i915_error_state_to_str(struct drm_i
 		obj = error->ring[i].wa_batchbuffer;
 		if (obj) {
 			err_printf(m, "%s (w/a) --- gtt_offset = 0x%08x\n",
-				   dev_priv->ring[i].name,
+				   dev_priv->engine[i].name,
 				   lower_32_bits(obj->gtt_offset));
 			print_error_obj(m, obj);
 		}
 
 		if (error->ring[i].num_requests) {
 			err_printf(m, "%s --- %d requests\n",
-				   dev_priv->ring[i].name,
+				   dev_priv->engine[i].name,
 				   error->ring[i].num_requests);
 			for (j = 0; j < error->ring[i].num_requests; j++) {
 				err_printf(m, "  seqno 0x%08x, emitted %ld, tail 0x%08x\n",
@@ -466,7 +465,7 @@ int i915_error_state_to_str(struct drm_i
 
 		if ((obj = error->ring[i].ringbuffer)) {
 			err_printf(m, "%s --- ringbuffer = 0x%08x\n",
-				   dev_priv->ring[i].name,
+				   dev_priv->engine[i].name,
 				   lower_32_bits(obj->gtt_offset));
 			print_error_obj(m, obj);
 		}
@@ -480,7 +479,7 @@ int i915_error_state_to_str(struct drm_i
 				hws_page = &obj->pages[LRC_PPHWSP_PN][0];
 			}
 			err_printf(m, "%s --- HW Status = 0x%08llx\n",
-				   dev_priv->ring[i].name, hws_offset);
+				   dev_priv->engine[i].name, hws_offset);
 			offset = 0;
 			for (elt = 0; elt < PAGE_SIZE/16; elt += 4) {
 				err_printf(m, "[%04x] %08x %08x %08x %08x\n",
@@ -493,9 +492,31 @@ int i915_error_state_to_str(struct drm_i
 			}
 		}
 
+		obj = error->ring[i].wa_ctx;
+		if (obj) {
+			u64 wa_ctx_offset = obj->gtt_offset;
+			u32 *wa_ctx_page = &obj->pages[0][0];
+			struct intel_engine_cs *engine = &dev_priv->engine[RCS];
+			u32 wa_ctx_size = (engine->wa_ctx.indirect_ctx.size +
+					   engine->wa_ctx.per_ctx.size);
+
+			err_printf(m, "%s --- WA ctx batch buffer = 0x%08llx\n",
+				   dev_priv->engine[i].name, wa_ctx_offset);
+			offset = 0;
+			for (elt = 0; elt < wa_ctx_size; elt += 4) {
+				err_printf(m, "[%04x] %08x %08x %08x %08x\n",
+					   offset,
+					   wa_ctx_page[elt + 0],
+					   wa_ctx_page[elt + 1],
+					   wa_ctx_page[elt + 2],
+					   wa_ctx_page[elt + 3]);
+				offset += 16;
+			}
+		}
+
 		if ((obj = error->ring[i].ctx)) {
 			err_printf(m, "%s --- HW Context = 0x%08x\n",
-				   dev_priv->ring[i].name,
+				   dev_priv->engine[i].name,
 				   lower_32_bits(obj->gtt_offset));
 			print_error_obj(m, obj);
 		}
@@ -585,6 +606,7 @@ static void i915_error_state_free(struct
 		i915_error_object_free(error->ring[i].hws_page);
 		i915_error_object_free(error->ring[i].ctx);
 		kfree(error->ring[i].requests);
+		i915_error_object_free(error->ring[i].wa_ctx);
 	}
 
 	i915_error_object_free(error->semaphore_obj);
@@ -606,6 +628,7 @@ i915_error_object_create(struct drm_i915
 			 struct drm_i915_gem_object *src,
 			 struct i915_address_space *vm)
 {
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	struct drm_i915_error_object *dst;
 	struct i915_vma *vma = NULL;
 	int num_pages;
@@ -632,7 +655,7 @@ i915_error_object_create(struct drm_i915
 		vma = i915_gem_obj_to_ggtt(src);
 	use_ggtt = (src->cache_level == I915_CACHE_NONE &&
 		   vma && (vma->bound & GLOBAL_BIND) &&
-		   reloc_offset + num_pages * PAGE_SIZE <= dev_priv->gtt.mappable_end);
+		   reloc_offset + num_pages * PAGE_SIZE <= ggtt->mappable_end);
 
 	/* Cannot access stolen address directly, try to use the aperture */
 	if (src->stolen) {
@@ -642,12 +665,13 @@ i915_error_object_create(struct drm_i915
 			goto unwind;
 
 		reloc_offset = i915_gem_obj_ggtt_offset(src);
-		if (reloc_offset + num_pages * PAGE_SIZE > dev_priv->gtt.mappable_end)
+		if (reloc_offset + num_pages * PAGE_SIZE > ggtt->mappable_end)
 			goto unwind;
 	}
 
 	/* Cannot access snooped pages through the aperture */
-	if (use_ggtt && src->cache_level != I915_CACHE_NONE && !HAS_LLC(dev_priv->dev))
+	if (use_ggtt && src->cache_level != I915_CACHE_NONE &&
+	    !HAS_LLC(dev_priv))
 		goto unwind;
 
 	dst->page_count = num_pages;
@@ -668,7 +692,7 @@ i915_error_object_create(struct drm_i915
 			 * captures what the GPU read.
 			 */
 
-			s = io_mapping_map_atomic_wc(dev_priv->gtt.mappable,
+			s = io_mapping_map_atomic_wc(ggtt->mappable,
 						     reloc_offset);
 			memcpy_fromio(d, s, PAGE_SIZE);
 			io_mapping_unmap_atomic(s);
@@ -701,7 +725,7 @@ unwind:
 	return NULL;
 }
 #define i915_error_ggtt_object_create(dev_priv, src) \
-	i915_error_object_create((dev_priv), (src), &(dev_priv)->gtt.base)
+	i915_error_object_create((dev_priv), (src), &(dev_priv)->ggtt.base)
 
 static void capture_bo(struct drm_i915_error_buffer *err,
 		       struct i915_vma *vma)
@@ -711,7 +735,7 @@ static void capture_bo(struct drm_i915_e
 
 	err->size = obj->base.size;
 	err->name = obj->base.name;
-	for (i = 0; i < I915_NUM_RINGS; i++)
+	for (i = 0; i < I915_NUM_ENGINES; i++)
 		err->rseqno[i] = i915_gem_request_get_seqno(obj->last_read_req[i]);
 	err->wseqno = i915_gem_request_get_seqno(obj->last_write_req);
 	err->gtt_offset = vma->node.start;
@@ -726,7 +750,7 @@ static void capture_bo(struct drm_i915_e
 	err->purgeable = obj->madv != I915_MADV_WILLNEED;
 	err->userptr = obj->userptr.mm != NULL;
 	err->ring = obj->last_write_req ?
-			i915_gem_request_get_ring(obj->last_write_req)->id : -1;
+			i915_gem_request_get_engine(obj->last_write_req)->id : -1;
 	err->cache_level = obj->cache_level;
 }
 
@@ -788,7 +812,7 @@ static uint32_t i915_error_generate_code
 	 * synchronization commands which almost always appear in the case
 	 * strictly a client bug. Use instdone to differentiate those some.
 	 */
-	for (i = 0; i < I915_NUM_RINGS; i++) {
+	for (i = 0; i < I915_NUM_ENGINES; i++) {
 		if (error->ring[i].hangcheck_action == HANGCHECK_HUNG) {
 			if (ring_id)
 				*ring_id = i;
@@ -821,11 +845,11 @@ static void i915_gem_record_fences(struc
 
 static void gen8_record_semaphore_state(struct drm_i915_private *dev_priv,
 					struct drm_i915_error_state *error,
-					struct intel_engine_cs *ring,
+					struct intel_engine_cs *engine,
 					struct drm_i915_error_ring *ering)
 {
 	struct intel_engine_cs *to;
-	int i;
+	enum intel_engine_id id;
 
 	if (!i915_semaphore_is_enabled(dev_priv->dev))
 		return;
@@ -835,68 +859,69 @@ static void gen8_record_semaphore_state(
 			i915_error_ggtt_object_create(dev_priv,
 						      dev_priv->semaphore_obj);
 
-	for_each_ring(to, dev_priv, i) {
+	for_each_engine_id(to, dev_priv, id) {
 		int idx;
 		u16 signal_offset;
 		u32 *tmp;
 
-		if (ring == to)
+		if (engine == to)
 			continue;
 
-		signal_offset = (GEN8_SIGNAL_OFFSET(ring, i) & (PAGE_SIZE - 1))
+		signal_offset = (GEN8_SIGNAL_OFFSET(engine, id) & (PAGE_SIZE - 1))
 				/ 4;
 		tmp = error->semaphore_obj->pages[0];
-		idx = intel_ring_sync_index(ring, to);
+		idx = intel_ring_sync_index(engine, to);
 
 		ering->semaphore_mboxes[idx] = tmp[signal_offset];
-		ering->semaphore_seqno[idx] = ring->semaphore.sync_seqno[idx];
+		ering->semaphore_seqno[idx] = engine->semaphore.sync_seqno[idx];
 	}
 }
 
 static void gen6_record_semaphore_state(struct drm_i915_private *dev_priv,
-					struct intel_engine_cs *ring,
+					struct intel_engine_cs *engine,
 					struct drm_i915_error_ring *ering)
 {
-	ering->semaphore_mboxes[0] = I915_READ(RING_SYNC_0(ring->mmio_base));
-	ering->semaphore_mboxes[1] = I915_READ(RING_SYNC_1(ring->mmio_base));
-	ering->semaphore_seqno[0] = ring->semaphore.sync_seqno[0];
-	ering->semaphore_seqno[1] = ring->semaphore.sync_seqno[1];
+	ering->semaphore_mboxes[0] = I915_READ(RING_SYNC_0(engine->mmio_base));
+	ering->semaphore_mboxes[1] = I915_READ(RING_SYNC_1(engine->mmio_base));
+	ering->semaphore_seqno[0] = engine->semaphore.sync_seqno[0];
+	ering->semaphore_seqno[1] = engine->semaphore.sync_seqno[1];
 
-	if (HAS_VEBOX(dev_priv->dev)) {
+	if (HAS_VEBOX(dev_priv)) {
 		ering->semaphore_mboxes[2] =
-			I915_READ(RING_SYNC_2(ring->mmio_base));
-		ering->semaphore_seqno[2] = ring->semaphore.sync_seqno[2];
+			I915_READ(RING_SYNC_2(engine->mmio_base));
+		ering->semaphore_seqno[2] = engine->semaphore.sync_seqno[2];
 	}
 }
 
 static void i915_record_ring_state(struct drm_device *dev,
 				   struct drm_i915_error_state *error,
-				   struct intel_engine_cs *ring,
+				   struct intel_engine_cs *engine,
 				   struct drm_i915_error_ring *ering)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	if (INTEL_INFO(dev)->gen >= 6) {
-		ering->rc_psmi = I915_READ(RING_PSMI_CTL(ring->mmio_base));
-		ering->fault_reg = I915_READ(RING_FAULT_REG(ring));
+		ering->rc_psmi = I915_READ(RING_PSMI_CTL(engine->mmio_base));
+		ering->fault_reg = I915_READ(RING_FAULT_REG(engine));
 		if (INTEL_INFO(dev)->gen >= 8)
-			gen8_record_semaphore_state(dev_priv, error, ring, ering);
+			gen8_record_semaphore_state(dev_priv, error, engine,
+						    ering);
 		else
-			gen6_record_semaphore_state(dev_priv, ring, ering);
+			gen6_record_semaphore_state(dev_priv, engine, ering);
 	}
 
 	if (INTEL_INFO(dev)->gen >= 4) {
-		ering->faddr = I915_READ(RING_DMA_FADD(ring->mmio_base));
-		ering->ipeir = I915_READ(RING_IPEIR(ring->mmio_base));
-		ering->ipehr = I915_READ(RING_IPEHR(ring->mmio_base));
-		ering->instdone = I915_READ(RING_INSTDONE(ring->mmio_base));
-		ering->instps = I915_READ(RING_INSTPS(ring->mmio_base));
-		ering->bbaddr = I915_READ(RING_BBADDR(ring->mmio_base));
+		ering->faddr = I915_READ(RING_DMA_FADD(engine->mmio_base));
+		ering->ipeir = I915_READ(RING_IPEIR(engine->mmio_base));
+		ering->ipehr = I915_READ(RING_IPEHR(engine->mmio_base));
+		ering->instdone = I915_READ(RING_INSTDONE(engine->mmio_base));
+		ering->instps = I915_READ(RING_INSTPS(engine->mmio_base));
+		ering->bbaddr = I915_READ(RING_BBADDR(engine->mmio_base));
 		if (INTEL_INFO(dev)->gen >= 8) {
-			ering->faddr |= (u64) I915_READ(RING_DMA_FADD_UDW(ring->mmio_base)) << 32;
-			ering->bbaddr |= (u64) I915_READ(RING_BBADDR_UDW(ring->mmio_base)) << 32;
+			ering->faddr |= (u64) I915_READ(RING_DMA_FADD_UDW(engine->mmio_base)) << 32;
+			ering->bbaddr |= (u64) I915_READ(RING_BBADDR_UDW(engine->mmio_base)) << 32;
 		}
-		ering->bbstate = I915_READ(RING_BBSTATE(ring->mmio_base));
+		ering->bbstate = I915_READ(RING_BBSTATE(engine->mmio_base));
 	} else {
 		ering->faddr = I915_READ(DMA_FADD_I8XX);
 		ering->ipeir = I915_READ(IPEIR);
@@ -904,20 +929,21 @@ static void i915_record_ring_state(struc
 		ering->instdone = I915_READ(GEN2_INSTDONE);
 	}
 
-	ering->waiting = waitqueue_active(&ring->irq_queue);
-	ering->instpm = I915_READ(RING_INSTPM(ring->mmio_base));
-	ering->seqno = ring->get_seqno(ring, false);
-	ering->acthd = intel_ring_get_active_head(ring);
-	ering->start = I915_READ_START(ring);
-	ering->head = I915_READ_HEAD(ring);
-	ering->tail = I915_READ_TAIL(ring);
-	ering->ctl = I915_READ_CTL(ring);
+	ering->waiting = waitqueue_active(&engine->irq_queue);
+	ering->instpm = I915_READ(RING_INSTPM(engine->mmio_base));
+	ering->acthd = intel_ring_get_active_head(engine);
+	ering->seqno = engine->get_seqno(engine);
+	ering->last_seqno = engine->last_submitted_seqno;
+	ering->start = I915_READ_START(engine);
+	ering->head = I915_READ_HEAD(engine);
+	ering->tail = I915_READ_TAIL(engine);
+	ering->ctl = I915_READ_CTL(engine);
 
 	if (I915_NEED_GFX_HWS(dev)) {
 		i915_reg_t mmio;
 
 		if (IS_GEN7(dev)) {
-			switch (ring->id) {
+			switch (engine->id) {
 			default:
 			case RCS:
 				mmio = RENDER_HWS_PGA_GEN7;
@@ -932,51 +958,51 @@ static void i915_record_ring_state(struc
 				mmio = VEBOX_HWS_PGA_GEN7;
 				break;
 			}
-		} else if (IS_GEN6(ring->dev)) {
-			mmio = RING_HWS_PGA_GEN6(ring->mmio_base);
+		} else if (IS_GEN6(engine->dev)) {
+			mmio = RING_HWS_PGA_GEN6(engine->mmio_base);
 		} else {
 			/* XXX: gen8 returns to sanity */
-			mmio = RING_HWS_PGA(ring->mmio_base);
+			mmio = RING_HWS_PGA(engine->mmio_base);
 		}
 
 		ering->hws = I915_READ(mmio);
 	}
 
-	ering->hangcheck_score = ring->hangcheck.score;
-	ering->hangcheck_action = ring->hangcheck.action;
+	ering->hangcheck_score = engine->hangcheck.score;
+	ering->hangcheck_action = engine->hangcheck.action;
 
 	if (USES_PPGTT(dev)) {
 		int i;
 
-		ering->vm_info.gfx_mode = I915_READ(RING_MODE_GEN7(ring));
+		ering->vm_info.gfx_mode = I915_READ(RING_MODE_GEN7(engine));
 
 		if (IS_GEN6(dev))
 			ering->vm_info.pp_dir_base =
-				I915_READ(RING_PP_DIR_BASE_READ(ring));
+				I915_READ(RING_PP_DIR_BASE_READ(engine));
 		else if (IS_GEN7(dev))
 			ering->vm_info.pp_dir_base =
-				I915_READ(RING_PP_DIR_BASE(ring));
+				I915_READ(RING_PP_DIR_BASE(engine));
 		else if (INTEL_INFO(dev)->gen >= 8)
 			for (i = 0; i < 4; i++) {
 				ering->vm_info.pdp[i] =
-					I915_READ(GEN8_RING_PDP_UDW(ring, i));
+					I915_READ(GEN8_RING_PDP_UDW(engine, i));
 				ering->vm_info.pdp[i] <<= 32;
 				ering->vm_info.pdp[i] |=
-					I915_READ(GEN8_RING_PDP_LDW(ring, i));
+					I915_READ(GEN8_RING_PDP_LDW(engine, i));
 			}
 	}
 }
 
 
-static void i915_gem_record_active_context(struct intel_engine_cs *ring,
+static void i915_gem_record_active_context(struct intel_engine_cs *engine,
 					   struct drm_i915_error_state *error,
 					   struct drm_i915_error_ring *ering)
 {
-	struct drm_i915_private *dev_priv = ring->dev->dev_private;
+	struct drm_i915_private *dev_priv = engine->dev->dev_private;
 	struct drm_i915_gem_object *obj;
 
 	/* Currently render ring is the only HW context user */
-	if (ring->id != RCS || !error->ccid)
+	if (engine->id != RCS || !error->ccid)
 		return;
 
 	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
@@ -993,30 +1019,31 @@ static void i915_gem_record_active_conte
 static void i915_gem_record_rings(struct drm_device *dev,
 				  struct drm_i915_error_state *error)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	struct drm_i915_gem_request *request;
 	int i, count;
 
-	for (i = 0; i < I915_NUM_RINGS; i++) {
-		struct intel_engine_cs *ring = &dev_priv->ring[i];
+	for (i = 0; i < I915_NUM_ENGINES; i++) {
+		struct intel_engine_cs *engine = &dev_priv->engine[i];
 		struct intel_ringbuffer *rbuf;
 
 		error->ring[i].pid = -1;
 
-		if (ring->dev == NULL)
+		if (engine->dev == NULL)
 			continue;
 
 		error->ring[i].valid = true;
 
-		i915_record_ring_state(dev, error, ring, &error->ring[i]);
+		i915_record_ring_state(dev, error, engine, &error->ring[i]);
 
-		request = i915_gem_find_active_request(ring);
+		request = i915_gem_find_active_request(engine);
 		if (request) {
 			struct i915_address_space *vm;
 
 			vm = request->ctx && request->ctx->ppgtt ?
 				&request->ctx->ppgtt->base :
-				&dev_priv->gtt.base;
+				&ggtt->base;
 
 			/* We need to copy these to an anonymous buffer
 			 * as the simplest method to avoid being overwritten
@@ -1027,10 +1054,10 @@ static void i915_gem_record_rings(struct
 							 request->batch_obj,
 							 vm);
 
-			if (HAS_BROKEN_CS_TLB(dev_priv->dev))
+			if (HAS_BROKEN_CS_TLB(dev_priv))
 				error->ring[i].wa_batchbuffer =
 					i915_error_ggtt_object_create(dev_priv,
-							     ring->scratch.obj);
+							     engine->scratch.obj);
 
 			if (request->pid) {
 				struct task_struct *task;
@@ -1052,11 +1079,11 @@ static void i915_gem_record_rings(struct
 			 * executed).
 			 */
 			if (request)
-				rbuf = request->ctx->engine[ring->id].ringbuf;
+				rbuf = request->ctx->engine[engine->id].ringbuf;
 			else
-				rbuf = dev_priv->kernel_context->engine[ring->id].ringbuf;
+				rbuf = dev_priv->kernel_context->engine[engine->id].ringbuf;
 		} else
-			rbuf = ring->buffer;
+			rbuf = engine->buffer;
 
 		error->ring[i].cpu_ring_head = rbuf->head;
 		error->ring[i].cpu_ring_tail = rbuf->tail;
@@ -1065,12 +1092,19 @@ static void i915_gem_record_rings(struct
 			i915_error_ggtt_object_create(dev_priv, rbuf->obj);
 
 		error->ring[i].hws_page =
-			i915_error_ggtt_object_create(dev_priv, ring->status_page.obj);
+			i915_error_ggtt_object_create(dev_priv,
+						      engine->status_page.obj);
 
-		i915_gem_record_active_context(ring, error, &error->ring[i]);
+		if (engine->wa_ctx.obj) {
+			error->ring[i].wa_ctx =
+				i915_error_ggtt_object_create(dev_priv,
+							      engine->wa_ctx.obj);
+		}
+
+		i915_gem_record_active_context(engine, error, &error->ring[i]);
 
 		count = 0;
-		list_for_each_entry(request, &ring->request_list, list)
+		list_for_each_entry(request, &engine->request_list, list)
 			count++;
 
 		error->ring[i].num_requests = count;
@@ -1083,7 +1117,7 @@ static void i915_gem_record_rings(struct
 		}
 
 		count = 0;
-		list_for_each_entry(request, &ring->request_list, list) {
+		list_for_each_entry(request, &engine->request_list, list) {
 			struct drm_i915_error_request *erq;
 
 			if (count >= error->ring[i].num_requests) {
@@ -1272,7 +1306,7 @@ static void i915_capture_reg_state(struc
 
 static void i915_error_capture_msg(struct drm_device *dev,
 				   struct drm_i915_error_state *error,
-				   bool wedged,
+				   u32 engine_mask,
 				   const char *error_msg)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1295,7 +1329,7 @@ static void i915_error_capture_msg(struc
 	scnprintf(error->error_msg + len, sizeof(error->error_msg) - len,
 		  ", reason: %s, action: %s",
 		  error_msg,
-		  wedged ? "reset" : "continue");
+		  engine_mask ? "reset" : "continue");
 }
 
 static void i915_capture_gen_state(struct drm_i915_private *dev_priv,
@@ -1318,7 +1352,7 @@ static void i915_capture_gen_state(struc
  * out a structure which becomes available in debugfs for user level tools
  * to pick up.
  */
-void i915_capture_error_state(struct drm_device *dev, bool wedged,
+void i915_capture_error_state(struct drm_device *dev, u32 engine_mask,
 			      const char *error_msg)
 {
 	static bool warned;
@@ -1346,7 +1380,7 @@ void i915_capture_error_state(struct drm
 	error->overlay = intel_overlay_capture_error_state(dev);
 	error->display = intel_display_capture_error_state(dev);
 
-	i915_error_capture_msg(dev, error, wedged, error_msg);
+	i915_error_capture_msg(dev, error, engine_mask, error_msg);
 	DRM_INFO("%s\n", error->error_msg);
 
 	spin_lock_irqsave(&dev_priv->gpu_error.lock, flags);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_guc_reg.h linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_guc_reg.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_guc_reg.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_guc_reg.h	2016-07-24 15:23:50.000000000 -0400
@@ -27,9 +27,12 @@
 /* Definitions of GuC H/W registers, bits, etc */
 
 #define GUC_STATUS			_MMIO(0xc000)
+#define   GS_RESET_SHIFT		0
+#define   GS_MIA_IN_RESET		  (0x01 << GS_RESET_SHIFT)
 #define   GS_BOOTROM_SHIFT		1
 #define   GS_BOOTROM_MASK		  (0x7F << GS_BOOTROM_SHIFT)
 #define   GS_BOOTROM_RSA_FAILED		  (0x50 << GS_BOOTROM_SHIFT)
+#define   GS_BOOTROM_JUMP_PASSED	  (0x76 << GS_BOOTROM_SHIFT)
 #define   GS_UKERNEL_SHIFT		8
 #define   GS_UKERNEL_MASK		  (0xFF << GS_UKERNEL_SHIFT)
 #define   GS_UKERNEL_LAPIC_DONE		  (0x30 << GS_UKERNEL_SHIFT)
@@ -37,7 +40,13 @@
 #define   GS_UKERNEL_READY		  (0xF0 << GS_UKERNEL_SHIFT)
 #define   GS_MIA_SHIFT			16
 #define   GS_MIA_MASK			  (0x07 << GS_MIA_SHIFT)
-#define   GS_MIA_CORE_STATE		  (1 << GS_MIA_SHIFT)
+#define   GS_MIA_CORE_STATE		  (0x01 << GS_MIA_SHIFT)
+#define   GS_MIA_HALT_REQUESTED		  (0x02 << GS_MIA_SHIFT)
+#define   GS_MIA_ISR_ENTRY		  (0x04 << GS_MIA_SHIFT)
+#define   GS_AUTH_STATUS_SHIFT		30
+#define   GS_AUTH_STATUS_MASK		  (0x03 << GS_AUTH_STATUS_SHIFT)
+#define   GS_AUTH_STATUS_BAD		  (0x01 << GS_AUTH_STATUS_SHIFT)
+#define   GS_AUTH_STATUS_GOOD		  (0x02 << GS_AUTH_STATUS_SHIFT)
 
 #define SOFT_SCRATCH(n)			_MMIO(0xc180 + (n) * 4)
 #define SOFT_SCRATCH_COUNT		16
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_guc_submission.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_guc_submission.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_guc_submission.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_guc_submission.c	2016-07-24 15:23:50.000000000 -0400
@@ -179,15 +179,11 @@ static void guc_init_doorbell(struct int
 			      struct i915_guc_client *client)
 {
 	struct guc_doorbell_info *doorbell;
-	void *base;
 
-	base = kmap_atomic(i915_gem_object_get_page(client->client_obj, 0));
-	doorbell = base + client->doorbell_offset;
+	doorbell = client->client_base + client->doorbell_offset;
 
-	doorbell->db_status = 1;
+	doorbell->db_status = GUC_DOORBELL_ENABLED;
 	doorbell->cookie = 0;
-
-	kunmap_atomic(base);
 }
 
 static int guc_ring_doorbell(struct i915_guc_client *gc)
@@ -195,11 +191,9 @@ static int guc_ring_doorbell(struct i915
 	struct guc_process_desc *desc;
 	union guc_doorbell_qw db_cmp, db_exc, db_ret;
 	union guc_doorbell_qw *db;
-	void *base;
 	int attempt = 2, ret = -EAGAIN;
 
-	base = kmap_atomic(i915_gem_object_get_page(gc->client_obj, 0));
-	desc = base + gc->proc_desc_offset;
+	desc = gc->client_base + gc->proc_desc_offset;
 
 	/* Update the tail so it is visible to GuC */
 	desc->tail = gc->wq_tail;
@@ -215,7 +209,7 @@ static int guc_ring_doorbell(struct i915
 		db_exc.cookie = 1;
 
 	/* pointer of current doorbell cacheline */
-	db = base + gc->doorbell_offset;
+	db = gc->client_base + gc->doorbell_offset;
 
 	while (attempt--) {
 		/* lets ring the doorbell */
@@ -244,10 +238,6 @@ static int guc_ring_doorbell(struct i915
 			db_exc.cookie = 1;
 	}
 
-	/* Finally, update the cached copy of the GuC's WQ head */
-	gc->wq_head = desc->head;
-
-	kunmap_atomic(base);
 	return ret;
 }
 
@@ -256,16 +246,12 @@ static void guc_disable_doorbell(struct
 {
 	struct drm_i915_private *dev_priv = guc_to_i915(guc);
 	struct guc_doorbell_info *doorbell;
-	void *base;
 	i915_reg_t drbreg = GEN8_DRBREGL(client->doorbell_id);
 	int value;
 
-	base = kmap_atomic(i915_gem_object_get_page(client->client_obj, 0));
-	doorbell = base + client->doorbell_offset;
-
-	doorbell->db_status = 0;
+	doorbell = client->client_base + client->doorbell_offset;
 
-	kunmap_atomic(base);
+	doorbell->db_status = GUC_DOORBELL_DISABLED;
 
 	I915_WRITE(drbreg, I915_READ(drbreg) & ~GEN8_DRB_VALID);
 
@@ -341,10 +327,8 @@ static void guc_init_proc_desc(struct in
 			       struct i915_guc_client *client)
 {
 	struct guc_process_desc *desc;
-	void *base;
 
-	base = kmap_atomic(i915_gem_object_get_page(client->client_obj, 0));
-	desc = base + client->proc_desc_offset;
+	desc = client->client_base + client->proc_desc_offset;
 
 	memset(desc, 0, sizeof(*desc));
 
@@ -361,8 +345,6 @@ static void guc_init_proc_desc(struct in
 	desc->wq_size_bytes = client->wq_size;
 	desc->wq_status = WQ_STATUS_ACTIVE;
 	desc->priority = client->priority;
-
-	kunmap_atomic(base);
 }
 
 /*
@@ -376,12 +358,14 @@ static void guc_init_proc_desc(struct in
 static void guc_init_ctx_desc(struct intel_guc *guc,
 			      struct i915_guc_client *client)
 {
+	struct drm_i915_gem_object *client_obj = client->client_obj;
 	struct drm_i915_private *dev_priv = guc_to_i915(guc);
-	struct intel_engine_cs *ring;
+	struct intel_engine_cs *engine;
 	struct intel_context *ctx = client->owner;
 	struct guc_context_desc desc;
 	struct sg_table *sg;
-	int i;
+	enum intel_engine_id id;
+	u32 gfx_addr;
 
 	memset(&desc, 0, sizeof(desc));
 
@@ -390,8 +374,8 @@ static void guc_init_ctx_desc(struct int
 	desc.priority = client->priority;
 	desc.db_id = client->doorbell_id;
 
-	for_each_ring(ring, dev_priv, i) {
-		struct guc_execlist_context *lrc = &desc.lrc[ring->guc_id];
+	for_each_engine_id(engine, dev_priv, id) {
+		struct guc_execlist_context *lrc = &desc.lrc[engine->guc_id];
 		struct drm_i915_gem_object *obj;
 		uint64_t ctx_desc;
 
@@ -402,48 +386,44 @@ static void guc_init_ctx_desc(struct int
 		 * for now who owns a GuC client. But for future owner of GuC
 		 * client, need to make sure lrc is pinned prior to enter here.
 		 */
-		obj = ctx->engine[i].state;
+		obj = ctx->engine[id].state;
 		if (!obj)
 			break;	/* XXX: continue? */
 
-		ctx_desc = intel_lr_context_descriptor(ctx, ring);
+		ctx_desc = intel_lr_context_descriptor(ctx, engine);
 		lrc->context_desc = (u32)ctx_desc;
 
 		/* The state page is after PPHWSP */
-		lrc->ring_lcra = i915_gem_obj_ggtt_offset(obj) +
-				LRC_STATE_PN * PAGE_SIZE;
+		gfx_addr = i915_gem_obj_ggtt_offset(obj);
+		lrc->ring_lcra = gfx_addr + LRC_STATE_PN * PAGE_SIZE;
 		lrc->context_id = (client->ctx_index << GUC_ELC_CTXID_OFFSET) |
-				(ring->guc_id << GUC_ELC_ENGINE_OFFSET);
+				(engine->guc_id << GUC_ELC_ENGINE_OFFSET);
 
-		obj = ctx->engine[i].ringbuf->obj;
+		obj = ctx->engine[id].ringbuf->obj;
+		gfx_addr = i915_gem_obj_ggtt_offset(obj);
 
-		lrc->ring_begin = i915_gem_obj_ggtt_offset(obj);
-		lrc->ring_end = lrc->ring_begin + obj->base.size - 1;
-		lrc->ring_next_free_location = lrc->ring_begin;
+		lrc->ring_begin = gfx_addr;
+		lrc->ring_end = gfx_addr + obj->base.size - 1;
+		lrc->ring_next_free_location = gfx_addr;
 		lrc->ring_current_tail_pointer_value = 0;
 
-		desc.engines_used |= (1 << ring->guc_id);
+		desc.engines_used |= (1 << engine->guc_id);
 	}
 
 	WARN_ON(desc.engines_used == 0);
 
 	/*
-	 * The CPU address is only needed at certain points, so kmap_atomic on
-	 * demand instead of storing it in the ctx descriptor.
-	 * XXX: May make debug easier to have it mapped
+	 * The doorbell, process descriptor, and workqueue are all parts
+	 * of the client object, which the GuC will reference via the GGTT
 	 */
-	desc.db_trigger_cpu = 0;
-	desc.db_trigger_uk = client->doorbell_offset +
-		i915_gem_obj_ggtt_offset(client->client_obj);
-	desc.db_trigger_phy = client->doorbell_offset +
-		sg_dma_address(client->client_obj->pages->sgl);
-
-	desc.process_desc = client->proc_desc_offset +
-		i915_gem_obj_ggtt_offset(client->client_obj);
-
-	desc.wq_addr = client->wq_offset +
-		i915_gem_obj_ggtt_offset(client->client_obj);
-
+	gfx_addr = i915_gem_obj_ggtt_offset(client_obj);
+	desc.db_trigger_phy = sg_dma_address(client_obj->pages->sgl) +
+				client->doorbell_offset;
+	desc.db_trigger_cpu = (uintptr_t)client->client_base +
+				client->doorbell_offset;
+	desc.db_trigger_uk = gfx_addr + client->doorbell_offset;
+	desc.process_desc = gfx_addr + client->proc_desc_offset;
+	desc.wq_addr = gfx_addr + client->wq_offset;
 	desc.wq_size = client->wq_size;
 
 	/*
@@ -474,25 +454,16 @@ static void guc_fini_ctx_desc(struct int
 int i915_guc_wq_check_space(struct i915_guc_client *gc)
 {
 	struct guc_process_desc *desc;
-	void *base;
 	u32 size = sizeof(struct guc_wq_item);
 	int ret = -ETIMEDOUT, timeout_counter = 200;
 
 	if (!gc)
 		return 0;
 
-	/* Quickly return if wq space is available since last time we cache the
-	 * head position. */
-	if (CIRC_SPACE(gc->wq_tail, gc->wq_head, gc->wq_size) >= size)
-		return 0;
-
-	base = kmap_atomic(i915_gem_object_get_page(gc->client_obj, 0));
-	desc = base + gc->proc_desc_offset;
+	desc = gc->client_base + gc->proc_desc_offset;
 
 	while (timeout_counter-- > 0) {
-		gc->wq_head = desc->head;
-
-		if (CIRC_SPACE(gc->wq_tail, gc->wq_head, gc->wq_size) >= size) {
+		if (CIRC_SPACE(gc->wq_tail, desc->head, gc->wq_size) >= size) {
 			ret = 0;
 			break;
 		}
@@ -501,19 +472,19 @@ int i915_guc_wq_check_space(struct i915_
 			usleep_range(1000, 2000);
 	};
 
-	kunmap_atomic(base);
-
 	return ret;
 }
 
 static int guc_add_workqueue_item(struct i915_guc_client *gc,
 				  struct drm_i915_gem_request *rq)
 {
+	struct guc_process_desc *desc;
 	struct guc_wq_item *wqi;
 	void *base;
 	u32 tail, wq_len, wq_off, space;
 
-	space = CIRC_SPACE(gc->wq_tail, gc->wq_head, gc->wq_size);
+	desc = gc->client_base + gc->proc_desc_offset;
+	space = CIRC_SPACE(gc->wq_tail, desc->head, gc->wq_size);
 	if (WARN_ON(space < sizeof(struct guc_wq_item)))
 		return -ENOSPC; /* shouldn't happen */
 
@@ -542,11 +513,12 @@ static int guc_add_workqueue_item(struct
 	wq_len = sizeof(struct guc_wq_item) / sizeof(u32) - 1;
 	wqi->header = WQ_TYPE_INORDER |
 			(wq_len << WQ_LEN_SHIFT) |
-			(rq->ring->guc_id << WQ_TARGET_SHIFT) |
+			(rq->engine->guc_id << WQ_TARGET_SHIFT) |
 			WQ_NO_WCFLUSH_WAIT;
 
 	/* The GuC wants only the low-order word of the context descriptor */
-	wqi->context_desc = (u32)intel_lr_context_descriptor(rq->ctx, rq->ring);
+	wqi->context_desc = (u32)intel_lr_context_descriptor(rq->ctx,
+							     rq->engine);
 
 	/* The GuC firmware wants the tail index in QWords, not bytes */
 	tail = rq->ringbuf->tail >> 3;
@@ -569,7 +541,7 @@ int i915_guc_submit(struct i915_guc_clie
 		    struct drm_i915_gem_request *rq)
 {
 	struct intel_guc *guc = client->guc;
-	unsigned int engine_id = rq->ring->guc_id;
+	unsigned int engine_id = rq->engine->guc_id;
 	int q_ret, b_ret;
 
 	q_ret = guc_add_workqueue_item(client, rq);
@@ -660,21 +632,28 @@ static void guc_client_free(struct drm_d
 	if (!client)
 		return;
 
-	if (client->doorbell_id != GUC_INVALID_DOORBELL_ID) {
-		/*
-		 * First disable the doorbell, then tell the GuC we've
-		 * finished with it, finally deallocate it in our bitmap
-		 */
-		guc_disable_doorbell(guc, client);
-		host2guc_release_doorbell(guc, client);
-		release_doorbell(guc, client->doorbell_id);
-	}
-
 	/*
 	 * XXX: wait for any outstanding submissions before freeing memory.
 	 * Be sure to drop any locks
 	 */
 
+	if (client->client_base) {
+		/*
+		 * If we got as far as setting up a doorbell, make sure
+		 * we shut it down before unmapping & deallocating the
+		 * memory. So first disable the doorbell, then tell the
+		 * GuC that we've finished with it, finally deallocate
+		 * it in our bitmap
+		 */
+		if (client->doorbell_id != GUC_INVALID_DOORBELL_ID) {
+			guc_disable_doorbell(guc, client);
+			host2guc_release_doorbell(guc, client);
+			release_doorbell(guc, client->doorbell_id);
+		}
+
+		kunmap(kmap_to_page(client->client_base));
+	}
+
 	gem_release_guc_obj(client->client_obj);
 
 	if (client->ctx_index != GUC_INVALID_CTX_ID) {
@@ -695,7 +674,7 @@ static void guc_client_free(struct drm_d
  * @ctx:	the context that owns the client (we use the default render
  * 		context)
  *
- * Return:	An i915_guc_client object if success.
+ * Return:	An i915_guc_client object if success, else NULL.
  */
 static struct i915_guc_client *guc_client_alloc(struct drm_device *dev,
 						uint32_t priority,
@@ -727,7 +706,9 @@ static struct i915_guc_client *guc_clien
 	if (!obj)
 		goto err;
 
+	/* We'll keep just the first (doorbell/proc) page permanently kmap'd. */
 	client->client_obj = obj;
+	client->client_base = kmap(i915_gem_object_get_page(obj, 0));
 	client->wq_offset = GUC_DB_SIZE;
 	client->wq_size = GUC_WQ_SIZE;
 
@@ -839,9 +820,9 @@ static void guc_create_ads(struct intel_
 	struct guc_ads *ads;
 	struct guc_policies *policies;
 	struct guc_mmio_reg_state *reg_state;
-	struct intel_engine_cs *ring;
+	struct intel_engine_cs *engine;
 	struct page *page;
-	u32 size, i;
+	u32 size;
 
 	/* The ads obj includes the struct itself and buffers passed to GuC */
 	size = sizeof(struct guc_ads) + sizeof(struct guc_policies) +
@@ -867,11 +848,11 @@ static void guc_create_ads(struct intel_
 	 * so its address won't change after we've told the GuC where
 	 * to find it.
 	 */
-	ring = &dev_priv->ring[RCS];
-	ads->golden_context_lrca = ring->status_page.gfx_addr;
+	engine = &dev_priv->engine[RCS];
+	ads->golden_context_lrca = engine->status_page.gfx_addr;
 
-	for_each_ring(ring, dev_priv, i)
-		ads->eng_state_size[ring->guc_id] = intel_lr_context_size(ring);
+	for_each_engine(engine, dev_priv)
+		ads->eng_state_size[engine->guc_id] = intel_lr_context_size(engine);
 
 	/* GuC scheduling policies */
 	policies = (void *)ads + sizeof(struct guc_ads);
@@ -883,12 +864,12 @@ static void guc_create_ads(struct intel_
 	/* MMIO reg state */
 	reg_state = (void *)policies + sizeof(struct guc_policies);
 
-	for_each_ring(ring, dev_priv, i) {
-		reg_state->mmio_white_list[ring->guc_id].mmio_start =
-			ring->mmio_base + GUC_MMIO_WHITE_LIST_START;
+	for_each_engine(engine, dev_priv) {
+		reg_state->mmio_white_list[engine->guc_id].mmio_start =
+			engine->mmio_base + GUC_MMIO_WHITE_LIST_START;
 
 		/* Nothing to be saved or restored for now. */
-		reg_state->mmio_white_list[ring->guc_id].count = 0;
+		reg_state->mmio_white_list[engine->guc_id].count = 0;
 	}
 
 	ads->reg_state_addr = ads->scheduler_policies +
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_irq.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_irq.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_irq.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_irq.c	2016-07-24 15:23:50.000000000 -0400
@@ -994,14 +994,15 @@ static void ironlake_rps_change_irq_hand
 	return;
 }
 
-static void notify_ring(struct intel_engine_cs *ring)
+static void notify_ring(struct intel_engine_cs *engine)
 {
-	if (!intel_ring_initialized(ring))
+	if (!intel_engine_initialized(engine))
 		return;
 
-	trace_i915_gem_request_notify(ring);
+	trace_i915_gem_request_notify(engine);
+	engine->user_interrupts++;
 
-	wake_up_all(&ring->irq_queue);
+	wake_up_all(&engine->irq_queue);
 }
 
 static void vlv_c0_read(struct drm_i915_private *dev_priv,
@@ -1079,11 +1080,10 @@ static u32 vlv_wa_c0_ei(struct drm_i915_
 
 static bool any_waiters(struct drm_i915_private *dev_priv)
 {
-	struct intel_engine_cs *ring;
-	int i;
+	struct intel_engine_cs *engine;
 
-	for_each_ring(ring, dev_priv, i)
-		if (ring->irq_refcount)
+	for_each_engine(engine, dev_priv)
+		if (engine->irq_refcount)
 			return true;
 
 	return false;
@@ -1219,7 +1219,7 @@ static void ivybridge_parity_work(struct
 		i915_reg_t reg;
 
 		slice--;
-		if (WARN_ON_ONCE(slice >= NUM_L3_SLICES(dev_priv->dev)))
+		if (WARN_ON_ONCE(slice >= NUM_L3_SLICES(dev_priv)))
 			break;
 
 		dev_priv->l3_parity.which_slice &= ~(1<<slice);
@@ -1258,24 +1258,23 @@ static void ivybridge_parity_work(struct
 out:
 	WARN_ON(dev_priv->l3_parity.which_slice);
 	spin_lock_irq(&dev_priv->irq_lock);
-	gen5_enable_gt_irq(dev_priv, GT_PARITY_ERROR(dev_priv->dev));
+	gen5_enable_gt_irq(dev_priv, GT_PARITY_ERROR(dev_priv));
 	spin_unlock_irq(&dev_priv->irq_lock);
 
 	mutex_unlock(&dev_priv->dev->struct_mutex);
 }
 
-static void ivybridge_parity_error_irq_handler(struct drm_device *dev, u32 iir)
+static void ivybridge_parity_error_irq_handler(struct drm_i915_private *dev_priv,
+					       u32 iir)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-
-	if (!HAS_L3_DPF(dev))
+	if (!HAS_L3_DPF(dev_priv))
 		return;
 
 	spin_lock(&dev_priv->irq_lock);
-	gen5_disable_gt_irq(dev_priv, GT_PARITY_ERROR(dev));
+	gen5_disable_gt_irq(dev_priv, GT_PARITY_ERROR(dev_priv));
 	spin_unlock(&dev_priv->irq_lock);
 
-	iir &= GT_PARITY_ERROR(dev);
+	iir &= GT_PARITY_ERROR(dev_priv);
 	if (iir & GT_RENDER_L3_PARITY_ERROR_INTERRUPT_S1)
 		dev_priv->l3_parity.which_slice |= 1 << 1;
 
@@ -1285,102 +1284,85 @@ static void ivybridge_parity_error_irq_h
 	queue_work(dev_priv->wq, &dev_priv->l3_parity.error_work);
 }
 
-static void ilk_gt_irq_handler(struct drm_device *dev,
-			       struct drm_i915_private *dev_priv,
+static void ilk_gt_irq_handler(struct drm_i915_private *dev_priv,
 			       u32 gt_iir)
 {
 	if (gt_iir &
 	    (GT_RENDER_USER_INTERRUPT | GT_RENDER_PIPECTL_NOTIFY_INTERRUPT))
-		notify_ring(&dev_priv->ring[RCS]);
+		notify_ring(&dev_priv->engine[RCS]);
 	if (gt_iir & ILK_BSD_USER_INTERRUPT)
-		notify_ring(&dev_priv->ring[VCS]);
+		notify_ring(&dev_priv->engine[VCS]);
 }
 
-static void snb_gt_irq_handler(struct drm_device *dev,
-			       struct drm_i915_private *dev_priv,
+static void snb_gt_irq_handler(struct drm_i915_private *dev_priv,
 			       u32 gt_iir)
 {
 
 	if (gt_iir &
 	    (GT_RENDER_USER_INTERRUPT | GT_RENDER_PIPECTL_NOTIFY_INTERRUPT))
-		notify_ring(&dev_priv->ring[RCS]);
+		notify_ring(&dev_priv->engine[RCS]);
 	if (gt_iir & GT_BSD_USER_INTERRUPT)
-		notify_ring(&dev_priv->ring[VCS]);
+		notify_ring(&dev_priv->engine[VCS]);
 	if (gt_iir & GT_BLT_USER_INTERRUPT)
-		notify_ring(&dev_priv->ring[BCS]);
+		notify_ring(&dev_priv->engine[BCS]);
 
 	if (gt_iir & (GT_BLT_CS_ERROR_INTERRUPT |
 		      GT_BSD_CS_ERROR_INTERRUPT |
 		      GT_RENDER_CS_MASTER_ERROR_INTERRUPT))
 		DRM_DEBUG("Command parser error, gt_iir 0x%08x\n", gt_iir);
 
-	if (gt_iir & GT_PARITY_ERROR(dev))
-		ivybridge_parity_error_irq_handler(dev, gt_iir);
+	if (gt_iir & GT_PARITY_ERROR(dev_priv))
+		ivybridge_parity_error_irq_handler(dev_priv, gt_iir);
 }
 
 static __always_inline void
-gen8_cs_irq_handler(struct intel_engine_cs *ring, u32 iir, int test_shift)
+gen8_cs_irq_handler(struct intel_engine_cs *engine, u32 iir, int test_shift)
 {
 	if (iir & (GT_RENDER_USER_INTERRUPT << test_shift))
-		notify_ring(ring);
+		notify_ring(engine);
 	if (iir & (GT_CONTEXT_SWITCH_INTERRUPT << test_shift))
-		intel_lrc_irq_handler(ring);
+		tasklet_schedule(&engine->irq_tasklet);
 }
 
-static irqreturn_t gen8_gt_irq_handler(struct drm_i915_private *dev_priv,
-				       u32 master_ctl)
+static irqreturn_t gen8_gt_irq_ack(struct drm_i915_private *dev_priv,
+				   u32 master_ctl,
+				   u32 gt_iir[4])
 {
 	irqreturn_t ret = IRQ_NONE;
 
 	if (master_ctl & (GEN8_GT_RCS_IRQ | GEN8_GT_BCS_IRQ)) {
-		u32 iir = I915_READ_FW(GEN8_GT_IIR(0));
-		if (iir) {
-			I915_WRITE_FW(GEN8_GT_IIR(0), iir);
+		gt_iir[0] = I915_READ_FW(GEN8_GT_IIR(0));
+		if (gt_iir[0]) {
+			I915_WRITE_FW(GEN8_GT_IIR(0), gt_iir[0]);
 			ret = IRQ_HANDLED;
-
-			gen8_cs_irq_handler(&dev_priv->ring[RCS],
-					iir, GEN8_RCS_IRQ_SHIFT);
-
-			gen8_cs_irq_handler(&dev_priv->ring[BCS],
-					iir, GEN8_BCS_IRQ_SHIFT);
 		} else
 			DRM_ERROR("The master control interrupt lied (GT0)!\n");
 	}
 
 	if (master_ctl & (GEN8_GT_VCS1_IRQ | GEN8_GT_VCS2_IRQ)) {
-		u32 iir = I915_READ_FW(GEN8_GT_IIR(1));
-		if (iir) {
-			I915_WRITE_FW(GEN8_GT_IIR(1), iir);
+		gt_iir[1] = I915_READ_FW(GEN8_GT_IIR(1));
+		if (gt_iir[1]) {
+			I915_WRITE_FW(GEN8_GT_IIR(1), gt_iir[1]);
 			ret = IRQ_HANDLED;
-
-			gen8_cs_irq_handler(&dev_priv->ring[VCS],
-					iir, GEN8_VCS1_IRQ_SHIFT);
-
-			gen8_cs_irq_handler(&dev_priv->ring[VCS2],
-					iir, GEN8_VCS2_IRQ_SHIFT);
 		} else
 			DRM_ERROR("The master control interrupt lied (GT1)!\n");
 	}
 
 	if (master_ctl & GEN8_GT_VECS_IRQ) {
-		u32 iir = I915_READ_FW(GEN8_GT_IIR(3));
-		if (iir) {
-			I915_WRITE_FW(GEN8_GT_IIR(3), iir);
+		gt_iir[3] = I915_READ_FW(GEN8_GT_IIR(3));
+		if (gt_iir[3]) {
+			I915_WRITE_FW(GEN8_GT_IIR(3), gt_iir[3]);
 			ret = IRQ_HANDLED;
-
-			gen8_cs_irq_handler(&dev_priv->ring[VECS],
-					iir, GEN8_VECS_IRQ_SHIFT);
 		} else
 			DRM_ERROR("The master control interrupt lied (GT3)!\n");
 	}
 
 	if (master_ctl & GEN8_GT_PM_IRQ) {
-		u32 iir = I915_READ_FW(GEN8_GT_IIR(2));
-		if (iir & dev_priv->pm_rps_events) {
+		gt_iir[2] = I915_READ_FW(GEN8_GT_IIR(2));
+		if (gt_iir[2] & dev_priv->pm_rps_events) {
 			I915_WRITE_FW(GEN8_GT_IIR(2),
-				      iir & dev_priv->pm_rps_events);
+				      gt_iir[2] & dev_priv->pm_rps_events);
 			ret = IRQ_HANDLED;
-			gen6_rps_irq_handler(dev_priv, iir);
 		} else
 			DRM_ERROR("The master control interrupt lied (PM)!\n");
 	}
@@ -1388,6 +1370,31 @@ static irqreturn_t gen8_gt_irq_handler(s
 	return ret;
 }
 
+static void gen8_gt_irq_handler(struct drm_i915_private *dev_priv,
+				u32 gt_iir[4])
+{
+	if (gt_iir[0]) {
+		gen8_cs_irq_handler(&dev_priv->engine[RCS],
+				    gt_iir[0], GEN8_RCS_IRQ_SHIFT);
+		gen8_cs_irq_handler(&dev_priv->engine[BCS],
+				    gt_iir[0], GEN8_BCS_IRQ_SHIFT);
+	}
+
+	if (gt_iir[1]) {
+		gen8_cs_irq_handler(&dev_priv->engine[VCS],
+				    gt_iir[1], GEN8_VCS1_IRQ_SHIFT);
+		gen8_cs_irq_handler(&dev_priv->engine[VCS2],
+				    gt_iir[1], GEN8_VCS2_IRQ_SHIFT);
+	}
+
+	if (gt_iir[3])
+		gen8_cs_irq_handler(&dev_priv->engine[VECS],
+				    gt_iir[3], GEN8_VECS_IRQ_SHIFT);
+
+	if (gt_iir[2] & dev_priv->pm_rps_events)
+		gen6_rps_irq_handler(dev_priv, gt_iir[2]);
+}
+
 static bool bxt_port_hotplug_long_detect(enum port port, u32 val)
 {
 	switch (port) {
@@ -1627,9 +1634,9 @@ static void gen6_rps_irq_handler(struct
 	if (INTEL_INFO(dev_priv)->gen >= 8)
 		return;
 
-	if (HAS_VEBOX(dev_priv->dev)) {
+	if (HAS_VEBOX(dev_priv)) {
 		if (pm_iir & PM_VEBOX_USER_INTERRUPT)
-			notify_ring(&dev_priv->ring[VECS]);
+			notify_ring(&dev_priv->engine[VECS]);
 
 		if (pm_iir & PM_VEBOX_CS_ERROR_INTERRUPT)
 			DRM_DEBUG("Command parser error, pm_iir 0x%08x\n", pm_iir);
@@ -1644,10 +1651,10 @@ static bool intel_pipe_handle_vblank(str
 	return true;
 }
 
-static void valleyview_pipestat_irq_handler(struct drm_device *dev, u32 iir)
+static void valleyview_pipestat_irq_ack(struct drm_device *dev, u32 iir,
+					u32 pipe_stats[I915_MAX_PIPES])
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 pipe_stats[I915_MAX_PIPES] = { };
 	int pipe;
 
 	spin_lock(&dev_priv->irq_lock);
@@ -1701,6 +1708,13 @@ static void valleyview_pipestat_irq_hand
 			I915_WRITE(reg, pipe_stats[pipe]);
 	}
 	spin_unlock(&dev_priv->irq_lock);
+}
+
+static void valleyview_pipestat_irq_handler(struct drm_device *dev,
+					    u32 pipe_stats[I915_MAX_PIPES])
+{
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	enum pipe pipe;
 
 	for_each_pipe(dev_priv, pipe) {
 		if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS &&
@@ -1723,21 +1737,20 @@ static void valleyview_pipestat_irq_hand
 		gmbus_irq_handler(dev);
 }
 
-static void i9xx_hpd_irq_handler(struct drm_device *dev)
+static u32 i9xx_hpd_irq_ack(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT);
-	u32 pin_mask = 0, long_mask = 0;
 
-	if (!hotplug_status)
-		return;
+	if (hotplug_status)
+		I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
 
-	I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
-	/*
-	 * Make sure hotplug status is cleared before we clear IIR, or else we
-	 * may miss hotplug events.
-	 */
-	POSTING_READ(PORT_HOTPLUG_STAT);
+	return hotplug_status;
+}
+
+static void i9xx_hpd_irq_handler(struct drm_device *dev,
+				 u32 hotplug_status)
+{
+	u32 pin_mask = 0, long_mask = 0;
 
 	if (IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
 		u32 hotplug_trigger = hotplug_status & HOTPLUG_INT_STATUS_G4X;
@@ -1768,7 +1781,6 @@ static irqreturn_t valleyview_irq_handle
 {
 	struct drm_device *dev = arg;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 iir, gt_iir, pm_iir;
 	irqreturn_t ret = IRQ_NONE;
 
 	if (!intel_irqs_enabled(dev_priv))
@@ -1777,40 +1789,72 @@ static irqreturn_t valleyview_irq_handle
 	/* IRQs are synced during runtime_suspend, we don't require a wakeref */
 	disable_rpm_wakeref_asserts(dev_priv);
 
-	while (true) {
-		/* Find, clear, then process each source of interrupt */
+	do {
+		u32 iir, gt_iir, pm_iir;
+		u32 pipe_stats[I915_MAX_PIPES] = {};
+		u32 hotplug_status = 0;
+		u32 ier = 0;
 
 		gt_iir = I915_READ(GTIIR);
-		if (gt_iir)
-			I915_WRITE(GTIIR, gt_iir);
-
 		pm_iir = I915_READ(GEN6_PMIIR);
-		if (pm_iir)
-			I915_WRITE(GEN6_PMIIR, pm_iir);
-
 		iir = I915_READ(VLV_IIR);
-		if (iir) {
-			/* Consume port before clearing IIR or we'll miss events */
-			if (iir & I915_DISPLAY_PORT_INTERRUPT)
-				i9xx_hpd_irq_handler(dev);
-			I915_WRITE(VLV_IIR, iir);
-		}
 
 		if (gt_iir == 0 && pm_iir == 0 && iir == 0)
-			goto out;
+			break;
 
 		ret = IRQ_HANDLED;
 
+		/*
+		 * Theory on interrupt generation, based on empirical evidence:
+		 *
+		 * x = ((VLV_IIR & VLV_IER) ||
+		 *      (((GT_IIR & GT_IER) || (GEN6_PMIIR & GEN6_PMIER)) &&
+		 *       (VLV_MASTER_IER & MASTER_INTERRUPT_ENABLE)));
+		 *
+		 * A CPU interrupt will only be raised when 'x' has a 0->1 edge.
+		 * Hence we clear MASTER_INTERRUPT_ENABLE and VLV_IER to
+		 * guarantee the CPU interrupt will be raised again even if we
+		 * don't end up clearing all the VLV_IIR, GT_IIR, GEN6_PMIIR
+		 * bits this time around.
+		 */
+		I915_WRITE(VLV_MASTER_IER, 0);
+		ier = I915_READ(VLV_IER);
+		I915_WRITE(VLV_IER, 0);
+
 		if (gt_iir)
-			snb_gt_irq_handler(dev, dev_priv, gt_iir);
+			I915_WRITE(GTIIR, gt_iir);
 		if (pm_iir)
-			gen6_rps_irq_handler(dev_priv, pm_iir);
+			I915_WRITE(GEN6_PMIIR, pm_iir);
+
+		if (iir & I915_DISPLAY_PORT_INTERRUPT)
+			hotplug_status = i9xx_hpd_irq_ack(dev_priv);
+
 		/* Call regardless, as some status bits might not be
 		 * signalled in iir */
-		valleyview_pipestat_irq_handler(dev, iir);
-	}
+		valleyview_pipestat_irq_ack(dev, iir, pipe_stats);
+
+		/*
+		 * VLV_IIR is single buffered, and reflects the level
+		 * from PIPESTAT/PORT_HOTPLUG_STAT, hence clear it last.
+		 */
+		if (iir)
+			I915_WRITE(VLV_IIR, iir);
+
+		I915_WRITE(VLV_IER, ier);
+		I915_WRITE(VLV_MASTER_IER, MASTER_INTERRUPT_ENABLE);
+		POSTING_READ(VLV_MASTER_IER);
+
+		if (gt_iir)
+			snb_gt_irq_handler(dev_priv, gt_iir);
+		if (pm_iir)
+			gen6_rps_irq_handler(dev_priv, pm_iir);
+
+		if (hotplug_status)
+			i9xx_hpd_irq_handler(dev, hotplug_status);
+
+		valleyview_pipestat_irq_handler(dev, pipe_stats);
+	} while (0);
 
-out:
 	enable_rpm_wakeref_asserts(dev_priv);
 
 	return ret;
@@ -1820,7 +1864,6 @@ static irqreturn_t cherryview_irq_handle
 {
 	struct drm_device *dev = arg;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 master_ctl, iir;
 	irqreturn_t ret = IRQ_NONE;
 
 	if (!intel_irqs_enabled(dev_priv))
@@ -1830,6 +1873,12 @@ static irqreturn_t cherryview_irq_handle
 	disable_rpm_wakeref_asserts(dev_priv);
 
 	do {
+		u32 master_ctl, iir;
+		u32 gt_iir[4] = {};
+		u32 pipe_stats[I915_MAX_PIPES] = {};
+		u32 hotplug_status = 0;
+		u32 ier = 0;
+
 		master_ctl = I915_READ(GEN8_MASTER_IRQ) & ~GEN8_MASTER_IRQ_CONTROL;
 		iir = I915_READ(VLV_IIR);
 
@@ -1838,25 +1887,49 @@ static irqreturn_t cherryview_irq_handle
 
 		ret = IRQ_HANDLED;
 
+		/*
+		 * Theory on interrupt generation, based on empirical evidence:
+		 *
+		 * x = ((VLV_IIR & VLV_IER) ||
+		 *      ((GEN8_MASTER_IRQ & ~GEN8_MASTER_IRQ_CONTROL) &&
+		 *       (GEN8_MASTER_IRQ & GEN8_MASTER_IRQ_CONTROL)));
+		 *
+		 * A CPU interrupt will only be raised when 'x' has a 0->1 edge.
+		 * Hence we clear GEN8_MASTER_IRQ_CONTROL and VLV_IER to
+		 * guarantee the CPU interrupt will be raised again even if we
+		 * don't end up clearing all the VLV_IIR and GEN8_MASTER_IRQ_CONTROL
+		 * bits this time around.
+		 */
 		I915_WRITE(GEN8_MASTER_IRQ, 0);
+		ier = I915_READ(VLV_IER);
+		I915_WRITE(VLV_IER, 0);
 
-		/* Find, clear, then process each source of interrupt */
-
-		if (iir) {
-			/* Consume port before clearing IIR or we'll miss events */
-			if (iir & I915_DISPLAY_PORT_INTERRUPT)
-				i9xx_hpd_irq_handler(dev);
-			I915_WRITE(VLV_IIR, iir);
-		}
+		gen8_gt_irq_ack(dev_priv, master_ctl, gt_iir);
 
-		gen8_gt_irq_handler(dev_priv, master_ctl);
+		if (iir & I915_DISPLAY_PORT_INTERRUPT)
+			hotplug_status = i9xx_hpd_irq_ack(dev_priv);
 
 		/* Call regardless, as some status bits might not be
 		 * signalled in iir */
-		valleyview_pipestat_irq_handler(dev, iir);
+		valleyview_pipestat_irq_ack(dev, iir, pipe_stats);
 
-		I915_WRITE(GEN8_MASTER_IRQ, DE_MASTER_IRQ_CONTROL);
+		/*
+		 * VLV_IIR is single buffered, and reflects the level
+		 * from PIPESTAT/PORT_HOTPLUG_STAT, hence clear it last.
+		 */
+		if (iir)
+			I915_WRITE(VLV_IIR, iir);
+
+		I915_WRITE(VLV_IER, ier);
+		I915_WRITE(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
 		POSTING_READ(GEN8_MASTER_IRQ);
+
+		gen8_gt_irq_handler(dev_priv, gt_iir);
+
+		if (hotplug_status)
+			i9xx_hpd_irq_handler(dev, hotplug_status);
+
+		valleyview_pipestat_irq_handler(dev, pipe_stats);
 	} while (0);
 
 	enable_rpm_wakeref_asserts(dev_priv);
@@ -2217,9 +2290,9 @@ static irqreturn_t ironlake_irq_handler(
 		I915_WRITE(GTIIR, gt_iir);
 		ret = IRQ_HANDLED;
 		if (INTEL_INFO(dev)->gen >= 6)
-			snb_gt_irq_handler(dev, dev_priv, gt_iir);
+			snb_gt_irq_handler(dev_priv, gt_iir);
 		else
-			ilk_gt_irq_handler(dev, dev_priv, gt_iir);
+			ilk_gt_irq_handler(dev_priv, gt_iir);
 	}
 
 	de_iir = I915_READ(DEIIR);
@@ -2398,7 +2471,7 @@ gen8_de_irq_handler(struct drm_i915_priv
 			I915_WRITE(SDEIIR, iir);
 			ret = IRQ_HANDLED;
 
-			if (HAS_PCH_SPT(dev_priv))
+			if (HAS_PCH_SPT(dev_priv) || HAS_PCH_KBP(dev_priv))
 				spt_irq_handler(dev, iir);
 			else
 				cpt_irq_handler(dev, iir);
@@ -2419,6 +2492,7 @@ static irqreturn_t gen8_irq_handler(int
 	struct drm_device *dev = arg;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 master_ctl;
+	u32 gt_iir[4] = {};
 	irqreturn_t ret;
 
 	if (!intel_irqs_enabled(dev_priv))
@@ -2435,7 +2509,8 @@ static irqreturn_t gen8_irq_handler(int
 	disable_rpm_wakeref_asserts(dev_priv);
 
 	/* Find, clear, then process each source of interrupt */
-	ret = gen8_gt_irq_handler(dev_priv, master_ctl);
+	ret = gen8_gt_irq_ack(dev_priv, master_ctl, gt_iir);
+	gen8_gt_irq_handler(dev_priv, gt_iir);
 	ret |= gen8_de_irq_handler(dev_priv, master_ctl);
 
 	I915_WRITE_FW(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
@@ -2449,8 +2524,7 @@ static irqreturn_t gen8_irq_handler(int
 static void i915_error_wake_up(struct drm_i915_private *dev_priv,
 			       bool reset_completed)
 {
-	struct intel_engine_cs *ring;
-	int i;
+	struct intel_engine_cs *engine;
 
 	/*
 	 * Notify all waiters for GPU completion events that reset state has
@@ -2460,8 +2534,8 @@ static void i915_error_wake_up(struct dr
 	 */
 
 	/* Wake up __wait_seqno, potentially holding dev->struct_mutex. */
-	for_each_ring(ring, dev_priv, i)
-		wake_up_all(&ring->irq_queue);
+	for_each_engine(engine, dev_priv)
+		wake_up_all(&engine->irq_queue);
 
 	/* Wake up intel_crtc_wait_for_pending_flips, holding crtc->mutex. */
 	wake_up_all(&dev_priv->pending_flip_queue);
@@ -2484,7 +2558,6 @@ static void i915_error_wake_up(struct dr
 static void i915_reset_and_wakeup(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
-	struct i915_gpu_error *error = &dev_priv->gpu_error;
 	char *error_event[] = { I915_ERROR_UEVENT "=1", NULL };
 	char *reset_event[] = { I915_RESET_UEVENT "=1", NULL };
 	char *reset_done_event[] = { I915_ERROR_UEVENT "=0", NULL };
@@ -2502,7 +2575,7 @@ static void i915_reset_and_wakeup(struct
 	 * the reset in-progress bit is only ever set by code outside of this
 	 * work we don't need to worry about any other races.
 	 */
-	if (i915_reset_in_progress(error) && !i915_terminally_wedged(error)) {
+	if (i915_reset_in_progress(&dev_priv->gpu_error)) {
 		DRM_DEBUG_DRIVER("resetting chip\n");
 		kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE,
 				   reset_event);
@@ -2530,25 +2603,9 @@ static void i915_reset_and_wakeup(struct
 
 		intel_runtime_pm_put(dev_priv);
 
-		if (ret == 0) {
-			/*
-			 * After all the gem state is reset, increment the reset
-			 * counter and wake up everyone waiting for the reset to
-			 * complete.
-			 *
-			 * Since unlock operations are a one-sided barrier only,
-			 * we need to insert a barrier here to order any seqno
-			 * updates before
-			 * the counter increment.
-			 */
-			smp_mb__before_atomic();
-			atomic_inc(&dev_priv->gpu_error.reset_counter);
-
+		if (ret == 0)
 			kobject_uevent_env(&dev->primary->kdev->kobj,
 					   KOBJ_CHANGE, reset_done_event);
-		} else {
-			atomic_or(I915_WEDGED, &error->reset_counter);
-		}
 
 		/*
 		 * Note: The wake_up also serves as a memory barrier so that
@@ -2653,14 +2710,14 @@ static void i915_report_and_clear_eir(st
 /**
  * i915_handle_error - handle a gpu error
  * @dev: drm device
- *
+ * @engine_mask: mask representing engines that are hung
  * Do some basic checking of register state at error time and
  * dump it to the syslog.  Also call i915_capture_error_state() to make
  * sure we get a record and make it available in debugfs.  Fire a uevent
  * so userspace knows something bad happened (should trigger collection
  * of a ring dump etc.).
  */
-void i915_handle_error(struct drm_device *dev, bool wedged,
+void i915_handle_error(struct drm_device *dev, u32 engine_mask,
 		       const char *fmt, ...)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -2671,10 +2728,10 @@ void i915_handle_error(struct drm_device
 	vscnprintf(error_msg, sizeof(error_msg), fmt, args);
 	va_end(args);
 
-	i915_capture_error_state(dev, wedged, error_msg);
+	i915_capture_error_state(dev, engine_mask, error_msg);
 	i915_report_and_clear_eir(dev);
 
-	if (wedged) {
+	if (engine_mask) {
 		atomic_or(I915_RESET_IN_PROGRESS_FLAG,
 				&dev_priv->gpu_error.reset_counter);
 
@@ -2805,10 +2862,10 @@ static void gen8_disable_vblank(struct d
 }
 
 static bool
-ring_idle(struct intel_engine_cs *ring, u32 seqno)
+ring_idle(struct intel_engine_cs *engine, u32 seqno)
 {
-	return (list_empty(&ring->request_list) ||
-		i915_seqno_passed(seqno, ring->last_submitted_seqno));
+	return i915_seqno_passed(seqno,
+				 READ_ONCE(engine->last_submitted_seqno));
 }
 
 static bool
@@ -2824,42 +2881,42 @@ ipehr_is_semaphore_wait(struct drm_devic
 }
 
 static struct intel_engine_cs *
-semaphore_wait_to_signaller_ring(struct intel_engine_cs *ring, u32 ipehr, u64 offset)
+semaphore_wait_to_signaller_ring(struct intel_engine_cs *engine, u32 ipehr,
+				 u64 offset)
 {
-	struct drm_i915_private *dev_priv = ring->dev->dev_private;
+	struct drm_i915_private *dev_priv = engine->dev->dev_private;
 	struct intel_engine_cs *signaller;
-	int i;
 
-	if (INTEL_INFO(dev_priv->dev)->gen >= 8) {
-		for_each_ring(signaller, dev_priv, i) {
-			if (ring == signaller)
+	if (INTEL_INFO(dev_priv)->gen >= 8) {
+		for_each_engine(signaller, dev_priv) {
+			if (engine == signaller)
 				continue;
 
-			if (offset == signaller->semaphore.signal_ggtt[ring->id])
+			if (offset == signaller->semaphore.signal_ggtt[engine->id])
 				return signaller;
 		}
 	} else {
 		u32 sync_bits = ipehr & MI_SEMAPHORE_SYNC_MASK;
 
-		for_each_ring(signaller, dev_priv, i) {
-			if(ring == signaller)
+		for_each_engine(signaller, dev_priv) {
+			if(engine == signaller)
 				continue;
 
-			if (sync_bits == signaller->semaphore.mbox.wait[ring->id])
+			if (sync_bits == signaller->semaphore.mbox.wait[engine->id])
 				return signaller;
 		}
 	}
 
 	DRM_ERROR("No signaller ring found for ring %i, ipehr 0x%08x, offset 0x%016llx\n",
-		  ring->id, ipehr, offset);
+		  engine->id, ipehr, offset);
 
 	return NULL;
 }
 
 static struct intel_engine_cs *
-semaphore_waits_for(struct intel_engine_cs *ring, u32 *seqno)
+semaphore_waits_for(struct intel_engine_cs *engine, u32 *seqno)
 {
-	struct drm_i915_private *dev_priv = ring->dev->dev_private;
+	struct drm_i915_private *dev_priv = engine->dev->dev_private;
 	u32 cmd, ipehr, head;
 	u64 offset = 0;
 	int i, backwards;
@@ -2881,11 +2938,11 @@ semaphore_waits_for(struct intel_engine_
 	 * Therefore, this function does not support execlist mode in its
 	 * current form. Just return NULL and move on.
 	 */
-	if (ring->buffer == NULL)
+	if (engine->buffer == NULL)
 		return NULL;
 
-	ipehr = I915_READ(RING_IPEHR(ring->mmio_base));
-	if (!ipehr_is_semaphore_wait(ring->dev, ipehr))
+	ipehr = I915_READ(RING_IPEHR(engine->mmio_base));
+	if (!ipehr_is_semaphore_wait(engine->dev, ipehr))
 		return NULL;
 
 	/*
@@ -2896,8 +2953,8 @@ semaphore_waits_for(struct intel_engine_
 	 * point at at batch, and semaphores are always emitted into the
 	 * ringbuffer itself.
 	 */
-	head = I915_READ_HEAD(ring) & HEAD_ADDR;
-	backwards = (INTEL_INFO(ring->dev)->gen >= 8) ? 5 : 4;
+	head = I915_READ_HEAD(engine) & HEAD_ADDR;
+	backwards = (INTEL_INFO(engine->dev)->gen >= 8) ? 5 : 4;
 
 	for (i = backwards; i; --i) {
 		/*
@@ -2905,10 +2962,10 @@ semaphore_waits_for(struct intel_engine_
 		 * our ring is smaller than what the hardware (and hence
 		 * HEAD_ADDR) allows. Also handles wrap-around.
 		 */
-		head &= ring->buffer->size - 1;
+		head &= engine->buffer->size - 1;
 
 		/* This here seems to blow up */
-		cmd = ioread32(ring->buffer->virtual_start + head);
+		cmd = ioread32(engine->buffer->virtual_start + head);
 		if (cmd == ipehr)
 			break;
 
@@ -2918,32 +2975,32 @@ semaphore_waits_for(struct intel_engine_
 	if (!i)
 		return NULL;
 
-	*seqno = ioread32(ring->buffer->virtual_start + head + 4) + 1;
-	if (INTEL_INFO(ring->dev)->gen >= 8) {
-		offset = ioread32(ring->buffer->virtual_start + head + 12);
+	*seqno = ioread32(engine->buffer->virtual_start + head + 4) + 1;
+	if (INTEL_INFO(engine->dev)->gen >= 8) {
+		offset = ioread32(engine->buffer->virtual_start + head + 12);
 		offset <<= 32;
-		offset = ioread32(ring->buffer->virtual_start + head + 8);
+		offset = ioread32(engine->buffer->virtual_start + head + 8);
 	}
-	return semaphore_wait_to_signaller_ring(ring, ipehr, offset);
+	return semaphore_wait_to_signaller_ring(engine, ipehr, offset);
 }
 
-static int semaphore_passed(struct intel_engine_cs *ring)
+static int semaphore_passed(struct intel_engine_cs *engine)
 {
-	struct drm_i915_private *dev_priv = ring->dev->dev_private;
+	struct drm_i915_private *dev_priv = engine->dev->dev_private;
 	struct intel_engine_cs *signaller;
 	u32 seqno;
 
-	ring->hangcheck.deadlock++;
+	engine->hangcheck.deadlock++;
 
-	signaller = semaphore_waits_for(ring, &seqno);
+	signaller = semaphore_waits_for(engine, &seqno);
 	if (signaller == NULL)
 		return -1;
 
 	/* Prevent pathological recursion due to driver bugs */
-	if (signaller->hangcheck.deadlock >= I915_NUM_RINGS)
+	if (signaller->hangcheck.deadlock >= I915_NUM_ENGINES)
 		return -1;
 
-	if (i915_seqno_passed(signaller->get_seqno(signaller, false), seqno))
+	if (i915_seqno_passed(signaller->get_seqno(signaller), seqno))
 		return 1;
 
 	/* cursory check for an unkickable deadlock */
@@ -2956,23 +3013,22 @@ static int semaphore_passed(struct intel
 
 static void semaphore_clear_deadlocks(struct drm_i915_private *dev_priv)
 {
-	struct intel_engine_cs *ring;
-	int i;
+	struct intel_engine_cs *engine;
 
-	for_each_ring(ring, dev_priv, i)
-		ring->hangcheck.deadlock = 0;
+	for_each_engine(engine, dev_priv)
+		engine->hangcheck.deadlock = 0;
 }
 
-static bool subunits_stuck(struct intel_engine_cs *ring)
+static bool subunits_stuck(struct intel_engine_cs *engine)
 {
 	u32 instdone[I915_NUM_INSTDONE_REG];
 	bool stuck;
 	int i;
 
-	if (ring->id != RCS)
+	if (engine->id != RCS)
 		return true;
 
-	i915_get_extra_instdone(ring->dev, instdone);
+	i915_get_extra_instdone(engine->dev, instdone);
 
 	/* There might be unstable subunit states even when
 	 * actual head is not moving. Filter out the unstable ones by
@@ -2981,49 +3037,44 @@ static bool subunits_stuck(struct intel_
 	 */
 	stuck = true;
 	for (i = 0; i < I915_NUM_INSTDONE_REG; i++) {
-		const u32 tmp = instdone[i] | ring->hangcheck.instdone[i];
+		const u32 tmp = instdone[i] | engine->hangcheck.instdone[i];
 
-		if (tmp != ring->hangcheck.instdone[i])
+		if (tmp != engine->hangcheck.instdone[i])
 			stuck = false;
 
-		ring->hangcheck.instdone[i] |= tmp;
+		engine->hangcheck.instdone[i] |= tmp;
 	}
 
 	return stuck;
 }
 
 static enum intel_ring_hangcheck_action
-head_stuck(struct intel_engine_cs *ring, u64 acthd)
+head_stuck(struct intel_engine_cs *engine, u64 acthd)
 {
-	if (acthd != ring->hangcheck.acthd) {
+	if (acthd != engine->hangcheck.acthd) {
 
 		/* Clear subunit states on head movement */
-		memset(ring->hangcheck.instdone, 0,
-		       sizeof(ring->hangcheck.instdone));
-
-		if (acthd > ring->hangcheck.max_acthd) {
-			ring->hangcheck.max_acthd = acthd;
-			return HANGCHECK_ACTIVE;
-		}
+		memset(engine->hangcheck.instdone, 0,
+		       sizeof(engine->hangcheck.instdone));
 
-		return HANGCHECK_ACTIVE_LOOP;
+		return HANGCHECK_ACTIVE;
 	}
 
-	if (!subunits_stuck(ring))
+	if (!subunits_stuck(engine))
 		return HANGCHECK_ACTIVE;
 
 	return HANGCHECK_HUNG;
 }
 
 static enum intel_ring_hangcheck_action
-ring_stuck(struct intel_engine_cs *ring, u64 acthd)
+ring_stuck(struct intel_engine_cs *engine, u64 acthd)
 {
-	struct drm_device *dev = ring->dev;
+	struct drm_device *dev = engine->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	enum intel_ring_hangcheck_action ha;
 	u32 tmp;
 
-	ha = head_stuck(ring, acthd);
+	ha = head_stuck(engine, acthd);
 	if (ha != HANGCHECK_HUNG)
 		return ha;
 
@@ -3035,24 +3086,24 @@ ring_stuck(struct intel_engine_cs *ring,
 	 * and break the hang. This should work on
 	 * all but the second generation chipsets.
 	 */
-	tmp = I915_READ_CTL(ring);
+	tmp = I915_READ_CTL(engine);
 	if (tmp & RING_WAIT) {
-		i915_handle_error(dev, false,
+		i915_handle_error(dev, 0,
 				  "Kicking stuck wait on %s",
-				  ring->name);
-		I915_WRITE_CTL(ring, tmp);
+				  engine->name);
+		I915_WRITE_CTL(engine, tmp);
 		return HANGCHECK_KICK;
 	}
 
 	if (INTEL_INFO(dev)->gen >= 6 && tmp & RING_WAIT_SEMAPHORE) {
-		switch (semaphore_passed(ring)) {
+		switch (semaphore_passed(engine)) {
 		default:
 			return HANGCHECK_HUNG;
 		case 1:
-			i915_handle_error(dev, false,
+			i915_handle_error(dev, 0,
 					  "Kicking stuck semaphore on %s",
-					  ring->name);
-			I915_WRITE_CTL(ring, tmp);
+					  engine->name);
+			I915_WRITE_CTL(engine, tmp);
 			return HANGCHECK_KICK;
 		case 0:
 			return HANGCHECK_WAIT;
@@ -3062,6 +3113,24 @@ ring_stuck(struct intel_engine_cs *ring,
 	return HANGCHECK_HUNG;
 }
 
+static unsigned kick_waiters(struct intel_engine_cs *engine)
+{
+	struct drm_i915_private *i915 = to_i915(engine->dev);
+	unsigned user_interrupts = READ_ONCE(engine->user_interrupts);
+
+	if (engine->hangcheck.user_interrupts == user_interrupts &&
+	    !test_and_set_bit(engine->id, &i915->gpu_error.missed_irq_rings)) {
+		if (!(i915->gpu_error.test_irq_rings & intel_engine_flag(engine)))
+			DRM_ERROR("Hangcheck timer elapsed... %s idle\n",
+				  engine->name);
+		else
+			DRM_INFO("Fake missed irq on %s\n",
+				 engine->name);
+		wake_up_all(&engine->irq_queue);
+	}
+
+	return user_interrupts;
+}
 /*
  * This is called when the chip hasn't reported back with completed
  * batchbuffers in a long time. We keep track per ring seqno progress and
@@ -3076,13 +3145,14 @@ static void i915_hangcheck_elapsed(struc
 		container_of(work, typeof(*dev_priv),
 			     gpu_error.hangcheck_work.work);
 	struct drm_device *dev = dev_priv->dev;
-	struct intel_engine_cs *ring;
-	int i;
+	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
 	int busy_count = 0, rings_hung = 0;
-	bool stuck[I915_NUM_RINGS] = { 0 };
+	bool stuck[I915_NUM_ENGINES] = { 0 };
 #define BUSY 1
 #define KICK 5
 #define HUNG 20
+#define ACTIVE_DECAY 15
 
 	if (!i915.enable_hangcheck)
 		return;
@@ -3100,33 +3170,37 @@ static void i915_hangcheck_elapsed(struc
 	 */
 	intel_uncore_arm_unclaimed_mmio_detection(dev_priv);
 
-	for_each_ring(ring, dev_priv, i) {
+	for_each_engine_id(engine, dev_priv, id) {
 		u64 acthd;
 		u32 seqno;
+		unsigned user_interrupts;
 		bool busy = true;
 
 		semaphore_clear_deadlocks(dev_priv);
 
-		seqno = ring->get_seqno(ring, false);
-		acthd = intel_ring_get_active_head(ring);
+		/* We don't strictly need an irq-barrier here, as we are not
+		 * serving an interrupt request, be paranoid in case the
+		 * barrier has side-effects (such as preventing a broken
+		 * cacheline snoop) and so be sure that we can see the seqno
+		 * advance. If the seqno should stick, due to a stale
+		 * cacheline, we would erroneously declare the GPU hung.
+		 */
+		if (engine->irq_seqno_barrier)
+			engine->irq_seqno_barrier(engine);
 
-		if (ring->hangcheck.seqno == seqno) {
-			if (ring_idle(ring, seqno)) {
-				ring->hangcheck.action = HANGCHECK_IDLE;
+		acthd = intel_ring_get_active_head(engine);
+		seqno = engine->get_seqno(engine);
 
-				if (waitqueue_active(&ring->irq_queue)) {
-					/* Issue a wake-up to catch stuck h/w. */
-					if (!test_and_set_bit(ring->id, &dev_priv->gpu_error.missed_irq_rings)) {
-						if (!(dev_priv->gpu_error.test_irq_rings & intel_ring_flag(ring)))
-							DRM_ERROR("Hangcheck timer elapsed... %s idle\n",
-								  ring->name);
-						else
-							DRM_INFO("Fake missed irq on %s\n",
-								 ring->name);
-						wake_up_all(&ring->irq_queue);
-					}
+		/* Reset stuck interrupts between batch advances */
+		user_interrupts = 0;
+
+		if (engine->hangcheck.seqno == seqno) {
+			if (ring_idle(engine, seqno)) {
+				engine->hangcheck.action = HANGCHECK_IDLE;
+				if (waitqueue_active(&engine->irq_queue)) {
 					/* Safeguard against driver failure */
-					ring->hangcheck.score += BUSY;
+					user_interrupts = kick_waiters(engine);
+					engine->hangcheck.score += BUSY;
 				} else
 					busy = false;
 			} else {
@@ -3145,58 +3219,60 @@ static void i915_hangcheck_elapsed(struc
 				 * being repeatedly kicked and so responsible
 				 * for stalling the machine.
 				 */
-				ring->hangcheck.action = ring_stuck(ring,
-								    acthd);
+				engine->hangcheck.action = ring_stuck(engine,
+								      acthd);
 
-				switch (ring->hangcheck.action) {
+				switch (engine->hangcheck.action) {
 				case HANGCHECK_IDLE:
 				case HANGCHECK_WAIT:
-				case HANGCHECK_ACTIVE:
 					break;
-				case HANGCHECK_ACTIVE_LOOP:
-					ring->hangcheck.score += BUSY;
+				case HANGCHECK_ACTIVE:
+					engine->hangcheck.score += BUSY;
 					break;
 				case HANGCHECK_KICK:
-					ring->hangcheck.score += KICK;
+					engine->hangcheck.score += KICK;
 					break;
 				case HANGCHECK_HUNG:
-					ring->hangcheck.score += HUNG;
-					stuck[i] = true;
+					engine->hangcheck.score += HUNG;
+					stuck[id] = true;
 					break;
 				}
 			}
 		} else {
-			ring->hangcheck.action = HANGCHECK_ACTIVE;
+			engine->hangcheck.action = HANGCHECK_ACTIVE;
 
 			/* Gradually reduce the count so that we catch DoS
 			 * attempts across multiple batches.
 			 */
-			if (ring->hangcheck.score > 0)
-				ring->hangcheck.score--;
+			if (engine->hangcheck.score > 0)
+				engine->hangcheck.score -= ACTIVE_DECAY;
+			if (engine->hangcheck.score < 0)
+				engine->hangcheck.score = 0;
 
 			/* Clear head and subunit states on seqno movement */
-			ring->hangcheck.acthd = ring->hangcheck.max_acthd = 0;
+			acthd = 0;
 
-			memset(ring->hangcheck.instdone, 0,
-			       sizeof(ring->hangcheck.instdone));
+			memset(engine->hangcheck.instdone, 0,
+			       sizeof(engine->hangcheck.instdone));
 		}
 
-		ring->hangcheck.seqno = seqno;
-		ring->hangcheck.acthd = acthd;
+		engine->hangcheck.seqno = seqno;
+		engine->hangcheck.acthd = acthd;
+		engine->hangcheck.user_interrupts = user_interrupts;
 		busy_count += busy;
 	}
 
-	for_each_ring(ring, dev_priv, i) {
-		if (ring->hangcheck.score >= HANGCHECK_SCORE_RING_HUNG) {
+	for_each_engine_id(engine, dev_priv, id) {
+		if (engine->hangcheck.score >= HANGCHECK_SCORE_RING_HUNG) {
 			DRM_INFO("%s on %s\n",
-				 stuck[i] ? "stuck" : "no progress",
-				 ring->name);
-			rings_hung++;
+				 stuck[id] ? "stuck" : "no progress",
+				 engine->name);
+			rings_hung |= intel_engine_flag(engine);
 		}
 	}
 
 	if (rings_hung) {
-		i915_handle_error(dev, true, "Ring hung");
+		i915_handle_error(dev, rings_hung, "Engine(s) hung");
 		goto out;
 	}
 
@@ -3267,6 +3343,55 @@ static void gen5_gt_irq_reset(struct drm
 		GEN5_IRQ_RESET(GEN6_PM);
 }
 
+static void vlv_display_irq_reset(struct drm_i915_private *dev_priv)
+{
+	enum pipe pipe;
+
+	if (IS_CHERRYVIEW(dev_priv))
+		I915_WRITE(DPINVGTT, DPINVGTT_STATUS_MASK_CHV);
+	else
+		I915_WRITE(DPINVGTT, DPINVGTT_STATUS_MASK);
+
+	i915_hotplug_interrupt_update_locked(dev_priv, 0xffffffff, 0);
+	I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
+
+	for_each_pipe(dev_priv, pipe) {
+		I915_WRITE(PIPESTAT(pipe),
+			   PIPE_FIFO_UNDERRUN_STATUS |
+			   PIPESTAT_INT_STATUS_MASK);
+		dev_priv->pipestat_irq_mask[pipe] = 0;
+	}
+
+	GEN5_IRQ_RESET(VLV_);
+	dev_priv->irq_mask = ~0;
+}
+
+static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv)
+{
+	u32 pipestat_mask;
+	u32 enable_mask;
+	enum pipe pipe;
+
+	pipestat_mask = PLANE_FLIP_DONE_INT_STATUS_VLV |
+			PIPE_CRC_DONE_INTERRUPT_STATUS;
+
+	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS);
+	for_each_pipe(dev_priv, pipe)
+		i915_enable_pipestat(dev_priv, pipe, pipestat_mask);
+
+	enable_mask = I915_DISPLAY_PORT_INTERRUPT |
+		I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
+		I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
+	if (IS_CHERRYVIEW(dev_priv))
+		enable_mask |= I915_DISPLAY_PIPE_C_EVENT_INTERRUPT;
+
+	WARN_ON(dev_priv->irq_mask != ~0);
+
+	dev_priv->irq_mask = ~enable_mask;
+
+	GEN5_IRQ_INIT(VLV_, dev_priv->irq_mask, enable_mask);
+}
+
 /* drm_dma.h hooks
 */
 static void ironlake_irq_reset(struct drm_device *dev)
@@ -3284,34 +3409,19 @@ static void ironlake_irq_reset(struct dr
 	ibx_irq_reset(dev);
 }
 
-static void vlv_display_irq_reset(struct drm_i915_private *dev_priv)
-{
-	enum pipe pipe;
-
-	i915_hotplug_interrupt_update(dev_priv, 0xFFFFFFFF, 0);
-	I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
-
-	for_each_pipe(dev_priv, pipe)
-		I915_WRITE(PIPESTAT(pipe), 0xffff);
-
-	GEN5_IRQ_RESET(VLV_);
-}
-
 static void valleyview_irq_preinstall(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	/* VLV magic */
-	I915_WRITE(VLV_IMR, 0);
-	I915_WRITE(RING_IMR(RENDER_RING_BASE), 0);
-	I915_WRITE(RING_IMR(GEN6_BSD_RING_BASE), 0);
-	I915_WRITE(RING_IMR(BLT_RING_BASE), 0);
+	I915_WRITE(VLV_MASTER_IER, 0);
+	POSTING_READ(VLV_MASTER_IER);
 
 	gen5_gt_irq_reset(dev);
 
-	I915_WRITE(DPINVGTT, DPINVGTT_STATUS_MASK);
-
-	vlv_display_irq_reset(dev_priv);
+	spin_lock_irq(&dev_priv->irq_lock);
+	if (dev_priv->display_irqs_enabled)
+		vlv_display_irq_reset(dev_priv);
+	spin_unlock_irq(&dev_priv->irq_lock);
 }
 
 static void gen8_gt_irq_reset(struct drm_i915_private *dev_priv)
@@ -3384,9 +3494,10 @@ static void cherryview_irq_preinstall(st
 
 	GEN5_IRQ_RESET(GEN8_PCU_);
 
-	I915_WRITE(DPINVGTT, DPINVGTT_STATUS_MASK_CHV);
-
-	vlv_display_irq_reset(dev_priv);
+	spin_lock_irq(&dev_priv->irq_lock);
+	if (dev_priv->display_irqs_enabled)
+		vlv_display_irq_reset(dev_priv);
+	spin_unlock_irq(&dev_priv->irq_lock);
 }
 
 static u32 intel_hpd_enabled_irqs(struct drm_device *dev,
@@ -3506,6 +3617,26 @@ static void bxt_hpd_irq_setup(struct drm
 	hotplug = I915_READ(PCH_PORT_HOTPLUG);
 	hotplug |= PORTC_HOTPLUG_ENABLE | PORTB_HOTPLUG_ENABLE |
 		PORTA_HOTPLUG_ENABLE;
+
+	DRM_DEBUG_KMS("Invert bit setting: hp_ctl:%x hp_port:%x\n",
+		      hotplug, enabled_irqs);
+	hotplug &= ~BXT_DDI_HPD_INVERT_MASK;
+
+	/*
+	 * For BXT invert bit has to be set based on AOB design
+	 * for HPD detection logic, update it based on VBT fields.
+	 */
+
+	if ((enabled_irqs & BXT_DE_PORT_HP_DDIA) &&
+	    intel_bios_is_port_hpd_inverted(dev_priv, PORT_A))
+		hotplug |= BXT_DDIA_HPD_INVERT;
+	if ((enabled_irqs & BXT_DE_PORT_HP_DDIB) &&
+	    intel_bios_is_port_hpd_inverted(dev_priv, PORT_B))
+		hotplug |= BXT_DDIB_HPD_INVERT;
+	if ((enabled_irqs & BXT_DE_PORT_HP_DDIC) &&
+	    intel_bios_is_port_hpd_inverted(dev_priv, PORT_C))
+		hotplug |= BXT_DDIC_HPD_INVERT;
+
 	I915_WRITE(PCH_PORT_HOTPLUG, hotplug);
 }
 
@@ -3613,74 +3744,6 @@ static int ironlake_irq_postinstall(stru
 	return 0;
 }
 
-static void valleyview_display_irqs_install(struct drm_i915_private *dev_priv)
-{
-	u32 pipestat_mask;
-	u32 iir_mask;
-	enum pipe pipe;
-
-	pipestat_mask = PIPESTAT_INT_STATUS_MASK |
-			PIPE_FIFO_UNDERRUN_STATUS;
-
-	for_each_pipe(dev_priv, pipe)
-		I915_WRITE(PIPESTAT(pipe), pipestat_mask);
-	POSTING_READ(PIPESTAT(PIPE_A));
-
-	pipestat_mask = PLANE_FLIP_DONE_INT_STATUS_VLV |
-			PIPE_CRC_DONE_INTERRUPT_STATUS;
-
-	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS);
-	for_each_pipe(dev_priv, pipe)
-		      i915_enable_pipestat(dev_priv, pipe, pipestat_mask);
-
-	iir_mask = I915_DISPLAY_PORT_INTERRUPT |
-		   I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
-		   I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
-	if (IS_CHERRYVIEW(dev_priv))
-		iir_mask |= I915_DISPLAY_PIPE_C_EVENT_INTERRUPT;
-	dev_priv->irq_mask &= ~iir_mask;
-
-	I915_WRITE(VLV_IIR, iir_mask);
-	I915_WRITE(VLV_IIR, iir_mask);
-	I915_WRITE(VLV_IER, ~dev_priv->irq_mask);
-	I915_WRITE(VLV_IMR, dev_priv->irq_mask);
-	POSTING_READ(VLV_IMR);
-}
-
-static void valleyview_display_irqs_uninstall(struct drm_i915_private *dev_priv)
-{
-	u32 pipestat_mask;
-	u32 iir_mask;
-	enum pipe pipe;
-
-	iir_mask = I915_DISPLAY_PORT_INTERRUPT |
-		   I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
-		   I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
-	if (IS_CHERRYVIEW(dev_priv))
-		iir_mask |= I915_DISPLAY_PIPE_C_EVENT_INTERRUPT;
-
-	dev_priv->irq_mask |= iir_mask;
-	I915_WRITE(VLV_IMR, dev_priv->irq_mask);
-	I915_WRITE(VLV_IER, ~dev_priv->irq_mask);
-	I915_WRITE(VLV_IIR, iir_mask);
-	I915_WRITE(VLV_IIR, iir_mask);
-	POSTING_READ(VLV_IIR);
-
-	pipestat_mask = PLANE_FLIP_DONE_INT_STATUS_VLV |
-			PIPE_CRC_DONE_INTERRUPT_STATUS;
-
-	i915_disable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS);
-	for_each_pipe(dev_priv, pipe)
-		i915_disable_pipestat(dev_priv, pipe, pipestat_mask);
-
-	pipestat_mask = PIPESTAT_INT_STATUS_MASK |
-			PIPE_FIFO_UNDERRUN_STATUS;
-
-	for_each_pipe(dev_priv, pipe)
-		I915_WRITE(PIPESTAT(pipe), pipestat_mask);
-	POSTING_READ(PIPESTAT(PIPE_A));
-}
-
 void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv)
 {
 	assert_spin_locked(&dev_priv->irq_lock);
@@ -3690,8 +3753,10 @@ void valleyview_enable_display_irqs(stru
 
 	dev_priv->display_irqs_enabled = true;
 
-	if (intel_irqs_enabled(dev_priv))
-		valleyview_display_irqs_install(dev_priv);
+	if (intel_irqs_enabled(dev_priv)) {
+		vlv_display_irq_reset(dev_priv);
+		vlv_display_irq_postinstall(dev_priv);
+	}
 }
 
 void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv)
@@ -3704,45 +3769,23 @@ void valleyview_disable_display_irqs(str
 	dev_priv->display_irqs_enabled = false;
 
 	if (intel_irqs_enabled(dev_priv))
-		valleyview_display_irqs_uninstall(dev_priv);
+		vlv_display_irq_reset(dev_priv);
 }
 
-static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv)
-{
-	dev_priv->irq_mask = ~0;
-
-	i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0);
-	POSTING_READ(PORT_HOTPLUG_EN);
-
-	I915_WRITE(VLV_IIR, 0xffffffff);
-	I915_WRITE(VLV_IIR, 0xffffffff);
-	I915_WRITE(VLV_IER, ~dev_priv->irq_mask);
-	I915_WRITE(VLV_IMR, dev_priv->irq_mask);
-	POSTING_READ(VLV_IMR);
-
-	/* Interrupt setup is already guaranteed to be single-threaded, this is
-	 * just to make the assert_spin_locked check happy. */
-	spin_lock_irq(&dev_priv->irq_lock);
-	if (dev_priv->display_irqs_enabled)
-		valleyview_display_irqs_install(dev_priv);
-	spin_unlock_irq(&dev_priv->irq_lock);
-}
 
 static int valleyview_irq_postinstall(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	vlv_display_irq_postinstall(dev_priv);
-
 	gen5_gt_irq_postinstall(dev);
 
-	/* ack & enable invalid PTE error interrupts */
-#if 0 /* FIXME: add support to irq handler for checking these bits */
-	I915_WRITE(DPINVGTT, DPINVGTT_STATUS_MASK);
-	I915_WRITE(DPINVGTT, DPINVGTT_EN_MASK);
-#endif
+	spin_lock_irq(&dev_priv->irq_lock);
+	if (dev_priv->display_irqs_enabled)
+		vlv_display_irq_postinstall(dev_priv);
+	spin_unlock_irq(&dev_priv->irq_lock);
 
 	I915_WRITE(VLV_MASTER_IER, MASTER_INTERRUPT_ENABLE);
+	POSTING_READ(VLV_MASTER_IER);
 
 	return 0;
 }
@@ -3753,7 +3796,6 @@ static void gen8_gt_irq_postinstall(stru
 	uint32_t gt_interrupts[] = {
 		GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT |
 			GT_CONTEXT_SWITCH_INTERRUPT << GEN8_RCS_IRQ_SHIFT |
-			GT_RENDER_L3_PARITY_ERROR_INTERRUPT |
 			GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT |
 			GT_CONTEXT_SWITCH_INTERRUPT << GEN8_BCS_IRQ_SHIFT,
 		GT_RENDER_USER_INTERRUPT << GEN8_VCS1_IRQ_SHIFT |
@@ -3765,6 +3807,9 @@ static void gen8_gt_irq_postinstall(stru
 			GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VECS_IRQ_SHIFT
 		};
 
+	if (HAS_L3_DPF(dev_priv))
+		gt_interrupts[0] |= GT_RENDER_L3_PARITY_ERROR_INTERRUPT;
+
 	dev_priv->pm_irq_mask = 0xffffffff;
 	GEN8_IRQ_INIT_NDX(GT, 0, ~gt_interrupts[0], gt_interrupts[0]);
 	GEN8_IRQ_INIT_NDX(GT, 1, ~gt_interrupts[1], gt_interrupts[1]);
@@ -3832,7 +3877,7 @@ static int gen8_irq_postinstall(struct d
 	if (HAS_PCH_SPLIT(dev))
 		ibx_irq_postinstall(dev);
 
-	I915_WRITE(GEN8_MASTER_IRQ, DE_MASTER_IRQ_CONTROL);
+	I915_WRITE(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
 	POSTING_READ(GEN8_MASTER_IRQ);
 
 	return 0;
@@ -3842,11 +3887,14 @@ static int cherryview_irq_postinstall(st
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	vlv_display_irq_postinstall(dev_priv);
-
 	gen8_gt_irq_postinstall(dev_priv);
 
-	I915_WRITE(GEN8_MASTER_IRQ, MASTER_INTERRUPT_ENABLE);
+	spin_lock_irq(&dev_priv->irq_lock);
+	if (dev_priv->display_irqs_enabled)
+		vlv_display_irq_postinstall(dev_priv);
+	spin_unlock_irq(&dev_priv->irq_lock);
+
+	I915_WRITE(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
 	POSTING_READ(GEN8_MASTER_IRQ);
 
 	return 0;
@@ -3862,20 +3910,6 @@ static void gen8_irq_uninstall(struct dr
 	gen8_irq_reset(dev);
 }
 
-static void vlv_display_irq_uninstall(struct drm_i915_private *dev_priv)
-{
-	/* Interrupt setup is already guaranteed to be single-threaded, this is
-	 * just to make the assert_spin_locked check happy. */
-	spin_lock_irq(&dev_priv->irq_lock);
-	if (dev_priv->display_irqs_enabled)
-		valleyview_display_irqs_uninstall(dev_priv);
-	spin_unlock_irq(&dev_priv->irq_lock);
-
-	vlv_display_irq_reset(dev_priv);
-
-	dev_priv->irq_mask = ~0;
-}
-
 static void valleyview_irq_uninstall(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3884,12 +3918,16 @@ static void valleyview_irq_uninstall(str
 		return;
 
 	I915_WRITE(VLV_MASTER_IER, 0);
+	POSTING_READ(VLV_MASTER_IER);
 
 	gen5_gt_irq_reset(dev);
 
 	I915_WRITE(HWSTAM, 0xffffffff);
 
-	vlv_display_irq_uninstall(dev_priv);
+	spin_lock_irq(&dev_priv->irq_lock);
+	if (dev_priv->display_irqs_enabled)
+		vlv_display_irq_reset(dev_priv);
+	spin_unlock_irq(&dev_priv->irq_lock);
 }
 
 static void cherryview_irq_uninstall(struct drm_device *dev)
@@ -3906,7 +3944,10 @@ static void cherryview_irq_uninstall(str
 
 	GEN5_IRQ_RESET(GEN8_PCU_);
 
-	vlv_display_irq_uninstall(dev_priv);
+	spin_lock_irq(&dev_priv->irq_lock);
+	if (dev_priv->display_irqs_enabled)
+		vlv_display_irq_reset(dev_priv);
+	spin_unlock_irq(&dev_priv->irq_lock);
 }
 
 static void ironlake_irq_uninstall(struct drm_device *dev)
@@ -4044,7 +4085,7 @@ static irqreturn_t i8xx_irq_handler(int
 		new_iir = I915_READ16(IIR); /* Flush posted writes */
 
 		if (iir & I915_USER_INTERRUPT)
-			notify_ring(&dev_priv->ring[RCS]);
+			notify_ring(&dev_priv->engine[RCS]);
 
 		for_each_pipe(dev_priv, pipe) {
 			int plane = pipe;
@@ -4233,14 +4274,17 @@ static irqreturn_t i915_irq_handler(int
 
 		/* Consume port.  Then clear IIR or we'll miss events */
 		if (I915_HAS_HOTPLUG(dev) &&
-		    iir & I915_DISPLAY_PORT_INTERRUPT)
-			i9xx_hpd_irq_handler(dev);
+		    iir & I915_DISPLAY_PORT_INTERRUPT) {
+			u32 hotplug_status = i9xx_hpd_irq_ack(dev_priv);
+			if (hotplug_status)
+				i9xx_hpd_irq_handler(dev, hotplug_status);
+		}
 
 		I915_WRITE(IIR, iir & ~flip_mask);
 		new_iir = I915_READ(IIR); /* Flush posted writes */
 
 		if (iir & I915_USER_INTERRUPT)
-			notify_ring(&dev_priv->ring[RCS]);
+			notify_ring(&dev_priv->engine[RCS]);
 
 		for_each_pipe(dev_priv, pipe) {
 			int plane = pipe;
@@ -4463,16 +4507,19 @@ static irqreturn_t i965_irq_handler(int
 		ret = IRQ_HANDLED;
 
 		/* Consume port.  Then clear IIR or we'll miss events */
-		if (iir & I915_DISPLAY_PORT_INTERRUPT)
-			i9xx_hpd_irq_handler(dev);
+		if (iir & I915_DISPLAY_PORT_INTERRUPT) {
+			u32 hotplug_status = i9xx_hpd_irq_ack(dev_priv);
+			if (hotplug_status)
+				i9xx_hpd_irq_handler(dev, hotplug_status);
+		}
 
 		I915_WRITE(IIR, iir & ~flip_mask);
 		new_iir = I915_READ(IIR); /* Flush posted writes */
 
 		if (iir & I915_USER_INTERRUPT)
-			notify_ring(&dev_priv->ring[RCS]);
+			notify_ring(&dev_priv->engine[RCS]);
 		if (iir & I915_BSD_USER_INTERRUPT)
-			notify_ring(&dev_priv->ring[VCS]);
+			notify_ring(&dev_priv->engine[VCS]);
 
 		for_each_pipe(dev_priv, pipe) {
 			if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS &&
@@ -4567,8 +4614,6 @@ void intel_irq_init(struct drm_i915_priv
 	INIT_DELAYED_WORK(&dev_priv->gpu_error.hangcheck_work,
 			  i915_hangcheck_elapsed);
 
-	pm_qos_add_request(&dev_priv->pm_qos, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
-
 	if (IS_GEN2(dev_priv)) {
 		dev->max_vblank_count = 0;
 		dev->driver->get_vblank_counter = i8xx_get_vblank_counter;
@@ -4616,7 +4661,7 @@ void intel_irq_init(struct drm_i915_priv
 		dev->driver->disable_vblank = gen8_disable_vblank;
 		if (IS_BROXTON(dev))
 			dev_priv->display.hpd_irq_setup = bxt_hpd_irq_setup;
-		else if (HAS_PCH_SPT(dev))
+		else if (HAS_PCH_SPT(dev) || HAS_PCH_KBP(dev))
 			dev_priv->display.hpd_irq_setup = spt_hpd_irq_setup;
 		else
 			dev_priv->display.hpd_irq_setup = ilk_hpd_irq_setup;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_params.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_params.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_params.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_params.c	2016-07-24 15:23:50.000000000 -0400
@@ -56,6 +56,8 @@ struct i915_params i915 __read_mostly =
 	.edp_vswing = 0,
 	.enable_guc_submission = false,
 	.guc_log_level = -1,
+	.enable_dp_mst = true,
+	.inject_load_failure = 0,
 };
 
 module_param_named(modeset, i915.modeset, int, 0400);
@@ -201,3 +203,10 @@ MODULE_PARM_DESC(enable_guc_submission,
 module_param_named(guc_log_level, i915.guc_log_level, int, 0400);
 MODULE_PARM_DESC(guc_log_level,
 	"GuC firmware logging level (-1:disabled (default), 0-3:enabled)");
+
+module_param_named_unsafe(enable_dp_mst, i915.enable_dp_mst, bool, 0600);
+MODULE_PARM_DESC(enable_dp_mst,
+	"Enable multi-stream transport (MST) for new DisplayPort sinks. (default: true)");
+module_param_named_unsafe(inject_load_failure, i915.inject_load_failure, uint, 0400);
+MODULE_PARM_DESC(inject_load_failure,
+	"Force an error after a number of failure check points (0:disabled (default), N:force failure at the Nth failure check point)");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_params.h linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_params.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_params.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_params.h	2016-07-24 15:23:50.000000000 -0400
@@ -49,6 +49,7 @@ struct i915_params {
 	int use_mmio_flip;
 	int mmio_debug;
 	int edp_vswing;
+	unsigned int inject_load_failure;
 	/* leave bools at the end to not create holes */
 	bool enable_hangcheck;
 	bool fastboot;
@@ -59,6 +60,7 @@ struct i915_params {
 	bool enable_guc_submission;
 	bool verbose_state_checks;
 	bool nuclear_pageflip;
+	bool enable_dp_mst;
 };
 
 extern struct i915_params i915 __read_mostly;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_reg.h linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_reg.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_reg.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_reg.h	2016-07-24 15:23:50.000000000 -0400
@@ -79,6 +79,16 @@ static inline bool i915_mmio_reg_valid(i
 
 /* PCI config space */
 
+#define MCHBAR_I915 0x44
+#define MCHBAR_I965 0x48
+#define MCHBAR_SIZE (4 * 4096)
+
+#define DEVEN 0x54
+#define   DEVEN_MCHBAR_EN (1 << 28)
+
+#define BSM 0x5c
+#define   BSM_MASK (0xFFFF << 20)
+
 #define HPLLCC	0xc0 /* 85x only */
 #define   GC_CLOCK_CONTROL_MASK		(0x7 << 0)
 #define   GC_CLOCK_133_200		(0 << 0)
@@ -90,6 +100,16 @@ static inline bool i915_mmio_reg_valid(i
 #define   GC_CLOCK_166_266		(6 << 0)
 #define   GC_CLOCK_166_250		(7 << 0)
 
+#define I915_GDRST 0xc0 /* PCI config register */
+#define   GRDOM_FULL		(0 << 2)
+#define   GRDOM_RENDER		(1 << 2)
+#define   GRDOM_MEDIA		(3 << 2)
+#define   GRDOM_MASK		(3 << 2)
+#define   GRDOM_RESET_STATUS	(1 << 1)
+#define   GRDOM_RESET_ENABLE	(1 << 0)
+
+#define GCDGMBUS 0xcc
+
 #define GCFGC2	0xda
 #define GCFGC	0xf0 /* 915+ only */
 #define   GC_LOW_FREQUENCY_ENABLE	(1 << 7)
@@ -121,18 +141,16 @@ static inline bool i915_mmio_reg_valid(i
 #define   I915_GC_RENDER_CLOCK_166_MHZ	(0 << 0)
 #define   I915_GC_RENDER_CLOCK_200_MHZ	(1 << 0)
 #define   I915_GC_RENDER_CLOCK_333_MHZ	(4 << 0)
-#define GCDGMBUS 0xcc
-#define PCI_LBPC 0xf4 /* legacy/combination backlight modes, also called LBB */
 
+#define ASLE	0xe4
+#define ASLS	0xfc
+
+#define SWSCI	0xe8
+#define   SWSCI_SCISEL	(1 << 15)
+#define   SWSCI_GSSCIE	(1 << 0)
+
+#define LBPC 0xf4 /* legacy/combination backlight modes, also called LBB */
 
-/* Graphics reset regs */
-#define I915_GDRST 0xc0 /* PCI config register */
-#define  GRDOM_FULL	(0<<2)
-#define  GRDOM_RENDER	(1<<2)
-#define  GRDOM_MEDIA	(3<<2)
-#define  GRDOM_MASK	(3<<2)
-#define  GRDOM_RESET_STATUS (1<<1)
-#define  GRDOM_RESET_ENABLE (1<<0)
 
 #define ILK_GDSR _MMIO(MCHBAR_MIRROR_BASE + 0x2ca4)
 #define  ILK_GRDOM_FULL		(0<<1)
@@ -164,6 +182,9 @@ static inline bool i915_mmio_reg_valid(i
 #define  GEN6_GRDOM_RENDER		(1 << 1)
 #define  GEN6_GRDOM_MEDIA		(1 << 2)
 #define  GEN6_GRDOM_BLT			(1 << 3)
+#define  GEN6_GRDOM_VECS		(1 << 4)
+#define  GEN9_GRDOM_GUC			(1 << 5)
+#define  GEN8_GRDOM_MEDIA2		(1 << 7)
 
 #define RING_PP_DIR_BASE(ring)		_MMIO((ring)->mmio_base+0x228)
 #define RING_PP_DIR_BASE_READ(ring)	_MMIO((ring)->mmio_base+0x518)
@@ -199,6 +220,9 @@ static inline bool i915_mmio_reg_valid(i
 #define   ECOCHK_PPGTT_WT_HSW		(0x2<<3)
 #define   ECOCHK_PPGTT_WB_HSW		(0x3<<3)
 
+#define GEN8_CONFIG0			_MMIO(0xD00)
+#define  GEN9_DEFAULT_FIXES		(1 << 3 | 1 << 2 | 1 << 1)
+
 #define GAC_ECO_BITS			_MMIO(0x14090)
 #define   ECOBITS_SNB_BIT		(1<<13)
 #define   ECOBITS_PPGTT_CACHE64B	(3<<8)
@@ -586,6 +610,10 @@ static inline bool i915_mmio_reg_valid(i
 #define GEN7_GPGPU_DISPATCHDIMY         _MMIO(0x2504)
 #define GEN7_GPGPU_DISPATCHDIMZ         _MMIO(0x2508)
 
+/* There are the 16 64-bit CS General Purpose Registers */
+#define HSW_CS_GPR(n)                   _MMIO(0x2600 + (n) * 8)
+#define HSW_CS_GPR_UDW(n)               _MMIO(0x2600 + (n) * 8 + 4)
+
 #define OACONTROL _MMIO(0x2360)
 
 #define _GEN7_PIPEA_DE_LOAD_SL	0x70068
@@ -621,6 +649,10 @@ static inline bool i915_mmio_reg_valid(i
 #define   IOSF_PORT_GPIO_SC			0x48
 #define   IOSF_PORT_GPIO_SUS			0xa8
 #define   IOSF_PORT_CCU				0xa9
+#define   CHV_IOSF_PORT_GPIO_N			0x13
+#define   CHV_IOSF_PORT_GPIO_SE			0x48
+#define   CHV_IOSF_PORT_GPIO_E			0xa8
+#define   CHV_IOSF_PORT_GPIO_SW			0xb2
 #define VLV_IOSF_DATA				_MMIO(VLV_DISPLAY_BASE + 0x2104)
 #define VLV_IOSF_ADDR				_MMIO(VLV_DISPLAY_BASE + 0x2108)
 
@@ -785,7 +817,9 @@ enum skl_disp_power_wells {
 #define  DSI_PLL_M1_DIV_SHIFT			0
 #define  DSI_PLL_M1_DIV_MASK			(0x1ff << 0)
 #define CCK_CZ_CLOCK_CONTROL			0x62
+#define CCK_GPLL_CLOCK_CONTROL			0x67
 #define CCK_DISPLAY_CLOCK_CONTROL		0x6b
+#define CCK_DISPLAY_REF_CLOCK_CONTROL		0x6c
 #define  CCK_TRUNK_FORCE_ON			(1 << 17)
 #define  CCK_TRUNK_FORCE_OFF			(1 << 16)
 #define  CCK_FREQUENCY_STATUS			(0x1f << 8)
@@ -1317,6 +1351,7 @@ enum skl_disp_power_wells {
 #define _PORT_CL1CM_DW0_A		0x162000
 #define _PORT_CL1CM_DW0_BC		0x6C000
 #define   PHY_POWER_GOOD		(1 << 16)
+#define   PHY_RESERVED			(1 << 7)
 #define BXT_PORT_CL1CM_DW0(phy)		_BXT_PHY((phy), _PORT_CL1CM_DW0_BC, \
 							_PORT_CL1CM_DW0_A)
 
@@ -1361,14 +1396,10 @@ enum skl_disp_power_wells {
 
 #define _PORT_REF_DW6_A			0x162198
 #define _PORT_REF_DW6_BC		0x6C198
-/*
- * FIXME: BSpec/CHV ConfigDB disagrees on the following two fields, fix them
- * after testing.
- */
-#define   GRC_CODE_SHIFT		23
-#define   GRC_CODE_MASK			(0x1FF << GRC_CODE_SHIFT)
+#define   GRC_CODE_SHIFT		24
+#define   GRC_CODE_MASK			(0xFF << GRC_CODE_SHIFT)
 #define   GRC_CODE_FAST_SHIFT		16
-#define   GRC_CODE_FAST_MASK		(0x7F << GRC_CODE_FAST_SHIFT)
+#define   GRC_CODE_FAST_MASK		(0xFF << GRC_CODE_FAST_SHIFT)
 #define   GRC_CODE_SLOW_SHIFT		8
 #define   GRC_CODE_SLOW_MASK		(0xFF << GRC_CODE_SLOW_SHIFT)
 #define   GRC_CODE_NOM_MASK		0xFF
@@ -1641,6 +1672,9 @@ enum skl_disp_power_wells {
 
 #define GEN7_TLB_RD_ADDR	_MMIO(0x4700)
 
+#define GAMT_CHKN_BIT_REG	_MMIO(0x4ab8)
+#define   GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING	(1<<28)
+
 #if 0
 #define PRB0_TAIL	_MMIO(0x2030)
 #define PRB0_HEAD	_MMIO(0x2034)
@@ -1776,6 +1810,22 @@ enum skl_disp_power_wells {
 #define   GEN9_IZ_HASHING_MASK(slice)			(0x3 << ((slice) * 2))
 #define   GEN9_IZ_HASHING(slice, val)			((val) << ((slice) * 2))
 
+/* chicken reg for WaConextSwitchWithConcurrentTLBInvalidate */
+#define GEN9_CSFE_CHICKEN1_RCS _MMIO(0x20D4)
+#define   GEN9_PREEMPT_GPGPU_SYNC_SWITCH_DISABLE (1 << 2)
+
+/* WaClearTdlStateAckDirtyBits */
+#define GEN8_STATE_ACK		_MMIO(0x20F0)
+#define GEN9_STATE_ACK_SLICE1	_MMIO(0x20F8)
+#define GEN9_STATE_ACK_SLICE2	_MMIO(0x2100)
+#define   GEN9_STATE_ACK_TDL0 (1 << 12)
+#define   GEN9_STATE_ACK_TDL1 (1 << 13)
+#define   GEN9_STATE_ACK_TDL2 (1 << 14)
+#define   GEN9_STATE_ACK_TDL3 (1 << 15)
+#define   GEN9_SUBSLICE_TDL_ACK_BITS \
+	(GEN9_STATE_ACK_TDL3 | GEN9_STATE_ACK_TDL2 | \
+	 GEN9_STATE_ACK_TDL1 | GEN9_STATE_ACK_TDL0)
+
 #define GFX_MODE	_MMIO(0x2520)
 #define GFX_MODE_GEN7	_MMIO(0x229c)
 #define RING_MODE_GEN7(ring)	_MMIO((ring)->mmio_base+0x29c)
@@ -1795,6 +1845,7 @@ enum skl_disp_power_wells {
 
 #define VLV_DISPLAY_BASE 0x180000
 #define VLV_MIPI_BASE VLV_DISPLAY_BASE
+#define BXT_MIPI_BASE 0x60000
 
 #define VLV_GU_CTL0	_MMIO(VLV_DISPLAY_BASE + 0x2030)
 #define VLV_GU_CTL1	_MMIO(VLV_DISPLAY_BASE + 0x2034)
@@ -2159,6 +2210,8 @@ enum skl_disp_power_wells {
 #define ILK_DPFC_STATUS		_MMIO(0x43210)
 #define ILK_DPFC_FENCE_YOFF	_MMIO(0x43218)
 #define ILK_DPFC_CHICKEN	_MMIO(0x43224)
+#define   ILK_DPFC_DISABLE_DUMMY0 (1<<8)
+#define   ILK_DPFC_NUKE_ON_ANY_MODIFICATION	(1<<23)
 #define ILK_FBC_RT_BASE		_MMIO(0x2128)
 #define   ILK_FBC_RT_VALID	(1<<0)
 #define   SNB_FBC_FRONT_BUFFER	(1<<1)
@@ -2923,6 +2976,15 @@ enum skl_disp_power_wells {
 				INTERVAL_1_33_US(us)) : \
 				INTERVAL_1_28_US(us))
 
+#define INTERVAL_1_28_TO_US(interval)  (((interval) << 7) / 100)
+#define INTERVAL_1_33_TO_US(interval)  (((interval) << 2) / 3)
+#define INTERVAL_0_833_TO_US(interval) (((interval) * 5)  / 6)
+#define GT_PM_INTERVAL_TO_US(dev_priv, interval) (IS_GEN9(dev_priv) ? \
+                           (IS_BROXTON(dev_priv) ? \
+                           INTERVAL_0_833_TO_US(interval) : \
+                           INTERVAL_1_33_TO_US(interval)) : \
+                           INTERVAL_1_28_TO_US(interval))
+
 /*
  * Logical Context regs
  */
@@ -4784,6 +4846,10 @@ enum skl_disp_power_wells {
 #define  CBR_PND_DEADLINE_DISABLE	(1<<31)
 #define  CBR_PWM_CLOCK_MUX_SELECT	(1<<30)
 
+#define CBR4_VLV			_MMIO(VLV_DISPLAY_BASE + 0x70450)
+#define  CBR_DPLLBMD_PIPE_C		(1<<29)
+#define  CBR_DPLLBMD_PIPE_B		(1<<18)
+
 /* FIFO watermark sizes etc */
 #define G4X_FIFO_LINE_SIZE	64
 #define I915_FIFO_LINE_SIZE	64
@@ -5977,6 +6043,7 @@ enum skl_disp_power_wells {
 #define CHICKEN_PAR1_1		_MMIO(0x42080)
 #define  DPA_MASK_VBLANK_SRD	(1 << 15)
 #define  FORCE_ARB_IDLE_PLANES	(1 << 14)
+#define  SKL_EDP_PSR_FIX_RDWRAP	(1 << 3)
 
 #define _CHICKEN_PIPESL_1_A	0x420b0
 #define _CHICKEN_PIPESL_1_B	0x420b4
@@ -5985,6 +6052,7 @@ enum skl_disp_power_wells {
 #define CHICKEN_PIPESL_1(pipe) _MMIO_PIPE(pipe, _CHICKEN_PIPESL_1_A, _CHICKEN_PIPESL_1_B)
 
 #define DISP_ARB_CTL	_MMIO(0x45000)
+#define  DISP_FBC_MEMORY_WAKE		(1<<31)
 #define  DISP_TILE_SURFACE_SWIZZLING	(1<<13)
 #define  DISP_FBC_WM_DIS		(1<<15)
 #define DISP_ARB_CTL2	_MMIO(0x45004)
@@ -5998,6 +6066,9 @@ enum skl_disp_power_wells {
 #define HSW_NDE_RSTWRN_OPT	_MMIO(0x46408)
 #define  RESET_PCH_HANDSHAKE_ENABLE	(1<<4)
 
+#define GEN8_CHICKEN_DCPR_1		_MMIO(0x46430)
+#define   MASK_WAKEMEM			(1<<13)
+
 #define SKL_DFSM			_MMIO(0x51000)
 #define SKL_DFSM_CDCLK_LIMIT_MASK	(3 << 23)
 #define SKL_DFSM_CDCLK_LIMIT_675	(0 << 23)
@@ -6015,6 +6086,7 @@ enum skl_disp_power_wells {
 #define  GEN9_TSG_BARRIER_ACK_DISABLE		(1<<8)
 
 #define GEN9_CS_DEBUG_MODE1		_MMIO(0x20ec)
+#define GEN9_CTX_PREEMPT_REG		_MMIO(0x2248)
 #define GEN8_CS_CHICKEN1		_MMIO(0x2580)
 
 /* GEN7 chicken */
@@ -6022,6 +6094,7 @@ enum skl_disp_power_wells {
 # define GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC	((1<<10) | (1<<26))
 # define GEN9_RHWO_OPTIMIZATION_DISABLE		(1<<14)
 #define COMMON_SLICE_CHICKEN2			_MMIO(0x7014)
+# define GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION (1<<8)
 # define GEN8_CSC2_SBE_VUE_CACHE_CONSERVATIVE	(1<<0)
 
 #define HIZ_CHICKEN					_MMIO(0x7018)
@@ -6184,6 +6257,7 @@ enum skl_disp_power_wells {
 /* digital port hotplug */
 #define PCH_PORT_HOTPLUG		_MMIO(0xc4030)	/* SHOTPLUG_CTL */
 #define  PORTA_HOTPLUG_ENABLE		(1 << 28) /* LPT:LP+ & BXT */
+#define  BXT_DDIA_HPD_INVERT            (1 << 27)
 #define  PORTA_HOTPLUG_STATUS_MASK	(3 << 24) /* SPT+ & BXT */
 #define  PORTA_HOTPLUG_NO_DETECT	(0 << 24) /* SPT+ & BXT */
 #define  PORTA_HOTPLUG_SHORT_DETECT	(1 << 24) /* SPT+ & BXT */
@@ -6199,6 +6273,7 @@ enum skl_disp_power_wells {
 #define  PORTD_HOTPLUG_SHORT_DETECT	(1 << 16)
 #define  PORTD_HOTPLUG_LONG_DETECT	(2 << 16)
 #define  PORTC_HOTPLUG_ENABLE		(1 << 12)
+#define  BXT_DDIC_HPD_INVERT            (1 << 11)
 #define  PORTC_PULSE_DURATION_2ms	(0 << 10) /* pre-LPT */
 #define  PORTC_PULSE_DURATION_4_5ms	(1 << 10) /* pre-LPT */
 #define  PORTC_PULSE_DURATION_6ms	(2 << 10) /* pre-LPT */
@@ -6209,6 +6284,7 @@ enum skl_disp_power_wells {
 #define  PORTC_HOTPLUG_SHORT_DETECT	(1 << 8)
 #define  PORTC_HOTPLUG_LONG_DETECT	(2 << 8)
 #define  PORTB_HOTPLUG_ENABLE		(1 << 4)
+#define  BXT_DDIB_HPD_INVERT            (1 << 3)
 #define  PORTB_PULSE_DURATION_2ms	(0 << 2) /* pre-LPT */
 #define  PORTB_PULSE_DURATION_4_5ms	(1 << 2) /* pre-LPT */
 #define  PORTB_PULSE_DURATION_6ms	(2 << 2) /* pre-LPT */
@@ -6218,6 +6294,9 @@ enum skl_disp_power_wells {
 #define  PORTB_HOTPLUG_NO_DETECT	(0 << 0)
 #define  PORTB_HOTPLUG_SHORT_DETECT	(1 << 0)
 #define  PORTB_HOTPLUG_LONG_DETECT	(2 << 0)
+#define  BXT_DDI_HPD_INVERT_MASK	(BXT_DDIA_HPD_INVERT | \
+					BXT_DDIB_HPD_INVERT | \
+					BXT_DDIC_HPD_INVERT)
 
 #define PCH_PORT_HOTPLUG2		_MMIO(0xc403C)	/* SHOTPLUG_CTL2 SPT+ */
 #define  PORTE_HOTPLUG_ENABLE		(1 << 4)
@@ -6836,6 +6915,8 @@ enum skl_disp_power_wells {
 #define  VLV_SPAREG2H				_MMIO(0xA194)
 
 #define  GTFIFODBG				_MMIO(0x120000)
+#define    GT_FIFO_SBDEDICATE_FREE_ENTRY_CHV	(0x1f << 20)
+#define    GT_FIFO_FREE_ENTRIES_CHV		(0x7f << 13)
 #define    GT_FIFO_SBDROPERR			(1<<6)
 #define    GT_FIFO_BLOBDROPERR			(1<<5)
 #define    GT_FIFO_SB_READ_ABORTERR		(1<<4)
@@ -6852,10 +6933,14 @@ enum skl_disp_power_wells {
 
 #define  HSW_IDICR				_MMIO(0x9008)
 #define    IDIHASHMSK(x)			(((x) & 0x3f) << 16)
-#define  HSW_EDRAM_PRESENT			_MMIO(0x120010)
+#define  HSW_EDRAM_CAP				_MMIO(0x120010)
 #define    EDRAM_ENABLED			0x1
+#define    EDRAM_NUM_BANKS(cap)			(((cap) >> 1) & 0xf)
+#define    EDRAM_WAYS_IDX(cap)			(((cap) >> 5) & 0x7)
+#define    EDRAM_SETS_IDX(cap)			(((cap) >> 8) & 0x3)
 
 #define GEN6_UCGCTL1				_MMIO(0x9400)
+# define GEN6_GAMUNIT_CLOCK_GATE_DISABLE		(1 << 22)
 # define GEN6_EU_TCUNIT_CLOCK_GATE_DISABLE		(1 << 16)
 # define GEN6_BLBUNIT_CLOCK_GATE_DISABLE		(1 << 5)
 # define GEN6_CSUNIT_CLOCK_GATE_DISABLE			(1 << 7)
@@ -6872,6 +6957,7 @@ enum skl_disp_power_wells {
 
 #define GEN7_UCGCTL4				_MMIO(0x940c)
 #define  GEN7_L3BANK2X_CLOCK_GATE_DISABLE	(1<<25)
+#define  GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE	(1<<14)
 
 #define GEN6_RCGCTL1				_MMIO(0x9410)
 #define GEN6_RCGCTL2				_MMIO(0x9414)
@@ -7109,6 +7195,7 @@ enum skl_disp_power_wells {
 #define   GEN9_CCS_TLB_PREFETCH_ENABLE	(1<<3)
 
 #define GEN8_ROW_CHICKEN		_MMIO(0xe4f0)
+#define   FLOW_CONTROL_ENABLE		(1<<15)
 #define   PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE	(1<<8)
 #define   STALL_DOP_GATING_DISABLE		(1<<5)
 
@@ -7130,6 +7217,7 @@ enum skl_disp_power_wells {
 
 #define GEN9_HALF_SLICE_CHICKEN7	_MMIO(0xe194)
 #define   GEN9_ENABLE_YV12_BUGFIX	(1<<4)
+#define   GEN9_ENABLE_GPGPU_PREEMPTION	(1<<2)
 
 /* Audio */
 #define G4X_AUD_VID_DID			_MMIO(dev_priv->info.display_mmio_offset + 0x62020)
@@ -7369,9 +7457,11 @@ enum skl_disp_power_wells {
 /* SBI offsets */
 #define  SBI_SSCDIVINTPHASE			0x0200
 #define  SBI_SSCDIVINTPHASE6			0x0600
-#define   SBI_SSCDIVINTPHASE_DIVSEL_MASK	((0x7f)<<1)
+#define   SBI_SSCDIVINTPHASE_DIVSEL_SHIFT	1
+#define   SBI_SSCDIVINTPHASE_DIVSEL_MASK	(0x7f<<1)
 #define   SBI_SSCDIVINTPHASE_DIVSEL(x)		((x)<<1)
-#define   SBI_SSCDIVINTPHASE_INCVAL_MASK	((0x7f)<<8)
+#define   SBI_SSCDIVINTPHASE_INCVAL_SHIFT	8
+#define   SBI_SSCDIVINTPHASE_INCVAL_MASK	(0x7f<<8)
 #define   SBI_SSCDIVINTPHASE_INCVAL(x)		((x)<<8)
 #define   SBI_SSCDIVINTPHASE_DIR(x)		((x)<<15)
 #define   SBI_SSCDIVINTPHASE_PROPAGATE		(1<<0)
@@ -7381,6 +7471,8 @@ enum skl_disp_power_wells {
 #define   SBI_SSCCTL_PATHALT			(1<<3)
 #define   SBI_SSCCTL_DISABLE			(1<<0)
 #define  SBI_SSCAUXDIV6				0x0610
+#define   SBI_SSCAUXDIV_FINALDIV2SEL_SHIFT	4
+#define   SBI_SSCAUXDIV_FINALDIV2SEL_MASK	(1<<4)
 #define   SBI_SSCAUXDIV_FINALDIV2SEL(x)		((x)<<4)
 #define  SBI_DBUFF0				0x2a00
 #define  SBI_GEN0				0x1f00
@@ -7660,6 +7752,59 @@ enum skl_disp_power_wells {
 #define PIPE_CSC_POSTOFF_ME(pipe)	_MMIO_PIPE(pipe, _PIPE_A_CSC_POSTOFF_ME, _PIPE_B_CSC_POSTOFF_ME)
 #define PIPE_CSC_POSTOFF_LO(pipe)	_MMIO_PIPE(pipe, _PIPE_A_CSC_POSTOFF_LO, _PIPE_B_CSC_POSTOFF_LO)
 
+/* pipe degamma/gamma LUTs on IVB+ */
+#define _PAL_PREC_INDEX_A	0x4A400
+#define _PAL_PREC_INDEX_B	0x4AC00
+#define _PAL_PREC_INDEX_C	0x4B400
+#define   PAL_PREC_10_12_BIT		(0 << 31)
+#define   PAL_PREC_SPLIT_MODE		(1 << 31)
+#define   PAL_PREC_AUTO_INCREMENT	(1 << 15)
+#define _PAL_PREC_DATA_A	0x4A404
+#define _PAL_PREC_DATA_B	0x4AC04
+#define _PAL_PREC_DATA_C	0x4B404
+#define _PAL_PREC_GC_MAX_A	0x4A410
+#define _PAL_PREC_GC_MAX_B	0x4AC10
+#define _PAL_PREC_GC_MAX_C	0x4B410
+#define _PAL_PREC_EXT_GC_MAX_A	0x4A420
+#define _PAL_PREC_EXT_GC_MAX_B	0x4AC20
+#define _PAL_PREC_EXT_GC_MAX_C	0x4B420
+
+#define PREC_PAL_INDEX(pipe)		_MMIO_PIPE(pipe, _PAL_PREC_INDEX_A, _PAL_PREC_INDEX_B)
+#define PREC_PAL_DATA(pipe)		_MMIO_PIPE(pipe, _PAL_PREC_DATA_A, _PAL_PREC_DATA_B)
+#define PREC_PAL_GC_MAX(pipe, i)	_MMIO(_PIPE(pipe, _PAL_PREC_GC_MAX_A, _PAL_PREC_GC_MAX_B) + (i) * 4)
+#define PREC_PAL_EXT_GC_MAX(pipe, i)	_MMIO(_PIPE(pipe, _PAL_PREC_EXT_GC_MAX_A, _PAL_PREC_EXT_GC_MAX_B) + (i) * 4)
+
+/* pipe CSC & degamma/gamma LUTs on CHV */
+#define _CGM_PIPE_A_CSC_COEFF01	(VLV_DISPLAY_BASE + 0x67900)
+#define _CGM_PIPE_A_CSC_COEFF23	(VLV_DISPLAY_BASE + 0x67904)
+#define _CGM_PIPE_A_CSC_COEFF45	(VLV_DISPLAY_BASE + 0x67908)
+#define _CGM_PIPE_A_CSC_COEFF67	(VLV_DISPLAY_BASE + 0x6790C)
+#define _CGM_PIPE_A_CSC_COEFF8	(VLV_DISPLAY_BASE + 0x67910)
+#define _CGM_PIPE_A_DEGAMMA	(VLV_DISPLAY_BASE + 0x66000)
+#define _CGM_PIPE_A_GAMMA	(VLV_DISPLAY_BASE + 0x67000)
+#define _CGM_PIPE_A_MODE	(VLV_DISPLAY_BASE + 0x67A00)
+#define   CGM_PIPE_MODE_GAMMA	(1 << 2)
+#define   CGM_PIPE_MODE_CSC	(1 << 1)
+#define   CGM_PIPE_MODE_DEGAMMA	(1 << 0)
+
+#define _CGM_PIPE_B_CSC_COEFF01	(VLV_DISPLAY_BASE + 0x69900)
+#define _CGM_PIPE_B_CSC_COEFF23	(VLV_DISPLAY_BASE + 0x69904)
+#define _CGM_PIPE_B_CSC_COEFF45	(VLV_DISPLAY_BASE + 0x69908)
+#define _CGM_PIPE_B_CSC_COEFF67	(VLV_DISPLAY_BASE + 0x6990C)
+#define _CGM_PIPE_B_CSC_COEFF8	(VLV_DISPLAY_BASE + 0x69910)
+#define _CGM_PIPE_B_DEGAMMA	(VLV_DISPLAY_BASE + 0x68000)
+#define _CGM_PIPE_B_GAMMA	(VLV_DISPLAY_BASE + 0x69000)
+#define _CGM_PIPE_B_MODE	(VLV_DISPLAY_BASE + 0x69A00)
+
+#define CGM_PIPE_CSC_COEFF01(pipe)	_MMIO_PIPE(pipe, _CGM_PIPE_A_CSC_COEFF01, _CGM_PIPE_B_CSC_COEFF01)
+#define CGM_PIPE_CSC_COEFF23(pipe)	_MMIO_PIPE(pipe, _CGM_PIPE_A_CSC_COEFF23, _CGM_PIPE_B_CSC_COEFF23)
+#define CGM_PIPE_CSC_COEFF45(pipe)	_MMIO_PIPE(pipe, _CGM_PIPE_A_CSC_COEFF45, _CGM_PIPE_B_CSC_COEFF45)
+#define CGM_PIPE_CSC_COEFF67(pipe)	_MMIO_PIPE(pipe, _CGM_PIPE_A_CSC_COEFF67, _CGM_PIPE_B_CSC_COEFF67)
+#define CGM_PIPE_CSC_COEFF8(pipe)	_MMIO_PIPE(pipe, _CGM_PIPE_A_CSC_COEFF8, _CGM_PIPE_B_CSC_COEFF8)
+#define CGM_PIPE_DEGAMMA(pipe, i, w)	_MMIO(_PIPE(pipe, _CGM_PIPE_A_DEGAMMA, _CGM_PIPE_B_DEGAMMA) + (i) * 8 + (w) * 4)
+#define CGM_PIPE_GAMMA(pipe, i, w)	_MMIO(_PIPE(pipe, _CGM_PIPE_A_GAMMA, _CGM_PIPE_B_GAMMA) + (i) * 8 + (w) * 4)
+#define CGM_PIPE_MODE(pipe)		_MMIO_PIPE(pipe, _CGM_PIPE_A_MODE, _CGM_PIPE_B_MODE)
+
 /* MIPI DSI registers */
 
 #define _MIPI_PORT(port, a, c)	_PORT3(port, a, 0, c)	/* ports A and C only */
@@ -7674,58 +7819,62 @@ enum skl_disp_power_wells {
 #define  BXT_MIPI_DIV_SHIFT(port)		\
 			_MIPI_PORT(port, BXT_MIPI1_DIV_SHIFT, \
 					BXT_MIPI2_DIV_SHIFT)
-/* Var clock divider to generate TX source. Result must be < 39.5 M */
-#define  BXT_MIPI1_ESCLK_VAR_DIV_MASK		(0x3F << 26)
-#define  BXT_MIPI2_ESCLK_VAR_DIV_MASK		(0x3F << 10)
-#define  BXT_MIPI_ESCLK_VAR_DIV_MASK(port)	\
-			_MIPI_PORT(port, BXT_MIPI1_ESCLK_VAR_DIV_MASK, \
-						BXT_MIPI2_ESCLK_VAR_DIV_MASK)
 
-#define  BXT_MIPI_ESCLK_VAR_DIV(port, val)	\
-			(val << BXT_MIPI_DIV_SHIFT(port))
 /* TX control divider to select actual TX clock output from (8x/var) */
-#define  BXT_MIPI1_TX_ESCLK_SHIFT		21
-#define  BXT_MIPI2_TX_ESCLK_SHIFT		5
+#define  BXT_MIPI1_TX_ESCLK_SHIFT		26
+#define  BXT_MIPI2_TX_ESCLK_SHIFT		10
 #define  BXT_MIPI_TX_ESCLK_SHIFT(port)		\
 			_MIPI_PORT(port, BXT_MIPI1_TX_ESCLK_SHIFT, \
 					BXT_MIPI2_TX_ESCLK_SHIFT)
-#define  BXT_MIPI1_TX_ESCLK_FIXDIV_MASK		(3 << 21)
-#define  BXT_MIPI2_TX_ESCLK_FIXDIV_MASK		(3 << 5)
+#define  BXT_MIPI1_TX_ESCLK_FIXDIV_MASK		(0x3F << 26)
+#define  BXT_MIPI2_TX_ESCLK_FIXDIV_MASK		(0x3F << 10)
 #define  BXT_MIPI_TX_ESCLK_FIXDIV_MASK(port)	\
 			_MIPI_PORT(port, BXT_MIPI1_TX_ESCLK_FIXDIV_MASK, \
-						BXT_MIPI2_TX_ESCLK_FIXDIV_MASK)
-#define  BXT_MIPI_TX_ESCLK_8XDIV_BY2(port)	\
-		(0x0 << BXT_MIPI_TX_ESCLK_SHIFT(port))
-#define  BXT_MIPI_TX_ESCLK_8XDIV_BY4(port)	\
-		(0x1 << BXT_MIPI_TX_ESCLK_SHIFT(port))
-#define  BXT_MIPI_TX_ESCLK_8XDIV_BY8(port)	\
-		(0x2 << BXT_MIPI_TX_ESCLK_SHIFT(port))
-/* RX control divider to select actual RX clock output from 8x*/
-#define  BXT_MIPI1_RX_ESCLK_SHIFT		19
-#define  BXT_MIPI2_RX_ESCLK_SHIFT		3
-#define  BXT_MIPI_RX_ESCLK_SHIFT(port)		\
-			_MIPI_PORT(port, BXT_MIPI1_RX_ESCLK_SHIFT, \
-					BXT_MIPI2_RX_ESCLK_SHIFT)
-#define  BXT_MIPI1_RX_ESCLK_FIXDIV_MASK		(3 << 19)
-#define  BXT_MIPI2_RX_ESCLK_FIXDIV_MASK		(3 << 3)
-#define  BXT_MIPI_RX_ESCLK_FIXDIV_MASK(port)	\
-		(3 << BXT_MIPI_RX_ESCLK_SHIFT(port))
-#define  BXT_MIPI_RX_ESCLK_8X_BY2(port)	\
-		(1 << BXT_MIPI_RX_ESCLK_SHIFT(port))
-#define  BXT_MIPI_RX_ESCLK_8X_BY3(port)	\
-		(2 << BXT_MIPI_RX_ESCLK_SHIFT(port))
-#define  BXT_MIPI_RX_ESCLK_8X_BY4(port)	\
-		(3 << BXT_MIPI_RX_ESCLK_SHIFT(port))
-/* BXT-A WA: Always prog DPHY dividers to 00 */
-#define  BXT_MIPI1_DPHY_DIV_SHIFT		16
-#define  BXT_MIPI2_DPHY_DIV_SHIFT		0
-#define  BXT_MIPI_DPHY_DIV_SHIFT(port)		\
-			_MIPI_PORT(port, BXT_MIPI1_DPHY_DIV_SHIFT, \
-					BXT_MIPI2_DPHY_DIV_SHIFT)
-#define  BXT_MIPI_1_DPHY_DIVIDER_MASK		(3 << 16)
-#define  BXT_MIPI_2_DPHY_DIVIDER_MASK		(3 << 0)
-#define  BXT_MIPI_DPHY_DIVIDER_MASK(port)	\
-		(3 << BXT_MIPI_DPHY_DIV_SHIFT(port))
+					BXT_MIPI2_TX_ESCLK_FIXDIV_MASK)
+#define  BXT_MIPI_TX_ESCLK_DIVIDER(port, val)	\
+		((val & 0x3F) << BXT_MIPI_TX_ESCLK_SHIFT(port))
+/* RX upper control divider to select actual RX clock output from 8x */
+#define  BXT_MIPI1_RX_ESCLK_UPPER_SHIFT		21
+#define  BXT_MIPI2_RX_ESCLK_UPPER_SHIFT		5
+#define  BXT_MIPI_RX_ESCLK_UPPER_SHIFT(port)		\
+			_MIPI_PORT(port, BXT_MIPI1_RX_ESCLK_UPPER_SHIFT, \
+					BXT_MIPI2_RX_ESCLK_UPPER_SHIFT)
+#define  BXT_MIPI1_RX_ESCLK_UPPER_FIXDIV_MASK		(3 << 21)
+#define  BXT_MIPI2_RX_ESCLK_UPPER_FIXDIV_MASK		(3 << 5)
+#define  BXT_MIPI_RX_ESCLK_UPPER_FIXDIV_MASK(port)	\
+			_MIPI_PORT(port, BXT_MIPI1_RX_ESCLK_UPPER_FIXDIV_MASK, \
+					BXT_MIPI2_RX_ESCLK_UPPER_FIXDIV_MASK)
+#define  BXT_MIPI_RX_ESCLK_UPPER_DIVIDER(port, val)	\
+		((val & 3) << BXT_MIPI_RX_ESCLK_UPPER_SHIFT(port))
+/* 8/3X divider to select the actual 8/3X clock output from 8x */
+#define  BXT_MIPI1_8X_BY3_SHIFT                19
+#define  BXT_MIPI2_8X_BY3_SHIFT                3
+#define  BXT_MIPI_8X_BY3_SHIFT(port)          \
+			_MIPI_PORT(port, BXT_MIPI1_8X_BY3_SHIFT, \
+					BXT_MIPI2_8X_BY3_SHIFT)
+#define  BXT_MIPI1_8X_BY3_DIVIDER_MASK         (3 << 19)
+#define  BXT_MIPI2_8X_BY3_DIVIDER_MASK         (3 << 3)
+#define  BXT_MIPI_8X_BY3_DIVIDER_MASK(port)    \
+			_MIPI_PORT(port, BXT_MIPI1_8X_BY3_DIVIDER_MASK, \
+						BXT_MIPI2_8X_BY3_DIVIDER_MASK)
+#define  BXT_MIPI_8X_BY3_DIVIDER(port, val)    \
+			((val & 3) << BXT_MIPI_8X_BY3_SHIFT(port))
+/* RX lower control divider to select actual RX clock output from 8x */
+#define  BXT_MIPI1_RX_ESCLK_LOWER_SHIFT		16
+#define  BXT_MIPI2_RX_ESCLK_LOWER_SHIFT		0
+#define  BXT_MIPI_RX_ESCLK_LOWER_SHIFT(port)		\
+			_MIPI_PORT(port, BXT_MIPI1_RX_ESCLK_LOWER_SHIFT, \
+					BXT_MIPI2_RX_ESCLK_LOWER_SHIFT)
+#define  BXT_MIPI1_RX_ESCLK_LOWER_FIXDIV_MASK		(3 << 16)
+#define  BXT_MIPI2_RX_ESCLK_LOWER_FIXDIV_MASK		(3 << 0)
+#define  BXT_MIPI_RX_ESCLK_LOWER_FIXDIV_MASK(port)	\
+			_MIPI_PORT(port, BXT_MIPI1_RX_ESCLK_LOWER_FIXDIV_MASK, \
+					BXT_MIPI2_RX_ESCLK_LOWER_FIXDIV_MASK)
+#define  BXT_MIPI_RX_ESCLK_LOWER_DIVIDER(port, val)	\
+		((val & 3) << BXT_MIPI_RX_ESCLK_LOWER_SHIFT(port))
+
+#define RX_DIVIDER_BIT_1_2                     0x3
+#define RX_DIVIDER_BIT_3_4                     0xC
 
 /* BXT MIPI mode configure */
 #define  _BXT_MIPIA_TRANS_HACTIVE			0x6B0F8
@@ -7750,9 +7899,11 @@ enum skl_disp_power_wells {
 #define  BXT_DSIC_16X_BY2		(1 << 10)
 #define  BXT_DSIC_16X_BY3		(2 << 10)
 #define  BXT_DSIC_16X_BY4		(3 << 10)
+#define  BXT_DSIC_16X_MASK		(3 << 10)
 #define  BXT_DSIA_16X_BY2		(1 << 8)
 #define  BXT_DSIA_16X_BY3		(2 << 8)
 #define  BXT_DSIA_16X_BY4		(3 << 8)
+#define  BXT_DSIA_16X_MASK		(3 << 8)
 #define  BXT_DSI_FREQ_SEL_SHIFT		8
 #define  BXT_DSI_FREQ_SEL_MASK		(0xF << BXT_DSI_FREQ_SEL_SHIFT)
 
@@ -7887,8 +8038,8 @@ enum skl_disp_power_wells {
 #define  VID_MODE_FORMAT_MASK				(0xf << 7)
 #define  VID_MODE_NOT_SUPPORTED				(0 << 7)
 #define  VID_MODE_FORMAT_RGB565				(1 << 7)
-#define  VID_MODE_FORMAT_RGB666				(2 << 7)
-#define  VID_MODE_FORMAT_RGB666_LOOSE			(3 << 7)
+#define  VID_MODE_FORMAT_RGB666_PACKED			(2 << 7)
+#define  VID_MODE_FORMAT_RGB666				(3 << 7)
 #define  VID_MODE_FORMAT_RGB888				(4 << 7)
 #define  CMD_MODE_CHANNEL_NUMBER_SHIFT			5
 #define  CMD_MODE_CHANNEL_NUMBER_MASK			(3 << 5)
@@ -8144,6 +8295,7 @@ enum skl_disp_power_wells {
 #define  READ_REQUEST_PRIORITY_HIGH			(3 << 3)
 #define  RGB_FLIP_TO_BGR				(1 << 2)
 
+#define  BXT_PIPE_SELECT_SHIFT				7
 #define  BXT_PIPE_SELECT_MASK				(7 << 7)
 #define  BXT_PIPE_SELECT(pipe)				((pipe) << 7)
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_sysfs.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_sysfs.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_sysfs.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_sysfs.c	2016-07-24 15:23:50.000000000 -0400
@@ -370,6 +370,8 @@ static ssize_t gt_max_freq_mhz_store(str
 
 	flush_delayed_work(&dev_priv->rps.delayed_resume_work);
 
+	intel_runtime_pm_get(dev_priv);
+
 	mutex_lock(&dev_priv->rps.hw_lock);
 
 	val = intel_freq_opcode(dev_priv, val);
@@ -378,6 +380,7 @@ static ssize_t gt_max_freq_mhz_store(str
 	    val > dev_priv->rps.max_freq ||
 	    val < dev_priv->rps.min_freq_softlimit) {
 		mutex_unlock(&dev_priv->rps.hw_lock);
+		intel_runtime_pm_put(dev_priv);
 		return -EINVAL;
 	}
 
@@ -398,6 +401,8 @@ static ssize_t gt_max_freq_mhz_store(str
 
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
+	intel_runtime_pm_put(dev_priv);
+
 	return count;
 }
 
@@ -433,6 +438,8 @@ static ssize_t gt_min_freq_mhz_store(str
 
 	flush_delayed_work(&dev_priv->rps.delayed_resume_work);
 
+	intel_runtime_pm_get(dev_priv);
+
 	mutex_lock(&dev_priv->rps.hw_lock);
 
 	val = intel_freq_opcode(dev_priv, val);
@@ -441,6 +448,7 @@ static ssize_t gt_min_freq_mhz_store(str
 	    val > dev_priv->rps.max_freq ||
 	    val > dev_priv->rps.max_freq_softlimit) {
 		mutex_unlock(&dev_priv->rps.hw_lock);
+		intel_runtime_pm_put(dev_priv);
 		return -EINVAL;
 	}
 
@@ -457,6 +465,8 @@ static ssize_t gt_min_freq_mhz_store(str
 
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
+	intel_runtime_pm_put(dev_priv);
+
 	return count;
 
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_trace.h linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_trace.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_trace.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_trace.h	2016-07-24 15:23:50.000000000 -0400
@@ -464,7 +464,7 @@ TRACE_EVENT(i915_gem_ring_sync_to,
 	    TP_fast_assign(
 			   __entry->dev = from->dev->primary->index;
 			   __entry->sync_from = from->id;
-			   __entry->sync_to = to_req->ring->id;
+			   __entry->sync_to = to_req->engine->id;
 			   __entry->seqno = i915_gem_request_get_seqno(req);
 			   ),
 
@@ -486,13 +486,13 @@ TRACE_EVENT(i915_gem_ring_dispatch,
 			     ),
 
 	    TP_fast_assign(
-			   struct intel_engine_cs *ring =
-						i915_gem_request_get_ring(req);
-			   __entry->dev = ring->dev->primary->index;
-			   __entry->ring = ring->id;
+			   struct intel_engine_cs *engine =
+						i915_gem_request_get_engine(req);
+			   __entry->dev = engine->dev->primary->index;
+			   __entry->ring = engine->id;
 			   __entry->seqno = i915_gem_request_get_seqno(req);
 			   __entry->flags = flags;
-			   i915_trace_irq_get(ring, req);
+			   i915_trace_irq_get(engine, req);
 			   ),
 
 	    TP_printk("dev=%u, ring=%u, seqno=%u, flags=%x",
@@ -511,8 +511,8 @@ TRACE_EVENT(i915_gem_ring_flush,
 			     ),
 
 	    TP_fast_assign(
-			   __entry->dev = req->ring->dev->primary->index;
-			   __entry->ring = req->ring->id;
+			   __entry->dev = req->engine->dev->primary->index;
+			   __entry->ring = req->engine->id;
 			   __entry->invalidate = invalidate;
 			   __entry->flush = flush;
 			   ),
@@ -533,10 +533,10 @@ DECLARE_EVENT_CLASS(i915_gem_request,
 			     ),
 
 	    TP_fast_assign(
-			   struct intel_engine_cs *ring =
-						i915_gem_request_get_ring(req);
-			   __entry->dev = ring->dev->primary->index;
-			   __entry->ring = ring->id;
+			   struct intel_engine_cs *engine =
+						i915_gem_request_get_engine(req);
+			   __entry->dev = engine->dev->primary->index;
+			   __entry->ring = engine->id;
 			   __entry->seqno = i915_gem_request_get_seqno(req);
 			   ),
 
@@ -550,8 +550,8 @@ DEFINE_EVENT(i915_gem_request, i915_gem_
 );
 
 TRACE_EVENT(i915_gem_request_notify,
-	    TP_PROTO(struct intel_engine_cs *ring),
-	    TP_ARGS(ring),
+	    TP_PROTO(struct intel_engine_cs *engine),
+	    TP_ARGS(engine),
 
 	    TP_STRUCT__entry(
 			     __field(u32, dev)
@@ -560,9 +560,9 @@ TRACE_EVENT(i915_gem_request_notify,
 			     ),
 
 	    TP_fast_assign(
-			   __entry->dev = ring->dev->primary->index;
-			   __entry->ring = ring->id;
-			   __entry->seqno = ring->get_seqno(ring, false);
+			   __entry->dev = engine->dev->primary->index;
+			   __entry->ring = engine->id;
+			   __entry->seqno = engine->get_seqno(engine);
 			   ),
 
 	    TP_printk("dev=%u, ring=%u, seqno=%u",
@@ -597,13 +597,13 @@ TRACE_EVENT(i915_gem_request_wait_begin,
 	     * less desirable.
 	     */
 	    TP_fast_assign(
-			   struct intel_engine_cs *ring =
-						i915_gem_request_get_ring(req);
-			   __entry->dev = ring->dev->primary->index;
-			   __entry->ring = ring->id;
+			   struct intel_engine_cs *engine =
+						i915_gem_request_get_engine(req);
+			   __entry->dev = engine->dev->primary->index;
+			   __entry->ring = engine->id;
 			   __entry->seqno = i915_gem_request_get_seqno(req);
 			   __entry->blocking =
-				     mutex_is_locked(&ring->dev->struct_mutex);
+				     mutex_is_locked(&engine->dev->struct_mutex);
 			   ),
 
 	    TP_printk("dev=%u, ring=%u, seqno=%u, blocking=%s",
@@ -777,9 +777,9 @@ DEFINE_EVENT(i915_context, i915_context_
  * called only if full ppgtt is enabled.
  */
 TRACE_EVENT(switch_mm,
-	TP_PROTO(struct intel_engine_cs *ring, struct intel_context *to),
+	TP_PROTO(struct intel_engine_cs *engine, struct intel_context *to),
 
-	TP_ARGS(ring, to),
+	TP_ARGS(engine, to),
 
 	TP_STRUCT__entry(
 			__field(u32, ring)
@@ -789,10 +789,10 @@ TRACE_EVENT(switch_mm,
 	),
 
 	TP_fast_assign(
-			__entry->ring = ring->id;
+			__entry->ring = engine->id;
 			__entry->to = to;
 			__entry->vm = to->ppgtt? &to->ppgtt->base : NULL;
-			__entry->dev = ring->dev->primary->index;
+			__entry->dev = engine->dev->primary->index;
 	),
 
 	TP_printk("dev=%u, ring=%u, ctx=%p, ctx_vm=%p",
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_vgpu.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_vgpu.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/i915_vgpu.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/i915_vgpu.c	2016-07-24 15:23:50.000000000 -0400
@@ -181,8 +181,8 @@ static int vgt_balloon_space(struct drm_
 int intel_vgt_balloon(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
-	struct i915_address_space *ggtt_vm = &dev_priv->gtt.base;
-	unsigned long ggtt_vm_end = ggtt_vm->start + ggtt_vm->total;
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
+	unsigned long ggtt_end = ggtt->base.start + ggtt->base.total;
 
 	unsigned long mappable_base, mappable_size, mappable_end;
 	unsigned long unmappable_base, unmappable_size, unmappable_end;
@@ -202,19 +202,19 @@ int intel_vgt_balloon(struct drm_device
 	DRM_INFO("Unmappable graphic memory: base 0x%lx size %ldKiB\n",
 		 unmappable_base, unmappable_size / 1024);
 
-	if (mappable_base < ggtt_vm->start ||
-	    mappable_end > dev_priv->gtt.mappable_end ||
-	    unmappable_base < dev_priv->gtt.mappable_end ||
-	    unmappable_end > ggtt_vm_end) {
+	if (mappable_base < ggtt->base.start ||
+	    mappable_end > ggtt->mappable_end ||
+	    unmappable_base < ggtt->mappable_end ||
+	    unmappable_end > ggtt_end) {
 		DRM_ERROR("Invalid ballooning configuration!\n");
 		return -EINVAL;
 	}
 
 	/* Unmappable graphic memory ballooning */
-	if (unmappable_base > dev_priv->gtt.mappable_end) {
-		ret = vgt_balloon_space(&ggtt_vm->mm,
+	if (unmappable_base > ggtt->mappable_end) {
+		ret = vgt_balloon_space(&ggtt->base.mm,
 					&bl_info.space[2],
-					dev_priv->gtt.mappable_end,
+					ggtt->mappable_end,
 					unmappable_base);
 
 		if (ret)
@@ -225,30 +225,30 @@ int intel_vgt_balloon(struct drm_device
 	 * No need to partition out the last physical page,
 	 * because it is reserved to the guard page.
 	 */
-	if (unmappable_end < ggtt_vm_end - PAGE_SIZE) {
-		ret = vgt_balloon_space(&ggtt_vm->mm,
+	if (unmappable_end < ggtt_end - PAGE_SIZE) {
+		ret = vgt_balloon_space(&ggtt->base.mm,
 					&bl_info.space[3],
 					unmappable_end,
-					ggtt_vm_end - PAGE_SIZE);
+					ggtt_end - PAGE_SIZE);
 		if (ret)
 			goto err;
 	}
 
 	/* Mappable graphic memory ballooning */
-	if (mappable_base > ggtt_vm->start) {
-		ret = vgt_balloon_space(&ggtt_vm->mm,
+	if (mappable_base > ggtt->base.start) {
+		ret = vgt_balloon_space(&ggtt->base.mm,
 					&bl_info.space[0],
-					ggtt_vm->start, mappable_base);
+					ggtt->base.start, mappable_base);
 
 		if (ret)
 			goto err;
 	}
 
-	if (mappable_end < dev_priv->gtt.mappable_end) {
-		ret = vgt_balloon_space(&ggtt_vm->mm,
+	if (mappable_end < ggtt->mappable_end) {
+		ret = vgt_balloon_space(&ggtt->base.mm,
 					&bl_info.space[1],
 					mappable_end,
-					dev_priv->gtt.mappable_end);
+					ggtt->mappable_end);
 
 		if (ret)
 			goto err;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_atomic.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_atomic.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_atomic.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_atomic.c	2016-07-24 15:23:50.000000000 -0400
@@ -96,8 +96,11 @@ intel_crtc_duplicate_state(struct drm_cr
 	crtc_state->update_pipe = false;
 	crtc_state->disable_lp_wm = false;
 	crtc_state->disable_cxsr = false;
-	crtc_state->wm_changed = false;
+	crtc_state->update_wm_pre = false;
+	crtc_state->update_wm_post = false;
 	crtc_state->fb_changed = false;
+	crtc_state->wm.need_postvbl_update = false;
+	crtc_state->fb_bits = 0;
 
 	return &crtc_state->base;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_atomic_plane.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_atomic_plane.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_atomic_plane.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_atomic_plane.c	2016-07-24 15:23:50.000000000 -0400
@@ -195,12 +195,10 @@ static void intel_plane_atomic_update(st
 	struct intel_plane_state *intel_state =
 		to_intel_plane_state(plane->state);
 	struct drm_crtc *crtc = plane->state->crtc ?: old_state->crtc;
-	struct drm_crtc_state *crtc_state =
-		drm_atomic_get_existing_crtc_state(old_state->state, crtc);
 
 	if (intel_state->visible)
 		intel_plane->update_plane(plane,
-					  to_intel_crtc_state(crtc_state),
+					  to_intel_crtc_state(crtc->state),
 					  intel_state);
 	else
 		intel_plane->disable_plane(plane, crtc);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_audio.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_audio.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_audio.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_audio.c	2016-07-24 15:23:50.000000000 -0400
@@ -372,7 +372,7 @@ static void ilk_audio_codec_disable(stru
 	if (WARN_ON(port == PORT_A))
 		return;
 
-	if (HAS_PCH_IBX(dev_priv->dev)) {
+	if (HAS_PCH_IBX(dev_priv)) {
 		aud_config = IBX_AUD_CFG(pipe);
 		aud_cntrl_st2 = IBX_AUD_CNTL_ST2;
 	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
@@ -561,23 +561,21 @@ void intel_audio_codec_disable(struct in
 }
 
 /**
- * intel_init_audio - Set up chip specific audio functions
- * @dev: drm device
+ * intel_init_audio_hooks - Set up chip specific audio hooks
+ * @dev_priv: device private
  */
-void intel_init_audio(struct drm_device *dev)
+void intel_init_audio_hooks(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-
-	if (IS_G4X(dev)) {
+	if (IS_G4X(dev_priv)) {
 		dev_priv->display.audio_codec_enable = g4x_audio_codec_enable;
 		dev_priv->display.audio_codec_disable = g4x_audio_codec_disable;
-	} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
 		dev_priv->display.audio_codec_enable = ilk_audio_codec_enable;
 		dev_priv->display.audio_codec_disable = ilk_audio_codec_disable;
-	} else if (IS_HASWELL(dev) || INTEL_INFO(dev)->gen >= 8) {
+	} else if (IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 8) {
 		dev_priv->display.audio_codec_enable = hsw_audio_codec_enable;
 		dev_priv->display.audio_codec_disable = hsw_audio_codec_disable;
-	} else if (HAS_PCH_SPLIT(dev)) {
+	} else if (HAS_PCH_SPLIT(dev_priv)) {
 		dev_priv->display.audio_codec_enable = ilk_audio_codec_enable;
 		dev_priv->display.audio_codec_disable = ilk_audio_codec_disable;
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_bios.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_bios.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_bios.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_bios.c	2016-07-24 15:23:50.000000000 -0400
@@ -29,7 +29,9 @@
 #include <drm/drmP.h>
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
-#include "intel_bios.h"
+
+#define _INTEL_BIOS_PRIVATE
+#include "intel_vbt_defs.h"
 
 /**
  * DOC: Video BIOS Table (VBT)
@@ -56,8 +58,6 @@
 #define	SLAVE_ADDR1	0x70
 #define	SLAVE_ADDR2	0x72
 
-static int panel_type;
-
 /* Get BDB block size given a pointer to Block ID. */
 static u32 _get_blocksize(const u8 *block_base)
 {
@@ -139,6 +139,11 @@ fill_detail_timing_data(struct drm_displ
 	else
 		panel_fixed_mode->flags |= DRM_MODE_FLAG_NVSYNC;
 
+	panel_fixed_mode->width_mm = (dvo_timing->himage_hi << 8) |
+		dvo_timing->himage_lo;
+	panel_fixed_mode->height_mm = (dvo_timing->vimage_hi << 8) |
+		dvo_timing->vimage_lo;
+
 	/* Some VBTs have bogus h/vtotal values */
 	if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal)
 		panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1;
@@ -203,17 +208,32 @@ parse_lfp_panel_data(struct drm_i915_pri
 	const struct lvds_dvo_timing *panel_dvo_timing;
 	const struct lvds_fp_timing *fp_timing;
 	struct drm_display_mode *panel_fixed_mode;
+	int panel_type;
 	int drrs_mode;
+	int ret;
 
 	lvds_options = find_section(bdb, BDB_LVDS_OPTIONS);
 	if (!lvds_options)
 		return;
 
 	dev_priv->vbt.lvds_dither = lvds_options->pixel_dither;
-	if (lvds_options->panel_type == 0xff)
-		return;
 
-	panel_type = lvds_options->panel_type;
+	ret = intel_opregion_get_panel_type(dev_priv->dev);
+	if (ret >= 0) {
+		WARN_ON(ret > 0xf);
+		panel_type = ret;
+		DRM_DEBUG_KMS("Panel type: %d (OpRegion)\n", panel_type);
+	} else {
+		if (lvds_options->panel_type > 0xf) {
+			DRM_DEBUG_KMS("Invalid VBT panel type 0x%x\n",
+				      lvds_options->panel_type);
+			return;
+		}
+		panel_type = lvds_options->panel_type;
+		DRM_DEBUG_KMS("Panel type: %d (VBT)\n", panel_type);
+	}
+
+	dev_priv->vbt.panel_type = panel_type;
 
 	drrs_mode = (lvds_options->dps_panel_type_bits
 				>> (panel_type * 2)) & MODE_MASK;
@@ -249,7 +269,7 @@ parse_lfp_panel_data(struct drm_i915_pri
 
 	panel_dvo_timing = get_lvds_dvo_timing(lvds_lfp_data,
 					       lvds_lfp_data_ptrs,
-					       lvds_options->panel_type);
+					       panel_type);
 
 	panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL);
 	if (!panel_fixed_mode)
@@ -264,7 +284,7 @@ parse_lfp_panel_data(struct drm_i915_pri
 
 	fp_timing = get_lvds_fp_timing(bdb, lvds_lfp_data,
 				       lvds_lfp_data_ptrs,
-				       lvds_options->panel_type);
+				       panel_type);
 	if (fp_timing) {
 		/* check the resolution, just to be sure */
 		if (fp_timing->x_res == panel_fixed_mode->hdisplay &&
@@ -282,6 +302,7 @@ parse_lfp_backlight(struct drm_i915_priv
 {
 	const struct bdb_lfp_backlight_data *backlight_data;
 	const struct bdb_lfp_backlight_data_entry *entry;
+	int panel_type = dev_priv->vbt.panel_type;
 
 	backlight_data = find_section(bdb, BDB_LVDS_BACKLIGHT);
 	if (!backlight_data)
@@ -480,7 +501,7 @@ parse_sdvo_device_mapping(struct drm_i91
 			      child->slave_addr,
 			      (child->dvo_port == DEVICE_PORT_DVOB) ?
 			      "SDVOB" : "SDVOC");
-		p_mapping = &(dev_priv->sdvo_mappings[child->dvo_port - 1]);
+		p_mapping = &dev_priv->vbt.sdvo_mappings[child->dvo_port - 1];
 		if (!p_mapping->initialized) {
 			p_mapping->dvo_port = child->dvo_port;
 			p_mapping->slave_addr = child->slave_addr;
@@ -525,10 +546,7 @@ parse_driver_features(struct drm_i915_pr
 		return;
 
 	if (driver->lvds_config == BDB_DRIVER_FEATURE_EDP)
-		dev_priv->vbt.edp_support = 1;
-
-	if (driver->dual_frequency)
-		dev_priv->render_reclock_avail = true;
+		dev_priv->vbt.edp.support = 1;
 
 	DRM_DEBUG_KMS("DRRS State Enabled:%d\n", driver->drrs_enabled);
 	/*
@@ -547,23 +565,24 @@ parse_edp(struct drm_i915_private *dev_p
 	const struct bdb_edp *edp;
 	const struct edp_power_seq *edp_pps;
 	const struct edp_link_params *edp_link_params;
+	int panel_type = dev_priv->vbt.panel_type;
 
 	edp = find_section(bdb, BDB_EDP);
 	if (!edp) {
-		if (dev_priv->vbt.edp_support)
+		if (dev_priv->vbt.edp.support)
 			DRM_DEBUG_KMS("No eDP BDB found but eDP panel supported.\n");
 		return;
 	}
 
 	switch ((edp->color_depth >> (panel_type * 2)) & 3) {
 	case EDP_18BPP:
-		dev_priv->vbt.edp_bpp = 18;
+		dev_priv->vbt.edp.bpp = 18;
 		break;
 	case EDP_24BPP:
-		dev_priv->vbt.edp_bpp = 24;
+		dev_priv->vbt.edp.bpp = 24;
 		break;
 	case EDP_30BPP:
-		dev_priv->vbt.edp_bpp = 30;
+		dev_priv->vbt.edp.bpp = 30;
 		break;
 	}
 
@@ -571,14 +590,14 @@ parse_edp(struct drm_i915_private *dev_p
 	edp_pps = &edp->power_seqs[panel_type];
 	edp_link_params = &edp->link_params[panel_type];
 
-	dev_priv->vbt.edp_pps = *edp_pps;
+	dev_priv->vbt.edp.pps = *edp_pps;
 
 	switch (edp_link_params->rate) {
 	case EDP_RATE_1_62:
-		dev_priv->vbt.edp_rate = DP_LINK_BW_1_62;
+		dev_priv->vbt.edp.rate = DP_LINK_BW_1_62;
 		break;
 	case EDP_RATE_2_7:
-		dev_priv->vbt.edp_rate = DP_LINK_BW_2_7;
+		dev_priv->vbt.edp.rate = DP_LINK_BW_2_7;
 		break;
 	default:
 		DRM_DEBUG_KMS("VBT has unknown eDP link rate value %u\n",
@@ -588,13 +607,13 @@ parse_edp(struct drm_i915_private *dev_p
 
 	switch (edp_link_params->lanes) {
 	case EDP_LANE_1:
-		dev_priv->vbt.edp_lanes = 1;
+		dev_priv->vbt.edp.lanes = 1;
 		break;
 	case EDP_LANE_2:
-		dev_priv->vbt.edp_lanes = 2;
+		dev_priv->vbt.edp.lanes = 2;
 		break;
 	case EDP_LANE_4:
-		dev_priv->vbt.edp_lanes = 4;
+		dev_priv->vbt.edp.lanes = 4;
 		break;
 	default:
 		DRM_DEBUG_KMS("VBT has unknown eDP lane count value %u\n",
@@ -604,16 +623,16 @@ parse_edp(struct drm_i915_private *dev_p
 
 	switch (edp_link_params->preemphasis) {
 	case EDP_PREEMPHASIS_NONE:
-		dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_0;
+		dev_priv->vbt.edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_0;
 		break;
 	case EDP_PREEMPHASIS_3_5dB:
-		dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_1;
+		dev_priv->vbt.edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_1;
 		break;
 	case EDP_PREEMPHASIS_6dB:
-		dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_2;
+		dev_priv->vbt.edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_2;
 		break;
 	case EDP_PREEMPHASIS_9_5dB:
-		dev_priv->vbt.edp_preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_3;
+		dev_priv->vbt.edp.preemphasis = DP_TRAIN_PRE_EMPH_LEVEL_3;
 		break;
 	default:
 		DRM_DEBUG_KMS("VBT has unknown eDP pre-emphasis value %u\n",
@@ -623,16 +642,16 @@ parse_edp(struct drm_i915_private *dev_p
 
 	switch (edp_link_params->vswing) {
 	case EDP_VSWING_0_4V:
-		dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_0;
+		dev_priv->vbt.edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_0;
 		break;
 	case EDP_VSWING_0_6V:
-		dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_1;
+		dev_priv->vbt.edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_1;
 		break;
 	case EDP_VSWING_0_8V:
-		dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
+		dev_priv->vbt.edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
 		break;
 	case EDP_VSWING_1_2V:
-		dev_priv->vbt.edp_vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
+		dev_priv->vbt.edp.vswing = DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
 		break;
 	default:
 		DRM_DEBUG_KMS("VBT has unknown eDP voltage swing value %u\n",
@@ -645,10 +664,10 @@ parse_edp(struct drm_i915_private *dev_p
 
 		/* Don't read from VBT if module parameter has valid value*/
 		if (i915.edp_vswing) {
-			dev_priv->edp_low_vswing = i915.edp_vswing == 1;
+			dev_priv->vbt.edp.low_vswing = i915.edp_vswing == 1;
 		} else {
 			vswing = (edp->edp_vswing_preemph >> (panel_type * 4)) & 0xF;
-			dev_priv->edp_low_vswing = vswing == 0;
+			dev_priv->vbt.edp.low_vswing = vswing == 0;
 		}
 	}
 }
@@ -658,6 +677,7 @@ parse_psr(struct drm_i915_private *dev_p
 {
 	const struct bdb_psr *psr;
 	const struct psr_table *psr_table;
+	int panel_type = dev_priv->vbt.panel_type;
 
 	psr = find_section(bdb, BDB_PSR);
 	if (!psr) {
@@ -704,9 +724,10 @@ parse_mipi_config(struct drm_i915_privat
 	const struct bdb_mipi_config *start;
 	const struct mipi_config *config;
 	const struct mipi_pps_data *pps;
+	int panel_type = dev_priv->vbt.panel_type;
 
 	/* parse MIPI blocks only if LFP type is MIPI */
-	if (!dev_priv->vbt.has_mipi)
+	if (!intel_bios_is_dsi_present(dev_priv, NULL))
 		return;
 
 	/* Initialize this to undefined indicating no generic MIPI support */
@@ -911,6 +932,7 @@ static void
 parse_mipi_sequence(struct drm_i915_private *dev_priv,
 		    const struct bdb_header *bdb)
 {
+	int panel_type = dev_priv->vbt.panel_type;
 	const struct bdb_mipi_sequence *sequence;
 	const u8 *seq_data;
 	u32 seq_size;
@@ -1124,7 +1146,7 @@ static void parse_ddi_port(struct drm_i9
 	}
 
 	/* Parse the I_boost config for SKL and above */
-	if (bdb->version >= 196 && (child->common.flags_1 & IBOOST_ENABLE)) {
+	if (bdb->version >= 196 && child->common.iboost) {
 		info->dp_boost_level = translate_iboost(child->common.iboost_level & 0xF);
 		DRM_DEBUG_KMS("VBT (e)DP boost level for port %c: %d\n",
 			      port_name(port), info->dp_boost_level);
@@ -1170,7 +1192,7 @@ parse_device_mapping(struct drm_i915_pri
 	}
 	if (bdb->version < 106) {
 		expected_size = 22;
-	} else if (bdb->version < 109) {
+	} else if (bdb->version < 111) {
 		expected_size = 27;
 	} else if (bdb->version < 195) {
 		BUILD_BUG_ON(sizeof(struct old_child_dev_config) != 33);
@@ -1232,14 +1254,6 @@ parse_device_mapping(struct drm_i915_pri
 			continue;
 		}
 
-		if (p_child->common.dvo_port >= DVO_PORT_MIPIA
-		    && p_child->common.dvo_port <= DVO_PORT_MIPID
-		    &&p_child->common.device_type & DEVICE_TYPE_MIPI_OUTPUT) {
-			DRM_DEBUG_KMS("Found MIPI as LFP\n");
-			dev_priv->vbt.has_mipi = 1;
-			dev_priv->vbt.dsi.port = p_child->common.dvo_port;
-		}
-
 		child_dev_ptr = dev_priv->vbt.child_dev + count;
 		count++;
 
@@ -1250,6 +1264,19 @@ parse_device_mapping(struct drm_i915_pri
 		 */
 		memcpy(child_dev_ptr, p_child,
 		       min_t(size_t, p_defs->child_dev_size, sizeof(*p_child)));
+
+		/*
+		 * copied full block, now init values when they are not
+		 * available in current version
+		 */
+		if (bdb->version < 196) {
+			/* Set default values for bits added from v196 */
+			child_dev_ptr->common.iboost = 0;
+			child_dev_ptr->common.hpd_invert = 0;
+		}
+
+		if (bdb->version < 192)
+			child_dev_ptr->common.lspcon = 0;
 	}
 	return;
 }
@@ -1431,3 +1458,285 @@ intel_bios_init(struct drm_i915_private
 
 	return 0;
 }
+
+/**
+ * intel_bios_is_tv_present - is integrated TV present in VBT
+ * @dev_priv:	i915 device instance
+ *
+ * Return true if TV is present. If no child devices were parsed from VBT,
+ * assume TV is present.
+ */
+bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv)
+{
+	union child_device_config *p_child;
+	int i;
+
+	if (!dev_priv->vbt.int_tv_support)
+		return false;
+
+	if (!dev_priv->vbt.child_dev_num)
+		return true;
+
+	for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
+		p_child = dev_priv->vbt.child_dev + i;
+		/*
+		 * If the device type is not TV, continue.
+		 */
+		switch (p_child->old.device_type) {
+		case DEVICE_TYPE_INT_TV:
+		case DEVICE_TYPE_TV:
+		case DEVICE_TYPE_TV_SVIDEO_COMPOSITE:
+			break;
+		default:
+			continue;
+		}
+		/* Only when the addin_offset is non-zero, it is regarded
+		 * as present.
+		 */
+		if (p_child->old.addin_offset)
+			return true;
+	}
+
+	return false;
+}
+
+/**
+ * intel_bios_is_lvds_present - is LVDS present in VBT
+ * @dev_priv:	i915 device instance
+ * @i2c_pin:	i2c pin for LVDS if present
+ *
+ * Return true if LVDS is present. If no child devices were parsed from VBT,
+ * assume LVDS is present.
+ */
+bool intel_bios_is_lvds_present(struct drm_i915_private *dev_priv, u8 *i2c_pin)
+{
+	int i;
+
+	if (!dev_priv->vbt.child_dev_num)
+		return true;
+
+	for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
+		union child_device_config *uchild = dev_priv->vbt.child_dev + i;
+		struct old_child_dev_config *child = &uchild->old;
+
+		/* If the device type is not LFP, continue.
+		 * We have to check both the new identifiers as well as the
+		 * old for compatibility with some BIOSes.
+		 */
+		if (child->device_type != DEVICE_TYPE_INT_LFP &&
+		    child->device_type != DEVICE_TYPE_LFP)
+			continue;
+
+		if (intel_gmbus_is_valid_pin(dev_priv, child->i2c_pin))
+			*i2c_pin = child->i2c_pin;
+
+		/* However, we cannot trust the BIOS writers to populate
+		 * the VBT correctly.  Since LVDS requires additional
+		 * information from AIM blocks, a non-zero addin offset is
+		 * a good indicator that the LVDS is actually present.
+		 */
+		if (child->addin_offset)
+			return true;
+
+		/* But even then some BIOS writers perform some black magic
+		 * and instantiate the device without reference to any
+		 * additional data.  Trust that if the VBT was written into
+		 * the OpRegion then they have validated the LVDS's existence.
+		 */
+		if (dev_priv->opregion.vbt)
+			return true;
+	}
+
+	return false;
+}
+
+/**
+ * intel_bios_is_port_present - is the specified digital port present
+ * @dev_priv:	i915 device instance
+ * @port:	port to check
+ *
+ * Return true if the device in %port is present.
+ */
+bool intel_bios_is_port_present(struct drm_i915_private *dev_priv, enum port port)
+{
+	static const struct {
+		u16 dp, hdmi;
+	} port_mapping[] = {
+		[PORT_B] = { DVO_PORT_DPB, DVO_PORT_HDMIB, },
+		[PORT_C] = { DVO_PORT_DPC, DVO_PORT_HDMIC, },
+		[PORT_D] = { DVO_PORT_DPD, DVO_PORT_HDMID, },
+		[PORT_E] = { DVO_PORT_DPE, DVO_PORT_HDMIE, },
+	};
+	int i;
+
+	/* FIXME maybe deal with port A as well? */
+	if (WARN_ON(port == PORT_A) || port >= ARRAY_SIZE(port_mapping))
+		return false;
+
+	if (!dev_priv->vbt.child_dev_num)
+		return false;
+
+	for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
+		const union child_device_config *p_child =
+			&dev_priv->vbt.child_dev[i];
+		if ((p_child->common.dvo_port == port_mapping[port].dp ||
+		     p_child->common.dvo_port == port_mapping[port].hdmi) &&
+		    (p_child->common.device_type & (DEVICE_TYPE_TMDS_DVI_SIGNALING |
+						    DEVICE_TYPE_DISPLAYPORT_OUTPUT)))
+			return true;
+	}
+
+	return false;
+}
+
+/**
+ * intel_bios_is_port_edp - is the device in given port eDP
+ * @dev_priv:	i915 device instance
+ * @port:	port to check
+ *
+ * Return true if the device in %port is eDP.
+ */
+bool intel_bios_is_port_edp(struct drm_i915_private *dev_priv, enum port port)
+{
+	union child_device_config *p_child;
+	static const short port_mapping[] = {
+		[PORT_B] = DVO_PORT_DPB,
+		[PORT_C] = DVO_PORT_DPC,
+		[PORT_D] = DVO_PORT_DPD,
+		[PORT_E] = DVO_PORT_DPE,
+	};
+	int i;
+
+	if (!dev_priv->vbt.child_dev_num)
+		return false;
+
+	for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
+		p_child = dev_priv->vbt.child_dev + i;
+
+		if (p_child->common.dvo_port == port_mapping[port] &&
+		    (p_child->common.device_type & DEVICE_TYPE_eDP_BITS) ==
+		    (DEVICE_TYPE_eDP & DEVICE_TYPE_eDP_BITS))
+			return true;
+	}
+
+	return false;
+}
+
+bool intel_bios_is_port_dp_dual_mode(struct drm_i915_private *dev_priv, enum port port)
+{
+	static const struct {
+		u16 dp, hdmi;
+	} port_mapping[] = {
+		/*
+		 * Buggy VBTs may declare DP ports as having
+		 * HDMI type dvo_port :( So let's check both.
+		 */
+		[PORT_B] = { DVO_PORT_DPB, DVO_PORT_HDMIB, },
+		[PORT_C] = { DVO_PORT_DPC, DVO_PORT_HDMIC, },
+		[PORT_D] = { DVO_PORT_DPD, DVO_PORT_HDMID, },
+		[PORT_E] = { DVO_PORT_DPE, DVO_PORT_HDMIE, },
+	};
+	int i;
+
+	if (port == PORT_A || port >= ARRAY_SIZE(port_mapping))
+		return false;
+
+	if (!dev_priv->vbt.child_dev_num)
+		return false;
+
+	for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
+		const union child_device_config *p_child =
+			&dev_priv->vbt.child_dev[i];
+
+		if ((p_child->common.dvo_port == port_mapping[port].dp ||
+		     p_child->common.dvo_port == port_mapping[port].hdmi) &&
+		    (p_child->common.device_type & DEVICE_TYPE_DP_DUAL_MODE_BITS) ==
+		    (DEVICE_TYPE_DP_DUAL_MODE & DEVICE_TYPE_DP_DUAL_MODE_BITS))
+			return true;
+	}
+
+	return false;
+}
+
+/**
+ * intel_bios_is_dsi_present - is DSI present in VBT
+ * @dev_priv:	i915 device instance
+ * @port:	port for DSI if present
+ *
+ * Return true if DSI is present, and return the port in %port.
+ */
+bool intel_bios_is_dsi_present(struct drm_i915_private *dev_priv,
+			       enum port *port)
+{
+	union child_device_config *p_child;
+	u8 dvo_port;
+	int i;
+
+	for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
+		p_child = dev_priv->vbt.child_dev + i;
+
+		if (!(p_child->common.device_type & DEVICE_TYPE_MIPI_OUTPUT))
+			continue;
+
+		dvo_port = p_child->common.dvo_port;
+
+		switch (dvo_port) {
+		case DVO_PORT_MIPIA:
+		case DVO_PORT_MIPIC:
+			if (port)
+				*port = dvo_port - DVO_PORT_MIPIA;
+			return true;
+		case DVO_PORT_MIPIB:
+		case DVO_PORT_MIPID:
+			DRM_DEBUG_KMS("VBT has unsupported DSI port %c\n",
+				      port_name(dvo_port - DVO_PORT_MIPIA));
+			break;
+		}
+	}
+
+	return false;
+}
+
+/**
+ * intel_bios_is_port_hpd_inverted - is HPD inverted for %port
+ * @dev_priv:	i915 device instance
+ * @port:	port to check
+ *
+ * Return true if HPD should be inverted for %port.
+ */
+bool
+intel_bios_is_port_hpd_inverted(struct drm_i915_private *dev_priv,
+				enum port port)
+{
+	int i;
+
+	if (WARN_ON_ONCE(!IS_BROXTON(dev_priv)))
+		return false;
+
+	for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
+		if (!dev_priv->vbt.child_dev[i].common.hpd_invert)
+			continue;
+
+		switch (dev_priv->vbt.child_dev[i].common.dvo_port) {
+		case DVO_PORT_DPA:
+		case DVO_PORT_HDMIA:
+			if (port == PORT_A)
+				return true;
+			break;
+		case DVO_PORT_DPB:
+		case DVO_PORT_HDMIB:
+			if (port == PORT_B)
+				return true;
+			break;
+		case DVO_PORT_DPC:
+		case DVO_PORT_HDMIC:
+			if (port == PORT_C)
+				return true;
+			break;
+		default:
+			break;
+		}
+	}
+
+	return false;
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_bios.h linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_bios.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_bios.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_bios.h	2016-07-24 15:23:50.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2006 Intel Corporation
+ * Copyright © 2016 Intel Corporation
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -19,543 +19,16 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
- *
- * Authors:
- *    Eric Anholt <eric@anholt.net>
- *
- */
-
-#ifndef _INTEL_BIOS_H_
-#define _INTEL_BIOS_H_
-
-/**
- * struct vbt_header - VBT Header structure
- * @signature:		VBT signature, always starts with "$VBT"
- * @version:		Version of this structure
- * @header_size:	Size of this structure
- * @vbt_size:		Size of VBT (VBT Header, BDB Header and data blocks)
- * @vbt_checksum:	Checksum
- * @reserved0:		Reserved
- * @bdb_offset:		Offset of &struct bdb_header from beginning of VBT
- * @aim_offset:		Offsets of add-in data blocks from beginning of VBT
- */
-struct vbt_header {
-	u8 signature[20];
-	u16 version;
-	u16 header_size;
-	u16 vbt_size;
-	u8 vbt_checksum;
-	u8 reserved0;
-	u32 bdb_offset;
-	u32 aim_offset[4];
-} __packed;
-
-/**
- * struct bdb_header - BDB Header structure
- * @signature:		BDB signature "BIOS_DATA_BLOCK"
- * @version:		Version of the data block definitions
- * @header_size:	Size of this structure
- * @bdb_size:		Size of BDB (BDB Header and data blocks)
  */
-struct bdb_header {
-	u8 signature[16];
-	u16 version;
-	u16 header_size;
-	u16 bdb_size;
-} __packed;
-
-/* strictly speaking, this is a "skip" block, but it has interesting info */
-struct vbios_data {
-	u8 type; /* 0 == desktop, 1 == mobile */
-	u8 relstage;
-	u8 chipset;
-	u8 lvds_present:1;
-	u8 tv_present:1;
-	u8 rsvd2:6; /* finish byte */
-	u8 rsvd3[4];
-	u8 signon[155];
-	u8 copyright[61];
-	u16 code_segment;
-	u8 dos_boot_mode;
-	u8 bandwidth_percent;
-	u8 rsvd4; /* popup memory size */
-	u8 resize_pci_bios;
-	u8 rsvd5; /* is crt already on ddc2 */
-} __packed;
 
 /*
- * There are several types of BIOS data blocks (BDBs), each block has
- * an ID and size in the first 3 bytes (ID in first, size in next 2).
- * Known types are listed below.
+ * Please use intel_vbt_defs.h for VBT private data, to hide and abstract away
+ * the VBT from the rest of the driver. Add the parsed, clean data to struct
+ * intel_vbt_data within struct drm_i915_private.
  */
-#define BDB_GENERAL_FEATURES	  1
-#define BDB_GENERAL_DEFINITIONS	  2
-#define BDB_OLD_TOGGLE_LIST	  3
-#define BDB_MODE_SUPPORT_LIST	  4
-#define BDB_GENERIC_MODE_TABLE	  5
-#define BDB_EXT_MMIO_REGS	  6
-#define BDB_SWF_IO		  7
-#define BDB_SWF_MMIO		  8
-#define BDB_PSR			  9
-#define BDB_MODE_REMOVAL_TABLE	 10
-#define BDB_CHILD_DEVICE_TABLE	 11
-#define BDB_DRIVER_FEATURES	 12
-#define BDB_DRIVER_PERSISTENCE	 13
-#define BDB_EXT_TABLE_PTRS	 14
-#define BDB_DOT_CLOCK_OVERRIDE	 15
-#define BDB_DISPLAY_SELECT	 16
-/* 17 rsvd */
-#define BDB_DRIVER_ROTATION	 18
-#define BDB_DISPLAY_REMOVE	 19
-#define BDB_OEM_CUSTOM		 20
-#define BDB_EFP_LIST		 21 /* workarounds for VGA hsync/vsync */
-#define BDB_SDVO_LVDS_OPTIONS	 22
-#define BDB_SDVO_PANEL_DTDS	 23
-#define BDB_SDVO_LVDS_PNP_IDS	 24
-#define BDB_SDVO_LVDS_POWER_SEQ	 25
-#define BDB_TV_OPTIONS		 26
-#define BDB_EDP			 27
-#define BDB_LVDS_OPTIONS	 40
-#define BDB_LVDS_LFP_DATA_PTRS	 41
-#define BDB_LVDS_LFP_DATA	 42
-#define BDB_LVDS_BACKLIGHT	 43
-#define BDB_LVDS_POWER		 44
-#define BDB_MIPI_CONFIG		 52
-#define BDB_MIPI_SEQUENCE	 53
-#define BDB_SKIP		254 /* VBIOS private block, ignore */
-
-struct bdb_general_features {
-        /* bits 1 */
-	u8 panel_fitting:2;
-	u8 flexaim:1;
-	u8 msg_enable:1;
-	u8 clear_screen:3;
-	u8 color_flip:1;
-
-        /* bits 2 */
-	u8 download_ext_vbt:1;
-	u8 enable_ssc:1;
-	u8 ssc_freq:1;
-	u8 enable_lfp_on_override:1;
-	u8 disable_ssc_ddt:1;
-	u8 rsvd7:1;
-	u8 display_clock_mode:1;
-	u8 rsvd8:1; /* finish byte */
-
-        /* bits 3 */
-	u8 disable_smooth_vision:1;
-	u8 single_dvi:1;
-	u8 rsvd9:1;
-	u8 fdi_rx_polarity_inverted:1;
-	u8 rsvd10:4; /* finish byte */
-
-        /* bits 4 */
-	u8 legacy_monitor_detect;
-
-        /* bits 5 */
-	u8 int_crt_support:1;
-	u8 int_tv_support:1;
-	u8 int_efp_support:1;
-	u8 dp_ssc_enb:1;	/* PCH attached eDP supports SSC */
-	u8 dp_ssc_freq:1;	/* SSC freq for PCH attached eDP */
-	u8 rsvd11:3; /* finish byte */
-} __packed;
-
-/* pre-915 */
-#define GPIO_PIN_DVI_LVDS	0x03 /* "DVI/LVDS DDC GPIO pins" */
-#define GPIO_PIN_ADD_I2C	0x05 /* "ADDCARD I2C GPIO pins" */
-#define GPIO_PIN_ADD_DDC	0x04 /* "ADDCARD DDC GPIO pins" */
-#define GPIO_PIN_ADD_DDC_I2C	0x06 /* "ADDCARD DDC/I2C GPIO pins" */
-
-/* Pre 915 */
-#define DEVICE_TYPE_NONE	0x00
-#define DEVICE_TYPE_CRT		0x01
-#define DEVICE_TYPE_TV		0x09
-#define DEVICE_TYPE_EFP		0x12
-#define DEVICE_TYPE_LFP		0x22
-/* On 915+ */
-#define DEVICE_TYPE_CRT_DPMS		0x6001
-#define DEVICE_TYPE_CRT_DPMS_HOTPLUG	0x4001
-#define DEVICE_TYPE_TV_COMPOSITE	0x0209
-#define DEVICE_TYPE_TV_MACROVISION	0x0289
-#define DEVICE_TYPE_TV_RF_COMPOSITE	0x020c
-#define DEVICE_TYPE_TV_SVIDEO_COMPOSITE	0x0609
-#define DEVICE_TYPE_TV_SCART		0x0209
-#define DEVICE_TYPE_TV_CODEC_HOTPLUG_PWR 0x6009
-#define DEVICE_TYPE_EFP_HOTPLUG_PWR	0x6012
-#define DEVICE_TYPE_EFP_DVI_HOTPLUG_PWR	0x6052
-#define DEVICE_TYPE_EFP_DVI_I		0x6053
-#define DEVICE_TYPE_EFP_DVI_D_DUAL	0x6152
-#define DEVICE_TYPE_EFP_DVI_D_HDCP	0x60d2
-#define DEVICE_TYPE_OPENLDI_HOTPLUG_PWR	0x6062
-#define DEVICE_TYPE_OPENLDI_DUALPIX	0x6162
-#define DEVICE_TYPE_LFP_PANELLINK	0x5012
-#define DEVICE_TYPE_LFP_CMOS_PWR	0x5042
-#define DEVICE_TYPE_LFP_LVDS_PWR	0x5062
-#define DEVICE_TYPE_LFP_LVDS_DUAL	0x5162
-#define DEVICE_TYPE_LFP_LVDS_DUAL_HDCP	0x51e2
-
-#define DEVICE_CFG_NONE		0x00
-#define DEVICE_CFG_12BIT_DVOB	0x01
-#define DEVICE_CFG_12BIT_DVOC	0x02
-#define DEVICE_CFG_24BIT_DVOBC	0x09
-#define DEVICE_CFG_24BIT_DVOCB	0x0a
-#define DEVICE_CFG_DUAL_DVOB	0x11
-#define DEVICE_CFG_DUAL_DVOC	0x12
-#define DEVICE_CFG_DUAL_DVOBC	0x13
-#define DEVICE_CFG_DUAL_LINK_DVOBC	0x19
-#define DEVICE_CFG_DUAL_LINK_DVOCB	0x1a
-
-#define DEVICE_WIRE_NONE	0x00
-#define DEVICE_WIRE_DVOB	0x01
-#define DEVICE_WIRE_DVOC	0x02
-#define DEVICE_WIRE_DVOBC	0x03
-#define DEVICE_WIRE_DVOBB	0x05
-#define DEVICE_WIRE_DVOCC	0x06
-#define DEVICE_WIRE_DVOB_MASTER 0x0d
-#define DEVICE_WIRE_DVOC_MASTER 0x0e
 
-#define DEVICE_PORT_DVOA	0x00 /* none on 845+ */
-#define DEVICE_PORT_DVOB	0x01
-#define DEVICE_PORT_DVOC	0x02
-
-/*
- * We used to keep this struct but without any version control. We should avoid
- * using it in the future, but it should be safe to keep using it in the old
- * code. Do not change; we rely on its size.
- */
-struct old_child_dev_config {
-	u16 handle;
-	u16 device_type;
-	u8  device_id[10]; /* ascii string */
-	u16 addin_offset;
-	u8  dvo_port; /* See Device_PORT_* above */
-	u8  i2c_pin;
-	u8  slave_addr;
-	u8  ddc_pin;
-	u16 edid_ptr;
-	u8  dvo_cfg; /* See DEVICE_CFG_* above */
-	u8  dvo2_port;
-	u8  i2c2_pin;
-	u8  slave2_addr;
-	u8  ddc2_pin;
-	u8  capabilities;
-	u8  dvo_wiring;/* See DEVICE_WIRE_* above */
-	u8  dvo2_wiring;
-	u16 extended_type;
-	u8  dvo_function;
-} __packed;
-
-/* This one contains field offsets that are known to be common for all BDB
- * versions. Notice that the meaning of the contents contents may still change,
- * but at least the offsets are consistent. */
-
-/* Definitions for flags_1 */
-#define IBOOST_ENABLE (1<<3)
-
-struct common_child_dev_config {
-	u16 handle;
-	u16 device_type;
-	u8 not_common1[12];
-	u8 dvo_port;
-	u8 not_common2[2];
-	u8 ddc_pin;
-	u16 edid_ptr;
-	u8 obsolete;
-	u8 flags_1;
-	u8 not_common3[13];
-	u8 iboost_level;
-} __packed;
-
-
-/* This field changes depending on the BDB version, so the most reliable way to
- * read it is by checking the BDB version and reading the raw pointer. */
-union child_device_config {
-	/* This one is safe to be used anywhere, but the code should still check
-	 * the BDB version. */
-	u8 raw[33];
-	/* This one should only be kept for legacy code. */
-	struct old_child_dev_config old;
-	/* This one should also be safe to use anywhere, even without version
-	 * checks. */
-	struct common_child_dev_config common;
-} __packed;
-
-struct bdb_general_definitions {
-	/* DDC GPIO */
-	u8 crt_ddc_gmbus_pin;
-
-	/* DPMS bits */
-	u8 dpms_acpi:1;
-	u8 skip_boot_crt_detect:1;
-	u8 dpms_aim:1;
-	u8 rsvd1:5; /* finish byte */
-
-	/* boot device bits */
-	u8 boot_display[2];
-	u8 child_dev_size;
-
-	/*
-	 * Device info:
-	 * If TV is present, it'll be at devices[0].
-	 * LVDS will be next, either devices[0] or [1], if present.
-	 * On some platforms the number of device is 6. But could be as few as
-	 * 4 if both TV and LVDS are missing.
-	 * And the device num is related with the size of general definition
-	 * block. It is obtained by using the following formula:
-	 * number = (block_size - sizeof(bdb_general_definitions))/
-	 *	     defs->child_dev_size;
-	 */
-	uint8_t devices[0];
-} __packed;
-
-/* Mask for DRRS / Panel Channel / SSC / BLT control bits extraction */
-#define MODE_MASK		0x3
-
-struct bdb_lvds_options {
-	u8 panel_type;
-	u8 rsvd1;
-	/* LVDS capabilities, stored in a dword */
-	u8 pfit_mode:2;
-	u8 pfit_text_mode_enhanced:1;
-	u8 pfit_gfx_mode_enhanced:1;
-	u8 pfit_ratio_auto:1;
-	u8 pixel_dither:1;
-	u8 lvds_edid:1;
-	u8 rsvd2:1;
-	u8 rsvd4;
-	/* LVDS Panel channel bits stored here */
-	u32 lvds_panel_channel_bits;
-	/* LVDS SSC (Spread Spectrum Clock) bits stored here. */
-	u16 ssc_bits;
-	u16 ssc_freq;
-	u16 ssc_ddt;
-	/* Panel color depth defined here */
-	u16 panel_color_depth;
-	/* LVDS panel type bits stored here */
-	u32 dps_panel_type_bits;
-	/* LVDS backlight control type bits stored here */
-	u32 blt_control_type_bits;
-} __packed;
-
-/* LFP pointer table contains entries to the struct below */
-struct bdb_lvds_lfp_data_ptr {
-	u16 fp_timing_offset; /* offsets are from start of bdb */
-	u8 fp_table_size;
-	u16 dvo_timing_offset;
-	u8 dvo_table_size;
-	u16 panel_pnp_id_offset;
-	u8 pnp_table_size;
-} __packed;
-
-struct bdb_lvds_lfp_data_ptrs {
-	u8 lvds_entries; /* followed by one or more lvds_data_ptr structs */
-	struct bdb_lvds_lfp_data_ptr ptr[16];
-} __packed;
-
-/* LFP data has 3 blocks per entry */
-struct lvds_fp_timing {
-	u16 x_res;
-	u16 y_res;
-	u32 lvds_reg;
-	u32 lvds_reg_val;
-	u32 pp_on_reg;
-	u32 pp_on_reg_val;
-	u32 pp_off_reg;
-	u32 pp_off_reg_val;
-	u32 pp_cycle_reg;
-	u32 pp_cycle_reg_val;
-	u32 pfit_reg;
-	u32 pfit_reg_val;
-	u16 terminator;
-} __packed;
-
-struct lvds_dvo_timing {
-	u16 clock;		/**< In 10khz */
-	u8 hactive_lo;
-	u8 hblank_lo;
-	u8 hblank_hi:4;
-	u8 hactive_hi:4;
-	u8 vactive_lo;
-	u8 vblank_lo;
-	u8 vblank_hi:4;
-	u8 vactive_hi:4;
-	u8 hsync_off_lo;
-	u8 hsync_pulse_width;
-	u8 vsync_pulse_width:4;
-	u8 vsync_off:4;
-	u8 rsvd0:6;
-	u8 hsync_off_hi:2;
-	u8 h_image;
-	u8 v_image;
-	u8 max_hv;
-	u8 h_border;
-	u8 v_border;
-	u8 rsvd1:3;
-	u8 digital:2;
-	u8 vsync_positive:1;
-	u8 hsync_positive:1;
-	u8 rsvd2:1;
-} __packed;
-
-struct lvds_pnp_id {
-	u16 mfg_name;
-	u16 product_code;
-	u32 serial;
-	u8 mfg_week;
-	u8 mfg_year;
-} __packed;
-
-struct bdb_lvds_lfp_data_entry {
-	struct lvds_fp_timing fp_timing;
-	struct lvds_dvo_timing dvo_timing;
-	struct lvds_pnp_id pnp_id;
-} __packed;
-
-struct bdb_lvds_lfp_data {
-	struct bdb_lvds_lfp_data_entry data[16];
-} __packed;
-
-#define BDB_BACKLIGHT_TYPE_NONE	0
-#define BDB_BACKLIGHT_TYPE_PWM	2
-
-struct bdb_lfp_backlight_data_entry {
-	u8 type:2;
-	u8 active_low_pwm:1;
-	u8 obsolete1:5;
-	u16 pwm_freq_hz;
-	u8 min_brightness;
-	u8 obsolete2;
-	u8 obsolete3;
-} __packed;
-
-struct bdb_lfp_backlight_data {
-	u8 entry_size;
-	struct bdb_lfp_backlight_data_entry data[16];
-	u8 level[16];
-} __packed;
-
-struct aimdb_header {
-	char signature[16];
-	char oem_device[20];
-	u16 aimdb_version;
-	u16 aimdb_header_size;
-	u16 aimdb_size;
-} __packed;
-
-struct aimdb_block {
-	u8 aimdb_id;
-	u16 aimdb_size;
-} __packed;
-
-struct vch_panel_data {
-	u16 fp_timing_offset;
-	u8 fp_timing_size;
-	u16 dvo_timing_offset;
-	u8 dvo_timing_size;
-	u16 text_fitting_offset;
-	u8 text_fitting_size;
-	u16 graphics_fitting_offset;
-	u8 graphics_fitting_size;
-} __packed;
-
-struct vch_bdb_22 {
-	struct aimdb_block aimdb_block;
-	struct vch_panel_data panels[16];
-} __packed;
-
-struct bdb_sdvo_lvds_options {
-	u8 panel_backlight;
-	u8 h40_set_panel_type;
-	u8 panel_type;
-	u8 ssc_clk_freq;
-	u16 als_low_trip;
-	u16 als_high_trip;
-	u8 sclalarcoeff_tab_row_num;
-	u8 sclalarcoeff_tab_row_size;
-	u8 coefficient[8];
-	u8 panel_misc_bits_1;
-	u8 panel_misc_bits_2;
-	u8 panel_misc_bits_3;
-	u8 panel_misc_bits_4;
-} __packed;
-
-
-#define BDB_DRIVER_FEATURE_NO_LVDS		0
-#define BDB_DRIVER_FEATURE_INT_LVDS		1
-#define BDB_DRIVER_FEATURE_SDVO_LVDS		2
-#define BDB_DRIVER_FEATURE_EDP			3
-
-struct bdb_driver_features {
-	u8 boot_dev_algorithm:1;
-	u8 block_display_switch:1;
-	u8 allow_display_switch:1;
-	u8 hotplug_dvo:1;
-	u8 dual_view_zoom:1;
-	u8 int15h_hook:1;
-	u8 sprite_in_clone:1;
-	u8 primary_lfp_id:1;
-
-	u16 boot_mode_x;
-	u16 boot_mode_y;
-	u8 boot_mode_bpp;
-	u8 boot_mode_refresh;
-
-	u16 enable_lfp_primary:1;
-	u16 selective_mode_pruning:1;
-	u16 dual_frequency:1;
-	u16 render_clock_freq:1; /* 0: high freq; 1: low freq */
-	u16 nt_clone_support:1;
-	u16 power_scheme_ui:1; /* 0: CUI; 1: 3rd party */
-	u16 sprite_display_assign:1; /* 0: secondary; 1: primary */
-	u16 cui_aspect_scaling:1;
-	u16 preserve_aspect_ratio:1;
-	u16 sdvo_device_power_down:1;
-	u16 crt_hotplug:1;
-	u16 lvds_config:2;
-	u16 tv_hotplug:1;
-	u16 hdmi_config:2;
-
-	u8 static_display:1;
-	u8 reserved2:7;
-	u16 legacy_crt_max_x;
-	u16 legacy_crt_max_y;
-	u8 legacy_crt_max_refresh;
-
-	u8 hdmi_termination;
-	u8 custom_vbt_version;
-	/* Driver features data block */
-	u16 rmpm_enabled:1;
-	u16 s2ddt_enabled:1;
-	u16 dpst_enabled:1;
-	u16 bltclt_enabled:1;
-	u16 adb_enabled:1;
-	u16 drrs_enabled:1;
-	u16 grs_enabled:1;
-	u16 gpmt_enabled:1;
-	u16 tbt_enabled:1;
-	u16 psr_enabled:1;
-	u16 ips_enabled:1;
-	u16 reserved3:4;
-	u16 pc_feature_valid:1;
-} __packed;
-
-#define EDP_18BPP	0
-#define EDP_24BPP	1
-#define EDP_30BPP	2
-#define EDP_RATE_1_62	0
-#define EDP_RATE_2_7	1
-#define EDP_LANE_1	0
-#define EDP_LANE_2	1
-#define EDP_LANE_4	3
-#define EDP_PREEMPHASIS_NONE	0
-#define EDP_PREEMPHASIS_3_5dB	1
-#define EDP_PREEMPHASIS_6dB	2
-#define EDP_PREEMPHASIS_9_5dB	3
-#define EDP_VSWING_0_4V		0
-#define EDP_VSWING_0_6V		1
-#define EDP_VSWING_0_8V		2
-#define EDP_VSWING_1_2V		3
+#ifndef _INTEL_BIOS_H_
+#define _INTEL_BIOS_H_
 
 struct edp_power_seq {
 	u16 t1_t3;
@@ -565,245 +38,37 @@ struct edp_power_seq {
 	u16 t11_t12;
 } __packed;
 
-struct edp_link_params {
-	u8 rate:4;
-	u8 lanes:4;
-	u8 preemphasis:4;
-	u8 vswing:4;
-} __packed;
-
-struct bdb_edp {
-	struct edp_power_seq power_seqs[16];
-	u32 color_depth;
-	struct edp_link_params link_params[16];
-	u32 sdrrs_msa_timing_delay;
-
-	/* ith bit indicates enabled/disabled for (i+1)th panel */
-	u16 edp_s3d_feature;
-	u16 edp_t3_optimization;
-	u64 edp_vswing_preemph;		/* v173 */
-} __packed;
-
-struct psr_table {
-	/* Feature bits */
-	u8 full_link:1;
-	u8 require_aux_to_wakeup:1;
-	u8 feature_bits_rsvd:6;
-
-	/* Wait times */
-	u8 idle_frames:4;
-	u8 lines_to_wait:3;
-	u8 wait_times_rsvd:1;
-
-	/* TP wake up time in multiple of 100 */
-	u16 tp1_wakeup_time;
-	u16 tp2_tp3_wakeup_time;
-} __packed;
-
-struct bdb_psr {
-	struct psr_table psr_table[16];
-} __packed;
-
-/*
- * Driver<->VBIOS interaction occurs through scratch bits in
- * GR18 & SWF*.
- */
-
-/* GR18 bits are set on display switch and hotkey events */
-#define GR18_DRIVER_SWITCH_EN	(1<<7) /* 0: VBIOS control, 1: driver control */
-#define GR18_HOTKEY_MASK	0x78 /* See also SWF4 15:0 */
-#define   GR18_HK_NONE		(0x0<<3)
-#define   GR18_HK_LFP_STRETCH	(0x1<<3)
-#define   GR18_HK_TOGGLE_DISP	(0x2<<3)
-#define   GR18_HK_DISP_SWITCH	(0x4<<3) /* see SWF14 15:0 for what to enable */
-#define   GR18_HK_POPUP_DISABLED (0x6<<3)
-#define   GR18_HK_POPUP_ENABLED	(0x7<<3)
-#define   GR18_HK_PFIT		(0x8<<3)
-#define   GR18_HK_APM_CHANGE	(0xa<<3)
-#define   GR18_HK_MULTIPLE	(0xc<<3)
-#define GR18_USER_INT_EN	(1<<2)
-#define GR18_A0000_FLUSH_EN	(1<<1)
-#define GR18_SMM_EN		(1<<0)
-
-/* Set by driver, cleared by VBIOS */
-#define SWF00_YRES_SHIFT	16
-#define SWF00_XRES_SHIFT	0
-#define SWF00_RES_MASK		0xffff
-
-/* Set by VBIOS at boot time and driver at runtime */
-#define SWF01_TV2_FORMAT_SHIFT	8
-#define SWF01_TV1_FORMAT_SHIFT	0
-#define SWF01_TV_FORMAT_MASK	0xffff
-
-#define SWF10_VBIOS_BLC_I2C_EN	(1<<29)
-#define SWF10_GTT_OVERRIDE_EN	(1<<28)
-#define SWF10_LFP_DPMS_OVR	(1<<27) /* override DPMS on display switch */
-#define SWF10_ACTIVE_TOGGLE_LIST_MASK (7<<24)
-#define   SWF10_OLD_TOGGLE	0x0
-#define   SWF10_TOGGLE_LIST_1	0x1
-#define   SWF10_TOGGLE_LIST_2	0x2
-#define   SWF10_TOGGLE_LIST_3	0x3
-#define   SWF10_TOGGLE_LIST_4	0x4
-#define SWF10_PANNING_EN	(1<<23)
-#define SWF10_DRIVER_LOADED	(1<<22)
-#define SWF10_EXTENDED_DESKTOP	(1<<21)
-#define SWF10_EXCLUSIVE_MODE	(1<<20)
-#define SWF10_OVERLAY_EN	(1<<19)
-#define SWF10_PLANEB_HOLDOFF	(1<<18)
-#define SWF10_PLANEA_HOLDOFF	(1<<17)
-#define SWF10_VGA_HOLDOFF	(1<<16)
-#define SWF10_ACTIVE_DISP_MASK	0xffff
-#define   SWF10_PIPEB_LFP2	(1<<15)
-#define   SWF10_PIPEB_EFP2	(1<<14)
-#define   SWF10_PIPEB_TV2	(1<<13)
-#define   SWF10_PIPEB_CRT2	(1<<12)
-#define   SWF10_PIPEB_LFP	(1<<11)
-#define   SWF10_PIPEB_EFP	(1<<10)
-#define   SWF10_PIPEB_TV	(1<<9)
-#define   SWF10_PIPEB_CRT	(1<<8)
-#define   SWF10_PIPEA_LFP2	(1<<7)
-#define   SWF10_PIPEA_EFP2	(1<<6)
-#define   SWF10_PIPEA_TV2	(1<<5)
-#define   SWF10_PIPEA_CRT2	(1<<4)
-#define   SWF10_PIPEA_LFP	(1<<3)
-#define   SWF10_PIPEA_EFP	(1<<2)
-#define   SWF10_PIPEA_TV	(1<<1)
-#define   SWF10_PIPEA_CRT	(1<<0)
-
-#define SWF11_MEMORY_SIZE_SHIFT	16
-#define SWF11_SV_TEST_EN	(1<<15)
-#define SWF11_IS_AGP		(1<<14)
-#define SWF11_DISPLAY_HOLDOFF	(1<<13)
-#define SWF11_DPMS_REDUCED	(1<<12)
-#define SWF11_IS_VBE_MODE	(1<<11)
-#define SWF11_PIPEB_ACCESS	(1<<10) /* 0 here means pipe a */
-#define SWF11_DPMS_MASK		0x07
-#define   SWF11_DPMS_OFF	(1<<2)
-#define   SWF11_DPMS_SUSPEND	(1<<1)
-#define   SWF11_DPMS_STANDBY	(1<<0)
-#define   SWF11_DPMS_ON		0
-
-#define SWF14_GFX_PFIT_EN	(1<<31)
-#define SWF14_TEXT_PFIT_EN	(1<<30)
-#define SWF14_LID_STATUS_CLOSED	(1<<29) /* 0 here means open */
-#define SWF14_POPUP_EN		(1<<28)
-#define SWF14_DISPLAY_HOLDOFF	(1<<27)
-#define SWF14_DISP_DETECT_EN	(1<<26)
-#define SWF14_DOCKING_STATUS_DOCKED (1<<25) /* 0 here means undocked */
-#define SWF14_DRIVER_STATUS	(1<<24)
-#define SWF14_OS_TYPE_WIN9X	(1<<23)
-#define SWF14_OS_TYPE_WINNT	(1<<22)
-/* 21:19 rsvd */
-#define SWF14_PM_TYPE_MASK	0x00070000
-#define   SWF14_PM_ACPI_VIDEO	(0x4 << 16)
-#define   SWF14_PM_ACPI		(0x3 << 16)
-#define   SWF14_PM_APM_12	(0x2 << 16)
-#define   SWF14_PM_APM_11	(0x1 << 16)
-#define SWF14_HK_REQUEST_MASK	0x0000ffff /* see GR18 6:3 for event type */
-          /* if GR18 indicates a display switch */
-#define   SWF14_DS_PIPEB_LFP2_EN (1<<15)
-#define   SWF14_DS_PIPEB_EFP2_EN (1<<14)
-#define   SWF14_DS_PIPEB_TV2_EN  (1<<13)
-#define   SWF14_DS_PIPEB_CRT2_EN (1<<12)
-#define   SWF14_DS_PIPEB_LFP_EN  (1<<11)
-#define   SWF14_DS_PIPEB_EFP_EN  (1<<10)
-#define   SWF14_DS_PIPEB_TV_EN   (1<<9)
-#define   SWF14_DS_PIPEB_CRT_EN  (1<<8)
-#define   SWF14_DS_PIPEA_LFP2_EN (1<<7)
-#define   SWF14_DS_PIPEA_EFP2_EN (1<<6)
-#define   SWF14_DS_PIPEA_TV2_EN  (1<<5)
-#define   SWF14_DS_PIPEA_CRT2_EN (1<<4)
-#define   SWF14_DS_PIPEA_LFP_EN  (1<<3)
-#define   SWF14_DS_PIPEA_EFP_EN  (1<<2)
-#define   SWF14_DS_PIPEA_TV_EN   (1<<1)
-#define   SWF14_DS_PIPEA_CRT_EN  (1<<0)
-          /* if GR18 indicates a panel fitting request */
-#define   SWF14_PFIT_EN		(1<<0) /* 0 means disable */
-          /* if GR18 indicates an APM change request */
-#define   SWF14_APM_HIBERNATE	0x4
-#define   SWF14_APM_SUSPEND	0x3
-#define   SWF14_APM_STANDBY	0x1
-#define   SWF14_APM_RESTORE	0x0
-
-/* Add the device class for LFP, TV, HDMI */
-#define	 DEVICE_TYPE_INT_LFP	0x1022
-#define	 DEVICE_TYPE_INT_TV	0x1009
-#define	 DEVICE_TYPE_HDMI	0x60D2
-#define	 DEVICE_TYPE_DP		0x68C6
-#define	 DEVICE_TYPE_eDP	0x78C6
-
-#define  DEVICE_TYPE_CLASS_EXTENSION	(1 << 15)
-#define  DEVICE_TYPE_POWER_MANAGEMENT	(1 << 14)
-#define  DEVICE_TYPE_HOTPLUG_SIGNALING	(1 << 13)
-#define  DEVICE_TYPE_INTERNAL_CONNECTOR	(1 << 12)
-#define  DEVICE_TYPE_NOT_HDMI_OUTPUT	(1 << 11)
-#define  DEVICE_TYPE_MIPI_OUTPUT	(1 << 10)
-#define  DEVICE_TYPE_COMPOSITE_OUTPUT	(1 << 9)
-#define  DEVICE_TYPE_DUAL_CHANNEL	(1 << 8)
-#define  DEVICE_TYPE_HIGH_SPEED_LINK	(1 << 6)
-#define  DEVICE_TYPE_LVDS_SINGALING	(1 << 5)
-#define  DEVICE_TYPE_TMDS_DVI_SIGNALING	(1 << 4)
-#define  DEVICE_TYPE_VIDEO_SIGNALING	(1 << 3)
-#define  DEVICE_TYPE_DISPLAYPORT_OUTPUT	(1 << 2)
-#define  DEVICE_TYPE_DIGITAL_OUTPUT	(1 << 1)
-#define  DEVICE_TYPE_ANALOG_OUTPUT	(1 << 0)
-
-/*
- * Bits we care about when checking for DEVICE_TYPE_eDP
- * Depending on the system, the other bits may or may not
- * be set for eDP outputs.
- */
-#define DEVICE_TYPE_eDP_BITS \
-	(DEVICE_TYPE_INTERNAL_CONNECTOR | \
-	 DEVICE_TYPE_MIPI_OUTPUT | \
-	 DEVICE_TYPE_COMPOSITE_OUTPUT | \
-	 DEVICE_TYPE_DUAL_CHANNEL | \
-	 DEVICE_TYPE_LVDS_SINGALING | \
-	 DEVICE_TYPE_TMDS_DVI_SIGNALING | \
-	 DEVICE_TYPE_VIDEO_SIGNALING | \
-	 DEVICE_TYPE_DISPLAYPORT_OUTPUT | \
-	 DEVICE_TYPE_ANALOG_OUTPUT)
-
-/* define the DVO port for HDMI output type */
-#define		DVO_B		1
-#define		DVO_C		2
-#define		DVO_D		3
-
-/* Possible values for the "DVO Port" field for versions >= 155: */
-#define DVO_PORT_HDMIA	0
-#define DVO_PORT_HDMIB	1
-#define DVO_PORT_HDMIC	2
-#define DVO_PORT_HDMID	3
-#define DVO_PORT_LVDS	4
-#define DVO_PORT_TV	5
-#define DVO_PORT_CRT	6
-#define DVO_PORT_DPB	7
-#define DVO_PORT_DPC	8
-#define DVO_PORT_DPD	9
-#define DVO_PORT_DPA	10
-#define DVO_PORT_DPE	11
-#define DVO_PORT_HDMIE	12
-#define DVO_PORT_MIPIA	21
-#define DVO_PORT_MIPIB	22
-#define DVO_PORT_MIPIC	23
-#define DVO_PORT_MIPID	24
+/* MIPI Sequence Block definitions */
+enum mipi_seq {
+	MIPI_SEQ_END = 0,
+	MIPI_SEQ_ASSERT_RESET,
+	MIPI_SEQ_INIT_OTP,
+	MIPI_SEQ_DISPLAY_ON,
+	MIPI_SEQ_DISPLAY_OFF,
+	MIPI_SEQ_DEASSERT_RESET,
+	MIPI_SEQ_BACKLIGHT_ON,		/* sequence block v2+ */
+	MIPI_SEQ_BACKLIGHT_OFF,		/* sequence block v2+ */
+	MIPI_SEQ_TEAR_ON,		/* sequence block v2+ */
+	MIPI_SEQ_TEAR_OFF,		/* sequence block v3+ */
+	MIPI_SEQ_POWER_ON,		/* sequence block v3+ */
+	MIPI_SEQ_POWER_OFF,		/* sequence block v3+ */
+	MIPI_SEQ_MAX
+};
 
-/* Block 52 contains MIPI Panel info
- * 6 such enteries will there. Index into correct
- * entery is based on the panel_index in #40 LFP
- */
-#define MAX_MIPI_CONFIGURATIONS	6
+enum mipi_seq_element {
+	MIPI_SEQ_ELEM_END = 0,
+	MIPI_SEQ_ELEM_SEND_PKT,
+	MIPI_SEQ_ELEM_DELAY,
+	MIPI_SEQ_ELEM_GPIO,
+	MIPI_SEQ_ELEM_I2C,		/* sequence block v2+ */
+	MIPI_SEQ_ELEM_SPI,		/* sequence block v3+ */
+	MIPI_SEQ_ELEM_PMIC,		/* sequence block v3+ */
+	MIPI_SEQ_ELEM_MAX
+};
 
 #define MIPI_DSI_UNDEFINED_PANEL_ID	0
 #define MIPI_DSI_GENERIC_PANEL_ID	1
 
-/*
- * PMIC vs SoC Backlight support specified in pwm_blc
- * field in mipi_config block below.
-*/
-#define PPS_BLC_PMIC   0
-#define PPS_BLC_SOC    1
-
 struct mipi_config {
 	u16 panel_id;
 
@@ -821,6 +86,8 @@ struct mipi_config {
 	u32 video_transfer_mode:2;
 
 	u32 cabc_supported:1;
+#define PPS_BLC_PMIC   0
+#define PPS_BLC_SOC    1
 	u32 pwm_blc:1;
 
 	/* Bit 13:10 */
@@ -924,12 +191,7 @@ struct mipi_config {
 
 } __packed;
 
-/* Block 52 contains MIPI configuration block
- * 6 * bdb_mipi_config, followed by 6 pps data
- * block below
- *
- * all delays has a unit of 100us
- */
+/* all delays have a unit of 100us */
 struct mipi_pps_data {
 	u16 panel_on_delay;
 	u16 bl_enable_delay;
@@ -938,57 +200,4 @@ struct mipi_pps_data {
 	u16 panel_power_cycle_delay;
 } __packed;
 
-struct bdb_mipi_config {
-	struct mipi_config config[MAX_MIPI_CONFIGURATIONS];
-	struct mipi_pps_data pps[MAX_MIPI_CONFIGURATIONS];
-} __packed;
-
-/* Block 53 contains MIPI sequences as needed by the panel
- * for enabling it. This block can be variable in size and
- * can be maximum of 6 blocks
- */
-struct bdb_mipi_sequence {
-	u8 version;
-	u8 data[0];
-} __packed;
-
-/* MIPI Sequnece Block definitions */
-enum mipi_seq {
-	MIPI_SEQ_END = 0,
-	MIPI_SEQ_ASSERT_RESET,
-	MIPI_SEQ_INIT_OTP,
-	MIPI_SEQ_DISPLAY_ON,
-	MIPI_SEQ_DISPLAY_OFF,
-	MIPI_SEQ_DEASSERT_RESET,
-	MIPI_SEQ_BACKLIGHT_ON,		/* sequence block v2+ */
-	MIPI_SEQ_BACKLIGHT_OFF,		/* sequence block v2+ */
-	MIPI_SEQ_TEAR_ON,		/* sequence block v2+ */
-	MIPI_SEQ_TEAR_OFF,		/* sequence block v3+ */
-	MIPI_SEQ_POWER_ON,		/* sequence block v3+ */
-	MIPI_SEQ_POWER_OFF,		/* sequence block v3+ */
-	MIPI_SEQ_MAX
-};
-
-enum mipi_seq_element {
-	MIPI_SEQ_ELEM_END = 0,
-	MIPI_SEQ_ELEM_SEND_PKT,
-	MIPI_SEQ_ELEM_DELAY,
-	MIPI_SEQ_ELEM_GPIO,
-	MIPI_SEQ_ELEM_I2C,		/* sequence block v2+ */
-	MIPI_SEQ_ELEM_SPI,		/* sequence block v3+ */
-	MIPI_SEQ_ELEM_PMIC,		/* sequence block v3+ */
-	MIPI_SEQ_ELEM_MAX
-};
-
-enum mipi_gpio_pin_index {
-	MIPI_GPIO_UNDEFINED = 0,
-	MIPI_GPIO_PANEL_ENABLE,
-	MIPI_GPIO_BL_ENABLE,
-	MIPI_GPIO_PWM_ENABLE,
-	MIPI_GPIO_RESET_N,
-	MIPI_GPIO_PWR_DOWN_R,
-	MIPI_GPIO_STDBY_RST_N,
-	MIPI_GPIO_MAX
-};
-
 #endif /* _INTEL_BIOS_H_ */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_color.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_color.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_color.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_color.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,553 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "intel_drv.h"
+
+#define CTM_COEFF_SIGN	(1ULL << 63)
+
+#define CTM_COEFF_1_0	(1ULL << 32)
+#define CTM_COEFF_2_0	(CTM_COEFF_1_0 << 1)
+#define CTM_COEFF_4_0	(CTM_COEFF_2_0 << 1)
+#define CTM_COEFF_8_0	(CTM_COEFF_4_0 << 1)
+#define CTM_COEFF_0_5	(CTM_COEFF_1_0 >> 1)
+#define CTM_COEFF_0_25	(CTM_COEFF_0_5 >> 1)
+#define CTM_COEFF_0_125	(CTM_COEFF_0_25 >> 1)
+
+#define CTM_COEFF_LIMITED_RANGE ((235ULL - 16ULL) * CTM_COEFF_1_0 / 255)
+
+#define CTM_COEFF_NEGATIVE(coeff)	(((coeff) & CTM_COEFF_SIGN) != 0)
+#define CTM_COEFF_ABS(coeff)		((coeff) & (CTM_COEFF_SIGN - 1))
+
+#define LEGACY_LUT_LENGTH		(sizeof(struct drm_color_lut) * 256)
+
+/*
+ * Extract the CSC coefficient from a CTM coefficient (in U32.32 fixed point
+ * format). This macro takes the coefficient we want transformed and the
+ * number of fractional bits.
+ *
+ * We only have a 9 bits precision window which slides depending on the value
+ * of the CTM coefficient and we write the value from bit 3. We also round the
+ * value.
+ */
+#define I9XX_CSC_COEFF_FP(coeff, fbits)	\
+	(clamp_val(((coeff) >> (32 - (fbits) - 3)) + 4, 0, 0xfff) & 0xff8)
+
+#define I9XX_CSC_COEFF_LIMITED_RANGE	\
+	I9XX_CSC_COEFF_FP(CTM_COEFF_LIMITED_RANGE, 9)
+#define I9XX_CSC_COEFF_1_0		\
+	((7 << 12) | I9XX_CSC_COEFF_FP(CTM_COEFF_1_0, 8))
+
+static bool crtc_state_is_legacy(struct drm_crtc_state *state)
+{
+	return !state->degamma_lut &&
+		!state->ctm &&
+		state->gamma_lut &&
+		state->gamma_lut->length == LEGACY_LUT_LENGTH;
+}
+
+/*
+ * When using limited range, multiply the matrix given by userspace by
+ * the matrix that we would use for the limited range. We do the
+ * multiplication in U2.30 format.
+ */
+static void ctm_mult_by_limited(uint64_t *result, int64_t *input)
+{
+	int i;
+
+	for (i = 0; i < 9; i++)
+		result[i] = 0;
+
+	for (i = 0; i < 3; i++) {
+		int64_t user_coeff = input[i * 3 + i];
+		uint64_t limited_coeff = CTM_COEFF_LIMITED_RANGE >> 2;
+		uint64_t abs_coeff = clamp_val(CTM_COEFF_ABS(user_coeff),
+					       0,
+					       CTM_COEFF_4_0 - 1) >> 2;
+
+		result[i * 3 + i] = (limited_coeff * abs_coeff) >> 27;
+		if (CTM_COEFF_NEGATIVE(user_coeff))
+			result[i * 3 + i] |= CTM_COEFF_SIGN;
+	}
+}
+
+/* Set up the pipe CSC unit. */
+static void i9xx_load_csc_matrix(struct drm_crtc_state *crtc_state)
+{
+	struct drm_crtc *crtc = crtc_state->crtc;
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	int i, pipe = intel_crtc->pipe;
+	uint16_t coeffs[9] = { 0, };
+
+	if (crtc_state->ctm) {
+		struct drm_color_ctm *ctm =
+			(struct drm_color_ctm *)crtc_state->ctm->data;
+		uint64_t input[9] = { 0, };
+
+		if (intel_crtc->config->limited_color_range) {
+			ctm_mult_by_limited(input, ctm->matrix);
+		} else {
+			for (i = 0; i < ARRAY_SIZE(input); i++)
+				input[i] = ctm->matrix[i];
+		}
+
+		/*
+		 * Convert fixed point S31.32 input to format supported by the
+		 * hardware.
+		 */
+		for (i = 0; i < ARRAY_SIZE(coeffs); i++) {
+			uint64_t abs_coeff = ((1ULL << 63) - 1) & input[i];
+
+			/*
+			 * Clamp input value to min/max supported by
+			 * hardware.
+			 */
+			abs_coeff = clamp_val(abs_coeff, 0, CTM_COEFF_4_0 - 1);
+
+			/* sign bit */
+			if (CTM_COEFF_NEGATIVE(input[i]))
+				coeffs[i] |= 1 << 15;
+
+			if (abs_coeff < CTM_COEFF_0_125)
+				coeffs[i] |= (3 << 12) |
+					I9XX_CSC_COEFF_FP(abs_coeff, 12);
+			else if (abs_coeff < CTM_COEFF_0_25)
+				coeffs[i] |= (2 << 12) |
+					I9XX_CSC_COEFF_FP(abs_coeff, 11);
+			else if (abs_coeff < CTM_COEFF_0_5)
+				coeffs[i] |= (1 << 12) |
+					I9XX_CSC_COEFF_FP(abs_coeff, 10);
+			else if (abs_coeff < CTM_COEFF_1_0)
+				coeffs[i] |= I9XX_CSC_COEFF_FP(abs_coeff, 9);
+			else if (abs_coeff < CTM_COEFF_2_0)
+				coeffs[i] |= (7 << 12) |
+					I9XX_CSC_COEFF_FP(abs_coeff, 8);
+			else
+				coeffs[i] |= (6 << 12) |
+					I9XX_CSC_COEFF_FP(abs_coeff, 7);
+		}
+	} else {
+		/*
+		 * Load an identity matrix if no coefficients are provided.
+		 *
+		 * TODO: Check what kind of values actually come out of the
+		 * pipe with these coeff/postoff values and adjust to get the
+		 * best accuracy. Perhaps we even need to take the bpc value
+		 * into consideration.
+		 */
+		for (i = 0; i < 3; i++) {
+			if (intel_crtc->config->limited_color_range)
+				coeffs[i * 3 + i] =
+					I9XX_CSC_COEFF_LIMITED_RANGE;
+			else
+				coeffs[i * 3 + i] = I9XX_CSC_COEFF_1_0;
+		}
+	}
+
+	I915_WRITE(PIPE_CSC_COEFF_RY_GY(pipe), coeffs[0] << 16 | coeffs[1]);
+	I915_WRITE(PIPE_CSC_COEFF_BY(pipe), coeffs[2] << 16);
+
+	I915_WRITE(PIPE_CSC_COEFF_RU_GU(pipe), coeffs[3] << 16 | coeffs[4]);
+	I915_WRITE(PIPE_CSC_COEFF_BU(pipe), coeffs[5] << 16);
+
+	I915_WRITE(PIPE_CSC_COEFF_RV_GV(pipe), coeffs[6] << 16 | coeffs[7]);
+	I915_WRITE(PIPE_CSC_COEFF_BV(pipe), coeffs[8] << 16);
+
+	I915_WRITE(PIPE_CSC_PREOFF_HI(pipe), 0);
+	I915_WRITE(PIPE_CSC_PREOFF_ME(pipe), 0);
+	I915_WRITE(PIPE_CSC_PREOFF_LO(pipe), 0);
+
+	if (INTEL_INFO(dev)->gen > 6) {
+		uint16_t postoff = 0;
+
+		if (intel_crtc->config->limited_color_range)
+			postoff = (16 * (1 << 12) / 255) & 0x1fff;
+
+		I915_WRITE(PIPE_CSC_POSTOFF_HI(pipe), postoff);
+		I915_WRITE(PIPE_CSC_POSTOFF_ME(pipe), postoff);
+		I915_WRITE(PIPE_CSC_POSTOFF_LO(pipe), postoff);
+
+		I915_WRITE(PIPE_CSC_MODE(pipe), 0);
+	} else {
+		uint32_t mode = CSC_MODE_YUV_TO_RGB;
+
+		if (intel_crtc->config->limited_color_range)
+			mode |= CSC_BLACK_SCREEN_OFFSET;
+
+		I915_WRITE(PIPE_CSC_MODE(pipe), mode);
+	}
+}
+
+/*
+ * Set up the pipe CSC unit on CherryView.
+ */
+static void cherryview_load_csc_matrix(struct drm_crtc_state *state)
+{
+	struct drm_crtc *crtc = state->crtc;
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int pipe = to_intel_crtc(crtc)->pipe;
+	uint32_t mode;
+
+	if (state->ctm) {
+		struct drm_color_ctm *ctm =
+			(struct drm_color_ctm *) state->ctm->data;
+		uint16_t coeffs[9] = { 0, };
+		int i;
+
+		for (i = 0; i < ARRAY_SIZE(coeffs); i++) {
+			uint64_t abs_coeff =
+				((1ULL << 63) - 1) & ctm->matrix[i];
+
+			/* Round coefficient. */
+			abs_coeff += 1 << (32 - 13);
+			/* Clamp to hardware limits. */
+			abs_coeff = clamp_val(abs_coeff, 0, CTM_COEFF_8_0 - 1);
+
+			/* Write coefficients in S3.12 format. */
+			if (ctm->matrix[i] & (1ULL << 63))
+				coeffs[i] = 1 << 15;
+			coeffs[i] |= ((abs_coeff >> 32) & 7) << 12;
+			coeffs[i] |= (abs_coeff >> 20) & 0xfff;
+		}
+
+		I915_WRITE(CGM_PIPE_CSC_COEFF01(pipe),
+			   coeffs[1] << 16 | coeffs[0]);
+		I915_WRITE(CGM_PIPE_CSC_COEFF23(pipe),
+			   coeffs[3] << 16 | coeffs[2]);
+		I915_WRITE(CGM_PIPE_CSC_COEFF45(pipe),
+			   coeffs[5] << 16 | coeffs[4]);
+		I915_WRITE(CGM_PIPE_CSC_COEFF67(pipe),
+			   coeffs[7] << 16 | coeffs[6]);
+		I915_WRITE(CGM_PIPE_CSC_COEFF8(pipe), coeffs[8]);
+	}
+
+	mode = (state->ctm ? CGM_PIPE_MODE_CSC : 0);
+	if (!crtc_state_is_legacy(state)) {
+		mode |= (state->degamma_lut ? CGM_PIPE_MODE_DEGAMMA : 0) |
+			(state->gamma_lut ? CGM_PIPE_MODE_GAMMA : 0);
+	}
+	I915_WRITE(CGM_PIPE_MODE(pipe), mode);
+}
+
+void intel_color_set_csc(struct drm_crtc_state *crtc_state)
+{
+	struct drm_device *dev = crtc_state->crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (dev_priv->display.load_csc_matrix)
+		dev_priv->display.load_csc_matrix(crtc_state);
+}
+
+/* Loads the legacy palette/gamma unit for the CRTC. */
+static void i9xx_load_luts_internal(struct drm_crtc *crtc,
+				    struct drm_property_blob *blob)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	enum pipe pipe = intel_crtc->pipe;
+	int i;
+
+	if (HAS_GMCH_DISPLAY(dev)) {
+		if (intel_crtc->config->has_dsi_encoder)
+			assert_dsi_pll_enabled(dev_priv);
+		else
+			assert_pll_enabled(dev_priv, pipe);
+	}
+
+	if (blob) {
+		struct drm_color_lut *lut = (struct drm_color_lut *) blob->data;
+		for (i = 0; i < 256; i++) {
+			uint32_t word =
+				(drm_color_lut_extract(lut[i].red, 8) << 16) |
+				(drm_color_lut_extract(lut[i].green, 8) << 8) |
+				drm_color_lut_extract(lut[i].blue, 8);
+
+			if (HAS_GMCH_DISPLAY(dev))
+				I915_WRITE(PALETTE(pipe, i), word);
+			else
+				I915_WRITE(LGC_PALETTE(pipe, i), word);
+		}
+	} else {
+		for (i = 0; i < 256; i++) {
+			uint32_t word = (i << 16) | (i << 8) | i;
+
+			if (HAS_GMCH_DISPLAY(dev))
+				I915_WRITE(PALETTE(pipe, i), word);
+			else
+				I915_WRITE(LGC_PALETTE(pipe, i), word);
+		}
+	}
+}
+
+static void i9xx_load_luts(struct drm_crtc_state *crtc_state)
+{
+	i9xx_load_luts_internal(crtc_state->crtc, crtc_state->gamma_lut);
+}
+
+/* Loads the legacy palette/gamma unit for the CRTC on Haswell. */
+static void haswell_load_luts(struct drm_crtc_state *crtc_state)
+{
+	struct drm_crtc *crtc = crtc_state->crtc;
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_crtc_state *intel_crtc_state =
+		to_intel_crtc_state(crtc_state);
+	bool reenable_ips = false;
+
+	/*
+	 * Workaround : Do not read or write the pipe palette/gamma data while
+	 * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled.
+	 */
+	if (IS_HASWELL(dev) && intel_crtc->config->ips_enabled &&
+	    (intel_crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT)) {
+		hsw_disable_ips(intel_crtc);
+		reenable_ips = true;
+	}
+
+	intel_crtc_state->gamma_mode = GAMMA_MODE_MODE_8BIT;
+	I915_WRITE(GAMMA_MODE(intel_crtc->pipe), GAMMA_MODE_MODE_8BIT);
+
+	i9xx_load_luts(crtc_state);
+
+	if (reenable_ips)
+		hsw_enable_ips(intel_crtc);
+}
+
+/* Loads the palette/gamma unit for the CRTC on Broadwell+. */
+static void broadwell_load_luts(struct drm_crtc_state *state)
+{
+	struct drm_crtc *crtc = state->crtc;
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc_state *intel_state = to_intel_crtc_state(state);
+	enum pipe pipe = to_intel_crtc(crtc)->pipe;
+	uint32_t i, lut_size = INTEL_INFO(dev)->color.degamma_lut_size;
+
+	if (crtc_state_is_legacy(state)) {
+		haswell_load_luts(state);
+		return;
+	}
+
+	I915_WRITE(PREC_PAL_INDEX(pipe),
+		   PAL_PREC_SPLIT_MODE | PAL_PREC_AUTO_INCREMENT);
+
+	if (state->degamma_lut) {
+		struct drm_color_lut *lut =
+			(struct drm_color_lut *) state->degamma_lut->data;
+
+		for (i = 0; i < lut_size; i++) {
+			uint32_t word =
+			drm_color_lut_extract(lut[i].red, 10) << 20 |
+			drm_color_lut_extract(lut[i].green, 10) << 10 |
+			drm_color_lut_extract(lut[i].blue, 10);
+
+			I915_WRITE(PREC_PAL_DATA(pipe), word);
+		}
+	} else {
+		for (i = 0; i < lut_size; i++) {
+			uint32_t v = (i * ((1 << 10) - 1)) / (lut_size - 1);
+
+			I915_WRITE(PREC_PAL_DATA(pipe),
+				   (v << 20) | (v << 10) | v);
+		}
+	}
+
+	if (state->gamma_lut) {
+		struct drm_color_lut *lut =
+			(struct drm_color_lut *) state->gamma_lut->data;
+
+		for (i = 0; i < lut_size; i++) {
+			uint32_t word =
+			(drm_color_lut_extract(lut[i].red, 10) << 20) |
+			(drm_color_lut_extract(lut[i].green, 10) << 10) |
+			drm_color_lut_extract(lut[i].blue, 10);
+
+			I915_WRITE(PREC_PAL_DATA(pipe), word);
+		}
+
+		/* Program the max register to clamp values > 1.0. */
+		I915_WRITE(PREC_PAL_GC_MAX(pipe, 0),
+			   drm_color_lut_extract(lut[i].red, 16));
+		I915_WRITE(PREC_PAL_GC_MAX(pipe, 1),
+			   drm_color_lut_extract(lut[i].green, 16));
+		I915_WRITE(PREC_PAL_GC_MAX(pipe, 2),
+			   drm_color_lut_extract(lut[i].blue, 16));
+	} else {
+		for (i = 0; i < lut_size; i++) {
+			uint32_t v = (i * ((1 << 10) - 1)) / (lut_size - 1);
+
+			I915_WRITE(PREC_PAL_DATA(pipe),
+				   (v << 20) | (v << 10) | v);
+		}
+
+		I915_WRITE(PREC_PAL_GC_MAX(pipe, 0), (1 << 16) - 1);
+		I915_WRITE(PREC_PAL_GC_MAX(pipe, 1), (1 << 16) - 1);
+		I915_WRITE(PREC_PAL_GC_MAX(pipe, 2), (1 << 16) - 1);
+	}
+
+	intel_state->gamma_mode = GAMMA_MODE_MODE_SPLIT;
+	I915_WRITE(GAMMA_MODE(pipe), GAMMA_MODE_MODE_SPLIT);
+	POSTING_READ(GAMMA_MODE(pipe));
+
+	/*
+	 * Reset the index, otherwise it prevents the legacy palette to be
+	 * written properly.
+	 */
+	I915_WRITE(PREC_PAL_INDEX(pipe), 0);
+}
+
+/* Loads the palette/gamma unit for the CRTC on CherryView. */
+static void cherryview_load_luts(struct drm_crtc_state *state)
+{
+	struct drm_crtc *crtc = state->crtc;
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	enum pipe pipe = to_intel_crtc(crtc)->pipe;
+	struct drm_color_lut *lut;
+	uint32_t i, lut_size;
+	uint32_t word0, word1;
+
+	if (crtc_state_is_legacy(state)) {
+		/* Turn off degamma/gamma on CGM block. */
+		I915_WRITE(CGM_PIPE_MODE(pipe),
+			   (state->ctm ? CGM_PIPE_MODE_CSC : 0));
+		i9xx_load_luts_internal(crtc, state->gamma_lut);
+		return;
+	}
+
+	if (state->degamma_lut) {
+		lut = (struct drm_color_lut *) state->degamma_lut->data;
+		lut_size = INTEL_INFO(dev)->color.degamma_lut_size;
+		for (i = 0; i < lut_size; i++) {
+			/* Write LUT in U0.14 format. */
+			word0 =
+			(drm_color_lut_extract(lut[i].green, 14) << 16) |
+			drm_color_lut_extract(lut[i].blue, 14);
+			word1 = drm_color_lut_extract(lut[i].red, 14);
+
+			I915_WRITE(CGM_PIPE_DEGAMMA(pipe, i, 0), word0);
+			I915_WRITE(CGM_PIPE_DEGAMMA(pipe, i, 1), word1);
+		}
+	}
+
+	if (state->gamma_lut) {
+		lut = (struct drm_color_lut *) state->gamma_lut->data;
+		lut_size = INTEL_INFO(dev)->color.gamma_lut_size;
+		for (i = 0; i < lut_size; i++) {
+			/* Write LUT in U0.10 format. */
+			word0 =
+			(drm_color_lut_extract(lut[i].green, 10) << 16) |
+			drm_color_lut_extract(lut[i].blue, 10);
+			word1 = drm_color_lut_extract(lut[i].red, 10);
+
+			I915_WRITE(CGM_PIPE_GAMMA(pipe, i, 0), word0);
+			I915_WRITE(CGM_PIPE_GAMMA(pipe, i, 1), word1);
+		}
+	}
+
+	I915_WRITE(CGM_PIPE_MODE(pipe),
+		   (state->ctm ? CGM_PIPE_MODE_CSC : 0) |
+		   (state->degamma_lut ? CGM_PIPE_MODE_DEGAMMA : 0) |
+		   (state->gamma_lut ? CGM_PIPE_MODE_GAMMA : 0));
+
+	/*
+	 * Also program a linear LUT in the legacy block (behind the
+	 * CGM block).
+	 */
+	i9xx_load_luts_internal(crtc, NULL);
+}
+
+void intel_color_load_luts(struct drm_crtc_state *crtc_state)
+{
+	struct drm_device *dev = crtc_state->crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	dev_priv->display.load_luts(crtc_state);
+}
+
+int intel_color_check(struct drm_crtc *crtc,
+		      struct drm_crtc_state *crtc_state)
+{
+	struct drm_device *dev = crtc->dev;
+	size_t gamma_length, degamma_length;
+
+	degamma_length = INTEL_INFO(dev)->color.degamma_lut_size *
+		sizeof(struct drm_color_lut);
+	gamma_length = INTEL_INFO(dev)->color.gamma_lut_size *
+		sizeof(struct drm_color_lut);
+
+	/*
+	 * We allow both degamma & gamma luts at the right size or
+	 * NULL.
+	 */
+	if ((!crtc_state->degamma_lut ||
+	     crtc_state->degamma_lut->length == degamma_length) &&
+	    (!crtc_state->gamma_lut ||
+	     crtc_state->gamma_lut->length == gamma_length))
+		return 0;
+
+	/*
+	 * We also allow no degamma lut and a gamma lut at the legacy
+	 * size (256 entries).
+	 */
+	if (!crtc_state->degamma_lut &&
+	    crtc_state->gamma_lut &&
+	    crtc_state->gamma_lut->length == LEGACY_LUT_LENGTH)
+		return 0;
+
+	return -EINVAL;
+}
+
+void intel_color_init(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	drm_mode_crtc_set_gamma_size(crtc, 256);
+
+	if (IS_CHERRYVIEW(dev)) {
+		dev_priv->display.load_csc_matrix = cherryview_load_csc_matrix;
+		dev_priv->display.load_luts = cherryview_load_luts;
+	} else if (IS_HASWELL(dev)) {
+		dev_priv->display.load_csc_matrix = i9xx_load_csc_matrix;
+		dev_priv->display.load_luts = haswell_load_luts;
+	} else if (IS_BROADWELL(dev) || IS_SKYLAKE(dev) ||
+		   IS_BROXTON(dev) || IS_KABYLAKE(dev)) {
+		dev_priv->display.load_csc_matrix = i9xx_load_csc_matrix;
+		dev_priv->display.load_luts = broadwell_load_luts;
+	} else {
+		dev_priv->display.load_luts = i9xx_load_luts;
+	}
+
+	/* Enable color management support when we have degamma & gamma LUTs. */
+	if (INTEL_INFO(dev)->color.degamma_lut_size != 0 &&
+	    INTEL_INFO(dev)->color.gamma_lut_size != 0)
+		drm_helper_crtc_enable_color_mgmt(crtc,
+					INTEL_INFO(dev)->color.degamma_lut_size,
+					INTEL_INFO(dev)->color.gamma_lut_size);
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_crt.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_crt.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_crt.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_crt.c	2016-07-24 15:23:50.000000000 -0400
@@ -120,22 +120,16 @@ static unsigned int intel_crt_get_flags(
 static void intel_crt_get_config(struct intel_encoder *encoder,
 				 struct intel_crtc_state *pipe_config)
 {
-	struct drm_device *dev = encoder->base.dev;
-	int dotclock;
-
 	pipe_config->base.adjusted_mode.flags |= intel_crt_get_flags(encoder);
 
-	dotclock = pipe_config->port_clock;
-
-	if (HAS_PCH_SPLIT(dev))
-		ironlake_check_encoder_dotclock(pipe_config, dotclock);
-
-	pipe_config->base.adjusted_mode.crtc_clock = dotclock;
+	pipe_config->base.adjusted_mode.crtc_clock = pipe_config->port_clock;
 }
 
 static void hsw_crt_get_config(struct intel_encoder *encoder,
 			       struct intel_crtc_state *pipe_config)
 {
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+
 	intel_ddi_get_config(encoder, pipe_config);
 
 	pipe_config->base.adjusted_mode.flags &= ~(DRM_MODE_FLAG_PHSYNC |
@@ -143,6 +137,8 @@ static void hsw_crt_get_config(struct in
 					      DRM_MODE_FLAG_PVSYNC |
 					      DRM_MODE_FLAG_NVSYNC);
 	pipe_config->base.adjusted_mode.flags |= intel_crt_get_flags(encoder);
+
+	pipe_config->base.adjusted_mode.crtc_clock = lpt_get_iclkip(dev_priv);
 }
 
 /* Note: The caller is required to filter out dpms modes not supported by the
@@ -222,18 +218,26 @@ intel_crt_mode_valid(struct drm_connecto
 {
 	struct drm_device *dev = connector->dev;
 	int max_dotclk = to_i915(dev)->max_dotclk_freq;
+	int max_clock;
 
-	int max_clock = 0;
 	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
 		return MODE_NO_DBLESCAN;
 
 	if (mode->clock < 25000)
 		return MODE_CLOCK_LOW;
 
-	if (IS_GEN2(dev))
-		max_clock = 350000;
-	else
+	if (HAS_PCH_LPT(dev))
+		max_clock = 180000;
+	else if (IS_VALLEYVIEW(dev))
+		/*
+		 * 270 MHz due to current DPLL limits,
+		 * DAC limit supposedly 355 MHz.
+		 */
+		max_clock = 270000;
+	else if (IS_GEN3(dev) || IS_GEN4(dev))
 		max_clock = 400000;
+	else
+		max_clock = 350000;
 	if (mode->clock > max_clock)
 		return MODE_CLOCK_HIGH;
 
@@ -267,15 +271,9 @@ static bool intel_crt_compute_config(str
 	}
 
 	/* FDI must always be 2.7 GHz */
-	if (HAS_DDI(dev)) {
-		pipe_config->ddi_pll_sel = PORT_CLK_SEL_SPLL;
+	if (HAS_DDI(dev))
 		pipe_config->port_clock = 135000 * 2;
 
-		pipe_config->dpll_hw_state.wrpll = 0;
-		pipe_config->dpll_hw_state.spll =
-			SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC;
-	}
-
 	return true;
 }
 
@@ -658,6 +656,8 @@ intel_crt_detect(struct drm_connector *c
 		else if (INTEL_INFO(dev)->gen < 4)
 			status = intel_crt_load_detect(crt,
 				to_intel_crtc(connector->state->crtc)->pipe);
+		else if (i915.load_detect_test)
+			status = connector_status_disconnected;
 		else
 			status = connector_status_unknown;
 		intel_release_load_detect_pipe(connector, &tmp, &ctx);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_csr.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_csr.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_csr.c	2016-05-15 19:21:29.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_csr.c	2016-07-24 18:18:03.000000000 -0400
@@ -41,14 +41,22 @@
  * be moved to FW_FAILED.
  */
 
+#define I915_CSR_KBL "/*(DEBLOBBED)*/"
+/*(DEBLOBBED)*/
+#define KBL_CSR_VERSION_REQUIRED	CSR_VERSION(1, 1)
+
 #define I915_CSR_SKL "/*(DEBLOBBED)*/"
+/*(DEBLOBBED)*/
+#define SKL_CSR_VERSION_REQUIRED	CSR_VERSION(1, 23)
+
 #define I915_CSR_BXT "/*(DEBLOBBED)*/"
+/*(DEBLOBBED)*/
+#define BXT_CSR_VERSION_REQUIRED	CSR_VERSION(1, 7)
 
 #define FIRMWARE_URL  "/*(DEBLOBBED)*/"
 
-/*(DEBLOBBED)*/
 
-#define SKL_CSR_VERSION_REQUIRED	CSR_VERSION(1, 23)
+
 
 #define CSR_MAX_FW_SIZE			0x2FFF
 #define CSR_DEFAULT_FW_OFFSET		0xFFFFFFFF
@@ -167,12 +175,10 @@ struct stepping_info {
 	char substepping;
 };
 
-/*
- * Kabylake derivated from Skylake H0, so SKL H0
- * is the right firmware for KBL A0 (revid 0).
- */
 static const struct stepping_info kbl_stepping_info[] = {
-	{'H', '0'}, {'I', '0'}
+	{'A', '0'}, {'B', '0'}, {'C', '0'},
+	{'D', '0'}, {'E', '0'}, {'F', '0'},
+	{'G', '0'}, {'H', '0'}, {'I', '0'},
 };
 
 static const struct stepping_info skl_stepping_info[] = {
@@ -187,28 +193,49 @@ static const struct stepping_info bxt_st
 	{'B', '0'}, {'B', '1'}, {'B', '2'}
 };
 
-static const struct stepping_info *intel_get_stepping_info(struct drm_device *dev)
+static const struct stepping_info no_stepping_info = { '*', '*' };
+
+static const struct stepping_info *
+intel_get_stepping_info(struct drm_i915_private *dev_priv)
 {
 	const struct stepping_info *si;
 	unsigned int size;
 
-	if (IS_KABYLAKE(dev)) {
+	if (IS_KABYLAKE(dev_priv)) {
 		size = ARRAY_SIZE(kbl_stepping_info);
 		si = kbl_stepping_info;
-	} else if (IS_SKYLAKE(dev)) {
+	} else if (IS_SKYLAKE(dev_priv)) {
 		size = ARRAY_SIZE(skl_stepping_info);
 		si = skl_stepping_info;
-	} else if (IS_BROXTON(dev)) {
+	} else if (IS_BROXTON(dev_priv)) {
 		size = ARRAY_SIZE(bxt_stepping_info);
 		si = bxt_stepping_info;
 	} else {
-		return NULL;
+		size = 0;
 	}
 
-	if (INTEL_REVID(dev) < size)
-		return si + INTEL_REVID(dev);
+	if (INTEL_REVID(dev_priv) < size)
+		return si + INTEL_REVID(dev_priv);
 
-	return NULL;
+	return &no_stepping_info;
+}
+
+static void gen9_set_dc_state_debugmask(struct drm_i915_private *dev_priv)
+{
+	uint32_t val, mask;
+
+	mask = DC_STATE_DEBUG_MASK_MEMORY_UP;
+
+	if (IS_BROXTON(dev_priv))
+		mask |= DC_STATE_DEBUG_MASK_CORES;
+
+	/* The below bit doesn't need to be cleared ever afterwards */
+	val = I915_READ(DC_STATE_DEBUG);
+	if ((val & mask) != mask) {
+		val |= mask;
+		I915_WRITE(DC_STATE_DEBUG, val);
+		POSTING_READ(DC_STATE_DEBUG);
+	}
 }
 
 /**
@@ -219,19 +246,19 @@ static const struct stepping_info *intel
  * Everytime display comes back from low power state this function is called to
  * copy the firmware from internal memory to registers.
  */
-bool intel_csr_load_program(struct drm_i915_private *dev_priv)
+void intel_csr_load_program(struct drm_i915_private *dev_priv)
 {
 	u32 *payload = dev_priv->csr.dmc_payload;
 	uint32_t i, fw_size;
 
 	if (!IS_GEN9(dev_priv)) {
 		DRM_ERROR("No CSR support available for this platform\n");
-		return false;
+		return;
 	}
 
 	if (!dev_priv->csr.dmc_payload) {
 		DRM_ERROR("Tried to program CSR with empty payload\n");
-		return false;
+		return;
 	}
 
 	fw_size = dev_priv->csr.dmc_fw_size;
@@ -245,34 +272,25 @@ bool intel_csr_load_program(struct drm_i
 
 	dev_priv->csr.dc_state = 0;
 
-	return true;
+	gen9_set_dc_state_debugmask(dev_priv);
 }
 
 static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv,
 			      const struct firmware *fw)
 {
-	struct drm_device *dev = dev_priv->dev;
 	struct intel_css_header *css_header;
 	struct intel_package_header *package_header;
 	struct intel_dmc_header *dmc_header;
 	struct intel_csr *csr = &dev_priv->csr;
-	const struct stepping_info *stepping_info = intel_get_stepping_info(dev);
-	char stepping, substepping;
+	const struct stepping_info *si = intel_get_stepping_info(dev_priv);
 	uint32_t dmc_offset = CSR_DEFAULT_FW_OFFSET, readcount = 0, nbytes;
 	uint32_t i;
 	uint32_t *dmc_payload;
+	uint32_t required_min_version;
 
 	if (!fw)
 		return NULL;
 
-	if (!stepping_info) {
-		DRM_ERROR("Unknown stepping info, firmware loading failed\n");
-		return NULL;
-	}
-
-	stepping = stepping_info->stepping;
-	substepping = stepping_info->substepping;
-
 	/* Extract CSS Header information*/
 	css_header = (struct intel_css_header *)fw->data;
 	if (sizeof(struct intel_css_header) !=
@@ -284,15 +302,25 @@ static uint32_t *parse_csr_fw(struct drm
 
 	csr->version = css_header->version;
 
-	if ((IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) &&
-	    csr->version < SKL_CSR_VERSION_REQUIRED) {
-		DRM_INFO("Refusing to load old Skylake DMC firmware v%u.%u,"
+	if (IS_KABYLAKE(dev_priv)) {
+		required_min_version = KBL_CSR_VERSION_REQUIRED;
+	} else if (IS_SKYLAKE(dev_priv)) {
+		required_min_version = SKL_CSR_VERSION_REQUIRED;
+	} else if (IS_BROXTON(dev_priv)) {
+		required_min_version = BXT_CSR_VERSION_REQUIRED;
+	} else {
+		MISSING_CASE(INTEL_REVID(dev_priv));
+		required_min_version = 0;
+	}
+
+	if (csr->version < required_min_version) {
+		DRM_INFO("Refusing to load old DMC firmware v%u.%u,"
 			 " please upgrade to v%u.%u or later"
 			   " [" FIRMWARE_URL "].\n",
 			 CSR_VERSION_MAJOR(csr->version),
 			 CSR_VERSION_MINOR(csr->version),
-			 CSR_VERSION_MAJOR(SKL_CSR_VERSION_REQUIRED),
-			 CSR_VERSION_MINOR(SKL_CSR_VERSION_REQUIRED));
+			 CSR_VERSION_MAJOR(required_min_version),
+			 CSR_VERSION_MINOR(required_min_version));
 		return NULL;
 	}
 
@@ -312,11 +340,11 @@ static uint32_t *parse_csr_fw(struct drm
 	/* Search for dmc_offset to find firware binary. */
 	for (i = 0; i < package_header->num_entries; i++) {
 		if (package_header->fw_info[i].substepping == '*' &&
-		    stepping == package_header->fw_info[i].stepping) {
+		    si->stepping == package_header->fw_info[i].stepping) {
 			dmc_offset = package_header->fw_info[i].offset;
 			break;
-		} else if (stepping == package_header->fw_info[i].stepping &&
-			substepping == package_header->fw_info[i].substepping) {
+		} else if (si->stepping == package_header->fw_info[i].stepping &&
+			   si->substepping == package_header->fw_info[i].substepping) {
 			dmc_offset = package_header->fw_info[i].offset;
 			break;
 		} else if (package_header->fw_info[i].stepping == '*' &&
@@ -324,7 +352,8 @@ static uint32_t *parse_csr_fw(struct drm
 			dmc_offset = package_header->fw_info[i].offset;
 	}
 	if (dmc_offset == CSR_DEFAULT_FW_OFFSET) {
-		DRM_ERROR("Firmware not supported for %c stepping\n", stepping);
+		DRM_ERROR("Firmware not supported for %c stepping\n",
+			  si->stepping);
 		return NULL;
 	}
 	readcount += dmc_offset;
@@ -370,9 +399,7 @@ static uint32_t *parse_csr_fw(struct drm
 		return NULL;
 	}
 
-	memcpy(dmc_payload, &fw->data[readcount], nbytes);
-
-	return dmc_payload;
+	return memcpy(dmc_payload, &fw->data[readcount], nbytes);
 }
 
 static void csr_load_work_fn(struct work_struct *work)
@@ -387,18 +414,12 @@ static void csr_load_work_fn(struct work
 
 	ret = reject_firmware(&fw, dev_priv->csr.fw_path,
 			       &dev_priv->dev->pdev->dev);
-	if (!fw)
-		goto out;
-
-	dev_priv->csr.dmc_payload = parse_csr_fw(dev_priv, fw);
-	if (!dev_priv->csr.dmc_payload)
-		goto out;
-
-	/* load csr program during system boot, as needed for DC states */
-	intel_csr_load_program(dev_priv);
+	if (fw)
+		dev_priv->csr.dmc_payload = parse_csr_fw(dev_priv, fw);
 
-out:
 	if (dev_priv->csr.dmc_payload) {
+		intel_csr_load_program(dev_priv);
+
 		intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
 
 		DRM_INFO("Finished loading %s (v%u.%u)\n",
@@ -431,7 +452,9 @@ void intel_csr_ucode_init(struct drm_i91
 	if (!HAS_CSR(dev_priv))
 		return;
 
-	if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
+	if (IS_KABYLAKE(dev_priv))
+		csr->fw_path = I915_CSR_KBL;
+	else if (IS_SKYLAKE(dev_priv))
 		csr->fw_path = I915_CSR_SKL;
 	else if (IS_BROXTON(dev_priv))
 		csr->fw_path = I915_CSR_BXT;
@@ -452,10 +475,50 @@ void intel_csr_ucode_init(struct drm_i91
 }
 
 /**
+ * intel_csr_ucode_suspend() - prepare CSR firmware before system suspend
+ * @dev_priv: i915 drm device
+ *
+ * Prepare the DMC firmware before entering system suspend. This includes
+ * flushing pending work items and releasing any resources acquired during
+ * init.
+ */
+void intel_csr_ucode_suspend(struct drm_i915_private *dev_priv)
+{
+	if (!HAS_CSR(dev_priv))
+		return;
+
+	flush_work(&dev_priv->csr.work);
+
+	/* Drop the reference held in case DMC isn't loaded. */
+	if (!dev_priv->csr.dmc_payload)
+		intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
+}
+
+/**
+ * intel_csr_ucode_resume() - init CSR firmware during system resume
+ * @dev_priv: i915 drm device
+ *
+ * Reinitialize the DMC firmware during system resume, reacquiring any
+ * resources released in intel_csr_ucode_suspend().
+ */
+void intel_csr_ucode_resume(struct drm_i915_private *dev_priv)
+{
+	if (!HAS_CSR(dev_priv))
+		return;
+
+	/*
+	 * Reacquire the reference to keep RPM disabled in case DMC isn't
+	 * loaded.
+	 */
+	if (!dev_priv->csr.dmc_payload)
+		intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
+}
+
+/**
  * intel_csr_ucode_fini() - unload the CSR firmware.
  * @dev_priv: i915 drm device.
  *
- * Firmmware unloading includes freeing the internal momory and reset the
+ * Firmmware unloading includes freeing the internal memory and reset the
  * firmware loading status.
  */
 void intel_csr_ucode_fini(struct drm_i915_private *dev_priv)
@@ -463,7 +526,7 @@ void intel_csr_ucode_fini(struct drm_i91
 	if (!HAS_CSR(dev_priv))
 		return;
 
-	flush_work(&dev_priv->csr.work);
+	intel_csr_ucode_suspend(dev_priv);
 
 	kfree(dev_priv->csr.dmc_payload);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_ddi.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_ddi.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_ddi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_ddi.c	2016-07-24 15:23:50.000000000 -0400
@@ -315,6 +315,9 @@ static void ddi_get_encoder_port(struct
 		*dig_port = enc_to_mst(encoder)->primary;
 		*port = (*dig_port)->port;
 		break;
+	default:
+		WARN(1, "Invalid DDI encoder type %d\n", intel_encoder->type);
+		/* fallthrough and treat as unknown */
 	case INTEL_OUTPUT_DISPLAYPORT:
 	case INTEL_OUTPUT_EDP:
 	case INTEL_OUTPUT_HDMI:
@@ -326,9 +329,6 @@ static void ddi_get_encoder_port(struct
 		*dig_port = NULL;
 		*port = PORT_E;
 		break;
-	default:
-		WARN(1, "Invalid DDI encoder type %d\n", intel_encoder->type);
-		break;
 	}
 }
 
@@ -360,7 +360,7 @@ skl_get_buf_trans_dp(struct drm_i915_pri
 static const struct ddi_buf_trans *
 skl_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries)
 {
-	if (dev_priv->edp_low_vswing) {
+	if (dev_priv->vbt.edp.low_vswing) {
 		if (IS_SKL_ULX(dev_priv) || IS_KBL_ULX(dev_priv)) {
 			*n_entries = ARRAY_SIZE(skl_y_ddi_translations_edp);
 			return skl_y_ddi_translations_edp;
@@ -444,7 +444,7 @@ void intel_prepare_ddi_buffer(struct int
 		ddi_translations_fdi = bdw_ddi_translations_fdi;
 		ddi_translations_dp = bdw_ddi_translations_dp;
 
-		if (dev_priv->edp_low_vswing) {
+		if (dev_priv->vbt.edp.low_vswing) {
 			ddi_translations_edp = bdw_ddi_translations_edp;
 			n_edp_entries = ARRAY_SIZE(bdw_ddi_translations_edp);
 		} else {
@@ -637,6 +637,10 @@ void hsw_fdi_link_train(struct drm_crtc
 			break;
 		}
 
+		rx_ctl_val &= ~FDI_RX_ENABLE;
+		I915_WRITE(FDI_RX_CTL(PIPE_A), rx_ctl_val);
+		POSTING_READ(FDI_RX_CTL(PIPE_A));
+
 		temp = I915_READ(DDI_BUF_CTL(PORT_E));
 		temp &= ~DDI_BUF_CTL_ENABLE;
 		I915_WRITE(DDI_BUF_CTL(PORT_E), temp);
@@ -651,10 +655,6 @@ void hsw_fdi_link_train(struct drm_crtc
 
 		intel_wait_ddi_buf_idle(dev_priv, PORT_E);
 
-		rx_ctl_val &= ~FDI_RX_ENABLE;
-		I915_WRITE(FDI_RX_CTL(PIPE_A), rx_ctl_val);
-		POSTING_READ(FDI_RX_CTL(PIPE_A));
-
 		/* Reset FDI_RX_MISC pwrdn lanes */
 		temp = I915_READ(FDI_RX_MISC(PIPE_A));
 		temp &= ~(FDI_RX_PWRDN_LANE1_MASK | FDI_RX_PWRDN_LANE0_MASK);
@@ -732,160 +732,6 @@ intel_ddi_get_crtc_new_encoder(struct in
 }
 
 #define LC_FREQ 2700
-#define LC_FREQ_2K U64_C(LC_FREQ * 2000)
-
-#define P_MIN 2
-#define P_MAX 64
-#define P_INC 2
-
-/* Constraints for PLL good behavior */
-#define REF_MIN 48
-#define REF_MAX 400
-#define VCO_MIN 2400
-#define VCO_MAX 4800
-
-#define abs_diff(a, b) ({			\
-	typeof(a) __a = (a);			\
-	typeof(b) __b = (b);			\
-	(void) (&__a == &__b);			\
-	__a > __b ? (__a - __b) : (__b - __a); })
-
-struct hsw_wrpll_rnp {
-	unsigned p, n2, r2;
-};
-
-static unsigned hsw_wrpll_get_budget_for_freq(int clock)
-{
-	unsigned budget;
-
-	switch (clock) {
-	case 25175000:
-	case 25200000:
-	case 27000000:
-	case 27027000:
-	case 37762500:
-	case 37800000:
-	case 40500000:
-	case 40541000:
-	case 54000000:
-	case 54054000:
-	case 59341000:
-	case 59400000:
-	case 72000000:
-	case 74176000:
-	case 74250000:
-	case 81000000:
-	case 81081000:
-	case 89012000:
-	case 89100000:
-	case 108000000:
-	case 108108000:
-	case 111264000:
-	case 111375000:
-	case 148352000:
-	case 148500000:
-	case 162000000:
-	case 162162000:
-	case 222525000:
-	case 222750000:
-	case 296703000:
-	case 297000000:
-		budget = 0;
-		break;
-	case 233500000:
-	case 245250000:
-	case 247750000:
-	case 253250000:
-	case 298000000:
-		budget = 1500;
-		break;
-	case 169128000:
-	case 169500000:
-	case 179500000:
-	case 202000000:
-		budget = 2000;
-		break;
-	case 256250000:
-	case 262500000:
-	case 270000000:
-	case 272500000:
-	case 273750000:
-	case 280750000:
-	case 281250000:
-	case 286000000:
-	case 291750000:
-		budget = 4000;
-		break;
-	case 267250000:
-	case 268500000:
-		budget = 5000;
-		break;
-	default:
-		budget = 1000;
-		break;
-	}
-
-	return budget;
-}
-
-static void hsw_wrpll_update_rnp(uint64_t freq2k, unsigned budget,
-				 unsigned r2, unsigned n2, unsigned p,
-				 struct hsw_wrpll_rnp *best)
-{
-	uint64_t a, b, c, d, diff, diff_best;
-
-	/* No best (r,n,p) yet */
-	if (best->p == 0) {
-		best->p = p;
-		best->n2 = n2;
-		best->r2 = r2;
-		return;
-	}
-
-	/*
-	 * Output clock is (LC_FREQ_2K / 2000) * N / (P * R), which compares to
-	 * freq2k.
-	 *
-	 * delta = 1e6 *
-	 *	   abs(freq2k - (LC_FREQ_2K * n2/(p * r2))) /
-	 *	   freq2k;
-	 *
-	 * and we would like delta <= budget.
-	 *
-	 * If the discrepancy is above the PPM-based budget, always prefer to
-	 * improve upon the previous solution.  However, if you're within the
-	 * budget, try to maximize Ref * VCO, that is N / (P * R^2).
-	 */
-	a = freq2k * budget * p * r2;
-	b = freq2k * budget * best->p * best->r2;
-	diff = abs_diff(freq2k * p * r2, LC_FREQ_2K * n2);
-	diff_best = abs_diff(freq2k * best->p * best->r2,
-			     LC_FREQ_2K * best->n2);
-	c = 1000000 * diff;
-	d = 1000000 * diff_best;
-
-	if (a < c && b < d) {
-		/* If both are above the budget, pick the closer */
-		if (best->p * best->r2 * diff < p * r2 * diff_best) {
-			best->p = p;
-			best->n2 = n2;
-			best->r2 = r2;
-		}
-	} else if (a >= c && b < d) {
-		/* If A is below the threshold but B is above it?  Update. */
-		best->p = p;
-		best->n2 = n2;
-		best->r2 = r2;
-	} else if (a >= c && b >= d) {
-		/* Both are below the limit, so pick the higher n2/(r2*r2) */
-		if (n2 * best->r2 * best->r2 > best->n2 * r2 * r2) {
-			best->p = p;
-			best->n2 = n2;
-			best->r2 = r2;
-		}
-	}
-	/* Otherwise a < c && b >= d, do nothing */
-}
 
 static int hsw_ddi_calc_wrpll_link(struct drm_i915_private *dev_priv,
 				   i915_reg_t reg)
@@ -1147,363 +993,20 @@ void intel_ddi_clock_get(struct intel_en
 		bxt_ddi_clock_get(encoder, pipe_config);
 }
 
-static void
-hsw_ddi_calculate_wrpll(int clock /* in Hz */,
-			unsigned *r2_out, unsigned *n2_out, unsigned *p_out)
-{
-	uint64_t freq2k;
-	unsigned p, n2, r2;
-	struct hsw_wrpll_rnp best = { 0, 0, 0 };
-	unsigned budget;
-
-	freq2k = clock / 100;
-
-	budget = hsw_wrpll_get_budget_for_freq(clock);
-
-	/* Special case handling for 540 pixel clock: bypass WR PLL entirely
-	 * and directly pass the LC PLL to it. */
-	if (freq2k == 5400000) {
-		*n2_out = 2;
-		*p_out = 1;
-		*r2_out = 2;
-		return;
-	}
-
-	/*
-	 * Ref = LC_FREQ / R, where Ref is the actual reference input seen by
-	 * the WR PLL.
-	 *
-	 * We want R so that REF_MIN <= Ref <= REF_MAX.
-	 * Injecting R2 = 2 * R gives:
-	 *   REF_MAX * r2 > LC_FREQ * 2 and
-	 *   REF_MIN * r2 < LC_FREQ * 2
-	 *
-	 * Which means the desired boundaries for r2 are:
-	 *  LC_FREQ * 2 / REF_MAX < r2 < LC_FREQ * 2 / REF_MIN
-	 *
-	 */
-	for (r2 = LC_FREQ * 2 / REF_MAX + 1;
-	     r2 <= LC_FREQ * 2 / REF_MIN;
-	     r2++) {
-
-		/*
-		 * VCO = N * Ref, that is: VCO = N * LC_FREQ / R
-		 *
-		 * Once again we want VCO_MIN <= VCO <= VCO_MAX.
-		 * Injecting R2 = 2 * R and N2 = 2 * N, we get:
-		 *   VCO_MAX * r2 > n2 * LC_FREQ and
-		 *   VCO_MIN * r2 < n2 * LC_FREQ)
-		 *
-		 * Which means the desired boundaries for n2 are:
-		 * VCO_MIN * r2 / LC_FREQ < n2 < VCO_MAX * r2 / LC_FREQ
-		 */
-		for (n2 = VCO_MIN * r2 / LC_FREQ + 1;
-		     n2 <= VCO_MAX * r2 / LC_FREQ;
-		     n2++) {
-
-			for (p = P_MIN; p <= P_MAX; p += P_INC)
-				hsw_wrpll_update_rnp(freq2k, budget,
-						     r2, n2, p, &best);
-		}
-	}
-
-	*n2_out = best.n2;
-	*p_out = best.p;
-	*r2_out = best.r2;
-}
-
 static bool
 hsw_ddi_pll_select(struct intel_crtc *intel_crtc,
 		   struct intel_crtc_state *crtc_state,
 		   struct intel_encoder *intel_encoder)
 {
-	int clock = crtc_state->port_clock;
-
-	if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
-		struct intel_shared_dpll *pll;
-		uint32_t val;
-		unsigned p, n2, r2;
-
-		hsw_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p);
-
-		val = WRPLL_PLL_ENABLE | WRPLL_PLL_LCPLL |
-		      WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) |
-		      WRPLL_DIVIDER_POST(p);
-
-		memset(&crtc_state->dpll_hw_state, 0,
-		       sizeof(crtc_state->dpll_hw_state));
-
-		crtc_state->dpll_hw_state.wrpll = val;
-
-		pll = intel_get_shared_dpll(intel_crtc, crtc_state);
-		if (pll == NULL) {
-			DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n",
-					 pipe_name(intel_crtc->pipe));
-			return false;
-		}
-
-		crtc_state->ddi_pll_sel = PORT_CLK_SEL_WRPLL(pll->id);
-	} else if (crtc_state->ddi_pll_sel == PORT_CLK_SEL_SPLL) {
-		struct drm_atomic_state *state = crtc_state->base.state;
-		struct intel_shared_dpll_config *spll =
-			&intel_atomic_get_shared_dpll_state(state)[DPLL_ID_SPLL];
-
-		if (spll->crtc_mask &&
-		    WARN_ON(spll->hw_state.spll != crtc_state->dpll_hw_state.spll))
-			return false;
-
-		crtc_state->shared_dpll = DPLL_ID_SPLL;
-		spll->hw_state.spll = crtc_state->dpll_hw_state.spll;
-		spll->crtc_mask |= 1 << intel_crtc->pipe;
-	}
-
-	return true;
-}
-
-struct skl_wrpll_context {
-	uint64_t min_deviation;		/* current minimal deviation */
-	uint64_t central_freq;		/* chosen central freq */
-	uint64_t dco_freq;		/* chosen dco freq */
-	unsigned int p;			/* chosen divider */
-};
-
-static void skl_wrpll_context_init(struct skl_wrpll_context *ctx)
-{
-	memset(ctx, 0, sizeof(*ctx));
-
-	ctx->min_deviation = U64_MAX;
-}
-
-/* DCO freq must be within +1%/-6%  of the DCO central freq */
-#define SKL_DCO_MAX_PDEVIATION	100
-#define SKL_DCO_MAX_NDEVIATION	600
-
-static void skl_wrpll_try_divider(struct skl_wrpll_context *ctx,
-				  uint64_t central_freq,
-				  uint64_t dco_freq,
-				  unsigned int divider)
-{
-	uint64_t deviation;
-
-	deviation = div64_u64(10000 * abs_diff(dco_freq, central_freq),
-			      central_freq);
-
-	/* positive deviation */
-	if (dco_freq >= central_freq) {
-		if (deviation < SKL_DCO_MAX_PDEVIATION &&
-		    deviation < ctx->min_deviation) {
-			ctx->min_deviation = deviation;
-			ctx->central_freq = central_freq;
-			ctx->dco_freq = dco_freq;
-			ctx->p = divider;
-		}
-	/* negative deviation */
-	} else if (deviation < SKL_DCO_MAX_NDEVIATION &&
-		   deviation < ctx->min_deviation) {
-		ctx->min_deviation = deviation;
-		ctx->central_freq = central_freq;
-		ctx->dco_freq = dco_freq;
-		ctx->p = divider;
-	}
-}
-
-static void skl_wrpll_get_multipliers(unsigned int p,
-				      unsigned int *p0 /* out */,
-				      unsigned int *p1 /* out */,
-				      unsigned int *p2 /* out */)
-{
-	/* even dividers */
-	if (p % 2 == 0) {
-		unsigned int half = p / 2;
-
-		if (half == 1 || half == 2 || half == 3 || half == 5) {
-			*p0 = 2;
-			*p1 = 1;
-			*p2 = half;
-		} else if (half % 2 == 0) {
-			*p0 = 2;
-			*p1 = half / 2;
-			*p2 = 2;
-		} else if (half % 3 == 0) {
-			*p0 = 3;
-			*p1 = half / 3;
-			*p2 = 2;
-		} else if (half % 7 == 0) {
-			*p0 = 7;
-			*p1 = half / 7;
-			*p2 = 2;
-		}
-	} else if (p == 3 || p == 9) {  /* 3, 5, 7, 9, 15, 21, 35 */
-		*p0 = 3;
-		*p1 = 1;
-		*p2 = p / 3;
-	} else if (p == 5 || p == 7) {
-		*p0 = p;
-		*p1 = 1;
-		*p2 = 1;
-	} else if (p == 15) {
-		*p0 = 3;
-		*p1 = 1;
-		*p2 = 5;
-	} else if (p == 21) {
-		*p0 = 7;
-		*p1 = 1;
-		*p2 = 3;
-	} else if (p == 35) {
-		*p0 = 7;
-		*p1 = 1;
-		*p2 = 5;
-	}
-}
-
-struct skl_wrpll_params {
-	uint32_t        dco_fraction;
-	uint32_t        dco_integer;
-	uint32_t        qdiv_ratio;
-	uint32_t        qdiv_mode;
-	uint32_t        kdiv;
-	uint32_t        pdiv;
-	uint32_t        central_freq;
-};
-
-static void skl_wrpll_params_populate(struct skl_wrpll_params *params,
-				      uint64_t afe_clock,
-				      uint64_t central_freq,
-				      uint32_t p0, uint32_t p1, uint32_t p2)
-{
-	uint64_t dco_freq;
-
-	switch (central_freq) {
-	case 9600000000ULL:
-		params->central_freq = 0;
-		break;
-	case 9000000000ULL:
-		params->central_freq = 1;
-		break;
-	case 8400000000ULL:
-		params->central_freq = 3;
-	}
-
-	switch (p0) {
-	case 1:
-		params->pdiv = 0;
-		break;
-	case 2:
-		params->pdiv = 1;
-		break;
-	case 3:
-		params->pdiv = 2;
-		break;
-	case 7:
-		params->pdiv = 4;
-		break;
-	default:
-		WARN(1, "Incorrect PDiv\n");
-	}
-
-	switch (p2) {
-	case 5:
-		params->kdiv = 0;
-		break;
-	case 2:
-		params->kdiv = 1;
-		break;
-	case 3:
-		params->kdiv = 2;
-		break;
-	case 1:
-		params->kdiv = 3;
-		break;
-	default:
-		WARN(1, "Incorrect KDiv\n");
-	}
-
-	params->qdiv_ratio = p1;
-	params->qdiv_mode = (params->qdiv_ratio == 1) ? 0 : 1;
-
-	dco_freq = p0 * p1 * p2 * afe_clock;
-
-	/*
-	 * Intermediate values are in Hz.
-	 * Divide by MHz to match bsepc
-	 */
-	params->dco_integer = div_u64(dco_freq, 24 * MHz(1));
-	params->dco_fraction =
-		div_u64((div_u64(dco_freq, 24) -
-			 params->dco_integer * MHz(1)) * 0x8000, MHz(1));
-}
-
-static bool
-skl_ddi_calculate_wrpll(int clock /* in Hz */,
-			struct skl_wrpll_params *wrpll_params)
-{
-	uint64_t afe_clock = clock * 5; /* AFE Clock is 5x Pixel clock */
-	uint64_t dco_central_freq[3] = {8400000000ULL,
-					9000000000ULL,
-					9600000000ULL};
-	static const int even_dividers[] = {  4,  6,  8, 10, 12, 14, 16, 18, 20,
-					     24, 28, 30, 32, 36, 40, 42, 44,
-					     48, 52, 54, 56, 60, 64, 66, 68,
-					     70, 72, 76, 78, 80, 84, 88, 90,
-					     92, 96, 98 };
-	static const int odd_dividers[] = { 3, 5, 7, 9, 15, 21, 35 };
-	static const struct {
-		const int *list;
-		int n_dividers;
-	} dividers[] = {
-		{ even_dividers, ARRAY_SIZE(even_dividers) },
-		{ odd_dividers, ARRAY_SIZE(odd_dividers) },
-	};
-	struct skl_wrpll_context ctx;
-	unsigned int dco, d, i;
-	unsigned int p0, p1, p2;
-
-	skl_wrpll_context_init(&ctx);
-
-	for (d = 0; d < ARRAY_SIZE(dividers); d++) {
-		for (dco = 0; dco < ARRAY_SIZE(dco_central_freq); dco++) {
-			for (i = 0; i < dividers[d].n_dividers; i++) {
-				unsigned int p = dividers[d].list[i];
-				uint64_t dco_freq = p * afe_clock;
-
-				skl_wrpll_try_divider(&ctx,
-						      dco_central_freq[dco],
-						      dco_freq,
-						      p);
-				/*
-				 * Skip the remaining dividers if we're sure to
-				 * have found the definitive divider, we can't
-				 * improve a 0 deviation.
-				 */
-				if (ctx.min_deviation == 0)
-					goto skip_remaining_dividers;
-			}
-		}
-
-skip_remaining_dividers:
-		/*
-		 * If a solution is found with an even divider, prefer
-		 * this one.
-		 */
-		if (d == 0 && ctx.p)
-			break;
-	}
-
-	if (!ctx.p) {
-		DRM_DEBUG_DRIVER("No valid divider found for %dHz\n", clock);
-		return false;
-	}
+	struct intel_shared_dpll *pll;
 
-	/*
-	 * gcc incorrectly analyses that these can be used without being
-	 * initialized. To be fair, it's hard to guess.
-	 */
-	p0 = p1 = p2 = 0;
-	skl_wrpll_get_multipliers(ctx.p, &p0, &p1, &p2);
-	skl_wrpll_params_populate(wrpll_params, afe_clock, ctx.central_freq,
-				  p0, p1, p2);
+	pll = intel_get_shared_dpll(intel_crtc, crtc_state,
+				    intel_encoder);
+	if (!pll)
+		DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n",
+				 pipe_name(intel_crtc->pipe));
 
-	return true;
+	return pll;
 }
 
 static bool
@@ -1512,218 +1015,23 @@ skl_ddi_pll_select(struct intel_crtc *in
 		   struct intel_encoder *intel_encoder)
 {
 	struct intel_shared_dpll *pll;
-	uint32_t ctrl1, cfgcr1, cfgcr2;
-	int clock = crtc_state->port_clock;
-
-	/*
-	 * See comment in intel_dpll_hw_state to understand why we always use 0
-	 * as the DPLL id in this function.
-	 */
-
-	ctrl1 = DPLL_CTRL1_OVERRIDE(0);
-
-	if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
-		struct skl_wrpll_params wrpll_params = { 0, };
-
-		ctrl1 |= DPLL_CTRL1_HDMI_MODE(0);
-
-		if (!skl_ddi_calculate_wrpll(clock * 1000, &wrpll_params))
-			return false;
-
-		cfgcr1 = DPLL_CFGCR1_FREQ_ENABLE |
-			 DPLL_CFGCR1_DCO_FRACTION(wrpll_params.dco_fraction) |
-			 wrpll_params.dco_integer;
 
-		cfgcr2 = DPLL_CFGCR2_QDIV_RATIO(wrpll_params.qdiv_ratio) |
-			 DPLL_CFGCR2_QDIV_MODE(wrpll_params.qdiv_mode) |
-			 DPLL_CFGCR2_KDIV(wrpll_params.kdiv) |
-			 DPLL_CFGCR2_PDIV(wrpll_params.pdiv) |
-			 wrpll_params.central_freq;
-	} else if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT ||
-		   intel_encoder->type == INTEL_OUTPUT_DP_MST) {
-		switch (crtc_state->port_clock / 2) {
-		case 81000:
-			ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, 0);
-			break;
-		case 135000:
-			ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, 0);
-			break;
-		case 270000:
-			ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, 0);
-			break;
-		}
-
-		cfgcr1 = cfgcr2 = 0;
-	} else if (intel_encoder->type == INTEL_OUTPUT_EDP) {
-		return true;
-	} else
-		return false;
-
-	memset(&crtc_state->dpll_hw_state, 0,
-	       sizeof(crtc_state->dpll_hw_state));
-
-	crtc_state->dpll_hw_state.ctrl1 = ctrl1;
-	crtc_state->dpll_hw_state.cfgcr1 = cfgcr1;
-	crtc_state->dpll_hw_state.cfgcr2 = cfgcr2;
-
-	pll = intel_get_shared_dpll(intel_crtc, crtc_state);
+	pll = intel_get_shared_dpll(intel_crtc, crtc_state, intel_encoder);
 	if (pll == NULL) {
 		DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n",
 				 pipe_name(intel_crtc->pipe));
 		return false;
 	}
 
-	/* shared DPLL id 0 is DPLL 1 */
-	crtc_state->ddi_pll_sel = pll->id + 1;
-
 	return true;
 }
 
-/* bxt clock parameters */
-struct bxt_clk_div {
-	int clock;
-	uint32_t p1;
-	uint32_t p2;
-	uint32_t m2_int;
-	uint32_t m2_frac;
-	bool m2_frac_en;
-	uint32_t n;
-};
-
-/* pre-calculated values for DP linkrates */
-static const struct bxt_clk_div bxt_dp_clk_val[] = {
-	{162000, 4, 2, 32, 1677722, 1, 1},
-	{270000, 4, 1, 27,       0, 0, 1},
-	{540000, 2, 1, 27,       0, 0, 1},
-	{216000, 3, 2, 32, 1677722, 1, 1},
-	{243000, 4, 1, 24, 1258291, 1, 1},
-	{324000, 4, 1, 32, 1677722, 1, 1},
-	{432000, 3, 1, 32, 1677722, 1, 1}
-};
-
 static bool
 bxt_ddi_pll_select(struct intel_crtc *intel_crtc,
 		   struct intel_crtc_state *crtc_state,
 		   struct intel_encoder *intel_encoder)
 {
-	struct intel_shared_dpll *pll;
-	struct bxt_clk_div clk_div = {0};
-	int vco = 0;
-	uint32_t prop_coef, int_coef, gain_ctl, targ_cnt;
-	uint32_t lanestagger;
-	int clock = crtc_state->port_clock;
-
-	if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
-		intel_clock_t best_clock;
-
-		/* Calculate HDMI div */
-		/*
-		 * FIXME: tie the following calculation into
-		 * i9xx_crtc_compute_clock
-		 */
-		if (!bxt_find_best_dpll(crtc_state, clock, &best_clock)) {
-			DRM_DEBUG_DRIVER("no PLL dividers found for clock %d pipe %c\n",
-					 clock, pipe_name(intel_crtc->pipe));
-			return false;
-		}
-
-		clk_div.p1 = best_clock.p1;
-		clk_div.p2 = best_clock.p2;
-		WARN_ON(best_clock.m1 != 2);
-		clk_div.n = best_clock.n;
-		clk_div.m2_int = best_clock.m2 >> 22;
-		clk_div.m2_frac = best_clock.m2 & ((1 << 22) - 1);
-		clk_div.m2_frac_en = clk_div.m2_frac != 0;
-
-		vco = best_clock.vco;
-	} else if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT ||
-			intel_encoder->type == INTEL_OUTPUT_EDP) {
-		int i;
-
-		clk_div = bxt_dp_clk_val[0];
-		for (i = 0; i < ARRAY_SIZE(bxt_dp_clk_val); ++i) {
-			if (bxt_dp_clk_val[i].clock == clock) {
-				clk_div = bxt_dp_clk_val[i];
-				break;
-			}
-		}
-		vco = clock * 10 / 2 * clk_div.p1 * clk_div.p2;
-	}
-
-	if (vco >= 6200000 && vco <= 6700000) {
-		prop_coef = 4;
-		int_coef = 9;
-		gain_ctl = 3;
-		targ_cnt = 8;
-	} else if ((vco > 5400000 && vco < 6200000) ||
-			(vco >= 4800000 && vco < 5400000)) {
-		prop_coef = 5;
-		int_coef = 11;
-		gain_ctl = 3;
-		targ_cnt = 9;
-	} else if (vco == 5400000) {
-		prop_coef = 3;
-		int_coef = 8;
-		gain_ctl = 1;
-		targ_cnt = 9;
-	} else {
-		DRM_ERROR("Invalid VCO\n");
-		return false;
-	}
-
-	memset(&crtc_state->dpll_hw_state, 0,
-	       sizeof(crtc_state->dpll_hw_state));
-
-	if (clock > 270000)
-		lanestagger = 0x18;
-	else if (clock > 135000)
-		lanestagger = 0x0d;
-	else if (clock > 67000)
-		lanestagger = 0x07;
-	else if (clock > 33000)
-		lanestagger = 0x04;
-	else
-		lanestagger = 0x02;
-
-	crtc_state->dpll_hw_state.ebb0 =
-		PORT_PLL_P1(clk_div.p1) | PORT_PLL_P2(clk_div.p2);
-	crtc_state->dpll_hw_state.pll0 = clk_div.m2_int;
-	crtc_state->dpll_hw_state.pll1 = PORT_PLL_N(clk_div.n);
-	crtc_state->dpll_hw_state.pll2 = clk_div.m2_frac;
-
-	if (clk_div.m2_frac_en)
-		crtc_state->dpll_hw_state.pll3 =
-			PORT_PLL_M2_FRAC_ENABLE;
-
-	crtc_state->dpll_hw_state.pll6 =
-		prop_coef | PORT_PLL_INT_COEFF(int_coef);
-	crtc_state->dpll_hw_state.pll6 |=
-		PORT_PLL_GAIN_CTL(gain_ctl);
-
-	crtc_state->dpll_hw_state.pll8 = targ_cnt;
-
-	crtc_state->dpll_hw_state.pll9 = 5 << PORT_PLL_LOCK_THRESHOLD_SHIFT;
-
-	crtc_state->dpll_hw_state.pll10 =
-		PORT_PLL_DCO_AMP(PORT_PLL_DCO_AMP_DEFAULT)
-		| PORT_PLL_DCO_AMP_OVR_EN_H;
-
-	crtc_state->dpll_hw_state.ebb4 = PORT_PLL_10BIT_CLK_ENABLE;
-
-	crtc_state->dpll_hw_state.pcsdw12 =
-		LANESTAGGER_STRAP_OVRD | lanestagger;
-
-	pll = intel_get_shared_dpll(intel_crtc, crtc_state);
-	if (pll == NULL) {
-		DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n",
-			pipe_name(intel_crtc->pipe));
-		return false;
-	}
-
-	/* shared DPLL id 0 is DPLL A */
-	crtc_state->ddi_pll_sel = pll->id;
-
-	return true;
+	return !!intel_get_shared_dpll(intel_crtc, crtc_state, intel_encoder);
 }
 
 /*
@@ -1761,6 +1069,8 @@ void intel_ddi_set_pipe_settings(struct
 	uint32_t temp;
 
 	if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP || type == INTEL_OUTPUT_DP_MST) {
+		WARN_ON(transcoder_is_dsi(cpu_transcoder));
+
 		temp = TRANS_MSA_SYNC_CLK;
 		switch (intel_crtc->config->pipe_bpp) {
 		case 18:
@@ -2129,7 +1439,7 @@ static void bxt_ddi_vswing_sequence(stru
 	u32 n_entries, i;
 	uint32_t val;
 
-	if (type == INTEL_OUTPUT_EDP && dev_priv->edp_low_vswing) {
+	if (type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.low_vswing) {
 		n_entries = ARRAY_SIZE(bxt_ddi_translations_edp);
 		ddi_translations = bxt_ddi_translations_edp;
 	} else if (type == INTEL_OUTPUT_DISPLAYPORT
@@ -2267,24 +1577,6 @@ void intel_ddi_clk_select(struct intel_e
 		uint32_t dpll = pipe_config->ddi_pll_sel;
 		uint32_t val;
 
-		/*
-		 * DPLL0 is used for eDP and is the only "private" DPLL (as
-		 * opposed to shared) on SKL
-		 */
-		if (encoder->type == INTEL_OUTPUT_EDP) {
-			WARN_ON(dpll != SKL_DPLL0);
-
-			val = I915_READ(DPLL_CTRL1);
-
-			val &= ~(DPLL_CTRL1_HDMI_MODE(dpll) |
-				 DPLL_CTRL1_SSC(dpll) |
-				 DPLL_CTRL1_LINK_RATE_MASK(dpll));
-			val |= pipe_config->dpll_hw_state.ctrl1 << (dpll * 6);
-
-			I915_WRITE(DPLL_CTRL1, val);
-			POSTING_READ(DPLL_CTRL1);
-		}
-
 		/* DDI -> PLL mapping  */
 		val = I915_READ(DPLL_CTRL2);
 
@@ -2309,6 +1601,12 @@ static void intel_ddi_pre_enable(struct
 	enum port port = intel_ddi_get_encoder_port(intel_encoder);
 	int type = intel_encoder->type;
 
+	if (type == INTEL_OUTPUT_HDMI) {
+		struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+
+		intel_dp_dual_mode_set_tmds_output(intel_hdmi, true);
+	}
+
 	intel_prepare_ddi_buffer(intel_encoder);
 
 	if (type == INTEL_OUTPUT_EDP) {
@@ -2375,6 +1673,12 @@ static void intel_ddi_post_disable(struc
 					DPLL_CTRL2_DDI_CLK_OFF(port)));
 	else if (INTEL_INFO(dev)->gen < 9)
 		I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE);
+
+	if (type == INTEL_OUTPUT_HDMI) {
+		struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+
+		intel_dp_dual_mode_set_tmds_output(intel_hdmi, false);
+	}
 }
 
 static void intel_enable_ddi(struct intel_encoder *intel_encoder)
@@ -2438,251 +1742,101 @@ static void intel_disable_ddi(struct int
 	}
 }
 
-static void hsw_ddi_wrpll_enable(struct drm_i915_private *dev_priv,
-			       struct intel_shared_dpll *pll)
-{
-	I915_WRITE(WRPLL_CTL(pll->id), pll->config.hw_state.wrpll);
-	POSTING_READ(WRPLL_CTL(pll->id));
-	udelay(20);
-}
-
-static void hsw_ddi_spll_enable(struct drm_i915_private *dev_priv,
-				struct intel_shared_dpll *pll)
-{
-	I915_WRITE(SPLL_CTL, pll->config.hw_state.spll);
-	POSTING_READ(SPLL_CTL);
-	udelay(20);
-}
-
-static void hsw_ddi_wrpll_disable(struct drm_i915_private *dev_priv,
-				  struct intel_shared_dpll *pll)
-{
-	uint32_t val;
-
-	val = I915_READ(WRPLL_CTL(pll->id));
-	I915_WRITE(WRPLL_CTL(pll->id), val & ~WRPLL_PLL_ENABLE);
-	POSTING_READ(WRPLL_CTL(pll->id));
-}
-
-static void hsw_ddi_spll_disable(struct drm_i915_private *dev_priv,
-				 struct intel_shared_dpll *pll)
-{
-	uint32_t val;
-
-	val = I915_READ(SPLL_CTL);
-	I915_WRITE(SPLL_CTL, val & ~SPLL_PLL_ENABLE);
-	POSTING_READ(SPLL_CTL);
-}
-
-static bool hsw_ddi_wrpll_get_hw_state(struct drm_i915_private *dev_priv,
-				       struct intel_shared_dpll *pll,
-				       struct intel_dpll_hw_state *hw_state)
+static bool broxton_phy_is_enabled(struct drm_i915_private *dev_priv,
+				   enum dpio_phy phy)
 {
-	uint32_t val;
-
-	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
+	if (!(I915_READ(BXT_P_CR_GT_DISP_PWRON) & GT_DISPLAY_POWER_ON(phy)))
 		return false;
 
-	val = I915_READ(WRPLL_CTL(pll->id));
-	hw_state->wrpll = val;
-
-	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
-
-	return val & WRPLL_PLL_ENABLE;
-}
-
-static bool hsw_ddi_spll_get_hw_state(struct drm_i915_private *dev_priv,
-				      struct intel_shared_dpll *pll,
-				      struct intel_dpll_hw_state *hw_state)
-{
-	uint32_t val;
+	if ((I915_READ(BXT_PORT_CL1CM_DW0(phy)) &
+	     (PHY_POWER_GOOD | PHY_RESERVED)) != PHY_POWER_GOOD) {
+		DRM_DEBUG_DRIVER("DDI PHY %d powered, but power hasn't settled\n",
+				 phy);
 
-	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
 		return false;
+	}
 
-	val = I915_READ(SPLL_CTL);
-	hw_state->spll = val;
-
-	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
-
-	return val & SPLL_PLL_ENABLE;
-}
-
-
-static const char * const hsw_ddi_pll_names[] = {
-	"WRPLL 1",
-	"WRPLL 2",
-	"SPLL"
-};
+	if (phy == DPIO_PHY1 &&
+	    !(I915_READ(BXT_PORT_REF_DW3(DPIO_PHY1)) & GRC_DONE)) {
+		DRM_DEBUG_DRIVER("DDI PHY 1 powered, but GRC isn't done\n");
 
-static void hsw_shared_dplls_init(struct drm_i915_private *dev_priv)
-{
-	int i;
+		return false;
+	}
 
-	dev_priv->num_shared_dpll = 3;
+	if (!(I915_READ(BXT_PHY_CTL_FAMILY(phy)) & COMMON_RESET_DIS)) {
+		DRM_DEBUG_DRIVER("DDI PHY %d powered, but still in reset\n",
+				 phy);
 
-	for (i = 0; i < 2; i++) {
-		dev_priv->shared_dplls[i].id = i;
-		dev_priv->shared_dplls[i].name = hsw_ddi_pll_names[i];
-		dev_priv->shared_dplls[i].disable = hsw_ddi_wrpll_disable;
-		dev_priv->shared_dplls[i].enable = hsw_ddi_wrpll_enable;
-		dev_priv->shared_dplls[i].get_hw_state =
-			hsw_ddi_wrpll_get_hw_state;
+		return false;
 	}
 
-	/* SPLL is special, but needs to be initialized anyway.. */
-	dev_priv->shared_dplls[i].id = i;
-	dev_priv->shared_dplls[i].name = hsw_ddi_pll_names[i];
-	dev_priv->shared_dplls[i].disable = hsw_ddi_spll_disable;
-	dev_priv->shared_dplls[i].enable = hsw_ddi_spll_enable;
-	dev_priv->shared_dplls[i].get_hw_state = hsw_ddi_spll_get_hw_state;
-
+	return true;
 }
 
-static const char * const skl_ddi_pll_names[] = {
-	"DPLL 1",
-	"DPLL 2",
-	"DPLL 3",
-};
-
-struct skl_dpll_regs {
-	i915_reg_t ctl, cfgcr1, cfgcr2;
-};
-
-/* this array is indexed by the *shared* pll id */
-static const struct skl_dpll_regs skl_dpll_regs[3] = {
-	{
-		/* DPLL 1 */
-		.ctl = LCPLL2_CTL,
-		.cfgcr1 = DPLL_CFGCR1(SKL_DPLL1),
-		.cfgcr2 = DPLL_CFGCR2(SKL_DPLL1),
-	},
-	{
-		/* DPLL 2 */
-		.ctl = WRPLL_CTL(0),
-		.cfgcr1 = DPLL_CFGCR1(SKL_DPLL2),
-		.cfgcr2 = DPLL_CFGCR2(SKL_DPLL2),
-	},
-	{
-		/* DPLL 3 */
-		.ctl = WRPLL_CTL(1),
-		.cfgcr1 = DPLL_CFGCR1(SKL_DPLL3),
-		.cfgcr2 = DPLL_CFGCR2(SKL_DPLL3),
-	},
-};
-
-static void skl_ddi_pll_enable(struct drm_i915_private *dev_priv,
-			       struct intel_shared_dpll *pll)
+static u32 broxton_get_grc(struct drm_i915_private *dev_priv, enum dpio_phy phy)
 {
-	uint32_t val;
-	unsigned int dpll;
-	const struct skl_dpll_regs *regs = skl_dpll_regs;
-
-	/* DPLL0 is not part of the shared DPLLs, so pll->id is 0 for DPLL1 */
-	dpll = pll->id + 1;
-
-	val = I915_READ(DPLL_CTRL1);
-
-	val &= ~(DPLL_CTRL1_HDMI_MODE(dpll) | DPLL_CTRL1_SSC(dpll) |
-		 DPLL_CTRL1_LINK_RATE_MASK(dpll));
-	val |= pll->config.hw_state.ctrl1 << (dpll * 6);
-
-	I915_WRITE(DPLL_CTRL1, val);
-	POSTING_READ(DPLL_CTRL1);
-
-	I915_WRITE(regs[pll->id].cfgcr1, pll->config.hw_state.cfgcr1);
-	I915_WRITE(regs[pll->id].cfgcr2, pll->config.hw_state.cfgcr2);
-	POSTING_READ(regs[pll->id].cfgcr1);
-	POSTING_READ(regs[pll->id].cfgcr2);
-
-	/* the enable bit is always bit 31 */
-	I915_WRITE(regs[pll->id].ctl,
-		   I915_READ(regs[pll->id].ctl) | LCPLL_PLL_ENABLE);
+	u32 val = I915_READ(BXT_PORT_REF_DW6(phy));
 
-	if (wait_for(I915_READ(DPLL_STATUS) & DPLL_LOCK(dpll), 5))
-		DRM_ERROR("DPLL %d not locked\n", dpll);
+	return (val & GRC_CODE_MASK) >> GRC_CODE_SHIFT;
 }
 
-static void skl_ddi_pll_disable(struct drm_i915_private *dev_priv,
-				struct intel_shared_dpll *pll)
+static void broxton_phy_wait_grc_done(struct drm_i915_private *dev_priv,
+				      enum dpio_phy phy)
 {
-	const struct skl_dpll_regs *regs = skl_dpll_regs;
-
-	/* the enable bit is always bit 31 */
-	I915_WRITE(regs[pll->id].ctl,
-		   I915_READ(regs[pll->id].ctl) & ~LCPLL_PLL_ENABLE);
-	POSTING_READ(regs[pll->id].ctl);
+	if (wait_for(I915_READ(BXT_PORT_REF_DW3(phy)) & GRC_DONE, 10))
+		DRM_ERROR("timeout waiting for PHY%d GRC\n", phy);
 }
 
-static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
-				     struct intel_shared_dpll *pll,
-				     struct intel_dpll_hw_state *hw_state)
-{
-	uint32_t val;
-	unsigned int dpll;
-	const struct skl_dpll_regs *regs = skl_dpll_regs;
-	bool ret;
-
-	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
-		return false;
-
-	ret = false;
-
-	/* DPLL0 is not part of the shared DPLLs, so pll->id is 0 for DPLL1 */
-	dpll = pll->id + 1;
-
-	val = I915_READ(regs[pll->id].ctl);
-	if (!(val & LCPLL_PLL_ENABLE))
-		goto out;
-
-	val = I915_READ(DPLL_CTRL1);
-	hw_state->ctrl1 = (val >> (dpll * 6)) & 0x3f;
-
-	/* avoid reading back stale values if HDMI mode is not enabled */
-	if (val & DPLL_CTRL1_HDMI_MODE(dpll)) {
-		hw_state->cfgcr1 = I915_READ(regs[pll->id].cfgcr1);
-		hw_state->cfgcr2 = I915_READ(regs[pll->id].cfgcr2);
-	}
-	ret = true;
+static bool broxton_phy_verify_state(struct drm_i915_private *dev_priv,
+				     enum dpio_phy phy);
 
-out:
-	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+static void broxton_phy_init(struct drm_i915_private *dev_priv,
+			     enum dpio_phy phy)
+{
+	enum port port;
+	u32 ports, val;
 
-	return ret;
-}
+	if (broxton_phy_is_enabled(dev_priv, phy)) {
+		/* Still read out the GRC value for state verification */
+		if (phy == DPIO_PHY0)
+			dev_priv->bxt_phy_grc = broxton_get_grc(dev_priv, phy);
 
-static void skl_shared_dplls_init(struct drm_i915_private *dev_priv)
-{
-	int i;
+		if (broxton_phy_verify_state(dev_priv, phy)) {
+			DRM_DEBUG_DRIVER("DDI PHY %d already enabled, "
+					 "won't reprogram it\n", phy);
 
-	dev_priv->num_shared_dpll = 3;
+			return;
+		}
 
-	for (i = 0; i < dev_priv->num_shared_dpll; i++) {
-		dev_priv->shared_dplls[i].id = i;
-		dev_priv->shared_dplls[i].name = skl_ddi_pll_names[i];
-		dev_priv->shared_dplls[i].disable = skl_ddi_pll_disable;
-		dev_priv->shared_dplls[i].enable = skl_ddi_pll_enable;
-		dev_priv->shared_dplls[i].get_hw_state =
-			skl_ddi_pll_get_hw_state;
+		DRM_DEBUG_DRIVER("DDI PHY %d enabled with invalid state, "
+				 "force reprogramming it\n", phy);
+	} else {
+		DRM_DEBUG_DRIVER("DDI PHY %d not enabled, enabling it\n", phy);
 	}
-}
-
-static void broxton_phy_init(struct drm_i915_private *dev_priv,
-			     enum dpio_phy phy)
-{
-	enum port port;
-	uint32_t val;
 
 	val = I915_READ(BXT_P_CR_GT_DISP_PWRON);
 	val |= GT_DISPLAY_POWER_ON(phy);
 	I915_WRITE(BXT_P_CR_GT_DISP_PWRON, val);
 
-	/* Considering 10ms timeout until BSpec is updated */
-	if (wait_for(I915_READ(BXT_PORT_CL1CM_DW0(phy)) & PHY_POWER_GOOD, 10))
+	/*
+	 * The PHY registers start out inaccessible and respond to reads with
+	 * all 1s.  Eventually they become accessible as they power up, then
+	 * the reserved bit will give the default 0.  Poll on the reserved bit
+	 * becoming 0 to find when the PHY is accessible.
+	 * HW team confirmed that the time to reach phypowergood status is
+	 * anywhere between 50 us and 100us.
+	 */
+	if (wait_for_us(((I915_READ(BXT_PORT_CL1CM_DW0(phy)) &
+		(PHY_RESERVED | PHY_POWER_GOOD)) == PHY_POWER_GOOD), 100)) {
 		DRM_ERROR("timeout during PHY%d power on\n", phy);
+	}
 
-	for (port =  (phy == DPIO_PHY0 ? PORT_B : PORT_A);
-	     port <= (phy == DPIO_PHY0 ? PORT_C : PORT_A); port++) {
+	if (phy == DPIO_PHY0)
+		ports = BIT(PORT_B) | BIT(PORT_C);
+	else
+		ports = BIT(PORT_A);
+
+	for_each_port_masked(port, ports) {
 		int lane;
 
 		for (lane = 0; lane < 4; lane++) {
@@ -2730,6 +1884,9 @@ static void broxton_phy_init(struct drm_
 	 * enabled.
 	 * TODO: port C is only connected on BXT-P, so on BXT0/1 we should
 	 * power down the second channel on PHY0 as well.
+	 *
+	 * FIXME: Clarify programming of the following, the register is
+	 * read-only with bit 6 fixed at 0 at least in stepping A.
 	 */
 	if (phy == DPIO_PHY1)
 		val |= OCL2_LDOFUSE_PWR_DIS;
@@ -2742,12 +1899,10 @@ static void broxton_phy_init(struct drm_
 		 * the corresponding calibrated value from PHY1, and disable
 		 * the automatic calibration on PHY0.
 		 */
-		if (wait_for(I915_READ(BXT_PORT_REF_DW3(DPIO_PHY1)) & GRC_DONE,
-			     10))
-			DRM_ERROR("timeout waiting for PHY1 GRC\n");
+		broxton_phy_wait_grc_done(dev_priv, DPIO_PHY1);
 
-		val = I915_READ(BXT_PORT_REF_DW6(DPIO_PHY1));
-		val = (val & GRC_CODE_MASK) >> GRC_CODE_SHIFT;
+		val = dev_priv->bxt_phy_grc = broxton_get_grc(dev_priv,
+							      DPIO_PHY1);
 		grc_code = val << GRC_CODE_FAST_SHIFT |
 			   val << GRC_CODE_SLOW_SHIFT |
 			   val;
@@ -2757,17 +1912,27 @@ static void broxton_phy_init(struct drm_
 		val |= GRC_DIS | GRC_RDY_OVRD;
 		I915_WRITE(BXT_PORT_REF_DW8(DPIO_PHY0), val);
 	}
+	/*
+	 * During PHY1 init delay waiting for GRC calibration to finish, since
+	 * it can happen in parallel with the subsequent PHY0 init.
+	 */
 
 	val = I915_READ(BXT_PHY_CTL_FAMILY(phy));
 	val |= COMMON_RESET_DIS;
 	I915_WRITE(BXT_PHY_CTL_FAMILY(phy), val);
 }
 
-void broxton_ddi_phy_init(struct drm_device *dev)
+void broxton_ddi_phy_init(struct drm_i915_private *dev_priv)
 {
 	/* Enable PHY1 first since it provides Rcomp for PHY0 */
-	broxton_phy_init(dev->dev_private, DPIO_PHY1);
-	broxton_phy_init(dev->dev_private, DPIO_PHY0);
+	broxton_phy_init(dev_priv, DPIO_PHY1);
+	broxton_phy_init(dev_priv, DPIO_PHY0);
+
+	/*
+	 * If BIOS enabled only PHY0 and not PHY1, we skipped waiting for the
+	 * PHY1 GRC calibration to finish, so wait for it here.
+	 */
+	broxton_phy_wait_grc_done(dev_priv, DPIO_PHY1);
 }
 
 static void broxton_phy_uninit(struct drm_i915_private *dev_priv,
@@ -2778,260 +1943,126 @@ static void broxton_phy_uninit(struct dr
 	val = I915_READ(BXT_PHY_CTL_FAMILY(phy));
 	val &= ~COMMON_RESET_DIS;
 	I915_WRITE(BXT_PHY_CTL_FAMILY(phy), val);
+
+	val = I915_READ(BXT_P_CR_GT_DISP_PWRON);
+	val &= ~GT_DISPLAY_POWER_ON(phy);
+	I915_WRITE(BXT_P_CR_GT_DISP_PWRON, val);
 }
 
-void broxton_ddi_phy_uninit(struct drm_device *dev)
+void broxton_ddi_phy_uninit(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-
 	broxton_phy_uninit(dev_priv, DPIO_PHY1);
 	broxton_phy_uninit(dev_priv, DPIO_PHY0);
-
-	/* FIXME: do this in broxton_phy_uninit per phy */
-	I915_WRITE(BXT_P_CR_GT_DISP_PWRON, 0);
 }
 
-static const char * const bxt_ddi_pll_names[] = {
-	"PORT PLL A",
-	"PORT PLL B",
-	"PORT PLL C",
-};
-
-static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv,
-				struct intel_shared_dpll *pll)
+static bool __printf(6, 7)
+__phy_reg_verify_state(struct drm_i915_private *dev_priv, enum dpio_phy phy,
+		       i915_reg_t reg, u32 mask, u32 expected,
+		       const char *reg_fmt, ...)
 {
-	uint32_t temp;
-	enum port port = (enum port)pll->id;	/* 1:1 port->PLL mapping */
-
-	temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
-	temp &= ~PORT_PLL_REF_SEL;
-	/* Non-SSC reference */
-	I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
-
-	/* Disable 10 bit clock */
-	temp = I915_READ(BXT_PORT_PLL_EBB_4(port));
-	temp &= ~PORT_PLL_10BIT_CLK_ENABLE;
-	I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp);
-
-	/* Write P1 & P2 */
-	temp = I915_READ(BXT_PORT_PLL_EBB_0(port));
-	temp &= ~(PORT_PLL_P1_MASK | PORT_PLL_P2_MASK);
-	temp |= pll->config.hw_state.ebb0;
-	I915_WRITE(BXT_PORT_PLL_EBB_0(port), temp);
-
-	/* Write M2 integer */
-	temp = I915_READ(BXT_PORT_PLL(port, 0));
-	temp &= ~PORT_PLL_M2_MASK;
-	temp |= pll->config.hw_state.pll0;
-	I915_WRITE(BXT_PORT_PLL(port, 0), temp);
-
-	/* Write N */
-	temp = I915_READ(BXT_PORT_PLL(port, 1));
-	temp &= ~PORT_PLL_N_MASK;
-	temp |= pll->config.hw_state.pll1;
-	I915_WRITE(BXT_PORT_PLL(port, 1), temp);
-
-	/* Write M2 fraction */
-	temp = I915_READ(BXT_PORT_PLL(port, 2));
-	temp &= ~PORT_PLL_M2_FRAC_MASK;
-	temp |= pll->config.hw_state.pll2;
-	I915_WRITE(BXT_PORT_PLL(port, 2), temp);
-
-	/* Write M2 fraction enable */
-	temp = I915_READ(BXT_PORT_PLL(port, 3));
-	temp &= ~PORT_PLL_M2_FRAC_ENABLE;
-	temp |= pll->config.hw_state.pll3;
-	I915_WRITE(BXT_PORT_PLL(port, 3), temp);
-
-	/* Write coeff */
-	temp = I915_READ(BXT_PORT_PLL(port, 6));
-	temp &= ~PORT_PLL_PROP_COEFF_MASK;
-	temp &= ~PORT_PLL_INT_COEFF_MASK;
-	temp &= ~PORT_PLL_GAIN_CTL_MASK;
-	temp |= pll->config.hw_state.pll6;
-	I915_WRITE(BXT_PORT_PLL(port, 6), temp);
-
-	/* Write calibration val */
-	temp = I915_READ(BXT_PORT_PLL(port, 8));
-	temp &= ~PORT_PLL_TARGET_CNT_MASK;
-	temp |= pll->config.hw_state.pll8;
-	I915_WRITE(BXT_PORT_PLL(port, 8), temp);
-
-	temp = I915_READ(BXT_PORT_PLL(port, 9));
-	temp &= ~PORT_PLL_LOCK_THRESHOLD_MASK;
-	temp |= pll->config.hw_state.pll9;
-	I915_WRITE(BXT_PORT_PLL(port, 9), temp);
+	struct va_format vaf;
+	va_list args;
+	u32 val;
 
-	temp = I915_READ(BXT_PORT_PLL(port, 10));
-	temp &= ~PORT_PLL_DCO_AMP_OVR_EN_H;
-	temp &= ~PORT_PLL_DCO_AMP_MASK;
-	temp |= pll->config.hw_state.pll10;
-	I915_WRITE(BXT_PORT_PLL(port, 10), temp);
+	val = I915_READ(reg);
+	if ((val & mask) == expected)
+		return true;
 
-	/* Recalibrate with new settings */
-	temp = I915_READ(BXT_PORT_PLL_EBB_4(port));
-	temp |= PORT_PLL_RECALIBRATE;
-	I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp);
-	temp &= ~PORT_PLL_10BIT_CLK_ENABLE;
-	temp |= pll->config.hw_state.ebb4;
-	I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp);
+	va_start(args, reg_fmt);
+	vaf.fmt = reg_fmt;
+	vaf.va = &args;
 
-	/* Enable PLL */
-	temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
-	temp |= PORT_PLL_ENABLE;
-	I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
-	POSTING_READ(BXT_PORT_PLL_ENABLE(port));
+	DRM_DEBUG_DRIVER("DDI PHY %d reg %pV [%08x] state mismatch: "
+			 "current %08x, expected %08x (mask %08x)\n",
+			 phy, &vaf, reg.reg, val, (val & ~mask) | expected,
+			 mask);
 
-	if (wait_for_atomic_us((I915_READ(BXT_PORT_PLL_ENABLE(port)) &
-			PORT_PLL_LOCK), 200))
-		DRM_ERROR("PLL %d not locked\n", port);
+	va_end(args);
 
-	/*
-	 * While we write to the group register to program all lanes at once we
-	 * can read only lane registers and we pick lanes 0/1 for that.
-	 */
-	temp = I915_READ(BXT_PORT_PCS_DW12_LN01(port));
-	temp &= ~LANE_STAGGER_MASK;
-	temp &= ~LANESTAGGER_STRAP_OVRD;
-	temp |= pll->config.hw_state.pcsdw12;
-	I915_WRITE(BXT_PORT_PCS_DW12_GRP(port), temp);
+	return false;
 }
 
-static void bxt_ddi_pll_disable(struct drm_i915_private *dev_priv,
-					struct intel_shared_dpll *pll)
+static bool broxton_phy_verify_state(struct drm_i915_private *dev_priv,
+				     enum dpio_phy phy)
 {
-	enum port port = (enum port)pll->id;	/* 1:1 port->PLL mapping */
-	uint32_t temp;
-
-	temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
-	temp &= ~PORT_PLL_ENABLE;
-	I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
-	POSTING_READ(BXT_PORT_PLL_ENABLE(port));
-}
+	enum port port;
+	u32 ports;
+	uint32_t mask;
+	bool ok;
 
-static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
-					struct intel_shared_dpll *pll,
-					struct intel_dpll_hw_state *hw_state)
-{
-	enum port port = (enum port)pll->id;	/* 1:1 port->PLL mapping */
-	uint32_t val;
-	bool ret;
+#define _CHK(reg, mask, exp, fmt, ...)					\
+	__phy_reg_verify_state(dev_priv, phy, reg, mask, exp, fmt,	\
+			       ## __VA_ARGS__)
 
-	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
+	/* We expect the PHY to be always enabled */
+	if (!broxton_phy_is_enabled(dev_priv, phy))
 		return false;
 
-	ret = false;
-
-	val = I915_READ(BXT_PORT_PLL_ENABLE(port));
-	if (!(val & PORT_PLL_ENABLE))
-		goto out;
-
-	hw_state->ebb0 = I915_READ(BXT_PORT_PLL_EBB_0(port));
-	hw_state->ebb0 &= PORT_PLL_P1_MASK | PORT_PLL_P2_MASK;
-
-	hw_state->ebb4 = I915_READ(BXT_PORT_PLL_EBB_4(port));
-	hw_state->ebb4 &= PORT_PLL_10BIT_CLK_ENABLE;
-
-	hw_state->pll0 = I915_READ(BXT_PORT_PLL(port, 0));
-	hw_state->pll0 &= PORT_PLL_M2_MASK;
-
-	hw_state->pll1 = I915_READ(BXT_PORT_PLL(port, 1));
-	hw_state->pll1 &= PORT_PLL_N_MASK;
+	ok = true;
 
-	hw_state->pll2 = I915_READ(BXT_PORT_PLL(port, 2));
-	hw_state->pll2 &= PORT_PLL_M2_FRAC_MASK;
+	if (phy == DPIO_PHY0)
+		ports = BIT(PORT_B) | BIT(PORT_C);
+	else
+		ports = BIT(PORT_A);
 
-	hw_state->pll3 = I915_READ(BXT_PORT_PLL(port, 3));
-	hw_state->pll3 &= PORT_PLL_M2_FRAC_ENABLE;
+	for_each_port_masked(port, ports) {
+		int lane;
 
-	hw_state->pll6 = I915_READ(BXT_PORT_PLL(port, 6));
-	hw_state->pll6 &= PORT_PLL_PROP_COEFF_MASK |
-			  PORT_PLL_INT_COEFF_MASK |
-			  PORT_PLL_GAIN_CTL_MASK;
+		for (lane = 0; lane < 4; lane++)
+			ok &= _CHK(BXT_PORT_TX_DW14_LN(port, lane),
+				    LATENCY_OPTIM,
+				    lane != 1 ? LATENCY_OPTIM : 0,
+				    "BXT_PORT_TX_DW14_LN(%d, %d)", port, lane);
+	}
 
-	hw_state->pll8 = I915_READ(BXT_PORT_PLL(port, 8));
-	hw_state->pll8 &= PORT_PLL_TARGET_CNT_MASK;
+	/* PLL Rcomp code offset */
+	ok &= _CHK(BXT_PORT_CL1CM_DW9(phy),
+		    IREF0RC_OFFSET_MASK, 0xe4 << IREF0RC_OFFSET_SHIFT,
+		    "BXT_PORT_CL1CM_DW9(%d)", phy);
+	ok &= _CHK(BXT_PORT_CL1CM_DW10(phy),
+		    IREF1RC_OFFSET_MASK, 0xe4 << IREF1RC_OFFSET_SHIFT,
+		    "BXT_PORT_CL1CM_DW10(%d)", phy);
 
-	hw_state->pll9 = I915_READ(BXT_PORT_PLL(port, 9));
-	hw_state->pll9 &= PORT_PLL_LOCK_THRESHOLD_MASK;
+	/* Power gating */
+	mask = OCL1_POWER_DOWN_EN | DW28_OLDO_DYN_PWR_DOWN_EN | SUS_CLK_CONFIG;
+	ok &= _CHK(BXT_PORT_CL1CM_DW28(phy), mask, mask,
+		    "BXT_PORT_CL1CM_DW28(%d)", phy);
 
-	hw_state->pll10 = I915_READ(BXT_PORT_PLL(port, 10));
-	hw_state->pll10 &= PORT_PLL_DCO_AMP_OVR_EN_H |
-			   PORT_PLL_DCO_AMP_MASK;
+	if (phy == DPIO_PHY0)
+		ok &= _CHK(BXT_PORT_CL2CM_DW6_BC,
+			   DW6_OLDO_DYN_PWR_DOWN_EN, DW6_OLDO_DYN_PWR_DOWN_EN,
+			   "BXT_PORT_CL2CM_DW6_BC");
 
 	/*
-	 * While we write to the group register to program all lanes at once we
-	 * can read only lane registers. We configure all lanes the same way, so
-	 * here just read out lanes 0/1 and output a note if lanes 2/3 differ.
+	 * TODO: Verify BXT_PORT_CL1CM_DW30 bit OCL2_LDOFUSE_PWR_DIS,
+	 * at least on stepping A this bit is read-only and fixed at 0.
 	 */
-	hw_state->pcsdw12 = I915_READ(BXT_PORT_PCS_DW12_LN01(port));
-	if (I915_READ(BXT_PORT_PCS_DW12_LN23(port)) != hw_state->pcsdw12)
-		DRM_DEBUG_DRIVER("lane stagger config different for lane 01 (%08x) and 23 (%08x)\n",
-				 hw_state->pcsdw12,
-				 I915_READ(BXT_PORT_PCS_DW12_LN23(port)));
-	hw_state->pcsdw12 &= LANE_STAGGER_MASK | LANESTAGGER_STRAP_OVRD;
-
-	ret = true;
 
-out:
-	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
-
-	return ret;
-}
-
-static void bxt_shared_dplls_init(struct drm_i915_private *dev_priv)
-{
-	int i;
+	if (phy == DPIO_PHY0) {
+		u32 grc_code = dev_priv->bxt_phy_grc;
 
-	dev_priv->num_shared_dpll = 3;
+		grc_code = grc_code << GRC_CODE_FAST_SHIFT |
+			   grc_code << GRC_CODE_SLOW_SHIFT |
+			   grc_code;
+		mask = GRC_CODE_FAST_MASK | GRC_CODE_SLOW_MASK |
+		       GRC_CODE_NOM_MASK;
+		ok &= _CHK(BXT_PORT_REF_DW6(DPIO_PHY0), mask, grc_code,
+			    "BXT_PORT_REF_DW6(%d)", DPIO_PHY0);
 
-	for (i = 0; i < dev_priv->num_shared_dpll; i++) {
-		dev_priv->shared_dplls[i].id = i;
-		dev_priv->shared_dplls[i].name = bxt_ddi_pll_names[i];
-		dev_priv->shared_dplls[i].disable = bxt_ddi_pll_disable;
-		dev_priv->shared_dplls[i].enable = bxt_ddi_pll_enable;
-		dev_priv->shared_dplls[i].get_hw_state =
-			bxt_ddi_pll_get_hw_state;
+		mask = GRC_DIS | GRC_RDY_OVRD;
+		ok &= _CHK(BXT_PORT_REF_DW8(DPIO_PHY0), mask, mask,
+			    "BXT_PORT_REF_DW8(%d)", DPIO_PHY0);
 	}
+
+	return ok;
+#undef _CHK
 }
 
-void intel_ddi_pll_init(struct drm_device *dev)
+void broxton_ddi_phy_verify_state(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	uint32_t val = I915_READ(LCPLL_CTL);
-
-	if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
-		skl_shared_dplls_init(dev_priv);
-	else if (IS_BROXTON(dev))
-		bxt_shared_dplls_init(dev_priv);
-	else
-		hsw_shared_dplls_init(dev_priv);
-
-	if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
-		int cdclk_freq;
-
-		cdclk_freq = dev_priv->display.get_display_clock_speed(dev);
-		dev_priv->skl_boot_cdclk = cdclk_freq;
-		if (skl_sanitize_cdclk(dev_priv))
-			DRM_DEBUG_KMS("Sanitized cdclk programmed by pre-os\n");
-		if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE))
-			DRM_ERROR("LCPLL1 is disabled\n");
-	} else if (IS_BROXTON(dev)) {
-		broxton_init_cdclk(dev);
-		broxton_ddi_phy_init(dev);
-	} else {
-		/*
-		 * The LCPLL register should be turned on by the BIOS. For now
-		 * let's just check its state and print errors in case
-		 * something is wrong.  Don't even try to turn it on.
-		 */
-
-		if (val & LCPLL_CD_SOURCE_FCLK)
-			DRM_ERROR("CDCLK source is not LCPLL\n");
-
-		if (val & LCPLL_PLL_DISABLE)
-			DRM_ERROR("LCPLL is disabled\n");
-	}
+	if (!broxton_phy_verify_state(dev_priv, DPIO_PHY0) ||
+	    !broxton_phy_verify_state(dev_priv, DPIO_PHY1))
+		i915_report_error(dev_priv, "DDI PHY state mismatch\n");
 }
 
 void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp)
@@ -3086,12 +2117,18 @@ void intel_ddi_fdi_disable(struct drm_cr
 	struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
 	uint32_t val;
 
-	intel_ddi_post_disable(intel_encoder);
-
+	/*
+	 * Bspec lists this as both step 13 (before DDI_BUF_CTL disable)
+	 * and step 18 (after clearing PORT_CLK_SEL). Based on a BUN,
+	 * step 13 is the correct place for it. Step 18 is where it was
+	 * originally before the BUN.
+	 */
 	val = I915_READ(FDI_RX_CTL(PIPE_A));
 	val &= ~FDI_RX_ENABLE;
 	I915_WRITE(FDI_RX_CTL(PIPE_A), val);
 
+	intel_ddi_post_disable(intel_encoder);
+
 	val = I915_READ(FDI_RX_MISC(PIPE_A));
 	val &= ~(FDI_RX_PWRDN_LANE1_MASK | FDI_RX_PWRDN_LANE0_MASK);
 	val |= FDI_RX_PWRDN_LANE1_VAL(2) | FDI_RX_PWRDN_LANE0_VAL(2);
@@ -3115,6 +2152,10 @@ void intel_ddi_get_config(struct intel_e
 	struct intel_hdmi *intel_hdmi;
 	u32 temp, flags = 0;
 
+	/* XXX: DSI transcoder paranoia */
+	if (WARN_ON(transcoder_is_dsi(cpu_transcoder)))
+		return;
+
 	temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
 	if (temp & TRANS_DDI_PHSYNC)
 		flags |= DRM_MODE_FLAG_PHSYNC;
@@ -3151,8 +2192,10 @@ void intel_ddi_get_config(struct intel_e
 
 		if (intel_hdmi->infoframe_enabled(&encoder->base, pipe_config))
 			pipe_config->has_infoframe = true;
-		break;
+		/* fall through */
 	case TRANS_DDI_MODE_SELECT_DVI:
+		pipe_config->lane_count = 4;
+		break;
 	case TRANS_DDI_MODE_SELECT_FDI:
 		break;
 	case TRANS_DDI_MODE_SELECT_DP_SST:
@@ -3172,8 +2215,8 @@ void intel_ddi_get_config(struct intel_e
 			pipe_config->has_audio = true;
 	}
 
-	if (encoder->type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp_bpp &&
-	    pipe_config->pipe_bpp > dev_priv->vbt.edp_bpp) {
+	if (encoder->type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.bpp &&
+	    pipe_config->pipe_bpp > dev_priv->vbt.edp.bpp) {
 		/*
 		 * This is a big fat ugly hack.
 		 *
@@ -3188,8 +2231,8 @@ void intel_ddi_get_config(struct intel_e
 		 * load.
 		 */
 		DRM_DEBUG_KMS("pipe has %d bpp for eDP panel, overriding BIOS-provided max %d bpp\n",
-			      pipe_config->pipe_bpp, dev_priv->vbt.edp_bpp);
-		dev_priv->vbt.edp_bpp = pipe_config->pipe_bpp;
+			      pipe_config->pipe_bpp, dev_priv->vbt.edp.bpp);
+		dev_priv->vbt.edp.bpp = pipe_config->pipe_bpp;
 	}
 
 	intel_ddi_clock_get(encoder, pipe_config);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_display.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_display.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_display.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_display.c	2016-07-24 15:23:50.000000000 -0400
@@ -36,6 +36,7 @@
 #include "intel_drv.h"
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
+#include "intel_dsi.h"
 #include "i915_trace.h"
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
@@ -96,12 +97,13 @@ static int intel_framebuffer_init(struct
 				  struct drm_i915_gem_object *obj);
 static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc);
 static void intel_set_pipe_timings(struct intel_crtc *intel_crtc);
+static void intel_set_pipe_src_size(struct intel_crtc *intel_crtc);
 static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc,
 					 struct intel_link_m_n *m_n,
 					 struct intel_link_m_n *m2_n2);
 static void ironlake_set_pipeconf(struct drm_crtc *crtc);
 static void haswell_set_pipeconf(struct drm_crtc *crtc);
-static void intel_set_pipe_csc(struct drm_crtc *crtc);
+static void haswell_set_pipemisc(struct drm_crtc *crtc);
 static void vlv_prepare_pll(struct intel_crtc *crtc,
 			    const struct intel_crtc_state *pipe_config);
 static void chv_prepare_pll(struct intel_crtc *crtc,
@@ -110,13 +112,11 @@ static void intel_begin_crtc_commit(stru
 static void intel_finish_crtc_commit(struct drm_crtc *, struct drm_crtc_state *);
 static void skl_init_scalers(struct drm_device *dev, struct intel_crtc *intel_crtc,
 	struct intel_crtc_state *crtc_state);
-static int i9xx_get_refclk(const struct intel_crtc_state *crtc_state,
-			   int num_connectors);
 static void skylake_pfit_enable(struct intel_crtc *crtc);
 static void ironlake_pfit_disable(struct intel_crtc *crtc, bool force);
 static void ironlake_pfit_enable(struct intel_crtc *crtc);
 static void intel_modeset_setup_hw_state(struct drm_device *dev);
-static void intel_pre_disable_primary(struct drm_crtc *crtc);
+static void intel_pre_disable_primary_noatomic(struct drm_crtc *crtc);
 
 typedef struct {
 	int	min, max;
@@ -147,15 +147,12 @@ static int valleyview_get_vco(struct drm
 	return vco_freq[hpll_freq] * 1000;
 }
 
-static int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv,
-				  const char *name, u32 reg)
+int vlv_get_cck_clock(struct drm_i915_private *dev_priv,
+		      const char *name, u32 reg, int ref_freq)
 {
 	u32 val;
 	int divider;
 
-	if (dev_priv->hpll_freq == 0)
-		dev_priv->hpll_freq = valleyview_get_vco(dev_priv);
-
 	mutex_lock(&dev_priv->sb_lock);
 	val = vlv_cck_read(dev_priv, reg);
 	mutex_unlock(&dev_priv->sb_lock);
@@ -166,52 +163,75 @@ static int vlv_get_cck_clock_hpll(struct
 	     (divider << CCK_FREQUENCY_STATUS_SHIFT),
 	     "%s change in progress\n", name);
 
-	return DIV_ROUND_CLOSEST(dev_priv->hpll_freq << 1, divider + 1);
+	return DIV_ROUND_CLOSEST(ref_freq << 1, divider + 1);
 }
 
-int
-intel_pch_rawclk(struct drm_device *dev)
+static int vlv_get_cck_clock_hpll(struct drm_i915_private *dev_priv,
+				  const char *name, u32 reg)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	if (dev_priv->hpll_freq == 0)
+		dev_priv->hpll_freq = valleyview_get_vco(dev_priv);
 
-	WARN_ON(!HAS_PCH_SPLIT(dev));
+	return vlv_get_cck_clock(dev_priv, name, reg,
+				 dev_priv->hpll_freq);
+}
 
-	return I915_READ(PCH_RAWCLK_FREQ) & RAWCLK_FREQ_MASK;
+static int
+intel_pch_rawclk(struct drm_i915_private *dev_priv)
+{
+	return (I915_READ(PCH_RAWCLK_FREQ) & RAWCLK_FREQ_MASK) * 1000;
 }
 
-/* hrawclock is 1/4 the FSB frequency */
-int intel_hrawclk(struct drm_device *dev)
+static int
+intel_vlv_hrawclk(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	uint32_t clkcfg;
+	return vlv_get_cck_clock_hpll(dev_priv, "hrawclk",
+				      CCK_DISPLAY_REF_CLOCK_CONTROL);
+}
 
-	/* There is no CLKCFG reg in Valleyview. VLV hrawclk is 200 MHz */
-	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
-		return 200;
+static int
+intel_g4x_hrawclk(struct drm_i915_private *dev_priv)
+{
+	uint32_t clkcfg;
 
+	/* hrawclock is 1/4 the FSB frequency */
 	clkcfg = I915_READ(CLKCFG);
 	switch (clkcfg & CLKCFG_FSB_MASK) {
 	case CLKCFG_FSB_400:
-		return 100;
+		return 100000;
 	case CLKCFG_FSB_533:
-		return 133;
+		return 133333;
 	case CLKCFG_FSB_667:
-		return 166;
+		return 166667;
 	case CLKCFG_FSB_800:
-		return 200;
+		return 200000;
 	case CLKCFG_FSB_1067:
-		return 266;
+		return 266667;
 	case CLKCFG_FSB_1333:
-		return 333;
+		return 333333;
 	/* these two are just a guess; one of them might be right */
 	case CLKCFG_FSB_1600:
 	case CLKCFG_FSB_1600_ALT:
-		return 400;
+		return 400000;
 	default:
-		return 133;
+		return 133333;
 	}
 }
 
+static void intel_update_rawclk(struct drm_i915_private *dev_priv)
+{
+	if (HAS_PCH_SPLIT(dev_priv))
+		dev_priv->rawclk_freq = intel_pch_rawclk(dev_priv);
+	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+		dev_priv->rawclk_freq = intel_vlv_hrawclk(dev_priv);
+	else if (IS_G4X(dev_priv) || IS_PINEVIEW(dev_priv))
+		dev_priv->rawclk_freq = intel_g4x_hrawclk(dev_priv);
+	else
+		return; /* no rawclk on other platforms, or no need to know it */
+
+	DRM_DEBUG_DRIVER("rawclk rate: %d kHz\n", dev_priv->rawclk_freq);
+}
+
 static void intel_update_czclk(struct drm_i915_private *dev_priv)
 {
 	if (!(IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)))
@@ -224,13 +244,15 @@ static void intel_update_czclk(struct dr
 }
 
 static inline u32 /* units of 100MHz */
-intel_fdi_link_freq(struct drm_device *dev)
+intel_fdi_link_freq(struct drm_i915_private *dev_priv,
+		    const struct intel_crtc_state *pipe_config)
 {
-	if (IS_GEN5(dev)) {
-		struct drm_i915_private *dev_priv = dev->dev_private;
-		return (I915_READ(FDI_PLL_BIOS_0) & FDI_PLL_FB_CLOCK_MASK) + 2;
-	} else
-		return 27;
+	if (HAS_DDI(dev_priv))
+		return pipe_config->port_clock; /* SPLL */
+	else if (IS_GEN5(dev_priv))
+		return ((I915_READ(FDI_PLL_BIOS_0) & FDI_PLL_FB_CLOCK_MASK) + 2) * 10000;
+	else
+		return 270000;
 }
 
 static const intel_limit_t intel_limits_i8xx_dac = {
@@ -550,89 +572,6 @@ static bool intel_pipe_will_have_type(co
 	return false;
 }
 
-static const intel_limit_t *
-intel_ironlake_limit(struct intel_crtc_state *crtc_state, int refclk)
-{
-	struct drm_device *dev = crtc_state->base.crtc->dev;
-	const intel_limit_t *limit;
-
-	if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS)) {
-		if (intel_is_dual_link_lvds(dev)) {
-			if (refclk == 100000)
-				limit = &intel_limits_ironlake_dual_lvds_100m;
-			else
-				limit = &intel_limits_ironlake_dual_lvds;
-		} else {
-			if (refclk == 100000)
-				limit = &intel_limits_ironlake_single_lvds_100m;
-			else
-				limit = &intel_limits_ironlake_single_lvds;
-		}
-	} else
-		limit = &intel_limits_ironlake_dac;
-
-	return limit;
-}
-
-static const intel_limit_t *
-intel_g4x_limit(struct intel_crtc_state *crtc_state)
-{
-	struct drm_device *dev = crtc_state->base.crtc->dev;
-	const intel_limit_t *limit;
-
-	if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS)) {
-		if (intel_is_dual_link_lvds(dev))
-			limit = &intel_limits_g4x_dual_channel_lvds;
-		else
-			limit = &intel_limits_g4x_single_channel_lvds;
-	} else if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_HDMI) ||
-		   intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_ANALOG)) {
-		limit = &intel_limits_g4x_hdmi;
-	} else if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_SDVO)) {
-		limit = &intel_limits_g4x_sdvo;
-	} else /* The option is for other outputs */
-		limit = &intel_limits_i9xx_sdvo;
-
-	return limit;
-}
-
-static const intel_limit_t *
-intel_limit(struct intel_crtc_state *crtc_state, int refclk)
-{
-	struct drm_device *dev = crtc_state->base.crtc->dev;
-	const intel_limit_t *limit;
-
-	if (IS_BROXTON(dev))
-		limit = &intel_limits_bxt;
-	else if (HAS_PCH_SPLIT(dev))
-		limit = intel_ironlake_limit(crtc_state, refclk);
-	else if (IS_G4X(dev)) {
-		limit = intel_g4x_limit(crtc_state);
-	} else if (IS_PINEVIEW(dev)) {
-		if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS))
-			limit = &intel_limits_pineview_lvds;
-		else
-			limit = &intel_limits_pineview_sdvo;
-	} else if (IS_CHERRYVIEW(dev)) {
-		limit = &intel_limits_chv;
-	} else if (IS_VALLEYVIEW(dev)) {
-		limit = &intel_limits_vlv;
-	} else if (!IS_GEN2(dev)) {
-		if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS))
-			limit = &intel_limits_i9xx_lvds;
-		else
-			limit = &intel_limits_i9xx_sdvo;
-	} else {
-		if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS))
-			limit = &intel_limits_i8xx_lvds;
-		else if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_DVO))
-			limit = &intel_limits_i8xx_dvo;
-		else
-			limit = &intel_limits_i8xx_dac;
-	}
-	return limit;
-}
-
 /*
  * Platform specific helpers to calculate the port PLL loopback- (clock.m),
  * and post-divider (clock.p) values, pre- (clock.vco) and post-divided fast
@@ -763,6 +702,16 @@ i9xx_select_p2_div(const intel_limit_t *
 	}
 }
 
+/*
+ * Returns a set of divisors for the desired target clock with the given
+ * refclk, or FALSE.  The returned values represent the clock equation:
+ * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
+ *
+ * Target and reference clocks are specified in kHz.
+ *
+ * If match_clock is provided, then best_clock P divider must match the P
+ * divider from @match_clock used for LVDS downclocking.
+ */
 static bool
 i9xx_find_best_dpll(const intel_limit_t *limit,
 		    struct intel_crtc_state *crtc_state,
@@ -810,6 +759,16 @@ i9xx_find_best_dpll(const intel_limit_t
 	return (err != target);
 }
 
+/*
+ * Returns a set of divisors for the desired target clock with the given
+ * refclk, or FALSE.  The returned values represent the clock equation:
+ * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
+ *
+ * Target and reference clocks are specified in kHz.
+ *
+ * If match_clock is provided, then best_clock P divider must match the P
+ * divider from @match_clock used for LVDS downclocking.
+ */
 static bool
 pnv_find_best_dpll(const intel_limit_t *limit,
 		   struct intel_crtc_state *crtc_state,
@@ -855,6 +814,16 @@ pnv_find_best_dpll(const intel_limit_t *
 	return (err != target);
 }
 
+/*
+ * Returns a set of divisors for the desired target clock with the given
+ * refclk, or FALSE.  The returned values represent the clock equation:
+ * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
+ *
+ * Target and reference clocks are specified in kHz.
+ *
+ * If match_clock is provided, then best_clock P divider must match the P
+ * divider from @match_clock used for LVDS downclocking.
+ */
 static bool
 g4x_find_best_dpll(const intel_limit_t *limit,
 		   struct intel_crtc_state *crtc_state,
@@ -943,6 +912,11 @@ static bool vlv_PLL_is_optimal(struct dr
 	return *error_ppm + 10 < best_error_ppm;
 }
 
+/*
+ * Returns a set of divisors for the desired target clock with the given
+ * refclk, or FALSE.  The returned values represent the clock equation:
+ * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
+ */
 static bool
 vlv_find_best_dpll(const intel_limit_t *limit,
 		   struct intel_crtc_state *crtc_state,
@@ -997,6 +971,11 @@ vlv_find_best_dpll(const intel_limit_t *
 	return found;
 }
 
+/*
+ * Returns a set of divisors for the desired target clock with the given
+ * refclk, or FALSE.  The returned values represent the clock equation:
+ * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
+ */
 static bool
 chv_find_best_dpll(const intel_limit_t *limit,
 		   struct intel_crtc_state *crtc_state,
@@ -1058,9 +1037,10 @@ chv_find_best_dpll(const intel_limit_t *
 bool bxt_find_best_dpll(struct intel_crtc_state *crtc_state, int target_clock,
 			intel_clock_t *best_clock)
 {
-	int refclk = i9xx_get_refclk(crtc_state, 0);
+	int refclk = 100000;
+	const intel_limit_t *limit = &intel_limits_bxt;
 
-	return chv_find_best_dpll(intel_limit(crtc_state, refclk), crtc_state,
+	return chv_find_best_dpll(limit, crtc_state,
 				  target_clock, refclk, NULL, best_clock);
 }
 
@@ -1165,7 +1145,7 @@ void assert_pll(struct drm_i915_private
 }
 
 /* XXX: the dsi pll is shared between MIPI DSI ports */
-static void assert_dsi_pll(struct drm_i915_private *dev_priv, bool state)
+void assert_dsi_pll(struct drm_i915_private *dev_priv, bool state)
 {
 	u32 val;
 	bool cur_state;
@@ -1179,36 +1159,6 @@ static void assert_dsi_pll(struct drm_i9
 	     "DSI PLL state assertion failure (expected %s, current %s)\n",
 			onoff(state), onoff(cur_state));
 }
-#define assert_dsi_pll_enabled(d) assert_dsi_pll(d, true)
-#define assert_dsi_pll_disabled(d) assert_dsi_pll(d, false)
-
-struct intel_shared_dpll *
-intel_crtc_to_shared_dpll(struct intel_crtc *crtc)
-{
-	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
-
-	if (crtc->config->shared_dpll < 0)
-		return NULL;
-
-	return &dev_priv->shared_dplls[crtc->config->shared_dpll];
-}
-
-/* For ILK+ */
-void assert_shared_dpll(struct drm_i915_private *dev_priv,
-			struct intel_shared_dpll *pll,
-			bool state)
-{
-	bool cur_state;
-	struct intel_dpll_hw_state hw_state;
-
-	if (WARN(!pll, "asserting DPLL %s with no DPLL\n", onoff(state)))
-		return;
-
-	cur_state = pll->get_hw_state(dev_priv, pll, &hw_state);
-	I915_STATE_WARN(cur_state != state,
-	     "%s assertion failure (expected %s, current %s)\n",
-			pll->name, onoff(state), onoff(cur_state));
-}
 
 static void assert_fdi_tx(struct drm_i915_private *dev_priv,
 			  enum pipe pipe, bool state)
@@ -1217,7 +1167,7 @@ static void assert_fdi_tx(struct drm_i91
 	enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
 								      pipe);
 
-	if (HAS_DDI(dev_priv->dev)) {
+	if (HAS_DDI(dev_priv)) {
 		/* DDI does not have a specific FDI_TX register */
 		u32 val = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
 		cur_state = !!(val & TRANS_DDI_FUNC_ENABLE);
@@ -1253,11 +1203,11 @@ static void assert_fdi_tx_pll_enabled(st
 	u32 val;
 
 	/* ILK FDI PLL is always enabled */
-	if (INTEL_INFO(dev_priv->dev)->gen == 5)
+	if (INTEL_INFO(dev_priv)->gen == 5)
 		return;
 
 	/* On Haswell, DDI ports are responsible for the FDI PLL setup */
-	if (HAS_DDI(dev_priv->dev))
+	if (HAS_DDI(dev_priv))
 		return;
 
 	val = I915_READ(FDI_TX_CTL(pipe));
@@ -1446,21 +1396,8 @@ static void assert_vblank_disabled(struc
 		drm_crtc_vblank_put(crtc);
 }
 
-static void ibx_assert_pch_refclk_enabled(struct drm_i915_private *dev_priv)
-{
-	u32 val;
-	bool enabled;
-
-	I915_STATE_WARN_ON(!(HAS_PCH_IBX(dev_priv->dev) || HAS_PCH_CPT(dev_priv->dev)));
-
-	val = I915_READ(PCH_DREF_CONTROL);
-	enabled = !!(val & (DREF_SSC_SOURCE_MASK | DREF_NONSPREAD_SOURCE_MASK |
-			    DREF_SUPERSPREAD_SOURCE_MASK));
-	I915_STATE_WARN(!enabled, "PCH refclk assertion failure, should be active but is disabled\n");
-}
-
-static void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv,
-					   enum pipe pipe)
+void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv,
+				    enum pipe pipe)
 {
 	u32 val;
 	bool enabled;
@@ -1478,11 +1415,11 @@ static bool dp_pipe_enabled(struct drm_i
 	if ((val & DP_PORT_EN) == 0)
 		return false;
 
-	if (HAS_PCH_CPT(dev_priv->dev)) {
+	if (HAS_PCH_CPT(dev_priv)) {
 		u32 trans_dp_ctl = I915_READ(TRANS_DP_CTL(pipe));
 		if ((trans_dp_ctl & TRANS_DP_PORT_SEL_MASK) != port_sel)
 			return false;
-	} else if (IS_CHERRYVIEW(dev_priv->dev)) {
+	} else if (IS_CHERRYVIEW(dev_priv)) {
 		if ((val & DP_PIPE_MASK_CHV) != DP_PIPE_SELECT_CHV(pipe))
 			return false;
 	} else {
@@ -1498,10 +1435,10 @@ static bool hdmi_pipe_enabled(struct drm
 	if ((val & SDVO_ENABLE) == 0)
 		return false;
 
-	if (HAS_PCH_CPT(dev_priv->dev)) {
+	if (HAS_PCH_CPT(dev_priv)) {
 		if ((val & SDVO_PIPE_SEL_MASK_CPT) != SDVO_PIPE_SEL_CPT(pipe))
 			return false;
-	} else if (IS_CHERRYVIEW(dev_priv->dev)) {
+	} else if (IS_CHERRYVIEW(dev_priv)) {
 		if ((val & SDVO_PIPE_SEL_MASK_CHV) != SDVO_PIPE_SEL_CHV(pipe))
 			return false;
 	} else {
@@ -1517,7 +1454,7 @@ static bool lvds_pipe_enabled(struct drm
 	if ((val & LVDS_PORT_EN) == 0)
 		return false;
 
-	if (HAS_PCH_CPT(dev_priv->dev)) {
+	if (HAS_PCH_CPT(dev_priv)) {
 		if ((val & PORT_TRANS_SEL_MASK) != PORT_TRANS_SEL_CPT(pipe))
 			return false;
 	} else {
@@ -1532,7 +1469,7 @@ static bool adpa_pipe_enabled(struct drm
 {
 	if ((val & ADPA_DAC_ENABLE) == 0)
 		return false;
-	if (HAS_PCH_CPT(dev_priv->dev)) {
+	if (HAS_PCH_CPT(dev_priv)) {
 		if ((val & PORT_TRANS_SEL_MASK) != PORT_TRANS_SEL_CPT(pipe))
 			return false;
 	} else {
@@ -1551,7 +1488,7 @@ static void assert_pch_dp_disabled(struc
 	     "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n",
 	     i915_mmio_reg_offset(reg), pipe_name(pipe));
 
-	I915_STATE_WARN(HAS_PCH_IBX(dev_priv->dev) && (val & DP_PORT_EN) == 0
+	I915_STATE_WARN(HAS_PCH_IBX(dev_priv) && (val & DP_PORT_EN) == 0
 	     && (val & DP_PIPEB_SELECT),
 	     "IBX PCH dp port still using transcoder B\n");
 }
@@ -1564,7 +1501,7 @@ static void assert_pch_hdmi_disabled(str
 	     "PCH HDMI (0x%08x) enabled on transcoder %c, should be disabled\n",
 	     i915_mmio_reg_offset(reg), pipe_name(pipe));
 
-	I915_STATE_WARN(HAS_PCH_IBX(dev_priv->dev) && (val & SDVO_ENABLE) == 0
+	I915_STATE_WARN(HAS_PCH_IBX(dev_priv) && (val & SDVO_ENABLE) == 0
 	     && (val & SDVO_PIPE_B_SELECT),
 	     "IBX PCH hdmi port still using transcoder B\n");
 }
@@ -1593,53 +1530,47 @@ static void assert_pch_ports_disabled(st
 	assert_pch_hdmi_disabled(dev_priv, pipe, PCH_HDMID);
 }
 
+static void _vlv_enable_pll(struct intel_crtc *crtc,
+			    const struct intel_crtc_state *pipe_config)
+{
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+	enum pipe pipe = crtc->pipe;
+
+	I915_WRITE(DPLL(pipe), pipe_config->dpll_hw_state.dpll);
+	POSTING_READ(DPLL(pipe));
+	udelay(150);
+
+	if (wait_for(((I915_READ(DPLL(pipe)) & DPLL_LOCK_VLV) == DPLL_LOCK_VLV), 1))
+		DRM_ERROR("DPLL %d failed to lock\n", pipe);
+}
+
 static void vlv_enable_pll(struct intel_crtc *crtc,
 			   const struct intel_crtc_state *pipe_config)
 {
-	struct drm_device *dev = crtc->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	i915_reg_t reg = DPLL(crtc->pipe);
-	u32 dpll = pipe_config->dpll_hw_state.dpll;
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+	enum pipe pipe = crtc->pipe;
 
-	assert_pipe_disabled(dev_priv, crtc->pipe);
+	assert_pipe_disabled(dev_priv, pipe);
 
 	/* PLL is protected by panel, make sure we can write it */
-	if (IS_MOBILE(dev_priv->dev))
-		assert_panel_unlocked(dev_priv, crtc->pipe);
-
-	I915_WRITE(reg, dpll);
-	POSTING_READ(reg);
-	udelay(150);
-
-	if (wait_for(((I915_READ(reg) & DPLL_LOCK_VLV) == DPLL_LOCK_VLV), 1))
-		DRM_ERROR("DPLL %d failed to lock\n", crtc->pipe);
+	assert_panel_unlocked(dev_priv, pipe);
 
-	I915_WRITE(DPLL_MD(crtc->pipe), pipe_config->dpll_hw_state.dpll_md);
-	POSTING_READ(DPLL_MD(crtc->pipe));
+	if (pipe_config->dpll_hw_state.dpll & DPLL_VCO_ENABLE)
+		_vlv_enable_pll(crtc, pipe_config);
 
-	/* We do this three times for luck */
-	I915_WRITE(reg, dpll);
-	POSTING_READ(reg);
-	udelay(150); /* wait for warmup */
-	I915_WRITE(reg, dpll);
-	POSTING_READ(reg);
-	udelay(150); /* wait for warmup */
-	I915_WRITE(reg, dpll);
-	POSTING_READ(reg);
-	udelay(150); /* wait for warmup */
+	I915_WRITE(DPLL_MD(pipe), pipe_config->dpll_hw_state.dpll_md);
+	POSTING_READ(DPLL_MD(pipe));
 }
 
-static void chv_enable_pll(struct intel_crtc *crtc,
-			   const struct intel_crtc_state *pipe_config)
+
+static void _chv_enable_pll(struct intel_crtc *crtc,
+			    const struct intel_crtc_state *pipe_config)
 {
-	struct drm_device *dev = crtc->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	int pipe = crtc->pipe;
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+	enum pipe pipe = crtc->pipe;
 	enum dpio_channel port = vlv_pipe_to_channel(pipe);
 	u32 tmp;
 
-	assert_pipe_disabled(dev_priv, crtc->pipe);
-
 	mutex_lock(&dev_priv->sb_lock);
 
 	/* Enable back the 10bit clock to display controller */
@@ -1660,10 +1591,43 @@ static void chv_enable_pll(struct intel_
 	/* Check PLL is locked */
 	if (wait_for(((I915_READ(DPLL(pipe)) & DPLL_LOCK_VLV) == DPLL_LOCK_VLV), 1))
 		DRM_ERROR("PLL %d failed to lock\n", pipe);
+}
 
-	/* not sure when this should be written */
-	I915_WRITE(DPLL_MD(pipe), pipe_config->dpll_hw_state.dpll_md);
-	POSTING_READ(DPLL_MD(pipe));
+static void chv_enable_pll(struct intel_crtc *crtc,
+			   const struct intel_crtc_state *pipe_config)
+{
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+	enum pipe pipe = crtc->pipe;
+
+	assert_pipe_disabled(dev_priv, pipe);
+
+	/* PLL is protected by panel, make sure we can write it */
+	assert_panel_unlocked(dev_priv, pipe);
+
+	if (pipe_config->dpll_hw_state.dpll & DPLL_VCO_ENABLE)
+		_chv_enable_pll(crtc, pipe_config);
+
+	if (pipe != PIPE_A) {
+		/*
+		 * WaPixelRepeatModeFixForC0:chv
+		 *
+		 * DPLLCMD is AWOL. Use chicken bits to propagate
+		 * the value from DPLLBMD to either pipe B or C.
+		 */
+		I915_WRITE(CBR4_VLV, pipe == PIPE_B ? CBR_DPLLBMD_PIPE_B : CBR_DPLLBMD_PIPE_C);
+		I915_WRITE(DPLL_MD(PIPE_B), pipe_config->dpll_hw_state.dpll_md);
+		I915_WRITE(CBR4_VLV, 0);
+		dev_priv->chv_dpll_md[pipe] = pipe_config->dpll_hw_state.dpll_md;
+
+		/*
+		 * DPLLB VGA mode also seems to cause problems.
+		 * We should always have it disabled.
+		 */
+		WARN_ON((I915_READ(DPLL(PIPE_B)) & DPLL_VGA_MODE_DIS) == 0);
+	} else {
+		I915_WRITE(DPLL_MD(pipe), pipe_config->dpll_hw_state.dpll_md);
+		POSTING_READ(DPLL_MD(pipe));
+	}
 }
 
 static int intel_num_dvo_pipes(struct drm_device *dev)
@@ -1687,9 +1651,6 @@ static void i9xx_enable_pll(struct intel
 
 	assert_pipe_disabled(dev_priv, crtc->pipe);
 
-	/* No really, not for ILK+ */
-	BUG_ON(INTEL_INFO(dev)->gen >= 5);
-
 	/* PLL is protected by panel, make sure we can write it */
 	if (IS_MOBILE(dev) && !IS_I830(dev))
 		assert_panel_unlocked(dev_priv, crtc->pipe);
@@ -1788,16 +1749,13 @@ static void vlv_disable_pll(struct drm_i
 	/* Make sure the pipe isn't still relying on us */
 	assert_pipe_disabled(dev_priv, pipe);
 
-	/*
-	 * Leave integrated clock source and reference clock enabled for pipe B.
-	 * The latter is needed for VGA hotplug / manual detection.
-	 */
-	val = DPLL_VGA_MODE_DIS;
-	if (pipe == PIPE_B)
-		val = DPLL_INTEGRATED_CRI_CLK_VLV | DPLL_REF_CLK_ENABLE_VLV;
+	val = DPLL_INTEGRATED_REF_CLK_VLV |
+		DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS;
+	if (pipe != PIPE_A)
+		val |= DPLL_INTEGRATED_CRI_CLK_VLV;
+
 	I915_WRITE(DPLL(pipe), val);
 	POSTING_READ(DPLL(pipe));
-
 }
 
 static void chv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
@@ -1808,11 +1766,11 @@ static void chv_disable_pll(struct drm_i
 	/* Make sure the pipe isn't still relying on us */
 	assert_pipe_disabled(dev_priv, pipe);
 
-	/* Set PLL en = 0 */
 	val = DPLL_SSC_REF_CLK_CHV |
 		DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS;
 	if (pipe != PIPE_A)
 		val |= DPLL_INTEGRATED_CRI_CLK_VLV;
+
 	I915_WRITE(DPLL(pipe), val);
 	POSTING_READ(DPLL(pipe));
 
@@ -1856,100 +1814,6 @@ void vlv_wait_port_ready(struct drm_i915
 		     port_name(dport->port), I915_READ(dpll_reg) & port_mask, expected_mask);
 }
 
-static void intel_prepare_shared_dpll(struct intel_crtc *crtc)
-{
-	struct drm_device *dev = crtc->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc);
-
-	if (WARN_ON(pll == NULL))
-		return;
-
-	WARN_ON(!pll->config.crtc_mask);
-	if (pll->active == 0) {
-		DRM_DEBUG_DRIVER("setting up %s\n", pll->name);
-		WARN_ON(pll->on);
-		assert_shared_dpll_disabled(dev_priv, pll);
-
-		pll->mode_set(dev_priv, pll);
-	}
-}
-
-/**
- * intel_enable_shared_dpll - enable PCH PLL
- * @dev_priv: i915 private structure
- * @pipe: pipe PLL to enable
- *
- * The PCH PLL needs to be enabled before the PCH transcoder, since it
- * drives the transcoder clock.
- */
-static void intel_enable_shared_dpll(struct intel_crtc *crtc)
-{
-	struct drm_device *dev = crtc->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc);
-
-	if (WARN_ON(pll == NULL))
-		return;
-
-	if (WARN_ON(pll->config.crtc_mask == 0))
-		return;
-
-	DRM_DEBUG_KMS("enable %s (active %d, on? %d) for crtc %d\n",
-		      pll->name, pll->active, pll->on,
-		      crtc->base.base.id);
-
-	if (pll->active++) {
-		WARN_ON(!pll->on);
-		assert_shared_dpll_enabled(dev_priv, pll);
-		return;
-	}
-	WARN_ON(pll->on);
-
-	intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS);
-
-	DRM_DEBUG_KMS("enabling %s\n", pll->name);
-	pll->enable(dev_priv, pll);
-	pll->on = true;
-}
-
-static void intel_disable_shared_dpll(struct intel_crtc *crtc)
-{
-	struct drm_device *dev = crtc->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc);
-
-	/* PCH only available on ILK+ */
-	if (INTEL_INFO(dev)->gen < 5)
-		return;
-
-	if (pll == NULL)
-		return;
-
-	if (WARN_ON(!(pll->config.crtc_mask & (1 << drm_crtc_index(&crtc->base)))))
-		return;
-
-	DRM_DEBUG_KMS("disable %s (active %d, on? %d) for crtc %d\n",
-		      pll->name, pll->active, pll->on,
-		      crtc->base.base.id);
-
-	if (WARN_ON(pll->active == 0)) {
-		assert_shared_dpll_disabled(dev_priv, pll);
-		return;
-	}
-
-	assert_shared_dpll_enabled(dev_priv, pll);
-	WARN_ON(!pll->on);
-	if (--pll->active)
-		return;
-
-	DRM_DEBUG_KMS("disabling %s\n", pll->name);
-	pll->disable(dev_priv, pll);
-	pll->on = false;
-
-	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
-}
-
 static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv,
 					   enum pipe pipe)
 {
@@ -1959,12 +1823,8 @@ static void ironlake_enable_pch_transcod
 	i915_reg_t reg;
 	uint32_t val, pipeconf_val;
 
-	/* PCH only available on ILK+ */
-	BUG_ON(!HAS_PCH_SPLIT(dev));
-
 	/* Make sure PCH DPLL is enabled */
-	assert_shared_dpll_enabled(dev_priv,
-				   intel_crtc_to_shared_dpll(intel_crtc));
+	assert_shared_dpll_enabled(dev_priv, intel_crtc->config->shared_dpll);
 
 	/* FDI must be feeding us bits for PCH ports */
 	assert_fdi_tx_enabled(dev_priv, pipe);
@@ -1983,7 +1843,7 @@ static void ironlake_enable_pch_transcod
 	val = I915_READ(reg);
 	pipeconf_val = I915_READ(PIPECONF(pipe));
 
-	if (HAS_PCH_IBX(dev_priv->dev)) {
+	if (HAS_PCH_IBX(dev_priv)) {
 		/*
 		 * Make the BPC in transcoder be consistent with
 		 * that in pipeconf reg. For HDMI we must use 8bpc
@@ -1998,7 +1858,7 @@ static void ironlake_enable_pch_transcod
 
 	val &= ~TRANS_INTERLACE_MASK;
 	if ((pipeconf_val & PIPECONF_INTERLACE_MASK) == PIPECONF_INTERLACED_ILK)
-		if (HAS_PCH_IBX(dev_priv->dev) &&
+		if (HAS_PCH_IBX(dev_priv) &&
 		    intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_SDVO))
 			val |= TRANS_LEGACY_INTERLACED_ILK;
 		else
@@ -2016,9 +1876,6 @@ static void lpt_enable_pch_transcoder(st
 {
 	u32 val, pipeconf_val;
 
-	/* PCH only available on ILK+ */
-	BUG_ON(!HAS_PCH_SPLIT(dev_priv->dev));
-
 	/* FDI must be feeding us bits for PCH ports */
 	assert_fdi_tx_enabled(dev_priv, (enum pipe) cpu_transcoder);
 	assert_fdi_rx_enabled(dev_priv, TRANSCODER_A);
@@ -2113,7 +1970,7 @@ static void intel_enable_pipe(struct int
 	assert_cursor_disabled(dev_priv, pipe);
 	assert_sprites_disabled(dev_priv, pipe);
 
-	if (HAS_PCH_LPT(dev_priv->dev))
+	if (HAS_PCH_LPT(dev_priv))
 		pch_transcoder = TRANSCODER_A;
 	else
 		pch_transcoder = pipe;
@@ -2123,7 +1980,7 @@ static void intel_enable_pipe(struct int
 	 * a plane.  On ILK+ the pipe PLLs are integrated, so we don't
 	 * need the check.
 	 */
-	if (HAS_GMCH_DISPLAY(dev_priv->dev))
+	if (HAS_GMCH_DISPLAY(dev_priv))
 		if (crtc->config->has_dsi_encoder)
 			assert_dsi_pll_enabled(dev_priv);
 		else
@@ -2225,8 +2082,8 @@ static unsigned int intel_tile_size(cons
 	return IS_GEN2(dev_priv) ? 2048 : 4096;
 }
 
-static unsigned int intel_tile_width(const struct drm_i915_private *dev_priv,
-				     uint64_t fb_modifier, unsigned int cpp)
+static unsigned int intel_tile_width_bytes(const struct drm_i915_private *dev_priv,
+					   uint64_t fb_modifier, unsigned int cpp)
 {
 	switch (fb_modifier) {
 	case DRM_FORMAT_MOD_NONE:
@@ -2269,7 +2126,21 @@ unsigned int intel_tile_height(const str
 		return 1;
 	else
 		return intel_tile_size(dev_priv) /
-			intel_tile_width(dev_priv, fb_modifier, cpp);
+			intel_tile_width_bytes(dev_priv, fb_modifier, cpp);
+}
+
+/* Return the tile dimensions in pixel units */
+static void intel_tile_dims(const struct drm_i915_private *dev_priv,
+			    unsigned int *tile_width,
+			    unsigned int *tile_height,
+			    uint64_t fb_modifier,
+			    unsigned int cpp)
+{
+	unsigned int tile_width_bytes =
+		intel_tile_width_bytes(dev_priv, fb_modifier, cpp);
+
+	*tile_width = tile_width_bytes / cpp;
+	*tile_height = intel_tile_size(dev_priv) / tile_width_bytes;
 }
 
 unsigned int
@@ -2282,48 +2153,54 @@ intel_fb_align_height(struct drm_device
 	return ALIGN(height, tile_height);
 }
 
-static void
-intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
-			const struct drm_plane_state *plane_state)
+unsigned int intel_rotation_info_size(const struct intel_rotation_info *rot_info)
 {
-	struct drm_i915_private *dev_priv = to_i915(fb->dev);
-	struct intel_rotation_info *info = &view->params.rotated;
-	unsigned int tile_size, tile_width, tile_height, cpp;
-
-	*view = i915_ggtt_view_normal;
+	unsigned int size = 0;
+	int i;
 
-	if (!plane_state)
-		return;
+	for (i = 0 ; i < ARRAY_SIZE(rot_info->plane); i++)
+		size += rot_info->plane[i].width * rot_info->plane[i].height;
 
-	if (!intel_rotation_90_or_270(plane_state->rotation))
-		return;
+	return size;
+}
 
-	*view = i915_ggtt_view_rotated;
+static void
+intel_fill_fb_ggtt_view(struct i915_ggtt_view *view,
+			const struct drm_framebuffer *fb,
+			unsigned int rotation)
+{
+	if (intel_rotation_90_or_270(rotation)) {
+		*view = i915_ggtt_view_rotated;
+		view->params.rotated = to_intel_framebuffer(fb)->rot_info;
+	} else {
+		*view = i915_ggtt_view_normal;
+	}
+}
 
-	info->height = fb->height;
-	info->pixel_format = fb->pixel_format;
-	info->pitch = fb->pitches[0];
-	info->uv_offset = fb->offsets[1];
-	info->fb_modifier = fb->modifier[0];
+static void
+intel_fill_fb_info(struct drm_i915_private *dev_priv,
+		   struct drm_framebuffer *fb)
+{
+	struct intel_rotation_info *info = &to_intel_framebuffer(fb)->rot_info;
+	unsigned int tile_size, tile_width, tile_height, cpp;
 
 	tile_size = intel_tile_size(dev_priv);
 
 	cpp = drm_format_plane_cpp(fb->pixel_format, 0);
-	tile_width = intel_tile_width(dev_priv, fb->modifier[0], cpp);
-	tile_height = tile_size / tile_width;
+	intel_tile_dims(dev_priv, &tile_width, &tile_height,
+			fb->modifier[0], cpp);
 
-	info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_width);
-	info->height_pages = DIV_ROUND_UP(fb->height, tile_height);
-	info->size = info->width_pages * info->height_pages * tile_size;
+	info->plane[0].width = DIV_ROUND_UP(fb->pitches[0], tile_width * cpp);
+	info->plane[0].height = DIV_ROUND_UP(fb->height, tile_height);
 
 	if (info->pixel_format == DRM_FORMAT_NV12) {
 		cpp = drm_format_plane_cpp(fb->pixel_format, 1);
-		tile_width = intel_tile_width(dev_priv, fb->modifier[1], cpp);
-		tile_height = tile_size / tile_width;
+		intel_tile_dims(dev_priv, &tile_width, &tile_height,
+				fb->modifier[1], cpp);
 
-		info->width_pages_uv = DIV_ROUND_UP(fb->pitches[1], tile_width);
-		info->height_pages_uv = DIV_ROUND_UP(fb->height / 2, tile_height);
-		info->size_uv = info->width_pages_uv * info->height_pages_uv * tile_size;
+		info->uv_offset = fb->offsets[1];
+		info->plane[1].width = DIV_ROUND_UP(fb->pitches[1], tile_width * cpp);
+		info->plane[1].height = DIV_ROUND_UP(fb->height / 2, tile_height);
 	}
 }
 
@@ -2360,9 +2237,8 @@ static unsigned int intel_surf_alignment
 }
 
 int
-intel_pin_and_fence_fb_obj(struct drm_plane *plane,
-			   struct drm_framebuffer *fb,
-			   const struct drm_plane_state *plane_state)
+intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
+			   unsigned int rotation)
 {
 	struct drm_device *dev = fb->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -2375,7 +2251,7 @@ intel_pin_and_fence_fb_obj(struct drm_pl
 
 	alignment = intel_surf_alignment(dev_priv, fb->modifier[0]);
 
-	intel_fill_fb_ggtt_view(&view, fb, plane_state);
+	intel_fill_fb_ggtt_view(&view, fb, rotation);
 
 	/* Note that the w/a also requires 64 PTE of padding following the
 	 * bo. We currently fill all unused PTE with the shadow page and so
@@ -2433,15 +2309,14 @@ err_pm:
 	return ret;
 }
 
-static void intel_unpin_fb_obj(struct drm_framebuffer *fb,
-			       const struct drm_plane_state *plane_state)
+static void intel_unpin_fb_obj(struct drm_framebuffer *fb, unsigned int rotation)
 {
 	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
 	struct i915_ggtt_view view;
 
 	WARN_ON(!mutex_is_locked(&obj->base.dev->struct_mutex));
 
-	intel_fill_fb_ggtt_view(&view, fb, plane_state);
+	intel_fill_fb_ggtt_view(&view, fb, rotation);
 
 	if (view.type == I915_GGTT_VIEW_NORMAL)
 		i915_gem_object_unpin_fence(obj);
@@ -2449,38 +2324,93 @@ static void intel_unpin_fb_obj(struct dr
 	i915_gem_object_unpin_from_display_plane(obj, &view);
 }
 
-/* Computes the linear offset to the base tile and adjusts x, y. bytes per pixel
- * is assumed to be a power-of-two. */
-u32 intel_compute_tile_offset(struct drm_i915_private *dev_priv,
-			      int *x, int *y,
-			      uint64_t fb_modifier,
-			      unsigned int cpp,
-			      unsigned int pitch)
+/*
+ * Adjust the tile offset by moving the difference into
+ * the x/y offsets.
+ *
+ * Input tile dimensions and pitch must already be
+ * rotated to match x and y, and in pixel units.
+ */
+static u32 intel_adjust_tile_offset(int *x, int *y,
+				    unsigned int tile_width,
+				    unsigned int tile_height,
+				    unsigned int tile_size,
+				    unsigned int pitch_tiles,
+				    u32 old_offset,
+				    u32 new_offset)
+{
+	unsigned int tiles;
+
+	WARN_ON(old_offset & (tile_size - 1));
+	WARN_ON(new_offset & (tile_size - 1));
+	WARN_ON(new_offset > old_offset);
+
+	tiles = (old_offset - new_offset) / tile_size;
+
+	*y += tiles / pitch_tiles * tile_height;
+	*x += tiles % pitch_tiles * tile_width;
+
+	return new_offset;
+}
+
+/*
+ * Computes the linear offset to the base tile and adjusts
+ * x, y. bytes per pixel is assumed to be a power-of-two.
+ *
+ * In the 90/270 rotated case, x and y are assumed
+ * to be already rotated to match the rotated GTT view, and
+ * pitch is the tile_height aligned framebuffer height.
+ */
+u32 intel_compute_tile_offset(int *x, int *y,
+			      const struct drm_framebuffer *fb, int plane,
+			      unsigned int pitch,
+			      unsigned int rotation)
 {
+	const struct drm_i915_private *dev_priv = to_i915(fb->dev);
+	uint64_t fb_modifier = fb->modifier[plane];
+	unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, plane);
+	u32 offset, offset_aligned, alignment;
+
+	alignment = intel_surf_alignment(dev_priv, fb_modifier);
+	if (alignment)
+		alignment--;
+
 	if (fb_modifier != DRM_FORMAT_MOD_NONE) {
 		unsigned int tile_size, tile_width, tile_height;
-		unsigned int tile_rows, tiles;
+		unsigned int tile_rows, tiles, pitch_tiles;
 
 		tile_size = intel_tile_size(dev_priv);
-		tile_width = intel_tile_width(dev_priv, fb_modifier, cpp);
-		tile_height = tile_size / tile_width;
+		intel_tile_dims(dev_priv, &tile_width, &tile_height,
+				fb_modifier, cpp);
+
+		if (intel_rotation_90_or_270(rotation)) {
+			pitch_tiles = pitch / tile_height;
+			swap(tile_width, tile_height);
+		} else {
+			pitch_tiles = pitch / (tile_width * cpp);
+		}
 
 		tile_rows = *y / tile_height;
 		*y %= tile_height;
 
-		tiles = *x / (tile_width/cpp);
-		*x %= tile_width/cpp;
+		tiles = *x / tile_width;
+		*x %= tile_width;
 
-		return tile_rows * pitch * tile_height + tiles * tile_size;
-	} else {
-		unsigned int alignment = intel_linear_alignment(dev_priv) - 1;
-		unsigned int offset;
+		offset = (tile_rows * pitch_tiles + tiles) * tile_size;
+		offset_aligned = offset & ~alignment;
 
+		intel_adjust_tile_offset(x, y, tile_width, tile_height,
+					 tile_size, pitch_tiles,
+					 offset, offset_aligned);
+	} else {
 		offset = *y * pitch + *x * cpp;
+		offset_aligned = offset & ~alignment;
+
 		*y = (offset & alignment) / pitch;
 		*x = ((offset & alignment) - *y * pitch) / cpp;
-		return offset & ~alignment;
 	}
+
+	return offset_aligned;
 }
 
 static int i9xx_format_to_fourcc(int format)
@@ -2536,6 +2466,7 @@ intel_alloc_initial_plane_obj(struct int
 {
 	struct drm_device *dev = crtc->base.dev;
 	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	struct drm_i915_gem_object *obj = NULL;
 	struct drm_mode_fb_cmd2 mode_cmd = { 0 };
 	struct drm_framebuffer *fb = &plane_config->fb->base;
@@ -2551,7 +2482,7 @@ intel_alloc_initial_plane_obj(struct int
 	/* If the FB is too big, just don't use it since fbdev is not very
 	 * important and we should probably use that space with FBC or other
 	 * features. */
-	if (size_aligned * 2 > dev_priv->gtt.stolen_usable_size)
+	if (size_aligned * 2 > ggtt->stolen_usable_size)
 		return false;
 
 	mutex_lock(&dev->struct_mutex);
@@ -2667,7 +2598,7 @@ intel_find_initial_plane_obj(struct inte
 	 */
 	to_intel_plane_state(plane_state)->visible = false;
 	crtc_state->plane_mask &= ~(1 << drm_plane_index(primary));
-	intel_pre_disable_primary(&intel_crtc->base);
+	intel_pre_disable_primary_noatomic(&intel_crtc->base);
 	intel_plane->disable_plane(primary, &intel_crtc->base);
 
 	return;
@@ -2716,6 +2647,7 @@ static void i9xx_update_primary_plane(st
 	u32 linear_offset;
 	u32 dspcntr;
 	i915_reg_t reg = DSPCNTR(plane);
+	unsigned int rotation = plane_state->base.rotation;
 	int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
 	int x = plane_state->src.x1 >> 16;
 	int y = plane_state->src.y1 >> 16;
@@ -2780,15 +2712,14 @@ static void i9xx_update_primary_plane(st
 
 	if (INTEL_INFO(dev)->gen >= 4) {
 		intel_crtc->dspaddr_offset =
-			intel_compute_tile_offset(dev_priv, &x, &y,
-						  fb->modifier[0], cpp,
-						  fb->pitches[0]);
+			intel_compute_tile_offset(&x, &y, fb, 0,
+						  fb->pitches[0], rotation);
 		linear_offset -= intel_crtc->dspaddr_offset;
 	} else {
 		intel_crtc->dspaddr_offset = linear_offset;
 	}
 
-	if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) {
+	if (rotation == BIT(DRM_ROTATE_180)) {
 		dspcntr |= DISPPLANE_ROTATE_180;
 
 		x += (crtc_state->pipe_src_w - 1);
@@ -2846,6 +2777,7 @@ static void ironlake_update_primary_plan
 	u32 linear_offset;
 	u32 dspcntr;
 	i915_reg_t reg = DSPCNTR(plane);
+	unsigned int rotation = plane_state->base.rotation;
 	int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
 	int x = plane_state->src.x1 >> 16;
 	int y = plane_state->src.y1 >> 16;
@@ -2887,11 +2819,10 @@ static void ironlake_update_primary_plan
 
 	linear_offset = y * fb->pitches[0] + x * cpp;
 	intel_crtc->dspaddr_offset =
-		intel_compute_tile_offset(dev_priv, &x, &y,
-					  fb->modifier[0], cpp,
-					  fb->pitches[0]);
+		intel_compute_tile_offset(&x, &y, fb, 0,
+					  fb->pitches[0], rotation);
 	linear_offset -= intel_crtc->dspaddr_offset;
-	if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) {
+	if (rotation == BIT(DRM_ROTATE_180)) {
 		dspcntr |= DISPPLANE_ROTATE_180;
 
 		if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) {
@@ -2931,7 +2862,7 @@ u32 intel_fb_stride_alignment(const stru
 	} else {
 		int cpp = drm_format_plane_cpp(pixel_format, 0);
 
-		return intel_tile_width(dev_priv, fb_modifier, cpp);
+		return intel_tile_width_bytes(dev_priv, fb_modifier, cpp);
 	}
 }
 
@@ -2944,7 +2875,7 @@ u32 intel_plane_obj_offset(struct intel_
 	u64 offset;
 
 	intel_fill_fb_ggtt_view(&view, intel_plane->base.state->fb,
-				intel_plane->base.state);
+				intel_plane->base.state->rotation);
 
 	vma = i915_gem_obj_to_ggtt_view(obj, &view);
 	if (WARN(!vma, "ggtt vma for display object not found! (view=%u)\n",
@@ -3284,12 +3215,12 @@ void intel_finish_reset(struct drm_devic
 static bool intel_crtc_has_pending_flip(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	unsigned reset_counter;
 	bool pending;
 
-	if (i915_reset_in_progress(&dev_priv->gpu_error) ||
-	    intel_crtc->reset_counter != atomic_read(&dev_priv->gpu_error.reset_counter))
+	reset_counter = i915_reset_counter(&to_i915(dev)->gpu_error);
+	if (intel_crtc->reset_counter != reset_counter)
 		return false;
 
 	spin_lock_irq(&dev->event_lock);
@@ -3314,9 +3245,6 @@ static void intel_update_pipe_config(str
 		      old_crtc_state->pipe_src_w, old_crtc_state->pipe_src_h,
 		      pipe_config->pipe_src_w, pipe_config->pipe_src_h);
 
-	if (HAS_DDI(dev))
-		intel_set_pipe_csc(&crtc->base);
-
 	/*
 	 * Update pipe size and adjust fitter if needed: the reason for this is
 	 * that in compute_mode_changes we check the native mode (not the pfit
@@ -3894,9 +3822,7 @@ static void page_flip_completed(struct i
 	intel_crtc->unpin_work = NULL;
 
 	if (work->event)
-		drm_send_vblank_event(intel_crtc->base.dev,
-				      intel_crtc->pipe,
-				      work->event);
+		drm_crtc_send_vblank_event(&intel_crtc->base, work->event);
 
 	drm_crtc_vblank_put(&intel_crtc->base);
 
@@ -3955,37 +3881,35 @@ static void lpt_disable_iclkip(struct dr
 /* Program iCLKIP clock to the desired frequency */
 static void lpt_program_iclkip(struct drm_crtc *crtc)
 {
-	struct drm_device *dev = crtc->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
 	int clock = to_intel_crtc(crtc)->config->base.adjusted_mode.crtc_clock;
 	u32 divsel, phaseinc, auxdiv, phasedir = 0;
 	u32 temp;
 
 	lpt_disable_iclkip(dev_priv);
 
-	/* 20MHz is a corner case which is out of range for the 7-bit divisor */
-	if (clock == 20000) {
-		auxdiv = 1;
-		divsel = 0x41;
-		phaseinc = 0x20;
-	} else {
-		/* The iCLK virtual clock root frequency is in MHz,
-		 * but the adjusted_mode->crtc_clock in in KHz. To get the
-		 * divisors, it is necessary to divide one by another, so we
-		 * convert the virtual clock precision to KHz here for higher
-		 * precision.
-		 */
+	/* The iCLK virtual clock root frequency is in MHz,
+	 * but the adjusted_mode->crtc_clock in in KHz. To get the
+	 * divisors, it is necessary to divide one by another, so we
+	 * convert the virtual clock precision to KHz here for higher
+	 * precision.
+	 */
+	for (auxdiv = 0; auxdiv < 2; auxdiv++) {
 		u32 iclk_virtual_root_freq = 172800 * 1000;
 		u32 iclk_pi_range = 64;
-		u32 desired_divisor, msb_divisor_value, pi_value;
+		u32 desired_divisor;
 
-		desired_divisor = DIV_ROUND_CLOSEST(iclk_virtual_root_freq, clock);
-		msb_divisor_value = desired_divisor / iclk_pi_range;
-		pi_value = desired_divisor % iclk_pi_range;
+		desired_divisor = DIV_ROUND_CLOSEST(iclk_virtual_root_freq,
+						    clock << auxdiv);
+		divsel = (desired_divisor / iclk_pi_range) - 2;
+		phaseinc = desired_divisor % iclk_pi_range;
 
-		auxdiv = 0;
-		divsel = msb_divisor_value - 2;
-		phaseinc = pi_value;
+		/*
+		 * Near 20MHz is a corner case which is
+		 * out of range for the 7-bit divisor
+		 */
+		if (divsel <= 0x7f)
+			break;
 	}
 
 	/* This should not happen with any sane values */
@@ -4032,6 +3956,43 @@ static void lpt_program_iclkip(struct dr
 	I915_WRITE(PIXCLK_GATE, PIXCLK_GATE_UNGATE);
 }
 
+int lpt_get_iclkip(struct drm_i915_private *dev_priv)
+{
+	u32 divsel, phaseinc, auxdiv;
+	u32 iclk_virtual_root_freq = 172800 * 1000;
+	u32 iclk_pi_range = 64;
+	u32 desired_divisor;
+	u32 temp;
+
+	if ((I915_READ(PIXCLK_GATE) & PIXCLK_GATE_UNGATE) == 0)
+		return 0;
+
+	mutex_lock(&dev_priv->sb_lock);
+
+	temp = intel_sbi_read(dev_priv, SBI_SSCCTL6, SBI_ICLK);
+	if (temp & SBI_SSCCTL_DISABLE) {
+		mutex_unlock(&dev_priv->sb_lock);
+		return 0;
+	}
+
+	temp = intel_sbi_read(dev_priv, SBI_SSCDIVINTPHASE6, SBI_ICLK);
+	divsel = (temp & SBI_SSCDIVINTPHASE_DIVSEL_MASK) >>
+		SBI_SSCDIVINTPHASE_DIVSEL_SHIFT;
+	phaseinc = (temp & SBI_SSCDIVINTPHASE_INCVAL_MASK) >>
+		SBI_SSCDIVINTPHASE_INCVAL_SHIFT;
+
+	temp = intel_sbi_read(dev_priv, SBI_SSCAUXDIV6, SBI_ICLK);
+	auxdiv = (temp & SBI_SSCAUXDIV_FINALDIV2SEL_MASK) >>
+		SBI_SSCAUXDIV_FINALDIV2SEL_SHIFT;
+
+	mutex_unlock(&dev_priv->sb_lock);
+
+	desired_divisor = (divsel + 2) * iclk_pi_range + phaseinc;
+
+	return DIV_ROUND_CLOSEST(iclk_virtual_root_freq,
+				 desired_divisor << auxdiv);
+}
+
 static void ironlake_pch_transcoder_set_timings(struct intel_crtc *crtc,
 						enum pipe pch_transcoder)
 {
@@ -4142,12 +4103,6 @@ static void ironlake_pch_enable(struct d
 	I915_WRITE(FDI_RX_TUSIZE1(pipe),
 		   I915_READ(PIPE_DATA_M1(pipe)) & TU_SIZE_MASK);
 
-	/*
-	 * Sometimes spurious CPU pipe underruns happen during FDI
-	 * training, at least with VGA+HDMI cloning. Suppress them.
-	 */
-	intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
-
 	/* For PCH output, training FDI link */
 	dev_priv->display.fdi_link_train(crtc);
 
@@ -4159,7 +4114,8 @@ static void ironlake_pch_enable(struct d
 		temp = I915_READ(PCH_DPLL_SEL);
 		temp |= TRANS_DPLL_ENABLE(pipe);
 		sel = TRANS_DPLLB_SEL(pipe);
-		if (intel_crtc->config->shared_dpll == DPLL_ID_PCH_PLL_B)
+		if (intel_crtc->config->shared_dpll ==
+		    intel_get_shared_dpll_by_id(dev_priv, DPLL_ID_PCH_PLL_B))
 			temp |= sel;
 		else
 			temp &= ~sel;
@@ -4181,8 +4137,6 @@ static void ironlake_pch_enable(struct d
 
 	intel_fdi_normal_train(crtc);
 
-	intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
-
 	/* For PCH DP, enable TRANS_DP_CTL */
 	if (HAS_PCH_CPT(dev) && intel_crtc->config->has_dp_encoder) {
 		const struct drm_display_mode *adjusted_mode =
@@ -4238,113 +4192,6 @@ static void lpt_pch_enable(struct drm_cr
 	lpt_enable_pch_transcoder(dev_priv, cpu_transcoder);
 }
 
-struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc,
-						struct intel_crtc_state *crtc_state)
-{
-	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
-	struct intel_shared_dpll *pll;
-	struct intel_shared_dpll_config *shared_dpll;
-	enum intel_dpll_id i;
-	int max = dev_priv->num_shared_dpll;
-
-	shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state);
-
-	if (HAS_PCH_IBX(dev_priv->dev)) {
-		/* Ironlake PCH has a fixed PLL->PCH pipe mapping. */
-		i = (enum intel_dpll_id) crtc->pipe;
-		pll = &dev_priv->shared_dplls[i];
-
-		DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n",
-			      crtc->base.base.id, pll->name);
-
-		WARN_ON(shared_dpll[i].crtc_mask);
-
-		goto found;
-	}
-
-	if (IS_BROXTON(dev_priv->dev)) {
-		/* PLL is attached to port in bxt */
-		struct intel_encoder *encoder;
-		struct intel_digital_port *intel_dig_port;
-
-		encoder = intel_ddi_get_crtc_new_encoder(crtc_state);
-		if (WARN_ON(!encoder))
-			return NULL;
-
-		intel_dig_port = enc_to_dig_port(&encoder->base);
-		/* 1:1 mapping between ports and PLLs */
-		i = (enum intel_dpll_id)intel_dig_port->port;
-		pll = &dev_priv->shared_dplls[i];
-		DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n",
-			crtc->base.base.id, pll->name);
-		WARN_ON(shared_dpll[i].crtc_mask);
-
-		goto found;
-	} else if (INTEL_INFO(dev_priv)->gen < 9 && HAS_DDI(dev_priv))
-		/* Do not consider SPLL */
-		max = 2;
-
-	for (i = 0; i < max; i++) {
-		pll = &dev_priv->shared_dplls[i];
-
-		/* Only want to check enabled timings first */
-		if (shared_dpll[i].crtc_mask == 0)
-			continue;
-
-		if (memcmp(&crtc_state->dpll_hw_state,
-			   &shared_dpll[i].hw_state,
-			   sizeof(crtc_state->dpll_hw_state)) == 0) {
-			DRM_DEBUG_KMS("CRTC:%d sharing existing %s (crtc mask 0x%08x, ative %d)\n",
-				      crtc->base.base.id, pll->name,
-				      shared_dpll[i].crtc_mask,
-				      pll->active);
-			goto found;
-		}
-	}
-
-	/* Ok no matching timings, maybe there's a free one? */
-	for (i = 0; i < dev_priv->num_shared_dpll; i++) {
-		pll = &dev_priv->shared_dplls[i];
-		if (shared_dpll[i].crtc_mask == 0) {
-			DRM_DEBUG_KMS("CRTC:%d allocated %s\n",
-				      crtc->base.base.id, pll->name);
-			goto found;
-		}
-	}
-
-	return NULL;
-
-found:
-	if (shared_dpll[i].crtc_mask == 0)
-		shared_dpll[i].hw_state =
-			crtc_state->dpll_hw_state;
-
-	crtc_state->shared_dpll = i;
-	DRM_DEBUG_DRIVER("using %s for pipe %c\n", pll->name,
-			 pipe_name(crtc->pipe));
-
-	shared_dpll[i].crtc_mask |= 1 << crtc->pipe;
-
-	return pll;
-}
-
-static void intel_shared_dpll_commit(struct drm_atomic_state *state)
-{
-	struct drm_i915_private *dev_priv = to_i915(state->dev);
-	struct intel_shared_dpll_config *shared_dpll;
-	struct intel_shared_dpll *pll;
-	enum intel_dpll_id i;
-
-	if (!to_intel_atomic_state(state)->dpll_set)
-		return;
-
-	shared_dpll = to_intel_atomic_state(state)->shared_dpll;
-	for (i = 0; i < dev_priv->num_shared_dpll; i++) {
-		pll = &dev_priv->shared_dplls[i];
-		pll->config = shared_dpll[i];
-	}
-}
-
 static void cpt_verify_modeset(struct drm_device *dev, int pipe)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -4576,8 +4423,11 @@ void hsw_enable_ips(struct intel_crtc *c
 	if (!crtc->config->ips_enabled)
 		return;
 
-	/* We can only enable IPS after we enable a plane and wait for a vblank */
-	intel_wait_for_vblank(dev, crtc->pipe);
+	/*
+	 * We can only enable IPS after we enable a plane and wait for a vblank
+	 * This function is called from post_plane_update, which is run after
+	 * a vblank wait.
+	 */
 
 	assert_plane_enabled(dev_priv, crtc->plane);
 	if (IS_BROADWELL(dev)) {
@@ -4626,55 +4476,6 @@ void hsw_disable_ips(struct intel_crtc *
 	intel_wait_for_vblank(dev, crtc->pipe);
 }
 
-/** Loads the palette/gamma unit for the CRTC with the prepared values */
-static void intel_crtc_load_lut(struct drm_crtc *crtc)
-{
-	struct drm_device *dev = crtc->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	enum pipe pipe = intel_crtc->pipe;
-	int i;
-	bool reenable_ips = false;
-
-	/* The clocks have to be on to load the palette. */
-	if (!crtc->state->active)
-		return;
-
-	if (HAS_GMCH_DISPLAY(dev_priv->dev)) {
-		if (intel_crtc->config->has_dsi_encoder)
-			assert_dsi_pll_enabled(dev_priv);
-		else
-			assert_pll_enabled(dev_priv, pipe);
-	}
-
-	/* Workaround : Do not read or write the pipe palette/gamma data while
-	 * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled.
-	 */
-	if (IS_HASWELL(dev) && intel_crtc->config->ips_enabled &&
-	    ((I915_READ(GAMMA_MODE(pipe)) & GAMMA_MODE_MODE_MASK) ==
-	     GAMMA_MODE_MODE_SPLIT)) {
-		hsw_disable_ips(intel_crtc);
-		reenable_ips = true;
-	}
-
-	for (i = 0; i < 256; i++) {
-		i915_reg_t palreg;
-
-		if (HAS_GMCH_DISPLAY(dev))
-			palreg = PALETTE(pipe, i);
-		else
-			palreg = LGC_PALETTE(pipe, i);
-
-		I915_WRITE(palreg,
-			   (intel_crtc->lut_r[i] << 16) |
-			   (intel_crtc->lut_g[i] << 8) |
-			   intel_crtc->lut_b[i]);
-	}
-
-	if (reenable_ips)
-		hsw_enable_ips(intel_crtc);
-}
-
 static void intel_crtc_dpms_overlay_disable(struct intel_crtc *intel_crtc)
 {
 	if (intel_crtc->overlay) {
@@ -4734,16 +4535,7 @@ intel_post_enable_primary(struct drm_crt
 	intel_check_pch_fifo_underruns(dev_priv);
 }
 
-/**
- * intel_pre_disable_primary - Perform operations before disabling primary plane
- * @crtc: the CRTC whose primary plane is to be disabled
- *
- * Performs potentially sleeping operations that must be done before the
- * primary plane is disabled, such as updating FBC and IPS.  Note that this may
- * be called due to an explicit primary plane update, or due to an implicit
- * disable that is caused when a sprite plane completely hides the primary
- * plane.
- */
+/* FIXME move all this to pre_plane_update() with proper state tracking */
 static void
 intel_pre_disable_primary(struct drm_crtc *crtc)
 {
@@ -4762,6 +4554,26 @@ intel_pre_disable_primary(struct drm_crt
 		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
 
 	/*
+	 * FIXME IPS should be fine as long as one plane is
+	 * enabled, but in practice it seems to have problems
+	 * when going from primary only to sprite only and vice
+	 * versa.
+	 */
+	hsw_disable_ips(intel_crtc);
+}
+
+/* FIXME get rid of this and use pre_plane_update */
+static void
+intel_pre_disable_primary_noatomic(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	int pipe = intel_crtc->pipe;
+
+	intel_pre_disable_primary(crtc);
+
+	/*
 	 * Vblank time updates from the shadow to live plane control register
 	 * are blocked if the memory self-refresh mode is active at that
 	 * moment. So to make sure the plane gets truly disabled, disable
@@ -4775,37 +4587,39 @@ intel_pre_disable_primary(struct drm_crt
 		dev_priv->wm.vlv.cxsr = false;
 		intel_wait_for_vblank(dev, pipe);
 	}
-
-	/*
-	 * FIXME IPS should be fine as long as one plane is
-	 * enabled, but in practice it seems to have problems
-	 * when going from primary only to sprite only and vice
-	 * versa.
-	 */
-	hsw_disable_ips(intel_crtc);
 }
 
-static void intel_post_plane_update(struct intel_crtc *crtc)
+static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state)
 {
-	struct intel_crtc_atomic_commit *atomic = &crtc->atomic;
+	struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc);
+	struct drm_atomic_state *old_state = old_crtc_state->base.state;
 	struct intel_crtc_state *pipe_config =
 		to_intel_crtc_state(crtc->base.state);
 	struct drm_device *dev = crtc->base.dev;
+	struct drm_plane *primary = crtc->base.primary;
+	struct drm_plane_state *old_pri_state =
+		drm_atomic_get_existing_plane_state(old_state, primary);
 
-	intel_frontbuffer_flip(dev, atomic->fb_bits);
+	intel_frontbuffer_flip(dev, pipe_config->fb_bits);
 
 	crtc->wm.cxsr_allowed = true;
 
-	if (pipe_config->wm_changed && pipe_config->base.active)
+	if (pipe_config->update_wm_post && pipe_config->base.active)
 		intel_update_watermarks(&crtc->base);
 
-	if (atomic->update_fbc)
-		intel_fbc_post_update(crtc);
+	if (old_pri_state) {
+		struct intel_plane_state *primary_state =
+			to_intel_plane_state(primary->state);
+		struct intel_plane_state *old_primary_state =
+			to_intel_plane_state(old_pri_state);
 
-	if (atomic->post_enable_primary)
-		intel_post_enable_primary(&crtc->base);
+		intel_fbc_post_update(crtc);
 
-	memset(atomic, 0, sizeof(*atomic));
+		if (primary_state->visible &&
+		    (needs_modeset(&pipe_config->base) ||
+		     !old_primary_state->visible))
+			intel_post_enable_primary(&crtc->base);
+	}
 }
 
 static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state)
@@ -4813,7 +4627,6 @@ static void intel_pre_plane_update(struc
 	struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc);
 	struct drm_device *dev = crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_crtc_atomic_commit *atomic = &crtc->atomic;
 	struct intel_crtc_state *pipe_config =
 		to_intel_crtc_state(crtc->base.state);
 	struct drm_atomic_state *old_state = old_crtc_state->base.state;
@@ -4822,15 +4635,14 @@ static void intel_pre_plane_update(struc
 		drm_atomic_get_existing_plane_state(old_state, primary);
 	bool modeset = needs_modeset(&pipe_config->base);
 
-	if (atomic->update_fbc)
-		intel_fbc_pre_update(crtc);
-
 	if (old_pri_state) {
 		struct intel_plane_state *primary_state =
 			to_intel_plane_state(primary->state);
 		struct intel_plane_state *old_primary_state =
 			to_intel_plane_state(old_pri_state);
 
+		intel_fbc_pre_update(crtc);
+
 		if (old_primary_state->visible &&
 		    (modeset || !primary_state->visible))
 			intel_pre_disable_primary(&crtc->base);
@@ -4839,11 +4651,58 @@ static void intel_pre_plane_update(struc
 	if (pipe_config->disable_cxsr) {
 		crtc->wm.cxsr_allowed = false;
 
-		if (old_crtc_state->base.active)
+		/*
+		 * Vblank time updates from the shadow to live plane control register
+		 * are blocked if the memory self-refresh mode is active at that
+		 * moment. So to make sure the plane gets truly disabled, disable
+		 * first the self-refresh mode. The self-refresh enable bit in turn
+		 * will be checked/applied by the HW only at the next frame start
+		 * event which is after the vblank start event, so we need to have a
+		 * wait-for-vblank between disabling the plane and the pipe.
+		 */
+		if (old_crtc_state->base.active) {
 			intel_set_memory_cxsr(dev_priv, false);
+			dev_priv->wm.vlv.cxsr = false;
+			intel_wait_for_vblank(dev, crtc->pipe);
+		}
 	}
 
-	if (!needs_modeset(&pipe_config->base) && pipe_config->wm_changed)
+	/*
+	 * IVB workaround: must disable low power watermarks for at least
+	 * one frame before enabling scaling.  LP watermarks can be re-enabled
+	 * when scaling is disabled.
+	 *
+	 * WaCxSRDisabledForSpriteScaling:ivb
+	 */
+	if (pipe_config->disable_lp_wm) {
+		ilk_disable_lp_wm(dev);
+		intel_wait_for_vblank(dev, crtc->pipe);
+	}
+
+	/*
+	 * If we're doing a modeset, we're done.  No need to do any pre-vblank
+	 * watermark programming here.
+	 */
+	if (needs_modeset(&pipe_config->base))
+		return;
+
+	/*
+	 * For platforms that support atomic watermarks, program the
+	 * 'intermediate' watermarks immediately.  On pre-gen9 platforms, these
+	 * will be the intermediate values that are safe for both pre- and
+	 * post- vblank; when vblank happens, the 'active' values will be set
+	 * to the final 'target' values and we'll do this again to get the
+	 * optimal watermarks.  For gen9+ platforms, the values we program here
+	 * will be the final target values which will get automatically latched
+	 * at vblank time; no further programming will be necessary.
+	 *
+	 * If a platform hasn't been transitioned to atomic watermarks yet,
+	 * we'll continue to update watermarks the old way, if flags tell
+	 * us to.
+	 */
+	if (dev_priv->display.initial_watermarks != NULL)
+		dev_priv->display.initial_watermarks(pipe_config);
+	else if (pipe_config->update_wm_pre)
 		intel_update_watermarks(&crtc->base);
 }
 
@@ -4874,10 +4733,24 @@ static void ironlake_crtc_enable(struct
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct intel_encoder *encoder;
 	int pipe = intel_crtc->pipe;
+	struct intel_crtc_state *pipe_config =
+		to_intel_crtc_state(crtc->state);
 
 	if (WARN_ON(intel_crtc->active))
 		return;
 
+	/*
+	 * Sometimes spurious CPU pipe underruns happen during FDI
+	 * training, at least with VGA+HDMI cloning. Suppress them.
+	 *
+	 * On ILK we get an occasional spurious CPU pipe underruns
+	 * between eDP port A enable and vdd enable. Also PCH port
+	 * enable seems to result in the occasional CPU pipe underrun.
+	 *
+	 * Spurious PCH underruns also occur during PCH enabling.
+	 */
+	if (intel_crtc->config->has_pch_encoder || IS_GEN5(dev_priv))
+		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
 	if (intel_crtc->config->has_pch_encoder)
 		intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, false);
 
@@ -4888,6 +4761,7 @@ static void ironlake_crtc_enable(struct
 		intel_dp_set_m_n(intel_crtc, M1_N1);
 
 	intel_set_pipe_timings(intel_crtc);
+	intel_set_pipe_src_size(intel_crtc);
 
 	if (intel_crtc->config->has_pch_encoder) {
 		intel_cpu_transcoder_set_m_n(intel_crtc,
@@ -4898,8 +4772,6 @@ static void ironlake_crtc_enable(struct
 
 	intel_crtc->active = true;
 
-	intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
-
 	for_each_encoder_on_crtc(dev, crtc, encoder)
 		if (encoder->pre_enable)
 			encoder->pre_enable(encoder);
@@ -4920,9 +4792,10 @@ static void ironlake_crtc_enable(struct
 	 * On ILK+ LUT must be loaded before the pipe is running but with
 	 * clocks enabled
 	 */
-	intel_crtc_load_lut(crtc);
+	intel_color_load_luts(&pipe_config->base);
 
-	intel_update_watermarks(crtc);
+	if (dev_priv->display.initial_watermarks != NULL)
+		dev_priv->display.initial_watermarks(intel_crtc->config);
 	intel_enable_pipe(intel_crtc);
 
 	if (intel_crtc->config->has_pch_encoder)
@@ -4940,6 +4813,7 @@ static void ironlake_crtc_enable(struct
 	/* Must wait for vblank to avoid spurious PCH FIFO underruns */
 	if (intel_crtc->config->has_pch_encoder)
 		intel_wait_for_vblank(dev, pipe);
+	intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
 	intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, true);
 }
 
@@ -4956,6 +4830,7 @@ static void haswell_crtc_enable(struct d
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct intel_encoder *encoder;
 	int pipe = intel_crtc->pipe, hsw_workaround_pipe;
+	enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
 	struct intel_crtc_state *pipe_config =
 		to_intel_crtc_state(crtc->state);
 
@@ -4966,16 +4841,20 @@ static void haswell_crtc_enable(struct d
 		intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
 						      false);
 
-	if (intel_crtc_to_shared_dpll(intel_crtc))
+	if (intel_crtc->config->shared_dpll)
 		intel_enable_shared_dpll(intel_crtc);
 
 	if (intel_crtc->config->has_dp_encoder)
 		intel_dp_set_m_n(intel_crtc, M1_N1);
 
-	intel_set_pipe_timings(intel_crtc);
+	if (!intel_crtc->config->has_dsi_encoder)
+		intel_set_pipe_timings(intel_crtc);
 
-	if (intel_crtc->config->cpu_transcoder != TRANSCODER_EDP) {
-		I915_WRITE(PIPE_MULT(intel_crtc->config->cpu_transcoder),
+	intel_set_pipe_src_size(intel_crtc);
+
+	if (cpu_transcoder != TRANSCODER_EDP &&
+	    !transcoder_is_dsi(cpu_transcoder)) {
+		I915_WRITE(PIPE_MULT(cpu_transcoder),
 			   intel_crtc->config->pixel_multiplier - 1);
 	}
 
@@ -4984,9 +4863,12 @@ static void haswell_crtc_enable(struct d
 				     &intel_crtc->config->fdi_m_n, NULL);
 	}
 
-	haswell_set_pipeconf(crtc);
+	if (!intel_crtc->config->has_dsi_encoder)
+		haswell_set_pipeconf(crtc);
 
-	intel_set_pipe_csc(crtc);
+	haswell_set_pipemisc(crtc);
+
+	intel_color_set_csc(&pipe_config->base);
 
 	intel_crtc->active = true;
 
@@ -5015,14 +4897,20 @@ static void haswell_crtc_enable(struct d
 	 * On ILK+ LUT must be loaded before the pipe is running but with
 	 * clocks enabled
 	 */
-	intel_crtc_load_lut(crtc);
+	intel_color_load_luts(&pipe_config->base);
 
 	intel_ddi_set_pipe_settings(crtc);
 	if (!intel_crtc->config->has_dsi_encoder)
 		intel_ddi_enable_transcoder_func(crtc);
 
-	intel_update_watermarks(crtc);
-	intel_enable_pipe(intel_crtc);
+	if (dev_priv->display.initial_watermarks != NULL)
+		dev_priv->display.initial_watermarks(pipe_config);
+	else
+		intel_update_watermarks(crtc);
+
+	/* XXX: Do the pipe assertions at the right place for BXT DSI. */
+	if (!intel_crtc->config->has_dsi_encoder)
+		intel_enable_pipe(intel_crtc);
 
 	if (intel_crtc->config->has_pch_encoder)
 		lpt_pch_enable(crtc);
@@ -5078,8 +4966,15 @@ static void ironlake_crtc_disable(struct
 	struct intel_encoder *encoder;
 	int pipe = intel_crtc->pipe;
 
-	if (intel_crtc->config->has_pch_encoder)
+	/*
+	 * Sometimes spurious CPU pipe underruns happen when the
+	 * pipe is already disabled, but FDI RX/TX is still enabled.
+	 * Happens at least with VGA+HDMI cloning. Suppress them.
+	 */
+	if (intel_crtc->config->has_pch_encoder) {
+		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
 		intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, false);
+	}
 
 	for_each_encoder_on_crtc(dev, crtc, encoder)
 		encoder->disable(encoder);
@@ -5087,22 +4982,12 @@ static void ironlake_crtc_disable(struct
 	drm_crtc_vblank_off(crtc);
 	assert_vblank_disabled(crtc);
 
-	/*
-	 * Sometimes spurious CPU pipe underruns happen when the
-	 * pipe is already disabled, but FDI RX/TX is still enabled.
-	 * Happens at least with VGA+HDMI cloning. Suppress them.
-	 */
-	if (intel_crtc->config->has_pch_encoder)
-		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
-
 	intel_disable_pipe(intel_crtc);
 
 	ironlake_pfit_disable(intel_crtc, false);
 
-	if (intel_crtc->config->has_pch_encoder) {
+	if (intel_crtc->config->has_pch_encoder)
 		ironlake_fdi_disable(crtc);
-		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
-	}
 
 	for_each_encoder_on_crtc(dev, crtc, encoder)
 		if (encoder->post_disable)
@@ -5132,6 +5017,7 @@ static void ironlake_crtc_disable(struct
 		ironlake_fdi_pll_disable(intel_crtc);
 	}
 
+	intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
 	intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, true);
 }
 
@@ -5155,7 +5041,9 @@ static void haswell_crtc_disable(struct
 	drm_crtc_vblank_off(crtc);
 	assert_vblank_disabled(crtc);
 
-	intel_disable_pipe(intel_crtc);
+	/* XXX: Do the pipe assertions at the right place for BXT DSI. */
+	if (!intel_crtc->config->has_dsi_encoder)
+		intel_disable_pipe(intel_crtc);
 
 	if (intel_crtc->config->dp_encoder_is_mst)
 		intel_ddi_set_vc_payload_alloc(crtc, false);
@@ -5330,6 +5218,9 @@ static unsigned long get_crtc_power_doma
 		mask |= BIT(intel_display_port_power_domain(intel_encoder));
 	}
 
+	if (crtc_state->shared_dpll)
+		mask |= BIT(POWER_DOMAIN_PLLS);
+
 	return mask;
 }
 
@@ -5393,6 +5284,8 @@ static void intel_update_max_cdclk(struc
 			dev_priv->max_cdclk_freq = 450000;
 		else
 			dev_priv->max_cdclk_freq = 337500;
+	} else if (IS_BROXTON(dev)) {
+		dev_priv->max_cdclk_freq = 624000;
 	} else if (IS_BROADWELL(dev))  {
 		/*
 		 * FIXME with extra cooling we can allow
@@ -5452,9 +5345,8 @@ static void intel_update_cdclk(struct dr
 		intel_update_max_cdclk(dev);
 }
 
-static void broxton_set_cdclk(struct drm_device *dev, int frequency)
+static void broxton_set_cdclk(struct drm_i915_private *dev_priv, int frequency)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	uint32_t divider;
 	uint32_t ratio;
 	uint32_t current_freq;
@@ -5568,33 +5460,46 @@ static void broxton_set_cdclk(struct drm
 		return;
 	}
 
-	intel_update_cdclk(dev);
+	intel_update_cdclk(dev_priv->dev);
 }
 
-void broxton_init_cdclk(struct drm_device *dev)
+static bool broxton_cdclk_is_enabled(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	uint32_t val;
+	if (!(I915_READ(BXT_DE_PLL_ENABLE) & BXT_DE_PLL_PLL_ENABLE))
+		return false;
 
-	/*
-	 * NDE_RSTWRN_OPT RST PCH Handshake En must always be 0b on BXT
-	 * or else the reset will hang because there is no PCH to respond.
-	 * Move the handshake programming to initialization sequence.
-	 * Previously was left up to BIOS.
-	 */
-	val = I915_READ(HSW_NDE_RSTWRN_OPT);
-	val &= ~RESET_PCH_HANDSHAKE_ENABLE;
-	I915_WRITE(HSW_NDE_RSTWRN_OPT, val);
+	/* TODO: Check for a valid CDCLK rate */
 
-	/* Enable PG1 for cdclk */
-	intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS);
+	if (!(I915_READ(DBUF_CTL) & DBUF_POWER_REQUEST)) {
+		DRM_DEBUG_DRIVER("CDCLK enabled, but DBUF power not requested\n");
 
+		return false;
+	}
+
+	if (!(I915_READ(DBUF_CTL) & DBUF_POWER_STATE)) {
+		DRM_DEBUG_DRIVER("CDCLK enabled, but DBUF power hasn't settled\n");
+
+		return false;
+	}
+
+	return true;
+}
+
+bool broxton_cdclk_verify_state(struct drm_i915_private *dev_priv)
+{
+	return broxton_cdclk_is_enabled(dev_priv);
+}
+
+void broxton_init_cdclk(struct drm_i915_private *dev_priv)
+{
 	/* check if cd clock is enabled */
-	if (I915_READ(BXT_DE_PLL_ENABLE) & BXT_DE_PLL_PLL_ENABLE) {
-		DRM_DEBUG_KMS("Display already initialized\n");
+	if (broxton_cdclk_is_enabled(dev_priv)) {
+		DRM_DEBUG_KMS("CDCLK already enabled, won't reprogram it\n");
 		return;
 	}
 
+	DRM_DEBUG_KMS("CDCLK not enabled, enabling it\n");
+
 	/*
 	 * FIXME:
 	 * - The initial CDCLK needs to be read from VBT.
@@ -5602,7 +5507,7 @@ void broxton_init_cdclk(struct drm_devic
 	 * - check if setting the max (or any) cdclk freq is really necessary
 	 *   here, it belongs to modeset time
 	 */
-	broxton_set_cdclk(dev, 624000);
+	broxton_set_cdclk(dev_priv, 624000);
 
 	I915_WRITE(DBUF_CTL, I915_READ(DBUF_CTL) | DBUF_POWER_REQUEST);
 	POSTING_READ(DBUF_CTL);
@@ -5613,10 +5518,8 @@ void broxton_init_cdclk(struct drm_devic
 		DRM_ERROR("DBuf power enable timeout!\n");
 }
 
-void broxton_uninit_cdclk(struct drm_device *dev)
+void broxton_uninit_cdclk(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-
 	I915_WRITE(DBUF_CTL, I915_READ(DBUF_CTL) & ~DBUF_POWER_REQUEST);
 	POSTING_READ(DBUF_CTL);
 
@@ -5626,9 +5529,7 @@ void broxton_uninit_cdclk(struct drm_dev
 		DRM_ERROR("DBuf power disable timeout!\n");
 
 	/* Set minimum (bypass) frequency, in effect turning off the DE PLL */
-	broxton_set_cdclk(dev, 19200);
-
-	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+	broxton_set_cdclk(dev_priv, 19200);
 }
 
 static const struct skl_cdclk_entry {
@@ -6165,6 +6066,8 @@ static void valleyview_crtc_enable(struc
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct intel_encoder *encoder;
+	struct intel_crtc_state *pipe_config =
+		to_intel_crtc_state(crtc->state);
 	int pipe = intel_crtc->pipe;
 
 	if (WARN_ON(intel_crtc->active))
@@ -6174,6 +6077,7 @@ static void valleyview_crtc_enable(struc
 		intel_dp_set_m_n(intel_crtc, M1_N1);
 
 	intel_set_pipe_timings(intel_crtc);
+	intel_set_pipe_src_size(intel_crtc);
 
 	if (IS_CHERRYVIEW(dev) && pipe == PIPE_B) {
 		struct drm_i915_private *dev_priv = dev->dev_private;
@@ -6192,14 +6096,12 @@ static void valleyview_crtc_enable(struc
 		if (encoder->pre_pll_enable)
 			encoder->pre_pll_enable(encoder);
 
-	if (!intel_crtc->config->has_dsi_encoder) {
-		if (IS_CHERRYVIEW(dev)) {
-			chv_prepare_pll(intel_crtc, intel_crtc->config);
-			chv_enable_pll(intel_crtc, intel_crtc->config);
-		} else {
-			vlv_prepare_pll(intel_crtc, intel_crtc->config);
-			vlv_enable_pll(intel_crtc, intel_crtc->config);
-		}
+	if (IS_CHERRYVIEW(dev)) {
+		chv_prepare_pll(intel_crtc, intel_crtc->config);
+		chv_enable_pll(intel_crtc, intel_crtc->config);
+	} else {
+		vlv_prepare_pll(intel_crtc, intel_crtc->config);
+		vlv_enable_pll(intel_crtc, intel_crtc->config);
 	}
 
 	for_each_encoder_on_crtc(dev, crtc, encoder)
@@ -6208,8 +6110,9 @@ static void valleyview_crtc_enable(struc
 
 	i9xx_pfit_enable(intel_crtc);
 
-	intel_crtc_load_lut(crtc);
+	intel_color_load_luts(&pipe_config->base);
 
+	intel_update_watermarks(crtc);
 	intel_enable_pipe(intel_crtc);
 
 	assert_vblank_disabled(crtc);
@@ -6234,7 +6137,9 @@ static void i9xx_crtc_enable(struct drm_
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct intel_encoder *encoder;
-	int pipe = intel_crtc->pipe;
+	struct intel_crtc_state *pipe_config =
+		to_intel_crtc_state(crtc->state);
+	enum pipe pipe = intel_crtc->pipe;
 
 	if (WARN_ON(intel_crtc->active))
 		return;
@@ -6245,6 +6150,7 @@ static void i9xx_crtc_enable(struct drm_
 		intel_dp_set_m_n(intel_crtc, M1_N1);
 
 	intel_set_pipe_timings(intel_crtc);
+	intel_set_pipe_src_size(intel_crtc);
 
 	i9xx_set_pipeconf(intel_crtc);
 
@@ -6261,7 +6167,7 @@ static void i9xx_crtc_enable(struct drm_
 
 	i9xx_pfit_enable(intel_crtc);
 
-	intel_crtc_load_lut(crtc);
+	intel_color_load_luts(&pipe_config->base);
 
 	intel_update_watermarks(crtc);
 	intel_enable_pipe(intel_crtc);
@@ -6299,10 +6205,9 @@ static void i9xx_crtc_disable(struct drm
 	/*
 	 * On gen2 planes are double buffered but the pipe isn't, so we must
 	 * wait for planes to fully turn off before disabling the pipe.
-	 * We also need to wait on all gmch platforms because of the
-	 * self-refresh mode constraint explained above.
 	 */
-	intel_wait_for_vblank(dev, pipe);
+	if (IS_GEN2(dev))
+		intel_wait_for_vblank(dev, pipe);
 
 	for_each_encoder_on_crtc(dev, crtc, encoder)
 		encoder->disable(encoder);
@@ -6337,6 +6242,7 @@ static void i9xx_crtc_disable(struct drm
 
 static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
 {
+	struct intel_encoder *encoder;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
 	enum intel_display_power_domain domain;
@@ -6348,14 +6254,27 @@ static void intel_crtc_disable_noatomic(
 	if (to_intel_plane_state(crtc->primary->state)->visible) {
 		WARN_ON(intel_crtc->unpin_work);
 
-		intel_pre_disable_primary(crtc);
+		intel_pre_disable_primary_noatomic(crtc);
 
 		intel_crtc_disable_planes(crtc, 1 << drm_plane_index(crtc->primary));
 		to_intel_plane_state(crtc->primary->state)->visible = false;
 	}
 
 	dev_priv->display.crtc_disable(crtc);
+
+	DRM_DEBUG_KMS("[CRTC:%d] hw state adjusted, was enabled, now disabled\n",
+		      crtc->base.id);
+
+	WARN_ON(drm_atomic_set_mode_for_crtc(crtc->state, NULL) < 0);
+	crtc->state->active = false;
 	intel_crtc->active = false;
+	crtc->enabled = false;
+	crtc->state->connector_mask = 0;
+	crtc->state->encoder_mask = 0;
+
+	for_each_encoder_on_crtc(crtc->dev, crtc, encoder)
+		encoder->base.crtc = NULL;
+
 	intel_fbc_disable(intel_crtc);
 	intel_update_watermarks(crtc);
 	intel_disable_shared_dpll(intel_crtc);
@@ -6398,7 +6317,7 @@ void intel_encoder_destroy(struct drm_en
 
 /* Cross check the actual hw state with our own modeset state tracking (and it's
  * internal consistency). */
-static void intel_connector_check_state(struct intel_connector *connector)
+static void intel_connector_verify_state(struct intel_connector *connector)
 {
 	struct drm_crtc *crtc = connector->base.state->crtc;
 
@@ -6568,7 +6487,7 @@ retry:
 	 * Hence the bw of each lane in terms of the mode signal
 	 * is:
 	 */
-	link_bw = intel_fdi_link_freq(dev) * MHz(100)/KHz(1)/10;
+	link_bw = intel_fdi_link_freq(to_i915(dev), pipe_config);
 
 	fdi_dotclock = adjusted_mode->crtc_clock;
 
@@ -6580,8 +6499,7 @@ retry:
 	intel_link_compute_m_n(pipe_config->pipe_bpp, lane, fdi_dotclock,
 			       link_bw, &pipe_config->fdi_m_n);
 
-	ret = ironlake_check_fdi_lanes(intel_crtc->base.dev,
-				       intel_crtc->pipe, pipe_config);
+	ret = ironlake_check_fdi_lanes(dev, intel_crtc->pipe, pipe_config);
 	if (ret == -EINVAL && pipe_config->pipe_bpp > 6*3) {
 		pipe_config->pipe_bpp -= 2*3;
 		DRM_DEBUG_KMS("fdi link bw constraint, reducing pipe bpp to %i\n",
@@ -6605,7 +6523,7 @@ static bool pipe_config_supports_ips(str
 		return false;
 
 	/* HSW can handle pixel rate up to cdclk? */
-	if (IS_HASWELL(dev_priv->dev))
+	if (IS_HASWELL(dev_priv))
 		return true;
 
 	/*
@@ -7133,30 +7051,6 @@ static inline bool intel_panel_use_ssc(s
 		&& !(dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE);
 }
 
-static int i9xx_get_refclk(const struct intel_crtc_state *crtc_state,
-			   int num_connectors)
-{
-	struct drm_device *dev = crtc_state->base.crtc->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	int refclk;
-
-	WARN_ON(!crtc_state->base.state);
-
-	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev) || IS_BROXTON(dev)) {
-		refclk = 100000;
-	} else if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS) &&
-	    intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
-		refclk = dev_priv->vbt.lvds_ssc_freq;
-		DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", refclk);
-	} else if (!IS_GEN2(dev)) {
-		refclk = 96000;
-	} else {
-		refclk = 48000;
-	}
-
-	return refclk;
-}
-
 static uint32_t pnv_dpll_compute_fp(struct dpll *dpll)
 {
 	return (1 << dpll->n) << 16 | dpll->m2;
@@ -7300,24 +7194,34 @@ void intel_dp_set_m_n(struct intel_crtc
 static void vlv_compute_dpll(struct intel_crtc *crtc,
 			     struct intel_crtc_state *pipe_config)
 {
-	u32 dpll, dpll_md;
+	pipe_config->dpll_hw_state.dpll = DPLL_INTEGRATED_REF_CLK_VLV |
+		DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS;
+	if (crtc->pipe != PIPE_A)
+		pipe_config->dpll_hw_state.dpll |= DPLL_INTEGRATED_CRI_CLK_VLV;
 
-	/*
-	 * Enable DPIO clock input. We should never disable the reference
-	 * clock for pipe B, since VGA hotplug / manual detection depends
-	 * on it.
-	 */
-	dpll = DPLL_EXT_BUFFER_ENABLE_VLV | DPLL_REF_CLK_ENABLE_VLV |
-		DPLL_VGA_MODE_DIS | DPLL_INTEGRATED_REF_CLK_VLV;
-	/* We should never disable this, set it here for state tracking */
-	if (crtc->pipe == PIPE_B)
-		dpll |= DPLL_INTEGRATED_CRI_CLK_VLV;
-	dpll |= DPLL_VCO_ENABLE;
-	pipe_config->dpll_hw_state.dpll = dpll;
+	/* DPLL not used with DSI, but still need the rest set up */
+	if (!pipe_config->has_dsi_encoder)
+		pipe_config->dpll_hw_state.dpll |= DPLL_VCO_ENABLE |
+			DPLL_EXT_BUFFER_ENABLE_VLV;
 
-	dpll_md = (pipe_config->pixel_multiplier - 1)
-		<< DPLL_MD_UDI_MULTIPLIER_SHIFT;
-	pipe_config->dpll_hw_state.dpll_md = dpll_md;
+	pipe_config->dpll_hw_state.dpll_md =
+		(pipe_config->pixel_multiplier - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT;
+}
+
+static void chv_compute_dpll(struct intel_crtc *crtc,
+			     struct intel_crtc_state *pipe_config)
+{
+	pipe_config->dpll_hw_state.dpll = DPLL_SSC_REF_CLK_CHV |
+		DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS;
+	if (crtc->pipe != PIPE_A)
+		pipe_config->dpll_hw_state.dpll |= DPLL_INTEGRATED_CRI_CLK_VLV;
+
+	/* DPLL not used with DSI, but still need the rest set up */
+	if (!pipe_config->has_dsi_encoder)
+		pipe_config->dpll_hw_state.dpll |= DPLL_VCO_ENABLE;
+
+	pipe_config->dpll_hw_state.dpll_md =
+		(pipe_config->pixel_multiplier - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT;
 }
 
 static void vlv_prepare_pll(struct intel_crtc *crtc,
@@ -7325,11 +7229,20 @@ static void vlv_prepare_pll(struct intel
 {
 	struct drm_device *dev = crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	int pipe = crtc->pipe;
+	enum pipe pipe = crtc->pipe;
 	u32 mdiv;
 	u32 bestn, bestm1, bestm2, bestp1, bestp2;
 	u32 coreclk, reg_val;
 
+	/* Enable Refclk */
+	I915_WRITE(DPLL(pipe),
+		   pipe_config->dpll_hw_state.dpll &
+		   ~(DPLL_VCO_ENABLE | DPLL_EXT_BUFFER_ENABLE_VLV));
+
+	/* No need to actually set up the DPLL with DSI */
+	if ((pipe_config->dpll_hw_state.dpll & DPLL_VCO_ENABLE) == 0)
+		return;
+
 	mutex_lock(&dev_priv->sb_lock);
 
 	bestn = pipe_config->dpll.n;
@@ -7411,32 +7324,26 @@ static void vlv_prepare_pll(struct intel
 	mutex_unlock(&dev_priv->sb_lock);
 }
 
-static void chv_compute_dpll(struct intel_crtc *crtc,
-			     struct intel_crtc_state *pipe_config)
-{
-	pipe_config->dpll_hw_state.dpll = DPLL_SSC_REF_CLK_CHV |
-		DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS |
-		DPLL_VCO_ENABLE;
-	if (crtc->pipe != PIPE_A)
-		pipe_config->dpll_hw_state.dpll |= DPLL_INTEGRATED_CRI_CLK_VLV;
-
-	pipe_config->dpll_hw_state.dpll_md =
-		(pipe_config->pixel_multiplier - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT;
-}
-
 static void chv_prepare_pll(struct intel_crtc *crtc,
 			    const struct intel_crtc_state *pipe_config)
 {
 	struct drm_device *dev = crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	int pipe = crtc->pipe;
-	i915_reg_t dpll_reg = DPLL(crtc->pipe);
+	enum pipe pipe = crtc->pipe;
 	enum dpio_channel port = vlv_pipe_to_channel(pipe);
 	u32 loopfilter, tribuf_calcntr;
 	u32 bestn, bestm1, bestm2, bestp1, bestp2, bestm2_frac;
 	u32 dpio_val;
 	int vco;
 
+	/* Enable Refclk and SSC */
+	I915_WRITE(DPLL(pipe),
+		   pipe_config->dpll_hw_state.dpll & ~DPLL_VCO_ENABLE);
+
+	/* No need to actually set up the DPLL with DSI */
+	if ((pipe_config->dpll_hw_state.dpll & DPLL_VCO_ENABLE) == 0)
+		return;
+
 	bestn = pipe_config->dpll.n;
 	bestm2_frac = pipe_config->dpll.m2 & 0x3fffff;
 	bestm1 = pipe_config->dpll.m1;
@@ -7447,12 +7354,6 @@ static void chv_prepare_pll(struct intel
 	dpio_val = 0;
 	loopfilter = 0;
 
-	/*
-	 * Enable Refclk and SSC
-	 */
-	I915_WRITE(dpll_reg,
-		   pipe_config->dpll_hw_state.dpll & ~DPLL_VCO_ENABLE);
-
 	mutex_lock(&dev_priv->sb_lock);
 
 	/* p1 and p2 divider */
@@ -7586,8 +7487,7 @@ void vlv_force_pll_off(struct drm_device
 
 static void i9xx_compute_dpll(struct intel_crtc *crtc,
 			      struct intel_crtc_state *crtc_state,
-			      intel_clock_t *reduced_clock,
-			      int num_connectors)
+			      intel_clock_t *reduced_clock)
 {
 	struct drm_device *dev = crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -7646,7 +7546,7 @@ static void i9xx_compute_dpll(struct int
 	if (crtc_state->sdvo_tv_clock)
 		dpll |= PLL_REF_INPUT_TVCLKINBC;
 	else if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS) &&
-		 intel_panel_use_ssc(dev_priv) && num_connectors < 2)
+		 intel_panel_use_ssc(dev_priv))
 		dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
 	else
 		dpll |= PLL_REF_INPUT_DREFCLK;
@@ -7663,8 +7563,7 @@ static void i9xx_compute_dpll(struct int
 
 static void i8xx_compute_dpll(struct intel_crtc *crtc,
 			      struct intel_crtc_state *crtc_state,
-			      intel_clock_t *reduced_clock,
-			      int num_connectors)
+			      intel_clock_t *reduced_clock)
 {
 	struct drm_device *dev = crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -7690,7 +7589,7 @@ static void i8xx_compute_dpll(struct int
 		dpll |= DPLL_DVO_2X_MODE;
 
 	if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS) &&
-		 intel_panel_use_ssc(dev_priv) && num_connectors < 2)
+	    intel_panel_use_ssc(dev_priv))
 		dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
 	else
 		dpll |= PLL_REF_INPUT_DREFCLK;
@@ -7759,6 +7658,14 @@ static void intel_set_pipe_timings(struc
 	    (pipe == PIPE_B || pipe == PIPE_C))
 		I915_WRITE(VTOTAL(pipe), I915_READ(VTOTAL(cpu_transcoder)));
 
+}
+
+static void intel_set_pipe_src_size(struct intel_crtc *intel_crtc)
+{
+	struct drm_device *dev = intel_crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	enum pipe pipe = intel_crtc->pipe;
+
 	/* pipesrc controls the size that is scaled from, which should
 	 * always be the user's requested size.
 	 */
@@ -7800,6 +7707,14 @@ static void intel_get_pipe_timings(struc
 		pipe_config->base.adjusted_mode.crtc_vtotal += 1;
 		pipe_config->base.adjusted_mode.crtc_vblank_end += 1;
 	}
+}
+
+static void intel_get_pipe_src_size(struct intel_crtc *crtc,
+				    struct intel_crtc_state *pipe_config)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 tmp;
 
 	tmp = I915_READ(PIPESRC(crtc->pipe));
 	pipe_config->pipe_src_h = (tmp & 0xffff) + 1;
@@ -7897,69 +7812,192 @@ static void i9xx_set_pipeconf(struct int
 	POSTING_READ(PIPECONF(intel_crtc->pipe));
 }
 
-static int i9xx_crtc_compute_clock(struct intel_crtc *crtc,
+static int i8xx_crtc_compute_clock(struct intel_crtc *crtc,
 				   struct intel_crtc_state *crtc_state)
 {
 	struct drm_device *dev = crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	int refclk, num_connectors = 0;
-	intel_clock_t clock;
-	bool ok;
 	const intel_limit_t *limit;
-	struct drm_atomic_state *state = crtc_state->base.state;
-	struct drm_connector *connector;
-	struct drm_connector_state *connector_state;
-	int i;
+	int refclk = 48000;
 
 	memset(&crtc_state->dpll_hw_state, 0,
 	       sizeof(crtc_state->dpll_hw_state));
 
-	if (crtc_state->has_dsi_encoder)
-		return 0;
+	if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS)) {
+		if (intel_panel_use_ssc(dev_priv)) {
+			refclk = dev_priv->vbt.lvds_ssc_freq;
+			DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", refclk);
+		}
 
-	for_each_connector_in_state(state, connector, connector_state, i) {
-		if (connector_state->crtc == &crtc->base)
-			num_connectors++;
+		limit = &intel_limits_i8xx_lvds;
+	} else if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_DVO)) {
+		limit = &intel_limits_i8xx_dvo;
+	} else {
+		limit = &intel_limits_i8xx_dac;
 	}
 
-	if (!crtc_state->clock_set) {
-		refclk = i9xx_get_refclk(crtc_state, num_connectors);
+	if (!crtc_state->clock_set &&
+	    !i9xx_find_best_dpll(limit, crtc_state, crtc_state->port_clock,
+				 refclk, NULL, &crtc_state->dpll)) {
+		DRM_ERROR("Couldn't find PLL settings for mode!\n");
+		return -EINVAL;
+	}
 
-		/*
-		 * Returns a set of divisors for the desired target clock with
-		 * the given refclk, or FALSE.  The returned values represent
-		 * the clock equation: reflck * (5 * (m1 + 2) + (m2 + 2)) / (n +
-		 * 2) / p1 / p2.
-		 */
-		limit = intel_limit(crtc_state, refclk);
-		ok = dev_priv->display.find_dpll(limit, crtc_state,
-						 crtc_state->port_clock,
-						 refclk, NULL, &clock);
-		if (!ok) {
-			DRM_ERROR("Couldn't find PLL settings for mode!\n");
-			return -EINVAL;
+	i8xx_compute_dpll(crtc, crtc_state, NULL);
+
+	return 0;
+}
+
+static int g4x_crtc_compute_clock(struct intel_crtc *crtc,
+				  struct intel_crtc_state *crtc_state)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	const intel_limit_t *limit;
+	int refclk = 96000;
+
+	memset(&crtc_state->dpll_hw_state, 0,
+	       sizeof(crtc_state->dpll_hw_state));
+
+	if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS)) {
+		if (intel_panel_use_ssc(dev_priv)) {
+			refclk = dev_priv->vbt.lvds_ssc_freq;
+			DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", refclk);
 		}
 
-		/* Compat-code for transition, will disappear. */
-		crtc_state->dpll.n = clock.n;
-		crtc_state->dpll.m1 = clock.m1;
-		crtc_state->dpll.m2 = clock.m2;
-		crtc_state->dpll.p1 = clock.p1;
-		crtc_state->dpll.p2 = clock.p2;
+		if (intel_is_dual_link_lvds(dev))
+			limit = &intel_limits_g4x_dual_channel_lvds;
+		else
+			limit = &intel_limits_g4x_single_channel_lvds;
+	} else if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_HDMI) ||
+		   intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_ANALOG)) {
+		limit = &intel_limits_g4x_hdmi;
+	} else if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_SDVO)) {
+		limit = &intel_limits_g4x_sdvo;
+	} else {
+		/* The option is for other outputs */
+		limit = &intel_limits_i9xx_sdvo;
 	}
 
-	if (IS_GEN2(dev)) {
-		i8xx_compute_dpll(crtc, crtc_state, NULL,
-				  num_connectors);
-	} else if (IS_CHERRYVIEW(dev)) {
-		chv_compute_dpll(crtc, crtc_state);
-	} else if (IS_VALLEYVIEW(dev)) {
-		vlv_compute_dpll(crtc, crtc_state);
+	if (!crtc_state->clock_set &&
+	    !g4x_find_best_dpll(limit, crtc_state, crtc_state->port_clock,
+				refclk, NULL, &crtc_state->dpll)) {
+		DRM_ERROR("Couldn't find PLL settings for mode!\n");
+		return -EINVAL;
+	}
+
+	i9xx_compute_dpll(crtc, crtc_state, NULL);
+
+	return 0;
+}
+
+static int pnv_crtc_compute_clock(struct intel_crtc *crtc,
+				  struct intel_crtc_state *crtc_state)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	const intel_limit_t *limit;
+	int refclk = 96000;
+
+	memset(&crtc_state->dpll_hw_state, 0,
+	       sizeof(crtc_state->dpll_hw_state));
+
+	if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS)) {
+		if (intel_panel_use_ssc(dev_priv)) {
+			refclk = dev_priv->vbt.lvds_ssc_freq;
+			DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", refclk);
+		}
+
+		limit = &intel_limits_pineview_lvds;
 	} else {
-		i9xx_compute_dpll(crtc, crtc_state, NULL,
-				  num_connectors);
+		limit = &intel_limits_pineview_sdvo;
+	}
+
+	if (!crtc_state->clock_set &&
+	    !pnv_find_best_dpll(limit, crtc_state, crtc_state->port_clock,
+				refclk, NULL, &crtc_state->dpll)) {
+		DRM_ERROR("Couldn't find PLL settings for mode!\n");
+		return -EINVAL;
+	}
+
+	i9xx_compute_dpll(crtc, crtc_state, NULL);
+
+	return 0;
+}
+
+static int i9xx_crtc_compute_clock(struct intel_crtc *crtc,
+				   struct intel_crtc_state *crtc_state)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	const intel_limit_t *limit;
+	int refclk = 96000;
+
+	memset(&crtc_state->dpll_hw_state, 0,
+	       sizeof(crtc_state->dpll_hw_state));
+
+	if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS)) {
+		if (intel_panel_use_ssc(dev_priv)) {
+			refclk = dev_priv->vbt.lvds_ssc_freq;
+			DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n", refclk);
+		}
+
+		limit = &intel_limits_i9xx_lvds;
+	} else {
+		limit = &intel_limits_i9xx_sdvo;
 	}
 
+	if (!crtc_state->clock_set &&
+	    !i9xx_find_best_dpll(limit, crtc_state, crtc_state->port_clock,
+				 refclk, NULL, &crtc_state->dpll)) {
+		DRM_ERROR("Couldn't find PLL settings for mode!\n");
+		return -EINVAL;
+	}
+
+	i9xx_compute_dpll(crtc, crtc_state, NULL);
+
+	return 0;
+}
+
+static int chv_crtc_compute_clock(struct intel_crtc *crtc,
+				  struct intel_crtc_state *crtc_state)
+{
+	int refclk = 100000;
+	const intel_limit_t *limit = &intel_limits_chv;
+
+	memset(&crtc_state->dpll_hw_state, 0,
+	       sizeof(crtc_state->dpll_hw_state));
+
+	if (!crtc_state->clock_set &&
+	    !chv_find_best_dpll(limit, crtc_state, crtc_state->port_clock,
+				refclk, NULL, &crtc_state->dpll)) {
+		DRM_ERROR("Couldn't find PLL settings for mode!\n");
+		return -EINVAL;
+	}
+
+	chv_compute_dpll(crtc, crtc_state);
+
+	return 0;
+}
+
+static int vlv_crtc_compute_clock(struct intel_crtc *crtc,
+				  struct intel_crtc_state *crtc_state)
+{
+	int refclk = 100000;
+	const intel_limit_t *limit = &intel_limits_vlv;
+
+	memset(&crtc_state->dpll_hw_state, 0,
+	       sizeof(crtc_state->dpll_hw_state));
+
+	if (!crtc_state->clock_set &&
+	    !vlv_find_best_dpll(limit, crtc_state, crtc_state->port_clock,
+				refclk, NULL, &crtc_state->dpll)) {
+		DRM_ERROR("Couldn't find PLL settings for mode!\n");
+		return -EINVAL;
+	}
+
+	vlv_compute_dpll(crtc, crtc_state);
+
 	return 0;
 }
 
@@ -8000,8 +8038,8 @@ static void vlv_crtc_clock_get(struct in
 	u32 mdiv;
 	int refclk = 100000;
 
-	/* In case of MIPI DPLL will not even be used */
-	if (!(pipe_config->dpll_hw_state.dpll & DPLL_VCO_ENABLE))
+	/* In case of DSI, DPLL will not be used */
+	if ((pipe_config->dpll_hw_state.dpll & DPLL_VCO_ENABLE) == 0)
 		return;
 
 	mutex_lock(&dev_priv->sb_lock);
@@ -8097,6 +8135,10 @@ static void chv_crtc_clock_get(struct in
 	u32 cmn_dw13, pll_dw0, pll_dw1, pll_dw2, pll_dw3;
 	int refclk = 100000;
 
+	/* In case of DSI, DPLL will not be used */
+	if ((pipe_config->dpll_hw_state.dpll & DPLL_VCO_ENABLE) == 0)
+		return;
+
 	mutex_lock(&dev_priv->sb_lock);
 	cmn_dw13 = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW13(port));
 	pll_dw0 = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW0(port));
@@ -8130,7 +8172,7 @@ static bool i9xx_get_pipe_config(struct
 		return false;
 
 	pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe;
-	pipe_config->shared_dpll = DPLL_ID_PRIVATE;
+	pipe_config->shared_dpll = NULL;
 
 	ret = false;
 
@@ -8162,11 +8204,16 @@ static bool i9xx_get_pipe_config(struct
 		pipe_config->double_wide = tmp & PIPECONF_DOUBLE_WIDE;
 
 	intel_get_pipe_timings(crtc, pipe_config);
+	intel_get_pipe_src_size(crtc, pipe_config);
 
 	i9xx_get_pfit_config(crtc, pipe_config);
 
 	if (INTEL_INFO(dev)->gen >= 4) {
-		tmp = I915_READ(DPLL_MD(crtc->pipe));
+		/* No way to read it out on pipes B and C */
+		if (IS_CHERRYVIEW(dev) && crtc->pipe != PIPE_A)
+			tmp = dev_priv->chv_dpll_md[crtc->pipe];
+		else
+			tmp = I915_READ(DPLL_MD(crtc->pipe));
 		pipe_config->pixel_multiplier =
 			((tmp & DPLL_MD_UDI_MULTIPLIER_MASK)
 			 >> DPLL_MD_UDI_MULTIPLIER_SHIFT) + 1;
@@ -8228,12 +8275,14 @@ static void ironlake_init_pch_refclk(str
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_encoder *encoder;
+	int i;
 	u32 val, final;
 	bool has_lvds = false;
 	bool has_cpu_edp = false;
 	bool has_panel = false;
 	bool has_ck505 = false;
 	bool can_ssc = false;
+	bool using_ssc_source = false;
 
 	/* We need to take the global config into account */
 	for_each_intel_encoder(dev, encoder) {
@@ -8260,8 +8309,22 @@ static void ironlake_init_pch_refclk(str
 		can_ssc = true;
 	}
 
-	DRM_DEBUG_KMS("has_panel %d has_lvds %d has_ck505 %d\n",
-		      has_panel, has_lvds, has_ck505);
+	/* Check if any DPLLs are using the SSC source */
+	for (i = 0; i < dev_priv->num_shared_dpll; i++) {
+		u32 temp = I915_READ(PCH_DPLL(i));
+
+		if (!(temp & DPLL_VCO_ENABLE))
+			continue;
+
+		if ((temp & PLL_REF_INPUT_MASK) ==
+		    PLLB_REF_INPUT_SPREADSPECTRUMIN) {
+			using_ssc_source = true;
+			break;
+		}
+	}
+
+	DRM_DEBUG_KMS("has_panel %d has_lvds %d has_ck505 %d using_ssc_source %d\n",
+		      has_panel, has_lvds, has_ck505, using_ssc_source);
 
 	/* Ironlake: try to setup display ref clock before DPLL
 	 * enabling. This is only under driver's control after
@@ -8298,9 +8361,9 @@ static void ironlake_init_pch_refclk(str
 				final |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
 		} else
 			final |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
-	} else {
-		final |= DREF_SSC_SOURCE_DISABLE;
-		final |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
+	} else if (using_ssc_source) {
+		final |= DREF_SSC_SOURCE_ENABLE;
+		final |= DREF_SSC1_ENABLE;
 	}
 
 	if (final == val)
@@ -8346,7 +8409,7 @@ static void ironlake_init_pch_refclk(str
 		POSTING_READ(PCH_DREF_CONTROL);
 		udelay(200);
 	} else {
-		DRM_DEBUG_KMS("Disabling SSC entirely\n");
+		DRM_DEBUG_KMS("Disabling CPU source output\n");
 
 		val &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
 
@@ -8357,16 +8420,20 @@ static void ironlake_init_pch_refclk(str
 		POSTING_READ(PCH_DREF_CONTROL);
 		udelay(200);
 
-		/* Turn off the SSC source */
-		val &= ~DREF_SSC_SOURCE_MASK;
-		val |= DREF_SSC_SOURCE_DISABLE;
+		if (!using_ssc_source) {
+			DRM_DEBUG_KMS("Disabling SSC source\n");
 
-		/* Turn off SSC1 */
-		val &= ~DREF_SSC1_ENABLE;
+			/* Turn off the SSC source */
+			val &= ~DREF_SSC_SOURCE_MASK;
+			val |= DREF_SSC_SOURCE_DISABLE;
 
-		I915_WRITE(PCH_DREF_CONTROL, val);
-		POSTING_READ(PCH_DREF_CONTROL);
-		udelay(200);
+			/* Turn off SSC1 */
+			val &= ~DREF_SSC1_ENABLE;
+
+			I915_WRITE(PCH_DREF_CONTROL, val);
+			POSTING_READ(PCH_DREF_CONTROL);
+			udelay(200);
+		}
 	}
 
 	BUG_ON(val != final);
@@ -8380,16 +8447,16 @@ static void lpt_reset_fdi_mphy(struct dr
 	tmp |= FDI_MPHY_IOSFSB_RESET_CTL;
 	I915_WRITE(SOUTH_CHICKEN2, tmp);
 
-	if (wait_for_atomic_us(I915_READ(SOUTH_CHICKEN2) &
-			       FDI_MPHY_IOSFSB_RESET_STATUS, 100))
+	if (wait_for_us(I915_READ(SOUTH_CHICKEN2) &
+			FDI_MPHY_IOSFSB_RESET_STATUS, 100))
 		DRM_ERROR("FDI mPHY reset assert timeout\n");
 
 	tmp = I915_READ(SOUTH_CHICKEN2);
 	tmp &= ~FDI_MPHY_IOSFSB_RESET_CTL;
 	I915_WRITE(SOUTH_CHICKEN2, tmp);
 
-	if (wait_for_atomic_us((I915_READ(SOUTH_CHICKEN2) &
-				FDI_MPHY_IOSFSB_RESET_STATUS) == 0, 100))
+	if (wait_for_us((I915_READ(SOUTH_CHICKEN2) &
+			 FDI_MPHY_IOSFSB_RESET_STATUS) == 0, 100))
 		DRM_ERROR("FDI mPHY reset de-assert timeout\n");
 }
 
@@ -8635,42 +8702,6 @@ void intel_init_pch_refclk(struct drm_de
 		lpt_init_pch_refclk(dev);
 }
 
-static int ironlake_get_refclk(struct intel_crtc_state *crtc_state)
-{
-	struct drm_device *dev = crtc_state->base.crtc->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_atomic_state *state = crtc_state->base.state;
-	struct drm_connector *connector;
-	struct drm_connector_state *connector_state;
-	struct intel_encoder *encoder;
-	int num_connectors = 0, i;
-	bool is_lvds = false;
-
-	for_each_connector_in_state(state, connector, connector_state, i) {
-		if (connector_state->crtc != crtc_state->base.crtc)
-			continue;
-
-		encoder = to_intel_encoder(connector_state->best_encoder);
-
-		switch (encoder->type) {
-		case INTEL_OUTPUT_LVDS:
-			is_lvds = true;
-			break;
-		default:
-			break;
-		}
-		num_connectors++;
-	}
-
-	if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
-		DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n",
-			      dev_priv->vbt.lvds_ssc_freq);
-		return dev_priv->vbt.lvds_ssc_freq;
-	}
-
-	return 120000;
-}
-
 static void ironlake_set_pipeconf(struct drm_crtc *crtc)
 {
 	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
@@ -8713,82 +8744,14 @@ static void ironlake_set_pipeconf(struct
 	POSTING_READ(PIPECONF(pipe));
 }
 
-/*
- * Set up the pipe CSC unit.
- *
- * Currently only full range RGB to limited range RGB conversion
- * is supported, but eventually this should handle various
- * RGB<->YCbCr scenarios as well.
- */
-static void intel_set_pipe_csc(struct drm_crtc *crtc)
-{
-	struct drm_device *dev = crtc->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	int pipe = intel_crtc->pipe;
-	uint16_t coeff = 0x7800; /* 1.0 */
-
-	/*
-	 * TODO: Check what kind of values actually come out of the pipe
-	 * with these coeff/postoff values and adjust to get the best
-	 * accuracy. Perhaps we even need to take the bpc value into
-	 * consideration.
-	 */
-
-	if (intel_crtc->config->limited_color_range)
-		coeff = ((235 - 16) * (1 << 12) / 255) & 0xff8; /* 0.xxx... */
-
-	/*
-	 * GY/GU and RY/RU should be the other way around according
-	 * to BSpec, but reality doesn't agree. Just set them up in
-	 * a way that results in the correct picture.
-	 */
-	I915_WRITE(PIPE_CSC_COEFF_RY_GY(pipe), coeff << 16);
-	I915_WRITE(PIPE_CSC_COEFF_BY(pipe), 0);
-
-	I915_WRITE(PIPE_CSC_COEFF_RU_GU(pipe), coeff);
-	I915_WRITE(PIPE_CSC_COEFF_BU(pipe), 0);
-
-	I915_WRITE(PIPE_CSC_COEFF_RV_GV(pipe), 0);
-	I915_WRITE(PIPE_CSC_COEFF_BV(pipe), coeff << 16);
-
-	I915_WRITE(PIPE_CSC_PREOFF_HI(pipe), 0);
-	I915_WRITE(PIPE_CSC_PREOFF_ME(pipe), 0);
-	I915_WRITE(PIPE_CSC_PREOFF_LO(pipe), 0);
-
-	if (INTEL_INFO(dev)->gen > 6) {
-		uint16_t postoff = 0;
-
-		if (intel_crtc->config->limited_color_range)
-			postoff = (16 * (1 << 12) / 255) & 0x1fff;
-
-		I915_WRITE(PIPE_CSC_POSTOFF_HI(pipe), postoff);
-		I915_WRITE(PIPE_CSC_POSTOFF_ME(pipe), postoff);
-		I915_WRITE(PIPE_CSC_POSTOFF_LO(pipe), postoff);
-
-		I915_WRITE(PIPE_CSC_MODE(pipe), 0);
-	} else {
-		uint32_t mode = CSC_MODE_YUV_TO_RGB;
-
-		if (intel_crtc->config->limited_color_range)
-			mode |= CSC_BLACK_SCREEN_OFFSET;
-
-		I915_WRITE(PIPE_CSC_MODE(pipe), mode);
-	}
-}
-
 static void haswell_set_pipeconf(struct drm_crtc *crtc)
 {
-	struct drm_device *dev = crtc->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	enum pipe pipe = intel_crtc->pipe;
 	enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
-	uint32_t val;
-
-	val = 0;
+	u32 val = 0;
 
-	if (IS_HASWELL(dev) && intel_crtc->config->dither)
+	if (IS_HASWELL(dev_priv) && intel_crtc->config->dither)
 		val |= (PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP);
 
 	if (intel_crtc->config->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
@@ -8798,12 +8761,15 @@ static void haswell_set_pipeconf(struct
 
 	I915_WRITE(PIPECONF(cpu_transcoder), val);
 	POSTING_READ(PIPECONF(cpu_transcoder));
+}
 
-	I915_WRITE(GAMMA_MODE(intel_crtc->pipe), GAMMA_MODE_MODE_8BIT);
-	POSTING_READ(GAMMA_MODE(intel_crtc->pipe));
+static void haswell_set_pipemisc(struct drm_crtc *crtc)
+{
+	struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
-	if (IS_BROADWELL(dev) || INTEL_INFO(dev)->gen >= 9) {
-		val = 0;
+	if (IS_BROADWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 9) {
+		u32 val = 0;
 
 		switch (intel_crtc->config->pipe_bpp) {
 		case 18:
@@ -8826,39 +8792,10 @@ static void haswell_set_pipeconf(struct
 		if (intel_crtc->config->dither)
 			val |= PIPEMISC_DITHER_ENABLE | PIPEMISC_DITHER_TYPE_SP;
 
-		I915_WRITE(PIPEMISC(pipe), val);
+		I915_WRITE(PIPEMISC(intel_crtc->pipe), val);
 	}
 }
 
-static bool ironlake_compute_clocks(struct drm_crtc *crtc,
-				    struct intel_crtc_state *crtc_state,
-				    intel_clock_t *clock,
-				    bool *has_reduced_clock,
-				    intel_clock_t *reduced_clock)
-{
-	struct drm_device *dev = crtc->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	int refclk;
-	const intel_limit_t *limit;
-	bool ret;
-
-	refclk = ironlake_get_refclk(crtc_state);
-
-	/*
-	 * Returns a set of divisors for the desired target clock with the given
-	 * refclk, or FALSE.  The returned values represent the clock equation:
-	 * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
-	 */
-	limit = intel_limit(crtc_state, refclk);
-	ret = dev_priv->display.find_dpll(limit, crtc_state,
-					  crtc_state->port_clock,
-					  refclk, NULL, clock);
-	if (!ret)
-		return false;
-
-	return true;
-}
-
 int ironlake_get_lanes_required(int target_clock, int link_bw, int bpp)
 {
 	/*
@@ -8875,10 +8812,9 @@ static bool ironlake_needs_fb_cb_tune(st
 	return i9xx_dpll_compute_m(dpll) < factor * dpll->n;
 }
 
-static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc,
-				      struct intel_crtc_state *crtc_state,
-				      u32 *fp,
-				      intel_clock_t *reduced_clock, u32 *fp2)
+static void ironlake_compute_dpll(struct intel_crtc *intel_crtc,
+				  struct intel_crtc_state *crtc_state,
+				  intel_clock_t *reduced_clock)
 {
 	struct drm_crtc *crtc = &intel_crtc->base;
 	struct drm_device *dev = crtc->dev;
@@ -8887,8 +8823,8 @@ static uint32_t ironlake_compute_dpll(st
 	struct drm_connector *connector;
 	struct drm_connector_state *connector_state;
 	struct intel_encoder *encoder;
-	uint32_t dpll;
-	int factor, num_connectors = 0, i;
+	u32 dpll, fp, fp2;
+	int factor, i;
 	bool is_lvds = false, is_sdvo = false;
 
 	for_each_connector_in_state(state, connector, connector_state, i) {
@@ -8908,8 +8844,6 @@ static uint32_t ironlake_compute_dpll(st
 		default:
 			break;
 		}
-
-		num_connectors++;
 	}
 
 	/* Enable autotuning of the PLL clock (if permissible) */
@@ -8922,11 +8856,19 @@ static uint32_t ironlake_compute_dpll(st
 	} else if (crtc_state->sdvo_tv_clock)
 		factor = 20;
 
+	fp = i9xx_dpll_compute_fp(&crtc_state->dpll);
+
 	if (ironlake_needs_fb_cb_tune(&crtc_state->dpll, factor))
-		*fp |= FP_CB_TUNE;
+		fp |= FP_CB_TUNE;
 
-	if (fp2 && (reduced_clock->m < factor * reduced_clock->n))
-		*fp2 |= FP_CB_TUNE;
+	if (reduced_clock) {
+		fp2 = i9xx_dpll_compute_fp(reduced_clock);
+
+		if (reduced_clock->m < factor * reduced_clock->n)
+			fp2 |= FP_CB_TUNE;
+	} else {
+		fp2 = fp;
+	}
 
 	dpll = 0;
 
@@ -8963,76 +8905,80 @@ static uint32_t ironlake_compute_dpll(st
 		break;
 	}
 
-	if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2)
+	if (is_lvds && intel_panel_use_ssc(dev_priv))
 		dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
 	else
 		dpll |= PLL_REF_INPUT_DREFCLK;
 
-	return dpll | DPLL_VCO_ENABLE;
+	dpll |= DPLL_VCO_ENABLE;
+
+	crtc_state->dpll_hw_state.dpll = dpll;
+	crtc_state->dpll_hw_state.fp0 = fp;
+	crtc_state->dpll_hw_state.fp1 = fp2;
 }
 
 static int ironlake_crtc_compute_clock(struct intel_crtc *crtc,
 				       struct intel_crtc_state *crtc_state)
 {
 	struct drm_device *dev = crtc->base.dev;
-	intel_clock_t clock, reduced_clock;
-	u32 dpll = 0, fp = 0, fp2 = 0;
-	bool ok, has_reduced_clock = false;
-	bool is_lvds = false;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	intel_clock_t reduced_clock;
+	bool has_reduced_clock = false;
 	struct intel_shared_dpll *pll;
+	const intel_limit_t *limit;
+	int refclk = 120000;
 
 	memset(&crtc_state->dpll_hw_state, 0,
 	       sizeof(crtc_state->dpll_hw_state));
 
-	is_lvds = intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS);
+	crtc->lowfreq_avail = false;
 
-	WARN(!(HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)),
-	     "Unexpected PCH type %d\n", INTEL_PCH_TYPE(dev));
+	/* CPU eDP is the only output that doesn't need a PCH PLL of its own. */
+	if (!crtc_state->has_pch_encoder)
+		return 0;
 
-	ok = ironlake_compute_clocks(&crtc->base, crtc_state, &clock,
-				     &has_reduced_clock, &reduced_clock);
-	if (!ok && !crtc_state->clock_set) {
+	if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS)) {
+		if (intel_panel_use_ssc(dev_priv)) {
+			DRM_DEBUG_KMS("using SSC reference clock of %d kHz\n",
+				      dev_priv->vbt.lvds_ssc_freq);
+			refclk = dev_priv->vbt.lvds_ssc_freq;
+		}
+
+		if (intel_is_dual_link_lvds(dev)) {
+			if (refclk == 100000)
+				limit = &intel_limits_ironlake_dual_lvds_100m;
+			else
+				limit = &intel_limits_ironlake_dual_lvds;
+		} else {
+			if (refclk == 100000)
+				limit = &intel_limits_ironlake_single_lvds_100m;
+			else
+				limit = &intel_limits_ironlake_single_lvds;
+		}
+	} else {
+		limit = &intel_limits_ironlake_dac;
+	}
+
+	if (!crtc_state->clock_set &&
+	    !g4x_find_best_dpll(limit, crtc_state, crtc_state->port_clock,
+				refclk, NULL, &crtc_state->dpll)) {
 		DRM_ERROR("Couldn't find PLL settings for mode!\n");
 		return -EINVAL;
 	}
-	/* Compat-code for transition, will disappear. */
-	if (!crtc_state->clock_set) {
-		crtc_state->dpll.n = clock.n;
-		crtc_state->dpll.m1 = clock.m1;
-		crtc_state->dpll.m2 = clock.m2;
-		crtc_state->dpll.p1 = clock.p1;
-		crtc_state->dpll.p2 = clock.p2;
-	}
 
-	/* CPU eDP is the only output that doesn't need a PCH PLL of its own. */
-	if (crtc_state->has_pch_encoder) {
-		fp = i9xx_dpll_compute_fp(&crtc_state->dpll);
-		if (has_reduced_clock)
-			fp2 = i9xx_dpll_compute_fp(&reduced_clock);
-
-		dpll = ironlake_compute_dpll(crtc, crtc_state,
-					     &fp, &reduced_clock,
-					     has_reduced_clock ? &fp2 : NULL);
-
-		crtc_state->dpll_hw_state.dpll = dpll;
-		crtc_state->dpll_hw_state.fp0 = fp;
-		if (has_reduced_clock)
-			crtc_state->dpll_hw_state.fp1 = fp2;
-		else
-			crtc_state->dpll_hw_state.fp1 = fp;
+	ironlake_compute_dpll(crtc, crtc_state,
+			      has_reduced_clock ? &reduced_clock : NULL);
 
-		pll = intel_get_shared_dpll(crtc, crtc_state);
-		if (pll == NULL) {
-			DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n",
-					 pipe_name(crtc->pipe));
-			return -EINVAL;
-		}
+	pll = intel_get_shared_dpll(crtc, crtc_state, NULL);
+	if (pll == NULL) {
+		DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n",
+				 pipe_name(crtc->pipe));
+		return -EINVAL;
 	}
 
-	if (is_lvds && has_reduced_clock)
+	if (intel_pipe_will_have_type(crtc_state, INTEL_OUTPUT_LVDS) &&
+	    has_reduced_clock)
 		crtc->lowfreq_avail = true;
-	else
-		crtc->lowfreq_avail = false;
 
 	return 0;
 }
@@ -9334,7 +9280,7 @@ static bool ironlake_get_pipe_config(str
 		return false;
 
 	pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe;
-	pipe_config->shared_dpll = DPLL_ID_PRIVATE;
+	pipe_config->shared_dpll = NULL;
 
 	ret = false;
 	tmp = I915_READ(PIPECONF(crtc->pipe));
@@ -9363,6 +9309,7 @@ static bool ironlake_get_pipe_config(str
 
 	if (I915_READ(PCH_TRANSCONF(crtc->pipe)) & TRANS_ENABLE) {
 		struct intel_shared_dpll *pll;
+		enum intel_dpll_id pll_id;
 
 		pipe_config->has_pch_encoder = true;
 
@@ -9372,21 +9319,22 @@ static bool ironlake_get_pipe_config(str
 
 		ironlake_get_fdi_m_n_config(crtc, pipe_config);
 
-		if (HAS_PCH_IBX(dev_priv->dev)) {
-			pipe_config->shared_dpll =
-				(enum intel_dpll_id) crtc->pipe;
+		if (HAS_PCH_IBX(dev_priv)) {
+			pll_id = (enum intel_dpll_id) crtc->pipe;
 		} else {
 			tmp = I915_READ(PCH_DPLL_SEL);
 			if (tmp & TRANS_DPLLB_SEL(crtc->pipe))
-				pipe_config->shared_dpll = DPLL_ID_PCH_PLL_B;
+				pll_id = DPLL_ID_PCH_PLL_B;
 			else
-				pipe_config->shared_dpll = DPLL_ID_PCH_PLL_A;
+				pll_id= DPLL_ID_PCH_PLL_A;
 		}
 
-		pll = &dev_priv->shared_dplls[pipe_config->shared_dpll];
+		pipe_config->shared_dpll =
+			intel_get_shared_dpll_by_id(dev_priv, pll_id);
+		pll = pipe_config->shared_dpll;
 
-		WARN_ON(!pll->get_hw_state(dev_priv, pll,
-					   &pipe_config->dpll_hw_state));
+		WARN_ON(!pll->funcs.get_hw_state(dev_priv, pll,
+						 &pipe_config->dpll_hw_state));
 
 		tmp = pipe_config->dpll_hw_state.dpll;
 		pipe_config->pixel_multiplier =
@@ -9399,6 +9347,7 @@ static bool ironlake_get_pipe_config(str
 	}
 
 	intel_get_pipe_timings(crtc, pipe_config);
+	intel_get_pipe_src_size(crtc, pipe_config);
 
 	ironlake_get_pfit_config(crtc, pipe_config);
 
@@ -9491,8 +9440,8 @@ static void hsw_disable_lcpll(struct drm
 		val |= LCPLL_CD_SOURCE_FCLK;
 		I915_WRITE(LCPLL_CTL, val);
 
-		if (wait_for_atomic_us(I915_READ(LCPLL_CTL) &
-				       LCPLL_CD_SOURCE_FCLK_DONE, 1))
+		if (wait_for_us(I915_READ(LCPLL_CTL) &
+				LCPLL_CD_SOURCE_FCLK_DONE, 1))
 			DRM_ERROR("Switching to FCLK failed\n");
 
 		val = I915_READ(LCPLL_CTL);
@@ -9565,8 +9514,8 @@ static void hsw_restore_lcpll(struct drm
 		val &= ~LCPLL_CD_SOURCE_FCLK;
 		I915_WRITE(LCPLL_CTL, val);
 
-		if (wait_for_atomic_us((I915_READ(LCPLL_CTL) &
-					LCPLL_CD_SOURCE_FCLK_DONE) == 0, 1))
+		if (wait_for_us((I915_READ(LCPLL_CTL) &
+				 LCPLL_CD_SOURCE_FCLK_DONE) == 0, 1))
 			DRM_ERROR("Switching back to LCPLL failed\n");
 	}
 
@@ -9638,7 +9587,7 @@ static void broxton_modeset_commit_cdclk
 		to_intel_atomic_state(old_state);
 	unsigned int req_cdclk = old_intel_state->dev_cdclk;
 
-	broxton_set_cdclk(dev, req_cdclk);
+	broxton_set_cdclk(to_i915(dev), req_cdclk);
 }
 
 /* compute the max rate for new configuration */
@@ -9706,8 +9655,8 @@ static void broadwell_set_cdclk(struct d
 	val |= LCPLL_CD_SOURCE_FCLK;
 	I915_WRITE(LCPLL_CTL, val);
 
-	if (wait_for_atomic_us(I915_READ(LCPLL_CTL) &
-			       LCPLL_CD_SOURCE_FCLK_DONE, 1))
+	if (wait_for_us(I915_READ(LCPLL_CTL) &
+			LCPLL_CD_SOURCE_FCLK_DONE, 1))
 		DRM_ERROR("Switching to FCLK failed\n");
 
 	val = I915_READ(LCPLL_CTL);
@@ -9741,8 +9690,8 @@ static void broadwell_set_cdclk(struct d
 	val &= ~LCPLL_CD_SOURCE_FCLK;
 	I915_WRITE(LCPLL_CTL, val);
 
-	if (wait_for_atomic_us((I915_READ(LCPLL_CTL) &
-				LCPLL_CD_SOURCE_FCLK_DONE) == 0, 1))
+	if (wait_for_us((I915_READ(LCPLL_CTL) &
+			LCPLL_CD_SOURCE_FCLK_DONE) == 0, 1))
 		DRM_ERROR("Switching back to LCPLL failed\n");
 
 	mutex_lock(&dev_priv->rps.hw_lock);
@@ -9821,72 +9770,193 @@ static void bxt_get_ddi_pll(struct drm_i
 				enum port port,
 				struct intel_crtc_state *pipe_config)
 {
+	enum intel_dpll_id id;
+
 	switch (port) {
 	case PORT_A:
 		pipe_config->ddi_pll_sel = SKL_DPLL0;
-		pipe_config->shared_dpll = DPLL_ID_SKL_DPLL1;
+		id = DPLL_ID_SKL_DPLL0;
 		break;
 	case PORT_B:
 		pipe_config->ddi_pll_sel = SKL_DPLL1;
-		pipe_config->shared_dpll = DPLL_ID_SKL_DPLL2;
+		id = DPLL_ID_SKL_DPLL1;
 		break;
 	case PORT_C:
 		pipe_config->ddi_pll_sel = SKL_DPLL2;
-		pipe_config->shared_dpll = DPLL_ID_SKL_DPLL3;
+		id = DPLL_ID_SKL_DPLL2;
 		break;
 	default:
 		DRM_ERROR("Incorrect port type\n");
+		return;
 	}
+
+	pipe_config->shared_dpll = intel_get_shared_dpll_by_id(dev_priv, id);
 }
 
 static void skylake_get_ddi_pll(struct drm_i915_private *dev_priv,
 				enum port port,
 				struct intel_crtc_state *pipe_config)
 {
-	u32 temp, dpll_ctl1;
+	enum intel_dpll_id id;
+	u32 temp;
 
 	temp = I915_READ(DPLL_CTRL2) & DPLL_CTRL2_DDI_CLK_SEL_MASK(port);
 	pipe_config->ddi_pll_sel = temp >> (port * 3 + 1);
 
 	switch (pipe_config->ddi_pll_sel) {
 	case SKL_DPLL0:
-		/*
-		 * On SKL the eDP DPLL (DPLL0 as we don't use SSC) is not part
-		 * of the shared DPLL framework and thus needs to be read out
-		 * separately
-		 */
-		dpll_ctl1 = I915_READ(DPLL_CTRL1);
-		pipe_config->dpll_hw_state.ctrl1 = dpll_ctl1 & 0x3f;
+		id = DPLL_ID_SKL_DPLL0;
 		break;
 	case SKL_DPLL1:
-		pipe_config->shared_dpll = DPLL_ID_SKL_DPLL1;
+		id = DPLL_ID_SKL_DPLL1;
 		break;
 	case SKL_DPLL2:
-		pipe_config->shared_dpll = DPLL_ID_SKL_DPLL2;
+		id = DPLL_ID_SKL_DPLL2;
 		break;
 	case SKL_DPLL3:
-		pipe_config->shared_dpll = DPLL_ID_SKL_DPLL3;
+		id = DPLL_ID_SKL_DPLL3;
 		break;
+	default:
+		MISSING_CASE(pipe_config->ddi_pll_sel);
+		return;
 	}
+
+	pipe_config->shared_dpll = intel_get_shared_dpll_by_id(dev_priv, id);
 }
 
 static void haswell_get_ddi_pll(struct drm_i915_private *dev_priv,
 				enum port port,
 				struct intel_crtc_state *pipe_config)
 {
+	enum intel_dpll_id id;
+
 	pipe_config->ddi_pll_sel = I915_READ(PORT_CLK_SEL(port));
 
 	switch (pipe_config->ddi_pll_sel) {
 	case PORT_CLK_SEL_WRPLL1:
-		pipe_config->shared_dpll = DPLL_ID_WRPLL1;
+		id = DPLL_ID_WRPLL1;
 		break;
 	case PORT_CLK_SEL_WRPLL2:
-		pipe_config->shared_dpll = DPLL_ID_WRPLL2;
+		id = DPLL_ID_WRPLL2;
 		break;
 	case PORT_CLK_SEL_SPLL:
-		pipe_config->shared_dpll = DPLL_ID_SPLL;
+		id = DPLL_ID_SPLL;
+		break;
+	case PORT_CLK_SEL_LCPLL_810:
+		id = DPLL_ID_LCPLL_810;
+		break;
+	case PORT_CLK_SEL_LCPLL_1350:
+		id = DPLL_ID_LCPLL_1350;
+		break;
+	case PORT_CLK_SEL_LCPLL_2700:
+		id = DPLL_ID_LCPLL_2700;
+		break;
+	default:
+		MISSING_CASE(pipe_config->ddi_pll_sel);
+		/* fall through */
+	case PORT_CLK_SEL_NONE:
+		return;
+	}
+
+	pipe_config->shared_dpll = intel_get_shared_dpll_by_id(dev_priv, id);
+}
+
+static bool hsw_get_transcoder_state(struct intel_crtc *crtc,
+				     struct intel_crtc_state *pipe_config,
+				     unsigned long *power_domain_mask)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	enum intel_display_power_domain power_domain;
+	u32 tmp;
+
+	pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe;
+
+	/*
+	 * XXX: Do intel_display_power_get_if_enabled before reading this (for
+	 * consistency and less surprising code; it's in always on power).
+	 */
+	tmp = I915_READ(TRANS_DDI_FUNC_CTL(TRANSCODER_EDP));
+	if (tmp & TRANS_DDI_FUNC_ENABLE) {
+		enum pipe trans_edp_pipe;
+		switch (tmp & TRANS_DDI_EDP_INPUT_MASK) {
+		default:
+			WARN(1, "unknown pipe linked to edp transcoder\n");
+		case TRANS_DDI_EDP_INPUT_A_ONOFF:
+		case TRANS_DDI_EDP_INPUT_A_ON:
+			trans_edp_pipe = PIPE_A;
+			break;
+		case TRANS_DDI_EDP_INPUT_B_ONOFF:
+			trans_edp_pipe = PIPE_B;
+			break;
+		case TRANS_DDI_EDP_INPUT_C_ONOFF:
+			trans_edp_pipe = PIPE_C;
+			break;
+		}
+
+		if (trans_edp_pipe == crtc->pipe)
+			pipe_config->cpu_transcoder = TRANSCODER_EDP;
+	}
+
+	power_domain = POWER_DOMAIN_TRANSCODER(pipe_config->cpu_transcoder);
+	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+		return false;
+	*power_domain_mask |= BIT(power_domain);
+
+	tmp = I915_READ(PIPECONF(pipe_config->cpu_transcoder));
+
+	return tmp & PIPECONF_ENABLE;
+}
+
+static bool bxt_get_dsi_transcoder_state(struct intel_crtc *crtc,
+					 struct intel_crtc_state *pipe_config,
+					 unsigned long *power_domain_mask)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	enum intel_display_power_domain power_domain;
+	enum port port;
+	enum transcoder cpu_transcoder;
+	u32 tmp;
+
+	pipe_config->has_dsi_encoder = false;
+
+	for_each_port_masked(port, BIT(PORT_A) | BIT(PORT_C)) {
+		if (port == PORT_A)
+			cpu_transcoder = TRANSCODER_DSI_A;
+		else
+			cpu_transcoder = TRANSCODER_DSI_C;
+
+		power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder);
+		if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+			continue;
+		*power_domain_mask |= BIT(power_domain);
+
+		/*
+		 * The PLL needs to be enabled with a valid divider
+		 * configuration, otherwise accessing DSI registers will hang
+		 * the machine. See BSpec North Display Engine
+		 * registers/MIPI[BXT]. We can break out here early, since we
+		 * need the same DSI PLL to be enabled for both DSI ports.
+		 */
+		if (!intel_dsi_pll_is_enabled(dev_priv))
+			break;
+
+		/* XXX: this works for video mode only */
+		tmp = I915_READ(BXT_MIPI_PORT_CTRL(port));
+		if (!(tmp & DPI_ENABLE))
+			continue;
+
+		tmp = I915_READ(MIPI_CTRL(port));
+		if ((tmp & BXT_PIPE_SELECT_MASK) != BXT_PIPE_SELECT(crtc->pipe))
+			continue;
+
+		pipe_config->cpu_transcoder = cpu_transcoder;
+		pipe_config->has_dsi_encoder = true;
 		break;
 	}
+
+	return pipe_config->has_dsi_encoder;
 }
 
 static void haswell_get_ddi_port_state(struct intel_crtc *crtc,
@@ -9909,11 +9979,10 @@ static void haswell_get_ddi_port_state(s
 	else
 		haswell_get_ddi_pll(dev_priv, port, pipe_config);
 
-	if (pipe_config->shared_dpll >= 0) {
-		pll = &dev_priv->shared_dplls[pipe_config->shared_dpll];
-
-		WARN_ON(!pll->get_hw_state(dev_priv, pll,
-					   &pipe_config->dpll_hw_state));
+	pll = pipe_config->shared_dpll;
+	if (pll) {
+		WARN_ON(!pll->funcs.get_hw_state(dev_priv, pll,
+						 &pipe_config->dpll_hw_state));
 	}
 
 	/*
@@ -9940,53 +10009,37 @@ static bool haswell_get_pipe_config(stru
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	enum intel_display_power_domain power_domain;
 	unsigned long power_domain_mask;
-	uint32_t tmp;
-	bool ret;
+	bool active;
 
 	power_domain = POWER_DOMAIN_PIPE(crtc->pipe);
 	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
 		return false;
 	power_domain_mask = BIT(power_domain);
 
-	ret = false;
-
-	pipe_config->cpu_transcoder = (enum transcoder) crtc->pipe;
-	pipe_config->shared_dpll = DPLL_ID_PRIVATE;
+	pipe_config->shared_dpll = NULL;
 
-	tmp = I915_READ(TRANS_DDI_FUNC_CTL(TRANSCODER_EDP));
-	if (tmp & TRANS_DDI_FUNC_ENABLE) {
-		enum pipe trans_edp_pipe;
-		switch (tmp & TRANS_DDI_EDP_INPUT_MASK) {
-		default:
-			WARN(1, "unknown pipe linked to edp transcoder\n");
-		case TRANS_DDI_EDP_INPUT_A_ONOFF:
-		case TRANS_DDI_EDP_INPUT_A_ON:
-			trans_edp_pipe = PIPE_A;
-			break;
-		case TRANS_DDI_EDP_INPUT_B_ONOFF:
-			trans_edp_pipe = PIPE_B;
-			break;
-		case TRANS_DDI_EDP_INPUT_C_ONOFF:
-			trans_edp_pipe = PIPE_C;
-			break;
-		}
+	active = hsw_get_transcoder_state(crtc, pipe_config, &power_domain_mask);
 
-		if (trans_edp_pipe == crtc->pipe)
-			pipe_config->cpu_transcoder = TRANSCODER_EDP;
+	if (IS_BROXTON(dev_priv)) {
+		bxt_get_dsi_transcoder_state(crtc, pipe_config,
+					     &power_domain_mask);
+		WARN_ON(active && pipe_config->has_dsi_encoder);
+		if (pipe_config->has_dsi_encoder)
+			active = true;
 	}
 
-	power_domain = POWER_DOMAIN_TRANSCODER(pipe_config->cpu_transcoder);
-	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
+	if (!active)
 		goto out;
-	power_domain_mask |= BIT(power_domain);
 
-	tmp = I915_READ(PIPECONF(pipe_config->cpu_transcoder));
-	if (!(tmp & PIPECONF_ENABLE))
-		goto out;
+	if (!pipe_config->has_dsi_encoder) {
+		haswell_get_ddi_port_state(crtc, pipe_config);
+		intel_get_pipe_timings(crtc, pipe_config);
+	}
 
-	haswell_get_ddi_port_state(crtc, pipe_config);
+	intel_get_pipe_src_size(crtc, pipe_config);
 
-	intel_get_pipe_timings(crtc, pipe_config);
+	pipe_config->gamma_mode =
+		I915_READ(GAMMA_MODE(crtc->pipe)) & GAMMA_MODE_MODE_MASK;
 
 	if (INTEL_INFO(dev)->gen >= 9) {
 		skl_init_scalers(dev, crtc, pipe_config);
@@ -10010,20 +10063,19 @@ static bool haswell_get_pipe_config(stru
 		pipe_config->ips_enabled = hsw_crtc_supports_ips(crtc) &&
 			(I915_READ(IPS_CTL) & IPS_ENABLE);
 
-	if (pipe_config->cpu_transcoder != TRANSCODER_EDP) {
+	if (pipe_config->cpu_transcoder != TRANSCODER_EDP &&
+	    !transcoder_is_dsi(pipe_config->cpu_transcoder)) {
 		pipe_config->pixel_multiplier =
 			I915_READ(PIPE_MULT(pipe_config->cpu_transcoder)) + 1;
 	} else {
 		pipe_config->pixel_multiplier = 1;
 	}
 
-	ret = true;
-
 out:
 	for_each_power_domain(power_domain, power_domain_mask)
 		intel_display_power_put(dev_priv, power_domain);
 
-	return ret;
+	return active;
 }
 
 static void i845_update_cursor(struct drm_crtc *crtc, u32 base,
@@ -10216,21 +10268,6 @@ static bool cursor_size_ok(struct drm_de
 	return true;
 }
 
-static void intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
-				 u16 *blue, uint32_t start, uint32_t size)
-{
-	int end = (start + size > 256) ? 256 : start + size, i;
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-
-	for (i = start; i < end; i++) {
-		intel_crtc->lut_r[i] = red[i] >> 8;
-		intel_crtc->lut_g[i] = green[i] >> 8;
-		intel_crtc->lut_b[i] = blue[i] >> 8;
-	}
-
-	intel_crtc_load_lut(crtc);
-}
-
 /* VESA 640x480x72Hz mode to set on the pipe */
 static struct drm_display_mode load_detect_mode = {
 	DRM_MODE("640x480", DRM_MODE_TYPE_DEFAULT, 31500, 640, 664,
@@ -10718,19 +10755,18 @@ int intel_dotclock_calculate(int link_fr
 static void ironlake_pch_clock_get(struct intel_crtc *crtc,
 				   struct intel_crtc_state *pipe_config)
 {
-	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 
 	/* read out port_clock from the DPLL */
 	i9xx_crtc_clock_get(crtc, pipe_config);
 
 	/*
-	 * This value does not include pixel_multiplier.
-	 * We will check that port_clock and adjusted_mode.crtc_clock
-	 * agree once we know their relationship in the encoder's
-	 * get_config() function.
+	 * In case there is an active pipe without active ports,
+	 * we may need some idea for the dotclock anyway.
+	 * Calculate one based on the FDI configuration.
 	 */
 	pipe_config->base.adjusted_mode.crtc_clock =
-		intel_dotclock_calculate(intel_fdi_link_freq(dev) * 10000,
+		intel_dotclock_calculate(intel_fdi_link_freq(dev_priv, pipe_config),
 					 &pipe_config->fdi_m_n);
 }
 
@@ -10849,7 +10885,7 @@ static void intel_unpin_work_fn(struct w
 	struct drm_plane *primary = crtc->base.primary;
 
 	mutex_lock(&dev->struct_mutex);
-	intel_unpin_fb_obj(work->old_fb, primary->state);
+	intel_unpin_fb_obj(work->old_fb, primary->state->rotation);
 	drm_gem_object_unreference(&work->pending_flip_obj->base);
 
 	if (work->flip_queued_req)
@@ -10923,9 +10959,10 @@ static bool page_flip_finished(struct in
 {
 	struct drm_device *dev = crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	unsigned reset_counter;
 
-	if (i915_reset_in_progress(&dev_priv->gpu_error) ||
-	    crtc->reset_counter != atomic_read(&dev_priv->gpu_error.reset_counter))
+	reset_counter = i915_reset_counter(&dev_priv->gpu_error);
+	if (crtc->reset_counter != reset_counter)
 		return true;
 
 	/*
@@ -11003,7 +11040,7 @@ static int intel_gen2_queue_flip(struct
 				 struct drm_i915_gem_request *req,
 				 uint32_t flags)
 {
-	struct intel_engine_cs *ring = req->ring;
+	struct intel_engine_cs *engine = req->engine;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	u32 flip_mask;
 	int ret;
@@ -11019,13 +11056,13 @@ static int intel_gen2_queue_flip(struct
 		flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
 	else
 		flip_mask = MI_WAIT_FOR_PLANE_A_FLIP;
-	intel_ring_emit(ring, MI_WAIT_FOR_EVENT | flip_mask);
-	intel_ring_emit(ring, MI_NOOP);
-	intel_ring_emit(ring, MI_DISPLAY_FLIP |
+	intel_ring_emit(engine, MI_WAIT_FOR_EVENT | flip_mask);
+	intel_ring_emit(engine, MI_NOOP);
+	intel_ring_emit(engine, MI_DISPLAY_FLIP |
 			MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
-	intel_ring_emit(ring, fb->pitches[0]);
-	intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset);
-	intel_ring_emit(ring, 0); /* aux display base address, unused */
+	intel_ring_emit(engine, fb->pitches[0]);
+	intel_ring_emit(engine, intel_crtc->unpin_work->gtt_offset);
+	intel_ring_emit(engine, 0); /* aux display base address, unused */
 
 	intel_mark_page_flip_active(intel_crtc->unpin_work);
 	return 0;
@@ -11038,7 +11075,7 @@ static int intel_gen3_queue_flip(struct
 				 struct drm_i915_gem_request *req,
 				 uint32_t flags)
 {
-	struct intel_engine_cs *ring = req->ring;
+	struct intel_engine_cs *engine = req->engine;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	u32 flip_mask;
 	int ret;
@@ -11051,13 +11088,13 @@ static int intel_gen3_queue_flip(struct
 		flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
 	else
 		flip_mask = MI_WAIT_FOR_PLANE_A_FLIP;
-	intel_ring_emit(ring, MI_WAIT_FOR_EVENT | flip_mask);
-	intel_ring_emit(ring, MI_NOOP);
-	intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 |
+	intel_ring_emit(engine, MI_WAIT_FOR_EVENT | flip_mask);
+	intel_ring_emit(engine, MI_NOOP);
+	intel_ring_emit(engine, MI_DISPLAY_FLIP_I915 |
 			MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
-	intel_ring_emit(ring, fb->pitches[0]);
-	intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset);
-	intel_ring_emit(ring, MI_NOOP);
+	intel_ring_emit(engine, fb->pitches[0]);
+	intel_ring_emit(engine, intel_crtc->unpin_work->gtt_offset);
+	intel_ring_emit(engine, MI_NOOP);
 
 	intel_mark_page_flip_active(intel_crtc->unpin_work);
 	return 0;
@@ -11070,7 +11107,7 @@ static int intel_gen4_queue_flip(struct
 				 struct drm_i915_gem_request *req,
 				 uint32_t flags)
 {
-	struct intel_engine_cs *ring = req->ring;
+	struct intel_engine_cs *engine = req->engine;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	uint32_t pf, pipesrc;
@@ -11084,10 +11121,10 @@ static int intel_gen4_queue_flip(struct
 	 * Display Registers (which do not change across a page-flip)
 	 * so we need only reprogram the base address.
 	 */
-	intel_ring_emit(ring, MI_DISPLAY_FLIP |
+	intel_ring_emit(engine, MI_DISPLAY_FLIP |
 			MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
-	intel_ring_emit(ring, fb->pitches[0]);
-	intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset |
+	intel_ring_emit(engine, fb->pitches[0]);
+	intel_ring_emit(engine, intel_crtc->unpin_work->gtt_offset |
 			obj->tiling_mode);
 
 	/* XXX Enabling the panel-fitter across page-flip is so far
@@ -11096,7 +11133,7 @@ static int intel_gen4_queue_flip(struct
 	 */
 	pf = 0;
 	pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff;
-	intel_ring_emit(ring, pf | pipesrc);
+	intel_ring_emit(engine, pf | pipesrc);
 
 	intel_mark_page_flip_active(intel_crtc->unpin_work);
 	return 0;
@@ -11109,7 +11146,7 @@ static int intel_gen6_queue_flip(struct
 				 struct drm_i915_gem_request *req,
 				 uint32_t flags)
 {
-	struct intel_engine_cs *ring = req->ring;
+	struct intel_engine_cs *engine = req->engine;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	uint32_t pf, pipesrc;
@@ -11119,10 +11156,10 @@ static int intel_gen6_queue_flip(struct
 	if (ret)
 		return ret;
 
-	intel_ring_emit(ring, MI_DISPLAY_FLIP |
+	intel_ring_emit(engine, MI_DISPLAY_FLIP |
 			MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
-	intel_ring_emit(ring, fb->pitches[0] | obj->tiling_mode);
-	intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset);
+	intel_ring_emit(engine, fb->pitches[0] | obj->tiling_mode);
+	intel_ring_emit(engine, intel_crtc->unpin_work->gtt_offset);
 
 	/* Contrary to the suggestions in the documentation,
 	 * "Enable Panel Fitter" does not seem to be required when page
@@ -11132,7 +11169,7 @@ static int intel_gen6_queue_flip(struct
 	 */
 	pf = 0;
 	pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff;
-	intel_ring_emit(ring, pf | pipesrc);
+	intel_ring_emit(engine, pf | pipesrc);
 
 	intel_mark_page_flip_active(intel_crtc->unpin_work);
 	return 0;
@@ -11145,7 +11182,7 @@ static int intel_gen7_queue_flip(struct
 				 struct drm_i915_gem_request *req,
 				 uint32_t flags)
 {
-	struct intel_engine_cs *ring = req->ring;
+	struct intel_engine_cs *engine = req->engine;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	uint32_t plane_bit = 0;
 	int len, ret;
@@ -11166,7 +11203,7 @@ static int intel_gen7_queue_flip(struct
 	}
 
 	len = 4;
-	if (ring->id == RCS) {
+	if (engine->id == RCS) {
 		len += 6;
 		/*
 		 * On Gen 8, SRM is now taking an extra dword to accommodate
@@ -11204,36 +11241,36 @@ static int intel_gen7_queue_flip(struct
 	 * for the RCS also doesn't appear to drop events. Setting the DERRMR
 	 * to zero does lead to lockups within MI_DISPLAY_FLIP.
 	 */
-	if (ring->id == RCS) {
-		intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
-		intel_ring_emit_reg(ring, DERRMR);
-		intel_ring_emit(ring, ~(DERRMR_PIPEA_PRI_FLIP_DONE |
-					DERRMR_PIPEB_PRI_FLIP_DONE |
-					DERRMR_PIPEC_PRI_FLIP_DONE));
+	if (engine->id == RCS) {
+		intel_ring_emit(engine, MI_LOAD_REGISTER_IMM(1));
+		intel_ring_emit_reg(engine, DERRMR);
+		intel_ring_emit(engine, ~(DERRMR_PIPEA_PRI_FLIP_DONE |
+					  DERRMR_PIPEB_PRI_FLIP_DONE |
+					  DERRMR_PIPEC_PRI_FLIP_DONE));
 		if (IS_GEN8(dev))
-			intel_ring_emit(ring, MI_STORE_REGISTER_MEM_GEN8 |
+			intel_ring_emit(engine, MI_STORE_REGISTER_MEM_GEN8 |
 					      MI_SRM_LRM_GLOBAL_GTT);
 		else
-			intel_ring_emit(ring, MI_STORE_REGISTER_MEM |
+			intel_ring_emit(engine, MI_STORE_REGISTER_MEM |
 					      MI_SRM_LRM_GLOBAL_GTT);
-		intel_ring_emit_reg(ring, DERRMR);
-		intel_ring_emit(ring, ring->scratch.gtt_offset + 256);
+		intel_ring_emit_reg(engine, DERRMR);
+		intel_ring_emit(engine, engine->scratch.gtt_offset + 256);
 		if (IS_GEN8(dev)) {
-			intel_ring_emit(ring, 0);
-			intel_ring_emit(ring, MI_NOOP);
+			intel_ring_emit(engine, 0);
+			intel_ring_emit(engine, MI_NOOP);
 		}
 	}
 
-	intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | plane_bit);
-	intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode));
-	intel_ring_emit(ring, intel_crtc->unpin_work->gtt_offset);
-	intel_ring_emit(ring, (MI_NOOP));
+	intel_ring_emit(engine, MI_DISPLAY_FLIP_I915 | plane_bit);
+	intel_ring_emit(engine, (fb->pitches[0] | obj->tiling_mode));
+	intel_ring_emit(engine, intel_crtc->unpin_work->gtt_offset);
+	intel_ring_emit(engine, (MI_NOOP));
 
 	intel_mark_page_flip_active(intel_crtc->unpin_work);
 	return 0;
 }
 
-static bool use_mmio_flip(struct intel_engine_cs *ring,
+static bool use_mmio_flip(struct intel_engine_cs *engine,
 			  struct drm_i915_gem_object *obj)
 {
 	/*
@@ -11244,10 +11281,10 @@ static bool use_mmio_flip(struct intel_e
 	 * So using MMIO flips there would disrupt this mechanism.
 	 */
 
-	if (ring == NULL)
+	if (engine == NULL)
 		return true;
 
-	if (INTEL_INFO(ring->dev)->gen < 5)
+	if (INTEL_INFO(engine->dev)->gen < 5)
 		return false;
 
 	if (i915.use_mmio_flip < 0)
@@ -11261,7 +11298,7 @@ static bool use_mmio_flip(struct intel_e
 						       false))
 		return true;
 	else
-		return ring != i915_gem_request_get_ring(obj->last_write_req);
+		return engine != i915_gem_request_get_engine(obj->last_write_req);
 }
 
 static void skl_do_mmio_flip(struct intel_crtc *intel_crtc,
@@ -11379,7 +11416,6 @@ static void intel_mmio_flip_work_func(st
 
 	if (mmio_flip->req) {
 		WARN_ON(__i915_wait_request(mmio_flip->req,
-					    mmio_flip->crtc->reset_counter,
 					    false, NULL,
 					    &mmio_flip->i915->rps.mmioflips));
 		i915_gem_request_unreference__unlocked(mmio_flip->req);
@@ -11507,7 +11543,7 @@ static int intel_crtc_page_flip(struct d
 	struct drm_plane *primary = crtc->primary;
 	enum pipe pipe = intel_crtc->pipe;
 	struct intel_unpin_work *work;
-	struct intel_engine_cs *ring;
+	struct intel_engine_cs *engine;
 	bool mmio_flip;
 	struct drm_i915_gem_request *request = NULL;
 	int ret;
@@ -11587,28 +11623,33 @@ static int intel_crtc_page_flip(struct d
 	if (ret)
 		goto cleanup;
 
+	intel_crtc->reset_counter = i915_reset_counter(&dev_priv->gpu_error);
+	if (__i915_reset_in_progress_or_wedged(intel_crtc->reset_counter)) {
+		ret = -EIO;
+		goto cleanup;
+	}
+
 	atomic_inc(&intel_crtc->unpin_work_count);
-	intel_crtc->reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter);
 
 	if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev))
 		work->flip_count = I915_READ(PIPE_FLIPCOUNT_G4X(pipe)) + 1;
 
 	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
-		ring = &dev_priv->ring[BCS];
+		engine = &dev_priv->engine[BCS];
 		if (obj->tiling_mode != intel_fb_obj(work->old_fb)->tiling_mode)
 			/* vlv: DISPLAY_FLIP fails to change tiling */
-			ring = NULL;
+			engine = NULL;
 	} else if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) {
-		ring = &dev_priv->ring[BCS];
+		engine = &dev_priv->engine[BCS];
 	} else if (INTEL_INFO(dev)->gen >= 7) {
-		ring = i915_gem_request_get_ring(obj->last_write_req);
-		if (ring == NULL || ring->id != RCS)
-			ring = &dev_priv->ring[BCS];
+		engine = i915_gem_request_get_engine(obj->last_write_req);
+		if (engine == NULL || engine->id != RCS)
+			engine = &dev_priv->engine[BCS];
 	} else {
-		ring = &dev_priv->ring[RCS];
+		engine = &dev_priv->engine[RCS];
 	}
 
-	mmio_flip = use_mmio_flip(ring, obj);
+	mmio_flip = use_mmio_flip(engine, obj);
 
 	/* When using CS flips, we want to emit semaphores between rings.
 	 * However, when using mmio flips we will create a task to do the
@@ -11616,13 +11657,12 @@ static int intel_crtc_page_flip(struct d
 	 * into the display plane and skip any waits.
 	 */
 	if (!mmio_flip) {
-		ret = i915_gem_object_sync(obj, ring, &request);
+		ret = i915_gem_object_sync(obj, engine, &request);
 		if (ret)
 			goto cleanup_pending;
 	}
 
-	ret = intel_pin_and_fence_fb_obj(crtc->primary, fb,
-					 crtc->primary->state);
+	ret = intel_pin_and_fence_fb_obj(fb, primary->state->rotation);
 	if (ret)
 		goto cleanup_pending;
 
@@ -11639,7 +11679,7 @@ static int intel_crtc_page_flip(struct d
 					obj->last_write_req);
 	} else {
 		if (!request) {
-			request = i915_gem_request_alloc(ring, NULL);
+			request = i915_gem_request_alloc(engine, NULL);
 			if (IS_ERR(request)) {
 				ret = PTR_ERR(request);
 				goto cleanup_unpin;
@@ -11672,10 +11712,10 @@ static int intel_crtc_page_flip(struct d
 	return 0;
 
 cleanup_unpin:
-	intel_unpin_fb_obj(fb, crtc->primary->state);
+	intel_unpin_fb_obj(fb, crtc->primary->state->rotation);
 cleanup_pending:
 	if (!IS_ERR_OR_NULL(request))
-		i915_gem_request_cancel(request);
+		i915_add_request_no_flush(request);
 	atomic_dec(&intel_crtc->unpin_work_count);
 	mutex_unlock(&dev->struct_mutex);
 cleanup:
@@ -11725,7 +11765,7 @@ retry:
 
 		if (ret == 0 && event) {
 			spin_lock_irq(&dev->event_lock);
-			drm_send_vblank_event(dev, pipe, event);
+			drm_crtc_send_vblank_event(crtc, event);
 			spin_unlock_irq(&dev->event_lock);
 		}
 	}
@@ -11785,6 +11825,7 @@ int intel_plane_atomic_calc_changes(stru
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct drm_plane *plane = plane_state->plane;
 	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct intel_plane_state *old_plane_state =
 		to_intel_plane_state(plane->state);
 	int idx = intel_crtc->base.base.id, ret;
@@ -11833,42 +11874,43 @@ int intel_plane_atomic_calc_changes(stru
 			 plane->base.id, was_visible, visible,
 			 turn_off, turn_on, mode_changed);
 
-	if (turn_on || turn_off) {
-		pipe_config->wm_changed = true;
+	if (turn_on) {
+		pipe_config->update_wm_pre = true;
+
+		/* must disable cxsr around plane enable/disable */
+		if (plane->type != DRM_PLANE_TYPE_CURSOR)
+			pipe_config->disable_cxsr = true;
+	} else if (turn_off) {
+		pipe_config->update_wm_post = true;
 
 		/* must disable cxsr around plane enable/disable */
 		if (plane->type != DRM_PLANE_TYPE_CURSOR)
 			pipe_config->disable_cxsr = true;
 	} else if (intel_wm_need_update(plane, plane_state)) {
-		pipe_config->wm_changed = true;
+		/* FIXME bollocks */
+		pipe_config->update_wm_pre = true;
+		pipe_config->update_wm_post = true;
 	}
 
-	if (visible || was_visible)
-		intel_crtc->atomic.fb_bits |=
-			to_intel_plane(plane)->frontbuffer_bit;
+	/* Pre-gen9 platforms need two-step watermark updates */
+	if ((pipe_config->update_wm_pre || pipe_config->update_wm_post) &&
+	    INTEL_INFO(dev)->gen < 9 && dev_priv->display.optimize_watermarks)
+		to_intel_crtc_state(crtc_state)->wm.need_postvbl_update = true;
 
-	switch (plane->type) {
-	case DRM_PLANE_TYPE_PRIMARY:
-		intel_crtc->atomic.post_enable_primary = turn_on;
-		intel_crtc->atomic.update_fbc = true;
+	if (visible || was_visible)
+		pipe_config->fb_bits |= to_intel_plane(plane)->frontbuffer_bit;
 
-		break;
-	case DRM_PLANE_TYPE_CURSOR:
-		break;
-	case DRM_PLANE_TYPE_OVERLAY:
-		/*
-		 * WaCxSRDisabledForSpriteScaling:ivb
-		 *
-		 * cstate->update_wm was already set above, so this flag will
-		 * take effect when we commit and program watermarks.
-		 */
-		if (IS_IVYBRIDGE(dev) &&
-		    needs_scaling(to_intel_plane_state(plane_state)) &&
-		    !needs_scaling(old_plane_state))
-			pipe_config->disable_lp_wm = true;
+	/*
+	 * WaCxSRDisabledForSpriteScaling:ivb
+	 *
+	 * cstate->update_wm was already set above, so this flag will
+	 * take effect when we commit and program watermarks.
+	 */
+	if (plane->type == DRM_PLANE_TYPE_OVERLAY && IS_IVYBRIDGE(dev) &&
+	    needs_scaling(to_intel_plane_state(plane_state)) &&
+	    !needs_scaling(old_plane_state))
+		pipe_config->disable_lp_wm = true;
 
-		break;
-	}
 	return 0;
 }
 
@@ -11940,22 +11982,58 @@ static int intel_crtc_atomic_check(struc
 	}
 
 	if (mode_changed && !crtc_state->active)
-		pipe_config->wm_changed = true;
+		pipe_config->update_wm_post = true;
 
 	if (mode_changed && crtc_state->enable &&
 	    dev_priv->display.crtc_compute_clock &&
-	    !WARN_ON(pipe_config->shared_dpll != DPLL_ID_PRIVATE)) {
+	    !WARN_ON(pipe_config->shared_dpll)) {
 		ret = dev_priv->display.crtc_compute_clock(intel_crtc,
 							   pipe_config);
 		if (ret)
 			return ret;
 	}
 
+	if (crtc_state->color_mgmt_changed) {
+		ret = intel_color_check(crtc, crtc_state);
+		if (ret)
+			return ret;
+
+		/*
+		 * Changing color management on Intel hardware is
+		 * handled as part of planes update.
+		 */
+		crtc_state->planes_changed = true;
+	}
+
 	ret = 0;
 	if (dev_priv->display.compute_pipe_wm) {
-		ret = dev_priv->display.compute_pipe_wm(intel_crtc, state);
-		if (ret)
+		ret = dev_priv->display.compute_pipe_wm(pipe_config);
+		if (ret) {
+			DRM_DEBUG_KMS("Target pipe watermarks are invalid\n");
+			return ret;
+		}
+	}
+
+	if (dev_priv->display.compute_intermediate_wm &&
+	    !to_intel_atomic_state(state)->skip_intermediate_wm) {
+		if (WARN_ON(!dev_priv->display.compute_pipe_wm))
+			return 0;
+
+		/*
+		 * Calculate 'intermediate' watermarks that satisfy both the
+		 * old state and the new state.  We can program these
+		 * immediately.
+		 */
+		ret = dev_priv->display.compute_intermediate_wm(crtc->dev,
+								intel_crtc,
+								pipe_config);
+		if (ret) {
+			DRM_DEBUG_KMS("No valid intermediate pipe watermarks are possible\n");
 			return ret;
+		}
+	} else if (dev_priv->display.compute_intermediate_wm) {
+		if (HAS_PCH_SPLIT(dev_priv) && INTEL_GEN(dev_priv) < 9)
+			pipe_config->wm.intermediate = pipe_config->wm.optimal.ilk;
 	}
 
 	if (INTEL_INFO(dev)->gen >= 9) {
@@ -11972,7 +12050,6 @@ static int intel_crtc_atomic_check(struc
 
 static const struct drm_crtc_helper_funcs intel_helper_funcs = {
 	.mode_set_base_atomic = intel_pipe_set_base_atomic,
-	.load_lut = intel_crtc_load_lut,
 	.atomic_begin = intel_begin_crtc_commit,
 	.atomic_flush = intel_finish_crtc_commit,
 	.atomic_check = intel_crtc_atomic_check,
@@ -11983,11 +12060,16 @@ static void intel_modeset_update_connect
 	struct intel_connector *connector;
 
 	for_each_intel_connector(dev, connector) {
+		if (connector->base.state->crtc)
+			drm_connector_unreference(&connector->base);
+
 		if (connector->base.encoder) {
 			connector->base.state->best_encoder =
 				connector->base.encoder;
 			connector->base.state->crtc =
 				connector->base.encoder->crtc;
+
+			drm_connector_reference(&connector->base);
 		} else {
 			connector->base.state->best_encoder = NULL;
 			connector->base.state->crtc = NULL;
@@ -12089,7 +12171,7 @@ static void intel_dump_pipe_config(struc
 	DRM_DEBUG_KMS("[CRTC:%d]%s config %p for pipe %c\n", crtc->base.base.id,
 		      context, pipe_config, pipe_name(crtc->pipe));
 
-	DRM_DEBUG_KMS("cpu_transcoder: %c\n", transcoder_name(pipe_config->cpu_transcoder));
+	DRM_DEBUG_KMS("cpu_transcoder: %s\n", transcoder_name(pipe_config->cpu_transcoder));
 	DRM_DEBUG_KMS("pipe bpp: %i, dithering: %i\n",
 		      pipe_config->pipe_bpp, pipe_config->dither);
 	DRM_DEBUG_KMS("fdi/pch: %i, lanes: %i, gmch_m: %u, gmch_n: %u, link_m: %u, link_n: %u, tu: %u\n",
@@ -12165,7 +12247,7 @@ static void intel_dump_pipe_config(struc
 			      pipe_config->dpll_hw_state.cfgcr1,
 			      pipe_config->dpll_hw_state.cfgcr2);
 	} else if (HAS_DDI(dev)) {
-		DRM_DEBUG_KMS("ddi_pll_sel: %u; dpll_hw_state: wrpll: 0x%x spll: 0x%x\n",
+		DRM_DEBUG_KMS("ddi_pll_sel: 0x%x; dpll_hw_state: wrpll: 0x%x spll: 0x%x\n",
 			      pipe_config->ddi_pll_sel,
 			      pipe_config->dpll_hw_state.wrpll,
 			      pipe_config->dpll_hw_state.spll);
@@ -12268,7 +12350,7 @@ clear_intel_crtc_state(struct intel_crtc
 	struct drm_crtc_state tmp_state;
 	struct intel_crtc_scaler_state scaler_state;
 	struct intel_dpll_hw_state dpll_hw_state;
-	enum intel_dpll_id shared_dpll;
+	struct intel_shared_dpll *shared_dpll;
 	uint32_t ddi_pll_sel;
 	bool force_thru;
 
@@ -12538,6 +12620,15 @@ intel_pipe_config_compare(struct drm_dev
 		ret = false; \
 	}
 
+#define PIPE_CONF_CHECK_P(name)	\
+	if (current_config->name != pipe_config->name) { \
+		INTEL_ERR_OR_DBG_KMS("mismatch in " #name " " \
+			  "(expected %p, found %p)\n", \
+			  current_config->name, \
+			  pipe_config->name); \
+		ret = false; \
+	}
+
 #define PIPE_CONF_CHECK_M_N(name) \
 	if (!intel_compare_link_m_n(&current_config->name, \
 				    &pipe_config->name,\
@@ -12558,6 +12649,11 @@ intel_pipe_config_compare(struct drm_dev
 		ret = false; \
 	}
 
+/* This is required for BDW+ where there is only one set of registers for
+ * switching between high and low RR.
+ * This macro can be used whenever a comparison has to be made between one
+ * hw state and multiple sw state variables.
+ */
 #define PIPE_CONF_CHECK_M_N_ALT(name, alt_name) \
 	if (!intel_compare_link_m_n(&current_config->name, \
 				    &pipe_config->name, adjust) && \
@@ -12585,22 +12681,6 @@ intel_pipe_config_compare(struct drm_dev
 		ret = false; \
 	}
 
-/* This is required for BDW+ where there is only one set of registers for
- * switching between high and low RR.
- * This macro can be used whenever a comparison has to be made between one
- * hw state and multiple sw state variables.
- */
-#define PIPE_CONF_CHECK_I_ALT(name, alt_name) \
-	if ((current_config->name != pipe_config->name) && \
-		(current_config->alt_name != pipe_config->name)) { \
-			INTEL_ERR_OR_DBG_KMS("mismatch in " #name " " \
-				  "(expected %i or %i, found %i)\n", \
-				  current_config->name, \
-				  current_config->alt_name, \
-				  pipe_config->name); \
-			ret = false; \
-	}
-
 #define PIPE_CONF_CHECK_FLAGS(name, mask)	\
 	if ((current_config->name ^ pipe_config->name) & (mask)) { \
 		INTEL_ERR_OR_DBG_KMS("mismatch in " #name "(" #mask ") " \
@@ -12681,7 +12761,7 @@ intel_pipe_config_compare(struct drm_dev
 	PIPE_CONF_CHECK_X(gmch_pfit.control);
 	/* pfit ratios are autocomputed by the hw on gen4+ */
 	if (INTEL_INFO(dev)->gen < 4)
-		PIPE_CONF_CHECK_I(gmch_pfit.pgm_ratios);
+		PIPE_CONF_CHECK_X(gmch_pfit.pgm_ratios);
 	PIPE_CONF_CHECK_X(gmch_pfit.lvds_border_bits);
 
 	if (!adjust) {
@@ -12705,7 +12785,7 @@ intel_pipe_config_compare(struct drm_dev
 
 	PIPE_CONF_CHECK_X(ddi_pll_sel);
 
-	PIPE_CONF_CHECK_I(shared_dpll);
+	PIPE_CONF_CHECK_P(shared_dpll);
 	PIPE_CONF_CHECK_X(dpll_hw_state.dpll);
 	PIPE_CONF_CHECK_X(dpll_hw_state.dpll_md);
 	PIPE_CONF_CHECK_X(dpll_hw_state.fp0);
@@ -12716,6 +12796,9 @@ intel_pipe_config_compare(struct drm_dev
 	PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr1);
 	PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr2);
 
+	PIPE_CONF_CHECK_X(dsi_pll.ctrl);
+	PIPE_CONF_CHECK_X(dsi_pll.div);
+
 	if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5)
 		PIPE_CONF_CHECK_I(pipe_bpp);
 
@@ -12724,7 +12807,7 @@ intel_pipe_config_compare(struct drm_dev
 
 #undef PIPE_CONF_CHECK_X
 #undef PIPE_CONF_CHECK_I
-#undef PIPE_CONF_CHECK_I_ALT
+#undef PIPE_CONF_CHECK_P
 #undef PIPE_CONF_CHECK_FLAGS
 #undef PIPE_CONF_CHECK_CLOCK_FUZZY
 #undef PIPE_CONF_QUIRK
@@ -12733,48 +12816,61 @@ intel_pipe_config_compare(struct drm_dev
 	return ret;
 }
 
-static void check_wm_state(struct drm_device *dev)
+static void intel_pipe_config_sanity_check(struct drm_i915_private *dev_priv,
+					   const struct intel_crtc_state *pipe_config)
 {
+	if (pipe_config->has_pch_encoder) {
+		int fdi_dotclock = intel_dotclock_calculate(intel_fdi_link_freq(dev_priv, pipe_config),
+							    &pipe_config->fdi_m_n);
+		int dotclock = pipe_config->base.adjusted_mode.crtc_clock;
+
+		/*
+		 * FDI already provided one idea for the dotclock.
+		 * Yell if the encoder disagrees.
+		 */
+		WARN(!intel_fuzzy_clock_check(fdi_dotclock, dotclock),
+		     "FDI dotclock and encoder dotclock mismatch, fdi: %i, encoder: %i\n",
+		     fdi_dotclock, dotclock);
+	}
+}
+
+static void verify_wm_state(struct drm_crtc *crtc,
+			    struct drm_crtc_state *new_state)
+{
+	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct skl_ddb_allocation hw_ddb, *sw_ddb;
-	struct intel_crtc *intel_crtc;
+	struct skl_ddb_entry *hw_entry, *sw_entry;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	const enum pipe pipe = intel_crtc->pipe;
 	int plane;
 
-	if (INTEL_INFO(dev)->gen < 9)
+	if (INTEL_INFO(dev)->gen < 9 || !new_state->active)
 		return;
 
 	skl_ddb_get_hw_state(dev_priv, &hw_ddb);
 	sw_ddb = &dev_priv->wm.skl_hw.ddb;
 
-	for_each_intel_crtc(dev, intel_crtc) {
-		struct skl_ddb_entry *hw_entry, *sw_entry;
-		const enum pipe pipe = intel_crtc->pipe;
+	/* planes */
+	for_each_plane(dev_priv, pipe, plane) {
+		hw_entry = &hw_ddb.plane[pipe][plane];
+		sw_entry = &sw_ddb->plane[pipe][plane];
 
-		if (!intel_crtc->active)
+		if (skl_ddb_entry_equal(hw_entry, sw_entry))
 			continue;
 
-		/* planes */
-		for_each_plane(dev_priv, pipe, plane) {
-			hw_entry = &hw_ddb.plane[pipe][plane];
-			sw_entry = &sw_ddb->plane[pipe][plane];
-
-			if (skl_ddb_entry_equal(hw_entry, sw_entry))
-				continue;
-
-			DRM_ERROR("mismatch in DDB state pipe %c plane %d "
-				  "(expected (%u,%u), found (%u,%u))\n",
-				  pipe_name(pipe), plane + 1,
-				  sw_entry->start, sw_entry->end,
-				  hw_entry->start, hw_entry->end);
-		}
-
-		/* cursor */
-		hw_entry = &hw_ddb.plane[pipe][PLANE_CURSOR];
-		sw_entry = &sw_ddb->plane[pipe][PLANE_CURSOR];
+		DRM_ERROR("mismatch in DDB state pipe %c plane %d "
+			  "(expected (%u,%u), found (%u,%u))\n",
+			  pipe_name(pipe), plane + 1,
+			  sw_entry->start, sw_entry->end,
+			  hw_entry->start, hw_entry->end);
+	}
 
-		if (skl_ddb_entry_equal(hw_entry, sw_entry))
-			continue;
+	/* cursor */
+	hw_entry = &hw_ddb.plane[pipe][PLANE_CURSOR];
+	sw_entry = &sw_ddb->plane[pipe][PLANE_CURSOR];
 
+	if (!skl_ddb_entry_equal(hw_entry, sw_entry)) {
 		DRM_ERROR("mismatch in DDB state pipe %c cursor "
 			  "(expected (%u,%u), found (%u,%u))\n",
 			  pipe_name(pipe),
@@ -12784,20 +12880,18 @@ static void check_wm_state(struct drm_de
 }
 
 static void
-check_connector_state(struct drm_device *dev,
-		      struct drm_atomic_state *old_state)
+verify_connector_state(struct drm_device *dev, struct drm_crtc *crtc)
 {
-	struct drm_connector_state *old_conn_state;
 	struct drm_connector *connector;
-	int i;
 
-	for_each_connector_in_state(old_state, connector, old_conn_state, i) {
+	drm_for_each_connector(connector, dev) {
 		struct drm_encoder *encoder = connector->encoder;
 		struct drm_connector_state *state = connector->state;
 
-		/* This also checks the encoder/connector hw state with the
-		 * ->get_hw_state callbacks. */
-		intel_connector_check_state(to_intel_connector(connector));
+		if (state->crtc != crtc)
+			continue;
+
+		intel_connector_verify_state(to_intel_connector(connector));
 
 		I915_STATE_WARN(state->best_encoder != encoder,
 		     "connector's atomic encoder doesn't match legacy encoder\n");
@@ -12805,7 +12899,7 @@ check_connector_state(struct drm_device
 }
 
 static void
-check_encoder_state(struct drm_device *dev)
+verify_encoder_state(struct drm_device *dev)
 {
 	struct intel_encoder *encoder;
 	struct intel_connector *connector;
@@ -12845,149 +12939,186 @@ check_encoder_state(struct drm_device *d
 }
 
 static void
-check_crtc_state(struct drm_device *dev, struct drm_atomic_state *old_state)
+verify_crtc_state(struct drm_crtc *crtc,
+		  struct drm_crtc_state *old_crtc_state,
+		  struct drm_crtc_state *new_crtc_state)
 {
+	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_encoder *encoder;
-	struct drm_crtc_state *old_crtc_state;
-	struct drm_crtc *crtc;
-	int i;
-
-	for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
-		struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-		struct intel_crtc_state *pipe_config, *sw_config;
-		bool active;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_crtc_state *pipe_config, *sw_config;
+	struct drm_atomic_state *old_state;
+	bool active;
 
-		if (!needs_modeset(crtc->state) &&
-		    !to_intel_crtc_state(crtc->state)->update_pipe)
-			continue;
+	old_state = old_crtc_state->state;
+	__drm_atomic_helper_crtc_destroy_state(old_crtc_state);
+	pipe_config = to_intel_crtc_state(old_crtc_state);
+	memset(pipe_config, 0, sizeof(*pipe_config));
+	pipe_config->base.crtc = crtc;
+	pipe_config->base.state = old_state;
 
-		__drm_atomic_helper_crtc_destroy_state(crtc, old_crtc_state);
-		pipe_config = to_intel_crtc_state(old_crtc_state);
-		memset(pipe_config, 0, sizeof(*pipe_config));
-		pipe_config->base.crtc = crtc;
-		pipe_config->base.state = old_state;
+	DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
 
-		DRM_DEBUG_KMS("[CRTC:%d]\n",
-			      crtc->base.id);
+	active = dev_priv->display.get_pipe_config(intel_crtc, pipe_config);
 
-		active = dev_priv->display.get_pipe_config(intel_crtc,
-							   pipe_config);
+	/* hw state is inconsistent with the pipe quirk */
+	if ((intel_crtc->pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) ||
+	    (intel_crtc->pipe == PIPE_B && dev_priv->quirks & QUIRK_PIPEB_FORCE))
+		active = new_crtc_state->active;
 
-		/* hw state is inconsistent with the pipe quirk */
-		if ((intel_crtc->pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) ||
-		    (intel_crtc->pipe == PIPE_B && dev_priv->quirks & QUIRK_PIPEB_FORCE))
-			active = crtc->state->active;
+	I915_STATE_WARN(new_crtc_state->active != active,
+	     "crtc active state doesn't match with hw state "
+	     "(expected %i, found %i)\n", new_crtc_state->active, active);
 
-		I915_STATE_WARN(crtc->state->active != active,
-		     "crtc active state doesn't match with hw state "
-		     "(expected %i, found %i)\n", crtc->state->active, active);
+	I915_STATE_WARN(intel_crtc->active != new_crtc_state->active,
+	     "transitional active state does not match atomic hw state "
+	     "(expected %i, found %i)\n", new_crtc_state->active, intel_crtc->active);
 
-		I915_STATE_WARN(intel_crtc->active != crtc->state->active,
-		     "transitional active state does not match atomic hw state "
-		     "(expected %i, found %i)\n", crtc->state->active, intel_crtc->active);
+	for_each_encoder_on_crtc(dev, crtc, encoder) {
+		enum pipe pipe;
 
-		for_each_encoder_on_crtc(dev, crtc, encoder) {
-			enum pipe pipe;
+		active = encoder->get_hw_state(encoder, &pipe);
+		I915_STATE_WARN(active != new_crtc_state->active,
+			"[ENCODER:%i] active %i with crtc active %i\n",
+			encoder->base.base.id, active, new_crtc_state->active);
 
-			active = encoder->get_hw_state(encoder, &pipe);
-			I915_STATE_WARN(active != crtc->state->active,
-				"[ENCODER:%i] active %i with crtc active %i\n",
-				encoder->base.base.id, active, crtc->state->active);
+		I915_STATE_WARN(active && intel_crtc->pipe != pipe,
+				"Encoder connected to wrong pipe %c\n",
+				pipe_name(pipe));
 
-			I915_STATE_WARN(active && intel_crtc->pipe != pipe,
-					"Encoder connected to wrong pipe %c\n",
-					pipe_name(pipe));
+		if (active)
+			encoder->get_config(encoder, pipe_config);
+	}
 
-			if (active)
-				encoder->get_config(encoder, pipe_config);
-		}
+	if (!new_crtc_state->active)
+		return;
 
-		if (!crtc->state->active)
-			continue;
+	intel_pipe_config_sanity_check(dev_priv, pipe_config);
 
-		sw_config = to_intel_crtc_state(crtc->state);
-		if (!intel_pipe_config_compare(dev, sw_config,
-					       pipe_config, false)) {
-			I915_STATE_WARN(1, "pipe state doesn't match!\n");
-			intel_dump_pipe_config(intel_crtc, pipe_config,
-					       "[hw state]");
-			intel_dump_pipe_config(intel_crtc, sw_config,
-					       "[sw state]");
-		}
+	sw_config = to_intel_crtc_state(crtc->state);
+	if (!intel_pipe_config_compare(dev, sw_config,
+				       pipe_config, false)) {
+		I915_STATE_WARN(1, "pipe state doesn't match!\n");
+		intel_dump_pipe_config(intel_crtc, pipe_config,
+				       "[hw state]");
+		intel_dump_pipe_config(intel_crtc, sw_config,
+				       "[sw state]");
 	}
 }
 
 static void
-check_shared_dpll_state(struct drm_device *dev)
+verify_single_dpll_state(struct drm_i915_private *dev_priv,
+			 struct intel_shared_dpll *pll,
+			 struct drm_crtc *crtc,
+			 struct drm_crtc_state *new_state)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_crtc *crtc;
 	struct intel_dpll_hw_state dpll_hw_state;
-	int i;
-
-	for (i = 0; i < dev_priv->num_shared_dpll; i++) {
-		struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i];
-		int enabled_crtcs = 0, active_crtcs = 0;
-		bool active;
+	unsigned crtc_mask;
+	bool active;
 
-		memset(&dpll_hw_state, 0, sizeof(dpll_hw_state));
+	memset(&dpll_hw_state, 0, sizeof(dpll_hw_state));
 
-		DRM_DEBUG_KMS("%s\n", pll->name);
+	DRM_DEBUG_KMS("%s\n", pll->name);
 
-		active = pll->get_hw_state(dev_priv, pll, &dpll_hw_state);
+	active = pll->funcs.get_hw_state(dev_priv, pll, &dpll_hw_state);
 
-		I915_STATE_WARN(pll->active > hweight32(pll->config.crtc_mask),
-		     "more active pll users than references: %i vs %i\n",
-		     pll->active, hweight32(pll->config.crtc_mask));
-		I915_STATE_WARN(pll->active && !pll->on,
+	if (!(pll->flags & INTEL_DPLL_ALWAYS_ON)) {
+		I915_STATE_WARN(!pll->on && pll->active_mask,
 		     "pll in active use but not on in sw tracking\n");
-		I915_STATE_WARN(pll->on && !pll->active,
-		     "pll in on but not on in use in sw tracking\n");
+		I915_STATE_WARN(pll->on && !pll->active_mask,
+		     "pll is on but not used by any active crtc\n");
 		I915_STATE_WARN(pll->on != active,
 		     "pll on state mismatch (expected %i, found %i)\n",
 		     pll->on, active);
+	}
 
-		for_each_intel_crtc(dev, crtc) {
-			if (crtc->base.state->enable && intel_crtc_to_shared_dpll(crtc) == pll)
-				enabled_crtcs++;
-			if (crtc->active && intel_crtc_to_shared_dpll(crtc) == pll)
-				active_crtcs++;
-		}
-		I915_STATE_WARN(pll->active != active_crtcs,
-		     "pll active crtcs mismatch (expected %i, found %i)\n",
-		     pll->active, active_crtcs);
-		I915_STATE_WARN(hweight32(pll->config.crtc_mask) != enabled_crtcs,
-		     "pll enabled crtcs mismatch (expected %i, found %i)\n",
-		     hweight32(pll->config.crtc_mask), enabled_crtcs);
+	if (!crtc) {
+		I915_STATE_WARN(pll->active_mask & ~pll->config.crtc_mask,
+				"more active pll users than references: %x vs %x\n",
+				pll->active_mask, pll->config.crtc_mask);
 
-		I915_STATE_WARN(pll->on && memcmp(&pll->config.hw_state, &dpll_hw_state,
-				       sizeof(dpll_hw_state)),
-		     "pll hw state mismatch\n");
+		return;
+	}
+
+	crtc_mask = 1 << drm_crtc_index(crtc);
+
+	if (new_state->active)
+		I915_STATE_WARN(!(pll->active_mask & crtc_mask),
+				"pll active mismatch (expected pipe %c in active mask 0x%02x)\n",
+				pipe_name(drm_crtc_index(crtc)), pll->active_mask);
+	else
+		I915_STATE_WARN(pll->active_mask & crtc_mask,
+				"pll active mismatch (didn't expect pipe %c in active mask 0x%02x)\n",
+				pipe_name(drm_crtc_index(crtc)), pll->active_mask);
+
+	I915_STATE_WARN(!(pll->config.crtc_mask & crtc_mask),
+			"pll enabled crtcs mismatch (expected 0x%x in 0x%02x)\n",
+			crtc_mask, pll->config.crtc_mask);
+
+	I915_STATE_WARN(pll->on && memcmp(&pll->config.hw_state,
+					  &dpll_hw_state,
+					  sizeof(dpll_hw_state)),
+			"pll hw state mismatch\n");
+}
+
+static void
+verify_shared_dpll_state(struct drm_device *dev, struct drm_crtc *crtc,
+			 struct drm_crtc_state *old_crtc_state,
+			 struct drm_crtc_state *new_crtc_state)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc_state *old_state = to_intel_crtc_state(old_crtc_state);
+	struct intel_crtc_state *new_state = to_intel_crtc_state(new_crtc_state);
+
+	if (new_state->shared_dpll)
+		verify_single_dpll_state(dev_priv, new_state->shared_dpll, crtc, new_crtc_state);
+
+	if (old_state->shared_dpll &&
+	    old_state->shared_dpll != new_state->shared_dpll) {
+		unsigned crtc_mask = 1 << drm_crtc_index(crtc);
+		struct intel_shared_dpll *pll = old_state->shared_dpll;
+
+		I915_STATE_WARN(pll->active_mask & crtc_mask,
+				"pll active mismatch (didn't expect pipe %c in active mask)\n",
+				pipe_name(drm_crtc_index(crtc)));
+		I915_STATE_WARN(pll->config.crtc_mask & crtc_mask,
+				"pll enabled crtcs mismatch (found %x in enabled mask)\n",
+				pipe_name(drm_crtc_index(crtc)));
 	}
 }
 
 static void
-intel_modeset_check_state(struct drm_device *dev,
-			  struct drm_atomic_state *old_state)
+intel_modeset_verify_crtc(struct drm_crtc *crtc,
+			 struct drm_crtc_state *old_state,
+			 struct drm_crtc_state *new_state)
 {
-	check_wm_state(dev);
-	check_connector_state(dev, old_state);
-	check_encoder_state(dev);
-	check_crtc_state(dev, old_state);
-	check_shared_dpll_state(dev);
+	if (!needs_modeset(new_state) &&
+	    !to_intel_crtc_state(new_state)->update_pipe)
+		return;
+
+	verify_wm_state(crtc, new_state);
+	verify_connector_state(crtc->dev, crtc);
+	verify_crtc_state(crtc, old_state, new_state);
+	verify_shared_dpll_state(crtc->dev, crtc, old_state, new_state);
 }
 
-void ironlake_check_encoder_dotclock(const struct intel_crtc_state *pipe_config,
-				     int dotclock)
+static void
+verify_disabled_dpll_state(struct drm_device *dev)
 {
-	/*
-	 * FDI already provided one idea for the dotclock.
-	 * Yell if the encoder disagrees.
-	 */
-	WARN(!intel_fuzzy_clock_check(pipe_config->base.adjusted_mode.crtc_clock, dotclock),
-	     "FDI dotclock and encoder dotclock mismatch, fdi: %i, encoder: %i\n",
-	     pipe_config->base.adjusted_mode.crtc_clock, dotclock);
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int i;
+
+	for (i = 0; i < dev_priv->num_shared_dpll; i++)
+		verify_single_dpll_state(dev_priv, &dev_priv->shared_dplls[i], NULL, NULL);
+}
+
+static void
+intel_modeset_verify_disabled(struct drm_device *dev)
+{
+	verify_encoder_state(dev);
+	verify_connector_state(dev, NULL);
+	verify_disabled_dpll_state(dev);
 }
 
 static void update_scanline_offset(struct intel_crtc *crtc)
@@ -13042,20 +13173,21 @@ static void intel_modeset_clear_plls(str
 
 	for_each_crtc_in_state(state, crtc, crtc_state, i) {
 		struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-		int old_dpll = to_intel_crtc_state(crtc->state)->shared_dpll;
+		struct intel_shared_dpll *old_dpll =
+			to_intel_crtc_state(crtc->state)->shared_dpll;
 
 		if (!needs_modeset(crtc_state))
 			continue;
 
-		to_intel_crtc_state(crtc_state)->shared_dpll = DPLL_ID_PRIVATE;
+		to_intel_crtc_state(crtc_state)->shared_dpll = NULL;
 
-		if (old_dpll == DPLL_ID_PRIVATE)
+		if (!old_dpll)
 			continue;
 
 		if (!shared_dpll)
 			shared_dpll = intel_atomic_get_shared_dpll_state(state);
 
-		shared_dpll[old_dpll].crtc_mask &= ~(1 << intel_crtc->pipe);
+		intel_shared_dpll_config_put(shared_dpll, old_dpll, intel_crtc);
 	}
 }
 
@@ -13267,9 +13399,6 @@ static int intel_atomic_check(struct drm
 		struct intel_crtc_state *pipe_config =
 			to_intel_crtc_state(crtc_state);
 
-		memset(&to_intel_crtc(crtc)->atomic, 0,
-		       sizeof(struct intel_crtc_atomic_commit));
-
 		/* Catch I915_MODE_FLAG_INHERITED */
 		if (crtc_state->mode.private_flags != crtc->state->mode.private_flags)
 			crtc_state->mode_changed = true;
@@ -13335,7 +13464,7 @@ static int intel_atomic_check(struct drm
 
 static int intel_atomic_prepare_commit(struct drm_device *dev,
 				       struct drm_atomic_state *state,
-				       bool async)
+				       bool nonblock)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_plane_state *plane_state;
@@ -13344,8 +13473,8 @@ static int intel_atomic_prepare_commit(s
 	struct drm_crtc *crtc;
 	int i, ret;
 
-	if (async) {
-		DRM_DEBUG_KMS("i915 does not yet support async commit\n");
+	if (nonblock) {
+		DRM_DEBUG_KMS("i915 does not yet support nonblocking commit\n");
 		return -EINVAL;
 	}
 
@@ -13366,12 +13495,9 @@ static int intel_atomic_prepare_commit(s
 		return ret;
 
 	ret = drm_atomic_helper_prepare_planes(dev, state);
-	if (!ret && !async && !i915_reset_in_progress(&dev_priv->gpu_error)) {
-		u32 reset_counter;
-
-		reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter);
-		mutex_unlock(&dev->struct_mutex);
+	mutex_unlock(&dev->struct_mutex);
 
+	if (!ret && !nonblock) {
 		for_each_plane_in_state(state, plane, plane_state, i) {
 			struct intel_plane_state *intel_plane_state =
 				to_intel_plane_state(plane_state);
@@ -13380,25 +13506,18 @@ static int intel_atomic_prepare_commit(s
 				continue;
 
 			ret = __i915_wait_request(intel_plane_state->wait_req,
-						  reset_counter, true,
-						  NULL, NULL);
-
-			/* Swallow -EIO errors to allow updates during hw lockup. */
-			if (ret == -EIO)
-				ret = 0;
-
-			if (ret)
+						  true, NULL, NULL);
+			if (ret) {
+				/* Any hang should be swallowed by the wait */
+				WARN_ON(ret == -EIO);
+				mutex_lock(&dev->struct_mutex);
+				drm_atomic_helper_cleanup_planes(dev, state);
+				mutex_unlock(&dev->struct_mutex);
 				break;
+			}
 		}
-
-		if (!ret)
-			return 0;
-
-		mutex_lock(&dev->struct_mutex);
-		drm_atomic_helper_cleanup_planes(dev, state);
 	}
 
-	mutex_unlock(&dev->struct_mutex);
 	return ret;
 }
 
@@ -13440,7 +13559,7 @@ static void intel_atomic_wait_for_vblank
 					drm_crtc_vblank_count(crtc),
 				msecs_to_jiffies(50));
 
-		WARN_ON(!lret);
+		WARN(!lret, "pipe %c vblank wait timed out\n", pipe_name(pipe));
 
 		drm_crtc_vblank_put(crtc);
 	}
@@ -13453,12 +13572,12 @@ static bool needs_vblank_wait(struct int
 		return true;
 
 	/* wm changes, need vblank before final wm's */
-	if (crtc_state->wm_changed)
+	if (crtc_state->update_wm_post)
 		return true;
 
 	/*
 	 * cxsr is re-enabled after vblank.
-	 * This is already handled by crtc_state->wm_changed,
+	 * This is already handled by crtc_state->update_wm_post,
 	 * but added for clarity.
 	 */
 	if (crtc_state->disable_cxsr)
@@ -13471,39 +13590,41 @@ static bool needs_vblank_wait(struct int
  * intel_atomic_commit - commit validated state object
  * @dev: DRM device
  * @state: the top-level driver state object
- * @async: asynchronous commit
+ * @nonblock: nonblocking commit
  *
  * This function commits a top-level state object that has been validated
  * with drm_atomic_helper_check().
  *
  * FIXME:  Atomic modeset support for i915 is not yet complete.  At the moment
  * we can only handle plane-related operations and do not yet support
- * asynchronous commit.
+ * nonblocking commit.
  *
  * RETURNS
  * Zero for success or -errno.
  */
 static int intel_atomic_commit(struct drm_device *dev,
 			       struct drm_atomic_state *state,
-			       bool async)
+			       bool nonblock)
 {
 	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_crtc_state *crtc_state;
+	struct drm_crtc_state *old_crtc_state;
 	struct drm_crtc *crtc;
+	struct intel_crtc_state *intel_cstate;
 	int ret = 0, i;
 	bool hw_check = intel_state->modeset;
 	unsigned long put_domains[I915_MAX_PIPES] = {};
 	unsigned crtc_vblank_mask = 0;
 
-	ret = intel_atomic_prepare_commit(dev, state, async);
+	ret = intel_atomic_prepare_commit(dev, state, nonblock);
 	if (ret) {
 		DRM_DEBUG_ATOMIC("Preparing state failed with %i\n", ret);
 		return ret;
 	}
 
 	drm_atomic_helper_swap_state(dev, state);
-	dev_priv->wm.config = to_intel_atomic_state(state)->wm_config;
+	dev_priv->wm.config = intel_state->wm_config;
+	intel_shared_dpll_commit(state);
 
 	if (intel_state->modeset) {
 		memcpy(dev_priv->min_pixclk, intel_state->min_pixclk,
@@ -13514,7 +13635,7 @@ static int intel_atomic_commit(struct dr
 		intel_display_power_get(dev_priv, POWER_DOMAIN_MODESET);
 	}
 
-	for_each_crtc_in_state(state, crtc, crtc_state, i) {
+	for_each_crtc_in_state(state, crtc, old_crtc_state, i) {
 		struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
 		if (needs_modeset(crtc->state) ||
@@ -13529,10 +13650,10 @@ static int intel_atomic_commit(struct dr
 		if (!needs_modeset(crtc->state))
 			continue;
 
-		intel_pre_plane_update(to_intel_crtc_state(crtc_state));
+		intel_pre_plane_update(to_intel_crtc_state(old_crtc_state));
 
-		if (crtc_state->active) {
-			intel_crtc_disable_planes(crtc, crtc_state->plane_mask);
+		if (old_crtc_state->active) {
+			intel_crtc_disable_planes(crtc, old_crtc_state->plane_mask);
 			dev_priv->display.crtc_disable(crtc);
 			intel_crtc->active = false;
 			intel_fbc_disable(intel_crtc);
@@ -13555,17 +13676,17 @@ static int intel_atomic_commit(struct dr
 	intel_modeset_update_crtc_state(state);
 
 	if (intel_state->modeset) {
-		intel_shared_dpll_commit(state);
-
 		drm_atomic_helper_update_legacy_modeset_state(state->dev, state);
 
 		if (dev_priv->display.modeset_commit_cdclk &&
 		    intel_state->dev_cdclk != dev_priv->cdclk_freq)
 			dev_priv->display.modeset_commit_cdclk(state);
+
+		intel_modeset_verify_disabled(dev);
 	}
 
 	/* Now enable the clocks, plane, pipe, and connectors that we set up. */
-	for_each_crtc_in_state(state, crtc, crtc_state, i) {
+	for_each_crtc_in_state(state, crtc, old_crtc_state, i) {
 		struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 		bool modeset = needs_modeset(crtc->state);
 		struct intel_crtc_state *pipe_config =
@@ -13578,14 +13699,15 @@ static int intel_atomic_commit(struct dr
 		}
 
 		if (!modeset)
-			intel_pre_plane_update(to_intel_crtc_state(crtc_state));
+			intel_pre_plane_update(to_intel_crtc_state(old_crtc_state));
 
-		if (crtc->state->active && intel_crtc->atomic.update_fbc)
+		if (crtc->state->active &&
+		    drm_atomic_get_existing_plane_state(state, crtc->primary))
 			intel_fbc_enable(intel_crtc);
 
 		if (crtc->state->active &&
 		    (crtc->state->planes_changed || update_pipe))
-			drm_atomic_helper_commit_planes_on_crtc(crtc_state);
+			drm_atomic_helper_commit_planes_on_crtc(old_crtc_state);
 
 		if (pipe_config->base.active && needs_vblank_wait(pipe_config))
 			crtc_vblank_mask |= 1 << i;
@@ -13596,11 +13718,27 @@ static int intel_atomic_commit(struct dr
 	if (!state->legacy_cursor_update)
 		intel_atomic_wait_for_vblanks(dev, dev_priv, crtc_vblank_mask);
 
-	for_each_crtc_in_state(state, crtc, crtc_state, i) {
-		intel_post_plane_update(to_intel_crtc(crtc));
+	/*
+	 * Now that the vblank has passed, we can go ahead and program the
+	 * optimal watermarks on platforms that need two-step watermark
+	 * programming.
+	 *
+	 * TODO: Move this (and other cleanup) to an async worker eventually.
+	 */
+	for_each_crtc_in_state(state, crtc, old_crtc_state, i) {
+		intel_cstate = to_intel_crtc_state(crtc->state);
+
+		if (dev_priv->display.optimize_watermarks)
+			dev_priv->display.optimize_watermarks(intel_cstate);
+	}
+
+	for_each_crtc_in_state(state, crtc, old_crtc_state, i) {
+		intel_post_plane_update(to_intel_crtc_state(old_crtc_state));
 
 		if (put_domains[i])
 			modeset_put_power_domains(dev_priv, put_domains[i]);
+
+		intel_modeset_verify_crtc(crtc, old_crtc_state, crtc->state);
 	}
 
 	if (intel_state->modeset)
@@ -13610,9 +13748,6 @@ static int intel_atomic_commit(struct dr
 	drm_atomic_helper_cleanup_planes(dev, state);
 	mutex_unlock(&dev->struct_mutex);
 
-	if (hw_check)
-		intel_modeset_check_state(dev, state);
-
 	drm_atomic_state_free(state);
 
 	/* As one of the primary mmio accessors, KMS has a high likelihood
@@ -13672,116 +13807,15 @@ out:
 #undef for_each_intel_crtc_masked
 
 static const struct drm_crtc_funcs intel_crtc_funcs = {
-	.gamma_set = intel_crtc_gamma_set,
+	.gamma_set = drm_atomic_helper_legacy_gamma_set,
 	.set_config = drm_atomic_helper_set_config,
+	.set_property = drm_atomic_helper_crtc_set_property,
 	.destroy = intel_crtc_destroy,
 	.page_flip = intel_crtc_page_flip,
 	.atomic_duplicate_state = intel_crtc_duplicate_state,
 	.atomic_destroy_state = intel_crtc_destroy_state,
 };
 
-static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
-				      struct intel_shared_dpll *pll,
-				      struct intel_dpll_hw_state *hw_state)
-{
-	uint32_t val;
-
-	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
-		return false;
-
-	val = I915_READ(PCH_DPLL(pll->id));
-	hw_state->dpll = val;
-	hw_state->fp0 = I915_READ(PCH_FP0(pll->id));
-	hw_state->fp1 = I915_READ(PCH_FP1(pll->id));
-
-	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
-
-	return val & DPLL_VCO_ENABLE;
-}
-
-static void ibx_pch_dpll_mode_set(struct drm_i915_private *dev_priv,
-				  struct intel_shared_dpll *pll)
-{
-	I915_WRITE(PCH_FP0(pll->id), pll->config.hw_state.fp0);
-	I915_WRITE(PCH_FP1(pll->id), pll->config.hw_state.fp1);
-}
-
-static void ibx_pch_dpll_enable(struct drm_i915_private *dev_priv,
-				struct intel_shared_dpll *pll)
-{
-	/* PCH refclock must be enabled first */
-	ibx_assert_pch_refclk_enabled(dev_priv);
-
-	I915_WRITE(PCH_DPLL(pll->id), pll->config.hw_state.dpll);
-
-	/* Wait for the clocks to stabilize. */
-	POSTING_READ(PCH_DPLL(pll->id));
-	udelay(150);
-
-	/* The pixel multiplier can only be updated once the
-	 * DPLL is enabled and the clocks are stable.
-	 *
-	 * So write it again.
-	 */
-	I915_WRITE(PCH_DPLL(pll->id), pll->config.hw_state.dpll);
-	POSTING_READ(PCH_DPLL(pll->id));
-	udelay(200);
-}
-
-static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv,
-				 struct intel_shared_dpll *pll)
-{
-	struct drm_device *dev = dev_priv->dev;
-	struct intel_crtc *crtc;
-
-	/* Make sure no transcoder isn't still depending on us. */
-	for_each_intel_crtc(dev, crtc) {
-		if (intel_crtc_to_shared_dpll(crtc) == pll)
-			assert_pch_transcoder_disabled(dev_priv, crtc->pipe);
-	}
-
-	I915_WRITE(PCH_DPLL(pll->id), 0);
-	POSTING_READ(PCH_DPLL(pll->id));
-	udelay(200);
-}
-
-static char *ibx_pch_dpll_names[] = {
-	"PCH DPLL A",
-	"PCH DPLL B",
-};
-
-static void ibx_pch_dpll_init(struct drm_device *dev)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	int i;
-
-	dev_priv->num_shared_dpll = 2;
-
-	for (i = 0; i < dev_priv->num_shared_dpll; i++) {
-		dev_priv->shared_dplls[i].id = i;
-		dev_priv->shared_dplls[i].name = ibx_pch_dpll_names[i];
-		dev_priv->shared_dplls[i].mode_set = ibx_pch_dpll_mode_set;
-		dev_priv->shared_dplls[i].enable = ibx_pch_dpll_enable;
-		dev_priv->shared_dplls[i].disable = ibx_pch_dpll_disable;
-		dev_priv->shared_dplls[i].get_hw_state =
-			ibx_pch_dpll_get_hw_state;
-	}
-}
-
-static void intel_shared_dpll_init(struct drm_device *dev)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-
-	if (HAS_DDI(dev))
-		intel_ddi_pll_init(dev);
-	else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
-		ibx_pch_dpll_init(dev);
-	else
-		dev_priv->num_shared_dpll = 0;
-
-	BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS);
-}
-
 /**
  * intel_prepare_plane_fb - Prepare fb for usage on plane
  * @plane: drm plane to prepare for
@@ -13827,10 +13861,11 @@ intel_prepare_plane_fb(struct drm_plane
 		 */
 		if (needs_modeset(crtc_state))
 			ret = i915_gem_object_wait_rendering(old_obj, true);
-
-		/* Swallow -EIO errors to allow updates during hw lockup. */
-		if (ret && ret != -EIO)
+		if (ret) {
+			/* GPU hangs should have been swallowed by the wait */
+			WARN_ON(ret == -EIO);
 			return ret;
+		}
 	}
 
 	/* For framebuffer backed by dmabuf, wait for fence */
@@ -13855,7 +13890,7 @@ intel_prepare_plane_fb(struct drm_plane
 		if (ret)
 			DRM_DEBUG_KMS("failed to attach phys object\n");
 	} else {
-		ret = intel_pin_and_fence_fb_obj(plane, fb, new_state);
+		ret = intel_pin_and_fence_fb_obj(fb, new_state->rotation);
 	}
 
 	if (ret == 0) {
@@ -13899,7 +13934,7 @@ intel_cleanup_plane_fb(struct drm_plane
 
 	if (old_obj && (plane->type != DRM_PLANE_TYPE_CURSOR ||
 	    !INTEL_INFO(dev)->cursor_needs_physical))
-		intel_unpin_fb_obj(old_state->fb, old_state);
+		intel_unpin_fb_obj(old_state->fb, old_state->rotation);
 
 	/* prepare_fb aborted? */
 	if ((old_obj && (old_obj->frontbuffer_bits & intel_plane->frontbuffer_bit)) ||
@@ -13907,7 +13942,6 @@ intel_cleanup_plane_fb(struct drm_plane
 		i915_gem_track_fb(old_obj, obj, intel_plane->frontbuffer_bit);
 
 	i915_gem_request_assign(&old_intel_state->wait_req, NULL);
-
 }
 
 int
@@ -13982,6 +14016,11 @@ static void intel_begin_crtc_commit(stru
 	if (modeset)
 		return;
 
+	if (crtc->state->color_mgmt_changed || to_intel_crtc_state(crtc->state)->update_pipe) {
+		intel_color_set_csc(crtc->state);
+		intel_color_load_luts(crtc->state);
+	}
+
 	if (to_intel_crtc_state(crtc->state)->update_pipe)
 		intel_update_pipe_config(intel_crtc, old_intel_state);
 	else if (INTEL_INFO(dev)->gen >= 9)
@@ -14025,20 +14064,19 @@ const struct drm_plane_funcs intel_plane
 static struct drm_plane *intel_primary_plane_create(struct drm_device *dev,
 						    int pipe)
 {
-	struct intel_plane *primary;
-	struct intel_plane_state *state;
+	struct intel_plane *primary = NULL;
+	struct intel_plane_state *state = NULL;
 	const uint32_t *intel_primary_formats;
 	unsigned int num_formats;
+	int ret;
 
 	primary = kzalloc(sizeof(*primary), GFP_KERNEL);
-	if (primary == NULL)
-		return NULL;
+	if (!primary)
+		goto fail;
 
 	state = intel_create_plane_state(&primary->base);
-	if (!state) {
-		kfree(primary);
-		return NULL;
-	}
+	if (!state)
+		goto fail;
 	primary->base.state = &state->base;
 
 	primary->can_scale = false;
@@ -14080,10 +14118,12 @@ static struct drm_plane *intel_primary_p
 		primary->disable_plane = i9xx_disable_primary_plane;
 	}
 
-	drm_universal_plane_init(dev, &primary->base, 0,
-				 &intel_plane_funcs,
-				 intel_primary_formats, num_formats,
-				 DRM_PLANE_TYPE_PRIMARY, NULL);
+	ret = drm_universal_plane_init(dev, &primary->base, 0,
+				       &intel_plane_funcs,
+				       intel_primary_formats, num_formats,
+				       DRM_PLANE_TYPE_PRIMARY, NULL);
+	if (ret)
+		goto fail;
 
 	if (INTEL_INFO(dev)->gen >= 4)
 		intel_create_rotation_property(dev, primary);
@@ -14091,6 +14131,12 @@ static struct drm_plane *intel_primary_p
 	drm_plane_helper_add(&primary->base, &intel_plane_helper_funcs);
 
 	return &primary->base;
+
+fail:
+	kfree(state);
+	kfree(primary);
+
+	return NULL;
 }
 
 void intel_create_rotation_property(struct drm_device *dev, struct intel_plane *plane)
@@ -14207,18 +14253,17 @@ intel_update_cursor_plane(struct drm_pla
 static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
 						   int pipe)
 {
-	struct intel_plane *cursor;
-	struct intel_plane_state *state;
+	struct intel_plane *cursor = NULL;
+	struct intel_plane_state *state = NULL;
+	int ret;
 
 	cursor = kzalloc(sizeof(*cursor), GFP_KERNEL);
-	if (cursor == NULL)
-		return NULL;
+	if (!cursor)
+		goto fail;
 
 	state = intel_create_plane_state(&cursor->base);
-	if (!state) {
-		kfree(cursor);
-		return NULL;
-	}
+	if (!state)
+		goto fail;
 	cursor->base.state = &state->base;
 
 	cursor->can_scale = false;
@@ -14230,11 +14275,13 @@ static struct drm_plane *intel_cursor_pl
 	cursor->update_plane = intel_update_cursor_plane;
 	cursor->disable_plane = intel_disable_cursor_plane;
 
-	drm_universal_plane_init(dev, &cursor->base, 0,
-				 &intel_plane_funcs,
-				 intel_cursor_formats,
-				 ARRAY_SIZE(intel_cursor_formats),
-				 DRM_PLANE_TYPE_CURSOR, NULL);
+	ret = drm_universal_plane_init(dev, &cursor->base, 0,
+				       &intel_plane_funcs,
+				       intel_cursor_formats,
+				       ARRAY_SIZE(intel_cursor_formats),
+				       DRM_PLANE_TYPE_CURSOR, NULL);
+	if (ret)
+		goto fail;
 
 	if (INTEL_INFO(dev)->gen >= 4) {
 		if (!dev->mode_config.rotation_property)
@@ -14254,6 +14301,12 @@ static struct drm_plane *intel_cursor_pl
 	drm_plane_helper_add(&cursor->base, &intel_plane_helper_funcs);
 
 	return &cursor->base;
+
+fail:
+	kfree(state);
+	kfree(cursor);
+
+	return NULL;
 }
 
 static void skl_init_scalers(struct drm_device *dev, struct intel_crtc *intel_crtc,
@@ -14279,7 +14332,7 @@ static void intel_crtc_init(struct drm_d
 	struct intel_crtc_state *crtc_state = NULL;
 	struct drm_plane *primary = NULL;
 	struct drm_plane *cursor = NULL;
-	int i, ret;
+	int ret;
 
 	intel_crtc = kzalloc(sizeof(*intel_crtc), GFP_KERNEL);
 	if (intel_crtc == NULL)
@@ -14315,13 +14368,6 @@ static void intel_crtc_init(struct drm_d
 	if (ret)
 		goto fail;
 
-	drm_mode_crtc_set_gamma_size(&intel_crtc->base, 256);
-	for (i = 0; i < 256; i++) {
-		intel_crtc->lut_r[i] = i;
-		intel_crtc->lut_g[i] = i;
-		intel_crtc->lut_b[i] = i;
-	}
-
 	/*
 	 * On gen2/3 only plane A can do fbc, but the panel fitter and lvds port
 	 * is hooked to pipe B. Hence we want plane A feeding pipe B.
@@ -14346,6 +14392,8 @@ static void intel_crtc_init(struct drm_d
 
 	drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs);
 
+	intel_color_init(&intel_crtc->base);
+
 	WARN_ON(drm_crtc_index(&intel_crtc->base) != intel_crtc->pipe);
 	return;
 
@@ -14470,6 +14518,8 @@ static void intel_setup_outputs(struct d
 		intel_ddi_init(dev, PORT_A);
 		intel_ddi_init(dev, PORT_B);
 		intel_ddi_init(dev, PORT_C);
+
+		intel_dsi_init(dev);
 	} else if (HAS_DDI(dev)) {
 		int found;
 
@@ -14530,6 +14580,8 @@ static void intel_setup_outputs(struct d
 		if (I915_READ(PCH_DP_D) & DP_DETECTED)
 			intel_dp_init(dev, PCH_DP_D, PORT_D);
 	} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+		bool has_edp, has_port;
+
 		/*
 		 * The DP_DETECTED bit is the latched state of the DDC
 		 * SDA pin at boot. However since eDP doesn't require DDC
@@ -14538,27 +14590,37 @@ static void intel_setup_outputs(struct d
 		 * Thus we can't rely on the DP_DETECTED bit alone to detect
 		 * eDP ports. Consult the VBT as well as DP_DETECTED to
 		 * detect eDP ports.
+		 *
+		 * Sadly the straps seem to be missing sometimes even for HDMI
+		 * ports (eg. on Voyo V3 - CHT x7-Z8700), so check both strap
+		 * and VBT for the presence of the port. Additionally we can't
+		 * trust the port type the VBT declares as we've seen at least
+		 * HDMI ports that the VBT claim are DP or eDP.
 		 */
-		if (I915_READ(VLV_HDMIB) & SDVO_DETECTED &&
-		    !intel_dp_is_edp(dev, PORT_B))
+		has_edp = intel_dp_is_edp(dev, PORT_B);
+		has_port = intel_bios_is_port_present(dev_priv, PORT_B);
+		if (I915_READ(VLV_DP_B) & DP_DETECTED || has_port)
+			has_edp &= intel_dp_init(dev, VLV_DP_B, PORT_B);
+		if ((I915_READ(VLV_HDMIB) & SDVO_DETECTED || has_port) && !has_edp)
 			intel_hdmi_init(dev, VLV_HDMIB, PORT_B);
-		if (I915_READ(VLV_DP_B) & DP_DETECTED ||
-		    intel_dp_is_edp(dev, PORT_B))
-			intel_dp_init(dev, VLV_DP_B, PORT_B);
 
-		if (I915_READ(VLV_HDMIC) & SDVO_DETECTED &&
-		    !intel_dp_is_edp(dev, PORT_C))
+		has_edp = intel_dp_is_edp(dev, PORT_C);
+		has_port = intel_bios_is_port_present(dev_priv, PORT_C);
+		if (I915_READ(VLV_DP_C) & DP_DETECTED || has_port)
+			has_edp &= intel_dp_init(dev, VLV_DP_C, PORT_C);
+		if ((I915_READ(VLV_HDMIC) & SDVO_DETECTED || has_port) && !has_edp)
 			intel_hdmi_init(dev, VLV_HDMIC, PORT_C);
-		if (I915_READ(VLV_DP_C) & DP_DETECTED ||
-		    intel_dp_is_edp(dev, PORT_C))
-			intel_dp_init(dev, VLV_DP_C, PORT_C);
 
 		if (IS_CHERRYVIEW(dev)) {
-			/* eDP not supported on port D, so don't check VBT */
-			if (I915_READ(CHV_HDMID) & SDVO_DETECTED)
-				intel_hdmi_init(dev, CHV_HDMID, PORT_D);
-			if (I915_READ(CHV_DP_D) & DP_DETECTED)
+			/*
+			 * eDP not supported on port D,
+			 * so no need to worry about it
+			 */
+			has_port = intel_bios_is_port_present(dev_priv, PORT_D);
+			if (I915_READ(CHV_DP_D) & DP_DETECTED || has_port)
 				intel_dp_init(dev, CHV_DP_D, PORT_D);
+			if (I915_READ(CHV_HDMID) & SDVO_DETECTED || has_port)
+				intel_hdmi_init(dev, CHV_HDMID, PORT_D);
 		}
 
 		intel_dsi_init(dev);
@@ -14839,6 +14901,8 @@ static int intel_framebuffer_init(struct
 	drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd);
 	intel_fb->obj = obj;
 
+	intel_fill_fb_info(dev_priv, &intel_fb->base);
+
 	ret = drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs);
 	if (ret) {
 		DRM_ERROR("framebuffer init failed %d\n", ret);
@@ -14859,8 +14923,7 @@ intel_user_framebuffer_create(struct drm
 	struct drm_i915_gem_object *obj;
 	struct drm_mode_fb_cmd2 mode_cmd = *user_mode_cmd;
 
-	obj = to_intel_bo(drm_gem_object_lookup(dev, filp,
-						mode_cmd.handles[0]));
+	obj = to_intel_bo(drm_gem_object_lookup(filp, mode_cmd.handles[0]));
 	if (&obj->base == NULL)
 		return ERR_PTR(-ENOENT);
 
@@ -14886,23 +14949,13 @@ static const struct drm_mode_config_func
 	.atomic_state_clear = intel_atomic_state_clear,
 };
 
-/* Set up chip specific display functions */
-static void intel_init_display(struct drm_device *dev)
+/**
+ * intel_init_display_hooks - initialize the display modesetting hooks
+ * @dev_priv: device private
+ */
+void intel_init_display_hooks(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-
-	if (HAS_PCH_SPLIT(dev) || IS_G4X(dev))
-		dev_priv->display.find_dpll = g4x_find_best_dpll;
-	else if (IS_CHERRYVIEW(dev))
-		dev_priv->display.find_dpll = chv_find_best_dpll;
-	else if (IS_VALLEYVIEW(dev))
-		dev_priv->display.find_dpll = vlv_find_best_dpll;
-	else if (IS_PINEVIEW(dev))
-		dev_priv->display.find_dpll = pnv_find_best_dpll;
-	else
-		dev_priv->display.find_dpll = i9xx_find_best_dpll;
-
-	if (INTEL_INFO(dev)->gen >= 9) {
+	if (INTEL_INFO(dev_priv)->gen >= 9) {
 		dev_priv->display.get_pipe_config = haswell_get_pipe_config;
 		dev_priv->display.get_initial_plane_config =
 			skylake_get_initial_plane_config;
@@ -14910,7 +14963,7 @@ static void intel_init_display(struct dr
 			haswell_crtc_compute_clock;
 		dev_priv->display.crtc_enable = haswell_crtc_enable;
 		dev_priv->display.crtc_disable = haswell_crtc_disable;
-	} else if (HAS_DDI(dev)) {
+	} else if (HAS_DDI(dev_priv)) {
 		dev_priv->display.get_pipe_config = haswell_get_pipe_config;
 		dev_priv->display.get_initial_plane_config =
 			ironlake_get_initial_plane_config;
@@ -14918,7 +14971,7 @@ static void intel_init_display(struct dr
 			haswell_crtc_compute_clock;
 		dev_priv->display.crtc_enable = haswell_crtc_enable;
 		dev_priv->display.crtc_disable = haswell_crtc_disable;
-	} else if (HAS_PCH_SPLIT(dev)) {
+	} else if (HAS_PCH_SPLIT(dev_priv)) {
 		dev_priv->display.get_pipe_config = ironlake_get_pipe_config;
 		dev_priv->display.get_initial_plane_config =
 			ironlake_get_initial_plane_config;
@@ -14926,106 +14979,134 @@ static void intel_init_display(struct dr
 			ironlake_crtc_compute_clock;
 		dev_priv->display.crtc_enable = ironlake_crtc_enable;
 		dev_priv->display.crtc_disable = ironlake_crtc_disable;
-	} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+	} else if (IS_CHERRYVIEW(dev_priv)) {
 		dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
 		dev_priv->display.get_initial_plane_config =
 			i9xx_get_initial_plane_config;
-		dev_priv->display.crtc_compute_clock = i9xx_crtc_compute_clock;
+		dev_priv->display.crtc_compute_clock = chv_crtc_compute_clock;
 		dev_priv->display.crtc_enable = valleyview_crtc_enable;
 		dev_priv->display.crtc_disable = i9xx_crtc_disable;
-	} else {
+	} else if (IS_VALLEYVIEW(dev_priv)) {
+		dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
+		dev_priv->display.get_initial_plane_config =
+			i9xx_get_initial_plane_config;
+		dev_priv->display.crtc_compute_clock = vlv_crtc_compute_clock;
+		dev_priv->display.crtc_enable = valleyview_crtc_enable;
+		dev_priv->display.crtc_disable = i9xx_crtc_disable;
+	} else if (IS_G4X(dev_priv)) {
+		dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
+		dev_priv->display.get_initial_plane_config =
+			i9xx_get_initial_plane_config;
+		dev_priv->display.crtc_compute_clock = g4x_crtc_compute_clock;
+		dev_priv->display.crtc_enable = i9xx_crtc_enable;
+		dev_priv->display.crtc_disable = i9xx_crtc_disable;
+	} else if (IS_PINEVIEW(dev_priv)) {
+		dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
+		dev_priv->display.get_initial_plane_config =
+			i9xx_get_initial_plane_config;
+		dev_priv->display.crtc_compute_clock = pnv_crtc_compute_clock;
+		dev_priv->display.crtc_enable = i9xx_crtc_enable;
+		dev_priv->display.crtc_disable = i9xx_crtc_disable;
+	} else if (!IS_GEN2(dev_priv)) {
 		dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
 		dev_priv->display.get_initial_plane_config =
 			i9xx_get_initial_plane_config;
 		dev_priv->display.crtc_compute_clock = i9xx_crtc_compute_clock;
 		dev_priv->display.crtc_enable = i9xx_crtc_enable;
 		dev_priv->display.crtc_disable = i9xx_crtc_disable;
+	} else {
+		dev_priv->display.get_pipe_config = i9xx_get_pipe_config;
+		dev_priv->display.get_initial_plane_config =
+			i9xx_get_initial_plane_config;
+		dev_priv->display.crtc_compute_clock = i8xx_crtc_compute_clock;
+		dev_priv->display.crtc_enable = i9xx_crtc_enable;
+		dev_priv->display.crtc_disable = i9xx_crtc_disable;
 	}
 
 	/* Returns the core display clock speed */
-	if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
+	if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
 		dev_priv->display.get_display_clock_speed =
 			skylake_get_display_clock_speed;
-	else if (IS_BROXTON(dev))
+	else if (IS_BROXTON(dev_priv))
 		dev_priv->display.get_display_clock_speed =
 			broxton_get_display_clock_speed;
-	else if (IS_BROADWELL(dev))
+	else if (IS_BROADWELL(dev_priv))
 		dev_priv->display.get_display_clock_speed =
 			broadwell_get_display_clock_speed;
-	else if (IS_HASWELL(dev))
+	else if (IS_HASWELL(dev_priv))
 		dev_priv->display.get_display_clock_speed =
 			haswell_get_display_clock_speed;
-	else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
+	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
 		dev_priv->display.get_display_clock_speed =
 			valleyview_get_display_clock_speed;
-	else if (IS_GEN5(dev))
+	else if (IS_GEN5(dev_priv))
 		dev_priv->display.get_display_clock_speed =
 			ilk_get_display_clock_speed;
-	else if (IS_I945G(dev) || IS_BROADWATER(dev) ||
-		 IS_GEN6(dev) || IS_IVYBRIDGE(dev))
+	else if (IS_I945G(dev_priv) || IS_BROADWATER(dev_priv) ||
+		 IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv))
 		dev_priv->display.get_display_clock_speed =
 			i945_get_display_clock_speed;
-	else if (IS_GM45(dev))
+	else if (IS_GM45(dev_priv))
 		dev_priv->display.get_display_clock_speed =
 			gm45_get_display_clock_speed;
-	else if (IS_CRESTLINE(dev))
+	else if (IS_CRESTLINE(dev_priv))
 		dev_priv->display.get_display_clock_speed =
 			i965gm_get_display_clock_speed;
-	else if (IS_PINEVIEW(dev))
+	else if (IS_PINEVIEW(dev_priv))
 		dev_priv->display.get_display_clock_speed =
 			pnv_get_display_clock_speed;
-	else if (IS_G33(dev) || IS_G4X(dev))
+	else if (IS_G33(dev_priv) || IS_G4X(dev_priv))
 		dev_priv->display.get_display_clock_speed =
 			g33_get_display_clock_speed;
-	else if (IS_I915G(dev))
+	else if (IS_I915G(dev_priv))
 		dev_priv->display.get_display_clock_speed =
 			i915_get_display_clock_speed;
-	else if (IS_I945GM(dev) || IS_845G(dev))
+	else if (IS_I945GM(dev_priv) || IS_845G(dev_priv))
 		dev_priv->display.get_display_clock_speed =
 			i9xx_misc_get_display_clock_speed;
-	else if (IS_I915GM(dev))
+	else if (IS_I915GM(dev_priv))
 		dev_priv->display.get_display_clock_speed =
 			i915gm_get_display_clock_speed;
-	else if (IS_I865G(dev))
+	else if (IS_I865G(dev_priv))
 		dev_priv->display.get_display_clock_speed =
 			i865_get_display_clock_speed;
-	else if (IS_I85X(dev))
+	else if (IS_I85X(dev_priv))
 		dev_priv->display.get_display_clock_speed =
 			i85x_get_display_clock_speed;
 	else { /* 830 */
-		WARN(!IS_I830(dev), "Unknown platform. Assuming 133 MHz CDCLK\n");
+		WARN(!IS_I830(dev_priv), "Unknown platform. Assuming 133 MHz CDCLK\n");
 		dev_priv->display.get_display_clock_speed =
 			i830_get_display_clock_speed;
 	}
 
-	if (IS_GEN5(dev)) {
+	if (IS_GEN5(dev_priv)) {
 		dev_priv->display.fdi_link_train = ironlake_fdi_link_train;
-	} else if (IS_GEN6(dev)) {
+	} else if (IS_GEN6(dev_priv)) {
 		dev_priv->display.fdi_link_train = gen6_fdi_link_train;
-	} else if (IS_IVYBRIDGE(dev)) {
+	} else if (IS_IVYBRIDGE(dev_priv)) {
 		/* FIXME: detect B0+ stepping and use auto training */
 		dev_priv->display.fdi_link_train = ivb_manual_fdi_link_train;
-	} else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
+	} else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
 		dev_priv->display.fdi_link_train = hsw_fdi_link_train;
-		if (IS_BROADWELL(dev)) {
+		if (IS_BROADWELL(dev_priv)) {
 			dev_priv->display.modeset_commit_cdclk =
 				broadwell_modeset_commit_cdclk;
 			dev_priv->display.modeset_calc_cdclk =
 				broadwell_modeset_calc_cdclk;
 		}
-	} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
 		dev_priv->display.modeset_commit_cdclk =
 			valleyview_modeset_commit_cdclk;
 		dev_priv->display.modeset_calc_cdclk =
 			valleyview_modeset_calc_cdclk;
-	} else if (IS_BROXTON(dev)) {
+	} else if (IS_BROXTON(dev_priv)) {
 		dev_priv->display.modeset_commit_cdclk =
 			broxton_modeset_commit_cdclk;
 		dev_priv->display.modeset_calc_cdclk =
 			broxton_modeset_calc_cdclk;
 	}
 
-	switch (INTEL_INFO(dev)->gen) {
+	switch (INTEL_INFO(dev_priv)->gen) {
 	case 2:
 		dev_priv->display.queue_flip = intel_gen2_queue_flip;
 		break;
@@ -15052,8 +15133,6 @@ static void intel_init_display(struct dr
 		/* Default just returns -ENODEV to indicate unsupported */
 		dev_priv->display.queue_flip = intel_default_queue_flip;
 	}
-
-	mutex_init(&dev_priv->pps_mutex);
 }
 
 /*
@@ -15276,7 +15355,7 @@ static void sanitize_watermarks(struct d
 	int i;
 
 	/* Only supported on platforms that use atomic watermark design */
-	if (!dev_priv->display.program_watermarks)
+	if (!dev_priv->display.optimize_watermarks)
 		return;
 
 	/*
@@ -15297,6 +15376,13 @@ retry:
 	if (WARN_ON(IS_ERR(state)))
 		goto fail;
 
+	/*
+	 * Hardware readout is the only time we don't want to calculate
+	 * intermediate watermarks (since we don't trust the current
+	 * watermarks).
+	 */
+	to_intel_atomic_state(state)->skip_intermediate_wm = true;
+
 	ret = intel_atomic_check(dev, state);
 	if (ret) {
 		/*
@@ -15319,7 +15405,8 @@ retry:
 	for_each_crtc_in_state(state, crtc, cstate, i) {
 		struct intel_crtc_state *cs = to_intel_crtc_state(cstate);
 
-		dev_priv->display.program_watermarks(cs);
+		cs->wm.need_postvbl_update = true;
+		dev_priv->display.optimize_watermarks(cs);
 	}
 
 	drm_atomic_state_free(state);
@@ -15330,7 +15417,8 @@ fail:
 
 void intel_modeset_init(struct drm_device *dev)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	int sprite, ret;
 	enum pipe pipe;
 	struct intel_crtc *crtc;
@@ -15372,9 +15460,6 @@ void intel_modeset_init(struct drm_devic
 		}
 	}
 
-	intel_init_display(dev);
-	intel_init_audio(dev);
-
 	if (IS_GEN2(dev)) {
 		dev->mode_config.max_width = 2048;
 		dev->mode_config.max_height = 2048;
@@ -15397,7 +15482,7 @@ void intel_modeset_init(struct drm_devic
 		dev->mode_config.cursor_height = MAX_CURSOR_HEIGHT;
 	}
 
-	dev->mode_config.fb_base = dev_priv->gtt.mappable_base;
+	dev->mode_config.fb_base = ggtt->mappable_base;
 
 	DRM_DEBUG_KMS("%d display pipe%s available.\n",
 		      INTEL_INFO(dev)->num_pipes,
@@ -15414,6 +15499,7 @@ void intel_modeset_init(struct drm_devic
 	}
 
 	intel_update_czclk(dev_priv);
+	intel_update_rawclk(dev_priv);
 	intel_update_cdclk(dev);
 
 	intel_shared_dpll_init(dev);
@@ -15526,10 +15612,15 @@ static void intel_sanitize_crtc(struct i
 {
 	struct drm_device *dev = crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	i915_reg_t reg = PIPECONF(crtc->config->cpu_transcoder);
+	enum transcoder cpu_transcoder = crtc->config->cpu_transcoder;
 
 	/* Clear any frame start delays used for debugging left by the BIOS */
-	I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);
+	if (!transcoder_is_dsi(cpu_transcoder)) {
+		i915_reg_t reg = PIPECONF(cpu_transcoder);
+
+		I915_WRITE(reg,
+			   I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);
+	}
 
 	/* restore vblank interrupts to correct state */
 	drm_crtc_vblank_reset(&crtc->base);
@@ -15577,38 +15668,9 @@ static void intel_sanitize_crtc(struct i
 
 	/* Adjust the state of the output pipe according to whether we
 	 * have active connectors/encoders. */
-	if (!intel_crtc_has_encoders(crtc))
+	if (crtc->active && !intel_crtc_has_encoders(crtc))
 		intel_crtc_disable_noatomic(&crtc->base);
 
-	if (crtc->active != crtc->base.state->active) {
-		struct intel_encoder *encoder;
-
-		/* This can happen either due to bugs in the get_hw_state
-		 * functions or because of calls to intel_crtc_disable_noatomic,
-		 * or because the pipe is force-enabled due to the
-		 * pipe A quirk. */
-		DRM_DEBUG_KMS("[CRTC:%d] hw state adjusted, was %s, now %s\n",
-			      crtc->base.base.id,
-			      crtc->base.state->enable ? "enabled" : "disabled",
-			      crtc->active ? "enabled" : "disabled");
-
-		WARN_ON(drm_atomic_set_mode_for_crtc(crtc->base.state, NULL) < 0);
-		crtc->base.state->active = crtc->active;
-		crtc->base.enabled = crtc->active;
-		crtc->base.state->connector_mask = 0;
-		crtc->base.state->encoder_mask = 0;
-
-		/* Because we only establish the connector -> encoder ->
-		 * crtc links if something is active, this means the
-		 * crtc is now deactivated. Break the links. connector
-		 * -> encoder links are only establish when things are
-		 *  actually up, hence no need to break them. */
-		WARN_ON(crtc->active);
-
-		for_each_encoder_on_crtc(dev, &crtc->base, encoder)
-			encoder->base.crtc = NULL;
-	}
-
 	if (crtc->active || HAS_GMCH_DISPLAY(dev)) {
 		/*
 		 * We start out with underrun reporting disabled to avoid races.
@@ -15738,7 +15800,7 @@ static void intel_modeset_readout_hw_sta
 		struct intel_crtc_state *crtc_state = crtc->config;
 		int pixclk = 0;
 
-		__drm_atomic_helper_crtc_destroy_state(&crtc->base, &crtc_state->base);
+		__drm_atomic_helper_crtc_destroy_state(&crtc_state->base);
 		memset(crtc_state, 0, sizeof(*crtc_state));
 		crtc_state->base.crtc = &crtc->base;
 
@@ -15777,22 +15839,17 @@ static void intel_modeset_readout_hw_sta
 	for (i = 0; i < dev_priv->num_shared_dpll; i++) {
 		struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i];
 
-		pll->on = pll->get_hw_state(dev_priv, pll,
-					    &pll->config.hw_state);
-		pll->active = 0;
+		pll->on = pll->funcs.get_hw_state(dev_priv, pll,
+						  &pll->config.hw_state);
 		pll->config.crtc_mask = 0;
 		for_each_intel_crtc(dev, crtc) {
-			if (crtc->active && intel_crtc_to_shared_dpll(crtc) == pll) {
-				pll->active++;
+			if (crtc->active && crtc->config->shared_dpll == pll)
 				pll->config.crtc_mask |= 1 << crtc->pipe;
-			}
 		}
+		pll->active_mask = pll->config.crtc_mask;
 
 		DRM_DEBUG_KMS("%s hw state readout: crtc_mask 0x%08x, on %i\n",
 			      pll->name, pll->config.crtc_mask, pll->on);
-
-		if (pll->config.crtc_mask)
-			intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS);
 	}
 
 	for_each_intel_encoder(dev, encoder) {
@@ -15874,6 +15931,8 @@ static void intel_modeset_readout_hw_sta
 			drm_calc_timestamping_constants(&crtc->base, &crtc->base.hwmode);
 			update_scanline_offset(crtc);
 		}
+
+		intel_pipe_config_sanity_check(dev_priv, crtc->config);
 	}
 }
 
@@ -15908,12 +15967,12 @@ intel_modeset_setup_hw_state(struct drm_
 	for (i = 0; i < dev_priv->num_shared_dpll; i++) {
 		struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i];
 
-		if (!pll->on || pll->active)
+		if (!pll->on || pll->active_mask)
 			continue;
 
 		DRM_DEBUG_KMS("%s enabled but not in use, disabling\n", pll->name);
 
-		pll->disable(dev_priv, pll);
+		pll->funcs.disable(dev_priv, pll);
 		pll->on = false;
 	}
 
@@ -15972,6 +16031,9 @@ retry:
 
 		state->acquire_ctx = &ctx;
 
+		/* ignore any reset values/BIOS leftovers in the WM registers */
+		to_intel_atomic_state(state)->skip_intermediate_wm = true;
+
 		for_each_crtc_in_state(state, crtc, crtc_state, i) {
 			/*
 			 * Force recalculation even if we restore
@@ -16022,9 +16084,8 @@ void intel_modeset_gem_init(struct drm_d
 			continue;
 
 		mutex_lock(&dev->struct_mutex);
-		ret = intel_pin_and_fence_fb_obj(c->primary,
-						 c->primary->fb,
-						 c->primary->state);
+		ret = intel_pin_and_fence_fb_obj(c->primary->fb,
+						 c->primary->state->rotation);
 		mutex_unlock(&dev->struct_mutex);
 		if (ret) {
 			DRM_ERROR("failed to pin boot fb on pipe %d\n",
@@ -16233,8 +16294,9 @@ intel_display_capture_error_state(struct
 			error->pipe[i].stat = I915_READ(PIPESTAT(i));
 	}
 
+	/* Note: this does not include DSI transcoders. */
 	error->num_transcoders = INTEL_INFO(dev)->num_pipes;
-	if (HAS_DDI(dev_priv->dev))
+	if (HAS_DDI(dev_priv))
 		error->num_transcoders++; /* Account for eDP. */
 
 	for (i = 0; i < error->num_transcoders; i++) {
@@ -16305,7 +16367,7 @@ intel_display_print_error_state(struct d
 	}
 
 	for (i = 0; i < error->num_transcoders; i++) {
-		err_printf(m, "CPU transcoder: %c\n",
+		err_printf(m, "CPU transcoder: %s\n",
 			   transcoder_name(error->transcoder[i].cpu_transcoder));
 		err_printf(m, "  Power: %s\n",
 			   onoff(error->transcoder[i].power_domain_on));
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_dp.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_dp.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_dp.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_dp.c	2016-07-24 15:23:50.000000000 -0400
@@ -129,6 +129,7 @@ static void edp_panel_vdd_off(struct int
 static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp);
 static void vlv_steal_power_sequencer(struct drm_device *dev,
 				      enum pipe pipe);
+static void intel_dp_unset_edid(struct intel_dp *intel_dp);
 
 static unsigned int intel_dp_unused_lane_mask(int lane_count)
 {
@@ -662,7 +663,7 @@ intel_dp_aux_wait_done(struct intel_dp *
 		done = wait_event_timeout(dev_priv->gmbus_wait_queue, C,
 					  msecs_to_jiffies_timeout(10));
 	else
-		done = wait_for_atomic(C, 10) == 0;
+		done = wait_for(C, 10) == 0;
 	if (!done)
 		DRM_ERROR("dp aux hw did not signal timeout (has irq: %i)!\n",
 			  has_aux_irq);
@@ -671,60 +672,55 @@ intel_dp_aux_wait_done(struct intel_dp *
 	return status;
 }
 
-static uint32_t i9xx_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
+static uint32_t g4x_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
 {
 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
-	struct drm_device *dev = intel_dig_port->base.base.dev;
+	struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev);
+
+	if (index)
+		return 0;
 
 	/*
 	 * The clock divider is based off the hrawclk, and would like to run at
-	 * 2MHz.  So, take the hrawclk value and divide by 2 and use that
+	 * 2MHz.  So, take the hrawclk value and divide by 2000 and use that
 	 */
-	return index ? 0 : DIV_ROUND_CLOSEST(intel_hrawclk(dev), 2);
+	return DIV_ROUND_CLOSEST(dev_priv->rawclk_freq, 2000);
 }
 
 static uint32_t ilk_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
 {
 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
-	struct drm_device *dev = intel_dig_port->base.base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev);
 
 	if (index)
 		return 0;
 
-	if (intel_dig_port->port == PORT_A) {
+	/*
+	 * The clock divider is based off the cdclk or PCH rawclk, and would
+	 * like to run at 2MHz.  So, take the cdclk or PCH rawclk value and
+	 * divide by 2000 and use that
+	 */
+	if (intel_dig_port->port == PORT_A)
 		return DIV_ROUND_CLOSEST(dev_priv->cdclk_freq, 2000);
-
-	} else {
-		return DIV_ROUND_CLOSEST(intel_pch_rawclk(dev), 2);
-	}
+	else
+		return DIV_ROUND_CLOSEST(dev_priv->rawclk_freq, 2000);
 }
 
 static uint32_t hsw_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
 {
 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
-	struct drm_device *dev = intel_dig_port->base.base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev);
 
-	if (intel_dig_port->port == PORT_A) {
-		if (index)
-			return 0;
-		return DIV_ROUND_CLOSEST(dev_priv->cdclk_freq, 2000);
-	} else if (HAS_PCH_LPT_H(dev_priv)) {
+	if (intel_dig_port->port != PORT_A && HAS_PCH_LPT_H(dev_priv)) {
 		/* Workaround for non-ULT HSW */
 		switch (index) {
 		case 0: return 63;
 		case 1: return 72;
 		default: return 0;
 		}
-	} else  {
-		return index ? 0 : DIV_ROUND_CLOSEST(intel_pch_rawclk(dev), 2);
 	}
-}
 
-static uint32_t vlv_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
-{
-	return index ? 0 : 100;
+	return ilk_get_aux_clock_divider(intel_dp, index);
 }
 
 static uint32_t skl_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
@@ -737,10 +733,10 @@ static uint32_t skl_get_aux_clock_divide
 	return index ? 0 : 1;
 }
 
-static uint32_t i9xx_get_aux_send_ctl(struct intel_dp *intel_dp,
-				      bool has_aux_irq,
-				      int send_bytes,
-				      uint32_t aux_clock_divider)
+static uint32_t g4x_get_aux_send_ctl(struct intel_dp *intel_dp,
+				     bool has_aux_irq,
+				     int send_bytes,
+				     uint32_t aux_clock_divider)
 {
 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
 	struct drm_device *dev = intel_dig_port->base.base.dev;
@@ -1229,71 +1225,6 @@ intel_dp_connector_unregister(struct int
 	intel_connector_unregister(intel_connector);
 }
 
-static void
-skl_edp_set_pll_config(struct intel_crtc_state *pipe_config)
-{
-	u32 ctrl1;
-
-	memset(&pipe_config->dpll_hw_state, 0,
-	       sizeof(pipe_config->dpll_hw_state));
-
-	pipe_config->ddi_pll_sel = SKL_DPLL0;
-	pipe_config->dpll_hw_state.cfgcr1 = 0;
-	pipe_config->dpll_hw_state.cfgcr2 = 0;
-
-	ctrl1 = DPLL_CTRL1_OVERRIDE(SKL_DPLL0);
-	switch (pipe_config->port_clock / 2) {
-	case 81000:
-		ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810,
-					      SKL_DPLL0);
-		break;
-	case 135000:
-		ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350,
-					      SKL_DPLL0);
-		break;
-	case 270000:
-		ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700,
-					      SKL_DPLL0);
-		break;
-	case 162000:
-		ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620,
-					      SKL_DPLL0);
-		break;
-	/* TBD: For DP link rates 2.16 GHz and 4.32 GHz, VCO is 8640 which
-	results in CDCLK change. Need to handle the change of CDCLK by
-	disabling pipes and re-enabling them */
-	case 108000:
-		ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080,
-					      SKL_DPLL0);
-		break;
-	case 216000:
-		ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160,
-					      SKL_DPLL0);
-		break;
-
-	}
-	pipe_config->dpll_hw_state.ctrl1 = ctrl1;
-}
-
-void
-hsw_dp_set_ddi_pll_sel(struct intel_crtc_state *pipe_config)
-{
-	memset(&pipe_config->dpll_hw_state, 0,
-	       sizeof(pipe_config->dpll_hw_state));
-
-	switch (pipe_config->port_clock / 2) {
-	case 81000:
-		pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_810;
-		break;
-	case 135000:
-		pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_1350;
-		break;
-	case 270000:
-		pipe_config->ddi_pll_sel = PORT_CLK_SEL_LCPLL_2700;
-		break;
-	}
-}
-
 static int
 intel_dp_sink_rates(struct intel_dp *intel_dp, const int **sink_rates)
 {
@@ -1570,10 +1501,10 @@ intel_dp_compute_config(struct intel_enc
 
 		/* Get bpp from vbt only for panels that dont have bpp in edid */
 		if (intel_connector->base.display_info.bpc == 0 &&
-			(dev_priv->vbt.edp_bpp && dev_priv->vbt.edp_bpp < bpp)) {
+			(dev_priv->vbt.edp.bpp && dev_priv->vbt.edp.bpp < bpp)) {
 			DRM_DEBUG_KMS("clamping bpp for eDP panel to BIOS-provided %i\n",
-				      dev_priv->vbt.edp_bpp);
-			bpp = dev_priv->vbt.edp_bpp;
+				      dev_priv->vbt.edp.bpp);
+			bpp = dev_priv->vbt.edp.bpp;
 		}
 
 		/*
@@ -1651,13 +1582,7 @@ found:
 				&pipe_config->dp_m2_n2);
 	}
 
-	if ((IS_SKYLAKE(dev)  || IS_KABYLAKE(dev)) && is_edp(intel_dp))
-		skl_edp_set_pll_config(pipe_config);
-	else if (IS_BROXTON(dev))
-		/* handled in ddi */;
-	else if (IS_HASWELL(dev) || IS_BROADWELL(dev))
-		hsw_dp_set_ddi_pll_sel(pipe_config);
-	else
+	if (!HAS_DDI(dev))
 		intel_dp_set_clock(encoder, pipe_config);
 
 	return true;
@@ -1779,11 +1704,11 @@ static void wait_panel_status(struct int
 			I915_READ(pp_stat_reg),
 			I915_READ(pp_ctrl_reg));
 
-	if (_wait_for((I915_READ(pp_stat_reg) & mask) == value, 5000, 10)) {
+	if (_wait_for((I915_READ(pp_stat_reg) & mask) == value,
+		      5 * USEC_PER_SEC, 10 * USEC_PER_MSEC))
 		DRM_ERROR("Panel status timeout: status %08x control %08x\n",
 				I915_READ(pp_stat_reg),
 				I915_READ(pp_ctrl_reg));
-	}
 
 	DRM_DEBUG_KMS("Wait complete\n");
 }
@@ -2290,6 +2215,15 @@ static void ironlake_edp_pll_on(struct i
 	POSTING_READ(DP_A);
 	udelay(500);
 
+	/*
+	 * [DevILK] Work around required when enabling DP PLL
+	 * while a pipe is enabled going to FDI:
+	 * 1. Wait for the start of vertical blank on the enabled pipe going to FDI
+	 * 2. Program DP PLL enable
+	 */
+	if (IS_GEN5(dev_priv))
+		intel_wait_for_vblank_if_active(dev_priv->dev, !crtc->pipe);
+
 	intel_dp->DP |= DP_PLL_ENABLE;
 
 	I915_WRITE(DP_A, intel_dp->DP);
@@ -2409,7 +2343,6 @@ static void intel_dp_get_config(struct i
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	enum port port = dp_to_dig_port(intel_dp)->port;
 	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
-	int dotclock;
 
 	tmp = I915_READ(intel_dp->output_reg);
 
@@ -2459,16 +2392,12 @@ static void intel_dp_get_config(struct i
 			pipe_config->port_clock = 270000;
 	}
 
-	dotclock = intel_dotclock_calculate(pipe_config->port_clock,
-					    &pipe_config->dp_m_n);
-
-	if (HAS_PCH_SPLIT(dev_priv->dev) && port != PORT_A)
-		ironlake_check_encoder_dotclock(pipe_config, dotclock);
-
-	pipe_config->base.adjusted_mode.crtc_clock = dotclock;
+	pipe_config->base.adjusted_mode.crtc_clock =
+		intel_dotclock_calculate(pipe_config->port_clock,
+					 &pipe_config->dp_m_n);
 
-	if (is_edp(intel_dp) && dev_priv->vbt.edp_bpp &&
-	    pipe_config->pipe_bpp > dev_priv->vbt.edp_bpp) {
+	if (is_edp(intel_dp) && dev_priv->vbt.edp.bpp &&
+	    pipe_config->pipe_bpp > dev_priv->vbt.edp.bpp) {
 		/*
 		 * This is a big fat ugly hack.
 		 *
@@ -2483,8 +2412,8 @@ static void intel_dp_get_config(struct i
 		 * load.
 		 */
 		DRM_DEBUG_KMS("pipe has %d bpp for eDP panel, overriding BIOS-provided max %d bpp\n",
-			      pipe_config->pipe_bpp, dev_priv->vbt.edp_bpp);
-		dev_priv->vbt.edp_bpp = pipe_config->pipe_bpp;
+			      pipe_config->pipe_bpp, dev_priv->vbt.edp.bpp);
+		dev_priv->vbt.edp.bpp = pipe_config->pipe_bpp;
 	}
 }
 
@@ -2710,7 +2639,6 @@ static void intel_enable_dp(struct intel
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
 	uint32_t dp_reg = I915_READ(intel_dp->output_reg);
-	enum port port = dp_to_dig_port(intel_dp)->port;
 	enum pipe pipe = crtc->pipe;
 
 	if (WARN_ON(dp_reg & DP_PORT_EN))
@@ -2721,35 +2649,12 @@ static void intel_enable_dp(struct intel
 	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
 		vlv_init_panel_power_sequencer(intel_dp);
 
-	/*
-	 * We get an occasional spurious underrun between the port
-	 * enable and vdd enable, when enabling port A eDP.
-	 *
-	 * FIXME: Not sure if this applies to (PCH) port D eDP as well
-	 */
-	if (port == PORT_A)
-		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
-
 	intel_dp_enable_port(intel_dp);
 
-	if (port == PORT_A && IS_GEN5(dev_priv)) {
-		/*
-		 * Underrun reporting for the other pipe was disabled in
-		 * g4x_pre_enable_dp(). The eDP PLL and port have now been
-		 * enabled, so it's now safe to re-enable underrun reporting.
-		 */
-		intel_wait_for_vblank_if_active(dev_priv->dev, !pipe);
-		intel_set_cpu_fifo_underrun_reporting(dev_priv, !pipe, true);
-		intel_set_pch_fifo_underrun_reporting(dev_priv, !pipe, true);
-	}
-
 	edp_panel_vdd_on(intel_dp);
 	edp_panel_on(intel_dp);
 	edp_panel_vdd_off(intel_dp, true);
 
-	if (port == PORT_A)
-		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
-
 	pps_unlock(intel_dp);
 
 	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
@@ -2791,26 +2696,11 @@ static void vlv_enable_dp(struct intel_e
 
 static void g4x_pre_enable_dp(struct intel_encoder *encoder)
 {
-	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
 	enum port port = dp_to_dig_port(intel_dp)->port;
-	enum pipe pipe = to_intel_crtc(encoder->base.crtc)->pipe;
 
 	intel_dp_prepare(encoder);
 
-	if (port == PORT_A && IS_GEN5(dev_priv)) {
-		/*
-		 * We get FIFO underruns on the other pipe when
-		 * enabling the CPU eDP PLL, and when enabling CPU
-		 * eDP port. We could potentially avoid the PLL
-		 * underrun with a vblank wait just prior to enabling
-		 * the PLL, but that doesn't appear to help the port
-		 * enable case. Just sweep it all under the rug.
-		 */
-		intel_set_cpu_fifo_underrun_reporting(dev_priv, !pipe, false);
-		intel_set_pch_fifo_underrun_reporting(dev_priv, !pipe, false);
-	}
-
 	/* Only ilk+ has port A */
 	if (port == PORT_A)
 		ironlake_edp_pll_on(intel_dp);
@@ -3184,47 +3074,14 @@ static void chv_dp_post_pll_disable(stru
 }
 
 /*
- * Native read with retry for link status and receiver capability reads for
- * cases where the sink may still be asleep.
- *
- * Sinks are *supposed* to come up within 1ms from an off state, but we're also
- * supposed to retry 3 times per the spec.
- */
-static ssize_t
-intel_dp_dpcd_read_wake(struct drm_dp_aux *aux, unsigned int offset,
-			void *buffer, size_t size)
-{
-	ssize_t ret;
-	int i;
-
-	/*
-	 * Sometime we just get the same incorrect byte repeated
-	 * over the entire buffer. Doing just one throw away read
-	 * initially seems to "solve" it.
-	 */
-	drm_dp_dpcd_read(aux, DP_DPCD_REV, buffer, 1);
-
-	for (i = 0; i < 3; i++) {
-		ret = drm_dp_dpcd_read(aux, offset, buffer, size);
-		if (ret == size)
-			return ret;
-		msleep(1);
-	}
-
-	return ret;
-}
-
-/*
  * Fetch AUX CH registers 0x202 - 0x207 which contain
  * link status information
  */
 bool
 intel_dp_get_link_status(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE])
 {
-	return intel_dp_dpcd_read_wake(&intel_dp->aux,
-				       DP_LANE0_1_STATUS,
-				       link_status,
-				       DP_LINK_STATUS_SIZE) == DP_LINK_STATUS_SIZE;
+	return drm_dp_dpcd_read(&intel_dp->aux, DP_LANE0_1_STATUS, link_status,
+				DP_LINK_STATUS_SIZE) == DP_LINK_STATUS_SIZE;
 }
 
 /* These are source-specific values. */
@@ -3238,7 +3095,7 @@ intel_dp_voltage_max(struct intel_dp *in
 	if (IS_BROXTON(dev))
 		return DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
 	else if (INTEL_INFO(dev)->gen >= 9) {
-		if (dev_priv->edp_low_vswing && port == PORT_A)
+		if (dev_priv->vbt.edp.low_vswing && port == PORT_A)
 			return DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
 		return DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
 	} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
@@ -3859,8 +3716,8 @@ intel_dp_get_dpcd(struct intel_dp *intel
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	uint8_t rev;
 
-	if (intel_dp_dpcd_read_wake(&intel_dp->aux, 0x000, intel_dp->dpcd,
-				    sizeof(intel_dp->dpcd)) < 0)
+	if (drm_dp_dpcd_read(&intel_dp->aux, 0x000, intel_dp->dpcd,
+			     sizeof(intel_dp->dpcd)) < 0)
 		return false; /* aux transfer failed */
 
 	DRM_DEBUG_KMS("DPCD: %*ph\n", (int) sizeof(intel_dp->dpcd), intel_dp->dpcd);
@@ -3868,12 +3725,33 @@ intel_dp_get_dpcd(struct intel_dp *intel
 	if (intel_dp->dpcd[DP_DPCD_REV] == 0)
 		return false; /* DPCD not present */
 
+	if (drm_dp_dpcd_read(&intel_dp->aux, DP_SINK_COUNT,
+			     &intel_dp->sink_count, 1) < 0)
+		return false;
+
+	/*
+	 * Sink count can change between short pulse hpd hence
+	 * a member variable in intel_dp will track any changes
+	 * between short pulse interrupts.
+	 */
+	intel_dp->sink_count = DP_GET_SINK_COUNT(intel_dp->sink_count);
+
+	/*
+	 * SINK_COUNT == 0 and DOWNSTREAM_PORT_PRESENT == 1 implies that
+	 * a dongle is present but no display. Unless we require to know
+	 * if a dongle is present or not, we don't need to update
+	 * downstream port information. So, an early return here saves
+	 * time from performing other operations which are not required.
+	 */
+	if (!is_edp(intel_dp) && !intel_dp->sink_count)
+		return false;
+
 	/* Check if the panel supports PSR */
 	memset(intel_dp->psr_dpcd, 0, sizeof(intel_dp->psr_dpcd));
 	if (is_edp(intel_dp)) {
-		intel_dp_dpcd_read_wake(&intel_dp->aux, DP_PSR_SUPPORT,
-					intel_dp->psr_dpcd,
-					sizeof(intel_dp->psr_dpcd));
+		drm_dp_dpcd_read(&intel_dp->aux, DP_PSR_SUPPORT,
+				 intel_dp->psr_dpcd,
+				 sizeof(intel_dp->psr_dpcd));
 		if (intel_dp->psr_dpcd[0] & DP_PSR_IS_SUPPORTED) {
 			dev_priv->psr.sink_support = true;
 			DRM_DEBUG_KMS("Detected EDP PSR Panel.\n");
@@ -3884,9 +3762,9 @@ intel_dp_get_dpcd(struct intel_dp *intel
 			uint8_t frame_sync_cap;
 
 			dev_priv->psr.sink_support = true;
-			intel_dp_dpcd_read_wake(&intel_dp->aux,
-					DP_SINK_DEVICE_AUX_FRAME_SYNC_CAP,
-					&frame_sync_cap, 1);
+			drm_dp_dpcd_read(&intel_dp->aux,
+					 DP_SINK_DEVICE_AUX_FRAME_SYNC_CAP,
+					 &frame_sync_cap, 1);
 			dev_priv->psr.aux_frame_sync = frame_sync_cap ? true : false;
 			/* PSR2 needs frame sync as well */
 			dev_priv->psr.psr2_support = dev_priv->psr.aux_frame_sync;
@@ -3902,15 +3780,13 @@ intel_dp_get_dpcd(struct intel_dp *intel
 	/* Intermediate frequency support */
 	if (is_edp(intel_dp) &&
 	    (intel_dp->dpcd[DP_EDP_CONFIGURATION_CAP] &	DP_DPCD_DISPLAY_CONTROL_CAPABLE) &&
-	    (intel_dp_dpcd_read_wake(&intel_dp->aux, DP_EDP_DPCD_REV, &rev, 1) == 1) &&
+	    (drm_dp_dpcd_read(&intel_dp->aux, DP_EDP_DPCD_REV, &rev, 1) == 1) &&
 	    (rev >= 0x03)) { /* eDp v1.4 or higher */
 		__le16 sink_rates[DP_MAX_SUPPORTED_RATES];
 		int i;
 
-		intel_dp_dpcd_read_wake(&intel_dp->aux,
-				DP_SUPPORTED_LINK_RATES,
-				sink_rates,
-				sizeof(sink_rates));
+		drm_dp_dpcd_read(&intel_dp->aux, DP_SUPPORTED_LINK_RATES,
+				sink_rates, sizeof(sink_rates));
 
 		for (i = 0; i < ARRAY_SIZE(sink_rates); i++) {
 			int val = le16_to_cpu(sink_rates[i]);
@@ -3933,9 +3809,9 @@ intel_dp_get_dpcd(struct intel_dp *intel
 	if (intel_dp->dpcd[DP_DPCD_REV] == 0x10)
 		return true; /* no per-port downstream info */
 
-	if (intel_dp_dpcd_read_wake(&intel_dp->aux, DP_DOWNSTREAM_PORT_0,
-				    intel_dp->downstream_ports,
-				    DP_MAX_DOWNSTREAM_PORTS) < 0)
+	if (drm_dp_dpcd_read(&intel_dp->aux, DP_DOWNSTREAM_PORT_0,
+			     intel_dp->downstream_ports,
+			     DP_MAX_DOWNSTREAM_PORTS) < 0)
 		return false; /* downstream port status fetch failed */
 
 	return true;
@@ -3949,11 +3825,11 @@ intel_dp_probe_oui(struct intel_dp *inte
 	if (!(intel_dp->dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT))
 		return;
 
-	if (intel_dp_dpcd_read_wake(&intel_dp->aux, DP_SINK_OUI, buf, 3) == 3)
+	if (drm_dp_dpcd_read(&intel_dp->aux, DP_SINK_OUI, buf, 3) == 3)
 		DRM_DEBUG_KMS("Sink OUI: %02hx%02hx%02hx\n",
 			      buf[0], buf[1], buf[2]);
 
-	if (intel_dp_dpcd_read_wake(&intel_dp->aux, DP_BRANCH_OUI, buf, 3) == 3)
+	if (drm_dp_dpcd_read(&intel_dp->aux, DP_BRANCH_OUI, buf, 3) == 3)
 		DRM_DEBUG_KMS("Branch OUI: %02hx%02hx%02hx\n",
 			      buf[0], buf[1], buf[2]);
 }
@@ -3963,13 +3839,16 @@ intel_dp_probe_mst(struct intel_dp *inte
 {
 	u8 buf[1];
 
+	if (!i915.enable_dp_mst)
+		return false;
+
 	if (!intel_dp->can_mst)
 		return false;
 
 	if (intel_dp->dpcd[DP_DPCD_REV] < 0x12)
 		return false;
 
-	if (intel_dp_dpcd_read_wake(&intel_dp->aux, DP_MSTM_CAP, buf, 1)) {
+	if (drm_dp_dpcd_read(&intel_dp->aux, DP_MSTM_CAP, buf, 1)) {
 		if (buf[0] & DP_MST_CAP) {
 			DRM_DEBUG_KMS("Sink is MST capable\n");
 			intel_dp->is_mst = true;
@@ -4106,7 +3985,7 @@ stop:
 static bool
 intel_dp_get_sink_irq(struct intel_dp *intel_dp, u8 *sink_irq_vector)
 {
-	return intel_dp_dpcd_read_wake(&intel_dp->aux,
+	return drm_dp_dpcd_read(&intel_dp->aux,
 				       DP_DEVICE_SERVICE_IRQ_VECTOR,
 				       sink_irq_vector, 1) == 1;
 }
@@ -4116,7 +3995,7 @@ intel_dp_get_sink_irq_esi(struct intel_d
 {
 	int ret;
 
-	ret = intel_dp_dpcd_read_wake(&intel_dp->aux,
+	ret = drm_dp_dpcd_read(&intel_dp->aux,
 					     DP_SINK_COUNT_ESI,
 					     sink_irq_vector, 14);
 	if (ret != 14)
@@ -4292,6 +4171,36 @@ go_again:
 	return -EINVAL;
 }
 
+static void
+intel_dp_check_link_status(struct intel_dp *intel_dp)
+{
+	struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
+	u8 link_status[DP_LINK_STATUS_SIZE];
+
+	WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
+
+	if (!intel_dp_get_link_status(intel_dp, link_status)) {
+		DRM_ERROR("Failed to get link status\n");
+		return;
+	}
+
+	if (!intel_encoder->base.crtc)
+		return;
+
+	if (!to_intel_crtc(intel_encoder->base.crtc)->active)
+		return;
+
+	/* if link training is requested we should perform it always */
+	if ((intel_dp->compliance_test_type == DP_TEST_LINK_TRAINING) ||
+	    (!drm_dp_channel_eq_ok(link_status, intel_dp->lane_count))) {
+		DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n",
+			      intel_encoder->base.name);
+		intel_dp_start_link_train(intel_dp);
+		intel_dp_stop_link_train(intel_dp);
+	}
+}
+
 /*
  * According to DP spec
  * 5.1.2:
@@ -4299,16 +4208,19 @@ go_again:
  *  2. Configure link according to Receiver Capabilities
  *  3. Use Link Training from 2.5.3.3 and 3.5.1.3
  *  4. Check link status on receipt of hot-plug interrupt
+ *
+ * intel_dp_short_pulse -  handles short pulse interrupts
+ * when full detection is not required.
+ * Returns %true if short pulse is handled and full detection
+ * is NOT required and %false otherwise.
  */
-static void
-intel_dp_check_link_status(struct intel_dp *intel_dp)
+static bool
+intel_dp_short_pulse(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
-	struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
 	u8 sink_irq_vector;
-	u8 link_status[DP_LINK_STATUS_SIZE];
-
-	WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
+	u8 old_sink_count = intel_dp->sink_count;
+	bool ret;
 
 	/*
 	 * Clearing compliance test variables to allow capturing
@@ -4318,20 +4230,17 @@ intel_dp_check_link_status(struct intel_
 	intel_dp->compliance_test_type = 0;
 	intel_dp->compliance_test_data = 0;
 
-	if (!intel_encoder->base.crtc)
-		return;
-
-	if (!to_intel_crtc(intel_encoder->base.crtc)->active)
-		return;
-
-	/* Try to read receiver status if the link appears to be up */
-	if (!intel_dp_get_link_status(intel_dp, link_status)) {
-		return;
-	}
+	/*
+	 * Now read the DPCD to see if it's actually running
+	 * If the current value of sink count doesn't match with
+	 * the value that was stored earlier or dpcd read failed
+	 * we need to do full detection
+	 */
+	ret = intel_dp_get_dpcd(intel_dp);
 
-	/* Now read the DPCD to see if it's actually running */
-	if (!intel_dp_get_dpcd(intel_dp)) {
-		return;
+	if ((old_sink_count != intel_dp->sink_count) || !ret) {
+		/* No need to proceed if we are going to do full detect */
+		return false;
 	}
 
 	/* Try to read the source of the interrupt */
@@ -4348,14 +4257,11 @@ intel_dp_check_link_status(struct intel_
 			DRM_DEBUG_DRIVER("CP or sink specific irq unhandled\n");
 	}
 
-	/* if link training is requested we should perform it always */
-	if ((intel_dp->compliance_test_type == DP_TEST_LINK_TRAINING) ||
-		(!drm_dp_channel_eq_ok(link_status, intel_dp->lane_count))) {
-		DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n",
-			      intel_encoder->base.name);
-		intel_dp_start_link_train(intel_dp);
-		intel_dp_stop_link_train(intel_dp);
-	}
+	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+	intel_dp_check_link_status(intel_dp);
+	drm_modeset_unlock(&dev->mode_config.connection_mutex);
+
+	return true;
 }
 
 /* XXX this is probably wrong for multiple downstream ports */
@@ -4368,6 +4274,9 @@ intel_dp_detect_dpcd(struct intel_dp *in
 	if (!intel_dp_get_dpcd(intel_dp))
 		return connector_status_disconnected;
 
+	if (is_edp(intel_dp))
+		return connector_status_connected;
+
 	/* if there's no downstream port, we're done */
 	if (!(dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT))
 		return connector_status_connected;
@@ -4375,14 +4284,9 @@ intel_dp_detect_dpcd(struct intel_dp *in
 	/* If we're HPD-aware, SINK_COUNT changes dynamically */
 	if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 &&
 	    intel_dp->downstream_ports[0] & DP_DS_PORT_HPD) {
-		uint8_t reg;
-
-		if (intel_dp_dpcd_read_wake(&intel_dp->aux, DP_SINK_COUNT,
-					    &reg, 1) < 0)
-			return connector_status_unknown;
 
-		return DP_GET_SINK_COUNT(reg) ? connector_status_connected
-					      : connector_status_disconnected;
+		return intel_dp->sink_count ?
+		connector_status_connected : connector_status_disconnected;
 	}
 
 	/* If no HPD, poke DDC gently */
@@ -4591,6 +4495,7 @@ intel_dp_set_edid(struct intel_dp *intel
 	struct intel_connector *intel_connector = intel_dp->attached_connector;
 	struct edid *edid;
 
+	intel_dp_unset_edid(intel_dp);
 	edid = intel_dp_get_edid(intel_dp);
 	intel_connector->detect_edid = edid;
 
@@ -4611,9 +4516,10 @@ intel_dp_unset_edid(struct intel_dp *int
 	intel_dp->has_audio = false;
 }
 
-static enum drm_connector_status
-intel_dp_detect(struct drm_connector *connector, bool force)
+static void
+intel_dp_long_pulse(struct intel_connector *intel_connector)
 {
+	struct drm_connector *connector = &intel_connector->base;
 	struct intel_dp *intel_dp = intel_attached_dp(connector);
 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
 	struct intel_encoder *intel_encoder = &intel_dig_port->base;
@@ -4623,17 +4529,6 @@ intel_dp_detect(struct drm_connector *co
 	bool ret;
 	u8 sink_irq_vector;
 
-	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
-		      connector->base.id, connector->name);
-	intel_dp_unset_edid(intel_dp);
-
-	if (intel_dp->is_mst) {
-		/* MST devices are disconnected from a monitor POV */
-		if (intel_encoder->type != INTEL_OUTPUT_EDP)
-			intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
-		return connector_status_disconnected;
-	}
-
 	power_domain = intel_display_port_aux_power_domain(intel_encoder);
 	intel_display_power_get(to_i915(dev), power_domain);
 
@@ -4651,19 +4546,42 @@ intel_dp_detect(struct drm_connector *co
 		intel_dp->compliance_test_type = 0;
 		intel_dp->compliance_test_data = 0;
 
+		if (intel_dp->is_mst) {
+			DRM_DEBUG_KMS("MST device may have disappeared %d vs %d\n",
+				      intel_dp->is_mst,
+				      intel_dp->mst_mgr.mst_state);
+			intel_dp->is_mst = false;
+			drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr,
+							intel_dp->is_mst);
+		}
+
 		goto out;
 	}
 
+	if (intel_encoder->type != INTEL_OUTPUT_EDP)
+		intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
+
 	intel_dp_probe_oui(intel_dp);
 
 	ret = intel_dp_probe_mst(intel_dp);
 	if (ret) {
-		/* if we are in MST mode then this connector
-		   won't appear connected or have anything with EDID on it */
-		if (intel_encoder->type != INTEL_OUTPUT_EDP)
-			intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
+		/*
+		 * If we are in MST mode then this connector
+		 * won't appear connected or have anything
+		 * with EDID on it
+		 */
 		status = connector_status_disconnected;
 		goto out;
+	} else if (connector->status == connector_status_connected) {
+		/*
+		 * If display was connected already and is still connected
+		 * check links status, there has been known issues of
+		 * link loss triggerring long pulse!!!!
+		 */
+		drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+		intel_dp_check_link_status(intel_dp);
+		drm_modeset_unlock(&dev->mode_config.connection_mutex);
+		goto out;
 	}
 
 	/*
@@ -4676,9 +4594,8 @@ intel_dp_detect(struct drm_connector *co
 
 	intel_dp_set_edid(intel_dp);
 
-	if (intel_encoder->type != INTEL_OUTPUT_EDP)
-		intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
 	status = connector_status_connected;
+	intel_dp->detect_done = true;
 
 	/* Try to read the source of the interrupt */
 	if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 &&
@@ -4695,8 +4612,43 @@ intel_dp_detect(struct drm_connector *co
 	}
 
 out:
+	if ((status != connector_status_connected) &&
+	    (intel_dp->is_mst == false))
+		intel_dp_unset_edid(intel_dp);
+
 	intel_display_power_put(to_i915(dev), power_domain);
-	return status;
+	return;
+}
+
+static enum drm_connector_status
+intel_dp_detect(struct drm_connector *connector, bool force)
+{
+	struct intel_dp *intel_dp = intel_attached_dp(connector);
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+	struct intel_encoder *intel_encoder = &intel_dig_port->base;
+	struct intel_connector *intel_connector = to_intel_connector(connector);
+
+	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
+		      connector->base.id, connector->name);
+
+	if (intel_dp->is_mst) {
+		/* MST devices are disconnected from a monitor POV */
+		intel_dp_unset_edid(intel_dp);
+		if (intel_encoder->type != INTEL_OUTPUT_EDP)
+			intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
+		return connector_status_disconnected;
+	}
+
+	/* If full detect is not performed yet, do a full detect */
+	if (!intel_dp->detect_done)
+		intel_dp_long_pulse(intel_dp->attached_connector);
+
+	intel_dp->detect_done = false;
+
+	if (is_edp(intel_dp) || intel_connector->detect_edid)
+		return connector_status_connected;
+	else
+		return connector_status_disconnected;
 }
 
 static void
@@ -4835,6 +4787,11 @@ intel_dp_set_property(struct drm_connect
 			DRM_DEBUG_KMS("no scaling not supported\n");
 			return -EINVAL;
 		}
+		if (HAS_GMCH_DISPLAY(dev_priv) &&
+		    val == DRM_MODE_SCALE_CENTER) {
+			DRM_DEBUG_KMS("centering not supported\n");
+			return -EINVAL;
+		}
 
 		if (intel_connector->panel.fitting_mode == val) {
 			/* the eDP scaling property is not changed */
@@ -4942,13 +4899,15 @@ static void intel_edp_panel_vdd_sanitize
 
 void intel_dp_encoder_reset(struct drm_encoder *encoder)
 {
-	struct intel_dp *intel_dp;
+	struct drm_i915_private *dev_priv = to_i915(encoder->dev);
+	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+	if (!HAS_DDI(dev_priv))
+		intel_dp->DP = I915_READ(intel_dp->output_reg);
 
 	if (to_intel_encoder(encoder)->type != INTEL_OUTPUT_EDP)
 		return;
 
-	intel_dp = enc_to_intel_dp(encoder);
-
 	pps_lock(intel_dp);
 
 	/*
@@ -5020,47 +4979,37 @@ intel_dp_hpd_pulse(struct intel_digital_
 	intel_display_power_get(dev_priv, power_domain);
 
 	if (long_hpd) {
-		/* indicate that we need to restart link training */
-		intel_dp->train_set_valid = false;
-
-		if (!intel_digital_port_connected(dev_priv, intel_dig_port))
-			goto mst_fail;
-
-		if (!intel_dp_get_dpcd(intel_dp)) {
-			goto mst_fail;
-		}
-
-		intel_dp_probe_oui(intel_dp);
+		intel_dp_long_pulse(intel_dp->attached_connector);
+		if (intel_dp->is_mst)
+			ret = IRQ_HANDLED;
+		goto put_power;
 
-		if (!intel_dp_probe_mst(intel_dp)) {
-			drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
-			intel_dp_check_link_status(intel_dp);
-			drm_modeset_unlock(&dev->mode_config.connection_mutex);
-			goto mst_fail;
-		}
 	} else {
 		if (intel_dp->is_mst) {
-			if (intel_dp_check_mst_status(intel_dp) == -EINVAL)
-				goto mst_fail;
+			if (intel_dp_check_mst_status(intel_dp) == -EINVAL) {
+				/*
+				 * If we were in MST mode, and device is not
+				 * there, get out of MST mode
+				 */
+				DRM_DEBUG_KMS("MST device may have disappeared %d vs %d\n",
+					      intel_dp->is_mst, intel_dp->mst_mgr.mst_state);
+				intel_dp->is_mst = false;
+				drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr,
+								intel_dp->is_mst);
+				goto put_power;
+			}
 		}
 
 		if (!intel_dp->is_mst) {
-			drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
-			intel_dp_check_link_status(intel_dp);
-			drm_modeset_unlock(&dev->mode_config.connection_mutex);
+			if (!intel_dp_short_pulse(intel_dp)) {
+				intel_dp_long_pulse(intel_dp->attached_connector);
+				goto put_power;
+			}
 		}
 	}
 
 	ret = IRQ_HANDLED;
 
-	goto put_power;
-mst_fail:
-	/* if we were in MST mode, and device is not there get out of MST mode */
-	if (intel_dp->is_mst) {
-		DRM_DEBUG_KMS("MST device may have disappeared %d vs %d\n", intel_dp->is_mst, intel_dp->mst_mgr.mst_state);
-		intel_dp->is_mst = false;
-		drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst);
-	}
 put_power:
 	intel_display_power_put(dev_priv, power_domain);
 
@@ -5071,14 +5020,6 @@ put_power:
 bool intel_dp_is_edp(struct drm_device *dev, enum port port)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	union child_device_config *p_child;
-	int i;
-	static const short port_mapping[] = {
-		[PORT_B] = DVO_PORT_DPB,
-		[PORT_C] = DVO_PORT_DPC,
-		[PORT_D] = DVO_PORT_DPD,
-		[PORT_E] = DVO_PORT_DPE,
-	};
 
 	/*
 	 * eDP not supported on g4x. so bail out early just
@@ -5090,18 +5031,7 @@ bool intel_dp_is_edp(struct drm_device *
 	if (port == PORT_A)
 		return true;
 
-	if (!dev_priv->vbt.child_dev_num)
-		return false;
-
-	for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
-		p_child = dev_priv->vbt.child_dev + i;
-
-		if (p_child->common.dvo_port == port_mapping[port] &&
-		    (p_child->common.device_type & DEVICE_TYPE_eDP_BITS) ==
-		    (DEVICE_TYPE_eDP & DEVICE_TYPE_eDP_BITS))
-			return true;
-	}
-	return false;
+	return intel_bios_is_port_edp(dev_priv, port);
 }
 
 void
@@ -5208,7 +5138,7 @@ intel_dp_init_panel_power_sequencer(stru
 	DRM_DEBUG_KMS("cur t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n",
 		      cur.t1_t3, cur.t8, cur.t9, cur.t10, cur.t11_t12);
 
-	vbt = dev_priv->vbt.edp_pps;
+	vbt = dev_priv->vbt.edp.pps;
 
 	/* Upper limits from eDP 1.3 spec. Note that we use the clunky units of
 	 * our hw here, which are all in 100usec. */
@@ -5259,7 +5189,7 @@ intel_dp_init_panel_power_sequencer_regi
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 pp_on, pp_off, pp_div, port_sel = 0;
-	int div = HAS_PCH_SPLIT(dev) ? intel_pch_rawclk(dev) : intel_hrawclk(dev);
+	int div = dev_priv->rawclk_freq / 1000;
 	i915_reg_t pp_on_reg, pp_off_reg, pp_div_reg, pp_ctrl_reg;
 	enum port port = dp_to_dig_port(intel_dp)->port;
 	const struct edp_power_seq *seq = &intel_dp->pps_delays;
@@ -5794,8 +5724,11 @@ static bool intel_edp_init_connector(str
 	if (!fixed_mode && dev_priv->vbt.lfp_lvds_vbt_mode) {
 		fixed_mode = drm_mode_duplicate(dev,
 					dev_priv->vbt.lfp_lvds_vbt_mode);
-		if (fixed_mode)
+		if (fixed_mode) {
 			fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
+			connector->display_info.width_mm = fixed_mode->width_mm;
+			connector->display_info.height_mm = fixed_mode->height_mm;
+		}
 	}
 	mutex_unlock(&dev->mode_config.mutex);
 
@@ -5852,19 +5785,17 @@ intel_dp_init_connector(struct intel_dig
 	/* intel_dp vfuncs */
 	if (INTEL_INFO(dev)->gen >= 9)
 		intel_dp->get_aux_clock_divider = skl_get_aux_clock_divider;
-	else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
-		intel_dp->get_aux_clock_divider = vlv_get_aux_clock_divider;
 	else if (IS_HASWELL(dev) || IS_BROADWELL(dev))
 		intel_dp->get_aux_clock_divider = hsw_get_aux_clock_divider;
 	else if (HAS_PCH_SPLIT(dev))
 		intel_dp->get_aux_clock_divider = ilk_get_aux_clock_divider;
 	else
-		intel_dp->get_aux_clock_divider = i9xx_get_aux_clock_divider;
+		intel_dp->get_aux_clock_divider = g4x_get_aux_clock_divider;
 
 	if (INTEL_INFO(dev)->gen >= 9)
 		intel_dp->get_aux_send_ctl = skl_get_aux_send_ctl;
 	else
-		intel_dp->get_aux_send_ctl = i9xx_get_aux_send_ctl;
+		intel_dp->get_aux_send_ctl = g4x_get_aux_send_ctl;
 
 	if (HAS_DDI(dev))
 		intel_dp->prepare_link_retrain = intel_ddi_prepare_link_retrain;
@@ -5994,9 +5925,9 @@ fail:
 	return false;
 }
 
-void
-intel_dp_init(struct drm_device *dev,
-	      i915_reg_t output_reg, enum port port)
+bool intel_dp_init(struct drm_device *dev,
+		   i915_reg_t output_reg,
+		   enum port port)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_digital_port *intel_dig_port;
@@ -6006,7 +5937,7 @@ intel_dp_init(struct drm_device *dev,
 
 	intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL);
 	if (!intel_dig_port)
-		return;
+		return false;
 
 	intel_connector = intel_connector_alloc();
 	if (!intel_connector)
@@ -6063,7 +5994,7 @@ intel_dp_init(struct drm_device *dev,
 	if (!intel_dp_init_connector(intel_dig_port, intel_connector))
 		goto err_init_connector;
 
-	return;
+	return true;
 
 err_init_connector:
 	drm_encoder_cleanup(encoder);
@@ -6071,8 +6002,7 @@ err_encoder_init:
 	kfree(intel_connector);
 err_connector_alloc:
 	kfree(intel_dig_port);
-
-	return;
+	return false;
 }
 
 void intel_dp_mst_suspend(struct drm_device *dev)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_dp_link_training.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_dp_link_training.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_dp_link_training.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_dp_link_training.c	2016-07-24 15:23:50.000000000 -0400
@@ -85,8 +85,7 @@ static bool
 intel_dp_reset_link_train(struct intel_dp *intel_dp,
 			uint8_t dp_train_pat)
 {
-	if (!intel_dp->train_set_valid)
-		memset(intel_dp->train_set, 0, sizeof(intel_dp->train_set));
+	memset(intel_dp->train_set, 0, sizeof(intel_dp->train_set));
 	intel_dp_set_signal_levels(intel_dp);
 	return intel_dp_set_link_train(intel_dp, dp_train_pat);
 }
@@ -161,23 +160,6 @@ intel_dp_link_training_clock_recovery(st
 			break;
 		}
 
-		/*
-		 * if we used previously trained voltage and pre-emphasis values
-		 * and we don't get clock recovery, reset link training values
-		 */
-		if (intel_dp->train_set_valid) {
-			DRM_DEBUG_KMS("clock recovery not ok, reset");
-			/* clear the flag as we are not reusing train set */
-			intel_dp->train_set_valid = false;
-			if (!intel_dp_reset_link_train(intel_dp,
-						       DP_TRAINING_PATTERN_1 |
-						       DP_LINK_SCRAMBLING_DISABLE)) {
-				DRM_ERROR("failed to enable link training\n");
-				return;
-			}
-			continue;
-		}
-
 		/* Check to see if we've tried the max voltage */
 		for (i = 0; i < intel_dp->lane_count; i++)
 			if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
@@ -284,7 +266,6 @@ intel_dp_link_training_channel_equalizat
 		/* Make sure clock is still ok */
 		if (!drm_dp_clock_recovery_ok(link_status,
 					      intel_dp->lane_count)) {
-			intel_dp->train_set_valid = false;
 			intel_dp_link_training_clock_recovery(intel_dp);
 			intel_dp_set_link_train(intel_dp,
 						training_pattern |
@@ -301,7 +282,6 @@ intel_dp_link_training_channel_equalizat
 
 		/* Try 5 times, then try clock recovery if that fails */
 		if (tries > 5) {
-			intel_dp->train_set_valid = false;
 			intel_dp_link_training_clock_recovery(intel_dp);
 			intel_dp_set_link_train(intel_dp,
 						training_pattern |
@@ -322,10 +302,8 @@ intel_dp_link_training_channel_equalizat
 
 	intel_dp_set_idle_link_train(intel_dp);
 
-	if (channel_eq) {
-		intel_dp->train_set_valid = true;
+	if (channel_eq)
 		DRM_DEBUG_KMS("Channel EQ done. DP Training successful\n");
-	}
 }
 
 void intel_dp_stop_link_train(struct intel_dp *intel_dp)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_dpll_mgr.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_dpll_mgr.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_dpll_mgr.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_dpll_mgr.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,1786 @@
+/*
+ * Copyright © 2006-2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "intel_drv.h"
+
+struct intel_shared_dpll *
+intel_get_shared_dpll_by_id(struct drm_i915_private *dev_priv,
+			    enum intel_dpll_id id)
+{
+	return &dev_priv->shared_dplls[id];
+}
+
+enum intel_dpll_id
+intel_get_shared_dpll_id(struct drm_i915_private *dev_priv,
+			 struct intel_shared_dpll *pll)
+{
+	if (WARN_ON(pll < dev_priv->shared_dplls||
+		    pll > &dev_priv->shared_dplls[dev_priv->num_shared_dpll]))
+		return -1;
+
+	return (enum intel_dpll_id) (pll - dev_priv->shared_dplls);
+}
+
+void
+intel_shared_dpll_config_get(struct intel_shared_dpll_config *config,
+			     struct intel_shared_dpll *pll,
+			     struct intel_crtc *crtc)
+{
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+	enum intel_dpll_id id = intel_get_shared_dpll_id(dev_priv, pll);
+
+	config[id].crtc_mask |= 1 << crtc->pipe;
+}
+
+void
+intel_shared_dpll_config_put(struct intel_shared_dpll_config *config,
+			     struct intel_shared_dpll *pll,
+			     struct intel_crtc *crtc)
+{
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+	enum intel_dpll_id id = intel_get_shared_dpll_id(dev_priv, pll);
+
+	config[id].crtc_mask &= ~(1 << crtc->pipe);
+}
+
+/* For ILK+ */
+void assert_shared_dpll(struct drm_i915_private *dev_priv,
+			struct intel_shared_dpll *pll,
+			bool state)
+{
+	bool cur_state;
+	struct intel_dpll_hw_state hw_state;
+
+	if (WARN(!pll, "asserting DPLL %s with no DPLL\n", onoff(state)))
+		return;
+
+	cur_state = pll->funcs.get_hw_state(dev_priv, pll, &hw_state);
+	I915_STATE_WARN(cur_state != state,
+	     "%s assertion failure (expected %s, current %s)\n",
+			pll->name, onoff(state), onoff(cur_state));
+}
+
+void intel_prepare_shared_dpll(struct intel_crtc *crtc)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_shared_dpll *pll = crtc->config->shared_dpll;
+
+	if (WARN_ON(pll == NULL))
+		return;
+
+	mutex_lock(&dev_priv->dpll_lock);
+	WARN_ON(!pll->config.crtc_mask);
+	if (!pll->active_mask) {
+		DRM_DEBUG_DRIVER("setting up %s\n", pll->name);
+		WARN_ON(pll->on);
+		assert_shared_dpll_disabled(dev_priv, pll);
+
+		pll->funcs.mode_set(dev_priv, pll);
+	}
+	mutex_unlock(&dev_priv->dpll_lock);
+}
+
+/**
+ * intel_enable_shared_dpll - enable PCH PLL
+ * @dev_priv: i915 private structure
+ * @pipe: pipe PLL to enable
+ *
+ * The PCH PLL needs to be enabled before the PCH transcoder, since it
+ * drives the transcoder clock.
+ */
+void intel_enable_shared_dpll(struct intel_crtc *crtc)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_shared_dpll *pll = crtc->config->shared_dpll;
+	unsigned crtc_mask = 1 << drm_crtc_index(&crtc->base);
+	unsigned old_mask;
+
+	if (WARN_ON(pll == NULL))
+		return;
+
+	mutex_lock(&dev_priv->dpll_lock);
+	old_mask = pll->active_mask;
+
+	if (WARN_ON(!(pll->config.crtc_mask & crtc_mask)) ||
+	    WARN_ON(pll->active_mask & crtc_mask))
+		goto out;
+
+	pll->active_mask |= crtc_mask;
+
+	DRM_DEBUG_KMS("enable %s (active %x, on? %d) for crtc %d\n",
+		      pll->name, pll->active_mask, pll->on,
+		      crtc->base.base.id);
+
+	if (old_mask) {
+		WARN_ON(!pll->on);
+		assert_shared_dpll_enabled(dev_priv, pll);
+		goto out;
+	}
+	WARN_ON(pll->on);
+
+	DRM_DEBUG_KMS("enabling %s\n", pll->name);
+	pll->funcs.enable(dev_priv, pll);
+	pll->on = true;
+
+out:
+	mutex_unlock(&dev_priv->dpll_lock);
+}
+
+void intel_disable_shared_dpll(struct intel_crtc *crtc)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_shared_dpll *pll = crtc->config->shared_dpll;
+	unsigned crtc_mask = 1 << drm_crtc_index(&crtc->base);
+
+	/* PCH only available on ILK+ */
+	if (INTEL_INFO(dev)->gen < 5)
+		return;
+
+	if (pll == NULL)
+		return;
+
+	mutex_lock(&dev_priv->dpll_lock);
+	if (WARN_ON(!(pll->active_mask & crtc_mask)))
+		goto out;
+
+	DRM_DEBUG_KMS("disable %s (active %x, on? %d) for crtc %d\n",
+		      pll->name, pll->active_mask, pll->on,
+		      crtc->base.base.id);
+
+	assert_shared_dpll_enabled(dev_priv, pll);
+	WARN_ON(!pll->on);
+
+	pll->active_mask &= ~crtc_mask;
+	if (pll->active_mask)
+		goto out;
+
+	DRM_DEBUG_KMS("disabling %s\n", pll->name);
+	pll->funcs.disable(dev_priv, pll);
+	pll->on = false;
+
+out:
+	mutex_unlock(&dev_priv->dpll_lock);
+}
+
+static struct intel_shared_dpll *
+intel_find_shared_dpll(struct intel_crtc *crtc,
+		       struct intel_crtc_state *crtc_state,
+		       enum intel_dpll_id range_min,
+		       enum intel_dpll_id range_max)
+{
+	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+	struct intel_shared_dpll *pll;
+	struct intel_shared_dpll_config *shared_dpll;
+	enum intel_dpll_id i;
+
+	shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state);
+
+	for (i = range_min; i <= range_max; i++) {
+		pll = &dev_priv->shared_dplls[i];
+
+		/* Only want to check enabled timings first */
+		if (shared_dpll[i].crtc_mask == 0)
+			continue;
+
+		if (memcmp(&crtc_state->dpll_hw_state,
+			   &shared_dpll[i].hw_state,
+			   sizeof(crtc_state->dpll_hw_state)) == 0) {
+			DRM_DEBUG_KMS("CRTC:%d sharing existing %s (crtc mask 0x%08x, active %x)\n",
+				      crtc->base.base.id, pll->name,
+				      shared_dpll[i].crtc_mask,
+				      pll->active_mask);
+			return pll;
+		}
+	}
+
+	/* Ok no matching timings, maybe there's a free one? */
+	for (i = range_min; i <= range_max; i++) {
+		pll = &dev_priv->shared_dplls[i];
+		if (shared_dpll[i].crtc_mask == 0) {
+			DRM_DEBUG_KMS("CRTC:%d allocated %s\n",
+				      crtc->base.base.id, pll->name);
+			return pll;
+		}
+	}
+
+	return NULL;
+}
+
+static void
+intel_reference_shared_dpll(struct intel_shared_dpll *pll,
+			    struct intel_crtc_state *crtc_state)
+{
+	struct intel_shared_dpll_config *shared_dpll;
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+	enum intel_dpll_id i = pll->id;
+
+	shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state);
+
+	if (shared_dpll[i].crtc_mask == 0)
+		shared_dpll[i].hw_state =
+			crtc_state->dpll_hw_state;
+
+	crtc_state->shared_dpll = pll;
+	DRM_DEBUG_DRIVER("using %s for pipe %c\n", pll->name,
+			 pipe_name(crtc->pipe));
+
+	intel_shared_dpll_config_get(shared_dpll, pll, crtc);
+}
+
+void intel_shared_dpll_commit(struct drm_atomic_state *state)
+{
+	struct drm_i915_private *dev_priv = to_i915(state->dev);
+	struct intel_shared_dpll_config *shared_dpll;
+	struct intel_shared_dpll *pll;
+	enum intel_dpll_id i;
+
+	if (!to_intel_atomic_state(state)->dpll_set)
+		return;
+
+	shared_dpll = to_intel_atomic_state(state)->shared_dpll;
+	for (i = 0; i < dev_priv->num_shared_dpll; i++) {
+		pll = &dev_priv->shared_dplls[i];
+		pll->config = shared_dpll[i];
+	}
+}
+
+static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
+				      struct intel_shared_dpll *pll,
+				      struct intel_dpll_hw_state *hw_state)
+{
+	uint32_t val;
+
+	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
+		return false;
+
+	val = I915_READ(PCH_DPLL(pll->id));
+	hw_state->dpll = val;
+	hw_state->fp0 = I915_READ(PCH_FP0(pll->id));
+	hw_state->fp1 = I915_READ(PCH_FP1(pll->id));
+
+	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+
+	return val & DPLL_VCO_ENABLE;
+}
+
+static void ibx_pch_dpll_mode_set(struct drm_i915_private *dev_priv,
+				  struct intel_shared_dpll *pll)
+{
+	I915_WRITE(PCH_FP0(pll->id), pll->config.hw_state.fp0);
+	I915_WRITE(PCH_FP1(pll->id), pll->config.hw_state.fp1);
+}
+
+static void ibx_assert_pch_refclk_enabled(struct drm_i915_private *dev_priv)
+{
+	u32 val;
+	bool enabled;
+
+	I915_STATE_WARN_ON(!(HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)));
+
+	val = I915_READ(PCH_DREF_CONTROL);
+	enabled = !!(val & (DREF_SSC_SOURCE_MASK | DREF_NONSPREAD_SOURCE_MASK |
+			    DREF_SUPERSPREAD_SOURCE_MASK));
+	I915_STATE_WARN(!enabled, "PCH refclk assertion failure, should be active but is disabled\n");
+}
+
+static void ibx_pch_dpll_enable(struct drm_i915_private *dev_priv,
+				struct intel_shared_dpll *pll)
+{
+	/* PCH refclock must be enabled first */
+	ibx_assert_pch_refclk_enabled(dev_priv);
+
+	I915_WRITE(PCH_DPLL(pll->id), pll->config.hw_state.dpll);
+
+	/* Wait for the clocks to stabilize. */
+	POSTING_READ(PCH_DPLL(pll->id));
+	udelay(150);
+
+	/* The pixel multiplier can only be updated once the
+	 * DPLL is enabled and the clocks are stable.
+	 *
+	 * So write it again.
+	 */
+	I915_WRITE(PCH_DPLL(pll->id), pll->config.hw_state.dpll);
+	POSTING_READ(PCH_DPLL(pll->id));
+	udelay(200);
+}
+
+static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv,
+				 struct intel_shared_dpll *pll)
+{
+	struct drm_device *dev = dev_priv->dev;
+	struct intel_crtc *crtc;
+
+	/* Make sure no transcoder isn't still depending on us. */
+	for_each_intel_crtc(dev, crtc) {
+		if (crtc->config->shared_dpll == pll)
+			assert_pch_transcoder_disabled(dev_priv, crtc->pipe);
+	}
+
+	I915_WRITE(PCH_DPLL(pll->id), 0);
+	POSTING_READ(PCH_DPLL(pll->id));
+	udelay(200);
+}
+
+static struct intel_shared_dpll *
+ibx_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
+	     struct intel_encoder *encoder)
+{
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+	struct intel_shared_dpll *pll;
+	enum intel_dpll_id i;
+
+	if (HAS_PCH_IBX(dev_priv)) {
+		/* Ironlake PCH has a fixed PLL->PCH pipe mapping. */
+		i = (enum intel_dpll_id) crtc->pipe;
+		pll = &dev_priv->shared_dplls[i];
+
+		DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n",
+			      crtc->base.base.id, pll->name);
+	} else {
+		pll = intel_find_shared_dpll(crtc, crtc_state,
+					     DPLL_ID_PCH_PLL_A,
+					     DPLL_ID_PCH_PLL_B);
+	}
+
+	if (!pll)
+		return NULL;
+
+	/* reference the pll */
+	intel_reference_shared_dpll(pll, crtc_state);
+
+	return pll;
+}
+
+static const struct intel_shared_dpll_funcs ibx_pch_dpll_funcs = {
+	.mode_set = ibx_pch_dpll_mode_set,
+	.enable = ibx_pch_dpll_enable,
+	.disable = ibx_pch_dpll_disable,
+	.get_hw_state = ibx_pch_dpll_get_hw_state,
+};
+
+static void hsw_ddi_wrpll_enable(struct drm_i915_private *dev_priv,
+			       struct intel_shared_dpll *pll)
+{
+	I915_WRITE(WRPLL_CTL(pll->id), pll->config.hw_state.wrpll);
+	POSTING_READ(WRPLL_CTL(pll->id));
+	udelay(20);
+}
+
+static void hsw_ddi_spll_enable(struct drm_i915_private *dev_priv,
+				struct intel_shared_dpll *pll)
+{
+	I915_WRITE(SPLL_CTL, pll->config.hw_state.spll);
+	POSTING_READ(SPLL_CTL);
+	udelay(20);
+}
+
+static void hsw_ddi_wrpll_disable(struct drm_i915_private *dev_priv,
+				  struct intel_shared_dpll *pll)
+{
+	uint32_t val;
+
+	val = I915_READ(WRPLL_CTL(pll->id));
+	I915_WRITE(WRPLL_CTL(pll->id), val & ~WRPLL_PLL_ENABLE);
+	POSTING_READ(WRPLL_CTL(pll->id));
+}
+
+static void hsw_ddi_spll_disable(struct drm_i915_private *dev_priv,
+				 struct intel_shared_dpll *pll)
+{
+	uint32_t val;
+
+	val = I915_READ(SPLL_CTL);
+	I915_WRITE(SPLL_CTL, val & ~SPLL_PLL_ENABLE);
+	POSTING_READ(SPLL_CTL);
+}
+
+static bool hsw_ddi_wrpll_get_hw_state(struct drm_i915_private *dev_priv,
+				       struct intel_shared_dpll *pll,
+				       struct intel_dpll_hw_state *hw_state)
+{
+	uint32_t val;
+
+	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
+		return false;
+
+	val = I915_READ(WRPLL_CTL(pll->id));
+	hw_state->wrpll = val;
+
+	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+
+	return val & WRPLL_PLL_ENABLE;
+}
+
+static bool hsw_ddi_spll_get_hw_state(struct drm_i915_private *dev_priv,
+				      struct intel_shared_dpll *pll,
+				      struct intel_dpll_hw_state *hw_state)
+{
+	uint32_t val;
+
+	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
+		return false;
+
+	val = I915_READ(SPLL_CTL);
+	hw_state->spll = val;
+
+	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+
+	return val & SPLL_PLL_ENABLE;
+}
+
+static uint32_t hsw_pll_to_ddi_pll_sel(struct intel_shared_dpll *pll)
+{
+	switch (pll->id) {
+	case DPLL_ID_WRPLL1:
+		return PORT_CLK_SEL_WRPLL1;
+	case DPLL_ID_WRPLL2:
+		return PORT_CLK_SEL_WRPLL2;
+	case DPLL_ID_SPLL:
+		return PORT_CLK_SEL_SPLL;
+	case DPLL_ID_LCPLL_810:
+		return PORT_CLK_SEL_LCPLL_810;
+	case DPLL_ID_LCPLL_1350:
+		return PORT_CLK_SEL_LCPLL_1350;
+	case DPLL_ID_LCPLL_2700:
+		return PORT_CLK_SEL_LCPLL_2700;
+	default:
+		return PORT_CLK_SEL_NONE;
+	}
+}
+
+#define LC_FREQ 2700
+#define LC_FREQ_2K U64_C(LC_FREQ * 2000)
+
+#define P_MIN 2
+#define P_MAX 64
+#define P_INC 2
+
+/* Constraints for PLL good behavior */
+#define REF_MIN 48
+#define REF_MAX 400
+#define VCO_MIN 2400
+#define VCO_MAX 4800
+
+struct hsw_wrpll_rnp {
+	unsigned p, n2, r2;
+};
+
+static unsigned hsw_wrpll_get_budget_for_freq(int clock)
+{
+	unsigned budget;
+
+	switch (clock) {
+	case 25175000:
+	case 25200000:
+	case 27000000:
+	case 27027000:
+	case 37762500:
+	case 37800000:
+	case 40500000:
+	case 40541000:
+	case 54000000:
+	case 54054000:
+	case 59341000:
+	case 59400000:
+	case 72000000:
+	case 74176000:
+	case 74250000:
+	case 81000000:
+	case 81081000:
+	case 89012000:
+	case 89100000:
+	case 108000000:
+	case 108108000:
+	case 111264000:
+	case 111375000:
+	case 148352000:
+	case 148500000:
+	case 162000000:
+	case 162162000:
+	case 222525000:
+	case 222750000:
+	case 296703000:
+	case 297000000:
+		budget = 0;
+		break;
+	case 233500000:
+	case 245250000:
+	case 247750000:
+	case 253250000:
+	case 298000000:
+		budget = 1500;
+		break;
+	case 169128000:
+	case 169500000:
+	case 179500000:
+	case 202000000:
+		budget = 2000;
+		break;
+	case 256250000:
+	case 262500000:
+	case 270000000:
+	case 272500000:
+	case 273750000:
+	case 280750000:
+	case 281250000:
+	case 286000000:
+	case 291750000:
+		budget = 4000;
+		break;
+	case 267250000:
+	case 268500000:
+		budget = 5000;
+		break;
+	default:
+		budget = 1000;
+		break;
+	}
+
+	return budget;
+}
+
+static void hsw_wrpll_update_rnp(uint64_t freq2k, unsigned budget,
+				 unsigned r2, unsigned n2, unsigned p,
+				 struct hsw_wrpll_rnp *best)
+{
+	uint64_t a, b, c, d, diff, diff_best;
+
+	/* No best (r,n,p) yet */
+	if (best->p == 0) {
+		best->p = p;
+		best->n2 = n2;
+		best->r2 = r2;
+		return;
+	}
+
+	/*
+	 * Output clock is (LC_FREQ_2K / 2000) * N / (P * R), which compares to
+	 * freq2k.
+	 *
+	 * delta = 1e6 *
+	 *	   abs(freq2k - (LC_FREQ_2K * n2/(p * r2))) /
+	 *	   freq2k;
+	 *
+	 * and we would like delta <= budget.
+	 *
+	 * If the discrepancy is above the PPM-based budget, always prefer to
+	 * improve upon the previous solution.  However, if you're within the
+	 * budget, try to maximize Ref * VCO, that is N / (P * R^2).
+	 */
+	a = freq2k * budget * p * r2;
+	b = freq2k * budget * best->p * best->r2;
+	diff = abs_diff(freq2k * p * r2, LC_FREQ_2K * n2);
+	diff_best = abs_diff(freq2k * best->p * best->r2,
+			     LC_FREQ_2K * best->n2);
+	c = 1000000 * diff;
+	d = 1000000 * diff_best;
+
+	if (a < c && b < d) {
+		/* If both are above the budget, pick the closer */
+		if (best->p * best->r2 * diff < p * r2 * diff_best) {
+			best->p = p;
+			best->n2 = n2;
+			best->r2 = r2;
+		}
+	} else if (a >= c && b < d) {
+		/* If A is below the threshold but B is above it?  Update. */
+		best->p = p;
+		best->n2 = n2;
+		best->r2 = r2;
+	} else if (a >= c && b >= d) {
+		/* Both are below the limit, so pick the higher n2/(r2*r2) */
+		if (n2 * best->r2 * best->r2 > best->n2 * r2 * r2) {
+			best->p = p;
+			best->n2 = n2;
+			best->r2 = r2;
+		}
+	}
+	/* Otherwise a < c && b >= d, do nothing */
+}
+
+static void
+hsw_ddi_calculate_wrpll(int clock /* in Hz */,
+			unsigned *r2_out, unsigned *n2_out, unsigned *p_out)
+{
+	uint64_t freq2k;
+	unsigned p, n2, r2;
+	struct hsw_wrpll_rnp best = { 0, 0, 0 };
+	unsigned budget;
+
+	freq2k = clock / 100;
+
+	budget = hsw_wrpll_get_budget_for_freq(clock);
+
+	/* Special case handling for 540 pixel clock: bypass WR PLL entirely
+	 * and directly pass the LC PLL to it. */
+	if (freq2k == 5400000) {
+		*n2_out = 2;
+		*p_out = 1;
+		*r2_out = 2;
+		return;
+	}
+
+	/*
+	 * Ref = LC_FREQ / R, where Ref is the actual reference input seen by
+	 * the WR PLL.
+	 *
+	 * We want R so that REF_MIN <= Ref <= REF_MAX.
+	 * Injecting R2 = 2 * R gives:
+	 *   REF_MAX * r2 > LC_FREQ * 2 and
+	 *   REF_MIN * r2 < LC_FREQ * 2
+	 *
+	 * Which means the desired boundaries for r2 are:
+	 *  LC_FREQ * 2 / REF_MAX < r2 < LC_FREQ * 2 / REF_MIN
+	 *
+	 */
+	for (r2 = LC_FREQ * 2 / REF_MAX + 1;
+	     r2 <= LC_FREQ * 2 / REF_MIN;
+	     r2++) {
+
+		/*
+		 * VCO = N * Ref, that is: VCO = N * LC_FREQ / R
+		 *
+		 * Once again we want VCO_MIN <= VCO <= VCO_MAX.
+		 * Injecting R2 = 2 * R and N2 = 2 * N, we get:
+		 *   VCO_MAX * r2 > n2 * LC_FREQ and
+		 *   VCO_MIN * r2 < n2 * LC_FREQ)
+		 *
+		 * Which means the desired boundaries for n2 are:
+		 * VCO_MIN * r2 / LC_FREQ < n2 < VCO_MAX * r2 / LC_FREQ
+		 */
+		for (n2 = VCO_MIN * r2 / LC_FREQ + 1;
+		     n2 <= VCO_MAX * r2 / LC_FREQ;
+		     n2++) {
+
+			for (p = P_MIN; p <= P_MAX; p += P_INC)
+				hsw_wrpll_update_rnp(freq2k, budget,
+						     r2, n2, p, &best);
+		}
+	}
+
+	*n2_out = best.n2;
+	*p_out = best.p;
+	*r2_out = best.r2;
+}
+
+static struct intel_shared_dpll *
+hsw_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
+	     struct intel_encoder *encoder)
+{
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+	struct intel_shared_dpll *pll;
+	int clock = crtc_state->port_clock;
+
+	memset(&crtc_state->dpll_hw_state, 0,
+	       sizeof(crtc_state->dpll_hw_state));
+
+	if (encoder->type == INTEL_OUTPUT_HDMI) {
+		uint32_t val;
+		unsigned p, n2, r2;
+
+		hsw_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p);
+
+		val = WRPLL_PLL_ENABLE | WRPLL_PLL_LCPLL |
+		      WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) |
+		      WRPLL_DIVIDER_POST(p);
+
+		crtc_state->dpll_hw_state.wrpll = val;
+
+		pll = intel_find_shared_dpll(crtc, crtc_state,
+					     DPLL_ID_WRPLL1, DPLL_ID_WRPLL2);
+
+	} else if (encoder->type == INTEL_OUTPUT_DISPLAYPORT ||
+		   encoder->type == INTEL_OUTPUT_DP_MST ||
+		   encoder->type == INTEL_OUTPUT_EDP) {
+		enum intel_dpll_id pll_id;
+
+		switch (clock / 2) {
+		case 81000:
+			pll_id = DPLL_ID_LCPLL_810;
+			break;
+		case 135000:
+			pll_id = DPLL_ID_LCPLL_1350;
+			break;
+		case 270000:
+			pll_id = DPLL_ID_LCPLL_2700;
+			break;
+		default:
+			DRM_DEBUG_KMS("Invalid clock for DP: %d\n", clock);
+			return NULL;
+		}
+
+		pll = intel_get_shared_dpll_by_id(dev_priv, pll_id);
+
+	} else if (encoder->type == INTEL_OUTPUT_ANALOG) {
+		if (WARN_ON(crtc_state->port_clock / 2 != 135000))
+			return NULL;
+
+		crtc_state->dpll_hw_state.spll =
+			SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC;
+
+		pll = intel_find_shared_dpll(crtc, crtc_state,
+					     DPLL_ID_SPLL, DPLL_ID_SPLL);
+	} else {
+		return NULL;
+	}
+
+	if (!pll)
+		return NULL;
+
+	crtc_state->ddi_pll_sel = hsw_pll_to_ddi_pll_sel(pll);
+
+	intel_reference_shared_dpll(pll, crtc_state);
+
+	return pll;
+}
+
+
+static const struct intel_shared_dpll_funcs hsw_ddi_wrpll_funcs = {
+	.enable = hsw_ddi_wrpll_enable,
+	.disable = hsw_ddi_wrpll_disable,
+	.get_hw_state = hsw_ddi_wrpll_get_hw_state,
+};
+
+static const struct intel_shared_dpll_funcs hsw_ddi_spll_funcs = {
+	.enable = hsw_ddi_spll_enable,
+	.disable = hsw_ddi_spll_disable,
+	.get_hw_state = hsw_ddi_spll_get_hw_state,
+};
+
+static void hsw_ddi_lcpll_enable(struct drm_i915_private *dev_priv,
+				 struct intel_shared_dpll *pll)
+{
+}
+
+static void hsw_ddi_lcpll_disable(struct drm_i915_private *dev_priv,
+				  struct intel_shared_dpll *pll)
+{
+}
+
+static bool hsw_ddi_lcpll_get_hw_state(struct drm_i915_private *dev_priv,
+				       struct intel_shared_dpll *pll,
+				       struct intel_dpll_hw_state *hw_state)
+{
+	return true;
+}
+
+static const struct intel_shared_dpll_funcs hsw_ddi_lcpll_funcs = {
+	.enable = hsw_ddi_lcpll_enable,
+	.disable = hsw_ddi_lcpll_disable,
+	.get_hw_state = hsw_ddi_lcpll_get_hw_state,
+};
+
+struct skl_dpll_regs {
+	i915_reg_t ctl, cfgcr1, cfgcr2;
+};
+
+/* this array is indexed by the *shared* pll id */
+static const struct skl_dpll_regs skl_dpll_regs[4] = {
+	{
+		/* DPLL 0 */
+		.ctl = LCPLL1_CTL,
+		/* DPLL 0 doesn't support HDMI mode */
+	},
+	{
+		/* DPLL 1 */
+		.ctl = LCPLL2_CTL,
+		.cfgcr1 = DPLL_CFGCR1(SKL_DPLL1),
+		.cfgcr2 = DPLL_CFGCR2(SKL_DPLL1),
+	},
+	{
+		/* DPLL 2 */
+		.ctl = WRPLL_CTL(0),
+		.cfgcr1 = DPLL_CFGCR1(SKL_DPLL2),
+		.cfgcr2 = DPLL_CFGCR2(SKL_DPLL2),
+	},
+	{
+		/* DPLL 3 */
+		.ctl = WRPLL_CTL(1),
+		.cfgcr1 = DPLL_CFGCR1(SKL_DPLL3),
+		.cfgcr2 = DPLL_CFGCR2(SKL_DPLL3),
+	},
+};
+
+static void skl_ddi_pll_write_ctrl1(struct drm_i915_private *dev_priv,
+				    struct intel_shared_dpll *pll)
+{
+	uint32_t val;
+
+	val = I915_READ(DPLL_CTRL1);
+
+	val &= ~(DPLL_CTRL1_HDMI_MODE(pll->id) | DPLL_CTRL1_SSC(pll->id) |
+		 DPLL_CTRL1_LINK_RATE_MASK(pll->id));
+	val |= pll->config.hw_state.ctrl1 << (pll->id * 6);
+
+	I915_WRITE(DPLL_CTRL1, val);
+	POSTING_READ(DPLL_CTRL1);
+}
+
+static void skl_ddi_pll_enable(struct drm_i915_private *dev_priv,
+			       struct intel_shared_dpll *pll)
+{
+	const struct skl_dpll_regs *regs = skl_dpll_regs;
+
+	skl_ddi_pll_write_ctrl1(dev_priv, pll);
+
+	I915_WRITE(regs[pll->id].cfgcr1, pll->config.hw_state.cfgcr1);
+	I915_WRITE(regs[pll->id].cfgcr2, pll->config.hw_state.cfgcr2);
+	POSTING_READ(regs[pll->id].cfgcr1);
+	POSTING_READ(regs[pll->id].cfgcr2);
+
+	/* the enable bit is always bit 31 */
+	I915_WRITE(regs[pll->id].ctl,
+		   I915_READ(regs[pll->id].ctl) | LCPLL_PLL_ENABLE);
+
+	if (wait_for(I915_READ(DPLL_STATUS) & DPLL_LOCK(pll->id), 5))
+		DRM_ERROR("DPLL %d not locked\n", pll->id);
+}
+
+static void skl_ddi_dpll0_enable(struct drm_i915_private *dev_priv,
+				 struct intel_shared_dpll *pll)
+{
+	skl_ddi_pll_write_ctrl1(dev_priv, pll);
+}
+
+static void skl_ddi_pll_disable(struct drm_i915_private *dev_priv,
+				struct intel_shared_dpll *pll)
+{
+	const struct skl_dpll_regs *regs = skl_dpll_regs;
+
+	/* the enable bit is always bit 31 */
+	I915_WRITE(regs[pll->id].ctl,
+		   I915_READ(regs[pll->id].ctl) & ~LCPLL_PLL_ENABLE);
+	POSTING_READ(regs[pll->id].ctl);
+}
+
+static void skl_ddi_dpll0_disable(struct drm_i915_private *dev_priv,
+				  struct intel_shared_dpll *pll)
+{
+}
+
+static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
+				     struct intel_shared_dpll *pll,
+				     struct intel_dpll_hw_state *hw_state)
+{
+	uint32_t val;
+	const struct skl_dpll_regs *regs = skl_dpll_regs;
+	bool ret;
+
+	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
+		return false;
+
+	ret = false;
+
+	val = I915_READ(regs[pll->id].ctl);
+	if (!(val & LCPLL_PLL_ENABLE))
+		goto out;
+
+	val = I915_READ(DPLL_CTRL1);
+	hw_state->ctrl1 = (val >> (pll->id * 6)) & 0x3f;
+
+	/* avoid reading back stale values if HDMI mode is not enabled */
+	if (val & DPLL_CTRL1_HDMI_MODE(pll->id)) {
+		hw_state->cfgcr1 = I915_READ(regs[pll->id].cfgcr1);
+		hw_state->cfgcr2 = I915_READ(regs[pll->id].cfgcr2);
+	}
+	ret = true;
+
+out:
+	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+
+	return ret;
+}
+
+static bool skl_ddi_dpll0_get_hw_state(struct drm_i915_private *dev_priv,
+				       struct intel_shared_dpll *pll,
+				       struct intel_dpll_hw_state *hw_state)
+{
+	uint32_t val;
+	const struct skl_dpll_regs *regs = skl_dpll_regs;
+	bool ret;
+
+	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
+		return false;
+
+	ret = false;
+
+	/* DPLL0 is always enabled since it drives CDCLK */
+	val = I915_READ(regs[pll->id].ctl);
+	if (WARN_ON(!(val & LCPLL_PLL_ENABLE)))
+		goto out;
+
+	val = I915_READ(DPLL_CTRL1);
+	hw_state->ctrl1 = (val >> (pll->id * 6)) & 0x3f;
+
+	ret = true;
+
+out:
+	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+
+	return ret;
+}
+
+struct skl_wrpll_context {
+	uint64_t min_deviation;		/* current minimal deviation */
+	uint64_t central_freq;		/* chosen central freq */
+	uint64_t dco_freq;		/* chosen dco freq */
+	unsigned int p;			/* chosen divider */
+};
+
+static void skl_wrpll_context_init(struct skl_wrpll_context *ctx)
+{
+	memset(ctx, 0, sizeof(*ctx));
+
+	ctx->min_deviation = U64_MAX;
+}
+
+/* DCO freq must be within +1%/-6%  of the DCO central freq */
+#define SKL_DCO_MAX_PDEVIATION	100
+#define SKL_DCO_MAX_NDEVIATION	600
+
+static void skl_wrpll_try_divider(struct skl_wrpll_context *ctx,
+				  uint64_t central_freq,
+				  uint64_t dco_freq,
+				  unsigned int divider)
+{
+	uint64_t deviation;
+
+	deviation = div64_u64(10000 * abs_diff(dco_freq, central_freq),
+			      central_freq);
+
+	/* positive deviation */
+	if (dco_freq >= central_freq) {
+		if (deviation < SKL_DCO_MAX_PDEVIATION &&
+		    deviation < ctx->min_deviation) {
+			ctx->min_deviation = deviation;
+			ctx->central_freq = central_freq;
+			ctx->dco_freq = dco_freq;
+			ctx->p = divider;
+		}
+	/* negative deviation */
+	} else if (deviation < SKL_DCO_MAX_NDEVIATION &&
+		   deviation < ctx->min_deviation) {
+		ctx->min_deviation = deviation;
+		ctx->central_freq = central_freq;
+		ctx->dco_freq = dco_freq;
+		ctx->p = divider;
+	}
+}
+
+static void skl_wrpll_get_multipliers(unsigned int p,
+				      unsigned int *p0 /* out */,
+				      unsigned int *p1 /* out */,
+				      unsigned int *p2 /* out */)
+{
+	/* even dividers */
+	if (p % 2 == 0) {
+		unsigned int half = p / 2;
+
+		if (half == 1 || half == 2 || half == 3 || half == 5) {
+			*p0 = 2;
+			*p1 = 1;
+			*p2 = half;
+		} else if (half % 2 == 0) {
+			*p0 = 2;
+			*p1 = half / 2;
+			*p2 = 2;
+		} else if (half % 3 == 0) {
+			*p0 = 3;
+			*p1 = half / 3;
+			*p2 = 2;
+		} else if (half % 7 == 0) {
+			*p0 = 7;
+			*p1 = half / 7;
+			*p2 = 2;
+		}
+	} else if (p == 3 || p == 9) {  /* 3, 5, 7, 9, 15, 21, 35 */
+		*p0 = 3;
+		*p1 = 1;
+		*p2 = p / 3;
+	} else if (p == 5 || p == 7) {
+		*p0 = p;
+		*p1 = 1;
+		*p2 = 1;
+	} else if (p == 15) {
+		*p0 = 3;
+		*p1 = 1;
+		*p2 = 5;
+	} else if (p == 21) {
+		*p0 = 7;
+		*p1 = 1;
+		*p2 = 3;
+	} else if (p == 35) {
+		*p0 = 7;
+		*p1 = 1;
+		*p2 = 5;
+	}
+}
+
+struct skl_wrpll_params {
+	uint32_t        dco_fraction;
+	uint32_t        dco_integer;
+	uint32_t        qdiv_ratio;
+	uint32_t        qdiv_mode;
+	uint32_t        kdiv;
+	uint32_t        pdiv;
+	uint32_t        central_freq;
+};
+
+static void skl_wrpll_params_populate(struct skl_wrpll_params *params,
+				      uint64_t afe_clock,
+				      uint64_t central_freq,
+				      uint32_t p0, uint32_t p1, uint32_t p2)
+{
+	uint64_t dco_freq;
+
+	switch (central_freq) {
+	case 9600000000ULL:
+		params->central_freq = 0;
+		break;
+	case 9000000000ULL:
+		params->central_freq = 1;
+		break;
+	case 8400000000ULL:
+		params->central_freq = 3;
+	}
+
+	switch (p0) {
+	case 1:
+		params->pdiv = 0;
+		break;
+	case 2:
+		params->pdiv = 1;
+		break;
+	case 3:
+		params->pdiv = 2;
+		break;
+	case 7:
+		params->pdiv = 4;
+		break;
+	default:
+		WARN(1, "Incorrect PDiv\n");
+	}
+
+	switch (p2) {
+	case 5:
+		params->kdiv = 0;
+		break;
+	case 2:
+		params->kdiv = 1;
+		break;
+	case 3:
+		params->kdiv = 2;
+		break;
+	case 1:
+		params->kdiv = 3;
+		break;
+	default:
+		WARN(1, "Incorrect KDiv\n");
+	}
+
+	params->qdiv_ratio = p1;
+	params->qdiv_mode = (params->qdiv_ratio == 1) ? 0 : 1;
+
+	dco_freq = p0 * p1 * p2 * afe_clock;
+
+	/*
+	 * Intermediate values are in Hz.
+	 * Divide by MHz to match bsepc
+	 */
+	params->dco_integer = div_u64(dco_freq, 24 * MHz(1));
+	params->dco_fraction =
+		div_u64((div_u64(dco_freq, 24) -
+			 params->dco_integer * MHz(1)) * 0x8000, MHz(1));
+}
+
+static bool
+skl_ddi_calculate_wrpll(int clock /* in Hz */,
+			struct skl_wrpll_params *wrpll_params)
+{
+	uint64_t afe_clock = clock * 5; /* AFE Clock is 5x Pixel clock */
+	uint64_t dco_central_freq[3] = {8400000000ULL,
+					9000000000ULL,
+					9600000000ULL};
+	static const int even_dividers[] = {  4,  6,  8, 10, 12, 14, 16, 18, 20,
+					     24, 28, 30, 32, 36, 40, 42, 44,
+					     48, 52, 54, 56, 60, 64, 66, 68,
+					     70, 72, 76, 78, 80, 84, 88, 90,
+					     92, 96, 98 };
+	static const int odd_dividers[] = { 3, 5, 7, 9, 15, 21, 35 };
+	static const struct {
+		const int *list;
+		int n_dividers;
+	} dividers[] = {
+		{ even_dividers, ARRAY_SIZE(even_dividers) },
+		{ odd_dividers, ARRAY_SIZE(odd_dividers) },
+	};
+	struct skl_wrpll_context ctx;
+	unsigned int dco, d, i;
+	unsigned int p0, p1, p2;
+
+	skl_wrpll_context_init(&ctx);
+
+	for (d = 0; d < ARRAY_SIZE(dividers); d++) {
+		for (dco = 0; dco < ARRAY_SIZE(dco_central_freq); dco++) {
+			for (i = 0; i < dividers[d].n_dividers; i++) {
+				unsigned int p = dividers[d].list[i];
+				uint64_t dco_freq = p * afe_clock;
+
+				skl_wrpll_try_divider(&ctx,
+						      dco_central_freq[dco],
+						      dco_freq,
+						      p);
+				/*
+				 * Skip the remaining dividers if we're sure to
+				 * have found the definitive divider, we can't
+				 * improve a 0 deviation.
+				 */
+				if (ctx.min_deviation == 0)
+					goto skip_remaining_dividers;
+			}
+		}
+
+skip_remaining_dividers:
+		/*
+		 * If a solution is found with an even divider, prefer
+		 * this one.
+		 */
+		if (d == 0 && ctx.p)
+			break;
+	}
+
+	if (!ctx.p) {
+		DRM_DEBUG_DRIVER("No valid divider found for %dHz\n", clock);
+		return false;
+	}
+
+	/*
+	 * gcc incorrectly analyses that these can be used without being
+	 * initialized. To be fair, it's hard to guess.
+	 */
+	p0 = p1 = p2 = 0;
+	skl_wrpll_get_multipliers(ctx.p, &p0, &p1, &p2);
+	skl_wrpll_params_populate(wrpll_params, afe_clock, ctx.central_freq,
+				  p0, p1, p2);
+
+	return true;
+}
+
+static struct intel_shared_dpll *
+skl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
+	     struct intel_encoder *encoder)
+{
+	struct intel_shared_dpll *pll;
+	uint32_t ctrl1, cfgcr1, cfgcr2;
+	int clock = crtc_state->port_clock;
+
+	/*
+	 * See comment in intel_dpll_hw_state to understand why we always use 0
+	 * as the DPLL id in this function.
+	 */
+
+	ctrl1 = DPLL_CTRL1_OVERRIDE(0);
+
+	if (encoder->type == INTEL_OUTPUT_HDMI) {
+		struct skl_wrpll_params wrpll_params = { 0, };
+
+		ctrl1 |= DPLL_CTRL1_HDMI_MODE(0);
+
+		if (!skl_ddi_calculate_wrpll(clock * 1000, &wrpll_params))
+			return NULL;
+
+		cfgcr1 = DPLL_CFGCR1_FREQ_ENABLE |
+			 DPLL_CFGCR1_DCO_FRACTION(wrpll_params.dco_fraction) |
+			 wrpll_params.dco_integer;
+
+		cfgcr2 = DPLL_CFGCR2_QDIV_RATIO(wrpll_params.qdiv_ratio) |
+			 DPLL_CFGCR2_QDIV_MODE(wrpll_params.qdiv_mode) |
+			 DPLL_CFGCR2_KDIV(wrpll_params.kdiv) |
+			 DPLL_CFGCR2_PDIV(wrpll_params.pdiv) |
+			 wrpll_params.central_freq;
+	} else if (encoder->type == INTEL_OUTPUT_DISPLAYPORT ||
+		   encoder->type == INTEL_OUTPUT_DP_MST ||
+		   encoder->type == INTEL_OUTPUT_EDP) {
+		switch (crtc_state->port_clock / 2) {
+		case 81000:
+			ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, 0);
+			break;
+		case 135000:
+			ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, 0);
+			break;
+		case 270000:
+			ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, 0);
+			break;
+		/* eDP 1.4 rates */
+		case 162000:
+			ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, 0);
+			break;
+		/* TBD: For DP link rates 2.16 GHz and 4.32 GHz, VCO is 8640 which
+		results in CDCLK change. Need to handle the change of CDCLK by
+		disabling pipes and re-enabling them */
+		case 108000:
+			ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, 0);
+			break;
+		case 216000:
+			ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160, 0);
+			break;
+		}
+
+		cfgcr1 = cfgcr2 = 0;
+	} else {
+		return NULL;
+	}
+
+	memset(&crtc_state->dpll_hw_state, 0,
+	       sizeof(crtc_state->dpll_hw_state));
+
+	crtc_state->dpll_hw_state.ctrl1 = ctrl1;
+	crtc_state->dpll_hw_state.cfgcr1 = cfgcr1;
+	crtc_state->dpll_hw_state.cfgcr2 = cfgcr2;
+
+	if (encoder->type == INTEL_OUTPUT_EDP)
+		pll = intel_find_shared_dpll(crtc, crtc_state,
+					     DPLL_ID_SKL_DPLL0,
+					     DPLL_ID_SKL_DPLL0);
+	else
+		pll = intel_find_shared_dpll(crtc, crtc_state,
+					     DPLL_ID_SKL_DPLL1,
+					     DPLL_ID_SKL_DPLL3);
+	if (!pll)
+		return NULL;
+
+	crtc_state->ddi_pll_sel = pll->id;
+
+	intel_reference_shared_dpll(pll, crtc_state);
+
+	return pll;
+}
+
+static const struct intel_shared_dpll_funcs skl_ddi_pll_funcs = {
+	.enable = skl_ddi_pll_enable,
+	.disable = skl_ddi_pll_disable,
+	.get_hw_state = skl_ddi_pll_get_hw_state,
+};
+
+static const struct intel_shared_dpll_funcs skl_ddi_dpll0_funcs = {
+	.enable = skl_ddi_dpll0_enable,
+	.disable = skl_ddi_dpll0_disable,
+	.get_hw_state = skl_ddi_dpll0_get_hw_state,
+};
+
+static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv,
+				struct intel_shared_dpll *pll)
+{
+	uint32_t temp;
+	enum port port = (enum port)pll->id;	/* 1:1 port->PLL mapping */
+
+	/* Non-SSC reference */
+	temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
+	temp |= PORT_PLL_REF_SEL;
+	I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
+
+	/* Disable 10 bit clock */
+	temp = I915_READ(BXT_PORT_PLL_EBB_4(port));
+	temp &= ~PORT_PLL_10BIT_CLK_ENABLE;
+	I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp);
+
+	/* Write P1 & P2 */
+	temp = I915_READ(BXT_PORT_PLL_EBB_0(port));
+	temp &= ~(PORT_PLL_P1_MASK | PORT_PLL_P2_MASK);
+	temp |= pll->config.hw_state.ebb0;
+	I915_WRITE(BXT_PORT_PLL_EBB_0(port), temp);
+
+	/* Write M2 integer */
+	temp = I915_READ(BXT_PORT_PLL(port, 0));
+	temp &= ~PORT_PLL_M2_MASK;
+	temp |= pll->config.hw_state.pll0;
+	I915_WRITE(BXT_PORT_PLL(port, 0), temp);
+
+	/* Write N */
+	temp = I915_READ(BXT_PORT_PLL(port, 1));
+	temp &= ~PORT_PLL_N_MASK;
+	temp |= pll->config.hw_state.pll1;
+	I915_WRITE(BXT_PORT_PLL(port, 1), temp);
+
+	/* Write M2 fraction */
+	temp = I915_READ(BXT_PORT_PLL(port, 2));
+	temp &= ~PORT_PLL_M2_FRAC_MASK;
+	temp |= pll->config.hw_state.pll2;
+	I915_WRITE(BXT_PORT_PLL(port, 2), temp);
+
+	/* Write M2 fraction enable */
+	temp = I915_READ(BXT_PORT_PLL(port, 3));
+	temp &= ~PORT_PLL_M2_FRAC_ENABLE;
+	temp |= pll->config.hw_state.pll3;
+	I915_WRITE(BXT_PORT_PLL(port, 3), temp);
+
+	/* Write coeff */
+	temp = I915_READ(BXT_PORT_PLL(port, 6));
+	temp &= ~PORT_PLL_PROP_COEFF_MASK;
+	temp &= ~PORT_PLL_INT_COEFF_MASK;
+	temp &= ~PORT_PLL_GAIN_CTL_MASK;
+	temp |= pll->config.hw_state.pll6;
+	I915_WRITE(BXT_PORT_PLL(port, 6), temp);
+
+	/* Write calibration val */
+	temp = I915_READ(BXT_PORT_PLL(port, 8));
+	temp &= ~PORT_PLL_TARGET_CNT_MASK;
+	temp |= pll->config.hw_state.pll8;
+	I915_WRITE(BXT_PORT_PLL(port, 8), temp);
+
+	temp = I915_READ(BXT_PORT_PLL(port, 9));
+	temp &= ~PORT_PLL_LOCK_THRESHOLD_MASK;
+	temp |= pll->config.hw_state.pll9;
+	I915_WRITE(BXT_PORT_PLL(port, 9), temp);
+
+	temp = I915_READ(BXT_PORT_PLL(port, 10));
+	temp &= ~PORT_PLL_DCO_AMP_OVR_EN_H;
+	temp &= ~PORT_PLL_DCO_AMP_MASK;
+	temp |= pll->config.hw_state.pll10;
+	I915_WRITE(BXT_PORT_PLL(port, 10), temp);
+
+	/* Recalibrate with new settings */
+	temp = I915_READ(BXT_PORT_PLL_EBB_4(port));
+	temp |= PORT_PLL_RECALIBRATE;
+	I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp);
+	temp &= ~PORT_PLL_10BIT_CLK_ENABLE;
+	temp |= pll->config.hw_state.ebb4;
+	I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp);
+
+	/* Enable PLL */
+	temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
+	temp |= PORT_PLL_ENABLE;
+	I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
+	POSTING_READ(BXT_PORT_PLL_ENABLE(port));
+
+	if (wait_for_us((I915_READ(BXT_PORT_PLL_ENABLE(port)) & PORT_PLL_LOCK),
+			200))
+		DRM_ERROR("PLL %d not locked\n", port);
+
+	/*
+	 * While we write to the group register to program all lanes at once we
+	 * can read only lane registers and we pick lanes 0/1 for that.
+	 */
+	temp = I915_READ(BXT_PORT_PCS_DW12_LN01(port));
+	temp &= ~LANE_STAGGER_MASK;
+	temp &= ~LANESTAGGER_STRAP_OVRD;
+	temp |= pll->config.hw_state.pcsdw12;
+	I915_WRITE(BXT_PORT_PCS_DW12_GRP(port), temp);
+}
+
+static void bxt_ddi_pll_disable(struct drm_i915_private *dev_priv,
+					struct intel_shared_dpll *pll)
+{
+	enum port port = (enum port)pll->id;	/* 1:1 port->PLL mapping */
+	uint32_t temp;
+
+	temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
+	temp &= ~PORT_PLL_ENABLE;
+	I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
+	POSTING_READ(BXT_PORT_PLL_ENABLE(port));
+}
+
+static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
+					struct intel_shared_dpll *pll,
+					struct intel_dpll_hw_state *hw_state)
+{
+	enum port port = (enum port)pll->id;	/* 1:1 port->PLL mapping */
+	uint32_t val;
+	bool ret;
+
+	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
+		return false;
+
+	ret = false;
+
+	val = I915_READ(BXT_PORT_PLL_ENABLE(port));
+	if (!(val & PORT_PLL_ENABLE))
+		goto out;
+
+	hw_state->ebb0 = I915_READ(BXT_PORT_PLL_EBB_0(port));
+	hw_state->ebb0 &= PORT_PLL_P1_MASK | PORT_PLL_P2_MASK;
+
+	hw_state->ebb4 = I915_READ(BXT_PORT_PLL_EBB_4(port));
+	hw_state->ebb4 &= PORT_PLL_10BIT_CLK_ENABLE;
+
+	hw_state->pll0 = I915_READ(BXT_PORT_PLL(port, 0));
+	hw_state->pll0 &= PORT_PLL_M2_MASK;
+
+	hw_state->pll1 = I915_READ(BXT_PORT_PLL(port, 1));
+	hw_state->pll1 &= PORT_PLL_N_MASK;
+
+	hw_state->pll2 = I915_READ(BXT_PORT_PLL(port, 2));
+	hw_state->pll2 &= PORT_PLL_M2_FRAC_MASK;
+
+	hw_state->pll3 = I915_READ(BXT_PORT_PLL(port, 3));
+	hw_state->pll3 &= PORT_PLL_M2_FRAC_ENABLE;
+
+	hw_state->pll6 = I915_READ(BXT_PORT_PLL(port, 6));
+	hw_state->pll6 &= PORT_PLL_PROP_COEFF_MASK |
+			  PORT_PLL_INT_COEFF_MASK |
+			  PORT_PLL_GAIN_CTL_MASK;
+
+	hw_state->pll8 = I915_READ(BXT_PORT_PLL(port, 8));
+	hw_state->pll8 &= PORT_PLL_TARGET_CNT_MASK;
+
+	hw_state->pll9 = I915_READ(BXT_PORT_PLL(port, 9));
+	hw_state->pll9 &= PORT_PLL_LOCK_THRESHOLD_MASK;
+
+	hw_state->pll10 = I915_READ(BXT_PORT_PLL(port, 10));
+	hw_state->pll10 &= PORT_PLL_DCO_AMP_OVR_EN_H |
+			   PORT_PLL_DCO_AMP_MASK;
+
+	/*
+	 * While we write to the group register to program all lanes at once we
+	 * can read only lane registers. We configure all lanes the same way, so
+	 * here just read out lanes 0/1 and output a note if lanes 2/3 differ.
+	 */
+	hw_state->pcsdw12 = I915_READ(BXT_PORT_PCS_DW12_LN01(port));
+	if (I915_READ(BXT_PORT_PCS_DW12_LN23(port)) != hw_state->pcsdw12)
+		DRM_DEBUG_DRIVER("lane stagger config different for lane 01 (%08x) and 23 (%08x)\n",
+				 hw_state->pcsdw12,
+				 I915_READ(BXT_PORT_PCS_DW12_LN23(port)));
+	hw_state->pcsdw12 &= LANE_STAGGER_MASK | LANESTAGGER_STRAP_OVRD;
+
+	ret = true;
+
+out:
+	intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
+
+	return ret;
+}
+
+/* bxt clock parameters */
+struct bxt_clk_div {
+	int clock;
+	uint32_t p1;
+	uint32_t p2;
+	uint32_t m2_int;
+	uint32_t m2_frac;
+	bool m2_frac_en;
+	uint32_t n;
+};
+
+/* pre-calculated values for DP linkrates */
+static const struct bxt_clk_div bxt_dp_clk_val[] = {
+	{162000, 4, 2, 32, 1677722, 1, 1},
+	{270000, 4, 1, 27,       0, 0, 1},
+	{540000, 2, 1, 27,       0, 0, 1},
+	{216000, 3, 2, 32, 1677722, 1, 1},
+	{243000, 4, 1, 24, 1258291, 1, 1},
+	{324000, 4, 1, 32, 1677722, 1, 1},
+	{432000, 3, 1, 32, 1677722, 1, 1}
+};
+
+static struct intel_shared_dpll *
+bxt_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
+	     struct intel_encoder *encoder)
+{
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+	struct intel_shared_dpll *pll;
+	enum intel_dpll_id i;
+	struct intel_digital_port *intel_dig_port;
+	struct bxt_clk_div clk_div = {0};
+	int vco = 0;
+	uint32_t prop_coef, int_coef, gain_ctl, targ_cnt;
+	uint32_t lanestagger;
+	int clock = crtc_state->port_clock;
+
+	if (encoder->type == INTEL_OUTPUT_HDMI) {
+		intel_clock_t best_clock;
+
+		/* Calculate HDMI div */
+		/*
+		 * FIXME: tie the following calculation into
+		 * i9xx_crtc_compute_clock
+		 */
+		if (!bxt_find_best_dpll(crtc_state, clock, &best_clock)) {
+			DRM_DEBUG_DRIVER("no PLL dividers found for clock %d pipe %c\n",
+					 clock, pipe_name(crtc->pipe));
+			return NULL;
+		}
+
+		clk_div.p1 = best_clock.p1;
+		clk_div.p2 = best_clock.p2;
+		WARN_ON(best_clock.m1 != 2);
+		clk_div.n = best_clock.n;
+		clk_div.m2_int = best_clock.m2 >> 22;
+		clk_div.m2_frac = best_clock.m2 & ((1 << 22) - 1);
+		clk_div.m2_frac_en = clk_div.m2_frac != 0;
+
+		vco = best_clock.vco;
+	} else if (encoder->type == INTEL_OUTPUT_DISPLAYPORT ||
+		   encoder->type == INTEL_OUTPUT_EDP) {
+		int i;
+
+		clk_div = bxt_dp_clk_val[0];
+		for (i = 0; i < ARRAY_SIZE(bxt_dp_clk_val); ++i) {
+			if (bxt_dp_clk_val[i].clock == clock) {
+				clk_div = bxt_dp_clk_val[i];
+				break;
+			}
+		}
+		vco = clock * 10 / 2 * clk_div.p1 * clk_div.p2;
+	}
+
+	if (vco >= 6200000 && vco <= 6700000) {
+		prop_coef = 4;
+		int_coef = 9;
+		gain_ctl = 3;
+		targ_cnt = 8;
+	} else if ((vco > 5400000 && vco < 6200000) ||
+			(vco >= 4800000 && vco < 5400000)) {
+		prop_coef = 5;
+		int_coef = 11;
+		gain_ctl = 3;
+		targ_cnt = 9;
+	} else if (vco == 5400000) {
+		prop_coef = 3;
+		int_coef = 8;
+		gain_ctl = 1;
+		targ_cnt = 9;
+	} else {
+		DRM_ERROR("Invalid VCO\n");
+		return NULL;
+	}
+
+	memset(&crtc_state->dpll_hw_state, 0,
+	       sizeof(crtc_state->dpll_hw_state));
+
+	if (clock > 270000)
+		lanestagger = 0x18;
+	else if (clock > 135000)
+		lanestagger = 0x0d;
+	else if (clock > 67000)
+		lanestagger = 0x07;
+	else if (clock > 33000)
+		lanestagger = 0x04;
+	else
+		lanestagger = 0x02;
+
+	crtc_state->dpll_hw_state.ebb0 =
+		PORT_PLL_P1(clk_div.p1) | PORT_PLL_P2(clk_div.p2);
+	crtc_state->dpll_hw_state.pll0 = clk_div.m2_int;
+	crtc_state->dpll_hw_state.pll1 = PORT_PLL_N(clk_div.n);
+	crtc_state->dpll_hw_state.pll2 = clk_div.m2_frac;
+
+	if (clk_div.m2_frac_en)
+		crtc_state->dpll_hw_state.pll3 =
+			PORT_PLL_M2_FRAC_ENABLE;
+
+	crtc_state->dpll_hw_state.pll6 =
+		prop_coef | PORT_PLL_INT_COEFF(int_coef);
+	crtc_state->dpll_hw_state.pll6 |=
+		PORT_PLL_GAIN_CTL(gain_ctl);
+
+	crtc_state->dpll_hw_state.pll8 = targ_cnt;
+
+	crtc_state->dpll_hw_state.pll9 = 5 << PORT_PLL_LOCK_THRESHOLD_SHIFT;
+
+	crtc_state->dpll_hw_state.pll10 =
+		PORT_PLL_DCO_AMP(PORT_PLL_DCO_AMP_DEFAULT)
+		| PORT_PLL_DCO_AMP_OVR_EN_H;
+
+	crtc_state->dpll_hw_state.ebb4 = PORT_PLL_10BIT_CLK_ENABLE;
+
+	crtc_state->dpll_hw_state.pcsdw12 =
+		LANESTAGGER_STRAP_OVRD | lanestagger;
+
+	intel_dig_port = enc_to_dig_port(&encoder->base);
+
+	/* 1:1 mapping between ports and PLLs */
+	i = (enum intel_dpll_id) intel_dig_port->port;
+	pll = intel_get_shared_dpll_by_id(dev_priv, i);
+
+	DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n",
+		crtc->base.base.id, pll->name);
+
+	intel_reference_shared_dpll(pll, crtc_state);
+
+	/* shared DPLL id 0 is DPLL A */
+	crtc_state->ddi_pll_sel = pll->id;
+
+	return pll;
+}
+
+static const struct intel_shared_dpll_funcs bxt_ddi_pll_funcs = {
+	.enable = bxt_ddi_pll_enable,
+	.disable = bxt_ddi_pll_disable,
+	.get_hw_state = bxt_ddi_pll_get_hw_state,
+};
+
+static void intel_ddi_pll_init(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	uint32_t val = I915_READ(LCPLL_CTL);
+
+	if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
+		int cdclk_freq;
+
+		cdclk_freq = dev_priv->display.get_display_clock_speed(dev);
+		dev_priv->skl_boot_cdclk = cdclk_freq;
+		if (skl_sanitize_cdclk(dev_priv))
+			DRM_DEBUG_KMS("Sanitized cdclk programmed by pre-os\n");
+		if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE))
+			DRM_ERROR("LCPLL1 is disabled\n");
+	} else if (!IS_BROXTON(dev_priv)) {
+		/*
+		 * The LCPLL register should be turned on by the BIOS. For now
+		 * let's just check its state and print errors in case
+		 * something is wrong.  Don't even try to turn it on.
+		 */
+
+		if (val & LCPLL_CD_SOURCE_FCLK)
+			DRM_ERROR("CDCLK source is not LCPLL\n");
+
+		if (val & LCPLL_PLL_DISABLE)
+			DRM_ERROR("LCPLL is disabled\n");
+	}
+}
+
+struct dpll_info {
+	const char *name;
+	const int id;
+	const struct intel_shared_dpll_funcs *funcs;
+	uint32_t flags;
+};
+
+struct intel_dpll_mgr {
+	const struct dpll_info *dpll_info;
+
+	struct intel_shared_dpll *(*get_dpll)(struct intel_crtc *crtc,
+					      struct intel_crtc_state *crtc_state,
+					      struct intel_encoder *encoder);
+};
+
+static const struct dpll_info pch_plls[] = {
+	{ "PCH DPLL A", DPLL_ID_PCH_PLL_A, &ibx_pch_dpll_funcs, 0 },
+	{ "PCH DPLL B", DPLL_ID_PCH_PLL_B, &ibx_pch_dpll_funcs, 0 },
+	{ NULL, -1, NULL, 0 },
+};
+
+static const struct intel_dpll_mgr pch_pll_mgr = {
+	.dpll_info = pch_plls,
+	.get_dpll = ibx_get_dpll,
+};
+
+static const struct dpll_info hsw_plls[] = {
+	{ "WRPLL 1",    DPLL_ID_WRPLL1,     &hsw_ddi_wrpll_funcs, 0 },
+	{ "WRPLL 2",    DPLL_ID_WRPLL2,     &hsw_ddi_wrpll_funcs, 0 },
+	{ "SPLL",       DPLL_ID_SPLL,       &hsw_ddi_spll_funcs,  0 },
+	{ "LCPLL 810",  DPLL_ID_LCPLL_810,  &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON },
+	{ "LCPLL 1350", DPLL_ID_LCPLL_1350, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON },
+	{ "LCPLL 2700", DPLL_ID_LCPLL_2700, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON },
+	{ NULL, -1, NULL, },
+};
+
+static const struct intel_dpll_mgr hsw_pll_mgr = {
+	.dpll_info = hsw_plls,
+	.get_dpll = hsw_get_dpll,
+};
+
+static const struct dpll_info skl_plls[] = {
+	{ "DPLL 0", DPLL_ID_SKL_DPLL0, &skl_ddi_dpll0_funcs, INTEL_DPLL_ALWAYS_ON },
+	{ "DPLL 1", DPLL_ID_SKL_DPLL1, &skl_ddi_pll_funcs,   0 },
+	{ "DPLL 2", DPLL_ID_SKL_DPLL2, &skl_ddi_pll_funcs,   0 },
+	{ "DPLL 3", DPLL_ID_SKL_DPLL3, &skl_ddi_pll_funcs,   0 },
+	{ NULL, -1, NULL, },
+};
+
+static const struct intel_dpll_mgr skl_pll_mgr = {
+	.dpll_info = skl_plls,
+	.get_dpll = skl_get_dpll,
+};
+
+static const struct dpll_info bxt_plls[] = {
+	{ "PORT PLL A", DPLL_ID_SKL_DPLL0, &bxt_ddi_pll_funcs, 0 },
+	{ "PORT PLL B", DPLL_ID_SKL_DPLL1, &bxt_ddi_pll_funcs, 0 },
+	{ "PORT PLL C", DPLL_ID_SKL_DPLL2, &bxt_ddi_pll_funcs, 0 },
+	{ NULL, -1, NULL, },
+};
+
+static const struct intel_dpll_mgr bxt_pll_mgr = {
+	.dpll_info = bxt_plls,
+	.get_dpll = bxt_get_dpll,
+};
+
+void intel_shared_dpll_init(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	const struct intel_dpll_mgr *dpll_mgr = NULL;
+	const struct dpll_info *dpll_info;
+	int i;
+
+	if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
+		dpll_mgr = &skl_pll_mgr;
+	else if (IS_BROXTON(dev))
+		dpll_mgr = &bxt_pll_mgr;
+	else if (HAS_DDI(dev))
+		dpll_mgr = &hsw_pll_mgr;
+	else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
+		dpll_mgr = &pch_pll_mgr;
+
+	if (!dpll_mgr) {
+		dev_priv->num_shared_dpll = 0;
+		return;
+	}
+
+	dpll_info = dpll_mgr->dpll_info;
+
+	for (i = 0; dpll_info[i].id >= 0; i++) {
+		WARN_ON(i != dpll_info[i].id);
+
+		dev_priv->shared_dplls[i].id = dpll_info[i].id;
+		dev_priv->shared_dplls[i].name = dpll_info[i].name;
+		dev_priv->shared_dplls[i].funcs = *dpll_info[i].funcs;
+		dev_priv->shared_dplls[i].flags = dpll_info[i].flags;
+	}
+
+	dev_priv->dpll_mgr = dpll_mgr;
+	dev_priv->num_shared_dpll = i;
+	mutex_init(&dev_priv->dpll_lock);
+
+	BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS);
+
+	/* FIXME: Move this to a more suitable place */
+	if (HAS_DDI(dev))
+		intel_ddi_pll_init(dev);
+}
+
+struct intel_shared_dpll *
+intel_get_shared_dpll(struct intel_crtc *crtc,
+		      struct intel_crtc_state *crtc_state,
+		      struct intel_encoder *encoder)
+{
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+	const struct intel_dpll_mgr *dpll_mgr = dev_priv->dpll_mgr;
+
+	if (WARN_ON(!dpll_mgr))
+		return NULL;
+
+	return dpll_mgr->get_dpll(crtc, crtc_state, encoder);
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_dpll_mgr.h linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_dpll_mgr.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_dpll_mgr.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_dpll_mgr.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,164 @@
+/*
+ * Copyright © 2012-2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#ifndef _INTEL_DPLL_MGR_H_
+#define _INTEL_DPLL_MGR_H_
+
+/*FIXME: Move this to a more appropriate place. */
+#define abs_diff(a, b) ({			\
+	typeof(a) __a = (a);			\
+	typeof(b) __b = (b);			\
+	(void) (&__a == &__b);			\
+	__a > __b ? (__a - __b) : (__b - __a); })
+
+struct drm_i915_private;
+struct intel_crtc;
+struct intel_crtc_state;
+struct intel_encoder;
+
+struct intel_shared_dpll;
+struct intel_dpll_mgr;
+
+enum intel_dpll_id {
+	DPLL_ID_PRIVATE = -1, /* non-shared dpll in use */
+	/* real shared dpll ids must be >= 0 */
+	DPLL_ID_PCH_PLL_A = 0,
+	DPLL_ID_PCH_PLL_B = 1,
+	/* hsw/bdw */
+	DPLL_ID_WRPLL1 = 0,
+	DPLL_ID_WRPLL2 = 1,
+	DPLL_ID_SPLL = 2,
+	DPLL_ID_LCPLL_810 = 3,
+	DPLL_ID_LCPLL_1350 = 4,
+	DPLL_ID_LCPLL_2700 = 5,
+
+	/* skl */
+	DPLL_ID_SKL_DPLL0 = 0,
+	DPLL_ID_SKL_DPLL1 = 1,
+	DPLL_ID_SKL_DPLL2 = 2,
+	DPLL_ID_SKL_DPLL3 = 3,
+};
+#define I915_NUM_PLLS 6
+
+/** Inform the state checker that the DPLL is kept enabled even if not
+ * in use by any crtc.
+ */
+#define INTEL_DPLL_ALWAYS_ON	(1 << 0)
+
+struct intel_dpll_hw_state {
+	/* i9xx, pch plls */
+	uint32_t dpll;
+	uint32_t dpll_md;
+	uint32_t fp0;
+	uint32_t fp1;
+
+	/* hsw, bdw */
+	uint32_t wrpll;
+	uint32_t spll;
+
+	/* skl */
+	/*
+	 * DPLL_CTRL1 has 6 bits for each each this DPLL. We store those in
+	 * lower part of ctrl1 and they get shifted into position when writing
+	 * the register.  This allows us to easily compare the state to share
+	 * the DPLL.
+	 */
+	uint32_t ctrl1;
+	/* HDMI only, 0 when used for DP */
+	uint32_t cfgcr1, cfgcr2;
+
+	/* bxt */
+	uint32_t ebb0, ebb4, pll0, pll1, pll2, pll3, pll6, pll8, pll9, pll10,
+		 pcsdw12;
+};
+
+struct intel_shared_dpll_config {
+	unsigned crtc_mask; /* mask of CRTCs sharing this PLL */
+	struct intel_dpll_hw_state hw_state;
+};
+
+struct intel_shared_dpll_funcs {
+	/* The mode_set hook is optional and should be used together with the
+	 * intel_prepare_shared_dpll function. */
+	void (*mode_set)(struct drm_i915_private *dev_priv,
+			 struct intel_shared_dpll *pll);
+	void (*enable)(struct drm_i915_private *dev_priv,
+		       struct intel_shared_dpll *pll);
+	void (*disable)(struct drm_i915_private *dev_priv,
+			struct intel_shared_dpll *pll);
+	bool (*get_hw_state)(struct drm_i915_private *dev_priv,
+			     struct intel_shared_dpll *pll,
+			     struct intel_dpll_hw_state *hw_state);
+};
+
+struct intel_shared_dpll {
+	struct intel_shared_dpll_config config;
+
+	unsigned active_mask; /* mask of active CRTCs (i.e. DPMS on) */
+	bool on; /* is the PLL actually active? Disabled during modeset */
+	const char *name;
+	/* should match the index in the dev_priv->shared_dplls array */
+	enum intel_dpll_id id;
+
+	struct intel_shared_dpll_funcs funcs;
+
+	uint32_t flags;
+};
+
+#define SKL_DPLL0 0
+#define SKL_DPLL1 1
+#define SKL_DPLL2 2
+#define SKL_DPLL3 3
+
+/* shared dpll functions */
+struct intel_shared_dpll *
+intel_get_shared_dpll_by_id(struct drm_i915_private *dev_priv,
+			    enum intel_dpll_id id);
+enum intel_dpll_id
+intel_get_shared_dpll_id(struct drm_i915_private *dev_priv,
+			 struct intel_shared_dpll *pll);
+void
+intel_shared_dpll_config_get(struct intel_shared_dpll_config *config,
+			     struct intel_shared_dpll *pll,
+			     struct intel_crtc *crtc);
+void
+intel_shared_dpll_config_put(struct intel_shared_dpll_config *config,
+			     struct intel_shared_dpll *pll,
+			     struct intel_crtc *crtc);
+void assert_shared_dpll(struct drm_i915_private *dev_priv,
+			struct intel_shared_dpll *pll,
+			bool state);
+#define assert_shared_dpll_enabled(d, p) assert_shared_dpll(d, p, true)
+#define assert_shared_dpll_disabled(d, p) assert_shared_dpll(d, p, false)
+struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc,
+						struct intel_crtc_state *state,
+						struct intel_encoder *encoder);
+void intel_prepare_shared_dpll(struct intel_crtc *crtc);
+void intel_enable_shared_dpll(struct intel_crtc *crtc);
+void intel_disable_shared_dpll(struct intel_crtc *crtc);
+void intel_shared_dpll_commit(struct drm_atomic_state *state);
+void intel_shared_dpll_init(struct drm_device *dev);
+
+
+#endif /* _INTEL_DPLL_MGR_H_ */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_dp_mst.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_dp_mst.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_dp_mst.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_dp_mst.c	2016-07-24 15:23:50.000000000 -0400
@@ -33,7 +33,6 @@
 static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
 					struct intel_crtc_state *pipe_config)
 {
-	struct drm_device *dev = encoder->base.dev;
 	struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
 	struct intel_digital_port *intel_dig_port = intel_mst->primary;
 	struct intel_dp *intel_dp = &intel_dig_port->dp;
@@ -90,9 +89,6 @@ static bool intel_dp_mst_compute_config(
 
 	pipe_config->dp_m_n.tu = slots;
 
-	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
-		hsw_dp_set_ddi_pll_sel(pipe_config);
-
 	return true;
 
 }
@@ -106,7 +102,7 @@ static void intel_mst_disable_dp(struct
 
 	DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links);
 
-	drm_dp_mst_reset_vcpi_slots(&intel_dp->mst_mgr, intel_mst->port);
+	drm_dp_mst_reset_vcpi_slots(&intel_dp->mst_mgr, intel_mst->connector->port);
 
 	ret = drm_dp_update_payload_part1(&intel_dp->mst_mgr);
 	if (ret) {
@@ -127,10 +123,11 @@ static void intel_mst_post_disable_dp(st
 	/* and this can also fail */
 	drm_dp_update_payload_part2(&intel_dp->mst_mgr);
 
-	drm_dp_mst_deallocate_vcpi(&intel_dp->mst_mgr, intel_mst->port);
+	drm_dp_mst_deallocate_vcpi(&intel_dp->mst_mgr, intel_mst->connector->port);
 
 	intel_dp->active_mst_links--;
-	intel_mst->port = NULL;
+
+	intel_mst->connector = NULL;
 	if (intel_dp->active_mst_links == 0) {
 		intel_dig_port->base.post_disable(&intel_dig_port->base);
 		intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
@@ -170,7 +167,8 @@ static void intel_mst_pre_enable_dp(stru
 	found->encoder = encoder;
 
 	DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links);
-	intel_mst->port = found->port;
+
+	intel_mst->connector = found;
 
 	if (intel_dp->active_mst_links == 0) {
 		intel_prepare_ddi_buffer(&intel_dig_port->base);
@@ -188,7 +186,7 @@ static void intel_mst_pre_enable_dp(stru
 	}
 
 	ret = drm_dp_mst_allocate_vcpi(&intel_dp->mst_mgr,
-				       intel_mst->port,
+				       intel_mst->connector->port,
 				       intel_crtc->config->pbn, &slots);
 	if (ret == false) {
 		DRM_ERROR("failed to allocate vcpi\n");
@@ -229,7 +227,7 @@ static bool intel_dp_mst_enc_get_hw_stat
 {
 	struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
 	*pipe = intel_mst->pipe;
-	if (intel_mst->port)
+	if (intel_mst->connector)
 		return true;
 	return false;
 }
@@ -290,10 +288,11 @@ static int intel_dp_mst_get_ddc_modes(st
 	struct edid *edid;
 	int ret;
 
-	edid = drm_dp_mst_get_edid(connector, &intel_dp->mst_mgr, intel_connector->port);
-	if (!edid)
-		return 0;
+	if (!intel_dp) {
+		return intel_connector_update_modes(connector, NULL);
+	}
 
+	edid = drm_dp_mst_get_edid(connector, &intel_dp->mst_mgr, intel_connector->port);
 	ret = intel_connector_update_modes(connector, edid);
 	kfree(edid);
 
@@ -306,6 +305,8 @@ intel_dp_mst_detect(struct drm_connector
 	struct intel_connector *intel_connector = to_intel_connector(connector);
 	struct intel_dp *intel_dp = intel_connector->mst_port;
 
+	if (!intel_dp)
+		return connector_status_disconnected;
 	return drm_dp_mst_detect_port(connector, &intel_dp->mst_mgr, intel_connector->port);
 }
 
@@ -371,6 +372,8 @@ static struct drm_encoder *intel_mst_ato
 	struct intel_dp *intel_dp = intel_connector->mst_port;
 	struct intel_crtc *crtc = to_intel_crtc(state->crtc);
 
+	if (!intel_dp)
+		return NULL;
 	return &intel_dp->mst_encoders[crtc->pipe]->base.base;
 }
 
@@ -378,6 +381,8 @@ static struct drm_encoder *intel_mst_bes
 {
 	struct intel_connector *intel_connector = to_intel_connector(connector);
 	struct intel_dp *intel_dp = intel_connector->mst_port;
+	if (!intel_dp)
+		return NULL;
 	return &intel_dp->mst_encoders[0]->base.base;
 }
 
@@ -488,23 +493,11 @@ static void intel_dp_destroy_mst_connect
 
 	/* need to nuke the connector */
 	drm_modeset_lock_all(dev);
-	if (connector->state->crtc) {
-		struct drm_mode_set set;
-		int ret;
-
-		memset(&set, 0, sizeof(set));
-		set.crtc = connector->state->crtc,
-
-		ret = drm_atomic_helper_set_config(&set);
-
-		WARN(ret, "Disabling mst crtc failed with %i\n", ret);
-	}
-
 	intel_connector_remove_from_fbdev(intel_connector);
-	drm_connector_cleanup(connector);
+	intel_connector->mst_port = NULL;
 	drm_modeset_unlock_all(dev);
 
-	kfree(intel_connector);
+	drm_connector_unreference(&intel_connector->base);
 	DRM_DEBUG_KMS("\n");
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_drv.h linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_drv.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_drv.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_drv.h	2016-07-24 15:23:50.000000000 -0400
@@ -33,6 +33,7 @@
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_fb_helper.h>
+#include <drm/drm_dp_dual_mode_helper.h>
 #include <drm/drm_dp_mst_helper.h>
 #include <drm/drm_rect.h>
 #include <drm/drm_atomic.h>
@@ -44,9 +45,13 @@
  * contexts. Note that it's important that we check the condition again after
  * having timed out, since the timeout could be due to preemption or similar and
  * we've never had a chance to check the condition before the timeout.
+ *
+ * TODO: When modesetting has fully transitioned to atomic, the below
+ * drm_can_sleep() can be removed and in_atomic()/!in_atomic() asserts
+ * added.
  */
-#define _wait_for(COND, MS, W) ({ \
-	unsigned long timeout__ = jiffies + msecs_to_jiffies(MS) + 1;	\
+#define _wait_for(COND, US, W) ({ \
+	unsigned long timeout__ = jiffies + usecs_to_jiffies(US) + 1;	\
 	int ret__ = 0;							\
 	while (!(COND)) {						\
 		if (time_after(jiffies, timeout__)) {			\
@@ -55,7 +60,7 @@
 			break;						\
 		}							\
 		if ((W) && drm_can_sleep()) {				\
-			usleep_range((W)*1000, (W)*2000);		\
+			usleep_range((W), (W)*2);			\
 		} else {						\
 			cpu_relax();					\
 		}							\
@@ -63,10 +68,40 @@
 	ret__;								\
 })
 
-#define wait_for(COND, MS) _wait_for(COND, MS, 1)
-#define wait_for_atomic(COND, MS) _wait_for(COND, MS, 0)
-#define wait_for_atomic_us(COND, US) _wait_for((COND), \
-					       DIV_ROUND_UP((US), 1000), 0)
+#define wait_for(COND, MS)	  	_wait_for((COND), (MS) * 1000, 1000)
+#define wait_for_us(COND, US)	  	_wait_for((COND), (US), 1)
+
+/* If CONFIG_PREEMPT_COUNT is disabled, in_atomic() always reports false. */
+#if defined(CONFIG_DRM_I915_DEBUG) && defined(CONFIG_PREEMPT_COUNT)
+# define _WAIT_FOR_ATOMIC_CHECK WARN_ON_ONCE(!in_atomic())
+#else
+# define _WAIT_FOR_ATOMIC_CHECK do { } while (0)
+#endif
+
+#define _wait_for_atomic(COND, US) ({ \
+	unsigned long end__; \
+	int ret__ = 0; \
+	_WAIT_FOR_ATOMIC_CHECK; \
+	BUILD_BUG_ON((US) > 50000); \
+	end__ = (local_clock() >> 10) + (US) + 1; \
+	while (!(COND)) { \
+		if (time_after((unsigned long)(local_clock() >> 10), end__)) { \
+			/* Unlike the regular wait_for(), this atomic variant \
+			 * cannot be preempted (and we'll just ignore the issue\
+			 * of irq interruptions) and so we know that no time \
+			 * has passed since the last check of COND and can \
+			 * immediately report the timeout. \
+			 */ \
+			ret__ = -ETIMEDOUT; \
+			break; \
+		} \
+		cpu_relax(); \
+	} \
+	ret__; \
+})
+
+#define wait_for_atomic(COND, MS)	_wait_for_atomic((COND), (MS) * 1000)
+#define wait_for_atomic_us(COND, US)	_wait_for_atomic((COND), (US))
 
 #define KHz(x) (1000 * (x))
 #define MHz(x) KHz(1000 * (x))
@@ -118,6 +153,7 @@ enum intel_output_type {
 struct intel_framebuffer {
 	struct drm_framebuffer base;
 	struct drm_i915_gem_object *obj;
+	struct intel_rotation_info rot_info;
 };
 
 struct intel_fbdev {
@@ -260,6 +296,12 @@ struct intel_atomic_state {
 
 	struct intel_shared_dpll_config shared_dpll[I915_NUM_PLLS];
 	struct intel_wm_config wm_config;
+
+	/*
+	 * Current watermarks can't be trusted during hardware readout, so
+	 * don't bother calculating intermediate watermarks.
+	 */
+	bool skip_intermediate_wm;
 };
 
 struct intel_plane_state {
@@ -349,6 +391,7 @@ struct intel_crtc_scaler_state {
 
 struct intel_pipe_wm {
 	struct intel_wm_level wm[5];
+	struct intel_wm_level raw_wm[5];
 	uint32_t linetime;
 	bool fbc_wm_enabled;
 	bool pipe_enabled;
@@ -376,9 +419,10 @@ struct intel_crtc_state {
 #define PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS	(1<<0) /* unreliable sync mode.flags */
 	unsigned long quirks;
 
+	unsigned fb_bits; /* framebuffers to flip */
 	bool update_pipe; /* can a fast modeset be performed? */
 	bool disable_cxsr;
-	bool wm_changed; /* watermarks are updated */
+	bool update_wm_pre, update_wm_post; /* watermarks are updated */
 	bool fb_changed; /* fb on any of the planes is changed */
 
 	/* Pipe source size (ie. panel fitter input size)
@@ -394,7 +438,8 @@ struct intel_crtc_state {
 	bool has_infoframe;
 
 	/* CPU Transcoder for the pipe. Currently this can only differ from the
-	 * pipe on Haswell (where we have a special eDP transcoder). */
+	 * pipe on Haswell and later (where we have a special eDP transcoder)
+	 * and Broxton (where we have special DSI transcoders). */
 	enum transcoder cpu_transcoder;
 
 	/*
@@ -441,8 +486,8 @@ struct intel_crtc_state {
 	 * haswell. */
 	struct dpll dpll;
 
-	/* Selected dpll when shared or DPLL_ID_PRIVATE. */
-	enum intel_dpll_id shared_dpll;
+	/* Selected dpll when shared or NULL. */
+	struct intel_shared_dpll *shared_dpll;
 
 	/*
 	 * - PORT_CLK_SEL for DDI ports on HSW/BDW.
@@ -453,6 +498,11 @@ struct intel_crtc_state {
 	/* Actual register state of the dpll, for shared dpll cross-checking. */
 	struct intel_dpll_hw_state dpll_hw_state;
 
+	/* DSI PLL registers */
+	struct {
+		u32 ctrl, div;
+	} dsi_pll;
+
 	int pipe_bpp;
 	struct intel_link_m_n dp_m_n;
 
@@ -510,14 +560,33 @@ struct intel_crtc_state {
 
 	struct {
 		/*
-		 * optimal watermarks, programmed post-vblank when this state
-		 * is committed
+		 * Optimal watermarks, programmed post-vblank when this state
+		 * is committed.
 		 */
 		union {
 			struct intel_pipe_wm ilk;
 			struct skl_pipe_wm skl;
 		} optimal;
+
+		/*
+		 * Intermediate watermarks; these can be programmed immediately
+		 * since they satisfy both the current configuration we're
+		 * switching away from and the new configuration we're switching
+		 * to.
+		 */
+		struct intel_pipe_wm intermediate;
+
+		/*
+		 * Platforms with two-step watermark programming will need to
+		 * update watermark programming post-vblank to switch from the
+		 * safe intermediate watermarks to the optimal final
+		 * watermarks.
+		 */
+		bool need_postvbl_update;
 	} wm;
+
+	/* Gamma mode programmed on the pipe */
+	uint32_t gamma_mode;
 };
 
 struct vlv_wm_state {
@@ -537,23 +606,6 @@ struct intel_mmio_flip {
 	unsigned int rotation;
 };
 
-/*
- * Tracking of operations that need to be performed at the beginning/end of an
- * atomic commit, outside the atomic section where interrupts are disabled.
- * These are generally operations that grab mutexes or might otherwise sleep
- * and thus can't be run with interrupts disabled.
- */
-struct intel_crtc_atomic_commit {
-	/* Sleepable operations to perform before commit */
-
-	/* Sleepable operations to perform after commit */
-	unsigned fb_bits;
-	bool post_enable_primary;
-
-	/* Sleepable operations to perform before and after commit */
-	bool update_fbc;
-};
-
 struct intel_crtc {
 	struct drm_crtc base;
 	enum pipe pipe;
@@ -600,6 +652,7 @@ struct intel_crtc {
 			struct intel_pipe_wm ilk;
 			struct skl_pipe_wm skl;
 		} active;
+
 		/* allow CxSR on this pipe */
 		bool cxsr_allowed;
 	} wm;
@@ -613,8 +666,6 @@ struct intel_crtc {
 		int scanline_start;
 	} debug;
 
-	struct intel_crtc_atomic_commit atomic;
-
 	/* scalers available on this crtc */
 	int num_scalers;
 
@@ -703,6 +754,10 @@ struct cxsr_latency {
 struct intel_hdmi {
 	i915_reg_t hdmi_reg;
 	int ddc_bus;
+	struct {
+		enum drm_dp_dual_mode_type type;
+		int max_tmds_clock;
+	} dp_dual_mode;
 	bool limited_color_range;
 	bool color_range_auto;
 	bool has_hdmi_sink;
@@ -751,7 +806,9 @@ struct intel_dp {
 	uint32_t DP;
 	int link_rate;
 	uint8_t lane_count;
+	uint8_t sink_count;
 	bool has_audio;
+	bool detect_done;
 	enum hdmi_force_audio force_audio;
 	bool limited_color_range;
 	bool color_range_auto;
@@ -806,8 +863,6 @@ struct intel_dp {
 	/* This is called before a link training is starterd */
 	void (*prepare_link_retrain)(struct intel_dp *intel_dp);
 
-	bool train_set_valid;
-
 	/* Displayport compliance testing */
 	unsigned long compliance_test_type;
 	unsigned long compliance_test_data;
@@ -831,7 +886,7 @@ struct intel_dp_mst_encoder {
 	struct intel_encoder base;
 	enum pipe pipe;
 	struct intel_digital_port *primary;
-	void *port; /* store this opaque as its illegal to dereference it */
+	struct intel_connector *connector;
 };
 
 static inline enum dpio_channel
@@ -1007,7 +1062,6 @@ void hsw_fdi_link_train(struct drm_crtc
 void intel_ddi_init(struct drm_device *dev, enum port port);
 enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder);
 bool intel_ddi_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe);
-void intel_ddi_pll_init(struct drm_device *dev);
 void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc);
 void intel_ddi_disable_transcoder_func(struct drm_i915_private *dev_priv,
 				       enum transcoder cpu_transcoder);
@@ -1049,17 +1103,19 @@ u32 intel_fb_stride_alignment(const stru
 			      uint64_t fb_modifier, uint32_t pixel_format);
 
 /* intel_audio.c */
-void intel_init_audio(struct drm_device *dev);
+void intel_init_audio_hooks(struct drm_i915_private *dev_priv);
 void intel_audio_codec_enable(struct intel_encoder *encoder);
 void intel_audio_codec_disable(struct intel_encoder *encoder);
 void i915_audio_component_init(struct drm_i915_private *dev_priv);
 void i915_audio_component_cleanup(struct drm_i915_private *dev_priv);
 
 /* intel_display.c */
+int vlv_get_cck_clock(struct drm_i915_private *dev_priv,
+		      const char *name, u32 reg, int ref_freq);
 extern const struct drm_plane_funcs intel_plane_funcs;
+void intel_init_display_hooks(struct drm_i915_private *dev_priv);
+unsigned int intel_rotation_info_size(const struct intel_rotation_info *rot_info);
 bool intel_has_pending_fb_unpin(struct drm_device *dev);
-int intel_pch_rawclk(struct drm_device *dev);
-int intel_hrawclk(struct drm_device *dev);
 void intel_mark_busy(struct drm_device *dev);
 void intel_mark_idle(struct drm_device *dev);
 void intel_crtc_restore_mode(struct drm_crtc *crtc);
@@ -1104,9 +1160,8 @@ bool intel_get_load_detect_pipe(struct d
 void intel_release_load_detect_pipe(struct drm_connector *connector,
 				    struct intel_load_detect_pipe *old,
 				    struct drm_modeset_acquire_ctx *ctx);
-int intel_pin_and_fence_fb_obj(struct drm_plane *plane,
-			       struct drm_framebuffer *fb,
-			       const struct drm_plane_state *plane_state);
+int intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
+			       unsigned int rotation);
 struct drm_framebuffer *
 __intel_framebuffer_create(struct drm_device *dev,
 			   struct drm_mode_fb_cmd2 *mode_cmd,
@@ -1142,19 +1197,13 @@ intel_rotation_90_or_270(unsigned int ro
 void intel_create_rotation_property(struct drm_device *dev,
 					struct intel_plane *plane);
 
-/* shared dpll functions */
-struct intel_shared_dpll *intel_crtc_to_shared_dpll(struct intel_crtc *crtc);
-void assert_shared_dpll(struct drm_i915_private *dev_priv,
-			struct intel_shared_dpll *pll,
-			bool state);
-#define assert_shared_dpll_enabled(d, p) assert_shared_dpll(d, p, true)
-#define assert_shared_dpll_disabled(d, p) assert_shared_dpll(d, p, false)
-struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc *crtc,
-						struct intel_crtc_state *state);
+void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv,
+				    enum pipe pipe);
 
 int vlv_force_pll_on(struct drm_device *dev, enum pipe pipe,
 		     const struct dpll *dpll);
 void vlv_force_pll_off(struct drm_device *dev, enum pipe pipe);
+int lpt_get_iclkip(struct drm_i915_private *dev_priv);
 
 /* modesetting asserts */
 void assert_panel_unlocked(struct drm_i915_private *dev_priv,
@@ -1163,6 +1212,9 @@ void assert_pll(struct drm_i915_private
 		enum pipe pipe, bool state);
 #define assert_pll_enabled(d, p) assert_pll(d, p, true)
 #define assert_pll_disabled(d, p) assert_pll(d, p, false)
+void assert_dsi_pll(struct drm_i915_private *dev_priv, bool state);
+#define assert_dsi_pll_enabled(d) assert_dsi_pll(d, true)
+#define assert_dsi_pll_disabled(d) assert_dsi_pll(d, false)
 void assert_fdi_rx_pll(struct drm_i915_private *dev_priv,
 		       enum pipe pipe, bool state);
 #define assert_fdi_rx_pll_enabled(d, p) assert_fdi_rx_pll(d, p, true)
@@ -1170,21 +1222,24 @@ void assert_fdi_rx_pll(struct drm_i915_p
 void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, bool state);
 #define assert_pipe_enabled(d, p) assert_pipe(d, p, true)
 #define assert_pipe_disabled(d, p) assert_pipe(d, p, false)
-u32 intel_compute_tile_offset(struct drm_i915_private *dev_priv,
-			      int *x, int *y,
-			      uint64_t fb_modifier,
-			      unsigned int cpp,
-			      unsigned int pitch);
+u32 intel_compute_tile_offset(int *x, int *y,
+			      const struct drm_framebuffer *fb, int plane,
+			      unsigned int pitch,
+			      unsigned int rotation);
 void intel_prepare_reset(struct drm_device *dev);
 void intel_finish_reset(struct drm_device *dev);
 void hsw_enable_pc8(struct drm_i915_private *dev_priv);
 void hsw_disable_pc8(struct drm_i915_private *dev_priv);
-void broxton_init_cdclk(struct drm_device *dev);
-void broxton_uninit_cdclk(struct drm_device *dev);
-void broxton_ddi_phy_init(struct drm_device *dev);
-void broxton_ddi_phy_uninit(struct drm_device *dev);
+void broxton_init_cdclk(struct drm_i915_private *dev_priv);
+void broxton_uninit_cdclk(struct drm_i915_private *dev_priv);
+bool broxton_cdclk_verify_state(struct drm_i915_private *dev_priv);
+void broxton_ddi_phy_init(struct drm_i915_private *dev_priv);
+void broxton_ddi_phy_uninit(struct drm_i915_private *dev_priv);
+void broxton_ddi_phy_verify_state(struct drm_i915_private *dev_priv);
+void gen9_sanitize_dc_state(struct drm_i915_private *dev_priv);
 void bxt_enable_dc9(struct drm_i915_private *dev_priv);
 void bxt_disable_dc9(struct drm_i915_private *dev_priv);
+void gen9_enable_dc5(struct drm_i915_private *dev_priv);
 void skl_init_cdclk(struct drm_i915_private *dev_priv);
 int skl_sanitize_cdclk(struct drm_i915_private *dev_priv);
 void skl_uninit_cdclk(struct drm_i915_private *dev_priv);
@@ -1194,9 +1249,6 @@ void intel_dp_get_m_n(struct intel_crtc
 		      struct intel_crtc_state *pipe_config);
 void intel_dp_set_m_n(struct intel_crtc *crtc, enum link_m_n_set m_n);
 int intel_dotclock_calculate(int link_freq, const struct intel_link_m_n *m_n);
-void
-ironlake_check_encoder_dotclock(const struct intel_crtc_state *pipe_config,
-				int dotclock);
 bool bxt_find_best_dpll(struct intel_crtc_state *crtc_state, int target_clock,
 			intel_clock_t *best_clock);
 int chv_calc_dpll_params(int refclk, intel_clock_t *pll_clock);
@@ -1224,11 +1276,13 @@ u32 skl_plane_ctl_rotation(unsigned int
 
 /* intel_csr.c */
 void intel_csr_ucode_init(struct drm_i915_private *);
-bool intel_csr_load_program(struct drm_i915_private *);
+void intel_csr_load_program(struct drm_i915_private *);
 void intel_csr_ucode_fini(struct drm_i915_private *);
+void intel_csr_ucode_suspend(struct drm_i915_private *);
+void intel_csr_ucode_resume(struct drm_i915_private *);
 
 /* intel_dp.c */
-void intel_dp_init(struct drm_device *dev, i915_reg_t output_reg, enum port port);
+bool intel_dp_init(struct drm_device *dev, i915_reg_t output_reg, enum port port);
 bool intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 			     struct intel_connector *intel_connector);
 void intel_dp_set_link_params(struct intel_dp *intel_dp,
@@ -1266,7 +1320,6 @@ void intel_edp_drrs_invalidate(struct dr
 void intel_edp_drrs_flush(struct drm_device *dev, unsigned frontbuffer_bits);
 bool intel_digital_port_connected(struct drm_i915_private *dev_priv,
 					 struct intel_digital_port *port);
-void hsw_dp_set_ddi_pll_sel(struct intel_crtc_state *pipe_config);
 
 void
 intel_dp_program_link_training_pattern(struct intel_dp *intel_dp,
@@ -1351,6 +1404,7 @@ void intel_hdmi_init_connector(struct in
 struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder);
 bool intel_hdmi_compute_config(struct intel_encoder *encoder,
 			       struct intel_crtc_state *pipe_config);
+void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable);
 
 
 /* intel_lvds.c */
@@ -1423,8 +1477,8 @@ int intel_power_domains_init(struct drm_
 void intel_power_domains_fini(struct drm_i915_private *);
 void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume);
 void intel_power_domains_suspend(struct drm_i915_private *dev_priv);
-void skl_pw1_misc_io_init(struct drm_i915_private *dev_priv);
-void skl_pw1_misc_io_fini(struct drm_i915_private *dev_priv);
+void bxt_display_core_init(struct drm_i915_private *dev_priv, bool resume);
+void bxt_display_core_uninit(struct drm_i915_private *dev_priv);
 void intel_runtime_pm_enable(struct drm_i915_private *dev_priv);
 const char *
 intel_display_power_domain_str(enum intel_display_power_domain domain);
@@ -1541,6 +1595,7 @@ void intel_suspend_hw(struct drm_device
 int ilk_wm_max_level(const struct drm_device *dev);
 void intel_update_watermarks(struct drm_crtc *crtc);
 void intel_init_pm(struct drm_device *dev);
+void intel_init_clock_gating_hooks(struct drm_i915_private *dev_priv);
 void intel_pm_setup(struct drm_device *dev);
 void intel_gpu_ips_init(struct drm_i915_private *dev_priv);
 void intel_gpu_ips_teardown(void);
@@ -1565,6 +1620,7 @@ void skl_wm_get_hw_state(struct drm_devi
 void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
 			  struct skl_ddb_allocation *ddb /* out */);
 uint32_t ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config);
+bool ilk_disable_lp_wm(struct drm_device *dev);
 int sanitize_rc6_option(const struct drm_device *dev, int enable_rc6);
 
 /* intel_sdvo.c */
@@ -1606,6 +1662,18 @@ intel_atomic_get_crtc_state(struct drm_a
 
 	return to_intel_crtc_state(crtc_state);
 }
+
+static inline struct intel_plane_state *
+intel_atomic_get_existing_plane_state(struct drm_atomic_state *state,
+				      struct intel_plane *plane)
+{
+	struct drm_plane_state *plane_state;
+
+	plane_state = drm_atomic_get_existing_plane_state(state, &plane->base);
+
+	return to_intel_plane_state(plane_state);
+}
+
 int intel_atomic_setup_scalers(struct drm_device *dev,
 	struct intel_crtc *intel_crtc,
 	struct intel_crtc_state *crtc_state);
@@ -1617,4 +1685,10 @@ void intel_plane_destroy_state(struct dr
 			       struct drm_plane_state *state);
 extern const struct drm_plane_helper_funcs intel_plane_helper_funcs;
 
+/* intel_color.c */
+void intel_color_init(struct drm_crtc *crtc);
+int intel_color_check(struct drm_crtc *crtc, struct drm_crtc_state *state);
+void intel_color_set_csc(struct drm_crtc_state *crtc_state);
+void intel_color_load_luts(struct drm_crtc_state *crtc_state);
+
 #endif /* __INTEL_DRV_H__ */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_dsi.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_dsi.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_dsi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_dsi.c	2016-07-24 15:23:50.000000000 -0400
@@ -46,6 +46,40 @@ static const struct {
 	},
 };
 
+/* return pixels in terms of txbyteclkhs */
+static u16 txbyteclkhs(u16 pixels, int bpp, int lane_count,
+		       u16 burst_mode_ratio)
+{
+	return DIV_ROUND_UP(DIV_ROUND_UP(pixels * bpp * burst_mode_ratio,
+					 8 * 100), lane_count);
+}
+
+/* return pixels equvalent to txbyteclkhs */
+static u16 pixels_from_txbyteclkhs(u16 clk_hs, int bpp, int lane_count,
+			u16 burst_mode_ratio)
+{
+	return DIV_ROUND_UP((clk_hs * lane_count * 8 * 100),
+						(bpp * burst_mode_ratio));
+}
+
+enum mipi_dsi_pixel_format pixel_format_from_register_bits(u32 fmt)
+{
+	/* It just so happens the VBT matches register contents. */
+	switch (fmt) {
+	case VID_MODE_FORMAT_RGB888:
+		return MIPI_DSI_FMT_RGB888;
+	case VID_MODE_FORMAT_RGB666:
+		return MIPI_DSI_FMT_RGB666;
+	case VID_MODE_FORMAT_RGB666_PACKED:
+		return MIPI_DSI_FMT_RGB666_PACKED;
+	case VID_MODE_FORMAT_RGB565:
+		return MIPI_DSI_FMT_RGB565;
+	default:
+		MISSING_CASE(fmt);
+		return MIPI_DSI_FMT_RGB666;
+	}
+}
+
 static void wait_for_dsi_fifo_empty(struct intel_dsi *intel_dsi, enum port port)
 {
 	struct drm_encoder *encoder = &intel_dsi->base.base;
@@ -268,22 +302,47 @@ static inline bool is_cmd_mode(struct in
 static bool intel_dsi_compute_config(struct intel_encoder *encoder,
 				     struct intel_crtc_state *pipe_config)
 {
+	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
 	struct intel_dsi *intel_dsi = container_of(encoder, struct intel_dsi,
 						   base);
 	struct intel_connector *intel_connector = intel_dsi->attached_connector;
-	struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode;
+	struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc);
+	const struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode;
 	struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
+	int ret;
 
 	DRM_DEBUG_KMS("\n");
 
 	pipe_config->has_dsi_encoder = true;
 
-	if (fixed_mode)
+	if (fixed_mode) {
 		intel_fixed_panel_mode(fixed_mode, adjusted_mode);
 
+		if (HAS_GMCH_DISPLAY(dev_priv))
+			intel_gmch_panel_fitting(crtc, pipe_config,
+						 intel_connector->panel.fitting_mode);
+		else
+			intel_pch_panel_fitting(crtc, pipe_config,
+						intel_connector->panel.fitting_mode);
+	}
+
 	/* DSI uses short packets for sync events, so clear mode flags for DSI */
 	adjusted_mode->flags = 0;
 
+	if (IS_BROXTON(dev_priv)) {
+		/* Dual link goes to DSI transcoder A. */
+		if (intel_dsi->ports == BIT(PORT_C))
+			pipe_config->cpu_transcoder = TRANSCODER_DSI_C;
+		else
+			pipe_config->cpu_transcoder = TRANSCODER_DSI_A;
+	}
+
+	ret = intel_compute_dsi_pll(encoder, pipe_config);
+	if (ret)
+		return false;
+
+	pipe_config->clock_set = true;
+
 	return true;
 }
 
@@ -403,7 +462,7 @@ static void intel_dsi_port_enable(struct
 		temp &= ~LANE_CONFIGURATION_MASK;
 		temp &= ~DUAL_LINK_MODE_MASK;
 
-		if (intel_dsi->ports == ((1 << PORT_A) | (1 << PORT_C))) {
+		if (intel_dsi->ports == (BIT(PORT_A) | BIT(PORT_C))) {
 			temp |= (intel_dsi->dual_link - 1)
 						<< DUAL_LINK_MODE_SHIFT;
 			temp |= intel_crtc->pipe ?
@@ -471,14 +530,19 @@ static void intel_dsi_pre_enable(struct
 	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
-	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
-	enum pipe pipe = intel_crtc->pipe;
+	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
 	enum port port;
 	u32 tmp;
 
 	DRM_DEBUG_KMS("\n");
 
-	intel_enable_dsi_pll(encoder);
+	/*
+	 * The BIOS may leave the PLL in a wonky state where it doesn't
+	 * lock. It needs to be fully powered down to fix it.
+	 */
+	intel_disable_dsi_pll(encoder);
+	intel_enable_dsi_pll(encoder, crtc->config);
+
 	intel_dsi_prepare(encoder);
 
 	/* Panel Enable over CRC PMIC */
@@ -488,19 +552,7 @@ static void intel_dsi_pre_enable(struct
 	msleep(intel_dsi->panel_on_delay);
 
 	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
-		/*
-		 * Disable DPOunit clock gating, can stall pipe
-		 * and we need DPLL REFA always enabled
-		 */
-		tmp = I915_READ(DPLL(pipe));
-		tmp |= DPLL_REF_CLK_ENABLE_VLV;
-		I915_WRITE(DPLL(pipe), tmp);
-
-		/* update the hw state for DPLL */
-		intel_crtc->config->dpll_hw_state.dpll =
-				DPLL_INTEGRATED_REF_CLK_VLV |
-					DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS;
-
+		/* Disable DPOunit clock gating, can stall pipe */
 		tmp = I915_READ(DSPCLK_GATE_D);
 		tmp |= DPOUNIT_CLOCK_GATE_DISABLE;
 		I915_WRITE(DSPCLK_GATE_D, tmp);
@@ -652,11 +704,16 @@ static void intel_dsi_post_disable(struc
 	drm_panel_unprepare(intel_dsi->panel);
 
 	msleep(intel_dsi->panel_off_delay);
-	msleep(intel_dsi->panel_pwr_cycle_delay);
 
 	/* Panel Disable over CRC PMIC */
 	if (intel_dsi->gpio_panel)
 		gpiod_set_value_cansleep(intel_dsi->gpio_panel, 0);
+
+	/*
+	 * FIXME As we do with eDP, just make a note of the time here
+	 * and perform the wait before the next panel power on.
+	 */
+	msleep(intel_dsi->panel_pwr_cycle_delay);
 }
 
 static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
@@ -667,7 +724,7 @@ static bool intel_dsi_get_hw_state(struc
 	struct drm_device *dev = encoder->base.dev;
 	enum intel_display_power_domain power_domain;
 	enum port port;
-	bool ret;
+	bool active = false;
 
 	DRM_DEBUG_KMS("\n");
 
@@ -675,55 +732,234 @@ static bool intel_dsi_get_hw_state(struc
 	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
 		return false;
 
-	ret = false;
+	/*
+	 * On Broxton the PLL needs to be enabled with a valid divider
+	 * configuration, otherwise accessing DSI registers will hang the
+	 * machine. See BSpec North Display Engine registers/MIPI[BXT].
+	 */
+	if (IS_BROXTON(dev_priv) && !intel_dsi_pll_is_enabled(dev_priv))
+		goto out_put_power;
 
 	/* XXX: this only works for one DSI output */
 	for_each_dsi_port(port, intel_dsi->ports) {
 		i915_reg_t ctrl_reg = IS_BROXTON(dev) ?
 			BXT_MIPI_PORT_CTRL(port) : MIPI_PORT_CTRL(port);
-		u32 dpi_enabled, func;
-
-		func = I915_READ(MIPI_DSI_FUNC_PRG(port));
-		dpi_enabled = I915_READ(ctrl_reg) & DPI_ENABLE;
+		bool enabled = I915_READ(ctrl_reg) & DPI_ENABLE;
 
-		/* Due to some hardware limitations on BYT, MIPI Port C DPI
-		 * Enable bit does not get set. To check whether DSI Port C
-		 * was enabled in BIOS, check the Pipe B enable bit
+		/*
+		 * Due to some hardware limitations on VLV/CHV, the DPI enable
+		 * bit in port C control register does not get set. As a
+		 * workaround, check pipe B conf instead.
 		 */
-		if (IS_VALLEYVIEW(dev) && port == PORT_C)
-			dpi_enabled = I915_READ(PIPECONF(PIPE_B)) &
-							PIPECONF_ENABLE;
+		if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) && port == PORT_C)
+			enabled = I915_READ(PIPECONF(PIPE_B)) & PIPECONF_ENABLE;
 
-		if (dpi_enabled || (func & CMD_MODE_DATA_WIDTH_MASK)) {
-			if (I915_READ(MIPI_DEVICE_READY(port)) & DEVICE_READY) {
-				*pipe = port == PORT_A ? PIPE_A : PIPE_B;
-				ret = true;
+		/* Try command mode if video mode not enabled */
+		if (!enabled) {
+			u32 tmp = I915_READ(MIPI_DSI_FUNC_PRG(port));
+			enabled = tmp & CMD_MODE_DATA_WIDTH_MASK;
+		}
 
-				goto out;
-			}
+		if (!enabled)
+			continue;
+
+		if (!(I915_READ(MIPI_DEVICE_READY(port)) & DEVICE_READY))
+			continue;
+
+		if (IS_BROXTON(dev_priv)) {
+			u32 tmp = I915_READ(MIPI_CTRL(port));
+			tmp &= BXT_PIPE_SELECT_MASK;
+			tmp >>= BXT_PIPE_SELECT_SHIFT;
+
+			if (WARN_ON(tmp > PIPE_C))
+				continue;
+
+			*pipe = tmp;
+		} else {
+			*pipe = port == PORT_A ? PIPE_A : PIPE_B;
 		}
+
+		active = true;
+		break;
 	}
-out:
+
+out_put_power:
 	intel_display_power_put(dev_priv, power_domain);
 
-	return ret;
+	return active;
+}
+
+static void bxt_dsi_get_pipe_config(struct intel_encoder *encoder,
+				 struct intel_crtc_state *pipe_config)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_display_mode *adjusted_mode =
+					&pipe_config->base.adjusted_mode;
+	struct drm_display_mode *adjusted_mode_sw;
+	struct intel_crtc *intel_crtc;
+	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
+	unsigned int lane_count = intel_dsi->lane_count;
+	unsigned int bpp, fmt;
+	enum port port;
+	u16 hactive, hfp, hsync, hbp, vfp, vsync, vbp;
+	u16 hfp_sw, hsync_sw, hbp_sw;
+	u16 crtc_htotal_sw, crtc_hsync_start_sw, crtc_hsync_end_sw,
+				crtc_hblank_start_sw, crtc_hblank_end_sw;
+
+	intel_crtc = to_intel_crtc(encoder->base.crtc);
+	adjusted_mode_sw = &intel_crtc->config->base.adjusted_mode;
+
+	/*
+	 * Atleast one port is active as encoder->get_config called only if
+	 * encoder->get_hw_state() returns true.
+	 */
+	for_each_dsi_port(port, intel_dsi->ports) {
+		if (I915_READ(BXT_MIPI_PORT_CTRL(port)) & DPI_ENABLE)
+			break;
+	}
+
+	fmt = I915_READ(MIPI_DSI_FUNC_PRG(port)) & VID_MODE_FORMAT_MASK;
+	pipe_config->pipe_bpp =
+			mipi_dsi_pixel_format_to_bpp(
+				pixel_format_from_register_bits(fmt));
+	bpp = pipe_config->pipe_bpp;
+
+	/* In terms of pixels */
+	adjusted_mode->crtc_hdisplay =
+				I915_READ(BXT_MIPI_TRANS_HACTIVE(port));
+	adjusted_mode->crtc_vdisplay =
+				I915_READ(BXT_MIPI_TRANS_VACTIVE(port));
+	adjusted_mode->crtc_vtotal =
+				I915_READ(BXT_MIPI_TRANS_VTOTAL(port));
+
+	hactive = adjusted_mode->crtc_hdisplay;
+	hfp = I915_READ(MIPI_HFP_COUNT(port));
+
+	/*
+	 * Meaningful for video mode non-burst sync pulse mode only,
+	 * can be zero for non-burst sync events and burst modes
+	 */
+	hsync = I915_READ(MIPI_HSYNC_PADDING_COUNT(port));
+	hbp = I915_READ(MIPI_HBP_COUNT(port));
+
+	/* harizontal values are in terms of high speed byte clock */
+	hfp = pixels_from_txbyteclkhs(hfp, bpp, lane_count,
+						intel_dsi->burst_mode_ratio);
+	hsync = pixels_from_txbyteclkhs(hsync, bpp, lane_count,
+						intel_dsi->burst_mode_ratio);
+	hbp = pixels_from_txbyteclkhs(hbp, bpp, lane_count,
+						intel_dsi->burst_mode_ratio);
+
+	if (intel_dsi->dual_link) {
+		hfp *= 2;
+		hsync *= 2;
+		hbp *= 2;
+	}
+
+	/* vertical values are in terms of lines */
+	vfp = I915_READ(MIPI_VFP_COUNT(port));
+	vsync = I915_READ(MIPI_VSYNC_PADDING_COUNT(port));
+	vbp = I915_READ(MIPI_VBP_COUNT(port));
+
+	adjusted_mode->crtc_htotal = hactive + hfp + hsync + hbp;
+	adjusted_mode->crtc_hsync_start = hfp + adjusted_mode->crtc_hdisplay;
+	adjusted_mode->crtc_hsync_end = hsync + adjusted_mode->crtc_hsync_start;
+	adjusted_mode->crtc_hblank_start = adjusted_mode->crtc_hdisplay;
+	adjusted_mode->crtc_hblank_end = adjusted_mode->crtc_htotal;
+
+	adjusted_mode->crtc_vsync_start = vfp + adjusted_mode->crtc_vdisplay;
+	adjusted_mode->crtc_vsync_end = vsync + adjusted_mode->crtc_vsync_start;
+	adjusted_mode->crtc_vblank_start = adjusted_mode->crtc_vdisplay;
+	adjusted_mode->crtc_vblank_end = adjusted_mode->crtc_vtotal;
+
+	/*
+	 * In BXT DSI there is no regs programmed with few horizontal timings
+	 * in Pixels but txbyteclkhs.. So retrieval process adds some
+	 * ROUND_UP ERRORS in the process of PIXELS<==>txbyteclkhs.
+	 * Actually here for the given adjusted_mode, we are calculating the
+	 * value programmed to the port and then back to the horizontal timing
+	 * param in pixels. This is the expected value, including roundup errors
+	 * And if that is same as retrieved value from port, then
+	 * (HW state) adjusted_mode's horizontal timings are corrected to
+	 * match with SW state to nullify the errors.
+	 */
+	/* Calculating the value programmed to the Port register */
+	hfp_sw = adjusted_mode_sw->crtc_hsync_start -
+					adjusted_mode_sw->crtc_hdisplay;
+	hsync_sw = adjusted_mode_sw->crtc_hsync_end -
+					adjusted_mode_sw->crtc_hsync_start;
+	hbp_sw = adjusted_mode_sw->crtc_htotal -
+					adjusted_mode_sw->crtc_hsync_end;
+
+	if (intel_dsi->dual_link) {
+		hfp_sw /= 2;
+		hsync_sw /= 2;
+		hbp_sw /= 2;
+	}
+
+	hfp_sw = txbyteclkhs(hfp_sw, bpp, lane_count,
+						intel_dsi->burst_mode_ratio);
+	hsync_sw = txbyteclkhs(hsync_sw, bpp, lane_count,
+			    intel_dsi->burst_mode_ratio);
+	hbp_sw = txbyteclkhs(hbp_sw, bpp, lane_count,
+						intel_dsi->burst_mode_ratio);
+
+	/* Reverse calculating the adjusted mode parameters from port reg vals*/
+	hfp_sw = pixels_from_txbyteclkhs(hfp_sw, bpp, lane_count,
+						intel_dsi->burst_mode_ratio);
+	hsync_sw = pixels_from_txbyteclkhs(hsync_sw, bpp, lane_count,
+						intel_dsi->burst_mode_ratio);
+	hbp_sw = pixels_from_txbyteclkhs(hbp_sw, bpp, lane_count,
+						intel_dsi->burst_mode_ratio);
+
+	if (intel_dsi->dual_link) {
+		hfp_sw *= 2;
+		hsync_sw *= 2;
+		hbp_sw *= 2;
+	}
+
+	crtc_htotal_sw = adjusted_mode_sw->crtc_hdisplay + hfp_sw +
+							hsync_sw + hbp_sw;
+	crtc_hsync_start_sw = hfp_sw + adjusted_mode_sw->crtc_hdisplay;
+	crtc_hsync_end_sw = hsync_sw + crtc_hsync_start_sw;
+	crtc_hblank_start_sw = adjusted_mode_sw->crtc_hdisplay;
+	crtc_hblank_end_sw = crtc_htotal_sw;
+
+	if (adjusted_mode->crtc_htotal == crtc_htotal_sw)
+		adjusted_mode->crtc_htotal = adjusted_mode_sw->crtc_htotal;
+
+	if (adjusted_mode->crtc_hsync_start == crtc_hsync_start_sw)
+		adjusted_mode->crtc_hsync_start =
+					adjusted_mode_sw->crtc_hsync_start;
+
+	if (adjusted_mode->crtc_hsync_end == crtc_hsync_end_sw)
+		adjusted_mode->crtc_hsync_end =
+					adjusted_mode_sw->crtc_hsync_end;
+
+	if (adjusted_mode->crtc_hblank_start == crtc_hblank_start_sw)
+		adjusted_mode->crtc_hblank_start =
+					adjusted_mode_sw->crtc_hblank_start;
+
+	if (adjusted_mode->crtc_hblank_end == crtc_hblank_end_sw)
+		adjusted_mode->crtc_hblank_end =
+					adjusted_mode_sw->crtc_hblank_end;
 }
 
 static void intel_dsi_get_config(struct intel_encoder *encoder,
 				 struct intel_crtc_state *pipe_config)
 {
+	struct drm_device *dev = encoder->base.dev;
 	u32 pclk;
 	DRM_DEBUG_KMS("\n");
 
 	pipe_config->has_dsi_encoder = true;
 
-	/*
-	 * DPLL_MD is not used in case of DSI, reading will get some default value
-	 * set dpll_md = 0
-	 */
-	pipe_config->dpll_hw_state.dpll_md = 0;
+	if (IS_BROXTON(dev))
+		bxt_dsi_get_pipe_config(encoder, pipe_config);
 
-	pclk = intel_dsi_get_pclk(encoder, pipe_config->pipe_bpp);
+	pclk = intel_dsi_get_pclk(encoder, pipe_config->pipe_bpp,
+				  pipe_config);
 	if (!pclk)
 		return;
 
@@ -736,7 +972,7 @@ intel_dsi_mode_valid(struct drm_connecto
 		     struct drm_display_mode *mode)
 {
 	struct intel_connector *intel_connector = to_intel_connector(connector);
-	struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode;
+	const struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode;
 	int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
 
 	DRM_DEBUG_KMS("\n");
@@ -772,14 +1008,6 @@ static u16 txclkesc(u32 divider, unsigne
 	}
 }
 
-/* return pixels in terms of txbyteclkhs */
-static u16 txbyteclkhs(u16 pixels, int bpp, int lane_count,
-		       u16 burst_mode_ratio)
-{
-	return DIV_ROUND_UP(DIV_ROUND_UP(pixels * bpp * burst_mode_ratio,
-					 8 * 100), lane_count);
-}
-
 static void set_dsi_timings(struct drm_encoder *encoder,
 			    const struct drm_display_mode *adjusted_mode)
 {
@@ -787,7 +1015,7 @@ static void set_dsi_timings(struct drm_e
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
 	enum port port;
-	unsigned int bpp = dsi_pixel_format_bpp(intel_dsi->pixel_format);
+	unsigned int bpp = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format);
 	unsigned int lane_count = intel_dsi->lane_count;
 
 	u16 hactive, hfp, hsync, hbp, vfp, vsync, vbp;
@@ -849,6 +1077,23 @@ static void set_dsi_timings(struct drm_e
 	}
 }
 
+static u32 pixel_format_to_reg(enum mipi_dsi_pixel_format fmt)
+{
+	switch (fmt) {
+	case MIPI_DSI_FMT_RGB888:
+		return VID_MODE_FORMAT_RGB888;
+	case MIPI_DSI_FMT_RGB666:
+		return VID_MODE_FORMAT_RGB666;
+	case MIPI_DSI_FMT_RGB666_PACKED:
+		return VID_MODE_FORMAT_RGB666_PACKED;
+	case MIPI_DSI_FMT_RGB565:
+		return VID_MODE_FORMAT_RGB565;
+	default:
+		MISSING_CASE(fmt);
+		return VID_MODE_FORMAT_RGB666;
+	}
+}
+
 static void intel_dsi_prepare(struct intel_encoder *intel_encoder)
 {
 	struct drm_encoder *encoder = &intel_encoder->base;
@@ -858,7 +1103,7 @@ static void intel_dsi_prepare(struct int
 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
 	const struct drm_display_mode *adjusted_mode = &intel_crtc->config->base.adjusted_mode;
 	enum port port;
-	unsigned int bpp = dsi_pixel_format_bpp(intel_dsi->pixel_format);
+	unsigned int bpp = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format);
 	u32 val, tmp;
 	u16 mode_hdisplay;
 
@@ -917,9 +1162,7 @@ static void intel_dsi_prepare(struct int
 		val |= CMD_MODE_DATA_WIDTH_8_BIT; /* XXX */
 	} else {
 		val |= intel_dsi->channel << VID_MODE_CHANNEL_NUMBER_SHIFT;
-
-		/* XXX: cross-check bpp vs. pixel format? */
-		val |= intel_dsi->pixel_format;
+		val |= pixel_format_to_reg(intel_dsi->pixel_format);
 	}
 
 	tmp = 0;
@@ -1059,6 +1302,48 @@ static int intel_dsi_get_modes(struct dr
 	return 1;
 }
 
+static int intel_dsi_set_property(struct drm_connector *connector,
+				  struct drm_property *property,
+				  uint64_t val)
+{
+	struct drm_device *dev = connector->dev;
+	struct intel_connector *intel_connector = to_intel_connector(connector);
+	struct drm_crtc *crtc;
+	int ret;
+
+	ret = drm_object_property_set_value(&connector->base, property, val);
+	if (ret)
+		return ret;
+
+	if (property == dev->mode_config.scaling_mode_property) {
+		if (val == DRM_MODE_SCALE_NONE) {
+			DRM_DEBUG_KMS("no scaling not supported\n");
+			return -EINVAL;
+		}
+		if (HAS_GMCH_DISPLAY(dev) &&
+		    val == DRM_MODE_SCALE_CENTER) {
+			DRM_DEBUG_KMS("centering not supported\n");
+			return -EINVAL;
+		}
+
+		if (intel_connector->panel.fitting_mode == val)
+			return 0;
+
+		intel_connector->panel.fitting_mode = val;
+	}
+
+	crtc = intel_attached_encoder(connector)->base.crtc;
+	if (crtc && crtc->state->enable) {
+		/*
+		 * If the CRTC is enabled, the display will be changed
+		 * according to the new panel fitting mode.
+		 */
+		intel_crtc_restore_mode(crtc);
+	}
+
+	return 0;
+}
+
 static void intel_dsi_connector_destroy(struct drm_connector *connector)
 {
 	struct intel_connector *intel_connector = to_intel_connector(connector);
@@ -1101,11 +1386,25 @@ static const struct drm_connector_funcs
 	.detect = intel_dsi_detect,
 	.destroy = intel_dsi_connector_destroy,
 	.fill_modes = drm_helper_probe_single_connector_modes,
+	.set_property = intel_dsi_set_property,
 	.atomic_get_property = intel_connector_atomic_get_property,
 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
 };
 
+static void intel_dsi_add_properties(struct intel_connector *connector)
+{
+	struct drm_device *dev = connector->base.dev;
+
+	if (connector->panel.fixed_mode) {
+		drm_mode_create_scaling_mode_property(dev);
+		drm_object_attach_property(&connector->base.base,
+					   dev->mode_config.scaling_mode_property,
+					   DRM_MODE_SCALE_ASPECT);
+		connector->panel.fitting_mode = DRM_MODE_SCALE_ASPECT;
+	}
+}
+
 void intel_dsi_init(struct drm_device *dev)
 {
 	struct intel_dsi *intel_dsi;
@@ -1121,11 +1420,13 @@ void intel_dsi_init(struct drm_device *d
 	DRM_DEBUG_KMS("\n");
 
 	/* There is no detection method for MIPI so rely on VBT */
-	if (!dev_priv->vbt.has_mipi)
+	if (!intel_bios_is_dsi_present(dev_priv, &port))
 		return;
 
 	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
 		dev_priv->mipi_mmio_base = VLV_MIPI_BASE;
+	} else if (IS_BROXTON(dev)) {
+		dev_priv->mipi_mmio_base = BXT_MIPI_BASE;
 	} else {
 		DRM_ERROR("Unsupported Mipi device to reg base");
 		return;
@@ -1161,17 +1462,21 @@ void intel_dsi_init(struct drm_device *d
 	intel_connector->get_hw_state = intel_connector_get_hw_state;
 	intel_connector->unregister = intel_connector_unregister;
 
-	/* Pipe A maps to MIPI DSI port A, pipe B maps to MIPI DSI port C */
-	if (dev_priv->vbt.dsi.port == DVO_PORT_MIPIA) {
-		intel_encoder->crtc_mask = (1 << PIPE_A);
-		intel_dsi->ports = (1 << PORT_A);
-	} else if (dev_priv->vbt.dsi.port == DVO_PORT_MIPIC) {
-		intel_encoder->crtc_mask = (1 << PIPE_B);
-		intel_dsi->ports = (1 << PORT_C);
-	}
+	/*
+	 * On BYT/CHV, pipe A maps to MIPI DSI port A, pipe B maps to MIPI DSI
+	 * port C. BXT isn't limited like this.
+	 */
+	if (IS_BROXTON(dev_priv))
+		intel_encoder->crtc_mask = BIT(PIPE_A) | BIT(PIPE_B) | BIT(PIPE_C);
+	else if (port == PORT_A)
+		intel_encoder->crtc_mask = BIT(PIPE_A);
+	else
+		intel_encoder->crtc_mask = BIT(PIPE_B);
 
 	if (dev_priv->vbt.dsi.config->dual_link)
-		intel_dsi->ports = ((1 << PORT_A) | (1 << PORT_C));
+		intel_dsi->ports = BIT(PORT_A) | BIT(PORT_C);
+	else
+		intel_dsi->ports = BIT(port);
 
 	/* Create a DSI host (and a device) for each port. */
 	for_each_dsi_port(port, intel_dsi->ports) {
@@ -1223,8 +1528,6 @@ void intel_dsi_init(struct drm_device *d
 
 	intel_connector_attach_encoder(intel_connector, intel_encoder);
 
-	drm_connector_register(connector);
-
 	drm_panel_attach(intel_dsi->panel, connector);
 
 	mutex_lock(&dev->mode_config.mutex);
@@ -1242,7 +1545,15 @@ void intel_dsi_init(struct drm_device *d
 		goto err;
 	}
 
+	connector->display_info.width_mm = fixed_mode->width_mm;
+	connector->display_info.height_mm = fixed_mode->height_mm;
+
 	intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
+
+	intel_dsi_add_properties(intel_connector);
+
+	drm_connector_register(connector);
+
 	intel_panel_setup_backlight(connector, INVALID_PIPE);
 
 	return;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_dsi.h linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_dsi.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_dsi.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_dsi.h	2016-07-24 15:23:50.000000000 -0400
@@ -34,8 +34,6 @@
 #define DSI_DUAL_LINK_FRONT_BACK	1
 #define DSI_DUAL_LINK_PIXEL_ALT		2
 
-int dsi_pixel_format_bpp(int pixel_format);
-
 struct intel_dsi_host;
 
 struct intel_dsi {
@@ -64,8 +62,12 @@ struct intel_dsi {
 	/* number of DSI lanes */
 	unsigned int lane_count;
 
-	/* video mode pixel format for MIPI_DSI_FUNC_PRG register */
-	u32 pixel_format;
+	/*
+	 * video mode pixel format
+	 *
+	 * XXX: consolidate on .format in struct mipi_dsi_device.
+	 */
+	enum mipi_dsi_pixel_format pixel_format;
 
 	/* video mode format for MIPI_VIDEO_MODE_FORMAT register */
 	u32 video_mode_format;
@@ -117,21 +119,25 @@ static inline struct intel_dsi_host *to_
 	return container_of(h, struct intel_dsi_host, base);
 }
 
-#define for_each_dsi_port(__port, __ports_mask) \
-	for ((__port) = PORT_A; (__port) < I915_MAX_PORTS; (__port)++)	\
-		for_each_if ((__ports_mask) & (1 << (__port)))
+#define for_each_dsi_port(__port, __ports_mask) for_each_port_masked(__port, __ports_mask)
 
 static inline struct intel_dsi *enc_to_intel_dsi(struct drm_encoder *encoder)
 {
 	return container_of(encoder, struct intel_dsi, base.base);
 }
 
-extern void intel_enable_dsi_pll(struct intel_encoder *encoder);
-extern void intel_disable_dsi_pll(struct intel_encoder *encoder);
-extern u32 intel_dsi_get_pclk(struct intel_encoder *encoder, int pipe_bpp);
-extern void intel_dsi_reset_clocks(struct intel_encoder *encoder,
-							enum port port);
+bool intel_dsi_pll_is_enabled(struct drm_i915_private *dev_priv);
+int intel_compute_dsi_pll(struct intel_encoder *encoder,
+			  struct intel_crtc_state *config);
+void intel_enable_dsi_pll(struct intel_encoder *encoder,
+			  const struct intel_crtc_state *config);
+void intel_disable_dsi_pll(struct intel_encoder *encoder);
+u32 intel_dsi_get_pclk(struct intel_encoder *encoder, int pipe_bpp,
+		       struct intel_crtc_state *config);
+void intel_dsi_reset_clocks(struct intel_encoder *encoder,
+			    enum port port);
 
 struct drm_panel *vbt_panel_init(struct intel_dsi *intel_dsi, u16 panel_id);
+enum mipi_dsi_pixel_format pixel_format_from_register_bits(u32 fmt);
 
 #endif /* _INTEL_DSI_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c	2016-07-24 15:23:50.000000000 -0400
@@ -58,50 +58,41 @@ static inline struct vbt_panel *to_vbt_p
 
 #define NS_KHZ_RATIO 1000000
 
-#define GPI0_NC_0_HV_DDI0_HPD           0x4130
-#define GPIO_NC_0_HV_DDI0_PAD           0x4138
-#define GPIO_NC_1_HV_DDI0_DDC_SDA       0x4120
-#define GPIO_NC_1_HV_DDI0_DDC_SDA_PAD   0x4128
-#define GPIO_NC_2_HV_DDI0_DDC_SCL       0x4110
-#define GPIO_NC_2_HV_DDI0_DDC_SCL_PAD   0x4118
-#define GPIO_NC_3_PANEL0_VDDEN          0x4140
-#define GPIO_NC_3_PANEL0_VDDEN_PAD      0x4148
-#define GPIO_NC_4_PANEL0_BLKEN          0x4150
-#define GPIO_NC_4_PANEL0_BLKEN_PAD      0x4158
-#define GPIO_NC_5_PANEL0_BLKCTL         0x4160
-#define GPIO_NC_5_PANEL0_BLKCTL_PAD     0x4168
-#define GPIO_NC_6_PCONF0                0x4180
-#define GPIO_NC_6_PAD                   0x4188
-#define GPIO_NC_7_PCONF0                0x4190
-#define GPIO_NC_7_PAD                   0x4198
-#define GPIO_NC_8_PCONF0                0x4170
-#define GPIO_NC_8_PAD                   0x4178
-#define GPIO_NC_9_PCONF0                0x4100
-#define GPIO_NC_9_PAD                   0x4108
-#define GPIO_NC_10_PCONF0               0x40E0
-#define GPIO_NC_10_PAD                  0x40E8
-#define GPIO_NC_11_PCONF0               0x40F0
-#define GPIO_NC_11_PAD                  0x40F8
+/* base offsets for gpio pads */
+#define VLV_GPIO_NC_0_HV_DDI0_HPD	0x4130
+#define VLV_GPIO_NC_1_HV_DDI0_DDC_SDA	0x4120
+#define VLV_GPIO_NC_2_HV_DDI0_DDC_SCL	0x4110
+#define VLV_GPIO_NC_3_PANEL0_VDDEN	0x4140
+#define VLV_GPIO_NC_4_PANEL0_BKLTEN	0x4150
+#define VLV_GPIO_NC_5_PANEL0_BKLTCTL	0x4160
+#define VLV_GPIO_NC_6_HV_DDI1_HPD	0x4180
+#define VLV_GPIO_NC_7_HV_DDI1_DDC_SDA	0x4190
+#define VLV_GPIO_NC_8_HV_DDI1_DDC_SCL	0x4170
+#define VLV_GPIO_NC_9_PANEL1_VDDEN	0x4100
+#define VLV_GPIO_NC_10_PANEL1_BKLTEN	0x40E0
+#define VLV_GPIO_NC_11_PANEL1_BKLTCTL	0x40F0
 
-struct gpio_table {
-	u16 function_reg;
-	u16 pad_reg;
-	u8 init;
+#define VLV_GPIO_PCONF0(base_offset)	(base_offset)
+#define VLV_GPIO_PAD_VAL(base_offset)	((base_offset) + 8)
+
+struct gpio_map {
+	u16 base_offset;
+	bool init;
 };
 
-static struct gpio_table gtable[] = {
-	{ GPI0_NC_0_HV_DDI0_HPD, GPIO_NC_0_HV_DDI0_PAD, 0 },
-	{ GPIO_NC_1_HV_DDI0_DDC_SDA, GPIO_NC_1_HV_DDI0_DDC_SDA_PAD, 0 },
-	{ GPIO_NC_2_HV_DDI0_DDC_SCL, GPIO_NC_2_HV_DDI0_DDC_SCL_PAD, 0 },
-	{ GPIO_NC_3_PANEL0_VDDEN, GPIO_NC_3_PANEL0_VDDEN_PAD, 0 },
-	{ GPIO_NC_4_PANEL0_BLKEN, GPIO_NC_4_PANEL0_BLKEN_PAD, 0 },
-	{ GPIO_NC_5_PANEL0_BLKCTL, GPIO_NC_5_PANEL0_BLKCTL_PAD, 0 },
-	{ GPIO_NC_6_PCONF0, GPIO_NC_6_PAD, 0 },
-	{ GPIO_NC_7_PCONF0, GPIO_NC_7_PAD, 0 },
-	{ GPIO_NC_8_PCONF0, GPIO_NC_8_PAD, 0 },
-	{ GPIO_NC_9_PCONF0, GPIO_NC_9_PAD, 0 },
-	{ GPIO_NC_10_PCONF0, GPIO_NC_10_PAD, 0},
-	{ GPIO_NC_11_PCONF0, GPIO_NC_11_PAD, 0}
+static struct gpio_map vlv_gpio_table[] = {
+	{ VLV_GPIO_NC_0_HV_DDI0_HPD },
+	{ VLV_GPIO_NC_1_HV_DDI0_DDC_SDA },
+	{ VLV_GPIO_NC_2_HV_DDI0_DDC_SCL },
+	{ VLV_GPIO_NC_3_PANEL0_VDDEN },
+	{ VLV_GPIO_NC_4_PANEL0_BKLTEN },
+	{ VLV_GPIO_NC_5_PANEL0_BKLTCTL },
+	{ VLV_GPIO_NC_6_HV_DDI1_HPD },
+	{ VLV_GPIO_NC_7_HV_DDI1_DDC_SDA },
+	{ VLV_GPIO_NC_8_HV_DDI1_DDC_SCL },
+	{ VLV_GPIO_NC_9_PANEL1_VDDEN },
+	{ VLV_GPIO_NC_10_PANEL1_BKLTEN },
+	{ VLV_GPIO_NC_11_PANEL1_BKLTCTL },
 };
 
 static inline enum port intel_dsi_seq_port_to_port(u8 port)
@@ -196,56 +187,76 @@ static const u8 *mipi_exec_delay(struct
 	return data;
 }
 
-static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data)
+static void vlv_exec_gpio(struct drm_i915_private *dev_priv,
+			  u8 gpio_source, u8 gpio_index, bool value)
 {
-	u8 gpio, action;
-	u16 function, pad;
-	u32 val;
-	struct drm_device *dev = intel_dsi->base.base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-
-	if (dev_priv->vbt.dsi.seq_version >= 3)
-		data++;
-
-	gpio = *data++;
-
-	/* pull up/down */
-	action = *data++ & 1;
+	struct gpio_map *map;
+	u16 pconf0, padval;
+	u32 tmp;
+	u8 port;
 
-	if (gpio >= ARRAY_SIZE(gtable)) {
-		DRM_DEBUG_KMS("unknown gpio %u\n", gpio);
-		goto out;
+	if (gpio_index >= ARRAY_SIZE(vlv_gpio_table)) {
+		DRM_DEBUG_KMS("unknown gpio index %u\n", gpio_index);
+		return;
 	}
 
-	if (!IS_VALLEYVIEW(dev_priv)) {
-		DRM_DEBUG_KMS("GPIO element not supported on this platform\n");
-		goto out;
-	}
+	map = &vlv_gpio_table[gpio_index];
 
 	if (dev_priv->vbt.dsi.seq_version >= 3) {
 		DRM_DEBUG_KMS("GPIO element v3 not supported\n");
-		goto out;
+		return;
+	} else {
+		if (gpio_source == 0) {
+			port = IOSF_PORT_GPIO_NC;
+		} else if (gpio_source == 1) {
+			port = IOSF_PORT_GPIO_SC;
+		} else {
+			DRM_DEBUG_KMS("unknown gpio source %u\n", gpio_source);
+			return;
+		}
 	}
 
-	function = gtable[gpio].function_reg;
-	pad = gtable[gpio].pad_reg;
+	pconf0 = VLV_GPIO_PCONF0(map->base_offset);
+	padval = VLV_GPIO_PAD_VAL(map->base_offset);
 
 	mutex_lock(&dev_priv->sb_lock);
-	if (!gtable[gpio].init) {
-		/* program the function */
+	if (!map->init) {
 		/* FIXME: remove constant below */
-		vlv_iosf_sb_write(dev_priv, IOSF_PORT_GPIO_NC, function,
-				  0x2000CC00);
-		gtable[gpio].init = 1;
+		vlv_iosf_sb_write(dev_priv, port, pconf0, 0x2000CC00);
+		map->init = true;
 	}
 
-	val = 0x4 | action;
+	tmp = 0x4 | value;
+	vlv_iosf_sb_write(dev_priv, port, padval, tmp);
+	mutex_unlock(&dev_priv->sb_lock);
+}
+
+static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data)
+{
+	struct drm_device *dev = intel_dsi->base.base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u8 gpio_source, gpio_index;
+	bool value;
+
+	if (dev_priv->vbt.dsi.seq_version >= 3)
+		data++;
+
+	gpio_index = *data++;
+
+	/* gpio source in sequence v2 only */
+	if (dev_priv->vbt.dsi.seq_version == 2)
+		gpio_source = (*data >> 1) & 3;
+	else
+		gpio_source = 0;
 
 	/* pull up/down */
-	vlv_iosf_sb_write(dev_priv, IOSF_PORT_GPIO_NC, pad, val);
-	mutex_unlock(&dev_priv->sb_lock);
+	value = *data++ & 1;
+
+	if (IS_VALLEYVIEW(dev_priv))
+		vlv_exec_gpio(dev_priv, gpio_source, gpio_index, value);
+	else
+		DRM_DEBUG_KMS("GPIO element not supported on this platform\n");
 
-out:
 	return data;
 }
 
@@ -420,7 +431,7 @@ struct drm_panel *vbt_panel_init(struct
 	struct mipi_pps_data *pps = dev_priv->vbt.dsi.pps;
 	struct drm_display_mode *mode = dev_priv->vbt.lfp_lvds_vbt_mode;
 	struct vbt_panel *vbt_panel;
-	u32 bits_per_pixel = 24;
+	u32 bpp;
 	u32 tlpx_ns, extra_byte_count, bitrate, tlpx_ui;
 	u32 ui_num, ui_den;
 	u32 prepare_cnt, exit_zero_cnt, clk_zero_cnt, trail_cnt;
@@ -436,12 +447,13 @@ struct drm_panel *vbt_panel_init(struct
 	intel_dsi->eotp_pkt = mipi_config->eot_pkt_disabled ? 0 : 1;
 	intel_dsi->clock_stop = mipi_config->enable_clk_stop ? 1 : 0;
 	intel_dsi->lane_count = mipi_config->lane_cnt + 1;
-	intel_dsi->pixel_format = mipi_config->videomode_color_format << 7;
+	intel_dsi->pixel_format =
+			pixel_format_from_register_bits(
+				mipi_config->videomode_color_format << 7);
+	bpp = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format);
+
 	intel_dsi->dual_link = mipi_config->dual_link;
 	intel_dsi->pixel_overlap = mipi_config->pixel_overlap;
-
-	bits_per_pixel = dsi_pixel_format_bpp(intel_dsi->pixel_format);
-
 	intel_dsi->operation_mode = mipi_config->is_cmd_mode;
 	intel_dsi->video_mode_format = mipi_config->video_transfer_mode;
 	intel_dsi->escape_clk_div = mipi_config->byte_clk_sel;
@@ -475,8 +487,7 @@ struct drm_panel *vbt_panel_init(struct
 	 */
 	if (intel_dsi->video_mode_format == VIDEO_MODE_BURST) {
 		if (mipi_config->target_burst_mode_freq) {
-			computed_ddr =
-				(pclk * bits_per_pixel) / intel_dsi->lane_count;
+			computed_ddr = (pclk * bpp) / intel_dsi->lane_count;
 
 			if (mipi_config->target_burst_mode_freq <
 								computed_ddr) {
@@ -499,7 +510,7 @@ struct drm_panel *vbt_panel_init(struct
 	intel_dsi->burst_mode_ratio = burst_mode_ratio;
 	intel_dsi->pclk = pclk;
 
-	bitrate = (pclk * bits_per_pixel) / intel_dsi->lane_count;
+	bitrate = (pclk * bpp) / intel_dsi->lane_count;
 
 	switch (intel_dsi->escape_clk_div) {
 	case 0:
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_dsi_pll.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_dsi_pll.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_dsi_pll.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_dsi_pll.c	2016-07-24 15:23:50.000000000 -0400
@@ -30,33 +30,7 @@
 #include "i915_drv.h"
 #include "intel_dsi.h"
 
-int dsi_pixel_format_bpp(int pixel_format)
-{
-	int bpp;
-
-	switch (pixel_format) {
-	default:
-	case VID_MODE_FORMAT_RGB888:
-	case VID_MODE_FORMAT_RGB666_LOOSE:
-		bpp = 24;
-		break;
-	case VID_MODE_FORMAT_RGB666:
-		bpp = 18;
-		break;
-	case VID_MODE_FORMAT_RGB565:
-		bpp = 16;
-		break;
-	}
-
-	return bpp;
-}
-
-struct dsi_mnp {
-	u32 dsi_pll_ctrl;
-	u32 dsi_pll_div;
-};
-
-static const u32 lfsr_converts[] = {
+static const u16 lfsr_converts[] = {
 	426, 469, 234, 373, 442, 221, 110, 311, 411,		/* 62 - 70 */
 	461, 486, 243, 377, 188, 350, 175, 343, 427, 213,	/* 71 - 80 */
 	106, 53, 282, 397, 454, 227, 113, 56, 284, 142,		/* 81 - 90 */
@@ -64,10 +38,11 @@ static const u32 lfsr_converts[] = {
 };
 
 /* Get DSI clock from pixel clock */
-static u32 dsi_clk_from_pclk(u32 pclk, int pixel_format, int lane_count)
+static u32 dsi_clk_from_pclk(u32 pclk, enum mipi_dsi_pixel_format fmt,
+			     int lane_count)
 {
 	u32 dsi_clk_khz;
-	u32 bpp = dsi_pixel_format_bpp(pixel_format);
+	u32 bpp = mipi_dsi_pixel_format_to_bpp(fmt);
 
 	/* DSI data rate = pixel clock * bits per pixel / lane count
 	   pixel clock is converted from KHz to Hz */
@@ -77,7 +52,8 @@ static u32 dsi_clk_from_pclk(u32 pclk, i
 }
 
 static int dsi_calc_mnp(struct drm_i915_private *dev_priv,
-			struct dsi_mnp *dsi_mnp, int target_dsi_clk)
+			struct intel_crtc_state *config,
+			int target_dsi_clk)
 {
 	unsigned int calc_m = 0, calc_p = 0;
 	unsigned int m_min, m_max, p_min = 2, p_max = 6;
@@ -123,8 +99,8 @@ static int dsi_calc_mnp(struct drm_i915_
 	/* register has log2(N1), this works fine for powers of two */
 	n = ffs(n) - 1;
 	m_seed = lfsr_converts[calc_m - 62];
-	dsi_mnp->dsi_pll_ctrl = 1 << (DSI_PLL_P1_POST_DIV_SHIFT + calc_p - 2);
-	dsi_mnp->dsi_pll_div = n << DSI_PLL_N1_DIV_SHIFT |
+	config->dsi_pll.ctrl = 1 << (DSI_PLL_P1_POST_DIV_SHIFT + calc_p - 2);
+	config->dsi_pll.div = n << DSI_PLL_N1_DIV_SHIFT |
 		m_seed << DSI_PLL_M1_DIV_SHIFT;
 
 	return 0;
@@ -134,54 +110,55 @@ static int dsi_calc_mnp(struct drm_i915_
  * XXX: The muxing and gating is hard coded for now. Need to add support for
  * sharing PLLs with two DSI outputs.
  */
-static void vlv_configure_dsi_pll(struct intel_encoder *encoder)
+static int vlv_compute_dsi_pll(struct intel_encoder *encoder,
+			       struct intel_crtc_state *config)
 {
 	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
 	int ret;
-	struct dsi_mnp dsi_mnp;
 	u32 dsi_clk;
 
 	dsi_clk = dsi_clk_from_pclk(intel_dsi->pclk, intel_dsi->pixel_format,
 				    intel_dsi->lane_count);
 
-	ret = dsi_calc_mnp(dev_priv, &dsi_mnp, dsi_clk);
+	ret = dsi_calc_mnp(dev_priv, config, dsi_clk);
 	if (ret) {
 		DRM_DEBUG_KMS("dsi_calc_mnp failed\n");
-		return;
+		return ret;
 	}
 
 	if (intel_dsi->ports & (1 << PORT_A))
-		dsi_mnp.dsi_pll_ctrl |= DSI_PLL_CLK_GATE_DSI0_DSIPLL;
+		config->dsi_pll.ctrl |= DSI_PLL_CLK_GATE_DSI0_DSIPLL;
 
 	if (intel_dsi->ports & (1 << PORT_C))
-		dsi_mnp.dsi_pll_ctrl |= DSI_PLL_CLK_GATE_DSI1_DSIPLL;
+		config->dsi_pll.ctrl |= DSI_PLL_CLK_GATE_DSI1_DSIPLL;
+
+	config->dsi_pll.ctrl |= DSI_PLL_VCO_EN;
 
 	DRM_DEBUG_KMS("dsi pll div %08x, ctrl %08x\n",
-		      dsi_mnp.dsi_pll_div, dsi_mnp.dsi_pll_ctrl);
+		      config->dsi_pll.div, config->dsi_pll.ctrl);
 
-	vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, 0);
-	vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_DIVIDER, dsi_mnp.dsi_pll_div);
-	vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, dsi_mnp.dsi_pll_ctrl);
+	return 0;
 }
 
-static void vlv_enable_dsi_pll(struct intel_encoder *encoder)
+static void vlv_enable_dsi_pll(struct intel_encoder *encoder,
+			       const struct intel_crtc_state *config)
 {
-	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
-	u32 tmp;
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 
 	DRM_DEBUG_KMS("\n");
 
 	mutex_lock(&dev_priv->sb_lock);
 
-	vlv_configure_dsi_pll(encoder);
+	vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, 0);
+	vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_DIVIDER, config->dsi_pll.div);
+	vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL,
+		      config->dsi_pll.ctrl & ~DSI_PLL_VCO_EN);
 
 	/* wait at least 0.5 us after ungating before enabling VCO */
 	usleep_range(1, 10);
 
-	tmp = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL);
-	tmp |= DSI_PLL_VCO_EN;
-	vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, tmp);
+	vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, config->dsi_pll.ctrl);
 
 	if (wait_for(vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL) &
 						DSI_PLL_LOCK, 20)) {
@@ -197,7 +174,7 @@ static void vlv_enable_dsi_pll(struct in
 
 static void vlv_disable_dsi_pll(struct intel_encoder *encoder)
 {
-	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 	u32 tmp;
 
 	DRM_DEBUG_KMS("\n");
@@ -212,9 +189,39 @@ static void vlv_disable_dsi_pll(struct i
 	mutex_unlock(&dev_priv->sb_lock);
 }
 
+static bool bxt_dsi_pll_is_enabled(struct drm_i915_private *dev_priv)
+{
+	bool enabled;
+	u32 val;
+	u32 mask;
+
+	mask = BXT_DSI_PLL_DO_ENABLE | BXT_DSI_PLL_LOCKED;
+	val = I915_READ(BXT_DSI_PLL_ENABLE);
+	enabled = (val & mask) == mask;
+
+	if (!enabled)
+		return false;
+
+	/*
+	 * Both dividers must be programmed with valid values even if only one
+	 * of the PLL is used, see BSpec/Broxton Clocks. Check this here for
+	 * paranoia, since BIOS is known to misconfigure PLLs in this way at
+	 * times, and since accessing DSI registers with invalid dividers
+	 * causes a system hang.
+	 */
+	val = I915_READ(BXT_DSI_PLL_CTL);
+	if (!(val & BXT_DSIA_16X_MASK) || !(val & BXT_DSIC_16X_MASK)) {
+		DRM_DEBUG_DRIVER("PLL is enabled with invalid divider settings (%08x)\n",
+				 val);
+		enabled = false;
+	}
+
+	return enabled;
+}
+
 static void bxt_disable_dsi_pll(struct intel_encoder *encoder)
 {
-	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 	u32 val;
 
 	DRM_DEBUG_KMS("\n");
@@ -232,23 +239,24 @@ static void bxt_disable_dsi_pll(struct i
 		DRM_ERROR("Timeout waiting for PLL lock deassertion\n");
 }
 
-static void assert_bpp_mismatch(int pixel_format, int pipe_bpp)
+static void assert_bpp_mismatch(enum mipi_dsi_pixel_format fmt, int pipe_bpp)
 {
-	int bpp = dsi_pixel_format_bpp(pixel_format);
+	int bpp = mipi_dsi_pixel_format_to_bpp(fmt);
 
 	WARN(bpp != pipe_bpp,
 	     "bpp match assertion failure (expected %d, current %d)\n",
 	     bpp, pipe_bpp);
 }
 
-static u32 vlv_dsi_get_pclk(struct intel_encoder *encoder, int pipe_bpp)
+static u32 vlv_dsi_get_pclk(struct intel_encoder *encoder, int pipe_bpp,
+			    struct intel_crtc_state *config)
 {
-	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
 	u32 dsi_clock, pclk;
 	u32 pll_ctl, pll_div;
 	u32 m = 0, p = 0, n;
-	int refclk = 25000;
+	int refclk = IS_CHERRYVIEW(dev_priv) ? 100000 : 25000;
 	int i;
 
 	DRM_DEBUG_KMS("\n");
@@ -258,6 +266,9 @@ static u32 vlv_dsi_get_pclk(struct intel
 	pll_div = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_DIVIDER);
 	mutex_unlock(&dev_priv->sb_lock);
 
+	config->dsi_pll.ctrl = pll_ctl & ~DSI_PLL_LOCK;
+	config->dsi_pll.div = pll_div;
+
 	/* mask out other bits and extract the P1 divisor */
 	pll_ctl &= DSI_PLL_P1_POST_DIV_MASK;
 	pll_ctl = pll_ctl >> (DSI_PLL_P1_POST_DIV_SHIFT - 2);
@@ -303,7 +314,8 @@ static u32 vlv_dsi_get_pclk(struct intel
 	return pclk;
 }
 
-static u32 bxt_dsi_get_pclk(struct intel_encoder *encoder, int pipe_bpp)
+static u32 bxt_dsi_get_pclk(struct intel_encoder *encoder, int pipe_bpp,
+			    struct intel_crtc_state *config)
 {
 	u32 pclk;
 	u32 dsi_clk;
@@ -317,15 +329,9 @@ static u32 bxt_dsi_get_pclk(struct intel
 		return 0;
 	}
 
-	dsi_ratio = I915_READ(BXT_DSI_PLL_CTL) &
-				BXT_DSI_PLL_RATIO_MASK;
+	config->dsi_pll.ctrl = I915_READ(BXT_DSI_PLL_CTL);
 
-	/* Invalid DSI ratio ? */
-	if (dsi_ratio < BXT_DSI_PLL_RATIO_MIN ||
-			dsi_ratio > BXT_DSI_PLL_RATIO_MAX) {
-		DRM_ERROR("Invalid DSI pll ratio(%u) programmed\n", dsi_ratio);
-		return 0;
-	}
+	dsi_ratio = config->dsi_pll.ctrl & BXT_DSI_PLL_RATIO_MASK;
 
 	dsi_clk = (dsi_ratio * BXT_REF_CLOCK_KHZ) / 2;
 
@@ -338,12 +344,13 @@ static u32 bxt_dsi_get_pclk(struct intel
 	return pclk;
 }
 
-u32 intel_dsi_get_pclk(struct intel_encoder *encoder, int pipe_bpp)
+u32 intel_dsi_get_pclk(struct intel_encoder *encoder, int pipe_bpp,
+		       struct intel_crtc_state *config)
 {
 	if (IS_BROXTON(encoder->base.dev))
-		return bxt_dsi_get_pclk(encoder, pipe_bpp);
+		return bxt_dsi_get_pclk(encoder, pipe_bpp, config);
 	else
-		return vlv_dsi_get_pclk(encoder, pipe_bpp);
+		return vlv_dsi_get_pclk(encoder, pipe_bpp, config);
 }
 
 static void vlv_dsi_reset_clocks(struct intel_encoder *encoder, enum port port)
@@ -360,51 +367,72 @@ static void vlv_dsi_reset_clocks(struct
 }
 
 /* Program BXT Mipi clocks and dividers */
-static void bxt_dsi_program_clocks(struct drm_device *dev, enum port port)
+static void bxt_dsi_program_clocks(struct drm_device *dev, enum port port,
+				   const struct intel_crtc_state *config)
 {
-	u32 tmp;
-	u32 divider;
-	u32 dsi_rate;
-	u32 pll_ratio;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 tmp;
+	u32 dsi_rate = 0;
+	u32 pll_ratio = 0;
+	u32 rx_div;
+	u32 tx_div;
+	u32 rx_div_upper;
+	u32 rx_div_lower;
+	u32 mipi_8by3_divider;
 
 	/* Clear old configurations */
 	tmp = I915_READ(BXT_MIPI_CLOCK_CTL);
 	tmp &= ~(BXT_MIPI_TX_ESCLK_FIXDIV_MASK(port));
-	tmp &= ~(BXT_MIPI_RX_ESCLK_FIXDIV_MASK(port));
-	tmp &= ~(BXT_MIPI_ESCLK_VAR_DIV_MASK(port));
-	tmp &= ~(BXT_MIPI_DPHY_DIVIDER_MASK(port));
+	tmp &= ~(BXT_MIPI_RX_ESCLK_UPPER_FIXDIV_MASK(port));
+	tmp &= ~(BXT_MIPI_8X_BY3_DIVIDER_MASK(port));
+	tmp &= ~(BXT_MIPI_RX_ESCLK_LOWER_FIXDIV_MASK(port));
 
 	/* Get the current DSI rate(actual) */
-	pll_ratio = I915_READ(BXT_DSI_PLL_CTL) &
-				BXT_DSI_PLL_RATIO_MASK;
+	pll_ratio = config->dsi_pll.ctrl & BXT_DSI_PLL_RATIO_MASK;
 	dsi_rate = (BXT_REF_CLOCK_KHZ * pll_ratio) / 2;
 
-	/* Max possible output of clock is 39.5 MHz, program value -1 */
-	divider = (dsi_rate / BXT_MAX_VAR_OUTPUT_KHZ) - 1;
-	tmp |= BXT_MIPI_ESCLK_VAR_DIV(port, divider);
+	/*
+	 * tx clock should be <= 20MHz and the div value must be
+	 * subtracted by 1 as per bspec
+	 */
+	tx_div = DIV_ROUND_UP(dsi_rate, 20000) - 1;
+	/*
+	 * rx clock should be <= 150MHz and the div value must be
+	 * subtracted by 1 as per bspec
+	 */
+	rx_div = DIV_ROUND_UP(dsi_rate, 150000) - 1;
 
 	/*
-	 * Tx escape clock must be as close to 20MHz possible, but should
-	 * not exceed it. Hence select divide by 2
+	 * rx divider value needs to be updated in the
+	 * two differnt bit fields in the register hence splitting the
+	 * rx divider value accordingly
 	 */
-	tmp |= BXT_MIPI_TX_ESCLK_8XDIV_BY2(port);
+	rx_div_lower = rx_div & RX_DIVIDER_BIT_1_2;
+	rx_div_upper = (rx_div & RX_DIVIDER_BIT_3_4) >> 2;
 
-	tmp |= BXT_MIPI_RX_ESCLK_8X_BY3(port);
+	/* As per bpsec program the 8/3X clock divider to the below value */
+	if (dev_priv->vbt.dsi.config->is_cmd_mode)
+		mipi_8by3_divider = 0x2;
+	else
+		mipi_8by3_divider = 0x3;
+
+	tmp |= BXT_MIPI_8X_BY3_DIVIDER(port, mipi_8by3_divider);
+	tmp |= BXT_MIPI_TX_ESCLK_DIVIDER(port, tx_div);
+	tmp |= BXT_MIPI_RX_ESCLK_LOWER_DIVIDER(port, rx_div_lower);
+	tmp |= BXT_MIPI_RX_ESCLK_UPPER_DIVIDER(port, rx_div_upper);
 
 	I915_WRITE(BXT_MIPI_CLOCK_CTL, tmp);
 }
 
-static bool bxt_configure_dsi_pll(struct intel_encoder *encoder)
+static int bxt_compute_dsi_pll(struct intel_encoder *encoder,
+			       struct intel_crtc_state *config)
 {
-	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
 	u8 dsi_ratio;
 	u32 dsi_clk;
-	u32 val;
 
 	dsi_clk = dsi_clk_from_pclk(intel_dsi->pclk, intel_dsi->pixel_format,
-			intel_dsi->lane_count);
+				    intel_dsi->lane_count);
 
 	/*
 	 * From clock diagram, to get PLL ratio divider, divide double of DSI
@@ -413,9 +441,9 @@ static bool bxt_configure_dsi_pll(struct
 	 */
 	dsi_ratio = DIV_ROUND_UP(dsi_clk * 2, BXT_REF_CLOCK_KHZ);
 	if (dsi_ratio < BXT_DSI_PLL_RATIO_MIN ||
-			dsi_ratio > BXT_DSI_PLL_RATIO_MAX) {
+	    dsi_ratio > BXT_DSI_PLL_RATIO_MAX) {
 		DRM_ERROR("Cant get a suitable ratio from DSI PLL ratios\n");
-		return false;
+		return -ECHRNG;
 	}
 
 	/*
@@ -423,27 +451,19 @@ static bool bxt_configure_dsi_pll(struct
 	 * Spec says both have to be programmed, even if one is not getting
 	 * used. Configure MIPI_CLOCK_CTL dividers in modeset
 	 */
-	val = I915_READ(BXT_DSI_PLL_CTL);
-	val &= ~BXT_DSI_PLL_PVD_RATIO_MASK;
-	val &= ~BXT_DSI_FREQ_SEL_MASK;
-	val &= ~BXT_DSI_PLL_RATIO_MASK;
-	val |= (dsi_ratio | BXT_DSIA_16X_BY2 | BXT_DSIC_16X_BY2);
+	config->dsi_pll.ctrl = dsi_ratio | BXT_DSIA_16X_BY2 | BXT_DSIC_16X_BY2;
 
 	/* As per recommendation from hardware team,
 	 * Prog PVD ratio =1 if dsi ratio <= 50
 	 */
-	if (dsi_ratio <= 50) {
-		val &= ~BXT_DSI_PLL_PVD_RATIO_MASK;
-		val |= BXT_DSI_PLL_PVD_RATIO_1;
-	}
-
-	I915_WRITE(BXT_DSI_PLL_CTL, val);
-	POSTING_READ(BXT_DSI_PLL_CTL);
+	if (dsi_ratio <= 50)
+		config->dsi_pll.ctrl |= BXT_DSI_PLL_PVD_RATIO_1;
 
-	return true;
+	return 0;
 }
 
-static void bxt_enable_dsi_pll(struct intel_encoder *encoder)
+static void bxt_enable_dsi_pll(struct intel_encoder *encoder,
+			       const struct intel_crtc_state *config)
 {
 	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
@@ -452,23 +472,13 @@ static void bxt_enable_dsi_pll(struct in
 
 	DRM_DEBUG_KMS("\n");
 
-	val = I915_READ(BXT_DSI_PLL_ENABLE);
-
-	if (val & BXT_DSI_PLL_DO_ENABLE) {
-		WARN(1, "DSI PLL already enabled. Disabling it.\n");
-		val &= ~BXT_DSI_PLL_DO_ENABLE;
-		I915_WRITE(BXT_DSI_PLL_ENABLE, val);
-	}
-
 	/* Configure PLL vales */
-	if (!bxt_configure_dsi_pll(encoder)) {
-		DRM_ERROR("Configure DSI PLL failed, abort PLL enable\n");
-		return;
-	}
+	I915_WRITE(BXT_DSI_PLL_CTL, config->dsi_pll.ctrl);
+	POSTING_READ(BXT_DSI_PLL_CTL);
 
 	/* Program TX, RX, Dphy clocks */
 	for_each_dsi_port(port, intel_dsi->ports)
-		bxt_dsi_program_clocks(encoder->base.dev, port);
+		bxt_dsi_program_clocks(encoder->base.dev, port, config);
 
 	/* Enable DSI PLL */
 	val = I915_READ(BXT_DSI_PLL_ENABLE);
@@ -484,14 +494,38 @@ static void bxt_enable_dsi_pll(struct in
 	DRM_DEBUG_KMS("DSI PLL locked\n");
 }
 
-void intel_enable_dsi_pll(struct intel_encoder *encoder)
+bool intel_dsi_pll_is_enabled(struct drm_i915_private *dev_priv)
+{
+	if (IS_BROXTON(dev_priv))
+		return bxt_dsi_pll_is_enabled(dev_priv);
+
+	MISSING_CASE(INTEL_DEVID(dev_priv));
+
+	return false;
+}
+
+int intel_compute_dsi_pll(struct intel_encoder *encoder,
+			  struct intel_crtc_state *config)
 {
 	struct drm_device *dev = encoder->base.dev;
 
 	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
-		vlv_enable_dsi_pll(encoder);
+		return vlv_compute_dsi_pll(encoder, config);
 	else if (IS_BROXTON(dev))
-		bxt_enable_dsi_pll(encoder);
+		return bxt_compute_dsi_pll(encoder, config);
+
+	return -ENODEV;
+}
+
+void intel_enable_dsi_pll(struct intel_encoder *encoder,
+			  const struct intel_crtc_state *config)
+{
+	struct drm_device *dev = encoder->base.dev;
+
+	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
+		vlv_enable_dsi_pll(encoder, config);
+	else if (IS_BROXTON(dev))
+		bxt_enable_dsi_pll(encoder, config);
 }
 
 void intel_disable_dsi_pll(struct intel_encoder *encoder)
@@ -513,9 +547,9 @@ static void bxt_dsi_reset_clocks(struct
 	/* Clear old configurations */
 	tmp = I915_READ(BXT_MIPI_CLOCK_CTL);
 	tmp &= ~(BXT_MIPI_TX_ESCLK_FIXDIV_MASK(port));
-	tmp &= ~(BXT_MIPI_RX_ESCLK_FIXDIV_MASK(port));
-	tmp &= ~(BXT_MIPI_ESCLK_VAR_DIV_MASK(port));
-	tmp &= ~(BXT_MIPI_DPHY_DIVIDER_MASK(port));
+	tmp &= ~(BXT_MIPI_RX_ESCLK_UPPER_FIXDIV_MASK(port));
+	tmp &= ~(BXT_MIPI_8X_BY3_DIVIDER_MASK(port));
+	tmp &= ~(BXT_MIPI_RX_ESCLK_LOWER_FIXDIV_MASK(port));
 	I915_WRITE(BXT_MIPI_CLOCK_CTL, tmp);
 	I915_WRITE(MIPI_EOT_DISABLE(port), CLOCKSTOP);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_fbc.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_fbc.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_fbc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_fbc.c	2016-07-24 15:23:50.000000000 -0400
@@ -506,6 +506,7 @@ static int find_compression_threshold(st
 				      int size,
 				      int fb_cpp)
 {
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	int compression_threshold = 1;
 	int ret;
 	u64 end;
@@ -516,9 +517,9 @@ static int find_compression_threshold(st
 	 * underruns, even if that range is not reserved by the BIOS. */
 	if (IS_BROADWELL(dev_priv) ||
 	    IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
-		end = dev_priv->gtt.stolen_size - 8 * 1024 * 1024;
+		end = ggtt->stolen_size - 8 * 1024 * 1024;
 	else
-		end = dev_priv->gtt.stolen_usable_size;
+		end = ggtt->stolen_usable_size;
 
 	/* HACK: This code depends on what we will do in *_enable_fbc. If that
 	 * code changes, this code needs to change as well.
@@ -823,8 +824,7 @@ static bool intel_fbc_can_choose(struct
 {
 	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
 	struct intel_fbc *fbc = &dev_priv->fbc;
-	bool enable_by_default = IS_HASWELL(dev_priv) ||
-				 IS_BROADWELL(dev_priv);
+	bool enable_by_default = IS_BROADWELL(dev_priv);
 
 	if (intel_vgpu_active(dev_priv->dev)) {
 		fbc->no_fbc_reason = "VGPU is active";
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_fbdev.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_fbdev.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_fbdev.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_fbdev.c	2016-07-24 15:23:50.000000000 -0400
@@ -122,6 +122,7 @@ static int intelfb_alloc(struct drm_fb_h
 	struct drm_framebuffer *fb;
 	struct drm_device *dev = helper->dev;
 	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	struct drm_mode_fb_cmd2 mode_cmd = {};
 	struct drm_i915_gem_object *obj = NULL;
 	int size, ret;
@@ -146,7 +147,7 @@ static int intelfb_alloc(struct drm_fb_h
 	/* If the FB is too big, just don't use it since fbdev is not very
 	 * important and we should probably use that space with FBC or other
 	 * features. */
-	if (size * 2 < dev_priv->gtt.stolen_usable_size)
+	if (size * 2 < ggtt->stolen_usable_size)
 		obj = i915_gem_object_create_stolen(dev, size);
 	if (obj == NULL)
 		obj = i915_gem_alloc_object(dev, size);
@@ -181,7 +182,8 @@ static int intelfb_create(struct drm_fb_
 		container_of(helper, struct intel_fbdev, helper);
 	struct intel_framebuffer *intel_fb = ifbdev->fb;
 	struct drm_device *dev = helper->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	struct fb_info *info;
 	struct drm_framebuffer *fb;
 	struct drm_i915_gem_object *obj;
@@ -220,7 +222,7 @@ static int intelfb_create(struct drm_fb_
 	 * This also validates that any existing fb inherited from the
 	 * BIOS is suitable for own access.
 	 */
-	ret = intel_pin_and_fence_fb_obj(NULL, &ifbdev->fb->base, NULL);
+	ret = intel_pin_and_fence_fb_obj(&ifbdev->fb->base, BIT(DRM_ROTATE_0));
 	if (ret)
 		goto out_unlock;
 
@@ -244,13 +246,13 @@ static int intelfb_create(struct drm_fb_
 
 	/* setup aperture base/size for vesafb takeover */
 	info->apertures->ranges[0].base = dev->mode_config.fb_base;
-	info->apertures->ranges[0].size = dev_priv->gtt.mappable_end;
+	info->apertures->ranges[0].size = ggtt->mappable_end;
 
 	info->fix.smem_start = dev->mode_config.fb_base + i915_gem_obj_ggtt_offset(obj);
 	info->fix.smem_len = size;
 
 	info->screen_base =
-		ioremap_wc(dev_priv->gtt.mappable_base + i915_gem_obj_ggtt_offset(obj),
+		ioremap_wc(ggtt->mappable_base + i915_gem_obj_ggtt_offset(obj),
 			   size);
 	if (!info->screen_base) {
 		DRM_ERROR("Failed to remap framebuffer into virtual memory\n");
@@ -366,12 +368,12 @@ static bool intel_fb_initial_config(stru
 	uint64_t conn_configured = 0, mask;
 	int pass = 0;
 
-	save_enabled = kcalloc(dev->mode_config.num_connector, sizeof(bool),
+	save_enabled = kcalloc(fb_helper->connector_count, sizeof(bool),
 			       GFP_KERNEL);
 	if (!save_enabled)
 		return false;
 
-	memcpy(save_enabled, enabled, dev->mode_config.num_connector);
+	memcpy(save_enabled, enabled, fb_helper->connector_count);
 	mask = (1 << fb_helper->connector_count) - 1;
 retry:
 	for (i = 0; i < fb_helper->connector_count; i++) {
@@ -379,6 +381,7 @@ retry:
 		struct drm_connector *connector;
 		struct drm_encoder *encoder;
 		struct drm_fb_helper_crtc *new_crtc;
+		struct intel_crtc *intel_crtc;
 
 		fb_conn = fb_helper->connector_info[i];
 		connector = fb_conn->connector;
@@ -420,6 +423,13 @@ retry:
 
 		num_connectors_enabled++;
 
+		intel_crtc = to_intel_crtc(connector->state->crtc);
+		for (j = 0; j < 256; j++) {
+			intel_crtc->lut_r[j] = j;
+			intel_crtc->lut_g[j] = j;
+			intel_crtc->lut_b[j] = j;
+		}
+
 		new_crtc = intel_fb_helper_crtc(fb_helper, connector->state->crtc);
 
 		/*
@@ -510,7 +520,7 @@ retry:
 	if (fallback) {
 bail:
 		DRM_DEBUG_KMS("Not using firmware configuration\n");
-		memcpy(enabled, save_enabled, dev->mode_config.num_connector);
+		memcpy(enabled, save_enabled, fb_helper->connector_count);
 		kfree(save_enabled);
 		return false;
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_fifo_underrun.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_fifo_underrun.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_fifo_underrun.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_fifo_underrun.c	2016-07-24 15:23:50.000000000 -0400
@@ -212,7 +212,7 @@ static void cpt_check_pch_fifo_underruns
 	I915_WRITE(SERR_INT, SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder));
 	POSTING_READ(SERR_INT);
 
-	DRM_ERROR("pch fifo underrun on pch transcoder %c\n",
+	DRM_ERROR("pch fifo underrun on pch transcoder %s\n",
 		  transcoder_name(pch_transcoder));
 }
 
@@ -235,7 +235,7 @@ static void cpt_set_fifo_underrun_report
 
 		if (old && I915_READ(SERR_INT) &
 		    SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder)) {
-			DRM_ERROR("uncleared pch fifo underrun on pch transcoder %c\n",
+			DRM_ERROR("uncleared pch fifo underrun on pch transcoder %s\n",
 				  transcoder_name(pch_transcoder));
 		}
 	}
@@ -333,7 +333,7 @@ bool intel_set_pch_fifo_underrun_reporti
 	old = !intel_crtc->pch_fifo_underrun_disabled;
 	intel_crtc->pch_fifo_underrun_disabled = !enable;
 
-	if (HAS_PCH_IBX(dev_priv->dev))
+	if (HAS_PCH_IBX(dev_priv))
 		ibx_set_fifo_underrun_reporting(dev_priv->dev, pch_transcoder,
 						enable);
 	else
@@ -363,7 +363,7 @@ void intel_cpu_fifo_underrun_irq_handler
 		return;
 
 	/* GMCH can't disable fifo underruns, filter them. */
-	if (HAS_GMCH_DISPLAY(dev_priv->dev) &&
+	if (HAS_GMCH_DISPLAY(dev_priv) &&
 	    to_intel_crtc(crtc)->cpu_fifo_underrun_disabled)
 		return;
 
@@ -386,7 +386,7 @@ void intel_pch_fifo_underrun_irq_handler
 {
 	if (intel_set_pch_fifo_underrun_reporting(dev_priv, pch_transcoder,
 						  false))
-		DRM_ERROR("PCH transcoder %c FIFO underrun\n",
+		DRM_ERROR("PCH transcoder %s FIFO underrun\n",
 			  transcoder_name(pch_transcoder));
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_guc.h linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_guc.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_guc.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_guc.h	2016-07-24 15:23:50.000000000 -0400
@@ -27,8 +27,34 @@
 #include "intel_guc_fwif.h"
 #include "i915_guc_reg.h"
 
+struct drm_i915_gem_request;
+
+/*
+ * This structure primarily describes the GEM object shared with the GuC.
+ * The GEM object is held for the entire lifetime of our interaction with
+ * the GuC, being allocated before the GuC is loaded with its firmware.
+ * Because there's no way to update the address used by the GuC after
+ * initialisation, the shared object must stay pinned into the GGTT as
+ * long as the GuC is in use. We also keep the first page (only) mapped
+ * into kernel address space, as it includes shared data that must be
+ * updated on every request submission.
+ *
+ * The single GEM object described here is actually made up of several
+ * separate areas, as far as the GuC is concerned. The first page (kept
+ * kmap'd) includes the "process decriptor" which holds sequence data for
+ * the doorbell, and one cacheline which actually *is* the doorbell; a
+ * write to this will "ring the doorbell" (i.e. send an interrupt to the
+ * GuC). The subsequent  pages of the client object constitute the work
+ * queue (a circular array of work items), again described in the process
+ * descriptor. Work queue pages are mapped momentarily as required.
+ *
+ * Finally, we also keep a few statistics here, including the number of
+ * submissions to each engine, and a record of the last submission failure
+ * (if any).
+ */
 struct i915_guc_client {
 	struct drm_i915_gem_object *client_obj;
+	void *client_base;		/* first page (only) of above	*/
 	struct intel_context *owner;
 	struct intel_guc *guc;
 	uint32_t priority;
@@ -43,13 +69,14 @@ struct i915_guc_client {
 	uint32_t wq_offset;
 	uint32_t wq_size;
 	uint32_t wq_tail;
-	uint32_t wq_head;
+	uint32_t unused;		/* Was 'wq_head'		*/
 
 	/* GuC submission statistics & status */
 	uint64_t submissions[GUC_MAX_ENGINES_NUM];
 	uint32_t q_fail;
 	uint32_t b_fail;
 	int retcode;
+	int spare;			/* pad to 32 DWords		*/
 };
 
 enum intel_guc_fw_status {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_guc_loader.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_guc_loader.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_guc_loader.c	2016-05-15 19:21:32.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_guc_loader.c	2016-07-24 18:18:06.000000000 -0400
@@ -81,14 +81,14 @@ const char *intel_guc_fw_status_repr(enu
 
 static void direct_interrupts_to_host(struct drm_i915_private *dev_priv)
 {
-	struct intel_engine_cs *ring;
-	int i, irqs;
+	struct intel_engine_cs *engine;
+	int irqs;
 
 	/* tell all command streamers NOT to forward interrupts and vblank to GuC */
 	irqs = _MASKED_FIELD(GFX_FORWARD_VBLANK_MASK, GFX_FORWARD_VBLANK_NEVER);
 	irqs |= _MASKED_BIT_DISABLE(GFX_INTERRUPT_STEERING);
-	for_each_ring(ring, dev_priv, i)
-		I915_WRITE(RING_MODE_GEN7(ring), irqs);
+	for_each_engine(engine, dev_priv)
+		I915_WRITE(RING_MODE_GEN7(engine), irqs);
 
 	/* route all GT interrupts to the host */
 	I915_WRITE(GUC_BCS_RCS_IER, 0);
@@ -98,14 +98,14 @@ static void direct_interrupts_to_host(st
 
 static void direct_interrupts_to_guc(struct drm_i915_private *dev_priv)
 {
-	struct intel_engine_cs *ring;
-	int i, irqs;
+	struct intel_engine_cs *engine;
+	int irqs;
 
 	/* tell all command streamers to forward interrupts and vblank to GuC */
 	irqs = _MASKED_FIELD(GFX_FORWARD_VBLANK_MASK, GFX_FORWARD_VBLANK_ALWAYS);
 	irqs |= _MASKED_BIT_ENABLE(GFX_INTERRUPT_STEERING);
-	for_each_ring(ring, dev_priv, i)
-		I915_WRITE(RING_MODE_GEN7(ring), irqs);
+	for_each_engine(engine, dev_priv)
+		I915_WRITE(RING_MODE_GEN7(engine), irqs);
 
 	/* route USER_INTERRUPT to Host, all others are sent to GuC. */
 	irqs = GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT |
@@ -353,6 +353,24 @@ static int guc_ucode_xfer(struct drm_i91
 	return ret;
 }
 
+static int i915_reset_guc(struct drm_i915_private *dev_priv)
+{
+	int ret;
+	u32 guc_status;
+
+	ret = intel_guc_reset(dev_priv);
+	if (ret) {
+		DRM_ERROR("GuC reset failed, ret = %d\n", ret);
+		return ret;
+	}
+
+	guc_status = I915_READ(GUC_STATUS);
+	WARN(!(guc_status & GS_MIA_IN_RESET),
+	     "GuC status: 0x%x, MIA core expected to be in reset\n", guc_status);
+
+	return ret;
+}
+
 /**
  * intel_guc_ucode_load() - load GuC uCode into the device
  * @dev:	drm device
@@ -369,7 +387,7 @@ int intel_guc_ucode_load(struct drm_devi
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
-	int err = 0;
+	int retries, err = 0;
 
 	if (!i915.enable_guc_submission)
 		return 0;
@@ -417,9 +435,33 @@ int intel_guc_ucode_load(struct drm_devi
 	if (err)
 		goto fail;
 
-	err = guc_ucode_xfer(dev_priv);
-	if (err)
-		goto fail;
+	/*
+	 * WaEnableuKernelHeaderValidFix:skl,bxt
+	 * For BXT, this is only upto B0 but below WA is required for later
+	 * steppings also so this is extended as well.
+	 */
+	/* WaEnableGuCBootHashCheckNotSet:skl,bxt */
+	for (retries = 3; ; ) {
+		/*
+		 * Always reset the GuC just before (re)loading, so
+		 * that the state and timing are fairly predictable
+		 */
+		err = i915_reset_guc(dev_priv);
+		if (err) {
+			DRM_ERROR("GuC reset failed, err %d\n", err);
+			goto fail;
+		}
+
+		err = guc_ucode_xfer(dev_priv);
+		if (!err)
+			break;
+
+		if (--retries == 0)
+			goto fail;
+
+		DRM_INFO("GuC fw load failed, err %d; will reset and "
+			"retry %d more time(s)\n", err, retries);
+	}
 
 	guc_fw->guc_fw_load_status = GUC_FIRMWARE_SUCCESS;
 
@@ -440,6 +482,7 @@ int intel_guc_ucode_load(struct drm_devi
 	return 0;
 
 fail:
+	DRM_ERROR("GuC firmware load failed, err %d\n", err);
 	if (guc_fw->guc_fw_load_status == GUC_FIRMWARE_PENDING)
 		guc_fw->guc_fw_load_status = GUC_FIRMWARE_FAIL;
 
@@ -595,8 +638,8 @@ void intel_guc_ucode_init(struct drm_dev
 		fw_path = NULL;
 	} else if (IS_SKYLAKE(dev)) {
 		fw_path = I915_SKL_GUC_UCODE;
-		guc_fw->guc_fw_major_wanted = 4;
-		guc_fw->guc_fw_minor_wanted = 3;
+		guc_fw->guc_fw_major_wanted = 6;
+		guc_fw->guc_fw_minor_wanted = 1;
 	} else {
 		i915.enable_guc_submission = false;
 		fw_path = "";	/* unknown device */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_hdmi.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_hdmi.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_hdmi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_hdmi.c	2016-07-24 15:23:50.000000000 -0400
@@ -638,7 +638,7 @@ static bool intel_hdmi_set_gcp_infoframe
 		reg = HSW_TVIDEO_DIP_GCP(crtc->config->cpu_transcoder);
 	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
 		reg = VLV_TVIDEO_DIP_GCP(crtc->pipe);
-	else if (HAS_PCH_SPLIT(dev_priv->dev))
+	else if (HAS_PCH_SPLIT(dev_priv))
 		reg = TVIDEO_DIP_GCP(crtc->pipe);
 	else
 		return false;
@@ -836,6 +836,22 @@ static void hsw_set_infoframes(struct dr
 	intel_hdmi_set_hdmi_infoframe(encoder, adjusted_mode);
 }
 
+void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable)
+{
+	struct drm_i915_private *dev_priv = to_i915(intel_hdmi_to_dev(hdmi));
+	struct i2c_adapter *adapter =
+		intel_gmbus_get_adapter(dev_priv, hdmi->ddc_bus);
+
+	if (hdmi->dp_dual_mode.type < DRM_DP_DUAL_MODE_TYPE2_DVI)
+		return;
+
+	DRM_DEBUG_KMS("%s DP dual mode adaptor TMDS output\n",
+		      enable ? "Enabling" : "Disabling");
+
+	drm_dp_dual_mode_set_tmds_output(hdmi->dp_dual_mode.type,
+					 adapter, enable);
+}
+
 static void intel_hdmi_prepare(struct intel_encoder *encoder)
 {
 	struct drm_device *dev = encoder->base.dev;
@@ -845,6 +861,8 @@ static void intel_hdmi_prepare(struct in
 	const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
 	u32 hdmi_val;
 
+	intel_dp_dual_mode_set_tmds_output(intel_hdmi, true);
+
 	hdmi_val = SDVO_ENCODING_HDMI;
 	if (!HAS_PCH_SPLIT(dev) && crtc->config->limited_color_range)
 		hdmi_val |= HDMI_COLOR_RANGE_16_235;
@@ -952,10 +970,9 @@ static void intel_hdmi_get_config(struct
 	if (pipe_config->pixel_multiplier)
 		dotclock /= pipe_config->pixel_multiplier;
 
-	if (HAS_PCH_SPLIT(dev_priv->dev))
-		ironlake_check_encoder_dotclock(pipe_config, dotclock);
-
 	pipe_config->base.adjusted_mode.crtc_clock = dotclock;
+
+	pipe_config->lane_count = 4;
 }
 
 static void intel_enable_hdmi_audio(struct intel_encoder *encoder)
@@ -1143,6 +1160,8 @@ static void intel_disable_hdmi(struct in
 	}
 
 	intel_hdmi->set_infoframes(&encoder->base, false, NULL);
+
+	intel_dp_dual_mode_set_tmds_output(intel_hdmi, false);
 }
 
 static void g4x_disable_hdmi(struct intel_encoder *encoder)
@@ -1168,27 +1187,42 @@ static void pch_post_disable_hdmi(struct
 	intel_disable_hdmi(encoder);
 }
 
-static int hdmi_port_clock_limit(struct intel_hdmi *hdmi, bool respect_dvi_limit)
+static int intel_hdmi_source_max_tmds_clock(struct drm_i915_private *dev_priv)
 {
-	struct drm_device *dev = intel_hdmi_to_dev(hdmi);
-
-	if ((respect_dvi_limit && !hdmi->has_hdmi_sink) || IS_G4X(dev))
+	if (IS_G4X(dev_priv))
 		return 165000;
-	else if (IS_HASWELL(dev) || INTEL_INFO(dev)->gen >= 8)
+	else if (IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 8)
 		return 300000;
 	else
 		return 225000;
 }
 
+static int hdmi_port_clock_limit(struct intel_hdmi *hdmi,
+				 bool respect_downstream_limits)
+{
+	struct drm_device *dev = intel_hdmi_to_dev(hdmi);
+	int max_tmds_clock = intel_hdmi_source_max_tmds_clock(to_i915(dev));
+
+	if (respect_downstream_limits) {
+		if (hdmi->dp_dual_mode.max_tmds_clock)
+			max_tmds_clock = min(max_tmds_clock,
+					     hdmi->dp_dual_mode.max_tmds_clock);
+		if (!hdmi->has_hdmi_sink)
+			max_tmds_clock = min(max_tmds_clock, 165000);
+	}
+
+	return max_tmds_clock;
+}
+
 static enum drm_mode_status
 hdmi_port_clock_valid(struct intel_hdmi *hdmi,
-		      int clock, bool respect_dvi_limit)
+		      int clock, bool respect_downstream_limits)
 {
 	struct drm_device *dev = intel_hdmi_to_dev(hdmi);
 
 	if (clock < 25000)
 		return MODE_CLOCK_LOW;
-	if (clock > hdmi_port_clock_limit(hdmi, respect_dvi_limit))
+	if (clock > hdmi_port_clock_limit(hdmi, respect_downstream_limits))
 		return MODE_CLOCK_HIGH;
 
 	/* BXT DPLL can't generate 223-240 MHz */
@@ -1312,7 +1346,7 @@ bool intel_hdmi_compute_config(struct in
 	 * within limits.
 	 */
 	if (pipe_config->pipe_bpp > 8*3 && pipe_config->has_hdmi_sink &&
-	    hdmi_port_clock_valid(intel_hdmi, clock_12bpc, false) == MODE_OK &&
+	    hdmi_port_clock_valid(intel_hdmi, clock_12bpc, true) == MODE_OK &&
 	    hdmi_12bpc_possible(pipe_config)) {
 		DRM_DEBUG_KMS("picking bpc to 12 for HDMI output\n");
 		desired_bpp = 12*3;
@@ -1340,6 +1374,8 @@ bool intel_hdmi_compute_config(struct in
 	/* Set user selected PAR to incoming mode's member */
 	adjusted_mode->picture_aspect_ratio = intel_hdmi->aspect_ratio;
 
+	pipe_config->lane_count = 4;
+
 	return true;
 }
 
@@ -1352,10 +1388,57 @@ intel_hdmi_unset_edid(struct drm_connect
 	intel_hdmi->has_audio = false;
 	intel_hdmi->rgb_quant_range_selectable = false;
 
+	intel_hdmi->dp_dual_mode.type = DRM_DP_DUAL_MODE_NONE;
+	intel_hdmi->dp_dual_mode.max_tmds_clock = 0;
+
 	kfree(to_intel_connector(connector)->detect_edid);
 	to_intel_connector(connector)->detect_edid = NULL;
 }
 
+static void
+intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector, bool has_edid)
+{
+	struct drm_i915_private *dev_priv = to_i915(connector->dev);
+	struct intel_hdmi *hdmi = intel_attached_hdmi(connector);
+	enum port port = hdmi_to_dig_port(hdmi)->port;
+	struct i2c_adapter *adapter =
+		intel_gmbus_get_adapter(dev_priv, hdmi->ddc_bus);
+	enum drm_dp_dual_mode_type type = drm_dp_dual_mode_detect(adapter);
+
+	/*
+	 * Type 1 DVI adaptors are not required to implement any
+	 * registers, so we can't always detect their presence.
+	 * Ideally we should be able to check the state of the
+	 * CONFIG1 pin, but no such luck on our hardware.
+	 *
+	 * The only method left to us is to check the VBT to see
+	 * if the port is a dual mode capable DP port. But let's
+	 * only do that when we sucesfully read the EDID, to avoid
+	 * confusing log messages about DP dual mode adaptors when
+	 * there's nothing connected to the port.
+	 */
+	if (type == DRM_DP_DUAL_MODE_UNKNOWN) {
+		if (has_edid &&
+		    intel_bios_is_port_dp_dual_mode(dev_priv, port)) {
+			DRM_DEBUG_KMS("Assuming DP dual mode adaptor presence based on VBT\n");
+			type = DRM_DP_DUAL_MODE_TYPE1_DVI;
+		} else {
+			type = DRM_DP_DUAL_MODE_NONE;
+		}
+	}
+
+	if (type == DRM_DP_DUAL_MODE_NONE)
+		return;
+
+	hdmi->dp_dual_mode.type = type;
+	hdmi->dp_dual_mode.max_tmds_clock =
+		drm_dp_dual_mode_max_tmds_clock(type, adapter);
+
+	DRM_DEBUG_KMS("DP dual mode adaptor (%s) detected (max TMDS clock: %d kHz)\n",
+		      drm_dp_get_dual_mode_type_name(type),
+		      hdmi->dp_dual_mode.max_tmds_clock);
+}
+
 static bool
 intel_hdmi_set_edid(struct drm_connector *connector, bool force)
 {
@@ -1371,6 +1454,8 @@ intel_hdmi_set_edid(struct drm_connector
 				    intel_gmbus_get_adapter(dev_priv,
 				    intel_hdmi->ddc_bus));
 
+		intel_hdmi_dp_dual_mode_detect(connector, edid != NULL);
+
 		intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
 	}
 
@@ -2057,6 +2142,9 @@ void intel_hdmi_init_connector(struct in
 	enum port port = intel_dig_port->port;
 	uint8_t alternate_ddc_pin;
 
+	DRM_DEBUG_KMS("Adding HDMI connector on port %c\n",
+		      port_name(port));
+
 	if (WARN(intel_dig_port->max_lanes < 4,
 		 "Not enough lanes (%d) for HDMI on port %c\n",
 		 intel_dig_port->max_lanes, port_name(port)))
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_i2c.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_i2c.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_i2c.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_i2c.c	2016-07-24 15:23:50.000000000 -0400
@@ -124,7 +124,7 @@ static void intel_i2c_quirk_set(struct d
 	u32 val;
 
 	/* When using bit bashing for I2C, this bit needs to be set to 1 */
-	if (!IS_PINEVIEW(dev_priv->dev))
+	if (!IS_PINEVIEW(dev_priv))
 		return;
 
 	val = I915_READ(DSPCLK_GATE_D);
@@ -264,7 +264,7 @@ gmbus_wait_hw_status(struct drm_i915_pri
 	u32 gmbus2 = 0;
 	DEFINE_WAIT(wait);
 
-	if (!HAS_GMBUS_IRQ(dev_priv->dev))
+	if (!HAS_GMBUS_IRQ(dev_priv))
 		gmbus4_irq_en = 0;
 
 	/* Important: The hw handles only the first bit, so set only one! Since
@@ -300,7 +300,7 @@ gmbus_wait_idle(struct drm_i915_private
 
 #define C ((I915_READ_NOTRACE(GMBUS2) & GMBUS_ACTIVE) == 0)
 
-	if (!HAS_GMBUS_IRQ(dev_priv->dev))
+	if (!HAS_GMBUS_IRQ(dev_priv))
 		return wait_for(C, 10);
 
 	/* Important: The hw handles only the first bit, so set only one! */
@@ -571,15 +571,14 @@ clear_err:
 	goto out;
 
 timeout:
-	DRM_INFO("GMBUS [%s] timed out, falling back to bit banging on pin %d\n",
-		 bus->adapter.name, bus->reg0 & 0xff);
+	DRM_DEBUG_KMS("GMBUS [%s] timed out, falling back to bit banging on pin %d\n",
+		      bus->adapter.name, bus->reg0 & 0xff);
 	I915_WRITE(GMBUS0, 0);
 
 	/*
 	 * Hardware may not support GMBUS over these pins? Try GPIO bitbanging
 	 * instead. Use EAGAIN to have i2c core retry.
 	 */
-	bus->force_bit = 1;
 	ret = -EAGAIN;
 
 out:
@@ -597,10 +596,15 @@ gmbus_xfer(struct i2c_adapter *adapter,
 	intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
 	mutex_lock(&dev_priv->gmbus_mutex);
 
-	if (bus->force_bit)
+	if (bus->force_bit) {
 		ret = i2c_bit_algo.master_xfer(adapter, msgs, num);
-	else
+		if (ret < 0)
+			bus->force_bit &= ~GMBUS_FORCE_BIT_RETRY;
+	} else {
 		ret = do_gmbus_xfer(adapter, msgs, num);
+		if (ret == -EAGAIN)
+			bus->force_bit |= GMBUS_FORCE_BIT_RETRY;
+	}
 
 	mutex_unlock(&dev_priv->gmbus_mutex);
 	intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
@@ -718,11 +722,16 @@ void intel_gmbus_set_speed(struct i2c_ad
 void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit)
 {
 	struct intel_gmbus *bus = to_intel_gmbus(adapter);
+	struct drm_i915_private *dev_priv = bus->dev_priv;
+
+	mutex_lock(&dev_priv->gmbus_mutex);
 
 	bus->force_bit += force_bit ? 1 : -1;
 	DRM_DEBUG_KMS("%sabling bit-banging on %s. force bit now %d\n",
 		      force_bit ? "en" : "dis", adapter->name,
 		      bus->force_bit);
+
+	mutex_unlock(&dev_priv->gmbus_mutex);
 }
 
 void intel_teardown_gmbus(struct drm_device *dev)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_lrc.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_lrc.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_lrc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_lrc.c	2016-07-24 15:23:50.000000000 -0400
@@ -131,6 +131,7 @@
  * preemption, but just sampling the new tail pointer).
  *
  */
+#include <linux/interrupt.h>
 
 #include <drm/drmP.h>
 #include <drm/i915_drm.h>
@@ -228,9 +229,6 @@ enum {
 
 static int intel_lr_context_pin(struct intel_context *ctx,
 				struct intel_engine_cs *engine);
-static void lrc_setup_hardware_status_page(struct intel_engine_cs *ring,
-		struct drm_i915_gem_object *default_ctx_obj);
-
 
 /**
  * intel_sanitize_enable_execlists() - sanitize i915.enable_execlists
@@ -266,20 +264,23 @@ int intel_sanitize_enable_execlists(stru
 }
 
 static void
-logical_ring_init_platform_invariants(struct intel_engine_cs *ring)
+logical_ring_init_platform_invariants(struct intel_engine_cs *engine)
 {
-	struct drm_device *dev = ring->dev;
+	struct drm_device *dev = engine->dev;
 
-	ring->disable_lite_restore_wa = (IS_SKL_REVID(dev, 0, SKL_REVID_B0) ||
+	if (IS_GEN8(dev) || IS_GEN9(dev))
+		engine->idle_lite_restore_wa = ~0;
+
+	engine->disable_lite_restore_wa = (IS_SKL_REVID(dev, 0, SKL_REVID_B0) ||
 					IS_BXT_REVID(dev, 0, BXT_REVID_A1)) &&
-					(ring->id == VCS || ring->id == VCS2);
+					(engine->id == VCS || engine->id == VCS2);
 
-	ring->ctx_desc_template = GEN8_CTX_VALID;
-	ring->ctx_desc_template |= GEN8_CTX_ADDRESSING_MODE(dev) <<
+	engine->ctx_desc_template = GEN8_CTX_VALID;
+	engine->ctx_desc_template |= GEN8_CTX_ADDRESSING_MODE(dev) <<
 				   GEN8_CTX_ADDRESSING_MODE_SHIFT;
 	if (IS_GEN8(dev))
-		ring->ctx_desc_template |= GEN8_CTX_L3LLC_COHERENT;
-	ring->ctx_desc_template |= GEN8_CTX_PRIVILEGE;
+		engine->ctx_desc_template |= GEN8_CTX_L3LLC_COHERENT;
+	engine->ctx_desc_template |= GEN8_CTX_PRIVILEGE;
 
 	/* TODO: WaDisableLiteRestore when we start using semaphore
 	 * signalling between Command Streamers */
@@ -287,8 +288,8 @@ logical_ring_init_platform_invariants(st
 
 	/* WaEnableForceRestoreInCtxtDescForVCS:skl */
 	/* WaEnableForceRestoreInCtxtDescForVCS:bxt */
-	if (ring->disable_lite_restore_wa)
-		ring->ctx_desc_template |= GEN8_CTX_FORCE_RESTORE;
+	if (engine->disable_lite_restore_wa)
+		engine->ctx_desc_template |= GEN8_CTX_FORCE_RESTORE;
 }
 
 /**
@@ -311,24 +312,24 @@ logical_ring_init_platform_invariants(st
  */
 static void
 intel_lr_context_descriptor_update(struct intel_context *ctx,
-				   struct intel_engine_cs *ring)
+				   struct intel_engine_cs *engine)
 {
 	uint64_t lrca, desc;
 
-	lrca = ctx->engine[ring->id].lrc_vma->node.start +
+	lrca = ctx->engine[engine->id].lrc_vma->node.start +
 	       LRC_PPHWSP_PN * PAGE_SIZE;
 
-	desc = ring->ctx_desc_template;			   /* bits  0-11 */
+	desc = engine->ctx_desc_template;			   /* bits  0-11 */
 	desc |= lrca;					   /* bits 12-31 */
 	desc |= (lrca >> PAGE_SHIFT) << GEN8_CTX_ID_SHIFT; /* bits 32-51 */
 
-	ctx->engine[ring->id].lrc_desc = desc;
+	ctx->engine[engine->id].lrc_desc = desc;
 }
 
 uint64_t intel_lr_context_descriptor(struct intel_context *ctx,
-				     struct intel_engine_cs *ring)
+				     struct intel_engine_cs *engine)
 {
-	return ctx->engine[ring->id].lrc_desc;
+	return ctx->engine[engine->id].lrc_desc;
 }
 
 /**
@@ -348,98 +349,103 @@ uint64_t intel_lr_context_descriptor(str
  * Return: 20-bits globally unique context ID.
  */
 u32 intel_execlists_ctx_id(struct intel_context *ctx,
-			   struct intel_engine_cs *ring)
+			   struct intel_engine_cs *engine)
 {
-	return intel_lr_context_descriptor(ctx, ring) >> GEN8_CTX_ID_SHIFT;
+	return intel_lr_context_descriptor(ctx, engine) >> GEN8_CTX_ID_SHIFT;
 }
 
 static void execlists_elsp_write(struct drm_i915_gem_request *rq0,
 				 struct drm_i915_gem_request *rq1)
 {
 
-	struct intel_engine_cs *ring = rq0->ring;
-	struct drm_device *dev = ring->dev;
+	struct intel_engine_cs *engine = rq0->engine;
+	struct drm_device *dev = engine->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	uint64_t desc[2];
 
 	if (rq1) {
-		desc[1] = intel_lr_context_descriptor(rq1->ctx, rq1->ring);
+		desc[1] = intel_lr_context_descriptor(rq1->ctx, rq1->engine);
 		rq1->elsp_submitted++;
 	} else {
 		desc[1] = 0;
 	}
 
-	desc[0] = intel_lr_context_descriptor(rq0->ctx, rq0->ring);
+	desc[0] = intel_lr_context_descriptor(rq0->ctx, rq0->engine);
 	rq0->elsp_submitted++;
 
 	/* You must always write both descriptors in the order below. */
-	spin_lock(&dev_priv->uncore.lock);
-	intel_uncore_forcewake_get__locked(dev_priv, FORCEWAKE_ALL);
-	I915_WRITE_FW(RING_ELSP(ring), upper_32_bits(desc[1]));
-	I915_WRITE_FW(RING_ELSP(ring), lower_32_bits(desc[1]));
+	I915_WRITE_FW(RING_ELSP(engine), upper_32_bits(desc[1]));
+	I915_WRITE_FW(RING_ELSP(engine), lower_32_bits(desc[1]));
 
-	I915_WRITE_FW(RING_ELSP(ring), upper_32_bits(desc[0]));
+	I915_WRITE_FW(RING_ELSP(engine), upper_32_bits(desc[0]));
 	/* The context is automatically loaded after the following */
-	I915_WRITE_FW(RING_ELSP(ring), lower_32_bits(desc[0]));
+	I915_WRITE_FW(RING_ELSP(engine), lower_32_bits(desc[0]));
 
 	/* ELSP is a wo register, use another nearby reg for posting */
-	POSTING_READ_FW(RING_EXECLIST_STATUS_LO(ring));
-	intel_uncore_forcewake_put__locked(dev_priv, FORCEWAKE_ALL);
-	spin_unlock(&dev_priv->uncore.lock);
+	POSTING_READ_FW(RING_EXECLIST_STATUS_LO(engine));
 }
 
-static int execlists_update_context(struct drm_i915_gem_request *rq)
+static void
+execlists_update_context_pdps(struct i915_hw_ppgtt *ppgtt, u32 *reg_state)
 {
-	struct intel_engine_cs *ring = rq->ring;
+	ASSIGN_CTX_PDP(ppgtt, reg_state, 3);
+	ASSIGN_CTX_PDP(ppgtt, reg_state, 2);
+	ASSIGN_CTX_PDP(ppgtt, reg_state, 1);
+	ASSIGN_CTX_PDP(ppgtt, reg_state, 0);
+}
+
+static void execlists_update_context(struct drm_i915_gem_request *rq)
+{
+	struct intel_engine_cs *engine = rq->engine;
 	struct i915_hw_ppgtt *ppgtt = rq->ctx->ppgtt;
-	uint32_t *reg_state = rq->ctx->engine[ring->id].lrc_reg_state;
+	uint32_t *reg_state = rq->ctx->engine[engine->id].lrc_reg_state;
 
 	reg_state[CTX_RING_TAIL+1] = rq->tail;
 
-	if (ppgtt && !USES_FULL_48BIT_PPGTT(ppgtt->base.dev)) {
-		/* True 32b PPGTT with dynamic page allocation: update PDP
-		 * registers and point the unallocated PDPs to scratch page.
-		 * PML4 is allocated during ppgtt init, so this is not needed
-		 * in 48-bit mode.
-		 */
-		ASSIGN_CTX_PDP(ppgtt, reg_state, 3);
-		ASSIGN_CTX_PDP(ppgtt, reg_state, 2);
-		ASSIGN_CTX_PDP(ppgtt, reg_state, 1);
-		ASSIGN_CTX_PDP(ppgtt, reg_state, 0);
-	}
-
-	return 0;
+	/* True 32b PPGTT with dynamic page allocation: update PDP
+	 * registers and point the unallocated PDPs to scratch page.
+	 * PML4 is allocated during ppgtt init, so this is not needed
+	 * in 48-bit mode.
+	 */
+	if (ppgtt && !USES_FULL_48BIT_PPGTT(ppgtt->base.dev))
+		execlists_update_context_pdps(ppgtt, reg_state);
 }
 
 static void execlists_submit_requests(struct drm_i915_gem_request *rq0,
 				      struct drm_i915_gem_request *rq1)
 {
+	struct drm_i915_private *dev_priv = rq0->i915;
+	unsigned int fw_domains = rq0->engine->fw_domains;
+
 	execlists_update_context(rq0);
 
 	if (rq1)
 		execlists_update_context(rq1);
 
+	spin_lock_irq(&dev_priv->uncore.lock);
+	intel_uncore_forcewake_get__locked(dev_priv, fw_domains);
+
 	execlists_elsp_write(rq0, rq1);
+
+	intel_uncore_forcewake_put__locked(dev_priv, fw_domains);
+	spin_unlock_irq(&dev_priv->uncore.lock);
 }
 
-static void execlists_context_unqueue(struct intel_engine_cs *ring)
+static void execlists_context_unqueue(struct intel_engine_cs *engine)
 {
 	struct drm_i915_gem_request *req0 = NULL, *req1 = NULL;
-	struct drm_i915_gem_request *cursor = NULL, *tmp = NULL;
+	struct drm_i915_gem_request *cursor, *tmp;
 
-	assert_spin_locked(&ring->execlist_lock);
+	assert_spin_locked(&engine->execlist_lock);
 
 	/*
 	 * If irqs are not active generate a warning as batches that finish
 	 * without the irqs may get lost and a GPU Hang may occur.
 	 */
-	WARN_ON(!intel_irqs_enabled(ring->dev->dev_private));
-
-	if (list_empty(&ring->execlist_queue))
-		return;
+	WARN_ON(!intel_irqs_enabled(engine->dev->dev_private));
 
 	/* Try to read in pairs */
-	list_for_each_entry_safe(cursor, tmp, &ring->execlist_queue,
+	list_for_each_entry_safe(cursor, tmp, &engine->execlist_queue,
 				 execlist_link) {
 		if (!req0) {
 			req0 = cursor;
@@ -448,172 +454,179 @@ static void execlists_context_unqueue(st
 			 * will update tail past first request's workload */
 			cursor->elsp_submitted = req0->elsp_submitted;
 			list_move_tail(&req0->execlist_link,
-				       &ring->execlist_retired_req_list);
+				       &engine->execlist_retired_req_list);
 			req0 = cursor;
 		} else {
 			req1 = cursor;
+			WARN_ON(req1->elsp_submitted);
 			break;
 		}
 	}
 
-	if (IS_GEN8(ring->dev) || IS_GEN9(ring->dev)) {
+	if (unlikely(!req0))
+		return;
+
+	if (req0->elsp_submitted & engine->idle_lite_restore_wa) {
 		/*
-		 * WaIdleLiteRestore: make sure we never cause a lite
-		 * restore with HEAD==TAIL
+		 * WaIdleLiteRestore: make sure we never cause a lite restore
+		 * with HEAD==TAIL.
+		 *
+		 * Apply the wa NOOPS to prevent ring:HEAD == req:TAIL as we
+		 * resubmit the request. See gen8_emit_request() for where we
+		 * prepare the padding after the end of the request.
 		 */
-		if (req0->elsp_submitted) {
-			/*
-			 * Apply the wa NOOPS to prevent ring:HEAD == req:TAIL
-			 * as we resubmit the request. See gen8_emit_request()
-			 * for where we prepare the padding after the end of the
-			 * request.
-			 */
-			struct intel_ringbuffer *ringbuf;
+		struct intel_ringbuffer *ringbuf;
 
-			ringbuf = req0->ctx->engine[ring->id].ringbuf;
-			req0->tail += 8;
-			req0->tail &= ringbuf->size - 1;
-		}
+		ringbuf = req0->ctx->engine[engine->id].ringbuf;
+		req0->tail += 8;
+		req0->tail &= ringbuf->size - 1;
 	}
 
-	WARN_ON(req1 && req1->elsp_submitted);
-
 	execlists_submit_requests(req0, req1);
 }
 
-static bool execlists_check_remove_request(struct intel_engine_cs *ring,
-					   u32 request_id)
+static unsigned int
+execlists_check_remove_request(struct intel_engine_cs *engine, u32 request_id)
 {
 	struct drm_i915_gem_request *head_req;
 
-	assert_spin_locked(&ring->execlist_lock);
+	assert_spin_locked(&engine->execlist_lock);
 
-	head_req = list_first_entry_or_null(&ring->execlist_queue,
+	head_req = list_first_entry_or_null(&engine->execlist_queue,
 					    struct drm_i915_gem_request,
 					    execlist_link);
 
-	if (head_req != NULL) {
-		if (intel_execlists_ctx_id(head_req->ctx, ring) == request_id) {
-			WARN(head_req->elsp_submitted == 0,
-			     "Never submitted head request\n");
+	if (!head_req)
+		return 0;
 
-			if (--head_req->elsp_submitted <= 0) {
-				list_move_tail(&head_req->execlist_link,
-					       &ring->execlist_retired_req_list);
-				return true;
-			}
-		}
-	}
+	if (unlikely(intel_execlists_ctx_id(head_req->ctx, engine) != request_id))
+		return 0;
 
-	return false;
+	WARN(head_req->elsp_submitted == 0, "Never submitted head request\n");
+
+	if (--head_req->elsp_submitted > 0)
+		return 0;
+
+	list_move_tail(&head_req->execlist_link,
+		       &engine->execlist_retired_req_list);
+
+	return 1;
 }
 
-static void get_context_status(struct intel_engine_cs *ring,
-			       u8 read_pointer,
-			       u32 *status, u32 *context_id)
+static u32
+get_context_status(struct intel_engine_cs *engine, unsigned int read_pointer,
+		   u32 *context_id)
 {
-	struct drm_i915_private *dev_priv = ring->dev->dev_private;
+	struct drm_i915_private *dev_priv = engine->dev->dev_private;
+	u32 status;
 
-	if (WARN_ON(read_pointer >= GEN8_CSB_ENTRIES))
-		return;
+	read_pointer %= GEN8_CSB_ENTRIES;
 
-	*status = I915_READ(RING_CONTEXT_STATUS_BUF_LO(ring, read_pointer));
-	*context_id = I915_READ(RING_CONTEXT_STATUS_BUF_HI(ring, read_pointer));
+	status = I915_READ_FW(RING_CONTEXT_STATUS_BUF_LO(engine, read_pointer));
+
+	if (status & GEN8_CTX_STATUS_IDLE_ACTIVE)
+		return 0;
+
+	*context_id = I915_READ_FW(RING_CONTEXT_STATUS_BUF_HI(engine,
+							      read_pointer));
+
+	return status;
 }
 
 /**
  * intel_lrc_irq_handler() - handle Context Switch interrupts
- * @ring: Engine Command Streamer to handle.
+ * @engine: Engine Command Streamer to handle.
  *
  * Check the unread Context Status Buffers and manage the submission of new
  * contexts to the ELSP accordingly.
  */
-void intel_lrc_irq_handler(struct intel_engine_cs *ring)
+static void intel_lrc_irq_handler(unsigned long data)
 {
-	struct drm_i915_private *dev_priv = ring->dev->dev_private;
+	struct intel_engine_cs *engine = (struct intel_engine_cs *)data;
+	struct drm_i915_private *dev_priv = engine->dev->dev_private;
 	u32 status_pointer;
-	u8 read_pointer;
-	u8 write_pointer;
-	u32 status = 0;
-	u32 status_id;
-	u32 submit_contexts = 0;
+	unsigned int read_pointer, write_pointer;
+	u32 csb[GEN8_CSB_ENTRIES][2];
+	unsigned int csb_read = 0, i;
+	unsigned int submit_contexts = 0;
 
-	status_pointer = I915_READ(RING_CONTEXT_STATUS_PTR(ring));
+	intel_uncore_forcewake_get(dev_priv, engine->fw_domains);
 
-	read_pointer = ring->next_context_status_buffer;
+	status_pointer = I915_READ_FW(RING_CONTEXT_STATUS_PTR(engine));
+
+	read_pointer = engine->next_context_status_buffer;
 	write_pointer = GEN8_CSB_WRITE_PTR(status_pointer);
 	if (read_pointer > write_pointer)
 		write_pointer += GEN8_CSB_ENTRIES;
 
-	spin_lock(&ring->execlist_lock);
-
 	while (read_pointer < write_pointer) {
+		if (WARN_ON_ONCE(csb_read == GEN8_CSB_ENTRIES))
+			break;
+		csb[csb_read][0] = get_context_status(engine, ++read_pointer,
+						      &csb[csb_read][1]);
+		csb_read++;
+	}
 
-		get_context_status(ring, ++read_pointer % GEN8_CSB_ENTRIES,
-				   &status, &status_id);
+	engine->next_context_status_buffer = write_pointer % GEN8_CSB_ENTRIES;
 
-		if (status & GEN8_CTX_STATUS_IDLE_ACTIVE)
-			continue;
+	/* Update the read pointer to the old write pointer. Manual ringbuffer
+	 * management ftw </sarcasm> */
+	I915_WRITE_FW(RING_CONTEXT_STATUS_PTR(engine),
+		      _MASKED_FIELD(GEN8_CSB_READ_PTR_MASK,
+				    engine->next_context_status_buffer << 8));
 
-		if (status & GEN8_CTX_STATUS_PREEMPTED) {
-			if (status & GEN8_CTX_STATUS_LITE_RESTORE) {
-				if (execlists_check_remove_request(ring, status_id))
+	intel_uncore_forcewake_put(dev_priv, engine->fw_domains);
+
+	spin_lock(&engine->execlist_lock);
+
+	for (i = 0; i < csb_read; i++) {
+		if (unlikely(csb[i][0] & GEN8_CTX_STATUS_PREEMPTED)) {
+			if (csb[i][0] & GEN8_CTX_STATUS_LITE_RESTORE) {
+				if (execlists_check_remove_request(engine, csb[i][1]))
 					WARN(1, "Lite Restored request removed from queue\n");
 			} else
 				WARN(1, "Preemption without Lite Restore\n");
 		}
 
-		if ((status & GEN8_CTX_STATUS_ACTIVE_IDLE) ||
-		    (status & GEN8_CTX_STATUS_ELEMENT_SWITCH)) {
-			if (execlists_check_remove_request(ring, status_id))
-				submit_contexts++;
-		}
+		if (csb[i][0] & (GEN8_CTX_STATUS_ACTIVE_IDLE |
+		    GEN8_CTX_STATUS_ELEMENT_SWITCH))
+			submit_contexts +=
+				execlists_check_remove_request(engine, csb[i][1]);
 	}
 
-	if (ring->disable_lite_restore_wa) {
-		/* Prevent a ctx to preempt itself */
-		if ((status & GEN8_CTX_STATUS_ACTIVE_IDLE) &&
-		    (submit_contexts != 0))
-			execlists_context_unqueue(ring);
-	} else if (submit_contexts != 0) {
-		execlists_context_unqueue(ring);
+	if (submit_contexts) {
+		if (!engine->disable_lite_restore_wa ||
+		    (csb[i][0] & GEN8_CTX_STATUS_ACTIVE_IDLE))
+			execlists_context_unqueue(engine);
 	}
 
-	spin_unlock(&ring->execlist_lock);
+	spin_unlock(&engine->execlist_lock);
 
 	if (unlikely(submit_contexts > 2))
 		DRM_ERROR("More than two context complete events?\n");
-
-	ring->next_context_status_buffer = write_pointer % GEN8_CSB_ENTRIES;
-
-	/* Update the read pointer to the old write pointer. Manual ringbuffer
-	 * management ftw </sarcasm> */
-	I915_WRITE(RING_CONTEXT_STATUS_PTR(ring),
-		   _MASKED_FIELD(GEN8_CSB_READ_PTR_MASK,
-				 ring->next_context_status_buffer << 8));
 }
 
-static int execlists_context_queue(struct drm_i915_gem_request *request)
+static void execlists_context_queue(struct drm_i915_gem_request *request)
 {
-	struct intel_engine_cs *ring = request->ring;
+	struct intel_engine_cs *engine = request->engine;
 	struct drm_i915_gem_request *cursor;
 	int num_elements = 0;
 
 	if (request->ctx != request->i915->kernel_context)
-		intel_lr_context_pin(request->ctx, ring);
+		intel_lr_context_pin(request->ctx, engine);
 
 	i915_gem_request_reference(request);
 
-	spin_lock_irq(&ring->execlist_lock);
+	spin_lock_bh(&engine->execlist_lock);
 
-	list_for_each_entry(cursor, &ring->execlist_queue, execlist_link)
+	list_for_each_entry(cursor, &engine->execlist_queue, execlist_link)
 		if (++num_elements > 2)
 			break;
 
 	if (num_elements > 2) {
 		struct drm_i915_gem_request *tail_req;
 
-		tail_req = list_last_entry(&ring->execlist_queue,
+		tail_req = list_last_entry(&engine->execlist_queue,
 					   struct drm_i915_gem_request,
 					   execlist_link);
 
@@ -621,41 +634,39 @@ static int execlists_context_queue(struc
 			WARN(tail_req->elsp_submitted != 0,
 				"More than 2 already-submitted reqs queued\n");
 			list_move_tail(&tail_req->execlist_link,
-				       &ring->execlist_retired_req_list);
+				       &engine->execlist_retired_req_list);
 		}
 	}
 
-	list_add_tail(&request->execlist_link, &ring->execlist_queue);
+	list_add_tail(&request->execlist_link, &engine->execlist_queue);
 	if (num_elements == 0)
-		execlists_context_unqueue(ring);
-
-	spin_unlock_irq(&ring->execlist_lock);
+		execlists_context_unqueue(engine);
 
-	return 0;
+	spin_unlock_bh(&engine->execlist_lock);
 }
 
 static int logical_ring_invalidate_all_caches(struct drm_i915_gem_request *req)
 {
-	struct intel_engine_cs *ring = req->ring;
+	struct intel_engine_cs *engine = req->engine;
 	uint32_t flush_domains;
 	int ret;
 
 	flush_domains = 0;
-	if (ring->gpu_caches_dirty)
+	if (engine->gpu_caches_dirty)
 		flush_domains = I915_GEM_GPU_DOMAINS;
 
-	ret = ring->emit_flush(req, I915_GEM_GPU_DOMAINS, flush_domains);
+	ret = engine->emit_flush(req, I915_GEM_GPU_DOMAINS, flush_domains);
 	if (ret)
 		return ret;
 
-	ring->gpu_caches_dirty = false;
+	engine->gpu_caches_dirty = false;
 	return 0;
 }
 
 static int execlists_move_to_gpu(struct drm_i915_gem_request *req,
 				 struct list_head *vmas)
 {
-	const unsigned other_rings = ~intel_ring_flag(req->ring);
+	const unsigned other_rings = ~intel_engine_flag(req->engine);
 	struct i915_vma *vma;
 	uint32_t flush_domains = 0;
 	bool flush_chipset = false;
@@ -665,7 +676,7 @@ static int execlists_move_to_gpu(struct
 		struct drm_i915_gem_object *obj = vma->obj;
 
 		if (obj->active & other_rings) {
-			ret = i915_gem_object_sync(obj, req->ring, &req);
+			ret = i915_gem_object_sync(obj, req->engine, &req);
 			if (ret)
 				return ret;
 		}
@@ -689,7 +700,7 @@ int intel_logical_ring_alloc_request_ext
 {
 	int ret = 0;
 
-	request->ringbuf = request->ctx->engine[request->ring->id].ringbuf;
+	request->ringbuf = request->ctx->engine[request->engine->id].ringbuf;
 
 	if (i915.enable_guc_submission) {
 		/*
@@ -705,53 +716,11 @@ int intel_logical_ring_alloc_request_ext
 	}
 
 	if (request->ctx != request->i915->kernel_context)
-		ret = intel_lr_context_pin(request->ctx, request->ring);
+		ret = intel_lr_context_pin(request->ctx, request->engine);
 
 	return ret;
 }
 
-static int logical_ring_wait_for_space(struct drm_i915_gem_request *req,
-				       int bytes)
-{
-	struct intel_ringbuffer *ringbuf = req->ringbuf;
-	struct intel_engine_cs *ring = req->ring;
-	struct drm_i915_gem_request *target;
-	unsigned space;
-	int ret;
-
-	if (intel_ring_space(ringbuf) >= bytes)
-		return 0;
-
-	/* The whole point of reserving space is to not wait! */
-	WARN_ON(ringbuf->reserved_in_use);
-
-	list_for_each_entry(target, &ring->request_list, list) {
-		/*
-		 * The request queue is per-engine, so can contain requests
-		 * from multiple ringbuffers. Here, we must ignore any that
-		 * aren't from the ringbuffer we're considering.
-		 */
-		if (target->ringbuf != ringbuf)
-			continue;
-
-		/* Would completion of this request free enough space? */
-		space = __intel_ring_space(target->postfix, ringbuf->tail,
-					   ringbuf->size);
-		if (space >= bytes)
-			break;
-	}
-
-	if (WARN_ON(&target->list == &ring->request_list))
-		return -ENOSPC;
-
-	ret = i915_wait_request(target);
-	if (ret)
-		return ret;
-
-	ringbuf->space = space;
-	return 0;
-}
-
 /*
  * intel_logical_ring_advance_and_submit() - advance the tail and submit the workload
  * @request: Request to advance the logical ringbuffer of.
@@ -766,7 +735,7 @@ intel_logical_ring_advance_and_submit(st
 {
 	struct intel_ringbuffer *ringbuf = request->ringbuf;
 	struct drm_i915_private *dev_priv = request->i915;
-	struct intel_engine_cs *engine = request->ring;
+	struct intel_engine_cs *engine = request->engine;
 
 	intel_logical_ring_advance(ringbuf);
 	request->tail = ringbuf->tail;
@@ -781,7 +750,7 @@ intel_logical_ring_advance_and_submit(st
 	intel_logical_ring_emit(ringbuf, MI_NOOP);
 	intel_logical_ring_advance(ringbuf);
 
-	if (intel_ring_stopped(engine))
+	if (intel_engine_stopped(engine))
 		return 0;
 
 	if (engine->last_context != request->ctx) {
@@ -803,101 +772,6 @@ intel_logical_ring_advance_and_submit(st
 	return 0;
 }
 
-static void __wrap_ring_buffer(struct intel_ringbuffer *ringbuf)
-{
-	uint32_t __iomem *virt;
-	int rem = ringbuf->size - ringbuf->tail;
-
-	virt = ringbuf->virtual_start + ringbuf->tail;
-	rem /= 4;
-	while (rem--)
-		iowrite32(MI_NOOP, virt++);
-
-	ringbuf->tail = 0;
-	intel_ring_update_space(ringbuf);
-}
-
-static int logical_ring_prepare(struct drm_i915_gem_request *req, int bytes)
-{
-	struct intel_ringbuffer *ringbuf = req->ringbuf;
-	int remain_usable = ringbuf->effective_size - ringbuf->tail;
-	int remain_actual = ringbuf->size - ringbuf->tail;
-	int ret, total_bytes, wait_bytes = 0;
-	bool need_wrap = false;
-
-	if (ringbuf->reserved_in_use)
-		total_bytes = bytes;
-	else
-		total_bytes = bytes + ringbuf->reserved_size;
-
-	if (unlikely(bytes > remain_usable)) {
-		/*
-		 * Not enough space for the basic request. So need to flush
-		 * out the remainder and then wait for base + reserved.
-		 */
-		wait_bytes = remain_actual + total_bytes;
-		need_wrap = true;
-	} else {
-		if (unlikely(total_bytes > remain_usable)) {
-			/*
-			 * The base request will fit but the reserved space
-			 * falls off the end. So don't need an immediate wrap
-			 * and only need to effectively wait for the reserved
-			 * size space from the start of ringbuffer.
-			 */
-			wait_bytes = remain_actual + ringbuf->reserved_size;
-		} else if (total_bytes > ringbuf->space) {
-			/* No wrapping required, just waiting. */
-			wait_bytes = total_bytes;
-		}
-	}
-
-	if (wait_bytes) {
-		ret = logical_ring_wait_for_space(req, wait_bytes);
-		if (unlikely(ret))
-			return ret;
-
-		if (need_wrap)
-			__wrap_ring_buffer(ringbuf);
-	}
-
-	return 0;
-}
-
-/**
- * intel_logical_ring_begin() - prepare the logical ringbuffer to accept some commands
- *
- * @req: The request to start some new work for
- * @num_dwords: number of DWORDs that we plan to write to the ringbuffer.
- *
- * The ringbuffer might not be ready to accept the commands right away (maybe it needs to
- * be wrapped, or wait a bit for the tail to be updated). This function takes care of that
- * and also preallocates a request (every workload submission is still mediated through
- * requests, same as it did with legacy ringbuffer submission).
- *
- * Return: non-zero if the ringbuffer is not ready to be written to.
- */
-int intel_logical_ring_begin(struct drm_i915_gem_request *req, int num_dwords)
-{
-	struct drm_i915_private *dev_priv;
-	int ret;
-
-	WARN_ON(req == NULL);
-	dev_priv = req->ring->dev->dev_private;
-
-	ret = i915_gem_check_wedge(&dev_priv->gpu_error,
-				   dev_priv->mm.interruptible);
-	if (ret)
-		return ret;
-
-	ret = logical_ring_prepare(req, num_dwords * sizeof(uint32_t));
-	if (ret)
-		return ret;
-
-	req->ringbuf->space -= num_dwords * sizeof(uint32_t);
-	return 0;
-}
-
 int intel_logical_ring_reserve_space(struct drm_i915_gem_request *request)
 {
 	/*
@@ -910,7 +784,7 @@ int intel_logical_ring_reserve_space(str
 	 */
 	intel_ring_reserved_space_reserve(request->ringbuf, MIN_SPACE_FOR_ADD_REQUEST);
 
-	return intel_logical_ring_begin(request, 0);
+	return intel_ring_begin(request, 0);
 }
 
 /**
@@ -935,9 +809,9 @@ int intel_execlists_submission(struct i9
 			       struct list_head *vmas)
 {
 	struct drm_device       *dev = params->dev;
-	struct intel_engine_cs  *ring = params->ring;
+	struct intel_engine_cs *engine = params->engine;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_ringbuffer *ringbuf = params->ctx->engine[ring->id].ringbuf;
+	struct intel_ringbuffer *ringbuf = params->ctx->engine[engine->id].ringbuf;
 	u64 exec_start;
 	int instp_mode;
 	u32 instp_mask;
@@ -949,7 +823,7 @@ int intel_execlists_submission(struct i9
 	case I915_EXEC_CONSTANTS_REL_GENERAL:
 	case I915_EXEC_CONSTANTS_ABSOLUTE:
 	case I915_EXEC_CONSTANTS_REL_SURFACE:
-		if (instp_mode != 0 && ring != &dev_priv->ring[RCS]) {
+		if (instp_mode != 0 && engine != &dev_priv->engine[RCS]) {
 			DRM_DEBUG("non-0 rel constants mode on non-RCS\n");
 			return -EINVAL;
 		}
@@ -978,9 +852,9 @@ int intel_execlists_submission(struct i9
 	if (ret)
 		return ret;
 
-	if (ring == &dev_priv->ring[RCS] &&
+	if (engine == &dev_priv->engine[RCS] &&
 	    instp_mode != dev_priv->relative_constants_mode) {
-		ret = intel_logical_ring_begin(params->request, 4);
+		ret = intel_ring_begin(params->request, 4);
 		if (ret)
 			return ret;
 
@@ -996,116 +870,116 @@ int intel_execlists_submission(struct i9
 	exec_start = params->batch_obj_vm_offset +
 		     args->batch_start_offset;
 
-	ret = ring->emit_bb_start(params->request, exec_start, params->dispatch_flags);
+	ret = engine->emit_bb_start(params->request, exec_start, params->dispatch_flags);
 	if (ret)
 		return ret;
 
 	trace_i915_gem_ring_dispatch(params->request, params->dispatch_flags);
 
 	i915_gem_execbuffer_move_to_active(vmas, params->request);
-	i915_gem_execbuffer_retire_commands(params);
 
 	return 0;
 }
 
-void intel_execlists_retire_requests(struct intel_engine_cs *ring)
+void intel_execlists_retire_requests(struct intel_engine_cs *engine)
 {
 	struct drm_i915_gem_request *req, *tmp;
 	struct list_head retired_list;
 
-	WARN_ON(!mutex_is_locked(&ring->dev->struct_mutex));
-	if (list_empty(&ring->execlist_retired_req_list))
+	WARN_ON(!mutex_is_locked(&engine->dev->struct_mutex));
+	if (list_empty(&engine->execlist_retired_req_list))
 		return;
 
 	INIT_LIST_HEAD(&retired_list);
-	spin_lock_irq(&ring->execlist_lock);
-	list_replace_init(&ring->execlist_retired_req_list, &retired_list);
-	spin_unlock_irq(&ring->execlist_lock);
+	spin_lock_bh(&engine->execlist_lock);
+	list_replace_init(&engine->execlist_retired_req_list, &retired_list);
+	spin_unlock_bh(&engine->execlist_lock);
 
 	list_for_each_entry_safe(req, tmp, &retired_list, execlist_link) {
 		struct intel_context *ctx = req->ctx;
 		struct drm_i915_gem_object *ctx_obj =
-				ctx->engine[ring->id].state;
+				ctx->engine[engine->id].state;
 
 		if (ctx_obj && (ctx != req->i915->kernel_context))
-			intel_lr_context_unpin(ctx, ring);
+			intel_lr_context_unpin(ctx, engine);
 
 		list_del(&req->execlist_link);
 		i915_gem_request_unreference(req);
 	}
 }
 
-void intel_logical_ring_stop(struct intel_engine_cs *ring)
+void intel_logical_ring_stop(struct intel_engine_cs *engine)
 {
-	struct drm_i915_private *dev_priv = ring->dev->dev_private;
+	struct drm_i915_private *dev_priv = engine->dev->dev_private;
 	int ret;
 
-	if (!intel_ring_initialized(ring))
+	if (!intel_engine_initialized(engine))
 		return;
 
-	ret = intel_ring_idle(ring);
-	if (ret && !i915_reset_in_progress(&to_i915(ring->dev)->gpu_error))
+	ret = intel_engine_idle(engine);
+	if (ret)
 		DRM_ERROR("failed to quiesce %s whilst cleaning up: %d\n",
-			  ring->name, ret);
+			  engine->name, ret);
 
 	/* TODO: Is this correct with Execlists enabled? */
-	I915_WRITE_MODE(ring, _MASKED_BIT_ENABLE(STOP_RING));
-	if (wait_for_atomic((I915_READ_MODE(ring) & MODE_IDLE) != 0, 1000)) {
-		DRM_ERROR("%s :timed out trying to stop ring\n", ring->name);
+	I915_WRITE_MODE(engine, _MASKED_BIT_ENABLE(STOP_RING));
+	if (wait_for((I915_READ_MODE(engine) & MODE_IDLE) != 0, 1000)) {
+		DRM_ERROR("%s :timed out trying to stop ring\n", engine->name);
 		return;
 	}
-	I915_WRITE_MODE(ring, _MASKED_BIT_DISABLE(STOP_RING));
+	I915_WRITE_MODE(engine, _MASKED_BIT_DISABLE(STOP_RING));
 }
 
 int logical_ring_flush_all_caches(struct drm_i915_gem_request *req)
 {
-	struct intel_engine_cs *ring = req->ring;
+	struct intel_engine_cs *engine = req->engine;
 	int ret;
 
-	if (!ring->gpu_caches_dirty)
+	if (!engine->gpu_caches_dirty)
 		return 0;
 
-	ret = ring->emit_flush(req, 0, I915_GEM_GPU_DOMAINS);
+	ret = engine->emit_flush(req, 0, I915_GEM_GPU_DOMAINS);
 	if (ret)
 		return ret;
 
-	ring->gpu_caches_dirty = false;
+	engine->gpu_caches_dirty = false;
 	return 0;
 }
 
 static int intel_lr_context_do_pin(struct intel_context *ctx,
-				   struct intel_engine_cs *ring)
+				   struct intel_engine_cs *engine)
 {
-	struct drm_device *dev = ring->dev;
+	struct drm_device *dev = engine->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_i915_gem_object *ctx_obj = ctx->engine[ring->id].state;
-	struct intel_ringbuffer *ringbuf = ctx->engine[ring->id].ringbuf;
-	struct page *lrc_state_page;
-	uint32_t *lrc_reg_state;
+	struct drm_i915_gem_object *ctx_obj = ctx->engine[engine->id].state;
+	struct intel_ringbuffer *ringbuf = ctx->engine[engine->id].ringbuf;
+	void *vaddr;
+	u32 *lrc_reg_state;
 	int ret;
 
-	WARN_ON(!mutex_is_locked(&ring->dev->struct_mutex));
+	WARN_ON(!mutex_is_locked(&engine->dev->struct_mutex));
 
 	ret = i915_gem_obj_ggtt_pin(ctx_obj, GEN8_LR_CONTEXT_ALIGN,
 			PIN_OFFSET_BIAS | GUC_WOPCM_TOP);
 	if (ret)
 		return ret;
 
-	lrc_state_page = i915_gem_object_get_dirty_page(ctx_obj, LRC_STATE_PN);
-	if (WARN_ON(!lrc_state_page)) {
-		ret = -ENODEV;
+	vaddr = i915_gem_object_pin_map(ctx_obj);
+	if (IS_ERR(vaddr)) {
+		ret = PTR_ERR(vaddr);
 		goto unpin_ctx_obj;
 	}
 
-	ret = intel_pin_and_map_ringbuffer_obj(ring->dev, ringbuf);
+	lrc_reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE;
+
+	ret = intel_pin_and_map_ringbuffer_obj(engine->dev, ringbuf);
 	if (ret)
-		goto unpin_ctx_obj;
+		goto unpin_map;
 
-	ctx->engine[ring->id].lrc_vma = i915_gem_obj_to_ggtt(ctx_obj);
-	intel_lr_context_descriptor_update(ctx, ring);
-	lrc_reg_state = kmap(lrc_state_page);
+	ctx->engine[engine->id].lrc_vma = i915_gem_obj_to_ggtt(ctx_obj);
+	intel_lr_context_descriptor_update(ctx, engine);
 	lrc_reg_state[CTX_RING_BUFFER_START+1] = ringbuf->vma->node.start;
-	ctx->engine[ring->id].lrc_reg_state = lrc_reg_state;
+	ctx->engine[engine->id].lrc_reg_state = lrc_reg_state;
 	ctx_obj->dirty = true;
 
 	/* Invalidate GuC TLB. */
@@ -1114,6 +988,8 @@ static int intel_lr_context_do_pin(struc
 
 	return ret;
 
+unpin_map:
+	i915_gem_object_unpin_map(ctx_obj);
 unpin_ctx_obj:
 	i915_gem_object_ggtt_unpin(ctx_obj);
 
@@ -1146,7 +1022,7 @@ void intel_lr_context_unpin(struct intel
 
 	WARN_ON(!mutex_is_locked(&ctx->i915->dev->struct_mutex));
 	if (--ctx->engine[engine->id].pin_count == 0) {
-		kunmap(kmap_to_page(ctx->engine[engine->id].lrc_reg_state));
+		i915_gem_object_unpin_map(ctx_obj);
 		intel_unpin_ringbuffer_obj(ctx->engine[engine->id].ringbuf);
 		i915_gem_object_ggtt_unpin(ctx_obj);
 		ctx->engine[engine->id].lrc_vma = NULL;
@@ -1160,21 +1036,21 @@ void intel_lr_context_unpin(struct intel
 static int intel_logical_ring_workarounds_emit(struct drm_i915_gem_request *req)
 {
 	int ret, i;
-	struct intel_engine_cs *ring = req->ring;
+	struct intel_engine_cs *engine = req->engine;
 	struct intel_ringbuffer *ringbuf = req->ringbuf;
-	struct drm_device *dev = ring->dev;
+	struct drm_device *dev = engine->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct i915_workarounds *w = &dev_priv->workarounds;
 
 	if (w->count == 0)
 		return 0;
 
-	ring->gpu_caches_dirty = true;
+	engine->gpu_caches_dirty = true;
 	ret = logical_ring_flush_all_caches(req);
 	if (ret)
 		return ret;
 
-	ret = intel_logical_ring_begin(req, w->count * 2 + 2);
+	ret = intel_ring_begin(req, w->count * 2 + 2);
 	if (ret)
 		return ret;
 
@@ -1187,7 +1063,7 @@ static int intel_logical_ring_workaround
 
 	intel_logical_ring_advance(ringbuf);
 
-	ring->gpu_caches_dirty = true;
+	engine->gpu_caches_dirty = true;
 	ret = logical_ring_flush_all_caches(req);
 	if (ret)
 		return ret;
@@ -1223,25 +1099,27 @@ static int intel_logical_ring_workaround
  * This WA is also required for Gen9 so extracting as a function avoids
  * code duplication.
  */
-static inline int gen8_emit_flush_coherentl3_wa(struct intel_engine_cs *ring,
+static inline int gen8_emit_flush_coherentl3_wa(struct intel_engine_cs *engine,
 						uint32_t *const batch,
 						uint32_t index)
 {
+	struct drm_i915_private *dev_priv = engine->dev->dev_private;
 	uint32_t l3sqc4_flush = (0x40400000 | GEN8_LQSC_FLUSH_COHERENT_LINES);
 
 	/*
-	 * WaDisableLSQCROPERFforOCL:skl
+	 * WaDisableLSQCROPERFforOCL:skl,kbl
 	 * This WA is implemented in skl_init_clock_gating() but since
 	 * this batch updates GEN8_L3SQCREG4 with default value we need to
 	 * set this bit here to retain the WA during flush.
 	 */
-	if (IS_SKL_REVID(ring->dev, 0, SKL_REVID_E0))
+	if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_E0) ||
+	    IS_KBL_REVID(dev_priv, 0, KBL_REVID_E0))
 		l3sqc4_flush |= GEN8_LQSC_RO_PERF_DIS;
 
 	wa_ctx_emit(batch, index, (MI_STORE_REGISTER_MEM_GEN8 |
 				   MI_SRM_LRM_GLOBAL_GTT));
 	wa_ctx_emit_reg(batch, index, GEN8_L3SQCREG4);
-	wa_ctx_emit(batch, index, ring->scratch.gtt_offset + 256);
+	wa_ctx_emit(batch, index, engine->scratch.gtt_offset + 256);
 	wa_ctx_emit(batch, index, 0);
 
 	wa_ctx_emit(batch, index, MI_LOAD_REGISTER_IMM(1));
@@ -1259,7 +1137,7 @@ static inline int gen8_emit_flush_cohere
 	wa_ctx_emit(batch, index, (MI_LOAD_REGISTER_MEM_GEN8 |
 				   MI_SRM_LRM_GLOBAL_GTT));
 	wa_ctx_emit_reg(batch, index, GEN8_L3SQCREG4);
-	wa_ctx_emit(batch, index, ring->scratch.gtt_offset + 256);
+	wa_ctx_emit(batch, index, engine->scratch.gtt_offset + 256);
 	wa_ctx_emit(batch, index, 0);
 
 	return index;
@@ -1312,7 +1190,7 @@ static inline int wa_ctx_end(struct i915
  * Return: non-zero if we exceed the PAGE_SIZE limit.
  */
 
-static int gen8_init_indirectctx_bb(struct intel_engine_cs *ring,
+static int gen8_init_indirectctx_bb(struct intel_engine_cs *engine,
 				    struct i915_wa_ctx_bb *wa_ctx,
 				    uint32_t *const batch,
 				    uint32_t *offset)
@@ -1324,8 +1202,8 @@ static int gen8_init_indirectctx_bb(stru
 	wa_ctx_emit(batch, index, MI_ARB_ON_OFF | MI_ARB_DISABLE);
 
 	/* WaFlushCoherentL3CacheLinesAtContextSwitch:bdw */
-	if (IS_BROADWELL(ring->dev)) {
-		int rc = gen8_emit_flush_coherentl3_wa(ring, batch, index);
+	if (IS_BROADWELL(engine->dev)) {
+		int rc = gen8_emit_flush_coherentl3_wa(engine, batch, index);
 		if (rc < 0)
 			return rc;
 		index = rc;
@@ -1333,7 +1211,7 @@ static int gen8_init_indirectctx_bb(stru
 
 	/* WaClearSlmSpaceAtContextSwitch:bdw,chv */
 	/* Actual scratch location is at 128 bytes offset */
-	scratch_addr = ring->scratch.gtt_offset + 2*CACHELINE_BYTES;
+	scratch_addr = engine->scratch.gtt_offset + 2*CACHELINE_BYTES;
 
 	wa_ctx_emit(batch, index, GFX_OP_PIPE_CONTROL(6));
 	wa_ctx_emit(batch, index, (PIPE_CONTROL_FLUSH_L3 |
@@ -1375,7 +1253,7 @@ static int gen8_init_indirectctx_bb(stru
  *  This batch is terminated with MI_BATCH_BUFFER_END and so we need not add padding
  *  to align it with cacheline as padding after MI_BATCH_BUFFER_END is redundant.
  */
-static int gen8_init_perctx_bb(struct intel_engine_cs *ring,
+static int gen8_init_perctx_bb(struct intel_engine_cs *engine,
 			       struct i915_wa_ctx_bb *wa_ctx,
 			       uint32_t *const batch,
 			       uint32_t *offset)
@@ -1390,13 +1268,14 @@ static int gen8_init_perctx_bb(struct in
 	return wa_ctx_end(wa_ctx, *offset = index, 1);
 }
 
-static int gen9_init_indirectctx_bb(struct intel_engine_cs *ring,
+static int gen9_init_indirectctx_bb(struct intel_engine_cs *engine,
 				    struct i915_wa_ctx_bb *wa_ctx,
 				    uint32_t *const batch,
 				    uint32_t *offset)
 {
 	int ret;
-	struct drm_device *dev = ring->dev;
+	struct drm_device *dev = engine->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	uint32_t index = wa_ctx_start(wa_ctx, *offset, CACHELINE_DWORDS);
 
 	/* WaDisableCtxRestoreArbitration:skl,bxt */
@@ -1405,11 +1284,27 @@ static int gen9_init_indirectctx_bb(stru
 		wa_ctx_emit(batch, index, MI_ARB_ON_OFF | MI_ARB_DISABLE);
 
 	/* WaFlushCoherentL3CacheLinesAtContextSwitch:skl,bxt */
-	ret = gen8_emit_flush_coherentl3_wa(ring, batch, index);
+	ret = gen8_emit_flush_coherentl3_wa(engine, batch, index);
 	if (ret < 0)
 		return ret;
 	index = ret;
 
+	/* WaClearSlmSpaceAtContextSwitch:kbl */
+	/* Actual scratch location is at 128 bytes offset */
+	if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_A0)) {
+		uint32_t scratch_addr
+			= engine->scratch.gtt_offset + 2*CACHELINE_BYTES;
+
+		wa_ctx_emit(batch, index, GFX_OP_PIPE_CONTROL(6));
+		wa_ctx_emit(batch, index, (PIPE_CONTROL_FLUSH_L3 |
+					   PIPE_CONTROL_GLOBAL_GTT_IVB |
+					   PIPE_CONTROL_CS_STALL |
+					   PIPE_CONTROL_QW_WRITE));
+		wa_ctx_emit(batch, index, scratch_addr);
+		wa_ctx_emit(batch, index, 0);
+		wa_ctx_emit(batch, index, 0);
+		wa_ctx_emit(batch, index, 0);
+	}
 	/* Pad to end of cacheline */
 	while (index % CACHELINE_DWORDS)
 		wa_ctx_emit(batch, index, MI_NOOP);
@@ -1417,12 +1312,12 @@ static int gen9_init_indirectctx_bb(stru
 	return wa_ctx_end(wa_ctx, *offset = index, CACHELINE_DWORDS);
 }
 
-static int gen9_init_perctx_bb(struct intel_engine_cs *ring,
+static int gen9_init_perctx_bb(struct intel_engine_cs *engine,
 			       struct i915_wa_ctx_bb *wa_ctx,
 			       uint32_t *const batch,
 			       uint32_t *offset)
 {
-	struct drm_device *dev = ring->dev;
+	struct drm_device *dev = engine->dev;
 	uint32_t index = wa_ctx_start(wa_ctx, *offset, CACHELINE_DWORDS);
 
 	/* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:skl,bxt */
@@ -1435,6 +1330,25 @@ static int gen9_init_perctx_bb(struct in
 		wa_ctx_emit(batch, index, MI_NOOP);
 	}
 
+	/* WaClearTdlStateAckDirtyBits:bxt */
+	if (IS_BXT_REVID(dev, 0, BXT_REVID_B0)) {
+		wa_ctx_emit(batch, index, MI_LOAD_REGISTER_IMM(4));
+
+		wa_ctx_emit_reg(batch, index, GEN8_STATE_ACK);
+		wa_ctx_emit(batch, index, _MASKED_BIT_DISABLE(GEN9_SUBSLICE_TDL_ACK_BITS));
+
+		wa_ctx_emit_reg(batch, index, GEN9_STATE_ACK_SLICE1);
+		wa_ctx_emit(batch, index, _MASKED_BIT_DISABLE(GEN9_SUBSLICE_TDL_ACK_BITS));
+
+		wa_ctx_emit_reg(batch, index, GEN9_STATE_ACK_SLICE2);
+		wa_ctx_emit(batch, index, _MASKED_BIT_DISABLE(GEN9_SUBSLICE_TDL_ACK_BITS));
+
+		wa_ctx_emit_reg(batch, index, GEN7_ROW_CHICKEN2);
+		/* dummy write to CS, mask bits are 0 to ensure the register is not modified */
+		wa_ctx_emit(batch, index, 0x0);
+		wa_ctx_emit(batch, index, MI_NOOP);
+	}
+
 	/* WaDisableCtxRestoreArbitration:skl,bxt */
 	if (IS_SKL_REVID(dev, 0, SKL_REVID_D0) ||
 	    IS_BXT_REVID(dev, 0, BXT_REVID_A1))
@@ -1445,60 +1359,61 @@ static int gen9_init_perctx_bb(struct in
 	return wa_ctx_end(wa_ctx, *offset = index, 1);
 }
 
-static int lrc_setup_wa_ctx_obj(struct intel_engine_cs *ring, u32 size)
+static int lrc_setup_wa_ctx_obj(struct intel_engine_cs *engine, u32 size)
 {
 	int ret;
 
-	ring->wa_ctx.obj = i915_gem_alloc_object(ring->dev, PAGE_ALIGN(size));
-	if (!ring->wa_ctx.obj) {
+	engine->wa_ctx.obj = i915_gem_alloc_object(engine->dev,
+						   PAGE_ALIGN(size));
+	if (!engine->wa_ctx.obj) {
 		DRM_DEBUG_DRIVER("alloc LRC WA ctx backing obj failed.\n");
 		return -ENOMEM;
 	}
 
-	ret = i915_gem_obj_ggtt_pin(ring->wa_ctx.obj, PAGE_SIZE, 0);
+	ret = i915_gem_obj_ggtt_pin(engine->wa_ctx.obj, PAGE_SIZE, 0);
 	if (ret) {
 		DRM_DEBUG_DRIVER("pin LRC WA ctx backing obj failed: %d\n",
 				 ret);
-		drm_gem_object_unreference(&ring->wa_ctx.obj->base);
+		drm_gem_object_unreference(&engine->wa_ctx.obj->base);
 		return ret;
 	}
 
 	return 0;
 }
 
-static void lrc_destroy_wa_ctx_obj(struct intel_engine_cs *ring)
+static void lrc_destroy_wa_ctx_obj(struct intel_engine_cs *engine)
 {
-	if (ring->wa_ctx.obj) {
-		i915_gem_object_ggtt_unpin(ring->wa_ctx.obj);
-		drm_gem_object_unreference(&ring->wa_ctx.obj->base);
-		ring->wa_ctx.obj = NULL;
+	if (engine->wa_ctx.obj) {
+		i915_gem_object_ggtt_unpin(engine->wa_ctx.obj);
+		drm_gem_object_unreference(&engine->wa_ctx.obj->base);
+		engine->wa_ctx.obj = NULL;
 	}
 }
 
-static int intel_init_workaround_bb(struct intel_engine_cs *ring)
+static int intel_init_workaround_bb(struct intel_engine_cs *engine)
 {
 	int ret;
 	uint32_t *batch;
 	uint32_t offset;
 	struct page *page;
-	struct i915_ctx_workarounds *wa_ctx = &ring->wa_ctx;
+	struct i915_ctx_workarounds *wa_ctx = &engine->wa_ctx;
 
-	WARN_ON(ring->id != RCS);
+	WARN_ON(engine->id != RCS);
 
 	/* update this when WA for higher Gen are added */
-	if (INTEL_INFO(ring->dev)->gen > 9) {
+	if (INTEL_INFO(engine->dev)->gen > 9) {
 		DRM_ERROR("WA batch buffer is not initialized for Gen%d\n",
-			  INTEL_INFO(ring->dev)->gen);
+			  INTEL_INFO(engine->dev)->gen);
 		return 0;
 	}
 
 	/* some WA perform writes to scratch page, ensure it is valid */
-	if (ring->scratch.obj == NULL) {
-		DRM_ERROR("scratch page not allocated for %s\n", ring->name);
+	if (engine->scratch.obj == NULL) {
+		DRM_ERROR("scratch page not allocated for %s\n", engine->name);
 		return -EINVAL;
 	}
 
-	ret = lrc_setup_wa_ctx_obj(ring, PAGE_SIZE);
+	ret = lrc_setup_wa_ctx_obj(engine, PAGE_SIZE);
 	if (ret) {
 		DRM_DEBUG_DRIVER("Failed to setup context WA page: %d\n", ret);
 		return ret;
@@ -1508,29 +1423,29 @@ static int intel_init_workaround_bb(stru
 	batch = kmap_atomic(page);
 	offset = 0;
 
-	if (INTEL_INFO(ring->dev)->gen == 8) {
-		ret = gen8_init_indirectctx_bb(ring,
+	if (INTEL_INFO(engine->dev)->gen == 8) {
+		ret = gen8_init_indirectctx_bb(engine,
 					       &wa_ctx->indirect_ctx,
 					       batch,
 					       &offset);
 		if (ret)
 			goto out;
 
-		ret = gen8_init_perctx_bb(ring,
+		ret = gen8_init_perctx_bb(engine,
 					  &wa_ctx->per_ctx,
 					  batch,
 					  &offset);
 		if (ret)
 			goto out;
-	} else if (INTEL_INFO(ring->dev)->gen == 9) {
-		ret = gen9_init_indirectctx_bb(ring,
+	} else if (INTEL_INFO(engine->dev)->gen == 9) {
+		ret = gen9_init_indirectctx_bb(engine,
 					       &wa_ctx->indirect_ctx,
 					       batch,
 					       &offset);
 		if (ret)
 			goto out;
 
-		ret = gen9_init_perctx_bb(ring,
+		ret = gen9_init_perctx_bb(engine,
 					  &wa_ctx->per_ctx,
 					  batch,
 					  &offset);
@@ -1541,27 +1456,36 @@ static int intel_init_workaround_bb(stru
 out:
 	kunmap_atomic(batch);
 	if (ret)
-		lrc_destroy_wa_ctx_obj(ring);
+		lrc_destroy_wa_ctx_obj(engine);
 
 	return ret;
 }
 
-static int gen8_init_common_ring(struct intel_engine_cs *ring)
+static void lrc_init_hws(struct intel_engine_cs *engine)
 {
-	struct drm_device *dev = ring->dev;
+	struct drm_i915_private *dev_priv = engine->dev->dev_private;
+
+	I915_WRITE(RING_HWS_PGA(engine->mmio_base),
+		   (u32)engine->status_page.gfx_addr);
+	POSTING_READ(RING_HWS_PGA(engine->mmio_base));
+}
+
+static int gen8_init_common_ring(struct intel_engine_cs *engine)
+{
+	struct drm_device *dev = engine->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	u8 next_context_status_buffer_hw;
+	unsigned int next_context_status_buffer_hw;
 
-	lrc_setup_hardware_status_page(ring,
-				dev_priv->kernel_context->engine[ring->id].state);
+	lrc_init_hws(engine);
 
-	I915_WRITE_IMR(ring, ~(ring->irq_enable_mask | ring->irq_keep_mask));
-	I915_WRITE(RING_HWSTAM(ring->mmio_base), 0xffffffff);
+	I915_WRITE_IMR(engine,
+		       ~(engine->irq_enable_mask | engine->irq_keep_mask));
+	I915_WRITE(RING_HWSTAM(engine->mmio_base), 0xffffffff);
 
-	I915_WRITE(RING_MODE_GEN7(ring),
+	I915_WRITE(RING_MODE_GEN7(engine),
 		   _MASKED_BIT_DISABLE(GFX_REPLAY_MODE) |
 		   _MASKED_BIT_ENABLE(GFX_RUN_LIST_ENABLE));
-	POSTING_READ(RING_MODE_GEN7(ring));
+	POSTING_READ(RING_MODE_GEN7(engine));
 
 	/*
 	 * Instead of resetting the Context Status Buffer (CSB) read pointer to
@@ -1576,7 +1500,7 @@ static int gen8_init_common_ring(struct
 	 * BXT  |         ?                |         ?            |
 	 */
 	next_context_status_buffer_hw =
-		GEN8_CSB_WRITE_PTR(I915_READ(RING_CONTEXT_STATUS_PTR(ring)));
+		GEN8_CSB_WRITE_PTR(I915_READ(RING_CONTEXT_STATUS_PTR(engine)));
 
 	/*
 	 * When the CSB registers are reset (also after power-up / gpu reset),
@@ -1586,21 +1510,21 @@ static int gen8_init_common_ring(struct
 	if (next_context_status_buffer_hw == GEN8_CSB_PTR_MASK)
 		next_context_status_buffer_hw = (GEN8_CSB_ENTRIES - 1);
 
-	ring->next_context_status_buffer = next_context_status_buffer_hw;
-	DRM_DEBUG_DRIVER("Execlists enabled for %s\n", ring->name);
+	engine->next_context_status_buffer = next_context_status_buffer_hw;
+	DRM_DEBUG_DRIVER("Execlists enabled for %s\n", engine->name);
 
-	memset(&ring->hangcheck, 0, sizeof(ring->hangcheck));
+	intel_engine_init_hangcheck(engine);
 
-	return 0;
+	return intel_mocs_init_engine(engine);
 }
 
-static int gen8_init_render_ring(struct intel_engine_cs *ring)
+static int gen8_init_render_ring(struct intel_engine_cs *engine)
 {
-	struct drm_device *dev = ring->dev;
+	struct drm_device *dev = engine->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int ret;
 
-	ret = gen8_init_common_ring(ring);
+	ret = gen8_init_common_ring(engine);
 	if (ret)
 		return ret;
 
@@ -1614,29 +1538,29 @@ static int gen8_init_render_ring(struct
 
 	I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING));
 
-	return init_workarounds_ring(ring);
+	return init_workarounds_ring(engine);
 }
 
-static int gen9_init_render_ring(struct intel_engine_cs *ring)
+static int gen9_init_render_ring(struct intel_engine_cs *engine)
 {
 	int ret;
 
-	ret = gen8_init_common_ring(ring);
+	ret = gen8_init_common_ring(engine);
 	if (ret)
 		return ret;
 
-	return init_workarounds_ring(ring);
+	return init_workarounds_ring(engine);
 }
 
 static int intel_logical_ring_emit_pdps(struct drm_i915_gem_request *req)
 {
 	struct i915_hw_ppgtt *ppgtt = req->ctx->ppgtt;
-	struct intel_engine_cs *ring = req->ring;
+	struct intel_engine_cs *engine = req->engine;
 	struct intel_ringbuffer *ringbuf = req->ringbuf;
 	const int num_lri_cmds = GEN8_LEGACY_PDPES * 2;
 	int i, ret;
 
-	ret = intel_logical_ring_begin(req, num_lri_cmds * 2 + 2);
+	ret = intel_ring_begin(req, num_lri_cmds * 2 + 2);
 	if (ret)
 		return ret;
 
@@ -1644,9 +1568,11 @@ static int intel_logical_ring_emit_pdps(
 	for (i = GEN8_LEGACY_PDPES - 1; i >= 0; i--) {
 		const dma_addr_t pd_daddr = i915_page_dir_dma_addr(ppgtt, i);
 
-		intel_logical_ring_emit_reg(ringbuf, GEN8_RING_PDP_UDW(ring, i));
+		intel_logical_ring_emit_reg(ringbuf,
+					    GEN8_RING_PDP_UDW(engine, i));
 		intel_logical_ring_emit(ringbuf, upper_32_bits(pd_daddr));
-		intel_logical_ring_emit_reg(ringbuf, GEN8_RING_PDP_LDW(ring, i));
+		intel_logical_ring_emit_reg(ringbuf,
+					    GEN8_RING_PDP_LDW(engine, i));
 		intel_logical_ring_emit(ringbuf, lower_32_bits(pd_daddr));
 	}
 
@@ -1670,7 +1596,7 @@ static int gen8_emit_bb_start(struct drm
 	 * not idle). PML4 is allocated during ppgtt init so this is
 	 * not needed in 48-bit.*/
 	if (req->ctx->ppgtt &&
-	    (intel_ring_flag(req->ring) & req->ctx->ppgtt->pd_dirty_rings)) {
+	    (intel_engine_flag(req->engine) & req->ctx->ppgtt->pd_dirty_rings)) {
 		if (!USES_FULL_48BIT_PPGTT(req->i915) &&
 		    !intel_vgpu_active(req->i915->dev)) {
 			ret = intel_logical_ring_emit_pdps(req);
@@ -1678,10 +1604,10 @@ static int gen8_emit_bb_start(struct drm
 				return ret;
 		}
 
-		req->ctx->ppgtt->pd_dirty_rings &= ~intel_ring_flag(req->ring);
+		req->ctx->ppgtt->pd_dirty_rings &= ~intel_engine_flag(req->engine);
 	}
 
-	ret = intel_logical_ring_begin(req, 4);
+	ret = intel_ring_begin(req, 4);
 	if (ret)
 		return ret;
 
@@ -1698,9 +1624,9 @@ static int gen8_emit_bb_start(struct drm
 	return 0;
 }
 
-static bool gen8_logical_ring_get_irq(struct intel_engine_cs *ring)
+static bool gen8_logical_ring_get_irq(struct intel_engine_cs *engine)
 {
-	struct drm_device *dev = ring->dev;
+	struct drm_device *dev = engine->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	unsigned long flags;
 
@@ -1708,25 +1634,26 @@ static bool gen8_logical_ring_get_irq(st
 		return false;
 
 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
-	if (ring->irq_refcount++ == 0) {
-		I915_WRITE_IMR(ring, ~(ring->irq_enable_mask | ring->irq_keep_mask));
-		POSTING_READ(RING_IMR(ring->mmio_base));
+	if (engine->irq_refcount++ == 0) {
+		I915_WRITE_IMR(engine,
+			       ~(engine->irq_enable_mask | engine->irq_keep_mask));
+		POSTING_READ(RING_IMR(engine->mmio_base));
 	}
 	spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 
 	return true;
 }
 
-static void gen8_logical_ring_put_irq(struct intel_engine_cs *ring)
+static void gen8_logical_ring_put_irq(struct intel_engine_cs *engine)
 {
-	struct drm_device *dev = ring->dev;
+	struct drm_device *dev = engine->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	unsigned long flags;
 
 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
-	if (--ring->irq_refcount == 0) {
-		I915_WRITE_IMR(ring, ~ring->irq_keep_mask);
-		POSTING_READ(RING_IMR(ring->mmio_base));
+	if (--engine->irq_refcount == 0) {
+		I915_WRITE_IMR(engine, ~engine->irq_keep_mask);
+		POSTING_READ(RING_IMR(engine->mmio_base));
 	}
 	spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 }
@@ -1736,13 +1663,13 @@ static int gen8_emit_flush(struct drm_i9
 			   u32 unused)
 {
 	struct intel_ringbuffer *ringbuf = request->ringbuf;
-	struct intel_engine_cs *ring = ringbuf->ring;
-	struct drm_device *dev = ring->dev;
+	struct intel_engine_cs *engine = ringbuf->engine;
+	struct drm_device *dev = engine->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	uint32_t cmd;
 	int ret;
 
-	ret = intel_logical_ring_begin(request, 4);
+	ret = intel_ring_begin(request, 4);
 	if (ret)
 		return ret;
 
@@ -1757,7 +1684,7 @@ static int gen8_emit_flush(struct drm_i9
 
 	if (invalidate_domains & I915_GEM_GPU_DOMAINS) {
 		cmd |= MI_INVALIDATE_TLB;
-		if (ring == &dev_priv->ring[VCS])
+		if (engine == &dev_priv->engine[VCS])
 			cmd |= MI_INVALIDATE_BSD;
 	}
 
@@ -1777,11 +1704,12 @@ static int gen8_emit_flush_render(struct
 				  u32 flush_domains)
 {
 	struct intel_ringbuffer *ringbuf = request->ringbuf;
-	struct intel_engine_cs *ring = ringbuf->ring;
-	u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES;
-	bool vf_flush_wa = false;
+	struct intel_engine_cs *engine = ringbuf->engine;
+	u32 scratch_addr = engine->scratch.gtt_offset + 2 * CACHELINE_BYTES;
+	bool vf_flush_wa = false, dc_flush_wa = false;
 	u32 flags = 0;
 	int ret;
+	int len;
 
 	flags |= PIPE_CONTROL_CS_STALL;
 
@@ -1806,11 +1734,23 @@ static int gen8_emit_flush_render(struct
 		 * On GEN9: before VF_CACHE_INVALIDATE we need to emit a NULL
 		 * pipe control.
 		 */
-		if (IS_GEN9(ring->dev))
+		if (IS_GEN9(engine->dev))
 			vf_flush_wa = true;
+
+		/* WaForGAMHang:kbl */
+		if (IS_KBL_REVID(request->i915, 0, KBL_REVID_B0))
+			dc_flush_wa = true;
 	}
 
-	ret = intel_logical_ring_begin(request, vf_flush_wa ? 12 : 6);
+	len = 6;
+
+	if (vf_flush_wa)
+		len += 6;
+
+	if (dc_flush_wa)
+		len += 12;
+
+	ret = intel_ring_begin(request, len);
 	if (ret)
 		return ret;
 
@@ -1823,30 +1763,48 @@ static int gen8_emit_flush_render(struct
 		intel_logical_ring_emit(ringbuf, 0);
 	}
 
+	if (dc_flush_wa) {
+		intel_logical_ring_emit(ringbuf, GFX_OP_PIPE_CONTROL(6));
+		intel_logical_ring_emit(ringbuf, PIPE_CONTROL_DC_FLUSH_ENABLE);
+		intel_logical_ring_emit(ringbuf, 0);
+		intel_logical_ring_emit(ringbuf, 0);
+		intel_logical_ring_emit(ringbuf, 0);
+		intel_logical_ring_emit(ringbuf, 0);
+	}
+
 	intel_logical_ring_emit(ringbuf, GFX_OP_PIPE_CONTROL(6));
 	intel_logical_ring_emit(ringbuf, flags);
 	intel_logical_ring_emit(ringbuf, scratch_addr);
 	intel_logical_ring_emit(ringbuf, 0);
 	intel_logical_ring_emit(ringbuf, 0);
 	intel_logical_ring_emit(ringbuf, 0);
+
+	if (dc_flush_wa) {
+		intel_logical_ring_emit(ringbuf, GFX_OP_PIPE_CONTROL(6));
+		intel_logical_ring_emit(ringbuf, PIPE_CONTROL_CS_STALL);
+		intel_logical_ring_emit(ringbuf, 0);
+		intel_logical_ring_emit(ringbuf, 0);
+		intel_logical_ring_emit(ringbuf, 0);
+		intel_logical_ring_emit(ringbuf, 0);
+	}
+
 	intel_logical_ring_advance(ringbuf);
 
 	return 0;
 }
 
-static u32 gen8_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency)
+static u32 gen8_get_seqno(struct intel_engine_cs *engine)
 {
-	return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
+	return intel_read_status_page(engine, I915_GEM_HWS_INDEX);
 }
 
-static void gen8_set_seqno(struct intel_engine_cs *ring, u32 seqno)
+static void gen8_set_seqno(struct intel_engine_cs *engine, u32 seqno)
 {
-	intel_write_status_page(ring, I915_GEM_HWS_INDEX, seqno);
+	intel_write_status_page(engine, I915_GEM_HWS_INDEX, seqno);
 }
 
-static u32 bxt_a_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency)
+static void bxt_a_seqno_barrier(struct intel_engine_cs *engine)
 {
-
 	/*
 	 * On BXT A steppings there is a HW coherency issue whereby the
 	 * MI_STORE_DATA_IMM storing the completed request's seqno
@@ -1857,19 +1815,15 @@ static u32 bxt_a_get_seqno(struct intel_
 	 * bxt_a_set_seqno(), where we also do a clflush after the write. So
 	 * this clflush in practice becomes an invalidate operation.
 	 */
-
-	if (!lazy_coherency)
-		intel_flush_status_page(ring, I915_GEM_HWS_INDEX);
-
-	return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
+	intel_flush_status_page(engine, I915_GEM_HWS_INDEX);
 }
 
-static void bxt_a_set_seqno(struct intel_engine_cs *ring, u32 seqno)
+static void bxt_a_set_seqno(struct intel_engine_cs *engine, u32 seqno)
 {
-	intel_write_status_page(ring, I915_GEM_HWS_INDEX, seqno);
+	intel_write_status_page(engine, I915_GEM_HWS_INDEX, seqno);
 
 	/* See bxt_a_get_seqno() explaining the reason for the clflush. */
-	intel_flush_status_page(ring, I915_GEM_HWS_INDEX);
+	intel_flush_status_page(engine, I915_GEM_HWS_INDEX);
 }
 
 /*
@@ -1889,7 +1843,7 @@ static int gen8_emit_request(struct drm_
 	struct intel_ringbuffer *ringbuf = request->ringbuf;
 	int ret;
 
-	ret = intel_logical_ring_begin(request, 6 + WA_TAIL_DWORDS);
+	ret = intel_ring_begin(request, 6 + WA_TAIL_DWORDS);
 	if (ret)
 		return ret;
 
@@ -1899,7 +1853,7 @@ static int gen8_emit_request(struct drm_
 	intel_logical_ring_emit(ringbuf,
 				(MI_FLUSH_DW + 1) | MI_FLUSH_DW_OP_STOREDW);
 	intel_logical_ring_emit(ringbuf,
-				hws_seqno_address(request->ring) |
+				hws_seqno_address(request->engine) |
 				MI_FLUSH_DW_USE_GTT);
 	intel_logical_ring_emit(ringbuf, 0);
 	intel_logical_ring_emit(ringbuf, i915_gem_request_get_seqno(request));
@@ -1913,7 +1867,7 @@ static int gen8_emit_request_render(stru
 	struct intel_ringbuffer *ringbuf = request->ringbuf;
 	int ret;
 
-	ret = intel_logical_ring_begin(request, 8 + WA_TAIL_DWORDS);
+	ret = intel_ring_begin(request, 8 + WA_TAIL_DWORDS);
 	if (ret)
 		return ret;
 
@@ -1929,7 +1883,7 @@ static int gen8_emit_request_render(stru
 				(PIPE_CONTROL_GLOBAL_GTT_IVB |
 				 PIPE_CONTROL_CS_STALL |
 				 PIPE_CONTROL_QW_WRITE));
-	intel_logical_ring_emit(ringbuf, hws_seqno_address(request->ring));
+	intel_logical_ring_emit(ringbuf, hws_seqno_address(request->engine));
 	intel_logical_ring_emit(ringbuf, 0);
 	intel_logical_ring_emit(ringbuf, i915_gem_request_get_seqno(request));
 	/* We're thrashing one dword of HWS. */
@@ -1944,19 +1898,19 @@ static int intel_lr_context_render_state
 	struct render_state so;
 	int ret;
 
-	ret = i915_gem_render_state_prepare(req->ring, &so);
+	ret = i915_gem_render_state_prepare(req->engine, &so);
 	if (ret)
 		return ret;
 
 	if (so.rodata == NULL)
 		return 0;
 
-	ret = req->ring->emit_bb_start(req, so.ggtt_offset,
+	ret = req->engine->emit_bb_start(req, so.ggtt_offset,
 				       I915_DISPATCH_SECURE);
 	if (ret)
 		goto out;
 
-	ret = req->ring->emit_bb_start(req,
+	ret = req->engine->emit_bb_start(req,
 				       (so.ggtt_offset + so.aux_batch_offset),
 				       I915_DISPATCH_SECURE);
 	if (ret)
@@ -1994,146 +1948,197 @@ static int gen8_init_rcs_context(struct
  * @ring: Engine Command Streamer.
  *
  */
-void intel_logical_ring_cleanup(struct intel_engine_cs *ring)
+void intel_logical_ring_cleanup(struct intel_engine_cs *engine)
 {
 	struct drm_i915_private *dev_priv;
 
-	if (!intel_ring_initialized(ring))
+	if (!intel_engine_initialized(engine))
 		return;
 
-	dev_priv = ring->dev->dev_private;
+	/*
+	 * Tasklet cannot be active at this point due intel_mark_active/idle
+	 * so this is just for documentation.
+	 */
+	if (WARN_ON(test_bit(TASKLET_STATE_SCHED, &engine->irq_tasklet.state)))
+		tasklet_kill(&engine->irq_tasklet);
 
-	if (ring->buffer) {
-		intel_logical_ring_stop(ring);
-		WARN_ON((I915_READ_MODE(ring) & MODE_IDLE) == 0);
+	dev_priv = engine->dev->dev_private;
+
+	if (engine->buffer) {
+		intel_logical_ring_stop(engine);
+		WARN_ON((I915_READ_MODE(engine) & MODE_IDLE) == 0);
 	}
 
-	if (ring->cleanup)
-		ring->cleanup(ring);
+	if (engine->cleanup)
+		engine->cleanup(engine);
 
-	i915_cmd_parser_fini_ring(ring);
-	i915_gem_batch_pool_fini(&ring->batch_pool);
+	i915_cmd_parser_fini_ring(engine);
+	i915_gem_batch_pool_fini(&engine->batch_pool);
 
-	if (ring->status_page.obj) {
-		kunmap(sg_page(ring->status_page.obj->pages->sgl));
-		ring->status_page.obj = NULL;
+	if (engine->status_page.obj) {
+		i915_gem_object_unpin_map(engine->status_page.obj);
+		engine->status_page.obj = NULL;
 	}
 
-	ring->disable_lite_restore_wa = false;
-	ring->ctx_desc_template = 0;
+	engine->idle_lite_restore_wa = 0;
+	engine->disable_lite_restore_wa = false;
+	engine->ctx_desc_template = 0;
 
-	lrc_destroy_wa_ctx_obj(ring);
-	ring->dev = NULL;
+	lrc_destroy_wa_ctx_obj(engine);
+	engine->dev = NULL;
 }
 
 static void
 logical_ring_default_vfuncs(struct drm_device *dev,
-			    struct intel_engine_cs *ring)
+			    struct intel_engine_cs *engine)
 {
 	/* Default vfuncs which can be overriden by each engine. */
-	ring->init_hw = gen8_init_common_ring;
-	ring->emit_request = gen8_emit_request;
-	ring->emit_flush = gen8_emit_flush;
-	ring->irq_get = gen8_logical_ring_get_irq;
-	ring->irq_put = gen8_logical_ring_put_irq;
-	ring->emit_bb_start = gen8_emit_bb_start;
+	engine->init_hw = gen8_init_common_ring;
+	engine->emit_request = gen8_emit_request;
+	engine->emit_flush = gen8_emit_flush;
+	engine->irq_get = gen8_logical_ring_get_irq;
+	engine->irq_put = gen8_logical_ring_put_irq;
+	engine->emit_bb_start = gen8_emit_bb_start;
+	engine->get_seqno = gen8_get_seqno;
+	engine->set_seqno = gen8_set_seqno;
 	if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) {
-		ring->get_seqno = bxt_a_get_seqno;
-		ring->set_seqno = bxt_a_set_seqno;
-	} else {
-		ring->get_seqno = gen8_get_seqno;
-		ring->set_seqno = gen8_set_seqno;
+		engine->irq_seqno_barrier = bxt_a_seqno_barrier;
+		engine->set_seqno = bxt_a_set_seqno;
 	}
 }
 
 static inline void
-logical_ring_default_irqs(struct intel_engine_cs *ring, unsigned shift)
+logical_ring_default_irqs(struct intel_engine_cs *engine, unsigned shift)
 {
-	ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT << shift;
-	ring->irq_keep_mask = GT_CONTEXT_SWITCH_INTERRUPT << shift;
+	engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT << shift;
+	engine->irq_keep_mask = GT_CONTEXT_SWITCH_INTERRUPT << shift;
 }
 
 static int
-logical_ring_init(struct drm_device *dev, struct intel_engine_cs *ring)
+lrc_setup_hws(struct intel_engine_cs *engine,
+	      struct drm_i915_gem_object *dctx_obj)
 {
-	struct intel_context *dctx = to_i915(dev)->kernel_context;
+	void *hws;
+
+	/* The HWSP is part of the default context object in LRC mode. */
+	engine->status_page.gfx_addr = i915_gem_obj_ggtt_offset(dctx_obj) +
+				       LRC_PPHWSP_PN * PAGE_SIZE;
+	hws = i915_gem_object_pin_map(dctx_obj);
+	if (IS_ERR(hws))
+		return PTR_ERR(hws);
+	engine->status_page.page_addr = hws + LRC_PPHWSP_PN * PAGE_SIZE;
+	engine->status_page.obj = dctx_obj;
+
+	return 0;
+}
+
+static int
+logical_ring_init(struct drm_device *dev, struct intel_engine_cs *engine)
+{
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct intel_context *dctx = dev_priv->kernel_context;
+	enum forcewake_domains fw_domains;
 	int ret;
 
 	/* Intentionally left blank. */
-	ring->buffer = NULL;
+	engine->buffer = NULL;
 
-	ring->dev = dev;
-	INIT_LIST_HEAD(&ring->active_list);
-	INIT_LIST_HEAD(&ring->request_list);
-	i915_gem_batch_pool_init(dev, &ring->batch_pool);
-	init_waitqueue_head(&ring->irq_queue);
+	engine->dev = dev;
+	INIT_LIST_HEAD(&engine->active_list);
+	INIT_LIST_HEAD(&engine->request_list);
+	i915_gem_batch_pool_init(dev, &engine->batch_pool);
+	init_waitqueue_head(&engine->irq_queue);
 
-	INIT_LIST_HEAD(&ring->buffers);
-	INIT_LIST_HEAD(&ring->execlist_queue);
-	INIT_LIST_HEAD(&ring->execlist_retired_req_list);
-	spin_lock_init(&ring->execlist_lock);
+	INIT_LIST_HEAD(&engine->buffers);
+	INIT_LIST_HEAD(&engine->execlist_queue);
+	INIT_LIST_HEAD(&engine->execlist_retired_req_list);
+	spin_lock_init(&engine->execlist_lock);
 
-	logical_ring_init_platform_invariants(ring);
+	tasklet_init(&engine->irq_tasklet,
+		     intel_lrc_irq_handler, (unsigned long)engine);
 
-	ret = i915_cmd_parser_init_ring(ring);
+	logical_ring_init_platform_invariants(engine);
+
+	fw_domains = intel_uncore_forcewake_for_reg(dev_priv,
+						    RING_ELSP(engine),
+						    FW_REG_WRITE);
+
+	fw_domains |= intel_uncore_forcewake_for_reg(dev_priv,
+						     RING_CONTEXT_STATUS_PTR(engine),
+						     FW_REG_READ | FW_REG_WRITE);
+
+	fw_domains |= intel_uncore_forcewake_for_reg(dev_priv,
+						     RING_CONTEXT_STATUS_BUF_BASE(engine),
+						     FW_REG_READ);
+
+	engine->fw_domains = fw_domains;
+
+	ret = i915_cmd_parser_init_ring(engine);
 	if (ret)
 		goto error;
 
-	ret = intel_lr_context_deferred_alloc(dctx, ring);
+	ret = intel_lr_context_deferred_alloc(dctx, engine);
 	if (ret)
 		goto error;
 
 	/* As this is the default context, always pin it */
-	ret = intel_lr_context_do_pin(dctx, ring);
+	ret = intel_lr_context_do_pin(dctx, engine);
 	if (ret) {
 		DRM_ERROR(
 			"Failed to pin and map ringbuffer %s: %d\n",
-			ring->name, ret);
+			engine->name, ret);
+		goto error;
+	}
+
+	/* And setup the hardware status page. */
+	ret = lrc_setup_hws(engine, dctx->engine[engine->id].state);
+	if (ret) {
+		DRM_ERROR("Failed to set up hws %s: %d\n", engine->name, ret);
 		goto error;
 	}
 
 	return 0;
 
 error:
-	intel_logical_ring_cleanup(ring);
+	intel_logical_ring_cleanup(engine);
 	return ret;
 }
 
 static int logical_render_ring_init(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring = &dev_priv->ring[RCS];
+	struct intel_engine_cs *engine = &dev_priv->engine[RCS];
 	int ret;
 
-	ring->name = "render ring";
-	ring->id = RCS;
-	ring->exec_id = I915_EXEC_RENDER;
-	ring->guc_id = GUC_RENDER_ENGINE;
-	ring->mmio_base = RENDER_RING_BASE;
+	engine->name = "render ring";
+	engine->id = RCS;
+	engine->exec_id = I915_EXEC_RENDER;
+	engine->guc_id = GUC_RENDER_ENGINE;
+	engine->mmio_base = RENDER_RING_BASE;
 
-	logical_ring_default_irqs(ring, GEN8_RCS_IRQ_SHIFT);
+	logical_ring_default_irqs(engine, GEN8_RCS_IRQ_SHIFT);
 	if (HAS_L3_DPF(dev))
-		ring->irq_keep_mask |= GT_RENDER_L3_PARITY_ERROR_INTERRUPT;
+		engine->irq_keep_mask |= GT_RENDER_L3_PARITY_ERROR_INTERRUPT;
 
-	logical_ring_default_vfuncs(dev, ring);
+	logical_ring_default_vfuncs(dev, engine);
 
 	/* Override some for render ring. */
 	if (INTEL_INFO(dev)->gen >= 9)
-		ring->init_hw = gen9_init_render_ring;
+		engine->init_hw = gen9_init_render_ring;
 	else
-		ring->init_hw = gen8_init_render_ring;
-	ring->init_context = gen8_init_rcs_context;
-	ring->cleanup = intel_fini_pipe_control;
-	ring->emit_flush = gen8_emit_flush_render;
-	ring->emit_request = gen8_emit_request_render;
+		engine->init_hw = gen8_init_render_ring;
+	engine->init_context = gen8_init_rcs_context;
+	engine->cleanup = intel_fini_pipe_control;
+	engine->emit_flush = gen8_emit_flush_render;
+	engine->emit_request = gen8_emit_request_render;
 
-	ring->dev = dev;
+	engine->dev = dev;
 
-	ret = intel_init_pipe_control(ring);
+	ret = intel_init_pipe_control(engine);
 	if (ret)
 		return ret;
 
-	ret = intel_init_workaround_bb(ring);
+	ret = intel_init_workaround_bb(engine);
 	if (ret) {
 		/*
 		 * We continue even if we fail to initialize WA batch
@@ -2144,9 +2149,9 @@ static int logical_render_ring_init(stru
 			  ret);
 	}
 
-	ret = logical_ring_init(dev, ring);
+	ret = logical_ring_init(dev, engine);
 	if (ret) {
-		lrc_destroy_wa_ctx_obj(ring);
+		lrc_destroy_wa_ctx_obj(engine);
 	}
 
 	return ret;
@@ -2155,69 +2160,69 @@ static int logical_render_ring_init(stru
 static int logical_bsd_ring_init(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring = &dev_priv->ring[VCS];
+	struct intel_engine_cs *engine = &dev_priv->engine[VCS];
 
-	ring->name = "bsd ring";
-	ring->id = VCS;
-	ring->exec_id = I915_EXEC_BSD;
-	ring->guc_id = GUC_VIDEO_ENGINE;
-	ring->mmio_base = GEN6_BSD_RING_BASE;
+	engine->name = "bsd ring";
+	engine->id = VCS;
+	engine->exec_id = I915_EXEC_BSD;
+	engine->guc_id = GUC_VIDEO_ENGINE;
+	engine->mmio_base = GEN6_BSD_RING_BASE;
 
-	logical_ring_default_irqs(ring, GEN8_VCS1_IRQ_SHIFT);
-	logical_ring_default_vfuncs(dev, ring);
+	logical_ring_default_irqs(engine, GEN8_VCS1_IRQ_SHIFT);
+	logical_ring_default_vfuncs(dev, engine);
 
-	return logical_ring_init(dev, ring);
+	return logical_ring_init(dev, engine);
 }
 
 static int logical_bsd2_ring_init(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring = &dev_priv->ring[VCS2];
+	struct intel_engine_cs *engine = &dev_priv->engine[VCS2];
 
-	ring->name = "bsd2 ring";
-	ring->id = VCS2;
-	ring->exec_id = I915_EXEC_BSD;
-	ring->guc_id = GUC_VIDEO_ENGINE2;
-	ring->mmio_base = GEN8_BSD2_RING_BASE;
+	engine->name = "bsd2 ring";
+	engine->id = VCS2;
+	engine->exec_id = I915_EXEC_BSD;
+	engine->guc_id = GUC_VIDEO_ENGINE2;
+	engine->mmio_base = GEN8_BSD2_RING_BASE;
 
-	logical_ring_default_irqs(ring, GEN8_VCS2_IRQ_SHIFT);
-	logical_ring_default_vfuncs(dev, ring);
+	logical_ring_default_irqs(engine, GEN8_VCS2_IRQ_SHIFT);
+	logical_ring_default_vfuncs(dev, engine);
 
-	return logical_ring_init(dev, ring);
+	return logical_ring_init(dev, engine);
 }
 
 static int logical_blt_ring_init(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring = &dev_priv->ring[BCS];
+	struct intel_engine_cs *engine = &dev_priv->engine[BCS];
 
-	ring->name = "blitter ring";
-	ring->id = BCS;
-	ring->exec_id = I915_EXEC_BLT;
-	ring->guc_id = GUC_BLITTER_ENGINE;
-	ring->mmio_base = BLT_RING_BASE;
+	engine->name = "blitter ring";
+	engine->id = BCS;
+	engine->exec_id = I915_EXEC_BLT;
+	engine->guc_id = GUC_BLITTER_ENGINE;
+	engine->mmio_base = BLT_RING_BASE;
 
-	logical_ring_default_irqs(ring, GEN8_BCS_IRQ_SHIFT);
-	logical_ring_default_vfuncs(dev, ring);
+	logical_ring_default_irqs(engine, GEN8_BCS_IRQ_SHIFT);
+	logical_ring_default_vfuncs(dev, engine);
 
-	return logical_ring_init(dev, ring);
+	return logical_ring_init(dev, engine);
 }
 
 static int logical_vebox_ring_init(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring = &dev_priv->ring[VECS];
+	struct intel_engine_cs *engine = &dev_priv->engine[VECS];
 
-	ring->name = "video enhancement ring";
-	ring->id = VECS;
-	ring->exec_id = I915_EXEC_VEBOX;
-	ring->guc_id = GUC_VIDEOENHANCE_ENGINE;
-	ring->mmio_base = VEBOX_RING_BASE;
+	engine->name = "video enhancement ring";
+	engine->id = VECS;
+	engine->exec_id = I915_EXEC_VEBOX;
+	engine->guc_id = GUC_VIDEOENHANCE_ENGINE;
+	engine->mmio_base = VEBOX_RING_BASE;
 
-	logical_ring_default_irqs(ring, GEN8_VECS_IRQ_SHIFT);
-	logical_ring_default_vfuncs(dev, ring);
+	logical_ring_default_irqs(engine, GEN8_VECS_IRQ_SHIFT);
+	logical_ring_default_vfuncs(dev, engine);
 
-	return logical_ring_init(dev, ring);
+	return logical_ring_init(dev, engine);
 }
 
 /**
@@ -2225,7 +2230,7 @@ static int logical_vebox_ring_init(struc
  * @dev: DRM device.
  *
  * This function inits the engines for an Execlists submission style (the equivalent in the
- * legacy ringbuffer submission world would be i915_gem_init_rings). It does it only for
+ * legacy ringbuffer submission world would be i915_gem_init_engines). It does it only for
  * those engines that are present in the hardware.
  *
  * Return: non-zero if the initialization failed.
@@ -2266,13 +2271,13 @@ int intel_logical_rings_init(struct drm_
 	return 0;
 
 cleanup_vebox_ring:
-	intel_logical_ring_cleanup(&dev_priv->ring[VECS]);
+	intel_logical_ring_cleanup(&dev_priv->engine[VECS]);
 cleanup_blt_ring:
-	intel_logical_ring_cleanup(&dev_priv->ring[BCS]);
+	intel_logical_ring_cleanup(&dev_priv->engine[BCS]);
 cleanup_bsd_ring:
-	intel_logical_ring_cleanup(&dev_priv->ring[VCS]);
+	intel_logical_ring_cleanup(&dev_priv->engine[VCS]);
 cleanup_render_ring:
-	intel_logical_ring_cleanup(&dev_priv->ring[RCS]);
+	intel_logical_ring_cleanup(&dev_priv->engine[RCS]);
 
 	return ret;
 }
@@ -2320,13 +2325,13 @@ make_rpcs(struct drm_device *dev)
 	return rpcs;
 }
 
-static u32 intel_lr_indirect_ctx_offset(struct intel_engine_cs *ring)
+static u32 intel_lr_indirect_ctx_offset(struct intel_engine_cs *engine)
 {
 	u32 indirect_ctx_offset;
 
-	switch (INTEL_INFO(ring->dev)->gen) {
+	switch (INTEL_INFO(engine->dev)->gen) {
 	default:
-		MISSING_CASE(INTEL_INFO(ring->dev)->gen);
+		MISSING_CASE(INTEL_INFO(engine->dev)->gen);
 		/* fall through */
 	case 9:
 		indirect_ctx_offset =
@@ -2342,14 +2347,16 @@ static u32 intel_lr_indirect_ctx_offset(
 }
 
 static int
-populate_lr_context(struct intel_context *ctx, struct drm_i915_gem_object *ctx_obj,
-		    struct intel_engine_cs *ring, struct intel_ringbuffer *ringbuf)
+populate_lr_context(struct intel_context *ctx,
+		    struct drm_i915_gem_object *ctx_obj,
+		    struct intel_engine_cs *engine,
+		    struct intel_ringbuffer *ringbuf)
 {
-	struct drm_device *dev = ring->dev;
+	struct drm_device *dev = engine->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct i915_hw_ppgtt *ppgtt = ctx->ppgtt;
-	struct page *page;
-	uint32_t *reg_state;
+	void *vaddr;
+	u32 *reg_state;
 	int ret;
 
 	if (!ppgtt)
@@ -2361,18 +2368,17 @@ populate_lr_context(struct intel_context
 		return ret;
 	}
 
-	ret = i915_gem_object_get_pages(ctx_obj);
-	if (ret) {
-		DRM_DEBUG_DRIVER("Could not get object pages\n");
+	vaddr = i915_gem_object_pin_map(ctx_obj);
+	if (IS_ERR(vaddr)) {
+		ret = PTR_ERR(vaddr);
+		DRM_DEBUG_DRIVER("Could not map object pages! (%d)\n", ret);
 		return ret;
 	}
-
-	i915_gem_object_pin_pages(ctx_obj);
+	ctx_obj->dirty = true;
 
 	/* The second page of the context object contains some fields which must
 	 * be set up prior to the first execution. */
-	page = i915_gem_object_get_dirty_page(ctx_obj, LRC_STATE_PN);
-	reg_state = kmap_atomic(page);
+	reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE;
 
 	/* A context is actually a big batch buffer with several MI_LOAD_REGISTER_IMM
 	 * commands followed by (reg, value) pairs. The values we are setting here are
@@ -2380,33 +2386,47 @@ populate_lr_context(struct intel_context
 	 * recreate this batchbuffer with new values (including all the missing
 	 * MI_LOAD_REGISTER_IMM commands that we are not initializing here). */
 	reg_state[CTX_LRI_HEADER_0] =
-		MI_LOAD_REGISTER_IMM(ring->id == RCS ? 14 : 11) | MI_LRI_FORCE_POSTED;
-	ASSIGN_CTX_REG(reg_state, CTX_CONTEXT_CONTROL, RING_CONTEXT_CONTROL(ring),
+		MI_LOAD_REGISTER_IMM(engine->id == RCS ? 14 : 11) | MI_LRI_FORCE_POSTED;
+	ASSIGN_CTX_REG(reg_state, CTX_CONTEXT_CONTROL,
+		       RING_CONTEXT_CONTROL(engine),
 		       _MASKED_BIT_ENABLE(CTX_CTRL_INHIBIT_SYN_CTX_SWITCH |
 					  CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT |
 					  (HAS_RESOURCE_STREAMER(dev) ?
 					    CTX_CTRL_RS_CTX_ENABLE : 0)));
-	ASSIGN_CTX_REG(reg_state, CTX_RING_HEAD, RING_HEAD(ring->mmio_base), 0);
-	ASSIGN_CTX_REG(reg_state, CTX_RING_TAIL, RING_TAIL(ring->mmio_base), 0);
+	ASSIGN_CTX_REG(reg_state, CTX_RING_HEAD, RING_HEAD(engine->mmio_base),
+		       0);
+	ASSIGN_CTX_REG(reg_state, CTX_RING_TAIL, RING_TAIL(engine->mmio_base),
+		       0);
 	/* Ring buffer start address is not known until the buffer is pinned.
 	 * It is written to the context image in execlists_update_context()
 	 */
-	ASSIGN_CTX_REG(reg_state, CTX_RING_BUFFER_START, RING_START(ring->mmio_base), 0);
-	ASSIGN_CTX_REG(reg_state, CTX_RING_BUFFER_CONTROL, RING_CTL(ring->mmio_base),
+	ASSIGN_CTX_REG(reg_state, CTX_RING_BUFFER_START,
+		       RING_START(engine->mmio_base), 0);
+	ASSIGN_CTX_REG(reg_state, CTX_RING_BUFFER_CONTROL,
+		       RING_CTL(engine->mmio_base),
 		       ((ringbuf->size - PAGE_SIZE) & RING_NR_PAGES) | RING_VALID);
-	ASSIGN_CTX_REG(reg_state, CTX_BB_HEAD_U, RING_BBADDR_UDW(ring->mmio_base), 0);
-	ASSIGN_CTX_REG(reg_state, CTX_BB_HEAD_L, RING_BBADDR(ring->mmio_base), 0);
-	ASSIGN_CTX_REG(reg_state, CTX_BB_STATE, RING_BBSTATE(ring->mmio_base),
+	ASSIGN_CTX_REG(reg_state, CTX_BB_HEAD_U,
+		       RING_BBADDR_UDW(engine->mmio_base), 0);
+	ASSIGN_CTX_REG(reg_state, CTX_BB_HEAD_L,
+		       RING_BBADDR(engine->mmio_base), 0);
+	ASSIGN_CTX_REG(reg_state, CTX_BB_STATE,
+		       RING_BBSTATE(engine->mmio_base),
 		       RING_BB_PPGTT);
-	ASSIGN_CTX_REG(reg_state, CTX_SECOND_BB_HEAD_U, RING_SBBADDR_UDW(ring->mmio_base), 0);
-	ASSIGN_CTX_REG(reg_state, CTX_SECOND_BB_HEAD_L, RING_SBBADDR(ring->mmio_base), 0);
-	ASSIGN_CTX_REG(reg_state, CTX_SECOND_BB_STATE, RING_SBBSTATE(ring->mmio_base), 0);
-	if (ring->id == RCS) {
-		ASSIGN_CTX_REG(reg_state, CTX_BB_PER_CTX_PTR, RING_BB_PER_CTX_PTR(ring->mmio_base), 0);
-		ASSIGN_CTX_REG(reg_state, CTX_RCS_INDIRECT_CTX, RING_INDIRECT_CTX(ring->mmio_base), 0);
-		ASSIGN_CTX_REG(reg_state, CTX_RCS_INDIRECT_CTX_OFFSET, RING_INDIRECT_CTX_OFFSET(ring->mmio_base), 0);
-		if (ring->wa_ctx.obj) {
-			struct i915_ctx_workarounds *wa_ctx = &ring->wa_ctx;
+	ASSIGN_CTX_REG(reg_state, CTX_SECOND_BB_HEAD_U,
+		       RING_SBBADDR_UDW(engine->mmio_base), 0);
+	ASSIGN_CTX_REG(reg_state, CTX_SECOND_BB_HEAD_L,
+		       RING_SBBADDR(engine->mmio_base), 0);
+	ASSIGN_CTX_REG(reg_state, CTX_SECOND_BB_STATE,
+		       RING_SBBSTATE(engine->mmio_base), 0);
+	if (engine->id == RCS) {
+		ASSIGN_CTX_REG(reg_state, CTX_BB_PER_CTX_PTR,
+			       RING_BB_PER_CTX_PTR(engine->mmio_base), 0);
+		ASSIGN_CTX_REG(reg_state, CTX_RCS_INDIRECT_CTX,
+			       RING_INDIRECT_CTX(engine->mmio_base), 0);
+		ASSIGN_CTX_REG(reg_state, CTX_RCS_INDIRECT_CTX_OFFSET,
+			       RING_INDIRECT_CTX_OFFSET(engine->mmio_base), 0);
+		if (engine->wa_ctx.obj) {
+			struct i915_ctx_workarounds *wa_ctx = &engine->wa_ctx;
 			uint32_t ggtt_offset = i915_gem_obj_ggtt_offset(wa_ctx->obj);
 
 			reg_state[CTX_RCS_INDIRECT_CTX+1] =
@@ -2414,7 +2434,7 @@ populate_lr_context(struct intel_context
 				(wa_ctx->indirect_ctx.size / CACHELINE_DWORDS);
 
 			reg_state[CTX_RCS_INDIRECT_CTX_OFFSET+1] =
-				intel_lr_indirect_ctx_offset(ring) << 6;
+				intel_lr_indirect_ctx_offset(engine) << 6;
 
 			reg_state[CTX_BB_PER_CTX_PTR+1] =
 				(ggtt_offset + wa_ctx->per_ctx.offset * sizeof(uint32_t)) |
@@ -2422,16 +2442,25 @@ populate_lr_context(struct intel_context
 		}
 	}
 	reg_state[CTX_LRI_HEADER_1] = MI_LOAD_REGISTER_IMM(9) | MI_LRI_FORCE_POSTED;
-	ASSIGN_CTX_REG(reg_state, CTX_CTX_TIMESTAMP, RING_CTX_TIMESTAMP(ring->mmio_base), 0);
+	ASSIGN_CTX_REG(reg_state, CTX_CTX_TIMESTAMP,
+		       RING_CTX_TIMESTAMP(engine->mmio_base), 0);
 	/* PDP values well be assigned later if needed */
-	ASSIGN_CTX_REG(reg_state, CTX_PDP3_UDW, GEN8_RING_PDP_UDW(ring, 3), 0);
-	ASSIGN_CTX_REG(reg_state, CTX_PDP3_LDW, GEN8_RING_PDP_LDW(ring, 3), 0);
-	ASSIGN_CTX_REG(reg_state, CTX_PDP2_UDW, GEN8_RING_PDP_UDW(ring, 2), 0);
-	ASSIGN_CTX_REG(reg_state, CTX_PDP2_LDW, GEN8_RING_PDP_LDW(ring, 2), 0);
-	ASSIGN_CTX_REG(reg_state, CTX_PDP1_UDW, GEN8_RING_PDP_UDW(ring, 1), 0);
-	ASSIGN_CTX_REG(reg_state, CTX_PDP1_LDW, GEN8_RING_PDP_LDW(ring, 1), 0);
-	ASSIGN_CTX_REG(reg_state, CTX_PDP0_UDW, GEN8_RING_PDP_UDW(ring, 0), 0);
-	ASSIGN_CTX_REG(reg_state, CTX_PDP0_LDW, GEN8_RING_PDP_LDW(ring, 0), 0);
+	ASSIGN_CTX_REG(reg_state, CTX_PDP3_UDW, GEN8_RING_PDP_UDW(engine, 3),
+		       0);
+	ASSIGN_CTX_REG(reg_state, CTX_PDP3_LDW, GEN8_RING_PDP_LDW(engine, 3),
+		       0);
+	ASSIGN_CTX_REG(reg_state, CTX_PDP2_UDW, GEN8_RING_PDP_UDW(engine, 2),
+		       0);
+	ASSIGN_CTX_REG(reg_state, CTX_PDP2_LDW, GEN8_RING_PDP_LDW(engine, 2),
+		       0);
+	ASSIGN_CTX_REG(reg_state, CTX_PDP1_UDW, GEN8_RING_PDP_UDW(engine, 1),
+		       0);
+	ASSIGN_CTX_REG(reg_state, CTX_PDP1_LDW, GEN8_RING_PDP_LDW(engine, 1),
+		       0);
+	ASSIGN_CTX_REG(reg_state, CTX_PDP0_UDW, GEN8_RING_PDP_UDW(engine, 0),
+		       0);
+	ASSIGN_CTX_REG(reg_state, CTX_PDP0_LDW, GEN8_RING_PDP_LDW(engine, 0),
+		       0);
 
 	if (USES_FULL_48BIT_PPGTT(ppgtt->base.dev)) {
 		/* 64b PPGTT (48bit canonical)
@@ -2445,20 +2474,16 @@ populate_lr_context(struct intel_context
 		 * With dynamic page allocation, PDPs may not be allocated at
 		 * this point. Point the unallocated PDPs to the scratch page
 		 */
-		ASSIGN_CTX_PDP(ppgtt, reg_state, 3);
-		ASSIGN_CTX_PDP(ppgtt, reg_state, 2);
-		ASSIGN_CTX_PDP(ppgtt, reg_state, 1);
-		ASSIGN_CTX_PDP(ppgtt, reg_state, 0);
+		execlists_update_context_pdps(ppgtt, reg_state);
 	}
 
-	if (ring->id == RCS) {
+	if (engine->id == RCS) {
 		reg_state[CTX_LRI_HEADER_2] = MI_LOAD_REGISTER_IMM(1);
 		ASSIGN_CTX_REG(reg_state, CTX_R_PWR_CLK_STATE, GEN8_R_PWR_CLK_STATE,
 			       make_rpcs(dev));
 	}
 
-	kunmap_atomic(reg_state);
-	i915_gem_object_unpin_pages(ctx_obj);
+	i915_gem_object_unpin_map(ctx_obj);
 
 	return 0;
 }
@@ -2475,7 +2500,7 @@ void intel_lr_context_free(struct intel_
 {
 	int i;
 
-	for (i = I915_NUM_RINGS; --i >= 0; ) {
+	for (i = I915_NUM_ENGINES; --i >= 0; ) {
 		struct intel_ringbuffer *ringbuf = ctx->engine[i].ringbuf;
 		struct drm_i915_gem_object *ctx_obj = ctx->engine[i].state;
 
@@ -2485,6 +2510,7 @@ void intel_lr_context_free(struct intel_
 		if (ctx == ctx->i915->kernel_context) {
 			intel_unpin_ringbuffer_obj(ringbuf);
 			i915_gem_object_ggtt_unpin(ctx_obj);
+			i915_gem_object_unpin_map(ctx_obj);
 		}
 
 		WARN_ON(ctx->engine[i].pin_count);
@@ -2507,15 +2533,15 @@ void intel_lr_context_free(struct intel_
  * in LRC mode, but does not include the "shared data page" used with
  * GuC submission. The caller should account for this if using the GuC.
  */
-uint32_t intel_lr_context_size(struct intel_engine_cs *ring)
+uint32_t intel_lr_context_size(struct intel_engine_cs *engine)
 {
 	int ret = 0;
 
-	WARN_ON(INTEL_INFO(ring->dev)->gen < 8);
+	WARN_ON(INTEL_INFO(engine->dev)->gen < 8);
 
-	switch (ring->id) {
+	switch (engine->id) {
 	case RCS:
-		if (INTEL_INFO(ring->dev)->gen >= 9)
+		if (INTEL_INFO(engine->dev)->gen >= 9)
 			ret = GEN9_LR_CONTEXT_RENDER_SIZE;
 		else
 			ret = GEN8_LR_CONTEXT_RENDER_SIZE;
@@ -2531,24 +2557,6 @@ uint32_t intel_lr_context_size(struct in
 	return ret;
 }
 
-static void lrc_setup_hardware_status_page(struct intel_engine_cs *ring,
-		struct drm_i915_gem_object *default_ctx_obj)
-{
-	struct drm_i915_private *dev_priv = ring->dev->dev_private;
-	struct page *page;
-
-	/* The HWSP is part of the default context object in LRC mode. */
-	ring->status_page.gfx_addr = i915_gem_obj_ggtt_offset(default_ctx_obj)
-			+ LRC_PPHWSP_PN * PAGE_SIZE;
-	page = i915_gem_object_get_page(default_ctx_obj, LRC_PPHWSP_PN);
-	ring->status_page.page_addr = kmap(page);
-	ring->status_page.obj = default_ctx_obj;
-
-	I915_WRITE(RING_HWS_PGA(ring->mmio_base),
-			(u32)ring->status_page.gfx_addr);
-	POSTING_READ(RING_HWS_PGA(ring->mmio_base));
-}
-
 /**
  * intel_lr_context_deferred_alloc() - create the LRC specific bits of a context
  * @ctx: LR context to create.
@@ -2564,18 +2572,18 @@ static void lrc_setup_hardware_status_pa
  */
 
 int intel_lr_context_deferred_alloc(struct intel_context *ctx,
-				    struct intel_engine_cs *ring)
+				    struct intel_engine_cs *engine)
 {
-	struct drm_device *dev = ring->dev;
+	struct drm_device *dev = engine->dev;
 	struct drm_i915_gem_object *ctx_obj;
 	uint32_t context_size;
 	struct intel_ringbuffer *ringbuf;
 	int ret;
 
 	WARN_ON(ctx->legacy_hw_ctx.rcs_state != NULL);
-	WARN_ON(ctx->engine[ring->id].state);
+	WARN_ON(ctx->engine[engine->id].state);
 
-	context_size = round_up(intel_lr_context_size(ring), 4096);
+	context_size = round_up(intel_lr_context_size(engine), 4096);
 
 	/* One extra page as the sharing data between driver and GuC */
 	context_size += PAGE_SIZE * LRC_PPHWSP_PN;
@@ -2586,39 +2594,38 @@ int intel_lr_context_deferred_alloc(stru
 		return -ENOMEM;
 	}
 
-	ringbuf = intel_engine_create_ringbuffer(ring, 4 * PAGE_SIZE);
+	ringbuf = intel_engine_create_ringbuffer(engine, 4 * PAGE_SIZE);
 	if (IS_ERR(ringbuf)) {
 		ret = PTR_ERR(ringbuf);
 		goto error_deref_obj;
 	}
 
-	ret = populate_lr_context(ctx, ctx_obj, ring, ringbuf);
+	ret = populate_lr_context(ctx, ctx_obj, engine, ringbuf);
 	if (ret) {
 		DRM_DEBUG_DRIVER("Failed to populate LRC: %d\n", ret);
 		goto error_ringbuf;
 	}
 
-	ctx->engine[ring->id].ringbuf = ringbuf;
-	ctx->engine[ring->id].state = ctx_obj;
+	ctx->engine[engine->id].ringbuf = ringbuf;
+	ctx->engine[engine->id].state = ctx_obj;
 
-	if (ctx != ctx->i915->kernel_context && ring->init_context) {
+	if (ctx != ctx->i915->kernel_context && engine->init_context) {
 		struct drm_i915_gem_request *req;
 
-		req = i915_gem_request_alloc(ring, ctx);
+		req = i915_gem_request_alloc(engine, ctx);
 		if (IS_ERR(req)) {
 			ret = PTR_ERR(req);
 			DRM_ERROR("ring create req: %d\n", ret);
 			goto error_ringbuf;
 		}
 
-		ret = ring->init_context(req);
+		ret = engine->init_context(req);
+		i915_add_request_no_flush(req);
 		if (ret) {
 			DRM_ERROR("ring init context: %d\n",
 				ret);
-			i915_gem_request_cancel(req);
 			goto error_ringbuf;
 		}
-		i915_add_request_no_flush(req);
 	}
 	return 0;
 
@@ -2626,40 +2633,38 @@ error_ringbuf:
 	intel_ringbuffer_free(ringbuf);
 error_deref_obj:
 	drm_gem_object_unreference(&ctx_obj->base);
-	ctx->engine[ring->id].ringbuf = NULL;
-	ctx->engine[ring->id].state = NULL;
+	ctx->engine[engine->id].ringbuf = NULL;
+	ctx->engine[engine->id].state = NULL;
 	return ret;
 }
 
-void intel_lr_context_reset(struct drm_device *dev,
-			struct intel_context *ctx)
+void intel_lr_context_reset(struct drm_i915_private *dev_priv,
+			    struct intel_context *ctx)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring;
-	int i;
+	struct intel_engine_cs *engine;
 
-	for_each_ring(ring, dev_priv, i) {
+	for_each_engine(engine, dev_priv) {
 		struct drm_i915_gem_object *ctx_obj =
-				ctx->engine[ring->id].state;
+				ctx->engine[engine->id].state;
 		struct intel_ringbuffer *ringbuf =
-				ctx->engine[ring->id].ringbuf;
+				ctx->engine[engine->id].ringbuf;
+		void *vaddr;
 		uint32_t *reg_state;
-		struct page *page;
 
 		if (!ctx_obj)
 			continue;
 
-		if (i915_gem_object_get_pages(ctx_obj)) {
-			WARN(1, "Failed get_pages for context obj\n");
+		vaddr = i915_gem_object_pin_map(ctx_obj);
+		if (WARN_ON(IS_ERR(vaddr)))
 			continue;
-		}
-		page = i915_gem_object_get_dirty_page(ctx_obj, LRC_STATE_PN);
-		reg_state = kmap_atomic(page);
+
+		reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE;
+		ctx_obj->dirty = true;
 
 		reg_state[CTX_RING_HEAD+1] = 0;
 		reg_state[CTX_RING_TAIL+1] = 0;
 
-		kunmap_atomic(reg_state);
+		i915_gem_object_unpin_map(ctx_obj);
 
 		ringbuf->head = 0;
 		ringbuf->tail = 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_lrc.h linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_lrc.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_lrc.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_lrc.h	2016-07-24 15:23:50.000000000 -0400
@@ -24,6 +24,8 @@
 #ifndef _INTEL_LRC_H_
 #define _INTEL_LRC_H_
 
+#include "intel_ringbuffer.h"
+
 #define GEN8_LR_CONTEXT_ALIGN 4096
 
 /* Execlists regs */
@@ -34,6 +36,7 @@
 #define	  CTX_CTRL_INHIBIT_SYN_CTX_SWITCH	(1 << 3)
 #define	  CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT	(1 << 0)
 #define   CTX_CTRL_RS_CTX_ENABLE                (1 << 1)
+#define RING_CONTEXT_STATUS_BUF_BASE(ring)	_MMIO((ring)->mmio_base + 0x370)
 #define RING_CONTEXT_STATUS_BUF_LO(ring, i)	_MMIO((ring)->mmio_base + 0x370 + (i) * 8)
 #define RING_CONTEXT_STATUS_BUF_HI(ring, i)	_MMIO((ring)->mmio_base + 0x370 + (i) * 8 + 4)
 #define RING_CONTEXT_STATUS_PTR(ring)		_MMIO((ring)->mmio_base + 0x3a0)
@@ -57,10 +60,9 @@
 /* Logical Rings */
 int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request);
 int intel_logical_ring_reserve_space(struct drm_i915_gem_request *request);
-void intel_logical_ring_stop(struct intel_engine_cs *ring);
-void intel_logical_ring_cleanup(struct intel_engine_cs *ring);
+void intel_logical_ring_stop(struct intel_engine_cs *engine);
+void intel_logical_ring_cleanup(struct intel_engine_cs *engine);
 int intel_logical_rings_init(struct drm_device *dev);
-int intel_logical_ring_begin(struct drm_i915_gem_request *req, int num_dwords);
 
 int logical_ring_flush_all_caches(struct drm_i915_gem_request *req);
 /**
@@ -98,18 +100,21 @@ static inline void intel_logical_ring_em
 #define LRC_STATE_PN	(LRC_PPHWSP_PN + 1)
 
 void intel_lr_context_free(struct intel_context *ctx);
-uint32_t intel_lr_context_size(struct intel_engine_cs *ring);
+uint32_t intel_lr_context_size(struct intel_engine_cs *engine);
 int intel_lr_context_deferred_alloc(struct intel_context *ctx,
-				    struct intel_engine_cs *ring);
+				    struct intel_engine_cs *engine);
 void intel_lr_context_unpin(struct intel_context *ctx,
 			    struct intel_engine_cs *engine);
-void intel_lr_context_reset(struct drm_device *dev,
-			struct intel_context *ctx);
+
+struct drm_i915_private;
+
+void intel_lr_context_reset(struct drm_i915_private *dev_priv,
+			    struct intel_context *ctx);
 uint64_t intel_lr_context_descriptor(struct intel_context *ctx,
-				     struct intel_engine_cs *ring);
+				     struct intel_engine_cs *engine);
 
 u32 intel_execlists_ctx_id(struct intel_context *ctx,
-			   struct intel_engine_cs *ring);
+			   struct intel_engine_cs *engine);
 
 /* Execlists */
 int intel_sanitize_enable_execlists(struct drm_device *dev, int enable_execlists);
@@ -118,7 +123,6 @@ int intel_execlists_submission(struct i9
 			       struct drm_i915_gem_execbuffer2 *args,
 			       struct list_head *vmas);
 
-void intel_lrc_irq_handler(struct intel_engine_cs *ring);
-void intel_execlists_retire_requests(struct intel_engine_cs *ring);
+void intel_execlists_retire_requests(struct intel_engine_cs *engine);
 
 #endif /* _INTEL_LRC_H_ */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_lvds.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_lvds.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_lvds.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_lvds.c	2016-07-24 15:23:50.000000000 -0400
@@ -109,7 +109,6 @@ static void intel_lvds_get_config(struct
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
 	u32 tmp, flags = 0;
-	int dotclock;
 
 	tmp = I915_READ(lvds_encoder->reg);
 	if (tmp & LVDS_HSYNC_POLARITY)
@@ -134,12 +133,7 @@ static void intel_lvds_get_config(struct
 		pipe_config->gmch_pfit.control |= tmp & PANEL_8TO6_DITHER_ENABLE;
 	}
 
-	dotclock = pipe_config->port_clock;
-
-	if (HAS_PCH_SPLIT(dev_priv->dev))
-		ironlake_check_encoder_dotclock(pipe_config, dotclock);
-
-	pipe_config->base.adjusted_mode.crtc_clock = dotclock;
+	pipe_config->base.adjusted_mode.crtc_clock = pipe_config->port_clock;
 }
 
 static void intel_pre_enable_lvds(struct intel_encoder *encoder)
@@ -155,7 +149,7 @@ static void intel_pre_enable_lvds(struct
 	if (HAS_PCH_SPLIT(dev)) {
 		assert_fdi_rx_pll_disabled(dev_priv, pipe);
 		assert_shared_dpll_disabled(dev_priv,
-					    intel_crtc_to_shared_dpll(crtc));
+					    crtc->config->shared_dpll);
 	} else {
 		assert_pll_disabled(dev_priv, pipe);
 	}
@@ -782,57 +776,6 @@ static const struct dmi_system_id intel_
 	{ }	/* terminating entry */
 };
 
-/*
- * Enumerate the child dev array parsed from VBT to check whether
- * the LVDS is present.
- * If it is present, return 1.
- * If it is not present, return false.
- * If no child dev is parsed from VBT, it assumes that the LVDS is present.
- */
-static bool lvds_is_present_in_vbt(struct drm_device *dev,
-				   u8 *i2c_pin)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	int i;
-
-	if (!dev_priv->vbt.child_dev_num)
-		return true;
-
-	for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
-		union child_device_config *uchild = dev_priv->vbt.child_dev + i;
-		struct old_child_dev_config *child = &uchild->old;
-
-		/* If the device type is not LFP, continue.
-		 * We have to check both the new identifiers as well as the
-		 * old for compatibility with some BIOSes.
-		 */
-		if (child->device_type != DEVICE_TYPE_INT_LFP &&
-		    child->device_type != DEVICE_TYPE_LFP)
-			continue;
-
-		if (intel_gmbus_is_valid_pin(dev_priv, child->i2c_pin))
-			*i2c_pin = child->i2c_pin;
-
-		/* However, we cannot trust the BIOS writers to populate
-		 * the VBT correctly.  Since LVDS requires additional
-		 * information from AIM blocks, a non-zero addin offset is
-		 * a good indicator that the LVDS is actually present.
-		 */
-		if (child->addin_offset)
-			return true;
-
-		/* But even then some BIOS writers perform some black magic
-		 * and instantiate the device without reference to any
-		 * additional data.  Trust that if the VBT was written into
-		 * the OpRegion then they have validated the LVDS's existence.
-		 */
-		if (dev_priv->opregion.vbt)
-			return true;
-	}
-
-	return false;
-}
-
 static int intel_dual_link_lvds_callback(const struct dmi_system_id *id)
 {
 	DRM_INFO("Forcing lvds to dual link mode on %s\n", id->ident);
@@ -982,14 +925,14 @@ void intel_lvds_init(struct drm_device *
 	if (HAS_PCH_SPLIT(dev)) {
 		if ((lvds & LVDS_DETECTED) == 0)
 			return;
-		if (dev_priv->vbt.edp_support) {
+		if (dev_priv->vbt.edp.support) {
 			DRM_DEBUG_KMS("disable LVDS for eDP support\n");
 			return;
 		}
 	}
 
 	pin = GMBUS_PIN_PANEL;
-	if (!lvds_is_present_in_vbt(dev, &pin)) {
+	if (!intel_bios_is_lvds_present(dev_priv, &pin)) {
 		if ((lvds & LVDS_PORT_EN) == 0) {
 			DRM_DEBUG_KMS("LVDS is not present in VBT\n");
 			return;
@@ -1139,6 +1082,8 @@ void intel_lvds_init(struct drm_device *
 		fixed_mode = drm_mode_duplicate(dev, dev_priv->vbt.lfp_lvds_vbt_mode);
 		if (fixed_mode) {
 			fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
+			connector->display_info.width_mm = fixed_mode->width_mm;
+			connector->display_info.height_mm = fixed_mode->height_mm;
 			goto out;
 		}
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_mocs.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_mocs.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_mocs.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_mocs.c	2016-07-24 15:23:50.000000000 -0400
@@ -128,9 +128,9 @@ static const struct drm_i915_mocs_entry
 
 /**
  * get_mocs_settings()
- * @dev:        DRM device.
+ * @dev_priv:	i915 device.
  * @table:      Output table that will be made to point at appropriate
- *              MOCS values for the device.
+ *	      MOCS values for the device.
  *
  * This function will return the values of the MOCS table that needs to
  * be programmed for the platform. It will return the values that need
@@ -138,28 +138,28 @@ static const struct drm_i915_mocs_entry
  *
  * Return: true if there are applicable MOCS settings for the device.
  */
-static bool get_mocs_settings(struct drm_device *dev,
+static bool get_mocs_settings(struct drm_i915_private *dev_priv,
 			      struct drm_i915_mocs_table *table)
 {
 	bool result = false;
 
-	if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
+	if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
 		table->size  = ARRAY_SIZE(skylake_mocs_table);
 		table->table = skylake_mocs_table;
 		result = true;
-	} else if (IS_BROXTON(dev)) {
+	} else if (IS_BROXTON(dev_priv)) {
 		table->size  = ARRAY_SIZE(broxton_mocs_table);
 		table->table = broxton_mocs_table;
 		result = true;
 	} else {
-		WARN_ONCE(INTEL_INFO(dev)->gen >= 9,
+		WARN_ONCE(INTEL_INFO(dev_priv)->gen >= 9,
 			  "Platform that should have a MOCS table does not.\n");
 	}
 
 	return result;
 }
 
-static i915_reg_t mocs_register(enum intel_ring_id ring, int index)
+static i915_reg_t mocs_register(enum intel_engine_id ring, int index)
 {
 	switch (ring) {
 	case RCS:
@@ -179,10 +179,49 @@ static i915_reg_t mocs_register(enum int
 }
 
 /**
+ * intel_mocs_init_engine() - emit the mocs control table
+ * @engine:	The engine for whom to emit the registers.
+ *
+ * This function simply emits a MI_LOAD_REGISTER_IMM command for the
+ * given table starting at the given address.
+ *
+ * Return: 0 on success, otherwise the error status.
+ */
+int intel_mocs_init_engine(struct intel_engine_cs *engine)
+{
+	struct drm_i915_private *dev_priv = to_i915(engine->dev);
+	struct drm_i915_mocs_table table;
+	unsigned int index;
+
+	if (!get_mocs_settings(dev_priv, &table))
+		return 0;
+
+	if (WARN_ON(table.size > GEN9_NUM_MOCS_ENTRIES))
+		return -ENODEV;
+
+	for (index = 0; index < table.size; index++)
+		I915_WRITE(mocs_register(engine->id, index),
+			   table.table[index].control_value);
+
+	/*
+	 * Ok, now set the unused entries to uncached. These entries
+	 * are officially undefined and no contract for the contents
+	 * and settings is given for these entries.
+	 *
+	 * Entry 0 in the table is uncached - so we are just writing
+	 * that value to all the used entries.
+	 */
+	for (; index < GEN9_NUM_MOCS_ENTRIES; index++)
+		I915_WRITE(mocs_register(engine->id, index),
+			   table.table[0].control_value);
+
+	return 0;
+}
+
+/**
  * emit_mocs_control_table() - emit the mocs control table
  * @req:	Request to set up the MOCS table for.
  * @table:	The values to program into the control regs.
- * @ring:	The engine for whom to emit the registers.
  *
  * This function simply emits a MI_LOAD_REGISTER_IMM command for the
  * given table starting at the given address.
@@ -190,27 +229,26 @@ static i915_reg_t mocs_register(enum int
  * Return: 0 on success, otherwise the error status.
  */
 static int emit_mocs_control_table(struct drm_i915_gem_request *req,
-				   const struct drm_i915_mocs_table *table,
-				   enum intel_ring_id ring)
+				   const struct drm_i915_mocs_table *table)
 {
 	struct intel_ringbuffer *ringbuf = req->ringbuf;
+	enum intel_engine_id engine = req->engine->id;
 	unsigned int index;
 	int ret;
 
 	if (WARN_ON(table->size > GEN9_NUM_MOCS_ENTRIES))
 		return -ENODEV;
 
-	ret = intel_logical_ring_begin(req, 2 + 2 * GEN9_NUM_MOCS_ENTRIES);
-	if (ret) {
-		DRM_DEBUG("intel_logical_ring_begin failed %d\n", ret);
+	ret = intel_ring_begin(req, 2 + 2 * GEN9_NUM_MOCS_ENTRIES);
+	if (ret)
 		return ret;
-	}
 
 	intel_logical_ring_emit(ringbuf,
 				MI_LOAD_REGISTER_IMM(GEN9_NUM_MOCS_ENTRIES));
 
 	for (index = 0; index < table->size; index++) {
-		intel_logical_ring_emit_reg(ringbuf, mocs_register(ring, index));
+		intel_logical_ring_emit_reg(ringbuf,
+					    mocs_register(engine, index));
 		intel_logical_ring_emit(ringbuf,
 					table->table[index].control_value);
 	}
@@ -224,8 +262,10 @@ static int emit_mocs_control_table(struc
 	 * that value to all the used entries.
 	 */
 	for (; index < GEN9_NUM_MOCS_ENTRIES; index++) {
-		intel_logical_ring_emit_reg(ringbuf, mocs_register(ring, index));
-		intel_logical_ring_emit(ringbuf, table->table[0].control_value);
+		intel_logical_ring_emit_reg(ringbuf,
+					    mocs_register(engine, index));
+		intel_logical_ring_emit(ringbuf,
+					table->table[0].control_value);
 	}
 
 	intel_logical_ring_emit(ringbuf, MI_NOOP);
@@ -234,6 +274,14 @@ static int emit_mocs_control_table(struc
 	return 0;
 }
 
+static inline u32 l3cc_combine(const struct drm_i915_mocs_table *table,
+			       u16 low,
+			       u16 high)
+{
+	return table->table[low].l3cc_value |
+	       table->table[high].l3cc_value << 16;
+}
+
 /**
  * emit_mocs_l3cc_table() - emit the mocs control table
  * @req:	Request to set up the MOCS table for.
@@ -249,39 +297,31 @@ static int emit_mocs_l3cc_table(struct d
 				const struct drm_i915_mocs_table *table)
 {
 	struct intel_ringbuffer *ringbuf = req->ringbuf;
-	unsigned int count;
 	unsigned int i;
-	u32 value;
-	u32 filler = (table->table[0].l3cc_value & 0xffff) |
-			((table->table[0].l3cc_value & 0xffff) << 16);
 	int ret;
 
 	if (WARN_ON(table->size > GEN9_NUM_MOCS_ENTRIES))
 		return -ENODEV;
 
-	ret = intel_logical_ring_begin(req, 2 + GEN9_NUM_MOCS_ENTRIES);
-	if (ret) {
-		DRM_DEBUG("intel_logical_ring_begin failed %d\n", ret);
+	ret = intel_ring_begin(req, 2 + GEN9_NUM_MOCS_ENTRIES);
+	if (ret)
 		return ret;
-	}
 
 	intel_logical_ring_emit(ringbuf,
 			MI_LOAD_REGISTER_IMM(GEN9_NUM_MOCS_ENTRIES / 2));
 
-	for (i = 0, count = 0; i < table->size / 2; i++, count += 2) {
-		value = (table->table[count].l3cc_value & 0xffff) |
-			((table->table[count + 1].l3cc_value & 0xffff) << 16);
-
+	for (i = 0; i < table->size/2; i++) {
 		intel_logical_ring_emit_reg(ringbuf, GEN9_LNCFCMOCS(i));
-		intel_logical_ring_emit(ringbuf, value);
+		intel_logical_ring_emit(ringbuf,
+					l3cc_combine(table, 2*i, 2*i+1));
 	}
 
 	if (table->size & 0x01) {
 		/* Odd table size - 1 left over */
-		value = (table->table[count].l3cc_value & 0xffff) |
-			((table->table[0].l3cc_value & 0xffff) << 16);
-	} else
-		value = filler;
+		intel_logical_ring_emit_reg(ringbuf, GEN9_LNCFCMOCS(i));
+		intel_logical_ring_emit(ringbuf, l3cc_combine(table, 2*i, 0));
+		i++;
+	}
 
 	/*
 	 * Now set the rest of the table to uncached - use entry 0 as
@@ -290,9 +330,7 @@ static int emit_mocs_l3cc_table(struct d
 	 */
 	for (; i < GEN9_NUM_MOCS_ENTRIES / 2; i++) {
 		intel_logical_ring_emit_reg(ringbuf, GEN9_LNCFCMOCS(i));
-		intel_logical_ring_emit(ringbuf, value);
-
-		value = filler;
+		intel_logical_ring_emit(ringbuf, l3cc_combine(table, 0, 0));
 	}
 
 	intel_logical_ring_emit(ringbuf, MI_NOOP);
@@ -302,6 +340,47 @@ static int emit_mocs_l3cc_table(struct d
 }
 
 /**
+ * intel_mocs_init_l3cc_table() - program the mocs control table
+ * @dev:      The the device to be programmed.
+ *
+ * This function simply programs the mocs registers for the given table
+ * starting at the given address. This register set is  programmed in pairs.
+ *
+ * These registers may get programmed more than once, it is simpler to
+ * re-program 32 registers than maintain the state of when they were programmed.
+ * We are always reprogramming with the same values and this only on context
+ * start.
+ *
+ * Return: Nothing.
+ */
+void intel_mocs_init_l3cc_table(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_mocs_table table;
+	unsigned int i;
+
+	if (!get_mocs_settings(dev_priv, &table))
+		return;
+
+	for (i = 0; i < table.size/2; i++)
+		I915_WRITE(GEN9_LNCFCMOCS(i), l3cc_combine(&table, 2*i, 2*i+1));
+
+	/* Odd table size - 1 left over */
+	if (table.size & 0x01) {
+		I915_WRITE(GEN9_LNCFCMOCS(i), l3cc_combine(&table, 2*i, 0));
+		i++;
+	}
+
+	/*
+	 * Now set the rest of the table to uncached - use entry 0 as
+	 * this will be uncached. Leave the last pair as initialised as
+	 * they are reserved by the hardware.
+	 */
+	for (; i < (GEN9_NUM_MOCS_ENTRIES / 2); i++)
+		I915_WRITE(GEN9_LNCFCMOCS(i), l3cc_combine(&table, 0, 0));
+}
+
+/**
  * intel_rcs_context_init_mocs() - program the MOCS register.
  * @req:	Request to set up the MOCS tables for.
  *
@@ -322,17 +401,11 @@ int intel_rcs_context_init_mocs(struct d
 	struct drm_i915_mocs_table t;
 	int ret;
 
-	if (get_mocs_settings(req->ring->dev, &t)) {
-		struct drm_i915_private *dev_priv = req->i915;
-		struct intel_engine_cs *ring;
-		enum intel_ring_id ring_id;
-
-		/* Program the control registers */
-		for_each_ring(ring, dev_priv, ring_id) {
-			ret = emit_mocs_control_table(req, &t, ring_id);
-			if (ret)
-				return ret;
-		}
+	if (get_mocs_settings(req->i915, &t)) {
+		/* Program the RCS control registers */
+		ret = emit_mocs_control_table(req, &t);
+		if (ret)
+			return ret;
 
 		/* Now program the l3cc registers */
 		ret = emit_mocs_l3cc_table(req, &t);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_mocs.h linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_mocs.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_mocs.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_mocs.h	2016-07-24 15:23:50.000000000 -0400
@@ -53,5 +53,7 @@
 #include "i915_drv.h"
 
 int intel_rcs_context_init_mocs(struct drm_i915_gem_request *req);
+void intel_mocs_init_l3cc_table(struct drm_device *dev);
+int intel_mocs_init_engine(struct intel_engine_cs *ring);
 
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_opregion.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_opregion.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_opregion.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_opregion.c	2016-07-24 15:23:50.000000000 -0400
@@ -34,12 +34,6 @@
 #include "i915_drv.h"
 #include "intel_drv.h"
 
-#define PCI_ASLE		0xe4
-#define PCI_ASLS		0xfc
-#define PCI_SWSCI		0xe8
-#define PCI_SWSCI_SCISEL	(1 << 15)
-#define PCI_SWSCI_GSSCIE	(1 << 0)
-
 #define OPREGION_HEADER_OFFSET 0
 #define OPREGION_ACPI_OFFSET   0x100
 #define   ACPI_CLID 0x01ac /* current lid state indicator */
@@ -246,13 +240,12 @@ struct opregion_asle_ext {
 
 #define MAX_DSLP	1500
 
-#ifdef CONFIG_ACPI
 static int swsci(struct drm_device *dev, u32 function, u32 parm, u32 *parm_out)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct opregion_swsci *swsci = dev_priv->opregion.swsci;
 	u32 main_function, sub_function, scic;
-	u16 pci_swsci;
+	u16 swsci_val;
 	u32 dslp;
 
 	if (!swsci)
@@ -300,16 +293,16 @@ static int swsci(struct drm_device *dev,
 	swsci->scic = scic;
 
 	/* Ensure SCI event is selected and event trigger is cleared. */
-	pci_read_config_word(dev->pdev, PCI_SWSCI, &pci_swsci);
-	if (!(pci_swsci & PCI_SWSCI_SCISEL) || (pci_swsci & PCI_SWSCI_GSSCIE)) {
-		pci_swsci |= PCI_SWSCI_SCISEL;
-		pci_swsci &= ~PCI_SWSCI_GSSCIE;
-		pci_write_config_word(dev->pdev, PCI_SWSCI, pci_swsci);
+	pci_read_config_word(dev->pdev, SWSCI, &swsci_val);
+	if (!(swsci_val & SWSCI_SCISEL) || (swsci_val & SWSCI_GSSCIE)) {
+		swsci_val |= SWSCI_SCISEL;
+		swsci_val &= ~SWSCI_GSSCIE;
+		pci_write_config_word(dev->pdev, SWSCI, swsci_val);
 	}
 
 	/* Use event trigger to tell bios to check the mail. */
-	pci_swsci |= PCI_SWSCI_GSSCIE;
-	pci_write_config_word(dev->pdev, PCI_SWSCI, pci_swsci);
+	swsci_val |= SWSCI_GSSCIE;
+	pci_write_config_word(dev->pdev, SWSCI, swsci_val);
 
 	/* Poll for the result. */
 #define C (((scic = swsci->scic) & SWSCI_SCIC_INDICATOR) == 0)
@@ -905,9 +898,6 @@ static void swsci_setup(struct drm_devic
 			 opregion->swsci_gbda_sub_functions,
 			 opregion->swsci_sbcb_sub_functions);
 }
-#else /* CONFIG_ACPI */
-static inline void swsci_setup(struct drm_device *dev) {}
-#endif  /* CONFIG_ACPI */
 
 static int intel_no_opregion_vbt_callback(const struct dmi_system_id *id)
 {
@@ -943,16 +933,14 @@ int intel_opregion_setup(struct drm_devi
 	BUILD_BUG_ON(sizeof(struct opregion_asle) != 0x100);
 	BUILD_BUG_ON(sizeof(struct opregion_asle_ext) != 0x400);
 
-	pci_read_config_dword(dev->pdev, PCI_ASLS, &asls);
+	pci_read_config_dword(dev->pdev, ASLS, &asls);
 	DRM_DEBUG_DRIVER("graphic opregion physical addr: 0x%x\n", asls);
 	if (asls == 0) {
 		DRM_DEBUG_DRIVER("ACPI OpRegion not supported!\n");
 		return -ENOTSUPP;
 	}
 
-#ifdef CONFIG_ACPI
 	INIT_WORK(&opregion->asle_work, asle_work);
-#endif
 
 	base = memremap(asls, OPREGION_SIZE, MEMREMAP_WB);
 	if (!base)
@@ -1024,3 +1012,42 @@ err_out:
 	memunmap(base);
 	return err;
 }
+
+int
+intel_opregion_get_panel_type(struct drm_device *dev)
+{
+	u32 panel_details;
+	int ret;
+
+	ret = swsci(dev, SWSCI_GBDA_PANEL_DETAILS, 0x0, &panel_details);
+	if (ret) {
+		DRM_DEBUG_KMS("Failed to get panel details from OpRegion (%d)\n",
+			      ret);
+		return ret;
+	}
+
+	ret = (panel_details >> 8) & 0xff;
+	if (ret > 0x10) {
+		DRM_DEBUG_KMS("Invalid OpRegion panel type 0x%x\n", ret);
+		return -EINVAL;
+	}
+
+	/* fall back to VBT panel type? */
+	if (ret == 0x0) {
+		DRM_DEBUG_KMS("No panel type in OpRegion\n");
+		return -ENODEV;
+	}
+
+	/*
+	 * FIXME On Dell XPS 13 9350 the OpRegion panel type (0) gives us
+	 * low vswing for eDP, whereas the VBT panel type (2) gives us normal
+	 * vswing instead. Low vswing results in some display flickers, so
+	 * let's simply ignore the OpRegion panel type on SKL for now.
+	 */
+	if (IS_SKYLAKE(dev)) {
+		DRM_DEBUG_KMS("Ignoring OpRegion panel type (%d)\n", ret - 1);
+		return -ENODEV;
+	}
+
+	return ret - 1;
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_overlay.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_overlay.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_overlay.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_overlay.c	2016-07-24 15:23:50.000000000 -0400
@@ -190,13 +190,14 @@ struct intel_overlay {
 static struct overlay_registers __iomem *
 intel_overlay_map_regs(struct intel_overlay *overlay)
 {
-	struct drm_i915_private *dev_priv = overlay->dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(overlay->dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	struct overlay_registers __iomem *regs;
 
 	if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
 		regs = (struct overlay_registers __iomem *)overlay->reg_bo->phys_handle->vaddr;
 	else
-		regs = io_mapping_map_wc(dev_priv->gtt.mappable,
+		regs = io_mapping_map_wc(ggtt->mappable,
 					 i915_gem_obj_ggtt_offset(overlay->reg_bo));
 
 	return regs;
@@ -233,30 +234,30 @@ static int intel_overlay_on(struct intel
 {
 	struct drm_device *dev = overlay->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring = &dev_priv->ring[RCS];
+	struct intel_engine_cs *engine = &dev_priv->engine[RCS];
 	struct drm_i915_gem_request *req;
 	int ret;
 
 	WARN_ON(overlay->active);
 	WARN_ON(IS_I830(dev) && !(dev_priv->quirks & QUIRK_PIPEA_FORCE));
 
-	req = i915_gem_request_alloc(ring, NULL);
+	req = i915_gem_request_alloc(engine, NULL);
 	if (IS_ERR(req))
 		return PTR_ERR(req);
 
 	ret = intel_ring_begin(req, 4);
 	if (ret) {
-		i915_gem_request_cancel(req);
+		i915_add_request_no_flush(req);
 		return ret;
 	}
 
 	overlay->active = true;
 
-	intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_ON);
-	intel_ring_emit(ring, overlay->flip_addr | OFC_UPDATE);
-	intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
-	intel_ring_emit(ring, MI_NOOP);
-	intel_ring_advance(ring);
+	intel_ring_emit(engine, MI_OVERLAY_FLIP | MI_OVERLAY_ON);
+	intel_ring_emit(engine, overlay->flip_addr | OFC_UPDATE);
+	intel_ring_emit(engine, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
+	intel_ring_emit(engine, MI_NOOP);
+	intel_ring_advance(engine);
 
 	return intel_overlay_do_wait_request(overlay, req, NULL);
 }
@@ -267,7 +268,7 @@ static int intel_overlay_continue(struct
 {
 	struct drm_device *dev = overlay->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring = &dev_priv->ring[RCS];
+	struct intel_engine_cs *engine = &dev_priv->engine[RCS];
 	struct drm_i915_gem_request *req;
 	u32 flip_addr = overlay->flip_addr;
 	u32 tmp;
@@ -283,19 +284,19 @@ static int intel_overlay_continue(struct
 	if (tmp & (1 << 17))
 		DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp);
 
-	req = i915_gem_request_alloc(ring, NULL);
+	req = i915_gem_request_alloc(engine, NULL);
 	if (IS_ERR(req))
 		return PTR_ERR(req);
 
 	ret = intel_ring_begin(req, 2);
 	if (ret) {
-		i915_gem_request_cancel(req);
+		i915_add_request_no_flush(req);
 		return ret;
 	}
 
-	intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
-	intel_ring_emit(ring, flip_addr);
-	intel_ring_advance(ring);
+	intel_ring_emit(engine, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
+	intel_ring_emit(engine, flip_addr);
+	intel_ring_advance(engine);
 
 	WARN_ON(overlay->last_flip_req);
 	i915_gem_request_assign(&overlay->last_flip_req, req);
@@ -336,7 +337,7 @@ static int intel_overlay_off(struct inte
 {
 	struct drm_device *dev = overlay->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring = &dev_priv->ring[RCS];
+	struct intel_engine_cs *engine = &dev_priv->engine[RCS];
 	struct drm_i915_gem_request *req;
 	u32 flip_addr = overlay->flip_addr;
 	int ret;
@@ -349,33 +350,34 @@ static int intel_overlay_off(struct inte
 	 * of the hw. Do it in both cases */
 	flip_addr |= OFC_UPDATE;
 
-	req = i915_gem_request_alloc(ring, NULL);
+	req = i915_gem_request_alloc(engine, NULL);
 	if (IS_ERR(req))
 		return PTR_ERR(req);
 
 	ret = intel_ring_begin(req, 6);
 	if (ret) {
-		i915_gem_request_cancel(req);
+		i915_add_request_no_flush(req);
 		return ret;
 	}
 
 	/* wait for overlay to go idle */
-	intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
-	intel_ring_emit(ring, flip_addr);
-	intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
+	intel_ring_emit(engine, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
+	intel_ring_emit(engine, flip_addr);
+	intel_ring_emit(engine, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
 	/* turn overlay off */
 	if (IS_I830(dev)) {
 		/* Workaround: Don't disable the overlay fully, since otherwise
 		 * it dies on the next OVERLAY_ON cmd. */
-		intel_ring_emit(ring, MI_NOOP);
-		intel_ring_emit(ring, MI_NOOP);
-		intel_ring_emit(ring, MI_NOOP);
+		intel_ring_emit(engine, MI_NOOP);
+		intel_ring_emit(engine, MI_NOOP);
+		intel_ring_emit(engine, MI_NOOP);
 	} else {
-		intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
-		intel_ring_emit(ring, flip_addr);
-		intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
+		intel_ring_emit(engine, MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
+		intel_ring_emit(engine, flip_addr);
+		intel_ring_emit(engine,
+				MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
 	}
-	intel_ring_advance(ring);
+	intel_ring_advance(engine);
 
 	return intel_overlay_do_wait_request(overlay, req, intel_overlay_off_tail);
 }
@@ -408,7 +410,7 @@ static int intel_overlay_release_old_vid
 {
 	struct drm_device *dev = overlay->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring = &dev_priv->ring[RCS];
+	struct intel_engine_cs *engine = &dev_priv->engine[RCS];
 	int ret;
 
 	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
@@ -423,19 +425,20 @@ static int intel_overlay_release_old_vid
 		/* synchronous slowpath */
 		struct drm_i915_gem_request *req;
 
-		req = i915_gem_request_alloc(ring, NULL);
+		req = i915_gem_request_alloc(engine, NULL);
 		if (IS_ERR(req))
 			return PTR_ERR(req);
 
 		ret = intel_ring_begin(req, 2);
 		if (ret) {
-			i915_gem_request_cancel(req);
+			i915_add_request_no_flush(req);
 			return ret;
 		}
 
-		intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
-		intel_ring_emit(ring, MI_NOOP);
-		intel_ring_advance(ring);
+		intel_ring_emit(engine,
+				MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
+		intel_ring_emit(engine, MI_NOOP);
+		intel_ring_advance(engine);
 
 		ret = intel_overlay_do_wait_request(overlay, req,
 						    intel_overlay_release_old_vid_tail);
@@ -1124,7 +1127,7 @@ int intel_overlay_put_image(struct drm_d
 	}
 	crtc = to_intel_crtc(drmmode_crtc);
 
-	new_bo = to_intel_bo(drm_gem_object_lookup(dev, file_priv,
+	new_bo = to_intel_bo(drm_gem_object_lookup(file_priv,
 						   put_image_rec->bo_handle));
 	if (&new_bo->base == NULL) {
 		ret = -ENOENT;
@@ -1479,7 +1482,8 @@ struct intel_overlay_error_state {
 static struct overlay_registers __iomem *
 intel_overlay_map_regs_atomic(struct intel_overlay *overlay)
 {
-	struct drm_i915_private *dev_priv = overlay->dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(overlay->dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	struct overlay_registers __iomem *regs;
 
 	if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
@@ -1488,7 +1492,7 @@ intel_overlay_map_regs_atomic(struct int
 		regs = (struct overlay_registers __iomem *)
 			overlay->reg_bo->phys_handle->vaddr;
 	else
-		regs = io_mapping_map_atomic_wc(dev_priv->gtt.mappable,
+		regs = io_mapping_map_atomic_wc(ggtt->mappable,
 						i915_gem_obj_ggtt_offset(overlay->reg_bo));
 
 	return regs;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_panel.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_panel.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_panel.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_panel.c	2016-07-24 15:23:50.000000000 -0400
@@ -504,7 +504,7 @@ static u32 i9xx_get_backlight(struct int
 	if (panel->backlight.combination_mode) {
 		u8 lbpc;
 
-		pci_read_config_byte(dev_priv->dev->pdev, PCI_LBPC, &lbpc);
+		pci_read_config_byte(dev_priv->dev->pdev, LBPC, &lbpc);
 		val *= lbpc;
 	}
 
@@ -592,7 +592,7 @@ static void i9xx_set_backlight(struct in
 
 		lbpc = level * 0xfe / panel->backlight.max + 1;
 		level /= lbpc;
-		pci_write_config_byte(dev_priv->dev->pdev, PCI_LBPC, lbpc);
+		pci_write_config_byte(dev_priv->dev->pdev, LBPC, lbpc);
 	}
 
 	if (IS_GEN4(dev_priv)) {
@@ -1240,7 +1240,7 @@ static void intel_backlight_device_unreg
  */
 static u32 bxt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
 {
-	return KHz(19200) / pwm_freq_hz;
+	return DIV_ROUND_CLOSEST(KHz(19200), pwm_freq_hz);
 }
 
 /*
@@ -1251,16 +1251,14 @@ static u32 bxt_hz_to_pwm(struct intel_co
 static u32 spt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
 {
 	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
-	u32 mul, clock;
+	u32 mul;
 
 	if (I915_READ(SOUTH_CHICKEN1) & SPT_PWM_GRANULARITY)
 		mul = 128;
 	else
 		mul = 16;
 
-	clock = MHz(24);
-
-	return clock / (pwm_freq_hz * mul);
+	return DIV_ROUND_CLOSEST(MHz(24), pwm_freq_hz * mul);
 }
 
 /*
@@ -1283,7 +1281,7 @@ static u32 lpt_hz_to_pwm(struct intel_co
 	else
 		clock = MHz(24); /* LPT:LP */
 
-	return clock / (pwm_freq_hz * mul);
+	return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * mul);
 }
 
 /*
@@ -1292,10 +1290,9 @@ static u32 lpt_hz_to_pwm(struct intel_co
  */
 static u32 pch_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
 {
-	struct drm_device *dev = connector->base.dev;
-	int clock = MHz(intel_pch_rawclk(dev));
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
 
-	return clock / (pwm_freq_hz * 128);
+	return DIV_ROUND_CLOSEST(KHz(dev_priv->rawclk_freq), pwm_freq_hz * 128);
 }
 
 /*
@@ -1308,16 +1305,15 @@ static u32 pch_hz_to_pwm(struct intel_co
  */
 static u32 i9xx_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
 {
-	struct drm_device *dev = connector->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	int clock;
 
-	if (IS_PINEVIEW(dev))
-		clock = MHz(intel_hrawclk(dev));
+	if (IS_PINEVIEW(dev_priv))
+		clock = KHz(dev_priv->rawclk_freq);
 	else
-		clock = 1000 * dev_priv->cdclk_freq;
+		clock = KHz(dev_priv->cdclk_freq);
 
-	return clock / (pwm_freq_hz * 32);
+	return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * 32);
 }
 
 /*
@@ -1332,11 +1328,11 @@ static u32 i965_hz_to_pwm(struct intel_c
 	int clock;
 
 	if (IS_G4X(dev_priv))
-		clock = MHz(intel_hrawclk(dev));
+		clock = KHz(dev_priv->rawclk_freq);
 	else
-		clock = 1000 * dev_priv->cdclk_freq;
+		clock = KHz(dev_priv->cdclk_freq);
 
-	return clock / (pwm_freq_hz * 128);
+	return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * 128);
 }
 
 /*
@@ -1346,19 +1342,21 @@ static u32 i965_hz_to_pwm(struct intel_c
  */
 static u32 vlv_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
 {
-	struct drm_device *dev = connector->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	int clock;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+	int mul, clock;
 
 	if ((I915_READ(CBR1_VLV) & CBR_PWM_CLOCK_MUX_SELECT) == 0) {
-		if (IS_CHERRYVIEW(dev))
-			return KHz(19200) / (pwm_freq_hz * 16);
+		if (IS_CHERRYVIEW(dev_priv))
+			clock = KHz(19200);
 		else
-			return MHz(25) / (pwm_freq_hz * 16);
+			clock = MHz(25);
+		mul = 16;
 	} else {
-		clock = intel_hrawclk(dev);
-		return MHz(clock) / (pwm_freq_hz * 128);
+		clock = KHz(dev_priv->rawclk_freq);
+		mul = 128;
 	}
+
+	return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * mul);
 }
 
 static u32 get_backlight_max_vbt(struct intel_connector *connector)
@@ -1640,6 +1638,12 @@ static int pwm_setup_backlight(struct in
 		return -ENODEV;
 	}
 
+	/*
+	 * FIXME: pwm_apply_args() should be removed when switching to
+	 * the atomic PWM API.
+	 */
+	pwm_apply_args(panel->backlight.pwm);
+
 	retval = pwm_config(panel->backlight.pwm, CRC_PMIC_PWM_PERIOD_NS,
 			    CRC_PMIC_PWM_PERIOD_NS);
 	if (retval < 0) {
@@ -1727,7 +1731,8 @@ intel_panel_init_backlight_funcs(struct
 		panel->backlight.set = bxt_set_backlight;
 		panel->backlight.get = bxt_get_backlight;
 		panel->backlight.hz_to_pwm = bxt_hz_to_pwm;
-	} else if (HAS_PCH_LPT(dev_priv) || HAS_PCH_SPT(dev_priv)) {
+	} else if (HAS_PCH_LPT(dev_priv) || HAS_PCH_SPT(dev_priv) ||
+		   HAS_PCH_KBP(dev_priv)) {
 		panel->backlight.setup = lpt_setup_backlight;
 		panel->backlight.enable = lpt_enable_backlight;
 		panel->backlight.disable = lpt_disable_backlight;
@@ -1745,7 +1750,7 @@ intel_panel_init_backlight_funcs(struct
 		panel->backlight.get = pch_get_backlight;
 		panel->backlight.hz_to_pwm = pch_hz_to_pwm;
 	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
-		if (dev_priv->vbt.has_mipi) {
+		if (connector->base.connector_type == DRM_MODE_CONNECTOR_DSI) {
 			panel->backlight.setup = pwm_setup_backlight;
 			panel->backlight.enable = pwm_enable_backlight;
 			panel->backlight.disable = pwm_disable_backlight;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_pm.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_pm.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_pm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_pm.c	2016-07-24 15:23:50.000000000 -0400
@@ -54,10 +54,38 @@
 #define INTEL_RC6p_ENABLE			(1<<1)
 #define INTEL_RC6pp_ENABLE			(1<<2)
 
+static void gen9_init_clock_gating(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	/* See Bspec note for PSR2_CTL bit 31, Wa#828:skl,bxt,kbl */
+	I915_WRITE(CHICKEN_PAR1_1,
+		   I915_READ(CHICKEN_PAR1_1) | SKL_EDP_PSR_FIX_RDWRAP);
+
+	I915_WRITE(GEN8_CONFIG0,
+		   I915_READ(GEN8_CONFIG0) | GEN9_DEFAULT_FIXES);
+
+	/* WaEnableChickenDCPR:skl,bxt,kbl */
+	I915_WRITE(GEN8_CHICKEN_DCPR_1,
+		   I915_READ(GEN8_CHICKEN_DCPR_1) | MASK_WAKEMEM);
+
+	/* WaFbcTurnOffFbcWatermark:skl,bxt,kbl */
+	/* WaFbcWakeMemOn:skl,bxt,kbl */
+	I915_WRITE(DISP_ARB_CTL, I915_READ(DISP_ARB_CTL) |
+		   DISP_FBC_WM_DIS |
+		   DISP_FBC_MEMORY_WAKE);
+
+	/* WaFbcHighMemBwCorruptionAvoidance:skl,bxt,kbl */
+	I915_WRITE(ILK_DPFC_CHICKEN, I915_READ(ILK_DPFC_CHICKEN) |
+		   ILK_DPFC_DISABLE_DUMMY0);
+}
+
 static void bxt_init_clock_gating(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
+	gen9_init_clock_gating(dev);
+
 	/* WaDisableSDEUnitClockGating:bxt */
 	I915_WRITE(GEN8_UCGCTL6, I915_READ(GEN8_UCGCTL6) |
 		   GEN8_SDEUNIT_CLOCK_GATE_DISABLE);
@@ -487,20 +515,6 @@ static const struct intel_watermark_para
 	.guard_size = 2,
 	.cacheline_size = G4X_FIFO_LINE_SIZE,
 };
-static const struct intel_watermark_params valleyview_wm_info = {
-	.fifo_size = VALLEYVIEW_FIFO_SIZE,
-	.max_wm = VALLEYVIEW_MAX_WM,
-	.default_wm = VALLEYVIEW_MAX_WM,
-	.guard_size = 2,
-	.cacheline_size = G4X_FIFO_LINE_SIZE,
-};
-static const struct intel_watermark_params valleyview_cursor_wm_info = {
-	.fifo_size = I965_CURSOR_FIFO,
-	.max_wm = VALLEYVIEW_CURSOR_MAX_WM,
-	.default_wm = I965_CURSOR_DFT_WM,
-	.guard_size = 2,
-	.cacheline_size = G4X_FIFO_LINE_SIZE,
-};
 static const struct intel_watermark_params i965_cursor_wm_info = {
 	.fifo_size = I965_CURSOR_FIFO,
 	.max_wm = I965_CURSOR_MAX_WM,
@@ -2010,11 +2024,18 @@ static void ilk_compute_wm_level(const s
 		cur_latency *= 5;
 	}
 
-	result->pri_val = ilk_compute_pri_wm(cstate, pristate,
-					     pri_latency, level);
-	result->spr_val = ilk_compute_spr_wm(cstate, sprstate, spr_latency);
-	result->cur_val = ilk_compute_cur_wm(cstate, curstate, cur_latency);
-	result->fbc_val = ilk_compute_fbc_wm(cstate, pristate, result->pri_val);
+	if (pristate) {
+		result->pri_val = ilk_compute_pri_wm(cstate, pristate,
+						     pri_latency, level);
+		result->fbc_val = ilk_compute_fbc_wm(cstate, pristate, result->pri_val);
+	}
+
+	if (sprstate)
+		result->spr_val = ilk_compute_spr_wm(cstate, sprstate, spr_latency);
+
+	if (curstate)
+		result->cur_val = ilk_compute_cur_wm(cstate, curstate, cur_latency);
+
 	result->enable = true;
 }
 
@@ -2278,100 +2299,171 @@ static void skl_setup_wm_latency(struct
 	intel_print_wm_latency(dev, "Gen9 Plane", dev_priv->wm.skl_latency);
 }
 
+static bool ilk_validate_pipe_wm(struct drm_device *dev,
+				 struct intel_pipe_wm *pipe_wm)
+{
+	/* LP0 watermark maximums depend on this pipe alone */
+	const struct intel_wm_config config = {
+		.num_pipes_active = 1,
+		.sprites_enabled = pipe_wm->sprites_enabled,
+		.sprites_scaled = pipe_wm->sprites_scaled,
+	};
+	struct ilk_wm_maximums max;
+
+	/* LP0 watermarks always use 1/2 DDB partitioning */
+	ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
+
+	/* At least LP0 must be valid */
+	if (!ilk_validate_wm_level(0, &max, &pipe_wm->wm[0])) {
+		DRM_DEBUG_KMS("LP0 watermark invalid\n");
+		return false;
+	}
+
+	return true;
+}
+
 /* Compute new watermarks for the pipe */
-static int ilk_compute_pipe_wm(struct intel_crtc *intel_crtc,
-			       struct drm_atomic_state *state)
+static int ilk_compute_pipe_wm(struct intel_crtc_state *cstate)
 {
+	struct drm_atomic_state *state = cstate->base.state;
+	struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
 	struct intel_pipe_wm *pipe_wm;
-	struct drm_device *dev = intel_crtc->base.dev;
+	struct drm_device *dev = state->dev;
 	const struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_crtc_state *cstate = NULL;
 	struct intel_plane *intel_plane;
-	struct drm_plane_state *ps;
 	struct intel_plane_state *pristate = NULL;
 	struct intel_plane_state *sprstate = NULL;
 	struct intel_plane_state *curstate = NULL;
-	int level, max_level = ilk_wm_max_level(dev);
-	/* LP0 watermark maximums depend on this pipe alone */
-	struct intel_wm_config config = {
-		.num_pipes_active = 1,
-	};
+	int level, max_level = ilk_wm_max_level(dev), usable_level;
 	struct ilk_wm_maximums max;
 
-	cstate = intel_atomic_get_crtc_state(state, intel_crtc);
-	if (IS_ERR(cstate))
-		return PTR_ERR(cstate);
-
 	pipe_wm = &cstate->wm.optimal.ilk;
-	memset(pipe_wm, 0, sizeof(*pipe_wm));
 
 	for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
-		ps = drm_atomic_get_plane_state(state,
-						&intel_plane->base);
-		if (IS_ERR(ps))
-			return PTR_ERR(ps);
+		struct intel_plane_state *ps;
+
+		ps = intel_atomic_get_existing_plane_state(state,
+							   intel_plane);
+		if (!ps)
+			continue;
 
 		if (intel_plane->base.type == DRM_PLANE_TYPE_PRIMARY)
-			pristate = to_intel_plane_state(ps);
+			pristate = ps;
 		else if (intel_plane->base.type == DRM_PLANE_TYPE_OVERLAY)
-			sprstate = to_intel_plane_state(ps);
+			sprstate = ps;
 		else if (intel_plane->base.type == DRM_PLANE_TYPE_CURSOR)
-			curstate = to_intel_plane_state(ps);
+			curstate = ps;
 	}
 
-	config.sprites_enabled = sprstate->visible;
-	config.sprites_scaled = sprstate->visible &&
-		(drm_rect_width(&sprstate->dst) != drm_rect_width(&sprstate->src) >> 16 ||
-		drm_rect_height(&sprstate->dst) != drm_rect_height(&sprstate->src) >> 16);
-
 	pipe_wm->pipe_enabled = cstate->base.active;
-	pipe_wm->sprites_enabled = config.sprites_enabled;
-	pipe_wm->sprites_scaled = config.sprites_scaled;
+	if (sprstate) {
+		pipe_wm->sprites_enabled = sprstate->visible;
+		pipe_wm->sprites_scaled = sprstate->visible &&
+			(drm_rect_width(&sprstate->dst) != drm_rect_width(&sprstate->src) >> 16 ||
+			 drm_rect_height(&sprstate->dst) != drm_rect_height(&sprstate->src) >> 16);
+	}
+
+	usable_level = max_level;
 
 	/* ILK/SNB: LP2+ watermarks only w/o sprites */
-	if (INTEL_INFO(dev)->gen <= 6 && sprstate->visible)
-		max_level = 1;
+	if (INTEL_INFO(dev)->gen <= 6 && pipe_wm->sprites_enabled)
+		usable_level = 1;
 
 	/* ILK/SNB/IVB: LP1+ watermarks only w/o scaling */
-	if (config.sprites_scaled)
-		max_level = 0;
+	if (pipe_wm->sprites_scaled)
+		usable_level = 0;
 
 	ilk_compute_wm_level(dev_priv, intel_crtc, 0, cstate,
-			     pristate, sprstate, curstate, &pipe_wm->wm[0]);
+			     pristate, sprstate, curstate, &pipe_wm->raw_wm[0]);
+
+	memset(&pipe_wm->wm, 0, sizeof(pipe_wm->wm));
+	pipe_wm->wm[0] = pipe_wm->raw_wm[0];
 
 	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
 		pipe_wm->linetime = hsw_compute_linetime_wm(dev, cstate);
 
-	/* LP0 watermarks always use 1/2 DDB partitioning */
-	ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max);
-
-	/* At least LP0 must be valid */
-	if (!ilk_validate_wm_level(0, &max, &pipe_wm->wm[0]))
+	if (!ilk_validate_pipe_wm(dev, pipe_wm))
 		return -EINVAL;
 
 	ilk_compute_wm_reg_maximums(dev, 1, &max);
 
 	for (level = 1; level <= max_level; level++) {
-		struct intel_wm_level wm = {};
+		struct intel_wm_level *wm = &pipe_wm->raw_wm[level];
 
 		ilk_compute_wm_level(dev_priv, intel_crtc, level, cstate,
-				     pristate, sprstate, curstate, &wm);
+				     pristate, sprstate, curstate, wm);
 
 		/*
 		 * Disable any watermark level that exceeds the
 		 * register maximums since such watermarks are
 		 * always invalid.
 		 */
-		if (!ilk_validate_wm_level(level, &max, &wm))
-			break;
+		if (level > usable_level)
+			continue;
 
-		pipe_wm->wm[level] = wm;
+		if (ilk_validate_wm_level(level, &max, wm))
+			pipe_wm->wm[level] = *wm;
+		else
+			usable_level = level;
 	}
 
 	return 0;
 }
 
 /*
+ * Build a set of 'intermediate' watermark values that satisfy both the old
+ * state and the new state.  These can be programmed to the hardware
+ * immediately.
+ */
+static int ilk_compute_intermediate_wm(struct drm_device *dev,
+				       struct intel_crtc *intel_crtc,
+				       struct intel_crtc_state *newstate)
+{
+	struct intel_pipe_wm *a = &newstate->wm.intermediate;
+	struct intel_pipe_wm *b = &intel_crtc->wm.active.ilk;
+	int level, max_level = ilk_wm_max_level(dev);
+
+	/*
+	 * Start with the final, target watermarks, then combine with the
+	 * currently active watermarks to get values that are safe both before
+	 * and after the vblank.
+	 */
+	*a = newstate->wm.optimal.ilk;
+	a->pipe_enabled |= b->pipe_enabled;
+	a->sprites_enabled |= b->sprites_enabled;
+	a->sprites_scaled |= b->sprites_scaled;
+
+	for (level = 0; level <= max_level; level++) {
+		struct intel_wm_level *a_wm = &a->wm[level];
+		const struct intel_wm_level *b_wm = &b->wm[level];
+
+		a_wm->enable &= b_wm->enable;
+		a_wm->pri_val = max(a_wm->pri_val, b_wm->pri_val);
+		a_wm->spr_val = max(a_wm->spr_val, b_wm->spr_val);
+		a_wm->cur_val = max(a_wm->cur_val, b_wm->cur_val);
+		a_wm->fbc_val = max(a_wm->fbc_val, b_wm->fbc_val);
+	}
+
+	/*
+	 * We need to make sure that these merged watermark values are
+	 * actually a valid configuration themselves.  If they're not,
+	 * there's no safe way to transition from the old state to
+	 * the new state, so we need to fail the atomic transaction.
+	 */
+	if (!ilk_validate_pipe_wm(dev, a))
+		return -EINVAL;
+
+	/*
+	 * If our intermediate WM are identical to the final WM, then we can
+	 * omit the post-vblank programming; only update if it's different.
+	 */
+	if (memcmp(a, &newstate->wm.optimal.ilk, sizeof(*a)) == 0)
+		newstate->wm.need_postvbl_update = false;
+
+	return 0;
+}
+
+/*
  * Merge the watermarks from all active pipes for a specific level.
  */
 static void ilk_merge_wm_level(struct drm_device *dev,
@@ -2383,9 +2475,7 @@ static void ilk_merge_wm_level(struct dr
 	ret_wm->enable = true;
 
 	for_each_intel_crtc(dev, intel_crtc) {
-		const struct intel_crtc_state *cstate =
-			to_intel_crtc_state(intel_crtc->base.state);
-		const struct intel_pipe_wm *active = &cstate->wm.optimal.ilk;
+		const struct intel_pipe_wm *active = &intel_crtc->wm.active.ilk;
 		const struct intel_wm_level *wm = &active->wm[level];
 
 		if (!active->pipe_enabled)
@@ -2421,7 +2511,7 @@ static void ilk_wm_merge(struct drm_devi
 	/* ILK/SNB/IVB: LP1+ watermarks only w/ single pipe */
 	if ((INTEL_INFO(dev)->gen <= 6 || IS_IVYBRIDGE(dev)) &&
 	    config->num_pipes_active > 1)
-		return;
+		last_enabled_level = 0;
 
 	/* ILK: FBC WM must be disabled always */
 	merged->fbc_wm_enabled = INTEL_INFO(dev)->gen >= 6;
@@ -2533,15 +2623,14 @@ static void ilk_compute_wm_results(struc
 
 	/* LP0 register values */
 	for_each_intel_crtc(dev, intel_crtc) {
-		const struct intel_crtc_state *cstate =
-			to_intel_crtc_state(intel_crtc->base.state);
 		enum pipe pipe = intel_crtc->pipe;
-		const struct intel_wm_level *r = &cstate->wm.optimal.ilk.wm[0];
+		const struct intel_wm_level *r =
+			&intel_crtc->wm.active.ilk.wm[0];
 
 		if (WARN_ON(!r->enable))
 			continue;
 
-		results->wm_linetime[pipe] = cstate->wm.optimal.ilk.linetime;
+		results->wm_linetime[pipe] = intel_crtc->wm.active.ilk.linetime;
 
 		results->wm_pipe[pipe] =
 			(r->pri_val << WM0_PIPE_PLANE_SHIFT) |
@@ -2748,7 +2837,7 @@ static void ilk_write_wm_values(struct d
 	dev_priv->wm.hw = *results;
 }
 
-static bool ilk_disable_lp_wm(struct drm_device *dev)
+bool ilk_disable_lp_wm(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
@@ -3657,11 +3746,9 @@ static void ilk_compute_wm_config(struct
 	}
 }
 
-static void ilk_program_watermarks(struct intel_crtc_state *cstate)
+static void ilk_program_watermarks(struct drm_i915_private *dev_priv)
 {
-	struct drm_crtc *crtc = cstate->base.crtc;
-	struct drm_device *dev = crtc->dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_device *dev = dev_priv->dev;
 	struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {}, *best_lp_wm;
 	struct ilk_wm_maximums max;
 	struct intel_wm_config config = {};
@@ -3692,28 +3779,28 @@ static void ilk_program_watermarks(struc
 	ilk_write_wm_values(dev_priv, &results);
 }
 
-static void ilk_update_wm(struct drm_crtc *crtc)
+static void ilk_initial_watermarks(struct intel_crtc_state *cstate)
 {
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
-
-	WARN_ON(cstate->base.active != intel_crtc->active);
+	struct drm_i915_private *dev_priv = to_i915(cstate->base.crtc->dev);
+	struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
 
-	/*
-	 * IVB workaround: must disable low power watermarks for at least
-	 * one frame before enabling scaling.  LP watermarks can be re-enabled
-	 * when scaling is disabled.
-	 *
-	 * WaCxSRDisabledForSpriteScaling:ivb
-	 */
-	if (cstate->disable_lp_wm) {
-		ilk_disable_lp_wm(crtc->dev);
-		intel_wait_for_vblank(crtc->dev, intel_crtc->pipe);
-	}
+	mutex_lock(&dev_priv->wm.wm_mutex);
+	intel_crtc->wm.active.ilk = cstate->wm.intermediate;
+	ilk_program_watermarks(dev_priv);
+	mutex_unlock(&dev_priv->wm.wm_mutex);
+}
 
-	intel_crtc->wm.active.ilk = cstate->wm.optimal.ilk;
+static void ilk_optimize_watermarks(struct intel_crtc_state *cstate)
+{
+	struct drm_i915_private *dev_priv = to_i915(cstate->base.crtc->dev);
+	struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
 
-	ilk_program_watermarks(cstate);
+	mutex_lock(&dev_priv->wm.wm_mutex);
+	if (cstate->wm.need_postvbl_update) {
+		intel_crtc->wm.active.ilk = cstate->wm.optimal.ilk;
+		ilk_program_watermarks(dev_priv);
+	}
+	mutex_unlock(&dev_priv->wm.wm_mutex);
 }
 
 static void skl_pipe_wm_active_state(uint32_t val,
@@ -3845,6 +3932,8 @@ static void ilk_pipe_wm_get_hw_state(str
 	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
 		hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe));
 
+	memset(active, 0, sizeof(*active));
+
 	active->pipe_enabled = intel_crtc->active;
 
 	if (active->pipe_enabled) {
@@ -4243,7 +4332,7 @@ static u32 intel_rps_limits(struct drm_i
 	 * the hw runs at the minimal clock before selecting the desired
 	 * frequency, if the down threshold expires in that window we will not
 	 * receive a down interrupt. */
-	if (IS_GEN9(dev_priv->dev)) {
+	if (IS_GEN9(dev_priv)) {
 		limits = (dev_priv->rps.max_freq_softlimit) << 23;
 		if (val <= dev_priv->rps.min_freq_softlimit)
 			limits |= (dev_priv->rps.min_freq_softlimit) << 14;
@@ -4528,7 +4617,7 @@ void intel_set_rps(struct drm_device *de
 		gen6_set_rps(dev, val);
 }
 
-static void gen9_disable_rps(struct drm_device *dev)
+static void gen9_disable_rc6(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
@@ -4536,12 +4625,20 @@ static void gen9_disable_rps(struct drm_
 	I915_WRITE(GEN9_PG_ENABLE, 0);
 }
 
+static void gen9_disable_rps(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	I915_WRITE(GEN6_RP_CONTROL, 0);
+}
+
 static void gen6_disable_rps(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	I915_WRITE(GEN6_RC_CONTROL, 0);
 	I915_WRITE(GEN6_RPNSWREQ, 1 << 31);
+	I915_WRITE(GEN6_RP_CONTROL, 0);
 }
 
 static void cherryview_disable_rps(struct drm_device *dev)
@@ -4585,7 +4682,8 @@ static void intel_print_rc6_info(struct
 
 static bool bxt_check_bios_rc6_setup(const struct drm_device *dev)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	bool enable_rc6 = true;
 	unsigned long rc6_ctx_base;
 
@@ -4599,9 +4697,9 @@ static bool bxt_check_bios_rc6_setup(con
 	 * for this check.
 	 */
 	rc6_ctx_base = I915_READ(RC6_CTX_BASE) & RC6_CTX_BASE_MASK;
-	if (!((rc6_ctx_base >= dev_priv->gtt.stolen_reserved_base) &&
-	      (rc6_ctx_base + PAGE_SIZE <= dev_priv->gtt.stolen_reserved_base +
-					dev_priv->gtt.stolen_reserved_size))) {
+	if (!((rc6_ctx_base >= ggtt->stolen_reserved_base) &&
+	      (rc6_ctx_base + PAGE_SIZE <= ggtt->stolen_reserved_base +
+					ggtt->stolen_reserved_size))) {
 		DRM_DEBUG_KMS("RC6 Base address not as expected.\n");
 		enable_rc6 = false;
 	}
@@ -4744,6 +4842,16 @@ static void gen9_enable_rps(struct drm_d
 
 	/* WaGsvDisableTurbo: Workaround to disable turbo on BXT A* */
 	if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) {
+		/*
+		 * BIOS could leave the Hw Turbo enabled, so need to explicitly
+		 * clear out the Control register just to avoid inconsitency
+		 * with debugfs interface, which will show  Turbo as enabled
+		 * only and that is not expected by the User after adding the
+		 * WaGsvDisableTurbo. Apart from this there is no problem even
+		 * if the Turbo is left enabled in the Control register, as the
+		 * Up/Down interrupts would remain masked.
+		 */
+		gen9_disable_rps(dev);
 		intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
 		return;
 	}
@@ -4762,7 +4870,7 @@ static void gen9_enable_rps(struct drm_d
 	 * Up/Down EI & threshold registers, as well as the RP_CONTROL,
 	 * RP_INTERRUPT_LIMITS & RPNSWREQ registers */
 	dev_priv->rps.power = HIGH_POWER; /* force a reset */
-	gen6_set_rps(dev_priv->dev, dev_priv->rps.min_freq_softlimit);
+	gen6_set_rps(dev_priv->dev, dev_priv->rps.idle_freq);
 
 	intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
 }
@@ -4770,9 +4878,8 @@ static void gen9_enable_rps(struct drm_d
 static void gen9_enable_rc6(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring;
+	struct intel_engine_cs *engine;
 	uint32_t rc6_mask = 0;
-	int unused;
 
 	/* 1a: Software RC state - RC0 */
 	I915_WRITE(GEN6_RC_STATE, 0);
@@ -4793,8 +4900,8 @@ static void gen9_enable_rc6(struct drm_d
 		I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 54 << 16);
 	I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */
 	I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */
-	for_each_ring(ring, dev_priv, unused)
-		I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10);
+	for_each_engine(engine, dev_priv)
+		I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10);
 
 	if (HAS_GUC_UCODE(dev))
 		I915_WRITE(GUC_MAX_IDLE_COUNT, 0xA);
@@ -4840,9 +4947,8 @@ static void gen9_enable_rc6(struct drm_d
 static void gen8_enable_rps(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring;
+	struct intel_engine_cs *engine;
 	uint32_t rc6_mask = 0;
-	int unused;
 
 	/* 1a: Software RC state - RC0 */
 	I915_WRITE(GEN6_RC_STATE, 0);
@@ -4861,8 +4967,8 @@ static void gen8_enable_rps(struct drm_d
 	I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16);
 	I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */
 	I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */
-	for_each_ring(ring, dev_priv, unused)
-		I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10);
+	for_each_engine(engine, dev_priv)
+		I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10);
 	I915_WRITE(GEN6_RC_SLEEP, 0);
 	if (IS_BROADWELL(dev))
 		I915_WRITE(GEN6_RC6_THRESHOLD, 625); /* 800us/1.28 for TO */
@@ -4922,11 +5028,11 @@ static void gen8_enable_rps(struct drm_d
 static void gen6_enable_rps(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring;
+	struct intel_engine_cs *engine;
 	u32 rc6vids, pcu_mbox = 0, rc6_mask = 0;
 	u32 gtfifodbg;
 	int rc6_mode;
-	int i, ret;
+	int ret;
 
 	WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
 
@@ -4939,7 +5045,8 @@ static void gen6_enable_rps(struct drm_d
 	I915_WRITE(GEN6_RC_STATE, 0);
 
 	/* Clear the DBG now so we don't confuse earlier errors */
-	if ((gtfifodbg = I915_READ(GTFIFODBG))) {
+	gtfifodbg = I915_READ(GTFIFODBG);
+	if (gtfifodbg) {
 		DRM_ERROR("GT fifo had a previous error %x\n", gtfifodbg);
 		I915_WRITE(GTFIFODBG, gtfifodbg);
 	}
@@ -4958,8 +5065,8 @@ static void gen6_enable_rps(struct drm_d
 	I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000);
 	I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25);
 
-	for_each_ring(ring, dev_priv, i)
-		I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10);
+	for_each_engine(engine, dev_priv)
+		I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10);
 
 	I915_WRITE(GEN6_RC_SLEEP, 0);
 	I915_WRITE(GEN6_RC1e_THRESHOLD, 1000);
@@ -5244,9 +5351,9 @@ static void cherryview_check_pctx(struct
 
 static void cherryview_setup_pctx(struct drm_device *dev)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	unsigned long pctx_paddr, paddr;
-	struct i915_gtt *gtt = &dev_priv->gtt;
 	u32 pcbr;
 	int pctx_size = 32*1024;
 
@@ -5254,7 +5361,7 @@ static void cherryview_setup_pctx(struct
 	if ((pcbr >> VLV_PCBR_ADDR_SHIFT) == 0) {
 		DRM_DEBUG_DRIVER("BIOS didn't set up PCBR, fixing up\n");
 		paddr = (dev_priv->mm.stolen_base +
-			 (gtt->stolen_size - pctx_size));
+			 (ggtt->stolen_size - pctx_size));
 
 		pctx_paddr = (paddr & (~4095));
 		I915_WRITE(VLV_PCBR, pctx_paddr);
@@ -5322,6 +5429,17 @@ static void valleyview_cleanup_pctx(stru
 	dev_priv->vlv_pctx = NULL;
 }
 
+static void vlv_init_gpll_ref_freq(struct drm_i915_private *dev_priv)
+{
+	dev_priv->rps.gpll_ref_freq =
+		vlv_get_cck_clock(dev_priv, "GPLL ref",
+				  CCK_GPLL_CLOCK_CONTROL,
+				  dev_priv->czclk_freq);
+
+	DRM_DEBUG_DRIVER("GPLL reference freq: %d kHz\n",
+			 dev_priv->rps.gpll_ref_freq);
+}
+
 static void valleyview_init_gt_powersave(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -5329,6 +5447,8 @@ static void valleyview_init_gt_powersave
 
 	valleyview_setup_pctx(dev);
 
+	vlv_init_gpll_ref_freq(dev_priv);
+
 	mutex_lock(&dev_priv->rps.hw_lock);
 
 	val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
@@ -5386,6 +5506,8 @@ static void cherryview_init_gt_powersave
 
 	cherryview_setup_pctx(dev);
 
+	vlv_init_gpll_ref_freq(dev_priv);
+
 	mutex_lock(&dev_priv->rps.hw_lock);
 
 	mutex_lock(&dev_priv->sb_lock);
@@ -5450,13 +5572,13 @@ static void valleyview_cleanup_gt_powers
 static void cherryview_enable_rps(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring;
+	struct intel_engine_cs *engine;
 	u32 gtfifodbg, val, rc6_mode = 0, pcbr;
-	int i;
 
 	WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
 
-	gtfifodbg = I915_READ(GTFIFODBG);
+	gtfifodbg = I915_READ(GTFIFODBG) & ~(GT_FIFO_SBDEDICATE_FREE_ENTRY_CHV |
+					     GT_FIFO_FREE_ENTRIES_CHV);
 	if (gtfifodbg) {
 		DRM_DEBUG_DRIVER("GT fifo had a previous error %x\n",
 				 gtfifodbg);
@@ -5477,8 +5599,8 @@ static void cherryview_enable_rps(struct
 	I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */
 	I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */
 
-	for_each_ring(ring, dev_priv, i)
-		I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10);
+	for_each_engine(engine, dev_priv)
+		I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10);
 	I915_WRITE(GEN6_RC_SLEEP, 0);
 
 	/* TO threshold set to 500 us ( 0x186 * 1.28 us) */
@@ -5537,10 +5659,10 @@ static void cherryview_enable_rps(struct
 			 dev_priv->rps.cur_freq);
 
 	DRM_DEBUG_DRIVER("setting GPU freq to %d MHz (%u)\n",
-			 intel_gpu_freq(dev_priv, dev_priv->rps.efficient_freq),
-			 dev_priv->rps.efficient_freq);
+			 intel_gpu_freq(dev_priv, dev_priv->rps.idle_freq),
+			 dev_priv->rps.idle_freq);
 
-	valleyview_set_rps(dev_priv->dev, dev_priv->rps.efficient_freq);
+	valleyview_set_rps(dev_priv->dev, dev_priv->rps.idle_freq);
 
 	intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
 }
@@ -5548,15 +5670,15 @@ static void cherryview_enable_rps(struct
 static void valleyview_enable_rps(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring;
+	struct intel_engine_cs *engine;
 	u32 gtfifodbg, val, rc6_mode = 0;
-	int i;
 
 	WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
 
 	valleyview_check_pctx(dev_priv);
 
-	if ((gtfifodbg = I915_READ(GTFIFODBG))) {
+	gtfifodbg = I915_READ(GTFIFODBG);
+	if (gtfifodbg) {
 		DRM_DEBUG_DRIVER("GT fifo had a previous error %x\n",
 				 gtfifodbg);
 		I915_WRITE(GTFIFODBG, gtfifodbg);
@@ -5588,8 +5710,8 @@ static void valleyview_enable_rps(struct
 	I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000);
 	I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25);
 
-	for_each_ring(ring, dev_priv, i)
-		I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10);
+	for_each_engine(engine, dev_priv)
+		I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10);
 
 	I915_WRITE(GEN6_RC6_THRESHOLD, 0x557);
 
@@ -5627,10 +5749,10 @@ static void valleyview_enable_rps(struct
 			 dev_priv->rps.cur_freq);
 
 	DRM_DEBUG_DRIVER("setting GPU freq to %d MHz (%u)\n",
-			 intel_gpu_freq(dev_priv, dev_priv->rps.efficient_freq),
-			 dev_priv->rps.efficient_freq);
+			 intel_gpu_freq(dev_priv, dev_priv->rps.idle_freq),
+			 dev_priv->rps.idle_freq);
 
-	valleyview_set_rps(dev_priv->dev, dev_priv->rps.efficient_freq);
+	valleyview_set_rps(dev_priv->dev, dev_priv->rps.idle_freq);
 
 	intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
 }
@@ -5965,17 +6087,16 @@ EXPORT_SYMBOL_GPL(i915_gpu_lower);
 bool i915_gpu_busy(void)
 {
 	struct drm_i915_private *dev_priv;
-	struct intel_engine_cs *ring;
+	struct intel_engine_cs *engine;
 	bool ret = false;
-	int i;
 
 	spin_lock_irq(&mchdev_lock);
 	if (!i915_mch_dev)
 		goto out_unlock;
 	dev_priv = i915_mch_dev;
 
-	for_each_ring(ring, dev_priv, i)
-		ret |= !list_empty(&ring->request_list);
+	for_each_engine(engine, dev_priv)
+		ret |= !list_empty(&engine->request_list);
 
 out_unlock:
 	spin_unlock_irq(&mchdev_lock);
@@ -6195,9 +6316,10 @@ void intel_disable_gt_powersave(struct d
 		intel_suspend_gt_powersave(dev);
 
 		mutex_lock(&dev_priv->rps.hw_lock);
-		if (INTEL_INFO(dev)->gen >= 9)
+		if (INTEL_INFO(dev)->gen >= 9) {
+			gen9_disable_rc6(dev);
 			gen9_disable_rps(dev);
-		else if (IS_CHERRYVIEW(dev))
+		} else if (IS_CHERRYVIEW(dev))
 			cherryview_disable_rps(dev);
 		else if (IS_VALLEYVIEW(dev))
 			valleyview_disable_rps(dev);
@@ -6604,6 +6726,38 @@ static void lpt_suspend_hw(struct drm_de
 	}
 }
 
+static void kabylake_init_clock_gating(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	gen9_init_clock_gating(dev);
+
+	/* WaDisableSDEUnitClockGating:kbl */
+	if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_B0))
+		I915_WRITE(GEN8_UCGCTL6, I915_READ(GEN8_UCGCTL6) |
+			   GEN8_SDEUNIT_CLOCK_GATE_DISABLE);
+
+	/* WaDisableGamClockGating:kbl */
+	if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_B0))
+		I915_WRITE(GEN6_UCGCTL1, I915_READ(GEN6_UCGCTL1) |
+			   GEN6_GAMUNIT_CLOCK_GATE_DISABLE);
+
+	/* WaFbcNukeOnHostModify:kbl */
+	I915_WRITE(ILK_DPFC_CHICKEN, I915_READ(ILK_DPFC_CHICKEN) |
+		   ILK_DPFC_NUKE_ON_ANY_MODIFICATION);
+}
+
+static void skylake_init_clock_gating(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	gen9_init_clock_gating(dev);
+
+	/* WaFbcNukeOnHostModify:skl */
+	I915_WRITE(ILK_DPFC_CHICKEN, I915_READ(ILK_DPFC_CHICKEN) |
+		   ILK_DPFC_NUKE_ON_ANY_MODIFICATION);
+}
+
 static void broadwell_init_clock_gating(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -6818,23 +6972,10 @@ static void ivybridge_init_clock_gating(
 	gen6_check_mch_setup(dev);
 }
 
-static void vlv_init_display_clock_gating(struct drm_i915_private *dev_priv)
-{
-	I915_WRITE(DSPCLK_GATE_D, VRHUNIT_CLOCK_GATE_DISABLE);
-
-	/*
-	 * Disable trickle feed and enable pnd deadline calculation
-	 */
-	I915_WRITE(MI_ARB_VLV, MI_ARB_DISPLAY_TRICKLE_FEED_DISABLE);
-	I915_WRITE(CBR1_VLV, 0);
-}
-
 static void valleyview_init_clock_gating(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	vlv_init_display_clock_gating(dev_priv);
-
 	/* WaDisableEarlyCull:vlv */
 	I915_WRITE(_3D_CHICKEN3,
 		   _MASKED_BIT_ENABLE(_3D_CHICKEN_SF_DISABLE_OBJEND_CULL));
@@ -6917,8 +7058,6 @@ static void cherryview_init_clock_gating
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	vlv_init_display_clock_gating(dev_priv);
-
 	/* WaVSRefCountFullforceMissDisable:chv */
 	/* WaDSRefCountFullforceMissDisable:chv */
 	I915_WRITE(GEN7_FF_THREAD_MODE,
@@ -7058,8 +7197,7 @@ void intel_init_clock_gating(struct drm_
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	if (dev_priv->display.init_clock_gating)
-		dev_priv->display.init_clock_gating(dev);
+	dev_priv->display.init_clock_gating(dev);
 }
 
 void intel_suspend_hw(struct drm_device *dev)
@@ -7068,6 +7206,60 @@ void intel_suspend_hw(struct drm_device
 		lpt_suspend_hw(dev);
 }
 
+static void nop_init_clock_gating(struct drm_device *dev)
+{
+	DRM_DEBUG_KMS("No clock gating settings or workarounds applied.\n");
+}
+
+/**
+ * intel_init_clock_gating_hooks - setup the clock gating hooks
+ * @dev_priv: device private
+ *
+ * Setup the hooks that configure which clocks of a given platform can be
+ * gated and also apply various GT and display specific workarounds for these
+ * platforms. Note that some GT specific workarounds are applied separately
+ * when GPU contexts or batchbuffers start their execution.
+ */
+void intel_init_clock_gating_hooks(struct drm_i915_private *dev_priv)
+{
+	if (IS_SKYLAKE(dev_priv))
+		dev_priv->display.init_clock_gating = skylake_init_clock_gating;
+	else if (IS_KABYLAKE(dev_priv))
+		dev_priv->display.init_clock_gating = kabylake_init_clock_gating;
+	else if (IS_BROXTON(dev_priv))
+		dev_priv->display.init_clock_gating = bxt_init_clock_gating;
+	else if (IS_BROADWELL(dev_priv))
+		dev_priv->display.init_clock_gating = broadwell_init_clock_gating;
+	else if (IS_CHERRYVIEW(dev_priv))
+		dev_priv->display.init_clock_gating = cherryview_init_clock_gating;
+	else if (IS_HASWELL(dev_priv))
+		dev_priv->display.init_clock_gating = haswell_init_clock_gating;
+	else if (IS_IVYBRIDGE(dev_priv))
+		dev_priv->display.init_clock_gating = ivybridge_init_clock_gating;
+	else if (IS_VALLEYVIEW(dev_priv))
+		dev_priv->display.init_clock_gating = valleyview_init_clock_gating;
+	else if (IS_GEN6(dev_priv))
+		dev_priv->display.init_clock_gating = gen6_init_clock_gating;
+	else if (IS_GEN5(dev_priv))
+		dev_priv->display.init_clock_gating = ironlake_init_clock_gating;
+	else if (IS_G4X(dev_priv))
+		dev_priv->display.init_clock_gating = g4x_init_clock_gating;
+	else if (IS_CRESTLINE(dev_priv))
+		dev_priv->display.init_clock_gating = crestline_init_clock_gating;
+	else if (IS_BROADWATER(dev_priv))
+		dev_priv->display.init_clock_gating = broadwater_init_clock_gating;
+	else if (IS_GEN3(dev_priv))
+		dev_priv->display.init_clock_gating = gen3_init_clock_gating;
+	else if (IS_I85X(dev_priv) || IS_I865G(dev_priv))
+		dev_priv->display.init_clock_gating = i85x_init_clock_gating;
+	else if (IS_GEN2(dev_priv))
+		dev_priv->display.init_clock_gating = i830_init_clock_gating;
+	else {
+		MISSING_CASE(INTEL_DEVID(dev_priv));
+		dev_priv->display.init_clock_gating = nop_init_clock_gating;
+	}
+}
+
 /* Set up chip specific power management-related functions */
 void intel_init_pm(struct drm_device *dev)
 {
@@ -7084,10 +7276,6 @@ void intel_init_pm(struct drm_device *de
 	/* For FIFO watermark updates */
 	if (INTEL_INFO(dev)->gen >= 9) {
 		skl_setup_wm_latency(dev);
-
-		if (IS_BROXTON(dev))
-			dev_priv->display.init_clock_gating =
-				bxt_init_clock_gating;
 		dev_priv->display.update_wm = skl_update_wm;
 	} else if (HAS_PCH_SPLIT(dev)) {
 		ilk_setup_wm_latency(dev);
@@ -7096,36 +7284,23 @@ void intel_init_pm(struct drm_device *de
 		     dev_priv->wm.spr_latency[1] && dev_priv->wm.cur_latency[1]) ||
 		    (!IS_GEN5(dev) && dev_priv->wm.pri_latency[0] &&
 		     dev_priv->wm.spr_latency[0] && dev_priv->wm.cur_latency[0])) {
-			dev_priv->display.update_wm = ilk_update_wm;
 			dev_priv->display.compute_pipe_wm = ilk_compute_pipe_wm;
-			dev_priv->display.program_watermarks = ilk_program_watermarks;
+			dev_priv->display.compute_intermediate_wm =
+				ilk_compute_intermediate_wm;
+			dev_priv->display.initial_watermarks =
+				ilk_initial_watermarks;
+			dev_priv->display.optimize_watermarks =
+				ilk_optimize_watermarks;
 		} else {
 			DRM_DEBUG_KMS("Failed to read display plane latency. "
 				      "Disable CxSR\n");
 		}
-
-		if (IS_GEN5(dev))
-			dev_priv->display.init_clock_gating = ironlake_init_clock_gating;
-		else if (IS_GEN6(dev))
-			dev_priv->display.init_clock_gating = gen6_init_clock_gating;
-		else if (IS_IVYBRIDGE(dev))
-			dev_priv->display.init_clock_gating = ivybridge_init_clock_gating;
-		else if (IS_HASWELL(dev))
-			dev_priv->display.init_clock_gating = haswell_init_clock_gating;
-		else if (INTEL_INFO(dev)->gen == 8)
-			dev_priv->display.init_clock_gating = broadwell_init_clock_gating;
 	} else if (IS_CHERRYVIEW(dev)) {
 		vlv_setup_wm_latency(dev);
-
 		dev_priv->display.update_wm = vlv_update_wm;
-		dev_priv->display.init_clock_gating =
-			cherryview_init_clock_gating;
 	} else if (IS_VALLEYVIEW(dev)) {
 		vlv_setup_wm_latency(dev);
-
 		dev_priv->display.update_wm = vlv_update_wm;
-		dev_priv->display.init_clock_gating =
-			valleyview_init_clock_gating;
 	} else if (IS_PINEVIEW(dev)) {
 		if (!intel_get_cxsr_latency(IS_PINEVIEW_G(dev),
 					    dev_priv->is_ddr3,
@@ -7141,20 +7316,13 @@ void intel_init_pm(struct drm_device *de
 			dev_priv->display.update_wm = NULL;
 		} else
 			dev_priv->display.update_wm = pineview_update_wm;
-		dev_priv->display.init_clock_gating = gen3_init_clock_gating;
 	} else if (IS_G4X(dev)) {
 		dev_priv->display.update_wm = g4x_update_wm;
-		dev_priv->display.init_clock_gating = g4x_init_clock_gating;
 	} else if (IS_GEN4(dev)) {
 		dev_priv->display.update_wm = i965_update_wm;
-		if (IS_CRESTLINE(dev))
-			dev_priv->display.init_clock_gating = crestline_init_clock_gating;
-		else if (IS_BROADWATER(dev))
-			dev_priv->display.init_clock_gating = broadwater_init_clock_gating;
 	} else if (IS_GEN3(dev)) {
 		dev_priv->display.update_wm = i9xx_update_wm;
 		dev_priv->display.get_fifo_size = i9xx_get_fifo_size;
-		dev_priv->display.init_clock_gating = gen3_init_clock_gating;
 	} else if (IS_GEN2(dev)) {
 		if (INTEL_INFO(dev)->num_pipes == 1) {
 			dev_priv->display.update_wm = i845_update_wm;
@@ -7163,11 +7331,6 @@ void intel_init_pm(struct drm_device *de
 			dev_priv->display.update_wm = i9xx_update_wm;
 			dev_priv->display.get_fifo_size = i830_get_fifo_size;
 		}
-
-		if (IS_I85X(dev) || IS_I865G(dev))
-			dev_priv->display.init_clock_gating = i85x_init_clock_gating;
-		else
-			dev_priv->display.init_clock_gating = i830_init_clock_gating;
 	} else {
 		DRM_ERROR("unexpected fall-through in intel_init_pm\n");
 	}
@@ -7221,78 +7384,43 @@ int sandybridge_pcode_write(struct drm_i
 	return 0;
 }
 
-static int vlv_gpu_freq_div(unsigned int czclk_freq)
-{
-	switch (czclk_freq) {
-	case 200:
-		return 10;
-	case 267:
-		return 12;
-	case 320:
-	case 333:
-		return 16;
-	case 400:
-		return 20;
-	default:
-		return -1;
-	}
-}
-
 static int byt_gpu_freq(struct drm_i915_private *dev_priv, int val)
 {
-	int div, czclk_freq = DIV_ROUND_CLOSEST(dev_priv->czclk_freq, 1000);
-
-	div = vlv_gpu_freq_div(czclk_freq);
-	if (div < 0)
-		return div;
-
-	return DIV_ROUND_CLOSEST(czclk_freq * (val + 6 - 0xbd), div);
+	/*
+	 * N = val - 0xb7
+	 * Slow = Fast = GPLL ref * N
+	 */
+	return DIV_ROUND_CLOSEST(dev_priv->rps.gpll_ref_freq * (val - 0xb7), 1000);
 }
 
 static int byt_freq_opcode(struct drm_i915_private *dev_priv, int val)
 {
-	int mul, czclk_freq = DIV_ROUND_CLOSEST(dev_priv->czclk_freq, 1000);
-
-	mul = vlv_gpu_freq_div(czclk_freq);
-	if (mul < 0)
-		return mul;
-
-	return DIV_ROUND_CLOSEST(mul * val, czclk_freq) + 0xbd - 6;
+	return DIV_ROUND_CLOSEST(1000 * val, dev_priv->rps.gpll_ref_freq) + 0xb7;
 }
 
 static int chv_gpu_freq(struct drm_i915_private *dev_priv, int val)
 {
-	int div, czclk_freq = DIV_ROUND_CLOSEST(dev_priv->czclk_freq, 1000);
-
-	div = vlv_gpu_freq_div(czclk_freq);
-	if (div < 0)
-		return div;
-	div /= 2;
-
-	return DIV_ROUND_CLOSEST(czclk_freq * val, 2 * div) / 2;
+	/*
+	 * N = val / 2
+	 * CU (slow) = CU2x (fast) / 2 = GPLL ref * N / 2
+	 */
+	return DIV_ROUND_CLOSEST(dev_priv->rps.gpll_ref_freq * val, 2 * 2 * 1000);
 }
 
 static int chv_freq_opcode(struct drm_i915_private *dev_priv, int val)
 {
-	int mul, czclk_freq = DIV_ROUND_CLOSEST(dev_priv->czclk_freq, 1000);
-
-	mul = vlv_gpu_freq_div(czclk_freq);
-	if (mul < 0)
-		return mul;
-	mul /= 2;
-
 	/* CHV needs even values */
-	return DIV_ROUND_CLOSEST(val * 2 * mul, czclk_freq) * 2;
+	return DIV_ROUND_CLOSEST(2 * 1000 * val, dev_priv->rps.gpll_ref_freq) * 2;
 }
 
 int intel_gpu_freq(struct drm_i915_private *dev_priv, int val)
 {
-	if (IS_GEN9(dev_priv->dev))
+	if (IS_GEN9(dev_priv))
 		return DIV_ROUND_CLOSEST(val * GT_FREQUENCY_MULTIPLIER,
 					 GEN9_FREQ_SCALER);
-	else if (IS_CHERRYVIEW(dev_priv->dev))
+	else if (IS_CHERRYVIEW(dev_priv))
 		return chv_gpu_freq(dev_priv, val);
-	else if (IS_VALLEYVIEW(dev_priv->dev))
+	else if (IS_VALLEYVIEW(dev_priv))
 		return byt_gpu_freq(dev_priv, val);
 	else
 		return val * GT_FREQUENCY_MULTIPLIER;
@@ -7300,12 +7428,12 @@ int intel_gpu_freq(struct drm_i915_priva
 
 int intel_freq_opcode(struct drm_i915_private *dev_priv, int val)
 {
-	if (IS_GEN9(dev_priv->dev))
+	if (IS_GEN9(dev_priv))
 		return DIV_ROUND_CLOSEST(val * GEN9_FREQ_SCALER,
 					 GT_FREQUENCY_MULTIPLIER);
-	else if (IS_CHERRYVIEW(dev_priv->dev))
+	else if (IS_CHERRYVIEW(dev_priv))
 		return chv_freq_opcode(dev_priv, val);
-	else if (IS_VALLEYVIEW(dev_priv->dev))
+	else if (IS_VALLEYVIEW(dev_priv))
 		return byt_freq_opcode(dev_priv, val);
 	else
 		return DIV_ROUND_CLOSEST(val, GT_FREQUENCY_MULTIPLIER);
@@ -7322,7 +7450,7 @@ static void __intel_rps_boost_work(struc
 	struct drm_i915_gem_request *req = boost->req;
 
 	if (!i915_gem_request_completed(req, true))
-		gen6_rps_boost(to_i915(req->ring->dev), NULL,
+		gen6_rps_boost(to_i915(req->engine->dev), NULL,
 			       req->emitted_jiffies);
 
 	i915_gem_request_unreference__unlocked(req);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_psr.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_psr.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_psr.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_psr.c	2016-07-24 15:23:50.000000000 -0400
@@ -280,7 +280,10 @@ static void hsw_psr_enable_source(struct
 	 * with the 5 or 6 idle patterns.
 	 */
 	uint32_t idle_frames = max(6, dev_priv->vbt.psr.idle_frames);
-	uint32_t val = 0x0;
+	uint32_t val = EDP_PSR_ENABLE;
+
+	val |= max_sleep_time << EDP_PSR_MAX_SLEEP_TIME_SHIFT;
+	val |= idle_frames << EDP_PSR_IDLE_FRAME_SHIFT;
 
 	if (IS_HASWELL(dev))
 		val |= EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES;
@@ -288,14 +291,50 @@ static void hsw_psr_enable_source(struct
 	if (dev_priv->psr.link_standby)
 		val |= EDP_PSR_LINK_STANDBY;
 
-	I915_WRITE(EDP_PSR_CTL, val |
-		   max_sleep_time << EDP_PSR_MAX_SLEEP_TIME_SHIFT |
-		   idle_frames << EDP_PSR_IDLE_FRAME_SHIFT |
-		   EDP_PSR_ENABLE);
+	if (dev_priv->vbt.psr.tp1_wakeup_time > 5)
+		val |= EDP_PSR_TP1_TIME_2500us;
+	else if (dev_priv->vbt.psr.tp1_wakeup_time > 1)
+		val |= EDP_PSR_TP1_TIME_500us;
+	else if (dev_priv->vbt.psr.tp1_wakeup_time > 0)
+		val |= EDP_PSR_TP1_TIME_100us;
+	else
+		val |= EDP_PSR_TP1_TIME_0us;
 
-	if (dev_priv->psr.psr2_support)
-		I915_WRITE(EDP_PSR2_CTL, EDP_PSR2_ENABLE |
-				EDP_SU_TRACK_ENABLE | EDP_PSR2_TP2_TIME_100);
+	if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 5)
+		val |= EDP_PSR_TP2_TP3_TIME_2500us;
+	else if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 1)
+		val |= EDP_PSR_TP2_TP3_TIME_500us;
+	else if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 0)
+		val |= EDP_PSR_TP2_TP3_TIME_100us;
+	else
+		val |= EDP_PSR_TP2_TP3_TIME_0us;
+
+	if (intel_dp_source_supports_hbr2(intel_dp) &&
+	    drm_dp_tps3_supported(intel_dp->dpcd))
+		val |= EDP_PSR_TP1_TP3_SEL;
+	else
+		val |= EDP_PSR_TP1_TP2_SEL;
+
+	I915_WRITE(EDP_PSR_CTL, val);
+
+	if (!dev_priv->psr.psr2_support)
+		return;
+
+	/* FIXME: selective update is probably totally broken because it doesn't
+	 * mesh at all with our frontbuffer tracking. And the hw alone isn't
+	 * good enough. */
+	val = EDP_PSR2_ENABLE | EDP_SU_TRACK_ENABLE;
+
+	if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 5)
+		val |= EDP_PSR2_TP2_TIME_2500;
+	else if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 1)
+		val |= EDP_PSR2_TP2_TIME_500;
+	else if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 0)
+		val |= EDP_PSR2_TP2_TIME_100;
+	else
+		val |= EDP_PSR2_TP2_TIME_50;
+
+	I915_WRITE(EDP_PSR2_CTL, val);
 }
 
 static bool intel_psr_match_conditions(struct intel_dp *intel_dp)
@@ -507,7 +546,8 @@ static void hsw_psr_disable(struct intel
 
 		/* Wait till PSR is idle */
 		if (_wait_for((I915_READ(EDP_PSR_STATUS_CTL) &
-			       EDP_PSR_STATUS_STATE_MASK) == 0, 2000, 10))
+			       EDP_PSR_STATUS_STATE_MASK) == 0,
+			       2 * USEC_PER_SEC, 10 * USEC_PER_MSEC))
 			DRM_ERROR("Timed out waiting for PSR Idle State\n");
 
 		dev_priv->psr.active = false;
@@ -562,7 +602,7 @@ static void intel_psr_work(struct work_s
 	 * PSR might take some time to get fully disabled
 	 * and be ready for re-enable.
 	 */
-	if (HAS_DDI(dev_priv->dev)) {
+	if (HAS_DDI(dev_priv)) {
 		if (wait_for((I915_READ(EDP_PSR_STATUS_CTL) &
 			      EDP_PSR_STATUS_STATE_MASK) == 0, 50)) {
 			DRM_ERROR("Timed out waiting for PSR Idle for re-enable\n");
@@ -780,8 +820,7 @@ void intel_psr_init(struct drm_device *d
 
 	/* Per platform default */
 	if (i915.enable_psr == -1) {
-		if (IS_HASWELL(dev) || IS_BROADWELL(dev) ||
-		    IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
+		if (IS_HASWELL(dev) || IS_BROADWELL(dev))
 			i915.enable_psr = 1;
 		else
 			i915.enable_psr = 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_ringbuffer.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_ringbuffer.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_ringbuffer.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_ringbuffer.c	2016-07-24 15:23:50.000000000 -0400
@@ -53,25 +53,19 @@ void intel_ring_update_space(struct inte
 					    ringbuf->tail, ringbuf->size);
 }
 
-int intel_ring_space(struct intel_ringbuffer *ringbuf)
-{
-	intel_ring_update_space(ringbuf);
-	return ringbuf->space;
-}
-
-bool intel_ring_stopped(struct intel_engine_cs *ring)
+bool intel_engine_stopped(struct intel_engine_cs *engine)
 {
-	struct drm_i915_private *dev_priv = ring->dev->dev_private;
-	return dev_priv->gpu_error.stop_rings & intel_ring_flag(ring);
+	struct drm_i915_private *dev_priv = engine->dev->dev_private;
+	return dev_priv->gpu_error.stop_rings & intel_engine_flag(engine);
 }
 
-static void __intel_ring_advance(struct intel_engine_cs *ring)
+static void __intel_ring_advance(struct intel_engine_cs *engine)
 {
-	struct intel_ringbuffer *ringbuf = ring->buffer;
+	struct intel_ringbuffer *ringbuf = engine->buffer;
 	ringbuf->tail &= ringbuf->size - 1;
-	if (intel_ring_stopped(ring))
+	if (intel_engine_stopped(engine))
 		return;
-	ring->write_tail(ring, ringbuf->tail);
+	engine->write_tail(engine, ringbuf->tail);
 }
 
 static int
@@ -79,7 +73,7 @@ gen2_render_ring_flush(struct drm_i915_g
 		       u32	invalidate_domains,
 		       u32	flush_domains)
 {
-	struct intel_engine_cs *ring = req->ring;
+	struct intel_engine_cs *engine = req->engine;
 	u32 cmd;
 	int ret;
 
@@ -94,9 +88,9 @@ gen2_render_ring_flush(struct drm_i915_g
 	if (ret)
 		return ret;
 
-	intel_ring_emit(ring, cmd);
-	intel_ring_emit(ring, MI_NOOP);
-	intel_ring_advance(ring);
+	intel_ring_emit(engine, cmd);
+	intel_ring_emit(engine, MI_NOOP);
+	intel_ring_advance(engine);
 
 	return 0;
 }
@@ -106,8 +100,8 @@ gen4_render_ring_flush(struct drm_i915_g
 		       u32	invalidate_domains,
 		       u32	flush_domains)
 {
-	struct intel_engine_cs *ring = req->ring;
-	struct drm_device *dev = ring->dev;
+	struct intel_engine_cs *engine = req->engine;
+	struct drm_device *dev = engine->dev;
 	u32 cmd;
 	int ret;
 
@@ -153,9 +147,9 @@ gen4_render_ring_flush(struct drm_i915_g
 	if (ret)
 		return ret;
 
-	intel_ring_emit(ring, cmd);
-	intel_ring_emit(ring, MI_NOOP);
-	intel_ring_advance(ring);
+	intel_ring_emit(engine, cmd);
+	intel_ring_emit(engine, MI_NOOP);
+	intel_ring_advance(engine);
 
 	return 0;
 }
@@ -200,34 +194,34 @@ gen4_render_ring_flush(struct drm_i915_g
 static int
 intel_emit_post_sync_nonzero_flush(struct drm_i915_gem_request *req)
 {
-	struct intel_engine_cs *ring = req->ring;
-	u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES;
+	struct intel_engine_cs *engine = req->engine;
+	u32 scratch_addr = engine->scratch.gtt_offset + 2 * CACHELINE_BYTES;
 	int ret;
 
 	ret = intel_ring_begin(req, 6);
 	if (ret)
 		return ret;
 
-	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5));
-	intel_ring_emit(ring, PIPE_CONTROL_CS_STALL |
+	intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(5));
+	intel_ring_emit(engine, PIPE_CONTROL_CS_STALL |
 			PIPE_CONTROL_STALL_AT_SCOREBOARD);
-	intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */
-	intel_ring_emit(ring, 0); /* low dword */
-	intel_ring_emit(ring, 0); /* high dword */
-	intel_ring_emit(ring, MI_NOOP);
-	intel_ring_advance(ring);
+	intel_ring_emit(engine, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */
+	intel_ring_emit(engine, 0); /* low dword */
+	intel_ring_emit(engine, 0); /* high dword */
+	intel_ring_emit(engine, MI_NOOP);
+	intel_ring_advance(engine);
 
 	ret = intel_ring_begin(req, 6);
 	if (ret)
 		return ret;
 
-	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5));
-	intel_ring_emit(ring, PIPE_CONTROL_QW_WRITE);
-	intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */
-	intel_ring_emit(ring, 0);
-	intel_ring_emit(ring, 0);
-	intel_ring_emit(ring, MI_NOOP);
-	intel_ring_advance(ring);
+	intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(5));
+	intel_ring_emit(engine, PIPE_CONTROL_QW_WRITE);
+	intel_ring_emit(engine, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); /* address */
+	intel_ring_emit(engine, 0);
+	intel_ring_emit(engine, 0);
+	intel_ring_emit(engine, MI_NOOP);
+	intel_ring_advance(engine);
 
 	return 0;
 }
@@ -236,9 +230,9 @@ static int
 gen6_render_ring_flush(struct drm_i915_gem_request *req,
 		       u32 invalidate_domains, u32 flush_domains)
 {
-	struct intel_engine_cs *ring = req->ring;
+	struct intel_engine_cs *engine = req->engine;
 	u32 flags = 0;
-	u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES;
+	u32 scratch_addr = engine->scratch.gtt_offset + 2 * CACHELINE_BYTES;
 	int ret;
 
 	/* Force SNB workarounds for PIPE_CONTROL flushes */
@@ -276,11 +270,11 @@ gen6_render_ring_flush(struct drm_i915_g
 	if (ret)
 		return ret;
 
-	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4));
-	intel_ring_emit(ring, flags);
-	intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT);
-	intel_ring_emit(ring, 0);
-	intel_ring_advance(ring);
+	intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(4));
+	intel_ring_emit(engine, flags);
+	intel_ring_emit(engine, scratch_addr | PIPE_CONTROL_GLOBAL_GTT);
+	intel_ring_emit(engine, 0);
+	intel_ring_advance(engine);
 
 	return 0;
 }
@@ -288,19 +282,19 @@ gen6_render_ring_flush(struct drm_i915_g
 static int
 gen7_render_ring_cs_stall_wa(struct drm_i915_gem_request *req)
 {
-	struct intel_engine_cs *ring = req->ring;
+	struct intel_engine_cs *engine = req->engine;
 	int ret;
 
 	ret = intel_ring_begin(req, 4);
 	if (ret)
 		return ret;
 
-	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4));
-	intel_ring_emit(ring, PIPE_CONTROL_CS_STALL |
+	intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(4));
+	intel_ring_emit(engine, PIPE_CONTROL_CS_STALL |
 			      PIPE_CONTROL_STALL_AT_SCOREBOARD);
-	intel_ring_emit(ring, 0);
-	intel_ring_emit(ring, 0);
-	intel_ring_advance(ring);
+	intel_ring_emit(engine, 0);
+	intel_ring_emit(engine, 0);
+	intel_ring_advance(engine);
 
 	return 0;
 }
@@ -309,9 +303,9 @@ static int
 gen7_render_ring_flush(struct drm_i915_gem_request *req,
 		       u32 invalidate_domains, u32 flush_domains)
 {
-	struct intel_engine_cs *ring = req->ring;
+	struct intel_engine_cs *engine = req->engine;
 	u32 flags = 0;
-	u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES;
+	u32 scratch_addr = engine->scratch.gtt_offset + 2 * CACHELINE_BYTES;
 	int ret;
 
 	/*
@@ -360,11 +354,11 @@ gen7_render_ring_flush(struct drm_i915_g
 	if (ret)
 		return ret;
 
-	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4));
-	intel_ring_emit(ring, flags);
-	intel_ring_emit(ring, scratch_addr);
-	intel_ring_emit(ring, 0);
-	intel_ring_advance(ring);
+	intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(4));
+	intel_ring_emit(engine, flags);
+	intel_ring_emit(engine, scratch_addr);
+	intel_ring_emit(engine, 0);
+	intel_ring_advance(engine);
 
 	return 0;
 }
@@ -373,20 +367,20 @@ static int
 gen8_emit_pipe_control(struct drm_i915_gem_request *req,
 		       u32 flags, u32 scratch_addr)
 {
-	struct intel_engine_cs *ring = req->ring;
+	struct intel_engine_cs *engine = req->engine;
 	int ret;
 
 	ret = intel_ring_begin(req, 6);
 	if (ret)
 		return ret;
 
-	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(6));
-	intel_ring_emit(ring, flags);
-	intel_ring_emit(ring, scratch_addr);
-	intel_ring_emit(ring, 0);
-	intel_ring_emit(ring, 0);
-	intel_ring_emit(ring, 0);
-	intel_ring_advance(ring);
+	intel_ring_emit(engine, GFX_OP_PIPE_CONTROL(6));
+	intel_ring_emit(engine, flags);
+	intel_ring_emit(engine, scratch_addr);
+	intel_ring_emit(engine, 0);
+	intel_ring_emit(engine, 0);
+	intel_ring_emit(engine, 0);
+	intel_ring_advance(engine);
 
 	return 0;
 }
@@ -396,7 +390,7 @@ gen8_render_ring_flush(struct drm_i915_g
 		       u32 invalidate_domains, u32 flush_domains)
 {
 	u32 flags = 0;
-	u32 scratch_addr = req->ring->scratch.gtt_offset + 2 * CACHELINE_BYTES;
+	u32 scratch_addr = req->engine->scratch.gtt_offset + 2 * CACHELINE_BYTES;
 	int ret;
 
 	flags |= PIPE_CONTROL_CS_STALL;
@@ -429,51 +423,51 @@ gen8_render_ring_flush(struct drm_i915_g
 	return gen8_emit_pipe_control(req, flags, scratch_addr);
 }
 
-static void ring_write_tail(struct intel_engine_cs *ring,
+static void ring_write_tail(struct intel_engine_cs *engine,
 			    u32 value)
 {
-	struct drm_i915_private *dev_priv = ring->dev->dev_private;
-	I915_WRITE_TAIL(ring, value);
+	struct drm_i915_private *dev_priv = engine->dev->dev_private;
+	I915_WRITE_TAIL(engine, value);
 }
 
-u64 intel_ring_get_active_head(struct intel_engine_cs *ring)
+u64 intel_ring_get_active_head(struct intel_engine_cs *engine)
 {
-	struct drm_i915_private *dev_priv = ring->dev->dev_private;
+	struct drm_i915_private *dev_priv = engine->dev->dev_private;
 	u64 acthd;
 
-	if (INTEL_INFO(ring->dev)->gen >= 8)
-		acthd = I915_READ64_2x32(RING_ACTHD(ring->mmio_base),
-					 RING_ACTHD_UDW(ring->mmio_base));
-	else if (INTEL_INFO(ring->dev)->gen >= 4)
-		acthd = I915_READ(RING_ACTHD(ring->mmio_base));
+	if (INTEL_INFO(engine->dev)->gen >= 8)
+		acthd = I915_READ64_2x32(RING_ACTHD(engine->mmio_base),
+					 RING_ACTHD_UDW(engine->mmio_base));
+	else if (INTEL_INFO(engine->dev)->gen >= 4)
+		acthd = I915_READ(RING_ACTHD(engine->mmio_base));
 	else
 		acthd = I915_READ(ACTHD);
 
 	return acthd;
 }
 
-static void ring_setup_phys_status_page(struct intel_engine_cs *ring)
+static void ring_setup_phys_status_page(struct intel_engine_cs *engine)
 {
-	struct drm_i915_private *dev_priv = ring->dev->dev_private;
+	struct drm_i915_private *dev_priv = engine->dev->dev_private;
 	u32 addr;
 
 	addr = dev_priv->status_page_dmah->busaddr;
-	if (INTEL_INFO(ring->dev)->gen >= 4)
+	if (INTEL_INFO(engine->dev)->gen >= 4)
 		addr |= (dev_priv->status_page_dmah->busaddr >> 28) & 0xf0;
 	I915_WRITE(HWS_PGA, addr);
 }
 
-static void intel_ring_setup_status_page(struct intel_engine_cs *ring)
+static void intel_ring_setup_status_page(struct intel_engine_cs *engine)
 {
-	struct drm_device *dev = ring->dev;
-	struct drm_i915_private *dev_priv = ring->dev->dev_private;
+	struct drm_device *dev = engine->dev;
+	struct drm_i915_private *dev_priv = engine->dev->dev_private;
 	i915_reg_t mmio;
 
 	/* The ring status page addresses are no longer next to the rest of
 	 * the ring registers as of gen7.
 	 */
 	if (IS_GEN7(dev)) {
-		switch (ring->id) {
+		switch (engine->id) {
 		case RCS:
 			mmio = RENDER_HWS_PGA_GEN7;
 			break;
@@ -492,14 +486,14 @@ static void intel_ring_setup_status_page
 			mmio = VEBOX_HWS_PGA_GEN7;
 			break;
 		}
-	} else if (IS_GEN6(ring->dev)) {
-		mmio = RING_HWS_PGA_GEN6(ring->mmio_base);
+	} else if (IS_GEN6(engine->dev)) {
+		mmio = RING_HWS_PGA_GEN6(engine->mmio_base);
 	} else {
 		/* XXX: gen8 returns to sanity */
-		mmio = RING_HWS_PGA(ring->mmio_base);
+		mmio = RING_HWS_PGA(engine->mmio_base);
 	}
 
-	I915_WRITE(mmio, (u32)ring->status_page.gfx_addr);
+	I915_WRITE(mmio, (u32)engine->status_page.gfx_addr);
 	POSTING_READ(mmio);
 
 	/*
@@ -510,10 +504,10 @@ static void intel_ring_setup_status_page
 	 * invalidating the TLB?
 	 */
 	if (INTEL_INFO(dev)->gen >= 6 && INTEL_INFO(dev)->gen < 8) {
-		i915_reg_t reg = RING_INSTPM(ring->mmio_base);
+		i915_reg_t reg = RING_INSTPM(engine->mmio_base);
 
 		/* ring should be idle before issuing a sync flush*/
-		WARN_ON((I915_READ_MODE(ring) & MODE_IDLE) == 0);
+		WARN_ON((I915_READ_MODE(engine) & MODE_IDLE) == 0);
 
 		I915_WRITE(reg,
 			   _MASKED_BIT_ENABLE(INSTPM_TLB_INVALIDATE |
@@ -521,117 +515,125 @@ static void intel_ring_setup_status_page
 		if (wait_for((I915_READ(reg) & INSTPM_SYNC_FLUSH) == 0,
 			     1000))
 			DRM_ERROR("%s: wait for SyncFlush to complete for TLB invalidation timed out\n",
-				  ring->name);
+				  engine->name);
 	}
 }
 
-static bool stop_ring(struct intel_engine_cs *ring)
+static bool stop_ring(struct intel_engine_cs *engine)
 {
-	struct drm_i915_private *dev_priv = to_i915(ring->dev);
+	struct drm_i915_private *dev_priv = to_i915(engine->dev);
 
-	if (!IS_GEN2(ring->dev)) {
-		I915_WRITE_MODE(ring, _MASKED_BIT_ENABLE(STOP_RING));
-		if (wait_for((I915_READ_MODE(ring) & MODE_IDLE) != 0, 1000)) {
-			DRM_ERROR("%s : timed out trying to stop ring\n", ring->name);
+	if (!IS_GEN2(engine->dev)) {
+		I915_WRITE_MODE(engine, _MASKED_BIT_ENABLE(STOP_RING));
+		if (wait_for((I915_READ_MODE(engine) & MODE_IDLE) != 0, 1000)) {
+			DRM_ERROR("%s : timed out trying to stop ring\n",
+				  engine->name);
 			/* Sometimes we observe that the idle flag is not
 			 * set even though the ring is empty. So double
 			 * check before giving up.
 			 */
-			if (I915_READ_HEAD(ring) != I915_READ_TAIL(ring))
+			if (I915_READ_HEAD(engine) != I915_READ_TAIL(engine))
 				return false;
 		}
 	}
 
-	I915_WRITE_CTL(ring, 0);
-	I915_WRITE_HEAD(ring, 0);
-	ring->write_tail(ring, 0);
+	I915_WRITE_CTL(engine, 0);
+	I915_WRITE_HEAD(engine, 0);
+	engine->write_tail(engine, 0);
 
-	if (!IS_GEN2(ring->dev)) {
-		(void)I915_READ_CTL(ring);
-		I915_WRITE_MODE(ring, _MASKED_BIT_DISABLE(STOP_RING));
+	if (!IS_GEN2(engine->dev)) {
+		(void)I915_READ_CTL(engine);
+		I915_WRITE_MODE(engine, _MASKED_BIT_DISABLE(STOP_RING));
 	}
 
-	return (I915_READ_HEAD(ring) & HEAD_ADDR) == 0;
+	return (I915_READ_HEAD(engine) & HEAD_ADDR) == 0;
 }
 
-static int init_ring_common(struct intel_engine_cs *ring)
+void intel_engine_init_hangcheck(struct intel_engine_cs *engine)
 {
-	struct drm_device *dev = ring->dev;
+	memset(&engine->hangcheck, 0, sizeof(engine->hangcheck));
+}
+
+static int init_ring_common(struct intel_engine_cs *engine)
+{
+	struct drm_device *dev = engine->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_ringbuffer *ringbuf = ring->buffer;
+	struct intel_ringbuffer *ringbuf = engine->buffer;
 	struct drm_i915_gem_object *obj = ringbuf->obj;
 	int ret = 0;
 
 	intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
 
-	if (!stop_ring(ring)) {
+	if (!stop_ring(engine)) {
 		/* G45 ring initialization often fails to reset head to zero */
 		DRM_DEBUG_KMS("%s head not reset to zero "
 			      "ctl %08x head %08x tail %08x start %08x\n",
-			      ring->name,
-			      I915_READ_CTL(ring),
-			      I915_READ_HEAD(ring),
-			      I915_READ_TAIL(ring),
-			      I915_READ_START(ring));
+			      engine->name,
+			      I915_READ_CTL(engine),
+			      I915_READ_HEAD(engine),
+			      I915_READ_TAIL(engine),
+			      I915_READ_START(engine));
 
-		if (!stop_ring(ring)) {
+		if (!stop_ring(engine)) {
 			DRM_ERROR("failed to set %s head to zero "
 				  "ctl %08x head %08x tail %08x start %08x\n",
-				  ring->name,
-				  I915_READ_CTL(ring),
-				  I915_READ_HEAD(ring),
-				  I915_READ_TAIL(ring),
-				  I915_READ_START(ring));
+				  engine->name,
+				  I915_READ_CTL(engine),
+				  I915_READ_HEAD(engine),
+				  I915_READ_TAIL(engine),
+				  I915_READ_START(engine));
 			ret = -EIO;
 			goto out;
 		}
 	}
 
 	if (I915_NEED_GFX_HWS(dev))
-		intel_ring_setup_status_page(ring);
+		intel_ring_setup_status_page(engine);
 	else
-		ring_setup_phys_status_page(ring);
+		ring_setup_phys_status_page(engine);
 
 	/* Enforce ordering by reading HEAD register back */
-	I915_READ_HEAD(ring);
+	I915_READ_HEAD(engine);
 
 	/* Initialize the ring. This must happen _after_ we've cleared the ring
 	 * registers with the above sequence (the readback of the HEAD registers
 	 * also enforces ordering), otherwise the hw might lose the new ring
 	 * register values. */
-	I915_WRITE_START(ring, i915_gem_obj_ggtt_offset(obj));
+	I915_WRITE_START(engine, i915_gem_obj_ggtt_offset(obj));
 
 	/* WaClearRingBufHeadRegAtInit:ctg,elk */
-	if (I915_READ_HEAD(ring))
+	if (I915_READ_HEAD(engine))
 		DRM_DEBUG("%s initialization failed [head=%08x], fudging\n",
-			  ring->name, I915_READ_HEAD(ring));
-	I915_WRITE_HEAD(ring, 0);
-	(void)I915_READ_HEAD(ring);
+			  engine->name, I915_READ_HEAD(engine));
+	I915_WRITE_HEAD(engine, 0);
+	(void)I915_READ_HEAD(engine);
 
-	I915_WRITE_CTL(ring,
+	I915_WRITE_CTL(engine,
 			((ringbuf->size - PAGE_SIZE) & RING_NR_PAGES)
 			| RING_VALID);
 
 	/* If the head is still not zero, the ring is dead */
-	if (wait_for((I915_READ_CTL(ring) & RING_VALID) != 0 &&
-		     I915_READ_START(ring) == i915_gem_obj_ggtt_offset(obj) &&
-		     (I915_READ_HEAD(ring) & HEAD_ADDR) == 0, 50)) {
+	if (wait_for((I915_READ_CTL(engine) & RING_VALID) != 0 &&
+		     I915_READ_START(engine) == i915_gem_obj_ggtt_offset(obj) &&
+		     (I915_READ_HEAD(engine) & HEAD_ADDR) == 0, 50)) {
 		DRM_ERROR("%s initialization failed "
 			  "ctl %08x (valid? %d) head %08x tail %08x start %08x [expected %08lx]\n",
-			  ring->name,
-			  I915_READ_CTL(ring), I915_READ_CTL(ring) & RING_VALID,
-			  I915_READ_HEAD(ring), I915_READ_TAIL(ring),
-			  I915_READ_START(ring), (unsigned long)i915_gem_obj_ggtt_offset(obj));
+			  engine->name,
+			  I915_READ_CTL(engine),
+			  I915_READ_CTL(engine) & RING_VALID,
+			  I915_READ_HEAD(engine), I915_READ_TAIL(engine),
+			  I915_READ_START(engine),
+			  (unsigned long)i915_gem_obj_ggtt_offset(obj));
 		ret = -EIO;
 		goto out;
 	}
 
 	ringbuf->last_retired_head = -1;
-	ringbuf->head = I915_READ_HEAD(ring);
-	ringbuf->tail = I915_READ_TAIL(ring) & TAIL_ADDR;
+	ringbuf->head = I915_READ_HEAD(engine);
+	ringbuf->tail = I915_READ_TAIL(engine) & TAIL_ADDR;
 	intel_ring_update_space(ringbuf);
 
-	memset(&ring->hangcheck, 0, sizeof(ring->hangcheck));
+	intel_engine_init_hangcheck(engine);
 
 out:
 	intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
@@ -640,59 +642,60 @@ out:
 }
 
 void
-intel_fini_pipe_control(struct intel_engine_cs *ring)
+intel_fini_pipe_control(struct intel_engine_cs *engine)
 {
-	struct drm_device *dev = ring->dev;
+	struct drm_device *dev = engine->dev;
 
-	if (ring->scratch.obj == NULL)
+	if (engine->scratch.obj == NULL)
 		return;
 
 	if (INTEL_INFO(dev)->gen >= 5) {
-		kunmap(sg_page(ring->scratch.obj->pages->sgl));
-		i915_gem_object_ggtt_unpin(ring->scratch.obj);
+		kunmap(sg_page(engine->scratch.obj->pages->sgl));
+		i915_gem_object_ggtt_unpin(engine->scratch.obj);
 	}
 
-	drm_gem_object_unreference(&ring->scratch.obj->base);
-	ring->scratch.obj = NULL;
+	drm_gem_object_unreference(&engine->scratch.obj->base);
+	engine->scratch.obj = NULL;
 }
 
 int
-intel_init_pipe_control(struct intel_engine_cs *ring)
+intel_init_pipe_control(struct intel_engine_cs *engine)
 {
 	int ret;
 
-	WARN_ON(ring->scratch.obj);
+	WARN_ON(engine->scratch.obj);
 
-	ring->scratch.obj = i915_gem_alloc_object(ring->dev, 4096);
-	if (ring->scratch.obj == NULL) {
+	engine->scratch.obj = i915_gem_alloc_object(engine->dev, 4096);
+	if (engine->scratch.obj == NULL) {
 		DRM_ERROR("Failed to allocate seqno page\n");
 		ret = -ENOMEM;
 		goto err;
 	}
 
-	ret = i915_gem_object_set_cache_level(ring->scratch.obj, I915_CACHE_LLC);
+	ret = i915_gem_object_set_cache_level(engine->scratch.obj,
+					      I915_CACHE_LLC);
 	if (ret)
 		goto err_unref;
 
-	ret = i915_gem_obj_ggtt_pin(ring->scratch.obj, 4096, 0);
+	ret = i915_gem_obj_ggtt_pin(engine->scratch.obj, 4096, 0);
 	if (ret)
 		goto err_unref;
 
-	ring->scratch.gtt_offset = i915_gem_obj_ggtt_offset(ring->scratch.obj);
-	ring->scratch.cpu_page = kmap(sg_page(ring->scratch.obj->pages->sgl));
-	if (ring->scratch.cpu_page == NULL) {
+	engine->scratch.gtt_offset = i915_gem_obj_ggtt_offset(engine->scratch.obj);
+	engine->scratch.cpu_page = kmap(sg_page(engine->scratch.obj->pages->sgl));
+	if (engine->scratch.cpu_page == NULL) {
 		ret = -ENOMEM;
 		goto err_unpin;
 	}
 
 	DRM_DEBUG_DRIVER("%s pipe control offset: 0x%08x\n",
-			 ring->name, ring->scratch.gtt_offset);
+			 engine->name, engine->scratch.gtt_offset);
 	return 0;
 
 err_unpin:
-	i915_gem_object_ggtt_unpin(ring->scratch.obj);
+	i915_gem_object_ggtt_unpin(engine->scratch.obj);
 err_unref:
-	drm_gem_object_unreference(&ring->scratch.obj->base);
+	drm_gem_object_unreference(&engine->scratch.obj->base);
 err:
 	return ret;
 }
@@ -700,15 +703,15 @@ err:
 static int intel_ring_workarounds_emit(struct drm_i915_gem_request *req)
 {
 	int ret, i;
-	struct intel_engine_cs *ring = req->ring;
-	struct drm_device *dev = ring->dev;
+	struct intel_engine_cs *engine = req->engine;
+	struct drm_device *dev = engine->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct i915_workarounds *w = &dev_priv->workarounds;
 
 	if (w->count == 0)
 		return 0;
 
-	ring->gpu_caches_dirty = true;
+	engine->gpu_caches_dirty = true;
 	ret = intel_ring_flush_all_caches(req);
 	if (ret)
 		return ret;
@@ -717,16 +720,16 @@ static int intel_ring_workarounds_emit(s
 	if (ret)
 		return ret;
 
-	intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(w->count));
+	intel_ring_emit(engine, MI_LOAD_REGISTER_IMM(w->count));
 	for (i = 0; i < w->count; i++) {
-		intel_ring_emit_reg(ring, w->reg[i].addr);
-		intel_ring_emit(ring, w->reg[i].value);
+		intel_ring_emit_reg(engine, w->reg[i].addr);
+		intel_ring_emit(engine, w->reg[i].value);
 	}
-	intel_ring_emit(ring, MI_NOOP);
+	intel_ring_emit(engine, MI_NOOP);
 
-	intel_ring_advance(ring);
+	intel_ring_advance(engine);
 
-	ring->gpu_caches_dirty = true;
+	engine->gpu_caches_dirty = true;
 	ret = intel_ring_flush_all_caches(req);
 	if (ret)
 		return ret;
@@ -789,25 +792,26 @@ static int wa_add(struct drm_i915_privat
 
 #define WA_WRITE(addr, val) WA_REG(addr, 0xffffffff, val)
 
-static int wa_ring_whitelist_reg(struct intel_engine_cs *ring, i915_reg_t reg)
+static int wa_ring_whitelist_reg(struct intel_engine_cs *engine,
+				 i915_reg_t reg)
 {
-	struct drm_i915_private *dev_priv = ring->dev->dev_private;
+	struct drm_i915_private *dev_priv = engine->dev->dev_private;
 	struct i915_workarounds *wa = &dev_priv->workarounds;
-	const uint32_t index = wa->hw_whitelist_count[ring->id];
+	const uint32_t index = wa->hw_whitelist_count[engine->id];
 
 	if (WARN_ON(index >= RING_MAX_NONPRIV_SLOTS))
 		return -EINVAL;
 
-	WA_WRITE(RING_FORCE_TO_NONPRIV(ring->mmio_base, index),
+	WA_WRITE(RING_FORCE_TO_NONPRIV(engine->mmio_base, index),
 		 i915_mmio_reg_offset(reg));
-	wa->hw_whitelist_count[ring->id]++;
+	wa->hw_whitelist_count[engine->id]++;
 
 	return 0;
 }
 
-static int gen8_init_workarounds(struct intel_engine_cs *ring)
+static int gen8_init_workarounds(struct intel_engine_cs *engine)
 {
-	struct drm_device *dev = ring->dev;
+	struct drm_device *dev = engine->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	WA_SET_BIT_MASKED(INSTPM, INSTPM_FORCE_ORDERING);
@@ -857,13 +861,13 @@ static int gen8_init_workarounds(struct
 	return 0;
 }
 
-static int bdw_init_workarounds(struct intel_engine_cs *ring)
+static int bdw_init_workarounds(struct intel_engine_cs *engine)
 {
 	int ret;
-	struct drm_device *dev = ring->dev;
+	struct drm_device *dev = engine->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	ret = gen8_init_workarounds(ring);
+	ret = gen8_init_workarounds(engine);
 	if (ret)
 		return ret;
 
@@ -886,13 +890,13 @@ static int bdw_init_workarounds(struct i
 	return 0;
 }
 
-static int chv_init_workarounds(struct intel_engine_cs *ring)
+static int chv_init_workarounds(struct intel_engine_cs *engine)
 {
 	int ret;
-	struct drm_device *dev = ring->dev;
+	struct drm_device *dev = engine->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	ret = gen8_init_workarounds(ring);
+	ret = gen8_init_workarounds(engine);
 	if (ret)
 		return ret;
 
@@ -905,26 +909,30 @@ static int chv_init_workarounds(struct i
 	return 0;
 }
 
-static int gen9_init_workarounds(struct intel_engine_cs *ring)
+static int gen9_init_workarounds(struct intel_engine_cs *engine)
 {
-	struct drm_device *dev = ring->dev;
+	struct drm_device *dev = engine->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	uint32_t tmp;
 	int ret;
 
-	/* WaEnableLbsSlaRetryTimerDecrement:skl */
+	/* WaConextSwitchWithConcurrentTLBInvalidate:skl,bxt,kbl */
+	I915_WRITE(GEN9_CSFE_CHICKEN1_RCS, _MASKED_BIT_ENABLE(GEN9_PREEMPT_GPGPU_SYNC_SWITCH_DISABLE));
+
+	/* WaEnableLbsSlaRetryTimerDecrement:skl,bxt,kbl */
 	I915_WRITE(BDW_SCRATCH1, I915_READ(BDW_SCRATCH1) |
 		   GEN9_LBS_SLA_RETRY_TIMER_DECREMENT_ENABLE);
 
-	/* WaDisableKillLogic:bxt,skl */
+	/* WaDisableKillLogic:bxt,skl,kbl */
 	I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) |
 		   ECOCHK_DIS_TLB);
 
-	/* WaDisablePartialInstShootdown:skl,bxt */
+	/* WaClearFlowControlGpgpuContextSave:skl,bxt,kbl */
+	/* WaDisablePartialInstShootdown:skl,bxt,kbl */
 	WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN,
+			  FLOW_CONTROL_ENABLE |
 			  PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE);
 
-	/* Syncing dependencies between camera and graphics:skl,bxt */
+	/* Syncing dependencies between camera and graphics:skl,bxt,kbl */
 	WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
 			  GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC);
 
@@ -946,17 +954,18 @@ static int gen9_init_workarounds(struct
 		 */
 	}
 
-	/* WaEnableYV12BugFixInHalfSliceChicken7:skl,bxt */
-	if (IS_SKL_REVID(dev, SKL_REVID_C0, REVID_FOREVER) || IS_BROXTON(dev))
-		WA_SET_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN7,
-				  GEN9_ENABLE_YV12_BUGFIX);
+	/* WaEnableYV12BugFixInHalfSliceChicken7:skl,bxt,kbl */
+	/* WaEnableSamplerGPGPUPreemptionSupport:skl,bxt,kbl */
+	WA_SET_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN7,
+			  GEN9_ENABLE_YV12_BUGFIX |
+			  GEN9_ENABLE_GPGPU_PREEMPTION);
 
-	/* Wa4x4STCOptimizationDisable:skl,bxt */
-	/* WaDisablePartialResolveInVc:skl,bxt */
+	/* Wa4x4STCOptimizationDisable:skl,bxt,kbl */
+	/* WaDisablePartialResolveInVc:skl,bxt,kbl */
 	WA_SET_BIT_MASKED(CACHE_MODE_1, (GEN8_4x4_STC_OPTIMIZATION_DISABLE |
 					 GEN9_PARTIAL_RESOLVE_IN_VC_DISABLE));
 
-	/* WaCcsTlbPrefetchDisable:skl,bxt */
+	/* WaCcsTlbPrefetchDisable:skl,bxt,kbl */
 	WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5,
 			  GEN9_CCS_TLB_PREFETCH_ENABLE);
 
@@ -966,41 +975,67 @@ static int gen9_init_workarounds(struct
 		WA_SET_BIT_MASKED(SLICE_ECO_CHICKEN0,
 				  PIXEL_MASK_CAMMING_DISABLE);
 
-	/* WaForceContextSaveRestoreNonCoherent:skl,bxt */
-	tmp = HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT;
-	if (IS_SKL_REVID(dev, SKL_REVID_F0, REVID_FOREVER) ||
-	    IS_BXT_REVID(dev, BXT_REVID_B0, REVID_FOREVER))
-		tmp |= HDC_FORCE_CSR_NON_COHERENT_OVR_DISABLE;
-	WA_SET_BIT_MASKED(HDC_CHICKEN0, tmp);
+	/* WaForceContextSaveRestoreNonCoherent:skl,bxt,kbl */
+	WA_SET_BIT_MASKED(HDC_CHICKEN0,
+			  HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT |
+			  HDC_FORCE_CSR_NON_COHERENT_OVR_DISABLE);
 
-	/* WaDisableSamplerPowerBypassForSOPingPong:skl,bxt */
-	if (IS_SKYLAKE(dev) || IS_BXT_REVID(dev, 0, BXT_REVID_B0))
+	/* WaForceEnableNonCoherent and WaDisableHDCInvalidation are
+	 * both tied to WaForceContextSaveRestoreNonCoherent
+	 * in some hsds for skl. We keep the tie for all gen9. The
+	 * documentation is a bit hazy and so we want to get common behaviour,
+	 * even though there is no clear evidence we would need both on kbl/bxt.
+	 * This area has been source of system hangs so we play it safe
+	 * and mimic the skl regardless of what bspec says.
+	 *
+	 * Use Force Non-Coherent whenever executing a 3D context. This
+	 * is a workaround for a possible hang in the unlikely event
+	 * a TLB invalidation occurs during a PSD flush.
+	 */
+
+	/* WaForceEnableNonCoherent:skl,bxt,kbl */
+	WA_SET_BIT_MASKED(HDC_CHICKEN0,
+			  HDC_FORCE_NON_COHERENT);
+
+	/* WaDisableHDCInvalidation:skl,bxt,kbl */
+	I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) |
+		   BDW_DISABLE_HDC_INVALIDATION);
+
+	/* WaDisableSamplerPowerBypassForSOPingPong:skl,bxt,kbl */
+	if (IS_SKYLAKE(dev_priv) ||
+	    IS_KABYLAKE(dev_priv) ||
+	    IS_BXT_REVID(dev_priv, 0, BXT_REVID_B0))
 		WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
 				  GEN8_SAMPLER_POWER_BYPASS_DIS);
 
-	/* WaDisableSTUnitPowerOptimization:skl,bxt */
+	/* WaDisableSTUnitPowerOptimization:skl,bxt,kbl */
 	WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN2, GEN8_ST_PO_DISABLE);
 
-	/* WaOCLCoherentLineFlush:skl,bxt */
+	/* WaOCLCoherentLineFlush:skl,bxt,kbl */
 	I915_WRITE(GEN8_L3SQCREG4, (I915_READ(GEN8_L3SQCREG4) |
 				    GEN8_LQSC_FLUSH_COHERENT_LINES));
 
-	/* WaEnablePreemptionGranularityControlByUMD:skl,bxt */
-	ret= wa_ring_whitelist_reg(ring, GEN8_CS_CHICKEN1);
+	/* WaVFEStateAfterPipeControlwithMediaStateClear:skl,bxt */
+	ret = wa_ring_whitelist_reg(engine, GEN9_CTX_PREEMPT_REG);
 	if (ret)
 		return ret;
 
-	/* WaAllowUMDToModifyHDCChicken1:skl,bxt */
-	ret = wa_ring_whitelist_reg(ring, GEN8_HDC_CHICKEN1);
+	/* WaEnablePreemptionGranularityControlByUMD:skl,bxt,kbl */
+	ret= wa_ring_whitelist_reg(engine, GEN8_CS_CHICKEN1);
+	if (ret)
+		return ret;
+
+	/* WaAllowUMDToModifyHDCChicken1:skl,bxt,kbl */
+	ret = wa_ring_whitelist_reg(engine, GEN8_HDC_CHICKEN1);
 	if (ret)
 		return ret;
 
 	return 0;
 }
 
-static int skl_tune_iz_hashing(struct intel_engine_cs *ring)
+static int skl_tune_iz_hashing(struct intel_engine_cs *engine)
 {
-	struct drm_device *dev = ring->dev;
+	struct drm_device *dev = engine->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u8 vals[3] = { 0, 0, 0 };
 	unsigned int i;
@@ -1040,13 +1075,13 @@ static int skl_tune_iz_hashing(struct in
 	return 0;
 }
 
-static int skl_init_workarounds(struct intel_engine_cs *ring)
+static int skl_init_workarounds(struct intel_engine_cs *engine)
 {
 	int ret;
-	struct drm_device *dev = ring->dev;
+	struct drm_device *dev = engine->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	ret = gen9_init_workarounds(ring);
+	ret = gen9_init_workarounds(engine);
 	if (ret)
 		return ret;
 
@@ -1085,22 +1120,6 @@ static int skl_init_workarounds(struct i
 		WA_SET_BIT_MASKED(HIZ_CHICKEN,
 				  BDW_HIZ_POWER_COMPILER_CLOCK_GATING_DISABLE);
 
-	/* This is tied to WaForceContextSaveRestoreNonCoherent */
-	if (IS_SKL_REVID(dev, 0, REVID_FOREVER)) {
-		/*
-		 *Use Force Non-Coherent whenever executing a 3D context. This
-		 * is a workaround for a possible hang in the unlikely event
-		 * a TLB invalidation occurs during a PSD flush.
-		 */
-		/* WaForceEnableNonCoherent:skl */
-		WA_SET_BIT_MASKED(HDC_CHICKEN0,
-				  HDC_FORCE_NON_COHERENT);
-
-		/* WaDisableHDCInvalidation:skl */
-		I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) |
-			   BDW_DISABLE_HDC_INVALIDATION);
-	}
-
 	/* WaBarrierPerformanceFixDisable:skl */
 	if (IS_SKL_REVID(dev, SKL_REVID_C0, SKL_REVID_D0))
 		WA_SET_BIT_MASKED(HDC_CHICKEN0,
@@ -1113,21 +1132,24 @@ static int skl_init_workarounds(struct i
 			GEN7_HALF_SLICE_CHICKEN1,
 			GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE);
 
+	/* WaDisableGafsUnitClkGating:skl */
+	WA_SET_BIT(GEN7_UCGCTL4, GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE);
+
 	/* WaDisableLSQCROPERFforOCL:skl */
-	ret = wa_ring_whitelist_reg(ring, GEN8_L3SQCREG4);
+	ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4);
 	if (ret)
 		return ret;
 
-	return skl_tune_iz_hashing(ring);
+	return skl_tune_iz_hashing(engine);
 }
 
-static int bxt_init_workarounds(struct intel_engine_cs *ring)
+static int bxt_init_workarounds(struct intel_engine_cs *engine)
 {
 	int ret;
-	struct drm_device *dev = ring->dev;
+	struct drm_device *dev = engine->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	ret = gen9_init_workarounds(ring);
+	ret = gen9_init_workarounds(engine);
 	if (ret)
 		return ret;
 
@@ -1158,48 +1180,108 @@ static int bxt_init_workarounds(struct i
 	/* WaDisableObjectLevelPreemtionForInstanceId:bxt */
 	/* WaDisableLSQCROPERFforOCL:bxt */
 	if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) {
-		ret = wa_ring_whitelist_reg(ring, GEN9_CS_DEBUG_MODE1);
+		ret = wa_ring_whitelist_reg(engine, GEN9_CS_DEBUG_MODE1);
 		if (ret)
 			return ret;
 
-		ret = wa_ring_whitelist_reg(ring, GEN8_L3SQCREG4);
+		ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4);
 		if (ret)
 			return ret;
 	}
 
+	/* WaInsertDummyPushConstPs:bxt */
+	if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_B0))
+		WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
+				  GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION);
+
 	return 0;
 }
 
-int init_workarounds_ring(struct intel_engine_cs *ring)
+static int kbl_init_workarounds(struct intel_engine_cs *engine)
 {
-	struct drm_device *dev = ring->dev;
+	struct drm_i915_private *dev_priv = engine->dev->dev_private;
+	int ret;
+
+	ret = gen9_init_workarounds(engine);
+	if (ret)
+		return ret;
+
+	/* WaEnableGapsTsvCreditFix:kbl */
+	I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) |
+				   GEN9_GAPS_TSV_CREDIT_DISABLE));
+
+	/* WaDisableDynamicCreditSharing:kbl */
+	if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_B0))
+		WA_SET_BIT(GAMT_CHKN_BIT_REG,
+			   GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING);
+
+	/* WaDisableFenceDestinationToSLM:kbl (pre-prod) */
+	if (IS_KBL_REVID(dev_priv, KBL_REVID_A0, KBL_REVID_A0))
+		WA_SET_BIT_MASKED(HDC_CHICKEN0,
+				  HDC_FENCE_DEST_SLM_DISABLE);
+
+	/* GEN8_L3SQCREG4 has a dependency with WA batch so any new changes
+	 * involving this register should also be added to WA batch as required.
+	 */
+	if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_E0))
+		/* WaDisableLSQCROPERFforOCL:kbl */
+		I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) |
+			   GEN8_LQSC_RO_PERF_DIS);
+
+	/* WaInsertDummyPushConstPs:kbl */
+	if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_B0))
+		WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
+				  GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION);
+
+	/* WaDisableGafsUnitClkGating:kbl */
+	WA_SET_BIT(GEN7_UCGCTL4, GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE);
+
+	/* WaDisableSbeCacheDispatchPortSharing:kbl */
+	WA_SET_BIT_MASKED(
+		GEN7_HALF_SLICE_CHICKEN1,
+		GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE);
+
+	/* WaDisableLSQCROPERFforOCL:kbl */
+	ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+int init_workarounds_ring(struct intel_engine_cs *engine)
+{
+	struct drm_device *dev = engine->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	WARN_ON(ring->id != RCS);
+	WARN_ON(engine->id != RCS);
 
 	dev_priv->workarounds.count = 0;
 	dev_priv->workarounds.hw_whitelist_count[RCS] = 0;
 
 	if (IS_BROADWELL(dev))
-		return bdw_init_workarounds(ring);
+		return bdw_init_workarounds(engine);
 
 	if (IS_CHERRYVIEW(dev))
-		return chv_init_workarounds(ring);
+		return chv_init_workarounds(engine);
 
 	if (IS_SKYLAKE(dev))
-		return skl_init_workarounds(ring);
+		return skl_init_workarounds(engine);
 
 	if (IS_BROXTON(dev))
-		return bxt_init_workarounds(ring);
+		return bxt_init_workarounds(engine);
+
+	if (IS_KABYLAKE(dev_priv))
+		return kbl_init_workarounds(engine);
 
 	return 0;
 }
 
-static int init_render_ring(struct intel_engine_cs *ring)
+static int init_render_ring(struct intel_engine_cs *engine)
 {
-	struct drm_device *dev = ring->dev;
+	struct drm_device *dev = engine->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	int ret = init_ring_common(ring);
+	int ret = init_ring_common(engine);
 	if (ret)
 		return ret;
 
@@ -1242,14 +1324,14 @@ static int init_render_ring(struct intel
 		I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING));
 
 	if (HAS_L3_DPF(dev))
-		I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev));
+		I915_WRITE_IMR(engine, ~GT_PARITY_ERROR(dev));
 
-	return init_workarounds_ring(ring);
+	return init_workarounds_ring(engine);
 }
 
-static void render_ring_cleanup(struct intel_engine_cs *ring)
+static void render_ring_cleanup(struct intel_engine_cs *engine)
 {
-	struct drm_device *dev = ring->dev;
+	struct drm_device *dev = engine->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	if (dev_priv->semaphore_obj) {
@@ -1258,18 +1340,19 @@ static void render_ring_cleanup(struct i
 		dev_priv->semaphore_obj = NULL;
 	}
 
-	intel_fini_pipe_control(ring);
+	intel_fini_pipe_control(engine);
 }
 
 static int gen8_rcs_signal(struct drm_i915_gem_request *signaller_req,
 			   unsigned int num_dwords)
 {
 #define MBOX_UPDATE_DWORDS 8
-	struct intel_engine_cs *signaller = signaller_req->ring;
+	struct intel_engine_cs *signaller = signaller_req->engine;
 	struct drm_device *dev = signaller->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_engine_cs *waiter;
-	int i, ret, num_rings;
+	enum intel_engine_id id;
+	int ret, num_rings;
 
 	num_rings = hweight32(INTEL_INFO(dev)->ring_mask);
 	num_dwords += (num_rings-1) * MBOX_UPDATE_DWORDS;
@@ -1279,9 +1362,9 @@ static int gen8_rcs_signal(struct drm_i9
 	if (ret)
 		return ret;
 
-	for_each_ring(waiter, dev_priv, i) {
+	for_each_engine_id(waiter, dev_priv, id) {
 		u32 seqno;
-		u64 gtt_offset = signaller->semaphore.signal_ggtt[i];
+		u64 gtt_offset = signaller->semaphore.signal_ggtt[id];
 		if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID)
 			continue;
 
@@ -1295,7 +1378,7 @@ static int gen8_rcs_signal(struct drm_i9
 		intel_ring_emit(signaller, seqno);
 		intel_ring_emit(signaller, 0);
 		intel_ring_emit(signaller, MI_SEMAPHORE_SIGNAL |
-					   MI_SEMAPHORE_TARGET(waiter->id));
+					   MI_SEMAPHORE_TARGET(waiter->hw_id));
 		intel_ring_emit(signaller, 0);
 	}
 
@@ -1306,11 +1389,12 @@ static int gen8_xcs_signal(struct drm_i9
 			   unsigned int num_dwords)
 {
 #define MBOX_UPDATE_DWORDS 6
-	struct intel_engine_cs *signaller = signaller_req->ring;
+	struct intel_engine_cs *signaller = signaller_req->engine;
 	struct drm_device *dev = signaller->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_engine_cs *waiter;
-	int i, ret, num_rings;
+	enum intel_engine_id id;
+	int ret, num_rings;
 
 	num_rings = hweight32(INTEL_INFO(dev)->ring_mask);
 	num_dwords += (num_rings-1) * MBOX_UPDATE_DWORDS;
@@ -1320,9 +1404,9 @@ static int gen8_xcs_signal(struct drm_i9
 	if (ret)
 		return ret;
 
-	for_each_ring(waiter, dev_priv, i) {
+	for_each_engine_id(waiter, dev_priv, id) {
 		u32 seqno;
-		u64 gtt_offset = signaller->semaphore.signal_ggtt[i];
+		u64 gtt_offset = signaller->semaphore.signal_ggtt[id];
 		if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID)
 			continue;
 
@@ -1334,7 +1418,7 @@ static int gen8_xcs_signal(struct drm_i9
 		intel_ring_emit(signaller, upper_32_bits(gtt_offset));
 		intel_ring_emit(signaller, seqno);
 		intel_ring_emit(signaller, MI_SEMAPHORE_SIGNAL |
-					   MI_SEMAPHORE_TARGET(waiter->id));
+					   MI_SEMAPHORE_TARGET(waiter->hw_id));
 		intel_ring_emit(signaller, 0);
 	}
 
@@ -1344,11 +1428,12 @@ static int gen8_xcs_signal(struct drm_i9
 static int gen6_signal(struct drm_i915_gem_request *signaller_req,
 		       unsigned int num_dwords)
 {
-	struct intel_engine_cs *signaller = signaller_req->ring;
+	struct intel_engine_cs *signaller = signaller_req->engine;
 	struct drm_device *dev = signaller->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_engine_cs *useless;
-	int i, ret, num_rings;
+	enum intel_engine_id id;
+	int ret, num_rings;
 
 #define MBOX_UPDATE_DWORDS 3
 	num_rings = hweight32(INTEL_INFO(dev)->ring_mask);
@@ -1359,8 +1444,8 @@ static int gen6_signal(struct drm_i915_g
 	if (ret)
 		return ret;
 
-	for_each_ring(useless, dev_priv, i) {
-		i915_reg_t mbox_reg = signaller->semaphore.mbox.signal[i];
+	for_each_engine_id(useless, dev_priv, id) {
+		i915_reg_t mbox_reg = signaller->semaphore.mbox.signal[id];
 
 		if (i915_mmio_reg_valid(mbox_reg)) {
 			u32 seqno = i915_gem_request_get_seqno(signaller_req);
@@ -1389,22 +1474,23 @@ static int gen6_signal(struct drm_i915_g
 static int
 gen6_add_request(struct drm_i915_gem_request *req)
 {
-	struct intel_engine_cs *ring = req->ring;
+	struct intel_engine_cs *engine = req->engine;
 	int ret;
 
-	if (ring->semaphore.signal)
-		ret = ring->semaphore.signal(req, 4);
+	if (engine->semaphore.signal)
+		ret = engine->semaphore.signal(req, 4);
 	else
 		ret = intel_ring_begin(req, 4);
 
 	if (ret)
 		return ret;
 
-	intel_ring_emit(ring, MI_STORE_DWORD_INDEX);
-	intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
-	intel_ring_emit(ring, i915_gem_request_get_seqno(req));
-	intel_ring_emit(ring, MI_USER_INTERRUPT);
-	__intel_ring_advance(ring);
+	intel_ring_emit(engine, MI_STORE_DWORD_INDEX);
+	intel_ring_emit(engine,
+			I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
+	intel_ring_emit(engine, i915_gem_request_get_seqno(req));
+	intel_ring_emit(engine, MI_USER_INTERRUPT);
+	__intel_ring_advance(engine);
 
 	return 0;
 }
@@ -1429,7 +1515,7 @@ gen8_ring_sync(struct drm_i915_gem_reque
 	       struct intel_engine_cs *signaller,
 	       u32 seqno)
 {
-	struct intel_engine_cs *waiter = waiter_req->ring;
+	struct intel_engine_cs *waiter = waiter_req->engine;
 	struct drm_i915_private *dev_priv = waiter->dev->dev_private;
 	int ret;
 
@@ -1455,7 +1541,7 @@ gen6_ring_sync(struct drm_i915_gem_reque
 	       struct intel_engine_cs *signaller,
 	       u32 seqno)
 {
-	struct intel_engine_cs *waiter = waiter_req->ring;
+	struct intel_engine_cs *waiter = waiter_req->engine;
 	u32 dw1 = MI_SEMAPHORE_MBOX |
 		  MI_SEMAPHORE_COMPARE |
 		  MI_SEMAPHORE_REGISTER;
@@ -1503,8 +1589,8 @@ do {									\
 static int
 pc_render_add_request(struct drm_i915_gem_request *req)
 {
-	struct intel_engine_cs *ring = req->ring;
-	u32 scratch_addr = ring->scratch.gtt_offset + 2 * CACHELINE_BYTES;
+	struct intel_engine_cs *engine = req->engine;
+	u32 scratch_addr = engine->scratch.gtt_offset + 2 * CACHELINE_BYTES;
 	int ret;
 
 	/* For Ironlake, MI_USER_INTERRUPT was deprecated and apparently
@@ -1519,78 +1605,93 @@ pc_render_add_request(struct drm_i915_ge
 	if (ret)
 		return ret;
 
-	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE |
+	intel_ring_emit(engine,
+			GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE |
 			PIPE_CONTROL_WRITE_FLUSH |
 			PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE);
-	intel_ring_emit(ring, ring->scratch.gtt_offset | PIPE_CONTROL_GLOBAL_GTT);
-	intel_ring_emit(ring, i915_gem_request_get_seqno(req));
-	intel_ring_emit(ring, 0);
-	PIPE_CONTROL_FLUSH(ring, scratch_addr);
+	intel_ring_emit(engine,
+			engine->scratch.gtt_offset | PIPE_CONTROL_GLOBAL_GTT);
+	intel_ring_emit(engine, i915_gem_request_get_seqno(req));
+	intel_ring_emit(engine, 0);
+	PIPE_CONTROL_FLUSH(engine, scratch_addr);
 	scratch_addr += 2 * CACHELINE_BYTES; /* write to separate cachelines */
-	PIPE_CONTROL_FLUSH(ring, scratch_addr);
+	PIPE_CONTROL_FLUSH(engine, scratch_addr);
 	scratch_addr += 2 * CACHELINE_BYTES;
-	PIPE_CONTROL_FLUSH(ring, scratch_addr);
+	PIPE_CONTROL_FLUSH(engine, scratch_addr);
 	scratch_addr += 2 * CACHELINE_BYTES;
-	PIPE_CONTROL_FLUSH(ring, scratch_addr);
+	PIPE_CONTROL_FLUSH(engine, scratch_addr);
 	scratch_addr += 2 * CACHELINE_BYTES;
-	PIPE_CONTROL_FLUSH(ring, scratch_addr);
+	PIPE_CONTROL_FLUSH(engine, scratch_addr);
 	scratch_addr += 2 * CACHELINE_BYTES;
-	PIPE_CONTROL_FLUSH(ring, scratch_addr);
+	PIPE_CONTROL_FLUSH(engine, scratch_addr);
 
-	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE |
+	intel_ring_emit(engine,
+			GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE |
 			PIPE_CONTROL_WRITE_FLUSH |
 			PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE |
 			PIPE_CONTROL_NOTIFY);
-	intel_ring_emit(ring, ring->scratch.gtt_offset | PIPE_CONTROL_GLOBAL_GTT);
-	intel_ring_emit(ring, i915_gem_request_get_seqno(req));
-	intel_ring_emit(ring, 0);
-	__intel_ring_advance(ring);
+	intel_ring_emit(engine,
+			engine->scratch.gtt_offset | PIPE_CONTROL_GLOBAL_GTT);
+	intel_ring_emit(engine, i915_gem_request_get_seqno(req));
+	intel_ring_emit(engine, 0);
+	__intel_ring_advance(engine);
 
 	return 0;
 }
 
-static u32
-gen6_ring_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency)
+static void
+gen6_seqno_barrier(struct intel_engine_cs *engine)
 {
+	struct drm_i915_private *dev_priv = engine->dev->dev_private;
+
 	/* Workaround to force correct ordering between irq and seqno writes on
 	 * ivb (and maybe also on snb) by reading from a CS register (like
-	 * ACTHD) before reading the status page. */
-	if (!lazy_coherency) {
-		struct drm_i915_private *dev_priv = ring->dev->dev_private;
-		POSTING_READ(RING_ACTHD(ring->mmio_base));
-	}
-
-	return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
+	 * ACTHD) before reading the status page.
+	 *
+	 * Note that this effectively stalls the read by the time it takes to
+	 * do a memory transaction, which more or less ensures that the write
+	 * from the GPU has sufficient time to invalidate the CPU cacheline.
+	 * Alternatively we could delay the interrupt from the CS ring to give
+	 * the write time to land, but that would incur a delay after every
+	 * batch i.e. much more frequent than a delay when waiting for the
+	 * interrupt (with the same net latency).
+	 *
+	 * Also note that to prevent whole machine hangs on gen7, we have to
+	 * take the spinlock to guard against concurrent cacheline access.
+	 */
+	spin_lock_irq(&dev_priv->uncore.lock);
+	POSTING_READ_FW(RING_ACTHD(engine->mmio_base));
+	spin_unlock_irq(&dev_priv->uncore.lock);
 }
 
 static u32
-ring_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency)
+ring_get_seqno(struct intel_engine_cs *engine)
 {
-	return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
+	return intel_read_status_page(engine, I915_GEM_HWS_INDEX);
 }
 
 static void
-ring_set_seqno(struct intel_engine_cs *ring, u32 seqno)
+ring_set_seqno(struct intel_engine_cs *engine, u32 seqno)
 {
-	intel_write_status_page(ring, I915_GEM_HWS_INDEX, seqno);
+	intel_write_status_page(engine, I915_GEM_HWS_INDEX, seqno);
 }
 
 static u32
-pc_render_get_seqno(struct intel_engine_cs *ring, bool lazy_coherency)
+pc_render_get_seqno(struct intel_engine_cs *engine)
 {
-	return ring->scratch.cpu_page[0];
+	return engine->scratch.cpu_page[0];
 }
 
 static void
-pc_render_set_seqno(struct intel_engine_cs *ring, u32 seqno)
+pc_render_set_seqno(struct intel_engine_cs *engine, u32 seqno)
 {
-	ring->scratch.cpu_page[0] = seqno;
+	engine->scratch.cpu_page[0] = seqno;
 }
 
 static bool
-gen5_ring_get_irq(struct intel_engine_cs *ring)
+gen5_ring_get_irq(struct intel_engine_cs *engine)
 {
-	struct drm_device *dev = ring->dev;
+	struct drm_device *dev = engine->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	unsigned long flags;
 
@@ -1598,30 +1699,30 @@ gen5_ring_get_irq(struct intel_engine_cs
 		return false;
 
 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
-	if (ring->irq_refcount++ == 0)
-		gen5_enable_gt_irq(dev_priv, ring->irq_enable_mask);
+	if (engine->irq_refcount++ == 0)
+		gen5_enable_gt_irq(dev_priv, engine->irq_enable_mask);
 	spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 
 	return true;
 }
 
 static void
-gen5_ring_put_irq(struct intel_engine_cs *ring)
+gen5_ring_put_irq(struct intel_engine_cs *engine)
 {
-	struct drm_device *dev = ring->dev;
+	struct drm_device *dev = engine->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	unsigned long flags;
 
 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
-	if (--ring->irq_refcount == 0)
-		gen5_disable_gt_irq(dev_priv, ring->irq_enable_mask);
+	if (--engine->irq_refcount == 0)
+		gen5_disable_gt_irq(dev_priv, engine->irq_enable_mask);
 	spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 }
 
 static bool
-i9xx_ring_get_irq(struct intel_engine_cs *ring)
+i9xx_ring_get_irq(struct intel_engine_cs *engine)
 {
-	struct drm_device *dev = ring->dev;
+	struct drm_device *dev = engine->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	unsigned long flags;
 
@@ -1629,8 +1730,8 @@ i9xx_ring_get_irq(struct intel_engine_cs
 		return false;
 
 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
-	if (ring->irq_refcount++ == 0) {
-		dev_priv->irq_mask &= ~ring->irq_enable_mask;
+	if (engine->irq_refcount++ == 0) {
+		dev_priv->irq_mask &= ~engine->irq_enable_mask;
 		I915_WRITE(IMR, dev_priv->irq_mask);
 		POSTING_READ(IMR);
 	}
@@ -1640,15 +1741,15 @@ i9xx_ring_get_irq(struct intel_engine_cs
 }
 
 static void
-i9xx_ring_put_irq(struct intel_engine_cs *ring)
+i9xx_ring_put_irq(struct intel_engine_cs *engine)
 {
-	struct drm_device *dev = ring->dev;
+	struct drm_device *dev = engine->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	unsigned long flags;
 
 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
-	if (--ring->irq_refcount == 0) {
-		dev_priv->irq_mask |= ring->irq_enable_mask;
+	if (--engine->irq_refcount == 0) {
+		dev_priv->irq_mask |= engine->irq_enable_mask;
 		I915_WRITE(IMR, dev_priv->irq_mask);
 		POSTING_READ(IMR);
 	}
@@ -1656,9 +1757,9 @@ i9xx_ring_put_irq(struct intel_engine_cs
 }
 
 static bool
-i8xx_ring_get_irq(struct intel_engine_cs *ring)
+i8xx_ring_get_irq(struct intel_engine_cs *engine)
 {
-	struct drm_device *dev = ring->dev;
+	struct drm_device *dev = engine->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	unsigned long flags;
 
@@ -1666,8 +1767,8 @@ i8xx_ring_get_irq(struct intel_engine_cs
 		return false;
 
 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
-	if (ring->irq_refcount++ == 0) {
-		dev_priv->irq_mask &= ~ring->irq_enable_mask;
+	if (engine->irq_refcount++ == 0) {
+		dev_priv->irq_mask &= ~engine->irq_enable_mask;
 		I915_WRITE16(IMR, dev_priv->irq_mask);
 		POSTING_READ16(IMR);
 	}
@@ -1677,15 +1778,15 @@ i8xx_ring_get_irq(struct intel_engine_cs
 }
 
 static void
-i8xx_ring_put_irq(struct intel_engine_cs *ring)
+i8xx_ring_put_irq(struct intel_engine_cs *engine)
 {
-	struct drm_device *dev = ring->dev;
+	struct drm_device *dev = engine->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	unsigned long flags;
 
 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
-	if (--ring->irq_refcount == 0) {
-		dev_priv->irq_mask |= ring->irq_enable_mask;
+	if (--engine->irq_refcount == 0) {
+		dev_priv->irq_mask |= engine->irq_enable_mask;
 		I915_WRITE16(IMR, dev_priv->irq_mask);
 		POSTING_READ16(IMR);
 	}
@@ -1697,42 +1798,43 @@ bsd_ring_flush(struct drm_i915_gem_reque
 	       u32     invalidate_domains,
 	       u32     flush_domains)
 {
-	struct intel_engine_cs *ring = req->ring;
+	struct intel_engine_cs *engine = req->engine;
 	int ret;
 
 	ret = intel_ring_begin(req, 2);
 	if (ret)
 		return ret;
 
-	intel_ring_emit(ring, MI_FLUSH);
-	intel_ring_emit(ring, MI_NOOP);
-	intel_ring_advance(ring);
+	intel_ring_emit(engine, MI_FLUSH);
+	intel_ring_emit(engine, MI_NOOP);
+	intel_ring_advance(engine);
 	return 0;
 }
 
 static int
 i9xx_add_request(struct drm_i915_gem_request *req)
 {
-	struct intel_engine_cs *ring = req->ring;
+	struct intel_engine_cs *engine = req->engine;
 	int ret;
 
 	ret = intel_ring_begin(req, 4);
 	if (ret)
 		return ret;
 
-	intel_ring_emit(ring, MI_STORE_DWORD_INDEX);
-	intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
-	intel_ring_emit(ring, i915_gem_request_get_seqno(req));
-	intel_ring_emit(ring, MI_USER_INTERRUPT);
-	__intel_ring_advance(ring);
+	intel_ring_emit(engine, MI_STORE_DWORD_INDEX);
+	intel_ring_emit(engine,
+			I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
+	intel_ring_emit(engine, i915_gem_request_get_seqno(req));
+	intel_ring_emit(engine, MI_USER_INTERRUPT);
+	__intel_ring_advance(engine);
 
 	return 0;
 }
 
 static bool
-gen6_ring_get_irq(struct intel_engine_cs *ring)
+gen6_ring_get_irq(struct intel_engine_cs *engine)
 {
-	struct drm_device *dev = ring->dev;
+	struct drm_device *dev = engine->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	unsigned long flags;
 
@@ -1740,14 +1842,14 @@ gen6_ring_get_irq(struct intel_engine_cs
 		return false;
 
 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
-	if (ring->irq_refcount++ == 0) {
-		if (HAS_L3_DPF(dev) && ring->id == RCS)
-			I915_WRITE_IMR(ring,
-				       ~(ring->irq_enable_mask |
+	if (engine->irq_refcount++ == 0) {
+		if (HAS_L3_DPF(dev) && engine->id == RCS)
+			I915_WRITE_IMR(engine,
+				       ~(engine->irq_enable_mask |
 					 GT_PARITY_ERROR(dev)));
 		else
-			I915_WRITE_IMR(ring, ~ring->irq_enable_mask);
-		gen5_enable_gt_irq(dev_priv, ring->irq_enable_mask);
+			I915_WRITE_IMR(engine, ~engine->irq_enable_mask);
+		gen5_enable_gt_irq(dev_priv, engine->irq_enable_mask);
 	}
 	spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 
@@ -1755,27 +1857,27 @@ gen6_ring_get_irq(struct intel_engine_cs
 }
 
 static void
-gen6_ring_put_irq(struct intel_engine_cs *ring)
+gen6_ring_put_irq(struct intel_engine_cs *engine)
 {
-	struct drm_device *dev = ring->dev;
+	struct drm_device *dev = engine->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	unsigned long flags;
 
 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
-	if (--ring->irq_refcount == 0) {
-		if (HAS_L3_DPF(dev) && ring->id == RCS)
-			I915_WRITE_IMR(ring, ~GT_PARITY_ERROR(dev));
+	if (--engine->irq_refcount == 0) {
+		if (HAS_L3_DPF(dev) && engine->id == RCS)
+			I915_WRITE_IMR(engine, ~GT_PARITY_ERROR(dev));
 		else
-			I915_WRITE_IMR(ring, ~0);
-		gen5_disable_gt_irq(dev_priv, ring->irq_enable_mask);
+			I915_WRITE_IMR(engine, ~0);
+		gen5_disable_gt_irq(dev_priv, engine->irq_enable_mask);
 	}
 	spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 }
 
 static bool
-hsw_vebox_get_irq(struct intel_engine_cs *ring)
+hsw_vebox_get_irq(struct intel_engine_cs *engine)
 {
-	struct drm_device *dev = ring->dev;
+	struct drm_device *dev = engine->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	unsigned long flags;
 
@@ -1783,9 +1885,9 @@ hsw_vebox_get_irq(struct intel_engine_cs
 		return false;
 
 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
-	if (ring->irq_refcount++ == 0) {
-		I915_WRITE_IMR(ring, ~ring->irq_enable_mask);
-		gen6_enable_pm_irq(dev_priv, ring->irq_enable_mask);
+	if (engine->irq_refcount++ == 0) {
+		I915_WRITE_IMR(engine, ~engine->irq_enable_mask);
+		gen6_enable_pm_irq(dev_priv, engine->irq_enable_mask);
 	}
 	spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 
@@ -1793,24 +1895,24 @@ hsw_vebox_get_irq(struct intel_engine_cs
 }
 
 static void
-hsw_vebox_put_irq(struct intel_engine_cs *ring)
+hsw_vebox_put_irq(struct intel_engine_cs *engine)
 {
-	struct drm_device *dev = ring->dev;
+	struct drm_device *dev = engine->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	unsigned long flags;
 
 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
-	if (--ring->irq_refcount == 0) {
-		I915_WRITE_IMR(ring, ~0);
-		gen6_disable_pm_irq(dev_priv, ring->irq_enable_mask);
+	if (--engine->irq_refcount == 0) {
+		I915_WRITE_IMR(engine, ~0);
+		gen6_disable_pm_irq(dev_priv, engine->irq_enable_mask);
 	}
 	spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 }
 
 static bool
-gen8_ring_get_irq(struct intel_engine_cs *ring)
+gen8_ring_get_irq(struct intel_engine_cs *engine)
 {
-	struct drm_device *dev = ring->dev;
+	struct drm_device *dev = engine->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	unsigned long flags;
 
@@ -1818,15 +1920,15 @@ gen8_ring_get_irq(struct intel_engine_cs
 		return false;
 
 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
-	if (ring->irq_refcount++ == 0) {
-		if (HAS_L3_DPF(dev) && ring->id == RCS) {
-			I915_WRITE_IMR(ring,
-				       ~(ring->irq_enable_mask |
+	if (engine->irq_refcount++ == 0) {
+		if (HAS_L3_DPF(dev) && engine->id == RCS) {
+			I915_WRITE_IMR(engine,
+				       ~(engine->irq_enable_mask |
 					 GT_RENDER_L3_PARITY_ERROR_INTERRUPT));
 		} else {
-			I915_WRITE_IMR(ring, ~ring->irq_enable_mask);
+			I915_WRITE_IMR(engine, ~engine->irq_enable_mask);
 		}
-		POSTING_READ(RING_IMR(ring->mmio_base));
+		POSTING_READ(RING_IMR(engine->mmio_base));
 	}
 	spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 
@@ -1834,21 +1936,21 @@ gen8_ring_get_irq(struct intel_engine_cs
 }
 
 static void
-gen8_ring_put_irq(struct intel_engine_cs *ring)
+gen8_ring_put_irq(struct intel_engine_cs *engine)
 {
-	struct drm_device *dev = ring->dev;
+	struct drm_device *dev = engine->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	unsigned long flags;
 
 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
-	if (--ring->irq_refcount == 0) {
-		if (HAS_L3_DPF(dev) && ring->id == RCS) {
-			I915_WRITE_IMR(ring,
+	if (--engine->irq_refcount == 0) {
+		if (HAS_L3_DPF(dev) && engine->id == RCS) {
+			I915_WRITE_IMR(engine,
 				       ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT);
 		} else {
-			I915_WRITE_IMR(ring, ~0);
+			I915_WRITE_IMR(engine, ~0);
 		}
-		POSTING_READ(RING_IMR(ring->mmio_base));
+		POSTING_READ(RING_IMR(engine->mmio_base));
 	}
 	spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
 }
@@ -1858,20 +1960,20 @@ i965_dispatch_execbuffer(struct drm_i915
 			 u64 offset, u32 length,
 			 unsigned dispatch_flags)
 {
-	struct intel_engine_cs *ring = req->ring;
+	struct intel_engine_cs *engine = req->engine;
 	int ret;
 
 	ret = intel_ring_begin(req, 2);
 	if (ret)
 		return ret;
 
-	intel_ring_emit(ring,
+	intel_ring_emit(engine,
 			MI_BATCH_BUFFER_START |
 			MI_BATCH_GTT |
 			(dispatch_flags & I915_DISPATCH_SECURE ?
 			 0 : MI_BATCH_NON_SECURE_I965));
-	intel_ring_emit(ring, offset);
-	intel_ring_advance(ring);
+	intel_ring_emit(engine, offset);
+	intel_ring_advance(engine);
 
 	return 0;
 }
@@ -1885,8 +1987,8 @@ i830_dispatch_execbuffer(struct drm_i915
 			 u64 offset, u32 len,
 			 unsigned dispatch_flags)
 {
-	struct intel_engine_cs *ring = req->ring;
-	u32 cs_offset = ring->scratch.gtt_offset;
+	struct intel_engine_cs *engine = req->engine;
+	u32 cs_offset = engine->scratch.gtt_offset;
 	int ret;
 
 	ret = intel_ring_begin(req, 6);
@@ -1894,13 +1996,13 @@ i830_dispatch_execbuffer(struct drm_i915
 		return ret;
 
 	/* Evict the invalid PTE TLBs */
-	intel_ring_emit(ring, COLOR_BLT_CMD | BLT_WRITE_RGBA);
-	intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_COLOR_COPY | 4096);
-	intel_ring_emit(ring, I830_TLB_ENTRIES << 16 | 4); /* load each page */
-	intel_ring_emit(ring, cs_offset);
-	intel_ring_emit(ring, 0xdeadbeef);
-	intel_ring_emit(ring, MI_NOOP);
-	intel_ring_advance(ring);
+	intel_ring_emit(engine, COLOR_BLT_CMD | BLT_WRITE_RGBA);
+	intel_ring_emit(engine, BLT_DEPTH_32 | BLT_ROP_COLOR_COPY | 4096);
+	intel_ring_emit(engine, I830_TLB_ENTRIES << 16 | 4); /* load each page */
+	intel_ring_emit(engine, cs_offset);
+	intel_ring_emit(engine, 0xdeadbeef);
+	intel_ring_emit(engine, MI_NOOP);
+	intel_ring_advance(engine);
 
 	if ((dispatch_flags & I915_DISPATCH_PINNED) == 0) {
 		if (len > I830_BATCH_LIMIT)
@@ -1914,16 +2016,17 @@ i830_dispatch_execbuffer(struct drm_i915
 		 * stable batch scratch bo area (so that the CS never
 		 * stumbles over its tlb invalidation bug) ...
 		 */
-		intel_ring_emit(ring, SRC_COPY_BLT_CMD | BLT_WRITE_RGBA);
-		intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_SRC_COPY | 4096);
-		intel_ring_emit(ring, DIV_ROUND_UP(len, 4096) << 16 | 4096);
-		intel_ring_emit(ring, cs_offset);
-		intel_ring_emit(ring, 4096);
-		intel_ring_emit(ring, offset);
+		intel_ring_emit(engine, SRC_COPY_BLT_CMD | BLT_WRITE_RGBA);
+		intel_ring_emit(engine,
+				BLT_DEPTH_32 | BLT_ROP_SRC_COPY | 4096);
+		intel_ring_emit(engine, DIV_ROUND_UP(len, 4096) << 16 | 4096);
+		intel_ring_emit(engine, cs_offset);
+		intel_ring_emit(engine, 4096);
+		intel_ring_emit(engine, offset);
 
-		intel_ring_emit(ring, MI_FLUSH);
-		intel_ring_emit(ring, MI_NOOP);
-		intel_ring_advance(ring);
+		intel_ring_emit(engine, MI_FLUSH);
+		intel_ring_emit(engine, MI_NOOP);
+		intel_ring_advance(engine);
 
 		/* ... and execute it. */
 		offset = cs_offset;
@@ -1933,10 +2036,10 @@ i830_dispatch_execbuffer(struct drm_i915
 	if (ret)
 		return ret;
 
-	intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_GTT);
-	intel_ring_emit(ring, offset | (dispatch_flags & I915_DISPATCH_SECURE ?
-					0 : MI_BATCH_NON_SECURE));
-	intel_ring_advance(ring);
+	intel_ring_emit(engine, MI_BATCH_BUFFER_START | MI_BATCH_GTT);
+	intel_ring_emit(engine, offset | (dispatch_flags & I915_DISPATCH_SECURE ?
+					  0 : MI_BATCH_NON_SECURE));
+	intel_ring_advance(engine);
 
 	return 0;
 }
@@ -1946,55 +2049,55 @@ i915_dispatch_execbuffer(struct drm_i915
 			 u64 offset, u32 len,
 			 unsigned dispatch_flags)
 {
-	struct intel_engine_cs *ring = req->ring;
+	struct intel_engine_cs *engine = req->engine;
 	int ret;
 
 	ret = intel_ring_begin(req, 2);
 	if (ret)
 		return ret;
 
-	intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_GTT);
-	intel_ring_emit(ring, offset | (dispatch_flags & I915_DISPATCH_SECURE ?
-					0 : MI_BATCH_NON_SECURE));
-	intel_ring_advance(ring);
+	intel_ring_emit(engine, MI_BATCH_BUFFER_START | MI_BATCH_GTT);
+	intel_ring_emit(engine, offset | (dispatch_flags & I915_DISPATCH_SECURE ?
+					  0 : MI_BATCH_NON_SECURE));
+	intel_ring_advance(engine);
 
 	return 0;
 }
 
-static void cleanup_phys_status_page(struct intel_engine_cs *ring)
+static void cleanup_phys_status_page(struct intel_engine_cs *engine)
 {
-	struct drm_i915_private *dev_priv = to_i915(ring->dev);
+	struct drm_i915_private *dev_priv = to_i915(engine->dev);
 
 	if (!dev_priv->status_page_dmah)
 		return;
 
-	drm_pci_free(ring->dev, dev_priv->status_page_dmah);
-	ring->status_page.page_addr = NULL;
+	drm_pci_free(engine->dev, dev_priv->status_page_dmah);
+	engine->status_page.page_addr = NULL;
 }
 
-static void cleanup_status_page(struct intel_engine_cs *ring)
+static void cleanup_status_page(struct intel_engine_cs *engine)
 {
 	struct drm_i915_gem_object *obj;
 
-	obj = ring->status_page.obj;
+	obj = engine->status_page.obj;
 	if (obj == NULL)
 		return;
 
 	kunmap(sg_page(obj->pages->sgl));
 	i915_gem_object_ggtt_unpin(obj);
 	drm_gem_object_unreference(&obj->base);
-	ring->status_page.obj = NULL;
+	engine->status_page.obj = NULL;
 }
 
-static int init_status_page(struct intel_engine_cs *ring)
+static int init_status_page(struct intel_engine_cs *engine)
 {
-	struct drm_i915_gem_object *obj = ring->status_page.obj;
+	struct drm_i915_gem_object *obj = engine->status_page.obj;
 
 	if (obj == NULL) {
 		unsigned flags;
 		int ret;
 
-		obj = i915_gem_alloc_object(ring->dev, 4096);
+		obj = i915_gem_alloc_object(engine->dev, 4096);
 		if (obj == NULL) {
 			DRM_ERROR("Failed to allocate status page\n");
 			return -ENOMEM;
@@ -2005,7 +2108,7 @@ static int init_status_page(struct intel
 			goto err_unref;
 
 		flags = 0;
-		if (!HAS_LLC(ring->dev))
+		if (!HAS_LLC(engine->dev))
 			/* On g33, we cannot place HWS above 256MiB, so
 			 * restrict its pinning to the low mappable arena.
 			 * Though this restriction is not documented for
@@ -2024,32 +2127,32 @@ err_unref:
 			return ret;
 		}
 
-		ring->status_page.obj = obj;
+		engine->status_page.obj = obj;
 	}
 
-	ring->status_page.gfx_addr = i915_gem_obj_ggtt_offset(obj);
-	ring->status_page.page_addr = kmap(sg_page(obj->pages->sgl));
-	memset(ring->status_page.page_addr, 0, PAGE_SIZE);
+	engine->status_page.gfx_addr = i915_gem_obj_ggtt_offset(obj);
+	engine->status_page.page_addr = kmap(sg_page(obj->pages->sgl));
+	memset(engine->status_page.page_addr, 0, PAGE_SIZE);
 
 	DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n",
-			ring->name, ring->status_page.gfx_addr);
+			engine->name, engine->status_page.gfx_addr);
 
 	return 0;
 }
 
-static int init_phys_status_page(struct intel_engine_cs *ring)
+static int init_phys_status_page(struct intel_engine_cs *engine)
 {
-	struct drm_i915_private *dev_priv = ring->dev->dev_private;
+	struct drm_i915_private *dev_priv = engine->dev->dev_private;
 
 	if (!dev_priv->status_page_dmah) {
 		dev_priv->status_page_dmah =
-			drm_pci_alloc(ring->dev, PAGE_SIZE, PAGE_SIZE);
+			drm_pci_alloc(engine->dev, PAGE_SIZE, PAGE_SIZE);
 		if (!dev_priv->status_page_dmah)
 			return -ENOMEM;
 	}
 
-	ring->status_page.page_addr = dev_priv->status_page_dmah->vaddr;
-	memset(ring->status_page.page_addr, 0, PAGE_SIZE);
+	engine->status_page.page_addr = dev_priv->status_page_dmah->vaddr;
+	memset(engine->status_page.page_addr, 0, PAGE_SIZE);
 
 	return 0;
 }
@@ -2057,7 +2160,7 @@ static int init_phys_status_page(struct
 void intel_unpin_ringbuffer_obj(struct intel_ringbuffer *ringbuf)
 {
 	if (HAS_LLC(ringbuf->obj->base.dev) && !ringbuf->obj->stolen)
-		vunmap(ringbuf->virtual_start);
+		i915_gem_object_unpin_map(ringbuf->obj);
 	else
 		iounmap(ringbuf->virtual_start);
 	ringbuf->virtual_start = NULL;
@@ -2065,34 +2168,15 @@ void intel_unpin_ringbuffer_obj(struct i
 	i915_gem_object_ggtt_unpin(ringbuf->obj);
 }
 
-static u32 *vmap_obj(struct drm_i915_gem_object *obj)
-{
-	struct sg_page_iter sg_iter;
-	struct page **pages;
-	void *addr;
-	int i;
-
-	pages = drm_malloc_ab(obj->base.size >> PAGE_SHIFT, sizeof(*pages));
-	if (pages == NULL)
-		return NULL;
-
-	i = 0;
-	for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0)
-		pages[i++] = sg_page_iter_page(&sg_iter);
-
-	addr = vmap(pages, i, 0, PAGE_KERNEL);
-	drm_free_large(pages);
-
-	return addr;
-}
-
 int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev,
 				     struct intel_ringbuffer *ringbuf)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	struct drm_i915_gem_object *obj = ringbuf->obj;
 	/* Ring wraparound at offset 0 sometimes hangs. No idea why. */
 	unsigned flags = PIN_OFFSET_BIAS | 4096;
+	void *addr;
 	int ret;
 
 	if (HAS_LLC(dev_priv) && !obj->stolen) {
@@ -2101,15 +2185,13 @@ int intel_pin_and_map_ringbuffer_obj(str
 			return ret;
 
 		ret = i915_gem_object_set_to_cpu_domain(obj, true);
-		if (ret) {
-			i915_gem_object_ggtt_unpin(obj);
-			return ret;
-		}
+		if (ret)
+			goto err_unpin;
 
-		ringbuf->virtual_start = vmap_obj(obj);
-		if (ringbuf->virtual_start == NULL) {
-			i915_gem_object_ggtt_unpin(obj);
-			return -ENOMEM;
+		addr = i915_gem_object_pin_map(obj);
+		if (IS_ERR(addr)) {
+			ret = PTR_ERR(addr);
+			goto err_unpin;
 		}
 	} else {
 		ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE,
@@ -2118,25 +2200,27 @@ int intel_pin_and_map_ringbuffer_obj(str
 			return ret;
 
 		ret = i915_gem_object_set_to_gtt_domain(obj, true);
-		if (ret) {
-			i915_gem_object_ggtt_unpin(obj);
-			return ret;
-		}
+		if (ret)
+			goto err_unpin;
 
 		/* Access through the GTT requires the device to be awake. */
 		assert_rpm_wakelock_held(dev_priv);
 
-		ringbuf->virtual_start = ioremap_wc(dev_priv->gtt.mappable_base +
-						    i915_gem_obj_ggtt_offset(obj), ringbuf->size);
-		if (ringbuf->virtual_start == NULL) {
-			i915_gem_object_ggtt_unpin(obj);
-			return -EINVAL;
+		addr = ioremap_wc(ggtt->mappable_base +
+				  i915_gem_obj_ggtt_offset(obj), ringbuf->size);
+		if (addr == NULL) {
+			ret = -ENOMEM;
+			goto err_unpin;
 		}
 	}
 
+	ringbuf->virtual_start = addr;
 	ringbuf->vma = i915_gem_obj_to_ggtt(obj);
-
 	return 0;
+
+err_unpin:
+	i915_gem_object_ggtt_unpin(obj);
+	return ret;
 }
 
 static void intel_destroy_ringbuffer_obj(struct intel_ringbuffer *ringbuf)
@@ -2179,7 +2263,7 @@ intel_engine_create_ringbuffer(struct in
 		return ERR_PTR(-ENOMEM);
 	}
 
-	ring->ring = engine;
+	ring->engine = engine;
 	list_add(&ring->link, &engine->buffers);
 
 	ring->size = size;
@@ -2215,37 +2299,38 @@ intel_ringbuffer_free(struct intel_ringb
 }
 
 static int intel_init_ring_buffer(struct drm_device *dev,
-				  struct intel_engine_cs *ring)
+				  struct intel_engine_cs *engine)
 {
 	struct intel_ringbuffer *ringbuf;
 	int ret;
 
-	WARN_ON(ring->buffer);
+	WARN_ON(engine->buffer);
 
-	ring->dev = dev;
-	INIT_LIST_HEAD(&ring->active_list);
-	INIT_LIST_HEAD(&ring->request_list);
-	INIT_LIST_HEAD(&ring->execlist_queue);
-	INIT_LIST_HEAD(&ring->buffers);
-	i915_gem_batch_pool_init(dev, &ring->batch_pool);
-	memset(ring->semaphore.sync_seqno, 0, sizeof(ring->semaphore.sync_seqno));
+	engine->dev = dev;
+	INIT_LIST_HEAD(&engine->active_list);
+	INIT_LIST_HEAD(&engine->request_list);
+	INIT_LIST_HEAD(&engine->execlist_queue);
+	INIT_LIST_HEAD(&engine->buffers);
+	i915_gem_batch_pool_init(dev, &engine->batch_pool);
+	memset(engine->semaphore.sync_seqno, 0,
+	       sizeof(engine->semaphore.sync_seqno));
 
-	init_waitqueue_head(&ring->irq_queue);
+	init_waitqueue_head(&engine->irq_queue);
 
-	ringbuf = intel_engine_create_ringbuffer(ring, 32 * PAGE_SIZE);
+	ringbuf = intel_engine_create_ringbuffer(engine, 32 * PAGE_SIZE);
 	if (IS_ERR(ringbuf)) {
 		ret = PTR_ERR(ringbuf);
 		goto error;
 	}
-	ring->buffer = ringbuf;
+	engine->buffer = ringbuf;
 
 	if (I915_NEED_GFX_HWS(dev)) {
-		ret = init_status_page(ring);
+		ret = init_status_page(engine);
 		if (ret)
 			goto error;
 	} else {
-		WARN_ON(ring->id != RCS);
-		ret = init_phys_status_page(ring);
+		WARN_ON(engine->id != RCS);
+		ret = init_phys_status_page(engine);
 		if (ret)
 			goto error;
 	}
@@ -2253,122 +2338,76 @@ static int intel_init_ring_buffer(struct
 	ret = intel_pin_and_map_ringbuffer_obj(dev, ringbuf);
 	if (ret) {
 		DRM_ERROR("Failed to pin and map ringbuffer %s: %d\n",
-				ring->name, ret);
+				engine->name, ret);
 		intel_destroy_ringbuffer_obj(ringbuf);
 		goto error;
 	}
 
-	ret = i915_cmd_parser_init_ring(ring);
+	ret = i915_cmd_parser_init_ring(engine);
 	if (ret)
 		goto error;
 
 	return 0;
 
 error:
-	intel_cleanup_ring_buffer(ring);
+	intel_cleanup_engine(engine);
 	return ret;
 }
 
-void intel_cleanup_ring_buffer(struct intel_engine_cs *ring)
+void intel_cleanup_engine(struct intel_engine_cs *engine)
 {
 	struct drm_i915_private *dev_priv;
 
-	if (!intel_ring_initialized(ring))
+	if (!intel_engine_initialized(engine))
 		return;
 
-	dev_priv = to_i915(ring->dev);
+	dev_priv = to_i915(engine->dev);
 
-	if (ring->buffer) {
-		intel_stop_ring_buffer(ring);
-		WARN_ON(!IS_GEN2(ring->dev) && (I915_READ_MODE(ring) & MODE_IDLE) == 0);
+	if (engine->buffer) {
+		intel_stop_engine(engine);
+		WARN_ON(!IS_GEN2(engine->dev) && (I915_READ_MODE(engine) & MODE_IDLE) == 0);
 
-		intel_unpin_ringbuffer_obj(ring->buffer);
-		intel_ringbuffer_free(ring->buffer);
-		ring->buffer = NULL;
+		intel_unpin_ringbuffer_obj(engine->buffer);
+		intel_ringbuffer_free(engine->buffer);
+		engine->buffer = NULL;
 	}
 
-	if (ring->cleanup)
-		ring->cleanup(ring);
+	if (engine->cleanup)
+		engine->cleanup(engine);
 
-	if (I915_NEED_GFX_HWS(ring->dev)) {
-		cleanup_status_page(ring);
+	if (I915_NEED_GFX_HWS(engine->dev)) {
+		cleanup_status_page(engine);
 	} else {
-		WARN_ON(ring->id != RCS);
-		cleanup_phys_status_page(ring);
-	}
-
-	i915_cmd_parser_fini_ring(ring);
-	i915_gem_batch_pool_fini(&ring->batch_pool);
-	ring->dev = NULL;
-}
-
-static int ring_wait_for_space(struct intel_engine_cs *ring, int n)
-{
-	struct intel_ringbuffer *ringbuf = ring->buffer;
-	struct drm_i915_gem_request *request;
-	unsigned space;
-	int ret;
-
-	if (intel_ring_space(ringbuf) >= n)
-		return 0;
-
-	/* The whole point of reserving space is to not wait! */
-	WARN_ON(ringbuf->reserved_in_use);
-
-	list_for_each_entry(request, &ring->request_list, list) {
-		space = __intel_ring_space(request->postfix, ringbuf->tail,
-					   ringbuf->size);
-		if (space >= n)
-			break;
+		WARN_ON(engine->id != RCS);
+		cleanup_phys_status_page(engine);
 	}
 
-	if (WARN_ON(&request->list == &ring->request_list))
-		return -ENOSPC;
-
-	ret = i915_wait_request(request);
-	if (ret)
-		return ret;
-
-	ringbuf->space = space;
-	return 0;
-}
-
-static void __wrap_ring_buffer(struct intel_ringbuffer *ringbuf)
-{
-	uint32_t __iomem *virt;
-	int rem = ringbuf->size - ringbuf->tail;
-
-	virt = ringbuf->virtual_start + ringbuf->tail;
-	rem /= 4;
-	while (rem--)
-		iowrite32(MI_NOOP, virt++);
-
-	ringbuf->tail = 0;
-	intel_ring_update_space(ringbuf);
+	i915_cmd_parser_fini_ring(engine);
+	i915_gem_batch_pool_fini(&engine->batch_pool);
+	engine->dev = NULL;
 }
 
-int intel_ring_idle(struct intel_engine_cs *ring)
+int intel_engine_idle(struct intel_engine_cs *engine)
 {
 	struct drm_i915_gem_request *req;
 
 	/* Wait upon the last request to be completed */
-	if (list_empty(&ring->request_list))
+	if (list_empty(&engine->request_list))
 		return 0;
 
-	req = list_entry(ring->request_list.prev,
-			struct drm_i915_gem_request,
-			list);
+	req = list_entry(engine->request_list.prev,
+			 struct drm_i915_gem_request,
+			 list);
 
 	/* Make sure we do not trigger any retires */
 	return __i915_wait_request(req,
-				   atomic_read(&to_i915(ring->dev)->gpu_error.reset_counter),
-				   to_i915(ring->dev)->mm.interruptible,
+				   req->i915->mm.interruptible,
 				   NULL, NULL);
 }
 
 int intel_ring_alloc_request_extras(struct drm_i915_gem_request *request)
 {
-	request->ringbuf = request->ring->buffer;
+	request->ringbuf = request->engine->buffer;
 	return 0;
 }
 
@@ -2389,63 +2428,82 @@ int intel_ring_reserve_space(struct drm_
 
 void intel_ring_reserved_space_reserve(struct intel_ringbuffer *ringbuf, int size)
 {
-	WARN_ON(ringbuf->reserved_size);
-	WARN_ON(ringbuf->reserved_in_use);
-
+	GEM_BUG_ON(ringbuf->reserved_size);
 	ringbuf->reserved_size = size;
 }
 
 void intel_ring_reserved_space_cancel(struct intel_ringbuffer *ringbuf)
 {
-	WARN_ON(ringbuf->reserved_in_use);
-
+	GEM_BUG_ON(!ringbuf->reserved_size);
 	ringbuf->reserved_size   = 0;
-	ringbuf->reserved_in_use = false;
 }
 
 void intel_ring_reserved_space_use(struct intel_ringbuffer *ringbuf)
 {
-	WARN_ON(ringbuf->reserved_in_use);
-
-	ringbuf->reserved_in_use = true;
-	ringbuf->reserved_tail   = ringbuf->tail;
+	GEM_BUG_ON(!ringbuf->reserved_size);
+	ringbuf->reserved_size   = 0;
 }
 
 void intel_ring_reserved_space_end(struct intel_ringbuffer *ringbuf)
 {
-	WARN_ON(!ringbuf->reserved_in_use);
-	if (ringbuf->tail > ringbuf->reserved_tail) {
-		WARN(ringbuf->tail > ringbuf->reserved_tail + ringbuf->reserved_size,
-		     "request reserved size too small: %d vs %d!\n",
-		     ringbuf->tail - ringbuf->reserved_tail, ringbuf->reserved_size);
-	} else {
+	GEM_BUG_ON(ringbuf->reserved_size);
+}
+
+static int wait_for_space(struct drm_i915_gem_request *req, int bytes)
+{
+	struct intel_ringbuffer *ringbuf = req->ringbuf;
+	struct intel_engine_cs *engine = req->engine;
+	struct drm_i915_gem_request *target;
+
+	intel_ring_update_space(ringbuf);
+	if (ringbuf->space >= bytes)
+		return 0;
+
+	/*
+	 * Space is reserved in the ringbuffer for finalising the request,
+	 * as that cannot be allowed to fail. During request finalisation,
+	 * reserved_space is set to 0 to stop the overallocation and the
+	 * assumption is that then we never need to wait (which has the
+	 * risk of failing with EINTR).
+	 *
+	 * See also i915_gem_request_alloc() and i915_add_request().
+	 */
+	GEM_BUG_ON(!ringbuf->reserved_size);
+
+	list_for_each_entry(target, &engine->request_list, list) {
+		unsigned space;
+
 		/*
-		 * The ring was wrapped while the reserved space was in use.
-		 * That means that some unknown amount of the ring tail was
-		 * no-op filled and skipped. Thus simply adding the ring size
-		 * to the tail and doing the above space check will not work.
-		 * Rather than attempt to track how much tail was skipped,
-		 * it is much simpler to say that also skipping the sanity
-		 * check every once in a while is not a big issue.
+		 * The request queue is per-engine, so can contain requests
+		 * from multiple ringbuffers. Here, we must ignore any that
+		 * aren't from the ringbuffer we're considering.
 		 */
+		if (target->ringbuf != ringbuf)
+			continue;
+
+		/* Would completion of this request free enough space? */
+		space = __intel_ring_space(target->postfix, ringbuf->tail,
+					   ringbuf->size);
+		if (space >= bytes)
+			break;
 	}
 
-	ringbuf->reserved_size   = 0;
-	ringbuf->reserved_in_use = false;
+	if (WARN_ON(&target->list == &engine->request_list))
+		return -ENOSPC;
+
+	return i915_wait_request(target);
 }
 
-static int __intel_ring_prepare(struct intel_engine_cs *ring, int bytes)
+int intel_ring_begin(struct drm_i915_gem_request *req, int num_dwords)
 {
-	struct intel_ringbuffer *ringbuf = ring->buffer;
-	int remain_usable = ringbuf->effective_size - ringbuf->tail;
+	struct intel_ringbuffer *ringbuf = req->ringbuf;
 	int remain_actual = ringbuf->size - ringbuf->tail;
-	int ret, total_bytes, wait_bytes = 0;
+	int remain_usable = ringbuf->effective_size - ringbuf->tail;
+	int bytes = num_dwords * sizeof(u32);
+	int total_bytes, wait_bytes;
 	bool need_wrap = false;
 
-	if (ringbuf->reserved_in_use)
-		total_bytes = bytes;
-	else
-		total_bytes = bytes + ringbuf->reserved_size;
+	total_bytes = bytes + ringbuf->reserved_size;
 
 	if (unlikely(bytes > remain_usable)) {
 		/*
@@ -2454,62 +2512,50 @@ static int __intel_ring_prepare(struct i
 		 */
 		wait_bytes = remain_actual + total_bytes;
 		need_wrap = true;
+	} else if (unlikely(total_bytes > remain_usable)) {
+		/*
+		 * The base request will fit but the reserved space
+		 * falls off the end. So we don't need an immediate wrap
+		 * and only need to effectively wait for the reserved
+		 * size space from the start of ringbuffer.
+		 */
+		wait_bytes = remain_actual + ringbuf->reserved_size;
 	} else {
-		if (unlikely(total_bytes > remain_usable)) {
-			/*
-			 * The base request will fit but the reserved space
-			 * falls off the end. So don't need an immediate wrap
-			 * and only need to effectively wait for the reserved
-			 * size space from the start of ringbuffer.
-			 */
-			wait_bytes = remain_actual + ringbuf->reserved_size;
-		} else if (total_bytes > ringbuf->space) {
-			/* No wrapping required, just waiting. */
-			wait_bytes = total_bytes;
-		}
+		/* No wrapping required, just waiting. */
+		wait_bytes = total_bytes;
 	}
 
-	if (wait_bytes) {
-		ret = ring_wait_for_space(ring, wait_bytes);
+	if (wait_bytes > ringbuf->space) {
+		int ret = wait_for_space(req, wait_bytes);
 		if (unlikely(ret))
 			return ret;
 
-		if (need_wrap)
-			__wrap_ring_buffer(ringbuf);
+		intel_ring_update_space(ringbuf);
+		if (unlikely(ringbuf->space < wait_bytes))
+			return -EAGAIN;
 	}
 
-	return 0;
-}
-
-int intel_ring_begin(struct drm_i915_gem_request *req,
-		     int num_dwords)
-{
-	struct intel_engine_cs *ring;
-	struct drm_i915_private *dev_priv;
-	int ret;
-
-	WARN_ON(req == NULL);
-	ring = req->ring;
-	dev_priv = ring->dev->dev_private;
-
-	ret = i915_gem_check_wedge(&dev_priv->gpu_error,
-				   dev_priv->mm.interruptible);
-	if (ret)
-		return ret;
+	if (unlikely(need_wrap)) {
+		GEM_BUG_ON(remain_actual > ringbuf->space);
+		GEM_BUG_ON(ringbuf->tail + remain_actual > ringbuf->size);
 
-	ret = __intel_ring_prepare(ring, num_dwords * sizeof(uint32_t));
-	if (ret)
-		return ret;
+		/* Fill the tail with MI_NOOP */
+		memset(ringbuf->virtual_start + ringbuf->tail,
+		       0, remain_actual);
+		ringbuf->tail = 0;
+		ringbuf->space -= remain_actual;
+	}
 
-	ring->buffer->space -= num_dwords * sizeof(uint32_t);
+	ringbuf->space -= bytes;
+	GEM_BUG_ON(ringbuf->space < 0);
 	return 0;
 }
 
 /* Align the ring tail to a cacheline boundary */
 int intel_ring_cacheline_align(struct drm_i915_gem_request *req)
 {
-	struct intel_engine_cs *ring = req->ring;
-	int num_dwords = (ring->buffer->tail & (CACHELINE_BYTES - 1)) / sizeof(uint32_t);
+	struct intel_engine_cs *engine = req->engine;
+	int num_dwords = (engine->buffer->tail & (CACHELINE_BYTES - 1)) / sizeof(uint32_t);
 	int ret;
 
 	if (num_dwords == 0)
@@ -2521,33 +2567,52 @@ int intel_ring_cacheline_align(struct dr
 		return ret;
 
 	while (num_dwords--)
-		intel_ring_emit(ring, MI_NOOP);
+		intel_ring_emit(engine, MI_NOOP);
 
-	intel_ring_advance(ring);
+	intel_ring_advance(engine);
 
 	return 0;
 }
 
-void intel_ring_init_seqno(struct intel_engine_cs *ring, u32 seqno)
+void intel_ring_init_seqno(struct intel_engine_cs *engine, u32 seqno)
 {
-	struct drm_device *dev = ring->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = to_i915(engine->dev);
 
-	if (INTEL_INFO(dev)->gen == 6 || INTEL_INFO(dev)->gen == 7) {
-		I915_WRITE(RING_SYNC_0(ring->mmio_base), 0);
-		I915_WRITE(RING_SYNC_1(ring->mmio_base), 0);
-		if (HAS_VEBOX(dev))
-			I915_WRITE(RING_SYNC_2(ring->mmio_base), 0);
+	/* Our semaphore implementation is strictly monotonic (i.e. we proceed
+	 * so long as the semaphore value in the register/page is greater
+	 * than the sync value), so whenever we reset the seqno,
+	 * so long as we reset the tracking semaphore value to 0, it will
+	 * always be before the next request's seqno. If we don't reset
+	 * the semaphore value, then when the seqno moves backwards all
+	 * future waits will complete instantly (causing rendering corruption).
+	 */
+	if (INTEL_INFO(dev_priv)->gen == 6 || INTEL_INFO(dev_priv)->gen == 7) {
+		I915_WRITE(RING_SYNC_0(engine->mmio_base), 0);
+		I915_WRITE(RING_SYNC_1(engine->mmio_base), 0);
+		if (HAS_VEBOX(dev_priv))
+			I915_WRITE(RING_SYNC_2(engine->mmio_base), 0);
+	}
+	if (dev_priv->semaphore_obj) {
+		struct drm_i915_gem_object *obj = dev_priv->semaphore_obj;
+		struct page *page = i915_gem_object_get_dirty_page(obj, 0);
+		void *semaphores = kmap(page);
+		memset(semaphores + GEN8_SEMAPHORE_OFFSET(engine->id, 0),
+		       0, I915_NUM_ENGINES * gen8_semaphore_seqno_size);
+		kunmap(page);
 	}
+	memset(engine->semaphore.sync_seqno, 0,
+	       sizeof(engine->semaphore.sync_seqno));
 
-	ring->set_seqno(ring, seqno);
-	ring->hangcheck.seqno = seqno;
+	engine->set_seqno(engine, seqno);
+	engine->last_submitted_seqno = seqno;
+
+	engine->hangcheck.seqno = seqno;
 }
 
-static void gen6_bsd_ring_write_tail(struct intel_engine_cs *ring,
+static void gen6_bsd_ring_write_tail(struct intel_engine_cs *engine,
 				     u32 value)
 {
-	struct drm_i915_private *dev_priv = ring->dev->dev_private;
+	struct drm_i915_private *dev_priv = engine->dev->dev_private;
 
        /* Every tail move must follow the sequence below */
 
@@ -2567,8 +2632,8 @@ static void gen6_bsd_ring_write_tail(str
 		DRM_ERROR("timed out waiting for the BSD ring to wake up\n");
 
 	/* Now that the ring is fully powered up, update the tail */
-	I915_WRITE_TAIL(ring, value);
-	POSTING_READ(RING_TAIL(ring->mmio_base));
+	I915_WRITE_TAIL(engine, value);
+	POSTING_READ(RING_TAIL(engine->mmio_base));
 
 	/* Let the ring send IDLE messages to the GT again,
 	 * and so let it sleep to conserve power when idle.
@@ -2580,7 +2645,7 @@ static void gen6_bsd_ring_write_tail(str
 static int gen6_bsd_ring_flush(struct drm_i915_gem_request *req,
 			       u32 invalidate, u32 flush)
 {
-	struct intel_engine_cs *ring = req->ring;
+	struct intel_engine_cs *engine = req->engine;
 	uint32_t cmd;
 	int ret;
 
@@ -2589,7 +2654,7 @@ static int gen6_bsd_ring_flush(struct dr
 		return ret;
 
 	cmd = MI_FLUSH_DW;
-	if (INTEL_INFO(ring->dev)->gen >= 8)
+	if (INTEL_INFO(engine->dev)->gen >= 8)
 		cmd += 1;
 
 	/* We always require a command barrier so that subsequent
@@ -2608,16 +2673,17 @@ static int gen6_bsd_ring_flush(struct dr
 	if (invalidate & I915_GEM_GPU_DOMAINS)
 		cmd |= MI_INVALIDATE_TLB | MI_INVALIDATE_BSD;
 
-	intel_ring_emit(ring, cmd);
-	intel_ring_emit(ring, I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT);
-	if (INTEL_INFO(ring->dev)->gen >= 8) {
-		intel_ring_emit(ring, 0); /* upper addr */
-		intel_ring_emit(ring, 0); /* value */
+	intel_ring_emit(engine, cmd);
+	intel_ring_emit(engine,
+			I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT);
+	if (INTEL_INFO(engine->dev)->gen >= 8) {
+		intel_ring_emit(engine, 0); /* upper addr */
+		intel_ring_emit(engine, 0); /* value */
 	} else  {
-		intel_ring_emit(ring, 0);
-		intel_ring_emit(ring, MI_NOOP);
+		intel_ring_emit(engine, 0);
+		intel_ring_emit(engine, MI_NOOP);
 	}
-	intel_ring_advance(ring);
+	intel_ring_advance(engine);
 	return 0;
 }
 
@@ -2626,8 +2692,8 @@ gen8_ring_dispatch_execbuffer(struct drm
 			      u64 offset, u32 len,
 			      unsigned dispatch_flags)
 {
-	struct intel_engine_cs *ring = req->ring;
-	bool ppgtt = USES_PPGTT(ring->dev) &&
+	struct intel_engine_cs *engine = req->engine;
+	bool ppgtt = USES_PPGTT(engine->dev) &&
 			!(dispatch_flags & I915_DISPATCH_SECURE);
 	int ret;
 
@@ -2636,13 +2702,13 @@ gen8_ring_dispatch_execbuffer(struct drm
 		return ret;
 
 	/* FIXME(BDW): Address space and security selectors. */
-	intel_ring_emit(ring, MI_BATCH_BUFFER_START_GEN8 | (ppgtt<<8) |
+	intel_ring_emit(engine, MI_BATCH_BUFFER_START_GEN8 | (ppgtt<<8) |
 			(dispatch_flags & I915_DISPATCH_RS ?
 			 MI_BATCH_RESOURCE_STREAMER : 0));
-	intel_ring_emit(ring, lower_32_bits(offset));
-	intel_ring_emit(ring, upper_32_bits(offset));
-	intel_ring_emit(ring, MI_NOOP);
-	intel_ring_advance(ring);
+	intel_ring_emit(engine, lower_32_bits(offset));
+	intel_ring_emit(engine, upper_32_bits(offset));
+	intel_ring_emit(engine, MI_NOOP);
+	intel_ring_advance(engine);
 
 	return 0;
 }
@@ -2652,22 +2718,22 @@ hsw_ring_dispatch_execbuffer(struct drm_
 			     u64 offset, u32 len,
 			     unsigned dispatch_flags)
 {
-	struct intel_engine_cs *ring = req->ring;
+	struct intel_engine_cs *engine = req->engine;
 	int ret;
 
 	ret = intel_ring_begin(req, 2);
 	if (ret)
 		return ret;
 
-	intel_ring_emit(ring,
+	intel_ring_emit(engine,
 			MI_BATCH_BUFFER_START |
 			(dispatch_flags & I915_DISPATCH_SECURE ?
 			 0 : MI_BATCH_PPGTT_HSW | MI_BATCH_NON_SECURE_HSW) |
 			(dispatch_flags & I915_DISPATCH_RS ?
 			 MI_BATCH_RESOURCE_STREAMER : 0));
 	/* bit0-7 is the length on GEN6+ */
-	intel_ring_emit(ring, offset);
-	intel_ring_advance(ring);
+	intel_ring_emit(engine, offset);
+	intel_ring_advance(engine);
 
 	return 0;
 }
@@ -2677,20 +2743,20 @@ gen6_ring_dispatch_execbuffer(struct drm
 			      u64 offset, u32 len,
 			      unsigned dispatch_flags)
 {
-	struct intel_engine_cs *ring = req->ring;
+	struct intel_engine_cs *engine = req->engine;
 	int ret;
 
 	ret = intel_ring_begin(req, 2);
 	if (ret)
 		return ret;
 
-	intel_ring_emit(ring,
+	intel_ring_emit(engine,
 			MI_BATCH_BUFFER_START |
 			(dispatch_flags & I915_DISPATCH_SECURE ?
 			 0 : MI_BATCH_NON_SECURE_I965));
 	/* bit0-7 is the length on GEN6+ */
-	intel_ring_emit(ring, offset);
-	intel_ring_advance(ring);
+	intel_ring_emit(engine, offset);
+	intel_ring_advance(engine);
 
 	return 0;
 }
@@ -2700,8 +2766,8 @@ gen6_ring_dispatch_execbuffer(struct drm
 static int gen6_ring_flush(struct drm_i915_gem_request *req,
 			   u32 invalidate, u32 flush)
 {
-	struct intel_engine_cs *ring = req->ring;
-	struct drm_device *dev = ring->dev;
+	struct intel_engine_cs *engine = req->engine;
+	struct drm_device *dev = engine->dev;
 	uint32_t cmd;
 	int ret;
 
@@ -2728,16 +2794,17 @@ static int gen6_ring_flush(struct drm_i9
 	 */
 	if (invalidate & I915_GEM_DOMAIN_RENDER)
 		cmd |= MI_INVALIDATE_TLB;
-	intel_ring_emit(ring, cmd);
-	intel_ring_emit(ring, I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT);
+	intel_ring_emit(engine, cmd);
+	intel_ring_emit(engine,
+			I915_GEM_HWS_SCRATCH_ADDR | MI_FLUSH_DW_USE_GTT);
 	if (INTEL_INFO(dev)->gen >= 8) {
-		intel_ring_emit(ring, 0); /* upper addr */
-		intel_ring_emit(ring, 0); /* value */
+		intel_ring_emit(engine, 0); /* upper addr */
+		intel_ring_emit(engine, 0); /* value */
 	} else  {
-		intel_ring_emit(ring, 0);
-		intel_ring_emit(ring, MI_NOOP);
+		intel_ring_emit(engine, 0);
+		intel_ring_emit(engine, MI_NOOP);
 	}
-	intel_ring_advance(ring);
+	intel_ring_advance(engine);
 
 	return 0;
 }
@@ -2745,14 +2812,15 @@ static int gen6_ring_flush(struct drm_i9
 int intel_init_render_ring_buffer(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring = &dev_priv->ring[RCS];
+	struct intel_engine_cs *engine = &dev_priv->engine[RCS];
 	struct drm_i915_gem_object *obj;
 	int ret;
 
-	ring->name = "render ring";
-	ring->id = RCS;
-	ring->exec_id = I915_EXEC_RENDER;
-	ring->mmio_base = RENDER_RING_BASE;
+	engine->name = "render ring";
+	engine->id = RCS;
+	engine->exec_id = I915_EXEC_RENDER;
+	engine->hw_id = 0;
+	engine->mmio_base = RENDER_RING_BASE;
 
 	if (INTEL_INFO(dev)->gen >= 8) {
 		if (i915_semaphore_is_enabled(dev)) {
@@ -2772,34 +2840,36 @@ int intel_init_render_ring_buffer(struct
 			}
 		}
 
-		ring->init_context = intel_rcs_ctx_init;
-		ring->add_request = gen6_add_request;
-		ring->flush = gen8_render_ring_flush;
-		ring->irq_get = gen8_ring_get_irq;
-		ring->irq_put = gen8_ring_put_irq;
-		ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT;
-		ring->get_seqno = gen6_ring_get_seqno;
-		ring->set_seqno = ring_set_seqno;
+		engine->init_context = intel_rcs_ctx_init;
+		engine->add_request = gen6_add_request;
+		engine->flush = gen8_render_ring_flush;
+		engine->irq_get = gen8_ring_get_irq;
+		engine->irq_put = gen8_ring_put_irq;
+		engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT;
+		engine->irq_seqno_barrier = gen6_seqno_barrier;
+		engine->get_seqno = ring_get_seqno;
+		engine->set_seqno = ring_set_seqno;
 		if (i915_semaphore_is_enabled(dev)) {
 			WARN_ON(!dev_priv->semaphore_obj);
-			ring->semaphore.sync_to = gen8_ring_sync;
-			ring->semaphore.signal = gen8_rcs_signal;
-			GEN8_RING_SEMAPHORE_INIT;
+			engine->semaphore.sync_to = gen8_ring_sync;
+			engine->semaphore.signal = gen8_rcs_signal;
+			GEN8_RING_SEMAPHORE_INIT(engine);
 		}
 	} else if (INTEL_INFO(dev)->gen >= 6) {
-		ring->init_context = intel_rcs_ctx_init;
-		ring->add_request = gen6_add_request;
-		ring->flush = gen7_render_ring_flush;
+		engine->init_context = intel_rcs_ctx_init;
+		engine->add_request = gen6_add_request;
+		engine->flush = gen7_render_ring_flush;
 		if (INTEL_INFO(dev)->gen == 6)
-			ring->flush = gen6_render_ring_flush;
-		ring->irq_get = gen6_ring_get_irq;
-		ring->irq_put = gen6_ring_put_irq;
-		ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT;
-		ring->get_seqno = gen6_ring_get_seqno;
-		ring->set_seqno = ring_set_seqno;
+			engine->flush = gen6_render_ring_flush;
+		engine->irq_get = gen6_ring_get_irq;
+		engine->irq_put = gen6_ring_put_irq;
+		engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT;
+		engine->irq_seqno_barrier = gen6_seqno_barrier;
+		engine->get_seqno = ring_get_seqno;
+		engine->set_seqno = ring_set_seqno;
 		if (i915_semaphore_is_enabled(dev)) {
-			ring->semaphore.sync_to = gen6_ring_sync;
-			ring->semaphore.signal = gen6_signal;
+			engine->semaphore.sync_to = gen6_ring_sync;
+			engine->semaphore.signal = gen6_signal;
 			/*
 			 * The current semaphore is only applied on pre-gen8
 			 * platform.  And there is no VCS2 ring on the pre-gen8
@@ -2807,59 +2877,59 @@ int intel_init_render_ring_buffer(struct
 			 * initialized as INVALID.  Gen8 will initialize the
 			 * sema between VCS2 and RCS later.
 			 */
-			ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_INVALID;
-			ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_RV;
-			ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_RB;
-			ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_RVE;
-			ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
-			ring->semaphore.mbox.signal[RCS] = GEN6_NOSYNC;
-			ring->semaphore.mbox.signal[VCS] = GEN6_VRSYNC;
-			ring->semaphore.mbox.signal[BCS] = GEN6_BRSYNC;
-			ring->semaphore.mbox.signal[VECS] = GEN6_VERSYNC;
-			ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+			engine->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_INVALID;
+			engine->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_RV;
+			engine->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_RB;
+			engine->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_RVE;
+			engine->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
+			engine->semaphore.mbox.signal[RCS] = GEN6_NOSYNC;
+			engine->semaphore.mbox.signal[VCS] = GEN6_VRSYNC;
+			engine->semaphore.mbox.signal[BCS] = GEN6_BRSYNC;
+			engine->semaphore.mbox.signal[VECS] = GEN6_VERSYNC;
+			engine->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
 		}
 	} else if (IS_GEN5(dev)) {
-		ring->add_request = pc_render_add_request;
-		ring->flush = gen4_render_ring_flush;
-		ring->get_seqno = pc_render_get_seqno;
-		ring->set_seqno = pc_render_set_seqno;
-		ring->irq_get = gen5_ring_get_irq;
-		ring->irq_put = gen5_ring_put_irq;
-		ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT |
+		engine->add_request = pc_render_add_request;
+		engine->flush = gen4_render_ring_flush;
+		engine->get_seqno = pc_render_get_seqno;
+		engine->set_seqno = pc_render_set_seqno;
+		engine->irq_get = gen5_ring_get_irq;
+		engine->irq_put = gen5_ring_put_irq;
+		engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT |
 					GT_RENDER_PIPECTL_NOTIFY_INTERRUPT;
 	} else {
-		ring->add_request = i9xx_add_request;
+		engine->add_request = i9xx_add_request;
 		if (INTEL_INFO(dev)->gen < 4)
-			ring->flush = gen2_render_ring_flush;
+			engine->flush = gen2_render_ring_flush;
 		else
-			ring->flush = gen4_render_ring_flush;
-		ring->get_seqno = ring_get_seqno;
-		ring->set_seqno = ring_set_seqno;
+			engine->flush = gen4_render_ring_flush;
+		engine->get_seqno = ring_get_seqno;
+		engine->set_seqno = ring_set_seqno;
 		if (IS_GEN2(dev)) {
-			ring->irq_get = i8xx_ring_get_irq;
-			ring->irq_put = i8xx_ring_put_irq;
+			engine->irq_get = i8xx_ring_get_irq;
+			engine->irq_put = i8xx_ring_put_irq;
 		} else {
-			ring->irq_get = i9xx_ring_get_irq;
-			ring->irq_put = i9xx_ring_put_irq;
+			engine->irq_get = i9xx_ring_get_irq;
+			engine->irq_put = i9xx_ring_put_irq;
 		}
-		ring->irq_enable_mask = I915_USER_INTERRUPT;
+		engine->irq_enable_mask = I915_USER_INTERRUPT;
 	}
-	ring->write_tail = ring_write_tail;
+	engine->write_tail = ring_write_tail;
 
 	if (IS_HASWELL(dev))
-		ring->dispatch_execbuffer = hsw_ring_dispatch_execbuffer;
+		engine->dispatch_execbuffer = hsw_ring_dispatch_execbuffer;
 	else if (IS_GEN8(dev))
-		ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer;
+		engine->dispatch_execbuffer = gen8_ring_dispatch_execbuffer;
 	else if (INTEL_INFO(dev)->gen >= 6)
-		ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
+		engine->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
 	else if (INTEL_INFO(dev)->gen >= 4)
-		ring->dispatch_execbuffer = i965_dispatch_execbuffer;
+		engine->dispatch_execbuffer = i965_dispatch_execbuffer;
 	else if (IS_I830(dev) || IS_845G(dev))
-		ring->dispatch_execbuffer = i830_dispatch_execbuffer;
+		engine->dispatch_execbuffer = i830_dispatch_execbuffer;
 	else
-		ring->dispatch_execbuffer = i915_dispatch_execbuffer;
-	ring->init_hw = init_render_ring;
-	ring->cleanup = render_ring_cleanup;
+		engine->dispatch_execbuffer = i915_dispatch_execbuffer;
+	engine->init_hw = init_render_ring;
+	engine->cleanup = render_ring_cleanup;
 
 	/* Workaround batchbuffer to combat CS tlb bug. */
 	if (HAS_BROKEN_CS_TLB(dev)) {
@@ -2876,16 +2946,16 @@ int intel_init_render_ring_buffer(struct
 			return ret;
 		}
 
-		ring->scratch.obj = obj;
-		ring->scratch.gtt_offset = i915_gem_obj_ggtt_offset(obj);
+		engine->scratch.obj = obj;
+		engine->scratch.gtt_offset = i915_gem_obj_ggtt_offset(obj);
 	}
 
-	ret = intel_init_ring_buffer(dev, ring);
+	ret = intel_init_ring_buffer(dev, engine);
 	if (ret)
 		return ret;
 
 	if (INTEL_INFO(dev)->gen >= 5) {
-		ret = intel_init_pipe_control(ring);
+		ret = intel_init_pipe_control(engine);
 		if (ret)
 			return ret;
 	}
@@ -2896,75 +2966,77 @@ int intel_init_render_ring_buffer(struct
 int intel_init_bsd_ring_buffer(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring = &dev_priv->ring[VCS];
+	struct intel_engine_cs *engine = &dev_priv->engine[VCS];
 
-	ring->name = "bsd ring";
-	ring->id = VCS;
-	ring->exec_id = I915_EXEC_BSD;
+	engine->name = "bsd ring";
+	engine->id = VCS;
+	engine->exec_id = I915_EXEC_BSD;
+	engine->hw_id = 1;
 
-	ring->write_tail = ring_write_tail;
+	engine->write_tail = ring_write_tail;
 	if (INTEL_INFO(dev)->gen >= 6) {
-		ring->mmio_base = GEN6_BSD_RING_BASE;
+		engine->mmio_base = GEN6_BSD_RING_BASE;
 		/* gen6 bsd needs a special wa for tail updates */
 		if (IS_GEN6(dev))
-			ring->write_tail = gen6_bsd_ring_write_tail;
-		ring->flush = gen6_bsd_ring_flush;
-		ring->add_request = gen6_add_request;
-		ring->get_seqno = gen6_ring_get_seqno;
-		ring->set_seqno = ring_set_seqno;
+			engine->write_tail = gen6_bsd_ring_write_tail;
+		engine->flush = gen6_bsd_ring_flush;
+		engine->add_request = gen6_add_request;
+		engine->irq_seqno_barrier = gen6_seqno_barrier;
+		engine->get_seqno = ring_get_seqno;
+		engine->set_seqno = ring_set_seqno;
 		if (INTEL_INFO(dev)->gen >= 8) {
-			ring->irq_enable_mask =
+			engine->irq_enable_mask =
 				GT_RENDER_USER_INTERRUPT << GEN8_VCS1_IRQ_SHIFT;
-			ring->irq_get = gen8_ring_get_irq;
-			ring->irq_put = gen8_ring_put_irq;
-			ring->dispatch_execbuffer =
+			engine->irq_get = gen8_ring_get_irq;
+			engine->irq_put = gen8_ring_put_irq;
+			engine->dispatch_execbuffer =
 				gen8_ring_dispatch_execbuffer;
 			if (i915_semaphore_is_enabled(dev)) {
-				ring->semaphore.sync_to = gen8_ring_sync;
-				ring->semaphore.signal = gen8_xcs_signal;
-				GEN8_RING_SEMAPHORE_INIT;
+				engine->semaphore.sync_to = gen8_ring_sync;
+				engine->semaphore.signal = gen8_xcs_signal;
+				GEN8_RING_SEMAPHORE_INIT(engine);
 			}
 		} else {
-			ring->irq_enable_mask = GT_BSD_USER_INTERRUPT;
-			ring->irq_get = gen6_ring_get_irq;
-			ring->irq_put = gen6_ring_put_irq;
-			ring->dispatch_execbuffer =
+			engine->irq_enable_mask = GT_BSD_USER_INTERRUPT;
+			engine->irq_get = gen6_ring_get_irq;
+			engine->irq_put = gen6_ring_put_irq;
+			engine->dispatch_execbuffer =
 				gen6_ring_dispatch_execbuffer;
 			if (i915_semaphore_is_enabled(dev)) {
-				ring->semaphore.sync_to = gen6_ring_sync;
-				ring->semaphore.signal = gen6_signal;
-				ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VR;
-				ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_INVALID;
-				ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VB;
-				ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_VVE;
-				ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
-				ring->semaphore.mbox.signal[RCS] = GEN6_RVSYNC;
-				ring->semaphore.mbox.signal[VCS] = GEN6_NOSYNC;
-				ring->semaphore.mbox.signal[BCS] = GEN6_BVSYNC;
-				ring->semaphore.mbox.signal[VECS] = GEN6_VEVSYNC;
-				ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+				engine->semaphore.sync_to = gen6_ring_sync;
+				engine->semaphore.signal = gen6_signal;
+				engine->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VR;
+				engine->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_INVALID;
+				engine->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VB;
+				engine->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_VVE;
+				engine->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
+				engine->semaphore.mbox.signal[RCS] = GEN6_RVSYNC;
+				engine->semaphore.mbox.signal[VCS] = GEN6_NOSYNC;
+				engine->semaphore.mbox.signal[BCS] = GEN6_BVSYNC;
+				engine->semaphore.mbox.signal[VECS] = GEN6_VEVSYNC;
+				engine->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
 			}
 		}
 	} else {
-		ring->mmio_base = BSD_RING_BASE;
-		ring->flush = bsd_ring_flush;
-		ring->add_request = i9xx_add_request;
-		ring->get_seqno = ring_get_seqno;
-		ring->set_seqno = ring_set_seqno;
+		engine->mmio_base = BSD_RING_BASE;
+		engine->flush = bsd_ring_flush;
+		engine->add_request = i9xx_add_request;
+		engine->get_seqno = ring_get_seqno;
+		engine->set_seqno = ring_set_seqno;
 		if (IS_GEN5(dev)) {
-			ring->irq_enable_mask = ILK_BSD_USER_INTERRUPT;
-			ring->irq_get = gen5_ring_get_irq;
-			ring->irq_put = gen5_ring_put_irq;
+			engine->irq_enable_mask = ILK_BSD_USER_INTERRUPT;
+			engine->irq_get = gen5_ring_get_irq;
+			engine->irq_put = gen5_ring_put_irq;
 		} else {
-			ring->irq_enable_mask = I915_BSD_USER_INTERRUPT;
-			ring->irq_get = i9xx_ring_get_irq;
-			ring->irq_put = i9xx_ring_put_irq;
+			engine->irq_enable_mask = I915_BSD_USER_INTERRUPT;
+			engine->irq_get = i9xx_ring_get_irq;
+			engine->irq_put = i9xx_ring_put_irq;
 		}
-		ring->dispatch_execbuffer = i965_dispatch_execbuffer;
+		engine->dispatch_execbuffer = i965_dispatch_execbuffer;
 	}
-	ring->init_hw = init_ring_common;
+	engine->init_hw = init_ring_common;
 
-	return intel_init_ring_buffer(dev, ring);
+	return intel_init_ring_buffer(dev, engine);
 }
 
 /**
@@ -2973,68 +3045,72 @@ int intel_init_bsd_ring_buffer(struct dr
 int intel_init_bsd2_ring_buffer(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring = &dev_priv->ring[VCS2];
+	struct intel_engine_cs *engine = &dev_priv->engine[VCS2];
 
-	ring->name = "bsd2 ring";
-	ring->id = VCS2;
-	ring->exec_id = I915_EXEC_BSD;
+	engine->name = "bsd2 ring";
+	engine->id = VCS2;
+	engine->exec_id = I915_EXEC_BSD;
+	engine->hw_id = 4;
 
-	ring->write_tail = ring_write_tail;
-	ring->mmio_base = GEN8_BSD2_RING_BASE;
-	ring->flush = gen6_bsd_ring_flush;
-	ring->add_request = gen6_add_request;
-	ring->get_seqno = gen6_ring_get_seqno;
-	ring->set_seqno = ring_set_seqno;
-	ring->irq_enable_mask =
+	engine->write_tail = ring_write_tail;
+	engine->mmio_base = GEN8_BSD2_RING_BASE;
+	engine->flush = gen6_bsd_ring_flush;
+	engine->add_request = gen6_add_request;
+	engine->irq_seqno_barrier = gen6_seqno_barrier;
+	engine->get_seqno = ring_get_seqno;
+	engine->set_seqno = ring_set_seqno;
+	engine->irq_enable_mask =
 			GT_RENDER_USER_INTERRUPT << GEN8_VCS2_IRQ_SHIFT;
-	ring->irq_get = gen8_ring_get_irq;
-	ring->irq_put = gen8_ring_put_irq;
-	ring->dispatch_execbuffer =
+	engine->irq_get = gen8_ring_get_irq;
+	engine->irq_put = gen8_ring_put_irq;
+	engine->dispatch_execbuffer =
 			gen8_ring_dispatch_execbuffer;
 	if (i915_semaphore_is_enabled(dev)) {
-		ring->semaphore.sync_to = gen8_ring_sync;
-		ring->semaphore.signal = gen8_xcs_signal;
-		GEN8_RING_SEMAPHORE_INIT;
+		engine->semaphore.sync_to = gen8_ring_sync;
+		engine->semaphore.signal = gen8_xcs_signal;
+		GEN8_RING_SEMAPHORE_INIT(engine);
 	}
-	ring->init_hw = init_ring_common;
+	engine->init_hw = init_ring_common;
 
-	return intel_init_ring_buffer(dev, ring);
+	return intel_init_ring_buffer(dev, engine);
 }
 
 int intel_init_blt_ring_buffer(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring = &dev_priv->ring[BCS];
+	struct intel_engine_cs *engine = &dev_priv->engine[BCS];
 
-	ring->name = "blitter ring";
-	ring->id = BCS;
-	ring->exec_id = I915_EXEC_BLT;
+	engine->name = "blitter ring";
+	engine->id = BCS;
+	engine->exec_id = I915_EXEC_BLT;
+	engine->hw_id = 2;
 
-	ring->mmio_base = BLT_RING_BASE;
-	ring->write_tail = ring_write_tail;
-	ring->flush = gen6_ring_flush;
-	ring->add_request = gen6_add_request;
-	ring->get_seqno = gen6_ring_get_seqno;
-	ring->set_seqno = ring_set_seqno;
+	engine->mmio_base = BLT_RING_BASE;
+	engine->write_tail = ring_write_tail;
+	engine->flush = gen6_ring_flush;
+	engine->add_request = gen6_add_request;
+	engine->irq_seqno_barrier = gen6_seqno_barrier;
+	engine->get_seqno = ring_get_seqno;
+	engine->set_seqno = ring_set_seqno;
 	if (INTEL_INFO(dev)->gen >= 8) {
-		ring->irq_enable_mask =
+		engine->irq_enable_mask =
 			GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT;
-		ring->irq_get = gen8_ring_get_irq;
-		ring->irq_put = gen8_ring_put_irq;
-		ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer;
+		engine->irq_get = gen8_ring_get_irq;
+		engine->irq_put = gen8_ring_put_irq;
+		engine->dispatch_execbuffer = gen8_ring_dispatch_execbuffer;
 		if (i915_semaphore_is_enabled(dev)) {
-			ring->semaphore.sync_to = gen8_ring_sync;
-			ring->semaphore.signal = gen8_xcs_signal;
-			GEN8_RING_SEMAPHORE_INIT;
+			engine->semaphore.sync_to = gen8_ring_sync;
+			engine->semaphore.signal = gen8_xcs_signal;
+			GEN8_RING_SEMAPHORE_INIT(engine);
 		}
 	} else {
-		ring->irq_enable_mask = GT_BLT_USER_INTERRUPT;
-		ring->irq_get = gen6_ring_get_irq;
-		ring->irq_put = gen6_ring_put_irq;
-		ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
+		engine->irq_enable_mask = GT_BLT_USER_INTERRUPT;
+		engine->irq_get = gen6_ring_get_irq;
+		engine->irq_put = gen6_ring_put_irq;
+		engine->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
 		if (i915_semaphore_is_enabled(dev)) {
-			ring->semaphore.signal = gen6_signal;
-			ring->semaphore.sync_to = gen6_ring_sync;
+			engine->semaphore.signal = gen6_signal;
+			engine->semaphore.sync_to = gen6_ring_sync;
 			/*
 			 * The current semaphore is only applied on pre-gen8
 			 * platform.  And there is no VCS2 ring on the pre-gen8
@@ -3042,127 +3118,129 @@ int intel_init_blt_ring_buffer(struct dr
 			 * initialized as INVALID.  Gen8 will initialize the
 			 * sema between BCS and VCS2 later.
 			 */
-			ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_BR;
-			ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_BV;
-			ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_INVALID;
-			ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_BVE;
-			ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
-			ring->semaphore.mbox.signal[RCS] = GEN6_RBSYNC;
-			ring->semaphore.mbox.signal[VCS] = GEN6_VBSYNC;
-			ring->semaphore.mbox.signal[BCS] = GEN6_NOSYNC;
-			ring->semaphore.mbox.signal[VECS] = GEN6_VEBSYNC;
-			ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+			engine->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_BR;
+			engine->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_BV;
+			engine->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_INVALID;
+			engine->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_BVE;
+			engine->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
+			engine->semaphore.mbox.signal[RCS] = GEN6_RBSYNC;
+			engine->semaphore.mbox.signal[VCS] = GEN6_VBSYNC;
+			engine->semaphore.mbox.signal[BCS] = GEN6_NOSYNC;
+			engine->semaphore.mbox.signal[VECS] = GEN6_VEBSYNC;
+			engine->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
 		}
 	}
-	ring->init_hw = init_ring_common;
+	engine->init_hw = init_ring_common;
 
-	return intel_init_ring_buffer(dev, ring);
+	return intel_init_ring_buffer(dev, engine);
 }
 
 int intel_init_vebox_ring_buffer(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_engine_cs *ring = &dev_priv->ring[VECS];
+	struct intel_engine_cs *engine = &dev_priv->engine[VECS];
 
-	ring->name = "video enhancement ring";
-	ring->id = VECS;
-	ring->exec_id = I915_EXEC_VEBOX;
+	engine->name = "video enhancement ring";
+	engine->id = VECS;
+	engine->exec_id = I915_EXEC_VEBOX;
+	engine->hw_id = 3;
 
-	ring->mmio_base = VEBOX_RING_BASE;
-	ring->write_tail = ring_write_tail;
-	ring->flush = gen6_ring_flush;
-	ring->add_request = gen6_add_request;
-	ring->get_seqno = gen6_ring_get_seqno;
-	ring->set_seqno = ring_set_seqno;
+	engine->mmio_base = VEBOX_RING_BASE;
+	engine->write_tail = ring_write_tail;
+	engine->flush = gen6_ring_flush;
+	engine->add_request = gen6_add_request;
+	engine->irq_seqno_barrier = gen6_seqno_barrier;
+	engine->get_seqno = ring_get_seqno;
+	engine->set_seqno = ring_set_seqno;
 
 	if (INTEL_INFO(dev)->gen >= 8) {
-		ring->irq_enable_mask =
+		engine->irq_enable_mask =
 			GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT;
-		ring->irq_get = gen8_ring_get_irq;
-		ring->irq_put = gen8_ring_put_irq;
-		ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer;
+		engine->irq_get = gen8_ring_get_irq;
+		engine->irq_put = gen8_ring_put_irq;
+		engine->dispatch_execbuffer = gen8_ring_dispatch_execbuffer;
 		if (i915_semaphore_is_enabled(dev)) {
-			ring->semaphore.sync_to = gen8_ring_sync;
-			ring->semaphore.signal = gen8_xcs_signal;
-			GEN8_RING_SEMAPHORE_INIT;
+			engine->semaphore.sync_to = gen8_ring_sync;
+			engine->semaphore.signal = gen8_xcs_signal;
+			GEN8_RING_SEMAPHORE_INIT(engine);
 		}
 	} else {
-		ring->irq_enable_mask = PM_VEBOX_USER_INTERRUPT;
-		ring->irq_get = hsw_vebox_get_irq;
-		ring->irq_put = hsw_vebox_put_irq;
-		ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
+		engine->irq_enable_mask = PM_VEBOX_USER_INTERRUPT;
+		engine->irq_get = hsw_vebox_get_irq;
+		engine->irq_put = hsw_vebox_put_irq;
+		engine->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
 		if (i915_semaphore_is_enabled(dev)) {
-			ring->semaphore.sync_to = gen6_ring_sync;
-			ring->semaphore.signal = gen6_signal;
-			ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VER;
-			ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_VEV;
-			ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VEB;
-			ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_INVALID;
-			ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
-			ring->semaphore.mbox.signal[RCS] = GEN6_RVESYNC;
-			ring->semaphore.mbox.signal[VCS] = GEN6_VVESYNC;
-			ring->semaphore.mbox.signal[BCS] = GEN6_BVESYNC;
-			ring->semaphore.mbox.signal[VECS] = GEN6_NOSYNC;
-			ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+			engine->semaphore.sync_to = gen6_ring_sync;
+			engine->semaphore.signal = gen6_signal;
+			engine->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VER;
+			engine->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_VEV;
+			engine->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VEB;
+			engine->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_INVALID;
+			engine->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
+			engine->semaphore.mbox.signal[RCS] = GEN6_RVESYNC;
+			engine->semaphore.mbox.signal[VCS] = GEN6_VVESYNC;
+			engine->semaphore.mbox.signal[BCS] = GEN6_BVESYNC;
+			engine->semaphore.mbox.signal[VECS] = GEN6_NOSYNC;
+			engine->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
 		}
 	}
-	ring->init_hw = init_ring_common;
+	engine->init_hw = init_ring_common;
 
-	return intel_init_ring_buffer(dev, ring);
+	return intel_init_ring_buffer(dev, engine);
 }
 
 int
 intel_ring_flush_all_caches(struct drm_i915_gem_request *req)
 {
-	struct intel_engine_cs *ring = req->ring;
+	struct intel_engine_cs *engine = req->engine;
 	int ret;
 
-	if (!ring->gpu_caches_dirty)
+	if (!engine->gpu_caches_dirty)
 		return 0;
 
-	ret = ring->flush(req, 0, I915_GEM_GPU_DOMAINS);
+	ret = engine->flush(req, 0, I915_GEM_GPU_DOMAINS);
 	if (ret)
 		return ret;
 
 	trace_i915_gem_ring_flush(req, 0, I915_GEM_GPU_DOMAINS);
 
-	ring->gpu_caches_dirty = false;
+	engine->gpu_caches_dirty = false;
 	return 0;
 }
 
 int
 intel_ring_invalidate_all_caches(struct drm_i915_gem_request *req)
 {
-	struct intel_engine_cs *ring = req->ring;
+	struct intel_engine_cs *engine = req->engine;
 	uint32_t flush_domains;
 	int ret;
 
 	flush_domains = 0;
-	if (ring->gpu_caches_dirty)
+	if (engine->gpu_caches_dirty)
 		flush_domains = I915_GEM_GPU_DOMAINS;
 
-	ret = ring->flush(req, I915_GEM_GPU_DOMAINS, flush_domains);
+	ret = engine->flush(req, I915_GEM_GPU_DOMAINS, flush_domains);
 	if (ret)
 		return ret;
 
 	trace_i915_gem_ring_flush(req, I915_GEM_GPU_DOMAINS, flush_domains);
 
-	ring->gpu_caches_dirty = false;
+	engine->gpu_caches_dirty = false;
 	return 0;
 }
 
 void
-intel_stop_ring_buffer(struct intel_engine_cs *ring)
+intel_stop_engine(struct intel_engine_cs *engine)
 {
 	int ret;
 
-	if (!intel_ring_initialized(ring))
+	if (!intel_engine_initialized(engine))
 		return;
 
-	ret = intel_ring_idle(ring);
-	if (ret && !i915_reset_in_progress(&to_i915(ring->dev)->gpu_error))
+	ret = intel_engine_idle(engine);
+	if (ret)
 		DRM_ERROR("failed to quiesce %s whilst cleaning up: %d\n",
-			  ring->name, ret);
+			  engine->name, ret);
 
-	stop_ring(ring);
+	stop_ring(engine);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_ringbuffer.h linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_ringbuffer.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_ringbuffer.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_ringbuffer.h	2016-07-24 15:23:50.000000000 -0400
@@ -52,34 +52,32 @@ struct  intel_hw_status_page {
 /* seqno size is actually only a uint32, but since we plan to use MI_FLUSH_DW to
  * do the writes, and that must have qw aligned offsets, simply pretend it's 8b.
  */
-#define i915_semaphore_seqno_size sizeof(uint64_t)
+#define gen8_semaphore_seqno_size sizeof(uint64_t)
+#define GEN8_SEMAPHORE_OFFSET(__from, __to)			     \
+	(((__from) * I915_NUM_ENGINES  + (__to)) * gen8_semaphore_seqno_size)
 #define GEN8_SIGNAL_OFFSET(__ring, to)			     \
 	(i915_gem_obj_ggtt_offset(dev_priv->semaphore_obj) + \
-	((__ring)->id * I915_NUM_RINGS * i915_semaphore_seqno_size) +	\
-	(i915_semaphore_seqno_size * (to)))
-
+	 GEN8_SEMAPHORE_OFFSET((__ring)->id, (to)))
 #define GEN8_WAIT_OFFSET(__ring, from)			     \
 	(i915_gem_obj_ggtt_offset(dev_priv->semaphore_obj) + \
-	((from) * I915_NUM_RINGS * i915_semaphore_seqno_size) + \
-	(i915_semaphore_seqno_size * (__ring)->id))
+	 GEN8_SEMAPHORE_OFFSET(from, (__ring)->id))
 
-#define GEN8_RING_SEMAPHORE_INIT do { \
+#define GEN8_RING_SEMAPHORE_INIT(e) do { \
 	if (!dev_priv->semaphore_obj) { \
 		break; \
 	} \
-	ring->semaphore.signal_ggtt[RCS] = GEN8_SIGNAL_OFFSET(ring, RCS); \
-	ring->semaphore.signal_ggtt[VCS] = GEN8_SIGNAL_OFFSET(ring, VCS); \
-	ring->semaphore.signal_ggtt[BCS] = GEN8_SIGNAL_OFFSET(ring, BCS); \
-	ring->semaphore.signal_ggtt[VECS] = GEN8_SIGNAL_OFFSET(ring, VECS); \
-	ring->semaphore.signal_ggtt[VCS2] = GEN8_SIGNAL_OFFSET(ring, VCS2); \
-	ring->semaphore.signal_ggtt[ring->id] = MI_SEMAPHORE_SYNC_INVALID; \
+	(e)->semaphore.signal_ggtt[RCS] = GEN8_SIGNAL_OFFSET((e), RCS); \
+	(e)->semaphore.signal_ggtt[VCS] = GEN8_SIGNAL_OFFSET((e), VCS); \
+	(e)->semaphore.signal_ggtt[BCS] = GEN8_SIGNAL_OFFSET((e), BCS); \
+	(e)->semaphore.signal_ggtt[VECS] = GEN8_SIGNAL_OFFSET((e), VECS); \
+	(e)->semaphore.signal_ggtt[VCS2] = GEN8_SIGNAL_OFFSET((e), VCS2); \
+	(e)->semaphore.signal_ggtt[(e)->id] = MI_SEMAPHORE_SYNC_INVALID; \
 	} while(0)
 
 enum intel_ring_hangcheck_action {
 	HANGCHECK_IDLE = 0,
 	HANGCHECK_WAIT,
 	HANGCHECK_ACTIVE,
-	HANGCHECK_ACTIVE_LOOP,
 	HANGCHECK_KICK,
 	HANGCHECK_HUNG,
 };
@@ -88,8 +86,8 @@ enum intel_ring_hangcheck_action {
 
 struct intel_ring_hangcheck {
 	u64 acthd;
-	u64 max_acthd;
 	u32 seqno;
+	unsigned user_interrupts;
 	int score;
 	enum intel_ring_hangcheck_action action;
 	int deadlock;
@@ -101,7 +99,7 @@ struct intel_ringbuffer {
 	void __iomem *virtual_start;
 	struct i915_vma *vma;
 
-	struct intel_engine_cs *ring;
+	struct intel_engine_cs *engine;
 	struct list_head link;
 
 	u32 head;
@@ -110,8 +108,6 @@ struct intel_ringbuffer {
 	int size;
 	int effective_size;
 	int reserved_size;
-	int reserved_tail;
-	bool reserved_in_use;
 
 	/** We track the position of the requests in the ring buffer, and
 	 * when each is retired we increment last_retired_head as the GPU
@@ -125,7 +121,7 @@ struct intel_ringbuffer {
 };
 
 struct	intel_context;
-struct drm_i915_reg_descriptor;
+struct drm_i915_reg_table;
 
 /*
  * we use a single page to load ctx workarounds so all of these
@@ -148,17 +144,18 @@ struct  i915_ctx_workarounds {
 
 struct  intel_engine_cs {
 	const char	*name;
-	enum intel_ring_id {
+	enum intel_engine_id {
 		RCS = 0,
 		BCS,
 		VCS,
 		VCS2,	/* Keep instances of the same type engine together. */
 		VECS
 	} id;
-#define I915_NUM_RINGS 5
+#define I915_NUM_ENGINES 5
 #define _VCS(n) (VCS + (n))
 	unsigned int exec_id;
-	unsigned int guc_id;
+	unsigned int hw_id;
+	unsigned int guc_id; /* XXX same as hw_id? */
 	u32		mmio_base;
 	struct		drm_device *dev;
 	struct intel_ringbuffer *buffer;
@@ -196,8 +193,8 @@ struct  intel_engine_cs {
 	 * seen value is good enough. Note that the seqno will always be
 	 * monotonic, even if not coherent.
 	 */
-	u32		(*get_seqno)(struct intel_engine_cs *ring,
-				     bool lazy_coherency);
+	void		(*irq_seqno_barrier)(struct intel_engine_cs *ring);
+	u32		(*get_seqno)(struct intel_engine_cs *ring);
 	void		(*set_seqno)(struct intel_engine_cs *ring,
 				     u32 seqno);
 	int		(*dispatch_execbuffer)(struct drm_i915_gem_request *req,
@@ -246,16 +243,16 @@ struct  intel_engine_cs {
 	 *  ie. transpose of f(x, y)
 	 */
 	struct {
-		u32	sync_seqno[I915_NUM_RINGS-1];
+		u32	sync_seqno[I915_NUM_ENGINES-1];
 
 		union {
 			struct {
 				/* our mbox written by others */
-				u32		wait[I915_NUM_RINGS];
+				u32		wait[I915_NUM_ENGINES];
 				/* mboxes this ring signals to */
-				i915_reg_t	signal[I915_NUM_RINGS];
+				i915_reg_t	signal[I915_NUM_ENGINES];
 			} mbox;
-			u64		signal_ggtt[I915_NUM_RINGS];
+			u64		signal_ggtt[I915_NUM_ENGINES];
 		};
 
 		/* AKA wait() */
@@ -268,10 +265,13 @@ struct  intel_engine_cs {
 	} semaphore;
 
 	/* Execlists */
-	spinlock_t execlist_lock;
+	struct tasklet_struct irq_tasklet;
+	spinlock_t execlist_lock; /* used inside tasklet, use spin_lock_bh */
 	struct list_head execlist_queue;
 	struct list_head execlist_retired_req_list;
-	u8 next_context_status_buffer;
+	unsigned int fw_domains;
+	unsigned int next_context_status_buffer;
+	unsigned int idle_lite_restore_wa;
 	bool disable_lite_restore_wa;
 	u32 ctx_desc_template;
 	u32             irq_keep_mask; /* bitmask for interrupts that should not be masked */
@@ -306,6 +306,7 @@ struct  intel_engine_cs {
 	 * inspecting request list.
 	 */
 	u32 last_submitted_seqno;
+	unsigned user_interrupts;
 
 	bool gpu_caches_dirty;
 
@@ -332,15 +333,8 @@ struct  intel_engine_cs {
 	/*
 	 * Table of registers allowed in commands that read/write registers.
 	 */
-	const struct drm_i915_reg_descriptor *reg_table;
-	int reg_count;
-
-	/*
-	 * Table of registers allowed in commands that read/write registers, but
-	 * only from the DRM master.
-	 */
-	const struct drm_i915_reg_descriptor *master_reg_table;
-	int master_reg_count;
+	const struct drm_i915_reg_table *reg_tables;
+	int reg_table_count;
 
 	/*
 	 * Returns the bitmask for the length field of the specified command.
@@ -356,19 +350,19 @@ struct  intel_engine_cs {
 };
 
 static inline bool
-intel_ring_initialized(struct intel_engine_cs *ring)
+intel_engine_initialized(struct intel_engine_cs *engine)
 {
-	return ring->dev != NULL;
+	return engine->dev != NULL;
 }
 
 static inline unsigned
-intel_ring_flag(struct intel_engine_cs *ring)
+intel_engine_flag(struct intel_engine_cs *engine)
 {
-	return 1 << ring->id;
+	return 1 << engine->id;
 }
 
 static inline u32
-intel_ring_sync_index(struct intel_engine_cs *ring,
+intel_ring_sync_index(struct intel_engine_cs *engine,
 		      struct intel_engine_cs *other)
 {
 	int idx;
@@ -381,34 +375,33 @@ intel_ring_sync_index(struct intel_engin
 	 * vcs2 -> 0 = rcs, 1 = vcs, 2 = bcs, 3 = vecs;
 	 */
 
-	idx = (other - ring) - 1;
+	idx = (other - engine) - 1;
 	if (idx < 0)
-		idx += I915_NUM_RINGS;
+		idx += I915_NUM_ENGINES;
 
 	return idx;
 }
 
 static inline void
-intel_flush_status_page(struct intel_engine_cs *ring, int reg)
+intel_flush_status_page(struct intel_engine_cs *engine, int reg)
 {
-	drm_clflush_virt_range(&ring->status_page.page_addr[reg],
-			       sizeof(uint32_t));
+	mb();
+	clflush(&engine->status_page.page_addr[reg]);
+	mb();
 }
 
 static inline u32
-intel_read_status_page(struct intel_engine_cs *ring,
-		       int reg)
+intel_read_status_page(struct intel_engine_cs *engine, int reg)
 {
 	/* Ensure that the compiler doesn't optimize away the load. */
-	barrier();
-	return ring->status_page.page_addr[reg];
+	return READ_ONCE(engine->status_page.page_addr[reg]);
 }
 
 static inline void
-intel_write_status_page(struct intel_engine_cs *ring,
+intel_write_status_page(struct intel_engine_cs *engine,
 			int reg, u32 value)
 {
-	ring->status_page.page_addr[reg] = value;
+	engine->status_page.page_addr[reg] = value;
 }
 
 /*
@@ -439,42 +432,41 @@ int intel_pin_and_map_ringbuffer_obj(str
 void intel_unpin_ringbuffer_obj(struct intel_ringbuffer *ringbuf);
 void intel_ringbuffer_free(struct intel_ringbuffer *ring);
 
-void intel_stop_ring_buffer(struct intel_engine_cs *ring);
-void intel_cleanup_ring_buffer(struct intel_engine_cs *ring);
+void intel_stop_engine(struct intel_engine_cs *engine);
+void intel_cleanup_engine(struct intel_engine_cs *engine);
 
 int intel_ring_alloc_request_extras(struct drm_i915_gem_request *request);
 
 int __must_check intel_ring_begin(struct drm_i915_gem_request *req, int n);
 int __must_check intel_ring_cacheline_align(struct drm_i915_gem_request *req);
-static inline void intel_ring_emit(struct intel_engine_cs *ring,
+static inline void intel_ring_emit(struct intel_engine_cs *engine,
 				   u32 data)
 {
-	struct intel_ringbuffer *ringbuf = ring->buffer;
+	struct intel_ringbuffer *ringbuf = engine->buffer;
 	iowrite32(data, ringbuf->virtual_start + ringbuf->tail);
 	ringbuf->tail += 4;
 }
-static inline void intel_ring_emit_reg(struct intel_engine_cs *ring,
+static inline void intel_ring_emit_reg(struct intel_engine_cs *engine,
 				       i915_reg_t reg)
 {
-	intel_ring_emit(ring, i915_mmio_reg_offset(reg));
+	intel_ring_emit(engine, i915_mmio_reg_offset(reg));
 }
-static inline void intel_ring_advance(struct intel_engine_cs *ring)
+static inline void intel_ring_advance(struct intel_engine_cs *engine)
 {
-	struct intel_ringbuffer *ringbuf = ring->buffer;
+	struct intel_ringbuffer *ringbuf = engine->buffer;
 	ringbuf->tail &= ringbuf->size - 1;
 }
 int __intel_ring_space(int head, int tail, int size);
 void intel_ring_update_space(struct intel_ringbuffer *ringbuf);
-int intel_ring_space(struct intel_ringbuffer *ringbuf);
-bool intel_ring_stopped(struct intel_engine_cs *ring);
+bool intel_engine_stopped(struct intel_engine_cs *engine);
 
-int __must_check intel_ring_idle(struct intel_engine_cs *ring);
-void intel_ring_init_seqno(struct intel_engine_cs *ring, u32 seqno);
+int __must_check intel_engine_idle(struct intel_engine_cs *engine);
+void intel_ring_init_seqno(struct intel_engine_cs *engine, u32 seqno);
 int intel_ring_flush_all_caches(struct drm_i915_gem_request *req);
 int intel_ring_invalidate_all_caches(struct drm_i915_gem_request *req);
 
-void intel_fini_pipe_control(struct intel_engine_cs *ring);
-int intel_init_pipe_control(struct intel_engine_cs *ring);
+void intel_fini_pipe_control(struct intel_engine_cs *engine);
+int intel_init_pipe_control(struct intel_engine_cs *engine);
 
 int intel_init_render_ring_buffer(struct drm_device *dev);
 int intel_init_bsd_ring_buffer(struct drm_device *dev);
@@ -482,9 +474,9 @@ int intel_init_bsd2_ring_buffer(struct d
 int intel_init_blt_ring_buffer(struct drm_device *dev);
 int intel_init_vebox_ring_buffer(struct drm_device *dev);
 
-u64 intel_ring_get_active_head(struct intel_engine_cs *ring);
+u64 intel_ring_get_active_head(struct intel_engine_cs *engine);
 
-int init_workarounds_ring(struct intel_engine_cs *ring);
+int init_workarounds_ring(struct intel_engine_cs *engine);
 
 static inline u32 intel_ring_get_tail(struct intel_ringbuffer *ringbuf)
 {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_runtime_pm.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_runtime_pm.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_runtime_pm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_runtime_pm.c	2016-07-24 15:23:50.000000000 -0400
@@ -89,6 +89,10 @@ intel_display_power_domain_str(enum inte
 		return "TRANSCODER_C";
 	case POWER_DOMAIN_TRANSCODER_EDP:
 		return "TRANSCODER_EDP";
+	case POWER_DOMAIN_TRANSCODER_DSI_A:
+		return "TRANSCODER_DSI_A";
+	case POWER_DOMAIN_TRANSCODER_DSI_C:
+		return "TRANSCODER_DSI_C";
 	case POWER_DOMAIN_PORT_DDI_A_LANES:
 		return "PORT_DDI_A_LANES";
 	case POWER_DOMAIN_PORT_DDI_B_LANES:
@@ -393,11 +397,6 @@ static void hsw_set_power_well(struct dr
 	BIT(POWER_DOMAIN_MODESET) |			\
 	BIT(POWER_DOMAIN_AUX_A) |			\
 	BIT(POWER_DOMAIN_INIT))
-#define SKL_DISPLAY_ALWAYS_ON_POWER_DOMAINS (		\
-	(POWER_DOMAIN_MASK & ~(				\
-	SKL_DISPLAY_POWERWELL_2_POWER_DOMAINS |		\
-	SKL_DISPLAY_DC_OFF_POWER_DOMAINS)) |		\
-	BIT(POWER_DOMAIN_INIT))
 
 #define BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS (		\
 	BIT(POWER_DOMAIN_TRANSCODER_A) |		\
@@ -415,36 +414,21 @@ static void hsw_set_power_well(struct dr
 	BIT(POWER_DOMAIN_VGA) |				\
 	BIT(POWER_DOMAIN_GMBUS) |			\
 	BIT(POWER_DOMAIN_INIT))
-#define BXT_DISPLAY_POWERWELL_1_POWER_DOMAINS (		\
-	BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS |		\
-	BIT(POWER_DOMAIN_PIPE_A) |			\
-	BIT(POWER_DOMAIN_TRANSCODER_EDP) |		\
-	BIT(POWER_DOMAIN_PIPE_A_PANEL_FITTER) |		\
-	BIT(POWER_DOMAIN_PORT_DDI_A_LANES) |		\
-	BIT(POWER_DOMAIN_AUX_A) |			\
-	BIT(POWER_DOMAIN_PLLS) |			\
-	BIT(POWER_DOMAIN_INIT))
 #define BXT_DISPLAY_DC_OFF_POWER_DOMAINS (		\
 	BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS |		\
 	BIT(POWER_DOMAIN_MODESET) |			\
 	BIT(POWER_DOMAIN_AUX_A) |			\
 	BIT(POWER_DOMAIN_INIT))
-#define BXT_DISPLAY_ALWAYS_ON_POWER_DOMAINS (		\
-	(POWER_DOMAIN_MASK & ~(BXT_DISPLAY_POWERWELL_1_POWER_DOMAINS |	\
-	BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS)) |	\
-	BIT(POWER_DOMAIN_INIT))
 
 static void assert_can_enable_dc9(struct drm_i915_private *dev_priv)
 {
-	struct drm_device *dev = dev_priv->dev;
-
-	WARN(!IS_BROXTON(dev), "Platform doesn't support DC9.\n");
-	WARN((I915_READ(DC_STATE_EN) & DC_STATE_EN_DC9),
-		"DC9 already programmed to be enabled.\n");
-	WARN(I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5,
-		"DC5 still not disabled to enable DC9.\n");
-	WARN(I915_READ(HSW_PWR_WELL_DRIVER), "Power well on.\n");
-	WARN(intel_irqs_enabled(dev_priv), "Interrupts not disabled yet.\n");
+	WARN_ONCE((I915_READ(DC_STATE_EN) & DC_STATE_EN_DC9),
+		  "DC9 already programmed to be enabled.\n");
+	WARN_ONCE(I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5,
+		  "DC5 still not disabled to enable DC9.\n");
+	WARN_ONCE(I915_READ(HSW_PWR_WELL_DRIVER), "Power well on.\n");
+	WARN_ONCE(intel_irqs_enabled(dev_priv),
+		  "Interrupts not disabled yet.\n");
 
 	 /*
 	  * TODO: check for the following to verify the conditions to enter DC9
@@ -457,11 +441,10 @@ static void assert_can_enable_dc9(struct
 
 static void assert_can_disable_dc9(struct drm_i915_private *dev_priv)
 {
-	WARN(intel_irqs_enabled(dev_priv), "Interrupts not disabled yet.\n");
-	WARN(!(I915_READ(DC_STATE_EN) & DC_STATE_EN_DC9),
-		"DC9 already programmed to be disabled.\n");
-	WARN(I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5,
-		"DC5 still not disabled.\n");
+	WARN_ONCE(intel_irqs_enabled(dev_priv),
+		  "Interrupts not disabled yet.\n");
+	WARN_ONCE(I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5,
+		  "DC5 still not disabled.\n");
 
 	 /*
 	  * TODO: check for the following to verify DC9 state was indeed
@@ -472,24 +455,6 @@ static void assert_can_disable_dc9(struc
 	  */
 }
 
-static void gen9_set_dc_state_debugmask(struct drm_i915_private *dev_priv)
-{
-	uint32_t val, mask;
-
-	mask = DC_STATE_DEBUG_MASK_MEMORY_UP;
-
-	if (IS_BROXTON(dev_priv))
-		mask |= DC_STATE_DEBUG_MASK_CORES;
-
-	/* The below bit doesn't need to be cleared ever afterwards */
-	val = I915_READ(DC_STATE_DEBUG);
-	if ((val & mask) != mask) {
-		val |= mask;
-		I915_WRITE(DC_STATE_DEBUG, val);
-		POSTING_READ(DC_STATE_DEBUG);
-	}
-}
-
 static void gen9_write_dc_state(struct drm_i915_private *dev_priv,
 				u32 state)
 {
@@ -527,10 +492,9 @@ static void gen9_write_dc_state(struct d
 			      state, rewrites);
 }
 
-static void gen9_set_dc_state(struct drm_i915_private *dev_priv, uint32_t state)
+static u32 gen9_dc_mask(struct drm_i915_private *dev_priv)
 {
-	uint32_t val;
-	uint32_t mask;
+	u32 mask;
 
 	mask = DC_STATE_EN_UPTO_DC5;
 	if (IS_BROXTON(dev_priv))
@@ -538,14 +502,30 @@ static void gen9_set_dc_state(struct drm
 	else
 		mask |= DC_STATE_EN_UPTO_DC6;
 
-	WARN_ON_ONCE(state & ~mask);
+	return mask;
+}
 
-	if (i915.enable_dc == 0)
-		state = DC_STATE_DISABLE;
-	else if (i915.enable_dc == 1 && state > DC_STATE_EN_UPTO_DC5)
-		state = DC_STATE_EN_UPTO_DC5;
+void gen9_sanitize_dc_state(struct drm_i915_private *dev_priv)
+{
+	u32 val;
+
+	val = I915_READ(DC_STATE_EN) & gen9_dc_mask(dev_priv);
+
+	DRM_DEBUG_KMS("Resetting DC state tracking from %02x to %02x\n",
+		      dev_priv->csr.dc_state, val);
+	dev_priv->csr.dc_state = val;
+}
+
+static void gen9_set_dc_state(struct drm_i915_private *dev_priv, uint32_t state)
+{
+	uint32_t val;
+	uint32_t mask;
+
+	if (WARN_ON_ONCE(state & ~dev_priv->csr.allowed_dc_mask))
+		state &= dev_priv->csr.allowed_dc_mask;
 
 	val = I915_READ(DC_STATE_EN);
+	mask = gen9_dc_mask(dev_priv);
 	DRM_DEBUG_KMS("Setting DC state from %02x to %02x\n",
 		      val & mask, state);
 
@@ -590,13 +570,9 @@ static void assert_csr_loaded(struct drm
 
 static void assert_can_enable_dc5(struct drm_i915_private *dev_priv)
 {
-	struct drm_device *dev = dev_priv->dev;
 	bool pg2_enabled = intel_display_power_well_is_enabled(dev_priv,
 					SKL_DISP_PW_2);
 
-	WARN_ONCE(!IS_SKYLAKE(dev) && !IS_KABYLAKE(dev),
-		  "Platform doesn't support DC5.\n");
-	WARN_ONCE(!HAS_RUNTIME_PM(dev), "Runtime PM not enabled.\n");
 	WARN_ONCE(pg2_enabled, "PG2 not disabled to enable DC5.\n");
 
 	WARN_ONCE((I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5),
@@ -606,19 +582,7 @@ static void assert_can_enable_dc5(struct
 	assert_csr_loaded(dev_priv);
 }
 
-static void assert_can_disable_dc5(struct drm_i915_private *dev_priv)
-{
-	/*
-	 * During initialization, the firmware may not be loaded yet.
-	 * We still want to make sure that the DC enabling flag is cleared.
-	 */
-	if (dev_priv->power_domains.initializing)
-		return;
-
-	assert_rpm_wakelock_held(dev_priv);
-}
-
-static void gen9_enable_dc5(struct drm_i915_private *dev_priv)
+void gen9_enable_dc5(struct drm_i915_private *dev_priv)
 {
 	assert_can_enable_dc5(dev_priv);
 
@@ -629,11 +593,6 @@ static void gen9_enable_dc5(struct drm_i
 
 static void assert_can_enable_dc6(struct drm_i915_private *dev_priv)
 {
-	struct drm_device *dev = dev_priv->dev;
-
-	WARN_ONCE(!IS_SKYLAKE(dev) && !IS_KABYLAKE(dev),
-		  "Platform doesn't support DC6.\n");
-	WARN_ONCE(!HAS_RUNTIME_PM(dev), "Runtime PM not enabled.\n");
 	WARN_ONCE(I915_READ(UTIL_PIN_CTL) & UTIL_PIN_ENABLE,
 		  "Backlight is not disabled.\n");
 	WARN_ONCE((I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC6),
@@ -642,47 +601,60 @@ static void assert_can_enable_dc6(struct
 	assert_csr_loaded(dev_priv);
 }
 
-static void assert_can_disable_dc6(struct drm_i915_private *dev_priv)
+void skl_enable_dc6(struct drm_i915_private *dev_priv)
 {
-	/*
-	 * During initialization, the firmware may not be loaded yet.
-	 * We still want to make sure that the DC enabling flag is cleared.
-	 */
-	if (dev_priv->power_domains.initializing)
-		return;
+	assert_can_enable_dc6(dev_priv);
+
+	DRM_DEBUG_KMS("Enabling DC6\n");
+
+	gen9_set_dc_state(dev_priv, DC_STATE_EN_UPTO_DC6);
 
-	WARN_ONCE(!(I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC6),
-		  "DC6 already programmed to be disabled.\n");
 }
 
-static void gen9_disable_dc5_dc6(struct drm_i915_private *dev_priv)
+void skl_disable_dc6(struct drm_i915_private *dev_priv)
 {
-	assert_can_disable_dc5(dev_priv);
-
-	if ((IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) &&
-	    i915.enable_dc != 0 && i915.enable_dc != 1)
-		assert_can_disable_dc6(dev_priv);
+	DRM_DEBUG_KMS("Disabling DC6\n");
 
 	gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
 }
 
-void skl_enable_dc6(struct drm_i915_private *dev_priv)
+static void
+gen9_sanitize_power_well_requests(struct drm_i915_private *dev_priv,
+				  struct i915_power_well *power_well)
 {
-	assert_can_enable_dc6(dev_priv);
+	enum skl_disp_power_wells power_well_id = power_well->data;
+	u32 val;
+	u32 mask;
 
-	DRM_DEBUG_KMS("Enabling DC6\n");
+	mask = SKL_POWER_WELL_REQ(power_well_id);
 
-	gen9_set_dc_state(dev_priv, DC_STATE_EN_UPTO_DC6);
+	val = I915_READ(HSW_PWR_WELL_KVMR);
+	if (WARN_ONCE(val & mask, "Clearing unexpected KVMR request for %s\n",
+		      power_well->name))
+		I915_WRITE(HSW_PWR_WELL_KVMR, val & ~mask);
 
-}
+	val = I915_READ(HSW_PWR_WELL_BIOS);
+	val |= I915_READ(HSW_PWR_WELL_DEBUG);
 
-void skl_disable_dc6(struct drm_i915_private *dev_priv)
-{
-	assert_can_disable_dc6(dev_priv);
+	if (!(val & mask))
+		return;
 
-	DRM_DEBUG_KMS("Disabling DC6\n");
+	/*
+	 * DMC is known to force on the request bits for power well 1 on SKL
+	 * and BXT and the misc IO power well on SKL but we don't expect any
+	 * other request bits to be set, so WARN for those.
+	 */
+	if (power_well_id == SKL_DISP_PW_1 ||
+	    ((IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) &&
+	     power_well_id == SKL_DISP_PW_MISC_IO))
+		DRM_DEBUG_DRIVER("Clearing auxiliary requests for %s forced on "
+				 "by DMC\n", power_well->name);
+	else
+		WARN_ONCE(1, "Clearing unexpected auxiliary requests for %s\n",
+			  power_well->name);
 
-	gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
+	I915_WRITE(HSW_PWR_WELL_BIOS, val & ~mask);
+	I915_WRITE(HSW_PWR_WELL_DEBUG, val & ~mask);
 }
 
 static void skl_set_power_well(struct drm_i915_private *dev_priv,
@@ -739,10 +711,6 @@ static void skl_set_power_well(struct dr
 
 		if (!is_enabled) {
 			DRM_DEBUG_KMS("Enabling %s\n", power_well->name);
-			if (wait_for((I915_READ(HSW_PWR_WELL_DRIVER) &
-				state_mask), 1))
-				DRM_ERROR("%s enable timeout\n",
-					power_well->name);
 			check_fuse_status = true;
 		}
 	} else {
@@ -751,8 +719,16 @@ static void skl_set_power_well(struct dr
 			POSTING_READ(HSW_PWR_WELL_DRIVER);
 			DRM_DEBUG_KMS("Disabling %s\n", power_well->name);
 		}
+
+		if (IS_GEN9(dev_priv))
+			gen9_sanitize_power_well_requests(dev_priv, power_well);
 	}
 
+	if (wait_for(!!(I915_READ(HSW_PWR_WELL_DRIVER) & state_mask) == enable,
+		     1))
+		DRM_ERROR("%s %s timeout\n",
+			  power_well->name, enable ? "enable" : "disable");
+
 	if (check_fuse_status) {
 		if (power_well->data == SKL_DISP_PW_1) {
 			if (wait_for((I915_READ(SKL_FUSE_STATUS) &
@@ -833,32 +809,33 @@ static bool gen9_dc_off_power_well_enabl
 static void gen9_dc_off_power_well_enable(struct drm_i915_private *dev_priv,
 					  struct i915_power_well *power_well)
 {
-	gen9_disable_dc5_dc6(dev_priv);
+	gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
+
+	if (IS_BROXTON(dev_priv)) {
+		broxton_cdclk_verify_state(dev_priv);
+		broxton_ddi_phy_verify_state(dev_priv);
+	}
 }
 
 static void gen9_dc_off_power_well_disable(struct drm_i915_private *dev_priv,
 					   struct i915_power_well *power_well)
 {
-	if ((IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) &&
-	    i915.enable_dc != 0 && i915.enable_dc != 1)
+	if (!dev_priv->csr.dmc_payload)
+		return;
+
+	if (dev_priv->csr.allowed_dc_mask & DC_STATE_EN_UPTO_DC6)
 		skl_enable_dc6(dev_priv);
-	else
+	else if (dev_priv->csr.allowed_dc_mask & DC_STATE_EN_UPTO_DC5)
 		gen9_enable_dc5(dev_priv);
 }
 
 static void gen9_dc_off_power_well_sync_hw(struct drm_i915_private *dev_priv,
 					   struct i915_power_well *power_well)
 {
-	if (power_well->count > 0) {
-		gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
-	} else {
-		if ((IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) &&
-		    i915.enable_dc != 0 &&
-		    i915.enable_dc != 1)
-			gen9_set_dc_state(dev_priv, DC_STATE_EN_UPTO_DC6);
-		else
-			gen9_set_dc_state(dev_priv, DC_STATE_EN_UPTO_DC5);
-	}
+	if (power_well->count > 0)
+		gen9_dc_off_power_well_enable(dev_priv, power_well);
+	else
+		gen9_dc_off_power_well_disable(dev_priv, power_well);
 }
 
 static void i9xx_always_on_power_well_noop(struct drm_i915_private *dev_priv,
@@ -962,6 +939,17 @@ static bool vlv_power_well_enabled(struc
 	return enabled;
 }
 
+static void vlv_init_display_clock_gating(struct drm_i915_private *dev_priv)
+{
+	I915_WRITE(DSPCLK_GATE_D, VRHUNIT_CLOCK_GATE_DISABLE);
+
+	/*
+	 * Disable trickle feed and enable pnd deadline calculation
+	 */
+	I915_WRITE(MI_ARB_VLV, MI_ARB_DISPLAY_TRICKLE_FEED_DISABLE);
+	I915_WRITE(CBR1_VLV, 0);
+}
+
 static void vlv_display_power_well_init(struct drm_i915_private *dev_priv)
 {
 	enum pipe pipe;
@@ -984,6 +972,8 @@ static void vlv_display_power_well_init(
 		I915_WRITE(DPLL(pipe), val);
 	}
 
+	vlv_init_display_clock_gating(dev_priv);
+
 	spin_lock_irq(&dev_priv->irq_lock);
 	valleyview_enable_display_irqs(dev_priv);
 	spin_unlock_irq(&dev_priv->irq_lock);
@@ -1622,34 +1612,56 @@ void intel_display_power_put(struct drm_
 	intel_runtime_pm_put(dev_priv);
 }
 
-#define HSW_ALWAYS_ON_POWER_DOMAINS (			\
-	BIT(POWER_DOMAIN_PIPE_A) |			\
-	BIT(POWER_DOMAIN_TRANSCODER_EDP) |		\
-	BIT(POWER_DOMAIN_PORT_DDI_A_LANES) |		\
+#define HSW_DISPLAY_POWER_DOMAINS (			\
+	BIT(POWER_DOMAIN_PIPE_B) |			\
+	BIT(POWER_DOMAIN_PIPE_C) |			\
+	BIT(POWER_DOMAIN_PIPE_A_PANEL_FITTER) |		\
+	BIT(POWER_DOMAIN_PIPE_B_PANEL_FITTER) |		\
+	BIT(POWER_DOMAIN_PIPE_C_PANEL_FITTER) |		\
+	BIT(POWER_DOMAIN_TRANSCODER_A) |		\
+	BIT(POWER_DOMAIN_TRANSCODER_B) |		\
+	BIT(POWER_DOMAIN_TRANSCODER_C) |		\
 	BIT(POWER_DOMAIN_PORT_DDI_B_LANES) |		\
 	BIT(POWER_DOMAIN_PORT_DDI_C_LANES) |		\
 	BIT(POWER_DOMAIN_PORT_DDI_D_LANES) |		\
-	BIT(POWER_DOMAIN_PORT_CRT) |			\
-	BIT(POWER_DOMAIN_PLLS) |			\
-	BIT(POWER_DOMAIN_AUX_A) |			\
-	BIT(POWER_DOMAIN_AUX_B) |			\
-	BIT(POWER_DOMAIN_AUX_C) |			\
-	BIT(POWER_DOMAIN_AUX_D) |			\
-	BIT(POWER_DOMAIN_GMBUS) |			\
-	BIT(POWER_DOMAIN_INIT))
-#define HSW_DISPLAY_POWER_DOMAINS (				\
-	(POWER_DOMAIN_MASK & ~HSW_ALWAYS_ON_POWER_DOMAINS) |	\
+	BIT(POWER_DOMAIN_PORT_CRT) | /* DDI E */	\
+	BIT(POWER_DOMAIN_VGA) |				\
+	BIT(POWER_DOMAIN_AUDIO) |			\
 	BIT(POWER_DOMAIN_INIT))
 
-#define BDW_ALWAYS_ON_POWER_DOMAINS (			\
-	HSW_ALWAYS_ON_POWER_DOMAINS |			\
-	BIT(POWER_DOMAIN_PIPE_A_PANEL_FITTER))
-#define BDW_DISPLAY_POWER_DOMAINS (				\
-	(POWER_DOMAIN_MASK & ~BDW_ALWAYS_ON_POWER_DOMAINS) |	\
+#define BDW_DISPLAY_POWER_DOMAINS (			\
+	BIT(POWER_DOMAIN_PIPE_B) |			\
+	BIT(POWER_DOMAIN_PIPE_C) |			\
+	BIT(POWER_DOMAIN_PIPE_B_PANEL_FITTER) |		\
+	BIT(POWER_DOMAIN_PIPE_C_PANEL_FITTER) |		\
+	BIT(POWER_DOMAIN_TRANSCODER_A) |		\
+	BIT(POWER_DOMAIN_TRANSCODER_B) |		\
+	BIT(POWER_DOMAIN_TRANSCODER_C) |		\
+	BIT(POWER_DOMAIN_PORT_DDI_B_LANES) |		\
+	BIT(POWER_DOMAIN_PORT_DDI_C_LANES) |		\
+	BIT(POWER_DOMAIN_PORT_DDI_D_LANES) |		\
+	BIT(POWER_DOMAIN_PORT_CRT) | /* DDI E */	\
+	BIT(POWER_DOMAIN_VGA) |				\
+	BIT(POWER_DOMAIN_AUDIO) |			\
 	BIT(POWER_DOMAIN_INIT))
 
-#define VLV_ALWAYS_ON_POWER_DOMAINS	BIT(POWER_DOMAIN_INIT)
-#define VLV_DISPLAY_POWER_DOMAINS	POWER_DOMAIN_MASK
+#define VLV_DISPLAY_POWER_DOMAINS (		\
+	BIT(POWER_DOMAIN_PIPE_A) |		\
+	BIT(POWER_DOMAIN_PIPE_B) |		\
+	BIT(POWER_DOMAIN_PIPE_A_PANEL_FITTER) |	\
+	BIT(POWER_DOMAIN_PIPE_B_PANEL_FITTER) |	\
+	BIT(POWER_DOMAIN_TRANSCODER_A) |	\
+	BIT(POWER_DOMAIN_TRANSCODER_B) |	\
+	BIT(POWER_DOMAIN_PORT_DDI_B_LANES) |	\
+	BIT(POWER_DOMAIN_PORT_DDI_C_LANES) |	\
+	BIT(POWER_DOMAIN_PORT_DSI) |		\
+	BIT(POWER_DOMAIN_PORT_CRT) |		\
+	BIT(POWER_DOMAIN_VGA) |			\
+	BIT(POWER_DOMAIN_AUDIO) |		\
+	BIT(POWER_DOMAIN_AUX_B) |		\
+	BIT(POWER_DOMAIN_AUX_C) |		\
+	BIT(POWER_DOMAIN_GMBUS) |		\
+	BIT(POWER_DOMAIN_INIT))
 
 #define VLV_DPIO_CMN_BC_POWER_DOMAINS (		\
 	BIT(POWER_DOMAIN_PORT_DDI_B_LANES) |	\
@@ -1679,6 +1691,28 @@ void intel_display_power_put(struct drm_
 	BIT(POWER_DOMAIN_AUX_C) |		\
 	BIT(POWER_DOMAIN_INIT))
 
+#define CHV_DISPLAY_POWER_DOMAINS (		\
+	BIT(POWER_DOMAIN_PIPE_A) |		\
+	BIT(POWER_DOMAIN_PIPE_B) |		\
+	BIT(POWER_DOMAIN_PIPE_C) |		\
+	BIT(POWER_DOMAIN_PIPE_A_PANEL_FITTER) |	\
+	BIT(POWER_DOMAIN_PIPE_B_PANEL_FITTER) |	\
+	BIT(POWER_DOMAIN_PIPE_C_PANEL_FITTER) |	\
+	BIT(POWER_DOMAIN_TRANSCODER_A) |	\
+	BIT(POWER_DOMAIN_TRANSCODER_B) |	\
+	BIT(POWER_DOMAIN_TRANSCODER_C) |	\
+	BIT(POWER_DOMAIN_PORT_DDI_B_LANES) |	\
+	BIT(POWER_DOMAIN_PORT_DDI_C_LANES) |	\
+	BIT(POWER_DOMAIN_PORT_DDI_D_LANES) |	\
+	BIT(POWER_DOMAIN_PORT_DSI) |		\
+	BIT(POWER_DOMAIN_VGA) |			\
+	BIT(POWER_DOMAIN_AUDIO) |		\
+	BIT(POWER_DOMAIN_AUX_B) |		\
+	BIT(POWER_DOMAIN_AUX_C) |		\
+	BIT(POWER_DOMAIN_AUX_D) |		\
+	BIT(POWER_DOMAIN_GMBUS) |		\
+	BIT(POWER_DOMAIN_INIT))
+
 #define CHV_DPIO_CMN_BC_POWER_DOMAINS (		\
 	BIT(POWER_DOMAIN_PORT_DDI_B_LANES) |	\
 	BIT(POWER_DOMAIN_PORT_DDI_C_LANES) |	\
@@ -1746,7 +1780,7 @@ static struct i915_power_well hsw_power_
 	{
 		.name = "always-on",
 		.always_on = 1,
-		.domains = HSW_ALWAYS_ON_POWER_DOMAINS,
+		.domains = POWER_DOMAIN_MASK,
 		.ops = &i9xx_always_on_power_well_ops,
 	},
 	{
@@ -1760,7 +1794,7 @@ static struct i915_power_well bdw_power_
 	{
 		.name = "always-on",
 		.always_on = 1,
-		.domains = BDW_ALWAYS_ON_POWER_DOMAINS,
+		.domains = POWER_DOMAIN_MASK,
 		.ops = &i9xx_always_on_power_well_ops,
 	},
 	{
@@ -1795,7 +1829,7 @@ static struct i915_power_well vlv_power_
 	{
 		.name = "always-on",
 		.always_on = 1,
-		.domains = VLV_ALWAYS_ON_POWER_DOMAINS,
+		.domains = POWER_DOMAIN_MASK,
 		.ops = &i9xx_always_on_power_well_ops,
 		.data = PUNIT_POWER_WELL_ALWAYS_ON,
 	},
@@ -1853,7 +1887,7 @@ static struct i915_power_well chv_power_
 	{
 		.name = "always-on",
 		.always_on = 1,
-		.domains = VLV_ALWAYS_ON_POWER_DOMAINS,
+		.domains = POWER_DOMAIN_MASK,
 		.ops = &i9xx_always_on_power_well_ops,
 	},
 	{
@@ -1863,7 +1897,7 @@ static struct i915_power_well chv_power_
 		 * power wells don't actually exist. Pipe A power well is
 		 * required for any pipe to work.
 		 */
-		.domains = VLV_DISPLAY_POWER_DOMAINS,
+		.domains = CHV_DISPLAY_POWER_DOMAINS,
 		.data = PIPE_A,
 		.ops = &chv_pipe_power_well_ops,
 	},
@@ -1897,7 +1931,7 @@ static struct i915_power_well skl_power_
 	{
 		.name = "always-on",
 		.always_on = 1,
-		.domains = SKL_DISPLAY_ALWAYS_ON_POWER_DOMAINS,
+		.domains = POWER_DOMAIN_MASK,
 		.ops = &i9xx_always_on_power_well_ops,
 		.data = SKL_DISP_PW_ALWAYS_ON,
 	},
@@ -1953,44 +1987,16 @@ static struct i915_power_well skl_power_
 	},
 };
 
-void skl_pw1_misc_io_init(struct drm_i915_private *dev_priv)
-{
-	struct i915_power_well *well;
-
-	if (!(IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)))
-		return;
-
-	well = lookup_power_well(dev_priv, SKL_DISP_PW_1);
-	intel_power_well_enable(dev_priv, well);
-
-	well = lookup_power_well(dev_priv, SKL_DISP_PW_MISC_IO);
-	intel_power_well_enable(dev_priv, well);
-}
-
-void skl_pw1_misc_io_fini(struct drm_i915_private *dev_priv)
-{
-	struct i915_power_well *well;
-
-	if (!(IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)))
-		return;
-
-	well = lookup_power_well(dev_priv, SKL_DISP_PW_1);
-	intel_power_well_disable(dev_priv, well);
-
-	well = lookup_power_well(dev_priv, SKL_DISP_PW_MISC_IO);
-	intel_power_well_disable(dev_priv, well);
-}
-
 static struct i915_power_well bxt_power_wells[] = {
 	{
 		.name = "always-on",
 		.always_on = 1,
-		.domains = BXT_DISPLAY_ALWAYS_ON_POWER_DOMAINS,
+		.domains = POWER_DOMAIN_MASK,
 		.ops = &i9xx_always_on_power_well_ops,
 	},
 	{
 		.name = "power well 1",
-		.domains = BXT_DISPLAY_POWERWELL_1_POWER_DOMAINS,
+		.domains = 0,
 		.ops = &skl_power_well_ops,
 		.data = SKL_DISP_PW_1,
 	},
@@ -2015,12 +2021,56 @@ sanitize_disable_power_well_option(const
 	if (disable_power_well >= 0)
 		return !!disable_power_well;
 
-	if (IS_BROXTON(dev_priv)) {
-		DRM_DEBUG_KMS("Disabling display power well support\n");
-		return 0;
+	return 1;
+}
+
+static uint32_t get_allowed_dc_mask(const struct drm_i915_private *dev_priv,
+				    int enable_dc)
+{
+	uint32_t mask;
+	int requested_dc;
+	int max_dc;
+
+	if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
+		max_dc = 2;
+		mask = 0;
+	} else if (IS_BROXTON(dev_priv)) {
+		max_dc = 1;
+		/*
+		 * DC9 has a separate HW flow from the rest of the DC states,
+		 * not depending on the DMC firmware. It's needed by system
+		 * suspend/resume, so allow it unconditionally.
+		 */
+		mask = DC_STATE_EN_DC9;
+	} else {
+		max_dc = 0;
+		mask = 0;
 	}
 
-	return 1;
+	if (!i915.disable_power_well)
+		max_dc = 0;
+
+	if (enable_dc >= 0 && enable_dc <= max_dc) {
+		requested_dc = enable_dc;
+	} else if (enable_dc == -1) {
+		requested_dc = max_dc;
+	} else if (enable_dc > max_dc && enable_dc <= 2) {
+		DRM_DEBUG_KMS("Adjusting requested max DC state (%d->%d)\n",
+			      enable_dc, max_dc);
+		requested_dc = max_dc;
+	} else {
+		DRM_ERROR("Unexpected value for enable_dc (%d)\n", enable_dc);
+		requested_dc = max_dc;
+	}
+
+	if (requested_dc > 1)
+		mask |= DC_STATE_EN_UPTO_DC6;
+	if (requested_dc > 0)
+		mask |= DC_STATE_EN_UPTO_DC5;
+
+	DRM_DEBUG_KMS("Allowed DC state mask %02x\n", mask);
+
+	return mask;
 }
 
 #define set_power_wells(power_domains, __power_wells) ({		\
@@ -2041,6 +2091,8 @@ int intel_power_domains_init(struct drm_
 
 	i915.disable_power_well = sanitize_disable_power_well_option(dev_priv,
 						     i915.disable_power_well);
+	dev_priv->csr.allowed_dc_mask = get_allowed_dc_mask(dev_priv,
+							    i915.enable_dc);
 
 	BUILD_BUG_ON(POWER_DOMAIN_NUM > 31);
 
@@ -2050,17 +2102,17 @@ int intel_power_domains_init(struct drm_
 	 * The enabling order will be from lower to higher indexed wells,
 	 * the disabling order is reversed.
 	 */
-	if (IS_HASWELL(dev_priv->dev)) {
+	if (IS_HASWELL(dev_priv)) {
 		set_power_wells(power_domains, hsw_power_wells);
-	} else if (IS_BROADWELL(dev_priv->dev)) {
+	} else if (IS_BROADWELL(dev_priv)) {
 		set_power_wells(power_domains, bdw_power_wells);
-	} else if (IS_SKYLAKE(dev_priv->dev) || IS_KABYLAKE(dev_priv->dev)) {
+	} else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
 		set_power_wells(power_domains, skl_power_wells);
-	} else if (IS_BROXTON(dev_priv->dev)) {
+	} else if (IS_BROXTON(dev_priv)) {
 		set_power_wells(power_domains, bxt_power_wells);
-	} else if (IS_CHERRYVIEW(dev_priv->dev)) {
+	} else if (IS_CHERRYVIEW(dev_priv)) {
 		set_power_wells(power_domains, chv_power_wells);
-	} else if (IS_VALLEYVIEW(dev_priv->dev)) {
+	} else if (IS_VALLEYVIEW(dev_priv)) {
 		set_power_wells(power_domains, vlv_power_wells);
 	} else {
 		set_power_wells(power_domains, i9xx_always_on_power_well);
@@ -2120,9 +2172,10 @@ static void intel_power_domains_sync_hw(
 }
 
 static void skl_display_core_init(struct drm_i915_private *dev_priv,
-				  bool resume)
+				   bool resume)
 {
 	struct i915_power_domains *power_domains = &dev_priv->power_domains;
+	struct i915_power_well *well;
 	uint32_t val;
 
 	gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
@@ -2133,7 +2186,13 @@ static void skl_display_core_init(struct
 
 	/* enable PG1 and Misc I/O */
 	mutex_lock(&power_domains->lock);
-	skl_pw1_misc_io_init(dev_priv);
+
+	well = lookup_power_well(dev_priv, SKL_DISP_PW_1);
+	intel_power_well_enable(dev_priv, well);
+
+	well = lookup_power_well(dev_priv, SKL_DISP_PW_MISC_IO);
+	intel_power_well_enable(dev_priv, well);
+
 	mutex_unlock(&power_domains->lock);
 
 	if (!resume)
@@ -2141,13 +2200,14 @@ static void skl_display_core_init(struct
 
 	skl_init_cdclk(dev_priv);
 
-	if (dev_priv->csr.dmc_payload && intel_csr_load_program(dev_priv))
-		gen9_set_dc_state_debugmask(dev_priv);
+	if (dev_priv->csr.dmc_payload)
+		intel_csr_load_program(dev_priv);
 }
 
 static void skl_display_core_uninit(struct drm_i915_private *dev_priv)
 {
 	struct i915_power_domains *power_domains = &dev_priv->power_domains;
+	struct i915_power_well *well;
 
 	gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
 
@@ -2155,8 +2215,73 @@ static void skl_display_core_uninit(stru
 
 	/* The spec doesn't call for removing the reset handshake flag */
 	/* disable PG1 and Misc I/O */
+
 	mutex_lock(&power_domains->lock);
-	skl_pw1_misc_io_fini(dev_priv);
+
+	well = lookup_power_well(dev_priv, SKL_DISP_PW_MISC_IO);
+	intel_power_well_disable(dev_priv, well);
+
+	well = lookup_power_well(dev_priv, SKL_DISP_PW_1);
+	intel_power_well_disable(dev_priv, well);
+
+	mutex_unlock(&power_domains->lock);
+}
+
+void bxt_display_core_init(struct drm_i915_private *dev_priv,
+			   bool resume)
+{
+	struct i915_power_domains *power_domains = &dev_priv->power_domains;
+	struct i915_power_well *well;
+	uint32_t val;
+
+	gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
+
+	/*
+	 * NDE_RSTWRN_OPT RST PCH Handshake En must always be 0b on BXT
+	 * or else the reset will hang because there is no PCH to respond.
+	 * Move the handshake programming to initialization sequence.
+	 * Previously was left up to BIOS.
+	 */
+	val = I915_READ(HSW_NDE_RSTWRN_OPT);
+	val &= ~RESET_PCH_HANDSHAKE_ENABLE;
+	I915_WRITE(HSW_NDE_RSTWRN_OPT, val);
+
+	/* Enable PG1 */
+	mutex_lock(&power_domains->lock);
+
+	well = lookup_power_well(dev_priv, SKL_DISP_PW_1);
+	intel_power_well_enable(dev_priv, well);
+
+	mutex_unlock(&power_domains->lock);
+
+	broxton_init_cdclk(dev_priv);
+	broxton_ddi_phy_init(dev_priv);
+
+	broxton_cdclk_verify_state(dev_priv);
+	broxton_ddi_phy_verify_state(dev_priv);
+
+	if (resume && dev_priv->csr.dmc_payload)
+		intel_csr_load_program(dev_priv);
+}
+
+void bxt_display_core_uninit(struct drm_i915_private *dev_priv)
+{
+	struct i915_power_domains *power_domains = &dev_priv->power_domains;
+	struct i915_power_well *well;
+
+	gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
+
+	broxton_ddi_phy_uninit(dev_priv);
+	broxton_uninit_cdclk(dev_priv);
+
+	/* The spec doesn't call for removing the reset handshake flag */
+
+	/* Disable PG1 */
+	mutex_lock(&power_domains->lock);
+
+	well = lookup_power_well(dev_priv, SKL_DISP_PW_1);
+	intel_power_well_disable(dev_priv, well);
+
 	mutex_unlock(&power_domains->lock);
 }
 
@@ -2291,6 +2416,8 @@ void intel_power_domains_init_hw(struct
 
 	if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
 		skl_display_core_init(dev_priv, resume);
+	} else if (IS_BROXTON(dev)) {
+		bxt_display_core_init(dev_priv, resume);
 	} else if (IS_CHERRYVIEW(dev)) {
 		mutex_lock(&power_domains->lock);
 		chv_phy_control_init(dev_priv);
@@ -2328,6 +2455,8 @@ void intel_power_domains_suspend(struct
 
 	if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
 		skl_display_core_uninit(dev_priv);
+	else if (IS_BROXTON(dev_priv))
+		bxt_display_core_uninit(dev_priv);
 }
 
 /**
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_sdvo.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_sdvo.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_sdvo.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_sdvo.c	2016-07-24 15:23:50.000000000 -0400
@@ -1398,12 +1398,10 @@ static void intel_sdvo_get_config(struct
 	}
 
 	dotclock = pipe_config->port_clock;
+
 	if (pipe_config->pixel_multiplier)
 		dotclock /= pipe_config->pixel_multiplier;
 
-	if (HAS_PCH_SPLIT(dev))
-		ironlake_check_encoder_dotclock(pipe_config, dotclock);
-
 	pipe_config->base.adjusted_mode.crtc_clock = dotclock;
 
 	/* Cross check the port pixel multiplier with the sdvo encoder state. */
@@ -2262,9 +2260,9 @@ intel_sdvo_select_ddc_bus(struct drm_i91
 	struct sdvo_device_mapping *mapping;
 
 	if (sdvo->port == PORT_B)
-		mapping = &(dev_priv->sdvo_mappings[0]);
+		mapping = &dev_priv->vbt.sdvo_mappings[0];
 	else
-		mapping = &(dev_priv->sdvo_mappings[1]);
+		mapping = &dev_priv->vbt.sdvo_mappings[1];
 
 	if (mapping->initialized)
 		sdvo->ddc_bus = 1 << ((mapping->ddc_pin & 0xf0) >> 4);
@@ -2280,9 +2278,9 @@ intel_sdvo_select_i2c_bus(struct drm_i91
 	u8 pin;
 
 	if (sdvo->port == PORT_B)
-		mapping = &dev_priv->sdvo_mappings[0];
+		mapping = &dev_priv->vbt.sdvo_mappings[0];
 	else
-		mapping = &dev_priv->sdvo_mappings[1];
+		mapping = &dev_priv->vbt.sdvo_mappings[1];
 
 	if (mapping->initialized &&
 	    intel_gmbus_is_valid_pin(dev_priv, mapping->i2c_pin))
@@ -2318,11 +2316,11 @@ intel_sdvo_get_slave_addr(struct drm_dev
 	struct sdvo_device_mapping *my_mapping, *other_mapping;
 
 	if (sdvo->port == PORT_B) {
-		my_mapping = &dev_priv->sdvo_mappings[0];
-		other_mapping = &dev_priv->sdvo_mappings[1];
+		my_mapping = &dev_priv->vbt.sdvo_mappings[0];
+		other_mapping = &dev_priv->vbt.sdvo_mappings[1];
 	} else {
-		my_mapping = &dev_priv->sdvo_mappings[1];
-		other_mapping = &dev_priv->sdvo_mappings[0];
+		my_mapping = &dev_priv->vbt.sdvo_mappings[1];
+		other_mapping = &dev_priv->vbt.sdvo_mappings[0];
 	}
 
 	/* If the BIOS described our SDVO device, take advantage of it. */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_sprite.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_sprite.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_sprite.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_sprite.c	2016-07-24 15:23:50.000000000 -0400
@@ -193,7 +193,7 @@ skl_update_plane(struct drm_plane *drm_p
 	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
 	u32 surf_addr;
 	u32 tile_height, plane_offset, plane_size;
-	unsigned int rotation;
+	unsigned int rotation = plane_state->base.rotation;
 	int x_offset, y_offset;
 	int crtc_x = plane_state->dst.x1;
 	int crtc_y = plane_state->dst.y1;
@@ -213,7 +213,6 @@ skl_update_plane(struct drm_plane *drm_p
 	plane_ctl |= skl_plane_ctl_format(fb->pixel_format);
 	plane_ctl |= skl_plane_ctl_tiling(fb->modifier[0]);
 
-	rotation = plane_state->base.rotation;
 	plane_ctl |= skl_plane_ctl_rotation(rotation);
 
 	stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
@@ -351,6 +350,7 @@ vlv_update_plane(struct drm_plane *dplan
 	int plane = intel_plane->plane;
 	u32 sprctl;
 	u32 sprsurf_offset, linear_offset;
+	unsigned int rotation = dplane->state->rotation;
 	int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
 	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
 	int crtc_x = plane_state->dst.x1;
@@ -423,12 +423,11 @@ vlv_update_plane(struct drm_plane *dplan
 	crtc_h--;
 
 	linear_offset = y * fb->pitches[0] + x * cpp;
-	sprsurf_offset = intel_compute_tile_offset(dev_priv, &x, &y,
-						   fb->modifier[0], cpp,
-						   fb->pitches[0]);
+	sprsurf_offset = intel_compute_tile_offset(&x, &y, fb, 0,
+						   fb->pitches[0], rotation);
 	linear_offset -= sprsurf_offset;
 
-	if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) {
+	if (rotation == BIT(DRM_ROTATE_180)) {
 		sprctl |= SP_ROTATE_180;
 
 		x += src_w;
@@ -493,6 +492,7 @@ ivb_update_plane(struct drm_plane *plane
 	enum pipe pipe = intel_plane->pipe;
 	u32 sprctl, sprscale = 0;
 	u32 sprsurf_offset, linear_offset;
+	unsigned int rotation = plane_state->base.rotation;
 	int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
 	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
 	int crtc_x = plane_state->dst.x1;
@@ -556,12 +556,11 @@ ivb_update_plane(struct drm_plane *plane
 		sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
 
 	linear_offset = y * fb->pitches[0] + x * cpp;
-	sprsurf_offset = intel_compute_tile_offset(dev_priv, &x, &y,
-						   fb->modifier[0], cpp,
-						   fb->pitches[0]);
+	sprsurf_offset = intel_compute_tile_offset(&x, &y, fb, 0,
+						   fb->pitches[0], rotation);
 	linear_offset -= sprsurf_offset;
 
-	if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) {
+	if (rotation == BIT(DRM_ROTATE_180)) {
 		sprctl |= SPRITE_ROTATE_180;
 
 		/* HSW and BDW does this automagically in hardware */
@@ -634,6 +633,7 @@ ilk_update_plane(struct drm_plane *plane
 	int pipe = intel_plane->pipe;
 	u32 dvscntr, dvsscale;
 	u32 dvssurf_offset, linear_offset;
+	unsigned int rotation = plane_state->base.rotation;
 	int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
 	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
 	int crtc_x = plane_state->dst.x1;
@@ -693,12 +693,11 @@ ilk_update_plane(struct drm_plane *plane
 		dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
 
 	linear_offset = y * fb->pitches[0] + x * cpp;
-	dvssurf_offset = intel_compute_tile_offset(dev_priv, &x, &y,
-						   fb->modifier[0], cpp,
-						   fb->pitches[0]);
+	dvssurf_offset = intel_compute_tile_offset(&x, &y, fb, 0,
+						   fb->pitches[0], rotation);
 	linear_offset -= dvssurf_offset;
 
-	if (plane_state->base.rotation == BIT(DRM_ROTATE_180)) {
+	if (rotation == BIT(DRM_ROTATE_180)) {
 		dvscntr |= DVS_ROTATE_180;
 
 		x += src_w;
@@ -1026,8 +1025,8 @@ static uint32_t skl_plane_formats[] = {
 int
 intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
 {
-	struct intel_plane *intel_plane;
-	struct intel_plane_state *state;
+	struct intel_plane *intel_plane = NULL;
+	struct intel_plane_state *state = NULL;
 	unsigned long possible_crtcs;
 	const uint32_t *plane_formats;
 	int num_plane_formats;
@@ -1037,13 +1036,15 @@ intel_plane_init(struct drm_device *dev,
 		return -ENODEV;
 
 	intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL);
-	if (!intel_plane)
-		return -ENOMEM;
+	if (!intel_plane) {
+		ret = -ENOMEM;
+		goto fail;
+	}
 
 	state = intel_create_plane_state(&intel_plane->base);
 	if (!state) {
-		kfree(intel_plane);
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto fail;
 	}
 	intel_plane->base.state = &state->base;
 
@@ -1098,28 +1099,34 @@ intel_plane_init(struct drm_device *dev,
 		num_plane_formats = ARRAY_SIZE(skl_plane_formats);
 		break;
 	default:
-		kfree(intel_plane);
-		return -ENODEV;
+		MISSING_CASE(INTEL_INFO(dev)->gen);
+		ret = -ENODEV;
+		goto fail;
 	}
 
 	intel_plane->pipe = pipe;
 	intel_plane->plane = plane;
 	intel_plane->frontbuffer_bit = INTEL_FRONTBUFFER_SPRITE(pipe, plane);
 	intel_plane->check_plane = intel_check_sprite_plane;
+
 	possible_crtcs = (1 << pipe);
+
 	ret = drm_universal_plane_init(dev, &intel_plane->base, possible_crtcs,
 				       &intel_plane_funcs,
 				       plane_formats, num_plane_formats,
 				       DRM_PLANE_TYPE_OVERLAY, NULL);
-	if (ret) {
-		kfree(intel_plane);
-		goto out;
-	}
+	if (ret)
+		goto fail;
 
 	intel_create_rotation_property(dev, intel_plane);
 
 	drm_plane_helper_add(&intel_plane->base, &intel_plane_helper_funcs);
 
-out:
+	return 0;
+
+fail:
+	kfree(state);
+	kfree(intel_plane);
+
 	return ret;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_tv.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_tv.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_tv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_tv.c	2016-07-24 15:23:50.000000000 -0400
@@ -326,24 +326,12 @@ static const struct color_conversion sdt
 	.rv = 0x0100, .gv = 0x03ad, .bv = 0x074d, .av = 0x0200,
 };
 
-static const struct color_conversion sdtv_csc_rgb = {
-	.ry = 0x0000, .gy = 0x0f00, .by = 0x0000, .ay = 0x0166,
-	.ru = 0x0000, .gu = 0x0000, .bu = 0x0f00, .au = 0x0166,
-	.rv = 0x0f00, .gv = 0x0000, .bv = 0x0000, .av = 0x0166,
-};
-
 static const struct color_conversion hdtv_csc_yprpb = {
 	.ry = 0x05b3, .gy = 0x016e, .by = 0x0728, .ay = 0x0145,
 	.ru = 0x07d5, .gu = 0x038b, .bu = 0x0100, .au = 0x0200,
 	.rv = 0x0100, .gv = 0x03d1, .bv = 0x06bc, .av = 0x0200,
 };
 
-static const struct color_conversion hdtv_csc_rgb = {
-	.ry = 0x0000, .gy = 0x0f00, .by = 0x0000, .ay = 0x0166,
-	.ru = 0x0000, .gu = 0x0000, .bu = 0x0f00, .au = 0x0166,
-	.rv = 0x0f00, .gv = 0x0000, .bv = 0x0000, .av = 0x0166,
-};
-
 static const struct video_levels component_levels = {
 	.blank = 279, .black = 279, .burst = 0,
 };
@@ -1531,47 +1519,6 @@ static const struct drm_encoder_funcs in
 	.destroy = intel_encoder_destroy,
 };
 
-/*
- * Enumerate the child dev array parsed from VBT to check whether
- * the integrated TV is present.
- * If it is present, return 1.
- * If it is not present, return false.
- * If no child dev is parsed from VBT, it assumes that the TV is present.
- */
-static int tv_is_present_in_vbt(struct drm_device *dev)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	union child_device_config *p_child;
-	int i, ret;
-
-	if (!dev_priv->vbt.child_dev_num)
-		return 1;
-
-	ret = 0;
-	for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
-		p_child = dev_priv->vbt.child_dev + i;
-		/*
-		 * If the device type is not TV, continue.
-		 */
-		switch (p_child->old.device_type) {
-		case DEVICE_TYPE_INT_TV:
-		case DEVICE_TYPE_TV:
-		case DEVICE_TYPE_TV_SVIDEO_COMPOSITE:
-			break;
-		default:
-			continue;
-		}
-		/* Only when the addin_offset is non-zero, it is regarded
-		 * as present.
-		 */
-		if (p_child->old.addin_offset) {
-			ret = 1;
-			break;
-		}
-	}
-	return ret;
-}
-
 void
 intel_tv_init(struct drm_device *dev)
 {
@@ -1587,13 +1534,10 @@ intel_tv_init(struct drm_device *dev)
 	if ((I915_READ(TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED)
 		return;
 
-	if (!tv_is_present_in_vbt(dev)) {
+	if (!intel_bios_is_tv_present(dev_priv)) {
 		DRM_DEBUG_KMS("Integrated TV is not present.\n");
 		return;
 	}
-	/* Even if we have an encoder we may not have a connector */
-	if (!dev_priv->vbt.int_tv_support)
-		return;
 
 	/*
 	 * Sanity check the TV output by checking to see if the
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_uncore.c linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_uncore.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_uncore.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_uncore.c	2016-07-24 15:23:50.000000000 -0400
@@ -60,7 +60,11 @@ fw_domain_reset(const struct intel_uncor
 static inline void
 fw_domain_arm_timer(struct intel_uncore_forcewake_domain *d)
 {
-	mod_timer_pinned(&d->timer, jiffies + 1);
+	d->wake_count++;
+	hrtimer_start_range_ns(&d->timer,
+			       ktime_set(0, NSEC_PER_MSEC),
+			       NSEC_PER_MSEC,
+			       HRTIMER_MODE_REL);
 }
 
 static inline void
@@ -107,22 +111,22 @@ static void
 fw_domains_get(struct drm_i915_private *dev_priv, enum forcewake_domains fw_domains)
 {
 	struct intel_uncore_forcewake_domain *d;
-	enum forcewake_domain_id id;
 
-	for_each_fw_domain_mask(d, fw_domains, dev_priv, id) {
+	for_each_fw_domain_masked(d, fw_domains, dev_priv) {
 		fw_domain_wait_ack_clear(d);
 		fw_domain_get(d);
-		fw_domain_wait_ack(d);
 	}
+
+	for_each_fw_domain_masked(d, fw_domains, dev_priv)
+		fw_domain_wait_ack(d);
 }
 
 static void
 fw_domains_put(struct drm_i915_private *dev_priv, enum forcewake_domains fw_domains)
 {
 	struct intel_uncore_forcewake_domain *d;
-	enum forcewake_domain_id id;
 
-	for_each_fw_domain_mask(d, fw_domains, dev_priv, id) {
+	for_each_fw_domain_masked(d, fw_domains, dev_priv) {
 		fw_domain_put(d);
 		fw_domain_posting_read(d);
 	}
@@ -132,10 +136,9 @@ static void
 fw_domains_posting_read(struct drm_i915_private *dev_priv)
 {
 	struct intel_uncore_forcewake_domain *d;
-	enum forcewake_domain_id id;
 
 	/* No need to do for all, just do for first found */
-	for_each_fw_domain(d, dev_priv, id) {
+	for_each_fw_domain(d, dev_priv) {
 		fw_domain_posting_read(d);
 		break;
 	}
@@ -145,12 +148,11 @@ static void
 fw_domains_reset(struct drm_i915_private *dev_priv, enum forcewake_domains fw_domains)
 {
 	struct intel_uncore_forcewake_domain *d;
-	enum forcewake_domain_id id;
 
 	if (dev_priv->uncore.fw_domains == 0)
 		return;
 
-	for_each_fw_domain_mask(d, fw_domains, dev_priv, id)
+	for_each_fw_domain_masked(d, fw_domains, dev_priv)
 		fw_domain_reset(d);
 
 	fw_domains_posting_read(dev_priv);
@@ -204,7 +206,7 @@ static int __gen6_gt_wait_for_fifo(struc
 
 	/* On VLV, FIFO will be shared by both SW and HW.
 	 * So, we need to read the FREE_ENTRIES everytime */
-	if (IS_VALLEYVIEW(dev_priv->dev))
+	if (IS_VALLEYVIEW(dev_priv))
 		dev_priv->uncore.fifo_count = fifo_free_entries(dev_priv);
 
 	if (dev_priv->uncore.fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES) {
@@ -224,9 +226,11 @@ static int __gen6_gt_wait_for_fifo(struc
 	return ret;
 }
 
-static void intel_uncore_fw_release_timer(unsigned long arg)
+static enum hrtimer_restart
+intel_uncore_fw_release_timer(struct hrtimer *timer)
 {
-	struct intel_uncore_forcewake_domain *domain = (void *)arg;
+	struct intel_uncore_forcewake_domain *domain =
+	       container_of(timer, struct intel_uncore_forcewake_domain, timer);
 	unsigned long irqflags;
 
 	assert_rpm_device_not_suspended(domain->i915);
@@ -240,6 +244,8 @@ static void intel_uncore_fw_release_time
 							  1 << domain->id);
 
 	spin_unlock_irqrestore(&domain->i915->uncore.lock, irqflags);
+
+	return HRTIMER_NORESTART;
 }
 
 void intel_uncore_forcewake_reset(struct drm_device *dev, bool restore)
@@ -248,7 +254,6 @@ void intel_uncore_forcewake_reset(struct
 	unsigned long irqflags;
 	struct intel_uncore_forcewake_domain *domain;
 	int retry_count = 100;
-	enum forcewake_domain_id id;
 	enum forcewake_domains fw = 0, active_domains;
 
 	/* Hold uncore.lock across reset to prevent any register access
@@ -258,18 +263,18 @@ void intel_uncore_forcewake_reset(struct
 	while (1) {
 		active_domains = 0;
 
-		for_each_fw_domain(domain, dev_priv, id) {
-			if (del_timer_sync(&domain->timer) == 0)
+		for_each_fw_domain(domain, dev_priv) {
+			if (hrtimer_cancel(&domain->timer) == 0)
 				continue;
 
-			intel_uncore_fw_release_timer((unsigned long)domain);
+			intel_uncore_fw_release_timer(&domain->timer);
 		}
 
 		spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 
-		for_each_fw_domain(domain, dev_priv, id) {
-			if (timer_pending(&domain->timer))
-				active_domains |= (1 << id);
+		for_each_fw_domain(domain, dev_priv) {
+			if (hrtimer_active(&domain->timer))
+				active_domains |= domain->mask;
 		}
 
 		if (active_domains == 0)
@@ -286,9 +291,9 @@ void intel_uncore_forcewake_reset(struct
 
 	WARN_ON(active_domains);
 
-	for_each_fw_domain(domain, dev_priv, id)
+	for_each_fw_domain(domain, dev_priv)
 		if (domain->wake_count)
-			fw |= 1 << id;
+			fw |= domain->mask;
 
 	if (fw)
 		dev_priv->uncore.funcs.force_wake_put(dev_priv, fw);
@@ -310,21 +315,49 @@ void intel_uncore_forcewake_reset(struct
 	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
-static void intel_uncore_ellc_detect(struct drm_device *dev)
+static u64 gen9_edram_size(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	const unsigned int ways[8] = { 4, 8, 12, 16, 16, 16, 16, 16 };
+	const unsigned int sets[4] = { 1, 1, 2, 2 };
+	const u32 cap = dev_priv->edram_cap;
 
-	if ((IS_HASWELL(dev) || IS_BROADWELL(dev) ||
-	     INTEL_INFO(dev)->gen >= 9) &&
-	    (__raw_i915_read32(dev_priv, HSW_EDRAM_PRESENT) & EDRAM_ENABLED)) {
-		/* The docs do not explain exactly how the calculation can be
-		 * made. It is somewhat guessable, but for now, it's always
-		 * 128MB.
-		 * NB: We can't write IDICR yet because we do not have gt funcs
+	return EDRAM_NUM_BANKS(cap) *
+		ways[EDRAM_WAYS_IDX(cap)] *
+		sets[EDRAM_SETS_IDX(cap)] *
+		1024 * 1024;
+}
+
+u64 intel_uncore_edram_size(struct drm_i915_private *dev_priv)
+{
+	if (!HAS_EDRAM(dev_priv))
+		return 0;
+
+	/* The needed capability bits for size calculation
+	 * are not there with pre gen9 so return 128MB always.
+	 */
+	if (INTEL_GEN(dev_priv) < 9)
+		return 128 * 1024 * 1024;
+
+	return gen9_edram_size(dev_priv);
+}
+
+static void intel_uncore_edram_detect(struct drm_i915_private *dev_priv)
+{
+	if (IS_HASWELL(dev_priv) ||
+	    IS_BROADWELL(dev_priv) ||
+	    INTEL_GEN(dev_priv) >= 9) {
+		dev_priv->edram_cap = __raw_i915_read32(dev_priv,
+							HSW_EDRAM_CAP);
+
+		/* NB: We can't write IDICR yet because we do not have gt funcs
 		 * set up */
-		dev_priv->ellc_size = 128;
-		DRM_INFO("Found %zuMB of eLLC\n", dev_priv->ellc_size);
+	} else {
+		dev_priv->edram_cap = 0;
 	}
+
+	if (HAS_EDRAM(dev_priv))
+		DRM_INFO("Found %lluMB of eDRAM\n",
+			 intel_uncore_edram_size(dev_priv) / (1024 * 1024));
 }
 
 static bool
@@ -410,16 +443,15 @@ static void __intel_uncore_forcewake_get
 					 enum forcewake_domains fw_domains)
 {
 	struct intel_uncore_forcewake_domain *domain;
-	enum forcewake_domain_id id;
 
 	if (!dev_priv->uncore.funcs.force_wake_get)
 		return;
 
 	fw_domains &= dev_priv->uncore.fw_domains;
 
-	for_each_fw_domain_mask(domain, fw_domains, dev_priv, id) {
+	for_each_fw_domain_masked(domain, fw_domains, dev_priv) {
 		if (domain->wake_count++)
-			fw_domains &= ~(1 << id);
+			fw_domains &= ~domain->mask;
 	}
 
 	if (fw_domains)
@@ -477,21 +509,19 @@ static void __intel_uncore_forcewake_put
 					 enum forcewake_domains fw_domains)
 {
 	struct intel_uncore_forcewake_domain *domain;
-	enum forcewake_domain_id id;
 
 	if (!dev_priv->uncore.funcs.force_wake_put)
 		return;
 
 	fw_domains &= dev_priv->uncore.fw_domains;
 
-	for_each_fw_domain_mask(domain, fw_domains, dev_priv, id) {
+	for_each_fw_domain_masked(domain, fw_domains, dev_priv) {
 		if (WARN_ON(domain->wake_count == 0))
 			continue;
 
 		if (--domain->wake_count)
 			continue;
 
-		domain->wake_count++;
 		fw_domain_arm_timer(domain);
 	}
 }
@@ -539,18 +569,27 @@ void intel_uncore_forcewake_put__locked(
 void assert_forcewakes_inactive(struct drm_i915_private *dev_priv)
 {
 	struct intel_uncore_forcewake_domain *domain;
-	enum forcewake_domain_id id;
 
 	if (!dev_priv->uncore.funcs.force_wake_get)
 		return;
 
-	for_each_fw_domain(domain, dev_priv, id)
+	for_each_fw_domain(domain, dev_priv)
 		WARN_ON(domain->wake_count);
 }
 
 /* We give fast paths for the really cool registers */
 #define NEEDS_FORCE_WAKE(reg) ((reg) < 0x40000)
 
+#define __gen6_reg_read_fw_domains(offset) \
+({ \
+	enum forcewake_domains __fwd; \
+	if (NEEDS_FORCE_WAKE(offset)) \
+		__fwd = FORCEWAKE_RENDER; \
+	else \
+		__fwd = 0; \
+	__fwd; \
+})
+
 #define REG_RANGE(reg, start, end) ((reg) >= (start) && (reg) < (end))
 
 #define FORCEWAKE_VLV_RENDER_RANGE_OFFSET(reg) \
@@ -564,6 +603,48 @@ void assert_forcewakes_inactive(struct d
 	 REG_RANGE((reg), 0x22000, 0x24000) || \
 	 REG_RANGE((reg), 0x30000, 0x40000))
 
+#define __vlv_reg_read_fw_domains(offset) \
+({ \
+	enum forcewake_domains __fwd = 0; \
+	if (!NEEDS_FORCE_WAKE(offset)) \
+		__fwd = 0; \
+	else if (FORCEWAKE_VLV_RENDER_RANGE_OFFSET(offset)) \
+		__fwd = FORCEWAKE_RENDER; \
+	else if (FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(offset)) \
+		__fwd = FORCEWAKE_MEDIA; \
+	__fwd; \
+})
+
+static const i915_reg_t gen8_shadowed_regs[] = {
+	GEN6_RPNSWREQ,
+	GEN6_RC_VIDEO_FREQ,
+	RING_TAIL(RENDER_RING_BASE),
+	RING_TAIL(GEN6_BSD_RING_BASE),
+	RING_TAIL(VEBOX_RING_BASE),
+	RING_TAIL(BLT_RING_BASE),
+	/* TODO: Other registers are not yet used */
+};
+
+static bool is_gen8_shadowed(u32 offset)
+{
+	int i;
+	for (i = 0; i < ARRAY_SIZE(gen8_shadowed_regs); i++)
+		if (offset == gen8_shadowed_regs[i].reg)
+			return true;
+
+	return false;
+}
+
+#define __gen8_reg_write_fw_domains(offset) \
+({ \
+	enum forcewake_domains __fwd; \
+	if (NEEDS_FORCE_WAKE(offset) && !is_gen8_shadowed(offset)) \
+		__fwd = FORCEWAKE_RENDER; \
+	else \
+		__fwd = 0; \
+	__fwd; \
+})
+
 #define FORCEWAKE_CHV_RENDER_RANGE_OFFSET(reg) \
 	(REG_RANGE((reg), 0x2000, 0x4000) || \
 	 REG_RANGE((reg), 0x5200, 0x8000) || \
@@ -586,6 +667,34 @@ void assert_forcewakes_inactive(struct d
 	 REG_RANGE((reg), 0x9000, 0xB000) || \
 	 REG_RANGE((reg), 0xF000, 0x10000))
 
+#define __chv_reg_read_fw_domains(offset) \
+({ \
+	enum forcewake_domains __fwd = 0; \
+	if (!NEEDS_FORCE_WAKE(offset)) \
+		__fwd = 0; \
+	else if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(offset)) \
+		__fwd = FORCEWAKE_RENDER; \
+	else if (FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(offset)) \
+		__fwd = FORCEWAKE_MEDIA; \
+	else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(offset)) \
+		__fwd = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; \
+	__fwd; \
+})
+
+#define __chv_reg_write_fw_domains(offset) \
+({ \
+	enum forcewake_domains __fwd = 0; \
+	if (!NEEDS_FORCE_WAKE(offset) || is_gen8_shadowed(offset)) \
+		__fwd = 0; \
+	else if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(offset)) \
+		__fwd = FORCEWAKE_RENDER; \
+	else if (FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(offset)) \
+		__fwd = FORCEWAKE_MEDIA; \
+	else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(offset)) \
+		__fwd = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; \
+	__fwd; \
+})
+
 #define FORCEWAKE_GEN9_UNCORE_RANGE_OFFSET(reg) \
 	REG_RANGE((reg), 0xB00,  0x2000)
 
@@ -618,6 +727,61 @@ void assert_forcewakes_inactive(struct d
 	 !FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(reg) && \
 	 !FORCEWAKE_GEN9_COMMON_RANGE_OFFSET(reg))
 
+#define SKL_NEEDS_FORCE_WAKE(reg) \
+	((reg) < 0x40000 && !FORCEWAKE_GEN9_UNCORE_RANGE_OFFSET(reg))
+
+#define __gen9_reg_read_fw_domains(offset) \
+({ \
+	enum forcewake_domains __fwd; \
+	if (!SKL_NEEDS_FORCE_WAKE(offset)) \
+		__fwd = 0; \
+	else if (FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(offset)) \
+		__fwd = FORCEWAKE_RENDER; \
+	else if (FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(offset)) \
+		__fwd = FORCEWAKE_MEDIA; \
+	else if (FORCEWAKE_GEN9_COMMON_RANGE_OFFSET(offset)) \
+		__fwd = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; \
+	else \
+		__fwd = FORCEWAKE_BLITTER; \
+	__fwd; \
+})
+
+static const i915_reg_t gen9_shadowed_regs[] = {
+	RING_TAIL(RENDER_RING_BASE),
+	RING_TAIL(GEN6_BSD_RING_BASE),
+	RING_TAIL(VEBOX_RING_BASE),
+	RING_TAIL(BLT_RING_BASE),
+	GEN6_RPNSWREQ,
+	GEN6_RC_VIDEO_FREQ,
+	/* TODO: Other registers are not yet used */
+};
+
+static bool is_gen9_shadowed(u32 offset)
+{
+	int i;
+	for (i = 0; i < ARRAY_SIZE(gen9_shadowed_regs); i++)
+		if (offset == gen9_shadowed_regs[i].reg)
+			return true;
+
+	return false;
+}
+
+#define __gen9_reg_write_fw_domains(offset) \
+({ \
+	enum forcewake_domains __fwd; \
+	if (!SKL_NEEDS_FORCE_WAKE(offset) || is_gen9_shadowed(offset)) \
+		__fwd = 0; \
+	else if (FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(offset)) \
+		__fwd = FORCEWAKE_RENDER; \
+	else if (FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(offset)) \
+		__fwd = FORCEWAKE_MEDIA; \
+	else if (FORCEWAKE_GEN9_COMMON_RANGE_OFFSET(offset)) \
+		__fwd = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; \
+	else \
+		__fwd = FORCEWAKE_BLITTER; \
+	__fwd; \
+})
+
 static void
 ilk_dummy_write(struct drm_i915_private *dev_priv)
 {
@@ -633,15 +797,6 @@ __unclaimed_reg_debug(struct drm_i915_pr
 		      const bool read,
 		      const bool before)
 {
-	/* XXX. We limit the auto arming traces for mmio
-	 * debugs on these platforms. There are just too many
-	 * revealed by these and CI/Bat suffers from the noise.
-	 * Please fix and then re-enable the automatic traces.
-	 */
-	if (i915.mmio_debug < 2 &&
-	    (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)))
-		return;
-
 	if (WARN(check_for_unclaimed_mmio(dev_priv),
 		 "Unclaimed register detected %s %s register 0x%x\n",
 		 before ? "before" : "after",
@@ -716,23 +871,21 @@ __gen2_read(64)
 	trace_i915_reg_rw(false, reg, val, sizeof(val), trace); \
 	return val
 
-static inline void __force_wake_get(struct drm_i915_private *dev_priv,
-				    enum forcewake_domains fw_domains)
+static inline void __force_wake_auto(struct drm_i915_private *dev_priv,
+				     enum forcewake_domains fw_domains)
 {
 	struct intel_uncore_forcewake_domain *domain;
-	enum forcewake_domain_id id;
 
 	if (WARN_ON(!fw_domains))
 		return;
 
 	/* Ideally GCC would be constant-fold and eliminate this loop */
-	for_each_fw_domain_mask(domain, fw_domains, dev_priv, id) {
+	for_each_fw_domain_masked(domain, fw_domains, dev_priv) {
 		if (domain->wake_count) {
-			fw_domains &= ~(1 << id);
+			fw_domains &= ~domain->mask;
 			continue;
 		}
 
-		domain->wake_count++;
 		fw_domain_arm_timer(domain);
 	}
 
@@ -743,9 +896,11 @@ static inline void __force_wake_get(stru
 #define __gen6_read(x) \
 static u##x \
 gen6_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \
+	enum forcewake_domains fw_engine; \
 	GEN6_READ_HEADER(x); \
-	if (NEEDS_FORCE_WAKE(offset)) \
-		__force_wake_get(dev_priv, FORCEWAKE_RENDER); \
+	fw_engine = __gen6_reg_read_fw_domains(offset); \
+	if (fw_engine) \
+		__force_wake_auto(dev_priv, fw_engine); \
 	val = __raw_i915_read##x(dev_priv, reg); \
 	GEN6_READ_FOOTER; \
 }
@@ -753,16 +908,11 @@ gen6_read##x(struct drm_i915_private *de
 #define __vlv_read(x) \
 static u##x \
 vlv_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \
-	enum forcewake_domains fw_engine = 0; \
+	enum forcewake_domains fw_engine; \
 	GEN6_READ_HEADER(x); \
-	if (!NEEDS_FORCE_WAKE(offset)) \
-		fw_engine = 0; \
-	else if (FORCEWAKE_VLV_RENDER_RANGE_OFFSET(offset)) \
-		fw_engine = FORCEWAKE_RENDER; \
-	else if (FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(offset)) \
-		fw_engine = FORCEWAKE_MEDIA; \
+	fw_engine = __vlv_reg_read_fw_domains(offset); \
 	if (fw_engine) \
-		__force_wake_get(dev_priv, fw_engine); \
+		__force_wake_auto(dev_priv, fw_engine); \
 	val = __raw_i915_read##x(dev_priv, reg); \
 	GEN6_READ_FOOTER; \
 }
@@ -770,42 +920,23 @@ vlv_read##x(struct drm_i915_private *dev
 #define __chv_read(x) \
 static u##x \
 chv_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \
-	enum forcewake_domains fw_engine = 0; \
+	enum forcewake_domains fw_engine; \
 	GEN6_READ_HEADER(x); \
-	if (!NEEDS_FORCE_WAKE(offset)) \
-		fw_engine = 0; \
-	else if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(offset)) \
-		fw_engine = FORCEWAKE_RENDER; \
-	else if (FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(offset)) \
-		fw_engine = FORCEWAKE_MEDIA; \
-	else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(offset)) \
-		fw_engine = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; \
+	fw_engine = __chv_reg_read_fw_domains(offset); \
 	if (fw_engine) \
-		__force_wake_get(dev_priv, fw_engine); \
+		__force_wake_auto(dev_priv, fw_engine); \
 	val = __raw_i915_read##x(dev_priv, reg); \
 	GEN6_READ_FOOTER; \
 }
 
-#define SKL_NEEDS_FORCE_WAKE(reg) \
-	((reg) < 0x40000 && !FORCEWAKE_GEN9_UNCORE_RANGE_OFFSET(reg))
-
 #define __gen9_read(x) \
 static u##x \
 gen9_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \
 	enum forcewake_domains fw_engine; \
 	GEN6_READ_HEADER(x); \
-	if (!SKL_NEEDS_FORCE_WAKE(offset)) \
-		fw_engine = 0; \
-	else if (FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(offset)) \
-		fw_engine = FORCEWAKE_RENDER; \
-	else if (FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(offset)) \
-		fw_engine = FORCEWAKE_MEDIA; \
-	else if (FORCEWAKE_GEN9_COMMON_RANGE_OFFSET(offset)) \
-		fw_engine = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; \
-	else \
-		fw_engine = FORCEWAKE_BLITTER; \
+	fw_engine = __gen9_reg_read_fw_domains(offset); \
 	if (fw_engine) \
-		__force_wake_get(dev_priv, fw_engine); \
+		__force_wake_auto(dev_priv, fw_engine); \
 	val = __raw_i915_read##x(dev_priv, reg); \
 	GEN6_READ_FOOTER; \
 }
@@ -942,34 +1073,14 @@ hsw_write##x(struct drm_i915_private *de
 	GEN6_WRITE_FOOTER; \
 }
 
-static const i915_reg_t gen8_shadowed_regs[] = {
-	FORCEWAKE_MT,
-	GEN6_RPNSWREQ,
-	GEN6_RC_VIDEO_FREQ,
-	RING_TAIL(RENDER_RING_BASE),
-	RING_TAIL(GEN6_BSD_RING_BASE),
-	RING_TAIL(VEBOX_RING_BASE),
-	RING_TAIL(BLT_RING_BASE),
-	/* TODO: Other registers are not yet used */
-};
-
-static bool is_gen8_shadowed(struct drm_i915_private *dev_priv,
-			     i915_reg_t reg)
-{
-	int i;
-	for (i = 0; i < ARRAY_SIZE(gen8_shadowed_regs); i++)
-		if (i915_mmio_reg_equal(reg, gen8_shadowed_regs[i]))
-			return true;
-
-	return false;
-}
-
 #define __gen8_write(x) \
 static void \
 gen8_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool trace) { \
+	enum forcewake_domains fw_engine; \
 	GEN6_WRITE_HEADER; \
-	if (NEEDS_FORCE_WAKE(offset) && !is_gen8_shadowed(dev_priv, reg)) \
-		__force_wake_get(dev_priv, FORCEWAKE_RENDER); \
+	fw_engine = __gen8_reg_write_fw_domains(offset); \
+	if (fw_engine) \
+		__force_wake_auto(dev_priv, fw_engine); \
 	__raw_i915_write##x(dev_priv, reg, val); \
 	GEN6_WRITE_FOOTER; \
 }
@@ -977,66 +1088,24 @@ gen8_write##x(struct drm_i915_private *d
 #define __chv_write(x) \
 static void \
 chv_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool trace) { \
-	enum forcewake_domains fw_engine = 0; \
+	enum forcewake_domains fw_engine; \
 	GEN6_WRITE_HEADER; \
-	if (!NEEDS_FORCE_WAKE(offset) || \
-	    is_gen8_shadowed(dev_priv, reg)) \
-		fw_engine = 0; \
-	else if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(offset)) \
-		fw_engine = FORCEWAKE_RENDER; \
-	else if (FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(offset)) \
-		fw_engine = FORCEWAKE_MEDIA; \
-	else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(offset)) \
-		fw_engine = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; \
+	fw_engine = __chv_reg_write_fw_domains(offset); \
 	if (fw_engine) \
-		__force_wake_get(dev_priv, fw_engine); \
+		__force_wake_auto(dev_priv, fw_engine); \
 	__raw_i915_write##x(dev_priv, reg, val); \
 	GEN6_WRITE_FOOTER; \
 }
 
-static const i915_reg_t gen9_shadowed_regs[] = {
-	RING_TAIL(RENDER_RING_BASE),
-	RING_TAIL(GEN6_BSD_RING_BASE),
-	RING_TAIL(VEBOX_RING_BASE),
-	RING_TAIL(BLT_RING_BASE),
-	FORCEWAKE_BLITTER_GEN9,
-	FORCEWAKE_RENDER_GEN9,
-	FORCEWAKE_MEDIA_GEN9,
-	GEN6_RPNSWREQ,
-	GEN6_RC_VIDEO_FREQ,
-	/* TODO: Other registers are not yet used */
-};
-
-static bool is_gen9_shadowed(struct drm_i915_private *dev_priv,
-			     i915_reg_t reg)
-{
-	int i;
-	for (i = 0; i < ARRAY_SIZE(gen9_shadowed_regs); i++)
-		if (i915_mmio_reg_equal(reg, gen9_shadowed_regs[i]))
-			return true;
-
-	return false;
-}
-
 #define __gen9_write(x) \
 static void \
 gen9_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, \
 		bool trace) { \
 	enum forcewake_domains fw_engine; \
 	GEN6_WRITE_HEADER; \
-	if (!SKL_NEEDS_FORCE_WAKE(offset) || \
-	    is_gen9_shadowed(dev_priv, reg)) \
-		fw_engine = 0; \
-	else if (FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(offset)) \
-		fw_engine = FORCEWAKE_RENDER; \
-	else if (FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(offset)) \
-		fw_engine = FORCEWAKE_MEDIA; \
-	else if (FORCEWAKE_GEN9_COMMON_RANGE_OFFSET(offset)) \
-		fw_engine = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; \
-	else \
-		fw_engine = FORCEWAKE_BLITTER; \
+	fw_engine = __gen9_reg_write_fw_domains(offset); \
 	if (fw_engine) \
-		__force_wake_get(dev_priv, fw_engine); \
+		__force_wake_auto(dev_priv, fw_engine); \
 	__raw_i915_write##x(dev_priv, reg, val); \
 	GEN6_WRITE_FOOTER; \
 }
@@ -1150,7 +1219,14 @@ static void fw_domain_init(struct drm_i9
 	d->i915 = dev_priv;
 	d->id = domain_id;
 
-	setup_timer(&d->timer, intel_uncore_fw_release_timer, (unsigned long)d);
+	BUILD_BUG_ON(FORCEWAKE_RENDER != (1 << FW_DOMAIN_ID_RENDER));
+	BUILD_BUG_ON(FORCEWAKE_BLITTER != (1 << FW_DOMAIN_ID_BLITTER));
+	BUILD_BUG_ON(FORCEWAKE_MEDIA != (1 << FW_DOMAIN_ID_MEDIA));
+
+	d->mask = 1 << domain_id;
+
+	hrtimer_init(&d->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+	d->timer.function = intel_uncore_fw_release_timer;
 
 	dev_priv->uncore.fw_domains |= (1 << domain_id);
 
@@ -1161,7 +1237,7 @@ static void intel_uncore_fw_domains_init
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	if (INTEL_INFO(dev_priv->dev)->gen <= 5)
+	if (INTEL_INFO(dev_priv)->gen <= 5)
 		return;
 
 	if (IS_GEN9(dev)) {
@@ -1257,7 +1333,7 @@ void intel_uncore_init(struct drm_device
 
 	i915_check_vgpu(dev);
 
-	intel_uncore_ellc_detect(dev);
+	intel_uncore_edram_detect(dev_priv);
 	intel_uncore_fw_domains_init(dev);
 	__intel_uncore_early_sanitize(dev, false);
 
@@ -1437,7 +1513,7 @@ static int i915_reset_complete(struct dr
 	return (gdrst & GRDOM_RESET_STATUS) == 0;
 }
 
-static int i915_do_reset(struct drm_device *dev)
+static int i915_do_reset(struct drm_device *dev, unsigned engine_mask)
 {
 	/* assert reset for at least 20 usec */
 	pci_write_config_byte(dev->pdev, I915_GDRST, GRDOM_RESET_ENABLE);
@@ -1454,13 +1530,13 @@ static int g4x_reset_complete(struct drm
 	return (gdrst & GRDOM_RESET_ENABLE) == 0;
 }
 
-static int g33_do_reset(struct drm_device *dev)
+static int g33_do_reset(struct drm_device *dev, unsigned engine_mask)
 {
 	pci_write_config_byte(dev->pdev, I915_GDRST, GRDOM_RESET_ENABLE);
 	return wait_for(g4x_reset_complete(dev), 500);
 }
 
-static int g4x_do_reset(struct drm_device *dev)
+static int g4x_do_reset(struct drm_device *dev, unsigned engine_mask)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int ret;
@@ -1490,7 +1566,7 @@ static int g4x_do_reset(struct drm_devic
 	return 0;
 }
 
-static int ironlake_do_reset(struct drm_device *dev)
+static int ironlake_do_reset(struct drm_device *dev, unsigned engine_mask)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int ret;
@@ -1514,75 +1590,132 @@ static int ironlake_do_reset(struct drm_
 	return 0;
 }
 
-static int gen6_do_reset(struct drm_device *dev)
+/* Reset the hardware domains (GENX_GRDOM_*) specified by mask */
+static int gen6_hw_domain_reset(struct drm_i915_private *dev_priv,
+				u32 hw_domain_mask)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	int	ret;
-
-	/* Reset the chip */
+	int ret;
 
 	/* GEN6_GDRST is not in the gt power well, no need to check
 	 * for fifo space for the write or forcewake the chip for
 	 * the read
 	 */
-	__raw_i915_write32(dev_priv, GEN6_GDRST, GEN6_GRDOM_FULL);
+	__raw_i915_write32(dev_priv, GEN6_GDRST, hw_domain_mask);
 
-	/* Spin waiting for the device to ack the reset request */
-	ret = wait_for((__raw_i915_read32(dev_priv, GEN6_GDRST) & GEN6_GRDOM_FULL) == 0, 500);
+#define ACKED ((__raw_i915_read32(dev_priv, GEN6_GDRST) & hw_domain_mask) == 0)
+	/* Spin waiting for the device to ack the reset requests */
+	ret = wait_for(ACKED, 500);
+#undef ACKED
+
+	return ret;
+}
+
+/**
+ * gen6_reset_engines - reset individual engines
+ * @dev: DRM device
+ * @engine_mask: mask of intel_ring_flag() engines or ALL_ENGINES for full reset
+ *
+ * This function will reset the individual engines that are set in engine_mask.
+ * If you provide ALL_ENGINES as mask, full global domain reset will be issued.
+ *
+ * Note: It is responsibility of the caller to handle the difference between
+ * asking full domain reset versus reset for all available individual engines.
+ *
+ * Returns 0 on success, nonzero on error.
+ */
+static int gen6_reset_engines(struct drm_device *dev, unsigned engine_mask)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_engine_cs *engine;
+	const u32 hw_engine_mask[I915_NUM_ENGINES] = {
+		[RCS] = GEN6_GRDOM_RENDER,
+		[BCS] = GEN6_GRDOM_BLT,
+		[VCS] = GEN6_GRDOM_MEDIA,
+		[VCS2] = GEN8_GRDOM_MEDIA2,
+		[VECS] = GEN6_GRDOM_VECS,
+	};
+	u32 hw_mask;
+	int ret;
+
+	if (engine_mask == ALL_ENGINES) {
+		hw_mask = GEN6_GRDOM_FULL;
+	} else {
+		hw_mask = 0;
+		for_each_engine_masked(engine, dev_priv, engine_mask)
+			hw_mask |= hw_engine_mask[engine->id];
+	}
+
+	ret = gen6_hw_domain_reset(dev_priv, hw_mask);
 
 	intel_uncore_forcewake_reset(dev, true);
 
 	return ret;
 }
 
-static int wait_for_register(struct drm_i915_private *dev_priv,
-			     i915_reg_t reg,
-			     const u32 mask,
-			     const u32 value,
-			     const unsigned long timeout_ms)
+static int wait_for_register_fw(struct drm_i915_private *dev_priv,
+				i915_reg_t reg,
+				const u32 mask,
+				const u32 value,
+				const unsigned long timeout_ms)
 {
-	return wait_for((I915_READ(reg) & mask) == value, timeout_ms);
+	return wait_for((I915_READ_FW(reg) & mask) == value, timeout_ms);
 }
 
-static int gen8_do_reset(struct drm_device *dev)
+static int gen8_request_engine_reset(struct intel_engine_cs *engine)
+{
+	int ret;
+	struct drm_i915_private *dev_priv = engine->dev->dev_private;
+
+	I915_WRITE_FW(RING_RESET_CTL(engine->mmio_base),
+		      _MASKED_BIT_ENABLE(RESET_CTL_REQUEST_RESET));
+
+	ret = wait_for_register_fw(dev_priv,
+				   RING_RESET_CTL(engine->mmio_base),
+				   RESET_CTL_READY_TO_RESET,
+				   RESET_CTL_READY_TO_RESET,
+				   700);
+	if (ret)
+		DRM_ERROR("%s: reset request timeout\n", engine->name);
+
+	return ret;
+}
+
+static void gen8_unrequest_engine_reset(struct intel_engine_cs *engine)
+{
+	struct drm_i915_private *dev_priv = engine->dev->dev_private;
+
+	I915_WRITE_FW(RING_RESET_CTL(engine->mmio_base),
+		      _MASKED_BIT_DISABLE(RESET_CTL_REQUEST_RESET));
+}
+
+static int gen8_reset_engines(struct drm_device *dev, unsigned engine_mask)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_engine_cs *engine;
-	int i;
-
-	for_each_ring(engine, dev_priv, i) {
-		I915_WRITE(RING_RESET_CTL(engine->mmio_base),
-			   _MASKED_BIT_ENABLE(RESET_CTL_REQUEST_RESET));
 
-		if (wait_for_register(dev_priv,
-				      RING_RESET_CTL(engine->mmio_base),
-				      RESET_CTL_READY_TO_RESET,
-				      RESET_CTL_READY_TO_RESET,
-				      700)) {
-			DRM_ERROR("%s: reset request timeout\n", engine->name);
+	for_each_engine_masked(engine, dev_priv, engine_mask)
+		if (gen8_request_engine_reset(engine))
 			goto not_ready;
-		}
-	}
 
-	return gen6_do_reset(dev);
+	return gen6_reset_engines(dev, engine_mask);
 
 not_ready:
-	for_each_ring(engine, dev_priv, i)
-		I915_WRITE(RING_RESET_CTL(engine->mmio_base),
-			   _MASKED_BIT_DISABLE(RESET_CTL_REQUEST_RESET));
+	for_each_engine_masked(engine, dev_priv, engine_mask)
+		gen8_unrequest_engine_reset(engine);
 
 	return -EIO;
 }
 
-static int (*intel_get_gpu_reset(struct drm_device *dev))(struct drm_device *)
+static int (*intel_get_gpu_reset(struct drm_device *dev))(struct drm_device *,
+							  unsigned engine_mask)
 {
 	if (!i915.reset)
 		return NULL;
 
 	if (INTEL_INFO(dev)->gen >= 8)
-		return gen8_do_reset;
+		return gen8_reset_engines;
 	else if (INTEL_INFO(dev)->gen >= 6)
-		return gen6_do_reset;
+		return gen6_reset_engines;
 	else if (IS_GEN5(dev))
 		return ironlake_do_reset;
 	else if (IS_G4X(dev))
@@ -1595,10 +1728,10 @@ static int (*intel_get_gpu_reset(struct
 		return NULL;
 }
 
-int intel_gpu_reset(struct drm_device *dev)
+int intel_gpu_reset(struct drm_device *dev, unsigned engine_mask)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
-	int (*reset)(struct drm_device *);
+	int (*reset)(struct drm_device *, unsigned);
 	int ret;
 
 	reset = intel_get_gpu_reset(dev);
@@ -1609,7 +1742,7 @@ int intel_gpu_reset(struct drm_device *d
 	 * request may be dropped and never completes (causing -EIO).
 	 */
 	intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
-	ret = reset(dev);
+	ret = reset(dev, engine_mask);
 	intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
 
 	return ret;
@@ -1620,6 +1753,25 @@ bool intel_has_gpu_reset(struct drm_devi
 	return intel_get_gpu_reset(dev) != NULL;
 }
 
+int intel_guc_reset(struct drm_i915_private *dev_priv)
+{
+	int ret;
+	unsigned long irqflags;
+
+	if (!i915.enable_guc_submission)
+		return -EINVAL;
+
+	intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
+	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
+
+	ret = gen6_hw_domain_reset(dev_priv, GEN9_GRDOM_GUC);
+
+	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
+	intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
+
+	return ret;
+}
+
 bool intel_uncore_unclaimed_mmio(struct drm_i915_private *dev_priv)
 {
 	return check_for_unclaimed_mmio(dev_priv);
@@ -1643,3 +1795,111 @@ intel_uncore_arm_unclaimed_mmio_detectio
 
 	return false;
 }
+
+static enum forcewake_domains
+intel_uncore_forcewake_for_read(struct drm_i915_private *dev_priv,
+				i915_reg_t reg)
+{
+	enum forcewake_domains fw_domains;
+
+	if (intel_vgpu_active(dev_priv->dev))
+		return 0;
+
+	switch (INTEL_INFO(dev_priv)->gen) {
+	case 9:
+		fw_domains = __gen9_reg_read_fw_domains(i915_mmio_reg_offset(reg));
+		break;
+	case 8:
+		if (IS_CHERRYVIEW(dev_priv))
+			fw_domains = __chv_reg_read_fw_domains(i915_mmio_reg_offset(reg));
+		else
+			fw_domains = __gen6_reg_read_fw_domains(i915_mmio_reg_offset(reg));
+		break;
+	case 7:
+	case 6:
+		if (IS_VALLEYVIEW(dev_priv))
+			fw_domains = __vlv_reg_read_fw_domains(i915_mmio_reg_offset(reg));
+		else
+			fw_domains = __gen6_reg_read_fw_domains(i915_mmio_reg_offset(reg));
+		break;
+	default:
+		MISSING_CASE(INTEL_INFO(dev_priv)->gen);
+	case 5: /* forcewake was introduced with gen6 */
+	case 4:
+	case 3:
+	case 2:
+		return 0;
+	}
+
+	WARN_ON(fw_domains & ~dev_priv->uncore.fw_domains);
+
+	return fw_domains;
+}
+
+static enum forcewake_domains
+intel_uncore_forcewake_for_write(struct drm_i915_private *dev_priv,
+				 i915_reg_t reg)
+{
+	enum forcewake_domains fw_domains;
+
+	if (intel_vgpu_active(dev_priv->dev))
+		return 0;
+
+	switch (INTEL_INFO(dev_priv)->gen) {
+	case 9:
+		fw_domains = __gen9_reg_write_fw_domains(i915_mmio_reg_offset(reg));
+		break;
+	case 8:
+		if (IS_CHERRYVIEW(dev_priv))
+			fw_domains = __chv_reg_write_fw_domains(i915_mmio_reg_offset(reg));
+		else
+			fw_domains = __gen8_reg_write_fw_domains(i915_mmio_reg_offset(reg));
+		break;
+	case 7:
+	case 6:
+		fw_domains = FORCEWAKE_RENDER;
+		break;
+	default:
+		MISSING_CASE(INTEL_INFO(dev_priv)->gen);
+	case 5:
+	case 4:
+	case 3:
+	case 2:
+		return 0;
+	}
+
+	WARN_ON(fw_domains & ~dev_priv->uncore.fw_domains);
+
+	return fw_domains;
+}
+
+/**
+ * intel_uncore_forcewake_for_reg - which forcewake domains are needed to access
+ * 				    a register
+ * @dev_priv: pointer to struct drm_i915_private
+ * @reg: register in question
+ * @op: operation bitmask of FW_REG_READ and/or FW_REG_WRITE
+ *
+ * Returns a set of forcewake domains required to be taken with for example
+ * intel_uncore_forcewake_get for the specified register to be accessible in the
+ * specified mode (read, write or read/write) with raw mmio accessors.
+ *
+ * NOTE: On Gen6 and Gen7 write forcewake domain (FORCEWAKE_RENDER) requires the
+ * callers to do FIFO management on their own or risk losing writes.
+ */
+enum forcewake_domains
+intel_uncore_forcewake_for_reg(struct drm_i915_private *dev_priv,
+			       i915_reg_t reg, unsigned int op)
+{
+	enum forcewake_domains fw_domains = 0;
+
+	WARN_ON(!op);
+
+	if (op & FW_REG_READ)
+		fw_domains = intel_uncore_forcewake_for_read(dev_priv, reg);
+
+	if (op & FW_REG_WRITE)
+		fw_domains |= intel_uncore_forcewake_for_write(dev_priv, reg);
+
+	return fw_domains;
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_vbt_defs.h linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_vbt_defs.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/intel_vbt_defs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/intel_vbt_defs.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,845 @@
+/*
+ * Copyright © 2006-2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Eric Anholt <eric@anholt.net>
+ *
+ */
+
+/*
+ * This information is private to VBT parsing in intel_bios.c.
+ *
+ * Please do NOT include anywhere else.
+ */
+#ifndef _INTEL_BIOS_PRIVATE
+#error "intel_vbt_defs.h is private to intel_bios.c"
+#endif
+
+#ifndef _INTEL_VBT_DEFS_H_
+#define _INTEL_VBT_DEFS_H_
+
+#include "intel_bios.h"
+
+/**
+ * struct vbt_header - VBT Header structure
+ * @signature:		VBT signature, always starts with "$VBT"
+ * @version:		Version of this structure
+ * @header_size:	Size of this structure
+ * @vbt_size:		Size of VBT (VBT Header, BDB Header and data blocks)
+ * @vbt_checksum:	Checksum
+ * @reserved0:		Reserved
+ * @bdb_offset:		Offset of &struct bdb_header from beginning of VBT
+ * @aim_offset:		Offsets of add-in data blocks from beginning of VBT
+ */
+struct vbt_header {
+	u8 signature[20];
+	u16 version;
+	u16 header_size;
+	u16 vbt_size;
+	u8 vbt_checksum;
+	u8 reserved0;
+	u32 bdb_offset;
+	u32 aim_offset[4];
+} __packed;
+
+/**
+ * struct bdb_header - BDB Header structure
+ * @signature:		BDB signature "BIOS_DATA_BLOCK"
+ * @version:		Version of the data block definitions
+ * @header_size:	Size of this structure
+ * @bdb_size:		Size of BDB (BDB Header and data blocks)
+ */
+struct bdb_header {
+	u8 signature[16];
+	u16 version;
+	u16 header_size;
+	u16 bdb_size;
+} __packed;
+
+/* strictly speaking, this is a "skip" block, but it has interesting info */
+struct vbios_data {
+	u8 type; /* 0 == desktop, 1 == mobile */
+	u8 relstage;
+	u8 chipset;
+	u8 lvds_present:1;
+	u8 tv_present:1;
+	u8 rsvd2:6; /* finish byte */
+	u8 rsvd3[4];
+	u8 signon[155];
+	u8 copyright[61];
+	u16 code_segment;
+	u8 dos_boot_mode;
+	u8 bandwidth_percent;
+	u8 rsvd4; /* popup memory size */
+	u8 resize_pci_bios;
+	u8 rsvd5; /* is crt already on ddc2 */
+} __packed;
+
+/*
+ * There are several types of BIOS data blocks (BDBs), each block has
+ * an ID and size in the first 3 bytes (ID in first, size in next 2).
+ * Known types are listed below.
+ */
+#define BDB_GENERAL_FEATURES	  1
+#define BDB_GENERAL_DEFINITIONS	  2
+#define BDB_OLD_TOGGLE_LIST	  3
+#define BDB_MODE_SUPPORT_LIST	  4
+#define BDB_GENERIC_MODE_TABLE	  5
+#define BDB_EXT_MMIO_REGS	  6
+#define BDB_SWF_IO		  7
+#define BDB_SWF_MMIO		  8
+#define BDB_PSR			  9
+#define BDB_MODE_REMOVAL_TABLE	 10
+#define BDB_CHILD_DEVICE_TABLE	 11
+#define BDB_DRIVER_FEATURES	 12
+#define BDB_DRIVER_PERSISTENCE	 13
+#define BDB_EXT_TABLE_PTRS	 14
+#define BDB_DOT_CLOCK_OVERRIDE	 15
+#define BDB_DISPLAY_SELECT	 16
+/* 17 rsvd */
+#define BDB_DRIVER_ROTATION	 18
+#define BDB_DISPLAY_REMOVE	 19
+#define BDB_OEM_CUSTOM		 20
+#define BDB_EFP_LIST		 21 /* workarounds for VGA hsync/vsync */
+#define BDB_SDVO_LVDS_OPTIONS	 22
+#define BDB_SDVO_PANEL_DTDS	 23
+#define BDB_SDVO_LVDS_PNP_IDS	 24
+#define BDB_SDVO_LVDS_POWER_SEQ	 25
+#define BDB_TV_OPTIONS		 26
+#define BDB_EDP			 27
+#define BDB_LVDS_OPTIONS	 40
+#define BDB_LVDS_LFP_DATA_PTRS	 41
+#define BDB_LVDS_LFP_DATA	 42
+#define BDB_LVDS_BACKLIGHT	 43
+#define BDB_LVDS_POWER		 44
+#define BDB_MIPI_CONFIG		 52
+#define BDB_MIPI_SEQUENCE	 53
+#define BDB_SKIP		254 /* VBIOS private block, ignore */
+
+struct bdb_general_features {
+        /* bits 1 */
+	u8 panel_fitting:2;
+	u8 flexaim:1;
+	u8 msg_enable:1;
+	u8 clear_screen:3;
+	u8 color_flip:1;
+
+        /* bits 2 */
+	u8 download_ext_vbt:1;
+	u8 enable_ssc:1;
+	u8 ssc_freq:1;
+	u8 enable_lfp_on_override:1;
+	u8 disable_ssc_ddt:1;
+	u8 rsvd7:1;
+	u8 display_clock_mode:1;
+	u8 rsvd8:1; /* finish byte */
+
+        /* bits 3 */
+	u8 disable_smooth_vision:1;
+	u8 single_dvi:1;
+	u8 rsvd9:1;
+	u8 fdi_rx_polarity_inverted:1;
+	u8 rsvd10:4; /* finish byte */
+
+        /* bits 4 */
+	u8 legacy_monitor_detect;
+
+        /* bits 5 */
+	u8 int_crt_support:1;
+	u8 int_tv_support:1;
+	u8 int_efp_support:1;
+	u8 dp_ssc_enb:1;	/* PCH attached eDP supports SSC */
+	u8 dp_ssc_freq:1;	/* SSC freq for PCH attached eDP */
+	u8 rsvd11:3; /* finish byte */
+} __packed;
+
+/* pre-915 */
+#define GPIO_PIN_DVI_LVDS	0x03 /* "DVI/LVDS DDC GPIO pins" */
+#define GPIO_PIN_ADD_I2C	0x05 /* "ADDCARD I2C GPIO pins" */
+#define GPIO_PIN_ADD_DDC	0x04 /* "ADDCARD DDC GPIO pins" */
+#define GPIO_PIN_ADD_DDC_I2C	0x06 /* "ADDCARD DDC/I2C GPIO pins" */
+
+/* Pre 915 */
+#define DEVICE_TYPE_NONE	0x00
+#define DEVICE_TYPE_CRT		0x01
+#define DEVICE_TYPE_TV		0x09
+#define DEVICE_TYPE_EFP		0x12
+#define DEVICE_TYPE_LFP		0x22
+/* On 915+ */
+#define DEVICE_TYPE_CRT_DPMS		0x6001
+#define DEVICE_TYPE_CRT_DPMS_HOTPLUG	0x4001
+#define DEVICE_TYPE_TV_COMPOSITE	0x0209
+#define DEVICE_TYPE_TV_MACROVISION	0x0289
+#define DEVICE_TYPE_TV_RF_COMPOSITE	0x020c
+#define DEVICE_TYPE_TV_SVIDEO_COMPOSITE	0x0609
+#define DEVICE_TYPE_TV_SCART		0x0209
+#define DEVICE_TYPE_TV_CODEC_HOTPLUG_PWR 0x6009
+#define DEVICE_TYPE_EFP_HOTPLUG_PWR	0x6012
+#define DEVICE_TYPE_EFP_DVI_HOTPLUG_PWR	0x6052
+#define DEVICE_TYPE_EFP_DVI_I		0x6053
+#define DEVICE_TYPE_EFP_DVI_D_DUAL	0x6152
+#define DEVICE_TYPE_EFP_DVI_D_HDCP	0x60d2
+#define DEVICE_TYPE_OPENLDI_HOTPLUG_PWR	0x6062
+#define DEVICE_TYPE_OPENLDI_DUALPIX	0x6162
+#define DEVICE_TYPE_LFP_PANELLINK	0x5012
+#define DEVICE_TYPE_LFP_CMOS_PWR	0x5042
+#define DEVICE_TYPE_LFP_LVDS_PWR	0x5062
+#define DEVICE_TYPE_LFP_LVDS_DUAL	0x5162
+#define DEVICE_TYPE_LFP_LVDS_DUAL_HDCP	0x51e2
+
+#define DEVICE_CFG_NONE		0x00
+#define DEVICE_CFG_12BIT_DVOB	0x01
+#define DEVICE_CFG_12BIT_DVOC	0x02
+#define DEVICE_CFG_24BIT_DVOBC	0x09
+#define DEVICE_CFG_24BIT_DVOCB	0x0a
+#define DEVICE_CFG_DUAL_DVOB	0x11
+#define DEVICE_CFG_DUAL_DVOC	0x12
+#define DEVICE_CFG_DUAL_DVOBC	0x13
+#define DEVICE_CFG_DUAL_LINK_DVOBC	0x19
+#define DEVICE_CFG_DUAL_LINK_DVOCB	0x1a
+
+#define DEVICE_WIRE_NONE	0x00
+#define DEVICE_WIRE_DVOB	0x01
+#define DEVICE_WIRE_DVOC	0x02
+#define DEVICE_WIRE_DVOBC	0x03
+#define DEVICE_WIRE_DVOBB	0x05
+#define DEVICE_WIRE_DVOCC	0x06
+#define DEVICE_WIRE_DVOB_MASTER 0x0d
+#define DEVICE_WIRE_DVOC_MASTER 0x0e
+
+#define DEVICE_PORT_DVOA	0x00 /* none on 845+ */
+#define DEVICE_PORT_DVOB	0x01
+#define DEVICE_PORT_DVOC	0x02
+
+/*
+ * We used to keep this struct but without any version control. We should avoid
+ * using it in the future, but it should be safe to keep using it in the old
+ * code. Do not change; we rely on its size.
+ */
+struct old_child_dev_config {
+	u16 handle;
+	u16 device_type;
+	u8  device_id[10]; /* ascii string */
+	u16 addin_offset;
+	u8  dvo_port; /* See Device_PORT_* above */
+	u8  i2c_pin;
+	u8  slave_addr;
+	u8  ddc_pin;
+	u16 edid_ptr;
+	u8  dvo_cfg; /* See DEVICE_CFG_* above */
+	u8  dvo2_port;
+	u8  i2c2_pin;
+	u8  slave2_addr;
+	u8  ddc2_pin;
+	u8  capabilities;
+	u8  dvo_wiring;/* See DEVICE_WIRE_* above */
+	u8  dvo2_wiring;
+	u16 extended_type;
+	u8  dvo_function;
+} __packed;
+
+/* This one contains field offsets that are known to be common for all BDB
+ * versions. Notice that the meaning of the contents contents may still change,
+ * but at least the offsets are consistent. */
+
+struct common_child_dev_config {
+	u16 handle;
+	u16 device_type;
+	u8 not_common1[12];
+	u8 dvo_port;
+	u8 not_common2[2];
+	u8 ddc_pin;
+	u16 edid_ptr;
+	u8 dvo_cfg; /* See DEVICE_CFG_* above */
+	u8 efp_routed:1;
+	u8 lane_reversal:1;
+	u8 lspcon:1;
+	u8 iboost:1;
+	u8 hpd_invert:1;
+	u8 flag_reserved:3;
+	u8 hdmi_support:1;
+	u8 dp_support:1;
+	u8 tmds_support:1;
+	u8 support_reserved:5;
+	u8 not_common3[12];
+	u8 iboost_level;
+} __packed;
+
+
+/* This field changes depending on the BDB version, so the most reliable way to
+ * read it is by checking the BDB version and reading the raw pointer. */
+union child_device_config {
+	/* This one is safe to be used anywhere, but the code should still check
+	 * the BDB version. */
+	u8 raw[33];
+	/* This one should only be kept for legacy code. */
+	struct old_child_dev_config old;
+	/* This one should also be safe to use anywhere, even without version
+	 * checks. */
+	struct common_child_dev_config common;
+} __packed;
+
+struct bdb_general_definitions {
+	/* DDC GPIO */
+	u8 crt_ddc_gmbus_pin;
+
+	/* DPMS bits */
+	u8 dpms_acpi:1;
+	u8 skip_boot_crt_detect:1;
+	u8 dpms_aim:1;
+	u8 rsvd1:5; /* finish byte */
+
+	/* boot device bits */
+	u8 boot_display[2];
+	u8 child_dev_size;
+
+	/*
+	 * Device info:
+	 * If TV is present, it'll be at devices[0].
+	 * LVDS will be next, either devices[0] or [1], if present.
+	 * On some platforms the number of device is 6. But could be as few as
+	 * 4 if both TV and LVDS are missing.
+	 * And the device num is related with the size of general definition
+	 * block. It is obtained by using the following formula:
+	 * number = (block_size - sizeof(bdb_general_definitions))/
+	 *	     defs->child_dev_size;
+	 */
+	uint8_t devices[0];
+} __packed;
+
+/* Mask for DRRS / Panel Channel / SSC / BLT control bits extraction */
+#define MODE_MASK		0x3
+
+struct bdb_lvds_options {
+	u8 panel_type;
+	u8 rsvd1;
+	/* LVDS capabilities, stored in a dword */
+	u8 pfit_mode:2;
+	u8 pfit_text_mode_enhanced:1;
+	u8 pfit_gfx_mode_enhanced:1;
+	u8 pfit_ratio_auto:1;
+	u8 pixel_dither:1;
+	u8 lvds_edid:1;
+	u8 rsvd2:1;
+	u8 rsvd4;
+	/* LVDS Panel channel bits stored here */
+	u32 lvds_panel_channel_bits;
+	/* LVDS SSC (Spread Spectrum Clock) bits stored here. */
+	u16 ssc_bits;
+	u16 ssc_freq;
+	u16 ssc_ddt;
+	/* Panel color depth defined here */
+	u16 panel_color_depth;
+	/* LVDS panel type bits stored here */
+	u32 dps_panel_type_bits;
+	/* LVDS backlight control type bits stored here */
+	u32 blt_control_type_bits;
+} __packed;
+
+/* LFP pointer table contains entries to the struct below */
+struct bdb_lvds_lfp_data_ptr {
+	u16 fp_timing_offset; /* offsets are from start of bdb */
+	u8 fp_table_size;
+	u16 dvo_timing_offset;
+	u8 dvo_table_size;
+	u16 panel_pnp_id_offset;
+	u8 pnp_table_size;
+} __packed;
+
+struct bdb_lvds_lfp_data_ptrs {
+	u8 lvds_entries; /* followed by one or more lvds_data_ptr structs */
+	struct bdb_lvds_lfp_data_ptr ptr[16];
+} __packed;
+
+/* LFP data has 3 blocks per entry */
+struct lvds_fp_timing {
+	u16 x_res;
+	u16 y_res;
+	u32 lvds_reg;
+	u32 lvds_reg_val;
+	u32 pp_on_reg;
+	u32 pp_on_reg_val;
+	u32 pp_off_reg;
+	u32 pp_off_reg_val;
+	u32 pp_cycle_reg;
+	u32 pp_cycle_reg_val;
+	u32 pfit_reg;
+	u32 pfit_reg_val;
+	u16 terminator;
+} __packed;
+
+struct lvds_dvo_timing {
+	u16 clock;		/**< In 10khz */
+	u8 hactive_lo;
+	u8 hblank_lo;
+	u8 hblank_hi:4;
+	u8 hactive_hi:4;
+	u8 vactive_lo;
+	u8 vblank_lo;
+	u8 vblank_hi:4;
+	u8 vactive_hi:4;
+	u8 hsync_off_lo;
+	u8 hsync_pulse_width;
+	u8 vsync_pulse_width:4;
+	u8 vsync_off:4;
+	u8 rsvd0:6;
+	u8 hsync_off_hi:2;
+	u8 himage_lo;
+	u8 vimage_lo;
+	u8 vimage_hi:4;
+	u8 himage_hi:4;
+	u8 h_border;
+	u8 v_border;
+	u8 rsvd1:3;
+	u8 digital:2;
+	u8 vsync_positive:1;
+	u8 hsync_positive:1;
+	u8 rsvd2:1;
+} __packed;
+
+struct lvds_pnp_id {
+	u16 mfg_name;
+	u16 product_code;
+	u32 serial;
+	u8 mfg_week;
+	u8 mfg_year;
+} __packed;
+
+struct bdb_lvds_lfp_data_entry {
+	struct lvds_fp_timing fp_timing;
+	struct lvds_dvo_timing dvo_timing;
+	struct lvds_pnp_id pnp_id;
+} __packed;
+
+struct bdb_lvds_lfp_data {
+	struct bdb_lvds_lfp_data_entry data[16];
+} __packed;
+
+#define BDB_BACKLIGHT_TYPE_NONE	0
+#define BDB_BACKLIGHT_TYPE_PWM	2
+
+struct bdb_lfp_backlight_data_entry {
+	u8 type:2;
+	u8 active_low_pwm:1;
+	u8 obsolete1:5;
+	u16 pwm_freq_hz;
+	u8 min_brightness;
+	u8 obsolete2;
+	u8 obsolete3;
+} __packed;
+
+struct bdb_lfp_backlight_data {
+	u8 entry_size;
+	struct bdb_lfp_backlight_data_entry data[16];
+	u8 level[16];
+} __packed;
+
+struct aimdb_header {
+	char signature[16];
+	char oem_device[20];
+	u16 aimdb_version;
+	u16 aimdb_header_size;
+	u16 aimdb_size;
+} __packed;
+
+struct aimdb_block {
+	u8 aimdb_id;
+	u16 aimdb_size;
+} __packed;
+
+struct vch_panel_data {
+	u16 fp_timing_offset;
+	u8 fp_timing_size;
+	u16 dvo_timing_offset;
+	u8 dvo_timing_size;
+	u16 text_fitting_offset;
+	u8 text_fitting_size;
+	u16 graphics_fitting_offset;
+	u8 graphics_fitting_size;
+} __packed;
+
+struct vch_bdb_22 {
+	struct aimdb_block aimdb_block;
+	struct vch_panel_data panels[16];
+} __packed;
+
+struct bdb_sdvo_lvds_options {
+	u8 panel_backlight;
+	u8 h40_set_panel_type;
+	u8 panel_type;
+	u8 ssc_clk_freq;
+	u16 als_low_trip;
+	u16 als_high_trip;
+	u8 sclalarcoeff_tab_row_num;
+	u8 sclalarcoeff_tab_row_size;
+	u8 coefficient[8];
+	u8 panel_misc_bits_1;
+	u8 panel_misc_bits_2;
+	u8 panel_misc_bits_3;
+	u8 panel_misc_bits_4;
+} __packed;
+
+
+#define BDB_DRIVER_FEATURE_NO_LVDS		0
+#define BDB_DRIVER_FEATURE_INT_LVDS		1
+#define BDB_DRIVER_FEATURE_SDVO_LVDS		2
+#define BDB_DRIVER_FEATURE_EDP			3
+
+struct bdb_driver_features {
+	u8 boot_dev_algorithm:1;
+	u8 block_display_switch:1;
+	u8 allow_display_switch:1;
+	u8 hotplug_dvo:1;
+	u8 dual_view_zoom:1;
+	u8 int15h_hook:1;
+	u8 sprite_in_clone:1;
+	u8 primary_lfp_id:1;
+
+	u16 boot_mode_x;
+	u16 boot_mode_y;
+	u8 boot_mode_bpp;
+	u8 boot_mode_refresh;
+
+	u16 enable_lfp_primary:1;
+	u16 selective_mode_pruning:1;
+	u16 dual_frequency:1;
+	u16 render_clock_freq:1; /* 0: high freq; 1: low freq */
+	u16 nt_clone_support:1;
+	u16 power_scheme_ui:1; /* 0: CUI; 1: 3rd party */
+	u16 sprite_display_assign:1; /* 0: secondary; 1: primary */
+	u16 cui_aspect_scaling:1;
+	u16 preserve_aspect_ratio:1;
+	u16 sdvo_device_power_down:1;
+	u16 crt_hotplug:1;
+	u16 lvds_config:2;
+	u16 tv_hotplug:1;
+	u16 hdmi_config:2;
+
+	u8 static_display:1;
+	u8 reserved2:7;
+	u16 legacy_crt_max_x;
+	u16 legacy_crt_max_y;
+	u8 legacy_crt_max_refresh;
+
+	u8 hdmi_termination;
+	u8 custom_vbt_version;
+	/* Driver features data block */
+	u16 rmpm_enabled:1;
+	u16 s2ddt_enabled:1;
+	u16 dpst_enabled:1;
+	u16 bltclt_enabled:1;
+	u16 adb_enabled:1;
+	u16 drrs_enabled:1;
+	u16 grs_enabled:1;
+	u16 gpmt_enabled:1;
+	u16 tbt_enabled:1;
+	u16 psr_enabled:1;
+	u16 ips_enabled:1;
+	u16 reserved3:4;
+	u16 pc_feature_valid:1;
+} __packed;
+
+#define EDP_18BPP	0
+#define EDP_24BPP	1
+#define EDP_30BPP	2
+#define EDP_RATE_1_62	0
+#define EDP_RATE_2_7	1
+#define EDP_LANE_1	0
+#define EDP_LANE_2	1
+#define EDP_LANE_4	3
+#define EDP_PREEMPHASIS_NONE	0
+#define EDP_PREEMPHASIS_3_5dB	1
+#define EDP_PREEMPHASIS_6dB	2
+#define EDP_PREEMPHASIS_9_5dB	3
+#define EDP_VSWING_0_4V		0
+#define EDP_VSWING_0_6V		1
+#define EDP_VSWING_0_8V		2
+#define EDP_VSWING_1_2V		3
+
+
+struct edp_link_params {
+	u8 rate:4;
+	u8 lanes:4;
+	u8 preemphasis:4;
+	u8 vswing:4;
+} __packed;
+
+struct bdb_edp {
+	struct edp_power_seq power_seqs[16];
+	u32 color_depth;
+	struct edp_link_params link_params[16];
+	u32 sdrrs_msa_timing_delay;
+
+	/* ith bit indicates enabled/disabled for (i+1)th panel */
+	u16 edp_s3d_feature;
+	u16 edp_t3_optimization;
+	u64 edp_vswing_preemph;		/* v173 */
+} __packed;
+
+struct psr_table {
+	/* Feature bits */
+	u8 full_link:1;
+	u8 require_aux_to_wakeup:1;
+	u8 feature_bits_rsvd:6;
+
+	/* Wait times */
+	u8 idle_frames:4;
+	u8 lines_to_wait:3;
+	u8 wait_times_rsvd:1;
+
+	/* TP wake up time in multiple of 100 */
+	u16 tp1_wakeup_time;
+	u16 tp2_tp3_wakeup_time;
+} __packed;
+
+struct bdb_psr {
+	struct psr_table psr_table[16];
+} __packed;
+
+/*
+ * Driver<->VBIOS interaction occurs through scratch bits in
+ * GR18 & SWF*.
+ */
+
+/* GR18 bits are set on display switch and hotkey events */
+#define GR18_DRIVER_SWITCH_EN	(1<<7) /* 0: VBIOS control, 1: driver control */
+#define GR18_HOTKEY_MASK	0x78 /* See also SWF4 15:0 */
+#define   GR18_HK_NONE		(0x0<<3)
+#define   GR18_HK_LFP_STRETCH	(0x1<<3)
+#define   GR18_HK_TOGGLE_DISP	(0x2<<3)
+#define   GR18_HK_DISP_SWITCH	(0x4<<3) /* see SWF14 15:0 for what to enable */
+#define   GR18_HK_POPUP_DISABLED (0x6<<3)
+#define   GR18_HK_POPUP_ENABLED	(0x7<<3)
+#define   GR18_HK_PFIT		(0x8<<3)
+#define   GR18_HK_APM_CHANGE	(0xa<<3)
+#define   GR18_HK_MULTIPLE	(0xc<<3)
+#define GR18_USER_INT_EN	(1<<2)
+#define GR18_A0000_FLUSH_EN	(1<<1)
+#define GR18_SMM_EN		(1<<0)
+
+/* Set by driver, cleared by VBIOS */
+#define SWF00_YRES_SHIFT	16
+#define SWF00_XRES_SHIFT	0
+#define SWF00_RES_MASK		0xffff
+
+/* Set by VBIOS at boot time and driver at runtime */
+#define SWF01_TV2_FORMAT_SHIFT	8
+#define SWF01_TV1_FORMAT_SHIFT	0
+#define SWF01_TV_FORMAT_MASK	0xffff
+
+#define SWF10_VBIOS_BLC_I2C_EN	(1<<29)
+#define SWF10_GTT_OVERRIDE_EN	(1<<28)
+#define SWF10_LFP_DPMS_OVR	(1<<27) /* override DPMS on display switch */
+#define SWF10_ACTIVE_TOGGLE_LIST_MASK (7<<24)
+#define   SWF10_OLD_TOGGLE	0x0
+#define   SWF10_TOGGLE_LIST_1	0x1
+#define   SWF10_TOGGLE_LIST_2	0x2
+#define   SWF10_TOGGLE_LIST_3	0x3
+#define   SWF10_TOGGLE_LIST_4	0x4
+#define SWF10_PANNING_EN	(1<<23)
+#define SWF10_DRIVER_LOADED	(1<<22)
+#define SWF10_EXTENDED_DESKTOP	(1<<21)
+#define SWF10_EXCLUSIVE_MODE	(1<<20)
+#define SWF10_OVERLAY_EN	(1<<19)
+#define SWF10_PLANEB_HOLDOFF	(1<<18)
+#define SWF10_PLANEA_HOLDOFF	(1<<17)
+#define SWF10_VGA_HOLDOFF	(1<<16)
+#define SWF10_ACTIVE_DISP_MASK	0xffff
+#define   SWF10_PIPEB_LFP2	(1<<15)
+#define   SWF10_PIPEB_EFP2	(1<<14)
+#define   SWF10_PIPEB_TV2	(1<<13)
+#define   SWF10_PIPEB_CRT2	(1<<12)
+#define   SWF10_PIPEB_LFP	(1<<11)
+#define   SWF10_PIPEB_EFP	(1<<10)
+#define   SWF10_PIPEB_TV	(1<<9)
+#define   SWF10_PIPEB_CRT	(1<<8)
+#define   SWF10_PIPEA_LFP2	(1<<7)
+#define   SWF10_PIPEA_EFP2	(1<<6)
+#define   SWF10_PIPEA_TV2	(1<<5)
+#define   SWF10_PIPEA_CRT2	(1<<4)
+#define   SWF10_PIPEA_LFP	(1<<3)
+#define   SWF10_PIPEA_EFP	(1<<2)
+#define   SWF10_PIPEA_TV	(1<<1)
+#define   SWF10_PIPEA_CRT	(1<<0)
+
+#define SWF11_MEMORY_SIZE_SHIFT	16
+#define SWF11_SV_TEST_EN	(1<<15)
+#define SWF11_IS_AGP		(1<<14)
+#define SWF11_DISPLAY_HOLDOFF	(1<<13)
+#define SWF11_DPMS_REDUCED	(1<<12)
+#define SWF11_IS_VBE_MODE	(1<<11)
+#define SWF11_PIPEB_ACCESS	(1<<10) /* 0 here means pipe a */
+#define SWF11_DPMS_MASK		0x07
+#define   SWF11_DPMS_OFF	(1<<2)
+#define   SWF11_DPMS_SUSPEND	(1<<1)
+#define   SWF11_DPMS_STANDBY	(1<<0)
+#define   SWF11_DPMS_ON		0
+
+#define SWF14_GFX_PFIT_EN	(1<<31)
+#define SWF14_TEXT_PFIT_EN	(1<<30)
+#define SWF14_LID_STATUS_CLOSED	(1<<29) /* 0 here means open */
+#define SWF14_POPUP_EN		(1<<28)
+#define SWF14_DISPLAY_HOLDOFF	(1<<27)
+#define SWF14_DISP_DETECT_EN	(1<<26)
+#define SWF14_DOCKING_STATUS_DOCKED (1<<25) /* 0 here means undocked */
+#define SWF14_DRIVER_STATUS	(1<<24)
+#define SWF14_OS_TYPE_WIN9X	(1<<23)
+#define SWF14_OS_TYPE_WINNT	(1<<22)
+/* 21:19 rsvd */
+#define SWF14_PM_TYPE_MASK	0x00070000
+#define   SWF14_PM_ACPI_VIDEO	(0x4 << 16)
+#define   SWF14_PM_ACPI		(0x3 << 16)
+#define   SWF14_PM_APM_12	(0x2 << 16)
+#define   SWF14_PM_APM_11	(0x1 << 16)
+#define SWF14_HK_REQUEST_MASK	0x0000ffff /* see GR18 6:3 for event type */
+          /* if GR18 indicates a display switch */
+#define   SWF14_DS_PIPEB_LFP2_EN (1<<15)
+#define   SWF14_DS_PIPEB_EFP2_EN (1<<14)
+#define   SWF14_DS_PIPEB_TV2_EN  (1<<13)
+#define   SWF14_DS_PIPEB_CRT2_EN (1<<12)
+#define   SWF14_DS_PIPEB_LFP_EN  (1<<11)
+#define   SWF14_DS_PIPEB_EFP_EN  (1<<10)
+#define   SWF14_DS_PIPEB_TV_EN   (1<<9)
+#define   SWF14_DS_PIPEB_CRT_EN  (1<<8)
+#define   SWF14_DS_PIPEA_LFP2_EN (1<<7)
+#define   SWF14_DS_PIPEA_EFP2_EN (1<<6)
+#define   SWF14_DS_PIPEA_TV2_EN  (1<<5)
+#define   SWF14_DS_PIPEA_CRT2_EN (1<<4)
+#define   SWF14_DS_PIPEA_LFP_EN  (1<<3)
+#define   SWF14_DS_PIPEA_EFP_EN  (1<<2)
+#define   SWF14_DS_PIPEA_TV_EN   (1<<1)
+#define   SWF14_DS_PIPEA_CRT_EN  (1<<0)
+          /* if GR18 indicates a panel fitting request */
+#define   SWF14_PFIT_EN		(1<<0) /* 0 means disable */
+          /* if GR18 indicates an APM change request */
+#define   SWF14_APM_HIBERNATE	0x4
+#define   SWF14_APM_SUSPEND	0x3
+#define   SWF14_APM_STANDBY	0x1
+#define   SWF14_APM_RESTORE	0x0
+
+/* Add the device class for LFP, TV, HDMI */
+#define	 DEVICE_TYPE_INT_LFP	0x1022
+#define	 DEVICE_TYPE_INT_TV	0x1009
+#define	 DEVICE_TYPE_HDMI	0x60D2
+#define	 DEVICE_TYPE_DP		0x68C6
+#define	 DEVICE_TYPE_DP_DUAL_MODE	0x60D6
+#define	 DEVICE_TYPE_eDP	0x78C6
+
+#define  DEVICE_TYPE_CLASS_EXTENSION	(1 << 15)
+#define  DEVICE_TYPE_POWER_MANAGEMENT	(1 << 14)
+#define  DEVICE_TYPE_HOTPLUG_SIGNALING	(1 << 13)
+#define  DEVICE_TYPE_INTERNAL_CONNECTOR	(1 << 12)
+#define  DEVICE_TYPE_NOT_HDMI_OUTPUT	(1 << 11)
+#define  DEVICE_TYPE_MIPI_OUTPUT	(1 << 10)
+#define  DEVICE_TYPE_COMPOSITE_OUTPUT	(1 << 9)
+#define  DEVICE_TYPE_DUAL_CHANNEL	(1 << 8)
+#define  DEVICE_TYPE_HIGH_SPEED_LINK	(1 << 6)
+#define  DEVICE_TYPE_LVDS_SINGALING	(1 << 5)
+#define  DEVICE_TYPE_TMDS_DVI_SIGNALING	(1 << 4)
+#define  DEVICE_TYPE_VIDEO_SIGNALING	(1 << 3)
+#define  DEVICE_TYPE_DISPLAYPORT_OUTPUT	(1 << 2)
+#define  DEVICE_TYPE_DIGITAL_OUTPUT	(1 << 1)
+#define  DEVICE_TYPE_ANALOG_OUTPUT	(1 << 0)
+
+/*
+ * Bits we care about when checking for DEVICE_TYPE_eDP
+ * Depending on the system, the other bits may or may not
+ * be set for eDP outputs.
+ */
+#define DEVICE_TYPE_eDP_BITS \
+	(DEVICE_TYPE_INTERNAL_CONNECTOR | \
+	 DEVICE_TYPE_MIPI_OUTPUT | \
+	 DEVICE_TYPE_COMPOSITE_OUTPUT | \
+	 DEVICE_TYPE_DUAL_CHANNEL | \
+	 DEVICE_TYPE_LVDS_SINGALING | \
+	 DEVICE_TYPE_TMDS_DVI_SIGNALING | \
+	 DEVICE_TYPE_VIDEO_SIGNALING | \
+	 DEVICE_TYPE_DISPLAYPORT_OUTPUT | \
+	 DEVICE_TYPE_ANALOG_OUTPUT)
+
+#define DEVICE_TYPE_DP_DUAL_MODE_BITS \
+	(DEVICE_TYPE_INTERNAL_CONNECTOR | \
+	 DEVICE_TYPE_MIPI_OUTPUT | \
+	 DEVICE_TYPE_COMPOSITE_OUTPUT | \
+	 DEVICE_TYPE_LVDS_SINGALING | \
+	 DEVICE_TYPE_TMDS_DVI_SIGNALING | \
+	 DEVICE_TYPE_VIDEO_SIGNALING | \
+	 DEVICE_TYPE_DISPLAYPORT_OUTPUT | \
+	 DEVICE_TYPE_DIGITAL_OUTPUT | \
+	 DEVICE_TYPE_ANALOG_OUTPUT)
+
+/* define the DVO port for HDMI output type */
+#define		DVO_B		1
+#define		DVO_C		2
+#define		DVO_D		3
+
+/* Possible values for the "DVO Port" field for versions >= 155: */
+#define DVO_PORT_HDMIA	0
+#define DVO_PORT_HDMIB	1
+#define DVO_PORT_HDMIC	2
+#define DVO_PORT_HDMID	3
+#define DVO_PORT_LVDS	4
+#define DVO_PORT_TV	5
+#define DVO_PORT_CRT	6
+#define DVO_PORT_DPB	7
+#define DVO_PORT_DPC	8
+#define DVO_PORT_DPD	9
+#define DVO_PORT_DPA	10
+#define DVO_PORT_DPE	11
+#define DVO_PORT_HDMIE	12
+#define DVO_PORT_MIPIA	21
+#define DVO_PORT_MIPIB	22
+#define DVO_PORT_MIPIC	23
+#define DVO_PORT_MIPID	24
+
+/* Block 52 contains MIPI configuration block
+ * 6 * bdb_mipi_config, followed by 6 pps data block
+ * block below
+ */
+#define MAX_MIPI_CONFIGURATIONS	6
+
+struct bdb_mipi_config {
+	struct mipi_config config[MAX_MIPI_CONFIGURATIONS];
+	struct mipi_pps_data pps[MAX_MIPI_CONFIGURATIONS];
+} __packed;
+
+/* Block 53 contains MIPI sequences as needed by the panel
+ * for enabling it. This block can be variable in size and
+ * can be maximum of 6 blocks
+ */
+struct bdb_mipi_sequence {
+	u8 version;
+	u8 data[0];
+} __packed;
+
+enum mipi_gpio_pin_index {
+	MIPI_GPIO_UNDEFINED = 0,
+	MIPI_GPIO_PANEL_ENABLE,
+	MIPI_GPIO_BL_ENABLE,
+	MIPI_GPIO_PWM_ENABLE,
+	MIPI_GPIO_RESET_N,
+	MIPI_GPIO_PWR_DOWN_R,
+	MIPI_GPIO_STDBY_RST_N,
+	MIPI_GPIO_MAX
+};
+
+#endif /* _INTEL_VBT_DEFS_H_ */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/Kconfig linux-libre-4.7-gnu/drivers/gpu/drm/i915/Kconfig
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -56,3 +56,9 @@ config DRM_I915_USERPTR
 	  selected to enabled full userptr support.
 
 	  If in doubt, say "Y".
+
+menu "drm/i915 Debugging"
+depends on DRM_I915
+depends on EXPERT
+source drivers/gpu/drm/i915/Kconfig.debug
+endmenu
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/Kconfig.debug linux-libre-4.7-gnu/drivers/gpu/drm/i915/Kconfig.debug
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/Kconfig.debug	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/Kconfig.debug	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,41 @@
+config DRM_I915_WERROR
+        bool "Force GCC to throw an error instead of a warning when compiling"
+        # As this may inadvertently break the build, only allow the user
+        # to shoot oneself in the foot iff they aim really hard
+        depends on EXPERT
+        # We use the dependency on !COMPILE_TEST to not be enabled in
+        # allmodconfig or allyesconfig configurations
+        depends on !COMPILE_TEST
+        default n
+        help
+          Add -Werror to the build flags for (and only for) i915.ko.
+          Do not enable this unless you are writing code for the i915.ko module.
+
+          Recommended for driver developers only.
+
+          If in doubt, say "N".
+
+config DRM_I915_DEBUG
+        bool "Enable additional driver debugging"
+        depends on DRM_I915
+        default n
+        help
+          Choose this option to turn on extra driver debugging that may affect
+          performance but will catch some internal issues.
+
+          Recommended for driver developers only.
+
+          If in doubt, say "N".
+
+config DRM_I915_DEBUG_GEM
+        bool "Insert extra checks into the GEM internals"
+        default n
+        depends on DRM_I915_WERROR
+        help
+          Enable extra sanity checks (including BUGs) along the GEM driver
+          paths that may slow the system down and if hit hang the machine.
+
+          Recommended for driver developers only.
+
+          If in doubt, say "N".
+
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/i915/Makefile linux-libre-4.7-gnu/drivers/gpu/drm/i915/Makefile
--- linux-libre-4.6-gnu/drivers/gpu/drm/i915/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/i915/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -2,6 +2,8 @@
 # Makefile for the drm device driver.  This driver provides support for the
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
 
+subdir-ccflags-$(CONFIG_DRM_I915_WERROR) := -Werror
+
 # Please keep these build lists sorted!
 
 # core driver code
@@ -55,7 +57,9 @@ i915-y += intel_audio.o \
 	  intel_atomic.o \
 	  intel_atomic_plane.o \
 	  intel_bios.o \
+	  intel_color.o \
 	  intel_display.o \
+	  intel_dpll_mgr.o \
 	  intel_fbc.o \
 	  intel_fifo_underrun.o \
 	  intel_frontbuffer.o \
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/imx/imx-drm-core.c linux-libre-4.7-gnu/drivers/gpu/drm/imx/imx-drm-core.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/imx/imx-drm-core.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/imx/imx-drm-core.c	2016-07-24 15:23:50.000000000 -0400
@@ -25,6 +25,7 @@
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_of.h>
+#include <video/imx-ipu-v3.h>
 
 #include "imx-drm.h"
 
@@ -96,8 +97,8 @@ static struct imx_drm_crtc *imx_drm_find
 	return NULL;
 }
 
-int imx_drm_set_bus_format_pins(struct drm_encoder *encoder, u32 bus_format,
-		int hsync_pin, int vsync_pin)
+int imx_drm_set_bus_config(struct drm_encoder *encoder, u32 bus_format,
+		int hsync_pin, int vsync_pin, u32 bus_flags)
 {
 	struct imx_drm_crtc_helper_funcs *helper;
 	struct imx_drm_crtc *imx_crtc;
@@ -109,14 +110,17 @@ int imx_drm_set_bus_format_pins(struct d
 	helper = &imx_crtc->imx_drm_helper_funcs;
 	if (helper->set_interface_pix_fmt)
 		return helper->set_interface_pix_fmt(encoder->crtc,
-					bus_format, hsync_pin, vsync_pin);
+					bus_format, hsync_pin, vsync_pin,
+					bus_flags);
 	return 0;
 }
-EXPORT_SYMBOL_GPL(imx_drm_set_bus_format_pins);
+EXPORT_SYMBOL_GPL(imx_drm_set_bus_config);
 
 int imx_drm_set_bus_format(struct drm_encoder *encoder, u32 bus_format)
 {
-	return imx_drm_set_bus_format_pins(encoder, bus_format, 2, 3);
+	return imx_drm_set_bus_config(encoder, bus_format, 2, 3,
+				      DRM_BUS_FLAG_DE_HIGH |
+				      DRM_BUS_FLAG_PIXDATA_NEGEDGE);
 }
 EXPORT_SYMBOL_GPL(imx_drm_set_bus_format);
 
@@ -252,13 +256,6 @@ static int imx_drm_driver_load(struct dr
 	if (ret)
 		goto err_kms;
 
-	/*
-	 * with vblank_disable_allowed = true, vblank interrupt will be
-	 * disabled by drm timer once a current process gives up ownership
-	 * of vblank event. (after drm_vblank_put function is called)
-	 */
-	drm->vblank_disable_allowed = true;
-
 	platform_set_drvdata(drm->platformdev, drm);
 
 	/* Now try and bind all our sub-components */
@@ -411,7 +408,7 @@ static struct drm_driver imx_drm_driver
 	.unload			= imx_drm_driver_unload,
 	.lastclose		= imx_drm_driver_lastclose,
 	.set_busid		= drm_platform_set_busid,
-	.gem_free_object	= drm_gem_cma_free_object,
+	.gem_free_object_unlocked = drm_gem_cma_free_object,
 	.gem_vm_ops		= &drm_gem_cma_vm_ops,
 	.dumb_create		= drm_gem_cma_dumb_create,
 	.dumb_map_offset	= drm_gem_cma_dumb_map_offset,
@@ -444,6 +441,13 @@ static int compare_of(struct device *dev
 {
 	struct device_node *np = data;
 
+	/* Special case for DI, dev->of_node may not be set yet */
+	if (strcmp(dev->driver->name, "imx-ipuv3-crtc") == 0) {
+		struct ipu_client_platformdata *pdata = dev->platform_data;
+
+		return pdata->of_node == np;
+	}
+
 	/* Special case for LDB, one device for two channels */
 	if (of_node_cmp(np->name, "lvds-channel") == 0) {
 		np = of_get_parent(np);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/imx/imx-drm.h linux-libre-4.7-gnu/drivers/gpu/drm/imx/imx-drm.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/imx/imx-drm.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/imx/imx-drm.h	2016-07-24 15:23:50.000000000 -0400
@@ -19,7 +19,8 @@ struct imx_drm_crtc_helper_funcs {
 	int (*enable_vblank)(struct drm_crtc *crtc);
 	void (*disable_vblank)(struct drm_crtc *crtc);
 	int (*set_interface_pix_fmt)(struct drm_crtc *crtc,
-			u32 bus_format, int hsync_pin, int vsync_pin);
+			u32 bus_format, int hsync_pin, int vsync_pin,
+			u32 bus_flags);
 	const struct drm_crtc_helper_funcs *crtc_helper_funcs;
 	const struct drm_crtc_funcs *crtc_funcs;
 };
@@ -41,8 +42,8 @@ void imx_drm_mode_config_init(struct drm
 
 struct drm_gem_cma_object *imx_drm_fb_get_obj(struct drm_framebuffer *fb);
 
-int imx_drm_set_bus_format_pins(struct drm_encoder *encoder,
-		u32 bus_format, int hsync_pin, int vsync_pin);
+int imx_drm_set_bus_config(struct drm_encoder *encoder, u32 bus_format,
+		int hsync_pin, int vsync_pin, u32 bus_flags);
 int imx_drm_set_bus_format(struct drm_encoder *encoder,
 		u32 bus_format);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/imx/imx-ldb.c linux-libre-4.7-gnu/drivers/gpu/drm/imx/imx-ldb.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/imx/imx-ldb.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/imx/imx-ldb.c	2016-07-24 15:23:50.000000000 -0400
@@ -25,6 +25,7 @@
 #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
 #include <linux/of_device.h>
 #include <linux/of_graph.h>
+#include <video/of_display_timing.h>
 #include <video/of_videomode.h>
 #include <linux/regmap.h>
 #include <linux/videodev2.h>
@@ -59,6 +60,7 @@ struct imx_ldb_channel {
 	struct drm_encoder encoder;
 	struct drm_panel *panel;
 	struct device_node *child;
+	struct i2c_adapter *ddc;
 	int chno;
 	void *edid;
 	int edid_len;
@@ -107,6 +109,9 @@ static int imx_ldb_connector_get_modes(s
 			return num_modes;
 	}
 
+	if (!imx_ldb_ch->edid && imx_ldb_ch->ddc)
+		imx_ldb_ch->edid = drm_get_edid(connector, imx_ldb_ch->ddc);
+
 	if (imx_ldb_ch->edid) {
 		drm_mode_connector_update_edid_property(connector,
 							imx_ldb_ch->edid);
@@ -553,7 +558,8 @@ static int imx_ldb_bind(struct device *d
 
 	for_each_child_of_node(np, child) {
 		struct imx_ldb_channel *channel;
-		struct device_node *port;
+		struct device_node *ddc_node;
+		struct device_node *ep;
 
 		ret = of_property_read_u32(child, "reg", &i);
 		if (ret || i < 0 || i > 1)
@@ -576,33 +582,54 @@ static int imx_ldb_bind(struct device *d
 		 * The output port is port@4 with an external 4-port mux or
 		 * port@2 with the internal 2-port mux.
 		 */
-		port = of_graph_get_port_by_id(child, imx_ldb->lvds_mux ? 4 : 2);
-		if (port) {
-			struct device_node *endpoint, *remote;
+		ep = of_graph_get_endpoint_by_regs(child,
+						   imx_ldb->lvds_mux ? 4 : 2,
+						   -1);
+		if (ep) {
+			struct device_node *remote;
 
-			endpoint = of_get_child_by_name(port, "endpoint");
-			if (endpoint) {
-				remote = of_graph_get_remote_port_parent(endpoint);
-				if (remote)
-					channel->panel = of_drm_find_panel(remote);
-				else
-					return -EPROBE_DEFER;
-				if (!channel->panel) {
-					dev_err(dev, "panel not found: %s\n",
-						remote->full_name);
-					return -EPROBE_DEFER;
-				}
+			remote = of_graph_get_remote_port_parent(ep);
+			of_node_put(ep);
+			if (remote)
+				channel->panel = of_drm_find_panel(remote);
+			else
+				return -EPROBE_DEFER;
+			of_node_put(remote);
+			if (!channel->panel) {
+				dev_err(dev, "panel not found: %s\n",
+					remote->full_name);
+				return -EPROBE_DEFER;
 			}
 		}
 
-		edidp = of_get_property(child, "edid", &channel->edid_len);
-		if (edidp) {
-			channel->edid = kmemdup(edidp, channel->edid_len,
-						GFP_KERNEL);
-		} else if (!channel->panel) {
-			ret = of_get_drm_display_mode(child, &channel->mode, 0);
-			if (!ret)
-				channel->mode_valid = 1;
+		ddc_node = of_parse_phandle(child, "ddc-i2c-bus", 0);
+		if (ddc_node) {
+			channel->ddc = of_find_i2c_adapter_by_node(ddc_node);
+			of_node_put(ddc_node);
+			if (!channel->ddc) {
+				dev_warn(dev, "failed to get ddc i2c adapter\n");
+				return -EPROBE_DEFER;
+			}
+		}
+
+		if (!channel->ddc) {
+			/* if no DDC available, fallback to hardcoded EDID */
+			dev_dbg(dev, "no ddc available\n");
+
+			edidp = of_get_property(child, "edid",
+						&channel->edid_len);
+			if (edidp) {
+				channel->edid = kmemdup(edidp,
+							channel->edid_len,
+							GFP_KERNEL);
+			} else if (!channel->panel) {
+				/* fallback to display-timings node */
+				ret = of_get_drm_display_mode(child,
+							      &channel->mode,
+							      OF_USE_NATIVE_MODE);
+				if (!ret)
+					channel->mode_valid = 1;
+			}
 		}
 
 		channel->bus_format = of_get_bus_format(dev, child);
@@ -647,6 +674,7 @@ static void imx_ldb_unbind(struct device
 		channel->encoder.funcs->destroy(&channel->encoder);
 
 		kfree(channel->edid);
+		i2c_put_adapter(channel->ddc);
 	}
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/imx/imx-tve.c linux-libre-4.7-gnu/drivers/gpu/drm/imx/imx-tve.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/imx/imx-tve.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/imx/imx-tve.c	2016-07-24 15:23:50.000000000 -0400
@@ -294,8 +294,10 @@ static void imx_tve_encoder_prepare(stru
 
 	switch (tve->mode) {
 	case TVE_MODE_VGA:
-		imx_drm_set_bus_format_pins(encoder, MEDIA_BUS_FMT_GBR888_1X24,
-					    tve->hsync_pin, tve->vsync_pin);
+		imx_drm_set_bus_config(encoder, MEDIA_BUS_FMT_GBR888_1X24,
+				       tve->hsync_pin, tve->vsync_pin,
+				       DRM_BUS_FLAG_DE_HIGH |
+				       DRM_BUS_FLAG_PIXDATA_NEGEDGE);
 		break;
 	case TVE_MODE_TVOUT:
 		imx_drm_set_bus_format(encoder, MEDIA_BUS_FMT_YUV8_1X24);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/imx/ipuv3-crtc.c linux-libre-4.7-gnu/drivers/gpu/drm/imx/ipuv3-crtc.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/imx/ipuv3-crtc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/imx/ipuv3-crtc.c	2016-07-24 15:23:50.000000000 -0400
@@ -66,6 +66,7 @@ struct ipu_crtc {
 	struct ipu_flip_work	*flip_work;
 	int			irq;
 	u32			bus_format;
+	u32			bus_flags;
 	int			di_hsync_pin;
 	int			di_vsync_pin;
 };
@@ -271,8 +272,10 @@ static int ipu_crtc_mode_set(struct drm_
 	else
 		sig_cfg.clkflags = 0;
 
-	sig_cfg.enable_pol = 1;
-	sig_cfg.clk_pol = 0;
+	sig_cfg.enable_pol = !(ipu_crtc->bus_flags & DRM_BUS_FLAG_DE_LOW);
+	/* Default to driving pixel data on negative clock edges */
+	sig_cfg.clk_pol = !!(ipu_crtc->bus_flags &
+			     DRM_BUS_FLAG_PIXDATA_POSEDGE);
 	sig_cfg.bus_format = ipu_crtc->bus_format;
 	sig_cfg.v_to_h_sync = 0;
 	sig_cfg.hsync_pin = ipu_crtc->di_hsync_pin;
@@ -396,11 +399,12 @@ static void ipu_disable_vblank(struct dr
 }
 
 static int ipu_set_interface_pix_fmt(struct drm_crtc *crtc,
-		u32 bus_format, int hsync_pin, int vsync_pin)
+		u32 bus_format, int hsync_pin, int vsync_pin, u32 bus_flags)
 {
 	struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc);
 
 	ipu_crtc->bus_format = bus_format;
+	ipu_crtc->bus_flags = bus_flags;
 	ipu_crtc->di_hsync_pin = hsync_pin;
 	ipu_crtc->di_vsync_pin = vsync_pin;
 
@@ -473,7 +477,7 @@ static int ipu_crtc_init(struct ipu_crtc
 
 	ret = imx_drm_add_crtc(drm, &ipu_crtc->base, &ipu_crtc->imx_crtc,
 			&ipu_crtc->plane[0]->base, &ipu_crtc_helper_funcs,
-			ipu_crtc->dev->of_node);
+			pdata->of_node);
 	if (ret) {
 		dev_err(ipu_crtc->dev, "adding crtc failed with %d.\n", ret);
 		goto err_put_resources;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/imx/ipuv3-plane.c linux-libre-4.7-gnu/drivers/gpu/drm/imx/ipuv3-plane.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/imx/ipuv3-plane.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/imx/ipuv3-plane.c	2016-07-24 15:23:50.000000000 -0400
@@ -38,6 +38,8 @@ static const uint32_t ipu_plane_formats[
 	DRM_FORMAT_RGBX8888,
 	DRM_FORMAT_BGRA8888,
 	DRM_FORMAT_BGRA8888,
+	DRM_FORMAT_UYVY,
+	DRM_FORMAT_VYUY,
 	DRM_FORMAT_YUYV,
 	DRM_FORMAT_YVYU,
 	DRM_FORMAT_YUV420,
@@ -428,7 +430,6 @@ static int ipu_update_plane(struct drm_p
 	if (crtc != plane->crtc)
 		dev_dbg(plane->dev->dev, "crtc change: %p -> %p\n",
 				plane->crtc, crtc);
-	plane->crtc = crtc;
 
 	if (!ipu_plane->enabled)
 		ipu_plane_enable(ipu_plane);
@@ -461,7 +462,7 @@ static void ipu_plane_destroy(struct drm
 	kfree(ipu_plane);
 }
 
-static struct drm_plane_funcs ipu_plane_funcs = {
+static const struct drm_plane_funcs ipu_plane_funcs = {
 	.update_plane	= ipu_update_plane,
 	.disable_plane	= ipu_disable_plane,
 	.destroy	= ipu_plane_destroy,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/imx/parallel-display.c linux-libre-4.7-gnu/drivers/gpu/drm/imx/parallel-display.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/imx/parallel-display.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/imx/parallel-display.c	2016-07-24 15:23:50.000000000 -0400
@@ -35,7 +35,6 @@ struct imx_parallel_display {
 	void *edid;
 	int edid_len;
 	u32 bus_format;
-	int mode_valid;
 	struct drm_display_mode mode;
 	struct drm_panel *panel;
 };
@@ -68,17 +67,6 @@ static int imx_pd_connector_get_modes(st
 		num_modes = drm_add_edid_modes(connector, imxpd->edid);
 	}
 
-	if (imxpd->mode_valid) {
-		struct drm_display_mode *mode = drm_mode_create(connector->dev);
-
-		if (!mode)
-			return -EINVAL;
-		drm_mode_copy(mode, &imxpd->mode);
-		mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
-		drm_mode_probed_add(connector, mode);
-		num_modes++;
-	}
-
 	if (np) {
 		struct drm_display_mode *mode = drm_mode_create(connector->dev);
 
@@ -115,8 +103,8 @@ static void imx_pd_encoder_dpms(struct d
 static void imx_pd_encoder_prepare(struct drm_encoder *encoder)
 {
 	struct imx_parallel_display *imxpd = enc_to_imxpd(encoder);
-
-	imx_drm_set_bus_format(encoder, imxpd->bus_format);
+	imx_drm_set_bus_config(encoder, imxpd->bus_format, 2, 3,
+			       imxpd->connector.display_info.bus_flags);
 }
 
 static void imx_pd_encoder_commit(struct drm_encoder *encoder)
@@ -203,7 +191,7 @@ static int imx_pd_bind(struct device *de
 {
 	struct drm_device *drm = data;
 	struct device_node *np = dev->of_node;
-	struct device_node *port;
+	struct device_node *ep;
 	const u8 *edidp;
 	struct imx_parallel_display *imxpd;
 	int ret;
@@ -230,18 +218,18 @@ static int imx_pd_bind(struct device *de
 	}
 
 	/* port@1 is the output port */
-	port = of_graph_get_port_by_id(np, 1);
-	if (port) {
-		struct device_node *endpoint, *remote;
+	ep = of_graph_get_endpoint_by_regs(np, 1, -1);
+	if (ep) {
+		struct device_node *remote;
 
-		endpoint = of_get_child_by_name(port, "endpoint");
-		if (endpoint) {
-			remote = of_graph_get_remote_port_parent(endpoint);
-			if (remote)
-				imxpd->panel = of_drm_find_panel(remote);
-			if (!imxpd->panel)
-				return -EPROBE_DEFER;
+		remote = of_graph_get_remote_port_parent(ep);
+		of_node_put(ep);
+		if (remote) {
+			imxpd->panel = of_drm_find_panel(remote);
+			of_node_put(remote);
 		}
+		if (!imxpd->panel)
+			return -EPROBE_DEFER;
 	}
 
 	imxpd->dev = dev;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/Kconfig linux-libre-4.7-gnu/drivers/gpu/drm/Kconfig
--- linux-libre-4.6-gnu/drivers/gpu/drm/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -52,6 +52,7 @@ config DRM_KMS_FB_HELPER
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
+	select FB_DEFERRED_IO
 	help
 	  FBDEV helpers for KMS drivers.
 
@@ -252,6 +253,8 @@ source "drivers/gpu/drm/rcar-du/Kconfig"
 
 source "drivers/gpu/drm/shmobile/Kconfig"
 
+source "drivers/gpu/drm/sun4i/Kconfig"
+
 source "drivers/gpu/drm/omapdrm/Kconfig"
 
 source "drivers/gpu/drm/tilcdc/Kconfig"
@@ -281,3 +284,9 @@ source "drivers/gpu/drm/imx/Kconfig"
 source "drivers/gpu/drm/vc4/Kconfig"
 
 source "drivers/gpu/drm/etnaviv/Kconfig"
+
+source "drivers/gpu/drm/arc/Kconfig"
+
+source "drivers/gpu/drm/hisilicon/Kconfig"
+
+source "drivers/gpu/drm/mediatek/Kconfig"
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/Makefile linux-libre-4.7-gnu/drivers/gpu/drm/Makefile
--- linux-libre-4.6-gnu/drivers/gpu/drm/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -1,4 +1,4 @@
-#
+
 # Makefile for the drm device driver.  This driver provides support for the
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
 
@@ -23,7 +23,7 @@ drm-$(CONFIG_AGP) += drm_agpsupport.o
 
 drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \
 		drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \
-		drm_kms_helper_common.o
+		drm_kms_helper_common.o drm_dp_dual_mode_helper.o
 
 drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
 drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o
@@ -65,6 +65,7 @@ obj-$(CONFIG_DRM_ATMEL_HLCDC)	+= atmel-h
 obj-$(CONFIG_DRM_RCAR_DU) += rcar-du/
 obj-$(CONFIG_DRM_SHMOBILE) +=shmobile/
 obj-y			+= omapdrm/
+obj-$(CONFIG_DRM_SUN4I) += sun4i/
 obj-y			+= tilcdc/
 obj-$(CONFIG_DRM_QXL) += qxl/
 obj-$(CONFIG_DRM_BOCHS) += bochs/
@@ -73,8 +74,11 @@ obj-$(CONFIG_DRM_MSM) += msm/
 obj-$(CONFIG_DRM_TEGRA) += tegra/
 obj-$(CONFIG_DRM_STI) += sti/
 obj-$(CONFIG_DRM_IMX) += imx/
+obj-$(CONFIG_DRM_MEDIATEK) += mediatek/
 obj-y			+= i2c/
 obj-y			+= panel/
 obj-y			+= bridge/
 obj-$(CONFIG_DRM_FSL_DCU) += fsl-dcu/
 obj-$(CONFIG_DRM_ETNAVIV) += etnaviv/
+obj-$(CONFIG_DRM_ARCPGU)+= arc/
+obj-y			+= hisilicon/
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/Kconfig linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/Kconfig
--- linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,16 @@
+config DRM_MEDIATEK
+	tristate "DRM Support for Mediatek SoCs"
+	depends on DRM
+	depends on ARCH_MEDIATEK || (ARM && COMPILE_TEST)
+	select DRM_GEM_CMA_HELPER
+	select DRM_KMS_HELPER
+	select DRM_MIPI_DSI
+	select DRM_PANEL
+	select IOMMU_DMA
+	select MEMORY
+	select MTK_SMI
+	help
+	  Choose this option if you have a Mediatek SoCs.
+	  The module will be called mediatek-drm
+	  This driver provides kernel mode setting and
+	  buffer management to userspace.
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/Makefile linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/Makefile
--- linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,14 @@
+mediatek-drm-y := mtk_disp_ovl.o \
+		  mtk_disp_rdma.o \
+		  mtk_drm_crtc.o \
+		  mtk_drm_ddp.o \
+		  mtk_drm_ddp_comp.o \
+		  mtk_drm_drv.o \
+		  mtk_drm_fb.o \
+		  mtk_drm_gem.o \
+		  mtk_drm_plane.o \
+		  mtk_dsi.o \
+		  mtk_mipi_tx.o \
+		  mtk_dpi.o
+
+obj-$(CONFIG_DRM_MEDIATEK) += mediatek-drm.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_disp_ovl.c linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_disp_ovl.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_disp_ovl.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,302 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include <drm/drmP.h>
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+
+#include "mtk_drm_crtc.h"
+#include "mtk_drm_ddp_comp.h"
+
+#define DISP_REG_OVL_INTEN			0x0004
+#define OVL_FME_CPL_INT					BIT(1)
+#define DISP_REG_OVL_INTSTA			0x0008
+#define DISP_REG_OVL_EN				0x000c
+#define DISP_REG_OVL_RST			0x0014
+#define DISP_REG_OVL_ROI_SIZE			0x0020
+#define DISP_REG_OVL_ROI_BGCLR			0x0028
+#define DISP_REG_OVL_SRC_CON			0x002c
+#define DISP_REG_OVL_CON(n)			(0x0030 + 0x20 * (n))
+#define DISP_REG_OVL_SRC_SIZE(n)		(0x0038 + 0x20 * (n))
+#define DISP_REG_OVL_OFFSET(n)			(0x003c + 0x20 * (n))
+#define DISP_REG_OVL_PITCH(n)			(0x0044 + 0x20 * (n))
+#define DISP_REG_OVL_RDMA_CTRL(n)		(0x00c0 + 0x20 * (n))
+#define DISP_REG_OVL_RDMA_GMC(n)		(0x00c8 + 0x20 * (n))
+#define DISP_REG_OVL_ADDR(n)			(0x0f40 + 0x20 * (n))
+
+#define	OVL_RDMA_MEM_GMC	0x40402020
+
+#define OVL_CON_BYTE_SWAP	BIT(24)
+#define OVL_CON_CLRFMT_RGB565	(0 << 12)
+#define OVL_CON_CLRFMT_RGB888	(1 << 12)
+#define OVL_CON_CLRFMT_RGBA8888	(2 << 12)
+#define OVL_CON_CLRFMT_ARGB8888	(3 << 12)
+#define	OVL_CON_AEN		BIT(8)
+#define	OVL_CON_ALPHA		0xff
+
+/**
+ * struct mtk_disp_ovl - DISP_OVL driver structure
+ * @ddp_comp - structure containing type enum and hardware resources
+ * @crtc - associated crtc to report vblank events to
+ */
+struct mtk_disp_ovl {
+	struct mtk_ddp_comp		ddp_comp;
+	struct drm_crtc			*crtc;
+};
+
+static irqreturn_t mtk_disp_ovl_irq_handler(int irq, void *dev_id)
+{
+	struct mtk_disp_ovl *priv = dev_id;
+	struct mtk_ddp_comp *ovl = &priv->ddp_comp;
+
+	/* Clear frame completion interrupt */
+	writel(0x0, ovl->regs + DISP_REG_OVL_INTSTA);
+
+	if (!priv->crtc)
+		return IRQ_NONE;
+
+	mtk_crtc_ddp_irq(priv->crtc, ovl);
+
+	return IRQ_HANDLED;
+}
+
+static void mtk_ovl_enable_vblank(struct mtk_ddp_comp *comp,
+				  struct drm_crtc *crtc)
+{
+	struct mtk_disp_ovl *priv = container_of(comp, struct mtk_disp_ovl,
+						 ddp_comp);
+
+	priv->crtc = crtc;
+	writel_relaxed(OVL_FME_CPL_INT, comp->regs + DISP_REG_OVL_INTEN);
+}
+
+static void mtk_ovl_disable_vblank(struct mtk_ddp_comp *comp)
+{
+	struct mtk_disp_ovl *priv = container_of(comp, struct mtk_disp_ovl,
+						 ddp_comp);
+
+	priv->crtc = NULL;
+	writel_relaxed(0x0, comp->regs + DISP_REG_OVL_INTEN);
+}
+
+static void mtk_ovl_start(struct mtk_ddp_comp *comp)
+{
+	writel_relaxed(0x1, comp->regs + DISP_REG_OVL_EN);
+}
+
+static void mtk_ovl_stop(struct mtk_ddp_comp *comp)
+{
+	writel_relaxed(0x0, comp->regs + DISP_REG_OVL_EN);
+}
+
+static void mtk_ovl_config(struct mtk_ddp_comp *comp, unsigned int w,
+			   unsigned int h, unsigned int vrefresh)
+{
+	if (w != 0 && h != 0)
+		writel_relaxed(h << 16 | w, comp->regs + DISP_REG_OVL_ROI_SIZE);
+	writel_relaxed(0x0, comp->regs + DISP_REG_OVL_ROI_BGCLR);
+
+	writel(0x1, comp->regs + DISP_REG_OVL_RST);
+	writel(0x0, comp->regs + DISP_REG_OVL_RST);
+}
+
+static void mtk_ovl_layer_on(struct mtk_ddp_comp *comp, unsigned int idx)
+{
+	unsigned int reg;
+
+	writel(0x1, comp->regs + DISP_REG_OVL_RDMA_CTRL(idx));
+	writel(OVL_RDMA_MEM_GMC, comp->regs + DISP_REG_OVL_RDMA_GMC(idx));
+
+	reg = readl(comp->regs + DISP_REG_OVL_SRC_CON);
+	reg = reg | BIT(idx);
+	writel(reg, comp->regs + DISP_REG_OVL_SRC_CON);
+}
+
+static void mtk_ovl_layer_off(struct mtk_ddp_comp *comp, unsigned int idx)
+{
+	unsigned int reg;
+
+	reg = readl(comp->regs + DISP_REG_OVL_SRC_CON);
+	reg = reg & ~BIT(idx);
+	writel(reg, comp->regs + DISP_REG_OVL_SRC_CON);
+
+	writel(0x0, comp->regs + DISP_REG_OVL_RDMA_CTRL(idx));
+}
+
+static unsigned int ovl_fmt_convert(unsigned int fmt)
+{
+	switch (fmt) {
+	default:
+	case DRM_FORMAT_RGB565:
+		return OVL_CON_CLRFMT_RGB565;
+	case DRM_FORMAT_BGR565:
+		return OVL_CON_CLRFMT_RGB565 | OVL_CON_BYTE_SWAP;
+	case DRM_FORMAT_RGB888:
+		return OVL_CON_CLRFMT_RGB888;
+	case DRM_FORMAT_BGR888:
+		return OVL_CON_CLRFMT_RGB888 | OVL_CON_BYTE_SWAP;
+	case DRM_FORMAT_RGBX8888:
+	case DRM_FORMAT_RGBA8888:
+		return OVL_CON_CLRFMT_ARGB8888;
+	case DRM_FORMAT_BGRX8888:
+	case DRM_FORMAT_BGRA8888:
+		return OVL_CON_CLRFMT_ARGB8888 | OVL_CON_BYTE_SWAP;
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_ARGB8888:
+		return OVL_CON_CLRFMT_RGBA8888;
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_ABGR8888:
+		return OVL_CON_CLRFMT_RGBA8888 | OVL_CON_BYTE_SWAP;
+	}
+}
+
+static void mtk_ovl_layer_config(struct mtk_ddp_comp *comp, unsigned int idx,
+				 struct mtk_plane_state *state)
+{
+	struct mtk_plane_pending_state *pending = &state->pending;
+	unsigned int addr = pending->addr;
+	unsigned int pitch = pending->pitch & 0xffff;
+	unsigned int fmt = pending->format;
+	unsigned int offset = (pending->y << 16) | pending->x;
+	unsigned int src_size = (pending->height << 16) | pending->width;
+	unsigned int con;
+
+	if (!pending->enable)
+		mtk_ovl_layer_off(comp, idx);
+
+	con = ovl_fmt_convert(fmt);
+	if (idx != 0)
+		con |= OVL_CON_AEN | OVL_CON_ALPHA;
+
+	writel_relaxed(con, comp->regs + DISP_REG_OVL_CON(idx));
+	writel_relaxed(pitch, comp->regs + DISP_REG_OVL_PITCH(idx));
+	writel_relaxed(src_size, comp->regs + DISP_REG_OVL_SRC_SIZE(idx));
+	writel_relaxed(offset, comp->regs + DISP_REG_OVL_OFFSET(idx));
+	writel_relaxed(addr, comp->regs + DISP_REG_OVL_ADDR(idx));
+
+	if (pending->enable)
+		mtk_ovl_layer_on(comp, idx);
+}
+
+static const struct mtk_ddp_comp_funcs mtk_disp_ovl_funcs = {
+	.config = mtk_ovl_config,
+	.start = mtk_ovl_start,
+	.stop = mtk_ovl_stop,
+	.enable_vblank = mtk_ovl_enable_vblank,
+	.disable_vblank = mtk_ovl_disable_vblank,
+	.layer_on = mtk_ovl_layer_on,
+	.layer_off = mtk_ovl_layer_off,
+	.layer_config = mtk_ovl_layer_config,
+};
+
+static int mtk_disp_ovl_bind(struct device *dev, struct device *master,
+			     void *data)
+{
+	struct mtk_disp_ovl *priv = dev_get_drvdata(dev);
+	struct drm_device *drm_dev = data;
+	int ret;
+
+	ret = mtk_ddp_comp_register(drm_dev, &priv->ddp_comp);
+	if (ret < 0) {
+		dev_err(dev, "Failed to register component %s: %d\n",
+			dev->of_node->full_name, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void mtk_disp_ovl_unbind(struct device *dev, struct device *master,
+				void *data)
+{
+	struct mtk_disp_ovl *priv = dev_get_drvdata(dev);
+	struct drm_device *drm_dev = data;
+
+	mtk_ddp_comp_unregister(drm_dev, &priv->ddp_comp);
+}
+
+static const struct component_ops mtk_disp_ovl_component_ops = {
+	.bind	= mtk_disp_ovl_bind,
+	.unbind = mtk_disp_ovl_unbind,
+};
+
+static int mtk_disp_ovl_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct mtk_disp_ovl *priv;
+	int comp_id;
+	int irq;
+	int ret;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	ret = devm_request_irq(dev, irq, mtk_disp_ovl_irq_handler,
+			       IRQF_TRIGGER_NONE, dev_name(dev), priv);
+	if (ret < 0) {
+		dev_err(dev, "Failed to request irq %d: %d\n", irq, ret);
+		return ret;
+	}
+
+	comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DISP_OVL);
+	if (comp_id < 0) {
+		dev_err(dev, "Failed to identify by alias: %d\n", comp_id);
+		return comp_id;
+	}
+
+	ret = mtk_ddp_comp_init(dev, dev->of_node, &priv->ddp_comp, comp_id,
+				&mtk_disp_ovl_funcs);
+	if (ret) {
+		dev_err(dev, "Failed to initialize component: %d\n", ret);
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, priv);
+
+	ret = component_add(dev, &mtk_disp_ovl_component_ops);
+	if (ret)
+		dev_err(dev, "Failed to add component: %d\n", ret);
+
+	return ret;
+}
+
+static int mtk_disp_ovl_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &mtk_disp_ovl_component_ops);
+
+	return 0;
+}
+
+static const struct of_device_id mtk_disp_ovl_driver_dt_match[] = {
+	{ .compatible = "mediatek,mt8173-disp-ovl", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, mtk_disp_ovl_driver_dt_match);
+
+struct platform_driver mtk_disp_ovl_driver = {
+	.probe		= mtk_disp_ovl_probe,
+	.remove		= mtk_disp_ovl_remove,
+	.driver		= {
+		.name	= "mediatek-disp-ovl",
+		.owner	= THIS_MODULE,
+		.of_match_table = mtk_disp_ovl_driver_dt_match,
+	},
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_disp_rdma.c linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_disp_rdma.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_disp_rdma.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include <drm/drmP.h>
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+
+#include "mtk_drm_crtc.h"
+#include "mtk_drm_ddp_comp.h"
+
+#define DISP_REG_RDMA_INT_ENABLE		0x0000
+#define DISP_REG_RDMA_INT_STATUS		0x0004
+#define RDMA_TARGET_LINE_INT				BIT(5)
+#define RDMA_FIFO_UNDERFLOW_INT				BIT(4)
+#define RDMA_EOF_ABNORMAL_INT				BIT(3)
+#define RDMA_FRAME_END_INT				BIT(2)
+#define RDMA_FRAME_START_INT				BIT(1)
+#define RDMA_REG_UPDATE_INT				BIT(0)
+#define DISP_REG_RDMA_GLOBAL_CON		0x0010
+#define RDMA_ENGINE_EN					BIT(0)
+#define DISP_REG_RDMA_SIZE_CON_0		0x0014
+#define DISP_REG_RDMA_SIZE_CON_1		0x0018
+#define DISP_REG_RDMA_TARGET_LINE		0x001c
+#define DISP_REG_RDMA_FIFO_CON			0x0040
+#define RDMA_FIFO_UNDERFLOW_EN				BIT(31)
+#define RDMA_FIFO_PSEUDO_SIZE(bytes)			(((bytes) / 16) << 16)
+#define RDMA_OUTPUT_VALID_FIFO_THRESHOLD(bytes)		((bytes) / 16)
+
+/**
+ * struct mtk_disp_rdma - DISP_RDMA driver structure
+ * @ddp_comp - structure containing type enum and hardware resources
+ * @crtc - associated crtc to report irq events to
+ */
+struct mtk_disp_rdma {
+	struct mtk_ddp_comp		ddp_comp;
+	struct drm_crtc			*crtc;
+};
+
+static irqreturn_t mtk_disp_rdma_irq_handler(int irq, void *dev_id)
+{
+	struct mtk_disp_rdma *priv = dev_id;
+	struct mtk_ddp_comp *rdma = &priv->ddp_comp;
+
+	/* Clear frame completion interrupt */
+	writel(0x0, rdma->regs + DISP_REG_RDMA_INT_STATUS);
+
+	if (!priv->crtc)
+		return IRQ_NONE;
+
+	mtk_crtc_ddp_irq(priv->crtc, rdma);
+
+	return IRQ_HANDLED;
+}
+
+static void rdma_update_bits(struct mtk_ddp_comp *comp, unsigned int reg,
+			     unsigned int mask, unsigned int val)
+{
+	unsigned int tmp = readl(comp->regs + reg);
+
+	tmp = (tmp & ~mask) | (val & mask);
+	writel(tmp, comp->regs + reg);
+}
+
+static void mtk_rdma_enable_vblank(struct mtk_ddp_comp *comp,
+				   struct drm_crtc *crtc)
+{
+	struct mtk_disp_rdma *priv = container_of(comp, struct mtk_disp_rdma,
+						  ddp_comp);
+
+	priv->crtc = crtc;
+	rdma_update_bits(comp, DISP_REG_RDMA_INT_ENABLE, RDMA_FRAME_END_INT,
+			 RDMA_FRAME_END_INT);
+}
+
+static void mtk_rdma_disable_vblank(struct mtk_ddp_comp *comp)
+{
+	struct mtk_disp_rdma *priv = container_of(comp, struct mtk_disp_rdma,
+						  ddp_comp);
+
+	priv->crtc = NULL;
+	rdma_update_bits(comp, DISP_REG_RDMA_INT_ENABLE, RDMA_FRAME_END_INT, 0);
+}
+
+static void mtk_rdma_start(struct mtk_ddp_comp *comp)
+{
+	rdma_update_bits(comp, DISP_REG_RDMA_GLOBAL_CON, RDMA_ENGINE_EN,
+			 RDMA_ENGINE_EN);
+}
+
+static void mtk_rdma_stop(struct mtk_ddp_comp *comp)
+{
+	rdma_update_bits(comp, DISP_REG_RDMA_GLOBAL_CON, RDMA_ENGINE_EN, 0);
+}
+
+static void mtk_rdma_config(struct mtk_ddp_comp *comp, unsigned int width,
+			    unsigned int height, unsigned int vrefresh)
+{
+	unsigned int threshold;
+	unsigned int reg;
+
+	rdma_update_bits(comp, DISP_REG_RDMA_SIZE_CON_0, 0xfff, width);
+	rdma_update_bits(comp, DISP_REG_RDMA_SIZE_CON_1, 0xfffff, height);
+
+	/*
+	 * Enable FIFO underflow since DSI and DPI can't be blocked.
+	 * Keep the FIFO pseudo size reset default of 8 KiB. Set the
+	 * output threshold to 6 microseconds with 7/6 overhead to
+	 * account for blanking, and with a pixel depth of 4 bytes:
+	 */
+	threshold = width * height * vrefresh * 4 * 7 / 1000000;
+	reg = RDMA_FIFO_UNDERFLOW_EN |
+	      RDMA_FIFO_PSEUDO_SIZE(SZ_8K) |
+	      RDMA_OUTPUT_VALID_FIFO_THRESHOLD(threshold);
+	writel(reg, comp->regs + DISP_REG_RDMA_FIFO_CON);
+}
+
+static const struct mtk_ddp_comp_funcs mtk_disp_rdma_funcs = {
+	.config = mtk_rdma_config,
+	.start = mtk_rdma_start,
+	.stop = mtk_rdma_stop,
+	.enable_vblank = mtk_rdma_enable_vblank,
+	.disable_vblank = mtk_rdma_disable_vblank,
+};
+
+static int mtk_disp_rdma_bind(struct device *dev, struct device *master,
+			      void *data)
+{
+	struct mtk_disp_rdma *priv = dev_get_drvdata(dev);
+	struct drm_device *drm_dev = data;
+	int ret;
+
+	ret = mtk_ddp_comp_register(drm_dev, &priv->ddp_comp);
+	if (ret < 0) {
+		dev_err(dev, "Failed to register component %s: %d\n",
+			dev->of_node->full_name, ret);
+		return ret;
+	}
+
+	return 0;
+
+}
+
+static void mtk_disp_rdma_unbind(struct device *dev, struct device *master,
+				 void *data)
+{
+	struct mtk_disp_rdma *priv = dev_get_drvdata(dev);
+	struct drm_device *drm_dev = data;
+
+	mtk_ddp_comp_unregister(drm_dev, &priv->ddp_comp);
+}
+
+static const struct component_ops mtk_disp_rdma_component_ops = {
+	.bind	= mtk_disp_rdma_bind,
+	.unbind = mtk_disp_rdma_unbind,
+};
+
+static int mtk_disp_rdma_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct mtk_disp_rdma *priv;
+	int comp_id;
+	int irq;
+	int ret;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DISP_RDMA);
+	if (comp_id < 0) {
+		dev_err(dev, "Failed to identify by alias: %d\n", comp_id);
+		return comp_id;
+	}
+
+	ret = mtk_ddp_comp_init(dev, dev->of_node, &priv->ddp_comp, comp_id,
+				&mtk_disp_rdma_funcs);
+	if (ret) {
+		dev_err(dev, "Failed to initialize component: %d\n", ret);
+		return ret;
+	}
+
+	/* Disable and clear pending interrupts */
+	writel(0x0, priv->ddp_comp.regs + DISP_REG_RDMA_INT_ENABLE);
+	writel(0x0, priv->ddp_comp.regs + DISP_REG_RDMA_INT_STATUS);
+
+	ret = devm_request_irq(dev, irq, mtk_disp_rdma_irq_handler,
+			       IRQF_TRIGGER_NONE, dev_name(dev), priv);
+	if (ret < 0) {
+		dev_err(dev, "Failed to request irq %d: %d\n", irq, ret);
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, priv);
+
+	ret = component_add(dev, &mtk_disp_rdma_component_ops);
+	if (ret)
+		dev_err(dev, "Failed to add component: %d\n", ret);
+
+	return ret;
+}
+
+static int mtk_disp_rdma_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &mtk_disp_rdma_component_ops);
+
+	return 0;
+}
+
+static const struct of_device_id mtk_disp_rdma_driver_dt_match[] = {
+	{ .compatible = "mediatek,mt8173-disp-rdma", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, mtk_disp_rdma_driver_dt_match);
+
+struct platform_driver mtk_disp_rdma_driver = {
+	.probe		= mtk_disp_rdma_probe,
+	.remove		= mtk_disp_rdma_remove,
+	.driver		= {
+		.name	= "mediatek-disp-rdma",
+		.owner	= THIS_MODULE,
+		.of_match_table = mtk_disp_rdma_driver_dt_match,
+	},
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_dpi.c linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_dpi.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_dpi.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_dpi.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,764 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Jie Qiu <jie.qiu@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <linux/kernel.h>
+#include <linux/component.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_graph.h>
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <linux/clk.h>
+
+#include "mtk_dpi_regs.h"
+#include "mtk_drm_ddp_comp.h"
+
+enum mtk_dpi_out_bit_num {
+	MTK_DPI_OUT_BIT_NUM_8BITS,
+	MTK_DPI_OUT_BIT_NUM_10BITS,
+	MTK_DPI_OUT_BIT_NUM_12BITS,
+	MTK_DPI_OUT_BIT_NUM_16BITS
+};
+
+enum mtk_dpi_out_yc_map {
+	MTK_DPI_OUT_YC_MAP_RGB,
+	MTK_DPI_OUT_YC_MAP_CYCY,
+	MTK_DPI_OUT_YC_MAP_YCYC,
+	MTK_DPI_OUT_YC_MAP_CY,
+	MTK_DPI_OUT_YC_MAP_YC
+};
+
+enum mtk_dpi_out_channel_swap {
+	MTK_DPI_OUT_CHANNEL_SWAP_RGB,
+	MTK_DPI_OUT_CHANNEL_SWAP_GBR,
+	MTK_DPI_OUT_CHANNEL_SWAP_BRG,
+	MTK_DPI_OUT_CHANNEL_SWAP_RBG,
+	MTK_DPI_OUT_CHANNEL_SWAP_GRB,
+	MTK_DPI_OUT_CHANNEL_SWAP_BGR
+};
+
+enum mtk_dpi_out_color_format {
+	MTK_DPI_COLOR_FORMAT_RGB,
+	MTK_DPI_COLOR_FORMAT_RGB_FULL,
+	MTK_DPI_COLOR_FORMAT_YCBCR_444,
+	MTK_DPI_COLOR_FORMAT_YCBCR_422,
+	MTK_DPI_COLOR_FORMAT_XV_YCC,
+	MTK_DPI_COLOR_FORMAT_YCBCR_444_FULL,
+	MTK_DPI_COLOR_FORMAT_YCBCR_422_FULL
+};
+
+struct mtk_dpi {
+	struct mtk_ddp_comp ddp_comp;
+	struct drm_encoder encoder;
+	void __iomem *regs;
+	struct device *dev;
+	struct clk *engine_clk;
+	struct clk *pixel_clk;
+	struct clk *tvd_clk;
+	int irq;
+	struct drm_display_mode mode;
+	enum mtk_dpi_out_color_format color_format;
+	enum mtk_dpi_out_yc_map yc_map;
+	enum mtk_dpi_out_bit_num bit_num;
+	enum mtk_dpi_out_channel_swap channel_swap;
+	bool power_sta;
+	u8 power_ctl;
+};
+
+static inline struct mtk_dpi *mtk_dpi_from_encoder(struct drm_encoder *e)
+{
+	return container_of(e, struct mtk_dpi, encoder);
+}
+
+enum mtk_dpi_polarity {
+	MTK_DPI_POLARITY_RISING,
+	MTK_DPI_POLARITY_FALLING,
+};
+
+enum mtk_dpi_power_ctl {
+	DPI_POWER_START = BIT(0),
+	DPI_POWER_ENABLE = BIT(1),
+};
+
+struct mtk_dpi_polarities {
+	enum mtk_dpi_polarity de_pol;
+	enum mtk_dpi_polarity ck_pol;
+	enum mtk_dpi_polarity hsync_pol;
+	enum mtk_dpi_polarity vsync_pol;
+};
+
+struct mtk_dpi_sync_param {
+	u32 sync_width;
+	u32 front_porch;
+	u32 back_porch;
+	bool shift_half_line;
+};
+
+struct mtk_dpi_yc_limit {
+	u16 y_top;
+	u16 y_bottom;
+	u16 c_top;
+	u16 c_bottom;
+};
+
+static void mtk_dpi_mask(struct mtk_dpi *dpi, u32 offset, u32 val, u32 mask)
+{
+	u32 tmp = readl(dpi->regs + offset) & ~mask;
+
+	tmp |= (val & mask);
+	writel(tmp, dpi->regs + offset);
+}
+
+static void mtk_dpi_sw_reset(struct mtk_dpi *dpi, bool reset)
+{
+	mtk_dpi_mask(dpi, DPI_RET, reset ? RST : 0, RST);
+}
+
+static void mtk_dpi_enable(struct mtk_dpi *dpi)
+{
+	mtk_dpi_mask(dpi, DPI_EN, EN, EN);
+}
+
+static void mtk_dpi_disable(struct mtk_dpi *dpi)
+{
+	mtk_dpi_mask(dpi, DPI_EN, 0, EN);
+}
+
+static void mtk_dpi_config_hsync(struct mtk_dpi *dpi,
+				 struct mtk_dpi_sync_param *sync)
+{
+	mtk_dpi_mask(dpi, DPI_TGEN_HWIDTH,
+		     sync->sync_width << HPW, HPW_MASK);
+	mtk_dpi_mask(dpi, DPI_TGEN_HPORCH,
+		     sync->back_porch << HBP, HBP_MASK);
+	mtk_dpi_mask(dpi, DPI_TGEN_HPORCH, sync->front_porch << HFP,
+		     HFP_MASK);
+}
+
+static void mtk_dpi_config_vsync(struct mtk_dpi *dpi,
+				 struct mtk_dpi_sync_param *sync,
+				 u32 width_addr, u32 porch_addr)
+{
+	mtk_dpi_mask(dpi, width_addr,
+		     sync->sync_width << VSYNC_WIDTH_SHIFT,
+		     VSYNC_WIDTH_MASK);
+	mtk_dpi_mask(dpi, width_addr,
+		     sync->shift_half_line << VSYNC_HALF_LINE_SHIFT,
+		     VSYNC_HALF_LINE_MASK);
+	mtk_dpi_mask(dpi, porch_addr,
+		     sync->back_porch << VSYNC_BACK_PORCH_SHIFT,
+		     VSYNC_BACK_PORCH_MASK);
+	mtk_dpi_mask(dpi, porch_addr,
+		     sync->front_porch << VSYNC_FRONT_PORCH_SHIFT,
+		     VSYNC_FRONT_PORCH_MASK);
+}
+
+static void mtk_dpi_config_vsync_lodd(struct mtk_dpi *dpi,
+				      struct mtk_dpi_sync_param *sync)
+{
+	mtk_dpi_config_vsync(dpi, sync, DPI_TGEN_VWIDTH, DPI_TGEN_VPORCH);
+}
+
+static void mtk_dpi_config_vsync_leven(struct mtk_dpi *dpi,
+				       struct mtk_dpi_sync_param *sync)
+{
+	mtk_dpi_config_vsync(dpi, sync, DPI_TGEN_VWIDTH_LEVEN,
+			     DPI_TGEN_VPORCH_LEVEN);
+}
+
+static void mtk_dpi_config_vsync_rodd(struct mtk_dpi *dpi,
+				      struct mtk_dpi_sync_param *sync)
+{
+	mtk_dpi_config_vsync(dpi, sync, DPI_TGEN_VWIDTH_RODD,
+			     DPI_TGEN_VPORCH_RODD);
+}
+
+static void mtk_dpi_config_vsync_reven(struct mtk_dpi *dpi,
+				       struct mtk_dpi_sync_param *sync)
+{
+	mtk_dpi_config_vsync(dpi, sync, DPI_TGEN_VWIDTH_REVEN,
+			     DPI_TGEN_VPORCH_REVEN);
+}
+
+static void mtk_dpi_config_pol(struct mtk_dpi *dpi,
+			       struct mtk_dpi_polarities *dpi_pol)
+{
+	unsigned int pol;
+
+	pol = (dpi_pol->ck_pol == MTK_DPI_POLARITY_RISING ? 0 : CK_POL) |
+	      (dpi_pol->de_pol == MTK_DPI_POLARITY_RISING ? 0 : DE_POL) |
+	      (dpi_pol->hsync_pol == MTK_DPI_POLARITY_RISING ? 0 : HSYNC_POL) |
+	      (dpi_pol->vsync_pol == MTK_DPI_POLARITY_RISING ? 0 : VSYNC_POL);
+	mtk_dpi_mask(dpi, DPI_OUTPUT_SETTING, pol,
+		     CK_POL | DE_POL | HSYNC_POL | VSYNC_POL);
+}
+
+static void mtk_dpi_config_3d(struct mtk_dpi *dpi, bool en_3d)
+{
+	mtk_dpi_mask(dpi, DPI_CON, en_3d ? TDFP_EN : 0, TDFP_EN);
+}
+
+static void mtk_dpi_config_interface(struct mtk_dpi *dpi, bool inter)
+{
+	mtk_dpi_mask(dpi, DPI_CON, inter ? INTL_EN : 0, INTL_EN);
+}
+
+static void mtk_dpi_config_fb_size(struct mtk_dpi *dpi, u32 width, u32 height)
+{
+	mtk_dpi_mask(dpi, DPI_SIZE, width << HSIZE, HSIZE_MASK);
+	mtk_dpi_mask(dpi, DPI_SIZE, height << VSIZE, VSIZE_MASK);
+}
+
+static void mtk_dpi_config_channel_limit(struct mtk_dpi *dpi,
+					 struct mtk_dpi_yc_limit *limit)
+{
+	mtk_dpi_mask(dpi, DPI_Y_LIMIT, limit->y_bottom << Y_LIMINT_BOT,
+		     Y_LIMINT_BOT_MASK);
+	mtk_dpi_mask(dpi, DPI_Y_LIMIT, limit->y_top << Y_LIMINT_TOP,
+		     Y_LIMINT_TOP_MASK);
+	mtk_dpi_mask(dpi, DPI_C_LIMIT, limit->c_bottom << C_LIMIT_BOT,
+		     C_LIMIT_BOT_MASK);
+	mtk_dpi_mask(dpi, DPI_C_LIMIT, limit->c_top << C_LIMIT_TOP,
+		     C_LIMIT_TOP_MASK);
+}
+
+static void mtk_dpi_config_bit_num(struct mtk_dpi *dpi,
+				   enum mtk_dpi_out_bit_num num)
+{
+	u32 val;
+
+	switch (num) {
+	case MTK_DPI_OUT_BIT_NUM_8BITS:
+		val = OUT_BIT_8;
+		break;
+	case MTK_DPI_OUT_BIT_NUM_10BITS:
+		val = OUT_BIT_10;
+		break;
+	case MTK_DPI_OUT_BIT_NUM_12BITS:
+		val = OUT_BIT_12;
+		break;
+	case MTK_DPI_OUT_BIT_NUM_16BITS:
+		val = OUT_BIT_16;
+		break;
+	default:
+		val = OUT_BIT_8;
+		break;
+	}
+	mtk_dpi_mask(dpi, DPI_OUTPUT_SETTING, val << OUT_BIT,
+		     OUT_BIT_MASK);
+}
+
+static void mtk_dpi_config_yc_map(struct mtk_dpi *dpi,
+				  enum mtk_dpi_out_yc_map map)
+{
+	u32 val;
+
+	switch (map) {
+	case MTK_DPI_OUT_YC_MAP_RGB:
+		val = YC_MAP_RGB;
+		break;
+	case MTK_DPI_OUT_YC_MAP_CYCY:
+		val = YC_MAP_CYCY;
+		break;
+	case MTK_DPI_OUT_YC_MAP_YCYC:
+		val = YC_MAP_YCYC;
+		break;
+	case MTK_DPI_OUT_YC_MAP_CY:
+		val = YC_MAP_CY;
+		break;
+	case MTK_DPI_OUT_YC_MAP_YC:
+		val = YC_MAP_YC;
+		break;
+	default:
+		val = YC_MAP_RGB;
+		break;
+	}
+
+	mtk_dpi_mask(dpi, DPI_OUTPUT_SETTING, val << YC_MAP, YC_MAP_MASK);
+}
+
+static void mtk_dpi_config_channel_swap(struct mtk_dpi *dpi,
+					enum mtk_dpi_out_channel_swap swap)
+{
+	u32 val;
+
+	switch (swap) {
+	case MTK_DPI_OUT_CHANNEL_SWAP_RGB:
+		val = SWAP_RGB;
+		break;
+	case MTK_DPI_OUT_CHANNEL_SWAP_GBR:
+		val = SWAP_GBR;
+		break;
+	case MTK_DPI_OUT_CHANNEL_SWAP_BRG:
+		val = SWAP_BRG;
+		break;
+	case MTK_DPI_OUT_CHANNEL_SWAP_RBG:
+		val = SWAP_RBG;
+		break;
+	case MTK_DPI_OUT_CHANNEL_SWAP_GRB:
+		val = SWAP_GRB;
+		break;
+	case MTK_DPI_OUT_CHANNEL_SWAP_BGR:
+		val = SWAP_BGR;
+		break;
+	default:
+		val = SWAP_RGB;
+		break;
+	}
+
+	mtk_dpi_mask(dpi, DPI_OUTPUT_SETTING, val << CH_SWAP, CH_SWAP_MASK);
+}
+
+static void mtk_dpi_config_yuv422_enable(struct mtk_dpi *dpi, bool enable)
+{
+	mtk_dpi_mask(dpi, DPI_CON, enable ? YUV422_EN : 0, YUV422_EN);
+}
+
+static void mtk_dpi_config_csc_enable(struct mtk_dpi *dpi, bool enable)
+{
+	mtk_dpi_mask(dpi, DPI_CON, enable ? CSC_ENABLE : 0, CSC_ENABLE);
+}
+
+static void mtk_dpi_config_swap_input(struct mtk_dpi *dpi, bool enable)
+{
+	mtk_dpi_mask(dpi, DPI_CON, enable ? IN_RB_SWAP : 0, IN_RB_SWAP);
+}
+
+static void mtk_dpi_config_2n_h_fre(struct mtk_dpi *dpi)
+{
+	mtk_dpi_mask(dpi, DPI_H_FRE_CON, H_FRE_2N, H_FRE_2N);
+}
+
+static void mtk_dpi_config_color_format(struct mtk_dpi *dpi,
+					enum mtk_dpi_out_color_format format)
+{
+	if ((format == MTK_DPI_COLOR_FORMAT_YCBCR_444) ||
+	    (format == MTK_DPI_COLOR_FORMAT_YCBCR_444_FULL)) {
+		mtk_dpi_config_yuv422_enable(dpi, false);
+		mtk_dpi_config_csc_enable(dpi, true);
+		mtk_dpi_config_swap_input(dpi, false);
+		mtk_dpi_config_channel_swap(dpi, MTK_DPI_OUT_CHANNEL_SWAP_BGR);
+	} else if ((format == MTK_DPI_COLOR_FORMAT_YCBCR_422) ||
+		   (format == MTK_DPI_COLOR_FORMAT_YCBCR_422_FULL)) {
+		mtk_dpi_config_yuv422_enable(dpi, true);
+		mtk_dpi_config_csc_enable(dpi, true);
+		mtk_dpi_config_swap_input(dpi, true);
+		mtk_dpi_config_channel_swap(dpi, MTK_DPI_OUT_CHANNEL_SWAP_RGB);
+	} else {
+		mtk_dpi_config_yuv422_enable(dpi, false);
+		mtk_dpi_config_csc_enable(dpi, false);
+		mtk_dpi_config_swap_input(dpi, false);
+		mtk_dpi_config_channel_swap(dpi, MTK_DPI_OUT_CHANNEL_SWAP_RGB);
+	}
+}
+
+static void mtk_dpi_power_off(struct mtk_dpi *dpi, enum mtk_dpi_power_ctl pctl)
+{
+	dpi->power_ctl &= ~pctl;
+
+	if ((dpi->power_ctl & DPI_POWER_START) ||
+	    (dpi->power_ctl & DPI_POWER_ENABLE))
+		return;
+
+	if (!dpi->power_sta)
+		return;
+
+	mtk_dpi_disable(dpi);
+	clk_disable_unprepare(dpi->pixel_clk);
+	clk_disable_unprepare(dpi->engine_clk);
+	dpi->power_sta = false;
+}
+
+static int mtk_dpi_power_on(struct mtk_dpi *dpi, enum mtk_dpi_power_ctl pctl)
+{
+	int ret;
+
+	dpi->power_ctl |= pctl;
+
+	if (!(dpi->power_ctl & DPI_POWER_START) &&
+	    !(dpi->power_ctl & DPI_POWER_ENABLE))
+		return 0;
+
+	if (dpi->power_sta)
+		return 0;
+
+	ret = clk_prepare_enable(dpi->engine_clk);
+	if (ret) {
+		dev_err(dpi->dev, "Failed to enable engine clock: %d\n", ret);
+		goto err_eng;
+	}
+
+	ret = clk_prepare_enable(dpi->pixel_clk);
+	if (ret) {
+		dev_err(dpi->dev, "Failed to enable pixel clock: %d\n", ret);
+		goto err_pixel;
+	}
+
+	mtk_dpi_enable(dpi);
+	dpi->power_sta = true;
+	return 0;
+
+err_pixel:
+	clk_disable_unprepare(dpi->engine_clk);
+err_eng:
+	dpi->power_ctl &= ~pctl;
+	return ret;
+}
+
+static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi,
+				    struct drm_display_mode *mode)
+{
+	struct mtk_dpi_yc_limit limit;
+	struct mtk_dpi_polarities dpi_pol;
+	struct mtk_dpi_sync_param hsync;
+	struct mtk_dpi_sync_param vsync_lodd = { 0 };
+	struct mtk_dpi_sync_param vsync_leven = { 0 };
+	struct mtk_dpi_sync_param vsync_rodd = { 0 };
+	struct mtk_dpi_sync_param vsync_reven = { 0 };
+	unsigned long pix_rate;
+	unsigned long pll_rate;
+	unsigned int factor;
+
+	pix_rate = 1000UL * mode->clock;
+	if (mode->clock <= 74000)
+		factor = 8 * 3;
+	else
+		factor = 4 * 3;
+	pll_rate = pix_rate * factor;
+
+	dev_dbg(dpi->dev, "Want PLL %lu Hz, pixel clock %lu Hz\n",
+		pll_rate, pix_rate);
+
+	clk_set_rate(dpi->tvd_clk, pll_rate);
+	pll_rate = clk_get_rate(dpi->tvd_clk);
+
+	pix_rate = pll_rate / factor;
+	clk_set_rate(dpi->pixel_clk, pix_rate);
+	pix_rate = clk_get_rate(dpi->pixel_clk);
+
+	dev_dbg(dpi->dev, "Got  PLL %lu Hz, pixel clock %lu Hz\n",
+		pll_rate, pix_rate);
+
+	limit.c_bottom = 0x0010;
+	limit.c_top = 0x0FE0;
+	limit.y_bottom = 0x0010;
+	limit.y_top = 0x0FE0;
+
+	dpi_pol.ck_pol = MTK_DPI_POLARITY_FALLING;
+	dpi_pol.de_pol = MTK_DPI_POLARITY_RISING;
+	dpi_pol.hsync_pol = mode->flags & DRM_MODE_FLAG_PHSYNC ?
+			    MTK_DPI_POLARITY_FALLING : MTK_DPI_POLARITY_RISING;
+	dpi_pol.vsync_pol = mode->flags & DRM_MODE_FLAG_PVSYNC ?
+			    MTK_DPI_POLARITY_FALLING : MTK_DPI_POLARITY_RISING;
+
+	hsync.sync_width = mode->hsync_end - mode->hsync_start;
+	hsync.back_porch = mode->htotal - mode->hsync_end;
+	hsync.front_porch = mode->hsync_start - mode->hdisplay;
+	hsync.shift_half_line = false;
+
+	vsync_lodd.sync_width = mode->vsync_end - mode->vsync_start;
+	vsync_lodd.back_porch = mode->vtotal - mode->vsync_end;
+	vsync_lodd.front_porch = mode->vsync_start - mode->vdisplay;
+	vsync_lodd.shift_half_line = false;
+
+	if (mode->flags & DRM_MODE_FLAG_INTERLACE &&
+	    mode->flags & DRM_MODE_FLAG_3D_MASK) {
+		vsync_leven = vsync_lodd;
+		vsync_rodd = vsync_lodd;
+		vsync_reven = vsync_lodd;
+		vsync_leven.shift_half_line = true;
+		vsync_reven.shift_half_line = true;
+	} else if (mode->flags & DRM_MODE_FLAG_INTERLACE &&
+		   !(mode->flags & DRM_MODE_FLAG_3D_MASK)) {
+		vsync_leven = vsync_lodd;
+		vsync_leven.shift_half_line = true;
+	} else if (!(mode->flags & DRM_MODE_FLAG_INTERLACE) &&
+		   mode->flags & DRM_MODE_FLAG_3D_MASK) {
+		vsync_rodd = vsync_lodd;
+	}
+	mtk_dpi_sw_reset(dpi, true);
+	mtk_dpi_config_pol(dpi, &dpi_pol);
+
+	mtk_dpi_config_hsync(dpi, &hsync);
+	mtk_dpi_config_vsync_lodd(dpi, &vsync_lodd);
+	mtk_dpi_config_vsync_rodd(dpi, &vsync_rodd);
+	mtk_dpi_config_vsync_leven(dpi, &vsync_leven);
+	mtk_dpi_config_vsync_reven(dpi, &vsync_reven);
+
+	mtk_dpi_config_3d(dpi, !!(mode->flags & DRM_MODE_FLAG_3D_MASK));
+	mtk_dpi_config_interface(dpi, !!(mode->flags &
+					 DRM_MODE_FLAG_INTERLACE));
+	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+		mtk_dpi_config_fb_size(dpi, mode->hdisplay, mode->vdisplay / 2);
+	else
+		mtk_dpi_config_fb_size(dpi, mode->hdisplay, mode->vdisplay);
+
+	mtk_dpi_config_channel_limit(dpi, &limit);
+	mtk_dpi_config_bit_num(dpi, dpi->bit_num);
+	mtk_dpi_config_channel_swap(dpi, dpi->channel_swap);
+	mtk_dpi_config_yc_map(dpi, dpi->yc_map);
+	mtk_dpi_config_color_format(dpi, dpi->color_format);
+	mtk_dpi_config_2n_h_fre(dpi);
+	mtk_dpi_sw_reset(dpi, false);
+
+	return 0;
+}
+
+static void mtk_dpi_encoder_destroy(struct drm_encoder *encoder)
+{
+	drm_encoder_cleanup(encoder);
+}
+
+static const struct drm_encoder_funcs mtk_dpi_encoder_funcs = {
+	.destroy = mtk_dpi_encoder_destroy,
+};
+
+static bool mtk_dpi_encoder_mode_fixup(struct drm_encoder *encoder,
+				       const struct drm_display_mode *mode,
+				       struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+static void mtk_dpi_encoder_mode_set(struct drm_encoder *encoder,
+				     struct drm_display_mode *mode,
+				     struct drm_display_mode *adjusted_mode)
+{
+	struct mtk_dpi *dpi = mtk_dpi_from_encoder(encoder);
+
+	drm_mode_copy(&dpi->mode, adjusted_mode);
+}
+
+static void mtk_dpi_encoder_disable(struct drm_encoder *encoder)
+{
+	struct mtk_dpi *dpi = mtk_dpi_from_encoder(encoder);
+
+	mtk_dpi_power_off(dpi, DPI_POWER_ENABLE);
+}
+
+static void mtk_dpi_encoder_enable(struct drm_encoder *encoder)
+{
+	struct mtk_dpi *dpi = mtk_dpi_from_encoder(encoder);
+
+	mtk_dpi_power_on(dpi, DPI_POWER_ENABLE);
+	mtk_dpi_set_display_mode(dpi, &dpi->mode);
+}
+
+static int mtk_dpi_atomic_check(struct drm_encoder *encoder,
+				struct drm_crtc_state *crtc_state,
+				struct drm_connector_state *conn_state)
+{
+	return 0;
+}
+
+static const struct drm_encoder_helper_funcs mtk_dpi_encoder_helper_funcs = {
+	.mode_fixup = mtk_dpi_encoder_mode_fixup,
+	.mode_set = mtk_dpi_encoder_mode_set,
+	.disable = mtk_dpi_encoder_disable,
+	.enable = mtk_dpi_encoder_enable,
+	.atomic_check = mtk_dpi_atomic_check,
+};
+
+static void mtk_dpi_start(struct mtk_ddp_comp *comp)
+{
+	struct mtk_dpi *dpi = container_of(comp, struct mtk_dpi, ddp_comp);
+
+	mtk_dpi_power_on(dpi, DPI_POWER_START);
+}
+
+static void mtk_dpi_stop(struct mtk_ddp_comp *comp)
+{
+	struct mtk_dpi *dpi = container_of(comp, struct mtk_dpi, ddp_comp);
+
+	mtk_dpi_power_off(dpi, DPI_POWER_START);
+}
+
+static const struct mtk_ddp_comp_funcs mtk_dpi_funcs = {
+	.start = mtk_dpi_start,
+	.stop = mtk_dpi_stop,
+};
+
+static int mtk_dpi_bind(struct device *dev, struct device *master, void *data)
+{
+	struct mtk_dpi *dpi = dev_get_drvdata(dev);
+	struct drm_device *drm_dev = data;
+	int ret;
+
+	ret = mtk_ddp_comp_register(drm_dev, &dpi->ddp_comp);
+	if (ret < 0) {
+		dev_err(dev, "Failed to register component %s: %d\n",
+			dev->of_node->full_name, ret);
+		return ret;
+	}
+
+	ret = drm_encoder_init(drm_dev, &dpi->encoder, &mtk_dpi_encoder_funcs,
+			       DRM_MODE_ENCODER_TMDS, NULL);
+	if (ret) {
+		dev_err(dev, "Failed to initialize decoder: %d\n", ret);
+		goto err_unregister;
+	}
+	drm_encoder_helper_add(&dpi->encoder, &mtk_dpi_encoder_helper_funcs);
+
+	/* Currently DPI0 is fixed to be driven by OVL1 */
+	dpi->encoder.possible_crtcs = BIT(1);
+
+	dpi->encoder.bridge->encoder = &dpi->encoder;
+	ret = drm_bridge_attach(dpi->encoder.dev, dpi->encoder.bridge);
+	if (ret) {
+		dev_err(dev, "Failed to attach bridge: %d\n", ret);
+		goto err_cleanup;
+	}
+
+	dpi->bit_num = MTK_DPI_OUT_BIT_NUM_8BITS;
+	dpi->channel_swap = MTK_DPI_OUT_CHANNEL_SWAP_RGB;
+	dpi->yc_map = MTK_DPI_OUT_YC_MAP_RGB;
+	dpi->color_format = MTK_DPI_COLOR_FORMAT_RGB;
+
+	return 0;
+
+err_cleanup:
+	drm_encoder_cleanup(&dpi->encoder);
+err_unregister:
+	mtk_ddp_comp_unregister(drm_dev, &dpi->ddp_comp);
+	return ret;
+}
+
+static void mtk_dpi_unbind(struct device *dev, struct device *master,
+			   void *data)
+{
+	struct mtk_dpi *dpi = dev_get_drvdata(dev);
+	struct drm_device *drm_dev = data;
+
+	drm_encoder_cleanup(&dpi->encoder);
+	mtk_ddp_comp_unregister(drm_dev, &dpi->ddp_comp);
+}
+
+static const struct component_ops mtk_dpi_component_ops = {
+	.bind = mtk_dpi_bind,
+	.unbind = mtk_dpi_unbind,
+};
+
+static int mtk_dpi_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct mtk_dpi *dpi;
+	struct resource *mem;
+	struct device_node *ep, *bridge_node = NULL;
+	int comp_id;
+	int ret;
+
+	dpi = devm_kzalloc(dev, sizeof(*dpi), GFP_KERNEL);
+	if (!dpi)
+		return -ENOMEM;
+
+	dpi->dev = dev;
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	dpi->regs = devm_ioremap_resource(dev, mem);
+	if (IS_ERR(dpi->regs)) {
+		ret = PTR_ERR(dpi->regs);
+		dev_err(dev, "Failed to ioremap mem resource: %d\n", ret);
+		return ret;
+	}
+
+	dpi->engine_clk = devm_clk_get(dev, "engine");
+	if (IS_ERR(dpi->engine_clk)) {
+		ret = PTR_ERR(dpi->engine_clk);
+		dev_err(dev, "Failed to get engine clock: %d\n", ret);
+		return ret;
+	}
+
+	dpi->pixel_clk = devm_clk_get(dev, "pixel");
+	if (IS_ERR(dpi->pixel_clk)) {
+		ret = PTR_ERR(dpi->pixel_clk);
+		dev_err(dev, "Failed to get pixel clock: %d\n", ret);
+		return ret;
+	}
+
+	dpi->tvd_clk = devm_clk_get(dev, "pll");
+	if (IS_ERR(dpi->tvd_clk)) {
+		ret = PTR_ERR(dpi->tvd_clk);
+		dev_err(dev, "Failed to get tvdpll clock: %d\n", ret);
+		return ret;
+	}
+
+	dpi->irq = platform_get_irq(pdev, 0);
+	if (dpi->irq <= 0) {
+		dev_err(dev, "Failed to get irq: %d\n", dpi->irq);
+		return -EINVAL;
+	}
+
+	ep = of_graph_get_next_endpoint(dev->of_node, NULL);
+	if (ep) {
+		bridge_node = of_graph_get_remote_port_parent(ep);
+		of_node_put(ep);
+	}
+	if (!bridge_node) {
+		dev_err(dev, "Failed to find bridge node\n");
+		return -ENODEV;
+	}
+
+	dev_info(dev, "Found bridge node: %s\n", bridge_node->full_name);
+
+	dpi->encoder.bridge = of_drm_find_bridge(bridge_node);
+	of_node_put(bridge_node);
+	if (!dpi->encoder.bridge)
+		return -EPROBE_DEFER;
+
+	comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DPI);
+	if (comp_id < 0) {
+		dev_err(dev, "Failed to identify by alias: %d\n", comp_id);
+		return comp_id;
+	}
+
+	ret = mtk_ddp_comp_init(dev, dev->of_node, &dpi->ddp_comp, comp_id,
+				&mtk_dpi_funcs);
+	if (ret) {
+		dev_err(dev, "Failed to initialize component: %d\n", ret);
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, dpi);
+
+	ret = component_add(dev, &mtk_dpi_component_ops);
+	if (ret) {
+		dev_err(dev, "Failed to add component: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int mtk_dpi_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &mtk_dpi_component_ops);
+
+	return 0;
+}
+
+static const struct of_device_id mtk_dpi_of_ids[] = {
+	{ .compatible = "mediatek,mt8173-dpi", },
+	{}
+};
+
+struct platform_driver mtk_dpi_driver = {
+	.probe = mtk_dpi_probe,
+	.remove = mtk_dpi_remove,
+	.driver = {
+		.name = "mediatek-dpi",
+		.of_match_table = mtk_dpi_of_ids,
+	},
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_dpi_regs.h linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_dpi_regs.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_dpi_regs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_dpi_regs.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Jie Qiu <jie.qiu@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+#ifndef __MTK_DPI_REGS_H
+#define __MTK_DPI_REGS_H
+
+#define DPI_EN			0x00
+#define EN				BIT(0)
+
+#define DPI_RET			0x04
+#define RST				BIT(0)
+
+#define DPI_INTEN		0x08
+#define INT_VSYNC_EN			BIT(0)
+#define INT_VDE_EN			BIT(1)
+#define INT_UNDERFLOW_EN		BIT(2)
+
+#define DPI_INTSTA		0x0C
+#define INT_VSYNC_STA			BIT(0)
+#define INT_VDE_STA			BIT(1)
+#define INT_UNDERFLOW_STA		BIT(2)
+
+#define DPI_CON			0x10
+#define BG_ENABLE			BIT(0)
+#define IN_RB_SWAP			BIT(1)
+#define INTL_EN				BIT(2)
+#define TDFP_EN				BIT(3)
+#define CLPF_EN				BIT(4)
+#define YUV422_EN			BIT(5)
+#define CSC_ENABLE			BIT(6)
+#define R601_SEL			BIT(7)
+#define EMBSYNC_EN			BIT(8)
+#define VS_LODD_EN			BIT(16)
+#define VS_LEVEN_EN			BIT(17)
+#define VS_RODD_EN			BIT(18)
+#define VS_REVEN			BIT(19)
+#define FAKE_DE_LODD			BIT(20)
+#define FAKE_DE_LEVEN			BIT(21)
+#define FAKE_DE_RODD			BIT(22)
+#define FAKE_DE_REVEN			BIT(23)
+
+#define DPI_OUTPUT_SETTING	0x14
+#define CH_SWAP				0
+#define CH_SWAP_MASK			(0x7 << 0)
+#define SWAP_RGB			0x00
+#define SWAP_GBR			0x01
+#define SWAP_BRG			0x02
+#define SWAP_RBG			0x03
+#define SWAP_GRB			0x04
+#define SWAP_BGR			0x05
+#define BIT_SWAP			BIT(3)
+#define B_MASK				BIT(4)
+#define G_MASK				BIT(5)
+#define R_MASK				BIT(6)
+#define DE_MASK				BIT(8)
+#define HS_MASK				BIT(9)
+#define VS_MASK				BIT(10)
+#define DE_POL				BIT(12)
+#define HSYNC_POL			BIT(13)
+#define VSYNC_POL			BIT(14)
+#define CK_POL				BIT(15)
+#define OEN_OFF				BIT(16)
+#define EDGE_SEL			BIT(17)
+#define OUT_BIT				18
+#define OUT_BIT_MASK			(0x3 << 18)
+#define OUT_BIT_8			0x00
+#define OUT_BIT_10			0x01
+#define OUT_BIT_12			0x02
+#define OUT_BIT_16			0x03
+#define YC_MAP				20
+#define YC_MAP_MASK			(0x7 << 20)
+#define YC_MAP_RGB			0x00
+#define YC_MAP_CYCY			0x04
+#define YC_MAP_YCYC			0x05
+#define YC_MAP_CY			0x06
+#define YC_MAP_YC			0x07
+
+#define DPI_SIZE		0x18
+#define HSIZE				0
+#define HSIZE_MASK			(0x1FFF << 0)
+#define VSIZE				16
+#define VSIZE_MASK			(0x1FFF << 16)
+
+#define DPI_DDR_SETTING		0x1C
+#define DDR_EN				BIT(0)
+#define DDDR_SEL			BIT(1)
+#define DDR_4PHASE			BIT(2)
+#define DDR_WIDTH			(0x3 << 4)
+#define DDR_PAD_MODE			(0x1 << 8)
+
+#define DPI_TGEN_HWIDTH		0x20
+#define HPW				0
+#define HPW_MASK			(0xFFF << 0)
+
+#define DPI_TGEN_HPORCH		0x24
+#define HBP				0
+#define HBP_MASK			(0xFFF << 0)
+#define HFP				16
+#define HFP_MASK			(0xFFF << 16)
+
+#define DPI_TGEN_VWIDTH		0x28
+#define DPI_TGEN_VPORCH		0x2C
+
+#define VSYNC_WIDTH_SHIFT		0
+#define VSYNC_WIDTH_MASK		(0xFFF << 0)
+#define VSYNC_HALF_LINE_SHIFT		16
+#define VSYNC_HALF_LINE_MASK		BIT(16)
+#define VSYNC_BACK_PORCH_SHIFT		0
+#define VSYNC_BACK_PORCH_MASK		(0xFFF << 0)
+#define VSYNC_FRONT_PORCH_SHIFT		16
+#define VSYNC_FRONT_PORCH_MASK		(0xFFF << 16)
+
+#define DPI_BG_HCNTL		0x30
+#define BG_RIGHT			(0x1FFF << 0)
+#define BG_LEFT				(0x1FFF << 16)
+
+#define DPI_BG_VCNTL		0x34
+#define BG_BOT				(0x1FFF << 0)
+#define BG_TOP				(0x1FFF << 16)
+
+#define DPI_BG_COLOR		0x38
+#define BG_B				(0xF << 0)
+#define BG_G				(0xF << 8)
+#define BG_R				(0xF << 16)
+
+#define DPI_FIFO_CTL		0x3C
+#define FIFO_VALID_SET			(0x1F << 0)
+#define FIFO_RST_SEL			(0x1 << 8)
+
+#define DPI_STATUS		0x40
+#define VCOUNTER			(0x1FFF << 0)
+#define DPI_BUSY			BIT(16)
+#define OUTEN				BIT(17)
+#define FIELD				BIT(20)
+#define TDLR				BIT(21)
+
+#define DPI_TMODE		0x44
+#define DPI_OEN_ON			BIT(0)
+
+#define DPI_CHECKSUM		0x48
+#define DPI_CHECKSUM_MASK		(0xFFFFFF << 0)
+#define DPI_CHECKSUM_READY		BIT(30)
+#define DPI_CHECKSUM_EN			BIT(31)
+
+#define DPI_DUMMY		0x50
+#define DPI_DUMMY_MASK			(0xFFFFFFFF << 0)
+
+#define DPI_TGEN_VWIDTH_LEVEN	0x68
+#define DPI_TGEN_VPORCH_LEVEN	0x6C
+#define DPI_TGEN_VWIDTH_RODD	0x70
+#define DPI_TGEN_VPORCH_RODD	0x74
+#define DPI_TGEN_VWIDTH_REVEN	0x78
+#define DPI_TGEN_VPORCH_REVEN	0x7C
+
+#define DPI_ESAV_VTIMING_LODD	0x80
+#define ESAV_VOFST_LODD			(0xFFF << 0)
+#define ESAV_VWID_LODD			(0xFFF << 16)
+
+#define DPI_ESAV_VTIMING_LEVEN	0x84
+#define ESAV_VOFST_LEVEN		(0xFFF << 0)
+#define ESAV_VWID_LEVEN			(0xFFF << 16)
+
+#define DPI_ESAV_VTIMING_RODD	0x88
+#define ESAV_VOFST_RODD			(0xFFF << 0)
+#define ESAV_VWID_RODD			(0xFFF << 16)
+
+#define DPI_ESAV_VTIMING_REVEN	0x8C
+#define ESAV_VOFST_REVEN		(0xFFF << 0)
+#define ESAV_VWID_REVEN			(0xFFF << 16)
+
+#define DPI_ESAV_FTIMING	0x90
+#define ESAV_FOFST_ODD			(0xFFF << 0)
+#define ESAV_FOFST_EVEN			(0xFFF << 16)
+
+#define DPI_CLPF_SETTING	0x94
+#define CLPF_TYPE			(0x3 << 0)
+#define ROUND_EN			BIT(4)
+
+#define DPI_Y_LIMIT		0x98
+#define Y_LIMINT_BOT			0
+#define Y_LIMINT_BOT_MASK		(0xFFF << 0)
+#define Y_LIMINT_TOP			16
+#define Y_LIMINT_TOP_MASK		(0xFFF << 16)
+
+#define DPI_C_LIMIT		0x9C
+#define C_LIMIT_BOT			0
+#define C_LIMIT_BOT_MASK		(0xFFF << 0)
+#define C_LIMIT_TOP			16
+#define C_LIMIT_TOP_MASK		(0xFFF << 16)
+
+#define DPI_YUV422_SETTING	0xA0
+#define UV_SWAP				BIT(0)
+#define CR_DELSEL			BIT(4)
+#define CB_DELSEL			BIT(5)
+#define Y_DELSEL			BIT(6)
+#define DE_DELSEL			BIT(7)
+
+#define DPI_EMBSYNC_SETTING	0xA4
+#define EMBSYNC_R_CR_EN			BIT(0)
+#define EMPSYNC_G_Y_EN			BIT(1)
+#define EMPSYNC_B_CB_EN			BIT(2)
+#define ESAV_F_INV			BIT(4)
+#define ESAV_V_INV			BIT(5)
+#define ESAV_H_INV			BIT(6)
+#define ESAV_CODE_MAN			BIT(8)
+#define VS_OUT_SEL			(0x7 << 12)
+
+#define DPI_ESAV_CODE_SET0	0xA8
+#define ESAV_CODE0			(0xFFF << 0)
+#define ESAV_CODE1			(0xFFF << 16)
+
+#define DPI_ESAV_CODE_SET1	0xAC
+#define ESAV_CODE2			(0xFFF << 0)
+#define ESAV_CODE3_MSB			BIT(16)
+
+#define DPI_H_FRE_CON		0xE0
+#define H_FRE_2N			BIT(25)
+#endif /* __MTK_DPI_REGS_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_drm_crtc.c linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_drm_crtc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_drm_crtc.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,582 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include <asm/barrier.h>
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_plane_helper.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+#include <soc/mediatek/smi.h>
+
+#include "mtk_drm_drv.h"
+#include "mtk_drm_crtc.h"
+#include "mtk_drm_ddp.h"
+#include "mtk_drm_ddp_comp.h"
+#include "mtk_drm_gem.h"
+#include "mtk_drm_plane.h"
+
+/**
+ * struct mtk_drm_crtc - MediaTek specific crtc structure.
+ * @base: crtc object.
+ * @enabled: records whether crtc_enable succeeded
+ * @planes: array of 4 mtk_drm_plane structures, one for each overlay plane
+ * @pending_planes: whether any plane has pending changes to be applied
+ * @config_regs: memory mapped mmsys configuration register space
+ * @mutex: handle to one of the ten disp_mutex streams
+ * @ddp_comp_nr: number of components in ddp_comp
+ * @ddp_comp: array of pointers the mtk_ddp_comp structures used by this crtc
+ */
+struct mtk_drm_crtc {
+	struct drm_crtc			base;
+	bool				enabled;
+
+	bool				pending_needs_vblank;
+	struct drm_pending_vblank_event	*event;
+
+	struct mtk_drm_plane		planes[OVL_LAYER_NR];
+	bool				pending_planes;
+
+	void __iomem			*config_regs;
+	struct mtk_disp_mutex		*mutex;
+	unsigned int			ddp_comp_nr;
+	struct mtk_ddp_comp		**ddp_comp;
+};
+
+struct mtk_crtc_state {
+	struct drm_crtc_state		base;
+
+	bool				pending_config;
+	unsigned int			pending_width;
+	unsigned int			pending_height;
+	unsigned int			pending_vrefresh;
+};
+
+static inline struct mtk_drm_crtc *to_mtk_crtc(struct drm_crtc *c)
+{
+	return container_of(c, struct mtk_drm_crtc, base);
+}
+
+static inline struct mtk_crtc_state *to_mtk_crtc_state(struct drm_crtc_state *s)
+{
+	return container_of(s, struct mtk_crtc_state, base);
+}
+
+static void mtk_drm_crtc_finish_page_flip(struct mtk_drm_crtc *mtk_crtc)
+{
+	struct drm_crtc *crtc = &mtk_crtc->base;
+	unsigned long flags;
+
+	spin_lock_irqsave(&crtc->dev->event_lock, flags);
+	drm_crtc_send_vblank_event(crtc, mtk_crtc->event);
+	drm_crtc_vblank_put(crtc);
+	mtk_crtc->event = NULL;
+	spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+}
+
+static void mtk_drm_finish_page_flip(struct mtk_drm_crtc *mtk_crtc)
+{
+	drm_crtc_handle_vblank(&mtk_crtc->base);
+	if (mtk_crtc->pending_needs_vblank) {
+		mtk_drm_crtc_finish_page_flip(mtk_crtc);
+		mtk_crtc->pending_needs_vblank = false;
+	}
+}
+
+static void mtk_drm_crtc_destroy(struct drm_crtc *crtc)
+{
+	struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
+	int i;
+
+	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
+		clk_unprepare(mtk_crtc->ddp_comp[i]->clk);
+
+	mtk_disp_mutex_put(mtk_crtc->mutex);
+
+	drm_crtc_cleanup(crtc);
+}
+
+static void mtk_drm_crtc_reset(struct drm_crtc *crtc)
+{
+	struct mtk_crtc_state *state;
+
+	if (crtc->state) {
+		if (crtc->state->mode_blob)
+			drm_property_unreference_blob(crtc->state->mode_blob);
+
+		state = to_mtk_crtc_state(crtc->state);
+		memset(state, 0, sizeof(*state));
+	} else {
+		state = kzalloc(sizeof(*state), GFP_KERNEL);
+		if (!state)
+			return;
+		crtc->state = &state->base;
+	}
+
+	state->base.crtc = crtc;
+}
+
+static struct drm_crtc_state *mtk_drm_crtc_duplicate_state(struct drm_crtc *crtc)
+{
+	struct mtk_crtc_state *state;
+
+	state = kzalloc(sizeof(*state), GFP_KERNEL);
+	if (!state)
+		return NULL;
+
+	__drm_atomic_helper_crtc_duplicate_state(crtc, &state->base);
+
+	WARN_ON(state->base.crtc != crtc);
+	state->base.crtc = crtc;
+
+	return &state->base;
+}
+
+static void mtk_drm_crtc_destroy_state(struct drm_crtc *crtc,
+				       struct drm_crtc_state *state)
+{
+	__drm_atomic_helper_crtc_destroy_state(state);
+	kfree(to_mtk_crtc_state(state));
+}
+
+static bool mtk_drm_crtc_mode_fixup(struct drm_crtc *crtc,
+				    const struct drm_display_mode *mode,
+				    struct drm_display_mode *adjusted_mode)
+{
+	/* Nothing to do here, but this callback is mandatory. */
+	return true;
+}
+
+static void mtk_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
+{
+	struct mtk_crtc_state *state = to_mtk_crtc_state(crtc->state);
+
+	state->pending_width = crtc->mode.hdisplay;
+	state->pending_height = crtc->mode.vdisplay;
+	state->pending_vrefresh = crtc->mode.vrefresh;
+	wmb();	/* Make sure the above parameters are set before update */
+	state->pending_config = true;
+}
+
+int mtk_drm_crtc_enable_vblank(struct drm_device *drm, unsigned int pipe)
+{
+	struct mtk_drm_private *priv = drm->dev_private;
+	struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(priv->crtc[pipe]);
+	struct mtk_ddp_comp *ovl = mtk_crtc->ddp_comp[0];
+
+	mtk_ddp_comp_enable_vblank(ovl, &mtk_crtc->base);
+
+	return 0;
+}
+
+void mtk_drm_crtc_disable_vblank(struct drm_device *drm, unsigned int pipe)
+{
+	struct mtk_drm_private *priv = drm->dev_private;
+	struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(priv->crtc[pipe]);
+	struct mtk_ddp_comp *ovl = mtk_crtc->ddp_comp[0];
+
+	mtk_ddp_comp_disable_vblank(ovl);
+}
+
+static int mtk_crtc_ddp_clk_enable(struct mtk_drm_crtc *mtk_crtc)
+{
+	int ret;
+	int i;
+
+	DRM_DEBUG_DRIVER("%s\n", __func__);
+	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
+		ret = clk_enable(mtk_crtc->ddp_comp[i]->clk);
+		if (ret) {
+			DRM_ERROR("Failed to enable clock %d: %d\n", i, ret);
+			goto err;
+		}
+	}
+
+	return 0;
+err:
+	while (--i >= 0)
+		clk_disable(mtk_crtc->ddp_comp[i]->clk);
+	return ret;
+}
+
+static void mtk_crtc_ddp_clk_disable(struct mtk_drm_crtc *mtk_crtc)
+{
+	int i;
+
+	DRM_DEBUG_DRIVER("%s\n", __func__);
+	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
+		clk_disable(mtk_crtc->ddp_comp[i]->clk);
+}
+
+static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc)
+{
+	struct drm_crtc *crtc = &mtk_crtc->base;
+	unsigned int width, height, vrefresh;
+	int ret;
+	int i;
+
+	DRM_DEBUG_DRIVER("%s\n", __func__);
+	if (WARN_ON(!crtc->state))
+		return -EINVAL;
+
+	width = crtc->state->adjusted_mode.hdisplay;
+	height = crtc->state->adjusted_mode.vdisplay;
+	vrefresh = crtc->state->adjusted_mode.vrefresh;
+
+	ret = pm_runtime_get_sync(crtc->dev->dev);
+	if (ret < 0) {
+		DRM_ERROR("Failed to enable power domain: %d\n", ret);
+		return ret;
+	}
+
+	ret = mtk_disp_mutex_prepare(mtk_crtc->mutex);
+	if (ret < 0) {
+		DRM_ERROR("Failed to enable mutex clock: %d\n", ret);
+		goto err_pm_runtime_put;
+	}
+
+	ret = mtk_crtc_ddp_clk_enable(mtk_crtc);
+	if (ret < 0) {
+		DRM_ERROR("Failed to enable component clocks: %d\n", ret);
+		goto err_mutex_unprepare;
+	}
+
+	DRM_DEBUG_DRIVER("mediatek_ddp_ddp_path_setup\n");
+	for (i = 0; i < mtk_crtc->ddp_comp_nr - 1; i++) {
+		mtk_ddp_add_comp_to_path(mtk_crtc->config_regs,
+					 mtk_crtc->ddp_comp[i]->id,
+					 mtk_crtc->ddp_comp[i + 1]->id);
+		mtk_disp_mutex_add_comp(mtk_crtc->mutex,
+					mtk_crtc->ddp_comp[i]->id);
+	}
+	mtk_disp_mutex_add_comp(mtk_crtc->mutex, mtk_crtc->ddp_comp[i]->id);
+	mtk_disp_mutex_enable(mtk_crtc->mutex);
+
+	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
+		struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[i];
+
+		mtk_ddp_comp_config(comp, width, height, vrefresh);
+		mtk_ddp_comp_start(comp);
+	}
+
+	/* Initially configure all planes */
+	for (i = 0; i < OVL_LAYER_NR; i++) {
+		struct drm_plane *plane = &mtk_crtc->planes[i].base;
+		struct mtk_plane_state *plane_state;
+
+		plane_state = to_mtk_plane_state(plane->state);
+		mtk_ddp_comp_layer_config(mtk_crtc->ddp_comp[0], i,
+					  plane_state);
+	}
+
+	return 0;
+
+err_mutex_unprepare:
+	mtk_disp_mutex_unprepare(mtk_crtc->mutex);
+err_pm_runtime_put:
+	pm_runtime_put(crtc->dev->dev);
+	return ret;
+}
+
+static void mtk_crtc_ddp_hw_fini(struct mtk_drm_crtc *mtk_crtc)
+{
+	struct drm_device *drm = mtk_crtc->base.dev;
+	int i;
+
+	DRM_DEBUG_DRIVER("%s\n", __func__);
+	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
+		mtk_ddp_comp_stop(mtk_crtc->ddp_comp[i]);
+	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++)
+		mtk_disp_mutex_remove_comp(mtk_crtc->mutex,
+					   mtk_crtc->ddp_comp[i]->id);
+	mtk_disp_mutex_disable(mtk_crtc->mutex);
+	for (i = 0; i < mtk_crtc->ddp_comp_nr - 1; i++) {
+		mtk_ddp_remove_comp_from_path(mtk_crtc->config_regs,
+					      mtk_crtc->ddp_comp[i]->id,
+					      mtk_crtc->ddp_comp[i + 1]->id);
+		mtk_disp_mutex_remove_comp(mtk_crtc->mutex,
+					   mtk_crtc->ddp_comp[i]->id);
+	}
+	mtk_disp_mutex_remove_comp(mtk_crtc->mutex, mtk_crtc->ddp_comp[i]->id);
+	mtk_crtc_ddp_clk_disable(mtk_crtc);
+	mtk_disp_mutex_unprepare(mtk_crtc->mutex);
+
+	pm_runtime_put(drm->dev);
+}
+
+static void mtk_drm_crtc_enable(struct drm_crtc *crtc)
+{
+	struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
+	struct mtk_ddp_comp *ovl = mtk_crtc->ddp_comp[0];
+	int ret;
+
+	DRM_DEBUG_DRIVER("%s %d\n", __func__, crtc->base.id);
+
+	ret = mtk_smi_larb_get(ovl->larb_dev);
+	if (ret) {
+		DRM_ERROR("Failed to get larb: %d\n", ret);
+		return;
+	}
+
+	ret = mtk_crtc_ddp_hw_init(mtk_crtc);
+	if (ret) {
+		mtk_smi_larb_put(ovl->larb_dev);
+		return;
+	}
+
+	drm_crtc_vblank_on(crtc);
+	mtk_crtc->enabled = true;
+}
+
+static void mtk_drm_crtc_disable(struct drm_crtc *crtc)
+{
+	struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
+	struct mtk_ddp_comp *ovl = mtk_crtc->ddp_comp[0];
+	int i;
+
+	DRM_DEBUG_DRIVER("%s %d\n", __func__, crtc->base.id);
+	if (!mtk_crtc->enabled)
+		return;
+
+	/* Set all pending plane state to disabled */
+	for (i = 0; i < OVL_LAYER_NR; i++) {
+		struct drm_plane *plane = &mtk_crtc->planes[i].base;
+		struct mtk_plane_state *plane_state;
+
+		plane_state = to_mtk_plane_state(plane->state);
+		plane_state->pending.enable = false;
+		plane_state->pending.config = true;
+	}
+	mtk_crtc->pending_planes = true;
+
+	/* Wait for planes to be disabled */
+	drm_crtc_wait_one_vblank(crtc);
+
+	drm_crtc_vblank_off(crtc);
+	mtk_crtc_ddp_hw_fini(mtk_crtc);
+	mtk_smi_larb_put(ovl->larb_dev);
+
+	mtk_crtc->enabled = false;
+}
+
+static void mtk_drm_crtc_atomic_begin(struct drm_crtc *crtc,
+				      struct drm_crtc_state *old_crtc_state)
+{
+	struct mtk_crtc_state *state = to_mtk_crtc_state(crtc->state);
+	struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
+
+	if (mtk_crtc->event && state->base.event)
+		DRM_ERROR("new event while there is still a pending event\n");
+
+	if (state->base.event) {
+		state->base.event->pipe = drm_crtc_index(crtc);
+		WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+		mtk_crtc->event = state->base.event;
+		state->base.event = NULL;
+	}
+}
+
+static void mtk_drm_crtc_atomic_flush(struct drm_crtc *crtc,
+				      struct drm_crtc_state *old_crtc_state)
+{
+	struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
+	unsigned int pending_planes = 0;
+	int i;
+
+	if (mtk_crtc->event)
+		mtk_crtc->pending_needs_vblank = true;
+	for (i = 0; i < OVL_LAYER_NR; i++) {
+		struct drm_plane *plane = &mtk_crtc->planes[i].base;
+		struct mtk_plane_state *plane_state;
+
+		plane_state = to_mtk_plane_state(plane->state);
+		if (plane_state->pending.dirty) {
+			plane_state->pending.config = true;
+			plane_state->pending.dirty = false;
+			pending_planes |= BIT(i);
+		}
+	}
+	if (pending_planes)
+		mtk_crtc->pending_planes = true;
+}
+
+static const struct drm_crtc_funcs mtk_crtc_funcs = {
+	.set_config		= drm_atomic_helper_set_config,
+	.page_flip		= drm_atomic_helper_page_flip,
+	.destroy		= mtk_drm_crtc_destroy,
+	.reset			= mtk_drm_crtc_reset,
+	.atomic_duplicate_state	= mtk_drm_crtc_duplicate_state,
+	.atomic_destroy_state	= mtk_drm_crtc_destroy_state,
+};
+
+static const struct drm_crtc_helper_funcs mtk_crtc_helper_funcs = {
+	.mode_fixup	= mtk_drm_crtc_mode_fixup,
+	.mode_set_nofb	= mtk_drm_crtc_mode_set_nofb,
+	.enable		= mtk_drm_crtc_enable,
+	.disable	= mtk_drm_crtc_disable,
+	.atomic_begin	= mtk_drm_crtc_atomic_begin,
+	.atomic_flush	= mtk_drm_crtc_atomic_flush,
+};
+
+static int mtk_drm_crtc_init(struct drm_device *drm,
+			     struct mtk_drm_crtc *mtk_crtc,
+			     struct drm_plane *primary,
+			     struct drm_plane *cursor, unsigned int pipe)
+{
+	int ret;
+
+	ret = drm_crtc_init_with_planes(drm, &mtk_crtc->base, primary, cursor,
+					&mtk_crtc_funcs, NULL);
+	if (ret)
+		goto err_cleanup_crtc;
+
+	drm_crtc_helper_add(&mtk_crtc->base, &mtk_crtc_helper_funcs);
+
+	return 0;
+
+err_cleanup_crtc:
+	drm_crtc_cleanup(&mtk_crtc->base);
+	return ret;
+}
+
+void mtk_crtc_ddp_irq(struct drm_crtc *crtc, struct mtk_ddp_comp *ovl)
+{
+	struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
+	struct mtk_crtc_state *state = to_mtk_crtc_state(mtk_crtc->base.state);
+	unsigned int i;
+
+	/*
+	 * TODO: instead of updating the registers here, we should prepare
+	 * working registers in atomic_commit and let the hardware command
+	 * queue update module registers on vblank.
+	 */
+	if (state->pending_config) {
+		mtk_ddp_comp_config(ovl, state->pending_width,
+				    state->pending_height,
+				    state->pending_vrefresh);
+
+		state->pending_config = false;
+	}
+
+	if (mtk_crtc->pending_planes) {
+		for (i = 0; i < OVL_LAYER_NR; i++) {
+			struct drm_plane *plane = &mtk_crtc->planes[i].base;
+			struct mtk_plane_state *plane_state;
+
+			plane_state = to_mtk_plane_state(plane->state);
+
+			if (plane_state->pending.config) {
+				mtk_ddp_comp_layer_config(ovl, i, plane_state);
+				plane_state->pending.config = false;
+			}
+		}
+		mtk_crtc->pending_planes = false;
+	}
+
+	mtk_drm_finish_page_flip(mtk_crtc);
+}
+
+int mtk_drm_crtc_create(struct drm_device *drm_dev,
+			const enum mtk_ddp_comp_id *path, unsigned int path_len)
+{
+	struct mtk_drm_private *priv = drm_dev->dev_private;
+	struct device *dev = drm_dev->dev;
+	struct mtk_drm_crtc *mtk_crtc;
+	enum drm_plane_type type;
+	unsigned int zpos;
+	int pipe = priv->num_pipes;
+	int ret;
+	int i;
+
+	for (i = 0; i < path_len; i++) {
+		enum mtk_ddp_comp_id comp_id = path[i];
+		struct device_node *node;
+
+		node = priv->comp_node[comp_id];
+		if (!node) {
+			dev_info(dev,
+				 "Not creating crtc %d because component %d is disabled or missing\n",
+				 pipe, comp_id);
+			return 0;
+		}
+	}
+
+	mtk_crtc = devm_kzalloc(dev, sizeof(*mtk_crtc), GFP_KERNEL);
+	if (!mtk_crtc)
+		return -ENOMEM;
+
+	mtk_crtc->config_regs = priv->config_regs;
+	mtk_crtc->ddp_comp_nr = path_len;
+	mtk_crtc->ddp_comp = devm_kmalloc_array(dev, mtk_crtc->ddp_comp_nr,
+						sizeof(*mtk_crtc->ddp_comp),
+						GFP_KERNEL);
+
+	mtk_crtc->mutex = mtk_disp_mutex_get(priv->mutex_dev, pipe);
+	if (IS_ERR(mtk_crtc->mutex)) {
+		ret = PTR_ERR(mtk_crtc->mutex);
+		dev_err(dev, "Failed to get mutex: %d\n", ret);
+		return ret;
+	}
+
+	for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
+		enum mtk_ddp_comp_id comp_id = path[i];
+		struct mtk_ddp_comp *comp;
+		struct device_node *node;
+
+		node = priv->comp_node[comp_id];
+		comp = priv->ddp_comp[comp_id];
+		if (!comp) {
+			dev_err(dev, "Component %s not initialized\n",
+				node->full_name);
+			ret = -ENODEV;
+			goto unprepare;
+		}
+
+		ret = clk_prepare(comp->clk);
+		if (ret) {
+			dev_err(dev,
+				"Failed to prepare clock for component %s: %d\n",
+				node->full_name, ret);
+			goto unprepare;
+		}
+
+		mtk_crtc->ddp_comp[i] = comp;
+	}
+
+	for (zpos = 0; zpos < OVL_LAYER_NR; zpos++) {
+		type = (zpos == 0) ? DRM_PLANE_TYPE_PRIMARY :
+				(zpos == 1) ? DRM_PLANE_TYPE_CURSOR :
+						DRM_PLANE_TYPE_OVERLAY;
+		ret = mtk_plane_init(drm_dev, &mtk_crtc->planes[zpos],
+				     BIT(pipe), type, zpos);
+		if (ret)
+			goto unprepare;
+	}
+
+	ret = mtk_drm_crtc_init(drm_dev, mtk_crtc, &mtk_crtc->planes[0].base,
+				&mtk_crtc->planes[1].base, pipe);
+	if (ret < 0)
+		goto unprepare;
+
+	priv->crtc[pipe] = &mtk_crtc->base;
+	priv->num_pipes++;
+
+	return 0;
+
+unprepare:
+	while (--i >= 0)
+		clk_unprepare(mtk_crtc->ddp_comp[i]->clk);
+
+	return ret;
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_drm_crtc.h linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_drm_crtc.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_drm_crtc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_drm_crtc.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef MTK_DRM_CRTC_H
+#define MTK_DRM_CRTC_H
+
+#include <drm/drm_crtc.h>
+#include "mtk_drm_ddp_comp.h"
+#include "mtk_drm_plane.h"
+
+#define OVL_LAYER_NR	4
+
+int mtk_drm_crtc_enable_vblank(struct drm_device *drm, unsigned int pipe);
+void mtk_drm_crtc_disable_vblank(struct drm_device *drm, unsigned int pipe);
+void mtk_drm_crtc_check_flush(struct drm_crtc *crtc);
+void mtk_drm_crtc_commit(struct drm_crtc *crtc);
+void mtk_crtc_ddp_irq(struct drm_crtc *crtc, struct mtk_ddp_comp *ovl);
+int mtk_drm_crtc_create(struct drm_device *drm_dev,
+			const enum mtk_ddp_comp_id *path,
+			unsigned int path_len);
+
+#endif /* MTK_DRM_CRTC_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_drm_ddp.c linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_drm_ddp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_drm_ddp.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,353 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include "mtk_drm_ddp.h"
+#include "mtk_drm_ddp_comp.h"
+
+#define DISP_REG_CONFIG_DISP_OVL0_MOUT_EN	0x040
+#define DISP_REG_CONFIG_DISP_OVL1_MOUT_EN	0x044
+#define DISP_REG_CONFIG_DISP_OD_MOUT_EN		0x048
+#define DISP_REG_CONFIG_DISP_GAMMA_MOUT_EN	0x04c
+#define DISP_REG_CONFIG_DISP_UFOE_MOUT_EN	0x050
+#define DISP_REG_CONFIG_DISP_COLOR0_SEL_IN	0x084
+#define DISP_REG_CONFIG_DISP_COLOR1_SEL_IN	0x088
+#define DISP_REG_CONFIG_DPI_SEL_IN		0x0ac
+#define DISP_REG_CONFIG_DISP_RDMA1_MOUT_EN	0x0c8
+#define DISP_REG_CONFIG_MMSYS_CG_CON0		0x100
+
+#define DISP_REG_MUTEX_EN(n)	(0x20 + 0x20 * (n))
+#define DISP_REG_MUTEX_RST(n)	(0x28 + 0x20 * (n))
+#define DISP_REG_MUTEX_MOD(n)	(0x2c + 0x20 * (n))
+#define DISP_REG_MUTEX_SOF(n)	(0x30 + 0x20 * (n))
+
+#define MUTEX_MOD_DISP_OVL0		BIT(11)
+#define MUTEX_MOD_DISP_OVL1		BIT(12)
+#define MUTEX_MOD_DISP_RDMA0		BIT(13)
+#define MUTEX_MOD_DISP_RDMA1		BIT(14)
+#define MUTEX_MOD_DISP_RDMA2		BIT(15)
+#define MUTEX_MOD_DISP_WDMA0		BIT(16)
+#define MUTEX_MOD_DISP_WDMA1		BIT(17)
+#define MUTEX_MOD_DISP_COLOR0		BIT(18)
+#define MUTEX_MOD_DISP_COLOR1		BIT(19)
+#define MUTEX_MOD_DISP_AAL		BIT(20)
+#define MUTEX_MOD_DISP_GAMMA		BIT(21)
+#define MUTEX_MOD_DISP_UFOE		BIT(22)
+#define MUTEX_MOD_DISP_PWM0		BIT(23)
+#define MUTEX_MOD_DISP_PWM1		BIT(24)
+#define MUTEX_MOD_DISP_OD		BIT(25)
+
+#define MUTEX_SOF_SINGLE_MODE		0
+#define MUTEX_SOF_DSI0			1
+#define MUTEX_SOF_DSI1			2
+#define MUTEX_SOF_DPI0			3
+
+#define OVL0_MOUT_EN_COLOR0		0x1
+#define OD_MOUT_EN_RDMA0		0x1
+#define UFOE_MOUT_EN_DSI0		0x1
+#define COLOR0_SEL_IN_OVL0		0x1
+#define OVL1_MOUT_EN_COLOR1		0x1
+#define GAMMA_MOUT_EN_RDMA1		0x1
+#define RDMA1_MOUT_DPI0			0x2
+#define DPI0_SEL_IN_RDMA1		0x1
+#define COLOR1_SEL_IN_OVL1		0x1
+
+struct mtk_disp_mutex {
+	int id;
+	bool claimed;
+};
+
+struct mtk_ddp {
+	struct device			*dev;
+	struct clk			*clk;
+	void __iomem			*regs;
+	struct mtk_disp_mutex		mutex[10];
+};
+
+static const unsigned int mutex_mod[DDP_COMPONENT_ID_MAX] = {
+	[DDP_COMPONENT_AAL] = MUTEX_MOD_DISP_AAL,
+	[DDP_COMPONENT_COLOR0] = MUTEX_MOD_DISP_COLOR0,
+	[DDP_COMPONENT_COLOR1] = MUTEX_MOD_DISP_COLOR1,
+	[DDP_COMPONENT_GAMMA] = MUTEX_MOD_DISP_GAMMA,
+	[DDP_COMPONENT_OD] = MUTEX_MOD_DISP_OD,
+	[DDP_COMPONENT_OVL0] = MUTEX_MOD_DISP_OVL0,
+	[DDP_COMPONENT_OVL1] = MUTEX_MOD_DISP_OVL1,
+	[DDP_COMPONENT_PWM0] = MUTEX_MOD_DISP_PWM0,
+	[DDP_COMPONENT_PWM1] = MUTEX_MOD_DISP_PWM1,
+	[DDP_COMPONENT_RDMA0] = MUTEX_MOD_DISP_RDMA0,
+	[DDP_COMPONENT_RDMA1] = MUTEX_MOD_DISP_RDMA1,
+	[DDP_COMPONENT_RDMA2] = MUTEX_MOD_DISP_RDMA2,
+	[DDP_COMPONENT_UFOE] = MUTEX_MOD_DISP_UFOE,
+	[DDP_COMPONENT_WDMA0] = MUTEX_MOD_DISP_WDMA0,
+	[DDP_COMPONENT_WDMA1] = MUTEX_MOD_DISP_WDMA1,
+};
+
+static unsigned int mtk_ddp_mout_en(enum mtk_ddp_comp_id cur,
+				    enum mtk_ddp_comp_id next,
+				    unsigned int *addr)
+{
+	unsigned int value;
+
+	if (cur == DDP_COMPONENT_OVL0 && next == DDP_COMPONENT_COLOR0) {
+		*addr = DISP_REG_CONFIG_DISP_OVL0_MOUT_EN;
+		value = OVL0_MOUT_EN_COLOR0;
+	} else if (cur == DDP_COMPONENT_OD && next == DDP_COMPONENT_RDMA0) {
+		*addr = DISP_REG_CONFIG_DISP_OD_MOUT_EN;
+		value = OD_MOUT_EN_RDMA0;
+	} else if (cur == DDP_COMPONENT_UFOE && next == DDP_COMPONENT_DSI0) {
+		*addr = DISP_REG_CONFIG_DISP_UFOE_MOUT_EN;
+		value = UFOE_MOUT_EN_DSI0;
+	} else if (cur == DDP_COMPONENT_OVL1 && next == DDP_COMPONENT_COLOR1) {
+		*addr = DISP_REG_CONFIG_DISP_OVL1_MOUT_EN;
+		value = OVL1_MOUT_EN_COLOR1;
+	} else if (cur == DDP_COMPONENT_GAMMA && next == DDP_COMPONENT_RDMA1) {
+		*addr = DISP_REG_CONFIG_DISP_GAMMA_MOUT_EN;
+		value = GAMMA_MOUT_EN_RDMA1;
+	} else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DPI0) {
+		*addr = DISP_REG_CONFIG_DISP_RDMA1_MOUT_EN;
+		value = RDMA1_MOUT_DPI0;
+	} else {
+		value = 0;
+	}
+
+	return value;
+}
+
+static unsigned int mtk_ddp_sel_in(enum mtk_ddp_comp_id cur,
+				   enum mtk_ddp_comp_id next,
+				   unsigned int *addr)
+{
+	unsigned int value;
+
+	if (cur == DDP_COMPONENT_OVL0 && next == DDP_COMPONENT_COLOR0) {
+		*addr = DISP_REG_CONFIG_DISP_COLOR0_SEL_IN;
+		value = COLOR0_SEL_IN_OVL0;
+	} else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DPI0) {
+		*addr = DISP_REG_CONFIG_DPI_SEL_IN;
+		value = DPI0_SEL_IN_RDMA1;
+	} else if (cur == DDP_COMPONENT_OVL1 && next == DDP_COMPONENT_COLOR1) {
+		*addr = DISP_REG_CONFIG_DISP_COLOR1_SEL_IN;
+		value = COLOR1_SEL_IN_OVL1;
+	} else {
+		value = 0;
+	}
+
+	return value;
+}
+
+void mtk_ddp_add_comp_to_path(void __iomem *config_regs,
+			      enum mtk_ddp_comp_id cur,
+			      enum mtk_ddp_comp_id next)
+{
+	unsigned int addr, value, reg;
+
+	value = mtk_ddp_mout_en(cur, next, &addr);
+	if (value) {
+		reg = readl_relaxed(config_regs + addr) | value;
+		writel_relaxed(reg, config_regs + addr);
+	}
+
+	value = mtk_ddp_sel_in(cur, next, &addr);
+	if (value) {
+		reg = readl_relaxed(config_regs + addr) | value;
+		writel_relaxed(reg, config_regs + addr);
+	}
+}
+
+void mtk_ddp_remove_comp_from_path(void __iomem *config_regs,
+				   enum mtk_ddp_comp_id cur,
+				   enum mtk_ddp_comp_id next)
+{
+	unsigned int addr, value, reg;
+
+	value = mtk_ddp_mout_en(cur, next, &addr);
+	if (value) {
+		reg = readl_relaxed(config_regs + addr) & ~value;
+		writel_relaxed(reg, config_regs + addr);
+	}
+
+	value = mtk_ddp_sel_in(cur, next, &addr);
+	if (value) {
+		reg = readl_relaxed(config_regs + addr) & ~value;
+		writel_relaxed(reg, config_regs + addr);
+	}
+}
+
+struct mtk_disp_mutex *mtk_disp_mutex_get(struct device *dev, unsigned int id)
+{
+	struct mtk_ddp *ddp = dev_get_drvdata(dev);
+
+	if (id >= 10)
+		return ERR_PTR(-EINVAL);
+	if (ddp->mutex[id].claimed)
+		return ERR_PTR(-EBUSY);
+
+	ddp->mutex[id].claimed = true;
+
+	return &ddp->mutex[id];
+}
+
+void mtk_disp_mutex_put(struct mtk_disp_mutex *mutex)
+{
+	struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
+					   mutex[mutex->id]);
+
+	WARN_ON(&ddp->mutex[mutex->id] != mutex);
+
+	mutex->claimed = false;
+}
+
+int mtk_disp_mutex_prepare(struct mtk_disp_mutex *mutex)
+{
+	struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
+					   mutex[mutex->id]);
+	return clk_prepare_enable(ddp->clk);
+}
+
+void mtk_disp_mutex_unprepare(struct mtk_disp_mutex *mutex)
+{
+	struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
+					   mutex[mutex->id]);
+	clk_disable_unprepare(ddp->clk);
+}
+
+void mtk_disp_mutex_add_comp(struct mtk_disp_mutex *mutex,
+			     enum mtk_ddp_comp_id id)
+{
+	struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
+					   mutex[mutex->id]);
+	unsigned int reg;
+
+	WARN_ON(&ddp->mutex[mutex->id] != mutex);
+
+	switch (id) {
+	case DDP_COMPONENT_DSI0:
+		reg = MUTEX_SOF_DSI0;
+		break;
+	case DDP_COMPONENT_DSI1:
+		reg = MUTEX_SOF_DSI0;
+		break;
+	case DDP_COMPONENT_DPI0:
+		reg = MUTEX_SOF_DPI0;
+		break;
+	default:
+		reg = readl_relaxed(ddp->regs + DISP_REG_MUTEX_MOD(mutex->id));
+		reg |= mutex_mod[id];
+		writel_relaxed(reg, ddp->regs + DISP_REG_MUTEX_MOD(mutex->id));
+		return;
+	}
+
+	writel_relaxed(reg, ddp->regs + DISP_REG_MUTEX_SOF(mutex->id));
+}
+
+void mtk_disp_mutex_remove_comp(struct mtk_disp_mutex *mutex,
+				enum mtk_ddp_comp_id id)
+{
+	struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
+					   mutex[mutex->id]);
+	unsigned int reg;
+
+	WARN_ON(&ddp->mutex[mutex->id] != mutex);
+
+	switch (id) {
+	case DDP_COMPONENT_DSI0:
+	case DDP_COMPONENT_DSI1:
+	case DDP_COMPONENT_DPI0:
+		writel_relaxed(MUTEX_SOF_SINGLE_MODE,
+			       ddp->regs + DISP_REG_MUTEX_SOF(mutex->id));
+		break;
+	default:
+		reg = readl_relaxed(ddp->regs + DISP_REG_MUTEX_MOD(mutex->id));
+		reg &= ~mutex_mod[id];
+		writel_relaxed(reg, ddp->regs + DISP_REG_MUTEX_MOD(mutex->id));
+		break;
+	}
+}
+
+void mtk_disp_mutex_enable(struct mtk_disp_mutex *mutex)
+{
+	struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
+					   mutex[mutex->id]);
+
+	WARN_ON(&ddp->mutex[mutex->id] != mutex);
+
+	writel(1, ddp->regs + DISP_REG_MUTEX_EN(mutex->id));
+}
+
+void mtk_disp_mutex_disable(struct mtk_disp_mutex *mutex)
+{
+	struct mtk_ddp *ddp = container_of(mutex, struct mtk_ddp,
+					   mutex[mutex->id]);
+
+	WARN_ON(&ddp->mutex[mutex->id] != mutex);
+
+	writel(0, ddp->regs + DISP_REG_MUTEX_EN(mutex->id));
+}
+
+static int mtk_ddp_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct mtk_ddp *ddp;
+	struct resource *regs;
+	int i;
+
+	ddp = devm_kzalloc(dev, sizeof(*ddp), GFP_KERNEL);
+	if (!ddp)
+		return -ENOMEM;
+
+	for (i = 0; i < 10; i++)
+		ddp->mutex[i].id = i;
+
+	ddp->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(ddp->clk)) {
+		dev_err(dev, "Failed to get clock\n");
+		return PTR_ERR(ddp->clk);
+	}
+
+	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	ddp->regs = devm_ioremap_resource(dev, regs);
+	if (IS_ERR(ddp->regs)) {
+		dev_err(dev, "Failed to map mutex registers\n");
+		return PTR_ERR(ddp->regs);
+	}
+
+	platform_set_drvdata(pdev, ddp);
+
+	return 0;
+}
+
+static int mtk_ddp_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static const struct of_device_id ddp_driver_dt_match[] = {
+	{ .compatible = "mediatek,mt8173-disp-mutex" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, ddp_driver_dt_match);
+
+struct platform_driver mtk_ddp_driver = {
+	.probe		= mtk_ddp_probe,
+	.remove		= mtk_ddp_remove,
+	.driver		= {
+		.name	= "mediatek-ddp",
+		.owner	= THIS_MODULE,
+		.of_match_table = ddp_driver_dt_match,
+	},
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ * Authors:
+ *	YT Shen <yt.shen@mediatek.com>
+ *	CK Hu <ck.hu@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <drm/drmP.h>
+#include "mtk_drm_drv.h"
+#include "mtk_drm_plane.h"
+#include "mtk_drm_ddp_comp.h"
+
+#define DISP_OD_EN				0x0000
+#define DISP_OD_INTEN				0x0008
+#define DISP_OD_INTSTA				0x000c
+#define DISP_OD_CFG				0x0020
+#define DISP_OD_SIZE				0x0030
+
+#define DISP_REG_UFO_START			0x0000
+
+#define DISP_COLOR_CFG_MAIN			0x0400
+#define DISP_COLOR_START			0x0c00
+#define DISP_COLOR_WIDTH			0x0c50
+#define DISP_COLOR_HEIGHT			0x0c54
+
+#define	OD_RELAY_MODE		BIT(0)
+
+#define	UFO_BYPASS		BIT(2)
+
+#define	COLOR_BYPASS_ALL	BIT(7)
+#define	COLOR_SEQ_SEL		BIT(13)
+
+static void mtk_color_config(struct mtk_ddp_comp *comp, unsigned int w,
+			     unsigned int h, unsigned int vrefresh)
+{
+	writel(w, comp->regs + DISP_COLOR_WIDTH);
+	writel(h, comp->regs + DISP_COLOR_HEIGHT);
+}
+
+static void mtk_color_start(struct mtk_ddp_comp *comp)
+{
+	writel(COLOR_BYPASS_ALL | COLOR_SEQ_SEL,
+	       comp->regs + DISP_COLOR_CFG_MAIN);
+	writel(0x1, comp->regs + DISP_COLOR_START);
+}
+
+static void mtk_od_config(struct mtk_ddp_comp *comp, unsigned int w,
+			  unsigned int h, unsigned int vrefresh)
+{
+	writel(w << 16 | h, comp->regs + DISP_OD_SIZE);
+}
+
+static void mtk_od_start(struct mtk_ddp_comp *comp)
+{
+	writel(OD_RELAY_MODE, comp->regs + DISP_OD_CFG);
+	writel(1, comp->regs + DISP_OD_EN);
+}
+
+static void mtk_ufoe_start(struct mtk_ddp_comp *comp)
+{
+	writel(UFO_BYPASS, comp->regs + DISP_REG_UFO_START);
+}
+
+static const struct mtk_ddp_comp_funcs ddp_color = {
+	.config = mtk_color_config,
+	.start = mtk_color_start,
+};
+
+static const struct mtk_ddp_comp_funcs ddp_od = {
+	.config = mtk_od_config,
+	.start = mtk_od_start,
+};
+
+static const struct mtk_ddp_comp_funcs ddp_ufoe = {
+	.start = mtk_ufoe_start,
+};
+
+static const char * const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {
+	[MTK_DISP_OVL] = "ovl",
+	[MTK_DISP_RDMA] = "rdma",
+	[MTK_DISP_WDMA] = "wdma",
+	[MTK_DISP_COLOR] = "color",
+	[MTK_DISP_AAL] = "aal",
+	[MTK_DISP_GAMMA] = "gamma",
+	[MTK_DISP_UFOE] = "ufoe",
+	[MTK_DSI] = "dsi",
+	[MTK_DPI] = "dpi",
+	[MTK_DISP_PWM] = "pwm",
+	[MTK_DISP_MUTEX] = "mutex",
+	[MTK_DISP_OD] = "od",
+};
+
+struct mtk_ddp_comp_match {
+	enum mtk_ddp_comp_type type;
+	int alias_id;
+	const struct mtk_ddp_comp_funcs *funcs;
+};
+
+static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_ID_MAX] = {
+	[DDP_COMPONENT_AAL]	= { MTK_DISP_AAL,	0, NULL },
+	[DDP_COMPONENT_COLOR0]	= { MTK_DISP_COLOR,	0, &ddp_color },
+	[DDP_COMPONENT_COLOR1]	= { MTK_DISP_COLOR,	1, &ddp_color },
+	[DDP_COMPONENT_DPI0]	= { MTK_DPI,		0, NULL },
+	[DDP_COMPONENT_DSI0]	= { MTK_DSI,		0, NULL },
+	[DDP_COMPONENT_DSI1]	= { MTK_DSI,		1, NULL },
+	[DDP_COMPONENT_GAMMA]	= { MTK_DISP_GAMMA,	0, NULL },
+	[DDP_COMPONENT_OD]	= { MTK_DISP_OD,	0, &ddp_od },
+	[DDP_COMPONENT_OVL0]	= { MTK_DISP_OVL,	0, NULL },
+	[DDP_COMPONENT_OVL1]	= { MTK_DISP_OVL,	1, NULL },
+	[DDP_COMPONENT_PWM0]	= { MTK_DISP_PWM,	0, NULL },
+	[DDP_COMPONENT_RDMA0]	= { MTK_DISP_RDMA,	0, NULL },
+	[DDP_COMPONENT_RDMA1]	= { MTK_DISP_RDMA,	1, NULL },
+	[DDP_COMPONENT_RDMA2]	= { MTK_DISP_RDMA,	2, NULL },
+	[DDP_COMPONENT_UFOE]	= { MTK_DISP_UFOE,	0, &ddp_ufoe },
+	[DDP_COMPONENT_WDMA0]	= { MTK_DISP_WDMA,	0, NULL },
+	[DDP_COMPONENT_WDMA1]	= { MTK_DISP_WDMA,	1, NULL },
+};
+
+int mtk_ddp_comp_get_id(struct device_node *node,
+			enum mtk_ddp_comp_type comp_type)
+{
+	int id = of_alias_get_id(node, mtk_ddp_comp_stem[comp_type]);
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(mtk_ddp_matches); i++) {
+		if (comp_type == mtk_ddp_matches[i].type &&
+		    (id < 0 || id == mtk_ddp_matches[i].alias_id))
+			return i;
+	}
+
+	return -EINVAL;
+}
+
+int mtk_ddp_comp_init(struct device *dev, struct device_node *node,
+		      struct mtk_ddp_comp *comp, enum mtk_ddp_comp_id comp_id,
+		      const struct mtk_ddp_comp_funcs *funcs)
+{
+	enum mtk_ddp_comp_type type;
+	struct device_node *larb_node;
+	struct platform_device *larb_pdev;
+
+	if (comp_id < 0 || comp_id >= DDP_COMPONENT_ID_MAX)
+		return -EINVAL;
+
+	comp->id = comp_id;
+	comp->funcs = funcs ?: mtk_ddp_matches[comp_id].funcs;
+
+	if (comp_id == DDP_COMPONENT_DPI0 ||
+	    comp_id == DDP_COMPONENT_DSI0 ||
+	    comp_id == DDP_COMPONENT_PWM0) {
+		comp->regs = NULL;
+		comp->clk = NULL;
+		comp->irq = 0;
+		return 0;
+	}
+
+	comp->regs = of_iomap(node, 0);
+	comp->irq = of_irq_get(node, 0);
+	comp->clk = of_clk_get(node, 0);
+	if (IS_ERR(comp->clk))
+		comp->clk = NULL;
+
+	type = mtk_ddp_matches[comp_id].type;
+
+	/* Only DMA capable components need the LARB property */
+	comp->larb_dev = NULL;
+	if (type != MTK_DISP_OVL &&
+	    type != MTK_DISP_RDMA &&
+	    type != MTK_DISP_WDMA)
+		return 0;
+
+	larb_node = of_parse_phandle(node, "mediatek,larb", 0);
+	if (!larb_node) {
+		dev_err(dev,
+			"Missing mediadek,larb phandle in %s node\n",
+			node->full_name);
+		return -EINVAL;
+	}
+
+	larb_pdev = of_find_device_by_node(larb_node);
+	if (!larb_pdev) {
+		dev_warn(dev, "Waiting for larb device %s\n",
+			 larb_node->full_name);
+		of_node_put(larb_node);
+		return -EPROBE_DEFER;
+	}
+	of_node_put(larb_node);
+
+	comp->larb_dev = &larb_pdev->dev;
+
+	return 0;
+}
+
+int mtk_ddp_comp_register(struct drm_device *drm, struct mtk_ddp_comp *comp)
+{
+	struct mtk_drm_private *private = drm->dev_private;
+
+	if (private->ddp_comp[comp->id])
+		return -EBUSY;
+
+	private->ddp_comp[comp->id] = comp;
+	return 0;
+}
+
+void mtk_ddp_comp_unregister(struct drm_device *drm, struct mtk_ddp_comp *comp)
+{
+	struct mtk_drm_private *private = drm->dev_private;
+
+	private->ddp_comp[comp->id] = NULL;
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef MTK_DRM_DDP_COMP_H
+#define MTK_DRM_DDP_COMP_H
+
+#include <linux/io.h>
+
+struct device;
+struct device_node;
+struct drm_crtc;
+struct drm_device;
+struct mtk_plane_state;
+
+enum mtk_ddp_comp_type {
+	MTK_DISP_OVL,
+	MTK_DISP_RDMA,
+	MTK_DISP_WDMA,
+	MTK_DISP_COLOR,
+	MTK_DISP_AAL,
+	MTK_DISP_GAMMA,
+	MTK_DISP_UFOE,
+	MTK_DSI,
+	MTK_DPI,
+	MTK_DISP_PWM,
+	MTK_DISP_MUTEX,
+	MTK_DISP_OD,
+	MTK_DDP_COMP_TYPE_MAX,
+};
+
+enum mtk_ddp_comp_id {
+	DDP_COMPONENT_AAL,
+	DDP_COMPONENT_COLOR0,
+	DDP_COMPONENT_COLOR1,
+	DDP_COMPONENT_DPI0,
+	DDP_COMPONENT_DSI0,
+	DDP_COMPONENT_DSI1,
+	DDP_COMPONENT_GAMMA,
+	DDP_COMPONENT_OD,
+	DDP_COMPONENT_OVL0,
+	DDP_COMPONENT_OVL1,
+	DDP_COMPONENT_PWM0,
+	DDP_COMPONENT_PWM1,
+	DDP_COMPONENT_RDMA0,
+	DDP_COMPONENT_RDMA1,
+	DDP_COMPONENT_RDMA2,
+	DDP_COMPONENT_UFOE,
+	DDP_COMPONENT_WDMA0,
+	DDP_COMPONENT_WDMA1,
+	DDP_COMPONENT_ID_MAX,
+};
+
+struct mtk_ddp_comp;
+
+struct mtk_ddp_comp_funcs {
+	void (*config)(struct mtk_ddp_comp *comp, unsigned int w,
+		       unsigned int h, unsigned int vrefresh);
+	void (*start)(struct mtk_ddp_comp *comp);
+	void (*stop)(struct mtk_ddp_comp *comp);
+	void (*enable_vblank)(struct mtk_ddp_comp *comp, struct drm_crtc *crtc);
+	void (*disable_vblank)(struct mtk_ddp_comp *comp);
+	void (*layer_on)(struct mtk_ddp_comp *comp, unsigned int idx);
+	void (*layer_off)(struct mtk_ddp_comp *comp, unsigned int idx);
+	void (*layer_config)(struct mtk_ddp_comp *comp, unsigned int idx,
+			     struct mtk_plane_state *state);
+};
+
+struct mtk_ddp_comp {
+	struct clk *clk;
+	void __iomem *regs;
+	int irq;
+	struct device *larb_dev;
+	enum mtk_ddp_comp_id id;
+	const struct mtk_ddp_comp_funcs *funcs;
+};
+
+static inline void mtk_ddp_comp_config(struct mtk_ddp_comp *comp,
+				       unsigned int w, unsigned int h,
+				       unsigned int vrefresh)
+{
+	if (comp->funcs && comp->funcs->config)
+		comp->funcs->config(comp, w, h, vrefresh);
+}
+
+static inline void mtk_ddp_comp_start(struct mtk_ddp_comp *comp)
+{
+	if (comp->funcs && comp->funcs->start)
+		comp->funcs->start(comp);
+}
+
+static inline void mtk_ddp_comp_stop(struct mtk_ddp_comp *comp)
+{
+	if (comp->funcs && comp->funcs->stop)
+		comp->funcs->stop(comp);
+}
+
+static inline void mtk_ddp_comp_enable_vblank(struct mtk_ddp_comp *comp,
+					      struct drm_crtc *crtc)
+{
+	if (comp->funcs && comp->funcs->enable_vblank)
+		comp->funcs->enable_vblank(comp, crtc);
+}
+
+static inline void mtk_ddp_comp_disable_vblank(struct mtk_ddp_comp *comp)
+{
+	if (comp->funcs && comp->funcs->disable_vblank)
+		comp->funcs->disable_vblank(comp);
+}
+
+static inline void mtk_ddp_comp_layer_on(struct mtk_ddp_comp *comp,
+					 unsigned int idx)
+{
+	if (comp->funcs && comp->funcs->layer_on)
+		comp->funcs->layer_on(comp, idx);
+}
+
+static inline void mtk_ddp_comp_layer_off(struct mtk_ddp_comp *comp,
+					  unsigned int idx)
+{
+	if (comp->funcs && comp->funcs->layer_off)
+		comp->funcs->layer_off(comp, idx);
+}
+
+static inline void mtk_ddp_comp_layer_config(struct mtk_ddp_comp *comp,
+					     unsigned int idx,
+					     struct mtk_plane_state *state)
+{
+	if (comp->funcs && comp->funcs->layer_config)
+		comp->funcs->layer_config(comp, idx, state);
+}
+
+int mtk_ddp_comp_get_id(struct device_node *node,
+			enum mtk_ddp_comp_type comp_type);
+int mtk_ddp_comp_init(struct device *dev, struct device_node *comp_node,
+		      struct mtk_ddp_comp *comp, enum mtk_ddp_comp_id comp_id,
+		      const struct mtk_ddp_comp_funcs *funcs);
+int mtk_ddp_comp_register(struct drm_device *drm, struct mtk_ddp_comp *comp);
+void mtk_ddp_comp_unregister(struct drm_device *drm, struct mtk_ddp_comp *comp);
+
+#endif /* MTK_DRM_DDP_COMP_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_drm_ddp.h linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_drm_ddp.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_drm_ddp.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_drm_ddp.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef MTK_DRM_DDP_H
+#define MTK_DRM_DDP_H
+
+#include "mtk_drm_ddp_comp.h"
+
+struct regmap;
+struct device;
+struct mtk_disp_mutex;
+
+void mtk_ddp_add_comp_to_path(void __iomem *config_regs,
+			      enum mtk_ddp_comp_id cur,
+			      enum mtk_ddp_comp_id next);
+void mtk_ddp_remove_comp_from_path(void __iomem *config_regs,
+				   enum mtk_ddp_comp_id cur,
+				   enum mtk_ddp_comp_id next);
+
+struct mtk_disp_mutex *mtk_disp_mutex_get(struct device *dev, unsigned int id);
+int mtk_disp_mutex_prepare(struct mtk_disp_mutex *mutex);
+void mtk_disp_mutex_add_comp(struct mtk_disp_mutex *mutex,
+			     enum mtk_ddp_comp_id id);
+void mtk_disp_mutex_enable(struct mtk_disp_mutex *mutex);
+void mtk_disp_mutex_disable(struct mtk_disp_mutex *mutex);
+void mtk_disp_mutex_remove_comp(struct mtk_disp_mutex *mutex,
+				enum mtk_ddp_comp_id id);
+void mtk_disp_mutex_unprepare(struct mtk_disp_mutex *mutex);
+void mtk_disp_mutex_put(struct mtk_disp_mutex *mutex);
+
+#endif /* MTK_DRM_DDP_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_drm_drv.c linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_drm_drv.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_drm_drv.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_drm_drv.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,567 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ * Author: YT SHEN <yt.shen@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_gem.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <linux/component.h>
+#include <linux/iommu.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/pm_runtime.h>
+
+#include "mtk_drm_crtc.h"
+#include "mtk_drm_ddp.h"
+#include "mtk_drm_ddp_comp.h"
+#include "mtk_drm_drv.h"
+#include "mtk_drm_fb.h"
+#include "mtk_drm_gem.h"
+
+#define DRIVER_NAME "mediatek"
+#define DRIVER_DESC "Mediatek SoC DRM"
+#define DRIVER_DATE "20150513"
+#define DRIVER_MAJOR 1
+#define DRIVER_MINOR 0
+
+static void mtk_atomic_schedule(struct mtk_drm_private *private,
+				struct drm_atomic_state *state)
+{
+	private->commit.state = state;
+	schedule_work(&private->commit.work);
+}
+
+static void mtk_atomic_wait_for_fences(struct drm_atomic_state *state)
+{
+	struct drm_plane *plane;
+	struct drm_plane_state *plane_state;
+	int i;
+
+	for_each_plane_in_state(state, plane, plane_state, i)
+		mtk_fb_wait(plane->state->fb);
+}
+
+static void mtk_atomic_complete(struct mtk_drm_private *private,
+				struct drm_atomic_state *state)
+{
+	struct drm_device *drm = private->drm;
+
+	mtk_atomic_wait_for_fences(state);
+
+	drm_atomic_helper_commit_modeset_disables(drm, state);
+	drm_atomic_helper_commit_planes(drm, state, false);
+	drm_atomic_helper_commit_modeset_enables(drm, state);
+	drm_atomic_helper_wait_for_vblanks(drm, state);
+	drm_atomic_helper_cleanup_planes(drm, state);
+	drm_atomic_state_free(state);
+}
+
+static void mtk_atomic_work(struct work_struct *work)
+{
+	struct mtk_drm_private *private = container_of(work,
+			struct mtk_drm_private, commit.work);
+
+	mtk_atomic_complete(private, private->commit.state);
+}
+
+static int mtk_atomic_commit(struct drm_device *drm,
+			     struct drm_atomic_state *state,
+			     bool async)
+{
+	struct mtk_drm_private *private = drm->dev_private;
+	int ret;
+
+	ret = drm_atomic_helper_prepare_planes(drm, state);
+	if (ret)
+		return ret;
+
+	mutex_lock(&private->commit.lock);
+	flush_work(&private->commit.work);
+
+	drm_atomic_helper_swap_state(drm, state);
+
+	if (async)
+		mtk_atomic_schedule(private, state);
+	else
+		mtk_atomic_complete(private, state);
+
+	mutex_unlock(&private->commit.lock);
+
+	return 0;
+}
+
+static const struct drm_mode_config_funcs mtk_drm_mode_config_funcs = {
+	.fb_create = mtk_drm_mode_fb_create,
+	.atomic_check = drm_atomic_helper_check,
+	.atomic_commit = mtk_atomic_commit,
+};
+
+static const enum mtk_ddp_comp_id mtk_ddp_main[] = {
+	DDP_COMPONENT_OVL0,
+	DDP_COMPONENT_COLOR0,
+	DDP_COMPONENT_AAL,
+	DDP_COMPONENT_OD,
+	DDP_COMPONENT_RDMA0,
+	DDP_COMPONENT_UFOE,
+	DDP_COMPONENT_DSI0,
+	DDP_COMPONENT_PWM0,
+};
+
+static const enum mtk_ddp_comp_id mtk_ddp_ext[] = {
+	DDP_COMPONENT_OVL1,
+	DDP_COMPONENT_COLOR1,
+	DDP_COMPONENT_GAMMA,
+	DDP_COMPONENT_RDMA1,
+	DDP_COMPONENT_DPI0,
+};
+
+static int mtk_drm_kms_init(struct drm_device *drm)
+{
+	struct mtk_drm_private *private = drm->dev_private;
+	struct platform_device *pdev;
+	struct device_node *np;
+	int ret;
+
+	if (!iommu_present(&platform_bus_type))
+		return -EPROBE_DEFER;
+
+	pdev = of_find_device_by_node(private->mutex_node);
+	if (!pdev) {
+		dev_err(drm->dev, "Waiting for disp-mutex device %s\n",
+			private->mutex_node->full_name);
+		of_node_put(private->mutex_node);
+		return -EPROBE_DEFER;
+	}
+	private->mutex_dev = &pdev->dev;
+
+	drm_mode_config_init(drm);
+
+	drm->mode_config.min_width = 64;
+	drm->mode_config.min_height = 64;
+
+	/*
+	 * set max width and height as default value(4096x4096).
+	 * this value would be used to check framebuffer size limitation
+	 * at drm_mode_addfb().
+	 */
+	drm->mode_config.max_width = 4096;
+	drm->mode_config.max_height = 4096;
+	drm->mode_config.funcs = &mtk_drm_mode_config_funcs;
+
+	ret = component_bind_all(drm->dev, drm);
+	if (ret)
+		goto err_config_cleanup;
+
+	/*
+	 * We currently support two fixed data streams, each optional,
+	 * and each statically assigned to a crtc:
+	 * OVL0 -> COLOR0 -> AAL -> OD -> RDMA0 -> UFOE -> DSI0 ...
+	 */
+	ret = mtk_drm_crtc_create(drm, mtk_ddp_main, ARRAY_SIZE(mtk_ddp_main));
+	if (ret < 0)
+		goto err_component_unbind;
+	/* ... and OVL1 -> COLOR1 -> GAMMA -> RDMA1 -> DPI0. */
+	ret = mtk_drm_crtc_create(drm, mtk_ddp_ext, ARRAY_SIZE(mtk_ddp_ext));
+	if (ret < 0)
+		goto err_component_unbind;
+
+	/* Use OVL device for all DMA memory allocations */
+	np = private->comp_node[mtk_ddp_main[0]] ?:
+	     private->comp_node[mtk_ddp_ext[0]];
+	pdev = of_find_device_by_node(np);
+	if (!pdev) {
+		ret = -ENODEV;
+		dev_err(drm->dev, "Need at least one OVL device\n");
+		goto err_component_unbind;
+	}
+
+	private->dma_dev = &pdev->dev;
+
+	/*
+	 * We don't use the drm_irq_install() helpers provided by the DRM
+	 * core, so we need to set this manually in order to allow the
+	 * DRM_IOCTL_WAIT_VBLANK to operate correctly.
+	 */
+	drm->irq_enabled = true;
+	ret = drm_vblank_init(drm, MAX_CRTC);
+	if (ret < 0)
+		goto err_component_unbind;
+
+	drm_kms_helper_poll_init(drm);
+	drm_mode_config_reset(drm);
+
+	return 0;
+
+err_component_unbind:
+	component_unbind_all(drm->dev, drm);
+err_config_cleanup:
+	drm_mode_config_cleanup(drm);
+
+	return ret;
+}
+
+static void mtk_drm_kms_deinit(struct drm_device *drm)
+{
+	drm_kms_helper_poll_fini(drm);
+
+	drm_vblank_cleanup(drm);
+	component_unbind_all(drm->dev, drm);
+	drm_mode_config_cleanup(drm);
+}
+
+static const struct file_operations mtk_drm_fops = {
+	.owner = THIS_MODULE,
+	.open = drm_open,
+	.release = drm_release,
+	.unlocked_ioctl = drm_ioctl,
+	.mmap = mtk_drm_gem_mmap,
+	.poll = drm_poll,
+	.read = drm_read,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = drm_compat_ioctl,
+#endif
+};
+
+static struct drm_driver mtk_drm_driver = {
+	.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
+			   DRIVER_ATOMIC,
+
+	.get_vblank_counter = drm_vblank_count,
+	.enable_vblank = mtk_drm_crtc_enable_vblank,
+	.disable_vblank = mtk_drm_crtc_disable_vblank,
+
+	.gem_free_object = mtk_drm_gem_free_object,
+	.gem_vm_ops = &drm_gem_cma_vm_ops,
+	.dumb_create = mtk_drm_gem_dumb_create,
+	.dumb_map_offset = mtk_drm_gem_dumb_map_offset,
+	.dumb_destroy = drm_gem_dumb_destroy,
+
+	.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
+	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
+	.gem_prime_export = drm_gem_prime_export,
+	.gem_prime_import = drm_gem_prime_import,
+	.gem_prime_get_sg_table = mtk_gem_prime_get_sg_table,
+	.gem_prime_import_sg_table = mtk_gem_prime_import_sg_table,
+	.gem_prime_mmap = mtk_drm_gem_mmap_buf,
+	.fops = &mtk_drm_fops,
+
+	.name = DRIVER_NAME,
+	.desc = DRIVER_DESC,
+	.date = DRIVER_DATE,
+	.major = DRIVER_MAJOR,
+	.minor = DRIVER_MINOR,
+};
+
+static int compare_of(struct device *dev, void *data)
+{
+	return dev->of_node == data;
+}
+
+static int mtk_drm_bind(struct device *dev)
+{
+	struct mtk_drm_private *private = dev_get_drvdata(dev);
+	struct drm_device *drm;
+	int ret;
+
+	drm = drm_dev_alloc(&mtk_drm_driver, dev);
+	if (!drm)
+		return -ENOMEM;
+
+	drm_dev_set_unique(drm, dev_name(dev));
+
+	drm->dev_private = private;
+	private->drm = drm;
+
+	ret = mtk_drm_kms_init(drm);
+	if (ret < 0)
+		goto err_free;
+
+	ret = drm_dev_register(drm, 0);
+	if (ret < 0)
+		goto err_deinit;
+
+	ret = drm_connector_register_all(drm);
+	if (ret < 0)
+		goto err_unregister;
+
+	return 0;
+
+err_unregister:
+	drm_dev_unregister(drm);
+err_deinit:
+	mtk_drm_kms_deinit(drm);
+err_free:
+	drm_dev_unref(drm);
+	return ret;
+}
+
+static void mtk_drm_unbind(struct device *dev)
+{
+	struct mtk_drm_private *private = dev_get_drvdata(dev);
+
+	drm_put_dev(private->drm);
+	private->drm = NULL;
+}
+
+static const struct component_master_ops mtk_drm_ops = {
+	.bind		= mtk_drm_bind,
+	.unbind		= mtk_drm_unbind,
+};
+
+static const struct of_device_id mtk_ddp_comp_dt_ids[] = {
+	{ .compatible = "mediatek,mt8173-disp-ovl",   .data = (void *)MTK_DISP_OVL },
+	{ .compatible = "mediatek,mt8173-disp-rdma",  .data = (void *)MTK_DISP_RDMA },
+	{ .compatible = "mediatek,mt8173-disp-wdma",  .data = (void *)MTK_DISP_WDMA },
+	{ .compatible = "mediatek,mt8173-disp-color", .data = (void *)MTK_DISP_COLOR },
+	{ .compatible = "mediatek,mt8173-disp-aal",   .data = (void *)MTK_DISP_AAL},
+	{ .compatible = "mediatek,mt8173-disp-gamma", .data = (void *)MTK_DISP_GAMMA, },
+	{ .compatible = "mediatek,mt8173-disp-ufoe",  .data = (void *)MTK_DISP_UFOE },
+	{ .compatible = "mediatek,mt8173-dsi",        .data = (void *)MTK_DSI },
+	{ .compatible = "mediatek,mt8173-dpi",        .data = (void *)MTK_DPI },
+	{ .compatible = "mediatek,mt8173-disp-mutex", .data = (void *)MTK_DISP_MUTEX },
+	{ .compatible = "mediatek,mt8173-disp-pwm",   .data = (void *)MTK_DISP_PWM },
+	{ .compatible = "mediatek,mt8173-disp-od",    .data = (void *)MTK_DISP_OD },
+	{ }
+};
+
+static int mtk_drm_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct mtk_drm_private *private;
+	struct resource *mem;
+	struct device_node *node;
+	struct component_match *match = NULL;
+	int ret;
+	int i;
+
+	private = devm_kzalloc(dev, sizeof(*private), GFP_KERNEL);
+	if (!private)
+		return -ENOMEM;
+
+	mutex_init(&private->commit.lock);
+	INIT_WORK(&private->commit.work, mtk_atomic_work);
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	private->config_regs = devm_ioremap_resource(dev, mem);
+	if (IS_ERR(private->config_regs)) {
+		ret = PTR_ERR(private->config_regs);
+		dev_err(dev, "Failed to ioremap mmsys-config resource: %d\n",
+			ret);
+		return ret;
+	}
+
+	/* Iterate over sibling DISP function blocks */
+	for_each_child_of_node(dev->of_node->parent, node) {
+		const struct of_device_id *of_id;
+		enum mtk_ddp_comp_type comp_type;
+		int comp_id;
+
+		of_id = of_match_node(mtk_ddp_comp_dt_ids, node);
+		if (!of_id)
+			continue;
+
+		if (!of_device_is_available(node)) {
+			dev_dbg(dev, "Skipping disabled component %s\n",
+				node->full_name);
+			continue;
+		}
+
+		comp_type = (enum mtk_ddp_comp_type)of_id->data;
+
+		if (comp_type == MTK_DISP_MUTEX) {
+			private->mutex_node = of_node_get(node);
+			continue;
+		}
+
+		comp_id = mtk_ddp_comp_get_id(node, comp_type);
+		if (comp_id < 0) {
+			dev_warn(dev, "Skipping unknown component %s\n",
+				 node->full_name);
+			continue;
+		}
+
+		private->comp_node[comp_id] = of_node_get(node);
+
+		/*
+		 * Currently only the OVL, RDMA, DSI, and DPI blocks have
+		 * separate component platform drivers and initialize their own
+		 * DDP component structure. The others are initialized here.
+		 */
+		if (comp_type == MTK_DISP_OVL ||
+		    comp_type == MTK_DISP_RDMA ||
+		    comp_type == MTK_DSI ||
+		    comp_type == MTK_DPI) {
+			dev_info(dev, "Adding component match for %s\n",
+				 node->full_name);
+			component_match_add(dev, &match, compare_of, node);
+		} else {
+			struct mtk_ddp_comp *comp;
+
+			comp = devm_kzalloc(dev, sizeof(*comp), GFP_KERNEL);
+			if (!comp) {
+				ret = -ENOMEM;
+				goto err_node;
+			}
+
+			ret = mtk_ddp_comp_init(dev, node, comp, comp_id, NULL);
+			if (ret)
+				goto err_node;
+
+			private->ddp_comp[comp_id] = comp;
+		}
+	}
+
+	if (!private->mutex_node) {
+		dev_err(dev, "Failed to find disp-mutex node\n");
+		ret = -ENODEV;
+		goto err_node;
+	}
+
+	pm_runtime_enable(dev);
+
+	platform_set_drvdata(pdev, private);
+
+	ret = component_master_add_with_match(dev, &mtk_drm_ops, match);
+	if (ret)
+		goto err_pm;
+
+	return 0;
+
+err_pm:
+	pm_runtime_disable(dev);
+err_node:
+	of_node_put(private->mutex_node);
+	for (i = 0; i < DDP_COMPONENT_ID_MAX; i++)
+		of_node_put(private->comp_node[i]);
+	return ret;
+}
+
+static int mtk_drm_remove(struct platform_device *pdev)
+{
+	struct mtk_drm_private *private = platform_get_drvdata(pdev);
+	struct drm_device *drm = private->drm;
+	int i;
+
+	drm_connector_unregister_all(drm);
+	drm_dev_unregister(drm);
+	mtk_drm_kms_deinit(drm);
+	drm_dev_unref(drm);
+
+	component_master_del(&pdev->dev, &mtk_drm_ops);
+	pm_runtime_disable(&pdev->dev);
+	of_node_put(private->mutex_node);
+	for (i = 0; i < DDP_COMPONENT_ID_MAX; i++)
+		of_node_put(private->comp_node[i]);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int mtk_drm_sys_suspend(struct device *dev)
+{
+	struct mtk_drm_private *private = dev_get_drvdata(dev);
+	struct drm_device *drm = private->drm;
+
+	drm_kms_helper_poll_disable(drm);
+
+	private->suspend_state = drm_atomic_helper_suspend(drm);
+	if (IS_ERR(private->suspend_state)) {
+		drm_kms_helper_poll_enable(drm);
+		return PTR_ERR(private->suspend_state);
+	}
+
+	DRM_DEBUG_DRIVER("mtk_drm_sys_suspend\n");
+	return 0;
+}
+
+static int mtk_drm_sys_resume(struct device *dev)
+{
+	struct mtk_drm_private *private = dev_get_drvdata(dev);
+	struct drm_device *drm = private->drm;
+
+	drm_atomic_helper_resume(drm, private->suspend_state);
+	drm_kms_helper_poll_enable(drm);
+
+	DRM_DEBUG_DRIVER("mtk_drm_sys_resume\n");
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(mtk_drm_pm_ops, mtk_drm_sys_suspend,
+			 mtk_drm_sys_resume);
+
+static const struct of_device_id mtk_drm_of_ids[] = {
+	{ .compatible = "mediatek,mt8173-mmsys", },
+	{ }
+};
+
+static struct platform_driver mtk_drm_platform_driver = {
+	.probe	= mtk_drm_probe,
+	.remove	= mtk_drm_remove,
+	.driver	= {
+		.name	= "mediatek-drm",
+		.of_match_table = mtk_drm_of_ids,
+		.pm     = &mtk_drm_pm_ops,
+	},
+};
+
+static struct platform_driver * const mtk_drm_drivers[] = {
+	&mtk_ddp_driver,
+	&mtk_disp_ovl_driver,
+	&mtk_disp_rdma_driver,
+	&mtk_dpi_driver,
+	&mtk_drm_platform_driver,
+	&mtk_dsi_driver,
+	&mtk_mipi_tx_driver,
+};
+
+static int __init mtk_drm_init(void)
+{
+	int ret;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(mtk_drm_drivers); i++) {
+		ret = platform_driver_register(mtk_drm_drivers[i]);
+		if (ret < 0) {
+			pr_err("Failed to register %s driver: %d\n",
+			       mtk_drm_drivers[i]->driver.name, ret);
+			goto err;
+		}
+	}
+
+	return 0;
+
+err:
+	while (--i >= 0)
+		platform_driver_unregister(mtk_drm_drivers[i]);
+
+	return ret;
+}
+
+static void __exit mtk_drm_exit(void)
+{
+	int i;
+
+	for (i = ARRAY_SIZE(mtk_drm_drivers) - 1; i >= 0; i--)
+		platform_driver_unregister(mtk_drm_drivers[i]);
+}
+
+module_init(mtk_drm_init);
+module_exit(mtk_drm_exit);
+
+MODULE_AUTHOR("YT SHEN <yt.shen@mediatek.com>");
+MODULE_DESCRIPTION("Mediatek SoC DRM driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_drm_drv.h linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_drm_drv.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_drm_drv.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_drm_drv.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef MTK_DRM_DRV_H
+#define MTK_DRM_DRV_H
+
+#include <linux/io.h>
+#include "mtk_drm_ddp_comp.h"
+
+#define MAX_CRTC	2
+#define MAX_CONNECTOR	2
+
+struct device;
+struct device_node;
+struct drm_crtc;
+struct drm_device;
+struct drm_fb_helper;
+struct drm_property;
+struct regmap;
+
+struct mtk_drm_private {
+	struct drm_device *drm;
+	struct device *dma_dev;
+
+	struct drm_crtc *crtc[MAX_CRTC];
+	unsigned int num_pipes;
+
+	struct device_node *mutex_node;
+	struct device *mutex_dev;
+	void __iomem *config_regs;
+	struct device_node *comp_node[DDP_COMPONENT_ID_MAX];
+	struct mtk_ddp_comp *ddp_comp[DDP_COMPONENT_ID_MAX];
+
+	struct {
+		struct drm_atomic_state *state;
+		struct work_struct work;
+		struct mutex lock;
+	} commit;
+
+	struct drm_atomic_state *suspend_state;
+};
+
+extern struct platform_driver mtk_ddp_driver;
+extern struct platform_driver mtk_disp_ovl_driver;
+extern struct platform_driver mtk_disp_rdma_driver;
+extern struct platform_driver mtk_dpi_driver;
+extern struct platform_driver mtk_dsi_driver;
+extern struct platform_driver mtk_mipi_tx_driver;
+
+#endif /* MTK_DRM_DRV_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_drm_fb.c linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_drm_fb.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_drm_fb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_drm_fb.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_gem.h>
+#include <linux/dma-buf.h>
+#include <linux/reservation.h>
+
+#include "mtk_drm_drv.h"
+#include "mtk_drm_fb.h"
+#include "mtk_drm_gem.h"
+
+/*
+ * mtk specific framebuffer structure.
+ *
+ * @fb: drm framebuffer object.
+ * @gem_obj: array of gem objects.
+ */
+struct mtk_drm_fb {
+	struct drm_framebuffer	base;
+	/* For now we only support a single plane */
+	struct drm_gem_object	*gem_obj;
+};
+
+#define to_mtk_fb(x) container_of(x, struct mtk_drm_fb, base)
+
+struct drm_gem_object *mtk_fb_get_gem_obj(struct drm_framebuffer *fb)
+{
+	struct mtk_drm_fb *mtk_fb = to_mtk_fb(fb);
+
+	return mtk_fb->gem_obj;
+}
+
+static int mtk_drm_fb_create_handle(struct drm_framebuffer *fb,
+				    struct drm_file *file_priv,
+				    unsigned int *handle)
+{
+	struct mtk_drm_fb *mtk_fb = to_mtk_fb(fb);
+
+	return drm_gem_handle_create(file_priv, mtk_fb->gem_obj, handle);
+}
+
+static void mtk_drm_fb_destroy(struct drm_framebuffer *fb)
+{
+	struct mtk_drm_fb *mtk_fb = to_mtk_fb(fb);
+
+	drm_framebuffer_cleanup(fb);
+
+	drm_gem_object_unreference_unlocked(mtk_fb->gem_obj);
+
+	kfree(mtk_fb);
+}
+
+static const struct drm_framebuffer_funcs mtk_drm_fb_funcs = {
+	.create_handle = mtk_drm_fb_create_handle,
+	.destroy = mtk_drm_fb_destroy,
+};
+
+static struct mtk_drm_fb *mtk_drm_framebuffer_init(struct drm_device *dev,
+					const struct drm_mode_fb_cmd2 *mode,
+					struct drm_gem_object *obj)
+{
+	struct mtk_drm_fb *mtk_fb;
+	int ret;
+
+	if (drm_format_num_planes(mode->pixel_format) != 1)
+		return ERR_PTR(-EINVAL);
+
+	mtk_fb = kzalloc(sizeof(*mtk_fb), GFP_KERNEL);
+	if (!mtk_fb)
+		return ERR_PTR(-ENOMEM);
+
+	drm_helper_mode_fill_fb_struct(&mtk_fb->base, mode);
+
+	mtk_fb->gem_obj = obj;
+
+	ret = drm_framebuffer_init(dev, &mtk_fb->base, &mtk_drm_fb_funcs);
+	if (ret) {
+		DRM_ERROR("failed to initialize framebuffer\n");
+		kfree(mtk_fb);
+		return ERR_PTR(ret);
+	}
+
+	return mtk_fb;
+}
+
+/*
+ * Wait for any exclusive fence in fb's gem object's reservation object.
+ *
+ * Returns -ERESTARTSYS if interrupted, else 0.
+ */
+int mtk_fb_wait(struct drm_framebuffer *fb)
+{
+	struct drm_gem_object *gem;
+	struct reservation_object *resv;
+	long ret;
+
+	if (!fb)
+		return 0;
+
+	gem = mtk_fb_get_gem_obj(fb);
+	if (!gem || !gem->dma_buf || !gem->dma_buf->resv)
+		return 0;
+
+	resv = gem->dma_buf->resv;
+	ret = reservation_object_wait_timeout_rcu(resv, false, true,
+						  MAX_SCHEDULE_TIMEOUT);
+	/* MAX_SCHEDULE_TIMEOUT on success, -ERESTARTSYS if interrupted */
+	if (WARN_ON(ret < 0))
+		return ret;
+
+	return 0;
+}
+
+struct drm_framebuffer *mtk_drm_mode_fb_create(struct drm_device *dev,
+					       struct drm_file *file,
+					       const struct drm_mode_fb_cmd2 *cmd)
+{
+	struct mtk_drm_fb *mtk_fb;
+	struct drm_gem_object *gem;
+	unsigned int width = cmd->width;
+	unsigned int height = cmd->height;
+	unsigned int size, bpp;
+	int ret;
+
+	if (drm_format_num_planes(cmd->pixel_format) != 1)
+		return ERR_PTR(-EINVAL);
+
+	gem = drm_gem_object_lookup(file, cmd->handles[0]);
+	if (!gem)
+		return ERR_PTR(-ENOENT);
+
+	bpp = drm_format_plane_cpp(cmd->pixel_format, 0);
+	size = (height - 1) * cmd->pitches[0] + width * bpp;
+	size += cmd->offsets[0];
+
+	if (gem->size < size) {
+		ret = -EINVAL;
+		goto unreference;
+	}
+
+	mtk_fb = mtk_drm_framebuffer_init(dev, cmd, gem);
+	if (IS_ERR(mtk_fb)) {
+		ret = PTR_ERR(mtk_fb);
+		goto unreference;
+	}
+
+	return &mtk_fb->base;
+
+unreference:
+	drm_gem_object_unreference_unlocked(gem);
+	return ERR_PTR(ret);
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_drm_fb.h linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_drm_fb.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_drm_fb.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_drm_fb.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef MTK_DRM_FB_H
+#define MTK_DRM_FB_H
+
+struct drm_gem_object *mtk_fb_get_gem_obj(struct drm_framebuffer *fb);
+int mtk_fb_wait(struct drm_framebuffer *fb);
+struct drm_framebuffer *mtk_drm_mode_fb_create(struct drm_device *dev,
+					       struct drm_file *file,
+					       const struct drm_mode_fb_cmd2 *cmd);
+
+#endif /* MTK_DRM_FB_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_drm_gem.c linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_drm_gem.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_drm_gem.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_drm_gem.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_gem.h>
+#include <linux/dma-buf.h>
+
+#include "mtk_drm_drv.h"
+#include "mtk_drm_gem.h"
+
+static struct mtk_drm_gem_obj *mtk_drm_gem_init(struct drm_device *dev,
+						unsigned long size)
+{
+	struct mtk_drm_gem_obj *mtk_gem_obj;
+	int ret;
+
+	size = round_up(size, PAGE_SIZE);
+
+	mtk_gem_obj = kzalloc(sizeof(*mtk_gem_obj), GFP_KERNEL);
+	if (!mtk_gem_obj)
+		return ERR_PTR(-ENOMEM);
+
+	ret = drm_gem_object_init(dev, &mtk_gem_obj->base, size);
+	if (ret < 0) {
+		DRM_ERROR("failed to initialize gem object\n");
+		kfree(mtk_gem_obj);
+		return ERR_PTR(ret);
+	}
+
+	return mtk_gem_obj;
+}
+
+struct mtk_drm_gem_obj *mtk_drm_gem_create(struct drm_device *dev,
+					   size_t size, bool alloc_kmap)
+{
+	struct mtk_drm_private *priv = dev->dev_private;
+	struct mtk_drm_gem_obj *mtk_gem;
+	struct drm_gem_object *obj;
+	int ret;
+
+	mtk_gem = mtk_drm_gem_init(dev, size);
+	if (IS_ERR(mtk_gem))
+		return ERR_CAST(mtk_gem);
+
+	obj = &mtk_gem->base;
+
+	init_dma_attrs(&mtk_gem->dma_attrs);
+	dma_set_attr(DMA_ATTR_WRITE_COMBINE, &mtk_gem->dma_attrs);
+
+	if (!alloc_kmap)
+		dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &mtk_gem->dma_attrs);
+
+	mtk_gem->cookie = dma_alloc_attrs(priv->dma_dev, obj->size,
+					  &mtk_gem->dma_addr, GFP_KERNEL,
+					  &mtk_gem->dma_attrs);
+	if (!mtk_gem->cookie) {
+		DRM_ERROR("failed to allocate %zx byte dma buffer", obj->size);
+		ret = -ENOMEM;
+		goto err_gem_free;
+	}
+
+	if (alloc_kmap)
+		mtk_gem->kvaddr = mtk_gem->cookie;
+
+	DRM_DEBUG_DRIVER("cookie = %p dma_addr = %pad size = %zu\n",
+			 mtk_gem->cookie, &mtk_gem->dma_addr,
+			 size);
+
+	return mtk_gem;
+
+err_gem_free:
+	drm_gem_object_release(obj);
+	kfree(mtk_gem);
+	return ERR_PTR(ret);
+}
+
+void mtk_drm_gem_free_object(struct drm_gem_object *obj)
+{
+	struct mtk_drm_gem_obj *mtk_gem = to_mtk_gem_obj(obj);
+	struct mtk_drm_private *priv = obj->dev->dev_private;
+
+	if (mtk_gem->sg)
+		drm_prime_gem_destroy(obj, mtk_gem->sg);
+	else
+		dma_free_attrs(priv->dma_dev, obj->size, mtk_gem->cookie,
+			       mtk_gem->dma_addr, &mtk_gem->dma_attrs);
+
+	/* release file pointer to gem object. */
+	drm_gem_object_release(obj);
+
+	kfree(mtk_gem);
+}
+
+int mtk_drm_gem_dumb_create(struct drm_file *file_priv, struct drm_device *dev,
+			    struct drm_mode_create_dumb *args)
+{
+	struct mtk_drm_gem_obj *mtk_gem;
+	int ret;
+
+	args->pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
+	args->size = args->pitch * args->height;
+
+	mtk_gem = mtk_drm_gem_create(dev, args->size, false);
+	if (IS_ERR(mtk_gem))
+		return PTR_ERR(mtk_gem);
+
+	/*
+	 * allocate a id of idr table where the obj is registered
+	 * and handle has the id what user can see.
+	 */
+	ret = drm_gem_handle_create(file_priv, &mtk_gem->base, &args->handle);
+	if (ret)
+		goto err_handle_create;
+
+	/* drop reference from allocate - handle holds it now. */
+	drm_gem_object_unreference_unlocked(&mtk_gem->base);
+
+	return 0;
+
+err_handle_create:
+	mtk_drm_gem_free_object(&mtk_gem->base);
+	return ret;
+}
+
+int mtk_drm_gem_dumb_map_offset(struct drm_file *file_priv,
+				struct drm_device *dev, uint32_t handle,
+				uint64_t *offset)
+{
+	struct drm_gem_object *obj;
+	int ret;
+
+	obj = drm_gem_object_lookup(file_priv, handle);
+	if (!obj) {
+		DRM_ERROR("failed to lookup gem object.\n");
+		return -EINVAL;
+	}
+
+	ret = drm_gem_create_mmap_offset(obj);
+	if (ret)
+		goto out;
+
+	*offset = drm_vma_node_offset_addr(&obj->vma_node);
+	DRM_DEBUG_KMS("offset = 0x%llx\n", *offset);
+
+out:
+	drm_gem_object_unreference_unlocked(obj);
+	return ret;
+}
+
+static int mtk_drm_gem_object_mmap(struct drm_gem_object *obj,
+				   struct vm_area_struct *vma)
+
+{
+	int ret;
+	struct mtk_drm_gem_obj *mtk_gem = to_mtk_gem_obj(obj);
+	struct mtk_drm_private *priv = obj->dev->dev_private;
+
+	/*
+	 * dma_alloc_attrs() allocated a struct page table for mtk_gem, so clear
+	 * VM_PFNMAP flag that was set by drm_gem_mmap_obj()/drm_gem_mmap().
+	 */
+	vma->vm_flags &= ~VM_PFNMAP;
+	vma->vm_pgoff = 0;
+
+	ret = dma_mmap_attrs(priv->dma_dev, vma, mtk_gem->cookie,
+			     mtk_gem->dma_addr, obj->size, &mtk_gem->dma_attrs);
+	if (ret)
+		drm_gem_vm_close(vma);
+
+	return ret;
+}
+
+int mtk_drm_gem_mmap_buf(struct drm_gem_object *obj, struct vm_area_struct *vma)
+{
+	int ret;
+
+	ret = drm_gem_mmap_obj(obj, obj->size, vma);
+	if (ret)
+		return ret;
+
+	return mtk_drm_gem_object_mmap(obj, vma);
+}
+
+int mtk_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+	struct drm_gem_object *obj;
+	int ret;
+
+	ret = drm_gem_mmap(filp, vma);
+	if (ret)
+		return ret;
+
+	obj = vma->vm_private_data;
+
+	return mtk_drm_gem_object_mmap(obj, vma);
+}
+
+/*
+ * Allocate a sg_table for this GEM object.
+ * Note: Both the table's contents, and the sg_table itself must be freed by
+ *       the caller.
+ * Returns a pointer to the newly allocated sg_table, or an ERR_PTR() error.
+ */
+struct sg_table *mtk_gem_prime_get_sg_table(struct drm_gem_object *obj)
+{
+	struct mtk_drm_gem_obj *mtk_gem = to_mtk_gem_obj(obj);
+	struct mtk_drm_private *priv = obj->dev->dev_private;
+	struct sg_table *sgt;
+	int ret;
+
+	sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
+	if (!sgt)
+		return ERR_PTR(-ENOMEM);
+
+	ret = dma_get_sgtable_attrs(priv->dma_dev, sgt, mtk_gem->cookie,
+				    mtk_gem->dma_addr, obj->size,
+				    &mtk_gem->dma_attrs);
+	if (ret) {
+		DRM_ERROR("failed to allocate sgt, %d\n", ret);
+		kfree(sgt);
+		return ERR_PTR(ret);
+	}
+
+	return sgt;
+}
+
+struct drm_gem_object *mtk_gem_prime_import_sg_table(struct drm_device *dev,
+			struct dma_buf_attachment *attach, struct sg_table *sg)
+{
+	struct mtk_drm_gem_obj *mtk_gem;
+	int ret;
+	struct scatterlist *s;
+	unsigned int i;
+	dma_addr_t expected;
+
+	mtk_gem = mtk_drm_gem_init(dev, attach->dmabuf->size);
+
+	if (IS_ERR(mtk_gem))
+		return ERR_PTR(PTR_ERR(mtk_gem));
+
+	expected = sg_dma_address(sg->sgl);
+	for_each_sg(sg->sgl, s, sg->nents, i) {
+		if (sg_dma_address(s) != expected) {
+			DRM_ERROR("sg_table is not contiguous");
+			ret = -EINVAL;
+			goto err_gem_free;
+		}
+		expected = sg_dma_address(s) + sg_dma_len(s);
+	}
+
+	mtk_gem->dma_addr = sg_dma_address(sg->sgl);
+	mtk_gem->sg = sg;
+
+	return &mtk_gem->base;
+
+err_gem_free:
+	kfree(mtk_gem);
+	return ERR_PTR(ret);
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_drm_gem.h linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_drm_gem.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_drm_gem.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_drm_gem.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef _MTK_DRM_GEM_H_
+#define _MTK_DRM_GEM_H_
+
+#include <drm/drm_gem.h>
+
+/*
+ * mtk drm buffer structure.
+ *
+ * @base: a gem object.
+ *	- a new handle to this gem object would be created
+ *	by drm_gem_handle_create().
+ * @cookie: the return value of dma_alloc_attrs(), keep it for dma_free_attrs()
+ * @kvaddr: kernel virtual address of gem buffer.
+ * @dma_addr: dma address of gem buffer.
+ * @dma_attrs: dma attributes of gem buffer.
+ *
+ * P.S. this object would be transferred to user as kms_bo.handle so
+ *	user can access the buffer through kms_bo.handle.
+ */
+struct mtk_drm_gem_obj {
+	struct drm_gem_object	base;
+	void			*cookie;
+	void			*kvaddr;
+	dma_addr_t		dma_addr;
+	struct dma_attrs	dma_attrs;
+	struct sg_table		*sg;
+};
+
+#define to_mtk_gem_obj(x)	container_of(x, struct mtk_drm_gem_obj, base)
+
+void mtk_drm_gem_free_object(struct drm_gem_object *gem);
+struct mtk_drm_gem_obj *mtk_drm_gem_create(struct drm_device *dev, size_t size,
+					   bool alloc_kmap);
+int mtk_drm_gem_dumb_create(struct drm_file *file_priv, struct drm_device *dev,
+			    struct drm_mode_create_dumb *args);
+int mtk_drm_gem_dumb_map_offset(struct drm_file *file_priv,
+				struct drm_device *dev, uint32_t handle,
+				uint64_t *offset);
+int mtk_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma);
+int mtk_drm_gem_mmap_buf(struct drm_gem_object *obj,
+			 struct vm_area_struct *vma);
+struct sg_table *mtk_gem_prime_get_sg_table(struct drm_gem_object *obj);
+struct drm_gem_object *mtk_gem_prime_import_sg_table(struct drm_device *dev,
+			struct dma_buf_attachment *attach, struct sg_table *sg);
+
+#endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_drm_plane.c linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_drm_plane.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_drm_plane.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_drm_plane.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ * Author: CK Hu <ck.hu@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_plane_helper.h>
+
+#include "mtk_drm_crtc.h"
+#include "mtk_drm_ddp_comp.h"
+#include "mtk_drm_drv.h"
+#include "mtk_drm_fb.h"
+#include "mtk_drm_gem.h"
+#include "mtk_drm_plane.h"
+
+static const u32 formats[] = {
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_RGB565,
+};
+
+static void mtk_plane_enable(struct mtk_drm_plane *mtk_plane, bool enable,
+			     dma_addr_t addr, struct drm_rect *dest)
+{
+	struct drm_plane *plane = &mtk_plane->base;
+	struct mtk_plane_state *state = to_mtk_plane_state(plane->state);
+	unsigned int pitch, format;
+	int x, y;
+
+	if (WARN_ON(!plane->state || (enable && !plane->state->fb)))
+		return;
+
+	if (plane->state->fb) {
+		pitch = plane->state->fb->pitches[0];
+		format = plane->state->fb->pixel_format;
+	} else {
+		pitch = 0;
+		format = DRM_FORMAT_RGBA8888;
+	}
+
+	x = plane->state->crtc_x;
+	y = plane->state->crtc_y;
+
+	if (x < 0) {
+		addr -= x * 4;
+		x = 0;
+	}
+
+	if (y < 0) {
+		addr -= y * pitch;
+		y = 0;
+	}
+
+	state->pending.enable = enable;
+	state->pending.pitch = pitch;
+	state->pending.format = format;
+	state->pending.addr = addr;
+	state->pending.x = x;
+	state->pending.y = y;
+	state->pending.width = dest->x2 - dest->x1;
+	state->pending.height = dest->y2 - dest->y1;
+	wmb(); /* Make sure the above parameters are set before update */
+	state->pending.dirty = true;
+}
+
+static void mtk_plane_reset(struct drm_plane *plane)
+{
+	struct mtk_plane_state *state;
+
+	if (plane->state) {
+		if (plane->state->fb)
+			drm_framebuffer_unreference(plane->state->fb);
+
+		state = to_mtk_plane_state(plane->state);
+		memset(state, 0, sizeof(*state));
+	} else {
+		state = kzalloc(sizeof(*state), GFP_KERNEL);
+		if (!state)
+			return;
+		plane->state = &state->base;
+	}
+
+	state->base.plane = plane;
+	state->pending.format = DRM_FORMAT_RGB565;
+}
+
+static struct drm_plane_state *mtk_plane_duplicate_state(struct drm_plane *plane)
+{
+	struct mtk_plane_state *old_state = to_mtk_plane_state(plane->state);
+	struct mtk_plane_state *state;
+
+	state = kzalloc(sizeof(*state), GFP_KERNEL);
+	if (!state)
+		return NULL;
+
+	__drm_atomic_helper_plane_duplicate_state(plane, &state->base);
+
+	WARN_ON(state->base.plane != plane);
+
+	state->pending = old_state->pending;
+
+	return &state->base;
+}
+
+static void mtk_drm_plane_destroy_state(struct drm_plane *plane,
+					struct drm_plane_state *state)
+{
+	__drm_atomic_helper_plane_destroy_state(state);
+	kfree(to_mtk_plane_state(state));
+}
+
+static const struct drm_plane_funcs mtk_plane_funcs = {
+	.update_plane = drm_atomic_helper_update_plane,
+	.disable_plane = drm_atomic_helper_disable_plane,
+	.destroy = drm_plane_cleanup,
+	.reset = mtk_plane_reset,
+	.atomic_duplicate_state = mtk_plane_duplicate_state,
+	.atomic_destroy_state = mtk_drm_plane_destroy_state,
+};
+
+static int mtk_plane_atomic_check(struct drm_plane *plane,
+				  struct drm_plane_state *state)
+{
+	struct drm_framebuffer *fb = state->fb;
+	struct drm_crtc_state *crtc_state;
+	bool visible;
+	struct drm_rect dest = {
+		.x1 = state->crtc_x,
+		.y1 = state->crtc_y,
+		.x2 = state->crtc_x + state->crtc_w,
+		.y2 = state->crtc_y + state->crtc_h,
+	};
+	struct drm_rect src = {
+		/* 16.16 fixed point */
+		.x1 = state->src_x,
+		.y1 = state->src_y,
+		.x2 = state->src_x + state->src_w,
+		.y2 = state->src_y + state->src_h,
+	};
+	struct drm_rect clip = { 0, };
+
+	if (!fb)
+		return 0;
+
+	if (!mtk_fb_get_gem_obj(fb)) {
+		DRM_DEBUG_KMS("buffer is null\n");
+		return -EFAULT;
+	}
+
+	if (!state->crtc)
+		return 0;
+
+	crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
+	if (IS_ERR(crtc_state))
+		return PTR_ERR(crtc_state);
+
+	clip.x2 = crtc_state->mode.hdisplay;
+	clip.y2 = crtc_state->mode.vdisplay;
+
+	return drm_plane_helper_check_update(plane, state->crtc, fb,
+					     &src, &dest, &clip,
+					     DRM_PLANE_HELPER_NO_SCALING,
+					     DRM_PLANE_HELPER_NO_SCALING,
+					     true, true, &visible);
+}
+
+static void mtk_plane_atomic_update(struct drm_plane *plane,
+				    struct drm_plane_state *old_state)
+{
+	struct mtk_plane_state *state = to_mtk_plane_state(plane->state);
+	struct drm_crtc *crtc = state->base.crtc;
+	struct drm_gem_object *gem;
+	struct mtk_drm_gem_obj *mtk_gem;
+	struct mtk_drm_plane *mtk_plane = to_mtk_plane(plane);
+	struct drm_rect dest = {
+		.x1 = state->base.crtc_x,
+		.y1 = state->base.crtc_y,
+		.x2 = state->base.crtc_x + state->base.crtc_w,
+		.y2 = state->base.crtc_y + state->base.crtc_h,
+	};
+	struct drm_rect clip = { 0, };
+
+	if (!crtc)
+		return;
+
+	clip.x2 = state->base.crtc->state->mode.hdisplay;
+	clip.y2 = state->base.crtc->state->mode.vdisplay;
+	drm_rect_intersect(&dest, &clip);
+
+	gem = mtk_fb_get_gem_obj(state->base.fb);
+	mtk_gem = to_mtk_gem_obj(gem);
+	mtk_plane_enable(mtk_plane, true, mtk_gem->dma_addr, &dest);
+}
+
+static void mtk_plane_atomic_disable(struct drm_plane *plane,
+				     struct drm_plane_state *old_state)
+{
+	struct mtk_plane_state *state = to_mtk_plane_state(plane->state);
+
+	state->pending.enable = false;
+	wmb(); /* Make sure the above parameter is set before update */
+	state->pending.dirty = true;
+}
+
+static const struct drm_plane_helper_funcs mtk_plane_helper_funcs = {
+	.atomic_check = mtk_plane_atomic_check,
+	.atomic_update = mtk_plane_atomic_update,
+	.atomic_disable = mtk_plane_atomic_disable,
+};
+
+int mtk_plane_init(struct drm_device *dev, struct mtk_drm_plane *mtk_plane,
+		   unsigned long possible_crtcs, enum drm_plane_type type,
+		   unsigned int zpos)
+{
+	int err;
+
+	err = drm_universal_plane_init(dev, &mtk_plane->base, possible_crtcs,
+				       &mtk_plane_funcs, formats,
+				       ARRAY_SIZE(formats), type, NULL);
+	if (err) {
+		DRM_ERROR("failed to initialize plane\n");
+		return err;
+	}
+
+	drm_plane_helper_add(&mtk_plane->base, &mtk_plane_helper_funcs);
+	mtk_plane->idx = zpos;
+
+	return 0;
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_drm_plane.h linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_drm_plane.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_drm_plane.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_drm_plane.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ * Author: CK Hu <ck.hu@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef _MTK_DRM_PLANE_H_
+#define _MTK_DRM_PLANE_H_
+
+#include <drm/drm_crtc.h>
+#include <linux/types.h>
+
+struct mtk_drm_plane {
+	struct drm_plane		base;
+	unsigned int			idx;
+};
+
+struct mtk_plane_pending_state {
+	bool				config;
+	bool				enable;
+	dma_addr_t			addr;
+	unsigned int			pitch;
+	unsigned int			format;
+	unsigned int			x;
+	unsigned int			y;
+	unsigned int			width;
+	unsigned int			height;
+	bool				dirty;
+};
+
+struct mtk_plane_state {
+	struct drm_plane_state		base;
+	struct mtk_plane_pending_state	pending;
+};
+
+static inline struct mtk_drm_plane *to_mtk_plane(struct drm_plane *plane)
+{
+	return container_of(plane, struct mtk_drm_plane, base);
+}
+
+static inline struct mtk_plane_state *
+to_mtk_plane_state(struct drm_plane_state *state)
+{
+	return container_of(state, struct mtk_plane_state, base);
+}
+
+int mtk_plane_init(struct drm_device *dev, struct mtk_drm_plane *mtk_plane,
+		   unsigned long possible_crtcs, enum drm_plane_type type,
+		   unsigned int zpos);
+
+#endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_dsi.c linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_dsi.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_dsi.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_dsi.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,911 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_panel.h>
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_graph.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <video/videomode.h>
+
+#include "mtk_drm_ddp_comp.h"
+
+#define DSI_VIDEO_FIFO_DEPTH	(1920 / 4)
+#define DSI_HOST_FIFO_DEPTH	64
+
+#define DSI_START		0x00
+
+#define DSI_CON_CTRL		0x10
+#define DSI_RESET			BIT(0)
+#define DSI_EN				BIT(1)
+
+#define DSI_MODE_CTRL		0x14
+#define MODE				(3)
+#define CMD_MODE			0
+#define SYNC_PULSE_MODE			1
+#define SYNC_EVENT_MODE			2
+#define BURST_MODE			3
+#define FRM_MODE			BIT(16)
+#define MIX_MODE			BIT(17)
+
+#define DSI_TXRX_CTRL		0x18
+#define VC_NUM				(2 << 0)
+#define LANE_NUM			(0xf << 2)
+#define DIS_EOT				BIT(6)
+#define NULL_EN				BIT(7)
+#define TE_FREERUN			BIT(8)
+#define EXT_TE_EN			BIT(9)
+#define EXT_TE_EDGE			BIT(10)
+#define MAX_RTN_SIZE			(0xf << 12)
+#define HSTX_CKLP_EN			BIT(16)
+
+#define DSI_PSCTRL		0x1c
+#define DSI_PS_WC			0x3fff
+#define DSI_PS_SEL			(3 << 16)
+#define PACKED_PS_16BIT_RGB565		(0 << 16)
+#define LOOSELY_PS_18BIT_RGB666		(1 << 16)
+#define PACKED_PS_18BIT_RGB666		(2 << 16)
+#define PACKED_PS_24BIT_RGB888		(3 << 16)
+
+#define DSI_VSA_NL		0x20
+#define DSI_VBP_NL		0x24
+#define DSI_VFP_NL		0x28
+#define DSI_VACT_NL		0x2C
+#define DSI_HSA_WC		0x50
+#define DSI_HBP_WC		0x54
+#define DSI_HFP_WC		0x58
+
+#define DSI_HSTX_CKL_WC		0x64
+
+#define DSI_PHY_LCCON		0x104
+#define LC_HS_TX_EN			BIT(0)
+#define LC_ULPM_EN			BIT(1)
+#define LC_WAKEUP_EN			BIT(2)
+
+#define DSI_PHY_LD0CON		0x108
+#define LD0_HS_TX_EN			BIT(0)
+#define LD0_ULPM_EN			BIT(1)
+#define LD0_WAKEUP_EN			BIT(2)
+
+#define DSI_PHY_TIMECON0	0x110
+#define LPX				(0xff << 0)
+#define HS_PRPR				(0xff << 8)
+#define HS_ZERO				(0xff << 16)
+#define HS_TRAIL			(0xff << 24)
+
+#define DSI_PHY_TIMECON1	0x114
+#define TA_GO				(0xff << 0)
+#define TA_SURE				(0xff << 8)
+#define TA_GET				(0xff << 16)
+#define DA_HS_EXIT			(0xff << 24)
+
+#define DSI_PHY_TIMECON2	0x118
+#define CONT_DET			(0xff << 0)
+#define CLK_ZERO			(0xff << 16)
+#define CLK_TRAIL			(0xff << 24)
+
+#define DSI_PHY_TIMECON3	0x11c
+#define CLK_HS_PRPR			(0xff << 0)
+#define CLK_HS_POST			(0xff << 8)
+#define CLK_HS_EXIT			(0xff << 16)
+
+#define NS_TO_CYCLE(n, c)    ((n) / (c) + (((n) % (c)) ? 1 : 0))
+
+struct phy;
+
+struct mtk_dsi {
+	struct mtk_ddp_comp ddp_comp;
+	struct device *dev;
+	struct mipi_dsi_host host;
+	struct drm_encoder encoder;
+	struct drm_connector conn;
+	struct drm_panel *panel;
+	struct drm_bridge *bridge;
+	struct phy *phy;
+
+	void __iomem *regs;
+
+	struct clk *engine_clk;
+	struct clk *digital_clk;
+	struct clk *hs_clk;
+
+	u32 data_rate;
+
+	unsigned long mode_flags;
+	enum mipi_dsi_pixel_format format;
+	unsigned int lanes;
+	struct videomode vm;
+	int refcount;
+	bool enabled;
+};
+
+static inline struct mtk_dsi *encoder_to_dsi(struct drm_encoder *e)
+{
+	return container_of(e, struct mtk_dsi, encoder);
+}
+
+static inline struct mtk_dsi *connector_to_dsi(struct drm_connector *c)
+{
+	return container_of(c, struct mtk_dsi, conn);
+}
+
+static inline struct mtk_dsi *host_to_dsi(struct mipi_dsi_host *h)
+{
+	return container_of(h, struct mtk_dsi, host);
+}
+
+static void mtk_dsi_mask(struct mtk_dsi *dsi, u32 offset, u32 mask, u32 data)
+{
+	u32 temp = readl(dsi->regs + offset);
+
+	writel((temp & ~mask) | (data & mask), dsi->regs + offset);
+}
+
+static void dsi_phy_timconfig(struct mtk_dsi *dsi)
+{
+	u32 timcon0, timcon1, timcon2, timcon3;
+	unsigned int ui, cycle_time;
+	unsigned int lpx;
+
+	ui = 1000 / dsi->data_rate + 0x01;
+	cycle_time = 8000 / dsi->data_rate + 0x01;
+	lpx = 5;
+
+	timcon0 = (8 << 24) | (0xa << 16) | (0x6 << 8) | lpx;
+	timcon1 = (7 << 24) | (5 * lpx << 16) | ((3 * lpx) / 2) << 8 |
+		  (4 * lpx);
+	timcon2 = ((NS_TO_CYCLE(0x64, cycle_time) + 0xa) << 24) |
+		  (NS_TO_CYCLE(0x150, cycle_time) << 16);
+	timcon3 = (2 * lpx) << 16 | NS_TO_CYCLE(80 + 52 * ui, cycle_time) << 8 |
+		   NS_TO_CYCLE(0x40, cycle_time);
+
+	writel(timcon0, dsi->regs + DSI_PHY_TIMECON0);
+	writel(timcon1, dsi->regs + DSI_PHY_TIMECON1);
+	writel(timcon2, dsi->regs + DSI_PHY_TIMECON2);
+	writel(timcon3, dsi->regs + DSI_PHY_TIMECON3);
+}
+
+static void mtk_dsi_enable(struct mtk_dsi *dsi)
+{
+	mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_EN, DSI_EN);
+}
+
+static void mtk_dsi_disable(struct mtk_dsi *dsi)
+{
+	mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_EN, 0);
+}
+
+static void mtk_dsi_reset(struct mtk_dsi *dsi)
+{
+	mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_RESET, DSI_RESET);
+	mtk_dsi_mask(dsi, DSI_CON_CTRL, DSI_RESET, 0);
+}
+
+static int mtk_dsi_poweron(struct mtk_dsi *dsi)
+{
+	struct device *dev = dsi->dev;
+	int ret;
+
+	if (++dsi->refcount != 1)
+		return 0;
+
+	/**
+	 * data_rate = (pixel_clock / 1000) * pixel_dipth * mipi_ratio;
+	 * pixel_clock unit is Khz, data_rata unit is MHz, so need divide 1000.
+	 * mipi_ratio is mipi clk coefficient for balance the pixel clk in mipi.
+	 * we set mipi_ratio is 1.05.
+	 */
+	dsi->data_rate = dsi->vm.pixelclock * 3 * 21 / (1 * 1000 * 10);
+
+	ret = clk_set_rate(dsi->hs_clk, dsi->data_rate * 1000000);
+	if (ret < 0) {
+		dev_err(dev, "Failed to set data rate: %d\n", ret);
+		goto err_refcount;
+	}
+
+	phy_power_on(dsi->phy);
+
+	ret = clk_prepare_enable(dsi->engine_clk);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enable engine clock: %d\n", ret);
+		goto err_phy_power_off;
+	}
+
+	ret = clk_prepare_enable(dsi->digital_clk);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enable digital clock: %d\n", ret);
+		goto err_disable_engine_clk;
+	}
+
+	mtk_dsi_enable(dsi);
+	mtk_dsi_reset(dsi);
+	dsi_phy_timconfig(dsi);
+
+	return 0;
+
+err_disable_engine_clk:
+	clk_disable_unprepare(dsi->engine_clk);
+err_phy_power_off:
+	phy_power_off(dsi->phy);
+err_refcount:
+	dsi->refcount--;
+	return ret;
+}
+
+static void dsi_clk_ulp_mode_enter(struct mtk_dsi *dsi)
+{
+	mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_HS_TX_EN, 0);
+	mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_ULPM_EN, 0);
+}
+
+static void dsi_clk_ulp_mode_leave(struct mtk_dsi *dsi)
+{
+	mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_ULPM_EN, 0);
+	mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_WAKEUP_EN, LC_WAKEUP_EN);
+	mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_WAKEUP_EN, 0);
+}
+
+static void dsi_lane0_ulp_mode_enter(struct mtk_dsi *dsi)
+{
+	mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_HS_TX_EN, 0);
+	mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_ULPM_EN, 0);
+}
+
+static void dsi_lane0_ulp_mode_leave(struct mtk_dsi *dsi)
+{
+	mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_ULPM_EN, 0);
+	mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_WAKEUP_EN, LD0_WAKEUP_EN);
+	mtk_dsi_mask(dsi, DSI_PHY_LD0CON, LD0_WAKEUP_EN, 0);
+}
+
+static bool dsi_clk_hs_state(struct mtk_dsi *dsi)
+{
+	u32 tmp_reg1;
+
+	tmp_reg1 = readl(dsi->regs + DSI_PHY_LCCON);
+	return ((tmp_reg1 & LC_HS_TX_EN) == 1) ? true : false;
+}
+
+static void dsi_clk_hs_mode(struct mtk_dsi *dsi, bool enter)
+{
+	if (enter && !dsi_clk_hs_state(dsi))
+		mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_HS_TX_EN, LC_HS_TX_EN);
+	else if (!enter && dsi_clk_hs_state(dsi))
+		mtk_dsi_mask(dsi, DSI_PHY_LCCON, LC_HS_TX_EN, 0);
+}
+
+static void dsi_set_mode(struct mtk_dsi *dsi)
+{
+	u32 vid_mode = CMD_MODE;
+
+	if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
+		vid_mode = SYNC_PULSE_MODE;
+
+		if ((dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) &&
+		    !(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE))
+			vid_mode = BURST_MODE;
+	}
+
+	writel(vid_mode, dsi->regs + DSI_MODE_CTRL);
+}
+
+static void dsi_ps_control_vact(struct mtk_dsi *dsi)
+{
+	struct videomode *vm = &dsi->vm;
+	u32 dsi_buf_bpp, ps_wc;
+	u32 ps_bpp_mode;
+
+	if (dsi->format == MIPI_DSI_FMT_RGB565)
+		dsi_buf_bpp = 2;
+	else
+		dsi_buf_bpp = 3;
+
+	ps_wc = vm->hactive * dsi_buf_bpp;
+	ps_bpp_mode = ps_wc;
+
+	switch (dsi->format) {
+	case MIPI_DSI_FMT_RGB888:
+		ps_bpp_mode |= PACKED_PS_24BIT_RGB888;
+		break;
+	case MIPI_DSI_FMT_RGB666:
+		ps_bpp_mode |= PACKED_PS_18BIT_RGB666;
+		break;
+	case MIPI_DSI_FMT_RGB666_PACKED:
+		ps_bpp_mode |= LOOSELY_PS_18BIT_RGB666;
+		break;
+	case MIPI_DSI_FMT_RGB565:
+		ps_bpp_mode |= PACKED_PS_16BIT_RGB565;
+		break;
+	}
+
+	writel(vm->vactive, dsi->regs + DSI_VACT_NL);
+	writel(ps_bpp_mode, dsi->regs + DSI_PSCTRL);
+	writel(ps_wc, dsi->regs + DSI_HSTX_CKL_WC);
+}
+
+static void dsi_rxtx_control(struct mtk_dsi *dsi)
+{
+	u32 tmp_reg;
+
+	switch (dsi->lanes) {
+	case 1:
+		tmp_reg = 1 << 2;
+		break;
+	case 2:
+		tmp_reg = 3 << 2;
+		break;
+	case 3:
+		tmp_reg = 7 << 2;
+		break;
+	case 4:
+		tmp_reg = 0xf << 2;
+		break;
+	default:
+		tmp_reg = 0xf << 2;
+		break;
+	}
+
+	writel(tmp_reg, dsi->regs + DSI_TXRX_CTRL);
+}
+
+static void dsi_ps_control(struct mtk_dsi *dsi)
+{
+	unsigned int dsi_tmp_buf_bpp;
+	u32 tmp_reg;
+
+	switch (dsi->format) {
+	case MIPI_DSI_FMT_RGB888:
+		tmp_reg = PACKED_PS_24BIT_RGB888;
+		dsi_tmp_buf_bpp = 3;
+		break;
+	case MIPI_DSI_FMT_RGB666:
+		tmp_reg = LOOSELY_PS_18BIT_RGB666;
+		dsi_tmp_buf_bpp = 3;
+		break;
+	case MIPI_DSI_FMT_RGB666_PACKED:
+		tmp_reg = PACKED_PS_18BIT_RGB666;
+		dsi_tmp_buf_bpp = 3;
+		break;
+	case MIPI_DSI_FMT_RGB565:
+		tmp_reg = PACKED_PS_16BIT_RGB565;
+		dsi_tmp_buf_bpp = 2;
+		break;
+	default:
+		tmp_reg = PACKED_PS_24BIT_RGB888;
+		dsi_tmp_buf_bpp = 3;
+		break;
+	}
+
+	tmp_reg += dsi->vm.hactive * dsi_tmp_buf_bpp & DSI_PS_WC;
+	writel(tmp_reg, dsi->regs + DSI_PSCTRL);
+}
+
+static void dsi_config_vdo_timing(struct mtk_dsi *dsi)
+{
+	unsigned int horizontal_sync_active_byte;
+	unsigned int horizontal_backporch_byte;
+	unsigned int horizontal_frontporch_byte;
+	unsigned int dsi_tmp_buf_bpp;
+
+	struct videomode *vm = &dsi->vm;
+
+	if (dsi->format == MIPI_DSI_FMT_RGB565)
+		dsi_tmp_buf_bpp = 2;
+	else
+		dsi_tmp_buf_bpp = 3;
+
+	writel(vm->vsync_len, dsi->regs + DSI_VSA_NL);
+	writel(vm->vback_porch, dsi->regs + DSI_VBP_NL);
+	writel(vm->vfront_porch, dsi->regs + DSI_VFP_NL);
+	writel(vm->vactive, dsi->regs + DSI_VACT_NL);
+
+	horizontal_sync_active_byte = (vm->hsync_len * dsi_tmp_buf_bpp - 10);
+
+	if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
+		horizontal_backporch_byte =
+			(vm->hback_porch * dsi_tmp_buf_bpp - 10);
+	else
+		horizontal_backporch_byte = ((vm->hback_porch + vm->hsync_len) *
+			dsi_tmp_buf_bpp - 10);
+
+	horizontal_frontporch_byte = (vm->hfront_porch * dsi_tmp_buf_bpp - 12);
+
+	writel(horizontal_sync_active_byte, dsi->regs + DSI_HSA_WC);
+	writel(horizontal_backporch_byte, dsi->regs + DSI_HBP_WC);
+	writel(horizontal_frontporch_byte, dsi->regs + DSI_HFP_WC);
+
+	dsi_ps_control(dsi);
+}
+
+static void mtk_dsi_start(struct mtk_dsi *dsi)
+{
+	writel(0, dsi->regs + DSI_START);
+	writel(1, dsi->regs + DSI_START);
+}
+
+static void mtk_dsi_poweroff(struct mtk_dsi *dsi)
+{
+	if (WARN_ON(dsi->refcount == 0))
+		return;
+
+	if (--dsi->refcount != 0)
+		return;
+
+	dsi_lane0_ulp_mode_enter(dsi);
+	dsi_clk_ulp_mode_enter(dsi);
+
+	mtk_dsi_disable(dsi);
+
+	clk_disable_unprepare(dsi->engine_clk);
+	clk_disable_unprepare(dsi->digital_clk);
+
+	phy_power_off(dsi->phy);
+}
+
+static void mtk_output_dsi_enable(struct mtk_dsi *dsi)
+{
+	int ret;
+
+	if (dsi->enabled)
+		return;
+
+	if (dsi->panel) {
+		if (drm_panel_prepare(dsi->panel)) {
+			DRM_ERROR("failed to setup the panel\n");
+			return;
+		}
+	}
+
+	ret = mtk_dsi_poweron(dsi);
+	if (ret < 0) {
+		DRM_ERROR("failed to power on dsi\n");
+		return;
+	}
+
+	dsi_rxtx_control(dsi);
+
+	dsi_clk_ulp_mode_leave(dsi);
+	dsi_lane0_ulp_mode_leave(dsi);
+	dsi_clk_hs_mode(dsi, 0);
+	dsi_set_mode(dsi);
+
+	dsi_ps_control_vact(dsi);
+	dsi_config_vdo_timing(dsi);
+
+	dsi_set_mode(dsi);
+	dsi_clk_hs_mode(dsi, 1);
+
+	mtk_dsi_start(dsi);
+
+	dsi->enabled = true;
+}
+
+static void mtk_output_dsi_disable(struct mtk_dsi *dsi)
+{
+	if (!dsi->enabled)
+		return;
+
+	if (dsi->panel) {
+		if (drm_panel_disable(dsi->panel)) {
+			DRM_ERROR("failed to disable the panel\n");
+			return;
+		}
+	}
+
+	mtk_dsi_poweroff(dsi);
+
+	dsi->enabled = false;
+}
+
+static void mtk_dsi_encoder_destroy(struct drm_encoder *encoder)
+{
+	drm_encoder_cleanup(encoder);
+}
+
+static const struct drm_encoder_funcs mtk_dsi_encoder_funcs = {
+	.destroy = mtk_dsi_encoder_destroy,
+};
+
+static bool mtk_dsi_encoder_mode_fixup(struct drm_encoder *encoder,
+				       const struct drm_display_mode *mode,
+				       struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+static void mtk_dsi_encoder_mode_set(struct drm_encoder *encoder,
+				     struct drm_display_mode *mode,
+				     struct drm_display_mode *adjusted)
+{
+	struct mtk_dsi *dsi = encoder_to_dsi(encoder);
+
+	dsi->vm.pixelclock = adjusted->clock;
+	dsi->vm.hactive = adjusted->hdisplay;
+	dsi->vm.hback_porch = adjusted->htotal - adjusted->hsync_end;
+	dsi->vm.hfront_porch = adjusted->hsync_start - adjusted->hdisplay;
+	dsi->vm.hsync_len = adjusted->hsync_end - adjusted->hsync_start;
+
+	dsi->vm.vactive = adjusted->vdisplay;
+	dsi->vm.vback_porch = adjusted->vtotal - adjusted->vsync_end;
+	dsi->vm.vfront_porch = adjusted->vsync_start - adjusted->vdisplay;
+	dsi->vm.vsync_len = adjusted->vsync_end - adjusted->vsync_start;
+}
+
+static void mtk_dsi_encoder_disable(struct drm_encoder *encoder)
+{
+	struct mtk_dsi *dsi = encoder_to_dsi(encoder);
+
+	mtk_output_dsi_disable(dsi);
+}
+
+static void mtk_dsi_encoder_enable(struct drm_encoder *encoder)
+{
+	struct mtk_dsi *dsi = encoder_to_dsi(encoder);
+
+	mtk_output_dsi_enable(dsi);
+}
+
+static enum drm_connector_status mtk_dsi_connector_detect(
+	struct drm_connector *connector, bool force)
+{
+	return connector_status_connected;
+}
+
+static int mtk_dsi_connector_get_modes(struct drm_connector *connector)
+{
+	struct mtk_dsi *dsi = connector_to_dsi(connector);
+
+	return drm_panel_get_modes(dsi->panel);
+}
+
+static struct drm_encoder *mtk_dsi_connector_best_encoder(
+		struct drm_connector *connector)
+{
+	struct mtk_dsi *dsi = connector_to_dsi(connector);
+
+	return &dsi->encoder;
+}
+
+static const struct drm_encoder_helper_funcs mtk_dsi_encoder_helper_funcs = {
+	.mode_fixup = mtk_dsi_encoder_mode_fixup,
+	.mode_set = mtk_dsi_encoder_mode_set,
+	.disable = mtk_dsi_encoder_disable,
+	.enable = mtk_dsi_encoder_enable,
+};
+
+static const struct drm_connector_funcs mtk_dsi_connector_funcs = {
+	.dpms = drm_atomic_helper_connector_dpms,
+	.detect = mtk_dsi_connector_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = drm_connector_cleanup,
+	.reset = drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static const struct drm_connector_helper_funcs
+	mtk_dsi_connector_helper_funcs = {
+	.get_modes = mtk_dsi_connector_get_modes,
+	.best_encoder = mtk_dsi_connector_best_encoder,
+};
+
+static int mtk_drm_attach_bridge(struct drm_bridge *bridge,
+				 struct drm_encoder *encoder)
+{
+	int ret;
+
+	if (!bridge)
+		return -ENOENT;
+
+	encoder->bridge = bridge;
+	bridge->encoder = encoder;
+	ret = drm_bridge_attach(encoder->dev, bridge);
+	if (ret) {
+		DRM_ERROR("Failed to attach bridge to drm\n");
+		encoder->bridge = NULL;
+		bridge->encoder = NULL;
+	}
+
+	return ret;
+}
+
+static int mtk_dsi_create_connector(struct drm_device *drm, struct mtk_dsi *dsi)
+{
+	int ret;
+
+	ret = drm_connector_init(drm, &dsi->conn, &mtk_dsi_connector_funcs,
+				 DRM_MODE_CONNECTOR_DSI);
+	if (ret) {
+		DRM_ERROR("Failed to connector init to drm\n");
+		return ret;
+	}
+
+	drm_connector_helper_add(&dsi->conn, &mtk_dsi_connector_helper_funcs);
+
+	dsi->conn.dpms = DRM_MODE_DPMS_OFF;
+	drm_mode_connector_attach_encoder(&dsi->conn, &dsi->encoder);
+
+	if (dsi->panel) {
+		ret = drm_panel_attach(dsi->panel, &dsi->conn);
+		if (ret) {
+			DRM_ERROR("Failed to attach panel to drm\n");
+			goto err_connector_cleanup;
+		}
+	}
+
+	return 0;
+
+err_connector_cleanup:
+	drm_connector_cleanup(&dsi->conn);
+	return ret;
+}
+
+static int mtk_dsi_create_conn_enc(struct drm_device *drm, struct mtk_dsi *dsi)
+{
+	int ret;
+
+	ret = drm_encoder_init(drm, &dsi->encoder, &mtk_dsi_encoder_funcs,
+			       DRM_MODE_ENCODER_DSI, NULL);
+	if (ret) {
+		DRM_ERROR("Failed to encoder init to drm\n");
+		return ret;
+	}
+	drm_encoder_helper_add(&dsi->encoder, &mtk_dsi_encoder_helper_funcs);
+
+	/*
+	 * Currently display data paths are statically assigned to a crtc each.
+	 * crtc 0 is OVL0 -> COLOR0 -> AAL -> OD -> RDMA0 -> UFOE -> DSI0
+	 */
+	dsi->encoder.possible_crtcs = 1;
+
+	/* If there's a bridge, attach to it and let it create the connector */
+	ret = mtk_drm_attach_bridge(dsi->bridge, &dsi->encoder);
+	if (ret) {
+		/* Otherwise create our own connector and attach to a panel */
+		ret = mtk_dsi_create_connector(drm, dsi);
+		if (ret)
+			goto err_encoder_cleanup;
+	}
+
+	return 0;
+
+err_encoder_cleanup:
+	drm_encoder_cleanup(&dsi->encoder);
+	return ret;
+}
+
+static void mtk_dsi_destroy_conn_enc(struct mtk_dsi *dsi)
+{
+	drm_encoder_cleanup(&dsi->encoder);
+	/* Skip connector cleanup if creation was delegated to the bridge */
+	if (dsi->conn.dev)
+		drm_connector_cleanup(&dsi->conn);
+}
+
+static void mtk_dsi_ddp_start(struct mtk_ddp_comp *comp)
+{
+	struct mtk_dsi *dsi = container_of(comp, struct mtk_dsi, ddp_comp);
+
+	mtk_dsi_poweron(dsi);
+}
+
+static void mtk_dsi_ddp_stop(struct mtk_ddp_comp *comp)
+{
+	struct mtk_dsi *dsi = container_of(comp, struct mtk_dsi, ddp_comp);
+
+	mtk_dsi_poweroff(dsi);
+}
+
+static const struct mtk_ddp_comp_funcs mtk_dsi_funcs = {
+	.start = mtk_dsi_ddp_start,
+	.stop = mtk_dsi_ddp_stop,
+};
+
+static int mtk_dsi_host_attach(struct mipi_dsi_host *host,
+			       struct mipi_dsi_device *device)
+{
+	struct mtk_dsi *dsi = host_to_dsi(host);
+
+	dsi->lanes = device->lanes;
+	dsi->format = device->format;
+	dsi->mode_flags = device->mode_flags;
+
+	if (dsi->conn.dev)
+		drm_helper_hpd_irq_event(dsi->conn.dev);
+
+	return 0;
+}
+
+static int mtk_dsi_host_detach(struct mipi_dsi_host *host,
+			       struct mipi_dsi_device *device)
+{
+	struct mtk_dsi *dsi = host_to_dsi(host);
+
+	if (dsi->conn.dev)
+		drm_helper_hpd_irq_event(dsi->conn.dev);
+
+	return 0;
+}
+
+static const struct mipi_dsi_host_ops mtk_dsi_ops = {
+	.attach = mtk_dsi_host_attach,
+	.detach = mtk_dsi_host_detach,
+};
+
+static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
+{
+	int ret;
+	struct drm_device *drm = data;
+	struct mtk_dsi *dsi = dev_get_drvdata(dev);
+
+	ret = mtk_ddp_comp_register(drm, &dsi->ddp_comp);
+	if (ret < 0) {
+		dev_err(dev, "Failed to register component %s: %d\n",
+			dev->of_node->full_name, ret);
+		return ret;
+	}
+
+	ret = mipi_dsi_host_register(&dsi->host);
+	if (ret < 0) {
+		dev_err(dev, "failed to register DSI host: %d\n", ret);
+		goto err_ddp_comp_unregister;
+	}
+
+	ret = mtk_dsi_create_conn_enc(drm, dsi);
+	if (ret) {
+		DRM_ERROR("Encoder create failed with %d\n", ret);
+		goto err_unregister;
+	}
+
+	return 0;
+
+err_unregister:
+	mipi_dsi_host_unregister(&dsi->host);
+err_ddp_comp_unregister:
+	mtk_ddp_comp_unregister(drm, &dsi->ddp_comp);
+	return ret;
+}
+
+static void mtk_dsi_unbind(struct device *dev, struct device *master,
+			   void *data)
+{
+	struct drm_device *drm = data;
+	struct mtk_dsi *dsi = dev_get_drvdata(dev);
+
+	mtk_dsi_destroy_conn_enc(dsi);
+	mipi_dsi_host_unregister(&dsi->host);
+	mtk_ddp_comp_unregister(drm, &dsi->ddp_comp);
+}
+
+static const struct component_ops mtk_dsi_component_ops = {
+	.bind = mtk_dsi_bind,
+	.unbind = mtk_dsi_unbind,
+};
+
+static int mtk_dsi_probe(struct platform_device *pdev)
+{
+	struct mtk_dsi *dsi;
+	struct device *dev = &pdev->dev;
+	struct device_node *remote_node, *endpoint;
+	struct resource *regs;
+	int comp_id;
+	int ret;
+
+	dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL);
+	if (!dsi)
+		return -ENOMEM;
+
+	dsi->host.ops = &mtk_dsi_ops;
+	dsi->host.dev = dev;
+
+	endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
+	if (endpoint) {
+		remote_node = of_graph_get_remote_port_parent(endpoint);
+		if (!remote_node) {
+			dev_err(dev, "No panel connected\n");
+			return -ENODEV;
+		}
+
+		dsi->bridge = of_drm_find_bridge(remote_node);
+		dsi->panel = of_drm_find_panel(remote_node);
+		of_node_put(remote_node);
+		if (!dsi->bridge && !dsi->panel) {
+			dev_info(dev, "Waiting for bridge or panel driver\n");
+			return -EPROBE_DEFER;
+		}
+	}
+
+	dsi->engine_clk = devm_clk_get(dev, "engine");
+	if (IS_ERR(dsi->engine_clk)) {
+		ret = PTR_ERR(dsi->engine_clk);
+		dev_err(dev, "Failed to get engine clock: %d\n", ret);
+		return ret;
+	}
+
+	dsi->digital_clk = devm_clk_get(dev, "digital");
+	if (IS_ERR(dsi->digital_clk)) {
+		ret = PTR_ERR(dsi->digital_clk);
+		dev_err(dev, "Failed to get digital clock: %d\n", ret);
+		return ret;
+	}
+
+	dsi->hs_clk = devm_clk_get(dev, "hs");
+	if (IS_ERR(dsi->hs_clk)) {
+		ret = PTR_ERR(dsi->hs_clk);
+		dev_err(dev, "Failed to get hs clock: %d\n", ret);
+		return ret;
+	}
+
+	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	dsi->regs = devm_ioremap_resource(dev, regs);
+	if (IS_ERR(dsi->regs)) {
+		ret = PTR_ERR(dsi->regs);
+		dev_err(dev, "Failed to ioremap memory: %d\n", ret);
+		return ret;
+	}
+
+	dsi->phy = devm_phy_get(dev, "dphy");
+	if (IS_ERR(dsi->phy)) {
+		ret = PTR_ERR(dsi->phy);
+		dev_err(dev, "Failed to get MIPI-DPHY: %d\n", ret);
+		return ret;
+	}
+
+	comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DSI);
+	if (comp_id < 0) {
+		dev_err(dev, "Failed to identify by alias: %d\n", comp_id);
+		return comp_id;
+	}
+
+	ret = mtk_ddp_comp_init(dev, dev->of_node, &dsi->ddp_comp, comp_id,
+				&mtk_dsi_funcs);
+	if (ret) {
+		dev_err(dev, "Failed to initialize component: %d\n", ret);
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, dsi);
+
+	return component_add(&pdev->dev, &mtk_dsi_component_ops);
+}
+
+static int mtk_dsi_remove(struct platform_device *pdev)
+{
+	struct mtk_dsi *dsi = platform_get_drvdata(pdev);
+
+	mtk_output_dsi_disable(dsi);
+	component_del(&pdev->dev, &mtk_dsi_component_ops);
+
+	return 0;
+}
+
+static const struct of_device_id mtk_dsi_of_match[] = {
+	{ .compatible = "mediatek,mt8173-dsi" },
+	{ },
+};
+
+struct platform_driver mtk_dsi_driver = {
+	.probe = mtk_dsi_probe,
+	.remove = mtk_dsi_remove,
+	.driver = {
+		.name = "mtk-dsi",
+		.of_match_table = mtk_dsi_of_match,
+	},
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_mipi_tx.c linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_mipi_tx.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/mediatek/mtk_mipi_tx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/mediatek/mtk_mipi_tx.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,463 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/phy/phy.h>
+
+#define MIPITX_DSI_CON		0x00
+#define RG_DSI_LDOCORE_EN		BIT(0)
+#define RG_DSI_CKG_LDOOUT_EN		BIT(1)
+#define RG_DSI_BCLK_SEL			(3 << 2)
+#define RG_DSI_LD_IDX_SEL		(7 << 4)
+#define RG_DSI_PHYCLK_SEL		(2 << 8)
+#define RG_DSI_DSICLK_FREQ_SEL		BIT(10)
+#define RG_DSI_LPTX_CLMP_EN		BIT(11)
+
+#define MIPITX_DSI_CLOCK_LANE	0x04
+#define MIPITX_DSI_DATA_LANE0	0x08
+#define MIPITX_DSI_DATA_LANE1	0x0c
+#define MIPITX_DSI_DATA_LANE2	0x10
+#define MIPITX_DSI_DATA_LANE3	0x14
+#define RG_DSI_LNTx_LDOOUT_EN		BIT(0)
+#define RG_DSI_LNTx_CKLANE_EN		BIT(1)
+#define RG_DSI_LNTx_LPTX_IPLUS1		BIT(2)
+#define RG_DSI_LNTx_LPTX_IPLUS2		BIT(3)
+#define RG_DSI_LNTx_LPTX_IMINUS		BIT(4)
+#define RG_DSI_LNTx_LPCD_IPLUS		BIT(5)
+#define RG_DSI_LNTx_LPCD_IMINUS		BIT(6)
+#define RG_DSI_LNTx_RT_CODE		(0xf << 8)
+
+#define MIPITX_DSI_TOP_CON	0x40
+#define RG_DSI_LNT_INTR_EN		BIT(0)
+#define RG_DSI_LNT_HS_BIAS_EN		BIT(1)
+#define RG_DSI_LNT_IMP_CAL_EN		BIT(2)
+#define RG_DSI_LNT_TESTMODE_EN		BIT(3)
+#define RG_DSI_LNT_IMP_CAL_CODE		(0xf << 4)
+#define RG_DSI_LNT_AIO_SEL		(7 << 8)
+#define RG_DSI_PAD_TIE_LOW_EN		BIT(11)
+#define RG_DSI_DEBUG_INPUT_EN		BIT(12)
+#define RG_DSI_PRESERVE			(7 << 13)
+
+#define MIPITX_DSI_BG_CON	0x44
+#define RG_DSI_BG_CORE_EN		BIT(0)
+#define RG_DSI_BG_CKEN			BIT(1)
+#define RG_DSI_BG_DIV			(0x3 << 2)
+#define RG_DSI_BG_FAST_CHARGE		BIT(4)
+#define RG_DSI_VOUT_MSK			(0x3ffff << 5)
+#define RG_DSI_V12_SEL			(7 << 5)
+#define RG_DSI_V10_SEL			(7 << 8)
+#define RG_DSI_V072_SEL			(7 << 11)
+#define RG_DSI_V04_SEL			(7 << 14)
+#define RG_DSI_V032_SEL			(7 << 17)
+#define RG_DSI_V02_SEL			(7 << 20)
+#define RG_DSI_BG_R1_TRIM		(0xf << 24)
+#define RG_DSI_BG_R2_TRIM		(0xf << 28)
+
+#define MIPITX_DSI_PLL_CON0	0x50
+#define RG_DSI_MPPLL_PLL_EN		BIT(0)
+#define RG_DSI_MPPLL_DIV_MSK		(0x1ff << 1)
+#define RG_DSI_MPPLL_PREDIV		(3 << 1)
+#define RG_DSI_MPPLL_TXDIV0		(3 << 3)
+#define RG_DSI_MPPLL_TXDIV1		(3 << 5)
+#define RG_DSI_MPPLL_POSDIV		(7 << 7)
+#define RG_DSI_MPPLL_MONVC_EN		BIT(10)
+#define RG_DSI_MPPLL_MONREF_EN		BIT(11)
+#define RG_DSI_MPPLL_VOD_EN		BIT(12)
+
+#define MIPITX_DSI_PLL_CON1	0x54
+#define RG_DSI_MPPLL_SDM_FRA_EN		BIT(0)
+#define RG_DSI_MPPLL_SDM_SSC_PH_INIT	BIT(1)
+#define RG_DSI_MPPLL_SDM_SSC_EN		BIT(2)
+#define RG_DSI_MPPLL_SDM_SSC_PRD	(0xffff << 16)
+
+#define MIPITX_DSI_PLL_CON2	0x58
+
+#define MIPITX_DSI_PLL_PWR	0x68
+#define RG_DSI_MPPLL_SDM_PWR_ON		BIT(0)
+#define RG_DSI_MPPLL_SDM_ISO_EN		BIT(1)
+#define RG_DSI_MPPLL_SDM_PWR_ACK	BIT(8)
+
+#define MIPITX_DSI_SW_CTRL	0x80
+#define SW_CTRL_EN			BIT(0)
+
+#define MIPITX_DSI_SW_CTRL_CON0	0x84
+#define SW_LNTC_LPTX_PRE_OE		BIT(0)
+#define SW_LNTC_LPTX_OE			BIT(1)
+#define SW_LNTC_LPTX_P			BIT(2)
+#define SW_LNTC_LPTX_N			BIT(3)
+#define SW_LNTC_HSTX_PRE_OE		BIT(4)
+#define SW_LNTC_HSTX_OE			BIT(5)
+#define SW_LNTC_HSTX_ZEROCLK		BIT(6)
+#define SW_LNT0_LPTX_PRE_OE		BIT(7)
+#define SW_LNT0_LPTX_OE			BIT(8)
+#define SW_LNT0_LPTX_P			BIT(9)
+#define SW_LNT0_LPTX_N			BIT(10)
+#define SW_LNT0_HSTX_PRE_OE		BIT(11)
+#define SW_LNT0_HSTX_OE			BIT(12)
+#define SW_LNT0_LPRX_EN			BIT(13)
+#define SW_LNT1_LPTX_PRE_OE		BIT(14)
+#define SW_LNT1_LPTX_OE			BIT(15)
+#define SW_LNT1_LPTX_P			BIT(16)
+#define SW_LNT1_LPTX_N			BIT(17)
+#define SW_LNT1_HSTX_PRE_OE		BIT(18)
+#define SW_LNT1_HSTX_OE			BIT(19)
+#define SW_LNT2_LPTX_PRE_OE		BIT(20)
+#define SW_LNT2_LPTX_OE			BIT(21)
+#define SW_LNT2_LPTX_P			BIT(22)
+#define SW_LNT2_LPTX_N			BIT(23)
+#define SW_LNT2_HSTX_PRE_OE		BIT(24)
+#define SW_LNT2_HSTX_OE			BIT(25)
+
+struct mtk_mipi_tx {
+	struct device *dev;
+	void __iomem *regs;
+	unsigned int data_rate;
+	struct clk_hw pll_hw;
+	struct clk *pll;
+};
+
+static inline struct mtk_mipi_tx *mtk_mipi_tx_from_clk_hw(struct clk_hw *hw)
+{
+	return container_of(hw, struct mtk_mipi_tx, pll_hw);
+}
+
+static void mtk_mipi_tx_clear_bits(struct mtk_mipi_tx *mipi_tx, u32 offset,
+				   u32 bits)
+{
+	u32 temp = readl(mipi_tx->regs + offset);
+
+	writel(temp & ~bits, mipi_tx->regs + offset);
+}
+
+static void mtk_mipi_tx_set_bits(struct mtk_mipi_tx *mipi_tx, u32 offset,
+				 u32 bits)
+{
+	u32 temp = readl(mipi_tx->regs + offset);
+
+	writel(temp | bits, mipi_tx->regs + offset);
+}
+
+static void mtk_mipi_tx_update_bits(struct mtk_mipi_tx *mipi_tx, u32 offset,
+				    u32 mask, u32 data)
+{
+	u32 temp = readl(mipi_tx->regs + offset);
+
+	writel((temp & ~mask) | (data & mask), mipi_tx->regs + offset);
+}
+
+static int mtk_mipi_tx_pll_prepare(struct clk_hw *hw)
+{
+	struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw);
+	unsigned int txdiv, txdiv0, txdiv1;
+	u64 pcw;
+
+	dev_dbg(mipi_tx->dev, "prepare: %u Hz\n", mipi_tx->data_rate);
+
+	if (mipi_tx->data_rate >= 500000000) {
+		txdiv = 1;
+		txdiv0 = 0;
+		txdiv1 = 0;
+	} else if (mipi_tx->data_rate >= 250000000) {
+		txdiv = 2;
+		txdiv0 = 1;
+		txdiv1 = 0;
+	} else if (mipi_tx->data_rate >= 125000000) {
+		txdiv = 4;
+		txdiv0 = 2;
+		txdiv1 = 0;
+	} else if (mipi_tx->data_rate > 62000000) {
+		txdiv = 8;
+		txdiv0 = 2;
+		txdiv1 = 1;
+	} else if (mipi_tx->data_rate >= 50000000) {
+		txdiv = 16;
+		txdiv0 = 2;
+		txdiv1 = 2;
+	} else {
+		return -EINVAL;
+	}
+
+	mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_BG_CON,
+				RG_DSI_VOUT_MSK |
+				RG_DSI_BG_CKEN | RG_DSI_BG_CORE_EN,
+				(4 << 20) | (4 << 17) | (4 << 14) |
+				(4 << 11) | (4 << 8) | (4 << 5) |
+				RG_DSI_BG_CKEN | RG_DSI_BG_CORE_EN);
+
+	usleep_range(30, 100);
+
+	mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_TOP_CON,
+				RG_DSI_LNT_IMP_CAL_CODE | RG_DSI_LNT_HS_BIAS_EN,
+				(8 << 4) | RG_DSI_LNT_HS_BIAS_EN);
+
+	mtk_mipi_tx_set_bits(mipi_tx, MIPITX_DSI_CON,
+			     RG_DSI_CKG_LDOOUT_EN | RG_DSI_LDOCORE_EN);
+
+	mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_PWR,
+				RG_DSI_MPPLL_SDM_PWR_ON |
+				RG_DSI_MPPLL_SDM_ISO_EN,
+				RG_DSI_MPPLL_SDM_PWR_ON);
+
+	mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_PLL_CON0,
+			       RG_DSI_MPPLL_PLL_EN);
+
+	mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_CON0,
+				RG_DSI_MPPLL_TXDIV0 | RG_DSI_MPPLL_TXDIV1 |
+				RG_DSI_MPPLL_PREDIV,
+				(txdiv0 << 3) | (txdiv1 << 5));
+
+	/*
+	 * PLL PCW config
+	 * PCW bit 24~30 = integer part of pcw
+	 * PCW bit 0~23 = fractional part of pcw
+	 * pcw = data_Rate*4*txdiv/(Ref_clk*2);
+	 * Post DIV =4, so need data_Rate*4
+	 * Ref_clk is 26MHz
+	 */
+	pcw = div_u64(((u64)mipi_tx->data_rate * 2 * txdiv) << 24,
+		      26000000);
+	writel(pcw, mipi_tx->regs + MIPITX_DSI_PLL_CON2);
+
+	mtk_mipi_tx_set_bits(mipi_tx, MIPITX_DSI_PLL_CON1,
+			     RG_DSI_MPPLL_SDM_FRA_EN);
+
+	mtk_mipi_tx_set_bits(mipi_tx, MIPITX_DSI_PLL_CON0, RG_DSI_MPPLL_PLL_EN);
+
+	usleep_range(20, 100);
+
+	mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_PLL_CON1,
+			       RG_DSI_MPPLL_SDM_SSC_EN);
+
+	return 0;
+}
+
+static void mtk_mipi_tx_pll_unprepare(struct clk_hw *hw)
+{
+	struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw);
+
+	dev_dbg(mipi_tx->dev, "unprepare\n");
+
+	mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_PLL_CON0,
+			       RG_DSI_MPPLL_PLL_EN);
+
+	mtk_mipi_tx_update_bits(mipi_tx, MIPITX_DSI_PLL_PWR,
+				RG_DSI_MPPLL_SDM_ISO_EN |
+				RG_DSI_MPPLL_SDM_PWR_ON,
+				RG_DSI_MPPLL_SDM_ISO_EN);
+
+	mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_TOP_CON,
+			       RG_DSI_LNT_HS_BIAS_EN);
+
+	mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_CON,
+			       RG_DSI_CKG_LDOOUT_EN | RG_DSI_LDOCORE_EN);
+
+	mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_BG_CON,
+			       RG_DSI_BG_CKEN | RG_DSI_BG_CORE_EN);
+
+	mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_PLL_CON0,
+			       RG_DSI_MPPLL_DIV_MSK);
+}
+
+static long mtk_mipi_tx_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+				       unsigned long *prate)
+{
+	return clamp_val(rate, 50000000, 1250000000);
+}
+
+static int mtk_mipi_tx_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+				    unsigned long parent_rate)
+{
+	struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw);
+
+	dev_dbg(mipi_tx->dev, "set rate: %lu Hz\n", rate);
+
+	mipi_tx->data_rate = rate;
+
+	return 0;
+}
+
+static unsigned long mtk_mipi_tx_pll_recalc_rate(struct clk_hw *hw,
+						 unsigned long parent_rate)
+{
+	struct mtk_mipi_tx *mipi_tx = mtk_mipi_tx_from_clk_hw(hw);
+
+	return mipi_tx->data_rate;
+}
+
+static const struct clk_ops mtk_mipi_tx_pll_ops = {
+	.prepare = mtk_mipi_tx_pll_prepare,
+	.unprepare = mtk_mipi_tx_pll_unprepare,
+	.round_rate = mtk_mipi_tx_pll_round_rate,
+	.set_rate = mtk_mipi_tx_pll_set_rate,
+	.recalc_rate = mtk_mipi_tx_pll_recalc_rate,
+};
+
+static int mtk_mipi_tx_power_on_signal(struct phy *phy)
+{
+	struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy);
+	unsigned int reg;
+
+	for (reg = MIPITX_DSI_CLOCK_LANE;
+	     reg <= MIPITX_DSI_DATA_LANE3; reg += 4)
+		mtk_mipi_tx_set_bits(mipi_tx, reg, RG_DSI_LNTx_LDOOUT_EN);
+
+	mtk_mipi_tx_clear_bits(mipi_tx, MIPITX_DSI_TOP_CON,
+			       RG_DSI_PAD_TIE_LOW_EN);
+
+	return 0;
+}
+
+static int mtk_mipi_tx_power_on(struct phy *phy)
+{
+	struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy);
+	int ret;
+
+	/* Power up core and enable PLL */
+	ret = clk_prepare_enable(mipi_tx->pll);
+	if (ret < 0)
+		return ret;
+
+	/* Enable DSI Lane LDO outputs, disable pad tie low */
+	mtk_mipi_tx_power_on_signal(phy);
+
+	return 0;
+}
+
+static void mtk_mipi_tx_power_off_signal(struct phy *phy)
+{
+	struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy);
+	unsigned int reg;
+
+	mtk_mipi_tx_set_bits(mipi_tx, MIPITX_DSI_TOP_CON,
+			     RG_DSI_PAD_TIE_LOW_EN);
+
+	for (reg = MIPITX_DSI_CLOCK_LANE;
+	     reg <= MIPITX_DSI_DATA_LANE3; reg += 4)
+		mtk_mipi_tx_clear_bits(mipi_tx, reg, RG_DSI_LNTx_LDOOUT_EN);
+}
+
+static int mtk_mipi_tx_power_off(struct phy *phy)
+{
+	struct mtk_mipi_tx *mipi_tx = phy_get_drvdata(phy);
+
+	/* Enable pad tie low, disable DSI Lane LDO outputs */
+	mtk_mipi_tx_power_off_signal(phy);
+
+	/* Disable PLL and power down core */
+	clk_disable_unprepare(mipi_tx->pll);
+
+	return 0;
+}
+
+static const struct phy_ops mtk_mipi_tx_ops = {
+	.power_on = mtk_mipi_tx_power_on,
+	.power_off = mtk_mipi_tx_power_off,
+	.owner = THIS_MODULE,
+};
+
+static int mtk_mipi_tx_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct mtk_mipi_tx *mipi_tx;
+	struct resource *mem;
+	struct clk *ref_clk;
+	const char *ref_clk_name;
+	struct clk_init_data clk_init = {
+		.ops = &mtk_mipi_tx_pll_ops,
+		.num_parents = 1,
+		.parent_names = (const char * const *)&ref_clk_name,
+		.flags = CLK_SET_RATE_GATE,
+	};
+	struct phy *phy;
+	struct phy_provider *phy_provider;
+	int ret;
+
+	mipi_tx = devm_kzalloc(dev, sizeof(*mipi_tx), GFP_KERNEL);
+	if (!mipi_tx)
+		return -ENOMEM;
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mipi_tx->regs = devm_ioremap_resource(dev, mem);
+	if (IS_ERR(mipi_tx->regs)) {
+		ret = PTR_ERR(mipi_tx->regs);
+		dev_err(dev, "Failed to get memory resource: %d\n", ret);
+		return ret;
+	}
+
+	ref_clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(ref_clk)) {
+		ret = PTR_ERR(ref_clk);
+		dev_err(dev, "Failed to get reference clock: %d\n", ret);
+		return ret;
+	}
+	ref_clk_name = __clk_get_name(ref_clk);
+
+	ret = of_property_read_string(dev->of_node, "clock-output-names",
+				      &clk_init.name);
+	if (ret < 0) {
+		dev_err(dev, "Failed to read clock-output-names: %d\n", ret);
+		return ret;
+	}
+
+	mipi_tx->pll_hw.init = &clk_init;
+	mipi_tx->pll = devm_clk_register(dev, &mipi_tx->pll_hw);
+	if (IS_ERR(mipi_tx->pll)) {
+		ret = PTR_ERR(mipi_tx->pll);
+		dev_err(dev, "Failed to register PLL: %d\n", ret);
+		return ret;
+	}
+
+	phy = devm_phy_create(dev, NULL, &mtk_mipi_tx_ops);
+	if (IS_ERR(phy)) {
+		ret = PTR_ERR(phy);
+		dev_err(dev, "Failed to create MIPI D-PHY: %d\n", ret);
+		return ret;
+	}
+	phy_set_drvdata(phy, mipi_tx);
+
+	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+	if (IS_ERR(phy)) {
+		ret = PTR_ERR(phy_provider);
+		return ret;
+	}
+
+	mipi_tx->dev = dev;
+
+	return of_clk_add_provider(dev->of_node, of_clk_src_simple_get,
+				   mipi_tx->pll);
+}
+
+static int mtk_mipi_tx_remove(struct platform_device *pdev)
+{
+	of_clk_del_provider(pdev->dev.of_node);
+	return 0;
+}
+
+static const struct of_device_id mtk_mipi_tx_match[] = {
+	{ .compatible = "mediatek,mt8173-mipi-tx", },
+	{},
+};
+
+struct platform_driver mtk_mipi_tx_driver = {
+	.probe = mtk_mipi_tx_probe,
+	.remove = mtk_mipi_tx_remove,
+	.driver = {
+		.name = "mediatek-mipi-tx",
+		.of_match_table = mtk_mipi_tx_match,
+	},
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/mgag200/mgag200_cursor.c linux-libre-4.7-gnu/drivers/gpu/drm/mgag200/mgag200_cursor.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/mgag200/mgag200_cursor.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/mgag200/mgag200_cursor.c	2016-07-24 15:23:50.000000000 -0400
@@ -75,7 +75,7 @@ int mga_crtc_cursor_set(struct drm_crtc
 		return 0;
 	}
 
-	obj = drm_gem_object_lookup(dev, file_priv, handle);
+	obj = drm_gem_object_lookup(file_priv, handle);
 	if (!obj)
 		return -ENOENT;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/mgag200/mgag200_drv.c linux-libre-4.7-gnu/drivers/gpu/drm/mgag200/mgag200_drv.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/mgag200/mgag200_drv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/mgag200/mgag200_drv.c	2016-07-24 15:23:50.000000000 -0400
@@ -116,10 +116,8 @@ static struct pci_driver mgag200_pci_dri
 
 static int __init mgag200_init(void)
 {
-#ifdef CONFIG_VGA_CONSOLE
 	if (vgacon_text_force() && mgag200_modeset == -1)
 		return -EINVAL;
-#endif
 
 	if (mgag200_modeset == 0)
 		return -EINVAL;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/mgag200/mgag200_drv.h linux-libre-4.7-gnu/drivers/gpu/drm/mgag200/mgag200_drv.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/mgag200/mgag200_drv.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/mgag200/mgag200_drv.h	2016-07-24 15:23:50.000000000 -0400
@@ -281,7 +281,7 @@ static inline int mgag200_bo_reserve(str
 {
 	int ret;
 
-	ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, NULL);
+	ret = ttm_bo_reserve(&bo->bo, true, no_wait, NULL);
 	if (ret) {
 		if (ret != -ERESTARTSYS && ret != -EBUSY)
 			DRM_ERROR("reserve failed %p\n", bo);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/mgag200/mgag200_main.c linux-libre-4.7-gnu/drivers/gpu/drm/mgag200/mgag200_main.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/mgag200/mgag200_main.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/mgag200/mgag200_main.c	2016-07-24 15:23:50.000000000 -0400
@@ -53,7 +53,7 @@ mgag200_user_framebuffer_create(struct d
 	struct mga_framebuffer *mga_fb;
 	int ret;
 
-	obj = drm_gem_object_lookup(dev, filp, mode_cmd->handles[0]);
+	obj = drm_gem_object_lookup(filp, mode_cmd->handles[0]);
 	if (obj == NULL)
 		return ERR_PTR(-ENOENT);
 
@@ -358,7 +358,7 @@ mgag200_dumb_mmap_offset(struct drm_file
 	struct drm_gem_object *obj;
 	struct mgag200_bo *bo;
 
-	obj = drm_gem_object_lookup(dev, file, handle);
+	obj = drm_gem_object_lookup(file, handle);
 	if (obj == NULL)
 		return -ENOENT;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/mgag200/mgag200_mode.c linux-libre-4.7-gnu/drivers/gpu/drm/mgag200/mgag200_mode.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/mgag200/mgag200_mode.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/mgag200/mgag200_mode.c	2016-07-24 15:23:50.000000000 -0400
@@ -182,7 +182,7 @@ static int mga_g200se_set_plls(struct mg
 			}
 		}
 
-		fvv = pllreffreq * testn / testm;
+		fvv = pllreffreq * (n + 1) / (m + 1);
 		fvv = (fvv - 800000) / 50000;
 
 		if (fvv > 15)
@@ -202,6 +202,14 @@ static int mga_g200se_set_plls(struct mg
 	WREG_DAC(MGA1064_PIX_PLLC_M, m);
 	WREG_DAC(MGA1064_PIX_PLLC_N, n);
 	WREG_DAC(MGA1064_PIX_PLLC_P, p);
+
+	if (mdev->unique_rev_id >= 0x04) {
+		WREG_DAC(0x1a, 0x09);
+		msleep(20);
+		WREG_DAC(0x1a, 0x01);
+
+	}
+
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/mgag200/mgag200_ttm.c linux-libre-4.7-gnu/drivers/gpu/drm/mgag200/mgag200_ttm.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/mgag200/mgag200_ttm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/mgag200/mgag200_ttm.c	2016-07-24 15:23:50.000000000 -0400
@@ -245,6 +245,8 @@ struct ttm_bo_driver mgag200_bo_driver =
 	.verify_access = mgag200_bo_verify_access,
 	.io_mem_reserve = &mgag200_ttm_io_mem_reserve,
 	.io_mem_free = &mgag200_ttm_io_mem_free,
+	.lru_tail = &ttm_bo_default_lru_tail,
+	.swap_lru_tail = &ttm_bo_default_swap_lru_tail,
 };
 
 int mgag200_mm_init(struct mga_device *mdev)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/adreno/adreno_gpu.c linux-libre-4.7-gnu/drivers/gpu/drm/msm/adreno/adreno_gpu.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/adreno/adreno_gpu.c	2016-05-15 19:21:52.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/adreno/adreno_gpu.c	2016-07-24 18:18:30.000000000 -0400
@@ -120,8 +120,8 @@ void adreno_recover(struct msm_gpu *gpu)
 	/* reset ringbuffer: */
 	gpu->rb->cur = gpu->rb->start;
 
-	/* reset completed fence seqno, just discard anything pending: */
-	adreno_gpu->memptrs->fence = gpu->submitted_fence;
+	/* reset completed fence seqno: */
+	adreno_gpu->memptrs->fence = gpu->fctx->completed_fence;
 	adreno_gpu->memptrs->rptr  = 0;
 	adreno_gpu->memptrs->wptr  = 0;
 
@@ -133,7 +133,7 @@ void adreno_recover(struct msm_gpu *gpu)
 	}
 }
 
-int adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
+void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
 		struct msm_file_private *ctx)
 {
 	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
@@ -168,7 +168,7 @@ int adreno_submit(struct msm_gpu *gpu, s
 		OUT_PKT2(ring);
 
 	OUT_PKT0(ring, REG_AXXX_CP_SCRATCH_REG2, 1);
-	OUT_RING(ring, submit->fence);
+	OUT_RING(ring, submit->fence->seqno);
 
 	if (adreno_is_a3xx(adreno_gpu) || adreno_is_a4xx(adreno_gpu)) {
 		/* Flush HLSQ lazy updates to make sure there is nothing
@@ -185,7 +185,7 @@ int adreno_submit(struct msm_gpu *gpu, s
 	OUT_PKT3(ring, CP_EVENT_WRITE, 3);
 	OUT_RING(ring, CACHE_FLUSH_TS);
 	OUT_RING(ring, rbmemptr(adreno_gpu, fence));
-	OUT_RING(ring, submit->fence);
+	OUT_RING(ring, submit->fence->seqno);
 
 	/* we could maybe be clever and only CP_COND_EXEC the interrupt: */
 	OUT_PKT3(ring, CP_INTERRUPT, 1);
@@ -212,8 +212,6 @@ int adreno_submit(struct msm_gpu *gpu, s
 #endif
 
 	gpu->funcs->flush(gpu);
-
-	return 0;
 }
 
 void adreno_flush(struct msm_gpu *gpu)
@@ -254,7 +252,7 @@ void adreno_show(struct msm_gpu *gpu, st
 			adreno_gpu->rev.patchid);
 
 	seq_printf(m, "fence:    %d/%d\n", adreno_gpu->memptrs->fence,
-			gpu->submitted_fence);
+			gpu->fctx->last_fence);
 	seq_printf(m, "rptr:     %d\n", get_rptr(adreno_gpu));
 	seq_printf(m, "wptr:     %d\n", adreno_gpu->memptrs->wptr);
 	seq_printf(m, "rb wptr:  %d\n", get_wptr(gpu->rb));
@@ -295,7 +293,7 @@ void adreno_dump_info(struct msm_gpu *gp
 			adreno_gpu->rev.patchid);
 
 	printk("fence:    %d/%d\n", adreno_gpu->memptrs->fence,
-			gpu->submitted_fence);
+			gpu->fctx->last_fence);
 	printk("rptr:     %d\n", get_rptr(adreno_gpu));
 	printk("wptr:     %d\n", adreno_gpu->memptrs->wptr);
 	printk("rb wptr:  %d\n", get_wptr(gpu->rb));
@@ -410,7 +408,7 @@ int adreno_gpu_init(struct drm_device *d
 	}
 
 	adreno_gpu->memptrs = msm_gem_vaddr(adreno_gpu->memptrs_bo);
-	if (!adreno_gpu->memptrs) {
+	if (IS_ERR(adreno_gpu->memptrs)) {
 		dev_err(drm->dev, "could not vmap memptrs\n");
 		return -ENOMEM;
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/adreno/adreno_gpu.h linux-libre-4.7-gnu/drivers/gpu/drm/msm/adreno/adreno_gpu.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/adreno/adreno_gpu.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/adreno/adreno_gpu.h	2016-07-24 15:23:50.000000000 -0400
@@ -238,7 +238,7 @@ int adreno_get_param(struct msm_gpu *gpu
 int adreno_hw_init(struct msm_gpu *gpu);
 uint32_t adreno_last_fence(struct msm_gpu *gpu);
 void adreno_recover(struct msm_gpu *gpu);
-int adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
+void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
 		struct msm_file_private *ctx);
 void adreno_flush(struct msm_gpu *gpu);
 void adreno_idle(struct msm_gpu *gpu);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/dsi/dsi_cfg.c linux-libre-4.7-gnu/drivers/gpu/drm/msm/dsi/dsi_cfg.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/dsi/dsi_cfg.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/dsi/dsi_cfg.c	2016-07-24 15:23:50.000000000 -0400
@@ -22,9 +22,9 @@ static const struct msm_dsi_config apq80
 	.reg_cfg = {
 		.num = 3,
 		.regs = {
-			{"vdda", 1200000, 1200000, 100000, 100},
-			{"avdd", 3000000, 3000000, 110000, 100},
-			{"vddio", 1800000, 1800000, 100000, 100},
+			{"vdda", 100000, 100},	/* 1.2 V */
+			{"avdd", 10000, 100},	/* 3.0 V */
+			{"vddio", 100000, 100},	/* 1.8 V */
 		},
 	},
 	.bus_clk_names = dsi_v2_bus_clk_names,
@@ -40,10 +40,10 @@ static const struct msm_dsi_config msm89
 	.reg_cfg = {
 		.num = 4,
 		.regs = {
-			{"gdsc", -1, -1, -1, -1},
-			{"vdd", 3000000, 3000000, 150000, 100},
-			{"vdda", 1200000, 1200000, 100000, 100},
-			{"vddio", 1800000, 1800000, 100000, 100},
+			{"gdsc", -1, -1},
+			{"vdd", 150000, 100},	/* 3.0 V */
+			{"vdda", 100000, 100},	/* 1.2 V */
+			{"vddio", 100000, 100},	/* 1.8 V */
 		},
 	},
 	.bus_clk_names = dsi_6g_bus_clk_names,
@@ -59,9 +59,9 @@ static const struct msm_dsi_config msm89
 	.reg_cfg = {
 		.num = 3,
 		.regs = {
-			{"gdsc", -1, -1, -1, -1},
-			{"vdda", 1200000, 1200000, 100000, 100},
-			{"vddio", 1800000, 1800000, 100000, 100},
+			{"gdsc", -1, -1},
+			{"vdda", 100000, 100},	/* 1.2 V */
+			{"vddio", 100000, 100},	/* 1.8 V */
 		},
 	},
 	.bus_clk_names = dsi_8916_bus_clk_names,
@@ -73,13 +73,13 @@ static const struct msm_dsi_config msm89
 	.reg_cfg = {
 		.num = 7,
 		.regs = {
-			{"gdsc", -1, -1, -1, -1},
-			{"vdda", 1250000, 1250000, 100000, 100},
-			{"vddio", 1800000, 1800000, 100000, 100},
-			{"vcca", 1000000, 1000000, 10000, 100},
-			{"vdd", 1800000, 1800000, 100000, 100},
-			{"lab_reg", -1, -1, -1, -1},
-			{"ibb_reg", -1, -1, -1, -1},
+			{"gdsc", -1, -1},
+			{"vdda", 100000, 100},	/* 1.25 V */
+			{"vddio", 100000, 100},	/* 1.8 V */
+			{"vcca", 10000, 100},	/* 1.0 V */
+			{"vdd", 100000, 100},	/* 1.8 V */
+			{"lab_reg", -1, -1},
+			{"ibb_reg", -1, -1},
 		},
 	},
 	.bus_clk_names = dsi_6g_bus_clk_names,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/dsi/dsi.h linux-libre-4.7-gnu/drivers/gpu/drm/msm/dsi/dsi.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/dsi/dsi.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/dsi/dsi.h	2016-07-24 15:23:50.000000000 -0400
@@ -41,8 +41,6 @@ enum msm_dsi_phy_type {
 /* Regulators for DSI devices */
 struct dsi_reg_entry {
 	char name[32];
-	int min_voltage;
-	int max_voltage;
 	int enable_load;
 	int disable_load;
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/dsi/dsi_host.c linux-libre-4.7-gnu/drivers/gpu/drm/msm/dsi/dsi_host.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/dsi/dsi_host.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/dsi/dsi_host.c	2016-07-24 15:23:50.000000000 -0400
@@ -325,18 +325,6 @@ static int dsi_regulator_init(struct msm
 		return ret;
 	}
 
-	for (i = 0; i < num; i++) {
-		if (regulator_can_change_voltage(s[i].consumer)) {
-			ret = regulator_set_voltage(s[i].consumer,
-				regs[i].min_voltage, regs[i].max_voltage);
-			if (ret < 0) {
-				pr_err("regulator %d set voltage failed, %d\n",
-					i, ret);
-				return ret;
-			}
-		}
-	}
-
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/dsi/dsi_manager.c linux-libre-4.7-gnu/drivers/gpu/drm/msm/dsi/dsi_manager.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/dsi/dsi_manager.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/dsi/dsi_manager.c	2016-07-24 15:23:50.000000000 -0400
@@ -198,9 +198,13 @@ static enum drm_connector_status dsi_mgr
 
 static void dsi_mgr_connector_destroy(struct drm_connector *connector)
 {
+	struct dsi_connector *dsi_connector = to_dsi_connector(connector);
+
 	DBG("");
-	drm_connector_unregister(connector);
+
 	drm_connector_cleanup(connector);
+
+	kfree(dsi_connector);
 }
 
 static void dsi_dual_connector_fix_modes(struct drm_connector *connector)
@@ -538,12 +542,9 @@ struct drm_connector *msm_dsi_manager_co
 	struct dsi_connector *dsi_connector;
 	int ret, i;
 
-	dsi_connector = devm_kzalloc(msm_dsi->dev->dev,
-				sizeof(*dsi_connector), GFP_KERNEL);
-	if (!dsi_connector) {
-		ret = -ENOMEM;
-		goto fail;
-	}
+	dsi_connector = kzalloc(sizeof(*dsi_connector), GFP_KERNEL);
+	if (!dsi_connector)
+		return ERR_PTR(-ENOMEM);
 
 	dsi_connector->id = id;
 
@@ -552,7 +553,7 @@ struct drm_connector *msm_dsi_manager_co
 	ret = drm_connector_init(msm_dsi->dev, connector,
 			&dsi_mgr_connector_funcs, DRM_MODE_CONNECTOR_DSI);
 	if (ret)
-		goto fail;
+		return ERR_PTR(ret);
 
 	drm_connector_helper_add(connector, &dsi_mgr_conn_helper_funcs);
 
@@ -565,21 +566,11 @@ struct drm_connector *msm_dsi_manager_co
 	connector->interlace_allowed = 0;
 	connector->doublescan_allowed = 0;
 
-	ret = drm_connector_register(connector);
-	if (ret)
-		goto fail;
-
 	for (i = 0; i < MSM_DSI_ENCODER_NUM; i++)
 		drm_mode_connector_attach_encoder(connector,
 						msm_dsi->encoders[i]);
 
 	return connector;
-
-fail:
-	if (connector)
-		dsi_mgr_connector_destroy(connector);
-
-	return ERR_PTR(ret);
 }
 
 /* initialize bridge */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c linux-libre-4.7-gnu/drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c	2016-07-24 15:23:50.000000000 -0400
@@ -138,8 +138,8 @@ const struct msm_dsi_phy_cfg dsi_phy_20n
 	.reg_cfg = {
 		.num = 2,
 		.regs = {
-			{"vddio", 1800000, 1800000, 100000, 100},
-			{"vcca", 1000000, 1000000, 10000, 100},
+			{"vddio", 100000, 100},	/* 1.8 V */
+			{"vcca", 10000, 100},	/* 1.0 V */
 		},
 	},
 	.ops = {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c linux-libre-4.7-gnu/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c	2016-07-24 15:23:50.000000000 -0400
@@ -185,7 +185,7 @@ const struct msm_dsi_phy_cfg dsi_phy_28n
 	.reg_cfg = {
 		.num = 1,
 		.regs = {
-			{"vddio", 1800000, 1800000, 100000, 100},
+			{"vddio", 100000, 100},	/* 1.8 V */
 		},
 	},
 	.ops = {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c linux-libre-4.7-gnu/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c	2016-07-24 15:23:50.000000000 -0400
@@ -138,7 +138,7 @@ const struct msm_dsi_phy_cfg dsi_phy_28n
 	.reg_cfg = {
 		.num = 1,
 		.regs = {
-			{"vddio", 1800000, 1800000, 100000, 100},
+			{"vddio", 100000, 100},
 		},
 	},
 	.ops = {
@@ -153,7 +153,7 @@ const struct msm_dsi_phy_cfg dsi_phy_28n
 	.reg_cfg = {
 		.num = 1,
 		.regs = {
-			{"vddio", 1800000, 1800000, 100000, 100},
+			{"vddio", 100000, 100},	/* 1.8 V */
 		},
 	},
 	.ops = {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c linux-libre-4.7-gnu/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c	2016-07-24 15:23:50.000000000 -0400
@@ -177,19 +177,6 @@ static int dsi_phy_regulator_init(struct
 		return ret;
 	}
 
-	for (i = 0; i < num; i++) {
-		if (regulator_can_change_voltage(s[i].consumer)) {
-			ret = regulator_set_voltage(s[i].consumer,
-				regs[i].min_voltage, regs[i].max_voltage);
-			if (ret < 0) {
-				dev_err(dev,
-					"regulator %d set voltage failed, %d\n",
-					i, ret);
-				return ret;
-			}
-		}
-	}
-
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/edp/edp_connector.c linux-libre-4.7-gnu/drivers/gpu/drm/msm/edp/edp_connector.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/edp/edp_connector.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/edp/edp_connector.c	2016-07-24 15:23:50.000000000 -0400
@@ -37,7 +37,7 @@ static void edp_connector_destroy(struct
 	struct edp_connector *edp_connector = to_edp_connector(connector);
 
 	DBG("");
-	drm_connector_unregister(connector);
+
 	drm_connector_cleanup(connector);
 
 	kfree(edp_connector);
@@ -124,10 +124,8 @@ struct drm_connector *msm_edp_connector_
 	int ret;
 
 	edp_connector = kzalloc(sizeof(*edp_connector), GFP_KERNEL);
-	if (!edp_connector) {
-		ret = -ENOMEM;
-		goto fail;
-	}
+	if (!edp_connector)
+		return ERR_PTR(-ENOMEM);
 
 	edp_connector->edp = edp;
 
@@ -136,7 +134,7 @@ struct drm_connector *msm_edp_connector_
 	ret = drm_connector_init(edp->dev, connector, &edp_connector_funcs,
 			DRM_MODE_CONNECTOR_eDP);
 	if (ret)
-		goto fail;
+		return ERR_PTR(ret);
 
 	drm_connector_helper_add(connector, &edp_connector_helper_funcs);
 
@@ -147,17 +145,7 @@ struct drm_connector *msm_edp_connector_
 	connector->interlace_allowed = false;
 	connector->doublescan_allowed = false;
 
-	ret = drm_connector_register(connector);
-	if (ret)
-		goto fail;
-
 	drm_mode_connector_attach_encoder(connector, edp->encoder);
 
 	return connector;
-
-fail:
-	if (connector)
-		edp_connector_destroy(connector);
-
-	return ERR_PTR(ret);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/edp/edp_ctrl.c linux-libre-4.7-gnu/drivers/gpu/drm/msm/edp/edp_ctrl.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/edp/edp_ctrl.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/edp/edp_ctrl.c	2016-07-24 15:23:50.000000000 -0400
@@ -21,8 +21,6 @@
 #include "edp.h"
 #include "edp.xml.h"
 
-#define VDDA_MIN_UV		1800000	/* uV units */
-#define VDDA_MAX_UV		1800000	/* uV units */
 #define VDDA_UA_ON_LOAD		100000	/* uA units */
 #define VDDA_UA_OFF_LOAD	100	/* uA units */
 
@@ -67,7 +65,7 @@ struct edp_ctrl {
 	void __iomem *base;
 
 	/* regulators */
-	struct regulator *vdda_vreg;
+	struct regulator *vdda_vreg;	/* 1.8 V */
 	struct regulator *lvl_vreg;
 
 	/* clocks */
@@ -302,21 +300,24 @@ static void edp_clk_disable(struct edp_c
 static int edp_regulator_init(struct edp_ctrl *ctrl)
 {
 	struct device *dev = &ctrl->pdev->dev;
+	int ret;
 
 	DBG("");
 	ctrl->vdda_vreg = devm_regulator_get(dev, "vdda");
-	if (IS_ERR(ctrl->vdda_vreg)) {
-		pr_err("%s: Could not get vdda reg, ret = %ld\n", __func__,
-				PTR_ERR(ctrl->vdda_vreg));
+	ret = PTR_ERR_OR_ZERO(ctrl->vdda_vreg);
+	if (ret) {
+		pr_err("%s: Could not get vdda reg, ret = %d\n", __func__,
+				ret);
 		ctrl->vdda_vreg = NULL;
-		return PTR_ERR(ctrl->vdda_vreg);
+		return ret;
 	}
 	ctrl->lvl_vreg = devm_regulator_get(dev, "lvl-vdd");
-	if (IS_ERR(ctrl->lvl_vreg)) {
-		pr_err("Could not get lvl-vdd reg, %ld",
-				PTR_ERR(ctrl->lvl_vreg));
+	ret = PTR_ERR_OR_ZERO(ctrl->lvl_vreg);
+	if (ret) {
+		pr_err("%s: Could not get lvl-vdd reg, ret = %d\n", __func__,
+				ret);
 		ctrl->lvl_vreg = NULL;
-		return PTR_ERR(ctrl->lvl_vreg);
+		return ret;
 	}
 
 	return 0;
@@ -326,12 +327,6 @@ static int edp_regulator_enable(struct e
 {
 	int ret;
 
-	ret = regulator_set_voltage(ctrl->vdda_vreg, VDDA_MIN_UV, VDDA_MAX_UV);
-	if (ret) {
-		pr_err("%s:vdda_vreg set_voltage failed, %d\n", __func__, ret);
-		goto vdda_set_fail;
-	}
-
 	ret = regulator_set_load(ctrl->vdda_vreg, VDDA_UA_ON_LOAD);
 	if (ret < 0) {
 		pr_err("%s: vdda_vreg set regulator mode failed.\n", __func__);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/hdmi/hdmi_connector.c linux-libre-4.7-gnu/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/hdmi/hdmi_connector.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/hdmi/hdmi_connector.c	2016-07-24 15:23:50.000000000 -0400
@@ -112,6 +112,9 @@ static int gpio_config(struct hdmi *hdmi
 		for (i = 0; i < HDMI_MAX_NUM_GPIO; i++) {
 			struct hdmi_gpio_data gpio = config->gpios[i];
 
+			if (gpio.num == -1)
+				continue;
+
 			if (gpio.output) {
 				int value = gpio.value ? 0 : 1;
 
@@ -126,8 +129,10 @@ static int gpio_config(struct hdmi *hdmi
 
 	return 0;
 err:
-	while (i--)
-		gpio_free(config->gpios[i].num);
+	while (i--) {
+		if (config->gpios[i].num != -1)
+			gpio_free(config->gpios[i].num);
+	}
 
 	return ret;
 }
@@ -341,7 +346,6 @@ static void hdmi_connector_destroy(struc
 
 	hdp_disable(hdmi_connector);
 
-	drm_connector_unregister(connector);
 	drm_connector_cleanup(connector);
 
 	kfree(hdmi_connector);
@@ -433,10 +437,8 @@ struct drm_connector *msm_hdmi_connector
 	int ret;
 
 	hdmi_connector = kzalloc(sizeof(*hdmi_connector), GFP_KERNEL);
-	if (!hdmi_connector) {
-		ret = -ENOMEM;
-		goto fail;
-	}
+	if (!hdmi_connector)
+		return ERR_PTR(-ENOMEM);
 
 	hdmi_connector->hdmi = hdmi;
 	INIT_WORK(&hdmi_connector->hpd_work, msm_hdmi_hotplug_work);
@@ -453,21 +455,13 @@ struct drm_connector *msm_hdmi_connector
 	connector->interlace_allowed = 0;
 	connector->doublescan_allowed = 0;
 
-	drm_connector_register(connector);
-
 	ret = hpd_enable(hdmi_connector);
 	if (ret) {
 		dev_err(&hdmi->pdev->dev, "failed to enable HPD: %d\n", ret);
-		goto fail;
+		return ERR_PTR(ret);
 	}
 
 	drm_mode_connector_attach_encoder(connector, hdmi->encoder);
 
 	return connector;
-
-fail:
-	if (connector)
-		hdmi_connector_destroy(connector);
-
-	return ERR_PTR(ret);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/hdmi/hdmi.h linux-libre-4.7-gnu/drivers/gpu/drm/msm/hdmi/hdmi.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/hdmi/hdmi.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/hdmi/hdmi.h	2016-07-24 15:23:50.000000000 -0400
@@ -243,10 +243,21 @@ struct i2c_adapter *msm_hdmi_i2c_init(st
 /*
  * hdcp
  */
+#ifdef CONFIG_DRM_MSM_HDMI_HDCP
 struct hdmi_hdcp_ctrl *msm_hdmi_hdcp_init(struct hdmi *hdmi);
 void msm_hdmi_hdcp_destroy(struct hdmi *hdmi);
 void msm_hdmi_hdcp_on(struct hdmi_hdcp_ctrl *hdcp_ctrl);
 void msm_hdmi_hdcp_off(struct hdmi_hdcp_ctrl *hdcp_ctrl);
 void msm_hdmi_hdcp_irq(struct hdmi_hdcp_ctrl *hdcp_ctrl);
+#else
+static inline struct hdmi_hdcp_ctrl *msm_hdmi_hdcp_init(struct hdmi *hdmi)
+{
+	return ERR_PTR(-ENXIO);
+}
+static inline void msm_hdmi_hdcp_destroy(struct hdmi *hdmi) {}
+static inline void msm_hdmi_hdcp_on(struct hdmi_hdcp_ctrl *hdcp_ctrl) {}
+static inline void msm_hdmi_hdcp_off(struct hdmi_hdcp_ctrl *hdcp_ctrl) {}
+static inline void msm_hdmi_hdcp_irq(struct hdmi_hdcp_ctrl *hdcp_ctrl) {}
+#endif
 
 #endif /* __HDMI_CONNECTOR_H__ */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/Kconfig linux-libre-4.7-gnu/drivers/gpu/drm/msm/Kconfig
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -23,6 +23,13 @@ config DRM_MSM_REGISTER_LOGGING
 	  that can be parsed by envytools demsm tool.  If enabled, register
 	  logging can be switched on via msm.reglog=y module param.
 
+config DRM_MSM_HDMI_HDCP
+	bool "Enable HDMI HDCP support in MSM DRM driver"
+	depends on DRM_MSM && QCOM_SCM
+	default y
+	help
+	  Choose this option to enable HDCP state machine
+
 config DRM_MSM_DSI
 	bool "Enable DSI support in MSM DRM driver"
 	depends on DRM_MSM
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/Makefile linux-libre-4.7-gnu/drivers/gpu/drm/msm/Makefile
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -10,7 +10,6 @@ msm-y := \
 	hdmi/hdmi_audio.o \
 	hdmi/hdmi_bridge.o \
 	hdmi/hdmi_connector.o \
-	hdmi/hdmi_hdcp.o \
 	hdmi/hdmi_i2c.o \
 	hdmi/hdmi_phy.o \
 	hdmi/hdmi_phy_8960.o \
@@ -40,8 +39,10 @@ msm-y := \
 	mdp/mdp5/mdp5_plane.o \
 	mdp/mdp5/mdp5_smp.o \
 	msm_atomic.o \
+	msm_debugfs.o \
 	msm_drv.o \
 	msm_fb.o \
+	msm_fence.o \
 	msm_gem.o \
 	msm_gem_prime.o \
 	msm_gem_submit.o \
@@ -56,6 +57,8 @@ msm-$(CONFIG_COMMON_CLK) += mdp/mdp4/mdp
 msm-$(CONFIG_COMMON_CLK) += hdmi/hdmi_pll_8960.o
 msm-$(CONFIG_COMMON_CLK) += hdmi/hdmi_phy_8996.o
 
+msm-$(CONFIG_DRM_MSM_HDMI_HDCP) += hdmi/hdmi_hdcp.o
+
 msm-$(CONFIG_DRM_MSM_DSI) += dsi/dsi.o \
 			mdp/mdp4/mdp4_dsi_encoder.o \
 			dsi/dsi_cfg.o \
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c linux-libre-4.7-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c	2016-07-24 15:23:50.000000000 -0400
@@ -121,7 +121,7 @@ static void complete_flip(struct drm_crt
 		if (!file || (event->base.file_priv == file)) {
 			mdp4_crtc->event = NULL;
 			DBG("%s: send event: %p", mdp4_crtc->name, event);
-			drm_send_vblank_event(dev, mdp4_crtc->id, event);
+			drm_crtc_send_vblank_event(crtc, event);
 		}
 	}
 	spin_unlock_irqrestore(&dev->event_lock, flags);
@@ -427,7 +427,7 @@ static int mdp4_crtc_cursor_set(struct d
 	}
 
 	if (handle) {
-		cursor_bo = drm_gem_object_lookup(dev, file_priv, handle);
+		cursor_bo = drm_gem_object_lookup(file_priv, handle);
 		if (!cursor_bo)
 			return -ENOENT;
 	} else {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c linux-libre-4.7-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c	2016-07-24 15:23:50.000000000 -0400
@@ -50,30 +50,6 @@ static int mdp4_hw_init(struct msm_kms *
 
 	mdp4_kms->rev = minor;
 
-	if (mdp4_kms->dsi_pll_vdda) {
-		if ((mdp4_kms->rev == 2) || (mdp4_kms->rev == 4)) {
-			ret = regulator_set_voltage(mdp4_kms->dsi_pll_vdda,
-					1200000, 1200000);
-			if (ret) {
-				dev_err(dev->dev,
-					"failed to set dsi_pll_vdda voltage: %d\n", ret);
-				goto out;
-			}
-		}
-	}
-
-	if (mdp4_kms->dsi_pll_vddio) {
-		if (mdp4_kms->rev == 2) {
-			ret = regulator_set_voltage(mdp4_kms->dsi_pll_vddio,
-					1800000, 1800000);
-			if (ret) {
-				dev_err(dev->dev,
-					"failed to set dsi_pll_vddio voltage: %d\n", ret);
-				goto out;
-			}
-		}
-	}
-
 	if (mdp4_kms->rev > 1) {
 		mdp4_write(mdp4_kms, REG_MDP4_CS_CONTROLLER0, 0x0707ffff);
 		mdp4_write(mdp4_kms, REG_MDP4_CS_CONTROLLER1, 0x03073f3f);
@@ -485,16 +461,6 @@ struct msm_kms *mdp4_kms_init(struct drm
 		goto fail;
 	}
 
-	mdp4_kms->dsi_pll_vdda =
-			devm_regulator_get_optional(&pdev->dev, "dsi_pll_vdda");
-	if (IS_ERR(mdp4_kms->dsi_pll_vdda))
-		mdp4_kms->dsi_pll_vdda = NULL;
-
-	mdp4_kms->dsi_pll_vddio =
-			devm_regulator_get_optional(&pdev->dev, "dsi_pll_vddio");
-	if (IS_ERR(mdp4_kms->dsi_pll_vddio))
-		mdp4_kms->dsi_pll_vddio = NULL;
-
 	/* NOTE: driver for this regulator still missing upstream.. use
 	 * _get_exclusive() and ignore the error if it does not exist
 	 * (and hope that the bootloader left it on for us)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h linux-libre-4.7-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h	2016-07-24 15:23:50.000000000 -0400
@@ -37,8 +37,6 @@ struct mdp4_kms {
 
 	void __iomem *mmio;
 
-	struct regulator *dsi_pll_vdda;
-	struct regulator *dsi_pll_vddio;
 	struct regulator *vdd;
 
 	struct clk *clk;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_connector.c linux-libre-4.7-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_connector.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_connector.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lvds_connector.c	2016-07-24 15:23:50.000000000 -0400
@@ -48,7 +48,6 @@ static void mdp4_lvds_connector_destroy(
 	struct mdp4_lvds_connector *mdp4_lvds_connector =
 			to_mdp4_lvds_connector(connector);
 
-	drm_connector_unregister(connector);
 	drm_connector_cleanup(connector);
 
 	kfree(mdp4_lvds_connector);
@@ -121,13 +120,10 @@ struct drm_connector *mdp4_lvds_connecto
 {
 	struct drm_connector *connector = NULL;
 	struct mdp4_lvds_connector *mdp4_lvds_connector;
-	int ret;
 
 	mdp4_lvds_connector = kzalloc(sizeof(*mdp4_lvds_connector), GFP_KERNEL);
-	if (!mdp4_lvds_connector) {
-		ret = -ENOMEM;
-		goto fail;
-	}
+	if (!mdp4_lvds_connector)
+		return ERR_PTR(-ENOMEM);
 
 	mdp4_lvds_connector->encoder = encoder;
 	mdp4_lvds_connector->panel_node = panel_node;
@@ -143,15 +139,7 @@ struct drm_connector *mdp4_lvds_connecto
 	connector->interlace_allowed = 0;
 	connector->doublescan_allowed = 0;
 
-	drm_connector_register(connector);
-
 	drm_mode_connector_attach_encoder(connector, encoder);
 
 	return connector;
-
-fail:
-	if (connector)
-		mdp4_lvds_connector_destroy(connector);
-
-	return ERR_PTR(ret);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c linux-libre-4.7-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c	2016-07-24 15:23:50.000000000 -0400
@@ -149,7 +149,7 @@ static void complete_flip(struct drm_crt
 		if (!file || (event->base.file_priv == file)) {
 			mdp5_crtc->event = NULL;
 			DBG("%s: send event: %p", mdp5_crtc->name, event);
-			drm_send_vblank_event(dev, mdp5_crtc->id, event);
+			drm_crtc_send_vblank_event(crtc, event);
 		}
 	}
 	spin_unlock_irqrestore(&dev->event_lock, flags);
@@ -518,7 +518,7 @@ static int mdp5_crtc_cursor_set(struct d
 		goto set_cursor;
 	}
 
-	cursor_bo = drm_gem_object_lookup(dev, file, handle);
+	cursor_bo = drm_gem_object_lookup(file, handle);
 	if (!cursor_bo)
 		return -ENOENT;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/mdp/mdp_format.c linux-libre-4.7-gnu/drivers/gpu/drm/msm/mdp/mdp_format.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/mdp/mdp_format.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/mdp/mdp_format.c	2016-07-24 15:23:50.000000000 -0400
@@ -105,6 +105,12 @@ static const struct mdp_format formats[]
 			MDP_PLANE_INTERLEAVED, CHROMA_FULL, false),
 	FMT(XRGB8888, 8, 8, 8, 8,  1, 0, 2, 3,  false,  true,  4,  4,
 			MDP_PLANE_INTERLEAVED, CHROMA_FULL, false),
+	FMT(XBGR8888, 8, 8, 8, 8,  2, 0, 1, 3,  false,   true,  4,  4,
+			MDP_PLANE_INTERLEAVED, CHROMA_FULL, false),
+	FMT(RGBX8888, 8, 8, 8, 8,  3, 1, 0, 2,  false,   true,  4,  4,
+			MDP_PLANE_INTERLEAVED, CHROMA_FULL, false),
+	FMT(BGRX8888, 8, 8, 8, 8,  3, 2, 0, 1,  false,   true,  4,  4,
+			MDP_PLANE_INTERLEAVED, CHROMA_FULL, false),
 	FMT(RGB888,   0, 8, 8, 8,  1, 0, 2, 0,  false,  true,  3,  3,
 			MDP_PLANE_INTERLEAVED, CHROMA_FULL, false),
 	FMT(BGR888,   0, 8, 8, 8,  2, 0, 1, 0,  false,  true,  3,  3,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/msm_atomic.c linux-libre-4.7-gnu/drivers/gpu/drm/msm/msm_atomic.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/msm_atomic.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/msm_atomic.c	2016-07-24 15:23:50.000000000 -0400
@@ -18,16 +18,16 @@
 #include "msm_drv.h"
 #include "msm_kms.h"
 #include "msm_gem.h"
+#include "msm_fence.h"
 
 struct msm_commit {
 	struct drm_device *dev;
 	struct drm_atomic_state *state;
-	uint32_t fence;
-	struct msm_fence_cb fence_cb;
+	struct work_struct work;
 	uint32_t crtc_mask;
 };
 
-static void fence_cb(struct msm_fence_cb *cb);
+static void commit_worker(struct work_struct *work);
 
 /* block until specified crtcs are no longer pending update, and
  * atomically mark them as pending update
@@ -69,11 +69,7 @@ static struct msm_commit *commit_init(st
 	c->dev = state->dev;
 	c->state = state;
 
-	/* TODO we might need a way to indicate to run the cb on a
-	 * different wq so wait_for_vblanks() doesn't block retiring
-	 * bo's..
-	 */
-	INIT_FENCE_CB(&c->fence_cb, fence_cb);
+	INIT_WORK(&c->work, commit_worker);
 
 	return c;
 }
@@ -114,13 +110,15 @@ static void msm_atomic_wait_for_commit_d
 /* The (potentially) asynchronous part of the commit.  At this point
  * nothing can fail short of armageddon.
  */
-static void complete_commit(struct msm_commit *c)
+static void complete_commit(struct msm_commit *c, bool async)
 {
 	struct drm_atomic_state *state = c->state;
 	struct drm_device *dev = state->dev;
 	struct msm_drm_private *priv = dev->dev_private;
 	struct msm_kms *kms = priv->kms;
 
+	drm_atomic_helper_wait_for_fences(dev, state);
+
 	kms->funcs->prepare_commit(kms, state);
 
 	drm_atomic_helper_commit_modeset_disables(dev, state);
@@ -153,17 +151,9 @@ static void complete_commit(struct msm_c
 	commit_destroy(c);
 }
 
-static void fence_cb(struct msm_fence_cb *cb)
-{
-	struct msm_commit *c =
-			container_of(cb, struct msm_commit, fence_cb);
-	complete_commit(c);
-}
-
-static void add_fb(struct msm_commit *c, struct drm_framebuffer *fb)
+static void commit_worker(struct work_struct *work)
 {
-	struct drm_gem_object *obj = msm_framebuffer_bo(fb, 0);
-	c->fence = max(c->fence, msm_gem_fence(to_msm_bo(obj), MSM_PREP_READ));
+	complete_commit(container_of(work, struct msm_commit, work), true);
 }
 
 int msm_atomic_check(struct drm_device *dev,
@@ -190,21 +180,20 @@ int msm_atomic_check(struct drm_device *
  * drm_atomic_helper_commit - commit validated state object
  * @dev: DRM device
  * @state: the driver state object
- * @async: asynchronous commit
+ * @nonblock: nonblocking commit
  *
  * This function commits a with drm_atomic_helper_check() pre-validated state
- * object. This can still fail when e.g. the framebuffer reservation fails. For
- * now this doesn't implement asynchronous commits.
+ * object. This can still fail when e.g. the framebuffer reservation fails.
  *
  * RETURNS
  * Zero for success or -errno.
  */
 int msm_atomic_commit(struct drm_device *dev,
-		struct drm_atomic_state *state, bool async)
+		struct drm_atomic_state *state, bool nonblock)
 {
+	struct msm_drm_private *priv = dev->dev_private;
 	int nplanes = dev->mode_config.num_total_plane;
 	int ncrtcs = dev->mode_config.num_crtc;
-	ktime_t timeout;
 	struct msm_commit *c;
 	int i, ret;
 
@@ -238,8 +227,12 @@ int msm_atomic_commit(struct drm_device
 		if (!plane)
 			continue;
 
-		if ((plane->state->fb != new_state->fb) && new_state->fb)
-			add_fb(c, new_state->fb);
+		if ((plane->state->fb != new_state->fb) && new_state->fb) {
+			struct drm_gem_object *obj = msm_framebuffer_bo(new_state->fb, 0);
+			struct msm_gem_object *msm_obj = to_msm_bo(obj);
+
+			new_state->fence = reservation_object_get_excl_rcu(msm_obj->resv);
+		}
 	}
 
 	/*
@@ -276,17 +269,12 @@ int msm_atomic_commit(struct drm_device
 	 * current layout.
 	 */
 
-	if (async) {
-		msm_queue_fence_cb(dev, &c->fence_cb, c->fence);
+	if (nonblock) {
+		queue_work(priv->atomic_wq, &c->work);
 		return 0;
 	}
 
-	timeout = ktime_add_ms(ktime_get(), 1000);
-
-	/* uninterruptible wait */
-	msm_wait_fence(dev, c->fence, &timeout, false);
-
-	complete_commit(c);
+	complete_commit(c, false);
 
 	return 0;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/msm_debugfs.c linux-libre-4.7-gnu/drivers/gpu/drm/msm/msm_debugfs.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/msm_debugfs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/msm_debugfs.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2013-2016 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef CONFIG_DEBUG_FS
+#include "msm_drv.h"
+#include "msm_gpu.h"
+
+static int msm_gpu_show(struct drm_device *dev, struct seq_file *m)
+{
+	struct msm_drm_private *priv = dev->dev_private;
+	struct msm_gpu *gpu = priv->gpu;
+
+	if (gpu) {
+		seq_printf(m, "%s Status:\n", gpu->name);
+		gpu->funcs->show(gpu, m);
+	}
+
+	return 0;
+}
+
+static int msm_gem_show(struct drm_device *dev, struct seq_file *m)
+{
+	struct msm_drm_private *priv = dev->dev_private;
+	struct msm_gpu *gpu = priv->gpu;
+
+	if (gpu) {
+		seq_printf(m, "Active Objects (%s):\n", gpu->name);
+		msm_gem_describe_objects(&gpu->active_list, m);
+	}
+
+	seq_printf(m, "Inactive Objects:\n");
+	msm_gem_describe_objects(&priv->inactive_list, m);
+
+	return 0;
+}
+
+static int msm_mm_show(struct drm_device *dev, struct seq_file *m)
+{
+	return drm_mm_dump_table(m, &dev->vma_offset_manager->vm_addr_space_mm);
+}
+
+static int msm_fb_show(struct drm_device *dev, struct seq_file *m)
+{
+	struct msm_drm_private *priv = dev->dev_private;
+	struct drm_framebuffer *fb, *fbdev_fb = NULL;
+
+	if (priv->fbdev) {
+		seq_printf(m, "fbcon ");
+		fbdev_fb = priv->fbdev->fb;
+		msm_framebuffer_describe(fbdev_fb, m);
+	}
+
+	mutex_lock(&dev->mode_config.fb_lock);
+	list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
+		if (fb == fbdev_fb)
+			continue;
+
+		seq_printf(m, "user ");
+		msm_framebuffer_describe(fb, m);
+	}
+	mutex_unlock(&dev->mode_config.fb_lock);
+
+	return 0;
+}
+
+static int show_locked(struct seq_file *m, void *arg)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	int (*show)(struct drm_device *dev, struct seq_file *m) =
+			node->info_ent->data;
+	int ret;
+
+	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	if (ret)
+		return ret;
+
+	ret = show(dev, m);
+
+	mutex_unlock(&dev->struct_mutex);
+
+	return ret;
+}
+
+static struct drm_info_list msm_debugfs_list[] = {
+		{"gpu", show_locked, 0, msm_gpu_show},
+		{"gem", show_locked, 0, msm_gem_show},
+		{ "mm", show_locked, 0, msm_mm_show },
+		{ "fb", show_locked, 0, msm_fb_show },
+};
+
+static int late_init_minor(struct drm_minor *minor)
+{
+	int ret;
+
+	if (!minor)
+		return 0;
+
+	ret = msm_rd_debugfs_init(minor);
+	if (ret) {
+		dev_err(minor->dev->dev, "could not install rd debugfs\n");
+		return ret;
+	}
+
+	ret = msm_perf_debugfs_init(minor);
+	if (ret) {
+		dev_err(minor->dev->dev, "could not install perf debugfs\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+int msm_debugfs_late_init(struct drm_device *dev)
+{
+	int ret;
+	ret = late_init_minor(dev->primary);
+	if (ret)
+		return ret;
+	ret = late_init_minor(dev->render);
+	if (ret)
+		return ret;
+	ret = late_init_minor(dev->control);
+	return ret;
+}
+
+int msm_debugfs_init(struct drm_minor *minor)
+{
+	struct drm_device *dev = minor->dev;
+	int ret;
+
+	ret = drm_debugfs_create_files(msm_debugfs_list,
+			ARRAY_SIZE(msm_debugfs_list),
+			minor->debugfs_root, minor);
+
+	if (ret) {
+		dev_err(dev->dev, "could not install msm_debugfs_list\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+void msm_debugfs_cleanup(struct drm_minor *minor)
+{
+	drm_debugfs_remove_files(msm_debugfs_list,
+			ARRAY_SIZE(msm_debugfs_list), minor);
+	if (!minor->dev->dev_private)
+		return;
+	msm_rd_debugfs_cleanup(minor);
+	msm_perf_debugfs_cleanup(minor);
+}
+#endif
+
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/msm_debugfs.h linux-libre-4.7-gnu/drivers/gpu/drm/msm/msm_debugfs.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/msm_debugfs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/msm_debugfs.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2016 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MSM_DEBUGFS_H__
+#define __MSM_DEBUGFS_H__
+
+#ifdef CONFIG_DEBUG_FS
+int msm_debugfs_init(struct drm_minor *minor);
+void msm_debugfs_cleanup(struct drm_minor *minor);
+#endif
+
+#endif /* __MSM_DEBUGFS_H__ */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/msm_drv.c linux-libre-4.7-gnu/drivers/gpu/drm/msm/msm_drv.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/msm_drv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/msm_drv.c	2016-07-24 15:23:50.000000000 -0400
@@ -16,6 +16,8 @@
  */
 
 #include "msm_drv.h"
+#include "msm_debugfs.h"
+#include "msm_fence.h"
 #include "msm_gpu.h"
 #include "msm_kms.h"
 
@@ -173,13 +175,11 @@ static int vblank_ctrl_queue_work(struct
 	return 0;
 }
 
-/*
- * DRM operations:
- */
-
-static int msm_unload(struct drm_device *dev)
+static int msm_drm_uninit(struct device *dev)
 {
-	struct msm_drm_private *priv = dev->dev_private;
+	struct platform_device *pdev = to_platform_device(dev);
+	struct drm_device *ddev = platform_get_drvdata(pdev);
+	struct msm_drm_private *priv = ddev->dev_private;
 	struct msm_kms *kms = priv->kms;
 	struct msm_gpu *gpu = priv->gpu;
 	struct msm_vblank_ctrl *vbl_ctrl = &priv->vblank_ctrl;
@@ -195,31 +195,37 @@ static int msm_unload(struct drm_device
 		kfree(vbl_ev);
 	}
 
-	drm_kms_helper_poll_fini(dev);
+	drm_kms_helper_poll_fini(ddev);
+
+	drm_connector_unregister_all(ddev);
+
+	drm_dev_unregister(ddev);
 
 #ifdef CONFIG_DRM_FBDEV_EMULATION
 	if (fbdev && priv->fbdev)
-		msm_fbdev_free(dev);
+		msm_fbdev_free(ddev);
 #endif
-	drm_mode_config_cleanup(dev);
-	drm_vblank_cleanup(dev);
+	drm_mode_config_cleanup(ddev);
 
-	pm_runtime_get_sync(dev->dev);
-	drm_irq_uninstall(dev);
-	pm_runtime_put_sync(dev->dev);
+	pm_runtime_get_sync(dev);
+	drm_irq_uninstall(ddev);
+	pm_runtime_put_sync(dev);
 
 	flush_workqueue(priv->wq);
 	destroy_workqueue(priv->wq);
 
+	flush_workqueue(priv->atomic_wq);
+	destroy_workqueue(priv->atomic_wq);
+
 	if (kms) {
-		pm_runtime_disable(dev->dev);
+		pm_runtime_disable(dev);
 		kms->funcs->destroy(kms);
 	}
 
 	if (gpu) {
-		mutex_lock(&dev->struct_mutex);
+		mutex_lock(&ddev->struct_mutex);
 		gpu->funcs->pm_suspend(gpu);
-		mutex_unlock(&dev->struct_mutex);
+		mutex_unlock(&ddev->struct_mutex);
 		gpu->funcs->destroy(gpu);
 	}
 
@@ -227,13 +233,14 @@ static int msm_unload(struct drm_device
 		DEFINE_DMA_ATTRS(attrs);
 		dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs);
 		drm_mm_takedown(&priv->vram.mm);
-		dma_free_attrs(dev->dev, priv->vram.size, NULL,
-				priv->vram.paddr, &attrs);
+		dma_free_attrs(dev, priv->vram.size, NULL,
+			       priv->vram.paddr, &attrs);
 	}
 
-	component_unbind_all(dev->dev, dev);
+	component_unbind_all(dev, ddev);
 
-	dev->dev_private = NULL;
+	ddev->dev_private = NULL;
+	drm_dev_unref(ddev);
 
 	kfree(priv);
 
@@ -321,50 +328,60 @@ static int msm_init_vram(struct drm_devi
 	return ret;
 }
 
-static int msm_load(struct drm_device *dev, unsigned long flags)
+static int msm_drm_init(struct device *dev, struct drm_driver *drv)
 {
-	struct platform_device *pdev = dev->platformdev;
+	struct platform_device *pdev = to_platform_device(dev);
+	struct drm_device *ddev;
 	struct msm_drm_private *priv;
 	struct msm_kms *kms;
 	int ret;
 
+	ddev = drm_dev_alloc(drv, dev);
+	if (!ddev) {
+		dev_err(dev, "failed to allocate drm_device\n");
+		return -ENOMEM;
+	}
+
+	platform_set_drvdata(pdev, ddev);
+	ddev->platformdev = pdev;
+
 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 	if (!priv) {
-		dev_err(dev->dev, "failed to allocate private data\n");
+		drm_dev_unref(ddev);
 		return -ENOMEM;
 	}
 
-	dev->dev_private = priv;
+	ddev->dev_private = priv;
 
 	priv->wq = alloc_ordered_workqueue("msm", 0);
-	init_waitqueue_head(&priv->fence_event);
+	priv->atomic_wq = alloc_ordered_workqueue("msm:atomic", 0);
 	init_waitqueue_head(&priv->pending_crtcs_event);
 
 	INIT_LIST_HEAD(&priv->inactive_list);
-	INIT_LIST_HEAD(&priv->fence_cbs);
 	INIT_LIST_HEAD(&priv->vblank_ctrl.event_list);
 	INIT_WORK(&priv->vblank_ctrl.work, vblank_ctrl_worker);
 	spin_lock_init(&priv->vblank_ctrl.lock);
 
-	drm_mode_config_init(dev);
-
-	platform_set_drvdata(pdev, dev);
+	drm_mode_config_init(ddev);
 
 	/* Bind all our sub-components: */
-	ret = component_bind_all(dev->dev, dev);
-	if (ret)
+	ret = component_bind_all(dev, ddev);
+	if (ret) {
+		kfree(priv);
+		drm_dev_unref(ddev);
 		return ret;
+	}
 
-	ret = msm_init_vram(dev);
+	ret = msm_init_vram(ddev);
 	if (ret)
 		goto fail;
 
 	switch (get_mdp_ver(pdev)) {
 	case 4:
-		kms = mdp4_kms_init(dev);
+		kms = mdp4_kms_init(ddev);
 		break;
 	case 5:
-		kms = mdp5_kms_init(dev);
+		kms = mdp5_kms_init(ddev);
 		break;
 	default:
 		kms = ERR_PTR(-ENODEV);
@@ -378,7 +395,7 @@ static int msm_load(struct drm_device *d
 		 * and (for example) use dmabuf/prime to share buffers with
 		 * imx drm driver on iMX5
 		 */
-		dev_err(dev->dev, "failed to load kms\n");
+		dev_err(dev, "failed to load kms\n");
 		ret = PTR_ERR(kms);
 		goto fail;
 	}
@@ -386,50 +403,64 @@ static int msm_load(struct drm_device *d
 	priv->kms = kms;
 
 	if (kms) {
-		pm_runtime_enable(dev->dev);
+		pm_runtime_enable(dev);
 		ret = kms->funcs->hw_init(kms);
 		if (ret) {
-			dev_err(dev->dev, "kms hw init failed: %d\n", ret);
+			dev_err(dev, "kms hw init failed: %d\n", ret);
 			goto fail;
 		}
 	}
 
-	dev->mode_config.funcs = &mode_config_funcs;
+	ddev->mode_config.funcs = &mode_config_funcs;
 
-	ret = drm_vblank_init(dev, priv->num_crtcs);
+	ret = drm_vblank_init(ddev, priv->num_crtcs);
 	if (ret < 0) {
-		dev_err(dev->dev, "failed to initialize vblank\n");
+		dev_err(dev, "failed to initialize vblank\n");
 		goto fail;
 	}
 
-	pm_runtime_get_sync(dev->dev);
-	ret = drm_irq_install(dev, platform_get_irq(dev->platformdev, 0));
-	pm_runtime_put_sync(dev->dev);
+	pm_runtime_get_sync(dev);
+	ret = drm_irq_install(ddev, platform_get_irq(pdev, 0));
+	pm_runtime_put_sync(dev);
 	if (ret < 0) {
-		dev_err(dev->dev, "failed to install IRQ handler\n");
+		dev_err(dev, "failed to install IRQ handler\n");
 		goto fail;
 	}
 
-	drm_mode_config_reset(dev);
+	ret = drm_dev_register(ddev, 0);
+	if (ret)
+		goto fail;
+
+	ret = drm_connector_register_all(ddev);
+	if (ret) {
+		dev_err(dev, "failed to register connectors\n");
+		goto fail;
+	}
+
+	drm_mode_config_reset(ddev);
 
 #ifdef CONFIG_DRM_FBDEV_EMULATION
 	if (fbdev)
-		priv->fbdev = msm_fbdev_init(dev);
+		priv->fbdev = msm_fbdev_init(ddev);
 #endif
 
-	ret = msm_debugfs_late_init(dev);
+	ret = msm_debugfs_late_init(ddev);
 	if (ret)
 		goto fail;
 
-	drm_kms_helper_poll_init(dev);
+	drm_kms_helper_poll_init(ddev);
 
 	return 0;
 
 fail:
-	msm_unload(dev);
+	msm_drm_uninit(dev);
 	return ret;
 }
 
+/*
+ * DRM operations:
+ */
+
 static void load_gpu(struct drm_device *dev)
 {
 	static DEFINE_MUTEX(init_lock);
@@ -465,7 +496,6 @@ static void msm_preclose(struct drm_devi
 {
 	struct msm_drm_private *priv = dev->dev_private;
 	struct msm_file_private *ctx = file->driver_priv;
-	struct msm_kms *kms = priv->kms;
 
 	mutex_lock(&dev->struct_mutex);
 	if (ctx == priv->lastctx)
@@ -536,265 +566,6 @@ static void msm_disable_vblank(struct dr
 }
 
 /*
- * DRM debugfs:
- */
-
-#ifdef CONFIG_DEBUG_FS
-static int msm_gpu_show(struct drm_device *dev, struct seq_file *m)
-{
-	struct msm_drm_private *priv = dev->dev_private;
-	struct msm_gpu *gpu = priv->gpu;
-
-	if (gpu) {
-		seq_printf(m, "%s Status:\n", gpu->name);
-		gpu->funcs->show(gpu, m);
-	}
-
-	return 0;
-}
-
-static int msm_gem_show(struct drm_device *dev, struct seq_file *m)
-{
-	struct msm_drm_private *priv = dev->dev_private;
-	struct msm_gpu *gpu = priv->gpu;
-
-	if (gpu) {
-		seq_printf(m, "Active Objects (%s):\n", gpu->name);
-		msm_gem_describe_objects(&gpu->active_list, m);
-	}
-
-	seq_printf(m, "Inactive Objects:\n");
-	msm_gem_describe_objects(&priv->inactive_list, m);
-
-	return 0;
-}
-
-static int msm_mm_show(struct drm_device *dev, struct seq_file *m)
-{
-	return drm_mm_dump_table(m, &dev->vma_offset_manager->vm_addr_space_mm);
-}
-
-static int msm_fb_show(struct drm_device *dev, struct seq_file *m)
-{
-	struct msm_drm_private *priv = dev->dev_private;
-	struct drm_framebuffer *fb, *fbdev_fb = NULL;
-
-	if (priv->fbdev) {
-		seq_printf(m, "fbcon ");
-		fbdev_fb = priv->fbdev->fb;
-		msm_framebuffer_describe(fbdev_fb, m);
-	}
-
-	mutex_lock(&dev->mode_config.fb_lock);
-	list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
-		if (fb == fbdev_fb)
-			continue;
-
-		seq_printf(m, "user ");
-		msm_framebuffer_describe(fb, m);
-	}
-	mutex_unlock(&dev->mode_config.fb_lock);
-
-	return 0;
-}
-
-static int show_locked(struct seq_file *m, void *arg)
-{
-	struct drm_info_node *node = (struct drm_info_node *) m->private;
-	struct drm_device *dev = node->minor->dev;
-	int (*show)(struct drm_device *dev, struct seq_file *m) =
-			node->info_ent->data;
-	int ret;
-
-	ret = mutex_lock_interruptible(&dev->struct_mutex);
-	if (ret)
-		return ret;
-
-	ret = show(dev, m);
-
-	mutex_unlock(&dev->struct_mutex);
-
-	return ret;
-}
-
-static struct drm_info_list msm_debugfs_list[] = {
-		{"gpu", show_locked, 0, msm_gpu_show},
-		{"gem", show_locked, 0, msm_gem_show},
-		{ "mm", show_locked, 0, msm_mm_show },
-		{ "fb", show_locked, 0, msm_fb_show },
-};
-
-static int late_init_minor(struct drm_minor *minor)
-{
-	int ret;
-
-	if (!minor)
-		return 0;
-
-	ret = msm_rd_debugfs_init(minor);
-	if (ret) {
-		dev_err(minor->dev->dev, "could not install rd debugfs\n");
-		return ret;
-	}
-
-	ret = msm_perf_debugfs_init(minor);
-	if (ret) {
-		dev_err(minor->dev->dev, "could not install perf debugfs\n");
-		return ret;
-	}
-
-	return 0;
-}
-
-int msm_debugfs_late_init(struct drm_device *dev)
-{
-	int ret;
-	ret = late_init_minor(dev->primary);
-	if (ret)
-		return ret;
-	ret = late_init_minor(dev->render);
-	if (ret)
-		return ret;
-	ret = late_init_minor(dev->control);
-	return ret;
-}
-
-static int msm_debugfs_init(struct drm_minor *minor)
-{
-	struct drm_device *dev = minor->dev;
-	int ret;
-
-	ret = drm_debugfs_create_files(msm_debugfs_list,
-			ARRAY_SIZE(msm_debugfs_list),
-			minor->debugfs_root, minor);
-
-	if (ret) {
-		dev_err(dev->dev, "could not install msm_debugfs_list\n");
-		return ret;
-	}
-
-	return 0;
-}
-
-static void msm_debugfs_cleanup(struct drm_minor *minor)
-{
-	drm_debugfs_remove_files(msm_debugfs_list,
-			ARRAY_SIZE(msm_debugfs_list), minor);
-	if (!minor->dev->dev_private)
-		return;
-	msm_rd_debugfs_cleanup(minor);
-	msm_perf_debugfs_cleanup(minor);
-}
-#endif
-
-/*
- * Fences:
- */
-
-int msm_wait_fence(struct drm_device *dev, uint32_t fence,
-		ktime_t *timeout , bool interruptible)
-{
-	struct msm_drm_private *priv = dev->dev_private;
-	int ret;
-
-	if (!priv->gpu)
-		return 0;
-
-	if (fence > priv->gpu->submitted_fence) {
-		DRM_ERROR("waiting on invalid fence: %u (of %u)\n",
-				fence, priv->gpu->submitted_fence);
-		return -EINVAL;
-	}
-
-	if (!timeout) {
-		/* no-wait: */
-		ret = fence_completed(dev, fence) ? 0 : -EBUSY;
-	} else {
-		ktime_t now = ktime_get();
-		unsigned long remaining_jiffies;
-
-		if (ktime_compare(*timeout, now) < 0) {
-			remaining_jiffies = 0;
-		} else {
-			ktime_t rem = ktime_sub(*timeout, now);
-			struct timespec ts = ktime_to_timespec(rem);
-			remaining_jiffies = timespec_to_jiffies(&ts);
-		}
-
-		if (interruptible)
-			ret = wait_event_interruptible_timeout(priv->fence_event,
-				fence_completed(dev, fence),
-				remaining_jiffies);
-		else
-			ret = wait_event_timeout(priv->fence_event,
-				fence_completed(dev, fence),
-				remaining_jiffies);
-
-		if (ret == 0) {
-			DBG("timeout waiting for fence: %u (completed: %u)",
-					fence, priv->completed_fence);
-			ret = -ETIMEDOUT;
-		} else if (ret != -ERESTARTSYS) {
-			ret = 0;
-		}
-	}
-
-	return ret;
-}
-
-int msm_queue_fence_cb(struct drm_device *dev,
-		struct msm_fence_cb *cb, uint32_t fence)
-{
-	struct msm_drm_private *priv = dev->dev_private;
-	int ret = 0;
-
-	mutex_lock(&dev->struct_mutex);
-	if (!list_empty(&cb->work.entry)) {
-		ret = -EINVAL;
-	} else if (fence > priv->completed_fence) {
-		cb->fence = fence;
-		list_add_tail(&cb->work.entry, &priv->fence_cbs);
-	} else {
-		queue_work(priv->wq, &cb->work);
-	}
-	mutex_unlock(&dev->struct_mutex);
-
-	return ret;
-}
-
-/* called from workqueue */
-void msm_update_fence(struct drm_device *dev, uint32_t fence)
-{
-	struct msm_drm_private *priv = dev->dev_private;
-
-	mutex_lock(&dev->struct_mutex);
-	priv->completed_fence = max(fence, priv->completed_fence);
-
-	while (!list_empty(&priv->fence_cbs)) {
-		struct msm_fence_cb *cb;
-
-		cb = list_first_entry(&priv->fence_cbs,
-				struct msm_fence_cb, work.entry);
-
-		if (cb->fence > priv->completed_fence)
-			break;
-
-		list_del_init(&cb->work.entry);
-		queue_work(priv->wq, &cb->work);
-	}
-
-	mutex_unlock(&dev->struct_mutex);
-
-	wake_up_all(&priv->fence_event);
-}
-
-void __msm_fence_worker(struct work_struct *work)
-{
-	struct msm_fence_cb *cb = container_of(work, struct msm_fence_cb, work);
-	cb->func(cb);
-}
-
-/*
  * DRM ioctls:
  */
 
@@ -851,7 +622,7 @@ static int msm_ioctl_gem_cpu_prep(struct
 		return -EINVAL;
 	}
 
-	obj = drm_gem_object_lookup(dev, file, args->handle);
+	obj = drm_gem_object_lookup(file, args->handle);
 	if (!obj)
 		return -ENOENT;
 
@@ -869,7 +640,7 @@ static int msm_ioctl_gem_cpu_fini(struct
 	struct drm_gem_object *obj;
 	int ret;
 
-	obj = drm_gem_object_lookup(dev, file, args->handle);
+	obj = drm_gem_object_lookup(file, args->handle);
 	if (!obj)
 		return -ENOENT;
 
@@ -890,7 +661,7 @@ static int msm_ioctl_gem_info(struct drm
 	if (args->pad)
 		return -EINVAL;
 
-	obj = drm_gem_object_lookup(dev, file, args->handle);
+	obj = drm_gem_object_lookup(file, args->handle);
 	if (!obj)
 		return -ENOENT;
 
@@ -904,6 +675,7 @@ static int msm_ioctl_gem_info(struct drm
 static int msm_ioctl_wait_fence(struct drm_device *dev, void *data,
 		struct drm_file *file)
 {
+	struct msm_drm_private *priv = dev->dev_private;
 	struct drm_msm_wait_fence *args = data;
 	ktime_t timeout = to_ktime(args->timeout);
 
@@ -912,7 +684,10 @@ static int msm_ioctl_wait_fence(struct d
 		return -EINVAL;
 	}
 
-	return msm_wait_fence(dev, args->fence, &timeout, true);
+	if (!priv->gpu)
+		return 0;
+
+	return msm_wait_fence(priv->gpu->fctx, args->fence, &timeout, true);
 }
 
 static const struct drm_ioctl_desc msm_ioctls[] = {
@@ -952,8 +727,6 @@ static struct drm_driver msm_driver = {
 				DRIVER_RENDER |
 				DRIVER_ATOMIC |
 				DRIVER_MODESET,
-	.load               = msm_load,
-	.unload             = msm_unload,
 	.open               = msm_open,
 	.preclose           = msm_preclose,
 	.lastclose          = msm_lastclose,
@@ -1053,12 +826,12 @@ static int add_components(struct device
 
 static int msm_drm_bind(struct device *dev)
 {
-	return drm_platform_init(&msm_driver, to_platform_device(dev));
+	return msm_drm_init(dev, &msm_driver);
 }
 
 static void msm_drm_unbind(struct device *dev)
 {
-	drm_put_dev(platform_get_drvdata(to_platform_device(dev)));
+	msm_drm_uninit(dev);
 }
 
 static const struct component_master_ops msm_drm_ops = {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/msm_drv.h linux-libre-4.7-gnu/drivers/gpu/drm/msm/msm_drv.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/msm_drv.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/msm_drv.h	2016-07-24 15:23:50.000000000 -0400
@@ -49,6 +49,8 @@ struct msm_mmu;
 struct msm_rd_state;
 struct msm_perf_state;
 struct msm_gem_submit;
+struct msm_fence_context;
+struct msm_fence_cb;
 
 #define NUM_DOMAINS 2    /* one for KMS, then one per gpu core (?) */
 
@@ -100,9 +102,6 @@ struct msm_drm_private {
 
 	struct drm_fb_helper *fbdev;
 
-	uint32_t next_fence, completed_fence;
-	wait_queue_head_t fence_event;
-
 	struct msm_rd_state *rd;
 	struct msm_perf_state *perf;
 
@@ -110,9 +109,7 @@ struct msm_drm_private {
 	struct list_head inactive_list;
 
 	struct workqueue_struct *wq;
-
-	/* callbacks deferred until bo is inactive: */
-	struct list_head fence_cbs;
+	struct workqueue_struct *atomic_wq;
 
 	/* crtcs pending async atomic updates: */
 	uint32_t pending_crtcs;
@@ -157,33 +154,14 @@ struct msm_format {
 	uint32_t pixel_format;
 };
 
-/* callback from wq once fence has passed: */
-struct msm_fence_cb {
-	struct work_struct work;
-	uint32_t fence;
-	void (*func)(struct msm_fence_cb *cb);
-};
-
-void __msm_fence_worker(struct work_struct *work);
-
-#define INIT_FENCE_CB(_cb, _func)  do {                     \
-		INIT_WORK(&(_cb)->work, __msm_fence_worker); \
-		(_cb)->func = _func;                         \
-	} while (0)
-
 int msm_atomic_check(struct drm_device *dev,
 		     struct drm_atomic_state *state);
 int msm_atomic_commit(struct drm_device *dev,
-		struct drm_atomic_state *state, bool async);
+		struct drm_atomic_state *state, bool nonblock);
 
 int msm_register_mmu(struct drm_device *dev, struct msm_mmu *mmu);
 
-int msm_wait_fence(struct drm_device *dev, uint32_t fence,
-		ktime_t *timeout, bool interruptible);
-int msm_queue_fence_cb(struct drm_device *dev,
-		struct msm_fence_cb *cb, uint32_t fence);
-void msm_update_fence(struct drm_device *dev, uint32_t fence);
-
+void msm_gem_submit_free(struct msm_gem_submit *submit);
 int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
 		struct drm_file *file);
 
@@ -213,13 +191,12 @@ int msm_gem_prime_pin(struct drm_gem_obj
 void msm_gem_prime_unpin(struct drm_gem_object *obj);
 void *msm_gem_vaddr_locked(struct drm_gem_object *obj);
 void *msm_gem_vaddr(struct drm_gem_object *obj);
-int msm_gem_queue_inactive_cb(struct drm_gem_object *obj,
-		struct msm_fence_cb *cb);
+int msm_gem_sync_object(struct drm_gem_object *obj,
+		struct msm_fence_context *fctx, bool exclusive);
 void msm_gem_move_to_active(struct drm_gem_object *obj,
-		struct msm_gpu *gpu, bool write, uint32_t fence);
+		struct msm_gpu *gpu, bool exclusive, struct fence *fence);
 void msm_gem_move_to_inactive(struct drm_gem_object *obj);
-int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op,
-		ktime_t *timeout);
+int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout);
 int msm_gem_cpu_fini(struct drm_gem_object *obj);
 void msm_gem_free_object(struct drm_gem_object *obj);
 int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file,
@@ -227,7 +204,7 @@ int msm_gem_new_handle(struct drm_device
 struct drm_gem_object *msm_gem_new(struct drm_device *dev,
 		uint32_t size, uint32_t flags);
 struct drm_gem_object *msm_gem_import(struct drm_device *dev,
-		uint32_t size, struct sg_table *sgt);
+		struct dma_buf *dmabuf, struct sg_table *sgt);
 
 int msm_framebuffer_prepare(struct drm_framebuffer *fb, int id);
 void msm_framebuffer_cleanup(struct drm_framebuffer *fb, int id);
@@ -303,12 +280,6 @@ u32 msm_readl(const void __iomem *addr);
 #define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
 #define VERB(fmt, ...) if (0) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
 
-static inline bool fence_completed(struct drm_device *dev, uint32_t fence)
-{
-	struct msm_drm_private *priv = dev->dev_private;
-	return priv->completed_fence >= fence;
-}
-
 static inline int align_pitch(int width, int bpp)
 {
 	int bytespp = (bpp + 7) / 8;
@@ -327,5 +298,20 @@ static inline int align_pitch(int width,
 /* for conditionally setting boolean flag(s): */
 #define COND(bool, val) ((bool) ? (val) : 0)
 
+static inline unsigned long timeout_to_jiffies(const ktime_t *timeout)
+{
+	ktime_t now = ktime_get();
+	unsigned long remaining_jiffies;
+
+	if (ktime_compare(*timeout, now) < 0) {
+		remaining_jiffies = 0;
+	} else {
+		ktime_t rem = ktime_sub(*timeout, now);
+		struct timespec ts = ktime_to_timespec(rem);
+		remaining_jiffies = timespec_to_jiffies(&ts);
+	}
+
+	return remaining_jiffies;
+}
 
 #endif /* __MSM_DRV_H__ */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/msm_fb.c linux-libre-4.7-gnu/drivers/gpu/drm/msm/msm_fb.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/msm_fb.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/msm_fb.c	2016-07-24 15:23:50.000000000 -0400
@@ -77,7 +77,7 @@ void msm_framebuffer_describe(struct drm
 
 	seq_printf(m, "fb: %dx%d@%4.4s (%2d, ID:%d)\n",
 			fb->width, fb->height, (char *)&fb->pixel_format,
-			fb->refcount.refcount.counter, fb->base.id);
+			drm_framebuffer_read_refcount(fb), fb->base.id);
 
 	for (i = 0; i < n; i++) {
 		seq_printf(m, "   %d: offset=%d pitch=%d, obj: ",
@@ -145,8 +145,7 @@ struct drm_framebuffer *msm_framebuffer_
 	int ret, i, n = drm_format_num_planes(mode_cmd->pixel_format);
 
 	for (i = 0; i < n; i++) {
-		bos[i] = drm_gem_object_lookup(dev, file,
-				mode_cmd->handles[i]);
+		bos[i] = drm_gem_object_lookup(file, mode_cmd->handles[i]);
 		if (!bos[i]) {
 			ret = -ENXIO;
 			goto out_unref;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/msm_fbdev.c linux-libre-4.7-gnu/drivers/gpu/drm/msm/msm_fbdev.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/msm_fbdev.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/msm_fbdev.c	2016-07-24 15:23:50.000000000 -0400
@@ -159,6 +159,10 @@ static int msm_fbdev_create(struct drm_f
 	dev->mode_config.fb_base = paddr;
 
 	fbi->screen_base = msm_gem_vaddr_locked(fbdev->bo);
+	if (IS_ERR(fbi->screen_base)) {
+		ret = PTR_ERR(fbi->screen_base);
+		goto fail_unlock;
+	}
 	fbi->screen_size = fbdev->bo->size;
 	fbi->fix.smem_start = paddr;
 	fbi->fix.smem_len = fbdev->bo->size;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/msm_fence.c linux-libre-4.7-gnu/drivers/gpu/drm/msm/msm_fence.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/msm_fence.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/msm_fence.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2013-2016 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/fence.h>
+
+#include "msm_drv.h"
+#include "msm_fence.h"
+
+
+struct msm_fence_context *
+msm_fence_context_alloc(struct drm_device *dev, const char *name)
+{
+	struct msm_fence_context *fctx;
+
+	fctx = kzalloc(sizeof(*fctx), GFP_KERNEL);
+	if (!fctx)
+		return ERR_PTR(-ENOMEM);
+
+	fctx->dev = dev;
+	fctx->name = name;
+	fctx->context = fence_context_alloc(1);
+	init_waitqueue_head(&fctx->event);
+	spin_lock_init(&fctx->spinlock);
+
+	return fctx;
+}
+
+void msm_fence_context_free(struct msm_fence_context *fctx)
+{
+	kfree(fctx);
+}
+
+static inline bool fence_completed(struct msm_fence_context *fctx, uint32_t fence)
+{
+	return (int32_t)(fctx->completed_fence - fence) >= 0;
+}
+
+/* legacy path for WAIT_FENCE ioctl: */
+int msm_wait_fence(struct msm_fence_context *fctx, uint32_t fence,
+		ktime_t *timeout, bool interruptible)
+{
+	int ret;
+
+	if (fence > fctx->last_fence) {
+		DRM_ERROR("%s: waiting on invalid fence: %u (of %u)\n",
+				fctx->name, fence, fctx->last_fence);
+		return -EINVAL;
+	}
+
+	if (!timeout) {
+		/* no-wait: */
+		ret = fence_completed(fctx, fence) ? 0 : -EBUSY;
+	} else {
+		unsigned long remaining_jiffies = timeout_to_jiffies(timeout);
+
+		if (interruptible)
+			ret = wait_event_interruptible_timeout(fctx->event,
+				fence_completed(fctx, fence),
+				remaining_jiffies);
+		else
+			ret = wait_event_timeout(fctx->event,
+				fence_completed(fctx, fence),
+				remaining_jiffies);
+
+		if (ret == 0) {
+			DBG("timeout waiting for fence: %u (completed: %u)",
+					fence, fctx->completed_fence);
+			ret = -ETIMEDOUT;
+		} else if (ret != -ERESTARTSYS) {
+			ret = 0;
+		}
+	}
+
+	return ret;
+}
+
+/* called from workqueue */
+void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence)
+{
+	spin_lock(&fctx->spinlock);
+	fctx->completed_fence = max(fence, fctx->completed_fence);
+	spin_unlock(&fctx->spinlock);
+
+	wake_up_all(&fctx->event);
+}
+
+struct msm_fence {
+	struct msm_fence_context *fctx;
+	struct fence base;
+};
+
+static inline struct msm_fence *to_msm_fence(struct fence *fence)
+{
+	return container_of(fence, struct msm_fence, base);
+}
+
+static const char *msm_fence_get_driver_name(struct fence *fence)
+{
+	return "msm";
+}
+
+static const char *msm_fence_get_timeline_name(struct fence *fence)
+{
+	struct msm_fence *f = to_msm_fence(fence);
+	return f->fctx->name;
+}
+
+static bool msm_fence_enable_signaling(struct fence *fence)
+{
+	return true;
+}
+
+static bool msm_fence_signaled(struct fence *fence)
+{
+	struct msm_fence *f = to_msm_fence(fence);
+	return fence_completed(f->fctx, f->base.seqno);
+}
+
+static void msm_fence_release(struct fence *fence)
+{
+	struct msm_fence *f = to_msm_fence(fence);
+	kfree_rcu(f, base.rcu);
+}
+
+static const struct fence_ops msm_fence_ops = {
+	.get_driver_name = msm_fence_get_driver_name,
+	.get_timeline_name = msm_fence_get_timeline_name,
+	.enable_signaling = msm_fence_enable_signaling,
+	.signaled = msm_fence_signaled,
+	.wait = fence_default_wait,
+	.release = msm_fence_release,
+};
+
+struct fence *
+msm_fence_alloc(struct msm_fence_context *fctx)
+{
+	struct msm_fence *f;
+
+	f = kzalloc(sizeof(*f), GFP_KERNEL);
+	if (!f)
+		return ERR_PTR(-ENOMEM);
+
+	f->fctx = fctx;
+
+	fence_init(&f->base, &msm_fence_ops, &fctx->spinlock,
+			fctx->context, ++fctx->last_fence);
+
+	return &f->base;
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/msm_fence.h linux-libre-4.7-gnu/drivers/gpu/drm/msm/msm_fence.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/msm_fence.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/msm_fence.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2013-2016 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MSM_FENCE_H__
+#define __MSM_FENCE_H__
+
+#include "msm_drv.h"
+
+struct msm_fence_context {
+	struct drm_device *dev;
+	const char *name;
+	unsigned context;
+	/* last_fence == completed_fence --> no pending work */
+	uint32_t last_fence;          /* last assigned fence */
+	uint32_t completed_fence;     /* last completed fence */
+	wait_queue_head_t event;
+	spinlock_t spinlock;
+};
+
+struct msm_fence_context * msm_fence_context_alloc(struct drm_device *dev,
+		const char *name);
+void msm_fence_context_free(struct msm_fence_context *fctx);
+
+int msm_wait_fence(struct msm_fence_context *fctx, uint32_t fence,
+		ktime_t *timeout, bool interruptible);
+int msm_queue_fence_cb(struct msm_fence_context *fctx,
+		struct msm_fence_cb *cb, uint32_t fence);
+void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence);
+
+struct fence * msm_fence_alloc(struct msm_fence_context *fctx);
+
+#endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/msm_gem.c linux-libre-4.7-gnu/drivers/gpu/drm/msm/msm_gem.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/msm_gem.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/msm_gem.c	2016-07-24 15:23:50.000000000 -0400
@@ -21,6 +21,7 @@
 #include <linux/pfn_t.h>
 
 #include "msm_drv.h"
+#include "msm_fence.h"
 #include "msm_gem.h"
 #include "msm_gpu.h"
 #include "msm_mmu.h"
@@ -373,7 +374,7 @@ int msm_gem_dumb_map_offset(struct drm_f
 	int ret = 0;
 
 	/* GEM does all our handle to object mapping */
-	obj = drm_gem_object_lookup(dev, file, handle);
+	obj = drm_gem_object_lookup(file, handle);
 	if (obj == NULL) {
 		ret = -ENOENT;
 		goto fail;
@@ -397,6 +398,8 @@ void *msm_gem_vaddr_locked(struct drm_ge
 			return ERR_CAST(pages);
 		msm_obj->vaddr = vmap(pages, obj->size >> PAGE_SHIFT,
 				VM_MAP, pgprot_writecombine(PAGE_KERNEL));
+		if (msm_obj->vaddr == NULL)
+			return ERR_PTR(-ENOMEM);
 	}
 	return msm_obj->vaddr;
 }
@@ -410,27 +413,62 @@ void *msm_gem_vaddr(struct drm_gem_objec
 	return ret;
 }
 
-/* setup callback for when bo is no longer busy..
- * TODO probably want to differentiate read vs write..
- */
-int msm_gem_queue_inactive_cb(struct drm_gem_object *obj,
-		struct msm_fence_cb *cb)
+/* must be called before _move_to_active().. */
+int msm_gem_sync_object(struct drm_gem_object *obj,
+		struct msm_fence_context *fctx, bool exclusive)
 {
 	struct msm_gem_object *msm_obj = to_msm_bo(obj);
-	uint32_t fence = msm_gem_fence(msm_obj,
-			MSM_PREP_READ | MSM_PREP_WRITE);
-	return msm_queue_fence_cb(obj->dev, cb, fence);
+	struct reservation_object_list *fobj;
+	struct fence *fence;
+	int i, ret;
+
+	if (!exclusive) {
+		/* NOTE: _reserve_shared() must happen before _add_shared_fence(),
+		 * which makes this a slightly strange place to call it.  OTOH this
+		 * is a convenient can-fail point to hook it in.  (And similar to
+		 * how etnaviv and nouveau handle this.)
+		 */
+		ret = reservation_object_reserve_shared(msm_obj->resv);
+		if (ret)
+			return ret;
+	}
+
+	fobj = reservation_object_get_list(msm_obj->resv);
+	if (!fobj || (fobj->shared_count == 0)) {
+		fence = reservation_object_get_excl(msm_obj->resv);
+		/* don't need to wait on our own fences, since ring is fifo */
+		if (fence && (fence->context != fctx->context)) {
+			ret = fence_wait(fence, true);
+			if (ret)
+				return ret;
+		}
+	}
+
+	if (!exclusive || !fobj)
+		return 0;
+
+	for (i = 0; i < fobj->shared_count; i++) {
+		fence = rcu_dereference_protected(fobj->shared[i],
+						reservation_object_held(msm_obj->resv));
+		if (fence->context != fctx->context) {
+			ret = fence_wait(fence, true);
+			if (ret)
+				return ret;
+		}
+	}
+
+	return 0;
 }
 
 void msm_gem_move_to_active(struct drm_gem_object *obj,
-		struct msm_gpu *gpu, bool write, uint32_t fence)
+		struct msm_gpu *gpu, bool exclusive, struct fence *fence)
 {
 	struct msm_gem_object *msm_obj = to_msm_bo(obj);
 	msm_obj->gpu = gpu;
-	if (write)
-		msm_obj->write_fence = fence;
+	if (exclusive)
+		reservation_object_add_excl_fence(msm_obj->resv, fence);
 	else
-		msm_obj->read_fence = fence;
+		reservation_object_add_shared_fence(msm_obj->resv, fence);
 	list_del_init(&msm_obj->mm_list);
 	list_add_tail(&msm_obj->mm_list, &gpu->active_list);
 }
@@ -444,30 +482,30 @@ void msm_gem_move_to_inactive(struct drm
 	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
 
 	msm_obj->gpu = NULL;
-	msm_obj->read_fence = 0;
-	msm_obj->write_fence = 0;
 	list_del_init(&msm_obj->mm_list);
 	list_add_tail(&msm_obj->mm_list, &priv->inactive_list);
 }
 
 int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout)
 {
-	struct drm_device *dev = obj->dev;
 	struct msm_gem_object *msm_obj = to_msm_bo(obj);
-	int ret = 0;
-
-	if (is_active(msm_obj)) {
-		uint32_t fence = msm_gem_fence(msm_obj, op);
+	bool write = !!(op & MSM_PREP_WRITE);
 
-		if (op & MSM_PREP_NOSYNC)
-			timeout = NULL;
+	if (op & MSM_PREP_NOSYNC) {
+		if (!reservation_object_test_signaled_rcu(msm_obj->resv, write))
+			return -EBUSY;
+	} else {
+		int ret;
 
-		ret = msm_wait_fence(dev, fence, timeout, true);
+		ret = reservation_object_wait_timeout_rcu(msm_obj->resv, write,
+				true, timeout_to_jiffies(timeout));
+		if (ret <= 0)
+			return ret == 0 ? -ETIMEDOUT : ret;
 	}
 
 	/* TODO cache maintenance */
 
-	return ret;
+	return 0;
 }
 
 int msm_gem_cpu_fini(struct drm_gem_object *obj)
@@ -477,18 +515,46 @@ int msm_gem_cpu_fini(struct drm_gem_obje
 }
 
 #ifdef CONFIG_DEBUG_FS
+static void describe_fence(struct fence *fence, const char *type,
+		struct seq_file *m)
+{
+	if (!fence_is_signaled(fence))
+		seq_printf(m, "\t%9s: %s %s seq %u\n", type,
+				fence->ops->get_driver_name(fence),
+				fence->ops->get_timeline_name(fence),
+				fence->seqno);
+}
+
 void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m)
 {
-	struct drm_device *dev = obj->dev;
 	struct msm_gem_object *msm_obj = to_msm_bo(obj);
+	struct reservation_object *robj = msm_obj->resv;
+	struct reservation_object_list *fobj;
+	struct fence *fence;
 	uint64_t off = drm_vma_node_start(&obj->vma_node);
 
-	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
-	seq_printf(m, "%08x: %c(r=%u,w=%u) %2d (%2d) %08llx %p %zu\n",
+	WARN_ON(!mutex_is_locked(&obj->dev->struct_mutex));
+
+	seq_printf(m, "%08x: %c %2d (%2d) %08llx %p %zu\n",
 			msm_obj->flags, is_active(msm_obj) ? 'A' : 'I',
-			msm_obj->read_fence, msm_obj->write_fence,
 			obj->name, obj->refcount.refcount.counter,
 			off, msm_obj->vaddr, obj->size);
+
+	rcu_read_lock();
+	fobj = rcu_dereference(robj->fence);
+	if (fobj) {
+		unsigned int i, shared_count = fobj->shared_count;
+
+		for (i = 0; i < shared_count; i++) {
+			fence = rcu_dereference(fobj->shared[i]);
+			describe_fence(fence, "Shared", m);
+		}
+	}
+
+	fence = rcu_dereference(robj->fence_excl);
+	if (fence)
+		describe_fence(fence, "Exclusive", m);
+	rcu_read_unlock();
 }
 
 void msm_gem_describe_objects(struct list_head *list, struct seq_file *m)
@@ -583,6 +649,7 @@ int msm_gem_new_handle(struct drm_device
 
 static int msm_gem_new_impl(struct drm_device *dev,
 		uint32_t size, uint32_t flags,
+		struct reservation_object *resv,
 		struct drm_gem_object **obj)
 {
 	struct msm_drm_private *priv = dev->dev_private;
@@ -622,8 +689,12 @@ static int msm_gem_new_impl(struct drm_d
 
 	msm_obj->flags = flags;
 
-	msm_obj->resv = &msm_obj->_resv;
-	reservation_object_init(msm_obj->resv);
+	if (resv) {
+		msm_obj->resv = resv;
+	} else {
+		msm_obj->resv = &msm_obj->_resv;
+		reservation_object_init(msm_obj->resv);
+	}
 
 	INIT_LIST_HEAD(&msm_obj->submit_entry);
 	list_add_tail(&msm_obj->mm_list, &priv->inactive_list);
@@ -643,7 +714,7 @@ struct drm_gem_object *msm_gem_new(struc
 
 	size = PAGE_ALIGN(size);
 
-	ret = msm_gem_new_impl(dev, size, flags, &obj);
+	ret = msm_gem_new_impl(dev, size, flags, NULL, &obj);
 	if (ret)
 		goto fail;
 
@@ -665,10 +736,11 @@ fail:
 }
 
 struct drm_gem_object *msm_gem_import(struct drm_device *dev,
-		uint32_t size, struct sg_table *sgt)
+		struct dma_buf *dmabuf, struct sg_table *sgt)
 {
 	struct msm_gem_object *msm_obj;
 	struct drm_gem_object *obj;
+	uint32_t size;
 	int ret, npages;
 
 	/* if we don't have IOMMU, don't bother pretending we can import: */
@@ -677,9 +749,9 @@ struct drm_gem_object *msm_gem_import(st
 		return ERR_PTR(-EINVAL);
 	}
 
-	size = PAGE_ALIGN(size);
+	size = PAGE_ALIGN(dmabuf->size);
 
-	ret = msm_gem_new_impl(dev, size, MSM_BO_WC, &obj);
+	ret = msm_gem_new_impl(dev, size, MSM_BO_WC, dmabuf->resv, &obj);
 	if (ret)
 		goto fail;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/msm_gem.h linux-libre-4.7-gnu/drivers/gpu/drm/msm/msm_gem.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/msm_gem.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/msm_gem.h	2016-07-24 15:23:50.000000000 -0400
@@ -39,7 +39,6 @@ struct msm_gem_object {
 	 */
 	struct list_head mm_list;
 	struct msm_gpu *gpu;     /* non-null if active */
-	uint32_t read_fence, write_fence;
 
 	/* Transiently in the process of submit ioctl, objects associated
 	 * with the submit are on submit->bo_list.. this only lasts for
@@ -73,19 +72,6 @@ static inline bool is_active(struct msm_
 	return msm_obj->gpu != NULL;
 }
 
-static inline uint32_t msm_gem_fence(struct msm_gem_object *msm_obj,
-		uint32_t op)
-{
-	uint32_t fence = 0;
-
-	if (op & MSM_PREP_READ)
-		fence = msm_obj->write_fence;
-	if (op & MSM_PREP_WRITE)
-		fence = max(fence, msm_obj->read_fence);
-
-	return fence;
-}
-
 #define MAX_CMDS 4
 
 /* Created per submit-ioctl, to track bo's and cmdstream bufs, etc,
@@ -99,8 +85,9 @@ struct msm_gem_submit {
 	struct list_head node;   /* node in gpu submit_list */
 	struct list_head bo_list;
 	struct ww_acquire_ctx ticket;
-	uint32_t fence;
-	bool valid;
+	struct fence *fence;
+	struct pid *pid;    /* submitting process */
+	bool valid;         /* true if no cmdstream patching needed */
 	unsigned int nr_cmds;
 	unsigned int nr_bos;
 	struct {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/msm_gem_prime.c linux-libre-4.7-gnu/drivers/gpu/drm/msm/msm_gem_prime.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/msm_gem_prime.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/msm_gem_prime.c	2016-07-24 15:23:50.000000000 -0400
@@ -55,7 +55,7 @@ int msm_gem_prime_mmap(struct drm_gem_ob
 struct drm_gem_object *msm_gem_prime_import_sg_table(struct drm_device *dev,
 		struct dma_buf_attachment *attach, struct sg_table *sg)
 {
-	return msm_gem_import(dev, attach->dmabuf->size, sg);
+	return msm_gem_import(dev, attach->dmabuf, sg);
 }
 
 int msm_gem_prime_pin(struct drm_gem_object *obj)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/msm_gem_submit.c linux-libre-4.7-gnu/drivers/gpu/drm/msm/msm_gem_submit.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/msm_gem_submit.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/msm_gem_submit.c	2016-07-24 15:23:50.000000000 -0400
@@ -24,15 +24,10 @@
  */
 
 /* make sure these don't conflict w/ MSM_SUBMIT_BO_x */
-#define BO_VALID    0x8000
+#define BO_VALID    0x8000   /* is current addr in cmdstream correct/valid? */
 #define BO_LOCKED   0x4000
 #define BO_PINNED   0x2000
 
-static inline void __user *to_user_ptr(u64 address)
-{
-	return (void __user *)(uintptr_t)address;
-}
-
 static struct msm_gem_submit *submit_create(struct drm_device *dev,
 		struct msm_gpu *gpu, int nr)
 {
@@ -40,21 +35,33 @@ static struct msm_gem_submit *submit_cre
 	int sz = sizeof(*submit) + (nr * sizeof(submit->bos[0]));
 
 	submit = kmalloc(sz, GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY);
-	if (submit) {
-		submit->dev = dev;
-		submit->gpu = gpu;
+	if (!submit)
+		return NULL;
 
-		/* initially, until copy_from_user() and bo lookup succeeds: */
-		submit->nr_bos = 0;
-		submit->nr_cmds = 0;
+	submit->dev = dev;
+	submit->gpu = gpu;
+	submit->fence = NULL;
+	submit->pid = get_pid(task_pid(current));
 
-		INIT_LIST_HEAD(&submit->bo_list);
-		ww_acquire_init(&submit->ticket, &reservation_ww_class);
-	}
+	/* initially, until copy_from_user() and bo lookup succeeds: */
+	submit->nr_bos = 0;
+	submit->nr_cmds = 0;
+
+	INIT_LIST_HEAD(&submit->node);
+	INIT_LIST_HEAD(&submit->bo_list);
+	ww_acquire_init(&submit->ticket, &reservation_ww_class);
 
 	return submit;
 }
 
+void msm_gem_submit_free(struct msm_gem_submit *submit)
+{
+	fence_put(submit->fence);
+	list_del(&submit->node);
+	put_pid(submit->pid);
+	kfree(submit);
+}
+
 static int submit_lookup_objects(struct msm_gem_submit *submit,
 		struct drm_msm_gem_submit *args, struct drm_file *file)
 {
@@ -68,7 +75,12 @@ static int submit_lookup_objects(struct
 		struct drm_gem_object *obj;
 		struct msm_gem_object *msm_obj;
 		void __user *userptr =
-			to_user_ptr(args->bos + (i * sizeof(submit_bo)));
+			u64_to_user_ptr(args->bos + (i * sizeof(submit_bo)));
+
+		/* make sure we don't have garbage flags, in case we hit
+		 * error path before flags is initialized:
+		 */
+		submit->bos[i].flags = 0;
 
 		ret = copy_from_user(&submit_bo, userptr, sizeof(submit_bo));
 		if (ret) {
@@ -136,16 +148,13 @@ static void submit_unlock_unpin_bo(struc
 }
 
 /* This is where we make sure all the bo's are reserved and pin'd: */
-static int submit_validate_objects(struct msm_gem_submit *submit)
+static int submit_lock_objects(struct msm_gem_submit *submit)
 {
 	int contended, slow_locked = -1, i, ret = 0;
 
 retry:
-	submit->valid = true;
-
 	for (i = 0; i < submit->nr_bos; i++) {
 		struct msm_gem_object *msm_obj = submit->bos[i].obj;
-		uint32_t iova;
 
 		if (slow_locked == i)
 			slow_locked = -1;
@@ -159,30 +168,6 @@ retry:
 				goto fail;
 			submit->bos[i].flags |= BO_LOCKED;
 		}
-
-
-		/* if locking succeeded, pin bo: */
-		ret = msm_gem_get_iova_locked(&msm_obj->base,
-				submit->gpu->id, &iova);
-
-		/* this would break the logic in the fail path.. there is no
-		 * reason for this to happen, but just to be on the safe side
-		 * let's notice if this starts happening in the future:
-		 */
-		WARN_ON(ret == -EDEADLK);
-
-		if (ret)
-			goto fail;
-
-		submit->bos[i].flags |= BO_PINNED;
-
-		if (iova == submit->bos[i].iova) {
-			submit->bos[i].flags |= BO_VALID;
-		} else {
-			submit->bos[i].iova = iova;
-			submit->bos[i].flags &= ~BO_VALID;
-			submit->valid = false;
-		}
 	}
 
 	ww_acquire_done(&submit->ticket);
@@ -211,6 +196,54 @@ fail:
 	return ret;
 }
 
+static int submit_fence_sync(struct msm_gem_submit *submit)
+{
+	int i, ret = 0;
+
+	for (i = 0; i < submit->nr_bos; i++) {
+		struct msm_gem_object *msm_obj = submit->bos[i].obj;
+		bool write = submit->bos[i].flags & MSM_SUBMIT_BO_WRITE;
+
+		ret = msm_gem_sync_object(&msm_obj->base, submit->gpu->fctx, write);
+		if (ret)
+			break;
+	}
+
+	return ret;
+}
+
+static int submit_pin_objects(struct msm_gem_submit *submit)
+{
+	int i, ret = 0;
+
+	submit->valid = true;
+
+	for (i = 0; i < submit->nr_bos; i++) {
+		struct msm_gem_object *msm_obj = submit->bos[i].obj;
+		uint32_t iova;
+
+		/* if locking succeeded, pin bo: */
+		ret = msm_gem_get_iova_locked(&msm_obj->base,
+				submit->gpu->id, &iova);
+
+		if (ret)
+			break;
+
+		submit->bos[i].flags |= BO_PINNED;
+
+		if (iova == submit->bos[i].iova) {
+			submit->bos[i].flags |= BO_VALID;
+		} else {
+			submit->bos[i].iova = iova;
+			/* iova changed, so address in cmdstream is not valid: */
+			submit->bos[i].flags &= ~BO_VALID;
+			submit->valid = false;
+		}
+	}
+
+	return ret;
+}
+
 static int submit_bo(struct msm_gem_submit *submit, uint32_t idx,
 		struct msm_gem_object **obj, uint32_t *iova, bool *valid)
 {
@@ -257,7 +290,7 @@ static int submit_reloc(struct msm_gem_s
 	for (i = 0; i < nr_relocs; i++) {
 		struct drm_msm_gem_submit_reloc submit_reloc;
 		void __user *userptr =
-			to_user_ptr(relocs + (i * sizeof(submit_reloc)));
+			u64_to_user_ptr(relocs + (i * sizeof(submit_reloc)));
 		uint32_t iova, off;
 		bool valid;
 
@@ -302,7 +335,7 @@ static int submit_reloc(struct msm_gem_s
 	return 0;
 }
 
-static void submit_cleanup(struct msm_gem_submit *submit, bool fail)
+static void submit_cleanup(struct msm_gem_submit *submit)
 {
 	unsigned i;
 
@@ -349,14 +382,22 @@ int msm_ioctl_gem_submit(struct drm_devi
 	if (ret)
 		goto out;
 
-	ret = submit_validate_objects(submit);
+	ret = submit_lock_objects(submit);
+	if (ret)
+		goto out;
+
+	ret = submit_fence_sync(submit);
+	if (ret)
+		goto out;
+
+	ret = submit_pin_objects(submit);
 	if (ret)
 		goto out;
 
 	for (i = 0; i < args->nr_cmds; i++) {
 		struct drm_msm_gem_submit_cmd submit_cmd;
 		void __user *userptr =
-			to_user_ptr(args->cmds + (i * sizeof(submit_cmd)));
+			u64_to_user_ptr(args->cmds + (i * sizeof(submit_cmd)));
 		struct msm_gem_object *msm_obj;
 		uint32_t iova;
 
@@ -415,10 +456,12 @@ int msm_ioctl_gem_submit(struct drm_devi
 
 	ret = msm_gpu_submit(gpu, submit, ctx);
 
-	args->fence = submit->fence;
+	args->fence = submit->fence->seqno;
 
 out:
-	submit_cleanup(submit, !!ret);
+	submit_cleanup(submit);
+	if (ret)
+		msm_gem_submit_free(submit);
 	mutex_unlock(&dev->struct_mutex);
 	return ret;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/msm_gpu.c linux-libre-4.7-gnu/drivers/gpu/drm/msm/msm_gpu.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/msm_gpu.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/msm_gpu.c	2016-07-24 15:23:50.000000000 -0400
@@ -18,6 +18,7 @@
 #include "msm_gpu.h"
 #include "msm_gem.h"
 #include "msm_mmu.h"
+#include "msm_fence.h"
 
 
 /*
@@ -265,22 +266,38 @@ static void inactive_start(struct msm_gp
  * Hangcheck detection for locked gpu:
  */
 
-static void retire_submits(struct msm_gpu *gpu, uint32_t fence);
+static void retire_submits(struct msm_gpu *gpu);
 
 static void recover_worker(struct work_struct *work)
 {
 	struct msm_gpu *gpu = container_of(work, struct msm_gpu, recover_work);
 	struct drm_device *dev = gpu->dev;
+	struct msm_gem_submit *submit;
+	uint32_t fence = gpu->funcs->last_fence(gpu);
 
-	dev_err(dev->dev, "%s: hangcheck recover!\n", gpu->name);
+	msm_update_fence(gpu->fctx, fence + 1);
 
 	mutex_lock(&dev->struct_mutex);
-	if (msm_gpu_active(gpu)) {
-		struct msm_gem_submit *submit;
-		uint32_t fence = gpu->funcs->last_fence(gpu);
 
+	dev_err(dev->dev, "%s: hangcheck recover!\n", gpu->name);
+	list_for_each_entry(submit, &gpu->submit_list, node) {
+		if (submit->fence->seqno == (fence + 1)) {
+			struct task_struct *task;
+
+			rcu_read_lock();
+			task = pid_task(submit->pid, PIDTYPE_PID);
+			if (task) {
+				dev_err(dev->dev, "%s: offending task: %s\n",
+						gpu->name, task->comm);
+			}
+			rcu_read_unlock();
+			break;
+		}
+	}
+
+	if (msm_gpu_active(gpu)) {
 		/* retire completed submits, plus the one that hung: */
-		retire_submits(gpu, fence + 1);
+		retire_submits(gpu);
 
 		inactive_cancel(gpu);
 		gpu->funcs->recover(gpu);
@@ -290,6 +307,7 @@ static void recover_worker(struct work_s
 			gpu->funcs->submit(gpu, submit, NULL);
 		}
 	}
+
 	mutex_unlock(&dev->struct_mutex);
 
 	msm_gpu_retire(gpu);
@@ -312,7 +330,7 @@ static void hangcheck_handler(unsigned l
 	if (fence != gpu->hangcheck_fence) {
 		/* some progress has been made.. ya! */
 		gpu->hangcheck_fence = fence;
-	} else if (fence < gpu->submitted_fence) {
+	} else if (fence < gpu->fctx->last_fence) {
 		/* no progress and not done.. hung! */
 		gpu->hangcheck_fence = fence;
 		dev_err(dev->dev, "%s: hangcheck detected gpu lockup!\n",
@@ -320,12 +338,12 @@ static void hangcheck_handler(unsigned l
 		dev_err(dev->dev, "%s:     completed fence: %u\n",
 				gpu->name, fence);
 		dev_err(dev->dev, "%s:     submitted fence: %u\n",
-				gpu->name, gpu->submitted_fence);
+				gpu->name, gpu->fctx->last_fence);
 		queue_work(priv->wq, &gpu->recover_work);
 	}
 
 	/* if still more pending work, reset the hangcheck timer: */
-	if (gpu->submitted_fence > gpu->hangcheck_fence)
+	if (gpu->fctx->last_fence > gpu->hangcheck_fence)
 		hangcheck_timer_reset(gpu);
 
 	/* workaround for missing irq: */
@@ -431,7 +449,22 @@ out:
  * Cmdstream submission/retirement:
  */
 
-static void retire_submits(struct msm_gpu *gpu, uint32_t fence)
+static void retire_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
+{
+	int i;
+
+	for (i = 0; i < submit->nr_bos; i++) {
+		struct msm_gem_object *msm_obj = submit->bos[i].obj;
+		/* move to inactive: */
+		msm_gem_move_to_inactive(&msm_obj->base);
+		msm_gem_put_iova(&msm_obj->base, gpu->id);
+		drm_gem_object_unreference(&msm_obj->base);
+	}
+
+	msm_gem_submit_free(submit);
+}
+
+static void retire_submits(struct msm_gpu *gpu)
 {
 	struct drm_device *dev = gpu->dev;
 
@@ -443,9 +476,8 @@ static void retire_submits(struct msm_gp
 		submit = list_first_entry(&gpu->submit_list,
 				struct msm_gem_submit, node);
 
-		if (submit->fence <= fence) {
-			list_del(&submit->node);
-			kfree(submit);
+		if (fence_is_signaled(submit->fence)) {
+			retire_submit(gpu, submit);
 		} else {
 			break;
 		}
@@ -458,29 +490,10 @@ static void retire_worker(struct work_st
 	struct drm_device *dev = gpu->dev;
 	uint32_t fence = gpu->funcs->last_fence(gpu);
 
-	msm_update_fence(gpu->dev, fence);
+	msm_update_fence(gpu->fctx, fence);
 
 	mutex_lock(&dev->struct_mutex);
-
-	retire_submits(gpu, fence);
-
-	while (!list_empty(&gpu->active_list)) {
-		struct msm_gem_object *obj;
-
-		obj = list_first_entry(&gpu->active_list,
-				struct msm_gem_object, mm_list);
-
-		if ((obj->read_fence <= fence) &&
-				(obj->write_fence <= fence)) {
-			/* move to inactive: */
-			msm_gem_move_to_inactive(&obj->base);
-			msm_gem_put_iova(&obj->base, gpu->id);
-			drm_gem_object_unreference(&obj->base);
-		} else {
-			break;
-		}
-	}
-
+	retire_submits(gpu);
 	mutex_unlock(&dev->struct_mutex);
 
 	if (!msm_gpu_active(gpu))
@@ -505,9 +518,12 @@ int msm_gpu_submit(struct msm_gpu *gpu,
 
 	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
 
-	submit->fence = ++priv->next_fence;
-
-	gpu->submitted_fence = submit->fence;
+	submit->fence = msm_fence_alloc(gpu->fctx);
+	if (IS_ERR(submit->fence)) {
+		ret = PTR_ERR(submit->fence);
+		submit->fence = NULL;
+		return ret;
+	}
 
 	inactive_cancel(gpu);
 
@@ -515,40 +531,34 @@ int msm_gpu_submit(struct msm_gpu *gpu,
 
 	msm_rd_dump_submit(submit);
 
-	gpu->submitted_fence = submit->fence;
-
 	update_sw_cntrs(gpu);
 
 	for (i = 0; i < submit->nr_bos; i++) {
 		struct msm_gem_object *msm_obj = submit->bos[i].obj;
+		uint32_t iova;
 
 		/* can't happen yet.. but when we add 2d support we'll have
 		 * to deal w/ cross-ring synchronization:
 		 */
 		WARN_ON(is_active(msm_obj) && (msm_obj->gpu != gpu));
 
-		if (!is_active(msm_obj)) {
-			uint32_t iova;
-
-			/* ring takes a reference to the bo and iova: */
-			drm_gem_object_reference(&msm_obj->base);
-			msm_gem_get_iova_locked(&msm_obj->base,
-					submit->gpu->id, &iova);
-		}
-
-		if (submit->bos[i].flags & MSM_SUBMIT_BO_READ)
-			msm_gem_move_to_active(&msm_obj->base, gpu, false, submit->fence);
+		/* submit takes a reference to the bo and iova until retired: */
+		drm_gem_object_reference(&msm_obj->base);
+		msm_gem_get_iova_locked(&msm_obj->base,
+				submit->gpu->id, &iova);
 
 		if (submit->bos[i].flags & MSM_SUBMIT_BO_WRITE)
 			msm_gem_move_to_active(&msm_obj->base, gpu, true, submit->fence);
+		else if (submit->bos[i].flags & MSM_SUBMIT_BO_READ)
+			msm_gem_move_to_active(&msm_obj->base, gpu, false, submit->fence);
 	}
 
-	ret = gpu->funcs->submit(gpu, submit, ctx);
+	gpu->funcs->submit(gpu, submit, ctx);
 	priv->lastctx = ctx;
 
 	hangcheck_timer_reset(gpu);
 
-	return ret;
+	return 0;
 }
 
 /*
@@ -580,6 +590,12 @@ int msm_gpu_init(struct drm_device *drm,
 	gpu->funcs = funcs;
 	gpu->name = name;
 	gpu->inactive = true;
+	gpu->fctx = msm_fence_context_alloc(drm, name);
+	if (IS_ERR(gpu->fctx)) {
+		ret = PTR_ERR(gpu->fctx);
+		gpu->fctx = NULL;
+		goto fail;
+	}
 
 	INIT_LIST_HEAD(&gpu->active_list);
 	INIT_WORK(&gpu->retire_work, retire_worker);
@@ -700,4 +716,7 @@ void msm_gpu_cleanup(struct msm_gpu *gpu
 
 	if (gpu->mmu)
 		gpu->mmu->funcs->destroy(gpu->mmu);
+
+	if (gpu->fctx)
+		msm_fence_context_free(gpu->fctx);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/msm_gpu.h linux-libre-4.7-gnu/drivers/gpu/drm/msm/msm_gpu.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/msm_gpu.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/msm_gpu.h	2016-07-24 15:23:50.000000000 -0400
@@ -22,6 +22,7 @@
 #include <linux/regulator/consumer.h>
 
 #include "msm_drv.h"
+#include "msm_fence.h"
 #include "msm_ringbuffer.h"
 
 struct msm_gem_submit;
@@ -46,7 +47,7 @@ struct msm_gpu_funcs {
 	int (*hw_init)(struct msm_gpu *gpu);
 	int (*pm_suspend)(struct msm_gpu *gpu);
 	int (*pm_resume)(struct msm_gpu *gpu);
-	int (*submit)(struct msm_gpu *gpu, struct msm_gem_submit *submit,
+	void (*submit)(struct msm_gpu *gpu, struct msm_gem_submit *submit,
 			struct msm_file_private *ctx);
 	void (*flush)(struct msm_gpu *gpu);
 	void (*idle)(struct msm_gpu *gpu);
@@ -77,13 +78,15 @@ struct msm_gpu {
 	const struct msm_gpu_perfcntr *perfcntrs;
 	uint32_t num_perfcntrs;
 
+	/* ringbuffer: */
 	struct msm_ringbuffer *rb;
 	uint32_t rb_iova;
 
 	/* list of GEM active objects: */
 	struct list_head active_list;
 
-	uint32_t submitted_fence;
+	/* fencing: */
+	struct msm_fence_context *fctx;
 
 	/* is gpu powered/active? */
 	int active_cnt;
@@ -125,7 +128,7 @@ struct msm_gpu {
 
 static inline bool msm_gpu_active(struct msm_gpu *gpu)
 {
-	return gpu->submitted_fence > gpu->funcs->last_fence(gpu);
+	return gpu->fctx->last_fence > gpu->funcs->last_fence(gpu);
 }
 
 /* Perf-Counters:
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/msm_rd.c linux-libre-4.7-gnu/drivers/gpu/drm/msm/msm_rd.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/msm_rd.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/msm_rd.c	2016-07-24 15:23:50.000000000 -0400
@@ -296,7 +296,7 @@ void msm_rd_dump_submit(struct msm_gem_s
 
 	n = snprintf(msg, sizeof(msg), "%.*s/%d: fence=%u",
 			TASK_COMM_LEN, current->comm, task_pid_nr(current),
-			submit->fence);
+			submit->fence->seqno);
 
 	rd_write_section(rd, RD_CMD, msg, ALIGN(n, 4));
 
@@ -312,6 +312,9 @@ void msm_rd_dump_submit(struct msm_gem_s
 		struct msm_gem_object *obj = submit->bos[idx].obj;
 		const char *buf = msm_gem_vaddr_locked(&obj->base);
 
+		if (IS_ERR(buf))
+			continue;
+
 		buf += iova - submit->bos[idx].iova;
 
 		rd_write_section(rd, RD_GPUADDR,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/msm/msm_ringbuffer.c linux-libre-4.7-gnu/drivers/gpu/drm/msm/msm_ringbuffer.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/msm/msm_ringbuffer.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/msm/msm_ringbuffer.c	2016-07-24 15:23:50.000000000 -0400
@@ -40,6 +40,10 @@ struct msm_ringbuffer *msm_ringbuffer_ne
 	}
 
 	ring->start = msm_gem_vaddr_locked(ring->bo);
+	if (IS_ERR(ring->start)) {
+		ret = PTR_ERR(ring->start);
+		goto fail;
+	}
 	ring->end   = ring->start + (size / 4);
 	ring->cur   = ring->start;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/dispnv04/arb.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/dispnv04/arb.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/dispnv04/arb.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/dispnv04/arb.c	2016-07-24 15:23:50.000000000 -0400
@@ -23,7 +23,7 @@
 
 #include <drm/drmP.h>
 
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_reg.h"
 #include "hw.h"
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/dispnv04/crtc.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/dispnv04/crtc.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/dispnv04/crtc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/dispnv04/crtc.c	2016-07-24 15:23:50.000000000 -0400
@@ -28,8 +28,9 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_plane_helper.h>
 
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_reg.h"
+#include "nouveau_ttm.h"
 #include "nouveau_bo.h"
 #include "nouveau_gem.h"
 #include "nouveau_encoder.h"
@@ -995,7 +996,7 @@ nv04_crtc_cursor_set(struct drm_crtc *cr
 	if (width != 64 || height != 64)
 		return -EINVAL;
 
-	gem = drm_gem_object_lookup(dev, file_priv, buffer_handle);
+	gem = drm_gem_object_lookup(file_priv, buffer_handle);
 	if (!gem)
 		return -ENOENT;
 	cursor = nouveau_gem_object(gem);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/dispnv04/cursor.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/dispnv04/cursor.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/dispnv04/cursor.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/dispnv04/cursor.c	2016-07-24 15:23:50.000000000 -0400
@@ -1,6 +1,6 @@
 #include <drm/drmP.h>
 #include <drm/drm_mode.h>
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_reg.h"
 #include "nouveau_crtc.h"
 #include "hw.h"
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/dispnv04/dac.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/dispnv04/dac.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/dispnv04/dac.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/dispnv04/dac.c	2016-07-24 15:23:50.000000000 -0400
@@ -27,7 +27,7 @@
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
 
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_encoder.h"
 #include "nouveau_connector.h"
 #include "nouveau_crtc.h"
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/dispnv04/dfp.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/dispnv04/dfp.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/dispnv04/dfp.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/dispnv04/dfp.c	2016-07-24 15:23:50.000000000 -0400
@@ -27,7 +27,7 @@
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
 
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_reg.h"
 #include "nouveau_encoder.h"
 #include "nouveau_connector.h"
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/dispnv04/disp.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/dispnv04/disp.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/dispnv04/disp.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/dispnv04/disp.c	2016-07-24 15:23:50.000000000 -0400
@@ -25,7 +25,7 @@
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
 
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_reg.h"
 #include "hw.h"
 #include "nouveau_encoder.h"
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/dispnv04/disp.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/dispnv04/disp.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/dispnv04/disp.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/dispnv04/disp.h	2016-07-24 15:23:50.000000000 -0400
@@ -1,6 +1,6 @@
 #ifndef __NV04_DISPLAY_H__
 #define __NV04_DISPLAY_H__
-
+#include <subdev/bios.h>
 #include <subdev/bios/pll.h>
 
 #include "nouveau_display.h"
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/dispnv04/hw.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/dispnv04/hw.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/dispnv04/hw.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/dispnv04/hw.c	2016-07-24 15:23:50.000000000 -0400
@@ -23,7 +23,7 @@
  */
 
 #include <drm/drmP.h>
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "hw.h"
 
 #include <subdev/bios/pll.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/dispnv04/overlay.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/dispnv04/overlay.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/dispnv04/overlay.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/dispnv04/overlay.c	2016-07-24 15:23:50.000000000 -0400
@@ -27,7 +27,7 @@
 #include <drm/drm_crtc.h>
 #include <drm/drm_fourcc.h>
 
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 
 #include "nouveau_bo.h"
 #include "nouveau_connector.h"
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/dispnv04/tvmodesnv17.c	2016-07-24 15:23:50.000000000 -0400
@@ -26,7 +26,7 @@
 
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_encoder.h"
 #include "nouveau_crtc.h"
 #include "hw.h"
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c	2016-07-24 15:23:50.000000000 -0400
@@ -25,7 +25,7 @@
  */
 
 #include <drm/drmP.h>
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_reg.h"
 #include "nouveau_encoder.h"
 #include "nouveau_connector.h"
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c	2016-07-24 15:23:50.000000000 -0400
@@ -26,7 +26,7 @@
 
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_reg.h"
 #include "nouveau_encoder.h"
 #include "nouveau_connector.h"
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/include/nvkm/core/device.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/include/nvkm/core/device.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/include/nvkm/core/device.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/include/nvkm/core/device.h	2016-07-24 15:23:50.000000000 -0400
@@ -7,6 +7,7 @@ enum nvkm_devidx {
 	NVKM_SUBDEV_PCI,
 	NVKM_SUBDEV_VBIOS,
 	NVKM_SUBDEV_DEVINIT,
+	NVKM_SUBDEV_TOP,
 	NVKM_SUBDEV_IBUS,
 	NVKM_SUBDEV_GPIO,
 	NVKM_SUBDEV_I2C,
@@ -15,9 +16,9 @@ enum nvkm_devidx {
 	NVKM_SUBDEV_MC,
 	NVKM_SUBDEV_BUS,
 	NVKM_SUBDEV_TIMER,
+	NVKM_SUBDEV_INSTMEM,
 	NVKM_SUBDEV_FB,
 	NVKM_SUBDEV_LTC,
-	NVKM_SUBDEV_INSTMEM,
 	NVKM_SUBDEV_MMU,
 	NVKM_SUBDEV_BAR,
 	NVKM_SUBDEV_PMU,
@@ -131,6 +132,7 @@ struct nvkm_device {
 	struct nvkm_secboot *secboot;
 	struct nvkm_therm *therm;
 	struct nvkm_timer *timer;
+	struct nvkm_top *top;
 	struct nvkm_volt *volt;
 
 	struct nvkm_engine *bsp;
@@ -200,6 +202,7 @@ struct nvkm_device_chip {
 	int (*secboot )(struct nvkm_device *, int idx, struct nvkm_secboot **);
 	int (*therm   )(struct nvkm_device *, int idx, struct nvkm_therm **);
 	int (*timer   )(struct nvkm_device *, int idx, struct nvkm_timer **);
+	int (*top     )(struct nvkm_device *, int idx, struct nvkm_top **);
 	int (*volt    )(struct nvkm_device *, int idx, struct nvkm_volt **);
 
 	int (*bsp     )(struct nvkm_device *, int idx, struct nvkm_engine **);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h	2016-07-24 15:23:50.000000000 -0400
@@ -38,11 +38,9 @@ struct nvkm_engine_func {
 };
 
 int nvkm_engine_ctor(const struct nvkm_engine_func *, struct nvkm_device *,
-		     int index, u32 pmc_enable, bool enable,
-		     struct nvkm_engine *);
+		     int index, bool enable, struct nvkm_engine *);
 int nvkm_engine_new_(const struct nvkm_engine_func *, struct nvkm_device *,
-		     int index, u32 pmc_enable, bool enable,
-		     struct nvkm_engine **);
+		     int index, bool enable, struct nvkm_engine **);
 struct nvkm_engine *nvkm_engine_ref(struct nvkm_engine *);
 void nvkm_engine_unref(struct nvkm_engine **);
 void nvkm_engine_tile(struct nvkm_engine *, int region);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h	2016-07-24 15:23:50.000000000 -0400
@@ -6,7 +6,6 @@ struct nvkm_subdev {
 	const struct nvkm_subdev_func *func;
 	struct nvkm_device *device;
 	enum nvkm_devidx index;
-	u32 pmc_enable;
 	struct mutex mutex;
 	u32 debug;
 
@@ -24,7 +23,7 @@ struct nvkm_subdev_func {
 
 extern const char *nvkm_subdev_name[NVKM_SUBDEV_NR];
 void nvkm_subdev_ctor(const struct nvkm_subdev_func *, struct nvkm_device *,
-		      int index, u32 pmc_enable, struct nvkm_subdev *);
+		      int index, struct nvkm_subdev *);
 void nvkm_subdev_del(struct nvkm_subdev **);
 int  nvkm_subdev_preinit(struct nvkm_subdev *);
 int  nvkm_subdev_init(struct nvkm_subdev *);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h	2016-07-24 15:23:50.000000000 -0400
@@ -40,7 +40,6 @@ struct nvkm_falcon_func {
 		u32 *data;
 		u32  size;
 	} data;
-	u32 pmc_enable;
 	void (*init)(struct nvkm_falcon *);
 	void (*intr)(struct nvkm_falcon *, struct nvkm_fifo_chan *);
 	struct nvkm_sclass sclass[];
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/include/nvkm/engine/xtensa.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/include/nvkm/engine/xtensa.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/include/nvkm/engine/xtensa.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/include/nvkm/engine/xtensa.h	2016-07-24 15:23:50.000000000 -0400
@@ -15,7 +15,6 @@ int nvkm_xtensa_new_(const struct nvkm_x
 		     int index, bool enable, u32 addr, struct nvkm_engine **);
 
 struct nvkm_xtensa_func {
-	u32 pmc_enable;
 	u32 fifo_val;
 	u32 unkd28;
 	struct nvkm_sclass sclass[];
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/disp.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/disp.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/disp.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/disp.h	2016-07-24 15:23:50.000000000 -0400
@@ -25,7 +25,8 @@ u16 nvbios_outp_match(struct nvkm_bios *
 		      u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_outp *);
 
 struct nvbios_ocfg {
-	u16 match;
+	u8  proto;
+	u8  flags;
 	u16 clkcmp[2];
 };
 
@@ -33,7 +34,7 @@ u16 nvbios_ocfg_entry(struct nvkm_bios *
 		      u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
 u16 nvbios_ocfg_parse(struct nvkm_bios *, u16 outp, u8 idx,
 		      u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_ocfg *);
-u16 nvbios_ocfg_match(struct nvkm_bios *, u16 outp, u16 type,
+u16 nvbios_ocfg_match(struct nvkm_bios *, u16 outp, u8 proto, u8 flags,
 		      u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_ocfg *);
 u16 nvbios_oclk_match(struct nvkm_bios *, u16 cmp, u32 khz);
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/devinit.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/devinit.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/devinit.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/devinit.h	2016-07-24 15:23:50.000000000 -0400
@@ -7,6 +7,7 @@ struct nvkm_devinit {
 	const struct nvkm_devinit_func *func;
 	struct nvkm_subdev subdev;
 	bool post;
+	bool force_post;
 };
 
 u32 nvkm_devinit_mmio(struct nvkm_devinit *, u32 addr);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h	2016-07-24 15:23:50.000000000 -0400
@@ -55,6 +55,9 @@ struct nvkm_fb {
 		struct nvkm_fb_tile region[16];
 		int regions;
 	} tile;
+
+	struct nvkm_memory *mmu_rd;
+	struct nvkm_memory *mmu_wr;
 };
 
 bool nvkm_fb_memtype_valid(struct nvkm_fb *, u32 memtype);
@@ -87,6 +90,7 @@ int gf100_fb_new(struct nvkm_device *, i
 int gk104_fb_new(struct nvkm_device *, int, struct nvkm_fb **);
 int gk20a_fb_new(struct nvkm_device *, int, struct nvkm_fb **);
 int gm107_fb_new(struct nvkm_device *, int, struct nvkm_fb **);
+int gm200_fb_new(struct nvkm_device *, int, struct nvkm_fb **);
 
 #include <subdev/bios.h>
 #include <subdev/bios/ramcfg.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/iccsense.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/iccsense.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/iccsense.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/iccsense.h	2016-07-24 15:23:50.000000000 -0400
@@ -3,15 +3,13 @@
 
 #include <core/subdev.h>
 
-struct nkvm_iccsense_rail;
 struct nvkm_iccsense {
 	struct nvkm_subdev subdev;
-	u8 rail_count;
 	bool data_valid;
-	struct nvkm_iccsense_rail *rails;
+	struct list_head sensors;
+	struct list_head rails;
 };
 
 int gf100_iccsense_new(struct nvkm_device *, int index, struct nvkm_iccsense **);
-int nvkm_iccsense_read(struct nvkm_iccsense *iccsense, u8 idx);
 int nvkm_iccsense_read_all(struct nvkm_iccsense *iccsense);
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/mc.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/mc.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/mc.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/mc.h	2016-07-24 15:23:50.000000000 -0400
@@ -10,12 +10,18 @@ struct nvkm_mc {
 void nvkm_mc_intr(struct nvkm_mc *, bool *handled);
 void nvkm_mc_intr_unarm(struct nvkm_mc *);
 void nvkm_mc_intr_rearm(struct nvkm_mc *);
+void nvkm_mc_reset(struct nvkm_mc *, enum nvkm_devidx);
 void nvkm_mc_unk260(struct nvkm_mc *, u32 data);
 
 int nv04_mc_new(struct nvkm_device *, int, struct nvkm_mc **);
+int nv11_mc_new(struct nvkm_device *, int, struct nvkm_mc **);
+int nv17_mc_new(struct nvkm_device *, int, struct nvkm_mc **);
 int nv44_mc_new(struct nvkm_device *, int, struct nvkm_mc **);
 int nv50_mc_new(struct nvkm_device *, int, struct nvkm_mc **);
+int g84_mc_new(struct nvkm_device *, int, struct nvkm_mc **);
 int g98_mc_new(struct nvkm_device *, int, struct nvkm_mc **);
+int gt215_mc_new(struct nvkm_device *, int, struct nvkm_mc **);
 int gf100_mc_new(struct nvkm_device *, int, struct nvkm_mc **);
+int gk104_mc_new(struct nvkm_device *, int, struct nvkm_mc **);
 int gk20a_mc_new(struct nvkm_device *, int, struct nvkm_mc **);
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/top.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/top.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/top.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/top.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,17 @@
+#ifndef __NVKM_TOP_H__
+#define __NVKM_TOP_H__
+#include <core/subdev.h>
+
+struct nvkm_top {
+	const struct nvkm_top_func *func;
+	struct nvkm_subdev subdev;
+	struct list_head device;
+};
+
+u32 nvkm_top_reset(struct nvkm_top *, enum nvkm_devidx);
+u32 nvkm_top_intr(struct nvkm_top *, u32 intr, u64 *subdevs);
+enum nvkm_devidx nvkm_top_fault(struct nvkm_top *, int fault);
+enum nvkm_devidx nvkm_top_engine(struct nvkm_top *, int, int *runl, int *engn);
+
+int gk104_top_new(struct nvkm_device *, int, struct nvkm_top **);
+#endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_abi16.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_abi16.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_abi16.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_abi16.c	2016-07-24 15:23:50.000000000 -0400
@@ -29,7 +29,7 @@
 #include <nvif/cla06f.h>
 #include <nvif/unpack.h>
 
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_dma.h"
 #include "nouveau_gem.h"
 #include "nouveau_chan.h"
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_acpi.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_acpi.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_acpi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_acpi.c	2016-07-24 15:23:50.000000000 -0400
@@ -6,7 +6,7 @@
 #include <drm/drm_edid.h>
 #include <acpi/video.h>
 
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_acpi.h"
 
 #define NOUVEAU_DSM_LED 0x02
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_backlight.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_backlight.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_backlight.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_backlight.c	2016-07-24 15:23:50.000000000 -0400
@@ -32,7 +32,7 @@
 
 #include <linux/backlight.h>
 
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_reg.h"
 #include "nouveau_encoder.h"
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_bios.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_bios.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_bios.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_bios.c	2016-07-24 15:23:50.000000000 -0400
@@ -24,7 +24,7 @@
 
 #include <drm/drmP.h>
 
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_reg.h"
 #include "dispnv04/hw.h"
 #include "nouveau_encoder.h"
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_bo.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_bo.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_bo.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_bo.c	2016-07-24 15:23:50.000000000 -0400
@@ -30,7 +30,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/swiotlb.h>
 
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_dma.h"
 #include "nouveau_fence.h"
 
@@ -312,7 +312,7 @@ nouveau_bo_pin(struct nouveau_bo *nvbo,
 	bool force = false, evict = false;
 	int ret;
 
-	ret = ttm_bo_reserve(bo, false, false, false, NULL);
+	ret = ttm_bo_reserve(bo, false, false, NULL);
 	if (ret)
 		return ret;
 
@@ -385,7 +385,7 @@ nouveau_bo_unpin(struct nouveau_bo *nvbo
 	struct ttm_buffer_object *bo = &nvbo->bo;
 	int ret, ref;
 
-	ret = ttm_bo_reserve(bo, false, false, false, NULL);
+	ret = ttm_bo_reserve(bo, false, false, NULL);
 	if (ret)
 		return ret;
 
@@ -420,7 +420,7 @@ nouveau_bo_map(struct nouveau_bo *nvbo)
 {
 	int ret;
 
-	ret = ttm_bo_reserve(&nvbo->bo, false, false, false, NULL);
+	ret = ttm_bo_reserve(&nvbo->bo, false, false, NULL);
 	if (ret)
 		return ret;
 
@@ -1322,7 +1322,7 @@ nouveau_bo_move(struct ttm_buffer_object
 	}
 
 	/* Fallback to software copy. */
-	ret = ttm_bo_wait(bo, true, intr, no_wait_gpu);
+	ret = ttm_bo_wait(bo, intr, no_wait_gpu);
 	if (ret == 0)
 		ret = ttm_bo_move_memcpy(bo, evict, no_wait_gpu, new_mem);
 
@@ -1611,6 +1611,8 @@ struct ttm_bo_driver nouveau_bo_driver =
 	.fault_reserve_notify = &nouveau_ttm_fault_reserve_notify,
 	.io_mem_reserve = &nouveau_ttm_io_mem_reserve,
 	.io_mem_free = &nouveau_ttm_io_mem_free,
+	.lru_tail = &ttm_bo_default_lru_tail,
+	.swap_lru_tail = &ttm_bo_default_swap_lru_tail,
 };
 
 struct nvkm_vma *
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_chan.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_chan.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_chan.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_chan.c	2016-07-24 15:23:50.000000000 -0400
@@ -34,7 +34,7 @@
 /*XXX*/
 #include <core/client.h>
 
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_dma.h"
 #include "nouveau_bo.h"
 #include "nouveau_chan.h"
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_connector.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_connector.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_connector.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_connector.c	2016-07-24 15:23:50.000000000 -0400
@@ -34,7 +34,7 @@
 #include <drm/drm_crtc_helper.h>
 
 #include "nouveau_reg.h"
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "dispnv04/hw.h"
 #include "nouveau_acpi.h"
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_debugfs.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_debugfs.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_debugfs.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_debugfs.c	2016-07-24 15:23:50.000000000 -0400
@@ -32,7 +32,7 @@
 #include <nvif/class.h>
 #include <nvif/if0001.h>
 #include "nouveau_debugfs.h"
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 
 static int
 nouveau_debugfs_vbios_image(struct seq_file *m, void *data)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_debugfs.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_debugfs.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_debugfs.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_debugfs.h	2016-07-24 15:23:50.000000000 -0400
@@ -5,7 +5,7 @@
 
 #if defined(CONFIG_DEBUG_FS)
 
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 
 struct nouveau_debugfs {
 	struct nvif_object ctrl;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_display.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_display.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_display.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_display.c	2016-07-24 15:23:50.000000000 -0400
@@ -279,7 +279,7 @@ nouveau_user_framebuffer_create(struct d
 	struct drm_gem_object *gem;
 	int ret = -ENOMEM;
 
-	gem = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]);
+	gem = drm_gem_object_lookup(file_priv, mode_cmd->handles[0]);
 	if (!gem)
 		return ERR_PTR(-ENOENT);
 
@@ -296,7 +296,7 @@ nouveau_user_framebuffer_create(struct d
 err:
 	kfree(nouveau_fb);
 err_unref:
-	drm_gem_object_unreference(gem);
+	drm_gem_object_unreference_unlocked(gem);
 	return ERR_PTR(ret);
 }
 
@@ -739,7 +739,7 @@ nouveau_crtc_page_flip(struct drm_crtc *
 	}
 
 	mutex_lock(&cli->mutex);
-	ret = ttm_bo_reserve(&new_bo->bo, true, false, false, NULL);
+	ret = ttm_bo_reserve(&new_bo->bo, true, false, NULL);
 	if (ret)
 		goto fail_unpin;
 
@@ -753,7 +753,7 @@ nouveau_crtc_page_flip(struct drm_crtc *
 	if (new_bo != old_bo) {
 		ttm_bo_unreserve(&new_bo->bo);
 
-		ret = ttm_bo_reserve(&old_bo->bo, true, false, false, NULL);
+		ret = ttm_bo_reserve(&old_bo->bo, true, false, NULL);
 		if (ret)
 			goto fail_unpin;
 	}
@@ -916,7 +916,7 @@ nouveau_display_dumb_map_offset(struct d
 {
 	struct drm_gem_object *gem;
 
-	gem = drm_gem_object_lookup(dev, file_priv, handle);
+	gem = drm_gem_object_lookup(file_priv, handle);
 	if (gem) {
 		struct nouveau_bo *bo = nouveau_gem_object(gem);
 		*poffset = drm_vma_node_offset_addr(&bo->bo.vma_node);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_display.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_display.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_display.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_display.h	2016-07-24 15:23:50.000000000 -0400
@@ -3,7 +3,7 @@
 
 #include <subdev/mmu.h>
 
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 
 struct nouveau_framebuffer {
 	struct drm_framebuffer base;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_dma.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_dma.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_dma.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_dma.c	2016-07-24 15:23:50.000000000 -0400
@@ -24,7 +24,7 @@
  *
  */
 
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_dma.h"
 
 void
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_dp.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_dp.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_dp.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_dp.c	2016-07-24 15:23:50.000000000 -0400
@@ -25,7 +25,7 @@
 #include <drm/drmP.h>
 #include <drm/drm_dp_helper.h>
 
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_connector.h"
 #include "nouveau_encoder.h"
 #include "nouveau_crtc.h"
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_drm.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_drm.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_drm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_drm.c	2016-07-24 15:23:50.000000000 -0400
@@ -44,7 +44,7 @@
 #include <nvif/cla06f.h>
 #include <nvif/if0004.h>
 
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_dma.h"
 #include "nouveau_ttm.h"
 #include "nouveau_gem.h"
@@ -1083,10 +1083,8 @@ nouveau_drm_init(void)
 	nouveau_display_options();
 
 	if (nouveau_modeset == -1) {
-#ifdef CONFIG_VGA_CONSOLE
 		if (vgacon_text_force())
 			nouveau_modeset = 0;
-#endif
 	}
 
 	if (!nouveau_modeset)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_drm.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_drm.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_drm.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_drm.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,207 +0,0 @@
-#ifndef __NOUVEAU_DRMCLI_H__
-#define __NOUVEAU_DRMCLI_H__
-
-#define DRIVER_AUTHOR		"Nouveau Project"
-#define DRIVER_EMAIL		"nouveau@lists.freedesktop.org"
-
-#define DRIVER_NAME		"nouveau"
-#define DRIVER_DESC		"nVidia Riva/TNT/GeForce/Quadro/Tesla"
-#define DRIVER_DATE		"20120801"
-
-#define DRIVER_MAJOR		1
-#define DRIVER_MINOR		3
-#define DRIVER_PATCHLEVEL	1
-
-/*
- * 1.1.1:
- * 	- added support for tiled system memory buffer objects
- *      - added support for NOUVEAU_GETPARAM_GRAPH_UNITS on [nvc0,nve0].
- *      - added support for compressed memory storage types on [nvc0,nve0].
- *      - added support for software methods 0x600,0x644,0x6ac on nvc0
- *        to control registers on the MPs to enable performance counters,
- *        and to control the warp error enable mask (OpenGL requires out of
- *        bounds access to local memory to be silently ignored / return 0).
- * 1.1.2:
- *      - fixes multiple bugs in flip completion events and timestamping
- * 1.2.0:
- * 	- object api exposed to userspace
- * 	- fermi,kepler,maxwell zbc
- * 1.2.1:
- *      - allow concurrent access to bo's mapped read/write.
- * 1.2.2:
- *      - add NOUVEAU_GEM_DOMAIN_COHERENT flag
- * 1.3.0:
- *      - NVIF ABI modified, safe because only (current) users are test
- *        programs that get directly linked with NVKM.
- * 1.3.1:
- *      - implemented limited ABI16/NVIF interop
- */
-
-#include <nvif/client.h>
-#include <nvif/device.h>
-#include <nvif/ioctl.h>
-
-#include <drmP.h>
-
-#include <drm/ttm/ttm_bo_api.h>
-#include <drm/ttm/ttm_bo_driver.h>
-#include <drm/ttm/ttm_placement.h>
-#include <drm/ttm/ttm_memory.h>
-#include <drm/ttm/ttm_module.h>
-#include <drm/ttm/ttm_page_alloc.h>
-
-#include "uapi/drm/nouveau_drm.h"
-
-struct nouveau_channel;
-struct platform_device;
-
-#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
-
-#include "nouveau_fence.h"
-#include "nouveau_bios.h"
-
-struct nouveau_drm_tile {
-	struct nouveau_fence *fence;
-	bool used;
-};
-
-enum nouveau_drm_object_route {
-	NVDRM_OBJECT_NVIF = NVIF_IOCTL_V0_OWNER_NVIF,
-	NVDRM_OBJECT_USIF,
-	NVDRM_OBJECT_ABI16,
-	NVDRM_OBJECT_ANY = NVIF_IOCTL_V0_OWNER_ANY,
-};
-
-enum nouveau_drm_notify_route {
-	NVDRM_NOTIFY_NVIF = 0,
-	NVDRM_NOTIFY_USIF
-};
-
-enum nouveau_drm_handle {
-	NVDRM_CHAN    = 0xcccc0000, /* |= client chid */
-	NVDRM_NVSW    = 0x55550000,
-};
-
-struct nouveau_cli {
-	struct nvif_client base;
-	struct nvkm_vm *vm; /*XXX*/
-	struct list_head head;
-	struct mutex mutex;
-	void *abi16;
-	struct list_head objects;
-	struct list_head notifys;
-	char name[32];
-	struct drm_device *dev;
-};
-
-static inline struct nouveau_cli *
-nouveau_cli(struct drm_file *fpriv)
-{
-	return fpriv ? fpriv->driver_priv : NULL;
-}
-
-#include <nvif/object.h>
-#include <nvif/device.h>
-
-extern int nouveau_runtime_pm;
-
-struct nouveau_drm {
-	struct nouveau_cli client;
-	struct drm_device *dev;
-
-	struct nvif_device device;
-	struct list_head clients;
-
-	struct {
-		struct agp_bridge_data *bridge;
-		u32 base;
-		u32 size;
-		bool cma;
-	} agp;
-
-	/* TTM interface support */
-	struct {
-		struct drm_global_reference mem_global_ref;
-		struct ttm_bo_global_ref bo_global_ref;
-		struct ttm_bo_device bdev;
-		atomic_t validate_sequence;
-		int (*move)(struct nouveau_channel *,
-			    struct ttm_buffer_object *,
-			    struct ttm_mem_reg *, struct ttm_mem_reg *);
-		struct nouveau_channel *chan;
-		struct nvif_object copy;
-		int mtrr;
-	} ttm;
-
-	/* GEM interface support */
-	struct {
-		u64 vram_available;
-		u64 gart_available;
-	} gem;
-
-	/* synchronisation */
-	void *fence;
-
-	/* context for accelerated drm-internal operations */
-	struct nouveau_channel *cechan;
-	struct nouveau_channel *channel;
-	struct nvkm_gpuobj *notify;
-	struct nouveau_fbdev *fbcon;
-	struct nvif_object nvsw;
-	struct nvif_object ntfy;
-	struct nvif_notify flip;
-
-	/* nv10-nv40 tiling regions */
-	struct {
-		struct nouveau_drm_tile reg[15];
-		spinlock_t lock;
-	} tile;
-
-	/* modesetting */
-	struct nvbios vbios;
-	struct nouveau_display *display;
-	struct backlight_device *backlight;
-
-	/* power management */
-	struct nouveau_hwmon *hwmon;
-	struct nouveau_debugfs *debugfs;
-
-	/* display power reference */
-	bool have_disp_power_ref;
-
-	struct dev_pm_domain vga_pm_domain;
-	struct pci_dev *hdmi_device;
-};
-
-static inline struct nouveau_drm *
-nouveau_drm(struct drm_device *dev)
-{
-	return dev->dev_private;
-}
-
-int nouveau_pmops_suspend(struct device *);
-int nouveau_pmops_resume(struct device *);
-
-#include <nvkm/core/tegra.h>
-
-struct drm_device *
-nouveau_platform_device_create(const struct nvkm_device_tegra_func *,
-			       struct platform_device *, struct nvkm_device **);
-void nouveau_drm_device_remove(struct drm_device *dev);
-
-#define NV_PRINTK(l,c,f,a...) do {                                             \
-	struct nouveau_cli *_cli = (c);                                        \
-	dev_##l(_cli->dev->dev, "%s: "f, _cli->name, ##a);                     \
-} while(0)
-#define NV_FATAL(drm,f,a...) NV_PRINTK(crit, &(drm)->client, f, ##a)
-#define NV_ERROR(drm,f,a...) NV_PRINTK(err, &(drm)->client, f, ##a)
-#define NV_WARN(drm,f,a...) NV_PRINTK(warn, &(drm)->client, f, ##a)
-#define NV_INFO(drm,f,a...) NV_PRINTK(info, &(drm)->client, f, ##a)
-#define NV_DEBUG(drm,f,a...) do {                                              \
-	if (unlikely(drm_debug & DRM_UT_DRIVER))                               \
-		NV_PRINTK(info, &(drm)->client, f, ##a);                       \
-} while(0)
-
-extern int nouveau_modeset;
-
-#endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_drv.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_drv.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_drv.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_drv.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,207 @@
+#ifndef __NOUVEAU_DRV_H__
+#define __NOUVEAU_DRV_H__
+
+#define DRIVER_AUTHOR		"Nouveau Project"
+#define DRIVER_EMAIL		"nouveau@lists.freedesktop.org"
+
+#define DRIVER_NAME		"nouveau"
+#define DRIVER_DESC		"nVidia Riva/TNT/GeForce/Quadro/Tesla"
+#define DRIVER_DATE		"20120801"
+
+#define DRIVER_MAJOR		1
+#define DRIVER_MINOR		3
+#define DRIVER_PATCHLEVEL	1
+
+/*
+ * 1.1.1:
+ * 	- added support for tiled system memory buffer objects
+ *      - added support for NOUVEAU_GETPARAM_GRAPH_UNITS on [nvc0,nve0].
+ *      - added support for compressed memory storage types on [nvc0,nve0].
+ *      - added support for software methods 0x600,0x644,0x6ac on nvc0
+ *        to control registers on the MPs to enable performance counters,
+ *        and to control the warp error enable mask (OpenGL requires out of
+ *        bounds access to local memory to be silently ignored / return 0).
+ * 1.1.2:
+ *      - fixes multiple bugs in flip completion events and timestamping
+ * 1.2.0:
+ * 	- object api exposed to userspace
+ * 	- fermi,kepler,maxwell zbc
+ * 1.2.1:
+ *      - allow concurrent access to bo's mapped read/write.
+ * 1.2.2:
+ *      - add NOUVEAU_GEM_DOMAIN_COHERENT flag
+ * 1.3.0:
+ *      - NVIF ABI modified, safe because only (current) users are test
+ *        programs that get directly linked with NVKM.
+ * 1.3.1:
+ *      - implemented limited ABI16/NVIF interop
+ */
+
+#include <nvif/client.h>
+#include <nvif/device.h>
+#include <nvif/ioctl.h>
+
+#include <drmP.h>
+
+#include <drm/ttm/ttm_bo_api.h>
+#include <drm/ttm/ttm_bo_driver.h>
+#include <drm/ttm/ttm_placement.h>
+#include <drm/ttm/ttm_memory.h>
+#include <drm/ttm/ttm_module.h>
+#include <drm/ttm/ttm_page_alloc.h>
+
+#include "uapi/drm/nouveau_drm.h"
+
+struct nouveau_channel;
+struct platform_device;
+
+#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
+
+#include "nouveau_fence.h"
+#include "nouveau_bios.h"
+
+struct nouveau_drm_tile {
+	struct nouveau_fence *fence;
+	bool used;
+};
+
+enum nouveau_drm_object_route {
+	NVDRM_OBJECT_NVIF = NVIF_IOCTL_V0_OWNER_NVIF,
+	NVDRM_OBJECT_USIF,
+	NVDRM_OBJECT_ABI16,
+	NVDRM_OBJECT_ANY = NVIF_IOCTL_V0_OWNER_ANY,
+};
+
+enum nouveau_drm_notify_route {
+	NVDRM_NOTIFY_NVIF = 0,
+	NVDRM_NOTIFY_USIF
+};
+
+enum nouveau_drm_handle {
+	NVDRM_CHAN    = 0xcccc0000, /* |= client chid */
+	NVDRM_NVSW    = 0x55550000,
+};
+
+struct nouveau_cli {
+	struct nvif_client base;
+	struct nvkm_vm *vm; /*XXX*/
+	struct list_head head;
+	struct mutex mutex;
+	void *abi16;
+	struct list_head objects;
+	struct list_head notifys;
+	char name[32];
+	struct drm_device *dev;
+};
+
+static inline struct nouveau_cli *
+nouveau_cli(struct drm_file *fpriv)
+{
+	return fpriv ? fpriv->driver_priv : NULL;
+}
+
+#include <nvif/object.h>
+#include <nvif/device.h>
+
+extern int nouveau_runtime_pm;
+
+struct nouveau_drm {
+	struct nouveau_cli client;
+	struct drm_device *dev;
+
+	struct nvif_device device;
+	struct list_head clients;
+
+	struct {
+		struct agp_bridge_data *bridge;
+		u32 base;
+		u32 size;
+		bool cma;
+	} agp;
+
+	/* TTM interface support */
+	struct {
+		struct drm_global_reference mem_global_ref;
+		struct ttm_bo_global_ref bo_global_ref;
+		struct ttm_bo_device bdev;
+		atomic_t validate_sequence;
+		int (*move)(struct nouveau_channel *,
+			    struct ttm_buffer_object *,
+			    struct ttm_mem_reg *, struct ttm_mem_reg *);
+		struct nouveau_channel *chan;
+		struct nvif_object copy;
+		int mtrr;
+	} ttm;
+
+	/* GEM interface support */
+	struct {
+		u64 vram_available;
+		u64 gart_available;
+	} gem;
+
+	/* synchronisation */
+	void *fence;
+
+	/* context for accelerated drm-internal operations */
+	struct nouveau_channel *cechan;
+	struct nouveau_channel *channel;
+	struct nvkm_gpuobj *notify;
+	struct nouveau_fbdev *fbcon;
+	struct nvif_object nvsw;
+	struct nvif_object ntfy;
+	struct nvif_notify flip;
+
+	/* nv10-nv40 tiling regions */
+	struct {
+		struct nouveau_drm_tile reg[15];
+		spinlock_t lock;
+	} tile;
+
+	/* modesetting */
+	struct nvbios vbios;
+	struct nouveau_display *display;
+	struct backlight_device *backlight;
+
+	/* power management */
+	struct nouveau_hwmon *hwmon;
+	struct nouveau_debugfs *debugfs;
+
+	/* display power reference */
+	bool have_disp_power_ref;
+
+	struct dev_pm_domain vga_pm_domain;
+	struct pci_dev *hdmi_device;
+};
+
+static inline struct nouveau_drm *
+nouveau_drm(struct drm_device *dev)
+{
+	return dev->dev_private;
+}
+
+int nouveau_pmops_suspend(struct device *);
+int nouveau_pmops_resume(struct device *);
+
+#include <nvkm/core/tegra.h>
+
+struct drm_device *
+nouveau_platform_device_create(const struct nvkm_device_tegra_func *,
+			       struct platform_device *, struct nvkm_device **);
+void nouveau_drm_device_remove(struct drm_device *dev);
+
+#define NV_PRINTK(l,c,f,a...) do {                                             \
+	struct nouveau_cli *_cli = (c);                                        \
+	dev_##l(_cli->dev->dev, "%s: "f, _cli->name, ##a);                     \
+} while(0)
+#define NV_FATAL(drm,f,a...) NV_PRINTK(crit, &(drm)->client, f, ##a)
+#define NV_ERROR(drm,f,a...) NV_PRINTK(err, &(drm)->client, f, ##a)
+#define NV_WARN(drm,f,a...) NV_PRINTK(warn, &(drm)->client, f, ##a)
+#define NV_INFO(drm,f,a...) NV_PRINTK(info, &(drm)->client, f, ##a)
+#define NV_DEBUG(drm,f,a...) do {                                              \
+	if (unlikely(drm_debug & DRM_UT_DRIVER))                               \
+		NV_PRINTK(info, &(drm)->client, f, ##a);                       \
+} while(0)
+
+extern int nouveau_modeset;
+
+#endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_fbcon.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_fbcon.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_fbcon.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_fbcon.c	2016-07-24 15:23:50.000000000 -0400
@@ -43,7 +43,7 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_fb_helper.h>
 
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_gem.h"
 #include "nouveau_bo.h"
 #include "nouveau_fbcon.h"
@@ -386,8 +386,6 @@ nouveau_fbcon_create(struct drm_fb_helpe
 		}
 	}
 
-	mutex_lock(&dev->struct_mutex);
-
 	info = drm_fb_helper_alloc_fbi(helper);
 	if (IS_ERR(info)) {
 		ret = PTR_ERR(info);
@@ -426,8 +424,6 @@ nouveau_fbcon_create(struct drm_fb_helpe
 
 	/* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
 
-	mutex_unlock(&dev->struct_mutex);
-
 	if (chan)
 		nouveau_fbcon_accel_init(dev);
 	nouveau_fbcon_zfill(dev, fbcon);
@@ -441,7 +437,6 @@ nouveau_fbcon_create(struct drm_fb_helpe
 	return 0;
 
 out_unlock:
-	mutex_unlock(&dev->struct_mutex);
 	if (chan)
 		nouveau_bo_vma_del(nvbo, &fbcon->nouveau_fb.vma);
 	nouveau_bo_unmap(nvbo);
@@ -557,6 +552,8 @@ nouveau_fbcon_init(struct drm_device *de
 	if (ret)
 		goto fini;
 
+	if (fbcon->helper.fbdev)
+		fbcon->helper.fbdev->pixmap.buf_align = 4;
 	return 0;
 
 fini:
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_fence.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_fence.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_fence.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_fence.c	2016-07-24 15:23:50.000000000 -0400
@@ -34,7 +34,7 @@
 #include <nvif/notify.h>
 #include <nvif/event.h>
 
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_dma.h"
 #include "nouveau_fence.h"
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_gem.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_gem.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_gem.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_gem.c	2016-07-24 15:23:50.000000000 -0400
@@ -24,7 +24,7 @@
  *
  */
 
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_dma.h"
 #include "nouveau_fence.h"
 #include "nouveau_abi16.h"
@@ -71,7 +71,7 @@ nouveau_gem_object_open(struct drm_gem_o
 	if (!cli->vm)
 		return 0;
 
-	ret = ttm_bo_reserve(&nvbo->bo, false, false, false, NULL);
+	ret = ttm_bo_reserve(&nvbo->bo, false, false, NULL);
 	if (ret)
 		return ret;
 
@@ -126,7 +126,7 @@ nouveau_gem_object_unmap(struct nouveau_
 	list_del(&vma->head);
 
 	if (fobj && fobj->shared_count > 1)
-		ttm_bo_wait(&nvbo->bo, true, false, false);
+		ttm_bo_wait(&nvbo->bo, false, false);
 	else if (fobj && fobj->shared_count == 1)
 		fence = rcu_dereference_protected(fobj->shared[0],
 						reservation_object_held(resv));
@@ -156,7 +156,7 @@ nouveau_gem_object_close(struct drm_gem_
 	if (!cli->vm)
 		return;
 
-	ret = ttm_bo_reserve(&nvbo->bo, false, false, false, NULL);
+	ret = ttm_bo_reserve(&nvbo->bo, false, false, NULL);
 	if (ret)
 		return;
 
@@ -368,7 +368,6 @@ validate_init(struct nouveau_channel *ch
 	      int nr_buffers, struct validate_op *op)
 {
 	struct nouveau_cli *cli = nouveau_cli(file_priv);
-	struct drm_device *dev = chan->drm->dev;
 	int trycnt = 0;
 	int ret, i;
 	struct nouveau_bo *res_bo = NULL;
@@ -388,7 +387,7 @@ retry:
 		struct drm_gem_object *gem;
 		struct nouveau_bo *nvbo;
 
-		gem = drm_gem_object_lookup(dev, file_priv, b->handle);
+		gem = drm_gem_object_lookup(file_priv, b->handle);
 		if (!gem) {
 			NV_PRINTK(err, cli, "Unknown handle 0x%08x\n", b->handle);
 			ret = -ENOENT;
@@ -409,7 +408,7 @@ retry:
 			break;
 		}
 
-		ret = ttm_bo_reserve(&nvbo->bo, true, false, true, &op->ticket);
+		ret = ttm_bo_reserve(&nvbo->bo, true, false, &op->ticket);
 		if (ret) {
 			list_splice_tail_init(&vram_list, &op->list);
 			list_splice_tail_init(&gart_list, &op->list);
@@ -651,7 +650,7 @@ nouveau_gem_pushbuf_reloc_apply(struct n
 				data |= r->vor;
 		}
 
-		ret = ttm_bo_wait(&nvbo->bo, true, false, false);
+		ret = ttm_bo_wait(&nvbo->bo, false, false);
 		if (ret) {
 			NV_PRINTK(err, cli, "reloc wait_idle failed: %d\n", ret);
 			break;
@@ -864,7 +863,7 @@ nouveau_gem_ioctl_cpu_prep(struct drm_de
 	bool write = !!(req->flags & NOUVEAU_GEM_CPU_PREP_WRITE);
 	int ret;
 
-	gem = drm_gem_object_lookup(dev, file_priv, req->handle);
+	gem = drm_gem_object_lookup(file_priv, req->handle);
 	if (!gem)
 		return -ENOENT;
 	nvbo = nouveau_gem_object(gem);
@@ -896,7 +895,7 @@ nouveau_gem_ioctl_cpu_fini(struct drm_de
 	struct drm_gem_object *gem;
 	struct nouveau_bo *nvbo;
 
-	gem = drm_gem_object_lookup(dev, file_priv, req->handle);
+	gem = drm_gem_object_lookup(file_priv, req->handle);
 	if (!gem)
 		return -ENOENT;
 	nvbo = nouveau_gem_object(gem);
@@ -914,7 +913,7 @@ nouveau_gem_ioctl_info(struct drm_device
 	struct drm_gem_object *gem;
 	int ret;
 
-	gem = drm_gem_object_lookup(dev, file_priv, req->handle);
+	gem = drm_gem_object_lookup(file_priv, req->handle);
 	if (!gem)
 		return -ENOENT;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_gem.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_gem.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_gem.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_gem.h	2016-07-24 15:23:50.000000000 -0400
@@ -3,7 +3,7 @@
 
 #include <drm/drmP.h>
 
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_bo.h"
 
 #define nouveau_bo_tile_layout(nvbo)				\
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_hwmon.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_hwmon.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_hwmon.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_hwmon.c	2016-07-24 15:23:50.000000000 -0400
@@ -31,7 +31,7 @@
 
 #include <drm/drmP.h>
 
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_hwmon.h"
 
 #include <nvkm/subdev/iccsense.h>
@@ -689,7 +689,7 @@ nouveau_hwmon_init(struct drm_device *de
 			goto error;
 	}
 
-	if (iccsense && iccsense->data_valid && iccsense->rail_count) {
+	if (iccsense && iccsense->data_valid && !list_empty(&iccsense->rails)) {
 		ret = sysfs_create_group(&hwmon_dev->kobj,
 					 &hwmon_power_attrgroup);
 		if (ret)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_nvif.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_nvif.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_nvif.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_nvif.c	2016-07-24 15:23:50.000000000 -0400
@@ -36,7 +36,7 @@
 #include <nvif/event.h>
 #include <nvif/ioctl.h>
 
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_usif.h"
 
 static void
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_platform.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_platform.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_platform.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_platform.h	2016-07-24 15:23:50.000000000 -0400
@@ -21,7 +21,7 @@
  */
 #ifndef __NOUVEAU_PLATFORM_H__
 #define __NOUVEAU_PLATFORM_H__
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 
 extern struct platform_driver nouveau_platform_driver;
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_prime.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_prime.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_prime.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_prime.c	2016-07-24 15:23:50.000000000 -0400
@@ -25,7 +25,7 @@
 #include <drm/drmP.h>
 #include <linux/dma-buf.h>
 
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_gem.h"
 
 struct sg_table *nouveau_gem_prime_get_sg_table(struct drm_gem_object *obj)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_sgdma.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_sgdma.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_sgdma.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_sgdma.c	2016-07-24 15:23:50.000000000 -0400
@@ -1,7 +1,7 @@
 #include <linux/pagemap.h>
 #include <linux/slab.h>
 
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_ttm.h"
 
 struct nouveau_sgdma_be {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_ttm.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_ttm.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_ttm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_ttm.c	2016-07-24 15:23:50.000000000 -0400
@@ -24,7 +24,7 @@
  * USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_ttm.h"
 #include "nouveau_gem.h"
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_usif.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_usif.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_usif.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_usif.c	2016-07-24 15:23:50.000000000 -0400
@@ -22,7 +22,7 @@
  * Authors: Ben Skeggs <bskeggs@redhat.com>
  */
 
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_usif.h"
 #include "nouveau_abi16.h"
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_vga.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_vga.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nouveau_vga.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nouveau_vga.c	2016-07-24 15:23:50.000000000 -0400
@@ -4,7 +4,7 @@
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
 
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_acpi.h"
 #include "nouveau_fbcon.h"
 #include "nouveau_vga.h"
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nv04_fbcon.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nv04_fbcon.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nv04_fbcon.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nv04_fbcon.c	2016-07-24 15:23:50.000000000 -0400
@@ -22,7 +22,7 @@
  * DEALINGS IN THE SOFTWARE.
  */
 
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_dma.h"
 #include "nouveau_fbcon.h"
 
@@ -82,7 +82,6 @@ nv04_fbcon_imageblit(struct fb_info *inf
 	uint32_t fg;
 	uint32_t bg;
 	uint32_t dsize;
-	uint32_t width;
 	uint32_t *data = (uint32_t *)image->data;
 	int ret;
 
@@ -93,9 +92,6 @@ nv04_fbcon_imageblit(struct fb_info *inf
 	if (ret)
 		return ret;
 
-	width = ALIGN(image->width, 8);
-	dsize = ALIGN(width * image->height, 32) >> 5;
-
 	if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
 	    info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
 		fg = ((uint32_t *) info->pseudo_palette)[image->fg_color];
@@ -111,10 +107,11 @@ nv04_fbcon_imageblit(struct fb_info *inf
 			 ((image->dx + image->width) & 0xffff));
 	OUT_RING(chan, bg);
 	OUT_RING(chan, fg);
-	OUT_RING(chan, (image->height << 16) | width);
+	OUT_RING(chan, (image->height << 16) | image->width);
 	OUT_RING(chan, (image->height << 16) | image->width);
 	OUT_RING(chan, (image->dy << 16) | (image->dx & 0xffff));
 
+	dsize = ALIGN(image->width * image->height, 32) >> 5;
 	while (dsize) {
 		int iter_len = dsize > 128 ? 128 : dsize;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nv04_fence.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nv04_fence.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nv04_fence.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nv04_fence.c	2016-07-24 15:23:50.000000000 -0400
@@ -22,7 +22,7 @@
  * Authors: Ben Skeggs
  */
 
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_dma.h"
 #include "nouveau_fence.h"
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nv10_fence.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nv10_fence.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nv10_fence.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nv10_fence.c	2016-07-24 15:23:50.000000000 -0400
@@ -22,7 +22,7 @@
  * Authors: Ben Skeggs <bskeggs@redhat.com>
  */
 
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_dma.h"
 #include "nv10_fence.h"
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nv17_fence.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nv17_fence.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nv17_fence.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nv17_fence.c	2016-07-24 15:23:50.000000000 -0400
@@ -26,7 +26,7 @@
 #include <nvif/class.h>
 #include <nvif/cl0002.h>
 
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_dma.h"
 #include "nv10_fence.h"
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nv50_display.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nv50_display.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nv50_display.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nv50_display.c	2016-07-24 15:23:50.000000000 -0400
@@ -39,7 +39,7 @@
 #include <nvif/cl507d.h>
 #include <nvif/cl507e.h>
 
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_dma.h"
 #include "nouveau_gem.h"
 #include "nouveau_connector.h"
@@ -1305,7 +1305,6 @@ nv50_crtc_cursor_set(struct drm_crtc *cr
 		     uint32_t handle, uint32_t width, uint32_t height)
 {
 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
-	struct drm_device *dev = crtc->dev;
 	struct drm_gem_object *gem = NULL;
 	struct nouveau_bo *nvbo = NULL;
 	int ret = 0;
@@ -1314,7 +1313,7 @@ nv50_crtc_cursor_set(struct drm_crtc *cr
 		if (width != 64 || height != 64)
 			return -EINVAL;
 
-		gem = drm_gem_object_lookup(dev, file_priv, handle);
+		gem = drm_gem_object_lookup(file_priv, handle);
 		if (unlikely(!gem))
 			return -ENOENT;
 		nvbo = nouveau_gem_object(gem);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nv50_fbcon.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nv50_fbcon.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nv50_fbcon.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nv50_fbcon.c	2016-07-24 15:23:50.000000000 -0400
@@ -22,7 +22,7 @@
  * Authors: Ben Skeggs
  */
 
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_dma.h"
 #include "nouveau_fbcon.h"
 
@@ -95,7 +95,7 @@ nv50_fbcon_imageblit(struct fb_info *inf
 	struct nouveau_fbdev *nfbdev = info->par;
 	struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
 	struct nouveau_channel *chan = drm->channel;
-	uint32_t width, dwords, *data = (uint32_t *)image->data;
+	uint32_t dwords, *data = (uint32_t *)image->data;
 	uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel));
 	uint32_t *palette = info->pseudo_palette;
 	int ret;
@@ -107,9 +107,6 @@ nv50_fbcon_imageblit(struct fb_info *inf
 	if (ret)
 		return ret;
 
-	width = ALIGN(image->width, 32);
-	dwords = (width * image->height) >> 5;
-
 	BEGIN_NV04(chan, NvSub2D, 0x0814, 2);
 	if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
 	    info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
@@ -128,6 +125,7 @@ nv50_fbcon_imageblit(struct fb_info *inf
 	OUT_RING(chan, 0);
 	OUT_RING(chan, image->dy);
 
+	dwords = ALIGN(image->width * image->height, 32) >> 5;
 	while (dwords) {
 		int push = dwords > 2047 ? 2047 : dwords;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nv50_fence.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nv50_fence.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nv50_fence.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nv50_fence.c	2016-07-24 15:23:50.000000000 -0400
@@ -26,7 +26,7 @@
 #include <nvif/class.h>
 #include <nvif/cl0002.h>
 
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_dma.h"
 #include "nv10_fence.h"
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nv84_fence.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nv84_fence.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nv84_fence.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nv84_fence.c	2016-07-24 15:23:50.000000000 -0400
@@ -22,7 +22,7 @@
  * Authors: Ben Skeggs
  */
 
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_dma.h"
 #include "nouveau_fence.h"
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvc0_fbcon.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvc0_fbcon.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvc0_fbcon.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvc0_fbcon.c	2016-07-24 15:23:50.000000000 -0400
@@ -22,7 +22,7 @@
  * Authors: Ben Skeggs
  */
 
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_dma.h"
 #include "nouveau_fbcon.h"
 
@@ -95,7 +95,7 @@ nvc0_fbcon_imageblit(struct fb_info *inf
 	struct nouveau_fbdev *nfbdev = info->par;
 	struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
 	struct nouveau_channel *chan = drm->channel;
-	uint32_t width, dwords, *data = (uint32_t *)image->data;
+	uint32_t dwords, *data = (uint32_t *)image->data;
 	uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel));
 	uint32_t *palette = info->pseudo_palette;
 	int ret;
@@ -107,9 +107,6 @@ nvc0_fbcon_imageblit(struct fb_info *inf
 	if (ret)
 		return ret;
 
-	width = ALIGN(image->width, 32);
-	dwords = (width * image->height) >> 5;
-
 	BEGIN_NVC0(chan, NvSub2D, 0x0814, 2);
 	if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
 	    info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
@@ -128,6 +125,7 @@ nvc0_fbcon_imageblit(struct fb_info *inf
 	OUT_RING  (chan, 0);
 	OUT_RING  (chan, image->dy);
 
+	dwords = ALIGN(image->width * image->height, 32) >> 5;
 	while (dwords) {
 		int push = dwords > 2047 ? 2047 : dwords;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvc0_fence.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvc0_fence.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvc0_fence.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvc0_fence.c	2016-07-24 15:23:50.000000000 -0400
@@ -22,7 +22,7 @@
  * Authors: Ben Skeggs
  */
 
-#include "nouveau_drm.h"
+#include "nouveau_drv.h"
 #include "nouveau_dma.h"
 #include "nouveau_fence.h"
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/core/engine.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/core/engine.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/core/engine.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/core/engine.c	2016-07-24 15:23:50.000000000 -0400
@@ -137,11 +137,10 @@ nvkm_engine_func = {
 
 int
 nvkm_engine_ctor(const struct nvkm_engine_func *func,
-		 struct nvkm_device *device, int index, u32 pmc_enable,
-		 bool enable, struct nvkm_engine *engine)
+		 struct nvkm_device *device, int index, bool enable,
+		 struct nvkm_engine *engine)
 {
-	nvkm_subdev_ctor(&nvkm_engine_func, device, index,
-			 pmc_enable, &engine->subdev);
+	nvkm_subdev_ctor(&nvkm_engine_func, device, index, &engine->subdev);
 	engine->func = func;
 
 	if (!nvkm_boolopt(device->cfgopt, nvkm_subdev_name[index], enable)) {
@@ -155,11 +154,10 @@ nvkm_engine_ctor(const struct nvkm_engin
 
 int
 nvkm_engine_new_(const struct nvkm_engine_func *func,
-		 struct nvkm_device *device, int index, u32 pmc_enable,
-		 bool enable, struct nvkm_engine **pengine)
+		 struct nvkm_device *device, int index, bool enable,
+		 struct nvkm_engine **pengine)
 {
 	if (!(*pengine = kzalloc(sizeof(**pengine), GFP_KERNEL)))
 		return -ENOMEM;
-	return nvkm_engine_ctor(func, device, index, pmc_enable,
-				enable, *pengine);
+	return nvkm_engine_ctor(func, device, index, enable, *pengine);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/core/subdev.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/core/subdev.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/core/subdev.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/core/subdev.c	2016-07-24 15:23:50.000000000 -0400
@@ -24,6 +24,7 @@
 #include <core/subdev.h>
 #include <core/device.h>
 #include <core/option.h>
+#include <subdev/mc.h>
 
 static struct lock_class_key nvkm_subdev_lock_class[NVKM_SUBDEV_NR];
 
@@ -50,6 +51,7 @@ nvkm_subdev_name[NVKM_SUBDEV_NR] = {
 	[NVKM_SUBDEV_SECBOOT ] = "secboot",
 	[NVKM_SUBDEV_THERM   ] = "therm",
 	[NVKM_SUBDEV_TIMER   ] = "tmr",
+	[NVKM_SUBDEV_TOP     ] = "top",
 	[NVKM_SUBDEV_VOLT    ] = "volt",
 	[NVKM_ENGINE_BSP     ] = "bsp",
 	[NVKM_ENGINE_CE0     ] = "ce0",
@@ -89,7 +91,6 @@ nvkm_subdev_fini(struct nvkm_subdev *sub
 {
 	struct nvkm_device *device = subdev->device;
 	const char *action = suspend ? "suspend" : "fini";
-	u32 pmc_enable = subdev->pmc_enable;
 	s64 time;
 
 	nvkm_trace(subdev, "%s running...\n", action);
@@ -104,11 +105,7 @@ nvkm_subdev_fini(struct nvkm_subdev *sub
 		}
 	}
 
-	if (pmc_enable) {
-		nvkm_mask(device, 0x000200, pmc_enable, 0x00000000);
-		nvkm_mask(device, 0x000200, pmc_enable, pmc_enable);
-		nvkm_rd32(device, 0x000200);
-	}
+	nvkm_mc_reset(device->mc, subdev->index);
 
 	time = ktime_to_us(ktime_get()) - time;
 	nvkm_trace(subdev, "%s completed in %lldus\n", action, time);
@@ -193,14 +190,13 @@ nvkm_subdev_del(struct nvkm_subdev **psu
 
 void
 nvkm_subdev_ctor(const struct nvkm_subdev_func *func,
-		 struct nvkm_device *device, int index, u32 pmc_enable,
+		 struct nvkm_device *device, int index,
 		 struct nvkm_subdev *subdev)
 {
 	const char *name = nvkm_subdev_name[index];
 	subdev->func = func;
 	subdev->device = device;
 	subdev->index = index;
-	subdev->pmc_enable = pmc_enable;
 
 	__mutex_init(&subdev->mutex, name, &nvkm_subdev_lock_class[index]);
 	subdev->debug = nvkm_dbgopt(device->dbgopt, name);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/bsp/g84.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/bsp/g84.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/bsp/g84.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/bsp/g84.c	2016-07-24 15:23:50.000000000 -0400
@@ -27,7 +27,6 @@
 
 static const struct nvkm_xtensa_func
 g84_bsp = {
-	.pmc_enable = 0x04008000,
 	.fifo_val = 0x1111,
 	.unkd28 = 0x90044,
 	.sclass = {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/gf100.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/gf100.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/gf100.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/gf100.c	2016-07-24 15:23:50.000000000 -0400
@@ -40,7 +40,6 @@ gf100_ce0 = {
 	.code.size = sizeof(gf100_ce_code),
 	.data.data = gf100_ce_data,
 	.data.size = sizeof(gf100_ce_data),
-	.pmc_enable = 0x00000040,
 	.init = gf100_ce_init,
 	.intr = gt215_ce_intr,
 	.sclass = {
@@ -55,7 +54,6 @@ gf100_ce1 = {
 	.code.size = sizeof(gf100_ce_code),
 	.data.data = gf100_ce_data,
 	.data.size = sizeof(gf100_ce_data),
-	.pmc_enable = 0x00000080,
 	.init = gf100_ce_init,
 	.intr = gt215_ce_intr,
 	.sclass = {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/gk104.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/gk104.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/gk104.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/gk104.c	2016-07-24 15:23:50.000000000 -0400
@@ -97,17 +97,5 @@ int
 gk104_ce_new(struct nvkm_device *device, int index,
 	     struct nvkm_engine **pengine)
 {
-	if (index == NVKM_ENGINE_CE0) {
-		return nvkm_engine_new_(&gk104_ce, device, index,
-					0x00000040, true, pengine);
-	} else
-	if (index == NVKM_ENGINE_CE1) {
-		return nvkm_engine_new_(&gk104_ce, device, index,
-					0x00000080, true, pengine);
-	} else
-	if (index == NVKM_ENGINE_CE2) {
-		return nvkm_engine_new_(&gk104_ce, device, index,
-					0x00200000, true, pengine);
-	}
-	return -ENODEV;
+	return nvkm_engine_new_(&gk104_ce, device, index, true, pengine);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/gm107.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/gm107.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/gm107.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/gm107.c	2016-07-24 15:23:50.000000000 -0400
@@ -39,17 +39,5 @@ int
 gm107_ce_new(struct nvkm_device *device, int index,
 	     struct nvkm_engine **pengine)
 {
-	if (index == NVKM_ENGINE_CE0) {
-		return nvkm_engine_new_(&gm107_ce, device, index,
-					0x00000040, true, pengine);
-	} else
-	if (index == NVKM_ENGINE_CE1) {
-		return nvkm_engine_new_(&gm107_ce, device, index,
-					0x00000080, true, pengine);
-	} else
-	if (index == NVKM_ENGINE_CE2) {
-		return nvkm_engine_new_(&gm107_ce, device, index,
-					0x00200000, true, pengine);
-	}
-	return -ENODEV;
+	return nvkm_engine_new_(&gm107_ce, device, index, true, pengine);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/gm200.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/gm200.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/gm200.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/gm200.c	2016-07-24 15:23:50.000000000 -0400
@@ -38,17 +38,5 @@ int
 gm200_ce_new(struct nvkm_device *device, int index,
 	     struct nvkm_engine **pengine)
 {
-	if (index == NVKM_ENGINE_CE0) {
-		return nvkm_engine_new_(&gm200_ce, device, index,
-					0x00000040, true, pengine);
-	} else
-	if (index == NVKM_ENGINE_CE1) {
-		return nvkm_engine_new_(&gm200_ce, device, index,
-					0x00000080, true, pengine);
-	} else
-	if (index == NVKM_ENGINE_CE2) {
-		return nvkm_engine_new_(&gm200_ce, device, index,
-					0x00200000, true, pengine);
-	}
-	return -ENODEV;
+	return nvkm_engine_new_(&gm200_ce, device, index, true, pengine);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/gt215.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/gt215.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/gt215.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/gt215.c	2016-07-24 15:23:50.000000000 -0400
@@ -67,7 +67,6 @@ gt215_ce = {
 	.code.size = sizeof(gt215_ce_code),
 	.data.data = gt215_ce_data,
 	.data.size = sizeof(gt215_ce_data),
-	.pmc_enable = 0x00802000,
 	.intr = gt215_ce_intr,
 	.sclass = {
 		{ -1, -1, GT212_DMA },
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/cipher/g84.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/cipher/g84.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/cipher/g84.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/cipher/g84.c	2016-07-24 15:23:50.000000000 -0400
@@ -130,6 +130,5 @@ int
 g84_cipher_new(struct nvkm_device *device, int index,
 	       struct nvkm_engine **pengine)
 {
-	return nvkm_engine_new_(&g84_cipher, device, index,
-				0x00004000, true, pengine);
+	return nvkm_engine_new_(&g84_cipher, device, index, true, pengine);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c	2016-07-24 15:23:50.000000000 -0400
@@ -146,7 +146,7 @@ nv11_chipset = {
 	.gpio = nv10_gpio_new,
 	.i2c = nv04_i2c_new,
 	.imem = nv04_instmem_new,
-	.mc = nv04_mc_new,
+	.mc = nv11_mc_new,
 	.mmu = nv04_mmu_new,
 	.pci = nv04_pci_new,
 	.timer = nv04_timer_new,
@@ -190,7 +190,7 @@ nv17_chipset = {
 	.gpio = nv10_gpio_new,
 	.i2c = nv04_i2c_new,
 	.imem = nv04_instmem_new,
-	.mc = nv04_mc_new,
+	.mc = nv17_mc_new,
 	.mmu = nv04_mmu_new,
 	.pci = nv04_pci_new,
 	.timer = nv04_timer_new,
@@ -212,7 +212,7 @@ nv18_chipset = {
 	.gpio = nv10_gpio_new,
 	.i2c = nv04_i2c_new,
 	.imem = nv04_instmem_new,
-	.mc = nv04_mc_new,
+	.mc = nv17_mc_new,
 	.mmu = nv04_mmu_new,
 	.pci = nv04_pci_new,
 	.timer = nv04_timer_new,
@@ -256,7 +256,7 @@ nv1f_chipset = {
 	.gpio = nv10_gpio_new,
 	.i2c = nv04_i2c_new,
 	.imem = nv04_instmem_new,
-	.mc = nv04_mc_new,
+	.mc = nv17_mc_new,
 	.mmu = nv04_mmu_new,
 	.pci = nv04_pci_new,
 	.timer = nv04_timer_new,
@@ -278,7 +278,7 @@ nv20_chipset = {
 	.gpio = nv10_gpio_new,
 	.i2c = nv04_i2c_new,
 	.imem = nv04_instmem_new,
-	.mc = nv04_mc_new,
+	.mc = nv17_mc_new,
 	.mmu = nv04_mmu_new,
 	.pci = nv04_pci_new,
 	.timer = nv04_timer_new,
@@ -300,7 +300,7 @@ nv25_chipset = {
 	.gpio = nv10_gpio_new,
 	.i2c = nv04_i2c_new,
 	.imem = nv04_instmem_new,
-	.mc = nv04_mc_new,
+	.mc = nv17_mc_new,
 	.mmu = nv04_mmu_new,
 	.pci = nv04_pci_new,
 	.timer = nv04_timer_new,
@@ -322,7 +322,7 @@ nv28_chipset = {
 	.gpio = nv10_gpio_new,
 	.i2c = nv04_i2c_new,
 	.imem = nv04_instmem_new,
-	.mc = nv04_mc_new,
+	.mc = nv17_mc_new,
 	.mmu = nv04_mmu_new,
 	.pci = nv04_pci_new,
 	.timer = nv04_timer_new,
@@ -344,7 +344,7 @@ nv2a_chipset = {
 	.gpio = nv10_gpio_new,
 	.i2c = nv04_i2c_new,
 	.imem = nv04_instmem_new,
-	.mc = nv04_mc_new,
+	.mc = nv17_mc_new,
 	.mmu = nv04_mmu_new,
 	.pci = nv04_pci_new,
 	.timer = nv04_timer_new,
@@ -366,7 +366,7 @@ nv30_chipset = {
 	.gpio = nv10_gpio_new,
 	.i2c = nv04_i2c_new,
 	.imem = nv04_instmem_new,
-	.mc = nv04_mc_new,
+	.mc = nv17_mc_new,
 	.mmu = nv04_mmu_new,
 	.pci = nv04_pci_new,
 	.timer = nv04_timer_new,
@@ -388,7 +388,7 @@ nv31_chipset = {
 	.gpio = nv10_gpio_new,
 	.i2c = nv04_i2c_new,
 	.imem = nv04_instmem_new,
-	.mc = nv04_mc_new,
+	.mc = nv17_mc_new,
 	.mmu = nv04_mmu_new,
 	.pci = nv04_pci_new,
 	.timer = nv04_timer_new,
@@ -411,7 +411,7 @@ nv34_chipset = {
 	.gpio = nv10_gpio_new,
 	.i2c = nv04_i2c_new,
 	.imem = nv04_instmem_new,
-	.mc = nv04_mc_new,
+	.mc = nv17_mc_new,
 	.mmu = nv04_mmu_new,
 	.pci = nv04_pci_new,
 	.timer = nv04_timer_new,
@@ -434,7 +434,7 @@ nv35_chipset = {
 	.gpio = nv10_gpio_new,
 	.i2c = nv04_i2c_new,
 	.imem = nv04_instmem_new,
-	.mc = nv04_mc_new,
+	.mc = nv17_mc_new,
 	.mmu = nv04_mmu_new,
 	.pci = nv04_pci_new,
 	.timer = nv04_timer_new,
@@ -456,7 +456,7 @@ nv36_chipset = {
 	.gpio = nv10_gpio_new,
 	.i2c = nv04_i2c_new,
 	.imem = nv04_instmem_new,
-	.mc = nv04_mc_new,
+	.mc = nv17_mc_new,
 	.mmu = nv04_mmu_new,
 	.pci = nv04_pci_new,
 	.timer = nv04_timer_new,
@@ -479,7 +479,7 @@ nv40_chipset = {
 	.gpio = nv10_gpio_new,
 	.i2c = nv04_i2c_new,
 	.imem = nv40_instmem_new,
-	.mc = nv04_mc_new,
+	.mc = nv17_mc_new,
 	.mmu = nv04_mmu_new,
 	.pci = nv40_pci_new,
 	.therm = nv40_therm_new,
@@ -505,7 +505,7 @@ nv41_chipset = {
 	.gpio = nv10_gpio_new,
 	.i2c = nv04_i2c_new,
 	.imem = nv40_instmem_new,
-	.mc = nv04_mc_new,
+	.mc = nv17_mc_new,
 	.mmu = nv41_mmu_new,
 	.pci = nv40_pci_new,
 	.therm = nv40_therm_new,
@@ -531,7 +531,7 @@ nv42_chipset = {
 	.gpio = nv10_gpio_new,
 	.i2c = nv04_i2c_new,
 	.imem = nv40_instmem_new,
-	.mc = nv04_mc_new,
+	.mc = nv17_mc_new,
 	.mmu = nv41_mmu_new,
 	.pci = nv40_pci_new,
 	.therm = nv40_therm_new,
@@ -557,7 +557,7 @@ nv43_chipset = {
 	.gpio = nv10_gpio_new,
 	.i2c = nv04_i2c_new,
 	.imem = nv40_instmem_new,
-	.mc = nv04_mc_new,
+	.mc = nv17_mc_new,
 	.mmu = nv41_mmu_new,
 	.pci = nv40_pci_new,
 	.therm = nv40_therm_new,
@@ -609,7 +609,7 @@ nv45_chipset = {
 	.gpio = nv10_gpio_new,
 	.i2c = nv04_i2c_new,
 	.imem = nv40_instmem_new,
-	.mc = nv04_mc_new,
+	.mc = nv17_mc_new,
 	.mmu = nv04_mmu_new,
 	.pci = nv40_pci_new,
 	.therm = nv40_therm_new,
@@ -661,7 +661,7 @@ nv47_chipset = {
 	.gpio = nv10_gpio_new,
 	.i2c = nv04_i2c_new,
 	.imem = nv40_instmem_new,
-	.mc = nv04_mc_new,
+	.mc = nv17_mc_new,
 	.mmu = nv41_mmu_new,
 	.pci = nv40_pci_new,
 	.therm = nv40_therm_new,
@@ -687,7 +687,7 @@ nv49_chipset = {
 	.gpio = nv10_gpio_new,
 	.i2c = nv04_i2c_new,
 	.imem = nv40_instmem_new,
-	.mc = nv04_mc_new,
+	.mc = nv17_mc_new,
 	.mmu = nv41_mmu_new,
 	.pci = nv40_pci_new,
 	.therm = nv40_therm_new,
@@ -739,7 +739,7 @@ nv4b_chipset = {
 	.gpio = nv10_gpio_new,
 	.i2c = nv04_i2c_new,
 	.imem = nv40_instmem_new,
-	.mc = nv04_mc_new,
+	.mc = nv17_mc_new,
 	.mmu = nv41_mmu_new,
 	.pci = nv40_pci_new,
 	.therm = nv40_therm_new,
@@ -926,7 +926,7 @@ nv84_chipset = {
 	.gpio = nv50_gpio_new,
 	.i2c = nv50_i2c_new,
 	.imem = nv50_instmem_new,
-	.mc = nv50_mc_new,
+	.mc = g84_mc_new,
 	.mmu = nv50_mmu_new,
 	.mxm = nv50_mxm_new,
 	.pci = g84_pci_new,
@@ -958,7 +958,7 @@ nv86_chipset = {
 	.gpio = nv50_gpio_new,
 	.i2c = nv50_i2c_new,
 	.imem = nv50_instmem_new,
-	.mc = nv50_mc_new,
+	.mc = g84_mc_new,
 	.mmu = nv50_mmu_new,
 	.mxm = nv50_mxm_new,
 	.pci = g84_pci_new,
@@ -990,7 +990,7 @@ nv92_chipset = {
 	.gpio = nv50_gpio_new,
 	.i2c = nv50_i2c_new,
 	.imem = nv50_instmem_new,
-	.mc = nv50_mc_new,
+	.mc = g84_mc_new,
 	.mmu = nv50_mmu_new,
 	.mxm = nv50_mxm_new,
 	.pci = g84_pci_new,
@@ -1022,7 +1022,7 @@ nv94_chipset = {
 	.gpio = g94_gpio_new,
 	.i2c = g94_i2c_new,
 	.imem = nv50_instmem_new,
-	.mc = nv50_mc_new,
+	.mc = g84_mc_new,
 	.mmu = nv50_mmu_new,
 	.mxm = nv50_mxm_new,
 	.pci = g94_pci_new,
@@ -1054,7 +1054,7 @@ nv96_chipset = {
 	.gpio = g94_gpio_new,
 	.i2c = g94_i2c_new,
 	.imem = nv50_instmem_new,
-	.mc = nv50_mc_new,
+	.mc = g84_mc_new,
 	.mmu = nv50_mmu_new,
 	.mxm = nv50_mxm_new,
 	.pci = g94_pci_new,
@@ -1118,7 +1118,7 @@ nva0_chipset = {
 	.gpio = g94_gpio_new,
 	.i2c = nv50_i2c_new,
 	.imem = nv50_instmem_new,
-	.mc = g98_mc_new,
+	.mc = g84_mc_new,
 	.mmu = nv50_mmu_new,
 	.mxm = nv50_mxm_new,
 	.pci = g94_pci_new,
@@ -1150,7 +1150,7 @@ nva3_chipset = {
 	.gpio = g94_gpio_new,
 	.i2c = g94_i2c_new,
 	.imem = nv50_instmem_new,
-	.mc = g98_mc_new,
+	.mc = gt215_mc_new,
 	.mmu = nv50_mmu_new,
 	.mxm = nv50_mxm_new,
 	.pci = g94_pci_new,
@@ -1184,7 +1184,7 @@ nva5_chipset = {
 	.gpio = g94_gpio_new,
 	.i2c = g94_i2c_new,
 	.imem = nv50_instmem_new,
-	.mc = g98_mc_new,
+	.mc = gt215_mc_new,
 	.mmu = nv50_mmu_new,
 	.mxm = nv50_mxm_new,
 	.pci = g94_pci_new,
@@ -1217,7 +1217,7 @@ nva8_chipset = {
 	.gpio = g94_gpio_new,
 	.i2c = g94_i2c_new,
 	.imem = nv50_instmem_new,
-	.mc = g98_mc_new,
+	.mc = gt215_mc_new,
 	.mmu = nv50_mmu_new,
 	.mxm = nv50_mxm_new,
 	.pci = g94_pci_new,
@@ -1314,7 +1314,7 @@ nvaf_chipset = {
 	.gpio = g94_gpio_new,
 	.i2c = g94_i2c_new,
 	.imem = nv50_instmem_new,
-	.mc = g98_mc_new,
+	.mc = gt215_mc_new,
 	.mmu = nv50_mmu_new,
 	.mxm = nv50_mxm_new,
 	.pci = g94_pci_new,
@@ -1676,13 +1676,14 @@ nve4_chipset = {
 	.iccsense = gf100_iccsense_new,
 	.imem = nv50_instmem_new,
 	.ltc = gk104_ltc_new,
-	.mc = gf100_mc_new,
+	.mc = gk104_mc_new,
 	.mmu = gf100_mmu_new,
 	.mxm = nv50_mxm_new,
 	.pci = gk104_pci_new,
 	.pmu = gk104_pmu_new,
 	.therm = gf119_therm_new,
 	.timer = nv41_timer_new,
+	.top = gk104_top_new,
 	.volt = gk104_volt_new,
 	.ce[0] = gk104_ce_new,
 	.ce[1] = gk104_ce_new,
@@ -1714,13 +1715,14 @@ nve6_chipset = {
 	.iccsense = gf100_iccsense_new,
 	.imem = nv50_instmem_new,
 	.ltc = gk104_ltc_new,
-	.mc = gf100_mc_new,
+	.mc = gk104_mc_new,
 	.mmu = gf100_mmu_new,
 	.mxm = nv50_mxm_new,
 	.pci = gk104_pci_new,
 	.pmu = gk104_pmu_new,
 	.therm = gf119_therm_new,
 	.timer = nv41_timer_new,
+	.top = gk104_top_new,
 	.volt = gk104_volt_new,
 	.ce[0] = gk104_ce_new,
 	.ce[1] = gk104_ce_new,
@@ -1752,13 +1754,14 @@ nve7_chipset = {
 	.iccsense = gf100_iccsense_new,
 	.imem = nv50_instmem_new,
 	.ltc = gk104_ltc_new,
-	.mc = gf100_mc_new,
+	.mc = gk104_mc_new,
 	.mmu = gf100_mmu_new,
 	.mxm = nv50_mxm_new,
 	.pci = gk104_pci_new,
 	.pmu = gk104_pmu_new,
 	.therm = gf119_therm_new,
 	.timer = nv41_timer_new,
+	.top = gk104_top_new,
 	.volt = gk104_volt_new,
 	.ce[0] = gk104_ce_new,
 	.ce[1] = gk104_ce_new,
@@ -1789,6 +1792,7 @@ nvea_chipset = {
 	.mmu = gf100_mmu_new,
 	.pmu = gk20a_pmu_new,
 	.timer = gk20a_timer_new,
+	.top = gk104_top_new,
 	.volt = gk20a_volt_new,
 	.ce[2] = gk104_ce_new,
 	.dma = gf119_dma_new,
@@ -1814,13 +1818,14 @@ nvf0_chipset = {
 	.iccsense = gf100_iccsense_new,
 	.imem = nv50_instmem_new,
 	.ltc = gk104_ltc_new,
-	.mc = gf100_mc_new,
+	.mc = gk104_mc_new,
 	.mmu = gf100_mmu_new,
 	.mxm = nv50_mxm_new,
 	.pci = gk104_pci_new,
 	.pmu = gk110_pmu_new,
 	.therm = gf119_therm_new,
 	.timer = nv41_timer_new,
+	.top = gk104_top_new,
 	.volt = gk104_volt_new,
 	.ce[0] = gk104_ce_new,
 	.ce[1] = gk104_ce_new,
@@ -1851,13 +1856,14 @@ nvf1_chipset = {
 	.iccsense = gf100_iccsense_new,
 	.imem = nv50_instmem_new,
 	.ltc = gk104_ltc_new,
-	.mc = gf100_mc_new,
+	.mc = gk104_mc_new,
 	.mmu = gf100_mmu_new,
 	.mxm = nv50_mxm_new,
 	.pci = gk104_pci_new,
 	.pmu = gk110_pmu_new,
 	.therm = gf119_therm_new,
 	.timer = nv41_timer_new,
+	.top = gk104_top_new,
 	.volt = gk104_volt_new,
 	.ce[0] = gk104_ce_new,
 	.ce[1] = gk104_ce_new,
@@ -1895,6 +1901,7 @@ nv106_chipset = {
 	.pmu = gk208_pmu_new,
 	.therm = gf119_therm_new,
 	.timer = nv41_timer_new,
+	.top = gk104_top_new,
 	.volt = gk104_volt_new,
 	.ce[0] = gk104_ce_new,
 	.ce[1] = gk104_ce_new,
@@ -1932,6 +1939,7 @@ nv108_chipset = {
 	.pmu = gk208_pmu_new,
 	.therm = gf119_therm_new,
 	.timer = nv41_timer_new,
+	.top = gk104_top_new,
 	.volt = gk104_volt_new,
 	.ce[0] = gk104_ce_new,
 	.ce[1] = gk104_ce_new,
@@ -1969,6 +1977,41 @@ nv117_chipset = {
 	.pmu = gm107_pmu_new,
 	.therm = gm107_therm_new,
 	.timer = gk20a_timer_new,
+	.top = gk104_top_new,
+	.volt = gk104_volt_new,
+	.ce[0] = gm107_ce_new,
+	.ce[2] = gm107_ce_new,
+	.disp = gm107_disp_new,
+	.dma = gf119_dma_new,
+	.fifo = gm107_fifo_new,
+	.gr = gm107_gr_new,
+	.sw = gf100_sw_new,
+};
+
+static const struct nvkm_device_chip
+nv118_chipset = {
+	.name = "GM108",
+	.bar = gf100_bar_new,
+	.bios = nvkm_bios_new,
+	.bus = gf100_bus_new,
+	.clk = gk104_clk_new,
+	.devinit = gm107_devinit_new,
+	.fb = gm107_fb_new,
+	.fuse = gm107_fuse_new,
+	.gpio = gk104_gpio_new,
+	.i2c = gf119_i2c_new,
+	.ibus = gk104_ibus_new,
+	.iccsense = gf100_iccsense_new,
+	.imem = nv50_instmem_new,
+	.ltc = gm107_ltc_new,
+	.mc = gk20a_mc_new,
+	.mmu = gf100_mmu_new,
+	.mxm = nv50_mxm_new,
+	.pci = gk104_pci_new,
+	.pmu = gm107_pmu_new,
+	.therm = gm107_therm_new,
+	.timer = gk20a_timer_new,
+	.top = gk104_top_new,
 	.volt = gk104_volt_new,
 	.ce[0] = gm107_ce_new,
 	.ce[2] = gm107_ce_new,
@@ -1986,7 +2029,7 @@ nv120_chipset = {
 	.bios = nvkm_bios_new,
 	.bus = gf100_bus_new,
 	.devinit = gm200_devinit_new,
-	.fb = gm107_fb_new,
+	.fb = gm200_fb_new,
 	.fuse = gm107_fuse_new,
 	.gpio = gk104_gpio_new,
 	.i2c = gm200_i2c_new,
@@ -2001,6 +2044,7 @@ nv120_chipset = {
 	.pmu = gm107_pmu_new,
 	.secboot = gm200_secboot_new,
 	.timer = gk20a_timer_new,
+	.top = gk104_top_new,
 	.volt = gk104_volt_new,
 	.ce[0] = gm200_ce_new,
 	.ce[1] = gm200_ce_new,
@@ -2019,7 +2063,7 @@ nv124_chipset = {
 	.bios = nvkm_bios_new,
 	.bus = gf100_bus_new,
 	.devinit = gm200_devinit_new,
-	.fb = gm107_fb_new,
+	.fb = gm200_fb_new,
 	.fuse = gm107_fuse_new,
 	.gpio = gk104_gpio_new,
 	.i2c = gm200_i2c_new,
@@ -2034,6 +2078,7 @@ nv124_chipset = {
 	.pmu = gm107_pmu_new,
 	.secboot = gm200_secboot_new,
 	.timer = gk20a_timer_new,
+	.top = gk104_top_new,
 	.volt = gk104_volt_new,
 	.ce[0] = gm200_ce_new,
 	.ce[1] = gm200_ce_new,
@@ -2052,7 +2097,7 @@ nv126_chipset = {
 	.bios = nvkm_bios_new,
 	.bus = gf100_bus_new,
 	.devinit = gm200_devinit_new,
-	.fb = gm107_fb_new,
+	.fb = gm200_fb_new,
 	.fuse = gm107_fuse_new,
 	.gpio = gk104_gpio_new,
 	.i2c = gm200_i2c_new,
@@ -2067,6 +2112,7 @@ nv126_chipset = {
 	.pmu = gm107_pmu_new,
 	.secboot = gm200_secboot_new,
 	.timer = gk20a_timer_new,
+	.top = gk104_top_new,
 	.volt = gk104_volt_new,
 	.ce[0] = gm200_ce_new,
 	.ce[1] = gm200_ce_new,
@@ -2093,6 +2139,7 @@ nv12b_chipset = {
 	.mmu = gf100_mmu_new,
 	.secboot = gm20b_secboot_new,
 	.timer = gk20a_timer_new,
+	.top = gk104_top_new,
 	.ce[2] = gm200_ce_new,
 	.volt = gm20b_volt_new,
 	.dma = gf119_dma_new,
@@ -2150,6 +2197,7 @@ nvkm_device_subdev(struct nvkm_device *d
 	_(SECBOOT , device->secboot , &device->secboot->subdev);
 	_(THERM   , device->therm   , &device->therm->subdev);
 	_(TIMER   , device->timer   , &device->timer->subdev);
+	_(TOP     , device->top     , &device->top->subdev);
 	_(VOLT    , device->volt    , &device->volt->subdev);
 #undef _
 	default:
@@ -2523,6 +2571,7 @@ nvkm_device_ctor(const struct nvkm_devic
 		case 0x106: device->chip = &nv106_chipset; break;
 		case 0x108: device->chip = &nv108_chipset; break;
 		case 0x117: device->chip = &nv117_chipset; break;
+		case 0x118: device->chip = &nv118_chipset; break;
 		case 0x120: device->chip = &nv120_chipset; break;
 		case 0x124: device->chip = &nv124_chipset; break;
 		case 0x126: device->chip = &nv126_chipset; break;
@@ -2604,6 +2653,7 @@ nvkm_device_ctor(const struct nvkm_devic
 		_(NVKM_SUBDEV_SECBOOT ,  secboot);
 		_(NVKM_SUBDEV_THERM   ,    therm);
 		_(NVKM_SUBDEV_TIMER   ,    timer);
+		_(NVKM_SUBDEV_TOP     ,      top);
 		_(NVKM_SUBDEV_VOLT    ,     volt);
 		_(NVKM_ENGINE_BSP     ,      bsp);
 		_(NVKM_ENGINE_CE0     ,    ce[0]);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c	2016-07-24 15:23:50.000000000 -0400
@@ -1614,7 +1614,7 @@ nvkm_device_pci_func = {
 	.fini = nvkm_device_pci_fini,
 	.resource_addr = nvkm_device_pci_resource_addr,
 	.resource_size = nvkm_device_pci_resource_size,
-	.cpu_coherent = !IS_ENABLED(CONFIG_ARM) && !IS_ENABLED(CONFIG_ARM64),
+	.cpu_coherent = !IS_ENABLED(CONFIG_ARM),
 };
 
 int
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h	2016-07-24 15:23:50.000000000 -0400
@@ -22,6 +22,7 @@
 #include <subdev/pmu.h>
 #include <subdev/therm.h>
 #include <subdev/timer.h>
+#include <subdev/top.h>
 #include <subdev/volt.h>
 #include <subdev/secboot.h>
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c	2016-07-24 15:23:50.000000000 -0400
@@ -298,8 +298,7 @@ nvkm_disp_ctor(const struct nvkm_disp_fu
 	disp->func = func;
 	disp->head.nr = heads;
 
-	ret = nvkm_engine_ctor(&nvkm_disp, device, index, 0,
-			       true, &disp->engine);
+	ret = nvkm_engine_ctor(&nvkm_disp, device, index, true, &disp->engine);
 	if (ret)
 		return ret;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c	2016-07-24 15:23:50.000000000 -0400
@@ -76,6 +76,7 @@ exec_lookup(struct nv50_disp *disp, int
 	mask |= 0x0001 << or;
 	mask |= 0x0100 << head;
 
+
 	list_for_each_entry(outp, &disp->base.outp, head) {
 		if ((outp->info.hasht & 0xff) == type &&
 		    (outp->info.hashm & mask) == mask) {
@@ -155,25 +156,21 @@ exec_clkcmp(struct nv50_disp *disp, int
 	if (!outp)
 		return NULL;
 
+	*conf = (ctrl & 0x00000f00) >> 8;
 	switch (outp->info.type) {
 	case DCB_OUTPUT_TMDS:
-		*conf = (ctrl & 0x00000f00) >> 8;
 		if (*conf == 5)
 			*conf |= 0x0100;
 		break;
 	case DCB_OUTPUT_LVDS:
-		*conf = disp->sor.lvdsconf;
-		break;
-	case DCB_OUTPUT_DP:
-		*conf = (ctrl & 0x00000f00) >> 8;
+		*conf |= disp->sor.lvdsconf;
 		break;
-	case DCB_OUTPUT_ANALOG:
 	default:
-		*conf = 0x00ff;
 		break;
 	}
 
-	data = nvbios_ocfg_match(bios, data, *conf, &ver, &hdr, &cnt, &len, &info2);
+	data = nvbios_ocfg_match(bios, data, *conf & 0xff, *conf >> 8,
+				 &ver, &hdr, &cnt, &len, &info2);
 	if (data && id < 0xff) {
 		data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk);
 		if (data) {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c	2016-07-24 15:23:50.000000000 -0400
@@ -36,7 +36,7 @@ gm107_disp = {
 	.outp.internal.crt = nv50_dac_output_new,
 	.outp.internal.tmds = nv50_sor_output_new,
 	.outp.internal.lvds = nv50_sor_output_new,
-	.outp.internal.dp = gf119_sor_dp_new,
+	.outp.internal.dp = gm107_sor_dp_new,
 	.dac.nr = 3,
 	.dac.power = nv50_dac_power,
 	.dac.sense = nv50_dac_sense,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild	2016-07-24 15:23:50.000000000 -0400
@@ -18,6 +18,7 @@ nvkm-y += nvkm/engine/disp/piornv50.o
 nvkm-y += nvkm/engine/disp/sornv50.o
 nvkm-y += nvkm/engine/disp/sorg94.o
 nvkm-y += nvkm/engine/disp/sorgf119.o
+nvkm-y += nvkm/engine/disp/sorgm107.o
 nvkm-y += nvkm/engine/disp/sorgm200.o
 nvkm-y += nvkm/engine/disp/dport.o
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c	2016-07-24 15:23:50.000000000 -0400
@@ -387,22 +387,17 @@ exec_clkcmp(struct nv50_disp *disp, int
 	if (!outp)
 		return NULL;
 
+	*conf = (ctrl & 0x00000f00) >> 8;
 	if (outp->info.location == 0) {
 		switch (outp->info.type) {
 		case DCB_OUTPUT_TMDS:
-			*conf = (ctrl & 0x00000f00) >> 8;
 			if (*conf == 5)
 				*conf |= 0x0100;
 			break;
 		case DCB_OUTPUT_LVDS:
-			*conf = disp->sor.lvdsconf;
-			break;
-		case DCB_OUTPUT_DP:
-			*conf = (ctrl & 0x00000f00) >> 8;
+			*conf |= disp->sor.lvdsconf;
 			break;
-		case DCB_OUTPUT_ANALOG:
 		default:
-			*conf = 0x00ff;
 			break;
 		}
 	} else {
@@ -410,7 +405,8 @@ exec_clkcmp(struct nv50_disp *disp, int
 		pclk = pclk / 2;
 	}
 
-	data = nvbios_ocfg_match(bios, data, *conf, &ver, &hdr, &cnt, &len, &info2);
+	data = nvbios_ocfg_match(bios, data, *conf & 0xff, *conf >> 8,
+				 &ver, &hdr, &cnt, &len, &info2);
 	if (data && id < 0xff) {
 		data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk);
 		if (data) {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h	2016-07-24 15:23:50.000000000 -0400
@@ -62,7 +62,12 @@ int g94_sor_dp_lnk_pwr(struct nvkm_outpu
 int gf119_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *,
 		     struct nvkm_output **);
 int gf119_sor_dp_lnk_ctl(struct nvkm_output_dp *, int, int, bool);
+int gf119_sor_dp_drv_ctl(struct nvkm_output_dp *, int, int, int, int);
 
-int  gm200_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *,
-		      struct nvkm_output **);
+int gm107_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *,
+		     struct nvkm_output **);
+int gm107_sor_dp_pattern(struct nvkm_output_dp *, int);
+
+int gm200_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *,
+		     struct nvkm_output **);
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c	2016-07-24 15:23:50.000000000 -0400
@@ -40,8 +40,8 @@ static int
 gf119_sor_dp_pattern(struct nvkm_output_dp *outp, int pattern)
 {
 	struct nvkm_device *device = outp->base.disp->engine.subdev.device;
-	const u32 loff = gf119_sor_loff(outp);
-	nvkm_mask(device, 0x61c110 + loff, 0x0f0f0f0f, 0x01010101 * pattern);
+	const u32 soff = gf119_sor_soff(outp);
+	nvkm_mask(device, 0x61c110 + soff, 0x0f0f0f0f, 0x01010101 * pattern);
 	return 0;
 }
 
@@ -64,7 +64,7 @@ gf119_sor_dp_lnk_ctl(struct nvkm_output_
 	return 0;
 }
 
-static int
+int
 gf119_sor_dp_drv_ctl(struct nvkm_output_dp *outp,
 		     int ln, int vs, int pe, int pc)
 {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2016 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+#include "nv50.h"
+#include "outpdp.h"
+
+int
+gm107_sor_dp_pattern(struct nvkm_output_dp *outp, int pattern)
+{
+	struct nvkm_device *device = outp->base.disp->engine.subdev.device;
+	const u32 soff = outp->base.or * 0x800;
+	const u32 data = 0x01010101 * pattern;
+	if (outp->base.info.sorconf.link & 1)
+		nvkm_mask(device, 0x61c110 + soff, 0x0f0f0f0f, data);
+	else
+		nvkm_mask(device, 0x61c12c + soff, 0x0f0f0f0f, data);
+	return 0;
+}
+
+static const struct nvkm_output_dp_func
+gm107_sor_dp_func = {
+	.pattern = gm107_sor_dp_pattern,
+	.lnk_pwr = g94_sor_dp_lnk_pwr,
+	.lnk_ctl = gf119_sor_dp_lnk_ctl,
+	.drv_ctl = gf119_sor_dp_drv_ctl,
+};
+
+int
+gm107_sor_dp_new(struct nvkm_disp *disp, int index,
+		 struct dcb_output *dcbE, struct nvkm_output **poutp)
+{
+	return nvkm_output_dp_new_(&gm107_sor_dp_func, disp, index, dcbE, poutp);
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c	2016-07-24 15:23:50.000000000 -0400
@@ -57,19 +57,6 @@ gm200_sor_dp_lane_map(struct nvkm_device
 }
 
 static int
-gm200_sor_dp_pattern(struct nvkm_output_dp *outp, int pattern)
-{
-	struct nvkm_device *device = outp->base.disp->engine.subdev.device;
-	const u32 soff = gm200_sor_soff(outp);
-	const u32 data = 0x01010101 * pattern;
-	if (outp->base.info.sorconf.link & 1)
-		nvkm_mask(device, 0x61c110 + soff, 0x0f0f0f0f, data);
-	else
-		nvkm_mask(device, 0x61c12c + soff, 0x0f0f0f0f, data);
-	return 0;
-}
-
-static int
 gm200_sor_dp_lnk_pwr(struct nvkm_output_dp *outp, int nr)
 {
 	struct nvkm_device *device = outp->base.disp->engine.subdev.device;
@@ -129,7 +116,7 @@ gm200_sor_dp_drv_ctl(struct nvkm_output_
 
 static const struct nvkm_output_dp_func
 gm200_sor_dp_func = {
-	.pattern = gm200_sor_dp_pattern,
+	.pattern = gm107_sor_dp_pattern,
 	.lnk_pwr = gm200_sor_dp_lnk_pwr,
 	.lnk_ctl = gf119_sor_dp_lnk_ctl,
 	.drv_ctl = gm200_sor_dp_drv_ctl,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/dma/base.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/dma/base.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/dma/base.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/dma/base.c	2016-07-24 15:23:50.000000000 -0400
@@ -152,6 +152,5 @@ nvkm_dma_new_(const struct nvkm_dma_func
 		return -ENOMEM;
 	dma->func = func;
 
-	return nvkm_engine_ctor(&nvkm_dma, device, index,
-				0, true, &dma->engine);
+	return nvkm_engine_ctor(&nvkm_dma, device, index, true, &dma->engine);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c	2016-05-15 19:21:38.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c	2016-07-24 18:18:11.000000000 -0400
@@ -348,6 +348,6 @@ nvkm_falcon_new_(const struct nvkm_falco
 	falcon->data.size = func->data.size;
 	*pengine = &falcon->engine;
 
-	return nvkm_engine_ctor(&nvkm_falcon, device, index, func->pmc_enable,
+	return nvkm_engine_ctor(&nvkm_falcon, device, index,
 				enable, &falcon->engine);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c	2016-07-24 15:23:50.000000000 -0400
@@ -178,6 +178,17 @@ nvkm_fifo_class_get(struct nvkm_oclass *
 	const struct nvkm_fifo_chan_oclass *sclass;
 	int c = 0;
 
+	if (fifo->func->class_get) {
+		int ret = fifo->func->class_get(fifo, index, &sclass);
+		if (ret == 0) {
+			oclass->base = sclass->base;
+			oclass->engn = sclass;
+			*class = &nvkm_fifo_class;
+			return 0;
+		}
+		return ret;
+	}
+
 	while ((sclass = fifo->func->chan[c])) {
 		if (c++ == index) {
 			oclass->base = sclass->base;
@@ -261,8 +272,7 @@ nvkm_fifo_ctor(const struct nvkm_fifo_fu
 		fifo->nr = nr;
 	bitmap_clear(fifo->mask, 0, fifo->nr);
 
-	ret = nvkm_engine_ctor(&nvkm_fifo, device, index, 0x00000100,
-			       true, &fifo->engine);
+	ret = nvkm_engine_ctor(&nvkm_fifo, device, index, true, &fifo->engine);
 	if (ret)
 		return ret;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c	2016-07-24 15:23:50.000000000 -0400
@@ -25,21 +25,36 @@
 #include "changk104.h"
 
 #include <core/client.h>
-#include <core/enum.h>
 #include <core/gpuobj.h>
 #include <subdev/bar.h>
+#include <subdev/top.h>
 #include <engine/sw.h>
 
 #include <nvif/class.h>
 
-void
+static int
+gk104_fifo_class_get(struct nvkm_fifo *base, int index,
+		     const struct nvkm_fifo_chan_oclass **psclass)
+{
+	struct gk104_fifo *fifo = gk104_fifo(base);
+	int c = 0;
+
+	while ((*psclass = fifo->func->chan[c])) {
+		if (c++ == index)
+			return 0;
+	}
+
+	return c;
+}
+
+static void
 gk104_fifo_uevent_fini(struct nvkm_fifo *fifo)
 {
 	struct nvkm_device *device = fifo->engine.subdev.device;
 	nvkm_mask(device, 0x002140, 0x80000000, 0x00000000);
 }
 
-void
+static void
 gk104_fifo_uevent_init(struct nvkm_fifo *fifo)
 {
 	struct nvkm_device *device = fifo->engine.subdev.device;
@@ -267,111 +282,6 @@ gk104_fifo_intr_dropped_fault(struct gk1
 	nvkm_error(subdev, "DROPPED_MMU_FAULT %08x\n", stat);
 }
 
-static const struct nvkm_enum
-gk104_fifo_fault_engine[] = {
-	{ 0x00, "GR", NULL, NVKM_ENGINE_GR },
-	{ 0x03, "IFB", NULL, NVKM_ENGINE_IFB },
-	{ 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR },
-	{ 0x05, "BAR3", NULL, NVKM_SUBDEV_INSTMEM },
-	{ 0x07, "PBDMA0", NULL, NVKM_ENGINE_FIFO },
-	{ 0x08, "PBDMA1", NULL, NVKM_ENGINE_FIFO },
-	{ 0x09, "PBDMA2", NULL, NVKM_ENGINE_FIFO },
-	{ 0x10, "MSVLD", NULL, NVKM_ENGINE_MSVLD },
-	{ 0x11, "MSPPP", NULL, NVKM_ENGINE_MSPPP },
-	{ 0x13, "PERF" },
-	{ 0x14, "MSPDEC", NULL, NVKM_ENGINE_MSPDEC },
-	{ 0x15, "CE0", NULL, NVKM_ENGINE_CE0 },
-	{ 0x16, "CE1", NULL, NVKM_ENGINE_CE1 },
-	{ 0x17, "PMU" },
-	{ 0x19, "MSENC", NULL, NVKM_ENGINE_MSENC },
-	{ 0x1b, "CE2", NULL, NVKM_ENGINE_CE2 },
-	{}
-};
-
-static const struct nvkm_enum
-gk104_fifo_fault_reason[] = {
-	{ 0x00, "PDE" },
-	{ 0x01, "PDE_SIZE" },
-	{ 0x02, "PTE" },
-	{ 0x03, "VA_LIMIT_VIOLATION" },
-	{ 0x04, "UNBOUND_INST_BLOCK" },
-	{ 0x05, "PRIV_VIOLATION" },
-	{ 0x06, "RO_VIOLATION" },
-	{ 0x07, "WO_VIOLATION" },
-	{ 0x08, "PITCH_MASK_VIOLATION" },
-	{ 0x09, "WORK_CREATION" },
-	{ 0x0a, "UNSUPPORTED_APERTURE" },
-	{ 0x0b, "COMPRESSION_FAILURE" },
-	{ 0x0c, "UNSUPPORTED_KIND" },
-	{ 0x0d, "REGION_VIOLATION" },
-	{ 0x0e, "BOTH_PTES_VALID" },
-	{ 0x0f, "INFO_TYPE_POISONED" },
-	{}
-};
-
-static const struct nvkm_enum
-gk104_fifo_fault_hubclient[] = {
-	{ 0x00, "VIP" },
-	{ 0x01, "CE0" },
-	{ 0x02, "CE1" },
-	{ 0x03, "DNISO" },
-	{ 0x04, "FE" },
-	{ 0x05, "FECS" },
-	{ 0x06, "HOST" },
-	{ 0x07, "HOST_CPU" },
-	{ 0x08, "HOST_CPU_NB" },
-	{ 0x09, "ISO" },
-	{ 0x0a, "MMU" },
-	{ 0x0b, "MSPDEC" },
-	{ 0x0c, "MSPPP" },
-	{ 0x0d, "MSVLD" },
-	{ 0x0e, "NISO" },
-	{ 0x0f, "P2P" },
-	{ 0x10, "PD" },
-	{ 0x11, "PERF" },
-	{ 0x12, "PMU" },
-	{ 0x13, "RASTERTWOD" },
-	{ 0x14, "SCC" },
-	{ 0x15, "SCC_NB" },
-	{ 0x16, "SEC" },
-	{ 0x17, "SSYNC" },
-	{ 0x18, "GR_CE" },
-	{ 0x19, "CE2" },
-	{ 0x1a, "XV" },
-	{ 0x1b, "MMU_NB" },
-	{ 0x1c, "MSENC" },
-	{ 0x1d, "DFALCON" },
-	{ 0x1e, "SKED" },
-	{ 0x1f, "AFALCON" },
-	{}
-};
-
-static const struct nvkm_enum
-gk104_fifo_fault_gpcclient[] = {
-	{ 0x00, "L1_0" }, { 0x01, "T1_0" }, { 0x02, "PE_0" },
-	{ 0x03, "L1_1" }, { 0x04, "T1_1" }, { 0x05, "PE_1" },
-	{ 0x06, "L1_2" }, { 0x07, "T1_2" }, { 0x08, "PE_2" },
-	{ 0x09, "L1_3" }, { 0x0a, "T1_3" }, { 0x0b, "PE_3" },
-	{ 0x0c, "RAST" },
-	{ 0x0d, "GCC" },
-	{ 0x0e, "GPCCS" },
-	{ 0x0f, "PROP_0" },
-	{ 0x10, "PROP_1" },
-	{ 0x11, "PROP_2" },
-	{ 0x12, "PROP_3" },
-	{ 0x13, "L1_4" }, { 0x14, "T1_4" }, { 0x15, "PE_4" },
-	{ 0x16, "L1_5" }, { 0x17, "T1_5" }, { 0x18, "PE_5" },
-	{ 0x19, "L1_6" }, { 0x1a, "T1_6" }, { 0x1b, "PE_6" },
-	{ 0x1c, "L1_7" }, { 0x1d, "T1_7" }, { 0x1e, "PE_7" },
-	{ 0x1f, "GPM" },
-	{ 0x20, "LTP_UTLB_0" },
-	{ 0x21, "LTP_UTLB_1" },
-	{ 0x22, "LTP_UTLB_2" },
-	{ 0x23, "LTP_UTLB_3" },
-	{ 0x24, "GPC_RGG_UTLB" },
-	{}
-};
-
 static void
 gk104_fifo_intr_fault(struct gk104_fifo *fifo, int unit)
 {
@@ -390,14 +300,14 @@ gk104_fifo_intr_fault(struct gk104_fifo
 	struct nvkm_engine *engine = NULL;
 	struct nvkm_fifo_chan *chan;
 	unsigned long flags;
-	char gpcid[8] = "";
+	char gpcid[8] = "", en[16] = "";
 
-	er = nvkm_enum_find(gk104_fifo_fault_reason, reason);
-	eu = nvkm_enum_find(gk104_fifo_fault_engine, unit);
+	er = nvkm_enum_find(fifo->func->fault.reason, reason);
+	eu = nvkm_enum_find(fifo->func->fault.engine, unit);
 	if (hub) {
-		ec = nvkm_enum_find(gk104_fifo_fault_hubclient, client);
+		ec = nvkm_enum_find(fifo->func->fault.hubclient, client);
 	} else {
-		ec = nvkm_enum_find(gk104_fifo_fault_gpcclient, client);
+		ec = nvkm_enum_find(fifo->func->fault.gpcclient, client);
 		snprintf(gpcid, sizeof(gpcid), "GPC%d/", gpc);
 	}
 
@@ -418,13 +328,27 @@ gk104_fifo_intr_fault(struct gk104_fifo
 		}
 	}
 
+	if (eu == NULL) {
+		enum nvkm_devidx engidx = nvkm_top_fault(device->top, unit);
+		if (engidx < NVKM_SUBDEV_NR) {
+			const char *src = nvkm_subdev_name[engidx];
+			char *dst = en;
+			do {
+				*dst++ = toupper(*src++);
+			} while(*src);
+			engine = nvkm_device_engine(device, engidx);
+		}
+	} else {
+		snprintf(en, sizeof(en), "%s", eu->name);
+	}
+
 	chan = nvkm_fifo_chan_inst(&fifo->base, (u64)inst << 12, &flags);
 
 	nvkm_error(subdev,
 		   "%s fault at %010llx engine %02x [%s] client %02x [%s%s] "
 		   "reason %02x [%s] on channel %d [%010llx %s]\n",
 		   write ? "write" : "read", (u64)vahi << 32 | valo,
-		   unit, eu ? eu->name : "", client, gpcid, ec ? ec->name : "",
+		   unit, en, client, gpcid, ec ? ec->name : "",
 		   reason, er ? er->name : "", chan ? chan->chid : -1,
 		   (u64)inst << 12,
 		   chan ? chan->object.client->name : "unknown");
@@ -557,7 +481,7 @@ gk104_fifo_intr_engine(struct gk104_fifo
 	nvkm_fifo_uevent(&fifo->base);
 }
 
-void
+static void
 gk104_fifo_intr(struct nvkm_fifo *base)
 {
 	struct gk104_fifo *fifo = gk104_fifo(base);
@@ -649,7 +573,7 @@ gk104_fifo_intr(struct nvkm_fifo *base)
 	}
 }
 
-void
+static void
 gk104_fifo_fini(struct nvkm_fifo *base)
 {
 	struct gk104_fifo *fifo = gk104_fifo(base);
@@ -659,13 +583,15 @@ gk104_fifo_fini(struct nvkm_fifo *base)
 	nvkm_mask(device, 0x002140, 0x10000000, 0x10000000);
 }
 
-int
+static int
 gk104_fifo_oneinit(struct nvkm_fifo *base)
 {
 	struct gk104_fifo *fifo = gk104_fifo(base);
 	struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
 	struct nvkm_device *device = subdev->device;
-	int ret, i;
+	struct nvkm_top *top = device->top;
+	int engn, runl, pbid, ret, i, j;
+	enum nvkm_devidx engidx;
 	u32 *map;
 
 	/* Determine number of PBDMAs by checking valid enable bits. */
@@ -680,86 +606,26 @@ gk104_fifo_oneinit(struct nvkm_fifo *bas
 	for (i = 0; i < fifo->pbdma_nr; i++)
 		map[i] = nvkm_rd32(device, 0x002390 + (i * 0x04));
 
-	/* Read device topology from HW. */
-	for (i = 0; i < 64; i++) {
-		int type = -1, pbid = -1, engidx = -1;
-		int engn = -1, runl = -1, intr = -1, mcen = -1;
-		int fault = -1, j;
-		u32 data, addr = 0;
-
-		do {
-			data = nvkm_rd32(device, 0x022700 + (i * 0x04));
-			nvkm_trace(subdev, "%02x: %08x\n", i, data);
-			switch (data & 0x00000003) {
-			case 0x00000000: /* NOT_VALID */
-				continue;
-			case 0x00000001: /* DATA */
-				addr  = (data & 0x00fff000);
-				fault = (data & 0x000000f8) >> 3;
-				break;
-			case 0x00000002: /* ENUM */
-				if (data & 0x00000020)
-					engn = (data & 0x3c000000) >> 26;
-				if (data & 0x00000010)
-					runl = (data & 0x01e00000) >> 21;
-				if (data & 0x00000008)
-					intr = (data & 0x000f8000) >> 15;
-				if (data & 0x00000004)
-					mcen = (data & 0x00003e00) >> 9;
-				break;
-			case 0x00000003: /* ENGINE_TYPE */
-				type = (data & 0x7ffffffc) >> 2;
-				break;
-			}
-		} while ((data & 0x80000000) && ++i < 64);
-
-		if (!data)
-			continue;
-
+	/* Determine runlist configuration from topology device info. */
+	i = 0;
+	while ((int)(engidx = nvkm_top_engine(top, i++, &runl, &engn)) >= 0) {
 		/* Determine which PBDMA handles requests for this engine. */
-		for (j = 0; runl >= 0 && j < fifo->pbdma_nr; j++) {
+		for (j = 0, pbid = -1; j < fifo->pbdma_nr; j++) {
 			if (map[j] & (1 << runl)) {
 				pbid = j;
 				break;
 			}
 		}
 
-		/* Translate engine type to NVKM engine identifier. */
-		switch (type) {
-		case 0x00000000: engidx = NVKM_ENGINE_GR; break;
-		case 0x00000001: engidx = NVKM_ENGINE_CE0; break;
-		case 0x00000002: engidx = NVKM_ENGINE_CE1; break;
-		case 0x00000003: engidx = NVKM_ENGINE_CE2; break;
-		case 0x00000008: engidx = NVKM_ENGINE_MSPDEC; break;
-		case 0x00000009: engidx = NVKM_ENGINE_MSPPP; break;
-		case 0x0000000a: engidx = NVKM_ENGINE_MSVLD; break;
-		case 0x0000000b: engidx = NVKM_ENGINE_MSENC; break;
-		case 0x0000000c: engidx = NVKM_ENGINE_VIC; break;
-		case 0x0000000d: engidx = NVKM_ENGINE_SEC; break;
-		case 0x0000000e: engidx = NVKM_ENGINE_NVENC0; break;
-		case 0x0000000f: engidx = NVKM_ENGINE_NVENC1; break;
-		case 0x00000010: engidx = NVKM_ENGINE_NVDEC; break;
-			break;
-		default:
-			break;
-		}
-
-		nvkm_debug(subdev, "%02x (%8s): engine %2d runlist %2d "
-				   "pbdma %2d intr %2d reset %2d "
-				   "fault %2d addr %06x\n", type,
-			   engidx < 0 ? NULL : nvkm_subdev_name[engidx],
-			   engn, runl, pbid, intr, mcen, fault, addr);
+		nvkm_debug(subdev, "engine %2d: runlist %2d pbdma %2d\n",
+			   engn, runl, pbid);
 
-		/* Mark the engine as supported if everything checks out. */
-		if (engn >= 0 && runl >= 0) {
-			fifo->engine[engn].engine = engidx < 0 ? NULL :
-				nvkm_device_engine(device, engidx);
-			fifo->engine[engn].runl = runl;
-			fifo->engine[engn].pbid = pbid;
-			fifo->engine_nr = max(fifo->engine_nr, engn + 1);
-			fifo->runlist[runl].engm |= 1 << engn;
-			fifo->runlist_nr = max(fifo->runlist_nr, runl + 1);
-		}
+		fifo->engine[engn].engine = nvkm_device_engine(device, engidx);
+		fifo->engine[engn].runl = runl;
+		fifo->engine[engn].pbid = pbid;
+		fifo->engine_nr = max(fifo->engine_nr, engn + 1);
+		fifo->runlist[runl].engm |= 1 << engn;
+		fifo->runlist_nr = max(fifo->runlist_nr, runl + 1);
 	}
 
 	kfree(map);
@@ -796,7 +662,7 @@ gk104_fifo_oneinit(struct nvkm_fifo *bas
 	return 0;
 }
 
-void
+static void
 gk104_fifo_init(struct nvkm_fifo *base)
 {
 	struct gk104_fifo *fifo = gk104_fifo(base);
@@ -825,7 +691,7 @@ gk104_fifo_init(struct nvkm_fifo *base)
 	nvkm_wr32(device, 0x002140, 0x7fffffff);
 }
 
-void *
+static void *
 gk104_fifo_dtor(struct nvkm_fifo *base)
 {
 	struct gk104_fifo *fifo = gk104_fifo(base);
@@ -842,29 +708,154 @@ gk104_fifo_dtor(struct nvkm_fifo *base)
 	return fifo;
 }
 
+static const struct nvkm_fifo_func
+gk104_fifo_ = {
+	.dtor = gk104_fifo_dtor,
+	.oneinit = gk104_fifo_oneinit,
+	.init = gk104_fifo_init,
+	.fini = gk104_fifo_fini,
+	.intr = gk104_fifo_intr,
+	.uevent_init = gk104_fifo_uevent_init,
+	.uevent_fini = gk104_fifo_uevent_fini,
+	.class_get = gk104_fifo_class_get,
+};
+
 int
-gk104_fifo_new_(const struct nvkm_fifo_func *func, struct nvkm_device *device,
+gk104_fifo_new_(const struct gk104_fifo_func *func, struct nvkm_device *device,
 		int index, int nr, struct nvkm_fifo **pfifo)
 {
 	struct gk104_fifo *fifo;
 
 	if (!(fifo = kzalloc(sizeof(*fifo), GFP_KERNEL)))
 		return -ENOMEM;
+	fifo->func = func;
 	INIT_WORK(&fifo->recover.work, gk104_fifo_recover_work);
 	*pfifo = &fifo->base;
 
-	return nvkm_fifo_ctor(func, device, index, nr, &fifo->base);
+	return nvkm_fifo_ctor(&gk104_fifo_, device, index, nr, &fifo->base);
 }
 
-static const struct nvkm_fifo_func
+const struct nvkm_enum
+gk104_fifo_fault_engine[] = {
+	{ 0x00, "GR", NULL, NVKM_ENGINE_GR },
+	{ 0x01, "DISPLAY" },
+	{ 0x02, "CAPTURE" },
+	{ 0x03, "IFB", NULL, NVKM_ENGINE_IFB },
+	{ 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR },
+	{ 0x05, "BAR2", NULL, NVKM_SUBDEV_INSTMEM },
+	{ 0x06, "SCHED" },
+	{ 0x07, "HOST0" },
+	{ 0x08, "HOST1" },
+	{ 0x09, "HOST2" },
+	{ 0x0a, "HOST3" },
+	{ 0x0b, "HOST4" },
+	{ 0x0c, "HOST5" },
+	{ 0x0d, "HOST6" },
+	{ 0x0e, "HOST7" },
+	{ 0x0f, "HOSTSR" },
+	{ 0x10, "MSVLD", NULL, NVKM_ENGINE_MSVLD },
+	{ 0x11, "MSPPP", NULL, NVKM_ENGINE_MSPPP },
+	{ 0x13, "PERF" },
+	{ 0x14, "MSPDEC", NULL, NVKM_ENGINE_MSPDEC },
+	{ 0x15, "CE0", NULL, NVKM_ENGINE_CE0 },
+	{ 0x16, "CE1", NULL, NVKM_ENGINE_CE1 },
+	{ 0x17, "PMU" },
+	{ 0x18, "PTP" },
+	{ 0x19, "MSENC", NULL, NVKM_ENGINE_MSENC },
+	{ 0x1b, "CE2", NULL, NVKM_ENGINE_CE2 },
+	{}
+};
+
+const struct nvkm_enum
+gk104_fifo_fault_reason[] = {
+	{ 0x00, "PDE" },
+	{ 0x01, "PDE_SIZE" },
+	{ 0x02, "PTE" },
+	{ 0x03, "VA_LIMIT_VIOLATION" },
+	{ 0x04, "UNBOUND_INST_BLOCK" },
+	{ 0x05, "PRIV_VIOLATION" },
+	{ 0x06, "RO_VIOLATION" },
+	{ 0x07, "WO_VIOLATION" },
+	{ 0x08, "PITCH_MASK_VIOLATION" },
+	{ 0x09, "WORK_CREATION" },
+	{ 0x0a, "UNSUPPORTED_APERTURE" },
+	{ 0x0b, "COMPRESSION_FAILURE" },
+	{ 0x0c, "UNSUPPORTED_KIND" },
+	{ 0x0d, "REGION_VIOLATION" },
+	{ 0x0e, "BOTH_PTES_VALID" },
+	{ 0x0f, "INFO_TYPE_POISONED" },
+	{}
+};
+
+const struct nvkm_enum
+gk104_fifo_fault_hubclient[] = {
+	{ 0x00, "VIP" },
+	{ 0x01, "CE0" },
+	{ 0x02, "CE1" },
+	{ 0x03, "DNISO" },
+	{ 0x04, "FE" },
+	{ 0x05, "FECS" },
+	{ 0x06, "HOST" },
+	{ 0x07, "HOST_CPU" },
+	{ 0x08, "HOST_CPU_NB" },
+	{ 0x09, "ISO" },
+	{ 0x0a, "MMU" },
+	{ 0x0b, "MSPDEC" },
+	{ 0x0c, "MSPPP" },
+	{ 0x0d, "MSVLD" },
+	{ 0x0e, "NISO" },
+	{ 0x0f, "P2P" },
+	{ 0x10, "PD" },
+	{ 0x11, "PERF" },
+	{ 0x12, "PMU" },
+	{ 0x13, "RASTERTWOD" },
+	{ 0x14, "SCC" },
+	{ 0x15, "SCC_NB" },
+	{ 0x16, "SEC" },
+	{ 0x17, "SSYNC" },
+	{ 0x18, "GR_CE" },
+	{ 0x19, "CE2" },
+	{ 0x1a, "XV" },
+	{ 0x1b, "MMU_NB" },
+	{ 0x1c, "MSENC" },
+	{ 0x1d, "DFALCON" },
+	{ 0x1e, "SKED" },
+	{ 0x1f, "AFALCON" },
+	{}
+};
+
+const struct nvkm_enum
+gk104_fifo_fault_gpcclient[] = {
+	{ 0x00, "L1_0" }, { 0x01, "T1_0" }, { 0x02, "PE_0" },
+	{ 0x03, "L1_1" }, { 0x04, "T1_1" }, { 0x05, "PE_1" },
+	{ 0x06, "L1_2" }, { 0x07, "T1_2" }, { 0x08, "PE_2" },
+	{ 0x09, "L1_3" }, { 0x0a, "T1_3" }, { 0x0b, "PE_3" },
+	{ 0x0c, "RAST" },
+	{ 0x0d, "GCC" },
+	{ 0x0e, "GPCCS" },
+	{ 0x0f, "PROP_0" },
+	{ 0x10, "PROP_1" },
+	{ 0x11, "PROP_2" },
+	{ 0x12, "PROP_3" },
+	{ 0x13, "L1_4" }, { 0x14, "T1_4" }, { 0x15, "PE_4" },
+	{ 0x16, "L1_5" }, { 0x17, "T1_5" }, { 0x18, "PE_5" },
+	{ 0x19, "L1_6" }, { 0x1a, "T1_6" }, { 0x1b, "PE_6" },
+	{ 0x1c, "L1_7" }, { 0x1d, "T1_7" }, { 0x1e, "PE_7" },
+	{ 0x1f, "GPM" },
+	{ 0x20, "LTP_UTLB_0" },
+	{ 0x21, "LTP_UTLB_1" },
+	{ 0x22, "LTP_UTLB_2" },
+	{ 0x23, "LTP_UTLB_3" },
+	{ 0x24, "GPC_RGG_UTLB" },
+	{}
+};
+
+static const struct gk104_fifo_func
 gk104_fifo = {
-	.dtor = gk104_fifo_dtor,
-	.oneinit = gk104_fifo_oneinit,
-	.init = gk104_fifo_init,
-	.fini = gk104_fifo_fini,
-	.intr = gk104_fifo_intr,
-	.uevent_init = gk104_fifo_uevent_init,
-	.uevent_fini = gk104_fifo_uevent_fini,
+	.fault.engine = gk104_fifo_fault_engine,
+	.fault.reason = gk104_fifo_fault_reason,
+	.fault.hubclient = gk104_fifo_fault_hubclient,
+	.fault.gpcclient = gk104_fifo_fault_gpcclient,
 	.chan = {
 		&gk104_fifo_gpfifo_oclass,
 		NULL
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h	2016-07-24 15:23:50.000000000 -0400
@@ -3,10 +3,12 @@
 #define gk104_fifo(p) container_of((p), struct gk104_fifo, base)
 #include "priv.h"
 
+#include <core/enum.h>
 #include <subdev/mmu.h>
 
 struct gk104_fifo_chan;
 struct gk104_fifo {
+	const struct gk104_fifo_func *func;
 	struct nvkm_fifo base;
 
 	struct {
@@ -39,15 +41,19 @@ struct gk104_fifo {
 	} user;
 };
 
-int gk104_fifo_new_(const struct nvkm_fifo_func *, struct nvkm_device *,
+struct gk104_fifo_func {
+	struct {
+		const struct nvkm_enum *engine;
+		const struct nvkm_enum *reason;
+		const struct nvkm_enum *hubclient;
+		const struct nvkm_enum *gpcclient;
+	} fault;
+
+	const struct nvkm_fifo_chan_oclass *chan[];
+};
+
+int gk104_fifo_new_(const struct gk104_fifo_func *, struct nvkm_device *,
 		    int index, int nr, struct nvkm_fifo **);
-void *gk104_fifo_dtor(struct nvkm_fifo *);
-int gk104_fifo_oneinit(struct nvkm_fifo *);
-void gk104_fifo_init(struct nvkm_fifo *);
-void gk104_fifo_fini(struct nvkm_fifo *);
-void gk104_fifo_intr(struct nvkm_fifo *);
-void gk104_fifo_uevent_init(struct nvkm_fifo *);
-void gk104_fifo_uevent_fini(struct nvkm_fifo *);
 void gk104_fifo_runlist_insert(struct gk104_fifo *, struct gk104_fifo_chan *);
 void gk104_fifo_runlist_remove(struct gk104_fifo *, struct gk104_fifo_chan *);
 void gk104_fifo_runlist_commit(struct gk104_fifo *, int runl);
@@ -70,4 +76,11 @@ gk104_fifo_engine_subdev(int engine)
 		return 0;
 	}
 }
+
+extern const struct nvkm_enum gk104_fifo_fault_engine[];
+extern const struct nvkm_enum gk104_fifo_fault_reason[];
+extern const struct nvkm_enum gk104_fifo_fault_hubclient[];
+extern const struct nvkm_enum gk104_fifo_fault_gpcclient[];
+
+extern const struct nvkm_enum gm107_fifo_fault_engine[];
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c	2016-07-24 15:23:50.000000000 -0400
@@ -24,15 +24,12 @@
 #include "gk104.h"
 #include "changk104.h"
 
-static const struct nvkm_fifo_func
+static const struct gk104_fifo_func
 gk110_fifo = {
-	.dtor = gk104_fifo_dtor,
-	.oneinit = gk104_fifo_oneinit,
-	.init = gk104_fifo_init,
-	.fini = gk104_fifo_fini,
-	.intr = gk104_fifo_intr,
-	.uevent_init = gk104_fifo_uevent_init,
-	.uevent_fini = gk104_fifo_uevent_fini,
+	.fault.engine = gk104_fifo_fault_engine,
+	.fault.reason = gk104_fifo_fault_reason,
+	.fault.hubclient = gk104_fifo_fault_hubclient,
+	.fault.gpcclient = gk104_fifo_fault_gpcclient,
 	.chan = {
 		&gk110_fifo_gpfifo_oclass,
 		NULL
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c	2016-07-24 15:23:50.000000000 -0400
@@ -24,15 +24,12 @@
 #include "gk104.h"
 #include "changk104.h"
 
-static const struct nvkm_fifo_func
+static const struct gk104_fifo_func
 gk208_fifo = {
-	.dtor = gk104_fifo_dtor,
-	.oneinit = gk104_fifo_oneinit,
-	.init = gk104_fifo_init,
-	.fini = gk104_fifo_fini,
-	.intr = gk104_fifo_intr,
-	.uevent_init = gk104_fifo_uevent_init,
-	.uevent_fini = gk104_fifo_uevent_fini,
+	.fault.engine = gk104_fifo_fault_engine,
+	.fault.reason = gk104_fifo_fault_reason,
+	.fault.hubclient = gk104_fifo_fault_hubclient,
+	.fault.gpcclient = gk104_fifo_fault_gpcclient,
 	.chan = {
 		&gk104_fifo_gpfifo_oclass,
 		NULL
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c	2016-07-24 15:23:50.000000000 -0400
@@ -22,15 +22,12 @@
 #include "gk104.h"
 #include "changk104.h"
 
-static const struct nvkm_fifo_func
+static const struct gk104_fifo_func
 gk20a_fifo = {
-	.dtor = gk104_fifo_dtor,
-	.oneinit = gk104_fifo_oneinit,
-	.init = gk104_fifo_init,
-	.fini = gk104_fifo_fini,
-	.intr = gk104_fifo_intr,
-	.uevent_init = gk104_fifo_uevent_init,
-	.uevent_fini = gk104_fifo_uevent_fini,
+	.fault.engine = gk104_fifo_fault_engine,
+	.fault.reason = gk104_fifo_fault_reason,
+	.fault.hubclient = gk104_fifo_fault_hubclient,
+	.fault.gpcclient = gk104_fifo_fault_gpcclient,
 	.chan = {
 		&gk104_fifo_gpfifo_oclass,
 		NULL
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c	2016-07-24 15:23:50.000000000 -0400
@@ -24,15 +24,35 @@
 #include "gk104.h"
 #include "changk104.h"
 
-static const struct nvkm_fifo_func
+const struct nvkm_enum
+gm107_fifo_fault_engine[] = {
+	{ 0x01, "DISPLAY" },
+	{ 0x02, "CAPTURE" },
+	{ 0x03, "IFB", NULL, NVKM_ENGINE_IFB },
+	{ 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR },
+	{ 0x05, "BAR2", NULL, NVKM_SUBDEV_INSTMEM },
+	{ 0x06, "SCHED" },
+	{ 0x07, "HOST0" },
+	{ 0x08, "HOST1" },
+	{ 0x09, "HOST2" },
+	{ 0x0a, "HOST3" },
+	{ 0x0b, "HOST4" },
+	{ 0x0c, "HOST5" },
+	{ 0x0d, "HOST6" },
+	{ 0x0e, "HOST7" },
+	{ 0x0f, "HOSTSR" },
+	{ 0x13, "PERF" },
+	{ 0x17, "PMU" },
+	{ 0x18, "PTP" },
+	{}
+};
+
+static const struct gk104_fifo_func
 gm107_fifo = {
-	.dtor = gk104_fifo_dtor,
-	.oneinit = gk104_fifo_oneinit,
-	.init = gk104_fifo_init,
-	.fini = gk104_fifo_fini,
-	.intr = gk104_fifo_intr,
-	.uevent_init = gk104_fifo_uevent_init,
-	.uevent_fini = gk104_fifo_uevent_fini,
+	.fault.engine = gm107_fifo_fault_engine,
+	.fault.reason = gk104_fifo_fault_reason,
+	.fault.hubclient = gk104_fifo_fault_hubclient,
+	.fault.gpcclient = gk104_fifo_fault_gpcclient,
 	.chan = {
 		&gk110_fifo_gpfifo_oclass,
 		NULL
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c	2016-07-24 15:23:50.000000000 -0400
@@ -24,15 +24,12 @@
 #include "gk104.h"
 #include "changk104.h"
 
-static const struct nvkm_fifo_func
+static const struct gk104_fifo_func
 gm200_fifo = {
-	.dtor = gk104_fifo_dtor,
-	.oneinit = gk104_fifo_oneinit,
-	.init = gk104_fifo_init,
-	.fini = gk104_fifo_fini,
-	.intr = gk104_fifo_intr,
-	.uevent_init = gk104_fifo_uevent_init,
-	.uevent_fini = gk104_fifo_uevent_fini,
+	.fault.engine = gm107_fifo_fault_engine,
+	.fault.reason = gk104_fifo_fault_reason,
+	.fault.hubclient = gk104_fifo_fault_hubclient,
+	.fault.gpcclient = gk104_fifo_fault_gpcclient,
 	.chan = {
 		&gm200_fifo_gpfifo_oclass,
 		NULL
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm20b.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm20b.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm20b.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm20b.c	2016-07-24 15:23:50.000000000 -0400
@@ -22,15 +22,12 @@
 #include "gk104.h"
 #include "changk104.h"
 
-static const struct nvkm_fifo_func
+static const struct gk104_fifo_func
 gm20b_fifo = {
-	.dtor = gk104_fifo_dtor,
-	.oneinit = gk104_fifo_oneinit,
-	.init = gk104_fifo_init,
-	.fini = gk104_fifo_fini,
-	.intr = gk104_fifo_intr,
-	.uevent_init = gk104_fifo_uevent_init,
-	.uevent_fini = gk104_fifo_uevent_fini,
+	.fault.engine = gm107_fifo_fault_engine,
+	.fault.reason = gk104_fifo_fault_reason,
+	.fault.hubclient = gk104_fifo_fault_hubclient,
+	.fault.gpcclient = gk104_fifo_fault_gpcclient,
 	.chan = {
 		&gm200_fifo_gpfifo_oclass,
 		NULL
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h	2016-07-24 15:23:50.000000000 -0400
@@ -7,6 +7,7 @@ int nvkm_fifo_ctor(const struct nvkm_fif
 		   int index, int nr, struct nvkm_fifo *);
 void nvkm_fifo_uevent(struct nvkm_fifo *);
 
+struct nvkm_fifo_chan_oclass;
 struct nvkm_fifo_func {
 	void *(*dtor)(struct nvkm_fifo *);
 	int (*oneinit)(struct nvkm_fifo *);
@@ -17,6 +18,8 @@ struct nvkm_fifo_func {
 	void (*start)(struct nvkm_fifo *, unsigned long *);
 	void (*uevent_init)(struct nvkm_fifo *);
 	void (*uevent_fini)(struct nvkm_fifo *);
+	int (*class_get)(struct nvkm_fifo *, int index,
+			 const struct nvkm_fifo_chan_oclass **);
 	const struct nvkm_fifo_chan_oclass *chan[];
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/base.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/base.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/base.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/base.c	2016-07-24 15:23:50.000000000 -0400
@@ -128,9 +128,8 @@ nvkm_gr = {
 
 int
 nvkm_gr_ctor(const struct nvkm_gr_func *func, struct nvkm_device *device,
-	     int index, u32 pmc_enable, bool enable, struct nvkm_gr *gr)
+	     int index, bool enable, struct nvkm_gr *gr)
 {
 	gr->func = func;
-	return nvkm_engine_ctor(&nvkm_gr, device, index, pmc_enable,
-				enable, &gr->engine);
+	return nvkm_engine_ctor(&nvkm_gr, device, index, enable, &gr->engine);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c	2016-07-24 15:23:50.000000000 -0400
@@ -1181,20 +1181,20 @@ gf100_grctx_generate_r418bb8(struct gf10
 
 	/* GPC_BROADCAST */
 	nvkm_wr32(device, 0x418bb8, (gr->tpc_total << 8) |
-				 gr->magic_not_rop_nr);
+				     gr->screen_tile_row_offset);
 	for (i = 0; i < 6; i++)
 		nvkm_wr32(device, 0x418b08 + (i * 4), data[i]);
 
 	/* GPC_BROADCAST.TP_BROADCAST */
 	nvkm_wr32(device, 0x419bd0, (gr->tpc_total << 8) |
-				 gr->magic_not_rop_nr | data2[0]);
+				     gr->screen_tile_row_offset | data2[0]);
 	nvkm_wr32(device, 0x419be4, data2[1]);
 	for (i = 0; i < 6; i++)
 		nvkm_wr32(device, 0x419b00 + (i * 4), data[i]);
 
 	/* UNK78xx */
 	nvkm_wr32(device, 0x4078bc, (gr->tpc_total << 8) |
-				 gr->magic_not_rop_nr);
+				     gr->screen_tile_row_offset);
 	for (i = 0; i < 6; i++)
 		nvkm_wr32(device, 0x40780c + (i * 4), data[i]);
 }
@@ -1238,6 +1238,7 @@ gf100_grctx_generate_main(struct gf100_g
 {
 	struct nvkm_device *device = gr->base.engine.subdev.device;
 	const struct gf100_grctx_func *grctx = gr->func->grctx;
+	u32 idle_timeout;
 
 	nvkm_mc_unk260(device->mc, 0);
 
@@ -1247,7 +1248,7 @@ gf100_grctx_generate_main(struct gf100_g
 	gf100_gr_mmio(gr, grctx->tpc);
 	gf100_gr_mmio(gr, grctx->ppc);
 
-	nvkm_wr32(device, 0x404154, 0x00000000);
+	idle_timeout = nvkm_mask(device, 0x404154, 0xffffffff, 0x00000000);
 
 	grctx->bundle(info);
 	grctx->pagepool(info);
@@ -1261,7 +1262,7 @@ gf100_grctx_generate_main(struct gf100_g
 	gf100_grctx_generate_r406800(gr);
 
 	gf100_gr_icmd(gr, grctx->icmd);
-	nvkm_wr32(device, 0x404154, 0x00000400);
+	nvkm_wr32(device, 0x404154, idle_timeout);
 	gf100_gr_mthd(gr, grctx->mthd);
 	nvkm_mc_unk260(device->mc, 1);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h	2016-07-24 15:23:50.000000000 -0400
@@ -81,8 +81,6 @@ void gk104_grctx_generate_bundle(struct
 void gk104_grctx_generate_pagepool(struct gf100_grctx *);
 void gk104_grctx_generate_unkn(struct gf100_gr *);
 void gk104_grctx_generate_r418bb8(struct gf100_gr *);
-void gk104_grctx_generate_rop_active_fbps(struct gf100_gr *);
-
 
 void gm107_grctx_generate_bundle(struct gf100_grctx *);
 void gm107_grctx_generate_pagepool(struct gf100_grctx *);
@@ -98,7 +96,6 @@ void gm107_grctx_generate_pagepool(struc
 void gm107_grctx_generate_attrib(struct gf100_grctx *);
 
 extern const struct gf100_grctx_func gm200_grctx;
-void gm200_grctx_generate_main(struct gf100_gr *, struct gf100_grctx *);
 void gm200_grctx_generate_tpcid(struct gf100_gr *);
 void gm200_grctx_generate_405b60(struct gf100_gr *);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c	2016-07-24 15:23:50.000000000 -0400
@@ -223,6 +223,7 @@ gf117_grctx_generate_main(struct gf100_g
 {
 	struct nvkm_device *device = gr->base.engine.subdev.device;
 	const struct gf100_grctx_func *grctx = gr->func->grctx;
+	u32 idle_timeout;
 	int i;
 
 	nvkm_mc_unk260(device->mc, 0);
@@ -233,7 +234,7 @@ gf117_grctx_generate_main(struct gf100_g
 	gf100_gr_mmio(gr, grctx->tpc);
 	gf100_gr_mmio(gr, grctx->ppc);
 
-	nvkm_wr32(device, 0x404154, 0x00000000);
+	idle_timeout = nvkm_mask(device, 0x404154, 0xffffffff, 0x00000000);
 
 	grctx->bundle(info);
 	grctx->pagepool(info);
@@ -250,7 +251,7 @@ gf117_grctx_generate_main(struct gf100_g
 		nvkm_wr32(device, 0x4064d0 + (i * 0x04), 0x00000000);
 
 	gf100_gr_icmd(gr, grctx->icmd);
-	nvkm_wr32(device, 0x404154, 0x00000400);
+	nvkm_wr32(device, 0x404154, idle_timeout);
 	gf100_gr_mthd(gr, grctx->mthd);
 	nvkm_mc_unk260(device->mc, 1);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c	2016-07-24 15:23:50.000000000 -0400
@@ -924,38 +924,30 @@ gk104_grctx_generate_r418bb8(struct gf10
 
 	/* GPC_BROADCAST */
 	nvkm_wr32(device, 0x418bb8, (gr->tpc_total << 8) |
-				 gr->magic_not_rop_nr);
+				     gr->screen_tile_row_offset);
 	for (i = 0; i < 6; i++)
 		nvkm_wr32(device, 0x418b08 + (i * 4), data[i]);
 
 	/* GPC_BROADCAST.TP_BROADCAST */
 	nvkm_wr32(device, 0x41bfd0, (gr->tpc_total << 8) |
-				 gr->magic_not_rop_nr | data2[0]);
+				     gr->screen_tile_row_offset | data2[0]);
 	nvkm_wr32(device, 0x41bfe4, data2[1]);
 	for (i = 0; i < 6; i++)
 		nvkm_wr32(device, 0x41bf00 + (i * 4), data[i]);
 
 	/* UNK78xx */
 	nvkm_wr32(device, 0x4078bc, (gr->tpc_total << 8) |
-				 gr->magic_not_rop_nr);
+				     gr->screen_tile_row_offset);
 	for (i = 0; i < 6; i++)
 		nvkm_wr32(device, 0x40780c + (i * 4), data[i]);
 }
 
 void
-gk104_grctx_generate_rop_active_fbps(struct gf100_gr *gr)
-{
-	struct nvkm_device *device = gr->base.engine.subdev.device;
-	const u32 fbp_count = nvkm_rd32(device, 0x120074);
-	nvkm_mask(device, 0x408850, 0x0000000f, fbp_count); /* zrop */
-	nvkm_mask(device, 0x408958, 0x0000000f, fbp_count); /* crop */
-}
-
-void
 gk104_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info)
 {
 	struct nvkm_device *device = gr->base.engine.subdev.device;
 	const struct gf100_grctx_func *grctx = gr->func->grctx;
+	u32 idle_timeout;
 	int i;
 
 	nvkm_mc_unk260(device->mc, 0);
@@ -966,7 +958,7 @@ gk104_grctx_generate_main(struct gf100_g
 	gf100_gr_mmio(gr, grctx->tpc);
 	gf100_gr_mmio(gr, grctx->ppc);
 
-	nvkm_wr32(device, 0x404154, 0x00000000);
+	idle_timeout = nvkm_mask(device, 0x404154, 0xffffffff, 0x00000000);
 
 	grctx->bundle(info);
 	grctx->pagepool(info);
@@ -982,11 +974,10 @@ gk104_grctx_generate_main(struct gf100_g
 		nvkm_wr32(device, 0x4064d0 + (i * 0x04), 0x00000000);
 
 	nvkm_wr32(device, 0x405b00, (gr->tpc_total << 8) | gr->gpc_nr);
-	gk104_grctx_generate_rop_active_fbps(gr);
 	nvkm_mask(device, 0x419f78, 0x00000001, 0x00000000);
 
 	gf100_gr_icmd(gr, grctx->icmd);
-	nvkm_wr32(device, 0x404154, 0x00000400);
+	nvkm_wr32(device, 0x404154, idle_timeout);
 	gf100_gr_mthd(gr, grctx->mthd);
 	nvkm_mc_unk260(device->mc, 1);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c	2016-07-24 15:23:50.000000000 -0400
@@ -29,15 +29,14 @@ gk20a_grctx_generate_main(struct gf100_g
 {
 	struct nvkm_device *device = gr->base.engine.subdev.device;
 	const struct gf100_grctx_func *grctx = gr->func->grctx;
-	int idle_timeout_save;
+	u32 idle_timeout;
 	int i;
 
 	gf100_gr_mmio(gr, gr->fuc_sw_ctx);
 
 	gf100_gr_wait_idle(gr);
 
-	idle_timeout_save = nvkm_rd32(device, 0x404154);
-	nvkm_wr32(device, 0x404154, 0x00000000);
+	idle_timeout = nvkm_mask(device, 0x404154, 0xffffffff, 0x00000000);
 
 	grctx->attrib(info);
 
@@ -53,13 +52,11 @@ gk20a_grctx_generate_main(struct gf100_g
 
 	nvkm_wr32(device, 0x405b00, (gr->tpc_total << 8) | gr->gpc_nr);
 
-	gk104_grctx_generate_rop_active_fbps(gr);
-
 	nvkm_mask(device, 0x5044b0, 0x08000000, 0x08000000);
 
 	gf100_gr_wait_idle(gr);
 
-	nvkm_wr32(device, 0x404154, idle_timeout_save);
+	nvkm_wr32(device, 0x404154, idle_timeout);
 	gf100_gr_wait_idle(gr);
 
 	gf100_gr_mthd(gr, gr->fuc_method);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c	2016-07-24 15:23:50.000000000 -0400
@@ -920,13 +920,15 @@ gm107_grctx_generate_attrib(struct gf100
 			const u32 bs = attrib * gr->ppc_tpc_nr[gpc][ppc];
 			const u32 u = 0x418ea0 + (n * 0x04);
 			const u32 o = PPC_UNIT(gpc, ppc, 0);
+			if (!(gr->ppc_mask[gpc] & (1 << ppc)))
+				continue;
 			mmio_wr32(info, o + 0xc0, bs);
 			mmio_wr32(info, o + 0xf4, bo);
 			bo += grctx->attrib_nr_max * gr->ppc_tpc_nr[gpc][ppc];
 			mmio_wr32(info, o + 0xe4, as);
 			mmio_wr32(info, o + 0xf8, ao);
 			ao += grctx->alpha_nr_max * gr->ppc_tpc_nr[gpc][ppc];
-			mmio_wr32(info, u, ((bs / 3 /*XXX*/) << 16) | bs);
+			mmio_wr32(info, u, ((bs / 3) << 16) | bs);
 		}
 	}
 }
@@ -957,6 +959,7 @@ gm107_grctx_generate_main(struct gf100_g
 {
 	struct nvkm_device *device = gr->base.engine.subdev.device;
 	const struct gf100_grctx_func *grctx = gr->func->grctx;
+	u32 idle_timeout;
 	int i;
 
 	gf100_gr_mmio(gr, grctx->hub);
@@ -965,7 +968,7 @@ gm107_grctx_generate_main(struct gf100_g
 	gf100_gr_mmio(gr, grctx->tpc);
 	gf100_gr_mmio(gr, grctx->ppc);
 
-	nvkm_wr32(device, 0x404154, 0x00000000);
+	idle_timeout = nvkm_mask(device, 0x404154, 0xffffffff, 0x00000000);
 
 	grctx->bundle(info);
 	grctx->pagepool(info);
@@ -984,10 +987,8 @@ gm107_grctx_generate_main(struct gf100_g
 
 	nvkm_wr32(device, 0x405b00, (gr->tpc_total << 8) | gr->gpc_nr);
 
-	gk104_grctx_generate_rop_active_fbps(gr);
-
 	gf100_gr_icmd(gr, grctx->icmd);
-	nvkm_wr32(device, 0x404154, 0x00000400);
+	nvkm_wr32(device, 0x404154, idle_timeout);
 	gf100_gr_mthd(gr, grctx->mthd);
 
 	nvkm_mask(device, 0x419e00, 0x00808080, 0x00808080);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm200.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm200.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm200.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm200.c	2016-07-24 15:23:50.000000000 -0400
@@ -33,7 +33,7 @@ gm200_grctx_generate_tpcid(struct gf100_
 	struct nvkm_device *device = gr->base.engine.subdev.device;
 	int gpc, tpc, id;
 
-	for (tpc = 0, id = 0; tpc < 4; tpc++) {
+	for (tpc = 0, id = 0; tpc < TPC_MAX_PER_GPC; tpc++) {
 		for (gpc = 0; gpc < gr->gpc_nr; gpc++) {
 			if (tpc < gr->tpc_nr[gpc]) {
 				nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x698), id);
@@ -45,15 +45,6 @@ gm200_grctx_generate_tpcid(struct gf100_
 	}
 }
 
-static void
-gm200_grctx_generate_rop_active_fbps(struct gf100_gr *gr)
-{
-	struct nvkm_device *device = gr->base.engine.subdev.device;
-	const u32 fbp_count = nvkm_rd32(device, 0x12006c);
-	nvkm_mask(device, 0x408850, 0x0000000f, fbp_count); /* zrop */
-	nvkm_mask(device, 0x408958, 0x0000000f, fbp_count); /* crop */
-}
-
 void
 gm200_grctx_generate_405b60(struct gf100_gr *gr)
 {
@@ -86,17 +77,17 @@ gm200_grctx_generate_405b60(struct gf100
 		nvkm_wr32(device, 0x405ba0 + (i * 4), gpcs[i]);
 }
 
-void
+static void
 gm200_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info)
 {
 	struct nvkm_device *device = gr->base.engine.subdev.device;
 	const struct gf100_grctx_func *grctx = gr->func->grctx;
-	u32 tmp;
+	u32 idle_timeout, tmp;
 	int i;
 
 	gf100_gr_mmio(gr, gr->fuc_sw_ctx);
 
-	nvkm_wr32(device, 0x404154, 0x00000000);
+	idle_timeout = nvkm_mask(device, 0x404154, 0xffffffff, 0x00000000);
 
 	grctx->bundle(info);
 	grctx->pagepool(info);
@@ -113,8 +104,6 @@ gm200_grctx_generate_main(struct gf100_g
 
 	nvkm_wr32(device, 0x405b00, (gr->tpc_total << 8) | gr->gpc_nr);
 
-	gm200_grctx_generate_rop_active_fbps(gr);
-
 	for (tmp = 0, i = 0; i < gr->gpc_nr; i++)
 		tmp |= ((1 << gr->tpc_nr[i]) - 1) << (i * 4);
 	nvkm_wr32(device, 0x4041c4, tmp);
@@ -122,7 +111,7 @@ gm200_grctx_generate_main(struct gf100_g
 	gm200_grctx_generate_405b60(gr);
 
 	gf100_gr_icmd(gr, gr->fuc_bundle);
-	nvkm_wr32(device, 0x404154, 0x00000800);
+	nvkm_wr32(device, 0x404154, idle_timeout);
 	gf100_gr_mthd(gr, gr->fuc_method);
 
 	nvkm_mask(device, 0x418e94, 0xffffffff, 0xc4230000);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm20b.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm20b.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm20b.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm20b.c	2016-07-24 15:23:50.000000000 -0400
@@ -40,15 +40,14 @@ gm20b_grctx_generate_main(struct gf100_g
 {
 	struct nvkm_device *device = gr->base.engine.subdev.device;
 	const struct gf100_grctx_func *grctx = gr->func->grctx;
-	int idle_timeout_save;
+	u32 idle_timeout;
 	int i, tmp;
 
 	gf100_gr_mmio(gr, gr->fuc_sw_ctx);
 
 	gf100_gr_wait_idle(gr);
 
-	idle_timeout_save = nvkm_rd32(device, 0x404154);
-	nvkm_wr32(device, 0x404154, 0x00000000);
+	idle_timeout = nvkm_mask(device, 0x404154, 0xffffffff, 0x00000000);
 
 	grctx->attrib(info);
 
@@ -63,7 +62,6 @@ gm20b_grctx_generate_main(struct gf100_g
 
 	nvkm_wr32(device, 0x405b00, (gr->tpc_total << 8) | gr->gpc_nr);
 
-	gk104_grctx_generate_rop_active_fbps(gr);
 	nvkm_wr32(device, 0x408908, nvkm_rd32(device, 0x410108) | 0x80000000);
 
 	for (tmp = 0, i = 0; i < gr->gpc_nr; i++)
@@ -74,7 +72,7 @@ gm20b_grctx_generate_main(struct gf100_g
 
 	gf100_gr_wait_idle(gr);
 
-	nvkm_wr32(device, 0x404154, idle_timeout_save);
+	nvkm_wr32(device, 0x404154, idle_timeout);
 	gf100_gr_wait_idle(gr);
 
 	gf100_gr_mthd(gr, gr->fuc_method);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpc.fuc linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpc.fuc
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpc.fuc	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpc.fuc	2016-07-24 15:23:50.000000000 -0400
@@ -291,12 +291,13 @@ init:
 // Main program loop, very simple, sleeps until woken up by the interrupt
 // handler, pulls a command from the queue and executes its handler
 //
-main:
-	bset $flags $p0
+wait:
 	sleep $p0
+	bset $flags $p0
+main:
 	mov $r13 #cmd_queue
 	call(queue_get)
-	bra $p1 #main
+	bra $p1 #wait
 
 	// 0x0000-0x0003 are all context transfers
 	cmpu b32 $r14 0x04
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf100.fuc3.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf100.fuc3.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf100.fuc3.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf100.fuc3.h	2016-07-24 15:23:50.000000000 -0400
@@ -370,9 +370,10 @@ uint32_t gf100_grgpc_code[] = {
 	0xf11f29f0,
 	0xf0080007,
 	0x02d00203,
-/* 0x04bb: main */
+/* 0x04bb: wait */
 	0xf404bd00,
-	0x28f40031,
+	0x31f40028,
+/* 0x04c1: main */
 	0x1cd7f000,
 	0xf43921f4,
 	0xe4b0f401,
@@ -384,10 +385,10 @@ uint32_t gf100_grgpc_code[] = {
 	0x0018fe05,
 	0x05b421f5,
 /* 0x04eb: main_not_ctx_xfer */
-	0x94d30ef4,
+	0x94d90ef4,
 	0xf5f010ef,
 	0x7e21f501,
-	0xc60ef403,
+	0xcc0ef403,
 /* 0x04f8: ih */
 	0x80f900f9,
 	0xf90188fe,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf117.fuc3.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf117.fuc3.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf117.fuc3.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf117.fuc3.h	2016-07-24 15:23:50.000000000 -0400
@@ -397,9 +397,10 @@ uint32_t gf117_grgpc_code[] = {
 	0x080007f1,
 	0xd00203f0,
 	0x04bd0002,
-/* 0x0508: main */
-	0xf40031f4,
-	0xd7f00028,
+/* 0x0508: wait */
+	0xf40028f4,
+/* 0x050e: main */
+	0xd7f00031,
 	0x3921f424,
 	0xb0f401f4,
 	0x18f404e4,
@@ -409,13 +410,13 @@ uint32_t gf117_grgpc_code[] = {
 	0xfd01e4b6,
 	0x18fe051e,
 	0x0121f500,
-	0xd30ef406,
+	0xd90ef406,
 /* 0x0538: main_not_ctx_xfer */
 	0xf010ef94,
 	0x21f501f5,
 	0x0ef4037e,
 /* 0x0545: ih */
-	0xf900f9c6,
+	0xf900f9cc,
 	0x0188fe80,
 	0x90f980f9,
 	0xb0f9a0f9,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk104.fuc3.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk104.fuc3.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk104.fuc3.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk104.fuc3.h	2016-07-24 15:23:50.000000000 -0400
@@ -397,9 +397,10 @@ uint32_t gk104_grgpc_code[] = {
 	0x080007f1,
 	0xd00203f0,
 	0x04bd0002,
-/* 0x0508: main */
-	0xf40031f4,
-	0xd7f00028,
+/* 0x0508: wait */
+	0xf40028f4,
+/* 0x050e: main */
+	0xd7f00031,
 	0x3921f424,
 	0xb0f401f4,
 	0x18f404e4,
@@ -409,13 +410,13 @@ uint32_t gk104_grgpc_code[] = {
 	0xfd01e4b6,
 	0x18fe051e,
 	0x0121f500,
-	0xd30ef406,
+	0xd90ef406,
 /* 0x0538: main_not_ctx_xfer */
 	0xf010ef94,
 	0x21f501f5,
 	0x0ef4037e,
 /* 0x0545: ih */
-	0xf900f9c6,
+	0xf900f9cc,
 	0x0188fe80,
 	0x90f980f9,
 	0xb0f9a0f9,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk110.fuc3.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk110.fuc3.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk110.fuc3.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk110.fuc3.h	2016-07-24 15:23:50.000000000 -0400
@@ -397,9 +397,10 @@ uint32_t gk110_grgpc_code[] = {
 	0x300007f1,
 	0xd00203f0,
 	0x04bd0002,
-/* 0x0508: main */
-	0xf40031f4,
-	0xd7f00028,
+/* 0x0508: wait */
+	0xf40028f4,
+/* 0x050e: main */
+	0xd7f00031,
 	0x3921f424,
 	0xb0f401f4,
 	0x18f404e4,
@@ -409,13 +410,13 @@ uint32_t gk110_grgpc_code[] = {
 	0xfd01e4b6,
 	0x18fe051e,
 	0x0121f500,
-	0xd30ef406,
+	0xd90ef406,
 /* 0x0538: main_not_ctx_xfer */
 	0xf010ef94,
 	0x21f501f5,
 	0x0ef4037e,
 /* 0x0545: ih */
-	0xf900f9c6,
+	0xf900f9cc,
 	0x0188fe80,
 	0x90f980f9,
 	0xb0f9a0f9,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk208.fuc5.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk208.fuc5.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk208.fuc5.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk208.fuc5.h	2016-07-24 15:23:50.000000000 -0400
@@ -349,9 +349,10 @@ uint32_t gk208_grgpc_code[] = {
 	0x801f29f0,
 	0xf6023000,
 	0x04bd0002,
-/* 0x0448: main */
-	0xf40031f4,
-	0x240d0028,
+/* 0x0448: wait */
+	0xf40028f4,
+/* 0x044e: main */
+	0x240d0031,
 	0x0000377e,
 	0xb0f401f4,
 	0x18f404e4,
@@ -362,10 +363,10 @@ uint32_t gk208_grgpc_code[] = {
 	0x0018fe05,
 	0x00051f7e,
 /* 0x0477: main_not_ctx_xfer */
-	0x94d40ef4,
+	0x94da0ef4,
 	0xf5f010ef,
 	0x02f87e01,
-	0xc70ef400,
+	0xcd0ef400,
 /* 0x0484: ih */
 	0x80f900f9,
 	0xf90188fe,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgm107.fuc5.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgm107.fuc5.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgm107.fuc5.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgm107.fuc5.h	2016-07-24 15:23:50.000000000 -0400
@@ -427,9 +427,10 @@ uint32_t gm107_grgpc_code[] = {
 	0x1f29f024,
 	0x02300080,
 	0xbd0002f6,
-/* 0x0571: main */
-	0x0031f404,
-	0x0d0028f4,
+/* 0x0571: wait */
+	0x0028f404,
+/* 0x0577: main */
+	0x0d0031f4,
 	0x00377e24,
 	0xf401f400,
 	0xf404e4b0,
@@ -439,13 +440,13 @@ uint32_t gm107_grgpc_code[] = {
 	0xfd01e4b6,
 	0x18fe051e,
 	0x06487e00,
-	0xd40ef400,
+	0xda0ef400,
 /* 0x05a0: main_not_ctx_xfer */
 	0xf010ef94,
 	0xf87e01f5,
 	0x0ef40002,
 /* 0x05ad: ih */
-	0xf900f9c7,
+	0xf900f9cd,
 	0x0188fe80,
 	0x90f980f9,
 	0xb0f9a0f9,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hub.fuc linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hub.fuc
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hub.fuc	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hub.fuc	2016-07-24 15:23:50.000000000 -0400
@@ -218,13 +218,14 @@ init:
 // Main program loop, very simple, sleeps until woken up by the interrupt
 // handler, pulls a command from the queue and executes its handler
 //
-main:
+wait:
 	// sleep until we have something to do
-	bset $flags $p0
 	sleep $p0
+	bset $flags $p0
+main:
 	mov $r13 #cmd_queue
 	call(queue_get)
-	bra $p1 #main
+	bra $p1 #wait
 
 	// context switch, requested by GPU?
 	cmpu b32 $r14 0x4001
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgf100.fuc3.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgf100.fuc3.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgf100.fuc3.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgf100.fuc3.h	2016-07-24 15:23:50.000000000 -0400
@@ -584,9 +584,10 @@ uint32_t gf100_grhub_code[] = {
 	0x080007f1,
 	0xd00203f0,
 	0x04bd0001,
-/* 0x0564: main */
-	0xf40031f4,
-	0xd7f00028,
+/* 0x0564: wait */
+	0xf40028f4,
+/* 0x056a: main */
+	0xd7f00031,
 	0x3921f410,
 	0xb1f401f4,
 	0xf54001e4,
@@ -650,7 +651,7 @@ uint32_t gf100_grhub_code[] = {
 	0x170007f1,
 	0xd00203f0,
 	0x04bd0009,
-	0xff080ef5,
+	0xff0e0ef5,
 /* 0x0660: main_not_ctx_switch */
 	0xf401e4b0,
 	0xf2b90d1b,
@@ -675,12 +676,12 @@ uint32_t gf100_grhub_code[] = {
 	0xf501f5f0,
 	0xf5037e21,
 /* 0x06b3: main_done */
-	0xbdfeb50e,
+	0xbdfebb0e,
 	0x1f29f024,
 	0x080007f1,
 	0xd00203f0,
 	0x04bd0002,
-	0xfea00ef5,
+	0xfea60ef5,
 /* 0x06c8: ih */
 	0x80f900f9,
 	0xf90188fe,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgf117.fuc3.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgf117.fuc3.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgf117.fuc3.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgf117.fuc3.h	2016-07-24 15:23:50.000000000 -0400
@@ -584,9 +584,10 @@ uint32_t gf117_grhub_code[] = {
 	0x080007f1,
 	0xd00203f0,
 	0x04bd0001,
-/* 0x0564: main */
-	0xf40031f4,
-	0xd7f00028,
+/* 0x0564: wait */
+	0xf40028f4,
+/* 0x056a: main */
+	0xd7f00031,
 	0x3921f410,
 	0xb1f401f4,
 	0xf54001e4,
@@ -650,7 +651,7 @@ uint32_t gf117_grhub_code[] = {
 	0x170007f1,
 	0xd00203f0,
 	0x04bd0009,
-	0xff080ef5,
+	0xff0e0ef5,
 /* 0x0660: main_not_ctx_switch */
 	0xf401e4b0,
 	0xf2b90d1b,
@@ -675,12 +676,12 @@ uint32_t gf117_grhub_code[] = {
 	0xf501f5f0,
 	0xf5037e21,
 /* 0x06b3: main_done */
-	0xbdfeb50e,
+	0xbdfebb0e,
 	0x1f29f024,
 	0x080007f1,
 	0xd00203f0,
 	0x04bd0002,
-	0xfea00ef5,
+	0xfea60ef5,
 /* 0x06c8: ih */
 	0x80f900f9,
 	0xf90188fe,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk104.fuc3.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk104.fuc3.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk104.fuc3.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk104.fuc3.h	2016-07-24 15:23:50.000000000 -0400
@@ -584,9 +584,10 @@ uint32_t gk104_grhub_code[] = {
 	0x080007f1,
 	0xd00203f0,
 	0x04bd0001,
-/* 0x0564: main */
-	0xf40031f4,
-	0xd7f00028,
+/* 0x0564: wait */
+	0xf40028f4,
+/* 0x056a: main */
+	0xd7f00031,
 	0x3921f410,
 	0xb1f401f4,
 	0xf54001e4,
@@ -650,7 +651,7 @@ uint32_t gk104_grhub_code[] = {
 	0x170007f1,
 	0xd00203f0,
 	0x04bd0009,
-	0xff080ef5,
+	0xff0e0ef5,
 /* 0x0660: main_not_ctx_switch */
 	0xf401e4b0,
 	0xf2b90d1b,
@@ -675,12 +676,12 @@ uint32_t gk104_grhub_code[] = {
 	0xf501f5f0,
 	0xf5037e21,
 /* 0x06b3: main_done */
-	0xbdfeb50e,
+	0xbdfebb0e,
 	0x1f29f024,
 	0x080007f1,
 	0xd00203f0,
 	0x04bd0002,
-	0xfea00ef5,
+	0xfea60ef5,
 /* 0x06c8: ih */
 	0x80f900f9,
 	0xf90188fe,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk110.fuc3.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk110.fuc3.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk110.fuc3.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk110.fuc3.h	2016-07-24 15:23:50.000000000 -0400
@@ -584,9 +584,10 @@ uint32_t gk110_grhub_code[] = {
 	0x300007f1,
 	0xd00203f0,
 	0x04bd0001,
-/* 0x0564: main */
-	0xf40031f4,
-	0xd7f00028,
+/* 0x0564: wait */
+	0xf40028f4,
+/* 0x056a: main */
+	0xd7f00031,
 	0x3921f410,
 	0xb1f401f4,
 	0xf54001e4,
@@ -650,7 +651,7 @@ uint32_t gk110_grhub_code[] = {
 	0x170007f1,
 	0xd00203f0,
 	0x04bd0009,
-	0xff080ef5,
+	0xff0e0ef5,
 /* 0x0660: main_not_ctx_switch */
 	0xf401e4b0,
 	0xf2b90d1b,
@@ -675,12 +676,12 @@ uint32_t gk110_grhub_code[] = {
 	0xf501f5f0,
 	0xf5037e21,
 /* 0x06b3: main_done */
-	0xbdfeb50e,
+	0xbdfebb0e,
 	0x1f29f024,
 	0x300007f1,
 	0xd00203f0,
 	0x04bd0002,
-	0xfea00ef5,
+	0xfea60ef5,
 /* 0x06c8: ih */
 	0x80f900f9,
 	0xf90188fe,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk208.fuc5.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk208.fuc5.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk208.fuc5.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk208.fuc5.h	2016-07-24 15:23:50.000000000 -0400
@@ -531,9 +531,10 @@ uint32_t gk208_grhub_code[] = {
 	0x1f19f014,
 	0x02300080,
 	0xbd0001f6,
-/* 0x0491: main */
-	0x0031f404,
-	0x0d0028f4,
+/* 0x0491: wait */
+	0x0028f404,
+/* 0x0497: main */
+	0x0d0031f4,
 	0x00377e10,
 	0xf401f400,
 	0x4001e4b1,
@@ -590,7 +591,7 @@ uint32_t gk208_grhub_code[] = {
 	0x09f60217,
 	0xf504bd00,
 /* 0x056b: main_not_ctx_switch */
-	0xb0ff2a0e,
+	0xb0ff300e,
 	0x1bf401e4,
 	0x7ef2b20c,
 	0xf4000820,
@@ -612,11 +613,11 @@ uint32_t gk208_grhub_code[] = {
 	0x7e01f5f0,
 	0xf50002f8,
 /* 0x05b7: main_done */
-	0xbdfede0e,
+	0xbdfee40e,
 	0x1f29f024,
 	0x02300080,
 	0xbd0002f6,
-	0xcc0ef504,
+	0xd20ef504,
 /* 0x05c9: ih */
 	0xf900f9fe,
 	0x0188fe80,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgm107.fuc5.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgm107.fuc5.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgm107.fuc5.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgm107.fuc5.h	2016-07-24 15:23:50.000000000 -0400
@@ -531,9 +531,10 @@ uint32_t gm107_grhub_code[] = {
 	0x1f19f014,
 	0x02300080,
 	0xbd0001f6,
-/* 0x0491: main */
-	0x0031f404,
-	0x0d0028f4,
+/* 0x0491: wait */
+	0x0028f404,
+/* 0x0497: main */
+	0x0d0031f4,
 	0x00377e10,
 	0xf401f400,
 	0x4001e4b1,
@@ -590,7 +591,7 @@ uint32_t gm107_grhub_code[] = {
 	0x09f60217,
 	0xf504bd00,
 /* 0x056b: main_not_ctx_switch */
-	0xb0ff2a0e,
+	0xb0ff300e,
 	0x1bf401e4,
 	0x7ef2b20c,
 	0xf4000820,
@@ -612,11 +613,11 @@ uint32_t gm107_grhub_code[] = {
 	0x7e01f5f0,
 	0xf50002f8,
 /* 0x05b7: main_done */
-	0xbdfede0e,
+	0xbdfee40e,
 	0x1f29f024,
 	0x02300080,
 	0xbd0002f6,
-	0xcc0ef504,
+	0xd20ef504,
 /* 0x05c9: ih */
 	0xf900f9fe,
 	0x0188fe80,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c	2016-07-24 15:23:50.000000000 -0400
@@ -702,6 +702,13 @@ gf100_gr_pack_mmio[] = {
  * PGRAPH engine/subdev functions
  ******************************************************************************/
 
+int
+gf100_gr_rops(struct gf100_gr *gr)
+{
+	struct nvkm_device *device = gr->base.engine.subdev.device;
+	return (nvkm_rd32(device, 0x409604) & 0x001f0000) >> 16;
+}
+
 void
 gf100_gr_zbc_init(struct gf100_gr *gr)
 {
@@ -942,22 +949,41 @@ gf100_gr_trap_gpc_rop(struct gf100_gr *g
 }
 
 static const struct nvkm_enum gf100_mp_warp_error[] = {
-	{ 0x00, "NO_ERROR" },
-	{ 0x01, "STACK_MISMATCH" },
+	{ 0x01, "STACK_ERROR" },
+	{ 0x02, "API_STACK_ERROR" },
+	{ 0x03, "RET_EMPTY_STACK_ERROR" },
+	{ 0x04, "PC_WRAP" },
 	{ 0x05, "MISALIGNED_PC" },
-	{ 0x08, "MISALIGNED_GPR" },
-	{ 0x09, "INVALID_OPCODE" },
-	{ 0x0d, "GPR_OUT_OF_BOUNDS" },
-	{ 0x0e, "MEM_OUT_OF_BOUNDS" },
-	{ 0x0f, "UNALIGNED_MEM_ACCESS" },
+	{ 0x06, "PC_OVERFLOW" },
+	{ 0x07, "MISALIGNED_IMMC_ADDR" },
+	{ 0x08, "MISALIGNED_REG" },
+	{ 0x09, "ILLEGAL_INSTR_ENCODING" },
+	{ 0x0a, "ILLEGAL_SPH_INSTR_COMBO" },
+	{ 0x0b, "ILLEGAL_INSTR_PARAM" },
+	{ 0x0c, "INVALID_CONST_ADDR" },
+	{ 0x0d, "OOR_REG" },
+	{ 0x0e, "OOR_ADDR" },
+	{ 0x0f, "MISALIGNED_ADDR" },
 	{ 0x10, "INVALID_ADDR_SPACE" },
-	{ 0x11, "INVALID_PARAM" },
+	{ 0x11, "ILLEGAL_INSTR_PARAM2" },
+	{ 0x12, "INVALID_CONST_ADDR_LDC" },
+	{ 0x13, "GEOMETRY_SM_ERROR" },
+	{ 0x14, "DIVERGENT" },
+	{ 0x15, "WARP_EXIT" },
 	{}
 };
 
 static const struct nvkm_bitfield gf100_mp_global_error[] = {
+	{ 0x00000001, "SM_TO_SM_FAULT" },
+	{ 0x00000002, "L1_ERROR" },
 	{ 0x00000004, "MULTIPLE_WARP_ERRORS" },
-	{ 0x00000008, "OUT_OF_STACK_SPACE" },
+	{ 0x00000008, "PHYSICAL_STACK_OVERFLOW" },
+	{ 0x00000010, "BPT_INT" },
+	{ 0x00000020, "BPT_PAUSE" },
+	{ 0x00000040, "SINGLE_STEP_COMPLETE" },
+	{ 0x20000000, "ECC_SEC_ERROR" },
+	{ 0x40000000, "ECC_DED_ERROR" },
+	{ 0x80000000, "TIMEOUT" },
 	{}
 };
 
@@ -1609,32 +1635,12 @@ gf100_gr_oneinit(struct nvkm_gr *base)
 {
 	struct gf100_gr *gr = gf100_gr(base);
 	struct nvkm_device *device = gr->base.engine.subdev.device;
-	int ret, i, j;
+	int i, j;
 
 	nvkm_pmu_pgob(device->pmu, false);
 
-	ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 256, false,
-			      &gr->unk4188b4);
-	if (ret)
-		return ret;
-
-	ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 256, false,
-			      &gr->unk4188b8);
-	if (ret)
-		return ret;
-
-	nvkm_kmap(gr->unk4188b4);
-	for (i = 0; i < 0x1000; i += 4)
-		nvkm_wo32(gr->unk4188b4, i, 0x00000010);
-	nvkm_done(gr->unk4188b4);
-
-	nvkm_kmap(gr->unk4188b8);
-	for (i = 0; i < 0x1000; i += 4)
-		nvkm_wo32(gr->unk4188b8, i, 0x00000010);
-	nvkm_done(gr->unk4188b8);
-
-	gr->rop_nr = (nvkm_rd32(device, 0x409604) & 0x001f0000) >> 16;
-	gr->gpc_nr =  nvkm_rd32(device, 0x409604) & 0x0000001f;
+	gr->rop_nr = gr->func->rops(gr);
+	gr->gpc_nr = nvkm_rd32(device, 0x409604) & 0x0000001f;
 	for (i = 0; i < gr->gpc_nr; i++) {
 		gr->tpc_nr[i]  = nvkm_rd32(device, GPC_UNIT(i, 0x2608));
 		gr->tpc_total += gr->tpc_nr[i];
@@ -1651,38 +1657,38 @@ gf100_gr_oneinit(struct nvkm_gr *base)
 	switch (device->chipset) {
 	case 0xc0:
 		if (gr->tpc_total == 11) { /* 465, 3/4/4/0, 4 */
-			gr->magic_not_rop_nr = 0x07;
+			gr->screen_tile_row_offset = 0x07;
 		} else
 		if (gr->tpc_total == 14) { /* 470, 3/3/4/4, 5 */
-			gr->magic_not_rop_nr = 0x05;
+			gr->screen_tile_row_offset = 0x05;
 		} else
 		if (gr->tpc_total == 15) { /* 480, 3/4/4/4, 6 */
-			gr->magic_not_rop_nr = 0x06;
+			gr->screen_tile_row_offset = 0x06;
 		}
 		break;
 	case 0xc3: /* 450, 4/0/0/0, 2 */
-		gr->magic_not_rop_nr = 0x03;
+		gr->screen_tile_row_offset = 0x03;
 		break;
 	case 0xc4: /* 460, 3/4/0/0, 4 */
-		gr->magic_not_rop_nr = 0x01;
+		gr->screen_tile_row_offset = 0x01;
 		break;
 	case 0xc1: /* 2/0/0/0, 1 */
-		gr->magic_not_rop_nr = 0x01;
+		gr->screen_tile_row_offset = 0x01;
 		break;
 	case 0xc8: /* 4/4/3/4, 5 */
-		gr->magic_not_rop_nr = 0x06;
+		gr->screen_tile_row_offset = 0x06;
 		break;
 	case 0xce: /* 4/4/0/0, 4 */
-		gr->magic_not_rop_nr = 0x03;
+		gr->screen_tile_row_offset = 0x03;
 		break;
 	case 0xcf: /* 4/0/0/0, 3 */
-		gr->magic_not_rop_nr = 0x03;
+		gr->screen_tile_row_offset = 0x03;
 		break;
 	case 0xd7:
 	case 0xd9: /* 1/0/0/0, 1 */
 	case 0xea: /* gk20a */
 	case 0x12b: /* gm20b */
-		gr->magic_not_rop_nr = 0x01;
+		gr->screen_tile_row_offset = 0x01;
 		break;
 	}
 
@@ -1729,8 +1735,6 @@ gf100_gr_dtor(struct nvkm_gr *base)
 	gf100_gr_dtor_init(gr->fuc_sw_ctx);
 	gf100_gr_dtor_init(gr->fuc_sw_nonctx);
 
-	nvkm_memory_del(&gr->unk4188b8);
-	nvkm_memory_del(&gr->unk4188b4);
 	return gr;
 }
 
@@ -1776,7 +1780,7 @@ gf100_gr_ctor(const struct gf100_gr_func
 	gr->firmware = nvkm_boolopt(device->cfgopt, "NvGrUseFW",
 				    func->fecs.ucode == NULL);
 
-	ret = nvkm_gr_ctor(&gf100_gr_, device, index, 0x08001000,
+	ret = nvkm_gr_ctor(&gf100_gr_, device, index,
 			   gr->firmware || func->fecs.ucode != NULL,
 			   &gr->base);
 	if (ret)
@@ -1815,6 +1819,7 @@ int
 gf100_gr_init(struct gf100_gr *gr)
 {
 	struct nvkm_device *device = gr->base.engine.subdev.device;
+	struct nvkm_fb *fb = device->fb;
 	const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, gr->tpc_total);
 	u32 data[TPC_MAX / 8] = {};
 	u8  tpcnr[GPC_MAX];
@@ -1827,8 +1832,8 @@ gf100_gr_init(struct gf100_gr *gr)
 	nvkm_wr32(device, GPC_BCAST(0x088c), 0x00000000);
 	nvkm_wr32(device, GPC_BCAST(0x0890), 0x00000000);
 	nvkm_wr32(device, GPC_BCAST(0x0894), 0x00000000);
-	nvkm_wr32(device, GPC_BCAST(0x08b4), nvkm_memory_addr(gr->unk4188b4) >> 8);
-	nvkm_wr32(device, GPC_BCAST(0x08b8), nvkm_memory_addr(gr->unk4188b8) >> 8);
+	nvkm_wr32(device, GPC_BCAST(0x08b4), nvkm_memory_addr(fb->mmu_wr) >> 8);
+	nvkm_wr32(device, GPC_BCAST(0x08b8), nvkm_memory_addr(fb->mmu_rd) >> 8);
 
 	gf100_gr_mmio(gr, gr->func->mmio);
 
@@ -1851,9 +1856,9 @@ gf100_gr_init(struct gf100_gr *gr)
 
 	for (gpc = 0; gpc < gr->gpc_nr; gpc++) {
 		nvkm_wr32(device, GPC_UNIT(gpc, 0x0914),
-			gr->magic_not_rop_nr << 8 | gr->tpc_nr[gpc]);
+			  gr->screen_tile_row_offset << 8 | gr->tpc_nr[gpc]);
 		nvkm_wr32(device, GPC_UNIT(gpc, 0x0910), 0x00040000 |
-			gr->tpc_total);
+							 gr->tpc_total);
 		nvkm_wr32(device, GPC_UNIT(gpc, 0x0918), magicgpc918);
 	}
 
@@ -1946,6 +1951,7 @@ gf100_gr = {
 	.mmio = gf100_gr_pack_mmio,
 	.fecs.ucode = &gf100_gr_fecs_ucode,
 	.gpccs.ucode = &gf100_gr_gpccs_ucode,
+	.rops = gf100_gr_rops,
 	.grctx = &gf100_grctx,
 	.sclass = {
 		{ -1, -1, FERMI_TWOD_A },
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h	2016-07-24 15:23:50.000000000 -0400
@@ -31,7 +31,8 @@
 #include <subdev/mmu.h>
 
 #define GPC_MAX 32
-#define TPC_MAX (GPC_MAX * 8)
+#define TPC_MAX_PER_GPC 8
+#define TPC_MAX (GPC_MAX * TPC_MAX_PER_GPC)
 
 #define ROP_BCAST(r)      (0x408800 + (r))
 #define ROP_UNIT(u, r)    (0x410000 + (u) * 0x400 + (r))
@@ -100,15 +101,12 @@ struct gf100_gr {
 	u8 ppc_mask[GPC_MAX];
 	u8 ppc_tpc_nr[GPC_MAX][4];
 
-	struct nvkm_memory *unk4188b4;
-	struct nvkm_memory *unk4188b8;
-
 	struct gf100_gr_data mmio_data[4];
 	struct gf100_gr_mmio mmio_list[4096/8];
 	u32  size;
 	u32 *data;
 
-	u8 magic_not_rop_nr;
+	u8 screen_tile_row_offset;
 };
 
 int gf100_gr_ctor(const struct gf100_gr_func *, struct nvkm_device *,
@@ -121,6 +119,8 @@ struct gf100_gr_func {
 	void (*dtor)(struct gf100_gr *);
 	int (*init)(struct gf100_gr *);
 	void (*init_gpc_mmu)(struct gf100_gr *);
+	void (*init_rop_active_fbps)(struct gf100_gr *);
+	void (*init_ppc_exceptions)(struct gf100_gr *);
 	void (*set_hww_esr_report_mask)(struct gf100_gr *);
 	const struct gf100_gr_pack *mmio;
 	struct {
@@ -129,18 +129,23 @@ struct gf100_gr_func {
 	struct {
 		struct gf100_gr_ucode *ucode;
 	} gpccs;
+	int (*rops)(struct gf100_gr *);
 	int ppc_nr;
 	const struct gf100_grctx_func *grctx;
 	struct nvkm_sclass sclass[];
 };
 
 int gf100_gr_init(struct gf100_gr *);
+int gf100_gr_rops(struct gf100_gr *);
 
 int gk104_gr_init(struct gf100_gr *);
+void gk104_gr_init_rop_active_fbps(struct gf100_gr *);
+void gk104_gr_init_ppc_exceptions(struct gf100_gr *);
 
 int gk20a_gr_init(struct gf100_gr *);
 
 int gm200_gr_init(struct gf100_gr *);
+int gm200_gr_rops(struct gf100_gr *);
 
 #define gf100_gr_chan(p) container_of((p), struct gf100_gr_chan, object)
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c	2016-07-24 15:23:50.000000000 -0400
@@ -118,6 +118,7 @@ gf104_gr = {
 	.mmio = gf104_gr_pack_mmio,
 	.fecs.ucode = &gf100_gr_fecs_ucode,
 	.gpccs.ucode = &gf100_gr_gpccs_ucode,
+	.rops = gf100_gr_rops,
 	.grctx = &gf104_grctx,
 	.sclass = {
 		{ -1, -1, FERMI_TWOD_A },
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c	2016-07-24 15:23:50.000000000 -0400
@@ -109,6 +109,7 @@ gf108_gr = {
 	.mmio = gf108_gr_pack_mmio,
 	.fecs.ucode = &gf100_gr_fecs_ucode,
 	.gpccs.ucode = &gf100_gr_gpccs_ucode,
+	.rops = gf100_gr_rops,
 	.grctx = &gf108_grctx,
 	.sclass = {
 		{ -1, -1, FERMI_TWOD_A },
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c	2016-07-24 15:23:50.000000000 -0400
@@ -90,6 +90,7 @@ gf110_gr = {
 	.mmio = gf110_gr_pack_mmio,
 	.fecs.ucode = &gf100_gr_fecs_ucode,
 	.gpccs.ucode = &gf100_gr_gpccs_ucode,
+	.rops = gf100_gr_rops,
 	.grctx = &gf110_grctx,
 	.sclass = {
 		{ -1, -1, FERMI_TWOD_A },
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c	2016-07-24 15:23:50.000000000 -0400
@@ -126,6 +126,7 @@ gf117_gr = {
 	.mmio = gf117_gr_pack_mmio,
 	.fecs.ucode = &gf117_gr_fecs_ucode,
 	.gpccs.ucode = &gf117_gr_gpccs_ucode,
+	.rops = gf100_gr_rops,
 	.ppc_nr = 1,
 	.grctx = &gf117_grctx,
 	.sclass = {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c	2016-07-24 15:23:50.000000000 -0400
@@ -181,6 +181,7 @@ gf119_gr = {
 	.mmio = gf119_gr_pack_mmio,
 	.fecs.ucode = &gf100_gr_fecs_ucode,
 	.gpccs.ucode = &gf100_gr_gpccs_ucode,
+	.rops = gf100_gr_rops,
 	.grctx = &gf119_grctx,
 	.sclass = {
 		{ -1, -1, FERMI_TWOD_A },
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c	2016-07-24 15:23:50.000000000 -0400
@@ -24,6 +24,8 @@
 #include "gf100.h"
 #include "ctxgf100.h"
 
+#include <subdev/fb.h>
+
 #include <nvif/class.h>
 
 /*******************************************************************************
@@ -177,10 +179,35 @@ gk104_gr_pack_mmio[] = {
  * PGRAPH engine/subdev functions
  ******************************************************************************/
 
+void
+gk104_gr_init_rop_active_fbps(struct gf100_gr *gr)
+{
+	struct nvkm_device *device = gr->base.engine.subdev.device;
+	const u32 fbp_count = nvkm_rd32(device, 0x120074);
+	nvkm_mask(device, 0x408850, 0x0000000f, fbp_count); /* zrop */
+	nvkm_mask(device, 0x408958, 0x0000000f, fbp_count); /* crop */
+}
+
+void
+gk104_gr_init_ppc_exceptions(struct gf100_gr *gr)
+{
+	struct nvkm_device *device = gr->base.engine.subdev.device;
+	int gpc, ppc;
+
+	for (gpc = 0; gpc < gr->gpc_nr; gpc++) {
+		for (ppc = 0; ppc < gr->ppc_nr[gpc]; ppc++) {
+			if (!(gr->ppc_mask[gpc] & (1 << ppc)))
+				continue;
+			nvkm_wr32(device, PPC_UNIT(gpc, ppc, 0x038), 0xc0000000);
+		}
+	}
+}
+
 int
 gk104_gr_init(struct gf100_gr *gr)
 {
 	struct nvkm_device *device = gr->base.engine.subdev.device;
+	struct nvkm_fb *fb = device->fb;
 	const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, gr->tpc_total);
 	u32 data[TPC_MAX / 8] = {};
 	u8  tpcnr[GPC_MAX];
@@ -193,8 +220,8 @@ gk104_gr_init(struct gf100_gr *gr)
 	nvkm_wr32(device, GPC_BCAST(0x088c), 0x00000000);
 	nvkm_wr32(device, GPC_BCAST(0x0890), 0x00000000);
 	nvkm_wr32(device, GPC_BCAST(0x0894), 0x00000000);
-	nvkm_wr32(device, GPC_BCAST(0x08b4), nvkm_memory_addr(gr->unk4188b4) >> 8);
-	nvkm_wr32(device, GPC_BCAST(0x08b8), nvkm_memory_addr(gr->unk4188b8) >> 8);
+	nvkm_wr32(device, GPC_BCAST(0x08b4), nvkm_memory_addr(fb->mmu_wr) >> 8);
+	nvkm_wr32(device, GPC_BCAST(0x08b8), nvkm_memory_addr(fb->mmu_rd) >> 8);
 
 	gf100_gr_mmio(gr, gr->func->mmio);
 
@@ -218,15 +245,17 @@ gk104_gr_init(struct gf100_gr *gr)
 
 	for (gpc = 0; gpc < gr->gpc_nr; gpc++) {
 		nvkm_wr32(device, GPC_UNIT(gpc, 0x0914),
-			gr->magic_not_rop_nr << 8 | gr->tpc_nr[gpc]);
+			  gr->screen_tile_row_offset << 8 | gr->tpc_nr[gpc]);
 		nvkm_wr32(device, GPC_UNIT(gpc, 0x0910), 0x00040000 |
-			gr->tpc_total);
+							 gr->tpc_total);
 		nvkm_wr32(device, GPC_UNIT(gpc, 0x0918), magicgpc918);
 	}
 
 	nvkm_wr32(device, GPC_BCAST(0x3fd4), magicgpc918);
 	nvkm_wr32(device, GPC_BCAST(0x08ac), nvkm_rd32(device, 0x100800));
 
+	gr->func->init_rop_active_fbps(gr);
+
 	nvkm_wr32(device, 0x400500, 0x00010001);
 
 	nvkm_wr32(device, 0x400100, 0xffffffff);
@@ -246,8 +275,9 @@ gk104_gr_init(struct gf100_gr *gr)
 	nvkm_mask(device, 0x419cc0, 0x00000008, 0x00000008);
 	nvkm_mask(device, 0x419eb4, 0x00001000, 0x00001000);
 
+	gr->func->init_ppc_exceptions(gr);
+
 	for (gpc = 0; gpc < gr->gpc_nr; gpc++) {
-		nvkm_wr32(device, GPC_UNIT(gpc, 0x3038), 0xc0000000);
 		nvkm_wr32(device, GPC_UNIT(gpc, 0x0420), 0xc0000000);
 		nvkm_wr32(device, GPC_UNIT(gpc, 0x0900), 0xc0000000);
 		nvkm_wr32(device, GPC_UNIT(gpc, 0x1028), 0xc0000000);
@@ -309,9 +339,12 @@ gk104_gr_gpccs_ucode = {
 static const struct gf100_gr_func
 gk104_gr = {
 	.init = gk104_gr_init,
+	.init_rop_active_fbps = gk104_gr_init_rop_active_fbps,
+	.init_ppc_exceptions = gk104_gr_init_ppc_exceptions,
 	.mmio = gk104_gr_pack_mmio,
 	.fecs.ucode = &gk104_gr_fecs_ucode,
 	.gpccs.ucode = &gk104_gr_gpccs_ucode,
+	.rops = gf100_gr_rops,
 	.ppc_nr = 1,
 	.grctx = &gk104_grctx,
 	.sclass = {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c	2016-07-24 15:23:50.000000000 -0400
@@ -103,9 +103,12 @@ gk110b_gr_pack_mmio[] = {
 static const struct gf100_gr_func
 gk110b_gr = {
 	.init = gk104_gr_init,
+	.init_rop_active_fbps = gk104_gr_init_rop_active_fbps,
+	.init_ppc_exceptions = gk104_gr_init_ppc_exceptions,
 	.mmio = gk110b_gr_pack_mmio,
 	.fecs.ucode = &gk110_gr_fecs_ucode,
 	.gpccs.ucode = &gk110_gr_gpccs_ucode,
+	.rops = gf100_gr_rops,
 	.ppc_nr = 2,
 	.grctx = &gk110b_grctx,
 	.sclass = {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c	2016-07-24 15:23:50.000000000 -0400
@@ -183,9 +183,12 @@ gk110_gr_gpccs_ucode = {
 static const struct gf100_gr_func
 gk110_gr = {
 	.init = gk104_gr_init,
+	.init_rop_active_fbps = gk104_gr_init_rop_active_fbps,
+	.init_ppc_exceptions = gk104_gr_init_ppc_exceptions,
 	.mmio = gk110_gr_pack_mmio,
 	.fecs.ucode = &gk110_gr_fecs_ucode,
 	.gpccs.ucode = &gk110_gr_gpccs_ucode,
+	.rops = gf100_gr_rops,
 	.ppc_nr = 2,
 	.grctx = &gk110_grctx,
 	.sclass = {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c	2016-07-24 15:23:50.000000000 -0400
@@ -162,9 +162,12 @@ gk208_gr_gpccs_ucode = {
 static const struct gf100_gr_func
 gk208_gr = {
 	.init = gk104_gr_init,
+	.init_rop_active_fbps = gk104_gr_init_rop_active_fbps,
+	.init_ppc_exceptions = gk104_gr_init_ppc_exceptions,
 	.mmio = gk208_gr_pack_mmio,
 	.fecs.ucode = &gk208_gr_fecs_ucode,
 	.gpccs.ucode = &gk208_gr_gpccs_ucode,
+	.rops = gf100_gr_rops,
 	.ppc_nr = 1,
 	.grctx = &gk208_grctx,
 	.sclass = {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c	2016-07-24 15:23:50.000000000 -0400
@@ -239,9 +239,6 @@ gk20a_gr_init(struct gf100_gr *gr)
 		return ret;
 
 	/* MMU debug buffer */
-	nvkm_wr32(device, 0x100cc8, nvkm_memory_addr(gr->unk4188b4) >> 8);
-	nvkm_wr32(device, 0x100ccc, nvkm_memory_addr(gr->unk4188b8) >> 8);
-
 	if (gr->func->init_gpc_mmu)
 		gr->func->init_gpc_mmu(gr);
 
@@ -267,7 +264,7 @@ gk20a_gr_init(struct gf100_gr *gr)
 
 	for (gpc = 0; gpc < gr->gpc_nr; gpc++) {
 		nvkm_wr32(device, GPC_UNIT(gpc, 0x0914),
-			  gr->magic_not_rop_nr << 8 | gr->tpc_nr[gpc]);
+			  gr->screen_tile_row_offset << 8 | gr->tpc_nr[gpc]);
 		nvkm_wr32(device, GPC_UNIT(gpc, 0x0910), 0x00040000 |
 			  gr->tpc_total);
 		nvkm_wr32(device, GPC_UNIT(gpc, 0x0918), magicgpc918);
@@ -275,6 +272,8 @@ gk20a_gr_init(struct gf100_gr *gr)
 
 	nvkm_wr32(device, GPC_BCAST(0x3fd4), magicgpc918);
 
+	gr->func->init_rop_active_fbps(gr);
+
 	/* Enable FIFO access */
 	nvkm_wr32(device, 0x400500, 0x00010001);
 
@@ -312,7 +311,9 @@ gk20a_gr_init(struct gf100_gr *gr)
 static const struct gf100_gr_func
 gk20a_gr = {
 	.init = gk20a_gr_init,
+	.init_rop_active_fbps = gk104_gr_init_rop_active_fbps,
 	.set_hww_esr_report_mask = gk20a_gr_set_hww_esr_report_mask,
+	.rops = gf100_gr_rops,
 	.ppc_nr = 1,
 	.grctx = &gk20a_grctx,
 	.sclass = {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c	2016-07-24 15:23:50.000000000 -0400
@@ -26,6 +26,7 @@
 
 #include <subdev/bios.h>
 #include <subdev/bios/P0260.h>
+#include <subdev/fb.h>
 
 #include <nvif/class.h>
 
@@ -311,17 +312,18 @@ int
 gm107_gr_init(struct gf100_gr *gr)
 {
 	struct nvkm_device *device = gr->base.engine.subdev.device;
+	struct nvkm_fb *fb = device->fb;
 	const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, gr->tpc_total);
 	u32 data[TPC_MAX / 8] = {};
 	u8  tpcnr[GPC_MAX];
-	int gpc, tpc, ppc, rop;
+	int gpc, tpc, rop;
 	int i;
 
 	nvkm_wr32(device, GPC_BCAST(0x0880), 0x00000000);
 	nvkm_wr32(device, GPC_BCAST(0x0890), 0x00000000);
 	nvkm_wr32(device, GPC_BCAST(0x0894), 0x00000000);
-	nvkm_wr32(device, GPC_BCAST(0x08b4), nvkm_memory_addr(gr->unk4188b4) >> 8);
-	nvkm_wr32(device, GPC_BCAST(0x08b8), nvkm_memory_addr(gr->unk4188b8) >> 8);
+	nvkm_wr32(device, GPC_BCAST(0x08b4), nvkm_memory_addr(fb->mmu_wr) >> 8);
+	nvkm_wr32(device, GPC_BCAST(0x08b8), nvkm_memory_addr(fb->mmu_rd) >> 8);
 
 	gf100_gr_mmio(gr, gr->func->mmio);
 
@@ -347,15 +349,17 @@ gm107_gr_init(struct gf100_gr *gr)
 
 	for (gpc = 0; gpc < gr->gpc_nr; gpc++) {
 		nvkm_wr32(device, GPC_UNIT(gpc, 0x0914),
-			gr->magic_not_rop_nr << 8 | gr->tpc_nr[gpc]);
+			  gr->screen_tile_row_offset << 8 | gr->tpc_nr[gpc]);
 		nvkm_wr32(device, GPC_UNIT(gpc, 0x0910), 0x00040000 |
-			gr->tpc_total);
+							 gr->tpc_total);
 		nvkm_wr32(device, GPC_UNIT(gpc, 0x0918), magicgpc918);
 	}
 
 	nvkm_wr32(device, GPC_BCAST(0x3fd4), magicgpc918);
 	nvkm_wr32(device, GPC_BCAST(0x08ac), nvkm_rd32(device, 0x100800));
 
+	gr->func->init_rop_active_fbps(gr);
+
 	nvkm_wr32(device, 0x400500, 0x00010001);
 
 	nvkm_wr32(device, 0x400100, 0xffffffff);
@@ -373,9 +377,9 @@ gm107_gr_init(struct gf100_gr *gr)
 	nvkm_wr32(device, 0x405844, 0x00ffffff);
 	nvkm_mask(device, 0x419cc0, 0x00000008, 0x00000008);
 
+	gr->func->init_ppc_exceptions(gr);
+
 	for (gpc = 0; gpc < gr->gpc_nr; gpc++) {
-		for (ppc = 0; ppc < 2 /* gr->ppc_nr[gpc] */; ppc++)
-			nvkm_wr32(device, PPC_UNIT(gpc, ppc, 0x038), 0xc0000000);
 		nvkm_wr32(device, GPC_UNIT(gpc, 0x0420), 0xc0000000);
 		nvkm_wr32(device, GPC_UNIT(gpc, 0x0900), 0xc0000000);
 		nvkm_wr32(device, GPC_UNIT(gpc, 0x1028), 0xc0000000);
@@ -438,9 +442,12 @@ gm107_gr_gpccs_ucode = {
 static const struct gf100_gr_func
 gm107_gr = {
 	.init = gm107_gr_init,
+	.init_rop_active_fbps = gk104_gr_init_rop_active_fbps,
+	.init_ppc_exceptions = gk104_gr_init_ppc_exceptions,
 	.mmio = gm107_gr_pack_mmio,
 	.fecs.ucode = &gm107_gr_fecs_ucode,
 	.gpccs.ucode = &gm107_gr_gpccs_ucode,
+	.rops = gf100_gr_rops,
 	.ppc_nr = 2,
 	.grctx = &gm107_grctx,
 	.sclass = {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c	2016-07-24 15:23:50.000000000 -0400
@@ -33,27 +33,45 @@
  ******************************************************************************/
 
 int
+gm200_gr_rops(struct gf100_gr *gr)
+{
+	return nvkm_rd32(gr->base.engine.subdev.device, 0x12006c);
+}
+
+static void
+gm200_gr_init_gpc_mmu(struct gf100_gr *gr)
+{
+	struct nvkm_device *device = gr->base.engine.subdev.device;
+
+	nvkm_wr32(device, 0x418880, nvkm_rd32(device, 0x100c80) & 0xf0001fff);
+	nvkm_wr32(device, 0x418890, 0x00000000);
+	nvkm_wr32(device, 0x418894, 0x00000000);
+
+	nvkm_wr32(device, 0x4188b4, nvkm_rd32(device, 0x100cc8));
+	nvkm_wr32(device, 0x4188b8, nvkm_rd32(device, 0x100ccc));
+	nvkm_wr32(device, 0x4188b0, nvkm_rd32(device, 0x100cc4));
+}
+
+static void
+gm200_gr_init_rop_active_fbps(struct gf100_gr *gr)
+{
+	struct nvkm_device *device = gr->base.engine.subdev.device;
+	const u32 fbp_count = nvkm_rd32(device, 0x12006c);
+	nvkm_mask(device, 0x408850, 0x0000000f, fbp_count); /* zrop */
+	nvkm_mask(device, 0x408958, 0x0000000f, fbp_count); /* crop */
+}
+
+int
 gm200_gr_init(struct gf100_gr *gr)
 {
 	struct nvkm_device *device = gr->base.engine.subdev.device;
 	const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, gr->tpc_total);
-	u32 data[TPC_MAX / 8] = {}, tmp;
+	u32 data[TPC_MAX / 8] = {};
 	u8  tpcnr[GPC_MAX];
-	int gpc, tpc, ppc, rop;
+	int gpc, tpc, rop;
 	int i;
 
-	tmp = nvkm_rd32(device, 0x100c80); /*XXX: mask? */
-	nvkm_wr32(device, 0x418880, 0x00001000 | (tmp & 0x00000fff));
-	nvkm_wr32(device, 0x418890, 0x00000000);
-	nvkm_wr32(device, 0x418894, 0x00000000);
-	nvkm_wr32(device, 0x4188b4, nvkm_memory_addr(gr->unk4188b4) >> 8);
-	nvkm_wr32(device, 0x4188b8, nvkm_memory_addr(gr->unk4188b8) >> 8);
-	nvkm_mask(device, 0x4188b0, 0x00040000, 0x00040000);
-
-	/*XXX: belongs in fb */
-	nvkm_wr32(device, 0x100cc8, nvkm_memory_addr(gr->unk4188b4) >> 8);
-	nvkm_wr32(device, 0x100ccc, nvkm_memory_addr(gr->unk4188b8) >> 8);
-	nvkm_mask(device, 0x100cc4, 0x00040000, 0x00040000);
+	gr->func->init_gpc_mmu(gr);
 
 	gf100_gr_mmio(gr, gr->fuc_sw_nonctx);
 
@@ -79,9 +97,9 @@ gm200_gr_init(struct gf100_gr *gr)
 
 	for (gpc = 0; gpc < gr->gpc_nr; gpc++) {
 		nvkm_wr32(device, GPC_UNIT(gpc, 0x0914),
-			gr->magic_not_rop_nr << 8 | gr->tpc_nr[gpc]);
+			  gr->screen_tile_row_offset << 8 | gr->tpc_nr[gpc]);
 		nvkm_wr32(device, GPC_UNIT(gpc, 0x0910), 0x00040000 |
-			gr->tpc_total);
+							 gr->tpc_total);
 		nvkm_wr32(device, GPC_UNIT(gpc, 0x0918), magicgpc918);
 	}
 
@@ -89,6 +107,8 @@ gm200_gr_init(struct gf100_gr *gr)
 	nvkm_wr32(device, GPC_BCAST(0x08ac), nvkm_rd32(device, 0x100800));
 	nvkm_wr32(device, GPC_BCAST(0x033c), nvkm_rd32(device, 0x100804));
 
+	gr->func->init_rop_active_fbps(gr);
+
 	nvkm_wr32(device, 0x400500, 0x00010001);
 	nvkm_wr32(device, 0x400100, 0xffffffff);
 	nvkm_wr32(device, 0x40013c, 0xffffffff);
@@ -106,9 +126,9 @@ gm200_gr_init(struct gf100_gr *gr)
 	nvkm_wr32(device, 0x405844, 0x00ffffff);
 	nvkm_mask(device, 0x419cc0, 0x00000008, 0x00000008);
 
+	gr->func->init_ppc_exceptions(gr);
+
 	for (gpc = 0; gpc < gr->gpc_nr; gpc++) {
-		for (ppc = 0; ppc < gr->ppc_nr[gpc]; ppc++)
-			nvkm_wr32(device, PPC_UNIT(gpc, ppc, 0x038), 0xc0000000);
 		nvkm_wr32(device, GPC_UNIT(gpc, 0x0420), 0xc0000000);
 		nvkm_wr32(device, GPC_UNIT(gpc, 0x0900), 0xc0000000);
 		nvkm_wr32(device, GPC_UNIT(gpc, 0x1028), 0xc0000000);
@@ -189,6 +209,10 @@ gm200_gr_new_(const struct gf100_gr_func
 static const struct gf100_gr_func
 gm200_gr = {
 	.init = gm200_gr_init,
+	.init_gpc_mmu = gm200_gr_init_gpc_mmu,
+	.init_rop_active_fbps = gm200_gr_init_rop_active_fbps,
+	.init_ppc_exceptions = gk104_gr_init_ppc_exceptions,
+	.rops = gm200_gr_rops,
 	.ppc_nr = 2,
 	.grctx = &gm200_grctx,
 	.sclass = {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c	2016-07-24 15:23:50.000000000 -0400
@@ -42,7 +42,7 @@ gm20b_gr_init_gpc_mmu(struct gf100_gr *g
 	}
 
 	val = nvkm_rd32(device, 0x100c80);
-	val &= 0xf000087f;
+	val &= 0xf000187f;
 	nvkm_wr32(device, 0x418880, val);
 	nvkm_wr32(device, 0x418890, 0);
 	nvkm_wr32(device, 0x418894, 0);
@@ -66,7 +66,9 @@ static const struct gf100_gr_func
 gm20b_gr = {
 	.init = gk20a_gr_init,
 	.init_gpc_mmu = gm20b_gr_init_gpc_mmu,
+	.init_rop_active_fbps = gk104_gr_init_rop_active_fbps,
 	.set_hww_esr_report_mask = gm20b_gr_set_hww_esr_report_mask,
+	.rops = gm200_gr_rops,
 	.ppc_nr = 1,
 	.grctx = &gm20b_grctx,
 	.sclass = {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv04.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv04.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv04.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv04.c	2016-07-24 15:23:50.000000000 -0400
@@ -1422,6 +1422,5 @@ nv04_gr_new(struct nvkm_device *device,
 	spin_lock_init(&gr->lock);
 	*pgr = &gr->base;
 
-	return nvkm_gr_ctor(&nv04_gr, device, index, 0x00001000,
-			    true, &gr->base);
+	return nvkm_gr_ctor(&nv04_gr, device, index, true, &gr->base);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.c	2016-07-24 15:23:50.000000000 -0400
@@ -1182,7 +1182,7 @@ nv10_gr_new_(const struct nvkm_gr_func *
 	spin_lock_init(&gr->lock);
 	*pgr = &gr->base;
 
-	return nvkm_gr_ctor(func, device, index, 0x00001000, true, &gr->base);
+	return nvkm_gr_ctor(func, device, index, true, &gr->base);
 }
 
 static const struct nvkm_gr_func
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c	2016-07-24 15:23:50.000000000 -0400
@@ -337,7 +337,7 @@ nv20_gr_new_(const struct nvkm_gr_func *
 		return -ENOMEM;
 	*pgr = &gr->base;
 
-	return nvkm_gr_ctor(func, device, index, 0x00001000, true, &gr->base);
+	return nvkm_gr_ctor(func, device, index, true, &gr->base);
 }
 
 static const struct nvkm_gr_func
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c	2016-07-24 15:23:50.000000000 -0400
@@ -438,7 +438,7 @@ nv40_gr_new_(const struct nvkm_gr_func *
 	*pgr = &gr->base;
 	INIT_LIST_HEAD(&gr->chan);
 
-	return nvkm_gr_ctor(func, device, index, 0x00001000, true, &gr->base);
+	return nvkm_gr_ctor(func, device, index, true, &gr->base);
 }
 
 static const struct nvkm_gr_func
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.c	2016-07-24 15:23:50.000000000 -0400
@@ -768,7 +768,7 @@ nv50_gr_new_(const struct nvkm_gr_func *
 	spin_lock_init(&gr->lock);
 	*pgr = &gr->base;
 
-	return nvkm_gr_ctor(func, device, index, 0x00201000, true, &gr->base);
+	return nvkm_gr_ctor(func, device, index, true, &gr->base);
 }
 
 static const struct nvkm_gr_func
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/priv.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/priv.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/priv.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/priv.h	2016-07-24 15:23:50.000000000 -0400
@@ -7,8 +7,7 @@ struct nvkm_fb_tile;
 struct nvkm_fifo_chan;
 
 int nvkm_gr_ctor(const struct nvkm_gr_func *, struct nvkm_device *,
-		 int index, u32 pmc_enable, bool enable,
-		 struct nvkm_gr *);
+		 int index, bool enable, struct nvkm_gr *);
 
 bool nv04_gr_idle(struct nvkm_gr *);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/g84.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/g84.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/g84.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/g84.c	2016-07-24 15:23:50.000000000 -0400
@@ -39,6 +39,5 @@ g84_mpeg = {
 int
 g84_mpeg_new(struct nvkm_device *device, int index, struct nvkm_engine **pmpeg)
 {
-	return nvkm_engine_new_(&g84_mpeg, device, index, 0x00000002,
-				true, pmpeg);
+	return nvkm_engine_new_(&g84_mpeg, device, index, true, pmpeg);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c	2016-07-24 15:23:50.000000000 -0400
@@ -278,7 +278,7 @@ nv31_mpeg_new_(const struct nv31_mpeg_fu
 	mpeg->func = func;
 	*pmpeg = &mpeg->engine;
 
-	return nvkm_engine_ctor(&nv31_mpeg_, device, index, 0x00000002,
+	return nvkm_engine_ctor(&nv31_mpeg_, device, index,
 				true, &mpeg->engine);
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c	2016-07-24 15:23:50.000000000 -0400
@@ -212,6 +212,5 @@ nv44_mpeg_new(struct nvkm_device *device
 	INIT_LIST_HEAD(&mpeg->chan);
 	*pmpeg = &mpeg->engine;
 
-	return nvkm_engine_ctor(&nv44_mpeg, device, index, 0x00000002,
-				true, &mpeg->engine);
+	return nvkm_engine_ctor(&nv44_mpeg, device, index, true, &mpeg->engine);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv50.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv50.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv50.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv50.c	2016-07-24 15:23:50.000000000 -0400
@@ -130,6 +130,5 @@ nv50_mpeg = {
 int
 nv50_mpeg_new(struct nvkm_device *device, int index, struct nvkm_engine **pmpeg)
 {
-	return nvkm_engine_new_(&nv50_mpeg, device, index, 0x00400002,
-				true, pmpeg);
+	return nvkm_engine_new_(&nv50_mpeg, device, index, true, pmpeg);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/g98.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/g98.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/g98.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/g98.c	2016-07-24 15:23:50.000000000 -0400
@@ -35,7 +35,6 @@ g98_mspdec_init(struct nvkm_falcon *mspd
 
 static const struct nvkm_falcon_func
 g98_mspdec = {
-	.pmc_enable = 0x01020000,
 	.init = g98_mspdec_init,
 	.sclass = {
 		{ -1, -1, G98_MSPDEC },
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/gf100.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/gf100.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/gf100.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/gf100.c	2016-07-24 15:23:50.000000000 -0400
@@ -35,7 +35,6 @@ gf100_mspdec_init(struct nvkm_falcon *ms
 
 static const struct nvkm_falcon_func
 gf100_mspdec = {
-	.pmc_enable = 0x00020000,
 	.init = gf100_mspdec_init,
 	.sclass = {
 		{ -1, -1, GF100_MSPDEC },
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/gk104.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/gk104.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/gk104.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/gk104.c	2016-07-24 15:23:50.000000000 -0400
@@ -27,7 +27,6 @@
 
 static const struct nvkm_falcon_func
 gk104_mspdec = {
-	.pmc_enable = 0x00020000,
 	.init = gf100_mspdec_init,
 	.sclass = {
 		{ -1, -1, GK104_MSPDEC },
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/gt215.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/gt215.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/gt215.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/mspdec/gt215.c	2016-07-24 15:23:50.000000000 -0400
@@ -27,7 +27,6 @@
 
 static const struct nvkm_falcon_func
 gt215_mspdec = {
-	.pmc_enable = 0x01020000,
 	.init = g98_mspdec_init,
 	.sclass = {
 		{ -1, -1, GT212_MSPDEC },
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/msppp/g98.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/msppp/g98.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/msppp/g98.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/msppp/g98.c	2016-07-24 15:23:50.000000000 -0400
@@ -35,7 +35,6 @@ g98_msppp_init(struct nvkm_falcon *msppp
 
 static const struct nvkm_falcon_func
 g98_msppp = {
-	.pmc_enable = 0x00400002,
 	.init = g98_msppp_init,
 	.sclass = {
 		{ -1, -1, G98_MSPPP },
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/msppp/gf100.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/msppp/gf100.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/msppp/gf100.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/msppp/gf100.c	2016-07-24 15:23:50.000000000 -0400
@@ -35,7 +35,6 @@ gf100_msppp_init(struct nvkm_falcon *msp
 
 static const struct nvkm_falcon_func
 gf100_msppp = {
-	.pmc_enable = 0x00000002,
 	.init = gf100_msppp_init,
 	.sclass = {
 		{ -1, -1, GF100_MSPPP },
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/msppp/gt215.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/msppp/gt215.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/msppp/gt215.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/msppp/gt215.c	2016-07-24 15:23:50.000000000 -0400
@@ -27,7 +27,6 @@
 
 static const struct nvkm_falcon_func
 gt215_msppp = {
-	.pmc_enable = 0x00400002,
 	.init = g98_msppp_init,
 	.sclass = {
 		{ -1, -1, GT212_MSPPP },
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/msvld/g98.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/msvld/g98.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/msvld/g98.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/msvld/g98.c	2016-07-24 15:23:50.000000000 -0400
@@ -35,7 +35,6 @@ g98_msvld_init(struct nvkm_falcon *msvld
 
 static const struct nvkm_falcon_func
 g98_msvld = {
-	.pmc_enable = 0x04008000,
 	.init = g98_msvld_init,
 	.sclass = {
 		{ -1, -1, G98_MSVLD },
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/msvld/gf100.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/msvld/gf100.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/msvld/gf100.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/msvld/gf100.c	2016-07-24 15:23:50.000000000 -0400
@@ -35,7 +35,6 @@ gf100_msvld_init(struct nvkm_falcon *msv
 
 static const struct nvkm_falcon_func
 gf100_msvld = {
-	.pmc_enable = 0x00008000,
 	.init = gf100_msvld_init,
 	.sclass = {
 		{ -1, -1, GF100_MSVLD },
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/msvld/gk104.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/msvld/gk104.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/msvld/gk104.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/msvld/gk104.c	2016-07-24 15:23:50.000000000 -0400
@@ -27,7 +27,6 @@
 
 static const struct nvkm_falcon_func
 gk104_msvld = {
-	.pmc_enable = 0x00008000,
 	.init = gf100_msvld_init,
 	.sclass = {
 		{ -1, -1, GK104_MSVLD },
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/msvld/gt215.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/msvld/gt215.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/msvld/gt215.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/msvld/gt215.c	2016-07-24 15:23:50.000000000 -0400
@@ -27,7 +27,6 @@
 
 static const struct nvkm_falcon_func
 gt215_msvld = {
-	.pmc_enable = 0x04008000,
 	.init = g98_msvld_init,
 	.sclass = {
 		{ -1, -1, GT212_MSVLD },
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/msvld/mcp89.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/msvld/mcp89.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/msvld/mcp89.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/msvld/mcp89.c	2016-07-24 15:23:50.000000000 -0400
@@ -27,7 +27,6 @@
 
 static const struct nvkm_falcon_func
 mcp89_msvld = {
-	.pmc_enable = 0x04008000,
 	.init = g98_msvld_init,
 	.sclass = {
 		{ -1, -1, IGT21A_MSVLD },
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c	2016-07-24 15:23:50.000000000 -0400
@@ -863,5 +863,5 @@ nvkm_pm_ctor(const struct nvkm_pm_func *
 	pm->func = func;
 	INIT_LIST_HEAD(&pm->domains);
 	INIT_LIST_HEAD(&pm->sources);
-	return nvkm_engine_ctor(&nvkm_pm, device, index, 0, true, &pm->engine);
+	return nvkm_engine_ctor(&nvkm_pm, device, index, true, &pm->engine);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/sec/g98.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/sec/g98.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/sec/g98.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/sec/g98.c	2016-07-24 15:23:50.000000000 -0400
@@ -66,7 +66,6 @@ g98_sec = {
 	.code.size = sizeof(g98_sec_code),
 	.data.data = g98_sec_data,
 	.data.size = sizeof(g98_sec_data),
-	.pmc_enable = 0x00004000,
 	.intr = g98_sec_intr,
 	.sclass = {
 		{ -1, -1, G98_SEC },
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/sw/base.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/sw/base.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/sw/base.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/sw/base.c	2016-07-24 15:23:50.000000000 -0400
@@ -106,5 +106,5 @@ nvkm_sw_new_(const struct nvkm_sw_func *
 	INIT_LIST_HEAD(&sw->chan);
 	sw->func = func;
 
-	return nvkm_engine_ctor(&nvkm_sw, device, index, 0, true, &sw->engine);
+	return nvkm_engine_ctor(&nvkm_sw, device, index, true, &sw->engine);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/vp/g84.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/vp/g84.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/vp/g84.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/vp/g84.c	2016-07-24 15:23:50.000000000 -0400
@@ -27,7 +27,6 @@
 
 static const struct nvkm_xtensa_func
 g84_vp = {
-	.pmc_enable = 0x01020000,
 	.fifo_val = 0x111,
 	.unkd28 = 0x9c544,
 	.sclass = {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/xtensa.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/xtensa.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/engine/xtensa.c	2016-05-15 19:21:40.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/engine/xtensa.c	2016-07-24 18:18:14.000000000 -0400
@@ -187,6 +187,6 @@ nvkm_xtensa_new_(const struct nvkm_xtens
 	xtensa->addr = addr;
 	*pengine = &xtensa->engine;
 
-	return nvkm_engine_ctor(&nvkm_xtensa, device, index, func->pmc_enable,
+	return nvkm_engine_ctor(&nvkm_xtensa, device, index,
 				enable, &xtensa->engine);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bar/base.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bar/base.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bar/base.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bar/base.c	2016-07-24 15:23:50.000000000 -0400
@@ -77,7 +77,7 @@ void
 nvkm_bar_ctor(const struct nvkm_bar_func *func, struct nvkm_device *device,
 	      int index, struct nvkm_bar *bar)
 {
-	nvkm_subdev_ctor(&nvkm_bar, device, index, 0, &bar->subdev);
+	nvkm_subdev_ctor(&nvkm_bar, device, index, &bar->subdev);
 	bar->func = func;
 	spin_lock_init(&bar->lock);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c	2016-07-24 15:23:50.000000000 -0400
@@ -105,7 +105,7 @@ nvkm_bios_new(struct nvkm_device *device
 
 	if (!(bios = *pbios = kzalloc(sizeof(*bios), GFP_KERNEL)))
 		return -ENOMEM;
-	nvkm_subdev_ctor(&nvkm_bios, device, index, 0, &bios->subdev);
+	nvkm_subdev_ctor(&nvkm_bios, device, index, &bios->subdev);
 
 	ret = nvbios_shadow(bios);
 	if (ret)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/disp.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/disp.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/disp.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/disp.c	2016-07-24 15:23:50.000000000 -0400
@@ -141,7 +141,8 @@ nvbios_ocfg_parse(struct nvkm_bios *bios
 {
 	u16 data = nvbios_ocfg_entry(bios, outp, idx, ver, hdr, cnt, len);
 	if (data) {
-		info->match     = nvbios_rd16(bios, data + 0x00);
+		info->proto     = nvbios_rd08(bios, data + 0x00);
+		info->flags     = nvbios_rd16(bios, data + 0x01);
 		info->clkcmp[0] = nvbios_rd16(bios, data + 0x02);
 		info->clkcmp[1] = nvbios_rd16(bios, data + 0x04);
 	}
@@ -149,12 +150,13 @@ nvbios_ocfg_parse(struct nvkm_bios *bios
 }
 
 u16
-nvbios_ocfg_match(struct nvkm_bios *bios, u16 outp, u16 type,
+nvbios_ocfg_match(struct nvkm_bios *bios, u16 outp, u8 proto, u8 flags,
 		  u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_ocfg *info)
 {
 	u16 data, idx = 0;
 	while ((data = nvbios_ocfg_parse(bios, outp, idx++, ver, hdr, cnt, len, info))) {
-		if (info->match == type)
+		if ((info->proto == proto || info->proto == 0xff) &&
+		    (info->flags == flags))
 			break;
 	}
 	return data;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/pll.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/pll.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/pll.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/pll.c	2016-07-24 15:23:50.000000000 -0400
@@ -81,9 +81,11 @@ static u16
 pll_limits_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
 {
 	struct bit_entry bit_C;
+	u16 data = 0x0000;
 
-	if (!bit_entry(bios, 'C', &bit_C) && bit_C.length >= 10) {
-		u16 data = nvbios_rd16(bios, bit_C.offset + 8);
+	if (!bit_entry(bios, 'C', &bit_C)) {
+		if (bit_C.version == 1 && bit_C.length >= 10)
+			data = nvbios_rd16(bios, bit_C.offset + 8);
 		if (data) {
 			*ver = nvbios_rd08(bios, data + 0);
 			*hdr = nvbios_rd08(bios, data + 1);
@@ -94,7 +96,7 @@ pll_limits_table(struct nvkm_bios *bios,
 	}
 
 	if (bmp_version(bios) >= 0x0524) {
-		u16 data = nvbios_rd16(bios, bios->bmp_offset + 142);
+		data = nvbios_rd16(bios, bios->bmp_offset + 142);
 		if (data) {
 			*ver = nvbios_rd08(bios, data + 0);
 			*hdr = 1;
@@ -105,7 +107,7 @@ pll_limits_table(struct nvkm_bios *bios,
 	}
 
 	*ver = 0x00;
-	return 0x0000;
+	return data;
 }
 
 static struct pll_mapping *
@@ -156,7 +158,7 @@ pll_map_reg(struct nvkm_bios *bios, u32
 	}
 
 	map = pll_map(bios);
-	while (map->reg) {
+	while (map && map->reg) {
 		if (map->reg == reg && *ver >= 0x20) {
 			u16 addr = (data += hdr);
 			*type = map->type;
@@ -198,7 +200,7 @@ pll_map_type(struct nvkm_bios *bios, u8
 	}
 
 	map = pll_map(bios);
-	while (map->reg) {
+	while (map && map->reg) {
 		if (map->type == type && *ver >= 0x20) {
 			u16 addr = (data += hdr);
 			*reg = map->reg;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bus/base.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bus/base.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bus/base.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bus/base.c	2016-07-24 15:23:50.000000000 -0400
@@ -58,7 +58,7 @@ nvkm_bus_new_(const struct nvkm_bus_func
 	struct nvkm_bus *bus;
 	if (!(bus = *pbus = kzalloc(sizeof(*bus), GFP_KERNEL)))
 		return -ENOMEM;
-	nvkm_subdev_ctor(&nvkm_bus, device, index, 0, &bus->subdev);
+	nvkm_subdev_ctor(&nvkm_bus, device, index, &bus->subdev);
 	bus->func = func;
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c	2016-07-24 15:23:50.000000000 -0400
@@ -564,7 +564,7 @@ nvkm_clk_ctor(const struct nvkm_clk_func
 	int ret, idx, arglen;
 	const char *mode;
 
-	nvkm_subdev_ctor(&nvkm_clk, device, index, 0, &clk->subdev);
+	nvkm_subdev_ctor(&nvkm_clk, device, index, &clk->subdev);
 	clk->func = func;
 	INIT_LIST_HEAD(&clk->states);
 	clk->domains = func->domains;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/base.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/base.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/base.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/base.c	2016-07-24 15:23:50.000000000 -0400
@@ -83,6 +83,12 @@ nvkm_devinit_preinit(struct nvkm_subdev
 	if (init->func->preinit)
 		init->func->preinit(init);
 
+	/* Override the post flag during the first call if NvForcePost is set */
+	if (init->force_post) {
+		init->post = init->force_post;
+		init->force_post = false;
+	}
+
 	/* unlock the extended vga crtc regs */
 	nvkm_lockvgac(subdev->device, false);
 	return 0;
@@ -124,7 +130,7 @@ nvkm_devinit_ctor(const struct nvkm_devi
 		  struct nvkm_device *device, int index,
 		  struct nvkm_devinit *init)
 {
-	nvkm_subdev_ctor(&nvkm_devinit, device, index, 0, &init->subdev);
+	nvkm_subdev_ctor(&nvkm_devinit, device, index, &init->subdev);
 	init->func = func;
-	init->post = nvkm_boolopt(device->cfgopt, "NvForcePost", false);
+	init->force_post = nvkm_boolopt(device->cfgopt, "NvForcePost", false);
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gf100.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gf100.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gf100.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gf100.c	2016-07-24 15:23:50.000000000 -0400
@@ -97,9 +97,11 @@ gf100_devinit_preinit(struct nvkm_devini
 	struct nvkm_subdev *subdev = &init->base.subdev;
 	struct nvkm_device *device = subdev->device;
 
-	/* This bit is set by devinit, and flips back to 0 on suspend */
-	if (!base->post)
-		base->post = ((nvkm_rd32(device, 0x2240c) & BIT(1)) == 0);
+	/*
+	 * This bit is set by devinit, and flips back to 0 on suspend. We
+	 * can use it as a reliable way to know whether we should run devinit.
+	 */
+	base->post = ((nvkm_rd32(device, 0x2240c) & BIT(1)) == 0);
 }
 
 static const struct nvkm_devinit_func
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c	2016-07-24 15:23:50.000000000 -0400
@@ -24,6 +24,7 @@
 #include "priv.h"
 #include "ram.h"
 
+#include <core/memory.h>
 #include <subdev/bios.h>
 #include <subdev/bios/M0203.h>
 #include <engine/gr.h>
@@ -98,6 +99,7 @@ static int
 nvkm_fb_oneinit(struct nvkm_subdev *subdev)
 {
 	struct nvkm_fb *fb = nvkm_fb(subdev);
+
 	if (fb->func->ram_new) {
 		int ret = fb->func->ram_new(fb, &fb->ram);
 		if (ret) {
@@ -105,6 +107,13 @@ nvkm_fb_oneinit(struct nvkm_subdev *subd
 			return ret;
 		}
 	}
+
+	if (fb->func->oneinit) {
+		int ret = fb->func->oneinit(fb);
+		if (ret)
+			return ret;
+	}
+
 	return 0;
 }
 
@@ -134,6 +143,9 @@ nvkm_fb_dtor(struct nvkm_subdev *subdev)
 	struct nvkm_fb *fb = nvkm_fb(subdev);
 	int i;
 
+	nvkm_memory_del(&fb->mmu_wr);
+	nvkm_memory_del(&fb->mmu_rd);
+
 	for (i = 0; i < fb->tile.regions; i++)
 		fb->func->tile.fini(fb, i, &fb->tile.region[i]);
 
@@ -156,7 +168,7 @@ void
 nvkm_fb_ctor(const struct nvkm_fb_func *func, struct nvkm_device *device,
 	     int index, struct nvkm_fb *fb)
 {
-	nvkm_subdev_ctor(&nvkm_fb, device, index, 0, &fb->subdev);
+	nvkm_subdev_ctor(&nvkm_fb, device, index, &fb->subdev);
 	fb->func = func;
 	fb->tile.regions = fb->func->tile.regions;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c	2016-07-24 15:23:50.000000000 -0400
@@ -24,6 +24,9 @@
 #include "gf100.h"
 #include "ram.h"
 
+#include <core/memory.h>
+#include <core/option.h>
+
 extern const u8 gf100_pte_storage_type_map[256];
 
 bool
@@ -46,6 +49,28 @@ gf100_fb_intr(struct nvkm_fb *base)
 		nvkm_debug(subdev, "PBFB intr\n");
 }
 
+int
+gf100_fb_oneinit(struct nvkm_fb *fb)
+{
+	struct nvkm_device *device = fb->subdev.device;
+	int ret, size = 0x1000;
+
+	size = nvkm_longopt(device->cfgopt, "MmuDebugBufferSize", size);
+	size = min(size, 0x1000);
+
+	ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, size, 0x1000,
+			      false, &fb->mmu_rd);
+	if (ret)
+		return ret;
+
+	ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, size, 0x1000,
+			      false, &fb->mmu_wr);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
 void
 gf100_fb_init(struct nvkm_fb *base)
 {
@@ -98,6 +123,7 @@ gf100_fb_new_(const struct nvkm_fb_func
 static const struct nvkm_fb_func
 gf100_fb = {
 	.dtor = gf100_fb_dtor,
+	.oneinit = gf100_fb_oneinit,
 	.init = gf100_fb_init,
 	.intr = gf100_fb_intr,
 	.ram_new = gf100_ram_new,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.c	2016-07-24 15:23:50.000000000 -0400
@@ -27,6 +27,7 @@
 static const struct nvkm_fb_func
 gk104_fb = {
 	.dtor = gf100_fb_dtor,
+	.oneinit = gf100_fb_oneinit,
 	.init = gf100_fb_init,
 	.intr = gf100_fb_intr,
 	.ram_new = gk104_ram_new,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk20a.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk20a.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk20a.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk20a.c	2016-07-24 15:23:50.000000000 -0400
@@ -21,15 +21,20 @@
  */
 #include "priv.h"
 
+#include <core/memory.h>
+
 static void
 gk20a_fb_init(struct nvkm_fb *fb)
 {
 	struct nvkm_device *device = fb->subdev.device;
 	nvkm_mask(device, 0x100c80, 0x00000001, 0x00000000); /* 128KiB lpg */
+	nvkm_wr32(device, 0x100cc8, nvkm_memory_addr(fb->mmu_wr) >> 8);
+	nvkm_wr32(device, 0x100ccc, nvkm_memory_addr(fb->mmu_rd) >> 8);
 }
 
 static const struct nvkm_fb_func
 gk20a_fb = {
+	.oneinit = gf100_fb_oneinit,
 	.init = gk20a_fb_init,
 	.memtype_valid = gf100_fb_memtype_valid,
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm107.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm107.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm107.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm107.c	2016-07-24 15:23:50.000000000 -0400
@@ -27,6 +27,7 @@
 static const struct nvkm_fb_func
 gm107_fb = {
 	.dtor = gf100_fb_dtor,
+	.oneinit = gf100_fb_oneinit,
 	.init = gf100_fb_init,
 	.intr = gf100_fb_intr,
 	.ram_new = gm107_ram_new,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+#include "gf100.h"
+#include "ram.h"
+
+#include <core/memory.h>
+
+static void
+gm200_fb_init(struct nvkm_fb *base)
+{
+	struct gf100_fb *fb = gf100_fb(base);
+	struct nvkm_device *device = fb->base.subdev.device;
+
+	if (fb->r100c10_page)
+		nvkm_wr32(device, 0x100c10, fb->r100c10 >> 8);
+
+	nvkm_mask(device, 0x100c80, 0x00000001, 0x00000000); /* 128KiB lpg */
+
+	nvkm_wr32(device, 0x100cc8, nvkm_memory_addr(fb->base.mmu_wr) >> 8);
+	nvkm_wr32(device, 0x100ccc, nvkm_memory_addr(fb->base.mmu_rd) >> 8);
+	nvkm_mask(device, 0x100cc4, 0x00060000,
+		  min(nvkm_memory_size(fb->base.mmu_rd) >> 16, (u64)2) << 17);
+}
+
+static const struct nvkm_fb_func
+gm200_fb = {
+	.dtor = gf100_fb_dtor,
+	.oneinit = gf100_fb_oneinit,
+	.init = gm200_fb_init,
+	.intr = gf100_fb_intr,
+	.ram_new = gm107_ram_new,
+	.memtype_valid = gf100_fb_memtype_valid,
+};
+
+int
+gm200_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb)
+{
+	return gf100_fb_new_(&gm200_fb, device, index, pfb);
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild	2016-07-24 15:23:50.000000000 -0400
@@ -23,6 +23,7 @@ nvkm-y += nvkm/subdev/fb/gf100.o
 nvkm-y += nvkm/subdev/fb/gk104.o
 nvkm-y += nvkm/subdev/fb/gk20a.o
 nvkm-y += nvkm/subdev/fb/gm107.o
+nvkm-y += nvkm/subdev/fb/gm200.o
 
 nvkm-y += nvkm/subdev/fb/ram.o
 nvkm-y += nvkm/subdev/fb/ramnv04.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h	2016-07-24 15:23:50.000000000 -0400
@@ -6,6 +6,7 @@ struct nvkm_bios;
 
 struct nvkm_fb_func {
 	void *(*dtor)(struct nvkm_fb *);
+	int (*oneinit)(struct nvkm_fb *);
 	void (*init)(struct nvkm_fb *);
 	void (*intr)(struct nvkm_fb *);
 
@@ -58,5 +59,6 @@ void nv44_fb_tile_prog(struct nvkm_fb *,
 void nv46_fb_tile_init(struct nvkm_fb *, int i, u32 addr, u32 size,
 		       u32 pitch, u32 flags, struct nvkm_fb_tile *);
 
+int gf100_fb_oneinit(struct nvkm_fb *);
 bool gf100_fb_memtype_valid(struct nvkm_fb *, u32);
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fuse/base.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fuse/base.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fuse/base.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fuse/base.c	2016-07-24 15:23:50.000000000 -0400
@@ -47,7 +47,7 @@ nvkm_fuse_new_(const struct nvkm_fuse_fu
 	struct nvkm_fuse *fuse;
 	if (!(fuse = *pfuse = kzalloc(sizeof(*fuse), GFP_KERNEL)))
 		return -ENOMEM;
-	nvkm_subdev_ctor(&nvkm_fuse, device, index, 0, &fuse->subdev);
+	nvkm_subdev_ctor(&nvkm_fuse, device, index, &fuse->subdev);
 	fuse->func = func;
 	spin_lock_init(&fuse->lock);
 	return 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c	2016-07-24 15:23:50.000000000 -0400
@@ -216,7 +216,7 @@ nvkm_gpio_new_(const struct nvkm_gpio_fu
 	if (!(gpio = *pgpio = kzalloc(sizeof(*gpio), GFP_KERNEL)))
 		return -ENOMEM;
 
-	nvkm_subdev_ctor(&nvkm_gpio, device, index, 0, &gpio->subdev);
+	nvkm_subdev_ctor(&nvkm_gpio, device, index, &gpio->subdev);
 	gpio->func = func;
 
 	return nvkm_event_init(&nvkm_gpio_intr_func, 2, func->lines,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c	2016-07-24 15:23:50.000000000 -0400
@@ -254,7 +254,7 @@ nvkm_i2c_new_(const struct nvkm_i2c_func
 	if (!(i2c = *pi2c = kzalloc(sizeof(*i2c), GFP_KERNEL)))
 		return -ENOMEM;
 
-	nvkm_subdev_ctor(&nvkm_i2c, device, index, 0, &i2c->subdev);
+	nvkm_subdev_ctor(&nvkm_i2c, device, index, &i2c->subdev);
 	i2c->func = func;
 	INIT_LIST_HEAD(&i2c->pad);
 	INIT_LIST_HEAD(&i2c->bus);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf100.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf100.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf100.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf100.c	2016-07-24 15:23:50.000000000 -0400
@@ -117,6 +117,6 @@ gf100_ibus_new(struct nvkm_device *devic
 	struct nvkm_subdev *ibus;
 	if (!(ibus = *pibus = kzalloc(sizeof(*ibus), GFP_KERNEL)))
 		return -ENOMEM;
-	nvkm_subdev_ctor(&gf100_ibus, device, index, 0, ibus);
+	nvkm_subdev_ctor(&gf100_ibus, device, index, ibus);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf117.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf117.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf117.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf117.c	2016-07-24 15:23:50.000000000 -0400
@@ -46,6 +46,6 @@ gf117_ibus_new(struct nvkm_device *devic
 	struct nvkm_subdev *ibus;
 	if (!(ibus = *pibus = kzalloc(sizeof(*ibus), GFP_KERNEL)))
 		return -ENOMEM;
-	nvkm_subdev_ctor(&gf117_ibus, device, index, 0, ibus);
+	nvkm_subdev_ctor(&gf117_ibus, device, index, ibus);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk104.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk104.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk104.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk104.c	2016-07-24 15:23:50.000000000 -0400
@@ -120,6 +120,6 @@ gk104_ibus_new(struct nvkm_device *devic
 	struct nvkm_subdev *ibus;
 	if (!(ibus = *pibus = kzalloc(sizeof(*ibus), GFP_KERNEL)))
 		return -ENOMEM;
-	nvkm_subdev_ctor(&gk104_ibus, device, index, 0, ibus);
+	nvkm_subdev_ctor(&gk104_ibus, device, index, ibus);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk20a.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk20a.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk20a.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk20a.c	2016-07-24 15:23:50.000000000 -0400
@@ -84,6 +84,6 @@ gk20a_ibus_new(struct nvkm_device *devic
 	struct nvkm_subdev *ibus;
 	if (!(ibus = *pibus = kzalloc(sizeof(*ibus), GFP_KERNEL)))
 		return -ENOMEM;
-	nvkm_subdev_ctor(&gk20a_ibus, device, index, 0, ibus);
+	nvkm_subdev_ctor(&gk20a_ibus, device, index, ibus);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gm200.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gm200.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gm200.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gm200.c	2016-07-24 15:23:50.000000000 -0400
@@ -35,6 +35,6 @@ gm200_ibus_new(struct nvkm_device *devic
 	struct nvkm_subdev *ibus;
 	if (!(ibus = *pibus = kzalloc(sizeof(*ibus), GFP_KERNEL)))
 		return -ENOMEM;
-	nvkm_subdev_ctor(&gm200_ibus, device, index, 0, ibus);
+	nvkm_subdev_ctor(&gm200_ibus, device, index, ibus);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/base.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/base.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/base.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/base.c	2016-07-24 15:23:50.000000000 -0400
@@ -30,15 +30,14 @@
 
 static bool
 nvkm_iccsense_validate_device(struct i2c_adapter *i2c, u8 addr,
-			      enum nvbios_extdev_type type, u8 rail)
+			      enum nvbios_extdev_type type)
 {
 	switch (type) {
 	case NVBIOS_EXTDEV_INA209:
 	case NVBIOS_EXTDEV_INA219:
-		return rail == 0 && nv_rd16i2cr(i2c, addr, 0x0) >= 0;
+		return nv_rd16i2cr(i2c, addr, 0x0) >= 0;
 	case NVBIOS_EXTDEV_INA3221:
-		return rail <= 3 &&
-		       nv_rd16i2cr(i2c, addr, 0xff) == 0x3220 &&
+		return nv_rd16i2cr(i2c, addr, 0xff) == 0x3220 &&
 		       nv_rd16i2cr(i2c, addr, 0xfe) == 0x5449;
 	default:
 		return false;
@@ -67,8 +66,9 @@ nvkm_iccsense_ina2x9_read(struct nvkm_ic
                           struct nvkm_iccsense_rail *rail,
 			  u8 shunt_reg, u8 bus_reg)
 {
-	return nvkm_iccsense_poll_lane(rail->i2c, rail->addr, shunt_reg, 0,
-				       bus_reg, 3, rail->mohm, 10 * 4);
+	return nvkm_iccsense_poll_lane(rail->sensor->i2c, rail->sensor->addr,
+				       shunt_reg, 0, bus_reg, 3, rail->mohm,
+				       10 * 4);
 }
 
 static int
@@ -89,37 +89,87 @@ static int
 nvkm_iccsense_ina3221_read(struct nvkm_iccsense *iccsense,
 			   struct nvkm_iccsense_rail *rail)
 {
-	return nvkm_iccsense_poll_lane(rail->i2c, rail->addr,
-				       1 + (rail->rail * 2), 3,
-				       2 + (rail->rail * 2), 3, rail->mohm,
+	return nvkm_iccsense_poll_lane(rail->sensor->i2c, rail->sensor->addr,
+				       1 + (rail->idx * 2), 3,
+				       2 + (rail->idx * 2), 3, rail->mohm,
 				       40 * 8);
 }
 
-int
-nvkm_iccsense_read(struct nvkm_iccsense *iccsense, u8 idx)
+static void
+nvkm_iccsense_ina209_config(struct nvkm_iccsense *iccsense,
+			    struct nvkm_iccsense_sensor *sensor)
 {
-	struct nvkm_iccsense_rail *rail;
-
-	if (!iccsense || idx >= iccsense->rail_count)
-		return -EINVAL;
+	struct nvkm_subdev *subdev = &iccsense->subdev;
+	/* configuration:
+	 * 0x0007: 0x0007 shunt and bus continous
+	 * 0x0078: 0x0078 128 samples shunt
+	 * 0x0780: 0x0780 128 samples bus
+	 * 0x1800: 0x0000 +-40 mV shunt range
+	 * 0x2000: 0x0000 16V FSR
+         */
+	u16 value = 0x07ff;
+	nvkm_debug(subdev, "config for sensor id %i: 0x%x\n", sensor->id, value);
+	nv_wr16i2cr(sensor->i2c, sensor->addr, 0x00, value);
+}
 
-	rail = &iccsense->rails[idx];
-	if (!rail->read)
-		return -ENODEV;
+static void
+nvkm_iccsense_ina3221_config(struct nvkm_iccsense *iccsense,
+			     struct nvkm_iccsense_sensor *sensor)
+{
+	struct nvkm_subdev *subdev = &iccsense->subdev;
+	/* configuration:
+	 * 0x0007: 0x0007 shunt and bus continous
+	 * 0x0031: 0x0000 140 us conversion time shunt
+	 * 0x01c0: 0x0000 140 us conversion time bus
+	 * 0x0f00: 0x0f00 1024 samples
+	 * 0x7000: 0x?000 channels
+         */
+	u16 value = 0x0e07;
+	if (sensor->rail_mask & 0x1)
+		value |= 0x1 << 14;
+	if (sensor->rail_mask & 0x2)
+		value |= 0x1 << 13;
+	if (sensor->rail_mask & 0x4)
+		value |= 0x1 << 12;
+	nvkm_debug(subdev, "config for sensor id %i: 0x%x\n", sensor->id, value);
+	nv_wr16i2cr(sensor->i2c, sensor->addr, 0x00, value);
+}
 
-	return rail->read(iccsense, rail);
+static void
+nvkm_iccsense_sensor_config(struct nvkm_iccsense *iccsense,
+		            struct nvkm_iccsense_sensor *sensor)
+{
+	switch (sensor->type) {
+	case NVBIOS_EXTDEV_INA209:
+	case NVBIOS_EXTDEV_INA219:
+		nvkm_iccsense_ina209_config(iccsense, sensor);
+		break;
+	case NVBIOS_EXTDEV_INA3221:
+		nvkm_iccsense_ina3221_config(iccsense, sensor);
+		break;
+	default:
+		break;
+	}
 }
 
 int
 nvkm_iccsense_read_all(struct nvkm_iccsense *iccsense)
 {
-	int result = 0, i;
-	for (i = 0; i < iccsense->rail_count; ++i) {
-		int res = nvkm_iccsense_read(iccsense, i);
-		if (res >= 0)
-			result += res;
-		else
+	int result = 0;
+	struct nvkm_iccsense_rail *rail;
+
+	if (!iccsense)
+		return -EINVAL;
+
+	list_for_each_entry(rail, &iccsense->rails, head) {
+		int res;
+		if (!rail->read)
+			return -ENODEV;
+
+		res = rail->read(iccsense, rail);
+		if (res < 0)
 			return res;
+		result += res;
 	}
 	return result;
 }
@@ -128,89 +178,160 @@ static void *
 nvkm_iccsense_dtor(struct nvkm_subdev *subdev)
 {
 	struct nvkm_iccsense *iccsense = nvkm_iccsense(subdev);
+	struct nvkm_iccsense_sensor *sensor, *tmps;
+	struct nvkm_iccsense_rail *rail, *tmpr;
 
-	if (iccsense->rails)
-		kfree(iccsense->rails);
+	list_for_each_entry_safe(sensor, tmps, &iccsense->sensors, head) {
+		list_del(&sensor->head);
+		kfree(sensor);
+	}
+	list_for_each_entry_safe(rail, tmpr, &iccsense->rails, head) {
+		list_del(&rail->head);
+		kfree(rail);
+	}
 
 	return iccsense;
 }
 
+static struct nvkm_iccsense_sensor*
+nvkm_iccsense_create_sensor(struct nvkm_iccsense *iccsense, u8 id)
+{
+
+	struct nvkm_subdev *subdev = &iccsense->subdev;
+	struct nvkm_bios *bios = subdev->device->bios;
+	struct nvkm_i2c *i2c = subdev->device->i2c;
+	struct nvbios_extdev_func extdev;
+	struct nvkm_i2c_bus *i2c_bus;
+	struct nvkm_iccsense_sensor *sensor;
+	u8 addr;
+
+	if (!i2c || !bios || nvbios_extdev_parse(bios, id, &extdev))
+		return NULL;
+
+	if (extdev.type == 0xff)
+		return NULL;
+
+	if (extdev.type != NVBIOS_EXTDEV_INA209 &&
+	    extdev.type != NVBIOS_EXTDEV_INA219 &&
+	    extdev.type != NVBIOS_EXTDEV_INA3221) {
+		iccsense->data_valid = false;
+		nvkm_error(subdev, "Unknown sensor type %x, power reading "
+			   "disabled\n", extdev.type);
+		return NULL;
+	}
+
+	if (extdev.bus)
+		i2c_bus = nvkm_i2c_bus_find(i2c, NVKM_I2C_BUS_SEC);
+	else
+		i2c_bus = nvkm_i2c_bus_find(i2c, NVKM_I2C_BUS_PRI);
+	if (!i2c_bus)
+		return NULL;
+
+	addr = extdev.addr >> 1;
+	if (!nvkm_iccsense_validate_device(&i2c_bus->i2c, addr,
+					   extdev.type)) {
+		iccsense->data_valid = false;
+		nvkm_warn(subdev, "found invalid sensor id: %i, power reading"
+			  "might be invalid\n", id);
+		return NULL;
+	}
+
+	sensor = kmalloc(sizeof(*sensor), GFP_KERNEL);
+	if (!sensor)
+		return NULL;
+
+	list_add_tail(&sensor->head, &iccsense->sensors);
+	sensor->id = id;
+	sensor->type = extdev.type;
+	sensor->i2c = &i2c_bus->i2c;
+	sensor->addr = addr;
+	sensor->rail_mask = 0x0;
+	return sensor;
+}
+
+static struct nvkm_iccsense_sensor*
+nvkm_iccsense_get_sensor(struct nvkm_iccsense *iccsense, u8 id)
+{
+	struct nvkm_iccsense_sensor *sensor;
+	list_for_each_entry(sensor, &iccsense->sensors, head) {
+		if (sensor->id == id)
+			return sensor;
+	}
+	return nvkm_iccsense_create_sensor(iccsense, id);
+}
+
 static int
 nvkm_iccsense_oneinit(struct nvkm_subdev *subdev)
 {
 	struct nvkm_iccsense *iccsense = nvkm_iccsense(subdev);
 	struct nvkm_bios *bios = subdev->device->bios;
-	struct nvkm_i2c *i2c = subdev->device->i2c;
 	struct nvbios_iccsense stbl;
 	int i;
 
-	if (!i2c || !bios || nvbios_iccsense_parse(bios, &stbl)
-	    || !stbl.nr_entry)
+	if (!bios || nvbios_iccsense_parse(bios, &stbl) || !stbl.nr_entry)
 		return 0;
 
-	iccsense->rails = kmalloc(sizeof(*iccsense->rails) * stbl.nr_entry,
-	                          GFP_KERNEL);
-	if (!iccsense->rails)
-		return -ENOMEM;
-
 	iccsense->data_valid = true;
 	for (i = 0; i < stbl.nr_entry; ++i) {
 		struct pwr_rail_t *r = &stbl.rail[i];
-		struct nvbios_extdev_func extdev;
 		struct nvkm_iccsense_rail *rail;
-		struct nvkm_i2c_bus *i2c_bus;
-		u8 addr;
+		struct nvkm_iccsense_sensor *sensor;
+		int (*read)(struct nvkm_iccsense *,
+			    struct nvkm_iccsense_rail *);
 
 		if (!r->mode || r->resistor_mohm == 0)
 			continue;
 
-		if (nvbios_extdev_parse(bios, r->extdev_id, &extdev))
-			continue;
-
-		if (extdev.type == 0xff)
-			continue;
-
-		if (extdev.bus)
-			i2c_bus = nvkm_i2c_bus_find(i2c, NVKM_I2C_BUS_SEC);
-		else
-			i2c_bus = nvkm_i2c_bus_find(i2c, NVKM_I2C_BUS_PRI);
-		if (!i2c_bus)
-			continue;
-
-		addr = extdev.addr >> 1;
-		if (!nvkm_iccsense_validate_device(&i2c_bus->i2c, addr,
-						   extdev.type, r->rail)) {
-			iccsense->data_valid = false;
-			nvkm_warn(subdev, "found unknown or invalid rail entry"
-				  " type 0x%x rail %i, power reading might be"
-				  " invalid\n", extdev.type, r->rail);
+		sensor = nvkm_iccsense_get_sensor(iccsense, r->extdev_id);
+		if (!sensor)
 			continue;
-		}
 
-		rail = &iccsense->rails[iccsense->rail_count];
-		switch (extdev.type) {
+		switch (sensor->type) {
 		case NVBIOS_EXTDEV_INA209:
-			rail->read = nvkm_iccsense_ina209_read;
+			if (r->rail != 0)
+				continue;
+			read = nvkm_iccsense_ina209_read;
 			break;
 		case NVBIOS_EXTDEV_INA219:
-			rail->read = nvkm_iccsense_ina219_read;
+			if (r->rail != 0)
+				continue;
+			read = nvkm_iccsense_ina219_read;
 			break;
 		case NVBIOS_EXTDEV_INA3221:
-			rail->read = nvkm_iccsense_ina3221_read;
+			if (r->rail >= 3)
+				continue;
+			read = nvkm_iccsense_ina3221_read;
 			break;
+		default:
+			continue;
 		}
 
-		rail->addr = addr;
-		rail->rail = r->rail;
+		rail = kmalloc(sizeof(*rail), GFP_KERNEL);
+		if (!rail)
+			return -ENOMEM;
+		sensor->rail_mask |= 1 << r->rail;
+		rail->read = read;
+		rail->sensor = sensor;
+		rail->idx = r->rail;
 		rail->mohm = r->resistor_mohm;
-		rail->i2c = &i2c_bus->i2c;
-		++iccsense->rail_count;
+		list_add_tail(&rail->head, &iccsense->rails);
 	}
 	return 0;
 }
 
+static int
+nvkm_iccsense_init(struct nvkm_subdev *subdev)
+{
+	struct nvkm_iccsense *iccsense = nvkm_iccsense(subdev);
+	struct nvkm_iccsense_sensor *sensor;
+	list_for_each_entry(sensor, &iccsense->sensors, head)
+		nvkm_iccsense_sensor_config(iccsense, sensor);
+	return 0;
+}
+
 struct nvkm_subdev_func iccsense_func = {
 	.oneinit = nvkm_iccsense_oneinit,
+	.init = nvkm_iccsense_init,
 	.dtor = nvkm_iccsense_dtor,
 };
 
@@ -218,7 +339,7 @@ void
 nvkm_iccsense_ctor(struct nvkm_device *device, int index,
 		   struct nvkm_iccsense *iccsense)
 {
-	nvkm_subdev_ctor(&iccsense_func, device, index, 0, &iccsense->subdev);
+	nvkm_subdev_ctor(&iccsense_func, device, index, &iccsense->subdev);
 }
 
 int
@@ -227,6 +348,8 @@ nvkm_iccsense_new_(struct nvkm_device *d
 {
 	if (!(*iccsense = kzalloc(sizeof(**iccsense), GFP_KERNEL)))
 		return -ENOMEM;
+	INIT_LIST_HEAD(&(*iccsense)->sensors);
+	INIT_LIST_HEAD(&(*iccsense)->rails);
 	nvkm_iccsense_ctor(device, index, *iccsense);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/priv.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/priv.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/priv.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/priv.h	2016-07-24 15:23:50.000000000 -0400
@@ -2,12 +2,22 @@
 #define __NVKM_ICCSENSE_PRIV_H__
 #define nvkm_iccsense(p) container_of((p), struct nvkm_iccsense, subdev)
 #include <subdev/iccsense.h>
+#include <subdev/bios/extdev.h>
 
-struct nvkm_iccsense_rail {
-	int (*read)(struct nvkm_iccsense *, struct nvkm_iccsense_rail *);
+struct nvkm_iccsense_sensor {
+	struct list_head head;
+	int id;
+	enum nvbios_extdev_type type;
 	struct i2c_adapter *i2c;
 	u8 addr;
-	u8 rail;
+	u8 rail_mask;
+};
+
+struct nvkm_iccsense_rail {
+	struct list_head head;
+	int (*read)(struct nvkm_iccsense *, struct nvkm_iccsense_rail *);
+	struct nvkm_iccsense_sensor *sensor;
+	u8 idx;
 	u8 mohm;
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c	2016-07-24 15:23:50.000000000 -0400
@@ -311,7 +311,7 @@ nvkm_instmem_ctor(const struct nvkm_inst
 		  struct nvkm_device *device, int index,
 		  struct nvkm_instmem *imem)
 {
-	nvkm_subdev_ctor(&nvkm_instmem, device, index, 0, &imem->subdev);
+	nvkm_subdev_ctor(&nvkm_instmem, device, index, &imem->subdev);
 	imem->func = func;
 	spin_lock_init(&imem->lock);
 	INIT_LIST_HEAD(&imem->list);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/Kbuild linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/Kbuild
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/Kbuild	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/Kbuild	2016-07-24 15:23:50.000000000 -0400
@@ -19,4 +19,5 @@ include $(src)/nvkm/subdev/pmu/Kbuild
 include $(src)/nvkm/subdev/secboot/Kbuild
 include $(src)/nvkm/subdev/therm/Kbuild
 include $(src)/nvkm/subdev/timer/Kbuild
+include $(src)/nvkm/subdev/top/Kbuild
 include $(src)/nvkm/subdev/volt/Kbuild
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c	2016-07-24 15:23:50.000000000 -0400
@@ -138,7 +138,7 @@ nvkm_ltc_new_(const struct nvkm_ltc_func
 	if (!(ltc = *pltc = kzalloc(sizeof(*ltc), GFP_KERNEL)))
 		return -ENOMEM;
 
-	nvkm_subdev_ctor(&nvkm_ltc, device, index, 0, &ltc->subdev);
+	nvkm_subdev_ctor(&nvkm_ltc, device, index, &ltc->subdev);
 	ltc->func = func;
 	ltc->zbc_min = 1; /* reserve 0 for disabled */
 	ltc->zbc_max = min(func->zbc, NVKM_LTC_MAX_ZBC_CNT) - 1;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm107.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm107.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm107.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm107.c	2016-07-24 15:23:50.000000000 -0400
@@ -69,11 +69,11 @@ gm107_ltc_zbc_clear_depth(struct nvkm_lt
 }
 
 static void
-gm107_ltc_lts_isr(struct nvkm_ltc *ltc, int c, int s)
+gm107_ltc_intr_lts(struct nvkm_ltc *ltc, int c, int s)
 {
 	struct nvkm_subdev *subdev = &ltc->subdev;
 	struct nvkm_device *device = subdev->device;
-	u32 base = 0x140000 + (c * 0x2000) + (s * 0x200);
+	u32 base = 0x140400 + (c * 0x2000) + (s * 0x200);
 	u32 stat = nvkm_rd32(device, base + 0x00c);
 
 	if (stat) {
@@ -92,7 +92,7 @@ gm107_ltc_intr(struct nvkm_ltc *ltc)
 	while (mask) {
 		u32 s, c = __ffs(mask);
 		for (s = 0; s < ltc->lts_nr; s++)
-			gm107_ltc_lts_isr(ltc, c, s);
+			gm107_ltc_intr_lts(ltc, c, s);
 		mask &= ~(1 << c);
 	}
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm200.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm200.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm200.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm200.c	2016-07-24 15:23:50.000000000 -0400
@@ -46,7 +46,7 @@ static const struct nvkm_ltc_func
 gm200_ltc = {
 	.oneinit = gm200_ltc_oneinit,
 	.init = gm200_ltc_init,
-	.intr = gm107_ltc_intr, /*XXX: not validated */
+	.intr = gm107_ltc_intr,
 	.cbc_clear = gm107_ltc_cbc_clear,
 	.cbc_wait = gm107_ltc_cbc_wait,
 	.zbc = 16,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c	2016-07-24 15:23:50.000000000 -0400
@@ -24,6 +24,7 @@
 #include "priv.h"
 
 #include <core/option.h>
+#include <subdev/top.h>
 
 void
 nvkm_mc_unk260(struct nvkm_mc *mc, u32 data)
@@ -58,10 +59,19 @@ nvkm_mc_intr(struct nvkm_mc *mc, bool *h
 {
 	struct nvkm_device *device = mc->subdev.device;
 	struct nvkm_subdev *subdev;
-	const struct nvkm_mc_intr *map = mc->func->intr;
-	u32 stat, intr;
+	const struct nvkm_mc_map *map = mc->func->intr;
+	u32 stat, intr = nvkm_mc_intr_mask(mc);
+	u64 subdevs;
+
+	stat = nvkm_top_intr(device->top, intr, &subdevs);
+	while (subdevs) {
+		enum nvkm_devidx subidx = __ffs64(subdevs);
+		subdev = nvkm_device_subdev(device, subidx);
+		if (subdev)
+			nvkm_subdev_intr(subdev);
+		subdevs &= ~BIT_ULL(subidx);
+	}
 
-	stat = intr = nvkm_mc_intr_mask(mc);
 	while (map->stat) {
 		if (intr & map->stat) {
 			subdev = nvkm_device_subdev(device, map->unit);
@@ -77,6 +87,36 @@ nvkm_mc_intr(struct nvkm_mc *mc, bool *h
 	*handled = intr != 0;
 }
 
+static void
+nvkm_mc_reset_(struct nvkm_mc *mc, enum nvkm_devidx devidx)
+{
+	struct nvkm_device *device = mc->subdev.device;
+	const struct nvkm_mc_map *map;
+	u64 pmc_enable;
+
+	if (!(pmc_enable = nvkm_top_reset(device->top, devidx))) {
+		for (map = mc->func->reset; map && map->stat; map++) {
+			if (map->unit == devidx) {
+				pmc_enable = map->stat;
+				break;
+			}
+		}
+	}
+
+	if (pmc_enable) {
+		nvkm_mask(device, 0x000200, pmc_enable, 0x00000000);
+		nvkm_mask(device, 0x000200, pmc_enable, pmc_enable);
+		nvkm_rd32(device, 0x000200);
+	}
+}
+
+void
+nvkm_mc_reset(struct nvkm_mc *mc, enum nvkm_devidx devidx)
+{
+	if (likely(mc))
+		nvkm_mc_reset_(mc, devidx);
+}
+
 static int
 nvkm_mc_fini(struct nvkm_subdev *subdev, bool suspend)
 {
@@ -117,7 +157,7 @@ nvkm_mc_new_(const struct nvkm_mc_func *
 	if (!(mc = *pmc = kzalloc(sizeof(*mc), GFP_KERNEL)))
 		return -ENOMEM;
 
-	nvkm_subdev_ctor(&nvkm_mc, device, index, 0, &mc->subdev);
+	nvkm_subdev_ctor(&nvkm_mc, device, index, &mc->subdev);
 	mc->func = func;
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g84.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g84.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g84.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g84.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+#include "priv.h"
+
+static const struct nvkm_mc_map
+g84_mc_reset[] = {
+	{ 0x04008000, NVKM_ENGINE_BSP },
+	{ 0x02004000, NVKM_ENGINE_CIPHER },
+	{ 0x01020000, NVKM_ENGINE_VP },
+	{ 0x00400002, NVKM_ENGINE_MPEG },
+	{ 0x00201000, NVKM_ENGINE_GR },
+	{ 0x00000100, NVKM_ENGINE_FIFO },
+	{}
+};
+
+const struct nvkm_mc_map
+g84_mc_intr[] = {
+	{ 0x04000000, NVKM_ENGINE_DISP },
+	{ 0x00020000, NVKM_ENGINE_VP },
+	{ 0x00008000, NVKM_ENGINE_BSP },
+	{ 0x00004000, NVKM_ENGINE_CIPHER },
+	{ 0x00001000, NVKM_ENGINE_GR },
+	{ 0x00000100, NVKM_ENGINE_FIFO },
+	{ 0x00000001, NVKM_ENGINE_MPEG },
+	{ 0x0002d101, NVKM_SUBDEV_FB },
+	{ 0x10000000, NVKM_SUBDEV_BUS },
+	{ 0x00200000, NVKM_SUBDEV_GPIO },
+	{ 0x00200000, NVKM_SUBDEV_I2C },
+	{ 0x00100000, NVKM_SUBDEV_TIMER },
+	{},
+};
+
+static const struct nvkm_mc_func
+g84_mc = {
+	.init = nv50_mc_init,
+	.intr = g84_mc_intr,
+	.intr_unarm = nv04_mc_intr_unarm,
+	.intr_rearm = nv04_mc_intr_rearm,
+	.intr_mask = nv04_mc_intr_mask,
+	.reset = g84_mc_reset,
+};
+
+int
+g84_mc_new(struct nvkm_device *device, int index, struct nvkm_mc **pmc)
+{
+	return nvkm_mc_new_(&g84_mc, device, index, pmc);
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g98.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g98.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g98.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g98.c	2016-07-24 15:23:50.000000000 -0400
@@ -23,24 +23,31 @@
  */
 #include "priv.h"
 
-static const struct nvkm_mc_intr
-g98_mc_intr[] = {
-	{ 0x04000000, NVKM_ENGINE_DISP },  /* DISP first, so pageflip timestamps work */
-	{ 0x00000001, NVKM_ENGINE_MSPPP },
+static const struct nvkm_mc_map
+g98_mc_reset[] = {
+	{ 0x04008000, NVKM_ENGINE_MSVLD },
+	{ 0x02004000, NVKM_ENGINE_SEC },
+	{ 0x01020000, NVKM_ENGINE_MSPDEC },
+	{ 0x00400002, NVKM_ENGINE_MSPPP },
+	{ 0x00201000, NVKM_ENGINE_GR },
 	{ 0x00000100, NVKM_ENGINE_FIFO },
-	{ 0x00001000, NVKM_ENGINE_GR },
-	{ 0x00004000, NVKM_ENGINE_SEC },	/* NV84:NVA3 */
-	{ 0x00008000, NVKM_ENGINE_MSVLD },
+	{}
+};
+
+static const struct nvkm_mc_map
+g98_mc_intr[] = {
+	{ 0x04000000, NVKM_ENGINE_DISP },
 	{ 0x00020000, NVKM_ENGINE_MSPDEC },
-	{ 0x00040000, NVKM_SUBDEV_PMU },	/* NVA3:NVC0 */
-	{ 0x00080000, NVKM_SUBDEV_THERM },	/* NVA3:NVC0 */
-	{ 0x00100000, NVKM_SUBDEV_TIMER },
-	{ 0x00200000, NVKM_SUBDEV_GPIO },	/* PMGR->GPIO */
-	{ 0x00200000, NVKM_SUBDEV_I2C }, 	/* PMGR->I2C/AUX */
-	{ 0x00400000, NVKM_ENGINE_CE0 },	/* NVA3-     */
+	{ 0x00008000, NVKM_ENGINE_MSVLD },
+	{ 0x00004000, NVKM_ENGINE_SEC },
+	{ 0x00001000, NVKM_ENGINE_GR },
+	{ 0x00000100, NVKM_ENGINE_FIFO },
+	{ 0x00000001, NVKM_ENGINE_MSPPP },
+	{ 0x0002d101, NVKM_SUBDEV_FB },
 	{ 0x10000000, NVKM_SUBDEV_BUS },
-	{ 0x80000000, NVKM_ENGINE_SW },
-	{ 0x0042d101, NVKM_SUBDEV_FB },
+	{ 0x00200000, NVKM_SUBDEV_GPIO },
+	{ 0x00200000, NVKM_SUBDEV_I2C },
+	{ 0x00100000, NVKM_SUBDEV_TIMER },
 	{},
 };
 
@@ -51,6 +58,7 @@ g98_mc = {
 	.intr_unarm = nv04_mc_intr_unarm,
 	.intr_rearm = nv04_mc_intr_rearm,
 	.intr_mask = nv04_mc_intr_mask,
+	.reset = g98_mc_reset,
 };
 
 int
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c	2016-07-24 15:23:50.000000000 -0400
@@ -23,28 +23,38 @@
  */
 #include "priv.h"
 
-const struct nvkm_mc_intr
-gf100_mc_intr[] = {
-	{ 0x04000000, NVKM_ENGINE_DISP },  /* DISP first, so pageflip timestamps work. */
-	{ 0x00000001, NVKM_ENGINE_MSPPP },
-	{ 0x00000020, NVKM_ENGINE_CE0 },
-	{ 0x00000040, NVKM_ENGINE_CE1 },
-	{ 0x00000080, NVKM_ENGINE_CE2 },
-	{ 0x00000100, NVKM_ENGINE_FIFO },
-	{ 0x00001000, NVKM_ENGINE_GR },
-	{ 0x00002000, NVKM_SUBDEV_FB },
+static const struct nvkm_mc_map
+gf100_mc_reset[] = {
+	{ 0x00020000, NVKM_ENGINE_MSPDEC },
 	{ 0x00008000, NVKM_ENGINE_MSVLD },
-	{ 0x00040000, NVKM_SUBDEV_THERM },
+	{ 0x00001000, NVKM_ENGINE_GR },
+	{ 0x00000100, NVKM_ENGINE_FIFO },
+	{ 0x00000080, NVKM_ENGINE_CE1 },
+	{ 0x00000040, NVKM_ENGINE_CE0 },
+	{ 0x00000002, NVKM_ENGINE_MSPPP },
+	{}
+};
+
+static const struct nvkm_mc_map
+gf100_mc_intr[] = {
+	{ 0x04000000, NVKM_ENGINE_DISP },
 	{ 0x00020000, NVKM_ENGINE_MSPDEC },
-	{ 0x00100000, NVKM_SUBDEV_TIMER },
-	{ 0x00200000, NVKM_SUBDEV_GPIO },	/* PMGR->GPIO */
-	{ 0x00200000, NVKM_SUBDEV_I2C },	/* PMGR->I2C/AUX */
-	{ 0x01000000, NVKM_SUBDEV_PMU },
-	{ 0x02000000, NVKM_SUBDEV_LTC },
-	{ 0x08000000, NVKM_SUBDEV_FB },
-	{ 0x10000000, NVKM_SUBDEV_BUS },
+	{ 0x00008000, NVKM_ENGINE_MSVLD },
+	{ 0x00001000, NVKM_ENGINE_GR },
+	{ 0x00000100, NVKM_ENGINE_FIFO },
+	{ 0x00000040, NVKM_ENGINE_CE1 },
+	{ 0x00000020, NVKM_ENGINE_CE0 },
+	{ 0x00000001, NVKM_ENGINE_MSPPP },
 	{ 0x40000000, NVKM_SUBDEV_IBUS },
-	{ 0x80000000, NVKM_ENGINE_SW },
+	{ 0x10000000, NVKM_SUBDEV_BUS },
+	{ 0x08000000, NVKM_SUBDEV_FB },
+	{ 0x02000000, NVKM_SUBDEV_LTC },
+	{ 0x01000000, NVKM_SUBDEV_PMU },
+	{ 0x00200000, NVKM_SUBDEV_GPIO },
+	{ 0x00200000, NVKM_SUBDEV_I2C },
+	{ 0x00100000, NVKM_SUBDEV_TIMER },
+	{ 0x00040000, NVKM_SUBDEV_THERM },
+	{ 0x00002000, NVKM_SUBDEV_FB },
 	{},
 };
 
@@ -87,6 +97,7 @@ gf100_mc = {
 	.intr_unarm = gf100_mc_intr_unarm,
 	.intr_rearm = gf100_mc_intr_rearm,
 	.intr_mask = gf100_mc_intr_mask,
+	.reset = gf100_mc_reset,
 	.unk260 = gf100_mc_unk260,
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk104.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk104.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk104.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk104.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2016 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+#include "priv.h"
+
+const struct nvkm_mc_map
+gk104_mc_reset[] = {
+	{ 0x00000100, NVKM_ENGINE_FIFO },
+	{}
+};
+
+const struct nvkm_mc_map
+gk104_mc_intr[] = {
+	{ 0x04000000, NVKM_ENGINE_DISP },
+	{ 0x00000100, NVKM_ENGINE_FIFO },
+	{ 0x40000000, NVKM_SUBDEV_IBUS },
+	{ 0x10000000, NVKM_SUBDEV_BUS },
+	{ 0x08000000, NVKM_SUBDEV_FB },
+	{ 0x02000000, NVKM_SUBDEV_LTC },
+	{ 0x01000000, NVKM_SUBDEV_PMU },
+	{ 0x00200000, NVKM_SUBDEV_GPIO },
+	{ 0x00200000, NVKM_SUBDEV_I2C },
+	{ 0x00100000, NVKM_SUBDEV_TIMER },
+	{ 0x00040000, NVKM_SUBDEV_THERM },
+	{ 0x00002000, NVKM_SUBDEV_FB },
+	{},
+};
+
+static const struct nvkm_mc_func
+gk104_mc = {
+	.init = nv50_mc_init,
+	.intr = gk104_mc_intr,
+	.intr_unarm = gf100_mc_intr_unarm,
+	.intr_rearm = gf100_mc_intr_rearm,
+	.intr_mask = gf100_mc_intr_mask,
+	.reset = gk104_mc_reset,
+	.unk260 = gf100_mc_unk260,
+};
+
+int
+gk104_mc_new(struct nvkm_device *device, int index, struct nvkm_mc **pmc)
+{
+	return nvkm_mc_new_(&gk104_mc, device, index, pmc);
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk20a.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk20a.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk20a.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk20a.c	2016-07-24 15:23:50.000000000 -0400
@@ -26,10 +26,11 @@
 static const struct nvkm_mc_func
 gk20a_mc = {
 	.init = nv50_mc_init,
-	.intr = gf100_mc_intr,
+	.intr = gk104_mc_intr,
 	.intr_unarm = gf100_mc_intr_unarm,
 	.intr_rearm = gf100_mc_intr_rearm,
 	.intr_mask = gf100_mc_intr_mask,
+	.reset = gk104_mc_reset,
 };
 
 int
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gt215.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gt215.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gt215.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gt215.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2016 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+#include "priv.h"
+
+static const struct nvkm_mc_map
+gt215_mc_reset[] = {
+	{ 0x04008000, NVKM_ENGINE_MSVLD },
+	{ 0x01020000, NVKM_ENGINE_MSPDEC },
+	{ 0x00802000, NVKM_ENGINE_CE0 },
+	{ 0x00400002, NVKM_ENGINE_MSPPP },
+	{ 0x00201000, NVKM_ENGINE_GR },
+	{ 0x00000100, NVKM_ENGINE_FIFO },
+	{}
+};
+
+static const struct nvkm_mc_map
+gt215_mc_intr[] = {
+	{ 0x04000000, NVKM_ENGINE_DISP },
+	{ 0x00400000, NVKM_ENGINE_CE0 },
+	{ 0x00020000, NVKM_ENGINE_MSPDEC },
+	{ 0x00008000, NVKM_ENGINE_MSVLD },
+	{ 0x00001000, NVKM_ENGINE_GR },
+	{ 0x00000100, NVKM_ENGINE_FIFO },
+	{ 0x00000001, NVKM_ENGINE_MSPPP },
+	{ 0x00429101, NVKM_SUBDEV_FB },
+	{ 0x10000000, NVKM_SUBDEV_BUS },
+	{ 0x00200000, NVKM_SUBDEV_GPIO },
+	{ 0x00200000, NVKM_SUBDEV_I2C },
+	{ 0x00100000, NVKM_SUBDEV_TIMER },
+	{ 0x00080000, NVKM_SUBDEV_THERM },
+	{ 0x00040000, NVKM_SUBDEV_PMU },
+	{},
+};
+
+static const struct nvkm_mc_func
+gt215_mc = {
+	.init = nv50_mc_init,
+	.intr = gt215_mc_intr,
+	.intr_unarm = nv04_mc_intr_unarm,
+	.intr_rearm = nv04_mc_intr_rearm,
+	.intr_mask = nv04_mc_intr_mask,
+	.reset = gt215_mc_reset,
+};
+
+int
+gt215_mc_new(struct nvkm_device *device, int index, struct nvkm_mc **pmc)
+{
+	return nvkm_mc_new_(&gt215_mc, device, index, pmc);
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/Kbuild linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/Kbuild
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/Kbuild	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/Kbuild	2016-07-24 15:23:50.000000000 -0400
@@ -1,7 +1,12 @@
 nvkm-y += nvkm/subdev/mc/base.o
 nvkm-y += nvkm/subdev/mc/nv04.o
+nvkm-y += nvkm/subdev/mc/nv11.o
+nvkm-y += nvkm/subdev/mc/nv17.o
 nvkm-y += nvkm/subdev/mc/nv44.o
 nvkm-y += nvkm/subdev/mc/nv50.o
+nvkm-y += nvkm/subdev/mc/g84.o
 nvkm-y += nvkm/subdev/mc/g98.o
+nvkm-y += nvkm/subdev/mc/gt215.o
 nvkm-y += nvkm/subdev/mc/gf100.o
+nvkm-y += nvkm/subdev/mc/gk104.o
 nvkm-y += nvkm/subdev/mc/gk20a.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv04.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv04.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv04.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv04.c	2016-07-24 15:23:50.000000000 -0400
@@ -23,18 +23,20 @@
  */
 #include "priv.h"
 
-const struct nvkm_mc_intr
-nv04_mc_intr[] = {
-	{ 0x00000001, NVKM_ENGINE_MPEG },	/* NV17- MPEG/ME */
+const struct nvkm_mc_map
+nv04_mc_reset[] = {
+	{ 0x00001000, NVKM_ENGINE_GR },
 	{ 0x00000100, NVKM_ENGINE_FIFO },
+	{}
+};
+
+static const struct nvkm_mc_map
+nv04_mc_intr[] = {
+	{ 0x01010000, NVKM_ENGINE_DISP },
 	{ 0x00001000, NVKM_ENGINE_GR },
-	{ 0x00010000, NVKM_ENGINE_DISP },
-	{ 0x00020000, NVKM_ENGINE_VP },	/* NV40- */
-	{ 0x00100000, NVKM_SUBDEV_TIMER },
-	{ 0x01000000, NVKM_ENGINE_DISP },	/* NV04- PCRTC0 */
-	{ 0x02000000, NVKM_ENGINE_DISP },	/* NV11- PCRTC1 */
+	{ 0x00000100, NVKM_ENGINE_FIFO },
 	{ 0x10000000, NVKM_SUBDEV_BUS },
-	{ 0x80000000, NVKM_ENGINE_SW },
+	{ 0x00100000, NVKM_SUBDEV_TIMER },
 	{}
 };
 
@@ -74,6 +76,7 @@ nv04_mc = {
 	.intr_unarm = nv04_mc_intr_unarm,
 	.intr_rearm = nv04_mc_intr_rearm,
 	.intr_mask = nv04_mc_intr_mask,
+	.reset = nv04_mc_reset,
 };
 
 int
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv11.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv11.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv11.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv11.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2016 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+#include "priv.h"
+
+static const struct nvkm_mc_map
+nv11_mc_intr[] = {
+	{ 0x03010000, NVKM_ENGINE_DISP },
+	{ 0x00001000, NVKM_ENGINE_GR },
+	{ 0x00000100, NVKM_ENGINE_FIFO },
+	{ 0x10000000, NVKM_SUBDEV_BUS },
+	{ 0x00100000, NVKM_SUBDEV_TIMER },
+	{}
+};
+
+static const struct nvkm_mc_func
+nv11_mc = {
+	.init = nv04_mc_init,
+	.intr = nv11_mc_intr,
+	.intr_unarm = nv04_mc_intr_unarm,
+	.intr_rearm = nv04_mc_intr_rearm,
+	.intr_mask = nv04_mc_intr_mask,
+	.reset = nv04_mc_reset,
+};
+
+int
+nv11_mc_new(struct nvkm_device *device, int index, struct nvkm_mc **pmc)
+{
+	return nvkm_mc_new_(&nv11_mc, device, index, pmc);
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv17.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv17.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv17.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv17.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2016 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+#include "priv.h"
+
+const struct nvkm_mc_map
+nv17_mc_reset[] = {
+	{ 0x00001000, NVKM_ENGINE_GR },
+	{ 0x00000100, NVKM_ENGINE_FIFO },
+	{ 0x00000002, NVKM_ENGINE_MPEG },
+	{}
+};
+
+const struct nvkm_mc_map
+nv17_mc_intr[] = {
+	{ 0x03010000, NVKM_ENGINE_DISP },
+	{ 0x00001000, NVKM_ENGINE_GR },
+	{ 0x00000100, NVKM_ENGINE_FIFO },
+	{ 0x00000001, NVKM_ENGINE_MPEG },
+	{ 0x10000000, NVKM_SUBDEV_BUS },
+	{ 0x00100000, NVKM_SUBDEV_TIMER },
+	{}
+};
+
+static const struct nvkm_mc_func
+nv17_mc = {
+	.init = nv04_mc_init,
+	.intr = nv17_mc_intr,
+	.intr_unarm = nv04_mc_intr_unarm,
+	.intr_rearm = nv04_mc_intr_rearm,
+	.intr_mask = nv04_mc_intr_mask,
+	.reset = nv17_mc_reset,
+};
+
+int
+nv17_mc_new(struct nvkm_device *device, int index, struct nvkm_mc **pmc)
+{
+	return nvkm_mc_new_(&nv17_mc, device, index, pmc);
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv44.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv44.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv44.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv44.c	2016-07-24 15:23:50.000000000 -0400
@@ -40,10 +40,11 @@ nv44_mc_init(struct nvkm_mc *mc)
 static const struct nvkm_mc_func
 nv44_mc = {
 	.init = nv44_mc_init,
-	.intr = nv04_mc_intr,
+	.intr = nv17_mc_intr,
 	.intr_unarm = nv04_mc_intr_unarm,
 	.intr_rearm = nv04_mc_intr_rearm,
 	.intr_mask = nv04_mc_intr_mask,
+	.reset = nv17_mc_reset,
 };
 
 int
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv50.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv50.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv50.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv50.c	2016-07-24 15:23:50.000000000 -0400
@@ -23,21 +23,17 @@
  */
 #include "priv.h"
 
-const struct nvkm_mc_intr
+static const struct nvkm_mc_map
 nv50_mc_intr[] = {
-	{ 0x04000000, NVKM_ENGINE_DISP },  /* DISP before FIFO, so pageflip-timestamping works! */
-	{ 0x00000001, NVKM_ENGINE_MPEG },
-	{ 0x00000100, NVKM_ENGINE_FIFO },
+	{ 0x04000000, NVKM_ENGINE_DISP },
 	{ 0x00001000, NVKM_ENGINE_GR },
-	{ 0x00004000, NVKM_ENGINE_CIPHER },	/* NV84- */
-	{ 0x00008000, NVKM_ENGINE_BSP },	/* NV84- */
-	{ 0x00020000, NVKM_ENGINE_VP },	/* NV84- */
-	{ 0x00100000, NVKM_SUBDEV_TIMER },
-	{ 0x00200000, NVKM_SUBDEV_GPIO },	/* PMGR->GPIO */
-	{ 0x00200000, NVKM_SUBDEV_I2C }, 	/* PMGR->I2C/AUX */
+	{ 0x00000100, NVKM_ENGINE_FIFO },
+	{ 0x00000001, NVKM_ENGINE_MPEG },
+	{ 0x00001101, NVKM_SUBDEV_FB },
 	{ 0x10000000, NVKM_SUBDEV_BUS },
-	{ 0x80000000, NVKM_ENGINE_SW },
-	{ 0x0002d101, NVKM_SUBDEV_FB },
+	{ 0x00200000, NVKM_SUBDEV_GPIO },
+	{ 0x00200000, NVKM_SUBDEV_I2C },
+	{ 0x00100000, NVKM_SUBDEV_TIMER },
 	{},
 };
 
@@ -55,6 +51,7 @@ nv50_mc = {
 	.intr_unarm = nv04_mc_intr_unarm,
 	.intr_rearm = nv04_mc_intr_rearm,
 	.intr_mask = nv04_mc_intr_mask,
+	.reset = nv17_mc_reset,
 };
 
 int
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/priv.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/priv.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/priv.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/priv.h	2016-07-24 15:23:50.000000000 -0400
@@ -6,37 +6,42 @@
 int nvkm_mc_new_(const struct nvkm_mc_func *, struct nvkm_device *,
 		 int index, struct nvkm_mc **);
 
-struct nvkm_mc_intr {
+struct nvkm_mc_map {
 	u32 stat;
 	u32 unit;
 };
 
 struct nvkm_mc_func {
 	void (*init)(struct nvkm_mc *);
-	const struct nvkm_mc_intr *intr;
+	const struct nvkm_mc_map *intr;
 	/* disable reporting of interrupts to host */
 	void (*intr_unarm)(struct nvkm_mc *);
 	/* enable reporting of interrupts to host */
 	void (*intr_rearm)(struct nvkm_mc *);
 	/* retrieve pending interrupt mask (NV_PMC_INTR) */
 	u32 (*intr_mask)(struct nvkm_mc *);
+	const struct nvkm_mc_map *reset;
 	void (*unk260)(struct nvkm_mc *, u32);
 };
 
 void nv04_mc_init(struct nvkm_mc *);
-extern const struct nvkm_mc_intr nv04_mc_intr[];
 void nv04_mc_intr_unarm(struct nvkm_mc *);
 void nv04_mc_intr_rearm(struct nvkm_mc *);
 u32 nv04_mc_intr_mask(struct nvkm_mc *);
+extern const struct nvkm_mc_map nv04_mc_reset[];
+
+extern const struct nvkm_mc_map nv17_mc_intr[];
+extern const struct nvkm_mc_map nv17_mc_reset[];
 
 void nv44_mc_init(struct nvkm_mc *);
 
 void nv50_mc_init(struct nvkm_mc *);
-extern const struct nvkm_mc_intr nv50_mc_intr[];
 
-extern const struct nvkm_mc_intr gf100_mc_intr[];
 void gf100_mc_intr_unarm(struct nvkm_mc *);
 void gf100_mc_intr_rearm(struct nvkm_mc *);
 u32 gf100_mc_intr_mask(struct nvkm_mc *);
 void gf100_mc_unk260(struct nvkm_mc *, u32);
+
+extern const struct nvkm_mc_map gk104_mc_intr[];
+extern const struct nvkm_mc_map gk104_mc_reset[];
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c	2016-07-24 15:23:50.000000000 -0400
@@ -524,7 +524,7 @@ void
 nvkm_mmu_ctor(const struct nvkm_mmu_func *func, struct nvkm_device *device,
 	      int index, struct nvkm_mmu *mmu)
 {
-	nvkm_subdev_ctor(&nvkm_mmu, device, index, 0, &mmu->subdev);
+	nvkm_subdev_ctor(&nvkm_mmu, device, index, &mmu->subdev);
 	mmu->func = func;
 	mmu->limit = func->limit;
 	mmu->dma_bits = func->dma_bits;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/base.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/base.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/base.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/base.c	2016-07-24 15:23:50.000000000 -0400
@@ -241,7 +241,7 @@ nvkm_mxm_new_(struct nvkm_device *device
 	if (!(mxm = *pmxm = kzalloc(sizeof(*mxm), GFP_KERNEL)))
 		return -ENOMEM;
 
-	nvkm_subdev_ctor(&nvkm_mxm, device, index, 0, &mxm->subdev);
+	nvkm_subdev_ctor(&nvkm_mxm, device, index, &mxm->subdev);
 
 	data = mxm_table(bios, &ver, &len);
 	if (!data || !(ver = nvbios_rd08(bios, data))) {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c	2016-07-24 15:23:50.000000000 -0400
@@ -168,7 +168,7 @@ nvkm_pci_new_(const struct nvkm_pci_func
 
 	if (!(pci = *ppci = kzalloc(sizeof(**ppci), GFP_KERNEL)))
 		return -ENOMEM;
-	nvkm_subdev_ctor(&nvkm_pci_func, device, index, 0, &pci->subdev);
+	nvkm_subdev_ctor(&nvkm_pci_func, device, index, &pci->subdev);
 	pci->func = func;
 	pci->pdev = device->func->pci(device)->pdev;
 	pci->irq = -1;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c	2016-07-24 15:23:50.000000000 -0400
@@ -40,21 +40,23 @@ nvkm_pmu_send(struct nvkm_pmu *pmu, u32
 	struct nvkm_device *device = subdev->device;
 	u32 addr;
 
+	mutex_lock(&subdev->mutex);
 	/* wait for a free slot in the fifo */
 	addr  = nvkm_rd32(device, 0x10a4a0);
 	if (nvkm_msec(device, 2000,
 		u32 tmp = nvkm_rd32(device, 0x10a4b0);
 		if (tmp != (addr ^ 8))
 			break;
-	) < 0)
+	) < 0) {
+		mutex_unlock(&subdev->mutex);
 		return -EBUSY;
+	}
 
 	/* we currently only support a single process at a time waiting
 	 * on a synchronous reply, take the PMU mutex and tell the
 	 * receive handler what we're waiting for
 	 */
 	if (reply) {
-		mutex_lock(&subdev->mutex);
 		pmu->recv.message = message;
 		pmu->recv.process = process;
 	}
@@ -81,9 +83,9 @@ nvkm_pmu_send(struct nvkm_pmu *pmu, u32
 		wait_event(pmu->recv.wait, (pmu->recv.process == 0));
 		reply[0] = pmu->recv.data[0];
 		reply[1] = pmu->recv.data[1];
-		mutex_unlock(&subdev->mutex);
 	}
 
+	mutex_unlock(&subdev->mutex);
 	return 0;
 }
 
@@ -272,7 +274,7 @@ nvkm_pmu_new_(const struct nvkm_pmu_func
 	struct nvkm_pmu *pmu;
 	if (!(pmu = *ppmu = kzalloc(sizeof(*pmu), GFP_KERNEL)))
 		return -ENOMEM;
-	nvkm_subdev_ctor(&nvkm_pmu, device, index, 0, &pmu->subdev);
+	nvkm_subdev_ctor(&nvkm_pmu, device, index, &pmu->subdev);
 	pmu->func = func;
 	INIT_WORK(&pmu->recv.work, nvkm_pmu_recv);
 	init_waitqueue_head(&pmu->recv.wait);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk20a.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk20a.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk20a.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk20a.c	2016-07-24 15:23:50.000000000 -0400
@@ -220,7 +220,7 @@ gk20a_pmu_new(struct nvkm_device *device
 	pmu->base.func = &func;
 	*ppmu = &pmu->base;
 
-	nvkm_subdev_ctor(&gk20a_pmu, device, index, 0, &pmu->base.subdev);
+	nvkm_subdev_ctor(&gk20a_pmu, device, index, &pmu->base.subdev);
 	pmu->data = &gk20a_dvfs_data;
 	nvkm_alarm_init(&pmu->alarm, gk20a_pmu_dvfs_work);
 	return 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/base.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/base.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/base.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/base.c	2016-07-24 15:23:50.000000000 -0400
@@ -264,7 +264,7 @@ nvkm_secboot_ctor(const struct nvkm_secb
 {
 	unsigned long fid;
 
-	nvkm_subdev_ctor(&nvkm_secboot, device, index, 0, &sb->subdev);
+	nvkm_subdev_ctor(&nvkm_secboot, device, index, &sb->subdev);
 	sb->func = func;
 
 	/* setup the performing falcon's base address and masks */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c	2016-07-24 15:23:50.000000000 -0400
@@ -366,7 +366,7 @@ nvkm_therm_new_(const struct nvkm_therm_
 	if (!(therm = *ptherm = kzalloc(sizeof(*therm), GFP_KERNEL)))
 		return -ENOMEM;
 
-	nvkm_subdev_ctor(&nvkm_therm, device, index, 0, &therm->subdev);
+	nvkm_subdev_ctor(&nvkm_therm, device, index, &therm->subdev);
 	therm->func = func;
 
 	nvkm_alarm_init(&therm->alarm, nvkm_therm_alarm);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c	2016-07-24 15:23:50.000000000 -0400
@@ -143,7 +143,7 @@ nvkm_timer_new_(const struct nvkm_timer_
 	if (!(tmr = *ptmr = kzalloc(sizeof(*tmr), GFP_KERNEL)))
 		return -ENOMEM;
 
-	nvkm_subdev_ctor(&nvkm_timer, device, index, 0, &tmr->subdev);
+	nvkm_subdev_ctor(&nvkm_timer, device, index, &tmr->subdev);
 	tmr->func = func;
 	INIT_LIST_HEAD(&tmr->alarms);
 	spin_lock_init(&tmr->lock);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/top/base.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/top/base.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/top/base.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/top/base.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2016 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+#include "priv.h"
+
+struct nvkm_top_device *
+nvkm_top_device_new(struct nvkm_top *top)
+{
+	struct nvkm_top_device *info = kmalloc(sizeof(*info), GFP_KERNEL);
+	if (info) {
+		info->index = NVKM_SUBDEV_NR;
+		info->addr = 0;
+		info->fault = -1;
+		info->engine = -1;
+		info->runlist = -1;
+		info->reset = -1;
+		info->intr = -1;
+		list_add_tail(&info->head, &top->device);
+	}
+	return info;
+}
+
+u32
+nvkm_top_reset(struct nvkm_top *top, enum nvkm_devidx index)
+{
+	struct nvkm_top_device *info;
+
+	if (top) {
+		list_for_each_entry(info, &top->device, head) {
+			if (info->index == index && info->reset >= 0)
+				return BIT(info->reset);
+		}
+	}
+
+	return 0;
+}
+
+u32
+nvkm_top_intr(struct nvkm_top *top, u32 intr, u64 *psubdevs)
+{
+	struct nvkm_top_device *info;
+	u64 subdevs = 0;
+	u32 handled = 0;
+
+	if (top) {
+		list_for_each_entry(info, &top->device, head) {
+			if (info->index != NVKM_SUBDEV_NR && info->intr >= 0) {
+				if (intr & BIT(info->intr)) {
+					subdevs |= BIT_ULL(info->index);
+					handled |= BIT(info->intr);
+				}
+			}
+		}
+	}
+
+	*psubdevs = subdevs;
+	return intr & ~handled;
+}
+
+enum nvkm_devidx
+nvkm_top_fault(struct nvkm_top *top, int fault)
+{
+	struct nvkm_top_device *info;
+
+	list_for_each_entry(info, &top->device, head) {
+		if (info->fault == fault)
+			return info->index;
+	}
+
+	return NVKM_SUBDEV_NR;
+}
+
+enum nvkm_devidx
+nvkm_top_engine(struct nvkm_top *top, int index, int *runl, int *engn)
+{
+	struct nvkm_top_device *info;
+	int n = 0;
+
+	list_for_each_entry(info, &top->device, head) {
+		if (info->engine >= 0 && info->runlist >= 0 && n++ == index) {
+			*runl = info->runlist;
+			*engn = info->engine;
+			return info->index;
+		}
+	}
+
+	return -ENODEV;
+}
+
+static int
+nvkm_top_oneinit(struct nvkm_subdev *subdev)
+{
+	struct nvkm_top *top = nvkm_top(subdev);
+	return top->func->oneinit(top);
+}
+
+static void *
+nvkm_top_dtor(struct nvkm_subdev *subdev)
+{
+	struct nvkm_top *top = nvkm_top(subdev);
+	struct nvkm_top_device *info, *temp;
+
+	list_for_each_entry_safe(info, temp, &top->device, head) {
+		list_del(&info->head);
+		kfree(info);
+	}
+
+	return top;
+}
+
+static const struct nvkm_subdev_func
+nvkm_top = {
+	.dtor = nvkm_top_dtor,
+	.oneinit = nvkm_top_oneinit,
+};
+
+int
+nvkm_top_new_(const struct nvkm_top_func *func, struct nvkm_device *device,
+	      int index, struct nvkm_top **ptop)
+{
+	struct nvkm_top *top;
+	if (!(top = *ptop = kzalloc(sizeof(*top), GFP_KERNEL)))
+		return -ENOMEM;
+	nvkm_subdev_ctor(&nvkm_top, device, index, &top->subdev);
+	top->func = func;
+	INIT_LIST_HEAD(&top->device);
+	return 0;
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/top/gk104.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/top/gk104.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/top/gk104.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/top/gk104.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2016 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs <bskeggs@redhat.com>
+ */
+#include "priv.h"
+
+static int
+gk104_top_oneinit(struct nvkm_top *top)
+{
+	struct nvkm_subdev *subdev = &top->subdev;
+	struct nvkm_device *device = subdev->device;
+	struct nvkm_top_device *info = NULL;
+	u32 data, type;
+	int i;
+
+	for (i = 0; i < 64; i++) {
+		if (!info) {
+			if (!(info = nvkm_top_device_new(top)))
+				return -ENOMEM;
+			type = ~0;
+		}
+
+		data = nvkm_rd32(device, 0x022700 + (i * 0x04));
+		nvkm_trace(subdev, "%02x: %08x\n", i, data);
+		switch (data & 0x00000003) {
+		case 0x00000000: /* NOT_VALID */
+			continue;
+		case 0x00000001: /* DATA */
+			info->addr  = (data & 0x00fff000);
+			info->fault = (data & 0x000000f8) >> 3;
+			break;
+		case 0x00000002: /* ENUM */
+			if (data & 0x00000020)
+				info->engine  = (data & 0x3c000000) >> 26;
+			if (data & 0x00000010)
+				info->runlist = (data & 0x01e00000) >> 21;
+			if (data & 0x00000008)
+				info->intr    = (data & 0x000f8000) >> 15;
+			if (data & 0x00000004)
+				info->reset   = (data & 0x00003e00) >> 9;
+			break;
+		case 0x00000003: /* ENGINE_TYPE */
+			type = (data & 0x7ffffffc) >> 2;
+			break;
+		}
+
+		if (data & 0x80000000)
+			continue;
+
+		/* Translate engine type to NVKM engine identifier. */
+		switch (type) {
+		case 0x00000000: info->index = NVKM_ENGINE_GR; break;
+		case 0x00000001: info->index = NVKM_ENGINE_CE0; break;
+		case 0x00000002: info->index = NVKM_ENGINE_CE1; break;
+		case 0x00000003: info->index = NVKM_ENGINE_CE2; break;
+		case 0x00000008: info->index = NVKM_ENGINE_MSPDEC; break;
+		case 0x00000009: info->index = NVKM_ENGINE_MSPPP; break;
+		case 0x0000000a: info->index = NVKM_ENGINE_MSVLD; break;
+		case 0x0000000b: info->index = NVKM_ENGINE_MSENC; break;
+		case 0x0000000c: info->index = NVKM_ENGINE_VIC; break;
+		case 0x0000000d: info->index = NVKM_ENGINE_SEC; break;
+		case 0x0000000e: info->index = NVKM_ENGINE_NVENC0; break;
+		case 0x0000000f: info->index = NVKM_ENGINE_NVENC1; break;
+		case 0x00000010: info->index = NVKM_ENGINE_NVDEC; break;
+			break;
+		default:
+			break;
+		}
+
+		nvkm_debug(subdev, "%02x (%8s): addr %06x fault %2d engine %2d "
+				   "runlist %2d intr %2d reset %2d\n", type,
+			   info->index == NVKM_SUBDEV_NR ? NULL :
+					  nvkm_subdev_name[info->index],
+			   info->addr, info->fault, info->engine, info->runlist,
+			   info->intr, info->reset);
+		info = NULL;
+	}
+
+	return 0;
+}
+
+static const struct nvkm_top_func
+gk104_top = {
+	.oneinit = gk104_top_oneinit,
+};
+
+int
+gk104_top_new(struct nvkm_device *device, int index, struct nvkm_top **ptop)
+{
+	return nvkm_top_new_(&gk104_top, device, index, ptop);
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/top/Kbuild linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/top/Kbuild
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/top/Kbuild	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/top/Kbuild	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,2 @@
+nvkm-y += nvkm/subdev/top/base.o
+nvkm-y += nvkm/subdev/top/gk104.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/top/priv.h linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/top/priv.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/top/priv.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/top/priv.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,25 @@
+#ifndef __NVKM_TOP_PRIV_H__
+#define __NVKM_TOP_PRIV_H__
+#define nvkm_top(p) container_of((p), struct nvkm_top, subdev)
+#include <subdev/top.h>
+
+struct nvkm_top_func {
+	int (*oneinit)(struct nvkm_top *);
+};
+
+int nvkm_top_new_(const struct nvkm_top_func *, struct nvkm_device *,
+		  int, struct nvkm_top **);
+
+struct nvkm_top_device {
+	enum nvkm_devidx index;
+	u32 addr;
+	int fault;
+	int engine;
+	int runlist;
+	int reset;
+	int intr;
+	struct list_head head;
+};
+
+struct nvkm_top_device *nvkm_top_device_new(struct nvkm_top *);
+#endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c	2016-07-24 15:23:50.000000000 -0400
@@ -177,7 +177,7 @@ nvkm_volt_ctor(const struct nvkm_volt_fu
 	struct nvkm_bios *bios = device->bios;
 	int i;
 
-	nvkm_subdev_ctor(&nvkm_volt, device, index, 0, &volt->subdev);
+	nvkm_subdev_ctor(&nvkm_volt, device, index, &volt->subdev);
 	volt->func = func;
 
 	/* Assuming the non-bios device should build the voltage table later */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gk104.c linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gk104.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gk104.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gk104.c	2016-07-24 15:23:50.000000000 -0400
@@ -56,7 +56,7 @@ gk104_volt_set(struct nvkm_volt *base, u
 
 	/* the blob uses this crystal frequency, let's use it too. */
 	div = 27648000 / bios->pwm_freq;
-	duty = (uv - bios->base) * div / bios->pwm_range;
+	duty = DIV_ROUND_UP((uv - bios->base) * div, bios->pwm_range);
 
 	nvkm_wr32(device, 0x20340, div);
 	nvkm_wr32(device, 0x20344, 0x80000000 | duty);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c	2016-07-24 15:23:50.000000000 -0400
@@ -9,6 +9,7 @@
  * the Free Software Foundation.
  */
 
+#include <linux/gpio/consumer.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c	2016-07-24 15:23:50.000000000 -0400
@@ -14,7 +14,7 @@
  * the Free Software Foundation.
  */
 
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c	2016-07-24 15:23:50.000000000 -0400
@@ -9,7 +9,7 @@
  * the Free Software Foundation.
  */
 
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/displays/panel-dpi.c linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/displays/panel-dpi.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/displays/panel-dpi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/displays/panel-dpi.c	2016-07-24 15:23:50.000000000 -0400
@@ -9,7 +9,7 @@
  * the Free Software Foundation.
  */
 
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c	2016-07-24 15:23:50.000000000 -0400
@@ -14,7 +14,7 @@
 #include <linux/backlight.h>
 #include <linux/delay.h>
 #include <linux/fb.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/interrupt.h>
 #include <linux/jiffies.h>
 #include <linux/module.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c	2016-07-24 15:23:50.000000000 -0400
@@ -15,6 +15,7 @@
 #include <linux/spi/spi.h>
 #include <linux/mutex.h>
 #include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 
 #include <video/omapdss.h>
 #include <video/omap-panel-data.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c	2016-07-24 15:23:50.000000000 -0400
@@ -15,7 +15,7 @@
 #include <linux/delay.h>
 #include <linux/spi/spi.h>
 #include <linux/fb.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/of_gpio.h>
 
 #include <video/omapdss.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c	2016-07-24 15:23:50.000000000 -0400
@@ -10,7 +10,7 @@
  */
 
 #include <linux/delay.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c	2016-07-24 15:23:50.000000000 -0400
@@ -29,7 +29,7 @@
 #include <linux/sched.h>
 #include <linux/backlight.h>
 #include <linux/fb.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c	2016-07-24 15:23:50.000000000 -0400
@@ -14,7 +14,7 @@
 #include <linux/delay.h>
 #include <linux/spi/spi.h>
 #include <linux/regulator/consumer.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/of_gpio.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/dss/dsi.c linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/dss/dsi.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/dss/dsi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/dss/dsi.c	2016-07-24 15:23:50.000000000 -0400
@@ -1167,7 +1167,6 @@ static int dsi_regulator_init(struct pla
 {
 	struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
 	struct regulator *vdds_dsi;
-	int r;
 
 	if (dsi->vdds_dsi_reg != NULL)
 		return 0;
@@ -1180,15 +1179,6 @@ static int dsi_regulator_init(struct pla
 		return PTR_ERR(vdds_dsi);
 	}
 
-	if (regulator_can_change_voltage(vdds_dsi)) {
-		r = regulator_set_voltage(vdds_dsi, 1800000, 1800000);
-		if (r) {
-			devm_regulator_put(vdds_dsi);
-			DSSERR("can't set the DSI regulator voltage\n");
-			return r;
-		}
-	}
-
 	dsi->vdds_dsi_reg = vdds_dsi;
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/dss/dss.c linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/dss/dss.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/dss/dss.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/dss/dss.c	2016-07-24 15:23:50.000000000 -0400
@@ -30,6 +30,7 @@
 #include <linux/delay.h>
 #include <linux/seq_file.h>
 #include <linux/clk.h>
+#include <linux/pinctrl/consumer.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/gfp.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/dss/hdmi4.c linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/dss/hdmi4.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/dss/hdmi4.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/dss/hdmi4.c	2016-07-24 15:23:50.000000000 -0400
@@ -33,6 +33,7 @@
 #include <linux/gpio.h>
 #include <linux/regulator/consumer.h>
 #include <linux/component.h>
+#include <linux/of.h>
 #include <video/omapdss.h>
 #include <sound/omap-hdmi-audio.h>
 
@@ -100,7 +101,6 @@ static irqreturn_t hdmi_irq_handler(int
 
 static int hdmi_init_regulator(void)
 {
-	int r;
 	struct regulator *reg;
 
 	if (hdmi.vdda_reg != NULL)
@@ -114,15 +114,6 @@ static int hdmi_init_regulator(void)
 		return PTR_ERR(reg);
 	}
 
-	if (regulator_can_change_voltage(reg)) {
-		r = regulator_set_voltage(reg, 1800000, 1800000);
-		if (r) {
-			devm_regulator_put(reg);
-			DSSWARN("can't set the regulator voltage\n");
-			return r;
-		}
-	}
-
 	hdmi.vdda_reg = reg;
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c	2016-07-24 15:23:50.000000000 -0400
@@ -211,7 +211,7 @@ static void hdmi_core_init(struct hdmi_c
 static void hdmi_core_powerdown_disable(struct hdmi_core_data *core)
 {
 	DSSDBG("Enter hdmi_core_powerdown_disable\n");
-	REG_FLD_MOD(core->base, HDMI_CORE_SYS_SYS_CTRL1, 0x0, 0, 0);
+	REG_FLD_MOD(core->base, HDMI_CORE_SYS_SYS_CTRL1, 0x1, 0, 0);
 }
 
 static void hdmi_core_swreset_release(struct hdmi_core_data *core)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/dss/hdmi5.c linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/dss/hdmi5.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/dss/hdmi5.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/dss/hdmi5.c	2016-07-24 15:23:50.000000000 -0400
@@ -38,6 +38,7 @@
 #include <linux/gpio.h>
 #include <linux/regulator/consumer.h>
 #include <linux/component.h>
+#include <linux/of.h>
 #include <video/omapdss.h>
 #include <sound/omap-hdmi-audio.h>
 
@@ -119,7 +120,6 @@ static irqreturn_t hdmi_irq_handler(int
 
 static int hdmi_init_regulator(void)
 {
-	int r;
 	struct regulator *reg;
 
 	if (hdmi.vdda_reg != NULL)
@@ -131,15 +131,6 @@ static int hdmi_init_regulator(void)
 		return PTR_ERR(reg);
 	}
 
-	if (regulator_can_change_voltage(reg)) {
-		r = regulator_set_voltage(reg, 1800000, 1800000);
-		if (r) {
-			devm_regulator_put(reg);
-			DSSWARN("can't set the regulator voltage\n");
-			return r;
-		}
-	}
-
 	hdmi.vdda_reg = reg;
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c	2016-07-24 15:23:50.000000000 -0400
@@ -51,8 +51,8 @@ static void hdmi_core_ddc_init(struct hd
 {
 	void __iomem *base = core->base;
 	const unsigned long long iclk = 266000000;	/* DSS L3 ICLK */
-	const unsigned ss_scl_high = 4000;		/* ns */
-	const unsigned ss_scl_low = 4700;		/* ns */
+	const unsigned ss_scl_high = 4600;		/* ns */
+	const unsigned ss_scl_low = 5400;		/* ns */
 	const unsigned fs_scl_high = 600;		/* ns */
 	const unsigned fs_scl_low = 1300;		/* ns */
 	const unsigned sda_hold = 1000;			/* ns */
@@ -458,7 +458,7 @@ static void hdmi_core_write_avi_infofram
 
 	c = (ptr[1] >> 6) & 0x3;
 	m = (ptr[1] >> 4) & 0x3;
-	r = (ptr[1] >> 0) & 0x3;
+	r = (ptr[1] >> 0) & 0xf;
 
 	itc = (ptr[2] >> 7) & 0x1;
 	ec = (ptr[2] >> 4) & 0x7;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/dss/hdmi_phy.c linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/dss/hdmi_phy.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/dss/hdmi_phy.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/dss/hdmi_phy.c	2016-07-24 15:23:50.000000000 -0400
@@ -13,6 +13,7 @@
 #include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
+#include <linux/seq_file.h>
 #include <video/omapdss.h>
 
 #include "dss.h"
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/dss/hdmi_pll.c linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/dss/hdmi_pll.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/dss/hdmi_pll.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/dss/hdmi_pll.c	2016-07-24 15:23:50.000000000 -0400
@@ -16,6 +16,7 @@
 #include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
+#include <linux/seq_file.h>
 
 #include <video/omapdss.h>
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c	2016-07-24 15:23:50.000000000 -0400
@@ -14,6 +14,7 @@
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
+#include <linux/seq_file.h>
 #include <video/omapdss.h>
 
 #include "dss.h"
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/Kconfig linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/Kconfig
--- linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -2,6 +2,7 @@ config DRM_OMAP
 	tristate "OMAP DRM"
 	depends on DRM
 	depends on ARCH_OMAP2PLUS || ARCH_MULTIPLATFORM
+	select OMAP2_DSS
 	select DRM_KMS_HELPER
 	select DRM_KMS_FB_HELPER
 	select FB_SYS_FILLRECT
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/omap_debugfs.c linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/omap_debugfs.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/omap_debugfs.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/omap_debugfs.c	2016-07-24 15:23:50.000000000 -0400
@@ -17,6 +17,8 @@
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/seq_file.h>
+
 #include <drm/drm_crtc.h>
 #include <drm/drm_fb_helper.h>
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c	2016-07-24 15:23:50.000000000 -0400
@@ -27,6 +27,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h> /* platform_device() */
 #include <linux/sched.h>
+#include <linux/seq_file.h>
 #include <linux/slab.h>
 #include <linux/time.h>
 #include <linux/vmalloc.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/omap_drv.c linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/omap_drv.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/omap_drv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/omap_drv.c	2016-07-24 15:23:50.000000000 -0400
@@ -138,7 +138,7 @@ static bool omap_atomic_is_pending(struc
 }
 
 static int omap_atomic_commit(struct drm_device *dev,
-			      struct drm_atomic_state *state, bool async)
+			      struct drm_atomic_state *state, bool nonblock)
 {
 	struct omap_drm_private *priv = dev->dev_private;
 	struct omap_atomic_state_commit *commit;
@@ -177,7 +177,7 @@ static int omap_atomic_commit(struct drm
 	/* Swap the state, this is the point of no return. */
 	drm_atomic_helper_swap_state(dev, state);
 
-	if (async)
+	if (nonblock)
 		schedule_work(&commit->work);
 	else
 		omap_atomic_complete(commit);
@@ -561,7 +561,7 @@ static int ioctl_gem_cpu_prep(struct drm
 
 	VERB("%p:%p: handle=%d, op=%x", dev, file_priv, args->handle, args->op);
 
-	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+	obj = drm_gem_object_lookup(file_priv, args->handle);
 	if (!obj)
 		return -ENOENT;
 
@@ -584,7 +584,7 @@ static int ioctl_gem_cpu_fini(struct drm
 
 	VERB("%p:%p: handle=%d", dev, file_priv, args->handle);
 
-	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+	obj = drm_gem_object_lookup(file_priv, args->handle);
 	if (!obj)
 		return -ENOENT;
 
@@ -608,7 +608,7 @@ static int ioctl_gem_info(struct drm_dev
 
 	VERB("%p:%p: handle=%d", dev, file_priv, args->handle);
 
-	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+	obj = drm_gem_object_lookup(file_priv, args->handle);
 	if (!obj)
 		return -ENOENT;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/omap_drv.h linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/omap_drv.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/omap_drv.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/omap_drv.h	2016-07-24 15:23:50.000000000 -0400
@@ -257,14 +257,14 @@ struct omap_dss_device *omap_encoder_get
 /* should these be made into common util helpers?
  */
 
-static inline int objects_lookup(struct drm_device *dev,
+static inline int objects_lookup(
 		struct drm_file *filp, uint32_t pixel_format,
 		struct drm_gem_object **bos, const uint32_t *handles)
 {
 	int i, n = drm_format_num_planes(pixel_format);
 
 	for (i = 0; i < n; i++) {
-		bos[i] = drm_gem_object_lookup(dev, filp, handles[i]);
+		bos[i] = drm_gem_object_lookup(filp, handles[i]);
 		if (!bos[i])
 			goto fail;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/omap_fb.c linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/omap_fb.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/omap_fb.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/omap_fb.c	2016-07-24 15:23:50.000000000 -0400
@@ -17,6 +17,8 @@
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/seq_file.h>
+
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
 
@@ -378,7 +380,7 @@ struct drm_framebuffer *omap_framebuffer
 	struct drm_framebuffer *fb;
 	int ret;
 
-	ret = objects_lookup(dev, file, mode_cmd->pixel_format,
+	ret = objects_lookup(file, mode_cmd->pixel_format,
 			bos, mode_cmd->handles);
 	if (ret)
 		return ERR_PTR(ret);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/omap_fbdev.c linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/omap_fbdev.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/omap_fbdev.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/omap_fbdev.c	2016-07-24 15:23:50.000000000 -0400
@@ -153,7 +153,7 @@ static int omap_fbdev_create(struct drm_
 		/* note: if fb creation failed, we can't rely on fb destroy
 		 * to unref the bo:
 		 */
-		drm_gem_object_unreference(fbdev->bo);
+		drm_gem_object_unreference_unlocked(fbdev->bo);
 		ret = PTR_ERR(fb);
 		goto fail;
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/omap_gem.c linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/omap_gem.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/omap_gem.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/omap_gem.c	2016-07-24 15:23:50.000000000 -0400
@@ -17,6 +17,7 @@
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/seq_file.h>
 #include <linux/shmem_fs.h>
 #include <linux/spinlock.h>
 #include <linux/pfn_t.h>
@@ -687,7 +688,7 @@ int omap_gem_dumb_map_offset(struct drm_
 	int ret = 0;
 
 	/* GEM does all our handle to object mapping */
-	obj = drm_gem_object_lookup(dev, file, handle);
+	obj = drm_gem_object_lookup(file, handle);
 	if (obj == NULL) {
 		ret = -ENOENT;
 		goto fail;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/omap_plane.c linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/omap_plane.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/omapdrm/omap_plane.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/omapdrm/omap_plane.c	2016-07-24 15:23:50.000000000 -0400
@@ -245,7 +245,7 @@ omap_plane_atomic_duplicate_state(struct
 static void omap_plane_atomic_destroy_state(struct drm_plane *plane,
 					    struct drm_plane_state *state)
 {
-	__drm_atomic_helper_plane_destroy_state(plane, state);
+	__drm_atomic_helper_plane_destroy_state(state);
 	kfree(to_omap_plane_state(state));
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/panel/panel-simple.c linux-libre-4.7-gnu/drivers/gpu/drm/panel/panel-simple.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/panel/panel-simple.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/panel/panel-simple.c	2016-07-24 15:23:50.000000000 -0400
@@ -72,6 +72,7 @@ struct panel_desc {
 	} delay;
 
 	u32 bus_format;
+	u32 bus_flags;
 };
 
 struct panel_simple {
@@ -116,7 +117,11 @@ static int panel_simple_get_fixed_modes(
 		}
 
 		drm_display_mode_from_videomode(&vm, mode);
-		drm_mode_set_name(mode);
+
+		mode->type |= DRM_MODE_TYPE_DRIVER;
+
+		if (panel->desc->num_modes == 1)
+			mode->type |= DRM_MODE_TYPE_PREFERRED;
 
 		drm_mode_probed_add(connector, mode);
 		num++;
@@ -132,6 +137,11 @@ static int panel_simple_get_fixed_modes(
 			continue;
 		}
 
+		mode->type |= DRM_MODE_TYPE_DRIVER;
+
+		if (panel->desc->num_modes == 1)
+			mode->type |= DRM_MODE_TYPE_PREFERRED;
+
 		drm_mode_set_name(mode);
 
 		drm_mode_probed_add(connector, mode);
@@ -144,6 +154,7 @@ static int panel_simple_get_fixed_modes(
 	if (panel->desc->bus_format)
 		drm_display_info_set_bus_formats(&connector->display_info,
 						 &panel->desc->bus_format, 1);
+	connector->display_info.bus_flags = panel->desc->bus_flags;
 
 	return num;
 }
@@ -813,6 +824,29 @@ static const struct panel_desc innolux_a
 	.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
 };
 
+static const struct drm_display_mode innolux_at070tn92_mode = {
+	.clock = 33333,
+	.hdisplay = 800,
+	.hsync_start = 800 + 210,
+	.hsync_end = 800 + 210 + 20,
+	.htotal = 800 + 210 + 20 + 46,
+	.vdisplay = 480,
+	.vsync_start = 480 + 22,
+	.vsync_end = 480 + 22 + 10,
+	.vtotal = 480 + 22 + 23 + 10,
+	.vrefresh = 60,
+};
+
+static const struct panel_desc innolux_at070tn92 = {
+	.modes = &innolux_at070tn92_mode,
+	.num_modes = 1,
+	.size = {
+		.width = 154,
+		.height = 86,
+	},
+	.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
+};
+
 static const struct drm_display_mode innolux_g121i1_l01_mode = {
 	.clock = 71000,
 	.hdisplay = 1280,
@@ -1051,7 +1085,8 @@ static const struct panel_desc nec_nl482
 		.width = 95,
 		.height = 54,
 	},
-	.bus_format = MEDIA_BUS_FMT_RGB888_1X24
+	.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
+	.bus_flags = DRM_BUS_FLAG_PIXDATA_POSEDGE,
 };
 
 static const struct display_timing okaya_rs800480t_7x0gp_timing = {
@@ -1084,6 +1119,63 @@ static const struct panel_desc okaya_rs8
 	.bus_format = MEDIA_BUS_FMT_RGB666_1X18,
 };
 
+static const struct drm_display_mode olimex_lcd_olinuxino_43ts_mode = {
+	.clock = 9000,
+	.hdisplay = 480,
+	.hsync_start = 480 + 5,
+	.hsync_end = 480 + 5 + 30,
+	.htotal = 480 + 5 + 30 + 10,
+	.vdisplay = 272,
+	.vsync_start = 272 + 8,
+	.vsync_end = 272 + 8 + 5,
+	.vtotal = 272 + 8 + 5 + 3,
+	.vrefresh = 60,
+};
+
+static const struct panel_desc olimex_lcd_olinuxino_43ts = {
+	.modes = &olimex_lcd_olinuxino_43ts_mode,
+	.num_modes = 1,
+	.size = {
+		.width = 105,
+		.height = 67,
+	},
+	.bus_format = MEDIA_BUS_FMT_RGB666_1X18,
+};
+
+/*
+ * 800x480 CVT. The panel appears to be quite accepting, at least as far as
+ * pixel clocks, but this is the timing that was being used in the Adafruit
+ * installation instructions.
+ */
+static const struct drm_display_mode ontat_yx700wv03_mode = {
+	.clock = 29500,
+	.hdisplay = 800,
+	.hsync_start = 824,
+	.hsync_end = 896,
+	.htotal = 992,
+	.vdisplay = 480,
+	.vsync_start = 483,
+	.vsync_end = 493,
+	.vtotal = 500,
+	.vrefresh = 60,
+	.flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
+};
+
+/*
+ * Specification at:
+ * https://www.adafruit.com/images/product-files/2406/c3163.pdf
+ */
+static const struct panel_desc ontat_yx700wv03 = {
+	.modes = &ontat_yx700wv03_mode,
+	.num_modes = 1,
+	.bpc = 8,
+	.size = {
+		.width = 154,
+		.height = 83,
+	},
+	.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
+};
+
 static const struct drm_display_mode ortustech_com43h4m85ulc_mode  = {
 	.clock = 25000,
 	.hdisplay = 480,
@@ -1201,6 +1293,51 @@ static const struct panel_desc shelly_sc
 	.bus_format = MEDIA_BUS_FMT_RGB666_1X18,
 };
 
+static const struct drm_display_mode tpk_f07a_0102_mode = {
+	.clock = 33260,
+	.hdisplay = 800,
+	.hsync_start = 800 + 40,
+	.hsync_end = 800 + 40 + 128,
+	.htotal = 800 + 40 + 128 + 88,
+	.vdisplay = 480,
+	.vsync_start = 480 + 10,
+	.vsync_end = 480 + 10 + 2,
+	.vtotal = 480 + 10 + 2 + 33,
+	.vrefresh = 60,
+};
+
+static const struct panel_desc tpk_f07a_0102 = {
+	.modes = &tpk_f07a_0102_mode,
+	.num_modes = 1,
+	.size = {
+		.width = 152,
+		.height = 91,
+	},
+	.bus_flags = DRM_BUS_FLAG_PIXDATA_POSEDGE,
+};
+
+static const struct drm_display_mode tpk_f10a_0102_mode = {
+	.clock = 45000,
+	.hdisplay = 1024,
+	.hsync_start = 1024 + 176,
+	.hsync_end = 1024 + 176 + 5,
+	.htotal = 1024 + 176 + 5 + 88,
+	.vdisplay = 600,
+	.vsync_start = 600 + 20,
+	.vsync_end = 600 + 20 + 5,
+	.vtotal = 600 + 20 + 5 + 25,
+	.vrefresh = 60,
+};
+
+static const struct panel_desc tpk_f10a_0102 = {
+	.modes = &tpk_f10a_0102_mode,
+	.num_modes = 1,
+	.size = {
+		.width = 223,
+		.height = 125,
+	},
+};
+
 static const struct display_timing urt_umsh_8596md_timing = {
 	.pixelclock = { 33260000, 33260000, 33260000 },
 	.hactive = { 800, 800, 800 },
@@ -1296,6 +1433,9 @@ static const struct of_device_id platfor
 		.compatible = "innolux,at043tn24",
 		.data = &innolux_at043tn24,
 	}, {
+		.compatible = "innolux,at070tn92",
+		.data = &innolux_at070tn92,
+	}, {
 		.compatible ="innolux,g121i1-l01",
 		.data = &innolux_g121i1_l01
 	}, {
@@ -1329,6 +1469,12 @@ static const struct of_device_id platfor
 		.compatible = "okaya,rs800480t-7x0gp",
 		.data = &okaya_rs800480t_7x0gp,
 	}, {
+		.compatible = "olimex,lcd-olinuxino-43-ts",
+		.data = &olimex_lcd_olinuxino_43ts,
+	}, {
+		.compatible = "ontat,yx700wv03",
+		.data = &ontat_yx700wv03,
+	}, {
 		.compatible = "ortustech,com43h4m85ulc",
 		.data = &ortustech_com43h4m85ulc,
 	}, {
@@ -1344,6 +1490,12 @@ static const struct of_device_id platfor
 		.compatible = "shelly,sca07010-bfn-lnn",
 		.data = &shelly_sca07010_bfn_lnn,
 	}, {
+		.compatible = "tpk,f07a-0102",
+		.data = &tpk_f07a_0102,
+	}, {
+		.compatible = "tpk,f10a-0102",
+		.data = &tpk_f10a_0102,
+	}, {
 		.compatible = "urt,umsh-8596md-t",
 		.data = &urt_umsh_8596md_parallel,
 	}, {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/qxl/qxl_cmd.c linux-libre-4.7-gnu/drivers/gpu/drm/qxl/qxl_cmd.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/qxl/qxl_cmd.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/qxl/qxl_cmd.c	2016-07-24 15:23:50.000000000 -0400
@@ -624,7 +624,7 @@ static int qxl_reap_surf(struct qxl_devi
 	if (stall)
 		mutex_unlock(&qdev->surf_evict_mutex);
 
-	ret = ttm_bo_wait(&surf->tbo, true, true, !stall);
+	ret = ttm_bo_wait(&surf->tbo, true, !stall);
 
 	if (stall)
 		mutex_lock(&qdev->surf_evict_mutex);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/qxl/qxl_display.c linux-libre-4.7-gnu/drivers/gpu/drm/qxl/qxl_display.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/qxl/qxl_display.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/qxl/qxl_display.c	2016-07-24 15:23:50.000000000 -0400
@@ -318,7 +318,7 @@ static int qxl_crtc_cursor_set2(struct d
 	if (!handle)
 		return qxl_hide_cursor(qdev);
 
-	obj = drm_gem_object_lookup(crtc->dev, file_priv, handle);
+	obj = drm_gem_object_lookup(file_priv, handle);
 	if (!obj) {
 		DRM_ERROR("cannot find cursor object\n");
 		return -ENOENT;
@@ -465,7 +465,7 @@ static const struct drm_crtc_funcs qxl_c
 	.page_flip = qxl_crtc_page_flip,
 };
 
-static void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb)
+void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb)
 {
 	struct qxl_framebuffer *qxl_fb = to_qxl_framebuffer(fb);
 
@@ -527,12 +527,13 @@ int
 qxl_framebuffer_init(struct drm_device *dev,
 		     struct qxl_framebuffer *qfb,
 		     const struct drm_mode_fb_cmd2 *mode_cmd,
-		     struct drm_gem_object *obj)
+		     struct drm_gem_object *obj,
+		     const struct drm_framebuffer_funcs *funcs)
 {
 	int ret;
 
 	qfb->obj = obj;
-	ret = drm_framebuffer_init(dev, &qfb->base, &qxl_fb_funcs);
+	ret = drm_framebuffer_init(dev, &qfb->base, funcs);
 	if (ret) {
 		qfb->obj = NULL;
 		return ret;
@@ -993,13 +994,15 @@ qxl_user_framebuffer_create(struct drm_d
 	struct qxl_framebuffer *qxl_fb;
 	int ret;
 
-	obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]);
+	obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[0]);
+	if (!obj)
+		return NULL;
 
 	qxl_fb = kzalloc(sizeof(*qxl_fb), GFP_KERNEL);
 	if (qxl_fb == NULL)
 		return NULL;
 
-	ret = qxl_framebuffer_init(dev, qxl_fb, mode_cmd, obj);
+	ret = qxl_framebuffer_init(dev, qxl_fb, mode_cmd, obj, &qxl_fb_funcs);
 	if (ret) {
 		kfree(qxl_fb);
 		drm_gem_object_unreference_unlocked(obj);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/qxl/qxl_drv.c linux-libre-4.7-gnu/drivers/gpu/drm/qxl/qxl_drv.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/qxl/qxl_drv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/qxl/qxl_drv.c	2016-07-24 15:23:50.000000000 -0400
@@ -272,10 +272,8 @@ static struct drm_driver qxl_driver = {
 
 static int __init qxl_init(void)
 {
-#ifdef CONFIG_VGA_CONSOLE
 	if (vgacon_text_force() && qxl_modeset == -1)
 		return -EINVAL;
-#endif
 
 	if (qxl_modeset == 0)
 		return -EINVAL;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/qxl/qxl_drv.h linux-libre-4.7-gnu/drivers/gpu/drm/qxl/qxl_drv.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/qxl/qxl_drv.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/qxl/qxl_drv.h	2016-07-24 15:23:50.000000000 -0400
@@ -324,8 +324,6 @@ struct qxl_device {
 	struct workqueue_struct *gc_queue;
 	struct work_struct gc_work;
 
-	struct work_struct fb_work;
-
 	struct drm_property *hotplug_mode_update_property;
 	int monitors_config_width;
 	int monitors_config_height;
@@ -389,11 +387,13 @@ int qxl_get_handle_for_primary_fb(struct
 void qxl_fbdev_set_suspend(struct qxl_device *qdev, int state);
 
 /* qxl_display.c */
+void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb);
 int
 qxl_framebuffer_init(struct drm_device *dev,
 		     struct qxl_framebuffer *rfb,
 		     const struct drm_mode_fb_cmd2 *mode_cmd,
-		     struct drm_gem_object *obj);
+		     struct drm_gem_object *obj,
+		     const struct drm_framebuffer_funcs *funcs);
 void qxl_display_read_client_monitors_config(struct qxl_device *qdev);
 void qxl_send_monitors_config(struct qxl_device *qdev);
 int qxl_create_monitors_object(struct qxl_device *qdev);
@@ -553,7 +553,6 @@ int qxl_irq_init(struct qxl_device *qdev
 irqreturn_t qxl_irq_handler(int irq, void *arg);
 
 /* qxl_fb.c */
-int qxl_fb_init(struct qxl_device *qdev);
 bool qxl_fbdev_qobj_is_fb(struct qxl_device *qdev, struct qxl_bo *qobj);
 
 int qxl_debugfs_add_files(struct qxl_device *qdev,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/qxl/qxl_dumb.c linux-libre-4.7-gnu/drivers/gpu/drm/qxl/qxl_dumb.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/qxl/qxl_dumb.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/qxl/qxl_dumb.c	2016-07-24 15:23:50.000000000 -0400
@@ -76,7 +76,7 @@ int qxl_mode_dumb_mmap(struct drm_file *
 	struct qxl_bo *qobj;
 
 	BUG_ON(!offset_p);
-	gobj = drm_gem_object_lookup(dev, file_priv, handle);
+	gobj = drm_gem_object_lookup(file_priv, handle);
 	if (gobj == NULL)
 		return -ENOENT;
 	qobj = gem_to_qxl_bo(gobj);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/qxl/qxl_fb.c linux-libre-4.7-gnu/drivers/gpu/drm/qxl/qxl_fb.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/qxl/qxl_fb.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/qxl/qxl_fb.c	2016-07-24 15:23:50.000000000 -0400
@@ -46,15 +46,6 @@ struct qxl_fbdev {
 	struct list_head delayed_ops;
 	void *shadow;
 	int size;
-
-	/* dirty memory logging */
-	struct {
-		spinlock_t lock;
-		unsigned x1;
-		unsigned y1;
-		unsigned x2;
-		unsigned y2;
-	} dirty;
 };
 
 static void qxl_fb_image_init(struct qxl_fb_image *qxl_fb_image,
@@ -82,169 +73,18 @@ static void qxl_fb_image_init(struct qxl
 	}
 }
 
-static void qxl_fb_dirty_flush(struct fb_info *info)
-{
-	struct qxl_fbdev *qfbdev = info->par;
-	struct qxl_device *qdev = qfbdev->qdev;
-	struct qxl_fb_image qxl_fb_image;
-	struct fb_image *image = &qxl_fb_image.fb_image;
-	unsigned long flags;
-	u32 x1, x2, y1, y2;
-
-	/* TODO: hard coding 32 bpp */
-	int stride = qfbdev->qfb.base.pitches[0];
-
-	spin_lock_irqsave(&qfbdev->dirty.lock, flags);
-
-	x1 = qfbdev->dirty.x1;
-	x2 = qfbdev->dirty.x2;
-	y1 = qfbdev->dirty.y1;
-	y2 = qfbdev->dirty.y2;
-	qfbdev->dirty.x1 = 0;
-	qfbdev->dirty.x2 = 0;
-	qfbdev->dirty.y1 = 0;
-	qfbdev->dirty.y2 = 0;
-
-	spin_unlock_irqrestore(&qfbdev->dirty.lock, flags);
-
-	/*
-	 * we are using a shadow draw buffer, at qdev->surface0_shadow
-	 */
-	qxl_io_log(qdev, "dirty x[%d, %d], y[%d, %d]", x1, x2, y1, y2);
-	image->dx = x1;
-	image->dy = y1;
-	image->width = x2 - x1 + 1;
-	image->height = y2 - y1 + 1;
-	image->fg_color = 0xffffffff; /* unused, just to avoid uninitialized
-					 warnings */
-	image->bg_color = 0;
-	image->depth = 32;	     /* TODO: take from somewhere? */
-	image->cmap.start = 0;
-	image->cmap.len = 0;
-	image->cmap.red = NULL;
-	image->cmap.green = NULL;
-	image->cmap.blue = NULL;
-	image->cmap.transp = NULL;
-	image->data = qfbdev->shadow + (x1 * 4) + (stride * y1);
-
-	qxl_fb_image_init(&qxl_fb_image, qdev, info, NULL);
-	qxl_draw_opaque_fb(&qxl_fb_image, stride);
-}
-
-static void qxl_dirty_update(struct qxl_fbdev *qfbdev,
-			     int x, int y, int width, int height)
-{
-	struct qxl_device *qdev = qfbdev->qdev;
-	unsigned long flags;
-	int x2, y2;
-
-	x2 = x + width - 1;
-	y2 = y + height - 1;
-
-	spin_lock_irqsave(&qfbdev->dirty.lock, flags);
-
-	if ((qfbdev->dirty.y2 - qfbdev->dirty.y1) &&
-	    (qfbdev->dirty.x2 - qfbdev->dirty.x1)) {
-		if (qfbdev->dirty.y1 < y)
-			y = qfbdev->dirty.y1;
-		if (qfbdev->dirty.y2 > y2)
-			y2 = qfbdev->dirty.y2;
-		if (qfbdev->dirty.x1 < x)
-			x = qfbdev->dirty.x1;
-		if (qfbdev->dirty.x2 > x2)
-			x2 = qfbdev->dirty.x2;
-	}
-
-	qfbdev->dirty.x1 = x;
-	qfbdev->dirty.x2 = x2;
-	qfbdev->dirty.y1 = y;
-	qfbdev->dirty.y2 = y2;
-
-	spin_unlock_irqrestore(&qfbdev->dirty.lock, flags);
-
-	schedule_work(&qdev->fb_work);
-}
-
-static void qxl_deferred_io(struct fb_info *info,
-			    struct list_head *pagelist)
-{
-	struct qxl_fbdev *qfbdev = info->par;
-	unsigned long start, end, min, max;
-	struct page *page;
-	int y1, y2;
-
-	min = ULONG_MAX;
-	max = 0;
-	list_for_each_entry(page, pagelist, lru) {
-		start = page->index << PAGE_SHIFT;
-		end = start + PAGE_SIZE - 1;
-		min = min(min, start);
-		max = max(max, end);
-	}
-
-	if (min < max) {
-		y1 = min / info->fix.line_length;
-		y2 = (max / info->fix.line_length) + 1;
-		qxl_dirty_update(qfbdev, 0, y1, info->var.xres, y2 - y1);
-	}
-};
-
 static struct fb_deferred_io qxl_defio = {
 	.delay		= QXL_DIRTY_DELAY,
-	.deferred_io	= qxl_deferred_io,
+	.deferred_io	= drm_fb_helper_deferred_io,
 };
 
-static void qxl_fb_fillrect(struct fb_info *info,
-			    const struct fb_fillrect *rect)
-{
-	struct qxl_fbdev *qfbdev = info->par;
-
-	drm_fb_helper_sys_fillrect(info, rect);
-	qxl_dirty_update(qfbdev, rect->dx, rect->dy, rect->width,
-			 rect->height);
-}
-
-static void qxl_fb_copyarea(struct fb_info *info,
-			    const struct fb_copyarea *area)
-{
-	struct qxl_fbdev *qfbdev = info->par;
-
-	drm_fb_helper_sys_copyarea(info, area);
-	qxl_dirty_update(qfbdev, area->dx, area->dy, area->width,
-			 area->height);
-}
-
-static void qxl_fb_imageblit(struct fb_info *info,
-			     const struct fb_image *image)
-{
-	struct qxl_fbdev *qfbdev = info->par;
-
-	drm_fb_helper_sys_imageblit(info, image);
-	qxl_dirty_update(qfbdev, image->dx, image->dy, image->width,
-			 image->height);
-}
-
-static void qxl_fb_work(struct work_struct *work)
-{
-	struct qxl_device *qdev = container_of(work, struct qxl_device, fb_work);
-	struct qxl_fbdev *qfbdev = qdev->mode_info.qfbdev;
-
-	qxl_fb_dirty_flush(qfbdev->helper.fbdev);
-}
-
-int qxl_fb_init(struct qxl_device *qdev)
-{
-	INIT_WORK(&qdev->fb_work, qxl_fb_work);
-	return 0;
-}
-
 static struct fb_ops qxlfb_ops = {
 	.owner = THIS_MODULE,
 	.fb_check_var = drm_fb_helper_check_var,
 	.fb_set_par = drm_fb_helper_set_par, /* TODO: copy vmwgfx */
-	.fb_fillrect = qxl_fb_fillrect,
-	.fb_copyarea = qxl_fb_copyarea,
-	.fb_imageblit = qxl_fb_imageblit,
+	.fb_fillrect = drm_fb_helper_sys_fillrect,
+	.fb_copyarea = drm_fb_helper_sys_copyarea,
+	.fb_imageblit = drm_fb_helper_sys_imageblit,
 	.fb_pan_display = drm_fb_helper_pan_display,
 	.fb_blank = drm_fb_helper_blank,
 	.fb_setcmap = drm_fb_helper_setcmap,
@@ -338,6 +178,57 @@ out_unref:
 	return ret;
 }
 
+/*
+ * FIXME
+ * It should not be necessary to have a special dirty() callback for fbdev.
+ */
+static int qxlfb_framebuffer_dirty(struct drm_framebuffer *fb,
+				   struct drm_file *file_priv,
+				   unsigned flags, unsigned color,
+				   struct drm_clip_rect *clips,
+				   unsigned num_clips)
+{
+	struct qxl_device *qdev = fb->dev->dev_private;
+	struct fb_info *info = qdev->fbdev_info;
+	struct qxl_fbdev *qfbdev = info->par;
+	struct qxl_fb_image qxl_fb_image;
+	struct fb_image *image = &qxl_fb_image.fb_image;
+
+	/* TODO: hard coding 32 bpp */
+	int stride = qfbdev->qfb.base.pitches[0];
+
+	/*
+	 * we are using a shadow draw buffer, at qdev->surface0_shadow
+	 */
+	qxl_io_log(qdev, "dirty x[%d, %d], y[%d, %d]", clips->x1, clips->x2,
+		   clips->y1, clips->y2);
+	image->dx = clips->x1;
+	image->dy = clips->y1;
+	image->width = clips->x2 - clips->x1;
+	image->height = clips->y2 - clips->y1;
+	image->fg_color = 0xffffffff; /* unused, just to avoid uninitialized
+					 warnings */
+	image->bg_color = 0;
+	image->depth = 32;	     /* TODO: take from somewhere? */
+	image->cmap.start = 0;
+	image->cmap.len = 0;
+	image->cmap.red = NULL;
+	image->cmap.green = NULL;
+	image->cmap.blue = NULL;
+	image->cmap.transp = NULL;
+	image->data = qfbdev->shadow + (clips->x1 * 4) + (stride * clips->y1);
+
+	qxl_fb_image_init(&qxl_fb_image, qdev, info, NULL);
+	qxl_draw_opaque_fb(&qxl_fb_image, stride);
+
+	return 0;
+}
+
+static const struct drm_framebuffer_funcs qxlfb_fb_funcs = {
+	.destroy = qxl_user_framebuffer_destroy,
+	.dirty = qxlfb_framebuffer_dirty,
+};
+
 static int qxlfb_create(struct qxl_fbdev *qfbdev,
 			struct drm_fb_helper_surface_size *sizes)
 {
@@ -360,6 +251,9 @@ static int qxlfb_create(struct qxl_fbdev
 	mode_cmd.pixel_format = drm_mode_legacy_fb_format(bpp, depth);
 
 	ret = qxlfb_create_pinned_object(qfbdev, &mode_cmd, &gobj);
+	if (ret < 0)
+		return ret;
+
 	qbo = gem_to_qxl_bo(gobj);
 	QXL_INFO(qdev, "%s: %dx%d %d\n", __func__, mode_cmd.width,
 		 mode_cmd.height, mode_cmd.pitches[0]);
@@ -383,7 +277,8 @@ static int qxlfb_create(struct qxl_fbdev
 
 	info->par = qfbdev;
 
-	qxl_framebuffer_init(qdev->ddev, &qfbdev->qfb, &mode_cmd, gobj);
+	qxl_framebuffer_init(qdev->ddev, &qfbdev->qfb, &mode_cmd, gobj,
+			     &qxlfb_fb_funcs);
 
 	fb = &qfbdev->qfb.base;
 
@@ -443,11 +338,11 @@ out_unref:
 		}
 	}
 	if (fb && ret) {
-		drm_gem_object_unreference(gobj);
+		drm_gem_object_unreference_unlocked(gobj);
 		drm_framebuffer_cleanup(fb);
 		kfree(fb);
 	}
-	drm_gem_object_unreference(gobj);
+	drm_gem_object_unreference_unlocked(gobj);
 	return ret;
 }
 
@@ -504,7 +399,6 @@ int qxl_fbdev_init(struct qxl_device *qd
 	qfbdev->qdev = qdev;
 	qdev->mode_info.qfbdev = qfbdev;
 	spin_lock_init(&qfbdev->delayed_ops_lock);
-	spin_lock_init(&qfbdev->dirty.lock);
 	INIT_LIST_HEAD(&qfbdev->delayed_ops);
 
 	drm_fb_helper_prepare(qdev->ddev, &qfbdev->helper,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/qxl/qxl_ioctl.c linux-libre-4.7-gnu/drivers/gpu/drm/qxl/qxl_ioctl.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/qxl/qxl_ioctl.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/qxl/qxl_ioctl.c	2016-07-24 15:23:50.000000000 -0400
@@ -107,15 +107,14 @@ apply_surf_reloc(struct qxl_device *qdev
 }
 
 /* return holding the reference to this object */
-static int qxlhw_handle_to_bo(struct qxl_device *qdev,
-			      struct drm_file *file_priv, uint64_t handle,
+static int qxlhw_handle_to_bo(struct drm_file *file_priv, uint64_t handle,
 			      struct qxl_release *release, struct qxl_bo **qbo_p)
 {
 	struct drm_gem_object *gobj;
 	struct qxl_bo *qobj;
 	int ret;
 
-	gobj = drm_gem_object_lookup(qdev->ddev, file_priv, handle);
+	gobj = drm_gem_object_lookup(file_priv, handle);
 	if (!gobj)
 		return -EINVAL;
 
@@ -221,7 +220,7 @@ static int qxl_process_single_command(st
 		reloc_info[i].type = reloc.reloc_type;
 
 		if (reloc.dst_handle) {
-			ret = qxlhw_handle_to_bo(qdev, file_priv, reloc.dst_handle, release,
+			ret = qxlhw_handle_to_bo(file_priv, reloc.dst_handle, release,
 						 &reloc_info[i].dst_bo);
 			if (ret)
 				goto out_free_bos;
@@ -234,7 +233,7 @@ static int qxl_process_single_command(st
 
 		/* reserve and validate the reloc dst bo */
 		if (reloc.reloc_type == QXL_RELOC_TYPE_BO || reloc.src_handle) {
-			ret = qxlhw_handle_to_bo(qdev, file_priv, reloc.src_handle, release,
+			ret = qxlhw_handle_to_bo(file_priv, reloc.src_handle, release,
 						 &reloc_info[i].src_bo);
 			if (ret)
 				goto out_free_bos;
@@ -314,7 +313,7 @@ static int qxl_update_area_ioctl(struct
 	    update_area->top >= update_area->bottom)
 		return -EINVAL;
 
-	gobj = drm_gem_object_lookup(dev, file, update_area->handle);
+	gobj = drm_gem_object_lookup(file, update_area->handle);
 	if (gobj == NULL)
 		return -ENOENT;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/qxl/qxl_kms.c linux-libre-4.7-gnu/drivers/gpu/drm/qxl/qxl_kms.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/qxl/qxl_kms.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/qxl/qxl_kms.c	2016-07-24 15:23:50.000000000 -0400
@@ -261,10 +261,6 @@ static int qxl_device_init(struct qxl_de
 	qdev->gc_queue = create_singlethread_workqueue("qxl_gc");
 	INIT_WORK(&qdev->gc_work, qxl_gc_work);
 
-	r = qxl_fb_init(qdev);
-	if (r)
-		return r;
-
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/qxl/qxl_object.h linux-libre-4.7-gnu/drivers/gpu/drm/qxl/qxl_object.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/qxl/qxl_object.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/qxl/qxl_object.h	2016-07-24 15:23:50.000000000 -0400
@@ -31,7 +31,7 @@ static inline int qxl_bo_reserve(struct
 {
 	int r;
 
-	r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, NULL);
+	r = ttm_bo_reserve(&bo->tbo, true, no_wait, NULL);
 	if (unlikely(r != 0)) {
 		if (r != -ERESTARTSYS) {
 			struct qxl_device *qdev = (struct qxl_device *)bo->gem_base.dev->dev_private;
@@ -67,7 +67,7 @@ static inline int qxl_bo_wait(struct qxl
 {
 	int r;
 
-	r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, NULL);
+	r = ttm_bo_reserve(&bo->tbo, true, no_wait, NULL);
 	if (unlikely(r != 0)) {
 		if (r != -ERESTARTSYS) {
 			struct qxl_device *qdev = (struct qxl_device *)bo->gem_base.dev->dev_private;
@@ -79,7 +79,7 @@ static inline int qxl_bo_wait(struct qxl
 	if (mem_type)
 		*mem_type = bo->tbo.mem.mem_type;
 
-	r = ttm_bo_wait(&bo->tbo, true, true, no_wait);
+	r = ttm_bo_wait(&bo->tbo, true, no_wait);
 	ttm_bo_unreserve(&bo->tbo);
 	return r;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/qxl/qxl_ttm.c linux-libre-4.7-gnu/drivers/gpu/drm/qxl/qxl_ttm.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/qxl/qxl_ttm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/qxl/qxl_ttm.c	2016-07-24 15:23:50.000000000 -0400
@@ -384,6 +384,8 @@ static struct ttm_bo_driver qxl_bo_drive
 	.io_mem_reserve = &qxl_ttm_io_mem_reserve,
 	.io_mem_free = &qxl_ttm_io_mem_free,
 	.move_notify = &qxl_bo_move_notify,
+	.lru_tail = &ttm_bo_default_lru_tail,
+	.swap_lru_tail = &ttm_bo_default_swap_lru_tail,
 };
 
 int qxl_ttm_init(struct qxl_device *qdev)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/radeon/atombios_crtc.c linux-libre-4.7-gnu/drivers/gpu/drm/radeon/atombios_crtc.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/radeon/atombios_crtc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/radeon/atombios_crtc.c	2016-07-24 15:23:50.000000000 -0400
@@ -589,7 +589,8 @@ static u32 atombios_adjust_pll(struct dr
 		if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev) || ASIC_IS_DCE8(rdev))
 			radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV;
 		/* use frac fb div on RS780/RS880 */
-		if ((rdev->family == CHIP_RS780) || (rdev->family == CHIP_RS880))
+		if (((rdev->family == CHIP_RS780) || (rdev->family == CHIP_RS880))
+		    && !radeon_crtc->ss_enabled)
 			radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV;
 		if (ASIC_IS_DCE32(rdev) && mode->clock > 165000)
 			radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV;
@@ -626,7 +627,7 @@ static u32 atombios_adjust_pll(struct dr
 			if (radeon_crtc->ss.refdiv) {
 				radeon_crtc->pll_flags |= RADEON_PLL_USE_REF_DIV;
 				radeon_crtc->pll_reference_div = radeon_crtc->ss.refdiv;
-				if (ASIC_IS_AVIVO(rdev))
+				if (rdev->family >= CHIP_RV770)
 					radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV;
 			}
 		}
@@ -1375,6 +1376,11 @@ static int dce4_crtc_do_set_base(struct
 		break;
 	}
 
+	/* Make sure surface address is updated at vertical blank rather than
+	 * horizontal blank
+	 */
+	WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, 0);
+
 	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
 	       upper_32_bits(fb_location));
 	WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
@@ -1427,12 +1433,6 @@ static int dce4_crtc_do_set_base(struct
 	WREG32(EVERGREEN_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
 	       (viewport_w << 16) | viewport_h);
 
-	/* pageflip setup */
-	/* make sure flip is at vb rather than hb */
-	tmp = RREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset);
-	tmp &= ~EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN;
-	WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp);
-
 	/* set pageflip to happen only at start of vblank interval (front porch) */
 	WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 3);
 
@@ -1466,7 +1466,7 @@ static int avivo_crtc_do_set_base(struct
 	uint64_t fb_location;
 	uint32_t fb_format, fb_pitch_pixels, tiling_flags;
 	u32 fb_swap = R600_D1GRPH_SWAP_ENDIAN_NONE;
-	u32 tmp, viewport_w, viewport_h;
+	u32 viewport_w, viewport_h;
 	int r;
 	bool bypass_lut = false;
 
@@ -1581,6 +1581,11 @@ static int avivo_crtc_do_set_base(struct
 	else
 		WREG32(AVIVO_D2VGA_CONTROL, 0);
 
+	/* Make sure surface address is update at vertical blank rather than
+	 * horizontal blank
+	 */
+	WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, 0);
+
 	if (rdev->family >= CHIP_RV770) {
 		if (radeon_crtc->crtc_id) {
 			WREG32(R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(fb_location));
@@ -1627,12 +1632,6 @@ static int avivo_crtc_do_set_base(struct
 	WREG32(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
 	       (viewport_w << 16) | viewport_h);
 
-	/* pageflip setup */
-	/* make sure flip is at vb rather than hb */
-	tmp = RREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset);
-	tmp &= ~AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN;
-	WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp);
-
 	/* set pageflip to happen only at start of vblank interval (front porch) */
 	WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 3);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/radeon/cik.c linux-libre-4.7-gnu/drivers/gpu/drm/radeon/cik.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/radeon/cik.c	2016-05-15 19:22:28.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/radeon/cik.c	2016-07-24 18:19:09.000000000 -0400
@@ -5182,15 +5182,21 @@ static void cik_gpu_pci_config_reset(str
  * cik_asic_reset - soft reset GPU
  *
  * @rdev: radeon_device pointer
+ * @hard: force hard reset
  *
  * Look up which blocks are hung and attempt
  * to reset them.
  * Returns 0 for success.
  */
-int cik_asic_reset(struct radeon_device *rdev)
+int cik_asic_reset(struct radeon_device *rdev, bool hard)
 {
 	u32 reset_mask;
 
+	if (hard) {
+		cik_gpu_pci_config_reset(rdev);
+		return 0;
+	}
+
 	reset_mask = cik_gpu_check_soft_reset(rdev);
 
 	if (reset_mask)
@@ -8058,6 +8064,164 @@ restart_ih:
 /*
  * startup/shutdown callbacks
  */
+static void cik_uvd_init(struct radeon_device *rdev)
+{
+	int r;
+
+	if (!rdev->has_uvd)
+		return;
+
+	r = radeon_uvd_init(rdev);
+	if (r) {
+		dev_err(rdev->dev, "failed UVD (%d) init.\n", r);
+		/*
+		 * At this point rdev->uvd.vcpu_bo is NULL which trickles down
+		 * to early fails cik_uvd_start() and thus nothing happens
+		 * there. So it is pointless to try to go through that code
+		 * hence why we disable uvd here.
+		 */
+		rdev->has_uvd = 0;
+		return;
+	}
+	rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_obj = NULL;
+	r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX], 4096);
+}
+
+static void cik_uvd_start(struct radeon_device *rdev)
+{
+	int r;
+
+	if (!rdev->has_uvd)
+		return;
+
+	r = radeon_uvd_resume(rdev);
+	if (r) {
+		dev_err(rdev->dev, "failed UVD resume (%d).\n", r);
+		goto error;
+	}
+	r = uvd_v4_2_resume(rdev);
+	if (r) {
+		dev_err(rdev->dev, "failed UVD 4.2 resume (%d).\n", r);
+		goto error;
+	}
+	r = radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_UVD_INDEX);
+	if (r) {
+		dev_err(rdev->dev, "failed initializing UVD fences (%d).\n", r);
+		goto error;
+	}
+	return;
+
+error:
+	rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
+}
+
+static void cik_uvd_resume(struct radeon_device *rdev)
+{
+	struct radeon_ring *ring;
+	int r;
+
+	if (!rdev->has_uvd || !rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size)
+		return;
+
+	ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
+	r = radeon_ring_init(rdev, ring, ring->ring_size, 0, RADEON_CP_PACKET2);
+	if (r) {
+		dev_err(rdev->dev, "failed initializing UVD ring (%d).\n", r);
+		return;
+	}
+	r = uvd_v1_0_init(rdev);
+	if (r) {
+		dev_err(rdev->dev, "failed initializing UVD (%d).\n", r);
+		return;
+	}
+}
+
+static void cik_vce_init(struct radeon_device *rdev)
+{
+	int r;
+
+	if (!rdev->has_vce)
+		return;
+
+	r = radeon_vce_init(rdev);
+	if (r) {
+		dev_err(rdev->dev, "failed VCE (%d) init.\n", r);
+		/*
+		 * At this point rdev->vce.vcpu_bo is NULL which trickles down
+		 * to early fails cik_vce_start() and thus nothing happens
+		 * there. So it is pointless to try to go through that code
+		 * hence why we disable vce here.
+		 */
+		rdev->has_vce = 0;
+		return;
+	}
+	rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_obj = NULL;
+	r600_ring_init(rdev, &rdev->ring[TN_RING_TYPE_VCE1_INDEX], 4096);
+	rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_obj = NULL;
+	r600_ring_init(rdev, &rdev->ring[TN_RING_TYPE_VCE2_INDEX], 4096);
+}
+
+static void cik_vce_start(struct radeon_device *rdev)
+{
+	int r;
+
+	if (!rdev->has_vce)
+		return;
+
+	r = radeon_vce_resume(rdev);
+	if (r) {
+		dev_err(rdev->dev, "failed VCE resume (%d).\n", r);
+		goto error;
+	}
+	r = vce_v2_0_resume(rdev);
+	if (r) {
+		dev_err(rdev->dev, "failed VCE resume (%d).\n", r);
+		goto error;
+	}
+	r = radeon_fence_driver_start_ring(rdev, TN_RING_TYPE_VCE1_INDEX);
+	if (r) {
+		dev_err(rdev->dev, "failed initializing VCE1 fences (%d).\n", r);
+		goto error;
+	}
+	r = radeon_fence_driver_start_ring(rdev, TN_RING_TYPE_VCE2_INDEX);
+	if (r) {
+		dev_err(rdev->dev, "failed initializing VCE2 fences (%d).\n", r);
+		goto error;
+	}
+	return;
+
+error:
+	rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size = 0;
+	rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_size = 0;
+}
+
+static void cik_vce_resume(struct radeon_device *rdev)
+{
+	struct radeon_ring *ring;
+	int r;
+
+	if (!rdev->has_vce || !rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size)
+		return;
+
+	ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX];
+	r = radeon_ring_init(rdev, ring, ring->ring_size, 0, VCE_CMD_NO_OP);
+	if (r) {
+		dev_err(rdev->dev, "failed initializing VCE1 ring (%d).\n", r);
+		return;
+	}
+	ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
+	r = radeon_ring_init(rdev, ring, ring->ring_size, 0, VCE_CMD_NO_OP);
+	if (r) {
+		dev_err(rdev->dev, "failed initializing VCE1 ring (%d).\n", r);
+		return;
+	}
+	r = vce_v1_0_init(rdev);
+	if (r) {
+		dev_err(rdev->dev, "failed initializing VCE (%d).\n", r);
+		return;
+	}
+}
+
 /**
  * cik_startup - program the asic to a functional state
  *
@@ -8160,34 +8324,8 @@ static int cik_startup(struct radeon_dev
 		return r;
 	}
 
-	r = radeon_uvd_resume(rdev);
-	if (!r) {
-		r = uvd_v4_2_resume(rdev);
-		if (!r) {
-			r = radeon_fence_driver_start_ring(rdev,
-							   R600_RING_TYPE_UVD_INDEX);
-			if (r)
-				dev_err(rdev->dev, "UVD fences init error (%d).\n", r);
-		}
-	}
-	if (r)
-		rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
-
-	r = radeon_vce_resume(rdev);
-	if (!r) {
-		r = vce_v2_0_resume(rdev);
-		if (!r)
-			r = radeon_fence_driver_start_ring(rdev,
-							   TN_RING_TYPE_VCE1_INDEX);
-		if (!r)
-			r = radeon_fence_driver_start_ring(rdev,
-							   TN_RING_TYPE_VCE2_INDEX);
-	}
-	if (r) {
-		dev_err(rdev->dev, "VCE init error (%d).\n", r);
-		rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size = 0;
-		rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_size = 0;
-	}
+	cik_uvd_start(rdev);
+	cik_vce_start(rdev);
 
 	/* Enable IRQ */
 	if (!rdev->irq.installed) {
@@ -8263,32 +8401,8 @@ static int cik_startup(struct radeon_dev
 	if (r)
 		return r;
 
-	ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
-	if (ring->ring_size) {
-		r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
-				     RADEON_CP_PACKET2);
-		if (!r)
-			r = uvd_v1_0_init(rdev);
-		if (r)
-			DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
-	}
-
-	r = -ENOENT;
-
-	ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX];
-	if (ring->ring_size)
-		r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
-				     VCE_CMD_NO_OP);
-
-	ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
-	if (ring->ring_size)
-		r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
-				     VCE_CMD_NO_OP);
-
-	if (!r)
-		r = vce_v1_0_init(rdev);
-	else if (r != -ENOENT)
-		DRM_ERROR("radeon: failed initializing VCE (%d).\n", r);
+	cik_uvd_resume(rdev);
+	cik_vce_resume(rdev);
 
 	r = radeon_ib_pool_init(rdev);
 	if (r) {
@@ -8364,9 +8478,12 @@ int cik_suspend(struct radeon_device *rd
 	radeon_vm_manager_fini(rdev);
 	cik_cp_enable(rdev, false);
 	cik_sdma_enable(rdev, false);
-	uvd_v1_0_fini(rdev);
-	radeon_uvd_suspend(rdev);
-	radeon_vce_suspend(rdev);
+	if (rdev->has_uvd) {
+		uvd_v1_0_fini(rdev);
+		radeon_uvd_suspend(rdev);
+	}
+	if (rdev->has_vce)
+		radeon_vce_suspend(rdev);
 	cik_fini_pg(rdev);
 	cik_fini_cg(rdev);
 	cik_irq_suspend(rdev);
@@ -8492,23 +8609,8 @@ int cik_init(struct radeon_device *rdev)
 	ring->ring_obj = NULL;
 	r600_ring_init(rdev, ring, 256 * 1024);
 
-	r = radeon_uvd_init(rdev);
-	if (!r) {
-		ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
-		ring->ring_obj = NULL;
-		r600_ring_init(rdev, ring, 4096);
-	}
-
-	r = radeon_vce_init(rdev);
-	if (!r) {
-		ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX];
-		ring->ring_obj = NULL;
-		r600_ring_init(rdev, ring, 4096);
-
-		ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
-		ring->ring_obj = NULL;
-		r600_ring_init(rdev, ring, 4096);
-	}
+	cik_uvd_init(rdev);
+	cik_vce_init(rdev);
 
 	rdev->ih.ring_obj = NULL;
 	r600_ih_ring_init(rdev, 64 * 1024);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/radeon/cikd.h linux-libre-4.7-gnu/drivers/gpu/drm/radeon/cikd.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/radeon/cikd.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/radeon/cikd.h	2016-07-24 15:23:50.000000000 -0400
@@ -2071,6 +2071,7 @@
 #define UVD_UDEC_DBW_ADDR_CONFIG	0xef54
 
 #define UVD_LMI_EXT40_ADDR		0xf498
+#define UVD_GP_SCRATCH4			0xf4e0
 #define UVD_LMI_ADDR_EXT		0xf594
 #define UVD_VCPU_CACHE_OFFSET0		0xf608
 #define UVD_VCPU_CACHE_SIZE0		0xf60c
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/radeon/evergreen.c linux-libre-4.7-gnu/drivers/gpu/drm/radeon/evergreen.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/radeon/evergreen.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/radeon/evergreen.c	2016-07-24 15:23:50.000000000 -0400
@@ -1407,11 +1407,14 @@ void dce4_wait_for_vblank(struct radeon_
  * Triggers the actual pageflip by updating the primary
  * surface base address (evergreen+).
  */
-void evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
+void evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base,
+			 bool async)
 {
 	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
 
 	/* update the scanout addresses */
+	WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset,
+	       async ? EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN : 0);
 	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
 	       upper_32_bits(crtc_base));
 	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
@@ -1864,7 +1867,8 @@ void evergreen_hpd_init(struct radeon_de
 			break;
 		}
 		radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
-		enabled |= 1 << radeon_connector->hpd.hpd;
+		if (radeon_connector->hpd.hpd != RADEON_HPD_NONE)
+			enabled |= 1 << radeon_connector->hpd.hpd;
 	}
 	radeon_irq_kms_enable_hpd(rdev, enabled);
 }
@@ -1907,7 +1911,8 @@ void evergreen_hpd_fini(struct radeon_de
 		default:
 			break;
 		}
-		disabled |= 1 << radeon_connector->hpd.hpd;
+		if (radeon_connector->hpd.hpd != RADEON_HPD_NONE)
+			disabled |= 1 << radeon_connector->hpd.hpd;
 	}
 	radeon_irq_kms_disable_hpd(rdev, disabled);
 }
@@ -4136,10 +4141,15 @@ void evergreen_gpu_pci_config_reset(stru
 	}
 }
 
-int evergreen_asic_reset(struct radeon_device *rdev)
+int evergreen_asic_reset(struct radeon_device *rdev, bool hard)
 {
 	u32 reset_mask;
 
+	if (hard) {
+		evergreen_gpu_pci_config_reset(rdev);
+		return 0;
+	}
+
 	reset_mask = evergreen_gpu_check_soft_reset(rdev);
 
 	if (reset_mask)
@@ -5515,6 +5525,73 @@ restart_ih:
 	return IRQ_HANDLED;
 }
 
+static void evergreen_uvd_init(struct radeon_device *rdev)
+{
+	int r;
+
+	if (!rdev->has_uvd)
+		return;
+
+	r = radeon_uvd_init(rdev);
+	if (r) {
+		dev_err(rdev->dev, "failed UVD (%d) init.\n", r);
+		/*
+		 * At this point rdev->uvd.vcpu_bo is NULL which trickles down
+		 * to early fails uvd_v2_2_resume() and thus nothing happens
+		 * there. So it is pointless to try to go through that code
+		 * hence why we disable uvd here.
+		 */
+		rdev->has_uvd = 0;
+		return;
+	}
+	rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_obj = NULL;
+	r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX], 4096);
+}
+
+static void evergreen_uvd_start(struct radeon_device *rdev)
+{
+	int r;
+
+	if (!rdev->has_uvd)
+		return;
+
+	r = uvd_v2_2_resume(rdev);
+	if (r) {
+		dev_err(rdev->dev, "failed UVD resume (%d).\n", r);
+		goto error;
+	}
+	r = radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_UVD_INDEX);
+	if (r) {
+		dev_err(rdev->dev, "failed initializing UVD fences (%d).\n", r);
+		goto error;
+	}
+	return;
+
+error:
+	rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
+}
+
+static void evergreen_uvd_resume(struct radeon_device *rdev)
+{
+	struct radeon_ring *ring;
+	int r;
+
+	if (!rdev->has_uvd || !rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size)
+		return;
+
+	ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
+	r = radeon_ring_init(rdev, ring, ring->ring_size, 0, RADEON_CP_PACKET2);
+	if (r) {
+		dev_err(rdev->dev, "failed initializing UVD ring (%d).\n", r);
+		return;
+	}
+	r = uvd_v1_0_init(rdev);
+	if (r) {
+		dev_err(rdev->dev, "failed initializing UVD (%d).\n", r);
+		return;
+	}
+}
+
 static int evergreen_startup(struct radeon_device *rdev)
 {
 	struct radeon_ring *ring;
@@ -5579,16 +5656,7 @@ static int evergreen_startup(struct rade
 		return r;
 	}
 
-	r = uvd_v2_2_resume(rdev);
-	if (!r) {
-		r = radeon_fence_driver_start_ring(rdev,
-						   R600_RING_TYPE_UVD_INDEX);
-		if (r)
-			dev_err(rdev->dev, "UVD fences init error (%d).\n", r);
-	}
-
-	if (r)
-		rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
+	evergreen_uvd_start(rdev);
 
 	/* Enable IRQ */
 	if (!rdev->irq.installed) {
@@ -5627,16 +5695,7 @@ static int evergreen_startup(struct rade
 	if (r)
 		return r;
 
-	ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
-	if (ring->ring_size) {
-		r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
-				     RADEON_CP_PACKET2);
-		if (!r)
-			r = uvd_v1_0_init(rdev);
-
-		if (r)
-			DRM_ERROR("radeon: error initializing UVD (%d).\n", r);
-	}
+	evergreen_uvd_resume(rdev);
 
 	r = radeon_ib_pool_init(rdev);
 	if (r) {
@@ -5691,8 +5750,10 @@ int evergreen_suspend(struct radeon_devi
 {
 	radeon_pm_suspend(rdev);
 	radeon_audio_fini(rdev);
-	uvd_v1_0_fini(rdev);
-	radeon_uvd_suspend(rdev);
+	if (rdev->has_uvd) {
+		uvd_v1_0_fini(rdev);
+		radeon_uvd_suspend(rdev);
+	}
 	r700_cp_stop(rdev);
 	r600_dma_stop(rdev);
 	evergreen_irq_suspend(rdev);
@@ -5793,12 +5854,7 @@ int evergreen_init(struct radeon_device
 	rdev->ring[R600_RING_TYPE_DMA_INDEX].ring_obj = NULL;
 	r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_DMA_INDEX], 64 * 1024);
 
-	r = radeon_uvd_init(rdev);
-	if (!r) {
-		rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_obj = NULL;
-		r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX],
-			       4096);
-	}
+	evergreen_uvd_init(rdev);
 
 	rdev->ih.ring_obj = NULL;
 	r600_ih_ring_init(rdev, 64 * 1024);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/radeon/evergreen_cs.c linux-libre-4.7-gnu/drivers/gpu/drm/radeon/evergreen_cs.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/radeon/evergreen_cs.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/radeon/evergreen_cs.c	2016-07-24 15:23:50.000000000 -0400
@@ -2608,6 +2608,51 @@ static int evergreen_packet3_check(struc
 			}
 		}
 		break;
+	case PACKET3_SET_APPEND_CNT:
+	{
+		uint32_t areg;
+		uint32_t allowed_reg_base;
+		uint32_t source_sel;
+		if (pkt->count != 2) {
+			DRM_ERROR("bad SET_APPEND_CNT (invalid count)\n");
+			return -EINVAL;
+		}
+
+		allowed_reg_base = GDS_APPEND_COUNT_0;
+		allowed_reg_base -= PACKET3_SET_CONTEXT_REG_START;
+		allowed_reg_base >>= 2;
+
+		areg = idx_value >> 16;
+		if (areg < allowed_reg_base || areg > (allowed_reg_base + 11)) {
+			dev_warn(p->dev, "forbidden register for append cnt 0x%08x at %d\n",
+				 areg, idx);
+			return -EINVAL;
+		}
+
+		source_sel = G_PACKET3_SET_APPEND_CNT_SRC_SELECT(idx_value);
+		if (source_sel == PACKET3_SAC_SRC_SEL_MEM) {
+			uint64_t offset;
+			uint32_t swap;
+			r = radeon_cs_packet_next_reloc(p, &reloc, 0);
+			if (r) {
+				DRM_ERROR("bad SET_APPEND_CNT (missing reloc)\n");
+				return -EINVAL;
+			}
+			offset = radeon_get_ib_value(p, idx + 1);
+			swap = offset & 0x3;
+			offset &= ~0x3;
+
+			offset += ((u64)(radeon_get_ib_value(p, idx + 2) & 0xff)) << 32;
+
+			offset += reloc->gpu_offset;
+			ib[idx+1] = (offset & 0xfffffffc) | swap;
+			ib[idx+2] = upper_32_bits(offset) & 0xff;
+		} else {
+			DRM_ERROR("bad SET_APPEND_CNT (unsupported operation)\n");
+			return -EINVAL;
+		}
+		break;
+	}
 	case PACKET3_NOP:
 		break;
 	default:
@@ -3438,6 +3483,27 @@ static int evergreen_vm_packet3_check(st
 			}
 		}
 		break;
+	case PACKET3_SET_APPEND_CNT: {
+		uint32_t areg;
+		uint32_t allowed_reg_base;
+
+		if (pkt->count != 2) {
+			DRM_ERROR("bad SET_APPEND_CNT (invalid count)\n");
+			return -EINVAL;
+		}
+
+		allowed_reg_base = GDS_APPEND_COUNT_0;
+		allowed_reg_base -= PACKET3_SET_CONTEXT_REG_START;
+		allowed_reg_base >>= 2;
+
+		areg = idx_value >> 16;
+		if (areg < allowed_reg_base || areg > (allowed_reg_base + 11)) {
+			DRM_ERROR("forbidden register for append cnt 0x%08x at %d\n",
+				  areg, idx);
+			return -EINVAL;
+		}
+		break;
+	}
 	default:
 		return -EINVAL;
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/radeon/evergreend.h linux-libre-4.7-gnu/drivers/gpu/drm/radeon/evergreend.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/radeon/evergreend.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/radeon/evergreend.h	2016-07-24 15:23:50.000000000 -0400
@@ -1689,6 +1689,36 @@
 #define	PACKET3_SET_CONTEXT_REG_INDIRECT		0x73
 #define	PACKET3_SET_RESOURCE_INDIRECT			0x74
 #define	PACKET3_SET_APPEND_CNT			        0x75
+/* SET_APPEND_CNT - documentation
+ * 1. header
+ * 2. COMMAND
+ *  1:0 - SOURCE SEL
+ *  15:2 - Reserved
+ *  31:16 - WR_REG_OFFSET - context register to write source data to.
+ *          (one of R_02872C_GDS_APPEND_COUNT_0-11)
+ * 3. CONTROL
+ *  (for source == mem)
+ *  31:2 SRC_ADDRESS_LO
+ *  0:1 SWAP
+ *  (for source == GDS)
+ *  31:0 GDS offset
+ *  (for source == DATA)
+ *  31:0 DATA
+ *  (for source == REG)
+ *  31:0 REG
+ * 4. SRC_ADDRESS_HI[7:0]
+ * kernel driver 2.44 only supports SRC == MEM.
+ */
+#define PACKET3_SET_APPEND_CNT_SRC_SELECT(x) ((x) << 0)
+#define G_PACKET3_SET_APPEND_CNT_SRC_SELECT(x) ((x & 0x3) >> 0)
+/* source is from the data in CONTROL */
+#define PACKET3_SAC_SRC_SEL_DATA 0x0
+/* source is from register */
+#define PACKET3_SAC_SRC_SEL_REG  0x1
+/* source is from GDS offset in CONTROL */
+#define PACKET3_SAC_SRC_SEL_GDS  0x2
+/* source is from memory address */
+#define PACKET3_SAC_SRC_SEL_MEM  0x3
 
 #define	SQ_RESOURCE_CONSTANT_WORD7_0				0x3001c
 #define		S__SQ_CONSTANT_TYPE(x)			(((x) & 3) << 30)
@@ -2005,6 +2035,19 @@
 
 #define GDS_ADDR_BASE					0x28720
 
+#define GDS_APPEND_COUNT_0				0x2872C
+#define GDS_APPEND_COUNT_1				0x28730
+#define GDS_APPEND_COUNT_2				0x28734
+#define GDS_APPEND_COUNT_3				0x28738
+#define GDS_APPEND_COUNT_4				0x2873C
+#define GDS_APPEND_COUNT_5				0x28740
+#define GDS_APPEND_COUNT_6				0x28744
+#define GDS_APPEND_COUNT_7				0x28748
+#define GDS_APPEND_COUNT_8				0x2874c
+#define GDS_APPEND_COUNT_9				0x28750
+#define GDS_APPEND_COUNT_10				0x28754
+#define GDS_APPEND_COUNT_11				0x28758
+
 #define	CB_IMMED0_BASE					0x28b9c
 #define	CB_IMMED1_BASE					0x28ba0
 #define	CB_IMMED2_BASE					0x28ba4
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/radeon/kv_dpm.c linux-libre-4.7-gnu/drivers/gpu/drm/radeon/kv_dpm.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/radeon/kv_dpm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/radeon/kv_dpm.c	2016-07-24 15:23:50.000000000 -0400
@@ -2164,7 +2164,7 @@ static void kv_apply_state_adjust_rules(
 	if (pi->caps_stable_p_state) {
 		stable_p_state_sclk = (max_limits->sclk * 75) / 100;
 
-		for (i = table->count - 1; i >= 0; i++) {
+		for (i = table->count - 1; i >= 0; i--) {
 			if (stable_p_state_sclk >= table->entries[i].clk) {
 				stable_p_state_sclk = table->entries[i].clk;
 				break;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/radeon/ni.c linux-libre-4.7-gnu/drivers/gpu/drm/radeon/ni.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/radeon/ni.c	2016-05-15 19:22:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/radeon/ni.c	2016-07-24 18:18:53.000000000 -0400
@@ -1939,10 +1939,15 @@ static void cayman_gpu_soft_reset(struct
 	evergreen_print_gpu_status_regs(rdev);
 }
 
-int cayman_asic_reset(struct radeon_device *rdev)
+int cayman_asic_reset(struct radeon_device *rdev, bool hard)
 {
 	u32 reset_mask;
 
+	if (hard) {
+		evergreen_gpu_pci_config_reset(rdev);
+		return 0;
+	}
+
 	reset_mask = cayman_gpu_check_soft_reset(rdev);
 
 	if (reset_mask)
@@ -1982,6 +1987,160 @@ bool cayman_gfx_is_lockup(struct radeon_
 	return radeon_ring_test_lockup(rdev, ring);
 }
 
+static void cayman_uvd_init(struct radeon_device *rdev)
+{
+	int r;
+
+	if (!rdev->has_uvd)
+		return;
+
+	r = radeon_uvd_init(rdev);
+	if (r) {
+		dev_err(rdev->dev, "failed UVD (%d) init.\n", r);
+		/*
+		 * At this point rdev->uvd.vcpu_bo is NULL which trickles down
+		 * to early fails uvd_v2_2_resume() and thus nothing happens
+		 * there. So it is pointless to try to go through that code
+		 * hence why we disable uvd here.
+		 */
+		rdev->has_uvd = 0;
+		return;
+	}
+	rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_obj = NULL;
+	r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX], 4096);
+}
+
+static void cayman_uvd_start(struct radeon_device *rdev)
+{
+	int r;
+
+	if (!rdev->has_uvd)
+		return;
+
+	r = uvd_v2_2_resume(rdev);
+	if (r) {
+		dev_err(rdev->dev, "failed UVD resume (%d).\n", r);
+		goto error;
+	}
+	r = radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_UVD_INDEX);
+	if (r) {
+		dev_err(rdev->dev, "failed initializing UVD fences (%d).\n", r);
+		goto error;
+	}
+	return;
+
+error:
+	rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
+}
+
+static void cayman_uvd_resume(struct radeon_device *rdev)
+{
+	struct radeon_ring *ring;
+	int r;
+
+	if (!rdev->has_uvd || !rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size)
+		return;
+
+	ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
+	r = radeon_ring_init(rdev, ring, ring->ring_size, 0, RADEON_CP_PACKET2);
+	if (r) {
+		dev_err(rdev->dev, "failed initializing UVD ring (%d).\n", r);
+		return;
+	}
+	r = uvd_v1_0_init(rdev);
+	if (r) {
+		dev_err(rdev->dev, "failed initializing UVD (%d).\n", r);
+		return;
+	}
+}
+
+static void cayman_vce_init(struct radeon_device *rdev)
+{
+	int r;
+
+	/* Only set for CHIP_ARUBA */
+	if (!rdev->has_vce)
+		return;
+
+	r = radeon_vce_init(rdev);
+	if (r) {
+		dev_err(rdev->dev, "failed VCE (%d) init.\n", r);
+		/*
+		 * At this point rdev->vce.vcpu_bo is NULL which trickles down
+		 * to early fails cayman_vce_start() and thus nothing happens
+		 * there. So it is pointless to try to go through that code
+		 * hence why we disable vce here.
+		 */
+		rdev->has_vce = 0;
+		return;
+	}
+	rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_obj = NULL;
+	r600_ring_init(rdev, &rdev->ring[TN_RING_TYPE_VCE1_INDEX], 4096);
+	rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_obj = NULL;
+	r600_ring_init(rdev, &rdev->ring[TN_RING_TYPE_VCE2_INDEX], 4096);
+}
+
+static void cayman_vce_start(struct radeon_device *rdev)
+{
+	int r;
+
+	if (!rdev->has_vce)
+		return;
+
+	r = radeon_vce_resume(rdev);
+	if (r) {
+		dev_err(rdev->dev, "failed VCE resume (%d).\n", r);
+		goto error;
+	}
+	r = vce_v1_0_resume(rdev);
+	if (r) {
+		dev_err(rdev->dev, "failed VCE resume (%d).\n", r);
+		goto error;
+	}
+	r = radeon_fence_driver_start_ring(rdev, TN_RING_TYPE_VCE1_INDEX);
+	if (r) {
+		dev_err(rdev->dev, "failed initializing VCE1 fences (%d).\n", r);
+		goto error;
+	}
+	r = radeon_fence_driver_start_ring(rdev, TN_RING_TYPE_VCE2_INDEX);
+	if (r) {
+		dev_err(rdev->dev, "failed initializing VCE2 fences (%d).\n", r);
+		goto error;
+	}
+	return;
+
+error:
+	rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size = 0;
+	rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_size = 0;
+}
+
+static void cayman_vce_resume(struct radeon_device *rdev)
+{
+	struct radeon_ring *ring;
+	int r;
+
+	if (!rdev->has_vce || !rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size)
+		return;
+
+	ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX];
+	r = radeon_ring_init(rdev, ring, ring->ring_size, 0, 0x0);
+	if (r) {
+		dev_err(rdev->dev, "failed initializing VCE1 ring (%d).\n", r);
+		return;
+	}
+	ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
+	r = radeon_ring_init(rdev, ring, ring->ring_size, 0, 0x0);
+	if (r) {
+		dev_err(rdev->dev, "failed initializing VCE1 ring (%d).\n", r);
+		return;
+	}
+	r = vce_v1_0_init(rdev);
+	if (r) {
+		dev_err(rdev->dev, "failed initializing VCE (%d).\n", r);
+		return;
+	}
+}
+
 static int cayman_startup(struct radeon_device *rdev)
 {
 	struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
@@ -2036,34 +2195,8 @@ static int cayman_startup(struct radeon_
 		return r;
 	}
 
-	r = uvd_v2_2_resume(rdev);
-	if (!r) {
-		r = radeon_fence_driver_start_ring(rdev,
-						   R600_RING_TYPE_UVD_INDEX);
-		if (r)
-			dev_err(rdev->dev, "UVD fences init error (%d).\n", r);
-	}
-	if (r)
-		rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
-
-	if (rdev->family == CHIP_ARUBA) {
-		r = radeon_vce_resume(rdev);
-		if (!r)
-			r = vce_v1_0_resume(rdev);
-
-		if (!r)
-			r = radeon_fence_driver_start_ring(rdev,
-							   TN_RING_TYPE_VCE1_INDEX);
-		if (!r)
-			r = radeon_fence_driver_start_ring(rdev,
-							   TN_RING_TYPE_VCE2_INDEX);
-
-		if (r) {
-			dev_err(rdev->dev, "VCE init error (%d).\n", r);
-			rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size = 0;
-			rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_size = 0;
-		}
-	}
+	cayman_uvd_start(rdev);
+	cayman_vce_start(rdev);
 
 	r = radeon_fence_driver_start_ring(rdev, CAYMAN_RING_TYPE_CP1_INDEX);
 	if (r) {
@@ -2132,30 +2265,8 @@ static int cayman_startup(struct radeon_
 	if (r)
 		return r;
 
-	ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
-	if (ring->ring_size) {
-		r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
-				     RADEON_CP_PACKET2);
-		if (!r)
-			r = uvd_v1_0_init(rdev);
-		if (r)
-			DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
-	}
-
-	if (rdev->family == CHIP_ARUBA) {
-		ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX];
-		if (ring->ring_size)
-			r = radeon_ring_init(rdev, ring, ring->ring_size, 0, 0x0);
-
-		ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
-		if (ring->ring_size)
-			r = radeon_ring_init(rdev, ring, ring->ring_size, 0, 0x0);
-
-		if (!r)
-			r = vce_v1_0_init(rdev);
-		if (r)
-			DRM_ERROR("radeon: failed initializing VCE (%d).\n", r);
-	}
+	cayman_uvd_resume(rdev);
+	cayman_vce_resume(rdev);
 
 	r = radeon_ib_pool_init(rdev);
 	if (r) {
@@ -2210,8 +2321,10 @@ int cayman_suspend(struct radeon_device
 	radeon_vm_manager_fini(rdev);
 	cayman_cp_enable(rdev, false);
 	cayman_dma_stop(rdev);
-	uvd_v1_0_fini(rdev);
-	radeon_uvd_suspend(rdev);
+	if (rdev->has_uvd) {
+		uvd_v1_0_fini(rdev);
+		radeon_uvd_suspend(rdev);
+	}
 	evergreen_irq_suspend(rdev);
 	radeon_wb_disable(rdev);
 	cayman_pcie_gart_disable(rdev);
@@ -2305,25 +2418,8 @@ int cayman_init(struct radeon_device *rd
 	ring->ring_obj = NULL;
 	r600_ring_init(rdev, ring, 64 * 1024);
 
-	r = radeon_uvd_init(rdev);
-	if (!r) {
-		ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
-		ring->ring_obj = NULL;
-		r600_ring_init(rdev, ring, 4096);
-	}
-
-	if (rdev->family == CHIP_ARUBA) {
-		r = radeon_vce_init(rdev);
-		if (!r) {
-			ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX];
-			ring->ring_obj = NULL;
-			r600_ring_init(rdev, ring, 4096);
-
-			ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
-			ring->ring_obj = NULL;
-			r600_ring_init(rdev, ring, 4096);
-		}
-	}
+	cayman_uvd_init(rdev);
+	cayman_vce_init(rdev);
 
 	rdev->ih.ring_obj = NULL;
 	r600_ih_ring_init(rdev, 64 * 1024);
@@ -2378,7 +2474,7 @@ void cayman_fini(struct radeon_device *r
 	radeon_irq_kms_fini(rdev);
 	uvd_v1_0_fini(rdev);
 	radeon_uvd_fini(rdev);
-	if (rdev->family == CHIP_ARUBA)
+	if (rdev->has_vce)
 		radeon_vce_fini(rdev);
 	cayman_pcie_gart_fini(rdev);
 	r600_vram_scratch_fini(rdev);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/radeon/r100.c linux-libre-4.7-gnu/drivers/gpu/drm/radeon/r100.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/radeon/r100.c	2016-05-15 19:22:04.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/radeon/r100.c	2016-07-24 18:18:44.000000000 -0400
@@ -147,7 +147,7 @@ void r100_wait_for_vblank(struct radeon_
  * bit to go high, when it does, we release the lock, and allow the
  * double buffered update to take place.
  */
-void r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
+void r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base, bool async)
 {
 	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
 	u32 tmp = ((u32)crtc_base) | RADEON_CRTC_OFFSET__OFFSET_LOCK;
@@ -586,7 +586,8 @@ void r100_hpd_init(struct radeon_device
 
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-		enable |= 1 << radeon_connector->hpd.hpd;
+		if (radeon_connector->hpd.hpd != RADEON_HPD_NONE)
+			enable |= 1 << radeon_connector->hpd.hpd;
 		radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
 	}
 	radeon_irq_kms_enable_hpd(rdev, enable);
@@ -608,7 +609,8 @@ void r100_hpd_fini(struct radeon_device
 
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 		struct radeon_connector *radeon_connector = to_radeon_connector(connector);
-		disable |= 1 << radeon_connector->hpd.hpd;
+		if (radeon_connector->hpd.hpd != RADEON_HPD_NONE)
+			disable |= 1 << radeon_connector->hpd.hpd;
 	}
 	radeon_irq_kms_disable_hpd(rdev, disable);
 }
@@ -2549,7 +2551,7 @@ void r100_bm_disable(struct radeon_devic
 	mdelay(1);
 }
 
-int r100_asic_reset(struct radeon_device *rdev)
+int r100_asic_reset(struct radeon_device *rdev, bool hard)
 {
 	struct r100_mc_save save;
 	u32 status, tmp;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/radeon/r300.c linux-libre-4.7-gnu/drivers/gpu/drm/radeon/r300.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/radeon/r300.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/radeon/r300.c	2016-07-24 15:23:50.000000000 -0400
@@ -410,7 +410,7 @@ static void r300_gpu_init(struct radeon_
 		 rdev->num_gb_pipes, rdev->num_z_pipes);
 }
 
-int r300_asic_reset(struct radeon_device *rdev)
+int r300_asic_reset(struct radeon_device *rdev, bool hard)
 {
 	struct r100_mc_save save;
 	u32 status, tmp;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/radeon/r600.c linux-libre-4.7-gnu/drivers/gpu/drm/radeon/r600.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/radeon/r600.c	2016-05-15 19:22:09.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/radeon/r600.c	2016-07-24 18:18:49.000000000 -0400
@@ -954,7 +954,8 @@ void r600_hpd_init(struct radeon_device
 				break;
 			}
 		}
-		enable |= 1 << radeon_connector->hpd.hpd;
+		if (radeon_connector->hpd.hpd != RADEON_HPD_NONE)
+			enable |= 1 << radeon_connector->hpd.hpd;
 		radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
 	}
 	radeon_irq_kms_enable_hpd(rdev, enable);
@@ -1007,7 +1008,8 @@ void r600_hpd_fini(struct radeon_device
 				break;
 			}
 		}
-		disable |= 1 << radeon_connector->hpd.hpd;
+		if (radeon_connector->hpd.hpd != RADEON_HPD_NONE)
+			disable |= 1 << radeon_connector->hpd.hpd;
 	}
 	radeon_irq_kms_disable_hpd(rdev, disable);
 }
@@ -1823,10 +1825,15 @@ static void r600_gpu_pci_config_reset(st
 	}
 }
 
-int r600_asic_reset(struct radeon_device *rdev)
+int r600_asic_reset(struct radeon_device *rdev, bool hard)
 {
 	u32 reset_mask;
 
+	if (hard) {
+		r600_gpu_pci_config_reset(rdev);
+		return 0;
+	}
+
 	reset_mask = r600_gpu_check_soft_reset(rdev);
 
 	if (reset_mask)
@@ -2987,6 +2994,73 @@ void r600_clear_surface_reg(struct radeo
 	/* FIXME: implement */
 }
 
+static void r600_uvd_init(struct radeon_device *rdev)
+{
+	int r;
+
+	if (!rdev->has_uvd)
+		return;
+
+	r = radeon_uvd_init(rdev);
+	if (r) {
+		dev_err(rdev->dev, "failed UVD (%d) init.\n", r);
+		/*
+		 * At this point rdev->uvd.vcpu_bo is NULL which trickles down
+		 * to early fails uvd_v1_0_resume() and thus nothing happens
+		 * there. So it is pointless to try to go through that code
+		 * hence why we disable uvd here.
+		 */
+		rdev->has_uvd = 0;
+		return;
+	}
+	rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_obj = NULL;
+	r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX], 4096);
+}
+
+static void r600_uvd_start(struct radeon_device *rdev)
+{
+	int r;
+
+	if (!rdev->has_uvd)
+		return;
+
+	r = uvd_v1_0_resume(rdev);
+	if (r) {
+		dev_err(rdev->dev, "failed UVD resume (%d).\n", r);
+		goto error;
+	}
+	r = radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_UVD_INDEX);
+	if (r) {
+		dev_err(rdev->dev, "failed initializing UVD fences (%d).\n", r);
+		goto error;
+	}
+	return;
+
+error:
+	rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
+}
+
+static void r600_uvd_resume(struct radeon_device *rdev)
+{
+	struct radeon_ring *ring;
+	int r;
+
+	if (!rdev->has_uvd || !rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size)
+		return;
+
+	ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
+	r = radeon_ring_init(rdev, ring, ring->ring_size, 0, RADEON_CP_PACKET2);
+	if (r) {
+		dev_err(rdev->dev, "failed initializing UVD ring (%d).\n", r);
+		return;
+	}
+	r = uvd_v1_0_init(rdev);
+	if (r) {
+		dev_err(rdev->dev, "failed initializing UVD (%d).\n", r);
+		return;
+	}
+}
+
 static int r600_startup(struct radeon_device *rdev)
 {
 	struct radeon_ring *ring;
@@ -3022,17 +3096,7 @@ static int r600_startup(struct radeon_de
 		return r;
 	}
 
-	if (rdev->has_uvd) {
-		r = uvd_v1_0_resume(rdev);
-		if (!r) {
-			r = radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_UVD_INDEX);
-			if (r) {
-				dev_err(rdev->dev, "failed initializing UVD fences (%d).\n", r);
-			}
-		}
-		if (r)
-			rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
-	}
+	r600_uvd_start(rdev);
 
 	/* Enable IRQ */
 	if (!rdev->irq.installed) {
@@ -3062,17 +3126,7 @@ static int r600_startup(struct radeon_de
 	if (r)
 		return r;
 
-	if (rdev->has_uvd) {
-		ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
-		if (ring->ring_size) {
-			r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
-					     RADEON_CP_PACKET2);
-			if (!r)
-				r = uvd_v1_0_init(rdev);
-			if (r)
-				DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
-		}
-	}
+	r600_uvd_resume(rdev);
 
 	r = radeon_ib_pool_init(rdev);
 	if (r) {
@@ -3216,13 +3270,7 @@ int r600_init(struct radeon_device *rdev
 	rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL;
 	r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024);
 
-	if (rdev->has_uvd) {
-		r = radeon_uvd_init(rdev);
-		if (!r) {
-			rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_obj = NULL;
-			r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX], 4096);
-		}
-	}
+	r600_uvd_init(rdev);
 
 	rdev->ih.ring_obj = NULL;
 	r600_ih_ring_init(rdev, 64 * 1024);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/radeon/radeon_asic.c linux-libre-4.7-gnu/drivers/gpu/drm/radeon/radeon_asic.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/radeon/radeon_asic.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/radeon/radeon_asic.c	2016-07-24 15:23:50.000000000 -0400
@@ -2324,6 +2324,7 @@ int radeon_asic_init(struct radeon_devic
 		rdev->num_crtc = 2;
 
 	rdev->has_uvd = false;
+	rdev->has_vce = false;
 
 	switch (rdev->family) {
 	case CHIP_R100:
@@ -2454,6 +2455,7 @@ int radeon_asic_init(struct radeon_devic
 		/* set num crtcs */
 		rdev->num_crtc = 4;
 		rdev->has_uvd = true;
+		rdev->has_vce = true;
 		rdev->cg_flags =
 			RADEON_CG_SUPPORT_VCE_MGCG;
 		break;
@@ -2470,10 +2472,13 @@ int radeon_asic_init(struct radeon_devic
 			rdev->num_crtc = 2;
 		else
 			rdev->num_crtc = 6;
-		if (rdev->family == CHIP_HAINAN)
+		if (rdev->family == CHIP_HAINAN) {
 			rdev->has_uvd = false;
-		else
+			rdev->has_vce = false;
+		} else {
 			rdev->has_uvd = true;
+			rdev->has_vce = true;
+		}
 		switch (rdev->family) {
 		case CHIP_TAHITI:
 			rdev->cg_flags =
@@ -2578,6 +2583,7 @@ int radeon_asic_init(struct radeon_devic
 		rdev->asic = &ci_asic;
 		rdev->num_crtc = 6;
 		rdev->has_uvd = true;
+		rdev->has_vce = true;
 		if (rdev->family == CHIP_BONAIRE) {
 			rdev->cg_flags =
 				RADEON_CG_SUPPORT_GFX_MGCG |
@@ -2678,6 +2684,7 @@ int radeon_asic_init(struct radeon_devic
 				RADEON_PG_SUPPORT_SAMU;*/
 		}
 		rdev->has_uvd = true;
+		rdev->has_vce = true;
 		break;
 	default:
 		/* FIXME: not supported yet */
@@ -2689,6 +2696,11 @@ int radeon_asic_init(struct radeon_devic
 		rdev->asic->pm.set_memory_clock = NULL;
 	}
 
+	if (!radeon_uvd)
+		rdev->has_uvd = false;
+	if (!radeon_vce)
+		rdev->has_vce = false;
+
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/radeon/radeon_asic.h linux-libre-4.7-gnu/drivers/gpu/drm/radeon/radeon_asic.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/radeon/radeon_asic.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/radeon/radeon_asic.h	2016-07-24 15:23:50.000000000 -0400
@@ -64,7 +64,7 @@ int r100_suspend(struct radeon_device *r
 int r100_resume(struct radeon_device *rdev);
 void r100_vga_set_state(struct radeon_device *rdev, bool state);
 bool r100_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *cp);
-int r100_asic_reset(struct radeon_device *rdev);
+int r100_asic_reset(struct radeon_device *rdev, bool hard);
 u32 r100_get_vblank_counter(struct radeon_device *rdev, int crtc);
 void r100_pci_gart_tlb_flush(struct radeon_device *rdev);
 uint64_t r100_pci_gart_get_page_entry(uint64_t addr, uint32_t flags);
@@ -138,7 +138,7 @@ extern void r100_pm_finish(struct radeon
 extern void r100_pm_init_profile(struct radeon_device *rdev);
 extern void r100_pm_get_dynpm_state(struct radeon_device *rdev);
 extern void r100_page_flip(struct radeon_device *rdev, int crtc,
-			   u64 crtc_base);
+			   u64 crtc_base, bool async);
 extern bool r100_page_flip_pending(struct radeon_device *rdev, int crtc);
 extern void r100_wait_for_vblank(struct radeon_device *rdev, int crtc);
 extern int r100_mc_wait_for_idle(struct radeon_device *rdev);
@@ -167,7 +167,7 @@ extern int r300_init(struct radeon_devic
 extern void r300_fini(struct radeon_device *rdev);
 extern int r300_suspend(struct radeon_device *rdev);
 extern int r300_resume(struct radeon_device *rdev);
-extern int r300_asic_reset(struct radeon_device *rdev);
+extern int r300_asic_reset(struct radeon_device *rdev, bool hard);
 extern void r300_ring_start(struct radeon_device *rdev, struct radeon_ring *ring);
 extern void r300_fence_ring_emit(struct radeon_device *rdev,
 				struct radeon_fence *fence);
@@ -225,7 +225,7 @@ extern int rs400_mc_wait_for_idle(struct
 /*
  * rs600.
  */
-extern int rs600_asic_reset(struct radeon_device *rdev);
+extern int rs600_asic_reset(struct radeon_device *rdev, bool hard);
 extern int rs600_init(struct radeon_device *rdev);
 extern void rs600_fini(struct radeon_device *rdev);
 extern int rs600_suspend(struct radeon_device *rdev);
@@ -250,7 +250,7 @@ extern void rs600_pm_misc(struct radeon_
 extern void rs600_pm_prepare(struct radeon_device *rdev);
 extern void rs600_pm_finish(struct radeon_device *rdev);
 extern void rs600_page_flip(struct radeon_device *rdev, int crtc,
-			    u64 crtc_base);
+			    u64 crtc_base, bool async);
 extern bool rs600_page_flip_pending(struct radeon_device *rdev, int crtc);
 void rs600_set_safe_registers(struct radeon_device *rdev);
 extern void avivo_wait_for_vblank(struct radeon_device *rdev, int crtc);
@@ -334,7 +334,7 @@ bool r600_dma_semaphore_ring_emit(struct
 void r600_dma_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
 bool r600_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring);
 bool r600_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *cp);
-int r600_asic_reset(struct radeon_device *rdev);
+int r600_asic_reset(struct radeon_device *rdev, bool hard);
 int r600_set_surface_reg(struct radeon_device *rdev, int reg,
 			 uint32_t tiling_flags, uint32_t pitch,
 			 uint32_t offset, uint32_t obj_size);
@@ -464,7 +464,8 @@ void rv770_fini(struct radeon_device *rd
 int rv770_suspend(struct radeon_device *rdev);
 int rv770_resume(struct radeon_device *rdev);
 void rv770_pm_misc(struct radeon_device *rdev);
-void rv770_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base);
+void rv770_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base,
+		     bool async);
 bool rv770_page_flip_pending(struct radeon_device *rdev, int crtc);
 void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc);
 void r700_cp_stop(struct radeon_device *rdev);
@@ -513,7 +514,7 @@ int evergreen_suspend(struct radeon_devi
 int evergreen_resume(struct radeon_device *rdev);
 bool evergreen_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *cp);
 bool evergreen_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *cp);
-int evergreen_asic_reset(struct radeon_device *rdev);
+int evergreen_asic_reset(struct radeon_device *rdev, bool hard);
 void evergreen_bandwidth_update(struct radeon_device *rdev);
 void evergreen_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
 void evergreen_hpd_init(struct radeon_device *rdev);
@@ -534,7 +535,7 @@ extern void btc_pm_init_profile(struct r
 int sumo_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);
 int evergreen_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);
 extern void evergreen_page_flip(struct radeon_device *rdev, int crtc,
-				u64 crtc_base);
+				u64 crtc_base, bool async);
 extern bool evergreen_page_flip_pending(struct radeon_device *rdev, int crtc);
 extern void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc);
 void evergreen_disable_interrupt_state(struct radeon_device *rdev);
@@ -606,7 +607,7 @@ int cayman_init(struct radeon_device *rd
 void cayman_fini(struct radeon_device *rdev);
 int cayman_suspend(struct radeon_device *rdev);
 int cayman_resume(struct radeon_device *rdev);
-int cayman_asic_reset(struct radeon_device *rdev);
+int cayman_asic_reset(struct radeon_device *rdev, bool hard);
 void cayman_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
 int cayman_vm_init(struct radeon_device *rdev);
 void cayman_vm_fini(struct radeon_device *rdev);
@@ -712,7 +713,7 @@ int si_suspend(struct radeon_device *rde
 int si_resume(struct radeon_device *rdev);
 bool si_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *cp);
 bool si_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *cp);
-int si_asic_reset(struct radeon_device *rdev);
+int si_asic_reset(struct radeon_device *rdev, bool hard);
 void si_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
 int si_irq_set(struct radeon_device *rdev);
 int si_irq_process(struct radeon_device *rdev);
@@ -817,7 +818,7 @@ void cik_fini(struct radeon_device *rdev
 int cik_suspend(struct radeon_device *rdev);
 int cik_resume(struct radeon_device *rdev);
 bool cik_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *cp);
-int cik_asic_reset(struct radeon_device *rdev);
+int cik_asic_reset(struct radeon_device *rdev, bool hard);
 void cik_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
 int cik_ring_test(struct radeon_device *rdev, struct radeon_ring *ring);
 int cik_ib_test(struct radeon_device *rdev, struct radeon_ring *ring);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/radeon/radeon_cs.c linux-libre-4.7-gnu/drivers/gpu/drm/radeon/radeon_cs.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/radeon/radeon_cs.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/radeon/radeon_cs.c	2016-07-24 15:23:50.000000000 -0400
@@ -74,7 +74,6 @@ static void radeon_cs_buckets_get_list(s
 
 static int radeon_cs_parser_relocs(struct radeon_cs_parser *p)
 {
-	struct drm_device *ddev = p->rdev->ddev;
 	struct radeon_cs_chunk *chunk;
 	struct radeon_cs_buckets buckets;
 	unsigned i;
@@ -101,7 +100,7 @@ static int radeon_cs_parser_relocs(struc
 		unsigned priority;
 
 		r = (struct drm_radeon_cs_reloc *)&chunk->kdata[i*4];
-		gobj = drm_gem_object_lookup(ddev, p->filp, r->handle);
+		gobj = drm_gem_object_lookup(p->filp, r->handle);
 		if (gobj == NULL) {
 			DRM_ERROR("gem object lookup failed 0x%x\n",
 				  r->handle);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/radeon/radeon_cursor.c linux-libre-4.7-gnu/drivers/gpu/drm/radeon/radeon_cursor.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/radeon/radeon_cursor.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/radeon/radeon_cursor.c	2016-07-24 15:23:50.000000000 -0400
@@ -274,7 +274,7 @@ int radeon_crtc_cursor_set2(struct drm_c
 		return -EINVAL;
 	}
 
-	obj = drm_gem_object_lookup(crtc->dev, file_priv, handle);
+	obj = drm_gem_object_lookup(file_priv, handle);
 	if (!obj) {
 		DRM_ERROR("Cannot find cursor object %x for crtc %d\n", handle, radeon_crtc->crtc_id);
 		return -ENOENT;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/radeon/radeon_device.c linux-libre-4.7-gnu/drivers/gpu/drm/radeon/radeon_device.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/radeon/radeon_device.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/radeon/radeon_device.c	2016-07-24 15:23:50.000000000 -0400
@@ -630,6 +630,23 @@ void radeon_gtt_location(struct radeon_d
 /*
  * GPU helpers function.
  */
+
+/**
+ * radeon_device_is_virtual - check if we are running is a virtual environment
+ *
+ * Check if the asic has been passed through to a VM (all asics).
+ * Used at driver startup.
+ * Returns true if virtual or false if not.
+ */
+static bool radeon_device_is_virtual(void)
+{
+#ifdef CONFIG_X86
+	return boot_cpu_has(X86_FEATURE_HYPERVISOR);
+#else
+	return false;
+#endif
+}
+
 /**
  * radeon_card_posted - check if the hw has already been initialized
  *
@@ -643,6 +660,10 @@ bool radeon_card_posted(struct radeon_de
 {
 	uint32_t reg;
 
+	/* for pass through, always force asic_init */
+	if (radeon_device_is_virtual())
+		return false;
+
 	/* required for EFI mode on macbook2,1 which uses an r5xx asic */
 	if (efi_enabled(EFI_BOOT) &&
 	    (rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE) &&
@@ -1230,7 +1251,7 @@ static void radeon_switcheroo_set_state(
 		printk(KERN_INFO "radeon: switched off\n");
 		drm_kms_helper_poll_disable(dev);
 		dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
-		radeon_suspend_kms(dev, true, true);
+		radeon_suspend_kms(dev, true, true, false);
 		dev->switch_power_state = DRM_SWITCH_POWER_OFF;
 	}
 }
@@ -1555,7 +1576,8 @@ void radeon_device_fini(struct radeon_de
  * Returns 0 for success or an error on failure.
  * Called at driver suspend.
  */
-int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon)
+int radeon_suspend_kms(struct drm_device *dev, bool suspend,
+		       bool fbcon, bool freeze)
 {
 	struct radeon_device *rdev;
 	struct drm_crtc *crtc;
@@ -1630,7 +1652,10 @@ int radeon_suspend_kms(struct drm_device
 	radeon_agp_suspend(rdev);
 
 	pci_save_state(dev->pdev);
-	if (suspend) {
+	if (freeze && rdev->family >= CHIP_CEDAR) {
+		rdev->asic->asic_reset(rdev, true);
+		pci_restore_state(dev->pdev);
+	} else if (suspend) {
 		/* Shut down the device */
 		pci_disable_device(dev->pdev);
 		pci_set_power_state(dev->pdev, PCI_D3hot);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/radeon/radeon_display.c linux-libre-4.7-gnu/drivers/gpu/drm/radeon/radeon_display.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/radeon/radeon_display.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/radeon/radeon_display.c	2016-07-24 15:23:50.000000000 -0400
@@ -377,7 +377,7 @@ void radeon_crtc_handle_flip(struct rade
 
 	/* wakeup userspace */
 	if (work->event)
-		drm_send_vblank_event(rdev->ddev, crtc_id, work->event);
+		drm_crtc_send_vblank_event(&radeon_crtc->base, work->event);
 
 	spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
 
@@ -490,7 +490,7 @@ static void radeon_flip_work_func(struct
 				 vblank->linedur_ns / 1000, stat, vpos, hpos);
 
 	/* do the flip (mmio) */
-	radeon_page_flip(rdev, radeon_crtc->crtc_id, work->base);
+	radeon_page_flip(rdev, radeon_crtc->crtc_id, work->base, work->async);
 
 	radeon_crtc->flip_status = RADEON_FLIP_SUBMITTED;
 	spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
@@ -525,6 +525,7 @@ static int radeon_crtc_page_flip(struct
 	work->rdev = rdev;
 	work->crtc_id = radeon_crtc->crtc_id;
 	work->event = event;
+	work->async = (page_flip_flags & DRM_MODE_PAGE_FLIP_ASYNC) != 0;
 
 	/* schedule unpin of the old buffer */
 	old_radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
@@ -1367,7 +1368,7 @@ radeon_user_framebuffer_create(struct dr
 	struct radeon_framebuffer *radeon_fb;
 	int ret;
 
-	obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]);
+	obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[0]);
 	if (obj ==  NULL) {
 		dev_err(&dev->pdev->dev, "No GEM object associated to handle 0x%08X, "
 			"can't create framebuffer\n", mode_cmd->handles[0]);
@@ -1630,6 +1631,9 @@ int radeon_modeset_init(struct radeon_de
 
 	rdev->ddev->mode_config.funcs = &radeon_mode_funcs;
 
+	if (radeon_use_pflipirq == 2 && rdev->family >= CHIP_R600)
+		rdev->ddev->mode_config.async_page_flip = true;
+
 	if (ASIC_IS_DCE5(rdev)) {
 		rdev->ddev->mode_config.max_width = 16384;
 		rdev->ddev->mode_config.max_height = 16384;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/radeon/radeon_drv.c linux-libre-4.7-gnu/drivers/gpu/drm/radeon/radeon_drv.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/radeon/radeon_drv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/radeon/radeon_drv.c	2016-07-24 15:23:50.000000000 -0400
@@ -93,9 +93,11 @@
  *   2.41.0 - evergreen/cayman: Add SET_BASE/DRAW_INDIRECT command parsing support
  *   2.42.0 - Add VCE/VUI (Video Usability Information) support
  *   2.43.0 - RADEON_INFO_GPU_RESET_COUNTER
+ *   2.44.0 - SET_APPEND_CNT packet3 support
+ *   2.45.0 - Allow setting shader registers using DMA/COPY packet3 on SI
  */
 #define KMS_DRIVER_MAJOR	2
-#define KMS_DRIVER_MINOR	43
+#define KMS_DRIVER_MINOR	45
 #define KMS_DRIVER_PATCHLEVEL	0
 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
 int radeon_driver_unload_kms(struct drm_device *dev);
@@ -105,7 +107,8 @@ void radeon_driver_postclose_kms(struct
 				 struct drm_file *file_priv);
 void radeon_driver_preclose_kms(struct drm_device *dev,
 				struct drm_file *file_priv);
-int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon);
+int radeon_suspend_kms(struct drm_device *dev, bool suspend,
+		       bool fbcon, bool freeze);
 int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon);
 u32 radeon_get_vblank_counter_kms(struct drm_device *dev, unsigned int pipe);
 int radeon_enable_vblank_kms(struct drm_device *dev, unsigned int pipe);
@@ -196,6 +199,8 @@ int radeon_bapm = -1;
 int radeon_backlight = -1;
 int radeon_auxch = -1;
 int radeon_mst = 0;
+int radeon_uvd = 1;
+int radeon_vce = 1;
 
 MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");
 module_param_named(no_wb, radeon_no_wb, int, 0444);
@@ -287,6 +292,12 @@ module_param_named(auxch, radeon_auxch,
 MODULE_PARM_DESC(mst, "DisplayPort MST experimental support (1 = enable, 0 = disable)");
 module_param_named(mst, radeon_mst, int, 0444);
 
+MODULE_PARM_DESC(uvd, "uvd enable/disable uvd support (1 = enable, 0 = disable)");
+module_param_named(uvd, radeon_uvd, int, 0444);
+
+MODULE_PARM_DESC(vce, "vce enable/disable vce support (1 = enable, 0 = disable)");
+module_param_named(vce, radeon_vce, int, 0444);
+
 static struct pci_device_id pciidlist[] = {
 	radeon_PCI_IDS
 };
@@ -358,7 +369,7 @@ static int radeon_pmops_suspend(struct d
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
 	struct drm_device *drm_dev = pci_get_drvdata(pdev);
-	return radeon_suspend_kms(drm_dev, true, true);
+	return radeon_suspend_kms(drm_dev, true, true, false);
 }
 
 static int radeon_pmops_resume(struct device *dev)
@@ -372,7 +383,7 @@ static int radeon_pmops_freeze(struct de
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
 	struct drm_device *drm_dev = pci_get_drvdata(pdev);
-	return radeon_suspend_kms(drm_dev, false, true);
+	return radeon_suspend_kms(drm_dev, false, true, true);
 }
 
 static int radeon_pmops_thaw(struct device *dev)
@@ -397,7 +408,7 @@ static int radeon_pmops_runtime_suspend(
 	drm_kms_helper_poll_disable(drm_dev);
 	vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_OFF);
 
-	ret = radeon_suspend_kms(drm_dev, false, false);
+	ret = radeon_suspend_kms(drm_dev, false, false, false);
 	pci_save_state(pdev);
 	pci_disable_device(pdev);
 	pci_ignore_hotplug(pdev);
@@ -525,7 +536,7 @@ static struct drm_driver kms_driver = {
 	.irq_uninstall = radeon_driver_irq_uninstall_kms,
 	.irq_handler = radeon_driver_irq_handler_kms,
 	.ioctls = radeon_ioctls_kms,
-	.gem_free_object = radeon_gem_object_free,
+	.gem_free_object_unlocked = radeon_gem_object_free,
 	.gem_open_object = radeon_gem_object_open,
 	.gem_close_object = radeon_gem_object_close,
 	.dumb_create = radeon_mode_dumb_create,
@@ -566,12 +577,10 @@ static struct pci_driver radeon_kms_pci_
 
 static int __init radeon_init(void)
 {
-#ifdef CONFIG_VGA_CONSOLE
 	if (vgacon_text_force() && radeon_modeset == -1) {
 		DRM_INFO("VGACON disable radeon kernel modesetting.\n");
 		radeon_modeset = 0;
 	}
-#endif
 	/* set to modesetting by default if not nomodeset */
 	if (radeon_modeset == -1)
 		radeon_modeset = 1;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/radeon/radeon_gem.c linux-libre-4.7-gnu/drivers/gpu/drm/radeon/radeon_gem.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/radeon/radeon_gem.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/radeon/radeon_gem.c	2016-07-24 15:23:50.000000000 -0400
@@ -382,7 +382,7 @@ int radeon_gem_set_domain_ioctl(struct d
 	down_read(&rdev->exclusive_lock);
 
 	/* just do a BO wait for now */
-	gobj = drm_gem_object_lookup(dev, filp, args->handle);
+	gobj = drm_gem_object_lookup(filp, args->handle);
 	if (gobj == NULL) {
 		up_read(&rdev->exclusive_lock);
 		return -ENOENT;
@@ -404,7 +404,7 @@ int radeon_mode_dumb_mmap(struct drm_fil
 	struct drm_gem_object *gobj;
 	struct radeon_bo *robj;
 
-	gobj = drm_gem_object_lookup(dev, filp, handle);
+	gobj = drm_gem_object_lookup(filp, handle);
 	if (gobj == NULL) {
 		return -ENOENT;
 	}
@@ -435,7 +435,7 @@ int radeon_gem_busy_ioctl(struct drm_dev
 	int r;
 	uint32_t cur_placement = 0;
 
-	gobj = drm_gem_object_lookup(dev, filp, args->handle);
+	gobj = drm_gem_object_lookup(filp, args->handle);
 	if (gobj == NULL) {
 		return -ENOENT;
 	}
@@ -464,7 +464,7 @@ int radeon_gem_wait_idle_ioctl(struct dr
 	uint32_t cur_placement = 0;
 	long ret;
 
-	gobj = drm_gem_object_lookup(dev, filp, args->handle);
+	gobj = drm_gem_object_lookup(filp, args->handle);
 	if (gobj == NULL) {
 		return -ENOENT;
 	}
@@ -495,7 +495,7 @@ int radeon_gem_set_tiling_ioctl(struct d
 	int r = 0;
 
 	DRM_DEBUG("%d \n", args->handle);
-	gobj = drm_gem_object_lookup(dev, filp, args->handle);
+	gobj = drm_gem_object_lookup(filp, args->handle);
 	if (gobj == NULL)
 		return -ENOENT;
 	robj = gem_to_radeon_bo(gobj);
@@ -513,7 +513,7 @@ int radeon_gem_get_tiling_ioctl(struct d
 	int r = 0;
 
 	DRM_DEBUG("\n");
-	gobj = drm_gem_object_lookup(dev, filp, args->handle);
+	gobj = drm_gem_object_lookup(filp, args->handle);
 	if (gobj == NULL)
 		return -ENOENT;
 	rbo = gem_to_radeon_bo(gobj);
@@ -648,7 +648,7 @@ int radeon_gem_va_ioctl(struct drm_devic
 		return -EINVAL;
 	}
 
-	gobj = drm_gem_object_lookup(dev, filp, args->handle);
+	gobj = drm_gem_object_lookup(filp, args->handle);
 	if (gobj == NULL) {
 		args->operation = RADEON_VA_RESULT_ERROR;
 		return -ENOENT;
@@ -703,7 +703,7 @@ int radeon_gem_op_ioctl(struct drm_devic
 	struct radeon_bo *robj;
 	int r;
 
-	gobj = drm_gem_object_lookup(dev, filp, args->handle);
+	gobj = drm_gem_object_lookup(filp, args->handle);
 	if (gobj == NULL) {
 		return -ENOENT;
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/radeon/radeon.h linux-libre-4.7-gnu/drivers/gpu/drm/radeon/radeon.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/radeon/radeon.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/radeon/radeon.h	2016-07-24 15:23:50.000000000 -0400
@@ -113,6 +113,8 @@ extern int radeon_bapm;
 extern int radeon_backlight;
 extern int radeon_auxch;
 extern int radeon_mst;
+extern int radeon_uvd;
+extern int radeon_vce;
 
 /*
  * Copy from radeon_drv.h so we don't have to include both and have conflicting
@@ -744,6 +746,7 @@ struct radeon_flip_work {
 	struct drm_pending_vblank_event *event;
 	struct radeon_bo		*old_rbo;
 	struct fence			*fence;
+	bool				async;
 };
 
 struct r500_irq_stat_regs {
@@ -1671,14 +1674,18 @@ int radeon_pm_get_type_index(struct rade
 /*
  * UVD
  */
-#define RADEON_MAX_UVD_HANDLES	10
-#define RADEON_UVD_STACK_SIZE	(1024*1024)
-#define RADEON_UVD_HEAP_SIZE	(1024*1024)
+#define RADEON_DEFAULT_UVD_HANDLES	10
+#define RADEON_MAX_UVD_HANDLES		30
+#define RADEON_UVD_STACK_SIZE		(200*1024)
+#define RADEON_UVD_HEAP_SIZE		(256*1024)
+#define RADEON_UVD_SESSION_SIZE		(50*1024)
 
 struct radeon_uvd {
+	bool			fw_header_present;
 	struct radeon_bo	*vcpu_bo;
 	void			*cpu_addr;
 	uint64_t		gpu_addr;
+	unsigned		max_handles;
 	atomic_t		handles[RADEON_MAX_UVD_HANDLES];
 	struct drm_file		*filp[RADEON_MAX_UVD_HANDLES];
 	unsigned		img_size[RADEON_MAX_UVD_HANDLES];
@@ -1852,7 +1859,7 @@ struct radeon_asic {
 	int (*resume)(struct radeon_device *rdev);
 	int (*suspend)(struct radeon_device *rdev);
 	void (*vga_set_state)(struct radeon_device *rdev, bool state);
-	int (*asic_reset)(struct radeon_device *rdev);
+	int (*asic_reset)(struct radeon_device *rdev, bool hard);
 	/* Flush the HDP cache via MMIO */
 	void (*mmio_hdp_flush)(struct radeon_device *rdev);
 	/* check if 3D engine is idle */
@@ -1998,7 +2005,7 @@ struct radeon_asic {
 	} dpm;
 	/* pageflipping */
 	struct {
-		void (*page_flip)(struct radeon_device *rdev, int crtc, u64 crtc_base);
+		void (*page_flip)(struct radeon_device *rdev, int crtc, u64 crtc_base, bool async);
 		bool (*page_flip_pending)(struct radeon_device *rdev, int crtc);
 	} pflip;
 };
@@ -2394,7 +2401,6 @@ struct radeon_device {
 	struct radeon_wb		wb;
 	struct radeon_dummy_page	dummy_page;
 	bool				shutdown;
-	bool				suspend;
 	bool				need_dma32;
 	bool				accel_working;
 	bool				fastfb_working; /* IGP feature*/
@@ -2423,6 +2429,7 @@ struct radeon_device {
 	int num_crtc; /* number of crtcs */
 	struct mutex dc_hw_i2c_mutex; /* display controller hw i2c mutex */
 	bool has_uvd;
+	bool has_vce;
 	struct r600_audio audio; /* audio stuff */
 	struct notifier_block acpi_nb;
 	/* only one userspace can use Hyperz features or CMASK at a time */
@@ -2717,7 +2724,7 @@ static inline void radeon_ring_write(str
 #define radeon_suspend(rdev) (rdev)->asic->suspend((rdev))
 #define radeon_cs_parse(rdev, r, p) (rdev)->asic->ring[(r)]->cs_parse((p))
 #define radeon_vga_set_state(rdev, state) (rdev)->asic->vga_set_state((rdev), (state))
-#define radeon_asic_reset(rdev) (rdev)->asic->asic_reset((rdev))
+#define radeon_asic_reset(rdev) (rdev)->asic->asic_reset((rdev), false)
 #define radeon_gart_tlb_flush(rdev) (rdev)->asic->gart.tlb_flush((rdev))
 #define radeon_gart_get_page_entry(a, f) (rdev)->asic->gart.get_page_entry((a), (f))
 #define radeon_gart_set_page(rdev, i, e) (rdev)->asic->gart.set_page((rdev), (i), (e))
@@ -2775,7 +2782,7 @@ static inline void radeon_ring_write(str
 #define radeon_pm_finish(rdev) (rdev)->asic->pm.finish((rdev))
 #define radeon_pm_init_profile(rdev) (rdev)->asic->pm.init_profile((rdev))
 #define radeon_pm_get_dynpm_state(rdev) (rdev)->asic->pm.get_dynpm_state((rdev))
-#define radeon_page_flip(rdev, crtc, base) (rdev)->asic->pflip.page_flip((rdev), (crtc), (base))
+#define radeon_page_flip(rdev, crtc, base, async) (rdev)->asic->pflip.page_flip((rdev), (crtc), (base), (async))
 #define radeon_page_flip_pending(rdev, crtc) (rdev)->asic->pflip.page_flip_pending((rdev), (crtc))
 #define radeon_wait_for_vblank(rdev, crtc) (rdev)->asic->display.wait_for_vblank((rdev), (crtc))
 #define radeon_mc_wait_for_idle(rdev) (rdev)->asic->mc_wait_for_idle((rdev))
@@ -2832,7 +2839,8 @@ extern bool radeon_ttm_tt_is_readonly(st
 extern void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 base);
 extern void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc);
 extern int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon);
-extern int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon);
+extern int radeon_suspend_kms(struct drm_device *dev, bool suspend,
+			      bool fbcon, bool freeze);
 extern void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size);
 extern void radeon_program_register_sequence(struct radeon_device *rdev,
 					     const u32 *registers,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/radeon/radeon_irq_kms.c linux-libre-4.7-gnu/drivers/gpu/drm/radeon/radeon_irq_kms.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/radeon/radeon_irq_kms.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/radeon/radeon_irq_kms.c	2016-07-24 15:23:50.000000000 -0400
@@ -291,7 +291,6 @@ int radeon_irq_kms_init(struct radeon_de
 	if (r) {
 		return r;
 	}
-	rdev->ddev->vblank_disable_allowed = true;
 
 	/* enable msi */
 	rdev->msi_enabled = 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/radeon/radeon_mn.c linux-libre-4.7-gnu/drivers/gpu/drm/radeon/radeon_mn.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/radeon/radeon_mn.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/radeon/radeon_mn.c	2016-07-24 15:23:50.000000000 -0400
@@ -186,7 +186,9 @@ static struct radeon_mn *radeon_mn_get(s
 	struct radeon_mn *rmn;
 	int r;
 
-	down_write(&mm->mmap_sem);
+	if (down_write_killable(&mm->mmap_sem))
+		return ERR_PTR(-EINTR);
+
 	mutex_lock(&rdev->mn_lock);
 
 	hash_for_each_possible(rdev->mn_hash, rmn, node, (unsigned long)mm)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/radeon/radeon_object.c linux-libre-4.7-gnu/drivers/gpu/drm/radeon/radeon_object.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/radeon/radeon_object.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/radeon/radeon_object.c	2016-07-24 15:23:50.000000000 -0400
@@ -832,13 +832,13 @@ int radeon_bo_wait(struct radeon_bo *bo,
 {
 	int r;
 
-	r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, NULL);
+	r = ttm_bo_reserve(&bo->tbo, true, no_wait, NULL);
 	if (unlikely(r != 0))
 		return r;
 	if (mem_type)
 		*mem_type = bo->tbo.mem.mem_type;
 
-	r = ttm_bo_wait(&bo->tbo, true, true, no_wait);
+	r = ttm_bo_wait(&bo->tbo, true, no_wait);
 	ttm_bo_unreserve(&bo->tbo);
 	return r;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/radeon/radeon_object.h linux-libre-4.7-gnu/drivers/gpu/drm/radeon/radeon_object.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/radeon/radeon_object.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/radeon/radeon_object.h	2016-07-24 15:23:50.000000000 -0400
@@ -65,7 +65,7 @@ static inline int radeon_bo_reserve(stru
 {
 	int r;
 
-	r = ttm_bo_reserve(&bo->tbo, !no_intr, false, false, NULL);
+	r = ttm_bo_reserve(&bo->tbo, !no_intr, false, NULL);
 	if (unlikely(r != 0)) {
 		if (r != -ERESTARTSYS)
 			dev_err(bo->rdev->dev, "%p reserve failed\n", bo);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/radeon/radeon_ttm.c linux-libre-4.7-gnu/drivers/gpu/drm/radeon/radeon_ttm.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/radeon/radeon_ttm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/radeon/radeon_ttm.c	2016-07-24 15:23:50.000000000 -0400
@@ -865,6 +865,8 @@ static struct ttm_bo_driver radeon_bo_dr
 	.fault_reserve_notify = &radeon_bo_fault_reserve_notify,
 	.io_mem_reserve = &radeon_ttm_io_mem_reserve,
 	.io_mem_free = &radeon_ttm_io_mem_free,
+	.lru_tail = &ttm_bo_default_lru_tail,
+	.swap_lru_tail = &ttm_bo_default_swap_lru_tail,
 };
 
 int radeon_ttm_init(struct radeon_device *rdev)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/radeon/radeon_uvd.c linux-libre-4.7-gnu/drivers/gpu/drm/radeon/radeon_uvd.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/radeon/radeon_uvd.c	2016-05-15 19:22:30.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/radeon/radeon_uvd.c	2016-07-24 18:19:12.000000000 -0400
@@ -34,6 +34,7 @@
 #include <drm/drm.h>
 
 #include "radeon.h"
+#include "radeon_ucode.h"
 #include "r600d.h"
 
 /* 1 second timeout */
@@ -47,6 +48,7 @@
 #define FIRMWARE_CYPRESS	"/*(DEBLOBBED)*/"
 #define FIRMWARE_SUMO		"/*(DEBLOBBED)*/"
 #define FIRMWARE_TAHITI		"/*(DEBLOBBED)*/"
+#define FIRMWARE_BONAIRE_LEGACY	"/*(DEBLOBBED)*/"
 #define FIRMWARE_BONAIRE	"/*(DEBLOBBED)*/"
 
 /*(DEBLOBBED)*/
@@ -56,7 +58,7 @@ static void radeon_uvd_idle_work_handler
 int radeon_uvd_init(struct radeon_device *rdev)
 {
 	unsigned long bo_size;
-	const char *fw_name;
+	const char *fw_name = NULL, *legacy_fw_name = NULL;
 	int i, r;
 
 	INIT_DELAYED_WORK(&rdev->uvd.idle_work, radeon_uvd_idle_work_handler);
@@ -67,22 +69,22 @@ int radeon_uvd_init(struct radeon_device
 	case CHIP_RV670:
 	case CHIP_RV620:
 	case CHIP_RV635:
-		fw_name = FIRMWARE_R600;
+		legacy_fw_name = FIRMWARE_R600;
 		break;
 
 	case CHIP_RS780:
 	case CHIP_RS880:
-		fw_name = FIRMWARE_RS780;
+		legacy_fw_name = FIRMWARE_RS780;
 		break;
 
 	case CHIP_RV770:
-		fw_name = FIRMWARE_RV770;
+		legacy_fw_name = FIRMWARE_RV770;
 		break;
 
 	case CHIP_RV710:
 	case CHIP_RV730:
 	case CHIP_RV740:
-		fw_name = FIRMWARE_RV710;
+		legacy_fw_name = FIRMWARE_RV710;
 		break;
 
 	case CHIP_CYPRESS:
@@ -90,7 +92,7 @@ int radeon_uvd_init(struct radeon_device
 	case CHIP_JUNIPER:
 	case CHIP_REDWOOD:
 	case CHIP_CEDAR:
-		fw_name = FIRMWARE_CYPRESS;
+		legacy_fw_name = FIRMWARE_CYPRESS;
 		break;
 
 	case CHIP_SUMO:
@@ -100,7 +102,7 @@ int radeon_uvd_init(struct radeon_device
 	case CHIP_BARTS:
 	case CHIP_TURKS:
 	case CHIP_CAICOS:
-		fw_name = FIRMWARE_SUMO;
+		legacy_fw_name = FIRMWARE_SUMO;
 		break;
 
 	case CHIP_TAHITI:
@@ -108,7 +110,7 @@ int radeon_uvd_init(struct radeon_device
 	case CHIP_PITCAIRN:
 	case CHIP_ARUBA:
 	case CHIP_OLAND:
-		fw_name = FIRMWARE_TAHITI;
+		legacy_fw_name = FIRMWARE_TAHITI;
 		break;
 
 	case CHIP_BONAIRE:
@@ -116,6 +118,7 @@ int radeon_uvd_init(struct radeon_device
 	case CHIP_KAVERI:
 	case CHIP_HAWAII:
 	case CHIP_MULLINS:
+		legacy_fw_name = FIRMWARE_BONAIRE_LEGACY;
 		fw_name = FIRMWARE_BONAIRE;
 		break;
 
@@ -123,16 +126,56 @@ int radeon_uvd_init(struct radeon_device
 		return -EINVAL;
 	}
 
-	r = reject_firmware(&rdev->uvd_fw, fw_name, rdev->dev);
-	if (r) {
-		dev_err(rdev->dev, "radeon_uvd: Can't load firmware \"%s\"\n",
-			fw_name);
-		return r;
+	rdev->uvd.fw_header_present = false;
+	rdev->uvd.max_handles = RADEON_DEFAULT_UVD_HANDLES;
+	if (fw_name) {
+		/* Let's try to load the newer firmware first */
+		r = reject_firmware(&rdev->uvd_fw, fw_name, rdev->dev);
+		if (r) {
+			dev_err(rdev->dev, "radeon_uvd: Can't load firmware \"%s\"\n",
+				fw_name);
+		} else {
+			struct common_firmware_header *hdr = (void *)rdev->uvd_fw->data;
+			unsigned version_major, version_minor, family_id;
+
+			r = radeon_ucode_validate(rdev->uvd_fw);
+			if (r)
+				return r;
+
+			rdev->uvd.fw_header_present = true;
+
+			family_id = le32_to_cpu(hdr->ucode_version) & 0xff;
+			version_major = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xff;
+			version_minor = (le32_to_cpu(hdr->ucode_version) >> 8) & 0xff;
+			DRM_INFO("Found UVD firmware Version: %hu.%hu Family ID: %hu\n",
+				 version_major, version_minor, family_id);
+
+			/*
+			 * Limit the number of UVD handles depending on
+			 * microcode major and minor versions.
+			 */
+			if ((version_major >= 0x01) && (version_minor >= 0x37))
+				rdev->uvd.max_handles = RADEON_MAX_UVD_HANDLES;
+		}
+	}
+
+	/*
+	 * In case there is only legacy firmware, or we encounter an error
+	 * while loading the new firmware, we fall back to loading the legacy
+	 * firmware now.
+	 */
+	if (!fw_name || r) {
+		r = reject_firmware(&rdev->uvd_fw, legacy_fw_name, rdev->dev);
+		if (r) {
+			dev_err(rdev->dev, "radeon_uvd: Can't load firmware \"%s\"\n",
+				legacy_fw_name);
+			return r;
+		}
 	}
 
 	bo_size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 8) +
 		  RADEON_UVD_STACK_SIZE + RADEON_UVD_HEAP_SIZE +
-		  RADEON_GPU_PAGE_SIZE;
+		  RADEON_UVD_SESSION_SIZE * rdev->uvd.max_handles;
 	r = radeon_bo_create(rdev, bo_size, PAGE_SIZE, true,
 			     RADEON_GEM_DOMAIN_VRAM, 0, NULL,
 			     NULL, &rdev->uvd.vcpu_bo);
@@ -165,7 +208,7 @@ int radeon_uvd_init(struct radeon_device
 
 	radeon_bo_unreserve(rdev->uvd.vcpu_bo);
 
-	for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
+	for (i = 0; i < rdev->uvd.max_handles; ++i) {
 		atomic_set(&rdev->uvd.handles[i], 0);
 		rdev->uvd.filp[i] = NULL;
 		rdev->uvd.img_size[i] = 0;
@@ -202,7 +245,7 @@ int radeon_uvd_suspend(struct radeon_dev
 	if (rdev->uvd.vcpu_bo == NULL)
 		return 0;
 
-	for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
+	for (i = 0; i < rdev->uvd.max_handles; ++i) {
 		uint32_t handle = atomic_read(&rdev->uvd.handles[i]);
 		if (handle != 0) {
 			struct radeon_fence *fence;
@@ -277,7 +320,7 @@ void radeon_uvd_force_into_uvd_segment(s
 void radeon_uvd_free_handles(struct radeon_device *rdev, struct drm_file *filp)
 {
 	int i, r;
-	for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
+	for (i = 0; i < rdev->uvd.max_handles; ++i) {
 		uint32_t handle = atomic_read(&rdev->uvd.handles[i]);
 		if (handle != 0 && rdev->uvd.filp[i] == filp) {
 			struct radeon_fence *fence;
@@ -462,7 +505,7 @@ static int radeon_uvd_cs_msg(struct rade
 			return r;
 
 		/* try to alloc a new handle */
-		for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
+		for (i = 0; i < p->rdev->uvd.max_handles; ++i) {
 			if (atomic_read(&p->rdev->uvd.handles[i]) == handle) {
 				DRM_ERROR("Handle 0x%x already in use!\n", handle);
 				return -EINVAL;
@@ -488,7 +531,7 @@ static int radeon_uvd_cs_msg(struct rade
 			return r;
 
 		/* validate the handle */
-		for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
+		for (i = 0; i < p->rdev->uvd.max_handles; ++i) {
 			if (atomic_read(&p->rdev->uvd.handles[i]) == handle) {
 				if (p->rdev->uvd.filp[i] != p->filp) {
 					DRM_ERROR("UVD handle collision detected!\n");
@@ -503,7 +546,7 @@ static int radeon_uvd_cs_msg(struct rade
 
 	case 2:
 		/* it's a destroy msg, free the handle */
-		for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i)
+		for (i = 0; i < p->rdev->uvd.max_handles; ++i)
 			atomic_cmpxchg(&p->rdev->uvd.handles[i], handle, 0);
 		radeon_bo_kunmap(bo);
 		return 0;
@@ -802,7 +845,7 @@ static void radeon_uvd_count_handles(str
 	*sd = 0;
 	*hd = 0;
 
-	for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
+	for (i = 0; i < rdev->uvd.max_handles; ++i) {
 		if (!atomic_read(&rdev->uvd.handles[i]))
 			continue;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/radeon/rs600.c linux-libre-4.7-gnu/drivers/gpu/drm/radeon/rs600.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/radeon/rs600.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/radeon/rs600.c	2016-07-24 15:23:50.000000000 -0400
@@ -110,7 +110,7 @@ void avivo_wait_for_vblank(struct radeon
 	}
 }
 
-void rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
+void rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base, bool async)
 {
 	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
 	u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset);
@@ -121,6 +121,8 @@ void rs600_page_flip(struct radeon_devic
 	WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp);
 
 	/* update the scanout addresses */
+	WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset,
+	       async ? AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN : 0);
 	WREG32(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
 	       (u32)crtc_base);
 	WREG32(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
@@ -413,7 +415,8 @@ void rs600_hpd_init(struct radeon_device
 		default:
 			break;
 		}
-		enable |= 1 << radeon_connector->hpd.hpd;
+		if (radeon_connector->hpd.hpd != RADEON_HPD_NONE)
+			enable |= 1 << radeon_connector->hpd.hpd;
 		radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
 	}
 	radeon_irq_kms_enable_hpd(rdev, enable);
@@ -439,12 +442,13 @@ void rs600_hpd_fini(struct radeon_device
 		default:
 			break;
 		}
-		disable |= 1 << radeon_connector->hpd.hpd;
+		if (radeon_connector->hpd.hpd != RADEON_HPD_NONE)
+			disable |= 1 << radeon_connector->hpd.hpd;
 	}
 	radeon_irq_kms_disable_hpd(rdev, disable);
 }
 
-int rs600_asic_reset(struct radeon_device *rdev)
+int rs600_asic_reset(struct radeon_device *rdev, bool hard)
 {
 	struct rv515_mc_save save;
 	u32 status, tmp;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/radeon/rv770.c linux-libre-4.7-gnu/drivers/gpu/drm/radeon/rv770.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/radeon/rv770.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/radeon/rv770.c	2016-07-24 15:23:50.000000000 -0400
@@ -801,7 +801,7 @@ u32 rv770_get_xclk(struct radeon_device
 	return reference_clock;
 }
 
-void rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
+void rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base, bool async)
 {
 	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
 	u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset);
@@ -812,6 +812,8 @@ void rv770_page_flip(struct radeon_devic
 	WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp);
 
 	/* update the scanout addresses */
+	WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset,
+	       async ? AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN : 0);
 	if (radeon_crtc->crtc_id) {
 		WREG32(D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base));
 		WREG32(D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base));
@@ -1681,6 +1683,73 @@ static int rv770_mc_init(struct radeon_d
 	return 0;
 }
 
+static void rv770_uvd_init(struct radeon_device *rdev)
+{
+	int r;
+
+	if (!rdev->has_uvd)
+		return;
+
+	r = radeon_uvd_init(rdev);
+	if (r) {
+		dev_err(rdev->dev, "failed UVD (%d) init.\n", r);
+		/*
+		 * At this point rdev->uvd.vcpu_bo is NULL which trickles down
+		 * to early fails uvd_v2_2_resume() and thus nothing happens
+		 * there. So it is pointless to try to go through that code
+		 * hence why we disable uvd here.
+		 */
+		rdev->has_uvd = 0;
+		return;
+	}
+	rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_obj = NULL;
+	r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX], 4096);
+}
+
+static void rv770_uvd_start(struct radeon_device *rdev)
+{
+	int r;
+
+	if (!rdev->has_uvd)
+		return;
+
+	r = uvd_v2_2_resume(rdev);
+	if (r) {
+		dev_err(rdev->dev, "failed UVD resume (%d).\n", r);
+		goto error;
+	}
+	r = radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_UVD_INDEX);
+	if (r) {
+		dev_err(rdev->dev, "failed initializing UVD fences (%d).\n", r);
+		goto error;
+	}
+	return;
+
+error:
+	rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
+}
+
+static void rv770_uvd_resume(struct radeon_device *rdev)
+{
+	struct radeon_ring *ring;
+	int r;
+
+	if (!rdev->has_uvd || !rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size)
+		return;
+
+	ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
+	r = radeon_ring_init(rdev, ring, ring->ring_size, 0, RADEON_CP_PACKET2);
+	if (r) {
+		dev_err(rdev->dev, "failed initializing UVD ring (%d).\n", r);
+		return;
+	}
+	r = uvd_v1_0_init(rdev);
+	if (r) {
+		dev_err(rdev->dev, "failed initializing UVD (%d).\n", r);
+		return;
+	}
+}
+
 static int rv770_startup(struct radeon_device *rdev)
 {
 	struct radeon_ring *ring;
@@ -1723,16 +1792,7 @@ static int rv770_startup(struct radeon_d
 		return r;
 	}
 
-	r = uvd_v2_2_resume(rdev);
-	if (!r) {
-		r = radeon_fence_driver_start_ring(rdev,
-						   R600_RING_TYPE_UVD_INDEX);
-		if (r)
-			dev_err(rdev->dev, "UVD fences init error (%d).\n", r);
-	}
-
-	if (r)
-		rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
+	rv770_uvd_start(rdev);
 
 	/* Enable IRQ */
 	if (!rdev->irq.installed) {
@@ -1772,16 +1832,7 @@ static int rv770_startup(struct radeon_d
 	if (r)
 		return r;
 
-	ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
-	if (ring->ring_size) {
-		r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
-				     RADEON_CP_PACKET2);
-		if (!r)
-			r = uvd_v1_0_init(rdev);
-
-		if (r)
-			DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
-	}
+	rv770_uvd_resume(rdev);
 
 	r = radeon_ib_pool_init(rdev);
 	if (r) {
@@ -1831,8 +1882,10 @@ int rv770_suspend(struct radeon_device *
 {
 	radeon_pm_suspend(rdev);
 	radeon_audio_fini(rdev);
-	uvd_v1_0_fini(rdev);
-	radeon_uvd_suspend(rdev);
+	if (rdev->has_uvd) {
+		uvd_v1_0_fini(rdev);
+		radeon_uvd_suspend(rdev);
+	}
 	r700_cp_stop(rdev);
 	r600_dma_stop(rdev);
 	r600_irq_suspend(rdev);
@@ -1917,12 +1970,7 @@ int rv770_init(struct radeon_device *rde
 	rdev->ring[R600_RING_TYPE_DMA_INDEX].ring_obj = NULL;
 	r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_DMA_INDEX], 64 * 1024);
 
-	r = radeon_uvd_init(rdev);
-	if (!r) {
-		rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_obj = NULL;
-		r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX],
-			       4096);
-	}
+	rv770_uvd_init(rdev);
 
 	rdev->ih.ring_obj = NULL;
 	r600_ih_ring_init(rdev, 64 * 1024);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/radeon/si.c linux-libre-4.7-gnu/drivers/gpu/drm/radeon/si.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/radeon/si.c	2016-05-15 19:22:20.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/radeon/si.c	2016-07-24 18:19:01.000000000 -0400
@@ -3961,10 +3961,15 @@ static void si_gpu_pci_config_reset(stru
 	}
 }
 
-int si_asic_reset(struct radeon_device *rdev)
+int si_asic_reset(struct radeon_device *rdev, bool hard)
 {
 	u32 reset_mask;
 
+	if (hard) {
+		si_gpu_pci_config_reset(rdev);
+		return 0;
+	}
+
 	reset_mask = si_gpu_check_soft_reset(rdev);
 
 	if (reset_mask)
@@ -4286,6 +4291,10 @@ static bool si_vm_reg_valid(u32 reg)
 	if (reg >= 0x28000)
 		return true;
 
+	/* shader regs are also fine */
+	if (reg >= 0xB000 && reg < 0xC000)
+		return true;
+
 	/* check config regs */
 	switch (reg) {
 	case GRBM_GFX_INDEX:
@@ -6748,6 +6757,159 @@ restart_ih:
 /*
  * startup/shutdown callbacks
  */
+static void si_uvd_init(struct radeon_device *rdev)
+{
+	int r;
+
+	if (!rdev->has_uvd)
+		return;
+
+	r = radeon_uvd_init(rdev);
+	if (r) {
+		dev_err(rdev->dev, "failed UVD (%d) init.\n", r);
+		/*
+		 * At this point rdev->uvd.vcpu_bo is NULL which trickles down
+		 * to early fails uvd_v2_2_resume() and thus nothing happens
+		 * there. So it is pointless to try to go through that code
+		 * hence why we disable uvd here.
+		 */
+		rdev->has_uvd = 0;
+		return;
+	}
+	rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_obj = NULL;
+	r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX], 4096);
+}
+
+static void si_uvd_start(struct radeon_device *rdev)
+{
+	int r;
+
+	if (!rdev->has_uvd)
+		return;
+
+	r = uvd_v2_2_resume(rdev);
+	if (r) {
+		dev_err(rdev->dev, "failed UVD resume (%d).\n", r);
+		goto error;
+	}
+	r = radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_UVD_INDEX);
+	if (r) {
+		dev_err(rdev->dev, "failed initializing UVD fences (%d).\n", r);
+		goto error;
+	}
+	return;
+
+error:
+	rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
+}
+
+static void si_uvd_resume(struct radeon_device *rdev)
+{
+	struct radeon_ring *ring;
+	int r;
+
+	if (!rdev->has_uvd || !rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size)
+		return;
+
+	ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
+	r = radeon_ring_init(rdev, ring, ring->ring_size, 0, RADEON_CP_PACKET2);
+	if (r) {
+		dev_err(rdev->dev, "failed initializing UVD ring (%d).\n", r);
+		return;
+	}
+	r = uvd_v1_0_init(rdev);
+	if (r) {
+		dev_err(rdev->dev, "failed initializing UVD (%d).\n", r);
+		return;
+	}
+}
+
+static void si_vce_init(struct radeon_device *rdev)
+{
+	int r;
+
+	if (!rdev->has_vce)
+		return;
+
+	r = radeon_vce_init(rdev);
+	if (r) {
+		dev_err(rdev->dev, "failed VCE (%d) init.\n", r);
+		/*
+		 * At this point rdev->vce.vcpu_bo is NULL which trickles down
+		 * to early fails si_vce_start() and thus nothing happens
+		 * there. So it is pointless to try to go through that code
+		 * hence why we disable vce here.
+		 */
+		rdev->has_vce = 0;
+		return;
+	}
+	rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_obj = NULL;
+	r600_ring_init(rdev, &rdev->ring[TN_RING_TYPE_VCE1_INDEX], 4096);
+	rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_obj = NULL;
+	r600_ring_init(rdev, &rdev->ring[TN_RING_TYPE_VCE2_INDEX], 4096);
+}
+
+static void si_vce_start(struct radeon_device *rdev)
+{
+	int r;
+
+	if (!rdev->has_vce)
+		return;
+
+	r = radeon_vce_resume(rdev);
+	if (r) {
+		dev_err(rdev->dev, "failed VCE resume (%d).\n", r);
+		goto error;
+	}
+	r = vce_v1_0_resume(rdev);
+	if (r) {
+		dev_err(rdev->dev, "failed VCE resume (%d).\n", r);
+		goto error;
+	}
+	r = radeon_fence_driver_start_ring(rdev, TN_RING_TYPE_VCE1_INDEX);
+	if (r) {
+		dev_err(rdev->dev, "failed initializing VCE1 fences (%d).\n", r);
+		goto error;
+	}
+	r = radeon_fence_driver_start_ring(rdev, TN_RING_TYPE_VCE2_INDEX);
+	if (r) {
+		dev_err(rdev->dev, "failed initializing VCE2 fences (%d).\n", r);
+		goto error;
+	}
+	return;
+
+error:
+	rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size = 0;
+	rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_size = 0;
+}
+
+static void si_vce_resume(struct radeon_device *rdev)
+{
+	struct radeon_ring *ring;
+	int r;
+
+	if (!rdev->has_vce || !rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size)
+		return;
+
+	ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX];
+	r = radeon_ring_init(rdev, ring, ring->ring_size, 0, VCE_CMD_NO_OP);
+	if (r) {
+		dev_err(rdev->dev, "failed initializing VCE1 ring (%d).\n", r);
+		return;
+	}
+	ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
+	r = radeon_ring_init(rdev, ring, ring->ring_size, 0, VCE_CMD_NO_OP);
+	if (r) {
+		dev_err(rdev->dev, "failed initializing VCE1 ring (%d).\n", r);
+		return;
+	}
+	r = vce_v1_0_init(rdev);
+	if (r) {
+		dev_err(rdev->dev, "failed initializing VCE (%d).\n", r);
+		return;
+	}
+}
+
 static int si_startup(struct radeon_device *rdev)
 {
 	struct radeon_ring *ring;
@@ -6826,33 +6988,8 @@ static int si_startup(struct radeon_devi
 		return r;
 	}
 
-	if (rdev->has_uvd) {
-		r = uvd_v2_2_resume(rdev);
-		if (!r) {
-			r = radeon_fence_driver_start_ring(rdev,
-							   R600_RING_TYPE_UVD_INDEX);
-			if (r)
-				dev_err(rdev->dev, "UVD fences init error (%d).\n", r);
-		}
-		if (r)
-			rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;
-	}
-
-	r = radeon_vce_resume(rdev);
-	if (!r) {
-		r = vce_v1_0_resume(rdev);
-		if (!r)
-			r = radeon_fence_driver_start_ring(rdev,
-							   TN_RING_TYPE_VCE1_INDEX);
-		if (!r)
-			r = radeon_fence_driver_start_ring(rdev,
-							   TN_RING_TYPE_VCE2_INDEX);
-	}
-	if (r) {
-		dev_err(rdev->dev, "VCE init error (%d).\n", r);
-		rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size = 0;
-		rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_size = 0;
-	}
+	si_uvd_start(rdev);
+	si_vce_start(rdev);
 
 	/* Enable IRQ */
 	if (!rdev->irq.installed) {
@@ -6910,34 +7047,8 @@ static int si_startup(struct radeon_devi
 	if (r)
 		return r;
 
-	if (rdev->has_uvd) {
-		ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
-		if (ring->ring_size) {
-			r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
-					     RADEON_CP_PACKET2);
-			if (!r)
-				r = uvd_v1_0_init(rdev);
-			if (r)
-				DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
-		}
-	}
-
-	r = -ENOENT;
-
-	ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX];
-	if (ring->ring_size)
-		r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
-				     VCE_CMD_NO_OP);
-
-	ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
-	if (ring->ring_size)
-		r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
-				     VCE_CMD_NO_OP);
-
-	if (!r)
-		r = vce_v1_0_init(rdev);
-	else if (r != -ENOENT)
-		DRM_ERROR("radeon: failed initializing VCE (%d).\n", r);
+	si_uvd_resume(rdev);
+	si_vce_resume(rdev);
 
 	r = radeon_ib_pool_init(rdev);
 	if (r) {
@@ -6997,8 +7108,9 @@ int si_suspend(struct radeon_device *rde
 	if (rdev->has_uvd) {
 		uvd_v1_0_fini(rdev);
 		radeon_uvd_suspend(rdev);
-		radeon_vce_suspend(rdev);
 	}
+	if (rdev->has_vce)
+		radeon_vce_suspend(rdev);
 	si_fini_pg(rdev);
 	si_fini_cg(rdev);
 	si_irq_suspend(rdev);
@@ -7096,25 +7208,8 @@ int si_init(struct radeon_device *rdev)
 	ring->ring_obj = NULL;
 	r600_ring_init(rdev, ring, 64 * 1024);
 
-	if (rdev->has_uvd) {
-		r = radeon_uvd_init(rdev);
-		if (!r) {
-			ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
-			ring->ring_obj = NULL;
-			r600_ring_init(rdev, ring, 4096);
-		}
-	}
-
-	r = radeon_vce_init(rdev);
-	if (!r) {
-		ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX];
-		ring->ring_obj = NULL;
-		r600_ring_init(rdev, ring, 4096);
-
-		ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
-		ring->ring_obj = NULL;
-		r600_ring_init(rdev, ring, 4096);
-	}
+	si_uvd_init(rdev);
+	si_vce_init(rdev);
 
 	rdev->ih.ring_obj = NULL;
 	r600_ih_ring_init(rdev, 64 * 1024);
@@ -7167,8 +7262,9 @@ void si_fini(struct radeon_device *rdev)
 	if (rdev->has_uvd) {
 		uvd_v1_0_fini(rdev);
 		radeon_uvd_fini(rdev);
-		radeon_vce_fini(rdev);
 	}
+	if (rdev->has_vce)
+		radeon_vce_fini(rdev);
 	si_pcie_gart_fini(rdev);
 	r600_vram_scratch_fini(rdev);
 	radeon_gem_fini(rdev);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/radeon/uvd_v1_0.c linux-libre-4.7-gnu/drivers/gpu/drm/radeon/uvd_v1_0.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/radeon/uvd_v1_0.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/radeon/uvd_v1_0.c	2016-07-24 15:23:50.000000000 -0400
@@ -124,12 +124,13 @@ int uvd_v1_0_resume(struct radeon_device
 	WREG32(UVD_VCPU_CACHE_SIZE0, size);
 
 	addr += size;
-	size = RADEON_UVD_STACK_SIZE >> 3;
+	size = RADEON_UVD_HEAP_SIZE >> 3;
 	WREG32(UVD_VCPU_CACHE_OFFSET1, addr);
 	WREG32(UVD_VCPU_CACHE_SIZE1, size);
 
 	addr += size;
-	size = RADEON_UVD_HEAP_SIZE >> 3;
+	size = (RADEON_UVD_STACK_SIZE +
+	       (RADEON_UVD_SESSION_SIZE * rdev->uvd.max_handles)) >> 3;
 	WREG32(UVD_VCPU_CACHE_OFFSET2, addr);
 	WREG32(UVD_VCPU_CACHE_SIZE2, size);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/radeon/uvd_v2_2.c linux-libre-4.7-gnu/drivers/gpu/drm/radeon/uvd_v2_2.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/radeon/uvd_v2_2.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/radeon/uvd_v2_2.c	2016-07-24 15:23:50.000000000 -0400
@@ -116,12 +116,13 @@ int uvd_v2_2_resume(struct radeon_device
 	WREG32(UVD_VCPU_CACHE_SIZE0, size);
 
 	addr += size;
-	size = RADEON_UVD_STACK_SIZE >> 3;
+	size = RADEON_UVD_HEAP_SIZE >> 3;
 	WREG32(UVD_VCPU_CACHE_OFFSET1, addr);
 	WREG32(UVD_VCPU_CACHE_SIZE1, size);
 
 	addr += size;
-	size = RADEON_UVD_HEAP_SIZE >> 3;
+	size = (RADEON_UVD_STACK_SIZE +
+	       (RADEON_UVD_SESSION_SIZE * rdev->uvd.max_handles)) >> 3;
 	WREG32(UVD_VCPU_CACHE_OFFSET2, addr);
 	WREG32(UVD_VCPU_CACHE_SIZE2, size);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/radeon/uvd_v4_2.c linux-libre-4.7-gnu/drivers/gpu/drm/radeon/uvd_v4_2.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/radeon/uvd_v4_2.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/radeon/uvd_v4_2.c	2016-07-24 15:23:50.000000000 -0400
@@ -41,18 +41,25 @@ int uvd_v4_2_resume(struct radeon_device
 	uint32_t size;
 
 	/* programm the VCPU memory controller bits 0-27 */
-	addr = rdev->uvd.gpu_addr >> 3;
+
+	/* skip over the header of the new firmware format */
+	if (rdev->uvd.fw_header_present)
+		addr = (rdev->uvd.gpu_addr + 0x200) >> 3;
+	else
+		addr = rdev->uvd.gpu_addr >> 3;
+
 	size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 4) >> 3;
 	WREG32(UVD_VCPU_CACHE_OFFSET0, addr);
 	WREG32(UVD_VCPU_CACHE_SIZE0, size);
 
 	addr += size;
-	size = RADEON_UVD_STACK_SIZE >> 3;
+	size = RADEON_UVD_HEAP_SIZE >> 3;
 	WREG32(UVD_VCPU_CACHE_OFFSET1, addr);
 	WREG32(UVD_VCPU_CACHE_SIZE1, size);
 
 	addr += size;
-	size = RADEON_UVD_HEAP_SIZE >> 3;
+	size = (RADEON_UVD_STACK_SIZE +
+	       (RADEON_UVD_SESSION_SIZE * rdev->uvd.max_handles)) >> 3;
 	WREG32(UVD_VCPU_CACHE_OFFSET2, addr);
 	WREG32(UVD_VCPU_CACHE_SIZE2, size);
 
@@ -64,5 +71,8 @@ int uvd_v4_2_resume(struct radeon_device
 	addr = (rdev->uvd.gpu_addr >> 32) & 0xFF;
 	WREG32(UVD_LMI_EXT40_ADDR, addr | (0x9 << 16) | (0x1 << 31));
 
+	if (rdev->uvd.fw_header_present)
+		WREG32(UVD_GP_SCRATCH4, rdev->uvd.max_handles);
+
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/rcar-du/Kconfig linux-libre-4.7-gnu/drivers/gpu/drm/rcar-du/Kconfig
--- linux-libre-4.6-gnu/drivers/gpu/drm/rcar-du/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/rcar-du/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -2,7 +2,7 @@ config DRM_RCAR_DU
 	tristate "DRM Support for R-Car Display Unit"
 	depends on DRM && OF
 	depends on ARM || ARM64
-	depends on ARCH_SHMOBILE || COMPILE_TEST
+	depends on ARCH_RENESAS || COMPILE_TEST
 	select DRM_KMS_HELPER
 	select DRM_KMS_CMA_HELPER
 	select DRM_GEM_CMA_HELPER
@@ -27,6 +27,6 @@ config DRM_RCAR_LVDS
 config DRM_RCAR_VSP
 	bool "R-Car DU VSP Compositor Support"
 	depends on DRM_RCAR_DU
-	depends on VIDEO_RENESAS_VSP1
+	depends on VIDEO_RENESAS_VSP1=y || (VIDEO_RENESAS_VSP1 && DRM_RCAR_DU=m)
 	help
 	  Enable support to expose the R-Car VSP Compositor as KMS planes.
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/rcar-du/rcar_du_crtc.c linux-libre-4.7-gnu/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/rcar-du/rcar_du_crtc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/rcar-du/rcar_du_crtc.c	2016-07-24 15:23:50.000000000 -0400
@@ -314,7 +314,7 @@ static void rcar_du_crtc_finish_page_fli
 		return;
 
 	spin_lock_irqsave(&dev->event_lock, flags);
-	drm_send_vblank_event(dev, rcrtc->index, event);
+	drm_crtc_send_vblank_event(&rcrtc->crtc, event);
 	wake_up(&rcrtc->flip_wait);
 	spin_unlock_irqrestore(&dev->event_lock, flags);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/rcar-du/rcar_du_drv.c linux-libre-4.7-gnu/drivers/gpu/drm/rcar-du/rcar_du_drv.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/rcar-du/rcar_du_drv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/rcar-du/rcar_du_drv.c	2016-07-24 15:23:50.000000000 -0400
@@ -278,10 +278,7 @@ static int rcar_du_remove(struct platfor
 	struct rcar_du_device *rcdu = platform_get_drvdata(pdev);
 	struct drm_device *ddev = rcdu->ddev;
 
-	mutex_lock(&ddev->mode_config.mutex);
-	drm_connector_unplug_all(ddev);
-	mutex_unlock(&ddev->mode_config.mutex);
-
+	drm_connector_unregister_all(ddev);
 	drm_dev_unregister(ddev);
 
 	if (rcdu->fbdev)
@@ -300,7 +297,6 @@ static int rcar_du_probe(struct platform
 {
 	struct device_node *np = pdev->dev.of_node;
 	struct rcar_du_device *rcdu;
-	struct drm_connector *connector;
 	struct drm_device *ddev;
 	struct resource *mem;
 	int ret;
@@ -364,14 +360,7 @@ static int rcar_du_probe(struct platform
 	if (ret)
 		goto error;
 
-	mutex_lock(&ddev->mode_config.mutex);
-	drm_for_each_connector(connector, ddev) {
-		ret = drm_connector_register(connector);
-		if (ret < 0)
-			break;
-	}
-	mutex_unlock(&ddev->mode_config.mutex);
-
+	ret = drm_connector_register_all(ddev);
 	if (ret < 0)
 		goto error;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/rcar-du/rcar_du_kms.c linux-libre-4.7-gnu/drivers/gpu/drm/rcar-du/rcar_du_kms.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/rcar-du/rcar_du_kms.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/rcar-du/rcar_du_kms.c	2016-07-24 15:23:50.000000000 -0400
@@ -283,7 +283,8 @@ static void rcar_du_atomic_work(struct w
 }
 
 static int rcar_du_atomic_commit(struct drm_device *dev,
-				 struct drm_atomic_state *state, bool async)
+				 struct drm_atomic_state *state,
+				 bool nonblock)
 {
 	struct rcar_du_device *rcdu = dev->dev_private;
 	struct rcar_du_commit *commit;
@@ -328,7 +329,7 @@ static int rcar_du_atomic_commit(struct
 	/* Swap the state, this is the point of no return. */
 	drm_atomic_helper_swap_state(dev, state);
 
-	if (async)
+	if (nonblock)
 		schedule_work(&commit->work);
 	else
 		rcar_du_atomic_complete(commit);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/rcar-du/rcar_du_plane.c linux-libre-4.7-gnu/drivers/gpu/drm/rcar-du/rcar_du_plane.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/rcar-du/rcar_du_plane.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/rcar-du/rcar_du_plane.c	2016-07-24 15:23:50.000000000 -0400
@@ -635,7 +635,7 @@ rcar_du_plane_atomic_duplicate_state(str
 static void rcar_du_plane_atomic_destroy_state(struct drm_plane *plane,
 					       struct drm_plane_state *state)
 {
-	__drm_atomic_helper_plane_destroy_state(plane, state);
+	__drm_atomic_helper_plane_destroy_state(state);
 	kfree(to_rcar_plane_state(state));
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/rcar-du/rcar_du_vsp.c linux-libre-4.7-gnu/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/rcar-du/rcar_du_vsp.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/rcar-du/rcar_du_vsp.c	2016-07-24 15:23:50.000000000 -0400
@@ -251,7 +251,7 @@ rcar_du_vsp_plane_atomic_duplicate_state
 static void rcar_du_vsp_plane_atomic_destroy_state(struct drm_plane *plane,
 						   struct drm_plane_state *state)
 {
-	__drm_atomic_helper_plane_destroy_state(plane, state);
+	__drm_atomic_helper_plane_destroy_state(state);
 	kfree(to_rcar_vsp_plane_state(state));
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c linux-libre-4.7-gnu/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,390 @@
+/*
+ * Rockchip SoC DP (Display Port) interface driver.
+ *
+ * Copyright (C) Fuzhou Rockchip Electronics Co., Ltd.
+ * Author: Andy Yan <andy.yan@rock-chips.com>
+ *         Yakir Yang <ykk@rock-chips.com>
+ *         Jeff Chen <jeff.chen@rock-chips.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/component.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of_graph.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+#include <linux/clk.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_dp_helper.h>
+#include <drm/drm_of.h>
+#include <drm/drm_panel.h>
+
+#include <video/of_videomode.h>
+#include <video/videomode.h>
+
+#include <drm/bridge/analogix_dp.h>
+
+#include "rockchip_drm_drv.h"
+#include "rockchip_drm_vop.h"
+
+#define to_dp(nm)	container_of(nm, struct rockchip_dp_device, nm)
+
+/* dp grf register offset */
+#define GRF_SOC_CON6                            0x025c
+#define GRF_EDP_LCD_SEL_MASK                    BIT(5)
+#define GRF_EDP_SEL_VOP_LIT                     BIT(5)
+#define GRF_EDP_SEL_VOP_BIG                     0
+
+struct rockchip_dp_device {
+	struct drm_device        *drm_dev;
+	struct device            *dev;
+	struct drm_encoder       encoder;
+	struct drm_display_mode  mode;
+
+	struct clk               *pclk;
+	struct regmap            *grf;
+	struct reset_control     *rst;
+
+	struct analogix_dp_plat_data plat_data;
+};
+
+static int rockchip_dp_pre_init(struct rockchip_dp_device *dp)
+{
+	reset_control_assert(dp->rst);
+	usleep_range(10, 20);
+	reset_control_deassert(dp->rst);
+
+	return 0;
+}
+
+static int rockchip_dp_poweron(struct analogix_dp_plat_data *plat_data)
+{
+	struct rockchip_dp_device *dp = to_dp(plat_data);
+	int ret;
+
+	ret = clk_prepare_enable(dp->pclk);
+	if (ret < 0) {
+		dev_err(dp->dev, "failed to enable pclk %d\n", ret);
+		return ret;
+	}
+
+	ret = rockchip_dp_pre_init(dp);
+	if (ret < 0) {
+		dev_err(dp->dev, "failed to dp pre init %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int rockchip_dp_powerdown(struct analogix_dp_plat_data *plat_data)
+{
+	struct rockchip_dp_device *dp = to_dp(plat_data);
+
+	clk_disable_unprepare(dp->pclk);
+
+	return 0;
+}
+
+static bool
+rockchip_dp_drm_encoder_mode_fixup(struct drm_encoder *encoder,
+				   const struct drm_display_mode *mode,
+				   struct drm_display_mode *adjusted_mode)
+{
+	/* do nothing */
+	return true;
+}
+
+static void rockchip_dp_drm_encoder_mode_set(struct drm_encoder *encoder,
+					     struct drm_display_mode *mode,
+					     struct drm_display_mode *adjusted)
+{
+	/* do nothing */
+}
+
+static void rockchip_dp_drm_encoder_enable(struct drm_encoder *encoder)
+{
+	struct rockchip_dp_device *dp = to_dp(encoder);
+	int ret;
+	u32 val;
+
+	ret = drm_of_encoder_active_endpoint_id(dp->dev->of_node, encoder);
+	if (ret < 0)
+		return;
+
+	if (ret)
+		val = GRF_EDP_SEL_VOP_LIT | (GRF_EDP_LCD_SEL_MASK << 16);
+	else
+		val = GRF_EDP_SEL_VOP_BIG | (GRF_EDP_LCD_SEL_MASK << 16);
+
+	dev_dbg(dp->dev, "vop %s output to dp\n", (ret) ? "LIT" : "BIG");
+
+	ret = regmap_write(dp->grf, GRF_SOC_CON6, val);
+	if (ret != 0) {
+		dev_err(dp->dev, "Could not write to GRF: %d\n", ret);
+		return;
+	}
+}
+
+static void rockchip_dp_drm_encoder_nop(struct drm_encoder *encoder)
+{
+	/* do nothing */
+}
+
+static int
+rockchip_dp_drm_encoder_atomic_check(struct drm_encoder *encoder,
+				      struct drm_crtc_state *crtc_state,
+				      struct drm_connector_state *conn_state)
+{
+	struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
+
+	/*
+	 * FIXME(Yakir): driver should configure the CRTC output video
+	 * mode with the display information which indicated the monitor
+	 * support colorimetry.
+	 *
+	 * But don't know why the CRTC driver seems could only output the
+	 * RGBaaa rightly. For example, if connect the "innolux,n116bge"
+	 * eDP screen, EDID would indicated that screen only accepted the
+	 * 6bpc mode. But if I configure CRTC to RGB666 output, then eDP
+	 * screen would show a blue picture (RGB888 show a green picture).
+	 * But if I configure CTRC to RGBaaa, and eDP driver still keep
+	 * RGB666 input video mode, then screen would works prefect.
+	 */
+	s->output_mode = ROCKCHIP_OUT_MODE_AAAA;
+	s->output_type = DRM_MODE_CONNECTOR_eDP;
+
+	return 0;
+}
+
+static struct drm_encoder_helper_funcs rockchip_dp_encoder_helper_funcs = {
+	.mode_fixup = rockchip_dp_drm_encoder_mode_fixup,
+	.mode_set = rockchip_dp_drm_encoder_mode_set,
+	.enable = rockchip_dp_drm_encoder_enable,
+	.disable = rockchip_dp_drm_encoder_nop,
+	.atomic_check = rockchip_dp_drm_encoder_atomic_check,
+};
+
+static void rockchip_dp_drm_encoder_destroy(struct drm_encoder *encoder)
+{
+	drm_encoder_cleanup(encoder);
+}
+
+static struct drm_encoder_funcs rockchip_dp_encoder_funcs = {
+	.destroy = rockchip_dp_drm_encoder_destroy,
+};
+
+static int rockchip_dp_init(struct rockchip_dp_device *dp)
+{
+	struct device *dev = dp->dev;
+	struct device_node *np = dev->of_node;
+	int ret;
+
+	dp->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
+	if (IS_ERR(dp->grf)) {
+		dev_err(dev, "failed to get rockchip,grf property\n");
+		return PTR_ERR(dp->grf);
+	}
+
+	dp->pclk = devm_clk_get(dev, "pclk");
+	if (IS_ERR(dp->pclk)) {
+		dev_err(dev, "failed to get pclk property\n");
+		return PTR_ERR(dp->pclk);
+	}
+
+	dp->rst = devm_reset_control_get(dev, "dp");
+	if (IS_ERR(dp->rst)) {
+		dev_err(dev, "failed to get dp reset control\n");
+		return PTR_ERR(dp->rst);
+	}
+
+	ret = clk_prepare_enable(dp->pclk);
+	if (ret < 0) {
+		dev_err(dp->dev, "failed to enable pclk %d\n", ret);
+		return ret;
+	}
+
+	ret = rockchip_dp_pre_init(dp);
+	if (ret < 0) {
+		dev_err(dp->dev, "failed to pre init %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int rockchip_dp_drm_create_encoder(struct rockchip_dp_device *dp)
+{
+	struct drm_encoder *encoder = &dp->encoder;
+	struct drm_device *drm_dev = dp->drm_dev;
+	struct device *dev = dp->dev;
+	int ret;
+
+	encoder->possible_crtcs = drm_of_find_possible_crtcs(drm_dev,
+							     dev->of_node);
+	DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs);
+
+	ret = drm_encoder_init(drm_dev, encoder, &rockchip_dp_encoder_funcs,
+			       DRM_MODE_ENCODER_TMDS, NULL);
+	if (ret) {
+		DRM_ERROR("failed to initialize encoder with drm\n");
+		return ret;
+	}
+
+	drm_encoder_helper_add(encoder, &rockchip_dp_encoder_helper_funcs);
+
+	return 0;
+}
+
+static int rockchip_dp_bind(struct device *dev, struct device *master,
+			    void *data)
+{
+	struct rockchip_dp_device *dp = dev_get_drvdata(dev);
+	struct drm_device *drm_dev = data;
+	int ret;
+
+	/*
+	 * Just like the probe function said, we don't need the
+	 * device drvrate anymore, we should leave the charge to
+	 * analogix dp driver, set the device drvdata to NULL.
+	 */
+	dev_set_drvdata(dev, NULL);
+
+	ret = rockchip_dp_init(dp);
+	if (ret < 0)
+		return ret;
+
+	dp->drm_dev = drm_dev;
+
+	ret = rockchip_dp_drm_create_encoder(dp);
+	if (ret) {
+		DRM_ERROR("failed to create drm encoder\n");
+		return ret;
+	}
+
+	dp->plat_data.encoder = &dp->encoder;
+
+	dp->plat_data.dev_type = RK3288_DP;
+	dp->plat_data.power_on = rockchip_dp_poweron;
+	dp->plat_data.power_off = rockchip_dp_powerdown;
+
+	return analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data);
+}
+
+static void rockchip_dp_unbind(struct device *dev, struct device *master,
+			       void *data)
+{
+	return analogix_dp_unbind(dev, master, data);
+}
+
+static const struct component_ops rockchip_dp_component_ops = {
+	.bind = rockchip_dp_bind,
+	.unbind = rockchip_dp_unbind,
+};
+
+static int rockchip_dp_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *panel_node, *port, *endpoint;
+	struct rockchip_dp_device *dp;
+	struct drm_panel *panel;
+
+	port = of_graph_get_port_by_id(dev->of_node, 1);
+	if (!port) {
+		dev_err(dev, "can't find output port\n");
+		return -EINVAL;
+	}
+
+	endpoint = of_get_child_by_name(port, "endpoint");
+	of_node_put(port);
+	if (!endpoint) {
+		dev_err(dev, "no output endpoint found\n");
+		return -EINVAL;
+	}
+
+	panel_node = of_graph_get_remote_port_parent(endpoint);
+	of_node_put(endpoint);
+	if (!panel_node) {
+		dev_err(dev, "no output node found\n");
+		return -EINVAL;
+	}
+
+	panel = of_drm_find_panel(panel_node);
+	if (!panel) {
+		DRM_ERROR("failed to find panel\n");
+		of_node_put(panel_node);
+		return -EPROBE_DEFER;
+	}
+
+	of_node_put(panel_node);
+
+	dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL);
+	if (!dp)
+		return -ENOMEM;
+
+	dp->dev = dev;
+
+	dp->plat_data.panel = panel;
+
+	/*
+	 * We just use the drvdata until driver run into component
+	 * add function, and then we would set drvdata to null, so
+	 * that analogix dp driver could take charge of the drvdata.
+	 */
+	platform_set_drvdata(pdev, dp);
+
+	return component_add(dev, &rockchip_dp_component_ops);
+}
+
+static int rockchip_dp_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &rockchip_dp_component_ops);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int rockchip_dp_suspend(struct device *dev)
+{
+	return analogix_dp_suspend(dev);
+}
+
+static int rockchip_dp_resume(struct device *dev)
+{
+	return analogix_dp_resume(dev);
+}
+#endif
+
+static const struct dev_pm_ops rockchip_dp_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(rockchip_dp_suspend, rockchip_dp_resume)
+};
+
+static const struct of_device_id rockchip_dp_dt_ids[] = {
+	{.compatible = "rockchip,rk3288-dp",},
+	{}
+};
+MODULE_DEVICE_TABLE(of, rockchip_dp_dt_ids);
+
+static struct platform_driver rockchip_dp_driver = {
+	.probe = rockchip_dp_probe,
+	.remove = rockchip_dp_remove,
+	.driver = {
+		   .name = "rockchip-dp",
+		   .owner = THIS_MODULE,
+		   .pm = &rockchip_dp_pm_ops,
+		   .of_match_table = of_match_ptr(rockchip_dp_dt_ids),
+	},
+};
+
+module_platform_driver(rockchip_dp_driver);
+
+MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>");
+MODULE_AUTHOR("Jeff chen <jeff.chen@rock-chips.com>");
+MODULE_DESCRIPTION("Rockchip Specific Analogix-DP Driver Extension");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c linux-libre-4.7-gnu/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c	2016-07-24 15:23:50.000000000 -0400
@@ -201,9 +201,6 @@ static void dw_hdmi_rockchip_encoder_ena
 	u32 val;
 	int mux;
 
-	rockchip_drm_crtc_mode_config(encoder->crtc, DRM_MODE_CONNECTOR_HDMIA,
-				      ROCKCHIP_OUT_MODE_AAAA);
-
 	mux = drm_of_encoder_active_endpoint_id(hdmi->dev->of_node, encoder);
 	if (mux)
 		val = HDMI_SEL_VOP_LIT | (HDMI_SEL_VOP_LIT << 16);
@@ -215,11 +212,25 @@ static void dw_hdmi_rockchip_encoder_ena
 		(mux) ? "LIT" : "BIG");
 }
 
+static int
+dw_hdmi_rockchip_encoder_atomic_check(struct drm_encoder *encoder,
+				      struct drm_crtc_state *crtc_state,
+				      struct drm_connector_state *conn_state)
+{
+	struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
+
+	s->output_mode = ROCKCHIP_OUT_MODE_AAAA;
+	s->output_type = DRM_MODE_CONNECTOR_HDMIA;
+
+	return 0;
+}
+
 static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_funcs = {
 	.mode_fixup = dw_hdmi_rockchip_encoder_mode_fixup,
 	.mode_set   = dw_hdmi_rockchip_encoder_mode_set,
 	.enable     = dw_hdmi_rockchip_encoder_enable,
 	.disable    = dw_hdmi_rockchip_encoder_disable,
+	.atomic_check = dw_hdmi_rockchip_encoder_atomic_check,
 };
 
 static const struct dw_hdmi_plat_data rockchip_hdmi_drv_data = {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/rockchip/dw-mipi-dsi.c linux-libre-4.7-gnu/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/rockchip/dw-mipi-dsi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/rockchip/dw-mipi-dsi.c	2016-07-24 15:23:50.000000000 -0400
@@ -879,7 +879,6 @@ static void dw_mipi_dsi_encoder_commit(s
 {
 	struct dw_mipi_dsi *dsi = encoder_to_dsi(encoder);
 	int mux = drm_of_encoder_active_endpoint_id(dsi->dev->of_node, encoder);
-	u32 interface_pix_fmt;
 	u32 val;
 
 	if (clk_prepare_enable(dsi->pclk)) {
@@ -895,31 +894,41 @@ static void dw_mipi_dsi_encoder_commit(s
 
 	clk_disable_unprepare(dsi->pclk);
 
+	if (mux)
+		val = DSI0_SEL_VOP_LIT | (DSI0_SEL_VOP_LIT << 16);
+	else
+		val = DSI0_SEL_VOP_LIT << 16;
+
+	regmap_write(dsi->grf_regmap, GRF_SOC_CON6, val);
+	dev_dbg(dsi->dev, "vop %s output to dsi0\n", (mux) ? "LIT" : "BIG");
+}
+
+static int
+dw_mipi_dsi_encoder_atomic_check(struct drm_encoder *encoder,
+				 struct drm_crtc_state *crtc_state,
+				 struct drm_connector_state *conn_state)
+{
+	struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
+	struct dw_mipi_dsi *dsi = encoder_to_dsi(encoder);
+
 	switch (dsi->format) {
 	case MIPI_DSI_FMT_RGB888:
-		interface_pix_fmt = ROCKCHIP_OUT_MODE_P888;
+		s->output_mode = ROCKCHIP_OUT_MODE_P888;
 		break;
 	case MIPI_DSI_FMT_RGB666:
-		interface_pix_fmt = ROCKCHIP_OUT_MODE_P666;
+		s->output_mode = ROCKCHIP_OUT_MODE_P666;
 		break;
 	case MIPI_DSI_FMT_RGB565:
-		interface_pix_fmt = ROCKCHIP_OUT_MODE_P565;
+		s->output_mode = ROCKCHIP_OUT_MODE_P565;
 		break;
 	default:
 		WARN_ON(1);
-		return;
+		return -EINVAL;
 	}
 
-	rockchip_drm_crtc_mode_config(encoder->crtc, DRM_MODE_CONNECTOR_DSI,
-				      interface_pix_fmt);
-
-	if (mux)
-		val = DSI0_SEL_VOP_LIT | (DSI0_SEL_VOP_LIT << 16);
-	else
-		val = DSI0_SEL_VOP_LIT << 16;
+	s->output_type = DRM_MODE_CONNECTOR_DSI;
 
-	regmap_write(dsi->grf_regmap, GRF_SOC_CON6, val);
-	dev_dbg(dsi->dev, "vop %s output to dsi0\n", (mux) ? "LIT" : "BIG");
+	return 0;
 }
 
 static struct drm_encoder_helper_funcs
@@ -927,6 +936,7 @@ dw_mipi_dsi_encoder_helper_funcs = {
 	.commit = dw_mipi_dsi_encoder_commit,
 	.mode_set = dw_mipi_dsi_encoder_mode_set,
 	.disable = dw_mipi_dsi_encoder_disable,
+	.atomic_check = dw_mipi_dsi_encoder_atomic_check,
 };
 
 static struct drm_encoder_funcs dw_mipi_dsi_encoder_funcs = {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/rockchip/inno_hdmi.c linux-libre-4.7-gnu/drivers/gpu/drm/rockchip/inno_hdmi.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/rockchip/inno_hdmi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/rockchip/inno_hdmi.c	2016-07-24 15:23:50.000000000 -0400
@@ -500,9 +500,6 @@ static void inno_hdmi_encoder_enable(str
 {
 	struct inno_hdmi *hdmi = to_inno_hdmi(encoder);
 
-	rockchip_drm_crtc_mode_config(encoder->crtc, DRM_MODE_CONNECTOR_HDMIA,
-				      ROCKCHIP_OUT_MODE_P888);
-
 	inno_hdmi_set_pwr_mode(hdmi, NORMAL);
 }
 
@@ -520,11 +517,25 @@ static bool inno_hdmi_encoder_mode_fixup
 	return true;
 }
 
+static int
+inno_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
+			       struct drm_crtc_state *crtc_state,
+			       struct drm_connector_state *conn_state)
+{
+	struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
+
+	s->output_mode = ROCKCHIP_OUT_MODE_P888;
+	s->output_type = DRM_MODE_CONNECTOR_HDMIA;
+
+	return 0;
+}
+
 static struct drm_encoder_helper_funcs inno_hdmi_encoder_helper_funcs = {
 	.enable     = inno_hdmi_encoder_enable,
 	.disable    = inno_hdmi_encoder_disable,
 	.mode_fixup = inno_hdmi_encoder_mode_fixup,
 	.mode_set   = inno_hdmi_encoder_mode_set,
+	.atomic_check = inno_hdmi_encoder_atomic_check,
 };
 
 static struct drm_encoder_funcs inno_hdmi_encoder_funcs = {
@@ -855,8 +866,9 @@ static int inno_hdmi_bind(struct device
 
 	hdmi->ddc = inno_hdmi_i2c_adapter(hdmi);
 	if (IS_ERR(hdmi->ddc)) {
+		ret = PTR_ERR(hdmi->ddc);
 		hdmi->ddc = NULL;
-		return PTR_ERR(hdmi->ddc);
+		return ret;
 	}
 
 	/*
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/rockchip/Kconfig linux-libre-4.7-gnu/drivers/gpu/drm/rockchip/Kconfig
--- linux-libre-4.6-gnu/drivers/gpu/drm/rockchip/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/rockchip/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -16,6 +16,15 @@ config DRM_ROCKCHIP
 	  2D or 3D acceleration; acceleration is performed by other
 	  IP found on the SoC.
 
+config ROCKCHIP_ANALOGIX_DP
+	tristate "Rockchip specific extensions for Analogix DP driver"
+	depends on DRM_ROCKCHIP
+	select DRM_ANALOGIX_DP
+	help
+	  This selects support for Rockchip SoC specific extensions
+	  for the Analogix Core DP driver. If you want to enable DP
+	  on RK3288 based SoC, you should selet this option.
+
 config ROCKCHIP_DW_HDMI
         tristate "Rockchip specific extensions for Synopsys DW HDMI"
         depends on DRM_ROCKCHIP
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/rockchip/Makefile linux-libre-4.7-gnu/drivers/gpu/drm/rockchip/Makefile
--- linux-libre-4.6-gnu/drivers/gpu/drm/rockchip/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/rockchip/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -6,6 +6,7 @@ rockchipdrm-y := rockchip_drm_drv.o rock
 		rockchip_drm_gem.o rockchip_drm_vop.o
 rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
 
+obj-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
 obj-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
 obj-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi.o
 obj-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/rockchip/rockchip_drm_drv.c linux-libre-4.7-gnu/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/rockchip/rockchip_drm_drv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/rockchip/rockchip_drm_drv.c	2016-07-24 15:23:50.000000000 -0400
@@ -36,6 +36,8 @@
 #define DRIVER_MAJOR	1
 #define DRIVER_MINOR	0
 
+static bool is_support_iommu = true;
+
 /*
  * Attach a (component) device to the shared drm dma mapping from master drm
  * device.  This is used by the VOPs to map GEM buffers to a common DMA
@@ -47,6 +49,9 @@ int rockchip_drm_dma_attach_device(struc
 	struct dma_iommu_mapping *mapping = drm_dev->dev->archdata.mapping;
 	int ret;
 
+	if (!is_support_iommu)
+		return 0;
+
 	ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
 	if (ret)
 		return ret;
@@ -59,6 +64,9 @@ int rockchip_drm_dma_attach_device(struc
 void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
 				    struct device *dev)
 {
+	if (!is_support_iommu)
+		return;
+
 	arm_iommu_detach_device(dev);
 }
 
@@ -127,7 +135,7 @@ static void rockchip_drm_crtc_disable_vb
 static int rockchip_drm_load(struct drm_device *drm_dev, unsigned long flags)
 {
 	struct rockchip_drm_private *private;
-	struct dma_iommu_mapping *mapping;
+	struct dma_iommu_mapping *mapping = NULL;
 	struct device *dev = drm_dev->dev;
 	struct drm_connector *connector;
 	int ret;
@@ -152,23 +160,26 @@ static int rockchip_drm_load(struct drm_
 		goto err_config_cleanup;
 	}
 
-	/* TODO(djkurtz): fetch the mapping start/size from somewhere */
-	mapping = arm_iommu_create_mapping(&platform_bus_type, 0x00000000,
-					   SZ_2G);
-	if (IS_ERR(mapping)) {
-		ret = PTR_ERR(mapping);
-		goto err_config_cleanup;
-	}
+	if (is_support_iommu) {
+		/* TODO(djkurtz): fetch the mapping start/size from somewhere */
+		mapping = arm_iommu_create_mapping(&platform_bus_type,
+						   0x00000000,
+						   SZ_2G);
+		if (IS_ERR(mapping)) {
+			ret = PTR_ERR(mapping);
+			goto err_config_cleanup;
+		}
 
-	ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
-	if (ret)
-		goto err_release_mapping;
+		ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
+		if (ret)
+			goto err_release_mapping;
 
-	dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
+		dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
 
-	ret = arm_iommu_attach_device(dev, mapping);
-	if (ret)
-		goto err_release_mapping;
+		ret = arm_iommu_attach_device(dev, mapping);
+		if (ret)
+			goto err_release_mapping;
+	}
 
 	/* Try to bind all sub drivers. */
 	ret = component_bind_all(dev, drm_dev);
@@ -205,19 +216,14 @@ static int rockchip_drm_load(struct drm_
 	if (ret)
 		goto err_kms_helper_poll_fini;
 
-	/*
-	 * with vblank_disable_allowed = true, vblank interrupt will be disabled
-	 * by drm timer once a current process gives up ownership of
-	 * vblank event.(after drm_vblank_put function is called)
-	 */
-	drm_dev->vblank_disable_allowed = true;
-
 	drm_mode_config_reset(drm_dev);
 
 	ret = rockchip_drm_fbdev_init(drm_dev);
 	if (ret)
 		goto err_vblank_cleanup;
 
+	if (is_support_iommu)
+		arm_iommu_release_mapping(mapping);
 	return 0;
 err_vblank_cleanup:
 	drm_vblank_cleanup(drm_dev);
@@ -226,9 +232,11 @@ err_kms_helper_poll_fini:
 err_unbind:
 	component_unbind_all(dev, drm_dev);
 err_detach_device:
-	arm_iommu_detach_device(dev);
+	if (is_support_iommu)
+		arm_iommu_detach_device(dev);
 err_release_mapping:
-	arm_iommu_release_mapping(dev->archdata.mapping);
+	if (is_support_iommu)
+		arm_iommu_release_mapping(mapping);
 err_config_cleanup:
 	drm_mode_config_cleanup(drm_dev);
 	drm_dev->dev_private = NULL;
@@ -243,8 +251,8 @@ static int rockchip_drm_unload(struct dr
 	drm_vblank_cleanup(drm_dev);
 	drm_kms_helper_poll_fini(drm_dev);
 	component_unbind_all(dev, drm_dev);
-	arm_iommu_detach_device(dev);
-	arm_iommu_release_mapping(dev->archdata.mapping);
+	if (is_support_iommu)
+		arm_iommu_detach_device(dev);
 	drm_mode_config_cleanup(drm_dev);
 	drm_dev->dev_private = NULL;
 
@@ -488,6 +496,8 @@ static int rockchip_drm_platform_probe(s
 	 * works as expected.
 	 */
 	for (i = 0;; i++) {
+		struct device_node *iommu;
+
 		port = of_parse_phandle(np, "ports", i);
 		if (!port)
 			break;
@@ -497,6 +507,17 @@ static int rockchip_drm_platform_probe(s
 			continue;
 		}
 
+		iommu = of_parse_phandle(port->parent, "iommus", 0);
+		if (!iommu || !of_device_is_available(iommu->parent)) {
+			dev_dbg(dev, "no iommu attached for %s, using non-iommu buffers\n",
+				port->parent->full_name);
+			/*
+			 * if there is a crtc not support iommu, force set all
+			 * crtc use non-iommu buffer.
+			 */
+			is_support_iommu = false;
+		}
+
 		component_match_add(dev, &match, compare_of, port->parent);
 		of_node_put(port);
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/rockchip/rockchip_drm_drv.h linux-libre-4.7-gnu/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/rockchip/rockchip_drm_drv.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/rockchip/rockchip_drm_drv.h	2016-07-24 15:23:50.000000000 -0400
@@ -50,6 +50,14 @@ struct rockchip_atomic_commit {
 	struct mutex lock;
 };
 
+struct rockchip_crtc_state {
+	struct drm_crtc_state base;
+	int output_type;
+	int output_mode;
+};
+#define to_rockchip_crtc_state(s) \
+		container_of(s, struct rockchip_crtc_state, base)
+
 /*
  * Rockchip drm private structure.
  *
@@ -68,8 +76,6 @@ void rockchip_drm_atomic_work(struct wor
 int rockchip_register_crtc_funcs(struct drm_crtc *crtc,
 				 const struct rockchip_crtc_funcs *crtc_funcs);
 void rockchip_unregister_crtc_funcs(struct drm_crtc *crtc);
-int rockchip_drm_crtc_mode_config(struct drm_crtc *crtc, int connector_type,
-				  int out_mode);
 int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
 				   struct device *dev);
 void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/rockchip/rockchip_drm_fb.c linux-libre-4.7-gnu/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/rockchip/rockchip_drm_fb.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/rockchip/rockchip_drm_fb.c	2016-07-24 15:23:50.000000000 -0400
@@ -123,8 +123,7 @@ rockchip_user_fb_create(struct drm_devic
 		unsigned int height = mode_cmd->height / (i ? vsub : 1);
 		unsigned int min_size;
 
-		obj = drm_gem_object_lookup(dev, file_priv,
-					    mode_cmd->handles[i]);
+		obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[i]);
 		if (!obj) {
 			dev_err(dev->dev, "Failed to lookup GEM object\n");
 			ret = -ENXIO;
@@ -276,7 +275,7 @@ void rockchip_drm_atomic_work(struct wor
 
 int rockchip_drm_atomic_commit(struct drm_device *dev,
 			       struct drm_atomic_state *state,
-			       bool async)
+			       bool nonblock)
 {
 	struct rockchip_drm_private *private = dev->dev_private;
 	struct rockchip_atomic_commit *commit = &private->commit;
@@ -286,7 +285,7 @@ int rockchip_drm_atomic_commit(struct dr
 	if (ret)
 		return ret;
 
-	/* serialize outstanding asynchronous commits */
+	/* serialize outstanding nonblocking commits */
 	mutex_lock(&commit->lock);
 	flush_work(&commit->work);
 
@@ -295,7 +294,7 @@ int rockchip_drm_atomic_commit(struct dr
 	commit->dev = dev;
 	commit->state = state;
 
-	if (async)
+	if (nonblock)
 		schedule_work(&commit->work);
 	else
 		rockchip_atomic_commit_complete(commit);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/rockchip/rockchip_drm_gem.c linux-libre-4.7-gnu/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/rockchip/rockchip_drm_gem.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/rockchip/rockchip_drm_gem.c	2016-07-24 15:23:50.000000000 -0400
@@ -198,7 +198,7 @@ int rockchip_gem_dumb_map_offset(struct
 	struct drm_gem_object *obj;
 	int ret;
 
-	obj = drm_gem_object_lookup(dev, file_priv, handle);
+	obj = drm_gem_object_lookup(file_priv, handle);
 	if (!obj) {
 		DRM_ERROR("failed to lookup gem object.\n");
 		return -EINVAL;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/rockchip/rockchip_drm_vop.c linux-libre-4.7-gnu/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/rockchip/rockchip_drm_vop.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/rockchip/rockchip_drm_vop.c	2016-07-24 15:23:50.000000000 -0400
@@ -310,7 +310,7 @@ static void scl_vop_cal_scl_fac(struct v
 	uint16_t vsu_mode;
 	uint16_t lb_mode;
 	uint32_t val;
-	int vskiplines;
+	int vskiplines = 0;
 
 	if (dst_w > 3840) {
 		DRM_ERROR("Maximum destination width (3840) exceeded\n");
@@ -560,6 +560,22 @@ static void vop_plane_destroy(struct drm
 	drm_plane_cleanup(plane);
 }
 
+static int vop_plane_prepare_fb(struct drm_plane *plane,
+				const struct drm_plane_state *new_state)
+{
+	if (plane->state->fb)
+		drm_framebuffer_reference(plane->state->fb);
+
+	return 0;
+}
+
+static void vop_plane_cleanup_fb(struct drm_plane *plane,
+				 const struct drm_plane_state *old_state)
+{
+	if (old_state->fb)
+		drm_framebuffer_unreference(old_state->fb);
+}
+
 static int vop_plane_atomic_check(struct drm_plane *plane,
 			   struct drm_plane_state *state)
 {
@@ -756,6 +772,8 @@ static void vop_plane_atomic_update(stru
 }
 
 static const struct drm_plane_helper_funcs plane_helper_funcs = {
+	.prepare_fb = vop_plane_prepare_fb,
+	.cleanup_fb = vop_plane_cleanup_fb,
 	.atomic_check = vop_plane_atomic_check,
 	.atomic_update = vop_plane_atomic_update,
 	.atomic_disable = vop_plane_atomic_disable,
@@ -804,7 +822,7 @@ static void vop_atomic_plane_destroy_sta
 {
 	struct vop_plane_state *vop_state = to_vop_plane_state(state);
 
-	__drm_atomic_helper_plane_destroy_state(plane, state);
+	__drm_atomic_helper_plane_destroy_state(state);
 
 	kfree(vop_state);
 }
@@ -818,38 +836,6 @@ static const struct drm_plane_funcs vop_
 	.atomic_destroy_state = vop_atomic_plane_destroy_state,
 };
 
-int rockchip_drm_crtc_mode_config(struct drm_crtc *crtc,
-				  int connector_type,
-				  int out_mode)
-{
-	struct vop *vop = to_vop(crtc);
-
-	if (WARN_ON(!vop->is_enabled))
-		return -EINVAL;
-
-	switch (connector_type) {
-	case DRM_MODE_CONNECTOR_LVDS:
-		VOP_CTRL_SET(vop, rgb_en, 1);
-		break;
-	case DRM_MODE_CONNECTOR_eDP:
-		VOP_CTRL_SET(vop, edp_en, 1);
-		break;
-	case DRM_MODE_CONNECTOR_HDMIA:
-		VOP_CTRL_SET(vop, hdmi_en, 1);
-		break;
-	case DRM_MODE_CONNECTOR_DSI:
-		VOP_CTRL_SET(vop, mipi_en, 1);
-		break;
-	default:
-		DRM_ERROR("unsupport connector_type[%d]\n", connector_type);
-		return -EINVAL;
-	};
-	VOP_CTRL_SET(vop, out_mode, out_mode);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(rockchip_drm_crtc_mode_config);
-
 static int vop_crtc_enable_vblank(struct drm_crtc *crtc)
 {
 	struct vop *vop = to_vop(crtc);
@@ -931,6 +917,7 @@ static bool vop_crtc_mode_fixup(struct d
 static void vop_crtc_enable(struct drm_crtc *crtc)
 {
 	struct vop *vop = to_vop(crtc);
+	struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state);
 	struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
 	u16 hsync_len = adjusted_mode->hsync_end - adjusted_mode->hsync_start;
 	u16 hdisplay = adjusted_mode->hdisplay;
@@ -985,6 +972,23 @@ static void vop_crtc_enable(struct drm_c
 	val |= (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) ? 0 : 1;
 	val |= (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) ? 0 : (1 << 1);
 	VOP_CTRL_SET(vop, pin_pol, val);
+	switch (s->output_type) {
+	case DRM_MODE_CONNECTOR_LVDS:
+		VOP_CTRL_SET(vop, rgb_en, 1);
+		break;
+	case DRM_MODE_CONNECTOR_eDP:
+		VOP_CTRL_SET(vop, edp_en, 1);
+		break;
+	case DRM_MODE_CONNECTOR_HDMIA:
+		VOP_CTRL_SET(vop, hdmi_en, 1);
+		break;
+	case DRM_MODE_CONNECTOR_DSI:
+		VOP_CTRL_SET(vop, mipi_en, 1);
+		break;
+	default:
+		DRM_ERROR("unsupport connector_type[%d]\n", s->output_type);
+	}
+	VOP_CTRL_SET(vop, out_mode, s->output_mode);
 
 	VOP_CTRL_SET(vop, htotal_pw, (htotal << 16) | hsync_len);
 	val = hact_st << 16;
@@ -1044,13 +1048,34 @@ static void vop_crtc_destroy(struct drm_
 	drm_crtc_cleanup(crtc);
 }
 
+static struct drm_crtc_state *vop_crtc_duplicate_state(struct drm_crtc *crtc)
+{
+	struct rockchip_crtc_state *rockchip_state;
+
+	rockchip_state = kzalloc(sizeof(*rockchip_state), GFP_KERNEL);
+	if (!rockchip_state)
+		return NULL;
+
+	__drm_atomic_helper_crtc_duplicate_state(crtc, &rockchip_state->base);
+	return &rockchip_state->base;
+}
+
+static void vop_crtc_destroy_state(struct drm_crtc *crtc,
+				   struct drm_crtc_state *state)
+{
+	struct rockchip_crtc_state *s = to_rockchip_crtc_state(state);
+
+	__drm_atomic_helper_crtc_destroy_state(&s->base);
+	kfree(s);
+}
+
 static const struct drm_crtc_funcs vop_crtc_funcs = {
 	.set_config = drm_atomic_helper_set_config,
 	.page_flip = drm_atomic_helper_page_flip,
 	.destroy = vop_crtc_destroy,
 	.reset = drm_atomic_helper_crtc_reset,
-	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
-	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+	.atomic_duplicate_state = vop_crtc_duplicate_state,
+	.atomic_destroy_state = vop_crtc_destroy_state,
 };
 
 static bool vop_win_pending_is_complete(struct vop_win *vop_win)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/shmobile/shmob_drm_crtc.c linux-libre-4.7-gnu/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/shmobile/shmob_drm_crtc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/shmobile/shmob_drm_crtc.c	2016-07-24 15:23:50.000000000 -0400
@@ -440,7 +440,7 @@ void shmob_drm_crtc_finish_page_flip(str
 	event = scrtc->event;
 	scrtc->event = NULL;
 	if (event) {
-		drm_send_vblank_event(dev, 0, event);
+		drm_crtc_send_vblank_event(&scrtc->crtc, event);
 		drm_vblank_put(dev, 0);
 	}
 	spin_unlock_irqrestore(&dev->event_lock, flags);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/sti/sti_crtc.c linux-libre-4.7-gnu/drivers/gpu/drm/sti/sti_crtc.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/sti/sti_crtc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/sti/sti_crtc.c	2016-07-24 15:23:50.000000000 -0400
@@ -51,15 +51,6 @@ static void sti_crtc_disabling(struct dr
 	mixer->status = STI_MIXER_DISABLING;
 }
 
-static bool sti_crtc_mode_fixup(struct drm_crtc *crtc,
-				const struct drm_display_mode *mode,
-				struct drm_display_mode *adjusted_mode)
-{
-	/* accept the provided drm_display_mode, do not fix it up */
-	drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
-	return true;
-}
-
 static int
 sti_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode)
 {
@@ -230,7 +221,6 @@ static void sti_crtc_atomic_flush(struct
 static const struct drm_crtc_helper_funcs sti_crtc_helper_funcs = {
 	.enable = sti_crtc_enable,
 	.disable = sti_crtc_disabling,
-	.mode_fixup = sti_crtc_mode_fixup,
 	.mode_set = drm_helper_crtc_mode_set,
 	.mode_set_nofb = sti_crtc_mode_set_nofb,
 	.mode_set_base = drm_helper_crtc_mode_set_base,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/sti/sti_cursor.c linux-libre-4.7-gnu/drivers/gpu/drm/sti/sti_cursor.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/sti/sti_cursor.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/sti/sti_cursor.c	2016-07-24 15:23:50.000000000 -0400
@@ -6,6 +6,8 @@
  * License terms:  GNU General Public License (GPL), version 2
  */
 
+#include <linux/seq_file.h>
+
 #include <drm/drm_atomic.h>
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_gem_cma_helper.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/sti/sti_drv.c linux-libre-4.7-gnu/drivers/gpu/drm/sti/sti_drv.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/sti/sti_drv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/sti/sti_drv.c	2016-07-24 15:23:50.000000000 -0400
@@ -202,7 +202,7 @@ static void sti_atomic_work(struct work_
 }
 
 static int sti_atomic_commit(struct drm_device *drm,
-			     struct drm_atomic_state *state, bool async)
+			     struct drm_atomic_state *state, bool nonblock)
 {
 	struct sti_private *private = drm->dev_private;
 	int err;
@@ -211,7 +211,7 @@ static int sti_atomic_commit(struct drm_
 	if (err)
 		return err;
 
-	/* serialize outstanding asynchronous commits */
+	/* serialize outstanding nonblocking commits */
 	mutex_lock(&private->commit.lock);
 	flush_work(&private->commit.work);
 
@@ -223,7 +223,7 @@ static int sti_atomic_commit(struct drm_
 
 	drm_atomic_helper_swap_state(drm, state);
 
-	if (async)
+	if (nonblock)
 		sti_atomic_schedule(private, state);
 	else
 		sti_atomic_complete(private, state);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/sti/sti_gdp.c linux-libre-4.7-gnu/drivers/gpu/drm/sti/sti_gdp.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/sti/sti_gdp.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/sti/sti_gdp.c	2016-07-24 15:23:50.000000000 -0400
@@ -5,6 +5,7 @@
  *          for STMicroelectronics.
  * License terms:  GNU General Public License (GPL), version 2
  */
+#include <linux/seq_file.h>
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_fb_cma_helper.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/sti/sti_hda.c linux-libre-4.7-gnu/drivers/gpu/drm/sti/sti_hda.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/sti/sti_hda.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/sti/sti_hda.c	2016-07-24 15:23:50.000000000 -0400
@@ -8,6 +8,7 @@
 #include <linux/component.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/seq_file.h>
 
 #include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/sti/sti_hqvdp.c linux-libre-4.7-gnu/drivers/gpu/drm/sti/sti_hqvdp.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/sti/sti_hqvdp.c	2016-05-15 19:22:37.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/sti/sti_hqvdp.c	2016-07-24 18:19:18.000000000 -0400
@@ -7,6 +7,7 @@
 #include <linux/component.h>
 #include <linux/firmware.h>
 #include <linux/reset.h>
+#include <linux/seq_file.h>
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_fb_cma_helper.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/sti/sti_mixer.c linux-libre-4.7-gnu/drivers/gpu/drm/sti/sti_mixer.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/sti/sti_mixer.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/sti/sti_mixer.c	2016-07-24 15:23:50.000000000 -0400
@@ -5,6 +5,7 @@
  *          for STMicroelectronics.
  * License terms:  GNU General Public License (GPL), version 2
  */
+#include <linux/seq_file.h>
 
 #include "sti_compositor.h"
 #include "sti_mixer.h"
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/sti/sti_tvout.c linux-libre-4.7-gnu/drivers/gpu/drm/sti/sti_tvout.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/sti/sti_tvout.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/sti/sti_tvout.c	2016-07-24 15:23:50.000000000 -0400
@@ -12,6 +12,7 @@
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/reset.h>
+#include <linux/seq_file.h>
 
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/sti/sti_vid.c linux-libre-4.7-gnu/drivers/gpu/drm/sti/sti_vid.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/sti/sti_vid.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/sti/sti_vid.c	2016-07-24 15:23:50.000000000 -0400
@@ -3,6 +3,7 @@
  * Author: Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics.
  * License terms:  GNU General Public License (GPL), version 2
  */
+#include <linux/seq_file.h>
 
 #include <drm/drmP.h>
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/sti/sti_vtg.c linux-libre-4.7-gnu/drivers/gpu/drm/sti/sti_vtg.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/sti/sti_vtg.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/sti/sti_vtg.c	2016-07-24 15:23:50.000000000 -0400
@@ -437,7 +437,7 @@ static int vtg_probe(struct platform_dev
 			return -EPROBE_DEFER;
 	} else {
 		vtg->irq = platform_get_irq(pdev, 0);
-		if (IS_ERR_VALUE(vtg->irq)) {
+		if (vtg->irq < 0) {
 			DRM_ERROR("Failed to get VTG interrupt\n");
 			return vtg->irq;
 		}
@@ -447,7 +447,7 @@ static int vtg_probe(struct platform_dev
 		ret = devm_request_threaded_irq(dev, vtg->irq, vtg_irq,
 				vtg_irq_thread, IRQF_ONESHOT,
 				dev_name(dev), vtg);
-		if (IS_ERR_VALUE(ret)) {
+		if (ret < 0) {
 			DRM_ERROR("Failed to register VTG interrupt\n");
 			return ret;
 		}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/sun4i/Kconfig linux-libre-4.7-gnu/drivers/gpu/drm/sun4i/Kconfig
--- linux-libre-4.6-gnu/drivers/gpu/drm/sun4i/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/sun4i/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,14 @@
+config DRM_SUN4I
+	tristate "DRM Support for Allwinner A10 Display Engine"
+	depends on DRM && ARM && COMMON_CLK
+	depends on ARCH_SUNXI || COMPILE_TEST
+	select DRM_GEM_CMA_HELPER
+	select DRM_KMS_HELPER
+	select DRM_KMS_CMA_HELPER
+	select DRM_PANEL
+	select REGMAP_MMIO
+	select VIDEOMODE_HELPERS
+	help
+	  Choose this option if you have an Allwinner SoC with a
+	  Display Engine. If M is selected the module will be called
+	  sun4i-drm.
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/sun4i/Makefile linux-libre-4.7-gnu/drivers/gpu/drm/sun4i/Makefile
--- linux-libre-4.6-gnu/drivers/gpu/drm/sun4i/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/sun4i/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,13 @@
+sun4i-drm-y += sun4i_crtc.o
+sun4i-drm-y += sun4i_drv.o
+sun4i-drm-y += sun4i_framebuffer.o
+sun4i-drm-y += sun4i_layer.o
+
+sun4i-tcon-y += sun4i_tcon.o
+sun4i-tcon-y += sun4i_rgb.o
+sun4i-tcon-y += sun4i_dotclock.o
+
+obj-$(CONFIG_DRM_SUN4I)		+= sun4i-drm.o sun4i-tcon.o
+obj-$(CONFIG_DRM_SUN4I)		+= sun4i_backend.o
+
+obj-$(CONFIG_DRM_SUN4I)		+= sun4i_tv.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/sun4i/sun4i_backend.c linux-libre-4.7-gnu/drivers/gpu/drm/sun4i/sun4i_backend.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/sun4i/sun4i_backend.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/sun4i/sun4i_backend.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,364 @@
+/*
+ * Copyright (C) 2015 Free Electrons
+ * Copyright (C) 2015 NextThing Co
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_plane_helper.h>
+
+#include <linux/component.h>
+#include <linux/reset.h>
+
+#include "sun4i_backend.h"
+#include "sun4i_drv.h"
+
+static u32 sunxi_rgb2yuv_coef[12] = {
+	0x00000107, 0x00000204, 0x00000064, 0x00000108,
+	0x00003f69, 0x00003ed6, 0x000001c1, 0x00000808,
+	0x000001c1, 0x00003e88, 0x00003fb8, 0x00000808
+};
+
+void sun4i_backend_apply_color_correction(struct sun4i_backend *backend)
+{
+	int i;
+
+	DRM_DEBUG_DRIVER("Applying RGB to YUV color correction\n");
+
+	/* Set color correction */
+	regmap_write(backend->regs, SUN4I_BACKEND_OCCTL_REG,
+		     SUN4I_BACKEND_OCCTL_ENABLE);
+
+	for (i = 0; i < 12; i++)
+		regmap_write(backend->regs, SUN4I_BACKEND_OCRCOEF_REG(i),
+			     sunxi_rgb2yuv_coef[i]);
+}
+EXPORT_SYMBOL(sun4i_backend_apply_color_correction);
+
+void sun4i_backend_disable_color_correction(struct sun4i_backend *backend)
+{
+	DRM_DEBUG_DRIVER("Disabling color correction\n");
+
+	/* Disable color correction */
+	regmap_update_bits(backend->regs, SUN4I_BACKEND_OCCTL_REG,
+			   SUN4I_BACKEND_OCCTL_ENABLE, 0);
+}
+EXPORT_SYMBOL(sun4i_backend_disable_color_correction);
+
+void sun4i_backend_commit(struct sun4i_backend *backend)
+{
+	DRM_DEBUG_DRIVER("Committing changes\n");
+
+	regmap_write(backend->regs, SUN4I_BACKEND_REGBUFFCTL_REG,
+		     SUN4I_BACKEND_REGBUFFCTL_AUTOLOAD_DIS |
+		     SUN4I_BACKEND_REGBUFFCTL_LOADCTL);
+}
+EXPORT_SYMBOL(sun4i_backend_commit);
+
+void sun4i_backend_layer_enable(struct sun4i_backend *backend,
+				int layer, bool enable)
+{
+	u32 val;
+
+	DRM_DEBUG_DRIVER("Enabling layer %d\n", layer);
+
+	if (enable)
+		val = SUN4I_BACKEND_MODCTL_LAY_EN(layer);
+	else
+		val = 0;
+
+	regmap_update_bits(backend->regs, SUN4I_BACKEND_MODCTL_REG,
+			   SUN4I_BACKEND_MODCTL_LAY_EN(layer), val);
+}
+EXPORT_SYMBOL(sun4i_backend_layer_enable);
+
+static int sun4i_backend_drm_format_to_layer(u32 format, u32 *mode)
+{
+	switch (format) {
+	case DRM_FORMAT_ARGB8888:
+		*mode = SUN4I_BACKEND_LAY_FBFMT_ARGB8888;
+		break;
+
+	case DRM_FORMAT_XRGB8888:
+		*mode = SUN4I_BACKEND_LAY_FBFMT_XRGB8888;
+		break;
+
+	case DRM_FORMAT_RGB888:
+		*mode = SUN4I_BACKEND_LAY_FBFMT_RGB888;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int sun4i_backend_update_layer_coord(struct sun4i_backend *backend,
+				     int layer, struct drm_plane *plane)
+{
+	struct drm_plane_state *state = plane->state;
+	struct drm_framebuffer *fb = state->fb;
+
+	DRM_DEBUG_DRIVER("Updating layer %d\n", layer);
+
+	if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
+		DRM_DEBUG_DRIVER("Primary layer, updating global size W: %u H: %u\n",
+				 state->crtc_w, state->crtc_h);
+		regmap_write(backend->regs, SUN4I_BACKEND_DISSIZE_REG,
+			     SUN4I_BACKEND_DISSIZE(state->crtc_w,
+						   state->crtc_h));
+	}
+
+	/* Set the line width */
+	DRM_DEBUG_DRIVER("Layer line width: %d bits\n", fb->pitches[0] * 8);
+	regmap_write(backend->regs, SUN4I_BACKEND_LAYLINEWIDTH_REG(layer),
+		     fb->pitches[0] * 8);
+
+	/* Set height and width */
+	DRM_DEBUG_DRIVER("Layer size W: %u H: %u\n",
+			 state->crtc_w, state->crtc_h);
+	regmap_write(backend->regs, SUN4I_BACKEND_LAYSIZE_REG(layer),
+		     SUN4I_BACKEND_LAYSIZE(state->crtc_w,
+					   state->crtc_h));
+
+	/* Set base coordinates */
+	DRM_DEBUG_DRIVER("Layer coordinates X: %d Y: %d\n",
+			 state->crtc_x, state->crtc_y);
+	regmap_write(backend->regs, SUN4I_BACKEND_LAYCOOR_REG(layer),
+		     SUN4I_BACKEND_LAYCOOR(state->crtc_x,
+					   state->crtc_y));
+
+	return 0;
+}
+EXPORT_SYMBOL(sun4i_backend_update_layer_coord);
+
+int sun4i_backend_update_layer_formats(struct sun4i_backend *backend,
+				       int layer, struct drm_plane *plane)
+{
+	struct drm_plane_state *state = plane->state;
+	struct drm_framebuffer *fb = state->fb;
+	bool interlaced = false;
+	u32 val;
+	int ret;
+
+	if (plane->state->crtc)
+		interlaced = plane->state->crtc->state->adjusted_mode.flags
+			& DRM_MODE_FLAG_INTERLACE;
+
+	regmap_update_bits(backend->regs, SUN4I_BACKEND_MODCTL_REG,
+			   SUN4I_BACKEND_MODCTL_ITLMOD_EN,
+			   interlaced ? SUN4I_BACKEND_MODCTL_ITLMOD_EN : 0);
+
+	DRM_DEBUG_DRIVER("Switching display backend interlaced mode %s\n",
+			 interlaced ? "on" : "off");
+
+	ret = sun4i_backend_drm_format_to_layer(fb->pixel_format, &val);
+	if (ret) {
+		DRM_DEBUG_DRIVER("Invalid format\n");
+		return val;
+	}
+
+	regmap_update_bits(backend->regs, SUN4I_BACKEND_ATTCTL_REG1(layer),
+			   SUN4I_BACKEND_ATTCTL_REG1_LAY_FBFMT, val);
+
+	return 0;
+}
+EXPORT_SYMBOL(sun4i_backend_update_layer_formats);
+
+int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend,
+				      int layer, struct drm_plane *plane)
+{
+	struct drm_plane_state *state = plane->state;
+	struct drm_framebuffer *fb = state->fb;
+	struct drm_gem_cma_object *gem;
+	u32 lo_paddr, hi_paddr;
+	dma_addr_t paddr;
+	int bpp;
+
+	/* Get the physical address of the buffer in memory */
+	gem = drm_fb_cma_get_gem_obj(fb, 0);
+
+	DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->paddr);
+
+	/* Compute the start of the displayed memory */
+	bpp = drm_format_plane_cpp(fb->pixel_format, 0);
+	paddr = gem->paddr + fb->offsets[0];
+	paddr += (state->src_x >> 16) * bpp;
+	paddr += (state->src_y >> 16) * fb->pitches[0];
+
+	DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
+
+	/* Write the 32 lower bits of the address (in bits) */
+	lo_paddr = paddr << 3;
+	DRM_DEBUG_DRIVER("Setting address lower bits to 0x%x\n", lo_paddr);
+	regmap_write(backend->regs, SUN4I_BACKEND_LAYFB_L32ADD_REG(layer),
+		     lo_paddr);
+
+	/* And the upper bits */
+	hi_paddr = paddr >> 29;
+	DRM_DEBUG_DRIVER("Setting address high bits to 0x%x\n", hi_paddr);
+	regmap_update_bits(backend->regs, SUN4I_BACKEND_LAYFB_H4ADD_REG,
+			   SUN4I_BACKEND_LAYFB_H4ADD_MSK(layer),
+			   SUN4I_BACKEND_LAYFB_H4ADD(layer, hi_paddr));
+
+	return 0;
+}
+EXPORT_SYMBOL(sun4i_backend_update_layer_buffer);
+
+static struct regmap_config sun4i_backend_regmap_config = {
+	.reg_bits	= 32,
+	.val_bits	= 32,
+	.reg_stride	= 4,
+	.max_register	= 0x5800,
+};
+
+static int sun4i_backend_bind(struct device *dev, struct device *master,
+			      void *data)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct drm_device *drm = data;
+	struct sun4i_drv *drv = drm->dev_private;
+	struct sun4i_backend *backend;
+	struct resource *res;
+	void __iomem *regs;
+	int i, ret;
+
+	backend = devm_kzalloc(dev, sizeof(*backend), GFP_KERNEL);
+	if (!backend)
+		return -ENOMEM;
+	dev_set_drvdata(dev, backend);
+	drv->backend = backend;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(regs)) {
+		dev_err(dev, "Couldn't map the backend registers\n");
+		return PTR_ERR(regs);
+	}
+
+	backend->regs = devm_regmap_init_mmio(dev, regs,
+					      &sun4i_backend_regmap_config);
+	if (IS_ERR(backend->regs)) {
+		dev_err(dev, "Couldn't create the backend0 regmap\n");
+		return PTR_ERR(backend->regs);
+	}
+
+	backend->reset = devm_reset_control_get(dev, NULL);
+	if (IS_ERR(backend->reset)) {
+		dev_err(dev, "Couldn't get our reset line\n");
+		return PTR_ERR(backend->reset);
+	}
+
+	ret = reset_control_deassert(backend->reset);
+	if (ret) {
+		dev_err(dev, "Couldn't deassert our reset line\n");
+		return ret;
+	}
+
+	backend->bus_clk = devm_clk_get(dev, "ahb");
+	if (IS_ERR(backend->bus_clk)) {
+		dev_err(dev, "Couldn't get the backend bus clock\n");
+		ret = PTR_ERR(backend->bus_clk);
+		goto err_assert_reset;
+	}
+	clk_prepare_enable(backend->bus_clk);
+
+	backend->mod_clk = devm_clk_get(dev, "mod");
+	if (IS_ERR(backend->mod_clk)) {
+		dev_err(dev, "Couldn't get the backend module clock\n");
+		ret = PTR_ERR(backend->mod_clk);
+		goto err_disable_bus_clk;
+	}
+	clk_prepare_enable(backend->mod_clk);
+
+	backend->ram_clk = devm_clk_get(dev, "ram");
+	if (IS_ERR(backend->ram_clk)) {
+		dev_err(dev, "Couldn't get the backend RAM clock\n");
+		ret = PTR_ERR(backend->ram_clk);
+		goto err_disable_mod_clk;
+	}
+	clk_prepare_enable(backend->ram_clk);
+
+	/* Reset the registers */
+	for (i = 0x800; i < 0x1000; i += 4)
+		regmap_write(backend->regs, i, 0);
+
+	/* Disable registers autoloading */
+	regmap_write(backend->regs, SUN4I_BACKEND_REGBUFFCTL_REG,
+		     SUN4I_BACKEND_REGBUFFCTL_AUTOLOAD_DIS);
+
+	/* Enable the backend */
+	regmap_write(backend->regs, SUN4I_BACKEND_MODCTL_REG,
+		     SUN4I_BACKEND_MODCTL_DEBE_EN |
+		     SUN4I_BACKEND_MODCTL_START_CTL);
+
+	return 0;
+
+err_disable_mod_clk:
+	clk_disable_unprepare(backend->mod_clk);
+err_disable_bus_clk:
+	clk_disable_unprepare(backend->bus_clk);
+err_assert_reset:
+	reset_control_assert(backend->reset);
+	return ret;
+}
+
+static void sun4i_backend_unbind(struct device *dev, struct device *master,
+				 void *data)
+{
+	struct sun4i_backend *backend = dev_get_drvdata(dev);
+
+	clk_disable_unprepare(backend->ram_clk);
+	clk_disable_unprepare(backend->mod_clk);
+	clk_disable_unprepare(backend->bus_clk);
+	reset_control_assert(backend->reset);
+}
+
+static struct component_ops sun4i_backend_ops = {
+	.bind	= sun4i_backend_bind,
+	.unbind	= sun4i_backend_unbind,
+};
+
+static int sun4i_backend_probe(struct platform_device *pdev)
+{
+	return component_add(&pdev->dev, &sun4i_backend_ops);
+}
+
+static int sun4i_backend_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &sun4i_backend_ops);
+
+	return 0;
+}
+
+static const struct of_device_id sun4i_backend_of_table[] = {
+	{ .compatible = "allwinner,sun5i-a13-display-backend" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, sun4i_backend_of_table);
+
+static struct platform_driver sun4i_backend_platform_driver = {
+	.probe		= sun4i_backend_probe,
+	.remove		= sun4i_backend_remove,
+	.driver		= {
+		.name		= "sun4i-backend",
+		.of_match_table	= sun4i_backend_of_table,
+	},
+};
+module_platform_driver(sun4i_backend_platform_driver);
+
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
+MODULE_DESCRIPTION("Allwinner A10 Display Backend Driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/sun4i/sun4i_backend.h linux-libre-4.7-gnu/drivers/gpu/drm/sun4i/sun4i_backend.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/sun4i/sun4i_backend.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/sun4i/sun4i_backend.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2015 Free Electrons
+ * Copyright (C) 2015 NextThing Co
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#ifndef _SUN4I_BACKEND_H_
+#define _SUN4I_BACKEND_H_
+
+#include <linux/clk.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+#define SUN4I_BACKEND_MODCTL_REG		0x800
+#define SUN4I_BACKEND_MODCTL_LINE_SEL			BIT(29)
+#define SUN4I_BACKEND_MODCTL_ITLMOD_EN			BIT(28)
+#define SUN4I_BACKEND_MODCTL_OUT_SEL			GENMASK(22, 20)
+#define SUN4I_BACKEND_MODCTL_OUT_LCD				(0 << 20)
+#define SUN4I_BACKEND_MODCTL_OUT_FE0				(6 << 20)
+#define SUN4I_BACKEND_MODCTL_OUT_FE1				(7 << 20)
+#define SUN4I_BACKEND_MODCTL_HWC_EN			BIT(16)
+#define SUN4I_BACKEND_MODCTL_LAY_EN(l)			BIT(8 + l)
+#define SUN4I_BACKEND_MODCTL_OCSC_EN			BIT(5)
+#define SUN4I_BACKEND_MODCTL_DFLK_EN			BIT(4)
+#define SUN4I_BACKEND_MODCTL_DLP_START_CTL		BIT(2)
+#define SUN4I_BACKEND_MODCTL_START_CTL			BIT(1)
+#define SUN4I_BACKEND_MODCTL_DEBE_EN			BIT(0)
+
+#define SUN4I_BACKEND_BACKCOLOR_REG		0x804
+#define SUN4I_BACKEND_BACKCOLOR(r, g, b)		(((r) << 16) | ((g) << 8) | (b))
+
+#define SUN4I_BACKEND_DISSIZE_REG		0x808
+#define SUN4I_BACKEND_DISSIZE(w, h)			(((((h) - 1) & 0xffff) << 16) | \
+							 (((w) - 1) & 0xffff))
+
+#define SUN4I_BACKEND_LAYSIZE_REG(l)		(0x810 + (0x4 * (l)))
+#define SUN4I_BACKEND_LAYSIZE(w, h)			(((((h) - 1) & 0x1fff) << 16) | \
+							 (((w) - 1) & 0x1fff))
+
+#define SUN4I_BACKEND_LAYCOOR_REG(l)		(0x820 + (0x4 * (l)))
+#define SUN4I_BACKEND_LAYCOOR(x, y)			((((u32)(y) & 0xffff) << 16) | \
+							 ((u32)(x) & 0xffff))
+
+#define SUN4I_BACKEND_LAYLINEWIDTH_REG(l)	(0x840 + (0x4 * (l)))
+
+#define SUN4I_BACKEND_LAYFB_L32ADD_REG(l)	(0x850 + (0x4 * (l)))
+
+#define SUN4I_BACKEND_LAYFB_H4ADD_REG		0x860
+#define SUN4I_BACKEND_LAYFB_H4ADD_MSK(l)		GENMASK(3 + ((l) * 8), 0)
+#define SUN4I_BACKEND_LAYFB_H4ADD(l, val)			((val) << ((l) * 8))
+
+#define SUN4I_BACKEND_REGBUFFCTL_REG		0x870
+#define SUN4I_BACKEND_REGBUFFCTL_AUTOLOAD_DIS		BIT(1)
+#define SUN4I_BACKEND_REGBUFFCTL_LOADCTL		BIT(0)
+
+#define SUN4I_BACKEND_CKMAX_REG			0x880
+#define SUN4I_BACKEND_CKMIN_REG			0x884
+#define SUN4I_BACKEND_CKCFG_REG			0x888
+#define SUN4I_BACKEND_ATTCTL_REG0(l)		(0x890 + (0x4 * (l)))
+#define SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL_MASK	BIT(15)
+#define SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL(x)		((x) << 15)
+#define SUN4I_BACKEND_ATTCTL_REG0_LAY_PRISEL_MASK	GENMASK(11, 10)
+#define SUN4I_BACKEND_ATTCTL_REG0_LAY_PRISEL(x)			((x) << 10)
+
+#define SUN4I_BACKEND_ATTCTL_REG1(l)		(0x8a0 + (0x4 * (l)))
+#define SUN4I_BACKEND_ATTCTL_REG1_LAY_HSCAFCT		GENMASK(15, 14)
+#define SUN4I_BACKEND_ATTCTL_REG1_LAY_WSCAFCT		GENMASK(13, 12)
+#define SUN4I_BACKEND_ATTCTL_REG1_LAY_FBFMT		GENMASK(11, 8)
+#define SUN4I_BACKEND_LAY_FBFMT_1BPP				(0 << 8)
+#define SUN4I_BACKEND_LAY_FBFMT_2BPP				(1 << 8)
+#define SUN4I_BACKEND_LAY_FBFMT_4BPP				(2 << 8)
+#define SUN4I_BACKEND_LAY_FBFMT_8BPP				(3 << 8)
+#define SUN4I_BACKEND_LAY_FBFMT_RGB655				(4 << 8)
+#define SUN4I_BACKEND_LAY_FBFMT_RGB565				(5 << 8)
+#define SUN4I_BACKEND_LAY_FBFMT_RGB556				(6 << 8)
+#define SUN4I_BACKEND_LAY_FBFMT_ARGB1555			(7 << 8)
+#define SUN4I_BACKEND_LAY_FBFMT_RGBA5551			(8 << 8)
+#define SUN4I_BACKEND_LAY_FBFMT_XRGB8888			(9 << 8)
+#define SUN4I_BACKEND_LAY_FBFMT_ARGB8888			(10 << 8)
+#define SUN4I_BACKEND_LAY_FBFMT_RGB888				(11 << 8)
+#define SUN4I_BACKEND_LAY_FBFMT_ARGB4444			(12 << 8)
+#define SUN4I_BACKEND_LAY_FBFMT_RGBA4444			(13 << 8)
+
+#define SUN4I_BACKEND_DLCDPCTL_REG		0x8b0
+#define SUN4I_BACKEND_DLCDPFRMBUF_ADDRCTL_REG	0x8b4
+#define SUN4I_BACKEND_DLCDPCOOR_REG0		0x8b8
+#define SUN4I_BACKEND_DLCDPCOOR_REG1		0x8bc
+
+#define SUN4I_BACKEND_INT_EN_REG		0x8c0
+#define SUN4I_BACKEND_INT_FLAG_REG		0x8c4
+#define SUN4I_BACKEND_REG_LOAD_FINISHED			BIT(1)
+
+#define SUN4I_BACKEND_HWCCTL_REG		0x8d8
+#define SUN4I_BACKEND_HWCFBCTL_REG		0x8e0
+#define SUN4I_BACKEND_WBCTL_REG			0x8f0
+#define SUN4I_BACKEND_WBADD_REG			0x8f4
+#define SUN4I_BACKEND_WBLINEWIDTH_REG		0x8f8
+#define SUN4I_BACKEND_SPREN_REG			0x900
+#define SUN4I_BACKEND_SPRFMTCTL_REG		0x908
+#define SUN4I_BACKEND_SPRALPHACTL_REG		0x90c
+#define SUN4I_BACKEND_IYUVCTL_REG		0x920
+#define SUN4I_BACKEND_IYUVADD_REG(c)		(0x930 + (0x4 * (c)))
+#define SUN4I_BACKEND_IYUVLINEWITDTH_REG(c)	(0x940 + (0x4 * (c)))
+#define SUN4I_BACKEND_YGCOEF_REG(c)		(0x950 + (0x4 * (c)))
+#define SUN4I_BACKEND_YGCONS_REG		0x95c
+#define SUN4I_BACKEND_URCOEF_REG(c)		(0x960 + (0x4 * (c)))
+#define SUN4I_BACKEND_URCONS_REG		0x96c
+#define SUN4I_BACKEND_VBCOEF_REG(c)		(0x970 + (0x4 * (c)))
+#define SUN4I_BACKEND_VBCONS_REG		0x97c
+#define SUN4I_BACKEND_KSCTL_REG			0x980
+#define SUN4I_BACKEND_KSBKCOLOR_REG		0x984
+#define SUN4I_BACKEND_KSFSTLINEWIDTH_REG	0x988
+#define SUN4I_BACKEND_KSVSCAFCT_REG		0x98c
+#define SUN4I_BACKEND_KSHSCACOEF_REG(x)		(0x9a0 + (0x4 * (x)))
+#define SUN4I_BACKEND_OCCTL_REG			0x9c0
+#define SUN4I_BACKEND_OCCTL_ENABLE			BIT(0)
+
+#define SUN4I_BACKEND_OCRCOEF_REG(x)		(0x9d0 + (0x4 * (x)))
+#define SUN4I_BACKEND_OCRCONS_REG		0x9dc
+#define SUN4I_BACKEND_OCGCOEF_REG(x)		(0x9e0 + (0x4 * (x)))
+#define SUN4I_BACKEND_OCGCONS_REG		0x9ec
+#define SUN4I_BACKEND_OCBCOEF_REG(x)		(0x9f0 + (0x4 * (x)))
+#define SUN4I_BACKEND_OCBCONS_REG		0x9fc
+#define SUN4I_BACKEND_SPRCOORCTL_REG(s)		(0xa00 + (0x4 * (s)))
+#define SUN4I_BACKEND_SPRATTCTL_REG(s)		(0xb00 + (0x4 * (s)))
+#define SUN4I_BACKEND_SPRADD_REG(s)		(0xc00 + (0x4 * (s)))
+#define SUN4I_BACKEND_SPRLINEWIDTH_REG(s)	(0xd00 + (0x4 * (s)))
+
+#define SUN4I_BACKEND_SPRPALTAB_OFF		0x4000
+#define SUN4I_BACKEND_GAMMATAB_OFF		0x4400
+#define SUN4I_BACKEND_HWCPATTERN_OFF		0x4800
+#define SUN4I_BACKEND_HWCCOLORTAB_OFF		0x4c00
+#define SUN4I_BACKEND_PIPE_OFF(p)		(0x5000 + (0x400 * (p)))
+
+struct sun4i_backend {
+	struct regmap		*regs;
+
+	struct reset_control	*reset;
+
+	struct clk		*bus_clk;
+	struct clk		*mod_clk;
+	struct clk		*ram_clk;
+};
+
+void sun4i_backend_apply_color_correction(struct sun4i_backend *backend);
+void sun4i_backend_disable_color_correction(struct sun4i_backend *backend);
+
+void sun4i_backend_commit(struct sun4i_backend *backend);
+
+void sun4i_backend_layer_enable(struct sun4i_backend *backend,
+				int layer, bool enable);
+int sun4i_backend_update_layer_coord(struct sun4i_backend *backend,
+				     int layer, struct drm_plane *plane);
+int sun4i_backend_update_layer_formats(struct sun4i_backend *backend,
+				       int layer, struct drm_plane *plane);
+int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend,
+				      int layer, struct drm_plane *plane);
+
+#endif /* _SUN4I_BACKEND_H_ */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/sun4i/sun4i_crtc.c linux-libre-4.7-gnu/drivers/gpu/drm/sun4i/sun4i_crtc.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/sun4i/sun4i_crtc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/sun4i/sun4i_crtc.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2015 Free Electrons
+ * Copyright (C) 2015 NextThing Co
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_modes.h>
+
+#include <linux/clk-provider.h>
+#include <linux/ioport.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/regmap.h>
+
+#include <video/videomode.h>
+
+#include "sun4i_backend.h"
+#include "sun4i_crtc.h"
+#include "sun4i_drv.h"
+#include "sun4i_tcon.h"
+
+static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
+				    struct drm_crtc_state *old_state)
+{
+	struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	unsigned long flags;
+
+	if (crtc->state->event) {
+		WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+
+		spin_lock_irqsave(&dev->event_lock, flags);
+		scrtc->event = crtc->state->event;
+		spin_unlock_irqrestore(&dev->event_lock, flags);
+		crtc->state->event = NULL;
+	 }
+}
+
+static void sun4i_crtc_atomic_flush(struct drm_crtc *crtc,
+				    struct drm_crtc_state *old_state)
+{
+	struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
+	struct sun4i_drv *drv = scrtc->drv;
+
+	DRM_DEBUG_DRIVER("Committing plane changes\n");
+
+	sun4i_backend_commit(drv->backend);
+}
+
+static void sun4i_crtc_disable(struct drm_crtc *crtc)
+{
+	struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
+	struct sun4i_drv *drv = scrtc->drv;
+
+	DRM_DEBUG_DRIVER("Disabling the CRTC\n");
+
+	sun4i_tcon_disable(drv->tcon);
+
+	if (crtc->state->event && !crtc->state->active) {
+		spin_lock_irq(&crtc->dev->event_lock);
+		drm_crtc_send_vblank_event(crtc, crtc->state->event);
+		spin_unlock_irq(&crtc->dev->event_lock);
+
+		crtc->state->event = NULL;
+	}
+}
+
+static void sun4i_crtc_enable(struct drm_crtc *crtc)
+{
+	struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
+	struct sun4i_drv *drv = scrtc->drv;
+
+	DRM_DEBUG_DRIVER("Enabling the CRTC\n");
+
+	sun4i_tcon_enable(drv->tcon);
+}
+
+static const struct drm_crtc_helper_funcs sun4i_crtc_helper_funcs = {
+	.atomic_begin	= sun4i_crtc_atomic_begin,
+	.atomic_flush	= sun4i_crtc_atomic_flush,
+	.disable	= sun4i_crtc_disable,
+	.enable		= sun4i_crtc_enable,
+};
+
+static const struct drm_crtc_funcs sun4i_crtc_funcs = {
+	.atomic_destroy_state	= drm_atomic_helper_crtc_destroy_state,
+	.atomic_duplicate_state	= drm_atomic_helper_crtc_duplicate_state,
+	.destroy		= drm_crtc_cleanup,
+	.page_flip		= drm_atomic_helper_page_flip,
+	.reset			= drm_atomic_helper_crtc_reset,
+	.set_config		= drm_atomic_helper_set_config,
+};
+
+struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm)
+{
+	struct sun4i_drv *drv = drm->dev_private;
+	struct sun4i_crtc *scrtc;
+	int ret;
+
+	scrtc = devm_kzalloc(drm->dev, sizeof(*scrtc), GFP_KERNEL);
+	if (!scrtc)
+		return NULL;
+	scrtc->drv = drv;
+
+	ret = drm_crtc_init_with_planes(drm, &scrtc->crtc,
+					drv->primary,
+					NULL,
+					&sun4i_crtc_funcs,
+					NULL);
+	if (ret) {
+		dev_err(drm->dev, "Couldn't init DRM CRTC\n");
+		return NULL;
+	}
+
+	drm_crtc_helper_add(&scrtc->crtc, &sun4i_crtc_helper_funcs);
+
+	return scrtc;
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/sun4i/sun4i_crtc.h linux-libre-4.7-gnu/drivers/gpu/drm/sun4i/sun4i_crtc.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/sun4i/sun4i_crtc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/sun4i/sun4i_crtc.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2015 Free Electrons
+ * Copyright (C) 2015 NextThing Co
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#ifndef _SUN4I_CRTC_H_
+#define _SUN4I_CRTC_H_
+
+struct sun4i_crtc {
+	struct drm_crtc			crtc;
+	struct drm_pending_vblank_event	*event;
+
+	struct sun4i_drv		*drv;
+};
+
+static inline struct sun4i_crtc *drm_crtc_to_sun4i_crtc(struct drm_crtc *crtc)
+{
+	return container_of(crtc, struct sun4i_crtc, crtc);
+}
+
+struct sun4i_crtc *sun4i_crtc_init(struct drm_device *drm);
+
+#endif /* _SUN4I_CRTC_H_ */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/sun4i/sun4i_dotclock.c linux-libre-4.7-gnu/drivers/gpu/drm/sun4i/sun4i_dotclock.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/sun4i/sun4i_dotclock.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/sun4i/sun4i_dotclock.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2016 Free Electrons
+ * Copyright (C) 2016 NextThing Co
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+
+#include "sun4i_tcon.h"
+
+struct sun4i_dclk {
+	struct clk_hw	hw;
+	struct regmap	*regmap;
+};
+
+static inline struct sun4i_dclk *hw_to_dclk(struct clk_hw *hw)
+{
+	return container_of(hw, struct sun4i_dclk, hw);
+}
+
+static void sun4i_dclk_disable(struct clk_hw *hw)
+{
+	struct sun4i_dclk *dclk = hw_to_dclk(hw);
+
+	regmap_update_bits(dclk->regmap, SUN4I_TCON0_DCLK_REG,
+			   BIT(SUN4I_TCON0_DCLK_GATE_BIT), 0);
+}
+
+static int sun4i_dclk_enable(struct clk_hw *hw)
+{
+	struct sun4i_dclk *dclk = hw_to_dclk(hw);
+
+	return regmap_update_bits(dclk->regmap, SUN4I_TCON0_DCLK_REG,
+				  BIT(SUN4I_TCON0_DCLK_GATE_BIT),
+				  BIT(SUN4I_TCON0_DCLK_GATE_BIT));
+}
+
+static int sun4i_dclk_is_enabled(struct clk_hw *hw)
+{
+	struct sun4i_dclk *dclk = hw_to_dclk(hw);
+	u32 val;
+
+	regmap_read(dclk->regmap, SUN4I_TCON0_DCLK_REG, &val);
+
+	return val & BIT(SUN4I_TCON0_DCLK_GATE_BIT);
+}
+
+static unsigned long sun4i_dclk_recalc_rate(struct clk_hw *hw,
+					    unsigned long parent_rate)
+{
+	struct sun4i_dclk *dclk = hw_to_dclk(hw);
+	u32 val;
+
+	regmap_read(dclk->regmap, SUN4I_TCON0_DCLK_REG, &val);
+
+	val >>= SUN4I_TCON0_DCLK_DIV_SHIFT;
+	val &= SUN4I_TCON0_DCLK_DIV_WIDTH;
+
+	if (!val)
+		val = 1;
+
+	return parent_rate / val;
+}
+
+static long sun4i_dclk_round_rate(struct clk_hw *hw, unsigned long rate,
+				  unsigned long *parent_rate)
+{
+	unsigned long best_parent = 0;
+	u8 best_div = 1;
+	int i;
+
+	for (i = 6; i < 127; i++) {
+		unsigned long ideal = rate * i;
+		unsigned long rounded;
+
+		rounded = clk_hw_round_rate(clk_hw_get_parent(hw),
+					    ideal);
+
+		if (rounded == ideal) {
+			best_parent = rounded;
+			best_div = i;
+			goto out;
+		}
+
+		if ((rounded < ideal) && (rounded > best_parent)) {
+			best_parent = rounded;
+			best_div = i;
+		}
+	}
+
+out:
+	*parent_rate = best_parent;
+
+	return best_parent / best_div;
+}
+
+static int sun4i_dclk_set_rate(struct clk_hw *hw, unsigned long rate,
+			       unsigned long parent_rate)
+{
+	struct sun4i_dclk *dclk = hw_to_dclk(hw);
+	u8 div = parent_rate / rate;
+
+	return regmap_update_bits(dclk->regmap, SUN4I_TCON0_DCLK_REG,
+				  GENMASK(6, 0), div);
+}
+
+static int sun4i_dclk_get_phase(struct clk_hw *hw)
+{
+	struct sun4i_dclk *dclk = hw_to_dclk(hw);
+	u32 val;
+
+	regmap_read(dclk->regmap, SUN4I_TCON0_IO_POL_REG, &val);
+
+	val >>= 28;
+	val &= 3;
+
+	return val * 120;
+}
+
+static int sun4i_dclk_set_phase(struct clk_hw *hw, int degrees)
+{
+	struct sun4i_dclk *dclk = hw_to_dclk(hw);
+
+	regmap_update_bits(dclk->regmap, SUN4I_TCON0_IO_POL_REG,
+			   GENMASK(29, 28),
+			   degrees / 120);
+
+	return 0;
+}
+
+static const struct clk_ops sun4i_dclk_ops = {
+	.disable	= sun4i_dclk_disable,
+	.enable		= sun4i_dclk_enable,
+	.is_enabled	= sun4i_dclk_is_enabled,
+
+	.recalc_rate	= sun4i_dclk_recalc_rate,
+	.round_rate	= sun4i_dclk_round_rate,
+	.set_rate	= sun4i_dclk_set_rate,
+
+	.get_phase	= sun4i_dclk_get_phase,
+	.set_phase	= sun4i_dclk_set_phase,
+};
+
+int sun4i_dclk_create(struct device *dev, struct sun4i_tcon *tcon)
+{
+	const char *clk_name, *parent_name;
+	struct clk_init_data init;
+	struct sun4i_dclk *dclk;
+	int ret;
+
+	parent_name = __clk_get_name(tcon->sclk0);
+	ret = of_property_read_string_index(dev->of_node,
+					    "clock-output-names", 0,
+					    &clk_name);
+	if (ret)
+		return ret;
+
+	dclk = devm_kzalloc(dev, sizeof(*dclk), GFP_KERNEL);
+	if (!dclk)
+		return -ENOMEM;
+
+	init.name = clk_name;
+	init.ops = &sun4i_dclk_ops;
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+	init.flags = CLK_SET_RATE_PARENT;
+
+	dclk->regmap = tcon->regs;
+	dclk->hw.init = &init;
+
+	tcon->dclk = clk_register(dev, &dclk->hw);
+	if (IS_ERR(tcon->dclk))
+		return PTR_ERR(tcon->dclk);
+
+	return 0;
+}
+EXPORT_SYMBOL(sun4i_dclk_create);
+
+int sun4i_dclk_free(struct sun4i_tcon *tcon)
+{
+	clk_unregister(tcon->dclk);
+	return 0;
+}
+EXPORT_SYMBOL(sun4i_dclk_free);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/sun4i/sun4i_dotclock.h linux-libre-4.7-gnu/drivers/gpu/drm/sun4i/sun4i_dotclock.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/sun4i/sun4i_dotclock.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/sun4i/sun4i_dotclock.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2015 Free Electrons
+ * Copyright (C) 2015 NextThing Co
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#ifndef _SUN4I_DOTCLOCK_H_
+#define _SUN4I_DOTCLOCK_H_
+
+struct sun4i_tcon;
+
+int sun4i_dclk_create(struct device *dev, struct sun4i_tcon *tcon);
+int sun4i_dclk_free(struct sun4i_tcon *tcon);
+
+#endif /* _SUN4I_DOTCLOCK_H_ */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/sun4i/sun4i_drv.c linux-libre-4.7-gnu/drivers/gpu/drm/sun4i/sun4i_drv.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/sun4i/sun4i_drv.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/sun4i/sun4i_drv.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,351 @@
+/*
+ * Copyright (C) 2015 Free Electrons
+ * Copyright (C) 2015 NextThing Co
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <linux/component.h>
+#include <linux/of_graph.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+
+#include "sun4i_crtc.h"
+#include "sun4i_drv.h"
+#include "sun4i_framebuffer.h"
+#include "sun4i_layer.h"
+#include "sun4i_tcon.h"
+
+static int sun4i_drv_enable_vblank(struct drm_device *drm, unsigned int pipe)
+{
+	struct sun4i_drv *drv = drm->dev_private;
+	struct sun4i_tcon *tcon = drv->tcon;
+
+	DRM_DEBUG_DRIVER("Enabling VBLANK on pipe %d\n", pipe);
+
+	sun4i_tcon_enable_vblank(tcon, true);
+
+	return 0;
+}
+
+static void sun4i_drv_disable_vblank(struct drm_device *drm, unsigned int pipe)
+{
+	struct sun4i_drv *drv = drm->dev_private;
+	struct sun4i_tcon *tcon = drv->tcon;
+
+	DRM_DEBUG_DRIVER("Disabling VBLANK on pipe %d\n", pipe);
+
+	sun4i_tcon_enable_vblank(tcon, false);
+}
+
+static const struct file_operations sun4i_drv_fops = {
+	.owner		= THIS_MODULE,
+	.open		= drm_open,
+	.release	= drm_release,
+	.unlocked_ioctl	= drm_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= drm_compat_ioctl,
+#endif
+	.poll		= drm_poll,
+	.read		= drm_read,
+	.llseek		= no_llseek,
+	.mmap		= drm_gem_cma_mmap,
+};
+
+static struct drm_driver sun4i_drv_driver = {
+	.driver_features	= DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_ATOMIC,
+
+	/* Generic Operations */
+	.fops			= &sun4i_drv_fops,
+	.name			= "sun4i-drm",
+	.desc			= "Allwinner sun4i Display Engine",
+	.date			= "20150629",
+	.major			= 1,
+	.minor			= 0,
+
+	/* GEM Operations */
+	.dumb_create		= drm_gem_cma_dumb_create,
+	.dumb_destroy		= drm_gem_dumb_destroy,
+	.dumb_map_offset	= drm_gem_cma_dumb_map_offset,
+	.gem_free_object	= drm_gem_cma_free_object,
+	.gem_vm_ops		= &drm_gem_cma_vm_ops,
+
+	/* PRIME Operations */
+	.prime_handle_to_fd	= drm_gem_prime_handle_to_fd,
+	.prime_fd_to_handle	= drm_gem_prime_fd_to_handle,
+	.gem_prime_import	= drm_gem_prime_import,
+	.gem_prime_export	= drm_gem_prime_export,
+	.gem_prime_get_sg_table	= drm_gem_cma_prime_get_sg_table,
+	.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
+	.gem_prime_vmap		= drm_gem_cma_prime_vmap,
+	.gem_prime_vunmap	= drm_gem_cma_prime_vunmap,
+	.gem_prime_mmap		= drm_gem_cma_prime_mmap,
+
+	/* Frame Buffer Operations */
+
+	/* VBlank Operations */
+	.get_vblank_counter	= drm_vblank_no_hw_counter,
+	.enable_vblank		= sun4i_drv_enable_vblank,
+	.disable_vblank		= sun4i_drv_disable_vblank,
+};
+
+static void sun4i_remove_framebuffers(void)
+{
+	struct apertures_struct *ap;
+
+	ap = alloc_apertures(1);
+	if (!ap)
+		return;
+
+	/* The framebuffer can be located anywhere in RAM */
+	ap->ranges[0].base = 0;
+	ap->ranges[0].size = ~0;
+
+	remove_conflicting_framebuffers(ap, "sun4i-drm-fb", false);
+	kfree(ap);
+}
+
+static int sun4i_drv_bind(struct device *dev)
+{
+	struct drm_device *drm;
+	struct sun4i_drv *drv;
+	int ret;
+
+	drm = drm_dev_alloc(&sun4i_drv_driver, dev);
+	if (!drm)
+		return -ENOMEM;
+
+	ret = drm_dev_set_unique(drm, dev_name(drm->dev));
+	if (ret)
+		goto free_drm;
+
+	drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL);
+	if (!drv) {
+		ret = -ENOMEM;
+		goto free_drm;
+	}
+	drm->dev_private = drv;
+
+	drm_vblank_init(drm, 1);
+	drm_mode_config_init(drm);
+
+	ret = component_bind_all(drm->dev, drm);
+	if (ret) {
+		dev_err(drm->dev, "Couldn't bind all pipelines components\n");
+		goto free_drm;
+	}
+
+	/* Create our layers */
+	drv->layers = sun4i_layers_init(drm);
+	if (!drv->layers) {
+		dev_err(drm->dev, "Couldn't create the planes\n");
+		ret = -EINVAL;
+		goto free_drm;
+	}
+
+	/* Create our CRTC */
+	drv->crtc = sun4i_crtc_init(drm);
+	if (!drv->crtc) {
+		dev_err(drm->dev, "Couldn't create the CRTC\n");
+		ret = -EINVAL;
+		goto free_drm;
+	}
+	drm->irq_enabled = true;
+
+	/* Remove early framebuffers (ie. simplefb) */
+	sun4i_remove_framebuffers();
+
+	/* Create our framebuffer */
+	drv->fbdev = sun4i_framebuffer_init(drm);
+	if (IS_ERR(drv->fbdev)) {
+		dev_err(drm->dev, "Couldn't create our framebuffer\n");
+		ret = PTR_ERR(drv->fbdev);
+		goto free_drm;
+	}
+
+	/* Enable connectors polling */
+	drm_kms_helper_poll_init(drm);
+
+	ret = drm_dev_register(drm, 0);
+	if (ret)
+		goto free_drm;
+
+	ret = drm_connector_register_all(drm);
+	if (ret)
+		goto unregister_drm;
+
+	return 0;
+
+unregister_drm:
+	drm_dev_unregister(drm);
+free_drm:
+	drm_dev_unref(drm);
+	return ret;
+}
+
+static void sun4i_drv_unbind(struct device *dev)
+{
+	struct drm_device *drm = dev_get_drvdata(dev);
+
+	drm_connector_unregister_all(drm);
+	drm_dev_unregister(drm);
+	drm_kms_helper_poll_fini(drm);
+	sun4i_framebuffer_free(drm);
+	drm_vblank_cleanup(drm);
+	drm_dev_unref(drm);
+}
+
+static const struct component_master_ops sun4i_drv_master_ops = {
+	.bind	= sun4i_drv_bind,
+	.unbind	= sun4i_drv_unbind,
+};
+
+static bool sun4i_drv_node_is_frontend(struct device_node *node)
+{
+	return of_device_is_compatible(node,
+				       "allwinner,sun5i-a13-display-frontend");
+}
+
+static bool sun4i_drv_node_is_tcon(struct device_node *node)
+{
+	return of_device_is_compatible(node, "allwinner,sun5i-a13-tcon");
+}
+
+static int compare_of(struct device *dev, void *data)
+{
+	DRM_DEBUG_DRIVER("Comparing of node %s with %s\n",
+			 of_node_full_name(dev->of_node),
+			 of_node_full_name(data));
+
+	return dev->of_node == data;
+}
+
+static int sun4i_drv_add_endpoints(struct device *dev,
+				   struct component_match **match,
+				   struct device_node *node)
+{
+	struct device_node *port, *ep, *remote;
+	int count = 0;
+
+	/*
+	 * We don't support the frontend for now, so we will never
+	 * have a device bound. Just skip over it, but we still want
+	 * the rest our pipeline to be added.
+	 */
+	if (!sun4i_drv_node_is_frontend(node) &&
+	    !of_device_is_available(node))
+		return 0;
+
+	if (!sun4i_drv_node_is_frontend(node)) {
+		/* Add current component */
+		DRM_DEBUG_DRIVER("Adding component %s\n",
+				 of_node_full_name(node));
+		component_match_add(dev, match, compare_of, node);
+		count++;
+	}
+
+	/* Inputs are listed first, then outputs */
+	port = of_graph_get_port_by_id(node, 1);
+	if (!port) {
+		DRM_DEBUG_DRIVER("No output to bind\n");
+		return count;
+	}
+
+	for_each_available_child_of_node(port, ep) {
+		remote = of_graph_get_remote_port_parent(ep);
+		if (!remote) {
+			DRM_DEBUG_DRIVER("Error retrieving the output node\n");
+			of_node_put(remote);
+			continue;
+		}
+
+		/*
+		 * If the node is our TCON, the first port is used for our
+		 * panel, and will not be part of the
+		 * component framework.
+		 */
+		if (sun4i_drv_node_is_tcon(node)) {
+			struct of_endpoint endpoint;
+
+			if (of_graph_parse_endpoint(ep, &endpoint)) {
+				DRM_DEBUG_DRIVER("Couldn't parse endpoint\n");
+				continue;
+			}
+
+			if (!endpoint.id) {
+				DRM_DEBUG_DRIVER("Endpoint is our panel... skipping\n");
+				continue;
+			}
+		}
+
+		/* Walk down our tree */
+		count += sun4i_drv_add_endpoints(dev, match, remote);
+
+		of_node_put(remote);
+	}
+
+	return count;
+}
+
+static int sun4i_drv_probe(struct platform_device *pdev)
+{
+	struct component_match *match = NULL;
+	struct device_node *np = pdev->dev.of_node;
+	int i, count = 0;
+
+	for (i = 0;; i++) {
+		struct device_node *pipeline = of_parse_phandle(np,
+								"allwinner,pipelines",
+								i);
+		if (!pipeline)
+			break;
+
+		count += sun4i_drv_add_endpoints(&pdev->dev, &match,
+						pipeline);
+		of_node_put(pipeline);
+
+		DRM_DEBUG_DRIVER("Queued %d outputs on pipeline %d\n",
+				 count, i);
+	}
+
+	if (count)
+		return component_master_add_with_match(&pdev->dev,
+						       &sun4i_drv_master_ops,
+						       match);
+	else
+		return 0;
+}
+
+static int sun4i_drv_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static const struct of_device_id sun4i_drv_of_table[] = {
+	{ .compatible = "allwinner,sun5i-a13-display-engine" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, sun4i_drv_of_table);
+
+static struct platform_driver sun4i_drv_platform_driver = {
+	.probe		= sun4i_drv_probe,
+	.remove		= sun4i_drv_remove,
+	.driver		= {
+		.name		= "sun4i-drm",
+		.of_match_table	= sun4i_drv_of_table,
+	},
+};
+module_platform_driver(sun4i_drv_platform_driver);
+
+MODULE_AUTHOR("Boris Brezillon <boris.brezillon@free-electrons.com>");
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
+MODULE_DESCRIPTION("Allwinner A10 Display Engine DRM/KMS Driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/sun4i/sun4i_drv.h linux-libre-4.7-gnu/drivers/gpu/drm/sun4i/sun4i_drv.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/sun4i/sun4i_drv.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/sun4i/sun4i_drv.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2015 Free Electrons
+ * Copyright (C) 2015 NextThing Co
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#ifndef _SUN4I_DRV_H_
+#define _SUN4I_DRV_H_
+
+#include <linux/clk.h>
+#include <linux/regmap.h>
+
+struct sun4i_drv {
+	struct sun4i_backend	*backend;
+	struct sun4i_crtc	*crtc;
+	struct sun4i_tcon	*tcon;
+
+	struct drm_plane	*primary;
+	struct drm_fbdev_cma	*fbdev;
+
+	struct sun4i_layer	**layers;
+};
+
+#endif /* _SUN4I_DRV_H_ */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/sun4i/sun4i_framebuffer.c linux-libre-4.7-gnu/drivers/gpu/drm/sun4i/sun4i_framebuffer.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/sun4i/sun4i_framebuffer.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/sun4i/sun4i_framebuffer.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2015 Free Electrons
+ * Copyright (C) 2015 NextThing Co
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drmP.h>
+
+#include "sun4i_drv.h"
+
+static void sun4i_de_output_poll_changed(struct drm_device *drm)
+{
+	struct sun4i_drv *drv = drm->dev_private;
+
+	if (drv->fbdev)
+		drm_fbdev_cma_hotplug_event(drv->fbdev);
+}
+
+static const struct drm_mode_config_funcs sun4i_de_mode_config_funcs = {
+	.output_poll_changed	= sun4i_de_output_poll_changed,
+	.atomic_check		= drm_atomic_helper_check,
+	.atomic_commit		= drm_atomic_helper_commit,
+	.fb_create		= drm_fb_cma_create,
+};
+
+struct drm_fbdev_cma *sun4i_framebuffer_init(struct drm_device *drm)
+{
+	drm_mode_config_reset(drm);
+
+	drm->mode_config.max_width = 8192;
+	drm->mode_config.max_height = 8192;
+
+	drm->mode_config.funcs = &sun4i_de_mode_config_funcs;
+
+	return drm_fbdev_cma_init(drm, 32,
+				  drm->mode_config.num_crtc,
+				  drm->mode_config.num_connector);
+}
+
+void sun4i_framebuffer_free(struct drm_device *drm)
+{
+	struct sun4i_drv *drv = drm->dev_private;
+
+	drm_fbdev_cma_fini(drv->fbdev);
+	drm_mode_config_cleanup(drm);
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/sun4i/sun4i_framebuffer.h linux-libre-4.7-gnu/drivers/gpu/drm/sun4i/sun4i_framebuffer.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/sun4i/sun4i_framebuffer.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/sun4i/sun4i_framebuffer.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2015 Free Electrons
+ * Copyright (C) 2015 NextThing Co
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#ifndef _SUN4I_FRAMEBUFFER_H_
+#define _SUN4I_FRAMEBUFFER_H_
+
+struct drm_fbdev_cma *sun4i_framebuffer_init(struct drm_device *drm);
+void sun4i_framebuffer_free(struct drm_device *drm);
+
+#endif /* _SUN4I_FRAMEBUFFER_H_ */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/sun4i/sun4i_layer.c linux-libre-4.7-gnu/drivers/gpu/drm/sun4i/sun4i_layer.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/sun4i/sun4i_layer.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/sun4i/sun4i_layer.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2015 Free Electrons
+ * Copyright (C) 2015 NextThing Co
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drmP.h>
+
+#include "sun4i_backend.h"
+#include "sun4i_drv.h"
+#include "sun4i_layer.h"
+
+#define SUN4I_NUM_LAYERS	2
+
+static int sun4i_backend_layer_atomic_check(struct drm_plane *plane,
+					    struct drm_plane_state *state)
+{
+	return 0;
+}
+
+static void sun4i_backend_layer_atomic_disable(struct drm_plane *plane,
+					       struct drm_plane_state *old_state)
+{
+	struct sun4i_layer *layer = plane_to_sun4i_layer(plane);
+	struct sun4i_drv *drv = layer->drv;
+	struct sun4i_backend *backend = drv->backend;
+
+	sun4i_backend_layer_enable(backend, layer->id, false);
+}
+
+static void sun4i_backend_layer_atomic_update(struct drm_plane *plane,
+					      struct drm_plane_state *old_state)
+{
+	struct sun4i_layer *layer = plane_to_sun4i_layer(plane);
+	struct sun4i_drv *drv = layer->drv;
+	struct sun4i_backend *backend = drv->backend;
+
+	sun4i_backend_update_layer_coord(backend, layer->id, plane);
+	sun4i_backend_update_layer_formats(backend, layer->id, plane);
+	sun4i_backend_update_layer_buffer(backend, layer->id, plane);
+	sun4i_backend_layer_enable(backend, layer->id, true);
+}
+
+static struct drm_plane_helper_funcs sun4i_backend_layer_helper_funcs = {
+	.atomic_check	= sun4i_backend_layer_atomic_check,
+	.atomic_disable	= sun4i_backend_layer_atomic_disable,
+	.atomic_update	= sun4i_backend_layer_atomic_update,
+};
+
+static const struct drm_plane_funcs sun4i_backend_layer_funcs = {
+	.atomic_destroy_state	= drm_atomic_helper_plane_destroy_state,
+	.atomic_duplicate_state	= drm_atomic_helper_plane_duplicate_state,
+	.destroy		= drm_plane_cleanup,
+	.disable_plane		= drm_atomic_helper_disable_plane,
+	.reset			= drm_atomic_helper_plane_reset,
+	.update_plane		= drm_atomic_helper_update_plane,
+};
+
+static const uint32_t sun4i_backend_layer_formats[] = {
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_RGB888,
+};
+
+static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm,
+						enum drm_plane_type type)
+{
+	struct sun4i_drv *drv = drm->dev_private;
+	struct sun4i_layer *layer;
+	int ret;
+
+	layer = devm_kzalloc(drm->dev, sizeof(*layer), GFP_KERNEL);
+	if (!layer)
+		return ERR_PTR(-ENOMEM);
+
+	ret = drm_universal_plane_init(drm, &layer->plane, BIT(0),
+				       &sun4i_backend_layer_funcs,
+				       sun4i_backend_layer_formats,
+				       ARRAY_SIZE(sun4i_backend_layer_formats),
+				       type,
+				       NULL);
+	if (ret) {
+		dev_err(drm->dev, "Couldn't initialize layer\n");
+		return ERR_PTR(ret);
+	}
+
+	drm_plane_helper_add(&layer->plane,
+			     &sun4i_backend_layer_helper_funcs);
+	layer->drv = drv;
+
+	if (type == DRM_PLANE_TYPE_PRIMARY)
+		drv->primary = &layer->plane;
+
+	return layer;
+}
+
+struct sun4i_layer **sun4i_layers_init(struct drm_device *drm)
+{
+	struct sun4i_drv *drv = drm->dev_private;
+	struct sun4i_layer **layers;
+	int i;
+
+	layers = devm_kcalloc(drm->dev, SUN4I_NUM_LAYERS, sizeof(**layers),
+			      GFP_KERNEL);
+	if (!layers)
+		return ERR_PTR(-ENOMEM);
+
+	/*
+	 * The hardware is a bit unusual here.
+	 *
+	 * Even though it supports 4 layers, it does the composition
+	 * in two separate steps.
+	 *
+	 * The first one is assigning a layer to one of its two
+	 * pipes. If more that 1 layer is assigned to the same pipe,
+	 * and if pixels overlaps, the pipe will take the pixel from
+	 * the layer with the highest priority.
+	 *
+	 * The second step is the actual alpha blending, that takes
+	 * the two pipes as input, and uses the eventual alpha
+	 * component to do the transparency between the two.
+	 *
+	 * This two steps scenario makes us unable to guarantee a
+	 * robust alpha blending between the 4 layers in all
+	 * situations. So we just expose two layers, one per pipe. On
+	 * SoCs that support it, sprites could fill the need for more
+	 * layers.
+	 */
+	for (i = 0; i < SUN4I_NUM_LAYERS; i++) {
+		enum drm_plane_type type = (i == 0)
+					 ? DRM_PLANE_TYPE_PRIMARY
+					 : DRM_PLANE_TYPE_OVERLAY;
+		struct sun4i_layer *layer = layers[i];
+
+		layer = sun4i_layer_init_one(drm, type);
+		if (IS_ERR(layer)) {
+			dev_err(drm->dev, "Couldn't initialize %s plane\n",
+				i ? "overlay" : "primary");
+			return ERR_CAST(layer);
+		};
+
+		DRM_DEBUG_DRIVER("Assigning %s plane to pipe %d\n",
+				 i ? "overlay" : "primary", i);
+		regmap_update_bits(drv->backend->regs, SUN4I_BACKEND_ATTCTL_REG0(i),
+				   SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL_MASK,
+				   SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL(i));
+
+		layer->id = i;
+	};
+
+	return layers;
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/sun4i/sun4i_layer.h linux-libre-4.7-gnu/drivers/gpu/drm/sun4i/sun4i_layer.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/sun4i/sun4i_layer.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/sun4i/sun4i_layer.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2015 Free Electrons
+ * Copyright (C) 2015 NextThing Co
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#ifndef _SUN4I_LAYER_H_
+#define _SUN4I_LAYER_H_
+
+struct sun4i_layer {
+	struct drm_plane	plane;
+	struct sun4i_drv	*drv;
+	int			id;
+};
+
+static inline struct sun4i_layer *
+plane_to_sun4i_layer(struct drm_plane *plane)
+{
+	return container_of(plane, struct sun4i_layer, plane);
+}
+
+struct sun4i_layer **sun4i_layers_init(struct drm_device *drm);
+
+#endif /* _SUN4I_LAYER_H_ */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/sun4i/sun4i_rgb.c linux-libre-4.7-gnu/drivers/gpu/drm/sun4i/sun4i_rgb.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/sun4i/sun4i_rgb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/sun4i/sun4i_rgb.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) 2015 Free Electrons
+ * Copyright (C) 2015 NextThing Co
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <linux/clk.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_panel.h>
+
+#include "sun4i_drv.h"
+#include "sun4i_tcon.h"
+
+struct sun4i_rgb {
+	struct drm_connector	connector;
+	struct drm_encoder	encoder;
+
+	struct sun4i_drv	*drv;
+};
+
+static inline struct sun4i_rgb *
+drm_connector_to_sun4i_rgb(struct drm_connector *connector)
+{
+	return container_of(connector, struct sun4i_rgb,
+			    connector);
+}
+
+static inline struct sun4i_rgb *
+drm_encoder_to_sun4i_rgb(struct drm_encoder *encoder)
+{
+	return container_of(encoder, struct sun4i_rgb,
+			    encoder);
+}
+
+static int sun4i_rgb_get_modes(struct drm_connector *connector)
+{
+	struct sun4i_rgb *rgb =
+		drm_connector_to_sun4i_rgb(connector);
+	struct sun4i_drv *drv = rgb->drv;
+	struct sun4i_tcon *tcon = drv->tcon;
+
+	return drm_panel_get_modes(tcon->panel);
+}
+
+static int sun4i_rgb_mode_valid(struct drm_connector *connector,
+				struct drm_display_mode *mode)
+{
+	struct sun4i_rgb *rgb = drm_connector_to_sun4i_rgb(connector);
+	struct sun4i_drv *drv = rgb->drv;
+	struct sun4i_tcon *tcon = drv->tcon;
+	u32 hsync = mode->hsync_end - mode->hsync_start;
+	u32 vsync = mode->vsync_end - mode->vsync_start;
+	unsigned long rate = mode->clock * 1000;
+	long rounded_rate;
+
+	DRM_DEBUG_DRIVER("Validating modes...\n");
+
+	if (hsync < 1)
+		return MODE_HSYNC_NARROW;
+
+	if (hsync > 0x3ff)
+		return MODE_HSYNC_WIDE;
+
+	if ((mode->hdisplay < 1) || (mode->htotal < 1))
+		return MODE_H_ILLEGAL;
+
+	if ((mode->hdisplay > 0x7ff) || (mode->htotal > 0xfff))
+		return MODE_BAD_HVALUE;
+
+	DRM_DEBUG_DRIVER("Horizontal parameters OK\n");
+
+	if (vsync < 1)
+		return MODE_VSYNC_NARROW;
+
+	if (vsync > 0x3ff)
+		return MODE_VSYNC_WIDE;
+
+	if ((mode->vdisplay < 1) || (mode->vtotal < 1))
+		return MODE_V_ILLEGAL;
+
+	if ((mode->vdisplay > 0x7ff) || (mode->vtotal > 0xfff))
+		return MODE_BAD_VVALUE;
+
+	DRM_DEBUG_DRIVER("Vertical parameters OK\n");
+
+	rounded_rate = clk_round_rate(tcon->dclk, rate);
+	if (rounded_rate < rate)
+		return MODE_CLOCK_LOW;
+
+	if (rounded_rate > rate)
+		return MODE_CLOCK_HIGH;
+
+	DRM_DEBUG_DRIVER("Clock rate OK\n");
+
+	return MODE_OK;
+}
+
+static struct drm_encoder *
+sun4i_rgb_best_encoder(struct drm_connector *connector)
+{
+	struct sun4i_rgb *rgb =
+		drm_connector_to_sun4i_rgb(connector);
+
+	return &rgb->encoder;
+}
+
+static struct drm_connector_helper_funcs sun4i_rgb_con_helper_funcs = {
+	.get_modes	= sun4i_rgb_get_modes,
+	.mode_valid	= sun4i_rgb_mode_valid,
+	.best_encoder	= sun4i_rgb_best_encoder,
+};
+
+static enum drm_connector_status
+sun4i_rgb_connector_detect(struct drm_connector *connector, bool force)
+{
+	return connector_status_connected;
+}
+
+static void
+sun4i_rgb_connector_destroy(struct drm_connector *connector)
+{
+	struct sun4i_rgb *rgb = drm_connector_to_sun4i_rgb(connector);
+	struct sun4i_drv *drv = rgb->drv;
+	struct sun4i_tcon *tcon = drv->tcon;
+
+	drm_panel_detach(tcon->panel);
+	drm_connector_cleanup(connector);
+}
+
+static struct drm_connector_funcs sun4i_rgb_con_funcs = {
+	.dpms			= drm_atomic_helper_connector_dpms,
+	.detect			= sun4i_rgb_connector_detect,
+	.fill_modes		= drm_helper_probe_single_connector_modes,
+	.destroy		= sun4i_rgb_connector_destroy,
+	.reset			= drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state	= drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
+};
+
+static int sun4i_rgb_atomic_check(struct drm_encoder *encoder,
+				  struct drm_crtc_state *crtc_state,
+				  struct drm_connector_state *conn_state)
+{
+	return 0;
+}
+
+static void sun4i_rgb_encoder_enable(struct drm_encoder *encoder)
+{
+	struct sun4i_rgb *rgb = drm_encoder_to_sun4i_rgb(encoder);
+	struct sun4i_drv *drv = rgb->drv;
+	struct sun4i_tcon *tcon = drv->tcon;
+
+	DRM_DEBUG_DRIVER("Enabling RGB output\n");
+
+	drm_panel_enable(tcon->panel);
+	sun4i_tcon_channel_enable(tcon, 0);
+}
+
+static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder)
+{
+	struct sun4i_rgb *rgb = drm_encoder_to_sun4i_rgb(encoder);
+	struct sun4i_drv *drv = rgb->drv;
+	struct sun4i_tcon *tcon = drv->tcon;
+
+	DRM_DEBUG_DRIVER("Disabling RGB output\n");
+
+	sun4i_tcon_channel_disable(tcon, 0);
+	drm_panel_disable(tcon->panel);
+}
+
+static void sun4i_rgb_encoder_mode_set(struct drm_encoder *encoder,
+				       struct drm_display_mode *mode,
+				       struct drm_display_mode *adjusted_mode)
+{
+	struct sun4i_rgb *rgb = drm_encoder_to_sun4i_rgb(encoder);
+	struct sun4i_drv *drv = rgb->drv;
+	struct sun4i_tcon *tcon = drv->tcon;
+
+	sun4i_tcon0_mode_set(tcon, mode);
+
+	clk_set_rate(tcon->dclk, mode->crtc_clock * 1000);
+
+	/* FIXME: This seems to be board specific */
+	clk_set_phase(tcon->dclk, 120);
+}
+
+static struct drm_encoder_helper_funcs sun4i_rgb_enc_helper_funcs = {
+	.atomic_check	= sun4i_rgb_atomic_check,
+	.mode_set	= sun4i_rgb_encoder_mode_set,
+	.disable	= sun4i_rgb_encoder_disable,
+	.enable		= sun4i_rgb_encoder_enable,
+};
+
+static void sun4i_rgb_enc_destroy(struct drm_encoder *encoder)
+{
+	drm_encoder_cleanup(encoder);
+}
+
+static struct drm_encoder_funcs sun4i_rgb_enc_funcs = {
+	.destroy	= sun4i_rgb_enc_destroy,
+};
+
+int sun4i_rgb_init(struct drm_device *drm)
+{
+	struct sun4i_drv *drv = drm->dev_private;
+	struct sun4i_tcon *tcon = drv->tcon;
+	struct sun4i_rgb *rgb;
+	int ret;
+
+	/* If we don't have a panel, there's no point in going on */
+	if (IS_ERR(tcon->panel))
+		return -ENODEV;
+
+	rgb = devm_kzalloc(drm->dev, sizeof(*rgb), GFP_KERNEL);
+	if (!rgb)
+		return -ENOMEM;
+	rgb->drv = drv;
+
+	drm_encoder_helper_add(&rgb->encoder,
+			       &sun4i_rgb_enc_helper_funcs);
+	ret = drm_encoder_init(drm,
+			       &rgb->encoder,
+			       &sun4i_rgb_enc_funcs,
+			       DRM_MODE_ENCODER_NONE,
+			       NULL);
+	if (ret) {
+		dev_err(drm->dev, "Couldn't initialise the rgb encoder\n");
+		goto err_out;
+	}
+
+	/* The RGB encoder can only work with the TCON channel 0 */
+	rgb->encoder.possible_crtcs = BIT(0);
+
+	drm_connector_helper_add(&rgb->connector,
+				 &sun4i_rgb_con_helper_funcs);
+	ret = drm_connector_init(drm, &rgb->connector,
+				 &sun4i_rgb_con_funcs,
+				 DRM_MODE_CONNECTOR_Unknown);
+	if (ret) {
+		dev_err(drm->dev, "Couldn't initialise the rgb connector\n");
+		goto err_cleanup_connector;
+	}
+
+	drm_mode_connector_attach_encoder(&rgb->connector, &rgb->encoder);
+
+	drm_panel_attach(tcon->panel, &rgb->connector);
+
+	return 0;
+
+err_cleanup_connector:
+	drm_encoder_cleanup(&rgb->encoder);
+err_out:
+	return ret;
+}
+EXPORT_SYMBOL(sun4i_rgb_init);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/sun4i/sun4i_rgb.h linux-libre-4.7-gnu/drivers/gpu/drm/sun4i/sun4i_rgb.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/sun4i/sun4i_rgb.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/sun4i/sun4i_rgb.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2015 Free Electrons
+ * Copyright (C) 2015 NextThing Co
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#ifndef _SUN4I_RGB_H_
+#define _SUN4I_RGB_H_
+
+int sun4i_rgb_init(struct drm_device *drm);
+
+#endif /* _SUN4I_RGB_H_ */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/sun4i/sun4i_tcon.c linux-libre-4.7-gnu/drivers/gpu/drm/sun4i/sun4i_tcon.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/sun4i/sun4i_tcon.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/sun4i/sun4i_tcon.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,566 @@
+/*
+ * Copyright (C) 2015 Free Electrons
+ * Copyright (C) 2015 NextThing Co
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+#include <linux/component.h>
+#include <linux/ioport.h>
+#include <linux/of_address.h>
+#include <linux/of_graph.h>
+#include <linux/of_irq.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+#include "sun4i_crtc.h"
+#include "sun4i_dotclock.h"
+#include "sun4i_drv.h"
+#include "sun4i_rgb.h"
+#include "sun4i_tcon.h"
+
+void sun4i_tcon_disable(struct sun4i_tcon *tcon)
+{
+	DRM_DEBUG_DRIVER("Disabling TCON\n");
+
+	/* Disable the TCON */
+	regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
+			   SUN4I_TCON_GCTL_TCON_ENABLE, 0);
+}
+EXPORT_SYMBOL(sun4i_tcon_disable);
+
+void sun4i_tcon_enable(struct sun4i_tcon *tcon)
+{
+	DRM_DEBUG_DRIVER("Enabling TCON\n");
+
+	/* Enable the TCON */
+	regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
+			   SUN4I_TCON_GCTL_TCON_ENABLE,
+			   SUN4I_TCON_GCTL_TCON_ENABLE);
+}
+EXPORT_SYMBOL(sun4i_tcon_enable);
+
+void sun4i_tcon_channel_disable(struct sun4i_tcon *tcon, int channel)
+{
+	/* Disable the TCON's channel */
+	if (channel == 0) {
+		regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
+				   SUN4I_TCON0_CTL_TCON_ENABLE, 0);
+		clk_disable_unprepare(tcon->dclk);
+	} else if (channel == 1) {
+		regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
+				   SUN4I_TCON1_CTL_TCON_ENABLE, 0);
+		clk_disable_unprepare(tcon->sclk1);
+	}
+}
+EXPORT_SYMBOL(sun4i_tcon_channel_disable);
+
+void sun4i_tcon_channel_enable(struct sun4i_tcon *tcon, int channel)
+{
+	/* Enable the TCON's channel */
+	if (channel == 0) {
+		regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
+				   SUN4I_TCON0_CTL_TCON_ENABLE,
+				   SUN4I_TCON0_CTL_TCON_ENABLE);
+		clk_prepare_enable(tcon->dclk);
+	} else if (channel == 1) {
+		regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
+				   SUN4I_TCON1_CTL_TCON_ENABLE,
+				   SUN4I_TCON1_CTL_TCON_ENABLE);
+		clk_prepare_enable(tcon->sclk1);
+	}
+}
+EXPORT_SYMBOL(sun4i_tcon_channel_enable);
+
+void sun4i_tcon_enable_vblank(struct sun4i_tcon *tcon, bool enable)
+{
+	u32 mask, val = 0;
+
+	DRM_DEBUG_DRIVER("%sabling VBLANK interrupt\n", enable ? "En" : "Dis");
+
+	mask = SUN4I_TCON_GINT0_VBLANK_ENABLE(0) |
+	       SUN4I_TCON_GINT0_VBLANK_ENABLE(1);
+
+	if (enable)
+		val = mask;
+
+	regmap_update_bits(tcon->regs, SUN4I_TCON_GINT0_REG, mask, val);
+}
+EXPORT_SYMBOL(sun4i_tcon_enable_vblank);
+
+static int sun4i_tcon_get_clk_delay(struct drm_display_mode *mode,
+				    int channel)
+{
+	int delay = mode->vtotal - mode->vdisplay;
+
+	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+		delay /= 2;
+
+	if (channel == 1)
+		delay -= 2;
+
+	delay = min(delay, 30);
+
+	DRM_DEBUG_DRIVER("TCON %d clock delay %u\n", channel, delay);
+
+	return delay;
+}
+
+void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
+			  struct drm_display_mode *mode)
+{
+	unsigned int bp, hsync, vsync;
+	u8 clk_delay;
+	u32 val = 0;
+
+	/* Adjust clock delay */
+	clk_delay = sun4i_tcon_get_clk_delay(mode, 0);
+	regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
+			   SUN4I_TCON0_CTL_CLK_DELAY_MASK,
+			   SUN4I_TCON0_CTL_CLK_DELAY(clk_delay));
+
+	/* Set the resolution */
+	regmap_write(tcon->regs, SUN4I_TCON0_BASIC0_REG,
+		     SUN4I_TCON0_BASIC0_X(mode->crtc_hdisplay) |
+		     SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
+
+	/*
+	 * This is called a backporch in the register documentation,
+	 * but it really is the front porch + hsync
+	 */
+	bp = mode->crtc_htotal - mode->crtc_hsync_start;
+	DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n",
+			 mode->crtc_htotal, bp);
+
+	/* Set horizontal display timings */
+	regmap_write(tcon->regs, SUN4I_TCON0_BASIC1_REG,
+		     SUN4I_TCON0_BASIC1_H_TOTAL(mode->crtc_htotal) |
+		     SUN4I_TCON0_BASIC1_H_BACKPORCH(bp));
+
+	/*
+	 * This is called a backporch in the register documentation,
+	 * but it really is the front porch + hsync
+	 */
+	bp = mode->crtc_vtotal - mode->crtc_vsync_start;
+	DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n",
+			 mode->crtc_vtotal, bp);
+
+	/* Set vertical display timings */
+	regmap_write(tcon->regs, SUN4I_TCON0_BASIC2_REG,
+		     SUN4I_TCON0_BASIC2_V_TOTAL(mode->crtc_vtotal) |
+		     SUN4I_TCON0_BASIC2_V_BACKPORCH(bp));
+
+	/* Set Hsync and Vsync length */
+	hsync = mode->crtc_hsync_end - mode->crtc_hsync_start;
+	vsync = mode->crtc_vsync_end - mode->crtc_vsync_start;
+	DRM_DEBUG_DRIVER("Setting HSYNC %d, VSYNC %d\n", hsync, vsync);
+	regmap_write(tcon->regs, SUN4I_TCON0_BASIC3_REG,
+		     SUN4I_TCON0_BASIC3_V_SYNC(vsync) |
+		     SUN4I_TCON0_BASIC3_H_SYNC(hsync));
+
+	/* Setup the polarity of the various signals */
+	if (!(mode->flags & DRM_MODE_FLAG_PHSYNC))
+		val |= SUN4I_TCON0_IO_POL_HSYNC_POSITIVE;
+
+	if (!(mode->flags & DRM_MODE_FLAG_PVSYNC))
+		val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE;
+
+	regmap_update_bits(tcon->regs, SUN4I_TCON0_IO_POL_REG,
+			   SUN4I_TCON0_IO_POL_HSYNC_POSITIVE | SUN4I_TCON0_IO_POL_VSYNC_POSITIVE,
+			   val);
+
+	/* Map output pins to channel 0 */
+	regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
+			   SUN4I_TCON_GCTL_IOMAP_MASK,
+			   SUN4I_TCON_GCTL_IOMAP_TCON0);
+
+	/* Enable the output on the pins */
+	regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0);
+}
+EXPORT_SYMBOL(sun4i_tcon0_mode_set);
+
+void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
+			  struct drm_display_mode *mode)
+{
+	unsigned int bp, hsync, vsync;
+	u8 clk_delay;
+	u32 val;
+
+	/* Adjust clock delay */
+	clk_delay = sun4i_tcon_get_clk_delay(mode, 1);
+	regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
+			   SUN4I_TCON1_CTL_CLK_DELAY_MASK,
+			   SUN4I_TCON1_CTL_CLK_DELAY(clk_delay));
+
+	/* Set interlaced mode */
+	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+		val = SUN4I_TCON1_CTL_INTERLACE_ENABLE;
+	else
+		val = 0;
+	regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
+			   SUN4I_TCON1_CTL_INTERLACE_ENABLE,
+			   val);
+
+	/* Set the input resolution */
+	regmap_write(tcon->regs, SUN4I_TCON1_BASIC0_REG,
+		     SUN4I_TCON1_BASIC0_X(mode->crtc_hdisplay) |
+		     SUN4I_TCON1_BASIC0_Y(mode->crtc_vdisplay));
+
+	/* Set the upscaling resolution */
+	regmap_write(tcon->regs, SUN4I_TCON1_BASIC1_REG,
+		     SUN4I_TCON1_BASIC1_X(mode->crtc_hdisplay) |
+		     SUN4I_TCON1_BASIC1_Y(mode->crtc_vdisplay));
+
+	/* Set the output resolution */
+	regmap_write(tcon->regs, SUN4I_TCON1_BASIC2_REG,
+		     SUN4I_TCON1_BASIC2_X(mode->crtc_hdisplay) |
+		     SUN4I_TCON1_BASIC2_Y(mode->crtc_vdisplay));
+
+	/* Set horizontal display timings */
+	bp = mode->crtc_htotal - mode->crtc_hsync_end;
+	DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n",
+			 mode->htotal, bp);
+	regmap_write(tcon->regs, SUN4I_TCON1_BASIC3_REG,
+		     SUN4I_TCON1_BASIC3_H_TOTAL(mode->crtc_htotal) |
+		     SUN4I_TCON1_BASIC3_H_BACKPORCH(bp));
+
+	/* Set vertical display timings */
+	bp = mode->crtc_vtotal - mode->crtc_vsync_end;
+	DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n",
+			 mode->vtotal, bp);
+	regmap_write(tcon->regs, SUN4I_TCON1_BASIC4_REG,
+		     SUN4I_TCON1_BASIC4_V_TOTAL(mode->vtotal) |
+		     SUN4I_TCON1_BASIC4_V_BACKPORCH(bp));
+
+	/* Set Hsync and Vsync length */
+	hsync = mode->crtc_hsync_end - mode->crtc_hsync_start;
+	vsync = mode->crtc_vsync_end - mode->crtc_vsync_start;
+	DRM_DEBUG_DRIVER("Setting HSYNC %d, VSYNC %d\n", hsync, vsync);
+	regmap_write(tcon->regs, SUN4I_TCON1_BASIC5_REG,
+		     SUN4I_TCON1_BASIC5_V_SYNC(vsync) |
+		     SUN4I_TCON1_BASIC5_H_SYNC(hsync));
+
+	/* Map output pins to channel 1 */
+	regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
+			   SUN4I_TCON_GCTL_IOMAP_MASK,
+			   SUN4I_TCON_GCTL_IOMAP_TCON1);
+
+	/*
+	 * FIXME: Undocumented bits
+	 */
+	if (tcon->has_mux)
+		regmap_write(tcon->regs, SUN4I_TCON_MUX_CTRL_REG, 1);
+}
+EXPORT_SYMBOL(sun4i_tcon1_mode_set);
+
+static void sun4i_tcon_finish_page_flip(struct drm_device *dev,
+					struct sun4i_crtc *scrtc)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->event_lock, flags);
+	if (scrtc->event) {
+		drm_crtc_send_vblank_event(&scrtc->crtc, scrtc->event);
+		drm_crtc_vblank_put(&scrtc->crtc);
+		scrtc->event = NULL;
+	}
+	spin_unlock_irqrestore(&dev->event_lock, flags);
+}
+
+static irqreturn_t sun4i_tcon_handler(int irq, void *private)
+{
+	struct sun4i_tcon *tcon = private;
+	struct drm_device *drm = tcon->drm;
+	struct sun4i_drv *drv = drm->dev_private;
+	struct sun4i_crtc *scrtc = drv->crtc;
+	unsigned int status;
+
+	regmap_read(tcon->regs, SUN4I_TCON_GINT0_REG, &status);
+
+	if (!(status & (SUN4I_TCON_GINT0_VBLANK_INT(0) |
+			SUN4I_TCON_GINT0_VBLANK_INT(1))))
+		return IRQ_NONE;
+
+	drm_crtc_handle_vblank(&scrtc->crtc);
+	sun4i_tcon_finish_page_flip(drm, scrtc);
+
+	/* Acknowledge the interrupt */
+	regmap_update_bits(tcon->regs, SUN4I_TCON_GINT0_REG,
+			   SUN4I_TCON_GINT0_VBLANK_INT(0) |
+			   SUN4I_TCON_GINT0_VBLANK_INT(1),
+			   0);
+
+	return IRQ_HANDLED;
+}
+
+static int sun4i_tcon_init_clocks(struct device *dev,
+				  struct sun4i_tcon *tcon)
+{
+	tcon->clk = devm_clk_get(dev, "ahb");
+	if (IS_ERR(tcon->clk)) {
+		dev_err(dev, "Couldn't get the TCON bus clock\n");
+		return PTR_ERR(tcon->clk);
+	}
+	clk_prepare_enable(tcon->clk);
+
+	tcon->sclk0 = devm_clk_get(dev, "tcon-ch0");
+	if (IS_ERR(tcon->sclk0)) {
+		dev_err(dev, "Couldn't get the TCON channel 0 clock\n");
+		return PTR_ERR(tcon->sclk0);
+	}
+
+	tcon->sclk1 = devm_clk_get(dev, "tcon-ch1");
+	if (IS_ERR(tcon->sclk1)) {
+		dev_err(dev, "Couldn't get the TCON channel 1 clock\n");
+		return PTR_ERR(tcon->sclk1);
+	}
+
+	return sun4i_dclk_create(dev, tcon);
+}
+
+static void sun4i_tcon_free_clocks(struct sun4i_tcon *tcon)
+{
+	sun4i_dclk_free(tcon);
+	clk_disable_unprepare(tcon->clk);
+}
+
+static int sun4i_tcon_init_irq(struct device *dev,
+			       struct sun4i_tcon *tcon)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	int irq, ret;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(dev, "Couldn't retrieve the TCON interrupt\n");
+		return irq;
+	}
+
+	ret = devm_request_irq(dev, irq, sun4i_tcon_handler, 0,
+			       dev_name(dev), tcon);
+	if (ret) {
+		dev_err(dev, "Couldn't request the IRQ\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct regmap_config sun4i_tcon_regmap_config = {
+	.reg_bits	= 32,
+	.val_bits	= 32,
+	.reg_stride	= 4,
+	.max_register	= 0x800,
+};
+
+static int sun4i_tcon_init_regmap(struct device *dev,
+				  struct sun4i_tcon *tcon)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct resource *res;
+	void __iomem *regs;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(regs)) {
+		dev_err(dev, "Couldn't map the TCON registers\n");
+		return PTR_ERR(regs);
+	}
+
+	tcon->regs = devm_regmap_init_mmio(dev, regs,
+					   &sun4i_tcon_regmap_config);
+	if (IS_ERR(tcon->regs)) {
+		dev_err(dev, "Couldn't create the TCON regmap\n");
+		return PTR_ERR(tcon->regs);
+	}
+
+	/* Make sure the TCON is disabled and all IRQs are off */
+	regmap_write(tcon->regs, SUN4I_TCON_GCTL_REG, 0);
+	regmap_write(tcon->regs, SUN4I_TCON_GINT0_REG, 0);
+	regmap_write(tcon->regs, SUN4I_TCON_GINT1_REG, 0);
+
+	/* Disable IO lines and set them to tristate */
+	regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, ~0);
+	regmap_write(tcon->regs, SUN4I_TCON1_IO_TRI_REG, ~0);
+
+	return 0;
+}
+
+static struct drm_panel *sun4i_tcon_find_panel(struct device_node *node)
+{
+	struct device_node *port, *remote, *child;
+	struct device_node *end_node = NULL;
+
+	/* Inputs are listed first, then outputs */
+	port = of_graph_get_port_by_id(node, 1);
+
+	/*
+	 * Our first output is the RGB interface where the panel will
+	 * be connected.
+	 */
+	for_each_child_of_node(port, child) {
+		u32 reg;
+
+		of_property_read_u32(child, "reg", &reg);
+		if (reg == 0)
+			end_node = child;
+	}
+
+	if (!end_node) {
+		DRM_DEBUG_DRIVER("Missing panel endpoint\n");
+		return ERR_PTR(-ENODEV);
+	}
+
+	remote = of_graph_get_remote_port_parent(end_node);
+	if (!remote) {
+		DRM_DEBUG_DRIVER("Unable to parse remote node\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	return of_drm_find_panel(remote) ?: ERR_PTR(-EPROBE_DEFER);
+}
+
+static int sun4i_tcon_bind(struct device *dev, struct device *master,
+			   void *data)
+{
+	struct drm_device *drm = data;
+	struct sun4i_drv *drv = drm->dev_private;
+	struct sun4i_tcon *tcon;
+	int ret;
+
+	tcon = devm_kzalloc(dev, sizeof(*tcon), GFP_KERNEL);
+	if (!tcon)
+		return -ENOMEM;
+	dev_set_drvdata(dev, tcon);
+	drv->tcon = tcon;
+	tcon->drm = drm;
+
+	if (of_device_is_compatible(dev->of_node, "allwinner,sun5i-a13-tcon"))
+		tcon->has_mux = true;
+
+	tcon->lcd_rst = devm_reset_control_get(dev, "lcd");
+	if (IS_ERR(tcon->lcd_rst)) {
+		dev_err(dev, "Couldn't get our reset line\n");
+		return PTR_ERR(tcon->lcd_rst);
+	}
+
+	/* Make sure our TCON is reset */
+	if (!reset_control_status(tcon->lcd_rst))
+		reset_control_assert(tcon->lcd_rst);
+
+	ret = reset_control_deassert(tcon->lcd_rst);
+	if (ret) {
+		dev_err(dev, "Couldn't deassert our reset line\n");
+		return ret;
+	}
+
+	ret = sun4i_tcon_init_regmap(dev, tcon);
+	if (ret) {
+		dev_err(dev, "Couldn't init our TCON regmap\n");
+		goto err_assert_reset;
+	}
+
+	ret = sun4i_tcon_init_clocks(dev, tcon);
+	if (ret) {
+		dev_err(dev, "Couldn't init our TCON clocks\n");
+		goto err_assert_reset;
+	}
+
+	ret = sun4i_tcon_init_irq(dev, tcon);
+	if (ret) {
+		dev_err(dev, "Couldn't init our TCON interrupts\n");
+		goto err_free_clocks;
+	}
+
+	tcon->panel = sun4i_tcon_find_panel(dev->of_node);
+	if (IS_ERR(tcon->panel)) {
+		dev_info(dev, "No panel found... RGB output disabled\n");
+		return 0;
+	}
+
+	ret = sun4i_rgb_init(drm);
+	if (ret < 0)
+		goto err_free_clocks;
+
+	return 0;
+
+err_free_clocks:
+	sun4i_tcon_free_clocks(tcon);
+err_assert_reset:
+	reset_control_assert(tcon->lcd_rst);
+	return ret;
+}
+
+static void sun4i_tcon_unbind(struct device *dev, struct device *master,
+			      void *data)
+{
+	struct sun4i_tcon *tcon = dev_get_drvdata(dev);
+
+	sun4i_tcon_free_clocks(tcon);
+}
+
+static struct component_ops sun4i_tcon_ops = {
+	.bind	= sun4i_tcon_bind,
+	.unbind	= sun4i_tcon_unbind,
+};
+
+static int sun4i_tcon_probe(struct platform_device *pdev)
+{
+	struct device_node *node = pdev->dev.of_node;
+	struct drm_panel *panel;
+
+	/*
+	 * The panel is not ready.
+	 * Defer the probe.
+	 */
+	panel = sun4i_tcon_find_panel(node);
+
+	/*
+	 * If we don't have a panel endpoint, just go on
+	 */
+	if (PTR_ERR(panel) == -EPROBE_DEFER) {
+		DRM_DEBUG_DRIVER("Still waiting for our panel. Deferring...\n");
+		return -EPROBE_DEFER;
+	}
+
+	return component_add(&pdev->dev, &sun4i_tcon_ops);
+}
+
+static int sun4i_tcon_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &sun4i_tcon_ops);
+
+	return 0;
+}
+
+static const struct of_device_id sun4i_tcon_of_table[] = {
+	{ .compatible = "allwinner,sun5i-a13-tcon" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, sun4i_tcon_of_table);
+
+static struct platform_driver sun4i_tcon_platform_driver = {
+	.probe		= sun4i_tcon_probe,
+	.remove		= sun4i_tcon_remove,
+	.driver		= {
+		.name		= "sun4i-tcon",
+		.of_match_table	= sun4i_tcon_of_table,
+	},
+};
+module_platform_driver(sun4i_tcon_platform_driver);
+
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
+MODULE_DESCRIPTION("Allwinner A10 Timing Controller Driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/sun4i/sun4i_tcon.h linux-libre-4.7-gnu/drivers/gpu/drm/sun4i/sun4i_tcon.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/sun4i/sun4i_tcon.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/sun4i/sun4i_tcon.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2015 Free Electrons
+ * Copyright (C) 2015 NextThing Co
+ *
+ * Boris Brezillon <boris.brezillon@free-electrons.com>
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#ifndef __SUN4I_TCON_H__
+#define __SUN4I_TCON_H__
+
+#include <drm/drm_crtc.h>
+
+#include <linux/kernel.h>
+#include <linux/reset.h>
+
+#define SUN4I_TCON_GCTL_REG			0x0
+#define SUN4I_TCON_GCTL_TCON_ENABLE			BIT(31)
+#define SUN4I_TCON_GCTL_IOMAP_MASK			BIT(0)
+#define SUN4I_TCON_GCTL_IOMAP_TCON1			(1 << 0)
+#define SUN4I_TCON_GCTL_IOMAP_TCON0			(0 << 0)
+
+#define SUN4I_TCON_GINT0_REG			0x4
+#define SUN4I_TCON_GINT0_VBLANK_ENABLE(pipe)		BIT(31 - (pipe))
+#define SUN4I_TCON_GINT0_VBLANK_INT(pipe)		BIT(15 - (pipe))
+
+#define SUN4I_TCON_GINT1_REG			0x8
+#define SUN4I_TCON_FRM_CTL_REG			0x10
+
+#define SUN4I_TCON0_CTL_REG			0x40
+#define SUN4I_TCON0_CTL_TCON_ENABLE			BIT(31)
+#define SUN4I_TCON0_CTL_CLK_DELAY_MASK			GENMASK(8, 4)
+#define SUN4I_TCON0_CTL_CLK_DELAY(delay)		((delay << 4) & SUN4I_TCON0_CTL_CLK_DELAY_MASK)
+
+#define SUN4I_TCON0_DCLK_REG			0x44
+#define SUN4I_TCON0_DCLK_GATE_BIT			(31)
+#define SUN4I_TCON0_DCLK_DIV_SHIFT			(0)
+#define SUN4I_TCON0_DCLK_DIV_WIDTH			(7)
+
+#define SUN4I_TCON0_BASIC0_REG			0x48
+#define SUN4I_TCON0_BASIC0_X(width)			((((width) - 1) & 0xfff) << 16)
+#define SUN4I_TCON0_BASIC0_Y(height)			(((height) - 1) & 0xfff)
+
+#define SUN4I_TCON0_BASIC1_REG			0x4c
+#define SUN4I_TCON0_BASIC1_H_TOTAL(total)		((((total) - 1) & 0x1fff) << 16)
+#define SUN4I_TCON0_BASIC1_H_BACKPORCH(bp)		(((bp) - 1) & 0xfff)
+
+#define SUN4I_TCON0_BASIC2_REG			0x50
+#define SUN4I_TCON0_BASIC2_V_TOTAL(total)		((((total) * 2) & 0x1fff) << 16)
+#define SUN4I_TCON0_BASIC2_V_BACKPORCH(bp)		(((bp) - 1) & 0xfff)
+
+#define SUN4I_TCON0_BASIC3_REG			0x54
+#define SUN4I_TCON0_BASIC3_H_SYNC(width)		((((width) - 1) & 0x7ff) << 16)
+#define SUN4I_TCON0_BASIC3_V_SYNC(height)		(((height) - 1) & 0x7ff)
+
+#define SUN4I_TCON0_HV_IF_REG			0x58
+#define SUN4I_TCON0_CPU_IF_REG			0x60
+#define SUN4I_TCON0_CPU_WR_REG			0x64
+#define SUN4I_TCON0_CPU_RD0_REG			0x68
+#define SUN4I_TCON0_CPU_RDA_REG			0x6c
+#define SUN4I_TCON0_TTL0_REG			0x70
+#define SUN4I_TCON0_TTL1_REG			0x74
+#define SUN4I_TCON0_TTL2_REG			0x78
+#define SUN4I_TCON0_TTL3_REG			0x7c
+#define SUN4I_TCON0_TTL4_REG			0x80
+#define SUN4I_TCON0_LVDS_IF_REG			0x84
+#define SUN4I_TCON0_IO_POL_REG			0x88
+#define SUN4I_TCON0_IO_POL_DCLK_PHASE(phase)		((phase & 3) << 28)
+#define SUN4I_TCON0_IO_POL_HSYNC_POSITIVE		BIT(25)
+#define SUN4I_TCON0_IO_POL_VSYNC_POSITIVE		BIT(24)
+
+#define SUN4I_TCON0_IO_TRI_REG			0x8c
+#define SUN4I_TCON0_IO_TRI_HSYNC_DISABLE		BIT(25)
+#define SUN4I_TCON0_IO_TRI_VSYNC_DISABLE		BIT(24)
+#define SUN4I_TCON0_IO_TRI_DATA_PINS_DISABLE(pins)	GENMASK(pins, 0)
+
+#define SUN4I_TCON1_CTL_REG			0x90
+#define SUN4I_TCON1_CTL_TCON_ENABLE			BIT(31)
+#define SUN4I_TCON1_CTL_INTERLACE_ENABLE		BIT(20)
+#define SUN4I_TCON1_CTL_CLK_DELAY_MASK			GENMASK(8, 4)
+#define SUN4I_TCON1_CTL_CLK_DELAY(delay)		((delay << 4) & SUN4I_TCON1_CTL_CLK_DELAY_MASK)
+
+#define SUN4I_TCON1_BASIC0_REG			0x94
+#define SUN4I_TCON1_BASIC0_X(width)			((((width) - 1) & 0xfff) << 16)
+#define SUN4I_TCON1_BASIC0_Y(height)			(((height) - 1) & 0xfff)
+
+#define SUN4I_TCON1_BASIC1_REG			0x98
+#define SUN4I_TCON1_BASIC1_X(width)			((((width) - 1) & 0xfff) << 16)
+#define SUN4I_TCON1_BASIC1_Y(height)			(((height) - 1) & 0xfff)
+
+#define SUN4I_TCON1_BASIC2_REG			0x9c
+#define SUN4I_TCON1_BASIC2_X(width)			((((width) - 1) & 0xfff) << 16)
+#define SUN4I_TCON1_BASIC2_Y(height)			(((height) - 1) & 0xfff)
+
+#define SUN4I_TCON1_BASIC3_REG			0xa0
+#define SUN4I_TCON1_BASIC3_H_TOTAL(total)		((((total) - 1) & 0x1fff) << 16)
+#define SUN4I_TCON1_BASIC3_H_BACKPORCH(bp)		(((bp) - 1) & 0xfff)
+
+#define SUN4I_TCON1_BASIC4_REG			0xa4
+#define SUN4I_TCON1_BASIC4_V_TOTAL(total)		(((total) & 0x1fff) << 16)
+#define SUN4I_TCON1_BASIC4_V_BACKPORCH(bp)		(((bp) - 1) & 0xfff)
+
+#define SUN4I_TCON1_BASIC5_REG			0xa8
+#define SUN4I_TCON1_BASIC5_H_SYNC(width)		((((width) - 1) & 0x3ff) << 16)
+#define SUN4I_TCON1_BASIC5_V_SYNC(height)		(((height) - 1) & 0x3ff)
+
+#define SUN4I_TCON1_IO_POL_REG			0xf0
+#define SUN4I_TCON1_IO_TRI_REG			0xf4
+#define SUN4I_TCON_CEU_CTL_REG			0x100
+#define SUN4I_TCON_CEU_MUL_RR_REG		0x110
+#define SUN4I_TCON_CEU_MUL_RG_REG		0x114
+#define SUN4I_TCON_CEU_MUL_RB_REG		0x118
+#define SUN4I_TCON_CEU_ADD_RC_REG		0x11c
+#define SUN4I_TCON_CEU_MUL_GR_REG		0x120
+#define SUN4I_TCON_CEU_MUL_GG_REG		0x124
+#define SUN4I_TCON_CEU_MUL_GB_REG		0x128
+#define SUN4I_TCON_CEU_ADD_GC_REG		0x12c
+#define SUN4I_TCON_CEU_MUL_BR_REG		0x130
+#define SUN4I_TCON_CEU_MUL_BG_REG		0x134
+#define SUN4I_TCON_CEU_MUL_BB_REG		0x138
+#define SUN4I_TCON_CEU_ADD_BC_REG		0x13c
+#define SUN4I_TCON_CEU_RANGE_R_REG		0x140
+#define SUN4I_TCON_CEU_RANGE_G_REG		0x144
+#define SUN4I_TCON_CEU_RANGE_B_REG		0x148
+#define SUN4I_TCON_MUX_CTRL_REG			0x200
+#define SUN4I_TCON1_FILL_CTL_REG		0x300
+#define SUN4I_TCON1_FILL_BEG0_REG		0x304
+#define SUN4I_TCON1_FILL_END0_REG		0x308
+#define SUN4I_TCON1_FILL_DATA0_REG		0x30c
+#define SUN4I_TCON1_FILL_BEG1_REG		0x310
+#define SUN4I_TCON1_FILL_END1_REG		0x314
+#define SUN4I_TCON1_FILL_DATA1_REG		0x318
+#define SUN4I_TCON1_FILL_BEG2_REG		0x31c
+#define SUN4I_TCON1_FILL_END2_REG		0x320
+#define SUN4I_TCON1_FILL_DATA2_REG		0x324
+#define SUN4I_TCON1_GAMMA_TABLE_REG		0x400
+
+#define SUN4I_TCON_MAX_CHANNELS		2
+
+struct sun4i_tcon {
+	struct drm_device		*drm;
+	struct regmap			*regs;
+
+	/* Main bus clock */
+	struct clk			*clk;
+
+	/* Clocks for the TCON channels */
+	struct clk			*sclk0;
+	struct clk			*sclk1;
+
+	/* Pixel clock */
+	struct clk			*dclk;
+
+	/* Reset control */
+	struct reset_control		*lcd_rst;
+
+	/* Platform adjustments */
+	bool				has_mux;
+
+	struct drm_panel		*panel;
+};
+
+/* Global Control */
+void sun4i_tcon_disable(struct sun4i_tcon *tcon);
+void sun4i_tcon_enable(struct sun4i_tcon *tcon);
+
+/* Channel Control */
+void sun4i_tcon_channel_disable(struct sun4i_tcon *tcon, int channel);
+void sun4i_tcon_channel_enable(struct sun4i_tcon *tcon, int channel);
+
+void sun4i_tcon_enable_vblank(struct sun4i_tcon *tcon, bool enable);
+
+/* Mode Related Controls */
+void sun4i_tcon_switch_interlace(struct sun4i_tcon *tcon,
+				 bool enable);
+void sun4i_tcon0_mode_set(struct sun4i_tcon *tcon,
+			  struct drm_display_mode *mode);
+void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
+			  struct drm_display_mode *mode);
+
+#endif /* __SUN4I_TCON_H__ */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/sun4i/sun4i_tv.c linux-libre-4.7-gnu/drivers/gpu/drm/sun4i/sun4i_tv.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/sun4i/sun4i_tv.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/sun4i/sun4i_tv.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,708 @@
+/*
+ * Copyright (C) 2015 Free Electrons
+ * Copyright (C) 2015 NextThing Co
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/of_address.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_panel.h>
+
+#include "sun4i_backend.h"
+#include "sun4i_drv.h"
+#include "sun4i_tcon.h"
+
+#define SUN4I_TVE_EN_REG		0x000
+#define SUN4I_TVE_EN_DAC_MAP_MASK		GENMASK(19, 4)
+#define SUN4I_TVE_EN_DAC_MAP(dac, out)		(((out) & 0xf) << (dac + 1) * 4)
+#define SUN4I_TVE_EN_ENABLE			BIT(0)
+
+#define SUN4I_TVE_CFG0_REG		0x004
+#define SUN4I_TVE_CFG0_DAC_CONTROL_54M		BIT(26)
+#define SUN4I_TVE_CFG0_CORE_DATAPATH_54M	BIT(25)
+#define SUN4I_TVE_CFG0_CORE_CONTROL_54M		BIT(24)
+#define SUN4I_TVE_CFG0_YC_EN			BIT(17)
+#define SUN4I_TVE_CFG0_COMP_EN			BIT(16)
+#define SUN4I_TVE_CFG0_RES(x)			((x) & 0xf)
+#define SUN4I_TVE_CFG0_RES_480i			SUN4I_TVE_CFG0_RES(0)
+#define SUN4I_TVE_CFG0_RES_576i			SUN4I_TVE_CFG0_RES(1)
+
+#define SUN4I_TVE_DAC0_REG		0x008
+#define SUN4I_TVE_DAC0_CLOCK_INVERT		BIT(24)
+#define SUN4I_TVE_DAC0_LUMA(x)			(((x) & 3) << 20)
+#define SUN4I_TVE_DAC0_LUMA_0_4			SUN4I_TVE_DAC0_LUMA(3)
+#define SUN4I_TVE_DAC0_CHROMA(x)		(((x) & 3) << 18)
+#define SUN4I_TVE_DAC0_CHROMA_0_75		SUN4I_TVE_DAC0_CHROMA(3)
+#define SUN4I_TVE_DAC0_INTERNAL_DAC(x)		(((x) & 3) << 16)
+#define SUN4I_TVE_DAC0_INTERNAL_DAC_37_5_OHMS	SUN4I_TVE_DAC0_INTERNAL_DAC(3)
+#define SUN4I_TVE_DAC0_DAC_EN(dac)		BIT(dac)
+
+#define SUN4I_TVE_NOTCH_REG		0x00c
+#define SUN4I_TVE_NOTCH_DAC0_TO_DAC_DLY(dac, x)	((4 - (x)) << (dac * 3))
+
+#define SUN4I_TVE_CHROMA_FREQ_REG	0x010
+
+#define SUN4I_TVE_PORCH_REG		0x014
+#define SUN4I_TVE_PORCH_BACK(x)			((x) << 16)
+#define SUN4I_TVE_PORCH_FRONT(x)		(x)
+
+#define SUN4I_TVE_LINE_REG		0x01c
+#define SUN4I_TVE_LINE_FIRST(x)			((x) << 16)
+#define SUN4I_TVE_LINE_NUMBER(x)		(x)
+
+#define SUN4I_TVE_LEVEL_REG		0x020
+#define SUN4I_TVE_LEVEL_BLANK(x)		((x) << 16)
+#define SUN4I_TVE_LEVEL_BLACK(x)		(x)
+
+#define SUN4I_TVE_DAC1_REG		0x024
+#define SUN4I_TVE_DAC1_AMPLITUDE(dac, x)	((x) << (dac * 8))
+
+#define SUN4I_TVE_DETECT_STA_REG	0x038
+#define SUN4I_TVE_DETECT_STA_DAC(dac)		BIT((dac * 8))
+#define SUN4I_TVE_DETECT_STA_UNCONNECTED		0
+#define SUN4I_TVE_DETECT_STA_CONNECTED			1
+#define SUN4I_TVE_DETECT_STA_GROUND			2
+
+#define SUN4I_TVE_CB_CR_LVL_REG		0x10c
+#define SUN4I_TVE_CB_CR_LVL_CR_BURST(x)		((x) << 8)
+#define SUN4I_TVE_CB_CR_LVL_CB_BURST(x)		(x)
+
+#define SUN4I_TVE_TINT_BURST_PHASE_REG	0x110
+#define SUN4I_TVE_TINT_BURST_PHASE_CHROMA(x)	(x)
+
+#define SUN4I_TVE_BURST_WIDTH_REG	0x114
+#define SUN4I_TVE_BURST_WIDTH_BREEZEWAY(x)	((x) << 16)
+#define SUN4I_TVE_BURST_WIDTH_BURST_WIDTH(x)	((x) << 8)
+#define SUN4I_TVE_BURST_WIDTH_HSYNC_WIDTH(x)	(x)
+
+#define SUN4I_TVE_CB_CR_GAIN_REG	0x118
+#define SUN4I_TVE_CB_CR_GAIN_CR(x)		((x) << 8)
+#define SUN4I_TVE_CB_CR_GAIN_CB(x)		(x)
+
+#define SUN4I_TVE_SYNC_VBI_REG		0x11c
+#define SUN4I_TVE_SYNC_VBI_SYNC(x)		((x) << 16)
+#define SUN4I_TVE_SYNC_VBI_VBLANK(x)		(x)
+
+#define SUN4I_TVE_ACTIVE_LINE_REG	0x124
+#define SUN4I_TVE_ACTIVE_LINE(x)		(x)
+
+#define SUN4I_TVE_CHROMA_REG		0x128
+#define SUN4I_TVE_CHROMA_COMP_GAIN(x)		((x) & 3)
+#define SUN4I_TVE_CHROMA_COMP_GAIN_50		SUN4I_TVE_CHROMA_COMP_GAIN(2)
+
+#define SUN4I_TVE_12C_REG		0x12c
+#define SUN4I_TVE_12C_NOTCH_WIDTH_WIDE		BIT(8)
+#define SUN4I_TVE_12C_COMP_YUV_EN		BIT(0)
+
+#define SUN4I_TVE_RESYNC_REG		0x130
+#define SUN4I_TVE_RESYNC_FIELD			BIT(31)
+#define SUN4I_TVE_RESYNC_LINE(x)		((x) << 16)
+#define SUN4I_TVE_RESYNC_PIXEL(x)		(x)
+
+#define SUN4I_TVE_SLAVE_REG		0x134
+
+#define SUN4I_TVE_WSS_DATA2_REG		0x244
+
+struct color_gains {
+	u16	cb;
+	u16	cr;
+};
+
+struct burst_levels {
+	u16	cb;
+	u16	cr;
+};
+
+struct video_levels {
+	u16	black;
+	u16	blank;
+};
+
+struct resync_parameters {
+	bool	field;
+	u16	line;
+	u16	pixel;
+};
+
+struct tv_mode {
+	char		*name;
+
+	u32		mode;
+	u32		chroma_freq;
+	u16		back_porch;
+	u16		front_porch;
+	u16		line_number;
+	u16		vblank_level;
+
+	u32		hdisplay;
+	u16		hfront_porch;
+	u16		hsync_len;
+	u16		hback_porch;
+
+	u32		vdisplay;
+	u16		vfront_porch;
+	u16		vsync_len;
+	u16		vback_porch;
+
+	bool		yc_en;
+	bool		dac3_en;
+	bool		dac_bit25_en;
+
+	struct color_gains		*color_gains;
+	struct burst_levels		*burst_levels;
+	struct video_levels		*video_levels;
+	struct resync_parameters	*resync_params;
+};
+
+struct sun4i_tv {
+	struct drm_connector	connector;
+	struct drm_encoder	encoder;
+
+	struct clk		*clk;
+	struct regmap		*regs;
+	struct reset_control	*reset;
+
+	struct sun4i_drv	*drv;
+};
+
+struct video_levels ntsc_video_levels = {
+	.black = 282,	.blank = 240,
+};
+
+struct video_levels pal_video_levels = {
+	.black = 252,	.blank = 252,
+};
+
+struct burst_levels ntsc_burst_levels = {
+	.cb = 79,	.cr = 0,
+};
+
+struct burst_levels pal_burst_levels = {
+	.cb = 40,	.cr = 40,
+};
+
+struct color_gains ntsc_color_gains = {
+	.cb = 160,	.cr = 160,
+};
+
+struct color_gains pal_color_gains = {
+	.cb = 224,	.cr = 224,
+};
+
+struct resync_parameters ntsc_resync_parameters = {
+	.field = false,	.line = 14,	.pixel = 12,
+};
+
+struct resync_parameters pal_resync_parameters = {
+	.field = true,	.line = 13,	.pixel = 12,
+};
+
+struct tv_mode tv_modes[] = {
+	{
+		.name		= "NTSC",
+		.mode		= SUN4I_TVE_CFG0_RES_480i,
+		.chroma_freq	= 0x21f07c1f,
+		.yc_en		= true,
+		.dac3_en	= true,
+		.dac_bit25_en	= true,
+
+		.back_porch	= 118,
+		.front_porch	= 32,
+		.line_number	= 525,
+
+		.hdisplay	= 720,
+		.hfront_porch	= 18,
+		.hsync_len	= 2,
+		.hback_porch	= 118,
+
+		.vdisplay	= 480,
+		.vfront_porch	= 26,
+		.vsync_len	= 2,
+		.vback_porch	= 17,
+
+		.vblank_level	= 240,
+
+		.color_gains	= &ntsc_color_gains,
+		.burst_levels	= &ntsc_burst_levels,
+		.video_levels	= &ntsc_video_levels,
+		.resync_params	= &ntsc_resync_parameters,
+	},
+	{
+		.name		= "PAL",
+		.mode		= SUN4I_TVE_CFG0_RES_576i,
+		.chroma_freq	= 0x2a098acb,
+
+		.back_porch	= 138,
+		.front_porch	= 24,
+		.line_number	= 625,
+
+		.hdisplay	= 720,
+		.hfront_porch	= 3,
+		.hsync_len	= 2,
+		.hback_porch	= 139,
+
+		.vdisplay	= 576,
+		.vfront_porch	= 28,
+		.vsync_len	= 2,
+		.vback_porch	= 19,
+
+		.vblank_level	= 252,
+
+		.color_gains	= &pal_color_gains,
+		.burst_levels	= &pal_burst_levels,
+		.video_levels	= &pal_video_levels,
+		.resync_params	= &pal_resync_parameters,
+	},
+};
+
+static inline struct sun4i_tv *
+drm_encoder_to_sun4i_tv(struct drm_encoder *encoder)
+{
+	return container_of(encoder, struct sun4i_tv,
+			    encoder);
+}
+
+static inline struct sun4i_tv *
+drm_connector_to_sun4i_tv(struct drm_connector *connector)
+{
+	return container_of(connector, struct sun4i_tv,
+			    connector);
+}
+
+/*
+ * FIXME: If only the drm_display_mode private field was usable, this
+ * could go away...
+ *
+ * So far, it doesn't seem to be preserved when the mode is passed by
+ * to mode_set for some reason.
+ */
+static struct tv_mode *sun4i_tv_find_tv_by_mode(struct drm_display_mode *mode)
+{
+	int i;
+
+	/* First try to identify the mode by name */
+	for (i = 0; i < ARRAY_SIZE(tv_modes); i++) {
+		struct tv_mode *tv_mode = &tv_modes[i];
+
+		DRM_DEBUG_DRIVER("Comparing mode %s vs %s",
+				 mode->name, tv_mode->name);
+
+		if (!strcmp(mode->name, tv_mode->name))
+			return tv_mode;
+	}
+
+	/* Then by number of lines */
+	for (i = 0; i < ARRAY_SIZE(tv_modes); i++) {
+		struct tv_mode *tv_mode = &tv_modes[i];
+
+		DRM_DEBUG_DRIVER("Comparing mode %s vs %s (X: %d vs %d)",
+				 mode->name, tv_mode->name,
+				 mode->vdisplay, tv_mode->vdisplay);
+
+		if (mode->vdisplay == tv_mode->vdisplay)
+			return tv_mode;
+	}
+
+	return NULL;
+}
+
+static void sun4i_tv_mode_to_drm_mode(struct tv_mode *tv_mode,
+				      struct drm_display_mode *mode)
+{
+	DRM_DEBUG_DRIVER("Creating mode %s\n", mode->name);
+
+	mode->type = DRM_MODE_TYPE_DRIVER;
+	mode->clock = 13500;
+	mode->flags = DRM_MODE_FLAG_INTERLACE;
+
+	mode->hdisplay = tv_mode->hdisplay;
+	mode->hsync_start = mode->hdisplay + tv_mode->hfront_porch;
+	mode->hsync_end = mode->hsync_start + tv_mode->hsync_len;
+	mode->htotal = mode->hsync_end  + tv_mode->hback_porch;
+
+	mode->vdisplay = tv_mode->vdisplay;
+	mode->vsync_start = mode->vdisplay + tv_mode->vfront_porch;
+	mode->vsync_end = mode->vsync_start + tv_mode->vsync_len;
+	mode->vtotal = mode->vsync_end  + tv_mode->vback_porch;
+}
+
+static int sun4i_tv_atomic_check(struct drm_encoder *encoder,
+				 struct drm_crtc_state *crtc_state,
+				 struct drm_connector_state *conn_state)
+{
+	return 0;
+}
+
+static void sun4i_tv_disable(struct drm_encoder *encoder)
+{
+	struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder);
+	struct sun4i_drv *drv = tv->drv;
+	struct sun4i_tcon *tcon = drv->tcon;
+
+	DRM_DEBUG_DRIVER("Disabling the TV Output\n");
+
+	sun4i_tcon_channel_disable(tcon, 1);
+
+	regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG,
+			   SUN4I_TVE_EN_ENABLE,
+			   0);
+	sun4i_backend_disable_color_correction(drv->backend);
+}
+
+static void sun4i_tv_enable(struct drm_encoder *encoder)
+{
+	struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder);
+	struct sun4i_drv *drv = tv->drv;
+	struct sun4i_tcon *tcon = drv->tcon;
+
+	DRM_DEBUG_DRIVER("Enabling the TV Output\n");
+
+	sun4i_backend_apply_color_correction(drv->backend);
+
+	regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG,
+			   SUN4I_TVE_EN_ENABLE,
+			   SUN4I_TVE_EN_ENABLE);
+
+	sun4i_tcon_channel_enable(tcon, 1);
+}
+
+static void sun4i_tv_mode_set(struct drm_encoder *encoder,
+			      struct drm_display_mode *mode,
+			      struct drm_display_mode *adjusted_mode)
+{
+	struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder);
+	struct sun4i_drv *drv = tv->drv;
+	struct sun4i_tcon *tcon = drv->tcon;
+	struct tv_mode *tv_mode = sun4i_tv_find_tv_by_mode(mode);
+
+	sun4i_tcon1_mode_set(tcon, mode);
+
+	/* Enable and map the DAC to the output */
+	regmap_update_bits(tv->regs, SUN4I_TVE_EN_REG,
+			   SUN4I_TVE_EN_DAC_MAP_MASK,
+			   SUN4I_TVE_EN_DAC_MAP(0, 1) |
+			   SUN4I_TVE_EN_DAC_MAP(1, 2) |
+			   SUN4I_TVE_EN_DAC_MAP(2, 3) |
+			   SUN4I_TVE_EN_DAC_MAP(3, 4));
+
+	/* Set PAL settings */
+	regmap_write(tv->regs, SUN4I_TVE_CFG0_REG,
+		     tv_mode->mode |
+		     (tv_mode->yc_en ? SUN4I_TVE_CFG0_YC_EN : 0) |
+		     SUN4I_TVE_CFG0_COMP_EN |
+		     SUN4I_TVE_CFG0_DAC_CONTROL_54M |
+		     SUN4I_TVE_CFG0_CORE_DATAPATH_54M |
+		     SUN4I_TVE_CFG0_CORE_CONTROL_54M);
+
+	/* Configure the DAC for a composite output */
+	regmap_write(tv->regs, SUN4I_TVE_DAC0_REG,
+		     SUN4I_TVE_DAC0_DAC_EN(0) |
+		     (tv_mode->dac3_en ? SUN4I_TVE_DAC0_DAC_EN(3) : 0) |
+		     SUN4I_TVE_DAC0_INTERNAL_DAC_37_5_OHMS |
+		     SUN4I_TVE_DAC0_CHROMA_0_75 |
+		     SUN4I_TVE_DAC0_LUMA_0_4 |
+		     SUN4I_TVE_DAC0_CLOCK_INVERT |
+		     (tv_mode->dac_bit25_en ? BIT(25) : 0) |
+		     BIT(30));
+
+	/* Configure the sample delay between DAC0 and the other DAC */
+	regmap_write(tv->regs, SUN4I_TVE_NOTCH_REG,
+		     SUN4I_TVE_NOTCH_DAC0_TO_DAC_DLY(1, 0) |
+		     SUN4I_TVE_NOTCH_DAC0_TO_DAC_DLY(2, 0));
+
+	regmap_write(tv->regs, SUN4I_TVE_CHROMA_FREQ_REG,
+		     tv_mode->chroma_freq);
+
+	/* Set the front and back porch */
+	regmap_write(tv->regs, SUN4I_TVE_PORCH_REG,
+		     SUN4I_TVE_PORCH_BACK(tv_mode->back_porch) |
+		     SUN4I_TVE_PORCH_FRONT(tv_mode->front_porch));
+
+	/* Set the lines setup */
+	regmap_write(tv->regs, SUN4I_TVE_LINE_REG,
+		     SUN4I_TVE_LINE_FIRST(22) |
+		     SUN4I_TVE_LINE_NUMBER(tv_mode->line_number));
+
+	regmap_write(tv->regs, SUN4I_TVE_LEVEL_REG,
+		     SUN4I_TVE_LEVEL_BLANK(tv_mode->video_levels->blank) |
+		     SUN4I_TVE_LEVEL_BLACK(tv_mode->video_levels->black));
+
+	regmap_write(tv->regs, SUN4I_TVE_DAC1_REG,
+		     SUN4I_TVE_DAC1_AMPLITUDE(0, 0x18) |
+		     SUN4I_TVE_DAC1_AMPLITUDE(1, 0x18) |
+		     SUN4I_TVE_DAC1_AMPLITUDE(2, 0x18) |
+		     SUN4I_TVE_DAC1_AMPLITUDE(3, 0x18));
+
+	regmap_write(tv->regs, SUN4I_TVE_CB_CR_LVL_REG,
+		     SUN4I_TVE_CB_CR_LVL_CB_BURST(tv_mode->burst_levels->cb) |
+		     SUN4I_TVE_CB_CR_LVL_CR_BURST(tv_mode->burst_levels->cr));
+
+	/* Set burst width for a composite output */
+	regmap_write(tv->regs, SUN4I_TVE_BURST_WIDTH_REG,
+		     SUN4I_TVE_BURST_WIDTH_HSYNC_WIDTH(126) |
+		     SUN4I_TVE_BURST_WIDTH_BURST_WIDTH(68) |
+		     SUN4I_TVE_BURST_WIDTH_BREEZEWAY(22));
+
+	regmap_write(tv->regs, SUN4I_TVE_CB_CR_GAIN_REG,
+		     SUN4I_TVE_CB_CR_GAIN_CB(tv_mode->color_gains->cb) |
+		     SUN4I_TVE_CB_CR_GAIN_CR(tv_mode->color_gains->cr));
+
+	regmap_write(tv->regs, SUN4I_TVE_SYNC_VBI_REG,
+		     SUN4I_TVE_SYNC_VBI_SYNC(0x10) |
+		     SUN4I_TVE_SYNC_VBI_VBLANK(tv_mode->vblank_level));
+
+	regmap_write(tv->regs, SUN4I_TVE_ACTIVE_LINE_REG,
+		     SUN4I_TVE_ACTIVE_LINE(1440));
+
+	/* Set composite chroma gain to 50 % */
+	regmap_write(tv->regs, SUN4I_TVE_CHROMA_REG,
+		     SUN4I_TVE_CHROMA_COMP_GAIN_50);
+
+	regmap_write(tv->regs, SUN4I_TVE_12C_REG,
+		     SUN4I_TVE_12C_COMP_YUV_EN |
+		     SUN4I_TVE_12C_NOTCH_WIDTH_WIDE);
+
+	regmap_write(tv->regs, SUN4I_TVE_RESYNC_REG,
+		     SUN4I_TVE_RESYNC_PIXEL(tv_mode->resync_params->pixel) |
+		     SUN4I_TVE_RESYNC_LINE(tv_mode->resync_params->line) |
+		     (tv_mode->resync_params->field ?
+		      SUN4I_TVE_RESYNC_FIELD : 0));
+
+	regmap_write(tv->regs, SUN4I_TVE_SLAVE_REG, 0);
+
+	clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000);
+}
+
+static struct drm_encoder_helper_funcs sun4i_tv_helper_funcs = {
+	.atomic_check	= sun4i_tv_atomic_check,
+	.disable	= sun4i_tv_disable,
+	.enable		= sun4i_tv_enable,
+	.mode_set	= sun4i_tv_mode_set,
+};
+
+static void sun4i_tv_destroy(struct drm_encoder *encoder)
+{
+	drm_encoder_cleanup(encoder);
+}
+
+static struct drm_encoder_funcs sun4i_tv_funcs = {
+	.destroy	= sun4i_tv_destroy,
+};
+
+static int sun4i_tv_comp_get_modes(struct drm_connector *connector)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(tv_modes); i++) {
+		struct drm_display_mode *mode = drm_mode_create(connector->dev);
+		struct tv_mode *tv_mode = &tv_modes[i];
+
+		strcpy(mode->name, tv_mode->name);
+
+		sun4i_tv_mode_to_drm_mode(tv_mode, mode);
+		drm_mode_probed_add(connector, mode);
+	}
+
+	return i;
+}
+
+static int sun4i_tv_comp_mode_valid(struct drm_connector *connector,
+				    struct drm_display_mode *mode)
+{
+	/* TODO */
+	return MODE_OK;
+}
+
+static struct drm_encoder *
+sun4i_tv_comp_best_encoder(struct drm_connector *connector)
+{
+	struct sun4i_tv *tv = drm_connector_to_sun4i_tv(connector);
+
+	return &tv->encoder;
+}
+
+static struct drm_connector_helper_funcs sun4i_tv_comp_connector_helper_funcs = {
+	.get_modes	= sun4i_tv_comp_get_modes,
+	.mode_valid	= sun4i_tv_comp_mode_valid,
+	.best_encoder	= sun4i_tv_comp_best_encoder,
+};
+
+static enum drm_connector_status
+sun4i_tv_comp_connector_detect(struct drm_connector *connector, bool force)
+{
+	return connector_status_connected;
+}
+
+static void
+sun4i_tv_comp_connector_destroy(struct drm_connector *connector)
+{
+	drm_connector_cleanup(connector);
+}
+
+static struct drm_connector_funcs sun4i_tv_comp_connector_funcs = {
+	.dpms			= drm_atomic_helper_connector_dpms,
+	.detect			= sun4i_tv_comp_connector_detect,
+	.fill_modes		= drm_helper_probe_single_connector_modes,
+	.destroy		= sun4i_tv_comp_connector_destroy,
+	.reset			= drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state	= drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
+};
+
+static struct regmap_config sun4i_tv_regmap_config = {
+	.reg_bits	= 32,
+	.val_bits	= 32,
+	.reg_stride	= 4,
+	.max_register	= SUN4I_TVE_WSS_DATA2_REG,
+	.name		= "tv-encoder",
+};
+
+static int sun4i_tv_bind(struct device *dev, struct device *master,
+			 void *data)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct drm_device *drm = data;
+	struct sun4i_drv *drv = drm->dev_private;
+	struct sun4i_tv *tv;
+	struct resource *res;
+	void __iomem *regs;
+	int ret;
+
+	tv = devm_kzalloc(dev, sizeof(*tv), GFP_KERNEL);
+	if (!tv)
+		return -ENOMEM;
+	tv->drv = drv;
+	dev_set_drvdata(dev, tv);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(regs)) {
+		dev_err(dev, "Couldn't map the TV encoder registers\n");
+		return PTR_ERR(regs);
+	}
+
+	tv->regs = devm_regmap_init_mmio(dev, regs,
+					 &sun4i_tv_regmap_config);
+	if (IS_ERR(tv->regs)) {
+		dev_err(dev, "Couldn't create the TV encoder regmap\n");
+		return PTR_ERR(tv->regs);
+	}
+
+	tv->reset = devm_reset_control_get(dev, NULL);
+	if (IS_ERR(tv->reset)) {
+		dev_err(dev, "Couldn't get our reset line\n");
+		return PTR_ERR(tv->reset);
+	}
+
+	ret = reset_control_deassert(tv->reset);
+	if (ret) {
+		dev_err(dev, "Couldn't deassert our reset line\n");
+		return ret;
+	}
+
+	tv->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(tv->clk)) {
+		dev_err(dev, "Couldn't get the TV encoder clock\n");
+		ret = PTR_ERR(tv->clk);
+		goto err_assert_reset;
+	}
+	clk_prepare_enable(tv->clk);
+
+	drm_encoder_helper_add(&tv->encoder,
+			       &sun4i_tv_helper_funcs);
+	ret = drm_encoder_init(drm,
+			       &tv->encoder,
+			       &sun4i_tv_funcs,
+			       DRM_MODE_ENCODER_TVDAC,
+			       NULL);
+	if (ret) {
+		dev_err(dev, "Couldn't initialise the TV encoder\n");
+		goto err_disable_clk;
+	}
+
+	tv->encoder.possible_crtcs = BIT(0);
+
+	drm_connector_helper_add(&tv->connector,
+				 &sun4i_tv_comp_connector_helper_funcs);
+	ret = drm_connector_init(drm, &tv->connector,
+				 &sun4i_tv_comp_connector_funcs,
+				 DRM_MODE_CONNECTOR_Composite);
+	if (ret) {
+		dev_err(dev,
+			"Couldn't initialise the Composite connector\n");
+		goto err_cleanup_connector;
+	}
+	tv->connector.interlace_allowed = true;
+
+	drm_mode_connector_attach_encoder(&tv->connector, &tv->encoder);
+
+	return 0;
+
+err_cleanup_connector:
+	drm_encoder_cleanup(&tv->encoder);
+err_disable_clk:
+	clk_disable_unprepare(tv->clk);
+err_assert_reset:
+	reset_control_assert(tv->reset);
+	return ret;
+}
+
+static void sun4i_tv_unbind(struct device *dev, struct device *master,
+			    void *data)
+{
+	struct sun4i_tv *tv = dev_get_drvdata(dev);
+
+	drm_connector_cleanup(&tv->connector);
+	drm_encoder_cleanup(&tv->encoder);
+	clk_disable_unprepare(tv->clk);
+}
+
+static struct component_ops sun4i_tv_ops = {
+	.bind	= sun4i_tv_bind,
+	.unbind	= sun4i_tv_unbind,
+};
+
+static int sun4i_tv_probe(struct platform_device *pdev)
+{
+	return component_add(&pdev->dev, &sun4i_tv_ops);
+}
+
+static int sun4i_tv_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &sun4i_tv_ops);
+
+	return 0;
+}
+
+static const struct of_device_id sun4i_tv_of_table[] = {
+	{ .compatible = "allwinner,sun4i-a10-tv-encoder" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, sun4i_tv_of_table);
+
+static struct platform_driver sun4i_tv_platform_driver = {
+	.probe		= sun4i_tv_probe,
+	.remove		= sun4i_tv_remove,
+	.driver		= {
+		.name		= "sun4i-tve",
+		.of_match_table	= sun4i_tv_of_table,
+	},
+};
+module_platform_driver(sun4i_tv_platform_driver);
+
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
+MODULE_DESCRIPTION("Allwinner A10 TV Encoder Driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/tegra/dc.c linux-libre-4.7-gnu/drivers/gpu/drm/tegra/dc.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/tegra/dc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/tegra/dc.c	2016-07-24 15:23:50.000000000 -0400
@@ -434,7 +434,7 @@ static void tegra_plane_reset(struct drm
 	struct tegra_plane_state *state;
 
 	if (plane->state)
-		__drm_atomic_helper_plane_destroy_state(plane, plane->state);
+		__drm_atomic_helper_plane_destroy_state(plane->state);
 
 	kfree(plane->state);
 	plane->state = NULL;
@@ -466,7 +466,7 @@ static struct drm_plane_state *tegra_pla
 static void tegra_plane_atomic_destroy_state(struct drm_plane *plane,
 					     struct drm_plane_state *state)
 {
-	__drm_atomic_helper_plane_destroy_state(plane, state);
+	__drm_atomic_helper_plane_destroy_state(state);
 	kfree(state);
 }
 
@@ -998,7 +998,7 @@ static void tegra_crtc_reset(struct drm_
 	struct tegra_dc_state *state;
 
 	if (crtc->state)
-		__drm_atomic_helper_crtc_destroy_state(crtc, crtc->state);
+		__drm_atomic_helper_crtc_destroy_state(crtc->state);
 
 	kfree(crtc->state);
 	crtc->state = NULL;
@@ -1034,7 +1034,7 @@ tegra_crtc_atomic_duplicate_state(struct
 static void tegra_crtc_atomic_destroy_state(struct drm_crtc *crtc,
 					    struct drm_crtc_state *state)
 {
-	__drm_atomic_helper_crtc_destroy_state(crtc, state);
+	__drm_atomic_helper_crtc_destroy_state(state);
 	kfree(state);
 }
 
@@ -1722,7 +1722,6 @@ static int tegra_dc_init(struct host1x_c
 	if (err < 0)
 		goto cleanup;
 
-	drm_mode_crtc_set_gamma_size(&dc->base, 256);
 	drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs);
 
 	/*
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/tegra/drm.c linux-libre-4.7-gnu/drivers/gpu/drm/tegra/drm.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/tegra/drm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/tegra/drm.c	2016-07-24 15:23:50.000000000 -0400
@@ -74,7 +74,7 @@ static void tegra_atomic_work(struct wor
 }
 
 static int tegra_atomic_commit(struct drm_device *drm,
-			       struct drm_atomic_state *state, bool async)
+			       struct drm_atomic_state *state, bool nonblock)
 {
 	struct tegra_drm *tegra = drm->dev_private;
 	int err;
@@ -83,7 +83,7 @@ static int tegra_atomic_commit(struct dr
 	if (err)
 		return err;
 
-	/* serialize outstanding asynchronous commits */
+	/* serialize outstanding nonblocking commits */
 	mutex_lock(&tegra->commit.lock);
 	flush_work(&tegra->commit.work);
 
@@ -95,7 +95,7 @@ static int tegra_atomic_commit(struct dr
 
 	drm_atomic_helper_swap_state(drm, state);
 
-	if (async)
+	if (nonblock)
 		tegra_atomic_schedule(tegra, state);
 	else
 		tegra_atomic_complete(tegra, state);
@@ -180,7 +180,6 @@ static int tegra_drm_load(struct drm_dev
 
 	/* syncpoints are used for full 32-bit hardware VBLANK counters */
 	drm->max_vblank_count = 0xffffffff;
-	drm->vblank_disable_allowed = true;
 
 	err = drm_vblank_init(drm, drm->mode_config.num_crtc);
 	if (err < 0)
@@ -268,12 +267,12 @@ static void tegra_drm_lastclose(struct d
 }
 
 static struct host1x_bo *
-host1x_bo_lookup(struct drm_device *drm, struct drm_file *file, u32 handle)
+host1x_bo_lookup(struct drm_file *file, u32 handle)
 {
 	struct drm_gem_object *gem;
 	struct tegra_bo *bo;
 
-	gem = drm_gem_object_lookup(drm, file, handle);
+	gem = drm_gem_object_lookup(file, handle);
 	if (!gem)
 		return NULL;
 
@@ -311,11 +310,11 @@ static int host1x_reloc_copy_from_user(s
 	if (err < 0)
 		return err;
 
-	dest->cmdbuf.bo = host1x_bo_lookup(drm, file, cmdbuf);
+	dest->cmdbuf.bo = host1x_bo_lookup(file, cmdbuf);
 	if (!dest->cmdbuf.bo)
 		return -ENOENT;
 
-	dest->target.bo = host1x_bo_lookup(drm, file, target);
+	dest->target.bo = host1x_bo_lookup(file, target);
 	if (!dest->target.bo)
 		return -ENOENT;
 
@@ -363,7 +362,7 @@ int tegra_drm_submit(struct tegra_drm_co
 			goto fail;
 		}
 
-		bo = host1x_bo_lookup(drm, file, cmdbuf.handle);
+		bo = host1x_bo_lookup(file, cmdbuf.handle);
 		if (!bo) {
 			err = -ENOENT;
 			goto fail;
@@ -463,7 +462,7 @@ static int tegra_gem_mmap(struct drm_dev
 	struct drm_gem_object *gem;
 	struct tegra_bo *bo;
 
-	gem = drm_gem_object_lookup(drm, file, args->handle);
+	gem = drm_gem_object_lookup(file, args->handle);
 	if (!gem)
 		return -EINVAL;
 
@@ -672,7 +671,7 @@ static int tegra_gem_set_tiling(struct d
 		return -EINVAL;
 	}
 
-	gem = drm_gem_object_lookup(drm, file, args->handle);
+	gem = drm_gem_object_lookup(file, args->handle);
 	if (!gem)
 		return -ENOENT;
 
@@ -694,7 +693,7 @@ static int tegra_gem_get_tiling(struct d
 	struct tegra_bo *bo;
 	int err = 0;
 
-	gem = drm_gem_object_lookup(drm, file, args->handle);
+	gem = drm_gem_object_lookup(file, args->handle);
 	if (!gem)
 		return -ENOENT;
 
@@ -736,7 +735,7 @@ static int tegra_gem_set_flags(struct dr
 	if (args->flags & ~DRM_TEGRA_GEM_FLAGS)
 		return -EINVAL;
 
-	gem = drm_gem_object_lookup(drm, file, args->handle);
+	gem = drm_gem_object_lookup(file, args->handle);
 	if (!gem)
 		return -ENOENT;
 
@@ -758,7 +757,7 @@ static int tegra_gem_get_flags(struct dr
 	struct drm_gem_object *gem;
 	struct tegra_bo *bo;
 
-	gem = drm_gem_object_lookup(drm, file, args->handle);
+	gem = drm_gem_object_lookup(file, args->handle);
 	if (!gem)
 		return -ENOENT;
 
@@ -878,7 +877,7 @@ static int tegra_debugfs_framebuffers(st
 		seq_printf(s, "%3d: user size: %d x %d, depth %d, %d bpp, refcount %d\n",
 			   fb->base.id, fb->width, fb->height, fb->depth,
 			   fb->bits_per_pixel,
-			   atomic_read(&fb->refcount.refcount));
+			   drm_framebuffer_read_refcount(fb));
 	}
 
 	mutex_unlock(&drm->mode_config.fb_lock);
@@ -932,7 +931,7 @@ static struct drm_driver tegra_drm_drive
 	.debugfs_cleanup = tegra_debugfs_cleanup,
 #endif
 
-	.gem_free_object = tegra_bo_free_object,
+	.gem_free_object_unlocked = tegra_bo_free_object,
 	.gem_vm_ops = &tegra_bo_vm_ops,
 
 	.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/tegra/drm.h linux-libre-4.7-gnu/drivers/gpu/drm/tegra/drm.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/tegra/drm.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/tegra/drm.h	2016-07-24 15:23:50.000000000 -0400
@@ -121,7 +121,7 @@ struct tegra_dc {
 	spinlock_t lock;
 
 	struct drm_crtc base;
-	int powergate;
+	unsigned int powergate;
 	int pipe;
 
 	struct clk *clk;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/tegra/dsi.c linux-libre-4.7-gnu/drivers/gpu/drm/tegra/dsi.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/tegra/dsi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/tegra/dsi.c	2016-07-24 15:23:50.000000000 -0400
@@ -745,13 +745,17 @@ static void tegra_dsi_soft_reset(struct
 
 static void tegra_dsi_connector_reset(struct drm_connector *connector)
 {
-	struct tegra_dsi_state *state =
-		kzalloc(sizeof(*state), GFP_KERNEL);
+	struct tegra_dsi_state *state = kzalloc(sizeof(*state), GFP_KERNEL);
 
-	if (state) {
+	if (!state)
+		return;
+
+	if (connector->state) {
+		__drm_atomic_helper_connector_destroy_state(connector->state);
 		kfree(connector->state);
-		__drm_atomic_helper_connector_reset(connector, &state->base);
 	}
+
+	__drm_atomic_helper_connector_reset(connector, &state->base);
 }
 
 static struct drm_connector_state *
@@ -764,6 +768,9 @@ tegra_dsi_connector_duplicate_state(stru
 	if (!copy)
 		return NULL;
 
+	__drm_atomic_helper_connector_duplicate_state(connector,
+						      &copy->base);
+
 	return &copy->base;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/tegra/fb.c linux-libre-4.7-gnu/drivers/gpu/drm/tegra/fb.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/tegra/fb.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/tegra/fb.c	2016-07-24 15:23:50.000000000 -0400
@@ -149,7 +149,7 @@ struct drm_framebuffer *tegra_fb_create(
 		unsigned int height = cmd->height / (i ? vsub : 1);
 		unsigned int size, bpp;
 
-		gem = drm_gem_object_lookup(drm, file, cmd->handles[i]);
+		gem = drm_gem_object_lookup(file, cmd->handles[i]);
 		if (!gem) {
 			err = -ENXIO;
 			goto unreference;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/tegra/gem.c linux-libre-4.7-gnu/drivers/gpu/drm/tegra/gem.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/tegra/gem.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/tegra/gem.c	2016-07-24 15:23:50.000000000 -0400
@@ -401,7 +401,7 @@ int tegra_bo_dumb_map_offset(struct drm_
 	struct drm_gem_object *gem;
 	struct tegra_bo *bo;
 
-	gem = drm_gem_object_lookup(drm, file, handle);
+	gem = drm_gem_object_lookup(file, handle);
 	if (!gem) {
 		dev_err(drm->dev, "failed to lookup GEM object\n");
 		return -EINVAL;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/tilcdc/tilcdc_crtc.c linux-libre-4.7-gnu/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/tilcdc/tilcdc_crtc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/tilcdc/tilcdc_crtc.c	2016-07-24 15:23:50.000000000 -0400
@@ -707,7 +707,7 @@ irqreturn_t tilcdc_crtc_irq(struct drm_c
 			event = tilcdc_crtc->event;
 			tilcdc_crtc->event = NULL;
 			if (event)
-				drm_send_vblank_event(dev, 0, event);
+				drm_crtc_send_vblank_event(crtc, event);
 
 			spin_unlock_irqrestore(&dev->event_lock, flags);
 		}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c linux-libre-4.7-gnu/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c	2016-07-24 15:23:50.000000000 -0400
@@ -157,7 +157,7 @@ struct device_node * __init tilcdc_get_o
 	if (!overlay_data || kfree_table_add(kft, overlay_data))
 		return NULL;
 
-	of_fdt_unflatten_tree(overlay_data, &overlay);
+	of_fdt_unflatten_tree(overlay_data, NULL, &overlay);
 	if (!overlay) {
 		pr_warn("%s: Unfattening overlay tree failed\n", __func__);
 		return NULL;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c linux-libre-4.7-gnu/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c	2016-07-24 15:23:50.000000000 -0400
@@ -342,7 +342,7 @@ static int tfp410_probe(struct platform_
 
 	tfp410_mod->gpio = of_get_named_gpio_flags(node, "powerdn-gpio",
 			0, NULL);
-	if (IS_ERR_VALUE(tfp410_mod->gpio)) {
+	if (tfp410_mod->gpio < 0) {
 		dev_warn(&pdev->dev, "No power down GPIO\n");
 	} else {
 		ret = gpio_request(tfp410_mod->gpio, "DVI_PDn");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/ttm/Makefile linux-libre-4.7-gnu/drivers/gpu/drm/ttm/Makefile
--- linux-libre-4.6-gnu/drivers/gpu/drm/ttm/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/ttm/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -2,9 +2,10 @@
 # Makefile for the drm device driver.  This driver provides support for the
 
 ccflags-y := -Iinclude/drm
-ttm-y := ttm_agp_backend.o ttm_memory.o ttm_tt.o ttm_bo.o \
+ttm-y := ttm_memory.o ttm_tt.o ttm_bo.o \
 	ttm_bo_util.o ttm_bo_vm.o ttm_module.o \
 	ttm_object.o ttm_lock.o ttm_execbuf_util.o ttm_page_alloc.o \
 	ttm_bo_manager.o ttm_page_alloc_dma.o
+ttm-$(CONFIG_AGP) += ttm_agp_backend.o
 
 obj-$(CONFIG_DRM_TTM) += ttm.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/ttm/ttm_agp_backend.c linux-libre-4.7-gnu/drivers/gpu/drm/ttm/ttm_agp_backend.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/ttm/ttm_agp_backend.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/ttm/ttm_agp_backend.c	2016-07-24 15:23:50.000000000 -0400
@@ -34,7 +34,6 @@
 #include <drm/ttm/ttm_module.h>
 #include <drm/ttm/ttm_bo_driver.h>
 #include <drm/ttm/ttm_page_alloc.h>
-#ifdef TTM_HAS_AGP
 #include <drm/ttm/ttm_placement.h>
 #include <linux/agp_backend.h>
 #include <linux/module.h>
@@ -148,5 +147,3 @@ void ttm_agp_tt_unpopulate(struct ttm_tt
 	ttm_pool_unpopulate(ttm);
 }
 EXPORT_SYMBOL(ttm_agp_tt_unpopulate);
-
-#endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/ttm/ttm_bo.c linux-libre-4.7-gnu/drivers/gpu/drm/ttm/ttm_bo.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/ttm/ttm_bo.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/ttm/ttm_bo.c	2016-07-24 15:23:50.000000000 -0400
@@ -164,7 +164,6 @@ static void ttm_bo_release_list(struct k
 void ttm_bo_add_to_lru(struct ttm_buffer_object *bo)
 {
 	struct ttm_bo_device *bdev = bo->bdev;
-	struct ttm_mem_type_manager *man;
 
 	lockdep_assert_held(&bo->resv->lock.base);
 
@@ -172,12 +171,11 @@ void ttm_bo_add_to_lru(struct ttm_buffer
 
 		BUG_ON(!list_empty(&bo->lru));
 
-		man = &bdev->man[bo->mem.mem_type];
-		list_add_tail(&bo->lru, &man->lru);
+		list_add(&bo->lru, bdev->driver->lru_tail(bo));
 		kref_get(&bo->list_kref);
 
 		if (bo->ttm && !(bo->ttm->page_flags & TTM_PAGE_FLAG_SG)) {
-			list_add_tail(&bo->swap, &bo->glob->swap_lru);
+			list_add(&bo->swap, bdev->driver->swap_lru_tail(bo));
 			kref_get(&bo->list_kref);
 		}
 	}
@@ -186,8 +184,12 @@ EXPORT_SYMBOL(ttm_bo_add_to_lru);
 
 int ttm_bo_del_from_lru(struct ttm_buffer_object *bo)
 {
+	struct ttm_bo_device *bdev = bo->bdev;
 	int put_count = 0;
 
+	if (bdev->driver->lru_removal)
+		bdev->driver->lru_removal(bo);
+
 	if (!list_empty(&bo->swap)) {
 		list_del_init(&bo->swap);
 		++put_count;
@@ -197,11 +199,6 @@ int ttm_bo_del_from_lru(struct ttm_buffe
 		++put_count;
 	}
 
-	/*
-	 * TODO: Add a driver hook to delete from
-	 * driver-specific LRU's here.
-	 */
-
 	return put_count;
 }
 
@@ -230,16 +227,32 @@ EXPORT_SYMBOL(ttm_bo_del_sub_from_lru);
 
 void ttm_bo_move_to_lru_tail(struct ttm_buffer_object *bo)
 {
+	struct ttm_bo_device *bdev = bo->bdev;
 	int put_count = 0;
 
 	lockdep_assert_held(&bo->resv->lock.base);
 
+	if (bdev->driver->lru_removal)
+		bdev->driver->lru_removal(bo);
+
 	put_count = ttm_bo_del_from_lru(bo);
 	ttm_bo_list_ref_sub(bo, put_count, true);
 	ttm_bo_add_to_lru(bo);
 }
 EXPORT_SYMBOL(ttm_bo_move_to_lru_tail);
 
+struct list_head *ttm_bo_default_lru_tail(struct ttm_buffer_object *bo)
+{
+	return bo->bdev->man[bo->mem.mem_type].lru.prev;
+}
+EXPORT_SYMBOL(ttm_bo_default_lru_tail);
+
+struct list_head *ttm_bo_default_swap_lru_tail(struct ttm_buffer_object *bo)
+{
+	return bo->glob->swap_lru.prev;
+}
+EXPORT_SYMBOL(ttm_bo_default_swap_lru_tail);
+
 /*
  * Call bo->mutex locked.
  */
@@ -443,10 +456,10 @@ static void ttm_bo_cleanup_refs_or_queue
 	int ret;
 
 	spin_lock(&glob->lru_lock);
-	ret = __ttm_bo_reserve(bo, false, true, false, NULL);
+	ret = __ttm_bo_reserve(bo, false, true, NULL);
 
 	if (!ret) {
-		if (!ttm_bo_wait(bo, false, false, true)) {
+		if (!ttm_bo_wait(bo, false, true)) {
 			put_count = ttm_bo_del_from_lru(bo);
 
 			spin_unlock(&glob->lru_lock);
@@ -499,7 +512,7 @@ static int ttm_bo_cleanup_refs_and_unloc
 	int put_count;
 	int ret;
 
-	ret = ttm_bo_wait(bo, false, false, true);
+	ret = ttm_bo_wait(bo, false, true);
 
 	if (ret && !no_wait_gpu) {
 		long lret;
@@ -517,7 +530,7 @@ static int ttm_bo_cleanup_refs_and_unloc
 			return -EBUSY;
 
 		spin_lock(&glob->lru_lock);
-		ret = __ttm_bo_reserve(bo, false, true, false, NULL);
+		ret = __ttm_bo_reserve(bo, false, true, NULL);
 
 		/*
 		 * We raced, and lost, someone else holds the reservation now,
@@ -536,7 +549,7 @@ static int ttm_bo_cleanup_refs_and_unloc
 		 * remove sync_obj with ttm_bo_wait, the wait should be
 		 * finished, and no new wait object should have been added.
 		 */
-		ret = ttm_bo_wait(bo, false, false, true);
+		ret = ttm_bo_wait(bo, false, true);
 		WARN_ON(ret);
 	}
 
@@ -586,11 +599,10 @@ static int ttm_bo_delayed_delete(struct
 			kref_get(&nentry->list_kref);
 		}
 
-		ret = __ttm_bo_reserve(entry, false, true, false, NULL);
+		ret = __ttm_bo_reserve(entry, false, true, NULL);
 		if (remove_all && ret) {
 			spin_unlock(&glob->lru_lock);
-			ret = __ttm_bo_reserve(entry, false, false,
-					       false, NULL);
+			ret = __ttm_bo_reserve(entry, false, false, NULL);
 			spin_lock(&glob->lru_lock);
 		}
 
@@ -676,7 +688,7 @@ static int ttm_bo_evict(struct ttm_buffe
 	struct ttm_placement placement;
 	int ret = 0;
 
-	ret = ttm_bo_wait(bo, false, interruptible, no_wait_gpu);
+	ret = ttm_bo_wait(bo, interruptible, no_wait_gpu);
 
 	if (unlikely(ret != 0)) {
 		if (ret != -ERESTARTSYS) {
@@ -732,7 +744,7 @@ static int ttm_mem_evict_first(struct tt
 
 	spin_lock(&glob->lru_lock);
 	list_for_each_entry(bo, &man->lru, lru) {
-		ret = __ttm_bo_reserve(bo, false, true, false, NULL);
+		ret = __ttm_bo_reserve(bo, false, true, NULL);
 		if (!ret) {
 			if (place && (place->fpfn || place->lpfn)) {
 				/* Don't evict this BO if it's outside of the
@@ -989,13 +1001,19 @@ static int ttm_bo_move_buffer(struct ttm
 	lockdep_assert_held(&bo->resv->lock.base);
 
 	/*
-	 * FIXME: It's possible to pipeline buffer moves.
-	 * Have the driver move function wait for idle when necessary,
-	 * instead of doing it here.
+	 * Don't wait for the BO on initial allocation. This is important when
+	 * the BO has an imported reservation object.
 	 */
-	ret = ttm_bo_wait(bo, false, interruptible, no_wait_gpu);
-	if (ret)
-		return ret;
+	if (bo->mem.mem_type != TTM_PL_SYSTEM || bo->ttm != NULL) {
+		/*
+		 * FIXME: It's possible to pipeline buffer moves.
+		 * Have the driver move function wait for idle when necessary,
+		 * instead of doing it here.
+		 */
+		ret = ttm_bo_wait(bo, interruptible, no_wait_gpu);
+		if (ret)
+			return ret;
+	}
 	mem.num_pages = bo->num_pages;
 	mem.size = mem.num_pages << PAGE_SHIFT;
 	mem.page_alignment = bo->mem.page_alignment;
@@ -1016,9 +1034,9 @@ out_unlock:
 	return ret;
 }
 
-static bool ttm_bo_mem_compat(struct ttm_placement *placement,
-			      struct ttm_mem_reg *mem,
-			      uint32_t *new_flags)
+bool ttm_bo_mem_compat(struct ttm_placement *placement,
+		       struct ttm_mem_reg *mem,
+		       uint32_t *new_flags)
 {
 	int i;
 
@@ -1050,6 +1068,7 @@ static bool ttm_bo_mem_compat(struct ttm
 
 	return false;
 }
+EXPORT_SYMBOL(ttm_bo_mem_compat);
 
 int ttm_bo_validate(struct ttm_buffer_object *bo,
 			struct ttm_placement *placement,
@@ -1206,7 +1225,7 @@ size_t ttm_bo_acc_size(struct ttm_bo_dev
 	size_t size = 0;
 
 	size += ttm_round_pot(struct_size);
-	size += PAGE_ALIGN(npages * sizeof(void *));
+	size += ttm_round_pot(npages * sizeof(void *));
 	size += ttm_round_pot(sizeof(struct ttm_tt));
 	return size;
 }
@@ -1220,8 +1239,7 @@ size_t ttm_bo_dma_acc_size(struct ttm_bo
 	size_t size = 0;
 
 	size += ttm_round_pot(struct_size);
-	size += PAGE_ALIGN(npages * sizeof(void *));
-	size += PAGE_ALIGN(npages * sizeof(dma_addr_t));
+	size += ttm_round_pot(npages * (2*sizeof(void *) + sizeof(dma_addr_t)));
 	size += ttm_round_pot(sizeof(struct ttm_dma_tt));
 	return size;
 }
@@ -1500,7 +1518,6 @@ int ttm_bo_device_init(struct ttm_bo_dev
 	bdev->dev_mapping = mapping;
 	bdev->glob = glob;
 	bdev->need_dma32 = need_dma32;
-	bdev->val_seq = 0;
 	mutex_lock(&glob->device_list_mutex);
 	list_add_tail(&bdev->device_list, &glob->device_list);
 	mutex_unlock(&glob->device_list_mutex);
@@ -1554,7 +1571,7 @@ void ttm_bo_unmap_virtual(struct ttm_buf
 EXPORT_SYMBOL(ttm_bo_unmap_virtual);
 
 int ttm_bo_wait(struct ttm_buffer_object *bo,
-		bool lazy, bool interruptible, bool no_wait)
+		bool interruptible, bool no_wait)
 {
 	struct reservation_object_list *fobj;
 	struct reservation_object *resv;
@@ -1609,10 +1626,10 @@ int ttm_bo_synccpu_write_grab(struct ttm
 	 * Using ttm_bo_reserve makes sure the lru lists are updated.
 	 */
 
-	ret = ttm_bo_reserve(bo, true, no_wait, false, NULL);
+	ret = ttm_bo_reserve(bo, true, no_wait, NULL);
 	if (unlikely(ret != 0))
 		return ret;
-	ret = ttm_bo_wait(bo, false, true, no_wait);
+	ret = ttm_bo_wait(bo, true, no_wait);
 	if (likely(ret == 0))
 		atomic_inc(&bo->cpu_writers);
 	ttm_bo_unreserve(bo);
@@ -1642,7 +1659,7 @@ static int ttm_bo_swapout(struct ttm_mem
 
 	spin_lock(&glob->lru_lock);
 	list_for_each_entry(bo, &glob->swap_lru, swap) {
-		ret = __ttm_bo_reserve(bo, false, true, false, NULL);
+		ret = __ttm_bo_reserve(bo, false, true, NULL);
 		if (!ret)
 			break;
 	}
@@ -1669,7 +1686,7 @@ static int ttm_bo_swapout(struct ttm_mem
 	 * Wait for GPU, then move to system cached.
 	 */
 
-	ret = ttm_bo_wait(bo, false, false, false);
+	ret = ttm_bo_wait(bo, false, false);
 
 	if (unlikely(ret != 0))
 		goto out;
@@ -1741,7 +1758,7 @@ int ttm_bo_wait_unreserved(struct ttm_bu
 		return -ERESTARTSYS;
 	if (!ww_mutex_is_locked(&bo->resv->lock))
 		goto out_unlock;
-	ret = __ttm_bo_reserve(bo, true, false, false, NULL);
+	ret = __ttm_bo_reserve(bo, true, false, NULL);
 	if (unlikely(ret != 0))
 		goto out_unlock;
 	__ttm_bo_unreserve(bo);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/ttm/ttm_bo_util.c linux-libre-4.7-gnu/drivers/gpu/drm/ttm/ttm_bo_util.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/ttm/ttm_bo_util.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/ttm/ttm_bo_util.c	2016-07-24 15:23:50.000000000 -0400
@@ -645,7 +645,7 @@ int ttm_bo_move_accel_cleanup(struct ttm
 
 	reservation_object_add_excl_fence(bo->resv, fence);
 	if (evict) {
-		ret = ttm_bo_wait(bo, false, false, false);
+		ret = ttm_bo_wait(bo, false, false);
 		if (ret)
 			return ret;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/ttm/ttm_bo_vm.c linux-libre-4.7-gnu/drivers/gpu/drm/ttm/ttm_bo_vm.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/ttm/ttm_bo_vm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/ttm/ttm_bo_vm.c	2016-07-24 15:23:50.000000000 -0400
@@ -54,7 +54,7 @@ static int ttm_bo_vm_fault_idle(struct t
 	/*
 	 * Quick non-stalling check for idle.
 	 */
-	ret = ttm_bo_wait(bo, false, false, true);
+	ret = ttm_bo_wait(bo, false, true);
 	if (likely(ret == 0))
 		goto out_unlock;
 
@@ -68,14 +68,14 @@ static int ttm_bo_vm_fault_idle(struct t
 			goto out_unlock;
 
 		up_read(&vma->vm_mm->mmap_sem);
-		(void) ttm_bo_wait(bo, false, true, false);
+		(void) ttm_bo_wait(bo, true, false);
 		goto out_unlock;
 	}
 
 	/*
 	 * Ordinary wait.
 	 */
-	ret = ttm_bo_wait(bo, false, true, false);
+	ret = ttm_bo_wait(bo, true, false);
 	if (unlikely(ret != 0))
 		ret = (ret != -ERESTARTSYS) ? VM_FAULT_SIGBUS :
 			VM_FAULT_NOPAGE;
@@ -108,7 +108,7 @@ static int ttm_bo_vm_fault(struct vm_are
 	 * for reserve, and if it fails, retry the fault after waiting
 	 * for the buffer to become unreserved.
 	 */
-	ret = ttm_bo_reserve(bo, true, true, false, NULL);
+	ret = ttm_bo_reserve(bo, true, true, NULL);
 	if (unlikely(ret != 0)) {
 		if (ret != -EBUSY)
 			return VM_FAULT_NOPAGE;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/ttm/ttm_execbuf_util.c linux-libre-4.7-gnu/drivers/gpu/drm/ttm/ttm_execbuf_util.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/ttm/ttm_execbuf_util.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/ttm/ttm_execbuf_util.c	2016-07-24 15:23:50.000000000 -0400
@@ -112,8 +112,7 @@ int ttm_eu_reserve_buffers(struct ww_acq
 	list_for_each_entry(entry, list, head) {
 		struct ttm_buffer_object *bo = entry->bo;
 
-		ret = __ttm_bo_reserve(bo, intr, (ticket == NULL), true,
-				       ticket);
+		ret = __ttm_bo_reserve(bo, intr, (ticket == NULL), ticket);
 		if (!ret && unlikely(atomic_read(&bo->cpu_writers) > 0)) {
 			__ttm_bo_unreserve(bo);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/ttm/ttm_page_alloc.c linux-libre-4.7-gnu/drivers/gpu/drm/ttm/ttm_page_alloc.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/ttm/ttm_page_alloc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/ttm/ttm_page_alloc.c	2016-07-24 15:23:50.000000000 -0400
@@ -48,7 +48,7 @@
 #include <drm/ttm/ttm_bo_driver.h>
 #include <drm/ttm/ttm_page_alloc.h>
 
-#ifdef TTM_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
 #include <asm/agp.h>
 #endif
 
@@ -219,7 +219,7 @@ static struct ttm_pool_manager *_manager
 #ifndef CONFIG_X86
 static int set_pages_array_wb(struct page **pages, int addrinarray)
 {
-#ifdef TTM_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
 	int i;
 
 	for (i = 0; i < addrinarray; i++)
@@ -230,7 +230,7 @@ static int set_pages_array_wb(struct pag
 
 static int set_pages_array_wc(struct page **pages, int addrinarray)
 {
-#ifdef TTM_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
 	int i;
 
 	for (i = 0; i < addrinarray; i++)
@@ -241,7 +241,7 @@ static int set_pages_array_wc(struct pag
 
 static int set_pages_array_uc(struct page **pages, int addrinarray)
 {
-#ifdef TTM_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
 	int i;
 
 	for (i = 0; i < addrinarray; i++)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c linux-libre-4.7-gnu/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c	2016-07-24 15:23:50.000000000 -0400
@@ -50,7 +50,7 @@
 #include <linux/kthread.h>
 #include <drm/ttm/ttm_bo_driver.h>
 #include <drm/ttm/ttm_page_alloc.h>
-#ifdef TTM_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
 #include <asm/agp.h>
 #endif
 
@@ -271,7 +271,7 @@ static struct kobj_type ttm_pool_kobj_ty
 #ifndef CONFIG_X86
 static int set_pages_array_wb(struct page **pages, int addrinarray)
 {
-#ifdef TTM_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
 	int i;
 
 	for (i = 0; i < addrinarray; i++)
@@ -282,7 +282,7 @@ static int set_pages_array_wb(struct pag
 
 static int set_pages_array_wc(struct page **pages, int addrinarray)
 {
-#ifdef TTM_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
 	int i;
 
 	for (i = 0; i < addrinarray; i++)
@@ -293,7 +293,7 @@ static int set_pages_array_wc(struct pag
 
 static int set_pages_array_uc(struct page **pages, int addrinarray)
 {
-#ifdef TTM_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
 	int i;
 
 	for (i = 0; i < addrinarray; i++)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/udl/udl_drv.c linux-libre-4.7-gnu/drivers/gpu/drm/udl/udl_drv.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/udl/udl_drv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/udl/udl_drv.c	2016-07-24 15:23:50.000000000 -0400
@@ -94,7 +94,7 @@ static void udl_usb_disconnect(struct us
 	struct drm_device *dev = usb_get_intfdata(interface);
 
 	drm_kms_helper_poll_disable(dev);
-	drm_connector_unplug_all(dev);
+	drm_connector_unregister_all(dev);
 	udl_fbdev_unplug(dev);
 	udl_drop_usb(dev);
 	drm_unplug_dev(dev);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/udl/udl_drv.h linux-libre-4.7-gnu/drivers/gpu/drm/udl/udl_drv.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/udl/udl_drv.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/udl/udl_drv.h	2016-07-24 15:23:50.000000000 -0400
@@ -81,8 +81,6 @@ struct udl_framebuffer {
 	struct drm_framebuffer base;
 	struct udl_gem_object *obj;
 	bool active_16; /* active on the 16-bit channel */
-	int x1, y1, x2, y2; /* dirty rect */
-	spinlock_t dirty_lock;
 };
 
 #define to_udl_fb(x) container_of(x, struct udl_framebuffer, base)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/udl/udl_fb.c linux-libre-4.7-gnu/drivers/gpu/drm/udl/udl_fb.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/udl/udl_fb.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/udl/udl_fb.c	2016-07-24 15:23:50.000000000 -0400
@@ -77,68 +77,6 @@ static uint16_t rgb16(uint32_t col)
 }
 #endif
 
-/*
- * NOTE: fb_defio.c is holding info->fbdefio.mutex
- *   Touching ANY framebuffer memory that triggers a page fault
- *   in fb_defio will cause a deadlock, when it also tries to
- *   grab the same mutex.
- */
-static void udlfb_dpy_deferred_io(struct fb_info *info,
-				  struct list_head *pagelist)
-{
-	struct page *cur;
-	struct fb_deferred_io *fbdefio = info->fbdefio;
-	struct udl_fbdev *ufbdev = info->par;
-	struct drm_device *dev = ufbdev->ufb.base.dev;
-	struct udl_device *udl = dev->dev_private;
-	struct urb *urb;
-	char *cmd;
-	cycles_t start_cycles, end_cycles;
-	int bytes_sent = 0;
-	int bytes_identical = 0;
-	int bytes_rendered = 0;
-
-	if (!fb_defio)
-		return;
-
-	start_cycles = get_cycles();
-
-	urb = udl_get_urb(dev);
-	if (!urb)
-		return;
-
-	cmd = urb->transfer_buffer;
-
-	/* walk the written page list and render each to device */
-	list_for_each_entry(cur, &fbdefio->pagelist, lru) {
-
-		if (udl_render_hline(dev, (ufbdev->ufb.base.bits_per_pixel / 8),
-				     &urb, (char *) info->fix.smem_start,
-				     &cmd, cur->index << PAGE_SHIFT,
-				     cur->index << PAGE_SHIFT,
-				     PAGE_SIZE, &bytes_identical, &bytes_sent))
-			goto error;
-		bytes_rendered += PAGE_SIZE;
-	}
-
-	if (cmd > (char *) urb->transfer_buffer) {
-		/* Send partial buffer remaining before exiting */
-		int len = cmd - (char *) urb->transfer_buffer;
-		udl_submit_urb(dev, urb, len);
-		bytes_sent += len;
-	} else
-		udl_urb_completion(urb);
-
-error:
-	atomic_add(bytes_sent, &udl->bytes_sent);
-	atomic_add(bytes_identical, &udl->bytes_identical);
-	atomic_add(bytes_rendered, &udl->bytes_rendered);
-	end_cycles = get_cycles();
-	atomic_add(((unsigned int) ((end_cycles - start_cycles)
-		    >> 10)), /* Kcycles */
-		   &udl->cpu_kcycles_used);
-}
-
 int udl_handle_damage(struct udl_framebuffer *fb, int x, int y,
 		      int width, int height)
 {
@@ -152,9 +90,6 @@ int udl_handle_damage(struct udl_framebu
 	struct urb *urb;
 	int aligned_x;
 	int bpp = (fb->base.bits_per_pixel / 8);
-	int x2, y2;
-	bool store_for_later = false;
-	unsigned long flags;
 
 	if (!fb->active_16)
 		return 0;
@@ -180,38 +115,6 @@ int udl_handle_damage(struct udl_framebu
 	    (y + height > fb->base.height))
 		return -EINVAL;
 
-	/* if we are in atomic just store the info
-	   can't test inside spin lock */
-	if (in_atomic())
-		store_for_later = true;
-
-	x2 = x + width - 1;
-	y2 = y + height - 1;
-
-	spin_lock_irqsave(&fb->dirty_lock, flags);
-
-	if (fb->y1 < y)
-		y = fb->y1;
-	if (fb->y2 > y2)
-		y2 = fb->y2;
-	if (fb->x1 < x)
-		x = fb->x1;
-	if (fb->x2 > x2)
-		x2 = fb->x2;
-
-	if (store_for_later) {
-		fb->x1 = x;
-		fb->x2 = x2;
-		fb->y1 = y;
-		fb->y2 = y2;
-		spin_unlock_irqrestore(&fb->dirty_lock, flags);
-		return 0;
-	}
-
-	fb->x1 = fb->y1 = INT_MAX;
-	fb->x2 = fb->y2 = 0;
-
-	spin_unlock_irqrestore(&fb->dirty_lock, flags);
 	start_cycles = get_cycles();
 
 	urb = udl_get_urb(dev);
@@ -219,14 +122,14 @@ int udl_handle_damage(struct udl_framebu
 		return 0;
 	cmd = urb->transfer_buffer;
 
-	for (i = y; i <= y2 ; i++) {
+	for (i = y; i < height ; i++) {
 		const int line_offset = fb->base.pitches[0] * i;
 		const int byte_offset = line_offset + (x * bpp);
 		const int dev_byte_offset = (fb->base.width * bpp * i) + (x * bpp);
 		if (udl_render_hline(dev, bpp, &urb,
 				     (char *) fb->obj->vmapping,
 				     &cmd, byte_offset, dev_byte_offset,
-				     (x2 - x + 1) * bpp,
+				     width * bpp,
 				     &bytes_identical, &bytes_sent))
 			goto error;
 	}
@@ -283,36 +186,6 @@ static int udl_fb_mmap(struct fb_info *i
 	return 0;
 }
 
-static void udl_fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{
-	struct udl_fbdev *ufbdev = info->par;
-
-	drm_fb_helper_sys_fillrect(info, rect);
-
-	udl_handle_damage(&ufbdev->ufb, rect->dx, rect->dy, rect->width,
-			  rect->height);
-}
-
-static void udl_fb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
-{
-	struct udl_fbdev *ufbdev = info->par;
-
-	drm_fb_helper_sys_copyarea(info, region);
-
-	udl_handle_damage(&ufbdev->ufb, region->dx, region->dy, region->width,
-			  region->height);
-}
-
-static void udl_fb_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	struct udl_fbdev *ufbdev = info->par;
-
-	drm_fb_helper_sys_imageblit(info, image);
-
-	udl_handle_damage(&ufbdev->ufb, image->dx, image->dy, image->width,
-			  image->height);
-}
-
 /*
  * It's common for several clients to have framebuffer open simultaneously.
  * e.g. both fbcon and X. Makes things interesting.
@@ -339,7 +212,7 @@ static int udl_fb_open(struct fb_info *i
 
 		if (fbdefio) {
 			fbdefio->delay = DL_DEFIO_WRITE_DELAY;
-			fbdefio->deferred_io = udlfb_dpy_deferred_io;
+			fbdefio->deferred_io = drm_fb_helper_deferred_io;
 		}
 
 		info->fbdefio = fbdefio;
@@ -379,9 +252,9 @@ static struct fb_ops udlfb_ops = {
 	.owner = THIS_MODULE,
 	.fb_check_var = drm_fb_helper_check_var,
 	.fb_set_par = drm_fb_helper_set_par,
-	.fb_fillrect = udl_fb_fillrect,
-	.fb_copyarea = udl_fb_copyarea,
-	.fb_imageblit = udl_fb_imageblit,
+	.fb_fillrect = drm_fb_helper_sys_fillrect,
+	.fb_copyarea = drm_fb_helper_sys_copyarea,
+	.fb_imageblit = drm_fb_helper_sys_imageblit,
 	.fb_pan_display = drm_fb_helper_pan_display,
 	.fb_blank = drm_fb_helper_blank,
 	.fb_setcmap = drm_fb_helper_setcmap,
@@ -458,7 +331,6 @@ udl_framebuffer_init(struct drm_device *
 {
 	int ret;
 
-	spin_lock_init(&ufb->dirty_lock);
 	ufb->obj = obj;
 	drm_helper_mode_fill_fb_struct(&ufb->base, mode_cmd);
 	ret = drm_framebuffer_init(dev, &ufb->base, &udlfb_funcs);
@@ -628,7 +500,7 @@ udl_fb_user_fb_create(struct drm_device
 	int ret;
 	uint32_t size;
 
-	obj = drm_gem_object_lookup(dev, file, mode_cmd->handles[0]);
+	obj = drm_gem_object_lookup(file, mode_cmd->handles[0]);
 	if (obj == NULL)
 		return ERR_PTR(-ENOENT);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/udl/udl_gem.c linux-libre-4.7-gnu/drivers/gpu/drm/udl/udl_gem.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/udl/udl_gem.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/udl/udl_gem.c	2016-07-24 15:23:50.000000000 -0400
@@ -217,7 +217,7 @@ int udl_gem_mmap(struct drm_file *file,
 	int ret = 0;
 
 	mutex_lock(&dev->struct_mutex);
-	obj = drm_gem_object_lookup(dev, file, handle);
+	obj = drm_gem_object_lookup(file, handle);
 	if (obj == NULL) {
 		ret = -ENOENT;
 		goto unlock;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/vc4/Kconfig linux-libre-4.7-gnu/drivers/gpu/drm/vc4/Kconfig
--- linux-libre-4.6-gnu/drivers/gpu/drm/vc4/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/vc4/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -5,6 +5,7 @@ config DRM_VC4
 	select DRM_KMS_HELPER
 	select DRM_KMS_CMA_HELPER
 	select DRM_GEM_CMA_HELPER
+	select DRM_PANEL
 	help
 	  Choose this option if you have a system that has a Broadcom
 	  VC4 GPU, such as the Raspberry Pi or other BCM2708/BCM2835.
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/vc4/Makefile linux-libre-4.7-gnu/drivers/gpu/drm/vc4/Makefile
--- linux-libre-4.6-gnu/drivers/gpu/drm/vc4/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/vc4/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -7,6 +7,7 @@ vc4-y := \
 	vc4_bo.o \
 	vc4_crtc.o \
 	vc4_drv.o \
+	vc4_dpi.o \
 	vc4_kms.o \
 	vc4_gem.o \
 	vc4_hdmi.o \
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/vc4/vc4_bo.c linux-libre-4.7-gnu/drivers/gpu/drm/vc4/vc4_bo.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/vc4/vc4_bo.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/vc4/vc4_bo.c	2016-07-24 15:23:50.000000000 -0400
@@ -457,7 +457,7 @@ int vc4_mmap_bo_ioctl(struct drm_device
 	struct drm_vc4_mmap_bo *args = data;
 	struct drm_gem_object *gem_obj;
 
-	gem_obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+	gem_obj = drm_gem_object_lookup(file_priv, args->handle);
 	if (!gem_obj) {
 		DRM_ERROR("Failed to look up GEM BO %d\n", args->handle);
 		return -EINVAL;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/vc4/vc4_crtc.c linux-libre-4.7-gnu/drivers/gpu/drm/vc4/vc4_crtc.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/vc4/vc4_crtc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/vc4/vc4_crtc.c	2016-07-24 15:23:50.000000000 -0400
@@ -49,6 +49,10 @@ struct vc4_crtc {
 	/* Which HVS channel we're using for our CRTC. */
 	int channel;
 
+	u8 lut_r[256];
+	u8 lut_g[256];
+	u8 lut_b[256];
+
 	struct drm_pending_vblank_event *event;
 };
 
@@ -147,6 +151,46 @@ static void vc4_crtc_destroy(struct drm_
 	drm_crtc_cleanup(crtc);
 }
 
+static void
+vc4_crtc_lut_load(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct vc4_dev *vc4 = to_vc4_dev(dev);
+	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+	u32 i;
+
+	/* The LUT memory is laid out with each HVS channel in order,
+	 * each of which takes 256 writes for R, 256 for G, then 256
+	 * for B.
+	 */
+	HVS_WRITE(SCALER_GAMADDR,
+		  SCALER_GAMADDR_AUTOINC |
+		  (vc4_crtc->channel * 3 * crtc->gamma_size));
+
+	for (i = 0; i < crtc->gamma_size; i++)
+		HVS_WRITE(SCALER_GAMDATA, vc4_crtc->lut_r[i]);
+	for (i = 0; i < crtc->gamma_size; i++)
+		HVS_WRITE(SCALER_GAMDATA, vc4_crtc->lut_g[i]);
+	for (i = 0; i < crtc->gamma_size; i++)
+		HVS_WRITE(SCALER_GAMDATA, vc4_crtc->lut_b[i]);
+}
+
+static void
+vc4_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,
+		   uint32_t start, uint32_t size)
+{
+	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+	u32 i;
+
+	for (i = start; i < start + size; i++) {
+		vc4_crtc->lut_r[i] = r[i] >> 8;
+		vc4_crtc->lut_g[i] = g[i] >> 8;
+		vc4_crtc->lut_b[i] = b[i] >> 8;
+	}
+
+	vc4_crtc_lut_load(crtc);
+}
+
 static u32 vc4_get_fifo_full_level(u32 format)
 {
 	static const u32 fifo_len_bytes = 64;
@@ -260,8 +304,14 @@ static void vc4_crtc_mode_set_nofb(struc
 
 	HVS_WRITE(SCALER_DISPBKGNDX(vc4_crtc->channel),
 		  SCALER_DISPBKGND_AUTOHS |
+		  SCALER_DISPBKGND_GAMMA |
 		  (interlace ? SCALER_DISPBKGND_INTERLACE : 0));
 
+	/* Reload the LUT, since the SRAMs would have been disabled if
+	 * all CRTCs had SCALER_DISPBKGND_GAMMA unset at once.
+	 */
+	vc4_crtc_lut_load(crtc);
+
 	if (debug_dump_regs) {
 		DRM_INFO("CRTC %d regs after:\n", drm_crtc_index(crtc));
 		vc4_crtc_dump_regs(vc4_crtc);
@@ -406,14 +456,6 @@ static void vc4_crtc_atomic_flush(struct
 
 	WARN_ON_ONCE(dlist_next - dlist_start != vc4_state->mm.size);
 
-	HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
-		  vc4_state->mm.start);
-
-	if (debug_dump_regs) {
-		DRM_INFO("CRTC %d HVS after:\n", drm_crtc_index(crtc));
-		vc4_hvs_dump_state(dev);
-	}
-
 	if (crtc->state->event) {
 		unsigned long flags;
 
@@ -423,8 +465,20 @@ static void vc4_crtc_atomic_flush(struct
 
 		spin_lock_irqsave(&dev->event_lock, flags);
 		vc4_crtc->event = crtc->state->event;
-		spin_unlock_irqrestore(&dev->event_lock, flags);
 		crtc->state->event = NULL;
+
+		HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
+			  vc4_state->mm.start);
+
+		spin_unlock_irqrestore(&dev->event_lock, flags);
+	} else {
+		HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
+			  vc4_state->mm.start);
+	}
+
+	if (debug_dump_regs) {
+		DRM_INFO("CRTC %d HVS after:\n", drm_crtc_index(crtc));
+		vc4_hvs_dump_state(dev);
 	}
 }
 
@@ -450,12 +504,17 @@ static void vc4_crtc_handle_page_flip(st
 {
 	struct drm_crtc *crtc = &vc4_crtc->base;
 	struct drm_device *dev = crtc->dev;
+	struct vc4_dev *vc4 = to_vc4_dev(dev);
+	struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
+	u32 chan = vc4_crtc->channel;
 	unsigned long flags;
 
 	spin_lock_irqsave(&dev->event_lock, flags);
-	if (vc4_crtc->event) {
+	if (vc4_crtc->event &&
+	    (vc4_state->mm.start == HVS_READ(SCALER_DISPLACTX(chan)))) {
 		drm_crtc_send_vblank_event(crtc, vc4_crtc->event);
 		vc4_crtc->event = NULL;
+		drm_crtc_vblank_put(crtc);
 	}
 	spin_unlock_irqrestore(&dev->event_lock, flags);
 }
@@ -506,6 +565,7 @@ vc4_async_page_flip_complete(struct vc4_
 		spin_unlock_irqrestore(&dev->event_lock, flags);
 	}
 
+	drm_crtc_vblank_put(crtc);
 	drm_framebuffer_unreference(flip_state->fb);
 	kfree(flip_state);
 
@@ -548,6 +608,8 @@ static int vc4_async_page_flip(struct dr
 		return ret;
 	}
 
+	WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+
 	/* Immediately update the plane's legacy fb pointer, so that later
 	 * modeset prep sees the state that will be present when the semaphore
 	 * is released.
@@ -600,7 +662,7 @@ static void vc4_crtc_destroy_state(struc
 
 	}
 
-	__drm_atomic_helper_crtc_destroy_state(crtc, state);
+	__drm_atomic_helper_crtc_destroy_state(state);
 }
 
 static const struct drm_crtc_funcs vc4_crtc_funcs = {
@@ -613,6 +675,7 @@ static const struct drm_crtc_funcs vc4_c
 	.reset = drm_atomic_helper_crtc_reset,
 	.atomic_duplicate_state = vc4_crtc_duplicate_state,
 	.atomic_destroy_state = vc4_crtc_destroy_state,
+	.gamma_set = vc4_crtc_gamma_set,
 };
 
 static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
@@ -711,6 +774,7 @@ static int vc4_crtc_bind(struct device *
 	primary_plane->crtc = crtc;
 	vc4->crtc[drm_crtc_index(crtc)] = vc4_crtc;
 	vc4_crtc->channel = vc4_crtc->data->hvs_channel;
+	drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r));
 
 	/* Set up some arbitrary number of planes.  We're not limited
 	 * by a set number of physical registers, just the space in
@@ -751,6 +815,12 @@ static int vc4_crtc_bind(struct device *
 
 	vc4_set_crtc_possible_masks(drm, crtc);
 
+	for (i = 0; i < crtc->gamma_size; i++) {
+		vc4_crtc->lut_r[i] = i;
+		vc4_crtc->lut_g[i] = i;
+		vc4_crtc->lut_b[i] = i;
+	}
+
 	platform_set_drvdata(pdev, vc4_crtc);
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/vc4/vc4_debugfs.c linux-libre-4.7-gnu/drivers/gpu/drm/vc4/vc4_debugfs.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/vc4/vc4_debugfs.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/vc4/vc4_debugfs.c	2016-07-24 15:23:50.000000000 -0400
@@ -17,6 +17,7 @@
 
 static const struct drm_info_list vc4_debugfs_list[] = {
 	{"bo_stats", vc4_bo_stats_debugfs, 0},
+	{"dpi_regs", vc4_dpi_debugfs_regs, 0},
 	{"hdmi_regs", vc4_hdmi_debugfs_regs, 0},
 	{"hvs_regs", vc4_hvs_debugfs_regs, 0},
 	{"crtc0_regs", vc4_crtc_debugfs_regs, 0, (void *)(uintptr_t)0},
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/vc4/vc4_dpi.c linux-libre-4.7-gnu/drivers/gpu/drm/vc4/vc4_dpi.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/vc4/vc4_dpi.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/vc4/vc4_dpi.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,520 @@
+/*
+ * Copyright (C) 2016 Broadcom Limited
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * DOC: VC4 DPI module
+ *
+ * The VC4 DPI hardware supports MIPI DPI type 4 and Nokia ViSSI
+ * signals, which are routed out to GPIO0-27 with the ALT2 function.
+ */
+
+#include "drm_atomic_helper.h"
+#include "drm_crtc_helper.h"
+#include "drm_edid.h"
+#include "drm_panel.h"
+#include "linux/clk.h"
+#include "linux/component.h"
+#include "linux/of_graph.h"
+#include "linux/of_platform.h"
+#include "vc4_drv.h"
+#include "vc4_regs.h"
+
+#define DPI_C			0x00
+# define DPI_OUTPUT_ENABLE_MODE		BIT(16)
+
+/* The order field takes the incoming 24 bit RGB from the pixel valve
+ * and shuffles the 3 channels.
+ */
+# define DPI_ORDER_MASK			VC4_MASK(15, 14)
+# define DPI_ORDER_SHIFT		14
+# define DPI_ORDER_RGB			0
+# define DPI_ORDER_BGR			1
+# define DPI_ORDER_GRB			2
+# define DPI_ORDER_BRG			3
+
+/* The format field takes the ORDER-shuffled pixel valve data and
+ * formats it onto the output lines.
+ */
+# define DPI_FORMAT_MASK		VC4_MASK(13, 11)
+# define DPI_FORMAT_SHIFT		11
+/* This define is named in the hardware, but actually just outputs 0. */
+# define DPI_FORMAT_9BIT_666_RGB	0
+/* Outputs 00000000rrrrrggggggbbbbb */
+# define DPI_FORMAT_16BIT_565_RGB_1	1
+/* Outputs 000rrrrr00gggggg000bbbbb */
+# define DPI_FORMAT_16BIT_565_RGB_2	2
+/* Outputs 00rrrrr000gggggg00bbbbb0 */
+# define DPI_FORMAT_16BIT_565_RGB_3	3
+/* Outputs 000000rrrrrrggggggbbbbbb */
+# define DPI_FORMAT_18BIT_666_RGB_1	4
+/* Outputs 00rrrrrr00gggggg00bbbbbb */
+# define DPI_FORMAT_18BIT_666_RGB_2	5
+/* Outputs rrrrrrrrggggggggbbbbbbbb */
+# define DPI_FORMAT_24BIT_888_RGB	6
+
+/* Reverses the polarity of the corresponding signal */
+# define DPI_PIXEL_CLK_INVERT		BIT(10)
+# define DPI_HSYNC_INVERT		BIT(9)
+# define DPI_VSYNC_INVERT		BIT(8)
+# define DPI_OUTPUT_ENABLE_INVERT	BIT(7)
+
+/* Outputs the signal the falling clock edge instead of rising. */
+# define DPI_HSYNC_NEGATE		BIT(6)
+# define DPI_VSYNC_NEGATE		BIT(5)
+# define DPI_OUTPUT_ENABLE_NEGATE	BIT(4)
+
+/* Disables the signal */
+# define DPI_HSYNC_DISABLE		BIT(3)
+# define DPI_VSYNC_DISABLE		BIT(2)
+# define DPI_OUTPUT_ENABLE_DISABLE	BIT(1)
+
+/* Power gate to the device, full reset at 0 -> 1 transition */
+# define DPI_ENABLE			BIT(0)
+
+/* All other registers besides DPI_C return the ID */
+#define DPI_ID			0x04
+# define DPI_ID_VALUE		0x00647069
+
+/* General DPI hardware state. */
+struct vc4_dpi {
+	struct platform_device *pdev;
+
+	struct drm_encoder *encoder;
+	struct drm_connector *connector;
+	struct drm_panel *panel;
+
+	void __iomem *regs;
+
+	struct clk *pixel_clock;
+	struct clk *core_clock;
+};
+
+#define DPI_READ(offset) readl(dpi->regs + (offset))
+#define DPI_WRITE(offset, val) writel(val, dpi->regs + (offset))
+
+/* VC4 DPI encoder KMS struct */
+struct vc4_dpi_encoder {
+	struct vc4_encoder base;
+	struct vc4_dpi *dpi;
+};
+
+static inline struct vc4_dpi_encoder *
+to_vc4_dpi_encoder(struct drm_encoder *encoder)
+{
+	return container_of(encoder, struct vc4_dpi_encoder, base.base);
+}
+
+/* VC4 DPI connector KMS struct */
+struct vc4_dpi_connector {
+	struct drm_connector base;
+	struct vc4_dpi *dpi;
+
+	/* Since the connector is attached to just the one encoder,
+	 * this is the reference to it so we can do the best_encoder()
+	 * hook.
+	 */
+	struct drm_encoder *encoder;
+};
+
+static inline struct vc4_dpi_connector *
+to_vc4_dpi_connector(struct drm_connector *connector)
+{
+	return container_of(connector, struct vc4_dpi_connector, base);
+}
+
+#define DPI_REG(reg) { reg, #reg }
+static const struct {
+	u32 reg;
+	const char *name;
+} dpi_regs[] = {
+	DPI_REG(DPI_C),
+	DPI_REG(DPI_ID),
+};
+
+static void vc4_dpi_dump_regs(struct vc4_dpi *dpi)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(dpi_regs); i++) {
+		DRM_INFO("0x%04x (%s): 0x%08x\n",
+			 dpi_regs[i].reg, dpi_regs[i].name,
+			 DPI_READ(dpi_regs[i].reg));
+	}
+}
+
+#ifdef CONFIG_DEBUG_FS
+int vc4_dpi_debugfs_regs(struct seq_file *m, void *unused)
+{
+	struct drm_info_node *node = (struct drm_info_node *)m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct vc4_dev *vc4 = to_vc4_dev(dev);
+	struct vc4_dpi *dpi = vc4->dpi;
+	int i;
+
+	if (!dpi)
+		return 0;
+
+	for (i = 0; i < ARRAY_SIZE(dpi_regs); i++) {
+		seq_printf(m, "%s (0x%04x): 0x%08x\n",
+			   dpi_regs[i].name, dpi_regs[i].reg,
+			   DPI_READ(dpi_regs[i].reg));
+	}
+
+	return 0;
+}
+#endif
+
+static enum drm_connector_status
+vc4_dpi_connector_detect(struct drm_connector *connector, bool force)
+{
+	struct vc4_dpi_connector *vc4_connector =
+		to_vc4_dpi_connector(connector);
+	struct vc4_dpi *dpi = vc4_connector->dpi;
+
+	if (dpi->panel)
+		return connector_status_connected;
+	else
+		return connector_status_disconnected;
+}
+
+static void vc4_dpi_connector_destroy(struct drm_connector *connector)
+{
+	drm_connector_unregister(connector);
+	drm_connector_cleanup(connector);
+}
+
+static int vc4_dpi_connector_get_modes(struct drm_connector *connector)
+{
+	struct vc4_dpi_connector *vc4_connector =
+		to_vc4_dpi_connector(connector);
+	struct vc4_dpi *dpi = vc4_connector->dpi;
+
+	if (dpi->panel)
+		return drm_panel_get_modes(dpi->panel);
+
+	return 0;
+}
+
+static struct drm_encoder *
+vc4_dpi_connector_best_encoder(struct drm_connector *connector)
+{
+	struct vc4_dpi_connector *dpi_connector =
+		to_vc4_dpi_connector(connector);
+	return dpi_connector->encoder;
+}
+
+static const struct drm_connector_funcs vc4_dpi_connector_funcs = {
+	.dpms = drm_atomic_helper_connector_dpms,
+	.detect = vc4_dpi_connector_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = vc4_dpi_connector_destroy,
+	.reset = drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static const struct drm_connector_helper_funcs vc4_dpi_connector_helper_funcs = {
+	.get_modes = vc4_dpi_connector_get_modes,
+	.best_encoder = vc4_dpi_connector_best_encoder,
+};
+
+static struct drm_connector *vc4_dpi_connector_init(struct drm_device *dev,
+						    struct vc4_dpi *dpi)
+{
+	struct drm_connector *connector = NULL;
+	struct vc4_dpi_connector *dpi_connector;
+	int ret = 0;
+
+	dpi_connector = devm_kzalloc(dev->dev, sizeof(*dpi_connector),
+				     GFP_KERNEL);
+	if (!dpi_connector) {
+		ret = -ENOMEM;
+		goto fail;
+	}
+	connector = &dpi_connector->base;
+
+	dpi_connector->encoder = dpi->encoder;
+	dpi_connector->dpi = dpi;
+
+	drm_connector_init(dev, connector, &vc4_dpi_connector_funcs,
+			   DRM_MODE_CONNECTOR_DPI);
+	drm_connector_helper_add(connector, &vc4_dpi_connector_helper_funcs);
+
+	connector->polled = 0;
+	connector->interlace_allowed = 0;
+	connector->doublescan_allowed = 0;
+
+	drm_mode_connector_attach_encoder(connector, dpi->encoder);
+
+	return connector;
+
+ fail:
+	if (connector)
+		vc4_dpi_connector_destroy(connector);
+
+	return ERR_PTR(ret);
+}
+
+static const struct drm_encoder_funcs vc4_dpi_encoder_funcs = {
+	.destroy = drm_encoder_cleanup,
+};
+
+static void vc4_dpi_encoder_disable(struct drm_encoder *encoder)
+{
+	struct vc4_dpi_encoder *vc4_encoder = to_vc4_dpi_encoder(encoder);
+	struct vc4_dpi *dpi = vc4_encoder->dpi;
+
+	drm_panel_disable(dpi->panel);
+
+	clk_disable_unprepare(dpi->pixel_clock);
+
+	drm_panel_unprepare(dpi->panel);
+}
+
+static void vc4_dpi_encoder_enable(struct drm_encoder *encoder)
+{
+	struct drm_display_mode *mode = &encoder->crtc->mode;
+	struct vc4_dpi_encoder *vc4_encoder = to_vc4_dpi_encoder(encoder);
+	struct vc4_dpi *dpi = vc4_encoder->dpi;
+	u32 dpi_c = DPI_ENABLE | DPI_OUTPUT_ENABLE_MODE;
+	int ret;
+
+	ret = drm_panel_prepare(dpi->panel);
+	if (ret) {
+		DRM_ERROR("Panel failed to prepare\n");
+		return;
+	}
+
+	if (dpi->connector->display_info.num_bus_formats) {
+		u32 bus_format = dpi->connector->display_info.bus_formats[0];
+
+		switch (bus_format) {
+		case MEDIA_BUS_FMT_RGB888_1X24:
+			dpi_c |= VC4_SET_FIELD(DPI_FORMAT_24BIT_888_RGB,
+					       DPI_FORMAT);
+			break;
+		case MEDIA_BUS_FMT_BGR888_1X24:
+			dpi_c |= VC4_SET_FIELD(DPI_FORMAT_24BIT_888_RGB,
+					       DPI_FORMAT);
+			dpi_c |= VC4_SET_FIELD(DPI_ORDER_BGR, DPI_ORDER);
+			break;
+		case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
+			dpi_c |= VC4_SET_FIELD(DPI_FORMAT_18BIT_666_RGB_2,
+					       DPI_FORMAT);
+			break;
+		case MEDIA_BUS_FMT_RGB666_1X18:
+			dpi_c |= VC4_SET_FIELD(DPI_FORMAT_18BIT_666_RGB_1,
+					       DPI_FORMAT);
+			break;
+		case MEDIA_BUS_FMT_RGB565_1X16:
+			dpi_c |= VC4_SET_FIELD(DPI_FORMAT_16BIT_565_RGB_3,
+					       DPI_FORMAT);
+			break;
+		default:
+			DRM_ERROR("Unknown media bus format %d\n", bus_format);
+			break;
+		}
+	}
+
+	if (mode->flags & DRM_MODE_FLAG_NHSYNC)
+		dpi_c |= DPI_HSYNC_INVERT;
+	else if (!(mode->flags & DRM_MODE_FLAG_PHSYNC))
+		dpi_c |= DPI_HSYNC_DISABLE;
+
+	if (mode->flags & DRM_MODE_FLAG_NVSYNC)
+		dpi_c |= DPI_VSYNC_INVERT;
+	else if (!(mode->flags & DRM_MODE_FLAG_PVSYNC))
+		dpi_c |= DPI_VSYNC_DISABLE;
+
+	DPI_WRITE(DPI_C, dpi_c);
+
+	ret = clk_set_rate(dpi->pixel_clock, mode->clock * 1000);
+	if (ret)
+		DRM_ERROR("Failed to set clock rate: %d\n", ret);
+
+	ret = clk_prepare_enable(dpi->pixel_clock);
+	if (ret)
+		DRM_ERROR("Failed to set clock rate: %d\n", ret);
+
+	ret = drm_panel_enable(dpi->panel);
+	if (ret) {
+		DRM_ERROR("Panel failed to enable\n");
+		drm_panel_unprepare(dpi->panel);
+		return;
+	}
+}
+
+static const struct drm_encoder_helper_funcs vc4_dpi_encoder_helper_funcs = {
+	.disable = vc4_dpi_encoder_disable,
+	.enable = vc4_dpi_encoder_enable,
+};
+
+static const struct of_device_id vc4_dpi_dt_match[] = {
+	{ .compatible = "brcm,bcm2835-dpi", .data = NULL },
+	{}
+};
+
+/* Walks the OF graph to find the panel node and then asks DRM to look
+ * up the panel.
+ */
+static struct drm_panel *vc4_dpi_get_panel(struct device *dev)
+{
+	struct device_node *endpoint, *panel_node;
+	struct device_node *np = dev->of_node;
+	struct drm_panel *panel;
+
+	endpoint = of_graph_get_next_endpoint(np, NULL);
+	if (!endpoint) {
+		dev_err(dev, "no endpoint to fetch DPI panel\n");
+		return NULL;
+	}
+
+	/* don't proceed if we have an endpoint but no panel_node tied to it */
+	panel_node = of_graph_get_remote_port_parent(endpoint);
+	of_node_put(endpoint);
+	if (!panel_node) {
+		dev_err(dev, "no valid panel node\n");
+		return NULL;
+	}
+
+	panel = of_drm_find_panel(panel_node);
+	of_node_put(panel_node);
+
+	return panel;
+}
+
+static int vc4_dpi_bind(struct device *dev, struct device *master, void *data)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct drm_device *drm = dev_get_drvdata(master);
+	struct vc4_dev *vc4 = to_vc4_dev(drm);
+	struct vc4_dpi *dpi;
+	struct vc4_dpi_encoder *vc4_dpi_encoder;
+	int ret;
+
+	dpi = devm_kzalloc(dev, sizeof(*dpi), GFP_KERNEL);
+	if (!dpi)
+		return -ENOMEM;
+
+	vc4_dpi_encoder = devm_kzalloc(dev, sizeof(*vc4_dpi_encoder),
+				       GFP_KERNEL);
+	if (!vc4_dpi_encoder)
+		return -ENOMEM;
+	vc4_dpi_encoder->base.type = VC4_ENCODER_TYPE_DPI;
+	vc4_dpi_encoder->dpi = dpi;
+	dpi->encoder = &vc4_dpi_encoder->base.base;
+
+	dpi->pdev = pdev;
+	dpi->regs = vc4_ioremap_regs(pdev, 0);
+	if (IS_ERR(dpi->regs))
+		return PTR_ERR(dpi->regs);
+
+	vc4_dpi_dump_regs(dpi);
+
+	if (DPI_READ(DPI_ID) != DPI_ID_VALUE) {
+		dev_err(dev, "Port returned 0x%08x for ID instead of 0x%08x\n",
+			DPI_READ(DPI_ID), DPI_ID_VALUE);
+		return -ENODEV;
+	}
+
+	dpi->core_clock = devm_clk_get(dev, "core");
+	if (IS_ERR(dpi->core_clock)) {
+		ret = PTR_ERR(dpi->core_clock);
+		if (ret != -EPROBE_DEFER)
+			DRM_ERROR("Failed to get core clock: %d\n", ret);
+		return ret;
+	}
+	dpi->pixel_clock = devm_clk_get(dev, "pixel");
+	if (IS_ERR(dpi->pixel_clock)) {
+		ret = PTR_ERR(dpi->pixel_clock);
+		if (ret != -EPROBE_DEFER)
+			DRM_ERROR("Failed to get pixel clock: %d\n", ret);
+		return ret;
+	}
+
+	ret = clk_prepare_enable(dpi->core_clock);
+	if (ret)
+		DRM_ERROR("Failed to turn on core clock: %d\n", ret);
+
+	dpi->panel = vc4_dpi_get_panel(dev);
+
+	drm_encoder_init(drm, dpi->encoder, &vc4_dpi_encoder_funcs,
+			 DRM_MODE_ENCODER_DPI, NULL);
+	drm_encoder_helper_add(dpi->encoder, &vc4_dpi_encoder_helper_funcs);
+
+	dpi->connector = vc4_dpi_connector_init(drm, dpi);
+	if (IS_ERR(dpi->connector)) {
+		ret = PTR_ERR(dpi->connector);
+		goto err_destroy_encoder;
+	}
+
+	if (dpi->panel)
+		drm_panel_attach(dpi->panel, dpi->connector);
+
+	dev_set_drvdata(dev, dpi);
+
+	vc4->dpi = dpi;
+
+	return 0;
+
+err_destroy_encoder:
+	drm_encoder_cleanup(dpi->encoder);
+	clk_disable_unprepare(dpi->core_clock);
+	return ret;
+}
+
+static void vc4_dpi_unbind(struct device *dev, struct device *master,
+			   void *data)
+{
+	struct drm_device *drm = dev_get_drvdata(master);
+	struct vc4_dev *vc4 = to_vc4_dev(drm);
+	struct vc4_dpi *dpi = dev_get_drvdata(dev);
+
+	if (dpi->panel)
+		drm_panel_detach(dpi->panel);
+
+	vc4_dpi_connector_destroy(dpi->connector);
+	drm_encoder_cleanup(dpi->encoder);
+
+	clk_disable_unprepare(dpi->core_clock);
+
+	vc4->dpi = NULL;
+}
+
+static const struct component_ops vc4_dpi_ops = {
+	.bind   = vc4_dpi_bind,
+	.unbind = vc4_dpi_unbind,
+};
+
+static int vc4_dpi_dev_probe(struct platform_device *pdev)
+{
+	return component_add(&pdev->dev, &vc4_dpi_ops);
+}
+
+static int vc4_dpi_dev_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &vc4_dpi_ops);
+	return 0;
+}
+
+struct platform_driver vc4_dpi_driver = {
+	.probe = vc4_dpi_dev_probe,
+	.remove = vc4_dpi_dev_remove,
+	.driver = {
+		.name = "vc4_dpi",
+		.of_match_table = vc4_dpi_dt_match,
+	},
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/vc4/vc4_drv.c linux-libre-4.7-gnu/drivers/gpu/drm/vc4/vc4_drv.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/vc4/vc4_drv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/vc4/vc4_drv.c	2016-07-24 15:23:50.000000000 -0400
@@ -66,12 +66,12 @@ static const struct file_operations vc4_
 };
 
 static const struct drm_ioctl_desc vc4_drm_ioctls[] = {
-	DRM_IOCTL_DEF_DRV(VC4_SUBMIT_CL, vc4_submit_cl_ioctl, 0),
-	DRM_IOCTL_DEF_DRV(VC4_WAIT_SEQNO, vc4_wait_seqno_ioctl, 0),
-	DRM_IOCTL_DEF_DRV(VC4_WAIT_BO, vc4_wait_bo_ioctl, 0),
-	DRM_IOCTL_DEF_DRV(VC4_CREATE_BO, vc4_create_bo_ioctl, 0),
-	DRM_IOCTL_DEF_DRV(VC4_MMAP_BO, vc4_mmap_bo_ioctl, 0),
-	DRM_IOCTL_DEF_DRV(VC4_CREATE_SHADER_BO, vc4_create_shader_bo_ioctl, 0),
+	DRM_IOCTL_DEF_DRV(VC4_SUBMIT_CL, vc4_submit_cl_ioctl, DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF_DRV(VC4_WAIT_SEQNO, vc4_wait_seqno_ioctl, DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF_DRV(VC4_WAIT_BO, vc4_wait_bo_ioctl, DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF_DRV(VC4_CREATE_BO, vc4_create_bo_ioctl, DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF_DRV(VC4_MMAP_BO, vc4_mmap_bo_ioctl, DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF_DRV(VC4_CREATE_SHADER_BO, vc4_create_shader_bo_ioctl, DRM_RENDER_ALLOW),
 	DRM_IOCTL_DEF_DRV(VC4_GET_HANG_STATE, vc4_get_hang_state_ioctl,
 			  DRM_ROOT_ONLY),
 };
@@ -81,6 +81,7 @@ static struct drm_driver vc4_drm_driver
 			    DRIVER_ATOMIC |
 			    DRIVER_GEM |
 			    DRIVER_HAVE_IRQ |
+			    DRIVER_RENDER |
 			    DRIVER_PRIME),
 	.lastclose = vc4_lastclose,
 	.irq_handler = vc4_irq,
@@ -90,7 +91,7 @@ static struct drm_driver vc4_drm_driver
 
 	.enable_vblank = vc4_enable_vblank,
 	.disable_vblank = vc4_disable_vblank,
-	.get_vblank_counter = drm_vblank_count,
+	.get_vblank_counter = drm_vblank_no_hw_counter,
 
 #if defined(CONFIG_DEBUG_FS)
 	.debugfs_init = vc4_debugfs_init,
@@ -153,6 +154,24 @@ static void vc4_match_add_drivers(struct
 	}
 }
 
+static void vc4_kick_out_firmware_fb(void)
+{
+	struct apertures_struct *ap;
+
+	ap = alloc_apertures(1);
+	if (!ap)
+		return;
+
+	/* Since VC4 is a UMA device, the simplefb node may have been
+	 * located anywhere in memory.
+	 */
+	ap->ranges[0].base = 0;
+	ap->ranges[0].size = ~0;
+
+	remove_conflicting_framebuffers(ap, "vc4drmfb", false);
+	kfree(ap);
+}
+
 static int vc4_drm_bind(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
@@ -186,6 +205,8 @@ static int vc4_drm_bind(struct device *d
 	if (ret)
 		goto gem_destroy;
 
+	vc4_kick_out_firmware_fb();
+
 	ret = drm_dev_register(drm, 0);
 	if (ret < 0)
 		goto unbind_all;
@@ -237,6 +258,7 @@ static const struct component_master_ops
 
 static struct platform_driver *const component_drivers[] = {
 	&vc4_hdmi_driver,
+	&vc4_dpi_driver,
 	&vc4_crtc_driver,
 	&vc4_hvs_driver,
 	&vc4_v3d_driver,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/vc4/vc4_drv.h linux-libre-4.7-gnu/drivers/gpu/drm/vc4/vc4_drv.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/vc4/vc4_drv.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/vc4/vc4_drv.h	2016-07-24 15:23:50.000000000 -0400
@@ -16,6 +16,7 @@ struct vc4_dev {
 	struct vc4_hvs *hvs;
 	struct vc4_crtc *crtc[3];
 	struct vc4_v3d *v3d;
+	struct vc4_dpi *dpi;
 
 	struct drm_fbdev_cma *fbdev;
 
@@ -422,6 +423,10 @@ void vc4_debugfs_cleanup(struct drm_mino
 /* vc4_drv.c */
 void __iomem *vc4_ioremap_regs(struct platform_device *dev, int index);
 
+/* vc4_dpi.c */
+extern struct platform_driver vc4_dpi_driver;
+int vc4_dpi_debugfs_regs(struct seq_file *m, void *unused);
+
 /* vc4_gem.c */
 void vc4_gem_init(struct drm_device *dev);
 void vc4_gem_destroy(struct drm_device *dev);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/vc4/vc4_gem.c linux-libre-4.7-gnu/drivers/gpu/drm/vc4/vc4_gem.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/vc4/vc4_gem.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/vc4/vc4_gem.c	2016-07-24 15:23:50.000000000 -0400
@@ -822,7 +822,7 @@ vc4_wait_bo_ioctl(struct drm_device *dev
 	if (args->pad != 0)
 		return -EINVAL;
 
-	gem_obj = drm_gem_object_lookup(dev, file_priv, args->handle);
+	gem_obj = drm_gem_object_lookup(file_priv, args->handle);
 	if (!gem_obj) {
 		DRM_ERROR("Failed to look up GEM BO %d\n", args->handle);
 		return -EINVAL;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/vc4/vc4_hdmi.c linux-libre-4.7-gnu/drivers/gpu/drm/vc4/vc4_hdmi.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/vc4/vc4_hdmi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/vc4/vc4_hdmi.c	2016-07-24 15:23:50.000000000 -0400
@@ -573,7 +573,7 @@ err_unprepare_hsm:
 err_unprepare_pix:
 	clk_disable_unprepare(hdmi->pixel_clock);
 err_put_i2c:
-	put_device(&vc4->hdmi->ddc->dev);
+	put_device(&hdmi->ddc->dev);
 
 	return ret;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/vc4/vc4_kms.c linux-libre-4.7-gnu/drivers/gpu/drm/vc4/vc4_kms.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/vc4/vc4_kms.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/vc4/vc4_kms.c	2016-07-24 15:23:50.000000000 -0400
@@ -93,7 +93,7 @@ static struct vc4_commit *commit_init(st
  * vc4_atomic_commit - commit validated state object
  * @dev: DRM device
  * @state: the driver state object
- * @async: asynchronous commit
+ * @nonblock: nonblocking commit
  *
  * This function commits a with drm_atomic_helper_check() pre-validated state
  * object. This can still fail when e.g. the framebuffer reservation fails. For
@@ -104,7 +104,7 @@ static struct vc4_commit *commit_init(st
  */
 static int vc4_atomic_commit(struct drm_device *dev,
 			     struct drm_atomic_state *state,
-			     bool async)
+			     bool nonblock)
 {
 	struct vc4_dev *vc4 = to_vc4_dev(dev);
 	int ret;
@@ -117,10 +117,18 @@ static int vc4_atomic_commit(struct drm_
 		return -ENOMEM;
 
 	/* Make sure that any outstanding modesets have finished. */
-	ret = down_interruptible(&vc4->async_modeset);
-	if (ret) {
-		kfree(c);
-		return ret;
+	if (nonblock) {
+		ret = down_trylock(&vc4->async_modeset);
+		if (ret) {
+			kfree(c);
+			return -EBUSY;
+		}
+	} else {
+		ret = down_interruptible(&vc4->async_modeset);
+		if (ret) {
+			kfree(c);
+			return ret;
+		}
 	}
 
 	ret = drm_atomic_helper_prepare_planes(dev, state);
@@ -170,7 +178,7 @@ static int vc4_atomic_commit(struct drm_
 	 * current layout.
 	 */
 
-	if (async) {
+	if (nonblock) {
 		vc4_queue_seqno_cb(dev, &c->cb, wait_seqno,
 				   vc4_atomic_complete_commit_seqno_cb);
 	} else {
@@ -207,8 +215,6 @@ int vc4_kms_load(struct drm_device *dev)
 	dev->mode_config.preferred_depth = 24;
 	dev->mode_config.async_page_flip = true;
 
-	dev->vblank_disable_allowed = true;
-
 	drm_mode_config_reset(dev);
 
 	vc4->fbdev = drm_fbdev_cma_init(dev, 32,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/vc4/vc4_plane.c linux-libre-4.7-gnu/drivers/gpu/drm/vc4/vc4_plane.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/vc4/vc4_plane.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/vc4/vc4_plane.c	2016-07-24 15:23:50.000000000 -0400
@@ -208,7 +208,7 @@ static void vc4_plane_destroy_state(stru
 	}
 
 	kfree(vc4_state->dlist);
-	__drm_atomic_helper_plane_destroy_state(plane, &vc4_state->base);
+	__drm_atomic_helper_plane_destroy_state(&vc4_state->base);
 	kfree(state);
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/vc4/vc4_regs.h linux-libre-4.7-gnu/drivers/gpu/drm/vc4/vc4_regs.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/vc4/vc4_regs.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/vc4/vc4_regs.h	2016-07-24 15:23:50.000000000 -0400
@@ -341,6 +341,10 @@
 #define SCALER_DISPLACT0                        0x00000030
 #define SCALER_DISPLACT1                        0x00000034
 #define SCALER_DISPLACT2                        0x00000038
+#define SCALER_DISPLACTX(x)			(SCALER_DISPLACT0 +	\
+						 (x) * (SCALER_DISPLACT1 - \
+							SCALER_DISPLACT0))
+
 #define SCALER_DISPCTRL0                        0x00000040
 # define SCALER_DISPCTRLX_ENABLE		BIT(31)
 # define SCALER_DISPCTRLX_RESET			BIT(30)
@@ -390,6 +394,12 @@
 #define SCALER_DISPBASE2                        0x0000006c
 #define SCALER_DISPALPHA2                       0x00000070
 #define SCALER_GAMADDR                          0x00000078
+# define SCALER_GAMADDR_AUTOINC			BIT(31)
+/* Enables all gamma ramp SRAMs, not just those of CRTCs with gamma
+ * enabled.
+ */
+# define SCALER_GAMADDR_SRAMENB			BIT(30)
+
 #define SCALER_GAMDATA                          0x000000e0
 #define SCALER_DLIST_START                      0x00002000
 #define SCALER_DLIST_SIZE                       0x00004000
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/vgem/vgem_drv.c linux-libre-4.7-gnu/drivers/gpu/drm/vgem/vgem_drv.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/vgem/vgem_drv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/vgem/vgem_drv.c	2016-07-24 15:23:50.000000000 -0400
@@ -89,7 +89,6 @@ int vgem_gem_get_pages(struct drm_vgem_g
 static int vgem_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
 	struct drm_vgem_gem_object *obj = vma->vm_private_data;
-	struct drm_device *dev = obj->base.dev;
 	loff_t num_pages;
 	pgoff_t page_offset;
 	int ret;
@@ -103,12 +102,8 @@ static int vgem_gem_fault(struct vm_area
 	if (page_offset > num_pages)
 		return VM_FAULT_SIGBUS;
 
-	mutex_lock(&dev->struct_mutex);
-
 	ret = vm_insert_page(vma, (unsigned long)vmf->virtual_address,
 			     obj->pages[page_offset]);
-
-	mutex_unlock(&dev->struct_mutex);
 	switch (ret) {
 	case 0:
 		return VM_FAULT_NOPAGE;
@@ -154,6 +149,10 @@ static struct drm_gem_object *vgem_gem_c
 	if (err)
 		goto out;
 
+	err = vgem_gem_get_pages(obj);
+	if (err)
+		goto out;
+
 	err = drm_gem_handle_create(file, gem_object, handle);
 	if (err)
 		goto handle_out;
@@ -201,37 +200,23 @@ int vgem_gem_dumb_map(struct drm_file *f
 	int ret = 0;
 	struct drm_gem_object *obj;
 
-	mutex_lock(&dev->struct_mutex);
-	obj = drm_gem_object_lookup(dev, file, handle);
-	if (!obj) {
-		ret = -ENOENT;
-		goto unlock;
-	}
+	obj = drm_gem_object_lookup(file, handle);
+	if (!obj)
+		return -ENOENT;
 
-	if (!drm_vma_node_has_offset(&obj->vma_node)) {
-		ret = drm_gem_create_mmap_offset(obj);
-		if (ret)
-			goto unref;
-	}
+	ret = drm_gem_create_mmap_offset(obj);
+	if (ret)
+		goto unref;
 
 	BUG_ON(!obj->filp);
 
 	obj->filp->private_data = obj;
 
-	ret = vgem_gem_get_pages(to_vgem_bo(obj));
-	if (ret)
-		goto fail_get_pages;
-
 	*offset = drm_vma_node_offset_addr(&obj->vma_node);
 
-	goto unref;
-
-fail_get_pages:
-	drm_gem_free_mmap_offset(obj);
 unref:
-	drm_gem_object_unreference(obj);
-unlock:
-	mutex_unlock(&dev->struct_mutex);
+	drm_gem_object_unreference_unlocked(obj);
+
 	return ret;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/virtio/virtgpu_display.c linux-libre-4.7-gnu/drivers/gpu/drm/virtio/virtgpu_display.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/virtio/virtgpu_display.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/virtio/virtgpu_display.c	2016-07-24 15:23:50.000000000 -0400
@@ -38,13 +38,6 @@
 #define XRES_MAX  8192
 #define YRES_MAX  8192
 
-static void virtio_gpu_crtc_gamma_set(struct drm_crtc *crtc,
-				      u16 *red, u16 *green, u16 *blue,
-				      uint32_t start, uint32_t size)
-{
-	/* TODO */
-}
-
 static void
 virtio_gpu_hide_cursor(struct virtio_gpu_device *vgdev,
 		       struct virtio_gpu_output *output)
@@ -75,7 +68,7 @@ static int virtio_gpu_crtc_cursor_set(st
 	}
 
 	/* lookup the cursor */
-	gobj = drm_gem_object_lookup(crtc->dev, file_priv, handle);
+	gobj = drm_gem_object_lookup(file_priv, handle);
 	if (gobj == NULL)
 		return -ENOENT;
 
@@ -173,7 +166,6 @@ static int virtio_gpu_page_flip(struct d
 static const struct drm_crtc_funcs virtio_gpu_crtc_funcs = {
 	.cursor_set2            = virtio_gpu_crtc_cursor_set,
 	.cursor_move            = virtio_gpu_crtc_cursor_move,
-	.gamma_set              = virtio_gpu_crtc_gamma_set,
 	.set_config             = drm_atomic_helper_set_config,
 	.destroy                = drm_crtc_cleanup,
 
@@ -428,7 +420,6 @@ static int vgdev_output_init(struct virt
 		return PTR_ERR(plane);
 	drm_crtc_init_with_planes(dev, crtc, plane, NULL,
 				  &virtio_gpu_crtc_funcs, NULL);
-	drm_mode_crtc_set_gamma_size(crtc, 256);
 	drm_crtc_helper_add(crtc, &virtio_gpu_crtc_helper_funcs);
 	plane->crtc = crtc;
 
@@ -456,7 +447,7 @@ virtio_gpu_user_framebuffer_create(struc
 	int ret;
 
 	/* lookup object associated with res handle */
-	obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]);
+	obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[0]);
 	if (!obj)
 		return ERR_PTR(-EINVAL);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/virtio/virtgpu_drv.c linux-libre-4.7-gnu/drivers/gpu/drm/virtio/virtgpu_drv.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/virtio/virtgpu_drv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/virtio/virtgpu_drv.c	2016-07-24 15:23:50.000000000 -0400
@@ -42,10 +42,8 @@ module_param_named(modeset, virtio_gpu_m
 
 static int virtio_gpu_probe(struct virtio_device *vdev)
 {
-#ifdef CONFIG_VGA_CONSOLE
 	if (vgacon_text_force() && virtio_gpu_modeset == -1)
 		return -EINVAL;
-#endif
 
 	if (virtio_gpu_modeset == 0)
 		return -EINVAL;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/virtio/virtgpu_drv.h linux-libre-4.7-gnu/drivers/gpu/drm/virtio/virtgpu_drv.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/virtio/virtgpu_drv.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/virtio/virtgpu_drv.h	2016-07-24 15:23:50.000000000 -0400
@@ -400,7 +400,7 @@ static inline int virtio_gpu_object_rese
 {
 	int r;
 
-	r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, NULL);
+	r = ttm_bo_reserve(&bo->tbo, true, no_wait, NULL);
 	if (unlikely(r != 0)) {
 		if (r != -ERESTARTSYS) {
 			struct virtio_gpu_device *qdev =
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/virtio/virtgpu_gem.c linux-libre-4.7-gnu/drivers/gpu/drm/virtio/virtgpu_gem.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/virtio/virtgpu_gem.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/virtio/virtgpu_gem.c	2016-07-24 15:23:50.000000000 -0400
@@ -130,7 +130,7 @@ int virtio_gpu_mode_dumb_mmap(struct drm
 	struct drm_gem_object *gobj;
 	struct virtio_gpu_object *obj;
 	BUG_ON(!offset_p);
-	gobj = drm_gem_object_lookup(dev, file_priv, handle);
+	gobj = drm_gem_object_lookup(file_priv, handle);
 	if (gobj == NULL)
 		return -ENOENT;
 	obj = gem_to_virtio_gpu_obj(gobj);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/virtio/virtgpu_ioctl.c linux-libre-4.7-gnu/drivers/gpu/drm/virtio/virtgpu_ioctl.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/virtio/virtgpu_ioctl.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/virtio/virtgpu_ioctl.c	2016-07-24 15:23:50.000000000 -0400
@@ -133,8 +133,7 @@ static int virtio_gpu_execbuffer(struct
 		}
 
 		for (i = 0; i < exbuf->num_bo_handles; i++) {
-			gobj = drm_gem_object_lookup(dev,
-						     drm_file, bo_handles[i]);
+			gobj = drm_gem_object_lookup(drm_file, bo_handles[i]);
 			if (!gobj) {
 				drm_free_large(bo_handles);
 				drm_free_large(buflist);
@@ -345,7 +344,7 @@ static int virtio_gpu_resource_info_ioct
 	struct drm_gem_object *gobj = NULL;
 	struct virtio_gpu_object *qobj = NULL;
 
-	gobj = drm_gem_object_lookup(dev, file_priv, ri->bo_handle);
+	gobj = drm_gem_object_lookup(file_priv, ri->bo_handle);
 	if (gobj == NULL)
 		return -ENOENT;
 
@@ -374,7 +373,7 @@ static int virtio_gpu_transfer_from_host
 	if (vgdev->has_virgl_3d == false)
 		return -ENOSYS;
 
-	gobj = drm_gem_object_lookup(dev, file, args->bo_handle);
+	gobj = drm_gem_object_lookup(file, args->bo_handle);
 	if (gobj == NULL)
 		return -ENOENT;
 
@@ -418,7 +417,7 @@ static int virtio_gpu_transfer_to_host_i
 	int ret;
 	u32 offset = args->offset;
 
-	gobj = drm_gem_object_lookup(dev, file, args->bo_handle);
+	gobj = drm_gem_object_lookup(file, args->bo_handle);
 	if (gobj == NULL)
 		return -ENOENT;
 
@@ -464,7 +463,7 @@ static int virtio_gpu_wait_ioctl(struct
 	int ret;
 	bool nowait = false;
 
-	gobj = drm_gem_object_lookup(dev, file, args->handle);
+	gobj = drm_gem_object_lookup(file, args->handle);
 	if (gobj == NULL)
 		return -ENOENT;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/virtio/virtgpu_object.c linux-libre-4.7-gnu/drivers/gpu/drm/virtio/virtgpu_object.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/virtio/virtgpu_object.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/virtio/virtgpu_object.c	2016-07-24 15:23:50.000000000 -0400
@@ -155,10 +155,10 @@ int virtio_gpu_object_wait(struct virtio
 {
 	int r;
 
-	r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, NULL);
+	r = ttm_bo_reserve(&bo->tbo, true, no_wait, NULL);
 	if (unlikely(r != 0))
 		return r;
-	r = ttm_bo_wait(&bo->tbo, true, true, no_wait);
+	r = ttm_bo_wait(&bo->tbo, true, no_wait);
 	ttm_bo_unreserve(&bo->tbo);
 	return r;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/virtio/virtgpu_ttm.c linux-libre-4.7-gnu/drivers/gpu/drm/virtio/virtgpu_ttm.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/virtio/virtgpu_ttm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/virtio/virtgpu_ttm.c	2016-07-24 15:23:50.000000000 -0400
@@ -426,6 +426,8 @@ static struct ttm_bo_driver virtio_gpu_b
 	.io_mem_free = &virtio_gpu_ttm_io_mem_free,
 	.move_notify = &virtio_gpu_bo_move_notify,
 	.swap_notify = &virtio_gpu_bo_swap_notify,
+	.lru_tail = &ttm_bo_default_lru_tail,
+	.swap_lru_tail = &ttm_bo_default_swap_lru_tail,
 };
 
 int virtio_gpu_ttm_init(struct virtio_gpu_device *vgdev)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/vmwgfx/Makefile linux-libre-4.7-gnu/drivers/gpu/drm/vmwgfx/Makefile
--- linux-libre-4.6-gnu/drivers/gpu/drm/vmwgfx/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/vmwgfx/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -8,6 +8,6 @@ vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.
 	    vmwgfx_fence.o vmwgfx_dmabuf.o vmwgfx_scrn.o vmwgfx_context.o \
 	    vmwgfx_surface.o vmwgfx_prime.o vmwgfx_mob.o vmwgfx_shader.o \
 	    vmwgfx_cmdbuf_res.o vmwgfx_cmdbuf.o vmwgfx_stdu.o \
-	    vmwgfx_cotable.o vmwgfx_so.o vmwgfx_binding.o
+	    vmwgfx_cotable.o vmwgfx_so.o vmwgfx_binding.o vmwgfx_msg.o
 
 obj-$(CONFIG_DRM_VMWGFX) := vmwgfx.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c linux-libre-4.7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c	2016-07-24 15:23:50.000000000 -0400
@@ -839,7 +839,7 @@ static void vmw_move_notify(struct ttm_b
  */
 static void vmw_swap_notify(struct ttm_buffer_object *bo)
 {
-	ttm_bo_wait(bo, false, false, false);
+	ttm_bo_wait(bo, false, false);
 }
 
 
@@ -857,4 +857,6 @@ struct ttm_bo_driver vmw_bo_driver = {
 	.fault_reserve_notify = &vmw_ttm_fault_reserve_notify,
 	.io_mem_reserve = &vmw_ttm_io_mem_reserve,
 	.io_mem_free = &vmw_ttm_io_mem_free,
+	.lru_tail = &ttm_bo_default_lru_tail,
+	.swap_lru_tail = &ttm_bo_default_swap_lru_tail,
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c linux-libre-4.7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c	2016-07-24 15:23:50.000000000 -0400
@@ -421,9 +421,9 @@ static int vmw_cotable_resize(struct vmw
 	}
 
 	bo = &buf->base;
-	WARN_ON_ONCE(ttm_bo_reserve(bo, false, true, false, NULL));
+	WARN_ON_ONCE(ttm_bo_reserve(bo, false, true, NULL));
 
-	ret = ttm_bo_wait(old_bo, false, false, false);
+	ret = ttm_bo_wait(old_bo, false, false);
 	if (unlikely(ret != 0)) {
 		DRM_ERROR("Failed waiting for cotable unbind.\n");
 		goto out_wait;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c linux-libre-4.7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c	2016-07-24 15:23:50.000000000 -0400
@@ -49,6 +49,7 @@ int vmw_dmabuf_pin_in_placement(struct v
 {
 	struct ttm_buffer_object *bo = &buf->base;
 	int ret;
+	uint32_t new_flags;
 
 	ret = ttm_write_lock(&dev_priv->reservation_sem, interruptible);
 	if (unlikely(ret != 0))
@@ -56,11 +57,16 @@ int vmw_dmabuf_pin_in_placement(struct v
 
 	vmw_execbuf_release_pinned_bo(dev_priv);
 
-	ret = ttm_bo_reserve(bo, interruptible, false, false, NULL);
+	ret = ttm_bo_reserve(bo, interruptible, false, NULL);
 	if (unlikely(ret != 0))
 		goto err;
 
-	ret = ttm_bo_validate(bo, placement, interruptible, false);
+	if (buf->pin_count > 0)
+		ret = ttm_bo_mem_compat(placement, &bo->mem,
+					&new_flags) == true ? 0 : -EINVAL;
+	else
+		ret = ttm_bo_validate(bo, placement, interruptible, false);
+
 	if (!ret)
 		vmw_bo_pin_reserved(buf, true);
 
@@ -91,6 +97,7 @@ int vmw_dmabuf_pin_in_vram_or_gmr(struct
 {
 	struct ttm_buffer_object *bo = &buf->base;
 	int ret;
+	uint32_t new_flags;
 
 	ret = ttm_write_lock(&dev_priv->reservation_sem, interruptible);
 	if (unlikely(ret != 0))
@@ -98,10 +105,16 @@ int vmw_dmabuf_pin_in_vram_or_gmr(struct
 
 	vmw_execbuf_release_pinned_bo(dev_priv);
 
-	ret = ttm_bo_reserve(bo, interruptible, false, false, NULL);
+	ret = ttm_bo_reserve(bo, interruptible, false, NULL);
 	if (unlikely(ret != 0))
 		goto err;
 
+	if (buf->pin_count > 0) {
+		ret = ttm_bo_mem_compat(&vmw_vram_gmr_placement, &bo->mem,
+					&new_flags) == true ? 0 : -EINVAL;
+		goto out_unreserve;
+	}
+
 	ret = ttm_bo_validate(bo, &vmw_vram_gmr_placement, interruptible,
 			      false);
 	if (likely(ret == 0) || ret == -ERESTARTSYS)
@@ -161,6 +174,7 @@ int vmw_dmabuf_pin_in_start_of_vram(stru
 	struct ttm_placement placement;
 	struct ttm_place place;
 	int ret = 0;
+	uint32_t new_flags;
 
 	place = vmw_vram_placement.placement[0];
 	place.lpfn = bo->num_pages;
@@ -174,7 +188,7 @@ int vmw_dmabuf_pin_in_start_of_vram(stru
 		return ret;
 
 	vmw_execbuf_release_pinned_bo(dev_priv);
-	ret = ttm_bo_reserve(bo, interruptible, false, false, NULL);
+	ret = ttm_bo_reserve(bo, interruptible, false, NULL);
 	if (unlikely(ret != 0))
 		goto err_unlock;
 
@@ -185,10 +199,15 @@ int vmw_dmabuf_pin_in_start_of_vram(stru
 	 */
 	if (bo->mem.mem_type == TTM_PL_VRAM &&
 	    bo->mem.start < bo->num_pages &&
-	    bo->mem.start > 0)
+	    bo->mem.start > 0 &&
+	    buf->pin_count == 0)
 		(void) ttm_bo_validate(bo, &vmw_sys_placement, false, false);
 
-	ret = ttm_bo_validate(bo, &placement, interruptible, false);
+	if (buf->pin_count > 0)
+		ret = ttm_bo_mem_compat(&placement, &bo->mem,
+					&new_flags) == true ? 0 : -EINVAL;
+	else
+		ret = ttm_bo_validate(bo, &placement, interruptible, false);
 
 	/* For some reason we didn't end up at the start of vram */
 	WARN_ON(ret == 0 && bo->offset != 0);
@@ -225,7 +244,7 @@ int vmw_dmabuf_unpin(struct vmw_private
 	if (unlikely(ret != 0))
 		return ret;
 
-	ret = ttm_bo_reserve(bo, interruptible, false, false, NULL);
+	ret = ttm_bo_reserve(bo, interruptible, false, NULL);
 	if (unlikely(ret != 0))
 		goto err;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c linux-libre-4.7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c	2016-07-24 15:23:50.000000000 -0400
@@ -1,6 +1,6 @@
 /**************************************************************************
  *
- * Copyright © 2009-2015 VMware, Inc., Palo Alto, CA., USA
+ * Copyright © 2009-2016 VMware, Inc., Palo Alto, CA., USA
  * All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -44,6 +44,12 @@
 #define VMW_MIN_INITIAL_WIDTH 800
 #define VMW_MIN_INITIAL_HEIGHT 600
 
+#ifndef VMWGFX_GIT_VERSION
+#define VMWGFX_GIT_VERSION "Unknown"
+#endif
+
+#define VMWGFX_REPO "In Tree"
+
 
 /**
  * Fully encoded drm commands. Might move to vmw_drm.h
@@ -227,6 +233,7 @@ static int vmw_force_iommu;
 static int vmw_restrict_iommu;
 static int vmw_force_coherent;
 static int vmw_restrict_dma_mask;
+static int vmw_assume_16bpp;
 
 static int vmw_probe(struct pci_dev *, const struct pci_device_id *);
 static void vmw_master_init(struct vmw_master *);
@@ -243,6 +250,8 @@ MODULE_PARM_DESC(force_coherent, "Force
 module_param_named(force_coherent, vmw_force_coherent, int, 0600);
 MODULE_PARM_DESC(restrict_dma_mask, "Restrict DMA mask to 44 bits with IOMMU");
 module_param_named(restrict_dma_mask, vmw_restrict_dma_mask, int, 0600);
+MODULE_PARM_DESC(assume_16bpp, "Assume 16-bpp when filtering modes");
+module_param_named(assume_16bpp, vmw_assume_16bpp, int, 0600);
 
 
 static void vmw_print_capabilities(uint32_t capabilities)
@@ -326,7 +335,7 @@ static int vmw_dummy_query_bo_create(str
 	if (unlikely(ret != 0))
 		return ret;
 
-	ret = ttm_bo_reserve(&vbo->base, false, true, false, NULL);
+	ret = ttm_bo_reserve(&vbo->base, false, true, NULL);
 	BUG_ON(ret != 0);
 	vmw_bo_pin_reserved(vbo, true);
 
@@ -613,6 +622,7 @@ static int vmw_driver_load(struct drm_de
 	uint32_t svga_id;
 	enum vmw_res_type i;
 	bool refuse_dma = false;
+	char host_log[100] = {0};
 
 	dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
 	if (unlikely(dev_priv == NULL)) {
@@ -628,6 +638,7 @@ static int vmw_driver_load(struct drm_de
 	mutex_init(&dev_priv->cmdbuf_mutex);
 	mutex_init(&dev_priv->release_mutex);
 	mutex_init(&dev_priv->binding_mutex);
+	mutex_init(&dev_priv->global_kms_state_mutex);
 	rwlock_init(&dev_priv->resource_lock);
 	ttm_lock_init(&dev_priv->reservation_sem);
 	spin_lock_init(&dev_priv->hw_lock);
@@ -652,6 +663,8 @@ static int vmw_driver_load(struct drm_de
 	dev_priv->vram_start = pci_resource_start(dev->pdev, 1);
 	dev_priv->mmio_start = pci_resource_start(dev->pdev, 2);
 
+	dev_priv->assume_16bpp = !!vmw_assume_16bpp;
+
 	dev_priv->enable_fb = enable_fbdev;
 
 	vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2);
@@ -698,6 +711,13 @@ static int vmw_driver_load(struct drm_de
 			vmw_read(dev_priv,
 				 SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB);
 
+		/*
+		 * Workaround for low memory 2D VMs to compensate for the
+		 * allocation taken by fbdev
+		 */
+		if (!(dev_priv->capabilities & SVGA_CAP_3D))
+			mem_size *= 2;
+
 		dev_priv->max_mob_pages = mem_size * 1024 / PAGE_SIZE;
 		dev_priv->prim_bb_mem =
 			vmw_read(dev_priv,
@@ -873,6 +893,16 @@ static int vmw_driver_load(struct drm_de
 
 	DRM_INFO("DX: %s\n", dev_priv->has_dx ? "yes." : "no.");
 
+	snprintf(host_log, sizeof(host_log), "vmwgfx: %s-%s",
+		VMWGFX_REPO, VMWGFX_GIT_VERSION);
+	vmw_host_log(host_log);
+
+	memset(host_log, 0, sizeof(host_log));
+	snprintf(host_log, sizeof(host_log), "vmwgfx: Module Version: %d.%d.%d",
+		VMWGFX_DRIVER_MAJOR, VMWGFX_DRIVER_MINOR,
+		VMWGFX_DRIVER_PATCHLEVEL);
+	vmw_host_log(host_log);
+
 	if (dev_priv->enable_fb) {
 		vmw_fifo_resource_inc(dev_priv);
 		vmw_svga_enable(dev_priv);
@@ -1530,10 +1560,8 @@ static int __init vmwgfx_init(void)
 {
 	int ret;
 
-#ifdef CONFIG_VGA_CONSOLE
 	if (vgacon_text_force())
 		return -EINVAL;
-#endif
 
 	ret = drm_pci_init(&driver, &vmw_pci_driver);
 	if (ret)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h linux-libre-4.7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h	2016-07-24 15:23:50.000000000 -0400
@@ -386,6 +386,7 @@ struct vmw_private {
 	spinlock_t hw_lock;
 	spinlock_t cap_lock;
 	bool has_dx;
+	bool assume_16bpp;
 
 	/*
 	 * VGA registers.
@@ -412,6 +413,7 @@ struct vmw_private {
 	struct drm_property *implicit_placement_property;
 	unsigned num_implicit;
 	struct vmw_framebuffer *implicit_fb;
+	struct mutex global_kms_state_mutex;
 
 	/*
 	 * Context and surface management.
@@ -1234,4 +1236,10 @@ static inline void vmw_mmio_write(u32 va
 {
 	WRITE_ONCE(*addr, value);
 }
+
+/**
+ * Add vmw_msg module function
+ */
+extern int vmw_host_log(const char *log);
+
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c linux-libre-4.7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c	2016-07-24 15:23:50.000000000 -0400
@@ -517,28 +517,6 @@ static int vmw_fb_kms_framebuffer(struct
 
 	par->set_fb = &vfb->base;
 
-	if (!par->bo_ptr) {
-		/*
-		 * Pin before mapping. Since we don't know in what placement
-		 * to pin, call into KMS to do it for us.
-		 */
-		ret = vfb->pin(vfb);
-		if (ret) {
-			DRM_ERROR("Could not pin the fbdev framebuffer.\n");
-			return ret;
-		}
-
-		ret = ttm_bo_kmap(&par->vmw_bo->base, 0,
-				  par->vmw_bo->base.num_pages, &par->map);
-		if (ret) {
-			vfb->unpin(vfb);
-			DRM_ERROR("Could not map the fbdev framebuffer.\n");
-			return ret;
-		}
-
-		par->bo_ptr = ttm_kmap_obj_virtual(&par->map, &par->bo_iowrite);
-	}
-
 	return 0;
 }
 
@@ -601,6 +579,31 @@ static int vmw_fb_set_par(struct fb_info
 	if (ret)
 		goto out_unlock;
 
+	if (!par->bo_ptr) {
+		struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(set.fb);
+
+		/*
+		 * Pin before mapping. Since we don't know in what placement
+		 * to pin, call into KMS to do it for us.
+		 */
+		ret = vfb->pin(vfb);
+		if (ret) {
+			DRM_ERROR("Could not pin the fbdev framebuffer.\n");
+			goto out_unlock;
+		}
+
+		ret = ttm_bo_kmap(&par->vmw_bo->base, 0,
+				  par->vmw_bo->base.num_pages, &par->map);
+		if (ret) {
+			vfb->unpin(vfb);
+			DRM_ERROR("Could not map the fbdev framebuffer.\n");
+			goto out_unlock;
+		}
+
+		par->bo_ptr = ttm_kmap_obj_virtual(&par->map, &par->bo_iowrite);
+	}
+
+
 	vmw_fb_dirty_mark(par, par->fb_x, par->fb_y,
 			  par->set_fb->width, par->set_fb->height);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c linux-libre-4.7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c	2016-07-24 15:23:50.000000000 -0400
@@ -98,7 +98,7 @@ int vmw_cursor_update_dmabuf(struct vmw_
 	kmap_offset = 0;
 	kmap_num = (width*height*4 + PAGE_SIZE - 1) >> PAGE_SHIFT;
 
-	ret = ttm_bo_reserve(&dmabuf->base, true, false, false, NULL);
+	ret = ttm_bo_reserve(&dmabuf->base, true, false, NULL);
 	if (unlikely(ret != 0)) {
 		DRM_ERROR("reserve failed\n");
 		return -EINVAL;
@@ -318,7 +318,7 @@ void vmw_kms_cursor_snoop(struct vmw_sur
 	kmap_offset = cmd->dma.guest.ptr.offset >> PAGE_SHIFT;
 	kmap_num = (64*64*4) >> PAGE_SHIFT;
 
-	ret = ttm_bo_reserve(bo, true, false, false, NULL);
+	ret = ttm_bo_reserve(bo, true, false, NULL);
 	if (unlikely(ret != 0)) {
 		DRM_ERROR("reserve failed\n");
 		return;
@@ -1553,14 +1553,10 @@ int vmw_du_connector_fill_modes(struct d
 		DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC)
 	};
 	int i;
-	u32 assumed_bpp = 2;
+	u32 assumed_bpp = 4;
 
-	/*
-	 * If using screen objects, then assume 32-bpp because that's what the
-	 * SVGA device is assuming
-	 */
-	if (dev_priv->active_display_unit == vmw_du_screen_object)
-		assumed_bpp = 4;
+	if (dev_priv->assume_16bpp)
+		assumed_bpp = 2;
 
 	if (dev_priv->active_display_unit == vmw_du_screen_target) {
 		max_width  = min(max_width,  dev_priv->stdu_max_width);
@@ -1859,7 +1855,7 @@ int vmw_kms_helper_buffer_prepare(struct
 	struct ttm_buffer_object *bo = &buf->base;
 	int ret;
 
-	ttm_bo_reserve(bo, false, false, interruptible, NULL);
+	ttm_bo_reserve(bo, false, false, NULL);
 	ret = vmw_validate_single_buffer(dev_priv, bo, interruptible,
 					 validate_as_mob);
 	if (ret)
@@ -2143,13 +2139,13 @@ int vmw_kms_fbdev_init_data(struct vmw_p
 void vmw_kms_del_active(struct vmw_private *dev_priv,
 			struct vmw_display_unit *du)
 {
-	lockdep_assert_held_once(&dev_priv->dev->mode_config.mutex);
-
+	mutex_lock(&dev_priv->global_kms_state_mutex);
 	if (du->active_implicit) {
 		if (--(dev_priv->num_implicit) == 0)
 			dev_priv->implicit_fb = NULL;
 		du->active_implicit = false;
 	}
+	mutex_unlock(&dev_priv->global_kms_state_mutex);
 }
 
 /**
@@ -2165,8 +2161,7 @@ void vmw_kms_add_active(struct vmw_priva
 			struct vmw_display_unit *du,
 			struct vmw_framebuffer *vfb)
 {
-	lockdep_assert_held_once(&dev_priv->dev->mode_config.mutex);
-
+	mutex_lock(&dev_priv->global_kms_state_mutex);
 	WARN_ON_ONCE(!dev_priv->num_implicit && dev_priv->implicit_fb);
 
 	if (!du->active_implicit && du->is_implicit) {
@@ -2174,6 +2169,7 @@ void vmw_kms_add_active(struct vmw_priva
 		du->active_implicit = true;
 		dev_priv->num_implicit++;
 	}
+	mutex_unlock(&dev_priv->global_kms_state_mutex);
 }
 
 /**
@@ -2190,16 +2186,13 @@ bool vmw_kms_crtc_flippable(struct vmw_p
 			    struct drm_crtc *crtc)
 {
 	struct vmw_display_unit *du = vmw_crtc_to_du(crtc);
+	bool ret;
 
-	lockdep_assert_held_once(&dev_priv->dev->mode_config.mutex);
-
-	if (!du->is_implicit)
-		return true;
-
-	if (dev_priv->num_implicit != 1)
-		return false;
+	mutex_lock(&dev_priv->global_kms_state_mutex);
+	ret = !du->is_implicit || dev_priv->num_implicit == 1;
+	mutex_unlock(&dev_priv->global_kms_state_mutex);
 
-	return true;
+	return ret;
 }
 
 /**
@@ -2214,16 +2207,18 @@ void vmw_kms_update_implicit_fb(struct v
 	struct vmw_display_unit *du = vmw_crtc_to_du(crtc);
 	struct vmw_framebuffer *vfb;
 
-	lockdep_assert_held_once(&dev_priv->dev->mode_config.mutex);
+	mutex_lock(&dev_priv->global_kms_state_mutex);
 
 	if (!du->is_implicit)
-		return;
+		goto out_unlock;
 
 	vfb = vmw_framebuffer_to_vfb(crtc->primary->fb);
 	WARN_ON_ONCE(dev_priv->num_implicit != 1 &&
 		     dev_priv->implicit_fb != vfb);
 
 	dev_priv->implicit_fb = vfb;
+out_unlock:
+	mutex_unlock(&dev_priv->global_kms_state_mutex);
 }
 
 /**
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c linux-libre-4.7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c	2016-07-24 15:23:50.000000000 -0400
@@ -222,7 +222,7 @@ static void vmw_takedown_otable_base(str
 	if (bo) {
 		int ret;
 
-		ret = ttm_bo_reserve(bo, false, true, false, NULL);
+		ret = ttm_bo_reserve(bo, false, true, NULL);
 		BUG_ON(ret != 0);
 
 		vmw_fence_single_bo(bo, NULL);
@@ -262,7 +262,7 @@ static int vmw_otable_batch_setup(struct
 	if (unlikely(ret != 0))
 		goto out_no_bo;
 
-	ret = ttm_bo_reserve(batch->otable_bo, false, true, false, NULL);
+	ret = ttm_bo_reserve(batch->otable_bo, false, true, NULL);
 	BUG_ON(ret != 0);
 	ret = vmw_bo_driver.ttm_tt_populate(batch->otable_bo->ttm);
 	if (unlikely(ret != 0))
@@ -357,7 +357,7 @@ static void vmw_otable_batch_takedown(st
 			vmw_takedown_otable_base(dev_priv, i,
 						 &batch->otables[i]);
 
-	ret = ttm_bo_reserve(bo, false, true, false, NULL);
+	ret = ttm_bo_reserve(bo, false, true, NULL);
 	BUG_ON(ret != 0);
 
 	vmw_fence_single_bo(bo, NULL);
@@ -440,7 +440,7 @@ static int vmw_mob_pt_populate(struct vm
 	if (unlikely(ret != 0))
 		return ret;
 
-	ret = ttm_bo_reserve(mob->pt_bo, false, true, false, NULL);
+	ret = ttm_bo_reserve(mob->pt_bo, false, true, NULL);
 
 	BUG_ON(ret != 0);
 	ret = vmw_bo_driver.ttm_tt_populate(mob->pt_bo->ttm);
@@ -545,7 +545,7 @@ static void vmw_mob_pt_setup(struct vmw_
 	const struct vmw_sg_table *vsgt;
 	int ret;
 
-	ret = ttm_bo_reserve(bo, false, true, false, NULL);
+	ret = ttm_bo_reserve(bo, false, true, NULL);
 	BUG_ON(ret != 0);
 
 	vsgt = vmw_bo_sg_table(bo);
@@ -595,7 +595,7 @@ void vmw_mob_unbind(struct vmw_private *
 	struct ttm_buffer_object *bo = mob->pt_bo;
 
 	if (bo) {
-		ret = ttm_bo_reserve(bo, false, true, false, NULL);
+		ret = ttm_bo_reserve(bo, false, true, NULL);
 		/*
 		 * Noone else should be using this buffer.
 		 */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c linux-libre-4.7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,421 @@
+/*
+ * Copyright © 2016 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/frame.h>
+#include <asm/hypervisor.h>
+#include "drmP.h"
+#include "vmwgfx_msg.h"
+
+
+#define MESSAGE_STATUS_SUCCESS  0x0001
+#define MESSAGE_STATUS_DORECV   0x0002
+#define MESSAGE_STATUS_CPT      0x0010
+#define MESSAGE_STATUS_HB       0x0080
+
+#define RPCI_PROTOCOL_NUM       0x49435052
+#define GUESTMSG_FLAG_COOKIE    0x80000000
+
+#define RETRIES                 3
+
+#define VMW_HYPERVISOR_MAGIC    0x564D5868
+#define VMW_HYPERVISOR_PORT     0x5658
+#define VMW_HYPERVISOR_HB_PORT  0x5659
+
+#define VMW_PORT_CMD_MSG        30
+#define VMW_PORT_CMD_HB_MSG     0
+#define VMW_PORT_CMD_OPEN_CHANNEL  (MSG_TYPE_OPEN << 16 | VMW_PORT_CMD_MSG)
+#define VMW_PORT_CMD_CLOSE_CHANNEL (MSG_TYPE_CLOSE << 16 | VMW_PORT_CMD_MSG)
+#define VMW_PORT_CMD_SENDSIZE   (MSG_TYPE_SENDSIZE << 16 | VMW_PORT_CMD_MSG)
+#define VMW_PORT_CMD_RECVSIZE   (MSG_TYPE_RECVSIZE << 16 | VMW_PORT_CMD_MSG)
+#define VMW_PORT_CMD_RECVSTATUS (MSG_TYPE_RECVSTATUS << 16 | VMW_PORT_CMD_MSG)
+
+#define HIGH_WORD(X) ((X & 0xFFFF0000) >> 16)
+
+static u32 vmw_msg_enabled = 1;
+
+enum rpc_msg_type {
+	MSG_TYPE_OPEN,
+	MSG_TYPE_SENDSIZE,
+	MSG_TYPE_SENDPAYLOAD,
+	MSG_TYPE_RECVSIZE,
+	MSG_TYPE_RECVPAYLOAD,
+	MSG_TYPE_RECVSTATUS,
+	MSG_TYPE_CLOSE,
+};
+
+struct rpc_channel {
+	u16 channel_id;
+	u32 cookie_high;
+	u32 cookie_low;
+};
+
+
+
+/**
+ * vmw_open_channel
+ *
+ * @channel: RPC channel
+ * @protocol:
+ *
+ * Returns: 0 on success
+ */
+static int vmw_open_channel(struct rpc_channel *channel, unsigned int protocol)
+{
+	unsigned long eax, ebx, ecx, edx, si = 0, di = 0;
+
+	VMW_PORT(VMW_PORT_CMD_OPEN_CHANNEL,
+		(protocol | GUESTMSG_FLAG_COOKIE), si, di,
+		VMW_HYPERVISOR_PORT,
+		VMW_HYPERVISOR_MAGIC,
+		eax, ebx, ecx, edx, si, di);
+
+	if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0)
+		return -EINVAL;
+
+	channel->channel_id  = HIGH_WORD(edx);
+	channel->cookie_high = si;
+	channel->cookie_low  = di;
+
+	return 0;
+}
+
+
+
+/**
+ * vmw_close_channel
+ *
+ * @channel: RPC channel
+ *
+ * Returns: 0 on success
+ */
+static int vmw_close_channel(struct rpc_channel *channel)
+{
+	unsigned long eax, ebx, ecx, edx, si, di;
+
+	/* Set up additional parameters */
+	si  = channel->cookie_high;
+	di  = channel->cookie_low;
+
+	VMW_PORT(VMW_PORT_CMD_CLOSE_CHANNEL,
+		0, si, di,
+		(VMW_HYPERVISOR_PORT | (channel->channel_id << 16)),
+		VMW_HYPERVISOR_MAGIC,
+		eax, ebx, ecx, edx, si, di);
+
+	if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+
+
+/**
+ * vmw_send_msg: Sends a message to the host
+ *
+ * @channel: RPC channel
+ * @logmsg: NULL terminated string
+ *
+ * Returns: 0 on success
+ */
+static int vmw_send_msg(struct rpc_channel *channel, const char *msg)
+{
+	unsigned long eax, ebx, ecx, edx, si, di, bp;
+	size_t msg_len = strlen(msg);
+	int retries = 0;
+
+
+	while (retries < RETRIES) {
+		retries++;
+
+		/* Set up additional parameters */
+		si  = channel->cookie_high;
+		di  = channel->cookie_low;
+
+		VMW_PORT(VMW_PORT_CMD_SENDSIZE,
+			msg_len, si, di,
+			VMW_HYPERVISOR_PORT | (channel->channel_id << 16),
+			VMW_HYPERVISOR_MAGIC,
+			eax, ebx, ecx, edx, si, di);
+
+		if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0 ||
+		    (HIGH_WORD(ecx) & MESSAGE_STATUS_HB) == 0) {
+			/* Expected success + high-bandwidth. Give up. */
+			return -EINVAL;
+		}
+
+		/* Send msg */
+		si  = (uintptr_t) msg;
+		di  = channel->cookie_low;
+		bp  = channel->cookie_high;
+
+		VMW_PORT_HB_OUT(
+			(MESSAGE_STATUS_SUCCESS << 16) | VMW_PORT_CMD_HB_MSG,
+			msg_len, si, di,
+			VMW_HYPERVISOR_HB_PORT | (channel->channel_id << 16),
+			VMW_HYPERVISOR_MAGIC, bp,
+			eax, ebx, ecx, edx, si, di);
+
+		if ((HIGH_WORD(ebx) & MESSAGE_STATUS_SUCCESS) != 0) {
+			return 0;
+		} else if ((HIGH_WORD(ebx) & MESSAGE_STATUS_CPT) != 0) {
+			/* A checkpoint occurred. Retry. */
+			continue;
+		} else {
+			break;
+		}
+	}
+
+	return -EINVAL;
+}
+STACK_FRAME_NON_STANDARD(vmw_send_msg);
+
+
+/**
+ * vmw_recv_msg: Receives a message from the host
+ *
+ * Note:  It is the caller's responsibility to call kfree() on msg.
+ *
+ * @channel:  channel opened by vmw_open_channel
+ * @msg:  [OUT] message received from the host
+ * @msg_len: message length
+ */
+static int vmw_recv_msg(struct rpc_channel *channel, void **msg,
+			size_t *msg_len)
+{
+	unsigned long eax, ebx, ecx, edx, si, di, bp;
+	char *reply;
+	size_t reply_len;
+	int retries = 0;
+
+
+	*msg_len = 0;
+	*msg = NULL;
+
+	while (retries < RETRIES) {
+		retries++;
+
+		/* Set up additional parameters */
+		si  = channel->cookie_high;
+		di  = channel->cookie_low;
+
+		VMW_PORT(VMW_PORT_CMD_RECVSIZE,
+			0, si, di,
+			(VMW_HYPERVISOR_PORT | (channel->channel_id << 16)),
+			VMW_HYPERVISOR_MAGIC,
+			eax, ebx, ecx, edx, si, di);
+
+		if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0 ||
+		    (HIGH_WORD(ecx) & MESSAGE_STATUS_HB) == 0) {
+			DRM_ERROR("Failed to get reply size\n");
+			return -EINVAL;
+		}
+
+		/* No reply available.  This is okay. */
+		if ((HIGH_WORD(ecx) & MESSAGE_STATUS_DORECV) == 0)
+			return 0;
+
+		reply_len = ebx;
+		reply     = kzalloc(reply_len + 1, GFP_KERNEL);
+		if (reply == NULL) {
+			DRM_ERROR("Cannot allocate memory for reply\n");
+			return -ENOMEM;
+		}
+
+
+		/* Receive buffer */
+		si  = channel->cookie_high;
+		di  = (uintptr_t) reply;
+		bp  = channel->cookie_low;
+
+		VMW_PORT_HB_IN(
+			(MESSAGE_STATUS_SUCCESS << 16) | VMW_PORT_CMD_HB_MSG,
+			reply_len, si, di,
+			VMW_HYPERVISOR_HB_PORT | (channel->channel_id << 16),
+			VMW_HYPERVISOR_MAGIC, bp,
+			eax, ebx, ecx, edx, si, di);
+
+		if ((HIGH_WORD(ebx) & MESSAGE_STATUS_SUCCESS) == 0) {
+			kfree(reply);
+
+			if ((HIGH_WORD(ebx) & MESSAGE_STATUS_CPT) != 0) {
+				/* A checkpoint occurred. Retry. */
+				continue;
+			}
+
+			return -EINVAL;
+		}
+
+		reply[reply_len] = '\0';
+
+
+		/* Ack buffer */
+		si  = channel->cookie_high;
+		di  = channel->cookie_low;
+
+		VMW_PORT(VMW_PORT_CMD_RECVSTATUS,
+			MESSAGE_STATUS_SUCCESS, si, di,
+			(VMW_HYPERVISOR_PORT | (channel->channel_id << 16)),
+			VMW_HYPERVISOR_MAGIC,
+			eax, ebx, ecx, edx, si, di);
+
+		if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0) {
+			kfree(reply);
+
+			if ((HIGH_WORD(ecx) & MESSAGE_STATUS_CPT) != 0) {
+				/* A checkpoint occurred. Retry. */
+				continue;
+			}
+
+			return -EINVAL;
+		}
+
+		break;
+	}
+
+	if (retries == RETRIES)
+		return -EINVAL;
+
+	*msg_len = reply_len;
+	*msg     = reply;
+
+	return 0;
+}
+STACK_FRAME_NON_STANDARD(vmw_recv_msg);
+
+
+/**
+ * vmw_host_get_guestinfo: Gets a GuestInfo parameter
+ *
+ * Gets the value of a  GuestInfo.* parameter.  The value returned will be in
+ * a string, and it is up to the caller to post-process.
+ *
+ * @guest_info_param:  Parameter to get, e.g. GuestInfo.svga.gl3
+ * @buffer: if NULL, *reply_len will contain reply size.
+ * @length: size of the reply_buf.  Set to size of reply upon return
+ *
+ * Returns: 0 on success
+ */
+int vmw_host_get_guestinfo(const char *guest_info_param,
+			   char *buffer, size_t *length)
+{
+	struct rpc_channel channel;
+	char *msg, *reply = NULL;
+	size_t msg_len, reply_len = 0;
+	int ret = 0;
+
+
+	if (!vmw_msg_enabled)
+		return -ENODEV;
+
+	if (!guest_info_param || !length)
+		return -EINVAL;
+
+	msg_len = strlen(guest_info_param) + strlen("info-get ") + 1;
+	msg = kzalloc(msg_len, GFP_KERNEL);
+	if (msg == NULL) {
+		DRM_ERROR("Cannot allocate memory to get %s", guest_info_param);
+		return -ENOMEM;
+	}
+
+	sprintf(msg, "info-get %s", guest_info_param);
+
+	if (vmw_open_channel(&channel, RPCI_PROTOCOL_NUM) ||
+	    vmw_send_msg(&channel, msg) ||
+	    vmw_recv_msg(&channel, (void *) &reply, &reply_len) ||
+	    vmw_close_channel(&channel)) {
+		DRM_ERROR("Failed to get %s", guest_info_param);
+
+		ret = -EINVAL;
+	}
+
+	if (buffer && reply && reply_len > 0) {
+		/* Remove reply code, which are the first 2 characters of
+		 * the reply
+		 */
+		reply_len = max(reply_len - 2, (size_t) 0);
+		reply_len = min(reply_len, *length);
+
+		if (reply_len > 0)
+			memcpy(buffer, reply + 2, reply_len);
+	}
+
+	*length = reply_len;
+
+	kfree(reply);
+	kfree(msg);
+
+	return ret;
+}
+
+
+
+/**
+ * vmw_host_log: Sends a log message to the host
+ *
+ * @log: NULL terminated string
+ *
+ * Returns: 0 on success
+ */
+int vmw_host_log(const char *log)
+{
+	struct rpc_channel channel;
+	char *msg;
+	int msg_len;
+	int ret = 0;
+
+
+	if (!vmw_msg_enabled)
+		return -ENODEV;
+
+	if (!log)
+		return ret;
+
+	msg_len = strlen(log) + strlen("log ") + 1;
+	msg = kzalloc(msg_len, GFP_KERNEL);
+	if (msg == NULL) {
+		DRM_ERROR("Cannot allocate memory for log message\n");
+		return -ENOMEM;
+	}
+
+	sprintf(msg, "log %s", log);
+
+	if (vmw_open_channel(&channel, RPCI_PROTOCOL_NUM) ||
+	    vmw_send_msg(&channel, msg) ||
+	    vmw_close_channel(&channel)) {
+		DRM_ERROR("Failed to send log\n");
+
+		ret = -EINVAL;
+	}
+
+	kfree(msg);
+
+	return ret;
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_msg.h linux-libre-4.7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_msg.h
--- linux-libre-4.6-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_msg.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_msg.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2016, VMware, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * Based on code from vmware.c and vmmouse.c.
+ * Author:
+ *   Sinclair Yeh <syeh@vmware.com>
+ */
+#ifndef _VMWGFX_MSG_H
+#define _VMWGFX_MSG_H
+
+
+/**
+ * Hypervisor-specific bi-directional communication channel.  Should never
+ * execute on bare metal hardware.  The caller must make sure to check for
+ * supported hypervisor before using these macros.
+ *
+ * The last two parameters are both input and output and must be initialized.
+ *
+ * @cmd: [IN] Message Cmd
+ * @in_ebx: [IN] Message Len, through EBX
+ * @in_si: [IN] Input argument through SI, set to 0 if not used
+ * @in_di: [IN] Input argument through DI, set ot 0 if not used
+ * @port_num: [IN] port number + [channel id]
+ * @magic: [IN] hypervisor magic value
+ * @eax: [OUT] value of EAX register
+ * @ebx: [OUT] e.g. status from an HB message status command
+ * @ecx: [OUT] e.g. status from a non-HB message status command
+ * @edx: [OUT] e.g. channel id
+ * @si:  [OUT]
+ * @di:  [OUT]
+ */
+#define VMW_PORT(cmd, in_ebx, in_si, in_di,	\
+		 port_num, magic,		\
+		 eax, ebx, ecx, edx, si, di)	\
+({						\
+	asm volatile ("inl %%dx, %%eax;" :	\
+		"=a"(eax),			\
+		"=b"(ebx),			\
+		"=c"(ecx),			\
+		"=d"(edx),			\
+		"=S"(si),			\
+		"=D"(di) :			\
+		"a"(magic),			\
+		"b"(in_ebx),			\
+		"c"(cmd),			\
+		"d"(port_num),			\
+		"S"(in_si),			\
+		"D"(in_di) :			\
+		"memory");			\
+})
+
+
+/**
+ * Hypervisor-specific bi-directional communication channel.  Should never
+ * execute on bare metal hardware.  The caller must make sure to check for
+ * supported hypervisor before using these macros.
+ *
+ * The last 3 parameters are both input and output and must be initialized.
+ *
+ * @cmd: [IN] Message Cmd
+ * @in_ecx: [IN] Message Len, through ECX
+ * @in_si: [IN] Input argument through SI, set to 0 if not used
+ * @in_di: [IN] Input argument through DI, set to 0 if not used
+ * @port_num: [IN] port number + [channel id]
+ * @magic: [IN] hypervisor magic value
+ * @bp:  [IN]
+ * @eax: [OUT] value of EAX register
+ * @ebx: [OUT] e.g. status from an HB message status command
+ * @ecx: [OUT] e.g. status from a non-HB message status command
+ * @edx: [OUT] e.g. channel id
+ * @si:  [OUT]
+ * @di:  [OUT]
+ */
+#ifdef __x86_64__
+
+#define VMW_PORT_HB_OUT(cmd, in_ecx, in_si, in_di,	\
+			port_num, magic, bp,		\
+			eax, ebx, ecx, edx, si, di)	\
+({							\
+	asm volatile ("push %%rbp;"			\
+		"mov %12, %%rbp;"			\
+		"rep outsb;"				\
+		"pop %%rbp;" :				\
+		"=a"(eax),				\
+		"=b"(ebx),				\
+		"=c"(ecx),				\
+		"=d"(edx),				\
+		"=S"(si),				\
+		"=D"(di) :				\
+		"a"(magic),				\
+		"b"(cmd),				\
+		"c"(in_ecx),				\
+		"d"(port_num),				\
+		"S"(in_si),				\
+		"D"(in_di),				\
+		"r"(bp) :				\
+		"memory", "cc");			\
+})
+
+
+#define VMW_PORT_HB_IN(cmd, in_ecx, in_si, in_di,	\
+		       port_num, magic, bp,		\
+		       eax, ebx, ecx, edx, si, di)	\
+({							\
+	asm volatile ("push %%rbp;"			\
+		"mov %12, %%rbp;"			\
+		"rep insb;"				\
+		"pop %%rbp" :				\
+		"=a"(eax),				\
+		"=b"(ebx),				\
+		"=c"(ecx),				\
+		"=d"(edx),				\
+		"=S"(si),				\
+		"=D"(di) :				\
+		"a"(magic),				\
+		"b"(cmd),				\
+		"c"(in_ecx),				\
+		"d"(port_num),				\
+		"S"(in_si),				\
+		"D"(in_di),				\
+		"r"(bp) :				\
+		"memory", "cc");			\
+})
+
+#else
+
+/* In the 32-bit version of this macro, we use "m" because there is no
+ * more register left for bp
+ */
+#define VMW_PORT_HB_OUT(cmd, in_ecx, in_si, in_di,	\
+			port_num, magic, bp,		\
+			eax, ebx, ecx, edx, si, di)	\
+({							\
+	asm volatile ("push %%ebp;"			\
+		"mov %12, %%ebp;"			\
+		"rep outsb;"				\
+		"pop %%ebp;" :				\
+		"=a"(eax),				\
+		"=b"(ebx),				\
+		"=c"(ecx),				\
+		"=d"(edx),				\
+		"=S"(si),				\
+		"=D"(di) :				\
+		"a"(magic),				\
+		"b"(cmd),				\
+		"c"(in_ecx),				\
+		"d"(port_num),				\
+		"S"(in_si),				\
+		"D"(in_di),				\
+		"m"(bp) :				\
+		"memory", "cc");			\
+})
+
+
+#define VMW_PORT_HB_IN(cmd, in_ecx, in_si, in_di,	\
+		       port_num, magic, bp,		\
+		       eax, ebx, ecx, edx, si, di)	\
+({							\
+	asm volatile ("push %%ebp;"			\
+		"mov %12, %%ebp;"			\
+		"rep insb;"				\
+		"pop %%ebp" :				\
+		"=a"(eax),				\
+		"=b"(ebx),				\
+		"=c"(ecx),				\
+		"=d"(edx),				\
+		"=S"(si),				\
+		"=D"(di) :				\
+		"a"(magic),				\
+		"b"(cmd),				\
+		"c"(in_ecx),				\
+		"d"(port_num),				\
+		"S"(in_si),				\
+		"D"(in_di),				\
+		"m"(bp) :				\
+		"memory", "cc");			\
+})
+#endif /* #if __x86_64__ */
+
+#endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c linux-libre-4.7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c	2016-07-24 15:23:50.000000000 -0400
@@ -129,7 +129,7 @@ static void vmw_resource_release(struct
 	if (res->backup) {
 		struct ttm_buffer_object *bo = &res->backup->base;
 
-		ttm_bo_reserve(bo, false, false, false, NULL);
+		ttm_bo_reserve(bo, false, false, NULL);
 		if (!list_empty(&res->mob_head) &&
 		    res->func->unbind != NULL) {
 			struct ttm_validate_buffer val_buf;
@@ -1512,7 +1512,7 @@ void vmw_resource_move_notify(struct ttm
 			list_del_init(&res->mob_head);
 		}
 
-		(void) ttm_bo_wait(bo, false, false, false);
+		(void) ttm_bo_wait(bo, false, false);
 	}
 }
 
@@ -1605,7 +1605,7 @@ void vmw_query_move_notify(struct ttm_bu
 		if (fence != NULL)
 			vmw_fence_obj_unreference(&fence);
 
-		(void) ttm_bo_wait(bo, false, false, false);
+		(void) ttm_bo_wait(bo, false, false);
 	} else
 		mutex_unlock(&dev_priv->binding_mutex);
 
@@ -1717,8 +1717,7 @@ int vmw_resource_pin(struct vmw_resource
 		if (res->backup) {
 			vbo = res->backup;
 
-			ttm_bo_reserve(&vbo->base, interruptible, false, false,
-				       NULL);
+			ttm_bo_reserve(&vbo->base, interruptible, false, NULL);
 			if (!vbo->pin_count) {
 				ret = ttm_bo_validate
 					(&vbo->base,
@@ -1773,7 +1772,7 @@ void vmw_resource_unpin(struct vmw_resou
 	if (--res->pin_count == 0 && res->backup) {
 		struct vmw_dma_buffer *vbo = res->backup;
 
-		ttm_bo_reserve(&vbo->base, false, false, false, NULL);
+		ttm_bo_reserve(&vbo->base, false, false, NULL);
 		vmw_bo_pin_reserved(vbo, false);
 		ttm_bo_unreserve(&vbo->base);
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c linux-libre-4.7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c	2016-07-24 15:23:50.000000000 -0400
@@ -285,14 +285,17 @@ static int vmw_sou_crtc_set_config(struc
 	}
 
 	/* Only one active implicit frame-buffer at a time. */
+	mutex_lock(&dev_priv->global_kms_state_mutex);
 	if (sou->base.is_implicit &&
 	    dev_priv->implicit_fb && vfb &&
 	    !(dev_priv->num_implicit == 1 &&
 	      sou->base.active_implicit) &&
 	    dev_priv->implicit_fb != vfb) {
+		mutex_unlock(&dev_priv->global_kms_state_mutex);
 		DRM_ERROR("Multiple implicit framebuffers not supported.\n");
 		return -EINVAL;
 	}
+	mutex_unlock(&dev_priv->global_kms_state_mutex);
 
 	/* since they always map one to one these are safe */
 	connector = &sou->base.connector;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c linux-libre-4.7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c	2016-07-24 15:23:50.000000000 -0400
@@ -988,7 +988,7 @@ int vmw_compat_shader_add(struct vmw_pri
 	if (unlikely(ret != 0))
 		goto out;
 
-	ret = ttm_bo_reserve(&buf->base, false, true, false, NULL);
+	ret = ttm_bo_reserve(&buf->base, false, true, NULL);
 	if (unlikely(ret != 0))
 		goto no_reserve;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c linux-libre-4.7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
--- linux-libre-4.6-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c	2016-07-24 15:23:50.000000000 -0400
@@ -399,8 +399,10 @@ static int vmw_stdu_bind_fb(struct vmw_p
 
 	WARN_ON_ONCE(!stdu->defined);
 
-	if (!vfb->dmabuf && new_fb->width == mode->hdisplay &&
-	    new_fb->height == mode->vdisplay)
+	new_vfbs = (vfb->dmabuf) ? NULL : vmw_framebuffer_to_vfbs(new_fb);
+
+	if (new_vfbs && new_vfbs->surface->base_size.width == mode->hdisplay &&
+	    new_vfbs->surface->base_size.height == mode->vdisplay)
 		new_content_type = SAME_AS_DISPLAY;
 	else if (vfb->dmabuf)
 		new_content_type = SEPARATE_DMA;
@@ -444,7 +446,6 @@ static int vmw_stdu_bind_fb(struct vmw_p
 			content_srf.mip_levels[0]     = 1;
 			content_srf.multisample_count = 0;
 		} else {
-			new_vfbs = vmw_framebuffer_to_vfbs(new_fb);
 			content_srf = *new_vfbs->surface;
 		}
 
@@ -464,7 +465,6 @@ static int vmw_stdu_bind_fb(struct vmw_p
 			return ret;
 		}
 	} else if (new_content_type == SAME_AS_DISPLAY) {
-		new_vfbs = vmw_framebuffer_to_vfbs(new_fb);
 		new_display_srf = vmw_surface_reference(new_vfbs->surface);
 	}
 
@@ -553,12 +553,15 @@ static int vmw_stdu_crtc_set_config(stru
 	}
 
 	/* Only one active implicit frame-buffer at a time. */
+	mutex_lock(&dev_priv->global_kms_state_mutex);
 	if (!turning_off && stdu->base.is_implicit && dev_priv->implicit_fb &&
 	    !(dev_priv->num_implicit == 1 && stdu->base.active_implicit)
 	    && dev_priv->implicit_fb != vfb) {
+		mutex_unlock(&dev_priv->global_kms_state_mutex);
 		DRM_ERROR("Multiple implicit framebuffers not supported.\n");
 		return -EINVAL;
 	}
+	mutex_unlock(&dev_priv->global_kms_state_mutex);
 
 	/* Since they always map one to one these are safe */
 	connector = &stdu->base.connector;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/host1x/hw/intr_hw.c linux-libre-4.7-gnu/drivers/gpu/host1x/hw/intr_hw.c
--- linux-libre-4.6-gnu/drivers/gpu/host1x/hw/intr_hw.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/host1x/hw/intr_hw.c	2016-07-24 15:23:50.000000000 -0400
@@ -85,7 +85,7 @@ static int _host1x_intr_init_host_sync(s
 	err = devm_request_irq(host->dev, host->intr_syncpt_irq,
 			       syncpt_thresh_isr, IRQF_SHARED,
 			       "host1x_syncpt", host);
-	if (IS_ERR_VALUE(err)) {
+	if (err < 0) {
 		WARN_ON(1);
 		return err;
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/gpu/ipu-v3/ipu-common.c linux-libre-4.7-gnu/drivers/gpu/ipu-v3/ipu-common.c
--- linux-libre-4.6-gnu/drivers/gpu/ipu-v3/ipu-common.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/gpu/ipu-v3/ipu-common.c	2016-07-24 15:23:50.000000000 -0400
@@ -997,7 +997,7 @@ struct ipu_platform_reg {
 };
 
 /* These must be in the order of the corresponding device tree port nodes */
-static const struct ipu_platform_reg client_reg[] = {
+static struct ipu_platform_reg client_reg[] = {
 	{
 		.pdata = {
 			.csi = 0,
@@ -1048,7 +1048,7 @@ static int ipu_add_client_devices(struct
 	mutex_unlock(&ipu_client_id_mutex);
 
 	for (i = 0; i < ARRAY_SIZE(client_reg); i++) {
-		const struct ipu_platform_reg *reg = &client_reg[i];
+		struct ipu_platform_reg *reg = &client_reg[i];
 		struct platform_device *pdev;
 		struct device_node *of_node;
 
@@ -1070,6 +1070,7 @@ static int ipu_add_client_devices(struct
 
 		pdev->dev.parent = dev;
 
+		reg->pdata.of_node = of_node;
 		ret = platform_device_add_data(pdev, &reg->pdata,
 					       sizeof(reg->pdata));
 		if (!ret)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hid/hid-asus.c linux-libre-4.7-gnu/drivers/hid/hid-asus.c
--- linux-libre-4.6-gnu/drivers/hid/hid-asus.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/hid/hid-asus.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,52 @@
+/*
+ *  HID driver for Asus notebook built-in keyboard.
+ *  Fixes small logical maximum to match usage maximum.
+ *
+ *  Currently supported devices are:
+ *    EeeBook X205TA
+ *    VivoBook E200HA
+ *
+ *  Copyright (c) 2016 Yusuke Fujimaki <usk.fujimaki@gmail.com>
+ *
+ *  This module based on hid-ortek by
+ *  Copyright (c) 2010 Johnathon Harris <jmharris@gmail.com>
+ *  Copyright (c) 2011 Jiri Kosina
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+static __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+		unsigned int *rsize)
+{
+	if (*rsize >= 56 && rdesc[54] == 0x25 && rdesc[55] == 0x65) {
+		hid_info(hdev, "Fixing up Asus notebook report descriptor\n");
+		rdesc[55] = 0xdd;
+	}
+	return rdesc;
+}
+
+static const struct hid_device_id asus_devices[] = {
+	{ HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_NOTEBOOK_KEYBOARD) },
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, asus_devices);
+
+static struct hid_driver asus_driver = {
+	.name = "asus",
+	.id_table = asus_devices,
+	.report_fixup = asus_report_fixup
+};
+module_hid_driver(asus_driver);
+
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hid/hid-core.c linux-libre-4.7-gnu/drivers/hid/hid-core.c
--- linux-libre-4.6-gnu/drivers/hid/hid-core.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hid/hid-core.c	2016-07-24 15:23:50.000000000 -0400
@@ -1129,48 +1129,45 @@ EXPORT_SYMBOL_GPL(hid_field_extract);
 static void __implement(u8 *report, unsigned offset, int n, u32 value)
 {
 	unsigned int idx = offset / 8;
-	unsigned int size = offset + n;
 	unsigned int bit_shift = offset % 8;
 	int bits_to_set = 8 - bit_shift;
-	u8 bit_mask = 0xff << bit_shift;
 
 	while (n - bits_to_set >= 0) {
-		report[idx] &= ~bit_mask;
+		report[idx] &= ~(0xff << bit_shift);
 		report[idx] |= value << bit_shift;
 		value >>= bits_to_set;
 		n -= bits_to_set;
 		bits_to_set = 8;
-		bit_mask = 0xff;
 		bit_shift = 0;
 		idx++;
 	}
 
 	/* last nibble */
 	if (n) {
-		if (size % 8)
-			bit_mask &= (1U << (size % 8)) - 1;
-		report[idx] &= ~bit_mask;
-		report[idx] |= (value << bit_shift) & bit_mask;
+		u8 bit_mask = ((1U << n) - 1);
+		report[idx] &= ~(bit_mask << bit_shift);
+		report[idx] |= value << bit_shift;
 	}
 }
 
 static void implement(const struct hid_device *hid, u8 *report,
 		      unsigned offset, unsigned n, u32 value)
 {
-	u64 m;
-
-	if (n > 32) {
+	if (unlikely(n > 32)) {
 		hid_warn(hid, "%s() called with n (%d) > 32! (%s)\n",
 			 __func__, n, current->comm);
 		n = 32;
-	}
+	} else if (n < 32) {
+		u32 m = (1U << n) - 1;
 
-	m = (1ULL << n) - 1;
-	if (value > m)
-		hid_warn(hid, "%s() called with too large value %d! (%s)\n",
-			 __func__, value, current->comm);
-	WARN_ON(value > m);
-	value &= m;
+		if (unlikely(value > m)) {
+			hid_warn(hid,
+				 "%s() called with too large value %d (n: %d)! (%s)\n",
+				 __func__, value, n, current->comm);
+			WARN_ON(1);
+			value &= m;
+		}
+	}
 
 	__implement(report, offset, n, value);
 }
@@ -1856,6 +1853,7 @@ static const struct hid_device_id hid_ha
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_JIS) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
+	{ HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_NOTEBOOK_KEYBOARD) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_AUREAL, USB_DEVICE_ID_AUREAL_W01RN) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185BFM, 0x2208) },
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hid/hid-elo.c linux-libre-4.7-gnu/drivers/hid/hid-elo.c
--- linux-libre-4.6-gnu/drivers/hid/hid-elo.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hid/hid-elo.c	2016-07-24 15:23:50.000000000 -0400
@@ -261,7 +261,7 @@ static void elo_remove(struct hid_device
 	struct elo_priv *priv = hid_get_drvdata(hdev);
 
 	hid_hw_stop(hdev);
-	flush_workqueue(wq);
+	cancel_delayed_work_sync(&priv->work);
 	kfree(priv);
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hid/hid-ids.h linux-libre-4.7-gnu/drivers/hid/hid-ids.h
--- linux-libre-4.6-gnu/drivers/hid/hid-ids.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hid/hid-ids.h	2016-07-24 15:23:50.000000000 -0400
@@ -163,6 +163,7 @@
 #define USB_VENDOR_ID_ASUSTEK		0x0b05
 #define USB_DEVICE_ID_ASUSTEK_LCM	0x1726
 #define USB_DEVICE_ID_ASUSTEK_LCM2	0x175b
+#define USB_DEVICE_ID_ASUSTEK_NOTEBOOK_KEYBOARD	0x8585
 
 #define USB_VENDOR_ID_ATEN		0x0557
 #define USB_DEVICE_ID_ATEN_UC100KM	0x2004
@@ -258,6 +259,13 @@
 #define USB_VENDOR_ID_CORSAIR		0x1b1c
 #define USB_DEVICE_ID_CORSAIR_K90	0x1b02
 
+#define USB_VENDOR_ID_CORSAIR           0x1b1c
+#define USB_DEVICE_ID_CORSAIR_K70R      0x1b09
+#define USB_DEVICE_ID_CORSAIR_K95RGB    0x1b11
+#define USB_DEVICE_ID_CORSAIR_M65RGB    0x1b12
+#define USB_DEVICE_ID_CORSAIR_K70RGB    0x1b13
+#define USB_DEVICE_ID_CORSAIR_K65RGB    0x1b17
+
 #define USB_VENDOR_ID_CREATIVELABS	0x041e
 #define USB_DEVICE_ID_CREATIVE_SB_OMNI_SURROUND_51	0x322c
 #define USB_DEVICE_ID_PRODIKEYS_PCMIDI	0x2801
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hid/hid-multitouch.c linux-libre-4.7-gnu/drivers/hid/hid-multitouch.c
--- linux-libre-4.6-gnu/drivers/hid/hid-multitouch.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hid/hid-multitouch.c	2016-07-24 15:23:50.000000000 -0400
@@ -61,6 +61,7 @@ MODULE_LICENSE("GPL");
 #define MT_QUIRK_ALWAYS_VALID		(1 << 4)
 #define MT_QUIRK_VALID_IS_INRANGE	(1 << 5)
 #define MT_QUIRK_VALID_IS_CONFIDENCE	(1 << 6)
+#define MT_QUIRK_CONFIDENCE		(1 << 7)
 #define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE	(1 << 8)
 #define MT_QUIRK_NO_AREA		(1 << 9)
 #define MT_QUIRK_IGNORE_DUPLICATES	(1 << 10)
@@ -78,6 +79,7 @@ struct mt_slot {
 	__s32 contactid;	/* the device ContactID assigned to this slot */
 	bool touch_state;	/* is the touch valid? */
 	bool inrange_state;	/* is the finger in proximity of the sensor? */
+	bool confidence_state;  /* is the touch made by a finger? */
 };
 
 struct mt_class {
@@ -503,10 +505,8 @@ static int mt_touch_input_mapping(struct
 			return 1;
 		case HID_DG_CONFIDENCE:
 			if (cls->name == MT_CLS_WIN_8 &&
-				field->application == HID_DG_TOUCHPAD) {
-				cls->quirks &= ~MT_QUIRK_ALWAYS_VALID;
-				cls->quirks |= MT_QUIRK_VALID_IS_CONFIDENCE;
-			}
+				field->application == HID_DG_TOUCHPAD)
+				cls->quirks |= MT_QUIRK_CONFIDENCE;
 			mt_store_field(usage, td, hi);
 			return 1;
 		case HID_DG_TIPSWITCH:
@@ -619,6 +619,7 @@ static void mt_complete_slot(struct mt_d
 		return;
 
 	if (td->curvalid || (td->mtclass.quirks & MT_QUIRK_ALWAYS_VALID)) {
+		int active;
 		int slotnum = mt_compute_slot(td, input);
 		struct mt_slot *s = &td->curdata;
 		struct input_mt *mt = input->mt;
@@ -633,10 +634,14 @@ static void mt_complete_slot(struct mt_d
 				return;
 		}
 
+		if (!(td->mtclass.quirks & MT_QUIRK_CONFIDENCE))
+			s->confidence_state = 1;
+		active = (s->touch_state || s->inrange_state) &&
+							s->confidence_state;
+
 		input_mt_slot(input, slotnum);
-		input_mt_report_slot_state(input, MT_TOOL_FINGER,
-			s->touch_state || s->inrange_state);
-		if (s->touch_state || s->inrange_state) {
+		input_mt_report_slot_state(input, MT_TOOL_FINGER, active);
+		if (active) {
 			/* this finger is in proximity of the sensor */
 			int wide = (s->w > s->h);
 			/* divided by two to match visual scale of touch */
@@ -701,6 +706,8 @@ static void mt_process_mt_event(struct h
 			td->curdata.touch_state = value;
 			break;
 		case HID_DG_CONFIDENCE:
+			if (quirks & MT_QUIRK_CONFIDENCE)
+				td->curdata.confidence_state = value;
 			if (quirks & MT_QUIRK_VALID_IS_CONFIDENCE)
 				td->curvalid = value;
 			break;
@@ -1401,6 +1408,11 @@ static const struct hid_device_id mt_dev
 		MT_USB_DEVICE(USB_VENDOR_ID_NOVATEK,
 			USB_DEVICE_ID_NOVATEK_PCT) },
 
+	/* Ntrig Panel */
+	{ .driver_data = MT_CLS_NSMU,
+		HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
+			USB_VENDOR_ID_NTRIG, 0x1b05) },
+
 	/* PixArt optical touch screen */
 	{ .driver_data = MT_CLS_INRANGE_CONTACTNUMBER,
 		MT_USB_DEVICE(USB_VENDOR_ID_PIXART,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hid/hidraw.c linux-libre-4.7-gnu/drivers/hid/hidraw.c
--- linux-libre-4.6-gnu/drivers/hid/hidraw.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hid/hidraw.c	2016-07-24 15:23:50.000000000 -0400
@@ -34,6 +34,7 @@
 #include <linux/hid.h>
 #include <linux/mutex.h>
 #include <linux/sched.h>
+#include <linux/string.h>
 
 #include <linux/hidraw.h>
 
@@ -123,7 +124,6 @@ static ssize_t hidraw_send_report(struct
 
 	dev = hidraw_table[minor]->hid;
 
-
 	if (count > HID_MAX_BUFFER_SIZE) {
 		hid_warn(dev, "pid %d passed too large report\n",
 			 task_pid_nr(current));
@@ -138,17 +138,12 @@ static ssize_t hidraw_send_report(struct
 		goto out;
 	}
 
-	buf = kmalloc(count * sizeof(__u8), GFP_KERNEL);
-	if (!buf) {
-		ret = -ENOMEM;
+	buf = memdup_user(buffer, count);
+	if (IS_ERR(buf)) {
+		ret = PTR_ERR(buf);
 		goto out;
 	}
 
-	if (copy_from_user(buf, buffer, count)) {
-		ret = -EFAULT;
-		goto out_free;
-	}
-
 	if ((report_type == HID_OUTPUT_REPORT) &&
 	    !(dev->quirks & HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP)) {
 		ret = hid_hw_output_report(dev, buf, count);
@@ -587,14 +582,13 @@ int __init hidraw_init(void)
 
 	result = alloc_chrdev_region(&dev_id, HIDRAW_FIRST_MINOR,
 			HIDRAW_MAX_DEVICES, "hidraw");
-
-	hidraw_major = MAJOR(dev_id);
-
 	if (result < 0) {
 		pr_warn("can't get major number\n");
 		goto out;
 	}
 
+	hidraw_major = MAJOR(dev_id);
+
 	hidraw_class = class_create(THIS_MODULE, "hidraw");
 	if (IS_ERR(hidraw_class)) {
 		result = PTR_ERR(hidraw_class);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hid/hid-roccat.c linux-libre-4.7-gnu/drivers/hid/hid-roccat.c
--- linux-libre-4.6-gnu/drivers/hid/hid-roccat.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hid/hid-roccat.c	2016-07-24 15:23:50.000000000 -0400
@@ -421,14 +421,13 @@ static int __init roccat_init(void)
 
 	retval = alloc_chrdev_region(&dev_id, ROCCAT_FIRST_MINOR,
 			ROCCAT_MAX_DEVICES, "roccat");
-
-	roccat_major = MAJOR(dev_id);
-
 	if (retval < 0) {
 		pr_warn("can't get major number\n");
 		goto error;
 	}
 
+	roccat_major = MAJOR(dev_id);
+
 	cdev_init(&roccat_cdev, &roccat_ops);
 	retval = cdev_add(&roccat_cdev, dev_id, ROCCAT_MAX_DEVICES);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hid/hid-thingm.c linux-libre-4.7-gnu/drivers/hid/hid-thingm.c
--- linux-libre-4.6-gnu/drivers/hid/hid-thingm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hid/hid-thingm.c	2016-07-24 15:23:50.000000000 -0400
@@ -148,13 +148,21 @@ static int thingm_led_set(struct led_cla
 			  enum led_brightness brightness)
 {
 	struct thingm_led *led = container_of(ldev, struct thingm_led, ldev);
-	int ret;
 
-	ret = thingm_write_color(led->rgb);
-	if (ret)
-		hid_err(led->rgb->tdev->hdev, "failed to write color\n");
+	return thingm_write_color(led->rgb);
+}
 
-	return ret;
+static int thingm_init_led(struct thingm_led *led, const char *color_name,
+			   struct thingm_rgb *rgb, int minor)
+{
+	snprintf(led->name, sizeof(led->name), "thingm%d:%s:led%d",
+		 minor, color_name, rgb->num);
+	led->ldev.name = led->name;
+	led->ldev.max_brightness = 255;
+	led->ldev.brightness_set_blocking = thingm_led_set;
+	led->ldev.flags = LED_HW_PLUGGABLE;
+	led->rgb = rgb;
+	return devm_led_classdev_register(&rgb->tdev->hdev->dev, &led->ldev);
 }
 
 static int thingm_init_rgb(struct thingm_rgb *rgb)
@@ -163,42 +171,17 @@ static int thingm_init_rgb(struct thingm
 	int err;
 
 	/* Register the red diode */
-	snprintf(rgb->red.name, sizeof(rgb->red.name),
-			"thingm%d:red:led%d", minor, rgb->num);
-	rgb->red.ldev.name = rgb->red.name;
-	rgb->red.ldev.max_brightness = 255;
-	rgb->red.ldev.brightness_set_blocking = thingm_led_set;
-	rgb->red.rgb = rgb;
-
-	err = devm_led_classdev_register(&rgb->tdev->hdev->dev,
-					 &rgb->red.ldev);
+	err = thingm_init_led(&rgb->red, "red", rgb, minor);
 	if (err)
 		return err;
 
 	/* Register the green diode */
-	snprintf(rgb->green.name, sizeof(rgb->green.name),
-			"thingm%d:green:led%d", minor, rgb->num);
-	rgb->green.ldev.name = rgb->green.name;
-	rgb->green.ldev.max_brightness = 255;
-	rgb->green.ldev.brightness_set_blocking = thingm_led_set;
-	rgb->green.rgb = rgb;
-
-	err = devm_led_classdev_register(&rgb->tdev->hdev->dev,
-					 &rgb->green.ldev);
+	err = thingm_init_led(&rgb->green, "green", rgb, minor);
 	if (err)
 		return err;
 
 	/* Register the blue diode */
-	snprintf(rgb->blue.name, sizeof(rgb->blue.name),
-			"thingm%d:blue:led%d", minor, rgb->num);
-	rgb->blue.ldev.name = rgb->blue.name;
-	rgb->blue.ldev.max_brightness = 255;
-	rgb->blue.ldev.brightness_set_blocking = thingm_led_set;
-	rgb->blue.rgb = rgb;
-
-	err = devm_led_classdev_register(&rgb->tdev->hdev->dev,
-					 &rgb->blue.ldev);
-	return err;
+	return thingm_init_led(&rgb->blue, "blue", rgb, minor);
 }
 
 static int thingm_probe(struct hid_device *hdev, const struct hid_device_id *id)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hid/Kconfig linux-libre-4.7-gnu/drivers/hid/Kconfig
--- linux-libre-4.6-gnu/drivers/hid/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hid/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -134,6 +134,16 @@ config HID_APPLEIR
 
 	Say Y here if you want support for Apple infrared remote control.
 
+config HID_ASUS
+	tristate "Asus"
+	depends on I2C_HID
+	---help---
+	Support for Asus notebook built-in keyboard via i2c.
+
+	Supported devices:
+	- EeeBook X205TA
+	- VivoBook E200HA
+
 config HID_AUREAL
 	tristate "Aureal"
 	depends on HID
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hid/Makefile linux-libre-4.7-gnu/drivers/hid/Makefile
--- linux-libre-4.6-gnu/drivers/hid/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hid/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -24,6 +24,7 @@ obj-$(CONFIG_HID_A4TECH)	+= hid-a4tech.o
 obj-$(CONFIG_HID_ACRUX)		+= hid-axff.o
 obj-$(CONFIG_HID_APPLE)		+= hid-apple.o
 obj-$(CONFIG_HID_APPLEIR)	+= hid-appleir.o
+obj-$(CONFIG_HID_ASUS)		+= hid-asus.o
 obj-$(CONFIG_HID_AUREAL)	+= hid-aureal.o
 obj-$(CONFIG_HID_BELKIN)	+= hid-belkin.o
 obj-$(CONFIG_HID_BETOP_FF)	+= hid-betopff.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hid/usbhid/hiddev.c linux-libre-4.7-gnu/drivers/hid/usbhid/hiddev.c
--- linux-libre-4.6-gnu/drivers/hid/usbhid/hiddev.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hid/usbhid/hiddev.c	2016-07-24 15:23:50.000000000 -0400
@@ -516,13 +516,13 @@ static noinline int hiddev_ioctl_usage(s
 					goto inval;
 			} else if (uref->usage_index >= field->report_count)
 				goto inval;
-
-			else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) &&
-				 (uref_multi->num_values > HID_MAX_MULTI_USAGES ||
-				  uref->usage_index + uref_multi->num_values > field->report_count))
-				goto inval;
 		}
 
+		if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) &&
+		    (uref_multi->num_values > HID_MAX_MULTI_USAGES ||
+		     uref->usage_index + uref_multi->num_values > field->report_count))
+			goto inval;
+
 		switch (cmd) {
 		case HIDIOCGUSAGE:
 			uref->value = field->value[uref->usage_index];
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hid/usbhid/hid-quirks.c linux-libre-4.7-gnu/drivers/hid/usbhid/hid-quirks.c
--- linux-libre-4.6-gnu/drivers/hid/usbhid/hid-quirks.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hid/usbhid/hid-quirks.c	2016-07-24 15:23:50.000000000 -0400
@@ -71,6 +71,11 @@ static const struct hid_blacklist {
 	{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_3AXIS_5BUTTON_STICK, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE, HID_QUIRK_ALWAYS_POLL },
+	{ USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K70R, HID_QUIRK_NO_INIT_REPORTS },
+	{ USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_M65RGB, HID_QUIRK_NO_INIT_REPORTS },
+	{ USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K95RGB, HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
+	{ USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K70RGB, HID_QUIRK_NO_INIT_REPORTS },
+	{ USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K65RGB, HID_QUIRK_NO_INIT_REPORTS },
 	{ USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_CREATIVE_SB_OMNI_SURROUND_51, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_WIIU, HID_QUIRK_MULTI_INPUT },
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hid/wacom_sys.c linux-libre-4.7-gnu/drivers/hid/wacom_sys.c
--- linux-libre-4.6-gnu/drivers/hid/wacom_sys.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hid/wacom_sys.c	2016-07-24 15:23:50.000000000 -0400
@@ -493,7 +493,8 @@ static void wacom_retrieve_hid_descripto
 	features->x_fuzz = 4;
 	features->y_fuzz = 4;
 	features->pressure_fuzz = 0;
-	features->distance_fuzz = 0;
+	features->distance_fuzz = 1;
+	features->tilt_fuzz = 1;
 
 	/*
 	 * The wireless device HID is basic and layout conflicts with
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hid/wacom_wac.c linux-libre-4.7-gnu/drivers/hid/wacom_wac.c
--- linux-libre-4.6-gnu/drivers/hid/wacom_wac.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hid/wacom_wac.c	2016-07-24 15:23:50.000000000 -0400
@@ -2344,12 +2344,13 @@ static void wacom_setup_basic_pro_pen(st
 	__set_bit(BTN_STYLUS2, input_dev->keybit);
 
 	input_set_abs_params(input_dev, ABS_DISTANCE,
-			     0, wacom_wac->features.distance_max, 0, 0);
+			     0, wacom_wac->features.distance_max, wacom_wac->features.distance_fuzz, 0);
 }
 
 static void wacom_setup_cintiq(struct wacom_wac *wacom_wac)
 {
 	struct input_dev *input_dev = wacom_wac->pen_input;
+	struct wacom_features *features = &wacom_wac->features;
 
 	wacom_setup_basic_pro_pen(wacom_wac);
 
@@ -2359,9 +2360,9 @@ static void wacom_setup_cintiq(struct wa
 	__set_bit(BTN_TOOL_AIRBRUSH, input_dev->keybit);
 
 	input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0);
-	input_set_abs_params(input_dev, ABS_TILT_X, -64, 63, 0, 0);
+	input_set_abs_params(input_dev, ABS_TILT_X, -64, 63, features->tilt_fuzz, 0);
 	input_abs_set_res(input_dev, ABS_TILT_X, 57);
-	input_set_abs_params(input_dev, ABS_TILT_Y, -64, 63, 0, 0);
+	input_set_abs_params(input_dev, ABS_TILT_Y, -64, 63, features->tilt_fuzz, 0);
 	input_abs_set_res(input_dev, ABS_TILT_Y, 57);
 }
 
@@ -2507,7 +2508,7 @@ int wacom_setup_pen_input_capabilities(s
 	case WACOM_G4:
 		input_set_abs_params(input_dev, ABS_DISTANCE, 0,
 					      features->distance_max,
-					      0, 0);
+					      features->distance_fuzz, 0);
 		/* fall through */
 
 	case GRAPHIRE:
@@ -2569,7 +2570,7 @@ int wacom_setup_pen_input_capabilities(s
 
 		input_set_abs_params(input_dev, ABS_DISTANCE, 0,
 				      features->distance_max,
-				      0, 0);
+				      features->distance_fuzz, 0);
 
 		input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
 		input_abs_set_res(input_dev, ABS_Z, 287);
@@ -2628,7 +2629,7 @@ int wacom_setup_pen_input_capabilities(s
 			__set_bit(BTN_STYLUS2, input_dev->keybit);
 			input_set_abs_params(input_dev, ABS_DISTANCE, 0,
 				      features->distance_max,
-				      0, 0);
+				      features->distance_fuzz, 0);
 		}
 		break;
 	case BAMBOO_PAD:
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hid/wacom_wac.h linux-libre-4.7-gnu/drivers/hid/wacom_wac.h
--- linux-libre-4.6-gnu/drivers/hid/wacom_wac.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hid/wacom_wac.h	2016-07-24 15:23:50.000000000 -0400
@@ -177,6 +177,7 @@ struct wacom_features {
 	int y_fuzz;
 	int pressure_fuzz;
 	int distance_fuzz;
+	int tilt_fuzz;
 	unsigned quirks;
 	unsigned touch_max;
 	int oVid;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hsi/controllers/Kconfig linux-libre-4.7-gnu/drivers/hsi/controllers/Kconfig
--- linux-libre-4.6-gnu/drivers/hsi/controllers/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hsi/controllers/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -5,15 +5,11 @@ comment "HSI controllers"
 
 config OMAP_SSI
 	tristate "OMAP SSI hardware driver"
-	depends on HSI && OF && (ARCH_OMAP3 || (ARM && COMPILE_TEST))
+	depends on HSI && OF && ARM && COMMON_CLK
+	depends on ARCH_OMAP3 || COMPILE_TEST
 	---help---
 	  SSI is a legacy version of HSI. It is usually used to connect
 	  an application engine with a cellular modem.
 	  If you say Y here, you will enable the OMAP SSI hardware driver.
 
 	  If unsure, say N.
-
-config OMAP_SSI_PORT
-	tristate
-	default m if OMAP_SSI=m
-	default y if OMAP_SSI=y
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hsi/controllers/Makefile linux-libre-4.7-gnu/drivers/hsi/controllers/Makefile
--- linux-libre-4.6-gnu/drivers/hsi/controllers/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hsi/controllers/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -2,5 +2,5 @@
 # Makefile for HSI controllers drivers
 #
 
-obj-$(CONFIG_OMAP_SSI)		+= omap_ssi.o
-obj-$(CONFIG_OMAP_SSI_PORT)	+= omap_ssi_port.o
+omap_ssi-objs		+= omap_ssi_core.o omap_ssi_port.o
+obj-$(CONFIG_OMAP_SSI)	+= omap_ssi.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hsi/controllers/omap_ssi.c linux-libre-4.7-gnu/drivers/hsi/controllers/omap_ssi.c
--- linux-libre-4.6-gnu/drivers/hsi/controllers/omap_ssi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hsi/controllers/omap_ssi.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,610 +0,0 @@
-/* OMAP SSI driver.
- *
- * Copyright (C) 2010 Nokia Corporation. All rights reserved.
- * Copyright (C) 2014 Sebastian Reichel <sre@kernel.org>
- *
- * Contact: Carlos Chinea <carlos.chinea@nokia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * 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
- */
-
-#include <linux/compiler.h>
-#include <linux/err.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/clk.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/dmaengine.h>
-#include <linux/delay.h>
-#include <linux/seq_file.h>
-#include <linux/scatterlist.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/debugfs.h>
-#include <linux/pm_runtime.h>
-#include <linux/of_platform.h>
-#include <linux/hsi/hsi.h>
-#include <linux/idr.h>
-
-#include "omap_ssi_regs.h"
-#include "omap_ssi.h"
-
-/* For automatically allocated device IDs */
-static DEFINE_IDA(platform_omap_ssi_ida);
-
-#ifdef CONFIG_DEBUG_FS
-static int ssi_debug_show(struct seq_file *m, void *p __maybe_unused)
-{
-	struct hsi_controller *ssi = m->private;
-	struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
-	void __iomem *sys = omap_ssi->sys;
-
-	pm_runtime_get_sync(ssi->device.parent);
-	seq_printf(m, "REVISION\t: 0x%08x\n",  readl(sys + SSI_REVISION_REG));
-	seq_printf(m, "SYSCONFIG\t: 0x%08x\n", readl(sys + SSI_SYSCONFIG_REG));
-	seq_printf(m, "SYSSTATUS\t: 0x%08x\n", readl(sys + SSI_SYSSTATUS_REG));
-	pm_runtime_put_sync(ssi->device.parent);
-
-	return 0;
-}
-
-static int ssi_debug_gdd_show(struct seq_file *m, void *p __maybe_unused)
-{
-	struct hsi_controller *ssi = m->private;
-	struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
-	void __iomem *gdd = omap_ssi->gdd;
-	void __iomem *sys = omap_ssi->sys;
-	int lch;
-
-	pm_runtime_get_sync(ssi->device.parent);
-
-	seq_printf(m, "GDD_MPU_STATUS\t: 0x%08x\n",
-		readl(sys + SSI_GDD_MPU_IRQ_STATUS_REG));
-	seq_printf(m, "GDD_MPU_ENABLE\t: 0x%08x\n\n",
-		readl(sys + SSI_GDD_MPU_IRQ_ENABLE_REG));
-	seq_printf(m, "HW_ID\t\t: 0x%08x\n",
-				readl(gdd + SSI_GDD_HW_ID_REG));
-	seq_printf(m, "PPORT_ID\t: 0x%08x\n",
-				readl(gdd + SSI_GDD_PPORT_ID_REG));
-	seq_printf(m, "MPORT_ID\t: 0x%08x\n",
-				readl(gdd + SSI_GDD_MPORT_ID_REG));
-	seq_printf(m, "TEST\t\t: 0x%08x\n",
-				readl(gdd + SSI_GDD_TEST_REG));
-	seq_printf(m, "GCR\t\t: 0x%08x\n",
-				readl(gdd + SSI_GDD_GCR_REG));
-
-	for (lch = 0; lch < SSI_MAX_GDD_LCH; lch++) {
-		seq_printf(m, "\nGDD LCH %d\n=========\n", lch);
-		seq_printf(m, "CSDP\t\t: 0x%04x\n",
-				readw(gdd + SSI_GDD_CSDP_REG(lch)));
-		seq_printf(m, "CCR\t\t: 0x%04x\n",
-				readw(gdd + SSI_GDD_CCR_REG(lch)));
-		seq_printf(m, "CICR\t\t: 0x%04x\n",
-				readw(gdd + SSI_GDD_CICR_REG(lch)));
-		seq_printf(m, "CSR\t\t: 0x%04x\n",
-				readw(gdd + SSI_GDD_CSR_REG(lch)));
-		seq_printf(m, "CSSA\t\t: 0x%08x\n",
-				readl(gdd + SSI_GDD_CSSA_REG(lch)));
-		seq_printf(m, "CDSA\t\t: 0x%08x\n",
-				readl(gdd + SSI_GDD_CDSA_REG(lch)));
-		seq_printf(m, "CEN\t\t: 0x%04x\n",
-				readw(gdd + SSI_GDD_CEN_REG(lch)));
-		seq_printf(m, "CSAC\t\t: 0x%04x\n",
-				readw(gdd + SSI_GDD_CSAC_REG(lch)));
-		seq_printf(m, "CDAC\t\t: 0x%04x\n",
-				readw(gdd + SSI_GDD_CDAC_REG(lch)));
-		seq_printf(m, "CLNK_CTRL\t: 0x%04x\n",
-				readw(gdd + SSI_GDD_CLNK_CTRL_REG(lch)));
-	}
-
-	pm_runtime_put_sync(ssi->device.parent);
-
-	return 0;
-}
-
-static int ssi_regs_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, ssi_debug_show, inode->i_private);
-}
-
-static int ssi_gdd_regs_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, ssi_debug_gdd_show, inode->i_private);
-}
-
-static const struct file_operations ssi_regs_fops = {
-	.open		= ssi_regs_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-static const struct file_operations ssi_gdd_regs_fops = {
-	.open		= ssi_gdd_regs_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-static int __init ssi_debug_add_ctrl(struct hsi_controller *ssi)
-{
-	struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
-	struct dentry *dir;
-
-	/* SSI controller */
-	omap_ssi->dir = debugfs_create_dir(dev_name(&ssi->device), NULL);
-	if (!omap_ssi->dir)
-		return -ENOMEM;
-
-	debugfs_create_file("regs", S_IRUGO, omap_ssi->dir, ssi,
-								&ssi_regs_fops);
-	/* SSI GDD (DMA) */
-	dir = debugfs_create_dir("gdd", omap_ssi->dir);
-	if (!dir)
-		goto rback;
-	debugfs_create_file("regs", S_IRUGO, dir, ssi, &ssi_gdd_regs_fops);
-
-	return 0;
-rback:
-	debugfs_remove_recursive(omap_ssi->dir);
-
-	return -ENOMEM;
-}
-
-static void ssi_debug_remove_ctrl(struct hsi_controller *ssi)
-{
-	struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
-
-	debugfs_remove_recursive(omap_ssi->dir);
-}
-#endif /* CONFIG_DEBUG_FS */
-
-/*
- * FIXME: Horrible HACK needed until we remove the useless wakeline test
- * in the CMT. To be removed !!!!
- */
-void ssi_waketest(struct hsi_client *cl, unsigned int enable)
-{
-	struct hsi_port *port = hsi_get_port(cl);
-	struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
-	struct hsi_controller *ssi = to_hsi_controller(port->device.parent);
-	struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
-
-	omap_port->wktest = !!enable;
-	if (omap_port->wktest) {
-		pm_runtime_get_sync(ssi->device.parent);
-		writel_relaxed(SSI_WAKE(0),
-				omap_ssi->sys + SSI_SET_WAKE_REG(port->num));
-	} else {
-		writel_relaxed(SSI_WAKE(0),
-				omap_ssi->sys +	SSI_CLEAR_WAKE_REG(port->num));
-		pm_runtime_put_sync(ssi->device.parent);
-	}
-}
-EXPORT_SYMBOL_GPL(ssi_waketest);
-
-static void ssi_gdd_complete(struct hsi_controller *ssi, unsigned int lch)
-{
-	struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
-	struct hsi_msg *msg = omap_ssi->gdd_trn[lch].msg;
-	struct hsi_port *port = to_hsi_port(msg->cl->device.parent);
-	struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
-	unsigned int dir;
-	u32 csr;
-	u32 val;
-
-	spin_lock(&omap_ssi->lock);
-
-	val = readl(omap_ssi->sys + SSI_GDD_MPU_IRQ_ENABLE_REG);
-	val &= ~SSI_GDD_LCH(lch);
-	writel_relaxed(val, omap_ssi->sys + SSI_GDD_MPU_IRQ_ENABLE_REG);
-
-	if (msg->ttype == HSI_MSG_READ) {
-		dir = DMA_FROM_DEVICE;
-		val = SSI_DATAAVAILABLE(msg->channel);
-		pm_runtime_put_sync(ssi->device.parent);
-	} else {
-		dir = DMA_TO_DEVICE;
-		val = SSI_DATAACCEPT(msg->channel);
-		/* Keep clocks reference for write pio event */
-	}
-	dma_unmap_sg(&ssi->device, msg->sgt.sgl, msg->sgt.nents, dir);
-	csr = readw(omap_ssi->gdd + SSI_GDD_CSR_REG(lch));
-	omap_ssi->gdd_trn[lch].msg = NULL; /* release GDD lch */
-	dev_dbg(&port->device, "DMA completed ch %d ttype %d\n",
-				msg->channel, msg->ttype);
-	spin_unlock(&omap_ssi->lock);
-	if (csr & SSI_CSR_TOUR) { /* Timeout error */
-		msg->status = HSI_STATUS_ERROR;
-		msg->actual_len = 0;
-		spin_lock(&omap_port->lock);
-		list_del(&msg->link); /* Dequeue msg */
-		spin_unlock(&omap_port->lock);
-		msg->complete(msg);
-		return;
-	}
-	spin_lock(&omap_port->lock);
-	val |= readl(omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num, 0));
-	writel_relaxed(val, omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num, 0));
-	spin_unlock(&omap_port->lock);
-
-	msg->status = HSI_STATUS_COMPLETED;
-	msg->actual_len = sg_dma_len(msg->sgt.sgl);
-}
-
-static void ssi_gdd_tasklet(unsigned long dev)
-{
-	struct hsi_controller *ssi = (struct hsi_controller *)dev;
-	struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
-	void __iomem *sys = omap_ssi->sys;
-	unsigned int lch;
-	u32 status_reg;
-
-	pm_runtime_get_sync(ssi->device.parent);
-
-	status_reg = readl(sys + SSI_GDD_MPU_IRQ_STATUS_REG);
-	for (lch = 0; lch < SSI_MAX_GDD_LCH; lch++) {
-		if (status_reg & SSI_GDD_LCH(lch))
-			ssi_gdd_complete(ssi, lch);
-	}
-	writel_relaxed(status_reg, sys + SSI_GDD_MPU_IRQ_STATUS_REG);
-	status_reg = readl(sys + SSI_GDD_MPU_IRQ_STATUS_REG);
-
-	pm_runtime_put_sync(ssi->device.parent);
-
-	if (status_reg)
-		tasklet_hi_schedule(&omap_ssi->gdd_tasklet);
-	else
-		enable_irq(omap_ssi->gdd_irq);
-
-}
-
-static irqreturn_t ssi_gdd_isr(int irq, void *ssi)
-{
-	struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
-
-	tasklet_hi_schedule(&omap_ssi->gdd_tasklet);
-	disable_irq_nosync(irq);
-
-	return IRQ_HANDLED;
-}
-
-static unsigned long ssi_get_clk_rate(struct hsi_controller *ssi)
-{
-	struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
-	unsigned long rate = clk_get_rate(omap_ssi->fck);
-	return rate;
-}
-
-static int __init ssi_get_iomem(struct platform_device *pd,
-		const char *name, void __iomem **pbase, dma_addr_t *phy)
-{
-	struct resource *mem;
-	void __iomem *base;
-	struct hsi_controller *ssi = platform_get_drvdata(pd);
-
-	mem = platform_get_resource_byname(pd, IORESOURCE_MEM, name);
-	base = devm_ioremap_resource(&ssi->device, mem);
-	if (IS_ERR(base))
-		return PTR_ERR(base);
-
-	*pbase = base;
-
-	if (phy)
-		*phy = mem->start;
-
-	return 0;
-}
-
-static int __init ssi_add_controller(struct hsi_controller *ssi,
-						struct platform_device *pd)
-{
-	struct omap_ssi_controller *omap_ssi;
-	int err;
-
-	omap_ssi = devm_kzalloc(&ssi->device, sizeof(*omap_ssi), GFP_KERNEL);
-	if (!omap_ssi) {
-		dev_err(&pd->dev, "not enough memory for omap ssi\n");
-		return -ENOMEM;
-	}
-
-	err = ida_simple_get(&platform_omap_ssi_ida, 0, 0, GFP_KERNEL);
-	if (err < 0)
-		goto out_err;
-	ssi->id = err;
-
-	ssi->owner = THIS_MODULE;
-	ssi->device.parent = &pd->dev;
-	dev_set_name(&ssi->device, "ssi%d", ssi->id);
-	hsi_controller_set_drvdata(ssi, omap_ssi);
-	omap_ssi->dev = &ssi->device;
-	err = ssi_get_iomem(pd, "sys", &omap_ssi->sys, NULL);
-	if (err < 0)
-		goto out_err;
-	err = ssi_get_iomem(pd, "gdd", &omap_ssi->gdd, NULL);
-	if (err < 0)
-		goto out_err;
-	err = platform_get_irq_byname(pd, "gdd_mpu");
-	if (err < 0) {
-		dev_err(&pd->dev, "GDD IRQ resource missing\n");
-		goto out_err;
-	}
-	omap_ssi->gdd_irq = err;
-	tasklet_init(&omap_ssi->gdd_tasklet, ssi_gdd_tasklet,
-							(unsigned long)ssi);
-	err = devm_request_irq(&ssi->device, omap_ssi->gdd_irq, ssi_gdd_isr,
-						0, "gdd_mpu", ssi);
-	if (err < 0) {
-		dev_err(&ssi->device, "Request GDD IRQ %d failed (%d)",
-							omap_ssi->gdd_irq, err);
-		goto out_err;
-	}
-
-	omap_ssi->port = devm_kzalloc(&ssi->device,
-		sizeof(struct omap_ssi_port *) * ssi->num_ports, GFP_KERNEL);
-	if (!omap_ssi->port) {
-		err = -ENOMEM;
-		goto out_err;
-	}
-
-	omap_ssi->fck = devm_clk_get(&ssi->device, "ssi_ssr_fck");
-	if (IS_ERR(omap_ssi->fck)) {
-		dev_err(&pd->dev, "Could not acquire clock \"ssi_ssr_fck\": %li\n",
-			PTR_ERR(omap_ssi->fck));
-		err = -ENODEV;
-		goto out_err;
-	}
-
-	/* TODO: find register, which can be used to detect context loss */
-	omap_ssi->get_loss = NULL;
-
-	omap_ssi->max_speed = UINT_MAX;
-	spin_lock_init(&omap_ssi->lock);
-	err = hsi_register_controller(ssi);
-
-	if (err < 0)
-		goto out_err;
-
-	return 0;
-
-out_err:
-	ida_simple_remove(&platform_omap_ssi_ida, ssi->id);
-	return err;
-}
-
-static int __init ssi_hw_init(struct hsi_controller *ssi)
-{
-	struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
-	unsigned int i;
-	u32 val;
-	int err;
-
-	err = pm_runtime_get_sync(ssi->device.parent);
-	if (err < 0) {
-		dev_err(&ssi->device, "runtime PM failed %d\n", err);
-		return err;
-	}
-	/* Reseting SSI controller */
-	writel_relaxed(SSI_SOFTRESET, omap_ssi->sys + SSI_SYSCONFIG_REG);
-	val = readl(omap_ssi->sys + SSI_SYSSTATUS_REG);
-	for (i = 0; ((i < 20) && !(val & SSI_RESETDONE)); i++) {
-		msleep(20);
-		val = readl(omap_ssi->sys + SSI_SYSSTATUS_REG);
-	}
-	if (!(val & SSI_RESETDONE)) {
-		dev_err(&ssi->device, "SSI HW reset failed\n");
-		pm_runtime_put_sync(ssi->device.parent);
-		return -EIO;
-	}
-	/* Reseting GDD */
-	writel_relaxed(SSI_SWRESET, omap_ssi->gdd + SSI_GDD_GRST_REG);
-	/* Get FCK rate in KHz */
-	omap_ssi->fck_rate = DIV_ROUND_CLOSEST(ssi_get_clk_rate(ssi), 1000);
-	dev_dbg(&ssi->device, "SSI fck rate %lu KHz\n", omap_ssi->fck_rate);
-	/* Set default PM settings */
-	val = SSI_AUTOIDLE | SSI_SIDLEMODE_SMART | SSI_MIDLEMODE_SMART;
-	writel_relaxed(val, omap_ssi->sys + SSI_SYSCONFIG_REG);
-	omap_ssi->sysconfig = val;
-	writel_relaxed(SSI_CLK_AUTOGATING_ON, omap_ssi->sys + SSI_GDD_GCR_REG);
-	omap_ssi->gdd_gcr = SSI_CLK_AUTOGATING_ON;
-	pm_runtime_put_sync(ssi->device.parent);
-
-	return 0;
-}
-
-static void ssi_remove_controller(struct hsi_controller *ssi)
-{
-	struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
-	int id = ssi->id;
-	tasklet_kill(&omap_ssi->gdd_tasklet);
-	hsi_unregister_controller(ssi);
-	ida_simple_remove(&platform_omap_ssi_ida, id);
-}
-
-static inline int ssi_of_get_available_ports_count(const struct device_node *np)
-{
-	struct device_node *child;
-	int num = 0;
-
-	for_each_available_child_of_node(np, child)
-		if (of_device_is_compatible(child, "ti,omap3-ssi-port"))
-			num++;
-
-	return num;
-}
-
-static int ssi_remove_ports(struct device *dev, void *c)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-
-	of_device_unregister(pdev);
-
-	return 0;
-}
-
-static int __init ssi_probe(struct platform_device *pd)
-{
-	struct platform_device *childpdev;
-	struct device_node *np = pd->dev.of_node;
-	struct device_node *child;
-	struct hsi_controller *ssi;
-	int err;
-	int num_ports;
-
-	if (!np) {
-		dev_err(&pd->dev, "missing device tree data\n");
-		return -EINVAL;
-	}
-
-	num_ports = ssi_of_get_available_ports_count(np);
-
-	ssi = hsi_alloc_controller(num_ports, GFP_KERNEL);
-	if (!ssi) {
-		dev_err(&pd->dev, "No memory for controller\n");
-		return -ENOMEM;
-	}
-
-	platform_set_drvdata(pd, ssi);
-
-	err = ssi_add_controller(ssi, pd);
-	if (err < 0)
-		goto out1;
-
-	pm_runtime_irq_safe(&pd->dev);
-	pm_runtime_enable(&pd->dev);
-
-	err = ssi_hw_init(ssi);
-	if (err < 0)
-		goto out2;
-#ifdef CONFIG_DEBUG_FS
-	err = ssi_debug_add_ctrl(ssi);
-	if (err < 0)
-		goto out2;
-#endif
-
-	for_each_available_child_of_node(np, child) {
-		if (!of_device_is_compatible(child, "ti,omap3-ssi-port"))
-			continue;
-
-		childpdev = of_platform_device_create(child, NULL, &pd->dev);
-		if (!childpdev) {
-			err = -ENODEV;
-			dev_err(&pd->dev, "failed to create ssi controller port\n");
-			goto out3;
-		}
-	}
-
-	dev_info(&pd->dev, "ssi controller %d initialized (%d ports)!\n",
-		ssi->id, num_ports);
-	return err;
-out3:
-	device_for_each_child(&pd->dev, NULL, ssi_remove_ports);
-out2:
-	ssi_remove_controller(ssi);
-out1:
-	platform_set_drvdata(pd, NULL);
-	pm_runtime_disable(&pd->dev);
-
-	return err;
-}
-
-static int __exit ssi_remove(struct platform_device *pd)
-{
-	struct hsi_controller *ssi = platform_get_drvdata(pd);
-
-#ifdef CONFIG_DEBUG_FS
-	ssi_debug_remove_ctrl(ssi);
-#endif
-	ssi_remove_controller(ssi);
-	platform_set_drvdata(pd, NULL);
-
-	pm_runtime_disable(&pd->dev);
-
-	/* cleanup of of_platform_populate() call */
-	device_for_each_child(&pd->dev, NULL, ssi_remove_ports);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int omap_ssi_runtime_suspend(struct device *dev)
-{
-	struct hsi_controller *ssi = dev_get_drvdata(dev);
-	struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
-
-	dev_dbg(dev, "runtime suspend!\n");
-
-	if (omap_ssi->get_loss)
-		omap_ssi->loss_count =
-				omap_ssi->get_loss(ssi->device.parent);
-
-	return 0;
-}
-
-static int omap_ssi_runtime_resume(struct device *dev)
-{
-	struct hsi_controller *ssi = dev_get_drvdata(dev);
-	struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
-
-	dev_dbg(dev, "runtime resume!\n");
-
-	if ((omap_ssi->get_loss) && (omap_ssi->loss_count ==
-				omap_ssi->get_loss(ssi->device.parent)))
-		return 0;
-
-	writel_relaxed(omap_ssi->gdd_gcr, omap_ssi->gdd + SSI_GDD_GCR_REG);
-
-	return 0;
-}
-
-static const struct dev_pm_ops omap_ssi_pm_ops = {
-	SET_RUNTIME_PM_OPS(omap_ssi_runtime_suspend, omap_ssi_runtime_resume,
-		NULL)
-};
-
-#define DEV_PM_OPS     (&omap_ssi_pm_ops)
-#else
-#define DEV_PM_OPS     NULL
-#endif
-
-#ifdef CONFIG_OF
-static const struct of_device_id omap_ssi_of_match[] = {
-	{ .compatible = "ti,omap3-ssi", },
-	{},
-};
-MODULE_DEVICE_TABLE(of, omap_ssi_of_match);
-#else
-#define omap_ssi_of_match NULL
-#endif
-
-static struct platform_driver ssi_pdriver = {
-	.remove	= __exit_p(ssi_remove),
-	.driver	= {
-		.name	= "omap_ssi",
-		.pm     = DEV_PM_OPS,
-		.of_match_table = omap_ssi_of_match,
-	},
-};
-
-module_platform_driver_probe(ssi_pdriver, ssi_probe);
-
-MODULE_ALIAS("platform:omap_ssi");
-MODULE_AUTHOR("Carlos Chinea <carlos.chinea@nokia.com>");
-MODULE_AUTHOR("Sebastian Reichel <sre@kernel.org>");
-MODULE_DESCRIPTION("Synchronous Serial Interface Driver");
-MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hsi/controllers/omap_ssi_core.c linux-libre-4.7-gnu/drivers/hsi/controllers/omap_ssi_core.c
--- linux-libre-4.6-gnu/drivers/hsi/controllers/omap_ssi_core.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/hsi/controllers/omap_ssi_core.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,693 @@
+/* OMAP SSI driver.
+ *
+ * Copyright (C) 2010 Nokia Corporation. All rights reserved.
+ * Copyright (C) 2014 Sebastian Reichel <sre@kernel.org>
+ *
+ * Contact: Carlos Chinea <carlos.chinea@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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
+ */
+
+#include <linux/compiler.h>
+#include <linux/err.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/scatterlist.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/debugfs.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/pm_runtime.h>
+#include <linux/of_platform.h>
+#include <linux/hsi/hsi.h>
+#include <linux/idr.h>
+
+#include "omap_ssi_regs.h"
+#include "omap_ssi.h"
+
+/* For automatically allocated device IDs */
+static DEFINE_IDA(platform_omap_ssi_ida);
+
+#ifdef CONFIG_DEBUG_FS
+static int ssi_debug_show(struct seq_file *m, void *p __maybe_unused)
+{
+	struct hsi_controller *ssi = m->private;
+	struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+	void __iomem *sys = omap_ssi->sys;
+
+	pm_runtime_get_sync(ssi->device.parent);
+	seq_printf(m, "REVISION\t: 0x%08x\n",  readl(sys + SSI_REVISION_REG));
+	seq_printf(m, "SYSCONFIG\t: 0x%08x\n", readl(sys + SSI_SYSCONFIG_REG));
+	seq_printf(m, "SYSSTATUS\t: 0x%08x\n", readl(sys + SSI_SYSSTATUS_REG));
+	pm_runtime_put_sync(ssi->device.parent);
+
+	return 0;
+}
+
+static int ssi_debug_gdd_show(struct seq_file *m, void *p __maybe_unused)
+{
+	struct hsi_controller *ssi = m->private;
+	struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+	void __iomem *gdd = omap_ssi->gdd;
+	void __iomem *sys = omap_ssi->sys;
+	int lch;
+
+	pm_runtime_get_sync(ssi->device.parent);
+
+	seq_printf(m, "GDD_MPU_STATUS\t: 0x%08x\n",
+		readl(sys + SSI_GDD_MPU_IRQ_STATUS_REG));
+	seq_printf(m, "GDD_MPU_ENABLE\t: 0x%08x\n\n",
+		readl(sys + SSI_GDD_MPU_IRQ_ENABLE_REG));
+	seq_printf(m, "HW_ID\t\t: 0x%08x\n",
+				readl(gdd + SSI_GDD_HW_ID_REG));
+	seq_printf(m, "PPORT_ID\t: 0x%08x\n",
+				readl(gdd + SSI_GDD_PPORT_ID_REG));
+	seq_printf(m, "MPORT_ID\t: 0x%08x\n",
+				readl(gdd + SSI_GDD_MPORT_ID_REG));
+	seq_printf(m, "TEST\t\t: 0x%08x\n",
+				readl(gdd + SSI_GDD_TEST_REG));
+	seq_printf(m, "GCR\t\t: 0x%08x\n",
+				readl(gdd + SSI_GDD_GCR_REG));
+
+	for (lch = 0; lch < SSI_MAX_GDD_LCH; lch++) {
+		seq_printf(m, "\nGDD LCH %d\n=========\n", lch);
+		seq_printf(m, "CSDP\t\t: 0x%04x\n",
+				readw(gdd + SSI_GDD_CSDP_REG(lch)));
+		seq_printf(m, "CCR\t\t: 0x%04x\n",
+				readw(gdd + SSI_GDD_CCR_REG(lch)));
+		seq_printf(m, "CICR\t\t: 0x%04x\n",
+				readw(gdd + SSI_GDD_CICR_REG(lch)));
+		seq_printf(m, "CSR\t\t: 0x%04x\n",
+				readw(gdd + SSI_GDD_CSR_REG(lch)));
+		seq_printf(m, "CSSA\t\t: 0x%08x\n",
+				readl(gdd + SSI_GDD_CSSA_REG(lch)));
+		seq_printf(m, "CDSA\t\t: 0x%08x\n",
+				readl(gdd + SSI_GDD_CDSA_REG(lch)));
+		seq_printf(m, "CEN\t\t: 0x%04x\n",
+				readw(gdd + SSI_GDD_CEN_REG(lch)));
+		seq_printf(m, "CSAC\t\t: 0x%04x\n",
+				readw(gdd + SSI_GDD_CSAC_REG(lch)));
+		seq_printf(m, "CDAC\t\t: 0x%04x\n",
+				readw(gdd + SSI_GDD_CDAC_REG(lch)));
+		seq_printf(m, "CLNK_CTRL\t: 0x%04x\n",
+				readw(gdd + SSI_GDD_CLNK_CTRL_REG(lch)));
+	}
+
+	pm_runtime_put_sync(ssi->device.parent);
+
+	return 0;
+}
+
+static int ssi_regs_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ssi_debug_show, inode->i_private);
+}
+
+static int ssi_gdd_regs_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ssi_debug_gdd_show, inode->i_private);
+}
+
+static const struct file_operations ssi_regs_fops = {
+	.open		= ssi_regs_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static const struct file_operations ssi_gdd_regs_fops = {
+	.open		= ssi_gdd_regs_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int ssi_debug_add_ctrl(struct hsi_controller *ssi)
+{
+	struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+	struct dentry *dir;
+
+	/* SSI controller */
+	omap_ssi->dir = debugfs_create_dir(dev_name(&ssi->device), NULL);
+	if (!omap_ssi->dir)
+		return -ENOMEM;
+
+	debugfs_create_file("regs", S_IRUGO, omap_ssi->dir, ssi,
+								&ssi_regs_fops);
+	/* SSI GDD (DMA) */
+	dir = debugfs_create_dir("gdd", omap_ssi->dir);
+	if (!dir)
+		goto rback;
+	debugfs_create_file("regs", S_IRUGO, dir, ssi, &ssi_gdd_regs_fops);
+
+	return 0;
+rback:
+	debugfs_remove_recursive(omap_ssi->dir);
+
+	return -ENOMEM;
+}
+
+static void ssi_debug_remove_ctrl(struct hsi_controller *ssi)
+{
+	struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+
+	debugfs_remove_recursive(omap_ssi->dir);
+}
+#endif /* CONFIG_DEBUG_FS */
+
+/*
+ * FIXME: Horrible HACK needed until we remove the useless wakeline test
+ * in the CMT. To be removed !!!!
+ */
+void ssi_waketest(struct hsi_client *cl, unsigned int enable)
+{
+	struct hsi_port *port = hsi_get_port(cl);
+	struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
+	struct hsi_controller *ssi = to_hsi_controller(port->device.parent);
+	struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+
+	omap_port->wktest = !!enable;
+	if (omap_port->wktest) {
+		pm_runtime_get_sync(ssi->device.parent);
+		writel_relaxed(SSI_WAKE(0),
+				omap_ssi->sys + SSI_SET_WAKE_REG(port->num));
+	} else {
+		writel_relaxed(SSI_WAKE(0),
+				omap_ssi->sys +	SSI_CLEAR_WAKE_REG(port->num));
+		pm_runtime_put_sync(ssi->device.parent);
+	}
+}
+EXPORT_SYMBOL_GPL(ssi_waketest);
+
+static void ssi_gdd_complete(struct hsi_controller *ssi, unsigned int lch)
+{
+	struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+	struct hsi_msg *msg = omap_ssi->gdd_trn[lch].msg;
+	struct hsi_port *port = to_hsi_port(msg->cl->device.parent);
+	struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
+	unsigned int dir;
+	u32 csr;
+	u32 val;
+
+	spin_lock(&omap_ssi->lock);
+
+	val = readl(omap_ssi->sys + SSI_GDD_MPU_IRQ_ENABLE_REG);
+	val &= ~SSI_GDD_LCH(lch);
+	writel_relaxed(val, omap_ssi->sys + SSI_GDD_MPU_IRQ_ENABLE_REG);
+
+	if (msg->ttype == HSI_MSG_READ) {
+		dir = DMA_FROM_DEVICE;
+		val = SSI_DATAAVAILABLE(msg->channel);
+		pm_runtime_put_sync(ssi->device.parent);
+	} else {
+		dir = DMA_TO_DEVICE;
+		val = SSI_DATAACCEPT(msg->channel);
+		/* Keep clocks reference for write pio event */
+	}
+	dma_unmap_sg(&ssi->device, msg->sgt.sgl, msg->sgt.nents, dir);
+	csr = readw(omap_ssi->gdd + SSI_GDD_CSR_REG(lch));
+	omap_ssi->gdd_trn[lch].msg = NULL; /* release GDD lch */
+	dev_dbg(&port->device, "DMA completed ch %d ttype %d\n",
+				msg->channel, msg->ttype);
+	spin_unlock(&omap_ssi->lock);
+	if (csr & SSI_CSR_TOUR) { /* Timeout error */
+		msg->status = HSI_STATUS_ERROR;
+		msg->actual_len = 0;
+		spin_lock(&omap_port->lock);
+		list_del(&msg->link); /* Dequeue msg */
+		spin_unlock(&omap_port->lock);
+		msg->complete(msg);
+		return;
+	}
+	spin_lock(&omap_port->lock);
+	val |= readl(omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num, 0));
+	writel_relaxed(val, omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num, 0));
+	spin_unlock(&omap_port->lock);
+
+	msg->status = HSI_STATUS_COMPLETED;
+	msg->actual_len = sg_dma_len(msg->sgt.sgl);
+}
+
+static void ssi_gdd_tasklet(unsigned long dev)
+{
+	struct hsi_controller *ssi = (struct hsi_controller *)dev;
+	struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+	void __iomem *sys = omap_ssi->sys;
+	unsigned int lch;
+	u32 status_reg;
+
+	pm_runtime_get_sync(ssi->device.parent);
+
+	status_reg = readl(sys + SSI_GDD_MPU_IRQ_STATUS_REG);
+	for (lch = 0; lch < SSI_MAX_GDD_LCH; lch++) {
+		if (status_reg & SSI_GDD_LCH(lch))
+			ssi_gdd_complete(ssi, lch);
+	}
+	writel_relaxed(status_reg, sys + SSI_GDD_MPU_IRQ_STATUS_REG);
+	status_reg = readl(sys + SSI_GDD_MPU_IRQ_STATUS_REG);
+
+	pm_runtime_put_sync(ssi->device.parent);
+
+	if (status_reg)
+		tasklet_hi_schedule(&omap_ssi->gdd_tasklet);
+	else
+		enable_irq(omap_ssi->gdd_irq);
+
+}
+
+static irqreturn_t ssi_gdd_isr(int irq, void *ssi)
+{
+	struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+
+	tasklet_hi_schedule(&omap_ssi->gdd_tasklet);
+	disable_irq_nosync(irq);
+
+	return IRQ_HANDLED;
+}
+
+static unsigned long ssi_get_clk_rate(struct hsi_controller *ssi)
+{
+	struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+	unsigned long rate = clk_get_rate(omap_ssi->fck);
+	return rate;
+}
+
+static int ssi_clk_event(struct notifier_block *nb, unsigned long event,
+								void *data)
+{
+	struct omap_ssi_controller *omap_ssi = container_of(nb,
+					struct omap_ssi_controller, fck_nb);
+	struct hsi_controller *ssi = to_hsi_controller(omap_ssi->dev);
+	struct clk_notifier_data *clk_data = data;
+	struct omap_ssi_port *omap_port;
+	int i;
+
+	switch (event) {
+	case PRE_RATE_CHANGE:
+		dev_dbg(&ssi->device, "pre rate change\n");
+
+		for (i = 0; i < ssi->num_ports; i++) {
+			omap_port = omap_ssi->port[i];
+
+			if (!omap_port)
+				continue;
+
+			/* Workaround for SWBREAK + CAwake down race in CMT */
+			tasklet_disable(&omap_port->wake_tasklet);
+
+			/* stop all ssi communication */
+			pinctrl_pm_select_idle_state(omap_port->pdev);
+			udelay(1); /* wait for racing frames */
+		}
+
+		break;
+	case ABORT_RATE_CHANGE:
+		dev_dbg(&ssi->device, "abort rate change\n");
+		/* Fall through */
+	case POST_RATE_CHANGE:
+		dev_dbg(&ssi->device, "post rate change (%lu -> %lu)\n",
+			clk_data->old_rate, clk_data->new_rate);
+		omap_ssi->fck_rate = DIV_ROUND_CLOSEST(clk_data->new_rate, 1000); /* KHz */
+
+		for (i = 0; i < ssi->num_ports; i++) {
+			omap_port = omap_ssi->port[i];
+
+			if (!omap_port)
+				continue;
+
+			omap_ssi_port_update_fclk(ssi, omap_port);
+
+			/* resume ssi communication */
+			pinctrl_pm_select_default_state(omap_port->pdev);
+			tasklet_enable(&omap_port->wake_tasklet);
+		}
+
+		break;
+	default:
+		break;
+	}
+
+	return NOTIFY_DONE;
+}
+
+static int ssi_get_iomem(struct platform_device *pd,
+		const char *name, void __iomem **pbase, dma_addr_t *phy)
+{
+	struct resource *mem;
+	void __iomem *base;
+	struct hsi_controller *ssi = platform_get_drvdata(pd);
+
+	mem = platform_get_resource_byname(pd, IORESOURCE_MEM, name);
+	base = devm_ioremap_resource(&ssi->device, mem);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	*pbase = base;
+
+	if (phy)
+		*phy = mem->start;
+
+	return 0;
+}
+
+static int ssi_add_controller(struct hsi_controller *ssi,
+						struct platform_device *pd)
+{
+	struct omap_ssi_controller *omap_ssi;
+	int err;
+
+	omap_ssi = devm_kzalloc(&ssi->device, sizeof(*omap_ssi), GFP_KERNEL);
+	if (!omap_ssi) {
+		dev_err(&pd->dev, "not enough memory for omap ssi\n");
+		return -ENOMEM;
+	}
+
+	err = ida_simple_get(&platform_omap_ssi_ida, 0, 0, GFP_KERNEL);
+	if (err < 0)
+		goto out_err;
+	ssi->id = err;
+
+	ssi->owner = THIS_MODULE;
+	ssi->device.parent = &pd->dev;
+	dev_set_name(&ssi->device, "ssi%d", ssi->id);
+	hsi_controller_set_drvdata(ssi, omap_ssi);
+	omap_ssi->dev = &ssi->device;
+	err = ssi_get_iomem(pd, "sys", &omap_ssi->sys, NULL);
+	if (err < 0)
+		goto out_err;
+	err = ssi_get_iomem(pd, "gdd", &omap_ssi->gdd, NULL);
+	if (err < 0)
+		goto out_err;
+	err = platform_get_irq_byname(pd, "gdd_mpu");
+	if (err < 0) {
+		dev_err(&pd->dev, "GDD IRQ resource missing\n");
+		goto out_err;
+	}
+	omap_ssi->gdd_irq = err;
+	tasklet_init(&omap_ssi->gdd_tasklet, ssi_gdd_tasklet,
+							(unsigned long)ssi);
+	err = devm_request_irq(&ssi->device, omap_ssi->gdd_irq, ssi_gdd_isr,
+						0, "gdd_mpu", ssi);
+	if (err < 0) {
+		dev_err(&ssi->device, "Request GDD IRQ %d failed (%d)",
+							omap_ssi->gdd_irq, err);
+		goto out_err;
+	}
+
+	omap_ssi->port = devm_kzalloc(&ssi->device,
+		sizeof(struct omap_ssi_port *) * ssi->num_ports, GFP_KERNEL);
+	if (!omap_ssi->port) {
+		err = -ENOMEM;
+		goto out_err;
+	}
+
+	omap_ssi->fck = devm_clk_get(&ssi->device, "ssi_ssr_fck");
+	if (IS_ERR(omap_ssi->fck)) {
+		dev_err(&pd->dev, "Could not acquire clock \"ssi_ssr_fck\": %li\n",
+			PTR_ERR(omap_ssi->fck));
+		err = -ENODEV;
+		goto out_err;
+	}
+
+	omap_ssi->fck_nb.notifier_call = ssi_clk_event;
+	omap_ssi->fck_nb.priority = INT_MAX;
+	clk_notifier_register(omap_ssi->fck, &omap_ssi->fck_nb);
+
+	/* TODO: find register, which can be used to detect context loss */
+	omap_ssi->get_loss = NULL;
+
+	omap_ssi->max_speed = UINT_MAX;
+	spin_lock_init(&omap_ssi->lock);
+	err = hsi_register_controller(ssi);
+
+	if (err < 0)
+		goto out_err;
+
+	return 0;
+
+out_err:
+	ida_simple_remove(&platform_omap_ssi_ida, ssi->id);
+	return err;
+}
+
+static int ssi_hw_init(struct hsi_controller *ssi)
+{
+	struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+	unsigned int i;
+	u32 val;
+	int err;
+
+	err = pm_runtime_get_sync(ssi->device.parent);
+	if (err < 0) {
+		dev_err(&ssi->device, "runtime PM failed %d\n", err);
+		return err;
+	}
+	/* Reseting SSI controller */
+	writel_relaxed(SSI_SOFTRESET, omap_ssi->sys + SSI_SYSCONFIG_REG);
+	val = readl(omap_ssi->sys + SSI_SYSSTATUS_REG);
+	for (i = 0; ((i < 20) && !(val & SSI_RESETDONE)); i++) {
+		msleep(20);
+		val = readl(omap_ssi->sys + SSI_SYSSTATUS_REG);
+	}
+	if (!(val & SSI_RESETDONE)) {
+		dev_err(&ssi->device, "SSI HW reset failed\n");
+		pm_runtime_put_sync(ssi->device.parent);
+		return -EIO;
+	}
+	/* Reseting GDD */
+	writel_relaxed(SSI_SWRESET, omap_ssi->gdd + SSI_GDD_GRST_REG);
+	/* Get FCK rate in KHz */
+	omap_ssi->fck_rate = DIV_ROUND_CLOSEST(ssi_get_clk_rate(ssi), 1000);
+	dev_dbg(&ssi->device, "SSI fck rate %lu KHz\n", omap_ssi->fck_rate);
+	/* Set default PM settings */
+	val = SSI_AUTOIDLE | SSI_SIDLEMODE_SMART | SSI_MIDLEMODE_SMART;
+	writel_relaxed(val, omap_ssi->sys + SSI_SYSCONFIG_REG);
+	omap_ssi->sysconfig = val;
+	writel_relaxed(SSI_CLK_AUTOGATING_ON, omap_ssi->sys + SSI_GDD_GCR_REG);
+	omap_ssi->gdd_gcr = SSI_CLK_AUTOGATING_ON;
+	pm_runtime_put_sync(ssi->device.parent);
+
+	return 0;
+}
+
+static void ssi_remove_controller(struct hsi_controller *ssi)
+{
+	struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+	int id = ssi->id;
+	tasklet_kill(&omap_ssi->gdd_tasklet);
+	hsi_unregister_controller(ssi);
+	clk_notifier_unregister(omap_ssi->fck, &omap_ssi->fck_nb);
+	ida_simple_remove(&platform_omap_ssi_ida, id);
+}
+
+static inline int ssi_of_get_available_ports_count(const struct device_node *np)
+{
+	struct device_node *child;
+	int num = 0;
+
+	for_each_available_child_of_node(np, child)
+		if (of_device_is_compatible(child, "ti,omap3-ssi-port"))
+			num++;
+
+	return num;
+}
+
+static int ssi_remove_ports(struct device *dev, void *c)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+
+	if (!dev->of_node)
+		return 0;
+
+	of_node_clear_flag(dev->of_node, OF_POPULATED);
+	of_device_unregister(pdev);
+
+	return 0;
+}
+
+static int ssi_probe(struct platform_device *pd)
+{
+	struct platform_device *childpdev;
+	struct device_node *np = pd->dev.of_node;
+	struct device_node *child;
+	struct hsi_controller *ssi;
+	int err;
+	int num_ports;
+
+	if (!np) {
+		dev_err(&pd->dev, "missing device tree data\n");
+		return -EINVAL;
+	}
+
+	num_ports = ssi_of_get_available_ports_count(np);
+
+	ssi = hsi_alloc_controller(num_ports, GFP_KERNEL);
+	if (!ssi) {
+		dev_err(&pd->dev, "No memory for controller\n");
+		return -ENOMEM;
+	}
+
+	platform_set_drvdata(pd, ssi);
+
+	err = ssi_add_controller(ssi, pd);
+	if (err < 0)
+		goto out1;
+
+	pm_runtime_irq_safe(&pd->dev);
+	pm_runtime_enable(&pd->dev);
+
+	err = ssi_hw_init(ssi);
+	if (err < 0)
+		goto out2;
+#ifdef CONFIG_DEBUG_FS
+	err = ssi_debug_add_ctrl(ssi);
+	if (err < 0)
+		goto out2;
+#endif
+
+	for_each_available_child_of_node(np, child) {
+		if (!of_device_is_compatible(child, "ti,omap3-ssi-port"))
+			continue;
+
+		childpdev = of_platform_device_create(child, NULL, &pd->dev);
+		if (!childpdev) {
+			err = -ENODEV;
+			dev_err(&pd->dev, "failed to create ssi controller port\n");
+			goto out3;
+		}
+	}
+
+	dev_info(&pd->dev, "ssi controller %d initialized (%d ports)!\n",
+		ssi->id, num_ports);
+	return err;
+out3:
+	device_for_each_child(&pd->dev, NULL, ssi_remove_ports);
+out2:
+	ssi_remove_controller(ssi);
+out1:
+	platform_set_drvdata(pd, NULL);
+	pm_runtime_disable(&pd->dev);
+
+	return err;
+}
+
+static int ssi_remove(struct platform_device *pd)
+{
+	struct hsi_controller *ssi = platform_get_drvdata(pd);
+
+	/* cleanup of of_platform_populate() call */
+	device_for_each_child(&pd->dev, NULL, ssi_remove_ports);
+
+#ifdef CONFIG_DEBUG_FS
+	ssi_debug_remove_ctrl(ssi);
+#endif
+	ssi_remove_controller(ssi);
+	platform_set_drvdata(pd, NULL);
+
+	pm_runtime_disable(&pd->dev);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int omap_ssi_runtime_suspend(struct device *dev)
+{
+	struct hsi_controller *ssi = dev_get_drvdata(dev);
+	struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+
+	dev_dbg(dev, "runtime suspend!\n");
+
+	if (omap_ssi->get_loss)
+		omap_ssi->loss_count =
+				omap_ssi->get_loss(ssi->device.parent);
+
+	return 0;
+}
+
+static int omap_ssi_runtime_resume(struct device *dev)
+{
+	struct hsi_controller *ssi = dev_get_drvdata(dev);
+	struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
+
+	dev_dbg(dev, "runtime resume!\n");
+
+	if ((omap_ssi->get_loss) && (omap_ssi->loss_count ==
+				omap_ssi->get_loss(ssi->device.parent)))
+		return 0;
+
+	writel_relaxed(omap_ssi->gdd_gcr, omap_ssi->gdd + SSI_GDD_GCR_REG);
+
+	return 0;
+}
+
+static const struct dev_pm_ops omap_ssi_pm_ops = {
+	SET_RUNTIME_PM_OPS(omap_ssi_runtime_suspend, omap_ssi_runtime_resume,
+		NULL)
+};
+
+#define DEV_PM_OPS     (&omap_ssi_pm_ops)
+#else
+#define DEV_PM_OPS     NULL
+#endif
+
+#ifdef CONFIG_OF
+static const struct of_device_id omap_ssi_of_match[] = {
+	{ .compatible = "ti,omap3-ssi", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, omap_ssi_of_match);
+#else
+#define omap_ssi_of_match NULL
+#endif
+
+static struct platform_driver ssi_pdriver = {
+	.probe = ssi_probe,
+	.remove	= ssi_remove,
+	.driver	= {
+		.name	= "omap_ssi",
+		.pm     = DEV_PM_OPS,
+		.of_match_table = omap_ssi_of_match,
+	},
+};
+
+static int __init ssi_init(void) {
+	int ret;
+
+	ret = platform_driver_register(&ssi_pdriver);
+	if (ret)
+		return ret;
+
+	return platform_driver_register(&ssi_port_pdriver);
+}
+module_init(ssi_init);
+
+static void __exit ssi_exit(void) {
+	platform_driver_unregister(&ssi_port_pdriver);
+	platform_driver_unregister(&ssi_pdriver);
+}
+module_exit(ssi_exit);
+
+MODULE_ALIAS("platform:omap_ssi");
+MODULE_AUTHOR("Carlos Chinea <carlos.chinea@nokia.com>");
+MODULE_AUTHOR("Sebastian Reichel <sre@kernel.org>");
+MODULE_DESCRIPTION("Synchronous Serial Interface Driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hsi/controllers/omap_ssi.h linux-libre-4.7-gnu/drivers/hsi/controllers/omap_ssi.h
--- linux-libre-4.6-gnu/drivers/hsi/controllers/omap_ssi.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hsi/controllers/omap_ssi.h	2016-07-24 15:23:50.000000000 -0400
@@ -27,7 +27,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/hsi/hsi.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
 
@@ -97,7 +97,7 @@ struct omap_ssi_port {
 	struct list_head	brkqueue;
 	unsigned int		irq;
 	int			wake_irq;
-	int			wake_gpio;
+	struct gpio_desc	*wake_gpio;
 	struct tasklet_struct	pio_tasklet;
 	struct tasklet_struct	wake_tasklet;
 	bool			wktest:1; /* FIXME: HACK to be removed */
@@ -134,6 +134,8 @@ struct gdd_trn {
  * @gdd_tasklet: bottom half for DMA transfers
  * @gdd_trn: Array of GDD transaction data for ongoing GDD transfers
  * @lock: lock to serialize access to GDD
+ * @fck_nb: DVFS notfifier block
+ * @fck_rate: clock rate
  * @loss_count: To follow if we need to restore context or not
  * @max_speed: Maximum TX speed (Kb/s) set by the clients.
  * @sysconfig: SSI controller saved context
@@ -151,6 +153,7 @@ struct omap_ssi_controller {
 	struct tasklet_struct	gdd_tasklet;
 	struct gdd_trn		gdd_trn[SSI_MAX_GDD_LCH];
 	spinlock_t		lock;
+	struct notifier_block	fck_nb;
 	unsigned long		fck_rate;
 	u32			loss_count;
 	u32			max_speed;
@@ -164,4 +167,9 @@ struct omap_ssi_controller {
 #endif
 };
 
+void omap_ssi_port_update_fclk(struct hsi_controller *ssi,
+			       struct omap_ssi_port *omap_port);
+
+extern struct platform_driver ssi_port_pdriver;
+
 #endif /* __LINUX_HSI_OMAP_SSI_H__ */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hsi/controllers/omap_ssi_port.c linux-libre-4.7-gnu/drivers/hsi/controllers/omap_ssi_port.c
--- linux-libre-4.6-gnu/drivers/hsi/controllers/omap_ssi_port.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hsi/controllers/omap_ssi_port.c	2016-07-24 15:23:50.000000000 -0400
@@ -23,8 +23,10 @@
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/pm_runtime.h>
+#include <linux/delay.h>
 
-#include <linux/of_gpio.h>
+#include <linux/gpio/consumer.h>
+#include <linux/pinctrl/consumer.h>
 #include <linux/debugfs.h>
 
 #include "omap_ssi_regs.h"
@@ -43,7 +45,7 @@ static inline int hsi_dummy_cl(struct hs
 static inline unsigned int ssi_wakein(struct hsi_port *port)
 {
 	struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
-	return gpio_get_value(omap_port->wake_gpio);
+	return gpiod_get_value(omap_port->wake_gpio);
 }
 
 #ifdef CONFIG_DEBUG_FS
@@ -171,7 +173,7 @@ static int ssi_div_set(void *data, u64 v
 
 DEFINE_SIMPLE_ATTRIBUTE(ssi_sst_div_fops, ssi_div_get, ssi_div_set, "%llu\n");
 
-static int __init ssi_debug_add_port(struct omap_ssi_port *omap_port,
+static int ssi_debug_add_port(struct omap_ssi_port *omap_port,
 				     struct dentry *dir)
 {
 	struct hsi_port *port = to_hsi_port(omap_port->dev);
@@ -514,6 +516,11 @@ static int ssi_flush(struct hsi_client *
 
 	pm_runtime_get_sync(omap_port->pdev);
 	spin_lock_bh(&omap_port->lock);
+
+	/* stop all ssi communication */
+	pinctrl_pm_select_idle_state(omap_port->pdev);
+	udelay(1); /* wait for racing frames */
+
 	/* Stop all DMA transfers */
 	for (i = 0; i < SSI_MAX_GDD_LCH; i++) {
 		msg = omap_ssi->gdd_trn[i].msg;
@@ -550,6 +557,10 @@ static int ssi_flush(struct hsi_client *
 		ssi_flush_queue(&omap_port->rxqueue[i], NULL);
 	}
 	ssi_flush_queue(&omap_port->brkqueue, NULL);
+
+	/* Resume SSI communication */
+	pinctrl_pm_select_default_state(omap_port->pdev);
+
 	spin_unlock_bh(&omap_port->lock);
 	pm_runtime_put_sync(omap_port->pdev);
 
@@ -1007,7 +1018,7 @@ static irqreturn_t ssi_wake_isr(int irq
 	return IRQ_HANDLED;
 }
 
-static int __init ssi_port_irq(struct hsi_port *port,
+static int ssi_port_irq(struct hsi_port *port,
 						struct platform_device *pd)
 {
 	struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
@@ -1029,19 +1040,19 @@ static int __init ssi_port_irq(struct hs
 	return err;
 }
 
-static int __init ssi_wake_irq(struct hsi_port *port,
+static int ssi_wake_irq(struct hsi_port *port,
 						struct platform_device *pd)
 {
 	struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
 	int cawake_irq;
 	int err;
 
-	if (omap_port->wake_gpio == -1) {
+	if (!omap_port->wake_gpio) {
 		omap_port->wake_irq = -1;
 		return 0;
 	}
 
-	cawake_irq = gpio_to_irq(omap_port->wake_gpio);
+	cawake_irq = gpiod_to_irq(omap_port->wake_gpio);
 
 	omap_port->wake_irq = cawake_irq;
 	tasklet_init(&omap_port->wake_tasklet, ssi_wake_tasklet,
@@ -1060,7 +1071,7 @@ static int __init ssi_wake_irq(struct hs
 	return err;
 }
 
-static void __init ssi_queues_init(struct omap_ssi_port *omap_port)
+static void ssi_queues_init(struct omap_ssi_port *omap_port)
 {
 	unsigned int ch;
 
@@ -1071,7 +1082,7 @@ static void __init ssi_queues_init(struc
 	INIT_LIST_HEAD(&omap_port->brkqueue);
 }
 
-static int __init ssi_port_get_iomem(struct platform_device *pd,
+static int ssi_port_get_iomem(struct platform_device *pd,
 		const char *name, void __iomem **pbase, dma_addr_t *phy)
 {
 	struct hsi_port *port = platform_get_drvdata(pd);
@@ -1104,24 +1115,19 @@ static int __init ssi_port_get_iomem(str
 	return 0;
 }
 
-static int __init ssi_port_probe(struct platform_device *pd)
+static int ssi_port_probe(struct platform_device *pd)
 {
 	struct device_node *np = pd->dev.of_node;
 	struct hsi_port *port;
 	struct omap_ssi_port *omap_port;
 	struct hsi_controller *ssi = dev_get_drvdata(pd->dev.parent);
 	struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
-	int cawake_gpio = 0;
+	struct gpio_desc *cawake_gpio = NULL;
 	u32 port_id;
 	int err;
 
 	dev_dbg(&pd->dev, "init ssi port...\n");
 
-	if (!try_module_get(ssi->owner)) {
-		dev_err(&pd->dev, "could not increment parent module refcount\n");
-		return -ENODEV;
-	}
-
 	if (!ssi->port || !omap_ssi->port) {
 		dev_err(&pd->dev, "ssi controller not initialized!\n");
 		err = -ENODEV;
@@ -1147,20 +1153,10 @@ static int __init ssi_port_probe(struct
 		goto error;
 	}
 
-	err = of_get_named_gpio(np, "ti,ssi-cawake-gpio", 0);
-	if (err < 0) {
-		dev_err(&pd->dev, "DT data is missing cawake gpio (err=%d)\n",
-			err);
-		goto error;
-	}
-	cawake_gpio = err;
-
-	err = devm_gpio_request_one(&port->device, cawake_gpio, GPIOF_DIR_IN,
-		"cawake");
-	if (err) {
-		dev_err(&pd->dev, "could not request cawake gpio (err=%d)!\n",
-			err);
-		err = -ENXIO;
+	cawake_gpio = devm_gpiod_get(&pd->dev, "ti,ssi-cawake", GPIOD_IN);
+	if (IS_ERR(cawake_gpio)) {
+		err = PTR_ERR(cawake_gpio);
+		dev_err(&pd->dev, "couldn't get cawake gpio (err=%d)!\n", err);
 		goto error;
 	}
 
@@ -1219,8 +1215,7 @@ static int __init ssi_port_probe(struct
 
 	hsi_add_clients_from_dt(port, np);
 
-	dev_info(&pd->dev, "ssi port %u successfully initialized (cawake=%d)\n",
-		port_id, cawake_gpio);
+	dev_info(&pd->dev, "ssi port %u successfully initialized\n", port_id);
 
 	return 0;
 
@@ -1228,7 +1223,7 @@ error:
 	return err;
 }
 
-static int __exit ssi_port_remove(struct platform_device *pd)
+static int ssi_port_remove(struct platform_device *pd)
 {
 	struct hsi_port *port = platform_get_drvdata(pd);
 	struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
@@ -1253,12 +1248,28 @@ static int __exit ssi_port_remove(struct
 
 	omap_ssi->port[omap_port->port_id] = NULL;
 	platform_set_drvdata(pd, NULL);
-	module_put(ssi->owner);
 	pm_runtime_disable(&pd->dev);
 
 	return 0;
 }
 
+static int ssi_restore_divisor(struct omap_ssi_port *omap_port)
+{
+	writel_relaxed(omap_port->sst.divisor,
+				omap_port->sst_base + SSI_SST_DIVISOR_REG);
+
+	return 0;
+}
+
+void omap_ssi_port_update_fclk(struct hsi_controller *ssi,
+			       struct omap_ssi_port *omap_port)
+{
+	/* update divisor */
+	u32 div = ssi_calculate_div(ssi);
+	omap_port->sst.divisor = div;
+	ssi_restore_divisor(omap_port);
+}
+
 #ifdef CONFIG_PM
 static int ssi_save_port_ctx(struct omap_ssi_port *omap_port)
 {
@@ -1311,14 +1322,6 @@ static int ssi_restore_port_mode(struct
 	return 0;
 }
 
-static int ssi_restore_divisor(struct omap_ssi_port *omap_port)
-{
-	writel_relaxed(omap_port->sst.divisor,
-				omap_port->sst_base + SSI_SST_DIVISOR_REG);
-
-	return 0;
-}
-
 static int omap_ssi_port_runtime_suspend(struct device *dev)
 {
 	struct hsi_port *port = dev_get_drvdata(dev);
@@ -1380,19 +1383,12 @@ MODULE_DEVICE_TABLE(of, omap_ssi_port_of
 #define omap_ssi_port_of_match NULL
 #endif
 
-static struct platform_driver ssi_port_pdriver = {
-	.remove	= __exit_p(ssi_port_remove),
+struct platform_driver ssi_port_pdriver = {
+	.probe = ssi_port_probe,
+	.remove	= ssi_port_remove,
 	.driver	= {
 		.name	= "omap_ssi_port",
 		.of_match_table = omap_ssi_port_of_match,
 		.pm	= DEV_PM_OPS,
 	},
 };
-
-module_platform_driver_probe(ssi_port_pdriver, ssi_port_probe);
-
-MODULE_ALIAS("platform:omap_ssi_port");
-MODULE_AUTHOR("Carlos Chinea <carlos.chinea@nokia.com>");
-MODULE_AUTHOR("Sebastian Reichel <sre@kernel.org>");
-MODULE_DESCRIPTION("Synchronous Serial Interface Port Driver");
-MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hv/channel_mgmt.c linux-libre-4.7-gnu/drivers/hv/channel_mgmt.c
--- linux-libre-4.6-gnu/drivers/hv/channel_mgmt.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hv/channel_mgmt.c	2016-07-24 15:23:50.000000000 -0400
@@ -597,27 +597,55 @@ static void init_vp_index(struct vmbus_c
 
 static void vmbus_wait_for_unload(void)
 {
-	int cpu = smp_processor_id();
-	void *page_addr = hv_context.synic_message_page[cpu];
-	struct hv_message *msg = (struct hv_message *)page_addr +
-				  VMBUS_MESSAGE_SINT;
+	int cpu;
+	void *page_addr;
+	struct hv_message *msg;
 	struct vmbus_channel_message_header *hdr;
-	bool unloaded = false;
+	u32 message_type;
 
+	/*
+	 * CHANNELMSG_UNLOAD_RESPONSE is always delivered to the CPU which was
+	 * used for initial contact or to CPU0 depending on host version. When
+	 * we're crashing on a different CPU let's hope that IRQ handler on
+	 * the cpu which receives CHANNELMSG_UNLOAD_RESPONSE is still
+	 * functional and vmbus_unload_response() will complete
+	 * vmbus_connection.unload_event. If not, the last thing we can do is
+	 * read message pages for all CPUs directly.
+	 */
 	while (1) {
-		if (READ_ONCE(msg->header.message_type) == HVMSG_NONE) {
-			mdelay(10);
-			continue;
-		}
+		if (completion_done(&vmbus_connection.unload_event))
+			break;
 
-		hdr = (struct vmbus_channel_message_header *)msg->u.payload;
-		if (hdr->msgtype == CHANNELMSG_UNLOAD_RESPONSE)
-			unloaded = true;
+		for_each_online_cpu(cpu) {
+			page_addr = hv_context.synic_message_page[cpu];
+			msg = (struct hv_message *)page_addr +
+				VMBUS_MESSAGE_SINT;
 
-		vmbus_signal_eom(msg);
+			message_type = READ_ONCE(msg->header.message_type);
+			if (message_type == HVMSG_NONE)
+				continue;
 
-		if (unloaded)
-			break;
+			hdr = (struct vmbus_channel_message_header *)
+				msg->u.payload;
+
+			if (hdr->msgtype == CHANNELMSG_UNLOAD_RESPONSE)
+				complete(&vmbus_connection.unload_event);
+
+			vmbus_signal_eom(msg, message_type);
+		}
+
+		mdelay(10);
+	}
+
+	/*
+	 * We're crashing and already got the UNLOAD_RESPONSE, cleanup all
+	 * maybe-pending messages on all CPUs to be able to receive new
+	 * messages after we reconnect.
+	 */
+	for_each_online_cpu(cpu) {
+		page_addr = hv_context.synic_message_page[cpu];
+		msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT;
+		msg->header.message_type = HVMSG_NONE;
 	}
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hv/connection.c linux-libre-4.7-gnu/drivers/hv/connection.c
--- linux-libre-4.6-gnu/drivers/hv/connection.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hv/connection.c	2016-07-24 15:23:50.000000000 -0400
@@ -495,3 +495,4 @@ void vmbus_set_event(struct vmbus_channe
 
 	hv_do_hypercall(HVCALL_SIGNAL_EVENT, channel->sig_event, NULL);
 }
+EXPORT_SYMBOL_GPL(vmbus_set_event);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hv/hv_balloon.c linux-libre-4.7-gnu/drivers/hv/hv_balloon.c
--- linux-libre-4.6-gnu/drivers/hv/hv_balloon.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hv/hv_balloon.c	2016-07-24 15:23:50.000000000 -0400
@@ -714,7 +714,7 @@ static bool pfn_covered(unsigned long st
 		 * If the pfn range we are dealing with is not in the current
 		 * "hot add block", move on.
 		 */
-		if ((start_pfn >= has->end_pfn))
+		if (start_pfn < has->start_pfn || start_pfn >= has->end_pfn)
 			continue;
 		/*
 		 * If the current hot add-request extends beyond
@@ -768,7 +768,7 @@ static unsigned long handle_pg_range(uns
 		 * If the pfn range we are dealing with is not in the current
 		 * "hot add block", move on.
 		 */
-		if ((start_pfn >= has->end_pfn))
+		if (start_pfn < has->start_pfn || start_pfn >= has->end_pfn)
 			continue;
 
 		old_covered_state = has->covered_end_pfn;
@@ -1400,6 +1400,7 @@ static void balloon_onchannelcallback(vo
 				 * This is a normal hot-add request specifying
 				 * hot-add memory.
 				 */
+				dm->host_specified_ha_region = false;
 				ha_pg_range = &ha_msg->range;
 				dm->ha_wrk.ha_page_range = *ha_pg_range;
 				dm->ha_wrk.ha_region_range.page_range = 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hv/hv_kvp.c linux-libre-4.7-gnu/drivers/hv/hv_kvp.c
--- linux-libre-4.6-gnu/drivers/hv/hv_kvp.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hv/hv_kvp.c	2016-07-24 15:23:50.000000000 -0400
@@ -78,9 +78,11 @@ static void kvp_send_key(struct work_str
 
 static void kvp_respond_to_host(struct hv_kvp_msg *msg, int error);
 static void kvp_timeout_func(struct work_struct *dummy);
+static void kvp_host_handshake_func(struct work_struct *dummy);
 static void kvp_register(int);
 
 static DECLARE_DELAYED_WORK(kvp_timeout_work, kvp_timeout_func);
+static DECLARE_DELAYED_WORK(kvp_host_handshake_work, kvp_host_handshake_func);
 static DECLARE_WORK(kvp_sendkey_work, kvp_send_key);
 
 static const char kvp_devname[] = "vmbus/hv_kvp";
@@ -130,6 +132,11 @@ static void kvp_timeout_func(struct work
 	hv_poll_channel(kvp_transaction.recv_channel, kvp_poll_wrapper);
 }
 
+static void kvp_host_handshake_func(struct work_struct *dummy)
+{
+	hv_poll_channel(kvp_transaction.recv_channel, hv_kvp_onchannelcallback);
+}
+
 static int kvp_handle_handshake(struct hv_kvp_msg *msg)
 {
 	switch (msg->kvp_hdr.operation) {
@@ -154,6 +161,12 @@ static int kvp_handle_handshake(struct h
 	pr_debug("KVP: userspace daemon ver. %d registered\n",
 		 KVP_OP_REGISTER);
 	kvp_register(dm_reg_value);
+
+	/*
+	 * If we're still negotiating with the host cancel the timeout
+	 * work to not poll the channel twice.
+	 */
+	cancel_delayed_work_sync(&kvp_host_handshake_work);
 	hv_poll_channel(kvp_transaction.recv_channel, kvp_poll_wrapper);
 
 	return 0;
@@ -594,7 +607,22 @@ void hv_kvp_onchannelcallback(void *cont
 	struct icmsg_negotiate *negop = NULL;
 	int util_fw_version;
 	int kvp_srv_version;
+	static enum {NEGO_NOT_STARTED,
+		     NEGO_IN_PROGRESS,
+		     NEGO_FINISHED} host_negotiatied = NEGO_NOT_STARTED;
 
+	if (host_negotiatied == NEGO_NOT_STARTED &&
+	    kvp_transaction.state < HVUTIL_READY) {
+		/*
+		 * If userspace daemon is not connected and host is asking
+		 * us to negotiate we need to delay to not lose messages.
+		 * This is important for Failover IP setting.
+		 */
+		host_negotiatied = NEGO_IN_PROGRESS;
+		schedule_delayed_work(&kvp_host_handshake_work,
+				      HV_UTIL_NEGO_TIMEOUT * HZ);
+		return;
+	}
 	if (kvp_transaction.state > HVUTIL_READY)
 		return;
 
@@ -672,6 +700,8 @@ void hv_kvp_onchannelcallback(void *cont
 		vmbus_sendpacket(channel, recv_buffer,
 				       recvlen, requestid,
 				       VM_PKT_DATA_INBAND, 0);
+
+		host_negotiatied = NEGO_FINISHED;
 	}
 
 }
@@ -708,6 +738,7 @@ hv_kvp_init(struct hv_util_service *srv)
 void hv_kvp_deinit(void)
 {
 	kvp_transaction.state = HVUTIL_DEVICE_DYING;
+	cancel_delayed_work_sync(&kvp_host_handshake_work);
 	cancel_delayed_work_sync(&kvp_timeout_work);
 	cancel_work_sync(&kvp_sendkey_work);
 	hvutil_transport_destroy(hvt);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hv/hyperv_vmbus.h linux-libre-4.7-gnu/drivers/hv/hyperv_vmbus.h
--- linux-libre-4.6-gnu/drivers/hv/hyperv_vmbus.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hv/hyperv_vmbus.h	2016-07-24 15:23:50.000000000 -0400
@@ -36,6 +36,11 @@
 #define HV_UTIL_TIMEOUT 30
 
 /*
+ * Timeout for guest-host handshake for services.
+ */
+#define HV_UTIL_NEGO_TIMEOUT 60
+
+/*
  * The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent
  * is set by CPUID(HVCPUID_VERSION_FEATURES).
  */
@@ -620,9 +625,21 @@ extern struct vmbus_channel_message_tabl
 	channel_message_table[CHANNELMSG_COUNT];
 
 /* Free the message slot and signal end-of-message if required */
-static inline void vmbus_signal_eom(struct hv_message *msg)
+static inline void vmbus_signal_eom(struct hv_message *msg, u32 old_msg_type)
 {
-	msg->header.message_type = HVMSG_NONE;
+	/*
+	 * On crash we're reading some other CPU's message page and we need
+	 * to be careful: this other CPU may already had cleared the header
+	 * and the host may already had delivered some other message there.
+	 * In case we blindly write msg->header.message_type we're going
+	 * to lose it. We can still lose a message of the same type but
+	 * we count on the fact that there can only be one
+	 * CHANNELMSG_UNLOAD_RESPONSE and we don't care about other messages
+	 * on crash.
+	 */
+	if (cmpxchg(&msg->header.message_type, old_msg_type,
+		    HVMSG_NONE) != old_msg_type)
+		return;
 
 	/*
 	 * Make sure the write to MessageType (ie set to
@@ -667,8 +684,6 @@ void vmbus_disconnect(void);
 
 int vmbus_post_msg(void *buffer, size_t buflen);
 
-void vmbus_set_event(struct vmbus_channel *channel);
-
 void vmbus_on_event(unsigned long data);
 void vmbus_on_msg_dpc(unsigned long data);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hv/ring_buffer.c linux-libre-4.7-gnu/drivers/hv/ring_buffer.c
--- linux-libre-4.6-gnu/drivers/hv/ring_buffer.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hv/ring_buffer.c	2016-07-24 15:23:50.000000000 -0400
@@ -33,25 +33,21 @@
 void hv_begin_read(struct hv_ring_buffer_info *rbi)
 {
 	rbi->ring_buffer->interrupt_mask = 1;
-	mb();
+	virt_mb();
 }
 
 u32 hv_end_read(struct hv_ring_buffer_info *rbi)
 {
-	u32 read;
-	u32 write;
 
 	rbi->ring_buffer->interrupt_mask = 0;
-	mb();
+	virt_mb();
 
 	/*
 	 * Now check to see if the ring buffer is still empty.
 	 * If it is not, we raced and we need to process new
 	 * incoming messages.
 	 */
-	hv_get_ringbuffer_availbytes(rbi, &read, &write);
-
-	return read;
+	return hv_get_bytes_to_read(rbi);
 }
 
 /*
@@ -72,69 +68,17 @@ u32 hv_end_read(struct hv_ring_buffer_in
 
 static bool hv_need_to_signal(u32 old_write, struct hv_ring_buffer_info *rbi)
 {
-	mb();
-	if (rbi->ring_buffer->interrupt_mask)
+	virt_mb();
+	if (READ_ONCE(rbi->ring_buffer->interrupt_mask))
 		return false;
 
 	/* check interrupt_mask before read_index */
-	rmb();
+	virt_rmb();
 	/*
 	 * This is the only case we need to signal when the
 	 * ring transitions from being empty to non-empty.
 	 */
-	if (old_write == rbi->ring_buffer->read_index)
-		return true;
-
-	return false;
-}
-
-/*
- * To optimize the flow management on the send-side,
- * when the sender is blocked because of lack of
- * sufficient space in the ring buffer, potential the
- * consumer of the ring buffer can signal the producer.
- * This is controlled by the following parameters:
- *
- * 1. pending_send_sz: This is the size in bytes that the
- *    producer is trying to send.
- * 2. The feature bit feat_pending_send_sz set to indicate if
- *    the consumer of the ring will signal when the ring
- *    state transitions from being full to a state where
- *    there is room for the producer to send the pending packet.
- */
-
-static bool hv_need_to_signal_on_read(struct hv_ring_buffer_info *rbi)
-{
-	u32 cur_write_sz;
-	u32 r_size;
-	u32 write_loc;
-	u32 read_loc = rbi->ring_buffer->read_index;
-	u32 pending_sz;
-
-	/*
-	 * Issue a full memory barrier before making the signaling decision.
-	 * Here is the reason for having this barrier:
-	 * If the reading of the pend_sz (in this function)
-	 * were to be reordered and read before we commit the new read
-	 * index (in the calling function)  we could
-	 * have a problem. If the host were to set the pending_sz after we
-	 * have sampled pending_sz and go to sleep before we commit the
-	 * read index, we could miss sending the interrupt. Issue a full
-	 * memory barrier to address this.
-	 */
-	mb();
-
-	pending_sz = rbi->ring_buffer->pending_send_sz;
-	write_loc = rbi->ring_buffer->write_index;
-	/* If the other end is not blocked on write don't bother. */
-	if (pending_sz == 0)
-		return false;
-
-	r_size = rbi->ring_datasize;
-	cur_write_sz = write_loc >= read_loc ? r_size - (write_loc - read_loc) :
-			read_loc - write_loc;
-
-	if (cur_write_sz >= pending_sz)
+	if (old_write == READ_ONCE(rbi->ring_buffer->read_index))
 		return true;
 
 	return false;
@@ -188,17 +132,9 @@ hv_set_next_read_location(struct hv_ring
 		    u32 next_read_location)
 {
 	ring_info->ring_buffer->read_index = next_read_location;
+	ring_info->priv_read_index = next_read_location;
 }
 
-
-/* Get the start of the ring buffer. */
-static inline void *
-hv_get_ring_buffer(struct hv_ring_buffer_info *ring_info)
-{
-	return (void *)ring_info->ring_buffer->buffer;
-}
-
-
 /* Get the size of the ring buffer. */
 static inline u32
 hv_get_ring_buffersize(struct hv_ring_buffer_info *ring_info)
@@ -332,7 +268,6 @@ int hv_ringbuffer_write(struct hv_ring_b
 {
 	int i = 0;
 	u32 bytes_avail_towrite;
-	u32 bytes_avail_toread;
 	u32 totalbytes_towrite = 0;
 
 	u32 next_write_location;
@@ -348,9 +283,7 @@ int hv_ringbuffer_write(struct hv_ring_b
 	if (lock)
 		spin_lock_irqsave(&outring_info->ring_lock, flags);
 
-	hv_get_ringbuffer_availbytes(outring_info,
-				&bytes_avail_toread,
-				&bytes_avail_towrite);
+	bytes_avail_towrite = hv_get_bytes_to_write(outring_info);
 
 	/*
 	 * If there is only room for the packet, assume it is full.
@@ -384,7 +317,7 @@ int hv_ringbuffer_write(struct hv_ring_b
 					     sizeof(u64));
 
 	/* Issue a full memory barrier before updating the write index */
-	mb();
+	virt_mb();
 
 	/* Now, update the write location */
 	hv_set_next_write_location(outring_info, next_write_location);
@@ -401,7 +334,6 @@ int hv_ringbuffer_read(struct hv_ring_bu
 		       void *buffer, u32 buflen, u32 *buffer_actual_len,
 		       u64 *requestid, bool *signal, bool raw)
 {
-	u32 bytes_avail_towrite;
 	u32 bytes_avail_toread;
 	u32 next_read_location = 0;
 	u64 prev_indices = 0;
@@ -417,10 +349,7 @@ int hv_ringbuffer_read(struct hv_ring_bu
 	*buffer_actual_len = 0;
 	*requestid = 0;
 
-	hv_get_ringbuffer_availbytes(inring_info,
-				&bytes_avail_toread,
-				&bytes_avail_towrite);
-
+	bytes_avail_toread = hv_get_bytes_to_read(inring_info);
 	/* Make sure there is something to read */
 	if (bytes_avail_toread < sizeof(desc)) {
 		/*
@@ -464,7 +393,7 @@ int hv_ringbuffer_read(struct hv_ring_bu
 	 * the writer may start writing to the read area once the read index
 	 * is updated.
 	 */
-	mb();
+	virt_mb();
 
 	/* Update the read index */
 	hv_set_next_read_location(inring_info, next_read_location);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hv/vmbus_drv.c linux-libre-4.7-gnu/drivers/hv/vmbus_drv.c
--- linux-libre-4.6-gnu/drivers/hv/vmbus_drv.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hv/vmbus_drv.c	2016-07-24 15:23:50.000000000 -0400
@@ -41,6 +41,7 @@
 #include <linux/ptrace.h>
 #include <linux/screen_info.h>
 #include <linux/kdebug.h>
+#include <linux/efi.h>
 #include "hyperv_vmbus.h"
 
 static struct acpi_device  *hv_acpi_dev;
@@ -101,7 +102,10 @@ static struct notifier_block hyperv_pani
 	.notifier_call = hyperv_panic_event,
 };
 
+static const char *fb_mmio_name = "fb_range";
+static struct resource *fb_mmio;
 struct resource *hyperv_mmio;
+DEFINE_SEMAPHORE(hyperv_mmio_lock);
 
 static int vmbus_exists(void)
 {
@@ -708,7 +712,7 @@ static void hv_process_timer_expiration(
 	if (dev->event_handler)
 		dev->event_handler(dev);
 
-	vmbus_signal_eom(msg);
+	vmbus_signal_eom(msg, HVMSG_TIMER_EXPIRED);
 }
 
 void vmbus_on_msg_dpc(unsigned long data)
@@ -720,8 +724,9 @@ void vmbus_on_msg_dpc(unsigned long data
 	struct vmbus_channel_message_header *hdr;
 	struct vmbus_channel_message_table_entry *entry;
 	struct onmessage_work_context *ctx;
+	u32 message_type = msg->header.message_type;
 
-	if (msg->header.message_type == HVMSG_NONE)
+	if (message_type == HVMSG_NONE)
 		/* no msg */
 		return;
 
@@ -746,7 +751,7 @@ void vmbus_on_msg_dpc(unsigned long data
 		entry->message_handler(hdr);
 
 msg_handled:
-	vmbus_signal_eom(msg);
+	vmbus_signal_eom(msg, message_type);
 }
 
 static void vmbus_isr(void)
@@ -1048,7 +1053,6 @@ static acpi_status vmbus_walk_resources(
 	new_res->end = end;
 
 	/*
-	 * Stick ranges from higher in address space at the front of the list.
 	 * If two ranges are adjacent, merge them.
 	 */
 	do {
@@ -1069,7 +1073,7 @@ static acpi_status vmbus_walk_resources(
 			break;
 		}
 
-		if ((*old_res)->end < new_res->start) {
+		if ((*old_res)->start > new_res->end) {
 			new_res->sibling = *old_res;
 			if (prev_res)
 				(*prev_res)->sibling = new_res;
@@ -1091,6 +1095,12 @@ static int vmbus_acpi_remove(struct acpi
 	struct resource *next_res;
 
 	if (hyperv_mmio) {
+		if (fb_mmio) {
+			__release_region(hyperv_mmio, fb_mmio->start,
+					 resource_size(fb_mmio));
+			fb_mmio = NULL;
+		}
+
 		for (cur_res = hyperv_mmio; cur_res; cur_res = next_res) {
 			next_res = cur_res->sibling;
 			kfree(cur_res);
@@ -1100,6 +1110,30 @@ static int vmbus_acpi_remove(struct acpi
 	return 0;
 }
 
+static void vmbus_reserve_fb(void)
+{
+	int size;
+	/*
+	 * Make a claim for the frame buffer in the resource tree under the
+	 * first node, which will be the one below 4GB.  The length seems to
+	 * be underreported, particularly in a Generation 1 VM.  So start out
+	 * reserving a larger area and make it smaller until it succeeds.
+	 */
+
+	if (screen_info.lfb_base) {
+		if (efi_enabled(EFI_BOOT))
+			size = max_t(__u32, screen_info.lfb_size, 0x800000);
+		else
+			size = max_t(__u32, screen_info.lfb_size, 0x4000000);
+
+		for (; !fb_mmio && (size >= 0x100000); size >>= 1) {
+			fb_mmio = __request_region(hyperv_mmio,
+						   screen_info.lfb_base, size,
+						   fb_mmio_name, 0);
+		}
+	}
+}
+
 /**
  * vmbus_allocate_mmio() - Pick a memory-mapped I/O range.
  * @new:		If successful, supplied a pointer to the
@@ -1128,11 +1162,33 @@ int vmbus_allocate_mmio(struct resource
 			resource_size_t size, resource_size_t align,
 			bool fb_overlap_ok)
 {
-	struct resource *iter;
-	resource_size_t range_min, range_max, start, local_min, local_max;
+	struct resource *iter, *shadow;
+	resource_size_t range_min, range_max, start;
 	const char *dev_n = dev_name(&device_obj->device);
-	u32 fb_end = screen_info.lfb_base + (screen_info.lfb_size << 1);
-	int i;
+	int retval;
+
+	retval = -ENXIO;
+	down(&hyperv_mmio_lock);
+
+	/*
+	 * If overlaps with frame buffers are allowed, then first attempt to
+	 * make the allocation from within the reserved region.  Because it
+	 * is already reserved, no shadow allocation is necessary.
+	 */
+	if (fb_overlap_ok && fb_mmio && !(min > fb_mmio->end) &&
+	    !(max < fb_mmio->start)) {
+
+		range_min = fb_mmio->start;
+		range_max = fb_mmio->end;
+		start = (range_min + align - 1) & ~(align - 1);
+		for (; start + size - 1 <= range_max; start += align) {
+			*new = request_mem_region_exclusive(start, size, dev_n);
+			if (*new) {
+				retval = 0;
+				goto exit;
+			}
+		}
+	}
 
 	for (iter = hyperv_mmio; iter; iter = iter->sibling) {
 		if ((iter->start >= max) || (iter->end <= min))
@@ -1140,46 +1196,56 @@ int vmbus_allocate_mmio(struct resource
 
 		range_min = iter->start;
 		range_max = iter->end;
+		start = (range_min + align - 1) & ~(align - 1);
+		for (; start + size - 1 <= range_max; start += align) {
+			shadow = __request_region(iter, start, size, NULL,
+						  IORESOURCE_BUSY);
+			if (!shadow)
+				continue;
 
-		/* If this range overlaps the frame buffer, split it into
-		   two tries. */
-		for (i = 0; i < 2; i++) {
-			local_min = range_min;
-			local_max = range_max;
-			if (fb_overlap_ok || (range_min >= fb_end) ||
-			    (range_max <= screen_info.lfb_base)) {
-				i++;
-			} else {
-				if ((range_min <= screen_info.lfb_base) &&
-				    (range_max >= screen_info.lfb_base)) {
-					/*
-					 * The frame buffer is in this window,
-					 * so trim this into the part that
-					 * preceeds the frame buffer.
-					 */
-					local_max = screen_info.lfb_base - 1;
-					range_min = fb_end;
-				} else {
-					range_min = fb_end;
-					continue;
-				}
+			*new = request_mem_region_exclusive(start, size, dev_n);
+			if (*new) {
+				shadow->name = (char *)*new;
+				retval = 0;
+				goto exit;
 			}
 
-			start = (local_min + align - 1) & ~(align - 1);
-			for (; start + size - 1 <= local_max; start += align) {
-				*new = request_mem_region_exclusive(start, size,
-								    dev_n);
-				if (*new)
-					return 0;
-			}
+			__release_region(iter, start, size);
 		}
 	}
 
-	return -ENXIO;
+exit:
+	up(&hyperv_mmio_lock);
+	return retval;
 }
 EXPORT_SYMBOL_GPL(vmbus_allocate_mmio);
 
 /**
+ * vmbus_free_mmio() - Free a memory-mapped I/O range.
+ * @start:		Base address of region to release.
+ * @size:		Size of the range to be allocated
+ *
+ * This function releases anything requested by
+ * vmbus_mmio_allocate().
+ */
+void vmbus_free_mmio(resource_size_t start, resource_size_t size)
+{
+	struct resource *iter;
+
+	down(&hyperv_mmio_lock);
+	for (iter = hyperv_mmio; iter; iter = iter->sibling) {
+		if ((iter->start >= start + size) || (iter->end <= start))
+			continue;
+
+		__release_region(iter, start, size);
+	}
+	release_mem_region(start, size);
+	up(&hyperv_mmio_lock);
+
+}
+EXPORT_SYMBOL_GPL(vmbus_free_mmio);
+
+/**
  * vmbus_cpu_number_to_vp_number() - Map CPU to VP.
  * @cpu_number: CPU number in Linux terms
  *
@@ -1219,8 +1285,10 @@ static int vmbus_acpi_add(struct acpi_de
 
 		if (ACPI_FAILURE(result))
 			continue;
-		if (hyperv_mmio)
+		if (hyperv_mmio) {
+			vmbus_reserve_fb();
 			break;
+		}
 	}
 	ret_val = 0;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwmon/ads7828.c linux-libre-4.7-gnu/drivers/hwmon/ads7828.c
--- linux-libre-4.6-gnu/drivers/hwmon/ads7828.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hwmon/ads7828.c	2016-07-24 15:23:50.000000000 -0400
@@ -120,6 +120,7 @@ static int ads7828_probe(struct i2c_clie
 	unsigned int vref_mv = ADS7828_INT_VREF_MV;
 	bool diff_input = false;
 	bool ext_vref = false;
+	unsigned int regval;
 
 	data = devm_kzalloc(dev, sizeof(struct ads7828_data), GFP_KERNEL);
 	if (!data)
@@ -154,6 +155,15 @@ static int ads7828_probe(struct i2c_clie
 	if (!diff_input)
 		data->cmd_byte |= ADS7828_CMD_SD_SE;
 
+	/*
+	 * Datasheet specifies internal reference voltage is disabled by
+	 * default. The internal reference voltage needs to be enabled and
+	 * voltage needs to settle before getting valid ADC data. So perform a
+	 * dummy read to enable the internal reference voltage.
+	 */
+	if (!ext_vref)
+		regmap_read(data->regmap, data->cmd_byte, &regval);
+
 	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
 							   data,
 							   ads7828_groups);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwmon/dell-smm-hwmon.c linux-libre-4.7-gnu/drivers/hwmon/dell-smm-hwmon.c
--- linux-libre-4.6-gnu/drivers/hwmon/dell-smm-hwmon.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hwmon/dell-smm-hwmon.c	2016-07-24 15:23:50.000000000 -0400
@@ -35,6 +35,7 @@
 #include <linux/uaccess.h>
 #include <linux/io.h>
 #include <linux/sched.h>
+#include <linux/ctype.h>
 
 #include <linux/i8k.h>
 
@@ -66,11 +67,13 @@
 
 static DEFINE_MUTEX(i8k_mutex);
 static char bios_version[4];
+static char bios_machineid[16];
 static struct device *i8k_hwmon_dev;
 static u32 i8k_hwmon_flags;
 static uint i8k_fan_mult = I8K_FAN_MULT;
 static uint i8k_pwm_mult;
 static uint i8k_fan_max = I8K_FAN_HIGH;
+static bool disallow_fan_type_call;
 
 #define I8K_HWMON_HAVE_TEMP1	(1 << 0)
 #define I8K_HWMON_HAVE_TEMP2	(1 << 1)
@@ -94,13 +97,13 @@ module_param(ignore_dmi, bool, 0);
 MODULE_PARM_DESC(ignore_dmi, "Continue probing hardware even if DMI data does not match");
 
 #if IS_ENABLED(CONFIG_I8K)
-static bool restricted;
+static bool restricted = true;
 module_param(restricted, bool, 0);
-MODULE_PARM_DESC(restricted, "Allow fan control if SYS_ADMIN capability set");
+MODULE_PARM_DESC(restricted, "Restrict fan control and serial number to CAP_SYS_ADMIN (default: 1)");
 
 static bool power_status;
 module_param(power_status, bool, 0600);
-MODULE_PARM_DESC(power_status, "Report power status in /proc/i8k");
+MODULE_PARM_DESC(power_status, "Report power status in /proc/i8k (default: 0)");
 #endif
 
 static uint fan_mult;
@@ -235,14 +238,28 @@ static int i8k_get_fan_speed(int fan)
 /*
  * Read the fan type.
  */
-static int i8k_get_fan_type(int fan)
+static int _i8k_get_fan_type(int fan)
 {
 	struct smm_regs regs = { .eax = I8K_SMM_GET_FAN_TYPE, };
 
+	if (disallow_fan_type_call)
+		return -EINVAL;
+
 	regs.ebx = fan & 0xff;
 	return i8k_smm(&regs) ? : regs.eax & 0xff;
 }
 
+static int i8k_get_fan_type(int fan)
+{
+	/* I8K_SMM_GET_FAN_TYPE SMM call is expensive, so cache values */
+	static int types[2] = { INT_MIN, INT_MIN };
+
+	if (types[fan] == INT_MIN)
+		types[fan] = _i8k_get_fan_type(fan);
+
+	return types[fan];
+}
+
 /*
  * Read the fan nominal rpm for specific fan speed.
  */
@@ -387,14 +404,20 @@ i8k_ioctl_unlocked(struct file *fp, unsi
 
 	switch (cmd) {
 	case I8K_BIOS_VERSION:
+		if (!isdigit(bios_version[0]) || !isdigit(bios_version[1]) ||
+		    !isdigit(bios_version[2]))
+			return -EINVAL;
+
 		val = (bios_version[0] << 16) |
 				(bios_version[1] << 8) | bios_version[2];
 		break;
 
 	case I8K_MACHINE_ID:
-		memset(buff, 0, 16);
-		strlcpy(buff, i8k_get_dmi_data(DMI_PRODUCT_SERIAL),
-			sizeof(buff));
+		if (restricted && !capable(CAP_SYS_ADMIN))
+			return -EPERM;
+
+		memset(buff, 0, sizeof(buff));
+		strlcpy(buff, bios_machineid, sizeof(buff));
 		break;
 
 	case I8K_FN_STATUS:
@@ -511,7 +534,7 @@ static int i8k_proc_show(struct seq_file
 	seq_printf(seq, "%s %s %s %d %d %d %d %d %d %d\n",
 		   I8K_PROC_FMT,
 		   bios_version,
-		   i8k_get_dmi_data(DMI_PRODUCT_SERIAL),
+		   (restricted && !capable(CAP_SYS_ADMIN)) ? "-1" : bios_machineid,
 		   cpu_temp,
 		   left_fan, right_fan, left_speed, right_speed,
 		   ac_power, fn_key);
@@ -718,6 +741,9 @@ static struct attribute *i8k_attrs[] = {
 static umode_t i8k_is_visible(struct kobject *kobj, struct attribute *attr,
 			      int index)
 {
+	if (disallow_fan_type_call &&
+	    (index == 9 || index == 12))
+		return 0;
 	if (index >= 0 && index <= 1 &&
 	    !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP1))
 		return 0;
@@ -767,13 +793,17 @@ static int __init i8k_init_hwmon(void)
 	if (err >= 0)
 		i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP4;
 
-	/* First fan attributes, if fan type is OK */
-	err = i8k_get_fan_type(0);
+	/* First fan attributes, if fan status or type is OK */
+	err = i8k_get_fan_status(0);
+	if (err < 0)
+		err = i8k_get_fan_type(0);
 	if (err >= 0)
 		i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN1;
 
-	/* Second fan attributes, if fan type is OK */
-	err = i8k_get_fan_type(1);
+	/* Second fan attributes, if fan status or type is OK */
+	err = i8k_get_fan_status(1);
+	if (err < 0)
+		err = i8k_get_fan_type(1);
 	if (err >= 0)
 		i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN2;
 
@@ -929,12 +959,14 @@ static struct dmi_system_id i8k_dmi_tabl
 
 MODULE_DEVICE_TABLE(dmi, i8k_dmi_table);
 
-static struct dmi_system_id i8k_blacklist_dmi_table[] __initdata = {
+/*
+ * On some machines once I8K_SMM_GET_FAN_TYPE is issued then CPU fan speed
+ * randomly going up and down due to bug in Dell SMM or BIOS. Here is blacklist
+ * of affected Dell machines for which we disallow I8K_SMM_GET_FAN_TYPE call.
+ * See bug: https://bugzilla.kernel.org/show_bug.cgi?id=100121
+ */
+static struct dmi_system_id i8k_blacklist_fan_type_dmi_table[] __initdata = {
 	{
-		/*
-		 * CPU fan speed going up and down on Dell Studio XPS 8000
-		 * for unknown reasons.
-		 */
 		.ident = "Dell Studio XPS 8000",
 		.matches = {
 			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
@@ -942,16 +974,19 @@ static struct dmi_system_id i8k_blacklis
 		},
 	},
 	{
-		/*
-		 * CPU fan speed going up and down on Dell Studio XPS 8100
-		 * for unknown reasons.
-		 */
 		.ident = "Dell Studio XPS 8100",
 		.matches = {
 			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Studio XPS 8100"),
 		},
 	},
+	{
+		.ident = "Dell Inspiron 580",
+		.matches = {
+			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Inspiron 580 "),
+		},
+	},
 	{ }
 };
 
@@ -966,8 +1001,7 @@ static int __init i8k_probe(void)
 	/*
 	 * Get DMI information
 	 */
-	if (!dmi_check_system(i8k_dmi_table) ||
-	    dmi_check_system(i8k_blacklist_dmi_table)) {
+	if (!dmi_check_system(i8k_dmi_table)) {
 		if (!ignore_dmi && !force)
 			return -ENODEV;
 
@@ -978,8 +1012,13 @@ static int __init i8k_probe(void)
 			i8k_get_dmi_data(DMI_BIOS_VERSION));
 	}
 
+	if (dmi_check_system(i8k_blacklist_fan_type_dmi_table))
+		disallow_fan_type_call = true;
+
 	strlcpy(bios_version, i8k_get_dmi_data(DMI_BIOS_VERSION),
 		sizeof(bios_version));
+	strlcpy(bios_machineid, i8k_get_dmi_data(DMI_PRODUCT_SERIAL),
+		sizeof(bios_machineid));
 
 	/*
 	 * Get SMM Dell signature
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwmon/emc2103.c linux-libre-4.7-gnu/drivers/hwmon/emc2103.c
--- linux-libre-4.6-gnu/drivers/hwmon/emc2103.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hwmon/emc2103.c	2016-07-24 15:23:50.000000000 -0400
@@ -58,7 +58,7 @@ static const u8 REG_TEMP_MAX[4] = { 0x34
  */
 static int apd = -1;
 module_param(apd, bint, 0);
-MODULE_PARM_DESC(init, "Set to zero to disable anti-parallel diode mode");
+MODULE_PARM_DESC(apd, "Set to zero to disable anti-parallel diode mode");
 
 struct temperature {
 	s8	degrees;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwmon/fam15h_power.c linux-libre-4.7-gnu/drivers/hwmon/fam15h_power.c
--- linux-libre-4.6-gnu/drivers/hwmon/fam15h_power.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hwmon/fam15h_power.c	2016-07-24 15:23:50.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * fam15h_power.c - AMD Family 15h processor power monitoring
  *
- * Copyright (c) 2011 Advanced Micro Devices, Inc.
+ * Copyright (c) 2011-2016 Advanced Micro Devices, Inc.
  * Author: Andreas Herrmann <herrmann.der.user@googlemail.com>
  *
  *
@@ -25,6 +25,10 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/bitops.h>
+#include <linux/cpu.h>
+#include <linux/cpumask.h>
+#include <linux/time.h>
+#include <linux/sched.h>
 #include <asm/processor.h>
 #include <asm/msr.h>
 
@@ -44,8 +48,14 @@ MODULE_LICENSE("GPL");
 
 #define FAM15H_MIN_NUM_ATTRS		2
 #define FAM15H_NUM_GROUPS		2
+#define MAX_CUS				8
 
+/* set maximum interval as 1 second */
+#define MAX_INTERVAL			1000
+
+#define MSR_F15H_CU_PWR_ACCUMULATOR	0xc001007a
 #define MSR_F15H_CU_MAX_PWR_ACCUMULATOR	0xc001007b
+#define MSR_F15H_PTSC			0xc0010280
 
 #define PCI_DEVICE_ID_AMD_15H_M70H_NB_F4 0x15b4
 
@@ -59,8 +69,20 @@ struct fam15h_power_data {
 	struct attribute_group group;
 	/* maximum accumulated power of a compute unit */
 	u64 max_cu_acc_power;
+	/* accumulated power of the compute units */
+	u64 cu_acc_power[MAX_CUS];
+	/* performance timestamp counter */
+	u64 cpu_sw_pwr_ptsc[MAX_CUS];
+	/* online/offline status of current compute unit */
+	int cu_on[MAX_CUS];
+	unsigned long power_period;
 };
 
+static bool is_carrizo_or_later(void)
+{
+	return boot_cpu_data.x86 == 0x15 && boot_cpu_data.x86_model >= 0x60;
+}
+
 static ssize_t show_power(struct device *dev,
 			  struct device_attribute *attr, char *buf)
 {
@@ -77,7 +99,7 @@ static ssize_t show_power(struct device
 	 * On Carrizo and later platforms, TdpRunAvgAccCap bit field
 	 * is extended to 4:31 from 4:25.
 	 */
-	if (boot_cpu_data.x86 == 0x15 && boot_cpu_data.x86_model >= 0x60) {
+	if (is_carrizo_or_later()) {
 		running_avg_capture = val >> 4;
 		running_avg_capture = sign_extend32(running_avg_capture, 27);
 	} else {
@@ -94,7 +116,7 @@ static ssize_t show_power(struct device
 	 * On Carrizo and later platforms, ApmTdpLimit bit field
 	 * is extended to 16:31 from 16:28.
 	 */
-	if (boot_cpu_data.x86 == 0x15 && boot_cpu_data.x86_model >= 0x60)
+	if (is_carrizo_or_later())
 		tdp_limit = val >> 16;
 	else
 		tdp_limit = (val >> 16) & 0x1fff;
@@ -125,6 +147,163 @@ static ssize_t show_power_crit(struct de
 }
 static DEVICE_ATTR(power1_crit, S_IRUGO, show_power_crit, NULL);
 
+static void do_read_registers_on_cu(void *_data)
+{
+	struct fam15h_power_data *data = _data;
+	int cpu, cu;
+
+	cpu = smp_processor_id();
+
+	/*
+	 * With the new x86 topology modelling, cpu core id actually
+	 * is compute unit id.
+	 */
+	cu = cpu_data(cpu).cpu_core_id;
+
+	rdmsrl_safe(MSR_F15H_CU_PWR_ACCUMULATOR, &data->cu_acc_power[cu]);
+	rdmsrl_safe(MSR_F15H_PTSC, &data->cpu_sw_pwr_ptsc[cu]);
+
+	data->cu_on[cu] = 1;
+}
+
+/*
+ * This function is only able to be called when CPUID
+ * Fn8000_0007:EDX[12] is set.
+ */
+static int read_registers(struct fam15h_power_data *data)
+{
+	int core, this_core;
+	cpumask_var_t mask;
+	int ret, cpu;
+
+	ret = zalloc_cpumask_var(&mask, GFP_KERNEL);
+	if (!ret)
+		return -ENOMEM;
+
+	memset(data->cu_on, 0, sizeof(int) * MAX_CUS);
+
+	get_online_cpus();
+
+	/*
+	 * Choose the first online core of each compute unit, and then
+	 * read their MSR value of power and ptsc in a single IPI,
+	 * because the MSR value of CPU core represent the compute
+	 * unit's.
+	 */
+	core = -1;
+
+	for_each_online_cpu(cpu) {
+		this_core = topology_core_id(cpu);
+
+		if (this_core == core)
+			continue;
+
+		core = this_core;
+
+		/* get any CPU on this compute unit */
+		cpumask_set_cpu(cpumask_any(topology_sibling_cpumask(cpu)), mask);
+	}
+
+	on_each_cpu_mask(mask, do_read_registers_on_cu, data, true);
+
+	put_online_cpus();
+	free_cpumask_var(mask);
+
+	return 0;
+}
+
+static ssize_t acc_show_power(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	struct fam15h_power_data *data = dev_get_drvdata(dev);
+	u64 prev_cu_acc_power[MAX_CUS], prev_ptsc[MAX_CUS],
+	    jdelta[MAX_CUS];
+	u64 tdelta, avg_acc;
+	int cu, cu_num, ret;
+	signed long leftover;
+
+	/*
+	 * With the new x86 topology modelling, x86_max_cores is the
+	 * compute unit number.
+	 */
+	cu_num = boot_cpu_data.x86_max_cores;
+
+	ret = read_registers(data);
+	if (ret)
+		return 0;
+
+	for (cu = 0; cu < cu_num; cu++) {
+		prev_cu_acc_power[cu] = data->cu_acc_power[cu];
+		prev_ptsc[cu] = data->cpu_sw_pwr_ptsc[cu];
+	}
+
+	leftover = schedule_timeout_interruptible(msecs_to_jiffies(data->power_period));
+	if (leftover)
+		return 0;
+
+	ret = read_registers(data);
+	if (ret)
+		return 0;
+
+	for (cu = 0, avg_acc = 0; cu < cu_num; cu++) {
+		/* check if current compute unit is online */
+		if (data->cu_on[cu] == 0)
+			continue;
+
+		if (data->cu_acc_power[cu] < prev_cu_acc_power[cu]) {
+			jdelta[cu] = data->max_cu_acc_power + data->cu_acc_power[cu];
+			jdelta[cu] -= prev_cu_acc_power[cu];
+		} else {
+			jdelta[cu] = data->cu_acc_power[cu] - prev_cu_acc_power[cu];
+		}
+		tdelta = data->cpu_sw_pwr_ptsc[cu] - prev_ptsc[cu];
+		jdelta[cu] *= data->cpu_pwr_sample_ratio * 1000;
+		do_div(jdelta[cu], tdelta);
+
+		/* the unit is microWatt */
+		avg_acc += jdelta[cu];
+	}
+
+	return sprintf(buf, "%llu\n", (unsigned long long)avg_acc);
+}
+static DEVICE_ATTR(power1_average, S_IRUGO, acc_show_power, NULL);
+
+static ssize_t acc_show_power_period(struct device *dev,
+				     struct device_attribute *attr,
+				     char *buf)
+{
+	struct fam15h_power_data *data = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%lu\n", data->power_period);
+}
+
+static ssize_t acc_set_power_period(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t count)
+{
+	struct fam15h_power_data *data = dev_get_drvdata(dev);
+	unsigned long temp;
+	int ret;
+
+	ret = kstrtoul(buf, 10, &temp);
+	if (ret)
+		return ret;
+
+	if (temp > MAX_INTERVAL)
+		return -EINVAL;
+
+	/* the interval value should be greater than 0 */
+	if (temp <= 0)
+		return -EINVAL;
+
+	data->power_period = temp;
+
+	return count;
+}
+static DEVICE_ATTR(power1_average_interval, S_IRUGO | S_IWUSR,
+		   acc_show_power_period, acc_set_power_period);
+
 static int fam15h_power_init_attrs(struct pci_dev *pdev,
 				   struct fam15h_power_data *data)
 {
@@ -137,6 +316,10 @@ static int fam15h_power_init_attrs(struc
 	     (c->x86_model >= 0x60 && c->x86_model <= 0x7f)))
 		n += 1;
 
+	/* check if processor supports accumulated power */
+	if (boot_cpu_has(X86_FEATURE_ACC_POWER))
+		n += 2;
+
 	fam15h_power_attrs = devm_kcalloc(&pdev->dev, n,
 					  sizeof(*fam15h_power_attrs),
 					  GFP_KERNEL);
@@ -151,6 +334,11 @@ static int fam15h_power_init_attrs(struc
 	     (c->x86_model >= 0x60 && c->x86_model <= 0x7f)))
 		fam15h_power_attrs[n++] = &dev_attr_power1_input.attr;
 
+	if (boot_cpu_has(X86_FEATURE_ACC_POWER)) {
+		fam15h_power_attrs[n++] = &dev_attr_power1_average.attr;
+		fam15h_power_attrs[n++] = &dev_attr_power1_average_interval.attr;
+	}
+
 	data->group.attrs = fam15h_power_attrs;
 
 	return 0;
@@ -216,7 +404,7 @@ static int fam15h_power_resume(struct pc
 static int fam15h_power_init_data(struct pci_dev *f4,
 				  struct fam15h_power_data *data)
 {
-	u32 val, eax, ebx, ecx, edx;
+	u32 val;
 	u64 tmp;
 	int ret;
 
@@ -243,10 +431,9 @@ static int fam15h_power_init_data(struct
 	if (ret)
 		return ret;
 
-	cpuid(0x80000007, &eax, &ebx, &ecx, &edx);
 
 	/* CPUID Fn8000_0007:EDX[12] indicates to support accumulated power */
-	if (!(edx & BIT(12)))
+	if (!boot_cpu_has(X86_FEATURE_ACC_POWER))
 		return 0;
 
 	/*
@@ -254,7 +441,7 @@ static int fam15h_power_init_data(struct
 	 * sample period to the PTSC counter period by executing CPUID
 	 * Fn8000_0007:ECX
 	 */
-	data->cpu_pwr_sample_ratio = ecx;
+	data->cpu_pwr_sample_ratio = cpuid_ecx(0x80000007);
 
 	if (rdmsrl_safe(MSR_F15H_CU_MAX_PWR_ACCUMULATOR, &tmp)) {
 		pr_err("Failed to read max compute unit power accumulator MSR\n");
@@ -263,7 +450,15 @@ static int fam15h_power_init_data(struct
 
 	data->max_cu_acc_power = tmp;
 
-	return 0;
+	/*
+	 * Milliseconds are a reasonable interval for the measurement.
+	 * But it shouldn't set too long here, because several seconds
+	 * would cause the read function to hang. So set default
+	 * interval as 10 ms.
+	 */
+	data->power_period = 10;
+
+	return read_registers(data);
 }
 
 static int fam15h_power_probe(struct pci_dev *pdev,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwmon/it87.c linux-libre-4.7-gnu/drivers/hwmon/it87.c
--- linux-libre-4.6-gnu/drivers/hwmon/it87.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hwmon/it87.c	2016-07-24 15:23:50.000000000 -0400
@@ -13,6 +13,7 @@
  *  Supports: IT8603E  Super I/O chip w/LPC interface
  *            IT8620E  Super I/O chip w/LPC interface
  *            IT8623E  Super I/O chip w/LPC interface
+ *            IT8628E  Super I/O chip w/LPC interface
  *            IT8705F  Super I/O chip w/LPC interface
  *            IT8712F  Super I/O chip w/LPC interface
  *            IT8716F  Super I/O chip w/LPC interface
@@ -44,14 +45,11 @@
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/bitops.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -72,17 +70,18 @@
 
 enum chips { it87, it8712, it8716, it8718, it8720, it8721, it8728, it8732,
 	     it8771, it8772, it8781, it8782, it8783, it8786, it8790, it8603,
-	     it8620 };
+	     it8620, it8628 };
 
 static unsigned short force_id;
 module_param(force_id, ushort, 0);
 MODULE_PARM_DESC(force_id, "Override the detected device ID");
 
-static struct platform_device *pdev;
+static struct platform_device *it87_pdev[2];
+
+#define	REG_2E	0x2e	/* The register to read/write */
+#define	REG_4E	0x4e	/* Secondary register to read/write */
 
-#define	REG	0x2e	/* The register to read/write */
 #define	DEV	0x07	/* Register: Logical device select */
-#define	VAL	0x2f	/* The value to read/write */
 #define PME	0x04	/* The device with the fan registers in it */
 
 /* The device with the IT8718F/IT8720F VID value in it */
@@ -91,54 +90,55 @@ static struct platform_device *pdev;
 #define	DEVID	0x20	/* Register: Device ID */
 #define	DEVREV	0x22	/* Register: Device Revision */
 
-static inline int superio_inb(int reg)
+static inline int superio_inb(int ioreg, int reg)
 {
-	outb(reg, REG);
-	return inb(VAL);
+	outb(reg, ioreg);
+	return inb(ioreg + 1);
 }
 
-static inline void superio_outb(int reg, int val)
+static inline void superio_outb(int ioreg, int reg, int val)
 {
-	outb(reg, REG);
-	outb(val, VAL);
+	outb(reg, ioreg);
+	outb(val, ioreg + 1);
 }
 
-static int superio_inw(int reg)
+static int superio_inw(int ioreg, int reg)
 {
 	int val;
-	outb(reg++, REG);
-	val = inb(VAL) << 8;
-	outb(reg, REG);
-	val |= inb(VAL);
+
+	outb(reg++, ioreg);
+	val = inb(ioreg + 1) << 8;
+	outb(reg, ioreg);
+	val |= inb(ioreg + 1);
 	return val;
 }
 
-static inline void superio_select(int ldn)
+static inline void superio_select(int ioreg, int ldn)
 {
-	outb(DEV, REG);
-	outb(ldn, VAL);
+	outb(DEV, ioreg);
+	outb(ldn, ioreg + 1);
 }
 
-static inline int superio_enter(void)
+static inline int superio_enter(int ioreg)
 {
 	/*
-	 * Try to reserve REG and REG + 1 for exclusive access.
+	 * Try to reserve ioreg and ioreg + 1 for exclusive access.
 	 */
-	if (!request_muxed_region(REG, 2, DRVNAME))
+	if (!request_muxed_region(ioreg, 2, DRVNAME))
 		return -EBUSY;
 
-	outb(0x87, REG);
-	outb(0x01, REG);
-	outb(0x55, REG);
-	outb(0x55, REG);
+	outb(0x87, ioreg);
+	outb(0x01, ioreg);
+	outb(0x55, ioreg);
+	outb(ioreg == REG_4E ? 0xaa : 0x55, ioreg);
 	return 0;
 }
 
-static inline void superio_exit(void)
+static inline void superio_exit(int ioreg)
 {
-	outb(0x02, REG);
-	outb(0x02, VAL);
-	release_region(REG, 2);
+	outb(0x02, ioreg);
+	outb(0x02, ioreg + 1);
+	release_region(ioreg, 2);
 }
 
 /* Logical device 4 registers */
@@ -161,6 +161,7 @@ static inline void superio_exit(void)
 #define IT8603E_DEVID 0x8603
 #define IT8620E_DEVID 0x8620
 #define IT8623E_DEVID 0x8623
+#define IT8628E_DEVID 0x8628
 #define IT87_ACT_REG  0x30
 #define IT87_BASE_REG 0x60
 
@@ -168,6 +169,7 @@ static inline void superio_exit(void)
 #define IT87_SIO_GPIO1_REG	0x25
 #define IT87_SIO_GPIO2_REG	0x26
 #define IT87_SIO_GPIO3_REG	0x27
+#define IT87_SIO_GPIO4_REG	0x28
 #define IT87_SIO_GPIO5_REG	0x29
 #define IT87_SIO_PINX1_REG	0x2a	/* Pin selection */
 #define IT87_SIO_PINX2_REG	0x2c	/* Pin selection */
@@ -217,7 +219,12 @@ static bool fix_pwm_polarity;
 #define IT87_REG_FAN_DIV       0x0b
 #define IT87_REG_FAN_16BIT     0x0c
 
-/* Monitors: 9 voltage (0 to 7, battery), 3 temp (1 to 3), 3 fan (1 to 3) */
+/*
+ * Monitors:
+ * - up to 13 voltage (0 to 7, battery, avcc, 10 to 12)
+ * - up to 6 temp (1 to 6)
+ * - up to 6 fan (1 to 6)
+ */
 
 static const u8 IT87_REG_FAN[]         = { 0x0d, 0x0e, 0x0f, 0x80, 0x82, 0x4c };
 static const u8 IT87_REG_FAN_MIN[]     = { 0x10, 0x11, 0x12, 0x84, 0x86, 0x4e };
@@ -227,10 +234,12 @@ static const u8 IT87_REG_TEMP_OFFSET[] =
 
 #define IT87_REG_FAN_MAIN_CTRL 0x13
 #define IT87_REG_FAN_CTL       0x14
-#define IT87_REG_PWM(nr)       (0x15 + (nr))
-#define IT87_REG_PWM_DUTY(nr)  (0x63 + (nr) * 8)
+static const u8 IT87_REG_PWM[]         = { 0x15, 0x16, 0x17, 0x7f, 0xa7, 0xaf };
+static const u8 IT87_REG_PWM_DUTY[]    = { 0x63, 0x6b, 0x73, 0x7b, 0xa3, 0xab };
+
+static const u8 IT87_REG_VIN[]	= { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
+				    0x27, 0x28, 0x2f, 0x2c, 0x2d, 0x2e };
 
-#define IT87_REG_VIN(nr)       (0x20 + (nr))
 #define IT87_REG_TEMP(nr)      (0x29 + (nr))
 
 #define IT87_REG_VIN_MAX(nr)   (0x30 + (nr) * 2)
@@ -245,30 +254,48 @@ static const u8 IT87_REG_TEMP_OFFSET[] =
 
 #define IT87_REG_CHIPID        0x58
 
-#define IT87_REG_AUTO_TEMP(nr, i) (0x60 + (nr) * 8 + (i))
-#define IT87_REG_AUTO_PWM(nr, i)  (0x65 + (nr) * 8 + (i))
+static const u8 IT87_REG_AUTO_BASE[] = { 0x60, 0x68, 0x70, 0x78, 0xa0, 0xa8 };
+
+#define IT87_REG_AUTO_TEMP(nr, i) (IT87_REG_AUTO_BASE[nr] + (i))
+#define IT87_REG_AUTO_PWM(nr, i)  (IT87_REG_AUTO_BASE[nr] + 5 + (i))
+
+#define IT87_REG_TEMP456_ENABLE	0x77
+
+#define NUM_VIN			ARRAY_SIZE(IT87_REG_VIN)
+#define NUM_VIN_LIMIT		8
+#define NUM_TEMP		6
+#define NUM_TEMP_OFFSET		ARRAY_SIZE(IT87_REG_TEMP_OFFSET)
+#define NUM_TEMP_LIMIT		3
+#define NUM_FAN			ARRAY_SIZE(IT87_REG_FAN)
+#define NUM_FAN_DIV		3
+#define NUM_PWM			ARRAY_SIZE(IT87_REG_PWM)
+#define NUM_AUTO_PWM		ARRAY_SIZE(IT87_REG_PWM)
 
 struct it87_devices {
 	const char *name;
 	const char * const suffix;
-	u16 features;
+	u32 features;
 	u8 peci_mask;
 	u8 old_peci_mask;
 };
 
-#define FEAT_12MV_ADC		(1 << 0)
-#define FEAT_NEWER_AUTOPWM	(1 << 1)
-#define FEAT_OLD_AUTOPWM	(1 << 2)
-#define FEAT_16BIT_FANS		(1 << 3)
-#define FEAT_TEMP_OFFSET	(1 << 4)
-#define FEAT_TEMP_PECI		(1 << 5)
-#define FEAT_TEMP_OLD_PECI	(1 << 6)
-#define FEAT_FAN16_CONFIG	(1 << 7)	/* Need to enable 16-bit fans */
-#define FEAT_FIVE_FANS		(1 << 8)	/* Supports five fans */
-#define FEAT_VID		(1 << 9)	/* Set if chip supports VID */
-#define FEAT_IN7_INTERNAL	(1 << 10)	/* Set if in7 is internal */
-#define FEAT_SIX_FANS		(1 << 11)	/* Supports six fans */
-#define FEAT_10_9MV_ADC		(1 << 12)
+#define FEAT_12MV_ADC		BIT(0)
+#define FEAT_NEWER_AUTOPWM	BIT(1)
+#define FEAT_OLD_AUTOPWM	BIT(2)
+#define FEAT_16BIT_FANS		BIT(3)
+#define FEAT_TEMP_OFFSET	BIT(4)
+#define FEAT_TEMP_PECI		BIT(5)
+#define FEAT_TEMP_OLD_PECI	BIT(6)
+#define FEAT_FAN16_CONFIG	BIT(7)	/* Need to enable 16-bit fans */
+#define FEAT_FIVE_FANS		BIT(8)	/* Supports five fans */
+#define FEAT_VID		BIT(9)	/* Set if chip supports VID */
+#define FEAT_IN7_INTERNAL	BIT(10)	/* Set if in7 is internal */
+#define FEAT_SIX_FANS		BIT(11)	/* Supports six fans */
+#define FEAT_10_9MV_ADC		BIT(12)
+#define FEAT_AVCC3		BIT(13)	/* Chip supports in9/AVCC3 */
+#define FEAT_SIX_PWM		BIT(14)	/* Chip supports 6 pwm chn */
+#define FEAT_PWM_FREQ2		BIT(15)	/* Separate pwm freq 2 */
+#define FEAT_SIX_TEMP		BIT(16)	/* Up to 6 temp sensors */
 
 static const struct it87_devices it87_devices[] = {
 	[it87] = {
@@ -286,20 +313,22 @@ static const struct it87_devices it87_de
 		.name = "it8716",
 		.suffix = "F",
 		.features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_VID
-		  | FEAT_FAN16_CONFIG | FEAT_FIVE_FANS,
+		  | FEAT_FAN16_CONFIG | FEAT_FIVE_FANS | FEAT_PWM_FREQ2,
 	},
 	[it8718] = {
 		.name = "it8718",
 		.suffix = "F",
 		.features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_VID
-		  | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_FIVE_FANS,
+		  | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_FIVE_FANS
+		  | FEAT_PWM_FREQ2,
 		.old_peci_mask = 0x4,
 	},
 	[it8720] = {
 		.name = "it8720",
 		.suffix = "F",
 		.features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET | FEAT_VID
-		  | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_FIVE_FANS,
+		  | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_FIVE_FANS
+		  | FEAT_PWM_FREQ2,
 		.old_peci_mask = 0x4,
 	},
 	[it8721] = {
@@ -307,7 +336,8 @@ static const struct it87_devices it87_de
 		.suffix = "F",
 		.features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
 		  | FEAT_TEMP_OFFSET | FEAT_TEMP_OLD_PECI | FEAT_TEMP_PECI
-		  | FEAT_FAN16_CONFIG | FEAT_FIVE_FANS | FEAT_IN7_INTERNAL,
+		  | FEAT_FAN16_CONFIG | FEAT_FIVE_FANS | FEAT_IN7_INTERNAL
+		  | FEAT_PWM_FREQ2,
 		.peci_mask = 0x05,
 		.old_peci_mask = 0x02,	/* Actually reports PCH */
 	},
@@ -316,7 +346,7 @@ static const struct it87_devices it87_de
 		.suffix = "F",
 		.features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
 		  | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_FIVE_FANS
-		  | FEAT_IN7_INTERNAL,
+		  | FEAT_IN7_INTERNAL | FEAT_PWM_FREQ2,
 		.peci_mask = 0x07,
 	},
 	[it8732] = {
@@ -332,7 +362,8 @@ static const struct it87_devices it87_de
 		.name = "it8771",
 		.suffix = "E",
 		.features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
-		  | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL,
+		  | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL
+		  | FEAT_PWM_FREQ2,
 				/* PECI: guesswork */
 				/* 12mV ADC (OHM) */
 				/* 16 bit fans (OHM) */
@@ -343,7 +374,8 @@ static const struct it87_devices it87_de
 		.name = "it8772",
 		.suffix = "E",
 		.features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
-		  | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL,
+		  | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL
+		  | FEAT_PWM_FREQ2,
 				/* PECI (coreboot) */
 				/* 12mV ADC (HWSensors4, OHM) */
 				/* 16 bit fans (HWSensors4, OHM) */
@@ -354,42 +386,45 @@ static const struct it87_devices it87_de
 		.name = "it8781",
 		.suffix = "F",
 		.features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET
-		  | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG,
+		  | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_PWM_FREQ2,
 		.old_peci_mask = 0x4,
 	},
 	[it8782] = {
 		.name = "it8782",
 		.suffix = "F",
 		.features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET
-		  | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG,
+		  | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_PWM_FREQ2,
 		.old_peci_mask = 0x4,
 	},
 	[it8783] = {
 		.name = "it8783",
 		.suffix = "E/F",
 		.features = FEAT_16BIT_FANS | FEAT_TEMP_OFFSET
-		  | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG,
+		  | FEAT_TEMP_OLD_PECI | FEAT_FAN16_CONFIG | FEAT_PWM_FREQ2,
 		.old_peci_mask = 0x4,
 	},
 	[it8786] = {
 		.name = "it8786",
 		.suffix = "E",
 		.features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
-		  | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL,
+		  | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL
+		  | FEAT_PWM_FREQ2,
 		.peci_mask = 0x07,
 	},
 	[it8790] = {
 		.name = "it8790",
 		.suffix = "E",
 		.features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
-		  | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL,
+		  | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL
+		  | FEAT_PWM_FREQ2,
 		.peci_mask = 0x07,
 	},
 	[it8603] = {
 		.name = "it8603",
 		.suffix = "E",
 		.features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
-		  | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL,
+		  | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_IN7_INTERNAL
+		  | FEAT_AVCC3 | FEAT_PWM_FREQ2,
 		.peci_mask = 0x07,
 	},
 	[it8620] = {
@@ -397,7 +432,17 @@ static const struct it87_devices it87_de
 		.suffix = "E",
 		.features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
 		  | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_SIX_FANS
-		  | FEAT_IN7_INTERNAL,
+		  | FEAT_IN7_INTERNAL | FEAT_SIX_PWM | FEAT_PWM_FREQ2
+		  | FEAT_SIX_TEMP,
+		.peci_mask = 0x07,
+	},
+	[it8628] = {
+		.name = "it8628",
+		.suffix = "E",
+		.features = FEAT_NEWER_AUTOPWM | FEAT_12MV_ADC | FEAT_16BIT_FANS
+		  | FEAT_TEMP_OFFSET | FEAT_TEMP_PECI | FEAT_SIX_FANS
+		  | FEAT_IN7_INTERNAL | FEAT_SIX_PWM | FEAT_PWM_FREQ2
+		  | FEAT_SIX_TEMP,
 		.peci_mask = 0x07,
 	},
 };
@@ -409,16 +454,20 @@ static const struct it87_devices it87_de
 #define has_old_autopwm(data)	((data)->features & FEAT_OLD_AUTOPWM)
 #define has_temp_offset(data)	((data)->features & FEAT_TEMP_OFFSET)
 #define has_temp_peci(data, nr)	(((data)->features & FEAT_TEMP_PECI) && \
-				 ((data)->peci_mask & (1 << nr)))
+				 ((data)->peci_mask & BIT(nr)))
 #define has_temp_old_peci(data, nr) \
 				(((data)->features & FEAT_TEMP_OLD_PECI) && \
-				 ((data)->old_peci_mask & (1 << nr)))
+				 ((data)->old_peci_mask & BIT(nr)))
 #define has_fan16_config(data)	((data)->features & FEAT_FAN16_CONFIG)
 #define has_five_fans(data)	((data)->features & (FEAT_FIVE_FANS | \
 						     FEAT_SIX_FANS))
 #define has_vid(data)		((data)->features & FEAT_VID)
 #define has_in7_internal(data)	((data)->features & FEAT_IN7_INTERNAL)
 #define has_six_fans(data)	((data)->features & FEAT_SIX_FANS)
+#define has_avcc3(data)		((data)->features & FEAT_AVCC3)
+#define has_six_pwm(data)	((data)->features & FEAT_SIX_PWM)
+#define has_pwm_freq2(data)	((data)->features & FEAT_PWM_FREQ2)
+#define has_six_temp(data)	((data)->features & FEAT_SIX_TEMP)
 
 struct it87_sio_data {
 	enum chips type;
@@ -440,7 +489,7 @@ struct it87_sio_data {
  * The structure is dynamically allocated.
  */
 struct it87_data {
-	struct device *hwmon_dev;
+	const struct attribute_group *groups[7];
 	enum chips type;
 	u16 features;
 	u8 peci_mask;
@@ -453,17 +502,21 @@ struct it87_data {
 	unsigned long last_updated;	/* In jiffies */
 
 	u16 in_scaled;		/* Internal voltage sensors are scaled */
-	u8 in[10][3];		/* [nr][0]=in, [1]=min, [2]=max */
+	u16 in_internal;	/* Bitfield, internal sensors (for labels) */
+	u16 has_in;		/* Bitfield, voltage sensors enabled */
+	u8 in[NUM_VIN][3];		/* [nr][0]=in, [1]=min, [2]=max */
 	u8 has_fan;		/* Bitfield, fans enabled */
-	u16 fan[6][2];		/* Register values, [nr][0]=fan, [1]=min */
+	u16 fan[NUM_FAN][2];	/* Register values, [nr][0]=fan, [1]=min */
 	u8 has_temp;		/* Bitfield, temp sensors enabled */
-	s8 temp[3][4];		/* [nr][0]=temp, [1]=min, [2]=max, [3]=offset */
+	s8 temp[NUM_TEMP][4];	/* [nr][0]=temp, [1]=min, [2]=max, [3]=offset */
 	u8 sensor;		/* Register value (IT87_REG_TEMP_ENABLE) */
 	u8 extra;		/* Register value (IT87_REG_TEMP_EXTRA) */
-	u8 fan_div[3];		/* Register encoding, shifted right */
+	u8 fan_div[NUM_FAN_DIV];/* Register encoding, shifted right */
+	bool has_vid;		/* True if VID supported */
 	u8 vid;			/* Register encoding, combined */
 	u8 vrm;
 	u32 alarms;		/* Register encoding, combined */
+	bool has_beep;		/* true if beep supported */
 	u8 beeps;		/* Register encoding */
 	u8 fan_main_ctrl;	/* Register value */
 	u8 fan_ctl;		/* Register value */
@@ -478,13 +531,14 @@ struct it87_data {
 	 * is no longer needed, but it is still done to keep the driver
 	 * simple.
 	 */
-	u8 pwm_ctrl[3];		/* Register value */
-	u8 pwm_duty[3];		/* Manual PWM value set by user */
-	u8 pwm_temp_map[3];	/* PWM to temp. chan. mapping (bits 1-0) */
+	u8 has_pwm;		/* Bitfield, pwm control enabled */
+	u8 pwm_ctrl[NUM_PWM];	/* Register value */
+	u8 pwm_duty[NUM_PWM];	/* Manual PWM value set by user */
+	u8 pwm_temp_map[NUM_PWM];/* PWM to temp. chan. mapping (bits 1-0) */
 
 	/* Automatic fan speed control registers */
-	u8 auto_pwm[3][4];	/* [nr][3] is hard-coded */
-	s8 auto_temp[3][5];	/* [nr][0] is point1_temp_hyst */
+	u8 auto_pwm[NUM_AUTO_PWM][4];	/* [nr][3] is hard-coded */
+	s8 auto_temp[NUM_AUTO_PWM][5];	/* [nr][0] is point1_temp_hyst */
 };
 
 static int adc_lsb(const struct it87_data *data, int nr)
@@ -497,7 +551,7 @@ static int adc_lsb(const struct it87_dat
 		lsb = 109;
 	else
 		lsb = 160;
-	if (data->in_scaled & (1 << nr))
+	if (data->in_scaled & BIT(nr))
 		lsb <<= 1;
 	return lsb;
 }
@@ -554,15 +608,16 @@ static int pwm_from_reg(const struct it8
 		return (reg & 0x7f) << 1;
 }
 
-
 static int DIV_TO_REG(int val)
 {
 	int answer = 0;
+
 	while (answer < 7 && (val >>= 1))
 		answer++;
 	return answer;
 }
-#define DIV_FROM_REG(val) (1 << (val))
+
+#define DIV_FROM_REG(val) BIT(val)
 
 /*
  * PWM base frequencies. The frequency has to be divided by either 128 or 256,
@@ -585,32 +640,204 @@ static const unsigned int pwm_freq[8] =
 	750000,
 };
 
-static int it87_probe(struct platform_device *pdev);
-static int it87_remove(struct platform_device *pdev);
+/*
+ * Must be called with data->update_lock held, except during initialization.
+ * We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks,
+ * would slow down the IT87 access and should not be necessary.
+ */
+static int it87_read_value(struct it87_data *data, u8 reg)
+{
+	outb_p(reg, data->addr + IT87_ADDR_REG_OFFSET);
+	return inb_p(data->addr + IT87_DATA_REG_OFFSET);
+}
 
-static int it87_read_value(struct it87_data *data, u8 reg);
-static void it87_write_value(struct it87_data *data, u8 reg, u8 value);
-static struct it87_data *it87_update_device(struct device *dev);
-static int it87_check_pwm(struct device *dev);
-static void it87_init_device(struct platform_device *pdev);
+/*
+ * Must be called with data->update_lock held, except during initialization.
+ * We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks,
+ * would slow down the IT87 access and should not be necessary.
+ */
+static void it87_write_value(struct it87_data *data, u8 reg, u8 value)
+{
+	outb_p(reg, data->addr + IT87_ADDR_REG_OFFSET);
+	outb_p(value, data->addr + IT87_DATA_REG_OFFSET);
+}
 
+static void it87_update_pwm_ctrl(struct it87_data *data, int nr)
+{
+	data->pwm_ctrl[nr] = it87_read_value(data, IT87_REG_PWM[nr]);
+	if (has_newer_autopwm(data)) {
+		data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03;
+		data->pwm_duty[nr] = it87_read_value(data,
+						     IT87_REG_PWM_DUTY[nr]);
+	} else {
+		if (data->pwm_ctrl[nr] & 0x80)	/* Automatic mode */
+			data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03;
+		else				/* Manual mode */
+			data->pwm_duty[nr] = data->pwm_ctrl[nr] & 0x7f;
+	}
 
-static struct platform_driver it87_driver = {
-	.driver = {
-		.name	= DRVNAME,
-	},
-	.probe	= it87_probe,
-	.remove	= it87_remove,
-};
+	if (has_old_autopwm(data)) {
+		int i;
+
+		for (i = 0; i < 5 ; i++)
+			data->auto_temp[nr][i] = it87_read_value(data,
+						IT87_REG_AUTO_TEMP(nr, i));
+		for (i = 0; i < 3 ; i++)
+			data->auto_pwm[nr][i] = it87_read_value(data,
+						IT87_REG_AUTO_PWM(nr, i));
+	} else if (has_newer_autopwm(data)) {
+		int i;
+
+		/*
+		 * 0: temperature hysteresis (base + 5)
+		 * 1: fan off temperature (base + 0)
+		 * 2: fan start temperature (base + 1)
+		 * 3: fan max temperature (base + 2)
+		 */
+		data->auto_temp[nr][0] =
+			it87_read_value(data, IT87_REG_AUTO_TEMP(nr, 5));
+
+		for (i = 0; i < 3 ; i++)
+			data->auto_temp[nr][i + 1] =
+				it87_read_value(data,
+						IT87_REG_AUTO_TEMP(nr, i));
+		/*
+		 * 0: start pwm value (base + 3)
+		 * 1: pwm slope (base + 4, 1/8th pwm)
+		 */
+		data->auto_pwm[nr][0] =
+			it87_read_value(data, IT87_REG_AUTO_TEMP(nr, 3));
+		data->auto_pwm[nr][1] =
+			it87_read_value(data, IT87_REG_AUTO_TEMP(nr, 4));
+	}
+}
+
+static struct it87_data *it87_update_device(struct device *dev)
+{
+	struct it87_data *data = dev_get_drvdata(dev);
+	int i;
+
+	mutex_lock(&data->update_lock);
+
+	if (time_after(jiffies, data->last_updated + HZ + HZ / 2) ||
+	    !data->valid) {
+		if (update_vbat) {
+			/*
+			 * Cleared after each update, so reenable.  Value
+			 * returned by this read will be previous value
+			 */
+			it87_write_value(data, IT87_REG_CONFIG,
+				it87_read_value(data, IT87_REG_CONFIG) | 0x40);
+		}
+		for (i = 0; i < NUM_VIN; i++) {
+			if (!(data->has_in & BIT(i)))
+				continue;
+
+			data->in[i][0] =
+				it87_read_value(data, IT87_REG_VIN[i]);
+
+			/* VBAT and AVCC don't have limit registers */
+			if (i >= NUM_VIN_LIMIT)
+				continue;
+
+			data->in[i][1] =
+				it87_read_value(data, IT87_REG_VIN_MIN(i));
+			data->in[i][2] =
+				it87_read_value(data, IT87_REG_VIN_MAX(i));
+		}
+
+		for (i = 0; i < NUM_FAN; i++) {
+			/* Skip disabled fans */
+			if (!(data->has_fan & BIT(i)))
+				continue;
+
+			data->fan[i][1] =
+				it87_read_value(data, IT87_REG_FAN_MIN[i]);
+			data->fan[i][0] = it87_read_value(data,
+				       IT87_REG_FAN[i]);
+			/* Add high byte if in 16-bit mode */
+			if (has_16bit_fans(data)) {
+				data->fan[i][0] |= it87_read_value(data,
+						IT87_REG_FANX[i]) << 8;
+				data->fan[i][1] |= it87_read_value(data,
+						IT87_REG_FANX_MIN[i]) << 8;
+			}
+		}
+		for (i = 0; i < NUM_TEMP; i++) {
+			if (!(data->has_temp & BIT(i)))
+				continue;
+			data->temp[i][0] =
+				it87_read_value(data, IT87_REG_TEMP(i));
+
+			if (has_temp_offset(data) && i < NUM_TEMP_OFFSET)
+				data->temp[i][3] =
+				  it87_read_value(data,
+						  IT87_REG_TEMP_OFFSET[i]);
+
+			if (i >= NUM_TEMP_LIMIT)
+				continue;
+
+			data->temp[i][1] =
+				it87_read_value(data, IT87_REG_TEMP_LOW(i));
+			data->temp[i][2] =
+				it87_read_value(data, IT87_REG_TEMP_HIGH(i));
+		}
+
+		/* Newer chips don't have clock dividers */
+		if ((data->has_fan & 0x07) && !has_16bit_fans(data)) {
+			i = it87_read_value(data, IT87_REG_FAN_DIV);
+			data->fan_div[0] = i & 0x07;
+			data->fan_div[1] = (i >> 3) & 0x07;
+			data->fan_div[2] = (i & 0x40) ? 3 : 1;
+		}
+
+		data->alarms =
+			it87_read_value(data, IT87_REG_ALARM1) |
+			(it87_read_value(data, IT87_REG_ALARM2) << 8) |
+			(it87_read_value(data, IT87_REG_ALARM3) << 16);
+		data->beeps = it87_read_value(data, IT87_REG_BEEP_ENABLE);
+
+		data->fan_main_ctrl = it87_read_value(data,
+				IT87_REG_FAN_MAIN_CTRL);
+		data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL);
+		for (i = 0; i < NUM_PWM; i++) {
+			if (!(data->has_pwm & BIT(i)))
+				continue;
+			it87_update_pwm_ctrl(data, i);
+		}
+
+		data->sensor = it87_read_value(data, IT87_REG_TEMP_ENABLE);
+		data->extra = it87_read_value(data, IT87_REG_TEMP_EXTRA);
+		/*
+		 * The IT8705F does not have VID capability.
+		 * The IT8718F and later don't use IT87_REG_VID for the
+		 * same purpose.
+		 */
+		if (data->type == it8712 || data->type == it8716) {
+			data->vid = it87_read_value(data, IT87_REG_VID);
+			/*
+			 * The older IT8712F revisions had only 5 VID pins,
+			 * but we assume it is always safe to read 6 bits.
+			 */
+			data->vid &= 0x3f;
+		}
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+
+	mutex_unlock(&data->update_lock);
+
+	return data;
+}
 
 static ssize_t show_in(struct device *dev, struct device_attribute *attr,
 		       char *buf)
 {
 	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
-	int nr = sattr->nr;
+	struct it87_data *data = it87_update_device(dev);
 	int index = sattr->index;
+	int nr = sattr->nr;
 
-	struct it87_data *data = it87_update_device(dev);
 	return sprintf(buf, "%d\n", in_from_reg(data, nr, data->in[nr][index]));
 }
 
@@ -618,10 +845,9 @@ static ssize_t set_in(struct device *dev
 		      const char *buf, size_t count)
 {
 	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
-	int nr = sattr->nr;
-	int index = sattr->index;
-
 	struct it87_data *data = dev_get_drvdata(dev);
+	int index = sattr->index;
+	int nr = sattr->nr;
 	unsigned long val;
 
 	if (kstrtoul(buf, 10, &val) < 0)
@@ -687,8 +913,11 @@ static SENSOR_DEVICE_ATTR_2(in7_max, S_I
 
 static SENSOR_DEVICE_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 8, 0);
 static SENSOR_DEVICE_ATTR_2(in9_input, S_IRUGO, show_in, NULL, 9, 0);
+static SENSOR_DEVICE_ATTR_2(in10_input, S_IRUGO, show_in, NULL, 10, 0);
+static SENSOR_DEVICE_ATTR_2(in11_input, S_IRUGO, show_in, NULL, 11, 0);
+static SENSOR_DEVICE_ATTR_2(in12_input, S_IRUGO, show_in, NULL, 12, 0);
 
-/* 3 temperatures */
+/* Up to 6 temperatures */
 static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
 			 char *buf)
 {
@@ -761,6 +990,9 @@ static SENSOR_DEVICE_ATTR_2(temp3_max, S
 			    2, 2);
 static SENSOR_DEVICE_ATTR_2(temp3_offset, S_IRUGO | S_IWUSR, show_temp,
 			    set_temp, 2, 3);
+static SENSOR_DEVICE_ATTR_2(temp4_input, S_IRUGO, show_temp, NULL, 3, 0);
+static SENSOR_DEVICE_ATTR_2(temp5_input, S_IRUGO, show_temp, NULL, 4, 0);
+static SENSOR_DEVICE_ATTR_2(temp6_input, S_IRUGO, show_temp, NULL, 5, 0);
 
 static ssize_t show_temp_type(struct device *dev, struct device_attribute *attr,
 			      char *buf)
@@ -771,8 +1003,8 @@ static ssize_t show_temp_type(struct dev
 	u8 reg = data->sensor;	    /* In case value is updated while used */
 	u8 extra = data->extra;
 
-	if ((has_temp_peci(data, nr) && (reg >> 6 == nr + 1))
-	    || (has_temp_old_peci(data, nr) && (extra & 0x80)))
+	if ((has_temp_peci(data, nr) && (reg >> 6 == nr + 1)) ||
+	    (has_temp_old_peci(data, nr) && (extra & 0x80)))
 		return sprintf(buf, "6\n");  /* Intel PECI */
 	if (reg & (1 << nr))
 		return sprintf(buf, "3\n");  /* thermal diode */
@@ -837,18 +1069,19 @@ static SENSOR_DEVICE_ATTR(temp2_type, S_
 static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO | S_IWUSR, show_temp_type,
 			  set_temp_type, 2);
 
-/* 3 Fans */
+/* 6 Fans */
 
 static int pwm_mode(const struct it87_data *data, int nr)
 {
-	int ctrl = data->fan_main_ctrl & (1 << nr);
+	if (data->type != it8603 && nr < 3 && !(data->fan_main_ctrl & BIT(nr)))
+		return 0;				/* Full speed */
+	if (data->pwm_ctrl[nr] & 0x80)
+		return 2;				/* Automatic mode */
+	if ((data->type == it8603 || nr >= 3) &&
+	    data->pwm_duty[nr] == pwm_to_reg(data, 0xff))
+		return 0;			/* Full speed */
 
-	if (ctrl == 0 && data->type != it8603)		/* Full speed */
-		return 0;
-	if (data->pwm_ctrl[nr] & 0x80)			/* Automatic mode */
-		return 2;
-	else						/* Manual mode */
-		return 1;
+	return 1;				/* Manual mode */
 }
 
 static ssize_t show_fan(struct device *dev, struct device_attribute *attr,
@@ -868,39 +1101,49 @@ static ssize_t show_fan(struct device *d
 }
 
 static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr,
-		char *buf)
+			    char *buf)
 {
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	struct it87_data *data = it87_update_device(dev);
 	int nr = sensor_attr->index;
 
-	struct it87_data *data = it87_update_device(dev);
-	return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]));
+	return sprintf(buf, "%lu\n", DIV_FROM_REG(data->fan_div[nr]));
 }
+
 static ssize_t show_pwm_enable(struct device *dev,
-		struct device_attribute *attr, char *buf)
+			       struct device_attribute *attr, char *buf)
 {
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	struct it87_data *data = it87_update_device(dev);
 	int nr = sensor_attr->index;
 
-	struct it87_data *data = it87_update_device(dev);
 	return sprintf(buf, "%d\n", pwm_mode(data, nr));
 }
+
 static ssize_t show_pwm(struct device *dev, struct device_attribute *attr,
-		char *buf)
+			char *buf)
 {
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	struct it87_data *data = it87_update_device(dev);
 	int nr = sensor_attr->index;
 
-	struct it87_data *data = it87_update_device(dev);
 	return sprintf(buf, "%d\n",
 		       pwm_from_reg(data, data->pwm_duty[nr]));
 }
+
 static ssize_t show_pwm_freq(struct device *dev, struct device_attribute *attr,
-		char *buf)
+			     char *buf)
 {
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	struct it87_data *data = it87_update_device(dev);
-	int index = (data->fan_ctl >> 4) & 0x07;
+	int nr = sensor_attr->index;
 	unsigned int freq;
+	int index;
+
+	if (has_pwm_freq2(data) && nr == 1)
+		index = (data->extra >> 4) & 0x07;
+	else
+		index = (data->fan_ctl >> 4) & 0x07;
 
 	freq = pwm_freq[index] / (has_newer_autopwm(data) ? 256 : 128);
 
@@ -953,12 +1196,11 @@ static ssize_t set_fan(struct device *de
 }
 
 static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
-		const char *buf, size_t count)
+			   const char *buf, size_t count)
 {
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
-	int nr = sensor_attr->index;
-
 	struct it87_data *data = dev_get_drvdata(dev);
+	int nr = sensor_attr->index;
 	unsigned long val;
 	int min;
 	u8 old;
@@ -1013,6 +1255,11 @@ static int check_trip_points(struct devi
 			if (data->auto_pwm[nr][i] > data->auto_pwm[nr][i + 1])
 				err = -EINVAL;
 		}
+	} else if (has_newer_autopwm(data)) {
+		for (i = 1; i < 3; i++) {
+			if (data->auto_temp[nr][i] > data->auto_temp[nr][i + 1])
+				err = -EINVAL;
+		}
 	}
 
 	if (err) {
@@ -1023,13 +1270,12 @@ static int check_trip_points(struct devi
 	return err;
 }
 
-static ssize_t set_pwm_enable(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr,
+			      const char *buf, size_t count)
 {
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
-	int nr = sensor_attr->index;
-
 	struct it87_data *data = dev_get_drvdata(dev);
+	int nr = sensor_attr->index;
 	long val;
 
 	if (kstrtol(buf, 10, &val) < 0 || val < 0 || val > 2)
@@ -1041,21 +1287,30 @@ static ssize_t set_pwm_enable(struct dev
 			return -EINVAL;
 	}
 
-	/* IT8603E does not have on/off mode */
-	if (val == 0 && data->type == it8603)
-		return -EINVAL;
-
 	mutex_lock(&data->update_lock);
 
 	if (val == 0) {
-		int tmp;
-		/* make sure the fan is on when in on/off mode */
-		tmp = it87_read_value(data, IT87_REG_FAN_CTL);
-		it87_write_value(data, IT87_REG_FAN_CTL, tmp | (1 << nr));
-		/* set on/off mode */
-		data->fan_main_ctrl &= ~(1 << nr);
-		it87_write_value(data, IT87_REG_FAN_MAIN_CTRL,
-				 data->fan_main_ctrl);
+		if (nr < 3 && data->type != it8603) {
+			int tmp;
+			/* make sure the fan is on when in on/off mode */
+			tmp = it87_read_value(data, IT87_REG_FAN_CTL);
+			it87_write_value(data, IT87_REG_FAN_CTL, tmp | BIT(nr));
+			/* set on/off mode */
+			data->fan_main_ctrl &= ~BIT(nr);
+			it87_write_value(data, IT87_REG_FAN_MAIN_CTRL,
+					 data->fan_main_ctrl);
+		} else {
+			/* No on/off mode, set maximum pwm value */
+			data->pwm_duty[nr] = pwm_to_reg(data, 0xff);
+			it87_write_value(data, IT87_REG_PWM_DUTY[nr],
+					 data->pwm_duty[nr]);
+			/* and set manual mode */
+			data->pwm_ctrl[nr] = has_newer_autopwm(data) ?
+					     data->pwm_temp_map[nr] :
+					     data->pwm_duty[nr];
+			it87_write_value(data, IT87_REG_PWM[nr],
+					 data->pwm_ctrl[nr]);
+		}
 	} else {
 		if (val == 1)				/* Manual mode */
 			data->pwm_ctrl[nr] = has_newer_autopwm(data) ?
@@ -1063,11 +1318,11 @@ static ssize_t set_pwm_enable(struct dev
 					     data->pwm_duty[nr];
 		else					/* Automatic mode */
 			data->pwm_ctrl[nr] = 0x80 | data->pwm_temp_map[nr];
-		it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]);
+		it87_write_value(data, IT87_REG_PWM[nr], data->pwm_ctrl[nr]);
 
-		if (data->type != it8603) {
+		if (data->type != it8603 && nr < 3) {
 			/* set SmartGuardian mode */
-			data->fan_main_ctrl |= (1 << nr);
+			data->fan_main_ctrl |= BIT(nr);
 			it87_write_value(data, IT87_REG_FAN_MAIN_CTRL,
 					 data->fan_main_ctrl);
 		}
@@ -1076,13 +1331,13 @@ static ssize_t set_pwm_enable(struct dev
 	mutex_unlock(&data->update_lock);
 	return count;
 }
+
 static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
-		const char *buf, size_t count)
+		       const char *buf, size_t count)
 {
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
-	int nr = sensor_attr->index;
-
 	struct it87_data *data = dev_get_drvdata(dev);
+	int nr = sensor_attr->index;
 	long val;
 
 	if (kstrtol(buf, 10, &val) < 0 || val < 0 || val > 255)
@@ -1099,7 +1354,7 @@ static ssize_t set_pwm(struct device *de
 			return -EBUSY;
 		}
 		data->pwm_duty[nr] = pwm_to_reg(data, val);
-		it87_write_value(data, IT87_REG_PWM_DUTY(nr),
+		it87_write_value(data, IT87_REG_PWM_DUTY[nr],
 				 data->pwm_duty[nr]);
 	} else {
 		data->pwm_duty[nr] = pwm_to_reg(data, val);
@@ -1109,17 +1364,20 @@ static ssize_t set_pwm(struct device *de
 		 */
 		if (!(data->pwm_ctrl[nr] & 0x80)) {
 			data->pwm_ctrl[nr] = data->pwm_duty[nr];
-			it87_write_value(data, IT87_REG_PWM(nr),
+			it87_write_value(data, IT87_REG_PWM[nr],
 					 data->pwm_ctrl[nr]);
 		}
 	}
 	mutex_unlock(&data->update_lock);
 	return count;
 }
-static ssize_t set_pwm_freq(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t count)
+
+static ssize_t set_pwm_freq(struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t count)
 {
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	struct it87_data *data = dev_get_drvdata(dev);
+	int nr = sensor_attr->index;
 	unsigned long val;
 	int i;
 
@@ -1131,63 +1389,66 @@ static ssize_t set_pwm_freq(struct devic
 
 	/* Search for the nearest available frequency */
 	for (i = 0; i < 7; i++) {
-		if (val > (pwm_freq[i] + pwm_freq[i+1]) / 2)
+		if (val > (pwm_freq[i] + pwm_freq[i + 1]) / 2)
 			break;
 	}
 
 	mutex_lock(&data->update_lock);
-	data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL) & 0x8f;
-	data->fan_ctl |= i << 4;
-	it87_write_value(data, IT87_REG_FAN_CTL, data->fan_ctl);
+	if (nr == 0) {
+		data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL) & 0x8f;
+		data->fan_ctl |= i << 4;
+		it87_write_value(data, IT87_REG_FAN_CTL, data->fan_ctl);
+	} else {
+		data->extra = it87_read_value(data, IT87_REG_TEMP_EXTRA) & 0x8f;
+		data->extra |= i << 4;
+		it87_write_value(data, IT87_REG_TEMP_EXTRA, data->extra);
+	}
 	mutex_unlock(&data->update_lock);
 
 	return count;
 }
+
 static ssize_t show_pwm_temp_map(struct device *dev,
-		struct device_attribute *attr, char *buf)
+				 struct device_attribute *attr, char *buf)
 {
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
-	int nr = sensor_attr->index;
-
 	struct it87_data *data = it87_update_device(dev);
+	int nr = sensor_attr->index;
 	int map;
 
-	if (data->pwm_temp_map[nr] < 3)
-		map = 1 << data->pwm_temp_map[nr];
-	else
-		map = 0;			/* Should never happen */
-	return sprintf(buf, "%d\n", map);
+	map = data->pwm_temp_map[nr];
+	if (map >= 3)
+		map = 0;	/* Should never happen */
+	if (nr >= 3)		/* pwm channels 3..6 map to temp4..6 */
+		map += 3;
+
+	return sprintf(buf, "%d\n", (int)BIT(map));
 }
+
 static ssize_t set_pwm_temp_map(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t count)
+				struct device_attribute *attr, const char *buf,
+				size_t count)
 {
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
-	int nr = sensor_attr->index;
-
 	struct it87_data *data = dev_get_drvdata(dev);
+	int nr = sensor_attr->index;
 	long val;
 	u8 reg;
 
-	/*
-	 * This check can go away if we ever support automatic fan speed
-	 * control on newer chips.
-	 */
-	if (!has_old_autopwm(data)) {
-		dev_notice(dev, "Mapping change disabled for safety reasons\n");
-		return -EINVAL;
-	}
-
 	if (kstrtol(buf, 10, &val) < 0)
 		return -EINVAL;
 
+	if (nr >= 3)
+		val -= 3;
+
 	switch (val) {
-	case (1 << 0):
+	case BIT(0):
 		reg = 0x00;
 		break;
-	case (1 << 1):
+	case BIT(1):
 		reg = 0x01;
 		break;
-	case (1 << 2):
+	case BIT(2):
 		reg = 0x02;
 		break;
 	default:
@@ -1202,14 +1463,14 @@ static ssize_t set_pwm_temp_map(struct d
 	 */
 	if (data->pwm_ctrl[nr] & 0x80) {
 		data->pwm_ctrl[nr] = 0x80 | data->pwm_temp_map[nr];
-		it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]);
+		it87_write_value(data, IT87_REG_PWM[nr], data->pwm_ctrl[nr]);
 	}
 	mutex_unlock(&data->update_lock);
 	return count;
 }
 
-static ssize_t show_auto_pwm(struct device *dev,
-		struct device_attribute *attr, char *buf)
+static ssize_t show_auto_pwm(struct device *dev, struct device_attribute *attr,
+			     char *buf)
 {
 	struct it87_data *data = it87_update_device(dev);
 	struct sensor_device_attribute_2 *sensor_attr =
@@ -1221,14 +1482,15 @@ static ssize_t show_auto_pwm(struct devi
 		       pwm_from_reg(data, data->auto_pwm[nr][point]));
 }
 
-static ssize_t set_auto_pwm(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t set_auto_pwm(struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t count)
 {
 	struct it87_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute_2 *sensor_attr =
 			to_sensor_dev_attr_2(attr);
 	int nr = sensor_attr->nr;
 	int point = sensor_attr->index;
+	int regaddr;
 	long val;
 
 	if (kstrtol(buf, 10, &val) < 0 || val < 0 || val > 255)
@@ -1236,26 +1498,65 @@ static ssize_t set_auto_pwm(struct devic
 
 	mutex_lock(&data->update_lock);
 	data->auto_pwm[nr][point] = pwm_to_reg(data, val);
-	it87_write_value(data, IT87_REG_AUTO_PWM(nr, point),
-			 data->auto_pwm[nr][point]);
+	if (has_newer_autopwm(data))
+		regaddr = IT87_REG_AUTO_TEMP(nr, 3);
+	else
+		regaddr = IT87_REG_AUTO_PWM(nr, point);
+	it87_write_value(data, regaddr, data->auto_pwm[nr][point]);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
 
-static ssize_t show_auto_temp(struct device *dev,
-		struct device_attribute *attr, char *buf)
+static ssize_t show_auto_pwm_slope(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct it87_data *data = it87_update_device(dev);
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+
+	return sprintf(buf, "%d\n", data->auto_pwm[nr][1] & 0x7f);
+}
+
+static ssize_t set_auto_pwm_slope(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t count)
+{
+	struct it87_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	unsigned long val;
+
+	if (kstrtoul(buf, 10, &val) < 0 || val > 127)
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+	data->auto_pwm[nr][1] = (data->auto_pwm[nr][1] & 0x80) | val;
+	it87_write_value(data, IT87_REG_AUTO_TEMP(nr, 4),
+			 data->auto_pwm[nr][1]);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t show_auto_temp(struct device *dev, struct device_attribute *attr,
+			      char *buf)
 {
 	struct it87_data *data = it87_update_device(dev);
 	struct sensor_device_attribute_2 *sensor_attr =
 			to_sensor_dev_attr_2(attr);
 	int nr = sensor_attr->nr;
 	int point = sensor_attr->index;
+	int reg;
 
-	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->auto_temp[nr][point]));
+	if (has_old_autopwm(data) || point)
+		reg = data->auto_temp[nr][point];
+	else
+		reg = data->auto_temp[nr][1] - (data->auto_temp[nr][0] & 0x1f);
+
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(reg));
 }
 
-static ssize_t set_auto_temp(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t set_auto_temp(struct device *dev, struct device_attribute *attr,
+			     const char *buf, size_t count)
 {
 	struct it87_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute_2 *sensor_attr =
@@ -1263,14 +1564,24 @@ static ssize_t set_auto_temp(struct devi
 	int nr = sensor_attr->nr;
 	int point = sensor_attr->index;
 	long val;
+	int reg;
 
 	if (kstrtol(buf, 10, &val) < 0 || val < -128000 || val > 127000)
 		return -EINVAL;
 
 	mutex_lock(&data->update_lock);
-	data->auto_temp[nr][point] = TEMP_TO_REG(val);
-	it87_write_value(data, IT87_REG_AUTO_TEMP(nr, point),
-			 data->auto_temp[nr][point]);
+	if (has_newer_autopwm(data) && !point) {
+		reg = data->auto_temp[nr][1] - TEMP_TO_REG(val);
+		reg = clamp_val(reg, 0, 0x1f) | (data->auto_temp[nr][0] & 0xe0);
+		data->auto_temp[nr][0] = reg;
+		it87_write_value(data, IT87_REG_AUTO_TEMP(nr, 5), reg);
+	} else {
+		reg = TEMP_TO_REG(val);
+		data->auto_temp[nr][point] = reg;
+		if (has_newer_autopwm(data))
+			point--;
+		it87_write_value(data, IT87_REG_AUTO_TEMP(nr, point), reg);
+	}
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -1308,8 +1619,9 @@ static SENSOR_DEVICE_ATTR_2(fan6_min, S_
 static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
 			  show_pwm_enable, set_pwm_enable, 0);
 static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 0);
-static DEVICE_ATTR(pwm1_freq, S_IRUGO | S_IWUSR, show_pwm_freq, set_pwm_freq);
-static SENSOR_DEVICE_ATTR(pwm1_auto_channels_temp, S_IRUGO | S_IWUSR,
+static SENSOR_DEVICE_ATTR(pwm1_freq, S_IRUGO | S_IWUSR, show_pwm_freq,
+			  set_pwm_freq, 0);
+static SENSOR_DEVICE_ATTR(pwm1_auto_channels_temp, S_IRUGO,
 			  show_pwm_temp_map, set_pwm_temp_map, 0);
 static SENSOR_DEVICE_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO | S_IWUSR,
 			    show_auto_pwm, set_auto_pwm, 0, 0);
@@ -1329,12 +1641,16 @@ static SENSOR_DEVICE_ATTR_2(pwm1_auto_po
 			    show_auto_temp, set_auto_temp, 0, 3);
 static SENSOR_DEVICE_ATTR_2(pwm1_auto_point4_temp, S_IRUGO | S_IWUSR,
 			    show_auto_temp, set_auto_temp, 0, 4);
+static SENSOR_DEVICE_ATTR_2(pwm1_auto_start, S_IRUGO | S_IWUSR,
+			    show_auto_pwm, set_auto_pwm, 0, 0);
+static SENSOR_DEVICE_ATTR(pwm1_auto_slope, S_IRUGO | S_IWUSR,
+			  show_auto_pwm_slope, set_auto_pwm_slope, 0);
 
 static SENSOR_DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR,
 			  show_pwm_enable, set_pwm_enable, 1);
 static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 1);
-static DEVICE_ATTR(pwm2_freq, S_IRUGO, show_pwm_freq, NULL);
-static SENSOR_DEVICE_ATTR(pwm2_auto_channels_temp, S_IRUGO | S_IWUSR,
+static SENSOR_DEVICE_ATTR(pwm2_freq, S_IRUGO, show_pwm_freq, set_pwm_freq, 1);
+static SENSOR_DEVICE_ATTR(pwm2_auto_channels_temp, S_IRUGO,
 			  show_pwm_temp_map, set_pwm_temp_map, 1);
 static SENSOR_DEVICE_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO | S_IWUSR,
 			    show_auto_pwm, set_auto_pwm, 1, 0);
@@ -1354,12 +1670,16 @@ static SENSOR_DEVICE_ATTR_2(pwm2_auto_po
 			    show_auto_temp, set_auto_temp, 1, 3);
 static SENSOR_DEVICE_ATTR_2(pwm2_auto_point4_temp, S_IRUGO | S_IWUSR,
 			    show_auto_temp, set_auto_temp, 1, 4);
+static SENSOR_DEVICE_ATTR_2(pwm2_auto_start, S_IRUGO | S_IWUSR,
+			    show_auto_pwm, set_auto_pwm, 1, 0);
+static SENSOR_DEVICE_ATTR(pwm2_auto_slope, S_IRUGO | S_IWUSR,
+			  show_auto_pwm_slope, set_auto_pwm_slope, 1);
 
 static SENSOR_DEVICE_ATTR(pwm3_enable, S_IRUGO | S_IWUSR,
 			  show_pwm_enable, set_pwm_enable, 2);
 static SENSOR_DEVICE_ATTR(pwm3, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 2);
-static DEVICE_ATTR(pwm3_freq, S_IRUGO, show_pwm_freq, NULL);
-static SENSOR_DEVICE_ATTR(pwm3_auto_channels_temp, S_IRUGO | S_IWUSR,
+static SENSOR_DEVICE_ATTR(pwm3_freq, S_IRUGO, show_pwm_freq, NULL, 2);
+static SENSOR_DEVICE_ATTR(pwm3_auto_channels_temp, S_IRUGO,
 			  show_pwm_temp_map, set_pwm_temp_map, 2);
 static SENSOR_DEVICE_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO | S_IWUSR,
 			    show_auto_pwm, set_auto_pwm, 2, 0);
@@ -1379,30 +1699,94 @@ static SENSOR_DEVICE_ATTR_2(pwm3_auto_po
 			    show_auto_temp, set_auto_temp, 2, 3);
 static SENSOR_DEVICE_ATTR_2(pwm3_auto_point4_temp, S_IRUGO | S_IWUSR,
 			    show_auto_temp, set_auto_temp, 2, 4);
+static SENSOR_DEVICE_ATTR_2(pwm3_auto_start, S_IRUGO | S_IWUSR,
+			    show_auto_pwm, set_auto_pwm, 2, 0);
+static SENSOR_DEVICE_ATTR(pwm3_auto_slope, S_IRUGO | S_IWUSR,
+			  show_auto_pwm_slope, set_auto_pwm_slope, 2);
+
+static SENSOR_DEVICE_ATTR(pwm4_enable, S_IRUGO | S_IWUSR,
+			  show_pwm_enable, set_pwm_enable, 3);
+static SENSOR_DEVICE_ATTR(pwm4, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 3);
+static SENSOR_DEVICE_ATTR(pwm4_freq, S_IRUGO, show_pwm_freq, NULL, 3);
+static SENSOR_DEVICE_ATTR(pwm4_auto_channels_temp, S_IRUGO,
+			  show_pwm_temp_map, set_pwm_temp_map, 3);
+static SENSOR_DEVICE_ATTR_2(pwm4_auto_point1_temp, S_IRUGO | S_IWUSR,
+			    show_auto_temp, set_auto_temp, 2, 1);
+static SENSOR_DEVICE_ATTR_2(pwm4_auto_point1_temp_hyst, S_IRUGO | S_IWUSR,
+			    show_auto_temp, set_auto_temp, 2, 0);
+static SENSOR_DEVICE_ATTR_2(pwm4_auto_point2_temp, S_IRUGO | S_IWUSR,
+			    show_auto_temp, set_auto_temp, 2, 2);
+static SENSOR_DEVICE_ATTR_2(pwm4_auto_point3_temp, S_IRUGO | S_IWUSR,
+			    show_auto_temp, set_auto_temp, 2, 3);
+static SENSOR_DEVICE_ATTR_2(pwm4_auto_start, S_IRUGO | S_IWUSR,
+			    show_auto_pwm, set_auto_pwm, 3, 0);
+static SENSOR_DEVICE_ATTR(pwm4_auto_slope, S_IRUGO | S_IWUSR,
+			  show_auto_pwm_slope, set_auto_pwm_slope, 3);
+
+static SENSOR_DEVICE_ATTR(pwm5_enable, S_IRUGO | S_IWUSR,
+			  show_pwm_enable, set_pwm_enable, 4);
+static SENSOR_DEVICE_ATTR(pwm5, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 4);
+static SENSOR_DEVICE_ATTR(pwm5_freq, S_IRUGO, show_pwm_freq, NULL, 4);
+static SENSOR_DEVICE_ATTR(pwm5_auto_channels_temp, S_IRUGO,
+			  show_pwm_temp_map, set_pwm_temp_map, 4);
+static SENSOR_DEVICE_ATTR_2(pwm5_auto_point1_temp, S_IRUGO | S_IWUSR,
+			    show_auto_temp, set_auto_temp, 2, 1);
+static SENSOR_DEVICE_ATTR_2(pwm5_auto_point1_temp_hyst, S_IRUGO | S_IWUSR,
+			    show_auto_temp, set_auto_temp, 2, 0);
+static SENSOR_DEVICE_ATTR_2(pwm5_auto_point2_temp, S_IRUGO | S_IWUSR,
+			    show_auto_temp, set_auto_temp, 2, 2);
+static SENSOR_DEVICE_ATTR_2(pwm5_auto_point3_temp, S_IRUGO | S_IWUSR,
+			    show_auto_temp, set_auto_temp, 2, 3);
+static SENSOR_DEVICE_ATTR_2(pwm5_auto_start, S_IRUGO | S_IWUSR,
+			    show_auto_pwm, set_auto_pwm, 4, 0);
+static SENSOR_DEVICE_ATTR(pwm5_auto_slope, S_IRUGO | S_IWUSR,
+			  show_auto_pwm_slope, set_auto_pwm_slope, 4);
+
+static SENSOR_DEVICE_ATTR(pwm6_enable, S_IRUGO | S_IWUSR,
+			  show_pwm_enable, set_pwm_enable, 5);
+static SENSOR_DEVICE_ATTR(pwm6, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 5);
+static SENSOR_DEVICE_ATTR(pwm6_freq, S_IRUGO, show_pwm_freq, NULL, 5);
+static SENSOR_DEVICE_ATTR(pwm6_auto_channels_temp, S_IRUGO,
+			  show_pwm_temp_map, set_pwm_temp_map, 5);
+static SENSOR_DEVICE_ATTR_2(pwm6_auto_point1_temp, S_IRUGO | S_IWUSR,
+			    show_auto_temp, set_auto_temp, 2, 1);
+static SENSOR_DEVICE_ATTR_2(pwm6_auto_point1_temp_hyst, S_IRUGO | S_IWUSR,
+			    show_auto_temp, set_auto_temp, 2, 0);
+static SENSOR_DEVICE_ATTR_2(pwm6_auto_point2_temp, S_IRUGO | S_IWUSR,
+			    show_auto_temp, set_auto_temp, 2, 2);
+static SENSOR_DEVICE_ATTR_2(pwm6_auto_point3_temp, S_IRUGO | S_IWUSR,
+			    show_auto_temp, set_auto_temp, 2, 3);
+static SENSOR_DEVICE_ATTR_2(pwm6_auto_start, S_IRUGO | S_IWUSR,
+			    show_auto_pwm, set_auto_pwm, 5, 0);
+static SENSOR_DEVICE_ATTR(pwm6_auto_slope, S_IRUGO | S_IWUSR,
+			  show_auto_pwm_slope, set_auto_pwm_slope, 5);
 
 /* Alarms */
 static ssize_t show_alarms(struct device *dev, struct device_attribute *attr,
-		char *buf)
+			   char *buf)
 {
 	struct it87_data *data = it87_update_device(dev);
+
 	return sprintf(buf, "%u\n", data->alarms);
 }
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
 static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
-		char *buf)
+			  char *buf)
 {
-	int bitnr = to_sensor_dev_attr(attr)->index;
 	struct it87_data *data = it87_update_device(dev);
+	int bitnr = to_sensor_dev_attr(attr)->index;
+
 	return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
 }
 
-static ssize_t clear_intrusion(struct device *dev, struct device_attribute
-		*attr, const char *buf, size_t count)
+static ssize_t clear_intrusion(struct device *dev,
+			       struct device_attribute *attr, const char *buf,
+			       size_t count)
 {
 	struct it87_data *data = dev_get_drvdata(dev);
-	long val;
 	int config;
+	long val;
 
 	if (kstrtol(buf, 10, &val) < 0 || val != 0)
 		return -EINVAL;
@@ -1412,7 +1796,7 @@ static ssize_t clear_intrusion(struct de
 	if (config < 0) {
 		count = config;
 	} else {
-		config |= 1 << 5;
+		config |= BIT(5);
 		it87_write_value(data, IT87_REG_CONFIG, config);
 		/* Invalidate cache to force re-read */
 		data->valid = 0;
@@ -1443,29 +1827,30 @@ static SENSOR_DEVICE_ATTR(intrusion0_ala
 			  show_alarm, clear_intrusion, 4);
 
 static ssize_t show_beep(struct device *dev, struct device_attribute *attr,
-		char *buf)
+			 char *buf)
 {
-	int bitnr = to_sensor_dev_attr(attr)->index;
 	struct it87_data *data = it87_update_device(dev);
+	int bitnr = to_sensor_dev_attr(attr)->index;
+
 	return sprintf(buf, "%u\n", (data->beeps >> bitnr) & 1);
 }
+
 static ssize_t set_beep(struct device *dev, struct device_attribute *attr,
-		const char *buf, size_t count)
+			const char *buf, size_t count)
 {
 	int bitnr = to_sensor_dev_attr(attr)->index;
 	struct it87_data *data = dev_get_drvdata(dev);
 	long val;
 
-	if (kstrtol(buf, 10, &val) < 0
-	 || (val != 0 && val != 1))
+	if (kstrtol(buf, 10, &val) < 0 || (val != 0 && val != 1))
 		return -EINVAL;
 
 	mutex_lock(&data->update_lock);
 	data->beeps = it87_read_value(data, IT87_REG_BEEP_ENABLE);
 	if (val)
-		data->beeps |= (1 << bitnr);
+		data->beeps |= BIT(bitnr);
 	else
-		data->beeps &= ~(1 << bitnr);
+		data->beeps &= ~BIT(bitnr);
 	it87_write_value(data, IT87_REG_BEEP_ENABLE, data->beeps);
 	mutex_unlock(&data->update_lock);
 	return count;
@@ -1493,13 +1878,15 @@ static SENSOR_DEVICE_ATTR(temp2_beep, S_
 static SENSOR_DEVICE_ATTR(temp3_beep, S_IRUGO, show_beep, NULL, 2);
 
 static ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr,
-		char *buf)
+			    char *buf)
 {
 	struct it87_data *data = dev_get_drvdata(dev);
+
 	return sprintf(buf, "%u\n", data->vrm);
 }
+
 static ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr,
-		const char *buf, size_t count)
+			     const char *buf, size_t count)
 {
 	struct it87_data *data = dev_get_drvdata(dev);
 	unsigned long val;
@@ -1514,15 +1901,16 @@ static ssize_t store_vrm_reg(struct devi
 static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
 
 static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr,
-		char *buf)
+			    char *buf)
 {
 	struct it87_data *data = it87_update_device(dev);
-	return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
+
+	return sprintf(buf, "%ld\n", (long)vid_from_reg(data->vid, data->vrm));
 }
 static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
 
 static ssize_t show_label(struct device *dev, struct device_attribute *attr,
-		char *buf)
+			  char *buf)
 {
 	static const char * const labels[] = {
 		"+5V",
@@ -1548,227 +1936,348 @@ static ssize_t show_label(struct device
 static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_label, NULL, 0);
 static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, show_label, NULL, 1);
 static SENSOR_DEVICE_ATTR(in8_label, S_IRUGO, show_label, NULL, 2);
-/* special AVCC3 IT8603E in9 */
+/* AVCC3 */
 static SENSOR_DEVICE_ATTR(in9_label, S_IRUGO, show_label, NULL, 0);
 
-static ssize_t show_name(struct device *dev, struct device_attribute
-			 *devattr, char *buf)
+static umode_t it87_in_is_visible(struct kobject *kobj,
+				  struct attribute *attr, int index)
 {
+	struct device *dev = container_of(kobj, struct device, kobj);
 	struct it87_data *data = dev_get_drvdata(dev);
-	return sprintf(buf, "%s\n", data->name);
+	int i = index / 5;	/* voltage index */
+	int a = index % 5;	/* attribute index */
+
+	if (index >= 40) {	/* in8 and higher only have input attributes */
+		i = index - 40 + 8;
+		a = 0;
+	}
+
+	if (!(data->has_in & BIT(i)))
+		return 0;
+
+	if (a == 4 && !data->has_beep)
+		return 0;
+
+	return attr->mode;
 }
-static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 
-static struct attribute *it87_attributes_in[10][5] = {
-{
+static struct attribute *it87_attributes_in[] = {
 	&sensor_dev_attr_in0_input.dev_attr.attr,
 	&sensor_dev_attr_in0_min.dev_attr.attr,
 	&sensor_dev_attr_in0_max.dev_attr.attr,
 	&sensor_dev_attr_in0_alarm.dev_attr.attr,
-	NULL
-}, {
+	&sensor_dev_attr_in0_beep.dev_attr.attr,	/* 4 */
+
 	&sensor_dev_attr_in1_input.dev_attr.attr,
 	&sensor_dev_attr_in1_min.dev_attr.attr,
 	&sensor_dev_attr_in1_max.dev_attr.attr,
 	&sensor_dev_attr_in1_alarm.dev_attr.attr,
-	NULL
-}, {
+	&sensor_dev_attr_in1_beep.dev_attr.attr,	/* 9 */
+
 	&sensor_dev_attr_in2_input.dev_attr.attr,
 	&sensor_dev_attr_in2_min.dev_attr.attr,
 	&sensor_dev_attr_in2_max.dev_attr.attr,
 	&sensor_dev_attr_in2_alarm.dev_attr.attr,
-	NULL
-}, {
+	&sensor_dev_attr_in2_beep.dev_attr.attr,	/* 14 */
+
 	&sensor_dev_attr_in3_input.dev_attr.attr,
 	&sensor_dev_attr_in3_min.dev_attr.attr,
 	&sensor_dev_attr_in3_max.dev_attr.attr,
 	&sensor_dev_attr_in3_alarm.dev_attr.attr,
-	NULL
-}, {
+	&sensor_dev_attr_in3_beep.dev_attr.attr,	/* 19 */
+
 	&sensor_dev_attr_in4_input.dev_attr.attr,
 	&sensor_dev_attr_in4_min.dev_attr.attr,
 	&sensor_dev_attr_in4_max.dev_attr.attr,
 	&sensor_dev_attr_in4_alarm.dev_attr.attr,
-	NULL
-}, {
+	&sensor_dev_attr_in4_beep.dev_attr.attr,	/* 24 */
+
 	&sensor_dev_attr_in5_input.dev_attr.attr,
 	&sensor_dev_attr_in5_min.dev_attr.attr,
 	&sensor_dev_attr_in5_max.dev_attr.attr,
 	&sensor_dev_attr_in5_alarm.dev_attr.attr,
-	NULL
-}, {
+	&sensor_dev_attr_in5_beep.dev_attr.attr,	/* 29 */
+
 	&sensor_dev_attr_in6_input.dev_attr.attr,
 	&sensor_dev_attr_in6_min.dev_attr.attr,
 	&sensor_dev_attr_in6_max.dev_attr.attr,
 	&sensor_dev_attr_in6_alarm.dev_attr.attr,
-	NULL
-}, {
+	&sensor_dev_attr_in6_beep.dev_attr.attr,	/* 34 */
+
 	&sensor_dev_attr_in7_input.dev_attr.attr,
 	&sensor_dev_attr_in7_min.dev_attr.attr,
 	&sensor_dev_attr_in7_max.dev_attr.attr,
 	&sensor_dev_attr_in7_alarm.dev_attr.attr,
-	NULL
-}, {
-	&sensor_dev_attr_in8_input.dev_attr.attr,
-	NULL
-}, {
-	&sensor_dev_attr_in9_input.dev_attr.attr,
-	NULL
-} };
+	&sensor_dev_attr_in7_beep.dev_attr.attr,	/* 39 */
 
-static const struct attribute_group it87_group_in[10] = {
-	{ .attrs = it87_attributes_in[0] },
-	{ .attrs = it87_attributes_in[1] },
-	{ .attrs = it87_attributes_in[2] },
-	{ .attrs = it87_attributes_in[3] },
-	{ .attrs = it87_attributes_in[4] },
-	{ .attrs = it87_attributes_in[5] },
-	{ .attrs = it87_attributes_in[6] },
-	{ .attrs = it87_attributes_in[7] },
-	{ .attrs = it87_attributes_in[8] },
-	{ .attrs = it87_attributes_in[9] },
+	&sensor_dev_attr_in8_input.dev_attr.attr,	/* 40 */
+	&sensor_dev_attr_in9_input.dev_attr.attr,	/* 41 */
+	&sensor_dev_attr_in10_input.dev_attr.attr,	/* 41 */
+	&sensor_dev_attr_in11_input.dev_attr.attr,	/* 41 */
+	&sensor_dev_attr_in12_input.dev_attr.attr,	/* 41 */
 };
 
-static struct attribute *it87_attributes_temp[3][6] = {
+static const struct attribute_group it87_group_in = {
+	.attrs = it87_attributes_in,
+	.is_visible = it87_in_is_visible,
+};
+
+static umode_t it87_temp_is_visible(struct kobject *kobj,
+				    struct attribute *attr, int index)
 {
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct it87_data *data = dev_get_drvdata(dev);
+	int i = index / 7;	/* temperature index */
+	int a = index % 7;	/* attribute index */
+
+	if (index >= 21) {
+		i = index - 21 + 3;
+		a = 0;
+	}
+
+	if (!(data->has_temp & BIT(i)))
+		return 0;
+
+	if (a == 5 && !has_temp_offset(data))
+		return 0;
+
+	if (a == 6 && !data->has_beep)
+		return 0;
+
+	return attr->mode;
+}
+
+static struct attribute *it87_attributes_temp[] = {
 	&sensor_dev_attr_temp1_input.dev_attr.attr,
 	&sensor_dev_attr_temp1_max.dev_attr.attr,
 	&sensor_dev_attr_temp1_min.dev_attr.attr,
 	&sensor_dev_attr_temp1_type.dev_attr.attr,
 	&sensor_dev_attr_temp1_alarm.dev_attr.attr,
-	NULL
-} , {
-	&sensor_dev_attr_temp2_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_offset.dev_attr.attr,	/* 5 */
+	&sensor_dev_attr_temp1_beep.dev_attr.attr,	/* 6 */
+
+	&sensor_dev_attr_temp2_input.dev_attr.attr,	/* 7 */
 	&sensor_dev_attr_temp2_max.dev_attr.attr,
 	&sensor_dev_attr_temp2_min.dev_attr.attr,
 	&sensor_dev_attr_temp2_type.dev_attr.attr,
 	&sensor_dev_attr_temp2_alarm.dev_attr.attr,
-	NULL
-} , {
-	&sensor_dev_attr_temp3_input.dev_attr.attr,
+	&sensor_dev_attr_temp2_offset.dev_attr.attr,
+	&sensor_dev_attr_temp2_beep.dev_attr.attr,
+
+	&sensor_dev_attr_temp3_input.dev_attr.attr,	/* 14 */
 	&sensor_dev_attr_temp3_max.dev_attr.attr,
 	&sensor_dev_attr_temp3_min.dev_attr.attr,
 	&sensor_dev_attr_temp3_type.dev_attr.attr,
 	&sensor_dev_attr_temp3_alarm.dev_attr.attr,
-	NULL
-} };
+	&sensor_dev_attr_temp3_offset.dev_attr.attr,
+	&sensor_dev_attr_temp3_beep.dev_attr.attr,
 
-static const struct attribute_group it87_group_temp[3] = {
-	{ .attrs = it87_attributes_temp[0] },
-	{ .attrs = it87_attributes_temp[1] },
-	{ .attrs = it87_attributes_temp[2] },
+	&sensor_dev_attr_temp4_input.dev_attr.attr,	/* 21 */
+	&sensor_dev_attr_temp5_input.dev_attr.attr,
+	&sensor_dev_attr_temp6_input.dev_attr.attr,
+	NULL
 };
 
-static struct attribute *it87_attributes_temp_offset[] = {
-	&sensor_dev_attr_temp1_offset.dev_attr.attr,
-	&sensor_dev_attr_temp2_offset.dev_attr.attr,
-	&sensor_dev_attr_temp3_offset.dev_attr.attr,
+static const struct attribute_group it87_group_temp = {
+	.attrs = it87_attributes_temp,
+	.is_visible = it87_temp_is_visible,
 };
 
+static umode_t it87_is_visible(struct kobject *kobj,
+			       struct attribute *attr, int index)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct it87_data *data = dev_get_drvdata(dev);
+
+	if ((index == 2 || index == 3) && !data->has_vid)
+		return 0;
+
+	if (index > 3 && !(data->in_internal & BIT(index - 4)))
+		return 0;
+
+	return attr->mode;
+}
+
 static struct attribute *it87_attributes[] = {
 	&dev_attr_alarms.attr,
 	&sensor_dev_attr_intrusion0_alarm.dev_attr.attr,
-	&dev_attr_name.attr,
+	&dev_attr_vrm.attr,				/* 2 */
+	&dev_attr_cpu0_vid.attr,			/* 3 */
+	&sensor_dev_attr_in3_label.dev_attr.attr,	/* 4 .. 7 */
+	&sensor_dev_attr_in7_label.dev_attr.attr,
+	&sensor_dev_attr_in8_label.dev_attr.attr,
+	&sensor_dev_attr_in9_label.dev_attr.attr,
 	NULL
 };
 
 static const struct attribute_group it87_group = {
 	.attrs = it87_attributes,
+	.is_visible = it87_is_visible,
 };
 
-static struct attribute *it87_attributes_in_beep[] = {
-	&sensor_dev_attr_in0_beep.dev_attr.attr,
-	&sensor_dev_attr_in1_beep.dev_attr.attr,
-	&sensor_dev_attr_in2_beep.dev_attr.attr,
-	&sensor_dev_attr_in3_beep.dev_attr.attr,
-	&sensor_dev_attr_in4_beep.dev_attr.attr,
-	&sensor_dev_attr_in5_beep.dev_attr.attr,
-	&sensor_dev_attr_in6_beep.dev_attr.attr,
-	&sensor_dev_attr_in7_beep.dev_attr.attr,
-	NULL,
-	NULL,
-};
+static umode_t it87_fan_is_visible(struct kobject *kobj,
+				   struct attribute *attr, int index)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct it87_data *data = dev_get_drvdata(dev);
+	int i = index / 5;	/* fan index */
+	int a = index % 5;	/* attribute index */
 
-static struct attribute *it87_attributes_temp_beep[] = {
-	&sensor_dev_attr_temp1_beep.dev_attr.attr,
-	&sensor_dev_attr_temp2_beep.dev_attr.attr,
-	&sensor_dev_attr_temp3_beep.dev_attr.attr,
-};
+	if (index >= 15) {	/* fan 4..6 don't have divisor attributes */
+		i = (index - 15) / 4 + 3;
+		a = (index - 15) % 4;
+	}
 
-static struct attribute *it87_attributes_fan[6][3+1] = { {
+	if (!(data->has_fan & BIT(i)))
+		return 0;
+
+	if (a == 3) {				/* beep */
+		if (!data->has_beep)
+			return 0;
+		/* first fan beep attribute is writable */
+		if (i == __ffs(data->has_fan))
+			return attr->mode | S_IWUSR;
+	}
+
+	if (a == 4 && has_16bit_fans(data))	/* divisor */
+		return 0;
+
+	return attr->mode;
+}
+
+static struct attribute *it87_attributes_fan[] = {
 	&sensor_dev_attr_fan1_input.dev_attr.attr,
 	&sensor_dev_attr_fan1_min.dev_attr.attr,
 	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
-	NULL
-}, {
+	&sensor_dev_attr_fan1_beep.dev_attr.attr,	/* 3 */
+	&sensor_dev_attr_fan1_div.dev_attr.attr,	/* 4 */
+
 	&sensor_dev_attr_fan2_input.dev_attr.attr,
 	&sensor_dev_attr_fan2_min.dev_attr.attr,
 	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
-	NULL
-}, {
+	&sensor_dev_attr_fan2_beep.dev_attr.attr,
+	&sensor_dev_attr_fan2_div.dev_attr.attr,	/* 9 */
+
 	&sensor_dev_attr_fan3_input.dev_attr.attr,
 	&sensor_dev_attr_fan3_min.dev_attr.attr,
 	&sensor_dev_attr_fan3_alarm.dev_attr.attr,
-	NULL
-}, {
-	&sensor_dev_attr_fan4_input.dev_attr.attr,
+	&sensor_dev_attr_fan3_beep.dev_attr.attr,
+	&sensor_dev_attr_fan3_div.dev_attr.attr,	/* 14 */
+
+	&sensor_dev_attr_fan4_input.dev_attr.attr,	/* 15 */
 	&sensor_dev_attr_fan4_min.dev_attr.attr,
 	&sensor_dev_attr_fan4_alarm.dev_attr.attr,
-	NULL
-}, {
-	&sensor_dev_attr_fan5_input.dev_attr.attr,
+	&sensor_dev_attr_fan4_beep.dev_attr.attr,
+
+	&sensor_dev_attr_fan5_input.dev_attr.attr,	/* 19 */
 	&sensor_dev_attr_fan5_min.dev_attr.attr,
 	&sensor_dev_attr_fan5_alarm.dev_attr.attr,
-	NULL
-}, {
-	&sensor_dev_attr_fan6_input.dev_attr.attr,
+	&sensor_dev_attr_fan5_beep.dev_attr.attr,
+
+	&sensor_dev_attr_fan6_input.dev_attr.attr,	/* 23 */
 	&sensor_dev_attr_fan6_min.dev_attr.attr,
 	&sensor_dev_attr_fan6_alarm.dev_attr.attr,
+	&sensor_dev_attr_fan6_beep.dev_attr.attr,
 	NULL
-} };
-
-static const struct attribute_group it87_group_fan[6] = {
-	{ .attrs = it87_attributes_fan[0] },
-	{ .attrs = it87_attributes_fan[1] },
-	{ .attrs = it87_attributes_fan[2] },
-	{ .attrs = it87_attributes_fan[3] },
-	{ .attrs = it87_attributes_fan[4] },
-	{ .attrs = it87_attributes_fan[5] },
 };
 
-static const struct attribute *it87_attributes_fan_div[] = {
-	&sensor_dev_attr_fan1_div.dev_attr.attr,
-	&sensor_dev_attr_fan2_div.dev_attr.attr,
-	&sensor_dev_attr_fan3_div.dev_attr.attr,
+static const struct attribute_group it87_group_fan = {
+	.attrs = it87_attributes_fan,
+	.is_visible = it87_fan_is_visible,
 };
 
-static struct attribute *it87_attributes_pwm[3][4+1] = { {
+static umode_t it87_pwm_is_visible(struct kobject *kobj,
+				   struct attribute *attr, int index)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct it87_data *data = dev_get_drvdata(dev);
+	int i = index / 4;	/* pwm index */
+	int a = index % 4;	/* attribute index */
+
+	if (!(data->has_pwm & BIT(i)))
+		return 0;
+
+	/* pwmX_auto_channels_temp is only writable if auto pwm is supported */
+	if (a == 3 && (has_old_autopwm(data) || has_newer_autopwm(data)))
+		return attr->mode | S_IWUSR;
+
+	/* pwm2_freq is writable if there are two pwm frequency selects */
+	if (has_pwm_freq2(data) && i == 1 && a == 2)
+		return attr->mode | S_IWUSR;
+
+	return attr->mode;
+}
+
+static struct attribute *it87_attributes_pwm[] = {
 	&sensor_dev_attr_pwm1_enable.dev_attr.attr,
 	&sensor_dev_attr_pwm1.dev_attr.attr,
-	&dev_attr_pwm1_freq.attr,
+	&sensor_dev_attr_pwm1_freq.dev_attr.attr,
 	&sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr,
-	NULL
-}, {
+
 	&sensor_dev_attr_pwm2_enable.dev_attr.attr,
 	&sensor_dev_attr_pwm2.dev_attr.attr,
-	&dev_attr_pwm2_freq.attr,
+	&sensor_dev_attr_pwm2_freq.dev_attr.attr,
 	&sensor_dev_attr_pwm2_auto_channels_temp.dev_attr.attr,
-	NULL
-}, {
+
 	&sensor_dev_attr_pwm3_enable.dev_attr.attr,
 	&sensor_dev_attr_pwm3.dev_attr.attr,
-	&dev_attr_pwm3_freq.attr,
+	&sensor_dev_attr_pwm3_freq.dev_attr.attr,
 	&sensor_dev_attr_pwm3_auto_channels_temp.dev_attr.attr,
+
+	&sensor_dev_attr_pwm4_enable.dev_attr.attr,
+	&sensor_dev_attr_pwm4.dev_attr.attr,
+	&sensor_dev_attr_pwm4_freq.dev_attr.attr,
+	&sensor_dev_attr_pwm4_auto_channels_temp.dev_attr.attr,
+
+	&sensor_dev_attr_pwm5_enable.dev_attr.attr,
+	&sensor_dev_attr_pwm5.dev_attr.attr,
+	&sensor_dev_attr_pwm5_freq.dev_attr.attr,
+	&sensor_dev_attr_pwm5_auto_channels_temp.dev_attr.attr,
+
+	&sensor_dev_attr_pwm6_enable.dev_attr.attr,
+	&sensor_dev_attr_pwm6.dev_attr.attr,
+	&sensor_dev_attr_pwm6_freq.dev_attr.attr,
+	&sensor_dev_attr_pwm6_auto_channels_temp.dev_attr.attr,
+
 	NULL
-} };
+};
 
-static const struct attribute_group it87_group_pwm[3] = {
-	{ .attrs = it87_attributes_pwm[0] },
-	{ .attrs = it87_attributes_pwm[1] },
-	{ .attrs = it87_attributes_pwm[2] },
+static const struct attribute_group it87_group_pwm = {
+	.attrs = it87_attributes_pwm,
+	.is_visible = it87_pwm_is_visible,
 };
 
-static struct attribute *it87_attributes_autopwm[3][9+1] = { {
+static umode_t it87_auto_pwm_is_visible(struct kobject *kobj,
+					struct attribute *attr, int index)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct it87_data *data = dev_get_drvdata(dev);
+	int i = index / 11;	/* pwm index */
+	int a = index % 11;	/* attribute index */
+
+	if (index >= 33) {	/* pwm 4..6 */
+		i = (index - 33) / 6 + 3;
+		a = (index - 33) % 6 + 4;
+	}
+
+	if (!(data->has_pwm & BIT(i)))
+		return 0;
+
+	if (has_newer_autopwm(data)) {
+		if (a < 4)	/* no auto point pwm */
+			return 0;
+		if (a == 8)	/* no auto_point4 */
+			return 0;
+	}
+	if (has_old_autopwm(data)) {
+		if (a >= 9)	/* no pwm_auto_start, pwm_auto_slope */
+			return 0;
+	}
+
+	return attr->mode;
+}
+
+static struct attribute *it87_attributes_auto_pwm[] = {
 	&sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr,
 	&sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr,
 	&sensor_dev_attr_pwm1_auto_point3_pwm.dev_attr.attr,
@@ -1778,9 +2287,10 @@ static struct attribute *it87_attributes
 	&sensor_dev_attr_pwm1_auto_point2_temp.dev_attr.attr,
 	&sensor_dev_attr_pwm1_auto_point3_temp.dev_attr.attr,
 	&sensor_dev_attr_pwm1_auto_point4_temp.dev_attr.attr,
-	NULL
-}, {
-	&sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr,
+	&sensor_dev_attr_pwm1_auto_start.dev_attr.attr,
+	&sensor_dev_attr_pwm1_auto_slope.dev_attr.attr,
+
+	&sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr,	/* 11 */
 	&sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr,
 	&sensor_dev_attr_pwm2_auto_point3_pwm.dev_attr.attr,
 	&sensor_dev_attr_pwm2_auto_point4_pwm.dev_attr.attr,
@@ -1789,9 +2299,10 @@ static struct attribute *it87_attributes
 	&sensor_dev_attr_pwm2_auto_point2_temp.dev_attr.attr,
 	&sensor_dev_attr_pwm2_auto_point3_temp.dev_attr.attr,
 	&sensor_dev_attr_pwm2_auto_point4_temp.dev_attr.attr,
-	NULL
-}, {
-	&sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr,
+	&sensor_dev_attr_pwm2_auto_start.dev_attr.attr,
+	&sensor_dev_attr_pwm2_auto_slope.dev_attr.attr,
+
+	&sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr,	/* 22 */
 	&sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr,
 	&sensor_dev_attr_pwm3_auto_point3_pwm.dev_attr.attr,
 	&sensor_dev_attr_pwm3_auto_point4_pwm.dev_attr.attr,
@@ -1800,61 +2311,53 @@ static struct attribute *it87_attributes
 	&sensor_dev_attr_pwm3_auto_point2_temp.dev_attr.attr,
 	&sensor_dev_attr_pwm3_auto_point3_temp.dev_attr.attr,
 	&sensor_dev_attr_pwm3_auto_point4_temp.dev_attr.attr,
-	NULL
-} };
-
-static const struct attribute_group it87_group_autopwm[3] = {
-	{ .attrs = it87_attributes_autopwm[0] },
-	{ .attrs = it87_attributes_autopwm[1] },
-	{ .attrs = it87_attributes_autopwm[2] },
-};
+	&sensor_dev_attr_pwm3_auto_start.dev_attr.attr,
+	&sensor_dev_attr_pwm3_auto_slope.dev_attr.attr,
 
-static struct attribute *it87_attributes_fan_beep[] = {
-	&sensor_dev_attr_fan1_beep.dev_attr.attr,
-	&sensor_dev_attr_fan2_beep.dev_attr.attr,
-	&sensor_dev_attr_fan3_beep.dev_attr.attr,
-	&sensor_dev_attr_fan4_beep.dev_attr.attr,
-	&sensor_dev_attr_fan5_beep.dev_attr.attr,
-	&sensor_dev_attr_fan6_beep.dev_attr.attr,
-};
+	&sensor_dev_attr_pwm4_auto_point1_temp.dev_attr.attr,	/* 33 */
+	&sensor_dev_attr_pwm4_auto_point1_temp_hyst.dev_attr.attr,
+	&sensor_dev_attr_pwm4_auto_point2_temp.dev_attr.attr,
+	&sensor_dev_attr_pwm4_auto_point3_temp.dev_attr.attr,
+	&sensor_dev_attr_pwm4_auto_start.dev_attr.attr,
+	&sensor_dev_attr_pwm4_auto_slope.dev_attr.attr,
 
-static struct attribute *it87_attributes_vid[] = {
-	&dev_attr_vrm.attr,
-	&dev_attr_cpu0_vid.attr,
-	NULL
-};
+	&sensor_dev_attr_pwm5_auto_point1_temp.dev_attr.attr,
+	&sensor_dev_attr_pwm5_auto_point1_temp_hyst.dev_attr.attr,
+	&sensor_dev_attr_pwm5_auto_point2_temp.dev_attr.attr,
+	&sensor_dev_attr_pwm5_auto_point3_temp.dev_attr.attr,
+	&sensor_dev_attr_pwm5_auto_start.dev_attr.attr,
+	&sensor_dev_attr_pwm5_auto_slope.dev_attr.attr,
 
-static const struct attribute_group it87_group_vid = {
-	.attrs = it87_attributes_vid,
-};
+	&sensor_dev_attr_pwm6_auto_point1_temp.dev_attr.attr,
+	&sensor_dev_attr_pwm6_auto_point1_temp_hyst.dev_attr.attr,
+	&sensor_dev_attr_pwm6_auto_point2_temp.dev_attr.attr,
+	&sensor_dev_attr_pwm6_auto_point3_temp.dev_attr.attr,
+	&sensor_dev_attr_pwm6_auto_start.dev_attr.attr,
+	&sensor_dev_attr_pwm6_auto_slope.dev_attr.attr,
 
-static struct attribute *it87_attributes_label[] = {
-	&sensor_dev_attr_in3_label.dev_attr.attr,
-	&sensor_dev_attr_in7_label.dev_attr.attr,
-	&sensor_dev_attr_in8_label.dev_attr.attr,
-	&sensor_dev_attr_in9_label.dev_attr.attr,
-	NULL
+	NULL,
 };
 
-static const struct attribute_group it87_group_label = {
-	.attrs = it87_attributes_label,
+static const struct attribute_group it87_group_auto_pwm = {
+	.attrs = it87_attributes_auto_pwm,
+	.is_visible = it87_auto_pwm_is_visible,
 };
 
 /* SuperIO detection - will change isa_address if a chip is found */
-static int __init it87_find(unsigned short *address,
-	struct it87_sio_data *sio_data)
+static int __init it87_find(int sioaddr, unsigned short *address,
+			    struct it87_sio_data *sio_data)
 {
 	int err;
 	u16 chip_type;
 	const char *board_vendor, *board_name;
 	const struct it87_devices *config;
 
-	err = superio_enter();
+	err = superio_enter(sioaddr);
 	if (err)
 		return err;
 
 	err = -ENODEV;
-	chip_type = force_id ? force_id : superio_inw(DEVID);
+	chip_type = force_id ? force_id : superio_inw(sioaddr, DEVID);
 
 	switch (chip_type) {
 	case IT8705F_DEVID:
@@ -1910,6 +2413,9 @@ static int __init it87_find(unsigned sho
 	case IT8620E_DEVID:
 		sio_data->type = it8620;
 		break;
+	case IT8628E_DEVID:
+		sio_data->type = it8628;
+		break;
 	case 0xffff:	/* No device at all */
 		goto exit;
 	default:
@@ -1917,20 +2423,20 @@ static int __init it87_find(unsigned sho
 		goto exit;
 	}
 
-	superio_select(PME);
-	if (!(superio_inb(IT87_ACT_REG) & 0x01)) {
+	superio_select(sioaddr, PME);
+	if (!(superio_inb(sioaddr, IT87_ACT_REG) & 0x01)) {
 		pr_info("Device not activated, skipping\n");
 		goto exit;
 	}
 
-	*address = superio_inw(IT87_BASE_REG) & ~(IT87_EXTENT - 1);
+	*address = superio_inw(sioaddr, IT87_BASE_REG) & ~(IT87_EXTENT - 1);
 	if (*address == 0) {
 		pr_info("Base address not set, skipping\n");
 		goto exit;
 	}
 
 	err = 0;
-	sio_data->revision = superio_inb(DEVREV) & 0x0f;
+	sio_data->revision = superio_inb(sioaddr, DEVREV) & 0x0f;
 	pr_info("Found IT%04x%s chip at 0x%x, revision %d\n", chip_type,
 		it87_devices[sio_data->type].suffix,
 		*address, sio_data->revision);
@@ -1939,14 +2445,19 @@ static int __init it87_find(unsigned sho
 
 	/* in7 (VSB or VCCH5V) is always internal on some chips */
 	if (has_in7_internal(config))
-		sio_data->internal |= (1 << 1);
+		sio_data->internal |= BIT(1);
 
 	/* in8 (Vbat) is always internal */
-	sio_data->internal |= (1 << 2);
+	sio_data->internal |= BIT(2);
 
-	/* Only the IT8603E has in9 */
-	if (sio_data->type != it8603)
-		sio_data->skip_in |= (1 << 9);
+	/* in9 (AVCC3), always internal if supported */
+	if (has_avcc3(config))
+		sio_data->internal |= BIT(3); /* in9 is AVCC */
+	else
+		sio_data->skip_in |= BIT(9);
+
+	if (!has_six_pwm(config))
+		sio_data->skip_pwm |= BIT(3) | BIT(4) | BIT(5);
 
 	if (!has_vid(config))
 		sio_data->skip_vid = 1;
@@ -1954,45 +2465,46 @@ static int __init it87_find(unsigned sho
 	/* Read GPIO config and VID value from LDN 7 (GPIO) */
 	if (sio_data->type == it87) {
 		/* The IT8705F has a different LD number for GPIO */
-		superio_select(5);
-		sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
+		superio_select(sioaddr, 5);
+		sio_data->beep_pin = superio_inb(sioaddr,
+						 IT87_SIO_BEEP_PIN_REG) & 0x3f;
 	} else if (sio_data->type == it8783) {
 		int reg25, reg27, reg2a, reg2c, regef;
 
-		superio_select(GPIO);
+		superio_select(sioaddr, GPIO);
 
-		reg25 = superio_inb(IT87_SIO_GPIO1_REG);
-		reg27 = superio_inb(IT87_SIO_GPIO3_REG);
-		reg2a = superio_inb(IT87_SIO_PINX1_REG);
-		reg2c = superio_inb(IT87_SIO_PINX2_REG);
-		regef = superio_inb(IT87_SIO_SPI_REG);
+		reg25 = superio_inb(sioaddr, IT87_SIO_GPIO1_REG);
+		reg27 = superio_inb(sioaddr, IT87_SIO_GPIO3_REG);
+		reg2a = superio_inb(sioaddr, IT87_SIO_PINX1_REG);
+		reg2c = superio_inb(sioaddr, IT87_SIO_PINX2_REG);
+		regef = superio_inb(sioaddr, IT87_SIO_SPI_REG);
 
 		/* Check if fan3 is there or not */
-		if ((reg27 & (1 << 0)) || !(reg2c & (1 << 2)))
-			sio_data->skip_fan |= (1 << 2);
-		if ((reg25 & (1 << 4))
-		    || (!(reg2a & (1 << 1)) && (regef & (1 << 0))))
-			sio_data->skip_pwm |= (1 << 2);
+		if ((reg27 & BIT(0)) || !(reg2c & BIT(2)))
+			sio_data->skip_fan |= BIT(2);
+		if ((reg25 & BIT(4)) ||
+		    (!(reg2a & BIT(1)) && (regef & BIT(0))))
+			sio_data->skip_pwm |= BIT(2);
 
 		/* Check if fan2 is there or not */
-		if (reg27 & (1 << 7))
-			sio_data->skip_fan |= (1 << 1);
-		if (reg27 & (1 << 3))
-			sio_data->skip_pwm |= (1 << 1);
+		if (reg27 & BIT(7))
+			sio_data->skip_fan |= BIT(1);
+		if (reg27 & BIT(3))
+			sio_data->skip_pwm |= BIT(1);
 
 		/* VIN5 */
-		if ((reg27 & (1 << 0)) || (reg2c & (1 << 2)))
-			sio_data->skip_in |= (1 << 5); /* No VIN5 */
+		if ((reg27 & BIT(0)) || (reg2c & BIT(2)))
+			sio_data->skip_in |= BIT(5); /* No VIN5 */
 
 		/* VIN6 */
-		if (reg27 & (1 << 1))
-			sio_data->skip_in |= (1 << 6); /* No VIN6 */
+		if (reg27 & BIT(1))
+			sio_data->skip_in |= BIT(6); /* No VIN6 */
 
 		/*
 		 * VIN7
 		 * Does not depend on bit 2 of Reg2C, contrary to datasheet.
 		 */
-		if (reg27 & (1 << 2)) {
+		if (reg27 & BIT(2)) {
 			/*
 			 * The data sheet is a bit unclear regarding the
 			 * internal voltage divider for VCCH5V. It says
@@ -2006,81 +2518,121 @@ static int __init it87_find(unsigned sho
 			 * not the case, and ask the user to report if the
 			 * resulting voltage is sane.
 			 */
-			if (!(reg2c & (1 << 1))) {
-				reg2c |= (1 << 1);
-				superio_outb(IT87_SIO_PINX2_REG, reg2c);
+			if (!(reg2c & BIT(1))) {
+				reg2c |= BIT(1);
+				superio_outb(sioaddr, IT87_SIO_PINX2_REG,
+					     reg2c);
 				pr_notice("Routing internal VCCH5V to in7.\n");
 			}
 			pr_notice("in7 routed to internal voltage divider, with external pin disabled.\n");
 			pr_notice("Please report if it displays a reasonable voltage.\n");
 		}
 
-		if (reg2c & (1 << 0))
-			sio_data->internal |= (1 << 0);
-		if (reg2c & (1 << 1))
-			sio_data->internal |= (1 << 1);
+		if (reg2c & BIT(0))
+			sio_data->internal |= BIT(0);
+		if (reg2c & BIT(1))
+			sio_data->internal |= BIT(1);
 
-		sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
+		sio_data->beep_pin = superio_inb(sioaddr,
+						 IT87_SIO_BEEP_PIN_REG) & 0x3f;
 	} else if (sio_data->type == it8603) {
 		int reg27, reg29;
 
-		superio_select(GPIO);
+		superio_select(sioaddr, GPIO);
 
-		reg27 = superio_inb(IT87_SIO_GPIO3_REG);
+		reg27 = superio_inb(sioaddr, IT87_SIO_GPIO3_REG);
 
 		/* Check if fan3 is there or not */
-		if (reg27 & (1 << 6))
-			sio_data->skip_pwm |= (1 << 2);
-		if (reg27 & (1 << 7))
-			sio_data->skip_fan |= (1 << 2);
+		if (reg27 & BIT(6))
+			sio_data->skip_pwm |= BIT(2);
+		if (reg27 & BIT(7))
+			sio_data->skip_fan |= BIT(2);
 
 		/* Check if fan2 is there or not */
-		reg29 = superio_inb(IT87_SIO_GPIO5_REG);
-		if (reg29 & (1 << 1))
-			sio_data->skip_pwm |= (1 << 1);
-		if (reg29 & (1 << 2))
-			sio_data->skip_fan |= (1 << 1);
-
-		sio_data->skip_in |= (1 << 5); /* No VIN5 */
-		sio_data->skip_in |= (1 << 6); /* No VIN6 */
+		reg29 = superio_inb(sioaddr, IT87_SIO_GPIO5_REG);
+		if (reg29 & BIT(1))
+			sio_data->skip_pwm |= BIT(1);
+		if (reg29 & BIT(2))
+			sio_data->skip_fan |= BIT(1);
 
-		sio_data->internal |= (1 << 3); /* in9 is AVCC */
+		sio_data->skip_in |= BIT(5); /* No VIN5 */
+		sio_data->skip_in |= BIT(6); /* No VIN6 */
 
-		sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
-	} else if (sio_data->type == it8620) {
+		sio_data->beep_pin = superio_inb(sioaddr,
+						 IT87_SIO_BEEP_PIN_REG) & 0x3f;
+	} else if (sio_data->type == it8620 || sio_data->type == it8628) {
 		int reg;
 
-		superio_select(GPIO);
+		superio_select(sioaddr, GPIO);
+
+		/* Check for pwm5 */
+		reg = superio_inb(sioaddr, IT87_SIO_GPIO1_REG);
+		if (reg & BIT(6))
+			sio_data->skip_pwm |= BIT(4);
 
 		/* Check for fan4, fan5 */
-		reg = superio_inb(IT87_SIO_GPIO2_REG);
-		if (!(reg & (1 << 5)))
-			sio_data->skip_fan |= (1 << 3);
-		if (!(reg & (1 << 4)))
-			sio_data->skip_fan |= (1 << 4);
+		reg = superio_inb(sioaddr, IT87_SIO_GPIO2_REG);
+		if (!(reg & BIT(5)))
+			sio_data->skip_fan |= BIT(3);
+		if (!(reg & BIT(4)))
+			sio_data->skip_fan |= BIT(4);
 
 		/* Check for pwm3, fan3 */
-		reg = superio_inb(IT87_SIO_GPIO3_REG);
-		if (reg & (1 << 6))
-			sio_data->skip_pwm |= (1 << 2);
-		if (reg & (1 << 7))
-			sio_data->skip_fan |= (1 << 2);
+		reg = superio_inb(sioaddr, IT87_SIO_GPIO3_REG);
+		if (reg & BIT(6))
+			sio_data->skip_pwm |= BIT(2);
+		if (reg & BIT(7))
+			sio_data->skip_fan |= BIT(2);
+
+		/* Check for pwm4 */
+		reg = superio_inb(sioaddr, IT87_SIO_GPIO4_REG);
+		if (!(reg & BIT(2)))
+			sio_data->skip_pwm |= BIT(3);
 
 		/* Check for pwm2, fan2 */
-		reg = superio_inb(IT87_SIO_GPIO5_REG);
-		if (reg & (1 << 1))
-			sio_data->skip_pwm |= (1 << 1);
-		if (reg & (1 << 2))
-			sio_data->skip_fan |= (1 << 1);
+		reg = superio_inb(sioaddr, IT87_SIO_GPIO5_REG);
+		if (reg & BIT(1))
+			sio_data->skip_pwm |= BIT(1);
+		if (reg & BIT(2))
+			sio_data->skip_fan |= BIT(1);
+		/* Check for pwm6, fan6 */
+		if (!(reg & BIT(7))) {
+			sio_data->skip_pwm |= BIT(5);
+			sio_data->skip_fan |= BIT(5);
+		}
 
-		sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
+		sio_data->beep_pin = superio_inb(sioaddr,
+						 IT87_SIO_BEEP_PIN_REG) & 0x3f;
 	} else {
 		int reg;
 		bool uart6;
 
-		superio_select(GPIO);
+		superio_select(sioaddr, GPIO);
 
-		reg = superio_inb(IT87_SIO_GPIO3_REG);
+		/* Check for fan4, fan5 */
+		if (has_five_fans(config)) {
+			reg = superio_inb(sioaddr, IT87_SIO_GPIO2_REG);
+			switch (sio_data->type) {
+			case it8718:
+				if (reg & BIT(5))
+					sio_data->skip_fan |= BIT(3);
+				if (reg & BIT(4))
+					sio_data->skip_fan |= BIT(4);
+				break;
+			case it8720:
+			case it8721:
+			case it8728:
+				if (!(reg & BIT(5)))
+					sio_data->skip_fan |= BIT(3);
+				if (!(reg & BIT(4)))
+					sio_data->skip_fan |= BIT(4);
+				break;
+			default:
+				break;
+			}
+		}
+
+		reg = superio_inb(sioaddr, IT87_SIO_GPIO3_REG);
 		if (!sio_data->skip_vid) {
 			/* We need at least 4 VID pins */
 			if (reg & 0x0f) {
@@ -2090,25 +2642,26 @@ static int __init it87_find(unsigned sho
 		}
 
 		/* Check if fan3 is there or not */
-		if (reg & (1 << 6))
-			sio_data->skip_pwm |= (1 << 2);
-		if (reg & (1 << 7))
-			sio_data->skip_fan |= (1 << 2);
+		if (reg & BIT(6))
+			sio_data->skip_pwm |= BIT(2);
+		if (reg & BIT(7))
+			sio_data->skip_fan |= BIT(2);
 
 		/* Check if fan2 is there or not */
-		reg = superio_inb(IT87_SIO_GPIO5_REG);
-		if (reg & (1 << 1))
-			sio_data->skip_pwm |= (1 << 1);
-		if (reg & (1 << 2))
-			sio_data->skip_fan |= (1 << 1);
+		reg = superio_inb(sioaddr, IT87_SIO_GPIO5_REG);
+		if (reg & BIT(1))
+			sio_data->skip_pwm |= BIT(1);
+		if (reg & BIT(2))
+			sio_data->skip_fan |= BIT(1);
 
-		if ((sio_data->type == it8718 || sio_data->type == it8720)
-		 && !(sio_data->skip_vid))
-			sio_data->vid_value = superio_inb(IT87_SIO_VID_REG);
+		if ((sio_data->type == it8718 || sio_data->type == it8720) &&
+		    !(sio_data->skip_vid))
+			sio_data->vid_value = superio_inb(sioaddr,
+							  IT87_SIO_VID_REG);
 
-		reg = superio_inb(IT87_SIO_PINX2_REG);
+		reg = superio_inb(sioaddr, IT87_SIO_PINX2_REG);
 
-		uart6 = sio_data->type == it8782 && (reg & (1 << 2));
+		uart6 = sio_data->type == it8782 && (reg & BIT(2));
 
 		/*
 		 * The IT8720F has no VIN7 pin, so VCCH should always be
@@ -2124,15 +2677,15 @@ static int __init it87_find(unsigned sho
 		 * If UART6 is enabled, re-route VIN7 to the internal divider
 		 * if that is not already the case.
 		 */
-		if ((sio_data->type == it8720 || uart6) && !(reg & (1 << 1))) {
-			reg |= (1 << 1);
-			superio_outb(IT87_SIO_PINX2_REG, reg);
+		if ((sio_data->type == it8720 || uart6) && !(reg & BIT(1))) {
+			reg |= BIT(1);
+			superio_outb(sioaddr, IT87_SIO_PINX2_REG, reg);
 			pr_notice("Routing internal VCCH to in7\n");
 		}
-		if (reg & (1 << 0))
-			sio_data->internal |= (1 << 0);
-		if (reg & (1 << 1))
-			sio_data->internal |= (1 << 1);
+		if (reg & BIT(0))
+			sio_data->internal |= BIT(0);
+		if (reg & BIT(1))
+			sio_data->internal |= BIT(1);
 
 		/*
 		 * On IT8782F, UART6 pins overlap with VIN5, VIN6, and VIN7.
@@ -2144,11 +2697,12 @@ static int __init it87_find(unsigned sho
 		 * temperature source here, skip_temp is preliminary.
 		 */
 		if (uart6) {
-			sio_data->skip_in |= (1 << 5) | (1 << 6);
-			sio_data->skip_temp |= (1 << 2);
+			sio_data->skip_in |= BIT(5) | BIT(6);
+			sio_data->skip_temp |= BIT(2);
 		}
 
-		sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
+		sio_data->beep_pin = superio_inb(sioaddr,
+						 IT87_SIO_BEEP_PIN_REG) & 0x3f;
 	}
 	if (sio_data->beep_pin)
 		pr_info("Beeping is supported\n");
@@ -2157,8 +2711,8 @@ static int __init it87_find(unsigned sho
 	board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
 	board_name = dmi_get_system_info(DMI_BOARD_NAME);
 	if (board_vendor && board_name) {
-		if (strcmp(board_vendor, "nVIDIA") == 0
-		 && strcmp(board_name, "FN68PT") == 0) {
+		if (strcmp(board_vendor, "nVIDIA") == 0 &&
+		    strcmp(board_name, "FN68PT") == 0) {
 			/*
 			 * On the Shuttle SN68PT, FAN_CTL2 is apparently not
 			 * connected to a fan, but to something else. One user
@@ -2168,373 +2722,15 @@ static int __init it87_find(unsigned sho
 			 * the same board is ever used in other systems.
 			 */
 			pr_info("Disabling pwm2 due to hardware constraints\n");
-			sio_data->skip_pwm = (1 << 1);
+			sio_data->skip_pwm = BIT(1);
 		}
 	}
 
 exit:
-	superio_exit();
-	return err;
-}
-
-static void it87_remove_files(struct device *dev)
-{
-	struct it87_data *data = platform_get_drvdata(pdev);
-	struct it87_sio_data *sio_data = dev_get_platdata(dev);
-	int i;
-
-	sysfs_remove_group(&dev->kobj, &it87_group);
-	for (i = 0; i < 10; i++) {
-		if (sio_data->skip_in & (1 << i))
-			continue;
-		sysfs_remove_group(&dev->kobj, &it87_group_in[i]);
-		if (it87_attributes_in_beep[i])
-			sysfs_remove_file(&dev->kobj,
-					  it87_attributes_in_beep[i]);
-	}
-	for (i = 0; i < 3; i++) {
-		if (!(data->has_temp & (1 << i)))
-			continue;
-		sysfs_remove_group(&dev->kobj, &it87_group_temp[i]);
-		if (has_temp_offset(data))
-			sysfs_remove_file(&dev->kobj,
-					  it87_attributes_temp_offset[i]);
-		if (sio_data->beep_pin)
-			sysfs_remove_file(&dev->kobj,
-					  it87_attributes_temp_beep[i]);
-	}
-	for (i = 0; i < 6; i++) {
-		if (!(data->has_fan & (1 << i)))
-			continue;
-		sysfs_remove_group(&dev->kobj, &it87_group_fan[i]);
-		if (sio_data->beep_pin)
-			sysfs_remove_file(&dev->kobj,
-					  it87_attributes_fan_beep[i]);
-		if (i < 3 && !has_16bit_fans(data))
-			sysfs_remove_file(&dev->kobj,
-					  it87_attributes_fan_div[i]);
-	}
-	for (i = 0; i < 3; i++) {
-		if (sio_data->skip_pwm & (1 << i))
-			continue;
-		sysfs_remove_group(&dev->kobj, &it87_group_pwm[i]);
-		if (has_old_autopwm(data))
-			sysfs_remove_group(&dev->kobj,
-					   &it87_group_autopwm[i]);
-	}
-	if (!sio_data->skip_vid)
-		sysfs_remove_group(&dev->kobj, &it87_group_vid);
-	sysfs_remove_group(&dev->kobj, &it87_group_label);
-}
-
-static int it87_probe(struct platform_device *pdev)
-{
-	struct it87_data *data;
-	struct resource *res;
-	struct device *dev = &pdev->dev;
-	struct it87_sio_data *sio_data = dev_get_platdata(dev);
-	int err = 0, i;
-	int enable_pwm_interface;
-	int fan_beep_need_rw;
-
-	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-	if (!devm_request_region(&pdev->dev, res->start, IT87_EC_EXTENT,
-				 DRVNAME)) {
-		dev_err(dev, "Failed to request region 0x%lx-0x%lx\n",
-			(unsigned long)res->start,
-			(unsigned long)(res->start + IT87_EC_EXTENT - 1));
-		return -EBUSY;
-	}
-
-	data = devm_kzalloc(&pdev->dev, sizeof(struct it87_data), GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	data->addr = res->start;
-	data->type = sio_data->type;
-	data->features = it87_devices[sio_data->type].features;
-	data->peci_mask = it87_devices[sio_data->type].peci_mask;
-	data->old_peci_mask = it87_devices[sio_data->type].old_peci_mask;
-	data->name = it87_devices[sio_data->type].name;
-	/*
-	 * IT8705F Datasheet 0.4.1, 3h == Version G.
-	 * IT8712F Datasheet 0.9.1, section 8.3.5 indicates 8h == Version J.
-	 * These are the first revisions with 16-bit tachometer support.
-	 */
-	switch (data->type) {
-	case it87:
-		if (sio_data->revision >= 0x03) {
-			data->features &= ~FEAT_OLD_AUTOPWM;
-			data->features |= FEAT_FAN16_CONFIG | FEAT_16BIT_FANS;
-		}
-		break;
-	case it8712:
-		if (sio_data->revision >= 0x08) {
-			data->features &= ~FEAT_OLD_AUTOPWM;
-			data->features |= FEAT_FAN16_CONFIG | FEAT_16BIT_FANS |
-					  FEAT_FIVE_FANS;
-		}
-		break;
-	default:
-		break;
-	}
-
-	/* Now, we do the remaining detection. */
-	if ((it87_read_value(data, IT87_REG_CONFIG) & 0x80)
-	 || it87_read_value(data, IT87_REG_CHIPID) != 0x90)
-		return -ENODEV;
-
-	platform_set_drvdata(pdev, data);
-
-	mutex_init(&data->update_lock);
-
-	/* Check PWM configuration */
-	enable_pwm_interface = it87_check_pwm(dev);
-
-	/* Starting with IT8721F, we handle scaling of internal voltages */
-	if (has_12mv_adc(data)) {
-		if (sio_data->internal & (1 << 0))
-			data->in_scaled |= (1 << 3);	/* in3 is AVCC */
-		if (sio_data->internal & (1 << 1))
-			data->in_scaled |= (1 << 7);	/* in7 is VSB */
-		if (sio_data->internal & (1 << 2))
-			data->in_scaled |= (1 << 8);	/* in8 is Vbat */
-		if (sio_data->internal & (1 << 3))
-			data->in_scaled |= (1 << 9);	/* in9 is AVCC */
-	} else if (sio_data->type == it8781 || sio_data->type == it8782 ||
-		   sio_data->type == it8783) {
-		if (sio_data->internal & (1 << 0))
-			data->in_scaled |= (1 << 3);	/* in3 is VCC5V */
-		if (sio_data->internal & (1 << 1))
-			data->in_scaled |= (1 << 7);	/* in7 is VCCH5V */
-	}
-
-	data->has_temp = 0x07;
-	if (sio_data->skip_temp & (1 << 2)) {
-		if (sio_data->type == it8782
-		    && !(it87_read_value(data, IT87_REG_TEMP_EXTRA) & 0x80))
-			data->has_temp &= ~(1 << 2);
-	}
-
-	/* Initialize the IT87 chip */
-	it87_init_device(pdev);
-
-	/* Register sysfs hooks */
-	err = sysfs_create_group(&dev->kobj, &it87_group);
-	if (err)
-		return err;
-
-	for (i = 0; i < 10; i++) {
-		if (sio_data->skip_in & (1 << i))
-			continue;
-		err = sysfs_create_group(&dev->kobj, &it87_group_in[i]);
-		if (err)
-			goto error;
-		if (sio_data->beep_pin && it87_attributes_in_beep[i]) {
-			err = sysfs_create_file(&dev->kobj,
-						it87_attributes_in_beep[i]);
-			if (err)
-				goto error;
-		}
-	}
-
-	for (i = 0; i < 3; i++) {
-		if (!(data->has_temp & (1 << i)))
-			continue;
-		err = sysfs_create_group(&dev->kobj, &it87_group_temp[i]);
-		if (err)
-			goto error;
-		if (has_temp_offset(data)) {
-			err = sysfs_create_file(&dev->kobj,
-						it87_attributes_temp_offset[i]);
-			if (err)
-				goto error;
-		}
-		if (sio_data->beep_pin) {
-			err = sysfs_create_file(&dev->kobj,
-						it87_attributes_temp_beep[i]);
-			if (err)
-				goto error;
-		}
-	}
-
-	/* Do not create fan files for disabled fans */
-	fan_beep_need_rw = 1;
-	for (i = 0; i < 6; i++) {
-		if (!(data->has_fan & (1 << i)))
-			continue;
-		err = sysfs_create_group(&dev->kobj, &it87_group_fan[i]);
-		if (err)
-			goto error;
-
-		if (i < 3 && !has_16bit_fans(data)) {
-			err = sysfs_create_file(&dev->kobj,
-						it87_attributes_fan_div[i]);
-			if (err)
-				goto error;
-		}
-
-		if (sio_data->beep_pin) {
-			err = sysfs_create_file(&dev->kobj,
-						it87_attributes_fan_beep[i]);
-			if (err)
-				goto error;
-			if (!fan_beep_need_rw)
-				continue;
-
-			/*
-			 * As we have a single beep enable bit for all fans,
-			 * only the first enabled fan has a writable attribute
-			 * for it.
-			 */
-			if (sysfs_chmod_file(&dev->kobj,
-					     it87_attributes_fan_beep[i],
-					     S_IRUGO | S_IWUSR))
-				dev_dbg(dev, "chmod +w fan%d_beep failed\n",
-					i + 1);
-			fan_beep_need_rw = 0;
-		}
-	}
-
-	if (enable_pwm_interface) {
-		for (i = 0; i < 3; i++) {
-			if (sio_data->skip_pwm & (1 << i))
-				continue;
-			err = sysfs_create_group(&dev->kobj,
-						 &it87_group_pwm[i]);
-			if (err)
-				goto error;
-
-			if (!has_old_autopwm(data))
-				continue;
-			err = sysfs_create_group(&dev->kobj,
-						 &it87_group_autopwm[i]);
-			if (err)
-				goto error;
-		}
-	}
-
-	if (!sio_data->skip_vid) {
-		data->vrm = vid_which_vrm();
-		/* VID reading from Super-I/O config space if available */
-		data->vid = sio_data->vid_value;
-		err = sysfs_create_group(&dev->kobj, &it87_group_vid);
-		if (err)
-			goto error;
-	}
-
-	/* Export labels for internal sensors */
-	for (i = 0; i < 4; i++) {
-		if (!(sio_data->internal & (1 << i)))
-			continue;
-		err = sysfs_create_file(&dev->kobj,
-					it87_attributes_label[i]);
-		if (err)
-			goto error;
-	}
-
-	data->hwmon_dev = hwmon_device_register(dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		goto error;
-	}
-
-	return 0;
-
-error:
-	it87_remove_files(dev);
+	superio_exit(sioaddr);
 	return err;
 }
 
-static int it87_remove(struct platform_device *pdev)
-{
-	struct it87_data *data = platform_get_drvdata(pdev);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	it87_remove_files(&pdev->dev);
-
-	return 0;
-}
-
-/*
- * Must be called with data->update_lock held, except during initialization.
- * We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks,
- * would slow down the IT87 access and should not be necessary.
- */
-static int it87_read_value(struct it87_data *data, u8 reg)
-{
-	outb_p(reg, data->addr + IT87_ADDR_REG_OFFSET);
-	return inb_p(data->addr + IT87_DATA_REG_OFFSET);
-}
-
-/*
- * Must be called with data->update_lock held, except during initialization.
- * We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks,
- * would slow down the IT87 access and should not be necessary.
- */
-static void it87_write_value(struct it87_data *data, u8 reg, u8 value)
-{
-	outb_p(reg, data->addr + IT87_ADDR_REG_OFFSET);
-	outb_p(value, data->addr + IT87_DATA_REG_OFFSET);
-}
-
-/* Return 1 if and only if the PWM interface is safe to use */
-static int it87_check_pwm(struct device *dev)
-{
-	struct it87_data *data = dev_get_drvdata(dev);
-	/*
-	 * Some BIOSes fail to correctly configure the IT87 fans. All fans off
-	 * and polarity set to active low is sign that this is the case so we
-	 * disable pwm control to protect the user.
-	 */
-	int tmp = it87_read_value(data, IT87_REG_FAN_CTL);
-	if ((tmp & 0x87) == 0) {
-		if (fix_pwm_polarity) {
-			/*
-			 * The user asks us to attempt a chip reconfiguration.
-			 * This means switching to active high polarity and
-			 * inverting all fan speed values.
-			 */
-			int i;
-			u8 pwm[3];
-
-			for (i = 0; i < 3; i++)
-				pwm[i] = it87_read_value(data,
-							 IT87_REG_PWM(i));
-
-			/*
-			 * If any fan is in automatic pwm mode, the polarity
-			 * might be correct, as suspicious as it seems, so we
-			 * better don't change anything (but still disable the
-			 * PWM interface).
-			 */
-			if (!((pwm[0] | pwm[1] | pwm[2]) & 0x80)) {
-				dev_info(dev,
-					 "Reconfiguring PWM to active high polarity\n");
-				it87_write_value(data, IT87_REG_FAN_CTL,
-						 tmp | 0x87);
-				for (i = 0; i < 3; i++)
-					it87_write_value(data,
-							 IT87_REG_PWM(i),
-							 0x7f & ~pwm[i]);
-				return 1;
-			}
-
-			dev_info(dev,
-				 "PWM configuration is too broken to be fixed\n");
-		}
-
-		dev_info(dev,
-			 "Detected broken BIOS defaults, disabling PWM interface\n");
-		return 0;
-	} else if (fix_pwm_polarity) {
-		dev_info(dev,
-			 "PWM configuration looks sane, won't touch\n");
-	}
-
-	return 1;
-}
-
 /* Called when we have found a new IT87. */
 static void it87_init_device(struct platform_device *pdev)
 {
@@ -2556,7 +2752,7 @@ static void it87_init_device(struct plat
 	 * these have separate registers for the temperature mapping and the
 	 * manual duty cycle.
 	 */
-	for (i = 0; i < 3; i++) {
+	for (i = 0; i < NUM_AUTO_PWM; i++) {
 		data->pwm_temp_map[i] = i;
 		data->pwm_duty[i] = 0x7f;	/* Full speed */
 		data->auto_pwm[i][3] = 0x7f;	/* Full speed, hard-coded */
@@ -2569,12 +2765,12 @@ static void it87_init_device(struct plat
 	 * means -1 degree C, which surprisingly doesn't trigger an alarm,
 	 * but is still confusing, so change to 127 degrees C.
 	 */
-	for (i = 0; i < 8; i++) {
+	for (i = 0; i < NUM_VIN_LIMIT; i++) {
 		tmp = it87_read_value(data, IT87_REG_VIN_MIN(i));
 		if (tmp == 0xff)
 			it87_write_value(data, IT87_REG_VIN_MIN(i), 0);
 	}
-	for (i = 0; i < 3; i++) {
+	for (i = 0; i < NUM_TEMP_LIMIT; i++) {
 		tmp = it87_read_value(data, IT87_REG_TEMP_HIGH(i));
 		if (tmp == 0xff)
 			it87_write_value(data, IT87_REG_TEMP_HIGH(i), 127);
@@ -2619,158 +2815,245 @@ static void it87_init_device(struct plat
 
 	/* Check for additional fans */
 	if (has_five_fans(data)) {
-		if (tmp & (1 << 4))
-			data->has_fan |= (1 << 3); /* fan4 enabled */
-		if (tmp & (1 << 5))
-			data->has_fan |= (1 << 4); /* fan5 enabled */
-		if (has_six_fans(data) && (tmp & (1 << 2)))
-			data->has_fan |= (1 << 5); /* fan6 enabled */
+		if (tmp & BIT(4))
+			data->has_fan |= BIT(3); /* fan4 enabled */
+		if (tmp & BIT(5))
+			data->has_fan |= BIT(4); /* fan5 enabled */
+		if (has_six_fans(data) && (tmp & BIT(2)))
+			data->has_fan |= BIT(5); /* fan6 enabled */
 	}
 
 	/* Fan input pins may be used for alternative functions */
 	data->has_fan &= ~sio_data->skip_fan;
 
+	/* Check if pwm5, pwm6 are enabled */
+	if (has_six_pwm(data)) {
+		/* The following code may be IT8620E specific */
+		tmp = it87_read_value(data, IT87_REG_FAN_DIV);
+		if ((tmp & 0xc0) == 0xc0)
+			sio_data->skip_pwm |= BIT(4);
+		if (!(tmp & BIT(3)))
+			sio_data->skip_pwm |= BIT(5);
+	}
+
 	/* Start monitoring */
 	it87_write_value(data, IT87_REG_CONFIG,
 			 (it87_read_value(data, IT87_REG_CONFIG) & 0x3e)
 			 | (update_vbat ? 0x41 : 0x01));
 }
 
-static void it87_update_pwm_ctrl(struct it87_data *data, int nr)
+/* Return 1 if and only if the PWM interface is safe to use */
+static int it87_check_pwm(struct device *dev)
 {
-	data->pwm_ctrl[nr] = it87_read_value(data, IT87_REG_PWM(nr));
-	if (has_newer_autopwm(data)) {
-		data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03;
-		data->pwm_duty[nr] = it87_read_value(data,
-						     IT87_REG_PWM_DUTY(nr));
-	} else {
-		if (data->pwm_ctrl[nr] & 0x80)	/* Automatic mode */
-			data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03;
-		else				/* Manual mode */
-			data->pwm_duty[nr] = data->pwm_ctrl[nr] & 0x7f;
-	}
+	struct it87_data *data = dev_get_drvdata(dev);
+	/*
+	 * Some BIOSes fail to correctly configure the IT87 fans. All fans off
+	 * and polarity set to active low is sign that this is the case so we
+	 * disable pwm control to protect the user.
+	 */
+	int tmp = it87_read_value(data, IT87_REG_FAN_CTL);
 
-	if (has_old_autopwm(data)) {
-		int i;
+	if ((tmp & 0x87) == 0) {
+		if (fix_pwm_polarity) {
+			/*
+			 * The user asks us to attempt a chip reconfiguration.
+			 * This means switching to active high polarity and
+			 * inverting all fan speed values.
+			 */
+			int i;
+			u8 pwm[3];
 
-		for (i = 0; i < 5 ; i++)
-			data->auto_temp[nr][i] = it87_read_value(data,
-						IT87_REG_AUTO_TEMP(nr, i));
-		for (i = 0; i < 3 ; i++)
-			data->auto_pwm[nr][i] = it87_read_value(data,
-						IT87_REG_AUTO_PWM(nr, i));
+			for (i = 0; i < ARRAY_SIZE(pwm); i++)
+				pwm[i] = it87_read_value(data,
+							 IT87_REG_PWM[i]);
+
+			/*
+			 * If any fan is in automatic pwm mode, the polarity
+			 * might be correct, as suspicious as it seems, so we
+			 * better don't change anything (but still disable the
+			 * PWM interface).
+			 */
+			if (!((pwm[0] | pwm[1] | pwm[2]) & 0x80)) {
+				dev_info(dev,
+					 "Reconfiguring PWM to active high polarity\n");
+				it87_write_value(data, IT87_REG_FAN_CTL,
+						 tmp | 0x87);
+				for (i = 0; i < 3; i++)
+					it87_write_value(data,
+							 IT87_REG_PWM[i],
+							 0x7f & ~pwm[i]);
+				return 1;
+			}
+
+			dev_info(dev,
+				 "PWM configuration is too broken to be fixed\n");
+		}
+
+		dev_info(dev,
+			 "Detected broken BIOS defaults, disabling PWM interface\n");
+		return 0;
+	} else if (fix_pwm_polarity) {
+		dev_info(dev,
+			 "PWM configuration looks sane, won't touch\n");
 	}
+
+	return 1;
 }
 
-static struct it87_data *it87_update_device(struct device *dev)
+static int it87_probe(struct platform_device *pdev)
 {
-	struct it87_data *data = dev_get_drvdata(dev);
-	int i;
+	struct it87_data *data;
+	struct resource *res;
+	struct device *dev = &pdev->dev;
+	struct it87_sio_data *sio_data = dev_get_platdata(dev);
+	int enable_pwm_interface;
+	struct device *hwmon_dev;
 
-	mutex_lock(&data->update_lock);
+	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	if (!devm_request_region(&pdev->dev, res->start, IT87_EC_EXTENT,
+				 DRVNAME)) {
+		dev_err(dev, "Failed to request region 0x%lx-0x%lx\n",
+			(unsigned long)res->start,
+			(unsigned long)(res->start + IT87_EC_EXTENT - 1));
+		return -EBUSY;
+	}
 
-	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
-	    || !data->valid) {
-		if (update_vbat) {
-			/*
-			 * Cleared after each update, so reenable.  Value
-			 * returned by this read will be previous value
-			 */
-			it87_write_value(data, IT87_REG_CONFIG,
-				it87_read_value(data, IT87_REG_CONFIG) | 0x40);
+	data = devm_kzalloc(&pdev->dev, sizeof(struct it87_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->addr = res->start;
+	data->type = sio_data->type;
+	data->features = it87_devices[sio_data->type].features;
+	data->peci_mask = it87_devices[sio_data->type].peci_mask;
+	data->old_peci_mask = it87_devices[sio_data->type].old_peci_mask;
+	/*
+	 * IT8705F Datasheet 0.4.1, 3h == Version G.
+	 * IT8712F Datasheet 0.9.1, section 8.3.5 indicates 8h == Version J.
+	 * These are the first revisions with 16-bit tachometer support.
+	 */
+	switch (data->type) {
+	case it87:
+		if (sio_data->revision >= 0x03) {
+			data->features &= ~FEAT_OLD_AUTOPWM;
+			data->features |= FEAT_FAN16_CONFIG | FEAT_16BIT_FANS;
 		}
-		for (i = 0; i <= 7; i++) {
-			data->in[i][0] =
-				it87_read_value(data, IT87_REG_VIN(i));
-			data->in[i][1] =
-				it87_read_value(data, IT87_REG_VIN_MIN(i));
-			data->in[i][2] =
-				it87_read_value(data, IT87_REG_VIN_MAX(i));
+		break;
+	case it8712:
+		if (sio_data->revision >= 0x08) {
+			data->features &= ~FEAT_OLD_AUTOPWM;
+			data->features |= FEAT_FAN16_CONFIG | FEAT_16BIT_FANS |
+					  FEAT_FIVE_FANS;
 		}
-		/* in8 (battery) has no limit registers */
-		data->in[8][0] = it87_read_value(data, IT87_REG_VIN(8));
-		if (data->type == it8603)
-			data->in[9][0] = it87_read_value(data, 0x2f);
+		break;
+	default:
+		break;
+	}
 
-		for (i = 0; i < 6; i++) {
-			/* Skip disabled fans */
-			if (!(data->has_fan & (1 << i)))
-				continue;
+	/* Now, we do the remaining detection. */
+	if ((it87_read_value(data, IT87_REG_CONFIG) & 0x80) ||
+	    it87_read_value(data, IT87_REG_CHIPID) != 0x90)
+		return -ENODEV;
 
-			data->fan[i][1] =
-				it87_read_value(data, IT87_REG_FAN_MIN[i]);
-			data->fan[i][0] = it87_read_value(data,
-				       IT87_REG_FAN[i]);
-			/* Add high byte if in 16-bit mode */
-			if (has_16bit_fans(data)) {
-				data->fan[i][0] |= it87_read_value(data,
-						IT87_REG_FANX[i]) << 8;
-				data->fan[i][1] |= it87_read_value(data,
-						IT87_REG_FANX_MIN[i]) << 8;
-			}
-		}
-		for (i = 0; i < 3; i++) {
-			if (!(data->has_temp & (1 << i)))
-				continue;
-			data->temp[i][0] =
-				it87_read_value(data, IT87_REG_TEMP(i));
-			data->temp[i][1] =
-				it87_read_value(data, IT87_REG_TEMP_LOW(i));
-			data->temp[i][2] =
-				it87_read_value(data, IT87_REG_TEMP_HIGH(i));
-			if (has_temp_offset(data))
-				data->temp[i][3] =
-				  it87_read_value(data,
-						  IT87_REG_TEMP_OFFSET[i]);
-		}
+	platform_set_drvdata(pdev, data);
 
-		/* Newer chips don't have clock dividers */
-		if ((data->has_fan & 0x07) && !has_16bit_fans(data)) {
-			i = it87_read_value(data, IT87_REG_FAN_DIV);
-			data->fan_div[0] = i & 0x07;
-			data->fan_div[1] = (i >> 3) & 0x07;
-			data->fan_div[2] = (i & 0x40) ? 3 : 1;
-		}
+	mutex_init(&data->update_lock);
 
-		data->alarms =
-			it87_read_value(data, IT87_REG_ALARM1) |
-			(it87_read_value(data, IT87_REG_ALARM2) << 8) |
-			(it87_read_value(data, IT87_REG_ALARM3) << 16);
-		data->beeps = it87_read_value(data, IT87_REG_BEEP_ENABLE);
+	/* Check PWM configuration */
+	enable_pwm_interface = it87_check_pwm(dev);
 
-		data->fan_main_ctrl = it87_read_value(data,
-				IT87_REG_FAN_MAIN_CTRL);
-		data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL);
-		for (i = 0; i < 3; i++)
-			it87_update_pwm_ctrl(data, i);
+	/* Starting with IT8721F, we handle scaling of internal voltages */
+	if (has_12mv_adc(data)) {
+		if (sio_data->internal & BIT(0))
+			data->in_scaled |= BIT(3);	/* in3 is AVCC */
+		if (sio_data->internal & BIT(1))
+			data->in_scaled |= BIT(7);	/* in7 is VSB */
+		if (sio_data->internal & BIT(2))
+			data->in_scaled |= BIT(8);	/* in8 is Vbat */
+		if (sio_data->internal & BIT(3))
+			data->in_scaled |= BIT(9);	/* in9 is AVCC */
+	} else if (sio_data->type == it8781 || sio_data->type == it8782 ||
+		   sio_data->type == it8783) {
+		if (sio_data->internal & BIT(0))
+			data->in_scaled |= BIT(3);	/* in3 is VCC5V */
+		if (sio_data->internal & BIT(1))
+			data->in_scaled |= BIT(7);	/* in7 is VCCH5V */
+	}
 
-		data->sensor = it87_read_value(data, IT87_REG_TEMP_ENABLE);
-		data->extra = it87_read_value(data, IT87_REG_TEMP_EXTRA);
-		/*
-		 * The IT8705F does not have VID capability.
-		 * The IT8718F and later don't use IT87_REG_VID for the
-		 * same purpose.
-		 */
-		if (data->type == it8712 || data->type == it8716) {
-			data->vid = it87_read_value(data, IT87_REG_VID);
-			/*
-			 * The older IT8712F revisions had only 5 VID pins,
-			 * but we assume it is always safe to read 6 bits.
-			 */
-			data->vid &= 0x3f;
-		}
-		data->last_updated = jiffies;
-		data->valid = 1;
+	data->has_temp = 0x07;
+	if (sio_data->skip_temp & BIT(2)) {
+		if (sio_data->type == it8782 &&
+		    !(it87_read_value(data, IT87_REG_TEMP_EXTRA) & 0x80))
+			data->has_temp &= ~BIT(2);
 	}
 
-	mutex_unlock(&data->update_lock);
+	data->in_internal = sio_data->internal;
+	data->has_in = 0x3ff & ~sio_data->skip_in;
 
-	return data;
+	if (has_six_temp(data)) {
+		u8 reg = it87_read_value(data, IT87_REG_TEMP456_ENABLE);
+
+		/* Check for additional temperature sensors */
+		if ((reg & 0x03) >= 0x02)
+			data->has_temp |= BIT(3);
+		if (((reg >> 2) & 0x03) >= 0x02)
+			data->has_temp |= BIT(4);
+		if (((reg >> 4) & 0x03) >= 0x02)
+			data->has_temp |= BIT(5);
+
+		/* Check for additional voltage sensors */
+		if ((reg & 0x03) == 0x01)
+			data->has_in |= BIT(10);
+		if (((reg >> 2) & 0x03) == 0x01)
+			data->has_in |= BIT(11);
+		if (((reg >> 4) & 0x03) == 0x01)
+			data->has_in |= BIT(12);
+	}
+
+	data->has_beep = !!sio_data->beep_pin;
+
+	/* Initialize the IT87 chip */
+	it87_init_device(pdev);
+
+	if (!sio_data->skip_vid) {
+		data->has_vid = true;
+		data->vrm = vid_which_vrm();
+		/* VID reading from Super-I/O config space if available */
+		data->vid = sio_data->vid_value;
+	}
+
+	/* Prepare for sysfs hooks */
+	data->groups[0] = &it87_group;
+	data->groups[1] = &it87_group_in;
+	data->groups[2] = &it87_group_temp;
+	data->groups[3] = &it87_group_fan;
+
+	if (enable_pwm_interface) {
+		data->has_pwm = BIT(ARRAY_SIZE(IT87_REG_PWM)) - 1;
+		data->has_pwm &= ~sio_data->skip_pwm;
+
+		data->groups[4] = &it87_group_pwm;
+		if (has_old_autopwm(data) || has_newer_autopwm(data))
+			data->groups[5] = &it87_group_auto_pwm;
+	}
+
+	hwmon_dev = devm_hwmon_device_register_with_groups(dev,
+					it87_devices[sio_data->type].name,
+					data, data->groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
-static int __init it87_device_add(unsigned short address,
+static struct platform_driver it87_driver = {
+	.driver = {
+		.name	= DRVNAME,
+	},
+	.probe	= it87_probe,
+};
+
+static int __init it87_device_add(int index, unsigned short address,
 				  const struct it87_sio_data *sio_data)
 {
+	struct platform_device *pdev;
 	struct resource res = {
 		.start	= address + IT87_EC_OFFSET,
 		.end	= address + IT87_EC_OFFSET + IT87_EC_EXTENT - 1,
@@ -2781,14 +3064,11 @@ static int __init it87_device_add(unsign
 
 	err = acpi_check_resource_conflict(&res);
 	if (err)
-		goto exit;
+		return err;
 
 	pdev = platform_device_alloc(DRVNAME, address);
-	if (!pdev) {
-		err = -ENOMEM;
-		pr_err("Device allocation failed\n");
-		goto exit;
-	}
+	if (!pdev)
+		return -ENOMEM;
 
 	err = platform_device_add_resources(pdev, &res, 1);
 	if (err) {
@@ -2809,44 +3089,61 @@ static int __init it87_device_add(unsign
 		goto exit_device_put;
 	}
 
+	it87_pdev[index] = pdev;
 	return 0;
 
 exit_device_put:
 	platform_device_put(pdev);
-exit:
 	return err;
 }
 
 static int __init sm_it87_init(void)
 {
-	int err;
-	unsigned short isa_address = 0;
+	int sioaddr[2] = { REG_2E, REG_4E };
 	struct it87_sio_data sio_data;
+	unsigned short isa_address;
+	bool found = false;
+	int i, err;
 
-	memset(&sio_data, 0, sizeof(struct it87_sio_data));
-	err = it87_find(&isa_address, &sio_data);
-	if (err)
-		return err;
 	err = platform_driver_register(&it87_driver);
 	if (err)
 		return err;
 
-	err = it87_device_add(isa_address, &sio_data);
-	if (err) {
-		platform_driver_unregister(&it87_driver);
-		return err;
+	for (i = 0; i < ARRAY_SIZE(sioaddr); i++) {
+		memset(&sio_data, 0, sizeof(struct it87_sio_data));
+		isa_address = 0;
+		err = it87_find(sioaddr[i], &isa_address, &sio_data);
+		if (err || isa_address == 0)
+			continue;
+
+		err = it87_device_add(i, isa_address, &sio_data);
+		if (err)
+			goto exit_dev_unregister;
+		found = true;
 	}
 
+	if (!found) {
+		err = -ENODEV;
+		goto exit_unregister;
+	}
 	return 0;
+
+exit_dev_unregister:
+	/* NULL check handled by platform_device_unregister */
+	platform_device_unregister(it87_pdev[0]);
+exit_unregister:
+	platform_driver_unregister(&it87_driver);
+	return err;
 }
 
 static void __exit sm_it87_exit(void)
 {
-	platform_device_unregister(pdev);
+	/* NULL check handled by platform_device_unregister */
+	platform_device_unregister(it87_pdev[1]);
+	platform_device_unregister(it87_pdev[0]);
 	platform_driver_unregister(&it87_driver);
 }
 
-
 MODULE_AUTHOR("Chris Gauthron, Jean Delvare <jdelvare@suse.de>");
 MODULE_DESCRIPTION("IT8705F/IT871xF/IT872xF hardware monitoring driver");
 module_param(update_vbat, bool, 0);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwmon/Kconfig linux-libre-4.7-gnu/drivers/hwmon/Kconfig
--- linux-libre-4.6-gnu/drivers/hwmon/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hwmon/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -288,7 +288,7 @@ config SENSORS_K10TEMP
 
 config SENSORS_FAM15H_POWER
 	tristate "AMD Family 15h processor power"
-	depends on X86 && PCI
+	depends on X86 && PCI && CPU_SUP_AMD
 	help
 	  If you say yes here you get support for processor power
 	  information of your AMD family 15h CPU.
@@ -621,7 +621,8 @@ config SENSORS_IT87
 	  If you say yes here you get support for ITE IT8705F, IT8712F, IT8716F,
 	  IT8718F, IT8720F, IT8721F, IT8726F, IT8728F, IT8732F, IT8758E,
 	  IT8771E, IT8772E, IT8781F, IT8782F, IT8783E/F, IT8786E, IT8790E,
-	  IT8603E, IT8620E, and IT8623E sensor chips, and the SiS950 clone.
+	  IT8603E, IT8620E, IT8623E, and IT8628E sensor chips, and the SiS950
+	  clone.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called it87.
@@ -821,6 +822,16 @@ config SENSORS_MAX197
 	  This driver can also be built as a module. If so, the module
 	  will be called max197.
 
+config SENSORS_MAX31722
+tristate "MAX31722 temperature sensor"
+	depends on SPI
+	help
+	  Support for the Maxim Integrated MAX31722/MAX31723 digital
+	  thermometers/thermostats operating over an SPI interface.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called max31722.
+
 config SENSORS_MAX6639
 	tristate "Maxim MAX6639 sensor chip"
 	depends on I2C
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwmon/lm75.c linux-libre-4.7-gnu/drivers/hwmon/lm75.c
--- linux-libre-4.6-gnu/drivers/hwmon/lm75.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hwmon/lm75.c	2016-07-24 15:23:50.000000000 -0400
@@ -77,7 +77,6 @@ static const u8 LM75_REG_TEMP[3] = {
 struct lm75_data {
 	struct i2c_client	*client;
 	struct device		*hwmon_dev;
-	struct thermal_zone_device	*tz;
 	struct mutex		update_lock;
 	u8			orig_conf;
 	u8			resolution;	/* In bits, between 9 and 12 */
@@ -306,11 +305,9 @@ lm75_probe(struct i2c_client *client, co
 	if (IS_ERR(data->hwmon_dev))
 		return PTR_ERR(data->hwmon_dev);
 
-	data->tz = thermal_zone_of_sensor_register(data->hwmon_dev, 0,
-						   data->hwmon_dev,
-						   &lm75_of_thermal_ops);
-	if (IS_ERR(data->tz))
-		data->tz = NULL;
+	devm_thermal_zone_of_sensor_register(data->hwmon_dev, 0,
+					     data->hwmon_dev,
+					     &lm75_of_thermal_ops);
 
 	dev_info(dev, "%s: sensor '%s'\n",
 		 dev_name(data->hwmon_dev), client->name);
@@ -322,7 +319,6 @@ static int lm75_remove(struct i2c_client
 {
 	struct lm75_data *data = i2c_get_clientdata(client);
 
-	thermal_zone_of_sensor_unregister(data->hwmon_dev, data->tz);
 	hwmon_device_unregister(data->hwmon_dev);
 	lm75_write_value(client, LM75_REG_CONF, data->orig_conf);
 	return 0;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwmon/lm90.c linux-libre-4.7-gnu/drivers/hwmon/lm90.c
--- linux-libre-4.6-gnu/drivers/hwmon/lm90.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hwmon/lm90.c	2016-07-24 15:23:50.000000000 -0400
@@ -375,7 +375,7 @@ struct lm90_data {
 	int kind;
 	u32 flags;
 
-	int update_interval;	/* in milliseconds */
+	unsigned int update_interval; /* in milliseconds */
 
 	u8 config_orig;		/* Original configuration register value */
 	u8 convrate_orig;	/* Original conversion rate register value */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwmon/Makefile linux-libre-4.7-gnu/drivers/hwmon/Makefile
--- linux-libre-4.6-gnu/drivers/hwmon/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hwmon/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -112,6 +112,7 @@ obj-$(CONFIG_SENSORS_MAX16065)	+= max160
 obj-$(CONFIG_SENSORS_MAX1619)	+= max1619.o
 obj-$(CONFIG_SENSORS_MAX1668)	+= max1668.o
 obj-$(CONFIG_SENSORS_MAX197)	+= max197.o
+obj-$(CONFIG_SENSORS_MAX31722)	+= max31722.o
 obj-$(CONFIG_SENSORS_MAX6639)	+= max6639.o
 obj-$(CONFIG_SENSORS_MAX6642)	+= max6642.o
 obj-$(CONFIG_SENSORS_MAX6650)	+= max6650.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwmon/max31722.c linux-libre-4.7-gnu/drivers/hwmon/max31722.c
--- linux-libre-4.6-gnu/drivers/hwmon/max31722.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/hwmon/max31722.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,165 @@
+/*
+ * max31722 - hwmon driver for Maxim Integrated MAX31722/MAX31723 SPI
+ * digital thermometer and thermostats.
+ *
+ * Copyright (c) 2016, Intel Corporation.
+ *
+ * This file is subject to the terms and conditions of version 2 of
+ * the GNU General Public License. See the file COPYING in the main
+ * directory of this archive for more details.
+ */
+
+#include <linux/acpi.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+
+#define MAX31722_REG_CFG				0x00
+#define MAX31722_REG_TEMP_LSB				0x01
+
+#define MAX31722_MODE_CONTINUOUS			0x00
+#define MAX31722_MODE_STANDBY				0x01
+#define MAX31722_MODE_MASK				0xFE
+#define MAX31722_RESOLUTION_12BIT			0x06
+#define MAX31722_WRITE_MASK				0x80
+
+struct max31722_data {
+	struct device *hwmon_dev;
+	struct spi_device *spi_device;
+	u8 mode;
+};
+
+static int max31722_set_mode(struct max31722_data *data, u8 mode)
+{
+	int ret;
+	struct spi_device *spi = data->spi_device;
+	u8 buf[2] = {
+		MAX31722_REG_CFG | MAX31722_WRITE_MASK,
+		(data->mode & MAX31722_MODE_MASK) | mode
+	};
+
+	ret = spi_write(spi, &buf, sizeof(buf));
+	if (ret < 0) {
+		dev_err(&spi->dev, "failed to set sensor mode.\n");
+		return ret;
+	}
+	data->mode = (data->mode & MAX31722_MODE_MASK) | mode;
+
+	return 0;
+}
+
+static ssize_t max31722_show_temp(struct device *dev,
+				  struct device_attribute *attr,
+				  char *buf)
+{
+	ssize_t ret;
+	struct max31722_data *data = dev_get_drvdata(dev);
+
+	ret = spi_w8r16(data->spi_device, MAX31722_REG_TEMP_LSB);
+	if (ret < 0)
+		return ret;
+	/* Keep 12 bits and multiply by the scale of 62.5 millidegrees/bit. */
+	return sprintf(buf, "%d\n", (s16)le16_to_cpu(ret) * 125 / 32);
+}
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO,
+			  max31722_show_temp, NULL, 0);
+
+static struct attribute *max31722_attrs[] = {
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	NULL,
+};
+
+ATTRIBUTE_GROUPS(max31722);
+
+static int max31722_probe(struct spi_device *spi)
+{
+	int ret;
+	struct max31722_data *data;
+
+	data = devm_kzalloc(&spi->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	spi_set_drvdata(spi, data);
+	data->spi_device = spi;
+	/*
+	 * Set SD bit to 0 so we can have continuous measurements.
+	 * Set resolution to 12 bits for maximum precision.
+	 */
+	data->mode = MAX31722_MODE_CONTINUOUS | MAX31722_RESOLUTION_12BIT;
+	ret = max31722_set_mode(data, MAX31722_MODE_CONTINUOUS);
+	if (ret < 0)
+		return ret;
+
+	data->hwmon_dev = hwmon_device_register_with_groups(&spi->dev,
+							    spi->modalias,
+							    data,
+							    max31722_groups);
+	if (IS_ERR(data->hwmon_dev)) {
+		max31722_set_mode(data, MAX31722_MODE_STANDBY);
+		return PTR_ERR(data->hwmon_dev);
+	}
+
+	return 0;
+}
+
+static int max31722_remove(struct spi_device *spi)
+{
+	struct max31722_data *data = spi_get_drvdata(spi);
+
+	hwmon_device_unregister(data->hwmon_dev);
+
+	return max31722_set_mode(data, MAX31722_MODE_STANDBY);
+}
+
+static int __maybe_unused max31722_suspend(struct device *dev)
+{
+	struct spi_device *spi_device = to_spi_device(dev);
+	struct max31722_data *data = spi_get_drvdata(spi_device);
+
+	return max31722_set_mode(data, MAX31722_MODE_STANDBY);
+}
+
+static int __maybe_unused max31722_resume(struct device *dev)
+{
+	struct spi_device *spi_device = to_spi_device(dev);
+	struct max31722_data *data = spi_get_drvdata(spi_device);
+
+	return max31722_set_mode(data, MAX31722_MODE_CONTINUOUS);
+}
+
+static SIMPLE_DEV_PM_OPS(max31722_pm_ops, max31722_suspend, max31722_resume);
+
+static const struct spi_device_id max31722_spi_id[] = {
+	{"max31722", 0},
+	{"max31723", 0},
+	{}
+};
+
+static const struct acpi_device_id __maybe_unused max31722_acpi_id[] = {
+	{"MAX31722", 0},
+	{"MAX31723", 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(spi, max31722_spi_id);
+
+static struct spi_driver max31722_driver = {
+	.driver = {
+		.name = "max31722",
+		.pm = &max31722_pm_ops,
+		.acpi_match_table = ACPI_PTR(max31722_acpi_id),
+	},
+	.probe =            max31722_probe,
+	.remove =           max31722_remove,
+	.id_table =         max31722_spi_id,
+};
+
+module_spi_driver(max31722_driver);
+
+MODULE_AUTHOR("Tiberiu Breana <tiberiu.a.breana@intel.com>");
+MODULE_DESCRIPTION("max31722 sensor driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwmon/ntc_thermistor.c linux-libre-4.7-gnu/drivers/hwmon/ntc_thermistor.c
--- linux-libre-4.6-gnu/drivers/hwmon/ntc_thermistor.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hwmon/ntc_thermistor.c	2016-07-24 15:23:50.000000000 -0400
@@ -259,7 +259,6 @@ struct ntc_data {
 	struct device *dev;
 	int n_comp;
 	char name[PLATFORM_NAME_SIZE];
-	struct thermal_zone_device *tz;
 };
 
 #if defined(CONFIG_OF) && IS_ENABLED(CONFIG_IIO)
@@ -579,6 +578,7 @@ static const struct thermal_zone_of_devi
 
 static int ntc_thermistor_probe(struct platform_device *pdev)
 {
+	struct thermal_zone_device *tz;
 	const struct of_device_id *of_id =
 			of_match_device(of_match_ptr(ntc_match), &pdev->dev);
 	const struct platform_device_id *pdev_id;
@@ -677,12 +677,10 @@ static int ntc_thermistor_probe(struct p
 	dev_info(&pdev->dev, "Thermistor type: %s successfully probed.\n",
 								pdev_id->name);
 
-	data->tz = thermal_zone_of_sensor_register(data->dev, 0, data->dev,
-						   &ntc_of_thermal_ops);
-	if (IS_ERR(data->tz)) {
+	tz = devm_thermal_zone_of_sensor_register(data->dev, 0, data->dev,
+						  &ntc_of_thermal_ops);
+	if (IS_ERR(tz))
 		dev_dbg(&pdev->dev, "Failed to register to thermal fw.\n");
-		data->tz = NULL;
-	}
 
 	return 0;
 err_after_sysfs:
@@ -700,8 +698,6 @@ static int ntc_thermistor_remove(struct
 	sysfs_remove_group(&data->dev->kobj, &ntc_attr_group);
 	ntc_iio_channel_release(pdata);
 
-	thermal_zone_of_sensor_unregister(data->dev, data->tz);
-
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwmon/pwm-fan.c linux-libre-4.7-gnu/drivers/hwmon/pwm-fan.c
--- linux-libre-4.6-gnu/drivers/hwmon/pwm-fan.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hwmon/pwm-fan.c	2016-07-24 15:23:50.000000000 -0400
@@ -40,15 +40,18 @@ struct pwm_fan_ctx {
 
 static int  __set_pwm(struct pwm_fan_ctx *ctx, unsigned long pwm)
 {
+	struct pwm_args pargs;
 	unsigned long duty;
 	int ret = 0;
 
+	pwm_get_args(ctx->pwm, &pargs);
+
 	mutex_lock(&ctx->lock);
 	if (ctx->pwm_value == pwm)
 		goto exit_set_pwm_err;
 
-	duty = DIV_ROUND_UP(pwm * (ctx->pwm->period - 1), MAX_PWM);
-	ret = pwm_config(ctx->pwm, duty, ctx->pwm->period);
+	duty = DIV_ROUND_UP(pwm * (pargs.period - 1), MAX_PWM);
+	ret = pwm_config(ctx->pwm, duty, pargs.period);
 	if (ret)
 		goto exit_set_pwm_err;
 
@@ -215,6 +218,7 @@ static int pwm_fan_probe(struct platform
 {
 	struct thermal_cooling_device *cdev;
 	struct pwm_fan_ctx *ctx;
+	struct pwm_args pargs;
 	struct device *hwmon;
 	int duty_cycle;
 	int ret;
@@ -233,11 +237,19 @@ static int pwm_fan_probe(struct platform
 
 	platform_set_drvdata(pdev, ctx);
 
+	/*
+	 * FIXME: pwm_apply_args() should be removed when switching to the
+	 * atomic PWM API.
+	 */
+	pwm_apply_args(ctx->pwm);
+
 	/* Set duty cycle to maximum allowed */
-	duty_cycle = ctx->pwm->period - 1;
+	pwm_get_args(ctx->pwm, &pargs);
+
+	duty_cycle = pargs.period - 1;
 	ctx->pwm_value = MAX_PWM;
 
-	ret = pwm_config(ctx->pwm, duty_cycle, ctx->pwm->period);
+	ret = pwm_config(ctx->pwm, duty_cycle, pargs.period);
 	if (ret) {
 		dev_err(&pdev->dev, "Failed to configure PWM\n");
 		return ret;
@@ -303,14 +315,16 @@ static int pwm_fan_suspend(struct device
 static int pwm_fan_resume(struct device *dev)
 {
 	struct pwm_fan_ctx *ctx = dev_get_drvdata(dev);
+	struct pwm_args pargs;
 	unsigned long duty;
 	int ret;
 
 	if (ctx->pwm_value == 0)
 		return 0;
 
-	duty = DIV_ROUND_UP(ctx->pwm_value * (ctx->pwm->period - 1), MAX_PWM);
-	ret = pwm_config(ctx->pwm, duty, ctx->pwm->period);
+	pwm_get_args(ctx->pwm, &pargs);
+	duty = DIV_ROUND_UP(ctx->pwm_value * (pargs.period - 1), MAX_PWM);
+	ret = pwm_config(ctx->pwm, duty, pargs.period);
 	if (ret)
 		return ret;
 	return pwm_enable(ctx->pwm);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwmon/sch5636.c linux-libre-4.7-gnu/drivers/hwmon/sch5636.c
--- linux-libre-4.6-gnu/drivers/hwmon/sch5636.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hwmon/sch5636.c	2016-07-24 15:23:50.000000000 -0400
@@ -449,7 +449,7 @@ static int sch5636_probe(struct platform
 		}
 		revision[i] = val;
 	}
-	pr_info("Found %s chip at %#hx, revison: %d.%02d\n", DEVNAME,
+	pr_info("Found %s chip at %#hx, revision: %d.%02d\n", DEVNAME,
 		data->addr, revision[0], revision[1]);
 
 	/* Read all temp + fan ctrl registers to determine which are active */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwmon/scpi-hwmon.c linux-libre-4.7-gnu/drivers/hwmon/scpi-hwmon.c
--- linux-libre-4.6-gnu/drivers/hwmon/scpi-hwmon.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hwmon/scpi-hwmon.c	2016-07-24 15:23:50.000000000 -0400
@@ -31,10 +31,8 @@ struct sensor_data {
 };
 
 struct scpi_thermal_zone {
-	struct list_head list;
 	int sensor_id;
 	struct scpi_sensors *scpi_sensors;
-	struct thermal_zone_device *tzd;
 };
 
 struct scpi_sensors {
@@ -92,20 +90,6 @@ scpi_show_label(struct device *dev, stru
 	return sprintf(buf, "%s\n", sensor->info.name);
 }
 
-static void
-unregister_thermal_zones(struct platform_device *pdev,
-			 struct scpi_sensors *scpi_sensors)
-{
-	struct list_head *pos;
-
-	list_for_each(pos, &scpi_sensors->thermal_zones) {
-		struct scpi_thermal_zone *zone;
-
-		zone = list_entry(pos, struct scpi_thermal_zone, list);
-		thermal_zone_of_sensor_unregister(&pdev->dev, zone->tzd);
-	}
-}
-
 static struct thermal_zone_of_device_ops scpi_sensor_ops = {
 	.get_temp = scpi_read_temp,
 };
@@ -118,7 +102,7 @@ static int scpi_hwmon_probe(struct platf
 	struct scpi_ops *scpi_ops;
 	struct device *hwdev, *dev = &pdev->dev;
 	struct scpi_sensors *scpi_sensors;
-	int ret, idx;
+	int idx, ret;
 
 	scpi_ops = get_scpi_ops();
 	if (!scpi_ops)
@@ -232,48 +216,35 @@ static int scpi_hwmon_probe(struct platf
 	INIT_LIST_HEAD(&scpi_sensors->thermal_zones);
 	for (i = 0; i < nr_sensors; i++) {
 		struct sensor_data *sensor = &scpi_sensors->data[i];
+		struct thermal_zone_device *z;
 		struct scpi_thermal_zone *zone;
 
 		if (sensor->info.class != TEMPERATURE)
 			continue;
 
 		zone = devm_kzalloc(dev, sizeof(*zone), GFP_KERNEL);
-		if (!zone) {
-			ret = -ENOMEM;
-			goto unregister_tzd;
-		}
+		if (!zone)
+			return -ENOMEM;
 
 		zone->sensor_id = i;
 		zone->scpi_sensors = scpi_sensors;
-		zone->tzd = thermal_zone_of_sensor_register(dev,
-				sensor->info.sensor_id, zone, &scpi_sensor_ops);
+		z = devm_thermal_zone_of_sensor_register(dev,
+							 sensor->info.sensor_id,
+							 zone,
+							 &scpi_sensor_ops);
 		/*
 		 * The call to thermal_zone_of_sensor_register returns
 		 * an error for sensors that are not associated with
 		 * any thermal zones or if the thermal subsystem is
 		 * not configured.
 		 */
-		if (IS_ERR(zone->tzd)) {
+		if (IS_ERR(z)) {
 			devm_kfree(dev, zone);
 			continue;
 		}
-		list_add(&zone->list, &scpi_sensors->thermal_zones);
 	}
 
 	return 0;
-
-unregister_tzd:
-	unregister_thermal_zones(pdev, scpi_sensors);
-	return ret;
-}
-
-static int scpi_hwmon_remove(struct platform_device *pdev)
-{
-	struct scpi_sensors *scpi_sensors = platform_get_drvdata(pdev);
-
-	unregister_thermal_zones(pdev, scpi_sensors);
-
-	return 0;
 }
 
 static const struct of_device_id scpi_of_match[] = {
@@ -288,7 +259,6 @@ static struct platform_driver scpi_hwmon
 		.of_match_table = scpi_of_match,
 	},
 	.probe		= scpi_hwmon_probe,
-	.remove		= scpi_hwmon_remove,
 };
 module_platform_driver(scpi_hwmon_platdrv);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwmon/tmp102.c linux-libre-4.7-gnu/drivers/hwmon/tmp102.c
--- linux-libre-4.6-gnu/drivers/hwmon/tmp102.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hwmon/tmp102.c	2016-07-24 15:23:50.000000000 -0400
@@ -53,7 +53,6 @@
 struct tmp102 {
 	struct i2c_client *client;
 	struct device *hwmon_dev;
-	struct thermal_zone_device *tz;
 	struct mutex lock;
 	u16 config_orig;
 	unsigned long last_update;
@@ -232,10 +231,8 @@ static int tmp102_probe(struct i2c_clien
 		goto fail_restore_config;
 	}
 	tmp102->hwmon_dev = hwmon_dev;
-	tmp102->tz = thermal_zone_of_sensor_register(hwmon_dev, 0, hwmon_dev,
-						     &tmp102_of_thermal_ops);
-	if (IS_ERR(tmp102->tz))
-		tmp102->tz = NULL;
+	devm_thermal_zone_of_sensor_register(hwmon_dev, 0, hwmon_dev,
+					     &tmp102_of_thermal_ops);
 
 	dev_info(dev, "initialized\n");
 
@@ -251,7 +248,6 @@ static int tmp102_remove(struct i2c_clie
 {
 	struct tmp102 *tmp102 = i2c_get_clientdata(client);
 
-	thermal_zone_of_sensor_unregister(tmp102->hwmon_dev, tmp102->tz);
 	hwmon_device_unregister(tmp102->hwmon_dev);
 
 	/* Stop monitoring if device was stopped originally */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwspinlock/hwspinlock_core.c linux-libre-4.7-gnu/drivers/hwspinlock/hwspinlock_core.c
--- linux-libre-4.6-gnu/drivers/hwspinlock/hwspinlock_core.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hwspinlock/hwspinlock_core.c	2016-07-24 15:23:50.000000000 -0400
@@ -313,7 +313,7 @@ int of_hwspin_lock_get_id(struct device_
 		hwlock = radix_tree_deref_slot(slot);
 		if (unlikely(!hwlock))
 			continue;
-		if (radix_tree_is_indirect_ptr(hwlock)) {
+		if (radix_tree_deref_retry(hwlock)) {
 			slot = radix_tree_iter_retry(&iter);
 			continue;
 		}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwtracing/coresight/coresight.c linux-libre-4.7-gnu/drivers/hwtracing/coresight/coresight.c
--- linux-libre-4.6-gnu/drivers/hwtracing/coresight/coresight.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hwtracing/coresight/coresight.c	2016-07-24 15:23:50.000000000 -0400
@@ -43,7 +43,15 @@ struct coresight_node {
  * When operating Coresight drivers from the sysFS interface, only a single
  * path can exist from a tracer (associated to a CPU) to a sink.
  */
-static DEFINE_PER_CPU(struct list_head *, sysfs_path);
+static DEFINE_PER_CPU(struct list_head *, tracer_path);
+
+/*
+ * As of this writing only a single STM can be found in CS topologies.  Since
+ * there is no way to know if we'll ever see more and what kind of
+ * configuration they will enact, for the time being only define a single path
+ * for STM.
+ */
+static struct list_head *stm_path;
 
 static int coresight_id_match(struct device *dev, void *data)
 {
@@ -257,15 +265,27 @@ static void coresight_disable_source(str
 
 void coresight_disable_path(struct list_head *path)
 {
+	u32 type;
 	struct coresight_node *nd;
 	struct coresight_device *csdev, *parent, *child;
 
 	list_for_each_entry(nd, path, link) {
 		csdev = nd->csdev;
+		type = csdev->type;
 
-		switch (csdev->type) {
+		/*
+		 * ETF devices are tricky... They can be a link or a sink,
+		 * depending on how they are configured.  If an ETF has been
+		 * "activated" it will be configured as a sink, otherwise
+		 * go ahead with the link configuration.
+		 */
+		if (type == CORESIGHT_DEV_TYPE_LINKSINK)
+			type = (csdev == coresight_get_sink(path)) ?
+						CORESIGHT_DEV_TYPE_SINK :
+						CORESIGHT_DEV_TYPE_LINK;
+
+		switch (type) {
 		case CORESIGHT_DEV_TYPE_SINK:
-		case CORESIGHT_DEV_TYPE_LINKSINK:
 			coresight_disable_sink(csdev);
 			break;
 		case CORESIGHT_DEV_TYPE_SOURCE:
@@ -286,15 +306,27 @@ int coresight_enable_path(struct list_he
 {
 
 	int ret = 0;
+	u32 type;
 	struct coresight_node *nd;
 	struct coresight_device *csdev, *parent, *child;
 
 	list_for_each_entry_reverse(nd, path, link) {
 		csdev = nd->csdev;
+		type = csdev->type;
 
-		switch (csdev->type) {
+		/*
+		 * ETF devices are tricky... They can be a link or a sink,
+		 * depending on how they are configured.  If an ETF has been
+		 * "activated" it will be configured as a sink, otherwise
+		 * go ahead with the link configuration.
+		 */
+		if (type == CORESIGHT_DEV_TYPE_LINKSINK)
+			type = (csdev == coresight_get_sink(path)) ?
+						CORESIGHT_DEV_TYPE_SINK :
+						CORESIGHT_DEV_TYPE_LINK;
+
+		switch (type) {
 		case CORESIGHT_DEV_TYPE_SINK:
-		case CORESIGHT_DEV_TYPE_LINKSINK:
 			ret = coresight_enable_sink(csdev, mode);
 			if (ret)
 				goto err;
@@ -353,7 +385,6 @@ static int _coresight_build_path(struct
 	int i;
 	bool found = false;
 	struct coresight_node *node;
-	struct coresight_connection *conn;
 
 	/* An activated sink has been found.  Enqueue the element */
 	if ((csdev->type == CORESIGHT_DEV_TYPE_SINK ||
@@ -362,8 +393,9 @@ static int _coresight_build_path(struct
 
 	/* Not a sink - recursively explore each port found on this element */
 	for (i = 0; i < csdev->nr_outport; i++) {
-		conn = &csdev->conns[i];
-		if (_coresight_build_path(conn->child_dev, path) == 0) {
+		struct coresight_device *child_dev = csdev->conns[i].child_dev;
+
+		if (child_dev && _coresight_build_path(child_dev, path) == 0) {
 			found = true;
 			break;
 		}
@@ -393,6 +425,7 @@ out:
 struct list_head *coresight_build_path(struct coresight_device *csdev)
 {
 	struct list_head *path;
+	int rc;
 
 	path = kzalloc(sizeof(struct list_head), GFP_KERNEL);
 	if (!path)
@@ -400,9 +433,10 @@ struct list_head *coresight_build_path(s
 
 	INIT_LIST_HEAD(path);
 
-	if (_coresight_build_path(csdev, path)) {
+	rc = _coresight_build_path(csdev, path);
+	if (rc) {
 		kfree(path);
-		path = NULL;
+		return ERR_PTR(rc);
 	}
 
 	return path;
@@ -432,24 +466,52 @@ void coresight_release_path(struct list_
 	path = NULL;
 }
 
+/** coresight_validate_source - make sure a source has the right credentials
+ *  @csdev:	the device structure for a source.
+ *  @function:	the function this was called from.
+ *
+ * Assumes the coresight_mutex is held.
+ */
+static int coresight_validate_source(struct coresight_device *csdev,
+				     const char *function)
+{
+	u32 type, subtype;
+
+	type = csdev->type;
+	subtype = csdev->subtype.source_subtype;
+
+	if (type != CORESIGHT_DEV_TYPE_SOURCE) {
+		dev_err(&csdev->dev, "wrong device type in %s\n", function);
+		return -EINVAL;
+	}
+
+	if (subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_PROC &&
+	    subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE) {
+		dev_err(&csdev->dev, "wrong device subtype in %s\n", function);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 int coresight_enable(struct coresight_device *csdev)
 {
-	int ret = 0;
-	int cpu;
+	int cpu, ret = 0;
 	struct list_head *path;
 
 	mutex_lock(&coresight_mutex);
-	if (csdev->type != CORESIGHT_DEV_TYPE_SOURCE) {
-		ret = -EINVAL;
-		dev_err(&csdev->dev, "wrong device type in %s\n", __func__);
+
+	ret = coresight_validate_source(csdev, __func__);
+	if (ret)
 		goto out;
-	}
+
 	if (csdev->enable)
 		goto out;
 
 	path = coresight_build_path(csdev);
-	if (!path) {
+	if (IS_ERR(path)) {
 		pr_err("building path(s) failed\n");
+		ret = PTR_ERR(path);
 		goto out;
 	}
 
@@ -461,15 +523,25 @@ int coresight_enable(struct coresight_de
 	if (ret)
 		goto err_source;
 
-	/*
-	 * When working from sysFS it is important to keep track
-	 * of the paths that were created so that they can be
-	 * undone in 'coresight_disable()'.  Since there can only
-	 * be a single session per tracer (when working from sysFS)
-	 * a per-cpu variable will do just fine.
-	 */
-	cpu = source_ops(csdev)->cpu_id(csdev);
-	per_cpu(sysfs_path, cpu) = path;
+	switch (csdev->subtype.source_subtype) {
+	case CORESIGHT_DEV_SUBTYPE_SOURCE_PROC:
+		/*
+		 * When working from sysFS it is important to keep track
+		 * of the paths that were created so that they can be
+		 * undone in 'coresight_disable()'.  Since there can only
+		 * be a single session per tracer (when working from sysFS)
+		 * a per-cpu variable will do just fine.
+		 */
+		cpu = source_ops(csdev)->cpu_id(csdev);
+		per_cpu(tracer_path, cpu) = path;
+		break;
+	case CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE:
+		stm_path = path;
+		break;
+	default:
+		/* We can't be here */
+		break;
+	}
 
 out:
 	mutex_unlock(&coresight_mutex);
@@ -486,23 +558,36 @@ EXPORT_SYMBOL_GPL(coresight_enable);
 
 void coresight_disable(struct coresight_device *csdev)
 {
-	int cpu;
-	struct list_head *path;
+	int cpu, ret;
+	struct list_head *path = NULL;
 
 	mutex_lock(&coresight_mutex);
-	if (csdev->type != CORESIGHT_DEV_TYPE_SOURCE) {
-		dev_err(&csdev->dev, "wrong device type in %s\n", __func__);
+
+	ret = coresight_validate_source(csdev, __func__);
+	if (ret)
 		goto out;
-	}
+
 	if (!csdev->enable)
 		goto out;
 
-	cpu = source_ops(csdev)->cpu_id(csdev);
-	path = per_cpu(sysfs_path, cpu);
+	switch (csdev->subtype.source_subtype) {
+	case CORESIGHT_DEV_SUBTYPE_SOURCE_PROC:
+		cpu = source_ops(csdev)->cpu_id(csdev);
+		path = per_cpu(tracer_path, cpu);
+		per_cpu(tracer_path, cpu) = NULL;
+		break;
+	case CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE:
+		path = stm_path;
+		stm_path = NULL;
+		break;
+	default:
+		/* We can't be here */
+		break;
+	}
+
 	coresight_disable_source(csdev);
 	coresight_disable_path(path);
 	coresight_release_path(path);
-	per_cpu(sysfs_path, cpu) = NULL;
 
 out:
 	mutex_unlock(&coresight_mutex);
@@ -514,7 +599,7 @@ static ssize_t enable_sink_show(struct d
 {
 	struct coresight_device *csdev = to_coresight_device(dev);
 
-	return scnprintf(buf, PAGE_SIZE, "%u\n", (unsigned)csdev->activated);
+	return scnprintf(buf, PAGE_SIZE, "%u\n", csdev->activated);
 }
 
 static ssize_t enable_sink_store(struct device *dev,
@@ -544,7 +629,7 @@ static ssize_t enable_source_show(struct
 {
 	struct coresight_device *csdev = to_coresight_device(dev);
 
-	return scnprintf(buf, PAGE_SIZE, "%u\n", (unsigned)csdev->enable);
+	return scnprintf(buf, PAGE_SIZE, "%u\n", csdev->enable);
 }
 
 static ssize_t enable_source_store(struct device *dev,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwtracing/coresight/coresight-etb10.c linux-libre-4.7-gnu/drivers/hwtracing/coresight/coresight-etb10.c
--- linux-libre-4.6-gnu/drivers/hwtracing/coresight/coresight-etb10.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hwtracing/coresight/coresight-etb10.c	2016-07-24 15:23:50.000000000 -0400
@@ -71,26 +71,6 @@
 #define ETB_FRAME_SIZE_WORDS	4
 
 /**
- * struct cs_buffer - keep track of a recording session' specifics
- * @cur:	index of the current buffer
- * @nr_pages:	max number of pages granted to us
- * @offset:	offset within the current buffer
- * @data_size:	how much we collected in this run
- * @lost:	other than zero if we had a HW buffer wrap around
- * @snapshot:	is this run in snapshot mode
- * @data_pages:	a handle the ring buffer
- */
-struct cs_buffers {
-	unsigned int		cur;
-	unsigned int		nr_pages;
-	unsigned long		offset;
-	local_t			data_size;
-	local_t			lost;
-	bool			snapshot;
-	void			**data_pages;
-};
-
-/**
  * struct etb_drvdata - specifics associated to an ETB component
  * @base:	memory mapped base address for this component.
  * @dev:	the device entity associated to this component.
@@ -440,7 +420,7 @@ static void etb_update_buffer(struct cor
 		u32 mask = ~(ETB_FRAME_SIZE_WORDS - 1);
 
 		/* The new read pointer must be frame size aligned */
-		to_read -= handle->size & mask;
+		to_read = handle->size & mask;
 		/*
 		 * Move the RAM read pointer up, keeping in mind that
 		 * everything is in frame size units.
@@ -448,7 +428,8 @@ static void etb_update_buffer(struct cor
 		read_ptr = (write_ptr + drvdata->buffer_depth) -
 					to_read / ETB_FRAME_SIZE_WORDS;
 		/* Wrap around if need be*/
-		read_ptr &= ~(drvdata->buffer_depth - 1);
+		if (read_ptr > (drvdata->buffer_depth - 1))
+			read_ptr -= drvdata->buffer_depth;
 		/* let the decoder know we've skipped ahead */
 		local_inc(&buf->lost);
 	}
@@ -579,47 +560,29 @@ static const struct file_operations etb_
 	.llseek		= no_llseek,
 };
 
-static ssize_t status_show(struct device *dev,
-			   struct device_attribute *attr, char *buf)
-{
-	unsigned long flags;
-	u32 etb_rdr, etb_sr, etb_rrp, etb_rwp;
-	u32 etb_trg, etb_cr, etb_ffsr, etb_ffcr;
-	struct etb_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	pm_runtime_get_sync(drvdata->dev);
-	spin_lock_irqsave(&drvdata->spinlock, flags);
-	CS_UNLOCK(drvdata->base);
-
-	etb_rdr = readl_relaxed(drvdata->base + ETB_RAM_DEPTH_REG);
-	etb_sr = readl_relaxed(drvdata->base + ETB_STATUS_REG);
-	etb_rrp = readl_relaxed(drvdata->base + ETB_RAM_READ_POINTER);
-	etb_rwp = readl_relaxed(drvdata->base + ETB_RAM_WRITE_POINTER);
-	etb_trg = readl_relaxed(drvdata->base + ETB_TRG);
-	etb_cr = readl_relaxed(drvdata->base + ETB_CTL_REG);
-	etb_ffsr = readl_relaxed(drvdata->base + ETB_FFSR);
-	etb_ffcr = readl_relaxed(drvdata->base + ETB_FFCR);
-
-	CS_LOCK(drvdata->base);
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
-
-	pm_runtime_put(drvdata->dev);
+#define coresight_etb10_simple_func(name, offset)                       \
+	coresight_simple_func(struct etb_drvdata, name, offset)
 
-	return sprintf(buf,
-		       "Depth:\t\t0x%x\n"
-		       "Status:\t\t0x%x\n"
-		       "RAM read ptr:\t0x%x\n"
-		       "RAM wrt ptr:\t0x%x\n"
-		       "Trigger cnt:\t0x%x\n"
-		       "Control:\t0x%x\n"
-		       "Flush status:\t0x%x\n"
-		       "Flush ctrl:\t0x%x\n",
-		       etb_rdr, etb_sr, etb_rrp, etb_rwp,
-		       etb_trg, etb_cr, etb_ffsr, etb_ffcr);
+coresight_etb10_simple_func(rdp, ETB_RAM_DEPTH_REG);
+coresight_etb10_simple_func(sts, ETB_STATUS_REG);
+coresight_etb10_simple_func(rrp, ETB_RAM_READ_POINTER);
+coresight_etb10_simple_func(rwp, ETB_RAM_WRITE_POINTER);
+coresight_etb10_simple_func(trg, ETB_TRG);
+coresight_etb10_simple_func(ctl, ETB_CTL_REG);
+coresight_etb10_simple_func(ffsr, ETB_FFSR);
+coresight_etb10_simple_func(ffcr, ETB_FFCR);
 
-	return -EINVAL;
-}
-static DEVICE_ATTR_RO(status);
+static struct attribute *coresight_etb_mgmt_attrs[] = {
+	&dev_attr_rdp.attr,
+	&dev_attr_sts.attr,
+	&dev_attr_rrp.attr,
+	&dev_attr_rwp.attr,
+	&dev_attr_trg.attr,
+	&dev_attr_ctl.attr,
+	&dev_attr_ffsr.attr,
+	&dev_attr_ffcr.attr,
+	NULL,
+};
 
 static ssize_t trigger_cntr_show(struct device *dev,
 			    struct device_attribute *attr, char *buf)
@@ -649,10 +612,23 @@ static DEVICE_ATTR_RW(trigger_cntr);
 
 static struct attribute *coresight_etb_attrs[] = {
 	&dev_attr_trigger_cntr.attr,
-	&dev_attr_status.attr,
 	NULL,
 };
-ATTRIBUTE_GROUPS(coresight_etb);
+
+static const struct attribute_group coresight_etb_group = {
+	.attrs = coresight_etb_attrs,
+};
+
+static const struct attribute_group coresight_etb_mgmt_group = {
+	.attrs = coresight_etb_mgmt_attrs,
+	.name = "mgmt",
+};
+
+const struct attribute_group *coresight_etb_groups[] = {
+	&coresight_etb_group,
+	&coresight_etb_mgmt_group,
+	NULL,
+};
 
 static int etb_probe(struct amba_device *adev, const struct amba_id *id)
 {
@@ -729,7 +705,6 @@ static int etb_probe(struct amba_device
 	if (ret)
 		goto err_misc_register;
 
-	dev_info(dev, "ETB initialized\n");
 	return 0;
 
 err_misc_register:
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c linux-libre-4.7-gnu/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c
--- linux-libre-4.6-gnu/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c	2016-07-24 15:23:50.000000000 -0400
@@ -1221,26 +1221,19 @@ static struct attribute *coresight_etm_a
 	NULL,
 };
 
-#define coresight_simple_func(name, offset)                             \
-static ssize_t name##_show(struct device *_dev,                         \
-			   struct device_attribute *attr, char *buf)    \
-{                                                                       \
-	struct etm_drvdata *drvdata = dev_get_drvdata(_dev->parent);    \
-	return scnprintf(buf, PAGE_SIZE, "0x%x\n",                      \
-			 readl_relaxed(drvdata->base + offset));        \
-}                                                                       \
-DEVICE_ATTR_RO(name)
+#define coresight_etm3x_simple_func(name, offset)			\
+	coresight_simple_func(struct etm_drvdata, name, offset)
 
-coresight_simple_func(etmccr, ETMCCR);
-coresight_simple_func(etmccer, ETMCCER);
-coresight_simple_func(etmscr, ETMSCR);
-coresight_simple_func(etmidr, ETMIDR);
-coresight_simple_func(etmcr, ETMCR);
-coresight_simple_func(etmtraceidr, ETMTRACEIDR);
-coresight_simple_func(etmteevr, ETMTEEVR);
-coresight_simple_func(etmtssvr, ETMTSSCR);
-coresight_simple_func(etmtecr1, ETMTECR1);
-coresight_simple_func(etmtecr2, ETMTECR2);
+coresight_etm3x_simple_func(etmccr, ETMCCR);
+coresight_etm3x_simple_func(etmccer, ETMCCER);
+coresight_etm3x_simple_func(etmscr, ETMSCR);
+coresight_etm3x_simple_func(etmidr, ETMIDR);
+coresight_etm3x_simple_func(etmcr, ETMCR);
+coresight_etm3x_simple_func(etmtraceidr, ETMTRACEIDR);
+coresight_etm3x_simple_func(etmteevr, ETMTEEVR);
+coresight_etm3x_simple_func(etmtssvr, ETMTSSCR);
+coresight_etm3x_simple_func(etmtecr1, ETMTECR1);
+coresight_etm3x_simple_func(etmtecr2, ETMTECR2);
 
 static struct attribute *coresight_etm_mgmt_attrs[] = {
 	&dev_attr_etmccr.attr,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwtracing/coresight/coresight-etm4x.c linux-libre-4.7-gnu/drivers/hwtracing/coresight/coresight-etm4x.c
--- linux-libre-4.6-gnu/drivers/hwtracing/coresight/coresight-etm4x.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hwtracing/coresight/coresight-etm4x.c	2016-07-24 15:23:50.000000000 -0400
@@ -26,15 +26,19 @@
 #include <linux/clk.h>
 #include <linux/cpu.h>
 #include <linux/coresight.h>
+#include <linux/coresight-pmu.h>
 #include <linux/pm_wakeup.h>
 #include <linux/amba/bus.h>
 #include <linux/seq_file.h>
 #include <linux/uaccess.h>
+#include <linux/perf_event.h>
 #include <linux/pm_runtime.h>
 #include <linux/perf_event.h>
 #include <asm/sections.h>
+#include <asm/local.h>
 
 #include "coresight-etm4x.h"
+#include "coresight-etm-perf.h"
 
 static int boot_enable;
 module_param_named(boot_enable, boot_enable, int, S_IRUGO);
@@ -42,13 +46,13 @@ module_param_named(boot_enable, boot_ena
 /* The number of ETMv4 currently registered */
 static int etm4_count;
 static struct etmv4_drvdata *etmdrvdata[NR_CPUS];
+static void etm4_set_default(struct etmv4_config *config);
 
-static void etm4_os_unlock(void *info)
+static void etm4_os_unlock(struct etmv4_drvdata *drvdata)
 {
-	struct etmv4_drvdata *drvdata = (struct etmv4_drvdata *)info;
-
 	/* Writing any value to ETMOSLAR unlocks the trace registers */
 	writel_relaxed(0x0, drvdata->base + TRCOSLAR);
+	drvdata->os_unlock = true;
 	isb();
 }
 
@@ -76,7 +80,7 @@ static int etm4_trace_id(struct coresigh
 	unsigned long flags;
 	int trace_id = -1;
 
-	if (!drvdata->enable)
+	if (!local_read(&drvdata->mode))
 		return drvdata->trcid;
 
 	spin_lock_irqsave(&drvdata->spinlock, flags);
@@ -95,6 +99,7 @@ static void etm4_enable_hw(void *info)
 {
 	int i;
 	struct etmv4_drvdata *drvdata = info;
+	struct etmv4_config *config = &drvdata->config;
 
 	CS_UNLOCK(drvdata->base);
 
@@ -109,69 +114,69 @@ static void etm4_enable_hw(void *info)
 			"timeout observed when probing at offset %#x\n",
 			TRCSTATR);
 
-	writel_relaxed(drvdata->pe_sel, drvdata->base + TRCPROCSELR);
-	writel_relaxed(drvdata->cfg, drvdata->base + TRCCONFIGR);
+	writel_relaxed(config->pe_sel, drvdata->base + TRCPROCSELR);
+	writel_relaxed(config->cfg, drvdata->base + TRCCONFIGR);
 	/* nothing specific implemented */
 	writel_relaxed(0x0, drvdata->base + TRCAUXCTLR);
-	writel_relaxed(drvdata->eventctrl0, drvdata->base + TRCEVENTCTL0R);
-	writel_relaxed(drvdata->eventctrl1, drvdata->base + TRCEVENTCTL1R);
-	writel_relaxed(drvdata->stall_ctrl, drvdata->base + TRCSTALLCTLR);
-	writel_relaxed(drvdata->ts_ctrl, drvdata->base + TRCTSCTLR);
-	writel_relaxed(drvdata->syncfreq, drvdata->base + TRCSYNCPR);
-	writel_relaxed(drvdata->ccctlr, drvdata->base + TRCCCCTLR);
-	writel_relaxed(drvdata->bb_ctrl, drvdata->base + TRCBBCTLR);
+	writel_relaxed(config->eventctrl0, drvdata->base + TRCEVENTCTL0R);
+	writel_relaxed(config->eventctrl1, drvdata->base + TRCEVENTCTL1R);
+	writel_relaxed(config->stall_ctrl, drvdata->base + TRCSTALLCTLR);
+	writel_relaxed(config->ts_ctrl, drvdata->base + TRCTSCTLR);
+	writel_relaxed(config->syncfreq, drvdata->base + TRCSYNCPR);
+	writel_relaxed(config->ccctlr, drvdata->base + TRCCCCTLR);
+	writel_relaxed(config->bb_ctrl, drvdata->base + TRCBBCTLR);
 	writel_relaxed(drvdata->trcid, drvdata->base + TRCTRACEIDR);
-	writel_relaxed(drvdata->vinst_ctrl, drvdata->base + TRCVICTLR);
-	writel_relaxed(drvdata->viiectlr, drvdata->base + TRCVIIECTLR);
-	writel_relaxed(drvdata->vissctlr,
+	writel_relaxed(config->vinst_ctrl, drvdata->base + TRCVICTLR);
+	writel_relaxed(config->viiectlr, drvdata->base + TRCVIIECTLR);
+	writel_relaxed(config->vissctlr,
 		       drvdata->base + TRCVISSCTLR);
-	writel_relaxed(drvdata->vipcssctlr,
+	writel_relaxed(config->vipcssctlr,
 		       drvdata->base + TRCVIPCSSCTLR);
 	for (i = 0; i < drvdata->nrseqstate - 1; i++)
-		writel_relaxed(drvdata->seq_ctrl[i],
+		writel_relaxed(config->seq_ctrl[i],
 			       drvdata->base + TRCSEQEVRn(i));
-	writel_relaxed(drvdata->seq_rst, drvdata->base + TRCSEQRSTEVR);
-	writel_relaxed(drvdata->seq_state, drvdata->base + TRCSEQSTR);
-	writel_relaxed(drvdata->ext_inp, drvdata->base + TRCEXTINSELR);
+	writel_relaxed(config->seq_rst, drvdata->base + TRCSEQRSTEVR);
+	writel_relaxed(config->seq_state, drvdata->base + TRCSEQSTR);
+	writel_relaxed(config->ext_inp, drvdata->base + TRCEXTINSELR);
 	for (i = 0; i < drvdata->nr_cntr; i++) {
-		writel_relaxed(drvdata->cntrldvr[i],
+		writel_relaxed(config->cntrldvr[i],
 			       drvdata->base + TRCCNTRLDVRn(i));
-		writel_relaxed(drvdata->cntr_ctrl[i],
+		writel_relaxed(config->cntr_ctrl[i],
 			       drvdata->base + TRCCNTCTLRn(i));
-		writel_relaxed(drvdata->cntr_val[i],
+		writel_relaxed(config->cntr_val[i],
 			       drvdata->base + TRCCNTVRn(i));
 	}
 
 	/* Resource selector pair 0 is always implemented and reserved */
-	for (i = 2; i < drvdata->nr_resource * 2; i++)
-		writel_relaxed(drvdata->res_ctrl[i],
+	for (i = 0; i < drvdata->nr_resource * 2; i++)
+		writel_relaxed(config->res_ctrl[i],
 			       drvdata->base + TRCRSCTLRn(i));
 
 	for (i = 0; i < drvdata->nr_ss_cmp; i++) {
-		writel_relaxed(drvdata->ss_ctrl[i],
+		writel_relaxed(config->ss_ctrl[i],
 			       drvdata->base + TRCSSCCRn(i));
-		writel_relaxed(drvdata->ss_status[i],
+		writel_relaxed(config->ss_status[i],
 			       drvdata->base + TRCSSCSRn(i));
-		writel_relaxed(drvdata->ss_pe_cmp[i],
+		writel_relaxed(config->ss_pe_cmp[i],
 			       drvdata->base + TRCSSPCICRn(i));
 	}
 	for (i = 0; i < drvdata->nr_addr_cmp; i++) {
-		writeq_relaxed(drvdata->addr_val[i],
+		writeq_relaxed(config->addr_val[i],
 			       drvdata->base + TRCACVRn(i));
-		writeq_relaxed(drvdata->addr_acc[i],
+		writeq_relaxed(config->addr_acc[i],
 			       drvdata->base + TRCACATRn(i));
 	}
 	for (i = 0; i < drvdata->numcidc; i++)
-		writeq_relaxed(drvdata->ctxid_pid[i],
+		writeq_relaxed(config->ctxid_pid[i],
 			       drvdata->base + TRCCIDCVRn(i));
-	writel_relaxed(drvdata->ctxid_mask0, drvdata->base + TRCCIDCCTLR0);
-	writel_relaxed(drvdata->ctxid_mask1, drvdata->base + TRCCIDCCTLR1);
+	writel_relaxed(config->ctxid_mask0, drvdata->base + TRCCIDCCTLR0);
+	writel_relaxed(config->ctxid_mask1, drvdata->base + TRCCIDCCTLR1);
 
 	for (i = 0; i < drvdata->numvmidc; i++)
-		writeq_relaxed(drvdata->vmid_val[i],
+		writeq_relaxed(config->vmid_val[i],
 			       drvdata->base + TRCVMIDCVRn(i));
-	writel_relaxed(drvdata->vmid_mask0, drvdata->base + TRCVMIDCCTLR0);
-	writel_relaxed(drvdata->vmid_mask1, drvdata->base + TRCVMIDCCTLR1);
+	writel_relaxed(config->vmid_mask0, drvdata->base + TRCVMIDCCTLR0);
+	writel_relaxed(config->vmid_mask1, drvdata->base + TRCVMIDCCTLR1);
 
 	/* Enable the trace unit */
 	writel_relaxed(1, drvdata->base + TRCPRGCTLR);
@@ -187,2120 +192,210 @@ static void etm4_enable_hw(void *info)
 	dev_dbg(drvdata->dev, "cpu: %d enable smp call done\n", drvdata->cpu);
 }
 
-static int etm4_enable(struct coresight_device *csdev,
-		       struct perf_event_attr *attr, u32 mode)
-{
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-	int ret;
-
-	spin_lock(&drvdata->spinlock);
-
-	/*
-	 * Executing etm4_enable_hw on the cpu whose ETM is being enabled
-	 * ensures that register writes occur when cpu is powered.
-	 */
-	ret = smp_call_function_single(drvdata->cpu,
-				       etm4_enable_hw, drvdata, 1);
-	if (ret)
-		goto err;
-	drvdata->enable = true;
-	drvdata->sticky_enable = true;
-
-	spin_unlock(&drvdata->spinlock);
-
-	dev_info(drvdata->dev, "ETM tracing enabled\n");
-	return 0;
-err:
-	spin_unlock(&drvdata->spinlock);
-	return ret;
-}
-
-static void etm4_disable_hw(void *info)
-{
-	u32 control;
-	struct etmv4_drvdata *drvdata = info;
-
-	CS_UNLOCK(drvdata->base);
-
-	control = readl_relaxed(drvdata->base + TRCPRGCTLR);
-
-	/* EN, bit[0] Trace unit enable bit */
-	control &= ~0x1;
-
-	/* make sure everything completes before disabling */
-	mb();
-	isb();
-	writel_relaxed(control, drvdata->base + TRCPRGCTLR);
-
-	CS_LOCK(drvdata->base);
-
-	dev_dbg(drvdata->dev, "cpu: %d disable smp call done\n", drvdata->cpu);
-}
-
-static void etm4_disable(struct coresight_device *csdev)
+static int etm4_parse_event_config(struct etmv4_drvdata *drvdata,
+				   struct perf_event_attr *attr)
 {
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-
-	/*
-	 * Taking hotplug lock here protects from clocks getting disabled
-	 * with tracing being left on (crash scenario) if user disable occurs
-	 * after cpu online mask indicates the cpu is offline but before the
-	 * DYING hotplug callback is serviced by the ETM driver.
-	 */
-	get_online_cpus();
-	spin_lock(&drvdata->spinlock);
-
-	/*
-	 * Executing etm4_disable_hw on the cpu whose ETM is being disabled
-	 * ensures that register writes occur when cpu is powered.
-	 */
-	smp_call_function_single(drvdata->cpu, etm4_disable_hw, drvdata, 1);
-	drvdata->enable = false;
+	struct etmv4_config *config = &drvdata->config;
 
-	spin_unlock(&drvdata->spinlock);
-	put_online_cpus();
+	if (!attr)
+		return -EINVAL;
 
-	dev_info(drvdata->dev, "ETM tracing disabled\n");
-}
+	/* Clear configuration from previous run */
+	memset(config, 0, sizeof(struct etmv4_config));
 
-static const struct coresight_ops_source etm4_source_ops = {
-	.cpu_id		= etm4_cpu_id,
-	.trace_id	= etm4_trace_id,
-	.enable		= etm4_enable,
-	.disable	= etm4_disable,
-};
+	if (attr->exclude_kernel)
+		config->mode = ETM_MODE_EXCL_KERN;
 
-static const struct coresight_ops etm4_cs_ops = {
-	.source_ops	= &etm4_source_ops,
-};
+	if (attr->exclude_user)
+		config->mode = ETM_MODE_EXCL_USER;
 
-static int etm4_set_mode_exclude(struct etmv4_drvdata *drvdata, bool exclude)
-{
-	u8 idx = drvdata->addr_idx;
+	/* Always start from the default config */
+	etm4_set_default(config);
 
 	/*
-	 * TRCACATRn.TYPE bit[1:0]: type of comparison
-	 * the trace unit performs
+	 * By default the tracers are configured to trace the whole address
+	 * range.  Narrow the field only if requested by user space.
 	 */
-	if (BMVAL(drvdata->addr_acc[idx], 0, 1) == ETM_INSTR_ADDR) {
-		if (idx % 2 != 0)
-			return -EINVAL;
+	if (config->mode)
+		etm4_config_trace_mode(config);
 
-		/*
-		 * We are performing instruction address comparison. Set the
-		 * relevant bit of ViewInst Include/Exclude Control register
-		 * for corresponding address comparator pair.
-		 */
-		if (drvdata->addr_type[idx] != ETM_ADDR_TYPE_RANGE ||
-		    drvdata->addr_type[idx + 1] != ETM_ADDR_TYPE_RANGE)
-			return -EINVAL;
+	/* Go from generic option to ETMv4 specifics */
+	if (attr->config & BIT(ETM_OPT_CYCACC))
+		config->cfg |= ETMv4_MODE_CYCACC;
+	if (attr->config & BIT(ETM_OPT_TS))
+		config->cfg |= ETMv4_MODE_TIMESTAMP;
 
-		if (exclude == true) {
-			/*
-			 * Set exclude bit and unset the include bit
-			 * corresponding to comparator pair
-			 */
-			drvdata->viiectlr |= BIT(idx / 2 + 16);
-			drvdata->viiectlr &= ~BIT(idx / 2);
-		} else {
-			/*
-			 * Set include bit and unset exclude bit
-			 * corresponding to comparator pair
-			 */
-			drvdata->viiectlr |= BIT(idx / 2);
-			drvdata->viiectlr &= ~BIT(idx / 2 + 16);
-		}
-	}
 	return 0;
 }
 
-static ssize_t nr_pe_cmp_show(struct device *dev,
-			      struct device_attribute *attr,
-			      char *buf)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	val = drvdata->nr_pe_cmp;
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-static DEVICE_ATTR_RO(nr_pe_cmp);
-
-static ssize_t nr_addr_cmp_show(struct device *dev,
-				struct device_attribute *attr,
-				char *buf)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	val = drvdata->nr_addr_cmp;
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-static DEVICE_ATTR_RO(nr_addr_cmp);
-
-static ssize_t nr_cntr_show(struct device *dev,
-			    struct device_attribute *attr,
-			    char *buf)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	val = drvdata->nr_cntr;
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-static DEVICE_ATTR_RO(nr_cntr);
-
-static ssize_t nr_ext_inp_show(struct device *dev,
-			       struct device_attribute *attr,
-			       char *buf)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	val = drvdata->nr_ext_inp;
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-static DEVICE_ATTR_RO(nr_ext_inp);
-
-static ssize_t numcidc_show(struct device *dev,
-			    struct device_attribute *attr,
-			    char *buf)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	val = drvdata->numcidc;
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-static DEVICE_ATTR_RO(numcidc);
-
-static ssize_t numvmidc_show(struct device *dev,
-			     struct device_attribute *attr,
-			     char *buf)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	val = drvdata->numvmidc;
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-static DEVICE_ATTR_RO(numvmidc);
-
-static ssize_t nrseqstate_show(struct device *dev,
-			       struct device_attribute *attr,
-			       char *buf)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	val = drvdata->nrseqstate;
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-static DEVICE_ATTR_RO(nrseqstate);
-
-static ssize_t nr_resource_show(struct device *dev,
-				struct device_attribute *attr,
-				char *buf)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	val = drvdata->nr_resource;
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-static DEVICE_ATTR_RO(nr_resource);
-
-static ssize_t nr_ss_cmp_show(struct device *dev,
-			      struct device_attribute *attr,
-			      char *buf)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	val = drvdata->nr_ss_cmp;
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-static DEVICE_ATTR_RO(nr_ss_cmp);
-
-static ssize_t reset_store(struct device *dev,
-			   struct device_attribute *attr,
-			   const char *buf, size_t size)
+static int etm4_enable_perf(struct coresight_device *csdev,
+			    struct perf_event_attr *attr)
 {
-	int i;
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 
-	if (kstrtoul(buf, 16, &val))
+	if (WARN_ON_ONCE(drvdata->cpu != smp_processor_id()))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
-	if (val)
-		drvdata->mode = 0x0;
-
-	/* Disable data tracing: do not trace load and store data transfers */
-	drvdata->mode &= ~(ETM_MODE_LOAD | ETM_MODE_STORE);
-	drvdata->cfg &= ~(BIT(1) | BIT(2));
-
-	/* Disable data value and data address tracing */
-	drvdata->mode &= ~(ETM_MODE_DATA_TRACE_ADDR |
-			   ETM_MODE_DATA_TRACE_VAL);
-	drvdata->cfg &= ~(BIT(16) | BIT(17));
-
-	/* Disable all events tracing */
-	drvdata->eventctrl0 = 0x0;
-	drvdata->eventctrl1 = 0x0;
-
-	/* Disable timestamp event */
-	drvdata->ts_ctrl = 0x0;
-
-	/* Disable stalling */
-	drvdata->stall_ctrl = 0x0;
-
-	/* Reset trace synchronization period  to 2^8 = 256 bytes*/
-	if (drvdata->syncpr == false)
-		drvdata->syncfreq = 0x8;
-
-	/*
-	 * Enable ViewInst to trace everything with start-stop logic in
-	 * started state. ARM recommends start-stop logic is set before
-	 * each trace run.
-	 */
-	drvdata->vinst_ctrl |= BIT(0);
-	if (drvdata->nr_addr_cmp == true) {
-		drvdata->mode |= ETM_MODE_VIEWINST_STARTSTOP;
-		/* SSSTATUS, bit[9] */
-		drvdata->vinst_ctrl |= BIT(9);
-	}
-
-	/* No address range filtering for ViewInst */
-	drvdata->viiectlr = 0x0;
-
-	/* No start-stop filtering for ViewInst */
-	drvdata->vissctlr = 0x0;
-
-	/* Disable seq events */
-	for (i = 0; i < drvdata->nrseqstate-1; i++)
-		drvdata->seq_ctrl[i] = 0x0;
-	drvdata->seq_rst = 0x0;
-	drvdata->seq_state = 0x0;
-
-	/* Disable external input events */
-	drvdata->ext_inp = 0x0;
-
-	drvdata->cntr_idx = 0x0;
-	for (i = 0; i < drvdata->nr_cntr; i++) {
-		drvdata->cntrldvr[i] = 0x0;
-		drvdata->cntr_ctrl[i] = 0x0;
-		drvdata->cntr_val[i] = 0x0;
-	}
-
-	/* Resource selector pair 0 is always implemented and reserved */
-	drvdata->res_idx = 0x2;
-	for (i = 2; i < drvdata->nr_resource * 2; i++)
-		drvdata->res_ctrl[i] = 0x0;
-
-	for (i = 0; i < drvdata->nr_ss_cmp; i++) {
-		drvdata->ss_ctrl[i] = 0x0;
-		drvdata->ss_pe_cmp[i] = 0x0;
-	}
-
-	drvdata->addr_idx = 0x0;
-	for (i = 0; i < drvdata->nr_addr_cmp * 2; i++) {
-		drvdata->addr_val[i] = 0x0;
-		drvdata->addr_acc[i] = 0x0;
-		drvdata->addr_type[i] = ETM_ADDR_TYPE_NONE;
-	}
-
-	drvdata->ctxid_idx = 0x0;
-	for (i = 0; i < drvdata->numcidc; i++) {
-		drvdata->ctxid_pid[i] = 0x0;
-		drvdata->ctxid_vpid[i] = 0x0;
-	}
-
-	drvdata->ctxid_mask0 = 0x0;
-	drvdata->ctxid_mask1 = 0x0;
-
-	drvdata->vmid_idx = 0x0;
-	for (i = 0; i < drvdata->numvmidc; i++)
-		drvdata->vmid_val[i] = 0x0;
-	drvdata->vmid_mask0 = 0x0;
-	drvdata->vmid_mask1 = 0x0;
-
-	drvdata->trcid = drvdata->cpu + 1;
-	spin_unlock(&drvdata->spinlock);
-	return size;
-}
-static DEVICE_ATTR_WO(reset);
-
-static ssize_t mode_show(struct device *dev,
-			 struct device_attribute *attr,
-			 char *buf)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	/* Configure the tracer based on the session's specifics */
+	etm4_parse_event_config(drvdata, attr);
+	/* And enable it */
+	etm4_enable_hw(drvdata);
 
-	val = drvdata->mode;
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+	return 0;
 }
 
-static ssize_t mode_store(struct device *dev,
-			  struct device_attribute *attr,
-			  const char *buf, size_t size)
+static int etm4_enable_sysfs(struct coresight_device *csdev)
 {
-	unsigned long val, mode;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	if (kstrtoul(buf, 16, &val))
-		return -EINVAL;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+	int ret;
 
 	spin_lock(&drvdata->spinlock);
-	drvdata->mode = val & ETMv4_MODE_ALL;
-
-	if (drvdata->mode & ETM_MODE_EXCLUDE)
-		etm4_set_mode_exclude(drvdata, true);
-	else
-		etm4_set_mode_exclude(drvdata, false);
-
-	if (drvdata->instrp0 == true) {
-		/* start by clearing instruction P0 field */
-		drvdata->cfg  &= ~(BIT(1) | BIT(2));
-		if (drvdata->mode & ETM_MODE_LOAD)
-			/* 0b01 Trace load instructions as P0 instructions */
-			drvdata->cfg  |= BIT(1);
-		if (drvdata->mode & ETM_MODE_STORE)
-			/* 0b10 Trace store instructions as P0 instructions */
-			drvdata->cfg  |= BIT(2);
-		if (drvdata->mode & ETM_MODE_LOAD_STORE)
-			/*
-			 * 0b11 Trace load and store instructions
-			 * as P0 instructions
-			 */
-			drvdata->cfg  |= BIT(1) | BIT(2);
-	}
 
-	/* bit[3], Branch broadcast mode */
-	if ((drvdata->mode & ETM_MODE_BB) && (drvdata->trcbb == true))
-		drvdata->cfg |= BIT(3);
-	else
-		drvdata->cfg &= ~BIT(3);
-
-	/* bit[4], Cycle counting instruction trace bit */
-	if ((drvdata->mode & ETMv4_MODE_CYCACC) &&
-		(drvdata->trccci == true))
-		drvdata->cfg |= BIT(4);
-	else
-		drvdata->cfg &= ~BIT(4);
-
-	/* bit[6], Context ID tracing bit */
-	if ((drvdata->mode & ETMv4_MODE_CTXID) && (drvdata->ctxid_size))
-		drvdata->cfg |= BIT(6);
-	else
-		drvdata->cfg &= ~BIT(6);
-
-	if ((drvdata->mode & ETM_MODE_VMID) && (drvdata->vmid_size))
-		drvdata->cfg |= BIT(7);
-	else
-		drvdata->cfg &= ~BIT(7);
-
-	/* bits[10:8], Conditional instruction tracing bit */
-	mode = ETM_MODE_COND(drvdata->mode);
-	if (drvdata->trccond == true) {
-		drvdata->cfg &= ~(BIT(8) | BIT(9) | BIT(10));
-		drvdata->cfg |= mode << 8;
-	}
-
-	/* bit[11], Global timestamp tracing bit */
-	if ((drvdata->mode & ETMv4_MODE_TIMESTAMP) && (drvdata->ts_size))
-		drvdata->cfg |= BIT(11);
-	else
-		drvdata->cfg &= ~BIT(11);
-
-	/* bit[12], Return stack enable bit */
-	if ((drvdata->mode & ETM_MODE_RETURNSTACK) &&
-		(drvdata->retstack == true))
-		drvdata->cfg |= BIT(12);
-	else
-		drvdata->cfg &= ~BIT(12);
-
-	/* bits[14:13], Q element enable field */
-	mode = ETM_MODE_QELEM(drvdata->mode);
-	/* start by clearing QE bits */
-	drvdata->cfg &= ~(BIT(13) | BIT(14));
-	/* if supported, Q elements with instruction counts are enabled */
-	if ((mode & BIT(0)) && (drvdata->q_support & BIT(0)))
-		drvdata->cfg |= BIT(13);
 	/*
-	 * if supported, Q elements with and without instruction
-	 * counts are enabled
+	 * Executing etm4_enable_hw on the cpu whose ETM is being enabled
+	 * ensures that register writes occur when cpu is powered.
 	 */
-	if ((mode & BIT(1)) && (drvdata->q_support & BIT(1)))
-		drvdata->cfg |= BIT(14);
-
-	/* bit[11], AMBA Trace Bus (ATB) trigger enable bit */
-	if ((drvdata->mode & ETM_MODE_ATB_TRIGGER) &&
-	    (drvdata->atbtrig == true))
-		drvdata->eventctrl1 |= BIT(11);
-	else
-		drvdata->eventctrl1 &= ~BIT(11);
-
-	/* bit[12], Low-power state behavior override bit */
-	if ((drvdata->mode & ETM_MODE_LPOVERRIDE) &&
-	    (drvdata->lpoverride == true))
-		drvdata->eventctrl1 |= BIT(12);
-	else
-		drvdata->eventctrl1 &= ~BIT(12);
-
-	/* bit[8], Instruction stall bit */
-	if (drvdata->mode & ETM_MODE_ISTALL_EN)
-		drvdata->stall_ctrl |= BIT(8);
-	else
-		drvdata->stall_ctrl &= ~BIT(8);
-
-	/* bit[10], Prioritize instruction trace bit */
-	if (drvdata->mode & ETM_MODE_INSTPRIO)
-		drvdata->stall_ctrl |= BIT(10);
-	else
-		drvdata->stall_ctrl &= ~BIT(10);
-
-	/* bit[13], Trace overflow prevention bit */
-	if ((drvdata->mode & ETM_MODE_NOOVERFLOW) &&
-		(drvdata->nooverflow == true))
-		drvdata->stall_ctrl |= BIT(13);
-	else
-		drvdata->stall_ctrl &= ~BIT(13);
-
-	/* bit[9] Start/stop logic control bit */
-	if (drvdata->mode & ETM_MODE_VIEWINST_STARTSTOP)
-		drvdata->vinst_ctrl |= BIT(9);
-	else
-		drvdata->vinst_ctrl &= ~BIT(9);
-
-	/* bit[10], Whether a trace unit must trace a Reset exception */
-	if (drvdata->mode & ETM_MODE_TRACE_RESET)
-		drvdata->vinst_ctrl |= BIT(10);
-	else
-		drvdata->vinst_ctrl &= ~BIT(10);
-
-	/* bit[11], Whether a trace unit must trace a system error exception */
-	if ((drvdata->mode & ETM_MODE_TRACE_ERR) &&
-		(drvdata->trc_error == true))
-		drvdata->vinst_ctrl |= BIT(11);
-	else
-		drvdata->vinst_ctrl &= ~BIT(11);
-
-	spin_unlock(&drvdata->spinlock);
-	return size;
-}
-static DEVICE_ATTR_RW(mode);
-
-static ssize_t pe_show(struct device *dev,
-		       struct device_attribute *attr,
-		       char *buf)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	val = drvdata->pe_sel;
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-
-static ssize_t pe_store(struct device *dev,
-			struct device_attribute *attr,
-			const char *buf, size_t size)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	if (kstrtoul(buf, 16, &val))
-		return -EINVAL;
-
-	spin_lock(&drvdata->spinlock);
-	if (val > drvdata->nr_pe) {
-		spin_unlock(&drvdata->spinlock);
-		return -EINVAL;
-	}
+	ret = smp_call_function_single(drvdata->cpu,
+				       etm4_enable_hw, drvdata, 1);
+	if (ret)
+		goto err;
 
-	drvdata->pe_sel = val;
+	drvdata->sticky_enable = true;
 	spin_unlock(&drvdata->spinlock);
-	return size;
-}
-static DEVICE_ATTR_RW(pe);
 
-static ssize_t event_show(struct device *dev,
-			  struct device_attribute *attr,
-			  char *buf)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	val = drvdata->eventctrl0;
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-
-static ssize_t event_store(struct device *dev,
-			   struct device_attribute *attr,
-			   const char *buf, size_t size)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	if (kstrtoul(buf, 16, &val))
-		return -EINVAL;
+	dev_info(drvdata->dev, "ETM tracing enabled\n");
+	return 0;
 
-	spin_lock(&drvdata->spinlock);
-	switch (drvdata->nr_event) {
-	case 0x0:
-		/* EVENT0, bits[7:0] */
-		drvdata->eventctrl0 = val & 0xFF;
-		break;
-	case 0x1:
-		 /* EVENT1, bits[15:8] */
-		drvdata->eventctrl0 = val & 0xFFFF;
-		break;
-	case 0x2:
-		/* EVENT2, bits[23:16] */
-		drvdata->eventctrl0 = val & 0xFFFFFF;
-		break;
-	case 0x3:
-		/* EVENT3, bits[31:24] */
-		drvdata->eventctrl0 = val;
-		break;
-	default:
-		break;
-	}
+err:
 	spin_unlock(&drvdata->spinlock);
-	return size;
+	return ret;
 }
-static DEVICE_ATTR_RW(event);
 
-static ssize_t event_instren_show(struct device *dev,
-				  struct device_attribute *attr,
-				  char *buf)
+static int etm4_enable(struct coresight_device *csdev,
+		       struct perf_event_attr *attr, u32 mode)
 {
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	val = BMVAL(drvdata->eventctrl1, 0, 3);
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
+	int ret;
+	u32 val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 
-static ssize_t event_instren_store(struct device *dev,
-				   struct device_attribute *attr,
-				   const char *buf, size_t size)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	val = local_cmpxchg(&drvdata->mode, CS_MODE_DISABLED, mode);
 
-	if (kstrtoul(buf, 16, &val))
-		return -EINVAL;
+	/* Someone is already using the tracer */
+	if (val)
+		return -EBUSY;
 
-	spin_lock(&drvdata->spinlock);
-	/* start by clearing all instruction event enable bits */
-	drvdata->eventctrl1 &= ~(BIT(0) | BIT(1) | BIT(2) | BIT(3));
-	switch (drvdata->nr_event) {
-	case 0x0:
-		/* generate Event element for event 1 */
-		drvdata->eventctrl1 |= val & BIT(1);
-		break;
-	case 0x1:
-		/* generate Event element for event 1 and 2 */
-		drvdata->eventctrl1 |= val & (BIT(0) | BIT(1));
-		break;
-	case 0x2:
-		/* generate Event element for event 1, 2 and 3 */
-		drvdata->eventctrl1 |= val & (BIT(0) | BIT(1) | BIT(2));
+	switch (mode) {
+	case CS_MODE_SYSFS:
+		ret = etm4_enable_sysfs(csdev);
 		break;
-	case 0x3:
-		/* generate Event element for all 4 events */
-		drvdata->eventctrl1 |= val & 0xF;
+	case CS_MODE_PERF:
+		ret = etm4_enable_perf(csdev, attr);
 		break;
 	default:
-		break;
-	}
-	spin_unlock(&drvdata->spinlock);
-	return size;
-}
-static DEVICE_ATTR_RW(event_instren);
-
-static ssize_t event_ts_show(struct device *dev,
-			     struct device_attribute *attr,
-			     char *buf)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	val = drvdata->ts_ctrl;
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-
-static ssize_t event_ts_store(struct device *dev,
-			      struct device_attribute *attr,
-			      const char *buf, size_t size)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	if (kstrtoul(buf, 16, &val))
-		return -EINVAL;
-	if (!drvdata->ts_size)
-		return -EINVAL;
-
-	drvdata->ts_ctrl = val & ETMv4_EVENT_MASK;
-	return size;
-}
-static DEVICE_ATTR_RW(event_ts);
-
-static ssize_t syncfreq_show(struct device *dev,
-			     struct device_attribute *attr,
-			     char *buf)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	val = drvdata->syncfreq;
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-
-static ssize_t syncfreq_store(struct device *dev,
-			      struct device_attribute *attr,
-			      const char *buf, size_t size)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	if (kstrtoul(buf, 16, &val))
-		return -EINVAL;
-	if (drvdata->syncpr == true)
-		return -EINVAL;
-
-	drvdata->syncfreq = val & ETMv4_SYNC_MASK;
-	return size;
-}
-static DEVICE_ATTR_RW(syncfreq);
-
-static ssize_t cyc_threshold_show(struct device *dev,
-				  struct device_attribute *attr,
-				  char *buf)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	val = drvdata->ccctlr;
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-
-static ssize_t cyc_threshold_store(struct device *dev,
-				   struct device_attribute *attr,
-				   const char *buf, size_t size)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	if (kstrtoul(buf, 16, &val))
-		return -EINVAL;
-	if (val < drvdata->ccitmin)
-		return -EINVAL;
-
-	drvdata->ccctlr = val & ETM_CYC_THRESHOLD_MASK;
-	return size;
-}
-static DEVICE_ATTR_RW(cyc_threshold);
-
-static ssize_t bb_ctrl_show(struct device *dev,
-			    struct device_attribute *attr,
-			    char *buf)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	val = drvdata->bb_ctrl;
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-
-static ssize_t bb_ctrl_store(struct device *dev,
-			     struct device_attribute *attr,
-			     const char *buf, size_t size)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	if (kstrtoul(buf, 16, &val))
-		return -EINVAL;
-	if (drvdata->trcbb == false)
-		return -EINVAL;
-	if (!drvdata->nr_addr_cmp)
-		return -EINVAL;
-	/*
-	 * Bit[7:0] selects which address range comparator is used for
-	 * branch broadcast control.
-	 */
-	if (BMVAL(val, 0, 7) > drvdata->nr_addr_cmp)
-		return -EINVAL;
-
-	drvdata->bb_ctrl = val;
-	return size;
-}
-static DEVICE_ATTR_RW(bb_ctrl);
-
-static ssize_t event_vinst_show(struct device *dev,
-				struct device_attribute *attr,
-				char *buf)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	val = drvdata->vinst_ctrl & ETMv4_EVENT_MASK;
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-
-static ssize_t event_vinst_store(struct device *dev,
-				 struct device_attribute *attr,
-				 const char *buf, size_t size)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	if (kstrtoul(buf, 16, &val))
-		return -EINVAL;
-
-	spin_lock(&drvdata->spinlock);
-	val &= ETMv4_EVENT_MASK;
-	drvdata->vinst_ctrl &= ~ETMv4_EVENT_MASK;
-	drvdata->vinst_ctrl |= val;
-	spin_unlock(&drvdata->spinlock);
-	return size;
-}
-static DEVICE_ATTR_RW(event_vinst);
-
-static ssize_t s_exlevel_vinst_show(struct device *dev,
-				    struct device_attribute *attr,
-				    char *buf)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	val = BMVAL(drvdata->vinst_ctrl, 16, 19);
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-
-static ssize_t s_exlevel_vinst_store(struct device *dev,
-				     struct device_attribute *attr,
-				     const char *buf, size_t size)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	if (kstrtoul(buf, 16, &val))
-		return -EINVAL;
-
-	spin_lock(&drvdata->spinlock);
-	/* clear all EXLEVEL_S bits (bit[18] is never implemented) */
-	drvdata->vinst_ctrl &= ~(BIT(16) | BIT(17) | BIT(19));
-	/* enable instruction tracing for corresponding exception level */
-	val &= drvdata->s_ex_level;
-	drvdata->vinst_ctrl |= (val << 16);
-	spin_unlock(&drvdata->spinlock);
-	return size;
-}
-static DEVICE_ATTR_RW(s_exlevel_vinst);
-
-static ssize_t ns_exlevel_vinst_show(struct device *dev,
-				     struct device_attribute *attr,
-				     char *buf)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	/* EXLEVEL_NS, bits[23:20] */
-	val = BMVAL(drvdata->vinst_ctrl, 20, 23);
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-
-static ssize_t ns_exlevel_vinst_store(struct device *dev,
-				      struct device_attribute *attr,
-				      const char *buf, size_t size)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	if (kstrtoul(buf, 16, &val))
-		return -EINVAL;
-
-	spin_lock(&drvdata->spinlock);
-	/* clear EXLEVEL_NS bits (bit[23] is never implemented */
-	drvdata->vinst_ctrl &= ~(BIT(20) | BIT(21) | BIT(22));
-	/* enable instruction tracing for corresponding exception level */
-	val &= drvdata->ns_ex_level;
-	drvdata->vinst_ctrl |= (val << 20);
-	spin_unlock(&drvdata->spinlock);
-	return size;
-}
-static DEVICE_ATTR_RW(ns_exlevel_vinst);
-
-static ssize_t addr_idx_show(struct device *dev,
-			     struct device_attribute *attr,
-			     char *buf)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	val = drvdata->addr_idx;
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-
-static ssize_t addr_idx_store(struct device *dev,
-			      struct device_attribute *attr,
-			      const char *buf, size_t size)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	if (kstrtoul(buf, 16, &val))
-		return -EINVAL;
-	if (val >= drvdata->nr_addr_cmp * 2)
-		return -EINVAL;
-
-	/*
-	 * Use spinlock to ensure index doesn't change while it gets
-	 * dereferenced multiple times within a spinlock block elsewhere.
-	 */
-	spin_lock(&drvdata->spinlock);
-	drvdata->addr_idx = val;
-	spin_unlock(&drvdata->spinlock);
-	return size;
-}
-static DEVICE_ATTR_RW(addr_idx);
-
-static ssize_t addr_instdatatype_show(struct device *dev,
-				      struct device_attribute *attr,
-				      char *buf)
-{
-	ssize_t len;
-	u8 val, idx;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	spin_lock(&drvdata->spinlock);
-	idx = drvdata->addr_idx;
-	val = BMVAL(drvdata->addr_acc[idx], 0, 1);
-	len = scnprintf(buf, PAGE_SIZE, "%s\n",
-			val == ETM_INSTR_ADDR ? "instr" :
-			(val == ETM_DATA_LOAD_ADDR ? "data_load" :
-			(val == ETM_DATA_STORE_ADDR ? "data_store" :
-			"data_load_store")));
-	spin_unlock(&drvdata->spinlock);
-	return len;
-}
-
-static ssize_t addr_instdatatype_store(struct device *dev,
-				       struct device_attribute *attr,
-				       const char *buf, size_t size)
-{
-	u8 idx;
-	char str[20] = "";
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	if (strlen(buf) >= 20)
-		return -EINVAL;
-	if (sscanf(buf, "%s", str) != 1)
-		return -EINVAL;
-
-	spin_lock(&drvdata->spinlock);
-	idx = drvdata->addr_idx;
-	if (!strcmp(str, "instr"))
-		/* TYPE, bits[1:0] */
-		drvdata->addr_acc[idx] &= ~(BIT(0) | BIT(1));
-
-	spin_unlock(&drvdata->spinlock);
-	return size;
-}
-static DEVICE_ATTR_RW(addr_instdatatype);
-
-static ssize_t addr_single_show(struct device *dev,
-				struct device_attribute *attr,
-				char *buf)
-{
-	u8 idx;
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	idx = drvdata->addr_idx;
-	spin_lock(&drvdata->spinlock);
-	if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
-	      drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
-		spin_unlock(&drvdata->spinlock);
-		return -EPERM;
-	}
-	val = (unsigned long)drvdata->addr_val[idx];
-	spin_unlock(&drvdata->spinlock);
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-
-static ssize_t addr_single_store(struct device *dev,
-				 struct device_attribute *attr,
-				 const char *buf, size_t size)
-{
-	u8 idx;
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	if (kstrtoul(buf, 16, &val))
-		return -EINVAL;
-
-	spin_lock(&drvdata->spinlock);
-	idx = drvdata->addr_idx;
-	if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
-	      drvdata->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
-		spin_unlock(&drvdata->spinlock);
-		return -EPERM;
-	}
-
-	drvdata->addr_val[idx] = (u64)val;
-	drvdata->addr_type[idx] = ETM_ADDR_TYPE_SINGLE;
-	spin_unlock(&drvdata->spinlock);
-	return size;
-}
-static DEVICE_ATTR_RW(addr_single);
-
-static ssize_t addr_range_show(struct device *dev,
-			       struct device_attribute *attr,
-			       char *buf)
-{
-	u8 idx;
-	unsigned long val1, val2;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	spin_lock(&drvdata->spinlock);
-	idx = drvdata->addr_idx;
-	if (idx % 2 != 0) {
-		spin_unlock(&drvdata->spinlock);
-		return -EPERM;
-	}
-	if (!((drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
-	       drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
-	      (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
-	       drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
-		spin_unlock(&drvdata->spinlock);
-		return -EPERM;
-	}
-
-	val1 = (unsigned long)drvdata->addr_val[idx];
-	val2 = (unsigned long)drvdata->addr_val[idx + 1];
-	spin_unlock(&drvdata->spinlock);
-	return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
-}
-
-static ssize_t addr_range_store(struct device *dev,
-				struct device_attribute *attr,
-				const char *buf, size_t size)
-{
-	u8 idx;
-	unsigned long val1, val2;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	if (sscanf(buf, "%lx %lx", &val1, &val2) != 2)
-		return -EINVAL;
-	/* lower address comparator cannot have a higher address value */
-	if (val1 > val2)
-		return -EINVAL;
-
-	spin_lock(&drvdata->spinlock);
-	idx = drvdata->addr_idx;
-	if (idx % 2 != 0) {
-		spin_unlock(&drvdata->spinlock);
-		return -EPERM;
-	}
-
-	if (!((drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
-	       drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
-	      (drvdata->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
-	       drvdata->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
-		spin_unlock(&drvdata->spinlock);
-		return -EPERM;
-	}
-
-	drvdata->addr_val[idx] = (u64)val1;
-	drvdata->addr_type[idx] = ETM_ADDR_TYPE_RANGE;
-	drvdata->addr_val[idx + 1] = (u64)val2;
-	drvdata->addr_type[idx + 1] = ETM_ADDR_TYPE_RANGE;
-	/*
-	 * Program include or exclude control bits for vinst or vdata
-	 * whenever we change addr comparators to ETM_ADDR_TYPE_RANGE
-	 */
-	if (drvdata->mode & ETM_MODE_EXCLUDE)
-		etm4_set_mode_exclude(drvdata, true);
-	else
-		etm4_set_mode_exclude(drvdata, false);
-
-	spin_unlock(&drvdata->spinlock);
-	return size;
-}
-static DEVICE_ATTR_RW(addr_range);
-
-static ssize_t addr_start_show(struct device *dev,
-			       struct device_attribute *attr,
-			       char *buf)
-{
-	u8 idx;
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	spin_lock(&drvdata->spinlock);
-	idx = drvdata->addr_idx;
-
-	if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
-	      drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) {
-		spin_unlock(&drvdata->spinlock);
-		return -EPERM;
-	}
-
-	val = (unsigned long)drvdata->addr_val[idx];
-	spin_unlock(&drvdata->spinlock);
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-
-static ssize_t addr_start_store(struct device *dev,
-				struct device_attribute *attr,
-				const char *buf, size_t size)
-{
-	u8 idx;
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	if (kstrtoul(buf, 16, &val))
-		return -EINVAL;
-
-	spin_lock(&drvdata->spinlock);
-	idx = drvdata->addr_idx;
-	if (!drvdata->nr_addr_cmp) {
-		spin_unlock(&drvdata->spinlock);
-		return -EINVAL;
-	}
-	if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
-	      drvdata->addr_type[idx] == ETM_ADDR_TYPE_START)) {
-		spin_unlock(&drvdata->spinlock);
-		return -EPERM;
-	}
-
-	drvdata->addr_val[idx] = (u64)val;
-	drvdata->addr_type[idx] = ETM_ADDR_TYPE_START;
-	drvdata->vissctlr |= BIT(idx);
-	/* SSSTATUS, bit[9] - turn on start/stop logic */
-	drvdata->vinst_ctrl |= BIT(9);
-	spin_unlock(&drvdata->spinlock);
-	return size;
-}
-static DEVICE_ATTR_RW(addr_start);
-
-static ssize_t addr_stop_show(struct device *dev,
-			      struct device_attribute *attr,
-			      char *buf)
-{
-	u8 idx;
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	spin_lock(&drvdata->spinlock);
-	idx = drvdata->addr_idx;
-
-	if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
-	      drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
-		spin_unlock(&drvdata->spinlock);
-		return -EPERM;
-	}
-
-	val = (unsigned long)drvdata->addr_val[idx];
-	spin_unlock(&drvdata->spinlock);
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-
-static ssize_t addr_stop_store(struct device *dev,
-			       struct device_attribute *attr,
-			       const char *buf, size_t size)
-{
-	u8 idx;
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	if (kstrtoul(buf, 16, &val))
-		return -EINVAL;
-
-	spin_lock(&drvdata->spinlock);
-	idx = drvdata->addr_idx;
-	if (!drvdata->nr_addr_cmp) {
-		spin_unlock(&drvdata->spinlock);
-		return -EINVAL;
-	}
-	if (!(drvdata->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
-	       drvdata->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
-		spin_unlock(&drvdata->spinlock);
-		return -EPERM;
-	}
-
-	drvdata->addr_val[idx] = (u64)val;
-	drvdata->addr_type[idx] = ETM_ADDR_TYPE_STOP;
-	drvdata->vissctlr |= BIT(idx + 16);
-	/* SSSTATUS, bit[9] - turn on start/stop logic */
-	drvdata->vinst_ctrl |= BIT(9);
-	spin_unlock(&drvdata->spinlock);
-	return size;
-}
-static DEVICE_ATTR_RW(addr_stop);
-
-static ssize_t addr_ctxtype_show(struct device *dev,
-				 struct device_attribute *attr,
-				 char *buf)
-{
-	ssize_t len;
-	u8 idx, val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	spin_lock(&drvdata->spinlock);
-	idx = drvdata->addr_idx;
-	/* CONTEXTTYPE, bits[3:2] */
-	val = BMVAL(drvdata->addr_acc[idx], 2, 3);
-	len = scnprintf(buf, PAGE_SIZE, "%s\n", val == ETM_CTX_NONE ? "none" :
-			(val == ETM_CTX_CTXID ? "ctxid" :
-			(val == ETM_CTX_VMID ? "vmid" : "all")));
-	spin_unlock(&drvdata->spinlock);
-	return len;
-}
-
-static ssize_t addr_ctxtype_store(struct device *dev,
-				  struct device_attribute *attr,
-				  const char *buf, size_t size)
-{
-	u8 idx;
-	char str[10] = "";
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	if (strlen(buf) >= 10)
-		return -EINVAL;
-	if (sscanf(buf, "%s", str) != 1)
-		return -EINVAL;
-
-	spin_lock(&drvdata->spinlock);
-	idx = drvdata->addr_idx;
-	if (!strcmp(str, "none"))
-		/* start by clearing context type bits */
-		drvdata->addr_acc[idx] &= ~(BIT(2) | BIT(3));
-	else if (!strcmp(str, "ctxid")) {
-		/* 0b01 The trace unit performs a Context ID */
-		if (drvdata->numcidc) {
-			drvdata->addr_acc[idx] |= BIT(2);
-			drvdata->addr_acc[idx] &= ~BIT(3);
-		}
-	} else if (!strcmp(str, "vmid")) {
-		/* 0b10 The trace unit performs a VMID */
-		if (drvdata->numvmidc) {
-			drvdata->addr_acc[idx] &= ~BIT(2);
-			drvdata->addr_acc[idx] |= BIT(3);
-		}
-	} else if (!strcmp(str, "all")) {
-		/*
-		 * 0b11 The trace unit performs a Context ID
-		 * comparison and a VMID
-		 */
-		if (drvdata->numcidc)
-			drvdata->addr_acc[idx] |= BIT(2);
-		if (drvdata->numvmidc)
-			drvdata->addr_acc[idx] |= BIT(3);
+		ret = -EINVAL;
 	}
-	spin_unlock(&drvdata->spinlock);
-	return size;
-}
-static DEVICE_ATTR_RW(addr_ctxtype);
 
-static ssize_t addr_context_show(struct device *dev,
-				 struct device_attribute *attr,
-				 char *buf)
-{
-	u8 idx;
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	spin_lock(&drvdata->spinlock);
-	idx = drvdata->addr_idx;
-	/* context ID comparator bits[6:4] */
-	val = BMVAL(drvdata->addr_acc[idx], 4, 6);
-	spin_unlock(&drvdata->spinlock);
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-
-static ssize_t addr_context_store(struct device *dev,
-				  struct device_attribute *attr,
-				  const char *buf, size_t size)
-{
-	u8 idx;
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	if (kstrtoul(buf, 16, &val))
-		return -EINVAL;
-	if ((drvdata->numcidc <= 1) && (drvdata->numvmidc <= 1))
-		return -EINVAL;
-	if (val >=  (drvdata->numcidc >= drvdata->numvmidc ?
-		     drvdata->numcidc : drvdata->numvmidc))
-		return -EINVAL;
-
-	spin_lock(&drvdata->spinlock);
-	idx = drvdata->addr_idx;
-	/* clear context ID comparator bits[6:4] */
-	drvdata->addr_acc[idx] &= ~(BIT(4) | BIT(5) | BIT(6));
-	drvdata->addr_acc[idx] |= (val << 4);
-	spin_unlock(&drvdata->spinlock);
-	return size;
-}
-static DEVICE_ATTR_RW(addr_context);
-
-static ssize_t seq_idx_show(struct device *dev,
-			    struct device_attribute *attr,
-			    char *buf)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	val = drvdata->seq_idx;
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-
-static ssize_t seq_idx_store(struct device *dev,
-			     struct device_attribute *attr,
-			     const char *buf, size_t size)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	if (kstrtoul(buf, 16, &val))
-		return -EINVAL;
-	if (val >= drvdata->nrseqstate - 1)
-		return -EINVAL;
-
-	/*
-	 * Use spinlock to ensure index doesn't change while it gets
-	 * dereferenced multiple times within a spinlock block elsewhere.
-	 */
-	spin_lock(&drvdata->spinlock);
-	drvdata->seq_idx = val;
-	spin_unlock(&drvdata->spinlock);
-	return size;
-}
-static DEVICE_ATTR_RW(seq_idx);
-
-static ssize_t seq_state_show(struct device *dev,
-			      struct device_attribute *attr,
-			      char *buf)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	val = drvdata->seq_state;
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-
-static ssize_t seq_state_store(struct device *dev,
-			       struct device_attribute *attr,
-			       const char *buf, size_t size)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	if (kstrtoul(buf, 16, &val))
-		return -EINVAL;
-	if (val >= drvdata->nrseqstate)
-		return -EINVAL;
-
-	drvdata->seq_state = val;
-	return size;
-}
-static DEVICE_ATTR_RW(seq_state);
-
-static ssize_t seq_event_show(struct device *dev,
-			      struct device_attribute *attr,
-			      char *buf)
-{
-	u8 idx;
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	spin_lock(&drvdata->spinlock);
-	idx = drvdata->seq_idx;
-	val = drvdata->seq_ctrl[idx];
-	spin_unlock(&drvdata->spinlock);
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-
-static ssize_t seq_event_store(struct device *dev,
-			       struct device_attribute *attr,
-			       const char *buf, size_t size)
-{
-	u8 idx;
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	if (kstrtoul(buf, 16, &val))
-		return -EINVAL;
-
-	spin_lock(&drvdata->spinlock);
-	idx = drvdata->seq_idx;
-	/* RST, bits[7:0] */
-	drvdata->seq_ctrl[idx] = val & 0xFF;
-	spin_unlock(&drvdata->spinlock);
-	return size;
-}
-static DEVICE_ATTR_RW(seq_event);
-
-static ssize_t seq_reset_event_show(struct device *dev,
-				    struct device_attribute *attr,
-				    char *buf)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	val = drvdata->seq_rst;
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-
-static ssize_t seq_reset_event_store(struct device *dev,
-				     struct device_attribute *attr,
-				     const char *buf, size_t size)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	if (kstrtoul(buf, 16, &val))
-		return -EINVAL;
-	if (!(drvdata->nrseqstate))
-		return -EINVAL;
-
-	drvdata->seq_rst = val & ETMv4_EVENT_MASK;
-	return size;
-}
-static DEVICE_ATTR_RW(seq_reset_event);
-
-static ssize_t cntr_idx_show(struct device *dev,
-			     struct device_attribute *attr,
-			     char *buf)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	val = drvdata->cntr_idx;
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-
-static ssize_t cntr_idx_store(struct device *dev,
-			      struct device_attribute *attr,
-			      const char *buf, size_t size)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	if (kstrtoul(buf, 16, &val))
-		return -EINVAL;
-	if (val >= drvdata->nr_cntr)
-		return -EINVAL;
-
-	/*
-	 * Use spinlock to ensure index doesn't change while it gets
-	 * dereferenced multiple times within a spinlock block elsewhere.
-	 */
-	spin_lock(&drvdata->spinlock);
-	drvdata->cntr_idx = val;
-	spin_unlock(&drvdata->spinlock);
-	return size;
-}
-static DEVICE_ATTR_RW(cntr_idx);
-
-static ssize_t cntrldvr_show(struct device *dev,
-			     struct device_attribute *attr,
-			     char *buf)
-{
-	u8 idx;
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	spin_lock(&drvdata->spinlock);
-	idx = drvdata->cntr_idx;
-	val = drvdata->cntrldvr[idx];
-	spin_unlock(&drvdata->spinlock);
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-
-static ssize_t cntrldvr_store(struct device *dev,
-			      struct device_attribute *attr,
-			      const char *buf, size_t size)
-{
-	u8 idx;
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	if (kstrtoul(buf, 16, &val))
-		return -EINVAL;
-	if (val > ETM_CNTR_MAX_VAL)
-		return -EINVAL;
-
-	spin_lock(&drvdata->spinlock);
-	idx = drvdata->cntr_idx;
-	drvdata->cntrldvr[idx] = val;
-	spin_unlock(&drvdata->spinlock);
-	return size;
-}
-static DEVICE_ATTR_RW(cntrldvr);
-
-static ssize_t cntr_val_show(struct device *dev,
-			     struct device_attribute *attr,
-			     char *buf)
-{
-	u8 idx;
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	spin_lock(&drvdata->spinlock);
-	idx = drvdata->cntr_idx;
-	val = drvdata->cntr_val[idx];
-	spin_unlock(&drvdata->spinlock);
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-
-static ssize_t cntr_val_store(struct device *dev,
-			      struct device_attribute *attr,
-			      const char *buf, size_t size)
-{
-	u8 idx;
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	if (kstrtoul(buf, 16, &val))
-		return -EINVAL;
-	if (val > ETM_CNTR_MAX_VAL)
-		return -EINVAL;
-
-	spin_lock(&drvdata->spinlock);
-	idx = drvdata->cntr_idx;
-	drvdata->cntr_val[idx] = val;
-	spin_unlock(&drvdata->spinlock);
-	return size;
-}
-static DEVICE_ATTR_RW(cntr_val);
-
-static ssize_t cntr_ctrl_show(struct device *dev,
-			      struct device_attribute *attr,
-			      char *buf)
-{
-	u8 idx;
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	spin_lock(&drvdata->spinlock);
-	idx = drvdata->cntr_idx;
-	val = drvdata->cntr_ctrl[idx];
-	spin_unlock(&drvdata->spinlock);
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-
-static ssize_t cntr_ctrl_store(struct device *dev,
-			       struct device_attribute *attr,
-			       const char *buf, size_t size)
-{
-	u8 idx;
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	if (kstrtoul(buf, 16, &val))
-		return -EINVAL;
+	/* The tracer didn't start */
+	if (ret)
+		local_set(&drvdata->mode, CS_MODE_DISABLED);
 
-	spin_lock(&drvdata->spinlock);
-	idx = drvdata->cntr_idx;
-	drvdata->cntr_ctrl[idx] = val;
-	spin_unlock(&drvdata->spinlock);
-	return size;
+	return ret;
 }
-static DEVICE_ATTR_RW(cntr_ctrl);
 
-static ssize_t res_idx_show(struct device *dev,
-			    struct device_attribute *attr,
-			    char *buf)
+static void etm4_disable_hw(void *info)
 {
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	u32 control;
+	struct etmv4_drvdata *drvdata = info;
 
-	val = drvdata->res_idx;
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
+	CS_UNLOCK(drvdata->base);
 
-static ssize_t res_idx_store(struct device *dev,
-			     struct device_attribute *attr,
-			     const char *buf, size_t size)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	control = readl_relaxed(drvdata->base + TRCPRGCTLR);
 
-	if (kstrtoul(buf, 16, &val))
-		return -EINVAL;
-	/* Resource selector pair 0 is always implemented and reserved */
-	if (val < 2 || val >= drvdata->nr_resource * 2)
-		return -EINVAL;
+	/* EN, bit[0] Trace unit enable bit */
+	control &= ~0x1;
 
-	/*
-	 * Use spinlock to ensure index doesn't change while it gets
-	 * dereferenced multiple times within a spinlock block elsewhere.
-	 */
-	spin_lock(&drvdata->spinlock);
-	drvdata->res_idx = val;
-	spin_unlock(&drvdata->spinlock);
-	return size;
-}
-static DEVICE_ATTR_RW(res_idx);
+	/* make sure everything completes before disabling */
+	mb();
+	isb();
+	writel_relaxed(control, drvdata->base + TRCPRGCTLR);
 
-static ssize_t res_ctrl_show(struct device *dev,
-			     struct device_attribute *attr,
-			     char *buf)
-{
-	u8 idx;
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	CS_LOCK(drvdata->base);
 
-	spin_lock(&drvdata->spinlock);
-	idx = drvdata->res_idx;
-	val = drvdata->res_ctrl[idx];
-	spin_unlock(&drvdata->spinlock);
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+	dev_dbg(drvdata->dev, "cpu: %d disable smp call done\n", drvdata->cpu);
 }
 
-static ssize_t res_ctrl_store(struct device *dev,
-			      struct device_attribute *attr,
-			      const char *buf, size_t size)
+static int etm4_disable_perf(struct coresight_device *csdev)
 {
-	u8 idx;
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 
-	if (kstrtoul(buf, 16, &val))
+	if (WARN_ON_ONCE(drvdata->cpu != smp_processor_id()))
 		return -EINVAL;
 
-	spin_lock(&drvdata->spinlock);
-	idx = drvdata->res_idx;
-	/* For odd idx pair inversal bit is RES0 */
-	if (idx % 2 != 0)
-		/* PAIRINV, bit[21] */
-		val &= ~BIT(21);
-	drvdata->res_ctrl[idx] = val;
-	spin_unlock(&drvdata->spinlock);
-	return size;
-}
-static DEVICE_ATTR_RW(res_ctrl);
-
-static ssize_t ctxid_idx_show(struct device *dev,
-			      struct device_attribute *attr,
-			      char *buf)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	val = drvdata->ctxid_idx;
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+	etm4_disable_hw(drvdata);
+	return 0;
 }
 
-static ssize_t ctxid_idx_store(struct device *dev,
-			       struct device_attribute *attr,
-			       const char *buf, size_t size)
+static void etm4_disable_sysfs(struct coresight_device *csdev)
 {
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	if (kstrtoul(buf, 16, &val))
-		return -EINVAL;
-	if (val >= drvdata->numcidc)
-		return -EINVAL;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 
 	/*
-	 * Use spinlock to ensure index doesn't change while it gets
-	 * dereferenced multiple times within a spinlock block elsewhere.
+	 * Taking hotplug lock here protects from clocks getting disabled
+	 * with tracing being left on (crash scenario) if user disable occurs
+	 * after cpu online mask indicates the cpu is offline but before the
+	 * DYING hotplug callback is serviced by the ETM driver.
 	 */
+	get_online_cpus();
 	spin_lock(&drvdata->spinlock);
-	drvdata->ctxid_idx = val;
-	spin_unlock(&drvdata->spinlock);
-	return size;
-}
-static DEVICE_ATTR_RW(ctxid_idx);
-
-static ssize_t ctxid_pid_show(struct device *dev,
-			      struct device_attribute *attr,
-			      char *buf)
-{
-	u8 idx;
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	spin_lock(&drvdata->spinlock);
-	idx = drvdata->ctxid_idx;
-	val = (unsigned long)drvdata->ctxid_vpid[idx];
-	spin_unlock(&drvdata->spinlock);
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-
-static ssize_t ctxid_pid_store(struct device *dev,
-			       struct device_attribute *attr,
-			       const char *buf, size_t size)
-{
-	u8 idx;
-	unsigned long vpid, pid;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
 
 	/*
-	 * only implemented when ctxid tracing is enabled, i.e. at least one
-	 * ctxid comparator is implemented and ctxid is greater than 0 bits
-	 * in length
-	 */
-	if (!drvdata->ctxid_size || !drvdata->numcidc)
-		return -EINVAL;
-	if (kstrtoul(buf, 16, &vpid))
-		return -EINVAL;
-
-	pid = coresight_vpid_to_pid(vpid);
-
-	spin_lock(&drvdata->spinlock);
-	idx = drvdata->ctxid_idx;
-	drvdata->ctxid_pid[idx] = (u64)pid;
-	drvdata->ctxid_vpid[idx] = (u64)vpid;
-	spin_unlock(&drvdata->spinlock);
-	return size;
-}
-static DEVICE_ATTR_RW(ctxid_pid);
-
-static ssize_t ctxid_masks_show(struct device *dev,
-				struct device_attribute *attr,
-				char *buf)
-{
-	unsigned long val1, val2;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	spin_lock(&drvdata->spinlock);
-	val1 = drvdata->ctxid_mask0;
-	val2 = drvdata->ctxid_mask1;
-	spin_unlock(&drvdata->spinlock);
-	return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
-}
-
-static ssize_t ctxid_masks_store(struct device *dev,
-				struct device_attribute *attr,
-				const char *buf, size_t size)
-{
-	u8 i, j, maskbyte;
-	unsigned long val1, val2, mask;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	/*
-	 * only implemented when ctxid tracing is enabled, i.e. at least one
-	 * ctxid comparator is implemented and ctxid is greater than 0 bits
-	 * in length
-	 */
-	if (!drvdata->ctxid_size || !drvdata->numcidc)
-		return -EINVAL;
-	if (sscanf(buf, "%lx %lx", &val1, &val2) != 2)
-		return -EINVAL;
-
-	spin_lock(&drvdata->spinlock);
-	/*
-	 * each byte[0..3] controls mask value applied to ctxid
-	 * comparator[0..3]
-	 */
-	switch (drvdata->numcidc) {
-	case 0x1:
-		/* COMP0, bits[7:0] */
-		drvdata->ctxid_mask0 = val1 & 0xFF;
-		break;
-	case 0x2:
-		/* COMP1, bits[15:8] */
-		drvdata->ctxid_mask0 = val1 & 0xFFFF;
-		break;
-	case 0x3:
-		/* COMP2, bits[23:16] */
-		drvdata->ctxid_mask0 = val1 & 0xFFFFFF;
-		break;
-	case 0x4:
-		 /* COMP3, bits[31:24] */
-		drvdata->ctxid_mask0 = val1;
-		break;
-	case 0x5:
-		/* COMP4, bits[7:0] */
-		drvdata->ctxid_mask0 = val1;
-		drvdata->ctxid_mask1 = val2 & 0xFF;
-		break;
-	case 0x6:
-		/* COMP5, bits[15:8] */
-		drvdata->ctxid_mask0 = val1;
-		drvdata->ctxid_mask1 = val2 & 0xFFFF;
-		break;
-	case 0x7:
-		/* COMP6, bits[23:16] */
-		drvdata->ctxid_mask0 = val1;
-		drvdata->ctxid_mask1 = val2 & 0xFFFFFF;
-		break;
-	case 0x8:
-		/* COMP7, bits[31:24] */
-		drvdata->ctxid_mask0 = val1;
-		drvdata->ctxid_mask1 = val2;
-		break;
-	default:
-		break;
-	}
-	/*
-	 * If software sets a mask bit to 1, it must program relevant byte
-	 * of ctxid comparator value 0x0, otherwise behavior is unpredictable.
-	 * For example, if bit[3] of ctxid_mask0 is 1, we must clear bits[31:24]
-	 * of ctxid comparator0 value (corresponding to byte 0) register.
+	 * Executing etm4_disable_hw on the cpu whose ETM is being disabled
+	 * ensures that register writes occur when cpu is powered.
 	 */
-	mask = drvdata->ctxid_mask0;
-	for (i = 0; i < drvdata->numcidc; i++) {
-		/* mask value of corresponding ctxid comparator */
-		maskbyte = mask & ETMv4_EVENT_MASK;
-		/*
-		 * each bit corresponds to a byte of respective ctxid comparator
-		 * value register
-		 */
-		for (j = 0; j < 8; j++) {
-			if (maskbyte & 1)
-				drvdata->ctxid_pid[i] &= ~(0xFF << (j * 8));
-			maskbyte >>= 1;
-		}
-		/* Select the next ctxid comparator mask value */
-		if (i == 3)
-			/* ctxid comparators[4-7] */
-			mask = drvdata->ctxid_mask1;
-		else
-			mask >>= 0x8;
-	}
+	smp_call_function_single(drvdata->cpu, etm4_disable_hw, drvdata, 1);
 
 	spin_unlock(&drvdata->spinlock);
-	return size;
-}
-static DEVICE_ATTR_RW(ctxid_masks);
-
-static ssize_t vmid_idx_show(struct device *dev,
-			     struct device_attribute *attr,
-			     char *buf)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	val = drvdata->vmid_idx;
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-
-static ssize_t vmid_idx_store(struct device *dev,
-			      struct device_attribute *attr,
-			      const char *buf, size_t size)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	if (kstrtoul(buf, 16, &val))
-		return -EINVAL;
-	if (val >= drvdata->numvmidc)
-		return -EINVAL;
-
-	/*
-	 * Use spinlock to ensure index doesn't change while it gets
-	 * dereferenced multiple times within a spinlock block elsewhere.
-	 */
-	spin_lock(&drvdata->spinlock);
-	drvdata->vmid_idx = val;
-	spin_unlock(&drvdata->spinlock);
-	return size;
-}
-static DEVICE_ATTR_RW(vmid_idx);
-
-static ssize_t vmid_val_show(struct device *dev,
-			     struct device_attribute *attr,
-			     char *buf)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	val = (unsigned long)drvdata->vmid_val[drvdata->vmid_idx];
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-
-static ssize_t vmid_val_store(struct device *dev,
-			      struct device_attribute *attr,
-			      const char *buf, size_t size)
-{
-	unsigned long val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	/*
-	 * only implemented when vmid tracing is enabled, i.e. at least one
-	 * vmid comparator is implemented and at least 8 bit vmid size
-	 */
-	if (!drvdata->vmid_size || !drvdata->numvmidc)
-		return -EINVAL;
-	if (kstrtoul(buf, 16, &val))
-		return -EINVAL;
+	put_online_cpus();
 
-	spin_lock(&drvdata->spinlock);
-	drvdata->vmid_val[drvdata->vmid_idx] = (u64)val;
-	spin_unlock(&drvdata->spinlock);
-	return size;
+	dev_info(drvdata->dev, "ETM tracing disabled\n");
 }
-static DEVICE_ATTR_RW(vmid_val);
 
-static ssize_t vmid_masks_show(struct device *dev,
-			       struct device_attribute *attr, char *buf)
+static void etm4_disable(struct coresight_device *csdev)
 {
-	unsigned long val1, val2;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	spin_lock(&drvdata->spinlock);
-	val1 = drvdata->vmid_mask0;
-	val2 = drvdata->vmid_mask1;
-	spin_unlock(&drvdata->spinlock);
-	return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
-}
+	u32 mode;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 
-static ssize_t vmid_masks_store(struct device *dev,
-				struct device_attribute *attr,
-				const char *buf, size_t size)
-{
-	u8 i, j, maskbyte;
-	unsigned long val1, val2, mask;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	/*
-	 * only implemented when vmid tracing is enabled, i.e. at least one
-	 * vmid comparator is implemented and at least 8 bit vmid size
+	 * For as long as the tracer isn't disabled another entity can't
+	 * change its status.  As such we can read the status here without
+	 * fearing it will change under us.
 	 */
-	if (!drvdata->vmid_size || !drvdata->numvmidc)
-		return -EINVAL;
-	if (sscanf(buf, "%lx %lx", &val1, &val2) != 2)
-		return -EINVAL;
-
-	spin_lock(&drvdata->spinlock);
+	mode = local_read(&drvdata->mode);
 
-	/*
-	 * each byte[0..3] controls mask value applied to vmid
-	 * comparator[0..3]
-	 */
-	switch (drvdata->numvmidc) {
-	case 0x1:
-		/* COMP0, bits[7:0] */
-		drvdata->vmid_mask0 = val1 & 0xFF;
-		break;
-	case 0x2:
-		/* COMP1, bits[15:8] */
-		drvdata->vmid_mask0 = val1 & 0xFFFF;
-		break;
-	case 0x3:
-		/* COMP2, bits[23:16] */
-		drvdata->vmid_mask0 = val1 & 0xFFFFFF;
-		break;
-	case 0x4:
-		/* COMP3, bits[31:24] */
-		drvdata->vmid_mask0 = val1;
-		break;
-	case 0x5:
-		/* COMP4, bits[7:0] */
-		drvdata->vmid_mask0 = val1;
-		drvdata->vmid_mask1 = val2 & 0xFF;
-		break;
-	case 0x6:
-		/* COMP5, bits[15:8] */
-		drvdata->vmid_mask0 = val1;
-		drvdata->vmid_mask1 = val2 & 0xFFFF;
-		break;
-	case 0x7:
-		/* COMP6, bits[23:16] */
-		drvdata->vmid_mask0 = val1;
-		drvdata->vmid_mask1 = val2 & 0xFFFFFF;
+	switch (mode) {
+	case CS_MODE_DISABLED:
 		break;
-	case 0x8:
-		/* COMP7, bits[31:24] */
-		drvdata->vmid_mask0 = val1;
-		drvdata->vmid_mask1 = val2;
+	case CS_MODE_SYSFS:
+		etm4_disable_sysfs(csdev);
 		break;
-	default:
+	case CS_MODE_PERF:
+		etm4_disable_perf(csdev);
 		break;
 	}
 
-	/*
-	 * If software sets a mask bit to 1, it must program relevant byte
-	 * of vmid comparator value 0x0, otherwise behavior is unpredictable.
-	 * For example, if bit[3] of vmid_mask0 is 1, we must clear bits[31:24]
-	 * of vmid comparator0 value (corresponding to byte 0) register.
-	 */
-	mask = drvdata->vmid_mask0;
-	for (i = 0; i < drvdata->numvmidc; i++) {
-		/* mask value of corresponding vmid comparator */
-		maskbyte = mask & ETMv4_EVENT_MASK;
-		/*
-		 * each bit corresponds to a byte of respective vmid comparator
-		 * value register
-		 */
-		for (j = 0; j < 8; j++) {
-			if (maskbyte & 1)
-				drvdata->vmid_val[i] &= ~(0xFF << (j * 8));
-			maskbyte >>= 1;
-		}
-		/* Select the next vmid comparator mask value */
-		if (i == 3)
-			/* vmid comparators[4-7] */
-			mask = drvdata->vmid_mask1;
-		else
-			mask >>= 0x8;
-	}
-	spin_unlock(&drvdata->spinlock);
-	return size;
-}
-static DEVICE_ATTR_RW(vmid_masks);
-
-static ssize_t cpu_show(struct device *dev,
-			struct device_attribute *attr, char *buf)
-{
-	int val;
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
-
-	val = drvdata->cpu;
-	return scnprintf(buf, PAGE_SIZE, "%d\n", val);
-
+	if (mode)
+		local_set(&drvdata->mode, CS_MODE_DISABLED);
 }
-static DEVICE_ATTR_RO(cpu);
-
-static struct attribute *coresight_etmv4_attrs[] = {
-	&dev_attr_nr_pe_cmp.attr,
-	&dev_attr_nr_addr_cmp.attr,
-	&dev_attr_nr_cntr.attr,
-	&dev_attr_nr_ext_inp.attr,
-	&dev_attr_numcidc.attr,
-	&dev_attr_numvmidc.attr,
-	&dev_attr_nrseqstate.attr,
-	&dev_attr_nr_resource.attr,
-	&dev_attr_nr_ss_cmp.attr,
-	&dev_attr_reset.attr,
-	&dev_attr_mode.attr,
-	&dev_attr_pe.attr,
-	&dev_attr_event.attr,
-	&dev_attr_event_instren.attr,
-	&dev_attr_event_ts.attr,
-	&dev_attr_syncfreq.attr,
-	&dev_attr_cyc_threshold.attr,
-	&dev_attr_bb_ctrl.attr,
-	&dev_attr_event_vinst.attr,
-	&dev_attr_s_exlevel_vinst.attr,
-	&dev_attr_ns_exlevel_vinst.attr,
-	&dev_attr_addr_idx.attr,
-	&dev_attr_addr_instdatatype.attr,
-	&dev_attr_addr_single.attr,
-	&dev_attr_addr_range.attr,
-	&dev_attr_addr_start.attr,
-	&dev_attr_addr_stop.attr,
-	&dev_attr_addr_ctxtype.attr,
-	&dev_attr_addr_context.attr,
-	&dev_attr_seq_idx.attr,
-	&dev_attr_seq_state.attr,
-	&dev_attr_seq_event.attr,
-	&dev_attr_seq_reset_event.attr,
-	&dev_attr_cntr_idx.attr,
-	&dev_attr_cntrldvr.attr,
-	&dev_attr_cntr_val.attr,
-	&dev_attr_cntr_ctrl.attr,
-	&dev_attr_res_idx.attr,
-	&dev_attr_res_ctrl.attr,
-	&dev_attr_ctxid_idx.attr,
-	&dev_attr_ctxid_pid.attr,
-	&dev_attr_ctxid_masks.attr,
-	&dev_attr_vmid_idx.attr,
-	&dev_attr_vmid_val.attr,
-	&dev_attr_vmid_masks.attr,
-	&dev_attr_cpu.attr,
-	NULL,
-};
-
-#define coresight_simple_func(name, offset)				\
-static ssize_t name##_show(struct device *_dev,				\
-			   struct device_attribute *attr, char *buf)	\
-{									\
-	struct etmv4_drvdata *drvdata = dev_get_drvdata(_dev->parent);	\
-	return scnprintf(buf, PAGE_SIZE, "0x%x\n",			\
-			 readl_relaxed(drvdata->base + offset));	\
-}									\
-static DEVICE_ATTR_RO(name)
-
-coresight_simple_func(trcoslsr, TRCOSLSR);
-coresight_simple_func(trcpdcr, TRCPDCR);
-coresight_simple_func(trcpdsr, TRCPDSR);
-coresight_simple_func(trclsr, TRCLSR);
-coresight_simple_func(trcauthstatus, TRCAUTHSTATUS);
-coresight_simple_func(trcdevid, TRCDEVID);
-coresight_simple_func(trcdevtype, TRCDEVTYPE);
-coresight_simple_func(trcpidr0, TRCPIDR0);
-coresight_simple_func(trcpidr1, TRCPIDR1);
-coresight_simple_func(trcpidr2, TRCPIDR2);
-coresight_simple_func(trcpidr3, TRCPIDR3);
-
-static struct attribute *coresight_etmv4_mgmt_attrs[] = {
-	&dev_attr_trcoslsr.attr,
-	&dev_attr_trcpdcr.attr,
-	&dev_attr_trcpdsr.attr,
-	&dev_attr_trclsr.attr,
-	&dev_attr_trcauthstatus.attr,
-	&dev_attr_trcdevid.attr,
-	&dev_attr_trcdevtype.attr,
-	&dev_attr_trcpidr0.attr,
-	&dev_attr_trcpidr1.attr,
-	&dev_attr_trcpidr2.attr,
-	&dev_attr_trcpidr3.attr,
-	NULL,
-};
-
-coresight_simple_func(trcidr0, TRCIDR0);
-coresight_simple_func(trcidr1, TRCIDR1);
-coresight_simple_func(trcidr2, TRCIDR2);
-coresight_simple_func(trcidr3, TRCIDR3);
-coresight_simple_func(trcidr4, TRCIDR4);
-coresight_simple_func(trcidr5, TRCIDR5);
-/* trcidr[6,7] are reserved */
-coresight_simple_func(trcidr8, TRCIDR8);
-coresight_simple_func(trcidr9, TRCIDR9);
-coresight_simple_func(trcidr10, TRCIDR10);
-coresight_simple_func(trcidr11, TRCIDR11);
-coresight_simple_func(trcidr12, TRCIDR12);
-coresight_simple_func(trcidr13, TRCIDR13);
-
-static struct attribute *coresight_etmv4_trcidr_attrs[] = {
-	&dev_attr_trcidr0.attr,
-	&dev_attr_trcidr1.attr,
-	&dev_attr_trcidr2.attr,
-	&dev_attr_trcidr3.attr,
-	&dev_attr_trcidr4.attr,
-	&dev_attr_trcidr5.attr,
-	/* trcidr[6,7] are reserved */
-	&dev_attr_trcidr8.attr,
-	&dev_attr_trcidr9.attr,
-	&dev_attr_trcidr10.attr,
-	&dev_attr_trcidr11.attr,
-	&dev_attr_trcidr12.attr,
-	&dev_attr_trcidr13.attr,
-	NULL,
-};
-
-static const struct attribute_group coresight_etmv4_group = {
-	.attrs = coresight_etmv4_attrs,
-};
-
-static const struct attribute_group coresight_etmv4_mgmt_group = {
-	.attrs = coresight_etmv4_mgmt_attrs,
-	.name = "mgmt",
-};
 
-static const struct attribute_group coresight_etmv4_trcidr_group = {
-	.attrs = coresight_etmv4_trcidr_attrs,
-	.name = "trcidr",
+static const struct coresight_ops_source etm4_source_ops = {
+	.cpu_id		= etm4_cpu_id,
+	.trace_id	= etm4_trace_id,
+	.enable		= etm4_enable,
+	.disable	= etm4_disable,
 };
 
-static const struct attribute_group *coresight_etmv4_groups[] = {
-	&coresight_etmv4_group,
-	&coresight_etmv4_mgmt_group,
-	&coresight_etmv4_trcidr_group,
-	NULL,
+static const struct coresight_ops etm4_cs_ops = {
+	.source_ops	= &etm4_source_ops,
 };
 
 static void etm4_init_arch_data(void *info)
@@ -2313,6 +408,9 @@ static void etm4_init_arch_data(void *in
 	u32 etmidr5;
 	struct etmv4_drvdata *drvdata = info;
 
+	/* Make sure all registers are accessible */
+	etm4_os_unlock(drvdata);
+
 	CS_UNLOCK(drvdata->base);
 
 	/* find all capabilities of the tracing unit */
@@ -2464,93 +562,115 @@ static void etm4_init_arch_data(void *in
 	CS_LOCK(drvdata->base);
 }
 
-static void etm4_init_default_data(struct etmv4_drvdata *drvdata)
+static void etm4_set_default(struct etmv4_config *config)
 {
-	int i;
+	if (WARN_ON_ONCE(!config))
+		return;
 
-	drvdata->pe_sel = 0x0;
-	drvdata->cfg = (ETMv4_MODE_CTXID | ETM_MODE_VMID |
-			ETMv4_MODE_TIMESTAMP | ETM_MODE_RETURNSTACK);
+	/*
+	 * Make default initialisation trace everything
+	 *
+	 * Select the "always true" resource selector on the
+	 * "Enablign Event" line and configure address range comparator
+	 * '0' to trace all the possible address range.  From there
+	 * configure the "include/exclude" engine to include address
+	 * range comparator '0'.
+	 */
 
 	/* disable all events tracing */
-	drvdata->eventctrl0 = 0x0;
-	drvdata->eventctrl1 = 0x0;
+	config->eventctrl0 = 0x0;
+	config->eventctrl1 = 0x0;
 
 	/* disable stalling */
-	drvdata->stall_ctrl = 0x0;
+	config->stall_ctrl = 0x0;
+
+	/* enable trace synchronization every 4096 bytes, if available */
+	config->syncfreq = 0xC;
 
 	/* disable timestamp event */
-	drvdata->ts_ctrl = 0x0;
+	config->ts_ctrl = 0x0;
 
-	/* enable trace synchronization every 4096 bytes for trace */
-	if (drvdata->syncpr == false)
-		drvdata->syncfreq = 0xC;
+	/* TRCVICTLR::EVENT = 0x01, select the always on logic */
+	config->vinst_ctrl |= BIT(0);
 
 	/*
-	 *  enable viewInst to trace everything with start-stop logic in
-	 *  started state
+	 * TRCVICTLR::SSSTATUS == 1, the start-stop logic is
+	 * in the started state
 	 */
-	drvdata->vinst_ctrl |= BIT(0);
-	/* set initial state of start-stop logic */
-	if (drvdata->nr_addr_cmp)
-		drvdata->vinst_ctrl |= BIT(9);
+	config->vinst_ctrl |= BIT(9);
 
-	/* no address range filtering for ViewInst */
-	drvdata->viiectlr = 0x0;
-	/* no start-stop filtering for ViewInst */
-	drvdata->vissctlr = 0x0;
+	/*
+	 * Configure address range comparator '0' to encompass all
+	 * possible addresses.
+	 */
 
-	/* disable seq events */
-	for (i = 0; i < drvdata->nrseqstate-1; i++)
-		drvdata->seq_ctrl[i] = 0x0;
-	drvdata->seq_rst = 0x0;
-	drvdata->seq_state = 0x0;
+	/* First half of default address comparator: start at address 0 */
+	config->addr_val[ETM_DEFAULT_ADDR_COMP] = 0x0;
+	/* trace instruction addresses */
+	config->addr_acc[ETM_DEFAULT_ADDR_COMP] &= ~(BIT(0) | BIT(1));
+	/* EXLEVEL_NS, bits[12:15], only trace application and kernel space */
+	config->addr_acc[ETM_DEFAULT_ADDR_COMP] |= ETM_EXLEVEL_NS_HYP;
+	/* EXLEVEL_S, bits[11:8], don't trace anything in secure state */
+	config->addr_acc[ETM_DEFAULT_ADDR_COMP] |= (ETM_EXLEVEL_S_APP |
+						    ETM_EXLEVEL_S_OS |
+						    ETM_EXLEVEL_S_HYP);
+	config->addr_type[ETM_DEFAULT_ADDR_COMP] = ETM_ADDR_TYPE_RANGE;
 
-	/* disable external input events */
-	drvdata->ext_inp = 0x0;
+	/*
+	 * Second half of default address comparator: go all
+	 * the way to the top.
+	*/
+	config->addr_val[ETM_DEFAULT_ADDR_COMP + 1] = ~0x0;
+	/* trace instruction addresses */
+	config->addr_acc[ETM_DEFAULT_ADDR_COMP + 1] &= ~(BIT(0) | BIT(1));
+	/* Address comparator type must be equal for both halves */
+	config->addr_acc[ETM_DEFAULT_ADDR_COMP + 1] =
+					config->addr_acc[ETM_DEFAULT_ADDR_COMP];
+	config->addr_type[ETM_DEFAULT_ADDR_COMP + 1] = ETM_ADDR_TYPE_RANGE;
 
-	for (i = 0; i < drvdata->nr_cntr; i++) {
-		drvdata->cntrldvr[i] = 0x0;
-		drvdata->cntr_ctrl[i] = 0x0;
-		drvdata->cntr_val[i] = 0x0;
-	}
+	/*
+	 * Configure the ViewInst function to filter on address range
+	 * comparator '0'.
+	 */
+	config->viiectlr = BIT(0);
 
-	/* Resource selector pair 0 is always implemented and reserved */
-	drvdata->res_idx = 0x2;
-	for (i = 2; i < drvdata->nr_resource * 2; i++)
-		drvdata->res_ctrl[i] = 0x0;
+	/* no start-stop filtering for ViewInst */
+	config->vissctlr = 0x0;
+}
 
-	for (i = 0; i < drvdata->nr_ss_cmp; i++) {
-		drvdata->ss_ctrl[i] = 0x0;
-		drvdata->ss_pe_cmp[i] = 0x0;
-	}
+void etm4_config_trace_mode(struct etmv4_config *config)
+{
+	u32 addr_acc, mode;
 
-	if (drvdata->nr_addr_cmp >= 1) {
-		drvdata->addr_val[0] = (unsigned long)_stext;
-		drvdata->addr_val[1] = (unsigned long)_etext;
-		drvdata->addr_type[0] = ETM_ADDR_TYPE_RANGE;
-		drvdata->addr_type[1] = ETM_ADDR_TYPE_RANGE;
-	}
+	mode = config->mode;
+	mode &= (ETM_MODE_EXCL_KERN | ETM_MODE_EXCL_USER);
 
-	for (i = 0; i < drvdata->numcidc; i++) {
-		drvdata->ctxid_pid[i] = 0x0;
-		drvdata->ctxid_vpid[i] = 0x0;
-	}
+	/* excluding kernel AND user space doesn't make sense */
+	WARN_ON_ONCE(mode == (ETM_MODE_EXCL_KERN | ETM_MODE_EXCL_USER));
 
-	drvdata->ctxid_mask0 = 0x0;
-	drvdata->ctxid_mask1 = 0x0;
+	/* nothing to do if neither flags are set */
+	if (!(mode & ETM_MODE_EXCL_KERN) && !(mode & ETM_MODE_EXCL_USER))
+		return;
 
-	for (i = 0; i < drvdata->numvmidc; i++)
-		drvdata->vmid_val[i] = 0x0;
-	drvdata->vmid_mask0 = 0x0;
-	drvdata->vmid_mask1 = 0x0;
+	addr_acc = config->addr_acc[ETM_DEFAULT_ADDR_COMP];
+	/* clear default config */
+	addr_acc &= ~(ETM_EXLEVEL_NS_APP | ETM_EXLEVEL_NS_OS);
 
 	/*
-	 * A trace ID value of 0 is invalid, so let's start at some
-	 * random value that fits in 7 bits.  ETMv3.x has 0x10 so let's
-	 * start at 0x20.
+	 * EXLEVEL_NS, bits[15:12]
+	 * The Exception levels are:
+	 *   Bit[12] Exception level 0 - Application
+	 *   Bit[13] Exception level 1 - OS
+	 *   Bit[14] Exception level 2 - Hypervisor
+	 *   Bit[15] Never implemented
 	 */
-	drvdata->trcid = 0x20 + drvdata->cpu;
+	if (mode & ETM_MODE_EXCL_KERN)
+		addr_acc |= ETM_EXLEVEL_NS_OS;
+	else
+		addr_acc |= ETM_EXLEVEL_NS_APP;
+
+	config->addr_acc[ETM_DEFAULT_ADDR_COMP] = addr_acc;
+	config->addr_acc[ETM_DEFAULT_ADDR_COMP + 1] = addr_acc;
 }
 
 static int etm4_cpu_callback(struct notifier_block *nfb, unsigned long action,
@@ -2569,7 +689,7 @@ static int etm4_cpu_callback(struct noti
 			etmdrvdata[cpu]->os_unlock = true;
 		}
 
-		if (etmdrvdata[cpu]->enable)
+		if (local_read(&etmdrvdata[cpu]->mode))
 			etm4_enable_hw(etmdrvdata[cpu]);
 		spin_unlock(&etmdrvdata[cpu]->spinlock);
 		break;
@@ -2582,7 +702,7 @@ static int etm4_cpu_callback(struct noti
 
 	case CPU_DYING:
 		spin_lock(&etmdrvdata[cpu]->spinlock);
-		if (etmdrvdata[cpu]->enable)
+		if (local_read(&etmdrvdata[cpu]->mode))
 			etm4_disable_hw(etmdrvdata[cpu]);
 		spin_unlock(&etmdrvdata[cpu]->spinlock);
 		break;
@@ -2595,6 +715,11 @@ static struct notifier_block etm4_cpu_no
 	.notifier_call = etm4_cpu_callback,
 };
 
+static void etm4_init_trace_id(struct etmv4_drvdata *drvdata)
+{
+	drvdata->trcid = coresight_get_trace_id(drvdata->cpu);
+}
+
 static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
 {
 	int ret;
@@ -2638,9 +763,6 @@ static int etm4_probe(struct amba_device
 	get_online_cpus();
 	etmdrvdata[drvdata->cpu] = drvdata;
 
-	if (!smp_call_function_single(drvdata->cpu, etm4_os_unlock, drvdata, 1))
-		drvdata->os_unlock = true;
-
 	if (smp_call_function_single(drvdata->cpu,
 				etm4_init_arch_data,  drvdata, 1))
 		dev_err(dev, "ETM arch init failed\n");
@@ -2654,9 +776,9 @@ static int etm4_probe(struct amba_device
 		ret = -EINVAL;
 		goto err_arch_supported;
 	}
-	etm4_init_default_data(drvdata);
 
-	pm_runtime_put(&adev->dev);
+	etm4_init_trace_id(drvdata);
+	etm4_set_default(&drvdata->config);
 
 	desc->type = CORESIGHT_DEV_TYPE_SOURCE;
 	desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
@@ -2667,9 +789,16 @@ static int etm4_probe(struct amba_device
 	drvdata->csdev = coresight_register(desc);
 	if (IS_ERR(drvdata->csdev)) {
 		ret = PTR_ERR(drvdata->csdev);
-		goto err_coresight_register;
+		goto err_arch_supported;
+	}
+
+	ret = etm_perf_symlink(drvdata->csdev, true);
+	if (ret) {
+		coresight_unregister(drvdata->csdev);
+		goto err_arch_supported;
 	}
 
+	pm_runtime_put(&adev->dev);
 	dev_info(dev, "%s initialized\n", (char *)id->data);
 
 	if (boot_enable) {
@@ -2680,8 +809,6 @@ static int etm4_probe(struct amba_device
 	return 0;
 
 err_arch_supported:
-	pm_runtime_put(&adev->dev);
-err_coresight_register:
 	if (--etm4_count == 0)
 		unregister_hotcpu_notifier(&etm4_cpu_notifier);
 	return ret;
@@ -2698,6 +825,11 @@ static struct amba_id etm4_ids[] = {
 		.mask	= 0x000fffff,
 		.data	= "ETM 4.0",
 	},
+	{       /* ETM 4.0 - A72, Maia, HiSilicon */
+		.id = 0x000bb95a,
+		.mask = 0x000fffff,
+		.data = "ETM 4.0",
+	},
 	{ 0, 0},
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwtracing/coresight/coresight-etm4x.h linux-libre-4.7-gnu/drivers/hwtracing/coresight/coresight-etm4x.h
--- linux-libre-4.6-gnu/drivers/hwtracing/coresight/coresight-etm4x.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hwtracing/coresight/coresight-etm4x.h	2016-07-24 15:23:50.000000000 -0400
@@ -13,6 +13,7 @@
 #ifndef _CORESIGHT_CORESIGHT_ETM_H
 #define _CORESIGHT_CORESIGHT_ETM_H
 
+#include <asm/local.h>
 #include <linux/spinlock.h>
 #include "coresight-priv.h"
 
@@ -175,71 +176,38 @@
 #define ETM_MODE_TRACE_RESET		BIT(25)
 #define ETM_MODE_TRACE_ERR		BIT(26)
 #define ETM_MODE_VIEWINST_STARTSTOP	BIT(27)
-#define ETMv4_MODE_ALL			0xFFFFFFF
+#define ETMv4_MODE_ALL			(GENMASK(27, 0) | \
+					 ETM_MODE_EXCL_KERN | \
+					 ETM_MODE_EXCL_USER)
 
 #define TRCSTATR_IDLE_BIT		0
+#define ETM_DEFAULT_ADDR_COMP		0
+
+/* secure state access levels */
+#define ETM_EXLEVEL_S_APP		BIT(8)
+#define ETM_EXLEVEL_S_OS		BIT(9)
+#define ETM_EXLEVEL_S_NA		BIT(10)
+#define ETM_EXLEVEL_S_HYP		BIT(11)
+/* non-secure state access levels */
+#define ETM_EXLEVEL_NS_APP		BIT(12)
+#define ETM_EXLEVEL_NS_OS		BIT(13)
+#define ETM_EXLEVEL_NS_HYP		BIT(14)
+#define ETM_EXLEVEL_NS_NA		BIT(15)
 
 /**
- * struct etm4_drvdata - specifics associated to an ETM component
- * @base:       Memory mapped base address for this component.
- * @dev:        The device entity associated to this component.
- * @csdev:      Component vitals needed by the framework.
- * @spinlock:   Only one at a time pls.
- * @cpu:        The cpu this component is affined to.
- * @arch:       ETM version number.
- * @enable:	Is this ETM currently tracing.
- * @sticky_enable: true if ETM base configuration has been done.
- * @boot_enable:True if we should start tracing at boot time.
- * @os_unlock:  True if access to management registers is allowed.
- * @nr_pe:	The number of processing entity available for tracing.
- * @nr_pe_cmp:	The number of processing entity comparator inputs that are
- *		available for tracing.
- * @nr_addr_cmp:Number of pairs of address comparators available
- *		as found in ETMIDR4 0-3.
- * @nr_cntr:    Number of counters as found in ETMIDR5 bit 28-30.
- * @nr_ext_inp: Number of external input.
- * @numcidc:	Number of contextID comparators.
- * @numvmidc:	Number of VMID comparators.
- * @nrseqstate: The number of sequencer states that are implemented.
- * @nr_event:	Indicates how many events the trace unit support.
- * @nr_resource:The number of resource selection pairs available for tracing.
- * @nr_ss_cmp:	Number of single-shot comparator controls that are available.
+ * struct etmv4_config - configuration information related to an ETMv4
  * @mode:	Controls various modes supported by this ETM.
- * @trcid:	value of the current ID for this component.
- * @trcid_size: Indicates the trace ID width.
- * @instrp0:	Tracing of load and store instructions
- *		as P0 elements is supported.
- * @trccond:	If the trace unit supports conditional
- *		instruction tracing.
- * @retstack:	Indicates if the implementation supports a return stack.
- * @trc_error:	Whether a trace unit can trace a system
- *		error exception.
- * @atbtrig:	If the implementation can support ATB triggers
- * @lpoverride:	If the implementation can support low-power state over.
  * @pe_sel:	Controls which PE to trace.
  * @cfg:	Controls the tracing options.
  * @eventctrl0: Controls the tracing of arbitrary events.
  * @eventctrl1: Controls the behavior of the events that @event_ctrl0 selects.
  * @stallctl:	If functionality that prevents trace unit buffer overflows
  *		is available.
- * @sysstall:	Does the system support stall control of the PE?
- * @nooverflow:	Indicate if overflow prevention is supported.
- * @stall_ctrl:	Enables trace unit functionality that prevents trace
- *		unit buffer overflows.
- * @ts_size:	Global timestamp size field.
  * @ts_ctrl:	Controls the insertion of global timestamps in the
  *		trace streams.
- * @syncpr:	Indicates if an implementation has a fixed
- *		synchronization period.
  * @syncfreq:	Controls how often trace synchronization requests occur.
- * @trccci:	Indicates if the trace unit supports cycle counting
- *		for instruction.
- * @ccsize:	Indicates the size of the cycle counter in bits.
- * @ccitmin:	minimum value that can be programmed in
  *		the TRCCCCTLR register.
  * @ccctlr:	Sets the threshold value for cycle counting.
- * @trcbb:	Indicates if the trace unit supports branch broadcast tracing.
- * @q_support:	Q element support characteristics.
  * @vinst_ctrl:	Controls instruction trace filtering.
  * @viiectlr:	Set or read, the address range comparators.
  * @vissctlr:	Set, or read, the single address comparators that control the
@@ -264,73 +232,28 @@
  * @addr_acc:	Address comparator access type.
  * @addr_type:	Current status of the comparator register.
  * @ctxid_idx:	Context ID index selector.
- * @ctxid_size:	Size of the context ID field to consider.
  * @ctxid_pid:	Value of the context ID comparator.
  * @ctxid_vpid:	Virtual PID seen by users if PID namespace is enabled, otherwise
  *		the same value of ctxid_pid.
  * @ctxid_mask0:Context ID comparator mask for comparator 0-3.
  * @ctxid_mask1:Context ID comparator mask for comparator 4-7.
  * @vmid_idx:	VM ID index selector.
- * @vmid_size:	Size of the VM ID comparator to consider.
  * @vmid_val:	Value of the VM ID comparator.
  * @vmid_mask0:	VM ID comparator mask for comparator 0-3.
  * @vmid_mask1:	VM ID comparator mask for comparator 4-7.
- * @s_ex_level:	In secure state, indicates whether instruction tracing is
- *		supported for the corresponding Exception level.
- * @ns_ex_level:In non-secure state, indicates whether instruction tracing is
- *		supported for the corresponding Exception level.
  * @ext_inp:	External input selection.
  */
-struct etmv4_drvdata {
-	void __iomem			*base;
-	struct device			*dev;
-	struct coresight_device		*csdev;
-	spinlock_t			spinlock;
-	int				cpu;
-	u8				arch;
-	bool				enable;
-	bool				sticky_enable;
-	bool				boot_enable;
-	bool				os_unlock;
-	u8				nr_pe;
-	u8				nr_pe_cmp;
-	u8				nr_addr_cmp;
-	u8				nr_cntr;
-	u8				nr_ext_inp;
-	u8				numcidc;
-	u8				numvmidc;
-	u8				nrseqstate;
-	u8				nr_event;
-	u8				nr_resource;
-	u8				nr_ss_cmp;
+struct etmv4_config {
 	u32				mode;
-	u8				trcid;
-	u8				trcid_size;
-	bool				instrp0;
-	bool				trccond;
-	bool				retstack;
-	bool				trc_error;
-	bool				atbtrig;
-	bool				lpoverride;
 	u32				pe_sel;
 	u32				cfg;
 	u32				eventctrl0;
 	u32				eventctrl1;
-	bool				stallctl;
-	bool				sysstall;
-	bool				nooverflow;
 	u32				stall_ctrl;
-	u8				ts_size;
 	u32				ts_ctrl;
-	bool				syncpr;
 	u32				syncfreq;
-	bool				trccci;
-	u8				ccsize;
-	u8				ccitmin;
 	u32				ccctlr;
-	bool				trcbb;
 	u32				bb_ctrl;
-	bool				q_support;
 	u32				vinst_ctrl;
 	u32				viiectlr;
 	u32				vissctlr;
@@ -353,19 +276,119 @@ struct etmv4_drvdata {
 	u64				addr_acc[ETM_MAX_SINGLE_ADDR_CMP];
 	u8				addr_type[ETM_MAX_SINGLE_ADDR_CMP];
 	u8				ctxid_idx;
-	u8				ctxid_size;
 	u64				ctxid_pid[ETMv4_MAX_CTXID_CMP];
 	u64				ctxid_vpid[ETMv4_MAX_CTXID_CMP];
 	u32				ctxid_mask0;
 	u32				ctxid_mask1;
 	u8				vmid_idx;
-	u8				vmid_size;
 	u64				vmid_val[ETM_MAX_VMID_CMP];
 	u32				vmid_mask0;
 	u32				vmid_mask1;
+	u32				ext_inp;
+};
+
+/**
+ * struct etm4_drvdata - specifics associated to an ETM component
+ * @base:       Memory mapped base address for this component.
+ * @dev:        The device entity associated to this component.
+ * @csdev:      Component vitals needed by the framework.
+ * @spinlock:   Only one at a time pls.
+ * @mode:	This tracer's mode, i.e sysFS, Perf or disabled.
+ * @cpu:        The cpu this component is affined to.
+ * @arch:       ETM version number.
+ * @nr_pe:	The number of processing entity available for tracing.
+ * @nr_pe_cmp:	The number of processing entity comparator inputs that are
+ *		available for tracing.
+ * @nr_addr_cmp:Number of pairs of address comparators available
+ *		as found in ETMIDR4 0-3.
+ * @nr_cntr:    Number of counters as found in ETMIDR5 bit 28-30.
+ * @nr_ext_inp: Number of external input.
+ * @numcidc:	Number of contextID comparators.
+ * @numvmidc:	Number of VMID comparators.
+ * @nrseqstate: The number of sequencer states that are implemented.
+ * @nr_event:	Indicates how many events the trace unit support.
+ * @nr_resource:The number of resource selection pairs available for tracing.
+ * @nr_ss_cmp:	Number of single-shot comparator controls that are available.
+ * @trcid:	value of the current ID for this component.
+ * @trcid_size: Indicates the trace ID width.
+ * @ts_size:	Global timestamp size field.
+ * @ctxid_size:	Size of the context ID field to consider.
+ * @vmid_size:	Size of the VM ID comparator to consider.
+ * @ccsize:	Indicates the size of the cycle counter in bits.
+ * @ccitmin:	minimum value that can be programmed in
+ * @s_ex_level:	In secure state, indicates whether instruction tracing is
+ *		supported for the corresponding Exception level.
+ * @ns_ex_level:In non-secure state, indicates whether instruction tracing is
+ *		supported for the corresponding Exception level.
+ * @sticky_enable: true if ETM base configuration has been done.
+ * @boot_enable:True if we should start tracing at boot time.
+ * @os_unlock:  True if access to management registers is allowed.
+ * @instrp0:	Tracing of load and store instructions
+ *		as P0 elements is supported.
+ * @trcbb:	Indicates if the trace unit supports branch broadcast tracing.
+ * @trccond:	If the trace unit supports conditional
+ *		instruction tracing.
+ * @retstack:	Indicates if the implementation supports a return stack.
+ * @trccci:	Indicates if the trace unit supports cycle counting
+ *		for instruction.
+ * @q_support:	Q element support characteristics.
+ * @trc_error:	Whether a trace unit can trace a system
+ *		error exception.
+ * @syncpr:	Indicates if an implementation has a fixed
+ *		synchronization period.
+ * @stall_ctrl:	Enables trace unit functionality that prevents trace
+ *		unit buffer overflows.
+ * @sysstall:	Does the system support stall control of the PE?
+ * @nooverflow:	Indicate if overflow prevention is supported.
+ * @atbtrig:	If the implementation can support ATB triggers
+ * @lpoverride:	If the implementation can support low-power state over.
+ * @config:	structure holding configuration parameters.
+ */
+struct etmv4_drvdata {
+	void __iomem			*base;
+	struct device			*dev;
+	struct coresight_device		*csdev;
+	spinlock_t			spinlock;
+	local_t				mode;
+	int				cpu;
+	u8				arch;
+	u8				nr_pe;
+	u8				nr_pe_cmp;
+	u8				nr_addr_cmp;
+	u8				nr_cntr;
+	u8				nr_ext_inp;
+	u8				numcidc;
+	u8				numvmidc;
+	u8				nrseqstate;
+	u8				nr_event;
+	u8				nr_resource;
+	u8				nr_ss_cmp;
+	u8				trcid;
+	u8				trcid_size;
+	u8				ts_size;
+	u8				ctxid_size;
+	u8				vmid_size;
+	u8				ccsize;
+	u8				ccitmin;
 	u8				s_ex_level;
 	u8				ns_ex_level;
-	u32				ext_inp;
+	u8				q_support;
+	bool				sticky_enable;
+	bool				boot_enable;
+	bool				os_unlock;
+	bool				instrp0;
+	bool				trcbb;
+	bool				trccond;
+	bool				retstack;
+	bool				trccci;
+	bool				trc_error;
+	bool				syncpr;
+	bool				stallctl;
+	bool				sysstall;
+	bool				nooverflow;
+	bool				atbtrig;
+	bool				lpoverride;
+	struct etmv4_config		config;
 };
 
 /* Address comparator access types */
@@ -391,4 +414,7 @@ enum etm_addr_type {
 	ETM_ADDR_TYPE_START,
 	ETM_ADDR_TYPE_STOP,
 };
+
+extern const struct attribute_group *coresight_etmv4_groups[];
+void etm4_config_trace_mode(struct etmv4_config *config);
 #endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c linux-libre-4.7-gnu/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
--- linux-libre-4.6-gnu/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,2126 @@
+/*
+ * Copyright(C) 2015 Linaro Limited. All rights reserved.
+ * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/pm_runtime.h>
+#include <linux/sysfs.h>
+#include "coresight-etm4x.h"
+
+static int etm4_set_mode_exclude(struct etmv4_drvdata *drvdata, bool exclude)
+{
+	u8 idx;
+	struct etmv4_config *config = &drvdata->config;
+
+	idx = config->addr_idx;
+
+	/*
+	 * TRCACATRn.TYPE bit[1:0]: type of comparison
+	 * the trace unit performs
+	 */
+	if (BMVAL(config->addr_acc[idx], 0, 1) == ETM_INSTR_ADDR) {
+		if (idx % 2 != 0)
+			return -EINVAL;
+
+		/*
+		 * We are performing instruction address comparison. Set the
+		 * relevant bit of ViewInst Include/Exclude Control register
+		 * for corresponding address comparator pair.
+		 */
+		if (config->addr_type[idx] != ETM_ADDR_TYPE_RANGE ||
+		    config->addr_type[idx + 1] != ETM_ADDR_TYPE_RANGE)
+			return -EINVAL;
+
+		if (exclude == true) {
+			/*
+			 * Set exclude bit and unset the include bit
+			 * corresponding to comparator pair
+			 */
+			config->viiectlr |= BIT(idx / 2 + 16);
+			config->viiectlr &= ~BIT(idx / 2);
+		} else {
+			/*
+			 * Set include bit and unset exclude bit
+			 * corresponding to comparator pair
+			 */
+			config->viiectlr |= BIT(idx / 2);
+			config->viiectlr &= ~BIT(idx / 2 + 16);
+		}
+	}
+	return 0;
+}
+
+static ssize_t nr_pe_cmp_show(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+	val = drvdata->nr_pe_cmp;
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+static DEVICE_ATTR_RO(nr_pe_cmp);
+
+static ssize_t nr_addr_cmp_show(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+	val = drvdata->nr_addr_cmp;
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+static DEVICE_ATTR_RO(nr_addr_cmp);
+
+static ssize_t nr_cntr_show(struct device *dev,
+			    struct device_attribute *attr,
+			    char *buf)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+	val = drvdata->nr_cntr;
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+static DEVICE_ATTR_RO(nr_cntr);
+
+static ssize_t nr_ext_inp_show(struct device *dev,
+			       struct device_attribute *attr,
+			       char *buf)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+	val = drvdata->nr_ext_inp;
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+static DEVICE_ATTR_RO(nr_ext_inp);
+
+static ssize_t numcidc_show(struct device *dev,
+			    struct device_attribute *attr,
+			    char *buf)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+	val = drvdata->numcidc;
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+static DEVICE_ATTR_RO(numcidc);
+
+static ssize_t numvmidc_show(struct device *dev,
+			     struct device_attribute *attr,
+			     char *buf)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+	val = drvdata->numvmidc;
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+static DEVICE_ATTR_RO(numvmidc);
+
+static ssize_t nrseqstate_show(struct device *dev,
+			       struct device_attribute *attr,
+			       char *buf)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+	val = drvdata->nrseqstate;
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+static DEVICE_ATTR_RO(nrseqstate);
+
+static ssize_t nr_resource_show(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+	val = drvdata->nr_resource;
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+static DEVICE_ATTR_RO(nr_resource);
+
+static ssize_t nr_ss_cmp_show(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+	val = drvdata->nr_ss_cmp;
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+static DEVICE_ATTR_RO(nr_ss_cmp);
+
+static ssize_t reset_store(struct device *dev,
+			   struct device_attribute *attr,
+			   const char *buf, size_t size)
+{
+	int i;
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	if (kstrtoul(buf, 16, &val))
+		return -EINVAL;
+
+	spin_lock(&drvdata->spinlock);
+	if (val)
+		config->mode = 0x0;
+
+	/* Disable data tracing: do not trace load and store data transfers */
+	config->mode &= ~(ETM_MODE_LOAD | ETM_MODE_STORE);
+	config->cfg &= ~(BIT(1) | BIT(2));
+
+	/* Disable data value and data address tracing */
+	config->mode &= ~(ETM_MODE_DATA_TRACE_ADDR |
+			   ETM_MODE_DATA_TRACE_VAL);
+	config->cfg &= ~(BIT(16) | BIT(17));
+
+	/* Disable all events tracing */
+	config->eventctrl0 = 0x0;
+	config->eventctrl1 = 0x0;
+
+	/* Disable timestamp event */
+	config->ts_ctrl = 0x0;
+
+	/* Disable stalling */
+	config->stall_ctrl = 0x0;
+
+	/* Reset trace synchronization period  to 2^8 = 256 bytes*/
+	if (drvdata->syncpr == false)
+		config->syncfreq = 0x8;
+
+	/*
+	 * Enable ViewInst to trace everything with start-stop logic in
+	 * started state. ARM recommends start-stop logic is set before
+	 * each trace run.
+	 */
+	config->vinst_ctrl |= BIT(0);
+	if (drvdata->nr_addr_cmp == true) {
+		config->mode |= ETM_MODE_VIEWINST_STARTSTOP;
+		/* SSSTATUS, bit[9] */
+		config->vinst_ctrl |= BIT(9);
+	}
+
+	/* No address range filtering for ViewInst */
+	config->viiectlr = 0x0;
+
+	/* No start-stop filtering for ViewInst */
+	config->vissctlr = 0x0;
+
+	/* Disable seq events */
+	for (i = 0; i < drvdata->nrseqstate-1; i++)
+		config->seq_ctrl[i] = 0x0;
+	config->seq_rst = 0x0;
+	config->seq_state = 0x0;
+
+	/* Disable external input events */
+	config->ext_inp = 0x0;
+
+	config->cntr_idx = 0x0;
+	for (i = 0; i < drvdata->nr_cntr; i++) {
+		config->cntrldvr[i] = 0x0;
+		config->cntr_ctrl[i] = 0x0;
+		config->cntr_val[i] = 0x0;
+	}
+
+	config->res_idx = 0x0;
+	for (i = 0; i < drvdata->nr_resource; i++)
+		config->res_ctrl[i] = 0x0;
+
+	for (i = 0; i < drvdata->nr_ss_cmp; i++) {
+		config->ss_ctrl[i] = 0x0;
+		config->ss_pe_cmp[i] = 0x0;
+	}
+
+	config->addr_idx = 0x0;
+	for (i = 0; i < drvdata->nr_addr_cmp * 2; i++) {
+		config->addr_val[i] = 0x0;
+		config->addr_acc[i] = 0x0;
+		config->addr_type[i] = ETM_ADDR_TYPE_NONE;
+	}
+
+	config->ctxid_idx = 0x0;
+	for (i = 0; i < drvdata->numcidc; i++) {
+		config->ctxid_pid[i] = 0x0;
+		config->ctxid_vpid[i] = 0x0;
+	}
+
+	config->ctxid_mask0 = 0x0;
+	config->ctxid_mask1 = 0x0;
+
+	config->vmid_idx = 0x0;
+	for (i = 0; i < drvdata->numvmidc; i++)
+		config->vmid_val[i] = 0x0;
+	config->vmid_mask0 = 0x0;
+	config->vmid_mask1 = 0x0;
+
+	drvdata->trcid = drvdata->cpu + 1;
+
+	spin_unlock(&drvdata->spinlock);
+
+	return size;
+}
+static DEVICE_ATTR_WO(reset);
+
+static ssize_t mode_show(struct device *dev,
+			 struct device_attribute *attr,
+			 char *buf)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	val = config->mode;
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t mode_store(struct device *dev,
+			  struct device_attribute *attr,
+			  const char *buf, size_t size)
+{
+	unsigned long val, mode;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	if (kstrtoul(buf, 16, &val))
+		return -EINVAL;
+
+	spin_lock(&drvdata->spinlock);
+	config->mode = val & ETMv4_MODE_ALL;
+
+	if (config->mode & ETM_MODE_EXCLUDE)
+		etm4_set_mode_exclude(drvdata, true);
+	else
+		etm4_set_mode_exclude(drvdata, false);
+
+	if (drvdata->instrp0 == true) {
+		/* start by clearing instruction P0 field */
+		config->cfg  &= ~(BIT(1) | BIT(2));
+		if (config->mode & ETM_MODE_LOAD)
+			/* 0b01 Trace load instructions as P0 instructions */
+			config->cfg  |= BIT(1);
+		if (config->mode & ETM_MODE_STORE)
+			/* 0b10 Trace store instructions as P0 instructions */
+			config->cfg  |= BIT(2);
+		if (config->mode & ETM_MODE_LOAD_STORE)
+			/*
+			 * 0b11 Trace load and store instructions
+			 * as P0 instructions
+			 */
+			config->cfg  |= BIT(1) | BIT(2);
+	}
+
+	/* bit[3], Branch broadcast mode */
+	if ((config->mode & ETM_MODE_BB) && (drvdata->trcbb == true))
+		config->cfg |= BIT(3);
+	else
+		config->cfg &= ~BIT(3);
+
+	/* bit[4], Cycle counting instruction trace bit */
+	if ((config->mode & ETMv4_MODE_CYCACC) &&
+		(drvdata->trccci == true))
+		config->cfg |= BIT(4);
+	else
+		config->cfg &= ~BIT(4);
+
+	/* bit[6], Context ID tracing bit */
+	if ((config->mode & ETMv4_MODE_CTXID) && (drvdata->ctxid_size))
+		config->cfg |= BIT(6);
+	else
+		config->cfg &= ~BIT(6);
+
+	if ((config->mode & ETM_MODE_VMID) && (drvdata->vmid_size))
+		config->cfg |= BIT(7);
+	else
+		config->cfg &= ~BIT(7);
+
+	/* bits[10:8], Conditional instruction tracing bit */
+	mode = ETM_MODE_COND(config->mode);
+	if (drvdata->trccond == true) {
+		config->cfg &= ~(BIT(8) | BIT(9) | BIT(10));
+		config->cfg |= mode << 8;
+	}
+
+	/* bit[11], Global timestamp tracing bit */
+	if ((config->mode & ETMv4_MODE_TIMESTAMP) && (drvdata->ts_size))
+		config->cfg |= BIT(11);
+	else
+		config->cfg &= ~BIT(11);
+
+	/* bit[12], Return stack enable bit */
+	if ((config->mode & ETM_MODE_RETURNSTACK) &&
+					(drvdata->retstack == true))
+		config->cfg |= BIT(12);
+	else
+		config->cfg &= ~BIT(12);
+
+	/* bits[14:13], Q element enable field */
+	mode = ETM_MODE_QELEM(config->mode);
+	/* start by clearing QE bits */
+	config->cfg &= ~(BIT(13) | BIT(14));
+	/* if supported, Q elements with instruction counts are enabled */
+	if ((mode & BIT(0)) && (drvdata->q_support & BIT(0)))
+		config->cfg |= BIT(13);
+	/*
+	 * if supported, Q elements with and without instruction
+	 * counts are enabled
+	 */
+	if ((mode & BIT(1)) && (drvdata->q_support & BIT(1)))
+		config->cfg |= BIT(14);
+
+	/* bit[11], AMBA Trace Bus (ATB) trigger enable bit */
+	if ((config->mode & ETM_MODE_ATB_TRIGGER) &&
+	    (drvdata->atbtrig == true))
+		config->eventctrl1 |= BIT(11);
+	else
+		config->eventctrl1 &= ~BIT(11);
+
+	/* bit[12], Low-power state behavior override bit */
+	if ((config->mode & ETM_MODE_LPOVERRIDE) &&
+	    (drvdata->lpoverride == true))
+		config->eventctrl1 |= BIT(12);
+	else
+		config->eventctrl1 &= ~BIT(12);
+
+	/* bit[8], Instruction stall bit */
+	if (config->mode & ETM_MODE_ISTALL_EN)
+		config->stall_ctrl |= BIT(8);
+	else
+		config->stall_ctrl &= ~BIT(8);
+
+	/* bit[10], Prioritize instruction trace bit */
+	if (config->mode & ETM_MODE_INSTPRIO)
+		config->stall_ctrl |= BIT(10);
+	else
+		config->stall_ctrl &= ~BIT(10);
+
+	/* bit[13], Trace overflow prevention bit */
+	if ((config->mode & ETM_MODE_NOOVERFLOW) &&
+		(drvdata->nooverflow == true))
+		config->stall_ctrl |= BIT(13);
+	else
+		config->stall_ctrl &= ~BIT(13);
+
+	/* bit[9] Start/stop logic control bit */
+	if (config->mode & ETM_MODE_VIEWINST_STARTSTOP)
+		config->vinst_ctrl |= BIT(9);
+	else
+		config->vinst_ctrl &= ~BIT(9);
+
+	/* bit[10], Whether a trace unit must trace a Reset exception */
+	if (config->mode & ETM_MODE_TRACE_RESET)
+		config->vinst_ctrl |= BIT(10);
+	else
+		config->vinst_ctrl &= ~BIT(10);
+
+	/* bit[11], Whether a trace unit must trace a system error exception */
+	if ((config->mode & ETM_MODE_TRACE_ERR) &&
+		(drvdata->trc_error == true))
+		config->vinst_ctrl |= BIT(11);
+	else
+		config->vinst_ctrl &= ~BIT(11);
+
+	if (config->mode & (ETM_MODE_EXCL_KERN | ETM_MODE_EXCL_USER))
+		etm4_config_trace_mode(config);
+
+	spin_unlock(&drvdata->spinlock);
+
+	return size;
+}
+static DEVICE_ATTR_RW(mode);
+
+static ssize_t pe_show(struct device *dev,
+		       struct device_attribute *attr,
+		       char *buf)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	val = config->pe_sel;
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t pe_store(struct device *dev,
+			struct device_attribute *attr,
+			const char *buf, size_t size)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	if (kstrtoul(buf, 16, &val))
+		return -EINVAL;
+
+	spin_lock(&drvdata->spinlock);
+	if (val > drvdata->nr_pe) {
+		spin_unlock(&drvdata->spinlock);
+		return -EINVAL;
+	}
+
+	config->pe_sel = val;
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR_RW(pe);
+
+static ssize_t event_show(struct device *dev,
+			  struct device_attribute *attr,
+			  char *buf)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	val = config->eventctrl0;
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t event_store(struct device *dev,
+			   struct device_attribute *attr,
+			   const char *buf, size_t size)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	if (kstrtoul(buf, 16, &val))
+		return -EINVAL;
+
+	spin_lock(&drvdata->spinlock);
+	switch (drvdata->nr_event) {
+	case 0x0:
+		/* EVENT0, bits[7:0] */
+		config->eventctrl0 = val & 0xFF;
+		break;
+	case 0x1:
+		 /* EVENT1, bits[15:8] */
+		config->eventctrl0 = val & 0xFFFF;
+		break;
+	case 0x2:
+		/* EVENT2, bits[23:16] */
+		config->eventctrl0 = val & 0xFFFFFF;
+		break;
+	case 0x3:
+		/* EVENT3, bits[31:24] */
+		config->eventctrl0 = val;
+		break;
+	default:
+		break;
+	}
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR_RW(event);
+
+static ssize_t event_instren_show(struct device *dev,
+				  struct device_attribute *attr,
+				  char *buf)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	val = BMVAL(config->eventctrl1, 0, 3);
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t event_instren_store(struct device *dev,
+				   struct device_attribute *attr,
+				   const char *buf, size_t size)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	if (kstrtoul(buf, 16, &val))
+		return -EINVAL;
+
+	spin_lock(&drvdata->spinlock);
+	/* start by clearing all instruction event enable bits */
+	config->eventctrl1 &= ~(BIT(0) | BIT(1) | BIT(2) | BIT(3));
+	switch (drvdata->nr_event) {
+	case 0x0:
+		/* generate Event element for event 1 */
+		config->eventctrl1 |= val & BIT(1);
+		break;
+	case 0x1:
+		/* generate Event element for event 1 and 2 */
+		config->eventctrl1 |= val & (BIT(0) | BIT(1));
+		break;
+	case 0x2:
+		/* generate Event element for event 1, 2 and 3 */
+		config->eventctrl1 |= val & (BIT(0) | BIT(1) | BIT(2));
+		break;
+	case 0x3:
+		/* generate Event element for all 4 events */
+		config->eventctrl1 |= val & 0xF;
+		break;
+	default:
+		break;
+	}
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR_RW(event_instren);
+
+static ssize_t event_ts_show(struct device *dev,
+			     struct device_attribute *attr,
+			     char *buf)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	val = config->ts_ctrl;
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t event_ts_store(struct device *dev,
+			      struct device_attribute *attr,
+			      const char *buf, size_t size)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	if (kstrtoul(buf, 16, &val))
+		return -EINVAL;
+	if (!drvdata->ts_size)
+		return -EINVAL;
+
+	config->ts_ctrl = val & ETMv4_EVENT_MASK;
+	return size;
+}
+static DEVICE_ATTR_RW(event_ts);
+
+static ssize_t syncfreq_show(struct device *dev,
+			     struct device_attribute *attr,
+			     char *buf)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	val = config->syncfreq;
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t syncfreq_store(struct device *dev,
+			      struct device_attribute *attr,
+			      const char *buf, size_t size)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	if (kstrtoul(buf, 16, &val))
+		return -EINVAL;
+	if (drvdata->syncpr == true)
+		return -EINVAL;
+
+	config->syncfreq = val & ETMv4_SYNC_MASK;
+	return size;
+}
+static DEVICE_ATTR_RW(syncfreq);
+
+static ssize_t cyc_threshold_show(struct device *dev,
+				  struct device_attribute *attr,
+				  char *buf)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	val = config->ccctlr;
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t cyc_threshold_store(struct device *dev,
+				   struct device_attribute *attr,
+				   const char *buf, size_t size)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	if (kstrtoul(buf, 16, &val))
+		return -EINVAL;
+	if (val < drvdata->ccitmin)
+		return -EINVAL;
+
+	config->ccctlr = val & ETM_CYC_THRESHOLD_MASK;
+	return size;
+}
+static DEVICE_ATTR_RW(cyc_threshold);
+
+static ssize_t bb_ctrl_show(struct device *dev,
+			    struct device_attribute *attr,
+			    char *buf)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	val = config->bb_ctrl;
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t bb_ctrl_store(struct device *dev,
+			     struct device_attribute *attr,
+			     const char *buf, size_t size)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	if (kstrtoul(buf, 16, &val))
+		return -EINVAL;
+	if (drvdata->trcbb == false)
+		return -EINVAL;
+	if (!drvdata->nr_addr_cmp)
+		return -EINVAL;
+	/*
+	 * Bit[7:0] selects which address range comparator is used for
+	 * branch broadcast control.
+	 */
+	if (BMVAL(val, 0, 7) > drvdata->nr_addr_cmp)
+		return -EINVAL;
+
+	config->bb_ctrl = val;
+	return size;
+}
+static DEVICE_ATTR_RW(bb_ctrl);
+
+static ssize_t event_vinst_show(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	val = config->vinst_ctrl & ETMv4_EVENT_MASK;
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t event_vinst_store(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t size)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	if (kstrtoul(buf, 16, &val))
+		return -EINVAL;
+
+	spin_lock(&drvdata->spinlock);
+	val &= ETMv4_EVENT_MASK;
+	config->vinst_ctrl &= ~ETMv4_EVENT_MASK;
+	config->vinst_ctrl |= val;
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR_RW(event_vinst);
+
+static ssize_t s_exlevel_vinst_show(struct device *dev,
+				    struct device_attribute *attr,
+				    char *buf)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	val = BMVAL(config->vinst_ctrl, 16, 19);
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t s_exlevel_vinst_store(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t size)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	if (kstrtoul(buf, 16, &val))
+		return -EINVAL;
+
+	spin_lock(&drvdata->spinlock);
+	/* clear all EXLEVEL_S bits (bit[18] is never implemented) */
+	config->vinst_ctrl &= ~(BIT(16) | BIT(17) | BIT(19));
+	/* enable instruction tracing for corresponding exception level */
+	val &= drvdata->s_ex_level;
+	config->vinst_ctrl |= (val << 16);
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR_RW(s_exlevel_vinst);
+
+static ssize_t ns_exlevel_vinst_show(struct device *dev,
+				     struct device_attribute *attr,
+				     char *buf)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	/* EXLEVEL_NS, bits[23:20] */
+	val = BMVAL(config->vinst_ctrl, 20, 23);
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t ns_exlevel_vinst_store(struct device *dev,
+				      struct device_attribute *attr,
+				      const char *buf, size_t size)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	if (kstrtoul(buf, 16, &val))
+		return -EINVAL;
+
+	spin_lock(&drvdata->spinlock);
+	/* clear EXLEVEL_NS bits (bit[23] is never implemented */
+	config->vinst_ctrl &= ~(BIT(20) | BIT(21) | BIT(22));
+	/* enable instruction tracing for corresponding exception level */
+	val &= drvdata->ns_ex_level;
+	config->vinst_ctrl |= (val << 20);
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR_RW(ns_exlevel_vinst);
+
+static ssize_t addr_idx_show(struct device *dev,
+			     struct device_attribute *attr,
+			     char *buf)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	val = config->addr_idx;
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t addr_idx_store(struct device *dev,
+			      struct device_attribute *attr,
+			      const char *buf, size_t size)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	if (kstrtoul(buf, 16, &val))
+		return -EINVAL;
+	if (val >= drvdata->nr_addr_cmp * 2)
+		return -EINVAL;
+
+	/*
+	 * Use spinlock to ensure index doesn't change while it gets
+	 * dereferenced multiple times within a spinlock block elsewhere.
+	 */
+	spin_lock(&drvdata->spinlock);
+	config->addr_idx = val;
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR_RW(addr_idx);
+
+static ssize_t addr_instdatatype_show(struct device *dev,
+				      struct device_attribute *attr,
+				      char *buf)
+{
+	ssize_t len;
+	u8 val, idx;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	spin_lock(&drvdata->spinlock);
+	idx = config->addr_idx;
+	val = BMVAL(config->addr_acc[idx], 0, 1);
+	len = scnprintf(buf, PAGE_SIZE, "%s\n",
+			val == ETM_INSTR_ADDR ? "instr" :
+			(val == ETM_DATA_LOAD_ADDR ? "data_load" :
+			(val == ETM_DATA_STORE_ADDR ? "data_store" :
+			"data_load_store")));
+	spin_unlock(&drvdata->spinlock);
+	return len;
+}
+
+static ssize_t addr_instdatatype_store(struct device *dev,
+				       struct device_attribute *attr,
+				       const char *buf, size_t size)
+{
+	u8 idx;
+	char str[20] = "";
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	if (strlen(buf) >= 20)
+		return -EINVAL;
+	if (sscanf(buf, "%s", str) != 1)
+		return -EINVAL;
+
+	spin_lock(&drvdata->spinlock);
+	idx = config->addr_idx;
+	if (!strcmp(str, "instr"))
+		/* TYPE, bits[1:0] */
+		config->addr_acc[idx] &= ~(BIT(0) | BIT(1));
+
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR_RW(addr_instdatatype);
+
+static ssize_t addr_single_show(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	u8 idx;
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	idx = config->addr_idx;
+	spin_lock(&drvdata->spinlock);
+	if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
+	      config->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
+		spin_unlock(&drvdata->spinlock);
+		return -EPERM;
+	}
+	val = (unsigned long)config->addr_val[idx];
+	spin_unlock(&drvdata->spinlock);
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t addr_single_store(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t size)
+{
+	u8 idx;
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	if (kstrtoul(buf, 16, &val))
+		return -EINVAL;
+
+	spin_lock(&drvdata->spinlock);
+	idx = config->addr_idx;
+	if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
+	      config->addr_type[idx] == ETM_ADDR_TYPE_SINGLE)) {
+		spin_unlock(&drvdata->spinlock);
+		return -EPERM;
+	}
+
+	config->addr_val[idx] = (u64)val;
+	config->addr_type[idx] = ETM_ADDR_TYPE_SINGLE;
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR_RW(addr_single);
+
+static ssize_t addr_range_show(struct device *dev,
+			       struct device_attribute *attr,
+			       char *buf)
+{
+	u8 idx;
+	unsigned long val1, val2;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	spin_lock(&drvdata->spinlock);
+	idx = config->addr_idx;
+	if (idx % 2 != 0) {
+		spin_unlock(&drvdata->spinlock);
+		return -EPERM;
+	}
+	if (!((config->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
+	       config->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
+	      (config->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
+	       config->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
+		spin_unlock(&drvdata->spinlock);
+		return -EPERM;
+	}
+
+	val1 = (unsigned long)config->addr_val[idx];
+	val2 = (unsigned long)config->addr_val[idx + 1];
+	spin_unlock(&drvdata->spinlock);
+	return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
+}
+
+static ssize_t addr_range_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t size)
+{
+	u8 idx;
+	unsigned long val1, val2;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	if (sscanf(buf, "%lx %lx", &val1, &val2) != 2)
+		return -EINVAL;
+	/* lower address comparator cannot have a higher address value */
+	if (val1 > val2)
+		return -EINVAL;
+
+	spin_lock(&drvdata->spinlock);
+	idx = config->addr_idx;
+	if (idx % 2 != 0) {
+		spin_unlock(&drvdata->spinlock);
+		return -EPERM;
+	}
+
+	if (!((config->addr_type[idx] == ETM_ADDR_TYPE_NONE &&
+	       config->addr_type[idx + 1] == ETM_ADDR_TYPE_NONE) ||
+	      (config->addr_type[idx] == ETM_ADDR_TYPE_RANGE &&
+	       config->addr_type[idx + 1] == ETM_ADDR_TYPE_RANGE))) {
+		spin_unlock(&drvdata->spinlock);
+		return -EPERM;
+	}
+
+	config->addr_val[idx] = (u64)val1;
+	config->addr_type[idx] = ETM_ADDR_TYPE_RANGE;
+	config->addr_val[idx + 1] = (u64)val2;
+	config->addr_type[idx + 1] = ETM_ADDR_TYPE_RANGE;
+	/*
+	 * Program include or exclude control bits for vinst or vdata
+	 * whenever we change addr comparators to ETM_ADDR_TYPE_RANGE
+	 */
+	if (config->mode & ETM_MODE_EXCLUDE)
+		etm4_set_mode_exclude(drvdata, true);
+	else
+		etm4_set_mode_exclude(drvdata, false);
+
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR_RW(addr_range);
+
+static ssize_t addr_start_show(struct device *dev,
+			       struct device_attribute *attr,
+			       char *buf)
+{
+	u8 idx;
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	spin_lock(&drvdata->spinlock);
+	idx = config->addr_idx;
+
+	if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
+	      config->addr_type[idx] == ETM_ADDR_TYPE_START)) {
+		spin_unlock(&drvdata->spinlock);
+		return -EPERM;
+	}
+
+	val = (unsigned long)config->addr_val[idx];
+	spin_unlock(&drvdata->spinlock);
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t addr_start_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t size)
+{
+	u8 idx;
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	if (kstrtoul(buf, 16, &val))
+		return -EINVAL;
+
+	spin_lock(&drvdata->spinlock);
+	idx = config->addr_idx;
+	if (!drvdata->nr_addr_cmp) {
+		spin_unlock(&drvdata->spinlock);
+		return -EINVAL;
+	}
+	if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
+	      config->addr_type[idx] == ETM_ADDR_TYPE_START)) {
+		spin_unlock(&drvdata->spinlock);
+		return -EPERM;
+	}
+
+	config->addr_val[idx] = (u64)val;
+	config->addr_type[idx] = ETM_ADDR_TYPE_START;
+	config->vissctlr |= BIT(idx);
+	/* SSSTATUS, bit[9] - turn on start/stop logic */
+	config->vinst_ctrl |= BIT(9);
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR_RW(addr_start);
+
+static ssize_t addr_stop_show(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	u8 idx;
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	spin_lock(&drvdata->spinlock);
+	idx = config->addr_idx;
+
+	if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
+	      config->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
+		spin_unlock(&drvdata->spinlock);
+		return -EPERM;
+	}
+
+	val = (unsigned long)config->addr_val[idx];
+	spin_unlock(&drvdata->spinlock);
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t addr_stop_store(struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buf, size_t size)
+{
+	u8 idx;
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	if (kstrtoul(buf, 16, &val))
+		return -EINVAL;
+
+	spin_lock(&drvdata->spinlock);
+	idx = config->addr_idx;
+	if (!drvdata->nr_addr_cmp) {
+		spin_unlock(&drvdata->spinlock);
+		return -EINVAL;
+	}
+	if (!(config->addr_type[idx] == ETM_ADDR_TYPE_NONE ||
+	       config->addr_type[idx] == ETM_ADDR_TYPE_STOP)) {
+		spin_unlock(&drvdata->spinlock);
+		return -EPERM;
+	}
+
+	config->addr_val[idx] = (u64)val;
+	config->addr_type[idx] = ETM_ADDR_TYPE_STOP;
+	config->vissctlr |= BIT(idx + 16);
+	/* SSSTATUS, bit[9] - turn on start/stop logic */
+	config->vinst_ctrl |= BIT(9);
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR_RW(addr_stop);
+
+static ssize_t addr_ctxtype_show(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buf)
+{
+	ssize_t len;
+	u8 idx, val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	spin_lock(&drvdata->spinlock);
+	idx = config->addr_idx;
+	/* CONTEXTTYPE, bits[3:2] */
+	val = BMVAL(config->addr_acc[idx], 2, 3);
+	len = scnprintf(buf, PAGE_SIZE, "%s\n", val == ETM_CTX_NONE ? "none" :
+			(val == ETM_CTX_CTXID ? "ctxid" :
+			(val == ETM_CTX_VMID ? "vmid" : "all")));
+	spin_unlock(&drvdata->spinlock);
+	return len;
+}
+
+static ssize_t addr_ctxtype_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t size)
+{
+	u8 idx;
+	char str[10] = "";
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	if (strlen(buf) >= 10)
+		return -EINVAL;
+	if (sscanf(buf, "%s", str) != 1)
+		return -EINVAL;
+
+	spin_lock(&drvdata->spinlock);
+	idx = config->addr_idx;
+	if (!strcmp(str, "none"))
+		/* start by clearing context type bits */
+		config->addr_acc[idx] &= ~(BIT(2) | BIT(3));
+	else if (!strcmp(str, "ctxid")) {
+		/* 0b01 The trace unit performs a Context ID */
+		if (drvdata->numcidc) {
+			config->addr_acc[idx] |= BIT(2);
+			config->addr_acc[idx] &= ~BIT(3);
+		}
+	} else if (!strcmp(str, "vmid")) {
+		/* 0b10 The trace unit performs a VMID */
+		if (drvdata->numvmidc) {
+			config->addr_acc[idx] &= ~BIT(2);
+			config->addr_acc[idx] |= BIT(3);
+		}
+	} else if (!strcmp(str, "all")) {
+		/*
+		 * 0b11 The trace unit performs a Context ID
+		 * comparison and a VMID
+		 */
+		if (drvdata->numcidc)
+			config->addr_acc[idx] |= BIT(2);
+		if (drvdata->numvmidc)
+			config->addr_acc[idx] |= BIT(3);
+	}
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR_RW(addr_ctxtype);
+
+static ssize_t addr_context_show(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buf)
+{
+	u8 idx;
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	spin_lock(&drvdata->spinlock);
+	idx = config->addr_idx;
+	/* context ID comparator bits[6:4] */
+	val = BMVAL(config->addr_acc[idx], 4, 6);
+	spin_unlock(&drvdata->spinlock);
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t addr_context_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t size)
+{
+	u8 idx;
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	if (kstrtoul(buf, 16, &val))
+		return -EINVAL;
+	if ((drvdata->numcidc <= 1) && (drvdata->numvmidc <= 1))
+		return -EINVAL;
+	if (val >=  (drvdata->numcidc >= drvdata->numvmidc ?
+		     drvdata->numcidc : drvdata->numvmidc))
+		return -EINVAL;
+
+	spin_lock(&drvdata->spinlock);
+	idx = config->addr_idx;
+	/* clear context ID comparator bits[6:4] */
+	config->addr_acc[idx] &= ~(BIT(4) | BIT(5) | BIT(6));
+	config->addr_acc[idx] |= (val << 4);
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR_RW(addr_context);
+
+static ssize_t seq_idx_show(struct device *dev,
+			    struct device_attribute *attr,
+			    char *buf)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	val = config->seq_idx;
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t seq_idx_store(struct device *dev,
+			     struct device_attribute *attr,
+			     const char *buf, size_t size)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	if (kstrtoul(buf, 16, &val))
+		return -EINVAL;
+	if (val >= drvdata->nrseqstate - 1)
+		return -EINVAL;
+
+	/*
+	 * Use spinlock to ensure index doesn't change while it gets
+	 * dereferenced multiple times within a spinlock block elsewhere.
+	 */
+	spin_lock(&drvdata->spinlock);
+	config->seq_idx = val;
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR_RW(seq_idx);
+
+static ssize_t seq_state_show(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	val = config->seq_state;
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t seq_state_store(struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buf, size_t size)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	if (kstrtoul(buf, 16, &val))
+		return -EINVAL;
+	if (val >= drvdata->nrseqstate)
+		return -EINVAL;
+
+	config->seq_state = val;
+	return size;
+}
+static DEVICE_ATTR_RW(seq_state);
+
+static ssize_t seq_event_show(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	u8 idx;
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	spin_lock(&drvdata->spinlock);
+	idx = config->seq_idx;
+	val = config->seq_ctrl[idx];
+	spin_unlock(&drvdata->spinlock);
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t seq_event_store(struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buf, size_t size)
+{
+	u8 idx;
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	if (kstrtoul(buf, 16, &val))
+		return -EINVAL;
+
+	spin_lock(&drvdata->spinlock);
+	idx = config->seq_idx;
+	/* RST, bits[7:0] */
+	config->seq_ctrl[idx] = val & 0xFF;
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR_RW(seq_event);
+
+static ssize_t seq_reset_event_show(struct device *dev,
+				    struct device_attribute *attr,
+				    char *buf)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	val = config->seq_rst;
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t seq_reset_event_store(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t size)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	if (kstrtoul(buf, 16, &val))
+		return -EINVAL;
+	if (!(drvdata->nrseqstate))
+		return -EINVAL;
+
+	config->seq_rst = val & ETMv4_EVENT_MASK;
+	return size;
+}
+static DEVICE_ATTR_RW(seq_reset_event);
+
+static ssize_t cntr_idx_show(struct device *dev,
+			     struct device_attribute *attr,
+			     char *buf)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	val = config->cntr_idx;
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t cntr_idx_store(struct device *dev,
+			      struct device_attribute *attr,
+			      const char *buf, size_t size)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	if (kstrtoul(buf, 16, &val))
+		return -EINVAL;
+	if (val >= drvdata->nr_cntr)
+		return -EINVAL;
+
+	/*
+	 * Use spinlock to ensure index doesn't change while it gets
+	 * dereferenced multiple times within a spinlock block elsewhere.
+	 */
+	spin_lock(&drvdata->spinlock);
+	config->cntr_idx = val;
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR_RW(cntr_idx);
+
+static ssize_t cntrldvr_show(struct device *dev,
+			     struct device_attribute *attr,
+			     char *buf)
+{
+	u8 idx;
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	spin_lock(&drvdata->spinlock);
+	idx = config->cntr_idx;
+	val = config->cntrldvr[idx];
+	spin_unlock(&drvdata->spinlock);
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t cntrldvr_store(struct device *dev,
+			      struct device_attribute *attr,
+			      const char *buf, size_t size)
+{
+	u8 idx;
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	if (kstrtoul(buf, 16, &val))
+		return -EINVAL;
+	if (val > ETM_CNTR_MAX_VAL)
+		return -EINVAL;
+
+	spin_lock(&drvdata->spinlock);
+	idx = config->cntr_idx;
+	config->cntrldvr[idx] = val;
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR_RW(cntrldvr);
+
+static ssize_t cntr_val_show(struct device *dev,
+			     struct device_attribute *attr,
+			     char *buf)
+{
+	u8 idx;
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	spin_lock(&drvdata->spinlock);
+	idx = config->cntr_idx;
+	val = config->cntr_val[idx];
+	spin_unlock(&drvdata->spinlock);
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t cntr_val_store(struct device *dev,
+			      struct device_attribute *attr,
+			      const char *buf, size_t size)
+{
+	u8 idx;
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	if (kstrtoul(buf, 16, &val))
+		return -EINVAL;
+	if (val > ETM_CNTR_MAX_VAL)
+		return -EINVAL;
+
+	spin_lock(&drvdata->spinlock);
+	idx = config->cntr_idx;
+	config->cntr_val[idx] = val;
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR_RW(cntr_val);
+
+static ssize_t cntr_ctrl_show(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	u8 idx;
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	spin_lock(&drvdata->spinlock);
+	idx = config->cntr_idx;
+	val = config->cntr_ctrl[idx];
+	spin_unlock(&drvdata->spinlock);
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t cntr_ctrl_store(struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buf, size_t size)
+{
+	u8 idx;
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	if (kstrtoul(buf, 16, &val))
+		return -EINVAL;
+
+	spin_lock(&drvdata->spinlock);
+	idx = config->cntr_idx;
+	config->cntr_ctrl[idx] = val;
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR_RW(cntr_ctrl);
+
+static ssize_t res_idx_show(struct device *dev,
+			    struct device_attribute *attr,
+			    char *buf)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	val = config->res_idx;
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t res_idx_store(struct device *dev,
+			     struct device_attribute *attr,
+			     const char *buf, size_t size)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	if (kstrtoul(buf, 16, &val))
+		return -EINVAL;
+	/* Resource selector pair 0 is always implemented and reserved */
+	if ((val == 0) || (val >= drvdata->nr_resource))
+		return -EINVAL;
+
+	/*
+	 * Use spinlock to ensure index doesn't change while it gets
+	 * dereferenced multiple times within a spinlock block elsewhere.
+	 */
+	spin_lock(&drvdata->spinlock);
+	config->res_idx = val;
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR_RW(res_idx);
+
+static ssize_t res_ctrl_show(struct device *dev,
+			     struct device_attribute *attr,
+			     char *buf)
+{
+	u8 idx;
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	spin_lock(&drvdata->spinlock);
+	idx = config->res_idx;
+	val = config->res_ctrl[idx];
+	spin_unlock(&drvdata->spinlock);
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t res_ctrl_store(struct device *dev,
+			      struct device_attribute *attr,
+			      const char *buf, size_t size)
+{
+	u8 idx;
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	if (kstrtoul(buf, 16, &val))
+		return -EINVAL;
+
+	spin_lock(&drvdata->spinlock);
+	idx = config->res_idx;
+	/* For odd idx pair inversal bit is RES0 */
+	if (idx % 2 != 0)
+		/* PAIRINV, bit[21] */
+		val &= ~BIT(21);
+	config->res_ctrl[idx] = val;
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR_RW(res_ctrl);
+
+static ssize_t ctxid_idx_show(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	val = config->ctxid_idx;
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t ctxid_idx_store(struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buf, size_t size)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	if (kstrtoul(buf, 16, &val))
+		return -EINVAL;
+	if (val >= drvdata->numcidc)
+		return -EINVAL;
+
+	/*
+	 * Use spinlock to ensure index doesn't change while it gets
+	 * dereferenced multiple times within a spinlock block elsewhere.
+	 */
+	spin_lock(&drvdata->spinlock);
+	config->ctxid_idx = val;
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR_RW(ctxid_idx);
+
+static ssize_t ctxid_pid_show(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	u8 idx;
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	spin_lock(&drvdata->spinlock);
+	idx = config->ctxid_idx;
+	val = (unsigned long)config->ctxid_vpid[idx];
+	spin_unlock(&drvdata->spinlock);
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t ctxid_pid_store(struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buf, size_t size)
+{
+	u8 idx;
+	unsigned long vpid, pid;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	/*
+	 * only implemented when ctxid tracing is enabled, i.e. at least one
+	 * ctxid comparator is implemented and ctxid is greater than 0 bits
+	 * in length
+	 */
+	if (!drvdata->ctxid_size || !drvdata->numcidc)
+		return -EINVAL;
+	if (kstrtoul(buf, 16, &vpid))
+		return -EINVAL;
+
+	pid = coresight_vpid_to_pid(vpid);
+
+	spin_lock(&drvdata->spinlock);
+	idx = config->ctxid_idx;
+	config->ctxid_pid[idx] = (u64)pid;
+	config->ctxid_vpid[idx] = (u64)vpid;
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR_RW(ctxid_pid);
+
+static ssize_t ctxid_masks_show(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	unsigned long val1, val2;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	spin_lock(&drvdata->spinlock);
+	val1 = config->ctxid_mask0;
+	val2 = config->ctxid_mask1;
+	spin_unlock(&drvdata->spinlock);
+	return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
+}
+
+static ssize_t ctxid_masks_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t size)
+{
+	u8 i, j, maskbyte;
+	unsigned long val1, val2, mask;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	/*
+	 * only implemented when ctxid tracing is enabled, i.e. at least one
+	 * ctxid comparator is implemented and ctxid is greater than 0 bits
+	 * in length
+	 */
+	if (!drvdata->ctxid_size || !drvdata->numcidc)
+		return -EINVAL;
+	if (sscanf(buf, "%lx %lx", &val1, &val2) != 2)
+		return -EINVAL;
+
+	spin_lock(&drvdata->spinlock);
+	/*
+	 * each byte[0..3] controls mask value applied to ctxid
+	 * comparator[0..3]
+	 */
+	switch (drvdata->numcidc) {
+	case 0x1:
+		/* COMP0, bits[7:0] */
+		config->ctxid_mask0 = val1 & 0xFF;
+		break;
+	case 0x2:
+		/* COMP1, bits[15:8] */
+		config->ctxid_mask0 = val1 & 0xFFFF;
+		break;
+	case 0x3:
+		/* COMP2, bits[23:16] */
+		config->ctxid_mask0 = val1 & 0xFFFFFF;
+		break;
+	case 0x4:
+		 /* COMP3, bits[31:24] */
+		config->ctxid_mask0 = val1;
+		break;
+	case 0x5:
+		/* COMP4, bits[7:0] */
+		config->ctxid_mask0 = val1;
+		config->ctxid_mask1 = val2 & 0xFF;
+		break;
+	case 0x6:
+		/* COMP5, bits[15:8] */
+		config->ctxid_mask0 = val1;
+		config->ctxid_mask1 = val2 & 0xFFFF;
+		break;
+	case 0x7:
+		/* COMP6, bits[23:16] */
+		config->ctxid_mask0 = val1;
+		config->ctxid_mask1 = val2 & 0xFFFFFF;
+		break;
+	case 0x8:
+		/* COMP7, bits[31:24] */
+		config->ctxid_mask0 = val1;
+		config->ctxid_mask1 = val2;
+		break;
+	default:
+		break;
+	}
+	/*
+	 * If software sets a mask bit to 1, it must program relevant byte
+	 * of ctxid comparator value 0x0, otherwise behavior is unpredictable.
+	 * For example, if bit[3] of ctxid_mask0 is 1, we must clear bits[31:24]
+	 * of ctxid comparator0 value (corresponding to byte 0) register.
+	 */
+	mask = config->ctxid_mask0;
+	for (i = 0; i < drvdata->numcidc; i++) {
+		/* mask value of corresponding ctxid comparator */
+		maskbyte = mask & ETMv4_EVENT_MASK;
+		/*
+		 * each bit corresponds to a byte of respective ctxid comparator
+		 * value register
+		 */
+		for (j = 0; j < 8; j++) {
+			if (maskbyte & 1)
+				config->ctxid_pid[i] &= ~(0xFF << (j * 8));
+			maskbyte >>= 1;
+		}
+		/* Select the next ctxid comparator mask value */
+		if (i == 3)
+			/* ctxid comparators[4-7] */
+			mask = config->ctxid_mask1;
+		else
+			mask >>= 0x8;
+	}
+
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR_RW(ctxid_masks);
+
+static ssize_t vmid_idx_show(struct device *dev,
+			     struct device_attribute *attr,
+			     char *buf)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	val = config->vmid_idx;
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t vmid_idx_store(struct device *dev,
+			      struct device_attribute *attr,
+			      const char *buf, size_t size)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	if (kstrtoul(buf, 16, &val))
+		return -EINVAL;
+	if (val >= drvdata->numvmidc)
+		return -EINVAL;
+
+	/*
+	 * Use spinlock to ensure index doesn't change while it gets
+	 * dereferenced multiple times within a spinlock block elsewhere.
+	 */
+	spin_lock(&drvdata->spinlock);
+	config->vmid_idx = val;
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR_RW(vmid_idx);
+
+static ssize_t vmid_val_show(struct device *dev,
+			     struct device_attribute *attr,
+			     char *buf)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	val = (unsigned long)config->vmid_val[config->vmid_idx];
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t vmid_val_store(struct device *dev,
+			      struct device_attribute *attr,
+			      const char *buf, size_t size)
+{
+	unsigned long val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	/*
+	 * only implemented when vmid tracing is enabled, i.e. at least one
+	 * vmid comparator is implemented and at least 8 bit vmid size
+	 */
+	if (!drvdata->vmid_size || !drvdata->numvmidc)
+		return -EINVAL;
+	if (kstrtoul(buf, 16, &val))
+		return -EINVAL;
+
+	spin_lock(&drvdata->spinlock);
+	config->vmid_val[config->vmid_idx] = (u64)val;
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR_RW(vmid_val);
+
+static ssize_t vmid_masks_show(struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+	unsigned long val1, val2;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	spin_lock(&drvdata->spinlock);
+	val1 = config->vmid_mask0;
+	val2 = config->vmid_mask1;
+	spin_unlock(&drvdata->spinlock);
+	return scnprintf(buf, PAGE_SIZE, "%#lx %#lx\n", val1, val2);
+}
+
+static ssize_t vmid_masks_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t size)
+{
+	u8 i, j, maskbyte;
+	unsigned long val1, val2, mask;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	struct etmv4_config *config = &drvdata->config;
+
+	/*
+	 * only implemented when vmid tracing is enabled, i.e. at least one
+	 * vmid comparator is implemented and at least 8 bit vmid size
+	 */
+	if (!drvdata->vmid_size || !drvdata->numvmidc)
+		return -EINVAL;
+	if (sscanf(buf, "%lx %lx", &val1, &val2) != 2)
+		return -EINVAL;
+
+	spin_lock(&drvdata->spinlock);
+
+	/*
+	 * each byte[0..3] controls mask value applied to vmid
+	 * comparator[0..3]
+	 */
+	switch (drvdata->numvmidc) {
+	case 0x1:
+		/* COMP0, bits[7:0] */
+		config->vmid_mask0 = val1 & 0xFF;
+		break;
+	case 0x2:
+		/* COMP1, bits[15:8] */
+		config->vmid_mask0 = val1 & 0xFFFF;
+		break;
+	case 0x3:
+		/* COMP2, bits[23:16] */
+		config->vmid_mask0 = val1 & 0xFFFFFF;
+		break;
+	case 0x4:
+		/* COMP3, bits[31:24] */
+		config->vmid_mask0 = val1;
+		break;
+	case 0x5:
+		/* COMP4, bits[7:0] */
+		config->vmid_mask0 = val1;
+		config->vmid_mask1 = val2 & 0xFF;
+		break;
+	case 0x6:
+		/* COMP5, bits[15:8] */
+		config->vmid_mask0 = val1;
+		config->vmid_mask1 = val2 & 0xFFFF;
+		break;
+	case 0x7:
+		/* COMP6, bits[23:16] */
+		config->vmid_mask0 = val1;
+		config->vmid_mask1 = val2 & 0xFFFFFF;
+		break;
+	case 0x8:
+		/* COMP7, bits[31:24] */
+		config->vmid_mask0 = val1;
+		config->vmid_mask1 = val2;
+		break;
+	default:
+		break;
+	}
+
+	/*
+	 * If software sets a mask bit to 1, it must program relevant byte
+	 * of vmid comparator value 0x0, otherwise behavior is unpredictable.
+	 * For example, if bit[3] of vmid_mask0 is 1, we must clear bits[31:24]
+	 * of vmid comparator0 value (corresponding to byte 0) register.
+	 */
+	mask = config->vmid_mask0;
+	for (i = 0; i < drvdata->numvmidc; i++) {
+		/* mask value of corresponding vmid comparator */
+		maskbyte = mask & ETMv4_EVENT_MASK;
+		/*
+		 * each bit corresponds to a byte of respective vmid comparator
+		 * value register
+		 */
+		for (j = 0; j < 8; j++) {
+			if (maskbyte & 1)
+				config->vmid_val[i] &= ~(0xFF << (j * 8));
+			maskbyte >>= 1;
+		}
+		/* Select the next vmid comparator mask value */
+		if (i == 3)
+			/* vmid comparators[4-7] */
+			mask = config->vmid_mask1;
+		else
+			mask >>= 0x8;
+	}
+	spin_unlock(&drvdata->spinlock);
+	return size;
+}
+static DEVICE_ATTR_RW(vmid_masks);
+
+static ssize_t cpu_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	int val;
+	struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+	val = drvdata->cpu;
+	return scnprintf(buf, PAGE_SIZE, "%d\n", val);
+
+}
+static DEVICE_ATTR_RO(cpu);
+
+static struct attribute *coresight_etmv4_attrs[] = {
+	&dev_attr_nr_pe_cmp.attr,
+	&dev_attr_nr_addr_cmp.attr,
+	&dev_attr_nr_cntr.attr,
+	&dev_attr_nr_ext_inp.attr,
+	&dev_attr_numcidc.attr,
+	&dev_attr_numvmidc.attr,
+	&dev_attr_nrseqstate.attr,
+	&dev_attr_nr_resource.attr,
+	&dev_attr_nr_ss_cmp.attr,
+	&dev_attr_reset.attr,
+	&dev_attr_mode.attr,
+	&dev_attr_pe.attr,
+	&dev_attr_event.attr,
+	&dev_attr_event_instren.attr,
+	&dev_attr_event_ts.attr,
+	&dev_attr_syncfreq.attr,
+	&dev_attr_cyc_threshold.attr,
+	&dev_attr_bb_ctrl.attr,
+	&dev_attr_event_vinst.attr,
+	&dev_attr_s_exlevel_vinst.attr,
+	&dev_attr_ns_exlevel_vinst.attr,
+	&dev_attr_addr_idx.attr,
+	&dev_attr_addr_instdatatype.attr,
+	&dev_attr_addr_single.attr,
+	&dev_attr_addr_range.attr,
+	&dev_attr_addr_start.attr,
+	&dev_attr_addr_stop.attr,
+	&dev_attr_addr_ctxtype.attr,
+	&dev_attr_addr_context.attr,
+	&dev_attr_seq_idx.attr,
+	&dev_attr_seq_state.attr,
+	&dev_attr_seq_event.attr,
+	&dev_attr_seq_reset_event.attr,
+	&dev_attr_cntr_idx.attr,
+	&dev_attr_cntrldvr.attr,
+	&dev_attr_cntr_val.attr,
+	&dev_attr_cntr_ctrl.attr,
+	&dev_attr_res_idx.attr,
+	&dev_attr_res_ctrl.attr,
+	&dev_attr_ctxid_idx.attr,
+	&dev_attr_ctxid_pid.attr,
+	&dev_attr_ctxid_masks.attr,
+	&dev_attr_vmid_idx.attr,
+	&dev_attr_vmid_val.attr,
+	&dev_attr_vmid_masks.attr,
+	&dev_attr_cpu.attr,
+	NULL,
+};
+
+#define coresight_etm4x_simple_func(name, offset)			\
+	coresight_simple_func(struct etmv4_drvdata, name, offset)
+
+coresight_etm4x_simple_func(trcoslsr, TRCOSLSR);
+coresight_etm4x_simple_func(trcpdcr, TRCPDCR);
+coresight_etm4x_simple_func(trcpdsr, TRCPDSR);
+coresight_etm4x_simple_func(trclsr, TRCLSR);
+coresight_etm4x_simple_func(trcconfig, TRCCONFIGR);
+coresight_etm4x_simple_func(trctraceid, TRCTRACEIDR);
+coresight_etm4x_simple_func(trcauthstatus, TRCAUTHSTATUS);
+coresight_etm4x_simple_func(trcdevid, TRCDEVID);
+coresight_etm4x_simple_func(trcdevtype, TRCDEVTYPE);
+coresight_etm4x_simple_func(trcpidr0, TRCPIDR0);
+coresight_etm4x_simple_func(trcpidr1, TRCPIDR1);
+coresight_etm4x_simple_func(trcpidr2, TRCPIDR2);
+coresight_etm4x_simple_func(trcpidr3, TRCPIDR3);
+
+static struct attribute *coresight_etmv4_mgmt_attrs[] = {
+	&dev_attr_trcoslsr.attr,
+	&dev_attr_trcpdcr.attr,
+	&dev_attr_trcpdsr.attr,
+	&dev_attr_trclsr.attr,
+	&dev_attr_trcconfig.attr,
+	&dev_attr_trctraceid.attr,
+	&dev_attr_trcauthstatus.attr,
+	&dev_attr_trcdevid.attr,
+	&dev_attr_trcdevtype.attr,
+	&dev_attr_trcpidr0.attr,
+	&dev_attr_trcpidr1.attr,
+	&dev_attr_trcpidr2.attr,
+	&dev_attr_trcpidr3.attr,
+	NULL,
+};
+
+coresight_etm4x_simple_func(trcidr0, TRCIDR0);
+coresight_etm4x_simple_func(trcidr1, TRCIDR1);
+coresight_etm4x_simple_func(trcidr2, TRCIDR2);
+coresight_etm4x_simple_func(trcidr3, TRCIDR3);
+coresight_etm4x_simple_func(trcidr4, TRCIDR4);
+coresight_etm4x_simple_func(trcidr5, TRCIDR5);
+/* trcidr[6,7] are reserved */
+coresight_etm4x_simple_func(trcidr8, TRCIDR8);
+coresight_etm4x_simple_func(trcidr9, TRCIDR9);
+coresight_etm4x_simple_func(trcidr10, TRCIDR10);
+coresight_etm4x_simple_func(trcidr11, TRCIDR11);
+coresight_etm4x_simple_func(trcidr12, TRCIDR12);
+coresight_etm4x_simple_func(trcidr13, TRCIDR13);
+
+static struct attribute *coresight_etmv4_trcidr_attrs[] = {
+	&dev_attr_trcidr0.attr,
+	&dev_attr_trcidr1.attr,
+	&dev_attr_trcidr2.attr,
+	&dev_attr_trcidr3.attr,
+	&dev_attr_trcidr4.attr,
+	&dev_attr_trcidr5.attr,
+	/* trcidr[6,7] are reserved */
+	&dev_attr_trcidr8.attr,
+	&dev_attr_trcidr9.attr,
+	&dev_attr_trcidr10.attr,
+	&dev_attr_trcidr11.attr,
+	&dev_attr_trcidr12.attr,
+	&dev_attr_trcidr13.attr,
+	NULL,
+};
+
+static const struct attribute_group coresight_etmv4_group = {
+	.attrs = coresight_etmv4_attrs,
+};
+
+static const struct attribute_group coresight_etmv4_mgmt_group = {
+	.attrs = coresight_etmv4_mgmt_attrs,
+	.name = "mgmt",
+};
+
+static const struct attribute_group coresight_etmv4_trcidr_group = {
+	.attrs = coresight_etmv4_trcidr_attrs,
+	.name = "trcidr",
+};
+
+const struct attribute_group *coresight_etmv4_groups[] = {
+	&coresight_etmv4_group,
+	&coresight_etmv4_mgmt_group,
+	&coresight_etmv4_trcidr_group,
+	NULL,
+};
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwtracing/coresight/coresight-funnel.c linux-libre-4.7-gnu/drivers/hwtracing/coresight/coresight-funnel.c
--- linux-libre-4.6-gnu/drivers/hwtracing/coresight/coresight-funnel.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hwtracing/coresight/coresight-funnel.c	2016-07-24 15:23:50.000000000 -0400
@@ -221,7 +221,6 @@ static int funnel_probe(struct amba_devi
 	if (IS_ERR(drvdata->csdev))
 		return PTR_ERR(drvdata->csdev);
 
-	dev_info(dev, "FUNNEL initialized\n");
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwtracing/coresight/coresight-priv.h linux-libre-4.7-gnu/drivers/hwtracing/coresight/coresight-priv.h
--- linux-libre-4.6-gnu/drivers/hwtracing/coresight/coresight-priv.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hwtracing/coresight/coresight-priv.h	2016-07-24 15:23:50.000000000 -0400
@@ -37,12 +37,42 @@
 #define ETM_MODE_EXCL_KERN	BIT(30)
 #define ETM_MODE_EXCL_USER	BIT(31)
 
+#define coresight_simple_func(type, name, offset)			\
+static ssize_t name##_show(struct device *_dev,				\
+			   struct device_attribute *attr, char *buf)	\
+{									\
+	type *drvdata = dev_get_drvdata(_dev->parent);			\
+	return scnprintf(buf, PAGE_SIZE, "0x%x\n",			\
+			 readl_relaxed(drvdata->base + offset));	\
+}									\
+static DEVICE_ATTR_RO(name)
+
 enum cs_mode {
 	CS_MODE_DISABLED,
 	CS_MODE_SYSFS,
 	CS_MODE_PERF,
 };
 
+/**
+ * struct cs_buffer - keep track of a recording session' specifics
+ * @cur:	index of the current buffer
+ * @nr_pages:	max number of pages granted to us
+ * @offset:	offset within the current buffer
+ * @data_size:	how much we collected in this run
+ * @lost:	other than zero if we had a HW buffer wrap around
+ * @snapshot:	is this run in snapshot mode
+ * @data_pages:	a handle the ring buffer
+ */
+struct cs_buffers {
+	unsigned int		cur;
+	unsigned int		nr_pages;
+	unsigned long		offset;
+	local_t			data_size;
+	local_t			lost;
+	bool			snapshot;
+	void			**data_pages;
+};
+
 static inline void CS_LOCK(void __iomem *addr)
 {
 	do {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwtracing/coresight/coresight-replicator.c linux-libre-4.7-gnu/drivers/hwtracing/coresight/coresight-replicator.c
--- linux-libre-4.6-gnu/drivers/hwtracing/coresight/coresight-replicator.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hwtracing/coresight/coresight-replicator.c	2016-07-24 15:23:50.000000000 -0400
@@ -114,7 +114,6 @@ static int replicator_probe(struct platf
 
 	pm_runtime_put(&pdev->dev);
 
-	dev_info(dev, "REPLICATOR initialized\n");
 	return 0;
 
 out_disable_pm:
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwtracing/coresight/coresight-stm.c linux-libre-4.7-gnu/drivers/hwtracing/coresight/coresight-stm.c
--- linux-libre-4.6-gnu/drivers/hwtracing/coresight/coresight-stm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/hwtracing/coresight/coresight-stm.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,920 @@
+/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+ *
+ * Description: CoreSight System Trace Macrocell driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 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.
+ *
+ * Initial implementation by Pratik Patel
+ * (C) 2014-2015 Pratik Patel <pratikp@codeaurora.org>
+ *
+ * Serious refactoring, code cleanup and upgrading to the Coresight upstream
+ * framework by Mathieu Poirier
+ * (C) 2015-2016 Mathieu Poirier <mathieu.poirier@linaro.org>
+ *
+ * Guaranteed timing and support for various packet type coming from the
+ * generic STM API by Chunyan Zhang
+ * (C) 2015-2016 Chunyan Zhang <zhang.chunyan@linaro.org>
+ */
+#include <asm/local.h>
+#include <linux/amba/bus.h>
+#include <linux/bitmap.h>
+#include <linux/clk.h>
+#include <linux/coresight.h>
+#include <linux/coresight-stm.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/moduleparam.h>
+#include <linux/of_address.h>
+#include <linux/perf_event.h>
+#include <linux/pm_runtime.h>
+#include <linux/stm.h>
+
+#include "coresight-priv.h"
+
+#define STMDMASTARTR			0xc04
+#define STMDMASTOPR			0xc08
+#define STMDMASTATR			0xc0c
+#define STMDMACTLR			0xc10
+#define STMDMAIDR			0xcfc
+#define STMHEER				0xd00
+#define STMHETER			0xd20
+#define STMHEBSR			0xd60
+#define STMHEMCR			0xd64
+#define STMHEMASTR			0xdf4
+#define STMHEFEAT1R			0xdf8
+#define STMHEIDR			0xdfc
+#define STMSPER				0xe00
+#define STMSPTER			0xe20
+#define STMPRIVMASKR			0xe40
+#define STMSPSCR			0xe60
+#define STMSPMSCR			0xe64
+#define STMSPOVERRIDER			0xe68
+#define STMSPMOVERRIDER			0xe6c
+#define STMSPTRIGCSR			0xe70
+#define STMTCSR				0xe80
+#define STMTSSTIMR			0xe84
+#define STMTSFREQR			0xe8c
+#define STMSYNCR			0xe90
+#define STMAUXCR			0xe94
+#define STMSPFEAT1R			0xea0
+#define STMSPFEAT2R			0xea4
+#define STMSPFEAT3R			0xea8
+#define STMITTRIGGER			0xee8
+#define STMITATBDATA0			0xeec
+#define STMITATBCTR2			0xef0
+#define STMITATBID			0xef4
+#define STMITATBCTR0			0xef8
+
+#define STM_32_CHANNEL			32
+#define BYTES_PER_CHANNEL		256
+#define STM_TRACE_BUF_SIZE		4096
+#define STM_SW_MASTER_END		127
+
+/* Register bit definition */
+#define STMTCSR_BUSY_BIT		23
+/* Reserve the first 10 channels for kernel usage */
+#define STM_CHANNEL_OFFSET		0
+
+enum stm_pkt_type {
+	STM_PKT_TYPE_DATA	= 0x98,
+	STM_PKT_TYPE_FLAG	= 0xE8,
+	STM_PKT_TYPE_TRIG	= 0xF8,
+};
+
+#define stm_channel_addr(drvdata, ch)	(drvdata->chs.base +	\
+					(ch * BYTES_PER_CHANNEL))
+#define stm_channel_off(type, opts)	(type & ~opts)
+
+static int boot_nr_channel;
+
+/*
+ * Not really modular but using module_param is the easiest way to
+ * remain consistent with existing use cases for now.
+ */
+module_param_named(
+	boot_nr_channel, boot_nr_channel, int, S_IRUGO
+);
+
+/**
+ * struct channel_space - central management entity for extended ports
+ * @base:		memory mapped base address where channels start.
+ * @guaraneed:		is the channel delivery guaranteed.
+ */
+struct channel_space {
+	void __iomem		*base;
+	unsigned long		*guaranteed;
+};
+
+/**
+ * struct stm_drvdata - specifics associated to an STM component
+ * @base:		memory mapped base address for this component.
+ * @dev:		the device entity associated to this component.
+ * @atclk:		optional clock for the core parts of the STM.
+ * @csdev:		component vitals needed by the framework.
+ * @spinlock:		only one at a time pls.
+ * @chs:		the channels accociated to this STM.
+ * @stm:		structure associated to the generic STM interface.
+ * @mode:		this tracer's mode, i.e sysFS, or disabled.
+ * @traceid:		value of the current ID for this component.
+ * @write_bytes:	Maximus bytes this STM can write at a time.
+ * @stmsper:		settings for register STMSPER.
+ * @stmspscr:		settings for register STMSPSCR.
+ * @numsp:		the total number of stimulus port support by this STM.
+ * @stmheer:		settings for register STMHEER.
+ * @stmheter:		settings for register STMHETER.
+ * @stmhebsr:		settings for register STMHEBSR.
+ */
+struct stm_drvdata {
+	void __iomem		*base;
+	struct device		*dev;
+	struct clk		*atclk;
+	struct coresight_device	*csdev;
+	spinlock_t		spinlock;
+	struct channel_space	chs;
+	struct stm_data		stm;
+	local_t			mode;
+	u8			traceid;
+	u32			write_bytes;
+	u32			stmsper;
+	u32			stmspscr;
+	u32			numsp;
+	u32			stmheer;
+	u32			stmheter;
+	u32			stmhebsr;
+};
+
+static void stm_hwevent_enable_hw(struct stm_drvdata *drvdata)
+{
+	CS_UNLOCK(drvdata->base);
+
+	writel_relaxed(drvdata->stmhebsr, drvdata->base + STMHEBSR);
+	writel_relaxed(drvdata->stmheter, drvdata->base + STMHETER);
+	writel_relaxed(drvdata->stmheer, drvdata->base + STMHEER);
+	writel_relaxed(0x01 |	/* Enable HW event tracing */
+		       0x04,	/* Error detection on event tracing */
+		       drvdata->base + STMHEMCR);
+
+	CS_LOCK(drvdata->base);
+}
+
+static void stm_port_enable_hw(struct stm_drvdata *drvdata)
+{
+	CS_UNLOCK(drvdata->base);
+	/* ATB trigger enable on direct writes to TRIG locations */
+	writel_relaxed(0x10,
+		       drvdata->base + STMSPTRIGCSR);
+	writel_relaxed(drvdata->stmspscr, drvdata->base + STMSPSCR);
+	writel_relaxed(drvdata->stmsper, drvdata->base + STMSPER);
+
+	CS_LOCK(drvdata->base);
+}
+
+static void stm_enable_hw(struct stm_drvdata *drvdata)
+{
+	if (drvdata->stmheer)
+		stm_hwevent_enable_hw(drvdata);
+
+	stm_port_enable_hw(drvdata);
+
+	CS_UNLOCK(drvdata->base);
+
+	/* 4096 byte between synchronisation packets */
+	writel_relaxed(0xFFF, drvdata->base + STMSYNCR);
+	writel_relaxed((drvdata->traceid << 16 | /* trace id */
+			0x02 |			 /* timestamp enable */
+			0x01),			 /* global STM enable */
+			drvdata->base + STMTCSR);
+
+	CS_LOCK(drvdata->base);
+}
+
+static int stm_enable(struct coresight_device *csdev,
+		      struct perf_event_attr *attr, u32 mode)
+{
+	u32 val;
+	struct stm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+	if (mode != CS_MODE_SYSFS)
+		return -EINVAL;
+
+	val = local_cmpxchg(&drvdata->mode, CS_MODE_DISABLED, mode);
+
+	/* Someone is already using the tracer */
+	if (val)
+		return -EBUSY;
+
+	pm_runtime_get_sync(drvdata->dev);
+
+	spin_lock(&drvdata->spinlock);
+	stm_enable_hw(drvdata);
+	spin_unlock(&drvdata->spinlock);
+
+	dev_info(drvdata->dev, "STM tracing enabled\n");
+	return 0;
+}
+
+static void stm_hwevent_disable_hw(struct stm_drvdata *drvdata)
+{
+	CS_UNLOCK(drvdata->base);
+
+	writel_relaxed(0x0, drvdata->base + STMHEMCR);
+	writel_relaxed(0x0, drvdata->base + STMHEER);
+	writel_relaxed(0x0, drvdata->base + STMHETER);
+
+	CS_LOCK(drvdata->base);
+}
+
+static void stm_port_disable_hw(struct stm_drvdata *drvdata)
+{
+	CS_UNLOCK(drvdata->base);
+
+	writel_relaxed(0x0, drvdata->base + STMSPER);
+	writel_relaxed(0x0, drvdata->base + STMSPTRIGCSR);
+
+	CS_LOCK(drvdata->base);
+}
+
+static void stm_disable_hw(struct stm_drvdata *drvdata)
+{
+	u32 val;
+
+	CS_UNLOCK(drvdata->base);
+
+	val = readl_relaxed(drvdata->base + STMTCSR);
+	val &= ~0x1; /* clear global STM enable [0] */
+	writel_relaxed(val, drvdata->base + STMTCSR);
+
+	CS_LOCK(drvdata->base);
+
+	stm_port_disable_hw(drvdata);
+	if (drvdata->stmheer)
+		stm_hwevent_disable_hw(drvdata);
+}
+
+static void stm_disable(struct coresight_device *csdev)
+{
+	struct stm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+	/*
+	 * For as long as the tracer isn't disabled another entity can't
+	 * change its status.  As such we can read the status here without
+	 * fearing it will change under us.
+	 */
+	if (local_read(&drvdata->mode) == CS_MODE_SYSFS) {
+		spin_lock(&drvdata->spinlock);
+		stm_disable_hw(drvdata);
+		spin_unlock(&drvdata->spinlock);
+
+		/* Wait until the engine has completely stopped */
+		coresight_timeout(drvdata, STMTCSR, STMTCSR_BUSY_BIT, 0);
+
+		pm_runtime_put(drvdata->dev);
+
+		local_set(&drvdata->mode, CS_MODE_DISABLED);
+		dev_info(drvdata->dev, "STM tracing disabled\n");
+	}
+}
+
+static int stm_trace_id(struct coresight_device *csdev)
+{
+	struct stm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+	return drvdata->traceid;
+}
+
+static const struct coresight_ops_source stm_source_ops = {
+	.trace_id	= stm_trace_id,
+	.enable		= stm_enable,
+	.disable	= stm_disable,
+};
+
+static const struct coresight_ops stm_cs_ops = {
+	.source_ops	= &stm_source_ops,
+};
+
+static inline bool stm_addr_unaligned(const void *addr, u8 write_bytes)
+{
+	return ((unsigned long)addr & (write_bytes - 1));
+}
+
+static void stm_send(void *addr, const void *data, u32 size, u8 write_bytes)
+{
+	u8 paload[8];
+
+	if (stm_addr_unaligned(data, write_bytes)) {
+		memcpy(paload, data, size);
+		data = paload;
+	}
+
+	/* now we are 64bit/32bit aligned */
+	switch (size) {
+#ifdef CONFIG_64BIT
+	case 8:
+		writeq_relaxed(*(u64 *)data, addr);
+		break;
+#endif
+	case 4:
+		writel_relaxed(*(u32 *)data, addr);
+		break;
+	case 2:
+		writew_relaxed(*(u16 *)data, addr);
+		break;
+	case 1:
+		writeb_relaxed(*(u8 *)data, addr);
+		break;
+	default:
+		break;
+	}
+}
+
+static int stm_generic_link(struct stm_data *stm_data,
+			    unsigned int master,  unsigned int channel)
+{
+	struct stm_drvdata *drvdata = container_of(stm_data,
+						   struct stm_drvdata, stm);
+	if (!drvdata || !drvdata->csdev)
+		return -EINVAL;
+
+	return coresight_enable(drvdata->csdev);
+}
+
+static void stm_generic_unlink(struct stm_data *stm_data,
+			       unsigned int master,  unsigned int channel)
+{
+	struct stm_drvdata *drvdata = container_of(stm_data,
+						   struct stm_drvdata, stm);
+	if (!drvdata || !drvdata->csdev)
+		return;
+
+	stm_disable(drvdata->csdev);
+}
+
+static long stm_generic_set_options(struct stm_data *stm_data,
+				    unsigned int master,
+				    unsigned int channel,
+				    unsigned int nr_chans,
+				    unsigned long options)
+{
+	struct stm_drvdata *drvdata = container_of(stm_data,
+						   struct stm_drvdata, stm);
+	if (!(drvdata && local_read(&drvdata->mode)))
+		return -EINVAL;
+
+	if (channel >= drvdata->numsp)
+		return -EINVAL;
+
+	switch (options) {
+	case STM_OPTION_GUARANTEED:
+		set_bit(channel, drvdata->chs.guaranteed);
+		break;
+
+	case STM_OPTION_INVARIANT:
+		clear_bit(channel, drvdata->chs.guaranteed);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static ssize_t stm_generic_packet(struct stm_data *stm_data,
+				  unsigned int master,
+				  unsigned int channel,
+				  unsigned int packet,
+				  unsigned int flags,
+				  unsigned int size,
+				  const unsigned char *payload)
+{
+	unsigned long ch_addr;
+	struct stm_drvdata *drvdata = container_of(stm_data,
+						   struct stm_drvdata, stm);
+
+	if (!(drvdata && local_read(&drvdata->mode)))
+		return 0;
+
+	if (channel >= drvdata->numsp)
+		return 0;
+
+	ch_addr = (unsigned long)stm_channel_addr(drvdata, channel);
+
+	flags = (flags == STP_PACKET_TIMESTAMPED) ? STM_FLAG_TIMESTAMPED : 0;
+	flags |= test_bit(channel, drvdata->chs.guaranteed) ?
+			   STM_FLAG_GUARANTEED : 0;
+
+	if (size > drvdata->write_bytes)
+		size = drvdata->write_bytes;
+	else
+		size = rounddown_pow_of_two(size);
+
+	switch (packet) {
+	case STP_PACKET_FLAG:
+		ch_addr |= stm_channel_off(STM_PKT_TYPE_FLAG, flags);
+
+		/*
+		 * The generic STM core sets a size of '0' on flag packets.
+		 * As such send a flag packet of size '1' and tell the
+		 * core we did so.
+		 */
+		stm_send((void *)ch_addr, payload, 1, drvdata->write_bytes);
+		size = 1;
+		break;
+
+	case STP_PACKET_DATA:
+		ch_addr |= stm_channel_off(STM_PKT_TYPE_DATA, flags);
+		stm_send((void *)ch_addr, payload, size,
+				drvdata->write_bytes);
+		break;
+
+	default:
+		return -ENOTSUPP;
+	}
+
+	return size;
+}
+
+static ssize_t hwevent_enable_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	unsigned long val = drvdata->stmheer;
+
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t hwevent_enable_store(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t size)
+{
+	struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	unsigned long val;
+	int ret = 0;
+
+	ret = kstrtoul(buf, 16, &val);
+	if (ret)
+		return -EINVAL;
+
+	drvdata->stmheer = val;
+	/* HW event enable and trigger go hand in hand */
+	drvdata->stmheter = val;
+
+	return size;
+}
+static DEVICE_ATTR_RW(hwevent_enable);
+
+static ssize_t hwevent_select_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	unsigned long val = drvdata->stmhebsr;
+
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t hwevent_select_store(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t size)
+{
+	struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	unsigned long val;
+	int ret = 0;
+
+	ret = kstrtoul(buf, 16, &val);
+	if (ret)
+		return -EINVAL;
+
+	drvdata->stmhebsr = val;
+
+	return size;
+}
+static DEVICE_ATTR_RW(hwevent_select);
+
+static ssize_t port_select_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	unsigned long val;
+
+	if (!local_read(&drvdata->mode)) {
+		val = drvdata->stmspscr;
+	} else {
+		spin_lock(&drvdata->spinlock);
+		val = readl_relaxed(drvdata->base + STMSPSCR);
+		spin_unlock(&drvdata->spinlock);
+	}
+
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t port_select_store(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t size)
+{
+	struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	unsigned long val, stmsper;
+	int ret = 0;
+
+	ret = kstrtoul(buf, 16, &val);
+	if (ret)
+		return ret;
+
+	spin_lock(&drvdata->spinlock);
+	drvdata->stmspscr = val;
+
+	if (local_read(&drvdata->mode)) {
+		CS_UNLOCK(drvdata->base);
+		/* Process as per ARM's TRM recommendation */
+		stmsper = readl_relaxed(drvdata->base + STMSPER);
+		writel_relaxed(0x0, drvdata->base + STMSPER);
+		writel_relaxed(drvdata->stmspscr, drvdata->base + STMSPSCR);
+		writel_relaxed(stmsper, drvdata->base + STMSPER);
+		CS_LOCK(drvdata->base);
+	}
+	spin_unlock(&drvdata->spinlock);
+
+	return size;
+}
+static DEVICE_ATTR_RW(port_select);
+
+static ssize_t port_enable_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	unsigned long val;
+
+	if (!local_read(&drvdata->mode)) {
+		val = drvdata->stmsper;
+	} else {
+		spin_lock(&drvdata->spinlock);
+		val = readl_relaxed(drvdata->base + STMSPER);
+		spin_unlock(&drvdata->spinlock);
+	}
+
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t port_enable_store(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t size)
+{
+	struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	unsigned long val;
+	int ret = 0;
+
+	ret = kstrtoul(buf, 16, &val);
+	if (ret)
+		return ret;
+
+	spin_lock(&drvdata->spinlock);
+	drvdata->stmsper = val;
+
+	if (local_read(&drvdata->mode)) {
+		CS_UNLOCK(drvdata->base);
+		writel_relaxed(drvdata->stmsper, drvdata->base + STMSPER);
+		CS_LOCK(drvdata->base);
+	}
+	spin_unlock(&drvdata->spinlock);
+
+	return size;
+}
+static DEVICE_ATTR_RW(port_enable);
+
+static ssize_t traceid_show(struct device *dev,
+			    struct device_attribute *attr, char *buf)
+{
+	unsigned long val;
+	struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+	val = drvdata->traceid;
+	return sprintf(buf, "%#lx\n", val);
+}
+
+static ssize_t traceid_store(struct device *dev,
+			     struct device_attribute *attr,
+			     const char *buf, size_t size)
+{
+	int ret;
+	unsigned long val;
+	struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+	ret = kstrtoul(buf, 16, &val);
+	if (ret)
+		return ret;
+
+	/* traceid field is 7bit wide on STM32 */
+	drvdata->traceid = val & 0x7f;
+	return size;
+}
+static DEVICE_ATTR_RW(traceid);
+
+#define coresight_stm_simple_func(name, offset)	\
+	coresight_simple_func(struct stm_drvdata, name, offset)
+
+coresight_stm_simple_func(tcsr, STMTCSR);
+coresight_stm_simple_func(tsfreqr, STMTSFREQR);
+coresight_stm_simple_func(syncr, STMSYNCR);
+coresight_stm_simple_func(sper, STMSPER);
+coresight_stm_simple_func(spter, STMSPTER);
+coresight_stm_simple_func(privmaskr, STMPRIVMASKR);
+coresight_stm_simple_func(spscr, STMSPSCR);
+coresight_stm_simple_func(spmscr, STMSPMSCR);
+coresight_stm_simple_func(spfeat1r, STMSPFEAT1R);
+coresight_stm_simple_func(spfeat2r, STMSPFEAT2R);
+coresight_stm_simple_func(spfeat3r, STMSPFEAT3R);
+coresight_stm_simple_func(devid, CORESIGHT_DEVID);
+
+static struct attribute *coresight_stm_attrs[] = {
+	&dev_attr_hwevent_enable.attr,
+	&dev_attr_hwevent_select.attr,
+	&dev_attr_port_enable.attr,
+	&dev_attr_port_select.attr,
+	&dev_attr_traceid.attr,
+	NULL,
+};
+
+static struct attribute *coresight_stm_mgmt_attrs[] = {
+	&dev_attr_tcsr.attr,
+	&dev_attr_tsfreqr.attr,
+	&dev_attr_syncr.attr,
+	&dev_attr_sper.attr,
+	&dev_attr_spter.attr,
+	&dev_attr_privmaskr.attr,
+	&dev_attr_spscr.attr,
+	&dev_attr_spmscr.attr,
+	&dev_attr_spfeat1r.attr,
+	&dev_attr_spfeat2r.attr,
+	&dev_attr_spfeat3r.attr,
+	&dev_attr_devid.attr,
+	NULL,
+};
+
+static const struct attribute_group coresight_stm_group = {
+	.attrs = coresight_stm_attrs,
+};
+
+static const struct attribute_group coresight_stm_mgmt_group = {
+	.attrs = coresight_stm_mgmt_attrs,
+	.name = "mgmt",
+};
+
+static const struct attribute_group *coresight_stm_groups[] = {
+	&coresight_stm_group,
+	&coresight_stm_mgmt_group,
+	NULL,
+};
+
+static int stm_get_resource_byname(struct device_node *np,
+				   char *ch_base, struct resource *res)
+{
+	const char *name = NULL;
+	int index = 0, found = 0;
+
+	while (!of_property_read_string_index(np, "reg-names", index, &name)) {
+		if (strcmp(ch_base, name)) {
+			index++;
+			continue;
+		}
+
+		/* We have a match and @index is where it's at */
+		found = 1;
+		break;
+	}
+
+	if (!found)
+		return -EINVAL;
+
+	return of_address_to_resource(np, index, res);
+}
+
+static u32 stm_fundamental_data_size(struct stm_drvdata *drvdata)
+{
+	u32 stmspfeat2r;
+
+	if (!IS_ENABLED(CONFIG_64BIT))
+		return 4;
+
+	stmspfeat2r = readl_relaxed(drvdata->base + STMSPFEAT2R);
+
+	/*
+	 * bit[15:12] represents the fundamental data size
+	 * 0 - 32-bit data
+	 * 1 - 64-bit data
+	 */
+	return BMVAL(stmspfeat2r, 12, 15) ? 8 : 4;
+}
+
+static u32 stm_num_stimulus_port(struct stm_drvdata *drvdata)
+{
+	u32 numsp;
+
+	numsp = readl_relaxed(drvdata->base + CORESIGHT_DEVID);
+	/*
+	 * NUMPS in STMDEVID is 17 bit long and if equal to 0x0,
+	 * 32 stimulus ports are supported.
+	 */
+	numsp &= 0x1ffff;
+	if (!numsp)
+		numsp = STM_32_CHANNEL;
+	return numsp;
+}
+
+static void stm_init_default_data(struct stm_drvdata *drvdata)
+{
+	/* Don't use port selection */
+	drvdata->stmspscr = 0x0;
+	/*
+	 * Enable all channel regardless of their number.  When port
+	 * selection isn't used (see above) STMSPER applies to all
+	 * 32 channel group available, hence setting all 32 bits to 1
+	 */
+	drvdata->stmsper = ~0x0;
+
+	/*
+	 * The trace ID value for *ETM* tracers start at CPU_ID * 2 + 0x10 and
+	 * anything equal to or higher than 0x70 is reserved.  Since 0x00 is
+	 * also reserved the STM trace ID needs to be higher than 0x00 and
+	 * lowner than 0x10.
+	 */
+	drvdata->traceid = 0x1;
+
+	/* Set invariant transaction timing on all channels */
+	bitmap_clear(drvdata->chs.guaranteed, 0, drvdata->numsp);
+}
+
+static void stm_init_generic_data(struct stm_drvdata *drvdata)
+{
+	drvdata->stm.name = dev_name(drvdata->dev);
+
+	/*
+	 * MasterIDs are assigned at HW design phase. As such the core is
+	 * using a single master for interaction with this device.
+	 */
+	drvdata->stm.sw_start = 1;
+	drvdata->stm.sw_end = 1;
+	drvdata->stm.hw_override = true;
+	drvdata->stm.sw_nchannels = drvdata->numsp;
+	drvdata->stm.packet = stm_generic_packet;
+	drvdata->stm.link = stm_generic_link;
+	drvdata->stm.unlink = stm_generic_unlink;
+	drvdata->stm.set_options = stm_generic_set_options;
+}
+
+static int stm_probe(struct amba_device *adev, const struct amba_id *id)
+{
+	int ret;
+	void __iomem *base;
+	unsigned long *guaranteed;
+	struct device *dev = &adev->dev;
+	struct coresight_platform_data *pdata = NULL;
+	struct stm_drvdata *drvdata;
+	struct resource *res = &adev->res;
+	struct resource ch_res;
+	size_t res_size, bitmap_size;
+	struct coresight_desc *desc;
+	struct device_node *np = adev->dev.of_node;
+
+	if (np) {
+		pdata = of_get_coresight_platform_data(dev, np);
+		if (IS_ERR(pdata))
+			return PTR_ERR(pdata);
+		adev->dev.platform_data = pdata;
+	}
+	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+	if (!drvdata)
+		return -ENOMEM;
+
+	drvdata->dev = &adev->dev;
+	drvdata->atclk = devm_clk_get(&adev->dev, "atclk"); /* optional */
+	if (!IS_ERR(drvdata->atclk)) {
+		ret = clk_prepare_enable(drvdata->atclk);
+		if (ret)
+			return ret;
+	}
+	dev_set_drvdata(dev, drvdata);
+
+	base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+	drvdata->base = base;
+
+	ret = stm_get_resource_byname(np, "stm-stimulus-base", &ch_res);
+	if (ret)
+		return ret;
+
+	base = devm_ioremap_resource(dev, &ch_res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+	drvdata->chs.base = base;
+
+	drvdata->write_bytes = stm_fundamental_data_size(drvdata);
+
+	if (boot_nr_channel) {
+		drvdata->numsp = boot_nr_channel;
+		res_size = min((resource_size_t)(boot_nr_channel *
+				  BYTES_PER_CHANNEL), resource_size(res));
+	} else {
+		drvdata->numsp = stm_num_stimulus_port(drvdata);
+		res_size = min((resource_size_t)(drvdata->numsp *
+				 BYTES_PER_CHANNEL), resource_size(res));
+	}
+	bitmap_size = BITS_TO_LONGS(drvdata->numsp) * sizeof(long);
+
+	guaranteed = devm_kzalloc(dev, bitmap_size, GFP_KERNEL);
+	if (!guaranteed)
+		return -ENOMEM;
+	drvdata->chs.guaranteed = guaranteed;
+
+	spin_lock_init(&drvdata->spinlock);
+
+	stm_init_default_data(drvdata);
+	stm_init_generic_data(drvdata);
+
+	if (stm_register_device(dev, &drvdata->stm, THIS_MODULE)) {
+		dev_info(dev,
+			 "stm_register_device failed, probing deffered\n");
+		return -EPROBE_DEFER;
+	}
+
+	desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+	if (!desc) {
+		ret = -ENOMEM;
+		goto stm_unregister;
+	}
+
+	desc->type = CORESIGHT_DEV_TYPE_SOURCE;
+	desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE;
+	desc->ops = &stm_cs_ops;
+	desc->pdata = pdata;
+	desc->dev = dev;
+	desc->groups = coresight_stm_groups;
+	drvdata->csdev = coresight_register(desc);
+	if (IS_ERR(drvdata->csdev)) {
+		ret = PTR_ERR(drvdata->csdev);
+		goto stm_unregister;
+	}
+
+	pm_runtime_put(&adev->dev);
+
+	dev_info(dev, "%s initialized\n", (char *)id->data);
+	return 0;
+
+stm_unregister:
+	stm_unregister_device(&drvdata->stm);
+	return ret;
+}
+
+#ifdef CONFIG_PM
+static int stm_runtime_suspend(struct device *dev)
+{
+	struct stm_drvdata *drvdata = dev_get_drvdata(dev);
+
+	if (drvdata && !IS_ERR(drvdata->atclk))
+		clk_disable_unprepare(drvdata->atclk);
+
+	return 0;
+}
+
+static int stm_runtime_resume(struct device *dev)
+{
+	struct stm_drvdata *drvdata = dev_get_drvdata(dev);
+
+	if (drvdata && !IS_ERR(drvdata->atclk))
+		clk_prepare_enable(drvdata->atclk);
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops stm_dev_pm_ops = {
+	SET_RUNTIME_PM_OPS(stm_runtime_suspend, stm_runtime_resume, NULL)
+};
+
+static struct amba_id stm_ids[] = {
+	{
+		.id     = 0x0003b962,
+		.mask   = 0x0003ffff,
+		.data	= "STM32",
+	},
+	{ 0, 0},
+};
+
+static struct amba_driver stm_driver = {
+	.drv = {
+		.name   = "coresight-stm",
+		.owner	= THIS_MODULE,
+		.pm	= &stm_dev_pm_ops,
+		.suppress_bind_attrs = true,
+	},
+	.probe          = stm_probe,
+	.id_table	= stm_ids,
+};
+
+builtin_amba_driver(stm_driver);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwtracing/coresight/coresight-tmc.c linux-libre-4.7-gnu/drivers/hwtracing/coresight/coresight-tmc.c
--- linux-libre-4.6-gnu/drivers/hwtracing/coresight/coresight-tmc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hwtracing/coresight/coresight-tmc.c	2016-07-24 15:23:50.000000000 -0400
@@ -30,127 +30,27 @@
 #include <linux/amba/bus.h>
 
 #include "coresight-priv.h"
+#include "coresight-tmc.h"
 
-#define TMC_RSZ			0x004
-#define TMC_STS			0x00c
-#define TMC_RRD			0x010
-#define TMC_RRP			0x014
-#define TMC_RWP			0x018
-#define TMC_TRG			0x01c
-#define TMC_CTL			0x020
-#define TMC_RWD			0x024
-#define TMC_MODE		0x028
-#define TMC_LBUFLEVEL		0x02c
-#define TMC_CBUFLEVEL		0x030
-#define TMC_BUFWM		0x034
-#define TMC_RRPHI		0x038
-#define TMC_RWPHI		0x03c
-#define TMC_AXICTL		0x110
-#define TMC_DBALO		0x118
-#define TMC_DBAHI		0x11c
-#define TMC_FFSR		0x300
-#define TMC_FFCR		0x304
-#define TMC_PSCR		0x308
-#define TMC_ITMISCOP0		0xee0
-#define TMC_ITTRFLIN		0xee8
-#define TMC_ITATBDATA0		0xeec
-#define TMC_ITATBCTR2		0xef0
-#define TMC_ITATBCTR1		0xef4
-#define TMC_ITATBCTR0		0xef8
-
-/* register description */
-/* TMC_CTL - 0x020 */
-#define TMC_CTL_CAPT_EN		BIT(0)
-/* TMC_STS - 0x00C */
-#define TMC_STS_TRIGGERED	BIT(1)
-/* TMC_AXICTL - 0x110 */
-#define TMC_AXICTL_PROT_CTL_B0	BIT(0)
-#define TMC_AXICTL_PROT_CTL_B1	BIT(1)
-#define TMC_AXICTL_SCT_GAT_MODE	BIT(7)
-#define TMC_AXICTL_WR_BURST_LEN 0xF00
-/* TMC_FFCR - 0x304 */
-#define TMC_FFCR_EN_FMT		BIT(0)
-#define TMC_FFCR_EN_TI		BIT(1)
-#define TMC_FFCR_FON_FLIN	BIT(4)
-#define TMC_FFCR_FON_TRIG_EVT	BIT(5)
-#define TMC_FFCR_FLUSHMAN	BIT(6)
-#define TMC_FFCR_TRIGON_TRIGIN	BIT(8)
-#define TMC_FFCR_STOP_ON_FLUSH	BIT(12)
-
-#define TMC_STS_TRIGGERED_BIT	2
-#define TMC_FFCR_FLUSHMAN_BIT	6
-
-enum tmc_config_type {
-	TMC_CONFIG_TYPE_ETB,
-	TMC_CONFIG_TYPE_ETR,
-	TMC_CONFIG_TYPE_ETF,
-};
-
-enum tmc_mode {
-	TMC_MODE_CIRCULAR_BUFFER,
-	TMC_MODE_SOFTWARE_FIFO,
-	TMC_MODE_HARDWARE_FIFO,
-};
-
-enum tmc_mem_intf_width {
-	TMC_MEM_INTF_WIDTH_32BITS	= 0x2,
-	TMC_MEM_INTF_WIDTH_64BITS	= 0x3,
-	TMC_MEM_INTF_WIDTH_128BITS	= 0x4,
-	TMC_MEM_INTF_WIDTH_256BITS	= 0x5,
-};
-
-/**
- * struct tmc_drvdata - specifics associated to an TMC component
- * @base:	memory mapped base address for this component.
- * @dev:	the device entity associated to this component.
- * @csdev:	component vitals needed by the framework.
- * @miscdev:	specifics to handle "/dev/xyz.tmc" entry.
- * @spinlock:	only one at a time pls.
- * @read_count:	manages preparation of buffer for reading.
- * @buf:	area of memory where trace data get sent.
- * @paddr:	DMA start location in RAM.
- * @vaddr:	virtual representation of @paddr.
- * @size:	@buf size.
- * @enable:	this TMC is being used.
- * @config_type: TMC variant, must be of type @tmc_config_type.
- * @trigger_cntr: amount of words to store after a trigger.
- */
-struct tmc_drvdata {
-	void __iomem		*base;
-	struct device		*dev;
-	struct coresight_device	*csdev;
-	struct miscdevice	miscdev;
-	spinlock_t		spinlock;
-	int			read_count;
-	bool			reading;
-	char			*buf;
-	dma_addr_t		paddr;
-	void			*vaddr;
-	u32			size;
-	bool			enable;
-	enum tmc_config_type	config_type;
-	u32			trigger_cntr;
-};
-
-static void tmc_wait_for_ready(struct tmc_drvdata *drvdata)
+void tmc_wait_for_tmcready(struct tmc_drvdata *drvdata)
 {
 	/* Ensure formatter, unformatter and hardware fifo are empty */
 	if (coresight_timeout(drvdata->base,
-			      TMC_STS, TMC_STS_TRIGGERED_BIT, 1)) {
+			      TMC_STS, TMC_STS_TMCREADY_BIT, 1)) {
 		dev_err(drvdata->dev,
 			"timeout observed when probing at offset %#x\n",
 			TMC_STS);
 	}
 }
 
-static void tmc_flush_and_stop(struct tmc_drvdata *drvdata)
+void tmc_flush_and_stop(struct tmc_drvdata *drvdata)
 {
 	u32 ffcr;
 
 	ffcr = readl_relaxed(drvdata->base + TMC_FFCR);
 	ffcr |= TMC_FFCR_STOP_ON_FLUSH;
 	writel_relaxed(ffcr, drvdata->base + TMC_FFCR);
-	ffcr |= TMC_FFCR_FLUSHMAN;
+	ffcr |= BIT(TMC_FFCR_FLUSHMAN_BIT);
 	writel_relaxed(ffcr, drvdata->base + TMC_FFCR);
 	/* Ensure flush completes */
 	if (coresight_timeout(drvdata->base,
@@ -160,338 +60,73 @@ static void tmc_flush_and_stop(struct tm
 			TMC_FFCR);
 	}
 
-	tmc_wait_for_ready(drvdata);
+	tmc_wait_for_tmcready(drvdata);
 }
 
-static void tmc_enable_hw(struct tmc_drvdata *drvdata)
+void tmc_enable_hw(struct tmc_drvdata *drvdata)
 {
 	writel_relaxed(TMC_CTL_CAPT_EN, drvdata->base + TMC_CTL);
 }
 
-static void tmc_disable_hw(struct tmc_drvdata *drvdata)
+void tmc_disable_hw(struct tmc_drvdata *drvdata)
 {
 	writel_relaxed(0x0, drvdata->base + TMC_CTL);
 }
 
-static void tmc_etb_enable_hw(struct tmc_drvdata *drvdata)
-{
-	/* Zero out the memory to help with debug */
-	memset(drvdata->buf, 0, drvdata->size);
-
-	CS_UNLOCK(drvdata->base);
-
-	writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE);
-	writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI |
-		       TMC_FFCR_FON_FLIN | TMC_FFCR_FON_TRIG_EVT |
-		       TMC_FFCR_TRIGON_TRIGIN,
-		       drvdata->base + TMC_FFCR);
-
-	writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG);
-	tmc_enable_hw(drvdata);
-
-	CS_LOCK(drvdata->base);
-}
-
-static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
-{
-	u32 axictl;
-
-	/* Zero out the memory to help with debug */
-	memset(drvdata->vaddr, 0, drvdata->size);
-
-	CS_UNLOCK(drvdata->base);
-
-	writel_relaxed(drvdata->size / 4, drvdata->base + TMC_RSZ);
-	writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE);
-
-	axictl = readl_relaxed(drvdata->base + TMC_AXICTL);
-	axictl |= TMC_AXICTL_WR_BURST_LEN;
-	writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
-	axictl &= ~TMC_AXICTL_SCT_GAT_MODE;
-	writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
-	axictl = (axictl &
-		  ~(TMC_AXICTL_PROT_CTL_B0 | TMC_AXICTL_PROT_CTL_B1)) |
-		  TMC_AXICTL_PROT_CTL_B1;
-	writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
-
-	writel_relaxed(drvdata->paddr, drvdata->base + TMC_DBALO);
-	writel_relaxed(0x0, drvdata->base + TMC_DBAHI);
-	writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI |
-		       TMC_FFCR_FON_FLIN | TMC_FFCR_FON_TRIG_EVT |
-		       TMC_FFCR_TRIGON_TRIGIN,
-		       drvdata->base + TMC_FFCR);
-	writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG);
-	tmc_enable_hw(drvdata);
-
-	CS_LOCK(drvdata->base);
-}
-
-static void tmc_etf_enable_hw(struct tmc_drvdata *drvdata)
-{
-	CS_UNLOCK(drvdata->base);
-
-	writel_relaxed(TMC_MODE_HARDWARE_FIFO, drvdata->base + TMC_MODE);
-	writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI,
-		       drvdata->base + TMC_FFCR);
-	writel_relaxed(0x0, drvdata->base + TMC_BUFWM);
-	tmc_enable_hw(drvdata);
-
-	CS_LOCK(drvdata->base);
-}
-
-static int tmc_enable(struct tmc_drvdata *drvdata, enum tmc_mode mode)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&drvdata->spinlock, flags);
-	if (drvdata->reading) {
-		spin_unlock_irqrestore(&drvdata->spinlock, flags);
-		return -EBUSY;
-	}
-
-	if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
-		tmc_etb_enable_hw(drvdata);
-	} else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
-		tmc_etr_enable_hw(drvdata);
-	} else {
-		if (mode == TMC_MODE_CIRCULAR_BUFFER)
-			tmc_etb_enable_hw(drvdata);
-		else
-			tmc_etf_enable_hw(drvdata);
-	}
-	drvdata->enable = true;
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
-
-	dev_info(drvdata->dev, "TMC enabled\n");
-	return 0;
-}
-
-static int tmc_enable_sink(struct coresight_device *csdev, u32 mode)
-{
-	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-
-	return tmc_enable(drvdata, TMC_MODE_CIRCULAR_BUFFER);
-}
-
-static int tmc_enable_link(struct coresight_device *csdev, int inport,
-			   int outport)
-{
-	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-
-	return tmc_enable(drvdata, TMC_MODE_HARDWARE_FIFO);
-}
-
-static void tmc_etb_dump_hw(struct tmc_drvdata *drvdata)
+static int tmc_read_prepare(struct tmc_drvdata *drvdata)
 {
-	enum tmc_mem_intf_width memwidth;
-	u8 memwords;
-	char *bufp;
-	u32 read_data;
-	int i;
-
-	memwidth = BMVAL(readl_relaxed(drvdata->base + CORESIGHT_DEVID), 8, 10);
-	if (memwidth == TMC_MEM_INTF_WIDTH_32BITS)
-		memwords = 1;
-	else if (memwidth == TMC_MEM_INTF_WIDTH_64BITS)
-		memwords = 2;
-	else if (memwidth == TMC_MEM_INTF_WIDTH_128BITS)
-		memwords = 4;
-	else
-		memwords = 8;
+	int ret = 0;
 
-	bufp = drvdata->buf;
-	while (1) {
-		for (i = 0; i < memwords; i++) {
-			read_data = readl_relaxed(drvdata->base + TMC_RRD);
-			if (read_data == 0xFFFFFFFF)
-				return;
-			memcpy(bufp, &read_data, 4);
-			bufp += 4;
-		}
+	switch (drvdata->config_type) {
+	case TMC_CONFIG_TYPE_ETB:
+	case TMC_CONFIG_TYPE_ETF:
+		ret = tmc_read_prepare_etb(drvdata);
+		break;
+	case TMC_CONFIG_TYPE_ETR:
+		ret = tmc_read_prepare_etr(drvdata);
+		break;
+	default:
+		ret = -EINVAL;
 	}
-}
-
-static void tmc_etb_disable_hw(struct tmc_drvdata *drvdata)
-{
-	CS_UNLOCK(drvdata->base);
-
-	tmc_flush_and_stop(drvdata);
-	tmc_etb_dump_hw(drvdata);
-	tmc_disable_hw(drvdata);
-
-	CS_LOCK(drvdata->base);
-}
-
-static void tmc_etr_dump_hw(struct tmc_drvdata *drvdata)
-{
-	u32 rwp, val;
-
-	rwp = readl_relaxed(drvdata->base + TMC_RWP);
-	val = readl_relaxed(drvdata->base + TMC_STS);
-
-	/* How much memory do we still have */
-	if (val & BIT(0))
-		drvdata->buf = drvdata->vaddr + rwp - drvdata->paddr;
-	else
-		drvdata->buf = drvdata->vaddr;
-}
-
-static void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
-{
-	CS_UNLOCK(drvdata->base);
-
-	tmc_flush_and_stop(drvdata);
-	tmc_etr_dump_hw(drvdata);
-	tmc_disable_hw(drvdata);
-
-	CS_LOCK(drvdata->base);
-}
-
-static void tmc_etf_disable_hw(struct tmc_drvdata *drvdata)
-{
-	CS_UNLOCK(drvdata->base);
 
-	tmc_flush_and_stop(drvdata);
-	tmc_disable_hw(drvdata);
+	if (!ret)
+		dev_info(drvdata->dev, "TMC read start\n");
 
-	CS_LOCK(drvdata->base);
+	return ret;
 }
 
-static void tmc_disable(struct tmc_drvdata *drvdata, enum tmc_mode mode)
+static int tmc_read_unprepare(struct tmc_drvdata *drvdata)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&drvdata->spinlock, flags);
-	if (drvdata->reading)
-		goto out;
+	int ret = 0;
 
-	if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
-		tmc_etb_disable_hw(drvdata);
-	} else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
-		tmc_etr_disable_hw(drvdata);
-	} else {
-		if (mode == TMC_MODE_CIRCULAR_BUFFER)
-			tmc_etb_disable_hw(drvdata);
-		else
-			tmc_etf_disable_hw(drvdata);
+	switch (drvdata->config_type) {
+	case TMC_CONFIG_TYPE_ETB:
+	case TMC_CONFIG_TYPE_ETF:
+		ret = tmc_read_unprepare_etb(drvdata);
+		break;
+	case TMC_CONFIG_TYPE_ETR:
+		ret = tmc_read_unprepare_etr(drvdata);
+		break;
+	default:
+		ret = -EINVAL;
 	}
-out:
-	drvdata->enable = false;
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
-
-	dev_info(drvdata->dev, "TMC disabled\n");
-}
-
-static void tmc_disable_sink(struct coresight_device *csdev)
-{
-	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-
-	tmc_disable(drvdata, TMC_MODE_CIRCULAR_BUFFER);
-}
-
-static void tmc_disable_link(struct coresight_device *csdev, int inport,
-			     int outport)
-{
-	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-
-	tmc_disable(drvdata, TMC_MODE_HARDWARE_FIFO);
-}
-
-static const struct coresight_ops_sink tmc_sink_ops = {
-	.enable		= tmc_enable_sink,
-	.disable	= tmc_disable_sink,
-};
-
-static const struct coresight_ops_link tmc_link_ops = {
-	.enable		= tmc_enable_link,
-	.disable	= tmc_disable_link,
-};
-
-static const struct coresight_ops tmc_etb_cs_ops = {
-	.sink_ops	= &tmc_sink_ops,
-};
-
-static const struct coresight_ops tmc_etr_cs_ops = {
-	.sink_ops	= &tmc_sink_ops,
-};
-
-static const struct coresight_ops tmc_etf_cs_ops = {
-	.sink_ops	= &tmc_sink_ops,
-	.link_ops	= &tmc_link_ops,
-};
-
-static int tmc_read_prepare(struct tmc_drvdata *drvdata)
-{
-	int ret;
-	unsigned long flags;
-	enum tmc_mode mode;
 
-	spin_lock_irqsave(&drvdata->spinlock, flags);
-	if (!drvdata->enable)
-		goto out;
-
-	if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
-		tmc_etb_disable_hw(drvdata);
-	} else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
-		tmc_etr_disable_hw(drvdata);
-	} else {
-		mode = readl_relaxed(drvdata->base + TMC_MODE);
-		if (mode == TMC_MODE_CIRCULAR_BUFFER) {
-			tmc_etb_disable_hw(drvdata);
-		} else {
-			ret = -ENODEV;
-			goto err;
-		}
-	}
-out:
-	drvdata->reading = true;
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	if (!ret)
+		dev_info(drvdata->dev, "TMC read end\n");
 
-	dev_info(drvdata->dev, "TMC read start\n");
-	return 0;
-err:
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
 	return ret;
 }
 
-static void tmc_read_unprepare(struct tmc_drvdata *drvdata)
-{
-	unsigned long flags;
-	enum tmc_mode mode;
-
-	spin_lock_irqsave(&drvdata->spinlock, flags);
-	if (!drvdata->enable)
-		goto out;
-
-	if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
-		tmc_etb_enable_hw(drvdata);
-	} else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
-		tmc_etr_enable_hw(drvdata);
-	} else {
-		mode = readl_relaxed(drvdata->base + TMC_MODE);
-		if (mode == TMC_MODE_CIRCULAR_BUFFER)
-			tmc_etb_enable_hw(drvdata);
-	}
-out:
-	drvdata->reading = false;
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
-
-	dev_info(drvdata->dev, "TMC read end\n");
-}
-
 static int tmc_open(struct inode *inode, struct file *file)
 {
+	int ret;
 	struct tmc_drvdata *drvdata = container_of(file->private_data,
 						   struct tmc_drvdata, miscdev);
-	int ret = 0;
-
-	if (drvdata->read_count++)
-		goto out;
 
 	ret = tmc_read_prepare(drvdata);
 	if (ret)
 		return ret;
-out:
+
 	nonseekable_open(inode, file);
 
 	dev_dbg(drvdata->dev, "%s: successfully opened\n", __func__);
@@ -531,19 +166,14 @@ static ssize_t tmc_read(struct file *fil
 
 static int tmc_release(struct inode *inode, struct file *file)
 {
+	int ret;
 	struct tmc_drvdata *drvdata = container_of(file->private_data,
 						   struct tmc_drvdata, miscdev);
 
-	if (--drvdata->read_count) {
-		if (drvdata->read_count < 0) {
-			dev_err(drvdata->dev, "mismatched close\n");
-			drvdata->read_count = 0;
-		}
-		goto out;
-	}
+	ret = tmc_read_unprepare(drvdata);
+	if (ret)
+		return ret;
 
-	tmc_read_unprepare(drvdata);
-out:
 	dev_dbg(drvdata->dev, "%s: released\n", __func__);
 	return 0;
 }
@@ -556,56 +186,71 @@ static const struct file_operations tmc_
 	.llseek		= no_llseek,
 };
 
-static ssize_t status_show(struct device *dev,
-			   struct device_attribute *attr, char *buf)
+static enum tmc_mem_intf_width tmc_get_memwidth(u32 devid)
 {
-	unsigned long flags;
-	u32 tmc_rsz, tmc_sts, tmc_rrp, tmc_rwp, tmc_trg;
-	u32 tmc_ctl, tmc_ffsr, tmc_ffcr, tmc_mode, tmc_pscr;
-	u32 devid;
-	struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	enum tmc_mem_intf_width memwidth;
 
-	pm_runtime_get_sync(drvdata->dev);
-	spin_lock_irqsave(&drvdata->spinlock, flags);
-	CS_UNLOCK(drvdata->base);
+	/*
+	 * Excerpt from the TRM:
+	 *
+	 * DEVID::MEMWIDTH[10:8]
+	 * 0x2 Memory interface databus is 32 bits wide.
+	 * 0x3 Memory interface databus is 64 bits wide.
+	 * 0x4 Memory interface databus is 128 bits wide.
+	 * 0x5 Memory interface databus is 256 bits wide.
+	 */
+	switch (BMVAL(devid, 8, 10)) {
+	case 0x2:
+		memwidth = TMC_MEM_INTF_WIDTH_32BITS;
+		break;
+	case 0x3:
+		memwidth = TMC_MEM_INTF_WIDTH_64BITS;
+		break;
+	case 0x4:
+		memwidth = TMC_MEM_INTF_WIDTH_128BITS;
+		break;
+	case 0x5:
+		memwidth = TMC_MEM_INTF_WIDTH_256BITS;
+		break;
+	default:
+		memwidth = 0;
+	}
 
-	tmc_rsz = readl_relaxed(drvdata->base + TMC_RSZ);
-	tmc_sts = readl_relaxed(drvdata->base + TMC_STS);
-	tmc_rrp = readl_relaxed(drvdata->base + TMC_RRP);
-	tmc_rwp = readl_relaxed(drvdata->base + TMC_RWP);
-	tmc_trg = readl_relaxed(drvdata->base + TMC_TRG);
-	tmc_ctl = readl_relaxed(drvdata->base + TMC_CTL);
-	tmc_ffsr = readl_relaxed(drvdata->base + TMC_FFSR);
-	tmc_ffcr = readl_relaxed(drvdata->base + TMC_FFCR);
-	tmc_mode = readl_relaxed(drvdata->base + TMC_MODE);
-	tmc_pscr = readl_relaxed(drvdata->base + TMC_PSCR);
-	devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID);
+	return memwidth;
+}
 
-	CS_LOCK(drvdata->base);
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
-	pm_runtime_put(drvdata->dev);
+#define coresight_tmc_simple_func(name, offset)			\
+	coresight_simple_func(struct tmc_drvdata, name, offset)
 
-	return sprintf(buf,
-		       "Depth:\t\t0x%x\n"
-		       "Status:\t\t0x%x\n"
-		       "RAM read ptr:\t0x%x\n"
-		       "RAM wrt ptr:\t0x%x\n"
-		       "Trigger cnt:\t0x%x\n"
-		       "Control:\t0x%x\n"
-		       "Flush status:\t0x%x\n"
-		       "Flush ctrl:\t0x%x\n"
-		       "Mode:\t\t0x%x\n"
-		       "PSRC:\t\t0x%x\n"
-		       "DEVID:\t\t0x%x\n",
-			tmc_rsz, tmc_sts, tmc_rrp, tmc_rwp, tmc_trg,
-			tmc_ctl, tmc_ffsr, tmc_ffcr, tmc_mode, tmc_pscr, devid);
+coresight_tmc_simple_func(rsz, TMC_RSZ);
+coresight_tmc_simple_func(sts, TMC_STS);
+coresight_tmc_simple_func(rrp, TMC_RRP);
+coresight_tmc_simple_func(rwp, TMC_RWP);
+coresight_tmc_simple_func(trg, TMC_TRG);
+coresight_tmc_simple_func(ctl, TMC_CTL);
+coresight_tmc_simple_func(ffsr, TMC_FFSR);
+coresight_tmc_simple_func(ffcr, TMC_FFCR);
+coresight_tmc_simple_func(mode, TMC_MODE);
+coresight_tmc_simple_func(pscr, TMC_PSCR);
+coresight_tmc_simple_func(devid, CORESIGHT_DEVID);
 
-	return -EINVAL;
-}
-static DEVICE_ATTR_RO(status);
+static struct attribute *coresight_tmc_mgmt_attrs[] = {
+	&dev_attr_rsz.attr,
+	&dev_attr_sts.attr,
+	&dev_attr_rrp.attr,
+	&dev_attr_rwp.attr,
+	&dev_attr_trg.attr,
+	&dev_attr_ctl.attr,
+	&dev_attr_ffsr.attr,
+	&dev_attr_ffcr.attr,
+	&dev_attr_mode.attr,
+	&dev_attr_pscr.attr,
+	&dev_attr_devid.attr,
+	NULL,
+};
 
-static ssize_t trigger_cntr_show(struct device *dev,
-			    struct device_attribute *attr, char *buf)
+ssize_t trigger_cntr_show(struct device *dev,
+			  struct device_attribute *attr, char *buf)
 {
 	struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val = drvdata->trigger_cntr;
@@ -630,26 +275,25 @@ static ssize_t trigger_cntr_store(struct
 }
 static DEVICE_ATTR_RW(trigger_cntr);
 
-static struct attribute *coresight_etb_attrs[] = {
+static struct attribute *coresight_tmc_attrs[] = {
 	&dev_attr_trigger_cntr.attr,
-	&dev_attr_status.attr,
 	NULL,
 };
-ATTRIBUTE_GROUPS(coresight_etb);
 
-static struct attribute *coresight_etr_attrs[] = {
-	&dev_attr_trigger_cntr.attr,
-	&dev_attr_status.attr,
-	NULL,
+static const struct attribute_group coresight_tmc_group = {
+	.attrs = coresight_tmc_attrs,
 };
-ATTRIBUTE_GROUPS(coresight_etr);
 
-static struct attribute *coresight_etf_attrs[] = {
-	&dev_attr_trigger_cntr.attr,
-	&dev_attr_status.attr,
+static const struct attribute_group coresight_tmc_mgmt_group = {
+	.attrs = coresight_tmc_mgmt_attrs,
+	.name = "mgmt",
+};
+
+const struct attribute_group *coresight_tmc_groups[] = {
+	&coresight_tmc_group,
+	&coresight_tmc_mgmt_group,
 	NULL,
 };
-ATTRIBUTE_GROUPS(coresight_etf);
 
 static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
 {
@@ -688,6 +332,7 @@ static int tmc_probe(struct amba_device
 
 	devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID);
 	drvdata->config_type = BMVAL(devid, 6, 7);
+	drvdata->memwidth = tmc_get_memwidth(devid);
 
 	if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
 		if (np)
@@ -702,20 +347,6 @@ static int tmc_probe(struct amba_device
 
 	pm_runtime_put(&adev->dev);
 
-	if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
-		drvdata->vaddr = dma_alloc_coherent(dev, drvdata->size,
-						&drvdata->paddr, GFP_KERNEL);
-		if (!drvdata->vaddr)
-			return -ENOMEM;
-
-		memset(drvdata->vaddr, 0, drvdata->size);
-		drvdata->buf = drvdata->vaddr;
-	} else {
-		drvdata->buf = devm_kzalloc(dev, drvdata->size, GFP_KERNEL);
-		if (!drvdata->buf)
-			return -ENOMEM;
-	}
-
 	desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
 	if (!desc) {
 		ret = -ENOMEM;
@@ -725,20 +356,18 @@ static int tmc_probe(struct amba_device
 	desc->pdata = pdata;
 	desc->dev = dev;
 	desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
+	desc->groups = coresight_tmc_groups;
 
 	if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
 		desc->type = CORESIGHT_DEV_TYPE_SINK;
 		desc->ops = &tmc_etb_cs_ops;
-		desc->groups = coresight_etb_groups;
 	} else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
 		desc->type = CORESIGHT_DEV_TYPE_SINK;
 		desc->ops = &tmc_etr_cs_ops;
-		desc->groups = coresight_etr_groups;
 	} else {
 		desc->type = CORESIGHT_DEV_TYPE_LINKSINK;
 		desc->subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_FIFO;
 		desc->ops = &tmc_etf_cs_ops;
-		desc->groups = coresight_etf_groups;
 	}
 
 	drvdata->csdev = coresight_register(desc);
@@ -754,7 +383,6 @@ static int tmc_probe(struct amba_device
 	if (ret)
 		goto err_misc_register;
 
-	dev_info(dev, "TMC initialized\n");
 	return 0;
 
 err_misc_register:
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwtracing/coresight/coresight-tmc-etf.c linux-libre-4.7-gnu/drivers/hwtracing/coresight/coresight-tmc-etf.c
--- linux-libre-4.6-gnu/drivers/hwtracing/coresight/coresight-tmc-etf.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/hwtracing/coresight/coresight-tmc-etf.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,604 @@
+/*
+ * Copyright(C) 2016 Linaro Limited. All rights reserved.
+ * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/circ_buf.h>
+#include <linux/coresight.h>
+#include <linux/perf_event.h>
+#include <linux/slab.h>
+#include "coresight-priv.h"
+#include "coresight-tmc.h"
+
+void tmc_etb_enable_hw(struct tmc_drvdata *drvdata)
+{
+	CS_UNLOCK(drvdata->base);
+
+	/* Wait for TMCSReady bit to be set */
+	tmc_wait_for_tmcready(drvdata);
+
+	writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE);
+	writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI |
+		       TMC_FFCR_FON_FLIN | TMC_FFCR_FON_TRIG_EVT |
+		       TMC_FFCR_TRIGON_TRIGIN,
+		       drvdata->base + TMC_FFCR);
+
+	writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG);
+	tmc_enable_hw(drvdata);
+
+	CS_LOCK(drvdata->base);
+}
+
+static void tmc_etb_dump_hw(struct tmc_drvdata *drvdata)
+{
+	char *bufp;
+	u32 read_data;
+	int i;
+
+	bufp = drvdata->buf;
+	while (1) {
+		for (i = 0; i < drvdata->memwidth; i++) {
+			read_data = readl_relaxed(drvdata->base + TMC_RRD);
+			if (read_data == 0xFFFFFFFF)
+				return;
+			memcpy(bufp, &read_data, 4);
+			bufp += 4;
+		}
+	}
+}
+
+static void tmc_etb_disable_hw(struct tmc_drvdata *drvdata)
+{
+	CS_UNLOCK(drvdata->base);
+
+	tmc_flush_and_stop(drvdata);
+	/*
+	 * When operating in sysFS mode the content of the buffer needs to be
+	 * read before the TMC is disabled.
+	 */
+	if (local_read(&drvdata->mode) == CS_MODE_SYSFS)
+		tmc_etb_dump_hw(drvdata);
+	tmc_disable_hw(drvdata);
+
+	CS_LOCK(drvdata->base);
+}
+
+static void tmc_etf_enable_hw(struct tmc_drvdata *drvdata)
+{
+	CS_UNLOCK(drvdata->base);
+
+	/* Wait for TMCSReady bit to be set */
+	tmc_wait_for_tmcready(drvdata);
+
+	writel_relaxed(TMC_MODE_HARDWARE_FIFO, drvdata->base + TMC_MODE);
+	writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI,
+		       drvdata->base + TMC_FFCR);
+	writel_relaxed(0x0, drvdata->base + TMC_BUFWM);
+	tmc_enable_hw(drvdata);
+
+	CS_LOCK(drvdata->base);
+}
+
+static void tmc_etf_disable_hw(struct tmc_drvdata *drvdata)
+{
+	CS_UNLOCK(drvdata->base);
+
+	tmc_flush_and_stop(drvdata);
+	tmc_disable_hw(drvdata);
+
+	CS_LOCK(drvdata->base);
+}
+
+static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev, u32 mode)
+{
+	int ret = 0;
+	bool used = false;
+	char *buf = NULL;
+	long val;
+	unsigned long flags;
+	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+	 /* This shouldn't be happening */
+	if (WARN_ON(mode != CS_MODE_SYSFS))
+		return -EINVAL;
+
+	/*
+	 * If we don't have a buffer release the lock and allocate memory.
+	 * Otherwise keep the lock and move along.
+	 */
+	spin_lock_irqsave(&drvdata->spinlock, flags);
+	if (!drvdata->buf) {
+		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+		/* Allocating the memory here while outside of the spinlock */
+		buf = kzalloc(drvdata->size, GFP_KERNEL);
+		if (!buf)
+			return -ENOMEM;
+
+		/* Let's try again */
+		spin_lock_irqsave(&drvdata->spinlock, flags);
+	}
+
+	if (drvdata->reading) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	val = local_xchg(&drvdata->mode, mode);
+	/*
+	 * In sysFS mode we can have multiple writers per sink.  Since this
+	 * sink is already enabled no memory is needed and the HW need not be
+	 * touched.
+	 */
+	if (val == CS_MODE_SYSFS)
+		goto out;
+
+	/*
+	 * If drvdata::buf isn't NULL, memory was allocated for a previous
+	 * trace run but wasn't read.  If so simply zero-out the memory.
+	 * Otherwise use the memory allocated above.
+	 *
+	 * The memory is freed when users read the buffer using the
+	 * /dev/xyz.{etf|etb} interface.  See tmc_read_unprepare_etf() for
+	 * details.
+	 */
+	if (drvdata->buf) {
+		memset(drvdata->buf, 0, drvdata->size);
+	} else {
+		used = true;
+		drvdata->buf = buf;
+	}
+
+	tmc_etb_enable_hw(drvdata);
+out:
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+	/* Free memory outside the spinlock if need be */
+	if (!used && buf)
+		kfree(buf);
+
+	if (!ret)
+		dev_info(drvdata->dev, "TMC-ETB/ETF enabled\n");
+
+	return ret;
+}
+
+static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, u32 mode)
+{
+	int ret = 0;
+	long val;
+	unsigned long flags;
+	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+	 /* This shouldn't be happening */
+	if (WARN_ON(mode != CS_MODE_PERF))
+		return -EINVAL;
+
+	spin_lock_irqsave(&drvdata->spinlock, flags);
+	if (drvdata->reading) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	val = local_xchg(&drvdata->mode, mode);
+	/*
+	 * In Perf mode there can be only one writer per sink.  There
+	 * is also no need to continue if the ETB/ETR is already operated
+	 * from sysFS.
+	 */
+	if (val != CS_MODE_DISABLED) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	tmc_etb_enable_hw(drvdata);
+out:
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+	return ret;
+}
+
+static int tmc_enable_etf_sink(struct coresight_device *csdev, u32 mode)
+{
+	switch (mode) {
+	case CS_MODE_SYSFS:
+		return tmc_enable_etf_sink_sysfs(csdev, mode);
+	case CS_MODE_PERF:
+		return tmc_enable_etf_sink_perf(csdev, mode);
+	}
+
+	/* We shouldn't be here */
+	return -EINVAL;
+}
+
+static void tmc_disable_etf_sink(struct coresight_device *csdev)
+{
+	long val;
+	unsigned long flags;
+	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+	spin_lock_irqsave(&drvdata->spinlock, flags);
+	if (drvdata->reading) {
+		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+		return;
+	}
+
+	val = local_xchg(&drvdata->mode, CS_MODE_DISABLED);
+	/* Disable the TMC only if it needs to */
+	if (val != CS_MODE_DISABLED)
+		tmc_etb_disable_hw(drvdata);
+
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+	dev_info(drvdata->dev, "TMC-ETB/ETF disabled\n");
+}
+
+static int tmc_enable_etf_link(struct coresight_device *csdev,
+			       int inport, int outport)
+{
+	unsigned long flags;
+	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+	spin_lock_irqsave(&drvdata->spinlock, flags);
+	if (drvdata->reading) {
+		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+		return -EBUSY;
+	}
+
+	tmc_etf_enable_hw(drvdata);
+	local_set(&drvdata->mode, CS_MODE_SYSFS);
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+	dev_info(drvdata->dev, "TMC-ETF enabled\n");
+	return 0;
+}
+
+static void tmc_disable_etf_link(struct coresight_device *csdev,
+				 int inport, int outport)
+{
+	unsigned long flags;
+	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+	spin_lock_irqsave(&drvdata->spinlock, flags);
+	if (drvdata->reading) {
+		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+		return;
+	}
+
+	tmc_etf_disable_hw(drvdata);
+	local_set(&drvdata->mode, CS_MODE_DISABLED);
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+	dev_info(drvdata->dev, "TMC disabled\n");
+}
+
+static void *tmc_alloc_etf_buffer(struct coresight_device *csdev, int cpu,
+				  void **pages, int nr_pages, bool overwrite)
+{
+	int node;
+	struct cs_buffers *buf;
+
+	if (cpu == -1)
+		cpu = smp_processor_id();
+	node = cpu_to_node(cpu);
+
+	/* Allocate memory structure for interaction with Perf */
+	buf = kzalloc_node(sizeof(struct cs_buffers), GFP_KERNEL, node);
+	if (!buf)
+		return NULL;
+
+	buf->snapshot = overwrite;
+	buf->nr_pages = nr_pages;
+	buf->data_pages = pages;
+
+	return buf;
+}
+
+static void tmc_free_etf_buffer(void *config)
+{
+	struct cs_buffers *buf = config;
+
+	kfree(buf);
+}
+
+static int tmc_set_etf_buffer(struct coresight_device *csdev,
+			      struct perf_output_handle *handle,
+			      void *sink_config)
+{
+	int ret = 0;
+	unsigned long head;
+	struct cs_buffers *buf = sink_config;
+
+	/* wrap head around to the amount of space we have */
+	head = handle->head & ((buf->nr_pages << PAGE_SHIFT) - 1);
+
+	/* find the page to write to */
+	buf->cur = head / PAGE_SIZE;
+
+	/* and offset within that page */
+	buf->offset = head % PAGE_SIZE;
+
+	local_set(&buf->data_size, 0);
+
+	return ret;
+}
+
+static unsigned long tmc_reset_etf_buffer(struct coresight_device *csdev,
+					  struct perf_output_handle *handle,
+					  void *sink_config, bool *lost)
+{
+	long size = 0;
+	struct cs_buffers *buf = sink_config;
+
+	if (buf) {
+		/*
+		 * In snapshot mode ->data_size holds the new address of the
+		 * ring buffer's head.  The size itself is the whole address
+		 * range since we want the latest information.
+		 */
+		if (buf->snapshot)
+			handle->head = local_xchg(&buf->data_size,
+						  buf->nr_pages << PAGE_SHIFT);
+		/*
+		 * Tell the tracer PMU how much we got in this run and if
+		 * something went wrong along the way.  Nobody else can use
+		 * this cs_buffers instance until we are done.  As such
+		 * resetting parameters here and squaring off with the ring
+		 * buffer API in the tracer PMU is fine.
+		 */
+		*lost = !!local_xchg(&buf->lost, 0);
+		size = local_xchg(&buf->data_size, 0);
+	}
+
+	return size;
+}
+
+static void tmc_update_etf_buffer(struct coresight_device *csdev,
+				  struct perf_output_handle *handle,
+				  void *sink_config)
+{
+	int i, cur;
+	u32 *buf_ptr;
+	u32 read_ptr, write_ptr;
+	u32 status, to_read;
+	unsigned long offset;
+	struct cs_buffers *buf = sink_config;
+	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+	if (!buf)
+		return;
+
+	/* This shouldn't happen */
+	if (WARN_ON_ONCE(local_read(&drvdata->mode) != CS_MODE_PERF))
+		return;
+
+	CS_UNLOCK(drvdata->base);
+
+	tmc_flush_and_stop(drvdata);
+
+	read_ptr = readl_relaxed(drvdata->base + TMC_RRP);
+	write_ptr = readl_relaxed(drvdata->base + TMC_RWP);
+
+	/*
+	 * Get a hold of the status register and see if a wrap around
+	 * has occurred.  If so adjust things accordingly.
+	 */
+	status = readl_relaxed(drvdata->base + TMC_STS);
+	if (status & TMC_STS_FULL) {
+		local_inc(&buf->lost);
+		to_read = drvdata->size;
+	} else {
+		to_read = CIRC_CNT(write_ptr, read_ptr, drvdata->size);
+	}
+
+	/*
+	 * The TMC RAM buffer may be bigger than the space available in the
+	 * perf ring buffer (handle->size).  If so advance the RRP so that we
+	 * get the latest trace data.
+	 */
+	if (to_read > handle->size) {
+		u32 mask = 0;
+
+		/*
+		 * The value written to RRP must be byte-address aligned to
+		 * the width of the trace memory databus _and_ to a frame
+		 * boundary (16 byte), whichever is the biggest. For example,
+		 * for 32-bit, 64-bit and 128-bit wide trace memory, the four
+		 * LSBs must be 0s. For 256-bit wide trace memory, the five
+		 * LSBs must be 0s.
+		 */
+		switch (drvdata->memwidth) {
+		case TMC_MEM_INTF_WIDTH_32BITS:
+		case TMC_MEM_INTF_WIDTH_64BITS:
+		case TMC_MEM_INTF_WIDTH_128BITS:
+			mask = GENMASK(31, 5);
+			break;
+		case TMC_MEM_INTF_WIDTH_256BITS:
+			mask = GENMASK(31, 6);
+			break;
+		}
+
+		/*
+		 * Make sure the new size is aligned in accordance with the
+		 * requirement explained above.
+		 */
+		to_read = handle->size & mask;
+		/* Move the RAM read pointer up */
+		read_ptr = (write_ptr + drvdata->size) - to_read;
+		/* Make sure we are still within our limits */
+		if (read_ptr > (drvdata->size - 1))
+			read_ptr -= drvdata->size;
+		/* Tell the HW */
+		writel_relaxed(read_ptr, drvdata->base + TMC_RRP);
+		local_inc(&buf->lost);
+	}
+
+	cur = buf->cur;
+	offset = buf->offset;
+
+	/* for every byte to read */
+	for (i = 0; i < to_read; i += 4) {
+		buf_ptr = buf->data_pages[cur] + offset;
+		*buf_ptr = readl_relaxed(drvdata->base + TMC_RRD);
+
+		offset += 4;
+		if (offset >= PAGE_SIZE) {
+			offset = 0;
+			cur++;
+			/* wrap around at the end of the buffer */
+			cur &= buf->nr_pages - 1;
+		}
+	}
+
+	/*
+	 * In snapshot mode all we have to do is communicate to
+	 * perf_aux_output_end() the address of the current head.  In full
+	 * trace mode the same function expects a size to move rb->aux_head
+	 * forward.
+	 */
+	if (buf->snapshot)
+		local_set(&buf->data_size, (cur * PAGE_SIZE) + offset);
+	else
+		local_add(to_read, &buf->data_size);
+
+	CS_LOCK(drvdata->base);
+}
+
+static const struct coresight_ops_sink tmc_etf_sink_ops = {
+	.enable		= tmc_enable_etf_sink,
+	.disable	= tmc_disable_etf_sink,
+	.alloc_buffer	= tmc_alloc_etf_buffer,
+	.free_buffer	= tmc_free_etf_buffer,
+	.set_buffer	= tmc_set_etf_buffer,
+	.reset_buffer	= tmc_reset_etf_buffer,
+	.update_buffer	= tmc_update_etf_buffer,
+};
+
+static const struct coresight_ops_link tmc_etf_link_ops = {
+	.enable		= tmc_enable_etf_link,
+	.disable	= tmc_disable_etf_link,
+};
+
+const struct coresight_ops tmc_etb_cs_ops = {
+	.sink_ops	= &tmc_etf_sink_ops,
+};
+
+const struct coresight_ops tmc_etf_cs_ops = {
+	.sink_ops	= &tmc_etf_sink_ops,
+	.link_ops	= &tmc_etf_link_ops,
+};
+
+int tmc_read_prepare_etb(struct tmc_drvdata *drvdata)
+{
+	long val;
+	enum tmc_mode mode;
+	int ret = 0;
+	unsigned long flags;
+
+	/* config types are set a boot time and never change */
+	if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETB &&
+			 drvdata->config_type != TMC_CONFIG_TYPE_ETF))
+		return -EINVAL;
+
+	spin_lock_irqsave(&drvdata->spinlock, flags);
+
+	if (drvdata->reading) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	/* There is no point in reading a TMC in HW FIFO mode */
+	mode = readl_relaxed(drvdata->base + TMC_MODE);
+	if (mode != TMC_MODE_CIRCULAR_BUFFER) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	val = local_read(&drvdata->mode);
+	/* Don't interfere if operated from Perf */
+	if (val == CS_MODE_PERF) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* If drvdata::buf is NULL the trace data has been read already */
+	if (drvdata->buf == NULL) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* Disable the TMC if need be */
+	if (val == CS_MODE_SYSFS)
+		tmc_etb_disable_hw(drvdata);
+
+	drvdata->reading = true;
+out:
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+	return ret;
+}
+
+int tmc_read_unprepare_etb(struct tmc_drvdata *drvdata)
+{
+	char *buf = NULL;
+	enum tmc_mode mode;
+	unsigned long flags;
+
+	/* config types are set a boot time and never change */
+	if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETB &&
+			 drvdata->config_type != TMC_CONFIG_TYPE_ETF))
+		return -EINVAL;
+
+	spin_lock_irqsave(&drvdata->spinlock, flags);
+
+	/* There is no point in reading a TMC in HW FIFO mode */
+	mode = readl_relaxed(drvdata->base + TMC_MODE);
+	if (mode != TMC_MODE_CIRCULAR_BUFFER) {
+		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+		return -EINVAL;
+	}
+
+	/* Re-enable the TMC if need be */
+	if (local_read(&drvdata->mode) == CS_MODE_SYSFS) {
+		/*
+		 * The trace run will continue with the same allocated trace
+		 * buffer. As such zero-out the buffer so that we don't end
+		 * up with stale data.
+		 *
+		 * Since the tracer is still enabled drvdata::buf
+		 * can't be NULL.
+		 */
+		memset(drvdata->buf, 0, drvdata->size);
+		tmc_etb_enable_hw(drvdata);
+	} else {
+		/*
+		 * The ETB/ETF is not tracing and the buffer was just read.
+		 * As such prepare to free the trace buffer.
+		 */
+		buf = drvdata->buf;
+		drvdata->buf = NULL;
+	}
+
+	drvdata->reading = false;
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+	/*
+	 * Free allocated memory outside of the spinlock.  There is no need
+	 * to assert the validity of 'buf' since calling kfree(NULL) is safe.
+	 */
+	kfree(buf);
+
+	return 0;
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwtracing/coresight/coresight-tmc-etr.c linux-libre-4.7-gnu/drivers/hwtracing/coresight/coresight-tmc-etr.c
--- linux-libre-4.6-gnu/drivers/hwtracing/coresight/coresight-tmc-etr.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/hwtracing/coresight/coresight-tmc-etr.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,326 @@
+/*
+ * Copyright(C) 2016 Linaro Limited. All rights reserved.
+ * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/coresight.h>
+#include <linux/dma-mapping.h>
+#include "coresight-priv.h"
+#include "coresight-tmc.h"
+
+void tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
+{
+	u32 axictl;
+
+	/* Zero out the memory to help with debug */
+	memset(drvdata->vaddr, 0, drvdata->size);
+
+	CS_UNLOCK(drvdata->base);
+
+	/* Wait for TMCSReady bit to be set */
+	tmc_wait_for_tmcready(drvdata);
+
+	writel_relaxed(drvdata->size / 4, drvdata->base + TMC_RSZ);
+	writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE);
+
+	axictl = readl_relaxed(drvdata->base + TMC_AXICTL);
+	axictl |= TMC_AXICTL_WR_BURST_16;
+	writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
+	axictl &= ~TMC_AXICTL_SCT_GAT_MODE;
+	writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
+	axictl = (axictl &
+		  ~(TMC_AXICTL_PROT_CTL_B0 | TMC_AXICTL_PROT_CTL_B1)) |
+		  TMC_AXICTL_PROT_CTL_B1;
+	writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
+
+	writel_relaxed(drvdata->paddr, drvdata->base + TMC_DBALO);
+	writel_relaxed(0x0, drvdata->base + TMC_DBAHI);
+	writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI |
+		       TMC_FFCR_FON_FLIN | TMC_FFCR_FON_TRIG_EVT |
+		       TMC_FFCR_TRIGON_TRIGIN,
+		       drvdata->base + TMC_FFCR);
+	writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG);
+	tmc_enable_hw(drvdata);
+
+	CS_LOCK(drvdata->base);
+}
+
+static void tmc_etr_dump_hw(struct tmc_drvdata *drvdata)
+{
+	u32 rwp, val;
+
+	rwp = readl_relaxed(drvdata->base + TMC_RWP);
+	val = readl_relaxed(drvdata->base + TMC_STS);
+
+	/* How much memory do we still have */
+	if (val & BIT(0))
+		drvdata->buf = drvdata->vaddr + rwp - drvdata->paddr;
+	else
+		drvdata->buf = drvdata->vaddr;
+}
+
+static void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
+{
+	CS_UNLOCK(drvdata->base);
+
+	tmc_flush_and_stop(drvdata);
+	/*
+	 * When operating in sysFS mode the content of the buffer needs to be
+	 * read before the TMC is disabled.
+	 */
+	if (local_read(&drvdata->mode) == CS_MODE_SYSFS)
+		tmc_etr_dump_hw(drvdata);
+	tmc_disable_hw(drvdata);
+
+	CS_LOCK(drvdata->base);
+}
+
+static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev, u32 mode)
+{
+	int ret = 0;
+	bool used = false;
+	long val;
+	unsigned long flags;
+	void __iomem *vaddr = NULL;
+	dma_addr_t paddr;
+	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+	 /* This shouldn't be happening */
+	if (WARN_ON(mode != CS_MODE_SYSFS))
+		return -EINVAL;
+
+	/*
+	 * If we don't have a buffer release the lock and allocate memory.
+	 * Otherwise keep the lock and move along.
+	 */
+	spin_lock_irqsave(&drvdata->spinlock, flags);
+	if (!drvdata->vaddr) {
+		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+		/*
+		 * Contiguous  memory can't be allocated while a spinlock is
+		 * held.  As such allocate memory here and free it if a buffer
+		 * has already been allocated (from a previous session).
+		 */
+		vaddr = dma_alloc_coherent(drvdata->dev, drvdata->size,
+					   &paddr, GFP_KERNEL);
+		if (!vaddr)
+			return -ENOMEM;
+
+		/* Let's try again */
+		spin_lock_irqsave(&drvdata->spinlock, flags);
+	}
+
+	if (drvdata->reading) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	val = local_xchg(&drvdata->mode, mode);
+	/*
+	 * In sysFS mode we can have multiple writers per sink.  Since this
+	 * sink is already enabled no memory is needed and the HW need not be
+	 * touched.
+	 */
+	if (val == CS_MODE_SYSFS)
+		goto out;
+
+	/*
+	 * If drvdata::buf == NULL, use the memory allocated above.
+	 * Otherwise a buffer still exists from a previous session, so
+	 * simply use that.
+	 */
+	if (drvdata->buf == NULL) {
+		used = true;
+		drvdata->vaddr = vaddr;
+		drvdata->paddr = paddr;
+		drvdata->buf = drvdata->vaddr;
+	}
+
+	memset(drvdata->vaddr, 0, drvdata->size);
+
+	tmc_etr_enable_hw(drvdata);
+out:
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+	/* Free memory outside the spinlock if need be */
+	if (!used && vaddr)
+		dma_free_coherent(drvdata->dev, drvdata->size, vaddr, paddr);
+
+	if (!ret)
+		dev_info(drvdata->dev, "TMC-ETR enabled\n");
+
+	return ret;
+}
+
+static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, u32 mode)
+{
+	int ret = 0;
+	long val;
+	unsigned long flags;
+	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+	 /* This shouldn't be happening */
+	if (WARN_ON(mode != CS_MODE_PERF))
+		return -EINVAL;
+
+	spin_lock_irqsave(&drvdata->spinlock, flags);
+	if (drvdata->reading) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	val = local_xchg(&drvdata->mode, mode);
+	/*
+	 * In Perf mode there can be only one writer per sink.  There
+	 * is also no need to continue if the ETR is already operated
+	 * from sysFS.
+	 */
+	if (val != CS_MODE_DISABLED) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	tmc_etr_enable_hw(drvdata);
+out:
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+	return ret;
+}
+
+static int tmc_enable_etr_sink(struct coresight_device *csdev, u32 mode)
+{
+	switch (mode) {
+	case CS_MODE_SYSFS:
+		return tmc_enable_etr_sink_sysfs(csdev, mode);
+	case CS_MODE_PERF:
+		return tmc_enable_etr_sink_perf(csdev, mode);
+	}
+
+	/* We shouldn't be here */
+	return -EINVAL;
+}
+
+static void tmc_disable_etr_sink(struct coresight_device *csdev)
+{
+	long val;
+	unsigned long flags;
+	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+	spin_lock_irqsave(&drvdata->spinlock, flags);
+	if (drvdata->reading) {
+		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+		return;
+	}
+
+	val = local_xchg(&drvdata->mode, CS_MODE_DISABLED);
+	/* Disable the TMC only if it needs to */
+	if (val != CS_MODE_DISABLED)
+		tmc_etr_disable_hw(drvdata);
+
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+	dev_info(drvdata->dev, "TMC-ETR disabled\n");
+}
+
+static const struct coresight_ops_sink tmc_etr_sink_ops = {
+	.enable		= tmc_enable_etr_sink,
+	.disable	= tmc_disable_etr_sink,
+};
+
+const struct coresight_ops tmc_etr_cs_ops = {
+	.sink_ops	= &tmc_etr_sink_ops,
+};
+
+int tmc_read_prepare_etr(struct tmc_drvdata *drvdata)
+{
+	int ret = 0;
+	long val;
+	unsigned long flags;
+
+	/* config types are set a boot time and never change */
+	if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETR))
+		return -EINVAL;
+
+	spin_lock_irqsave(&drvdata->spinlock, flags);
+	if (drvdata->reading) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	val = local_read(&drvdata->mode);
+	/* Don't interfere if operated from Perf */
+	if (val == CS_MODE_PERF) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* If drvdata::buf is NULL the trace data has been read already */
+	if (drvdata->buf == NULL) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* Disable the TMC if need be */
+	if (val == CS_MODE_SYSFS)
+		tmc_etr_disable_hw(drvdata);
+
+	drvdata->reading = true;
+out:
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+	return ret;
+}
+
+int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata)
+{
+	unsigned long flags;
+	dma_addr_t paddr;
+	void __iomem *vaddr = NULL;
+
+	/* config types are set a boot time and never change */
+	if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETR))
+		return -EINVAL;
+
+	spin_lock_irqsave(&drvdata->spinlock, flags);
+
+	/* RE-enable the TMC if need be */
+	if (local_read(&drvdata->mode) == CS_MODE_SYSFS) {
+		/*
+		 * The trace run will continue with the same allocated trace
+		 * buffer. The trace buffer is cleared in tmc_etr_enable_hw(),
+		 * so we don't have to explicitly clear it. Also, since the
+		 * tracer is still enabled drvdata::buf can't be NULL.
+		 */
+		tmc_etr_enable_hw(drvdata);
+	} else {
+		/*
+		 * The ETR is not tracing and the buffer was just read.
+		 * As such prepare to free the trace buffer.
+		 */
+		vaddr = drvdata->vaddr;
+		paddr = drvdata->paddr;
+		drvdata->buf = drvdata->vaddr = NULL;
+	}
+
+	drvdata->reading = false;
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+	/* Free allocated memory out side of the spinlock */
+	if (vaddr)
+		dma_free_coherent(drvdata->dev, drvdata->size, vaddr, paddr);
+
+	return 0;
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwtracing/coresight/coresight-tmc.h linux-libre-4.7-gnu/drivers/hwtracing/coresight/coresight-tmc.h
--- linux-libre-4.6-gnu/drivers/hwtracing/coresight/coresight-tmc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/hwtracing/coresight/coresight-tmc.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,140 @@
+/*
+ * Copyright(C) 2015 Linaro Limited. All rights reserved.
+ * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _CORESIGHT_TMC_H
+#define _CORESIGHT_TMC_H
+
+#include <linux/miscdevice.h>
+
+#define TMC_RSZ			0x004
+#define TMC_STS			0x00c
+#define TMC_RRD			0x010
+#define TMC_RRP			0x014
+#define TMC_RWP			0x018
+#define TMC_TRG			0x01c
+#define TMC_CTL			0x020
+#define TMC_RWD			0x024
+#define TMC_MODE		0x028
+#define TMC_LBUFLEVEL		0x02c
+#define TMC_CBUFLEVEL		0x030
+#define TMC_BUFWM		0x034
+#define TMC_RRPHI		0x038
+#define TMC_RWPHI		0x03c
+#define TMC_AXICTL		0x110
+#define TMC_DBALO		0x118
+#define TMC_DBAHI		0x11c
+#define TMC_FFSR		0x300
+#define TMC_FFCR		0x304
+#define TMC_PSCR		0x308
+#define TMC_ITMISCOP0		0xee0
+#define TMC_ITTRFLIN		0xee8
+#define TMC_ITATBDATA0		0xeec
+#define TMC_ITATBCTR2		0xef0
+#define TMC_ITATBCTR1		0xef4
+#define TMC_ITATBCTR0		0xef8
+
+/* register description */
+/* TMC_CTL - 0x020 */
+#define TMC_CTL_CAPT_EN		BIT(0)
+/* TMC_STS - 0x00C */
+#define TMC_STS_TMCREADY_BIT	2
+#define TMC_STS_FULL		BIT(0)
+#define TMC_STS_TRIGGERED	BIT(1)
+/* TMC_AXICTL - 0x110 */
+#define TMC_AXICTL_PROT_CTL_B0	BIT(0)
+#define TMC_AXICTL_PROT_CTL_B1	BIT(1)
+#define TMC_AXICTL_SCT_GAT_MODE	BIT(7)
+#define TMC_AXICTL_WR_BURST_16	0xF00
+/* TMC_FFCR - 0x304 */
+#define TMC_FFCR_FLUSHMAN_BIT	6
+#define TMC_FFCR_EN_FMT		BIT(0)
+#define TMC_FFCR_EN_TI		BIT(1)
+#define TMC_FFCR_FON_FLIN	BIT(4)
+#define TMC_FFCR_FON_TRIG_EVT	BIT(5)
+#define TMC_FFCR_TRIGON_TRIGIN	BIT(8)
+#define TMC_FFCR_STOP_ON_FLUSH	BIT(12)
+
+
+enum tmc_config_type {
+	TMC_CONFIG_TYPE_ETB,
+	TMC_CONFIG_TYPE_ETR,
+	TMC_CONFIG_TYPE_ETF,
+};
+
+enum tmc_mode {
+	TMC_MODE_CIRCULAR_BUFFER,
+	TMC_MODE_SOFTWARE_FIFO,
+	TMC_MODE_HARDWARE_FIFO,
+};
+
+enum tmc_mem_intf_width {
+	TMC_MEM_INTF_WIDTH_32BITS	= 1,
+	TMC_MEM_INTF_WIDTH_64BITS	= 2,
+	TMC_MEM_INTF_WIDTH_128BITS	= 4,
+	TMC_MEM_INTF_WIDTH_256BITS	= 8,
+};
+
+/**
+ * struct tmc_drvdata - specifics associated to an TMC component
+ * @base:	memory mapped base address for this component.
+ * @dev:	the device entity associated to this component.
+ * @csdev:	component vitals needed by the framework.
+ * @miscdev:	specifics to handle "/dev/xyz.tmc" entry.
+ * @spinlock:	only one at a time pls.
+ * @buf:	area of memory where trace data get sent.
+ * @paddr:	DMA start location in RAM.
+ * @vaddr:	virtual representation of @paddr.
+ * @size:	@buf size.
+ * @mode:	how this TMC is being used.
+ * @config_type: TMC variant, must be of type @tmc_config_type.
+ * @memwidth:	width of the memory interface databus, in bytes.
+ * @trigger_cntr: amount of words to store after a trigger.
+ */
+struct tmc_drvdata {
+	void __iomem		*base;
+	struct device		*dev;
+	struct coresight_device	*csdev;
+	struct miscdevice	miscdev;
+	spinlock_t		spinlock;
+	bool			reading;
+	char			*buf;
+	dma_addr_t		paddr;
+	void __iomem		*vaddr;
+	u32			size;
+	local_t			mode;
+	enum tmc_config_type	config_type;
+	enum tmc_mem_intf_width	memwidth;
+	u32			trigger_cntr;
+};
+
+/* Generic functions */
+void tmc_wait_for_tmcready(struct tmc_drvdata *drvdata);
+void tmc_flush_and_stop(struct tmc_drvdata *drvdata);
+void tmc_enable_hw(struct tmc_drvdata *drvdata);
+void tmc_disable_hw(struct tmc_drvdata *drvdata);
+
+/* ETB/ETF functions */
+int tmc_read_prepare_etb(struct tmc_drvdata *drvdata);
+int tmc_read_unprepare_etb(struct tmc_drvdata *drvdata);
+extern const struct coresight_ops tmc_etb_cs_ops;
+extern const struct coresight_ops tmc_etf_cs_ops;
+
+/* ETR functions */
+int tmc_read_prepare_etr(struct tmc_drvdata *drvdata);
+int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata);
+extern const struct coresight_ops tmc_etr_cs_ops;
+#endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwtracing/coresight/coresight-tpiu.c linux-libre-4.7-gnu/drivers/hwtracing/coresight/coresight-tpiu.c
--- linux-libre-4.6-gnu/drivers/hwtracing/coresight/coresight-tpiu.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hwtracing/coresight/coresight-tpiu.c	2016-07-24 15:23:50.000000000 -0400
@@ -167,7 +167,6 @@ static int tpiu_probe(struct amba_device
 	if (IS_ERR(drvdata->csdev))
 		return PTR_ERR(drvdata->csdev);
 
-	dev_info(dev, "TPIU initialized\n");
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwtracing/coresight/Kconfig linux-libre-4.7-gnu/drivers/hwtracing/coresight/Kconfig
--- linux-libre-4.6-gnu/drivers/hwtracing/coresight/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hwtracing/coresight/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -78,4 +78,15 @@ config CORESIGHT_QCOM_REPLICATOR
 	  programmable ATB replicator sends the ATB trace stream from the
 	  ETB/ETF to the TPIUi and ETR.
 
+config CORESIGHT_STM
+	bool "CoreSight System Trace Macrocell driver"
+	depends on (ARM && !(CPU_32v3 || CPU_32v4 || CPU_32v4T)) || ARM64
+	select CORESIGHT_LINKS_AND_SINKS
+	select STM
+	help
+	  This driver provides support for hardware assisted software
+	  instrumentation based tracing. This is primarily used for
+	  logging useful software events or data coming from various entities
+	  in the system, possibly running different OSs
+
 endif
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwtracing/coresight/Makefile linux-libre-4.7-gnu/drivers/hwtracing/coresight/Makefile
--- linux-libre-4.6-gnu/drivers/hwtracing/coresight/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hwtracing/coresight/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -1,15 +1,18 @@
 #
 # Makefile for CoreSight drivers.
 #
-obj-$(CONFIG_CORESIGHT) += coresight.o
+obj-$(CONFIG_CORESIGHT) += coresight.o coresight-etm-perf.o
 obj-$(CONFIG_OF) += of_coresight.o
-obj-$(CONFIG_CORESIGHT_LINK_AND_SINK_TMC) += coresight-tmc.o
+obj-$(CONFIG_CORESIGHT_LINK_AND_SINK_TMC) += coresight-tmc.o \
+					     coresight-tmc-etf.o \
+					     coresight-tmc-etr.o
 obj-$(CONFIG_CORESIGHT_SINK_TPIU) += coresight-tpiu.o
 obj-$(CONFIG_CORESIGHT_SINK_ETBV10) += coresight-etb10.o
 obj-$(CONFIG_CORESIGHT_LINKS_AND_SINKS) += coresight-funnel.o \
 					   coresight-replicator.o
 obj-$(CONFIG_CORESIGHT_SOURCE_ETM3X) += coresight-etm3x.o coresight-etm-cp14.o \
-					coresight-etm3x-sysfs.o \
-					coresight-etm-perf.o
-obj-$(CONFIG_CORESIGHT_SOURCE_ETM4X) += coresight-etm4x.o
+					coresight-etm3x-sysfs.o
+obj-$(CONFIG_CORESIGHT_SOURCE_ETM4X) += coresight-etm4x.o \
+					coresight-etm4x-sysfs.o
 obj-$(CONFIG_CORESIGHT_QCOM_REPLICATOR) += coresight-replicator-qcom.o
+obj-$(CONFIG_CORESIGHT_STM) += coresight-stm.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwtracing/intel_th/core.c linux-libre-4.7-gnu/drivers/hwtracing/intel_th/core.c
--- linux-libre-4.6-gnu/drivers/hwtracing/intel_th/core.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hwtracing/intel_th/core.c	2016-07-24 15:23:50.000000000 -0400
@@ -71,6 +71,15 @@ static int intel_th_probe(struct device
 	if (ret)
 		return ret;
 
+	if (thdrv->attr_group) {
+		ret = sysfs_create_group(&thdev->dev.kobj, thdrv->attr_group);
+		if (ret) {
+			thdrv->remove(thdev);
+
+			return ret;
+		}
+	}
+
 	if (thdev->type == INTEL_TH_OUTPUT &&
 	    !intel_th_output_assigned(thdev))
 		ret = hubdrv->assign(hub, thdev);
@@ -91,6 +100,9 @@ static int intel_th_remove(struct device
 			return err;
 	}
 
+	if (thdrv->attr_group)
+		sysfs_remove_group(&thdev->dev.kobj, thdrv->attr_group);
+
 	thdrv->remove(thdev);
 
 	if (intel_th_output_assigned(thdev)) {
@@ -171,7 +183,14 @@ static DEVICE_ATTR_RO(port);
 
 static int intel_th_output_activate(struct intel_th_device *thdev)
 {
-	struct intel_th_driver *thdrv = to_intel_th_driver(thdev->dev.driver);
+	struct intel_th_driver *thdrv =
+		to_intel_th_driver_or_null(thdev->dev.driver);
+
+	if (!thdrv)
+		return -ENODEV;
+
+	if (!try_module_get(thdrv->driver.owner))
+		return -ENODEV;
 
 	if (thdrv->activate)
 		return thdrv->activate(thdev);
@@ -183,12 +202,18 @@ static int intel_th_output_activate(stru
 
 static void intel_th_output_deactivate(struct intel_th_device *thdev)
 {
-	struct intel_th_driver *thdrv = to_intel_th_driver(thdev->dev.driver);
+	struct intel_th_driver *thdrv =
+		to_intel_th_driver_or_null(thdev->dev.driver);
+
+	if (!thdrv)
+		return;
 
 	if (thdrv->deactivate)
 		thdrv->deactivate(thdev);
 	else
 		intel_th_trace_disable(thdev);
+
+	module_put(thdrv->driver.owner);
 }
 
 static ssize_t active_show(struct device *dev, struct device_attribute *attr,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwtracing/intel_th/intel_th.h linux-libre-4.7-gnu/drivers/hwtracing/intel_th/intel_th.h
--- linux-libre-4.6-gnu/drivers/hwtracing/intel_th/intel_th.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hwtracing/intel_th/intel_th.h	2016-07-24 15:23:50.000000000 -0400
@@ -115,6 +115,7 @@ intel_th_output_assigned(struct intel_th
  * @enable:	enable tracing for a given output device
  * @disable:	disable tracing for a given output device
  * @fops:	file operations for device nodes
+ * @attr_group:	attributes provided by the driver
  *
  * Callbacks @probe and @remove are required for all device types.
  * Switch device driver needs to fill in @assign, @enable and @disable
@@ -139,6 +140,8 @@ struct intel_th_driver {
 	void			(*deactivate)(struct intel_th_device *thdev);
 	/* file_operations for those who want a device node */
 	const struct file_operations *fops;
+	/* optional attributes */
+	struct attribute_group	*attr_group;
 
 	/* source ops */
 	int			(*set_output)(struct intel_th_device *thdev,
@@ -148,6 +151,9 @@ struct intel_th_driver {
 #define to_intel_th_driver(_d)					\
 	container_of((_d), struct intel_th_driver, driver)
 
+#define to_intel_th_driver_or_null(_d)		\
+	((_d) ? to_intel_th_driver(_d) : NULL)
+
 static inline struct intel_th_device *
 to_intel_th_hub(struct intel_th_device *thdev)
 {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwtracing/intel_th/msu.c linux-libre-4.7-gnu/drivers/hwtracing/intel_th/msu.c
--- linux-libre-4.6-gnu/drivers/hwtracing/intel_th/msu.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hwtracing/intel_th/msu.c	2016-07-24 15:23:50.000000000 -0400
@@ -122,7 +122,6 @@ struct msc {
 	atomic_t		mmap_count;
 	struct mutex		buf_mutex;
 
-	struct mutex		iter_mutex;
 	struct list_head	iter_list;
 
 	/* config */
@@ -257,23 +256,37 @@ static struct msc_iter *msc_iter_install
 
 	iter = kzalloc(sizeof(*iter), GFP_KERNEL);
 	if (!iter)
-		return NULL;
+		return ERR_PTR(-ENOMEM);
+
+	mutex_lock(&msc->buf_mutex);
+
+	/*
+	 * Reading and tracing are mutually exclusive; if msc is
+	 * enabled, open() will fail; otherwise existing readers
+	 * will prevent enabling the msc and the rest of fops don't
+	 * need to worry about it.
+	 */
+	if (msc->enabled) {
+		kfree(iter);
+		iter = ERR_PTR(-EBUSY);
+		goto unlock;
+	}
 
 	msc_iter_init(iter);
 	iter->msc = msc;
 
-	mutex_lock(&msc->iter_mutex);
 	list_add_tail(&iter->entry, &msc->iter_list);
-	mutex_unlock(&msc->iter_mutex);
+unlock:
+	mutex_unlock(&msc->buf_mutex);
 
 	return iter;
 }
 
 static void msc_iter_remove(struct msc_iter *iter, struct msc *msc)
 {
-	mutex_lock(&msc->iter_mutex);
+	mutex_lock(&msc->buf_mutex);
 	list_del(&iter->entry);
-	mutex_unlock(&msc->iter_mutex);
+	mutex_unlock(&msc->buf_mutex);
 
 	kfree(iter);
 }
@@ -454,7 +467,6 @@ static void msc_buffer_clear_hw_header(s
 {
 	struct msc_window *win;
 
-	mutex_lock(&msc->buf_mutex);
 	list_for_each_entry(win, &msc->win_list, entry) {
 		unsigned int blk;
 		size_t hw_sz = sizeof(struct msc_block_desc) -
@@ -466,7 +478,6 @@ static void msc_buffer_clear_hw_header(s
 			memset(&bdesc->hw_tag, 0, hw_sz);
 		}
 	}
-	mutex_unlock(&msc->buf_mutex);
 }
 
 /**
@@ -474,12 +485,15 @@ static void msc_buffer_clear_hw_header(s
  * @msc:	the MSC device to configure
  *
  * Program storage mode, wrapping, burst length and trace buffer address
- * into a given MSC. If msc::enabled is set, enable the trace, too.
+ * into a given MSC. Then, enable tracing and set msc::enabled.
+ * The latter is serialized on msc::buf_mutex, so make sure to hold it.
  */
 static int msc_configure(struct msc *msc)
 {
 	u32 reg;
 
+	lockdep_assert_held(&msc->buf_mutex);
+
 	if (msc->mode > MSC_MODE_MULTI)
 		return -ENOTSUPP;
 
@@ -497,21 +511,19 @@ static int msc_configure(struct msc *msc
 	reg = ioread32(msc->reg_base + REG_MSU_MSC0CTL);
 	reg &= ~(MSC_MODE | MSC_WRAPEN | MSC_EN | MSC_RD_HDR_OVRD);
 
+	reg |= MSC_EN;
 	reg |= msc->mode << __ffs(MSC_MODE);
 	reg |= msc->burst_len << __ffs(MSC_LEN);
-	/*if (msc->mode == MSC_MODE_MULTI)
-	  reg |= MSC_RD_HDR_OVRD; */
+
 	if (msc->wrap)
 		reg |= MSC_WRAPEN;
-	if (msc->enabled)
-		reg |= MSC_EN;
 
 	iowrite32(reg, msc->reg_base + REG_MSU_MSC0CTL);
 
-	if (msc->enabled) {
-		msc->thdev->output.multiblock = msc->mode == MSC_MODE_MULTI;
-		intel_th_trace_enable(msc->thdev);
-	}
+	msc->thdev->output.multiblock = msc->mode == MSC_MODE_MULTI;
+	intel_th_trace_enable(msc->thdev);
+	msc->enabled = 1;
+
 
 	return 0;
 }
@@ -521,15 +533,14 @@ static int msc_configure(struct msc *msc
  * @msc:	MSC device to disable
  *
  * If @msc is enabled, disable tracing on the switch and then disable MSC
- * storage.
+ * storage. Caller must hold msc::buf_mutex.
  */
 static void msc_disable(struct msc *msc)
 {
 	unsigned long count;
 	u32 reg;
 
-	if (!msc->enabled)
-		return;
+	lockdep_assert_held(&msc->buf_mutex);
 
 	intel_th_trace_disable(msc->thdev);
 
@@ -569,33 +580,35 @@ static void msc_disable(struct msc *msc)
 static int intel_th_msc_activate(struct intel_th_device *thdev)
 {
 	struct msc *msc = dev_get_drvdata(&thdev->dev);
-	int ret = 0;
+	int ret = -EBUSY;
 
 	if (!atomic_inc_unless_negative(&msc->user_count))
 		return -ENODEV;
 
-	mutex_lock(&msc->iter_mutex);
-	if (!list_empty(&msc->iter_list))
-		ret = -EBUSY;
-	mutex_unlock(&msc->iter_mutex);
+	mutex_lock(&msc->buf_mutex);
 
-	if (ret) {
-		atomic_dec(&msc->user_count);
-		return ret;
-	}
+	/* if there are readers, refuse */
+	if (list_empty(&msc->iter_list))
+		ret = msc_configure(msc);
 
-	msc->enabled = 1;
+	mutex_unlock(&msc->buf_mutex);
 
-	return msc_configure(msc);
+	if (ret)
+		atomic_dec(&msc->user_count);
+
+	return ret;
 }
 
 static void intel_th_msc_deactivate(struct intel_th_device *thdev)
 {
 	struct msc *msc = dev_get_drvdata(&thdev->dev);
 
-	msc_disable(msc);
-
-	atomic_dec(&msc->user_count);
+	mutex_lock(&msc->buf_mutex);
+	if (msc->enabled) {
+		msc_disable(msc);
+		atomic_dec(&msc->user_count);
+	}
+	mutex_unlock(&msc->buf_mutex);
 }
 
 /**
@@ -1035,8 +1048,8 @@ static int intel_th_msc_open(struct inod
 		return -EPERM;
 
 	iter = msc_iter_install(msc);
-	if (!iter)
-		return -ENOMEM;
+	if (IS_ERR(iter))
+		return PTR_ERR(iter);
 
 	file->private_data = iter;
 
@@ -1101,11 +1114,6 @@ static ssize_t intel_th_msc_read(struct
 	if (!atomic_inc_unless_negative(&msc->user_count))
 		return 0;
 
-	if (msc->enabled) {
-		ret = -EBUSY;
-		goto put_count;
-	}
-
 	if (msc->mode == MSC_MODE_SINGLE && !msc->single_wrap)
 		size = msc->single_sz;
 	else
@@ -1164,7 +1172,7 @@ static void msc_mmap_close(struct vm_are
 	if (!atomic_dec_and_mutex_lock(&msc->mmap_count, &msc->buf_mutex))
 		return;
 
-	/* drop page _counts */
+	/* drop page _refcounts */
 	for (pg = 0; pg < msc->nr_pages; pg++) {
 		struct page *page = msc_buffer_get_page(msc, pg);
 
@@ -1245,6 +1253,7 @@ static const struct file_operations inte
 	.read		= intel_th_msc_read,
 	.mmap		= intel_th_msc_mmap,
 	.llseek		= no_llseek,
+	.owner		= THIS_MODULE,
 };
 
 static int intel_th_msc_init(struct msc *msc)
@@ -1254,8 +1263,6 @@ static int intel_th_msc_init(struct msc
 	msc->mode = MSC_MODE_MULTI;
 	mutex_init(&msc->buf_mutex);
 	INIT_LIST_HEAD(&msc->win_list);
-
-	mutex_init(&msc->iter_mutex);
 	INIT_LIST_HEAD(&msc->iter_list);
 
 	msc->burst_len =
@@ -1393,6 +1400,11 @@ nr_pages_store(struct device *dev, struc
 	do {
 		end = memchr(p, ',', len);
 		s = kstrndup(p, end ? end - p : len, GFP_KERNEL);
+		if (!s) {
+			ret = -ENOMEM;
+			goto free_win;
+		}
+
 		ret = kstrtoul(s, 10, &val);
 		kfree(s);
 
@@ -1473,10 +1485,6 @@ static int intel_th_msc_probe(struct int
 	if (err)
 		return err;
 
-	err = sysfs_create_group(&dev->kobj, &msc_output_group);
-	if (err)
-		return err;
-
 	dev_set_drvdata(dev, msc);
 
 	return 0;
@@ -1484,7 +1492,18 @@ static int intel_th_msc_probe(struct int
 
 static void intel_th_msc_remove(struct intel_th_device *thdev)
 {
-	sysfs_remove_group(&thdev->dev.kobj, &msc_output_group);
+	struct msc *msc = dev_get_drvdata(&thdev->dev);
+	int ret;
+
+	intel_th_msc_deactivate(thdev);
+
+	/*
+	 * Buffers should not be used at this point except if the
+	 * output character device is still open and the parent
+	 * device gets detached from its bus, which is a FIXME.
+	 */
+	ret = msc_buffer_free_unless_used(msc);
+	WARN_ON_ONCE(ret);
 }
 
 static struct intel_th_driver intel_th_msc_driver = {
@@ -1493,6 +1512,7 @@ static struct intel_th_driver intel_th_m
 	.activate	= intel_th_msc_activate,
 	.deactivate	= intel_th_msc_deactivate,
 	.fops	= &intel_th_msc_fops,
+	.attr_group	= &msc_output_group,
 	.driver	= {
 		.name	= "msc",
 		.owner	= THIS_MODULE,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwtracing/intel_th/pci.c linux-libre-4.7-gnu/drivers/hwtracing/intel_th/pci.c
--- linux-libre-4.6-gnu/drivers/hwtracing/intel_th/pci.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hwtracing/intel_th/pci.c	2016-07-24 15:23:50.000000000 -0400
@@ -75,6 +75,11 @@ static const struct pci_device_id intel_
 		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0a80),
 		.driver_data = (kernel_ulong_t)0,
 	},
+	{
+		/* Broxton B-step */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x1a8e),
+		.driver_data = (kernel_ulong_t)0,
+	},
 	{ 0 },
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwtracing/intel_th/pti.c linux-libre-4.7-gnu/drivers/hwtracing/intel_th/pti.c
--- linux-libre-4.6-gnu/drivers/hwtracing/intel_th/pti.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hwtracing/intel_th/pti.c	2016-07-24 15:23:50.000000000 -0400
@@ -200,7 +200,6 @@ static int intel_th_pti_probe(struct int
 	struct resource *res;
 	struct pti_device *pti;
 	void __iomem *base;
-	int ret;
 
 	res = intel_th_device_get_resource(thdev, IORESOURCE_MEM, 0);
 	if (!res)
@@ -219,10 +218,6 @@ static int intel_th_pti_probe(struct int
 
 	read_hw_config(pti);
 
-	ret = sysfs_create_group(&dev->kobj, &pti_output_group);
-	if (ret)
-		return ret;
-
 	dev_set_drvdata(dev, pti);
 
 	return 0;
@@ -237,6 +232,7 @@ static struct intel_th_driver intel_th_p
 	.remove	= intel_th_pti_remove,
 	.activate	= intel_th_pti_activate,
 	.deactivate	= intel_th_pti_deactivate,
+	.attr_group	= &pti_output_group,
 	.driver	= {
 		.name	= "pti",
 		.owner	= THIS_MODULE,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwtracing/stm/core.c linux-libre-4.7-gnu/drivers/hwtracing/stm/core.c
--- linux-libre-4.6-gnu/drivers/hwtracing/stm/core.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hwtracing/stm/core.c	2016-07-24 15:23:50.000000000 -0400
@@ -67,9 +67,24 @@ static ssize_t channels_show(struct devi
 
 static DEVICE_ATTR_RO(channels);
 
+static ssize_t hw_override_show(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	struct stm_device *stm = to_stm_device(dev);
+	int ret;
+
+	ret = sprintf(buf, "%u\n", stm->data->hw_override);
+
+	return ret;
+}
+
+static DEVICE_ATTR_RO(hw_override);
+
 static struct attribute *stm_attrs[] = {
 	&dev_attr_masters.attr,
 	&dev_attr_channels.attr,
+	&dev_attr_hw_override.attr,
 	NULL,
 };
 
@@ -546,8 +561,6 @@ static int stm_char_policy_set_ioctl(str
 	if (ret)
 		goto err_free;
 
-	ret = 0;
-
 	if (stm->data->link)
 		ret = stm->data->link(stm->data, stmf->output.master,
 				      stmf->output.channel);
@@ -668,18 +681,11 @@ int stm_register_device(struct device *p
 	stm->dev.parent = parent;
 	stm->dev.release = stm_device_release;
 
-	err = kobject_set_name(&stm->dev.kobj, "%s", stm_data->name);
-	if (err)
-		goto err_device;
-
-	err = device_add(&stm->dev);
-	if (err)
-		goto err_device;
-
 	mutex_init(&stm->link_mutex);
 	spin_lock_init(&stm->link_lock);
 	INIT_LIST_HEAD(&stm->link_list);
 
+	/* initialize the object before it is accessible via sysfs */
 	spin_lock_init(&stm->mc_lock);
 	mutex_init(&stm->policy_mutex);
 	stm->sw_nmasters = nmasters;
@@ -687,9 +693,19 @@ int stm_register_device(struct device *p
 	stm->data = stm_data;
 	stm_data->stm = stm;
 
+	err = kobject_set_name(&stm->dev.kobj, "%s", stm_data->name);
+	if (err)
+		goto err_device;
+
+	err = device_add(&stm->dev);
+	if (err)
+		goto err_device;
+
 	return 0;
 
 err_device:
+	unregister_chrdev(stm->major, stm_data->name);
+
 	/* matches device_initialize() above */
 	put_device(&stm->dev);
 err_free:
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwtracing/stm/dummy_stm.c linux-libre-4.7-gnu/drivers/hwtracing/stm/dummy_stm.c
--- linux-libre-4.6-gnu/drivers/hwtracing/stm/dummy_stm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hwtracing/stm/dummy_stm.c	2016-07-24 15:23:50.000000000 -0400
@@ -46,9 +46,7 @@ static struct stm_data dummy_stm[DUMMY_S
 
 static int nr_dummies = 4;
 
-module_param(nr_dummies, int, 0600);
-
-static unsigned int dummy_stm_nr;
+module_param(nr_dummies, int, 0400);
 
 static unsigned int fail_mode;
 
@@ -65,12 +63,12 @@ static int dummy_stm_link(struct stm_dat
 
 static int dummy_stm_init(void)
 {
-	int i, ret = -ENOMEM, __nr_dummies = ACCESS_ONCE(nr_dummies);
+	int i, ret = -ENOMEM;
 
-	if (__nr_dummies < 0 || __nr_dummies > DUMMY_STM_MAX)
+	if (nr_dummies < 0 || nr_dummies > DUMMY_STM_MAX)
 		return -EINVAL;
 
-	for (i = 0; i < __nr_dummies; i++) {
+	for (i = 0; i < nr_dummies; i++) {
 		dummy_stm[i].name = kasprintf(GFP_KERNEL, "dummy_stm.%d", i);
 		if (!dummy_stm[i].name)
 			goto fail_unregister;
@@ -86,8 +84,6 @@ static int dummy_stm_init(void)
 			goto fail_free;
 	}
 
-	dummy_stm_nr = __nr_dummies;
-
 	return 0;
 
 fail_unregister:
@@ -105,7 +101,7 @@ static void dummy_stm_exit(void)
 {
 	int i;
 
-	for (i = 0; i < dummy_stm_nr; i++) {
+	for (i = 0; i < nr_dummies; i++) {
 		stm_unregister_device(&dummy_stm[i]);
 		kfree(dummy_stm[i].name);
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwtracing/stm/heartbeat.c linux-libre-4.7-gnu/drivers/hwtracing/stm/heartbeat.c
--- linux-libre-4.6-gnu/drivers/hwtracing/stm/heartbeat.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hwtracing/stm/heartbeat.c	2016-07-24 15:23:50.000000000 -0400
@@ -26,7 +26,7 @@
 static int nr_devs = 4;
 static int interval_ms = 10;
 
-module_param(nr_devs, int, 0600);
+module_param(nr_devs, int, 0400);
 module_param(interval_ms, int, 0600);
 
 static struct stm_heartbeat {
@@ -35,8 +35,6 @@ static struct stm_heartbeat {
 	unsigned int		active;
 } stm_heartbeat[STM_HEARTBEAT_MAX];
 
-static unsigned int nr_instances;
-
 static const char str[] = "heartbeat stm source driver is here to serve you";
 
 static enum hrtimer_restart stm_heartbeat_hrtimer_handler(struct hrtimer *hr)
@@ -74,12 +72,12 @@ static void stm_heartbeat_unlink(struct
 
 static int stm_heartbeat_init(void)
 {
-	int i, ret = -ENOMEM, __nr_instances = ACCESS_ONCE(nr_devs);
+	int i, ret = -ENOMEM;
 
-	if (__nr_instances < 0 || __nr_instances > STM_HEARTBEAT_MAX)
+	if (nr_devs < 0 || nr_devs > STM_HEARTBEAT_MAX)
 		return -EINVAL;
 
-	for (i = 0; i < __nr_instances; i++) {
+	for (i = 0; i < nr_devs; i++) {
 		stm_heartbeat[i].data.name =
 			kasprintf(GFP_KERNEL, "heartbeat.%d", i);
 		if (!stm_heartbeat[i].data.name)
@@ -98,8 +96,6 @@ static int stm_heartbeat_init(void)
 			goto fail_free;
 	}
 
-	nr_instances = __nr_instances;
-
 	return 0;
 
 fail_unregister:
@@ -116,7 +112,7 @@ static void stm_heartbeat_exit(void)
 {
 	int i;
 
-	for (i = 0; i < nr_instances; i++) {
+	for (i = 0; i < nr_devs; i++) {
 		stm_source_unregister_device(&stm_heartbeat[i].data);
 		kfree(stm_heartbeat[i].data.name);
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/hwtracing/stm/policy.c linux-libre-4.7-gnu/drivers/hwtracing/stm/policy.c
--- linux-libre-4.6-gnu/drivers/hwtracing/stm/policy.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/hwtracing/stm/policy.c	2016-07-24 15:23:50.000000000 -0400
@@ -107,8 +107,7 @@ stp_policy_node_masters_store(struct con
 		goto unlock;
 
 	/* must be within [sw_start..sw_end], which is an inclusive range */
-	if (first > INT_MAX || last > INT_MAX || first > last ||
-	    first < stm->data->sw_start ||
+	if (first > last || first < stm->data->sw_start ||
 	    last > stm->data->sw_end) {
 		ret = -ERANGE;
 		goto unlock;
@@ -342,7 +341,7 @@ stp_policies_make(struct config_group *g
 		return ERR_PTR(-EINVAL);
 	}
 
-	*p++ = '\0';
+	*p = '\0';
 
 	stm = stm_find_device(devname);
 	kfree(devname);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/algos/i2c-algo-bit.c linux-libre-4.7-gnu/drivers/i2c/algos/i2c-algo-bit.c
--- linux-libre-4.6-gnu/drivers/i2c/algos/i2c-algo-bit.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/algos/i2c-algo-bit.c	2016-07-24 15:23:50.000000000 -0400
@@ -617,7 +617,7 @@ const struct i2c_algorithm i2c_bit_algo
 };
 EXPORT_SYMBOL(i2c_bit_algo);
 
-const struct i2c_adapter_quirks i2c_bit_quirk_no_clk_stretch = {
+static const struct i2c_adapter_quirks i2c_bit_quirk_no_clk_stretch = {
 	.flags = I2C_AQ_NO_CLK_STRETCH,
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/busses/i2c-at91.c linux-libre-4.7-gnu/drivers/i2c/busses/i2c-at91.c
--- linux-libre-4.6-gnu/drivers/i2c/busses/i2c-at91.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/busses/i2c-at91.c	2016-07-24 15:23:50.000000000 -0400
@@ -1013,7 +1013,7 @@ static int at91_twi_configure_dma(struct
 
 error:
 	if (ret != -EPROBE_DEFER)
-		dev_info(dev->dev, "can't use DMA, error %d\n", ret);
+		dev_info(dev->dev, "can't get DMA channel, continue without DMA support\n");
 	if (dma->chan_rx)
 		dma_release_channel(dma->chan_rx);
 	if (dma->chan_tx)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/busses/i2c-bcm-iproc.c linux-libre-4.7-gnu/drivers/i2c/busses/i2c-bcm-iproc.c
--- linux-libre-4.6-gnu/drivers/i2c/busses/i2c-bcm-iproc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/busses/i2c-bcm-iproc.c	2016-07-24 15:23:50.000000000 -0400
@@ -267,7 +267,7 @@ static int bcm_iproc_i2c_xfer_single_msg
 	iproc_i2c->msg = msg;
 
 	/* format and load slave address into the TX FIFO */
-	addr = msg->addr << 1 | (msg->flags & I2C_M_RD ? 1 : 0);
+	addr = i2c_8bit_addr_from_msg(msg);
 	writel(addr, iproc_i2c->base + M_TX_OFFSET);
 
 	/*
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/busses/i2c-bcm-kona.c linux-libre-4.7-gnu/drivers/i2c/busses/i2c-bcm-kona.c
--- linux-libre-4.6-gnu/drivers/i2c/busses/i2c-bcm-kona.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/busses/i2c-bcm-kona.c	2016-07-24 15:23:50.000000000 -0400
@@ -501,10 +501,7 @@ static int bcm_kona_i2c_do_addr(struct b
 				return -EREMOTEIO;
 		}
 	} else {
-		addr = msg->addr << 1;
-
-		if (msg->flags & I2C_M_RD)
-			addr |= 1;
+		addr = i2c_8bit_addr_from_msg(msg);
 
 		if (bcm_kona_i2c_write_byte(dev, addr, 0) < 0)
 			return -EREMOTEIO;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/busses/i2c-brcmstb.c linux-libre-4.7-gnu/drivers/i2c/busses/i2c-brcmstb.c
--- linux-libre-4.6-gnu/drivers/i2c/busses/i2c-brcmstb.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/busses/i2c-brcmstb.c	2016-07-24 15:23:50.000000000 -0400
@@ -446,9 +446,7 @@ static int brcmstb_i2c_do_addr(struct br
 
 		}
 	} else {
-		addr = msg->addr << 1;
-		if (msg->flags & I2C_M_RD)
-			addr |= 1;
+		addr = i2c_8bit_addr_from_msg(msg);
 
 		bsc_writel(dev, addr, chip_address);
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/busses/i2c-cpm.c linux-libre-4.7-gnu/drivers/i2c/busses/i2c-cpm.c
--- linux-libre-4.6-gnu/drivers/i2c/busses/i2c-cpm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/busses/i2c-cpm.c	2016-07-24 15:23:50.000000000 -0400
@@ -197,9 +197,7 @@ static void cpm_i2c_parse_message(struct
 	tbdf = cpm->tbase + tx;
 	rbdf = cpm->rbase + rx;
 
-	addr = pmsg->addr << 1;
-	if (pmsg->flags & I2C_M_RD)
-		addr |= 1;
+	addr = i2c_8bit_addr_from_msg(pmsg);
 
 	tb = cpm->txbuf[tx];
 	rb = cpm->rxbuf[rx];
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/busses/i2c-dln2.c linux-libre-4.7-gnu/drivers/i2c/busses/i2c-dln2.c
--- linux-libre-4.6-gnu/drivers/i2c/busses/i2c-dln2.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/busses/i2c-dln2.c	2016-07-24 15:23:50.000000000 -0400
@@ -19,6 +19,7 @@
 #include <linux/i2c.h>
 #include <linux/platform_device.h>
 #include <linux/mfd/dln2.h>
+#include <linux/acpi.h>
 
 #define DLN2_I2C_MODULE_ID		0x03
 #define DLN2_I2C_CMD(cmd)		DLN2_CMD(cmd, DLN2_I2C_MODULE_ID)
@@ -210,6 +211,7 @@ static int dln2_i2c_probe(struct platfor
 	dln2->adapter.algo = &dln2_i2c_usb_algorithm;
 	dln2->adapter.quirks = &dln2_i2c_quirks;
 	dln2->adapter.dev.parent = dev;
+	ACPI_COMPANION_SET(&dln2->adapter.dev, ACPI_COMPANION(&pdev->dev));
 	dln2->adapter.dev.of_node = dev->of_node;
 	i2c_set_adapdata(&dln2->adapter, dln2);
 	snprintf(dln2->adapter.name, sizeof(dln2->adapter.name), "%s-%s-%d",
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/busses/i2c-exynos5.c linux-libre-4.7-gnu/drivers/i2c/busses/i2c-exynos5.c
--- linux-libre-4.6-gnu/drivers/i2c/busses/i2c-exynos5.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/busses/i2c-exynos5.c	2016-07-24 15:23:50.000000000 -0400
@@ -861,14 +861,8 @@ static int exynos5_i2c_resume_noirq(stru
 #endif
 
 static const struct dev_pm_ops exynos5_i2c_dev_pm_ops = {
-#ifdef CONFIG_PM_SLEEP
-	.suspend_noirq = exynos5_i2c_suspend_noirq,
-	.resume_noirq = exynos5_i2c_resume_noirq,
-	.freeze_noirq = exynos5_i2c_suspend_noirq,
-	.thaw_noirq = exynos5_i2c_resume_noirq,
-	.poweroff_noirq = exynos5_i2c_suspend_noirq,
-	.restore_noirq = exynos5_i2c_resume_noirq,
-#endif
+	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(exynos5_i2c_suspend_noirq,
+				      exynos5_i2c_resume_noirq)
 };
 
 static struct platform_driver exynos5_i2c_driver = {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/busses/i2c-i801.c linux-libre-4.7-gnu/drivers/i2c/busses/i2c-i801.c
--- linux-libre-4.6-gnu/drivers/i2c/busses/i2c-i801.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/busses/i2c-i801.c	2016-07-24 15:23:50.000000000 -0400
@@ -94,6 +94,7 @@
 #include <linux/err.h>
 #include <linux/platform_device.h>
 #include <linux/platform_data/itco_wdt.h>
+#include <linux/pm_runtime.h>
 
 #if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \
 		defined CONFIG_DMI
@@ -244,6 +245,13 @@ struct i801_priv {
 	struct platform_device *mux_pdev;
 #endif
 	struct platform_device *tco_pdev;
+
+	/*
+	 * If set to true the host controller registers are reserved for
+	 * ACPI AML use. Protected by acpi_lock.
+	 */
+	bool acpi_reserved;
+	struct mutex acpi_lock;
 };
 
 #define FEATURE_SMBUS_PEC	(1 << 0)
@@ -714,9 +722,17 @@ static s32 i801_access(struct i2c_adapte
 {
 	int hwpec;
 	int block = 0;
-	int ret, xact = 0;
+	int ret = 0, xact = 0;
 	struct i801_priv *priv = i2c_get_adapdata(adap);
 
+	mutex_lock(&priv->acpi_lock);
+	if (priv->acpi_reserved) {
+		mutex_unlock(&priv->acpi_lock);
+		return -EBUSY;
+	}
+
+	pm_runtime_get_sync(&priv->pci_dev->dev);
+
 	hwpec = (priv->features & FEATURE_SMBUS_PEC) && (flags & I2C_CLIENT_PEC)
 		&& size != I2C_SMBUS_QUICK
 		&& size != I2C_SMBUS_I2C_BLOCK_DATA;
@@ -773,7 +789,8 @@ static s32 i801_access(struct i2c_adapte
 	default:
 		dev_err(&priv->pci_dev->dev, "Unsupported transaction %d\n",
 			size);
-		return -EOPNOTSUPP;
+		ret = -EOPNOTSUPP;
+		goto out;
 	}
 
 	if (hwpec)	/* enable/disable hardware PEC */
@@ -796,11 +813,11 @@ static s32 i801_access(struct i2c_adapte
 		       ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv));
 
 	if (block)
-		return ret;
+		goto out;
 	if (ret)
-		return ret;
+		goto out;
 	if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK))
-		return 0;
+		goto out;
 
 	switch (xact & 0x7f) {
 	case I801_BYTE:	/* Result put in SMBHSTDAT0 */
@@ -812,7 +829,12 @@ static s32 i801_access(struct i2c_adapte
 			     (inb_p(SMBHSTDAT1(priv)) << 8);
 		break;
 	}
-	return 0;
+
+out:
+	pm_runtime_mark_last_busy(&priv->pci_dev->dev);
+	pm_runtime_put_autosuspend(&priv->pci_dev->dev);
+	mutex_unlock(&priv->acpi_lock);
+	return ret;
 }
 
 
@@ -1249,6 +1271,83 @@ static void i801_add_tco(struct i801_pri
 	priv->tco_pdev = pdev;
 }
 
+#ifdef CONFIG_ACPI
+static acpi_status
+i801_acpi_io_handler(u32 function, acpi_physical_address address, u32 bits,
+		     u64 *value, void *handler_context, void *region_context)
+{
+	struct i801_priv *priv = handler_context;
+	struct pci_dev *pdev = priv->pci_dev;
+	acpi_status status;
+
+	/*
+	 * Once BIOS AML code touches the OpRegion we warn and inhibit any
+	 * further access from the driver itself. This device is now owned
+	 * by the system firmware.
+	 */
+	mutex_lock(&priv->acpi_lock);
+
+	if (!priv->acpi_reserved) {
+		priv->acpi_reserved = true;
+
+		dev_warn(&pdev->dev, "BIOS is accessing SMBus registers\n");
+		dev_warn(&pdev->dev, "Driver SMBus register access inhibited\n");
+
+		/*
+		 * BIOS is accessing the host controller so prevent it from
+		 * suspending automatically from now on.
+		 */
+		pm_runtime_get_sync(&pdev->dev);
+	}
+
+	if ((function & ACPI_IO_MASK) == ACPI_READ)
+		status = acpi_os_read_port(address, (u32 *)value, bits);
+	else
+		status = acpi_os_write_port(address, (u32)*value, bits);
+
+	mutex_unlock(&priv->acpi_lock);
+
+	return status;
+}
+
+static int i801_acpi_probe(struct i801_priv *priv)
+{
+	struct acpi_device *adev;
+	acpi_status status;
+
+	adev = ACPI_COMPANION(&priv->pci_dev->dev);
+	if (adev) {
+		status = acpi_install_address_space_handler(adev->handle,
+				ACPI_ADR_SPACE_SYSTEM_IO, i801_acpi_io_handler,
+				NULL, priv);
+		if (ACPI_SUCCESS(status))
+			return 0;
+	}
+
+	return acpi_check_resource_conflict(&priv->pci_dev->resource[SMBBAR]);
+}
+
+static void i801_acpi_remove(struct i801_priv *priv)
+{
+	struct acpi_device *adev;
+
+	adev = ACPI_COMPANION(&priv->pci_dev->dev);
+	if (!adev)
+		return;
+
+	acpi_remove_address_space_handler(adev->handle,
+		ACPI_ADR_SPACE_SYSTEM_IO, i801_acpi_io_handler);
+
+	mutex_lock(&priv->acpi_lock);
+	if (priv->acpi_reserved)
+		pm_runtime_put(&priv->pci_dev->dev);
+	mutex_unlock(&priv->acpi_lock);
+}
+#else
+static inline int i801_acpi_probe(struct i801_priv *priv) { return 0; }
+static inline void i801_acpi_remove(struct i801_priv *priv) { }
+#endif
+
 static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
 	unsigned char temp;
@@ -1266,6 +1365,7 @@ static int i801_probe(struct pci_dev *de
 	priv->adapter.dev.parent = &dev->dev;
 	ACPI_COMPANION_SET(&priv->adapter.dev, ACPI_COMPANION(&dev->dev));
 	priv->adapter.retries = 3;
+	mutex_init(&priv->acpi_lock);
 
 	priv->pci_dev = dev;
 	switch (dev->device) {
@@ -1328,10 +1428,8 @@ static int i801_probe(struct pci_dev *de
 		return -ENODEV;
 	}
 
-	err = acpi_check_resource_conflict(&dev->resource[SMBBAR]);
-	if (err) {
+	if (i801_acpi_probe(priv))
 		return -ENODEV;
-	}
 
 	err = pcim_iomap_regions(dev, 1 << SMBBAR,
 				 dev_driver_string(&dev->dev));
@@ -1340,6 +1438,7 @@ static int i801_probe(struct pci_dev *de
 			"Failed to request SMBus region 0x%lx-0x%Lx\n",
 			priv->smba,
 			(unsigned long long)pci_resource_end(dev, SMBBAR));
+		i801_acpi_remove(priv);
 		return err;
 	}
 
@@ -1404,6 +1503,7 @@ static int i801_probe(struct pci_dev *de
 	err = i2c_add_adapter(&priv->adapter);
 	if (err) {
 		dev_err(&dev->dev, "Failed to add SMBus adapter\n");
+		i801_acpi_remove(priv);
 		return err;
 	}
 
@@ -1413,6 +1513,11 @@ static int i801_probe(struct pci_dev *de
 
 	pci_set_drvdata(dev, priv);
 
+	pm_runtime_set_autosuspend_delay(&dev->dev, 1000);
+	pm_runtime_use_autosuspend(&dev->dev);
+	pm_runtime_put_autosuspend(&dev->dev);
+	pm_runtime_allow(&dev->dev);
+
 	return 0;
 }
 
@@ -1420,8 +1525,12 @@ static void i801_remove(struct pci_dev *
 {
 	struct i801_priv *priv = pci_get_drvdata(dev);
 
+	pm_runtime_forbid(&dev->dev);
+	pm_runtime_get_noresume(&dev->dev);
+
 	i801_del_mux(priv);
 	i2c_del_adapter(&priv->adapter);
+	i801_acpi_remove(priv);
 	pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg);
 
 	platform_device_unregister(priv->tco_pdev);
@@ -1433,34 +1542,32 @@ static void i801_remove(struct pci_dev *
 }
 
 #ifdef CONFIG_PM
-static int i801_suspend(struct pci_dev *dev, pm_message_t mesg)
+static int i801_suspend(struct device *dev)
 {
-	struct i801_priv *priv = pci_get_drvdata(dev);
+	struct pci_dev *pci_dev = to_pci_dev(dev);
+	struct i801_priv *priv = pci_get_drvdata(pci_dev);
 
-	pci_save_state(dev);
-	pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg);
-	pci_set_power_state(dev, pci_choose_state(dev, mesg));
+	pci_write_config_byte(pci_dev, SMBHSTCFG, priv->original_hstcfg);
 	return 0;
 }
 
-static int i801_resume(struct pci_dev *dev)
+static int i801_resume(struct device *dev)
 {
-	pci_set_power_state(dev, PCI_D0);
-	pci_restore_state(dev);
 	return 0;
 }
-#else
-#define i801_suspend NULL
-#define i801_resume NULL
 #endif
 
+static UNIVERSAL_DEV_PM_OPS(i801_pm_ops, i801_suspend,
+			    i801_resume, NULL);
+
 static struct pci_driver i801_driver = {
 	.name		= "i801_smbus",
 	.id_table	= i801_ids,
 	.probe		= i801_probe,
 	.remove		= i801_remove,
-	.suspend	= i801_suspend,
-	.resume		= i801_resume,
+	.driver		= {
+		.pm	= &i801_pm_ops,
+	},
 };
 
 static int __init i2c_i801_init(void)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/busses/i2c-ibm_iic.c linux-libre-4.7-gnu/drivers/i2c/busses/i2c-ibm_iic.c
--- linux-libre-4.6-gnu/drivers/i2c/busses/i2c-ibm_iic.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/busses/i2c-ibm_iic.c	2016-07-24 15:23:50.000000000 -0400
@@ -269,7 +269,7 @@ static int iic_smbus_quick(struct ibm_ii
 	ndelay(t->hd_sta);
 
 	/* Send address */
-	v = (u8)((p->addr << 1) | ((p->flags & I2C_M_RD) ? 1 : 0));
+	v = i2c_8bit_addr_from_msg(p);
 	for (i = 0, mask = 0x80; i < 8; ++i, mask >>= 1){
 		out_8(&iic->directcntl, sda);
 		ndelay(t->low / 2);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/busses/i2c-img-scb.c linux-libre-4.7-gnu/drivers/i2c/busses/i2c-img-scb.c
--- linux-libre-4.6-gnu/drivers/i2c/busses/i2c-img-scb.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/busses/i2c-img-scb.c	2016-07-24 15:23:50.000000000 -0400
@@ -751,9 +751,7 @@ static unsigned int img_i2c_atomic(struc
 	switch (i2c->at_cur_cmd) {
 	case CMD_GEN_START:
 		next_cmd = CMD_GEN_DATA;
-		next_data = (i2c->msg.addr << 1);
-		if (i2c->msg.flags & I2C_M_RD)
-			next_data |= 0x1;
+		next_data = i2c_8bit_addr_from_msg(&i2c->msg);
 		break;
 	case CMD_GEN_DATA:
 		if (i2c->line_status & LINESTAT_INPUT_HELD_V)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/busses/i2c-imx.c linux-libre-4.7-gnu/drivers/i2c/busses/i2c-imx.c
--- linux-libre-4.6-gnu/drivers/i2c/busses/i2c-imx.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/busses/i2c-imx.c	2016-07-24 15:23:50.000000000 -0400
@@ -525,7 +525,7 @@ static int i2c_imx_start(struct imx_i2c_
 	imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode, i2c_imx, IMX_I2C_I2CR);
 
 	/* Wait controller to be stable */
-	udelay(50);
+	usleep_range(50, 150);
 
 	/* Start I2C transaction */
 	temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/busses/i2c-iop3xx.c linux-libre-4.7-gnu/drivers/i2c/busses/i2c-iop3xx.c
--- linux-libre-4.6-gnu/drivers/i2c/busses/i2c-iop3xx.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/busses/i2c-iop3xx.c	2016-07-24 15:23:50.000000000 -0400
@@ -50,10 +50,7 @@ iic_cook_addr(struct i2c_msg *msg)
 {
 	unsigned char addr;
 
-	addr = (msg->addr << 1);
-
-	if (msg->flags & I2C_M_RD)
-		addr |= 1;
+	addr = i2c_8bit_addr_from_msg(msg);
 
 	return addr;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/busses/i2c-lpc2k.c linux-libre-4.7-gnu/drivers/i2c/busses/i2c-lpc2k.c
--- linux-libre-4.6-gnu/drivers/i2c/busses/i2c-lpc2k.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/busses/i2c-lpc2k.c	2016-07-24 15:23:50.000000000 -0400
@@ -133,9 +133,7 @@ static void i2c_lpc2k_pump_msg(struct lp
 	case M_START:
 	case M_REPSTART:
 		/* Start bit was just sent out, send out addr and dir */
-		data = i2c->msg->addr << 1;
-		if (i2c->msg->flags & I2C_M_RD)
-			data |= 1;
+		data = i2c_8bit_addr_from_msg(i2c->msg);
 
 		writel(data, i2c->base + LPC24XX_I2DAT);
 		writel(LPC24XX_STA, i2c->base + LPC24XX_I2CONCLR);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/busses/i2c-mt65xx.c linux-libre-4.7-gnu/drivers/i2c/busses/i2c-mt65xx.c
--- linux-libre-4.6-gnu/drivers/i2c/busses/i2c-mt65xx.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/busses/i2c-mt65xx.c	2016-07-24 15:23:50.000000000 -0400
@@ -413,10 +413,7 @@ static int mtk_i2c_do_transfer(struct mt
 	else
 		writew(I2C_FS_START_CON, i2c->base + OFFSET_EXT_CONF);
 
-	addr_reg = msgs->addr << 1;
-	if (i2c->op == I2C_MASTER_RD)
-		addr_reg |= 0x1;
-
+	addr_reg = i2c_8bit_addr_from_msg(msgs);
 	writew(addr_reg, i2c->base + OFFSET_SLAVE_ADDR);
 
 	/* Clear interrupt status */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/busses/i2c-mv64xxx.c linux-libre-4.7-gnu/drivers/i2c/busses/i2c-mv64xxx.c
--- linux-libre-4.6-gnu/drivers/i2c/busses/i2c-mv64xxx.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/busses/i2c-mv64xxx.c	2016-07-24 15:23:50.000000000 -0400
@@ -134,9 +134,7 @@ struct mv64xxx_i2c_data {
 	int			rc;
 	u32			freq_m;
 	u32			freq_n;
-#if defined(CONFIG_HAVE_CLK)
 	struct clk              *clk;
-#endif
 	wait_queue_head_t	waitq;
 	spinlock_t		lock;
 	struct i2c_msg		*msg;
@@ -757,7 +755,6 @@ static const struct of_device_id mv64xxx
 MODULE_DEVICE_TABLE(of, mv64xxx_i2c_of_match_table);
 
 #ifdef CONFIG_OF
-#ifdef CONFIG_HAVE_CLK
 static int
 mv64xxx_calc_freq(struct mv64xxx_i2c_data *drv_data,
 		  const int tclk, const int n, const int m)
@@ -791,25 +788,20 @@ mv64xxx_find_baud_factors(struct mv64xxx
 		return false;
 	return true;
 }
-#endif /* CONFIG_HAVE_CLK */
 
 static int
 mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
 		  struct device *dev)
 {
-	/* CLK is mandatory when using DT to describe the i2c bus. We
-	 * need to know tclk in order to calculate bus clock
-	 * factors.
-	 */
-#if !defined(CONFIG_HAVE_CLK)
-	/* Have OF but no CLK */
-	return -ENODEV;
-#else
 	const struct of_device_id *device;
 	struct device_node *np = dev->of_node;
 	u32 bus_freq, tclk;
 	int rc = 0;
 
+	/* CLK is mandatory when using DT to describe the i2c bus. We
+	 * need to know tclk in order to calculate bus clock
+	 * factors.
+	 */
 	if (IS_ERR(drv_data->clk)) {
 		rc = -ENODEV;
 		goto out;
@@ -869,7 +861,6 @@ mv64xxx_of_config(struct mv64xxx_i2c_dat
 
 out:
 	return rc;
-#endif
 }
 #else /* CONFIG_OF */
 static int
@@ -907,14 +898,13 @@ mv64xxx_i2c_probe(struct platform_device
 	init_waitqueue_head(&drv_data->waitq);
 	spin_lock_init(&drv_data->lock);
 
-#if defined(CONFIG_HAVE_CLK)
 	/* Not all platforms have a clk */
 	drv_data->clk = devm_clk_get(&pd->dev, NULL);
-	if (!IS_ERR(drv_data->clk)) {
-		clk_prepare(drv_data->clk);
-		clk_enable(drv_data->clk);
-	}
-#endif
+	if (IS_ERR(drv_data->clk) && PTR_ERR(drv_data->clk) == -EPROBE_DEFER)
+		return -EPROBE_DEFER;
+	if (!IS_ERR(drv_data->clk))
+		clk_prepare_enable(drv_data->clk);
+
 	if (pdata) {
 		drv_data->freq_m = pdata->freq_m;
 		drv_data->freq_n = pdata->freq_n;
@@ -964,13 +954,10 @@ exit_reset:
 	if (!IS_ERR_OR_NULL(drv_data->rstc))
 		reset_control_assert(drv_data->rstc);
 exit_clk:
-#if defined(CONFIG_HAVE_CLK)
 	/* Not all platforms have a clk */
-	if (!IS_ERR(drv_data->clk)) {
-		clk_disable(drv_data->clk);
-		clk_unprepare(drv_data->clk);
-	}
-#endif
+	if (!IS_ERR(drv_data->clk))
+		clk_disable_unprepare(drv_data->clk);
+
 	return rc;
 }
 
@@ -983,13 +970,9 @@ mv64xxx_i2c_remove(struct platform_devic
 	free_irq(drv_data->irq, drv_data);
 	if (!IS_ERR_OR_NULL(drv_data->rstc))
 		reset_control_assert(drv_data->rstc);
-#if defined(CONFIG_HAVE_CLK)
 	/* Not all platforms have a clk */
-	if (!IS_ERR(drv_data->clk)) {
-		clk_disable(drv_data->clk);
-		clk_unprepare(drv_data->clk);
-	}
-#endif
+	if (!IS_ERR(drv_data->clk))
+		clk_disable_unprepare(drv_data->clk);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/busses/i2c-nforce2.c linux-libre-4.7-gnu/drivers/i2c/busses/i2c-nforce2.c
--- linux-libre-4.6-gnu/drivers/i2c/busses/i2c-nforce2.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/busses/i2c-nforce2.c	2016-07-24 15:23:50.000000000 -0400
@@ -127,7 +127,7 @@ static struct pci_driver nforce2_driver;
 
 /* For multiplexing support, we need a global reference to the 1st
    SMBus channel */
-#if defined CONFIG_I2C_NFORCE2_S4985 || defined CONFIG_I2C_NFORCE2_S4985_MODULE
+#if IS_ENABLED(CONFIG_I2C_NFORCE2_S4985)
 struct i2c_adapter *nforce2_smbus;
 EXPORT_SYMBOL_GPL(nforce2_smbus);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/busses/i2c-ocores.c linux-libre-4.7-gnu/drivers/i2c/busses/i2c-ocores.c
--- linux-libre-4.6-gnu/drivers/i2c/busses/i2c-ocores.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/busses/i2c-ocores.c	2016-07-24 15:23:50.000000000 -0400
@@ -178,10 +178,7 @@ static void ocores_process(struct ocores
 		if (i2c->nmsgs) {	/* end? */
 			/* send start? */
 			if (!(msg->flags & I2C_M_NOSTART)) {
-				u8 addr = (msg->addr << 1);
-
-				if (msg->flags & I2C_M_RD)
-					addr |= 1;
+				u8 addr = i2c_8bit_addr_from_msg(msg);
 
 				i2c->state = STATE_START;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/busses/i2c-octeon.c linux-libre-4.7-gnu/drivers/i2c/busses/i2c-octeon.c
--- linux-libre-4.6-gnu/drivers/i2c/busses/i2c-octeon.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/busses/i2c-octeon.c	2016-07-24 15:23:50.000000000 -0400
@@ -11,6 +11,7 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include <linux/atomic.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
@@ -29,13 +30,23 @@
 /* Register offsets */
 #define SW_TWSI			0x00
 #define TWSI_INT		0x10
+#define SW_TWSI_EXT		0x18
 
 /* Controller command patterns */
 #define SW_TWSI_V		BIT_ULL(63)	/* Valid bit */
+#define SW_TWSI_EIA		BIT_ULL(61)	/* Extended internal address */
 #define SW_TWSI_R		BIT_ULL(56)	/* Result or read bit */
+#define SW_TWSI_SOVR		BIT_ULL(55)	/* Size override */
+#define SW_TWSI_SIZE_SHIFT	52
+#define SW_TWSI_ADDR_SHIFT	40
+#define SW_TWSI_IA_SHIFT	32		/* Internal address */
 
 /* Controller opcode word (bits 60:57) */
 #define SW_TWSI_OP_SHIFT	57
+#define SW_TWSI_OP_7		(0ULL << SW_TWSI_OP_SHIFT)
+#define SW_TWSI_OP_7_IA		(1ULL << SW_TWSI_OP_SHIFT)
+#define SW_TWSI_OP_10		(2ULL << SW_TWSI_OP_SHIFT)
+#define SW_TWSI_OP_10_IA	(3ULL << SW_TWSI_OP_SHIFT)
 #define SW_TWSI_OP_TWSI_CLK	(4ULL << SW_TWSI_OP_SHIFT)
 #define SW_TWSI_OP_EOP		(6ULL << SW_TWSI_OP_SHIFT) /* Extended opcode */
 
@@ -48,46 +59,93 @@
 #define SW_TWSI_EOP_TWSI_RST	(SW_TWSI_OP_EOP | 7ULL << SW_TWSI_EOP_SHIFT)
 
 /* Controller command and status bits */
-#define TWSI_CTL_CE		0x80
+#define TWSI_CTL_CE		0x80	/* High level controller enable */
 #define TWSI_CTL_ENAB		0x40	/* Bus enable */
 #define TWSI_CTL_STA		0x20	/* Master-mode start, HW clears when done */
 #define TWSI_CTL_STP		0x10	/* Master-mode stop, HW clears when done */
 #define TWSI_CTL_IFLG		0x08	/* HW event, SW writes 0 to ACK */
 #define TWSI_CTL_AAK		0x04	/* Assert ACK */
 
-/* Some status values */
+/* Status values */
+#define STAT_ERROR		0x00
 #define STAT_START		0x08
-#define STAT_RSTART		0x10
+#define STAT_REP_START		0x10
 #define STAT_TXADDR_ACK		0x18
+#define STAT_TXADDR_NAK		0x20
 #define STAT_TXDATA_ACK		0x28
+#define STAT_TXDATA_NAK		0x30
+#define STAT_LOST_ARB_38	0x38
 #define STAT_RXADDR_ACK		0x40
+#define STAT_RXADDR_NAK		0x48
 #define STAT_RXDATA_ACK		0x50
+#define STAT_RXDATA_NAK		0x58
+#define STAT_SLAVE_60		0x60
+#define STAT_LOST_ARB_68	0x68
+#define STAT_SLAVE_70		0x70
+#define STAT_LOST_ARB_78	0x78
+#define STAT_SLAVE_80		0x80
+#define STAT_SLAVE_88		0x88
+#define STAT_GENDATA_ACK	0x90
+#define STAT_GENDATA_NAK	0x98
+#define STAT_SLAVE_A0		0xA0
+#define STAT_SLAVE_A8		0xA8
+#define STAT_LOST_ARB_B0	0xB0
+#define STAT_SLAVE_LOST		0xB8
+#define STAT_SLAVE_NAK		0xC0
+#define STAT_SLAVE_ACK		0xC8
+#define STAT_AD2W_ACK		0xD0
+#define STAT_AD2W_NAK		0xD8
 #define STAT_IDLE		0xF8
 
 /* TWSI_INT values */
+#define TWSI_INT_ST_INT		BIT_ULL(0)
+#define TWSI_INT_TS_INT		BIT_ULL(1)
+#define TWSI_INT_CORE_INT	BIT_ULL(2)
+#define TWSI_INT_ST_EN		BIT_ULL(4)
+#define TWSI_INT_TS_EN		BIT_ULL(5)
 #define TWSI_INT_CORE_EN	BIT_ULL(6)
 #define TWSI_INT_SDA_OVR	BIT_ULL(8)
 #define TWSI_INT_SCL_OVR	BIT_ULL(9)
+#define TWSI_INT_SDA		BIT_ULL(10)
+#define TWSI_INT_SCL		BIT_ULL(11)
+
+#define I2C_OCTEON_EVENT_WAIT 80 /* microseconds */
 
 struct octeon_i2c {
 	wait_queue_head_t queue;
 	struct i2c_adapter adap;
 	int irq;
+	int hlc_irq;		/* For cn7890 only */
 	u32 twsi_freq;
 	int sys_freq;
 	void __iomem *twsi_base;
 	struct device *dev;
+	bool hlc_enabled;
+	bool broken_irq_mode;
+	bool broken_irq_check;
+	void (*int_enable)(struct octeon_i2c *);
+	void (*int_disable)(struct octeon_i2c *);
+	void (*hlc_int_enable)(struct octeon_i2c *);
+	void (*hlc_int_disable)(struct octeon_i2c *);
+	atomic_t int_enable_cnt;
+	atomic_t hlc_int_enable_cnt;
 };
 
+static void octeon_i2c_writeq_flush(u64 val, void __iomem *addr)
+{
+	__raw_writeq(val, addr);
+	__raw_readq(addr);	/* wait for write to land */
+}
+
 /**
- * octeon_i2c_write_sw - write an I2C core register
+ * octeon_i2c_reg_write - write an I2C core register
  * @i2c: The struct octeon_i2c
  * @eop_reg: Register selector
  * @data: Value to be written
  *
  * The I2C core registers are accessed indirectly via the SW_TWSI CSR.
  */
-static void octeon_i2c_write_sw(struct octeon_i2c *i2c, u64 eop_reg, u8 data)
+static void octeon_i2c_reg_write(struct octeon_i2c *i2c, u64 eop_reg, u8 data)
 {
 	u64 tmp;
 
@@ -97,8 +155,13 @@ static void octeon_i2c_write_sw(struct o
 	} while ((tmp & SW_TWSI_V) != 0);
 }
 
+#define octeon_i2c_ctl_write(i2c, val)					\
+	octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_CTL, val)
+#define octeon_i2c_data_write(i2c, val)					\
+	octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_DATA, val)
+
 /**
- * octeon_i2c_read_sw - read lower bits of an I2C core register
+ * octeon_i2c_reg_read - read lower bits of an I2C core register
  * @i2c: The struct octeon_i2c
  * @eop_reg: Register selector
  *
@@ -106,7 +169,7 @@ static void octeon_i2c_write_sw(struct o
  *
  * The I2C core registers are accessed indirectly via the SW_TWSI CSR.
  */
-static u8 octeon_i2c_read_sw(struct octeon_i2c *i2c, u64 eop_reg)
+static u8 octeon_i2c_reg_read(struct octeon_i2c *i2c, u64 eop_reg)
 {
 	u64 tmp;
 
@@ -118,6 +181,24 @@ static u8 octeon_i2c_read_sw(struct octe
 	return tmp & 0xFF;
 }
 
+#define octeon_i2c_ctl_read(i2c)					\
+	octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_CTL)
+#define octeon_i2c_data_read(i2c)					\
+	octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_DATA)
+#define octeon_i2c_stat_read(i2c)					\
+	octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_STAT)
+
+/**
+ * octeon_i2c_read_int - read the TWSI_INT register
+ * @i2c: The struct octeon_i2c
+ *
+ * Returns the value of the register.
+ */
+static u64 octeon_i2c_read_int(struct octeon_i2c *i2c)
+{
+	return __raw_readq(i2c->twsi_base + TWSI_INT);
+}
+
 /**
  * octeon_i2c_write_int - write the TWSI_INT register
  * @i2c: The struct octeon_i2c
@@ -125,8 +206,7 @@ static u8 octeon_i2c_read_sw(struct octe
  */
 static void octeon_i2c_write_int(struct octeon_i2c *i2c, u64 data)
 {
-	__raw_writeq(data, i2c->twsi_base + TWSI_INT);
-	__raw_readq(i2c->twsi_base + TWSI_INT);
+	octeon_i2c_writeq_flush(data, i2c->twsi_base + TWSI_INT);
 }
 
 /**
@@ -149,30 +229,96 @@ static void octeon_i2c_int_disable(struc
 }
 
 /**
- * octeon_i2c_unblock - unblock the bus
+ * octeon_i2c_int_enable78 - enable the CORE interrupt
  * @i2c: The struct octeon_i2c
  *
- * If there was a reset while a device was driving 0 to bus, bus is blocked.
- * We toggle it free manually by some clock cycles and send a stop.
+ * The interrupt will be asserted when there is non-STAT_IDLE state in the
+ * SW_TWSI_EOP_TWSI_STAT register.
  */
-static void octeon_i2c_unblock(struct octeon_i2c *i2c)
+static void octeon_i2c_int_enable78(struct octeon_i2c *i2c)
 {
-	int i;
+	atomic_inc_return(&i2c->int_enable_cnt);
+	enable_irq(i2c->irq);
+}
 
-	dev_dbg(i2c->dev, "%s\n", __func__);
+static void __octeon_i2c_irq_disable(atomic_t *cnt, int irq)
+{
+	int count;
 
-	for (i = 0; i < 9; i++) {
-		octeon_i2c_write_int(i2c, 0);
-		udelay(5);
-		octeon_i2c_write_int(i2c, TWSI_INT_SCL_OVR);
-		udelay(5);
+	/*
+	 * The interrupt can be disabled in two places, but we only
+	 * want to make the disable_irq_nosync() call once, so keep
+	 * track with the atomic variable.
+	 */
+	count = atomic_dec_if_positive(cnt);
+	if (count >= 0)
+		disable_irq_nosync(irq);
+}
+
+/* disable the CORE interrupt */
+static void octeon_i2c_int_disable78(struct octeon_i2c *i2c)
+{
+	__octeon_i2c_irq_disable(&i2c->int_enable_cnt, i2c->irq);
+}
+
+/**
+ * octeon_i2c_hlc_int_enable78 - enable the ST interrupt
+ * @i2c: The struct octeon_i2c
+ *
+ * The interrupt will be asserted when there is non-STAT_IDLE state in
+ * the SW_TWSI_EOP_TWSI_STAT register.
+ */
+static void octeon_i2c_hlc_int_enable78(struct octeon_i2c *i2c)
+{
+	atomic_inc_return(&i2c->hlc_int_enable_cnt);
+	enable_irq(i2c->hlc_irq);
+}
+
+/* disable the ST interrupt */
+static void octeon_i2c_hlc_int_disable78(struct octeon_i2c *i2c)
+{
+	__octeon_i2c_irq_disable(&i2c->hlc_int_enable_cnt, i2c->hlc_irq);
+}
+
+/*
+ * Cleanup low-level state & enable high-level controller.
+ */
+static void octeon_i2c_hlc_enable(struct octeon_i2c *i2c)
+{
+	int try = 0;
+	u64 val;
+
+	if (i2c->hlc_enabled)
+		return;
+	i2c->hlc_enabled = true;
+
+	while (1) {
+		val = octeon_i2c_ctl_read(i2c);
+		if (!(val & (TWSI_CTL_STA | TWSI_CTL_STP)))
+			break;
+
+		/* clear IFLG event */
+		if (val & TWSI_CTL_IFLG)
+			octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB);
+
+		if (try++ > 100) {
+			pr_err("%s: giving up\n", __func__);
+			break;
+		}
+
+		/* spin until any start/stop has finished */
+		udelay(10);
 	}
-	/* hand-crank a STOP */
-	octeon_i2c_write_int(i2c, TWSI_INT_SDA_OVR | TWSI_INT_SCL_OVR);
-	udelay(5);
-	octeon_i2c_write_int(i2c, TWSI_INT_SDA_OVR);
-	udelay(5);
-	octeon_i2c_write_int(i2c, 0);
+	octeon_i2c_ctl_write(i2c, TWSI_CTL_CE | TWSI_CTL_AAK | TWSI_CTL_ENAB);
+}
+
+static void octeon_i2c_hlc_disable(struct octeon_i2c *i2c)
+{
+	if (!i2c->hlc_enabled)
+		return;
+
+	i2c->hlc_enabled = false;
+	octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB);
 }
 
 /* interrupt service routine */
@@ -180,16 +326,44 @@ static irqreturn_t octeon_i2c_isr(int ir
 {
 	struct octeon_i2c *i2c = dev_id;
 
-	octeon_i2c_int_disable(i2c);
+	i2c->int_disable(i2c);
 	wake_up(&i2c->queue);
 
 	return IRQ_HANDLED;
 }
 
+/* HLC interrupt service routine */
+static irqreturn_t octeon_i2c_hlc_isr78(int irq, void *dev_id)
+{
+	struct octeon_i2c *i2c = dev_id;
 
-static int octeon_i2c_test_iflg(struct octeon_i2c *i2c)
+	i2c->hlc_int_disable(i2c);
+	wake_up(&i2c->queue);
+
+	return IRQ_HANDLED;
+}
+
+static bool octeon_i2c_test_iflg(struct octeon_i2c *i2c)
 {
-	return (octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_CTL) & TWSI_CTL_IFLG) != 0;
+	return (octeon_i2c_ctl_read(i2c) & TWSI_CTL_IFLG);
+}
+
+static bool octeon_i2c_test_ready(struct octeon_i2c *i2c, bool *first)
+{
+	if (octeon_i2c_test_iflg(i2c))
+		return true;
+
+	if (*first) {
+		*first = false;
+		return false;
+	}
+
+	/*
+	 * IRQ has signaled an event but IFLG hasn't changed.
+	 * Sleep and retry once.
+	 */
+	usleep_range(I2C_OCTEON_EVENT_WAIT, 2 * I2C_OCTEON_EVENT_WAIT);
+	return octeon_i2c_test_iflg(i2c);
 }
 
 /**
@@ -201,64 +375,493 @@ static int octeon_i2c_test_iflg(struct o
 static int octeon_i2c_wait(struct octeon_i2c *i2c)
 {
 	long time_left;
+	bool first = 1;
 
-	octeon_i2c_int_enable(i2c);
-	time_left = wait_event_timeout(i2c->queue, octeon_i2c_test_iflg(i2c),
+	/*
+	 * Some chip revisions don't assert the irq in the interrupt
+	 * controller. So we must poll for the IFLG change.
+	 */
+	if (i2c->broken_irq_mode) {
+		u64 end = get_jiffies_64() + i2c->adap.timeout;
+
+		while (!octeon_i2c_test_iflg(i2c) &&
+		       time_before64(get_jiffies_64(), end))
+			usleep_range(I2C_OCTEON_EVENT_WAIT / 2, I2C_OCTEON_EVENT_WAIT);
+
+		return octeon_i2c_test_iflg(i2c) ? 0 : -ETIMEDOUT;
+	}
+
+	i2c->int_enable(i2c);
+	time_left = wait_event_timeout(i2c->queue, octeon_i2c_test_ready(i2c, &first),
 				       i2c->adap.timeout);
-	octeon_i2c_int_disable(i2c);
-	if (!time_left) {
-		dev_dbg(i2c->dev, "%s: timeout\n", __func__);
-		return -ETIMEDOUT;
+	i2c->int_disable(i2c);
+
+	if (i2c->broken_irq_check && !time_left &&
+	    octeon_i2c_test_iflg(i2c)) {
+		dev_err(i2c->dev, "broken irq connection detected, switching to polling mode.\n");
+		i2c->broken_irq_mode = true;
+		return 0;
 	}
 
+	if (!time_left)
+		return -ETIMEDOUT;
+
 	return 0;
 }
 
+static int octeon_i2c_check_status(struct octeon_i2c *i2c, int final_read)
+{
+	u8 stat = octeon_i2c_stat_read(i2c);
+
+	switch (stat) {
+	/* Everything is fine */
+	case STAT_IDLE:
+	case STAT_AD2W_ACK:
+	case STAT_RXADDR_ACK:
+	case STAT_TXADDR_ACK:
+	case STAT_TXDATA_ACK:
+		return 0;
+
+	/* ACK allowed on pre-terminal bytes only */
+	case STAT_RXDATA_ACK:
+		if (!final_read)
+			return 0;
+		return -EIO;
+
+	/* NAK allowed on terminal byte only */
+	case STAT_RXDATA_NAK:
+		if (final_read)
+			return 0;
+		return -EIO;
+
+	/* Arbitration lost */
+	case STAT_LOST_ARB_38:
+	case STAT_LOST_ARB_68:
+	case STAT_LOST_ARB_78:
+	case STAT_LOST_ARB_B0:
+		return -EAGAIN;
+
+	/* Being addressed as slave, should back off & listen */
+	case STAT_SLAVE_60:
+	case STAT_SLAVE_70:
+	case STAT_GENDATA_ACK:
+	case STAT_GENDATA_NAK:
+		return -EOPNOTSUPP;
+
+	/* Core busy as slave */
+	case STAT_SLAVE_80:
+	case STAT_SLAVE_88:
+	case STAT_SLAVE_A0:
+	case STAT_SLAVE_A8:
+	case STAT_SLAVE_LOST:
+	case STAT_SLAVE_NAK:
+	case STAT_SLAVE_ACK:
+		return -EOPNOTSUPP;
+
+	case STAT_TXDATA_NAK:
+		return -EIO;
+	case STAT_TXADDR_NAK:
+	case STAT_RXADDR_NAK:
+	case STAT_AD2W_NAK:
+		return -ENXIO;
+	default:
+		dev_err(i2c->dev, "unhandled state: %d\n", stat);
+		return -EIO;
+	}
+}
+
+static bool octeon_i2c_hlc_test_valid(struct octeon_i2c *i2c)
+{
+	return (__raw_readq(i2c->twsi_base + SW_TWSI) & SW_TWSI_V) == 0;
+}
+
+static bool octeon_i2c_hlc_test_ready(struct octeon_i2c *i2c, bool *first)
+{
+	/* check if valid bit is cleared */
+	if (octeon_i2c_hlc_test_valid(i2c))
+		return true;
+
+	if (*first) {
+		*first = false;
+		return false;
+	}
+
+	/*
+	 * IRQ has signaled an event but valid bit isn't cleared.
+	 * Sleep and retry once.
+	 */
+	usleep_range(I2C_OCTEON_EVENT_WAIT, 2 * I2C_OCTEON_EVENT_WAIT);
+	return octeon_i2c_hlc_test_valid(i2c);
+}
+
+static void octeon_i2c_hlc_int_enable(struct octeon_i2c *i2c)
+{
+	octeon_i2c_write_int(i2c, TWSI_INT_ST_EN);
+}
+
+static void octeon_i2c_hlc_int_clear(struct octeon_i2c *i2c)
+{
+	/* clear ST/TS events, listen for neither */
+	octeon_i2c_write_int(i2c, TWSI_INT_ST_INT | TWSI_INT_TS_INT);
+}
+
 /**
- * octeon_i2c_start - send START to the bus
+ * octeon_i2c_hlc_wait - wait for an HLC operation to complete
  * @i2c: The struct octeon_i2c
  *
- * Returns 0 on success, otherwise a negative errno.
+ * Returns 0 on success, otherwise -ETIMEDOUT.
  */
-static int octeon_i2c_start(struct octeon_i2c *i2c)
+static int octeon_i2c_hlc_wait(struct octeon_i2c *i2c)
 {
-	int result;
-	u8 data;
+	bool first = 1;
+	int time_left;
 
-	octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL,
-			    TWSI_CTL_ENAB | TWSI_CTL_STA);
+	/*
+	 * Some cn38xx boards don't assert the irq in the interrupt
+	 * controller. So we must poll for the valid bit change.
+	 */
+	if (i2c->broken_irq_mode) {
+		u64 end = get_jiffies_64() + i2c->adap.timeout;
 
-	result = octeon_i2c_wait(i2c);
-	if (result) {
-		if (octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_STAT) == STAT_IDLE) {
+		while (!octeon_i2c_hlc_test_valid(i2c) &&
+		       time_before64(get_jiffies_64(), end))
+			usleep_range(I2C_OCTEON_EVENT_WAIT / 2, I2C_OCTEON_EVENT_WAIT);
+
+		return octeon_i2c_hlc_test_valid(i2c) ? 0 : -ETIMEDOUT;
+	}
+
+	i2c->hlc_int_enable(i2c);
+	time_left = wait_event_timeout(i2c->queue,
+				       octeon_i2c_hlc_test_ready(i2c, &first),
+				       i2c->adap.timeout);
+	i2c->hlc_int_disable(i2c);
+	if (!time_left)
+		octeon_i2c_hlc_int_clear(i2c);
+
+	if (i2c->broken_irq_check && !time_left &&
+	    octeon_i2c_hlc_test_valid(i2c)) {
+		dev_err(i2c->dev, "broken irq connection detected, switching to polling mode.\n");
+		i2c->broken_irq_mode = true;
+		return 0;
+	}
+
+	if (!time_left)
+		return -ETIMEDOUT;
+	return 0;
+}
+
+/* high-level-controller pure read of up to 8 bytes */
+static int octeon_i2c_hlc_read(struct octeon_i2c *i2c, struct i2c_msg *msgs)
+{
+	int i, j, ret = 0;
+	u64 cmd;
+
+	octeon_i2c_hlc_enable(i2c);
+	octeon_i2c_hlc_int_clear(i2c);
+
+	cmd = SW_TWSI_V | SW_TWSI_R | SW_TWSI_SOVR;
+	/* SIZE */
+	cmd |= (u64)(msgs[0].len - 1) << SW_TWSI_SIZE_SHIFT;
+	/* A */
+	cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_ADDR_SHIFT;
+
+	if (msgs[0].flags & I2C_M_TEN)
+		cmd |= SW_TWSI_OP_10;
+	else
+		cmd |= SW_TWSI_OP_7;
+
+	octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI);
+	ret = octeon_i2c_hlc_wait(i2c);
+	if (ret)
+		goto err;
+
+	cmd = __raw_readq(i2c->twsi_base + SW_TWSI);
+	if ((cmd & SW_TWSI_R) == 0)
+		return -EAGAIN;
+
+	for (i = 0, j = msgs[0].len - 1; i  < msgs[0].len && i < 4; i++, j--)
+		msgs[0].buf[j] = (cmd >> (8 * i)) & 0xff;
+
+	if (msgs[0].len > 4) {
+		cmd = __raw_readq(i2c->twsi_base + SW_TWSI_EXT);
+		for (i = 0; i  < msgs[0].len - 4 && i < 4; i++, j--)
+			msgs[0].buf[j] = (cmd >> (8 * i)) & 0xff;
+	}
+
+err:
+	return ret;
+}
+
+/* high-level-controller pure write of up to 8 bytes */
+static int octeon_i2c_hlc_write(struct octeon_i2c *i2c, struct i2c_msg *msgs)
+{
+	int i, j, ret = 0;
+	u64 cmd;
+
+	octeon_i2c_hlc_enable(i2c);
+	octeon_i2c_hlc_int_clear(i2c);
+
+	cmd = SW_TWSI_V | SW_TWSI_SOVR;
+	/* SIZE */
+	cmd |= (u64)(msgs[0].len - 1) << SW_TWSI_SIZE_SHIFT;
+	/* A */
+	cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_ADDR_SHIFT;
+
+	if (msgs[0].flags & I2C_M_TEN)
+		cmd |= SW_TWSI_OP_10;
+	else
+		cmd |= SW_TWSI_OP_7;
+
+	for (i = 0, j = msgs[0].len - 1; i  < msgs[0].len && i < 4; i++, j--)
+		cmd |= (u64)msgs[0].buf[j] << (8 * i);
+
+	if (msgs[0].len > 4) {
+		u64 ext = 0;
+
+		for (i = 0; i < msgs[0].len - 4 && i < 4; i++, j--)
+			ext |= (u64)msgs[0].buf[j] << (8 * i);
+		octeon_i2c_writeq_flush(ext, i2c->twsi_base + SW_TWSI_EXT);
+	}
+
+	octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI);
+	ret = octeon_i2c_hlc_wait(i2c);
+	if (ret)
+		goto err;
+
+	cmd = __raw_readq(i2c->twsi_base + SW_TWSI);
+	if ((cmd & SW_TWSI_R) == 0)
+		return -EAGAIN;
+
+	ret = octeon_i2c_check_status(i2c, false);
+
+err:
+	return ret;
+}
+
+/* high-level-controller composite write+read, msg0=addr, msg1=data */
+static int octeon_i2c_hlc_comp_read(struct octeon_i2c *i2c, struct i2c_msg *msgs)
+{
+	int i, j, ret = 0;
+	u64 cmd;
+
+	octeon_i2c_hlc_enable(i2c);
+
+	cmd = SW_TWSI_V | SW_TWSI_R | SW_TWSI_SOVR;
+	/* SIZE */
+	cmd |= (u64)(msgs[1].len - 1) << SW_TWSI_SIZE_SHIFT;
+	/* A */
+	cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_ADDR_SHIFT;
+
+	if (msgs[0].flags & I2C_M_TEN)
+		cmd |= SW_TWSI_OP_10_IA;
+	else
+		cmd |= SW_TWSI_OP_7_IA;
+
+	if (msgs[0].len == 2) {
+		u64 ext = 0;
+
+		cmd |= SW_TWSI_EIA;
+		ext = (u64)msgs[0].buf[0] << SW_TWSI_IA_SHIFT;
+		cmd |= (u64)msgs[0].buf[1] << SW_TWSI_IA_SHIFT;
+		octeon_i2c_writeq_flush(ext, i2c->twsi_base + SW_TWSI_EXT);
+	} else {
+		cmd |= (u64)msgs[0].buf[0] << SW_TWSI_IA_SHIFT;
+	}
+
+	octeon_i2c_hlc_int_clear(i2c);
+	octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI);
+
+	ret = octeon_i2c_hlc_wait(i2c);
+	if (ret)
+		goto err;
+
+	cmd = __raw_readq(i2c->twsi_base + SW_TWSI);
+	if ((cmd & SW_TWSI_R) == 0)
+		return -EAGAIN;
+
+	for (i = 0, j = msgs[1].len - 1; i  < msgs[1].len && i < 4; i++, j--)
+		msgs[1].buf[j] = (cmd >> (8 * i)) & 0xff;
+
+	if (msgs[1].len > 4) {
+		cmd = __raw_readq(i2c->twsi_base + SW_TWSI_EXT);
+		for (i = 0; i  < msgs[1].len - 4 && i < 4; i++, j--)
+			msgs[1].buf[j] = (cmd >> (8 * i)) & 0xff;
+	}
+
+err:
+	return ret;
+}
+
+/* high-level-controller composite write+write, m[0]len<=2, m[1]len<=8 */
+static int octeon_i2c_hlc_comp_write(struct octeon_i2c *i2c, struct i2c_msg *msgs)
+{
+	bool set_ext = false;
+	int i, j, ret = 0;
+	u64 cmd, ext = 0;
+
+	octeon_i2c_hlc_enable(i2c);
+
+	cmd = SW_TWSI_V | SW_TWSI_SOVR;
+	/* SIZE */
+	cmd |= (u64)(msgs[1].len - 1) << SW_TWSI_SIZE_SHIFT;
+	/* A */
+	cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_ADDR_SHIFT;
+
+	if (msgs[0].flags & I2C_M_TEN)
+		cmd |= SW_TWSI_OP_10_IA;
+	else
+		cmd |= SW_TWSI_OP_7_IA;
+
+	if (msgs[0].len == 2) {
+		cmd |= SW_TWSI_EIA;
+		ext |= (u64)msgs[0].buf[0] << SW_TWSI_IA_SHIFT;
+		set_ext = true;
+		cmd |= (u64)msgs[0].buf[1] << SW_TWSI_IA_SHIFT;
+	} else {
+		cmd |= (u64)msgs[0].buf[0] << SW_TWSI_IA_SHIFT;
+	}
+
+	for (i = 0, j = msgs[1].len - 1; i  < msgs[1].len && i < 4; i++, j--)
+		cmd |= (u64)msgs[1].buf[j] << (8 * i);
+
+	if (msgs[1].len > 4) {
+		for (i = 0; i < msgs[1].len - 4 && i < 4; i++, j--)
+			ext |= (u64)msgs[1].buf[j] << (8 * i);
+		set_ext = true;
+	}
+	if (set_ext)
+		octeon_i2c_writeq_flush(ext, i2c->twsi_base + SW_TWSI_EXT);
+
+	octeon_i2c_hlc_int_clear(i2c);
+	octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI);
+
+	ret = octeon_i2c_hlc_wait(i2c);
+	if (ret)
+		goto err;
+
+	cmd = __raw_readq(i2c->twsi_base + SW_TWSI);
+	if ((cmd & SW_TWSI_R) == 0)
+		return -EAGAIN;
+
+	ret = octeon_i2c_check_status(i2c, false);
+
+err:
+	return ret;
+}
+
+/* calculate and set clock divisors */
+static void octeon_i2c_set_clock(struct octeon_i2c *i2c)
+{
+	int tclk, thp_base, inc, thp_idx, mdiv_idx, ndiv_idx, foscl, diff;
+	int thp = 0x18, mdiv = 2, ndiv = 0, delta_hz = 1000000;
+
+	for (ndiv_idx = 0; ndiv_idx < 8 && delta_hz != 0; ndiv_idx++) {
+		/*
+		 * An mdiv value of less than 2 seems to not work well
+		 * with ds1337 RTCs, so we constrain it to larger values.
+		 */
+		for (mdiv_idx = 15; mdiv_idx >= 2 && delta_hz != 0; mdiv_idx--) {
 			/*
-			 * Controller refused to send start flag May
-			 * be a client is holding SDA low - let's try
-			 * to free it.
+			 * For given ndiv and mdiv values check the
+			 * two closest thp values.
 			 */
-			octeon_i2c_unblock(i2c);
-			octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL,
-					    TWSI_CTL_ENAB | TWSI_CTL_STA);
-			result = octeon_i2c_wait(i2c);
+			tclk = i2c->twsi_freq * (mdiv_idx + 1) * 10;
+			tclk *= (1 << ndiv_idx);
+			thp_base = (i2c->sys_freq / (tclk * 2)) - 1;
+
+			for (inc = 0; inc <= 1; inc++) {
+				thp_idx = thp_base + inc;
+				if (thp_idx < 5 || thp_idx > 0xff)
+					continue;
+
+				foscl = i2c->sys_freq / (2 * (thp_idx + 1));
+				foscl = foscl / (1 << ndiv_idx);
+				foscl = foscl / (mdiv_idx + 1) / 10;
+				diff = abs(foscl - i2c->twsi_freq);
+				if (diff < delta_hz) {
+					delta_hz = diff;
+					thp = thp_idx;
+					mdiv = mdiv_idx;
+					ndiv = ndiv_idx;
+				}
+			}
 		}
-		if (result)
-			return result;
 	}
+	octeon_i2c_reg_write(i2c, SW_TWSI_OP_TWSI_CLK, thp);
+	octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_CLKCTL, (mdiv << 3) | ndiv);
+}
 
-	data = octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_STAT);
-	if ((data != STAT_START) && (data != STAT_RSTART)) {
-		dev_err(i2c->dev, "%s: bad status (0x%x)\n", __func__, data);
+static int octeon_i2c_init_lowlevel(struct octeon_i2c *i2c)
+{
+	u8 status = 0;
+	int tries;
+
+	/* reset controller */
+	octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_RST, 0);
+
+	for (tries = 10; tries && status != STAT_IDLE; tries--) {
+		udelay(1);
+		status = octeon_i2c_stat_read(i2c);
+		if (status == STAT_IDLE)
+			break;
+	}
+
+	if (status != STAT_IDLE) {
+		dev_err(i2c->dev, "%s: TWSI_RST failed! (0x%x)\n",
+			__func__, status);
 		return -EIO;
 	}
 
+	/* toggle twice to force both teardowns */
+	octeon_i2c_hlc_enable(i2c);
+	octeon_i2c_hlc_disable(i2c);
 	return 0;
 }
 
+static int octeon_i2c_recovery(struct octeon_i2c *i2c)
+{
+	int ret;
+
+	ret = i2c_recover_bus(&i2c->adap);
+	if (ret)
+		/* recover failed, try hardware re-init */
+		ret = octeon_i2c_init_lowlevel(i2c);
+	return ret;
+}
+
+/**
+ * octeon_i2c_start - send START to the bus
+ * @i2c: The struct octeon_i2c
+ *
+ * Returns 0 on success, otherwise a negative errno.
+ */
+static int octeon_i2c_start(struct octeon_i2c *i2c)
+{
+	int ret;
+	u8 stat;
+
+	octeon_i2c_hlc_disable(i2c);
+
+	octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB | TWSI_CTL_STA);
+	ret = octeon_i2c_wait(i2c);
+	if (ret)
+		goto error;
+
+	stat = octeon_i2c_stat_read(i2c);
+	if (stat == STAT_START || stat == STAT_REP_START)
+		/* START successful, bail out */
+		return 0;
+
+error:
+	/* START failed, try to recover */
+	ret = octeon_i2c_recovery(i2c);
+	return (ret) ? ret : -EAGAIN;
+}
+
 /* send STOP to the bus */
 static void octeon_i2c_stop(struct octeon_i2c *i2c)
 {
-	octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL,
-			    TWSI_CTL_ENAB | TWSI_CTL_STP);
+	octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB | TWSI_CTL_STP);
 }
 
 /**
@@ -276,31 +879,21 @@ static int octeon_i2c_write(struct octeo
 			    const u8 *data, int length)
 {
 	int i, result;
-	u8 tmp;
-
-	result = octeon_i2c_start(i2c);
-	if (result)
-		return result;
 
-	octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_DATA, target << 1);
-	octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, TWSI_CTL_ENAB);
+	octeon_i2c_data_write(i2c, target << 1);
+	octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB);
 
 	result = octeon_i2c_wait(i2c);
 	if (result)
 		return result;
 
 	for (i = 0; i < length; i++) {
-		tmp = octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_STAT);
-
-		if ((tmp != STAT_TXADDR_ACK) && (tmp != STAT_TXDATA_ACK)) {
-			dev_err(i2c->dev,
-				"%s: bad status before write (0x%x)\n",
-				__func__, tmp);
-			return -EIO;
-		}
+		result = octeon_i2c_check_status(i2c, false);
+		if (result)
+			return result;
 
-		octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_DATA, data[i]);
-		octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, TWSI_CTL_ENAB);
+		octeon_i2c_data_write(i2c, data[i]);
+		octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB);
 
 		result = octeon_i2c_wait(i2c);
 		if (result)
@@ -326,53 +919,52 @@ static int octeon_i2c_read(struct octeon
 			   u8 *data, u16 *rlength, bool recv_len)
 {
 	int i, result, length = *rlength;
-	u8 tmp;
+	bool final_read = false;
 
-	if (length < 1)
-		return -EINVAL;
+	octeon_i2c_data_write(i2c, (target << 1) | 1);
+	octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB);
 
-	result = octeon_i2c_start(i2c);
+	result = octeon_i2c_wait(i2c);
 	if (result)
 		return result;
 
-	octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_DATA, (target << 1) | 1);
-	octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, TWSI_CTL_ENAB);
-
-	result = octeon_i2c_wait(i2c);
+	/* address OK ? */
+	result = octeon_i2c_check_status(i2c, false);
 	if (result)
 		return result;
 
 	for (i = 0; i < length; i++) {
-		tmp = octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_STAT);
-
-		if ((tmp != STAT_RXDATA_ACK) && (tmp != STAT_RXADDR_ACK)) {
-			dev_err(i2c->dev,
-				"%s: bad status before read (0x%x)\n",
-				__func__, tmp);
-			return -EIO;
-		}
+		/*
+		 * For the last byte to receive TWSI_CTL_AAK must not be set.
+		 *
+		 * A special case is I2C_M_RECV_LEN where we don't know the
+		 * additional length yet. If recv_len is set we assume we're
+		 * not reading the final byte and therefore need to set
+		 * TWSI_CTL_AAK.
+		 */
+		if ((i + 1 == length) && !(recv_len && i == 0))
+			final_read = true;
 
-		if (i + 1 < length)
-			octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL,
-					    TWSI_CTL_ENAB | TWSI_CTL_AAK);
+		/* clear iflg to allow next event */
+		if (final_read)
+			octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB);
 		else
-			octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL,
-					    TWSI_CTL_ENAB);
+			octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB | TWSI_CTL_AAK);
 
 		result = octeon_i2c_wait(i2c);
 		if (result)
 			return result;
 
-		data[i] = octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_DATA);
+		data[i] = octeon_i2c_data_read(i2c);
 		if (recv_len && i == 0) {
-			if (data[i] > I2C_SMBUS_BLOCK_MAX + 1) {
-				dev_err(i2c->dev,
-					"%s: read len > I2C_SMBUS_BLOCK_MAX %d\n",
-					__func__, data[i]);
+			if (data[i] > I2C_SMBUS_BLOCK_MAX + 1)
 				return -EPROTO;
-			}
 			length += data[i];
 		}
+
+		result = octeon_i2c_check_status(i2c, final_read);
+		if (result)
+			return result;
 	}
 	*rlength = length;
 	return 0;
@@ -392,13 +984,41 @@ static int octeon_i2c_xfer(struct i2c_ad
 	struct octeon_i2c *i2c = i2c_get_adapdata(adap);
 	int i, ret = 0;
 
+	if (num == 1) {
+		if (msgs[0].len > 0 && msgs[0].len <= 8) {
+			if (msgs[0].flags & I2C_M_RD)
+				ret = octeon_i2c_hlc_read(i2c, msgs);
+			else
+				ret = octeon_i2c_hlc_write(i2c, msgs);
+			goto out;
+		}
+	} else if (num == 2) {
+		if ((msgs[0].flags & I2C_M_RD) == 0 &&
+		    (msgs[1].flags & I2C_M_RECV_LEN) == 0 &&
+		    msgs[0].len > 0 && msgs[0].len <= 2 &&
+		    msgs[1].len > 0 && msgs[1].len <= 8 &&
+		    msgs[0].addr == msgs[1].addr) {
+			if (msgs[1].flags & I2C_M_RD)
+				ret = octeon_i2c_hlc_comp_read(i2c, msgs);
+			else
+				ret = octeon_i2c_hlc_comp_write(i2c, msgs);
+			goto out;
+		}
+	}
+
 	for (i = 0; ret == 0 && i < num; i++) {
 		struct i2c_msg *pmsg = &msgs[i];
 
-		dev_dbg(i2c->dev,
-			"Doing %s %d byte(s) to/from 0x%02x - %d of %d messages\n",
-			 pmsg->flags & I2C_M_RD ? "read" : "write",
-			 pmsg->len, pmsg->addr, i + 1, num);
+		/* zero-length messages are not supported */
+		if (!pmsg->len) {
+			ret = -EOPNOTSUPP;
+			break;
+		}
+
+		ret = octeon_i2c_start(i2c);
+		if (ret)
+			return ret;
+
 		if (pmsg->flags & I2C_M_RD)
 			ret = octeon_i2c_read(i2c, pmsg->addr, pmsg->buf,
 					      &pmsg->len, pmsg->flags & I2C_M_RECV_LEN);
@@ -407,102 +1027,105 @@ static int octeon_i2c_xfer(struct i2c_ad
 					       pmsg->len);
 	}
 	octeon_i2c_stop(i2c);
-
+out:
 	return (ret != 0) ? ret : num;
 }
 
-static u32 octeon_i2c_functionality(struct i2c_adapter *adap)
+static int octeon_i2c_get_scl(struct i2c_adapter *adap)
 {
-	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
-	       I2C_FUNC_SMBUS_READ_BLOCK_DATA | I2C_SMBUS_BLOCK_PROC_CALL;
+	struct octeon_i2c *i2c = i2c_get_adapdata(adap);
+	u64 state;
+
+	state = octeon_i2c_read_int(i2c);
+	return state & TWSI_INT_SCL;
 }
 
-static const struct i2c_algorithm octeon_i2c_algo = {
-	.master_xfer = octeon_i2c_xfer,
-	.functionality = octeon_i2c_functionality,
-};
+static void octeon_i2c_set_scl(struct i2c_adapter *adap, int val)
+{
+	struct octeon_i2c *i2c = i2c_get_adapdata(adap);
 
-static struct i2c_adapter octeon_i2c_ops = {
-	.owner = THIS_MODULE,
-	.name = "OCTEON adapter",
-	.algo = &octeon_i2c_algo,
-	.timeout = HZ / 50,
-};
+	octeon_i2c_write_int(i2c, TWSI_INT_SCL_OVR);
+}
 
-/* calculate and set clock divisors */
-static void octeon_i2c_set_clock(struct octeon_i2c *i2c)
+static int octeon_i2c_get_sda(struct i2c_adapter *adap)
 {
-	int tclk, thp_base, inc, thp_idx, mdiv_idx, ndiv_idx, foscl, diff;
-	int thp = 0x18, mdiv = 2, ndiv = 0, delta_hz = 1000000;
+	struct octeon_i2c *i2c = i2c_get_adapdata(adap);
+	u64 state;
 
-	for (ndiv_idx = 0; ndiv_idx < 8 && delta_hz != 0; ndiv_idx++) {
-		/*
-		 * An mdiv value of less than 2 seems to not work well
-		 * with ds1337 RTCs, so we constrain it to larger values.
-		 */
-		for (mdiv_idx = 15; mdiv_idx >= 2 && delta_hz != 0; mdiv_idx--) {
-			/*
-			 * For given ndiv and mdiv values check the
-			 * two closest thp values.
-			 */
-			tclk = i2c->twsi_freq * (mdiv_idx + 1) * 10;
-			tclk *= (1 << ndiv_idx);
-			thp_base = (i2c->sys_freq / (tclk * 2)) - 1;
+	state = octeon_i2c_read_int(i2c);
+	return state & TWSI_INT_SDA;
+}
 
-			for (inc = 0; inc <= 1; inc++) {
-				thp_idx = thp_base + inc;
-				if (thp_idx < 5 || thp_idx > 0xff)
-					continue;
+static void octeon_i2c_prepare_recovery(struct i2c_adapter *adap)
+{
+	struct octeon_i2c *i2c = i2c_get_adapdata(adap);
 
-				foscl = i2c->sys_freq / (2 * (thp_idx + 1));
-				foscl = foscl / (1 << ndiv_idx);
-				foscl = foscl / (mdiv_idx + 1) / 10;
-				diff = abs(foscl - i2c->twsi_freq);
-				if (diff < delta_hz) {
-					delta_hz = diff;
-					thp = thp_idx;
-					mdiv = mdiv_idx;
-					ndiv = ndiv_idx;
-				}
-			}
-		}
-	}
-	octeon_i2c_write_sw(i2c, SW_TWSI_OP_TWSI_CLK, thp);
-	octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CLKCTL, (mdiv << 3) | ndiv);
+	/*
+	 * The stop resets the state machine, does not _transmit_ STOP unless
+	 * engine was active.
+	 */
+	octeon_i2c_stop(i2c);
+
+	octeon_i2c_hlc_disable(i2c);
+	octeon_i2c_write_int(i2c, 0);
 }
 
-static int octeon_i2c_init_lowlevel(struct octeon_i2c *i2c)
+static void octeon_i2c_unprepare_recovery(struct i2c_adapter *adap)
 {
-	u8 status;
-	int tries;
+	struct octeon_i2c *i2c = i2c_get_adapdata(adap);
 
-	/* disable high level controller, enable bus access */
-	octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, TWSI_CTL_ENAB);
+	octeon_i2c_write_int(i2c, 0);
+}
 
-	/* reset controller */
-	octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_RST, 0);
+static struct i2c_bus_recovery_info octeon_i2c_recovery_info = {
+	.recover_bus = i2c_generic_scl_recovery,
+	.get_scl = octeon_i2c_get_scl,
+	.set_scl = octeon_i2c_set_scl,
+	.get_sda = octeon_i2c_get_sda,
+	.prepare_recovery = octeon_i2c_prepare_recovery,
+	.unprepare_recovery = octeon_i2c_unprepare_recovery,
+};
 
-	for (tries = 10; tries; tries--) {
-		udelay(1);
-		status = octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_STAT);
-		if (status == STAT_IDLE)
-			return 0;
-	}
-	dev_err(i2c->dev, "%s: TWSI_RST failed! (0x%x)\n", __func__, status);
-	return -EIO;
+static u32 octeon_i2c_functionality(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK) |
+	       I2C_FUNC_SMBUS_READ_BLOCK_DATA | I2C_SMBUS_BLOCK_PROC_CALL;
 }
 
+static const struct i2c_algorithm octeon_i2c_algo = {
+	.master_xfer = octeon_i2c_xfer,
+	.functionality = octeon_i2c_functionality,
+};
+
+static struct i2c_adapter octeon_i2c_ops = {
+	.owner = THIS_MODULE,
+	.name = "OCTEON adapter",
+	.algo = &octeon_i2c_algo,
+};
+
 static int octeon_i2c_probe(struct platform_device *pdev)
 {
 	struct device_node *node = pdev->dev.of_node;
+	int irq, result = 0, hlc_irq = 0;
 	struct resource *res_mem;
 	struct octeon_i2c *i2c;
-	int irq, result = 0;
+	bool cn78xx_style;
 
-	/* All adaptors have an irq.  */
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0)
-		return irq;
+	cn78xx_style = of_device_is_compatible(node, "cavium,octeon-7890-twsi");
+	if (cn78xx_style) {
+		hlc_irq = platform_get_irq(pdev, 0);
+		if (hlc_irq < 0)
+			return hlc_irq;
+
+		irq = platform_get_irq(pdev, 2);
+		if (irq < 0)
+			return irq;
+	} else {
+		/* All adaptors have an irq.  */
+		irq = platform_get_irq(pdev, 0);
+		if (irq < 0)
+			return irq;
+	}
 
 	i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
 	if (!i2c) {
@@ -537,6 +1160,31 @@ static int octeon_i2c_probe(struct platf
 
 	i2c->irq = irq;
 
+	if (cn78xx_style) {
+		i2c->hlc_irq = hlc_irq;
+
+		i2c->int_enable = octeon_i2c_int_enable78;
+		i2c->int_disable = octeon_i2c_int_disable78;
+		i2c->hlc_int_enable = octeon_i2c_hlc_int_enable78;
+		i2c->hlc_int_disable = octeon_i2c_hlc_int_disable78;
+
+		irq_set_status_flags(i2c->irq, IRQ_NOAUTOEN);
+		irq_set_status_flags(i2c->hlc_irq, IRQ_NOAUTOEN);
+
+		result = devm_request_irq(&pdev->dev, i2c->hlc_irq,
+					  octeon_i2c_hlc_isr78, 0,
+					  DRV_NAME, i2c);
+		if (result < 0) {
+			dev_err(i2c->dev, "failed to attach interrupt\n");
+			goto out;
+		}
+	} else {
+		i2c->int_enable = octeon_i2c_int_enable;
+		i2c->int_disable = octeon_i2c_int_disable;
+		i2c->hlc_int_enable = octeon_i2c_hlc_int_enable;
+		i2c->hlc_int_disable = octeon_i2c_int_disable;
+	}
+
 	result = devm_request_irq(&pdev->dev, i2c->irq,
 				  octeon_i2c_isr, 0, DRV_NAME, i2c);
 	if (result < 0) {
@@ -544,6 +1192,9 @@ static int octeon_i2c_probe(struct platf
 		goto out;
 	}
 
+	if (OCTEON_IS_MODEL(OCTEON_CN38XX))
+		i2c->broken_irq_check = true;
+
 	result = octeon_i2c_init_lowlevel(i2c);
 	if (result) {
 		dev_err(i2c->dev, "init low level failed\n");
@@ -553,6 +1204,9 @@ static int octeon_i2c_probe(struct platf
 	octeon_i2c_set_clock(i2c);
 
 	i2c->adap = octeon_i2c_ops;
+	i2c->adap.timeout = msecs_to_jiffies(2);
+	i2c->adap.retries = 5;
+	i2c->adap.bus_recovery_info = &octeon_i2c_recovery_info;
 	i2c->adap.dev.parent = &pdev->dev;
 	i2c->adap.dev.of_node = node;
 	i2c_set_adapdata(&i2c->adap, i2c);
@@ -580,6 +1234,7 @@ static int octeon_i2c_remove(struct plat
 
 static const struct of_device_id octeon_i2c_match[] = {
 	{ .compatible = "cavium,octeon-3860-twsi", },
+	{ .compatible = "cavium,octeon-7890-twsi", },
 	{},
 };
 MODULE_DEVICE_TABLE(of, octeon_i2c_match);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/busses/i2c-omap.c linux-libre-4.7-gnu/drivers/i2c/busses/i2c-omap.c
--- linux-libre-4.6-gnu/drivers/i2c/busses/i2c-omap.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/busses/i2c-omap.c	2016-07-24 15:23:50.000000000 -0400
@@ -185,7 +185,6 @@ enum {
 #define OMAP_I2C_IP_V2_INTERRUPTS_MASK	0x6FFF
 
 struct omap_i2c_dev {
-	spinlock_t		lock;		/* IRQ synchronization */
 	struct device		*dev;
 	void __iomem		*base;		/* virtual */
 	int			irq;
@@ -995,15 +994,12 @@ omap_i2c_isr(int irq, void *dev_id)
 	u16 mask;
 	u16 stat;
 
-	spin_lock(&omap->lock);
-	mask = omap_i2c_read_reg(omap, OMAP_I2C_IE_REG);
 	stat = omap_i2c_read_reg(omap, OMAP_I2C_STAT_REG);
+	mask = omap_i2c_read_reg(omap, OMAP_I2C_IE_REG);
 
 	if (stat & mask)
 		ret = IRQ_WAKE_THREAD;
 
-	spin_unlock(&omap->lock);
-
 	return ret;
 }
 
@@ -1011,12 +1007,10 @@ static irqreturn_t
 omap_i2c_isr_thread(int this_irq, void *dev_id)
 {
 	struct omap_i2c_dev *omap = dev_id;
-	unsigned long flags;
 	u16 bits;
 	u16 stat;
 	int err = 0, count = 0;
 
-	spin_lock_irqsave(&omap->lock, flags);
 	do {
 		bits = omap_i2c_read_reg(omap, OMAP_I2C_IE_REG);
 		stat = omap_i2c_read_reg(omap, OMAP_I2C_STAT_REG);
@@ -1142,8 +1136,6 @@ omap_i2c_isr_thread(int this_irq, void *
 	omap_i2c_complete_cmd(omap, err);
 
 out:
-	spin_unlock_irqrestore(&omap->lock, flags);
-
 	return IRQ_HANDLED;
 }
 
@@ -1330,8 +1322,6 @@ omap_i2c_probe(struct platform_device *p
 	omap->dev = &pdev->dev;
 	omap->irq = irq;
 
-	spin_lock_init(&omap->lock);
-
 	platform_set_drvdata(pdev, omap);
 	init_completion(&omap->cmd_complete);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/busses/i2c-powermac.c linux-libre-4.7-gnu/drivers/i2c/busses/i2c-powermac.c
--- linux-libre-4.6-gnu/drivers/i2c/busses/i2c-powermac.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/busses/i2c-powermac.c	2016-07-24 15:23:50.000000000 -0400
@@ -150,13 +150,11 @@ static int i2c_powermac_master_xfer(	str
 {
 	struct pmac_i2c_bus	*bus = i2c_get_adapdata(adap);
 	int			rc = 0;
-	int			read;
 	int			addrdir;
 
 	if (msgs->flags & I2C_M_TEN)
 		return -EINVAL;
-	read = (msgs->flags & I2C_M_RD) != 0;
-	addrdir = (msgs->addr << 1) | read;
+	addrdir = i2c_8bit_addr_from_msg(msgs);
 
 	rc = pmac_i2c_open(bus, 0);
 	if (rc) {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/busses/i2c-qup.c linux-libre-4.7-gnu/drivers/i2c/busses/i2c-qup.c
--- linux-libre-4.6-gnu/drivers/i2c/busses/i2c-qup.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/busses/i2c-qup.c	2016-07-24 15:23:50.000000000 -0400
@@ -515,7 +515,7 @@ static int qup_i2c_get_data_len(struct q
 static int qup_i2c_set_tags(u8 *tags, struct qup_i2c_dev *qup,
 			    struct i2c_msg *msg,  int is_dma)
 {
-	u16 addr = (msg->addr << 1) | ((msg->flags & I2C_M_RD) == I2C_M_RD);
+	u16 addr = i2c_8bit_addr_from_msg(msg);
 	int len = 0;
 	int data_len;
 
@@ -1268,6 +1268,8 @@ static int qup_i2c_xfer_v2(struct i2c_ad
 		}
 	}
 
+	idx = 0;
+
 	do {
 		if (msgs[idx].len == 0) {
 			ret = -EINVAL;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/busses/i2c-rcar.c linux-libre-4.7-gnu/drivers/i2c/busses/i2c-rcar.c
--- linux-libre-4.6-gnu/drivers/i2c/busses/i2c-rcar.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/busses/i2c-rcar.c	2016-07-24 15:23:50.000000000 -0400
@@ -21,6 +21,8 @@
  */
 #include <linux/clk.h>
 #include <linux/delay.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
 #include <linux/err.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
@@ -43,6 +45,8 @@
 #define ICSAR	0x1C	/* slave address */
 #define ICMAR	0x20	/* master address */
 #define ICRXTX	0x24	/* data port */
+#define ICDMAER	0x3c	/* DMA enable */
+#define ICFBSCR	0x38	/* first bit setup cycle */
 
 /* ICSCR */
 #define SDBS	(1 << 3)	/* slave data buffer select */
@@ -78,6 +82,16 @@
 #define MDR	(1 << 1)
 #define MAT	(1 << 0)	/* slave addr xfer done */
 
+/* ICDMAER */
+#define RSDMAE	(1 << 3)	/* DMA Slave Received Enable */
+#define TSDMAE	(1 << 2)	/* DMA Slave Transmitted Enable */
+#define RMDMAE	(1 << 1)	/* DMA Master Received Enable */
+#define TMDMAE	(1 << 0)	/* DMA Master Transmitted Enable */
+
+/* ICFBSCR */
+#define TCYC06	0x04		/*  6*Tcyc delay 1st bit between SDA and SCL */
+#define TCYC17	0x0f		/* 17*Tcyc delay 1st bit between SDA and SCL */
+
 
 #define RCAR_BUS_PHASE_START	(MDBS | MIE | ESG)
 #define RCAR_BUS_PHASE_DATA	(MDBS | MIE)
@@ -120,6 +134,12 @@ struct rcar_i2c_priv {
 	u32 flags;
 	enum rcar_i2c_type devtype;
 	struct i2c_client *slave;
+
+	struct resource *res;
+	struct dma_chan *dma_tx;
+	struct dma_chan *dma_rx;
+	struct scatterlist sg;
+	enum dma_data_direction dma_direction;
 };
 
 #define rcar_i2c_priv_to_dev(p)		((p)->adap.dev.parent)
@@ -287,6 +307,118 @@ static void rcar_i2c_next_msg(struct rca
 /*
  *		interrupt functions
  */
+static void rcar_i2c_dma_unmap(struct rcar_i2c_priv *priv)
+{
+	struct dma_chan *chan = priv->dma_direction == DMA_FROM_DEVICE
+		? priv->dma_rx : priv->dma_tx;
+
+	/* Disable DMA Master Received/Transmitted */
+	rcar_i2c_write(priv, ICDMAER, 0);
+
+	/* Reset default delay */
+	rcar_i2c_write(priv, ICFBSCR, TCYC06);
+
+	dma_unmap_single(chan->device->dev, sg_dma_address(&priv->sg),
+			 priv->msg->len, priv->dma_direction);
+
+	priv->dma_direction = DMA_NONE;
+}
+
+static void rcar_i2c_cleanup_dma(struct rcar_i2c_priv *priv)
+{
+	if (priv->dma_direction == DMA_NONE)
+		return;
+	else if (priv->dma_direction == DMA_FROM_DEVICE)
+		dmaengine_terminate_all(priv->dma_rx);
+	else if (priv->dma_direction == DMA_TO_DEVICE)
+		dmaengine_terminate_all(priv->dma_tx);
+
+	rcar_i2c_dma_unmap(priv);
+}
+
+static void rcar_i2c_dma_callback(void *data)
+{
+	struct rcar_i2c_priv *priv = data;
+
+	priv->pos += sg_dma_len(&priv->sg);
+
+	rcar_i2c_dma_unmap(priv);
+}
+
+static void rcar_i2c_dma(struct rcar_i2c_priv *priv)
+{
+	struct device *dev = rcar_i2c_priv_to_dev(priv);
+	struct i2c_msg *msg = priv->msg;
+	bool read = msg->flags & I2C_M_RD;
+	enum dma_data_direction dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+	struct dma_chan *chan = read ? priv->dma_rx : priv->dma_tx;
+	struct dma_async_tx_descriptor *txdesc;
+	dma_addr_t dma_addr;
+	dma_cookie_t cookie;
+	unsigned char *buf;
+	int len;
+
+	/* Do not use DMA if it's not available or for messages < 8 bytes */
+	if (IS_ERR(chan) || msg->len < 8)
+		return;
+
+	if (read) {
+		/*
+		 * The last two bytes needs to be fetched using PIO in
+		 * order for the STOP phase to work.
+		 */
+		buf = priv->msg->buf;
+		len = priv->msg->len - 2;
+	} else {
+		/*
+		 * First byte in message was sent using PIO.
+		 */
+		buf = priv->msg->buf + 1;
+		len = priv->msg->len - 1;
+	}
+
+	dma_addr = dma_map_single(chan->device->dev, buf, len, dir);
+	if (dma_mapping_error(dev, dma_addr)) {
+		dev_dbg(dev, "dma map failed, using PIO\n");
+		return;
+	}
+
+	sg_dma_len(&priv->sg) = len;
+	sg_dma_address(&priv->sg) = dma_addr;
+
+	priv->dma_direction = dir;
+
+	txdesc = dmaengine_prep_slave_sg(chan, &priv->sg, 1,
+					 read ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV,
+					 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!txdesc) {
+		dev_dbg(dev, "dma prep slave sg failed, using PIO\n");
+		rcar_i2c_cleanup_dma(priv);
+		return;
+	}
+
+	txdesc->callback = rcar_i2c_dma_callback;
+	txdesc->callback_param = priv;
+
+	cookie = dmaengine_submit(txdesc);
+	if (dma_submit_error(cookie)) {
+		dev_dbg(dev, "submitting dma failed, using PIO\n");
+		rcar_i2c_cleanup_dma(priv);
+		return;
+	}
+
+	/* Set delay for DMA operations */
+	rcar_i2c_write(priv, ICFBSCR, TCYC17);
+
+	/* Enable DMA Master Received/Transmitted */
+	if (read)
+		rcar_i2c_write(priv, ICDMAER, RMDMAE);
+	else
+		rcar_i2c_write(priv, ICDMAER, TMDMAE);
+
+	dma_async_issue_pending(chan);
+}
+
 static void rcar_i2c_irq_send(struct rcar_i2c_priv *priv, u32 msr)
 {
 	struct i2c_msg *msg = priv->msg;
@@ -306,6 +438,12 @@ static void rcar_i2c_irq_send(struct rca
 		rcar_i2c_write(priv, ICRXTX, msg->buf[priv->pos]);
 		priv->pos++;
 
+		/*
+		 * Try to use DMA to transmit the rest of the data if
+		 * address transfer pashe just finished.
+		 */
+		if (msr & MAT)
+			rcar_i2c_dma(priv);
 	} else {
 		/*
 		 * The last data was pushed to ICRXTX on _PREV_ empty irq.
@@ -340,7 +478,11 @@ static void rcar_i2c_irq_recv(struct rca
 		return;
 
 	if (msr & MAT) {
-		/* Address transfer phase finished, but no data at this point. */
+		/*
+		 * Address transfer phase finished, but no data at this point.
+		 * Try to use DMA to receive data.
+		 */
+		rcar_i2c_dma(priv);
 	} else if (priv->pos < msg->len) {
 		/* get received data */
 		msg->buf[priv->pos] = rcar_i2c_read(priv, ICRXTX);
@@ -472,6 +614,81 @@ out:
 	return IRQ_HANDLED;
 }
 
+static struct dma_chan *rcar_i2c_request_dma_chan(struct device *dev,
+					enum dma_transfer_direction dir,
+					dma_addr_t port_addr)
+{
+	struct dma_chan *chan;
+	struct dma_slave_config cfg;
+	char *chan_name = dir == DMA_MEM_TO_DEV ? "tx" : "rx";
+	int ret;
+
+	chan = dma_request_chan(dev, chan_name);
+	if (IS_ERR(chan)) {
+		ret = PTR_ERR(chan);
+		dev_dbg(dev, "request_channel failed for %s (%d)\n",
+			chan_name, ret);
+		return chan;
+	}
+
+	memset(&cfg, 0, sizeof(cfg));
+	cfg.direction = dir;
+	if (dir == DMA_MEM_TO_DEV) {
+		cfg.dst_addr = port_addr;
+		cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+	} else {
+		cfg.src_addr = port_addr;
+		cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+	}
+
+	ret = dmaengine_slave_config(chan, &cfg);
+	if (ret) {
+		dev_dbg(dev, "slave_config failed for %s (%d)\n",
+			chan_name, ret);
+		dma_release_channel(chan);
+		return ERR_PTR(ret);
+	}
+
+	dev_dbg(dev, "got DMA channel for %s\n", chan_name);
+	return chan;
+}
+
+static void rcar_i2c_request_dma(struct rcar_i2c_priv *priv,
+				 struct i2c_msg *msg)
+{
+	struct device *dev = rcar_i2c_priv_to_dev(priv);
+	bool read;
+	struct dma_chan *chan;
+	enum dma_transfer_direction dir;
+
+	read = msg->flags & I2C_M_RD;
+
+	chan = read ? priv->dma_rx : priv->dma_tx;
+	if (PTR_ERR(chan) != -EPROBE_DEFER)
+		return;
+
+	dir = read ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV;
+	chan = rcar_i2c_request_dma_chan(dev, dir, priv->res->start + ICRXTX);
+
+	if (read)
+		priv->dma_rx = chan;
+	else
+		priv->dma_tx = chan;
+}
+
+static void rcar_i2c_release_dma(struct rcar_i2c_priv *priv)
+{
+	if (!IS_ERR(priv->dma_tx)) {
+		dma_release_channel(priv->dma_tx);
+		priv->dma_tx = ERR_PTR(-EPROBE_DEFER);
+	}
+
+	if (!IS_ERR(priv->dma_rx)) {
+		dma_release_channel(priv->dma_rx);
+		priv->dma_rx = ERR_PTR(-EPROBE_DEFER);
+	}
+}
+
 static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
 				struct i2c_msg *msgs,
 				int num)
@@ -493,6 +710,7 @@ static int rcar_i2c_master_xfer(struct i
 			ret = -EOPNOTSUPP;
 			goto out;
 		}
+		rcar_i2c_request_dma(priv, msgs + i);
 	}
 
 	/* init first message */
@@ -504,6 +722,7 @@ static int rcar_i2c_master_xfer(struct i
 	time_left = wait_event_timeout(priv->wait, priv->flags & ID_DONE,
 				     num * adap->timeout);
 	if (!time_left) {
+		rcar_i2c_cleanup_dma(priv);
 		rcar_i2c_init(priv);
 		ret = -ETIMEDOUT;
 	} else if (priv->flags & ID_NACK) {
@@ -591,7 +810,6 @@ static int rcar_i2c_probe(struct platfor
 {
 	struct rcar_i2c_priv *priv;
 	struct i2c_adapter *adap;
-	struct resource *res;
 	struct device *dev = &pdev->dev;
 	struct i2c_timings i2c_t;
 	int irq, ret;
@@ -606,8 +824,9 @@ static int rcar_i2c_probe(struct platfor
 		return PTR_ERR(priv->clk);
 	}
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	priv->io = devm_ioremap_resource(dev, res);
+	priv->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	priv->io = devm_ioremap_resource(dev, priv->res);
 	if (IS_ERR(priv->io))
 		return PTR_ERR(priv->io);
 
@@ -626,6 +845,11 @@ static int rcar_i2c_probe(struct platfor
 
 	i2c_parse_fw_timings(dev, &i2c_t, false);
 
+	/* Init DMA */
+	sg_init_table(&priv->sg, 1);
+	priv->dma_direction = DMA_NONE;
+	priv->dma_rx = priv->dma_tx = ERR_PTR(-EPROBE_DEFER);
+
 	pm_runtime_enable(dev);
 	pm_runtime_get_sync(dev);
 	ret = rcar_i2c_clock_calculate(priv, &i2c_t);
@@ -673,6 +897,7 @@ static int rcar_i2c_remove(struct platfo
 	struct device *dev = &pdev->dev;
 
 	i2c_del_adapter(&priv->adap);
+	rcar_i2c_release_dma(priv);
 	if (priv->flags & ID_P_PM_BLOCKED)
 		pm_runtime_put(dev);
 	pm_runtime_disable(dev);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/busses/i2c-rk3x.c linux-libre-4.7-gnu/drivers/i2c/busses/i2c-rk3x.c
--- linux-libre-4.6-gnu/drivers/i2c/busses/i2c-rk3x.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/busses/i2c-rk3x.c	2016-07-24 15:23:50.000000000 -0400
@@ -101,10 +101,7 @@ struct rk3x_i2c {
 	struct notifier_block clk_rate_nb;
 
 	/* Settings */
-	unsigned int scl_frequency;
-	unsigned int scl_rise_ns;
-	unsigned int scl_fall_ns;
-	unsigned int sda_fall_ns;
+	struct i2c_timings t;
 
 	/* Synchronization & notification */
 	spinlock_t lock;
@@ -437,10 +434,7 @@ out:
  * Calculate divider values for desired SCL frequency
  *
  * @clk_rate: I2C input clock rate
- * @scl_rate: Desired SCL rate
- * @scl_rise_ns: How many ns it takes for SCL to rise.
- * @scl_fall_ns: How many ns it takes for SCL to fall.
- * @sda_fall_ns: How many ns it takes for SDA to fall.
+ * @t: Known I2C timing information.
  * @div_low: Divider output for low
  * @div_high: Divider output for high
  *
@@ -448,11 +442,10 @@ out:
  * a best-effort divider value is returned in divs. If the target rate is
  * too high, we silently use the highest possible rate.
  */
-static int rk3x_i2c_calc_divs(unsigned long clk_rate, unsigned long scl_rate,
-			      unsigned long scl_rise_ns,
-			      unsigned long scl_fall_ns,
-			      unsigned long sda_fall_ns,
-			      unsigned long *div_low, unsigned long *div_high)
+static int rk3x_i2c_calc_divs(unsigned long clk_rate,
+			      struct i2c_timings *t,
+			      unsigned long *div_low,
+			      unsigned long *div_high)
 {
 	unsigned long spec_min_low_ns, spec_min_high_ns;
 	unsigned long spec_setup_start, spec_max_data_hold_ns;
@@ -472,12 +465,12 @@ static int rk3x_i2c_calc_divs(unsigned l
 	int ret = 0;
 
 	/* Only support standard-mode and fast-mode */
-	if (WARN_ON(scl_rate > 400000))
-		scl_rate = 400000;
+	if (WARN_ON(t->bus_freq_hz > 400000))
+		t->bus_freq_hz = 400000;
 
 	/* prevent scl_rate_khz from becoming 0 */
-	if (WARN_ON(scl_rate < 1000))
-		scl_rate = 1000;
+	if (WARN_ON(t->bus_freq_hz < 1000))
+		t->bus_freq_hz = 1000;
 
 	/*
 	 * min_low_ns:  The minimum number of ns we need to hold low to
@@ -491,7 +484,7 @@ static int rk3x_i2c_calc_divs(unsigned l
 	 *	 This is because the i2c host on Rockchip holds the data line
 	 *	 for half the low time.
 	 */
-	if (scl_rate <= 100000) {
+	if (t->bus_freq_hz <= 100000) {
 		/* Standard-mode */
 		spec_min_low_ns = 4700;
 		spec_setup_start = 4700;
@@ -506,7 +499,7 @@ static int rk3x_i2c_calc_divs(unsigned l
 		spec_max_data_hold_ns = 900;
 		data_hold_buffer_ns = 50;
 	}
-	min_high_ns = scl_rise_ns + spec_min_high_ns;
+	min_high_ns = t->scl_rise_ns + spec_min_high_ns;
 
 	/*
 	 * Timings for repeated start:
@@ -517,18 +510,18 @@ static int rk3x_i2c_calc_divs(unsigned l
 	 * we meet tSU;STA and tHD;STA times.
 	 */
 	min_high_ns = max(min_high_ns,
-		DIV_ROUND_UP((scl_rise_ns + spec_setup_start) * 1000, 875));
+		DIV_ROUND_UP((t->scl_rise_ns + spec_setup_start) * 1000, 875));
 	min_high_ns = max(min_high_ns,
-		DIV_ROUND_UP((scl_rise_ns + spec_setup_start +
-			      sda_fall_ns + spec_min_high_ns), 2));
+		DIV_ROUND_UP((t->scl_rise_ns + spec_setup_start +
+			      t->sda_fall_ns + spec_min_high_ns), 2));
 
-	min_low_ns = scl_fall_ns + spec_min_low_ns;
+	min_low_ns = t->scl_fall_ns + spec_min_low_ns;
 	max_low_ns = spec_max_data_hold_ns * 2 - data_hold_buffer_ns;
 	min_total_ns = min_low_ns + min_high_ns;
 
 	/* Adjust to avoid overflow */
 	clk_rate_khz = DIV_ROUND_UP(clk_rate, 1000);
-	scl_rate_khz = scl_rate / 1000;
+	scl_rate_khz = t->bus_freq_hz / 1000;
 
 	/*
 	 * We need the total div to be >= this number
@@ -616,14 +609,13 @@ static int rk3x_i2c_calc_divs(unsigned l
 
 static void rk3x_i2c_adapt_div(struct rk3x_i2c *i2c, unsigned long clk_rate)
 {
+	struct i2c_timings *t = &i2c->t;
 	unsigned long div_low, div_high;
 	u64 t_low_ns, t_high_ns;
 	int ret;
 
-	ret = rk3x_i2c_calc_divs(clk_rate, i2c->scl_frequency, i2c->scl_rise_ns,
-				 i2c->scl_fall_ns, i2c->sda_fall_ns,
-				 &div_low, &div_high);
-	WARN_ONCE(ret != 0, "Could not reach SCL freq %u", i2c->scl_frequency);
+	ret = rk3x_i2c_calc_divs(clk_rate, t, &div_low, &div_high);
+	WARN_ONCE(ret != 0, "Could not reach SCL freq %u", t->bus_freq_hz);
 
 	clk_enable(i2c->clk);
 	i2c_writel(i2c, (div_high << 16) | (div_low & 0xffff), REG_CLKDIV);
@@ -634,7 +626,7 @@ static void rk3x_i2c_adapt_div(struct rk
 	dev_dbg(i2c->dev,
 		"CLK %lukhz, Req %uns, Act low %lluns high %lluns\n",
 		clk_rate / 1000,
-		1000000000 / i2c->scl_frequency,
+		1000000000 / t->bus_freq_hz,
 		t_low_ns, t_high_ns);
 }
 
@@ -664,9 +656,7 @@ static int rk3x_i2c_clk_notifier_cb(stru
 
 	switch (event) {
 	case PRE_RATE_CHANGE:
-		if (rk3x_i2c_calc_divs(ndata->new_rate, i2c->scl_frequency,
-				       i2c->scl_rise_ns, i2c->scl_fall_ns,
-				       i2c->sda_fall_ns,
+		if (rk3x_i2c_calc_divs(ndata->new_rate, &i2c->t,
 				       &div_low, &div_high) != 0)
 			return NOTIFY_STOP;
 
@@ -880,37 +870,8 @@ static int rk3x_i2c_probe(struct platfor
 	match = of_match_node(rk3x_i2c_match, np);
 	i2c->soc_data = (struct rk3x_i2c_soc_data *)match->data;
 
-	if (of_property_read_u32(pdev->dev.of_node, "clock-frequency",
-				 &i2c->scl_frequency)) {
-		dev_info(&pdev->dev, "using default SCL frequency: %d\n",
-			 DEFAULT_SCL_RATE);
-		i2c->scl_frequency = DEFAULT_SCL_RATE;
-	}
-
-	if (i2c->scl_frequency == 0 || i2c->scl_frequency > 400 * 1000) {
-		dev_warn(&pdev->dev, "invalid SCL frequency specified.\n");
-		dev_warn(&pdev->dev, "using default SCL frequency: %d\n",
-			 DEFAULT_SCL_RATE);
-		i2c->scl_frequency = DEFAULT_SCL_RATE;
-	}
-
-	/*
-	 * Read rise and fall time from device tree. If not available use
-	 * the default maximum timing from the specification.
-	 */
-	if (of_property_read_u32(pdev->dev.of_node, "i2c-scl-rising-time-ns",
-				 &i2c->scl_rise_ns)) {
-		if (i2c->scl_frequency <= 100000)
-			i2c->scl_rise_ns = 1000;
-		else
-			i2c->scl_rise_ns = 300;
-	}
-	if (of_property_read_u32(pdev->dev.of_node, "i2c-scl-falling-time-ns",
-				 &i2c->scl_fall_ns))
-		i2c->scl_fall_ns = 300;
-	if (of_property_read_u32(pdev->dev.of_node, "i2c-sda-falling-time-ns",
-				 &i2c->sda_fall_ns))
-		i2c->sda_fall_ns = i2c->scl_fall_ns;
+	/* use common interface to get I2C timing properties */
+	i2c_parse_fw_timings(&pdev->dev, &i2c->t, true);
 
 	strlcpy(i2c->adap.name, "rk3x-i2c", sizeof(i2c->adap.name));
 	i2c->adap.owner = THIS_MODULE;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/busses/i2c-s3c2410.c linux-libre-4.7-gnu/drivers/i2c/busses/i2c-s3c2410.c
--- linux-libre-4.6-gnu/drivers/i2c/busses/i2c-s3c2410.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/busses/i2c-s3c2410.c	2016-07-24 15:23:50.000000000 -0400
@@ -163,15 +163,14 @@ static const struct of_device_id s3c24xx
 MODULE_DEVICE_TABLE(of, s3c24xx_i2c_match);
 #endif
 
-/* s3c24xx_get_device_quirks
- *
+/*
  * Get controller type either from device tree or platform device variant.
-*/
-
+ */
 static inline kernel_ulong_t s3c24xx_get_device_quirks(struct platform_device *pdev)
 {
 	if (pdev->dev.of_node) {
 		const struct of_device_id *match;
+
 		match = of_match_node(s3c24xx_i2c_match, pdev->dev.of_node);
 		return (kernel_ulong_t)match->data;
 	}
@@ -179,12 +178,10 @@ static inline kernel_ulong_t s3c24xx_get
 	return platform_get_device_id(pdev)->driver_data;
 }
 
-/* s3c24xx_i2c_master_complete
- *
- * complete the message and wake up the caller, using the given return code,
+/*
+ * Complete the message and wake up the caller, using the given return code,
  * or zero to mean ok.
-*/
-
+ */
 static inline void s3c24xx_i2c_master_complete(struct s3c24xx_i2c *i2c, int ret)
 {
 	dev_dbg(i2c->dev, "master_complete %d\n", ret);
@@ -217,7 +214,6 @@ static inline void s3c24xx_i2c_enable_ac
 }
 
 /* irq enable/disable functions */
-
 static inline void s3c24xx_i2c_disable_irq(struct s3c24xx_i2c *i2c)
 {
 	unsigned long tmp;
@@ -251,11 +247,9 @@ static bool is_ack(struct s3c24xx_i2c *i
 	return false;
 }
 
-/* s3c24xx_i2c_message_start
- *
+/*
  * put the start of a message onto the bus
-*/
-
+ */
 static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c,
 				      struct i2c_msg *msg)
 {
@@ -284,9 +278,10 @@ static void s3c24xx_i2c_message_start(st
 	dev_dbg(i2c->dev, "START: %08lx to IICSTAT, %02x to DS\n", stat, addr);
 	writeb(addr, i2c->regs + S3C2410_IICDS);
 
-	/* delay here to ensure the data byte has gotten onto the bus
-	 * before the transaction is started */
-
+	/*
+	 * delay here to ensure the data byte has gotten onto the bus
+	 * before the transaction is started
+	 */
 	ndelay(i2c->tx_setup);
 
 	dev_dbg(i2c->dev, "iiccon, %08lx\n", iiccon);
@@ -361,50 +356,46 @@ static inline void s3c24xx_i2c_stop(stru
 	s3c24xx_i2c_disable_irq(i2c);
 }
 
-/* helper functions to determine the current state in the set of
- * messages we are sending */
+/*
+ * helper functions to determine the current state in the set of
+ * messages we are sending
+ */
 
-/* is_lastmsg()
- *
+/*
  * returns TRUE if the current message is the last in the set
-*/
-
+ */
 static inline int is_lastmsg(struct s3c24xx_i2c *i2c)
 {
 	return i2c->msg_idx >= (i2c->msg_num - 1);
 }
 
-/* is_msglast
- *
+/*
  * returns TRUE if we this is the last byte in the current message
-*/
-
+ */
 static inline int is_msglast(struct s3c24xx_i2c *i2c)
 {
-	/* msg->len is always 1 for the first byte of smbus block read.
+	/*
+	 * msg->len is always 1 for the first byte of smbus block read.
 	 * Actual length will be read from slave. More bytes will be
-	 * read according to the length then. */
+	 * read according to the length then.
+	 */
 	if (i2c->msg->flags & I2C_M_RECV_LEN && i2c->msg->len == 1)
 		return 0;
 
 	return i2c->msg_ptr == i2c->msg->len-1;
 }
 
-/* is_msgend
- *
+/*
  * returns TRUE if we reached the end of the current message
-*/
-
+ */
 static inline int is_msgend(struct s3c24xx_i2c *i2c)
 {
 	return i2c->msg_ptr >= i2c->msg->len;
 }
 
-/* i2c_s3c_irq_nextbyte
- *
+/*
  * process an interrupt and work out what to do
  */
-
 static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
 {
 	unsigned long tmp;
@@ -423,14 +414,13 @@ static int i2c_s3c_irq_nextbyte(struct s
 		goto out_ack;
 
 	case STATE_START:
-		/* last thing we did was send a start condition on the
+		/*
+		 * last thing we did was send a start condition on the
 		 * bus, or started a new i2c message
 		 */
-
 		if (iicstat & S3C2410_IICSTAT_LASTBIT &&
 		    !(i2c->msg->flags & I2C_M_IGNORE_NAK)) {
 			/* ack was not received... */
-
 			dev_dbg(i2c->dev, "ack was not received\n");
 			s3c24xx_i2c_stop(i2c, -ENXIO);
 			goto out_ack;
@@ -441,9 +431,10 @@ static int i2c_s3c_irq_nextbyte(struct s
 		else
 			i2c->state = STATE_WRITE;
 
-		/* terminate the transfer if there is nothing to do
-		 * as this is used by the i2c probe to find devices. */
-
+		/*
+		 * Terminate the transfer if there is nothing to do
+		 * as this is used by the i2c probe to find devices.
+		 */
 		if (is_lastmsg(i2c) && i2c->msg->len == 0) {
 			s3c24xx_i2c_stop(i2c, 0);
 			goto out_ack;
@@ -452,14 +443,16 @@ static int i2c_s3c_irq_nextbyte(struct s
 		if (i2c->state == STATE_READ)
 			goto prepare_read;
 
-		/* fall through to the write state, as we will need to
-		 * send a byte as well */
+		/*
+		 * fall through to the write state, as we will need to
+		 * send a byte as well
+		 */
 
 	case STATE_WRITE:
-		/* we are writing data to the device... check for the
+		/*
+		 * we are writing data to the device... check for the
 		 * end of the message, and if so, work out what to do
 		 */
-
 		if (!(i2c->msg->flags & I2C_M_IGNORE_NAK)) {
 			if (iicstat & S3C2410_IICSTAT_LASTBIT) {
 				dev_dbg(i2c->dev, "WRITE: No Ack\n");
@@ -475,12 +468,13 @@ static int i2c_s3c_irq_nextbyte(struct s
 			byte = i2c->msg->buf[i2c->msg_ptr++];
 			writeb(byte, i2c->regs + S3C2410_IICDS);
 
-			/* delay after writing the byte to allow the
+			/*
+			 * delay after writing the byte to allow the
 			 * data setup time on the bus, as writing the
 			 * data to the register causes the first bit
 			 * to appear on SDA, and SCL will change as
-			 * soon as the interrupt is acknowledged */
-
+			 * soon as the interrupt is acknowledged
+			 */
 			ndelay(i2c->tx_setup);
 
 		} else if (!is_lastmsg(i2c)) {
@@ -496,10 +490,11 @@ static int i2c_s3c_irq_nextbyte(struct s
 			if (i2c->msg->flags & I2C_M_NOSTART) {
 
 				if (i2c->msg->flags & I2C_M_RD) {
-					/* cannot do this, the controller
+					/*
+					 * cannot do this, the controller
 					 * forces us to send a new START
-					 * when we change direction */
-
+					 * when we change direction
+					 */
 					s3c24xx_i2c_stop(i2c, -EINVAL);
 				}
 
@@ -512,17 +507,16 @@ static int i2c_s3c_irq_nextbyte(struct s
 
 		} else {
 			/* send stop */
-
 			s3c24xx_i2c_stop(i2c, 0);
 		}
 		break;
 
 	case STATE_READ:
-		/* we have a byte of data in the data register, do
+		/*
+		 * we have a byte of data in the data register, do
 		 * something with it, and then work out whether we are
 		 * going to do any more read/write
 		 */
-
 		byte = readb(i2c->regs + S3C2410_IICDS);
 		i2c->msg->buf[i2c->msg_ptr++] = byte;
 
@@ -537,9 +531,10 @@ static int i2c_s3c_irq_nextbyte(struct s
 				s3c24xx_i2c_disable_ack(i2c);
 
 		} else if (is_msgend(i2c)) {
-			/* ok, we've read the entire buffer, see if there
-			 * is anything else we need to do */
-
+			/*
+			 * ok, we've read the entire buffer, see if there
+			 * is anything else we need to do
+			 */
 			if (is_lastmsg(i2c)) {
 				/* last message, send stop and complete */
 				dev_dbg(i2c->dev, "READ: Send Stop\n");
@@ -568,11 +563,9 @@ static int i2c_s3c_irq_nextbyte(struct s
 	return ret;
 }
 
-/* s3c24xx_i2c_irq
- *
+/*
  * top level IRQ servicing routine
-*/
-
+ */
 static irqreturn_t s3c24xx_i2c_irq(int irqno, void *dev_id)
 {
 	struct s3c24xx_i2c *i2c = dev_id;
@@ -595,9 +588,10 @@ static irqreturn_t s3c24xx_i2c_irq(int i
 		goto out;
 	}
 
-	/* pretty much this leaves us with the fact that we've
-	 * transmitted or received whatever byte we last sent */
-
+	/*
+	 * pretty much this leaves us with the fact that we've
+	 * transmitted or received whatever byte we last sent
+	 */
 	i2c_s3c_irq_nextbyte(i2c, status);
 
  out:
@@ -630,11 +624,9 @@ static inline void s3c24xx_i2c_disable_b
 }
 
 
-/* s3c24xx_i2c_set_master
- *
+/*
  * get the i2c bus for a master transaction
-*/
-
+ */
 static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c)
 {
 	unsigned long iicstat;
@@ -652,11 +644,9 @@ static int s3c24xx_i2c_set_master(struct
 	return -ETIMEDOUT;
 }
 
-/* s3c24xx_i2c_wait_idle
- *
+/*
  * wait for the i2c bus to become idle.
-*/
-
+ */
 static void s3c24xx_i2c_wait_idle(struct s3c24xx_i2c *i2c)
 {
 	unsigned long iicstat;
@@ -706,11 +696,9 @@ static void s3c24xx_i2c_wait_idle(struct
 		dev_warn(i2c->dev, "timeout waiting for bus idle\n");
 }
 
-/* s3c24xx_i2c_doxfer
- *
+/*
  * this starts an i2c transfer
-*/
-
+ */
 static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
 			      struct i2c_msg *msgs, int num)
 {
@@ -749,9 +737,10 @@ static int s3c24xx_i2c_doxfer(struct s3c
 
 	ret = i2c->msg_idx;
 
-	/* having these next two as dev_err() makes life very
-	 * noisy when doing an i2cdetect */
-
+	/*
+	 * Having these next two as dev_err() makes life very
+	 * noisy when doing an i2cdetect
+	 */
 	if (timeout == 0)
 		dev_dbg(i2c->dev, "timeout\n");
 	else if (ret != num)
@@ -771,12 +760,10 @@ static int s3c24xx_i2c_doxfer(struct s3c
 	return ret;
 }
 
-/* s3c24xx_i2c_xfer
- *
+/*
  * first port of call from the i2c bus code when an message needs
  * transferring across the i2c bus.
-*/
-
+ */
 static int s3c24xx_i2c_xfer(struct i2c_adapter *adap,
 			struct i2c_msg *msgs, int num)
 {
@@ -814,17 +801,14 @@ static u32 s3c24xx_i2c_func(struct i2c_a
 }
 
 /* i2c bus registration info */
-
 static const struct i2c_algorithm s3c24xx_i2c_algorithm = {
 	.master_xfer		= s3c24xx_i2c_xfer,
 	.functionality		= s3c24xx_i2c_func,
 };
 
-/* s3c24xx_i2c_calcdivisor
- *
+/*
  * return the divisor settings for a given frequency
-*/
-
+ */
 static int s3c24xx_i2c_calcdivisor(unsigned long clkin, unsigned int wanted,
 				   unsigned int *div1, unsigned int *divs)
 {
@@ -850,13 +834,11 @@ static int s3c24xx_i2c_calcdivisor(unsig
 	return clkin / (calc_divs * calc_div1);
 }
 
-/* s3c24xx_i2c_clockrate
- *
+/*
  * work out a divisor for the user requested frequency setting,
  * either by the requested frequency, or scanning the acceptable
  * range of frequencies until something is found
-*/
-
+ */
 static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got)
 {
 	struct s3c2410_platform_i2c *pdata = i2c->pdata;
@@ -944,7 +926,7 @@ static int s3c24xx_i2c_cpufreq_transitio
 		i2c_unlock_adapter(&i2c->adap);
 
 		if (ret < 0)
-			dev_err(i2c->dev, "cannot find frequency\n");
+			dev_err(i2c->dev, "cannot find frequency (%d)\n", ret);
 		else
 			dev_info(i2c->dev, "setting freq %d\n", got);
 	}
@@ -995,7 +977,8 @@ static int s3c24xx_i2c_parse_dt_gpio(str
 
 		ret = gpio_request(gpio, "i2c-bus");
 		if (ret) {
-			dev_err(i2c->dev, "gpio [%d] request failed\n", gpio);
+			dev_err(i2c->dev, "gpio [%d] request failed (%d)\n",
+				gpio, ret);
 			goto free_gpio;
 		}
 	}
@@ -1028,11 +1011,9 @@ static void s3c24xx_i2c_dt_gpio_free(str
 }
 #endif
 
-/* s3c24xx_i2c_init
- *
+/*
  * initialise the controller, set the IO lines and frequency
-*/
-
+ */
 static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
 {
 	struct s3c2410_platform_i2c *pdata;
@@ -1068,11 +1049,9 @@ static int s3c24xx_i2c_init(struct s3c24
 }
 
 #ifdef CONFIG_OF
-/* s3c24xx_i2c_parse_dt
- *
+/*
  * Parse the device tree node and retreive the platform data.
-*/
-
+ */
 static void
 s3c24xx_i2c_parse_dt(struct device_node *np, struct s3c24xx_i2c *i2c)
 {
@@ -1105,17 +1084,9 @@ s3c24xx_i2c_parse_dt(struct device_node
 }
 #else
 static void
-s3c24xx_i2c_parse_dt(struct device_node *np, struct s3c24xx_i2c *i2c)
-{
-	return;
-}
+s3c24xx_i2c_parse_dt(struct device_node *np, struct s3c24xx_i2c *i2c) { }
 #endif
 
-/* s3c24xx_i2c_probe
- *
- * called by the bus driver when a suitable device is found
-*/
-
 static int s3c24xx_i2c_probe(struct platform_device *pdev)
 {
 	struct s3c24xx_i2c *i2c;
@@ -1156,7 +1127,6 @@ static int s3c24xx_i2c_probe(struct plat
 	init_waitqueue_head(&i2c->wait);
 
 	/* find the clock and enable it */
-
 	i2c->dev = &pdev->dev;
 	i2c->clk = devm_clk_get(&pdev->dev, "i2c");
 	if (IS_ERR(i2c->clk)) {
@@ -1166,9 +1136,7 @@ static int s3c24xx_i2c_probe(struct plat
 
 	dev_dbg(&pdev->dev, "clock source %p\n", i2c->clk);
 
-
 	/* map the registers */
-
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	i2c->regs = devm_ioremap_resource(&pdev->dev, res);
 
@@ -1179,33 +1147,35 @@ static int s3c24xx_i2c_probe(struct plat
 		i2c->regs, res);
 
 	/* setup info block for the i2c core */
-
 	i2c->adap.algo_data = i2c;
 	i2c->adap.dev.parent = &pdev->dev;
-
 	i2c->pctrl = devm_pinctrl_get_select_default(i2c->dev);
 
 	/* inititalise the i2c gpio lines */
-
-	if (i2c->pdata->cfg_gpio) {
+	if (i2c->pdata->cfg_gpio)
 		i2c->pdata->cfg_gpio(to_platform_device(i2c->dev));
-	} else if (IS_ERR(i2c->pctrl) && s3c24xx_i2c_parse_dt_gpio(i2c)) {
+	else if (IS_ERR(i2c->pctrl) && s3c24xx_i2c_parse_dt_gpio(i2c))
 		return -EINVAL;
-	}
 
 	/* initialise the i2c controller */
+	ret = clk_prepare_enable(i2c->clk);
+	if (ret) {
+		dev_err(&pdev->dev, "I2C clock enable failed\n");
+		return ret;
+	}
 
-	clk_prepare_enable(i2c->clk);
 	ret = s3c24xx_i2c_init(i2c);
 	clk_disable(i2c->clk);
 	if (ret != 0) {
 		dev_err(&pdev->dev, "I2C controller init failed\n");
+		clk_unprepare(i2c->clk);
 		return ret;
 	}
-	/* find the IRQ for this unit (note, this relies on the init call to
+
+	/*
+	 * find the IRQ for this unit (note, this relies on the init call to
 	 * ensure no current IRQs pending
 	 */
-
 	if (!(i2c->quirks & QUIRK_POLL)) {
 		i2c->irq = ret = platform_get_irq(pdev, 0);
 		if (ret <= 0) {
@@ -1214,9 +1184,8 @@ static int s3c24xx_i2c_probe(struct plat
 			return ret;
 		}
 
-	ret = devm_request_irq(&pdev->dev, i2c->irq, s3c24xx_i2c_irq, 0,
-				dev_name(&pdev->dev), i2c);
-
+		ret = devm_request_irq(&pdev->dev, i2c->irq, s3c24xx_i2c_irq,
+				       0, dev_name(&pdev->dev), i2c);
 		if (ret != 0) {
 			dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq);
 			clk_unprepare(i2c->clk);
@@ -1231,12 +1200,12 @@ static int s3c24xx_i2c_probe(struct plat
 		return ret;
 	}
 
-	/* Note, previous versions of the driver used i2c_add_adapter()
+	/*
+	 * Note, previous versions of the driver used i2c_add_adapter()
 	 * to add the bus at any number. We now pass the bus number via
 	 * the platform data, so if unset it will now default to always
 	 * being bus 0.
 	 */
-
 	i2c->adap.nr = i2c->pdata->bus_num;
 	i2c->adap.dev.of_node = pdev->dev.of_node;
 
@@ -1257,11 +1226,6 @@ static int s3c24xx_i2c_probe(struct plat
 	return 0;
 }
 
-/* s3c24xx_i2c_remove
- *
- * called when device is removed from the bus
-*/
-
 static int s3c24xx_i2c_remove(struct platform_device *pdev)
 {
 	struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev);
@@ -1316,14 +1280,8 @@ static int s3c24xx_i2c_resume_noirq(stru
 
 #ifdef CONFIG_PM
 static const struct dev_pm_ops s3c24xx_i2c_dev_pm_ops = {
-#ifdef CONFIG_PM_SLEEP
-	.suspend_noirq = s3c24xx_i2c_suspend_noirq,
-	.resume_noirq = s3c24xx_i2c_resume_noirq,
-	.freeze_noirq = s3c24xx_i2c_suspend_noirq,
-	.thaw_noirq = s3c24xx_i2c_resume_noirq,
-	.poweroff_noirq = s3c24xx_i2c_suspend_noirq,
-	.restore_noirq = s3c24xx_i2c_resume_noirq,
-#endif
+	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(s3c24xx_i2c_suspend_noirq,
+				      s3c24xx_i2c_resume_noirq)
 };
 
 #define S3C24XX_DEV_PM_OPS (&s3c24xx_i2c_dev_pm_ops)
@@ -1331,8 +1289,6 @@ static const struct dev_pm_ops s3c24xx_i
 #define S3C24XX_DEV_PM_OPS NULL
 #endif
 
-/* device driver for platform bus bits */
-
 static struct platform_driver s3c24xx_i2c_driver = {
 	.probe		= s3c24xx_i2c_probe,
 	.remove		= s3c24xx_i2c_remove,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/busses/i2c-sh_mobile.c linux-libre-4.7-gnu/drivers/i2c/busses/i2c-sh_mobile.c
--- linux-libre-4.6-gnu/drivers/i2c/busses/i2c-sh_mobile.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/busses/i2c-sh_mobile.c	2016-07-24 15:23:50.000000000 -0400
@@ -398,8 +398,7 @@ static void sh_mobile_i2c_get_data(struc
 {
 	switch (pd->pos) {
 	case -1:
-		*buf = (pd->msg->addr & 0x7f) << 1;
-		*buf |= (pd->msg->flags & I2C_M_RD) ? 1 : 0;
+		*buf = i2c_8bit_addr_from_msg(pd->msg);
 		break;
 	default:
 		*buf = pd->msg->buf[pd->pos];
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/busses/i2c-sirf.c linux-libre-4.7-gnu/drivers/i2c/busses/i2c-sirf.c
--- linux-libre-4.6-gnu/drivers/i2c/busses/i2c-sirf.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/busses/i2c-sirf.c	2016-07-24 15:23:50.000000000 -0400
@@ -190,9 +190,7 @@ static void i2c_sirfsoc_set_address(stru
 
 	writel(regval, siic->base + SIRFSOC_I2C_CMD(siic->cmd_ptr++));
 
-	addr = msg->addr << 1;	/* Generate address */
-	if (msg->flags & I2C_M_RD)
-		addr |= 1;
+	addr = i2c_8bit_addr_from_msg(msg);
 
 	/* Reverse direction bit */
 	if (msg->flags & I2C_M_REV_DIR_ADDR)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/busses/i2c-st.c linux-libre-4.7-gnu/drivers/i2c/busses/i2c-st.c
--- linux-libre-4.6-gnu/drivers/i2c/busses/i2c-st.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/busses/i2c-st.c	2016-07-24 15:23:50.000000000 -0400
@@ -337,10 +337,42 @@ static void st_i2c_hw_config(struct st_i
 	writel_relaxed(val, i2c_dev->base + SSC_NOISE_SUPP_WIDTH_DATAOUT);
 }
 
+static int st_i2c_recover_bus(struct i2c_adapter *i2c_adap)
+{
+	struct st_i2c_dev *i2c_dev = i2c_get_adapdata(i2c_adap);
+	u32 ctl;
+
+	dev_dbg(i2c_dev->dev, "Trying to recover bus\n");
+
+	/*
+	 * SSP IP is dual role SPI/I2C to generate 9 clock pulses
+	 * we switch to SPI node, 9 bit words and write a 0. This
+	 * has been validate with a oscilloscope and is easier
+	 * than switching to GPIO mode.
+	 */
+
+	/* Disable interrupts */
+	writel_relaxed(0, i2c_dev->base + SSC_IEN);
+
+	st_i2c_hw_config(i2c_dev);
+
+	ctl = SSC_CTL_EN | SSC_CTL_MS |	SSC_CTL_EN_RX_FIFO | SSC_CTL_EN_TX_FIFO;
+	st_i2c_set_bits(i2c_dev->base + SSC_CTL, ctl);
+
+	st_i2c_clr_bits(i2c_dev->base + SSC_I2C, SSC_I2C_I2CM);
+	usleep_range(8000, 10000);
+
+	writel_relaxed(0, i2c_dev->base + SSC_TBUF);
+	usleep_range(2000, 4000);
+	st_i2c_set_bits(i2c_dev->base + SSC_I2C, SSC_I2C_I2CM);
+
+	return 0;
+}
+
 static int st_i2c_wait_free_bus(struct st_i2c_dev *i2c_dev)
 {
 	u32 sta;
-	int i;
+	int i, ret;
 
 	for (i = 0; i < 10; i++) {
 		sta = readl_relaxed(i2c_dev->base + SSC_STA);
@@ -352,6 +384,12 @@ static int st_i2c_wait_free_bus(struct s
 
 	dev_err(i2c_dev->dev, "bus not free (status = 0x%08x)\n", sta);
 
+	ret = i2c_recover_bus(&i2c_dev->adap);
+	if (ret) {
+		dev_err(i2c_dev->dev, "Failed to recover the bus (%d)\n", ret);
+		return ret;
+	}
+
 	return -EBUSY;
 }
 
@@ -614,8 +652,7 @@ static int st_i2c_xfer_msg(struct st_i2c
 	unsigned long timeout;
 	int ret;
 
-	c->addr		= (u8)(msg->addr << 1);
-	c->addr		|= (msg->flags & I2C_M_RD);
+	c->addr		= i2c_8bit_addr_from_msg(msg);
 	c->buf		= msg->buf;
 	c->count	= msg->len;
 	c->xfered	= 0;
@@ -744,6 +781,10 @@ static struct i2c_algorithm st_i2c_algo
 	.functionality = st_i2c_func,
 };
 
+static struct i2c_bus_recovery_info st_i2c_recovery_info = {
+	.recover_bus = st_i2c_recover_bus,
+};
+
 static int st_i2c_of_get_deglitch(struct device_node *np,
 		struct st_i2c_dev *i2c_dev)
 {
@@ -826,6 +867,7 @@ static int st_i2c_probe(struct platform_
 	adap->timeout = 2 * HZ;
 	adap->retries = 0;
 	adap->algo = &st_i2c_algo;
+	adap->bus_recovery_info = &st_i2c_recovery_info;
 	adap->dev.parent = &pdev->dev;
 	adap->dev.of_node = pdev->dev.of_node;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/busses/i2c-tegra.c linux-libre-4.7-gnu/drivers/i2c/busses/i2c-tegra.c
--- linux-libre-4.6-gnu/drivers/i2c/busses/i2c-tegra.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/busses/i2c-tegra.c	2016-07-24 15:23:50.000000000 -0400
@@ -38,6 +38,7 @@
 #define I2C_CNFG_DEBOUNCE_CNT_SHIFT		12
 #define I2C_CNFG_PACKET_MODE_EN			(1<<10)
 #define I2C_CNFG_NEW_MASTER_FSM			(1<<11)
+#define I2C_CNFG_MULTI_MASTER_MODE		(1<<17)
 #define I2C_STATUS				0x01C
 #define I2C_SL_CNFG				0x020
 #define I2C_SL_CNFG_NACK			(1<<1)
@@ -106,6 +107,9 @@
 #define I2C_SLV_CONFIG_LOAD			(1 << 1)
 #define I2C_TIMEOUT_CONFIG_LOAD			(1 << 2)
 
+#define I2C_CLKEN_OVERRIDE			0x090
+#define I2C_MST_CORE_CLKEN_OVR			(1 << 0)
+
 /*
  * msg_end_type: The bus control which need to be send at end of transfer.
  * @MSG_END_STOP: Send stop pulse at end of transfer.
@@ -143,6 +147,8 @@ struct tegra_i2c_hw_feature {
 	int clk_divisor_hs_mode;
 	int clk_divisor_std_fast_mode;
 	u16 clk_divisor_fast_plus_mode;
+	bool has_multi_master_mode;
+	bool has_slcg_override_reg;
 };
 
 /**
@@ -184,6 +190,7 @@ struct tegra_i2c_dev {
 	u32 bus_clk_rate;
 	u16 clk_divisor_non_hs_mode;
 	bool is_suspended;
+	bool is_multimaster_mode;
 };
 
 static void dvc_writel(struct tegra_i2c_dev *i2c_dev, u32 val, unsigned long reg)
@@ -438,6 +445,10 @@ static int tegra_i2c_init(struct tegra_i
 
 	val = I2C_CNFG_NEW_MASTER_FSM | I2C_CNFG_PACKET_MODE_EN |
 		(0x2 << I2C_CNFG_DEBOUNCE_CNT_SHIFT);
+
+	if (i2c_dev->hw->has_multi_master_mode)
+		val |= I2C_CNFG_MULTI_MASTER_MODE;
+
 	i2c_writel(i2c_dev, val, I2C_CNFG);
 	i2c_writel(i2c_dev, 0, I2C_INT_MASK);
 
@@ -463,25 +474,29 @@ static int tegra_i2c_init(struct tegra_i
 	if (tegra_i2c_flush_fifos(i2c_dev))
 		err = -ETIMEDOUT;
 
+	if (i2c_dev->is_multimaster_mode && i2c_dev->hw->has_slcg_override_reg)
+		i2c_writel(i2c_dev, I2C_MST_CORE_CLKEN_OVR, I2C_CLKEN_OVERRIDE);
+
 	if (i2c_dev->hw->has_config_load_reg) {
 		i2c_writel(i2c_dev, I2C_MSTR_CONFIG_LOAD, I2C_CONFIG_LOAD);
 		while (i2c_readl(i2c_dev, I2C_CONFIG_LOAD) != 0) {
 			if (time_after(jiffies, timeout)) {
 				dev_warn(i2c_dev->dev,
 					"timeout waiting for config load\n");
-				return -ETIMEDOUT;
+				err = -ETIMEDOUT;
+				goto err;
 			}
 			msleep(1);
 		}
 	}
 
-	tegra_i2c_clock_disable(i2c_dev);
-
 	if (i2c_dev->irq_disabled) {
 		i2c_dev->irq_disabled = 0;
 		enable_irq(i2c_dev->irq);
 	}
 
+err:
+	tegra_i2c_clock_disable(i2c_dev);
 	return err;
 }
 
@@ -688,6 +703,20 @@ static u32 tegra_i2c_func(struct i2c_ada
 	return ret;
 }
 
+static void tegra_i2c_parse_dt(struct tegra_i2c_dev *i2c_dev)
+{
+	struct device_node *np = i2c_dev->dev->of_node;
+	int ret;
+
+	ret = of_property_read_u32(np, "clock-frequency",
+			&i2c_dev->bus_clk_rate);
+	if (ret)
+		i2c_dev->bus_clk_rate = 100000; /* default clock rate */
+
+	i2c_dev->is_multimaster_mode = of_property_read_bool(np,
+			"multi-master");
+}
+
 static const struct i2c_algorithm tegra_i2c_algo = {
 	.master_xfer	= tegra_i2c_xfer,
 	.functionality	= tegra_i2c_func,
@@ -707,6 +736,8 @@ static const struct tegra_i2c_hw_feature
 	.clk_divisor_std_fast_mode = 0,
 	.clk_divisor_fast_plus_mode = 0,
 	.has_config_load_reg = false,
+	.has_multi_master_mode = false,
+	.has_slcg_override_reg = false,
 };
 
 static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
@@ -717,6 +748,8 @@ static const struct tegra_i2c_hw_feature
 	.clk_divisor_std_fast_mode = 0,
 	.clk_divisor_fast_plus_mode = 0,
 	.has_config_load_reg = false,
+	.has_multi_master_mode = false,
+	.has_slcg_override_reg = false,
 };
 
 static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {
@@ -727,6 +760,8 @@ static const struct tegra_i2c_hw_feature
 	.clk_divisor_std_fast_mode = 0x19,
 	.clk_divisor_fast_plus_mode = 0x10,
 	.has_config_load_reg = false,
+	.has_multi_master_mode = false,
+	.has_slcg_override_reg = false,
 };
 
 static const struct tegra_i2c_hw_feature tegra124_i2c_hw = {
@@ -737,10 +772,25 @@ static const struct tegra_i2c_hw_feature
 	.clk_divisor_std_fast_mode = 0x19,
 	.clk_divisor_fast_plus_mode = 0x10,
 	.has_config_load_reg = true,
+	.has_multi_master_mode = false,
+	.has_slcg_override_reg = true,
+};
+
+static const struct tegra_i2c_hw_feature tegra210_i2c_hw = {
+	.has_continue_xfer_support = true,
+	.has_per_pkt_xfer_complete_irq = true,
+	.has_single_clk_source = true,
+	.clk_divisor_hs_mode = 1,
+	.clk_divisor_std_fast_mode = 0x19,
+	.clk_divisor_fast_plus_mode = 0x10,
+	.has_config_load_reg = true,
+	.has_multi_master_mode = true,
+	.has_slcg_override_reg = true,
 };
 
 /* Match table for of_platform binding */
 static const struct of_device_id tegra_i2c_of_match[] = {
+	{ .compatible = "nvidia,tegra210-i2c", .data = &tegra210_i2c_hw, },
 	{ .compatible = "nvidia,tegra124-i2c", .data = &tegra124_i2c_hw, },
 	{ .compatible = "nvidia,tegra114-i2c", .data = &tegra114_i2c_hw, },
 	{ .compatible = "nvidia,tegra30-i2c", .data = &tegra30_i2c_hw, },
@@ -797,10 +847,7 @@ static int tegra_i2c_probe(struct platfo
 		return PTR_ERR(i2c_dev->rst);
 	}
 
-	ret = of_property_read_u32(i2c_dev->dev->of_node, "clock-frequency",
-					&i2c_dev->bus_clk_rate);
-	if (ret)
-		i2c_dev->bus_clk_rate = 100000; /* default clock rate */
+	tegra_i2c_parse_dt(i2c_dev);
 
 	i2c_dev->hw = &tegra20_i2c_hw;
 
@@ -853,17 +900,26 @@ static int tegra_i2c_probe(struct platfo
 		goto unprepare_fast_clk;
 	}
 
+	if (i2c_dev->is_multimaster_mode) {
+		ret = clk_enable(i2c_dev->div_clk);
+		if (ret < 0) {
+			dev_err(i2c_dev->dev, "div_clk enable failed %d\n",
+				ret);
+			goto unprepare_div_clk;
+		}
+	}
+
 	ret = tegra_i2c_init(i2c_dev);
 	if (ret) {
 		dev_err(&pdev->dev, "Failed to initialize i2c controller");
-		goto unprepare_div_clk;
+		goto disable_div_clk;
 	}
 
 	ret = devm_request_irq(&pdev->dev, i2c_dev->irq,
 			tegra_i2c_isr, 0, dev_name(&pdev->dev), i2c_dev);
 	if (ret) {
 		dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq);
-		goto unprepare_div_clk;
+		goto disable_div_clk;
 	}
 
 	i2c_set_adapdata(&i2c_dev->adapter, i2c_dev);
@@ -878,11 +934,15 @@ static int tegra_i2c_probe(struct platfo
 	ret = i2c_add_numbered_adapter(&i2c_dev->adapter);
 	if (ret) {
 		dev_err(&pdev->dev, "Failed to add I2C adapter\n");
-		goto unprepare_div_clk;
+		goto disable_div_clk;
 	}
 
 	return 0;
 
+disable_div_clk:
+	if (i2c_dev->is_multimaster_mode)
+		clk_disable(i2c_dev->div_clk);
+
 unprepare_div_clk:
 	clk_unprepare(i2c_dev->div_clk);
 
@@ -898,6 +958,9 @@ static int tegra_i2c_remove(struct platf
 	struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
 	i2c_del_adapter(&i2c_dev->adapter);
 
+	if (i2c_dev->is_multimaster_mode)
+		clk_disable(i2c_dev->div_clk);
+
 	clk_unprepare(i2c_dev->div_clk);
 	if (!i2c_dev->hw->has_single_clk_source)
 		clk_unprepare(i2c_dev->fast_clk);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/busses/i2c-uniphier.c linux-libre-4.7-gnu/drivers/i2c/busses/i2c-uniphier.c
--- linux-libre-4.6-gnu/drivers/i2c/busses/i2c-uniphier.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/busses/i2c-uniphier.c	2016-07-24 15:23:50.000000000 -0400
@@ -381,7 +381,7 @@ static int uniphier_i2c_probe(struct pla
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
-		dev_err(dev, "failed to get IRQ number");
+		dev_err(dev, "failed to get IRQ number\n");
 		return irq;
 	}
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/busses/i2c-uniphier-f.c linux-libre-4.7-gnu/drivers/i2c/busses/i2c-uniphier-f.c
--- linux-libre-4.6-gnu/drivers/i2c/busses/i2c-uniphier-f.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/busses/i2c-uniphier-f.c	2016-07-24 15:23:50.000000000 -0400
@@ -524,7 +524,7 @@ static int uniphier_fi2c_probe(struct pl
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
-		dev_err(dev, "failed to get IRQ number");
+		dev_err(dev, "failed to get IRQ number\n");
 		return irq;
 	}
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/busses/Kconfig linux-libre-4.7-gnu/drivers/i2c/busses/Kconfig
--- linux-libre-4.6-gnu/drivers/i2c/busses/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/busses/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -663,7 +663,7 @@ config I2C_MT65XX
 
 config I2C_MV64XXX
 	tristate "Marvell mv64xxx I2C Controller"
-	depends on MV64X60 || PLAT_ORION || ARCH_SUNXI
+	depends on MV64X60 || PLAT_ORION || ARCH_SUNXI || ARCH_MVEBU
 	help
 	  If you say yes to this option, support will be included for the
 	  built-in I2C interface on the Marvell 64xxx line of host bridges.
@@ -965,7 +965,7 @@ config I2C_XILINX
 
 config I2C_XLR
 	tristate "Netlogic XLR and Sigma Designs I2C support"
-	depends on CPU_XLR || ARCH_TANGOX
+	depends on CPU_XLR || ARCH_TANGO
 	help
 	  This driver enables support for the on-chip I2C interface of
 	  the Netlogic XLR/XLS MIPS processors and Sigma Designs SOCs.
@@ -985,6 +985,7 @@ config I2C_XLP9XX
 
 config I2C_RCAR
 	tristate "Renesas R-Car I2C Controller"
+	depends on HAS_DMA
 	depends on ARCH_RENESAS || COMPILE_TEST
 	select I2C_SLAVE
 	help
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/i2c-boardinfo.c linux-libre-4.7-gnu/drivers/i2c/i2c-boardinfo.c
--- linux-libre-4.6-gnu/drivers/i2c/i2c-boardinfo.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/i2c-boardinfo.c	2016-07-24 15:23:50.000000000 -0400
@@ -56,9 +56,7 @@ EXPORT_SYMBOL_GPL(__i2c_first_dynamic_bu
  * The board info passed can safely be __initdata, but be careful of embedded
  * pointers (for platform_data, functions, etc) since that won't be copied.
  */
-int __init
-i2c_register_board_info(int busnum,
-	struct i2c_board_info const *info, unsigned len)
+int i2c_register_board_info(int busnum, struct i2c_board_info const *info, unsigned len)
 {
 	int status;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/i2c-core.c linux-libre-4.7-gnu/drivers/i2c/i2c-core.c
--- linux-libre-4.6-gnu/drivers/i2c/i2c-core.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/i2c-core.c	2016-07-24 15:23:50.000000000 -0400
@@ -954,48 +954,40 @@ static int i2c_check_addr_busy(struct i2
 }
 
 /**
- * i2c_lock_adapter - Get exclusive access to an I2C bus segment
+ * i2c_adapter_lock_bus - Get exclusive access to an I2C bus segment
  * @adapter: Target I2C bus segment
+ * @flags: I2C_LOCK_ROOT_ADAPTER locks the root i2c adapter, I2C_LOCK_SEGMENT
+ *	locks only this branch in the adapter tree
  */
-void i2c_lock_adapter(struct i2c_adapter *adapter)
+static void i2c_adapter_lock_bus(struct i2c_adapter *adapter,
+				 unsigned int flags)
 {
-	struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter);
-
-	if (parent)
-		i2c_lock_adapter(parent);
-	else
-		rt_mutex_lock(&adapter->bus_lock);
+	rt_mutex_lock(&adapter->bus_lock);
 }
-EXPORT_SYMBOL_GPL(i2c_lock_adapter);
 
 /**
- * i2c_trylock_adapter - Try to get exclusive access to an I2C bus segment
+ * i2c_adapter_trylock_bus - Try to get exclusive access to an I2C bus segment
  * @adapter: Target I2C bus segment
+ * @flags: I2C_LOCK_ROOT_ADAPTER trylocks the root i2c adapter, I2C_LOCK_SEGMENT
+ *	trylocks only this branch in the adapter tree
  */
-static int i2c_trylock_adapter(struct i2c_adapter *adapter)
+static int i2c_adapter_trylock_bus(struct i2c_adapter *adapter,
+				   unsigned int flags)
 {
-	struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter);
-
-	if (parent)
-		return i2c_trylock_adapter(parent);
-	else
-		return rt_mutex_trylock(&adapter->bus_lock);
+	return rt_mutex_trylock(&adapter->bus_lock);
 }
 
 /**
- * i2c_unlock_adapter - Release exclusive access to an I2C bus segment
+ * i2c_adapter_unlock_bus - Release exclusive access to an I2C bus segment
  * @adapter: Target I2C bus segment
+ * @flags: I2C_LOCK_ROOT_ADAPTER unlocks the root i2c adapter, I2C_LOCK_SEGMENT
+ *	unlocks only this branch in the adapter tree
  */
-void i2c_unlock_adapter(struct i2c_adapter *adapter)
+static void i2c_adapter_unlock_bus(struct i2c_adapter *adapter,
+				   unsigned int flags)
 {
-	struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter);
-
-	if (parent)
-		i2c_unlock_adapter(parent);
-	else
-		rt_mutex_unlock(&adapter->bus_lock);
+	rt_mutex_unlock(&adapter->bus_lock);
 }
-EXPORT_SYMBOL_GPL(i2c_unlock_adapter);
 
 static void i2c_dev_set_name(struct i2c_adapter *adap,
 			     struct i2c_client *client)
@@ -1541,7 +1533,14 @@ static int i2c_register_adapter(struct i
 		return -EINVAL;
 	}
 
+	if (!adap->lock_bus) {
+		adap->lock_bus = i2c_adapter_lock_bus;
+		adap->trylock_bus = i2c_adapter_trylock_bus;
+		adap->unlock_bus = i2c_adapter_unlock_bus;
+	}
+
 	rt_mutex_init(&adap->bus_lock);
+	rt_mutex_init(&adap->mux_lock);
 	mutex_init(&adap->userspace_clients_lock);
 	INIT_LIST_HEAD(&adap->userspace_clients);
 
@@ -1559,6 +1558,7 @@ static int i2c_register_adapter(struct i
 	dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);
 
 	pm_runtime_no_callbacks(&adap->dev);
+	pm_suspend_ignore_children(&adap->dev, true);
 	pm_runtime_enable(&adap->dev);
 
 #ifdef CONFIG_I2C_COMPAT
@@ -1594,10 +1594,12 @@ static int i2c_register_adapter(struct i
 
 			bri->get_scl = get_scl_gpio_value;
 			bri->set_scl = set_scl_gpio_value;
-		} else if (!bri->set_scl || !bri->get_scl) {
+		} else if (bri->recover_bus == i2c_generic_scl_recovery) {
 			/* Generic SCL recovery */
-			dev_err(&adap->dev, "No {get|set}_gpio() found, not using recovery\n");
-			adap->bus_recovery_info = NULL;
+			if (!bri->set_scl || !bri->get_scl) {
+				dev_err(&adap->dev, "No {get|set}_scl() found, not using recovery\n");
+				adap->bus_recovery_info = NULL;
+			}
 		}
 	}
 
@@ -2309,16 +2311,16 @@ int i2c_transfer(struct i2c_adapter *ada
 #endif
 
 		if (in_atomic() || irqs_disabled()) {
-			ret = i2c_trylock_adapter(adap);
+			ret = adap->trylock_bus(adap, I2C_LOCK_SEGMENT);
 			if (!ret)
 				/* I2C activity is ongoing. */
 				return -EAGAIN;
 		} else {
-			i2c_lock_adapter(adap);
+			i2c_lock_bus(adap, I2C_LOCK_SEGMENT);
 		}
 
 		ret = __i2c_transfer(adap, msgs, num);
-		i2c_unlock_adapter(adap);
+		i2c_unlock_bus(adap, I2C_LOCK_SEGMENT);
 
 		return ret;
 	} else {
@@ -2646,7 +2648,7 @@ static u8 i2c_smbus_pec(u8 crc, u8 *p, s
 static u8 i2c_smbus_msg_pec(u8 pec, struct i2c_msg *msg)
 {
 	/* The address will be sent first */
-	u8 addr = (msg->addr << 1) | !!(msg->flags & I2C_M_RD);
+	u8 addr = i2c_8bit_addr_from_msg(msg);
 	pec = i2c_smbus_pec(pec, &addr, 1);
 
 	/* The data buffer follows */
@@ -3093,7 +3095,7 @@ s32 i2c_smbus_xfer(struct i2c_adapter *a
 	flags &= I2C_M_TEN | I2C_CLIENT_PEC | I2C_CLIENT_SCCB;
 
 	if (adapter->algo->smbus_xfer) {
-		i2c_lock_adapter(adapter);
+		i2c_lock_bus(adapter, I2C_LOCK_SEGMENT);
 
 		/* Retry automatically on arbitration loss */
 		orig_jiffies = jiffies;
@@ -3107,7 +3109,7 @@ s32 i2c_smbus_xfer(struct i2c_adapter *a
 				       orig_jiffies + adapter->timeout))
 				break;
 		}
-		i2c_unlock_adapter(adapter);
+		i2c_unlock_bus(adapter, I2C_LOCK_SEGMENT);
 
 		if (res != -EOPNOTSUPP || !adapter->algo->master_xfer)
 			goto trace;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/i2c-dev.c linux-libre-4.7-gnu/drivers/i2c/i2c-dev.c
--- linux-libre-4.6-gnu/drivers/i2c/i2c-dev.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/i2c-dev.c	2016-07-24 15:23:50.000000000 -0400
@@ -22,6 +22,7 @@
 
 /* The I2C_RDWR ioctl code is written by Kolja Waschk <waschk@telos.de> */
 
+#include <linux/cdev.h>
 #include <linux/device.h>
 #include <linux/fs.h>
 #include <linux/i2c-dev.h>
@@ -47,9 +48,10 @@ struct i2c_dev {
 	struct list_head list;
 	struct i2c_adapter *adap;
 	struct device *dev;
+	struct cdev cdev;
 };
 
-#define I2C_MINORS	256
+#define I2C_MINORS	MINORMASK
 static LIST_HEAD(i2c_dev_list);
 static DEFINE_SPINLOCK(i2c_dev_list_lock);
 
@@ -89,7 +91,7 @@ static struct i2c_dev *get_free_i2c_dev(
 	return i2c_dev;
 }
 
-static void return_i2c_dev(struct i2c_dev *i2c_dev)
+static void put_i2c_dev(struct i2c_dev *i2c_dev)
 {
 	spin_lock(&i2c_dev_list_lock);
 	list_del(&i2c_dev->list);
@@ -552,6 +554,12 @@ static int i2cdev_attach_adapter(struct
 	if (IS_ERR(i2c_dev))
 		return PTR_ERR(i2c_dev);
 
+	cdev_init(&i2c_dev->cdev, &i2cdev_fops);
+	i2c_dev->cdev.owner = THIS_MODULE;
+	res = cdev_add(&i2c_dev->cdev, MKDEV(I2C_MAJOR, adap->nr), 1);
+	if (res)
+		goto error_cdev;
+
 	/* register this i2c device with the driver core */
 	i2c_dev->dev = device_create(i2c_dev_class, &adap->dev,
 				     MKDEV(I2C_MAJOR, adap->nr), NULL,
@@ -565,7 +573,9 @@ static int i2cdev_attach_adapter(struct
 		 adap->name, adap->nr);
 	return 0;
 error:
-	return_i2c_dev(i2c_dev);
+	cdev_del(&i2c_dev->cdev);
+error_cdev:
+	put_i2c_dev(i2c_dev);
 	return res;
 }
 
@@ -582,7 +592,8 @@ static int i2cdev_detach_adapter(struct
 	if (!i2c_dev) /* attach_adapter must have failed */
 		return 0;
 
-	return_i2c_dev(i2c_dev);
+	cdev_del(&i2c_dev->cdev);
+	put_i2c_dev(i2c_dev);
 	device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));
 
 	pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name);
@@ -620,7 +631,7 @@ static int __init i2c_dev_init(void)
 
 	printk(KERN_INFO "i2c /dev entries driver\n");
 
-	res = register_chrdev(I2C_MAJOR, "i2c", &i2cdev_fops);
+	res = register_chrdev_region(MKDEV(I2C_MAJOR, 0), I2C_MINORS, "i2c");
 	if (res)
 		goto out;
 
@@ -644,7 +655,7 @@ static int __init i2c_dev_init(void)
 out_unreg_class:
 	class_destroy(i2c_dev_class);
 out_unreg_chrdev:
-	unregister_chrdev(I2C_MAJOR, "i2c");
+	unregister_chrdev_region(MKDEV(I2C_MAJOR, 0), I2C_MINORS);
 out:
 	printk(KERN_ERR "%s: Driver Initialisation failed\n", __FILE__);
 	return res;
@@ -655,7 +666,7 @@ static void __exit i2c_dev_exit(void)
 	bus_unregister_notifier(&i2c_bus_type, &i2cdev_notifier);
 	i2c_for_each_dev(NULL, i2cdev_detach_adapter);
 	class_destroy(i2c_dev_class);
-	unregister_chrdev(I2C_MAJOR, "i2c");
+	unregister_chrdev_region(MKDEV(I2C_MAJOR, 0), I2C_MINORS);
 }
 
 MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and "
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/i2c-mux.c linux-libre-4.7-gnu/drivers/i2c/i2c-mux.c
--- linux-libre-4.6-gnu/drivers/i2c/i2c-mux.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/i2c-mux.c	2016-07-24 15:23:50.000000000 -0400
@@ -31,30 +31,66 @@
 struct i2c_mux_priv {
 	struct i2c_adapter adap;
 	struct i2c_algorithm algo;
-
-	struct i2c_adapter *parent;
-	struct device *mux_dev;
-	void *mux_priv;
+	struct i2c_mux_core *muxc;
 	u32 chan_id;
-
-	int (*select)(struct i2c_adapter *, void *mux_priv, u32 chan_id);
-	int (*deselect)(struct i2c_adapter *, void *mux_priv, u32 chan_id);
 };
 
+static int __i2c_mux_master_xfer(struct i2c_adapter *adap,
+				 struct i2c_msg msgs[], int num)
+{
+	struct i2c_mux_priv *priv = adap->algo_data;
+	struct i2c_mux_core *muxc = priv->muxc;
+	struct i2c_adapter *parent = muxc->parent;
+	int ret;
+
+	/* Switch to the right mux port and perform the transfer. */
+
+	ret = muxc->select(muxc, priv->chan_id);
+	if (ret >= 0)
+		ret = __i2c_transfer(parent, msgs, num);
+	if (muxc->deselect)
+		muxc->deselect(muxc, priv->chan_id);
+
+	return ret;
+}
+
 static int i2c_mux_master_xfer(struct i2c_adapter *adap,
 			       struct i2c_msg msgs[], int num)
 {
 	struct i2c_mux_priv *priv = adap->algo_data;
-	struct i2c_adapter *parent = priv->parent;
+	struct i2c_mux_core *muxc = priv->muxc;
+	struct i2c_adapter *parent = muxc->parent;
 	int ret;
 
 	/* Switch to the right mux port and perform the transfer. */
 
-	ret = priv->select(parent, priv->mux_priv, priv->chan_id);
+	ret = muxc->select(muxc, priv->chan_id);
 	if (ret >= 0)
-		ret = __i2c_transfer(parent, msgs, num);
-	if (priv->deselect)
-		priv->deselect(parent, priv->mux_priv, priv->chan_id);
+		ret = i2c_transfer(parent, msgs, num);
+	if (muxc->deselect)
+		muxc->deselect(muxc, priv->chan_id);
+
+	return ret;
+}
+
+static int __i2c_mux_smbus_xfer(struct i2c_adapter *adap,
+				u16 addr, unsigned short flags,
+				char read_write, u8 command,
+				int size, union i2c_smbus_data *data)
+{
+	struct i2c_mux_priv *priv = adap->algo_data;
+	struct i2c_mux_core *muxc = priv->muxc;
+	struct i2c_adapter *parent = muxc->parent;
+	int ret;
+
+	/* Select the right mux port and perform the transfer. */
+
+	ret = muxc->select(muxc, priv->chan_id);
+	if (ret >= 0)
+		ret = parent->algo->smbus_xfer(parent, addr, flags,
+					read_write, command, size, data);
+	if (muxc->deselect)
+		muxc->deselect(muxc, priv->chan_id);
 
 	return ret;
 }
@@ -65,17 +101,18 @@ static int i2c_mux_smbus_xfer(struct i2c
 			      int size, union i2c_smbus_data *data)
 {
 	struct i2c_mux_priv *priv = adap->algo_data;
-	struct i2c_adapter *parent = priv->parent;
+	struct i2c_mux_core *muxc = priv->muxc;
+	struct i2c_adapter *parent = muxc->parent;
 	int ret;
 
 	/* Select the right mux port and perform the transfer. */
 
-	ret = priv->select(parent, priv->mux_priv, priv->chan_id);
+	ret = muxc->select(muxc, priv->chan_id);
 	if (ret >= 0)
-		ret = parent->algo->smbus_xfer(parent, addr, flags,
-					read_write, command, size, data);
-	if (priv->deselect)
-		priv->deselect(parent, priv->mux_priv, priv->chan_id);
+		ret = i2c_smbus_xfer(parent, addr, flags,
+				     read_write, command, size, data);
+	if (muxc->deselect)
+		muxc->deselect(muxc, priv->chan_id);
 
 	return ret;
 }
@@ -84,7 +121,7 @@ static int i2c_mux_smbus_xfer(struct i2c
 static u32 i2c_mux_functionality(struct i2c_adapter *adap)
 {
 	struct i2c_mux_priv *priv = adap->algo_data;
-	struct i2c_adapter *parent = priv->parent;
+	struct i2c_adapter *parent = priv->muxc->parent;
 
 	return parent->algo->functionality(parent);
 }
@@ -102,38 +139,167 @@ static unsigned int i2c_mux_parent_class
 	return class;
 }
 
-struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
-				struct device *mux_dev,
-				void *mux_priv, u32 force_nr, u32 chan_id,
-				unsigned int class,
-				int (*select) (struct i2c_adapter *,
-					       void *, u32),
-				int (*deselect) (struct i2c_adapter *,
-						 void *, u32))
+static void i2c_mux_lock_bus(struct i2c_adapter *adapter, unsigned int flags)
+{
+	struct i2c_mux_priv *priv = adapter->algo_data;
+	struct i2c_adapter *parent = priv->muxc->parent;
+
+	rt_mutex_lock(&parent->mux_lock);
+	if (!(flags & I2C_LOCK_ROOT_ADAPTER))
+		return;
+	i2c_lock_bus(parent, flags);
+}
+
+static int i2c_mux_trylock_bus(struct i2c_adapter *adapter, unsigned int flags)
+{
+	struct i2c_mux_priv *priv = adapter->algo_data;
+	struct i2c_adapter *parent = priv->muxc->parent;
+
+	if (!rt_mutex_trylock(&parent->mux_lock))
+		return 0;	/* mux_lock not locked, failure */
+	if (!(flags & I2C_LOCK_ROOT_ADAPTER))
+		return 1;	/* we only want mux_lock, success */
+	if (parent->trylock_bus(parent, flags))
+		return 1;	/* parent locked too, success */
+	rt_mutex_unlock(&parent->mux_lock);
+	return 0;		/* parent not locked, failure */
+}
+
+static void i2c_mux_unlock_bus(struct i2c_adapter *adapter, unsigned int flags)
+{
+	struct i2c_mux_priv *priv = adapter->algo_data;
+	struct i2c_adapter *parent = priv->muxc->parent;
+
+	if (flags & I2C_LOCK_ROOT_ADAPTER)
+		i2c_unlock_bus(parent, flags);
+	rt_mutex_unlock(&parent->mux_lock);
+}
+
+static void i2c_parent_lock_bus(struct i2c_adapter *adapter,
+				unsigned int flags)
+{
+	struct i2c_mux_priv *priv = adapter->algo_data;
+	struct i2c_adapter *parent = priv->muxc->parent;
+
+	rt_mutex_lock(&parent->mux_lock);
+	i2c_lock_bus(parent, flags);
+}
+
+static int i2c_parent_trylock_bus(struct i2c_adapter *adapter,
+				  unsigned int flags)
+{
+	struct i2c_mux_priv *priv = adapter->algo_data;
+	struct i2c_adapter *parent = priv->muxc->parent;
+
+	if (!rt_mutex_trylock(&parent->mux_lock))
+		return 0;	/* mux_lock not locked, failure */
+	if (parent->trylock_bus(parent, flags))
+		return 1;	/* parent locked too, success */
+	rt_mutex_unlock(&parent->mux_lock);
+	return 0;		/* parent not locked, failure */
+}
+
+static void i2c_parent_unlock_bus(struct i2c_adapter *adapter,
+				  unsigned int flags)
+{
+	struct i2c_mux_priv *priv = adapter->algo_data;
+	struct i2c_adapter *parent = priv->muxc->parent;
+
+	i2c_unlock_bus(parent, flags);
+	rt_mutex_unlock(&parent->mux_lock);
+}
+
+struct i2c_adapter *i2c_root_adapter(struct device *dev)
+{
+	struct device *i2c;
+	struct i2c_adapter *i2c_root;
+
+	/*
+	 * Walk up the device tree to find an i2c adapter, indicating
+	 * that this is an i2c client device. Check all ancestors to
+	 * handle mfd devices etc.
+	 */
+	for (i2c = dev; i2c; i2c = i2c->parent) {
+		if (i2c->type == &i2c_adapter_type)
+			break;
+	}
+	if (!i2c)
+		return NULL;
+
+	/* Continue up the tree to find the root i2c adapter */
+	i2c_root = to_i2c_adapter(i2c);
+	while (i2c_parent_is_i2c_adapter(i2c_root))
+		i2c_root = i2c_parent_is_i2c_adapter(i2c_root);
+
+	return i2c_root;
+}
+EXPORT_SYMBOL_GPL(i2c_root_adapter);
+
+struct i2c_mux_core *i2c_mux_alloc(struct i2c_adapter *parent,
+				   struct device *dev, int max_adapters,
+				   int sizeof_priv, u32 flags,
+				   int (*select)(struct i2c_mux_core *, u32),
+				   int (*deselect)(struct i2c_mux_core *, u32))
 {
+	struct i2c_mux_core *muxc;
+
+	muxc = devm_kzalloc(dev, sizeof(*muxc)
+			    + max_adapters * sizeof(muxc->adapter[0])
+			    + sizeof_priv, GFP_KERNEL);
+	if (!muxc)
+		return NULL;
+	if (sizeof_priv)
+		muxc->priv = &muxc->adapter[max_adapters];
+
+	muxc->parent = parent;
+	muxc->dev = dev;
+	if (flags & I2C_MUX_LOCKED)
+		muxc->mux_locked = true;
+	muxc->select = select;
+	muxc->deselect = deselect;
+	muxc->max_adapters = max_adapters;
+
+	return muxc;
+}
+EXPORT_SYMBOL_GPL(i2c_mux_alloc);
+
+int i2c_mux_add_adapter(struct i2c_mux_core *muxc,
+			u32 force_nr, u32 chan_id,
+			unsigned int class)
+{
+	struct i2c_adapter *parent = muxc->parent;
 	struct i2c_mux_priv *priv;
 	char symlink_name[20];
 	int ret;
 
-	priv = kzalloc(sizeof(struct i2c_mux_priv), GFP_KERNEL);
+	if (muxc->num_adapters >= muxc->max_adapters) {
+		dev_err(muxc->dev, "No room for more i2c-mux adapters\n");
+		return -EINVAL;
+	}
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 	if (!priv)
-		return NULL;
+		return -ENOMEM;
 
 	/* Set up private adapter data */
-	priv->parent = parent;
-	priv->mux_dev = mux_dev;
-	priv->mux_priv = mux_priv;
+	priv->muxc = muxc;
 	priv->chan_id = chan_id;
-	priv->select = select;
-	priv->deselect = deselect;
 
 	/* Need to do algo dynamically because we don't know ahead
 	 * of time what sort of physical adapter we'll be dealing with.
 	 */
-	if (parent->algo->master_xfer)
-		priv->algo.master_xfer = i2c_mux_master_xfer;
-	if (parent->algo->smbus_xfer)
-		priv->algo.smbus_xfer = i2c_mux_smbus_xfer;
+	if (parent->algo->master_xfer) {
+		if (muxc->mux_locked)
+			priv->algo.master_xfer = i2c_mux_master_xfer;
+		else
+			priv->algo.master_xfer = __i2c_mux_master_xfer;
+	}
+	if (parent->algo->smbus_xfer) {
+		if (muxc->mux_locked)
+			priv->algo.smbus_xfer = i2c_mux_smbus_xfer;
+		else
+			priv->algo.smbus_xfer = __i2c_mux_smbus_xfer;
+	}
 	priv->algo.functionality = i2c_mux_functionality;
 
 	/* Now fill out new adapter structure */
@@ -146,6 +312,15 @@ struct i2c_adapter *i2c_add_mux_adapter(
 	priv->adap.retries = parent->retries;
 	priv->adap.timeout = parent->timeout;
 	priv->adap.quirks = parent->quirks;
+	if (muxc->mux_locked) {
+		priv->adap.lock_bus = i2c_mux_lock_bus;
+		priv->adap.trylock_bus = i2c_mux_trylock_bus;
+		priv->adap.unlock_bus = i2c_mux_unlock_bus;
+	} else {
+		priv->adap.lock_bus = i2c_parent_lock_bus;
+		priv->adap.trylock_bus = i2c_parent_trylock_bus;
+		priv->adap.unlock_bus = i2c_parent_unlock_bus;
+	}
 
 	/* Sanity check on class */
 	if (i2c_mux_parent_classes(parent) & class)
@@ -159,11 +334,11 @@ struct i2c_adapter *i2c_add_mux_adapter(
 	 * Try to populate the mux adapter's of_node, expands to
 	 * nothing if !CONFIG_OF.
 	 */
-	if (mux_dev->of_node) {
+	if (muxc->dev->of_node) {
 		struct device_node *child;
 		u32 reg;
 
-		for_each_child_of_node(mux_dev->of_node, child) {
+		for_each_child_of_node(muxc->dev->of_node, child) {
 			ret = of_property_read_u32(child, "reg", &reg);
 			if (ret)
 				continue;
@@ -177,8 +352,9 @@ struct i2c_adapter *i2c_add_mux_adapter(
 	/*
 	 * Associate the mux channel with an ACPI node.
 	 */
-	if (has_acpi_companion(mux_dev))
-		acpi_preset_companion(&priv->adap.dev, ACPI_COMPANION(mux_dev),
+	if (has_acpi_companion(muxc->dev))
+		acpi_preset_companion(&priv->adap.dev,
+				      ACPI_COMPANION(muxc->dev),
 				      chan_id);
 
 	if (force_nr) {
@@ -192,35 +368,45 @@ struct i2c_adapter *i2c_add_mux_adapter(
 			"failed to add mux-adapter (error=%d)\n",
 			ret);
 		kfree(priv);
-		return NULL;
+		return ret;
 	}
 
-	WARN(sysfs_create_link(&priv->adap.dev.kobj, &mux_dev->kobj, "mux_device"),
-			       "can't create symlink to mux device\n");
+	WARN(sysfs_create_link(&priv->adap.dev.kobj, &muxc->dev->kobj,
+			       "mux_device"),
+	     "can't create symlink to mux device\n");
 
 	snprintf(symlink_name, sizeof(symlink_name), "channel-%u", chan_id);
-	WARN(sysfs_create_link(&mux_dev->kobj, &priv->adap.dev.kobj, symlink_name),
-			       "can't create symlink for channel %u\n", chan_id);
+	WARN(sysfs_create_link(&muxc->dev->kobj, &priv->adap.dev.kobj,
+			       symlink_name),
+	     "can't create symlink for channel %u\n", chan_id);
 	dev_info(&parent->dev, "Added multiplexed i2c bus %d\n",
 		 i2c_adapter_id(&priv->adap));
 
-	return &priv->adap;
+	muxc->adapter[muxc->num_adapters++] = &priv->adap;
+	return 0;
 }
-EXPORT_SYMBOL_GPL(i2c_add_mux_adapter);
+EXPORT_SYMBOL_GPL(i2c_mux_add_adapter);
 
-void i2c_del_mux_adapter(struct i2c_adapter *adap)
+void i2c_mux_del_adapters(struct i2c_mux_core *muxc)
 {
-	struct i2c_mux_priv *priv = adap->algo_data;
 	char symlink_name[20];
 
-	snprintf(symlink_name, sizeof(symlink_name), "channel-%u", priv->chan_id);
-	sysfs_remove_link(&priv->mux_dev->kobj, symlink_name);
+	while (muxc->num_adapters) {
+		struct i2c_adapter *adap = muxc->adapter[--muxc->num_adapters];
+		struct i2c_mux_priv *priv = adap->algo_data;
 
-	sysfs_remove_link(&priv->adap.dev.kobj, "mux_device");
-	i2c_del_adapter(adap);
-	kfree(priv);
+		muxc->adapter[muxc->num_adapters] = NULL;
+
+		snprintf(symlink_name, sizeof(symlink_name),
+			 "channel-%u", priv->chan_id);
+		sysfs_remove_link(&muxc->dev->kobj, symlink_name);
+
+		sysfs_remove_link(&priv->adap.dev.kobj, "mux_device");
+		i2c_del_adapter(adap);
+		kfree(priv);
+	}
 }
-EXPORT_SYMBOL_GPL(i2c_del_mux_adapter);
+EXPORT_SYMBOL_GPL(i2c_mux_del_adapters);
 
 MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
 MODULE_DESCRIPTION("I2C driver for multiplexed I2C busses");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/muxes/i2c-arb-gpio-challenge.c linux-libre-4.7-gnu/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
--- linux-libre-4.6-gnu/drivers/i2c/muxes/i2c-arb-gpio-challenge.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/muxes/i2c-arb-gpio-challenge.c	2016-07-24 15:23:50.000000000 -0400
@@ -28,8 +28,6 @@
 /**
  * struct i2c_arbitrator_data - Driver data for I2C arbitrator
  *
- * @parent: Parent adapter
- * @child: Child bus
  * @our_gpio: GPIO we'll use to claim.
  * @our_gpio_release: 0 if active high; 1 if active low; AKA if the GPIO ==
  *   this then consider it released.
@@ -42,8 +40,6 @@
  */
 
 struct i2c_arbitrator_data {
-	struct i2c_adapter *parent;
-	struct i2c_adapter *child;
 	int our_gpio;
 	int our_gpio_release;
 	int their_gpio;
@@ -59,9 +55,9 @@ struct i2c_arbitrator_data {
  *
  * Use the GPIO-based signalling protocol; return -EBUSY if we fail.
  */
-static int i2c_arbitrator_select(struct i2c_adapter *adap, void *data, u32 chan)
+static int i2c_arbitrator_select(struct i2c_mux_core *muxc, u32 chan)
 {
-	const struct i2c_arbitrator_data *arb = data;
+	const struct i2c_arbitrator_data *arb = i2c_mux_priv(muxc);
 	unsigned long stop_retry, stop_time;
 
 	/* Start a round of trying to claim the bus */
@@ -93,7 +89,7 @@ static int i2c_arbitrator_select(struct
 	/* Give up, release our claim */
 	gpio_set_value(arb->our_gpio, arb->our_gpio_release);
 	udelay(arb->slew_delay_us);
-	dev_err(&adap->dev, "Could not claim bus, timeout\n");
+	dev_err(muxc->dev, "Could not claim bus, timeout\n");
 	return -EBUSY;
 }
 
@@ -102,10 +98,9 @@ static int i2c_arbitrator_select(struct
  *
  * Release the I2C bus using the GPIO-based signalling protocol.
  */
-static int i2c_arbitrator_deselect(struct i2c_adapter *adap, void *data,
-				   u32 chan)
+static int i2c_arbitrator_deselect(struct i2c_mux_core *muxc, u32 chan)
 {
-	const struct i2c_arbitrator_data *arb = data;
+	const struct i2c_arbitrator_data *arb = i2c_mux_priv(muxc);
 
 	/* Release the bus and wait for the other master to notice */
 	gpio_set_value(arb->our_gpio, arb->our_gpio_release);
@@ -119,6 +114,7 @@ static int i2c_arbitrator_probe(struct p
 	struct device *dev = &pdev->dev;
 	struct device_node *np = dev->of_node;
 	struct device_node *parent_np;
+	struct i2c_mux_core *muxc;
 	struct i2c_arbitrator_data *arb;
 	enum of_gpio_flags gpio_flags;
 	unsigned long out_init;
@@ -134,12 +130,13 @@ static int i2c_arbitrator_probe(struct p
 		return -EINVAL;
 	}
 
-	arb = devm_kzalloc(dev, sizeof(*arb), GFP_KERNEL);
-	if (!arb) {
-		dev_err(dev, "Cannot allocate i2c_arbitrator_data\n");
+	muxc = i2c_mux_alloc(NULL, dev, 1, sizeof(*arb), 0,
+			     i2c_arbitrator_select, i2c_arbitrator_deselect);
+	if (!muxc)
 		return -ENOMEM;
-	}
-	platform_set_drvdata(pdev, arb);
+	arb = i2c_mux_priv(muxc);
+
+	platform_set_drvdata(pdev, muxc);
 
 	/* Request GPIOs */
 	ret = of_get_named_gpio_flags(np, "our-claim-gpio", 0, &gpio_flags);
@@ -196,21 +193,18 @@ static int i2c_arbitrator_probe(struct p
 		dev_err(dev, "Cannot parse i2c-parent\n");
 		return -EINVAL;
 	}
-	arb->parent = of_get_i2c_adapter_by_node(parent_np);
+	muxc->parent = of_get_i2c_adapter_by_node(parent_np);
 	of_node_put(parent_np);
-	if (!arb->parent) {
+	if (!muxc->parent) {
 		dev_err(dev, "Cannot find parent bus\n");
 		return -EPROBE_DEFER;
 	}
 
 	/* Actually add the mux adapter */
-	arb->child = i2c_add_mux_adapter(arb->parent, dev, arb, 0, 0, 0,
-					 i2c_arbitrator_select,
-					 i2c_arbitrator_deselect);
-	if (!arb->child) {
+	ret = i2c_mux_add_adapter(muxc, 0, 0, 0);
+	if (ret) {
 		dev_err(dev, "Failed to add adapter\n");
-		ret = -ENODEV;
-		i2c_put_adapter(arb->parent);
+		i2c_put_adapter(muxc->parent);
 	}
 
 	return ret;
@@ -218,11 +212,10 @@ static int i2c_arbitrator_probe(struct p
 
 static int i2c_arbitrator_remove(struct platform_device *pdev)
 {
-	struct i2c_arbitrator_data *arb = platform_get_drvdata(pdev);
-
-	i2c_del_mux_adapter(arb->child);
-	i2c_put_adapter(arb->parent);
+	struct i2c_mux_core *muxc = platform_get_drvdata(pdev);
 
+	i2c_mux_del_adapters(muxc);
+	i2c_put_adapter(muxc->parent);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/muxes/i2c-mux-gpio.c linux-libre-4.7-gnu/drivers/i2c/muxes/i2c-mux-gpio.c
--- linux-libre-4.6-gnu/drivers/i2c/muxes/i2c-mux-gpio.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/muxes/i2c-mux-gpio.c	2016-07-24 15:23:50.000000000 -0400
@@ -15,11 +15,10 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/gpio.h>
+#include "../../gpio/gpiolib.h"
 #include <linux/of_gpio.h>
 
 struct gpiomux {
-	struct i2c_adapter *parent;
-	struct i2c_adapter **adap; /* child busses */
 	struct i2c_mux_gpio_platform_data data;
 	unsigned gpio_base;
 };
@@ -33,18 +32,18 @@ static void i2c_mux_gpio_set(const struc
 					val & (1 << i));
 }
 
-static int i2c_mux_gpio_select(struct i2c_adapter *adap, void *data, u32 chan)
+static int i2c_mux_gpio_select(struct i2c_mux_core *muxc, u32 chan)
 {
-	struct gpiomux *mux = data;
+	struct gpiomux *mux = i2c_mux_priv(muxc);
 
 	i2c_mux_gpio_set(mux, chan);
 
 	return 0;
 }
 
-static int i2c_mux_gpio_deselect(struct i2c_adapter *adap, void *data, u32 chan)
+static int i2c_mux_gpio_deselect(struct i2c_mux_core *muxc, u32 chan)
 {
-	struct gpiomux *mux = data;
+	struct gpiomux *mux = i2c_mux_priv(muxc);
 
 	i2c_mux_gpio_set(mux, mux->data.idle);
 
@@ -136,19 +135,16 @@ static int i2c_mux_gpio_probe_dt(struct
 
 static int i2c_mux_gpio_probe(struct platform_device *pdev)
 {
+	struct i2c_mux_core *muxc;
 	struct gpiomux *mux;
 	struct i2c_adapter *parent;
-	int (*deselect) (struct i2c_adapter *, void *, u32);
+	struct i2c_adapter *root;
 	unsigned initial_state, gpio_base;
 	int i, ret;
 
 	mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL);
-	if (!mux) {
-		dev_err(&pdev->dev, "Cannot allocate gpiomux structure");
+	if (!mux)
 		return -ENOMEM;
-	}
-
-	platform_set_drvdata(pdev, mux);
 
 	if (!dev_get_platdata(&pdev->dev)) {
 		ret = i2c_mux_gpio_probe_dt(mux, pdev);
@@ -180,27 +176,32 @@ static int i2c_mux_gpio_probe(struct pla
 	if (!parent)
 		return -EPROBE_DEFER;
 
-	mux->parent = parent;
-	mux->gpio_base = gpio_base;
-
-	mux->adap = devm_kzalloc(&pdev->dev,
-				 sizeof(*mux->adap) * mux->data.n_values,
-				 GFP_KERNEL);
-	if (!mux->adap) {
-		dev_err(&pdev->dev, "Cannot allocate i2c_adapter structure");
+	muxc = i2c_mux_alloc(parent, &pdev->dev, mux->data.n_values, 0, 0,
+			     i2c_mux_gpio_select, NULL);
+	if (!muxc) {
 		ret = -ENOMEM;
 		goto alloc_failed;
 	}
+	muxc->priv = mux;
+
+	platform_set_drvdata(pdev, muxc);
+
+	root = i2c_root_adapter(&parent->dev);
+
+	muxc->mux_locked = true;
+	mux->gpio_base = gpio_base;
 
 	if (mux->data.idle != I2C_MUX_GPIO_NO_IDLE) {
 		initial_state = mux->data.idle;
-		deselect = i2c_mux_gpio_deselect;
+		muxc->deselect = i2c_mux_gpio_deselect;
 	} else {
 		initial_state = mux->data.values[0];
-		deselect = NULL;
 	}
 
 	for (i = 0; i < mux->data.n_gpios; i++) {
+		struct device *gpio_dev;
+		struct gpio_desc *gpio_desc;
+
 		ret = gpio_request(gpio_base + mux->data.gpios[i], "i2c-mux-gpio");
 		if (ret) {
 			dev_err(&pdev->dev, "Failed to request GPIO %d\n",
@@ -217,17 +218,24 @@ static int i2c_mux_gpio_probe(struct pla
 			i++;	/* gpio_request above succeeded, so must free */
 			goto err_request_gpio;
 		}
+
+		if (!muxc->mux_locked)
+			continue;
+
+		gpio_desc = gpio_to_desc(gpio_base + mux->data.gpios[i]);
+		gpio_dev = &gpio_desc->gdev->dev;
+		muxc->mux_locked = i2c_root_adapter(gpio_dev) == root;
 	}
 
+	if (muxc->mux_locked)
+		dev_info(&pdev->dev, "mux-locked i2c mux\n");
+
 	for (i = 0; i < mux->data.n_values; i++) {
 		u32 nr = mux->data.base_nr ? (mux->data.base_nr + i) : 0;
 		unsigned int class = mux->data.classes ? mux->data.classes[i] : 0;
 
-		mux->adap[i] = i2c_add_mux_adapter(parent, &pdev->dev, mux, nr,
-						   mux->data.values[i], class,
-						   i2c_mux_gpio_select, deselect);
-		if (!mux->adap[i]) {
-			ret = -ENODEV;
+		ret = i2c_mux_add_adapter(muxc, nr, mux->data.values[i], class);
+		if (ret) {
 			dev_err(&pdev->dev, "Failed to add adapter %d\n", i);
 			goto add_adapter_failed;
 		}
@@ -239,8 +247,7 @@ static int i2c_mux_gpio_probe(struct pla
 	return 0;
 
 add_adapter_failed:
-	for (; i > 0; i--)
-		i2c_del_mux_adapter(mux->adap[i - 1]);
+	i2c_mux_del_adapters(muxc);
 	i = mux->data.n_gpios;
 err_request_gpio:
 	for (; i > 0; i--)
@@ -253,16 +260,16 @@ alloc_failed:
 
 static int i2c_mux_gpio_remove(struct platform_device *pdev)
 {
-	struct gpiomux *mux = platform_get_drvdata(pdev);
+	struct i2c_mux_core *muxc = platform_get_drvdata(pdev);
+	struct gpiomux *mux = i2c_mux_priv(muxc);
 	int i;
 
-	for (i = 0; i < mux->data.n_values; i++)
-		i2c_del_mux_adapter(mux->adap[i]);
+	i2c_mux_del_adapters(muxc);
 
 	for (i = 0; i < mux->data.n_gpios; i++)
 		gpio_free(mux->gpio_base + mux->data.gpios[i]);
 
-	i2c_put_adapter(mux->parent);
+	i2c_put_adapter(muxc->parent);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/muxes/i2c-mux-pca9541.c linux-libre-4.7-gnu/drivers/i2c/muxes/i2c-mux-pca9541.c
--- linux-libre-4.6-gnu/drivers/i2c/muxes/i2c-mux-pca9541.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/muxes/i2c-mux-pca9541.c	2016-07-24 15:23:50.000000000 -0400
@@ -73,7 +73,7 @@
 #define SELECT_DELAY_LONG	1000
 
 struct pca9541 {
-	struct i2c_adapter *mux_adap;
+	struct i2c_client *client;
 	unsigned long select_timeout;
 	unsigned long arb_timeout;
 };
@@ -217,7 +217,8 @@ static const u8 pca9541_control[16] = {
  */
 static int pca9541_arbitrate(struct i2c_client *client)
 {
-	struct pca9541 *data = i2c_get_clientdata(client);
+	struct i2c_mux_core *muxc = i2c_get_clientdata(client);
+	struct pca9541 *data = i2c_mux_priv(muxc);
 	int reg;
 
 	reg = pca9541_reg_read(client, PCA9541_CONTROL);
@@ -285,9 +286,10 @@ static int pca9541_arbitrate(struct i2c_
 	return 0;
 }
 
-static int pca9541_select_chan(struct i2c_adapter *adap, void *client, u32 chan)
+static int pca9541_select_chan(struct i2c_mux_core *muxc, u32 chan)
 {
-	struct pca9541 *data = i2c_get_clientdata(client);
+	struct pca9541 *data = i2c_mux_priv(muxc);
+	struct i2c_client *client = data->client;
 	int ret;
 	unsigned long timeout = jiffies + ARB2_TIMEOUT;
 		/* give up after this time */
@@ -309,9 +311,11 @@ static int pca9541_select_chan(struct i2
 	return -ETIMEDOUT;
 }
 
-static int pca9541_release_chan(struct i2c_adapter *adap,
-				void *client, u32 chan)
+static int pca9541_release_chan(struct i2c_mux_core *muxc, u32 chan)
 {
+	struct pca9541 *data = i2c_mux_priv(muxc);
+	struct i2c_client *client = data->client;
+
 	pca9541_release_bus(client);
 	return 0;
 }
@@ -324,20 +328,13 @@ static int pca9541_probe(struct i2c_clie
 {
 	struct i2c_adapter *adap = client->adapter;
 	struct pca954x_platform_data *pdata = dev_get_platdata(&client->dev);
+	struct i2c_mux_core *muxc;
 	struct pca9541 *data;
 	int force;
-	int ret = -ENODEV;
+	int ret;
 
 	if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE_DATA))
-		goto err;
-
-	data = kzalloc(sizeof(struct pca9541), GFP_KERNEL);
-	if (!data) {
-		ret = -ENOMEM;
-		goto err;
-	}
-
-	i2c_set_clientdata(client, data);
+		return -ENODEV;
 
 	/*
 	 * I2C accesses are unprotected here.
@@ -352,34 +349,33 @@ static int pca9541_probe(struct i2c_clie
 	force = 0;
 	if (pdata)
 		force = pdata->modes[0].adap_id;
-	data->mux_adap = i2c_add_mux_adapter(adap, &client->dev, client,
-					     force, 0, 0,
-					     pca9541_select_chan,
-					     pca9541_release_chan);
+	muxc = i2c_mux_alloc(adap, &client->dev, 1, sizeof(*data), 0,
+			     pca9541_select_chan, pca9541_release_chan);
+	if (!muxc)
+		return -ENOMEM;
 
-	if (data->mux_adap == NULL) {
+	data = i2c_mux_priv(muxc);
+	data->client = client;
+
+	i2c_set_clientdata(client, muxc);
+
+	ret = i2c_mux_add_adapter(muxc, force, 0, 0);
+	if (ret) {
 		dev_err(&client->dev, "failed to register master selector\n");
-		goto exit_free;
+		return ret;
 	}
 
 	dev_info(&client->dev, "registered master selector for I2C %s\n",
 		 client->name);
 
 	return 0;
-
-exit_free:
-	kfree(data);
-err:
-	return ret;
 }
 
 static int pca9541_remove(struct i2c_client *client)
 {
-	struct pca9541 *data = i2c_get_clientdata(client);
-
-	i2c_del_mux_adapter(data->mux_adap);
+	struct i2c_mux_core *muxc = i2c_get_clientdata(client);
 
-	kfree(data);
+	i2c_mux_del_adapters(muxc);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/muxes/i2c-mux-pca954x.c linux-libre-4.7-gnu/drivers/i2c/muxes/i2c-mux-pca954x.c
--- linux-libre-4.6-gnu/drivers/i2c/muxes/i2c-mux-pca954x.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/muxes/i2c-mux-pca954x.c	2016-07-24 15:23:50.000000000 -0400
@@ -60,9 +60,10 @@ enum pca_type {
 
 struct pca954x {
 	enum pca_type type;
-	struct i2c_adapter *virt_adaps[PCA954X_MAX_NCHANS];
 
 	u8 last_chan;		/* last register value */
+	u8 deselect;
+	struct i2c_client *client;
 };
 
 struct chip_desc {
@@ -146,10 +147,10 @@ static int pca954x_reg_write(struct i2c_
 	return ret;
 }
 
-static int pca954x_select_chan(struct i2c_adapter *adap,
-			       void *client, u32 chan)
+static int pca954x_select_chan(struct i2c_mux_core *muxc, u32 chan)
 {
-	struct pca954x *data = i2c_get_clientdata(client);
+	struct pca954x *data = i2c_mux_priv(muxc);
+	struct i2c_client *client = data->client;
 	const struct chip_desc *chip = &chips[data->type];
 	u8 regval;
 	int ret = 0;
@@ -162,21 +163,24 @@ static int pca954x_select_chan(struct i2
 
 	/* Only select the channel if its different from the last channel */
 	if (data->last_chan != regval) {
-		ret = pca954x_reg_write(adap, client, regval);
+		ret = pca954x_reg_write(muxc->parent, client, regval);
 		data->last_chan = regval;
 	}
 
 	return ret;
 }
 
-static int pca954x_deselect_mux(struct i2c_adapter *adap,
-				void *client, u32 chan)
+static int pca954x_deselect_mux(struct i2c_mux_core *muxc, u32 chan)
 {
-	struct pca954x *data = i2c_get_clientdata(client);
+	struct pca954x *data = i2c_mux_priv(muxc);
+	struct i2c_client *client = data->client;
+
+	if (!(data->deselect & (1 << chan)))
+		return 0;
 
 	/* Deselect active channel */
 	data->last_chan = 0;
-	return pca954x_reg_write(adap, client, data->last_chan);
+	return pca954x_reg_write(muxc->parent, client, data->last_chan);
 }
 
 /*
@@ -191,17 +195,22 @@ static int pca954x_probe(struct i2c_clie
 	bool idle_disconnect_dt;
 	struct gpio_desc *gpio;
 	int num, force, class;
+	struct i2c_mux_core *muxc;
 	struct pca954x *data;
 	int ret;
 
 	if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE))
 		return -ENODEV;
 
-	data = devm_kzalloc(&client->dev, sizeof(struct pca954x), GFP_KERNEL);
-	if (!data)
+	muxc = i2c_mux_alloc(adap, &client->dev,
+			     PCA954X_MAX_NCHANS, sizeof(*data), 0,
+			     pca954x_select_chan, pca954x_deselect_mux);
+	if (!muxc)
 		return -ENOMEM;
+	data = i2c_mux_priv(muxc);
 
-	i2c_set_clientdata(client, data);
+	i2c_set_clientdata(client, muxc);
+	data->client = client;
 
 	/* Get the mux out of reset if a reset GPIO is specified. */
 	gpio = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_LOW);
@@ -238,16 +247,13 @@ static int pca954x_probe(struct i2c_clie
 				/* discard unconfigured channels */
 				break;
 			idle_disconnect_pd = pdata->modes[num].deselect_on_exit;
+			data->deselect |= (idle_disconnect_pd
+					   || idle_disconnect_dt) << num;
 		}
 
-		data->virt_adaps[num] =
-			i2c_add_mux_adapter(adap, &client->dev, client,
-				force, num, class, pca954x_select_chan,
-				(idle_disconnect_pd || idle_disconnect_dt)
-					? pca954x_deselect_mux : NULL);
+		ret = i2c_mux_add_adapter(muxc, force, num, class);
 
-		if (data->virt_adaps[num] == NULL) {
-			ret = -ENODEV;
+		if (ret) {
 			dev_err(&client->dev,
 				"failed to register multiplexed adapter"
 				" %d as bus %d\n", num, force);
@@ -263,23 +269,15 @@ static int pca954x_probe(struct i2c_clie
 	return 0;
 
 virt_reg_failed:
-	for (num--; num >= 0; num--)
-		i2c_del_mux_adapter(data->virt_adaps[num]);
+	i2c_mux_del_adapters(muxc);
 	return ret;
 }
 
 static int pca954x_remove(struct i2c_client *client)
 {
-	struct pca954x *data = i2c_get_clientdata(client);
-	const struct chip_desc *chip = &chips[data->type];
-	int i;
-
-	for (i = 0; i < chip->nchans; ++i)
-		if (data->virt_adaps[i]) {
-			i2c_del_mux_adapter(data->virt_adaps[i]);
-			data->virt_adaps[i] = NULL;
-		}
+	struct i2c_mux_core *muxc = i2c_get_clientdata(client);
 
+	i2c_mux_del_adapters(muxc);
 	return 0;
 }
 
@@ -287,7 +285,8 @@ static int pca954x_remove(struct i2c_cli
 static int pca954x_resume(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
-	struct pca954x *data = i2c_get_clientdata(client);
+	struct i2c_mux_core *muxc = i2c_get_clientdata(client);
+	struct pca954x *data = i2c_mux_priv(muxc);
 
 	data->last_chan = 0;
 	return i2c_smbus_write_byte(client, 0);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/muxes/i2c-mux-pinctrl.c linux-libre-4.7-gnu/drivers/i2c/muxes/i2c-mux-pinctrl.c
--- linux-libre-4.6-gnu/drivers/i2c/muxes/i2c-mux-pinctrl.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/muxes/i2c-mux-pinctrl.c	2016-07-24 15:23:50.000000000 -0400
@@ -24,36 +24,32 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/of.h>
+#include "../../pinctrl/core.h"
 
 struct i2c_mux_pinctrl {
-	struct device *dev;
 	struct i2c_mux_pinctrl_platform_data *pdata;
 	struct pinctrl *pinctrl;
 	struct pinctrl_state **states;
 	struct pinctrl_state *state_idle;
-	struct i2c_adapter *parent;
-	struct i2c_adapter **busses;
 };
 
-static int i2c_mux_pinctrl_select(struct i2c_adapter *adap, void *data,
-				  u32 chan)
+static int i2c_mux_pinctrl_select(struct i2c_mux_core *muxc, u32 chan)
 {
-	struct i2c_mux_pinctrl *mux = data;
+	struct i2c_mux_pinctrl *mux = i2c_mux_priv(muxc);
 
 	return pinctrl_select_state(mux->pinctrl, mux->states[chan]);
 }
 
-static int i2c_mux_pinctrl_deselect(struct i2c_adapter *adap, void *data,
-				    u32 chan)
+static int i2c_mux_pinctrl_deselect(struct i2c_mux_core *muxc, u32 chan)
 {
-	struct i2c_mux_pinctrl *mux = data;
+	struct i2c_mux_pinctrl *mux = i2c_mux_priv(muxc);
 
 	return pinctrl_select_state(mux->pinctrl, mux->state_idle);
 }
 
 #ifdef CONFIG_OF
 static int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux,
-				struct platform_device *pdev)
+				    struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
 	int num_names, i, ret;
@@ -64,15 +60,12 @@ static int i2c_mux_pinctrl_parse_dt(stru
 		return 0;
 
 	mux->pdata = devm_kzalloc(&pdev->dev, sizeof(*mux->pdata), GFP_KERNEL);
-	if (!mux->pdata) {
-		dev_err(mux->dev,
-			"Cannot allocate i2c_mux_pinctrl_platform_data\n");
+	if (!mux->pdata)
 		return -ENOMEM;
-	}
 
 	num_names = of_property_count_strings(np, "pinctrl-names");
 	if (num_names < 0) {
-		dev_err(mux->dev, "Cannot parse pinctrl-names: %d\n",
+		dev_err(&pdev->dev, "Cannot parse pinctrl-names: %d\n",
 			num_names);
 		return num_names;
 	}
@@ -80,23 +73,22 @@ static int i2c_mux_pinctrl_parse_dt(stru
 	mux->pdata->pinctrl_states = devm_kzalloc(&pdev->dev,
 		sizeof(*mux->pdata->pinctrl_states) * num_names,
 		GFP_KERNEL);
-	if (!mux->pdata->pinctrl_states) {
-		dev_err(mux->dev, "Cannot allocate pinctrl_states\n");
+	if (!mux->pdata->pinctrl_states)
 		return -ENOMEM;
-	}
 
 	for (i = 0; i < num_names; i++) {
 		ret = of_property_read_string_index(np, "pinctrl-names", i,
 			&mux->pdata->pinctrl_states[mux->pdata->bus_count]);
 		if (ret < 0) {
-			dev_err(mux->dev, "Cannot parse pinctrl-names: %d\n",
+			dev_err(&pdev->dev, "Cannot parse pinctrl-names: %d\n",
 				ret);
 			return ret;
 		}
 		if (!strcmp(mux->pdata->pinctrl_states[mux->pdata->bus_count],
 			    "idle")) {
 			if (i != num_names - 1) {
-				dev_err(mux->dev, "idle state must be last\n");
+				dev_err(&pdev->dev,
+					"idle state must be last\n");
 				return -EINVAL;
 			}
 			mux->pdata->pinctrl_state_idle = "idle";
@@ -107,13 +99,13 @@ static int i2c_mux_pinctrl_parse_dt(stru
 
 	adapter_np = of_parse_phandle(np, "i2c-parent", 0);
 	if (!adapter_np) {
-		dev_err(mux->dev, "Cannot parse i2c-parent\n");
+		dev_err(&pdev->dev, "Cannot parse i2c-parent\n");
 		return -ENODEV;
 	}
 	adapter = of_find_i2c_adapter_by_node(adapter_np);
 	of_node_put(adapter_np);
 	if (!adapter) {
-		dev_err(mux->dev, "Cannot find parent bus\n");
+		dev_err(&pdev->dev, "Cannot find parent bus\n");
 		return -EPROBE_DEFER;
 	}
 	mux->pdata->parent_bus_num = i2c_adapter_id(adapter);
@@ -129,21 +121,38 @@ static inline int i2c_mux_pinctrl_parse_
 }
 #endif
 
+static struct i2c_adapter *i2c_mux_pinctrl_root_adapter(
+	struct pinctrl_state *state)
+{
+	struct i2c_adapter *root = NULL;
+	struct pinctrl_setting *setting;
+	struct i2c_adapter *pin_root;
+
+	list_for_each_entry(setting, &state->settings, node) {
+		pin_root = i2c_root_adapter(setting->pctldev->dev);
+		if (!pin_root)
+			return NULL;
+		if (!root)
+			root = pin_root;
+		else if (root != pin_root)
+			return NULL;
+	}
+
+	return root;
+}
+
 static int i2c_mux_pinctrl_probe(struct platform_device *pdev)
 {
+	struct i2c_mux_core *muxc;
 	struct i2c_mux_pinctrl *mux;
-	int (*deselect)(struct i2c_adapter *, void *, u32);
+	struct i2c_adapter *root;
 	int i, ret;
 
 	mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL);
 	if (!mux) {
-		dev_err(&pdev->dev, "Cannot allocate i2c_mux_pinctrl\n");
 		ret = -ENOMEM;
 		goto err;
 	}
-	platform_set_drvdata(pdev, mux);
-
-	mux->dev = &pdev->dev;
 
 	mux->pdata = dev_get_platdata(&pdev->dev);
 	if (!mux->pdata) {
@@ -166,14 +175,15 @@ static int i2c_mux_pinctrl_probe(struct
 		goto err;
 	}
 
-	mux->busses = devm_kzalloc(&pdev->dev,
-				   sizeof(*mux->busses) * mux->pdata->bus_count,
-				   GFP_KERNEL);
-	if (!mux->busses) {
-		dev_err(&pdev->dev, "Cannot allocate busses\n");
+	muxc = i2c_mux_alloc(NULL, &pdev->dev, mux->pdata->bus_count, 0, 0,
+			     i2c_mux_pinctrl_select, NULL);
+	if (!muxc) {
 		ret = -ENOMEM;
 		goto err;
 	}
+	muxc->priv = mux;
+
+	platform_set_drvdata(pdev, muxc);
 
 	mux->pinctrl = devm_pinctrl_get(&pdev->dev);
 	if (IS_ERR(mux->pinctrl)) {
@@ -184,13 +194,13 @@ static int i2c_mux_pinctrl_probe(struct
 	for (i = 0; i < mux->pdata->bus_count; i++) {
 		mux->states[i] = pinctrl_lookup_state(mux->pinctrl,
 						mux->pdata->pinctrl_states[i]);
-			if (IS_ERR(mux->states[i])) {
-				ret = PTR_ERR(mux->states[i]);
-				dev_err(&pdev->dev,
-					"Cannot look up pinctrl state %s: %d\n",
-					mux->pdata->pinctrl_states[i], ret);
-				goto err;
-			}
+		if (IS_ERR(mux->states[i])) {
+			ret = PTR_ERR(mux->states[i]);
+			dev_err(&pdev->dev,
+				"Cannot look up pinctrl state %s: %d\n",
+				mux->pdata->pinctrl_states[i], ret);
+			goto err;
+		}
 	}
 	if (mux->pdata->pinctrl_state_idle) {
 		mux->state_idle = pinctrl_lookup_state(mux->pinctrl,
@@ -203,29 +213,39 @@ static int i2c_mux_pinctrl_probe(struct
 			goto err;
 		}
 
-		deselect = i2c_mux_pinctrl_deselect;
-	} else {
-		deselect = NULL;
+		muxc->deselect = i2c_mux_pinctrl_deselect;
 	}
 
-	mux->parent = i2c_get_adapter(mux->pdata->parent_bus_num);
-	if (!mux->parent) {
+	muxc->parent = i2c_get_adapter(mux->pdata->parent_bus_num);
+	if (!muxc->parent) {
 		dev_err(&pdev->dev, "Parent adapter (%d) not found\n",
 			mux->pdata->parent_bus_num);
 		ret = -EPROBE_DEFER;
 		goto err;
 	}
 
+	root = i2c_root_adapter(&muxc->parent->dev);
+
+	muxc->mux_locked = true;
+	for (i = 0; i < mux->pdata->bus_count; i++) {
+		if (root != i2c_mux_pinctrl_root_adapter(mux->states[i])) {
+			muxc->mux_locked = false;
+			break;
+		}
+	}
+	if (muxc->mux_locked && mux->pdata->pinctrl_state_idle &&
+	    root != i2c_mux_pinctrl_root_adapter(mux->state_idle))
+		muxc->mux_locked = false;
+
+	if (muxc->mux_locked)
+		dev_info(&pdev->dev, "mux-locked i2c mux\n");
+
 	for (i = 0; i < mux->pdata->bus_count; i++) {
 		u32 bus = mux->pdata->base_bus_num ?
 				(mux->pdata->base_bus_num + i) : 0;
 
-		mux->busses[i] = i2c_add_mux_adapter(mux->parent, &pdev->dev,
-						     mux, bus, i, 0,
-						     i2c_mux_pinctrl_select,
-						     deselect);
-		if (!mux->busses[i]) {
-			ret = -ENODEV;
+		ret = i2c_mux_add_adapter(muxc, bus, i, 0);
+		if (ret) {
 			dev_err(&pdev->dev, "Failed to add adapter %d\n", i);
 			goto err_del_adapter;
 		}
@@ -234,23 +254,18 @@ static int i2c_mux_pinctrl_probe(struct
 	return 0;
 
 err_del_adapter:
-	for (; i > 0; i--)
-		i2c_del_mux_adapter(mux->busses[i - 1]);
-	i2c_put_adapter(mux->parent);
+	i2c_mux_del_adapters(muxc);
+	i2c_put_adapter(muxc->parent);
 err:
 	return ret;
 }
 
 static int i2c_mux_pinctrl_remove(struct platform_device *pdev)
 {
-	struct i2c_mux_pinctrl *mux = platform_get_drvdata(pdev);
-	int i;
-
-	for (i = 0; i < mux->pdata->bus_count; i++)
-		i2c_del_mux_adapter(mux->busses[i]);
-
-	i2c_put_adapter(mux->parent);
+	struct i2c_mux_core *muxc = platform_get_drvdata(pdev);
 
+	i2c_mux_del_adapters(muxc);
+	i2c_put_adapter(muxc->parent);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/i2c/muxes/i2c-mux-reg.c linux-libre-4.7-gnu/drivers/i2c/muxes/i2c-mux-reg.c
--- linux-libre-4.6-gnu/drivers/i2c/muxes/i2c-mux-reg.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/i2c/muxes/i2c-mux-reg.c	2016-07-24 15:23:50.000000000 -0400
@@ -21,8 +21,6 @@
 #include <linux/slab.h>
 
 struct regmux {
-	struct i2c_adapter *parent;
-	struct i2c_adapter **adap; /* child busses */
 	struct i2c_mux_reg_platform_data data;
 };
 
@@ -64,18 +62,16 @@ static int i2c_mux_reg_set(const struct
 	return 0;
 }
 
-static int i2c_mux_reg_select(struct i2c_adapter *adap, void *data,
-			      unsigned int chan)
+static int i2c_mux_reg_select(struct i2c_mux_core *muxc, u32 chan)
 {
-	struct regmux *mux = data;
+	struct regmux *mux = i2c_mux_priv(muxc);
 
 	return i2c_mux_reg_set(mux, chan);
 }
 
-static int i2c_mux_reg_deselect(struct i2c_adapter *adap, void *data,
-				unsigned int chan)
+static int i2c_mux_reg_deselect(struct i2c_mux_core *muxc, u32 chan)
 {
-	struct regmux *mux = data;
+	struct regmux *mux = i2c_mux_priv(muxc);
 
 	if (mux->data.idle_in_use)
 		return i2c_mux_reg_set(mux, mux->data.idle);
@@ -85,7 +81,7 @@ static int i2c_mux_reg_deselect(struct i
 
 #ifdef CONFIG_OF
 static int i2c_mux_reg_probe_dt(struct regmux *mux,
-					struct platform_device *pdev)
+				struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
 	struct device_node *adapter_np, *child;
@@ -107,7 +103,6 @@ static int i2c_mux_reg_probe_dt(struct r
 	if (!adapter)
 		return -EPROBE_DEFER;
 
-	mux->parent = adapter;
 	mux->data.parent = i2c_adapter_id(adapter);
 	put_device(&adapter->dev);
 
@@ -150,7 +145,7 @@ static int i2c_mux_reg_probe_dt(struct r
 		mux->data.idle_in_use = true;
 
 	/* map address from "reg" if exists */
-	if (of_address_to_resource(np, 0, &res)) {
+	if (of_address_to_resource(np, 0, &res) == 0) {
 		mux->data.reg_size = resource_size(&res);
 		mux->data.reg = devm_ioremap_resource(&pdev->dev, &res);
 		if (IS_ERR(mux->data.reg))
@@ -161,7 +156,7 @@ static int i2c_mux_reg_probe_dt(struct r
 }
 #else
 static int i2c_mux_reg_probe_dt(struct regmux *mux,
-					struct platform_device *pdev)
+				struct platform_device *pdev)
 {
 	return 0;
 }
@@ -169,10 +164,10 @@ static int i2c_mux_reg_probe_dt(struct r
 
 static int i2c_mux_reg_probe(struct platform_device *pdev)
 {
+	struct i2c_mux_core *muxc;
 	struct regmux *mux;
 	struct i2c_adapter *parent;
 	struct resource *res;
-	int (*deselect)(struct i2c_adapter *, void *, u32);
 	unsigned int class;
 	int i, ret, nr;
 
@@ -180,17 +175,9 @@ static int i2c_mux_reg_probe(struct plat
 	if (!mux)
 		return -ENOMEM;
 
-	platform_set_drvdata(pdev, mux);
-
 	if (dev_get_platdata(&pdev->dev)) {
 		memcpy(&mux->data, dev_get_platdata(&pdev->dev),
 			sizeof(mux->data));
-
-		parent = i2c_get_adapter(mux->data.parent);
-		if (!parent)
-			return -EPROBE_DEFER;
-
-		mux->parent = parent;
 	} else {
 		ret = i2c_mux_reg_probe_dt(mux, pdev);
 		if (ret < 0) {
@@ -199,6 +186,10 @@ static int i2c_mux_reg_probe(struct plat
 		}
 	}
 
+	parent = i2c_get_adapter(mux->data.parent);
+	if (!parent)
+		return -EPROBE_DEFER;
+
 	if (!mux->data.reg) {
 		dev_info(&pdev->dev,
 			"Register not set, using platform resource\n");
@@ -215,55 +206,45 @@ static int i2c_mux_reg_probe(struct plat
 		return -EINVAL;
 	}
 
-	mux->adap = devm_kzalloc(&pdev->dev,
-				 sizeof(*mux->adap) * mux->data.n_values,
-				 GFP_KERNEL);
-	if (!mux->adap) {
-		dev_err(&pdev->dev, "Cannot allocate i2c_adapter structure");
+	muxc = i2c_mux_alloc(parent, &pdev->dev, mux->data.n_values, 0, 0,
+			     i2c_mux_reg_select, NULL);
+	if (!muxc)
 		return -ENOMEM;
-	}
+	muxc->priv = mux;
+
+	platform_set_drvdata(pdev, muxc);
 
 	if (mux->data.idle_in_use)
-		deselect = i2c_mux_reg_deselect;
-	else
-		deselect = NULL;
+		muxc->deselect = i2c_mux_reg_deselect;
 
 	for (i = 0; i < mux->data.n_values; i++) {
 		nr = mux->data.base_nr ? (mux->data.base_nr + i) : 0;
 		class = mux->data.classes ? mux->data.classes[i] : 0;
 
-		mux->adap[i] = i2c_add_mux_adapter(mux->parent, &pdev->dev, mux,
-						   nr, mux->data.values[i],
-						   class, i2c_mux_reg_select,
-						   deselect);
-		if (!mux->adap[i]) {
-			ret = -ENODEV;
+		ret = i2c_mux_add_adapter(muxc, nr, mux->data.values[i], class);
+		if (ret) {
 			dev_err(&pdev->dev, "Failed to add adapter %d\n", i);
 			goto add_adapter_failed;
 		}
 	}
 
 	dev_dbg(&pdev->dev, "%d port mux on %s adapter\n",
-		 mux->data.n_values, mux->parent->name);
+		 mux->data.n_values, muxc->parent->name);
 
 	return 0;
 
 add_adapter_failed:
-	for (; i > 0; i--)
-		i2c_del_mux_adapter(mux->adap[i - 1]);
+	i2c_mux_del_adapters(muxc);
 
 	return ret;
 }
 
 static int i2c_mux_reg_remove(struct platform_device *pdev)
 {
-	struct regmux *mux = platform_get_drvdata(pdev);
-	int i;
-
-	for (i = 0; i < mux->data.n_values; i++)
-		i2c_del_mux_adapter(mux->adap[i]);
+	struct i2c_mux_core *muxc = platform_get_drvdata(pdev);
 
-	i2c_put_adapter(mux->parent);
+	i2c_mux_del_adapters(muxc);
+	i2c_put_adapter(muxc->parent);
 
 	return 0;
 }
@@ -279,6 +260,7 @@ static struct platform_driver i2c_mux_re
 	.remove	= i2c_mux_reg_remove,
 	.driver	= {
 		.name	= "i2c-mux-reg",
+		.of_match_table = of_match_ptr(i2c_mux_reg_of_match),
 	},
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/ide/ide-disk.c linux-libre-4.7-gnu/drivers/ide/ide-disk.c
--- linux-libre-4.6-gnu/drivers/ide/ide-disk.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/ide/ide-disk.c	2016-07-24 15:23:50.000000000 -0400
@@ -522,7 +522,7 @@ static int ide_do_setfeature(ide_drive_t
 static void update_flush(ide_drive_t *drive)
 {
 	u16 *id = drive->id;
-	unsigned flush = 0;
+	bool wc = false;
 
 	if (drive->dev_flags & IDE_DFLAG_WCACHE) {
 		unsigned long long capacity;
@@ -546,12 +546,12 @@ static void update_flush(ide_drive_t *dr
 		       drive->name, barrier ? "" : "not ");
 
 		if (barrier) {
-			flush = REQ_FLUSH;
+			wc = true;
 			blk_queue_prep_rq(drive->queue, idedisk_prep_fn);
 		}
 	}
 
-	blk_queue_flush(drive->queue, flush);
+	blk_queue_write_cache(drive->queue, wc, false);
 }
 
 ide_devset_get_flag(wcache, IDE_DFLAG_WCACHE);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/idle/intel_idle.c linux-libre-4.7-gnu/drivers/idle/intel_idle.c
--- linux-libre-4.6-gnu/drivers/idle/intel_idle.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/idle/intel_idle.c	2016-07-24 15:23:50.000000000 -0400
@@ -766,6 +766,67 @@ static struct cpuidle_state knl_cstates[
 		.enter = NULL }
 };
 
+static struct cpuidle_state bxt_cstates[] = {
+	{
+		.name = "C1-BXT",
+		.desc = "MWAIT 0x00",
+		.flags = MWAIT2flg(0x00),
+		.exit_latency = 2,
+		.target_residency = 2,
+		.enter = &intel_idle,
+		.enter_freeze = intel_idle_freeze, },
+	{
+		.name = "C1E-BXT",
+		.desc = "MWAIT 0x01",
+		.flags = MWAIT2flg(0x01),
+		.exit_latency = 10,
+		.target_residency = 20,
+		.enter = &intel_idle,
+		.enter_freeze = intel_idle_freeze, },
+	{
+		.name = "C6-BXT",
+		.desc = "MWAIT 0x20",
+		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
+		.exit_latency = 133,
+		.target_residency = 133,
+		.enter = &intel_idle,
+		.enter_freeze = intel_idle_freeze, },
+	{
+		.name = "C7s-BXT",
+		.desc = "MWAIT 0x31",
+		.flags = MWAIT2flg(0x31) | CPUIDLE_FLAG_TLB_FLUSHED,
+		.exit_latency = 155,
+		.target_residency = 155,
+		.enter = &intel_idle,
+		.enter_freeze = intel_idle_freeze, },
+	{
+		.name = "C8-BXT",
+		.desc = "MWAIT 0x40",
+		.flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED,
+		.exit_latency = 1000,
+		.target_residency = 1000,
+		.enter = &intel_idle,
+		.enter_freeze = intel_idle_freeze, },
+	{
+		.name = "C9-BXT",
+		.desc = "MWAIT 0x50",
+		.flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED,
+		.exit_latency = 2000,
+		.target_residency = 2000,
+		.enter = &intel_idle,
+		.enter_freeze = intel_idle_freeze, },
+	{
+		.name = "C10-BXT",
+		.desc = "MWAIT 0x60",
+		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
+		.exit_latency = 10000,
+		.target_residency = 10000,
+		.enter = &intel_idle,
+		.enter_freeze = intel_idle_freeze, },
+	{
+		.enter = NULL }
+};
+
 /**
  * intel_idle
  * @dev: cpuidle_device
@@ -950,6 +1011,11 @@ static const struct idle_cpu idle_cpu_kn
 	.state_table = knl_cstates,
 };
 
+static const struct idle_cpu idle_cpu_bxt = {
+	.state_table = bxt_cstates,
+	.disable_promotion_to_c1e = true,
+};
+
 #define ICPU(model, cpu) \
 	{ X86_VENDOR_INTEL, 6, model, X86_FEATURE_MWAIT, (unsigned long)&cpu }
 
@@ -985,6 +1051,7 @@ static const struct x86_cpu_id intel_idl
 	ICPU(0x9e, idle_cpu_skl),
 	ICPU(0x55, idle_cpu_skx),
 	ICPU(0x57, idle_cpu_knl),
+	ICPU(0x5c, idle_cpu_bxt),
 	{}
 };
 MODULE_DEVICE_TABLE(x86cpu, intel_idle_ids);
@@ -1075,6 +1142,73 @@ static void ivt_idle_state_table_update(
 
 	/* else, 1 and 2 socket systems use default ivt_cstates */
 }
+
+/*
+ * Translate IRTL (Interrupt Response Time Limit) MSR to usec
+ */
+
+static unsigned int irtl_ns_units[] = {
+	1, 32, 1024, 32768, 1048576, 33554432, 0, 0 };
+
+static unsigned long long irtl_2_usec(unsigned long long irtl)
+{
+	unsigned long long ns;
+
+	ns = irtl_ns_units[(irtl >> 10) & 0x3];
+
+	return div64_u64((irtl & 0x3FF) * ns, 1000);
+}
+/*
+ * bxt_idle_state_table_update(void)
+ *
+ * On BXT, we trust the IRTL to show the definitive maximum latency
+ * We use the same value for target_residency.
+ */
+static void bxt_idle_state_table_update(void)
+{
+	unsigned long long msr;
+
+	rdmsrl(MSR_PKGC6_IRTL, msr);
+	if (msr) {
+		unsigned int usec = irtl_2_usec(msr);
+
+		bxt_cstates[2].exit_latency = usec;
+		bxt_cstates[2].target_residency = usec;
+	}
+
+	rdmsrl(MSR_PKGC7_IRTL, msr);
+	if (msr) {
+		unsigned int usec = irtl_2_usec(msr);
+
+		bxt_cstates[3].exit_latency = usec;
+		bxt_cstates[3].target_residency = usec;
+	}
+
+	rdmsrl(MSR_PKGC8_IRTL, msr);
+	if (msr) {
+		unsigned int usec = irtl_2_usec(msr);
+
+		bxt_cstates[4].exit_latency = usec;
+		bxt_cstates[4].target_residency = usec;
+	}
+
+	rdmsrl(MSR_PKGC9_IRTL, msr);
+	if (msr) {
+		unsigned int usec = irtl_2_usec(msr);
+
+		bxt_cstates[5].exit_latency = usec;
+		bxt_cstates[5].target_residency = usec;
+	}
+
+	rdmsrl(MSR_PKGC10_IRTL, msr);
+	if (msr) {
+		unsigned int usec = irtl_2_usec(msr);
+
+		bxt_cstates[6].exit_latency = usec;
+		bxt_cstates[6].target_residency = usec;
+	}
+
+}
 /*
  * sklh_idle_state_table_update(void)
  *
@@ -1130,6 +1264,9 @@ static void intel_idle_state_table_updat
 	case 0x3e: /* IVT */
 		ivt_idle_state_table_update();
 		break;
+	case 0x5c: /* BXT */
+		bxt_idle_state_table_update();
+		break;
 	case 0x5e: /* SKL-H */
 		sklh_idle_state_table_update();
 		break;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/accel/bmc150-accel-core.c linux-libre-4.7-gnu/drivers/iio/accel/bmc150-accel-core.c
--- linux-libre-4.6-gnu/drivers/iio/accel/bmc150-accel-core.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/accel/bmc150-accel-core.c	2016-07-24 15:23:50.000000000 -0400
@@ -25,7 +25,6 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/acpi.h>
-#include <linux/gpio/consumer.h>
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
 #include <linux/iio/iio.h>
@@ -138,6 +137,7 @@ enum bmc150_accel_axis {
 	AXIS_X,
 	AXIS_Y,
 	AXIS_Z,
+	AXIS_MAX,
 };
 
 enum bmc150_power_modes {
@@ -188,7 +188,6 @@ enum bmc150_accel_trigger_id {
 
 struct bmc150_accel_data {
 	struct regmap *regmap;
-	struct device *dev;
 	int irq;
 	struct bmc150_accel_interrupt interrupts[BMC150_ACCEL_INTERRUPTS];
 	atomic_t active_intr;
@@ -246,16 +245,18 @@ static const struct {
 				       {500000, BMC150_ACCEL_SLEEP_500_MS},
 				       {1000000, BMC150_ACCEL_SLEEP_1_SEC} };
 
-static const struct regmap_config bmc150_i2c_regmap_conf = {
+const struct regmap_config bmc150_regmap_conf = {
 	.reg_bits = 8,
 	.val_bits = 8,
 	.max_register = 0x3f,
 };
+EXPORT_SYMBOL_GPL(bmc150_regmap_conf);
 
 static int bmc150_accel_set_mode(struct bmc150_accel_data *data,
 				 enum bmc150_power_modes mode,
 				 int dur_us)
 {
+	struct device *dev = regmap_get_device(data->regmap);
 	int i;
 	int ret;
 	u8 lpw_bits;
@@ -279,11 +280,11 @@ static int bmc150_accel_set_mode(struct
 	lpw_bits = mode << BMC150_ACCEL_PMU_MODE_SHIFT;
 	lpw_bits |= (dur_val << BMC150_ACCEL_PMU_BIT_SLEEP_DUR_SHIFT);
 
-	dev_dbg(data->dev, "Set Mode bits %x\n", lpw_bits);
+	dev_dbg(dev, "Set Mode bits %x\n", lpw_bits);
 
 	ret = regmap_write(data->regmap, BMC150_ACCEL_REG_PMU_LPW, lpw_bits);
 	if (ret < 0) {
-		dev_err(data->dev, "Error writing reg_pmu_lpw\n");
+		dev_err(dev, "Error writing reg_pmu_lpw\n");
 		return ret;
 	}
 
@@ -316,23 +317,24 @@ static int bmc150_accel_set_bw(struct bm
 
 static int bmc150_accel_update_slope(struct bmc150_accel_data *data)
 {
+	struct device *dev = regmap_get_device(data->regmap);
 	int ret;
 
 	ret = regmap_write(data->regmap, BMC150_ACCEL_REG_INT_6,
 					data->slope_thres);
 	if (ret < 0) {
-		dev_err(data->dev, "Error writing reg_int_6\n");
+		dev_err(dev, "Error writing reg_int_6\n");
 		return ret;
 	}
 
 	ret = regmap_update_bits(data->regmap, BMC150_ACCEL_REG_INT_5,
 				 BMC150_ACCEL_SLOPE_DUR_MASK, data->slope_dur);
 	if (ret < 0) {
-		dev_err(data->dev, "Error updating reg_int_5\n");
+		dev_err(dev, "Error updating reg_int_5\n");
 		return ret;
 	}
 
-	dev_dbg(data->dev, "%s: %x %x\n", __func__, data->slope_thres,
+	dev_dbg(dev, "%s: %x %x\n", __func__, data->slope_thres,
 		data->slope_dur);
 
 	return ret;
@@ -378,20 +380,21 @@ static int bmc150_accel_get_startup_time
 
 static int bmc150_accel_set_power_state(struct bmc150_accel_data *data, bool on)
 {
+	struct device *dev = regmap_get_device(data->regmap);
 	int ret;
 
 	if (on) {
-		ret = pm_runtime_get_sync(data->dev);
+		ret = pm_runtime_get_sync(dev);
 	} else {
-		pm_runtime_mark_last_busy(data->dev);
-		ret = pm_runtime_put_autosuspend(data->dev);
+		pm_runtime_mark_last_busy(dev);
+		ret = pm_runtime_put_autosuspend(dev);
 	}
 
 	if (ret < 0) {
-		dev_err(data->dev,
+		dev_err(dev,
 			"Failed: bmc150_accel_set_power_state for %d\n", on);
 		if (on)
-			pm_runtime_put_noidle(data->dev);
+			pm_runtime_put_noidle(dev);
 
 		return ret;
 	}
@@ -445,6 +448,7 @@ static void bmc150_accel_interrupts_setu
 static int bmc150_accel_set_interrupt(struct bmc150_accel_data *data, int i,
 				      bool state)
 {
+	struct device *dev = regmap_get_device(data->regmap);
 	struct bmc150_accel_interrupt *intr = &data->interrupts[i];
 	const struct bmc150_accel_interrupt_info *info = intr->info;
 	int ret;
@@ -474,7 +478,7 @@ static int bmc150_accel_set_interrupt(st
 	ret = regmap_update_bits(data->regmap, info->map_reg, info->map_bitmask,
 				 (state ? info->map_bitmask : 0));
 	if (ret < 0) {
-		dev_err(data->dev, "Error updating reg_int_map\n");
+		dev_err(dev, "Error updating reg_int_map\n");
 		goto out_fix_power_state;
 	}
 
@@ -482,7 +486,7 @@ static int bmc150_accel_set_interrupt(st
 	ret = regmap_update_bits(data->regmap, info->en_reg, info->en_bitmask,
 				 (state ? info->en_bitmask : 0));
 	if (ret < 0) {
-		dev_err(data->dev, "Error updating reg_int_en\n");
+		dev_err(dev, "Error updating reg_int_en\n");
 		goto out_fix_power_state;
 	}
 
@@ -500,6 +504,7 @@ out_fix_power_state:
 
 static int bmc150_accel_set_scale(struct bmc150_accel_data *data, int val)
 {
+	struct device *dev = regmap_get_device(data->regmap);
 	int ret, i;
 
 	for (i = 0; i < ARRAY_SIZE(data->chip_info->scale_table); ++i) {
@@ -508,8 +513,7 @@ static int bmc150_accel_set_scale(struct
 				     BMC150_ACCEL_REG_PMU_RANGE,
 				     data->chip_info->scale_table[i].reg_range);
 			if (ret < 0) {
-				dev_err(data->dev,
-					"Error writing pmu_range\n");
+				dev_err(dev, "Error writing pmu_range\n");
 				return ret;
 			}
 
@@ -523,6 +527,7 @@ static int bmc150_accel_set_scale(struct
 
 static int bmc150_accel_get_temp(struct bmc150_accel_data *data, int *val)
 {
+	struct device *dev = regmap_get_device(data->regmap);
 	int ret;
 	unsigned int value;
 
@@ -530,7 +535,7 @@ static int bmc150_accel_get_temp(struct
 
 	ret = regmap_read(data->regmap, BMC150_ACCEL_REG_TEMP, &value);
 	if (ret < 0) {
-		dev_err(data->dev, "Error reading reg_temp\n");
+		dev_err(dev, "Error reading reg_temp\n");
 		mutex_unlock(&data->mutex);
 		return ret;
 	}
@@ -545,6 +550,7 @@ static int bmc150_accel_get_axis(struct
 				 struct iio_chan_spec const *chan,
 				 int *val)
 {
+	struct device *dev = regmap_get_device(data->regmap);
 	int ret;
 	int axis = chan->scan_index;
 	__le16 raw_val;
@@ -559,7 +565,7 @@ static int bmc150_accel_get_axis(struct
 	ret = regmap_bulk_read(data->regmap, BMC150_ACCEL_AXIS_TO_REG(axis),
 			       &raw_val, sizeof(raw_val));
 	if (ret < 0) {
-		dev_err(data->dev, "Error reading axis %d\n", axis);
+		dev_err(dev, "Error reading axis %d\n", axis);
 		bmc150_accel_set_power_state(data, false);
 		mutex_unlock(&data->mutex);
 		return ret;
@@ -831,6 +837,7 @@ static int bmc150_accel_set_watermark(st
 static int bmc150_accel_fifo_transfer(struct bmc150_accel_data *data,
 				      char *buffer, int samples)
 {
+	struct device *dev = regmap_get_device(data->regmap);
 	int sample_length = 3 * 2;
 	int ret;
 	int total_length = samples * sample_length;
@@ -854,7 +861,8 @@ static int bmc150_accel_fifo_transfer(st
 	}
 
 	if (ret)
-		dev_err(data->dev, "Error transferring data from fifo in single steps of %zu\n",
+		dev_err(dev,
+			"Error transferring data from fifo in single steps of %zu\n",
 			step);
 
 	return ret;
@@ -864,6 +872,7 @@ static int __bmc150_accel_fifo_flush(str
 				     unsigned samples, bool irq)
 {
 	struct bmc150_accel_data *data = iio_priv(indio_dev);
+	struct device *dev = regmap_get_device(data->regmap);
 	int ret, i;
 	u8 count;
 	u16 buffer[BMC150_ACCEL_FIFO_LENGTH * 3];
@@ -873,7 +882,7 @@ static int __bmc150_accel_fifo_flush(str
 
 	ret = regmap_read(data->regmap, BMC150_ACCEL_REG_FIFO_STATUS, &val);
 	if (ret < 0) {
-		dev_err(data->dev, "Error reading reg_fifo_status\n");
+		dev_err(dev, "Error reading reg_fifo_status\n");
 		return ret;
 	}
 
@@ -1105,27 +1114,23 @@ static const struct iio_info bmc150_acce
 	.driver_module		= THIS_MODULE,
 };
 
+static const unsigned long bmc150_accel_scan_masks[] = {
+					BIT(AXIS_X) | BIT(AXIS_Y) | BIT(AXIS_Z),
+					0};
+
 static irqreturn_t bmc150_accel_trigger_handler(int irq, void *p)
 {
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct bmc150_accel_data *data = iio_priv(indio_dev);
-	int bit, ret, i = 0;
-	unsigned int raw_val;
+	int ret;
 
 	mutex_lock(&data->mutex);
-	for_each_set_bit(bit, indio_dev->active_scan_mask,
-			 indio_dev->masklength) {
-		ret = regmap_bulk_read(data->regmap,
-				       BMC150_ACCEL_AXIS_TO_REG(bit), &raw_val,
-				       2);
-		if (ret < 0) {
-			mutex_unlock(&data->mutex);
-			goto err_read;
-		}
-		data->buffer[i++] = raw_val;
-	}
+	ret = regmap_bulk_read(data->regmap, BMC150_ACCEL_REG_XOUT_L,
+			       data->buffer, AXIS_MAX * 2);
 	mutex_unlock(&data->mutex);
+	if (ret < 0)
+		goto err_read;
 
 	iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
 					   pf->timestamp);
@@ -1139,6 +1144,7 @@ static int bmc150_accel_trig_try_reen(st
 {
 	struct bmc150_accel_trigger *t = iio_trigger_get_drvdata(trig);
 	struct bmc150_accel_data *data = t->data;
+	struct device *dev = regmap_get_device(data->regmap);
 	int ret;
 
 	/* new data interrupts don't need ack */
@@ -1152,8 +1158,7 @@ static int bmc150_accel_trig_try_reen(st
 			   BMC150_ACCEL_INT_MODE_LATCH_RESET);
 	mutex_unlock(&data->mutex);
 	if (ret < 0) {
-		dev_err(data->dev,
-			"Error writing reg_int_rst_latch\n");
+		dev_err(dev, "Error writing reg_int_rst_latch\n");
 		return ret;
 	}
 
@@ -1204,13 +1209,14 @@ static const struct iio_trigger_ops bmc1
 static int bmc150_accel_handle_roc_event(struct iio_dev *indio_dev)
 {
 	struct bmc150_accel_data *data = iio_priv(indio_dev);
+	struct device *dev = regmap_get_device(data->regmap);
 	int dir;
 	int ret;
 	unsigned int val;
 
 	ret = regmap_read(data->regmap, BMC150_ACCEL_REG_INT_STATUS_2, &val);
 	if (ret < 0) {
-		dev_err(data->dev, "Error reading reg_int_status_2\n");
+		dev_err(dev, "Error reading reg_int_status_2\n");
 		return ret;
 	}
 
@@ -1253,6 +1259,7 @@ static irqreturn_t bmc150_accel_irq_thre
 {
 	struct iio_dev *indio_dev = private;
 	struct bmc150_accel_data *data = iio_priv(indio_dev);
+	struct device *dev = regmap_get_device(data->regmap);
 	bool ack = false;
 	int ret;
 
@@ -1276,7 +1283,7 @@ static irqreturn_t bmc150_accel_irq_thre
 				   BMC150_ACCEL_INT_MODE_LATCH_INT |
 				   BMC150_ACCEL_INT_MODE_LATCH_RESET);
 		if (ret)
-			dev_err(data->dev, "Error writing reg_int_rst_latch\n");
+			dev_err(dev, "Error writing reg_int_rst_latch\n");
 
 		ret = IRQ_HANDLED;
 	} else {
@@ -1347,13 +1354,14 @@ static void bmc150_accel_unregister_trig
 static int bmc150_accel_triggers_setup(struct iio_dev *indio_dev,
 				       struct bmc150_accel_data *data)
 {
+	struct device *dev = regmap_get_device(data->regmap);
 	int i, ret;
 
 	for (i = 0; i < BMC150_ACCEL_TRIGGERS; i++) {
 		struct bmc150_accel_trigger *t = &data->triggers[i];
 
-		t->indio_trig = devm_iio_trigger_alloc(data->dev,
-					       bmc150_accel_triggers[i].name,
+		t->indio_trig = devm_iio_trigger_alloc(dev,
+					bmc150_accel_triggers[i].name,
 						       indio_dev->name,
 						       indio_dev->id);
 		if (!t->indio_trig) {
@@ -1361,7 +1369,7 @@ static int bmc150_accel_triggers_setup(s
 			break;
 		}
 
-		t->indio_trig->dev.parent = data->dev;
+		t->indio_trig->dev.parent = dev;
 		t->indio_trig->ops = &bmc150_accel_trigger_ops;
 		t->intr = bmc150_accel_triggers[i].intr;
 		t->data = data;
@@ -1385,12 +1393,13 @@ static int bmc150_accel_triggers_setup(s
 
 static int bmc150_accel_fifo_set_mode(struct bmc150_accel_data *data)
 {
+	struct device *dev = regmap_get_device(data->regmap);
 	u8 reg = BMC150_ACCEL_REG_FIFO_CONFIG1;
 	int ret;
 
 	ret = regmap_write(data->regmap, reg, data->fifo_mode);
 	if (ret < 0) {
-		dev_err(data->dev, "Error writing reg_fifo_config1\n");
+		dev_err(dev, "Error writing reg_fifo_config1\n");
 		return ret;
 	}
 
@@ -1400,7 +1409,7 @@ static int bmc150_accel_fifo_set_mode(st
 	ret = regmap_write(data->regmap, BMC150_ACCEL_REG_FIFO_CONFIG0,
 			   data->watermark);
 	if (ret < 0)
-		dev_err(data->dev, "Error writing reg_fifo_config0\n");
+		dev_err(dev, "Error writing reg_fifo_config0\n");
 
 	return ret;
 }
@@ -1484,17 +1493,17 @@ static const struct iio_buffer_setup_ops
 
 static int bmc150_accel_chip_init(struct bmc150_accel_data *data)
 {
+	struct device *dev = regmap_get_device(data->regmap);
 	int ret, i;
 	unsigned int val;
 
 	ret = regmap_read(data->regmap, BMC150_ACCEL_REG_CHIP_ID, &val);
 	if (ret < 0) {
-		dev_err(data->dev,
-			"Error: Reading chip id\n");
+		dev_err(dev, "Error: Reading chip id\n");
 		return ret;
 	}
 
-	dev_dbg(data->dev, "Chip Id %x\n", val);
+	dev_dbg(dev, "Chip Id %x\n", val);
 	for (i = 0; i < ARRAY_SIZE(bmc150_accel_chip_info_tbl); i++) {
 		if (bmc150_accel_chip_info_tbl[i].chip_id == val) {
 			data->chip_info = &bmc150_accel_chip_info_tbl[i];
@@ -1503,7 +1512,7 @@ static int bmc150_accel_chip_init(struct
 	}
 
 	if (!data->chip_info) {
-		dev_err(data->dev, "Invalid chip %x\n", val);
+		dev_err(dev, "Invalid chip %x\n", val);
 		return -ENODEV;
 	}
 
@@ -1520,8 +1529,7 @@ static int bmc150_accel_chip_init(struct
 	ret = regmap_write(data->regmap, BMC150_ACCEL_REG_PMU_RANGE,
 			   BMC150_ACCEL_DEF_RANGE_4G);
 	if (ret < 0) {
-		dev_err(data->dev,
-					"Error writing reg_pmu_range\n");
+		dev_err(dev, "Error writing reg_pmu_range\n");
 		return ret;
 	}
 
@@ -1539,8 +1547,7 @@ static int bmc150_accel_chip_init(struct
 			   BMC150_ACCEL_INT_MODE_LATCH_INT |
 			   BMC150_ACCEL_INT_MODE_LATCH_RESET);
 	if (ret < 0) {
-		dev_err(data->dev,
-			"Error writing reg_int_rst_latch\n");
+		dev_err(dev, "Error writing reg_int_rst_latch\n");
 		return ret;
 	}
 
@@ -1560,7 +1567,6 @@ int bmc150_accel_core_probe(struct devic
 
 	data = iio_priv(indio_dev);
 	dev_set_drvdata(dev, indio_dev);
-	data->dev = dev;
 	data->irq = irq;
 
 	data->regmap = regmap;
@@ -1575,6 +1581,7 @@ int bmc150_accel_core_probe(struct devic
 	indio_dev->channels = data->chip_info->channels;
 	indio_dev->num_channels = data->chip_info->num_channels;
 	indio_dev->name = name ? name : data->chip_info->name;
+	indio_dev->available_scan_masks = bmc150_accel_scan_masks;
 	indio_dev->modes = INDIO_DIRECT_MODE;
 	indio_dev->info = &bmc150_accel_info;
 
@@ -1583,13 +1590,13 @@ int bmc150_accel_core_probe(struct devic
 					 bmc150_accel_trigger_handler,
 					 &bmc150_accel_buffer_ops);
 	if (ret < 0) {
-		dev_err(data->dev, "Failed: iio triggered buffer setup\n");
+		dev_err(dev, "Failed: iio triggered buffer setup\n");
 		return ret;
 	}
 
 	if (data->irq > 0) {
 		ret = devm_request_threaded_irq(
-						data->dev, data->irq,
+						dev, data->irq,
 						bmc150_accel_irq_handler,
 						bmc150_accel_irq_thread_handler,
 						IRQF_TRIGGER_RISING,
@@ -1607,7 +1614,7 @@ int bmc150_accel_core_probe(struct devic
 		ret = regmap_write(data->regmap, BMC150_ACCEL_REG_INT_RST_LATCH,
 				   BMC150_ACCEL_INT_MODE_LATCH_RESET);
 		if (ret < 0) {
-			dev_err(data->dev, "Error writing reg_int_rst_latch\n");
+			dev_err(dev, "Error writing reg_int_rst_latch\n");
 			goto err_buffer_cleanup;
 		}
 
@@ -1656,9 +1663,9 @@ int bmc150_accel_core_remove(struct devi
 
 	iio_device_unregister(indio_dev);
 
-	pm_runtime_disable(data->dev);
-	pm_runtime_set_suspended(data->dev);
-	pm_runtime_put_noidle(data->dev);
+	pm_runtime_disable(dev);
+	pm_runtime_set_suspended(dev);
+	pm_runtime_put_noidle(dev);
 
 	bmc150_accel_unregister_triggers(data, BMC150_ACCEL_TRIGGERS - 1);
 
@@ -1707,7 +1714,7 @@ static int bmc150_accel_runtime_suspend(
 	struct bmc150_accel_data *data = iio_priv(indio_dev);
 	int ret;
 
-	dev_dbg(data->dev,  __func__);
+	dev_dbg(dev,  __func__);
 	ret = bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_SUSPEND, 0);
 	if (ret < 0)
 		return -EAGAIN;
@@ -1722,7 +1729,7 @@ static int bmc150_accel_runtime_resume(s
 	int ret;
 	int sleep_val;
 
-	dev_dbg(data->dev,  __func__);
+	dev_dbg(dev,  __func__);
 
 	ret = bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_NORMAL, 0);
 	if (ret < 0)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/accel/bmc150-accel.h linux-libre-4.7-gnu/drivers/iio/accel/bmc150-accel.h
--- linux-libre-4.6-gnu/drivers/iio/accel/bmc150-accel.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/accel/bmc150-accel.h	2016-07-24 15:23:50.000000000 -0400
@@ -16,5 +16,6 @@ int bmc150_accel_core_probe(struct devic
 			    const char *name, bool block_supported);
 int bmc150_accel_core_remove(struct device *dev);
 extern const struct dev_pm_ops bmc150_accel_pm_ops;
+extern const struct regmap_config bmc150_regmap_conf;
 
 #endif  /* _BMC150_ACCEL_H_ */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/accel/bmc150-accel-i2c.c linux-libre-4.7-gnu/drivers/iio/accel/bmc150-accel-i2c.c
--- linux-libre-4.6-gnu/drivers/iio/accel/bmc150-accel-i2c.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/accel/bmc150-accel-i2c.c	2016-07-24 15:23:50.000000000 -0400
@@ -28,11 +28,6 @@
 
 #include "bmc150-accel.h"
 
-static const struct regmap_config bmc150_i2c_regmap_conf = {
-	.reg_bits = 8,
-	.val_bits = 8,
-};
-
 static int bmc150_accel_probe(struct i2c_client *client,
 			      const struct i2c_device_id *id)
 {
@@ -43,7 +38,7 @@ static int bmc150_accel_probe(struct i2c
 		i2c_check_functionality(client->adapter,
 					I2C_FUNC_SMBUS_READ_I2C_BLOCK);
 
-	regmap = devm_regmap_init_i2c(client, &bmc150_i2c_regmap_conf);
+	regmap = devm_regmap_init_i2c(client, &bmc150_regmap_conf);
 	if (IS_ERR(regmap)) {
 		dev_err(&client->dev, "Failed to initialize i2c regmap\n");
 		return PTR_ERR(regmap);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/accel/bmc150-accel-spi.c linux-libre-4.7-gnu/drivers/iio/accel/bmc150-accel-spi.c
--- linux-libre-4.6-gnu/drivers/iio/accel/bmc150-accel-spi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/accel/bmc150-accel-spi.c	2016-07-24 15:23:50.000000000 -0400
@@ -25,18 +25,12 @@
 
 #include "bmc150-accel.h"
 
-static const struct regmap_config bmc150_spi_regmap_conf = {
-	.reg_bits = 8,
-	.val_bits = 8,
-	.max_register = 0x3f,
-};
-
 static int bmc150_accel_probe(struct spi_device *spi)
 {
 	struct regmap *regmap;
 	const struct spi_device_id *id = spi_get_device_id(spi);
 
-	regmap = devm_regmap_init_spi(spi, &bmc150_spi_regmap_conf);
+	regmap = devm_regmap_init_spi(spi, &bmc150_regmap_conf);
 	if (IS_ERR(regmap)) {
 		dev_err(&spi->dev, "Failed to initialize spi regmap\n");
 		return PTR_ERR(regmap);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/accel/Kconfig linux-libre-4.7-gnu/drivers/iio/accel/Kconfig
--- linux-libre-4.6-gnu/drivers/iio/accel/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/accel/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -64,7 +64,7 @@ config IIO_ST_ACCEL_3AXIS
 	help
 	  Say yes here to build support for STMicroelectronics accelerometers:
 	  LSM303DLH, LSM303DLHC, LIS3DH, LSM330D, LSM330DL, LSM330DLC,
-	  LIS331DLH, LSM303DL, LSM303DLM, LSM330, LIS2DH12.
+	  LIS331DLH, LSM303DL, LSM303DLM, LSM330, LIS2DH12, H3LIS331DL.
 
 	  This driver can also be built as a module. If so, these modules
 	  will be created:
@@ -143,7 +143,8 @@ config MMA8452
 	select IIO_TRIGGERED_BUFFER
 	help
 	  Say yes here to build support for the following Freescale 3-axis
-	  accelerometers: MMA8451Q, MMA8452Q, MMA8453Q, MMA8652FC, MMA8653FC.
+	  accelerometers: MMA8451Q, MMA8452Q, MMA8453Q, MMA8652FC, MMA8653FC,
+	  FXLS8471Q.
 
 	  To compile this driver as a module, choose M here: the module
 	  will be called mma8452.
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/accel/kxcjk-1013.c linux-libre-4.7-gnu/drivers/iio/accel/kxcjk-1013.c
--- linux-libre-4.6-gnu/drivers/iio/accel/kxcjk-1013.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/accel/kxcjk-1013.c	2016-07-24 15:23:50.000000000 -0400
@@ -20,7 +20,6 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/acpi.h>
-#include <linux/gpio/consumer.h>
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
 #include <linux/iio/iio.h>
@@ -115,6 +114,7 @@ enum kxcjk1013_axis {
 	AXIS_X,
 	AXIS_Y,
 	AXIS_Z,
+	AXIS_MAX,
 };
 
 enum kxcjk1013_mode {
@@ -922,7 +922,7 @@ static const struct iio_event_spec kxcjk
 		.realbits = 12,						\
 		.storagebits = 16,					\
 		.shift = 4,						\
-		.endianness = IIO_CPU,					\
+		.endianness = IIO_LE,					\
 	},								\
 	.event_spec = &kxcjk1013_event,				\
 	.num_event_specs = 1						\
@@ -953,25 +953,23 @@ static const struct iio_info kxcjk1013_i
 	.driver_module		= THIS_MODULE,
 };
 
+static const unsigned long kxcjk1013_scan_masks[] = {0x7, 0};
+
 static irqreturn_t kxcjk1013_trigger_handler(int irq, void *p)
 {
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct kxcjk1013_data *data = iio_priv(indio_dev);
-	int bit, ret, i = 0;
+	int ret;
 
 	mutex_lock(&data->mutex);
-
-	for_each_set_bit(bit, indio_dev->active_scan_mask,
-			 indio_dev->masklength) {
-		ret = kxcjk1013_get_acc_reg(data, bit);
-		if (ret < 0) {
-			mutex_unlock(&data->mutex);
-			goto err;
-		}
-		data->buffer[i++] = ret;
-	}
+	ret = i2c_smbus_read_i2c_block_data_or_emulated(data->client,
+							KXCJK1013_REG_XOUT_L,
+							AXIS_MAX * 2,
+							(u8 *)data->buffer);
 	mutex_unlock(&data->mutex);
+	if (ret < 0)
+		goto err;
 
 	iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
 					   data->timestamp);
@@ -1204,6 +1202,7 @@ static int kxcjk1013_probe(struct i2c_cl
 	indio_dev->dev.parent = &client->dev;
 	indio_dev->channels = kxcjk1013_channels;
 	indio_dev->num_channels = ARRAY_SIZE(kxcjk1013_channels);
+	indio_dev->available_scan_masks = kxcjk1013_scan_masks;
 	indio_dev->name = name;
 	indio_dev->modes = INDIO_DIRECT_MODE;
 	indio_dev->info = &kxcjk1013_info;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/accel/kxsd9.c linux-libre-4.7-gnu/drivers/iio/accel/kxsd9.c
--- linux-libre-4.6-gnu/drivers/iio/accel/kxsd9.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/accel/kxsd9.c	2016-07-24 15:23:50.000000000 -0400
@@ -81,7 +81,7 @@ static int kxsd9_write_scale(struct iio_
 
 	mutex_lock(&st->buf_lock);
 	ret = spi_w8r8(st->us, KXSD9_READ(KXSD9_REG_CTRL_C));
-	if (ret)
+	if (ret < 0)
 		goto error_ret;
 	st->tx[0] = KXSD9_WRITE(KXSD9_REG_CTRL_C);
 	st->tx[1] = (ret & ~KXSD9_FS_MASK) | i;
@@ -163,7 +163,7 @@ static int kxsd9_read_raw(struct iio_dev
 		break;
 	case IIO_CHAN_INFO_SCALE:
 		ret = spi_w8r8(st->us, KXSD9_READ(KXSD9_REG_CTRL_C));
-		if (ret)
+		if (ret < 0)
 			goto error_ret;
 		*val2 = kxsd9_micro_scales[ret & KXSD9_FS_MASK];
 		ret = IIO_VAL_INT_PLUS_MICRO;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/accel/mma7455_core.c linux-libre-4.7-gnu/drivers/iio/accel/mma7455_core.c
--- linux-libre-4.6-gnu/drivers/iio/accel/mma7455_core.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/accel/mma7455_core.c	2016-07-24 15:23:50.000000000 -0400
@@ -55,11 +55,11 @@
 
 struct mma7455_data {
 	struct regmap *regmap;
-	struct device *dev;
 };
 
 static int mma7455_drdy(struct mma7455_data *mma7455)
 {
+	struct device *dev = regmap_get_device(mma7455->regmap);
 	unsigned int reg;
 	int tries = 3;
 	int ret;
@@ -75,7 +75,7 @@ static int mma7455_drdy(struct mma7455_d
 		msleep(20);
 	}
 
-	dev_warn(mma7455->dev, "data not ready\n");
+	dev_warn(dev, "data not ready\n");
 
 	return -EIO;
 }
@@ -260,7 +260,6 @@ int mma7455_core_probe(struct device *de
 	dev_set_drvdata(dev, indio_dev);
 	mma7455 = iio_priv(indio_dev);
 	mma7455->regmap = regmap;
-	mma7455->dev = dev;
 
 	indio_dev->info = &mma7455_info;
 	indio_dev->name = name;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/accel/mma8452.c linux-libre-4.7-gnu/drivers/iio/accel/mma8452.c
--- linux-libre-4.6-gnu/drivers/iio/accel/mma8452.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/accel/mma8452.c	2016-07-24 15:23:50.000000000 -0400
@@ -6,6 +6,7 @@
  * MMA8453Q (10 bit)
  * MMA8652FC (12 bit)
  * MMA8653FC (10 bit)
+ * FXLS8471Q (14 bit)
  *
  * Copyright 2015 Martin Kepplinger <martin.kepplinger@theobroma-systems.com>
  * Copyright 2014 Peter Meerwald <pmeerw@pmeerw.net>
@@ -16,7 +17,7 @@
  *
  * 7-bit I2C slave address 0x1c/0x1d (pin selectable)
  *
- * TODO: orientation events, autosleep
+ * TODO: orientation events
  */
 
 #include <linux/module.h>
@@ -31,6 +32,7 @@
 #include <linux/delay.h>
 #include <linux/of_device.h>
 #include <linux/of_irq.h>
+#include <linux/pm_runtime.h>
 
 #define MMA8452_STATUS				0x00
 #define  MMA8452_STATUS_DRDY			(BIT(2) | BIT(1) | BIT(0))
@@ -91,6 +93,9 @@
 #define MMA8453_DEVICE_ID			0x3a
 #define MMA8652_DEVICE_ID			0x4a
 #define MMA8653_DEVICE_ID			0x5a
+#define FXLS8471_DEVICE_ID			0x6a
+
+#define MMA8452_AUTO_SUSPEND_DELAY_MS		2000
 
 struct mma8452_data {
 	struct i2c_client *client;
@@ -172,6 +177,31 @@ static int mma8452_drdy(struct mma8452_d
 	return -EIO;
 }
 
+static int mma8452_set_runtime_pm_state(struct i2c_client *client, bool on)
+{
+#ifdef CONFIG_PM
+	int ret;
+
+	if (on) {
+		ret = pm_runtime_get_sync(&client->dev);
+	} else {
+		pm_runtime_mark_last_busy(&client->dev);
+		ret = pm_runtime_put_autosuspend(&client->dev);
+	}
+
+	if (ret < 0) {
+		dev_err(&client->dev,
+			"failed to change power state to %d\n", on);
+		if (on)
+			pm_runtime_put_noidle(&client->dev);
+
+		return ret;
+	}
+#endif
+
+	return 0;
+}
+
 static int mma8452_read(struct mma8452_data *data, __be16 buf[3])
 {
 	int ret = mma8452_drdy(data);
@@ -179,8 +209,16 @@ static int mma8452_read(struct mma8452_d
 	if (ret < 0)
 		return ret;
 
-	return i2c_smbus_read_i2c_block_data(data->client, MMA8452_OUT_X,
-					     3 * sizeof(__be16), (u8 *)buf);
+	ret = mma8452_set_runtime_pm_state(data->client, true);
+	if (ret)
+		return ret;
+
+	ret = i2c_smbus_read_i2c_block_data(data->client, MMA8452_OUT_X,
+					    3 * sizeof(__be16), (u8 *)buf);
+
+	ret = mma8452_set_runtime_pm_state(data->client, false);
+
+	return ret;
 }
 
 static ssize_t mma8452_show_int_plus_micros(char *buf, const int (*vals)[2],
@@ -357,7 +395,8 @@ static int mma8452_read_raw(struct iio_d
 		return IIO_VAL_INT_PLUS_MICRO;
 	case IIO_CHAN_INFO_CALIBBIAS:
 		ret = i2c_smbus_read_byte_data(data->client,
-					      MMA8452_OFF_X + chan->scan_index);
+					       MMA8452_OFF_X +
+					       chan->scan_index);
 		if (ret < 0)
 			return ret;
 
@@ -392,24 +431,47 @@ static int mma8452_active(struct mma8452
 					 data->ctrl_reg1);
 }
 
+/* returns >0 if active, 0 if in standby and <0 on error */
+static int mma8452_is_active(struct mma8452_data *data)
+{
+	int reg;
+
+	reg = i2c_smbus_read_byte_data(data->client, MMA8452_CTRL_REG1);
+	if (reg < 0)
+		return reg;
+
+	return reg & MMA8452_CTRL_ACTIVE;
+}
+
 static int mma8452_change_config(struct mma8452_data *data, u8 reg, u8 val)
 {
 	int ret;
+	int is_active;
 
 	mutex_lock(&data->lock);
 
-	/* config can only be changed when in standby */
-	ret = mma8452_standby(data);
-	if (ret < 0)
+	is_active = mma8452_is_active(data);
+	if (is_active < 0) {
+		ret = is_active;
 		goto fail;
+	}
+
+	/* config can only be changed when in standby */
+	if (is_active > 0) {
+		ret = mma8452_standby(data);
+		if (ret < 0)
+			goto fail;
+	}
 
 	ret = i2c_smbus_write_byte_data(data->client, reg, val);
 	if (ret < 0)
 		goto fail;
 
-	ret = mma8452_active(data);
-	if (ret < 0)
-		goto fail;
+	if (is_active > 0) {
+		ret = mma8452_active(data);
+		if (ret < 0)
+			goto fail;
+	}
 
 	ret = 0;
 fail:
@@ -418,7 +480,7 @@ fail:
 	return ret;
 }
 
-/* returns >0 if in freefall mode, 0 if not or <0 if an error occured */
+/* returns >0 if in freefall mode, 0 if not or <0 if an error occurred */
 static int mma8452_freefall_mode_enabled(struct mma8452_data *data)
 {
 	int val;
@@ -668,7 +730,8 @@ static int mma8452_read_event_config(str
 		if (ret < 0)
 			return ret;
 
-		return !!(ret & BIT(chan->scan_index + chip->ev_cfg_chan_shift));
+		return !!(ret & BIT(chan->scan_index +
+				    chip->ev_cfg_chan_shift));
 	default:
 		return -EINVAL;
 	}
@@ -682,7 +745,11 @@ static int mma8452_write_event_config(st
 {
 	struct mma8452_data *data = iio_priv(indio_dev);
 	const struct mma_chip_info *chip = data->chip_info;
-	int val;
+	int val, ret;
+
+	ret = mma8452_set_runtime_pm_state(data->client, state);
+	if (ret)
+		return ret;
 
 	switch (dir) {
 	case IIO_EV_DIR_FALLING:
@@ -990,6 +1057,7 @@ enum {
 	mma8453,
 	mma8652,
 	mma8653,
+	fxls8471,
 };
 
 static const struct mma_chip_info mma_chip_info_table[] = {
@@ -1003,7 +1071,7 @@ static const struct mma_chip_info mma_ch
 		 * bit.
 		 * The userspace interface uses m/s^2 and we declare micro units
 		 * So scale factor for 12 bit here is given by:
-		 * 	g * N * 1000000 / 2048 for N = 2, 4, 8 and g=9.80665
+		 *	g * N * 1000000 / 2048 for N = 2, 4, 8 and g=9.80665
 		 */
 		.mma_scales = { {0, 2394}, {0, 4788}, {0, 9577} },
 		.ev_cfg = MMA8452_TRANSIENT_CFG,
@@ -1081,6 +1149,22 @@ static const struct mma_chip_info mma_ch
 		.ev_ths_mask = MMA8452_FF_MT_THS_MASK,
 		.ev_count = MMA8452_FF_MT_COUNT,
 	},
+	[fxls8471] = {
+		.chip_id = FXLS8471_DEVICE_ID,
+		.channels = mma8451_channels,
+		.num_channels = ARRAY_SIZE(mma8451_channels),
+		.mma_scales = { {0, 2394}, {0, 4788}, {0, 9577} },
+		.ev_cfg = MMA8452_TRANSIENT_CFG,
+		.ev_cfg_ele = MMA8452_TRANSIENT_CFG_ELE,
+		.ev_cfg_chan_shift = 1,
+		.ev_src = MMA8452_TRANSIENT_SRC,
+		.ev_src_xe = MMA8452_TRANSIENT_SRC_XTRANSE,
+		.ev_src_ye = MMA8452_TRANSIENT_SRC_YTRANSE,
+		.ev_src_ze = MMA8452_TRANSIENT_SRC_ZTRANSE,
+		.ev_ths = MMA8452_TRANSIENT_THS,
+		.ev_ths_mask = MMA8452_TRANSIENT_THS_MASK,
+		.ev_count = MMA8452_TRANSIENT_COUNT,
+	},
 };
 
 static struct attribute *mma8452_attributes[] = {
@@ -1114,7 +1198,11 @@ static int mma8452_data_rdy_trigger_set_
 {
 	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
 	struct mma8452_data *data = iio_priv(indio_dev);
-	int reg;
+	int reg, ret;
+
+	ret = mma8452_set_runtime_pm_state(data->client, state);
+	if (ret)
+		return ret;
 
 	reg = i2c_smbus_read_byte_data(data->client, MMA8452_CTRL_REG4);
 	if (reg < 0)
@@ -1206,6 +1294,7 @@ static const struct of_device_id mma8452
 	{ .compatible = "fsl,mma8453", .data = &mma_chip_info_table[mma8453] },
 	{ .compatible = "fsl,mma8652", .data = &mma_chip_info_table[mma8652] },
 	{ .compatible = "fsl,mma8653", .data = &mma_chip_info_table[mma8653] },
+	{ .compatible = "fsl,fxls8471", .data = &mma_chip_info_table[fxls8471] },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, mma8452_dt_ids);
@@ -1243,6 +1332,7 @@ static int mma8452_probe(struct i2c_clie
 	case MMA8453_DEVICE_ID:
 	case MMA8652_DEVICE_ID:
 	case MMA8653_DEVICE_ID:
+	case FXLS8471_DEVICE_ID:
 		if (ret == data->chip_info->chip_id)
 			break;
 	default:
@@ -1340,6 +1430,15 @@ static int mma8452_probe(struct i2c_clie
 			goto buffer_cleanup;
 	}
 
+	ret = pm_runtime_set_active(&client->dev);
+	if (ret < 0)
+		goto buffer_cleanup;
+
+	pm_runtime_enable(&client->dev);
+	pm_runtime_set_autosuspend_delay(&client->dev,
+					 MMA8452_AUTO_SUSPEND_DELAY_MS);
+	pm_runtime_use_autosuspend(&client->dev);
+
 	ret = iio_device_register(indio_dev);
 	if (ret < 0)
 		goto buffer_cleanup;
@@ -1364,6 +1463,11 @@ static int mma8452_remove(struct i2c_cli
 	struct iio_dev *indio_dev = i2c_get_clientdata(client);
 
 	iio_device_unregister(indio_dev);
+
+	pm_runtime_disable(&client->dev);
+	pm_runtime_set_suspended(&client->dev);
+	pm_runtime_put_noidle(&client->dev);
+
 	iio_triggered_buffer_cleanup(indio_dev);
 	mma8452_trigger_cleanup(indio_dev);
 	mma8452_standby(iio_priv(indio_dev));
@@ -1371,6 +1475,45 @@ static int mma8452_remove(struct i2c_cli
 	return 0;
 }
 
+#ifdef CONFIG_PM
+static int mma8452_runtime_suspend(struct device *dev)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+	struct mma8452_data *data = iio_priv(indio_dev);
+	int ret;
+
+	mutex_lock(&data->lock);
+	ret = mma8452_standby(data);
+	mutex_unlock(&data->lock);
+	if (ret < 0) {
+		dev_err(&data->client->dev, "powering off device failed\n");
+		return -EAGAIN;
+	}
+
+	return 0;
+}
+
+static int mma8452_runtime_resume(struct device *dev)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+	struct mma8452_data *data = iio_priv(indio_dev);
+	int ret, sleep_val;
+
+	ret = mma8452_active(data);
+	if (ret < 0)
+		return ret;
+
+	ret = mma8452_get_odr_index(data);
+	sleep_val = 1000 / mma8452_samp_freq[ret][0];
+	if (sleep_val < 20)
+		usleep_range(sleep_val * 1000, 20000);
+	else
+		msleep_interruptible(sleep_val);
+
+	return 0;
+}
+#endif
+
 #ifdef CONFIG_PM_SLEEP
 static int mma8452_suspend(struct device *dev)
 {
@@ -1383,18 +1526,21 @@ static int mma8452_resume(struct device
 	return mma8452_active(iio_priv(i2c_get_clientdata(
 		to_i2c_client(dev))));
 }
-
-static SIMPLE_DEV_PM_OPS(mma8452_pm_ops, mma8452_suspend, mma8452_resume);
-#define MMA8452_PM_OPS (&mma8452_pm_ops)
-#else
-#define MMA8452_PM_OPS NULL
 #endif
 
+static const struct dev_pm_ops mma8452_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(mma8452_suspend, mma8452_resume)
+	SET_RUNTIME_PM_OPS(mma8452_runtime_suspend,
+			   mma8452_runtime_resume, NULL)
+};
+
 static const struct i2c_device_id mma8452_id[] = {
+	{ "mma8451", mma8451 },
 	{ "mma8452", mma8452 },
 	{ "mma8453", mma8453 },
 	{ "mma8652", mma8652 },
 	{ "mma8653", mma8653 },
+	{ "fxls8471", fxls8471 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, mma8452_id);
@@ -1403,7 +1549,7 @@ static struct i2c_driver mma8452_driver
 	.driver = {
 		.name	= "mma8452",
 		.of_match_table = of_match_ptr(mma8452_dt_ids),
-		.pm	= MMA8452_PM_OPS,
+		.pm	= &mma8452_pm_ops,
 	},
 	.probe = mma8452_probe,
 	.remove = mma8452_remove,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/accel/mma9553.c linux-libre-4.7-gnu/drivers/iio/accel/mma9553.c
--- linux-libre-4.6-gnu/drivers/iio/accel/mma9553.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/accel/mma9553.c	2016-07-24 15:23:50.000000000 -0400
@@ -17,7 +17,6 @@
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/acpi.h>
-#include <linux/gpio/consumer.h>
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
 #include <linux/iio/events.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/accel/mxc4005.c linux-libre-4.7-gnu/drivers/iio/accel/mxc4005.c
--- linux-libre-4.6-gnu/drivers/iio/accel/mxc4005.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/accel/mxc4005.c	2016-07-24 15:23:50.000000000 -0400
@@ -17,7 +17,6 @@
 #include <linux/i2c.h>
 #include <linux/iio/iio.h>
 #include <linux/acpi.h>
-#include <linux/gpio/consumer.h>
 #include <linux/regmap.h>
 #include <linux/iio/sysfs.h>
 #include <linux/iio/trigger.h>
@@ -380,31 +379,6 @@ static const struct iio_trigger_ops mxc4
 	.owner = THIS_MODULE,
 };
 
-static int mxc4005_gpio_probe(struct i2c_client *client,
-			      struct mxc4005_data *data)
-{
-	struct device *dev;
-	struct gpio_desc *gpio;
-	int ret;
-
-	if (!client)
-		return -EINVAL;
-
-	dev = &client->dev;
-
-	gpio = devm_gpiod_get_index(dev, "mxc4005_int", 0, GPIOD_IN);
-	if (IS_ERR(gpio)) {
-		dev_err(dev, "failed to get acpi gpio index\n");
-		return PTR_ERR(gpio);
-	}
-
-	ret = gpiod_to_irq(gpio);
-
-	dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret);
-
-	return ret;
-}
-
 static int mxc4005_chip_init(struct mxc4005_data *data)
 {
 	int ret;
@@ -470,9 +444,6 @@ static int mxc4005_probe(struct i2c_clie
 		return ret;
 	}
 
-	if (client->irq < 0)
-		client->irq = mxc4005_gpio_probe(client, data);
-
 	if (client->irq > 0) {
 		data->dready_trig = devm_iio_trigger_alloc(&client->dev,
 							   "%s-dev%d",
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/accel/st_accel_buffer.c linux-libre-4.7-gnu/drivers/iio/accel/st_accel_buffer.c
--- linux-libre-4.6-gnu/drivers/iio/accel/st_accel_buffer.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/accel/st_accel_buffer.c	2016-07-24 15:23:50.000000000 -0400
@@ -91,7 +91,7 @@ static const struct iio_buffer_setup_ops
 
 int st_accel_allocate_ring(struct iio_dev *indio_dev)
 {
-	return iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
+	return iio_triggered_buffer_setup(indio_dev, NULL,
 		&st_sensors_trigger_handler, &st_accel_buffer_setup_ops);
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/accel/st_accel_core.c linux-libre-4.7-gnu/drivers/iio/accel/st_accel_core.c
--- linux-libre-4.6-gnu/drivers/iio/accel/st_accel_core.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/accel/st_accel_core.c	2016-07-24 15:23:50.000000000 -0400
@@ -39,6 +39,9 @@
 #define ST_ACCEL_FS_AVL_6G			6
 #define ST_ACCEL_FS_AVL_8G			8
 #define ST_ACCEL_FS_AVL_16G			16
+#define ST_ACCEL_FS_AVL_100G			100
+#define ST_ACCEL_FS_AVL_200G			200
+#define ST_ACCEL_FS_AVL_400G			400
 
 /* CUSTOM VALUES FOR SENSOR 1 */
 #define ST_ACCEL_1_WAI_EXP			0x33
@@ -96,6 +99,8 @@
 #define ST_ACCEL_2_DRDY_IRQ_INT2_MASK		0x10
 #define ST_ACCEL_2_IHL_IRQ_ADDR			0x22
 #define ST_ACCEL_2_IHL_IRQ_MASK			0x80
+#define ST_ACCEL_2_OD_IRQ_ADDR			0x22
+#define ST_ACCEL_2_OD_IRQ_MASK			0x40
 #define ST_ACCEL_2_MULTIREAD_BIT		true
 
 /* CUSTOM VALUES FOR SENSOR 3 */
@@ -177,10 +182,39 @@
 #define ST_ACCEL_5_DRDY_IRQ_INT2_MASK		0x20
 #define ST_ACCEL_5_IHL_IRQ_ADDR			0x22
 #define ST_ACCEL_5_IHL_IRQ_MASK			0x80
+#define ST_ACCEL_5_OD_IRQ_ADDR			0x22
+#define ST_ACCEL_5_OD_IRQ_MASK			0x40
 #define ST_ACCEL_5_IG1_EN_ADDR			0x21
 #define ST_ACCEL_5_IG1_EN_MASK			0x08
 #define ST_ACCEL_5_MULTIREAD_BIT		false
 
+/* CUSTOM VALUES FOR SENSOR 6 */
+#define ST_ACCEL_6_WAI_EXP			0x32
+#define ST_ACCEL_6_ODR_ADDR			0x20
+#define ST_ACCEL_6_ODR_MASK			0x18
+#define ST_ACCEL_6_ODR_AVL_50HZ_VAL		0x00
+#define ST_ACCEL_6_ODR_AVL_100HZ_VAL		0x01
+#define ST_ACCEL_6_ODR_AVL_400HZ_VAL		0x02
+#define ST_ACCEL_6_ODR_AVL_1000HZ_VAL		0x03
+#define ST_ACCEL_6_PW_ADDR			0x20
+#define ST_ACCEL_6_PW_MASK			0x20
+#define ST_ACCEL_6_FS_ADDR			0x23
+#define ST_ACCEL_6_FS_MASK			0x30
+#define ST_ACCEL_6_FS_AVL_100_VAL		0x00
+#define ST_ACCEL_6_FS_AVL_200_VAL		0x01
+#define ST_ACCEL_6_FS_AVL_400_VAL		0x03
+#define ST_ACCEL_6_FS_AVL_100_GAIN		IIO_G_TO_M_S_2(49000)
+#define ST_ACCEL_6_FS_AVL_200_GAIN		IIO_G_TO_M_S_2(98000)
+#define ST_ACCEL_6_FS_AVL_400_GAIN		IIO_G_TO_M_S_2(195000)
+#define ST_ACCEL_6_BDU_ADDR			0x23
+#define ST_ACCEL_6_BDU_MASK			0x80
+#define ST_ACCEL_6_DRDY_IRQ_ADDR		0x22
+#define ST_ACCEL_6_DRDY_IRQ_INT1_MASK		0x02
+#define ST_ACCEL_6_DRDY_IRQ_INT2_MASK		0x10
+#define ST_ACCEL_6_IHL_IRQ_ADDR			0x22
+#define ST_ACCEL_6_IHL_IRQ_MASK			0x80
+#define ST_ACCEL_6_MULTIREAD_BIT		true
+
 static const struct iio_chan_spec st_accel_8bit_channels[] = {
 	ST_SENSORS_LSM_CHANNELS(IIO_ACCEL,
 			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
@@ -302,6 +336,7 @@ static const struct st_sensor_settings s
 			.mask_int2 = ST_ACCEL_1_DRDY_IRQ_INT2_MASK,
 			.addr_ihl = ST_ACCEL_1_IHL_IRQ_ADDR,
 			.mask_ihl = ST_ACCEL_1_IHL_IRQ_MASK,
+			.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
 		},
 		.multi_read_bit = ST_ACCEL_1_MULTIREAD_BIT,
 		.bootime = 2,
@@ -367,6 +402,9 @@ static const struct st_sensor_settings s
 			.mask_int2 = ST_ACCEL_2_DRDY_IRQ_INT2_MASK,
 			.addr_ihl = ST_ACCEL_2_IHL_IRQ_ADDR,
 			.mask_ihl = ST_ACCEL_2_IHL_IRQ_MASK,
+			.addr_od = ST_ACCEL_2_OD_IRQ_ADDR,
+			.mask_od = ST_ACCEL_2_OD_IRQ_MASK,
+			.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
 		},
 		.multi_read_bit = ST_ACCEL_2_MULTIREAD_BIT,
 		.bootime = 2,
@@ -444,6 +482,7 @@ static const struct st_sensor_settings s
 			.mask_int2 = ST_ACCEL_3_DRDY_IRQ_INT2_MASK,
 			.addr_ihl = ST_ACCEL_3_IHL_IRQ_ADDR,
 			.mask_ihl = ST_ACCEL_3_IHL_IRQ_MASK,
+			.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
 			.ig1 = {
 				.en_addr = ST_ACCEL_3_IG1_EN_ADDR,
 				.en_mask = ST_ACCEL_3_IG1_EN_MASK,
@@ -502,6 +541,7 @@ static const struct st_sensor_settings s
 		.drdy_irq = {
 			.addr = ST_ACCEL_4_DRDY_IRQ_ADDR,
 			.mask_int1 = ST_ACCEL_4_DRDY_IRQ_INT1_MASK,
+			.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
 		},
 		.multi_read_bit = ST_ACCEL_4_MULTIREAD_BIT,
 		.bootime = 2, /* guess */
@@ -553,10 +593,75 @@ static const struct st_sensor_settings s
 			.mask_int2 = ST_ACCEL_5_DRDY_IRQ_INT2_MASK,
 			.addr_ihl = ST_ACCEL_5_IHL_IRQ_ADDR,
 			.mask_ihl = ST_ACCEL_5_IHL_IRQ_MASK,
+			.addr_od = ST_ACCEL_5_OD_IRQ_ADDR,
+			.mask_od = ST_ACCEL_5_OD_IRQ_MASK,
+			.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
 		},
 		.multi_read_bit = ST_ACCEL_5_MULTIREAD_BIT,
 		.bootime = 2, /* guess */
 	},
+	{
+		.wai = ST_ACCEL_6_WAI_EXP,
+		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
+		.sensors_supported = {
+			[0] = H3LIS331DL_DRIVER_NAME,
+		},
+		.ch = (struct iio_chan_spec *)st_accel_12bit_channels,
+		.odr = {
+			.addr = ST_ACCEL_6_ODR_ADDR,
+			.mask = ST_ACCEL_6_ODR_MASK,
+			.odr_avl = {
+				{ 50, ST_ACCEL_6_ODR_AVL_50HZ_VAL },
+				{ 100, ST_ACCEL_6_ODR_AVL_100HZ_VAL, },
+				{ 400, ST_ACCEL_6_ODR_AVL_400HZ_VAL, },
+				{ 1000, ST_ACCEL_6_ODR_AVL_1000HZ_VAL, },
+			},
+		},
+		.pw = {
+			.addr = ST_ACCEL_6_PW_ADDR,
+			.mask = ST_ACCEL_6_PW_MASK,
+			.value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
+			.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
+		},
+		.enable_axis = {
+			.addr = ST_SENSORS_DEFAULT_AXIS_ADDR,
+			.mask = ST_SENSORS_DEFAULT_AXIS_MASK,
+		},
+		.fs = {
+			.addr = ST_ACCEL_6_FS_ADDR,
+			.mask = ST_ACCEL_6_FS_MASK,
+			.fs_avl = {
+				[0] = {
+					.num = ST_ACCEL_FS_AVL_100G,
+					.value = ST_ACCEL_6_FS_AVL_100_VAL,
+					.gain = ST_ACCEL_6_FS_AVL_100_GAIN,
+				},
+				[1] = {
+					.num = ST_ACCEL_FS_AVL_200G,
+					.value = ST_ACCEL_6_FS_AVL_200_VAL,
+					.gain = ST_ACCEL_6_FS_AVL_200_GAIN,
+				},
+				[2] = {
+					.num = ST_ACCEL_FS_AVL_400G,
+					.value = ST_ACCEL_6_FS_AVL_400_VAL,
+					.gain = ST_ACCEL_6_FS_AVL_400_GAIN,
+				},
+			},
+		},
+		.bdu = {
+			.addr = ST_ACCEL_6_BDU_ADDR,
+			.mask = ST_ACCEL_6_BDU_MASK,
+		},
+		.drdy_irq = {
+			.addr = ST_ACCEL_6_DRDY_IRQ_ADDR,
+			.mask_int1 = ST_ACCEL_6_DRDY_IRQ_INT1_MASK,
+			.mask_int2 = ST_ACCEL_6_DRDY_IRQ_INT2_MASK,
+			.addr_ihl = ST_ACCEL_6_IHL_IRQ_ADDR,
+			.mask_ihl = ST_ACCEL_6_IHL_IRQ_MASK,
+		},
+		.multi_read_bit = ST_ACCEL_6_MULTIREAD_BIT,
+		.bootime = 2,
+	},
 };
 
 static int st_accel_read_raw(struct iio_dev *indio_dev,
@@ -636,6 +741,7 @@ static const struct iio_info accel_info
 static const struct iio_trigger_ops st_accel_trigger_ops = {
 	.owner = THIS_MODULE,
 	.set_trigger_state = ST_ACCEL_TRIGGER_SET_STATE,
+	.validate_device = st_sensors_validate_device,
 };
 #define ST_ACCEL_TRIGGER_OPS (&st_accel_trigger_ops)
 #else
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/accel/st_accel.h linux-libre-4.7-gnu/drivers/iio/accel/st_accel.h
--- linux-libre-4.6-gnu/drivers/iio/accel/st_accel.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/accel/st_accel.h	2016-07-24 15:23:50.000000000 -0400
@@ -14,6 +14,7 @@
 #include <linux/types.h>
 #include <linux/iio/common/st_sensors.h>
 
+#define H3LIS331DL_DRIVER_NAME		"h3lis331dl_accel"
 #define LIS3LV02DL_ACCEL_DEV_NAME	"lis3lv02dl_accel"
 #define LSM303DLHC_ACCEL_DEV_NAME	"lsm303dlhc_accel"
 #define LIS3DH_ACCEL_DEV_NAME		"lis3dh"
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/accel/st_accel_i2c.c linux-libre-4.7-gnu/drivers/iio/accel/st_accel_i2c.c
--- linux-libre-4.6-gnu/drivers/iio/accel/st_accel_i2c.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/accel/st_accel_i2c.c	2016-07-24 15:23:50.000000000 -0400
@@ -76,6 +76,10 @@ static const struct of_device_id st_acce
 		.compatible = "st,lis2dh12-accel",
 		.data = LIS2DH12_ACCEL_DEV_NAME,
 	},
+	{
+		.compatible = "st,h3lis331dl-accel",
+		.data = H3LIS331DL_DRIVER_NAME,
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(of, st_accel_of_match);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/accel/stk8312.c linux-libre-4.7-gnu/drivers/iio/accel/stk8312.c
--- linux-libre-4.6-gnu/drivers/iio/accel/stk8312.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/accel/stk8312.c	2016-07-24 15:23:50.000000000 -0400
@@ -11,7 +11,6 @@
  */
 
 #include <linux/acpi.h>
-#include <linux/gpio/consumer.h>
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/accel/stk8ba50.c linux-libre-4.7-gnu/drivers/iio/accel/stk8ba50.c
--- linux-libre-4.6-gnu/drivers/iio/accel/stk8ba50.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/accel/stk8ba50.c	2016-07-24 15:23:50.000000000 -0400
@@ -11,7 +11,6 @@
  */
 
 #include <linux/acpi.h>
-#include <linux/gpio/consumer.h>
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/adc/ad7266.c linux-libre-4.7-gnu/drivers/iio/adc/ad7266.c
--- linux-libre-4.6-gnu/drivers/iio/adc/ad7266.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/adc/ad7266.c	2016-07-24 15:23:50.000000000 -0400
@@ -396,8 +396,8 @@ static int ad7266_probe(struct spi_devic
 
 	st = iio_priv(indio_dev);
 
-	st->reg = devm_regulator_get(&spi->dev, "vref");
-	if (!IS_ERR_OR_NULL(st->reg)) {
+	st->reg = devm_regulator_get_optional(&spi->dev, "vref");
+	if (!IS_ERR(st->reg)) {
 		ret = regulator_enable(st->reg);
 		if (ret)
 			return ret;
@@ -408,6 +408,9 @@ static int ad7266_probe(struct spi_devic
 
 		st->vref_mv = ret / 1000;
 	} else {
+		/* Any other error indicates that the regulator does exist */
+		if (PTR_ERR(st->reg) != -ENODEV)
+			return PTR_ERR(st->reg);
 		/* Use internal reference */
 		st->vref_mv = 2500;
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/adc/ad799x.c linux-libre-4.7-gnu/drivers/iio/adc/ad799x.c
--- linux-libre-4.6-gnu/drivers/iio/adc/ad799x.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/adc/ad799x.c	2016-07-24 15:23:50.000000000 -0400
@@ -477,7 +477,7 @@ static int ad799x_read_event_value(struc
 	if (ret < 0)
 		return ret;
 	*val = (ret >> chan->scan_type.shift) &
-		GENMASK(chan->scan_type.realbits - 1 , 0);
+		GENMASK(chan->scan_type.realbits - 1, 0);
 
 	return IIO_VAL_INT;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/adc/at91_adc.c linux-libre-4.7-gnu/drivers/iio/adc/at91_adc.c
--- linux-libre-4.6-gnu/drivers/iio/adc/at91_adc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/adc/at91_adc.c	2016-07-24 15:23:50.000000000 -0400
@@ -797,8 +797,8 @@ static u32 calc_startup_ticks_9x5(u32 st
 	 * Startup Time = <lookup_table_value> / ADC Clock
 	 */
 	const int startup_lookup[] = {
-		0  , 8  , 16 , 24 ,
-		64 , 80 , 96 , 112,
+		0,   8,   16,  24,
+		64,  80,  96,  112,
 		512, 576, 640, 704,
 		768, 832, 896, 960
 		};
@@ -924,14 +924,14 @@ static int at91_adc_probe_dt(struct at91
 			ret = -EINVAL;
 			goto error_ret;
 		}
-	        trig->name = name;
+		trig->name = name;
 
 		if (of_property_read_u32(trig_node, "trigger-value", &prop)) {
 			dev_err(&idev->dev, "Missing trigger-value property in the DT.\n");
 			ret = -EINVAL;
 			goto error_ret;
 		}
-	        trig->value = prop;
+		trig->value = prop;
 		trig->is_external = of_property_read_bool(trig_node, "trigger-external");
 		i++;
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/adc/at91-sama5d2_adc.c linux-libre-4.7-gnu/drivers/iio/adc/at91-sama5d2_adc.c
--- linux-libre-4.6-gnu/drivers/iio/adc/at91-sama5d2_adc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/adc/at91-sama5d2_adc.c	2016-07-24 15:23:50.000000000 -0400
@@ -66,8 +66,10 @@
 #define	AT91_SAMA5D2_MR_PRESCAL(v)	((v) << AT91_SAMA5D2_MR_PRESCAL_OFFSET)
 #define	AT91_SAMA5D2_MR_PRESCAL_OFFSET	8
 #define	AT91_SAMA5D2_MR_PRESCAL_MAX	0xff
+#define AT91_SAMA5D2_MR_PRESCAL_MASK	GENMASK(15, 8)
 /* Startup Time */
 #define	AT91_SAMA5D2_MR_STARTUP(v)	((v) << 16)
+#define AT91_SAMA5D2_MR_STARTUP_MASK	GENMASK(19, 16)
 /* Analog Change */
 #define	AT91_SAMA5D2_MR_ANACH		BIT(23)
 /* Tracking Time */
@@ -92,13 +94,13 @@
 /* Last Converted Data Register */
 #define AT91_SAMA5D2_LCDR	0x20
 /* Interrupt Enable Register */
-#define AT91_SAMA5D2_IER		0x24
+#define AT91_SAMA5D2_IER	0x24
 /* Interrupt Disable Register */
-#define AT91_SAMA5D2_IDR		0x28
+#define AT91_SAMA5D2_IDR	0x28
 /* Interrupt Mask Register */
-#define AT91_SAMA5D2_IMR		0x2c
+#define AT91_SAMA5D2_IMR	0x2c
 /* Interrupt Status Register */
-#define AT91_SAMA5D2_ISR		0x30
+#define AT91_SAMA5D2_ISR	0x30
 /* Last Channel Trigger Mode Register */
 #define AT91_SAMA5D2_LCTMR	0x34
 /* Last Channel Compare Window Register */
@@ -106,17 +108,20 @@
 /* Overrun Status Register */
 #define AT91_SAMA5D2_OVER	0x3c
 /* Extended Mode Register */
-#define AT91_SAMA5D2_EMR		0x40
+#define AT91_SAMA5D2_EMR	0x40
 /* Compare Window Register */
-#define AT91_SAMA5D2_CWR		0x44
+#define AT91_SAMA5D2_CWR	0x44
 /* Channel Gain Register */
-#define AT91_SAMA5D2_CGR		0x48
+#define AT91_SAMA5D2_CGR	0x48
+
 /* Channel Offset Register */
-#define AT91_SAMA5D2_COR		0x4c
+#define AT91_SAMA5D2_COR	0x4c
+#define AT91_SAMA5D2_COR_DIFF_OFFSET	16
+
 /* Channel Data Register 0 */
 #define AT91_SAMA5D2_CDR0	0x50
 /* Analog Control Register */
-#define AT91_SAMA5D2_ACR		0x94
+#define AT91_SAMA5D2_ACR	0x94
 /* Touchscreen Mode Register */
 #define AT91_SAMA5D2_TSMR	0xb0
 /* Touchscreen X Position Register */
@@ -130,7 +135,7 @@
 /* Correction Select Register */
 #define AT91_SAMA5D2_COSR	0xd0
 /* Correction Value Register */
-#define AT91_SAMA5D2_CVR		0xd4
+#define AT91_SAMA5D2_CVR	0xd4
 /* Channel Error Correction Register */
 #define AT91_SAMA5D2_CECR	0xd8
 /* Write Protection Mode Register */
@@ -140,7 +145,7 @@
 /* Version Register */
 #define AT91_SAMA5D2_VERSION	0xfc
 
-#define AT91_AT91_SAMA5D2_CHAN(num, addr)				\
+#define AT91_SAMA5D2_CHAN_SINGLE(num, addr)				\
 	{								\
 		.type = IIO_VOLTAGE,					\
 		.channel = num,						\
@@ -156,6 +161,24 @@
 		.indexed = 1,						\
 	}
 
+#define AT91_SAMA5D2_CHAN_DIFF(num, num2, addr)				\
+	{								\
+		.type = IIO_VOLTAGE,					\
+		.differential = 1,					\
+		.channel = num,						\
+		.channel2 = num2,					\
+		.address = addr,					\
+		.scan_type = {						\
+			.sign = 's',					\
+			.realbits = 12,					\
+		},							\
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
+		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\
+		.datasheet_name = "CH"#num"-CH"#num2,			\
+		.indexed = 1,						\
+	}
+
 #define at91_adc_readl(st, reg)		readl_relaxed(st->base + reg)
 #define at91_adc_writel(st, reg, val)	writel_relaxed(val, st->base + reg)
 
@@ -185,18 +208,24 @@ struct at91_adc_state {
 };
 
 static const struct iio_chan_spec at91_adc_channels[] = {
-	AT91_AT91_SAMA5D2_CHAN(0, 0x50),
-	AT91_AT91_SAMA5D2_CHAN(1, 0x54),
-	AT91_AT91_SAMA5D2_CHAN(2, 0x58),
-	AT91_AT91_SAMA5D2_CHAN(3, 0x5c),
-	AT91_AT91_SAMA5D2_CHAN(4, 0x60),
-	AT91_AT91_SAMA5D2_CHAN(5, 0x64),
-	AT91_AT91_SAMA5D2_CHAN(6, 0x68),
-	AT91_AT91_SAMA5D2_CHAN(7, 0x6c),
-	AT91_AT91_SAMA5D2_CHAN(8, 0x70),
-	AT91_AT91_SAMA5D2_CHAN(9, 0x74),
-	AT91_AT91_SAMA5D2_CHAN(10, 0x78),
-	AT91_AT91_SAMA5D2_CHAN(11, 0x7c),
+	AT91_SAMA5D2_CHAN_SINGLE(0, 0x50),
+	AT91_SAMA5D2_CHAN_SINGLE(1, 0x54),
+	AT91_SAMA5D2_CHAN_SINGLE(2, 0x58),
+	AT91_SAMA5D2_CHAN_SINGLE(3, 0x5c),
+	AT91_SAMA5D2_CHAN_SINGLE(4, 0x60),
+	AT91_SAMA5D2_CHAN_SINGLE(5, 0x64),
+	AT91_SAMA5D2_CHAN_SINGLE(6, 0x68),
+	AT91_SAMA5D2_CHAN_SINGLE(7, 0x6c),
+	AT91_SAMA5D2_CHAN_SINGLE(8, 0x70),
+	AT91_SAMA5D2_CHAN_SINGLE(9, 0x74),
+	AT91_SAMA5D2_CHAN_SINGLE(10, 0x78),
+	AT91_SAMA5D2_CHAN_SINGLE(11, 0x7c),
+	AT91_SAMA5D2_CHAN_DIFF(0, 1, 0x50),
+	AT91_SAMA5D2_CHAN_DIFF(2, 3, 0x58),
+	AT91_SAMA5D2_CHAN_DIFF(4, 5, 0x60),
+	AT91_SAMA5D2_CHAN_DIFF(6, 7, 0x68),
+	AT91_SAMA5D2_CHAN_DIFF(8, 9, 0x70),
+	AT91_SAMA5D2_CHAN_DIFF(10, 11, 0x78),
 };
 
 static unsigned at91_adc_startup_time(unsigned startup_time_min,
@@ -226,7 +255,7 @@ static unsigned at91_adc_startup_time(un
 static void at91_adc_setup_samp_freq(struct at91_adc_state *st, unsigned freq)
 {
 	struct iio_dev *indio_dev = iio_priv_to_dev(st);
-	unsigned f_per, prescal, startup;
+	unsigned f_per, prescal, startup, mr;
 
 	f_per = clk_get_rate(st->per_clk);
 	prescal = (f_per / (2 * freq)) - 1;
@@ -234,10 +263,11 @@ static void at91_adc_setup_samp_freq(str
 	startup = at91_adc_startup_time(st->soc_info.startup_time,
 					freq / 1000);
 
-	at91_adc_writel(st, AT91_SAMA5D2_MR,
-			AT91_SAMA5D2_MR_TRANSFER(2)
-			| AT91_SAMA5D2_MR_STARTUP(startup)
-			| AT91_SAMA5D2_MR_PRESCAL(prescal));
+	mr = at91_adc_readl(st, AT91_SAMA5D2_MR);
+	mr &= ~(AT91_SAMA5D2_MR_STARTUP_MASK | AT91_SAMA5D2_MR_PRESCAL_MASK);
+	mr |= AT91_SAMA5D2_MR_STARTUP(startup);
+	mr |= AT91_SAMA5D2_MR_PRESCAL(prescal);
+	at91_adc_writel(st, AT91_SAMA5D2_MR, mr);
 
 	dev_dbg(&indio_dev->dev, "freq: %u, startup: %u, prescal: %u\n",
 		freq, startup, prescal);
@@ -278,6 +308,7 @@ static int at91_adc_read_raw(struct iio_
 			     int *val, int *val2, long mask)
 {
 	struct at91_adc_state *st = iio_priv(indio_dev);
+	u32 cor = 0;
 	int ret;
 
 	switch (mask) {
@@ -286,6 +317,11 @@ static int at91_adc_read_raw(struct iio_
 
 		st->chan = chan;
 
+		if (chan->differential)
+			cor = (BIT(chan->channel) | BIT(chan->channel2)) <<
+			      AT91_SAMA5D2_COR_DIFF_OFFSET;
+
+		at91_adc_writel(st, AT91_SAMA5D2_COR, cor);
 		at91_adc_writel(st, AT91_SAMA5D2_CHER, BIT(chan->channel));
 		at91_adc_writel(st, AT91_SAMA5D2_IER, BIT(chan->channel));
 		at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_START);
@@ -298,6 +334,8 @@ static int at91_adc_read_raw(struct iio_
 
 		if (ret > 0) {
 			*val = st->conversion_value;
+			if (chan->scan_type.sign == 's')
+				*val = sign_extend32(*val, 11);
 			ret = IIO_VAL_INT;
 			st->conversion_done = false;
 		}
@@ -310,6 +348,8 @@ static int at91_adc_read_raw(struct iio_
 
 	case IIO_CHAN_INFO_SCALE:
 		*val = st->vref_uv / 1000;
+		if (chan->differential)
+			*val *= 2;
 		*val2 = chan->scan_type.realbits;
 		return IIO_VAL_FRACTIONAL_LOG2;
 
@@ -444,6 +484,12 @@ static int at91_adc_probe(struct platfor
 
 	at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_SWRST);
 	at91_adc_writel(st, AT91_SAMA5D2_IDR, 0xffffffff);
+	/*
+	 * Transfer field must be set to 2 according to the datasheet and
+	 * allows different analog settings for each channel.
+	 */
+	at91_adc_writel(st, AT91_SAMA5D2_MR,
+			AT91_SAMA5D2_MR_TRANSFER(2) | AT91_SAMA5D2_MR_ANACH);
 
 	at91_adc_setup_samp_freq(st, st->soc_info.min_sample_rate);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/adc/ina2xx-adc.c linux-libre-4.7-gnu/drivers/iio/adc/ina2xx-adc.c
--- linux-libre-4.6-gnu/drivers/iio/adc/ina2xx-adc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/adc/ina2xx-adc.c	2016-07-24 15:23:50.000000000 -0400
@@ -185,9 +185,9 @@ static int ina2xx_read_raw(struct iio_de
 	case IIO_CHAN_INFO_SCALE:
 		switch (chan->address) {
 		case INA2XX_SHUNT_VOLTAGE:
-			/* processed (mV) = raw*1000/shunt_div */
+			/* processed (mV) = raw/shunt_div */
 			*val2 = chip->config->shunt_div;
-			*val = 1000;
+			*val = 1;
 			return IIO_VAL_FRACTIONAL;
 
 		case INA2XX_BUS_VOLTAGE:
@@ -350,6 +350,23 @@ static ssize_t ina2xx_allow_async_readou
 	return len;
 }
 
+/*
+ * Set current LSB to 1mA, shunt is in uOhms
+ * (equation 13 in datasheet). We hardcode a Current_LSB
+ * of 1.0 x10-6. The only remaining parameter is RShunt.
+ * There is no need to expose the CALIBRATION register
+ * to the user for now. But we need to reset this register
+ * if the user updates RShunt after driver init, e.g upon
+ * reading an EEPROM/Probe-type value.
+ */
+static int ina2xx_set_calibration(struct ina2xx_chip_info *chip)
+{
+	u16 regval = DIV_ROUND_CLOSEST(chip->config->calibration_factor,
+				   chip->shunt_resistor);
+
+	return regmap_write(chip->regmap, INA2XX_CALIBRATION, regval);
+}
+
 static int set_shunt_resistor(struct ina2xx_chip_info *chip, unsigned int val)
 {
 	if (val <= 0 || val > chip->config->calibration_factor)
@@ -385,6 +402,11 @@ static ssize_t ina2xx_shunt_resistor_sto
 	if (ret)
 		return ret;
 
+	/* Update the Calibration register */
+	ret = ina2xx_set_calibration(chip);
+	if (ret)
+		return ret;
+
 	return len;
 }
 
@@ -602,24 +624,11 @@ static const struct iio_info ina2xx_info
 /* Initialize the configuration and calibration registers. */
 static int ina2xx_init(struct ina2xx_chip_info *chip, unsigned int config)
 {
-	u16 regval;
-	int ret;
-
-	ret = regmap_write(chip->regmap, INA2XX_CONFIG, config);
+	int ret = regmap_write(chip->regmap, INA2XX_CONFIG, config);
 	if (ret)
 		return ret;
 
-	/*
-	 * Set current LSB to 1mA, shunt is in uOhms
-	 * (equation 13 in datasheet). We hardcode a Current_LSB
-	 * of 1.0 x10-6. The only remaining parameter is RShunt.
-	 * There is no need to expose the CALIBRATION register
-	 * to the user for now.
-	 */
-	regval = DIV_ROUND_CLOSEST(chip->config->calibration_factor,
-				   chip->shunt_resistor);
-
-	return regmap_write(chip->regmap, INA2XX_CALIBRATION, regval);
+	return ina2xx_set_calibration(chip);
 }
 
 static int ina2xx_probe(struct i2c_client *client,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/adc/Kconfig linux-libre-4.7-gnu/drivers/iio/adc/Kconfig
--- linux-libre-4.6-gnu/drivers/iio/adc/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/adc/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -242,6 +242,16 @@ config LP8788_ADC
 	  To compile this driver as a module, choose M here: the module will be
 	  called lp8788_adc.
 
+config LPC18XX_ADC
+	tristate "NXP LPC18xx ADC driver"
+	depends on ARCH_LPC18XX || COMPILE_TEST
+	depends on OF && HAS_IOMEM
+	help
+	  Say yes here to build support for NXP LPC18XX ADC.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called lpc18xx_adc.
+
 config MAX1027
 	tristate "Maxim max1027 ADC driver"
 	depends on SPI
@@ -375,11 +385,11 @@ config ROCKCHIP_SARADC
 	  module will be called rockchip_saradc.
 
 config TI_ADC081C
-	tristate "Texas Instruments ADC081C021/027"
+	tristate "Texas Instruments ADC081C/ADC101C/ADC121C family"
 	depends on I2C
 	help
-	  If you say yes here you get support for Texas Instruments ADC081C021
-	  and ADC081C027 ADC chips.
+	  If you say yes here you get support for Texas Instruments ADC081C,
+	  ADC101C and ADC121C ADC chips.
 
 	  This driver can also be built as a module. If so, the module will be
 	  called ti-adc081c.
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/adc/lpc18xx_adc.c linux-libre-4.7-gnu/drivers/iio/adc/lpc18xx_adc.c
--- linux-libre-4.6-gnu/drivers/iio/adc/lpc18xx_adc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/iio/adc/lpc18xx_adc.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,231 @@
+/*
+ * IIO ADC driver for NXP LPC18xx ADC
+ *
+ * Copyright (C) 2016 Joachim Eastwood <manabian@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * UNSUPPORTED hardware features:
+ *  - Hardware triggers
+ *  - Burst mode
+ *  - Interrupts
+ *  - DMA
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/driver.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+
+/* LPC18XX ADC registers and bits */
+#define LPC18XX_ADC_CR			0x000
+#define  LPC18XX_ADC_CR_CLKDIV_SHIFT	8
+#define  LPC18XX_ADC_CR_PDN		BIT(21)
+#define  LPC18XX_ADC_CR_START_NOW	(0x1 << 24)
+#define LPC18XX_ADC_GDR			0x004
+
+/* Data register bits */
+#define LPC18XX_ADC_SAMPLE_SHIFT	6
+#define LPC18XX_ADC_SAMPLE_MASK		0x3ff
+#define LPC18XX_ADC_CONV_DONE		BIT(31)
+
+/* Clock should be 4.5 MHz or less */
+#define LPC18XX_ADC_CLK_TARGET		4500000
+
+struct lpc18xx_adc {
+	struct regulator *vref;
+	void __iomem *base;
+	struct device *dev;
+	struct mutex lock;
+	struct clk *clk;
+	u32 cr_reg;
+};
+
+#define LPC18XX_ADC_CHAN(_idx) {				\
+	.type = IIO_VOLTAGE,					\
+	.indexed = 1,						\
+	.channel = _idx,					\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
+}
+
+static const struct iio_chan_spec lpc18xx_adc_iio_channels[] = {
+	LPC18XX_ADC_CHAN(0),
+	LPC18XX_ADC_CHAN(1),
+	LPC18XX_ADC_CHAN(2),
+	LPC18XX_ADC_CHAN(3),
+	LPC18XX_ADC_CHAN(4),
+	LPC18XX_ADC_CHAN(5),
+	LPC18XX_ADC_CHAN(6),
+	LPC18XX_ADC_CHAN(7),
+};
+
+static int lpc18xx_adc_read_chan(struct lpc18xx_adc *adc, unsigned int ch)
+{
+	int ret;
+	u32 reg;
+
+	reg = adc->cr_reg | BIT(ch) | LPC18XX_ADC_CR_START_NOW;
+	writel(reg, adc->base + LPC18XX_ADC_CR);
+
+	ret = readl_poll_timeout(adc->base + LPC18XX_ADC_GDR, reg,
+				 reg & LPC18XX_ADC_CONV_DONE, 3, 9);
+	if (ret) {
+		dev_warn(adc->dev, "adc read timed out\n");
+		return ret;
+	}
+
+	return (reg >> LPC18XX_ADC_SAMPLE_SHIFT) & LPC18XX_ADC_SAMPLE_MASK;
+}
+
+static int lpc18xx_adc_read_raw(struct iio_dev *indio_dev,
+				struct iio_chan_spec const *chan,
+				int *val, int *val2, long mask)
+{
+	struct lpc18xx_adc *adc = iio_priv(indio_dev);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		mutex_lock(&adc->lock);
+		*val = lpc18xx_adc_read_chan(adc, chan->channel);
+		mutex_unlock(&adc->lock);
+		if (*val < 0)
+			return *val;
+
+		return IIO_VAL_INT;
+
+	case IIO_CHAN_INFO_SCALE:
+		*val = regulator_get_voltage(adc->vref) / 1000;
+		*val2 = 10;
+
+		return IIO_VAL_FRACTIONAL_LOG2;
+	}
+
+	return -EINVAL;
+}
+
+static const struct iio_info lpc18xx_adc_info = {
+	.read_raw = lpc18xx_adc_read_raw,
+	.driver_module = THIS_MODULE,
+};
+
+static int lpc18xx_adc_probe(struct platform_device *pdev)
+{
+	struct iio_dev *indio_dev;
+	struct lpc18xx_adc *adc;
+	struct resource *res;
+	unsigned int clkdiv;
+	unsigned long rate;
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, indio_dev);
+	adc = iio_priv(indio_dev);
+	adc->dev = &pdev->dev;
+	mutex_init(&adc->lock);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	adc->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(adc->base))
+		return PTR_ERR(adc->base);
+
+	adc->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(adc->clk)) {
+		dev_err(&pdev->dev, "error getting clock\n");
+		return PTR_ERR(adc->clk);
+	}
+
+	rate = clk_get_rate(adc->clk);
+	clkdiv = DIV_ROUND_UP(rate, LPC18XX_ADC_CLK_TARGET);
+
+	adc->vref = devm_regulator_get(&pdev->dev, "vref");
+	if (IS_ERR(adc->vref)) {
+		dev_err(&pdev->dev, "error getting regulator\n");
+		return PTR_ERR(adc->vref);
+	}
+
+	indio_dev->name = dev_name(&pdev->dev);
+	indio_dev->dev.parent = &pdev->dev;
+	indio_dev->info = &lpc18xx_adc_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = lpc18xx_adc_iio_channels;
+	indio_dev->num_channels = ARRAY_SIZE(lpc18xx_adc_iio_channels);
+
+	ret = regulator_enable(adc->vref);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to enable regulator\n");
+		return ret;
+	}
+
+	ret = clk_prepare_enable(adc->clk);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to enable clock\n");
+		goto dis_reg;
+	}
+
+	adc->cr_reg = (clkdiv << LPC18XX_ADC_CR_CLKDIV_SHIFT) |
+			LPC18XX_ADC_CR_PDN;
+	writel(adc->cr_reg, adc->base + LPC18XX_ADC_CR);
+
+	ret = iio_device_register(indio_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to register device\n");
+		goto dis_clk;
+	}
+
+	return 0;
+
+dis_clk:
+	writel(0, adc->base + LPC18XX_ADC_CR);
+	clk_disable_unprepare(adc->clk);
+dis_reg:
+	regulator_disable(adc->vref);
+	return ret;
+}
+
+static int lpc18xx_adc_remove(struct platform_device *pdev)
+{
+	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+	struct lpc18xx_adc *adc = iio_priv(indio_dev);
+
+	iio_device_unregister(indio_dev);
+
+	writel(0, adc->base + LPC18XX_ADC_CR);
+	clk_disable_unprepare(adc->clk);
+	regulator_disable(adc->vref);
+
+	return 0;
+}
+
+static const struct of_device_id lpc18xx_adc_match[] = {
+	{ .compatible = "nxp,lpc1850-adc" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, lpc18xx_adc_match);
+
+static struct platform_driver lpc18xx_adc_driver = {
+	.probe	= lpc18xx_adc_probe,
+	.remove	= lpc18xx_adc_remove,
+	.driver	= {
+		.name = "lpc18xx-adc",
+		.of_match_table = lpc18xx_adc_match,
+	},
+};
+module_platform_driver(lpc18xx_adc_driver);
+
+MODULE_DESCRIPTION("LPC18xx ADC driver");
+MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/adc/Makefile linux-libre-4.7-gnu/drivers/iio/adc/Makefile
--- linux-libre-4.6-gnu/drivers/iio/adc/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/adc/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -25,6 +25,7 @@ obj-$(CONFIG_HI8435) += hi8435.o
 obj-$(CONFIG_IMX7D_ADC) += imx7d_adc.o
 obj-$(CONFIG_INA2XX_ADC) += ina2xx-adc.o
 obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
+obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o
 obj-$(CONFIG_MAX1027) += max1027.o
 obj-$(CONFIG_MAX1363) += max1363.o
 obj-$(CONFIG_MCP320X) += mcp320x.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/adc/mcp3422.c linux-libre-4.7-gnu/drivers/iio/adc/mcp3422.c
--- linux-libre-4.6-gnu/drivers/iio/adc/mcp3422.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/adc/mcp3422.c	2016-07-24 15:23:50.000000000 -0400
@@ -61,9 +61,9 @@
 
 static const int mcp3422_scales[4][4] = {
 	{ 1000000, 500000, 250000, 125000 },
-	{ 250000 , 125000, 62500 , 31250  },
-	{ 62500  , 31250 , 15625 , 7812   },
-	{ 15625  , 7812  , 3906  , 1953   } };
+	{ 250000,  125000, 62500,  31250  },
+	{ 62500,   31250,  15625,  7812   },
+	{ 15625,   7812,   3906,   1953   } };
 
 /* Constant msleep times for data acquisitions */
 static const int mcp3422_read_times[4] = {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/adc/mxs-lradc.c linux-libre-4.7-gnu/drivers/iio/adc/mxs-lradc.c
--- linux-libre-4.6-gnu/drivers/iio/adc/mxs-lradc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/adc/mxs-lradc.c	2016-07-24 15:23:50.000000000 -0400
@@ -686,6 +686,17 @@ static void mxs_lradc_prepare_pressure(s
 
 static void mxs_lradc_enable_touch_detection(struct mxs_lradc *lradc)
 {
+	/* Configure the touchscreen type */
+	if (lradc->soc == IMX28_LRADC) {
+		mxs_lradc_reg_clear(lradc, LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE,
+				    LRADC_CTRL0);
+
+		if (lradc->use_touchscreen == MXS_LRADC_TOUCHSCREEN_5WIRE)
+			mxs_lradc_reg_set(lradc,
+					  LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE,
+					  LRADC_CTRL0);
+	}
+
 	mxs_lradc_setup_touch_detection(lradc);
 
 	lradc->cur_plate = LRADC_TOUCH;
@@ -1127,6 +1138,7 @@ static int mxs_lradc_ts_register(struct
 	__set_bit(EV_ABS, input->evbit);
 	__set_bit(EV_KEY, input->evbit);
 	__set_bit(BTN_TOUCH, input->keybit);
+	__set_bit(INPUT_PROP_DIRECT, input->propbit);
 	input_set_abs_params(input, ABS_X, 0, LRADC_SINGLE_SAMPLE_MASK, 0, 0);
 	input_set_abs_params(input, ABS_Y, 0, LRADC_SINGLE_SAMPLE_MASK, 0, 0);
 	input_set_abs_params(input, ABS_PRESSURE, 0, LRADC_SINGLE_SAMPLE_MASK,
@@ -1475,18 +1487,13 @@ static const struct iio_chan_spec mx28_l
 	MXS_ADC_CHAN(15, IIO_VOLTAGE, "VDD5V"),
 };
 
-static int mxs_lradc_hw_init(struct mxs_lradc *lradc)
+static void mxs_lradc_hw_init(struct mxs_lradc *lradc)
 {
 	/* The ADC always uses DELAY CHANNEL 0. */
 	const u32 adc_cfg =
 		(1 << (LRADC_DELAY_TRIGGER_DELAYS_OFFSET + 0)) |
 		(LRADC_DELAY_TIMER_PER << LRADC_DELAY_DELAY_OFFSET);
 
-	int ret = stmp_reset_block(lradc->base);
-
-	if (ret)
-		return ret;
-
 	/* Configure DELAY CHANNEL 0 for generic ADC sampling. */
 	mxs_lradc_reg_wrt(lradc, adc_cfg, LRADC_DELAY(0));
 
@@ -1495,20 +1502,8 @@ static int mxs_lradc_hw_init(struct mxs_
 	mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(2));
 	mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(3));
 
-	/* Configure the touchscreen type */
-	if (lradc->soc == IMX28_LRADC) {
-		mxs_lradc_reg_clear(lradc, LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE,
-				    LRADC_CTRL0);
-
-	if (lradc->use_touchscreen == MXS_LRADC_TOUCHSCREEN_5WIRE)
-		mxs_lradc_reg_set(lradc, LRADC_CTRL0_MX28_TOUCH_SCREEN_TYPE,
-				  LRADC_CTRL0);
-	}
-
 	/* Start internal temperature sensing. */
 	mxs_lradc_reg_wrt(lradc, 0, LRADC_CTRL2);
-
-	return 0;
 }
 
 static void mxs_lradc_hw_stop(struct mxs_lradc *lradc)
@@ -1708,11 +1703,13 @@ static int mxs_lradc_probe(struct platfo
 		}
 	}
 
-	/* Configure the hardware. */
-	ret = mxs_lradc_hw_init(lradc);
+	ret = stmp_reset_block(lradc->base);
 	if (ret)
 		goto err_dev;
 
+	/* Configure the hardware. */
+	mxs_lradc_hw_init(lradc);
+
 	/* Register the touchscreen input device. */
 	if (touch_ret == 0) {
 		ret = mxs_lradc_ts_register(lradc);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/adc/rockchip_saradc.c linux-libre-4.7-gnu/drivers/iio/adc/rockchip_saradc.c
--- linux-libre-4.6-gnu/drivers/iio/adc/rockchip_saradc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/adc/rockchip_saradc.c	2016-07-24 15:23:50.000000000 -0400
@@ -159,6 +159,22 @@ static const struct rockchip_saradc_data
 	.clk_rate = 50000,
 };
 
+static const struct iio_chan_spec rockchip_rk3399_saradc_iio_channels[] = {
+	ADC_CHANNEL(0, "adc0"),
+	ADC_CHANNEL(1, "adc1"),
+	ADC_CHANNEL(2, "adc2"),
+	ADC_CHANNEL(3, "adc3"),
+	ADC_CHANNEL(4, "adc4"),
+	ADC_CHANNEL(5, "adc5"),
+};
+
+static const struct rockchip_saradc_data rk3399_saradc_data = {
+	.num_bits = 10,
+	.channels = rockchip_rk3399_saradc_iio_channels,
+	.num_channels = ARRAY_SIZE(rockchip_rk3399_saradc_iio_channels),
+	.clk_rate = 1000000,
+};
+
 static const struct of_device_id rockchip_saradc_match[] = {
 	{
 		.compatible = "rockchip,saradc",
@@ -166,6 +182,9 @@ static const struct of_device_id rockchi
 	}, {
 		.compatible = "rockchip,rk3066-tsadc",
 		.data = &rk3066_tsadc_data,
+	}, {
+		.compatible = "rockchip,rk3399-saradc",
+		.data = &rk3399_saradc_data,
 	},
 	{},
 };
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/adc/ti-adc081c.c linux-libre-4.7-gnu/drivers/iio/adc/ti-adc081c.c
--- linux-libre-4.6-gnu/drivers/iio/adc/ti-adc081c.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/adc/ti-adc081c.c	2016-07-24 15:23:50.000000000 -0400
@@ -1,9 +1,21 @@
 /*
+ * TI ADC081C/ADC101C/ADC121C 8/10/12-bit ADC driver
+ *
  * Copyright (C) 2012 Avionic Design GmbH
+ * Copyright (C) 2016 Intel
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
+ *
+ * Datasheets:
+ *	http://www.ti.com/lit/ds/symlink/adc081c021.pdf
+ *	http://www.ti.com/lit/ds/symlink/adc101c021.pdf
+ *	http://www.ti.com/lit/ds/symlink/adc121c021.pdf
+ *
+ * The devices have a very similar interface and differ mostly in the number of
+ * bits handled. For the 8-bit and 10-bit models the least-significant 4 or 2
+ * bits of value registers are reserved.
  */
 
 #include <linux/err.h>
@@ -12,11 +24,17 @@
 #include <linux/of.h>
 
 #include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
 #include <linux/regulator/consumer.h>
 
 struct adc081c {
 	struct i2c_client *i2c;
 	struct regulator *ref;
+
+	/* 8, 10 or 12 */
+	int bits;
 };
 
 #define REG_CONV_RES 0x00
@@ -34,7 +52,7 @@ static int adc081c_read_raw(struct iio_d
 		if (err < 0)
 			return err;
 
-		*value = (err >> 4) & 0xff;
+		*value = (err & 0xFFF) >> (12 - adc->bits);
 		return IIO_VAL_INT;
 
 	case IIO_CHAN_INFO_SCALE:
@@ -43,7 +61,7 @@ static int adc081c_read_raw(struct iio_d
 			return err;
 
 		*value = err / 1000;
-		*shift = 8;
+		*shift = adc->bits;
 
 		return IIO_VAL_FRACTIONAL_LOG2;
 
@@ -54,10 +72,53 @@ static int adc081c_read_raw(struct iio_d
 	return -EINVAL;
 }
 
-static const struct iio_chan_spec adc081c_channel = {
-	.type = IIO_VOLTAGE,
-	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
-	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+#define ADCxx1C_CHAN(_bits) {					\
+	.type = IIO_VOLTAGE,					\
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
+	.scan_type = {						\
+		.sign = 'u',					\
+		.realbits = (_bits),				\
+		.storagebits = 16,				\
+		.shift = 12 - (_bits),				\
+		.endianness = IIO_CPU,				\
+	},							\
+}
+
+#define DEFINE_ADCxx1C_CHANNELS(_name, _bits)				\
+	static const struct iio_chan_spec _name ## _channels[] = {	\
+		ADCxx1C_CHAN((_bits)),					\
+		IIO_CHAN_SOFT_TIMESTAMP(1),				\
+	};								\
+
+#define ADC081C_NUM_CHANNELS 2
+
+struct adcxx1c_model {
+	const struct iio_chan_spec* channels;
+	int bits;
+};
+
+#define ADCxx1C_MODEL(_name, _bits)					\
+	{								\
+		.channels = _name ## _channels,				\
+		.bits = (_bits),					\
+	}
+
+DEFINE_ADCxx1C_CHANNELS(adc081c,  8);
+DEFINE_ADCxx1C_CHANNELS(adc101c, 10);
+DEFINE_ADCxx1C_CHANNELS(adc121c, 12);
+
+/* Model ids are indexes in _models array */
+enum adcxx1c_model_id {
+	ADC081C = 0,
+	ADC101C = 1,
+	ADC121C = 2,
+};
+
+static struct adcxx1c_model adcxx1c_models[] = {
+	ADCxx1C_MODEL(adc081c,  8),
+	ADCxx1C_MODEL(adc101c, 10),
+	ADCxx1C_MODEL(adc121c, 12),
 };
 
 static const struct iio_info adc081c_info = {
@@ -65,11 +126,30 @@ static const struct iio_info adc081c_inf
 	.driver_module = THIS_MODULE,
 };
 
+static irqreturn_t adc081c_trigger_handler(int irq, void *p)
+{
+	struct iio_poll_func *pf = p;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct adc081c *data = iio_priv(indio_dev);
+	u16 buf[8]; /* 2 bytes data + 6 bytes padding + 8 bytes timestamp */
+	int ret;
+
+	ret = i2c_smbus_read_word_swapped(data->i2c, REG_CONV_RES);
+	if (ret < 0)
+		goto out;
+	buf[0] = ret;
+	iio_push_to_buffers_with_timestamp(indio_dev, buf, iio_get_time_ns());
+out:
+	iio_trigger_notify_done(indio_dev->trig);
+	return IRQ_HANDLED;
+}
+
 static int adc081c_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
 	struct iio_dev *iio;
 	struct adc081c *adc;
+	struct adcxx1c_model *model = &adcxx1c_models[id->driver_data];
 	int err;
 
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
@@ -81,6 +161,7 @@ static int adc081c_probe(struct i2c_clie
 
 	adc = iio_priv(iio);
 	adc->i2c = client;
+	adc->bits = model->bits;
 
 	adc->ref = devm_regulator_get(&client->dev, "vref");
 	if (IS_ERR(adc->ref))
@@ -95,18 +176,26 @@ static int adc081c_probe(struct i2c_clie
 	iio->modes = INDIO_DIRECT_MODE;
 	iio->info = &adc081c_info;
 
-	iio->channels = &adc081c_channel;
-	iio->num_channels = 1;
+	iio->channels = model->channels;
+	iio->num_channels = ADC081C_NUM_CHANNELS;
+
+	err = iio_triggered_buffer_setup(iio, NULL, adc081c_trigger_handler, NULL);
+	if (err < 0) {
+		dev_err(&client->dev, "iio triggered buffer setup failed\n");
+		goto err_regulator_disable;
+	}
 
 	err = iio_device_register(iio);
 	if (err < 0)
-		goto regulator_disable;
+		goto err_buffer_cleanup;
 
 	i2c_set_clientdata(client, iio);
 
 	return 0;
 
-regulator_disable:
+err_buffer_cleanup:
+	iio_triggered_buffer_cleanup(iio);
+err_regulator_disable:
 	regulator_disable(adc->ref);
 
 	return err;
@@ -118,13 +207,16 @@ static int adc081c_remove(struct i2c_cli
 	struct adc081c *adc = iio_priv(iio);
 
 	iio_device_unregister(iio);
+	iio_triggered_buffer_cleanup(iio);
 	regulator_disable(adc->ref);
 
 	return 0;
 }
 
 static const struct i2c_device_id adc081c_id[] = {
-	{ "adc081c", 0 },
+	{ "adc081c", ADC081C },
+	{ "adc101c", ADC101C },
+	{ "adc121c", ADC121C },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, adc081c_id);
@@ -132,6 +224,8 @@ MODULE_DEVICE_TABLE(i2c, adc081c_id);
 #ifdef CONFIG_OF
 static const struct of_device_id adc081c_of_match[] = {
 	{ .compatible = "ti,adc081c" },
+	{ .compatible = "ti,adc101c" },
+	{ .compatible = "ti,adc121c" },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, adc081c_of_match);
@@ -149,5 +243,5 @@ static struct i2c_driver adc081c_driver
 module_i2c_driver(adc081c_driver);
 
 MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>");
-MODULE_DESCRIPTION("Texas Instruments ADC081C021/027 driver");
+MODULE_DESCRIPTION("Texas Instruments ADC081C/ADC101C/ADC121C driver");
 MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/adc/vf610_adc.c linux-libre-4.7-gnu/drivers/iio/adc/vf610_adc.c
--- linux-libre-4.6-gnu/drivers/iio/adc/vf610_adc.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/adc/vf610_adc.c	2016-07-24 15:23:50.000000000 -0400
@@ -714,19 +714,19 @@ static int vf610_write_raw(struct iio_de
 	int i;
 
 	switch (mask) {
-		case IIO_CHAN_INFO_SAMP_FREQ:
-			for (i = 0;
-				i < ARRAY_SIZE(info->sample_freq_avail);
-				i++)
-				if (val == info->sample_freq_avail[i]) {
-					info->adc_feature.sample_rate = i;
-					vf610_adc_sample_set(info);
-					return 0;
-				}
-			break;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		for (i = 0;
+			i < ARRAY_SIZE(info->sample_freq_avail);
+			i++)
+			if (val == info->sample_freq_avail[i]) {
+				info->adc_feature.sample_rate = i;
+				vf610_adc_sample_set(info);
+				return 0;
+			}
+		break;
 
-		default:
-			break;
+	default:
+		break;
 	}
 
 	return -EINVAL;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/common/hid-sensors/hid-sensor-trigger.c linux-libre-4.7-gnu/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
--- linux-libre-4.6-gnu/drivers/iio/common/hid-sensors/hid-sensor-trigger.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/common/hid-sensors/hid-sensor-trigger.c	2016-07-24 15:23:50.000000000 -0400
@@ -115,7 +115,7 @@ int hid_sensor_power_state(struct hid_se
 		return ret;
 	}
 
- 	return 0;
+	return 0;
 #else
 	atomic_set(&st->user_requested_state, state);
 	return _hid_sensor_power_state(st, state);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/common/ms_sensors/ms_sensors_i2c.c linux-libre-4.7-gnu/drivers/iio/common/ms_sensors/ms_sensors_i2c.c
--- linux-libre-4.6-gnu/drivers/iio/common/ms_sensors/ms_sensors_i2c.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/common/ms_sensors/ms_sensors_i2c.c	2016-07-24 15:23:50.000000000 -0400
@@ -106,7 +106,7 @@ int ms_sensors_convert_and_read(void *cl
 				unsigned int delay, u32 *adc)
 {
 	int ret;
-        __be32 buf = 0;
+	__be32 buf = 0;
 	struct i2c_client *client = (struct i2c_client *)cli;
 
 	/* Trigger conversion */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/common/st_sensors/st_sensors_buffer.c linux-libre-4.7-gnu/drivers/iio/common/st_sensors/st_sensors_buffer.c
--- linux-libre-4.6-gnu/drivers/iio/common/st_sensors/st_sensors_buffer.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/common/st_sensors/st_sensors_buffer.c	2016-07-24 15:23:50.000000000 -0400
@@ -24,81 +24,30 @@
 
 int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf)
 {
-	u8 *addr;
-	int i, n = 0, len;
+	int i, len;
+	int total = 0;
 	struct st_sensor_data *sdata = iio_priv(indio_dev);
 	unsigned int num_data_channels = sdata->num_data_channels;
-	unsigned int byte_for_channel =
-			indio_dev->channels[0].scan_type.storagebits >> 3;
-
-	addr = kmalloc(num_data_channels, GFP_KERNEL);
-	if (!addr) {
-		len = -ENOMEM;
-		goto st_sensors_get_buffer_element_error;
-	}
 
 	for (i = 0; i < num_data_channels; i++) {
+		unsigned int bytes_to_read;
+
 		if (test_bit(i, indio_dev->active_scan_mask)) {
-			addr[n] = indio_dev->channels[i].address;
-			n++;
-		}
-	}
-	switch (n) {
-	case 1:
-		len = sdata->tf->read_multiple_byte(&sdata->tb, sdata->dev,
-			addr[0], byte_for_channel, buf, sdata->multiread_bit);
-		break;
-	case 2:
-		if ((addr[1] - addr[0]) == byte_for_channel) {
+			bytes_to_read = indio_dev->channels[i].scan_type.storagebits >> 3;
 			len = sdata->tf->read_multiple_byte(&sdata->tb,
-				sdata->dev, addr[0], byte_for_channel * n,
-				buf, sdata->multiread_bit);
-		} else {
-			u8 *rx_array;
-			rx_array = kmalloc(byte_for_channel * num_data_channels,
-					   GFP_KERNEL);
-			if (!rx_array) {
-				len = -ENOMEM;
-				goto st_sensors_free_memory;
-			}
+				sdata->dev, indio_dev->channels[i].address,
+				bytes_to_read,
+				buf + total, sdata->multiread_bit);
 
-			len = sdata->tf->read_multiple_byte(&sdata->tb,
-				sdata->dev, addr[0],
-				byte_for_channel * num_data_channels,
-				rx_array, sdata->multiread_bit);
-			if (len < 0) {
-				kfree(rx_array);
-				goto st_sensors_free_memory;
-			}
+			if (len < bytes_to_read)
+				return -EIO;
 
-			for (i = 0; i < n * byte_for_channel; i++) {
-				if (i < n)
-					buf[i] = rx_array[i];
-				else
-					buf[i] = rx_array[n + i];
-			}
-			kfree(rx_array);
-			len = byte_for_channel * n;
+			/* Advance the buffer pointer */
+			total += len;
 		}
-		break;
-	case 3:
-		len = sdata->tf->read_multiple_byte(&sdata->tb, sdata->dev,
-			addr[0], byte_for_channel * num_data_channels,
-			buf, sdata->multiread_bit);
-		break;
-	default:
-		len = -EINVAL;
-		goto st_sensors_free_memory;
-	}
-	if (len != byte_for_channel * n) {
-		len = -EIO;
-		goto st_sensors_free_memory;
 	}
 
-st_sensors_free_memory:
-	kfree(addr);
-st_sensors_get_buffer_element_error:
-	return len;
+	return total;
 }
 EXPORT_SYMBOL(st_sensors_get_buffer_element);
 
@@ -108,13 +57,20 @@ irqreturn_t st_sensors_trigger_handler(i
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct st_sensor_data *sdata = iio_priv(indio_dev);
+	s64 timestamp;
+
+	/* If we do timetamping here, do it before reading the values */
+	if (sdata->hw_irq_trigger)
+		timestamp = sdata->hw_timestamp;
+	else
+		timestamp = iio_get_time_ns();
 
 	len = st_sensors_get_buffer_element(indio_dev, sdata->buffer_data);
 	if (len < 0)
 		goto st_sensors_get_buffer_element_error;
 
 	iio_push_to_buffers_with_timestamp(indio_dev, sdata->buffer_data,
-		pf->timestamp);
+					   timestamp);
 
 st_sensors_get_buffer_element_error:
 	iio_trigger_notify_done(indio_dev->trig);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/common/st_sensors/st_sensors_core.c linux-libre-4.7-gnu/drivers/iio/common/st_sensors/st_sensors_core.c
--- linux-libre-4.6-gnu/drivers/iio/common/st_sensors/st_sensors_core.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/common/st_sensors/st_sensors_core.c	2016-07-24 15:23:50.000000000 -0400
@@ -301,6 +301,14 @@ static int st_sensors_set_drdy_int_pin(s
 		return -EINVAL;
 	}
 
+	if (pdata->open_drain) {
+		if (!sdata->sensor_settings->drdy_irq.addr_od)
+			dev_err(&indio_dev->dev,
+				"open drain requested but unsupported.\n");
+		else
+			sdata->int_pin_open_drain = true;
+	}
+
 	return 0;
 }
 
@@ -321,6 +329,8 @@ static struct st_sensors_platform_data *
 	else
 		pdata->drdy_int_pin = defdata ? defdata->drdy_int_pin : 0;
 
+	pdata->open_drain = of_property_read_bool(np, "drive-open-drain");
+
 	return pdata;
 }
 #else
@@ -353,6 +363,11 @@ int st_sensors_init_sensor(struct iio_de
 	if (err < 0)
 		return err;
 
+	/* Disable DRDY, this might be still be enabled after reboot. */
+	err = st_sensors_set_dataready_irq(indio_dev, false);
+	if (err < 0)
+		return err;
+
 	if (sdata->current_fullscale) {
 		err = st_sensors_set_fullscale(indio_dev,
 						sdata->current_fullscale->num);
@@ -374,6 +389,16 @@ int st_sensors_init_sensor(struct iio_de
 			return err;
 	}
 
+	if (sdata->int_pin_open_drain) {
+		dev_info(&indio_dev->dev,
+			 "set interrupt line to open drain mode\n");
+		err = st_sensors_write_data_with_mask(indio_dev,
+				sdata->sensor_settings->drdy_irq.addr_od,
+				sdata->sensor_settings->drdy_irq.mask_od, 1);
+		if (err < 0)
+			return err;
+	}
+
 	err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS);
 
 	return err;
@@ -404,6 +429,9 @@ int st_sensors_set_dataready_irq(struct
 	else
 		drdy_mask = sdata->sensor_settings->drdy_irq.mask_int2;
 
+	/* Flag to the poll function that the hardware trigger is in use */
+	sdata->hw_irq_trigger = enable;
+
 	/* Enable/Disable the interrupt generator for data ready. */
 	err = st_sensors_write_data_with_mask(indio_dev,
 					sdata->sensor_settings->drdy_irq.addr,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/common/st_sensors/st_sensors_trigger.c linux-libre-4.7-gnu/drivers/iio/common/st_sensors/st_sensors_trigger.c
--- linux-libre-4.6-gnu/drivers/iio/common/st_sensors/st_sensors_trigger.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/common/st_sensors/st_sensors_trigger.c	2016-07-24 15:23:50.000000000 -0400
@@ -17,6 +17,73 @@
 #include <linux/iio/common/st_sensors.h>
 #include "st_sensors_core.h"
 
+/**
+ * st_sensors_irq_handler() - top half of the IRQ-based triggers
+ * @irq: irq number
+ * @p: private handler data
+ */
+irqreturn_t st_sensors_irq_handler(int irq, void *p)
+{
+	struct iio_trigger *trig = p;
+	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+	struct st_sensor_data *sdata = iio_priv(indio_dev);
+
+	/* Get the time stamp as close in time as possible */
+	sdata->hw_timestamp = iio_get_time_ns();
+	return IRQ_WAKE_THREAD;
+}
+
+/**
+ * st_sensors_irq_thread() - bottom half of the IRQ-based triggers
+ * @irq: irq number
+ * @p: private handler data
+ */
+irqreturn_t st_sensors_irq_thread(int irq, void *p)
+{
+	struct iio_trigger *trig = p;
+	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+	struct st_sensor_data *sdata = iio_priv(indio_dev);
+	int ret;
+
+	/*
+	 * If this trigger is backed by a hardware interrupt and we have a
+	 * status register, check if this IRQ came from us
+	 */
+	if (sdata->sensor_settings->drdy_irq.addr_stat_drdy) {
+		u8 status;
+
+		ret = sdata->tf->read_byte(&sdata->tb, sdata->dev,
+			   sdata->sensor_settings->drdy_irq.addr_stat_drdy,
+			   &status);
+		if (ret < 0) {
+			dev_err(sdata->dev, "could not read channel status\n");
+			goto out_poll;
+		}
+		/*
+		 * the lower bits of .active_scan_mask[0] is directly mapped
+		 * to the channels on the sensor: either bit 0 for
+		 * one-dimensional sensors, or e.g. x,y,z for accelerometers,
+		 * gyroscopes or magnetometers. No sensor use more than 3
+		 * channels, so cut the other status bits here.
+		 */
+		status &= 0x07;
+
+		/*
+		 * If this was not caused by any channels on this sensor,
+		 * return IRQ_NONE
+		 */
+		if (!indio_dev->active_scan_mask)
+			return IRQ_NONE;
+		if (!(status & (u8)indio_dev->active_scan_mask[0]))
+			return IRQ_NONE;
+	}
+
+out_poll:
+	/* It's our IRQ: proceed to handle the register polling */
+	iio_trigger_poll_chained(p);
+	return IRQ_HANDLED;
+}
+
 int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
 				const struct iio_trigger_ops *trigger_ops)
 {
@@ -30,6 +97,10 @@ int st_sensors_allocate_trigger(struct i
 		return -ENOMEM;
 	}
 
+	iio_trigger_set_drvdata(sdata->trig, indio_dev);
+	sdata->trig->ops = trigger_ops;
+	sdata->trig->dev.parent = sdata->dev;
+
 	irq = sdata->get_irq_data_ready(indio_dev);
 	irq_trig = irqd_get_trigger_type(irq_get_irq_data(irq));
 	/*
@@ -64,9 +135,25 @@ int st_sensors_allocate_trigger(struct i
 			"rising edge\n", irq_trig);
 		irq_trig = IRQF_TRIGGER_RISING;
 	}
-	err = request_threaded_irq(irq,
-			iio_trigger_generic_data_rdy_poll,
-			NULL,
+
+	/*
+	 * If the interrupt pin is Open Drain, by definition this
+	 * means that the interrupt line may be shared with other
+	 * peripherals. But to do this we also need to have a status
+	 * register and mask to figure out if this sensor was firing
+	 * the IRQ or not, so we can tell the interrupt handle that
+	 * it was "our" interrupt.
+	 */
+	if (sdata->int_pin_open_drain &&
+	    sdata->sensor_settings->drdy_irq.addr_stat_drdy)
+		irq_trig |= IRQF_SHARED;
+
+	/* Let's create an interrupt thread masking the hard IRQ here */
+	irq_trig |= IRQF_ONESHOT;
+
+	err = request_threaded_irq(sdata->get_irq_data_ready(indio_dev),
+			st_sensors_irq_handler,
+			st_sensors_irq_thread,
 			irq_trig,
 			sdata->trig->name,
 			sdata->trig);
@@ -75,10 +162,6 @@ int st_sensors_allocate_trigger(struct i
 		goto iio_trigger_free;
 	}
 
-	iio_trigger_set_drvdata(sdata->trig, indio_dev);
-	sdata->trig->ops = trigger_ops;
-	sdata->trig->dev.parent = sdata->dev;
-
 	err = iio_trigger_register(sdata->trig);
 	if (err < 0) {
 		dev_err(&indio_dev->dev, "failed to register iio trigger.\n");
@@ -106,6 +189,18 @@ void st_sensors_deallocate_trigger(struc
 }
 EXPORT_SYMBOL(st_sensors_deallocate_trigger);
 
+int st_sensors_validate_device(struct iio_trigger *trig,
+			       struct iio_dev *indio_dev)
+{
+	struct iio_dev *indio = iio_trigger_get_drvdata(trig);
+
+	if (indio != indio_dev)
+		return -EINVAL;
+
+	return 0;
+}
+EXPORT_SYMBOL(st_sensors_validate_device);
+
 MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
 MODULE_DESCRIPTION("STMicroelectronics ST-sensors trigger");
 MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/dac/ad5592r-base.c linux-libre-4.7-gnu/drivers/iio/dac/ad5592r-base.c
--- linux-libre-4.6-gnu/drivers/iio/dac/ad5592r-base.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/iio/dac/ad5592r-base.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,691 @@
+/*
+ * AD5592R Digital <-> Analog converters driver
+ *
+ * Copyright 2014-2016 Analog Devices Inc.
+ * Author: Paul Cercueil <paul.cercueil@analog.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/iio/iio.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/driver.h>
+#include <linux/gpio.h>
+#include <linux/property.h>
+
+#include <dt-bindings/iio/adi,ad5592r.h>
+
+#include "ad5592r-base.h"
+
+static int ad5592r_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct ad5592r_state *st = gpiochip_get_data(chip);
+	int ret = 0;
+	u8 val;
+
+	mutex_lock(&st->gpio_lock);
+
+	if (st->gpio_out & BIT(offset))
+		val = st->gpio_val;
+	else
+		ret = st->ops->gpio_read(st, &val);
+
+	mutex_unlock(&st->gpio_lock);
+
+	if (ret < 0)
+		return ret;
+
+	return !!(val & BIT(offset));
+}
+
+static void ad5592r_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct ad5592r_state *st = gpiochip_get_data(chip);
+
+	mutex_lock(&st->gpio_lock);
+
+	if (value)
+		st->gpio_val |= BIT(offset);
+	else
+		st->gpio_val &= ~BIT(offset);
+
+	st->ops->reg_write(st, AD5592R_REG_GPIO_SET, st->gpio_val);
+
+	mutex_unlock(&st->gpio_lock);
+}
+
+static int ad5592r_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	struct ad5592r_state *st = gpiochip_get_data(chip);
+	int ret;
+
+	mutex_lock(&st->gpio_lock);
+
+	st->gpio_out &= ~BIT(offset);
+	st->gpio_in |= BIT(offset);
+
+	ret = st->ops->reg_write(st, AD5592R_REG_GPIO_OUT_EN, st->gpio_out);
+	if (ret < 0)
+		goto err_unlock;
+
+	ret = st->ops->reg_write(st, AD5592R_REG_GPIO_IN_EN, st->gpio_in);
+
+err_unlock:
+	mutex_unlock(&st->gpio_lock);
+
+	return ret;
+}
+
+static int ad5592r_gpio_direction_output(struct gpio_chip *chip,
+					 unsigned offset, int value)
+{
+	struct ad5592r_state *st = gpiochip_get_data(chip);
+	int ret;
+
+	mutex_lock(&st->gpio_lock);
+
+	if (value)
+		st->gpio_val |= BIT(offset);
+	else
+		st->gpio_val &= ~BIT(offset);
+
+	st->gpio_in &= ~BIT(offset);
+	st->gpio_out |= BIT(offset);
+
+	ret = st->ops->reg_write(st, AD5592R_REG_GPIO_SET, st->gpio_val);
+	if (ret < 0)
+		goto err_unlock;
+
+	ret = st->ops->reg_write(st, AD5592R_REG_GPIO_OUT_EN, st->gpio_out);
+	if (ret < 0)
+		goto err_unlock;
+
+	ret = st->ops->reg_write(st, AD5592R_REG_GPIO_IN_EN, st->gpio_in);
+
+err_unlock:
+	mutex_unlock(&st->gpio_lock);
+
+	return ret;
+}
+
+static int ad5592r_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	struct ad5592r_state *st = gpiochip_get_data(chip);
+
+	if (!(st->gpio_map & BIT(offset))) {
+		dev_err(st->dev, "GPIO %d is reserved by alternate function\n",
+			offset);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int ad5592r_gpio_init(struct ad5592r_state *st)
+{
+	if (!st->gpio_map)
+		return 0;
+
+	st->gpiochip.label = dev_name(st->dev);
+	st->gpiochip.base = -1;
+	st->gpiochip.ngpio = 8;
+	st->gpiochip.parent = st->dev;
+	st->gpiochip.can_sleep = true;
+	st->gpiochip.direction_input = ad5592r_gpio_direction_input;
+	st->gpiochip.direction_output = ad5592r_gpio_direction_output;
+	st->gpiochip.get = ad5592r_gpio_get;
+	st->gpiochip.set = ad5592r_gpio_set;
+	st->gpiochip.request = ad5592r_gpio_request;
+	st->gpiochip.owner = THIS_MODULE;
+
+	mutex_init(&st->gpio_lock);
+
+	return gpiochip_add_data(&st->gpiochip, st);
+}
+
+static void ad5592r_gpio_cleanup(struct ad5592r_state *st)
+{
+	if (st->gpio_map)
+		gpiochip_remove(&st->gpiochip);
+}
+
+static int ad5592r_reset(struct ad5592r_state *st)
+{
+	struct gpio_desc *gpio;
+	struct iio_dev *iio_dev = iio_priv_to_dev(st);
+
+	gpio = devm_gpiod_get_optional(st->dev, "reset", GPIOD_OUT_LOW);
+	if (IS_ERR(gpio))
+		return PTR_ERR(gpio);
+
+	if (gpio) {
+		udelay(1);
+		gpiod_set_value(gpio, 1);
+	} else {
+		mutex_lock(&iio_dev->mlock);
+		/* Writing this magic value resets the device */
+		st->ops->reg_write(st, AD5592R_REG_RESET, 0xdac);
+		mutex_unlock(&iio_dev->mlock);
+	}
+
+	udelay(250);
+
+	return 0;
+}
+
+static int ad5592r_get_vref(struct ad5592r_state *st)
+{
+	int ret;
+
+	if (st->reg) {
+		ret = regulator_get_voltage(st->reg);
+		if (ret < 0)
+			return ret;
+
+		return ret / 1000;
+	} else {
+		return 2500;
+	}
+}
+
+static int ad5592r_set_channel_modes(struct ad5592r_state *st)
+{
+	const struct ad5592r_rw_ops *ops = st->ops;
+	int ret;
+	unsigned i;
+	struct iio_dev *iio_dev = iio_priv_to_dev(st);
+	u8 pulldown = 0, tristate = 0, dac = 0, adc = 0;
+	u16 read_back;
+
+	for (i = 0; i < st->num_channels; i++) {
+		switch (st->channel_modes[i]) {
+		case CH_MODE_DAC:
+			dac |= BIT(i);
+			break;
+
+		case CH_MODE_ADC:
+			adc |= BIT(i);
+			break;
+
+		case CH_MODE_DAC_AND_ADC:
+			dac |= BIT(i);
+			adc |= BIT(i);
+			break;
+
+		case CH_MODE_GPIO:
+			st->gpio_map |= BIT(i);
+			st->gpio_in |= BIT(i); /* Default to input */
+			break;
+
+		case CH_MODE_UNUSED:
+			/* fall-through */
+		default:
+			switch (st->channel_offstate[i]) {
+			case CH_OFFSTATE_OUT_TRISTATE:
+				tristate |= BIT(i);
+				break;
+
+			case CH_OFFSTATE_OUT_LOW:
+				st->gpio_out |= BIT(i);
+				break;
+
+			case CH_OFFSTATE_OUT_HIGH:
+				st->gpio_out |= BIT(i);
+				st->gpio_val |= BIT(i);
+				break;
+
+			case CH_OFFSTATE_PULLDOWN:
+				/* fall-through */
+			default:
+				pulldown |= BIT(i);
+				break;
+			}
+		}
+	}
+
+	mutex_lock(&iio_dev->mlock);
+
+	/* Pull down unused pins to GND */
+	ret = ops->reg_write(st, AD5592R_REG_PULLDOWN, pulldown);
+	if (ret)
+		goto err_unlock;
+
+	ret = ops->reg_write(st, AD5592R_REG_TRISTATE, tristate);
+	if (ret)
+		goto err_unlock;
+
+	/* Configure pins that we use */
+	ret = ops->reg_write(st, AD5592R_REG_DAC_EN, dac);
+	if (ret)
+		goto err_unlock;
+
+	ret = ops->reg_write(st, AD5592R_REG_ADC_EN, adc);
+	if (ret)
+		goto err_unlock;
+
+	ret = ops->reg_write(st, AD5592R_REG_GPIO_SET, st->gpio_val);
+	if (ret)
+		goto err_unlock;
+
+	ret = ops->reg_write(st, AD5592R_REG_GPIO_OUT_EN, st->gpio_out);
+	if (ret)
+		goto err_unlock;
+
+	ret = ops->reg_write(st, AD5592R_REG_GPIO_IN_EN, st->gpio_in);
+	if (ret)
+		goto err_unlock;
+
+	/* Verify that we can read back at least one register */
+	ret = ops->reg_read(st, AD5592R_REG_ADC_EN, &read_back);
+	if (!ret && (read_back & 0xff) != adc)
+		ret = -EIO;
+
+err_unlock:
+	mutex_unlock(&iio_dev->mlock);
+	return ret;
+}
+
+static int ad5592r_reset_channel_modes(struct ad5592r_state *st)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(st->channel_modes); i++)
+		st->channel_modes[i] = CH_MODE_UNUSED;
+
+	return ad5592r_set_channel_modes(st);
+}
+
+static int ad5592r_write_raw(struct iio_dev *iio_dev,
+	struct iio_chan_spec const *chan, int val, int val2, long mask)
+{
+	struct ad5592r_state *st = iio_priv(iio_dev);
+	int ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+
+		if (val >= (1 << chan->scan_type.realbits) || val < 0)
+			return -EINVAL;
+
+		if (!chan->output)
+			return -EINVAL;
+
+		mutex_lock(&iio_dev->mlock);
+		ret = st->ops->write_dac(st, chan->channel, val);
+		if (!ret)
+			st->cached_dac[chan->channel] = val;
+		mutex_unlock(&iio_dev->mlock);
+		return ret;
+	case IIO_CHAN_INFO_SCALE:
+		if (chan->type == IIO_VOLTAGE) {
+			bool gain;
+
+			if (val == st->scale_avail[0][0] &&
+				val2 == st->scale_avail[0][1])
+				gain = false;
+			else if (val == st->scale_avail[1][0] &&
+				 val2 == st->scale_avail[1][1])
+				gain = true;
+			else
+				return -EINVAL;
+
+			mutex_lock(&iio_dev->mlock);
+
+			ret = st->ops->reg_read(st, AD5592R_REG_CTRL,
+						&st->cached_gp_ctrl);
+			if (ret < 0) {
+				mutex_unlock(&iio_dev->mlock);
+				return ret;
+			}
+
+			if (chan->output) {
+				if (gain)
+					st->cached_gp_ctrl |=
+						AD5592R_REG_CTRL_DAC_RANGE;
+				else
+					st->cached_gp_ctrl &=
+						~AD5592R_REG_CTRL_DAC_RANGE;
+			} else {
+				if (gain)
+					st->cached_gp_ctrl |=
+						AD5592R_REG_CTRL_ADC_RANGE;
+				else
+					st->cached_gp_ctrl &=
+						~AD5592R_REG_CTRL_ADC_RANGE;
+			}
+
+			ret = st->ops->reg_write(st, AD5592R_REG_CTRL,
+						 st->cached_gp_ctrl);
+			mutex_unlock(&iio_dev->mlock);
+
+			return ret;
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int ad5592r_read_raw(struct iio_dev *iio_dev,
+			   struct iio_chan_spec const *chan,
+			   int *val, int *val2, long m)
+{
+	struct ad5592r_state *st = iio_priv(iio_dev);
+	u16 read_val;
+	int ret;
+
+	switch (m) {
+	case IIO_CHAN_INFO_RAW:
+		mutex_lock(&iio_dev->mlock);
+
+		if (!chan->output) {
+			ret = st->ops->read_adc(st, chan->channel, &read_val);
+			if (ret)
+				goto unlock;
+
+			if ((read_val >> 12 & 0x7) != (chan->channel & 0x7)) {
+				dev_err(st->dev, "Error while reading channel %u\n",
+						chan->channel);
+				ret = -EIO;
+				goto unlock;
+			}
+
+			read_val &= GENMASK(11, 0);
+
+		} else {
+			read_val = st->cached_dac[chan->channel];
+		}
+
+		dev_dbg(st->dev, "Channel %u read: 0x%04hX\n",
+				chan->channel, read_val);
+
+		*val = (int) read_val;
+		ret = IIO_VAL_INT;
+		break;
+	case IIO_CHAN_INFO_SCALE:
+		*val = ad5592r_get_vref(st);
+
+		if (chan->type == IIO_TEMP) {
+			s64 tmp = *val * (3767897513LL / 25LL);
+			*val = div_s64_rem(tmp, 1000000000LL, val2);
+
+			ret = IIO_VAL_INT_PLUS_MICRO;
+		} else {
+			int mult;
+
+			mutex_lock(&iio_dev->mlock);
+
+			if (chan->output)
+				mult = !!(st->cached_gp_ctrl &
+					AD5592R_REG_CTRL_DAC_RANGE);
+			else
+				mult = !!(st->cached_gp_ctrl &
+					AD5592R_REG_CTRL_ADC_RANGE);
+
+			*val *= ++mult;
+
+			*val2 = chan->scan_type.realbits;
+			ret = IIO_VAL_FRACTIONAL_LOG2;
+		}
+		break;
+	case IIO_CHAN_INFO_OFFSET:
+		ret = ad5592r_get_vref(st);
+
+		mutex_lock(&iio_dev->mlock);
+
+		if (st->cached_gp_ctrl & AD5592R_REG_CTRL_ADC_RANGE)
+			*val = (-34365 * 25) / ret;
+		else
+			*val = (-75365 * 25) / ret;
+		ret =  IIO_VAL_INT;
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+unlock:
+	mutex_unlock(&iio_dev->mlock);
+	return ret;
+}
+
+static int ad5592r_write_raw_get_fmt(struct iio_dev *indio_dev,
+				 struct iio_chan_spec const *chan, long mask)
+{
+	switch (mask) {
+	case IIO_CHAN_INFO_SCALE:
+		return IIO_VAL_INT_PLUS_NANO;
+
+	default:
+		return IIO_VAL_INT_PLUS_MICRO;
+	}
+
+	return -EINVAL;
+}
+
+static const struct iio_info ad5592r_info = {
+	.read_raw = ad5592r_read_raw,
+	.write_raw = ad5592r_write_raw,
+	.write_raw_get_fmt = ad5592r_write_raw_get_fmt,
+	.driver_module = THIS_MODULE,
+};
+
+static ssize_t ad5592r_show_scale_available(struct iio_dev *iio_dev,
+					   uintptr_t private,
+					   const struct iio_chan_spec *chan,
+					   char *buf)
+{
+	struct ad5592r_state *st = iio_priv(iio_dev);
+
+	return sprintf(buf, "%d.%09u %d.%09u\n",
+		st->scale_avail[0][0], st->scale_avail[0][1],
+		st->scale_avail[1][0], st->scale_avail[1][1]);
+}
+
+static struct iio_chan_spec_ext_info ad5592r_ext_info[] = {
+	{
+	 .name = "scale_available",
+	 .read = ad5592r_show_scale_available,
+	 .shared = true,
+	 },
+	{},
+};
+
+static void ad5592r_setup_channel(struct iio_dev *iio_dev,
+		struct iio_chan_spec *chan, bool output, unsigned id)
+{
+	chan->type = IIO_VOLTAGE;
+	chan->indexed = 1;
+	chan->output = output;
+	chan->channel = id;
+	chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
+	chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE);
+	chan->scan_type.sign = 'u';
+	chan->scan_type.realbits = 12;
+	chan->scan_type.storagebits = 16;
+	chan->ext_info = ad5592r_ext_info;
+}
+
+static int ad5592r_alloc_channels(struct ad5592r_state *st)
+{
+	unsigned i, curr_channel = 0,
+		 num_channels = st->num_channels;
+	struct iio_dev *iio_dev = iio_priv_to_dev(st);
+	struct iio_chan_spec *channels;
+	struct fwnode_handle *child;
+	u32 reg, tmp;
+	int ret;
+
+	device_for_each_child_node(st->dev, child) {
+		ret = fwnode_property_read_u32(child, "reg", &reg);
+		if (ret || reg >= ARRAY_SIZE(st->channel_modes))
+			continue;
+
+		ret = fwnode_property_read_u32(child, "adi,mode", &tmp);
+		if (!ret)
+			st->channel_modes[reg] = tmp;
+
+		fwnode_property_read_u32(child, "adi,off-state", &tmp);
+		if (!ret)
+			st->channel_offstate[reg] = tmp;
+	}
+
+	channels = devm_kzalloc(st->dev,
+			(1 + 2 * num_channels) * sizeof(*channels), GFP_KERNEL);
+	if (!channels)
+		return -ENOMEM;
+
+	for (i = 0; i < num_channels; i++) {
+		switch (st->channel_modes[i]) {
+		case CH_MODE_DAC:
+			ad5592r_setup_channel(iio_dev, &channels[curr_channel],
+					true, i);
+			curr_channel++;
+			break;
+
+		case CH_MODE_ADC:
+			ad5592r_setup_channel(iio_dev, &channels[curr_channel],
+					false, i);
+			curr_channel++;
+			break;
+
+		case CH_MODE_DAC_AND_ADC:
+			ad5592r_setup_channel(iio_dev, &channels[curr_channel],
+					true, i);
+			curr_channel++;
+			ad5592r_setup_channel(iio_dev, &channels[curr_channel],
+					false, i);
+			curr_channel++;
+			break;
+
+		default:
+			continue;
+		}
+	}
+
+	channels[curr_channel].type = IIO_TEMP;
+	channels[curr_channel].channel = 8;
+	channels[curr_channel].info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+				   BIT(IIO_CHAN_INFO_SCALE) |
+				   BIT(IIO_CHAN_INFO_OFFSET);
+	curr_channel++;
+
+	iio_dev->num_channels = curr_channel;
+	iio_dev->channels = channels;
+
+	return 0;
+}
+
+static void ad5592r_init_scales(struct ad5592r_state *st, int vref_mV)
+{
+	s64 tmp = (s64)vref_mV * 1000000000LL >> 12;
+
+	st->scale_avail[0][0] =
+		div_s64_rem(tmp, 1000000000LL, &st->scale_avail[0][1]);
+	st->scale_avail[1][0] =
+		div_s64_rem(tmp * 2, 1000000000LL, &st->scale_avail[1][1]);
+}
+
+int ad5592r_probe(struct device *dev, const char *name,
+		const struct ad5592r_rw_ops *ops)
+{
+	struct iio_dev *iio_dev;
+	struct ad5592r_state *st;
+	int ret;
+
+	iio_dev = devm_iio_device_alloc(dev, sizeof(*st));
+	if (!iio_dev)
+		return -ENOMEM;
+
+	st = iio_priv(iio_dev);
+	st->dev = dev;
+	st->ops = ops;
+	st->num_channels = 8;
+	dev_set_drvdata(dev, iio_dev);
+
+	st->reg = devm_regulator_get_optional(dev, "vref");
+	if (IS_ERR(st->reg)) {
+		if ((PTR_ERR(st->reg) != -ENODEV) && dev->of_node)
+			return PTR_ERR(st->reg);
+
+		st->reg = NULL;
+	} else {
+		ret = regulator_enable(st->reg);
+		if (ret)
+			return ret;
+	}
+
+	iio_dev->dev.parent = dev;
+	iio_dev->name = name;
+	iio_dev->info = &ad5592r_info;
+	iio_dev->modes = INDIO_DIRECT_MODE;
+
+	ad5592r_init_scales(st, ad5592r_get_vref(st));
+
+	ret = ad5592r_reset(st);
+	if (ret)
+		goto error_disable_reg;
+
+	ret = ops->reg_write(st, AD5592R_REG_PD,
+		     (st->reg == NULL) ? AD5592R_REG_PD_EN_REF : 0);
+	if (ret)
+		goto error_disable_reg;
+
+	ret = ad5592r_alloc_channels(st);
+	if (ret)
+		goto error_disable_reg;
+
+	ret = ad5592r_set_channel_modes(st);
+	if (ret)
+		goto error_reset_ch_modes;
+
+	ret = iio_device_register(iio_dev);
+	if (ret)
+		goto error_reset_ch_modes;
+
+	ret = ad5592r_gpio_init(st);
+	if (ret)
+		goto error_dev_unregister;
+
+	return 0;
+
+error_dev_unregister:
+	iio_device_unregister(iio_dev);
+
+error_reset_ch_modes:
+	ad5592r_reset_channel_modes(st);
+
+error_disable_reg:
+	if (st->reg)
+		regulator_disable(st->reg);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(ad5592r_probe);
+
+int ad5592r_remove(struct device *dev)
+{
+	struct iio_dev *iio_dev = dev_get_drvdata(dev);
+	struct ad5592r_state *st = iio_priv(iio_dev);
+
+	iio_device_unregister(iio_dev);
+	ad5592r_reset_channel_modes(st);
+	ad5592r_gpio_cleanup(st);
+
+	if (st->reg)
+		regulator_disable(st->reg);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ad5592r_remove);
+
+MODULE_AUTHOR("Paul Cercueil <paul.cercueil@analog.com>");
+MODULE_DESCRIPTION("Analog Devices AD5592R multi-channel converters");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/dac/ad5592r-base.h linux-libre-4.7-gnu/drivers/iio/dac/ad5592r-base.h
--- linux-libre-4.6-gnu/drivers/iio/dac/ad5592r-base.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/iio/dac/ad5592r-base.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,76 @@
+/*
+ * AD5592R / AD5593R Digital <-> Analog converters driver
+ *
+ * Copyright 2015-2016 Analog Devices Inc.
+ * Author: Paul Cercueil <paul.cercueil@analog.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#ifndef __DRIVERS_IIO_DAC_AD5592R_BASE_H__
+#define __DRIVERS_IIO_DAC_AD5592R_BASE_H__
+
+#include <linux/types.h>
+#include <linux/cache.h>
+#include <linux/mutex.h>
+#include <linux/gpio/driver.h>
+
+struct device;
+struct ad5592r_state;
+
+enum ad5592r_registers {
+	AD5592R_REG_NOOP		= 0x0,
+	AD5592R_REG_DAC_READBACK	= 0x1,
+	AD5592R_REG_ADC_SEQ		= 0x2,
+	AD5592R_REG_CTRL		= 0x3,
+	AD5592R_REG_ADC_EN		= 0x4,
+	AD5592R_REG_DAC_EN		= 0x5,
+	AD5592R_REG_PULLDOWN		= 0x6,
+	AD5592R_REG_LDAC		= 0x7,
+	AD5592R_REG_GPIO_OUT_EN		= 0x8,
+	AD5592R_REG_GPIO_SET		= 0x9,
+	AD5592R_REG_GPIO_IN_EN		= 0xA,
+	AD5592R_REG_PD			= 0xB,
+	AD5592R_REG_OPEN_DRAIN		= 0xC,
+	AD5592R_REG_TRISTATE		= 0xD,
+	AD5592R_REG_RESET		= 0xF,
+};
+
+#define AD5592R_REG_PD_EN_REF		BIT(9)
+#define AD5592R_REG_CTRL_ADC_RANGE	BIT(5)
+#define AD5592R_REG_CTRL_DAC_RANGE	BIT(4)
+
+struct ad5592r_rw_ops {
+	int (*write_dac)(struct ad5592r_state *st, unsigned chan, u16 value);
+	int (*read_adc)(struct ad5592r_state *st, unsigned chan, u16 *value);
+	int (*reg_write)(struct ad5592r_state *st, u8 reg, u16 value);
+	int (*reg_read)(struct ad5592r_state *st, u8 reg, u16 *value);
+	int (*gpio_read)(struct ad5592r_state *st, u8 *value);
+};
+
+struct ad5592r_state {
+	struct device *dev;
+	struct regulator *reg;
+	struct gpio_chip gpiochip;
+	struct mutex gpio_lock;	/* Protect cached gpio_out, gpio_val, etc. */
+	unsigned int num_channels;
+	const struct ad5592r_rw_ops *ops;
+	int scale_avail[2][2];
+	u16 cached_dac[8];
+	u16 cached_gp_ctrl;
+	u8 channel_modes[8];
+	u8 channel_offstate[8];
+	u8 gpio_map;
+	u8 gpio_out;
+	u8 gpio_in;
+	u8 gpio_val;
+
+	__be16 spi_msg ____cacheline_aligned;
+	__be16 spi_msg_nop;
+};
+
+int ad5592r_probe(struct device *dev, const char *name,
+		const struct ad5592r_rw_ops *ops);
+int ad5592r_remove(struct device *dev);
+
+#endif /* __DRIVERS_IIO_DAC_AD5592R_BASE_H__ */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/dac/ad5592r.c linux-libre-4.7-gnu/drivers/iio/dac/ad5592r.c
--- linux-libre-4.6-gnu/drivers/iio/dac/ad5592r.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/iio/dac/ad5592r.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,164 @@
+/*
+ * AD5592R Digital <-> Analog converters driver
+ *
+ * Copyright 2015-2016 Analog Devices Inc.
+ * Author: Paul Cercueil <paul.cercueil@analog.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include "ad5592r-base.h"
+
+#include <linux/bitops.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/spi/spi.h>
+
+#define AD5592R_GPIO_READBACK_EN	BIT(10)
+#define AD5592R_LDAC_READBACK_EN	BIT(6)
+
+static int ad5592r_spi_wnop_r16(struct ad5592r_state *st, u16 *buf)
+{
+	struct spi_device *spi = container_of(st->dev, struct spi_device, dev);
+	struct spi_transfer t = {
+			.tx_buf	= &st->spi_msg_nop,
+			.rx_buf	= buf,
+			.len = 2
+		};
+
+	st->spi_msg_nop = 0; /* NOP */
+
+	return spi_sync_transfer(spi, &t, 1);
+}
+
+static int ad5592r_write_dac(struct ad5592r_state *st, unsigned chan, u16 value)
+{
+	struct spi_device *spi = container_of(st->dev, struct spi_device, dev);
+
+	st->spi_msg = cpu_to_be16(BIT(15) | (chan << 12) | value);
+
+	return spi_write(spi, &st->spi_msg, sizeof(st->spi_msg));
+}
+
+static int ad5592r_read_adc(struct ad5592r_state *st, unsigned chan, u16 *value)
+{
+	struct spi_device *spi = container_of(st->dev, struct spi_device, dev);
+	int ret;
+
+	st->spi_msg = cpu_to_be16((AD5592R_REG_ADC_SEQ << 11) | BIT(chan));
+
+	ret = spi_write(spi, &st->spi_msg, sizeof(st->spi_msg));
+	if (ret)
+		return ret;
+
+	/*
+	 * Invalid data:
+	 * See Figure 40. Single-Channel ADC Conversion Sequence
+	 */
+	ret = ad5592r_spi_wnop_r16(st, &st->spi_msg);
+	if (ret)
+		return ret;
+
+	ret = ad5592r_spi_wnop_r16(st, &st->spi_msg);
+	if (ret)
+		return ret;
+
+	*value = be16_to_cpu(st->spi_msg);
+
+	return 0;
+}
+
+static int ad5592r_reg_write(struct ad5592r_state *st, u8 reg, u16 value)
+{
+	struct spi_device *spi = container_of(st->dev, struct spi_device, dev);
+
+	st->spi_msg = cpu_to_be16((reg << 11) | value);
+
+	return spi_write(spi, &st->spi_msg, sizeof(st->spi_msg));
+}
+
+static int ad5592r_reg_read(struct ad5592r_state *st, u8 reg, u16 *value)
+{
+	struct spi_device *spi = container_of(st->dev, struct spi_device, dev);
+	int ret;
+
+	st->spi_msg = cpu_to_be16((AD5592R_REG_LDAC << 11) |
+				   AD5592R_LDAC_READBACK_EN | (reg << 2));
+
+	ret = spi_write(spi, &st->spi_msg, sizeof(st->spi_msg));
+	if (ret)
+		return ret;
+
+	ret = ad5592r_spi_wnop_r16(st, &st->spi_msg);
+	if (ret)
+		return ret;
+
+	*value = be16_to_cpu(st->spi_msg);
+
+	return 0;
+}
+
+static int ad5593r_gpio_read(struct ad5592r_state *st, u8 *value)
+{
+	int ret;
+
+	ret = ad5592r_reg_write(st, AD5592R_REG_GPIO_IN_EN,
+				AD5592R_GPIO_READBACK_EN | st->gpio_in);
+	if (ret)
+		return ret;
+
+	ret = ad5592r_spi_wnop_r16(st, &st->spi_msg);
+	if (ret)
+		return ret;
+
+	*value = (u8) be16_to_cpu(st->spi_msg);
+
+	return 0;
+}
+
+static const struct ad5592r_rw_ops ad5592r_rw_ops = {
+	.write_dac = ad5592r_write_dac,
+	.read_adc = ad5592r_read_adc,
+	.reg_write = ad5592r_reg_write,
+	.reg_read = ad5592r_reg_read,
+	.gpio_read = ad5593r_gpio_read,
+};
+
+static int ad5592r_spi_probe(struct spi_device *spi)
+{
+	const struct spi_device_id *id = spi_get_device_id(spi);
+
+	return ad5592r_probe(&spi->dev, id->name, &ad5592r_rw_ops);
+}
+
+static int ad5592r_spi_remove(struct spi_device *spi)
+{
+	return ad5592r_remove(&spi->dev);
+}
+
+static const struct spi_device_id ad5592r_spi_ids[] = {
+	{ .name = "ad5592r", },
+	{}
+};
+MODULE_DEVICE_TABLE(spi, ad5592r_spi_ids);
+
+static const struct of_device_id ad5592r_of_match[] = {
+	{ .compatible = "adi,ad5592r", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, ad5592r_of_match);
+
+static struct spi_driver ad5592r_spi_driver = {
+	.driver = {
+		.name = "ad5592r",
+		.of_match_table = of_match_ptr(ad5592r_of_match),
+	},
+	.probe = ad5592r_spi_probe,
+	.remove = ad5592r_spi_remove,
+	.id_table = ad5592r_spi_ids,
+};
+module_spi_driver(ad5592r_spi_driver);
+
+MODULE_AUTHOR("Paul Cercueil <paul.cercueil@analog.com>");
+MODULE_DESCRIPTION("Analog Devices AD5592R multi-channel converters");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/dac/ad5593r.c linux-libre-4.7-gnu/drivers/iio/dac/ad5593r.c
--- linux-libre-4.6-gnu/drivers/iio/dac/ad5593r.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/iio/dac/ad5593r.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,131 @@
+/*
+ * AD5593R Digital <-> Analog converters driver
+ *
+ * Copyright 2015-2016 Analog Devices Inc.
+ * Author: Paul Cercueil <paul.cercueil@analog.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include "ad5592r-base.h"
+
+#include <linux/bitops.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/of.h>
+
+#define AD5593R_MODE_CONF		(0 << 4)
+#define AD5593R_MODE_DAC_WRITE		(1 << 4)
+#define AD5593R_MODE_ADC_READBACK	(4 << 4)
+#define AD5593R_MODE_DAC_READBACK	(5 << 4)
+#define AD5593R_MODE_GPIO_READBACK	(6 << 4)
+#define AD5593R_MODE_REG_READBACK	(7 << 4)
+
+static int ad5593r_write_dac(struct ad5592r_state *st, unsigned chan, u16 value)
+{
+	struct i2c_client *i2c = to_i2c_client(st->dev);
+
+	return i2c_smbus_write_word_swapped(i2c,
+			AD5593R_MODE_DAC_WRITE | chan, value);
+}
+
+static int ad5593r_read_adc(struct ad5592r_state *st, unsigned chan, u16 *value)
+{
+	struct i2c_client *i2c = to_i2c_client(st->dev);
+	s32 val;
+
+	val = i2c_smbus_write_word_swapped(i2c,
+			AD5593R_MODE_CONF | AD5592R_REG_ADC_SEQ, BIT(chan));
+	if (val < 0)
+		return (int) val;
+
+	val = i2c_smbus_read_word_swapped(i2c, AD5593R_MODE_ADC_READBACK);
+	if (val < 0)
+		return (int) val;
+
+	*value = (u16) val;
+
+	return 0;
+}
+
+static int ad5593r_reg_write(struct ad5592r_state *st, u8 reg, u16 value)
+{
+	struct i2c_client *i2c = to_i2c_client(st->dev);
+
+	return i2c_smbus_write_word_swapped(i2c,
+			AD5593R_MODE_CONF | reg, value);
+}
+
+static int ad5593r_reg_read(struct ad5592r_state *st, u8 reg, u16 *value)
+{
+	struct i2c_client *i2c = to_i2c_client(st->dev);
+	s32 val;
+
+	val = i2c_smbus_read_word_swapped(i2c, AD5593R_MODE_REG_READBACK | reg);
+	if (val < 0)
+		return (int) val;
+
+	*value = (u16) val;
+
+	return 0;
+}
+
+static int ad5593r_gpio_read(struct ad5592r_state *st, u8 *value)
+{
+	struct i2c_client *i2c = to_i2c_client(st->dev);
+	s32 val;
+
+	val = i2c_smbus_read_word_swapped(i2c, AD5593R_MODE_GPIO_READBACK);
+	if (val < 0)
+		return (int) val;
+
+	*value = (u8) val;
+
+	return 0;
+}
+
+static const struct ad5592r_rw_ops ad5593r_rw_ops = {
+	.write_dac = ad5593r_write_dac,
+	.read_adc = ad5593r_read_adc,
+	.reg_write = ad5593r_reg_write,
+	.reg_read = ad5593r_reg_read,
+	.gpio_read = ad5593r_gpio_read,
+};
+
+static int ad5593r_i2c_probe(struct i2c_client *i2c,
+		const struct i2c_device_id *id)
+{
+	return ad5592r_probe(&i2c->dev, id->name, &ad5593r_rw_ops);
+}
+
+static int ad5593r_i2c_remove(struct i2c_client *i2c)
+{
+	return ad5592r_remove(&i2c->dev);
+}
+
+static const struct i2c_device_id ad5593r_i2c_ids[] = {
+	{ .name = "ad5593r", },
+	{},
+};
+MODULE_DEVICE_TABLE(i2c, ad5593r_i2c_ids);
+
+static const struct of_device_id ad5593r_of_match[] = {
+	{ .compatible = "adi,ad5593r", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, ad5593r_of_match);
+
+static struct i2c_driver ad5593r_driver = {
+	.driver = {
+		.name = "ad5593r",
+		.of_match_table = of_match_ptr(ad5593r_of_match),
+	},
+	.probe = ad5593r_i2c_probe,
+	.remove = ad5593r_i2c_remove,
+	.id_table = ad5593r_i2c_ids,
+};
+module_i2c_driver(ad5593r_driver);
+
+MODULE_AUTHOR("Paul Cercueil <paul.cercueil@analog.com>");
+MODULE_DESCRIPTION("Analog Devices AD5592R multi-channel converters");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/dac/Kconfig linux-libre-4.7-gnu/drivers/iio/dac/Kconfig
--- linux-libre-4.6-gnu/drivers/iio/dac/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/dac/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -74,6 +74,33 @@ config AD5449
 	  To compile this driver as a module, choose M here: the
 	  module will be called ad5449.
 
+config AD5592R_BASE
+	tristate
+
+config AD5592R
+	tristate "Analog Devices AD5592R ADC/DAC driver"
+	depends on SPI_MASTER
+	select GPIOLIB
+	select AD5592R_BASE
+	help
+	  Say yes here to build support for Analog Devices AD5592R
+	  Digital to Analog / Analog to Digital Converter.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ad5592r.
+
+config AD5593R
+	tristate "Analog Devices AD5593R ADC/DAC driver"
+	depends on I2C
+	select GPIOLIB
+	select AD5592R_BASE
+	help
+	  Say yes here to build support for Analog Devices AD5593R
+	  Digital to Analog / Analog to Digital Converter.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ad5593r.
+
 config AD5504
 	tristate "Analog Devices AD5504/AD5501 DAC SPI driver"
 	depends on SPI
@@ -154,6 +181,16 @@ config AD7303
 	  To compile this driver as module choose M here: the module will be called
 	  ad7303.
 
+config LPC18XX_DAC
+	tristate "NXP LPC18xx DAC driver"
+	depends on ARCH_LPC18XX || COMPILE_TEST
+	depends on OF && HAS_IOMEM
+	help
+	  Say yes here to build support for NXP LPC18XX DAC.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called lpc18xx_dac.
+
 config M62332
 	tristate "Mitsubishi M62332 DAC driver"
 	depends on I2C
@@ -210,7 +247,7 @@ config MCP4922
 
 config STX104
 	tristate "Apex Embedded Systems STX104 DAC driver"
-	depends on ISA
+	depends on X86 && ISA_BUS_API
 	help
 	  Say yes here to build support for the 2-channel DAC on the Apex
 	  Embedded Systems STX104 integrated analog PC/104 card. The base port
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/dac/lpc18xx_dac.c linux-libre-4.7-gnu/drivers/iio/dac/lpc18xx_dac.c
--- linux-libre-4.6-gnu/drivers/iio/dac/lpc18xx_dac.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/iio/dac/lpc18xx_dac.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,210 @@
+/*
+ * IIO DAC driver for NXP LPC18xx DAC
+ *
+ * Copyright (C) 2016 Joachim Eastwood <manabian@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * UNSUPPORTED hardware features:
+ *  - Interrupts
+ *  - DMA
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/driver.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+
+/* LPC18XX DAC registers and bits */
+#define LPC18XX_DAC_CR			0x000
+#define  LPC18XX_DAC_CR_VALUE_SHIFT	6
+#define  LPC18XX_DAC_CR_VALUE_MASK	0x3ff
+#define  LPC18XX_DAC_CR_BIAS		BIT(16)
+#define LPC18XX_DAC_CTRL		0x004
+#define  LPC18XX_DAC_CTRL_DMA_ENA	BIT(3)
+
+struct lpc18xx_dac {
+	struct regulator *vref;
+	void __iomem *base;
+	struct mutex lock;
+	struct clk *clk;
+};
+
+static const struct iio_chan_spec lpc18xx_dac_iio_channels[] = {
+	{
+		.type = IIO_VOLTAGE,
+		.output = 1,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+				      BIT(IIO_CHAN_INFO_SCALE),
+	},
+};
+
+static int lpc18xx_dac_read_raw(struct iio_dev *indio_dev,
+				struct iio_chan_spec const *chan,
+				int *val, int *val2, long mask)
+{
+	struct lpc18xx_dac *dac = iio_priv(indio_dev);
+	u32 reg;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		reg = readl(dac->base + LPC18XX_DAC_CR);
+		*val = reg >> LPC18XX_DAC_CR_VALUE_SHIFT;
+		*val &= LPC18XX_DAC_CR_VALUE_MASK;
+
+		return IIO_VAL_INT;
+
+	case IIO_CHAN_INFO_SCALE:
+		*val = regulator_get_voltage(dac->vref) / 1000;
+		*val2 = 10;
+
+		return IIO_VAL_FRACTIONAL_LOG2;
+	}
+
+	return -EINVAL;
+}
+
+static int lpc18xx_dac_write_raw(struct iio_dev *indio_dev,
+				 struct iio_chan_spec const *chan,
+				 int val, int val2, long mask)
+{
+	struct lpc18xx_dac *dac = iio_priv(indio_dev);
+	u32 reg;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		if (val < 0 || val > LPC18XX_DAC_CR_VALUE_MASK)
+			return -EINVAL;
+
+		reg = LPC18XX_DAC_CR_BIAS;
+		reg |= val << LPC18XX_DAC_CR_VALUE_SHIFT;
+
+		mutex_lock(&dac->lock);
+		writel(reg, dac->base + LPC18XX_DAC_CR);
+		writel(LPC18XX_DAC_CTRL_DMA_ENA, dac->base + LPC18XX_DAC_CTRL);
+		mutex_unlock(&dac->lock);
+
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static const struct iio_info lpc18xx_dac_info = {
+	.read_raw = lpc18xx_dac_read_raw,
+	.write_raw = lpc18xx_dac_write_raw,
+	.driver_module = THIS_MODULE,
+};
+
+static int lpc18xx_dac_probe(struct platform_device *pdev)
+{
+	struct iio_dev *indio_dev;
+	struct lpc18xx_dac *dac;
+	struct resource *res;
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*dac));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, indio_dev);
+	dac = iio_priv(indio_dev);
+	mutex_init(&dac->lock);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	dac->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(dac->base))
+		return PTR_ERR(dac->base);
+
+	dac->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(dac->clk)) {
+		dev_err(&pdev->dev, "error getting clock\n");
+		return PTR_ERR(dac->clk);
+	}
+
+	dac->vref = devm_regulator_get(&pdev->dev, "vref");
+	if (IS_ERR(dac->vref)) {
+		dev_err(&pdev->dev, "error getting regulator\n");
+		return PTR_ERR(dac->vref);
+	}
+
+	indio_dev->name = dev_name(&pdev->dev);
+	indio_dev->dev.parent = &pdev->dev;
+	indio_dev->info = &lpc18xx_dac_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = lpc18xx_dac_iio_channels;
+	indio_dev->num_channels = ARRAY_SIZE(lpc18xx_dac_iio_channels);
+
+	ret = regulator_enable(dac->vref);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to enable regulator\n");
+		return ret;
+	}
+
+	ret = clk_prepare_enable(dac->clk);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to enable clock\n");
+		goto dis_reg;
+	}
+
+	writel(0, dac->base + LPC18XX_DAC_CTRL);
+	writel(0, dac->base + LPC18XX_DAC_CR);
+
+	ret = iio_device_register(indio_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to register device\n");
+		goto dis_clk;
+	}
+
+	return 0;
+
+dis_clk:
+	clk_disable_unprepare(dac->clk);
+dis_reg:
+	regulator_disable(dac->vref);
+	return ret;
+}
+
+static int lpc18xx_dac_remove(struct platform_device *pdev)
+{
+	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+	struct lpc18xx_dac *dac = iio_priv(indio_dev);
+
+	iio_device_unregister(indio_dev);
+
+	writel(0, dac->base + LPC18XX_DAC_CTRL);
+	clk_disable_unprepare(dac->clk);
+	regulator_disable(dac->vref);
+
+	return 0;
+}
+
+static const struct of_device_id lpc18xx_dac_match[] = {
+	{ .compatible = "nxp,lpc1850-dac" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, lpc18xx_dac_match);
+
+static struct platform_driver lpc18xx_dac_driver = {
+	.probe	= lpc18xx_dac_probe,
+	.remove	= lpc18xx_dac_remove,
+	.driver	= {
+		.name = "lpc18xx-dac",
+		.of_match_table = lpc18xx_dac_match,
+	},
+};
+module_platform_driver(lpc18xx_dac_driver);
+
+MODULE_DESCRIPTION("LPC18xx DAC driver");
+MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/dac/Makefile linux-libre-4.7-gnu/drivers/iio/dac/Makefile
--- linux-libre-4.6-gnu/drivers/iio/dac/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/dac/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -11,12 +11,16 @@ obj-$(CONFIG_AD5064) += ad5064.o
 obj-$(CONFIG_AD5504) += ad5504.o
 obj-$(CONFIG_AD5446) += ad5446.o
 obj-$(CONFIG_AD5449) += ad5449.o
+obj-$(CONFIG_AD5592R_BASE) += ad5592r-base.o
+obj-$(CONFIG_AD5592R) += ad5592r.o
+obj-$(CONFIG_AD5593R) += ad5593r.o
 obj-$(CONFIG_AD5755) += ad5755.o
 obj-$(CONFIG_AD5761) += ad5761.o
 obj-$(CONFIG_AD5764) += ad5764.o
 obj-$(CONFIG_AD5791) += ad5791.o
 obj-$(CONFIG_AD5686) += ad5686.o
 obj-$(CONFIG_AD7303) += ad7303.o
+obj-$(CONFIG_LPC18XX_DAC) += lpc18xx_dac.o
 obj-$(CONFIG_M62332) += m62332.o
 obj-$(CONFIG_MAX517) += max517.o
 obj-$(CONFIG_MAX5821) += max5821.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/dac/stx104.c linux-libre-4.7-gnu/drivers/iio/dac/stx104.c
--- linux-libre-4.6-gnu/drivers/iio/dac/stx104.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/dac/stx104.c	2016-07-24 15:23:50.000000000 -0400
@@ -33,16 +33,9 @@
 }
 
 #define STX104_EXTENT 16
-/**
- * The highest base address possible for an ISA device is 0x3FF; this results in
- * 1024 possible base addresses. Dividing the number of possible base addresses
- * by the address extent taken by each device results in the maximum number of
- * devices on a system.
- */
-#define MAX_NUM_STX104 (1024 / STX104_EXTENT)
 
-static unsigned base[MAX_NUM_STX104];
-static unsigned num_stx104;
+static unsigned int base[max_num_isa_dev(STX104_EXTENT)];
+static unsigned int num_stx104;
 module_param_array(base, uint, &num_stx104, 0);
 MODULE_PARM_DESC(base, "Apex Embedded Systems STX104 base addresses");
 
@@ -134,18 +127,7 @@ static struct isa_driver stx104_driver =
 	}
 };
 
-static void __exit stx104_exit(void)
-{
-	isa_unregister_driver(&stx104_driver);
-}
-
-static int __init stx104_init(void)
-{
-	return isa_register_driver(&stx104_driver, num_stx104);
-}
-
-module_init(stx104_init);
-module_exit(stx104_exit);
+module_isa_driver(stx104_driver, num_stx104);
 
 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
 MODULE_DESCRIPTION("Apex Embedded Systems STX104 DAC driver");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/frequency/ad9523.c linux-libre-4.7-gnu/drivers/iio/frequency/ad9523.c
--- linux-libre-4.6-gnu/drivers/iio/frequency/ad9523.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/frequency/ad9523.c	2016-07-24 15:23:50.000000000 -0400
@@ -284,7 +284,7 @@ struct ad9523_state {
 	} data[2] ____cacheline_aligned;
 };
 
-static int ad9523_read(struct iio_dev *indio_dev, unsigned addr)
+static int ad9523_read(struct iio_dev *indio_dev, unsigned int addr)
 {
 	struct ad9523_state *st = iio_priv(indio_dev);
 	int ret;
@@ -318,7 +318,8 @@ static int ad9523_read(struct iio_dev *i
 	return ret;
 };
 
-static int ad9523_write(struct iio_dev *indio_dev, unsigned addr, unsigned val)
+static int ad9523_write(struct iio_dev *indio_dev,
+		unsigned int addr, unsigned int val)
 {
 	struct ad9523_state *st = iio_priv(indio_dev);
 	int ret;
@@ -351,11 +352,11 @@ static int ad9523_io_update(struct iio_d
 }
 
 static int ad9523_vco_out_map(struct iio_dev *indio_dev,
-			      unsigned ch, unsigned out)
+			      unsigned int ch, unsigned int out)
 {
 	struct ad9523_state *st = iio_priv(indio_dev);
 	int ret;
-	unsigned mask;
+	unsigned int mask;
 
 	switch (ch) {
 	case 0 ... 3:
@@ -405,7 +406,7 @@ static int ad9523_vco_out_map(struct iio
 }
 
 static int ad9523_set_clock_provider(struct iio_dev *indio_dev,
-			      unsigned ch, unsigned long freq)
+			      unsigned int ch, unsigned long freq)
 {
 	struct ad9523_state *st = iio_priv(indio_dev);
 	long tmp1, tmp2;
@@ -619,7 +620,7 @@ static int ad9523_read_raw(struct iio_de
 			   long m)
 {
 	struct ad9523_state *st = iio_priv(indio_dev);
-	unsigned code;
+	unsigned int code;
 	int ret;
 
 	mutex_lock(&indio_dev->mlock);
@@ -655,7 +656,7 @@ static int ad9523_write_raw(struct iio_d
 			    long mask)
 {
 	struct ad9523_state *st = iio_priv(indio_dev);
-	unsigned reg;
+	unsigned int reg;
 	int ret, tmp, code;
 
 	mutex_lock(&indio_dev->mlock);
@@ -709,8 +710,8 @@ out:
 }
 
 static int ad9523_reg_access(struct iio_dev *indio_dev,
-			      unsigned reg, unsigned writeval,
-			      unsigned *readval)
+			      unsigned int reg, unsigned int writeval,
+			      unsigned int *readval)
 {
 	int ret;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/gyro/bmg160_core.c linux-libre-4.7-gnu/drivers/iio/gyro/bmg160_core.c
--- linux-libre-4.6-gnu/drivers/iio/gyro/bmg160_core.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/gyro/bmg160_core.c	2016-07-24 15:23:50.000000000 -0400
@@ -17,7 +17,6 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/acpi.h>
-#include <linux/gpio/consumer.h>
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
 #include <linux/iio/iio.h>
@@ -31,7 +30,6 @@
 #include "bmg160.h"
 
 #define BMG160_IRQ_NAME		"bmg160_event"
-#define BMG160_GPIO_NAME		"gpio_int"
 
 #define BMG160_REG_CHIP_ID		0x00
 #define BMG160_CHIP_ID_VAL		0x0F
@@ -97,7 +95,6 @@
 #define BMG160_AUTO_SUSPEND_DELAY_MS	2000
 
 struct bmg160_data {
-	struct device *dev;
 	struct regmap *regmap;
 	struct iio_trigger *dready_trig;
 	struct iio_trigger *motion_trig;
@@ -116,6 +113,7 @@ enum bmg160_axis {
 	AXIS_X,
 	AXIS_Y,
 	AXIS_Z,
+	AXIS_MAX,
 };
 
 static const struct {
@@ -138,11 +136,12 @@ static const struct {
 
 static int bmg160_set_mode(struct bmg160_data *data, u8 mode)
 {
+	struct device *dev = regmap_get_device(data->regmap);
 	int ret;
 
 	ret = regmap_write(data->regmap, BMG160_REG_PMU_LPW, mode);
 	if (ret < 0) {
-		dev_err(data->dev, "Error writing reg_pmu_lpw\n");
+		dev_err(dev, "Error writing reg_pmu_lpw\n");
 		return ret;
 	}
 
@@ -163,6 +162,7 @@ static int bmg160_convert_freq_to_bit(in
 
 static int bmg160_set_bw(struct bmg160_data *data, int val)
 {
+	struct device *dev = regmap_get_device(data->regmap);
 	int ret;
 	int bw_bits;
 
@@ -172,7 +172,7 @@ static int bmg160_set_bw(struct bmg160_d
 
 	ret = regmap_write(data->regmap, BMG160_REG_PMU_BW, bw_bits);
 	if (ret < 0) {
-		dev_err(data->dev, "Error writing reg_pmu_bw\n");
+		dev_err(dev, "Error writing reg_pmu_bw\n");
 		return ret;
 	}
 
@@ -183,18 +183,19 @@ static int bmg160_set_bw(struct bmg160_d
 
 static int bmg160_chip_init(struct bmg160_data *data)
 {
+	struct device *dev = regmap_get_device(data->regmap);
 	int ret;
 	unsigned int val;
 
 	ret = regmap_read(data->regmap, BMG160_REG_CHIP_ID, &val);
 	if (ret < 0) {
-		dev_err(data->dev, "Error reading reg_chip_id\n");
+		dev_err(dev, "Error reading reg_chip_id\n");
 		return ret;
 	}
 
-	dev_dbg(data->dev, "Chip Id %x\n", val);
+	dev_dbg(dev, "Chip Id %x\n", val);
 	if (val != BMG160_CHIP_ID_VAL) {
-		dev_err(data->dev, "invalid chip %x\n", val);
+		dev_err(dev, "invalid chip %x\n", val);
 		return -ENODEV;
 	}
 
@@ -213,14 +214,14 @@ static int bmg160_chip_init(struct bmg16
 	/* Set Default Range */
 	ret = regmap_write(data->regmap, BMG160_REG_RANGE, BMG160_RANGE_500DPS);
 	if (ret < 0) {
-		dev_err(data->dev, "Error writing reg_range\n");
+		dev_err(dev, "Error writing reg_range\n");
 		return ret;
 	}
 	data->dps_range = BMG160_RANGE_500DPS;
 
 	ret = regmap_read(data->regmap, BMG160_REG_SLOPE_THRES, &val);
 	if (ret < 0) {
-		dev_err(data->dev, "Error reading reg_slope_thres\n");
+		dev_err(dev, "Error reading reg_slope_thres\n");
 		return ret;
 	}
 	data->slope_thres = val;
@@ -229,7 +230,7 @@ static int bmg160_chip_init(struct bmg16
 	ret = regmap_update_bits(data->regmap, BMG160_REG_INT_EN_1,
 				 BMG160_INT1_BIT_OD, 0);
 	if (ret < 0) {
-		dev_err(data->dev, "Error updating bits in reg_int_en_1\n");
+		dev_err(dev, "Error updating bits in reg_int_en_1\n");
 		return ret;
 	}
 
@@ -237,7 +238,7 @@ static int bmg160_chip_init(struct bmg16
 			   BMG160_INT_MODE_LATCH_INT |
 			   BMG160_INT_MODE_LATCH_RESET);
 	if (ret < 0) {
-		dev_err(data->dev,
+		dev_err(dev,
 			"Error writing reg_motion_intr\n");
 		return ret;
 	}
@@ -248,20 +249,21 @@ static int bmg160_chip_init(struct bmg16
 static int bmg160_set_power_state(struct bmg160_data *data, bool on)
 {
 #ifdef CONFIG_PM
+	struct device *dev = regmap_get_device(data->regmap);
 	int ret;
 
 	if (on)
-		ret = pm_runtime_get_sync(data->dev);
+		ret = pm_runtime_get_sync(dev);
 	else {
-		pm_runtime_mark_last_busy(data->dev);
-		ret = pm_runtime_put_autosuspend(data->dev);
+		pm_runtime_mark_last_busy(dev);
+		ret = pm_runtime_put_autosuspend(dev);
 	}
 
 	if (ret < 0) {
-		dev_err(data->dev,
-			"Failed: bmg160_set_power_state for %d\n", on);
+		dev_err(dev, "Failed: bmg160_set_power_state for %d\n", on);
+
 		if (on)
-			pm_runtime_put_noidle(data->dev);
+			pm_runtime_put_noidle(dev);
 
 		return ret;
 	}
@@ -273,6 +275,7 @@ static int bmg160_set_power_state(struct
 static int bmg160_setup_any_motion_interrupt(struct bmg160_data *data,
 					     bool status)
 {
+	struct device *dev = regmap_get_device(data->regmap);
 	int ret;
 
 	/* Enable/Disable INT_MAP0 mapping */
@@ -280,7 +283,7 @@ static int bmg160_setup_any_motion_inter
 				 BMG160_INT_MAP_0_BIT_ANY,
 				 (status ? BMG160_INT_MAP_0_BIT_ANY : 0));
 	if (ret < 0) {
-		dev_err(data->dev, "Error updating bits reg_int_map0\n");
+		dev_err(dev, "Error updating bits reg_int_map0\n");
 		return ret;
 	}
 
@@ -290,8 +293,7 @@ static int bmg160_setup_any_motion_inter
 		ret = regmap_write(data->regmap, BMG160_REG_SLOPE_THRES,
 				   data->slope_thres);
 		if (ret < 0) {
-			dev_err(data->dev,
-				"Error writing reg_slope_thres\n");
+			dev_err(dev, "Error writing reg_slope_thres\n");
 			return ret;
 		}
 
@@ -299,8 +301,7 @@ static int bmg160_setup_any_motion_inter
 				   BMG160_INT_MOTION_X | BMG160_INT_MOTION_Y |
 				   BMG160_INT_MOTION_Z);
 		if (ret < 0) {
-			dev_err(data->dev,
-				"Error writing reg_motion_intr\n");
+			dev_err(dev, "Error writing reg_motion_intr\n");
 			return ret;
 		}
 
@@ -315,8 +316,7 @@ static int bmg160_setup_any_motion_inter
 					   BMG160_INT_MODE_LATCH_INT |
 					   BMG160_INT_MODE_LATCH_RESET);
 			if (ret < 0) {
-				dev_err(data->dev,
-					"Error writing reg_rst_latch\n");
+				dev_err(dev, "Error writing reg_rst_latch\n");
 				return ret;
 			}
 		}
@@ -329,7 +329,7 @@ static int bmg160_setup_any_motion_inter
 	}
 
 	if (ret < 0) {
-		dev_err(data->dev, "Error writing reg_int_en0\n");
+		dev_err(dev, "Error writing reg_int_en0\n");
 		return ret;
 	}
 
@@ -339,6 +339,7 @@ static int bmg160_setup_any_motion_inter
 static int bmg160_setup_new_data_interrupt(struct bmg160_data *data,
 					   bool status)
 {
+	struct device *dev = regmap_get_device(data->regmap);
 	int ret;
 
 	/* Enable/Disable INT_MAP1 mapping */
@@ -346,7 +347,7 @@ static int bmg160_setup_new_data_interru
 				 BMG160_INT_MAP_1_BIT_NEW_DATA,
 				 (status ? BMG160_INT_MAP_1_BIT_NEW_DATA : 0));
 	if (ret < 0) {
-		dev_err(data->dev, "Error updating bits in reg_int_map1\n");
+		dev_err(dev, "Error updating bits in reg_int_map1\n");
 		return ret;
 	}
 
@@ -355,9 +356,8 @@ static int bmg160_setup_new_data_interru
 				   BMG160_INT_MODE_NON_LATCH_INT |
 				   BMG160_INT_MODE_LATCH_RESET);
 		if (ret < 0) {
-			dev_err(data->dev,
-				"Error writing reg_rst_latch\n");
-				return ret;
+			dev_err(dev, "Error writing reg_rst_latch\n");
+			return ret;
 		}
 
 		ret = regmap_write(data->regmap, BMG160_REG_INT_EN_0,
@@ -369,16 +369,15 @@ static int bmg160_setup_new_data_interru
 				   BMG160_INT_MODE_LATCH_INT |
 				   BMG160_INT_MODE_LATCH_RESET);
 		if (ret < 0) {
-			dev_err(data->dev,
-				"Error writing reg_rst_latch\n");
-				return ret;
+			dev_err(dev, "Error writing reg_rst_latch\n");
+			return ret;
 		}
 
 		ret = regmap_write(data->regmap, BMG160_REG_INT_EN_0, 0);
 	}
 
 	if (ret < 0) {
-		dev_err(data->dev, "Error writing reg_int_en0\n");
+		dev_err(dev, "Error writing reg_int_en0\n");
 		return ret;
 	}
 
@@ -401,6 +400,7 @@ static int bmg160_get_bw(struct bmg160_d
 
 static int bmg160_set_scale(struct bmg160_data *data, int val)
 {
+	struct device *dev = regmap_get_device(data->regmap);
 	int ret, i;
 
 	for (i = 0; i < ARRAY_SIZE(bmg160_scale_table); ++i) {
@@ -408,8 +408,7 @@ static int bmg160_set_scale(struct bmg16
 			ret = regmap_write(data->regmap, BMG160_REG_RANGE,
 					   bmg160_scale_table[i].dps_range);
 			if (ret < 0) {
-				dev_err(data->dev,
-					"Error writing reg_range\n");
+				dev_err(dev, "Error writing reg_range\n");
 				return ret;
 			}
 			data->dps_range = bmg160_scale_table[i].dps_range;
@@ -422,6 +421,7 @@ static int bmg160_set_scale(struct bmg16
 
 static int bmg160_get_temp(struct bmg160_data *data, int *val)
 {
+	struct device *dev = regmap_get_device(data->regmap);
 	int ret;
 	unsigned int raw_val;
 
@@ -434,7 +434,7 @@ static int bmg160_get_temp(struct bmg160
 
 	ret = regmap_read(data->regmap, BMG160_REG_TEMP, &raw_val);
 	if (ret < 0) {
-		dev_err(data->dev, "Error reading reg_temp\n");
+		dev_err(dev, "Error reading reg_temp\n");
 		bmg160_set_power_state(data, false);
 		mutex_unlock(&data->mutex);
 		return ret;
@@ -451,6 +451,7 @@ static int bmg160_get_temp(struct bmg160
 
 static int bmg160_get_axis(struct bmg160_data *data, int axis, int *val)
 {
+	struct device *dev = regmap_get_device(data->regmap);
 	int ret;
 	__le16 raw_val;
 
@@ -464,7 +465,7 @@ static int bmg160_get_axis(struct bmg160
 	ret = regmap_bulk_read(data->regmap, BMG160_AXIS_TO_REG(axis), &raw_val,
 			       sizeof(raw_val));
 	if (ret < 0) {
-		dev_err(data->dev, "Error reading axis %d\n", axis);
+		dev_err(dev, "Error reading axis %d\n", axis);
 		bmg160_set_power_state(data, false);
 		mutex_unlock(&data->mutex);
 		return ret;
@@ -764,26 +765,23 @@ static const struct iio_info bmg160_info
 	.driver_module		= THIS_MODULE,
 };
 
+static const unsigned long bmg160_accel_scan_masks[] = {
+					BIT(AXIS_X) | BIT(AXIS_Y) | BIT(AXIS_Z),
+					0};
+
 static irqreturn_t bmg160_trigger_handler(int irq, void *p)
 {
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct bmg160_data *data = iio_priv(indio_dev);
-	int bit, ret, i = 0;
-	unsigned int val;
+	int ret;
 
 	mutex_lock(&data->mutex);
-	for_each_set_bit(bit, indio_dev->active_scan_mask,
-			 indio_dev->masklength) {
-		ret = regmap_bulk_read(data->regmap, BMG160_AXIS_TO_REG(bit),
-				       &val, 2);
-		if (ret < 0) {
-			mutex_unlock(&data->mutex);
-			goto err;
-		}
-		data->buffer[i++] = val;
-	}
+	ret = regmap_bulk_read(data->regmap, BMG160_REG_XOUT_L,
+			       data->buffer, AXIS_MAX * 2);
 	mutex_unlock(&data->mutex);
+	if (ret < 0)
+		goto err;
 
 	iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
 					   pf->timestamp);
@@ -797,6 +795,7 @@ static int bmg160_trig_try_reen(struct i
 {
 	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
 	struct bmg160_data *data = iio_priv(indio_dev);
+	struct device *dev = regmap_get_device(data->regmap);
 	int ret;
 
 	/* new data interrupts don't need ack */
@@ -808,7 +807,7 @@ static int bmg160_trig_try_reen(struct i
 			   BMG160_INT_MODE_LATCH_INT |
 			   BMG160_INT_MODE_LATCH_RESET);
 	if (ret < 0) {
-		dev_err(data->dev, "Error writing reg_rst_latch\n");
+		dev_err(dev, "Error writing reg_rst_latch\n");
 		return ret;
 	}
 
@@ -868,13 +867,14 @@ static irqreturn_t bmg160_event_handler(
 {
 	struct iio_dev *indio_dev = private;
 	struct bmg160_data *data = iio_priv(indio_dev);
+	struct device *dev = regmap_get_device(data->regmap);
 	int ret;
 	int dir;
 	unsigned int val;
 
 	ret = regmap_read(data->regmap, BMG160_REG_INT_STATUS_2, &val);
 	if (ret < 0) {
-		dev_err(data->dev, "Error reading reg_int_status2\n");
+		dev_err(dev, "Error reading reg_int_status2\n");
 		goto ack_intr_status;
 	}
 
@@ -911,8 +911,7 @@ ack_intr_status:
 				   BMG160_INT_MODE_LATCH_INT |
 				   BMG160_INT_MODE_LATCH_RESET);
 		if (ret < 0)
-			dev_err(data->dev,
-				"Error writing reg_rst_latch\n");
+			dev_err(dev, "Error writing reg_rst_latch\n");
 	}
 
 	return IRQ_HANDLED;
@@ -956,29 +955,6 @@ static const struct iio_buffer_setup_ops
 	.postdisable = bmg160_buffer_postdisable,
 };
 
-static int bmg160_gpio_probe(struct bmg160_data *data)
-
-{
-	struct device *dev;
-	struct gpio_desc *gpio;
-
-	dev = data->dev;
-
-	/* data ready gpio interrupt pin */
-	gpio = devm_gpiod_get_index(dev, BMG160_GPIO_NAME, 0, GPIOD_IN);
-	if (IS_ERR(gpio)) {
-		dev_err(dev, "acpi gpio get index failed\n");
-		return PTR_ERR(gpio);
-	}
-
-	data->irq = gpiod_to_irq(gpio);
-
-	dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio),
-		data->irq);
-
-	return 0;
-}
-
 static const char *bmg160_match_acpi_device(struct device *dev)
 {
 	const struct acpi_device_id *id;
@@ -1003,7 +979,6 @@ int bmg160_core_probe(struct device *dev
 
 	data = iio_priv(indio_dev);
 	dev_set_drvdata(dev, indio_dev);
-	data->dev = dev;
 	data->irq = irq;
 	data->regmap = regmap;
 
@@ -1020,12 +995,10 @@ int bmg160_core_probe(struct device *dev
 	indio_dev->channels = bmg160_channels;
 	indio_dev->num_channels = ARRAY_SIZE(bmg160_channels);
 	indio_dev->name = name;
+	indio_dev->available_scan_masks = bmg160_accel_scan_masks;
 	indio_dev->modes = INDIO_DIRECT_MODE;
 	indio_dev->info = &bmg160_info;
 
-	if (data->irq <= 0)
-		bmg160_gpio_probe(data);
-
 	if (data->irq > 0) {
 		ret = devm_request_threaded_irq(dev,
 						data->irq,
@@ -1168,7 +1141,7 @@ static int bmg160_runtime_suspend(struct
 
 	ret = bmg160_set_mode(data, BMG160_MODE_SUSPEND);
 	if (ret < 0) {
-		dev_err(data->dev, "set mode failed\n");
+		dev_err(dev, "set mode failed\n");
 		return -EAGAIN;
 	}
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/gyro/Kconfig linux-libre-4.7-gnu/drivers/iio/gyro/Kconfig
--- linux-libre-4.6-gnu/drivers/iio/gyro/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/gyro/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -93,7 +93,7 @@ config IIO_ST_GYRO_3AXIS
 	select IIO_TRIGGERED_BUFFER if (IIO_BUFFER)
 	help
 	  Say yes here to build support for STMicroelectronics gyroscopes:
-	  L3G4200D, LSM330DL, L3GD20, LSM330DLC, L3G4IS, LSM330.
+	  L3G4200D, LSM330DL, L3GD20, LSM330DLC, L3G4IS, LSM330, LSM9DS0.
 
 	  This driver can also be built as a module. If so, these modules
 	  will be created:
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/gyro/st_gyro_buffer.c linux-libre-4.7-gnu/drivers/iio/gyro/st_gyro_buffer.c
--- linux-libre-4.6-gnu/drivers/iio/gyro/st_gyro_buffer.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/gyro/st_gyro_buffer.c	2016-07-24 15:23:50.000000000 -0400
@@ -91,7 +91,7 @@ static const struct iio_buffer_setup_ops
 
 int st_gyro_allocate_ring(struct iio_dev *indio_dev)
 {
-	return iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
+	return iio_triggered_buffer_setup(indio_dev, NULL,
 		&st_sensors_trigger_handler, &st_gyro_buffer_setup_ops);
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/gyro/st_gyro_core.c linux-libre-4.7-gnu/drivers/iio/gyro/st_gyro_core.c
--- linux-libre-4.6-gnu/drivers/iio/gyro/st_gyro_core.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/gyro/st_gyro_core.c	2016-07-24 15:23:50.000000000 -0400
@@ -190,6 +190,7 @@ static const struct st_sensor_settings s
 			 * drain settings, but only for INT1 and not
 			 * for the DRDY line on INT2.
 			 */
+			.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
 		},
 		.multi_read_bit = ST_GYRO_1_MULTIREAD_BIT,
 		.bootime = 2,
@@ -203,6 +204,7 @@ static const struct st_sensor_settings s
 			[2] = LSM330DLC_GYRO_DEV_NAME,
 			[3] = L3G4IS_GYRO_DEV_NAME,
 			[4] = LSM330_GYRO_DEV_NAME,
+			[5] = LSM9DS0_GYRO_DEV_NAME,
 		},
 		.ch = (struct iio_chan_spec *)st_gyro_16bit_channels,
 		.odr = {
@@ -258,6 +260,7 @@ static const struct st_sensor_settings s
 			 * drain settings, but only for INT1 and not
 			 * for the DRDY line on INT2.
 			 */
+			.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
 		},
 		.multi_read_bit = ST_GYRO_2_MULTIREAD_BIT,
 		.bootime = 2,
@@ -322,6 +325,7 @@ static const struct st_sensor_settings s
 			 * drain settings, but only for INT1 and not
 			 * for the DRDY line on INT2.
 			 */
+			.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
 		},
 		.multi_read_bit = ST_GYRO_3_MULTIREAD_BIT,
 		.bootime = 2,
@@ -405,6 +409,7 @@ static const struct iio_info gyro_info =
 static const struct iio_trigger_ops st_gyro_trigger_ops = {
 	.owner = THIS_MODULE,
 	.set_trigger_state = ST_GYRO_TRIGGER_SET_STATE,
+	.validate_device = st_sensors_validate_device,
 };
 #define ST_GYRO_TRIGGER_OPS (&st_gyro_trigger_ops)
 #else
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/gyro/st_gyro.h linux-libre-4.7-gnu/drivers/iio/gyro/st_gyro.h
--- linux-libre-4.6-gnu/drivers/iio/gyro/st_gyro.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/gyro/st_gyro.h	2016-07-24 15:23:50.000000000 -0400
@@ -21,6 +21,7 @@
 #define L3GD20_GYRO_DEV_NAME		"l3gd20"
 #define L3G4IS_GYRO_DEV_NAME		"l3g4is_ui"
 #define LSM330_GYRO_DEV_NAME		"lsm330_gyro"
+#define LSM9DS0_GYRO_DEV_NAME		"lsm9ds0_gyro"
 
 /**
  * struct st_sensors_platform_data - gyro platform data
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/gyro/st_gyro_i2c.c linux-libre-4.7-gnu/drivers/iio/gyro/st_gyro_i2c.c
--- linux-libre-4.6-gnu/drivers/iio/gyro/st_gyro_i2c.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/gyro/st_gyro_i2c.c	2016-07-24 15:23:50.000000000 -0400
@@ -48,6 +48,10 @@ static const struct of_device_id st_gyro
 		.compatible = "st,lsm330-gyro",
 		.data = LSM330_GYRO_DEV_NAME,
 	},
+	{
+		.compatible = "st,lsm9ds0-gyro",
+		.data = LSM9DS0_GYRO_DEV_NAME,
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(of, st_gyro_of_match);
@@ -93,6 +97,7 @@ static const struct i2c_device_id st_gyr
 	{ L3GD20_GYRO_DEV_NAME },
 	{ L3G4IS_GYRO_DEV_NAME },
 	{ LSM330_GYRO_DEV_NAME },
+	{ LSM9DS0_GYRO_DEV_NAME },
 	{},
 };
 MODULE_DEVICE_TABLE(i2c, st_gyro_id_table);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/gyro/st_gyro_spi.c linux-libre-4.7-gnu/drivers/iio/gyro/st_gyro_spi.c
--- linux-libre-4.6-gnu/drivers/iio/gyro/st_gyro_spi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/gyro/st_gyro_spi.c	2016-07-24 15:23:50.000000000 -0400
@@ -54,6 +54,7 @@ static const struct spi_device_id st_gyr
 	{ L3GD20_GYRO_DEV_NAME },
 	{ L3G4IS_GYRO_DEV_NAME },
 	{ LSM330_GYRO_DEV_NAME },
+	{ LSM9DS0_GYRO_DEV_NAME },
 	{},
 };
 MODULE_DEVICE_TABLE(spi, st_gyro_id_table);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/humidity/am2315.c linux-libre-4.7-gnu/drivers/iio/humidity/am2315.c
--- linux-libre-4.6-gnu/drivers/iio/humidity/am2315.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/iio/humidity/am2315.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,301 @@
+/**
+ * Aosong AM2315 relative humidity and temperature
+ *
+ * Copyright (c) 2016, Intel Corporation.
+ *
+ * This file is subject to the terms and conditions of version 2 of
+ * the GNU General Public License. See the file COPYING in the main
+ * directory of this archive for more details.
+ *
+ * 7-bit I2C address: 0x5C.
+ */
+
+#include <linux/acpi.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+
+#define AM2315_REG_HUM_MSB			0x00
+#define AM2315_REG_HUM_LSB			0x01
+#define AM2315_REG_TEMP_MSB			0x02
+#define AM2315_REG_TEMP_LSB			0x03
+
+#define AM2315_FUNCTION_READ			0x03
+#define AM2315_HUM_OFFSET			2
+#define AM2315_TEMP_OFFSET			4
+#define AM2315_ALL_CHANNEL_MASK			GENMASK(1, 0)
+
+#define AM2315_DRIVER_NAME			"am2315"
+
+struct am2315_data {
+	struct i2c_client *client;
+	struct mutex lock;
+	s16 buffer[8]; /* 2x16-bit channels + 2x16 padding + 4x16 timestamp */
+};
+
+struct am2315_sensor_data {
+	s16 hum_data;
+	s16 temp_data;
+};
+
+static const struct iio_chan_spec am2315_channels[] = {
+	{
+		.type = IIO_HUMIDITYRELATIVE,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+				      BIT(IIO_CHAN_INFO_SCALE),
+		.scan_index = 0,
+		.scan_type = {
+			.sign = 's',
+			.realbits = 16,
+			.storagebits = 16,
+			.endianness = IIO_CPU,
+		},
+	},
+	{
+		.type = IIO_TEMP,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+				      BIT(IIO_CHAN_INFO_SCALE),
+		.scan_index = 1,
+		.scan_type = {
+			.sign = 's',
+			.realbits = 16,
+			.storagebits = 16,
+			.endianness = IIO_CPU,
+		},
+	},
+	IIO_CHAN_SOFT_TIMESTAMP(2),
+};
+
+/* CRC calculation algorithm, as specified in the datasheet (page 13). */
+static u16 am2315_crc(u8 *data, u8 nr_bytes)
+{
+	int i;
+	u16 crc = 0xffff;
+
+	while (nr_bytes--) {
+		crc ^= *data++;
+		for (i = 0; i < 8; i++) {
+			if (crc & 0x01) {
+				crc >>= 1;
+				crc ^= 0xA001;
+			} else {
+				crc >>= 1;
+			}
+		}
+	}
+
+	return crc;
+}
+
+/* Simple function that sends a few bytes to the device to wake it up. */
+static void am2315_ping(struct i2c_client *client)
+{
+	i2c_smbus_read_byte_data(client, AM2315_REG_HUM_MSB);
+}
+
+static int am2315_read_data(struct am2315_data *data,
+			    struct am2315_sensor_data *sensor_data)
+{
+	int ret;
+	/* tx_buf format: <function code> <start addr> <nr of regs to read> */
+	u8 tx_buf[3] = { AM2315_FUNCTION_READ, AM2315_REG_HUM_MSB, 4 };
+	/*
+	 * rx_buf format:
+	 * <function code> <number of registers read>
+	 * <humidity MSB> <humidity LSB> <temp MSB> <temp LSB>
+	 * <CRC LSB> <CRC MSB>
+	 */
+	u8 rx_buf[8];
+	u16 crc;
+
+	/* First wake up the device. */
+	am2315_ping(data->client);
+
+	mutex_lock(&data->lock);
+	ret = i2c_master_send(data->client, tx_buf, sizeof(tx_buf));
+	if (ret < 0) {
+		dev_err(&data->client->dev, "failed to send read request\n");
+		goto exit_unlock;
+	}
+	/* Wait 2-3 ms, then read back the data sent by the device. */
+	usleep_range(2000, 3000);
+	/* Do a bulk data read, then pick out what we need. */
+	ret = i2c_master_recv(data->client, rx_buf, sizeof(rx_buf));
+	if (ret < 0) {
+		dev_err(&data->client->dev, "failed to read sensor data\n");
+		goto exit_unlock;
+	}
+	mutex_unlock(&data->lock);
+	/*
+	 * Do a CRC check on the data and compare it to the value
+	 * calculated by the device.
+	 */
+	crc = am2315_crc(rx_buf, sizeof(rx_buf) - 2);
+	if ((crc & 0xff) != rx_buf[6] || (crc >> 8) != rx_buf[7]) {
+		dev_err(&data->client->dev, "failed to verify sensor data\n");
+		return -EIO;
+	}
+
+	sensor_data->hum_data = (rx_buf[AM2315_HUM_OFFSET] << 8) |
+				 rx_buf[AM2315_HUM_OFFSET + 1];
+	sensor_data->temp_data = (rx_buf[AM2315_TEMP_OFFSET] << 8) |
+				  rx_buf[AM2315_TEMP_OFFSET + 1];
+
+	return ret;
+
+exit_unlock:
+	mutex_unlock(&data->lock);
+	return ret;
+}
+
+static irqreturn_t am2315_trigger_handler(int irq, void *p)
+{
+	int i;
+	int ret;
+	int bit;
+	struct iio_poll_func *pf = p;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct am2315_data *data = iio_priv(indio_dev);
+	struct am2315_sensor_data sensor_data;
+
+	ret = am2315_read_data(data, &sensor_data);
+	if (ret < 0)
+		goto err;
+
+	mutex_lock(&data->lock);
+	if (*(indio_dev->active_scan_mask) == AM2315_ALL_CHANNEL_MASK) {
+		data->buffer[0] = sensor_data.hum_data;
+		data->buffer[1] = sensor_data.temp_data;
+	} else {
+		i = 0;
+		for_each_set_bit(bit, indio_dev->active_scan_mask,
+				 indio_dev->masklength) {
+			data->buffer[i] = (bit ? sensor_data.temp_data :
+						 sensor_data.hum_data);
+			i++;
+		}
+	}
+	mutex_unlock(&data->lock);
+
+	iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
+					   pf->timestamp);
+err:
+	iio_trigger_notify_done(indio_dev->trig);
+	return IRQ_HANDLED;
+}
+
+static int am2315_read_raw(struct iio_dev *indio_dev,
+			   struct iio_chan_spec const *chan,
+			   int *val, int *val2, long mask)
+{
+	int ret;
+	struct am2315_sensor_data sensor_data;
+	struct am2315_data *data = iio_priv(indio_dev);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		ret = am2315_read_data(data, &sensor_data);
+		if (ret < 0)
+			return ret;
+		*val = (chan->type == IIO_HUMIDITYRELATIVE) ?
+				sensor_data.hum_data : sensor_data.temp_data;
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_SCALE:
+		*val = 100;
+		return IIO_VAL_INT;
+	}
+
+	return -EINVAL;
+}
+
+static const struct iio_info am2315_info = {
+	.driver_module		= THIS_MODULE,
+	.read_raw		= am2315_read_raw,
+};
+
+static int am2315_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	int ret;
+	struct iio_dev *indio_dev;
+	struct am2315_data *data;
+
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+	if (!indio_dev) {
+		dev_err(&client->dev, "iio allocation failed!\n");
+		return -ENOMEM;
+	}
+
+	data = iio_priv(indio_dev);
+	data->client = client;
+	i2c_set_clientdata(client, indio_dev);
+	mutex_init(&data->lock);
+
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->info = &am2315_info;
+	indio_dev->name = AM2315_DRIVER_NAME;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = am2315_channels;
+	indio_dev->num_channels = ARRAY_SIZE(am2315_channels);
+
+	ret = iio_triggered_buffer_setup(indio_dev, NULL,
+					 am2315_trigger_handler, NULL);
+	if (ret < 0) {
+		dev_err(&client->dev, "iio triggered buffer setup failed\n");
+		return ret;
+	}
+
+	ret = iio_device_register(indio_dev);
+	if (ret < 0)
+		goto err_buffer_cleanup;
+
+	return 0;
+
+err_buffer_cleanup:
+	iio_triggered_buffer_cleanup(indio_dev);
+	return ret;
+}
+
+static int am2315_remove(struct i2c_client *client)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+
+	iio_device_unregister(indio_dev);
+	iio_triggered_buffer_cleanup(indio_dev);
+
+	return 0;
+}
+
+static const struct i2c_device_id am2315_i2c_id[] = {
+	{"am2315", 0},
+	{}
+};
+
+static const struct acpi_device_id am2315_acpi_id[] = {
+	{"AOS2315", 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(acpi, am2315_acpi_id);
+
+static struct i2c_driver am2315_driver = {
+	.driver = {
+		.name = "am2315",
+		.acpi_match_table = ACPI_PTR(am2315_acpi_id),
+	},
+	.probe =            am2315_probe,
+	.remove =	    am2315_remove,
+	.id_table =         am2315_i2c_id,
+};
+
+module_i2c_driver(am2315_driver);
+
+MODULE_AUTHOR("Tiberiu Breana <tiberiu.a.breana@intel.com>");
+MODULE_DESCRIPTION("Aosong AM2315 relative humidity and temperature");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/humidity/dht11.c linux-libre-4.7-gnu/drivers/iio/humidity/dht11.c
--- linux-libre-4.6-gnu/drivers/iio/humidity/dht11.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/humidity/dht11.c	2016-07-24 15:23:50.000000000 -0400
@@ -96,6 +96,24 @@ struct dht11 {
 	struct {s64 ts; int value; }	edges[DHT11_EDGES_PER_READ];
 };
 
+#ifdef CONFIG_DYNAMIC_DEBUG
+/*
+ * dht11_edges_print: show the data as actually received by the
+ *                    driver.
+ */
+static void dht11_edges_print(struct dht11 *dht11)
+{
+	int i;
+
+	dev_dbg(dht11->dev, "%d edges detected:\n", dht11->num_edges);
+	for (i = 1; i < dht11->num_edges; ++i) {
+		dev_dbg(dht11->dev, "%d: %lld ns %s\n", i,
+			dht11->edges[i].ts - dht11->edges[i - 1].ts,
+			dht11->edges[i - 1].value ? "high" : "low");
+	}
+}
+#endif /* CONFIG_DYNAMIC_DEBUG */
+
 static unsigned char dht11_decode_byte(char *bits)
 {
 	unsigned char ret = 0;
@@ -119,8 +137,12 @@ static int dht11_decode(struct dht11 *dh
 	for (i = 0; i < DHT11_BITS_PER_READ; ++i) {
 		t = dht11->edges[offset + 2 * i + 2].ts -
 			dht11->edges[offset + 2 * i + 1].ts;
-		if (!dht11->edges[offset + 2 * i + 1].value)
-			return -EIO;  /* lost synchronisation */
+		if (!dht11->edges[offset + 2 * i + 1].value) {
+			dev_dbg(dht11->dev,
+				"lost synchronisation at edge %d\n",
+				offset + 2 * i + 1);
+			return -EIO;
+		}
 		bits[i] = t > DHT11_THRESHOLD;
 	}
 
@@ -130,8 +152,10 @@ static int dht11_decode(struct dht11 *dh
 	temp_dec = dht11_decode_byte(&bits[24]);
 	checksum = dht11_decode_byte(&bits[32]);
 
-	if (((hum_int + hum_dec + temp_int + temp_dec) & 0xff) != checksum)
+	if (((hum_int + hum_dec + temp_int + temp_dec) & 0xff) != checksum) {
+		dev_dbg(dht11->dev, "invalid checksum\n");
 		return -EIO;
+	}
 
 	dht11->timestamp = ktime_get_boot_ns();
 	if (hum_int < 20) {  /* DHT22 */
@@ -182,6 +206,7 @@ static int dht11_read_raw(struct iio_dev
 	mutex_lock(&dht11->lock);
 	if (dht11->timestamp + DHT11_DATA_VALID_TIME < ktime_get_boot_ns()) {
 		timeres = ktime_get_resolution_ns();
+		dev_dbg(dht11->dev, "current timeresolution: %dns\n", timeres);
 		if (timeres > DHT11_MIN_TIMERES) {
 			dev_err(dht11->dev, "timeresolution %dns too low\n",
 				timeres);
@@ -219,10 +244,13 @@ static int dht11_read_raw(struct iio_dev
 
 		free_irq(dht11->irq, iio_dev);
 
+#ifdef CONFIG_DYNAMIC_DEBUG
+		dht11_edges_print(dht11);
+#endif
+
 		if (ret == 0 && dht11->num_edges < DHT11_EDGES_PER_READ - 1) {
-			dev_err(&iio_dev->dev,
-				"Only %d signal edges detected\n",
-					dht11->num_edges);
+			dev_err(dht11->dev, "Only %d signal edges detected\n",
+				dht11->num_edges);
 			ret = -ETIMEDOUT;
 		}
 		if (ret < 0)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/humidity/hdc100x.c linux-libre-4.7-gnu/drivers/iio/humidity/hdc100x.c
--- linux-libre-4.6-gnu/drivers/iio/humidity/hdc100x.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/humidity/hdc100x.c	2016-07-24 15:23:50.000000000 -0400
@@ -55,7 +55,7 @@ static const struct {
 	},
 	{ /* IIO_HUMIDITYRELATIVE channel */
 		.shift = 8,
-		.mask = 2,
+		.mask = 3,
 	},
 };
 
@@ -164,14 +164,14 @@ static int hdc100x_get_measurement(struc
 		dev_err(&client->dev, "cannot read high byte measurement");
 		return ret;
 	}
-	val = ret << 6;
+	val = ret << 8;
 
 	ret = i2c_smbus_read_byte(client);
 	if (ret < 0) {
 		dev_err(&client->dev, "cannot read low byte measurement");
 		return ret;
 	}
-	val |= ret >> 2;
+	val |= ret;
 
 	return val;
 }
@@ -211,18 +211,18 @@ static int hdc100x_read_raw(struct iio_d
 		return IIO_VAL_INT_PLUS_MICRO;
 	case IIO_CHAN_INFO_SCALE:
 		if (chan->type == IIO_TEMP) {
-			*val = 165;
-			*val2 = 65536 >> 2;
+			*val = 165000;
+			*val2 = 65536;
 			return IIO_VAL_FRACTIONAL;
 		} else {
-			*val = 0;
-			*val2 = 10000;
-			return IIO_VAL_INT_PLUS_MICRO;
+			*val = 100;
+			*val2 = 65536;
+			return IIO_VAL_FRACTIONAL;
 		}
 		break;
 	case IIO_CHAN_INFO_OFFSET:
-		*val = -3971;
-		*val2 = 879096;
+		*val = -15887;
+		*val2 = 515151;
 		return IIO_VAL_INT_PLUS_MICRO;
 	default:
 		return -EINVAL;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/humidity/Kconfig linux-libre-4.7-gnu/drivers/iio/humidity/Kconfig
--- linux-libre-4.6-gnu/drivers/iio/humidity/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/humidity/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -3,6 +3,16 @@
 #
 menu "Humidity sensors"
 
+config AM2315
+    tristate "Aosong AM2315 relative humidity and temperature sensor"
+    depends on I2C
+    help
+      If you say yes here you get support for the Aosong AM2315
+      relative humidity and ambient temperature sensor.
+
+      This driver can also be built as a module. If so, the module will
+      be called am2315.
+
 config DHT11
 	tristate "DHT11 (and compatible sensors) driver"
 	depends on GPIOLIB || COMPILE_TEST
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/humidity/Makefile linux-libre-4.7-gnu/drivers/iio/humidity/Makefile
--- linux-libre-4.6-gnu/drivers/iio/humidity/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/humidity/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -2,6 +2,7 @@
 # Makefile for IIO humidity sensor drivers
 #
 
+obj-$(CONFIG_AM2315) += am2315.o
 obj-$(CONFIG_DHT11) += dht11.o
 obj-$(CONFIG_HDC100X) += hdc100x.o
 obj-$(CONFIG_HTU21) += htu21.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/imu/adis.c linux-libre-4.7-gnu/drivers/iio/imu/adis.c
--- linux-libre-4.6-gnu/drivers/iio/imu/adis.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/imu/adis.c	2016-07-24 15:23:50.000000000 -0400
@@ -324,7 +324,12 @@ static int adis_self_test(struct adis *a
 
 	msleep(adis->data->startup_delay);
 
-	return adis_check_status(adis);
+	ret = adis_check_status(adis);
+
+	if (adis->data->self_test_no_autoclear)
+		adis_write_reg_16(adis, adis->data->msc_ctrl_reg, 0x00);
+
+	return ret;
 }
 
 /**
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/imu/bmi160/bmi160_core.c linux-libre-4.7-gnu/drivers/iio/imu/bmi160/bmi160_core.c
--- linux-libre-4.6-gnu/drivers/iio/imu/bmi160/bmi160_core.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/iio/imu/bmi160/bmi160_core.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,596 @@
+/*
+ * BMI160 - Bosch IMU (accel, gyro plus external magnetometer)
+ *
+ * Copyright (c) 2016, Intel Corporation.
+ *
+ * This file is subject to the terms and conditions of version 2 of
+ * the GNU General Public License.  See the file COPYING in the main
+ * directory of this archive for more details.
+ *
+ * IIO core driver for BMI160, with support for I2C/SPI busses
+ *
+ * TODO: magnetometer, interrupts, hardware FIFO
+ */
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/acpi.h>
+#include <linux/delay.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/buffer.h>
+
+#include "bmi160.h"
+
+#define BMI160_REG_CHIP_ID	0x00
+#define BMI160_CHIP_ID_VAL	0xD1
+
+#define BMI160_REG_PMU_STATUS	0x03
+
+/* X axis data low byte address, the rest can be obtained using axis offset */
+#define BMI160_REG_DATA_MAGN_XOUT_L	0x04
+#define BMI160_REG_DATA_GYRO_XOUT_L	0x0C
+#define BMI160_REG_DATA_ACCEL_XOUT_L	0x12
+
+#define BMI160_REG_ACCEL_CONFIG		0x40
+#define BMI160_ACCEL_CONFIG_ODR_MASK	GENMASK(3, 0)
+#define BMI160_ACCEL_CONFIG_BWP_MASK	GENMASK(6, 4)
+
+#define BMI160_REG_ACCEL_RANGE		0x41
+#define BMI160_ACCEL_RANGE_2G		0x03
+#define BMI160_ACCEL_RANGE_4G		0x05
+#define BMI160_ACCEL_RANGE_8G		0x08
+#define BMI160_ACCEL_RANGE_16G		0x0C
+
+#define BMI160_REG_GYRO_CONFIG		0x42
+#define BMI160_GYRO_CONFIG_ODR_MASK	GENMASK(3, 0)
+#define BMI160_GYRO_CONFIG_BWP_MASK	GENMASK(5, 4)
+
+#define BMI160_REG_GYRO_RANGE		0x43
+#define BMI160_GYRO_RANGE_2000DPS	0x00
+#define BMI160_GYRO_RANGE_1000DPS	0x01
+#define BMI160_GYRO_RANGE_500DPS	0x02
+#define BMI160_GYRO_RANGE_250DPS	0x03
+#define BMI160_GYRO_RANGE_125DPS	0x04
+
+#define BMI160_REG_CMD			0x7E
+#define BMI160_CMD_ACCEL_PM_SUSPEND	0x10
+#define BMI160_CMD_ACCEL_PM_NORMAL	0x11
+#define BMI160_CMD_ACCEL_PM_LOW_POWER	0x12
+#define BMI160_CMD_GYRO_PM_SUSPEND	0x14
+#define BMI160_CMD_GYRO_PM_NORMAL	0x15
+#define BMI160_CMD_GYRO_PM_FAST_STARTUP	0x17
+#define BMI160_CMD_SOFTRESET		0xB6
+
+#define BMI160_REG_DUMMY		0x7F
+
+#define BMI160_ACCEL_PMU_MIN_USLEEP	3200
+#define BMI160_ACCEL_PMU_MAX_USLEEP	3800
+#define BMI160_GYRO_PMU_MIN_USLEEP	55000
+#define BMI160_GYRO_PMU_MAX_USLEEP	80000
+#define BMI160_SOFTRESET_USLEEP		1000
+
+#define BMI160_CHANNEL(_type, _axis, _index) {			\
+	.type = _type,						\
+	.modified = 1,						\
+	.channel2 = IIO_MOD_##_axis,				\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |  \
+		BIT(IIO_CHAN_INFO_SAMP_FREQ),			\
+	.scan_index = _index,					\
+	.scan_type = {						\
+		.sign = 's',					\
+		.realbits = 16,					\
+		.storagebits = 16,				\
+		.endianness = IIO_LE,				\
+	},							\
+}
+
+/* scan indexes follow DATA register order */
+enum bmi160_scan_axis {
+	BMI160_SCAN_EXT_MAGN_X = 0,
+	BMI160_SCAN_EXT_MAGN_Y,
+	BMI160_SCAN_EXT_MAGN_Z,
+	BMI160_SCAN_RHALL,
+	BMI160_SCAN_GYRO_X,
+	BMI160_SCAN_GYRO_Y,
+	BMI160_SCAN_GYRO_Z,
+	BMI160_SCAN_ACCEL_X,
+	BMI160_SCAN_ACCEL_Y,
+	BMI160_SCAN_ACCEL_Z,
+	BMI160_SCAN_TIMESTAMP,
+};
+
+enum bmi160_sensor_type {
+	BMI160_ACCEL	= 0,
+	BMI160_GYRO,
+	BMI160_EXT_MAGN,
+	BMI160_NUM_SENSORS /* must be last */
+};
+
+struct bmi160_data {
+	struct regmap *regmap;
+};
+
+const struct regmap_config bmi160_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+};
+EXPORT_SYMBOL(bmi160_regmap_config);
+
+struct bmi160_regs {
+	u8 data; /* LSB byte register for X-axis */
+	u8 config;
+	u8 config_odr_mask;
+	u8 config_bwp_mask;
+	u8 range;
+	u8 pmu_cmd_normal;
+	u8 pmu_cmd_suspend;
+};
+
+static struct bmi160_regs bmi160_regs[] = {
+	[BMI160_ACCEL] = {
+		.data	= BMI160_REG_DATA_ACCEL_XOUT_L,
+		.config	= BMI160_REG_ACCEL_CONFIG,
+		.config_odr_mask = BMI160_ACCEL_CONFIG_ODR_MASK,
+		.config_bwp_mask = BMI160_ACCEL_CONFIG_BWP_MASK,
+		.range	= BMI160_REG_ACCEL_RANGE,
+		.pmu_cmd_normal = BMI160_CMD_ACCEL_PM_NORMAL,
+		.pmu_cmd_suspend = BMI160_CMD_ACCEL_PM_SUSPEND,
+	},
+	[BMI160_GYRO] = {
+		.data	= BMI160_REG_DATA_GYRO_XOUT_L,
+		.config	= BMI160_REG_GYRO_CONFIG,
+		.config_odr_mask = BMI160_GYRO_CONFIG_ODR_MASK,
+		.config_bwp_mask = BMI160_GYRO_CONFIG_BWP_MASK,
+		.range	= BMI160_REG_GYRO_RANGE,
+		.pmu_cmd_normal = BMI160_CMD_GYRO_PM_NORMAL,
+		.pmu_cmd_suspend = BMI160_CMD_GYRO_PM_SUSPEND,
+	},
+};
+
+struct bmi160_pmu_time {
+	unsigned long min;
+	unsigned long max;
+};
+
+static struct bmi160_pmu_time bmi160_pmu_time[] = {
+	[BMI160_ACCEL] = {
+		.min = BMI160_ACCEL_PMU_MIN_USLEEP,
+		.max = BMI160_ACCEL_PMU_MAX_USLEEP
+	},
+	[BMI160_GYRO] = {
+		.min = BMI160_GYRO_PMU_MIN_USLEEP,
+		.max = BMI160_GYRO_PMU_MIN_USLEEP,
+	},
+};
+
+struct bmi160_scale {
+	u8 bits;
+	int uscale;
+};
+
+struct bmi160_odr {
+	u8 bits;
+	int odr;
+	int uodr;
+};
+
+static const struct bmi160_scale bmi160_accel_scale[] = {
+	{ BMI160_ACCEL_RANGE_2G, 598},
+	{ BMI160_ACCEL_RANGE_4G, 1197},
+	{ BMI160_ACCEL_RANGE_8G, 2394},
+	{ BMI160_ACCEL_RANGE_16G, 4788},
+};
+
+static const struct bmi160_scale bmi160_gyro_scale[] = {
+	{ BMI160_GYRO_RANGE_2000DPS, 1065},
+	{ BMI160_GYRO_RANGE_1000DPS, 532},
+	{ BMI160_GYRO_RANGE_500DPS, 266},
+	{ BMI160_GYRO_RANGE_250DPS, 133},
+	{ BMI160_GYRO_RANGE_125DPS, 66},
+};
+
+struct bmi160_scale_item {
+	const struct bmi160_scale *tbl;
+	int num;
+};
+
+static const struct  bmi160_scale_item bmi160_scale_table[] = {
+	[BMI160_ACCEL] = {
+		.tbl	= bmi160_accel_scale,
+		.num	= ARRAY_SIZE(bmi160_accel_scale),
+	},
+	[BMI160_GYRO] = {
+		.tbl	= bmi160_gyro_scale,
+		.num	= ARRAY_SIZE(bmi160_gyro_scale),
+	},
+};
+
+static const struct bmi160_odr bmi160_accel_odr[] = {
+	{0x01, 0, 781250},
+	{0x02, 1, 562500},
+	{0x03, 3, 125000},
+	{0x04, 6, 250000},
+	{0x05, 12, 500000},
+	{0x06, 25, 0},
+	{0x07, 50, 0},
+	{0x08, 100, 0},
+	{0x09, 200, 0},
+	{0x0A, 400, 0},
+	{0x0B, 800, 0},
+	{0x0C, 1600, 0},
+};
+
+static const struct bmi160_odr bmi160_gyro_odr[] = {
+	{0x06, 25, 0},
+	{0x07, 50, 0},
+	{0x08, 100, 0},
+	{0x09, 200, 0},
+	{0x0A, 400, 0},
+	{0x0B, 800, 0},
+	{0x0C, 1600, 0},
+	{0x0D, 3200, 0},
+};
+
+struct bmi160_odr_item {
+	const struct bmi160_odr *tbl;
+	int num;
+};
+
+static const struct  bmi160_odr_item bmi160_odr_table[] = {
+	[BMI160_ACCEL] = {
+		.tbl	= bmi160_accel_odr,
+		.num	= ARRAY_SIZE(bmi160_accel_odr),
+	},
+	[BMI160_GYRO] = {
+		.tbl	= bmi160_gyro_odr,
+		.num	= ARRAY_SIZE(bmi160_gyro_odr),
+	},
+};
+
+static const struct iio_chan_spec bmi160_channels[] = {
+	BMI160_CHANNEL(IIO_ACCEL, X, BMI160_SCAN_ACCEL_X),
+	BMI160_CHANNEL(IIO_ACCEL, Y, BMI160_SCAN_ACCEL_Y),
+	BMI160_CHANNEL(IIO_ACCEL, Z, BMI160_SCAN_ACCEL_Z),
+	BMI160_CHANNEL(IIO_ANGL_VEL, X, BMI160_SCAN_GYRO_X),
+	BMI160_CHANNEL(IIO_ANGL_VEL, Y, BMI160_SCAN_GYRO_Y),
+	BMI160_CHANNEL(IIO_ANGL_VEL, Z, BMI160_SCAN_GYRO_Z),
+	IIO_CHAN_SOFT_TIMESTAMP(BMI160_SCAN_TIMESTAMP),
+};
+
+static enum bmi160_sensor_type bmi160_to_sensor(enum iio_chan_type iio_type)
+{
+	switch (iio_type) {
+	case IIO_ACCEL:
+		return BMI160_ACCEL;
+	case IIO_ANGL_VEL:
+		return BMI160_GYRO;
+	default:
+		return -EINVAL;
+	}
+}
+
+static
+int bmi160_set_mode(struct bmi160_data *data, enum bmi160_sensor_type t,
+		    bool mode)
+{
+	int ret;
+	u8 cmd;
+
+	if (mode)
+		cmd = bmi160_regs[t].pmu_cmd_normal;
+	else
+		cmd = bmi160_regs[t].pmu_cmd_suspend;
+
+	ret = regmap_write(data->regmap, BMI160_REG_CMD, cmd);
+	if (ret < 0)
+		return ret;
+
+	usleep_range(bmi160_pmu_time[t].min, bmi160_pmu_time[t].max);
+
+	return 0;
+}
+
+static
+int bmi160_set_scale(struct bmi160_data *data, enum bmi160_sensor_type t,
+		     int uscale)
+{
+	int i;
+
+	for (i = 0; i < bmi160_scale_table[t].num; i++)
+		if (bmi160_scale_table[t].tbl[i].uscale == uscale)
+			break;
+
+	if (i == bmi160_scale_table[t].num)
+		return -EINVAL;
+
+	return regmap_write(data->regmap, bmi160_regs[t].range,
+			    bmi160_scale_table[t].tbl[i].bits);
+}
+
+static
+int bmi160_get_scale(struct bmi160_data *data, enum bmi160_sensor_type t,
+		     int *uscale)
+{
+	int i, ret, val;
+
+	ret = regmap_read(data->regmap, bmi160_regs[t].range, &val);
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < bmi160_scale_table[t].num; i++)
+		if (bmi160_scale_table[t].tbl[i].bits == val) {
+			*uscale = bmi160_scale_table[t].tbl[i].uscale;
+			return 0;
+		}
+
+	return -EINVAL;
+}
+
+static int bmi160_get_data(struct bmi160_data *data, int chan_type,
+			   int axis, int *val)
+{
+	u8 reg;
+	int ret;
+	__le16 sample;
+	enum bmi160_sensor_type t = bmi160_to_sensor(chan_type);
+
+	reg = bmi160_regs[t].data + (axis - IIO_MOD_X) * sizeof(__le16);
+
+	ret = regmap_bulk_read(data->regmap, reg, &sample, sizeof(__le16));
+	if (ret < 0)
+		return ret;
+
+	*val = sign_extend32(le16_to_cpu(sample), 15);
+
+	return 0;
+}
+
+static
+int bmi160_set_odr(struct bmi160_data *data, enum bmi160_sensor_type t,
+		   int odr, int uodr)
+{
+	int i;
+
+	for (i = 0; i < bmi160_odr_table[t].num; i++)
+		if (bmi160_odr_table[t].tbl[i].odr == odr &&
+		    bmi160_odr_table[t].tbl[i].uodr == uodr)
+			break;
+
+	if (i >= bmi160_odr_table[t].num)
+		return -EINVAL;
+
+	return regmap_update_bits(data->regmap,
+				  bmi160_regs[t].config,
+				  bmi160_regs[t].config_odr_mask,
+				  bmi160_odr_table[t].tbl[i].bits);
+}
+
+static int bmi160_get_odr(struct bmi160_data *data, enum bmi160_sensor_type t,
+			  int *odr, int *uodr)
+{
+	int i, val, ret;
+
+	ret = regmap_read(data->regmap, bmi160_regs[t].config, &val);
+	if (ret < 0)
+		return ret;
+
+	val &= bmi160_regs[t].config_odr_mask;
+
+	for (i = 0; i < bmi160_odr_table[t].num; i++)
+		if (val == bmi160_odr_table[t].tbl[i].bits)
+			break;
+
+	if (i >= bmi160_odr_table[t].num)
+		return -EINVAL;
+
+	*odr = bmi160_odr_table[t].tbl[i].odr;
+	*uodr = bmi160_odr_table[t].tbl[i].uodr;
+
+	return 0;
+}
+
+static irqreturn_t bmi160_trigger_handler(int irq, void *p)
+{
+	struct iio_poll_func *pf = p;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct bmi160_data *data = iio_priv(indio_dev);
+	s16 buf[16]; /* 3 sens x 3 axis x s16 + 3 x s16 pad + 4 x s16 tstamp */
+	int i, ret, j = 0, base = BMI160_REG_DATA_MAGN_XOUT_L;
+	__le16 sample;
+
+	for_each_set_bit(i, indio_dev->active_scan_mask,
+			 indio_dev->masklength) {
+		ret = regmap_bulk_read(data->regmap, base + i * sizeof(__le16),
+				       &sample, sizeof(__le16));
+		if (ret < 0)
+			goto done;
+		buf[j++] = sample;
+	}
+
+	iio_push_to_buffers_with_timestamp(indio_dev, buf, iio_get_time_ns());
+done:
+	iio_trigger_notify_done(indio_dev->trig);
+	return IRQ_HANDLED;
+}
+
+static int bmi160_read_raw(struct iio_dev *indio_dev,
+			   struct iio_chan_spec const *chan,
+			   int *val, int *val2, long mask)
+{
+	int ret;
+	struct bmi160_data *data = iio_priv(indio_dev);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		ret = bmi160_get_data(data, chan->type, chan->channel2, val);
+		if (ret < 0)
+			return ret;
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_SCALE:
+		*val = 0;
+		ret = bmi160_get_scale(data,
+				       bmi160_to_sensor(chan->type), val2);
+		return ret < 0 ? ret : IIO_VAL_INT_PLUS_MICRO;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		ret = bmi160_get_odr(data, bmi160_to_sensor(chan->type),
+				     val, val2);
+		return ret < 0 ? ret : IIO_VAL_INT_PLUS_MICRO;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int bmi160_write_raw(struct iio_dev *indio_dev,
+			    struct iio_chan_spec const *chan,
+			    int val, int val2, long mask)
+{
+	struct bmi160_data *data = iio_priv(indio_dev);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_SCALE:
+		return bmi160_set_scale(data,
+					bmi160_to_sensor(chan->type), val2);
+		break;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		return bmi160_set_odr(data, bmi160_to_sensor(chan->type),
+				      val, val2);
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct iio_info bmi160_info = {
+	.driver_module = THIS_MODULE,
+	.read_raw = bmi160_read_raw,
+	.write_raw = bmi160_write_raw,
+};
+
+static const char *bmi160_match_acpi_device(struct device *dev)
+{
+	const struct acpi_device_id *id;
+
+	id = acpi_match_device(dev->driver->acpi_match_table, dev);
+	if (!id)
+		return NULL;
+
+	return dev_name(dev);
+}
+
+static int bmi160_chip_init(struct bmi160_data *data, bool use_spi)
+{
+	int ret;
+	unsigned int val;
+	struct device *dev = regmap_get_device(data->regmap);
+
+	ret = regmap_write(data->regmap, BMI160_REG_CMD, BMI160_CMD_SOFTRESET);
+	if (ret < 0)
+		return ret;
+
+	usleep_range(BMI160_SOFTRESET_USLEEP, BMI160_SOFTRESET_USLEEP + 1);
+
+	/*
+	 * CS rising edge is needed before starting SPI, so do a dummy read
+	 * See Section 3.2.1, page 86 of the datasheet
+	 */
+	if (use_spi) {
+		ret = regmap_read(data->regmap, BMI160_REG_DUMMY, &val);
+		if (ret < 0)
+			return ret;
+	}
+
+	ret = regmap_read(data->regmap, BMI160_REG_CHIP_ID, &val);
+	if (ret < 0) {
+		dev_err(dev, "Error reading chip id\n");
+		return ret;
+	}
+	if (val != BMI160_CHIP_ID_VAL) {
+		dev_err(dev, "Wrong chip id, got %x expected %x\n",
+			val, BMI160_CHIP_ID_VAL);
+		return -ENODEV;
+	}
+
+	ret = bmi160_set_mode(data, BMI160_ACCEL, true);
+	if (ret < 0)
+		return ret;
+
+	ret = bmi160_set_mode(data, BMI160_GYRO, true);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static void bmi160_chip_uninit(struct bmi160_data *data)
+{
+	bmi160_set_mode(data, BMI160_GYRO, false);
+	bmi160_set_mode(data, BMI160_ACCEL, false);
+}
+
+int bmi160_core_probe(struct device *dev, struct regmap *regmap,
+		      const char *name, bool use_spi)
+{
+	struct iio_dev *indio_dev;
+	struct bmi160_data *data;
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	data = iio_priv(indio_dev);
+	dev_set_drvdata(dev, indio_dev);
+	data->regmap = regmap;
+
+	ret = bmi160_chip_init(data, use_spi);
+	if (ret < 0)
+		return ret;
+
+	if (!name && ACPI_HANDLE(dev))
+		name = bmi160_match_acpi_device(dev);
+
+	indio_dev->dev.parent = dev;
+	indio_dev->channels = bmi160_channels;
+	indio_dev->num_channels = ARRAY_SIZE(bmi160_channels);
+	indio_dev->name = name;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->info = &bmi160_info;
+
+	ret = iio_triggered_buffer_setup(indio_dev, NULL,
+					 bmi160_trigger_handler, NULL);
+	if (ret < 0)
+		goto uninit;
+
+	ret = iio_device_register(indio_dev);
+	if (ret < 0)
+		goto buffer_cleanup;
+
+	return 0;
+buffer_cleanup:
+	iio_triggered_buffer_cleanup(indio_dev);
+uninit:
+	bmi160_chip_uninit(data);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(bmi160_core_probe);
+
+void bmi160_core_remove(struct device *dev)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct bmi160_data *data = iio_priv(indio_dev);
+
+	iio_device_unregister(indio_dev);
+	iio_triggered_buffer_cleanup(indio_dev);
+	bmi160_chip_uninit(data);
+}
+EXPORT_SYMBOL_GPL(bmi160_core_remove);
+
+MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com");
+MODULE_DESCRIPTION("Bosch BMI160 driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/imu/bmi160/bmi160.h linux-libre-4.7-gnu/drivers/iio/imu/bmi160/bmi160.h
--- linux-libre-4.6-gnu/drivers/iio/imu/bmi160/bmi160.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/iio/imu/bmi160/bmi160.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,10 @@
+#ifndef BMI160_H_
+#define BMI160_H_
+
+extern const struct regmap_config bmi160_regmap_config;
+
+int bmi160_core_probe(struct device *dev, struct regmap *regmap,
+		      const char *name, bool use_spi);
+void bmi160_core_remove(struct device *dev);
+
+#endif  /* BMI160_H_ */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/imu/bmi160/bmi160_i2c.c linux-libre-4.7-gnu/drivers/iio/imu/bmi160/bmi160_i2c.c
--- linux-libre-4.6-gnu/drivers/iio/imu/bmi160/bmi160_i2c.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/iio/imu/bmi160/bmi160_i2c.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,72 @@
+/*
+ * BMI160 - Bosch IMU, I2C bits
+ *
+ * Copyright (c) 2016, Intel Corporation.
+ *
+ * This file is subject to the terms and conditions of version 2 of
+ * the GNU General Public License.  See the file COPYING in the main
+ * directory of this archive for more details.
+ *
+ * 7-bit I2C slave address is:
+ *      - 0x68 if SDO is pulled to GND
+ *      - 0x69 if SDO is pulled to VDDIO
+ */
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/acpi.h>
+
+#include "bmi160.h"
+
+static int bmi160_i2c_probe(struct i2c_client *client,
+			    const struct i2c_device_id *id)
+{
+	struct regmap *regmap;
+	const char *name = NULL;
+
+	regmap = devm_regmap_init_i2c(client, &bmi160_regmap_config);
+	if (IS_ERR(regmap)) {
+		dev_err(&client->dev, "Failed to register i2c regmap %d\n",
+			(int)PTR_ERR(regmap));
+		return PTR_ERR(regmap);
+	}
+
+	if (id)
+		name = id->name;
+
+	return bmi160_core_probe(&client->dev, regmap, name, false);
+}
+
+static int bmi160_i2c_remove(struct i2c_client *client)
+{
+	bmi160_core_remove(&client->dev);
+
+	return 0;
+}
+
+static const struct i2c_device_id bmi160_i2c_id[] = {
+	{"bmi160", 0},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, bmi160_i2c_id);
+
+static const struct acpi_device_id bmi160_acpi_match[] = {
+	{"BMI0160", 0},
+	{ },
+};
+MODULE_DEVICE_TABLE(acpi, bmi160_acpi_match);
+
+static struct i2c_driver bmi160_i2c_driver = {
+	.driver = {
+		.name			= "bmi160_i2c",
+		.acpi_match_table	= ACPI_PTR(bmi160_acpi_match),
+	},
+	.probe		= bmi160_i2c_probe,
+	.remove		= bmi160_i2c_remove,
+	.id_table	= bmi160_i2c_id,
+};
+module_i2c_driver(bmi160_i2c_driver);
+
+MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com>");
+MODULE_DESCRIPTION("BMI160 I2C driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/imu/bmi160/bmi160_spi.c linux-libre-4.7-gnu/drivers/iio/imu/bmi160/bmi160_spi.c
--- linux-libre-4.6-gnu/drivers/iio/imu/bmi160/bmi160_spi.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/iio/imu/bmi160/bmi160_spi.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,63 @@
+/*
+ * BMI160 - Bosch IMU, SPI bits
+ *
+ * Copyright (c) 2016, Intel Corporation.
+ *
+ * This file is subject to the terms and conditions of version 2 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/spi/spi.h>
+#include <linux/regmap.h>
+#include <linux/acpi.h>
+
+#include "bmi160.h"
+
+static int bmi160_spi_probe(struct spi_device *spi)
+{
+	struct regmap *regmap;
+	const struct spi_device_id *id = spi_get_device_id(spi);
+
+	regmap = devm_regmap_init_spi(spi, &bmi160_regmap_config);
+	if (IS_ERR(regmap)) {
+		dev_err(&spi->dev, "Failed to register spi regmap %d\n",
+			(int)PTR_ERR(regmap));
+		return PTR_ERR(regmap);
+	}
+	return bmi160_core_probe(&spi->dev, regmap, id->name, true);
+}
+
+static int bmi160_spi_remove(struct spi_device *spi)
+{
+	bmi160_core_remove(&spi->dev);
+
+	return 0;
+}
+
+static const struct spi_device_id bmi160_spi_id[] = {
+	{"bmi160", 0},
+	{}
+};
+MODULE_DEVICE_TABLE(spi, bmi160_spi_id);
+
+static const struct acpi_device_id bmi160_acpi_match[] = {
+	{"BMI0160", 0},
+	{ },
+};
+MODULE_DEVICE_TABLE(acpi, bmi160_acpi_match);
+
+static struct spi_driver bmi160_spi_driver = {
+	.probe		= bmi160_spi_probe,
+	.remove		= bmi160_spi_remove,
+	.id_table	= bmi160_spi_id,
+	.driver = {
+		.acpi_match_table = ACPI_PTR(bmi160_acpi_match),
+		.name	= "bmi160_spi",
+	},
+};
+module_spi_driver(bmi160_spi_driver);
+
+MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com");
+MODULE_DESCRIPTION("Bosch BMI160 SPI driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/imu/bmi160/Kconfig linux-libre-4.7-gnu/drivers/iio/imu/bmi160/Kconfig
--- linux-libre-4.6-gnu/drivers/iio/imu/bmi160/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/iio/imu/bmi160/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,32 @@
+#
+# BMI160 IMU driver
+#
+
+config BMI160
+	tristate
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
+
+config BMI160_I2C
+	tristate "Bosch BMI160 I2C driver"
+	depends on I2C
+	select BMI160
+	select REGMAP_I2C
+	help
+	  If you say yes here you get support for BMI160 IMU on I2C with
+	  accelerometer, gyroscope and external BMG160 magnetometer.
+
+	  This driver can also be built as a module. If so, the module will be
+	  called bmi160_i2c.
+
+config BMI160_SPI
+	tristate "Bosch BMI160 SPI driver"
+	depends on SPI
+	select BMI160
+	select REGMAP_SPI
+	help
+	  If you say yes here you get support for BMI160 IMU on SPI with
+	  accelerometer, gyroscope and external BMG160 magnetometer.
+
+	  This driver can also be built as a module. If so, the module will be
+	  called bmi160_spi.
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/imu/bmi160/Makefile linux-libre-4.7-gnu/drivers/iio/imu/bmi160/Makefile
--- linux-libre-4.6-gnu/drivers/iio/imu/bmi160/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/iio/imu/bmi160/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,6 @@
+#
+# Makefile for Bosch BMI160 IMU
+#
+obj-$(CONFIG_BMI160) += bmi160_core.o
+obj-$(CONFIG_BMI160_I2C) += bmi160_i2c.o
+obj-$(CONFIG_BMI160_SPI) += bmi160_spi.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c linux-libre-4.7-gnu/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
--- linux-libre-4.6-gnu/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c	2016-07-24 15:23:50.000000000 -0400
@@ -56,6 +56,7 @@ static int asus_acpi_get_sensor_info(str
 	int i;
 	acpi_status status;
 	union acpi_object *cpm;
+	int ret;
 
 	status = acpi_evaluate_object(adev->handle, "CNF0", NULL, &buffer);
 	if (ACPI_FAILURE(status))
@@ -82,10 +83,10 @@ static int asus_acpi_get_sensor_info(str
 			}
 		}
 	}
-
+	ret = cpm->package.count;
 	kfree(buffer.pointer);
 
-	return cpm->package.count;
+	return ret;
 }
 
 static int acpi_i2c_check_resource(struct acpi_resource *ares, void *data)
@@ -183,7 +184,7 @@ int inv_mpu_acpi_create_mux_client(struc
 			} else
 				return 0; /* no secondary addr, which is OK */
 		}
-		st->mux_client = i2c_new_device(st->mux_adapter, &info);
+		st->mux_client = i2c_new_device(st->muxc->adapter[0], &info);
 		if (!st->mux_client)
 			return -ENODEV;
 	}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c linux-libre-4.7-gnu/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
--- linux-libre-4.6-gnu/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c	2016-07-24 15:23:50.000000000 -0400
@@ -23,7 +23,6 @@
 #include <linux/kfifo.h>
 #include <linux/spinlock.h>
 #include <linux/iio/iio.h>
-#include <linux/i2c-mux.h>
 #include <linux/acpi.h>
 #include "inv_mpu_iio.h"
 
@@ -88,16 +87,29 @@ static const struct inv_mpu6050_chip_con
 	.accl_fs = INV_MPU6050_FS_02G,
 };
 
+/* Indexed by enum inv_devices */
 static const struct inv_mpu6050_hw hw_info[] = {
 	{
-		.num_reg = 117,
+		.whoami = INV_MPU6050_WHOAMI_VALUE,
+		.name = "MPU6050",
+		.reg = &reg_set_6050,
+		.config = &chip_config_6050,
+	},
+	{
+		.whoami = INV_MPU6500_WHOAMI_VALUE,
 		.name = "MPU6500",
 		.reg = &reg_set_6500,
 		.config = &chip_config_6050,
 	},
 	{
-		.num_reg = 117,
-		.name = "MPU6050",
+		.whoami = INV_MPU6000_WHOAMI_VALUE,
+		.name = "MPU6000",
+		.reg = &reg_set_6050,
+		.config = &chip_config_6050,
+	},
+	{
+		.whoami = INV_MPU9150_WHOAMI_VALUE,
+		.name = "MPU9150",
 		.reg = &reg_set_6050,
 		.config = &chip_config_6050,
 	},
@@ -600,6 +612,10 @@ inv_fifo_rate_show(struct device *dev, s
 /**
  * inv_attr_show() - calling this function will show current
  *                    parameters.
+ *
+ * Deprecated in favor of IIO mounting matrix API.
+ *
+ * See inv_get_mount_matrix()
  */
 static ssize_t inv_attr_show(struct device *dev, struct device_attribute *attr,
 			     char *buf)
@@ -644,6 +660,18 @@ static int inv_mpu6050_validate_trigger(
 	return 0;
 }
 
+static const struct iio_mount_matrix *
+inv_get_mount_matrix(const struct iio_dev *indio_dev,
+		     const struct iio_chan_spec *chan)
+{
+	return &((struct inv_mpu6050_state *)iio_priv(indio_dev))->orientation;
+}
+
+static const struct iio_chan_spec_ext_info inv_ext_info[] = {
+	IIO_MOUNT_MATRIX(IIO_SHARED_BY_TYPE, inv_get_mount_matrix),
+	{ },
+};
+
 #define INV_MPU6050_CHAN(_type, _channel2, _index)                    \
 	{                                                             \
 		.type = _type,                                        \
@@ -660,6 +688,7 @@ static int inv_mpu6050_validate_trigger(
 				.shift = 0,                           \
 				.endianness = IIO_BE,                 \
 			     },                                       \
+		.ext_info = inv_ext_info,                             \
 	}
 
 static const struct iio_chan_spec inv_mpu_channels[] = {
@@ -692,14 +721,16 @@ static IIO_CONST_ATTR(in_accel_scale_ava
 					  "0.000598 0.001196 0.002392 0.004785");
 static IIO_DEV_ATTR_SAMP_FREQ(S_IRUGO | S_IWUSR, inv_fifo_rate_show,
 	inv_mpu6050_fifo_rate_store);
+
+/* Deprecated: kept for userspace backward compatibility. */
 static IIO_DEVICE_ATTR(in_gyro_matrix, S_IRUGO, inv_attr_show, NULL,
 	ATTR_GYRO_MATRIX);
 static IIO_DEVICE_ATTR(in_accel_matrix, S_IRUGO, inv_attr_show, NULL,
 	ATTR_ACCL_MATRIX);
 
 static struct attribute *inv_attributes[] = {
-	&iio_dev_attr_in_gyro_matrix.dev_attr.attr,
-	&iio_dev_attr_in_accel_matrix.dev_attr.attr,
+	&iio_dev_attr_in_gyro_matrix.dev_attr.attr,  /* deprecated */
+	&iio_dev_attr_in_accel_matrix.dev_attr.attr, /* deprecated */
 	&iio_dev_attr_sampling_frequency.dev_attr.attr,
 	&iio_const_attr_sampling_frequency_available.dev_attr.attr,
 	&iio_const_attr_in_accel_scale_available.dev_attr.attr,
@@ -726,6 +757,7 @@ static const struct iio_info mpu_info =
 static int inv_check_and_setup_chip(struct inv_mpu6050_state *st)
 {
 	int result;
+	unsigned int regval;
 
 	st->hw  = &hw_info[st->chip_type];
 	st->reg = hw_info[st->chip_type].reg;
@@ -736,6 +768,17 @@ static int inv_check_and_setup_chip(stru
 	if (result)
 		return result;
 	msleep(INV_MPU6050_POWER_UP_TIME);
+
+	/* check chip self-identification */
+	result = regmap_read(st->map, INV_MPU6050_REG_WHOAMI, &regval);
+	if (result)
+		return result;
+	if (regval != st->hw->whoami) {
+		dev_warn(regmap_get_device(st->map),
+				"whoami mismatch got %#02x expected %#02hhx for %s\n",
+				regval, st->hw->whoami, st->hw->name);
+	}
+
 	/*
 	 * toggle power state. After reset, the sleep bit could be on
 	 * or off depending on the OTP settings. Toggling power would
@@ -774,14 +817,31 @@ int inv_mpu_core_probe(struct regmap *re
 	if (!indio_dev)
 		return -ENOMEM;
 
+	BUILD_BUG_ON(ARRAY_SIZE(hw_info) != INV_NUM_PARTS);
+	if (chip_type < 0 || chip_type >= INV_NUM_PARTS) {
+		dev_err(dev, "Bad invensense chip_type=%d name=%s\n",
+				chip_type, name);
+		return -ENODEV;
+	}
 	st = iio_priv(indio_dev);
 	st->chip_type = chip_type;
 	st->powerup_count = 0;
 	st->irq = irq;
 	st->map = regmap;
+
 	pdata = dev_get_platdata(dev);
-	if (pdata)
+	if (!pdata) {
+		result = of_iio_read_mount_matrix(dev, "mount-matrix",
+						  &st->orientation);
+		if (result) {
+			dev_err(dev, "Failed to retrieve mounting matrix %d\n",
+				result);
+			return result;
+		}
+	} else {
 		st->plat_data = *pdata;
+	}
+
 	/* power is turned on inside check chip type*/
 	result = inv_check_and_setup_chip(st);
 	if (result)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c linux-libre-4.7-gnu/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
--- linux-libre-4.6-gnu/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c	2016-07-24 15:23:50.000000000 -0400
@@ -15,7 +15,6 @@
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/i2c.h>
-#include <linux/i2c-mux.h>
 #include <linux/iio/iio.h>
 #include <linux/module.h>
 #include "inv_mpu_iio.h"
@@ -25,46 +24,16 @@ static const struct regmap_config inv_mp
 	.val_bits = 8,
 };
 
-/*
- * The i2c read/write needs to happen in unlocked mode. As the parent
- * adapter is common. If we use locked versions, it will fail as
- * the mux adapter will lock the parent i2c adapter, while calling
- * select/deselect functions.
- */
-static int inv_mpu6050_write_reg_unlocked(struct i2c_client *client,
-					  u8 reg, u8 d)
-{
-	int ret;
-	u8 buf[2] = {reg, d};
-	struct i2c_msg msg[1] = {
-		{
-			.addr = client->addr,
-			.flags = 0,
-			.len = sizeof(buf),
-			.buf = buf,
-		}
-	};
-
-	ret = __i2c_transfer(client->adapter, msg, 1);
-	if (ret != 1)
-		return ret;
-
-	return 0;
-}
-
-static int inv_mpu6050_select_bypass(struct i2c_adapter *adap, void *mux_priv,
-				     u32 chan_id)
+static int inv_mpu6050_select_bypass(struct i2c_mux_core *muxc, u32 chan_id)
 {
-	struct i2c_client *client = mux_priv;
-	struct iio_dev *indio_dev = dev_get_drvdata(&client->dev);
+	struct iio_dev *indio_dev = i2c_mux_priv(muxc);
 	struct inv_mpu6050_state *st = iio_priv(indio_dev);
 	int ret = 0;
 
 	/* Use the same mutex which was used everywhere to protect power-op */
 	mutex_lock(&indio_dev->mlock);
 	if (!st->powerup_count) {
-		ret = inv_mpu6050_write_reg_unlocked(client,
-						     st->reg->pwr_mgmt_1, 0);
+		ret = regmap_write(st->map, st->reg->pwr_mgmt_1, 0);
 		if (ret)
 			goto write_error;
 
@@ -73,10 +42,9 @@ static int inv_mpu6050_select_bypass(str
 	}
 	if (!ret) {
 		st->powerup_count++;
-		ret = inv_mpu6050_write_reg_unlocked(client,
-						     st->reg->int_pin_cfg,
-						     INV_MPU6050_INT_PIN_CFG |
-						     INV_MPU6050_BIT_BYPASS_EN);
+		ret = regmap_write(st->map, st->reg->int_pin_cfg,
+				   INV_MPU6050_INT_PIN_CFG |
+				   INV_MPU6050_BIT_BYPASS_EN);
 	}
 write_error:
 	mutex_unlock(&indio_dev->mlock);
@@ -84,21 +52,18 @@ write_error:
 	return ret;
 }
 
-static int inv_mpu6050_deselect_bypass(struct i2c_adapter *adap,
-				       void *mux_priv, u32 chan_id)
+static int inv_mpu6050_deselect_bypass(struct i2c_mux_core *muxc, u32 chan_id)
 {
-	struct i2c_client *client = mux_priv;
-	struct iio_dev *indio_dev = dev_get_drvdata(&client->dev);
+	struct iio_dev *indio_dev = i2c_mux_priv(muxc);
 	struct inv_mpu6050_state *st = iio_priv(indio_dev);
 
 	mutex_lock(&indio_dev->mlock);
 	/* It doesn't really mattter, if any of the calls fails */
-	inv_mpu6050_write_reg_unlocked(client, st->reg->int_pin_cfg,
-				       INV_MPU6050_INT_PIN_CFG);
+	regmap_write(st->map, st->reg->int_pin_cfg, INV_MPU6050_INT_PIN_CFG);
 	st->powerup_count--;
 	if (!st->powerup_count)
-		inv_mpu6050_write_reg_unlocked(client, st->reg->pwr_mgmt_1,
-					       INV_MPU6050_BIT_SLEEP);
+		regmap_write(st->map, st->reg->pwr_mgmt_1,
+			     INV_MPU6050_BIT_SLEEP);
 	mutex_unlock(&indio_dev->mlock);
 
 	return 0;
@@ -160,16 +125,18 @@ static int inv_mpu_probe(struct i2c_clie
 		return result;
 
 	st = iio_priv(dev_get_drvdata(&client->dev));
-	st->mux_adapter = i2c_add_mux_adapter(client->adapter,
-					      &client->dev,
-					      client,
-					      0, 0, 0,
-					      inv_mpu6050_select_bypass,
-					      inv_mpu6050_deselect_bypass);
-	if (!st->mux_adapter) {
-		result = -ENODEV;
+	st->muxc = i2c_mux_alloc(client->adapter, &client->dev,
+				 1, 0, I2C_MUX_LOCKED,
+				 inv_mpu6050_select_bypass,
+				 inv_mpu6050_deselect_bypass);
+	if (!st->muxc) {
+		result = -ENOMEM;
 		goto out_unreg_device;
 	}
+	st->muxc->priv = dev_get_drvdata(&client->dev);
+	result = i2c_mux_add_adapter(st->muxc, 0, 0, 0);
+	if (result)
+		goto out_unreg_device;
 
 	result = inv_mpu_acpi_create_mux_client(client);
 	if (result)
@@ -178,7 +145,7 @@ static int inv_mpu_probe(struct i2c_clie
 	return 0;
 
 out_del_mux:
-	i2c_del_mux_adapter(st->mux_adapter);
+	i2c_mux_del_adapters(st->muxc);
 out_unreg_device:
 	inv_mpu_core_remove(&client->dev);
 	return result;
@@ -190,7 +157,7 @@ static int inv_mpu_remove(struct i2c_cli
 	struct inv_mpu6050_state *st = iio_priv(indio_dev);
 
 	inv_mpu_acpi_delete_mux_client(client);
-	i2c_del_mux_adapter(st->mux_adapter);
+	i2c_mux_del_adapters(st->muxc);
 
 	return inv_mpu_core_remove(&client->dev);
 }
@@ -202,13 +169,14 @@ static int inv_mpu_remove(struct i2c_cli
 static const struct i2c_device_id inv_mpu_id[] = {
 	{"mpu6050", INV_MPU6050},
 	{"mpu6500", INV_MPU6500},
+	{"mpu9150", INV_MPU9150},
 	{}
 };
 
 MODULE_DEVICE_TABLE(i2c, inv_mpu_id);
 
 static const struct acpi_device_id inv_acpi_match[] = {
-	{"INVN6500", 0},
+	{"INVN6500", INV_MPU6500},
 	{ },
 };
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h linux-libre-4.7-gnu/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
--- linux-libre-4.6-gnu/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h	2016-07-24 15:23:50.000000000 -0400
@@ -11,6 +11,7 @@
 * GNU General Public License for more details.
 */
 #include <linux/i2c.h>
+#include <linux/i2c-mux.h>
 #include <linux/kfifo.h>
 #include <linux/spinlock.h>
 #include <linux/iio/iio.h>
@@ -68,6 +69,7 @@ enum inv_devices {
 	INV_MPU6050,
 	INV_MPU6500,
 	INV_MPU6000,
+	INV_MPU9150,
 	INV_NUM_PARTS
 };
 
@@ -93,13 +95,13 @@ struct inv_mpu6050_chip_config {
 
 /**
  *  struct inv_mpu6050_hw - Other important hardware information.
- *  @num_reg:	Number of registers on device.
+ *  @whoami:	Self identification byte from WHO_AM_I register
  *  @name:      name of the chip.
  *  @reg:   register map of the chip.
  *  @config:    configuration of the chip.
  */
 struct inv_mpu6050_hw {
-	u8 num_reg;
+	u8 whoami;
 	u8 *name;
 	const struct inv_mpu6050_reg_map *reg;
 	const struct inv_mpu6050_chip_config *config;
@@ -114,7 +116,8 @@ struct inv_mpu6050_hw {
  *  @hw:		Other hardware-specific information.
  *  @chip_type:		chip type.
  *  @time_stamp_lock:	spin lock to time stamp.
- *  @plat_data:		platform data.
+ *  @plat_data:		platform data (deprecated in favor of @orientation).
+ *  @orientation:	sensor chip orientation relative to main hardware.
  *  @timestamps:        kfifo queue to store time stamp.
  *  @map		regmap pointer.
  *  @irq		interrupt number.
@@ -127,10 +130,11 @@ struct inv_mpu6050_state {
 	const struct inv_mpu6050_hw *hw;
 	enum   inv_devices chip_type;
 	spinlock_t time_stamp_lock;
-	struct i2c_adapter *mux_adapter;
+	struct i2c_mux_core *muxc;
 	struct i2c_client *mux_client;
 	unsigned int powerup_count;
 	struct inv_mpu6050_platform_data plat_data;
+	struct iio_mount_matrix orientation;
 	DECLARE_KFIFO(timestamps, long long, TIMESTAMP_FIFO_SIZE);
 	struct regmap *map;
 	int irq;
@@ -215,6 +219,13 @@ struct inv_mpu6050_state {
 #define INV_MPU6050_MIN_FIFO_RATE            4
 #define INV_MPU6050_ONE_K_HZ                 1000
 
+#define INV_MPU6050_REG_WHOAMI			117
+
+#define INV_MPU6000_WHOAMI_VALUE		0x68
+#define INV_MPU6050_WHOAMI_VALUE		0x68
+#define INV_MPU6500_WHOAMI_VALUE		0x70
+#define INV_MPU9150_WHOAMI_VALUE		0x68
+
 /* scan element definition */
 enum inv_mpu6050_scan {
 	INV_MPU6050_SCAN_ACCL_X,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c linux-libre-4.7-gnu/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c
--- linux-libre-4.6-gnu/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c	2016-07-24 15:23:50.000000000 -0400
@@ -44,9 +44,19 @@ static int inv_mpu_i2c_disable(struct ii
 static int inv_mpu_probe(struct spi_device *spi)
 {
 	struct regmap *regmap;
-	const struct spi_device_id *id = spi_get_device_id(spi);
-	const char *name = id ? id->name : NULL;
-	const int chip_type = id ? id->driver_data : 0;
+	const struct spi_device_id *spi_id;
+	const struct acpi_device_id *acpi_id;
+	const char *name = NULL;
+	enum inv_devices chip_type;
+
+	if ((spi_id = spi_get_device_id(spi))) {
+		chip_type = (enum inv_devices)spi_id->driver_data;
+		name = spi_id->name;
+	} else if ((acpi_id = acpi_match_device(spi->dev.driver->acpi_match_table, &spi->dev))) {
+		chip_type = (enum inv_devices)acpi_id->driver_data;
+	} else {
+		return -ENODEV;
+	}
 
 	regmap = devm_regmap_init_spi(spi, &inv_mpu_regmap_config);
 	if (IS_ERR(regmap)) {
@@ -70,13 +80,15 @@ static int inv_mpu_remove(struct spi_dev
  */
 static const struct spi_device_id inv_mpu_id[] = {
 	{"mpu6000", INV_MPU6000},
+	{"mpu6500", INV_MPU6500},
+	{"mpu9150", INV_MPU9150},
 	{}
 };
 
 MODULE_DEVICE_TABLE(spi, inv_mpu_id);
 
 static const struct acpi_device_id inv_acpi_match[] = {
-	{"INVN6000", 0},
+	{"INVN6000", INV_MPU6000},
 	{ },
 };
 MODULE_DEVICE_TABLE(acpi, inv_acpi_match);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/imu/inv_mpu6050/Kconfig linux-libre-4.7-gnu/drivers/iio/imu/inv_mpu6050/Kconfig
--- linux-libre-4.6-gnu/drivers/iio/imu/inv_mpu6050/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/imu/inv_mpu6050/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -13,10 +13,8 @@ config INV_MPU6050_I2C
 	select INV_MPU6050_IIO
 	select REGMAP_I2C
 	help
-	  This driver supports the Invensense MPU6050 devices.
-	  This driver can also support MPU6500 in MPU6050 compatibility mode
-	  and also in MPU6500 mode with some limitations.
-	  It is a gyroscope/accelerometer combo device.
+	  This driver supports the Invensense MPU6050/6500/9150 motion tracking
+	  devices over I2C.
 	  This driver can be built as a module. The module will be called
 	  inv-mpu6050-i2c.
 
@@ -26,7 +24,7 @@ config INV_MPU6050_SPI
 	select INV_MPU6050_IIO
 	select REGMAP_SPI
 	help
-	  This driver supports the Invensense MPU6050 devices.
-	  It is a gyroscope/accelerometer combo device.
+	  This driver supports the Invensense MPU6000/6500/9150 motion tracking
+	  devices over SPI.
 	  This driver can be built as a module. The module will be called
 	  inv-mpu6050-spi.
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/imu/Kconfig linux-libre-4.7-gnu/drivers/iio/imu/Kconfig
--- linux-libre-4.6-gnu/drivers/iio/imu/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/imu/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -25,6 +25,8 @@ config ADIS16480
 	  Say yes here to build support for Analog Devices ADIS16375, ADIS16480,
 	  ADIS16485, ADIS16488 inertial sensors.
 
+source "drivers/iio/imu/bmi160/Kconfig"
+
 config KMX61
 	tristate "Kionix KMX61 6-axis accelerometer and magnetometer"
 	depends on I2C
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/imu/kmx61.c linux-libre-4.7-gnu/drivers/iio/imu/kmx61.c
--- linux-libre-4.6-gnu/drivers/iio/imu/kmx61.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/imu/kmx61.c	2016-07-24 15:23:50.000000000 -0400
@@ -14,7 +14,6 @@
 #include <linux/module.h>
 #include <linux/i2c.h>
 #include <linux/acpi.h>
-#include <linux/gpio/consumer.h>
 #include <linux/interrupt.h>
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/imu/Makefile linux-libre-4.7-gnu/drivers/iio/imu/Makefile
--- linux-libre-4.6-gnu/drivers/iio/imu/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/imu/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -13,6 +13,7 @@ adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) +
 adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_buffer.o
 obj-$(CONFIG_IIO_ADIS_LIB) += adis_lib.o
 
+obj-y += bmi160/
 obj-y += inv_mpu6050/
 
 obj-$(CONFIG_KMX61) += kmx61.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/industrialio-core.c linux-libre-4.7-gnu/drivers/iio/industrialio-core.c
--- linux-libre-4.6-gnu/drivers/iio/industrialio-core.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/industrialio-core.c	2016-07-24 15:23:50.000000000 -0400
@@ -25,6 +25,7 @@
 #include <linux/slab.h>
 #include <linux/anon_inodes.h>
 #include <linux/debugfs.h>
+#include <linux/mutex.h>
 #include <linux/iio/iio.h>
 #include "iio_core.h"
 #include "iio_core_trigger.h"
@@ -78,6 +79,7 @@ static const char * const iio_chan_type_
 	[IIO_CONCENTRATION] = "concentration",
 	[IIO_RESISTANCE] = "resistance",
 	[IIO_PH] = "ph",
+	[IIO_UVINDEX] = "uvindex",
 };
 
 static const char * const iio_modifier_names[] = {
@@ -100,6 +102,7 @@ static const char * const iio_modifier_n
 	[IIO_MOD_LIGHT_RED] = "red",
 	[IIO_MOD_LIGHT_GREEN] = "green",
 	[IIO_MOD_LIGHT_BLUE] = "blue",
+	[IIO_MOD_LIGHT_UV] = "uv",
 	[IIO_MOD_QUATERNION] = "quaternion",
 	[IIO_MOD_TEMP_AMBIENT] = "ambient",
 	[IIO_MOD_TEMP_OBJECT] = "object",
@@ -409,6 +412,88 @@ ssize_t iio_enum_write(struct iio_dev *i
 }
 EXPORT_SYMBOL_GPL(iio_enum_write);
 
+static const struct iio_mount_matrix iio_mount_idmatrix = {
+	.rotation = {
+		"1", "0", "0",
+		"0", "1", "0",
+		"0", "0", "1"
+	}
+};
+
+static int iio_setup_mount_idmatrix(const struct device *dev,
+				    struct iio_mount_matrix *matrix)
+{
+	*matrix = iio_mount_idmatrix;
+	dev_info(dev, "mounting matrix not found: using identity...\n");
+	return 0;
+}
+
+ssize_t iio_show_mount_matrix(struct iio_dev *indio_dev, uintptr_t priv,
+			      const struct iio_chan_spec *chan, char *buf)
+{
+	const struct iio_mount_matrix *mtx = ((iio_get_mount_matrix_t *)
+					      priv)(indio_dev, chan);
+
+	if (IS_ERR(mtx))
+		return PTR_ERR(mtx);
+
+	if (!mtx)
+		mtx = &iio_mount_idmatrix;
+
+	return snprintf(buf, PAGE_SIZE, "%s, %s, %s; %s, %s, %s; %s, %s, %s\n",
+			mtx->rotation[0], mtx->rotation[1], mtx->rotation[2],
+			mtx->rotation[3], mtx->rotation[4], mtx->rotation[5],
+			mtx->rotation[6], mtx->rotation[7], mtx->rotation[8]);
+}
+EXPORT_SYMBOL_GPL(iio_show_mount_matrix);
+
+/**
+ * of_iio_read_mount_matrix() - retrieve iio device mounting matrix from
+ *                              device-tree "mount-matrix" property
+ * @dev:	device the mounting matrix property is assigned to
+ * @propname:	device specific mounting matrix property name
+ * @matrix:	where to store retrieved matrix
+ *
+ * If device is assigned no mounting matrix property, a default 3x3 identity
+ * matrix will be filled in.
+ *
+ * Return: 0 if success, or a negative error code on failure.
+ */
+#ifdef CONFIG_OF
+int of_iio_read_mount_matrix(const struct device *dev,
+			     const char *propname,
+			     struct iio_mount_matrix *matrix)
+{
+	if (dev->of_node) {
+		int err = of_property_read_string_array(dev->of_node,
+				propname, matrix->rotation,
+				ARRAY_SIZE(iio_mount_idmatrix.rotation));
+
+		if (err == ARRAY_SIZE(iio_mount_idmatrix.rotation))
+			return 0;
+
+		if (err >= 0)
+			/* Invalid number of matrix entries. */
+			return -EINVAL;
+
+		if (err != -EINVAL)
+			/* Invalid matrix declaration format. */
+			return err;
+	}
+
+	/* Matrix was not declared at all: fallback to identity. */
+	return iio_setup_mount_idmatrix(dev, matrix);
+}
+#else
+int of_iio_read_mount_matrix(const struct device *dev,
+			     const char *propname,
+			     struct iio_mount_matrix *matrix)
+{
+	return iio_setup_mount_idmatrix(dev, matrix);
+}
+#endif
+EXPORT_SYMBOL(of_iio_read_mount_matrix);
+
 /**
  * iio_format_value() - Formats a IIO value into its string representation
  * @buf:	The buffer to which the formatted value gets written
@@ -1375,6 +1460,44 @@ void devm_iio_device_unregister(struct d
 }
 EXPORT_SYMBOL_GPL(devm_iio_device_unregister);
 
+/**
+ * iio_device_claim_direct_mode - Keep device in direct mode
+ * @indio_dev:	the iio_dev associated with the device
+ *
+ * If the device is in direct mode it is guaranteed to stay
+ * that way until iio_device_release_direct_mode() is called.
+ *
+ * Use with iio_device_release_direct_mode()
+ *
+ * Returns: 0 on success, -EBUSY on failure
+ */
+int iio_device_claim_direct_mode(struct iio_dev *indio_dev)
+{
+	mutex_lock(&indio_dev->mlock);
+
+	if (iio_buffer_enabled(indio_dev)) {
+		mutex_unlock(&indio_dev->mlock);
+		return -EBUSY;
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(iio_device_claim_direct_mode);
+
+/**
+ * iio_device_release_direct_mode - releases claim on direct mode
+ * @indio_dev:	the iio_dev associated with the device
+ *
+ * Release the claim. Device is no longer guaranteed to stay
+ * in direct mode.
+ *
+ * Use with iio_device_claim_direct_mode()
+ */
+void iio_device_release_direct_mode(struct iio_dev *indio_dev)
+{
+	mutex_unlock(&indio_dev->mlock);
+}
+EXPORT_SYMBOL_GPL(iio_device_release_direct_mode);
+
 subsys_initcall(iio_init);
 module_exit(iio_exit);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/industrialio-trigger.c linux-libre-4.7-gnu/drivers/iio/industrialio-trigger.c
--- linux-libre-4.6-gnu/drivers/iio/industrialio-trigger.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/industrialio-trigger.c	2016-07-24 15:23:50.000000000 -0400
@@ -210,22 +210,35 @@ static int iio_trigger_attach_poll_func(
 
 	/* Prevent the module from being removed whilst attached to a trigger */
 	__module_get(pf->indio_dev->info->driver_module);
+
+	/* Get irq number */
 	pf->irq = iio_trigger_get_irq(trig);
+	if (pf->irq < 0)
+		goto out_put_module;
+
+	/* Request irq */
 	ret = request_threaded_irq(pf->irq, pf->h, pf->thread,
 				   pf->type, pf->name,
 				   pf);
-	if (ret < 0) {
-		module_put(pf->indio_dev->info->driver_module);
-		return ret;
-	}
+	if (ret < 0)
+		goto out_put_irq;
 
+	/* Enable trigger in driver */
 	if (trig->ops && trig->ops->set_trigger_state && notinuse) {
 		ret = trig->ops->set_trigger_state(trig, true);
 		if (ret < 0)
-			module_put(pf->indio_dev->info->driver_module);
+			goto out_free_irq;
 	}
 
 	return ret;
+
+out_free_irq:
+	free_irq(pf->irq, pf);
+out_put_irq:
+	iio_trigger_put_irq(trig, pf->irq);
+out_put_module:
+	module_put(pf->indio_dev->info->driver_module);
+	return ret;
 }
 
 static int iio_trigger_detach_poll_func(struct iio_trigger *trig,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/inkern.c linux-libre-4.7-gnu/drivers/iio/inkern.c
--- linux-libre-4.6-gnu/drivers/iio/inkern.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/inkern.c	2016-07-24 15:23:50.000000000 -0400
@@ -356,6 +356,54 @@ void iio_channel_release(struct iio_chan
 }
 EXPORT_SYMBOL_GPL(iio_channel_release);
 
+static void devm_iio_channel_free(struct device *dev, void *res)
+{
+	struct iio_channel *channel = *(struct iio_channel **)res;
+
+	iio_channel_release(channel);
+}
+
+static int devm_iio_channel_match(struct device *dev, void *res, void *data)
+{
+	struct iio_channel **r = res;
+
+	if (!r || !*r) {
+		WARN_ON(!r || !*r);
+		return 0;
+	}
+
+	return *r == data;
+}
+
+struct iio_channel *devm_iio_channel_get(struct device *dev,
+					 const char *channel_name)
+{
+	struct iio_channel **ptr, *channel;
+
+	ptr = devres_alloc(devm_iio_channel_free, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return ERR_PTR(-ENOMEM);
+
+	channel = iio_channel_get(dev, channel_name);
+	if (IS_ERR(channel)) {
+		devres_free(ptr);
+		return channel;
+	}
+
+	*ptr = channel;
+	devres_add(dev, ptr);
+
+	return channel;
+}
+EXPORT_SYMBOL_GPL(devm_iio_channel_get);
+
+void devm_iio_channel_release(struct device *dev, struct iio_channel *channel)
+{
+	WARN_ON(devres_release(dev, devm_iio_channel_free,
+			       devm_iio_channel_match, channel));
+}
+EXPORT_SYMBOL_GPL(devm_iio_channel_release);
+
 struct iio_channel *iio_channel_get_all(struct device *dev)
 {
 	const char *name;
@@ -441,6 +489,42 @@ void iio_channel_release_all(struct iio_
 }
 EXPORT_SYMBOL_GPL(iio_channel_release_all);
 
+static void devm_iio_channel_free_all(struct device *dev, void *res)
+{
+	struct iio_channel *channels = *(struct iio_channel **)res;
+
+	iio_channel_release_all(channels);
+}
+
+struct iio_channel *devm_iio_channel_get_all(struct device *dev)
+{
+	struct iio_channel **ptr, *channels;
+
+	ptr = devres_alloc(devm_iio_channel_free_all, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return ERR_PTR(-ENOMEM);
+
+	channels = iio_channel_get_all(dev);
+	if (IS_ERR(channels)) {
+		devres_free(ptr);
+		return channels;
+	}
+
+	*ptr = channels;
+	devres_add(dev, ptr);
+
+	return channels;
+}
+EXPORT_SYMBOL_GPL(devm_iio_channel_get_all);
+
+void devm_iio_channel_release_all(struct device *dev,
+				  struct iio_channel *channels)
+{
+	WARN_ON(devres_release(dev, devm_iio_channel_free_all,
+			       devm_iio_channel_match, channels));
+}
+EXPORT_SYMBOL_GPL(devm_iio_channel_release_all);
+
 static int iio_channel_read(struct iio_channel *chan, int *val, int *val2,
 	enum iio_chan_info_enum info)
 {
@@ -452,7 +536,7 @@ static int iio_channel_read(struct iio_c
 	if (val2 == NULL)
 		val2 = &unused;
 
-	if(!iio_channel_has_info(chan->channel, info))
+	if (!iio_channel_has_info(chan->channel, info))
 		return -EINVAL;
 
 	if (chan->indio_dev->info->read_raw_multi) {
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/light/apds9960.c linux-libre-4.7-gnu/drivers/iio/light/apds9960.c
--- linux-libre-4.6-gnu/drivers/iio/light/apds9960.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/light/apds9960.c	2016-07-24 15:23:50.000000000 -0400
@@ -321,8 +321,12 @@ static const struct iio_chan_spec apds99
 };
 
 /* integration time in us */
-static const int apds9960_int_time[][2] =
-	{ {28000, 246}, {100000, 219}, {200000, 182}, {700000, 0} };
+static const int apds9960_int_time[][2] = {
+	{ 28000, 246},
+	{100000, 219},
+	{200000, 182},
+	{700000,   0}
+};
 
 /* gain mapping */
 static const int apds9960_pxs_gain_map[] = {1, 2, 4, 8};
@@ -491,9 +495,10 @@ static int apds9960_read_raw(struct iio_
 		case IIO_INTENSITY:
 			ret = regmap_bulk_read(data->regmap, chan->address,
 					       &buf, 2);
-			if (!ret)
+			if (!ret) {
 				ret = IIO_VAL_INT;
-			*val = le16_to_cpu(buf);
+				*val = le16_to_cpu(buf);
+			}
 			break;
 		default:
 			ret = -EINVAL;
@@ -1006,6 +1011,7 @@ static int apds9960_probe(struct i2c_cli
 
 	iio_device_attach_buffer(indio_dev, buffer);
 
+	indio_dev->dev.parent = &client->dev;
 	indio_dev->info = &apds9960_info;
 	indio_dev->name = APDS9960_DRV_NAME;
 	indio_dev->channels = apds9960_channels;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/light/bh1780.c linux-libre-4.7-gnu/drivers/iio/light/bh1780.c
--- linux-libre-4.6-gnu/drivers/iio/light/bh1780.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/iio/light/bh1780.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,299 @@
+/*
+ * ROHM 1780GLI Ambient Light Sensor Driver
+ *
+ * Copyright (C) 2016 Linaro Ltd.
+ * Author: Linus Walleij <linus.walleij@linaro.org>
+ * Loosely based on the previous BH1780 ALS misc driver
+ * Copyright (C) 2010 Texas Instruments
+ * Author: Hemanth V <hemanthv@ti.com>
+ */
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/pm_runtime.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/bitops.h>
+
+#define BH1780_CMD_BIT		BIT(7)
+#define BH1780_REG_CONTROL	0x00
+#define BH1780_REG_PARTID	0x0A
+#define BH1780_REG_MANFID	0x0B
+#define BH1780_REG_DLOW		0x0C
+#define BH1780_REG_DHIGH	0x0D
+
+#define BH1780_REVMASK		GENMASK(3,0)
+#define BH1780_POWMASK		GENMASK(1,0)
+#define BH1780_POFF		(0x0)
+#define BH1780_PON		(0x3)
+
+/* power on settling time in ms */
+#define BH1780_PON_DELAY	2
+/* max time before value available in ms */
+#define BH1780_INTERVAL		250
+
+struct bh1780_data {
+	struct i2c_client *client;
+};
+
+static int bh1780_write(struct bh1780_data *bh1780, u8 reg, u8 val)
+{
+	int ret = i2c_smbus_write_byte_data(bh1780->client,
+					    BH1780_CMD_BIT | reg,
+					    val);
+	if (ret < 0)
+		dev_err(&bh1780->client->dev,
+			"i2c_smbus_write_byte_data failed error "
+			"%d, register %01x\n",
+			ret, reg);
+	return ret;
+}
+
+static int bh1780_read(struct bh1780_data *bh1780, u8 reg)
+{
+	int ret = i2c_smbus_read_byte_data(bh1780->client,
+					   BH1780_CMD_BIT | reg);
+	if (ret < 0)
+		dev_err(&bh1780->client->dev,
+			"i2c_smbus_read_byte_data failed error "
+			"%d, register %01x\n",
+			ret, reg);
+	return ret;
+}
+
+static int bh1780_read_word(struct bh1780_data *bh1780, u8 reg)
+{
+	int ret = i2c_smbus_read_word_data(bh1780->client,
+					   BH1780_CMD_BIT | reg);
+	if (ret < 0)
+		dev_err(&bh1780->client->dev,
+			"i2c_smbus_read_word_data failed error "
+			"%d, register %01x\n",
+			ret, reg);
+	return ret;
+}
+
+static int bh1780_debugfs_reg_access(struct iio_dev *indio_dev,
+			      unsigned int reg, unsigned int writeval,
+			      unsigned int *readval)
+{
+	struct bh1780_data *bh1780 = iio_priv(indio_dev);
+	int ret;
+
+	if (!readval)
+		return bh1780_write(bh1780, (u8)reg, (u8)writeval);
+
+	ret = bh1780_read(bh1780, (u8)reg);
+	if (ret < 0)
+		return ret;
+
+	*readval = ret;
+
+	return 0;
+}
+
+static int bh1780_read_raw(struct iio_dev *indio_dev,
+			   struct iio_chan_spec const *chan,
+			   int *val, int *val2, long mask)
+{
+	struct bh1780_data *bh1780 = iio_priv(indio_dev);
+	int value;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		switch (chan->type) {
+		case IIO_LIGHT:
+			pm_runtime_get_sync(&bh1780->client->dev);
+			value = bh1780_read_word(bh1780, BH1780_REG_DLOW);
+			if (value < 0)
+				return value;
+			pm_runtime_mark_last_busy(&bh1780->client->dev);
+			pm_runtime_put_autosuspend(&bh1780->client->dev);
+			*val = value;
+
+			return IIO_VAL_INT;
+		default:
+			return -EINVAL;
+		}
+	case IIO_CHAN_INFO_INT_TIME:
+		*val = 0;
+		*val2 = BH1780_INTERVAL * 1000;
+		return IIO_VAL_INT_PLUS_MICRO;
+	default:
+		return -EINVAL;
+	}
+}
+
+static const struct iio_info bh1780_info = {
+	.driver_module = THIS_MODULE,
+	.read_raw = bh1780_read_raw,
+	.debugfs_reg_access = bh1780_debugfs_reg_access,
+};
+
+static const struct iio_chan_spec bh1780_channels[] = {
+	{
+		.type = IIO_LIGHT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+				      BIT(IIO_CHAN_INFO_INT_TIME)
+	}
+};
+
+static int bh1780_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	int ret;
+	struct bh1780_data *bh1780;
+	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+	struct iio_dev *indio_dev;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
+		return -EIO;
+
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*bh1780));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	bh1780 = iio_priv(indio_dev);
+	bh1780->client = client;
+	i2c_set_clientdata(client, indio_dev);
+
+	/* Power up the device */
+	ret = bh1780_write(bh1780, BH1780_REG_CONTROL, BH1780_PON);
+	if (ret < 0)
+		return ret;
+	msleep(BH1780_PON_DELAY);
+	pm_runtime_get_noresume(&client->dev);
+	pm_runtime_set_active(&client->dev);
+	pm_runtime_enable(&client->dev);
+
+	ret = bh1780_read(bh1780, BH1780_REG_PARTID);
+	if (ret < 0)
+		goto out_disable_pm;
+	dev_info(&client->dev,
+		 "Ambient Light Sensor, Rev : %lu\n",
+		 (ret & BH1780_REVMASK));
+
+	/*
+	 * As the device takes 250 ms to even come up with a fresh
+	 * measurement after power-on, do not shut it down unnecessarily.
+	 * Set autosuspend to a five seconds.
+	 */
+	pm_runtime_set_autosuspend_delay(&client->dev, 5000);
+	pm_runtime_use_autosuspend(&client->dev);
+	pm_runtime_put(&client->dev);
+
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->info = &bh1780_info;
+	indio_dev->name = "bh1780";
+	indio_dev->channels = bh1780_channels;
+	indio_dev->num_channels = ARRAY_SIZE(bh1780_channels);
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	ret = iio_device_register(indio_dev);
+	if (ret)
+		goto out_disable_pm;
+	return 0;
+
+out_disable_pm:
+	pm_runtime_put_noidle(&client->dev);
+	pm_runtime_disable(&client->dev);
+	return ret;
+}
+
+static int bh1780_remove(struct i2c_client *client)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+	struct bh1780_data *bh1780 = iio_priv(indio_dev);
+	int ret;
+
+	iio_device_unregister(indio_dev);
+	pm_runtime_get_sync(&client->dev);
+	pm_runtime_put_noidle(&client->dev);
+	pm_runtime_disable(&client->dev);
+	ret = bh1780_write(bh1780, BH1780_REG_CONTROL, BH1780_POFF);
+	if (ret < 0) {
+		dev_err(&client->dev, "failed to power off\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int bh1780_runtime_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+	struct bh1780_data *bh1780 = iio_priv(indio_dev);
+	int ret;
+
+	ret = bh1780_write(bh1780, BH1780_REG_CONTROL, BH1780_POFF);
+	if (ret < 0) {
+		dev_err(dev, "failed to runtime suspend\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int bh1780_runtime_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+	struct bh1780_data *bh1780 = iio_priv(indio_dev);
+	int ret;
+
+	ret = bh1780_write(bh1780, BH1780_REG_CONTROL, BH1780_PON);
+	if (ret < 0) {
+		dev_err(dev, "failed to runtime resume\n");
+		return ret;
+	}
+
+	/* Wait for power on, then for a value to be available */
+	msleep(BH1780_PON_DELAY + BH1780_INTERVAL);
+
+	return 0;
+}
+#endif /* CONFIG_PM */
+
+static const struct dev_pm_ops bh1780_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+				pm_runtime_force_resume)
+	SET_RUNTIME_PM_OPS(bh1780_runtime_suspend,
+			   bh1780_runtime_resume, NULL)
+};
+
+static const struct i2c_device_id bh1780_id[] = {
+	{ "bh1780", 0 },
+	{ },
+};
+
+MODULE_DEVICE_TABLE(i2c, bh1780_id);
+
+#ifdef CONFIG_OF
+static const struct of_device_id of_bh1780_match[] = {
+	{ .compatible = "rohm,bh1780gli", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, of_bh1780_match);
+#endif
+
+static struct i2c_driver bh1780_driver = {
+	.probe		= bh1780_probe,
+	.remove		= bh1780_remove,
+	.id_table	= bh1780_id,
+	.driver = {
+		.name = "bh1780",
+		.pm = &bh1780_dev_pm_ops,
+		.of_match_table = of_match_ptr(of_bh1780_match),
+	},
+};
+
+module_i2c_driver(bh1780_driver);
+
+MODULE_DESCRIPTION("ROHM BH1780GLI Ambient Light Sensor Driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/light/Kconfig linux-libre-4.7-gnu/drivers/iio/light/Kconfig
--- linux-libre-4.6-gnu/drivers/iio/light/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/light/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -73,6 +73,17 @@ config BH1750
 	 To compile this driver as a module, choose M here: the module will
 	 be called bh1750.
 
+config BH1780
+	tristate "ROHM BH1780 ambient light sensor"
+	depends on I2C
+	depends on !SENSORS_BH1780
+	help
+	 Say Y here to build support for the ROHM BH1780GLI ambient
+	 light sensor.
+
+	 To compile this driver as a module, choose M here: the module will
+	 be called bh1780.
+
 config CM32181
 	depends on I2C
 	tristate "CM32181 driver"
@@ -223,6 +234,17 @@ config LTR501
 	 This driver can also be built as a module.  If so, the module
          will be called ltr501.
 
+config MAX44000
+	tristate "MAX44000 Ambient and Infrared Proximity Sensor"
+	depends on I2C
+	select REGMAP_I2C
+	help
+	 Say Y here if you want to build support for Maxim Integrated's
+	 MAX44000 ambient and infrared proximity sensor device.
+
+	 To compile this driver as a module, choose M here:
+	 the module will be called max44000.
+
 config OPT3001
 	tristate "Texas Instruments OPT3001 Light Sensor"
 	depends on I2C
@@ -320,4 +342,14 @@ config VCNL4000
 	 To compile this driver as a module, choose M here: the
 	 module will be called vcnl4000.
 
+config VEML6070
+	tristate "VEML6070 UV A light sensor"
+	depends on I2C
+	help
+	 Say Y here if you want to build a driver for the Vishay VEML6070 UV A
+	 light sensor.
+
+	 To compile this driver as a module, choose M here: the
+	 module will be called veml6070.
+
 endmenu
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/light/Makefile linux-libre-4.7-gnu/drivers/iio/light/Makefile
--- linux-libre-4.6-gnu/drivers/iio/light/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/light/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -9,6 +9,7 @@ obj-$(CONFIG_AL3320A)		+= al3320a.o
 obj-$(CONFIG_APDS9300)		+= apds9300.o
 obj-$(CONFIG_APDS9960)		+= apds9960.o
 obj-$(CONFIG_BH1750)		+= bh1750.o
+obj-$(CONFIG_BH1780)		+= bh1780.o
 obj-$(CONFIG_CM32181)		+= cm32181.o
 obj-$(CONFIG_CM3232)		+= cm3232.o
 obj-$(CONFIG_CM3323)		+= cm3323.o
@@ -20,6 +21,7 @@ obj-$(CONFIG_ISL29125)		+= isl29125.o
 obj-$(CONFIG_JSA1212)		+= jsa1212.o
 obj-$(CONFIG_SENSORS_LM3533)	+= lm3533-als.o
 obj-$(CONFIG_LTR501)		+= ltr501.o
+obj-$(CONFIG_MAX44000)		+= max44000.o
 obj-$(CONFIG_OPT3001)		+= opt3001.o
 obj-$(CONFIG_PA12203001)	+= pa12203001.o
 obj-$(CONFIG_RPR0521)		+= rpr0521.o
@@ -30,3 +32,4 @@ obj-$(CONFIG_TCS3472)		+= tcs3472.o
 obj-$(CONFIG_TSL4531)		+= tsl4531.o
 obj-$(CONFIG_US5182D)		+= us5182d.o
 obj-$(CONFIG_VCNL4000)		+= vcnl4000.o
+obj-$(CONFIG_VEML6070)		+= veml6070.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/light/max44000.c linux-libre-4.7-gnu/drivers/iio/light/max44000.c
--- linux-libre-4.6-gnu/drivers/iio/light/max44000.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/iio/light/max44000.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,638 @@
+/*
+ * MAX44000 Ambient and Infrared Proximity Sensor
+ *
+ * Copyright (c) 2016, Intel Corporation.
+ *
+ * This file is subject to the terms and conditions of version 2 of
+ * the GNU General Public License.  See the file COPYING in the main
+ * directory of this archive for more details.
+ *
+ * Data sheet: https://datasheets.maximintegrated.com/en/ds/MAX44000.pdf
+ *
+ * 7-bit I2C slave address 0x4a
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/util_macros.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/acpi.h>
+
+#define MAX44000_DRV_NAME		"max44000"
+
+/* Registers in datasheet order */
+#define MAX44000_REG_STATUS		0x00
+#define MAX44000_REG_CFG_MAIN		0x01
+#define MAX44000_REG_CFG_RX		0x02
+#define MAX44000_REG_CFG_TX		0x03
+#define MAX44000_REG_ALS_DATA_HI	0x04
+#define MAX44000_REG_ALS_DATA_LO	0x05
+#define MAX44000_REG_PRX_DATA		0x16
+#define MAX44000_REG_ALS_UPTHR_HI	0x06
+#define MAX44000_REG_ALS_UPTHR_LO	0x07
+#define MAX44000_REG_ALS_LOTHR_HI	0x08
+#define MAX44000_REG_ALS_LOTHR_LO	0x09
+#define MAX44000_REG_PST		0x0a
+#define MAX44000_REG_PRX_IND		0x0b
+#define MAX44000_REG_PRX_THR		0x0c
+#define MAX44000_REG_TRIM_GAIN_GREEN	0x0f
+#define MAX44000_REG_TRIM_GAIN_IR	0x10
+
+/* REG_CFG bits */
+#define MAX44000_CFG_ALSINTE            0x01
+#define MAX44000_CFG_PRXINTE            0x02
+#define MAX44000_CFG_MASK               0x1c
+#define MAX44000_CFG_MODE_SHUTDOWN      0x00
+#define MAX44000_CFG_MODE_ALS_GIR       0x04
+#define MAX44000_CFG_MODE_ALS_G         0x08
+#define MAX44000_CFG_MODE_ALS_IR        0x0c
+#define MAX44000_CFG_MODE_ALS_PRX       0x10
+#define MAX44000_CFG_MODE_PRX           0x14
+#define MAX44000_CFG_TRIM               0x20
+
+/*
+ * Upper 4 bits are not documented but start as 1 on powerup
+ * Setting them to 0 causes proximity to misbehave so set them to 1
+ */
+#define MAX44000_REG_CFG_RX_DEFAULT 0xf0
+
+/* REG_RX bits */
+#define MAX44000_CFG_RX_ALSTIM_MASK	0x0c
+#define MAX44000_CFG_RX_ALSTIM_SHIFT	2
+#define MAX44000_CFG_RX_ALSPGA_MASK	0x03
+#define MAX44000_CFG_RX_ALSPGA_SHIFT	0
+
+/* REG_TX bits */
+#define MAX44000_LED_CURRENT_MASK	0xf
+#define MAX44000_LED_CURRENT_MAX	11
+#define MAX44000_LED_CURRENT_DEFAULT	6
+
+#define MAX44000_ALSDATA_OVERFLOW	0x4000
+
+struct max44000_data {
+	struct mutex lock;
+	struct regmap *regmap;
+};
+
+/* Default scale is set to the minimum of 0.03125 or 1 / (1 << 5) lux */
+#define MAX44000_ALS_TO_LUX_DEFAULT_FRACTION_LOG2 5
+
+/* Scale can be multiplied by up to 128x via ALSPGA for measurement gain */
+static const int max44000_alspga_shift[] = {0, 2, 4, 7};
+#define MAX44000_ALSPGA_MAX_SHIFT 7
+
+/*
+ * Scale can be multiplied by up to 64x via ALSTIM because of lost resolution
+ *
+ * This scaling factor is hidden from userspace and instead accounted for when
+ * reading raw values from the device.
+ *
+ * This makes it possible to cleanly expose ALSPGA as IIO_CHAN_INFO_SCALE and
+ * ALSTIM as IIO_CHAN_INFO_INT_TIME without the values affecting each other.
+ *
+ * Handling this internally is also required for buffer support because the
+ * channel's scan_type can't be modified dynamically.
+ */
+static const int max44000_alstim_shift[] = {0, 2, 4, 6};
+#define MAX44000_ALSTIM_SHIFT(alstim) (2 * (alstim))
+
+/* Available integration times with pretty manual alignment: */
+static const int max44000_int_time_avail_ns_array[] = {
+	   100000000,
+	    25000000,
+	     6250000,
+	     1562500,
+};
+static const char max44000_int_time_avail_str[] =
+	"0.100 "
+	"0.025 "
+	"0.00625 "
+	"0.001625";
+
+/* Available scales (internal to ulux) with pretty manual alignment: */
+static const int max44000_scale_avail_ulux_array[] = {
+	    31250,
+	   125000,
+	   500000,
+	  4000000,
+};
+static const char max44000_scale_avail_str[] =
+	"0.03125 "
+	"0.125 "
+	"0.5 "
+	 "4";
+
+#define MAX44000_SCAN_INDEX_ALS 0
+#define MAX44000_SCAN_INDEX_PRX 1
+
+static const struct iio_chan_spec max44000_channels[] = {
+	{
+		.type = IIO_LIGHT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |
+					    BIT(IIO_CHAN_INFO_INT_TIME),
+		.scan_index = MAX44000_SCAN_INDEX_ALS,
+		.scan_type = {
+			.sign		= 'u',
+			.realbits	= 14,
+			.storagebits	= 16,
+		}
+	},
+	{
+		.type = IIO_PROXIMITY,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.scan_index = MAX44000_SCAN_INDEX_PRX,
+		.scan_type = {
+			.sign		= 'u',
+			.realbits	= 8,
+			.storagebits	= 16,
+		}
+	},
+	IIO_CHAN_SOFT_TIMESTAMP(2),
+	{
+		.type = IIO_CURRENT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+				      BIT(IIO_CHAN_INFO_SCALE),
+		.extend_name = "led",
+		.output = 1,
+		.scan_index = -1,
+	},
+};
+
+static int max44000_read_alstim(struct max44000_data *data)
+{
+	unsigned int val;
+	int ret;
+
+	ret = regmap_read(data->regmap, MAX44000_REG_CFG_RX, &val);
+	if (ret < 0)
+		return ret;
+	return (val & MAX44000_CFG_RX_ALSTIM_MASK) >> MAX44000_CFG_RX_ALSTIM_SHIFT;
+}
+
+static int max44000_write_alstim(struct max44000_data *data, int val)
+{
+	return regmap_write_bits(data->regmap, MAX44000_REG_CFG_RX,
+				 MAX44000_CFG_RX_ALSTIM_MASK,
+				 val << MAX44000_CFG_RX_ALSTIM_SHIFT);
+}
+
+static int max44000_read_alspga(struct max44000_data *data)
+{
+	unsigned int val;
+	int ret;
+
+	ret = regmap_read(data->regmap, MAX44000_REG_CFG_RX, &val);
+	if (ret < 0)
+		return ret;
+	return (val & MAX44000_CFG_RX_ALSPGA_MASK) >> MAX44000_CFG_RX_ALSPGA_SHIFT;
+}
+
+static int max44000_write_alspga(struct max44000_data *data, int val)
+{
+	return regmap_write_bits(data->regmap, MAX44000_REG_CFG_RX,
+				 MAX44000_CFG_RX_ALSPGA_MASK,
+				 val << MAX44000_CFG_RX_ALSPGA_SHIFT);
+}
+
+static int max44000_read_alsval(struct max44000_data *data)
+{
+	u16 regval;
+	int alstim, ret;
+
+	ret = regmap_bulk_read(data->regmap, MAX44000_REG_ALS_DATA_HI,
+			       &regval, sizeof(regval));
+	if (ret < 0)
+		return ret;
+	alstim = ret = max44000_read_alstim(data);
+	if (ret < 0)
+		return ret;
+
+	regval = be16_to_cpu(regval);
+
+	/*
+	 * Overflow is explained on datasheet page 17.
+	 *
+	 * It's a warning that either the G or IR channel has become saturated
+	 * and that the value in the register is likely incorrect.
+	 *
+	 * The recommendation is to change the scale (ALSPGA).
+	 * The driver just returns the max representable value.
+	 */
+	if (regval & MAX44000_ALSDATA_OVERFLOW)
+		return 0x3FFF;
+
+	return regval << MAX44000_ALSTIM_SHIFT(alstim);
+}
+
+static int max44000_write_led_current_raw(struct max44000_data *data, int val)
+{
+	/* Maybe we should clamp the value instead? */
+	if (val < 0 || val > MAX44000_LED_CURRENT_MAX)
+		return -ERANGE;
+	if (val >= 8)
+		val += 4;
+	return regmap_write_bits(data->regmap, MAX44000_REG_CFG_TX,
+				 MAX44000_LED_CURRENT_MASK, val);
+}
+
+static int max44000_read_led_current_raw(struct max44000_data *data)
+{
+	unsigned int regval;
+	int ret;
+
+	ret = regmap_read(data->regmap, MAX44000_REG_CFG_TX, &regval);
+	if (ret < 0)
+		return ret;
+	regval &= MAX44000_LED_CURRENT_MASK;
+	if (regval >= 8)
+		regval -= 4;
+	return regval;
+}
+
+static int max44000_read_raw(struct iio_dev *indio_dev,
+			     struct iio_chan_spec const *chan,
+			     int *val, int *val2, long mask)
+{
+	struct max44000_data *data = iio_priv(indio_dev);
+	int alstim, alspga;
+	unsigned int regval;
+	int ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		switch (chan->type) {
+		case IIO_LIGHT:
+			mutex_lock(&data->lock);
+			ret = max44000_read_alsval(data);
+			mutex_unlock(&data->lock);
+			if (ret < 0)
+				return ret;
+			*val = ret;
+			return IIO_VAL_INT;
+
+		case IIO_PROXIMITY:
+			mutex_lock(&data->lock);
+			ret = regmap_read(data->regmap, MAX44000_REG_PRX_DATA, &regval);
+			mutex_unlock(&data->lock);
+			if (ret < 0)
+				return ret;
+			*val = regval;
+			return IIO_VAL_INT;
+
+		case IIO_CURRENT:
+			mutex_lock(&data->lock);
+			ret = max44000_read_led_current_raw(data);
+			mutex_unlock(&data->lock);
+			if (ret < 0)
+				return ret;
+			*val = ret;
+			return IIO_VAL_INT;
+
+		default:
+			return -EINVAL;
+		}
+
+	case IIO_CHAN_INFO_SCALE:
+		switch (chan->type) {
+		case IIO_CURRENT:
+			/* Output register is in 10s of miliamps */
+			*val = 10;
+			return IIO_VAL_INT;
+
+		case IIO_LIGHT:
+			mutex_lock(&data->lock);
+			alspga = ret = max44000_read_alspga(data);
+			mutex_unlock(&data->lock);
+			if (ret < 0)
+				return ret;
+
+			/* Avoid negative shifts */
+			*val = (1 << MAX44000_ALSPGA_MAX_SHIFT);
+			*val2 = MAX44000_ALS_TO_LUX_DEFAULT_FRACTION_LOG2
+					+ MAX44000_ALSPGA_MAX_SHIFT
+					- max44000_alspga_shift[alspga];
+			return IIO_VAL_FRACTIONAL_LOG2;
+
+		default:
+			return -EINVAL;
+		}
+
+	case IIO_CHAN_INFO_INT_TIME:
+		mutex_lock(&data->lock);
+		alstim = ret = max44000_read_alstim(data);
+		mutex_unlock(&data->lock);
+
+		if (ret < 0)
+			return ret;
+		*val = 0;
+		*val2 = max44000_int_time_avail_ns_array[alstim];
+		return IIO_VAL_INT_PLUS_NANO;
+
+	default:
+		return -EINVAL;
+	}
+}
+
+static int max44000_write_raw(struct iio_dev *indio_dev,
+			      struct iio_chan_spec const *chan,
+			      int val, int val2, long mask)
+{
+	struct max44000_data *data = iio_priv(indio_dev);
+	int ret;
+
+	if (mask == IIO_CHAN_INFO_RAW && chan->type == IIO_CURRENT) {
+		mutex_lock(&data->lock);
+		ret = max44000_write_led_current_raw(data, val);
+		mutex_unlock(&data->lock);
+		return ret;
+	} else if (mask == IIO_CHAN_INFO_INT_TIME && chan->type == IIO_LIGHT) {
+		s64 valns = val * NSEC_PER_SEC + val2;
+		int alstim = find_closest_descending(valns,
+				max44000_int_time_avail_ns_array,
+				ARRAY_SIZE(max44000_int_time_avail_ns_array));
+		mutex_lock(&data->lock);
+		ret = max44000_write_alstim(data, alstim);
+		mutex_unlock(&data->lock);
+		return ret;
+	} else if (mask == IIO_CHAN_INFO_SCALE && chan->type == IIO_LIGHT) {
+		s64 valus = val * USEC_PER_SEC + val2;
+		int alspga = find_closest(valus,
+				max44000_scale_avail_ulux_array,
+				ARRAY_SIZE(max44000_scale_avail_ulux_array));
+		mutex_lock(&data->lock);
+		ret = max44000_write_alspga(data, alspga);
+		mutex_unlock(&data->lock);
+		return ret;
+	}
+
+	return -EINVAL;
+}
+
+static int max44000_write_raw_get_fmt(struct iio_dev *indio_dev,
+				      struct iio_chan_spec const *chan,
+				      long mask)
+{
+	if (mask == IIO_CHAN_INFO_INT_TIME && chan->type == IIO_LIGHT)
+		return IIO_VAL_INT_PLUS_NANO;
+	else if (mask == IIO_CHAN_INFO_SCALE && chan->type == IIO_LIGHT)
+		return IIO_VAL_INT_PLUS_MICRO;
+	else
+		return IIO_VAL_INT;
+}
+
+static IIO_CONST_ATTR(illuminance_integration_time_available, max44000_int_time_avail_str);
+static IIO_CONST_ATTR(illuminance_scale_available, max44000_scale_avail_str);
+
+static struct attribute *max44000_attributes[] = {
+	&iio_const_attr_illuminance_integration_time_available.dev_attr.attr,
+	&iio_const_attr_illuminance_scale_available.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group max44000_attribute_group = {
+	.attrs = max44000_attributes,
+};
+
+static const struct iio_info max44000_info = {
+	.driver_module		= THIS_MODULE,
+	.read_raw		= max44000_read_raw,
+	.write_raw		= max44000_write_raw,
+	.write_raw_get_fmt	= max44000_write_raw_get_fmt,
+	.attrs			= &max44000_attribute_group,
+};
+
+static bool max44000_readable_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case MAX44000_REG_STATUS:
+	case MAX44000_REG_CFG_MAIN:
+	case MAX44000_REG_CFG_RX:
+	case MAX44000_REG_CFG_TX:
+	case MAX44000_REG_ALS_DATA_HI:
+	case MAX44000_REG_ALS_DATA_LO:
+	case MAX44000_REG_PRX_DATA:
+	case MAX44000_REG_ALS_UPTHR_HI:
+	case MAX44000_REG_ALS_UPTHR_LO:
+	case MAX44000_REG_ALS_LOTHR_HI:
+	case MAX44000_REG_ALS_LOTHR_LO:
+	case MAX44000_REG_PST:
+	case MAX44000_REG_PRX_IND:
+	case MAX44000_REG_PRX_THR:
+	case MAX44000_REG_TRIM_GAIN_GREEN:
+	case MAX44000_REG_TRIM_GAIN_IR:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool max44000_writeable_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case MAX44000_REG_CFG_MAIN:
+	case MAX44000_REG_CFG_RX:
+	case MAX44000_REG_CFG_TX:
+	case MAX44000_REG_ALS_UPTHR_HI:
+	case MAX44000_REG_ALS_UPTHR_LO:
+	case MAX44000_REG_ALS_LOTHR_HI:
+	case MAX44000_REG_ALS_LOTHR_LO:
+	case MAX44000_REG_PST:
+	case MAX44000_REG_PRX_IND:
+	case MAX44000_REG_PRX_THR:
+	case MAX44000_REG_TRIM_GAIN_GREEN:
+	case MAX44000_REG_TRIM_GAIN_IR:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool max44000_volatile_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case MAX44000_REG_STATUS:
+	case MAX44000_REG_ALS_DATA_HI:
+	case MAX44000_REG_ALS_DATA_LO:
+	case MAX44000_REG_PRX_DATA:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool max44000_precious_reg(struct device *dev, unsigned int reg)
+{
+	return reg == MAX44000_REG_STATUS;
+}
+
+static const struct regmap_config max44000_regmap_config = {
+	.reg_bits	= 8,
+	.val_bits	= 8,
+
+	.max_register	= MAX44000_REG_PRX_DATA,
+	.readable_reg	= max44000_readable_reg,
+	.writeable_reg	= max44000_writeable_reg,
+	.volatile_reg	= max44000_volatile_reg,
+	.precious_reg	= max44000_precious_reg,
+
+	.use_single_rw	= 1,
+	.cache_type	= REGCACHE_RBTREE,
+};
+
+static irqreturn_t max44000_trigger_handler(int irq, void *p)
+{
+	struct iio_poll_func *pf = p;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct max44000_data *data = iio_priv(indio_dev);
+	u16 buf[8]; /* 2x u16 + padding + 8 bytes timestamp */
+	int index = 0;
+	unsigned int regval;
+	int ret;
+
+	mutex_lock(&data->lock);
+	if (test_bit(MAX44000_SCAN_INDEX_ALS, indio_dev->active_scan_mask)) {
+		ret = max44000_read_alsval(data);
+		if (ret < 0)
+			goto out_unlock;
+		buf[index++] = ret;
+	}
+	if (test_bit(MAX44000_SCAN_INDEX_PRX, indio_dev->active_scan_mask)) {
+		ret = regmap_read(data->regmap, MAX44000_REG_PRX_DATA, &regval);
+		if (ret < 0)
+			goto out_unlock;
+		buf[index] = regval;
+	}
+	mutex_unlock(&data->lock);
+
+	iio_push_to_buffers_with_timestamp(indio_dev, buf, iio_get_time_ns());
+	iio_trigger_notify_done(indio_dev->trig);
+	return IRQ_HANDLED;
+
+out_unlock:
+	mutex_unlock(&data->lock);
+	iio_trigger_notify_done(indio_dev->trig);
+	return IRQ_HANDLED;
+}
+
+static int max44000_probe(struct i2c_client *client,
+			  const struct i2c_device_id *id)
+{
+	struct max44000_data *data;
+	struct iio_dev *indio_dev;
+	int ret, reg;
+
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+	if (!indio_dev)
+		return -ENOMEM;
+	data = iio_priv(indio_dev);
+	data->regmap = devm_regmap_init_i2c(client, &max44000_regmap_config);
+	if (IS_ERR(data->regmap)) {
+		dev_err(&client->dev, "regmap_init failed!\n");
+		return PTR_ERR(data->regmap);
+	}
+
+	i2c_set_clientdata(client, indio_dev);
+	mutex_init(&data->lock);
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->info = &max44000_info;
+	indio_dev->name = MAX44000_DRV_NAME;
+	indio_dev->channels = max44000_channels;
+	indio_dev->num_channels = ARRAY_SIZE(max44000_channels);
+
+	/*
+	 * The device doesn't have a reset function so we just clear some
+	 * important bits at probe time to ensure sane operation.
+	 *
+	 * Since we don't support interrupts/events the threshold values are
+	 * not important. We also don't touch trim values.
+	 */
+
+	/* Reset ALS scaling bits */
+	ret = regmap_write(data->regmap, MAX44000_REG_CFG_RX,
+			   MAX44000_REG_CFG_RX_DEFAULT);
+	if (ret < 0) {
+		dev_err(&client->dev, "failed to write default CFG_RX: %d\n",
+			ret);
+		return ret;
+	}
+
+	/*
+	 * By default the LED pulse used for the proximity sensor is disabled.
+	 * Set a middle value so that we get some sort of valid data by default.
+	 */
+	ret = max44000_write_led_current_raw(data, MAX44000_LED_CURRENT_DEFAULT);
+	if (ret < 0) {
+		dev_err(&client->dev, "failed to write init config: %d\n", ret);
+		return ret;
+	}
+
+	/* Reset CFG bits to ALS_PRX mode which allows easy reading of both values. */
+	reg = MAX44000_CFG_TRIM | MAX44000_CFG_MODE_ALS_PRX;
+	ret = regmap_write(data->regmap, MAX44000_REG_CFG_MAIN, reg);
+	if (ret < 0) {
+		dev_err(&client->dev, "failed to write init config: %d\n", ret);
+		return ret;
+	}
+
+	/* Read status at least once to clear any stale interrupt bits. */
+	ret = regmap_read(data->regmap, MAX44000_REG_STATUS, &reg);
+	if (ret < 0) {
+		dev_err(&client->dev, "failed to read init status: %d\n", ret);
+		return ret;
+	}
+
+	ret = iio_triggered_buffer_setup(indio_dev, NULL, max44000_trigger_handler, NULL);
+	if (ret < 0) {
+		dev_err(&client->dev, "iio triggered buffer setup failed\n");
+		return ret;
+	}
+
+	return iio_device_register(indio_dev);
+}
+
+static int max44000_remove(struct i2c_client *client)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+
+	iio_device_unregister(indio_dev);
+	iio_triggered_buffer_cleanup(indio_dev);
+
+	return 0;
+}
+
+static const struct i2c_device_id max44000_id[] = {
+	{"max44000", 0},
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, max44000_id);
+
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id max44000_acpi_match[] = {
+	{"MAX44000", 0},
+	{ }
+};
+MODULE_DEVICE_TABLE(acpi, max44000_acpi_match);
+#endif
+
+static struct i2c_driver max44000_driver = {
+	.driver = {
+		.name	= MAX44000_DRV_NAME,
+		.acpi_match_table = ACPI_PTR(max44000_acpi_match),
+	},
+	.probe		= max44000_probe,
+	.remove		= max44000_remove,
+	.id_table	= max44000_id,
+};
+
+module_i2c_driver(max44000_driver);
+
+MODULE_AUTHOR("Crestez Dan Leonard <leonard.crestez@intel.com>");
+MODULE_DESCRIPTION("MAX44000 Ambient and Infrared Proximity Sensor");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/light/stk3310.c linux-libre-4.7-gnu/drivers/iio/light/stk3310.c
--- linux-libre-4.6-gnu/drivers/iio/light/stk3310.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/light/stk3310.c	2016-07-24 15:23:50.000000000 -0400
@@ -16,7 +16,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/regmap.h>
-#include <linux/gpio/consumer.h>
 #include <linux/iio/events.h>
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/light/tsl2563.c linux-libre-4.7-gnu/drivers/iio/light/tsl2563.c
--- linux-libre-4.6-gnu/drivers/iio/light/tsl2563.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/light/tsl2563.c	2016-07-24 15:23:50.000000000 -0400
@@ -806,8 +806,7 @@ static int tsl2563_probe(struct i2c_clie
 	return 0;
 
 fail:
-	cancel_delayed_work(&chip->poweroff_work);
-	flush_scheduled_work();
+	cancel_delayed_work_sync(&chip->poweroff_work);
 	return err;
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/light/veml6070.c linux-libre-4.7-gnu/drivers/iio/light/veml6070.c
--- linux-libre-4.6-gnu/drivers/iio/light/veml6070.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/iio/light/veml6070.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,218 @@
+/*
+ * veml6070.c - Support for Vishay VEML6070 UV A light sensor
+ *
+ * Copyright 2016 Peter Meerwald-Stadler <pmeerw@pmeerw.net>
+ *
+ * This file is subject to the terms and conditions of version 2 of
+ * the GNU General Public License.  See the file COPYING in the main
+ * directory of this archive for more details.
+ *
+ * IIO driver for VEML6070 (7-bit I2C slave addresses 0x38 and 0x39)
+ *
+ * TODO: integration time, ACK signal
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+
+#define VEML6070_DRV_NAME "veml6070"
+
+#define VEML6070_ADDR_CONFIG_DATA_MSB 0x38 /* read: MSB data, write: config */
+#define VEML6070_ADDR_DATA_LSB	0x39 /* LSB data */
+
+#define VEML6070_COMMAND_ACK	BIT(5) /* raise interrupt when over threshold */
+#define VEML6070_COMMAND_IT	GENMASK(3, 2) /* bit mask integration time */
+#define VEML6070_COMMAND_RSRVD	BIT(1) /* reserved, set to 1 */
+#define VEML6070_COMMAND_SD	BIT(0) /* shutdown mode when set */
+
+#define VEML6070_IT_10	0x04 /* integration time 1x */
+
+struct veml6070_data {
+	struct i2c_client *client1;
+	struct i2c_client *client2;
+	u8 config;
+	struct mutex lock;
+};
+
+static int veml6070_read(struct veml6070_data *data)
+{
+	int ret;
+	u8 msb, lsb;
+
+	mutex_lock(&data->lock);
+
+	/* disable shutdown */
+	ret = i2c_smbus_write_byte(data->client1,
+	    data->config & ~VEML6070_COMMAND_SD);
+	if (ret < 0)
+		goto out;
+
+	msleep(125 + 10); /* measurement takes up to 125 ms for IT 1x */
+
+	ret = i2c_smbus_read_byte(data->client2); /* read MSB, address 0x39 */
+	if (ret < 0)
+		goto out;
+	msb = ret;
+
+	ret = i2c_smbus_read_byte(data->client1); /* read LSB, address 0x38 */
+	if (ret < 0)
+		goto out;
+	lsb = ret;
+
+	/* shutdown again */
+	ret = i2c_smbus_write_byte(data->client1, data->config);
+	if (ret < 0)
+		goto out;
+
+	ret = (msb << 8) | lsb;
+
+out:
+	mutex_unlock(&data->lock);
+	return ret;
+}
+
+static const struct iio_chan_spec veml6070_channels[] = {
+	{
+		.type = IIO_INTENSITY,
+		.modified = 1,
+		.channel2 = IIO_MOD_LIGHT_UV,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+	},
+	{
+		.type = IIO_UVINDEX,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+	}
+};
+
+static int veml6070_to_uv_index(unsigned val)
+{
+	/*
+	 * conversion of raw UV intensity values to UV index depends on
+	 * integration time (IT) and value of the resistor connected to
+	 * the RSET pin (default: 270 KOhm)
+	 */
+	unsigned uvi[11] = {
+		187, 373, 560, /* low */
+		746, 933, 1120, /* moderate */
+		1308, 1494, /* high */
+		1681, 1868, 2054}; /* very high */
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(uvi); i++)
+		if (val <= uvi[i])
+			return i;
+
+	return 11; /* extreme */
+}
+
+static int veml6070_read_raw(struct iio_dev *indio_dev,
+				struct iio_chan_spec const *chan,
+				int *val, int *val2, long mask)
+{
+	struct veml6070_data *data = iio_priv(indio_dev);
+	int ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+	case IIO_CHAN_INFO_PROCESSED:
+		ret = veml6070_read(data);
+		if (ret < 0)
+			return ret;
+		if (mask == IIO_CHAN_INFO_PROCESSED)
+			*val = veml6070_to_uv_index(ret);
+		else
+			*val = ret;
+		return IIO_VAL_INT;
+	default:
+		return -EINVAL;
+	}
+}
+
+static const struct iio_info veml6070_info = {
+	.read_raw = veml6070_read_raw,
+	.driver_module = THIS_MODULE,
+};
+
+static int veml6070_probe(struct i2c_client *client,
+			  const struct i2c_device_id *id)
+{
+	struct veml6070_data *data;
+	struct iio_dev *indio_dev;
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	data = iio_priv(indio_dev);
+	i2c_set_clientdata(client, indio_dev);
+	data->client1 = client;
+	mutex_init(&data->lock);
+
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->info = &veml6070_info;
+	indio_dev->channels = veml6070_channels;
+	indio_dev->num_channels = ARRAY_SIZE(veml6070_channels);
+	indio_dev->name = VEML6070_DRV_NAME;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	data->client2 = i2c_new_dummy(client->adapter, VEML6070_ADDR_DATA_LSB);
+	if (!data->client2) {
+		dev_err(&client->dev, "i2c device for second chip address failed\n");
+		return -ENODEV;
+	}
+
+	data->config = VEML6070_IT_10 | VEML6070_COMMAND_RSRVD |
+		VEML6070_COMMAND_SD;
+	ret = i2c_smbus_write_byte(data->client1, data->config);
+	if (ret < 0)
+		goto fail;
+
+	ret = iio_device_register(indio_dev);
+	if (ret < 0)
+		goto fail;
+
+	return ret;
+
+fail:
+	i2c_unregister_device(data->client2);
+	return ret;
+}
+
+static int veml6070_remove(struct i2c_client *client)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+	struct veml6070_data *data = iio_priv(indio_dev);
+
+	iio_device_unregister(indio_dev);
+	i2c_unregister_device(data->client2);
+
+	return 0;
+}
+
+static const struct i2c_device_id veml6070_id[] = {
+	{ "veml6070", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, veml6070_id);
+
+static struct i2c_driver veml6070_driver = {
+	.driver = {
+		.name   = VEML6070_DRV_NAME,
+	},
+	.probe  = veml6070_probe,
+	.remove  = veml6070_remove,
+	.id_table = veml6070_id,
+};
+
+module_i2c_driver(veml6070_driver);
+
+MODULE_AUTHOR("Peter Meerwald-Stadler <pmeerw@pmeerw.net>");
+MODULE_DESCRIPTION("Vishay VEML6070 UV A light sensor driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/magnetometer/ak8975.c linux-libre-4.7-gnu/drivers/iio/magnetometer/ak8975.c
--- linux-libre-4.6-gnu/drivers/iio/magnetometer/ak8975.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/magnetometer/ak8975.c	2016-07-24 15:23:50.000000000 -0400
@@ -32,9 +32,17 @@
 #include <linux/gpio.h>
 #include <linux/of_gpio.h>
 #include <linux/acpi.h>
+#include <linux/regulator/consumer.h>
 
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+
+#include <linux/iio/magnetometer/ak8975.h>
+
 /*
  * Register definitions, as well as various shifts and masks to get at the
  * individual fields of the registers.
@@ -361,7 +369,6 @@ static const struct ak_def ak_def_array[
 struct ak8975_data {
 	struct i2c_client	*client;
 	const struct ak_def	*def;
-	struct attribute_group	attrs;
 	struct mutex		lock;
 	u8			asa[3];
 	long			raw_to_gauss[3];
@@ -370,8 +377,41 @@ struct ak8975_data {
 	wait_queue_head_t	data_ready_queue;
 	unsigned long		flags;
 	u8			cntl_cache;
+	struct iio_mount_matrix orientation;
+	struct regulator	*vdd;
 };
 
+/* Enable attached power regulator if any. */
+static int ak8975_power_on(struct i2c_client *client)
+{
+	const struct iio_dev *indio_dev = i2c_get_clientdata(client);
+	struct ak8975_data *data = iio_priv(indio_dev);
+	int ret;
+
+	data->vdd = devm_regulator_get(&client->dev, "vdd");
+	if (IS_ERR_OR_NULL(data->vdd)) {
+		ret = PTR_ERR(data->vdd);
+		if (ret == -ENODEV)
+			ret = 0;
+	} else {
+		ret = regulator_enable(data->vdd);
+	}
+
+	if (ret)
+		dev_err(&client->dev, "failed to enable Vdd supply: %d\n", ret);
+	return ret;
+}
+
+/* Disable attached power regulator if any. */
+static void ak8975_power_off(const struct i2c_client *client)
+{
+	const struct iio_dev *indio_dev = i2c_get_clientdata(client);
+	const struct ak8975_data *data = iio_priv(indio_dev);
+
+	if (!IS_ERR_OR_NULL(data->vdd))
+		regulator_disable(data->vdd);
+}
+
 /*
  * Return 0 if the i2c device is the one we expect.
  * return a negative error number otherwise
@@ -601,22 +641,15 @@ static int wait_conversion_complete_inte
 	return ret > 0 ? 0 : -ETIME;
 }
 
-/*
- * Emits the raw flux value for the x, y, or z axis.
- */
-static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val)
+static int ak8975_start_read_axis(struct ak8975_data *data,
+				  const struct i2c_client *client)
 {
-	struct ak8975_data *data = iio_priv(indio_dev);
-	struct i2c_client *client = data->client;
-	int ret;
-
-	mutex_lock(&data->lock);
-
 	/* Set up the device for taking a sample. */
-	ret = ak8975_set_mode(data, MODE_ONCE);
+	int ret = ak8975_set_mode(data, MODE_ONCE);
+
 	if (ret < 0) {
 		dev_err(&client->dev, "Error in setting operating mode\n");
-		goto exit;
+		return ret;
 	}
 
 	/* Wait for the conversion to complete. */
@@ -627,7 +660,7 @@ static int ak8975_read_axis(struct iio_d
 	else
 		ret = wait_conversion_complete_polled(data);
 	if (ret < 0)
-		goto exit;
+		return ret;
 
 	/* This will be executed only for non-interrupt based waiting case */
 	if (ret & data->def->ctrl_masks[ST1_DRDY]) {
@@ -635,32 +668,45 @@ static int ak8975_read_axis(struct iio_d
 					       data->def->ctrl_regs[ST2]);
 		if (ret < 0) {
 			dev_err(&client->dev, "Error in reading ST2\n");
-			goto exit;
+			return ret;
 		}
 		if (ret & (data->def->ctrl_masks[ST2_DERR] |
 			   data->def->ctrl_masks[ST2_HOFL])) {
 			dev_err(&client->dev, "ST2 status error 0x%x\n", ret);
-			ret = -EINVAL;
-			goto exit;
+			return -EINVAL;
 		}
 	}
 
-	/* Read the flux value from the appropriate register
-	   (the register is specified in the iio device attributes). */
-	ret = i2c_smbus_read_word_data(client, data->def->data_regs[index]);
-	if (ret < 0) {
-		dev_err(&client->dev, "Read axis data fails\n");
+	return 0;
+}
+
+/* Retrieve raw flux value for one of the x, y, or z axis.  */
+static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val)
+{
+	struct ak8975_data *data = iio_priv(indio_dev);
+	const struct i2c_client *client = data->client;
+	const struct ak_def *def = data->def;
+	int ret;
+
+	mutex_lock(&data->lock);
+
+	ret = ak8975_start_read_axis(data, client);
+	if (ret)
+		goto exit;
+
+	ret = i2c_smbus_read_word_data(client, def->data_regs[index]);
+	if (ret < 0)
 		goto exit;
-	}
 
 	mutex_unlock(&data->lock);
 
 	/* Clamp to valid range. */
-	*val = clamp_t(s16, ret, -data->def->range, data->def->range);
+	*val = clamp_t(s16, ret, -def->range, def->range);
 	return IIO_VAL_INT;
 
 exit:
 	mutex_unlock(&data->lock);
+	dev_err(&client->dev, "Error in reading axis\n");
 	return ret;
 }
 
@@ -682,6 +728,18 @@ static int ak8975_read_raw(struct iio_de
 	return -EINVAL;
 }
 
+static const struct iio_mount_matrix *
+ak8975_get_mount_matrix(const struct iio_dev *indio_dev,
+			const struct iio_chan_spec *chan)
+{
+	return &((struct ak8975_data *)iio_priv(indio_dev))->orientation;
+}
+
+static const struct iio_chan_spec_ext_info ak8975_ext_info[] = {
+	IIO_MOUNT_MATRIX(IIO_SHARED_BY_DIR, ak8975_get_mount_matrix),
+	{ },
+};
+
 #define AK8975_CHANNEL(axis, index)					\
 	{								\
 		.type = IIO_MAGN,					\
@@ -690,12 +748,23 @@ static int ak8975_read_raw(struct iio_de
 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |		\
 			     BIT(IIO_CHAN_INFO_SCALE),			\
 		.address = index,					\
+		.scan_index = index,					\
+		.scan_type = {						\
+			.sign = 's',					\
+			.realbits = 16,					\
+			.storagebits = 16,				\
+			.endianness = IIO_CPU				\
+		},							\
+		.ext_info = ak8975_ext_info,				\
 	}
 
 static const struct iio_chan_spec ak8975_channels[] = {
 	AK8975_CHANNEL(X, 0), AK8975_CHANNEL(Y, 1), AK8975_CHANNEL(Z, 2),
+	IIO_CHAN_SOFT_TIMESTAMP(3),
 };
 
+static const unsigned long ak8975_scan_masks[] = { 0x7, 0 };
+
 static const struct iio_info ak8975_info = {
 	.read_raw = &ak8975_read_raw,
 	.driver_module = THIS_MODULE,
@@ -724,6 +793,56 @@ static const char *ak8975_match_acpi_dev
 	return dev_name(dev);
 }
 
+static void ak8975_fill_buffer(struct iio_dev *indio_dev)
+{
+	struct ak8975_data *data = iio_priv(indio_dev);
+	const struct i2c_client *client = data->client;
+	const struct ak_def *def = data->def;
+	int ret;
+	s16 buff[8]; /* 3 x 16 bits axis values + 1 aligned 64 bits timestamp */
+
+	mutex_lock(&data->lock);
+
+	ret = ak8975_start_read_axis(data, client);
+	if (ret)
+		goto unlock;
+
+	/*
+	 * For each axis, read the flux value from the appropriate register
+	 * (the register is specified in the iio device attributes).
+	 */
+	ret = i2c_smbus_read_i2c_block_data_or_emulated(client,
+							def->data_regs[0],
+							3 * sizeof(buff[0]),
+							(u8 *)buff);
+	if (ret < 0)
+		goto unlock;
+
+	mutex_unlock(&data->lock);
+
+	/* Clamp to valid range. */
+	buff[0] = clamp_t(s16, le16_to_cpu(buff[0]), -def->range, def->range);
+	buff[1] = clamp_t(s16, le16_to_cpu(buff[1]), -def->range, def->range);
+	buff[2] = clamp_t(s16, le16_to_cpu(buff[2]), -def->range, def->range);
+
+	iio_push_to_buffers_with_timestamp(indio_dev, buff, iio_get_time_ns());
+	return;
+
+unlock:
+	mutex_unlock(&data->lock);
+	dev_err(&client->dev, "Error in reading axes block\n");
+}
+
+static irqreturn_t ak8975_handle_trigger(int irq, void *p)
+{
+	const struct iio_poll_func *pf = p;
+	struct iio_dev *indio_dev = pf->indio_dev;
+
+	ak8975_fill_buffer(indio_dev);
+	iio_trigger_notify_done(indio_dev->trig);
+	return IRQ_HANDLED;
+}
+
 static int ak8975_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
@@ -733,10 +852,12 @@ static int ak8975_probe(struct i2c_clien
 	int err;
 	const char *name = NULL;
 	enum asahi_compass_chipset chipset = AK_MAX_TYPE;
+	const struct ak8975_platform_data *pdata =
+		dev_get_platdata(&client->dev);
 
 	/* Grab and set up the supplied GPIO. */
-	if (client->dev.platform_data)
-		eoc_gpio = *(int *)(client->dev.platform_data);
+	if (pdata)
+		eoc_gpio = pdata->eoc_gpio;
 	else if (client->dev.of_node)
 		eoc_gpio = of_get_gpio(client->dev.of_node, 0);
 	else
@@ -770,13 +891,24 @@ static int ak8975_probe(struct i2c_clien
 	data->eoc_gpio = eoc_gpio;
 	data->eoc_irq = 0;
 
+	if (!pdata) {
+		err = of_iio_read_mount_matrix(&client->dev,
+					       "mount-matrix",
+					       &data->orientation);
+		if (err)
+			return err;
+	} else
+		data->orientation = pdata->orientation;
+
 	/* id will be NULL when enumerated via ACPI */
 	if (id) {
 		chipset = (enum asahi_compass_chipset)(id->driver_data);
 		name = id->name;
-	} else if (ACPI_HANDLE(&client->dev))
+	} else if (ACPI_HANDLE(&client->dev)) {
 		name = ak8975_match_acpi_device(&client->dev, &chipset);
-	else
+		if (!name)
+			return -ENODEV;
+	} else
 		return -ENOSYS;
 
 	if (chipset >= AK_MAX_TYPE) {
@@ -786,10 +918,15 @@ static int ak8975_probe(struct i2c_clien
 	}
 
 	data->def = &ak_def_array[chipset];
+
+	err = ak8975_power_on(client);
+	if (err)
+		return err;
+
 	err = ak8975_who_i_am(client, data->def->type);
 	if (err < 0) {
 		dev_err(&client->dev, "Unexpected device\n");
-		return err;
+		goto power_off;
 	}
 	dev_dbg(&client->dev, "Asahi compass chip %s\n", name);
 
@@ -797,7 +934,7 @@ static int ak8975_probe(struct i2c_clien
 	err = ak8975_setup(client);
 	if (err < 0) {
 		dev_err(&client->dev, "%s initialization fails\n", name);
-		return err;
+		goto power_off;
 	}
 
 	mutex_init(&data->lock);
@@ -805,9 +942,41 @@ static int ak8975_probe(struct i2c_clien
 	indio_dev->channels = ak8975_channels;
 	indio_dev->num_channels = ARRAY_SIZE(ak8975_channels);
 	indio_dev->info = &ak8975_info;
+	indio_dev->available_scan_masks = ak8975_scan_masks;
 	indio_dev->modes = INDIO_DIRECT_MODE;
 	indio_dev->name = name;
-	return devm_iio_device_register(&client->dev, indio_dev);
+
+	err = iio_triggered_buffer_setup(indio_dev, NULL, ak8975_handle_trigger,
+					 NULL);
+	if (err) {
+		dev_err(&client->dev, "triggered buffer setup failed\n");
+		goto power_off;
+	}
+
+	err = iio_device_register(indio_dev);
+	if (err) {
+		dev_err(&client->dev, "device register failed\n");
+		goto cleanup_buffer;
+	}
+
+	return 0;
+
+cleanup_buffer:
+	iio_triggered_buffer_cleanup(indio_dev);
+power_off:
+	ak8975_power_off(client);
+	return err;
+}
+
+static int ak8975_remove(struct i2c_client *client)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+
+	iio_device_unregister(indio_dev);
+	iio_triggered_buffer_cleanup(indio_dev);
+	ak8975_power_off(client);
+
+	return 0;
 }
 
 static const struct i2c_device_id ak8975_id[] = {
@@ -841,6 +1010,7 @@ static struct i2c_driver ak8975_driver =
 		.acpi_match_table = ACPI_PTR(ak_acpi_match),
 	},
 	.probe		= ak8975_probe,
+	.remove		= ak8975_remove,
 	.id_table	= ak8975_id,
 };
 module_i2c_driver(ak8975_driver);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/magnetometer/bmc150_magn.c linux-libre-4.7-gnu/drivers/iio/magnetometer/bmc150_magn.c
--- linux-libre-4.6-gnu/drivers/iio/magnetometer/bmc150_magn.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/magnetometer/bmc150_magn.c	2016-07-24 15:23:50.000000000 -0400
@@ -23,7 +23,6 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/acpi.h>
-#include <linux/gpio/consumer.h>
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
 #include <linux/iio/iio.h>
@@ -35,6 +34,8 @@
 #include <linux/iio/triggered_buffer.h>
 #include <linux/regmap.h>
 
+#include "bmc150_magn.h"
+
 #define BMC150_MAGN_DRV_NAME			"bmc150_magn"
 #define BMC150_MAGN_IRQ_NAME			"bmc150_magn_event"
 
@@ -135,7 +136,7 @@ struct bmc150_magn_trim_regs {
 } __packed;
 
 struct bmc150_magn_data {
-	struct i2c_client *client;
+	struct device *dev;
 	/*
 	 * 1. Protect this structure.
 	 * 2. Serialize sequences that power on/off the device and access HW.
@@ -147,6 +148,7 @@ struct bmc150_magn_data {
 	struct iio_trigger *dready_trig;
 	bool dready_trigger_on;
 	int max_odr;
+	int irq;
 };
 
 static const struct {
@@ -216,7 +218,7 @@ static bool bmc150_magn_is_volatile_reg(
 	}
 }
 
-static const struct regmap_config bmc150_magn_regmap_config = {
+const struct regmap_config bmc150_magn_regmap_config = {
 	.reg_bits = 8,
 	.val_bits = 8,
 
@@ -226,6 +228,7 @@ static const struct regmap_config bmc150
 	.writeable_reg = bmc150_magn_is_writeable_reg,
 	.volatile_reg = bmc150_magn_is_volatile_reg,
 };
+EXPORT_SYMBOL(bmc150_magn_regmap_config);
 
 static int bmc150_magn_set_power_mode(struct bmc150_magn_data *data,
 				      enum bmc150_magn_power_modes mode,
@@ -264,17 +267,17 @@ static int bmc150_magn_set_power_state(s
 	int ret;
 
 	if (on) {
-		ret = pm_runtime_get_sync(&data->client->dev);
+		ret = pm_runtime_get_sync(data->dev);
 	} else {
-		pm_runtime_mark_last_busy(&data->client->dev);
-		ret = pm_runtime_put_autosuspend(&data->client->dev);
+		pm_runtime_mark_last_busy(data->dev);
+		ret = pm_runtime_put_autosuspend(data->dev);
 	}
 
 	if (ret < 0) {
-		dev_err(&data->client->dev,
+		dev_err(data->dev,
 			"failed to change power state to %d\n", on);
 		if (on)
-			pm_runtime_put_noidle(&data->client->dev);
+			pm_runtime_put_noidle(data->dev);
 
 		return ret;
 	}
@@ -351,7 +354,7 @@ static int bmc150_magn_set_max_odr(struc
 	/* the maximum selectable read-out frequency from datasheet */
 	max_odr = 1000000 / (145 * rep_xy + 500 * rep_z + 980);
 	if (odr > max_odr) {
-		dev_err(&data->client->dev,
+		dev_err(data->dev,
 			"Can't set oversampling with sampling freq %d\n",
 			odr);
 		return -EINVAL;
@@ -685,27 +688,27 @@ static int bmc150_magn_init(struct bmc15
 	ret = bmc150_magn_set_power_mode(data, BMC150_MAGN_POWER_MODE_SUSPEND,
 					 false);
 	if (ret < 0) {
-		dev_err(&data->client->dev,
+		dev_err(data->dev,
 			"Failed to bring up device from suspend mode\n");
 		return ret;
 	}
 
 	ret = regmap_read(data->regmap, BMC150_MAGN_REG_CHIP_ID, &chip_id);
 	if (ret < 0) {
-		dev_err(&data->client->dev, "Failed reading chip id\n");
+		dev_err(data->dev, "Failed reading chip id\n");
 		goto err_poweroff;
 	}
 	if (chip_id != BMC150_MAGN_CHIP_ID_VAL) {
-		dev_err(&data->client->dev, "Invalid chip id 0x%x\n", chip_id);
+		dev_err(data->dev, "Invalid chip id 0x%x\n", chip_id);
 		ret = -ENODEV;
 		goto err_poweroff;
 	}
-	dev_dbg(&data->client->dev, "Chip id %x\n", chip_id);
+	dev_dbg(data->dev, "Chip id %x\n", chip_id);
 
 	preset = bmc150_magn_presets_table[BMC150_MAGN_DEFAULT_PRESET];
 	ret = bmc150_magn_set_odr(data, preset.odr);
 	if (ret < 0) {
-		dev_err(&data->client->dev, "Failed to set ODR to %d\n",
+		dev_err(data->dev, "Failed to set ODR to %d\n",
 			preset.odr);
 		goto err_poweroff;
 	}
@@ -713,7 +716,7 @@ static int bmc150_magn_init(struct bmc15
 	ret = regmap_write(data->regmap, BMC150_MAGN_REG_REP_XY,
 			   BMC150_MAGN_REPXY_TO_REGVAL(preset.rep_xy));
 	if (ret < 0) {
-		dev_err(&data->client->dev, "Failed to set REP XY to %d\n",
+		dev_err(data->dev, "Failed to set REP XY to %d\n",
 			preset.rep_xy);
 		goto err_poweroff;
 	}
@@ -721,7 +724,7 @@ static int bmc150_magn_init(struct bmc15
 	ret = regmap_write(data->regmap, BMC150_MAGN_REG_REP_Z,
 			   BMC150_MAGN_REPZ_TO_REGVAL(preset.rep_z));
 	if (ret < 0) {
-		dev_err(&data->client->dev, "Failed to set REP Z to %d\n",
+		dev_err(data->dev, "Failed to set REP Z to %d\n",
 			preset.rep_z);
 		goto err_poweroff;
 	}
@@ -734,7 +737,7 @@ static int bmc150_magn_init(struct bmc15
 	ret = bmc150_magn_set_power_mode(data, BMC150_MAGN_POWER_MODE_NORMAL,
 					 true);
 	if (ret < 0) {
-		dev_err(&data->client->dev, "Failed to power on device\n");
+		dev_err(data->dev, "Failed to power on device\n");
 		goto err_poweroff;
 	}
 
@@ -843,41 +846,33 @@ static const char *bmc150_magn_match_acp
 	return dev_name(dev);
 }
 
-static int bmc150_magn_probe(struct i2c_client *client,
-			     const struct i2c_device_id *id)
+int bmc150_magn_probe(struct device *dev, struct regmap *regmap,
+		      int irq, const char *name)
 {
 	struct bmc150_magn_data *data;
 	struct iio_dev *indio_dev;
-	const char *name = NULL;
 	int ret;
 
-	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+	indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
 	if (!indio_dev)
 		return -ENOMEM;
 
 	data = iio_priv(indio_dev);
-	i2c_set_clientdata(client, indio_dev);
-	data->client = client;
+	dev_set_drvdata(dev, indio_dev);
+	data->regmap = regmap;
+	data->irq = irq;
+	data->dev = dev;
 
-	if (id)
-		name = id->name;
-	else if (ACPI_HANDLE(&client->dev))
-		name = bmc150_magn_match_acpi_device(&client->dev);
-	else
-		return -ENOSYS;
+	if (!name && ACPI_HANDLE(dev))
+		name = bmc150_magn_match_acpi_device(dev);
 
 	mutex_init(&data->mutex);
-	data->regmap = devm_regmap_init_i2c(client, &bmc150_magn_regmap_config);
-	if (IS_ERR(data->regmap)) {
-		dev_err(&client->dev, "Failed to allocate register map\n");
-		return PTR_ERR(data->regmap);
-	}
 
 	ret = bmc150_magn_init(data);
 	if (ret < 0)
 		return ret;
 
-	indio_dev->dev.parent = &client->dev;
+	indio_dev->dev.parent = dev;
 	indio_dev->channels = bmc150_magn_channels;
 	indio_dev->num_channels = ARRAY_SIZE(bmc150_magn_channels);
 	indio_dev->available_scan_masks = bmc150_magn_scan_masks;
@@ -885,35 +880,34 @@ static int bmc150_magn_probe(struct i2c_
 	indio_dev->modes = INDIO_DIRECT_MODE;
 	indio_dev->info = &bmc150_magn_info;
 
-	if (client->irq > 0) {
-		data->dready_trig = devm_iio_trigger_alloc(&client->dev,
+	if (irq > 0) {
+		data->dready_trig = devm_iio_trigger_alloc(dev,
 							   "%s-dev%d",
 							   indio_dev->name,
 							   indio_dev->id);
 		if (!data->dready_trig) {
 			ret = -ENOMEM;
-			dev_err(&client->dev, "iio trigger alloc failed\n");
+			dev_err(dev, "iio trigger alloc failed\n");
 			goto err_poweroff;
 		}
 
-		data->dready_trig->dev.parent = &client->dev;
+		data->dready_trig->dev.parent = dev;
 		data->dready_trig->ops = &bmc150_magn_trigger_ops;
 		iio_trigger_set_drvdata(data->dready_trig, indio_dev);
 		ret = iio_trigger_register(data->dready_trig);
 		if (ret) {
-			dev_err(&client->dev, "iio trigger register failed\n");
+			dev_err(dev, "iio trigger register failed\n");
 			goto err_poweroff;
 		}
 
-		ret = request_threaded_irq(client->irq,
+		ret = request_threaded_irq(irq,
 					   iio_trigger_generic_data_rdy_poll,
 					   NULL,
 					   IRQF_TRIGGER_RISING | IRQF_ONESHOT,
 					   BMC150_MAGN_IRQ_NAME,
 					   data->dready_trig);
 		if (ret < 0) {
-			dev_err(&client->dev, "request irq %d failed\n",
-				client->irq);
+			dev_err(dev, "request irq %d failed\n", irq);
 			goto err_trigger_unregister;
 		}
 	}
@@ -923,34 +917,33 @@ static int bmc150_magn_probe(struct i2c_
 					 bmc150_magn_trigger_handler,
 					 &bmc150_magn_buffer_setup_ops);
 	if (ret < 0) {
-		dev_err(&client->dev,
-			"iio triggered buffer setup failed\n");
+		dev_err(dev, "iio triggered buffer setup failed\n");
 		goto err_free_irq;
 	}
 
-	ret = pm_runtime_set_active(&client->dev);
+	ret = pm_runtime_set_active(dev);
 	if (ret)
 		goto err_buffer_cleanup;
 
-	pm_runtime_enable(&client->dev);
-	pm_runtime_set_autosuspend_delay(&client->dev,
+	pm_runtime_enable(dev);
+	pm_runtime_set_autosuspend_delay(dev,
 					 BMC150_MAGN_AUTO_SUSPEND_DELAY_MS);
-	pm_runtime_use_autosuspend(&client->dev);
+	pm_runtime_use_autosuspend(dev);
 
 	ret = iio_device_register(indio_dev);
 	if (ret < 0) {
-		dev_err(&client->dev, "unable to register iio device\n");
+		dev_err(dev, "unable to register iio device\n");
 		goto err_buffer_cleanup;
 	}
 
-	dev_dbg(&indio_dev->dev, "Registered device %s\n", name);
+	dev_dbg(dev, "Registered device %s\n", name);
 	return 0;
 
 err_buffer_cleanup:
 	iio_triggered_buffer_cleanup(indio_dev);
 err_free_irq:
-	if (client->irq > 0)
-		free_irq(client->irq, data->dready_trig);
+	if (irq > 0)
+		free_irq(irq, data->dready_trig);
 err_trigger_unregister:
 	if (data->dready_trig)
 		iio_trigger_unregister(data->dready_trig);
@@ -958,22 +951,23 @@ err_poweroff:
 	bmc150_magn_set_power_mode(data, BMC150_MAGN_POWER_MODE_SUSPEND, true);
 	return ret;
 }
+EXPORT_SYMBOL(bmc150_magn_probe);
 
-static int bmc150_magn_remove(struct i2c_client *client)
+int bmc150_magn_remove(struct device *dev)
 {
-	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	struct bmc150_magn_data *data = iio_priv(indio_dev);
 
 	iio_device_unregister(indio_dev);
 
-	pm_runtime_disable(&client->dev);
-	pm_runtime_set_suspended(&client->dev);
-	pm_runtime_put_noidle(&client->dev);
+	pm_runtime_disable(dev);
+	pm_runtime_set_suspended(dev);
+	pm_runtime_put_noidle(dev);
 
 	iio_triggered_buffer_cleanup(indio_dev);
 
-	if (client->irq > 0)
-		free_irq(data->client->irq, data->dready_trig);
+	if (data->irq > 0)
+		free_irq(data->irq, data->dready_trig);
 
 	if (data->dready_trig)
 		iio_trigger_unregister(data->dready_trig);
@@ -984,11 +978,12 @@ static int bmc150_magn_remove(struct i2c
 
 	return 0;
 }
+EXPORT_SYMBOL(bmc150_magn_remove);
 
 #ifdef CONFIG_PM
 static int bmc150_magn_runtime_suspend(struct device *dev)
 {
-	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	struct bmc150_magn_data *data = iio_priv(indio_dev);
 	int ret;
 
@@ -997,7 +992,7 @@ static int bmc150_magn_runtime_suspend(s
 					 true);
 	mutex_unlock(&data->mutex);
 	if (ret < 0) {
-		dev_err(&data->client->dev, "powering off device failed\n");
+		dev_err(dev, "powering off device failed\n");
 		return ret;
 	}
 	return 0;
@@ -1008,7 +1003,7 @@ static int bmc150_magn_runtime_suspend(s
  */
 static int bmc150_magn_runtime_resume(struct device *dev)
 {
-	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	struct bmc150_magn_data *data = iio_priv(indio_dev);
 
 	return bmc150_magn_set_power_mode(data, BMC150_MAGN_POWER_MODE_NORMAL,
@@ -1019,7 +1014,7 @@ static int bmc150_magn_runtime_resume(st
 #ifdef CONFIG_PM_SLEEP
 static int bmc150_magn_suspend(struct device *dev)
 {
-	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	struct bmc150_magn_data *data = iio_priv(indio_dev);
 	int ret;
 
@@ -1033,7 +1028,7 @@ static int bmc150_magn_suspend(struct de
 
 static int bmc150_magn_resume(struct device *dev)
 {
-	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	struct bmc150_magn_data *data = iio_priv(indio_dev);
 	int ret;
 
@@ -1046,38 +1041,13 @@ static int bmc150_magn_resume(struct dev
 }
 #endif
 
-static const struct dev_pm_ops bmc150_magn_pm_ops = {
+const struct dev_pm_ops bmc150_magn_pm_ops = {
 	SET_SYSTEM_SLEEP_PM_OPS(bmc150_magn_suspend, bmc150_magn_resume)
 	SET_RUNTIME_PM_OPS(bmc150_magn_runtime_suspend,
 			   bmc150_magn_runtime_resume, NULL)
 };
-
-static const struct acpi_device_id bmc150_magn_acpi_match[] = {
-	{"BMC150B", 0},
-	{"BMC156B", 0},
-	{},
-};
-MODULE_DEVICE_TABLE(acpi, bmc150_magn_acpi_match);
-
-static const struct i2c_device_id bmc150_magn_id[] = {
-	{"bmc150_magn", 0},
-	{"bmc156_magn", 0},
-	{},
-};
-MODULE_DEVICE_TABLE(i2c, bmc150_magn_id);
-
-static struct i2c_driver bmc150_magn_driver = {
-	.driver = {
-		   .name = BMC150_MAGN_DRV_NAME,
-		   .acpi_match_table = ACPI_PTR(bmc150_magn_acpi_match),
-		   .pm = &bmc150_magn_pm_ops,
-		   },
-	.probe = bmc150_magn_probe,
-	.remove = bmc150_magn_remove,
-	.id_table = bmc150_magn_id,
-};
-module_i2c_driver(bmc150_magn_driver);
+EXPORT_SYMBOL(bmc150_magn_pm_ops);
 
 MODULE_AUTHOR("Irina Tirdea <irina.tirdea@intel.com>");
 MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("BMC150 magnetometer driver");
+MODULE_DESCRIPTION("BMC150 magnetometer core driver");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/magnetometer/bmc150_magn.h linux-libre-4.7-gnu/drivers/iio/magnetometer/bmc150_magn.h
--- linux-libre-4.6-gnu/drivers/iio/magnetometer/bmc150_magn.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/iio/magnetometer/bmc150_magn.h	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,11 @@
+#ifndef _BMC150_MAGN_H_
+#define _BMC150_MAGN_H_
+
+extern const struct regmap_config bmc150_magn_regmap_config;
+extern const struct dev_pm_ops bmc150_magn_pm_ops;
+
+int bmc150_magn_probe(struct device *dev, struct regmap *regmap, int irq,
+		      const char *name);
+int bmc150_magn_remove(struct device *dev);
+
+#endif /* _BMC150_MAGN_H_ */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/magnetometer/bmc150_magn_i2c.c linux-libre-4.7-gnu/drivers/iio/magnetometer/bmc150_magn_i2c.c
--- linux-libre-4.6-gnu/drivers/iio/magnetometer/bmc150_magn_i2c.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/iio/magnetometer/bmc150_magn_i2c.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,77 @@
+/*
+ * 3-axis magnetometer driver supporting following I2C Bosch-Sensortec chips:
+ *  - BMC150
+ *  - BMC156
+ *
+ * Copyright (c) 2016, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ */
+#include <linux/device.h>
+#include <linux/mod_devicetable.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/acpi.h>
+#include <linux/regmap.h>
+
+#include "bmc150_magn.h"
+
+static int bmc150_magn_i2c_probe(struct i2c_client *client,
+				 const struct i2c_device_id *id)
+{
+	struct regmap *regmap;
+	const char *name = NULL;
+
+	regmap = devm_regmap_init_i2c(client, &bmc150_magn_regmap_config);
+	if (IS_ERR(regmap)) {
+		dev_err(&client->dev, "Failed to initialize i2c regmap\n");
+		return PTR_ERR(regmap);
+	}
+
+	if (id)
+		name = id->name;
+
+	return bmc150_magn_probe(&client->dev, regmap, client->irq, name);
+}
+
+static int bmc150_magn_i2c_remove(struct i2c_client *client)
+{
+	return bmc150_magn_remove(&client->dev);
+}
+
+static const struct acpi_device_id bmc150_magn_acpi_match[] = {
+	{"BMC150B", 0},
+	{"BMC156B", 0},
+	{},
+};
+MODULE_DEVICE_TABLE(acpi, bmc150_magn_acpi_match);
+
+static const struct i2c_device_id bmc150_magn_i2c_id[] = {
+	{"bmc150_magn",	0},
+	{"bmc156_magn", 0},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, bmc150_magn_i2c_id);
+
+static struct i2c_driver bmc150_magn_driver = {
+	.driver = {
+		.name	= "bmc150_magn_i2c",
+		.acpi_match_table = ACPI_PTR(bmc150_magn_acpi_match),
+		.pm	= &bmc150_magn_pm_ops,
+	},
+	.probe		= bmc150_magn_i2c_probe,
+	.remove		= bmc150_magn_i2c_remove,
+	.id_table	= bmc150_magn_i2c_id,
+};
+module_i2c_driver(bmc150_magn_driver);
+
+MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("BMC150 I2C magnetometer driver");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/magnetometer/bmc150_magn_spi.c linux-libre-4.7-gnu/drivers/iio/magnetometer/bmc150_magn_spi.c
--- linux-libre-4.6-gnu/drivers/iio/magnetometer/bmc150_magn_spi.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/iio/magnetometer/bmc150_magn_spi.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,68 @@
+/*
+ * 3-axis magnetometer driver support following SPI Bosch-Sensortec chips:
+ *  - BMC150
+ *  - BMC156
+ *
+ * Copyright (c) 2016, Intel Corporation.
+ *
+ * This file is subject to the terms and conditions of version 2 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/mod_devicetable.h>
+#include <linux/spi/spi.h>
+#include <linux/acpi.h>
+#include <linux/regmap.h>
+
+#include "bmc150_magn.h"
+
+static int bmc150_magn_spi_probe(struct spi_device *spi)
+{
+	struct regmap *regmap;
+	const struct spi_device_id *id = spi_get_device_id(spi);
+
+	regmap = devm_regmap_init_spi(spi, &bmc150_magn_regmap_config);
+	if (IS_ERR(regmap)) {
+		dev_err(&spi->dev, "Failed to register spi regmap %d\n",
+			(int)PTR_ERR(regmap));
+		return PTR_ERR(regmap);
+	}
+	return bmc150_magn_probe(&spi->dev, regmap, spi->irq, id->name);
+}
+
+static int bmc150_magn_spi_remove(struct spi_device *spi)
+{
+	bmc150_magn_remove(&spi->dev);
+
+	return 0;
+}
+
+static const struct spi_device_id bmc150_magn_spi_id[] = {
+	{"bmc150_magn", 0},
+	{"bmc156_magn", 0},
+	{}
+};
+MODULE_DEVICE_TABLE(spi, bmc150_magn_spi_id);
+
+static const struct acpi_device_id bmc150_magn_acpi_match[] = {
+	{"BMC150B", 0},
+	{"BMC156B", 0},
+	{},
+};
+MODULE_DEVICE_TABLE(acpi, bmc150_magn_acpi_match);
+
+static struct spi_driver bmc150_magn_spi_driver = {
+	.probe		= bmc150_magn_spi_probe,
+	.remove		= bmc150_magn_spi_remove,
+	.id_table	= bmc150_magn_spi_id,
+	.driver = {
+		.acpi_match_table = ACPI_PTR(bmc150_magn_acpi_match),
+		.name	= "bmc150_magn_spi",
+	},
+};
+module_spi_driver(bmc150_magn_spi_driver);
+
+MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com");
+MODULE_DESCRIPTION("BMC150 magnetometer SPI driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/magnetometer/Kconfig linux-libre-4.7-gnu/drivers/iio/magnetometer/Kconfig
--- linux-libre-4.6-gnu/drivers/iio/magnetometer/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/magnetometer/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -9,6 +9,8 @@ config AK8975
 	tristate "Asahi Kasei AK 3-Axis Magnetometer"
 	depends on I2C
 	depends on GPIOLIB || COMPILE_TEST
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
 	help
 	  Say yes here to build support for Asahi Kasei AK8975, AK8963,
 	  AK09911 or AK09912 3-Axis Magnetometer.
@@ -25,22 +27,41 @@ config AK09911
 	  Deprecated: AK09911 is now supported by AK8975 driver.
 
 config BMC150_MAGN
-	tristate "Bosch BMC150 Magnetometer Driver"
-	depends on I2C
-	select REGMAP_I2C
+	tristate
 	select IIO_BUFFER
 	select IIO_TRIGGERED_BUFFER
+
+config BMC150_MAGN_I2C
+	tristate "Bosch BMC150 I2C Magnetometer Driver"
+	depends on I2C
+	select BMC150_MAGN
+	select REGMAP_I2C
 	help
-	  Say yes here to build support for the BMC150 magnetometer.
+	  Say yes here to build support for the BMC150 magnetometer with
+	  I2C interface.
 
-	  Currently this only supports the device via an i2c interface.
+	  This is a combo module with both accelerometer and magnetometer.
+	  This driver is only implementing magnetometer part, which has
+	  its own address and register map.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called bmc150_magn_i2c.
+
+config BMC150_MAGN_SPI
+	tristate "Bosch BMC150 SPI Magnetometer Driver"
+	depends on SPI
+	select BMC150_MAGN
+	select REGMAP_SPI
+	help
+	  Say yes here to build support for the BMC150 magnetometer with
+	  SPI interface.
 
 	  This is a combo module with both accelerometer and magnetometer.
 	  This driver is only implementing magnetometer part, which has
 	  its own address and register map.
 
 	  To compile this driver as a module, choose M here: the module will be
-	  called bmc150_magn.
+	  called bmc150_magn_spi.
 
 config MAG3110
 	tristate "Freescale MAG3110 3-Axis Magnetometer"
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/magnetometer/Makefile linux-libre-4.7-gnu/drivers/iio/magnetometer/Makefile
--- linux-libre-4.6-gnu/drivers/iio/magnetometer/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/magnetometer/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -5,6 +5,9 @@
 # When adding new entries keep the list in alphabetical order
 obj-$(CONFIG_AK8975)	+= ak8975.o
 obj-$(CONFIG_BMC150_MAGN) += bmc150_magn.o
+obj-$(CONFIG_BMC150_MAGN_I2C) += bmc150_magn_i2c.o
+obj-$(CONFIG_BMC150_MAGN_SPI) += bmc150_magn_spi.o
+
 obj-$(CONFIG_MAG3110)	+= mag3110.o
 obj-$(CONFIG_HID_SENSOR_MAGNETOMETER_3D) += hid-sensor-magn-3d.o
 obj-$(CONFIG_MMC35240)	+= mmc35240.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/magnetometer/st_magn_buffer.c linux-libre-4.7-gnu/drivers/iio/magnetometer/st_magn_buffer.c
--- linux-libre-4.6-gnu/drivers/iio/magnetometer/st_magn_buffer.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/magnetometer/st_magn_buffer.c	2016-07-24 15:23:50.000000000 -0400
@@ -82,7 +82,7 @@ static const struct iio_buffer_setup_ops
 
 int st_magn_allocate_ring(struct iio_dev *indio_dev)
 {
-	return iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
+	return iio_triggered_buffer_setup(indio_dev, NULL,
 		&st_sensors_trigger_handler, &st_magn_buffer_setup_ops);
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/magnetometer/st_magn_core.c linux-libre-4.7-gnu/drivers/iio/magnetometer/st_magn_core.c
--- linux-libre-4.6-gnu/drivers/iio/magnetometer/st_magn_core.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/magnetometer/st_magn_core.c	2016-07-24 15:23:50.000000000 -0400
@@ -484,6 +484,7 @@ static const struct st_sensor_settings s
 			.mask_int1 = ST_MAGN_3_DRDY_INT_MASK,
 			.addr_ihl = ST_MAGN_3_IHL_IRQ_ADDR,
 			.mask_ihl = ST_MAGN_3_IHL_IRQ_MASK,
+			.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
 		},
 		.multi_read_bit = ST_MAGN_3_MULTIREAD_BIT,
 		.bootime = 2,
@@ -571,6 +572,7 @@ static const struct iio_info magn_info =
 static const struct iio_trigger_ops st_magn_trigger_ops = {
 	.owner = THIS_MODULE,
 	.set_trigger_state = ST_MAGN_TRIGGER_SET_STATE,
+	.validate_device = st_sensors_validate_device,
 };
 #define ST_MAGN_TRIGGER_OPS (&st_magn_trigger_ops)
 #else
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/potentiometer/ds1803.c linux-libre-4.7-gnu/drivers/iio/potentiometer/ds1803.c
--- linux-libre-4.6-gnu/drivers/iio/potentiometer/ds1803.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/iio/potentiometer/ds1803.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,173 @@
+/*
+ * Maxim Integrated DS1803 digital potentiometer driver
+ * Copyright (c) 2016 Slawomir Stepien
+ *
+ * Datasheet: https://datasheets.maximintegrated.com/en/ds/DS1803.pdf
+ *
+ * DEVID	#Wipers	#Positions	Resistor Opts (kOhm)	i2c address
+ * ds1803	2	256		10, 50, 100		0101xxx
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/module.h>
+#include <linux/of.h>
+
+#define DS1803_MAX_POS		255
+#define DS1803_WRITE(chan)	(0xa8 | ((chan) + 1))
+
+enum ds1803_type {
+	DS1803_010,
+	DS1803_050,
+	DS1803_100,
+};
+
+struct ds1803_cfg {
+	int kohms;
+};
+
+static const struct ds1803_cfg ds1803_cfg[] = {
+	[DS1803_010] = { .kohms =  10, },
+	[DS1803_050] = { .kohms =  50, },
+	[DS1803_100] = { .kohms = 100, },
+};
+
+struct ds1803_data {
+	struct i2c_client *client;
+	const struct ds1803_cfg *cfg;
+};
+
+#define DS1803_CHANNEL(ch) {					\
+	.type = IIO_RESISTANCE,					\
+	.indexed = 1,						\
+	.output = 1,						\
+	.channel = (ch),					\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
+}
+
+static const struct iio_chan_spec ds1803_channels[] = {
+	DS1803_CHANNEL(0),
+	DS1803_CHANNEL(1),
+};
+
+static int ds1803_read_raw(struct iio_dev *indio_dev,
+			    struct iio_chan_spec const *chan,
+			    int *val, int *val2, long mask)
+{
+	struct ds1803_data *data = iio_priv(indio_dev);
+	int pot = chan->channel;
+	int ret;
+	u8 result[indio_dev->num_channels];
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		ret = i2c_master_recv(data->client, result,
+				indio_dev->num_channels);
+		if (ret < 0)
+			return ret;
+
+		*val = result[pot];
+		return IIO_VAL_INT;
+
+	case IIO_CHAN_INFO_SCALE:
+		*val = 1000 * data->cfg->kohms;
+		*val2 = DS1803_MAX_POS;
+		return IIO_VAL_FRACTIONAL;
+	}
+
+	return -EINVAL;
+}
+
+static int ds1803_write_raw(struct iio_dev *indio_dev,
+			     struct iio_chan_spec const *chan,
+			     int val, int val2, long mask)
+{
+	struct ds1803_data *data = iio_priv(indio_dev);
+	int pot = chan->channel;
+
+	if (val2 != 0)
+		return -EINVAL;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		if (val > DS1803_MAX_POS || val < 0)
+			return -EINVAL;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return i2c_smbus_write_byte_data(data->client, DS1803_WRITE(pot), val);
+}
+
+static const struct iio_info ds1803_info = {
+	.read_raw = ds1803_read_raw,
+	.write_raw = ds1803_write_raw,
+	.driver_module = THIS_MODULE,
+};
+
+static int ds1803_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct device *dev = &client->dev;
+	struct ds1803_data *data;
+	struct iio_dev *indio_dev;
+
+	indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	i2c_set_clientdata(client, indio_dev);
+
+	data = iio_priv(indio_dev);
+	data->client = client;
+	data->cfg = &ds1803_cfg[id->driver_data];
+
+	indio_dev->dev.parent = dev;
+	indio_dev->info = &ds1803_info;
+	indio_dev->channels = ds1803_channels;
+	indio_dev->num_channels = ARRAY_SIZE(ds1803_channels);
+	indio_dev->name = client->name;
+
+	return devm_iio_device_register(dev, indio_dev);
+}
+
+#if defined(CONFIG_OF)
+static const struct of_device_id ds1803_dt_ids[] = {
+	{ .compatible = "maxim,ds1803-010", .data = &ds1803_cfg[DS1803_010] },
+	{ .compatible = "maxim,ds1803-050", .data = &ds1803_cfg[DS1803_050] },
+	{ .compatible = "maxim,ds1803-100", .data = &ds1803_cfg[DS1803_100] },
+	{}
+};
+MODULE_DEVICE_TABLE(of, ds1803_dt_ids);
+#endif /* CONFIG_OF */
+
+static const struct i2c_device_id ds1803_id[] = {
+	{ "ds1803-010", DS1803_010 },
+	{ "ds1803-050", DS1803_050 },
+	{ "ds1803-100", DS1803_100 },
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, ds1803_id);
+
+static struct i2c_driver ds1803_driver = {
+	.driver = {
+		.name	= "ds1803",
+		.of_match_table = of_match_ptr(ds1803_dt_ids),
+	},
+	.probe		= ds1803_probe,
+	.id_table	= ds1803_id,
+};
+
+module_i2c_driver(ds1803_driver);
+
+MODULE_AUTHOR("Slawomir Stepien <sst@poczta.fm>");
+MODULE_DESCRIPTION("DS1803 digital potentiometer");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/potentiometer/Kconfig linux-libre-4.7-gnu/drivers/iio/potentiometer/Kconfig
--- linux-libre-4.6-gnu/drivers/iio/potentiometer/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/potentiometer/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -5,6 +5,34 @@
 
 menu "Digital potentiometers"
 
+config DS1803
+	tristate "Maxim Integrated DS1803 Digital Potentiometer driver"
+	depends on I2C
+	help
+	  Say yes here to build support for the Maxim Integrated DS1803
+	  digital potentiomenter chip.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ds1803.
+
+config MCP4131
+	tristate "Microchip MCP413X/414X/415X/416X/423X/424X/425X/426X Digital Potentiometer driver"
+	depends on SPI
+	help
+	  Say yes here to build support for the Microchip
+	  MCP4131, MCP4132,
+	  MCP4141, MCP4142,
+	  MCP4151, MCP4152,
+	  MCP4161, MCP4162,
+	  MCP4231, MCP4232,
+	  MCP4241, MCP4242,
+	  MCP4251, MCP4252,
+	  MCP4261, MCP4262,
+	  digital potentiomenter chips.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called mcp4131.
+
 config MCP4531
 	tristate "Microchip MCP45xx/MCP46xx Digital Potentiometer driver"
 	depends on I2C
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/potentiometer/Makefile linux-libre-4.7-gnu/drivers/iio/potentiometer/Makefile
--- linux-libre-4.6-gnu/drivers/iio/potentiometer/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/potentiometer/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -3,5 +3,7 @@
 #
 
 # When adding new entries keep the list in alphabetical order
+obj-$(CONFIG_DS1803) += ds1803.o
+obj-$(CONFIG_MCP4131) += mcp4131.o
 obj-$(CONFIG_MCP4531) += mcp4531.o
 obj-$(CONFIG_TPL0102) += tpl0102.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/potentiometer/mcp4131.c linux-libre-4.7-gnu/drivers/iio/potentiometer/mcp4131.c
--- linux-libre-4.6-gnu/drivers/iio/potentiometer/mcp4131.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/iio/potentiometer/mcp4131.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,494 @@
+/*
+ * Industrial I/O driver for Microchip digital potentiometers
+ *
+ * Copyright (c) 2016 Slawomir Stepien
+ * Based on: Peter Rosin's code from mcp4531.c
+ *
+ * Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/22060b.pdf
+ *
+ * DEVID	#Wipers	#Positions	Resistor Opts (kOhm)
+ * mcp4131	1	129		5, 10, 50, 100
+ * mcp4132	1	129		5, 10, 50, 100
+ * mcp4141	1	129		5, 10, 50, 100
+ * mcp4142	1	129		5, 10, 50, 100
+ * mcp4151	1	257		5, 10, 50, 100
+ * mcp4152	1	257		5, 10, 50, 100
+ * mcp4161	1	257		5, 10, 50, 100
+ * mcp4162	1	257		5, 10, 50, 100
+ * mcp4231	2	129		5, 10, 50, 100
+ * mcp4232	2	129		5, 10, 50, 100
+ * mcp4241	2	129		5, 10, 50, 100
+ * mcp4242	2	129		5, 10, 50, 100
+ * mcp4251	2	257		5, 10, 50, 100
+ * mcp4252	2	257		5, 10, 50, 100
+ * mcp4261	2	257		5, 10, 50, 100
+ * mcp4262	2	257		5, 10, 50, 100
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+/*
+ * TODO:
+ * 1. Write wiper setting to EEPROM for EEPROM capable models.
+ */
+
+#include <linux/cache.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/types.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/spi/spi.h>
+
+#define MCP4131_WRITE		(0x00 << 2)
+#define MCP4131_READ		(0x03 << 2)
+
+#define MCP4131_WIPER_SHIFT	4
+#define MCP4131_CMDERR(r)	((r[0]) & 0x02)
+#define MCP4131_RAW(r)		((r[0]) == 0xff ? 0x100 : (r[1]))
+
+struct mcp4131_cfg {
+	int wipers;
+	int max_pos;
+	int kohms;
+};
+
+enum mcp4131_type {
+	MCP413x_502 = 0,
+	MCP413x_103,
+	MCP413x_503,
+	MCP413x_104,
+	MCP414x_502,
+	MCP414x_103,
+	MCP414x_503,
+	MCP414x_104,
+	MCP415x_502,
+	MCP415x_103,
+	MCP415x_503,
+	MCP415x_104,
+	MCP416x_502,
+	MCP416x_103,
+	MCP416x_503,
+	MCP416x_104,
+	MCP423x_502,
+	MCP423x_103,
+	MCP423x_503,
+	MCP423x_104,
+	MCP424x_502,
+	MCP424x_103,
+	MCP424x_503,
+	MCP424x_104,
+	MCP425x_502,
+	MCP425x_103,
+	MCP425x_503,
+	MCP425x_104,
+	MCP426x_502,
+	MCP426x_103,
+	MCP426x_503,
+	MCP426x_104,
+};
+
+static const struct mcp4131_cfg mcp4131_cfg[] = {
+	[MCP413x_502] = { .wipers = 1, .max_pos = 128, .kohms =   5, },
+	[MCP413x_103] = { .wipers = 1, .max_pos = 128, .kohms =  10, },
+	[MCP413x_503] = { .wipers = 1, .max_pos = 128, .kohms =  50, },
+	[MCP413x_104] = { .wipers = 1, .max_pos = 128, .kohms = 100, },
+	[MCP414x_502] = { .wipers = 1, .max_pos = 128, .kohms =   5, },
+	[MCP414x_103] = { .wipers = 1, .max_pos = 128, .kohms =  10, },
+	[MCP414x_503] = { .wipers = 1, .max_pos = 128, .kohms =  50, },
+	[MCP414x_104] = { .wipers = 1, .max_pos = 128, .kohms = 100, },
+	[MCP415x_502] = { .wipers = 1, .max_pos = 256, .kohms =   5, },
+	[MCP415x_103] = { .wipers = 1, .max_pos = 256, .kohms =  10, },
+	[MCP415x_503] = { .wipers = 1, .max_pos = 256, .kohms =  50, },
+	[MCP415x_104] = { .wipers = 1, .max_pos = 256, .kohms = 100, },
+	[MCP416x_502] = { .wipers = 1, .max_pos = 256, .kohms =   5, },
+	[MCP416x_103] = { .wipers = 1, .max_pos = 256, .kohms =  10, },
+	[MCP416x_503] = { .wipers = 1, .max_pos = 256, .kohms =  50, },
+	[MCP416x_104] = { .wipers = 1, .max_pos = 256, .kohms = 100, },
+	[MCP423x_502] = { .wipers = 2, .max_pos = 128, .kohms =   5, },
+	[MCP423x_103] = { .wipers = 2, .max_pos = 128, .kohms =  10, },
+	[MCP423x_503] = { .wipers = 2, .max_pos = 128, .kohms =  50, },
+	[MCP423x_104] = { .wipers = 2, .max_pos = 128, .kohms = 100, },
+	[MCP424x_502] = { .wipers = 2, .max_pos = 128, .kohms =   5, },
+	[MCP424x_103] = { .wipers = 2, .max_pos = 128, .kohms =  10, },
+	[MCP424x_503] = { .wipers = 2, .max_pos = 128, .kohms =  50, },
+	[MCP424x_104] = { .wipers = 2, .max_pos = 128, .kohms = 100, },
+	[MCP425x_502] = { .wipers = 2, .max_pos = 256, .kohms =   5, },
+	[MCP425x_103] = { .wipers = 2, .max_pos = 256, .kohms =  10, },
+	[MCP425x_503] = { .wipers = 2, .max_pos = 256, .kohms =  50, },
+	[MCP425x_104] = { .wipers = 2, .max_pos = 256, .kohms = 100, },
+	[MCP426x_502] = { .wipers = 2, .max_pos = 256, .kohms =   5, },
+	[MCP426x_103] = { .wipers = 2, .max_pos = 256, .kohms =  10, },
+	[MCP426x_503] = { .wipers = 2, .max_pos = 256, .kohms =  50, },
+	[MCP426x_104] = { .wipers = 2, .max_pos = 256, .kohms = 100, },
+};
+
+struct mcp4131_data {
+	struct spi_device *spi;
+	const struct mcp4131_cfg *cfg;
+	struct mutex lock;
+	u8 buf[2] ____cacheline_aligned;
+};
+
+#define MCP4131_CHANNEL(ch) {					\
+	.type = IIO_RESISTANCE,					\
+	.indexed = 1,						\
+	.output = 1,						\
+	.channel = (ch),					\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
+}
+
+static const struct iio_chan_spec mcp4131_channels[] = {
+	MCP4131_CHANNEL(0),
+	MCP4131_CHANNEL(1),
+};
+
+static int mcp4131_read(struct spi_device *spi, void *buf, size_t len)
+{
+	struct spi_transfer t = {
+		.tx_buf = buf, /* We need to send addr, cmd and 12 bits */
+		.rx_buf	= buf,
+		.len = len,
+	};
+	struct spi_message m;
+
+	spi_message_init(&m);
+	spi_message_add_tail(&t, &m);
+
+	return spi_sync(spi, &m);
+}
+
+static int mcp4131_read_raw(struct iio_dev *indio_dev,
+			    struct iio_chan_spec const *chan,
+			    int *val, int *val2, long mask)
+{
+	int err;
+	struct mcp4131_data *data = iio_priv(indio_dev);
+	int address = chan->channel;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		mutex_lock(&data->lock);
+
+		data->buf[0] = (address << MCP4131_WIPER_SHIFT) | MCP4131_READ;
+		data->buf[1] = 0;
+
+		err = mcp4131_read(data->spi, data->buf, 2);
+		if (err) {
+			mutex_unlock(&data->lock);
+			return err;
+		}
+
+		/* Error, bad address/command combination */
+		if (!MCP4131_CMDERR(data->buf)) {
+			mutex_unlock(&data->lock);
+			return -EIO;
+		}
+
+		*val = MCP4131_RAW(data->buf);
+		mutex_unlock(&data->lock);
+
+		return IIO_VAL_INT;
+
+	case IIO_CHAN_INFO_SCALE:
+		*val = 1000 * data->cfg->kohms;
+		*val2 = data->cfg->max_pos;
+		return IIO_VAL_FRACTIONAL;
+	}
+
+	return -EINVAL;
+}
+
+static int mcp4131_write_raw(struct iio_dev *indio_dev,
+			     struct iio_chan_spec const *chan,
+			     int val, int val2, long mask)
+{
+	int err;
+	struct mcp4131_data *data = iio_priv(indio_dev);
+	int address = chan->channel << MCP4131_WIPER_SHIFT;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		if (val > data->cfg->max_pos || val < 0)
+			return -EINVAL;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	mutex_lock(&data->lock);
+
+	data->buf[0] = address << MCP4131_WIPER_SHIFT;
+	data->buf[0] |= MCP4131_WRITE | (val >> 8);
+	data->buf[1] = val & 0xFF; /* 8 bits here */
+
+	err = spi_write(data->spi, data->buf, 2);
+	mutex_unlock(&data->lock);
+
+	return err;
+}
+
+static const struct iio_info mcp4131_info = {
+	.read_raw = mcp4131_read_raw,
+	.write_raw = mcp4131_write_raw,
+	.driver_module = THIS_MODULE,
+};
+
+static int mcp4131_probe(struct spi_device *spi)
+{
+	int err;
+	struct device *dev = &spi->dev;
+	unsigned long devid = spi_get_device_id(spi)->driver_data;
+	struct mcp4131_data *data;
+	struct iio_dev *indio_dev;
+
+	indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	data = iio_priv(indio_dev);
+	spi_set_drvdata(spi, indio_dev);
+	data->spi = spi;
+	data->cfg = &mcp4131_cfg[devid];
+
+	mutex_init(&data->lock);
+
+	indio_dev->dev.parent = dev;
+	indio_dev->info = &mcp4131_info;
+	indio_dev->channels = mcp4131_channels;
+	indio_dev->num_channels = data->cfg->wipers;
+	indio_dev->name = spi_get_device_id(spi)->name;
+
+	err = devm_iio_device_register(dev, indio_dev);
+	if (err) {
+		dev_info(&spi->dev, "Unable to register %s\n", indio_dev->name);
+		return err;
+	}
+
+	return 0;
+}
+
+#if defined(CONFIG_OF)
+static const struct of_device_id mcp4131_dt_ids[] = {
+	{ .compatible = "microchip,mcp4131-502",
+		.data = &mcp4131_cfg[MCP413x_502] },
+	{ .compatible = "microchip,mcp4131-103",
+		.data = &mcp4131_cfg[MCP413x_103] },
+	{ .compatible = "microchip,mcp4131-503",
+		.data = &mcp4131_cfg[MCP413x_503] },
+	{ .compatible = "microchip,mcp4131-104",
+		.data = &mcp4131_cfg[MCP413x_104] },
+	{ .compatible = "microchip,mcp4132-502",
+		.data = &mcp4131_cfg[MCP413x_502] },
+	{ .compatible = "microchip,mcp4132-103",
+		.data = &mcp4131_cfg[MCP413x_103] },
+	{ .compatible = "microchip,mcp4132-503",
+		.data = &mcp4131_cfg[MCP413x_503] },
+	{ .compatible = "microchip,mcp4132-104",
+		.data = &mcp4131_cfg[MCP413x_104] },
+	{ .compatible = "microchip,mcp4141-502",
+		.data = &mcp4131_cfg[MCP414x_502] },
+	{ .compatible = "microchip,mcp4141-103",
+		.data = &mcp4131_cfg[MCP414x_103] },
+	{ .compatible = "microchip,mcp4141-503",
+		.data = &mcp4131_cfg[MCP414x_503] },
+	{ .compatible = "microchip,mcp4141-104",
+		.data = &mcp4131_cfg[MCP414x_104] },
+	{ .compatible = "microchip,mcp4142-502",
+		.data = &mcp4131_cfg[MCP414x_502] },
+	{ .compatible = "microchip,mcp4142-103",
+		.data = &mcp4131_cfg[MCP414x_103] },
+	{ .compatible = "microchip,mcp4142-503",
+		.data = &mcp4131_cfg[MCP414x_503] },
+	{ .compatible = "microchip,mcp4142-104",
+		.data = &mcp4131_cfg[MCP414x_104] },
+	{ .compatible = "microchip,mcp4151-502",
+		.data = &mcp4131_cfg[MCP415x_502] },
+	{ .compatible = "microchip,mcp4151-103",
+		.data = &mcp4131_cfg[MCP415x_103] },
+	{ .compatible = "microchip,mcp4151-503",
+		.data = &mcp4131_cfg[MCP415x_503] },
+	{ .compatible = "microchip,mcp4151-104",
+		.data = &mcp4131_cfg[MCP415x_104] },
+	{ .compatible = "microchip,mcp4152-502",
+		.data = &mcp4131_cfg[MCP415x_502] },
+	{ .compatible = "microchip,mcp4152-103",
+		.data = &mcp4131_cfg[MCP415x_103] },
+	{ .compatible = "microchip,mcp4152-503",
+		.data = &mcp4131_cfg[MCP415x_503] },
+	{ .compatible = "microchip,mcp4152-104",
+		.data = &mcp4131_cfg[MCP415x_104] },
+	{ .compatible = "microchip,mcp4161-502",
+		.data = &mcp4131_cfg[MCP416x_502] },
+	{ .compatible = "microchip,mcp4161-103",
+		.data = &mcp4131_cfg[MCP416x_103] },
+	{ .compatible = "microchip,mcp4161-503",
+		.data = &mcp4131_cfg[MCP416x_503] },
+	{ .compatible = "microchip,mcp4161-104",
+		.data = &mcp4131_cfg[MCP416x_104] },
+	{ .compatible = "microchip,mcp4162-502",
+		.data = &mcp4131_cfg[MCP416x_502] },
+	{ .compatible = "microchip,mcp4162-103",
+		.data = &mcp4131_cfg[MCP416x_103] },
+	{ .compatible = "microchip,mcp4162-503",
+		.data = &mcp4131_cfg[MCP416x_503] },
+	{ .compatible = "microchip,mcp4162-104",
+		.data = &mcp4131_cfg[MCP416x_104] },
+	{ .compatible = "microchip,mcp4231-502",
+		.data = &mcp4131_cfg[MCP423x_502] },
+	{ .compatible = "microchip,mcp4231-103",
+		.data = &mcp4131_cfg[MCP423x_103] },
+	{ .compatible = "microchip,mcp4231-503",
+		.data = &mcp4131_cfg[MCP423x_503] },
+	{ .compatible = "microchip,mcp4231-104",
+		.data = &mcp4131_cfg[MCP423x_104] },
+	{ .compatible = "microchip,mcp4232-502",
+		.data = &mcp4131_cfg[MCP423x_502] },
+	{ .compatible = "microchip,mcp4232-103",
+		.data = &mcp4131_cfg[MCP423x_103] },
+	{ .compatible = "microchip,mcp4232-503",
+		.data = &mcp4131_cfg[MCP423x_503] },
+	{ .compatible = "microchip,mcp4232-104",
+		.data = &mcp4131_cfg[MCP423x_104] },
+	{ .compatible = "microchip,mcp4241-502",
+		.data = &mcp4131_cfg[MCP424x_502] },
+	{ .compatible = "microchip,mcp4241-103",
+		.data = &mcp4131_cfg[MCP424x_103] },
+	{ .compatible = "microchip,mcp4241-503",
+		.data = &mcp4131_cfg[MCP424x_503] },
+	{ .compatible = "microchip,mcp4241-104",
+		.data = &mcp4131_cfg[MCP424x_104] },
+	{ .compatible = "microchip,mcp4242-502",
+		.data = &mcp4131_cfg[MCP424x_502] },
+	{ .compatible = "microchip,mcp4242-103",
+		.data = &mcp4131_cfg[MCP424x_103] },
+	{ .compatible = "microchip,mcp4242-503",
+		.data = &mcp4131_cfg[MCP424x_503] },
+	{ .compatible = "microchip,mcp4242-104",
+		.data = &mcp4131_cfg[MCP424x_104] },
+	{ .compatible = "microchip,mcp4251-502",
+		.data = &mcp4131_cfg[MCP425x_502] },
+	{ .compatible = "microchip,mcp4251-103",
+		.data = &mcp4131_cfg[MCP425x_103] },
+	{ .compatible = "microchip,mcp4251-503",
+		.data = &mcp4131_cfg[MCP425x_503] },
+	{ .compatible = "microchip,mcp4251-104",
+		.data = &mcp4131_cfg[MCP425x_104] },
+	{ .compatible = "microchip,mcp4252-502",
+		.data = &mcp4131_cfg[MCP425x_502] },
+	{ .compatible = "microchip,mcp4252-103",
+		.data = &mcp4131_cfg[MCP425x_103] },
+	{ .compatible = "microchip,mcp4252-503",
+		.data = &mcp4131_cfg[MCP425x_503] },
+	{ .compatible = "microchip,mcp4252-104",
+		.data = &mcp4131_cfg[MCP425x_104] },
+	{ .compatible = "microchip,mcp4261-502",
+		.data = &mcp4131_cfg[MCP426x_502] },
+	{ .compatible = "microchip,mcp4261-103",
+		.data = &mcp4131_cfg[MCP426x_103] },
+	{ .compatible = "microchip,mcp4261-503",
+		.data = &mcp4131_cfg[MCP426x_503] },
+	{ .compatible = "microchip,mcp4261-104",
+		.data = &mcp4131_cfg[MCP426x_104] },
+	{ .compatible = "microchip,mcp4262-502",
+		.data = &mcp4131_cfg[MCP426x_502] },
+	{ .compatible = "microchip,mcp4262-103",
+		.data = &mcp4131_cfg[MCP426x_103] },
+	{ .compatible = "microchip,mcp4262-503",
+		.data = &mcp4131_cfg[MCP426x_503] },
+	{ .compatible = "microchip,mcp4262-104",
+		.data = &mcp4131_cfg[MCP426x_104] },
+	{}
+};
+MODULE_DEVICE_TABLE(of, mcp4131_dt_ids);
+#endif /* CONFIG_OF */
+
+static const struct spi_device_id mcp4131_id[] = {
+	{ "mcp4131-502", MCP413x_502 },
+	{ "mcp4131-103", MCP413x_103 },
+	{ "mcp4131-503", MCP413x_503 },
+	{ "mcp4131-104", MCP413x_104 },
+	{ "mcp4132-502", MCP413x_502 },
+	{ "mcp4132-103", MCP413x_103 },
+	{ "mcp4132-503", MCP413x_503 },
+	{ "mcp4132-104", MCP413x_104 },
+	{ "mcp4141-502", MCP414x_502 },
+	{ "mcp4141-103", MCP414x_103 },
+	{ "mcp4141-503", MCP414x_503 },
+	{ "mcp4141-104", MCP414x_104 },
+	{ "mcp4142-502", MCP414x_502 },
+	{ "mcp4142-103", MCP414x_103 },
+	{ "mcp4142-503", MCP414x_503 },
+	{ "mcp4142-104", MCP414x_104 },
+	{ "mcp4151-502", MCP415x_502 },
+	{ "mcp4151-103", MCP415x_103 },
+	{ "mcp4151-503", MCP415x_503 },
+	{ "mcp4151-104", MCP415x_104 },
+	{ "mcp4152-502", MCP415x_502 },
+	{ "mcp4152-103", MCP415x_103 },
+	{ "mcp4152-503", MCP415x_503 },
+	{ "mcp4152-104", MCP415x_104 },
+	{ "mcp4161-502", MCP416x_502 },
+	{ "mcp4161-103", MCP416x_103 },
+	{ "mcp4161-503", MCP416x_503 },
+	{ "mcp4161-104", MCP416x_104 },
+	{ "mcp4162-502", MCP416x_502 },
+	{ "mcp4162-103", MCP416x_103 },
+	{ "mcp4162-503", MCP416x_503 },
+	{ "mcp4162-104", MCP416x_104 },
+	{ "mcp4231-502", MCP423x_502 },
+	{ "mcp4231-103", MCP423x_103 },
+	{ "mcp4231-503", MCP423x_503 },
+	{ "mcp4231-104", MCP423x_104 },
+	{ "mcp4232-502", MCP423x_502 },
+	{ "mcp4232-103", MCP423x_103 },
+	{ "mcp4232-503", MCP423x_503 },
+	{ "mcp4232-104", MCP423x_104 },
+	{ "mcp4241-502", MCP424x_502 },
+	{ "mcp4241-103", MCP424x_103 },
+	{ "mcp4241-503", MCP424x_503 },
+	{ "mcp4241-104", MCP424x_104 },
+	{ "mcp4242-502", MCP424x_502 },
+	{ "mcp4242-103", MCP424x_103 },
+	{ "mcp4242-503", MCP424x_503 },
+	{ "mcp4242-104", MCP424x_104 },
+	{ "mcp4251-502", MCP425x_502 },
+	{ "mcp4251-103", MCP425x_103 },
+	{ "mcp4251-503", MCP425x_503 },
+	{ "mcp4251-104", MCP425x_104 },
+	{ "mcp4252-502", MCP425x_502 },
+	{ "mcp4252-103", MCP425x_103 },
+	{ "mcp4252-503", MCP425x_503 },
+	{ "mcp4252-104", MCP425x_104 },
+	{ "mcp4261-502", MCP426x_502 },
+	{ "mcp4261-103", MCP426x_103 },
+	{ "mcp4261-503", MCP426x_503 },
+	{ "mcp4261-104", MCP426x_104 },
+	{ "mcp4262-502", MCP426x_502 },
+	{ "mcp4262-103", MCP426x_103 },
+	{ "mcp4262-503", MCP426x_503 },
+	{ "mcp4262-104", MCP426x_104 },
+	{}
+};
+MODULE_DEVICE_TABLE(spi, mcp4131_id);
+
+static struct spi_driver mcp4131_driver = {
+	.driver = {
+		.name	= "mcp4131",
+		.of_match_table = of_match_ptr(mcp4131_dt_ids),
+	},
+	.probe		= mcp4131_probe,
+	.id_table	= mcp4131_id,
+};
+
+module_spi_driver(mcp4131_driver);
+
+MODULE_AUTHOR("Slawomir Stepien <sst@poczta.fm>");
+MODULE_DESCRIPTION("MCP4131 digital potentiometer");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/potentiometer/mcp4531.c linux-libre-4.7-gnu/drivers/iio/potentiometer/mcp4531.c
--- linux-libre-4.6-gnu/drivers/iio/potentiometer/mcp4531.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/potentiometer/mcp4531.c	2016-07-24 15:23:50.000000000 -0400
@@ -79,7 +79,7 @@ static const struct mcp4531_cfg mcp4531_
 
 struct mcp4531_data {
 	struct i2c_client *client;
-	unsigned long devid;
+	const struct mcp4531_cfg *cfg;
 };
 
 #define MCP4531_CHANNEL(ch) {					\
@@ -113,8 +113,8 @@ static int mcp4531_read_raw(struct iio_d
 		*val = ret;
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_SCALE:
-		*val = 1000 * mcp4531_cfg[data->devid].kohms;
-		*val2 = mcp4531_cfg[data->devid].max_pos;
+		*val = 1000 * data->cfg->kohms;
+		*val2 = data->cfg->max_pos;
 		return IIO_VAL_FRACTIONAL;
 	}
 
@@ -130,7 +130,7 @@ static int mcp4531_write_raw(struct iio_
 
 	switch (mask) {
 	case IIO_CHAN_INFO_RAW:
-		if (val > mcp4531_cfg[data->devid].max_pos || val < 0)
+		if (val > data->cfg->max_pos || val < 0)
 			return -EINVAL;
 		break;
 	default:
@@ -152,7 +152,6 @@ static int mcp4531_probe(struct i2c_clie
 			 const struct i2c_device_id *id)
 {
 	struct device *dev = &client->dev;
-	unsigned long devid = id->driver_data;
 	struct mcp4531_data *data;
 	struct iio_dev *indio_dev;
 
@@ -168,12 +167,12 @@ static int mcp4531_probe(struct i2c_clie
 	data = iio_priv(indio_dev);
 	i2c_set_clientdata(client, indio_dev);
 	data->client = client;
-	data->devid = devid;
+	data->cfg = &mcp4531_cfg[id->driver_data];
 
 	indio_dev->dev.parent = dev;
 	indio_dev->info = &mcp4531_info;
 	indio_dev->channels = mcp4531_channels;
-	indio_dev->num_channels = mcp4531_cfg[devid].wipers;
+	indio_dev->num_channels = data->cfg->wipers;
 	indio_dev->name = client->name;
 
 	return devm_iio_device_register(dev, indio_dev);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/potentiometer/tpl0102.c linux-libre-4.7-gnu/drivers/iio/potentiometer/tpl0102.c
--- linux-libre-4.6-gnu/drivers/iio/potentiometer/tpl0102.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/potentiometer/tpl0102.c	2016-07-24 15:23:50.000000000 -0400
@@ -118,7 +118,7 @@ static int tpl0102_probe(struct i2c_clie
 
 	if (!i2c_check_functionality(client->adapter,
 				     I2C_FUNC_SMBUS_WORD_DATA))
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 
 	indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
 	if (!indio_dev)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/pressure/bmp280.c linux-libre-4.7-gnu/drivers/iio/pressure/bmp280.c
--- linux-libre-4.6-gnu/drivers/iio/pressure/bmp280.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/pressure/bmp280.c	2016-07-24 15:23:50.000000000 -0400
@@ -1,12 +1,15 @@
 /*
  * Copyright (c) 2014 Intel Corporation
  *
- * Driver for Bosch Sensortec BMP280 digital pressure sensor.
+ * Driver for Bosch Sensortec BMP180 and BMP280 digital pressure sensor.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
+ * Datasheet:
+ * https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BMP180-DS000-121.pdf
+ * https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BMP280-DS001-12.pdf
  */
 
 #define pr_fmt(fmt) "bmp280: " fmt
@@ -15,9 +18,11 @@
 #include <linux/i2c.h>
 #include <linux/acpi.h>
 #include <linux/regmap.h>
+#include <linux/delay.h>
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
 
+/* BMP280 specific registers */
 #define BMP280_REG_TEMP_XLSB		0xFC
 #define BMP280_REG_TEMP_LSB		0xFB
 #define BMP280_REG_TEMP_MSB		0xFA
@@ -26,10 +31,7 @@
 #define BMP280_REG_PRESS_MSB		0xF7
 
 #define BMP280_REG_CONFIG		0xF5
-#define BMP280_REG_CTRL_MEAS		0xF4
 #define BMP280_REG_STATUS		0xF3
-#define BMP280_REG_RESET		0xE0
-#define BMP280_REG_ID			0xD0
 
 #define BMP280_REG_COMP_TEMP_START	0x88
 #define BMP280_COMP_TEMP_REG_COUNT	6
@@ -46,25 +48,49 @@
 
 #define BMP280_OSRS_TEMP_MASK		(BIT(7) | BIT(6) | BIT(5))
 #define BMP280_OSRS_TEMP_SKIP		0
-#define BMP280_OSRS_TEMP_1X		BIT(5)
-#define BMP280_OSRS_TEMP_2X		BIT(6)
-#define BMP280_OSRS_TEMP_4X		(BIT(6) | BIT(5))
-#define BMP280_OSRS_TEMP_8X		BIT(7)
-#define BMP280_OSRS_TEMP_16X		(BIT(7) | BIT(5))
+#define BMP280_OSRS_TEMP_X(osrs_t)	((osrs_t) << 5)
+#define BMP280_OSRS_TEMP_1X		BMP280_OSRS_TEMP_X(1)
+#define BMP280_OSRS_TEMP_2X		BMP280_OSRS_TEMP_X(2)
+#define BMP280_OSRS_TEMP_4X		BMP280_OSRS_TEMP_X(3)
+#define BMP280_OSRS_TEMP_8X		BMP280_OSRS_TEMP_X(4)
+#define BMP280_OSRS_TEMP_16X		BMP280_OSRS_TEMP_X(5)
 
 #define BMP280_OSRS_PRESS_MASK		(BIT(4) | BIT(3) | BIT(2))
 #define BMP280_OSRS_PRESS_SKIP		0
-#define BMP280_OSRS_PRESS_1X		BIT(2)
-#define BMP280_OSRS_PRESS_2X		BIT(3)
-#define BMP280_OSRS_PRESS_4X		(BIT(3) | BIT(2))
-#define BMP280_OSRS_PRESS_8X		BIT(4)
-#define BMP280_OSRS_PRESS_16X		(BIT(4) | BIT(2))
+#define BMP280_OSRS_PRESS_X(osrs_p)	((osrs_p) << 2)
+#define BMP280_OSRS_PRESS_1X		BMP280_OSRS_PRESS_X(1)
+#define BMP280_OSRS_PRESS_2X		BMP280_OSRS_PRESS_X(2)
+#define BMP280_OSRS_PRESS_4X		BMP280_OSRS_PRESS_X(3)
+#define BMP280_OSRS_PRESS_8X		BMP280_OSRS_PRESS_X(4)
+#define BMP280_OSRS_PRESS_16X		BMP280_OSRS_PRESS_X(5)
 
 #define BMP280_MODE_MASK		(BIT(1) | BIT(0))
 #define BMP280_MODE_SLEEP		0
 #define BMP280_MODE_FORCED		BIT(0)
 #define BMP280_MODE_NORMAL		(BIT(1) | BIT(0))
 
+/* BMP180 specific registers */
+#define BMP180_REG_OUT_XLSB		0xF8
+#define BMP180_REG_OUT_LSB		0xF7
+#define BMP180_REG_OUT_MSB		0xF6
+
+#define BMP180_REG_CALIB_START		0xAA
+#define BMP180_REG_CALIB_COUNT		22
+
+#define BMP180_MEAS_SCO			BIT(5)
+#define BMP180_MEAS_TEMP		(0x0E | BMP180_MEAS_SCO)
+#define BMP180_MEAS_PRESS_X(oss)	((oss) << 6 | 0x14 | BMP180_MEAS_SCO)
+#define BMP180_MEAS_PRESS_1X		BMP180_MEAS_PRESS_X(0)
+#define BMP180_MEAS_PRESS_2X		BMP180_MEAS_PRESS_X(1)
+#define BMP180_MEAS_PRESS_4X		BMP180_MEAS_PRESS_X(2)
+#define BMP180_MEAS_PRESS_8X		BMP180_MEAS_PRESS_X(3)
+
+/* BMP180 and BMP280 common registers */
+#define BMP280_REG_CTRL_MEAS		0xF4
+#define BMP280_REG_RESET		0xE0
+#define BMP280_REG_ID			0xD0
+
+#define BMP180_CHIP_ID			0x55
 #define BMP280_CHIP_ID			0x58
 #define BMP280_SOFT_RESET_VAL		0xB6
 
@@ -72,6 +98,11 @@ struct bmp280_data {
 	struct i2c_client *client;
 	struct mutex lock;
 	struct regmap *regmap;
+	const struct bmp280_chip_info *chip_info;
+
+	/* log of base 2 of oversampling rate */
+	u8 oversampling_press;
+	u8 oversampling_temp;
 
 	/*
 	 * Carryover value from temperature conversion, used in pressure
@@ -80,9 +111,23 @@ struct bmp280_data {
 	s32 t_fine;
 };
 
+struct bmp280_chip_info {
+	const struct regmap_config *regmap_config;
+
+	const int *oversampling_temp_avail;
+	int num_oversampling_temp_avail;
+
+	const int *oversampling_press_avail;
+	int num_oversampling_press_avail;
+
+	int (*chip_config)(struct bmp280_data *);
+	int (*read_temp)(struct bmp280_data *, int *);
+	int (*read_press)(struct bmp280_data *, int *, int *);
+};
+
 /*
  * These enums are used for indexing into the array of compensation
- * parameters.
+ * parameters for BMP280.
  */
 enum { T1, T2, T3 };
 enum { P1, P2, P3, P4, P5, P6, P7, P8, P9 };
@@ -90,11 +135,13 @@ enum { P1, P2, P3, P4, P5, P6, P7, P8, P
 static const struct iio_chan_spec bmp280_channels[] = {
 	{
 		.type = IIO_PRESSURE,
-		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
+				      BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
 	},
 	{
 		.type = IIO_TEMP,
-		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
+				      BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
 	},
 };
 
@@ -290,10 +337,25 @@ static int bmp280_read_raw(struct iio_de
 	case IIO_CHAN_INFO_PROCESSED:
 		switch (chan->type) {
 		case IIO_PRESSURE:
-			ret = bmp280_read_press(data, val, val2);
+			ret = data->chip_info->read_press(data, val, val2);
 			break;
 		case IIO_TEMP:
-			ret = bmp280_read_temp(data, val);
+			ret = data->chip_info->read_temp(data, val);
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+		}
+		break;
+	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
+		switch (chan->type) {
+		case IIO_PRESSURE:
+			*val = 1 << data->oversampling_press;
+			ret = IIO_VAL_INT;
+			break;
+		case IIO_TEMP:
+			*val = 1 << data->oversampling_temp;
+			ret = IIO_VAL_INT;
 			break;
 		default:
 			ret = -EINVAL;
@@ -310,22 +372,135 @@ static int bmp280_read_raw(struct iio_de
 	return ret;
 }
 
+static int bmp280_write_oversampling_ratio_temp(struct bmp280_data *data,
+					       int val)
+{
+	int i;
+	const int *avail = data->chip_info->oversampling_temp_avail;
+	const int n = data->chip_info->num_oversampling_temp_avail;
+
+	for (i = 0; i < n; i++) {
+		if (avail[i] == val) {
+			data->oversampling_temp = ilog2(val);
+
+			return data->chip_info->chip_config(data);
+		}
+	}
+	return -EINVAL;
+}
+
+static int bmp280_write_oversampling_ratio_press(struct bmp280_data *data,
+					       int val)
+{
+	int i;
+	const int *avail = data->chip_info->oversampling_press_avail;
+	const int n = data->chip_info->num_oversampling_press_avail;
+
+	for (i = 0; i < n; i++) {
+		if (avail[i] == val) {
+			data->oversampling_press = ilog2(val);
+
+			return data->chip_info->chip_config(data);
+		}
+	}
+	return -EINVAL;
+}
+
+static int bmp280_write_raw(struct iio_dev *indio_dev,
+			    struct iio_chan_spec const *chan,
+			    int val, int val2, long mask)
+{
+	int ret = 0;
+	struct bmp280_data *data = iio_priv(indio_dev);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
+		mutex_lock(&data->lock);
+		switch (chan->type) {
+		case IIO_PRESSURE:
+			ret = bmp280_write_oversampling_ratio_press(data, val);
+			break;
+		case IIO_TEMP:
+			ret = bmp280_write_oversampling_ratio_temp(data, val);
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+		}
+		mutex_unlock(&data->lock);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+static ssize_t bmp280_show_avail(char *buf, const int *vals, const int n)
+{
+	size_t len = 0;
+	int i;
+
+	for (i = 0; i < n; i++)
+		len += scnprintf(buf + len, PAGE_SIZE - len, "%d ", vals[i]);
+
+	buf[len - 1] = '\n';
+
+	return len;
+}
+
+static ssize_t bmp280_show_temp_oversampling_avail(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct bmp280_data *data = iio_priv(dev_to_iio_dev(dev));
+
+	return bmp280_show_avail(buf, data->chip_info->oversampling_temp_avail,
+				 data->chip_info->num_oversampling_temp_avail);
+}
+
+static ssize_t bmp280_show_press_oversampling_avail(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct bmp280_data *data = iio_priv(dev_to_iio_dev(dev));
+
+	return bmp280_show_avail(buf, data->chip_info->oversampling_press_avail,
+				 data->chip_info->num_oversampling_press_avail);
+}
+
+static IIO_DEVICE_ATTR(in_temp_oversampling_ratio_available,
+	S_IRUGO, bmp280_show_temp_oversampling_avail, NULL, 0);
+
+static IIO_DEVICE_ATTR(in_pressure_oversampling_ratio_available,
+	S_IRUGO, bmp280_show_press_oversampling_avail, NULL, 0);
+
+static struct attribute *bmp280_attributes[] = {
+	&iio_dev_attr_in_temp_oversampling_ratio_available.dev_attr.attr,
+	&iio_dev_attr_in_pressure_oversampling_ratio_available.dev_attr.attr,
+	NULL,
+};
+
+static const struct attribute_group bmp280_attrs_group = {
+	.attrs = bmp280_attributes,
+};
+
 static const struct iio_info bmp280_info = {
 	.driver_module = THIS_MODULE,
 	.read_raw = &bmp280_read_raw,
+	.write_raw = &bmp280_write_raw,
+	.attrs = &bmp280_attrs_group,
 };
 
-static int bmp280_chip_init(struct bmp280_data *data)
+static int bmp280_chip_config(struct bmp280_data *data)
 {
 	int ret;
+	u8 osrs = BMP280_OSRS_TEMP_X(data->oversampling_temp + 1) |
+		  BMP280_OSRS_PRESS_X(data->oversampling_press + 1);
 
 	ret = regmap_update_bits(data->regmap, BMP280_REG_CTRL_MEAS,
 				 BMP280_OSRS_TEMP_MASK |
 				 BMP280_OSRS_PRESS_MASK |
 				 BMP280_MODE_MASK,
-				 BMP280_OSRS_TEMP_2X |
-				 BMP280_OSRS_PRESS_16X |
-				 BMP280_MODE_NORMAL);
+				 osrs | BMP280_MODE_NORMAL);
 	if (ret < 0) {
 		dev_err(&data->client->dev,
 			"failed to write ctrl_meas register\n");
@@ -344,6 +519,317 @@ static int bmp280_chip_init(struct bmp28
 	return ret;
 }
 
+static const int bmp280_oversampling_avail[] = { 1, 2, 4, 8, 16 };
+
+static const struct bmp280_chip_info bmp280_chip_info = {
+	.regmap_config = &bmp280_regmap_config,
+
+	.oversampling_temp_avail = bmp280_oversampling_avail,
+	.num_oversampling_temp_avail = ARRAY_SIZE(bmp280_oversampling_avail),
+
+	.oversampling_press_avail = bmp280_oversampling_avail,
+	.num_oversampling_press_avail = ARRAY_SIZE(bmp280_oversampling_avail),
+
+	.chip_config = bmp280_chip_config,
+	.read_temp = bmp280_read_temp,
+	.read_press = bmp280_read_press,
+};
+
+static bool bmp180_is_writeable_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case BMP280_REG_CTRL_MEAS:
+	case BMP280_REG_RESET:
+		return true;
+	default:
+		return false;
+	};
+}
+
+static bool bmp180_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case BMP180_REG_OUT_XLSB:
+	case BMP180_REG_OUT_LSB:
+	case BMP180_REG_OUT_MSB:
+	case BMP280_REG_CTRL_MEAS:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static const struct regmap_config bmp180_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register = BMP180_REG_OUT_XLSB,
+	.cache_type = REGCACHE_RBTREE,
+
+	.writeable_reg = bmp180_is_writeable_reg,
+	.volatile_reg = bmp180_is_volatile_reg,
+};
+
+static int bmp180_measure(struct bmp280_data *data, u8 ctrl_meas)
+{
+	int ret;
+	const int conversion_time_max[] = { 4500, 7500, 13500, 25500 };
+	unsigned int delay_us;
+	unsigned int ctrl;
+
+	ret = regmap_write(data->regmap, BMP280_REG_CTRL_MEAS, ctrl_meas);
+	if (ret)
+		return ret;
+
+	if (ctrl_meas == BMP180_MEAS_TEMP)
+		delay_us = 4500;
+	else
+		delay_us = conversion_time_max[data->oversampling_press];
+
+	usleep_range(delay_us, delay_us + 1000);
+
+	ret = regmap_read(data->regmap, BMP280_REG_CTRL_MEAS, &ctrl);
+	if (ret)
+		return ret;
+
+	/* The value of this bit reset to "0" after conversion is complete */
+	if (ctrl & BMP180_MEAS_SCO)
+		return -EIO;
+
+	return 0;
+}
+
+static int bmp180_read_adc_temp(struct bmp280_data *data, int *val)
+{
+	int ret;
+	__be16 tmp = 0;
+
+	ret = bmp180_measure(data, BMP180_MEAS_TEMP);
+	if (ret)
+		return ret;
+
+	ret = regmap_bulk_read(data->regmap, BMP180_REG_OUT_MSB, (u8 *)&tmp, 2);
+	if (ret)
+		return ret;
+
+	*val = be16_to_cpu(tmp);
+
+	return 0;
+}
+
+/*
+ * These enums are used for indexing into the array of calibration
+ * coefficients for BMP180.
+ */
+enum { AC1, AC2, AC3, AC4, AC5, AC6, B1, B2, MB, MC, MD };
+
+struct bmp180_calib {
+	s16 AC1;
+	s16 AC2;
+	s16 AC3;
+	u16 AC4;
+	u16 AC5;
+	u16 AC6;
+	s16 B1;
+	s16 B2;
+	s16 MB;
+	s16 MC;
+	s16 MD;
+};
+
+static int bmp180_read_calib(struct bmp280_data *data,
+			     struct bmp180_calib *calib)
+{
+	int ret;
+	int i;
+	__be16 buf[BMP180_REG_CALIB_COUNT / 2];
+
+	ret = regmap_bulk_read(data->regmap, BMP180_REG_CALIB_START, buf,
+			       sizeof(buf));
+
+	if (ret < 0)
+		return ret;
+
+	/* None of the words has the value 0 or 0xFFFF */
+	for (i = 0; i < ARRAY_SIZE(buf); i++) {
+		if (buf[i] == cpu_to_be16(0) || buf[i] == cpu_to_be16(0xffff))
+			return -EIO;
+	}
+
+	calib->AC1 = be16_to_cpu(buf[AC1]);
+	calib->AC2 = be16_to_cpu(buf[AC2]);
+	calib->AC3 = be16_to_cpu(buf[AC3]);
+	calib->AC4 = be16_to_cpu(buf[AC4]);
+	calib->AC5 = be16_to_cpu(buf[AC5]);
+	calib->AC6 = be16_to_cpu(buf[AC6]);
+	calib->B1 = be16_to_cpu(buf[B1]);
+	calib->B2 = be16_to_cpu(buf[B2]);
+	calib->MB = be16_to_cpu(buf[MB]);
+	calib->MC = be16_to_cpu(buf[MC]);
+	calib->MD = be16_to_cpu(buf[MD]);
+
+	return 0;
+}
+
+/*
+ * Returns temperature in DegC, resolution is 0.1 DegC.
+ * t_fine carries fine temperature as global value.
+ *
+ * Taken from datasheet, Section 3.5, "Calculating pressure and temperature".
+ */
+static s32 bmp180_compensate_temp(struct bmp280_data *data, s32 adc_temp)
+{
+	int ret;
+	s32 x1, x2;
+	struct bmp180_calib calib;
+
+	ret = bmp180_read_calib(data, &calib);
+	if (ret < 0) {
+		dev_err(&data->client->dev,
+			"failed to read calibration coefficients\n");
+		return ret;
+	}
+
+	x1 = ((adc_temp - calib.AC6) * calib.AC5) >> 15;
+	x2 = (calib.MC << 11) / (x1 + calib.MD);
+	data->t_fine = x1 + x2;
+
+	return (data->t_fine + 8) >> 4;
+}
+
+static int bmp180_read_temp(struct bmp280_data *data, int *val)
+{
+	int ret;
+	s32 adc_temp, comp_temp;
+
+	ret = bmp180_read_adc_temp(data, &adc_temp);
+	if (ret)
+		return ret;
+
+	comp_temp = bmp180_compensate_temp(data, adc_temp);
+
+	/*
+	 * val might be NULL if we're called by the read_press routine,
+	 * who only cares about the carry over t_fine value.
+	 */
+	if (val) {
+		*val = comp_temp * 100;
+		return IIO_VAL_INT;
+	}
+
+	return 0;
+}
+
+static int bmp180_read_adc_press(struct bmp280_data *data, int *val)
+{
+	int ret;
+	__be32 tmp = 0;
+	u8 oss = data->oversampling_press;
+
+	ret = bmp180_measure(data, BMP180_MEAS_PRESS_X(oss));
+	if (ret)
+		return ret;
+
+	ret = regmap_bulk_read(data->regmap, BMP180_REG_OUT_MSB, (u8 *)&tmp, 3);
+	if (ret)
+		return ret;
+
+	*val = (be32_to_cpu(tmp) >> 8) >> (8 - oss);
+
+	return 0;
+}
+
+/*
+ * Returns pressure in Pa, resolution is 1 Pa.
+ *
+ * Taken from datasheet, Section 3.5, "Calculating pressure and temperature".
+ */
+static u32 bmp180_compensate_press(struct bmp280_data *data, s32 adc_press)
+{
+	int ret;
+	s32 x1, x2, x3, p;
+	s32 b3, b6;
+	u32 b4, b7;
+	s32 oss = data->oversampling_press;
+	struct bmp180_calib calib;
+
+	ret = bmp180_read_calib(data, &calib);
+	if (ret < 0) {
+		dev_err(&data->client->dev,
+			"failed to read calibration coefficients\n");
+		return ret;
+	}
+
+	b6 = data->t_fine - 4000;
+	x1 = (calib.B2 * (b6 * b6 >> 12)) >> 11;
+	x2 = calib.AC2 * b6 >> 11;
+	x3 = x1 + x2;
+	b3 = ((((s32)calib.AC1 * 4 + x3) << oss) + 2) / 4;
+	x1 = calib.AC3 * b6 >> 13;
+	x2 = (calib.B1 * ((b6 * b6) >> 12)) >> 16;
+	x3 = (x1 + x2 + 2) >> 2;
+	b4 = calib.AC4 * (u32)(x3 + 32768) >> 15;
+	b7 = ((u32)adc_press - b3) * (50000 >> oss);
+	if (b7 < 0x80000000)
+		p = (b7 * 2) / b4;
+	else
+		p = (b7 / b4) * 2;
+
+	x1 = (p >> 8) * (p >> 8);
+	x1 = (x1 * 3038) >> 16;
+	x2 = (-7357 * p) >> 16;
+
+	return p + ((x1 + x2 + 3791) >> 4);
+}
+
+static int bmp180_read_press(struct bmp280_data *data,
+			     int *val, int *val2)
+{
+	int ret;
+	s32 adc_press;
+	u32 comp_press;
+
+	/* Read and compensate temperature so we get a reading of t_fine. */
+	ret = bmp180_read_temp(data, NULL);
+	if (ret)
+		return ret;
+
+	ret = bmp180_read_adc_press(data, &adc_press);
+	if (ret)
+		return ret;
+
+	comp_press = bmp180_compensate_press(data, adc_press);
+
+	*val = comp_press;
+	*val2 = 1000;
+
+	return IIO_VAL_FRACTIONAL;
+}
+
+static int bmp180_chip_config(struct bmp280_data *data)
+{
+	return 0;
+}
+
+static const int bmp180_oversampling_temp_avail[] = { 1 };
+static const int bmp180_oversampling_press_avail[] = { 1, 2, 4, 8 };
+
+static const struct bmp280_chip_info bmp180_chip_info = {
+	.regmap_config = &bmp180_regmap_config,
+
+	.oversampling_temp_avail = bmp180_oversampling_temp_avail,
+	.num_oversampling_temp_avail =
+		ARRAY_SIZE(bmp180_oversampling_temp_avail),
+
+	.oversampling_press_avail = bmp180_oversampling_press_avail,
+	.num_oversampling_press_avail =
+		ARRAY_SIZE(bmp180_oversampling_press_avail),
+
+	.chip_config = bmp180_chip_config,
+	.read_temp = bmp180_read_temp,
+	.read_press = bmp180_read_press,
+};
+
 static int bmp280_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
@@ -367,7 +853,23 @@ static int bmp280_probe(struct i2c_clien
 	indio_dev->info = &bmp280_info;
 	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	data->regmap = devm_regmap_init_i2c(client, &bmp280_regmap_config);
+	switch (id->driver_data) {
+	case BMP180_CHIP_ID:
+		data->chip_info = &bmp180_chip_info;
+		data->oversampling_press = ilog2(8);
+		data->oversampling_temp = ilog2(1);
+		break;
+	case BMP280_CHIP_ID:
+		data->chip_info = &bmp280_chip_info;
+		data->oversampling_press = ilog2(16);
+		data->oversampling_temp = ilog2(2);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	data->regmap = devm_regmap_init_i2c(client,
+					data->chip_info->regmap_config);
 	if (IS_ERR(data->regmap)) {
 		dev_err(&client->dev, "failed to allocate register map\n");
 		return PTR_ERR(data->regmap);
@@ -376,13 +878,13 @@ static int bmp280_probe(struct i2c_clien
 	ret = regmap_read(data->regmap, BMP280_REG_ID, &chip_id);
 	if (ret < 0)
 		return ret;
-	if (chip_id != BMP280_CHIP_ID) {
-		dev_err(&client->dev, "bad chip id.  expected %x got %x\n",
-			BMP280_CHIP_ID, chip_id);
+	if (chip_id != id->driver_data) {
+		dev_err(&client->dev, "bad chip id.  expected %lx got %x\n",
+			id->driver_data, chip_id);
 		return -EINVAL;
 	}
 
-	ret = bmp280_chip_init(data);
+	ret = data->chip_info->chip_config(data);
 	if (ret < 0)
 		return ret;
 
@@ -390,13 +892,17 @@ static int bmp280_probe(struct i2c_clien
 }
 
 static const struct acpi_device_id bmp280_acpi_match[] = {
-	{"BMP0280", 0},
+	{"BMP0280", BMP280_CHIP_ID },
+	{"BMP0180", BMP180_CHIP_ID },
+	{"BMP0085", BMP180_CHIP_ID },
 	{ },
 };
 MODULE_DEVICE_TABLE(acpi, bmp280_acpi_match);
 
 static const struct i2c_device_id bmp280_id[] = {
-	{"bmp280", 0},
+	{"bmp280", BMP280_CHIP_ID },
+	{"bmp180", BMP180_CHIP_ID },
+	{"bmp085", BMP180_CHIP_ID },
 	{ },
 };
 MODULE_DEVICE_TABLE(i2c, bmp280_id);
@@ -412,5 +918,5 @@ static struct i2c_driver bmp280_driver =
 module_i2c_driver(bmp280_driver);
 
 MODULE_AUTHOR("Vlad Dogaru <vlad.dogaru@intel.com>");
-MODULE_DESCRIPTION("Driver for Bosch Sensortec BMP280 pressure and temperature sensor");
+MODULE_DESCRIPTION("Driver for Bosch Sensortec BMP180/BMP280 pressure and temperature sensor");
 MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/pressure/hp03.c linux-libre-4.7-gnu/drivers/iio/pressure/hp03.c
--- linux-libre-4.6-gnu/drivers/iio/pressure/hp03.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/iio/pressure/hp03.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,312 @@
+/*
+ * Copyright (c) 2016 Marek Vasut <marex@denx.de>
+ *
+ * Driver for Hope RF HP03 digital temperature and pressure sensor.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define pr_fmt(fmt) "hp03: " fmt
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+
+/*
+ * The HP03 sensor occupies two fixed I2C addresses:
+ *  0x50 ... read-only EEPROM with calibration data
+ *  0x77 ... read-write ADC for pressure and temperature
+ */
+#define HP03_EEPROM_ADDR		0x50
+#define HP03_ADC_ADDR			0x77
+
+#define HP03_EEPROM_CX_OFFSET		0x10
+#define HP03_EEPROM_AB_OFFSET		0x1e
+#define HP03_EEPROM_CD_OFFSET		0x20
+
+#define HP03_ADC_WRITE_REG		0xff
+#define HP03_ADC_READ_REG		0xfd
+#define HP03_ADC_READ_PRESSURE		0xf0	/* D1 in datasheet */
+#define HP03_ADC_READ_TEMP		0xe8	/* D2 in datasheet */
+
+struct hp03_priv {
+	struct i2c_client	*client;
+	struct mutex		lock;
+	struct gpio_desc	*xclr_gpio;
+
+	struct i2c_client	*eeprom_client;
+	struct regmap		*eeprom_regmap;
+
+	s32			pressure;	/* kPa */
+	s32			temp;		/* Deg. C */
+};
+
+static const struct iio_chan_spec hp03_channels[] = {
+	{
+		.type = IIO_PRESSURE,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+	},
+	{
+		.type = IIO_TEMP,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+	},
+};
+
+static bool hp03_is_writeable_reg(struct device *dev, unsigned int reg)
+{
+	return false;
+}
+
+static bool hp03_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+	return false;
+}
+
+static const struct regmap_config hp03_regmap_config = {
+	.reg_bits	= 8,
+	.val_bits	= 8,
+
+	.max_register	= HP03_EEPROM_CD_OFFSET + 1,
+	.cache_type	= REGCACHE_RBTREE,
+
+	.writeable_reg	= hp03_is_writeable_reg,
+	.volatile_reg	= hp03_is_volatile_reg,
+};
+
+static int hp03_get_temp_pressure(struct hp03_priv *priv, const u8 reg)
+{
+	int ret;
+
+	ret = i2c_smbus_write_byte_data(priv->client, HP03_ADC_WRITE_REG, reg);
+	if (ret < 0)
+		return ret;
+
+	msleep(50);	/* Wait for conversion to finish */
+
+	return i2c_smbus_read_word_data(priv->client, HP03_ADC_READ_REG);
+}
+
+static int hp03_update_temp_pressure(struct hp03_priv *priv)
+{
+	struct device *dev = &priv->client->dev;
+	u8 coefs[18];
+	u16 cx_val[7];
+	int ab_val, d1_val, d2_val, diff_val, dut, off, sens, x;
+	int i, ret;
+
+	/* Sample coefficients from EEPROM */
+	ret = regmap_bulk_read(priv->eeprom_regmap, HP03_EEPROM_CX_OFFSET,
+			       coefs, sizeof(coefs));
+	if (ret < 0) {
+		dev_err(dev, "Failed to read EEPROM (reg=%02x)\n",
+			HP03_EEPROM_CX_OFFSET);
+		return ret;
+	}
+
+	/* Sample Temperature and Pressure */
+	gpiod_set_value_cansleep(priv->xclr_gpio, 1);
+
+	ret = hp03_get_temp_pressure(priv, HP03_ADC_READ_PRESSURE);
+	if (ret < 0) {
+		dev_err(dev, "Failed to read pressure\n");
+		goto err_adc;
+	}
+	d1_val = ret;
+
+	ret = hp03_get_temp_pressure(priv, HP03_ADC_READ_TEMP);
+	if (ret < 0) {
+		dev_err(dev, "Failed to read temperature\n");
+		goto err_adc;
+	}
+	d2_val = ret;
+
+	gpiod_set_value_cansleep(priv->xclr_gpio, 0);
+
+	/* The Cx coefficients and Temp/Pressure values are MSB first. */
+	for (i = 0; i < 7; i++)
+		cx_val[i] = (coefs[2 * i] << 8) | (coefs[(2 * i) + 1] << 0);
+	d1_val = ((d1_val >> 8) & 0xff) | ((d1_val & 0xff) << 8);
+	d2_val = ((d2_val >> 8) & 0xff) | ((d2_val & 0xff) << 8);
+
+	/* Coefficient voodoo from the HP03 datasheet. */
+	if (d2_val >= cx_val[4])
+		ab_val = coefs[14];	/* A-value */
+	else
+		ab_val = coefs[15];	/* B-value */
+
+	diff_val = d2_val - cx_val[4];
+	dut = (ab_val * (diff_val >> 7) * (diff_val >> 7)) >> coefs[16];
+	dut = diff_val - dut;
+
+	off = (cx_val[1] + (((cx_val[3] - 1024) * dut) >> 14)) * 4;
+	sens = cx_val[0] + ((cx_val[2] * dut) >> 10);
+	x = ((sens * (d1_val - 7168)) >> 14) - off;
+
+	priv->pressure = ((x * 100) >> 5) + (cx_val[6] * 10);
+	priv->temp = 250 + ((dut * cx_val[5]) >> 16) - (dut >> coefs[17]);
+
+	return 0;
+
+err_adc:
+	gpiod_set_value_cansleep(priv->xclr_gpio, 0);
+	return ret;
+}
+
+static int hp03_read_raw(struct iio_dev *indio_dev,
+			 struct iio_chan_spec const *chan,
+			 int *val, int *val2, long mask)
+{
+	struct hp03_priv *priv = iio_priv(indio_dev);
+	int ret;
+
+	mutex_lock(&priv->lock);
+	ret = hp03_update_temp_pressure(priv);
+	mutex_unlock(&priv->lock);
+
+	if (ret)
+		return ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		switch (chan->type) {
+		case IIO_PRESSURE:
+			*val = priv->pressure;
+			return IIO_VAL_INT;
+		case IIO_TEMP:
+			*val = priv->temp;
+			return IIO_VAL_INT;
+		default:
+			return -EINVAL;
+		}
+		break;
+	case IIO_CHAN_INFO_SCALE:
+		switch (chan->type) {
+		case IIO_PRESSURE:
+			*val = 0;
+			*val2 = 1000;
+			return IIO_VAL_INT_PLUS_MICRO;
+		case IIO_TEMP:
+			*val = 10;
+			return IIO_VAL_INT;
+		default:
+			return -EINVAL;
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return -EINVAL;
+}
+
+static const struct iio_info hp03_info = {
+	.driver_module	= THIS_MODULE,
+	.read_raw	= &hp03_read_raw,
+};
+
+static int hp03_probe(struct i2c_client *client,
+		      const struct i2c_device_id *id)
+{
+	struct device *dev = &client->dev;
+	struct iio_dev *indio_dev;
+	struct hp03_priv *priv;
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(dev, sizeof(*priv));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	priv = iio_priv(indio_dev);
+	priv->client = client;
+	mutex_init(&priv->lock);
+
+	indio_dev->dev.parent = dev;
+	indio_dev->name = id->name;
+	indio_dev->channels = hp03_channels;
+	indio_dev->num_channels = ARRAY_SIZE(hp03_channels);
+	indio_dev->info = &hp03_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	priv->xclr_gpio = devm_gpiod_get_index(dev, "xclr", 0, GPIOD_OUT_HIGH);
+	if (IS_ERR(priv->xclr_gpio)) {
+		dev_err(dev, "Failed to claim XCLR GPIO\n");
+		ret = PTR_ERR(priv->xclr_gpio);
+		return ret;
+	}
+
+	/*
+	 * Allocate another device for the on-sensor EEPROM,
+	 * which has it's dedicated I2C address and contains
+	 * the calibration constants for the sensor.
+	 */
+	priv->eeprom_client = i2c_new_dummy(client->adapter, HP03_EEPROM_ADDR);
+	if (!priv->eeprom_client) {
+		dev_err(dev, "New EEPROM I2C device failed\n");
+		return -ENODEV;
+	}
+
+	priv->eeprom_regmap = regmap_init_i2c(priv->eeprom_client,
+					      &hp03_regmap_config);
+	if (IS_ERR(priv->eeprom_regmap)) {
+		dev_err(dev, "Failed to allocate EEPROM regmap\n");
+		ret = PTR_ERR(priv->eeprom_regmap);
+		goto err_cleanup_eeprom_client;
+	}
+
+	ret = iio_device_register(indio_dev);
+	if (ret) {
+		dev_err(dev, "Failed to register IIO device\n");
+		goto err_cleanup_eeprom_regmap;
+	}
+
+	i2c_set_clientdata(client, indio_dev);
+
+	return 0;
+
+err_cleanup_eeprom_regmap:
+	regmap_exit(priv->eeprom_regmap);
+
+err_cleanup_eeprom_client:
+	i2c_unregister_device(priv->eeprom_client);
+	return ret;
+}
+
+static int hp03_remove(struct i2c_client *client)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+	struct hp03_priv *priv = iio_priv(indio_dev);
+
+	iio_device_unregister(indio_dev);
+	regmap_exit(priv->eeprom_regmap);
+	i2c_unregister_device(priv->eeprom_client);
+
+	return 0;
+}
+
+static const struct i2c_device_id hp03_id[] = {
+	{ "hp03", 0 },
+	{ },
+};
+MODULE_DEVICE_TABLE(i2c, hp03_id);
+
+static struct i2c_driver hp03_driver = {
+	.driver = {
+		.name	= "hp03",
+	},
+	.probe		= hp03_probe,
+	.remove		= hp03_remove,
+	.id_table	= hp03_id,
+};
+module_i2c_driver(hp03_driver);
+
+MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
+MODULE_DESCRIPTION("Driver for Hope RF HP03 pressure and temperature sensor");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/pressure/hp206c.c linux-libre-4.7-gnu/drivers/iio/pressure/hp206c.c
--- linux-libre-4.6-gnu/drivers/iio/pressure/hp206c.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/iio/pressure/hp206c.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,426 @@
+/*
+ * hp206c.c - HOPERF HP206C precision barometer and altimeter sensor
+ *
+ * Copyright (c) 2016, Intel Corporation.
+ *
+ * This file is subject to the terms and conditions of version 2 of
+ * the GNU General Public License.  See the file COPYING in the main
+ * directory of this archive for more details.
+ *
+ * (7-bit I2C slave address 0x76)
+ *
+ * Datasheet:
+ *  http://www.hoperf.com/upload/sensor/HP206C_DataSheet_EN_V2.0.pdf
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/delay.h>
+#include <linux/util_macros.h>
+#include <linux/acpi.h>
+
+/* I2C commands: */
+#define HP206C_CMD_SOFT_RST	0x06
+
+#define HP206C_CMD_ADC_CVT	0x40
+
+#define HP206C_CMD_ADC_CVT_OSR_4096	0x00
+#define HP206C_CMD_ADC_CVT_OSR_2048	0x04
+#define HP206C_CMD_ADC_CVT_OSR_1024	0x08
+#define HP206C_CMD_ADC_CVT_OSR_512	0x0c
+#define HP206C_CMD_ADC_CVT_OSR_256	0x10
+#define HP206C_CMD_ADC_CVT_OSR_128	0x14
+
+#define HP206C_CMD_ADC_CVT_CHNL_PT	0x00
+#define HP206C_CMD_ADC_CVT_CHNL_T	0x02
+
+#define HP206C_CMD_READ_P	0x30
+#define HP206C_CMD_READ_T	0x32
+
+#define HP206C_CMD_READ_REG	0x80
+#define HP206C_CMD_WRITE_REG	0xc0
+
+#define HP206C_REG_INT_EN	0x0b
+#define HP206C_REG_INT_CFG	0x0c
+
+#define HP206C_REG_INT_SRC	0x0d
+#define HP206C_FLAG_DEV_RDY	0x40
+
+#define HP206C_REG_PARA		0x0f
+#define HP206C_FLAG_CMPS_EN	0x80
+
+/* Maximum spin for DEV_RDY */
+#define HP206C_MAX_DEV_RDY_WAIT_COUNT 20
+#define HP206C_DEV_RDY_WAIT_US    20000
+
+struct hp206c_data {
+	struct mutex mutex;
+	struct i2c_client *client;
+	int temp_osr_index;
+	int pres_osr_index;
+};
+
+struct hp206c_osr_setting {
+	u8 osr_mask;
+	unsigned int temp_conv_time_us;
+	unsigned int pres_conv_time_us;
+};
+
+/* Data from Table 5 in datasheet. */
+static const struct hp206c_osr_setting hp206c_osr_settings[] = {
+	{ HP206C_CMD_ADC_CVT_OSR_4096,	65600,	131100	},
+	{ HP206C_CMD_ADC_CVT_OSR_2048,	32800,	65600	},
+	{ HP206C_CMD_ADC_CVT_OSR_1024,	16400,	32800	},
+	{ HP206C_CMD_ADC_CVT_OSR_512,	8200,	16400	},
+	{ HP206C_CMD_ADC_CVT_OSR_256,	4100,	8200	},
+	{ HP206C_CMD_ADC_CVT_OSR_128,	2100,	4100	},
+};
+static const int hp206c_osr_rates[] = { 4096, 2048, 1024, 512, 256, 128 };
+static const char hp206c_osr_rates_str[] = "4096 2048 1024 512 256 128";
+
+static inline int hp206c_read_reg(struct i2c_client *client, u8 reg)
+{
+	return i2c_smbus_read_byte_data(client, HP206C_CMD_READ_REG | reg);
+}
+
+static inline int hp206c_write_reg(struct i2c_client *client, u8 reg, u8 val)
+{
+	return i2c_smbus_write_byte_data(client,
+			HP206C_CMD_WRITE_REG | reg, val);
+}
+
+static int hp206c_read_20bit(struct i2c_client *client, u8 cmd)
+{
+	int ret;
+	u8 values[3];
+
+	ret = i2c_smbus_read_i2c_block_data(client, cmd, 3, values);
+	if (ret < 0)
+		return ret;
+	if (ret != 3)
+		return -EIO;
+	return ((values[0] & 0xF) << 16) | (values[1] << 8) | (values[2]);
+}
+
+/* Spin for max 160ms until DEV_RDY is 1, or return error. */
+static int hp206c_wait_dev_rdy(struct iio_dev *indio_dev)
+{
+	int ret;
+	int count = 0;
+	struct hp206c_data *data = iio_priv(indio_dev);
+	struct i2c_client *client = data->client;
+
+	while (++count <= HP206C_MAX_DEV_RDY_WAIT_COUNT) {
+		ret = hp206c_read_reg(client, HP206C_REG_INT_SRC);
+		if (ret < 0) {
+			dev_err(&indio_dev->dev, "Failed READ_REG INT_SRC: %d\n", ret);
+			return ret;
+		}
+		if (ret & HP206C_FLAG_DEV_RDY)
+			return 0;
+		usleep_range(HP206C_DEV_RDY_WAIT_US, HP206C_DEV_RDY_WAIT_US * 3 / 2);
+	}
+	return -ETIMEDOUT;
+}
+
+static int hp206c_set_compensation(struct i2c_client *client, bool enabled)
+{
+	int val;
+
+	val = hp206c_read_reg(client, HP206C_REG_PARA);
+	if (val < 0)
+		return val;
+	if (enabled)
+		val |= HP206C_FLAG_CMPS_EN;
+	else
+		val &= ~HP206C_FLAG_CMPS_EN;
+
+	return hp206c_write_reg(client, HP206C_REG_PARA, val);
+}
+
+/* Do a soft reset */
+static int hp206c_soft_reset(struct iio_dev *indio_dev)
+{
+	int ret;
+	struct hp206c_data *data = iio_priv(indio_dev);
+	struct i2c_client *client = data->client;
+
+	ret = i2c_smbus_write_byte(client, HP206C_CMD_SOFT_RST);
+	if (ret) {
+		dev_err(&client->dev, "Failed to reset device: %d\n", ret);
+		return ret;
+	}
+
+	usleep_range(400, 600);
+
+	ret = hp206c_wait_dev_rdy(indio_dev);
+	if (ret) {
+		dev_err(&client->dev, "Device not ready after soft reset: %d\n", ret);
+		return ret;
+	}
+
+	ret = hp206c_set_compensation(client, true);
+	if (ret)
+		dev_err(&client->dev, "Failed to enable compensation: %d\n", ret);
+	return ret;
+}
+
+static int hp206c_conv_and_read(struct iio_dev *indio_dev,
+				u8 conv_cmd, u8 read_cmd,
+				unsigned int sleep_us)
+{
+	int ret;
+	struct hp206c_data *data = iio_priv(indio_dev);
+	struct i2c_client *client = data->client;
+
+	ret = hp206c_wait_dev_rdy(indio_dev);
+	if (ret < 0) {
+		dev_err(&indio_dev->dev, "Device not ready: %d\n", ret);
+		return ret;
+	}
+
+	ret = i2c_smbus_write_byte(client, conv_cmd);
+	if (ret < 0) {
+		dev_err(&indio_dev->dev, "Failed convert: %d\n", ret);
+		return ret;
+	}
+
+	usleep_range(sleep_us, sleep_us * 3 / 2);
+
+	ret = hp206c_wait_dev_rdy(indio_dev);
+	if (ret < 0) {
+		dev_err(&indio_dev->dev, "Device not ready: %d\n", ret);
+		return ret;
+	}
+
+	ret = hp206c_read_20bit(client, read_cmd);
+	if (ret < 0)
+		dev_err(&indio_dev->dev, "Failed read: %d\n", ret);
+
+	return ret;
+}
+
+static int hp206c_read_raw(struct iio_dev *indio_dev,
+			   struct iio_chan_spec const *chan, int *val,
+			   int *val2, long mask)
+{
+	int ret;
+	struct hp206c_data *data = iio_priv(indio_dev);
+	const struct hp206c_osr_setting *osr_setting;
+	u8 conv_cmd;
+
+	mutex_lock(&data->mutex);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
+		switch (chan->type) {
+		case IIO_TEMP:
+			*val = hp206c_osr_rates[data->temp_osr_index];
+			ret = IIO_VAL_INT;
+			break;
+
+		case IIO_PRESSURE:
+			*val = hp206c_osr_rates[data->pres_osr_index];
+			ret = IIO_VAL_INT;
+			break;
+		default:
+			ret = -EINVAL;
+		}
+		break;
+
+	case IIO_CHAN_INFO_RAW:
+		switch (chan->type) {
+		case IIO_TEMP:
+			osr_setting = &hp206c_osr_settings[data->temp_osr_index];
+			conv_cmd = HP206C_CMD_ADC_CVT |
+					osr_setting->osr_mask |
+					HP206C_CMD_ADC_CVT_CHNL_T;
+			ret = hp206c_conv_and_read(indio_dev,
+					conv_cmd,
+					HP206C_CMD_READ_T,
+					osr_setting->temp_conv_time_us);
+			if (ret >= 0) {
+				/* 20 significant bits are provided.
+				 * Extend sign over the rest.
+				 */
+				*val = sign_extend32(ret, 19);
+				ret = IIO_VAL_INT;
+			}
+			break;
+
+		case IIO_PRESSURE:
+			osr_setting = &hp206c_osr_settings[data->pres_osr_index];
+			conv_cmd = HP206C_CMD_ADC_CVT |
+					osr_setting->osr_mask |
+					HP206C_CMD_ADC_CVT_CHNL_PT;
+			ret = hp206c_conv_and_read(indio_dev,
+					conv_cmd,
+					HP206C_CMD_READ_P,
+					osr_setting->pres_conv_time_us);
+			if (ret >= 0) {
+				*val = ret;
+				ret = IIO_VAL_INT;
+			}
+			break;
+		default:
+			ret = -EINVAL;
+		}
+		break;
+
+	case IIO_CHAN_INFO_SCALE:
+		switch (chan->type) {
+		case IIO_TEMP:
+			*val = 0;
+			*val2 = 10000;
+			ret = IIO_VAL_INT_PLUS_MICRO;
+			break;
+
+		case IIO_PRESSURE:
+			*val = 0;
+			*val2 = 1000;
+			ret = IIO_VAL_INT_PLUS_MICRO;
+			break;
+		default:
+			ret = -EINVAL;
+		}
+		break;
+
+	default:
+		ret = -EINVAL;
+	}
+
+	mutex_unlock(&data->mutex);
+	return ret;
+}
+
+static int hp206c_write_raw(struct iio_dev *indio_dev,
+			    struct iio_chan_spec const *chan,
+			    int val, int val2, long mask)
+{
+	int ret = 0;
+	struct hp206c_data *data = iio_priv(indio_dev);
+
+	if (mask != IIO_CHAN_INFO_OVERSAMPLING_RATIO)
+		return -EINVAL;
+	mutex_lock(&data->mutex);
+	switch (chan->type) {
+	case IIO_TEMP:
+		data->temp_osr_index = find_closest_descending(val,
+			hp206c_osr_rates, ARRAY_SIZE(hp206c_osr_rates));
+		break;
+	case IIO_PRESSURE:
+		data->pres_osr_index = find_closest_descending(val,
+			hp206c_osr_rates, ARRAY_SIZE(hp206c_osr_rates));
+		break;
+	default:
+		ret = -EINVAL;
+	}
+	mutex_unlock(&data->mutex);
+	return ret;
+}
+
+static const struct iio_chan_spec hp206c_channels[] = {
+	{
+		.type = IIO_TEMP,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+				      BIT(IIO_CHAN_INFO_SCALE) |
+				      BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+	},
+	{
+		.type = IIO_PRESSURE,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+				      BIT(IIO_CHAN_INFO_SCALE) |
+				      BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+	}
+};
+
+static IIO_CONST_ATTR_SAMP_FREQ_AVAIL(hp206c_osr_rates_str);
+
+static struct attribute *hp206c_attributes[] = {
+	&iio_const_attr_sampling_frequency_available.dev_attr.attr,
+	NULL,
+};
+
+static const struct attribute_group hp206c_attribute_group = {
+	.attrs = hp206c_attributes,
+};
+
+static const struct iio_info hp206c_info = {
+	.attrs = &hp206c_attribute_group,
+	.read_raw = hp206c_read_raw,
+	.write_raw = hp206c_write_raw,
+	.driver_module = THIS_MODULE,
+};
+
+static int hp206c_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct iio_dev *indio_dev;
+	struct hp206c_data *data;
+	int ret;
+
+	if (!i2c_check_functionality(client->adapter,
+				     I2C_FUNC_SMBUS_BYTE |
+				     I2C_FUNC_SMBUS_BYTE_DATA |
+				     I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
+		dev_err(&client->dev, "Adapter does not support "
+				"all required i2c functionality\n");
+		return -ENODEV;
+	}
+
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	data = iio_priv(indio_dev);
+	data->client = client;
+	mutex_init(&data->mutex);
+
+	indio_dev->info = &hp206c_info;
+	indio_dev->name = id->name;
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = hp206c_channels;
+	indio_dev->num_channels = ARRAY_SIZE(hp206c_channels);
+
+	i2c_set_clientdata(client, indio_dev);
+
+	/* Do a soft reset on probe */
+	ret = hp206c_soft_reset(indio_dev);
+	if (ret) {
+		dev_err(&client->dev, "Failed to reset on startup: %d\n", ret);
+		return -ENODEV;
+	}
+
+	return devm_iio_device_register(&client->dev, indio_dev);
+}
+
+static const struct i2c_device_id hp206c_id[] = {
+	{"hp206c"},
+	{}
+};
+
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id hp206c_acpi_match[] = {
+	{"HOP206C", 0},
+	{ },
+};
+MODULE_DEVICE_TABLE(acpi, hp206c_acpi_match);
+#endif
+
+static struct i2c_driver hp206c_driver = {
+	.probe = hp206c_probe,
+	.id_table = hp206c_id,
+	.driver = {
+		.name = "hp206c",
+		.acpi_match_table = ACPI_PTR(hp206c_acpi_match),
+	},
+};
+
+module_i2c_driver(hp206c_driver);
+
+MODULE_DESCRIPTION("HOPERF HP206C precision barometer and altimeter sensor");
+MODULE_AUTHOR("Leonard Crestez <leonard.crestez@intel.com>");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/pressure/Kconfig linux-libre-4.7-gnu/drivers/iio/pressure/Kconfig
--- linux-libre-4.6-gnu/drivers/iio/pressure/Kconfig	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/pressure/Kconfig	2016-07-24 15:23:50.000000000 -0400
@@ -6,12 +6,13 @@
 menu "Pressure sensors"
 
 config BMP280
-	tristate "Bosch Sensortec BMP280 pressure sensor driver"
+	tristate "Bosch Sensortec BMP180 and BMP280 pressure sensor driver"
 	depends on I2C
+	depends on !(BMP085_I2C=y || BMP085_I2C=m)
 	select REGMAP_I2C
 	help
-	  Say yes here to build support for Bosch Sensortec BMP280
-	  pressure and temperature sensor.
+	  Say yes here to build support for Bosch Sensortec BMP180 and BMP280
+	  pressure and temperature sensors.
 
 	  To compile this driver as a module, choose M here: the module
 	  will be called bmp280.
@@ -30,6 +31,17 @@ config HID_SENSOR_PRESS
 	  To compile this driver as a module, choose M here: the module
 	  will be called hid-sensor-press.
 
+config HP03
+	tristate "Hope RF HP03 temperature and pressure sensor driver"
+	depends on I2C
+	select REGMAP_I2C
+	help
+	  Say yes here to build support for Hope RF HP03 pressure and
+	  temperature sensor.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called hp03.
+
 config MPL115
 	tristate
 
@@ -148,4 +160,14 @@ config T5403
 	  To compile this driver as a module, choose M here: the module
 	  will be called t5403.
 
+config HP206C
+	tristate "HOPERF HP206C precision barometer and altimeter sensor"
+	depends on I2C
+	help
+	  Say yes here to build support for the HOPREF HP206C precision
+	  barometer and altimeter sensor.
+
+	  This driver can also be built as a module. If so, the module will
+	  be called hp206c.
+
 endmenu
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/pressure/Makefile linux-libre-4.7-gnu/drivers/iio/pressure/Makefile
--- linux-libre-4.6-gnu/drivers/iio/pressure/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/pressure/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -5,6 +5,7 @@
 # When adding new entries keep the list in alphabetical order
 obj-$(CONFIG_BMP280) += bmp280.o
 obj-$(CONFIG_HID_SENSOR_PRESS)   += hid-sensor-press.o
+obj-$(CONFIG_HP03) += hp03.o
 obj-$(CONFIG_MPL115) += mpl115.o
 obj-$(CONFIG_MPL115_I2C) += mpl115_i2c.o
 obj-$(CONFIG_MPL115_SPI) += mpl115_spi.o
@@ -17,6 +18,7 @@ obj-$(CONFIG_IIO_ST_PRESS) += st_pressur
 st_pressure-y := st_pressure_core.o
 st_pressure-$(CONFIG_IIO_BUFFER) += st_pressure_buffer.o
 obj-$(CONFIG_T5403) += t5403.o
+obj-$(CONFIG_HP206C) += hp206c.o
 
 obj-$(CONFIG_IIO_ST_PRESS_I2C) += st_pressure_i2c.o
 obj-$(CONFIG_IIO_ST_PRESS_SPI) += st_pressure_spi.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/pressure/ms5611_core.c linux-libre-4.7-gnu/drivers/iio/pressure/ms5611_core.c
--- linux-libre-4.6-gnu/drivers/iio/pressure/ms5611_core.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/pressure/ms5611_core.c	2016-07-24 15:23:50.000000000 -0400
@@ -18,11 +18,44 @@
 #include <linux/delay.h>
 #include <linux/regulator/consumer.h>
 
+#include <linux/iio/sysfs.h>
 #include <linux/iio/buffer.h>
 #include <linux/iio/triggered_buffer.h>
 #include <linux/iio/trigger_consumer.h>
 #include "ms5611.h"
 
+#define MS5611_INIT_OSR(_cmd, _conv_usec, _rate) \
+	{ .cmd = _cmd, .conv_usec = _conv_usec, .rate = _rate }
+
+static const struct ms5611_osr ms5611_avail_pressure_osr[] = {
+	MS5611_INIT_OSR(0x40, 600,  256),
+	MS5611_INIT_OSR(0x42, 1170, 512),
+	MS5611_INIT_OSR(0x44, 2280, 1024),
+	MS5611_INIT_OSR(0x46, 4540, 2048),
+	MS5611_INIT_OSR(0x48, 9040, 4096)
+};
+
+static const struct ms5611_osr ms5611_avail_temp_osr[] = {
+	MS5611_INIT_OSR(0x50, 600,  256),
+	MS5611_INIT_OSR(0x52, 1170, 512),
+	MS5611_INIT_OSR(0x54, 2280, 1024),
+	MS5611_INIT_OSR(0x56, 4540, 2048),
+	MS5611_INIT_OSR(0x58, 9040, 4096)
+};
+
+static const char ms5611_show_osr[] = "256 512 1024 2048 4096";
+
+static IIO_CONST_ATTR(oversampling_ratio_available, ms5611_show_osr);
+
+static struct attribute *ms5611_attributes[] = {
+	&iio_const_attr_oversampling_ratio_available.dev_attr.attr,
+	NULL,
+};
+
+static const struct attribute_group ms5611_attribute_group = {
+	.attrs = ms5611_attributes,
+};
+
 static bool ms5611_prom_is_valid(u16 *prom, size_t len)
 {
 	int i, j;
@@ -239,11 +272,70 @@ static int ms5611_read_raw(struct iio_de
 		default:
 			return -EINVAL;
 		}
+	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
+		if (chan->type != IIO_TEMP && chan->type != IIO_PRESSURE)
+			break;
+		mutex_lock(&st->lock);
+		if (chan->type == IIO_TEMP)
+			*val = (int)st->temp_osr->rate;
+		else
+			*val = (int)st->pressure_osr->rate;
+		mutex_unlock(&st->lock);
+		return IIO_VAL_INT;
 	}
 
 	return -EINVAL;
 }
 
+static const struct ms5611_osr *ms5611_find_osr(int rate,
+						const struct ms5611_osr *osr,
+						size_t count)
+{
+	unsigned int r;
+
+	for (r = 0; r < count; r++)
+		if ((unsigned short)rate == osr[r].rate)
+			break;
+	if (r >= count)
+		return NULL;
+	return &osr[r];
+}
+
+static int ms5611_write_raw(struct iio_dev *indio_dev,
+			    struct iio_chan_spec const *chan,
+			    int val, int val2, long mask)
+{
+	struct ms5611_state *st = iio_priv(indio_dev);
+	const struct ms5611_osr *osr = NULL;
+
+	if (mask != IIO_CHAN_INFO_OVERSAMPLING_RATIO)
+		return -EINVAL;
+
+	if (chan->type == IIO_TEMP)
+		osr = ms5611_find_osr(val, ms5611_avail_temp_osr,
+				      ARRAY_SIZE(ms5611_avail_temp_osr));
+	else if (chan->type == IIO_PRESSURE)
+		osr = ms5611_find_osr(val, ms5611_avail_pressure_osr,
+				      ARRAY_SIZE(ms5611_avail_pressure_osr));
+	if (!osr)
+		return -EINVAL;
+
+	mutex_lock(&st->lock);
+
+	if (iio_buffer_enabled(indio_dev)) {
+		mutex_unlock(&st->lock);
+		return -EBUSY;
+	}
+
+	if (chan->type == IIO_TEMP)
+		st->temp_osr = osr;
+	else
+		st->pressure_osr = osr;
+
+	mutex_unlock(&st->lock);
+	return 0;
+}
+
 static const unsigned long ms5611_scan_masks[] = {0x3, 0};
 
 static struct ms5611_chip_info chip_info_tbl[] = {
@@ -259,7 +351,8 @@ static const struct iio_chan_spec ms5611
 	{
 		.type = IIO_PRESSURE,
 		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
-			BIT(IIO_CHAN_INFO_SCALE),
+			BIT(IIO_CHAN_INFO_SCALE) |
+			BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
 		.scan_index = 0,
 		.scan_type = {
 			.sign = 's',
@@ -271,7 +364,8 @@ static const struct iio_chan_spec ms5611
 	{
 		.type = IIO_TEMP,
 		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
-			BIT(IIO_CHAN_INFO_SCALE),
+			BIT(IIO_CHAN_INFO_SCALE) |
+			BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
 		.scan_index = 1,
 		.scan_type = {
 			.sign = 's',
@@ -285,40 +379,68 @@ static const struct iio_chan_spec ms5611
 
 static const struct iio_info ms5611_info = {
 	.read_raw = &ms5611_read_raw,
+	.write_raw = &ms5611_write_raw,
+	.attrs = &ms5611_attribute_group,
 	.driver_module = THIS_MODULE,
 };
 
 static int ms5611_init(struct iio_dev *indio_dev)
 {
 	int ret;
-	struct regulator *vdd = devm_regulator_get(indio_dev->dev.parent,
-	                                           "vdd");
+	struct ms5611_state *st = iio_priv(indio_dev);
 
 	/* Enable attached regulator if any. */
-	if (!IS_ERR(vdd)) {
-		ret = regulator_enable(vdd);
+	st->vdd = devm_regulator_get(indio_dev->dev.parent, "vdd");
+	if (!IS_ERR(st->vdd)) {
+		ret = regulator_enable(st->vdd);
 		if (ret) {
 			dev_err(indio_dev->dev.parent,
-			        "failed to enable Vdd supply: %d\n", ret);
+				"failed to enable Vdd supply: %d\n", ret);
 			return ret;
 		}
+	} else {
+		ret = PTR_ERR(st->vdd);
+		if (ret != -ENODEV)
+			return ret;
 	}
 
 	ret = ms5611_reset(indio_dev);
 	if (ret < 0)
-		return ret;
+		goto err_regulator_disable;
 
-	return ms5611_read_prom(indio_dev);
+	ret = ms5611_read_prom(indio_dev);
+	if (ret < 0)
+		goto err_regulator_disable;
+
+	return 0;
+
+err_regulator_disable:
+	if (!IS_ERR_OR_NULL(st->vdd))
+		regulator_disable(st->vdd);
+	return ret;
+}
+
+static void ms5611_fini(const struct iio_dev *indio_dev)
+{
+	const struct ms5611_state *st = iio_priv(indio_dev);
+
+	if (!IS_ERR_OR_NULL(st->vdd))
+		regulator_disable(st->vdd);
 }
 
 int ms5611_probe(struct iio_dev *indio_dev, struct device *dev,
-                 const char *name, int type)
+		 const char *name, int type)
 {
 	int ret;
 	struct ms5611_state *st = iio_priv(indio_dev);
 
 	mutex_init(&st->lock);
 	st->chip_info = &chip_info_tbl[type];
+	st->temp_osr =
+		&ms5611_avail_temp_osr[ARRAY_SIZE(ms5611_avail_temp_osr) - 1];
+	st->pressure_osr =
+		&ms5611_avail_pressure_osr[ARRAY_SIZE(ms5611_avail_pressure_osr)
+					   - 1];
 	indio_dev->dev.parent = dev;
 	indio_dev->name = name;
 	indio_dev->info = &ms5611_info;
@@ -335,7 +457,7 @@ int ms5611_probe(struct iio_dev *indio_d
 					 ms5611_trigger_handler, NULL);
 	if (ret < 0) {
 		dev_err(dev, "iio triggered buffer setup failed\n");
-		return ret;
+		goto err_fini;
 	}
 
 	ret = iio_device_register(indio_dev);
@@ -348,7 +470,8 @@ int ms5611_probe(struct iio_dev *indio_d
 
 err_buffer_cleanup:
 	iio_triggered_buffer_cleanup(indio_dev);
-
+err_fini:
+	ms5611_fini(indio_dev);
 	return ret;
 }
 EXPORT_SYMBOL(ms5611_probe);
@@ -357,6 +480,7 @@ int ms5611_remove(struct iio_dev *indio_
 {
 	iio_device_unregister(indio_dev);
 	iio_triggered_buffer_cleanup(indio_dev);
+	ms5611_fini(indio_dev);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/pressure/ms5611.h linux-libre-4.7-gnu/drivers/iio/pressure/ms5611.h
--- linux-libre-4.6-gnu/drivers/iio/pressure/ms5611.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/pressure/ms5611.h	2016-07-24 15:23:50.000000000 -0400
@@ -16,15 +16,11 @@
 #include <linux/iio/iio.h>
 #include <linux/mutex.h>
 
+struct regulator;
+
 #define MS5611_RESET			0x1e
 #define MS5611_READ_ADC			0x00
 #define MS5611_READ_PROM_WORD		0xA0
-#define MS5611_START_TEMP_CONV		0x58
-#define MS5611_START_PRESSURE_CONV	0x48
-
-#define MS5611_CONV_TIME_MIN		9040
-#define MS5611_CONV_TIME_MAX		10000
-
 #define MS5611_PROM_WORDS_NB		8
 
 enum {
@@ -39,16 +35,31 @@ struct ms5611_chip_info {
 					    s32 *temp, s32 *pressure);
 };
 
+/*
+ * OverSampling Rate descriptor.
+ * Warning: cmd MUST be kept aligned on a word boundary (see
+ * m5611_spi_read_adc_temp_and_pressure in ms5611_spi.c).
+ */
+struct ms5611_osr {
+	unsigned long conv_usec;
+	u8 cmd;
+	unsigned short rate;
+};
+
 struct ms5611_state {
 	void *client;
 	struct mutex lock;
 
+	const struct ms5611_osr *pressure_osr;
+	const struct ms5611_osr *temp_osr;
+
 	int (*reset)(struct device *dev);
 	int (*read_prom_word)(struct device *dev, int index, u16 *word);
 	int (*read_adc_temp_and_pressure)(struct device *dev,
 					  s32 *temp, s32 *pressure);
 
 	struct ms5611_chip_info *chip_info;
+	struct regulator *vdd;
 };
 
 int ms5611_probe(struct iio_dev *indio_dev, struct device *dev,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/pressure/ms5611_i2c.c linux-libre-4.7-gnu/drivers/iio/pressure/ms5611_i2c.c
--- linux-libre-4.6-gnu/drivers/iio/pressure/ms5611_i2c.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/pressure/ms5611_i2c.c	2016-07-24 15:23:50.000000000 -0400
@@ -17,6 +17,7 @@
 #include <linux/delay.h>
 #include <linux/i2c.h>
 #include <linux/module.h>
+#include <linux/of_device.h>
 
 #include "ms5611.h"
 
@@ -62,23 +63,23 @@ static int ms5611_i2c_read_adc_temp_and_
 {
 	int ret;
 	struct ms5611_state *st = iio_priv(dev_to_iio_dev(dev));
+	const struct ms5611_osr *osr = st->temp_osr;
 
-	ret = i2c_smbus_write_byte(st->client, MS5611_START_TEMP_CONV);
+	ret = i2c_smbus_write_byte(st->client, osr->cmd);
 	if (ret < 0)
 		return ret;
 
-	usleep_range(MS5611_CONV_TIME_MIN, MS5611_CONV_TIME_MAX);
-
+	usleep_range(osr->conv_usec, osr->conv_usec + (osr->conv_usec / 10UL));
 	ret = ms5611_i2c_read_adc(st, temp);
 	if (ret < 0)
 		return ret;
 
-	ret = i2c_smbus_write_byte(st->client, MS5611_START_PRESSURE_CONV);
+	osr = st->pressure_osr;
+	ret = i2c_smbus_write_byte(st->client, osr->cmd);
 	if (ret < 0)
 		return ret;
 
-	usleep_range(MS5611_CONV_TIME_MIN, MS5611_CONV_TIME_MAX);
-
+	usleep_range(osr->conv_usec, osr->conv_usec + (osr->conv_usec / 10UL));
 	return ms5611_i2c_read_adc(st, pressure);
 }
 
@@ -113,6 +114,17 @@ static int ms5611_i2c_remove(struct i2c_
 	return ms5611_remove(i2c_get_clientdata(client));
 }
 
+#if defined(CONFIG_OF)
+static const struct of_device_id ms5611_i2c_matches[] = {
+	{ .compatible = "meas,ms5611" },
+	{ .compatible = "ms5611" },
+	{ .compatible = "meas,ms5607" },
+	{ .compatible = "ms5607" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, ms5611_i2c_matches);
+#endif
+
 static const struct i2c_device_id ms5611_id[] = {
 	{ "ms5611", MS5611 },
 	{ "ms5607", MS5607 },
@@ -123,6 +135,7 @@ MODULE_DEVICE_TABLE(i2c, ms5611_id);
 static struct i2c_driver ms5611_driver = {
 	.driver = {
 		.name = "ms5611",
+		.of_match_table = of_match_ptr(ms5611_i2c_matches)
 	},
 	.id_table = ms5611_id,
 	.probe = ms5611_i2c_probe,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/pressure/ms5611_spi.c linux-libre-4.7-gnu/drivers/iio/pressure/ms5611_spi.c
--- linux-libre-4.6-gnu/drivers/iio/pressure/ms5611_spi.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/pressure/ms5611_spi.c	2016-07-24 15:23:50.000000000 -0400
@@ -12,6 +12,7 @@
 #include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/spi/spi.h>
+#include <linux/of_device.h>
 
 #include "ms5611.h"
 
@@ -55,28 +56,29 @@ static int ms5611_spi_read_adc(struct de
 static int ms5611_spi_read_adc_temp_and_pressure(struct device *dev,
 						 s32 *temp, s32 *pressure)
 {
-	u8 cmd;
 	int ret;
 	struct ms5611_state *st = iio_priv(dev_to_iio_dev(dev));
+	const struct ms5611_osr *osr = st->temp_osr;
 
-	cmd = MS5611_START_TEMP_CONV;
-	ret = spi_write_then_read(st->client, &cmd, 1, NULL, 0);
+	/*
+	 * Warning: &osr->cmd MUST be aligned on a word boundary since used as
+	 * 2nd argument (void*) of spi_write_then_read.
+	 */
+	ret = spi_write_then_read(st->client, &osr->cmd, 1, NULL, 0);
 	if (ret < 0)
 		return ret;
 
-	usleep_range(MS5611_CONV_TIME_MIN, MS5611_CONV_TIME_MAX);
-
+	usleep_range(osr->conv_usec, osr->conv_usec + (osr->conv_usec / 10UL));
 	ret = ms5611_spi_read_adc(dev, temp);
 	if (ret < 0)
 		return ret;
 
-	cmd = MS5611_START_PRESSURE_CONV;
-	ret = spi_write_then_read(st->client, &cmd, 1, NULL, 0);
+	osr = st->pressure_osr;
+	ret = spi_write_then_read(st->client, &osr->cmd, 1, NULL, 0);
 	if (ret < 0)
 		return ret;
 
-	usleep_range(MS5611_CONV_TIME_MIN, MS5611_CONV_TIME_MAX);
-
+	usleep_range(osr->conv_usec, osr->conv_usec + (osr->conv_usec / 10UL));
 	return ms5611_spi_read_adc(dev, pressure);
 }
 
@@ -106,7 +108,7 @@ static int ms5611_spi_probe(struct spi_d
 	st->client = spi;
 
 	return ms5611_probe(indio_dev, &spi->dev, spi_get_device_id(spi)->name,
-	                    spi_get_device_id(spi)->driver_data);
+			    spi_get_device_id(spi)->driver_data);
 }
 
 static int ms5611_spi_remove(struct spi_device *spi)
@@ -114,6 +116,17 @@ static int ms5611_spi_remove(struct spi_
 	return ms5611_remove(spi_get_drvdata(spi));
 }
 
+#if defined(CONFIG_OF)
+static const struct of_device_id ms5611_spi_matches[] = {
+	{ .compatible = "meas,ms5611" },
+	{ .compatible = "ms5611" },
+	{ .compatible = "meas,ms5607" },
+	{ .compatible = "ms5607" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, ms5611_spi_matches);
+#endif
+
 static const struct spi_device_id ms5611_id[] = {
 	{ "ms5611", MS5611 },
 	{ "ms5607", MS5607 },
@@ -124,6 +137,7 @@ MODULE_DEVICE_TABLE(spi, ms5611_id);
 static struct spi_driver ms5611_driver = {
 	.driver = {
 		.name = "ms5611",
+		.of_match_table = of_match_ptr(ms5611_spi_matches)
 	},
 	.id_table = ms5611_id,
 	.probe = ms5611_spi_probe,
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/pressure/st_pressure_buffer.c linux-libre-4.7-gnu/drivers/iio/pressure/st_pressure_buffer.c
--- linux-libre-4.6-gnu/drivers/iio/pressure/st_pressure_buffer.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/pressure/st_pressure_buffer.c	2016-07-24 15:23:50.000000000 -0400
@@ -82,7 +82,7 @@ static const struct iio_buffer_setup_ops
 
 int st_press_allocate_ring(struct iio_dev *indio_dev)
 {
-	return iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
+	return iio_triggered_buffer_setup(indio_dev, NULL,
 		&st_sensors_trigger_handler, &st_press_buffer_setup_ops);
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/pressure/st_pressure_core.c linux-libre-4.7-gnu/drivers/iio/pressure/st_pressure_core.c
--- linux-libre-4.6-gnu/drivers/iio/pressure/st_pressure_core.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/pressure/st_pressure_core.c	2016-07-24 15:23:50.000000000 -0400
@@ -28,15 +28,21 @@
 #include <linux/iio/common/st_sensors.h>
 #include "st_pressure.h"
 
+#define MCELSIUS_PER_CELSIUS			1000
+
+/* Default pressure sensitivity */
 #define ST_PRESS_LSB_PER_MBAR			4096UL
 #define ST_PRESS_KPASCAL_NANO_SCALE		(100000000UL / \
 						 ST_PRESS_LSB_PER_MBAR)
+
+/* Default temperature sensitivity */
 #define ST_PRESS_LSB_PER_CELSIUS		480UL
-#define ST_PRESS_CELSIUS_NANO_SCALE		(1000000000UL / \
-						 ST_PRESS_LSB_PER_CELSIUS)
+#define ST_PRESS_MILLI_CELSIUS_OFFSET		42500UL
+
 #define ST_PRESS_NUMBER_DATA_CHANNELS		1
 
 /* FULLSCALE */
+#define ST_PRESS_FS_AVL_1100MB			1100
 #define ST_PRESS_FS_AVL_1260MB			1260
 
 #define ST_PRESS_1_OUT_XL_ADDR			0x28
@@ -54,9 +60,6 @@
 #define ST_PRESS_LPS331AP_PW_MASK		0x80
 #define ST_PRESS_LPS331AP_FS_ADDR		0x23
 #define ST_PRESS_LPS331AP_FS_MASK		0x30
-#define ST_PRESS_LPS331AP_FS_AVL_1260_VAL	0x00
-#define ST_PRESS_LPS331AP_FS_AVL_1260_GAIN	ST_PRESS_KPASCAL_NANO_SCALE
-#define ST_PRESS_LPS331AP_FS_AVL_TEMP_GAIN	ST_PRESS_CELSIUS_NANO_SCALE
 #define ST_PRESS_LPS331AP_BDU_ADDR		0x20
 #define ST_PRESS_LPS331AP_BDU_MASK		0x04
 #define ST_PRESS_LPS331AP_DRDY_IRQ_ADDR		0x22
@@ -64,10 +67,17 @@
 #define ST_PRESS_LPS331AP_DRDY_IRQ_INT2_MASK	0x20
 #define ST_PRESS_LPS331AP_IHL_IRQ_ADDR		0x22
 #define ST_PRESS_LPS331AP_IHL_IRQ_MASK		0x80
+#define ST_PRESS_LPS331AP_OD_IRQ_ADDR		0x22
+#define ST_PRESS_LPS331AP_OD_IRQ_MASK		0x40
 #define ST_PRESS_LPS331AP_MULTIREAD_BIT		true
-#define ST_PRESS_LPS331AP_TEMP_OFFSET		42500
 
 /* CUSTOM VALUES FOR LPS001WP SENSOR */
+
+/* LPS001WP pressure resolution */
+#define ST_PRESS_LPS001WP_LSB_PER_MBAR		16UL
+/* LPS001WP temperature resolution */
+#define ST_PRESS_LPS001WP_LSB_PER_CELSIUS	64UL
+
 #define ST_PRESS_LPS001WP_WAI_EXP		0xba
 #define ST_PRESS_LPS001WP_ODR_ADDR		0x20
 #define ST_PRESS_LPS001WP_ODR_MASK		0x30
@@ -76,6 +86,8 @@
 #define ST_PRESS_LPS001WP_ODR_AVL_13HZ_VAL	0x03
 #define ST_PRESS_LPS001WP_PW_ADDR		0x20
 #define ST_PRESS_LPS001WP_PW_MASK		0x40
+#define ST_PRESS_LPS001WP_FS_AVL_PRESS_GAIN \
+	(100000000UL / ST_PRESS_LPS001WP_LSB_PER_MBAR)
 #define ST_PRESS_LPS001WP_BDU_ADDR		0x20
 #define ST_PRESS_LPS001WP_BDU_MASK		0x04
 #define ST_PRESS_LPS001WP_MULTIREAD_BIT		true
@@ -92,11 +104,6 @@
 #define ST_PRESS_LPS25H_ODR_AVL_25HZ_VAL	0x04
 #define ST_PRESS_LPS25H_PW_ADDR			0x20
 #define ST_PRESS_LPS25H_PW_MASK			0x80
-#define ST_PRESS_LPS25H_FS_ADDR			0x00
-#define ST_PRESS_LPS25H_FS_MASK			0x00
-#define ST_PRESS_LPS25H_FS_AVL_1260_VAL		0x00
-#define ST_PRESS_LPS25H_FS_AVL_1260_GAIN	ST_PRESS_KPASCAL_NANO_SCALE
-#define ST_PRESS_LPS25H_FS_AVL_TEMP_GAIN	ST_PRESS_CELSIUS_NANO_SCALE
 #define ST_PRESS_LPS25H_BDU_ADDR		0x20
 #define ST_PRESS_LPS25H_BDU_MASK		0x04
 #define ST_PRESS_LPS25H_DRDY_IRQ_ADDR		0x23
@@ -104,8 +111,9 @@
 #define ST_PRESS_LPS25H_DRDY_IRQ_INT2_MASK	0x10
 #define ST_PRESS_LPS25H_IHL_IRQ_ADDR		0x22
 #define ST_PRESS_LPS25H_IHL_IRQ_MASK		0x80
+#define ST_PRESS_LPS25H_OD_IRQ_ADDR		0x22
+#define ST_PRESS_LPS25H_OD_IRQ_MASK		0x40
 #define ST_PRESS_LPS25H_MULTIREAD_BIT		true
-#define ST_PRESS_LPS25H_TEMP_OFFSET		42500
 #define ST_PRESS_LPS25H_OUT_XL_ADDR		0x28
 #define ST_TEMP_LPS25H_OUT_L_ADDR		0x2b
 
@@ -157,7 +165,9 @@ static const struct iio_chan_spec st_pre
 			.storagebits = 16,
 			.endianness = IIO_LE,
 		},
-		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_separate =
+			BIT(IIO_CHAN_INFO_RAW) |
+			BIT(IIO_CHAN_INFO_SCALE),
 		.modified = 0,
 	},
 	{
@@ -173,7 +183,7 @@ static const struct iio_chan_spec st_pre
 		},
 		.info_mask_separate =
 			BIT(IIO_CHAN_INFO_RAW) |
-			BIT(IIO_CHAN_INFO_OFFSET),
+			BIT(IIO_CHAN_INFO_SCALE),
 		.modified = 0,
 	},
 	IIO_CHAN_SOFT_TIMESTAMP(1)
@@ -208,11 +218,14 @@ static const struct st_sensor_settings s
 			.addr = ST_PRESS_LPS331AP_FS_ADDR,
 			.mask = ST_PRESS_LPS331AP_FS_MASK,
 			.fs_avl = {
+				/*
+				 * Pressure and temperature sensitivity values
+				 * as defined in table 3 of LPS331AP datasheet.
+				 */
 				[0] = {
 					.num = ST_PRESS_FS_AVL_1260MB,
-					.value = ST_PRESS_LPS331AP_FS_AVL_1260_VAL,
-					.gain = ST_PRESS_LPS331AP_FS_AVL_1260_GAIN,
-					.gain2 = ST_PRESS_LPS331AP_FS_AVL_TEMP_GAIN,
+					.gain = ST_PRESS_KPASCAL_NANO_SCALE,
+					.gain2 = ST_PRESS_LSB_PER_CELSIUS,
 				},
 			},
 		},
@@ -226,6 +239,9 @@ static const struct st_sensor_settings s
 			.mask_int2 = ST_PRESS_LPS331AP_DRDY_IRQ_INT2_MASK,
 			.addr_ihl = ST_PRESS_LPS331AP_IHL_IRQ_ADDR,
 			.mask_ihl = ST_PRESS_LPS331AP_IHL_IRQ_MASK,
+			.addr_od = ST_PRESS_LPS331AP_OD_IRQ_ADDR,
+			.mask_od = ST_PRESS_LPS331AP_OD_IRQ_MASK,
+			.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
 		},
 		.multi_read_bit = ST_PRESS_LPS331AP_MULTIREAD_BIT,
 		.bootime = 2,
@@ -254,7 +270,17 @@ static const struct st_sensor_settings s
 			.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
 		},
 		.fs = {
-			.addr = 0,
+			.fs_avl = {
+				/*
+				 * Pressure and temperature resolution values
+				 * as defined in table 3 of LPS001WP datasheet.
+				 */
+				[0] = {
+					.num = ST_PRESS_FS_AVL_1100MB,
+					.gain = ST_PRESS_LPS001WP_FS_AVL_PRESS_GAIN,
+					.gain2 = ST_PRESS_LPS001WP_LSB_PER_CELSIUS,
+				},
+			},
 		},
 		.bdu = {
 			.addr = ST_PRESS_LPS001WP_BDU_ADDR,
@@ -291,14 +317,15 @@ static const struct st_sensor_settings s
 			.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
 		},
 		.fs = {
-			.addr = ST_PRESS_LPS25H_FS_ADDR,
-			.mask = ST_PRESS_LPS25H_FS_MASK,
 			.fs_avl = {
+				/*
+				 * Pressure and temperature sensitivity values
+				 * as defined in table 3 of LPS25H datasheet.
+				 */
 				[0] = {
 					.num = ST_PRESS_FS_AVL_1260MB,
-					.value = ST_PRESS_LPS25H_FS_AVL_1260_VAL,
-					.gain = ST_PRESS_LPS25H_FS_AVL_1260_GAIN,
-					.gain2 = ST_PRESS_LPS25H_FS_AVL_TEMP_GAIN,
+					.gain = ST_PRESS_KPASCAL_NANO_SCALE,
+					.gain2 = ST_PRESS_LSB_PER_CELSIUS,
 				},
 			},
 		},
@@ -312,6 +339,9 @@ static const struct st_sensor_settings s
 			.mask_int2 = ST_PRESS_LPS25H_DRDY_IRQ_INT2_MASK,
 			.addr_ihl = ST_PRESS_LPS25H_IHL_IRQ_ADDR,
 			.mask_ihl = ST_PRESS_LPS25H_IHL_IRQ_MASK,
+			.addr_od = ST_PRESS_LPS25H_OD_IRQ_ADDR,
+			.mask_od = ST_PRESS_LPS25H_OD_IRQ_MASK,
+			.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
 		},
 		.multi_read_bit = ST_PRESS_LPS25H_MULTIREAD_BIT,
 		.bootime = 2,
@@ -354,26 +384,26 @@ static int st_press_read_raw(struct iio_
 
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_SCALE:
-		*val = 0;
-
 		switch (ch->type) {
 		case IIO_PRESSURE:
+			*val = 0;
 			*val2 = press_data->current_fullscale->gain;
-			break;
+			return IIO_VAL_INT_PLUS_NANO;
 		case IIO_TEMP:
+			*val = MCELSIUS_PER_CELSIUS;
 			*val2 = press_data->current_fullscale->gain2;
-			break;
+			return IIO_VAL_FRACTIONAL;
 		default:
 			err = -EINVAL;
 			goto read_error;
 		}
 
-		return IIO_VAL_INT_PLUS_NANO;
 	case IIO_CHAN_INFO_OFFSET:
 		switch (ch->type) {
 		case IIO_TEMP:
-			*val = 425;
-			*val2 = 10;
+			*val = ST_PRESS_MILLI_CELSIUS_OFFSET *
+			       press_data->current_fullscale->gain2;
+			*val2 = MCELSIUS_PER_CELSIUS;
 			break;
 		default:
 			err = -EINVAL;
@@ -415,6 +445,7 @@ static const struct iio_info press_info
 static const struct iio_trigger_ops st_press_trigger_ops = {
 	.owner = THIS_MODULE,
 	.set_trigger_state = ST_PRESS_TRIGGER_SET_STATE,
+	.validate_device = st_sensors_validate_device,
 };
 #define ST_PRESS_TRIGGER_OPS (&st_press_trigger_ops)
 #else
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/iio/proximity/as3935.c linux-libre-4.7-gnu/drivers/iio/proximity/as3935.c
--- linux-libre-4.6-gnu/drivers/iio/proximity/as3935.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/iio/proximity/as3935.c	2016-07-24 15:23:50.000000000 -0400
@@ -64,6 +64,7 @@ struct as3935_state {
 	struct delayed_work work;
 
 	u32 tune_cap;
+	u8 buffer[16]; /* 8-bit data + 56-bit padding + 64-bit timestamp */
 	u8 buf[2] ____cacheline_aligned;
 };
 
@@ -72,7 +73,8 @@ static const struct iio_chan_spec as3935
 		.type           = IIO_PROXIMITY,
 		.info_mask_separate =
 			BIT(IIO_CHAN_INFO_RAW) |
-			BIT(IIO_CHAN_INFO_PROCESSED),
+			BIT(IIO_CHAN_INFO_PROCESSED) |
+			BIT(IIO_CHAN_INFO_SCALE),
 		.scan_index     = 0,
 		.scan_type = {
 			.sign           = 'u',
@@ -181,7 +183,12 @@ static int as3935_read_raw(struct iio_de
 		/* storm out of range */
 		if (*val == AS3935_DATA_MASK)
 			return -EINVAL;
-		*val *= 1000;
+
+		if (m == IIO_CHAN_INFO_PROCESSED)
+			*val *= 1000;
+		break;
+	case IIO_CHAN_INFO_SCALE:
+		*val = 1000;
 		break;
 	default:
 		return -EINVAL;
@@ -206,10 +213,10 @@ static irqreturn_t as3935_trigger_handle
 	ret = as3935_read(st, AS3935_DATA, &val);
 	if (ret)
 		goto err_read;
-	val &= AS3935_DATA_MASK;
-	val *= 1000;
 
-	iio_push_to_buffers_with_timestamp(indio_dev, &val, pf->timestamp);
+	st->buffer[0] = val & AS3935_DATA_MASK;
+	iio_push_to_buffers_with_timestamp(indio_dev, &st->buffer,
+					   pf->timestamp);
 err_read:
 	iio_trigger_notify_done(indio_dev->trig);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/infiniband/core/addr.c linux-libre-4.7-gnu/drivers/infiniband/core/addr.c
--- linux-libre-4.6-gnu/drivers/infiniband/core/addr.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/infiniband/core/addr.c	2016-07-24 15:23:50.000000000 -0400
@@ -46,10 +46,10 @@
 #include <net/ip6_route.h>
 #include <rdma/ib_addr.h>
 #include <rdma/ib.h>
+#include <rdma/rdma_netlink.h>
+#include <net/netlink.h>
 
-MODULE_AUTHOR("Sean Hefty");
-MODULE_DESCRIPTION("IB Address Translation");
-MODULE_LICENSE("Dual BSD/GPL");
+#include "core_priv.h"
 
 struct addr_req {
 	struct list_head list;
@@ -62,8 +62,11 @@ struct addr_req {
 			 struct rdma_dev_addr *addr, void *context);
 	unsigned long timeout;
 	int status;
+	u32 seq;
 };
 
+static atomic_t ib_nl_addr_request_seq = ATOMIC_INIT(0);
+
 static void process_req(struct work_struct *work);
 
 static DEFINE_MUTEX(lock);
@@ -71,6 +74,126 @@ static LIST_HEAD(req_list);
 static DECLARE_DELAYED_WORK(work, process_req);
 static struct workqueue_struct *addr_wq;
 
+static const struct nla_policy ib_nl_addr_policy[LS_NLA_TYPE_MAX] = {
+	[LS_NLA_TYPE_DGID] = {.type = NLA_BINARY,
+		.len = sizeof(struct rdma_nla_ls_gid)},
+};
+
+static inline bool ib_nl_is_good_ip_resp(const struct nlmsghdr *nlh)
+{
+	struct nlattr *tb[LS_NLA_TYPE_MAX] = {};
+	int ret;
+
+	if (nlh->nlmsg_flags & RDMA_NL_LS_F_ERR)
+		return false;
+
+	ret = nla_parse(tb, LS_NLA_TYPE_MAX - 1, nlmsg_data(nlh),
+			nlmsg_len(nlh), ib_nl_addr_policy);
+	if (ret)
+		return false;
+
+	return true;
+}
+
+static void ib_nl_process_good_ip_rsep(const struct nlmsghdr *nlh)
+{
+	const struct nlattr *head, *curr;
+	union ib_gid gid;
+	struct addr_req *req;
+	int len, rem;
+	int found = 0;
+
+	head = (const struct nlattr *)nlmsg_data(nlh);
+	len = nlmsg_len(nlh);
+
+	nla_for_each_attr(curr, head, len, rem) {
+		if (curr->nla_type == LS_NLA_TYPE_DGID)
+			memcpy(&gid, nla_data(curr), nla_len(curr));
+	}
+
+	mutex_lock(&lock);
+	list_for_each_entry(req, &req_list, list) {
+		if (nlh->nlmsg_seq != req->seq)
+			continue;
+		/* We set the DGID part, the rest was set earlier */
+		rdma_addr_set_dgid(req->addr, &gid);
+		req->status = 0;
+		found = 1;
+		break;
+	}
+	mutex_unlock(&lock);
+
+	if (!found)
+		pr_info("Couldn't find request waiting for DGID: %pI6\n",
+			&gid);
+}
+
+int ib_nl_handle_ip_res_resp(struct sk_buff *skb,
+			     struct netlink_callback *cb)
+{
+	const struct nlmsghdr *nlh = (struct nlmsghdr *)cb->nlh;
+
+	if ((nlh->nlmsg_flags & NLM_F_REQUEST) ||
+	    !(NETLINK_CB(skb).sk) ||
+	    !netlink_capable(skb, CAP_NET_ADMIN))
+		return -EPERM;
+
+	if (ib_nl_is_good_ip_resp(nlh))
+		ib_nl_process_good_ip_rsep(nlh);
+
+	return skb->len;
+}
+
+static int ib_nl_ip_send_msg(struct rdma_dev_addr *dev_addr,
+			     const void *daddr,
+			     u32 seq, u16 family)
+{
+	struct sk_buff *skb = NULL;
+	struct nlmsghdr *nlh;
+	struct rdma_ls_ip_resolve_header *header;
+	void *data;
+	size_t size;
+	int attrtype;
+	int len;
+
+	if (family == AF_INET) {
+		size = sizeof(struct in_addr);
+		attrtype = RDMA_NLA_F_MANDATORY | LS_NLA_TYPE_IPV4;
+	} else {
+		size = sizeof(struct in6_addr);
+		attrtype = RDMA_NLA_F_MANDATORY | LS_NLA_TYPE_IPV6;
+	}
+
+	len = nla_total_size(sizeof(size));
+	len += NLMSG_ALIGN(sizeof(*header));
+
+	skb = nlmsg_new(len, GFP_KERNEL);
+	if (!skb)
+		return -ENOMEM;
+
+	data = ibnl_put_msg(skb, &nlh, seq, 0, RDMA_NL_LS,
+			    RDMA_NL_LS_OP_IP_RESOLVE, NLM_F_REQUEST);
+	if (!data) {
+		nlmsg_free(skb);
+		return -ENODATA;
+	}
+
+	/* Construct the family header first */
+	header = (struct rdma_ls_ip_resolve_header *)
+		skb_put(skb, NLMSG_ALIGN(sizeof(*header)));
+	header->ifindex = dev_addr->bound_dev_if;
+	nla_put(skb, attrtype, size, daddr);
+
+	/* Repair the nlmsg header length */
+	nlmsg_end(skb, nlh);
+	ibnl_multicast(skb, nlh, RDMA_NL_GROUP_LS, GFP_KERNEL);
+
+	/* Make the request retry, so when we get the response from userspace
+	 * we will have something.
+	 */
+	return -ENODATA;
+}
+
 int rdma_addr_size(struct sockaddr *addr)
 {
 	switch (addr->sa_family) {
@@ -199,6 +322,17 @@ static void queue_req(struct addr_req *r
 	mutex_unlock(&lock);
 }
 
+static int ib_nl_fetch_ha(struct dst_entry *dst, struct rdma_dev_addr *dev_addr,
+			  const void *daddr, u32 seq, u16 family)
+{
+	if (ibnl_chk_listeners(RDMA_NL_GROUP_LS))
+		return -EADDRNOTAVAIL;
+
+	/* We fill in what we can, the response will fill the rest */
+	rdma_copy_addr(dev_addr, dst->dev, NULL);
+	return ib_nl_ip_send_msg(dev_addr, daddr, seq, family);
+}
+
 static int dst_fetch_ha(struct dst_entry *dst, struct rdma_dev_addr *dev_addr,
 			const void *daddr)
 {
@@ -223,6 +357,39 @@ static int dst_fetch_ha(struct dst_entry
 	return ret;
 }
 
+static bool has_gateway(struct dst_entry *dst, sa_family_t family)
+{
+	struct rtable *rt;
+	struct rt6_info *rt6;
+
+	if (family == AF_INET) {
+		rt = container_of(dst, struct rtable, dst);
+		return rt->rt_uses_gateway;
+	}
+
+	rt6 = container_of(dst, struct rt6_info, dst);
+	return rt6->rt6i_flags & RTF_GATEWAY;
+}
+
+static int fetch_ha(struct dst_entry *dst, struct rdma_dev_addr *dev_addr,
+		    const struct sockaddr *dst_in, u32 seq)
+{
+	const struct sockaddr_in *dst_in4 =
+		(const struct sockaddr_in *)dst_in;
+	const struct sockaddr_in6 *dst_in6 =
+		(const struct sockaddr_in6 *)dst_in;
+	const void *daddr = (dst_in->sa_family == AF_INET) ?
+		(const void *)&dst_in4->sin_addr.s_addr :
+		(const void *)&dst_in6->sin6_addr;
+	sa_family_t family = dst_in->sa_family;
+
+	/* Gateway + ARPHRD_INFINIBAND -> IB router */
+	if (has_gateway(dst, family) && dst->dev->type == ARPHRD_INFINIBAND)
+		return ib_nl_fetch_ha(dst, dev_addr, daddr, seq, family);
+	else
+		return dst_fetch_ha(dst, dev_addr, daddr);
+}
+
 static int addr4_resolve(struct sockaddr_in *src_in,
 			 const struct sockaddr_in *dst_in,
 			 struct rdma_dev_addr *addr,
@@ -246,10 +413,11 @@ static int addr4_resolve(struct sockaddr
 	src_in->sin_family = AF_INET;
 	src_in->sin_addr.s_addr = fl4.saddr;
 
-	/* If there's a gateway, we're definitely in RoCE v2 (as RoCE v1 isn't
-	 * routable) and we could set the network type accordingly.
+	/* If there's a gateway and type of device not ARPHRD_INFINIBAND, we're
+	 * definitely in RoCE v2 (as RoCE v1 isn't routable) set the network
+	 * type accordingly.
 	 */
-	if (rt->rt_uses_gateway)
+	if (rt->rt_uses_gateway && rt->dst.dev->type != ARPHRD_INFINIBAND)
 		addr->network = RDMA_NETWORK_IPV4;
 
 	addr->hoplimit = ip4_dst_hoplimit(&rt->dst);
@@ -291,10 +459,12 @@ static int addr6_resolve(struct sockaddr
 		src_in->sin6_addr = fl6.saddr;
 	}
 
-	/* If there's a gateway, we're definitely in RoCE v2 (as RoCE v1 isn't
-	 * routable) and we could set the network type accordingly.
+	/* If there's a gateway and type of device not ARPHRD_INFINIBAND, we're
+	 * definitely in RoCE v2 (as RoCE v1 isn't routable) set the network
+	 * type accordingly.
 	 */
-	if (rt->rt6i_flags & RTF_GATEWAY)
+	if (rt->rt6i_flags & RTF_GATEWAY &&
+	    ip6_dst_idev(dst)->dev->type != ARPHRD_INFINIBAND)
 		addr->network = RDMA_NETWORK_IPV6;
 
 	addr->hoplimit = ip6_dst_hoplimit(dst);
@@ -317,7 +487,8 @@ static int addr6_resolve(struct sockaddr
 
 static int addr_resolve_neigh(struct dst_entry *dst,
 			      const struct sockaddr *dst_in,
-			      struct rdma_dev_addr *addr)
+			      struct rdma_dev_addr *addr,
+			      u32 seq)
 {
 	if (dst->dev->flags & IFF_LOOPBACK) {
 		int ret;
@@ -331,17 +502,8 @@ static int addr_resolve_neigh(struct dst
 	}
 
 	/* If the device doesn't do ARP internally */
-	if (!(dst->dev->flags & IFF_NOARP)) {
-		const struct sockaddr_in *dst_in4 =
-			(const struct sockaddr_in *)dst_in;
-		const struct sockaddr_in6 *dst_in6 =
-			(const struct sockaddr_in6 *)dst_in;
-
-		return dst_fetch_ha(dst, addr,
-				    dst_in->sa_family == AF_INET ?
-				    (const void *)&dst_in4->sin_addr.s_addr :
-				    (const void *)&dst_in6->sin6_addr);
-	}
+	if (!(dst->dev->flags & IFF_NOARP))
+		return fetch_ha(dst, addr, dst_in, seq);
 
 	return rdma_copy_addr(addr, dst->dev, NULL);
 }
@@ -349,7 +511,8 @@ static int addr_resolve_neigh(struct dst
 static int addr_resolve(struct sockaddr *src_in,
 			const struct sockaddr *dst_in,
 			struct rdma_dev_addr *addr,
-			bool resolve_neigh)
+			bool resolve_neigh,
+			u32 seq)
 {
 	struct net_device *ndev;
 	struct dst_entry *dst;
@@ -366,7 +529,7 @@ static int addr_resolve(struct sockaddr
 			return ret;
 
 		if (resolve_neigh)
-			ret = addr_resolve_neigh(&rt->dst, dst_in, addr);
+			ret = addr_resolve_neigh(&rt->dst, dst_in, addr, seq);
 
 		ndev = rt->dst.dev;
 		dev_hold(ndev);
@@ -383,7 +546,7 @@ static int addr_resolve(struct sockaddr
 			return ret;
 
 		if (resolve_neigh)
-			ret = addr_resolve_neigh(dst, dst_in, addr);
+			ret = addr_resolve_neigh(dst, dst_in, addr, seq);
 
 		ndev = dst->dev;
 		dev_hold(ndev);
@@ -412,7 +575,7 @@ static void process_req(struct work_stru
 			src_in = (struct sockaddr *) &req->src_addr;
 			dst_in = (struct sockaddr *) &req->dst_addr;
 			req->status = addr_resolve(src_in, dst_in, req->addr,
-						   true);
+						   true, req->seq);
 			if (req->status && time_after_eq(jiffies, req->timeout))
 				req->status = -ETIMEDOUT;
 			else if (req->status == -ENODATA)
@@ -471,8 +634,9 @@ int rdma_resolve_ip(struct rdma_addr_cli
 	req->context = context;
 	req->client = client;
 	atomic_inc(&client->refcount);
+	req->seq = (u32)atomic_inc_return(&ib_nl_addr_request_seq);
 
-	req->status = addr_resolve(src_in, dst_in, addr, true);
+	req->status = addr_resolve(src_in, dst_in, addr, true, req->seq);
 	switch (req->status) {
 	case 0:
 		req->timeout = jiffies;
@@ -510,7 +674,7 @@ int rdma_resolve_ip_route(struct sockadd
 		src_in->sa_family = dst_addr->sa_family;
 	}
 
-	return addr_resolve(src_in, dst_addr, addr, false);
+	return addr_resolve(src_in, dst_addr, addr, false, 0);
 }
 EXPORT_SYMBOL(rdma_resolve_ip_route);
 
@@ -634,7 +798,7 @@ static struct notifier_block nb = {
 	.notifier_call = netevent_callback
 };
 
-static int __init addr_init(void)
+int addr_init(void)
 {
 	addr_wq = create_singlethread_workqueue("ib_addr");
 	if (!addr_wq)
@@ -642,15 +806,13 @@ static int __init addr_init(void)
 
 	register_netevent_notifier(&nb);
 	rdma_addr_register_client(&self);
+
 	return 0;
 }
 
-static void __exit addr_cleanup(void)
+void addr_cleanup(void)
 {
 	rdma_addr_unregister_client(&self);
 	unregister_netevent_notifier(&nb);
 	destroy_workqueue(addr_wq);
 }
-
-module_init(addr_init);
-module_exit(addr_cleanup);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/infiniband/core/cache.c linux-libre-4.7-gnu/drivers/infiniband/core/cache.c
--- linux-libre-4.6-gnu/drivers/infiniband/core/cache.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/infiniband/core/cache.c	2016-07-24 15:23:50.000000000 -0400
@@ -178,6 +178,7 @@ static int write_gid(struct ib_device *i
 {
 	int ret = 0;
 	struct net_device *old_net_dev;
+	enum ib_gid_type old_gid_type;
 
 	/* in rdma_cap_roce_gid_table, this funciton should be protected by a
 	 * sleep-able lock.
@@ -199,6 +200,7 @@ static int write_gid(struct ib_device *i
 	}
 
 	old_net_dev = table->data_vec[ix].attr.ndev;
+	old_gid_type = table->data_vec[ix].attr.gid_type;
 	if (old_net_dev && old_net_dev != attr->ndev)
 		dev_put(old_net_dev);
 	/* if modify_gid failed, just delete the old gid */
@@ -207,10 +209,14 @@ static int write_gid(struct ib_device *i
 		attr = &zattr;
 		table->data_vec[ix].context = NULL;
 	}
-	if (default_gid)
-		table->data_vec[ix].props |= GID_TABLE_ENTRY_DEFAULT;
+
 	memcpy(&table->data_vec[ix].gid, gid, sizeof(*gid));
 	memcpy(&table->data_vec[ix].attr, attr, sizeof(*attr));
+	if (default_gid) {
+		table->data_vec[ix].props |= GID_TABLE_ENTRY_DEFAULT;
+		if (action == GID_TABLE_WRITE_ACTION_DEL)
+			table->data_vec[ix].attr.gid_type = old_gid_type;
+	}
 	if (table->data_vec[ix].attr.ndev &&
 	    table->data_vec[ix].attr.ndev != old_net_dev)
 		dev_hold(table->data_vec[ix].attr.ndev);
@@ -405,7 +411,9 @@ int ib_cache_gid_del_all_netdev_gids(str
 
 	for (ix = 0; ix < table->sz; ix++)
 		if (table->data_vec[ix].attr.ndev == ndev)
-			if (!del_gid(ib_dev, port, table, ix, false))
+			if (!del_gid(ib_dev, port, table, ix,
+				     !!(table->data_vec[ix].props &
+					GID_TABLE_ENTRY_DEFAULT)))
 				deleted = true;
 
 	write_unlock_irq(&table->rwlock);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/infiniband/core/cma.c linux-libre-4.7-gnu/drivers/infiniband/core/cma.c
--- linux-libre-4.6-gnu/drivers/infiniband/core/cma.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/infiniband/core/cma.c	2016-07-24 15:23:50.000000000 -0400
@@ -708,17 +708,6 @@ static void cma_deref_id(struct rdma_id_
 		complete(&id_priv->comp);
 }
 
-static int cma_disable_callback(struct rdma_id_private *id_priv,
-				enum rdma_cm_state state)
-{
-	mutex_lock(&id_priv->handler_mutex);
-	if (id_priv->state != state) {
-		mutex_unlock(&id_priv->handler_mutex);
-		return -EINVAL;
-	}
-	return 0;
-}
-
 struct rdma_cm_id *rdma_create_id(struct net *net,
 				  rdma_cm_event_handler event_handler,
 				  void *context, enum rdma_port_space ps,
@@ -800,6 +789,7 @@ int rdma_create_qp(struct rdma_cm_id *id
 	if (id->device != pd->device)
 		return -EINVAL;
 
+	qp_init_attr->port_num = id->port_num;
 	qp = ib_create_qp(pd, qp_init_attr);
 	if (IS_ERR(qp))
 		return PTR_ERR(qp);
@@ -1670,11 +1660,12 @@ static int cma_ib_handler(struct ib_cm_i
 	struct rdma_cm_event event;
 	int ret = 0;
 
+	mutex_lock(&id_priv->handler_mutex);
 	if ((ib_event->event != IB_CM_TIMEWAIT_EXIT &&
-		cma_disable_callback(id_priv, RDMA_CM_CONNECT)) ||
+	     id_priv->state != RDMA_CM_CONNECT) ||
 	    (ib_event->event == IB_CM_TIMEWAIT_EXIT &&
-		cma_disable_callback(id_priv, RDMA_CM_DISCONNECT)))
-		return 0;
+	     id_priv->state != RDMA_CM_DISCONNECT))
+		goto out;
 
 	memset(&event, 0, sizeof event);
 	switch (ib_event->event) {
@@ -1869,7 +1860,7 @@ static int cma_check_req_qp_type(struct
 
 static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
 {
-	struct rdma_id_private *listen_id, *conn_id;
+	struct rdma_id_private *listen_id, *conn_id = NULL;
 	struct rdma_cm_event event;
 	struct net_device *net_dev;
 	int offset, ret;
@@ -1883,9 +1874,10 @@ static int cma_req_handler(struct ib_cm_
 		goto net_dev_put;
 	}
 
-	if (cma_disable_callback(listen_id, RDMA_CM_LISTEN)) {
+	mutex_lock(&listen_id->handler_mutex);
+	if (listen_id->state != RDMA_CM_LISTEN) {
 		ret = -ECONNABORTED;
-		goto net_dev_put;
+		goto err1;
 	}
 
 	memset(&event, 0, sizeof event);
@@ -1975,8 +1967,9 @@ static int cma_iw_handler(struct iw_cm_i
 	struct sockaddr *laddr = (struct sockaddr *)&iw_event->local_addr;
 	struct sockaddr *raddr = (struct sockaddr *)&iw_event->remote_addr;
 
-	if (cma_disable_callback(id_priv, RDMA_CM_CONNECT))
-		return 0;
+	mutex_lock(&id_priv->handler_mutex);
+	if (id_priv->state != RDMA_CM_CONNECT)
+		goto out;
 
 	memset(&event, 0, sizeof event);
 	switch (iw_event->event) {
@@ -2028,6 +2021,7 @@ static int cma_iw_handler(struct iw_cm_i
 		return ret;
 	}
 
+out:
 	mutex_unlock(&id_priv->handler_mutex);
 	return ret;
 }
@@ -2038,13 +2032,15 @@ static int iw_conn_req_handler(struct iw
 	struct rdma_cm_id *new_cm_id;
 	struct rdma_id_private *listen_id, *conn_id;
 	struct rdma_cm_event event;
-	int ret;
+	int ret = -ECONNABORTED;
 	struct sockaddr *laddr = (struct sockaddr *)&iw_event->local_addr;
 	struct sockaddr *raddr = (struct sockaddr *)&iw_event->remote_addr;
 
 	listen_id = cm_id->context;
-	if (cma_disable_callback(listen_id, RDMA_CM_LISTEN))
-		return -ECONNABORTED;
+
+	mutex_lock(&listen_id->handler_mutex);
+	if (listen_id->state != RDMA_CM_LISTEN)
+		goto out;
 
 	/* Create a new RDMA id for the new IW CM ID */
 	new_cm_id = rdma_create_id(listen_id->id.route.addr.dev_addr.net,
@@ -3215,8 +3211,9 @@ static int cma_sidr_rep_handler(struct i
 	struct ib_cm_sidr_rep_event_param *rep = &ib_event->param.sidr_rep_rcvd;
 	int ret = 0;
 
-	if (cma_disable_callback(id_priv, RDMA_CM_CONNECT))
-		return 0;
+	mutex_lock(&id_priv->handler_mutex);
+	if (id_priv->state != RDMA_CM_CONNECT)
+		goto out;
 
 	memset(&event, 0, sizeof event);
 	switch (ib_event->event) {
@@ -3672,12 +3669,13 @@ static int cma_ib_mc_handler(int status,
 	struct rdma_id_private *id_priv;
 	struct cma_multicast *mc = multicast->context;
 	struct rdma_cm_event event;
-	int ret;
+	int ret = 0;
 
 	id_priv = mc->id_priv;
-	if (cma_disable_callback(id_priv, RDMA_CM_ADDR_BOUND) &&
-	    cma_disable_callback(id_priv, RDMA_CM_ADDR_RESOLVED))
-		return 0;
+	mutex_lock(&id_priv->handler_mutex);
+	if (id_priv->state != RDMA_CM_ADDR_BOUND &&
+	    id_priv->state != RDMA_CM_ADDR_RESOLVED)
+		goto out;
 
 	if (!status)
 		status = cma_set_qkey(id_priv, be32_to_cpu(multicast->rec.qkey));
@@ -3719,6 +3717,7 @@ static int cma_ib_mc_handler(int status,
 		return 0;
 	}
 
+out:
 	mutex_unlock(&id_priv->handler_mutex);
 	return 0;
 }
@@ -3877,12 +3876,12 @@ static int cma_iboe_join_multicast(struc
 	gid_type = id_priv->cma_dev->default_gid_type[id_priv->id.port_num -
 		   rdma_start_port(id_priv->cma_dev->device)];
 	if (addr->sa_family == AF_INET) {
-		if (gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP)
+		if (gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP) {
+			mc->multicast.ib->rec.hop_limit = IPV6_DEFAULT_HOPLIMIT;
 			err = cma_igmp_send(ndev, &mc->multicast.ib->rec.mgid,
 					    true);
-		if (!err) {
-			mc->igmp_joined = true;
-			mc->multicast.ib->rec.hop_limit = IPV6_DEFAULT_HOPLIMIT;
+			if (!err)
+				mc->igmp_joined = true;
 		}
 	} else {
 		if (gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP)
@@ -4294,7 +4293,8 @@ static int __init cma_init(void)
 	if (ret)
 		goto err;
 
-	if (ibnl_add_client(RDMA_NL_RDMA_CM, RDMA_NL_RDMA_CM_NUM_OPS, cma_cb_table))
+	if (ibnl_add_client(RDMA_NL_RDMA_CM, ARRAY_SIZE(cma_cb_table),
+			    cma_cb_table))
 		pr_warn("RDMA CMA: failed to add netlink callback\n");
 	cma_configfs_init();
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/infiniband/core/cm.c linux-libre-4.7-gnu/drivers/infiniband/core/cm.c
--- linux-libre-4.6-gnu/drivers/infiniband/core/cm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/infiniband/core/cm.c	2016-07-24 15:23:50.000000000 -0400
@@ -3452,14 +3452,14 @@ static int cm_establish(struct ib_cm_id
 	work->cm_event.event = IB_CM_USER_ESTABLISHED;
 
 	/* Check if the device started its remove_one */
-	spin_lock_irq(&cm.lock);
+	spin_lock_irqsave(&cm.lock, flags);
 	if (!cm_dev->going_down) {
 		queue_delayed_work(cm.wq, &work->work, 0);
 	} else {
 		kfree(work);
 		ret = -ENODEV;
 	}
-	spin_unlock_irq(&cm.lock);
+	spin_unlock_irqrestore(&cm.lock, flags);
 
 out:
 	return ret;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/infiniband/core/core_priv.h linux-libre-4.7-gnu/drivers/infiniband/core/core_priv.h
--- linux-libre-4.6-gnu/drivers/infiniband/core/core_priv.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/infiniband/core/core_priv.h	2016-07-24 15:23:50.000000000 -0400
@@ -137,4 +137,20 @@ static inline bool rdma_is_upper_dev_rcu
 	return _upper == upper;
 }
 
+int addr_init(void);
+void addr_cleanup(void);
+
+int ib_mad_init(void);
+void ib_mad_cleanup(void);
+
+int ib_sa_init(void);
+void ib_sa_cleanup(void);
+
+int ib_nl_handle_resolve_resp(struct sk_buff *skb,
+			      struct netlink_callback *cb);
+int ib_nl_handle_set_timeout(struct sk_buff *skb,
+			     struct netlink_callback *cb);
+int ib_nl_handle_ip_res_resp(struct sk_buff *skb,
+			     struct netlink_callback *cb);
+
 #endif /* _CORE_PRIV_H */
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/infiniband/core/device.c linux-libre-4.7-gnu/drivers/infiniband/core/device.c
--- linux-libre-4.6-gnu/drivers/infiniband/core/device.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/infiniband/core/device.c	2016-07-24 15:23:50.000000000 -0400
@@ -661,6 +661,9 @@ int ib_query_port(struct ib_device *devi
 	if (err || port_attr->subnet_prefix)
 		return err;
 
+	if (rdma_port_get_link_layer(device, port_num) != IB_LINK_LAYER_INFINIBAND)
+		return 0;
+
 	err = ib_query_gid(device, port_num, 0, &gid, NULL);
 	if (err)
 		return err;
@@ -955,6 +958,29 @@ struct net_device *ib_get_net_dev_by_par
 }
 EXPORT_SYMBOL(ib_get_net_dev_by_params);
 
+static struct ibnl_client_cbs ibnl_ls_cb_table[] = {
+	[RDMA_NL_LS_OP_RESOLVE] = {
+		.dump = ib_nl_handle_resolve_resp,
+		.module = THIS_MODULE },
+	[RDMA_NL_LS_OP_SET_TIMEOUT] = {
+		.dump = ib_nl_handle_set_timeout,
+		.module = THIS_MODULE },
+	[RDMA_NL_LS_OP_IP_RESOLVE] = {
+		.dump = ib_nl_handle_ip_res_resp,
+		.module = THIS_MODULE },
+};
+
+static int ib_add_ibnl_clients(void)
+{
+	return ibnl_add_client(RDMA_NL_LS, ARRAY_SIZE(ibnl_ls_cb_table),
+			       ibnl_ls_cb_table);
+}
+
+static void ib_remove_ibnl_clients(void)
+{
+	ibnl_remove_client(RDMA_NL_LS);
+}
+
 static int __init ib_core_init(void)
 {
 	int ret;
@@ -983,10 +1009,42 @@ static int __init ib_core_init(void)
 		goto err_sysfs;
 	}
 
+	ret = addr_init();
+	if (ret) {
+		pr_warn("Could't init IB address resolution\n");
+		goto err_ibnl;
+	}
+
+	ret = ib_mad_init();
+	if (ret) {
+		pr_warn("Couldn't init IB MAD\n");
+		goto err_addr;
+	}
+
+	ret = ib_sa_init();
+	if (ret) {
+		pr_warn("Couldn't init SA\n");
+		goto err_mad;
+	}
+
+	ret = ib_add_ibnl_clients();
+	if (ret) {
+		pr_warn("Couldn't register ibnl clients\n");
+		goto err_sa;
+	}
+
 	ib_cache_setup();
 
 	return 0;
 
+err_sa:
+	ib_sa_cleanup();
+err_mad:
+	ib_mad_cleanup();
+err_addr:
+	addr_cleanup();
+err_ibnl:
+	ibnl_cleanup();
 err_sysfs:
 	class_unregister(&ib_class);
 err_comp:
@@ -999,6 +1057,10 @@ err:
 static void __exit ib_core_cleanup(void)
 {
 	ib_cache_cleanup();
+	ib_remove_ibnl_clients();
+	ib_sa_cleanup();
+	ib_mad_cleanup();
+	addr_cleanup();
 	ibnl_cleanup();
 	class_unregister(&ib_class);
 	destroy_workqueue(ib_comp_wq);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/infiniband/core/iwcm.c linux-libre-4.7-gnu/drivers/infiniband/core/iwcm.c
--- linux-libre-4.6-gnu/drivers/infiniband/core/iwcm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/infiniband/core/iwcm.c	2016-07-24 15:23:50.000000000 -0400
@@ -459,7 +459,7 @@ static void iw_cm_check_wildcard(struct
 	if (pm_addr->ss_family == AF_INET) {
 		struct sockaddr_in *pm4_addr = (struct sockaddr_in *)pm_addr;
 
-		if (pm4_addr->sin_addr.s_addr == INADDR_ANY) {
+		if (pm4_addr->sin_addr.s_addr == htonl(INADDR_ANY)) {
 			struct sockaddr_in *cm4_addr =
 				(struct sockaddr_in *)cm_addr;
 			struct sockaddr_in *cm4_outaddr =
@@ -1175,7 +1175,7 @@ static int __init iw_cm_init(void)
 	if (ret)
 		pr_err("iw_cm: couldn't init iwpm\n");
 
-	ret = ibnl_add_client(RDMA_NL_IWCM, RDMA_NL_IWPM_NUM_OPS,
+	ret = ibnl_add_client(RDMA_NL_IWCM, ARRAY_SIZE(iwcm_nl_cb_table),
 			      iwcm_nl_cb_table);
 	if (ret)
 		pr_err("iw_cm: couldn't register netlink callbacks\n");
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/infiniband/core/iwpm_msg.c linux-libre-4.7-gnu/drivers/infiniband/core/iwpm_msg.c
--- linux-libre-4.6-gnu/drivers/infiniband/core/iwpm_msg.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/infiniband/core/iwpm_msg.c	2016-07-24 15:23:50.000000000 -0400
@@ -506,7 +506,7 @@ int iwpm_add_and_query_mapping_cb(struct
 	if (!nlmsg_request) {
 		pr_info("%s: Could not find a matching request (seq = %u)\n",
 				 __func__, msg_seq);
-			return -EINVAL;
+		return -EINVAL;
 	}
 	pm_msg = nlmsg_request->req_buffer;
 	local_sockaddr = (struct sockaddr_storage *)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/infiniband/core/iwpm_util.c linux-libre-4.7-gnu/drivers/infiniband/core/iwpm_util.c
--- linux-libre-4.6-gnu/drivers/infiniband/core/iwpm_util.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/infiniband/core/iwpm_util.c	2016-07-24 15:23:50.000000000 -0400
@@ -634,6 +634,7 @@ static int send_nlmsg_done(struct sk_buf
 	if (!(ibnl_put_msg(skb, &nlh, 0, 0, nl_client,
 			   RDMA_NL_IWPM_MAPINFO, NLM_F_MULTI))) {
 		pr_warn("%s Unable to put NLMSG_DONE\n", __func__);
+		dev_kfree_skb(skb);
 		return -ENOMEM;
 	}
 	nlh->nlmsg_type = NLMSG_DONE;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/infiniband/core/mad.c linux-libre-4.7-gnu/drivers/infiniband/core/mad.c
--- linux-libre-4.6-gnu/drivers/infiniband/core/mad.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/infiniband/core/mad.c	2016-07-24 15:23:50.000000000 -0400
@@ -47,11 +47,7 @@
 #include "smi.h"
 #include "opa_smi.h"
 #include "agent.h"
-
-MODULE_LICENSE("Dual BSD/GPL");
-MODULE_DESCRIPTION("kernel IB MAD API");
-MODULE_AUTHOR("Hal Rosenstock");
-MODULE_AUTHOR("Sean Hefty");
+#include "core_priv.h"
 
 static int mad_sendq_size = IB_MAD_QP_SEND_SIZE;
 static int mad_recvq_size = IB_MAD_QP_RECV_SIZE;
@@ -1642,9 +1638,9 @@ static void remove_mad_reg_req(struct ib
 		/* Now, check to see if there are any methods still in use */
 		if (!check_method_table(method)) {
 			/* If not, release management method table */
-			 kfree(method);
-			 class->method_table[mgmt_class] = NULL;
-			 /* Any management classes left ? */
+			kfree(method);
+			class->method_table[mgmt_class] = NULL;
+			/* Any management classes left ? */
 			if (!check_class_table(class)) {
 				/* If not, release management class table */
 				kfree(class);
@@ -3316,7 +3312,7 @@ static struct ib_client mad_client = {
 	.remove = ib_mad_remove_device
 };
 
-static int __init ib_mad_init_module(void)
+int ib_mad_init(void)
 {
 	mad_recvq_size = min(mad_recvq_size, IB_MAD_QP_MAX_SIZE);
 	mad_recvq_size = max(mad_recvq_size, IB_MAD_QP_MIN_SIZE);
@@ -3334,10 +3330,7 @@ static int __init ib_mad_init_module(voi
 	return 0;
 }
 
-static void __exit ib_mad_cleanup_module(void)
+void ib_mad_cleanup(void)
 {
 	ib_unregister_client(&mad_client);
 }
-
-module_init(ib_mad_init_module);
-module_exit(ib_mad_cleanup_module);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/infiniband/core/Makefile linux-libre-4.7-gnu/drivers/infiniband/core/Makefile
--- linux-libre-4.6-gnu/drivers/infiniband/core/Makefile	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/infiniband/core/Makefile	2016-07-24 15:23:50.000000000 -0400
@@ -1,23 +1,19 @@
 infiniband-$(CONFIG_INFINIBAND_ADDR_TRANS)	:= rdma_cm.o
 user_access-$(CONFIG_INFINIBAND_ADDR_TRANS)	:= rdma_ucm.o
 
-obj-$(CONFIG_INFINIBAND) +=		ib_core.o ib_mad.o ib_sa.o \
-					ib_cm.o iw_cm.o ib_addr.o \
+obj-$(CONFIG_INFINIBAND) +=		ib_core.o ib_cm.o iw_cm.o \
 					$(infiniband-y)
 obj-$(CONFIG_INFINIBAND_USER_MAD) +=	ib_umad.o
 obj-$(CONFIG_INFINIBAND_USER_ACCESS) +=	ib_uverbs.o ib_ucm.o \
 					$(user_access-y)
 
-ib_core-y :=			packer.o ud_header.o verbs.o cq.o sysfs.o \
+ib_core-y :=			packer.o ud_header.o verbs.o cq.o rw.o sysfs.o \
 				device.o fmr_pool.o cache.o netlink.o \
-				roce_gid_mgmt.o
+				roce_gid_mgmt.o mr_pool.o addr.o sa_query.o \
+				multicast.o mad.o smi.o agent.o mad_rmpp.o
 ib_core-$(CONFIG_INFINIBAND_USER_MEM) += umem.o
 ib_core-$(CONFIG_INFINIBAND_ON_DEMAND_PAGING) += umem_odp.o umem_rbtree.o
 
-ib_mad-y :=			mad.o smi.o agent.o mad_rmpp.o
-
-ib_sa-y :=			sa_query.o multicast.o
-
 ib_cm-y :=			cm.o
 
 iw_cm-y :=			iwcm.o iwpm_util.o iwpm_msg.o
@@ -28,8 +24,6 @@ rdma_cm-$(CONFIG_INFINIBAND_ADDR_TRANS_C
 
 rdma_ucm-y :=			ucma.o
 
-ib_addr-y :=			addr.o
-
 ib_umad-y :=			user_mad.o
 
 ib_ucm-y :=			ucm.o
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/infiniband/core/mr_pool.c linux-libre-4.7-gnu/drivers/infiniband/core/mr_pool.c
--- linux-libre-4.6-gnu/drivers/infiniband/core/mr_pool.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/infiniband/core/mr_pool.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2016 HGST, a Western Digital Company.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ */
+#include <rdma/ib_verbs.h>
+#include <rdma/mr_pool.h>
+
+struct ib_mr *ib_mr_pool_get(struct ib_qp *qp, struct list_head *list)
+{
+	struct ib_mr *mr;
+	unsigned long flags;
+
+	spin_lock_irqsave(&qp->mr_lock, flags);
+	mr = list_first_entry_or_null(list, struct ib_mr, qp_entry);
+	if (mr) {
+		list_del(&mr->qp_entry);
+		qp->mrs_used++;
+	}
+	spin_unlock_irqrestore(&qp->mr_lock, flags);
+
+	return mr;
+}
+EXPORT_SYMBOL(ib_mr_pool_get);
+
+void ib_mr_pool_put(struct ib_qp *qp, struct list_head *list, struct ib_mr *mr)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&qp->mr_lock, flags);
+	list_add(&mr->qp_entry, list);
+	qp->mrs_used--;
+	spin_unlock_irqrestore(&qp->mr_lock, flags);
+}
+EXPORT_SYMBOL(ib_mr_pool_put);
+
+int ib_mr_pool_init(struct ib_qp *qp, struct list_head *list, int nr,
+		enum ib_mr_type type, u32 max_num_sg)
+{
+	struct ib_mr *mr;
+	unsigned long flags;
+	int ret, i;
+
+	for (i = 0; i < nr; i++) {
+		mr = ib_alloc_mr(qp->pd, type, max_num_sg);
+		if (IS_ERR(mr)) {
+			ret = PTR_ERR(mr);
+			goto out;
+		}
+
+		spin_lock_irqsave(&qp->mr_lock, flags);
+		list_add_tail(&mr->qp_entry, list);
+		spin_unlock_irqrestore(&qp->mr_lock, flags);
+	}
+
+	return 0;
+out:
+	ib_mr_pool_destroy(qp, list);
+	return ret;
+}
+EXPORT_SYMBOL(ib_mr_pool_init);
+
+void ib_mr_pool_destroy(struct ib_qp *qp, struct list_head *list)
+{
+	struct ib_mr *mr;
+	unsigned long flags;
+
+	spin_lock_irqsave(&qp->mr_lock, flags);
+	while (!list_empty(list)) {
+		mr = list_first_entry(list, struct ib_mr, qp_entry);
+		list_del(&mr->qp_entry);
+
+		spin_unlock_irqrestore(&qp->mr_lock, flags);
+		ib_dereg_mr(mr);
+		spin_lock_irqsave(&qp->mr_lock, flags);
+	}
+	spin_unlock_irqrestore(&qp->mr_lock, flags);
+}
+EXPORT_SYMBOL(ib_mr_pool_destroy);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/infiniband/core/multicast.c linux-libre-4.7-gnu/drivers/infiniband/core/multicast.c
--- linux-libre-4.6-gnu/drivers/infiniband/core/multicast.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/infiniband/core/multicast.c	2016-07-24 15:23:50.000000000 -0400
@@ -93,6 +93,18 @@ enum {
 
 struct mcast_member;
 
+/*
+* There are 4 types of join states:
+* FullMember, NonMember, SendOnlyNonMember, SendOnlyFullMember.
+*/
+enum {
+	FULLMEMBER_JOIN,
+	NONMEMBER_JOIN,
+	SENDONLY_NONMEBER_JOIN,
+	SENDONLY_FULLMEMBER_JOIN,
+	NUM_JOIN_MEMBERSHIP_TYPES,
+};
+
 struct mcast_group {
 	struct ib_sa_mcmember_rec rec;
 	struct rb_node		node;
@@ -102,7 +114,7 @@ struct mcast_group {
 	struct list_head	pending_list;
 	struct list_head	active_list;
 	struct mcast_member	*last_join;
-	int			members[3];
+	int			members[NUM_JOIN_MEMBERSHIP_TYPES];
 	atomic_t		refcount;
 	enum mcast_group_state	state;
 	struct ib_sa_query	*query;
@@ -220,8 +232,9 @@ static void queue_join(struct mcast_memb
 }
 
 /*
- * A multicast group has three types of members: full member, non member, and
- * send only member.  We need to keep track of the number of members of each
+ * A multicast group has four types of members: full member, non member,
+ * sendonly non member and sendonly full member.
+ * We need to keep track of the number of members of each
  * type based on their join state.  Adjust the number of members the belong to
  * the specified join states.
  */
@@ -229,7 +242,7 @@ static void adjust_membership(struct mca
 {
 	int i;
 
-	for (i = 0; i < 3; i++, join_state >>= 1)
+	for (i = 0; i < NUM_JOIN_MEMBERSHIP_TYPES; i++, join_state >>= 1)
 		if (join_state & 0x1)
 			group->members[i] += inc;
 }
@@ -245,7 +258,7 @@ static u8 get_leave_state(struct mcast_g
 	u8 leave_state = 0;
 	int i;
 
-	for (i = 0; i < 3; i++)
+	for (i = 0; i < NUM_JOIN_MEMBERSHIP_TYPES; i++)
 		if (!group->members[i])
 			leave_state |= (0x1 << i);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/infiniband/core/netlink.c linux-libre-4.7-gnu/drivers/infiniband/core/netlink.c
--- linux-libre-4.6-gnu/drivers/infiniband/core/netlink.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/infiniband/core/netlink.c	2016-07-24 15:23:50.000000000 -0400
@@ -151,12 +151,11 @@ static int ibnl_rcv_msg(struct sk_buff *
 	struct ibnl_client *client;
 	int type = nlh->nlmsg_type;
 	int index = RDMA_NL_GET_CLIENT(type);
-	int op = RDMA_NL_GET_OP(type);
+	unsigned int op = RDMA_NL_GET_OP(type);
 
 	list_for_each_entry(client, &client_list, list) {
 		if (client->index == index) {
-			if (op < 0 || op >= client->nops ||
-			    !client->cb_table[op].dump)
+			if (op >= client->nops || !client->cb_table[op].dump)
 				return -EINVAL;
 
 			/*
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/infiniband/core/rw.c linux-libre-4.7-gnu/drivers/infiniband/core/rw.c
--- linux-libre-4.6-gnu/drivers/infiniband/core/rw.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/infiniband/core/rw.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,727 @@
+/*
+ * Copyright (c) 2016 HGST, a Western Digital Company.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ */
+#include <linux/moduleparam.h>
+#include <linux/slab.h>
+#include <rdma/mr_pool.h>
+#include <rdma/rw.h>
+
+enum {
+	RDMA_RW_SINGLE_WR,
+	RDMA_RW_MULTI_WR,
+	RDMA_RW_MR,
+	RDMA_RW_SIG_MR,
+};
+
+static bool rdma_rw_force_mr;
+module_param_named(force_mr, rdma_rw_force_mr, bool, 0);
+MODULE_PARM_DESC(force_mr, "Force usage of MRs for RDMA READ/WRITE operations");
+
+/*
+ * Check if the device might use memory registration.  This is currently only
+ * true for iWarp devices. In the future we can hopefully fine tune this based
+ * on HCA driver input.
+ */
+static inline bool rdma_rw_can_use_mr(struct ib_device *dev, u8 port_num)
+{
+	if (rdma_protocol_iwarp(dev, port_num))
+		return true;
+	if (unlikely(rdma_rw_force_mr))
+		return true;
+	return false;
+}
+
+/*
+ * Check if the device will use memory registration for this RW operation.
+ * We currently always use memory registrations for iWarp RDMA READs, and
+ * have a debug option to force usage of MRs.
+ *
+ * XXX: In the future we can hopefully fine tune this based on HCA driver
+ * input.
+ */
+static inline bool rdma_rw_io_needs_mr(struct ib_device *dev, u8 port_num,
+		enum dma_data_direction dir, int dma_nents)
+{
+	if (rdma_protocol_iwarp(dev, port_num) && dir == DMA_FROM_DEVICE)
+		return true;
+	if (unlikely(rdma_rw_force_mr))
+		return true;
+	return false;
+}
+
+static inline u32 rdma_rw_max_sge(struct ib_device *dev,
+		enum dma_data_direction dir)
+{
+	return dir == DMA_TO_DEVICE ?
+		dev->attrs.max_sge : dev->attrs.max_sge_rd;
+}
+
+static inline u32 rdma_rw_fr_page_list_len(struct ib_device *dev)
+{
+	/* arbitrary limit to avoid allocating gigantic resources */
+	return min_t(u32, dev->attrs.max_fast_reg_page_list_len, 256);
+}
+
+static int rdma_rw_init_one_mr(struct ib_qp *qp, u8 port_num,
+		struct rdma_rw_reg_ctx *reg, struct scatterlist *sg,
+		u32 sg_cnt, u32 offset)
+{
+	u32 pages_per_mr = rdma_rw_fr_page_list_len(qp->pd->device);
+	u32 nents = min(sg_cnt, pages_per_mr);
+	int count = 0, ret;
+
+	reg->mr = ib_mr_pool_get(qp, &qp->rdma_mrs);
+	if (!reg->mr)
+		return -EAGAIN;
+
+	if (reg->mr->need_inval) {
+		reg->inv_wr.opcode = IB_WR_LOCAL_INV;
+		reg->inv_wr.ex.invalidate_rkey = reg->mr->lkey;
+		reg->inv_wr.next = &reg->reg_wr.wr;
+		count++;
+	} else {
+		reg->inv_wr.next = NULL;
+	}
+
+	ret = ib_map_mr_sg(reg->mr, sg, nents, &offset, PAGE_SIZE);
+	if (ret < nents) {
+		ib_mr_pool_put(qp, &qp->rdma_mrs, reg->mr);
+		return -EINVAL;
+	}
+
+	reg->reg_wr.wr.opcode = IB_WR_REG_MR;
+	reg->reg_wr.mr = reg->mr;
+	reg->reg_wr.access = IB_ACCESS_LOCAL_WRITE;
+	if (rdma_protocol_iwarp(qp->device, port_num))
+		reg->reg_wr.access |= IB_ACCESS_REMOTE_WRITE;
+	count++;
+
+	reg->sge.addr = reg->mr->iova;
+	reg->sge.length = reg->mr->length;
+	return count;
+}
+
+static int rdma_rw_init_mr_wrs(struct rdma_rw_ctx *ctx, struct ib_qp *qp,
+		u8 port_num, struct scatterlist *sg, u32 sg_cnt, u32 offset,
+		u64 remote_addr, u32 rkey, enum dma_data_direction dir)
+{
+	u32 pages_per_mr = rdma_rw_fr_page_list_len(qp->pd->device);
+	int i, j, ret = 0, count = 0;
+
+	ctx->nr_ops = (sg_cnt + pages_per_mr - 1) / pages_per_mr;
+	ctx->reg = kcalloc(ctx->nr_ops, sizeof(*ctx->reg), GFP_KERNEL);
+	if (!ctx->reg) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	for (i = 0; i < ctx->nr_ops; i++) {
+		struct rdma_rw_reg_ctx *prev = i ? &ctx->reg[i - 1] : NULL;
+		struct rdma_rw_reg_ctx *reg = &ctx->reg[i];
+		u32 nents = min(sg_cnt, pages_per_mr);
+
+		ret = rdma_rw_init_one_mr(qp, port_num, reg, sg, sg_cnt,
+				offset);
+		if (ret < 0)
+			goto out_free;
+		count += ret;
+
+		if (prev) {
+			if (reg->mr->need_inval)
+				prev->wr.wr.next = &reg->inv_wr;
+			else
+				prev->wr.wr.next = &reg->reg_wr.wr;
+		}
+
+		reg->reg_wr.wr.next = &reg->wr.wr;
+
+		reg->wr.wr.sg_list = &reg->sge;
+		reg->wr.wr.num_sge = 1;
+		reg->wr.remote_addr = remote_addr;
+		reg->wr.rkey = rkey;
+		if (dir == DMA_TO_DEVICE) {
+			reg->wr.wr.opcode = IB_WR_RDMA_WRITE;
+		} else if (!rdma_cap_read_inv(qp->device, port_num)) {
+			reg->wr.wr.opcode = IB_WR_RDMA_READ;
+		} else {
+			reg->wr.wr.opcode = IB_WR_RDMA_READ_WITH_INV;
+			reg->wr.wr.ex.invalidate_rkey = reg->mr->lkey;
+		}
+		count++;
+
+		remote_addr += reg->sge.length;
+		sg_cnt -= nents;
+		for (j = 0; j < nents; j++)
+			sg = sg_next(sg);
+		offset = 0;
+	}
+
+	ctx->type = RDMA_RW_MR;
+	return count;
+
+out_free:
+	while (--i >= 0)
+		ib_mr_pool_put(qp, &qp->rdma_mrs, ctx->reg[i].mr);
+	kfree(ctx->reg);
+out:
+	return ret;
+}
+
+static int rdma_rw_init_map_wrs(struct rdma_rw_ctx *ctx, struct ib_qp *qp,
+		struct scatterlist *sg, u32 sg_cnt, u32 offset,
+		u64 remote_addr, u32 rkey, enum dma_data_direction dir)
+{
+	struct ib_device *dev = qp->pd->device;
+	u32 max_sge = rdma_rw_max_sge(dev, dir);
+	struct ib_sge *sge;
+	u32 total_len = 0, i, j;
+
+	ctx->nr_ops = DIV_ROUND_UP(sg_cnt, max_sge);
+
+	ctx->map.sges = sge = kcalloc(sg_cnt, sizeof(*sge), GFP_KERNEL);
+	if (!ctx->map.sges)
+		goto out;
+
+	ctx->map.wrs = kcalloc(ctx->nr_ops, sizeof(*ctx->map.wrs), GFP_KERNEL);
+	if (!ctx->map.wrs)
+		goto out_free_sges;
+
+	for (i = 0; i < ctx->nr_ops; i++) {
+		struct ib_rdma_wr *rdma_wr = &ctx->map.wrs[i];
+		u32 nr_sge = min(sg_cnt, max_sge);
+
+		if (dir == DMA_TO_DEVICE)
+			rdma_wr->wr.opcode = IB_WR_RDMA_WRITE;
+		else
+			rdma_wr->wr.opcode = IB_WR_RDMA_READ;
+		rdma_wr->remote_addr = remote_addr + total_len;
+		rdma_wr->rkey = rkey;
+		rdma_wr->wr.sg_list = sge;
+
+		for (j = 0; j < nr_sge; j++, sg = sg_next(sg)) {
+			rdma_wr->wr.num_sge++;
+
+			sge->addr = ib_sg_dma_address(dev, sg) + offset;
+			sge->length = ib_sg_dma_len(dev, sg) - offset;
+			sge->lkey = qp->pd->local_dma_lkey;
+
+			total_len += sge->length;
+			sge++;
+			sg_cnt--;
+			offset = 0;
+		}
+
+		if (i + 1 < ctx->nr_ops)
+			rdma_wr->wr.next = &ctx->map.wrs[i + 1].wr;
+	}
+
+	ctx->type = RDMA_RW_MULTI_WR;
+	return ctx->nr_ops;
+
+out_free_sges:
+	kfree(ctx->map.sges);
+out:
+	return -ENOMEM;
+}
+
+static int rdma_rw_init_single_wr(struct rdma_rw_ctx *ctx, struct ib_qp *qp,
+		struct scatterlist *sg, u32 offset, u64 remote_addr, u32 rkey,
+		enum dma_data_direction dir)
+{
+	struct ib_device *dev = qp->pd->device;
+	struct ib_rdma_wr *rdma_wr = &ctx->single.wr;
+
+	ctx->nr_ops = 1;
+
+	ctx->single.sge.lkey = qp->pd->local_dma_lkey;
+	ctx->single.sge.addr = ib_sg_dma_address(dev, sg) + offset;
+	ctx->single.sge.length = ib_sg_dma_len(dev, sg) - offset;
+
+	memset(rdma_wr, 0, sizeof(*rdma_wr));
+	if (dir == DMA_TO_DEVICE)
+		rdma_wr->wr.opcode = IB_WR_RDMA_WRITE;
+	else
+		rdma_wr->wr.opcode = IB_WR_RDMA_READ;
+	rdma_wr->wr.sg_list = &ctx->single.sge;
+	rdma_wr->wr.num_sge = 1;
+	rdma_wr->remote_addr = remote_addr;
+	rdma_wr->rkey = rkey;
+
+	ctx->type = RDMA_RW_SINGLE_WR;
+	return 1;
+}
+
+/**
+ * rdma_rw_ctx_init - initialize a RDMA READ/WRITE context
+ * @ctx:	context to initialize
+ * @qp:		queue pair to operate on
+ * @port_num:	port num to which the connection is bound
+ * @sg:		scatterlist to READ/WRITE from/to
+ * @sg_cnt:	number of entries in @sg
+ * @sg_offset:	current byte offset into @sg
+ * @remote_addr:remote address to read/write (relative to @rkey)
+ * @rkey:	remote key to operate on
+ * @dir:	%DMA_TO_DEVICE for RDMA WRITE, %DMA_FROM_DEVICE for RDMA READ
+ *
+ * Returns the number of WQEs that will be needed on the workqueue if
+ * successful, or a negative error code.
+ */
+int rdma_rw_ctx_init(struct rdma_rw_ctx *ctx, struct ib_qp *qp, u8 port_num,
+		struct scatterlist *sg, u32 sg_cnt, u32 sg_offset,
+		u64 remote_addr, u32 rkey, enum dma_data_direction dir)
+{
+	struct ib_device *dev = qp->pd->device;
+	int ret;
+
+	ret = ib_dma_map_sg(dev, sg, sg_cnt, dir);
+	if (!ret)
+		return -ENOMEM;
+	sg_cnt = ret;
+
+	/*
+	 * Skip to the S/G entry that sg_offset falls into:
+	 */
+	for (;;) {
+		u32 len = ib_sg_dma_len(dev, sg);
+
+		if (sg_offset < len)
+			break;
+
+		sg = sg_next(sg);
+		sg_offset -= len;
+		sg_cnt--;
+	}
+
+	ret = -EIO;
+	if (WARN_ON_ONCE(sg_cnt == 0))
+		goto out_unmap_sg;
+
+	if (rdma_rw_io_needs_mr(qp->device, port_num, dir, sg_cnt)) {
+		ret = rdma_rw_init_mr_wrs(ctx, qp, port_num, sg, sg_cnt,
+				sg_offset, remote_addr, rkey, dir);
+	} else if (sg_cnt > 1) {
+		ret = rdma_rw_init_map_wrs(ctx, qp, sg, sg_cnt, sg_offset,
+				remote_addr, rkey, dir);
+	} else {
+		ret = rdma_rw_init_single_wr(ctx, qp, sg, sg_offset,
+				remote_addr, rkey, dir);
+	}
+
+	if (ret < 0)
+		goto out_unmap_sg;
+	return ret;
+
+out_unmap_sg:
+	ib_dma_unmap_sg(dev, sg, sg_cnt, dir);
+	return ret;
+}
+EXPORT_SYMBOL(rdma_rw_ctx_init);
+
+/**
+ * rdma_rw_ctx_signature init - initialize a RW context with signature offload
+ * @ctx:	context to initialize
+ * @qp:		queue pair to operate on
+ * @port_num:	port num to which the connection is bound
+ * @sg:		scatterlist to READ/WRITE from/to
+ * @sg_cnt:	number of entries in @sg
+ * @prot_sg:	scatterlist to READ/WRITE protection information from/to
+ * @prot_sg_cnt: number of entries in @prot_sg
+ * @sig_attrs:	signature offloading algorithms
+ * @remote_addr:remote address to read/write (relative to @rkey)
+ * @rkey:	remote key to operate on
+ * @dir:	%DMA_TO_DEVICE for RDMA WRITE, %DMA_FROM_DEVICE for RDMA READ
+ *
+ * Returns the number of WQEs that will be needed on the workqueue if
+ * successful, or a negative error code.
+ */
+int rdma_rw_ctx_signature_init(struct rdma_rw_ctx *ctx, struct ib_qp *qp,
+		u8 port_num, struct scatterlist *sg, u32 sg_cnt,
+		struct scatterlist *prot_sg, u32 prot_sg_cnt,
+		struct ib_sig_attrs *sig_attrs,
+		u64 remote_addr, u32 rkey, enum dma_data_direction dir)
+{
+	struct ib_device *dev = qp->pd->device;
+	u32 pages_per_mr = rdma_rw_fr_page_list_len(qp->pd->device);
+	struct ib_rdma_wr *rdma_wr;
+	struct ib_send_wr *prev_wr = NULL;
+	int count = 0, ret;
+
+	if (sg_cnt > pages_per_mr || prot_sg_cnt > pages_per_mr) {
+		pr_err("SG count too large\n");
+		return -EINVAL;
+	}
+
+	ret = ib_dma_map_sg(dev, sg, sg_cnt, dir);
+	if (!ret)
+		return -ENOMEM;
+	sg_cnt = ret;
+
+	ret = ib_dma_map_sg(dev, prot_sg, prot_sg_cnt, dir);
+	if (!ret) {
+		ret = -ENOMEM;
+		goto out_unmap_sg;
+	}
+	prot_sg_cnt = ret;
+
+	ctx->type = RDMA_RW_SIG_MR;
+	ctx->nr_ops = 1;
+	ctx->sig = kcalloc(1, sizeof(*ctx->sig), GFP_KERNEL);
+	if (!ctx->sig) {
+		ret = -ENOMEM;
+		goto out_unmap_prot_sg;
+	}
+
+	ret = rdma_rw_init_one_mr(qp, port_num, &ctx->sig->data, sg, sg_cnt, 0);
+	if (ret < 0)
+		goto out_free_ctx;
+	count += ret;
+	prev_wr = &ctx->sig->data.reg_wr.wr;
+
+	if (prot_sg_cnt) {
+		ret = rdma_rw_init_one_mr(qp, port_num, &ctx->sig->prot,
+				prot_sg, prot_sg_cnt, 0);
+		if (ret < 0)
+			goto out_destroy_data_mr;
+		count += ret;
+
+		if (ctx->sig->prot.inv_wr.next)
+			prev_wr->next = &ctx->sig->prot.inv_wr;
+		else
+			prev_wr->next = &ctx->sig->prot.reg_wr.wr;
+		prev_wr = &ctx->sig->prot.reg_wr.wr;
+	} else {
+		ctx->sig->prot.mr = NULL;
+	}
+
+	ctx->sig->sig_mr = ib_mr_pool_get(qp, &qp->sig_mrs);
+	if (!ctx->sig->sig_mr) {
+		ret = -EAGAIN;
+		goto out_destroy_prot_mr;
+	}
+
+	if (ctx->sig->sig_mr->need_inval) {
+		memset(&ctx->sig->sig_inv_wr, 0, sizeof(ctx->sig->sig_inv_wr));
+
+		ctx->sig->sig_inv_wr.opcode = IB_WR_LOCAL_INV;
+		ctx->sig->sig_inv_wr.ex.invalidate_rkey = ctx->sig->sig_mr->rkey;
+
+		prev_wr->next = &ctx->sig->sig_inv_wr;
+		prev_wr = &ctx->sig->sig_inv_wr;
+	}
+
+	ctx->sig->sig_wr.wr.opcode = IB_WR_REG_SIG_MR;
+	ctx->sig->sig_wr.wr.wr_cqe = NULL;
+	ctx->sig->sig_wr.wr.sg_list = &ctx->sig->data.sge;
+	ctx->sig->sig_wr.wr.num_sge = 1;
+	ctx->sig->sig_wr.access_flags = IB_ACCESS_LOCAL_WRITE;
+	ctx->sig->sig_wr.sig_attrs = sig_attrs;
+	ctx->sig->sig_wr.sig_mr = ctx->sig->sig_mr;
+	if (prot_sg_cnt)
+		ctx->sig->sig_wr.prot = &ctx->sig->prot.sge;
+	prev_wr->next = &ctx->sig->sig_wr.wr;
+	prev_wr = &ctx->sig->sig_wr.wr;
+	count++;
+
+	ctx->sig->sig_sge.addr = 0;
+	ctx->sig->sig_sge.length = ctx->sig->data.sge.length;
+	if (sig_attrs->wire.sig_type != IB_SIG_TYPE_NONE)
+		ctx->sig->sig_sge.length += ctx->sig->prot.sge.length;
+
+	rdma_wr = &ctx->sig->data.wr;
+	rdma_wr->wr.sg_list = &ctx->sig->sig_sge;
+	rdma_wr->wr.num_sge = 1;
+	rdma_wr->remote_addr = remote_addr;
+	rdma_wr->rkey = rkey;
+	if (dir == DMA_TO_DEVICE)
+		rdma_wr->wr.opcode = IB_WR_RDMA_WRITE;
+	else
+		rdma_wr->wr.opcode = IB_WR_RDMA_READ;
+	prev_wr->next = &rdma_wr->wr;
+	prev_wr = &rdma_wr->wr;
+	count++;
+
+	return count;
+
+out_destroy_prot_mr:
+	if (prot_sg_cnt)
+		ib_mr_pool_put(qp, &qp->rdma_mrs, ctx->sig->prot.mr);
+out_destroy_data_mr:
+	ib_mr_pool_put(qp, &qp->rdma_mrs, ctx->sig->data.mr);
+out_free_ctx:
+	kfree(ctx->sig);
+out_unmap_prot_sg:
+	ib_dma_unmap_sg(dev, prot_sg, prot_sg_cnt, dir);
+out_unmap_sg:
+	ib_dma_unmap_sg(dev, sg, sg_cnt, dir);
+	return ret;
+}
+EXPORT_SYMBOL(rdma_rw_ctx_signature_init);
+
+/*
+ * Now that we are going to post the WRs we can update the lkey and need_inval
+ * state on the MRs.  If we were doing this at init time, we would get double
+ * or missing invalidations if a context was initialized but not actually
+ * posted.
+ */
+static void rdma_rw_update_lkey(struct rdma_rw_reg_ctx *reg, bool need_inval)
+{
+	reg->mr->need_inval = need_inval;
+	ib_update_fast_reg_key(reg->mr, ib_inc_rkey(reg->mr->lkey));
+	reg->reg_wr.key = reg->mr->lkey;
+	reg->sge.lkey = reg->mr->lkey;
+}
+
+/**
+ * rdma_rw_ctx_wrs - return chain of WRs for a RDMA READ or WRITE operation
+ * @ctx:	context to operate on
+ * @qp:		queue pair to operate on
+ * @port_num:	port num to which the connection is bound
+ * @cqe:	completion queue entry for the last WR
+ * @chain_wr:	WR to append to the posted chain
+ *
+ * Return the WR chain for the set of RDMA READ/WRITE operations described by
+ * @ctx, as well as any memory registration operations needed.  If @chain_wr
+ * is non-NULL the WR it points to will be appended to the chain of WRs posted.
+ * If @chain_wr is not set @cqe must be set so that the caller gets a
+ * completion notification.
+ */
+struct ib_send_wr *rdma_rw_ctx_wrs(struct rdma_rw_ctx *ctx, struct ib_qp *qp,
+		u8 port_num, struct ib_cqe *cqe, struct ib_send_wr *chain_wr)
+{
+	struct ib_send_wr *first_wr, *last_wr;
+	int i;
+
+	switch (ctx->type) {
+	case RDMA_RW_SIG_MR:
+		rdma_rw_update_lkey(&ctx->sig->data, true);
+		if (ctx->sig->prot.mr)
+			rdma_rw_update_lkey(&ctx->sig->prot, true);
+	
+		ctx->sig->sig_mr->need_inval = true;
+		ib_update_fast_reg_key(ctx->sig->sig_mr,
+			ib_inc_rkey(ctx->sig->sig_mr->lkey));
+		ctx->sig->sig_sge.lkey = ctx->sig->sig_mr->lkey;
+
+		if (ctx->sig->data.inv_wr.next)
+			first_wr = &ctx->sig->data.inv_wr;
+		else
+			first_wr = &ctx->sig->data.reg_wr.wr;
+		last_wr = &ctx->sig->data.wr.wr;
+		break;
+	case RDMA_RW_MR:
+		for (i = 0; i < ctx->nr_ops; i++) {
+			rdma_rw_update_lkey(&ctx->reg[i],
+				ctx->reg[i].wr.wr.opcode !=
+					IB_WR_RDMA_READ_WITH_INV);
+		}
+
+		if (ctx->reg[0].inv_wr.next)
+			first_wr = &ctx->reg[0].inv_wr;
+		else
+			first_wr = &ctx->reg[0].reg_wr.wr;
+		last_wr = &ctx->reg[ctx->nr_ops - 1].wr.wr;
+		break;
+	case RDMA_RW_MULTI_WR:
+		first_wr = &ctx->map.wrs[0].wr;
+		last_wr = &ctx->map.wrs[ctx->nr_ops - 1].wr;
+		break;
+	case RDMA_RW_SINGLE_WR:
+		first_wr = &ctx->single.wr.wr;
+		last_wr = &ctx->single.wr.wr;
+		break;
+	default:
+		BUG();
+	}
+
+	if (chain_wr) {
+		last_wr->next = chain_wr;
+	} else {
+		last_wr->wr_cqe = cqe;
+		last_wr->send_flags |= IB_SEND_SIGNALED;
+	}
+
+	return first_wr;
+}
+EXPORT_SYMBOL(rdma_rw_ctx_wrs);
+
+/**
+ * rdma_rw_ctx_post - post a RDMA READ or RDMA WRITE operation
+ * @ctx:	context to operate on
+ * @qp:		queue pair to operate on
+ * @port_num:	port num to which the connection is bound
+ * @cqe:	completion queue entry for the last WR
+ * @chain_wr:	WR to append to the posted chain
+ *
+ * Post the set of RDMA READ/WRITE operations described by @ctx, as well as
+ * any memory registration operations needed.  If @chain_wr is non-NULL the
+ * WR it points to will be appended to the chain of WRs posted.  If @chain_wr
+ * is not set @cqe must be set so that the caller gets a completion
+ * notification.
+ */
+int rdma_rw_ctx_post(struct rdma_rw_ctx *ctx, struct ib_qp *qp, u8 port_num,
+		struct ib_cqe *cqe, struct ib_send_wr *chain_wr)
+{
+	struct ib_send_wr *first_wr, *bad_wr;
+
+	first_wr = rdma_rw_ctx_wrs(ctx, qp, port_num, cqe, chain_wr);
+	return ib_post_send(qp, first_wr, &bad_wr);
+}
+EXPORT_SYMBOL(rdma_rw_ctx_post);
+
+/**
+ * rdma_rw_ctx_destroy - release all resources allocated by rdma_rw_ctx_init
+ * @ctx:	context to release
+ * @qp:		queue pair to operate on
+ * @port_num:	port num to which the connection is bound
+ * @sg:		scatterlist that was used for the READ/WRITE
+ * @sg_cnt:	number of entries in @sg
+ * @dir:	%DMA_TO_DEVICE for RDMA WRITE, %DMA_FROM_DEVICE for RDMA READ
+ */
+void rdma_rw_ctx_destroy(struct rdma_rw_ctx *ctx, struct ib_qp *qp, u8 port_num,
+		struct scatterlist *sg, u32 sg_cnt, enum dma_data_direction dir)
+{
+	int i;
+
+	switch (ctx->type) {
+	case RDMA_RW_MR:
+		for (i = 0; i < ctx->nr_ops; i++)
+			ib_mr_pool_put(qp, &qp->rdma_mrs, ctx->reg[i].mr);
+		kfree(ctx->reg);
+		break;
+	case RDMA_RW_MULTI_WR:
+		kfree(ctx->map.wrs);
+		kfree(ctx->map.sges);
+		break;
+	case RDMA_RW_SINGLE_WR:
+		break;
+	default:
+		BUG();
+		break;
+	}
+
+	ib_dma_unmap_sg(qp->pd->device, sg, sg_cnt, dir);
+}
+EXPORT_SYMBOL(rdma_rw_ctx_destroy);
+
+/**
+ * rdma_rw_ctx_destroy_signature - release all resources allocated by
+ *	rdma_rw_ctx_init_signature
+ * @ctx:	context to release
+ * @qp:		queue pair to operate on
+ * @port_num:	port num to which the connection is bound
+ * @sg:		scatterlist that was used for the READ/WRITE
+ * @sg_cnt:	number of entries in @sg
+ * @prot_sg:	scatterlist that was used for the READ/WRITE of the PI
+ * @prot_sg_cnt: number of entries in @prot_sg
+ * @dir:	%DMA_TO_DEVICE for RDMA WRITE, %DMA_FROM_DEVICE for RDMA READ
+ */
+void rdma_rw_ctx_destroy_signature(struct rdma_rw_ctx *ctx, struct ib_qp *qp,
+		u8 port_num, struct scatterlist *sg, u32 sg_cnt,
+		struct scatterlist *prot_sg, u32 prot_sg_cnt,
+		enum dma_data_direction dir)
+{
+	if (WARN_ON_ONCE(ctx->type != RDMA_RW_SIG_MR))
+		return;
+
+	ib_mr_pool_put(qp, &qp->rdma_mrs, ctx->sig->data.mr);
+	ib_dma_unmap_sg(qp->pd->device, sg, sg_cnt, dir);
+
+	if (ctx->sig->prot.mr) {
+		ib_mr_pool_put(qp, &qp->rdma_mrs, ctx->sig->prot.mr);
+		ib_dma_unmap_sg(qp->pd->device, prot_sg, prot_sg_cnt, dir);
+	}
+
+	ib_mr_pool_put(qp, &qp->sig_mrs, ctx->sig->sig_mr);
+	kfree(ctx->sig);
+}
+EXPORT_SYMBOL(rdma_rw_ctx_destroy_signature);
+
+void rdma_rw_init_qp(struct ib_device *dev, struct ib_qp_init_attr *attr)
+{
+	u32 factor;
+
+	WARN_ON_ONCE(attr->port_num == 0);
+
+	/*
+	 * Each context needs at least one RDMA READ or WRITE WR.
+	 *
+	 * For some hardware we might need more, eventually we should ask the
+	 * HCA driver for a multiplier here.
+	 */
+	factor = 1;
+
+	/*
+	 * If the devices needs MRs to perform RDMA READ or WRITE operations,
+	 * we'll need two additional MRs for the registrations and the
+	 * invalidation.
+	 */
+	if (attr->create_flags & IB_QP_CREATE_SIGNATURE_EN)
+		factor += 6;	/* (inv + reg) * (data + prot + sig) */
+	else if (rdma_rw_can_use_mr(dev, attr->port_num))
+		factor += 2;	/* inv + reg */
+
+	attr->cap.max_send_wr += factor * attr->cap.max_rdma_ctxs;
+
+	/*
+	 * But maybe we were just too high in the sky and the device doesn't
+	 * even support all we need, and we'll have to live with what we get..
+	 */
+	attr->cap.max_send_wr =
+		min_t(u32, attr->cap.max_send_wr, dev->attrs.max_qp_wr);
+}
+
+int rdma_rw_init_mrs(struct ib_qp *qp, struct ib_qp_init_attr *attr)
+{
+	struct ib_device *dev = qp->pd->device;
+	u32 nr_mrs = 0, nr_sig_mrs = 0;
+	int ret = 0;
+
+	if (attr->create_flags & IB_QP_CREATE_SIGNATURE_EN) {
+		nr_sig_mrs = attr->cap.max_rdma_ctxs;
+		nr_mrs = attr->cap.max_rdma_ctxs * 2;
+	} else if (rdma_rw_can_use_mr(dev, attr->port_num)) {
+		nr_mrs = attr->cap.max_rdma_ctxs;
+	}
+
+	if (nr_mrs) {
+		ret = ib_mr_pool_init(qp, &qp->rdma_mrs, nr_mrs,
+				IB_MR_TYPE_MEM_REG,
+				rdma_rw_fr_page_list_len(dev));
+		if (ret) {
+			pr_err("%s: failed to allocated %d MRs\n",
+				__func__, nr_mrs);
+			return ret;
+		}
+	}
+
+	if (nr_sig_mrs) {
+		ret = ib_mr_pool_init(qp, &qp->sig_mrs, nr_sig_mrs,
+				IB_MR_TYPE_SIGNATURE, 2);
+		if (ret) {
+			pr_err("%s: failed to allocated %d SIG MRs\n",
+				__func__, nr_mrs);
+			goto out_free_rdma_mrs;
+		}
+	}
+
+	return 0;
+
+out_free_rdma_mrs:
+	ib_mr_pool_destroy(qp, &qp->rdma_mrs);
+	return ret;
+}
+
+void rdma_rw_cleanup_mrs(struct ib_qp *qp)
+{
+	ib_mr_pool_destroy(qp, &qp->sig_mrs);
+	ib_mr_pool_destroy(qp, &qp->rdma_mrs);
+}
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/infiniband/core/sa_query.c linux-libre-4.7-gnu/drivers/infiniband/core/sa_query.c
--- linux-libre-4.6-gnu/drivers/infiniband/core/sa_query.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/infiniband/core/sa_query.c	2016-07-24 15:23:50.000000000 -0400
@@ -53,10 +53,6 @@
 #include "sa.h"
 #include "core_priv.h"
 
-MODULE_AUTHOR("Roland Dreier");
-MODULE_DESCRIPTION("InfiniBand subnet administration query support");
-MODULE_LICENSE("Dual BSD/GPL");
-
 #define IB_SA_LOCAL_SVC_TIMEOUT_MIN		100
 #define IB_SA_LOCAL_SVC_TIMEOUT_DEFAULT		2000
 #define IB_SA_LOCAL_SVC_TIMEOUT_MAX		200000
@@ -119,6 +115,12 @@ struct ib_sa_guidinfo_query {
 	struct ib_sa_query sa_query;
 };
 
+struct ib_sa_classport_info_query {
+	void (*callback)(int, struct ib_class_port_info *, void *);
+	void *context;
+	struct ib_sa_query sa_query;
+};
+
 struct ib_sa_mcmember_query {
 	void (*callback)(int, struct ib_sa_mcmember_rec *, void *);
 	void *context;
@@ -392,6 +394,82 @@ static const struct ib_field service_rec
 	  .size_bits    = 2*64 },
 };
 
+#define CLASSPORTINFO_REC_FIELD(field) \
+	.struct_offset_bytes = offsetof(struct ib_class_port_info, field),	\
+	.struct_size_bytes   = sizeof((struct ib_class_port_info *)0)->field,	\
+	.field_name          = "ib_class_port_info:" #field
+
+static const struct ib_field classport_info_rec_table[] = {
+	{ CLASSPORTINFO_REC_FIELD(base_version),
+	  .offset_words = 0,
+	  .offset_bits  = 0,
+	  .size_bits    = 8 },
+	{ CLASSPORTINFO_REC_FIELD(class_version),
+	  .offset_words = 0,
+	  .offset_bits  = 8,
+	  .size_bits    = 8 },
+	{ CLASSPORTINFO_REC_FIELD(capability_mask),
+	  .offset_words = 0,
+	  .offset_bits  = 16,
+	  .size_bits    = 16 },
+	{ CLASSPORTINFO_REC_FIELD(cap_mask2_resp_time),
+	  .offset_words = 1,
+	  .offset_bits  = 0,
+	  .size_bits    = 32 },
+	{ CLASSPORTINFO_REC_FIELD(redirect_gid),
+	  .offset_words = 2,
+	  .offset_bits  = 0,
+	  .size_bits    = 128 },
+	{ CLASSPORTINFO_REC_FIELD(redirect_tcslfl),
+	  .offset_words = 6,
+	  .offset_bits  = 0,
+	  .size_bits    = 32 },
+	{ CLASSPORTINFO_REC_FIELD(redirect_lid),
+	  .offset_words = 7,
+	  .offset_bits  = 0,
+	  .size_bits    = 16 },
+	{ CLASSPORTINFO_REC_FIELD(redirect_pkey),
+	  .offset_words = 7,
+	  .offset_bits  = 16,
+	  .size_bits    = 16 },
+
+	{ CLASSPORTINFO_REC_FIELD(redirect_qp),
+	  .offset_words = 8,
+	  .offset_bits  = 0,
+	  .size_bits    = 32 },
+	{ CLASSPORTINFO_REC_FIELD(redirect_qkey),
+	  .offset_words = 9,
+	  .offset_bits  = 0,
+	  .size_bits    = 32 },
+
+	{ CLASSPORTINFO_REC_FIELD(trap_gid),
+	  .offset_words = 10,
+	  .offset_bits  = 0,
+	  .size_bits    = 128 },
+	{ CLASSPORTINFO_REC_FIELD(trap_tcslfl),
+	  .offset_words = 14,
+	  .offset_bits  = 0,
+	  .size_bits    = 32 },
+
+	{ CLASSPORTINFO_REC_FIELD(trap_lid),
+	  .offset_words = 15,
+	  .offset_bits  = 0,
+	  .size_bits    = 16 },
+	{ CLASSPORTINFO_REC_FIELD(trap_pkey),
+	  .offset_words = 15,
+	  .offset_bits  = 16,
+	  .size_bits    = 16 },
+
+	{ CLASSPORTINFO_REC_FIELD(trap_hlqp),
+	  .offset_words = 16,
+	  .offset_bits  = 0,
+	  .size_bits    = 32 },
+	{ CLASSPORTINFO_REC_FIELD(trap_qkey),
+	  .offset_words = 17,
+	  .offset_bits  = 0,
+	  .size_bits    = 32 },
+};
+
 #define GUIDINFO_REC_FIELD(field) \
 	.struct_offset_bytes = offsetof(struct ib_sa_guidinfo_rec, field),	\
 	.struct_size_bytes   = sizeof((struct ib_sa_guidinfo_rec *) 0)->field,	\
@@ -536,7 +614,7 @@ static int ib_nl_send_msg(struct ib_sa_q
 	data = ibnl_put_msg(skb, &nlh, query->seq, 0, RDMA_NL_LS,
 			    RDMA_NL_LS_OP_RESOLVE, NLM_F_REQUEST);
 	if (!data) {
-		kfree_skb(skb);
+		nlmsg_free(skb);
 		return -EMSGSIZE;
 	}
 
@@ -705,8 +783,8 @@ static void ib_nl_request_timeout(struct
 	spin_unlock_irqrestore(&ib_nl_request_lock, flags);
 }
 
-static int ib_nl_handle_set_timeout(struct sk_buff *skb,
-				    struct netlink_callback *cb)
+int ib_nl_handle_set_timeout(struct sk_buff *skb,
+			     struct netlink_callback *cb)
 {
 	const struct nlmsghdr *nlh = (struct nlmsghdr *)cb->nlh;
 	int timeout, delta, abs_delta;
@@ -782,8 +860,8 @@ static inline int ib_nl_is_good_resolve_
 	return 1;
 }
 
-static int ib_nl_handle_resolve_resp(struct sk_buff *skb,
-				     struct netlink_callback *cb)
+int ib_nl_handle_resolve_resp(struct sk_buff *skb,
+			      struct netlink_callback *cb)
 {
 	const struct nlmsghdr *nlh = (struct nlmsghdr *)cb->nlh;
 	unsigned long flags;
@@ -838,15 +916,6 @@ resp_out:
 	return skb->len;
 }
 
-static struct ibnl_client_cbs ib_sa_cb_table[] = {
-	[RDMA_NL_LS_OP_RESOLVE] = {
-		.dump = ib_nl_handle_resolve_resp,
-		.module = THIS_MODULE },
-	[RDMA_NL_LS_OP_SET_TIMEOUT] = {
-		.dump = ib_nl_handle_set_timeout,
-		.module = THIS_MODULE },
-};
-
 static void free_sm_ah(struct kref *kref)
 {
 	struct ib_sa_sm_ah *sm_ah = container_of(kref, struct ib_sa_sm_ah, ref);
@@ -1645,6 +1714,97 @@ err1:
 }
 EXPORT_SYMBOL(ib_sa_guid_info_rec_query);
 
+/* Support get SA ClassPortInfo */
+static void ib_sa_classport_info_rec_callback(struct ib_sa_query *sa_query,
+					      int status,
+					      struct ib_sa_mad *mad)
+{
+	struct ib_sa_classport_info_query *query =
+		container_of(sa_query, struct ib_sa_classport_info_query, sa_query);
+
+	if (mad) {
+		struct ib_class_port_info rec;
+
+		ib_unpack(classport_info_rec_table,
+			  ARRAY_SIZE(classport_info_rec_table),
+			  mad->data, &rec);
+		query->callback(status, &rec, query->context);
+	} else {
+		query->callback(status, NULL, query->context);
+	}
+}
+
+static void ib_sa_portclass_info_rec_release(struct ib_sa_query *sa_query)
+{
+	kfree(container_of(sa_query, struct ib_sa_classport_info_query,
+			   sa_query));
+}
+
+int ib_sa_classport_info_rec_query(struct ib_sa_client *client,
+				   struct ib_device *device, u8 port_num,
+				   int timeout_ms, gfp_t gfp_mask,
+				   void (*callback)(int status,
+						    struct ib_class_port_info *resp,
+						    void *context),
+				   void *context,
+				   struct ib_sa_query **sa_query)
+{
+	struct ib_sa_classport_info_query *query;
+	struct ib_sa_device *sa_dev = ib_get_client_data(device, &sa_client);
+	struct ib_sa_port *port;
+	struct ib_mad_agent *agent;
+	struct ib_sa_mad *mad;
+	int ret;
+
+	if (!sa_dev)
+		return -ENODEV;
+
+	port  = &sa_dev->port[port_num - sa_dev->start_port];
+	agent = port->agent;
+
+	query = kzalloc(sizeof(*query), gfp_mask);
+	if (!query)
+		return -ENOMEM;
+
+	query->sa_query.port = port;
+	ret = alloc_mad(&query->sa_query, gfp_mask);
+	if (ret)
+		goto err1;
+
+	ib_sa_client_get(client);
+	query->sa_query.client = client;
+	query->callback        = callback;
+	query->context         = context;
+
+	mad = query->sa_query.mad_buf->mad;
+	init_mad(mad, agent);
+
+	query->sa_query.callback = callback ? ib_sa_classport_info_rec_callback : NULL;
+
+	query->sa_query.release  = ib_sa_portclass_info_rec_release;
+	/* support GET only */
+	mad->mad_hdr.method	 = IB_MGMT_METHOD_GET;
+	mad->mad_hdr.attr_id	 = cpu_to_be16(IB_SA_ATTR_CLASS_PORTINFO);
+	mad->sa_hdr.comp_mask	 = 0;
+	*sa_query = &query->sa_query;
+
+	ret = send_mad(&query->sa_query, timeout_ms, gfp_mask);
+	if (ret < 0)
+		goto err2;
+
+	return ret;
+
+err2:
+	*sa_query = NULL;
+	ib_sa_client_put(query->sa_query.client);
+	free_mad(&query->sa_query);
+
+err1:
+	kfree(query);
+	return ret;
+}
+EXPORT_SYMBOL(ib_sa_classport_info_rec_query);
+
 static void send_handler(struct ib_mad_agent *agent,
 			 struct ib_mad_send_wc *mad_send_wc)
 {
@@ -1794,7 +1954,7 @@ static void ib_sa_remove_one(struct ib_d
 	kfree(sa_dev);
 }
 
-static int __init ib_sa_init(void)
+int ib_sa_init(void)
 {
 	int ret;
 
@@ -1820,17 +1980,10 @@ static int __init ib_sa_init(void)
 		goto err3;
 	}
 
-	if (ibnl_add_client(RDMA_NL_LS, RDMA_NL_LS_NUM_OPS,
-			    ib_sa_cb_table)) {
-		pr_err("Failed to add netlink callback\n");
-		ret = -EINVAL;
-		goto err4;
-	}
 	INIT_DELAYED_WORK(&ib_nl_timed_work, ib_nl_request_timeout);
 
 	return 0;
-err4:
-	destroy_workqueue(ib_nl_wq);
+
 err3:
 	mcast_cleanup();
 err2:
@@ -1839,9 +1992,8 @@ err1:
 	return ret;
 }
 
-static void __exit ib_sa_cleanup(void)
+void ib_sa_cleanup(void)
 {
-	ibnl_remove_client(RDMA_NL_LS);
 	cancel_delayed_work(&ib_nl_timed_work);
 	flush_workqueue(ib_nl_wq);
 	destroy_workqueue(ib_nl_wq);
@@ -1849,6 +2001,3 @@ static void __exit ib_sa_cleanup(void)
 	ib_unregister_client(&sa_client);
 	idr_destroy(&query_idr);
 }
-
-module_init(ib_sa_init);
-module_exit(ib_sa_cleanup);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/infiniband/core/sysfs.c linux-libre-4.7-gnu/drivers/infiniband/core/sysfs.c
--- linux-libre-4.6-gnu/drivers/infiniband/core/sysfs.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/infiniband/core/sysfs.c	2016-07-24 15:23:50.000000000 -0400
@@ -56,8 +56,10 @@ struct ib_port {
 	struct gid_attr_group *gid_attr_group;
 	struct attribute_group gid_group;
 	struct attribute_group pkey_group;
-	u8                     port_num;
 	struct attribute_group *pma_table;
+	struct attribute_group *hw_stats_ag;
+	struct rdma_hw_stats   *hw_stats;
+	u8                     port_num;
 };
 
 struct port_attribute {
@@ -80,6 +82,18 @@ struct port_table_attribute {
 	__be16			attr_id;
 };
 
+struct hw_stats_attribute {
+	struct attribute	attr;
+	ssize_t			(*show)(struct kobject *kobj,
+					struct attribute *attr, char *buf);
+	ssize_t			(*store)(struct kobject *kobj,
+					 struct attribute *attr,
+					 const char *buf,
+					 size_t count);
+	int			index;
+	u8			port_num;
+};
+
 static ssize_t port_attr_show(struct kobject *kobj,
 			      struct attribute *attr, char *buf)
 {
@@ -516,6 +530,7 @@ static PORT_PMA_ATTR(port_xmit_data
 static PORT_PMA_ATTR(port_rcv_data		    , 13, 32, 224);
 static PORT_PMA_ATTR(port_xmit_packets		    , 14, 32, 256);
 static PORT_PMA_ATTR(port_rcv_packets		    , 15, 32, 288);
+static PORT_PMA_ATTR(port_xmit_wait		    ,  0, 32, 320);
 
 /*
  * Counters added by extended set
@@ -546,6 +561,7 @@ static struct attribute *pma_attrs[] = {
 	&port_pma_attr_port_rcv_data.attr.attr,
 	&port_pma_attr_port_xmit_packets.attr.attr,
 	&port_pma_attr_port_rcv_packets.attr.attr,
+	&port_pma_attr_port_xmit_wait.attr.attr,
 	NULL
 };
 
@@ -565,6 +581,7 @@ static struct attribute *pma_attrs_ext[]
 	&port_pma_attr_ext_port_xmit_data.attr.attr,
 	&port_pma_attr_ext_port_rcv_data.attr.attr,
 	&port_pma_attr_ext_port_xmit_packets.attr.attr,
+	&port_pma_attr_port_xmit_wait.attr.attr,
 	&port_pma_attr_ext_port_rcv_packets.attr.attr,
 	&port_pma_attr_ext_unicast_rcv_packets.attr.attr,
 	&port_pma_attr_ext_unicast_xmit_packets.attr.attr,
@@ -590,6 +607,7 @@ static struct attribute *pma_attrs_noiet
 	&port_pma_attr_ext_port_rcv_data.attr.attr,
 	&port_pma_attr_ext_port_xmit_packets.attr.attr,
 	&port_pma_attr_ext_port_rcv_packets.attr.attr,
+	&port_pma_attr_port_xmit_wait.attr.attr,
 	NULL
 };
 
@@ -733,6 +751,220 @@ static struct attribute_group *get_count
 	return &pma_group;
 }
 
+static int update_hw_stats(struct ib_device *dev, struct rdma_hw_stats *stats,
+			   u8 port_num, int index)
+{
+	int ret;
+
+	if (time_is_after_eq_jiffies(stats->timestamp + stats->lifespan))
+		return 0;
+	ret = dev->get_hw_stats(dev, stats, port_num, index);
+	if (ret < 0)
+		return ret;
+	if (ret == stats->num_counters)
+		stats->timestamp = jiffies;
+
+	return 0;
+}
+
+static ssize_t print_hw_stat(struct rdma_hw_stats *stats, int index, char *buf)
+{
+	return sprintf(buf, "%llu\n", stats->value[index]);
+}
+
+static ssize_t show_hw_stats(struct kobject *kobj, struct attribute *attr,
+			     char *buf)
+{
+	struct ib_device *dev;
+	struct ib_port *port;
+	struct hw_stats_attribute *hsa;
+	struct rdma_hw_stats *stats;
+	int ret;
+
+	hsa = container_of(attr, struct hw_stats_attribute, attr);
+	if (!hsa->port_num) {
+		dev = container_of((struct device *)kobj,
+				   struct ib_device, dev);
+		stats = dev->hw_stats;
+	} else {
+		port = container_of(kobj, struct ib_port, kobj);
+		dev = port->ibdev;
+		stats = port->hw_stats;
+	}
+	ret = update_hw_stats(dev, stats, hsa->port_num, hsa->index);
+	if (ret)
+		return ret;
+	return print_hw_stat(stats, hsa->index, buf);
+}
+
+static ssize_t show_stats_lifespan(struct kobject *kobj,
+				   struct attribute *attr,
+				   char *buf)
+{
+	struct hw_stats_attribute *hsa;
+	int msecs;
+
+	hsa = container_of(attr, struct hw_stats_attribute, attr);
+	if (!hsa->port_num) {
+		struct ib_device *dev = container_of((struct device *)kobj,
+						     struct ib_device, dev);
+		msecs = jiffies_to_msecs(dev->hw_stats->lifespan);
+	} else {
+		struct ib_port *p = container_of(kobj, struct ib_port, kobj);
+		msecs = jiffies_to_msecs(p->hw_stats->lifespan);
+	}
+	return sprintf(buf, "%d\n", msecs);
+}
+
+static ssize_t set_stats_lifespan(struct kobject *kobj,
+				  struct attribute *attr,
+				  const char *buf, size_t count)
+{
+	struct hw_stats_attribute *hsa;
+	int msecs;
+	int jiffies;
+	int ret;
+
+	ret = kstrtoint(buf, 10, &msecs);
+	if (ret)
+		return ret;
+	if (msecs < 0 || msecs > 10000)
+		return -EINVAL;
+	jiffies = msecs_to_jiffies(msecs);
+	hsa = container_of(attr, struct hw_stats_attribute, attr);
+	if (!hsa->port_num) {
+		struct ib_device *dev = container_of((struct device *)kobj,
+						     struct ib_device, dev);
+		dev->hw_stats->lifespan = jiffies;
+	} else {
+		struct ib_port *p = container_of(kobj, struct ib_port, kobj);
+		p->hw_stats->lifespan = jiffies;
+	}
+	return count;
+}
+
+static void free_hsag(struct kobject *kobj, struct attribute_group *attr_group)
+{
+	struct attribute **attr;
+
+	sysfs_remove_group(kobj, attr_group);
+
+	for (attr = attr_group->attrs; *attr; attr++)
+		kfree(*attr);
+	kfree(attr_group);
+}
+
+static struct attribute *alloc_hsa(int index, u8 port_num, const char *name)
+{
+	struct hw_stats_attribute *hsa;
+
+	hsa = kmalloc(sizeof(*hsa), GFP_KERNEL);
+	if (!hsa)
+		return NULL;
+
+	hsa->attr.name = (char *)name;
+	hsa->attr.mode = S_IRUGO;
+	hsa->show = show_hw_stats;
+	hsa->store = NULL;
+	hsa->index = index;
+	hsa->port_num = port_num;
+
+	return &hsa->attr;
+}
+
+static struct attribute *alloc_hsa_lifespan(char *name, u8 port_num)
+{
+	struct hw_stats_attribute *hsa;
+
+	hsa = kmalloc(sizeof(*hsa), GFP_KERNEL);
+	if (!hsa)
+		return NULL;
+
+	hsa->attr.name = name;
+	hsa->attr.mode = S_IWUSR | S_IRUGO;
+	hsa->show = show_stats_lifespan;
+	hsa->store = set_stats_lifespan;
+	hsa->index = 0;
+	hsa->port_num = port_num;
+
+	return &hsa->attr;
+}
+
+static void setup_hw_stats(struct ib_device *device, struct ib_port *port,
+			   u8 port_num)
+{
+	struct attribute_group *hsag;
+	struct rdma_hw_stats *stats;
+	int i, ret;
+
+	stats = device->alloc_hw_stats(device, port_num);
+
+	if (!stats)
+		return;
+
+	if (!stats->names || stats->num_counters <= 0)
+		goto err_free_stats;
+
+	/*
+	 * Two extra attribue elements here, one for the lifespan entry and
+	 * one to NULL terminate the list for the sysfs core code
+	 */
+	hsag = kzalloc(sizeof(*hsag) +
+		       sizeof(void *) * (stats->num_counters + 2),
+		       GFP_KERNEL);
+	if (!hsag)
+		goto err_free_stats;
+
+	ret = device->get_hw_stats(device, stats, port_num,
+				   stats->num_counters);
+	if (ret != stats->num_counters)
+		goto err_free_hsag;
+
+	stats->timestamp = jiffies;
+
+	hsag->name = "hw_counters";
+	hsag->attrs = (void *)hsag + sizeof(*hsag);
+
+	for (i = 0; i < stats->num_counters; i++) {
+		hsag->attrs[i] = alloc_hsa(i, port_num, stats->names[i]);
+		if (!hsag->attrs[i])
+			goto err;
+		sysfs_attr_init(hsag->attrs[i]);
+	}
+
+	/* treat an error here as non-fatal */
+	hsag->attrs[i] = alloc_hsa_lifespan("lifespan", port_num);
+	if (hsag->attrs[i])
+		sysfs_attr_init(hsag->attrs[i]);
+
+	if (port) {
+		struct kobject *kobj = &port->kobj;
+		ret = sysfs_create_group(kobj, hsag);
+		if (ret)
+			goto err;
+		port->hw_stats_ag = hsag;
+		port->hw_stats = stats;
+	} else {
+		struct kobject *kobj = &device->dev.kobj;
+		ret = sysfs_create_group(kobj, hsag);
+		if (ret)
+			goto err;
+		device->hw_stats_ag = hsag;
+		device->hw_stats = stats;
+	}
+
+	return;
+
+err:
+	for (; i >= 0; i--)
+		kfree(hsag->attrs[i]);
+err_free_hsag:
+	kfree(hsag);
+err_free_stats:
+	kfree(stats);
+	return;
+}
+
 static int add_port(struct ib_device *device, int port_num,
 		    int (*port_callback)(struct ib_device *,
 					 u8, struct kobject *))
@@ -835,6 +1067,14 @@ static int add_port(struct ib_device *de
 			goto err_remove_pkey;
 	}
 
+	/*
+	 * If port == 0, it means we have only one port and the parent
+	 * device, not this port device, should be the holder of the
+	 * hw_counters
+	 */
+	if (device->alloc_hw_stats && port_num)
+		setup_hw_stats(device, p, port_num);
+
 	list_add_tail(&p->kobj.entry, &device->port_list);
 
 	kobject_uevent(&p->kobj, KOBJ_ADD);
@@ -972,120 +1212,6 @@ static struct device_attribute *ib_class
 	&dev_attr_node_desc
 };
 
-/* Show a given an attribute in the statistics group */
-static ssize_t show_protocol_stat(const struct device *device,
-			    struct device_attribute *attr, char *buf,
-			    unsigned offset)
-{
-	struct ib_device *dev = container_of(device, struct ib_device, dev);
-	union rdma_protocol_stats stats;
-	ssize_t ret;
-
-	ret = dev->get_protocol_stats(dev, &stats);
-	if (ret)
-		return ret;
-
-	return sprintf(buf, "%llu\n",
-		       (unsigned long long) ((u64 *) &stats)[offset]);
-}
-
-/* generate a read-only iwarp statistics attribute */
-#define IW_STATS_ENTRY(name)						\
-static ssize_t show_##name(struct device *device,			\
-			   struct device_attribute *attr, char *buf)	\
-{									\
-	return show_protocol_stat(device, attr, buf,			\
-				  offsetof(struct iw_protocol_stats, name) / \
-				  sizeof (u64));			\
-}									\
-static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
-
-IW_STATS_ENTRY(ipInReceives);
-IW_STATS_ENTRY(ipInHdrErrors);
-IW_STATS_ENTRY(ipInTooBigErrors);
-IW_STATS_ENTRY(ipInNoRoutes);
-IW_STATS_ENTRY(ipInAddrErrors);
-IW_STATS_ENTRY(ipInUnknownProtos);
-IW_STATS_ENTRY(ipInTruncatedPkts);
-IW_STATS_ENTRY(ipInDiscards);
-IW_STATS_ENTRY(ipInDelivers);
-IW_STATS_ENTRY(ipOutForwDatagrams);
-IW_STATS_ENTRY(ipOutRequests);
-IW_STATS_ENTRY(ipOutDiscards);
-IW_STATS_ENTRY(ipOutNoRoutes);
-IW_STATS_ENTRY(ipReasmTimeout);
-IW_STATS_ENTRY(ipReasmReqds);
-IW_STATS_ENTRY(ipReasmOKs);
-IW_STATS_ENTRY(ipReasmFails);
-IW_STATS_ENTRY(ipFragOKs);
-IW_STATS_ENTRY(ipFragFails);
-IW_STATS_ENTRY(ipFragCreates);
-IW_STATS_ENTRY(ipInMcastPkts);
-IW_STATS_ENTRY(ipOutMcastPkts);
-IW_STATS_ENTRY(ipInBcastPkts);
-IW_STATS_ENTRY(ipOutBcastPkts);
-IW_STATS_ENTRY(tcpRtoAlgorithm);
-IW_STATS_ENTRY(tcpRtoMin);
-IW_STATS_ENTRY(tcpRtoMax);
-IW_STATS_ENTRY(tcpMaxConn);
-IW_STATS_ENTRY(tcpActiveOpens);
-IW_STATS_ENTRY(tcpPassiveOpens);
-IW_STATS_ENTRY(tcpAttemptFails);
-IW_STATS_ENTRY(tcpEstabResets);
-IW_STATS_ENTRY(tcpCurrEstab);
-IW_STATS_ENTRY(tcpInSegs);
-IW_STATS_ENTRY(tcpOutSegs);
-IW_STATS_ENTRY(tcpRetransSegs);
-IW_STATS_ENTRY(tcpInErrs);
-IW_STATS_ENTRY(tcpOutRsts);
-
-static struct attribute *iw_proto_stats_attrs[] = {
-	&dev_attr_ipInReceives.attr,
-	&dev_attr_ipInHdrErrors.attr,
-	&dev_attr_ipInTooBigErrors.attr,
-	&dev_attr_ipInNoRoutes.attr,
-	&dev_attr_ipInAddrErrors.attr,
-	&dev_attr_ipInUnknownProtos.attr,
-	&dev_attr_ipInTruncatedPkts.attr,
-	&dev_attr_ipInDiscards.attr,
-	&dev_attr_ipInDelivers.attr,
-	&dev_attr_ipOutForwDatagrams.attr,
-	&dev_attr_ipOutRequests.attr,
-	&dev_attr_ipOutDiscards.attr,
-	&dev_attr_ipOutNoRoutes.attr,
-	&dev_attr_ipReasmTimeout.attr,
-	&dev_attr_ipReasmReqds.attr,
-	&dev_attr_ipReasmOKs.attr,
-	&dev_attr_ipReasmFails.attr,
-	&dev_attr_ipFragOKs.attr,
-	&dev_attr_ipFragFails.attr,
-	&dev_attr_ipFragCreates.attr,
-	&dev_attr_ipInMcastPkts.attr,
-	&dev_attr_ipOutMcastPkts.attr,
-	&dev_attr_ipInBcastPkts.attr,
-	&dev_attr_ipOutBcastPkts.attr,
-	&dev_attr_tcpRtoAlgorithm.attr,
-	&dev_attr_tcpRtoMin.attr,
-	&dev_attr_tcpRtoMax.attr,
-	&dev_attr_tcpMaxConn.attr,
-	&dev_attr_tcpActiveOpens.attr,
-	&dev_attr_tcpPassiveOpens.attr,
-	&dev_attr_tcpAttemptFails.attr,
-	&dev_attr_tcpEstabResets.attr,
-	&dev_attr_tcpCurrEstab.attr,
-	&dev_attr_tcpInSegs.attr,
-	&dev_attr_tcpOutSegs.attr,
-	&dev_attr_tcpRetransSegs.attr,
-	&dev_attr_tcpInErrs.attr,
-	&dev_attr_tcpOutRsts.attr,
-	NULL
-};
-
-static struct attribute_group iw_stats_group = {
-	.name	= "proto_stats",
-	.attrs	= iw_proto_stats_attrs,
-};
-
 static void free_port_list_attributes(struct ib_device *device)
 {
 	struct kobject *p, *t;
@@ -1093,6 +1219,10 @@ static void free_port_list_attributes(st
 	list_for_each_entry_safe(p, t, &device->port_list, entry) {
 		struct ib_port *port = container_of(p, struct ib_port, kobj);
 		list_del(&p->entry);
+		if (port->hw_stats) {
+			kfree(port->hw_stats);
+			free_hsag(&port->kobj, port->hw_stats_ag);
+		}
 		sysfs_remove_group(p, port->pma_table);
 		sysfs_remove_group(p, &port->pkey_group);
 		sysfs_remove_group(p, &port->gid_group);
@@ -1149,11 +1279,8 @@ int ib_device_register_sysfs(struct ib_d
 		}
 	}
 
-	if (device->node_type == RDMA_NODE_RNIC && device->get_protocol_stats) {
-		ret = sysfs_create_group(&class_dev->kobj, &iw_stats_group);
-		if (ret)
-			goto err_put;
-	}
+	if (device->alloc_hw_stats)
+		setup_hw_stats(device, NULL, 0);
 
 	return 0;
 
@@ -1169,15 +1296,18 @@ err:
 
 void ib_device_unregister_sysfs(struct ib_device *device)
 {
-	/* Hold kobject until ib_dealloc_device() */
-	struct kobject *kobj_dev = kobject_get(&device->dev.kobj);
 	int i;
 
-	if (device->node_type == RDMA_NODE_RNIC && device->get_protocol_stats)
-		sysfs_remove_group(kobj_dev, &iw_stats_group);
+	/* Hold kobject until ib_dealloc_device() */
+	kobject_get(&device->dev.kobj);
 
 	free_port_list_attributes(device);
 
+	if (device->hw_stats) {
+		kfree(device->hw_stats);
+		free_hsag(&device->dev.kobj, device->hw_stats_ag);
+	}
+
 	for (i = 0; i < ARRAY_SIZE(ib_class_attributes); ++i)
 		device_remove_file(&device->dev, ib_class_attributes[i]);
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/infiniband/core/uverbs_cmd.c linux-libre-4.7-gnu/drivers/infiniband/core/uverbs_cmd.c
--- linux-libre-4.6-gnu/drivers/infiniband/core/uverbs_cmd.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/infiniband/core/uverbs_cmd.c	2016-07-24 15:23:50.000000000 -0400
@@ -1747,7 +1747,7 @@ static int create_qp(struct ib_uverbs_fi
 	struct ib_srq			*srq = NULL;
 	struct ib_qp			*qp;
 	char				*buf;
-	struct ib_qp_init_attr		attr;
+	struct ib_qp_init_attr		attr = {};
 	struct ib_uverbs_ex_create_qp_resp resp;
 	int				ret;
 
@@ -1833,7 +1833,8 @@ static int create_qp(struct ib_uverbs_fi
 	if (attr.create_flags & ~(IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK |
 				IB_QP_CREATE_CROSS_CHANNEL |
 				IB_QP_CREATE_MANAGED_SEND |
-				IB_QP_CREATE_MANAGED_RECV)) {
+				IB_QP_CREATE_MANAGED_RECV |
+				IB_QP_CREATE_SCATTER_FCS)) {
 		ret = -EINVAL;
 		goto err_put;
 	}
@@ -3088,8 +3089,7 @@ int ib_uverbs_ex_create_flow(struct ib_u
 	if (cmd.comp_mask)
 		return -EINVAL;
 
-	if ((cmd.flow_attr.type == IB_FLOW_ATTR_SNIFFER &&
-	     !capable(CAP_NET_ADMIN)) || !capable(CAP_NET_RAW))
+	if (!capable(CAP_NET_RAW))
 		return -EPERM;
 
 	if (cmd.flow_attr.flags >= IB_FLOW_ATTR_FLAGS_RESERVED)
@@ -3655,6 +3655,11 @@ int ib_uverbs_ex_query_device(struct ib_
 	resp.hca_core_clock = attr.hca_core_clock;
 	resp.response_length += sizeof(resp.hca_core_clock);
 
+	if (ucore->outlen < resp.response_length + sizeof(resp.device_cap_flags_ex))
+		goto end;
+
+	resp.device_cap_flags_ex = attr.device_cap_flags;
+	resp.response_length += sizeof(resp.device_cap_flags_ex);
 end:
 	err = ib_copy_to_udata(ucore, &resp, resp.response_length);
 	return err;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/infiniband/core/verbs.c linux-libre-4.7-gnu/drivers/infiniband/core/verbs.c
--- linux-libre-4.6-gnu/drivers/infiniband/core/verbs.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/infiniband/core/verbs.c	2016-07-24 15:23:50.000000000 -0400
@@ -48,6 +48,7 @@
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_cache.h>
 #include <rdma/ib_addr.h>
+#include <rdma/rw.h>
 
 #include "core_priv.h"
 
@@ -510,12 +511,16 @@ int ib_init_ah_from_wc(struct ib_device
 		ah_attr->grh.dgid = sgid;
 
 		if (!rdma_cap_eth_ah(device, port_num)) {
-			ret = ib_find_cached_gid_by_port(device, &dgid,
-							 IB_GID_TYPE_IB,
-							 port_num, NULL,
-							 &gid_index);
-			if (ret)
-				return ret;
+			if (dgid.global.interface_id != cpu_to_be64(IB_SA_WELL_KNOWN_GUID)) {
+				ret = ib_find_cached_gid_by_port(device, &dgid,
+								 IB_GID_TYPE_IB,
+								 port_num, NULL,
+								 &gid_index);
+				if (ret)
+					return ret;
+			} else {
+				gid_index = 0;
+			}
 		}
 
 		ah_attr->grh.sgid_index = (u8) gid_index;
@@ -723,59 +728,89 @@ struct ib_qp *ib_open_qp(struct ib_xrcd
 }
 EXPORT_SYMBOL(ib_open_qp);
 
+static struct ib_qp *ib_create_xrc_qp(struct ib_qp *qp,
+		struct ib_qp_init_attr *qp_init_attr)
+{
+	struct ib_qp *real_qp = qp;
+
+	qp->event_handler = __ib_shared_qp_event_handler;
+	qp->qp_context = qp;
+	qp->pd = NULL;
+	qp->send_cq = qp->recv_cq = NULL;
+	qp->srq = NULL;
+	qp->xrcd = qp_init_attr->xrcd;
+	atomic_inc(&qp_init_attr->xrcd->usecnt);
+	INIT_LIST_HEAD(&qp->open_list);
+
+	qp = __ib_open_qp(real_qp, qp_init_attr->event_handler,
+			  qp_init_attr->qp_context);
+	if (!IS_ERR(qp))
+		__ib_insert_xrcd_qp(qp_init_attr->xrcd, real_qp);
+	else
+		real_qp->device->destroy_qp(real_qp);
+	return qp;
+}
+
 struct ib_qp *ib_create_qp(struct ib_pd *pd,
 			   struct ib_qp_init_attr *qp_init_attr)
 {
-	struct ib_qp *qp, *real_qp;
-	struct ib_device *device;
+	struct ib_device *device = pd ? pd->device : qp_init_attr->xrcd->device;
+	struct ib_qp *qp;
+	int ret;
+
+	/*
+	 * If the callers is using the RDMA API calculate the resources
+	 * needed for the RDMA READ/WRITE operations.
+	 *
+	 * Note that these callers need to pass in a port number.
+	 */
+	if (qp_init_attr->cap.max_rdma_ctxs)
+		rdma_rw_init_qp(device, qp_init_attr);
 
-	device = pd ? pd->device : qp_init_attr->xrcd->device;
 	qp = device->create_qp(pd, qp_init_attr, NULL);
+	if (IS_ERR(qp))
+		return qp;
 
-	if (!IS_ERR(qp)) {
-		qp->device     = device;
-		qp->real_qp    = qp;
-		qp->uobject    = NULL;
-		qp->qp_type    = qp_init_attr->qp_type;
+	qp->device     = device;
+	qp->real_qp    = qp;
+	qp->uobject    = NULL;
+	qp->qp_type    = qp_init_attr->qp_type;
 
-		atomic_set(&qp->usecnt, 0);
-		if (qp_init_attr->qp_type == IB_QPT_XRC_TGT) {
-			qp->event_handler = __ib_shared_qp_event_handler;
-			qp->qp_context = qp;
-			qp->pd = NULL;
-			qp->send_cq = qp->recv_cq = NULL;
-			qp->srq = NULL;
-			qp->xrcd = qp_init_attr->xrcd;
-			atomic_inc(&qp_init_attr->xrcd->usecnt);
-			INIT_LIST_HEAD(&qp->open_list);
+	atomic_set(&qp->usecnt, 0);
+	qp->mrs_used = 0;
+	spin_lock_init(&qp->mr_lock);
+	INIT_LIST_HEAD(&qp->rdma_mrs);
+	INIT_LIST_HEAD(&qp->sig_mrs);
 
-			real_qp = qp;
-			qp = __ib_open_qp(real_qp, qp_init_attr->event_handler,
-					  qp_init_attr->qp_context);
-			if (!IS_ERR(qp))
-				__ib_insert_xrcd_qp(qp_init_attr->xrcd, real_qp);
-			else
-				real_qp->device->destroy_qp(real_qp);
-		} else {
-			qp->event_handler = qp_init_attr->event_handler;
-			qp->qp_context = qp_init_attr->qp_context;
-			if (qp_init_attr->qp_type == IB_QPT_XRC_INI) {
-				qp->recv_cq = NULL;
-				qp->srq = NULL;
-			} else {
-				qp->recv_cq = qp_init_attr->recv_cq;
-				atomic_inc(&qp_init_attr->recv_cq->usecnt);
-				qp->srq = qp_init_attr->srq;
-				if (qp->srq)
-					atomic_inc(&qp_init_attr->srq->usecnt);
-			}
+	if (qp_init_attr->qp_type == IB_QPT_XRC_TGT)
+		return ib_create_xrc_qp(qp, qp_init_attr);
 
-			qp->pd	    = pd;
-			qp->send_cq = qp_init_attr->send_cq;
-			qp->xrcd    = NULL;
+	qp->event_handler = qp_init_attr->event_handler;
+	qp->qp_context = qp_init_attr->qp_context;
+	if (qp_init_attr->qp_type == IB_QPT_XRC_INI) {
+		qp->recv_cq = NULL;
+		qp->srq = NULL;
+	} else {
+		qp->recv_cq = qp_init_attr->recv_cq;
+		atomic_inc(&qp_init_attr->recv_cq->usecnt);
+		qp->srq = qp_init_attr->srq;
+		if (qp->srq)
+			atomic_inc(&qp_init_attr->srq->usecnt);
+	}
 
-			atomic_inc(&pd->usecnt);
-			atomic_inc(&qp_init_attr->send_cq->usecnt);
+	qp->pd	    = pd;
+	qp->send_cq = qp_init_attr->send_cq;
+	qp->xrcd    = NULL;
+
+	atomic_inc(&pd->usecnt);
+	atomic_inc(&qp_init_attr->send_cq->usecnt);
+
+	if (qp_init_attr->cap.max_rdma_ctxs) {
+		ret = rdma_rw_init_mrs(qp, qp_init_attr);
+		if (ret) {
+			pr_err("failed to init MR pool ret= %d\n", ret);
+			ib_destroy_qp(qp);
+			qp = ERR_PTR(ret);
 		}
 	}
 
@@ -1250,6 +1285,8 @@ int ib_destroy_qp(struct ib_qp *qp)
 	struct ib_srq *srq;
 	int ret;
 
+	WARN_ON_ONCE(qp->mrs_used > 0);
+
 	if (atomic_read(&qp->usecnt))
 		return -EBUSY;
 
@@ -1261,6 +1298,9 @@ int ib_destroy_qp(struct ib_qp *qp)
 	rcq  = qp->recv_cq;
 	srq  = qp->srq;
 
+	if (!qp->uobject)
+		rdma_rw_cleanup_mrs(qp);
+
 	ret = qp->device->destroy_qp(qp);
 	if (!ret) {
 		if (pd)
@@ -1343,6 +1383,7 @@ struct ib_mr *ib_get_dma_mr(struct ib_pd
 		mr->pd      = pd;
 		mr->uobject = NULL;
 		atomic_inc(&pd->usecnt);
+		mr->need_inval = false;
 	}
 
 	return mr;
@@ -1389,6 +1430,7 @@ struct ib_mr *ib_alloc_mr(struct ib_pd *
 		mr->pd      = pd;
 		mr->uobject = NULL;
 		atomic_inc(&pd->usecnt);
+		mr->need_inval = false;
 	}
 
 	return mr;
@@ -1597,6 +1639,7 @@ EXPORT_SYMBOL(ib_set_vf_guid);
  * @mr:            memory region
  * @sg:            dma mapped scatterlist
  * @sg_nents:      number of entries in sg
+ * @sg_offset:     offset in bytes into sg
  * @page_size:     page vector desired page size
  *
  * Constraints:
@@ -1615,17 +1658,15 @@ EXPORT_SYMBOL(ib_set_vf_guid);
  * After this completes successfully, the  memory region
  * is ready for registration.
  */
-int ib_map_mr_sg(struct ib_mr *mr,
-		 struct scatterlist *sg,
-		 int sg_nents,
-		 unsigned int page_size)
+int ib_map_mr_sg(struct ib_mr *mr, struct scatterlist *sg, int sg_nents,
+		 unsigned int *sg_offset, unsigned int page_size)
 {
 	if (unlikely(!mr->device->map_mr_sg))
 		return -ENOSYS;
 
 	mr->page_size = page_size;
 
-	return mr->device->map_mr_sg(mr, sg, sg_nents);
+	return mr->device->map_mr_sg(mr, sg, sg_nents, sg_offset);
 }
 EXPORT_SYMBOL(ib_map_mr_sg);
 
@@ -1635,6 +1676,10 @@ EXPORT_SYMBOL(ib_map_mr_sg);
  * @mr:            memory region
  * @sgl:           dma mapped scatterlist
  * @sg_nents:      number of entries in sg
+ * @sg_offset_p:   IN:  start offset in bytes into sg
+ *                 OUT: offset in bytes for element n of the sg of the first
+ *                      byte that has not been processed where n is the return
+ *                      value of this function.
  * @set_page:      driver page assignment function pointer
  *
  * Core service helper for drivers to convert the largest
@@ -1645,23 +1690,26 @@ EXPORT_SYMBOL(ib_map_mr_sg);
  * Returns the number of sg elements that were assigned to
  * a page vector.
  */
-int ib_sg_to_pages(struct ib_mr *mr,
-		   struct scatterlist *sgl,
-		   int sg_nents,
-		   int (*set_page)(struct ib_mr *, u64))
+int ib_sg_to_pages(struct ib_mr *mr, struct scatterlist *sgl, int sg_nents,
+		unsigned int *sg_offset_p, int (*set_page)(struct ib_mr *, u64))
 {
 	struct scatterlist *sg;
 	u64 last_end_dma_addr = 0;
+	unsigned int sg_offset = sg_offset_p ? *sg_offset_p : 0;
 	unsigned int last_page_off = 0;
 	u64 page_mask = ~((u64)mr->page_size - 1);
 	int i, ret;
 
-	mr->iova = sg_dma_address(&sgl[0]);
+	if (unlikely(sg_nents <= 0 || sg_offset > sg_dma_len(&sgl[0])))
+		return -EINVAL;
+
+	mr->iova = sg_dma_address(&sgl[0]) + sg_offset;
 	mr->length = 0;
 
 	for_each_sg(sgl, sg, sg_nents, i) {
-		u64 dma_addr = sg_dma_address(sg);
-		unsigned int dma_len = sg_dma_len(sg);
+		u64 dma_addr = sg_dma_address(sg) + sg_offset;
+		u64 prev_addr = dma_addr;
+		unsigned int dma_len = sg_dma_len(sg) - sg_offset;
 		u64 end_dma_addr = dma_addr + dma_len;
 		u64 page_addr = dma_addr & page_mask;
 
@@ -1685,8 +1733,14 @@ int ib_sg_to_pages(struct ib_mr *mr,
 
 		do {
 			ret = set_page(mr, page_addr);
-			if (unlikely(ret < 0))
-				return i ? : ret;
+			if (unlikely(ret < 0)) {
+				sg_offset = prev_addr - sg_dma_address(sg);
+				mr->length += prev_addr - dma_addr;
+				if (sg_offset_p)
+					*sg_offset_p = sg_offset;
+				return i || sg_offset ? i : ret;
+			}
+			prev_addr = page_addr;
 next_page:
 			page_addr += mr->page_size;
 		} while (page_addr < end_dma_addr);
@@ -1694,8 +1748,12 @@ next_page:
 		mr->length += dma_len;
 		last_end_dma_addr = end_dma_addr;
 		last_page_off = end_dma_addr & ~page_mask;
+
+		sg_offset = 0;
 	}
 
+	if (sg_offset_p)
+		*sg_offset_p = 0;
 	return i;
 }
 EXPORT_SYMBOL(ib_sg_to_pages);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/infiniband/hw/cxgb3/cxio_hal.c linux-libre-4.7-gnu/drivers/infiniband/hw/cxgb3/cxio_hal.c
--- linux-libre-4.6-gnu/drivers/infiniband/hw/cxgb3/cxio_hal.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/infiniband/hw/cxgb3/cxio_hal.c	2016-07-24 15:23:50.000000000 -0400
@@ -327,7 +327,7 @@ int cxio_destroy_cq(struct cxio_rdev *rd
 	kfree(cq->sw_queue);
 	dma_free_coherent(&(rdev_p->rnic_info.pdev->dev),
 			  (1UL << (cq->size_log2))
-			  * sizeof(struct t3_cqe), cq->queue,
+			  * sizeof(struct t3_cqe) + 1, cq->queue,
 			  dma_unmap_addr(cq, mapping));
 	cxio_hal_put_cqid(rdev_p->rscp, cq->cqid);
 	return err;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/infiniband/hw/cxgb3/iwch_cm.c linux-libre-4.7-gnu/drivers/infiniband/hw/cxgb3/iwch_cm.c
--- linux-libre-4.6-gnu/drivers/infiniband/hw/cxgb3/iwch_cm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/infiniband/hw/cxgb3/iwch_cm.c	2016-07-24 15:23:50.000000000 -0400
@@ -367,7 +367,7 @@ static void arp_failure_discard(struct t
  */
 static void act_open_req_arp_failure(struct t3cdev *dev, struct sk_buff *skb)
 {
-	printk(KERN_ERR MOD "ARP failure duing connect\n");
+	printk(KERN_ERR MOD "ARP failure during connect\n");
 	kfree_skb(skb);
 }
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/infiniband/hw/cxgb3/iwch_provider.c linux-libre-4.7-gnu/drivers/infiniband/hw/cxgb3/iwch_provider.c
--- linux-libre-4.6-gnu/drivers/infiniband/hw/cxgb3/iwch_provider.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/infiniband/hw/cxgb3/iwch_provider.c	2016-07-24 15:23:50.000000000 -0400
@@ -783,15 +783,14 @@ static int iwch_set_page(struct ib_mr *i
 	return 0;
 }
 
-static int iwch_map_mr_sg(struct ib_mr *ibmr,
-			  struct scatterlist *sg,
-			  int sg_nents)
+static int iwch_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg,
+			  int sg_nents, unsigned int *sg_offset)
 {
 	struct iwch_mr *mhp = to_iwch_mr(ibmr);
 
 	mhp->npages = 0;
 
-	return ib_sg_to_pages(ibmr, sg, sg_nents, iwch_set_page);
+	return ib_sg_to_pages(ibmr, sg, sg_nents, sg_offset, iwch_set_page);
 }
 
 static int iwch_destroy_qp(struct ib_qp *ib_qp)
@@ -1219,59 +1218,119 @@ static ssize_t show_board(struct device
 		       iwch_dev->rdev.rnic_info.pdev->device);
 }
 
-static int iwch_get_mib(struct ib_device *ibdev,
-			union rdma_protocol_stats *stats)
+enum counters {
+	IPINRECEIVES,
+	IPINHDRERRORS,
+	IPINADDRERRORS,
+	IPINUNKNOWNPROTOS,
+	IPINDISCARDS,
+	IPINDELIVERS,
+	IPOUTREQUESTS,
+	IPOUTDISCARDS,
+	IPOUTNOROUTES,
+	IPREASMTIMEOUT,
+	IPREASMREQDS,
+	IPREASMOKS,
+	IPREASMFAILS,
+	TCPACTIVEOPENS,
+	TCPPASSIVEOPENS,
+	TCPATTEMPTFAILS,
+	TCPESTABRESETS,
+	TCPCURRESTAB,
+	TCPINSEGS,
+	TCPOUTSEGS,
+	TCPRETRANSSEGS,
+	TCPINERRS,
+	TCPOUTRSTS,
+	TCPRTOMIN,
+	TCPRTOMAX,
+	NR_COUNTERS
+};
+
+static const char * const names[] = {
+	[IPINRECEIVES] = "ipInReceives",
+	[IPINHDRERRORS] = "ipInHdrErrors",
+	[IPINADDRERRORS] = "ipInAddrErrors",
+	[IPINUNKNOWNPROTOS] = "ipInUnknownProtos",
+	[IPINDISCARDS] = "ipInDiscards",
+	[IPINDELIVERS] = "ipInDelivers",
+	[IPOUTREQUESTS] = "ipOutRequests",
+	[IPOUTDISCARDS] = "ipOutDiscards",
+	[IPOUTNOROUTES] = "ipOutNoRoutes",
+	[IPREASMTIMEOUT] = "ipReasmTimeout",
+	[IPREASMREQDS] = "ipReasmReqds",
+	[IPREASMOKS] = "ipReasmOKs",
+	[IPREASMFAILS] = "ipReasmFails",
+	[TCPACTIVEOPENS] = "tcpActiveOpens",
+	[TCPPASSIVEOPENS] = "tcpPassiveOpens",
+	[TCPATTEMPTFAILS] = "tcpAttemptFails",
+	[TCPESTABRESETS] = "tcpEstabResets",
+	[TCPCURRESTAB] = "tcpCurrEstab",
+	[TCPINSEGS] = "tcpInSegs",
+	[TCPOUTSEGS] = "tcpOutSegs",
+	[TCPRETRANSSEGS] = "tcpRetransSegs",
+	[TCPINERRS] = "tcpInErrs",
+	[TCPOUTRSTS] = "tcpOutRsts",
+	[TCPRTOMIN] = "tcpRtoMin",
+	[TCPRTOMAX] = "tcpRtoMax",
+};
+
+static struct rdma_hw_stats *iwch_alloc_stats(struct ib_device *ibdev,
+					      u8 port_num)
+{
+	BUILD_BUG_ON(ARRAY_SIZE(names) != NR_COUNTERS);
+
+	/* Our driver only supports device level stats */
+	if (port_num != 0)
+		return NULL;
+
+	return rdma_alloc_hw_stats_struct(names, NR_COUNTERS,
+					  RDMA_HW_STATS_DEFAULT_LIFESPAN);
+}
+
+static int iwch_get_mib(struct ib_device *ibdev, struct rdma_hw_stats *stats,
+			u8 port, int index)
 {
 	struct iwch_dev *dev;
 	struct tp_mib_stats m;
 	int ret;
 
+	if (port != 0 || !stats)
+		return -ENOSYS;
+
 	PDBG("%s ibdev %p\n", __func__, ibdev);
 	dev = to_iwch_dev(ibdev);
 	ret = dev->rdev.t3cdev_p->ctl(dev->rdev.t3cdev_p, RDMA_GET_MIB, &m);
 	if (ret)
 		return -ENOSYS;
 
-	memset(stats, 0, sizeof *stats);
-	stats->iw.ipInReceives = ((u64) m.ipInReceive_hi << 32) +
-				m.ipInReceive_lo;
-	stats->iw.ipInHdrErrors = ((u64) m.ipInHdrErrors_hi << 32) +
-				  m.ipInHdrErrors_lo;
-	stats->iw.ipInAddrErrors = ((u64) m.ipInAddrErrors_hi << 32) +
-				   m.ipInAddrErrors_lo;
-	stats->iw.ipInUnknownProtos = ((u64) m.ipInUnknownProtos_hi << 32) +
-				      m.ipInUnknownProtos_lo;
-	stats->iw.ipInDiscards = ((u64) m.ipInDiscards_hi << 32) +
-				 m.ipInDiscards_lo;
-	stats->iw.ipInDelivers = ((u64) m.ipInDelivers_hi << 32) +
-				 m.ipInDelivers_lo;
-	stats->iw.ipOutRequests = ((u64) m.ipOutRequests_hi << 32) +
-				  m.ipOutRequests_lo;
-	stats->iw.ipOutDiscards = ((u64) m.ipOutDiscards_hi << 32) +
-				  m.ipOutDiscards_lo;
-	stats->iw.ipOutNoRoutes = ((u64) m.ipOutNoRoutes_hi << 32) +
-				  m.ipOutNoRoutes_lo;
-	stats->iw.ipReasmTimeout = (u64) m.ipReasmTimeout;
-	stats->iw.ipReasmReqds = (u64) m.ipReasmReqds;
-	stats->iw.ipReasmOKs = (u64) m.ipReasmOKs;
-	stats->iw.ipReasmFails = (u64) m.ipReasmFails;
-	stats->iw.tcpActiveOpens = (u64) m.tcpActiveOpens;
-	stats->iw.tcpPassiveOpens = (u64) m.tcpPassiveOpens;
-	stats->iw.tcpAttemptFails = (u64) m.tcpAttemptFails;
-	stats->iw.tcpEstabResets = (u64) m.tcpEstabResets;
-	stats->iw.tcpOutRsts = (u64) m.tcpOutRsts;
-	stats->iw.tcpCurrEstab = (u64) m.tcpCurrEstab;
-	stats->iw.tcpInSegs = ((u64) m.tcpInSegs_hi << 32) +
-			      m.tcpInSegs_lo;
-	stats->iw.tcpOutSegs = ((u64) m.tcpOutSegs_hi << 32) +
-			       m.tcpOutSegs_lo;
-	stats->iw.tcpRetransSegs = ((u64) m.tcpRetransSeg_hi << 32) +
-				  m.tcpRetransSeg_lo;
-	stats->iw.tcpInErrs = ((u64) m.tcpInErrs_hi << 32) +
-			      m.tcpInErrs_lo;
-	stats->iw.tcpRtoMin = (u64) m.tcpRtoMin;
-	stats->iw.tcpRtoMax = (u64) m.tcpRtoMax;
-	return 0;
+	stats->value[IPINRECEIVES] = ((u64)m.ipInReceive_hi << 32) +	m.ipInReceive_lo;
+	stats->value[IPINHDRERRORS] = ((u64)m.ipInHdrErrors_hi << 32) + m.ipInHdrErrors_lo;
+	stats->value[IPINADDRERRORS] = ((u64)m.ipInAddrErrors_hi << 32) + m.ipInAddrErrors_lo;
+	stats->value[IPINUNKNOWNPROTOS] = ((u64)m.ipInUnknownProtos_hi << 32) + m.ipInUnknownProtos_lo;
+	stats->value[IPINDISCARDS] = ((u64)m.ipInDiscards_hi << 32) + m.ipInDiscards_lo;
+	stats->value[IPINDELIVERS] = ((u64)m.ipInDelivers_hi << 32) + m.ipInDelivers_lo;
+	stats->value[IPOUTREQUESTS] = ((u64)m.ipOutRequests_hi << 32) + m.ipOutRequests_lo;
+	stats->value[IPOUTDISCARDS] = ((u64)m.ipOutDiscards_hi << 32) + m.ipOutDiscards_lo;
+	stats->value[IPOUTNOROUTES] = ((u64)m.ipOutNoRoutes_hi << 32) + m.ipOutNoRoutes_lo;
+	stats->value[IPREASMTIMEOUT] = 	m.ipReasmTimeout;
+	stats->value[IPREASMREQDS] = m.ipReasmReqds;
+	stats->value[IPREASMOKS] = m.ipReasmOKs;
+	stats->value[IPREASMFAILS] = m.ipReasmFails;
+	stats->value[TCPACTIVEOPENS] =	m.tcpActiveOpens;
+	stats->value[TCPPASSIVEOPENS] =	m.tcpPassiveOpens;
+	stats->value[TCPATTEMPTFAILS] = m.tcpAttemptFails;
+	stats->value[TCPESTABRESETS] = m.tcpEstabResets;
+	stats->value[TCPCURRESTAB] = m.tcpOutRsts;
+	stats->value[TCPINSEGS] = m.tcpCurrEstab;
+	stats->value[TCPOUTSEGS] = ((u64)m.tcpInSegs_hi << 32) + m.tcpInSegs_lo;
+	stats->value[TCPRETRANSSEGS] = ((u64)m.tcpOutSegs_hi << 32) + m.tcpOutSegs_lo;
+	stats->value[TCPINERRS] = ((u64)m.tcpRetransSeg_hi << 32) + m.tcpRetransSeg_lo,
+	stats->value[TCPOUTRSTS] = ((u64)m.tcpInErrs_hi << 32) + m.tcpInErrs_lo;
+	stats->value[TCPRTOMIN] = m.tcpRtoMin;
+	stats->value[TCPRTOMAX] = m.tcpRtoMax;
+
+	return stats->num_counters;
 }
 
 static DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
@@ -1374,7 +1433,8 @@ int iwch_register_device(struct iwch_dev
 	dev->ibdev.req_notify_cq = iwch_arm_cq;
 	dev->ibdev.post_send = iwch_post_send;
 	dev->ibdev.post_recv = iwch_post_receive;
-	dev->ibdev.get_protocol_stats = iwch_get_mib;
+	dev->ibdev.alloc_hw_stats = iwch_alloc_stats;
+	dev->ibdev.get_hw_stats = iwch_get_mib;
 	dev->ibdev.uverbs_abi_ver = IWCH_UVERBS_ABI_VERSION;
 	dev->ibdev.get_port_immutable = iwch_port_immutable;
 
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/infiniband/hw/cxgb4/cm.c linux-libre-4.7-gnu/drivers/infiniband/hw/cxgb4/cm.c
--- linux-libre-4.6-gnu/drivers/infiniband/hw/cxgb4/cm.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/infiniband/hw/cxgb4/cm.c	2016-07-24 15:23:50.000000000 -0400
@@ -119,7 +119,7 @@ MODULE_PARM_DESC(ep_timeout_secs, "CM En
 static int mpa_rev = 2;
 module_param(mpa_rev, int, 0644);
 MODULE_PARM_DESC(mpa_rev, "MPA Revision, 0 supports amso1100, "
-		"1 is RFC0544 spec compliant, 2 is IETF MPA Peer Connect Draft"
+		"1 is RFC5044 spec compliant, 2 is IETF MPA Peer Connect Draft"
 		" compliant (default=2)");
 
 static int markers_enabled;
@@ -145,19 +145,35 @@ static struct sk_buff_head rxq;
 static struct sk_buff *get_skb(struct sk_buff *skb, int len, gfp_t gfp);
 static void ep_timeout(unsigned long arg);
 static void connect_reply_upcall(struct c4iw_ep *ep, int status);
+static int sched(struct c4iw_dev *dev, struct sk_buff *skb);
 
 static LIST_HEAD(timeout_list);
 static spinlock_t timeout_lock;
 
+static void deref_cm_id(struct c4iw_ep_common *epc)
+{
+	epc->cm_id->rem_ref(epc->cm_id);
+	epc->cm_id = NULL;
+	set_bit(CM_ID_DEREFED, &epc->history);
+}
+
+static void ref_cm_id(struct c4iw_ep_common *epc)
+{
+	set_bit(CM_ID_REFED, &epc->history);
+	epc->cm_id->add_ref(epc->cm_id);
+}
+
 static void deref_qp(struct c4iw_ep *ep)
 {
 	c4iw_qp_rem_ref(&ep->com.qp->ibqp);
 	clear_bit(QP_REFERENCED, &ep->com.flags);
+	set_bit(QP_DEREFED, &ep->com.history);
 }
 
 static void ref_qp(struct c4iw_ep *ep)
 {
 	set_bit(QP_REFERENCED, &ep->com.flags);
+	set_bit(QP_REFED, &ep->com.history);
 	c4iw_qp_add_ref(&ep->com.qp->ibqp);
 }
 
@@ -201,6 +217,8 @@ static int c4iw_l2t_send(struct c4iw_rde
 	error = cxgb4_l2t_send(rdev->lldi.ports[0], skb, l2e);
 	if (error < 0)
 		kfree_skb(skb);
+	else if (error == NET_XMIT_DROP)
+		return -ENOMEM;
 	return error < 0 ? error : 0;
 }
 
@@ -290,12 +308,63 @@ static void *alloc_ep(int size, gfp_t gf
 	return epc;
 }
 
+static void remove_ep_tid(struct c4iw_ep *ep)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&ep->com.dev->lock, flags);
+	_remove_handle(ep->com.dev, &ep->com.dev->hwtid_idr, ep->hwtid, 0);
+	spin_unlock_irqrestore(&ep->com.dev->lock, flags);
+}
+
+static void insert_ep_tid(struct c4iw_ep *ep)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&ep->com.dev->lock, flags);
+	_insert_handle(ep->com.dev, &ep->com.dev->hwtid_idr, ep, ep->hwtid, 0);
+	spin_unlock_irqrestore(&ep->com.dev->lock, flags);
+}
+
+/*
+ * Atomically lookup the ep ptr given the tid and grab a reference on the ep.
+ */
+static struct c4iw_ep *get_ep_from_tid(struct c4iw_dev *dev, unsigned int tid)
+{
+	struct c4iw_ep *ep;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->lock, flags);
+	ep = idr_find(&dev->hwtid_idr, tid);
+	if (ep)
+		c4iw_get_ep(&ep->com);
+	spin_unlock_irqrestore(&dev->lock, flags);
+	return ep;
+}
+
+/*
+ * Atomically lookup the ep ptr given the stid and grab a reference on the ep.
+ */
+static struct c4iw_listen_ep *get_ep_from_stid(struct c4iw_dev *dev,
+					       unsigned int stid)
+{
+	struct c4iw_listen_ep *ep;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->lock, flags);
+	ep = idr_find(&dev->stid_idr, stid);
+	if (ep)
+		c4iw_get_ep(&ep->com);
+	spin_unlock_irqrestore(&dev->lock, flags);
+	return ep;
+}
+
 void _c4iw_free_ep(struct kref *kref)
 {
 	struct c4iw_ep *ep;
 
 	ep = container_of(kref, struct c4iw_ep, com.kref);
-	PDBG("%s ep %p state %s\n", __func__, ep, states[state_read(&ep->com)]);
+	PDBG("%s ep %p state %s\n", __func__, ep, states[ep->com.state]);
 	if (test_bit(QP_REFERENCED, &ep->com.flags))
 		deref_qp(ep);
 	if (test_bit(RELEASE_RESOURCES, &ep->com.flags)) {
@@ -309,10 +378,11 @@ void _c4iw_free_ep(struct kref *kref)
 					(const u32 *)&sin6->sin6_addr.s6_addr,
 					1);
 		}
-		remove_handle(ep->com.dev, &ep->com.dev->hwtid_idr, ep->hwtid);
 		cxgb4_remove_tid(ep->com.dev->rdev.lldi.tids, 0, ep->hwtid);
 		dst_release(ep->dst);
 		cxgb4_l2t_release(ep->l2t);
+		if (ep->mpa_skb)
+			kfree_skb(ep->mpa_skb);
 	}
 	kfree(ep);
 }
@@ -320,6 +390,15 @@ void _c4iw_free_ep(struct kref *kref)
 static void release_ep_resources(struct c4iw_ep *ep)
 {
 	set_bit(RELEASE_RESOURCES, &ep->com.flags);
+
+	/*
+	 * If we have a hwtid, then remove it from the idr table
+	 * so lookups will no longer find this endpoint.  Otherwise
+	 * we have a race where one thread finds the ep ptr just
+	 * before the other thread is freeing the ep memory.
+	 */
+	if (ep->hwtid != -1)
+		remove_ep_tid(ep);
 	c4iw_put_ep(&ep->com);
 }
 
@@ -432,10 +511,74 @@ static struct dst_entry *find_route(stru
 
 static void arp_failure_discard(void *handle, struct sk_buff *skb)
 {
-	PDBG("%s c4iw_dev %p\n", __func__, handle);
+	pr_err(MOD "ARP failure\n");
 	kfree_skb(skb);
 }
 
+static void mpa_start_arp_failure(void *handle, struct sk_buff *skb)
+{
+	pr_err("ARP failure during MPA Negotiation - Closing Connection\n");
+}
+
+enum {
+	NUM_FAKE_CPLS = 2,
+	FAKE_CPL_PUT_EP_SAFE = NUM_CPL_CMDS + 0,
+	FAKE_CPL_PASS_PUT_EP_SAFE = NUM_CPL_CMDS + 1,
+};
+
+static int _put_ep_safe(struct c4iw_dev *dev, struct sk_buff *skb)
+{
+	struct c4iw_ep *ep;
+
+	ep = *((struct c4iw_ep **)(skb->cb + 2 * sizeof(void *)));
+	release_ep_resources(ep);
+	return 0;
+}
+
+static int _put_pass_ep_safe(struct c4iw_dev *dev, struct sk_buff *skb)
+{
+	struct c4iw_ep *ep;
+
+	ep = *((struct c4iw_ep **)(skb->cb + 2 * sizeof(void *)));
+	c4iw_put_ep(&ep->parent_ep->com);
+	release_ep_resources(ep);
+	return 0;
+}
+
+/*
+ * Fake up a special CPL opcode and call sched() so process_work() will call
+ * _put_ep_safe() in a safe context to free the ep resources.  This is needed
+ * because ARP error handlers are called in an ATOMIC context, and
+ * _c4iw_free_ep() needs to block.
+ */
+static void queue_arp_failure_cpl(struct c4iw_ep *ep, struct sk_buff *skb,
+				  int cpl)
+{
+	struct cpl_act_establish *rpl = cplhdr(skb);
+
+	/* Set our special ARP_FAILURE opcode */
+	rpl->ot.opcode = cpl;
+
+	/*
+	 * Save ep in the skb->cb area, after where sched() will save the dev
+	 * ptr.
+	 */
+	*((struct c4iw_ep **)(skb->cb + 2 * sizeof(void *))) = ep;
+	sched(ep->com.dev, skb);
+}
+
+/* Handle an ARP failure for an accept */
+static void pass_accept_rpl_arp_failure(void *handle, struct sk_buff *skb)
+{
+	struct c4iw_ep *ep = handle;
+
+	pr_err(MOD "ARP failure during accept - tid %u -dropping connection\n",
+	       ep->hwtid);
+
+	__state_set(&ep->com, DEAD);
+	queue_arp_failure_cpl(ep, skb, FAKE_CPL_PASS_PUT_EP_SAFE);
+}
+
 /*
  * Handle an ARP failure for an active open.
  */
@@ -444,9 +587,8 @@ static void act_open_req_arp_failure(voi
 	struct c4iw_ep *ep = handle;
 
 	printk(KERN_ERR MOD "ARP failure during connect\n");
-	kfree_skb(skb);
 	connect_reply_upcall(ep, -EHOSTUNREACH);
-	state_set(&ep->com, DEAD);
+	__state_set(&ep->com, DEAD);
 	if (ep->com.remote_addr.ss_family == AF_INET6) {
 		struct sockaddr_in6 *sin6 =
 			(struct sockaddr_in6 *)&ep->com.local_addr;
@@ -455,9 +597,7 @@ static void act_open_req_arp_failure(voi
 	}
 	remove_handle(ep->com.dev, &ep->com.dev->atid_idr, ep->atid);
 	cxgb4_free_atid(ep->com.dev->rdev.lldi.tids, ep->atid);
-	dst_release(ep->dst);
-	cxgb4_l2t_release(ep->l2t);
-	c4iw_put_ep(&ep->com);
+	queue_arp_failure_cpl(ep, skb, FAKE_CPL_PUT_EP_SAFE);
 }
 
 /*
@@ -466,15 +606,21 @@ static void act_open_req_arp_failure(voi
  */
 static void abort_arp_failure(void *handle, struct sk_buff *skb)
 {
-	struct c4iw_rdev *rdev = handle;
+	int ret;
+	struct c4iw_ep *ep = handle;
+	struct c4iw_rdev *rdev = &ep->com.dev->rdev;
 	struct cpl_abort_req *req = cplhdr(skb);
 
 	PDBG("%s rdev %p\n", __func__, rdev);
 	req->cmd = CPL_ABORT_NO_RST;
-	c4iw_ofld_send(rdev, skb);
+	ret = c4iw_ofld_send(rdev, skb);
+	if (ret) {
+		__state_set(&ep->com, DEAD);
+		queue_arp_failure_cpl(ep, skb, FAKE_CPL_PUT_EP_SAFE);
+	}
 }
 
-static void send_flowc(struct c4iw_ep *ep, struct sk_buff *skb)
+static int send_flowc(struct c4iw_ep *ep, struct sk_buff *skb)
 {
 	unsigned int flowclen = 80;
 	struct fw_flowc_wr *flowc;
@@ -530,7 +676,7 @@ static void send_flowc(struct c4iw_ep *e
 	}
 
 	set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx);
-	c4iw_ofld_send(&ep->com.dev->rdev, skb);
+	return c4iw_ofld_send(&ep->com.dev->rdev, skb);
 }
 
 static int send_halfclose(struct c4iw_ep *ep, gfp_t gfp)
@@ -568,7 +714,7 @@ static int send_abort(struct c4iw_ep *ep
 		return -ENOMEM;
 	}
 	set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx);
-	t4_set_arp_err_handler(skb, &ep->com.dev->rdev, abort_arp_failure);
+	t4_set_arp_err_handler(skb, ep, abort_arp_failure);
 	req = (struct cpl_abort_req *) skb_put(skb, wrlen);
 	memset(req, 0, wrlen);
 	INIT_TP_WR(req, ep->hwtid);
@@ -807,10 +953,10 @@ clip_release:
 	return ret;
 }
 
-static void send_mpa_req(struct c4iw_ep *ep, struct sk_buff *skb,
-		u8 mpa_rev_to_use)
+static int send_mpa_req(struct c4iw_ep *ep, struct sk_buff *skb,
+			u8 mpa_rev_to_use)
 {
-	int mpalen, wrlen;
+	int mpalen, wrlen, ret;
 	struct fw_ofld_tx_data_wr *req;
 	struct mpa_message *mpa;
 	struct mpa_v2_conn_params mpa_v2_params;
@@ -826,7 +972,7 @@ static void send_mpa_req(struct c4iw_ep
 	skb = get_skb(skb, wrlen, GFP_KERNEL);
 	if (!skb) {
 		connect_reply_upcall(ep, -ENOMEM);
-		return;
+		return -ENOMEM;
 	}
 	set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx);
 
@@ -894,12 +1040,14 @@ static void send_mpa_req(struct c4iw_ep
 	t4_set_arp_err_handler(skb, NULL, arp_failure_discard);
 	BUG_ON(ep->mpa_skb);
 	ep->mpa_skb = skb;
-	c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
+	ret = c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
+	if (ret)
+		return ret;
 	start_ep_timer(ep);
 	__state_set(&ep->com, MPA_REQ_SENT);
 	ep->mpa_attr.initiator = 1;
 	ep->snd_seq += mpalen;
-	return;
+	return ret;
 }
 
 static int send_mpa_reject(struct c4iw_ep *ep, const void *pdata, u8 plen)
@@ -975,7 +1123,7 @@ static int send_mpa_reject(struct c4iw_e
 	 */
 	skb_get(skb);
 	set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx);
-	t4_set_arp_err_handler(skb, NULL, arp_failure_discard);
+	t4_set_arp_err_handler(skb, NULL, mpa_start_arp_failure);
 	BUG_ON(ep->mpa_skb);
 	ep->mpa_skb = skb;
 	ep->snd_seq += mpalen;
@@ -1060,7 +1208,7 @@ static int send_mpa_reply(struct c4iw_ep
 	 * Function fw4_ack() will deref it.
 	 */
 	skb_get(skb);
-	t4_set_arp_err_handler(skb, NULL, arp_failure_discard);
+	t4_set_arp_err_handler(skb, NULL, mpa_start_arp_failure);
 	ep->mpa_skb = skb;
 	__state_set(&ep->com, MPA_REP_SENT);
 	ep->snd_seq += mpalen;
@@ -1074,6 +1222,7 @@ static int act_establish(struct c4iw_dev
 	unsigned int tid = GET_TID(req);
 	unsigned int atid = TID_TID_G(ntohl(req->tos_atid));
 	struct tid_info *t = dev->rdev.lldi.tids;
+	int ret;
 
 	ep = lookup_atid(t, atid);
 
@@ -1086,7 +1235,7 @@ static int act_establish(struct c4iw_dev
 	/* setup the hwtid for this connection */
 	ep->hwtid = tid;
 	cxgb4_insert_tid(t, ep, tid);
-	insert_handle(dev, &dev->hwtid_idr, ep, ep->hwtid);
+	insert_ep_tid(ep);
 
 	ep->snd_seq = be32_to_cpu(req->snd_isn);
 	ep->rcv_seq = be32_to_cpu(req->rcv_isn);
@@ -1099,13 +1248,22 @@ static int act_establish(struct c4iw_dev
 	set_bit(ACT_ESTAB, &ep->com.history);
 
 	/* start MPA negotiation */
-	send_flowc(ep, NULL);
+	ret = send_flowc(ep, NULL);
+	if (ret)
+		goto err;
 	if (ep->retry_with_mpa_v1)
-		send_mpa_req(ep, skb, 1);
+		ret = send_mpa_req(ep, skb, 1);
 	else
-		send_mpa_req(ep, skb, mpa_rev);
+		ret = send_mpa_req(ep, skb, mpa_rev);
+	if (ret)
+		goto err;
 	mutex_unlock(&ep->com.mutex);
 	return 0;
+err:
+	mutex_unlock(&ep->com.mutex);
+	connect_reply_upcall(ep, -ENOMEM);
+	c4iw_ep_disconnect(ep, 0, GFP_KERNEL);
+	return 0;
 }
 
 static void close_complete_upcall(struct c4iw_ep *ep, int status)
@@ -1120,20 +1278,11 @@ static void close_complete_upcall(struct
 		PDBG("close complete delivered ep %p cm_id %p tid %u\n",
 		     ep, ep->com.cm_id, ep->hwtid);
 		ep->com.cm_id->event_handler(ep->com.cm_id, &event);
-		ep->com.cm_id->rem_ref(ep->com.cm_id);
-		ep->com.cm_id = NULL;
+		deref_cm_id(&ep->com);
 		set_bit(CLOSE_UPCALL, &ep->com.history);
 	}
 }
 
-static int abort_connection(struct c4iw_ep *ep, struct sk_buff *skb, gfp_t gfp)
-{
-	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
-	__state_set(&ep->com, ABORTING);
-	set_bit(ABORT_CONN, &ep->com.history);
-	return send_abort(ep, skb, gfp);
-}
-
 static void peer_close_upcall(struct c4iw_ep *ep)
 {
 	struct iw_cm_event event;
@@ -1161,8 +1310,7 @@ static void peer_abort_upcall(struct c4i
 		PDBG("abort delivered ep %p cm_id %p tid %u\n", ep,
 		     ep->com.cm_id, ep->hwtid);
 		ep->com.cm_id->event_handler(ep->com.cm_id, &event);
-		ep->com.cm_id->rem_ref(ep->com.cm_id);
-		ep->com.cm_id = NULL;
+		deref_cm_id(&ep->com);
 		set_bit(ABORT_UPCALL, &ep->com.history);
 	}
 }
@@ -1205,10 +1353,8 @@ static void connect_reply_upcall(struct
 	set_bit(CONN_RPL_UPCALL, &ep->com.history);
 	ep->com.cm_id->event_handler(ep->com.cm_id, &event);
 
-	if (status < 0) {
-		ep->com.cm_id->rem_ref(ep->com.cm_id);
-		ep->com.cm_id = NULL;
-	}
+	if (status < 0)
+		deref_cm_id(&ep->com);
 }
 
 static int connect_request_upcall(struct c4iw_ep *ep)
@@ -1301,6 +1447,18 @@ static int update_rx_credits(struct c4iw
 
 #define RELAXED_IRD_NEGOTIATION 1
 
+/*
+ * process_mpa_reply - process streaming mode MPA reply
+ *
+ * Returns:
+ *
+ * 0 upon success indicating a connect request was delivered to the ULP
+ * or the mpa request is incomplete but valid so far.
+ *
+ * 1 if a failure requires the caller to close the connection.
+ *
+ * 2 if a failure requires the caller to abort the connection.
+ */
 static int process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
 {
 	struct mpa_message *mpa;
@@ -1316,20 +1474,12 @@ static int process_mpa_reply(struct c4iw
 	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
 
 	/*
-	 * Stop mpa timer.  If it expired, then
-	 * we ignore the MPA reply.  process_timeout()
-	 * will abort the connection.
-	 */
-	if (stop_ep_timer(ep))
-		return 0;
-
-	/*
 	 * If we get more than the supported amount of private data
 	 * then we must fail this connection.
 	 */
 	if (ep->mpa_pkt_len + skb->len > sizeof(ep->mpa_pkt)) {
 		err = -EINVAL;
-		goto err;
+		goto err_stop_timer;
 	}
 
 	/*
@@ -1351,11 +1501,11 @@ static int process_mpa_reply(struct c4iw
 		printk(KERN_ERR MOD "%s MPA version mismatch. Local = %d,"
 		       " Received = %d\n", __func__, mpa_rev, mpa->revision);
 		err = -EPROTO;
-		goto err;
+		goto err_stop_timer;
 	}
 	if (memcmp(mpa->key, MPA_KEY_REP, sizeof(mpa->key))) {
 		err = -EPROTO;
-		goto err;
+		goto err_stop_timer;
 	}
 
 	plen = ntohs(mpa->private_data_size);
@@ -1365,7 +1515,7 @@ static int process_mpa_reply(struct c4iw
 	 */
 	if (plen > MPA_MAX_PRIVATE_DATA) {
 		err = -EPROTO;
-		goto err;
+		goto err_stop_timer;
 	}
 
 	/*
@@ -1373,7 +1523,7 @@ static int process_mpa_reply(struct c4iw
 	 */
 	if (ep->mpa_pkt_len > (sizeof(*mpa) + plen)) {
 		err = -EPROTO;
-		goto err;
+		goto err_stop_timer;
 	}
 
 	ep->plen = (u8) plen;
@@ -1387,10 +1537,18 @@ static int process_mpa_reply(struct c4iw
 
 	if (mpa->flags & MPA_REJECT) {
 		err = -ECONNREFUSED;
-		goto err;
+		goto err_stop_timer;
 	}
 
 	/*
+	 * Stop mpa timer.  If it expired, then
+	 * we ignore the MPA reply.  process_timeout()
+	 * will abort the connection.
+	 */
+	if (stop_ep_timer(ep))
+		return 0;
+
+	/*
 	 * If we get here we have accumulated the entire mpa
 	 * start reply message including private data. And
 	 * the MPA header is valid.
@@ -1529,15 +1687,28 @@ static int process_mpa_reply(struct c4iw
 		goto out;
 	}
 	goto out;
+err_stop_timer:
+	stop_ep_timer(ep);
 err:
-	__state_set(&ep->com, ABORTING);
-	send_abort(ep, skb, GFP_KERNEL);
+	disconnect = 2;
 out:
 	connect_reply_upcall(ep, err);
 	return disconnect;
 }
 
-static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb)
+/*
+ * process_mpa_request - process streaming mode MPA request
+ *
+ * Returns:
+ *
+ * 0 upon success indicating a connect request was delivered to the ULP
+ * or the mpa request is incomplete but valid so far.
+ *
+ * 1 if a failure requires the caller to close the connection.
+ *
+ * 2 if a failure requires the caller to abort the connection.
+ */
+static int process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb)
 {
 	struct mpa_message *mpa;
 	struct mpa_v2_conn_params *mpa_v2_params;
@@ -1549,11 +1720,8 @@ static void process_mpa_request(struct c
 	 * If we get more than the supported amount of private data
 	 * then we must fail this connection.
 	 */
-	if (ep->mpa_pkt_len + skb->len > sizeof(ep->mpa_pkt)) {
-		(void)stop_ep_timer(ep);
-		abort_connection(ep, skb, GFP_KERNEL);
-		return;
-	}
+	if (ep->mpa_pkt_len + skb->len > sizeof(ep->mpa_pkt))
+		goto err_stop_timer;
 
 	PDBG("%s enter (%s line %u)\n", __func__, __FILE__, __LINE__);
 
@@ -1569,7 +1737,7 @@ static void process_mpa_request(struct c
 	 * We'll continue process when more data arrives.
 	 */
 	if (ep->mpa_pkt_len < sizeof(*mpa))
-		return;
+		return 0;
 
 	PDBG("%s enter (%s line %u)\n", __func__, __FILE__, __LINE__);
 	mpa = (struct mpa_message *) ep->mpa_pkt;
@@ -1580,43 +1748,32 @@ static void process_mpa_request(struct c
 	if (mpa->revision > mpa_rev) {
 		printk(KERN_ERR MOD "%s MPA version mismatch. Local = %d,"
 		       " Received = %d\n", __func__, mpa_rev, mpa->revision);
-		(void)stop_ep_timer(ep);
-		abort_connection(ep, skb, GFP_KERNEL);
-		return;
+		goto err_stop_timer;
 	}
 
-	if (memcmp(mpa->key, MPA_KEY_REQ, sizeof(mpa->key))) {
-		(void)stop_ep_timer(ep);
-		abort_connection(ep, skb, GFP_KERNEL);
-		return;
-	}
+	if (memcmp(mpa->key, MPA_KEY_REQ, sizeof(mpa->key)))
+		goto err_stop_timer;
 
 	plen = ntohs(mpa->private_data_size);
 
 	/*
 	 * Fail if there's too much private data.
 	 */
-	if (plen > MPA_MAX_PRIVATE_DATA) {
-		(void)stop_ep_timer(ep);
-		abort_connection(ep, skb, GFP_KERNEL);
-		return;
-	}
+	if (plen > MPA_MAX_PRIVATE_DATA)
+		goto err_stop_timer;
 
 	/*
 	 * If plen does not account for pkt size
 	 */
-	if (ep->mpa_pkt_len > (sizeof(*mpa) + plen)) {
-		(void)stop_ep_timer(ep);
-		abort_connection(ep, skb, GFP_KERNEL);
-		return;
-	}
+	if (ep->mpa_pkt_len > (sizeof(*mpa) + plen))
+		goto err_stop_timer;
 	ep->plen = (u8) plen;
 
 	/*
 	 * If we don't have all the pdata yet, then bail.
 	 */
 	if (ep->mpa_pkt_len < (sizeof(*mpa) + plen))
-		return;
+		return 0;
 
 	/*
 	 * If we get here we have accumulated the entire mpa
@@ -1665,26 +1822,26 @@ static void process_mpa_request(struct c
 	     ep->mpa_attr.xmit_marker_enabled, ep->mpa_attr.version,
 	     ep->mpa_attr.p2p_type);
 
-	/*
-	 * If the endpoint timer already expired, then we ignore
-	 * the start request.  process_timeout() will abort
-	 * the connection.
-	 */
-	if (!stop_ep_timer(ep)) {
-		__state_set(&ep->com, MPA_REQ_RCVD);
+	__state_set(&ep->com, MPA_REQ_RCVD);
 
-		/* drive upcall */
-		mutex_lock_nested(&ep->parent_ep->com.mutex,
-				  SINGLE_DEPTH_NESTING);
-		if (ep->parent_ep->com.state != DEAD) {
-			if (connect_request_upcall(ep))
-				abort_connection(ep, skb, GFP_KERNEL);
-		} else {
-			abort_connection(ep, skb, GFP_KERNEL);
-		}
-		mutex_unlock(&ep->parent_ep->com.mutex);
+	/* drive upcall */
+	mutex_lock_nested(&ep->parent_ep->com.mutex, SINGLE_DEPTH_NESTING);
+	if (ep->parent_ep->com.state != DEAD) {
+		if (connect_request_upcall(ep))
+			goto err_unlock_parent;
+	} else {
+		goto err_unlock_parent;
 	}
-	return;
+	mutex_unlock(&ep->parent_ep->com.mutex);
+	return 0;
+
+err_unlock_parent:
+	mutex_unlock(&ep->parent_ep->com.mutex);
+	goto err_out;
+err_stop_timer:
+	(void)stop_ep_timer(ep);
+err_out:
+	return 2;
 }
 
 static int rx_data(struct c4iw_dev *dev, struct sk_buff *skb)
@@ -1693,11 +1850,10 @@ static int rx_data(struct c4iw_dev *dev,
 	struct cpl_rx_data *hdr = cplhdr(skb);
 	unsigned int dlen = ntohs(hdr->len);
 	unsigned int tid = GET_TID(hdr);
-	struct tid_info *t = dev->rdev.lldi.tids;
 	__u8 status = hdr->status;
 	int disconnect = 0;
 
-	ep = lookup_tid(t, tid);
+	ep = get_ep_from_tid(dev, tid);
 	if (!ep)
 		return 0;
 	PDBG("%s ep %p tid %u dlen %u\n", __func__, ep, ep->hwtid, dlen);
@@ -1715,7 +1871,7 @@ static int rx_data(struct c4iw_dev *dev,
 		break;
 	case MPA_REQ_WAIT:
 		ep->rcv_seq += dlen;
-		process_mpa_request(ep, skb);
+		disconnect = process_mpa_request(ep, skb);
 		break;
 	case FPDU_MODE: {
 		struct c4iw_qp_attributes attrs;
@@ -1736,7 +1892,8 @@ static int rx_data(struct c4iw_dev *dev,
 	}
 	mutex_unlock(&ep->com.mutex);
 	if (disconnect)
-		c4iw_ep_disconnect(ep, 0, GFP_KERNEL);
+		c4iw_ep_disconnect(ep, disconnect == 2, GFP_KERNEL);
+	c4iw_put_ep(&ep->com);
 	return 0;
 }
 
@@ -1746,9 +1903,8 @@ static int abort_rpl(struct c4iw_dev *de
 	struct cpl_abort_rpl_rss *rpl = cplhdr(skb);
 	int release = 0;
 	unsigned int tid = GET_TID(rpl);
-	struct tid_info *t = dev->rdev.lldi.tids;
 
-	ep = lookup_tid(t, tid);
+	ep = get_ep_from_tid(dev, tid);
 	if (!ep) {
 		printk(KERN_WARNING MOD "Abort rpl to freed endpoint\n");
 		return 0;
@@ -1770,10 +1926,11 @@ static int abort_rpl(struct c4iw_dev *de
 
 	if (release)
 		release_ep_resources(ep);
+	c4iw_put_ep(&ep->com);
 	return 0;
 }
 
-static void send_fw_act_open_req(struct c4iw_ep *ep, unsigned int atid)
+static int send_fw_act_open_req(struct c4iw_ep *ep, unsigned int atid)
 {
 	struct sk_buff *skb;
 	struct fw_ofld_connection_wr *req;
@@ -1843,7 +2000,7 @@ static void send_fw_act_open_req(struct
 	req->tcb.opt2 = cpu_to_be32((__force u32)req->tcb.opt2);
 	set_wr_txq(skb, CPL_PRIORITY_CONTROL, ep->ctrlq_idx);
 	set_bit(ACT_OFLD_CONN, &ep->com.history);
-	c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
+	return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
 }
 
 /*
@@ -1986,6 +2143,7 @@ static int c4iw_reconnect(struct c4iw_ep
 
 	PDBG("%s qp %p cm_id %p\n", __func__, ep->com.qp, ep->com.cm_id);
 	init_timer(&ep->timer);
+	c4iw_init_wr_wait(&ep->com.wr_wait);
 
 	/*
 	 * Allocate an active TID to initiate a TCP connection.
@@ -2069,6 +2227,7 @@ static int act_open_rpl(struct c4iw_dev
 	struct sockaddr_in *ra;
 	struct sockaddr_in6 *la6;
 	struct sockaddr_in6 *ra6;
+	int ret = 0;
 
 	ep = lookup_atid(t, atid);
 	la = (struct sockaddr_in *)&ep->com.local_addr;
@@ -2104,9 +2263,10 @@ static int act_open_rpl(struct c4iw_dev
 		mutex_unlock(&dev->rdev.stats.lock);
 		if (ep->com.local_addr.ss_family == AF_INET &&
 		    dev->rdev.lldi.enable_fw_ofld_conn) {
-			send_fw_act_open_req(ep,
-					     TID_TID_G(AOPEN_ATID_G(
-					     ntohl(rpl->atid_status))));
+			ret = send_fw_act_open_req(ep, TID_TID_G(AOPEN_ATID_G(
+						   ntohl(rpl->atid_status))));
+			if (ret)
+				goto fail;
 			return 0;
 		}
 		break;
@@ -2146,6 +2306,7 @@ static int act_open_rpl(struct c4iw_dev
 		break;
 	}
 
+fail:
 	connect_reply_upcall(ep, status2errno(status));
 	state_set(&ep->com, DEAD);
 
@@ -2170,9 +2331,8 @@ static int act_open_rpl(struct c4iw_dev
 static int pass_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
 {
 	struct cpl_pass_open_rpl *rpl = cplhdr(skb);
-	struct tid_info *t = dev->rdev.lldi.tids;
 	unsigned int stid = GET_TID(rpl);
-	struct c4iw_listen_ep *ep = lookup_stid(t, stid);
+	struct c4iw_listen_ep *ep = get_ep_from_stid(dev, stid);
 
 	if (!ep) {
 		PDBG("%s stid %d lookup failure!\n", __func__, stid);
@@ -2181,7 +2341,7 @@ static int pass_open_rpl(struct c4iw_dev
 	PDBG("%s ep %p status %d error %d\n", __func__, ep,
 	     rpl->status, status2errno(rpl->status));
 	c4iw_wake_up(&ep->com.wr_wait, status2errno(rpl->status));
-
+	c4iw_put_ep(&ep->com);
 out:
 	return 0;
 }
@@ -2189,17 +2349,17 @@ out:
 static int close_listsrv_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
 {
 	struct cpl_close_listsvr_rpl *rpl = cplhdr(skb);
-	struct tid_info *t = dev->rdev.lldi.tids;
 	unsigned int stid = GET_TID(rpl);
-	struct c4iw_listen_ep *ep = lookup_stid(t, stid);
+	struct c4iw_listen_ep *ep = get_ep_from_stid(dev, stid);
 
 	PDBG("%s ep %p\n", __func__, ep);
 	c4iw_wake_up(&ep->com.wr_wait, status2errno(rpl->status));
+	c4iw_put_ep(&ep->com);
 	return 0;
 }
 
-static void accept_cr(struct c4iw_ep *ep, struct sk_buff *skb,
-		      struct cpl_pass_accept_req *req)
+static int accept_cr(struct c4iw_ep *ep, struct sk_buff *skb,
+		     struct cpl_pass_accept_req *req)
 {
 	struct cpl_pass_accept_rpl *rpl;
 	unsigned int mtu_idx;
@@ -2287,10 +2447,9 @@ static void accept_cr(struct c4iw_ep *ep
 	rpl->opt0 = cpu_to_be64(opt0);
 	rpl->opt2 = cpu_to_be32(opt2);
 	set_wr_txq(skb, CPL_PRIORITY_SETUP, ep->ctrlq_idx);
-	t4_set_arp_err_handler(skb, NULL, arp_failure_discard);
-	c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
+	t4_set_arp_err_handler(skb, ep, pass_accept_rpl_arp_failure);
 
-	return;
+	return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
 }
 
 static void reject_cr(struct c4iw_dev *dev, u32 hwtid, struct sk_buff *skb)
@@ -2355,7 +2514,7 @@ static int pass_accept_req(struct c4iw_d
 	unsigned short hdrs;
 	u8 tos = PASS_OPEN_TOS_G(ntohl(req->tos_stid));
 
-	parent_ep = lookup_stid(t, stid);
+	parent_ep = (struct c4iw_ep *)get_ep_from_stid(dev, stid);
 	if (!parent_ep) {
 		PDBG("%s connect request on invalid stid %d\n", __func__, stid);
 		goto reject;
@@ -2468,9 +2627,13 @@ static int pass_accept_req(struct c4iw_d
 
 	init_timer(&child_ep->timer);
 	cxgb4_insert_tid(t, child_ep, hwtid);
-	insert_handle(dev, &dev->hwtid_idr, child_ep, child_ep->hwtid);
-	accept_cr(child_ep, skb, req);
-	set_bit(PASS_ACCEPT_REQ, &child_ep->com.history);
+	insert_ep_tid(child_ep);
+	if (accept_cr(child_ep, skb, req)) {
+		c4iw_put_ep(&parent_ep->com);
+		release_ep_resources(child_ep);
+	} else {
+		set_bit(PASS_ACCEPT_REQ, &child_ep->com.history);
+	}
 	if (iptype == 6) {
 		sin6 = (struct sockaddr_in6 *)&child_ep->com.local_addr;
 		cxgb4_clip_get(child_ep->com.dev->rdev.lldi.ports[0],
@@ -2479,6 +2642,8 @@ static int pass_accept_req(struct c4iw_d
 	goto out;
 reject:
 	reject_cr(dev, hwtid, skb);
+	if (parent_ep)
+		c4iw_put_ep(&parent_ep->com);
 out:
 	return 0;
 }
@@ -2487,10 +2652,10 @@ static int pass_establish(struct c4iw_de
 {
 	struct c4iw_ep *ep;
 	struct cpl_pass_establish *req = cplhdr(skb);
-	struct tid_info *t = dev->rdev.lldi.tids;
 	unsigned int tid = GET_TID(req);
+	int ret;
 
-	ep = lookup_tid(t, tid);
+	ep = get_ep_from_tid(dev, tid);
 	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
 	ep->snd_seq = be32_to_cpu(req->snd_isn);
 	ep->rcv_seq = be32_to_cpu(req->rcv_isn);
@@ -2501,10 +2666,15 @@ static int pass_establish(struct c4iw_de
 	set_emss(ep, ntohs(req->tcp_opt));
 
 	dst_confirm(ep->dst);
-	state_set(&ep->com, MPA_REQ_WAIT);
+	mutex_lock(&ep->com.mutex);
+	ep->com.state = MPA_REQ_WAIT;
 	start_ep_timer(ep);
-	send_flowc(ep, skb);
 	set_bit(PASS_ESTAB, &ep->com.history);
+	ret = send_flowc(ep, skb);
+	mutex_unlock(&ep->com.mutex);
+	if (ret)
+		c4iw_ep_disconnect(ep, 1, GFP_KERNEL);
+	c4iw_put_ep(&ep->com);
 
 	return 0;
 }
@@ -2516,11 +2686,13 @@ static int peer_close(struct c4iw_dev *d
 	struct c4iw_qp_attributes attrs;
 	int disconnect = 1;
 	int release = 0;
-	struct tid_info *t = dev->rdev.lldi.tids;
 	unsigned int tid = GET_TID(hdr);
 	int ret;
 
-	ep = lookup_tid(t, tid);
+	ep = get_ep_from_tid(dev, tid);
+	if (!ep)
+		return 0;
+
 	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
 	dst_confirm(ep->dst);
 
@@ -2592,6 +2764,7 @@ static int peer_close(struct c4iw_dev *d
 		c4iw_ep_disconnect(ep, 0, GFP_KERNEL);
 	if (release)
 		release_ep_resources(ep);
+	c4iw_put_ep(&ep->com);
 	return 0;
 }
 
@@ -2604,10 +2777,12 @@ static int peer_abort(struct c4iw_dev *d
 	struct c4iw_qp_attributes attrs;
 	int ret;
 	int release = 0;
-	struct tid_info *t = dev->rdev.lldi.tids;
 	unsigned int tid = GET_TID(req);
 
-	ep = lookup_tid(t, tid);
+	ep = get_ep_from_tid(dev, tid);
+	if (!ep)
+		return 0;
+
 	if (is_neg_adv(req->status)) {
 		PDBG("%s Negative advice on abort- tid %u status %d (%s)\n",
 		     __func__, ep->hwtid, req->status,
@@ -2616,7 +2791,7 @@ static int peer_abort(struct c4iw_dev *d
 		mutex_lock(&dev->rdev.stats.lock);
 		dev->rdev.stats.neg_adv++;
 		mutex_unlock(&dev->rdev.stats.lock);
-		return 0;
+		goto deref_ep;
 	}
 	PDBG("%s ep %p tid %u state %u\n", __func__, ep, ep->hwtid,
 	     ep->com.state);
@@ -2633,6 +2808,7 @@ static int peer_abort(struct c4iw_dev *d
 	mutex_lock(&ep->com.mutex);
 	switch (ep->com.state) {
 	case CONNECTING:
+		c4iw_put_ep(&ep->parent_ep->com);
 		break;
 	case MPA_REQ_WAIT:
 		(void)stop_ep_timer(ep);
@@ -2681,7 +2857,7 @@ static int peer_abort(struct c4iw_dev *d
 	case DEAD:
 		PDBG("%s PEER_ABORT IN DEAD STATE!!!!\n", __func__);
 		mutex_unlock(&ep->com.mutex);
-		return 0;
+		goto deref_ep;
 	default:
 		BUG_ON(1);
 		break;
@@ -2728,6 +2904,10 @@ out:
 		c4iw_reconnect(ep);
 	}
 
+deref_ep:
+	c4iw_put_ep(&ep->com);
+	/* Dereferencing ep, referenced in peer_abort_intr() */
+	c4iw_put_ep(&ep->com);
 	return 0;
 }
 
@@ -2737,16 +2917,18 @@ static int close_con_rpl(struct c4iw_dev
 	struct c4iw_qp_attributes attrs;
 	struct cpl_close_con_rpl *rpl = cplhdr(skb);
 	int release = 0;
-	struct tid_info *t = dev->rdev.lldi.tids;
 	unsigned int tid = GET_TID(rpl);
 
-	ep = lookup_tid(t, tid);
+	ep = get_ep_from_tid(dev, tid);
+	if (!ep)
+		return 0;
 
 	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
 	BUG_ON(!ep);
 
 	/* The cm_id may be null if we failed to connect */
 	mutex_lock(&ep->com.mutex);
+	set_bit(CLOSE_CON_RPL, &ep->com.history);
 	switch (ep->com.state) {
 	case CLOSING:
 		__state_set(&ep->com, MORIBUND);
@@ -2774,18 +2956,18 @@ static int close_con_rpl(struct c4iw_dev
 	mutex_unlock(&ep->com.mutex);
 	if (release)
 		release_ep_resources(ep);
+	c4iw_put_ep(&ep->com);
 	return 0;
 }
 
 static int terminate(struct c4iw_dev *dev, struct sk_buff *skb)
 {
 	struct cpl_rdma_terminate *rpl = cplhdr(skb);
-	struct tid_info *t = dev->rdev.lldi.tids;
 	unsigned int tid = GET_TID(rpl);
 	struct c4iw_ep *ep;
 	struct c4iw_qp_attributes attrs;
 
-	ep = lookup_tid(t, tid);
+	ep = get_ep_from_tid(dev, tid);
 	BUG_ON(!ep);
 
 	if (ep && ep->com.qp) {
@@ -2796,6 +2978,7 @@ static int terminate(struct c4iw_dev *de
 			       C4IW_QP_ATTR_NEXT_STATE, &attrs, 1);
 	} else
 		printk(KERN_WARNING MOD "TERM received tid %u no ep/qp\n", tid);
+	c4iw_put_ep(&ep->com);
 
 	return 0;
 }
@@ -2811,15 +2994,16 @@ static int fw4_ack(struct c4iw_dev *dev,
 	struct cpl_fw4_ack *hdr = cplhdr(skb);
 	u8 credits = hdr->credits;
 	unsigned int tid = GET_TID(hdr);
-	struct tid_info *t = dev->rdev.lldi.tids;
 
 
-	ep = lookup_tid(t, tid);
+	ep = get_ep_from_tid(dev, tid);
+	if (!ep)
+		return 0;
 	PDBG("%s ep %p tid %u credits %u\n", __func__, ep, ep->hwtid, credits);
 	if (credits == 0) {
 		PDBG("%s 0 credit ack ep %p tid %u state %u\n",
 		     __func__, ep, ep->hwtid, state_read(&ep->com));
-		return 0;
+		goto out;
 	}
 
 	dst_confirm(ep->dst);
@@ -2829,7 +3013,13 @@ static int fw4_ack(struct c4iw_dev *dev,
 		     state_read(&ep->com), ep->mpa_attr.initiator ? 1 : 0);
 		kfree_skb(ep->mpa_skb);
 		ep->mpa_skb = NULL;
+		mutex_lock(&ep->com.mutex);
+		if (test_bit(STOP_MPA_TIMER, &ep->com.flags))
+			stop_ep_timer(ep);
+		mutex_unlock(&ep->com.mutex);
 	}
+out:
+	c4iw_put_ep(&ep->com);
 	return 0;
 }
 
@@ -2841,22 +3031,23 @@ int c4iw_reject_cr(struct iw_cm_id *cm_i
 	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
 
 	mutex_lock(&ep->com.mutex);
-	if (ep->com.state == DEAD) {
+	if (ep->com.state != MPA_REQ_RCVD) {
 		mutex_unlock(&ep->com.mutex);
 		c4iw_put_ep(&ep->com);
 		return -ECONNRESET;
 	}
 	set_bit(ULP_REJECT, &ep->com.history);
-	BUG_ON(ep->com.state != MPA_REQ_RCVD);
 	if (mpa_rev == 0)
-		abort_connection(ep, NULL, GFP_KERNEL);
+		disconnect = 2;
 	else {
 		err = send_mpa_reject(ep, pdata, pdata_len);
 		disconnect = 1;
 	}
 	mutex_unlock(&ep->com.mutex);
-	if (disconnect)
-		err = c4iw_ep_disconnect(ep, 0, GFP_KERNEL);
+	if (disconnect) {
+		stop_ep_timer(ep);
+		err = c4iw_ep_disconnect(ep, disconnect == 2, GFP_KERNEL);
+	}
 	c4iw_put_ep(&ep->com);
 	return 0;
 }
@@ -2869,24 +3060,23 @@ int c4iw_accept_cr(struct iw_cm_id *cm_i
 	struct c4iw_ep *ep = to_ep(cm_id);
 	struct c4iw_dev *h = to_c4iw_dev(cm_id->device);
 	struct c4iw_qp *qp = get_qhp(h, conn_param->qpn);
+	int abort = 0;
 
 	PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
 
 	mutex_lock(&ep->com.mutex);
-	if (ep->com.state == DEAD) {
+	if (ep->com.state != MPA_REQ_RCVD) {
 		err = -ECONNRESET;
-		goto err;
+		goto err_out;
 	}
 
-	BUG_ON(ep->com.state != MPA_REQ_RCVD);
 	BUG_ON(!qp);
 
 	set_bit(ULP_ACCEPT, &ep->com.history);
 	if ((conn_param->ord > cur_max_read_depth(ep->com.dev)) ||
 	    (conn_param->ird > cur_max_read_depth(ep->com.dev))) {
-		abort_connection(ep, NULL, GFP_KERNEL);
 		err = -EINVAL;
-		goto err;
+		goto err_abort;
 	}
 
 	if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) {
@@ -2898,9 +3088,8 @@ int c4iw_accept_cr(struct iw_cm_id *cm_i
 				ep->ord = conn_param->ord;
 				send_mpa_reject(ep, conn_param->private_data,
 						conn_param->private_data_len);
-				abort_connection(ep, NULL, GFP_KERNEL);
 				err = -ENOMEM;
-				goto err;
+				goto err_abort;
 			}
 		}
 		if (conn_param->ird < ep->ord) {
@@ -2908,9 +3097,8 @@ int c4iw_accept_cr(struct iw_cm_id *cm_i
 			    ep->ord <= h->rdev.lldi.max_ordird_qp) {
 				conn_param->ird = ep->ord;
 			} else {
-				abort_connection(ep, NULL, GFP_KERNEL);
 				err = -ENOMEM;
-				goto err;
+				goto err_abort;
 			}
 		}
 	}
@@ -2929,8 +3117,8 @@ int c4iw_accept_cr(struct iw_cm_id *cm_i
 
 	PDBG("%s %d ird %d ord %d\n", __func__, __LINE__, ep->ird, ep->ord);
 
-	cm_id->add_ref(cm_id);
 	ep->com.cm_id = cm_id;
+	ref_cm_id(&ep->com);
 	ep->com.qp = qp;
 	ref_qp(ep);
 
@@ -2951,23 +3139,27 @@ int c4iw_accept_cr(struct iw_cm_id *cm_i
 	err = c4iw_modify_qp(ep->com.qp->rhp,
 			     ep->com.qp, mask, &attrs, 1);
 	if (err)
-		goto err1;
+		goto err_deref_cm_id;
+
+	set_bit(STOP_MPA_TIMER, &ep->com.flags);
 	err = send_mpa_reply(ep, conn_param->private_data,
 			     conn_param->private_data_len);
 	if (err)
-		goto err1;
+		goto err_deref_cm_id;
 
 	__state_set(&ep->com, FPDU_MODE);
 	established_upcall(ep);
 	mutex_unlock(&ep->com.mutex);
 	c4iw_put_ep(&ep->com);
 	return 0;
-err1:
-	ep->com.cm_id = NULL;
-	abort_connection(ep, NULL, GFP_KERNEL);
-	cm_id->rem_ref(cm_id);
-err:
+err_deref_cm_id:
+	deref_cm_id(&ep->com);
+err_abort:
+	abort = 1;
+err_out:
 	mutex_unlock(&ep->com.mutex);
+	if (abort)
+		c4iw_ep_disconnect(ep, 1, GFP_KERNEL);
 	c4iw_put_ep(&ep->com);
 	return err;
 }
@@ -3067,9 +3259,9 @@ int c4iw_connect(struct iw_cm_id *cm_id,
 	if (peer2peer && ep->ord == 0)
 		ep->ord = 1;
 
-	cm_id->add_ref(cm_id);
-	ep->com.dev = dev;
 	ep->com.cm_id = cm_id;
+	ref_cm_id(&ep->com);
+	ep->com.dev = dev;
 	ep->com.qp = get_qhp(dev, conn_param->qpn);
 	if (!ep->com.qp) {
 		PDBG("%s qpn 0x%x not found!\n", __func__, conn_param->qpn);
@@ -3108,7 +3300,7 @@ int c4iw_connect(struct iw_cm_id *cm_id,
 		/*
 		 * Handle loopback requests to INADDR_ANY.
 		 */
-		if ((__force int)raddr->sin_addr.s_addr == INADDR_ANY) {
+		if (raddr->sin_addr.s_addr == htonl(INADDR_ANY)) {
 			err = pick_local_ipaddrs(dev, cm_id);
 			if (err)
 				goto fail1;
@@ -3176,7 +3368,7 @@ fail2:
 	remove_handle(ep->com.dev, &ep->com.dev->atid_idr, ep->atid);
 	cxgb4_free_atid(ep->com.dev->rdev.lldi.tids, ep->atid);
 fail1:
-	cm_id->rem_ref(cm_id);
+	deref_cm_id(&ep->com);
 	c4iw_put_ep(&ep->com);
 out:
 	return err;
@@ -3270,8 +3462,8 @@ int c4iw_create_listen(struct iw_cm_id *
 		goto fail1;
 	}
 	PDBG("%s ep %p\n", __func__, ep);
-	cm_id->add_ref(cm_id);
 	ep->com.cm_id = cm_id;
+	ref_cm_id(&ep->com);
 	ep->com.dev = dev;
 	ep->backlog = backlog;
 	memcpy(&ep->com.local_addr, &cm_id->m_local_addr,
@@ -3311,7 +3503,7 @@ int c4iw_create_listen(struct iw_cm_id *
 	cxgb4_free_stid(ep->com.dev->rdev.lldi.tids, ep->stid,
 			ep->com.local_addr.ss_family);
 fail2:
-	cm_id->rem_ref(cm_id);
+	deref_cm_id(&ep->com);
 	c4iw_put_ep(&ep->com);
 fail1:
 out:
@@ -3350,7 +3542,7 @@ int c4iw_destroy_listen(struct iw_cm_id
 	cxgb4_free_stid(ep->com.dev->rdev.lldi.tids, ep->stid,
 			ep->com.local_addr.ss_family);
 done:
-	cm_id->rem_ref(cm_id);
+	deref_cm_id(&ep->com);
 	c4iw_put_ep(&ep->com);
 	return err;
 }
@@ -3367,6 +3559,12 @@ int c4iw_ep_disconnect(struct c4iw_ep *e
 	PDBG("%s ep %p state %s, abrupt %d\n", __func__, ep,
 	     states[ep->com.state], abrupt);
 
+	/*
+	 * Ref the ep here in case we have fatal errors causing the
+	 * ep to be released and freed.
+	 */
+	c4iw_get_ep(&ep->com);
+
 	rdev = &ep->com.dev->rdev;
 	if (c4iw_fatal_error(rdev)) {
 		fatal = 1;
@@ -3418,10 +3616,30 @@ int c4iw_ep_disconnect(struct c4iw_ep *e
 			set_bit(EP_DISC_CLOSE, &ep->com.history);
 			ret = send_halfclose(ep, gfp);
 		}
-		if (ret)
+		if (ret) {
+			set_bit(EP_DISC_FAIL, &ep->com.history);
+			if (!abrupt) {
+				stop_ep_timer(ep);
+				close_complete_upcall(ep, -EIO);
+			}
+			if (ep->com.qp) {
+				struct c4iw_qp_attributes attrs;
+
+				attrs.next_state = C4IW_QP_STATE_ERROR;
+				ret = c4iw_modify_qp(ep->com.qp->rhp,
+						     ep->com.qp,
+						     C4IW_QP_ATTR_NEXT_STATE,
+						     &attrs, 1);
+				if (ret)
+					pr_err(MOD
+					       "%s - qp <- error failed!\n",
+					       __func__);
+			}
 			fatal = 1;
+		}
 	}
 	mutex_unlock(&ep->com.mutex);
+	c4iw_put_ep(&ep->com);
 	if (fatal)
 		release_ep_resources(ep);
 	return ret;
@@ -3676,7 +3894,7 @@ static int rx_pkt(struct c4iw_dev *dev,
 	struct cpl_pass_accept_req *req = (void *)(rss + 1);
 	struct l2t_entry *e;
 	struct dst_entry *dst;
-	struct c4iw_ep *lep;
+	struct c4iw_ep *lep = NULL;
 	u16 window;
 	struct port_info *pi;
 	struct net_device *pdev;
@@ -3701,7 +3919,7 @@ static int rx_pkt(struct c4iw_dev *dev,
 	 */
 	stid = (__force int) cpu_to_be32((__force u32) rss->hash_val);
 
-	lep = (struct c4iw_ep *)lookup_stid(dev->rdev.lldi.tids, stid);
+	lep = (struct c4iw_ep *)get_ep_from_stid(dev, stid);
 	if (!lep) {
 		PDBG("%s connect request on invalid stid %d\n", __func__, stid);
 		goto reject;
@@ -3802,6 +4020,8 @@ static int rx_pkt(struct c4iw_dev *dev,
 free_dst:
 	dst_release(dst);
 reject:
+	if (lep)
+		c4iw_put_ep(&lep->com);
 	return 0;
 }
 
@@ -3809,7 +4029,7 @@ reject:
  * These are the real handlers that are called from a
  * work queue.
  */
-static c4iw_handler_func work_handlers[NUM_CPL_CMDS] = {
+static c4iw_handler_func work_handlers[NUM_CPL_CMDS + NUM_FAKE_CPLS] = {
 	[CPL_ACT_ESTABLISH] = act_establish,
 	[CPL_ACT_OPEN_RPL] = act_open_rpl,
 	[CPL_RX_DATA] = rx_data,
@@ -3825,7 +4045,9 @@ static c4iw_handler_func work_handlers[N
 	[CPL_RDMA_TERMINATE] = terminate,
 	[CPL_FW4_ACK] = fw4_ack,
 	[CPL_FW6_MSG] = deferred_fw6_msg,
-	[CPL_RX_PKT] = rx_pkt
+	[CPL_RX_PKT] = rx_pkt,
+	[FAKE_CPL_PUT_EP_SAFE] = _put_ep_safe,
+	[FAKE_CPL_PASS_PUT_EP_SAFE] = _put_pass_ep_safe
 };
 
 static void process_timeout(struct c4iw_ep *ep)
@@ -3839,11 +4061,12 @@ static void process_timeout(struct c4iw_
 	set_bit(TIMEDOUT, &ep->com.history);
 	switch (ep->com.state) {
 	case MPA_REQ_SENT:
-		__state_set(&ep->com, ABORTING);
 		connect_reply_upcall(ep, -ETIMEDOUT);
 		break;
 	case MPA_REQ_WAIT:
-		__state_set(&ep->com, ABORTING);
+	case MPA_REQ_RCVD:
+	case MPA_REP_SENT:
+	case FPDU_MODE:
 		break;
 	case CLOSING:
 	case MORIBUND:
@@ -3853,7 +4076,6 @@ static void process_timeout(struct c4iw_
 				     ep->com.qp, C4IW_QP_ATTR_NEXT_STATE,
 				     &attrs, 1);
 		}
-		__state_set(&ep->com, ABORTING);
 		close_complete_upcall(ep, -ETIMEDOUT);
 		break;
 	case ABORTING:
@@ -3871,9 +4093,9 @@ static void process_timeout(struct c4iw_
 			__func__, ep, ep->hwtid, ep->com.state);
 		abort = 0;
 	}
-	if (abort)
-		abort_connection(ep, NULL, GFP_KERNEL);
 	mutex_unlock(&ep->com.mutex);
+	if (abort)
+		c4iw_ep_disconnect(ep, 1, GFP_KERNEL);
 	c4iw_put_ep(&ep->com);
 }
 
@@ -4006,10 +4228,10 @@ static int peer_abort_intr(struct c4iw_d
 {
 	struct cpl_abort_req_rss *req = cplhdr(skb);
 	struct c4iw_ep *ep;
-	struct tid_info *t = dev->rdev.lldi.tids;
 	unsigned int tid = GET_TID(req);
 
-	ep = lookup_tid(t, tid);
+	ep = get_ep_from_tid(dev, tid);
+	/* This EP will be dereferenced in peer_abort() */
 	if (!ep) {
 		printk(KERN_WARNING MOD
 		       "Abort on non-existent endpoint, tid %d\n", tid);
@@ -4020,24 +4242,13 @@ static int peer_abort_intr(struct c4iw_d
 		PDBG("%s Negative advice on abort- tid %u status %d (%s)\n",
 		     __func__, ep->hwtid, req->status,
 		     neg_adv_str(req->status));
-		ep->stats.abort_neg_adv++;
-		dev->rdev.stats.neg_adv++;
-		kfree_skb(skb);
-		return 0;
+		goto out;
 	}
 	PDBG("%s ep %p tid %u state %u\n", __func__, ep, ep->hwtid,
 	     ep->com.state);
 
-	/*
-	 * Wake up any threads in rdma_init() or rdma_fini().
-	 * However, if we are on MPAv2 and want to retry with MPAv1
-	 * then, don't wake up yet.
-	 */
-	if (mpa_rev == 2 && !ep->tried_with_mpa_v1) {
-		if (ep->com.state != MPA_REQ_SENT)
-			c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET);
-	} else
-		c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET);
+	c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET);
+out:
 	sched(dev, skb);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/infiniband/hw/cxgb4/iw_cxgb4.h linux-libre-4.7-gnu/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
--- linux-libre-4.6-gnu/drivers/infiniband/hw/cxgb4/iw_cxgb4.h	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/infiniband/hw/cxgb4/iw_cxgb4.h	2016-07-24 15:23:50.000000000 -0400
@@ -755,6 +755,7 @@ enum c4iw_ep_flags {
 	CLOSE_SENT		= 3,
 	TIMEOUT                 = 4,
 	QP_REFERENCED           = 5,
+	STOP_MPA_TIMER		= 7,
 };
 
 enum c4iw_ep_history {
@@ -779,7 +780,13 @@ enum c4iw_ep_history {
 	EP_DISC_ABORT           = 18,
 	CONN_RPL_UPCALL         = 19,
 	ACT_RETRY_NOMEM         = 20,
-	ACT_RETRY_INUSE         = 21
+	ACT_RETRY_INUSE         = 21,
+	CLOSE_CON_RPL		= 22,
+	EP_DISC_FAIL		= 24,
+	QP_REFED		= 25,
+	QP_DEREFED		= 26,
+	CM_ID_REFED		= 27,
+	CM_ID_DEREFED		= 28,
 };
 
 struct c4iw_ep_common {
@@ -917,9 +924,8 @@ void c4iw_qp_rem_ref(struct ib_qp *qp);
 struct ib_mr *c4iw_alloc_mr(struct ib_pd *pd,
 			    enum ib_mr_type mr_type,
 			    u32 max_num_sg);
-int c4iw_map_mr_sg(struct ib_mr *ibmr,
-		   struct scatterlist *sg,
-		   int sg_nents);
+int c4iw_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents,
+		   unsigned int *sg_offset);
 int c4iw_dealloc_mw(struct ib_mw *mw);
 struct ib_mw *c4iw_alloc_mw(struct ib_pd *pd, enum ib_mw_type type,
 			    struct ib_udata *udata);
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/infiniband/hw/cxgb4/mem.c linux-libre-4.7-gnu/drivers/infiniband/hw/cxgb4/mem.c
--- linux-libre-4.6-gnu/drivers/infiniband/hw/cxgb4/mem.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/infiniband/hw/cxgb4/mem.c	2016-07-24 15:23:50.000000000 -0400
@@ -86,8 +86,9 @@ static int _c4iw_write_mem_dma_aligned(s
 			(wait ? FW_WR_COMPL_F : 0));
 	req->wr.wr_lo = wait ? (__force __be64)(unsigned long) &wr_wait : 0L;
 	req->wr.wr_mid = cpu_to_be32(FW_WR_LEN16_V(DIV_ROUND_UP(wr_len, 16)));
-	req->cmd = cpu_to_be32(ULPTX_CMD_V(ULP_TX_MEM_WRITE));
-	req->cmd |= cpu_to_be32(T5_ULP_MEMIO_ORDER_V(1));
+	req->cmd = cpu_to_be32(ULPTX_CMD_V(ULP_TX_MEM_WRITE) |
+			       T5_ULP_MEMIO_ORDER_V(1) |
+			       T5_ULP_MEMIO_FID_V(rdev->lldi.rxq_ids[0]));
 	req->dlen = cpu_to_be32(ULP_MEMIO_DATA_LEN_V(len>>5));
 	req->len16 = cpu_to_be32(DIV_ROUND_UP(wr_len-sizeof(req->wr), 16));
 	req->lock_addr = cpu_to_be32(ULP_MEMIO_ADDR_V(addr));
@@ -690,15 +691,14 @@ static int c4iw_set_page(struct ib_mr *i
 	return 0;
 }
 
-int c4iw_map_mr_sg(struct ib_mr *ibmr,
-		   struct scatterlist *sg,
-		   int sg_nents)
+int c4iw_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents,
+		   unsigned int *sg_offset)
 {
 	struct c4iw_mr *mhp = to_c4iw_mr(ibmr);
 
 	mhp->mpl_len = 0;
 
-	return ib_sg_to_pages(ibmr, sg, sg_nents, c4iw_set_page);
+	return ib_sg_to_pages(ibmr, sg, sg_nents, sg_offset, c4iw_set_page);
 }
 
 int c4iw_dereg_mr(struct ib_mr *ib_mr)
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/infiniband/hw/cxgb4/provider.c linux-libre-4.7-gnu/drivers/infiniband/hw/cxgb4/provider.c
--- linux-libre-4.6-gnu/drivers/infiniband/hw/cxgb4/provider.c	2016-05-15 18:43:13.000000000 -0400
+++ linux-libre-4.7-gnu/drivers/infiniband/hw/cxgb4/provider.c	2016-07-24 15:23:50.000000000 -0400
@@ -446,20 +446,59 @@ static ssize_t show_board(struct device
 		       c4iw_dev->rdev.lldi.pdev->device);
 }
 
+enum counters {
+	IP4INSEGS,
+	IP4OUTSEGS,
+	IP4RETRANSSEGS,
+	IP4OUTRSTS,
+	IP6INSEGS,
+	IP6OUTSEGS,
+	IP6RETRANSSEGS,
+	IP6OUTRSTS,
+	NR_COUNTERS
+};
+
+static const char * const names[] = {
+	[IP4INSEGS] = "ip4InSegs",
+	[IP4OUTSEGS] = "ip4OutSegs",
+	[IP4RETRANSSEGS] = "ip4RetransSegs",
+	[IP4OUTRSTS] = "ip4OutRsts",
+	[IP6INSEGS] = "ip6InSegs",
+	[IP6OUTSEGS] = "ip6OutSegs",
+	[IP6RETRANSSEGS] = "ip6RetransSegs",
+	[IP6OUTRSTS] = "ip6OutRsts"
+};
+
+static struct rdma_hw_stats *c4iw_alloc_stats(struct ib_device *ibdev,
+					      u8 port_num)
+{
+	BUILD_BUG_ON(ARRAY_SIZE(names) != NR_COUNTERS);
+
+	if (port_num != 0)
+		return NULL;
+
+	return rdma_alloc_hw_stats_struct(names, NR_COUNTERS,
+					  RDMA_HW_STATS_DEFAULT_LIFESPAN);
+}
+
 static int c4iw_get_mib(struct ib_device *ibdev,
-			union rdma_protocol_stats *stats)
+			struct rdma_hw_stats *stats,
+			u8 port, int index)
 {
 	struct tp_tcp_stats v4, v6;
 	struct c4iw_dev *c4iw_dev = to_c4iw_dev(ibdev);
 
 	cxgb4_get_tcp_stats(c4iw_dev->rdev.lldi.pdev, &v4, &v6);
-	memset(stats, 0, sizeof *stats);
-	stats->iw.tcpInSegs = v4.tcp_in_segs + v6.tcp_in_segs;
-	stats->iw.tcpOutSegs = v4.tcp_out_segs + v6.tcp_out_segs;
-	stats->iw.tcpRetransSegs = v4.tcp_retrans_segs + v6.tcp_retrans_segs;
-	stats->iw.tcpOutRsts = v4.tcp_out_rsts + v6.tcp_out_rsts;
+	stats->value[IP4INSEGS] = v4.tcp_in_segs;
+	stats->value[IP4OUTSEGS] = v4.tcp_out_segs;
+	stats->value[IP4RETRANSSEGS] = v4.tcp_retrans_segs;
+	stats->value[IP4OUTRSTS] = v4.tcp_out_rsts;
+	stats->value[IP6INSEGS] = v6.tcp_in_segs;
+	stats->value[IP6OUTSEGS] = v6.tcp_out_segs;
+	stats->value[IP6RETRANSSEGS] = v6.tcp_retrans_segs;
+	stats->value[IP6OUTRSTS] = v6.tcp_out_rsts;
 
-	return 0;
+	return stats->num_counters;
 }
 
 static DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
@@ -562,7 +601,8 @@ int c4iw_register_device(struct c4iw_dev
 	dev->ibdev.req_notify_cq = c4iw_arm_cq;
 	dev->ibdev.post_send = c4iw_post_send;
 	dev->ibdev.post_recv = c4iw_post_receive;
-	dev->ibdev.get_protocol_stats = c4iw_get_mib;
+	dev->ibdev.alloc_hw_stats = c4iw_alloc_stats;
+	dev->ibdev.get_hw_stats = c4iw_get_mib;
 	dev->ibdev.uverbs_abi_ver = C4IW_UVERBS_ABI_VERSION;
 	dev->ibdev.get_port_immutable = c4iw_port_immutable;
 	dev->ibdev.drain_sq = c4iw_drain_sq;
diff -druNp --no-dereference linux-libre-4.6-gnu/drivers/infiniband/hw/hfi1/affinity.c linux-libre-4.7-gnu/drivers/infiniband/hw/hfi1/affinity.c
--- linux-libre-4.6-gnu/drivers/infiniband/hw/hfi1/affinity.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.7-gnu/drivers/infiniband/hw/hfi1/affinity.c	2016-07-24 15:23:50.000000000 -0400
@@ -0,0 +1,428 @@
+/*
+ * Copyright(c) 2015, 2016 Intel Corporation.
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * 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.
+ *
+ * BSD LICENSE
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  - Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  - Neither the name of Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include <linux/topology.h>
+#include <linux/cpumask.h>
+#include <linux/module.h>
+
+#include "hfi.h"
+#include "affinity.h"
+#include "sdma.h"
+#include "trace.h"
+
+/* Name of IRQ types, indexed by enum irq_type */
+static const char * const irq_type_names[] = {
+	"SDMA",
+	"RCVCTXT",
+	"GENERAL",
+	"OTHER",
+};
+
+static inline void init_cpu_mask_set(struct cpu_mask_set *set)
+{
+	cpumask_clear(&set->mask);
+	cpumask_clear(&set->used);
+	set->gen = 0;
+}
+
+/* Initialize non-HT cpu cores mask */
+int init_real_cpu_mask(struct hfi1_devdata *dd)
+{
+	struct hfi1_affinity *info;
+	int possible, curr_cpu, i, ht;
+
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	cpumask_clear(&info->real_cpu_mask);
+
+	/* Start with cpu online mask as the real cpu mask */
+	cpumask_copy(&info->real_cpu_mask, cpu_online_mask);
+
+	/*
+	 * Remove HT cores from the real cpu mask.  Do this in two steps below.
+	 */
+	possible = cpumask_weight(&info->real_cpu_mask);
+	ht = cpumask_weight(topology_sibling_cpumask(
+					cpumask_first(&info->real_cpu_mask)));
+	/*
+	 * Step 1.  Skip over the first N HT siblings and use them as the
+	 * "real" cores.  Assumes that HT cores are not enumerated in
+	 * succession (except in the single core case).
+	 */
+	curr_cpu = cpumask_first(&info->real_cpu_mask);
+	for (i = 0; i < possible / ht; i++)
+		curr_cpu = cpumask_next(curr_cpu, &info->real_cpu_mask);
+	/*
+	 * Step 2.  Remove the remaining HT siblings.  Use cpumask_next() to
+	 * skip any gaps.
+	 */
+	for (; i < possible; i++) {
+		cpumask_clear_cpu(curr_cpu, &info->real_cpu_mask);
+		curr_cpu = cpumask_next(curr_cpu, &info->real_cpu_mask);
+	}
+
+	dd->affinity = info;
+	return 0;
+}
+
+/*
+ * Interrupt affinity.
+ *
+ * non-rcv avail gets a default mask that
+ * starts as possible cpus with threads reset
+ * and each rcv avail reset.
+ *
+ * rcv avail gets node relative 1 wrapping back
+ * to the node relative 1 as necessary.
+ *
+ */
+void hfi1_dev_affinity_init(struct hfi1_devdata *dd)
+{
+	int node = pcibus_to_node(dd->pcidev->bus);
+	struct hfi1_affinity *info = dd->affinity;
+	const struct cpumask *local_mask;
+	int curr_cpu, possible, i;
+
+	if (node < 0)
+		node = numa_node_id();
+	dd->node = node;
+
+	spin_lock_init(&info->lock);
+
+	init_cpu_mask_set(&info->def_intr);
+	init_cpu_mask_set(&info->rcv_intr);
+	init_cpu_mask_set(&info->proc);
+
+	local_mask = cpumask_of_node(dd->node);
+	if (cpumask_first(local_mask) >= nr_cpu_ids)
+		local_mask = topology_core_cpumask(0);
+	/* Use the "real" cpu mask of this node as the default */
+	cpumask_and(&info->def_intr.mask, &info->real_cpu_mask, local_mask);
+
+	/*  fill in the receive list */
+	possible = cpumask_weight(&info->def_intr.mask);
+	curr_cpu = cpumask_first(&info->def_intr.mask);
+	if (possible == 1) {
+		/*  only one CPU, everyone will use it */
+		cpumask_set_cpu(curr_cpu, &info->rcv_intr.mask);
+	} else {
+		/*
+		 * Retain the first CPU in the default list for the control
+		 * context.
+		 */
+		curr_cpu = cpumask_next(curr_cpu, &info->def_intr.mask);
+		/*
+		 * Remove the remaining kernel receive queues from
+		 * the default list and add them to the receive list.
+		 */
+		for (i = 0; i < dd->n_krcv_queues - 1; i++) {
+			cpumask_clear_cpu(curr_cpu, &info->def_intr.mask);
+			cpumask_set_cpu(curr_cpu, &info->rcv_intr.mask);
+			curr_cpu = cpumask_next(curr_cpu, &info->def_intr.mask);
+			if (curr_cpu >= nr_cpu_ids)
+				break;
+		}
+	}
+
+	cpumask_copy(&info->proc.mask, cpu_online_mask);
+}
+
+void hfi1_dev_affinity_free(struct hfi1_devdata *dd)
+{
+	kfree(dd->affinity);
+}
+
+int hfi1_get_irq_affinity(struct hfi1_devdata *dd, struct hfi1_msix_entry *msix)
+{
+	int ret;
+	cpumask_var_t diff;
+	struct cpu_mask_set *set;
+	struct sdma_engine *sde = NULL;
+	struct hfi1_ctxtdata *rcd = NULL;
+	char extra[64];
+	int cpu = -1;
+
+	extra[0] = '\0';
+	cpumask_clear(&msix->mask);
+
+	ret = zalloc_cpumask_var(&diff, GFP_KERNEL);
+	if (!ret)
+		return -ENOMEM;
+
+	switch (msix->type) {
+	case IRQ_SDMA:
+		sde = (struct sdma_engine *)msix->arg;
+		scnprintf(extra, 64, "engine %u", sde->this_idx);
+		/* fall through */
+	case IRQ_GENERAL:
+		set = &dd->affinity->def_intr;
+		break;
+	case IRQ_RCVCTXT:
+		rcd = (struct hfi1_ctxtdata *)msix->arg;
+		if (rcd->ctxt == HFI1_CTRL_CTXT) {
+			set = &dd->affinity->def_intr;
+			cpu = cpumask_first(&set->mask);
+		} else {
+			set = &dd->affinity->rcv_intr;
+		}
+		scnprintf(extra, 64, "ctxt %u", rcd->ctxt);
+		break;
+	default:
+		dd_dev_err(dd, "Invalid IRQ type %d\n", msix->type);
+		return -EINVAL;
+	}
+
+	/*
+	 * The control receive context is placed on a particular CPU, which
+	 * is set above.  Skip accounting for it.  Everything else finds its
+	 * CPU here.
+	 */
+	if (cpu == -1) {
+		spin_lock(&dd->affinity->lock);
+		if (cpumask_equal(&set->mask, &set->used)) {
+			/*
+			 * We've used up all the CPUs, bump up the generation
+			 * and reset the 'used' map
+			 */
+			set->gen++;
+			cpumask_clear(&set->used);
+		}
+		cpumask_andnot(diff, &set->mask, &set->used);
+		cpu = cpumask_first(diff);
+		cpumask_set_cpu(cpu, &set->used);
+		spin_unlock(&dd->affinity->lock);
+	}
+
+	switch (msix->type) {
+	case IRQ_SDMA:
+		sde->cpu = cpu;
+		break;
+	case IRQ_GENERAL:
+	case IRQ_RCVCTXT:
+	case IRQ_OTHER:
+		break;
+	}
+
+	cpumask_set_cpu(cpu, &msix->mask);
+	dd_dev_info(dd, "IRQ vector: %u, type %s %s -> cpu: %d\n",
+		    msix->msix.vector, irq_type_names[msix->type],
+		    extra, cpu);
+	irq_set_affinity_hint(msix->msix.vector, &msix->mask);
+
+	free_cpumask_var(diff);
+	return 0;
+}
+
+void hfi1_put_irq_affinity(struct hfi1_devdata *dd,
+			   struct hfi1_msix_entry *msix)
+{
+	struct cpu_mask_set *set = NULL;
+	struct hfi1_ctxtdata *rcd;
+
+	switch (msix->type) {
+	case IRQ_SDMA:
+	case IRQ_GENERAL:
+		set = &dd->affinity->def_intr;
+		break;
+	case IRQ_RCVCTXT:
+		rcd = (struct hfi1_ctxtdata *)msix->arg;
+		/* only do accounting for non control contexts */
+		if (rcd->ctxt != HFI1_CTRL_CTXT)
+			set = &dd->affinity->rcv_intr;
+		break;
+	default:
+		return;
+	}
+
+	if (set) {
+		spin_lock(&dd->affinity->lock);
+		cpumask_andnot(&set->used, &set->used, &msix->mask);
+		if (cpumask_empty(&set->used) && set->gen) {
+			set->gen--;
+			cpumask_copy(&set->used, &set->mask);
+		}
+		spin_unlock(&dd->affinity->lock);
+	}
+
+	irq_set_affinity_hint(msix->msix.vector, NULL);
+	cpumask_clear(&msix->mask);
+}
+
+int hfi1_get_proc_affinity(struct hfi1_devdata *dd, int node)
+{
+	int cpu = -1, ret;
+	cpumask_var_t diff, mask, intrs;
+	const struct cpumask *node_mask,
+		*proc_mask = tsk_cpus_allowed(current);
+	struct cpu_mask_set *set = &dd->affinity->proc;
+
+	/*
+	 * check whether process/context affinity has already
+	 * been set
+	 */
+	if (cpumask_weight(proc_mask) == 1) {
+		hfi1_cdbg(PROC, "PID %u %s affinity set to CPU %*pbl",
+			 